diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..dd6bec489 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,174 @@ +name: Build + +on: ["push", "workflow_dispatch"] + +jobs: + build_main: + name: Build for ${{ matrix.os_short }} + runs-on: ${{ matrix.os_version }} + + # skip build on '[ci skip]' + if: "!contains(github.event.head_commit.message, '[ci skip]')" + + strategy: + fail-fast: false + matrix: + os: + - ubuntu-22.04 + - ubuntu-latest + - windows-x32 + - windows-x64 + include: + - os: ubuntu-22.04 + os_short: linux-legacy + os_version: ubuntu-22.04 + package_ext: tar.gz + dbg_ext: dbg + cc: gcc + cxx: g++ + vs_arch: unused + am_arch: x86,x86_64 + + - os: ubuntu-latest + os_short: linux-latest + os_version: ubuntu-latest + package_ext: tar.gz + dbg_ext: dbg + cc: clang + cxx: clang++ + vs_arch: unused + am_arch: x86,x86_64 + + - os: windows-x32 + os_short: win32 + os_version: windows-latest + package_ext: zip + dbg_ext: pdb + cc: not-used + cxx: not-used + vs_arch: x32 + am_arch: x86 + + - os: windows-x64 + os_short: win64 + os_version: windows-latest + package_ext: zip + dbg_ext: pdb + cc: not-used + cxx: not-used + vs_arch: x64 + am_arch: x86_64 + + steps: + - name: Install (Linux) + if: runner.os == 'Linux' + run: | + sudo dpkg --add-architecture i386 + sudo apt-get update + sudo apt-get install -y clang g++-multilib + echo "CC=${{ matrix.cc }}" >> $GITHUB_ENV + echo "CXX=${{ matrix.cxx }}" >> $GITHUB_ENV + + - name: Add msbuild to PATH (Windows) + if: runner.os == 'Windows' + uses: microsoft/setup-msbuild@v2 + + - name: Install (Windows) + if: runner.os == 'Windows' + shell: cmd + run: | + :: See https://github.com/microsoft/vswhere/wiki/Find-VC + for /f "usebackq delims=*" %%i in (`vswhere -latest -property installationPath`) do ( + call "%%i"\Common7\Tools\vsdevcmd.bat -arch=${{ matrix.vs_arch }} -host_arch=x64 + ) + + :: Loop over all environment variables and make them global. + for /f "delims== tokens=1,2" %%a in ('set') do ( + echo>>"%GITHUB_ENV%" %%a=%%b + ) + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.os == 'ubuntu-22.04' && '3.11' || '3.12' }} + + - name: Setup ambuild + run: | + python -m pip install --upgrade pip + python -m pip install wheel + pip install git+https://github.com/alliedmodders/ambuild + + - name: Fetch RCBot2 + uses: actions/checkout@v4 + with: + path: rcbot2 + submodules: recursive + + - name: Build Files + working-directory: rcbot2 + run: | + mkdir post + cd post + python3 ../configure.py --sdks=present --mms-path="${{ github.workspace }}/rcbot2/alliedmodders/metamod-source" --sm-path="${{ github.workspace }}/rcbot2/alliedmodders/sourcemod" --hl2sdk-root="${{ github.workspace }}/rcbot2/alliedmodders" --symbol-files --target ${{ matrix.am_arch }} --enable-optimize + ambuild + + - uses: benjlevesque/short-sha@v2.2 + id: short-sha + + - name: Upload Binary + uses: actions/upload-artifact@v4 + with: + name: rcbot2-${{ matrix.os_short }}-${{ steps.short-sha.outputs.sha }} + path: | + rcbot2/post/package/* + + - name: Upload Debug Symbols + uses: actions/upload-artifact@v4 + with: + name: rcbot2-dbgsym-${{ matrix.os_short }}-${{ steps.short-sha.outputs.sha }} + path: | + rcbot2/post/**/*.${{ matrix.dbg_ext }} + + combine_windows: + name: Combine Windows Builds + needs: build_main + runs-on: ubuntu-latest + steps: + - uses: benjlevesque/short-sha@v2.2 + id: short-sha + + - name: Download Win32 artifact + uses: actions/download-artifact@v4 + with: + name: rcbot2-win32-${{ steps.short-sha.outputs.sha }} + path: combined/win32 + + - name: Download Win64 artifact + uses: actions/download-artifact@v4 + with: + name: rcbot2-win64-${{ steps.short-sha.outputs.sha }} + path: combined/win64 + + - name: Upload Combined Windows Artifact + uses: actions/upload-artifact@v4 + with: + name: rcbot2-windows-${{ steps.short-sha.outputs.sha }} + path: combined/ + + - name: Download Win32 Debug Symbols + uses: actions/download-artifact@v4 + with: + name: rcbot2-dbgsym-win32-${{ steps.short-sha.outputs.sha }} + path: combined-dbgsym/win32 + + - name: Download Win64 Debug Symbols + uses: actions/download-artifact@v4 + with: + name: rcbot2-dbgsym-win64-${{ steps.short-sha.outputs.sha }} + path: combined-dbgsym/win64 + + - name: Upload Combined Windows Debug Symbols + uses: actions/upload-artifact@v4 + with: + name: rcbot2-dbgsym-windows-${{ steps.short-sha.outputs.sha }} + path: combined-dbgsym/ \ No newline at end of file diff --git a/.gitignore b/.gitignore index 66bf39b0a..d73886d05 100644 --- a/.gitignore +++ b/.gitignore @@ -1,378 +1,29 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. -## -## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore +# Build outputs +build/ +build_linux/ +premake_build/ -# User-specific files -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ - -# Visual Studio 2015/2017 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# Visual Studio 2017 auto generated files -Generated\ Files/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUNIT -*.VisualState.xml -TestResult.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# Benchmark Results -BenchmarkDotNet.Artifacts/ - -# .NET Core -project.lock.json -project.fragment.lock.json -artifacts/ +utils/RCBot2_meta/Debug +utils/RCBot2_meta/.vs +utils/RCBot2_meta/x64 +utils/RCBot2_meta/x64/Release +utils/RCBot2_meta/x64/Release_NonHomeFolder +utils/RCBot2_meta/RCBot2Meta +utils/RCBot2_meta/HPB_Bot2.vcxproj.filters +utils/RCBot2_meta/Release_NonHomeFolder -# StyleCop -StyleCopReport.xml +# SourceMod compiled plugins +*.smx -# Files built by Visual Studio -*_i.c -*_p.c -*_h.h -*.ilk -*.meta +# Misc +*.ipch +*.db +*.suo +*.user +apg-load *.obj -*.iobj -*.pch -*.pdb -*.ipdb -*.pgc -*.pgd -*.rsp *.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# Visual Studio Trace Files -*.e2e - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# JustCode is a .NET coding add-in -.JustCode - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# AxoCover is a Code Coverage Tool -.axoCover/* -!.axoCover/settings.json - -# Visual Studio code coverage results -*.coverage -*.coveragexml - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# Note: Comment the next line if you want to checkin your web deploy settings, -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# The packages folder can be ignored because of Package Restore -**/[Pp]ackages/* -# except build/, which is used as an MSBuild target. -!**/[Pp]ackages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/[Pp]ackages/repositories.config -# NuGet v3's project.json files produces more ignorable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt -*.appx - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -orleans.codegen.cs - -# Including strong name files can present a security risk -# (https://github.com/github/gitignore/pull/2483#issue-259490424) -#*.snk - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm -ServiceFabricBackup/ -*.rptproj.bak - -# SQL Server files -*.mdf -*.ldf -*.ndf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings -*.rptproj.rsuser - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat -node_modules/ - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) -*.vbw - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# JetBrains Rider -.idea/ -*.sln.iml - -# CodeRush -.cr/ - -# Python Tools for Visual Studio (PTVS) -__pycache__/ -*.pyc - -# Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config - -# Tabs Studio -*.tss - -# Telerik's JustMock configuration file -*.jmconfig - -# BizTalk build output -*.btp.cs -*.btm.cs -*.odx.cs -*.xsd.cs - -# OpenCover UI analysis results -OpenCover/ - -# Azure Stream Analytics local run output -ASALocalRun/ - -# MSBuild Binary and Structured Log -*.binlog - -# NVidia Nsight GPU debugger configuration file -*.nvuser - -# MFractors (Xamarin productivity tool) working folder -.mfractor/ - -# Local History for Visual Studio -.localhistory/ - - -## From the original .gitignore - - -############# -## Eclipse ## -############# - -.project -.cproject -.buildpath -.o -.obj - -############### -## Generated ## -############### - -utils/RCBot2_meta/Debug -utils/RCBot2_meta/Release -utils/RCBot2_meta/Release_NonHomeFolder -utils/RCBot2_meta/HPB_Bot2.opensdf -utils/RCBot2_meta/HPB_Bot2.sdf -/linux_sdk/obj/HPB_bot2_meta_i486/utilCBot2_metmeta -/linux_sdk/obj/vcpm -/utils/RCBot2/Debug -/linux_sdk/obj/RCBot2MetaDebug_i486/utils/RCBot2_meta -linux_sdk/compile.log -linux_sdk/RCBot2Meta_i486.so -*.o -utils/RCBot2_meta/.vs/HPB_Bot2/v15/.suo -utils/RCBot2_meta/.vs/HPB_Bot2/v15/Browse.VC.db -utils/RCBot2_meta/.vs/HPB_Bot2/v15/ipch/AutoPCH/d4de04c781d129aa/BOT_PLUGIN_META.ipch -utils/RCBot2_meta/.vs/HPB_Bot2/v15/Browse.VC.db -utils/RCBot2_meta/.vs/HPB_Bot2/v15/ipch/AutoPCH/614135fe39e25e38/BOT_CLIENT.ipch -utils/RCBot2_meta/.vs/HPB_Bot2/v15/Browse.VC.db -utils/RCBot2_meta/.vs/HPB_Bot2/v15/.suo -utils/RCBot2_meta/.vs/HPB_Bot2/v15/.suo -linux_sdk/RCBot2MetaDebug_i486.so -utils/RCBot2_meta/.vs/HPB_Bot2/v15/ipch/AutoPCH/be995abba53e672f/BOT_PERCEPTRON.ipch -utils/RCBot2_meta/.vs/HPB_Bot2/v15/Browse.VC.opendb -utils/RCBot2_meta/.vs/HPB_Bot2/v15/.suo -utils/RCBot2_meta/.vs/HPB_Bot2/v15/Browse.VC.db -utils/RCBot2_meta/.vs/HPB_Bot2/v15/ipch/AutoPCH/5d5e72717a175a61/BOT_GLOBALS.ipch +# Visual Studio code +.vscode/ +*.code-workspace \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..76c16d07e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,45 @@ +[submodule "alliedmodders/hl2sdk-bms"] + path = alliedmodders/hl2sdk-bms + url = https://github.com/alliedmodders/hl2sdk + +[submodule "alliedmodders/hl2sdk-css"] + path = alliedmodders/hl2sdk-css + url = https://github.com/alliedmodders/hl2sdk + +[submodule "alliedmodders/hl2sdk-dods"] + path = alliedmodders/hl2sdk-dods + url = https://github.com/alliedmodders/hl2sdk + +[submodule "alliedmodders/hl2sdk-episode1"] + path = alliedmodders/hl2sdk-episode1 + url = https://github.com/alliedmodders/hl2sdk + +[submodule "alliedmodders/hl2sdk-hl2dm"] + path = alliedmodders/hl2sdk-hl2dm + url = https://github.com/alliedmodders/hl2sdk + +[submodule "alliedmodders/hl2sdk-orangebox"] + path = alliedmodders/hl2sdk-orangebox + url = https://github.com/alliedmodders/hl2sdk + +[submodule "alliedmodders/hl2sdk-sdk2013"] + path = alliedmodders/hl2sdk-sdk2013 + url = https://github.com/alliedmodders/hl2sdk + +[submodule "alliedmodders/hl2sdk-tf2"] + path = alliedmodders/hl2sdk-tf2 + url = https://github.com/alliedmodders/hl2sdk + +[submodule "alliedmodders/metamod-source"] + path = alliedmodders/metamod-source + url = https://github.com/alliedmodders/metamod-source + +[submodule "alliedmodders/sourcemod"] + path = alliedmodders/sourcemod + url = https://github.com/alliedmodders/sourcemod +[submodule "hl2sdk-manifests"] + path = hl2sdk-manifests + url = https://github.com/alliedmodders/hl2sdk-manifests +[submodule "alliedmodders/hl2sdk-proxy-repo"] + path = alliedmodders/hl2sdk-proxy-repo + url = https://github.com/alliedmodders/hl2sdk diff --git a/.kdev4/cheeseh_rcbot2_repo.kdev4 b/.kdev4/cheeseh_rcbot2_repo.kdev4 deleted file mode 100644 index 8a9d3f753..000000000 --- a/.kdev4/cheeseh_rcbot2_repo.kdev4 +++ /dev/null @@ -1,5 +0,0 @@ -[Buildset] -BuildItems=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x01\x00\x00\x00&\x00c\x00h\x00e\x00e\x00s\x00e\x00h\x00_\x00r\x00c\x00b\x00o\x00t\x002\x00_\x00r\x00e\x00p\x00o) - -[Project] -VersionControlSupport=kdevgit diff --git a/AMBuildScript b/AMBuildScript new file mode 100644 index 000000000..23eab9232 --- /dev/null +++ b/AMBuildScript @@ -0,0 +1,310 @@ +import os, sys + +# Force GCC on Linux for legacy support - [APG]RoboCop[CL] +#if sys.platform.startswith('linux'): +# os.environ['CC'] = 'gcc' +# os.environ['CXX'] = 'g++' + +def ResolveEnvPath(env, folder): + if env in os.environ: + path = os.environ[env] + if os.path.isdir(path): + return path + else: + head = os.getcwd() + oldhead = None + while head != None and head != oldhead: + path = os.path.join(head, folder) + if os.path.isdir(path): + return path + oldhead = head + head, tail = os.path.split(head) + return None + +sdkhelpers_path = os.path.join(builder.sourcePath, 'hl2sdk-manifests', 'SdkHelpers.ambuild') +SdkHelpers = builder.Eval(sdkhelpers_path, { + 'Project': 'metamod' +}) + +class MMSConfig(object): + def __init__(self): + self.sdk_manifests = [] + self.sdks = {} + self.sdk_targets = [] + self.binaries = [] + self.generated_headers = None + self.mms_root = builder.options.mms_path + self.all_targets = [] + self.target_archs = set() + + # Validate sm_path if provided + if builder.options.sm_path: + if os.path.isdir(builder.options.sm_path): + self.sm_path = builder.options.sm_path + else: + raise Exception("SourceMod path '{}' does not exist or is not a directory".format(builder.options.sm_path)) + else: + self.sm_path = None + + if builder.options.targets: + target_archs = builder.options.targets.split(',') + else: + target_archs = ['x86'] + if builder.backend == 'amb2': + target_archs.append('x86_64') + + for arch in target_archs: + try: + cxx = builder.DetectCxx(target_arch = arch) + self.target_archs.add(cxx.target.arch) + except Exception as e: + # Error if archs were manually overridden. + if builder.options.targets: + raise + print('Skipping target {}: {}'.format(arch, e)) + continue + self.all_targets.append(cxx) + + if not self.all_targets: + raise Exception('No suitable C/C++ compiler was found.') + + def AddVersioning(self, binary): + binary.compiler.sourcedeps += self.generated_headers + return binary + + def configure(self): + for cxx in self.all_targets: + if cxx.target.arch not in ['x86', 'x86_64']: + raise Exception('Unknown target architecture: {0}'.format(arch)) + + self.configure_cxx(cxx) + + def configure_cxx(self, cxx): + if cxx.behavior == 'gcc': + cxx.defines += [ + 'HAVE_STDINT_H', + 'GNUC', + ] + cxx.cflags += [ + '-pipe', + '-fno-strict-aliasing', + '-Wall', + '-Werror', + '-Wno-uninitialized', + '-Wno-sign-compare', + '-Wno-unused', + '-Wno-switch', + '-Wno-unknown-pragmas', + '-Wno-dangling-else', + '-Wno-null-dereference', + '-msse', + '-msse2', + '-fPIC', + '-std=c++17', + ] + + if (cxx.version >= 'gcc-4.0') or cxx.family == 'clang': + cxx.cflags += ['-fvisibility=hidden'] + cxx.cxxflags += ['-fvisibility-inlines-hidden'] + cxx.cxxflags += [ + '-fexceptions', + '-fno-rtti', + '-fno-threadsafe-statics', + '-Wno-non-virtual-dtor', + '-Wno-overloaded-virtual', + '-Wno-register', + ] + if (cxx.version >= 'gcc-4.7' or cxx.family == 'clang'): + cxx.cxxflags += ['-Wno-delete-non-virtual-dtor'] + if cxx.family == 'gcc': + cxx.cflags += ['-mfpmath=sse'] + cxx.cxxflags += ['-Wno-class-memaccess'] + if cxx.family == 'clang': + cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch'] + if cxx.version >= 'clang-3.9' or cxx.version >= 'apple-clang-10.0': + cxx.cxxflags += ['-Wno-expansion-to-defined'] + if cxx.version >= 'clang-3.6' or cxx.version >= 'apple-clang-7.0': + cxx.cxxflags += ['-Wno-inconsistent-missing-override'] + if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4': + cxx.cxxflags += ['-Wno-deprecated-register'] + else: + cxx.cxxflags += ['-Wno-deprecated'] + + # Work around SDK warnings. + if cxx.version >= 'clang-10.0' or cxx.version >= 'apple-clang-12.0': + cxx.cflags += [ + '-Wno-implicit-int-float-conversion', + '-Wno-tautological-overlap-compare', + ] + + elif cxx.like('msvc'): + if builder.options.debug == '1': + cxx.cflags += ['/MTd'] + cxx.linkflags += ['/NODEFAULTLIB:libcmt'] + else: + cxx.cflags += ['/MT'] + cxx.defines += [ + '_CRT_SECURE_NO_DEPRECATE', + '_CRT_SECURE_NO_WARNINGS', + '_CRT_NONSTDC_NO_DEPRECATE', + ] + cxx.cflags += [ + '/W3', + '/EHsc' + ] + cxx.cxxflags += ['/TP', '/std:c++17'] + + cxx.linkflags += [ + '/SUBSYSTEM:WINDOWS', + 'kernel32.lib', + 'user32.lib', + 'gdi32.lib', + 'winspool.lib', + 'comdlg32.lib', + 'advapi32.lib', + 'shell32.lib', + 'ole32.lib', + 'oleaut32.lib', + 'uuid.lib', + 'odbc32.lib', + 'odbccp32.lib', + ] + + # Optimization + if builder.options.opt: + cxx.defines += ['NDEBUG'] + if cxx.behavior == 'gcc': + cxx.cflags += ['-O3'] + elif cxx.behavior == 'msvc': + cxx.cflags += ['/Ox', '/Zo'] + cxx.linkflags += ['/OPT:ICF', '/OPT:REF'] + + # Debugging + if builder.options.debug: + cxx.defines += ['DEBUG', '_DEBUG'] + if cxx.behavior == 'gcc': + cxx.cflags += ['-g3'] + elif cxx.behavior == 'msvc': + cxx.cflags += ['/Od', '/RTC1'] + + # Don't omit the frame pointer. + # This needs to be after our optimization flags which could otherwise disable it. + if cxx.behavior == 'gcc': + cxx.cflags += ['-fno-omit-frame-pointer'] + elif cxx.behavior == 'msvc': + cxx.cflags += ['/Oy-'] + + # Platform-specifics + if cxx.target.platform == 'linux': + cxx.defines += ['LINUX', '_LINUX', 'POSIX', '_FILE_OFFSET_BITS=64'] + if cxx.family == 'gcc': + cxx.linkflags += ['-static-libgcc'] + elif cxx.family == 'clang': + cxx.linkflags += ['-lgcc_eh'] + cxx.linkflags += ['-static-libstdc++'] + elif cxx.target.platform == 'mac': + cxx.defines += ['OSX', '_OSX', 'POSIX'] + + if cxx.version >= 'apple-clang-10.0': + cxx.cflags += ['-mmacosx-version-min=10.9', '-stdlib=libc++'] + cxx.linkflags += [ + '-mmacosx-version-min=10.9', + ] + else: + cxx.cflags += ['-mmacosx-version-min=10.5'] + cxx.linkflags += [ + '-mmacosx-version-min=10.5', + ] + + cxx.linkflags += [ + '-stdlib=libc++', + '-lc++', + ] + cxx.cxxflags += ['-stdlib=libc++'] + elif cxx.target.platform == 'windows': + cxx.defines += ['WIN32', '_WINDOWS'] + + def findSdkPath(self, sdk_name): + dir_name = 'hl2sdk-{}'.format(sdk_name) + if builder.options.hl2sdk_root: + sdk_path = os.path.join(builder.options.hl2sdk_root, dir_name) + if os.path.exists(sdk_path): + return sdk_path + return ResolveEnvPath('HL2SDK{}'.format(sdk_name.upper()), dir_name) + + def shouldIncludeSdk(self, sdk): + if sdk.get('source2', False): + return False + return True + + def detectSDKs(self): + sdk_list = builder.options.sdks.split(',') + SdkHelpers.sdk_filter = self.shouldIncludeSdk + SdkHelpers.find_sdk_path = self.findSdkPath + SdkHelpers.findSdks(builder, self.all_targets, sdk_list) + + self.sdks = SdkHelpers.sdks + self.sdk_manifests = SdkHelpers.sdk_manifests + self.sdk_targets = SdkHelpers.sdk_targets + + def Library(self, cxx, name): + binary = cxx.Library(name) + return binary + + def StaticLibrary(self, cxx, name): + return cxx.StaticLibrary(name) + + def HL2Library(self, context, compiler, name, sdk): + binary = self.Library(compiler, name) + self.AddVersioning(binary) + cxx = binary.compiler + + cxx.cxxincludes += [ + os.path.join(context.currentSourcePath), + os.path.join(context.currentSourcePath, 'sourcehook'), + os.path.join(context.sourcePath, 'loader'), + os.path.join(self.mms_root, 'core'), + os.path.join(self.mms_root, 'core', 'sourcehook'), + ] + + for other_sdk in self.sdk_manifests: + cxx.defines += ['SE_{}={}'.format(other_sdk['define'], other_sdk['code'])] + + SdkHelpers.configureCxx(context, binary, sdk) + + return binary + +if builder.options.breakpadupload == '1' and not 'BREAKPAD_SYMBOL_SERVER' in os.environ: + raise Exception("--breakpad-upload passed to configure.py but environment variable 'BREAKPAD_SYMBOL_SERVER' isn't set!") + +if builder.options.breakpadupload == '1' and not builder.options.sm_path: + raise Exception("--breakpad-upload requires SourceMod path to be set!") + +MMS = MMSConfig() +MMS.detectSDKs() +MMS.configure() + +MMS.generated_headers = builder.Build('versioning/AMBuildScript', { 'MMS': MMS }) + +# This will clone the list and each cxx object as we recurse, preventing child +# scripts from messing up global state. +builder.targets = builder.CloneableList(MMS.all_targets) + +BuildScripts = [ + 'AMBuilder', + 'loader/AMBuilder' +] # add sub-modules here +if getattr(builder.options, 'enable_tests', False): + BuildScripts += [] # add tests here + +#import os + +if builder.backend == 'amb2': + BuildScripts += [ + 'PackageScript', + ] + +if builder.options.breakpadupload == '1': + BuildScripts += ['BreakpadSymbols'] + +builder.Build(BuildScripts, { 'MMS': MMS }) diff --git a/AMBuilder b/AMBuilder new file mode 100644 index 000000000..40f663e93 --- /dev/null +++ b/AMBuilder @@ -0,0 +1,180 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: +import os, sys + +projectName = 'rcbot' + +sourceFiles = [ + "utils/RCBot2_meta/bot.cpp", + "utils/RCBot2_meta/bot_accessclient.cpp", + #"utils/RCBot2_meta/bot_black_mesa.cpp", + "utils/RCBot2_meta/bot_buttons.cpp", + "utils/RCBot2_meta/bot_client.cpp", + "utils/RCBot2_meta/bot_commands.cpp", + "utils/RCBot2_meta/bot_configfile.cpp", + "utils/RCBot2_meta/bot_coop.cpp", + "utils/RCBot2_meta/bot_css_bot.cpp", + "utils/RCBot2_meta/bot_css_buying.cpp", + "utils/RCBot2_meta/bot_css_mod.cpp", + "utils/RCBot2_meta/bot_dod_bot.cpp", + "utils/RCBot2_meta/bot_dod_mod.cpp", + "utils/RCBot2_meta/bot_events.cpp", + "utils/RCBot2_meta/bot_fortress.cpp", + "utils/RCBot2_meta/bot_ga.cpp", + "utils/RCBot2_meta/bot_ga_ind.cpp", + "utils/RCBot2_meta/bot_getprop.cpp", + "utils/RCBot2_meta/bot_globals.cpp", + "utils/RCBot2_meta/bot_hl1dmsrc.cpp", + "utils/RCBot2_meta/bot_hldm_bot.cpp", + "utils/RCBot2_meta/bot_kv.cpp", + "utils/RCBot2_meta/bot_menu.cpp", + "utils/RCBot2_meta/bot_mods.cpp", + "utils/RCBot2_meta/bot_mtrand.cpp", + #"utils/RCBot2_meta/bot_navmesh.cpp", + "utils/RCBot2_meta/bot_perceptron.cpp", + "utils/RCBot2_meta/bot_profile.cpp", + "utils/RCBot2_meta/bot_profiling.cpp", + "utils/RCBot2_meta/bot_schedule.cpp", + "utils/RCBot2_meta/bot_tf2_points.cpp", + "utils/RCBot2_meta/bot_som.cpp", + "utils/RCBot2_meta/bot_squads.cpp", + "utils/RCBot2_meta/bot_strings.cpp", + "utils/RCBot2_meta/bot_synergy.cpp", + "utils/RCBot2_meta/bot_synergy_mod.cpp", + "utils/RCBot2_meta/bot_task.cpp", + "utils/RCBot2_meta/bot_tf2_mod.cpp", + "utils/RCBot2_meta/bot_utility.cpp", + "utils/RCBot2_meta/bot_visibles.cpp", + "utils/RCBot2_meta/bot_waypoint.cpp", + "utils/RCBot2_meta/bot_waypoint_locations.cpp", + "utils/RCBot2_meta/bot_waypoint_visibility.cpp", + "utils/RCBot2_meta/bot_weapons.cpp", + "utils/RCBot2_meta/bot_wpt_dist.cpp", + "utils/RCBot2_meta/bot_zombie.cpp", + "utils/RCBot2_meta/bot_sigscan.cpp", + "utils/RCBot2_meta/bot_cvars.cpp", + "utils/RCBot2_meta/bot_plugin_meta.cpp", + + "rcbot/logging.cpp", + "rcbot/helper.cpp", + "rcbot/entprops.cpp", + "rcbot/propvar.cpp", + "rcbot/math_fix.cpp", + "rcbot/utils.cpp", + "rcbot/tf2/conditions.cpp", +] + +include_paths = [ + os.path.join(builder.currentSourcePath, 'utils', 'RCBot2_meta'), +] + +compiler_defines = [] + +# Build with SourceMod extension support if --sm-path was specified +if builder.options.sm_path: + # Validate required SourceMod directories exist + required_sm_dirs = [ + os.path.join(builder.options.sm_path, 'sourcepawn', 'include'), + os.path.join(builder.options.sm_path, 'public'), + ] + + for sm_dir in required_sm_dirs: + if not os.path.isdir(sm_dir): + raise Exception("Required SourceMod directory '{}' not found. Check your --sm-path setting.".format(sm_dir)) + + include_paths += [ + os.path.join(builder.options.sm_path, 'sourcepawn', 'include'), + os.path.join(builder.options.sm_path, 'public', 'amtl'), + os.path.join(builder.options.sm_path, 'public', 'amtl', 'amtl'), + os.path.join(builder.options.sm_path, 'public', 'extensions'), + os.path.join(builder.options.sm_path, 'public'), + os.path.join(builder.currentSourcePath, 'sm_ext'), + ] + + sourceFiles += [ + os.path.join(builder.currentSourcePath, 'sm_ext', 'smsdk_config.cpp'), + os.path.join(builder.currentSourcePath, 'sm_ext', 'bot_sm_ext.cpp'), + os.path.join(builder.currentSourcePath, 'sm_ext', 'bot_sm_natives.cpp'), + ] + + compiler_defines += [ 'SM_EXT', ] + +# List of SDK names that require hooks on runcmd +mods_requiring_runcmd_overrides = [ + # hack: DOD:S uses `Bot_Think`, which forces all `bot`-spawned entities to use Valve's + # default bot AI. we'll hook into their RunPlayerMove for now, but for consistency across + # games it'd be better to supercede `Bot_Think` (or `Bot_RunAll` higher up the call stack) + 'dods', +] + +# List of SDK Names that has undefined reference to some math functions +sdks_requring_extern_math_functions = [ + 'sdk2013', + 'bms', +] + +# Decouple sourcesdk MAX_PLAYERS from the project - NoSoop +# https://github.com/nosoop/rcbot2/commit/684f2a28189b4523d067a31b26778632e5e50212 +default_maxplayers = 65 +override_maxplayers = { + 'tf2': 101, + 'hl2dm': 101, +} + +############### +# Make sure to edit PackageScript, which copies your files to their appropriate locations +# Simple extensions do not need to modify past this point. + +# set up the build info +include_paths += [ + os.path.join(builder.currentSourcePath, 'versioning'), + os.path.join(builder.buildPath, 'includes'), + ] + +sourceFiles += [ os.path.join(builder.currentSourcePath, 'versioning', 'build_info.cpp'), ] + +if os.path.isfile(os.path.join(builder.currentSourcePath, 'sdk', 'smsdk_ext.cpp')): + # Use the copy included in the project + # sourceFiles += [os.path.join('sdk', 'smsdk_ext.cpp')] + pass +else: + # Use the copy included with SM 1.6 and newer + # sourceFiles += [os.path.join(MMS.sm_root, 'public', 'smsdk_ext.cpp')] + pass + +for sdk_target in MMS.sdk_targets: + sdk = sdk_target.sdk + cxx = sdk_target.cxx + + name = projectName + '.' + sdk['extension'] + sdk_name = sdk['name'] + binary = MMS.HL2Library(builder, cxx, name, sdk) + + binary.sources += sourceFiles + + cxx = binary.compiler + + if cxx.family == 'msvc': + # suppress macro redefinition of 'offsetof' + cxx.cflags += [ '/wd4005' ] + + cxx.cxxincludes += include_paths + cxx.defines += compiler_defines + + if sdk_name in mods_requiring_runcmd_overrides: + cxx.defines += [ 'OVERRIDE_RUNCMD' ] + + if sdk_name in sdks_requring_extern_math_functions and cxx.target.platform == 'linux': + cxx.defines += [ 'MATH_LIB_FIX' ] + + # RCBot: Library requires exceptions + if '-fno-exceptions' in cxx.cflags: cxx.cflags.remove('-fno-exceptions') + + # Decouple sourcesdk MAX_PLAYERS from the project - NoSoop + cxx.defines += ['RCBOT_MAXPLAYERS={}'.format(override_maxplayers.get(sdk_name, default_maxplayers))] + + # Epic hack for rcbot2 + hl2sdkfolder = 'hl2sdk-' + sdk['name'] + cxx.cxxincludes += [ os.path.join(builder.options.hl2sdk_root, hl2sdkfolder, 'game', 'server') ] + + nodes = builder.Add(binary) + MMS.binaries += [nodes] diff --git a/BreakpadSymbols b/BreakpadSymbols new file mode 100644 index 000000000..e655d5bc9 --- /dev/null +++ b/BreakpadSymbols @@ -0,0 +1,39 @@ +# vim: set ts=2 sw=2 tw=99 noet ft=python: +import os, sys + +UPLOAD_SCRIPT = os.path.join(MMS.sm_path, 'tools', 'buildbot', 'upload_symbols.py') + +if 'BREAKPAD_SYMBOL_SERVER' in os.environ: + symbolServer = os.environ['BREAKPAD_SYMBOL_SERVER'] + builder.SetBuildFolder('breakpad-symbols') + + for cxx_task in MMS.binaries: + if cxx_task.target.platform in ['windows']: + debug_entry = cxx_task.debug + else: + debug_entry = cxx_task.binary + + debug_file = os.path.join(builder.buildPath, debug_entry.path) + if cxx_task.target.platform == 'linux': + argv = ['dump_syms', debug_file, os.path.dirname(debug_file)] + elif cxx_task.target.platform == 'mac': + # Required once dump_syms is updated on the slaves. + #argv = ['dump_syms', '-g', debug_file + '.dSYM', debug_file] + argv = ['dump_syms', debug_file + '.dSYM'] + elif cxx_task.target.platform == 'windows': + argv = ['dump_syms.exe', debug_file] + + plat_dir = os.path.dirname(debug_file) + bin_dir = os.path.split(plat_dir)[0] + + symbol_file = '{}-{}-{}.breakpad'.format( + os.path.split(bin_dir)[1], + cxx_task.target.platform, + cxx_task.target.arch) + + argv = [sys.executable, UPLOAD_SCRIPT, symbol_file] + argv + builder.AddCommand( + inputs = [UPLOAD_SCRIPT, debug_entry], + argv = argv, + outputs = [symbol_file] + ) \ No newline at end of file diff --git a/PackageScript b/PackageScript new file mode 100644 index 000000000..5105c8696 --- /dev/null +++ b/PackageScript @@ -0,0 +1,64 @@ +# vim: set ts=8 sts=2 sw=2 tw=99 et ft=python: +import os + +# This is where the files will be output to +# package is the default +builder.SetBuildFolder('package') + +# Add any folders you need to this list +folder_list = [ + 'addons/metamod', + 'addons/rcbot2/aux_data', + 'addons/rcbot2/bin', + 'addons/rcbot2/config', + # 'addons/rcbot2/launcher', + # 'addons/rcbot2/manual', + 'addons/rcbot2/profiles', + 'addons/rcbot2/waypoints', +] + +if 'x86_64' in MMS.target_archs: + folder_list.extend([ + 'addons/rcbot2/bin/x64', + ]) + +# Create the distribution folder hierarchy. +folder_map = {} +for folder in folder_list: + norm_folder = os.path.normpath(folder) + folder_map[folder] = builder.AddFolder(norm_folder) + +# Do all straight-up file copies from the source tree. +def CopyFiles(src, dest, files): + if not dest: + dest = src + dest_entry = folder_map[dest] + for source_file in files: + source_path = os.path.join(builder.sourcePath, src, source_file) + builder.AddCopy(source_path, dest_entry) + +CopyFiles('package', 'addons/metamod', + [ 'rcbot2.vdf', ] +) + +# RCBot2 config files +CopyFiles('package/config', 'addons/rcbot2/config', + [ + 'accessclients.ini', + 'attack_util.csv', + 'bot_mods.ini', + 'bot_quota.ini', + 'config.ini', + 'hookinfo.ini', + 'normal_util.csv', + 'weapons.ini' + ] +) + +# Copy binaries. +for cxx_task in MMS.binaries: + # mms expects our loader (RCBot2Meta) to exist in /bin/ + if cxx_task.target.arch == 'x86_64' and not 'RCBot2Meta' in cxx_task.binary.path: + builder.AddCopy(cxx_task.binary, folder_map['addons/rcbot2/bin/x64']) + else: + builder.AddCopy(cxx_task.binary, folder_map['addons/rcbot2/bin']) diff --git a/README.md b/README.md index e3afa8a5a..8a10245d1 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,163 @@ # RCBot2 for Windows and Linux (TF2, HL2:DM, DOD:S) -## Information -This is a fork of Cheeseh's RCBot2 repository. This aims to build on top of it to add features along with possible stability fixes. -Note that this is mainly intended for TF2. +## Information:- -[Installation](http://rcbot.bots-united.com/forums/index.php?showtopic=1967) +This is a fork of [the official RCBot2 plugin][rcbot2] written by Cheeseh. +Special thanks to pongo1231 for adding more TF2 support and NoSoop for adding AMBuild support and many more! -## Building -### Windows -Make sure to have Visual Studio 2013 installed. -Other than that, it should compile fine, even with the latest Visual Studio 2017. +The [bots-united.com discord][] and [forums][bots-united forums] are the places to ask for +general RCBot2 support. I'm not present in either of those; file an issue on this repository if +you need support for this particular project. -### Linux -Run ./compile.sh in 'linux_sdk' +[rcbot2]: http://rcbot.bots-united.com/ +[bots-united.com discord]: https://discord.gg/5v5YvKG4Hr +[bots-united forums]: http://rcbot.bots-united.com/forums/index.php?showforum=18 -Alternatively: -* Go to `linux_sdk` -* Type `make -f Makefile.rcbot2 vcpm` -* Type `make -f Makefile.rcbot2 genmf` (this will generate the Makefiles) -* Edit `Makefile.rcbot2` and `Makefile.HPB_bot2_*` according to your needs - * Most of the time you will only need to modify Line 21 and 55 of `Makefile.rcbot2` -* Type `make -f Makefile.rcbot2 all -j4 2> error.log` -* Check the `error.log` +## Changes from upstream:- ---- +- Build process uses [AMBuild][] instead of `make` or Visual Studio. This removes the need for +Valve's cross platform make conversion tool and keeping copies of modified Source SDK files. +- The plugin has been split into SDK-specific builds to ensure proper compatibility, using the +same loader shim SourceMod uses to load mod-specific builds. + - The shim is named `RCBot2Meta` to maintain compatibility with existing files; mod-specific + plugins are named `rcbot.2.${MOD}`. + - The `sdk-split` branch only contains modifications to get the project running on the + new build tooling and SDK support without issues. It should be fairly painless to merge + (though it does remove `using namespace std;` for sanity). +- The usage of the install directory has been dropped. In particular, waypoints must be located +under `rcbot2/waypoints/${MOD}` instead of nested under a folder matching the name of the +steamdir. +- Removed custom loadout and attribute support from the TF2 portion of the plugin. Other server +plugins (namely [tf2attributes][] and [TF2Items][], where the implementation was ported from) +are better-suited and maintained to handle that stuff; this plugin should only deal with bots +themselves. +- The Metamod:Source plugin can now optionally expose natives to SourceMod, adding some +functionality to control the RCBot2 plugin from SourcePawn. -Make sure to check out the [bots-united.com discord](https://discord.gg/BbxR5wY) for support and to stay updated. \ No newline at end of file +[AMBuild]: https://wiki.alliedmods.net/AMBuild +[tf2attributes]: https://github.com/FlaminSarge/tf2attributes +[TF2Items]: https://github.com/asherkin/TF2Items + +## Installation:- + +1. [Install MetaMod:Source]. +2. Download or build the RCBot2 package. +3. Extract the package into your game directory, similar to the process of installing MM:S. +4. Start the server. +5. To verify that the installation was successful, type `rcbotd` in your server console or RCON. +You should see multiple lines starting with "[RCBot]". + +Things like the waypointing guide, hookinfo updater, and waypoints themselves are currently not +available here. You can download those from the [official release thread][]. Waypoints are +also available at [this page][waypoints]. + +[Install MetaMod:Source]: https://wiki.alliedmods.net/Installing_Metamod:Source +[official release thread]: http://rcbot.bots-united.com/forums/index.php?showtopic=1994 +[waypoints]: http://rcbot.bots-united.com/waypoints.php + +## Building:- + +### Cloning from source + +RCBot2's repo history had all sorts of build artifacts / binaries at various points in time, so +pulling the repository down normally takes an unusually long while. I'd highly recommend +passing in `--depth 1` or a few to avoid retrieving the files that were removed since then. + +### Compiling on Windows / Linux + +1. [Install the prerequisites for building SourceMod for your OS.][Building SourceMod] +2. Create a `build/` subdirectory, then run `configure.py`. + - Use the following options (where `${MOD}` is only TF2): + `python ../configure.py -s ${MOD} --mms_path ${MMS_PATH} --hl2sdk-root ${HL2SDK_ROOT}` + - Specifying an `--sm-path` argument enables linking to SourceMod. + - Note that the automatic versioning system requires an installation of `git` and a + relatively modern version of Python 3. Python version 2 is now depreciated. +3. Run `ambuild`. MetaMod:Source plugin is built and the base install files will be available +in `build/package`. + +[Building SourceMod]: https://wiki.alliedmods.net/Building_SourceMod + +## License:- + +RCBot2 is released under the [GNU Affero General Public License][]. Among other things, this +means that any modifications you make to RCBot2 must have the sources available under the same +license to players on your server. + +Additionally, `rcbot/logging.{h,cpp}` is released separately under the +[BSD Zero Clause License][]. + +[GNU Affero General Public License]: https://spdx.org/licenses/AGPL-3.0-only.html +[BSD Zero Clause License]: https://spdx.org/licenses/0BSD.html + +### To-do:- + +- To allow bots to menuselect to buy upgrades for MVM +- To improve game detection for non-listed Source gamemods +- To add proper support for the new Zombie Infection TF2 maps since Scream Fortress XV update +- To add proper support for Robot Destruction gameplay by destroying bots when not ubered +- To prevent EngiBots from facing their SG Turrets the wrong way - Testing in progress! +- To allow DemoBots to sticky jump again - might need to check with using RCBot2 v1.7-beta versions +- To improve on how Medic and Spy bots behave smarter and adequately when interacting with SG Turrets and Healing/Ubering +- Bots need to understand how to play Kart games from sd_doomsday_event as they only wonder around those minigames +- CBotTF2::changeClass needs to be implemented to avoid bots punting when using ClassRestrictionsForBots.smx and `rcbot_change_classes 1` - Testing in progress! +- To add TF2C support along with Black Mesa Source, Counter-Strike: Source, Synergy and Dystopia + +## Credits:- + +- Founder - Cheeseh +- Bot base code - Botman's HPB Template +- Linux Conversion and Waypointing - [APG]RoboCop[CL] +- TF2 support and enhancements - Ducky1231/Pongo +- SourceMod and AMBuild support - nosoop +- Synergy, TF2, MvM, CSS and AMBuild support - Anonymous Player/caxanga334 +- TF2 Classic support - Technochips +- TF2 additional gamemodes support - RussiaTails +- Linux Black Mesa and SDK2013 mathlib fix - Sappho +- Dystopia support - Soft As Hell +- Major waypointer for TF2 - LK777, RussiaTails, Witch, Francis, RevilleAJ, Waffle033 +- Major waypointer for DoDS - INsane, Gamelarg05, genmac + +## Waypointers:- + +- NightC0re +- wakaflaka +- dgesd +- naMelesS +- ati251 +- Sandman[SA] +- Speed12 +- MarioGuy3 +- Sjru +- Fillmore +- htt123 +- swede +- YouLoseAndIWin +- ChiefEnragedDemo +- madmax2 +- Pyri +- Softny +- Wolf +- TesterYYY +- darkranger +- Emotional +- J@ck@l +- YuriFR +- Otakumanu +- 芝士人 +- Eye of Justice +- TheSpyhasaGun (ScoutDogger) +- NifesNforks +- parkourtrane +- assface +- Doc Lithius +- Kamaji +- Geralt +- Smoker +- dzoo11 +- Combine Soldier +- cyglade +- TFBot_Maverick +- apdonato +- Sntr +- mehdichallenger +- Mikou diff --git a/alliedmodders/hl2sdk-bms b/alliedmodders/hl2sdk-bms new file mode 160000 index 000000000..275769daf --- /dev/null +++ b/alliedmodders/hl2sdk-bms @@ -0,0 +1 @@ +Subproject commit 275769daf18769d37bbe9dc83200e79a347fd4b1 diff --git a/alliedmodders/hl2sdk-css b/alliedmodders/hl2sdk-css new file mode 160000 index 000000000..94b660e16 --- /dev/null +++ b/alliedmodders/hl2sdk-css @@ -0,0 +1 @@ +Subproject commit 94b660e16ec1447ca80c74741642f593ddfa9dfc diff --git a/alliedmodders/hl2sdk-dods b/alliedmodders/hl2sdk-dods new file mode 160000 index 000000000..25351308f --- /dev/null +++ b/alliedmodders/hl2sdk-dods @@ -0,0 +1 @@ +Subproject commit 25351308fe0e5c742e92eba67147ac0436830218 diff --git a/alliedmodders/hl2sdk-hl2dm b/alliedmodders/hl2sdk-hl2dm new file mode 160000 index 000000000..cab4b5540 --- /dev/null +++ b/alliedmodders/hl2sdk-hl2dm @@ -0,0 +1 @@ +Subproject commit cab4b5540f0018c358d5961a4880244635ab61e1 diff --git a/alliedmodders/hl2sdk-proxy-repo b/alliedmodders/hl2sdk-proxy-repo new file mode 160000 index 000000000..4c27c1305 --- /dev/null +++ b/alliedmodders/hl2sdk-proxy-repo @@ -0,0 +1 @@ +Subproject commit 4c27c1305c5e042ae1f62f6dc6ba7e96fd06e05d diff --git a/alliedmodders/hl2sdk-sdk2013 b/alliedmodders/hl2sdk-sdk2013 new file mode 160000 index 000000000..4c27c1305 --- /dev/null +++ b/alliedmodders/hl2sdk-sdk2013 @@ -0,0 +1 @@ +Subproject commit 4c27c1305c5e042ae1f62f6dc6ba7e96fd06e05d diff --git a/alliedmodders/hl2sdk-tf2 b/alliedmodders/hl2sdk-tf2 new file mode 160000 index 000000000..ebd971b42 --- /dev/null +++ b/alliedmodders/hl2sdk-tf2 @@ -0,0 +1 @@ +Subproject commit ebd971b42177ba73ca25a05f33551fa2005525b6 diff --git a/alliedmodders/metamod-source b/alliedmodders/metamod-source new file mode 160000 index 000000000..2309b81e6 --- /dev/null +++ b/alliedmodders/metamod-source @@ -0,0 +1 @@ +Subproject commit 2309b81e6e6ad92282346d1b0d68eaa6578324ff diff --git a/alliedmodders/sourcemod b/alliedmodders/sourcemod new file mode 160000 index 000000000..6baf01ac3 --- /dev/null +++ b/alliedmodders/sourcemod @@ -0,0 +1 @@ +Subproject commit 6baf01ac3b1b3ec23ff042715753b5517e41ffd8 diff --git a/cheeseh_rcbot2_repo.kdev4 b/cheeseh_rcbot2_repo.kdev4 deleted file mode 100644 index 20b892926..000000000 --- a/cheeseh_rcbot2_repo.kdev4 +++ /dev/null @@ -1,4 +0,0 @@ -[Project] -CreatedFrom= -Manager=KDevCustomBuildSystem -Name=cheeseh_rcbot2_repo diff --git a/clang-format.txt b/clang-format.txt new file mode 100644 index 000000000..014413051 --- /dev/null +++ b/clang-format.txt @@ -0,0 +1,100 @@ +--- +Language: Cpp +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: None +AlignConsecutiveAssignments: AcrossEmptyLinesAndComments +AlignConsecutiveBitFields: None +AlignConsecutiveDeclarations: None +AlignEscapedNewlines: Left +AlignOperands: AlignAfterOperator +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortEnumsOnASingleLine: false +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortLambdasOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +BinPackArguments: true +BinPackParameters: true +BreakBeforeBinaryOperators: NonAssignment +BreakBeforeConceptDeclarations: true +BreakBeforeBraces: Allman +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +BreakStringLiterals: true +ColumnLimit: 120 +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: false +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false +IncludeBlocks: Preserve +IndentCaseLabels: false +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: Indent +IndentRequires: false +IndentWidth: 4 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: All +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PenaltyIndentedWhitespace: 0 +PointerAlignment: Right +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceAroundPointerQualifiers: Default +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +BitFieldColonSpacing: Both +Standard: Latest +TabWidth: 4 +UseCRLF: true +UseTab: ForIndentation \ No newline at end of file diff --git a/configure.py b/configure.py new file mode 100644 index 000000000..7cf087d82 --- /dev/null +++ b/configure.py @@ -0,0 +1,27 @@ +import sys +import os +from ambuild2 import run + +build_dir = os.path.join(sys.path[0], 'post') +os.makedirs(build_dir, exist_ok=True) + +parser = run.BuildParser(sourcePath=sys.path[0], api='2.2') +parser.options.add_argument('--hl2sdk-root', type=str, dest='hl2sdk_root', default=None, + help='Root search folder for HL2SDKs') +parser.options.add_argument('--sm-path', type=str, dest='sm_path', default=None, + help='Path to SourceMod') +parser.options.add_argument('--mms-path', type=str, dest='mms_path', default=None, + help='Path to Metamod:Source') + +parser.options.add_argument('--enable-debug', action='store_const', const='1', dest='debug', + help='Enable debugging symbols') +parser.options.add_argument('--enable-optimize', action='store_const', const='1', dest='opt', + help='Enable optimization') +parser.options.add_argument('-s', '--sdks', default='present', dest='sdks', + help='Build against specified SDKs; valid args are "none", "all", "present",' + ' or comma-delimited list of engine names') +parser.options.add_argument('--targets', type=str, dest='targets', default=None, + help="Override the target architecture (use commas to separate multiple targets).") +parser.options.add_argument('--breakpad-upload', action='store_const', const='1', dest='breakpadupload', + help="Allow the upload of breakpad symbols to Accelerator.") +parser.Configure() \ No newline at end of file diff --git a/game/server/AI_Criteria.cpp b/game/server/AI_Criteria.cpp deleted file mode 100644 index 4771ae480..000000000 --- a/game/server/AI_Criteria.cpp +++ /dev/null @@ -1,510 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "AI_Criteria.h" -#include "ai_speech.h" -#include -#include "engine/IEngineSound.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -AI_CriteriaSet::AI_CriteriaSet() : m_Lookup( 0, 0, CritEntry_t::LessFunc ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : src - -//----------------------------------------------------------------------------- -AI_CriteriaSet::AI_CriteriaSet( const AI_CriteriaSet& src ) : m_Lookup( 0, 0, CritEntry_t::LessFunc ) -{ - m_Lookup.Purge(); - for ( short i = src.m_Lookup.FirstInorder(); - i != src.m_Lookup.InvalidIndex(); - i = src.m_Lookup.NextInorder( i ) ) - { - m_Lookup.Insert( src.m_Lookup[ i ] ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -AI_CriteriaSet::~AI_CriteriaSet() -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *criteria - -// "" - -// 1.0f - -//----------------------------------------------------------------------------- -void AI_CriteriaSet::AppendCriteria( const char *criteria, const char *value /*= ""*/, float weight /*= 1.0f*/ ) -{ - int idx = FindCriterionIndex( criteria ); - if ( idx == -1 ) - { - CritEntry_t entry; - entry.criterianame = criteria; - MEM_ALLOC_CREDIT(); - idx = m_Lookup.Insert( entry ); - } - - CritEntry_t *entry = &m_Lookup[ idx ]; - - entry->SetValue( value ); - entry->weight = weight; -} - - -//----------------------------------------------------------------------------- -// Removes criteria in a set -//----------------------------------------------------------------------------- -void AI_CriteriaSet::RemoveCriteria( const char *criteria ) -{ - int idx = FindCriterionIndex( criteria ); - if ( idx == -1 ) - return; - - m_Lookup.RemoveAt( idx ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int AI_CriteriaSet::GetCount() const -{ - return m_Lookup.Count(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -// Output : int -//----------------------------------------------------------------------------- -int AI_CriteriaSet::FindCriterionIndex( const char *name ) const -{ - CritEntry_t search; - search.criterianame = name; - int idx = m_Lookup.Find( search ); - if ( idx == m_Lookup.InvalidIndex() ) - return -1; - - return idx; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -// Output : char const -//----------------------------------------------------------------------------- -const char *AI_CriteriaSet::GetName( int index ) const -{ - static char namebuf[ 128 ]; - if ( index < 0 || index >= (int)m_Lookup.Count() ) - return ""; - - const CritEntry_t *entry = &m_Lookup[ index ]; - Q_strncpy( namebuf, entry->criterianame.String(), sizeof( namebuf ) ); - return namebuf; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -// Output : char const -//----------------------------------------------------------------------------- -const char *AI_CriteriaSet::GetValue( int index ) const -{ - if ( index < 0 || index >= (int)m_Lookup.Count() ) - return ""; - - const CritEntry_t *entry = &m_Lookup[ index ]; - return entry->value ? entry->value : ""; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -// Output : float -//----------------------------------------------------------------------------- -float AI_CriteriaSet::GetWeight( int index ) const -{ - if ( index < 0 || index >= (int)m_Lookup.Count() ) - return 1.0f; - - const CritEntry_t *entry = &m_Lookup[ index ]; - return entry->weight; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void AI_CriteriaSet::Describe() -{ - for ( short i = m_Lookup.FirstInorder(); i != m_Lookup.InvalidIndex(); i = m_Lookup.NextInorder( i ) ) - { - - CritEntry_t *entry = &m_Lookup[ i ]; - - if ( entry->weight != 1.0f ) - { - DevMsg( " %20s = '%s' (weight %f)\n", entry->criterianame.String(), entry->value ? entry->value : "", entry->weight ); - } - else - { - DevMsg( " %20s = '%s'\n", entry->criterianame.String(), entry->value ? entry->value : "" ); - } - } -} - -BEGIN_SIMPLE_DATADESC( AI_ResponseParams ) - DEFINE_FIELD( flags, FIELD_SHORT ), - DEFINE_FIELD( odds, FIELD_SHORT ), - DEFINE_FIELD( soundlevel, FIELD_CHARACTER ), - DEFINE_FIELD( delay, FIELD_INTEGER ), // These are compressed down to two float16s, so treat as an INT for saverestore - DEFINE_FIELD( respeakdelay, FIELD_INTEGER ), // -END_DATADESC() - -BEGIN_SIMPLE_DATADESC( AI_Response ) - DEFINE_FIELD( m_Type, FIELD_CHARACTER ), - DEFINE_ARRAY( m_szResponseName, FIELD_CHARACTER, AI_Response::MAX_RESPONSE_NAME ), - DEFINE_ARRAY( m_szMatchingRule, FIELD_CHARACTER, AI_Response::MAX_RULE_NAME ), - // DEFINE_FIELD( m_pCriteria, FIELD_??? ), // Don't need to save this probably - DEFINE_EMBEDDED( m_Params ), -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -AI_Response::AI_Response() -{ - m_Type = RESPONSE_NONE; - m_szResponseName[0] = 0; - m_pCriteria = NULL; - m_szMatchingRule[0]=0; - m_szContext = NULL; - m_bApplyContextToWorld = false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -AI_Response::AI_Response( const AI_Response &from ) -{ - Assert( (void*)(&m_Type) == (void*)this ); - m_pCriteria = NULL; - memcpy( this, &from, sizeof(*this) ); - m_pCriteria = NULL; - m_szContext = NULL; - SetContext( from.m_szContext ); - m_bApplyContextToWorld = from.m_bApplyContextToWorld; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -AI_Response::~AI_Response() -{ - delete m_pCriteria; - delete[] m_szContext; -} - -//----------------------------------------------------------------------------- -AI_Response &AI_Response::operator=( const AI_Response &from ) -{ - Assert( (void*)(&m_Type) == (void*)this ); - delete m_pCriteria; - m_pCriteria = NULL; - memcpy( this, &from, sizeof(*this) ); - m_pCriteria = NULL; - m_szContext = NULL; - SetContext( from.m_szContext ); - m_bApplyContextToWorld = from.m_bApplyContextToWorld; - return *this; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *response - -// *criteria - -//----------------------------------------------------------------------------- -void AI_Response::Init( ResponseType_t type, const char *responseName, const AI_CriteriaSet& criteria, const AI_ResponseParams& responseparams, const char *ruleName, const char *applyContext, bool bApplyContextToWorld ) -{ - m_Type = type; - Q_strncpy( m_szResponseName, responseName, sizeof( m_szResponseName ) ); - // Copy underlying criteria - m_pCriteria = new AI_CriteriaSet( criteria ); - Q_strncpy( m_szMatchingRule, ruleName ? ruleName : "NULL", sizeof( m_szMatchingRule ) ); - m_Params = responseparams; - SetContext( applyContext ); - m_bApplyContextToWorld = bApplyContextToWorld; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void AI_Response::Describe() -{ - if ( m_pCriteria ) - { - DevMsg( "Search criteria:\n" ); - m_pCriteria->Describe(); - } - if ( m_szMatchingRule[ 0 ] ) - { - DevMsg( "Matched rule '%s', ", m_szMatchingRule ); - } - if ( m_szContext ) - { - DevMsg( "Contexts to set '%s' on %s, ", m_szContext, m_bApplyContextToWorld ? "world" : "speaker" ); - } - - DevMsg( "response %s = '%s'\n", DescribeResponse( (ResponseType_t)m_Type ), m_szResponseName ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : char const -//----------------------------------------------------------------------------- -void AI_Response::GetName( char *buf, size_t buflen ) const -{ - Q_strncpy( buf, m_szResponseName, buflen ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : char const -//----------------------------------------------------------------------------- -void AI_Response::GetResponse( char *buf, size_t buflen ) const -{ - GetName( buf, buflen ); -} -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// Output : char const -//----------------------------------------------------------------------------- -const char *AI_Response::DescribeResponse( ResponseType_t type ) -{ - if ( (int)type < 0 || (int)type >= NUM_RESPONSES ) - { - Assert( 0 ); - return "???AI_Response bogus index"; - } - - switch( type ) - { - default: - { - Assert( 0 ); - } - // Fall through - case RESPONSE_NONE: - return "RESPONSE_NONE"; - case RESPONSE_SPEAK: - return "RESPONSE_SPEAK"; - case RESPONSE_SENTENCE: - return "RESPONSE_SENTENCE"; - case RESPONSE_SCENE: - return "RESPONSE_SCENE"; - case RESPONSE_RESPONSE: - return "RESPONSE_RESPONSE"; - case RESPONSE_PRINT: - return "RESPONSE_PRINT"; - } - - return "RESPONSE_NONE"; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const AI_CriteriaSet -//----------------------------------------------------------------------------- -const AI_CriteriaSet *AI_Response::GetCriteria() -{ - return m_pCriteria; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void AI_Response::Release() -{ - delete this; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : soundlevel_t -//----------------------------------------------------------------------------- -soundlevel_t AI_Response::GetSoundLevel() const -{ - if ( m_Params.flags & AI_ResponseParams::RG_SOUNDLEVEL ) - { - return (soundlevel_t)m_Params.soundlevel; - } - - return SNDLVL_TALKING; -} - -float AI_Response::GetRespeakDelay( void ) const -{ - if ( m_Params.flags & AI_ResponseParams::RG_RESPEAKDELAY ) - { - interval_t temp; - m_Params.respeakdelay.ToInterval( temp ); - return RandomInterval( temp ); - } - - return 0.0f; -} - -float AI_Response::GetWeaponDelay( void ) const -{ - if ( m_Params.flags & AI_ResponseParams::RG_WEAPONDELAY ) - { - interval_t temp; - m_Params.weapondelay.ToInterval( temp ); - return RandomInterval( temp ); - } - - return 0.0f; -} - -bool AI_Response::GetSpeakOnce( void ) const -{ - if ( m_Params.flags & AI_ResponseParams::RG_SPEAKONCE ) - { - return true; - } - - return false; -} - -bool AI_Response::ShouldntUseScene( void ) const -{ - return ( m_Params.flags & AI_ResponseParams::RG_DONT_USE_SCENE ) != 0; -} - -bool AI_Response::ShouldBreakOnNonIdle( void ) const -{ - return ( m_Params.flags & AI_ResponseParams::RG_STOP_ON_NONIDLE ) != 0; -} - -int AI_Response::GetOdds( void ) const -{ - if ( m_Params.flags & AI_ResponseParams::RG_ODDS ) - { - return m_Params.odds; - } - return 100; -} - -float AI_Response::GetDelay() const -{ - if ( m_Params.flags & AI_ResponseParams::RG_DELAYAFTERSPEAK ) - { - interval_t temp; - m_Params.delay.ToInterval( temp ); - return RandomInterval( temp ); - } - return 0.0f; -} - -float AI_Response::GetPreDelay() const -{ - if ( m_Params.flags & AI_ResponseParams::RG_DELAYBEFORESPEAK ) - { - interval_t temp; - m_Params.predelay.ToInterval( temp ); - return RandomInterval( temp ); - } - return 0.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: Sets context string -// Output : void -//----------------------------------------------------------------------------- -void AI_Response::SetContext( const char *context ) -{ - delete[] m_szContext; - m_szContext = NULL; - - if ( context ) - { - int len = Q_strlen( context ); - m_szContext = new char[ len + 1 ]; - Q_memcpy( m_szContext, context, len ); - m_szContext[ len ] = 0; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *raw - -// *key - -// keylen - -// *value - -// valuelen - -// *duration - -// Output : static bool -//----------------------------------------------------------------------------- -const char *SplitContext( const char *raw, char *key, int keylen, char *value, int valuelen, float *duration ) -{ - char *colon1 = Q_strstr( raw, ":" ); - if ( !colon1 ) - { - DevMsg( "SplitContext: warning, ignoring context '%s', missing colon separator!\n", raw ); - *key = *value = 0; - return NULL; - } - - int len = colon1 - raw; - Q_strncpy( key, raw, MIN( len + 1, keylen ) ); - key[ MIN( len, keylen - 1 ) ] = 0; - - bool last = false; - char *end = Q_strstr( colon1 + 1, "," ); - if ( !end ) - { - int remaining = Q_strlen( colon1 + 1 ); - end = colon1 + 1 + remaining; - last = true; - } - - char *colon2 = Q_strstr( colon1 + 1, ":" ); - if ( colon2 && ( colon2 < end ) ) - { - if ( duration ) - *duration = atof( colon2 + 1 ); - - len = MIN( colon2 - ( colon1 + 1 ), valuelen - 1 ); - Q_strncpy( value, colon1 + 1, len + 1 ); - value[ len ] = 0; - } - else - { - if ( duration ) - *duration = 0.0; - - len = MIN( end - ( colon1 + 1 ), valuelen - 1 ); - Q_strncpy( value, colon1 + 1, len + 1 ); - value[ len ] = 0; - } - - return last ? NULL : end + 1; -} diff --git a/game/server/AI_Criteria.h b/game/server/AI_Criteria.h deleted file mode 100644 index 5eebad88a..000000000 --- a/game/server/AI_Criteria.h +++ /dev/null @@ -1,237 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef AI_CRITERIA_H -#define AI_CRITERIA_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/utlrbtree.h" -#include "tier1/utlsymbol.h" -#include "interval.h" -#include "mathlib/compressed_vector.h" - -extern const char *SplitContext( const char *raw, char *key, int keylen, char *value, int valuelen, float *duration ); - - -class AI_CriteriaSet -{ -public: - AI_CriteriaSet(); - AI_CriteriaSet( const AI_CriteriaSet& src ); - ~AI_CriteriaSet(); - - void AppendCriteria( const char *criteria, const char *value = "", float weight = 1.0f ); - void RemoveCriteria( const char *criteria ); - - void Describe(); - - int GetCount() const; - int FindCriterionIndex( const char *name ) const; - - const char *GetName( int index ) const; - const char *GetValue( int index ) const; - float GetWeight( int index ) const; - -private: - - struct CritEntry_t - { - CritEntry_t() : - criterianame( UTL_INVAL_SYMBOL ), - weight( 0.0f ) - { - value[ 0 ] = 0; - } - - CritEntry_t( const CritEntry_t& src ) - { - criterianame = src.criterianame; - value[ 0 ] = 0; - weight = src.weight; - SetValue( src.value ); - } - - CritEntry_t& operator=( const CritEntry_t& src ) - { - if ( this == &src ) - return *this; - - criterianame = src.criterianame; - weight = src.weight; - SetValue( src.value ); - - return *this; - } - - static bool LessFunc( const CritEntry_t& lhs, const CritEntry_t& rhs ) - { - return Q_stricmp( lhs.criterianame.String(), rhs.criterianame.String() ) < 0 ? true : false; - } - - void SetValue( char const *str ) - { - if ( !str ) - { - value[ 0 ] = 0; - } - else - { - Q_strncpy( value, str, sizeof( value ) ); - } - } - - CUtlSymbol criterianame; - char value[ 64 ]; - float weight; - }; - - CUtlRBTree< CritEntry_t, short > m_Lookup; -}; - -#pragma pack(1) -template -struct response_interval_t -{ - T start; - T range; - - interval_t &ToInterval( interval_t &dest ) const { dest.start = start; dest.range = range; return dest; } - void FromInterval( const interval_t &from ) { start = from.start; range = from.range; } - float Random() const { interval_t temp = { start, range }; return RandomInterval( temp ); } -}; - -typedef response_interval_t responseparams_interval_t; - -struct AI_ResponseParams -{ - DECLARE_SIMPLE_DATADESC(); - - enum - { - RG_DELAYAFTERSPEAK = (1<<0), - RG_SPEAKONCE = (1<<1), - RG_ODDS = (1<<2), - RG_RESPEAKDELAY = (1<<3), - RG_SOUNDLEVEL = (1<<4), - RG_DONT_USE_SCENE = (1<<5), - RG_STOP_ON_NONIDLE = (1<<6), - RG_WEAPONDELAY = (1<<7), - RG_DELAYBEFORESPEAK = (1<<8), - }; - - AI_ResponseParams() - { - flags = 0; - odds = 100; - delay.start = 0; - delay.range = 0; - respeakdelay.start = 0; - respeakdelay.range = 0; - weapondelay.start = 0; - weapondelay.range = 0; - soundlevel = 0; - predelay.start = 0; - predelay.range = 0; - } - - responseparams_interval_t delay; //4 - responseparams_interval_t respeakdelay; //8 - responseparams_interval_t weapondelay; //12 - - short odds; //14 - - short flags; //16 - byte soundlevel; //17 - - responseparams_interval_t predelay; //21 -}; -#pragma pack() - -//----------------------------------------------------------------------------- -// Purpose: Generic container for a response to a match to a criteria set -// This is what searching for a response returns -//----------------------------------------------------------------------------- -enum ResponseType_t -{ - RESPONSE_NONE = 0, - RESPONSE_SPEAK, - RESPONSE_SENTENCE, - RESPONSE_SCENE, - RESPONSE_RESPONSE, // A reference to another response by name - RESPONSE_PRINT, - - NUM_RESPONSES, -}; - -class AI_Response -{ -public: - DECLARE_SIMPLE_DATADESC(); - - AI_Response(); - AI_Response( const AI_Response &from ); - ~AI_Response(); - AI_Response &operator=( const AI_Response &from ); - - void Release(); - - void GetName( char *buf, size_t buflen ) const; - void GetResponse( char *buf, size_t buflen ) const; - const AI_ResponseParams *GetParams() const { return &m_Params; } - ResponseType_t GetType() const { return (ResponseType_t)m_Type; } - soundlevel_t GetSoundLevel() const; - float GetRespeakDelay() const; - float GetWeaponDelay() const; - bool GetSpeakOnce() const; - bool ShouldntUseScene( ) const; - bool ShouldBreakOnNonIdle( void ) const; - int GetOdds() const; - float GetDelay() const; - float GetPreDelay() const; - - void SetContext( const char *context ); - const char * GetContext( void ) const { return m_szContext; } - - bool IsApplyContextToWorld( void ) { return m_bApplyContextToWorld; } - - void Describe(); - - const AI_CriteriaSet* GetCriteria(); - - void Init( ResponseType_t type, - const char *responseName, - const AI_CriteriaSet& criteria, - const AI_ResponseParams& responseparams, - const char *matchingRule, - const char *applyContext, - bool bApplyContextToWorld ); - - static const char *DescribeResponse( ResponseType_t type ); - - enum - { - MAX_RESPONSE_NAME = 64, - MAX_RULE_NAME = 64 - }; - - -private: - byte m_Type; - char m_szResponseName[ MAX_RESPONSE_NAME ]; - char m_szMatchingRule[ MAX_RULE_NAME ]; - - // The initial criteria to which we are responsive - AI_CriteriaSet *m_pCriteria; - - AI_ResponseParams m_Params; - - char * m_szContext; - bool m_bApplyContextToWorld; -}; - -#endif // AI_CRITERIA_H diff --git a/game/server/AI_Interest_Target.cpp b/game/server/AI_Interest_Target.cpp deleted file mode 100644 index baf915492..000000000 --- a/game/server/AI_Interest_Target.cpp +++ /dev/null @@ -1,139 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Hooks and classes for the support of humanoid NPCs with -// groovy facial animation capabilities, aka, "Actors" -// -//=============================================================================// - - -#include "cbase.h" -#include "AI_Interest_Target.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -bool CAI_InterestTarget_t::IsThis( CBaseEntity *pThis ) -{ - return (pThis == m_hTarget); -}; - -const Vector &CAI_InterestTarget_t::GetPosition( void ) -{ - if (m_eType == LOOKAT_ENTITY && m_hTarget != NULL) - { - m_vecPosition = m_hTarget->EyePosition(); - } - return m_vecPosition; -}; - -bool CAI_InterestTarget_t::IsActive( void ) -{ - if (m_flEndTime < gpGlobals->curtime) return false; - if (m_eType == LOOKAT_ENTITY && m_hTarget == NULL) return false; - return true; -}; - -float CAI_InterestTarget_t::Interest( void ) -{ - float t = (gpGlobals->curtime - m_flStartTime) / (m_flEndTime - m_flStartTime); - - if (t < 0.0f || t > 1.0f) - return 0.0f; - - if (m_flRamp && t < 1 - m_flRamp) - { - //t = t / m_flRamp; - t = 1.0 - ExponentialDecay( 0.2, m_flRamp, t ); - //t = 1.0 - ExponentialDecay( 0.01, 1 - m_flRamp, t ); - } - else if (t > 1.0f - m_flRamp) - { - t = (1.0 - t) / m_flRamp; - t = 3.0f * t * t - 2.0f * t * t * t; - } - else - { - t = 1.0f; - } - // ramp - t *= m_flInterest; - - return t; -} - - -void CAI_InterestTarget::Add( CBaseEntity *pTarget, float flImportance, float flDuration, float flRamp ) -{ - int i; - - for (i = 0; i < Count(); i++) - { - CAI_InterestTarget_t &target = Element( i ); - - if (target.m_hTarget == pTarget && target.m_flRamp == 0) - { - if (target.m_flStartTime == gpGlobals->curtime) - { - flImportance = MAX( flImportance, target.m_flInterest ); - } - Remove( i ); - break; - } - } - - Add( CAI_InterestTarget_t::LOOKAT_ENTITY, pTarget, Vector( 0, 0, 0 ), flImportance, flDuration, flRamp ); -} - -void CAI_InterestTarget::Add( const Vector &vecPosition, float flImportance, float flDuration, float flRamp ) -{ - int i; - - for (i = 0; i < Count(); i++) - { - CAI_InterestTarget_t &target = Element( i ); - - if (target.m_vecPosition == vecPosition) - { - Remove( i ); - break; - } - } - - Add( CAI_InterestTarget_t::LOOKAT_POSITION, NULL, vecPosition, flImportance, flDuration, flRamp ); -} - -void CAI_InterestTarget::Add( CBaseEntity *pTarget, const Vector &vecPosition, float flImportance, float flDuration, float flRamp ) -{ - int i; - - for (i = 0; i < Count(); i++) - { - CAI_InterestTarget_t &target = Element( i ); - - if (target.m_hTarget == pTarget) - { - if (target.m_flStartTime == gpGlobals->curtime) - { - flImportance = MAX( flImportance, target.m_flInterest ); - } - Remove( i ); - break; - } - } - - Add( CAI_InterestTarget_t::LOOKAT_BOTH, pTarget, vecPosition, flImportance, flDuration, flRamp ); -} - -void CAI_InterestTarget::Add( CAI_InterestTarget_t::CAI_InterestTarget_e type, CBaseEntity *pTarget, const Vector &vecPosition, float flImportance, float flDuration, float flRamp ) -{ - int i = AddToTail(); - CAI_InterestTarget_t &target = Element( i ); - - target.m_eType = type; - target.m_hTarget = pTarget; - target.m_vecPosition = vecPosition; - target.m_flInterest = flImportance; - target.m_flStartTime = gpGlobals->curtime; - target.m_flEndTime = gpGlobals->curtime + flDuration; - target.m_flRamp = flRamp / flDuration; -} diff --git a/game/server/AI_Interest_Target.h b/game/server/AI_Interest_Target.h deleted file mode 100644 index 1d3c57a13..000000000 --- a/game/server/AI_Interest_Target.h +++ /dev/null @@ -1,88 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Hooks and classes for the support of humanoid NPCs with -// groovy facial animation capabilities, aka, "Actors" -// -//=============================================================================// - -#ifndef AI_INTEREST_TARGET_H -#define AI_INTEREST_TARGET_H - -#if defined( _WIN32 ) -#pragma once -#endif - - -//----------------------------------------------------------------------------- -// CAI_BaseActor -// -// Purpose: The base class for all facially expressive NPCS. -// -//----------------------------------------------------------------------------- - -class CAI_InterestTarget_t -{ -public: - enum CAI_InterestTarget_e - { - LOOKAT_ENTITY = 0, - LOOKAT_POSITION, - LOOKAT_BOTH - }; - -public: - bool IsThis( CBaseEntity *pThis ); - const Vector &GetPosition( void ); - bool IsActive( void ); - float Interest( void ); - -public: - CAI_InterestTarget_e m_eType; // ???? - - EHANDLE m_hTarget; - Vector m_vecPosition; - float m_flStartTime; - float m_flEndTime; - float m_flRamp; - float m_flInterest; - - DECLARE_SIMPLE_DATADESC(); -}; - - -class CAI_InterestTarget : public CUtlVector -{ -public: - void Add( CBaseEntity *pTarget, float flImportance, float flDuration, float flRamp ); - void Add( const Vector &vecPosition, float flImportance, float flDuration, float flRamp ); - void Add( CBaseEntity *pTarget, const Vector &vecPosition, float flImportance, float flDuration, float flRamp ); - int Find( CBaseEntity *pTarget ) - { - int i; - for ( i = 0; i < Count(); i++) - { - if (pTarget == (*this)[i].m_hTarget) - return i; - } - return InvalidIndex(); - } - - void Cleanup( void ) - { - int i; - for (i = Count() - 1; i >= 0; i--) - { - if (!Element(i).IsActive()) - { - Remove( i ); - } - } - }; - -private: - void Add( CAI_InterestTarget_t::CAI_InterestTarget_e type, CBaseEntity *pTarget, const Vector &vecPosition, float flImportance, float flDuration, float flRamp ); -}; - - -//----------------------------------------------------------------------------- -#endif // AI_INTEREST_TARGET_H diff --git a/game/server/AI_ResponseSystem.cpp b/game/server/AI_ResponseSystem.cpp deleted file mode 100644 index 725dd6573..000000000 --- a/game/server/AI_ResponseSystem.cpp +++ /dev/null @@ -1,3401 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - - -#include "cbase.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" -#include "AI_ResponseSystem.h" -#include "igamesystem.h" -#include "AI_Criteria.h" -#include -#include "filesystem.h" -#include "utldict.h" -#include "ai_speech.h" -#include "tier0/icommandline.h" -#include -#include "sceneentity.h" -#include "isaverestore.h" -#include "utlbuffer.h" -#include "stringpool.h" -#include "fmtstr.h" -#include "multiplay_gamerules.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar rr_debugresponses( "rr_debugresponses", "0", FCVAR_NONE, "Show verbose matching output (1 for simple, 2 for rule scoring). If set to 3, it will only show response success/failure for npc_selected NPCs." ); -ConVar rr_debugrule( "rr_debugrule", "", FCVAR_NONE, "If set to the name of the rule, that rule's score will be shown whenever a concept is passed into the response rules system."); -ConVar rr_dumpresponses( "rr_dumpresponses", "0", FCVAR_NONE, "Dump all response_rules.txt and rules (requires restart)" ); - -static CUtlSymbolTable g_RS; - -inline static char *CopyString( const char *in ) -{ - if ( !in ) - return NULL; - - int len = Q_strlen( in ); - char *out = new char[ len + 1 ]; - Q_memcpy( out, in, len ); - out[ len ] = 0; - return out; -} - -#pragma pack(1) -class Matcher -{ -public: - Matcher() - { - valid = false; - isnumeric = false; - notequal = false; - usemin = false; - minequals = false; - usemax = false; - maxequals = false; - maxval = 0.0f; - minval = 0.0f; - - token = UTL_INVAL_SYMBOL; - rawtoken = UTL_INVAL_SYMBOL; - } - - void Describe( void ) - { - if ( !valid ) - { - DevMsg( " invalid!\n" ); - return; - } - char sz[ 128 ]; - - sz[ 0] = 0; - int minmaxcount = 0; - if ( usemin ) - { - Q_snprintf( sz, sizeof( sz ), ">%s%.3f", minequals ? "=" : "", minval ); - minmaxcount++; - } - if ( usemax ) - { - char sz2[ 128 ]; - Q_snprintf( sz2, sizeof( sz2 ), "<%s%.3f", maxequals ? "=" : "", maxval ); - - if ( minmaxcount > 0 ) - { - Q_strncat( sz, " and ", sizeof( sz ), COPY_ALL_CHARACTERS ); - } - Q_strncat( sz, sz2, sizeof( sz ), COPY_ALL_CHARACTERS ); - minmaxcount++; - } - - if ( minmaxcount >= 1 ) - { - DevMsg( " matcher: %s\n", sz ); - return; - } - - if ( notequal ) - { - DevMsg( " matcher: !=%s\n", GetToken() ); - return; - } - - DevMsg( " matcher: ==%s\n", GetToken() ); - } - - float maxval; - float minval; - - bool valid : 1; //1 - bool isnumeric : 1; //2 - bool notequal : 1; //3 - bool usemin : 1; //4 - bool minequals : 1; //5 - bool usemax : 1; //6 - bool maxequals : 1; //7 - - void SetToken( char const *s ) - { - token = g_RS.AddString( s ); - } - - char const *GetToken() - { - if ( token.IsValid() ) - { - return g_RS.String( token ); - } - return ""; - } - void SetRaw( char const *raw ) - { - rawtoken = g_RS.AddString( raw ); - } - char const *GetRaw() - { - if ( rawtoken.IsValid() ) - { - return g_RS.String( rawtoken ); - } - return ""; - } - -private: - CUtlSymbol token; - CUtlSymbol rawtoken; -}; - -struct Response -{ - DECLARE_SIMPLE_DATADESC(); - - Response() - { - type = RESPONSE_NONE; - value = NULL; - weight.SetFloat( 1.0f ); - depletioncount = 0; - first = false; - last = false; - } - - Response( const Response& src ) - { - weight = src.weight; - type = src.type; - value = CopyString( src.value ); - depletioncount = src.depletioncount; - first = src.first; - last = src.last; - } - - Response& operator =( const Response& src ) - { - if ( this == &src ) - return *this; - weight = src.weight; - type = src.type; - value = CopyString( src.value ); - depletioncount = src.depletioncount; - first = src.first; - last = src.last; - return *this; - } - - ~Response() - { - delete[] value; - } - - ResponseType_t GetType() { return (ResponseType_t)type; } - - char *value; // fixed up value spot // 4 - float16 weight; // 6 - - byte depletioncount; // 7 - byte type : 6; // 8 - byte first : 1; // - byte last : 1; // -}; - -struct ResponseGroup -{ - DECLARE_SIMPLE_DATADESC(); - - ResponseGroup() - { - // By default visit all nodes before repeating - m_bSequential = false; - m_bNoRepeat = false; - m_bEnabled = true; - m_nCurrentIndex = 0; - m_bDepleteBeforeRepeat = true; - m_nDepletionCount = 1; - m_bHasFirst = false; - m_bHasLast = false; - } - - ResponseGroup( const ResponseGroup& src ) - { - int c = src.group.Count(); - for ( int i = 0; i < c; i++ ) - { - group.AddToTail( src.group[ i ] ); - } - - rp = src.rp; - m_bDepleteBeforeRepeat = src.m_bDepleteBeforeRepeat; - m_nDepletionCount = src.m_nDepletionCount; - m_bHasFirst = src.m_bHasFirst; - m_bHasLast = src.m_bHasLast; - m_bSequential = src.m_bSequential; - m_bNoRepeat = src.m_bNoRepeat; - m_bEnabled = src.m_bEnabled; - m_nCurrentIndex = src.m_nCurrentIndex; - } - - ResponseGroup& operator=( const ResponseGroup& src ) - { - if ( this == &src ) - return *this; - int c = src.group.Count(); - for ( int i = 0; i < c; i++ ) - { - group.AddToTail( src.group[ i ] ); - } - - rp = src.rp; - m_bDepleteBeforeRepeat = src.m_bDepleteBeforeRepeat; - m_nDepletionCount = src.m_nDepletionCount; - m_bHasFirst = src.m_bHasFirst; - m_bHasLast = src.m_bHasLast; - m_bSequential = src.m_bSequential; - m_bNoRepeat = src.m_bNoRepeat; - m_bEnabled = src.m_bEnabled; - m_nCurrentIndex = src.m_nCurrentIndex; - return *this; - } - - bool HasUndepletedChoices() const - { - if ( !m_bDepleteBeforeRepeat ) - return true; - - int c = group.Count(); - for ( int i = 0; i < c; i++ ) - { - if ( group[ i ].depletioncount != m_nDepletionCount ) - return true; - } - - return false; - } - - void MarkResponseUsed( int idx ) - { - if ( !m_bDepleteBeforeRepeat ) - return; - - if ( idx < 0 || idx >= group.Count() ) - { - Assert( 0 ); - return; - } - - group[ idx ].depletioncount = m_nDepletionCount; - } - - void ResetDepletionCount() - { - if ( !m_bDepleteBeforeRepeat ) - return; - ++m_nDepletionCount; - } - - void Reset() - { - ResetDepletionCount(); - SetEnabled( true ); - SetCurrentIndex( 0 ); - m_nDepletionCount = 1; - - for ( int i = 0; i < group.Count(); ++i ) - { - group[ i ].depletioncount = 0; - } - } - - bool HasUndepletedFirst( int& index ) - { - index = -1; - - if ( !m_bDepleteBeforeRepeat ) - return false; - - int c = group.Count(); - for ( int i = 0; i < c; i++ ) - { - Response *r = &group[ i ]; - - if ( ( r->depletioncount != m_nDepletionCount ) && r->first ) - { - index = i; - return true; - } - } - - return false; - } - - bool HasUndepletedLast( int& index ) - { - index = -1; - - if ( !m_bDepleteBeforeRepeat ) - return false; - - int c = group.Count(); - for ( int i = 0; i < c; i++ ) - { - Response *r = &group[ i ]; - - if ( ( r->depletioncount != m_nDepletionCount ) && r->last ) - { - index = i; - return true; - } - } - - return false; - } - - bool ShouldCheckRepeats() const { return m_bDepleteBeforeRepeat; } - int GetDepletionCount() const { return m_nDepletionCount; } - - bool IsSequential() const { return m_bSequential; } - void SetSequential( bool seq ) { m_bSequential = seq; } - - bool IsNoRepeat() const { return m_bNoRepeat; } - void SetNoRepeat( bool norepeat ) { m_bNoRepeat = norepeat; } - - bool IsEnabled() const { return m_bEnabled; } - void SetEnabled( bool enabled ) { m_bEnabled = enabled; } - - int GetCurrentIndex() const { return m_nCurrentIndex; } - void SetCurrentIndex( byte idx ) { m_nCurrentIndex = idx; } - - CUtlVector< Response > group; - - AI_ResponseParams rp; - - bool m_bEnabled; - - byte m_nCurrentIndex; - // Invalidation counter - byte m_nDepletionCount; - - // Use all slots before repeating any - bool m_bDepleteBeforeRepeat : 1; - bool m_bHasFirst : 1; - bool m_bHasLast : 1; - bool m_bSequential : 1; - bool m_bNoRepeat : 1; - -}; - -struct Criteria -{ - Criteria() - { - name = NULL; - value = NULL; - weight.SetFloat( 1.0f ); - required = false; - } - Criteria& operator =(const Criteria& src ) - { - if ( this == &src ) - return *this; - - name = CopyString( src.name ); - value = CopyString( src.value ); - weight = src.weight; - required = src.required; - - matcher = src.matcher; - - int c = src.subcriteria.Count(); - for ( int i = 0; i < c; i++ ) - { - subcriteria.AddToTail( src.subcriteria[ i ] ); - } - - return *this; - } - Criteria(const Criteria& src ) - { - name = CopyString( src.name ); - value = CopyString( src.value ); - weight = src.weight; - required = src.required; - - matcher = src.matcher; - - int c = src.subcriteria.Count(); - for ( int i = 0; i < c; i++ ) - { - subcriteria.AddToTail( src.subcriteria[ i ] ); - } - } - ~Criteria() - { - delete[] name; - delete[] value; - } - - bool IsSubCriteriaType() const - { - return ( subcriteria.Count() > 0 ) ? true : false; - } - - char *name; - char *value; - float16 weight; - bool required; - - Matcher matcher; - - // Indices into sub criteria - CUtlVector< unsigned short > subcriteria; -}; - -struct Rule -{ - Rule() - { - m_bMatchOnce = false; - m_bEnabled = true; - m_szContext = NULL; - m_bApplyContextToWorld = false; - } - - Rule& operator =( const Rule& src ) - { - if ( this == &src ) - return *this; - - int i; - int c; - - c = src.m_Criteria.Count(); - for ( i = 0; i < c; i++ ) - { - m_Criteria.AddToTail( src.m_Criteria[ i ] ); - } - - c = src.m_Responses.Count(); - for ( i = 0; i < c; i++ ) - { - m_Responses.AddToTail( src.m_Responses[ i ] ); - } - - SetContext( src.m_szContext ); - m_bMatchOnce = src.m_bMatchOnce; - m_bEnabled = src.m_bEnabled; - m_bApplyContextToWorld = src.m_bApplyContextToWorld; - return *this; - } - - Rule( const Rule& src ) - { - int i; - int c; - - c = src.m_Criteria.Count(); - for ( i = 0; i < c; i++ ) - { - m_Criteria.AddToTail( src.m_Criteria[ i ] ); - } - - c = src.m_Responses.Count(); - for ( i = 0; i < c; i++ ) - { - m_Responses.AddToTail( src.m_Responses[ i ] ); - } - - SetContext( src.m_szContext ); - m_bMatchOnce = src.m_bMatchOnce; - m_bEnabled = src.m_bEnabled; - m_bApplyContextToWorld = src.m_bApplyContextToWorld; - } - - ~Rule() - { - delete[] m_szContext; - } - - void SetContext( const char *context ) - { - delete[] m_szContext; - m_szContext = CopyString( context ); - } - - const char *GetContext( void ) const { return m_szContext; } - - bool IsEnabled() const { return m_bEnabled; } - void Disable() { m_bEnabled = false; } - bool IsMatchOnce() const { return m_bMatchOnce; } - bool IsApplyContextToWorld() const { return m_bApplyContextToWorld; } - - // Indices into underlying criteria and response dictionaries - CUtlVector< unsigned short > m_Criteria; - CUtlVector< unsigned short> m_Responses; - - char *m_szContext; - bool m_bApplyContextToWorld : 1; - - bool m_bMatchOnce : 1; - bool m_bEnabled : 1; -}; -#pragma pack() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -abstract_class CResponseSystem : public IResponseSystem -{ -public: - CResponseSystem(); - ~CResponseSystem(); - - // IResponseSystem - virtual bool FindBestResponse( const AI_CriteriaSet& set, AI_Response& response, IResponseFilter *pFilter = NULL ); - virtual void GetAllResponses( CUtlVector *pResponses ); - - virtual void Release() = 0; - - virtual void DumpRules(); - - virtual void Precache(); - - virtual void PrecacheResponses( bool bEnable ) - { - m_bPrecache = bEnable; - } - - bool ShouldPrecache() { return m_bPrecache; } - bool IsCustomManagable() { return m_bCustomManagable; } - - void Clear(); - - void DumpDictionary( const char *pszName ); - -protected: - - virtual const char *GetScriptFile( void ) = 0; - void LoadRuleSet( const char *setname ); - - void ResetResponseGroups(); - - float LookForCriteria( const AI_CriteriaSet &criteriaSet, int iCriteria ); - float RecursiveLookForCriteria( const AI_CriteriaSet &criteriaSet, Criteria *pParent ); - -public: - - void CopyRuleFrom( Rule *pSrcRule, int iRule, CResponseSystem *pCustomSystem ); - void CopyCriteriaFrom( Rule *pSrcRule, Rule *pDstRule, CResponseSystem *pCustomSystem ); - void CopyResponsesFrom( Rule *pSrcRule, Rule *pDstRule, CResponseSystem *pCustomSystem ); - void CopyEnumerationsFrom( CResponseSystem *pCustomSystem ); - -//private: - - struct Enumeration - { - float value; - }; - - struct ResponseSearchResult - { - ResponseSearchResult() - { - group = NULL; - action = NULL; - } - - ResponseGroup *group; - Response *action; - }; - - inline bool ParseToken( void ) - { - if ( m_bUnget ) - { - m_bUnget = false; - return true; - } - if ( m_ScriptStack.Count() <= 0 ) - { - Assert( 0 ); - return false; - } - - m_ScriptStack[ 0 ].currenttoken = engine->ParseFile( m_ScriptStack[ 0 ].currenttoken, token, sizeof( token ) ); - m_ScriptStack[ 0 ].tokencount++; - return m_ScriptStack[ 0 ].currenttoken != NULL ? true : false; - } - - inline void Unget() - { - m_bUnget = true; - } - - inline bool TokenWaiting( void ) - { - if ( m_ScriptStack.Count() <= 0 ) - { - Assert( 0 ); - return false; - } - - const char *p = m_ScriptStack[ 0 ].currenttoken; - - if ( !p ) - { - Error( "AI_ResponseSystem: Unxpected TokenWaiting() with NULL buffer in %s", m_ScriptStack[ 0 ].name ); - return false; - } - - - while ( *p && *p!='\n') - { - // Special handler for // comment blocks - if ( *p == '/' && *(p+1) == '/' ) - return false; - - if ( !isspace( *p ) || isalnum( *p ) ) - return true; - - p++; - } - - return false; - } - - void ParseOneResponse( const char *responseGroupName, ResponseGroup& group ); - - void ParseInclude( CStringPool &includedFiles ); - void ParseResponse( void ); - void ParseCriterion( void ); - void ParseRule( void ); - void ParseEnumeration( void ); - - int ParseOneCriterion( const char *criterionName ); - - bool Compare( const char *setValue, Criteria *c, bool verbose = false ); - bool CompareUsingMatcher( const char *setValue, Matcher& m, bool verbose = false ); - void ComputeMatcher( Criteria *c, Matcher& matcher ); - void ResolveToken( Matcher& matcher, char *token, size_t bufsize, char const *rawtoken ); - float LookupEnumeration( const char *name, bool& found ); - - int FindBestMatchingRule( const AI_CriteriaSet& set, bool verbose ); - - float ScoreCriteriaAgainstRule( const AI_CriteriaSet& set, int irule, bool verbose = false ); - float RecursiveScoreSubcriteriaAgainstRule( const AI_CriteriaSet& set, Criteria *parent, bool& exclude, bool verbose /*=false*/ ); - float ScoreCriteriaAgainstRuleCriteria( const AI_CriteriaSet& set, int icriterion, bool& exclude, bool verbose = false ); - bool GetBestResponse( ResponseSearchResult& result, Rule *rule, bool verbose = false, IResponseFilter *pFilter = NULL ); - bool ResolveResponse( ResponseSearchResult& result, int depth, const char *name, bool verbose = false, IResponseFilter *pFilter = NULL ); - int SelectWeightedResponseFromResponseGroup( ResponseGroup *g, IResponseFilter *pFilter ); - void DescribeResponseGroup( ResponseGroup *group, int selected, int depth ); - void DebugPrint( int depth, const char *fmt, ... ); - - void LoadFromBuffer( const char *scriptfile, const char *buffer, CStringPool &includedFiles ); - - void GetCurrentScript( char *buf, size_t buflen ); - int GetCurrentToken() const; - void SetCurrentScript( const char *script ); - bool IsRootCommand(); - - void PushScript( const char *scriptfile, unsigned char *buffer ); - void PopScript(void); - - void ResponseWarning( const char *fmt, ... ); - - CUtlDict< ResponseGroup, short > m_Responses; - CUtlDict< Criteria, short > m_Criteria; - CUtlDict< Rule, short > m_Rules; - CUtlDict< Enumeration, short > m_Enumerations; - - char token[ 1204 ]; - - bool m_bUnget; - bool m_bPrecache; - - bool m_bCustomManagable; - - struct ScriptEntry - { - unsigned char *buffer; - FileNameHandle_t name; - const char *currenttoken; - int tokencount; - }; - - CUtlVector< ScriptEntry > m_ScriptStack; - - friend class CDefaultResponseSystemSaveRestoreBlockHandler; - friend class CResponseSystemSaveRestoreOps; -}; - -BEGIN_SIMPLE_DATADESC( Response ) - // DEFINE_FIELD( type, FIELD_INTEGER ), - // DEFINE_ARRAY( value, FIELD_CHARACTER ), - // DEFINE_FIELD( weight, FIELD_FLOAT ), - DEFINE_FIELD( depletioncount, FIELD_CHARACTER ), - // DEFINE_FIELD( first, FIELD_BOOLEAN ), - // DEFINE_FIELD( last, FIELD_BOOLEAN ), -END_DATADESC() - -BEGIN_SIMPLE_DATADESC( ResponseGroup ) - // DEFINE_FIELD( group, FIELD_UTLVECTOR ), - // DEFINE_FIELD( rp, FIELD_EMBEDDED ), - // DEFINE_FIELD( m_bDepleteBeforeRepeat, FIELD_BOOLEAN ), - DEFINE_FIELD( m_nDepletionCount, FIELD_CHARACTER ), - // DEFINE_FIELD( m_bHasFirst, FIELD_BOOLEAN ), - // DEFINE_FIELD( m_bHasLast, FIELD_BOOLEAN ), - // DEFINE_FIELD( m_bSequential, FIELD_BOOLEAN ), - // DEFINE_FIELD( m_bNoRepeat, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ), - DEFINE_FIELD( m_nCurrentIndex, FIELD_CHARACTER ), -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CResponseSystem::CResponseSystem() -{ - token[0] = 0; - m_bUnget = false; - m_bPrecache = true; - m_bCustomManagable = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CResponseSystem::~CResponseSystem() -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : char const -//----------------------------------------------------------------------------- -void CResponseSystem::GetCurrentScript( char *buf, size_t buflen ) -{ - Assert( buf ); - buf[ 0 ] = 0; - if ( m_ScriptStack.Count() <= 0 ) - return; - - if ( filesystem->String( m_ScriptStack[ 0 ].name, buf, buflen ) ) - { - return; - } - buf[ 0 ] = 0; -} - -void CResponseSystem::PushScript( const char *scriptfile, unsigned char *buffer ) -{ - ScriptEntry e; - e.name = filesystem->FindOrAddFileName( scriptfile ); - e.buffer = buffer; - e.currenttoken = (char *)e.buffer; - e.tokencount = 0; - m_ScriptStack.AddToHead( e ); -} - -void CResponseSystem::PopScript(void) -{ - Assert( m_ScriptStack.Count() >= 1 ); - if ( m_ScriptStack.Count() <= 0 ) - return; - - m_ScriptStack.Remove( 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CResponseSystem::Clear() -{ - m_Responses.RemoveAll(); - m_Criteria.RemoveAll(); - m_Rules.RemoveAll(); - m_Enumerations.RemoveAll(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -// found - -// Output : float -//----------------------------------------------------------------------------- -float CResponseSystem::LookupEnumeration( const char *name, bool& found ) -{ - int idx = m_Enumerations.Find( name ); - if ( idx == m_Enumerations.InvalidIndex() ) - { - found = false; - return 0.0f; - } - - - found = true; - return m_Enumerations[ idx ].value; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : matcher - -//----------------------------------------------------------------------------- -void CResponseSystem::ResolveToken( Matcher& matcher, char *token, size_t bufsize, char const *rawtoken ) -{ - if ( rawtoken[0] != '[' ) - { - Q_strncpy( token, rawtoken, bufsize ); - return; - } - - // Now lookup enumeration - bool found = false; - float f = LookupEnumeration( rawtoken, found ); - if ( !found ) - { - Q_strncpy( token, rawtoken, bufsize ); - ResponseWarning( "No such enumeration '%s'\n", token ); - return; - } - - Q_snprintf( token, bufsize, "%f", f ); -} - - -static bool AppearsToBeANumber( char const *token ) -{ - if ( atof( token ) != 0.0f ) - return true; - - char const *p = token; - while ( *p ) - { - if ( *p != '0' ) - return false; - - p++; - } - - return true; -} - -void CResponseSystem::ComputeMatcher( Criteria *c, Matcher& matcher ) -{ - const char *s = c->value; - if ( !s ) - { - matcher.valid = false; - return; - } - - const char *in = s; - - char token[ 128 ]; - char rawtoken[ 128 ]; - - token[ 0 ] = 0; - rawtoken[ 0 ] = 0; - - int n = 0; - - bool gt = false; - bool lt = false; - bool eq = false; - bool nt = false; - - bool done = false; - while ( !done ) - { - switch( *in ) - { - case '>': - { - gt = true; - Assert( !lt ); // Can't be both - } - break; - case '<': - { - lt = true; - Assert( !gt ); // Can't be both - } - break; - case '=': - { - eq = true; - } - break; - case ',': - case '\0': - { - rawtoken[ n ] = 0; - n = 0; - - // Convert raw token to real token in case token is an enumerated type specifier - ResolveToken( matcher, token, sizeof( token ), rawtoken ); - - // Fill in first data set - if ( gt ) - { - matcher.usemin = true; - matcher.minequals = eq; - matcher.minval = (float)atof( token ); - - matcher.isnumeric = true; - } - else if ( lt ) - { - matcher.usemax = true; - matcher.maxequals = eq; - matcher.maxval = (float)atof( token ); - - matcher.isnumeric = true; - } - else - { - if ( *in == ',' ) - { - // If there's a comma, this better have been a less than or a gt key - Assert( 0 ); - } - - matcher.notequal = nt; - - matcher.isnumeric = AppearsToBeANumber( token ); - } - - gt = lt = eq = nt = false; - - if ( !(*in) ) - { - done = true; - } - } - break; - case '!': - nt = true; - break; - default: - rawtoken[ n++ ] = *in; - break; - } - - in++; - } - - matcher.SetToken( token ); - matcher.SetRaw( rawtoken ); - matcher.valid = true; -} - -bool CResponseSystem::CompareUsingMatcher( const char *setValue, Matcher& m, bool verbose /*=false*/ ) -{ - if ( !m.valid ) - return false; - - float v = (float)atof( setValue ); - if ( setValue[0] == '[' ) - { - bool found = false; - v = LookupEnumeration( setValue, found ); - } - - int minmaxcount = 0; - - if ( m.usemin ) - { - if ( m.minequals ) - { - if ( v < m.minval ) - return false; - } - else - { - if ( v <= m.minval ) - return false; - } - - ++minmaxcount; - } - - if ( m.usemax ) - { - if ( m.maxequals ) - { - if ( v > m.maxval ) - return false; - } - else - { - if ( v >= m.maxval ) - return false; - } - - ++minmaxcount; - } - - // Had one or both criteria and met them - if ( minmaxcount >= 1 ) - { - return true; - } - - if ( m.notequal ) - { - if ( m.isnumeric ) - { - if ( v == (float)atof( m.GetToken() ) ) - return false; - } - else - { - if ( !Q_stricmp( setValue, m.GetToken() ) ) - return false; - } - - return true; - } - - if ( m.isnumeric ) - { - // If the setValue is "", the NPC doesn't have the key at all, - // in which case we shouldn't match "0". - if ( !setValue || !setValue[0] ) - return false; - - return v == (float)atof( m.GetToken() ); - } - - return !Q_stricmp( setValue, m.GetToken() ) ? true : false; -} - -bool CResponseSystem::Compare( const char *setValue, Criteria *c, bool verbose /*= false*/ ) -{ - Assert( c ); - Assert( setValue ); - - bool bret = CompareUsingMatcher( setValue, c->matcher, verbose ); - - if ( verbose ) - { - DevMsg( "'%20s' vs. '%20s' = ", setValue, c->value ); - - { - //DevMsg( "\n" ); - //m.Describe(); - } - } - return bret; -} - -float CResponseSystem::RecursiveScoreSubcriteriaAgainstRule( const AI_CriteriaSet& set, Criteria *parent, bool& exclude, bool verbose /*=false*/ ) -{ - float score = 0.0f; - int subcount = parent->subcriteria.Count(); - for ( int i = 0; i < subcount; i++ ) - { - int icriterion = parent->subcriteria[ i ]; - - bool excludesubrule = false; - if (verbose) - { - DevMsg( "\n" ); - } - score += ScoreCriteriaAgainstRuleCriteria( set, icriterion, excludesubrule, verbose ); - } - - exclude = ( parent->required && score == 0.0f ) ? true : false; - - return score * parent->weight.GetFloat(); -} - -float CResponseSystem::RecursiveLookForCriteria( const AI_CriteriaSet &criteriaSet, Criteria *pParent ) -{ - float flScore = 0.0f; - int nSubCount = pParent->subcriteria.Count(); - for ( int iSub = 0; iSub < nSubCount; ++iSub ) - { - int iCriteria = pParent->subcriteria[iSub]; - flScore += LookForCriteria( criteriaSet, iCriteria ); - } - - return flScore; -} - -float CResponseSystem::LookForCriteria( const AI_CriteriaSet &criteriaSet, int iCriteria ) -{ - Criteria *pCriteria = &m_Criteria[iCriteria]; - if ( pCriteria->IsSubCriteriaType() ) - { - return RecursiveLookForCriteria( criteriaSet, pCriteria ); - } - - int iIndex = criteriaSet.FindCriterionIndex( pCriteria->name ); - if ( iIndex == -1 ) - return 0.0f; - - Assert( criteriaSet.GetValue( iIndex ) ); - if ( Q_stricmp( criteriaSet.GetValue( iIndex ), pCriteria->value ) ) - return 0.0f; - - return 1.0f; -} - -float CResponseSystem::ScoreCriteriaAgainstRuleCriteria( const AI_CriteriaSet& set, int icriterion, bool& exclude, bool verbose /*=false*/ ) -{ - Criteria *c = &m_Criteria[ icriterion ]; - - if ( c->IsSubCriteriaType() ) - { - return RecursiveScoreSubcriteriaAgainstRule( set, c, exclude, verbose ); - } - - if ( verbose ) - { - DevMsg( " criterion '%25s':'%15s' ", m_Criteria.GetElementName( icriterion ), c->name ); - } - - exclude = false; - - float score = 0.0f; - - const char *actualValue = ""; - - int found = set.FindCriterionIndex( c->name ); - if ( found != -1 ) - { - actualValue = set.GetValue( found ); - if ( !actualValue ) - { - Assert( 0 ); - return score; - } - } - - Assert( actualValue ); - - if ( Compare( actualValue, c, verbose ) ) - { - float w = set.GetWeight( found ); - score = w * c->weight.GetFloat(); - - if ( verbose ) - { - DevMsg( "matched, weight %4.2f (s %4.2f x c %4.2f)", - score, w, c->weight.GetFloat() ); - } - } - else - { - if ( c->required ) - { - exclude = true; - if ( verbose ) - { - DevMsg( "failed (+exclude rule)" ); - } - } - else - { - if ( verbose ) - { - DevMsg( "failed" ); - } - } - } - - return score; -} - -float CResponseSystem::ScoreCriteriaAgainstRule( const AI_CriteriaSet& set, int irule, bool verbose /*=false*/ ) -{ - Rule *rule = &m_Rules[ irule ]; - float score = 0.0f; - - bool bBeingWatched = false; - - // See if we're trying to debug this rule - const char *pszText = rr_debugrule.GetString(); - if ( pszText && pszText[0] && !Q_stricmp( pszText, m_Rules.GetElementName( irule ) ) ) - { - bBeingWatched = true; - } - - if ( !rule->IsEnabled() ) - { - if ( bBeingWatched ) - { - DevMsg("Rule '%s' is disabled.\n" ); - } - return 0.0f; - } - - if ( bBeingWatched ) - { - verbose = true; - } - - if ( verbose ) - { - DevMsg( "Scoring rule '%s' (%i)\n{\n", m_Rules.GetElementName( irule ), irule+1 ); - } - - // Iterate set criteria - int count = rule->m_Criteria.Count(); - int i; - for ( i = 0; i < count; i++ ) - { - int icriterion = rule->m_Criteria[ i ]; - - bool exclude = false; - score += ScoreCriteriaAgainstRuleCriteria( set, icriterion, exclude, verbose ); - - if ( verbose ) - { - DevMsg( ", score %4.2f\n", score ); - } - - if ( exclude ) - { - score = 0.0f; - break; - } - } - - if ( verbose ) - { - DevMsg( "}\n" ); - } - - return score; -} - -void CResponseSystem::DebugPrint( int depth, const char *fmt, ... ) -{ - int indentchars = 3 * depth; - char *indent = (char *)_alloca( indentchars + 1); - indent[ indentchars ] = 0; - while ( --indentchars >= 0 ) - { - indent[ indentchars ] = ' '; - } - - // Dump text to debugging console. - va_list argptr; - char szText[1024]; - - va_start (argptr, fmt); - Q_vsnprintf (szText, sizeof( szText ), fmt, argptr); - va_end (argptr); - - DevMsg( "%s%s", indent, szText ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CResponseSystem::ResetResponseGroups() -{ - int i; - int c = m_Responses.Count(); - for ( i = 0; i < c; i++ ) - { - m_Responses[ i ].Reset(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *g - -// Output : int -//----------------------------------------------------------------------------- -int CResponseSystem::SelectWeightedResponseFromResponseGroup( ResponseGroup *g, IResponseFilter *pFilter ) -{ - int c = g->group.Count(); - if ( !c ) - { - Assert( !"Expecting response group with >= 1 elements" ); - return -1; - } - - int i; - - // Fake depletion of unavailable choices - CUtlVector fakedDepletes; - if ( pFilter && g->ShouldCheckRepeats() ) - { - for ( i = 0; i < c; i++ ) - { - Response *r = &g->group[ i ]; - if ( r->depletioncount != g->GetDepletionCount() && !pFilter->IsValidResponse( r->GetType(), r->value ) ) - { - fakedDepletes.AddToTail( i ); - g->MarkResponseUsed( i ); - } - } - } - - if ( !g->HasUndepletedChoices() ) - { - g->ResetDepletionCount(); - - if ( pFilter && g->ShouldCheckRepeats() ) - { - fakedDepletes.RemoveAll(); - for ( i = 0; i < c; i++ ) - { - Response *r = &g->group[ i ]; - if ( !pFilter->IsValidResponse( r->GetType(), r->value ) ) - { - fakedDepletes.AddToTail( i ); - g->MarkResponseUsed( i ); - } - } - } - - if ( !g->HasUndepletedChoices() ) - return -1; - - // Disable the group if we looped through all the way - if ( g->IsNoRepeat() ) - { - g->SetEnabled( false ); - return -1; - } - } - - bool checkrepeats = g->ShouldCheckRepeats(); - int depletioncount = g->GetDepletionCount(); - - float totalweight = 0.0f; - int slot = -1; - - if ( checkrepeats ) - { - int check= -1; - // Snag the first slot right away - if ( g->HasUndepletedFirst( check ) && check != -1 ) - { - slot = check; - } - - if ( slot == -1 && g->HasUndepletedLast( check ) && check != -1 ) - { - // If this is the only undepleted one, use it now - for ( i = 0; i < c; i++ ) - { - Response *r = &g->group[ i ]; - if ( checkrepeats && - ( r->depletioncount == depletioncount ) ) - { - continue; - } - - if ( r->last ) - { - Assert( i == check ); - continue; - } - - // There's still another undepleted entry - break; - } - - // No more undepleted so use the r->last slot - if ( i >= c ) - { - slot = check; - } - } - } - - if ( slot == -1 ) - { - for ( i = 0; i < c; i++ ) - { - Response *r = &g->group[ i ]; - if ( checkrepeats && - ( r->depletioncount == depletioncount ) ) - { - continue; - } - - // Always skip last entry here since we will deal with it above - if ( checkrepeats && r->last ) - continue; - - int prevSlot = slot; - - if ( !totalweight ) - { - slot = i; - } - - // Always assume very first slot will match - totalweight += r->weight.GetFloat(); - if ( !totalweight || random->RandomFloat(0,totalweight) < r->weight.GetFloat() ) - { - slot = i; - } - - if ( !checkrepeats && slot != prevSlot && pFilter && !pFilter->IsValidResponse( r->GetType(), r->value ) ) - { - slot = prevSlot; - totalweight -= r->weight.GetFloat(); - } - } - } - - if ( slot != -1 ) - g->MarkResponseUsed( slot ); - - // Revert fake depletion of unavailable choices - if ( pFilter && g->ShouldCheckRepeats() ) - { - for ( i = 0; i < fakedDepletes.Count(); i++ ) - { - g->group[ fakedDepletes[ i ] ].depletioncount = 0;; - } - } - - return slot; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : searchResult - -// depth - -// *name - -// verbose - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CResponseSystem::ResolveResponse( ResponseSearchResult& searchResult, int depth, const char *name, bool verbose /*= false*/, IResponseFilter *pFilter ) -{ - int responseIndex = m_Responses.Find( name ); - if ( responseIndex == m_Responses.InvalidIndex() ) - return false; - - ResponseGroup *g = &m_Responses[ responseIndex ]; - // Group has been disabled - if ( !g->IsEnabled() ) - return false; - - int c = g->group.Count(); - if ( !c ) - return false; - - int idx = 0; - - if ( g->IsSequential() ) - { - // See if next index is valid - int initialIndex = g->GetCurrentIndex(); - bool bFoundValid = false; - - do - { - idx = g->GetCurrentIndex(); - g->SetCurrentIndex( idx + 1 ); - if ( idx >= c ) - { - if ( g->IsNoRepeat() ) - { - g->SetEnabled( false ); - return false; - } - idx = 0; - g->SetCurrentIndex( 0 ); - } - - if ( !pFilter || pFilter->IsValidResponse( g->group[idx].GetType(), g->group[idx].value ) ) - { - bFoundValid = true; - break; - } - - } while ( g->GetCurrentIndex() != initialIndex ); - - if ( !bFoundValid ) - return false; - } - else - { - idx = SelectWeightedResponseFromResponseGroup( g, pFilter ); - if ( idx < 0 ) - return false; - } - - if ( verbose ) - { - DebugPrint( depth, "%s\n", m_Responses.GetElementName( responseIndex ) ); - DebugPrint( depth, "{\n" ); - DescribeResponseGroup( g, idx, depth ); - } - - bool bret = true; - - Response *result = &g->group[ idx ]; - if ( result->type == RESPONSE_RESPONSE ) - { - // Recurse - bret = ResolveResponse( searchResult, depth + 1, result->value, verbose, pFilter ); - } - else - { - searchResult.action = result; - searchResult.group = g; - } - - if( verbose ) - { - DebugPrint( depth, "}\n" ); - } - - return bret; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *group - -// selected - -// depth - -//----------------------------------------------------------------------------- -void CResponseSystem::DescribeResponseGroup( ResponseGroup *group, int selected, int depth ) -{ - int c = group->group.Count(); - - for ( int i = 0; i < c ; i++ ) - { - Response *r = &group->group[ i ]; - DebugPrint( depth + 1, "%s%20s : %40s %5.3f\n", - i == selected ? "-> " : " ", - AI_Response::DescribeResponse( r->GetType() ), - r->value, - r->weight.GetFloat() ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *rule - -// Output : CResponseSystem::Response -//----------------------------------------------------------------------------- -bool CResponseSystem::GetBestResponse( ResponseSearchResult& searchResult, Rule *rule, bool verbose /*=false*/, IResponseFilter *pFilter ) -{ - int c = rule->m_Responses.Count(); - if ( !c ) - return false; - - int index = random->RandomInt( 0, c - 1 ); - int groupIndex = rule->m_Responses[ index ]; - - ResponseGroup *g = &m_Responses[ groupIndex ]; - - // Group has been disabled - if ( !g->IsEnabled() ) - return false; - - int count = g->group.Count(); - if ( !count ) - return false; - - int responseIndex = 0; - - if ( g->IsSequential() ) - { - // See if next index is valid - int initialIndex = g->GetCurrentIndex(); - bool bFoundValid = false; - - do - { - responseIndex = g->GetCurrentIndex(); - g->SetCurrentIndex( responseIndex + 1 ); - if ( responseIndex >= count ) - { - if ( g->IsNoRepeat() ) - { - g->SetEnabled( false ); - return false; - } - responseIndex = 0; - g->SetCurrentIndex( 0 ); - } - - if ( !pFilter || pFilter->IsValidResponse( g->group[responseIndex].GetType(), g->group[responseIndex].value ) ) - { - bFoundValid = true; - break; - } - - } while ( g->GetCurrentIndex() != initialIndex ); - - if ( !bFoundValid ) - return false; - } - else - { - responseIndex = SelectWeightedResponseFromResponseGroup( g, pFilter ); - if ( responseIndex < 0 ) - return false; - } - - - Response *r = &g->group[ responseIndex ]; - - int depth = 0; - - if ( verbose ) - { - DebugPrint( depth, "%s\n", m_Responses.GetElementName( groupIndex ) ); - DebugPrint( depth, "{\n" ); - - DescribeResponseGroup( g, responseIndex, depth ); - } - - bool bret = true; - - if ( r->type == RESPONSE_RESPONSE ) - { - bret = ResolveResponse( searchResult, depth + 1, r->value, verbose, pFilter ); - } - else - { - searchResult.action = r; - searchResult.group = g; - } - - if ( verbose ) - { - DebugPrint( depth, "}\n" ); - } - - return bret; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : set - -// verbose - -// Output : int -//----------------------------------------------------------------------------- -int CResponseSystem::FindBestMatchingRule( const AI_CriteriaSet& set, bool verbose ) -{ - CUtlVector< int > bestrules; - float bestscore = 0.001f; - - int c = m_Rules.Count(); - int i; - for ( i = 0; i < c; i++ ) - { - float score = ScoreCriteriaAgainstRule( set, i, verbose ); - // Check equals so that we keep track of all matching rules - if ( score >= bestscore ) - { - // Reset bucket - if( score != bestscore ) - { - bestscore = score; - bestrules.RemoveAll(); - } - - // Add to bucket - bestrules.AddToTail( i ); - } - } - - int bestCount = bestrules.Count(); - if ( bestCount <= 0 ) - return -1; - - if ( bestCount == 1 ) - return bestrules[ 0 ]; - - // Randomly pick one of the tied matching rules - int idx = random->RandomInt( 0, bestCount - 1 ); - if ( verbose ) - { - DevMsg( "Found %i matching rules, selecting slot %i\n", bestCount, idx ); - } - return bestrules[ idx ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : set - -// Output : AI_Response -//----------------------------------------------------------------------------- -bool CResponseSystem::FindBestResponse( const AI_CriteriaSet& set, AI_Response& response, IResponseFilter *pFilter ) -{ - bool valid = false; - - int iDbgResponse = rr_debugresponses.GetInt(); - bool showRules = ( iDbgResponse == 2 ); - bool showResult = ( iDbgResponse == 1 || iDbgResponse == 2 ); - - // Look for match. verbose mode used to be at level 2, but disabled because the writers don't actually care for that info. - int bestRule = FindBestMatchingRule( set, false ); - - ResponseType_t responseType = RESPONSE_NONE; - AI_ResponseParams rp; - - char ruleName[ 128 ]; - char responseName[ 128 ]; - const char *context; - bool bcontexttoworld; - ruleName[ 0 ] = 0; - responseName[ 0 ] = 0; - context = NULL; - bcontexttoworld = false; - if ( bestRule != -1 ) - { - Rule *r = &m_Rules[ bestRule ]; - - ResponseSearchResult result; - if ( GetBestResponse( result, r, showResult, pFilter ) ) - { - Q_strncpy( responseName, result.action->value, sizeof( responseName ) ); - responseType = result.action->GetType(); - rp = result.group->rp; - } - - Q_strncpy( ruleName, m_Rules.GetElementName( bestRule ), sizeof( ruleName ) ); - - // Disable the rule if it only allows for matching one time - if ( r->IsMatchOnce() ) - { - r->Disable(); - } - context = r->GetContext(); - bcontexttoworld = r->IsApplyContextToWorld(); - - valid = true; - } - - response.Init( responseType, responseName, set, rp, ruleName, context, bcontexttoworld ); - - if ( showResult ) - { - /* - // clipped -- chet doesn't really want this info - if ( valid ) - { - // Rescore the winner and dump to console - ScoreCriteriaAgainstRule( set, bestRule, true ); - } - */ - - - if ( valid || showRules ) - { - // Describe the response, too - response.Describe(); - } - } - - return valid; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CResponseSystem::GetAllResponses( CUtlVector *pResponses ) -{ - for ( int i = 0; i < (int)m_Responses.Count(); i++ ) - { - ResponseGroup &group = m_Responses[i]; - - for ( int j = 0; j < group.group.Count(); j++) - { - Response &response = group.group[j]; - if ( response.type != RESPONSE_RESPONSE ) - { - AI_Response *pResponse = new AI_Response; - pResponse->Init( response.GetType(), response.value, AI_CriteriaSet(), group.rp, NULL, NULL, false ); - pResponses->AddToTail(pResponse); - } - } - } -} - -static void TouchFile( char const *pchFileName ) -{ - filesystem->Size( pchFileName ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CResponseSystem::Precache() -{ - bool bTouchFiles = CommandLine()->FindParm( "-makereslists" ) != 0; - - // enumerate and mark all the scripts so we know they're referenced - for ( int i = 0; i < (int)m_Responses.Count(); i++ ) - { - ResponseGroup &group = m_Responses[i]; - - for ( int j = 0; j < group.group.Count(); j++) - { - Response &response = group.group[j]; - - switch ( response.type ) - { - default: - break; - case RESPONSE_SCENE: - { - // fixup $gender references - char file[_MAX_PATH]; - Q_strncpy( file, response.value, sizeof(file) ); - char *gender = strstr( file, "$gender" ); - if ( gender ) - { - // replace with male & female - const char *postGender = gender + strlen("$gender"); - *gender = 0; - char genderFile[_MAX_PATH]; - // male - Q_snprintf( genderFile, sizeof(genderFile), "%smale%s", file, postGender); - - PrecacheInstancedScene( genderFile ); - if ( bTouchFiles ) - { - TouchFile( genderFile ); - } - - Q_snprintf( genderFile, sizeof(genderFile), "%sfemale%s", file, postGender); - - PrecacheInstancedScene( genderFile ); - if ( bTouchFiles ) - { - TouchFile( genderFile ); - } - } - else - { - PrecacheInstancedScene( file ); - if ( bTouchFiles ) - { - TouchFile( file ); - } - } - } - break; - case RESPONSE_SPEAK: - { - CBaseEntity::PrecacheScriptSound( response.value ); - } - break; - } - } - } -} - -void CResponseSystem::ParseInclude( CStringPool &includedFiles ) -{ - char includefile[ 256 ]; - ParseToken(); - Q_snprintf( includefile, sizeof( includefile ), "scripts/%s", token ); - - // check if the file is already included - if ( includedFiles.Find( includefile ) != NULL ) - { - return; - } - - MEM_ALLOC_CREDIT(); - - // Try and load it - CUtlBuffer buf; - if ( !filesystem->ReadFile( includefile, "GAME", buf ) ) - { - DevMsg( "Unable to load #included script %s\n", includefile ); - return; - } - - LoadFromBuffer( includefile, (const char *)buf.PeekGet(), includedFiles ); -} - -void CResponseSystem::LoadFromBuffer( const char *scriptfile, const char *buffer, CStringPool &includedFiles ) -{ - includedFiles.Allocate( scriptfile ); - PushScript( scriptfile, (unsigned char * )buffer ); - - if( rr_dumpresponses.GetBool() ) - { - DevMsg("Reading: %s\n", scriptfile ); - } - - while ( 1 ) - { - ParseToken(); - if ( !token[0] ) - { - break; - } - - if ( !Q_stricmp( token, "#include" ) ) - { - ParseInclude( includedFiles ); - } - else if ( !Q_stricmp( token, "response" ) ) - { - ParseResponse(); - } - else if ( !Q_stricmp( token, "criterion" ) || - !Q_stricmp( token, "criteria" ) ) - { - ParseCriterion(); - } - else if ( !Q_stricmp( token, "rule" ) ) - { - ParseRule(); - } - else if ( !Q_stricmp( token, "enumeration" ) ) - { - ParseEnumeration(); - } - else - { - int byteoffset = m_ScriptStack[ 0 ].currenttoken - (const char *)m_ScriptStack[ 0 ].buffer; - - Error( "CResponseSystem::LoadFromBuffer: Unknown entry type '%s', expecting 'response', 'criterion', 'enumeration' or 'rules' in file %s(offset:%i)\n", - token, scriptfile, byteoffset ); - break; - } - } - - if ( m_ScriptStack.Count() == 1 ) - { - char cur[ 256 ]; - GetCurrentScript( cur, sizeof( cur ) ); - DevMsg( 1, "CResponseSystem: %s (%i rules, %i criteria, and %i responses)\n", - cur, m_Rules.Count(), m_Criteria.Count(), m_Responses.Count() ); - - if( rr_dumpresponses.GetBool() ) - { - DumpRules(); - } - } - - PopScript(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CResponseSystem::LoadRuleSet( const char *basescript ) -{ - int length = 0; - unsigned char *buffer = (unsigned char *)UTIL_LoadFileForMe( basescript, &length ); - if ( length <= 0 || !buffer ) - { - DevMsg( 1, "CResponseSystem: failed to load %s\n", basescript ); - return; - } - - CStringPool includedFiles; - - LoadFromBuffer( basescript, (const char *)buffer, includedFiles ); - - UTIL_FreeFile( buffer ); - - Assert( m_ScriptStack.Count() == 0 ); -} - -static ResponseType_t ComputeResponseType( const char *s ) -{ - if ( !Q_stricmp( s, "scene" ) ) - { - return RESPONSE_SCENE; - } - else if ( !Q_stricmp( s, "sentence" ) ) - { - return RESPONSE_SENTENCE; - } - else if ( !Q_stricmp( s, "speak" ) ) - { - return RESPONSE_SPEAK; - } - else if ( !Q_stricmp( s, "response" ) ) - { - return RESPONSE_RESPONSE; - } - else if ( !Q_stricmp( s, "print" ) ) - { - return RESPONSE_PRINT; - } - - return RESPONSE_NONE; -} - -void CResponseSystem::ParseOneResponse( const char *responseGroupName, ResponseGroup& group ) -{ - Response newResponse; - newResponse.weight.SetFloat( 1.0f ); - AI_ResponseParams *rp = &group.rp; - - newResponse.type = ComputeResponseType( token ); - if ( RESPONSE_NONE == newResponse.type ) - { - ResponseWarning( "response entry '%s' with unknown response type '%s'\n", responseGroupName, token ); - return; - } - - ParseToken(); - newResponse.value = CopyString( token ); - - while ( TokenWaiting() ) - { - ParseToken(); - if ( !Q_stricmp( token, "weight" ) ) - { - ParseToken(); - newResponse.weight.SetFloat( (float)atof( token ) ); - continue; - } - - if ( !Q_stricmp( token, "predelay" ) ) - { - ParseToken(); - rp->flags |= AI_ResponseParams::RG_DELAYBEFORESPEAK; - rp->predelay.FromInterval( ReadInterval( token ) ); - continue; - } - - if ( !Q_stricmp( token, "nodelay" ) ) - { - ParseToken(); - rp->flags |= AI_ResponseParams::RG_DELAYAFTERSPEAK; - rp->delay.start = 0; - rp->delay.range = 0; - continue; - } - - if ( !Q_stricmp( token, "defaultdelay" ) ) - { - rp->flags |= AI_ResponseParams::RG_DELAYAFTERSPEAK; - rp->delay.start = AIS_DEF_MIN_DELAY; - rp->delay.range = ( AIS_DEF_MAX_DELAY - AIS_DEF_MIN_DELAY ); - continue; - } - - if ( !Q_stricmp( token, "delay" ) ) - { - ParseToken(); - rp->flags |= AI_ResponseParams::RG_DELAYAFTERSPEAK; - rp->delay.FromInterval( ReadInterval( token ) ); - continue; - } - - if ( !Q_stricmp( token, "speakonce" ) ) - { - rp->flags |= AI_ResponseParams::RG_SPEAKONCE; - continue; - } - - if ( !Q_stricmp( token, "noscene" ) ) - { - rp->flags |= AI_ResponseParams::RG_DONT_USE_SCENE; - continue; - } - - if ( !Q_stricmp( token, "stop_on_nonidle" ) ) - { - rp->flags |= AI_ResponseParams::RG_STOP_ON_NONIDLE; - continue; - } - - if ( !Q_stricmp( token, "odds" ) ) - { - ParseToken(); - rp->flags |= AI_ResponseParams::RG_ODDS; - rp->odds = clamp( atoi( token ), 0, 100 ); - continue; - } - - if ( !Q_stricmp( token, "respeakdelay" ) ) - { - ParseToken(); - rp->flags |= AI_ResponseParams::RG_RESPEAKDELAY; - rp->respeakdelay.FromInterval( ReadInterval( token ) ); - continue; - } - - if ( !Q_stricmp( token, "weapondelay" ) ) - { - ParseToken(); - rp->flags |= AI_ResponseParams::RG_WEAPONDELAY; - rp->weapondelay.FromInterval( ReadInterval( token ) ); - continue; - } - - if ( !Q_stricmp( token, "soundlevel" ) ) - { - ParseToken(); - rp->flags |= AI_ResponseParams::RG_SOUNDLEVEL; - rp->soundlevel = (soundlevel_t)TextToSoundLevel( token ); - continue; - } - - if ( !Q_stricmp( token, "displayfirst" ) ) - { - newResponse.first = true; - group.m_bHasFirst = true; - continue; - } - - if ( !Q_stricmp( token, "displaylast" ) ) - { - newResponse.last = true; - group.m_bHasLast= true; - continue; - } - - ResponseWarning( "response entry '%s' with unknown command '%s'\n", responseGroupName, token ); - } - - group.group.AddToTail( newResponse ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CResponseSystem::IsRootCommand() -{ - if ( !Q_stricmp( token, "#include" ) ) - return true; - if ( !Q_stricmp( token, "response" ) ) - return true; - if ( !Q_stricmp( token, "enumeration" ) ) - return true; - if ( !Q_stricmp( token, "criteria" ) ) - return true; - if ( !Q_stricmp( token, "criterion" ) ) - return true; - if ( !Q_stricmp( token, "rule" ) ) - return true; - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *kv - -//----------------------------------------------------------------------------- -void CResponseSystem::ParseResponse( void ) -{ - // Should have groupname at start - char responseGroupName[ 128 ]; - - ResponseGroup newGroup; - AI_ResponseParams *rp = &newGroup.rp; - - // Response Group Name - ParseToken(); - Q_strncpy( responseGroupName, token, sizeof( responseGroupName ) ); - - while ( 1 ) - { - ParseToken(); - - // Oops, part of next definition - if( IsRootCommand() ) - { - Unget(); - break; - } - - if ( !Q_stricmp( token, "{" ) ) - { - while ( 1 ) - { - ParseToken(); - if ( !Q_stricmp( token, "}" ) ) - break; - - if ( !Q_stricmp( token, "permitrepeats" ) ) - { - newGroup.m_bDepleteBeforeRepeat = false; - continue; - } - else if ( !Q_stricmp( token, "sequential" ) ) - { - newGroup.SetSequential( true ); - continue; - } - else if ( !Q_stricmp( token, "norepeat" ) ) - { - newGroup.SetNoRepeat( true ); - continue; - } - - ParseOneResponse( responseGroupName, newGroup ); - } - break; - } - - if ( !Q_stricmp( token, "predelay" ) ) - { - ParseToken(); - rp->flags |= AI_ResponseParams::RG_DELAYBEFORESPEAK; - rp->predelay.FromInterval( ReadInterval( token ) ); - continue; - } - - if ( !Q_stricmp( token, "nodelay" ) ) - { - ParseToken(); - rp->flags |= AI_ResponseParams::RG_DELAYAFTERSPEAK; - rp->delay.start = 0; - rp->delay.range = 0; - continue; - } - - if ( !Q_stricmp( token, "defaultdelay" ) ) - { - rp->flags |= AI_ResponseParams::RG_DELAYAFTERSPEAK; - rp->delay.start = AIS_DEF_MIN_DELAY; - rp->delay.range = ( AIS_DEF_MAX_DELAY - AIS_DEF_MIN_DELAY ); - continue; - } - - if ( !Q_stricmp( token, "delay" ) ) - { - ParseToken(); - rp->flags |= AI_ResponseParams::RG_DELAYAFTERSPEAK; - rp->delay.FromInterval( ReadInterval( token ) ); - continue; - } - - if ( !Q_stricmp( token, "speakonce" ) ) - { - rp->flags |= AI_ResponseParams::RG_SPEAKONCE; - continue; - } - - if ( !Q_stricmp( token, "noscene" ) ) - { - rp->flags |= AI_ResponseParams::RG_DONT_USE_SCENE; - continue; - } - - if ( !Q_stricmp( token, "stop_on_nonidle" ) ) - { - rp->flags |= AI_ResponseParams::RG_STOP_ON_NONIDLE; - continue; - } - - if ( !Q_stricmp( token, "odds" ) ) - { - ParseToken(); - rp->flags |= AI_ResponseParams::RG_ODDS; - rp->odds = clamp( atoi( token ), 0, 100 ); - continue; - } - - if ( !Q_stricmp( token, "respeakdelay" ) ) - { - ParseToken(); - rp->flags |= AI_ResponseParams::RG_RESPEAKDELAY; - rp->respeakdelay.FromInterval( ReadInterval( token ) ); - continue; - } - - if ( !Q_stricmp( token, "weapondelay" ) ) - { - ParseToken(); - rp->flags |= AI_ResponseParams::RG_WEAPONDELAY; - rp->weapondelay.FromInterval( ReadInterval( token ) ); - continue; - } - - if ( !Q_stricmp( token, "soundlevel" ) ) - { - ParseToken(); - rp->flags |= AI_ResponseParams::RG_SOUNDLEVEL; - rp->soundlevel = (soundlevel_t)TextToSoundLevel( token ); - continue; - } - - ParseOneResponse( responseGroupName, newGroup ); - } - - m_Responses.Insert( responseGroupName, newGroup ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *criterion - -//----------------------------------------------------------------------------- -int CResponseSystem::ParseOneCriterion( const char *criterionName ) -{ - char key[ 128 ]; - char value[ 128 ]; - - Criteria newCriterion; - - bool gotbody = false; - - while ( TokenWaiting() || !gotbody ) - { - ParseToken(); - - // Oops, part of next definition - if( IsRootCommand() ) - { - Unget(); - break; - } - - if ( !Q_stricmp( token, "{" ) ) - { - gotbody = true; - - while ( 1 ) - { - ParseToken(); - if ( !Q_stricmp( token, "}" ) ) - break; - - // Look up subcriteria index - int idx = m_Criteria.Find( token ); - if ( idx != m_Criteria.InvalidIndex() ) - { - newCriterion.subcriteria.AddToTail( idx ); - } - else - { - ResponseWarning( "Skipping unrecongized subcriterion '%s' in '%s'\n", token, criterionName ); - } - } - continue; - } - else if ( !Q_stricmp( token, "required" ) ) - { - newCriterion.required = true; - } - else if ( !Q_stricmp( token, "weight" ) ) - { - ParseToken(); - newCriterion.weight.SetFloat( (float)atof( token ) ); - } - else - { - Assert( newCriterion.subcriteria.Count() == 0 ); - - // Assume it's the math info for a non-subcriteria resposne - Q_strncpy( key, token, sizeof( key ) ); - ParseToken(); - Q_strncpy( value, token, sizeof( value ) ); - - newCriterion.name = CopyString( key ); - newCriterion.value = CopyString( value ); - - gotbody = true; - } - } - - if ( !newCriterion.IsSubCriteriaType() ) - { - ComputeMatcher( &newCriterion, newCriterion.matcher ); - } - - if ( m_Criteria.Find( criterionName ) != m_Criteria.InvalidIndex() ) - { - ResponseWarning( "Multiple definitions for criteria '%s'\n", criterionName ); - return m_Criteria.InvalidIndex(); - } - - int idx = m_Criteria.Insert( criterionName, newCriterion ); - return idx; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *kv - -//----------------------------------------------------------------------------- -void CResponseSystem::ParseCriterion( void ) -{ - // Should have groupname at start - char criterionName[ 128 ]; - ParseToken(); - Q_strncpy( criterionName, token, sizeof( criterionName ) ); - - ParseOneCriterion( criterionName ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *kv - -//----------------------------------------------------------------------------- -void CResponseSystem::ParseEnumeration( void ) -{ - char enumerationName[ 128 ]; - ParseToken(); - Q_strncpy( enumerationName, token, sizeof( enumerationName ) ); - - ParseToken(); - if ( Q_stricmp( token, "{" ) ) - { - ResponseWarning( "Expecting '{' in enumeration '%s', got '%s'\n", enumerationName, token ); - return; - } - - while ( 1 ) - { - ParseToken(); - if ( !Q_stricmp( token, "}" ) ) - break; - - if ( Q_strlen( token ) <= 0 ) - { - ResponseWarning( "Expecting more tokens in enumeration '%s'\n", enumerationName ); - break; - } - - char key[ 128 ]; - - Q_strncpy( key, token, sizeof( key ) ); - ParseToken(); - float value = (float)atof( token ); - - char sz[ 128 ]; - Q_snprintf( sz, sizeof( sz ), "[%s::%s]", enumerationName, key ); - Q_strlower( sz ); - - Enumeration newEnum; - newEnum.value = value; - - if ( m_Enumerations.Find( sz ) == m_Enumerations.InvalidIndex() ) - { - m_Enumerations.Insert( sz, newEnum ); - } - /* - else - { - ResponseWarning( "Ignoring duplication enumeration '%s'\n", sz ); - } - */ - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *kv - -//----------------------------------------------------------------------------- -void CResponseSystem::ParseRule( void ) -{ - static int instancedCriteria = 0; - - char ruleName[ 128 ]; - ParseToken(); - Q_strncpy( ruleName, token, sizeof( ruleName ) ); - - ParseToken(); - if ( Q_stricmp( token, "{" ) ) - { - ResponseWarning( "Expecting '{' in rule '%s', got '%s'\n", ruleName, token ); - return; - } - - // entries are "criteria", "response" or an in-line criteria to instance - Rule newRule; - - char sz[ 128 ]; - - bool validRule = true; - while ( 1 ) - { - ParseToken(); - if ( !Q_stricmp( token, "}" ) ) - { - break; - } - - if ( Q_strlen( token ) <= 0 ) - { - ResponseWarning( "Expecting more tokens in rule '%s'\n", ruleName ); - break; - } - - if ( !Q_stricmp( token, "matchonce" ) ) - { - newRule.m_bMatchOnce = true; - continue; - } - - if ( !Q_stricmp( token, "applyContextToWorld" ) ) - { - newRule.m_bApplyContextToWorld = true; - continue; - } - - if ( !Q_stricmp( token, "applyContext" ) ) - { - ParseToken(); - if ( newRule.GetContext() == NULL ) - { - newRule.SetContext( token ); - } - else - { - CFmtStrN<1024> newContext( "%s,%s", newRule.GetContext(), token ); - newRule.SetContext( newContext ); - } - continue; - } - - if ( !Q_stricmp( token, "response" ) ) - { - // Read them until we run out. - while ( TokenWaiting() ) - { - ParseToken(); - int idx = m_Responses.Find( token ); - if ( idx != m_Responses.InvalidIndex() ) - { - MEM_ALLOC_CREDIT(); - newRule.m_Responses.AddToTail( idx ); - } - else - { - validRule = false; - ResponseWarning( "No such response '%s' for rule '%s'\n", token, ruleName ); - } - } - continue; - } - - if ( !Q_stricmp( token, "criteria" ) || - !Q_stricmp( token, "criterion" ) ) - { - // Read them until we run out. - while ( TokenWaiting() ) - { - ParseToken(); - - int idx = m_Criteria.Find( token ); - if ( idx != m_Criteria.InvalidIndex() ) - { - MEM_ALLOC_CREDIT(); - newRule.m_Criteria.AddToTail( idx ); - } - else - { - validRule = false; - ResponseWarning( "No such criterion '%s' for rule '%s'\n", token, ruleName ); - } - } - continue; - } - - // It's an inline criteria, generate a name and parse it in - Q_snprintf( sz, sizeof( sz ), "[%s%03i]", ruleName, ++instancedCriteria ); - Unget(); - int idx = ParseOneCriterion( sz ); - if ( idx != m_Criteria.InvalidIndex() ) - { - newRule.m_Criteria.AddToTail( idx ); - } - } - - if ( validRule ) - { - m_Rules.Insert( ruleName, newRule ); - } - else - { - DevMsg( "Discarded rule %s\n", ruleName ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CResponseSystem::GetCurrentToken() const -{ - if ( m_ScriptStack.Count() <= 0 ) - return -1; - - return m_ScriptStack[ 0 ].tokencount; -} - - -void CResponseSystem::ResponseWarning( const char *fmt, ... ) -{ - va_list argptr; -#ifndef _XBOX - static char string[1024]; -#else - char string[1024]; -#endif - - va_start (argptr, fmt); - Q_vsnprintf(string, sizeof(string), fmt,argptr); - va_end (argptr); - - char cur[ 256 ]; - GetCurrentScript( cur, sizeof( cur ) ); - DevMsg( 1, "%s(token %i) : %s", cur, GetCurrentToken(), string ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CResponseSystem::CopyCriteriaFrom( Rule *pSrcRule, Rule *pDstRule, CResponseSystem *pCustomSystem ) -{ - // Add criteria from this rule to global list in custom response system. - int nCriteriaCount = pSrcRule->m_Criteria.Count(); - for ( int iCriteria = 0; iCriteria < nCriteriaCount; ++iCriteria ) - { - int iSrcIndex = pSrcRule->m_Criteria[iCriteria]; - Criteria *pSrcCriteria = &m_Criteria[iSrcIndex]; - if ( pSrcCriteria ) - { - int iIndex = pCustomSystem->m_Criteria.Find( m_Criteria.GetElementName( iSrcIndex ) ); - if ( iIndex != pCustomSystem->m_Criteria.InvalidIndex() ) - { - pDstRule->m_Criteria.AddToTail( iIndex ); - continue; - } - - // Add the criteria. - Criteria dstCriteria; - - dstCriteria.name = CopyString( pSrcCriteria->name ); - dstCriteria.value = CopyString( pSrcCriteria->value ); - dstCriteria.weight = pSrcCriteria->weight; - dstCriteria.required = pSrcCriteria->required; - dstCriteria.matcher = pSrcCriteria->matcher; - - int nSubCriteriaCount = pSrcCriteria->subcriteria.Count(); - for ( int iSubCriteria = 0; iSubCriteria < nSubCriteriaCount; ++iSubCriteria ) - { - int iSrcSubIndex = pSrcCriteria->subcriteria[iSubCriteria]; - Criteria *pSrcSubCriteria = &m_Criteria[iSrcSubIndex]; - if ( pSrcCriteria ) - { - int iSubIndex = pCustomSystem->m_Criteria.Find( pSrcSubCriteria->value ); - if ( iSubIndex != pCustomSystem->m_Criteria.InvalidIndex() ) - continue; - - // Add the criteria. - Criteria dstSubCriteria; - - dstSubCriteria.name = CopyString( pSrcSubCriteria->name ); - dstSubCriteria.value = CopyString( pSrcSubCriteria->value ); - dstSubCriteria.weight = pSrcSubCriteria->weight; - dstSubCriteria.required = pSrcSubCriteria->required; - dstSubCriteria.matcher = pSrcSubCriteria->matcher; - - int iSubInsertIndex = pCustomSystem->m_Criteria.Insert( pSrcSubCriteria->value, dstSubCriteria ); - dstCriteria.subcriteria.AddToTail( iSubInsertIndex ); - } - } - - int iInsertIndex = pCustomSystem->m_Criteria.Insert( m_Criteria.GetElementName( iSrcIndex ), dstCriteria ); - pDstRule->m_Criteria.AddToTail( iInsertIndex ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CResponseSystem::CopyResponsesFrom( Rule *pSrcRule, Rule *pDstRule, CResponseSystem *pCustomSystem ) -{ - // Add responses from this rule to global list in custom response system. - int nResponseGroupCount = pSrcRule->m_Responses.Count(); - for ( int iResponseGroup = 0; iResponseGroup < nResponseGroupCount; ++iResponseGroup ) - { - int iSrcResponseGroup = pSrcRule->m_Responses[iResponseGroup]; - ResponseGroup *pSrcResponseGroup = &m_Responses[iSrcResponseGroup]; - if ( pSrcResponseGroup ) - { - // Add response group. - ResponseGroup dstResponseGroup; - - dstResponseGroup.rp = pSrcResponseGroup->rp; - dstResponseGroup.m_bDepleteBeforeRepeat = pSrcResponseGroup->m_bDepleteBeforeRepeat; - dstResponseGroup.m_nDepletionCount = pSrcResponseGroup->m_nDepletionCount; - dstResponseGroup.m_bHasFirst = pSrcResponseGroup->m_bHasFirst; - dstResponseGroup.m_bHasLast = pSrcResponseGroup->m_bHasLast; - dstResponseGroup.m_bSequential = pSrcResponseGroup->m_bSequential; - dstResponseGroup.m_bNoRepeat = pSrcResponseGroup->m_bNoRepeat; - dstResponseGroup.m_bEnabled = pSrcResponseGroup->m_bEnabled; - dstResponseGroup.m_nCurrentIndex = pSrcResponseGroup->m_nCurrentIndex; - - int nSrcResponseCount = pSrcResponseGroup->group.Count(); - for ( int iResponse = 0; iResponse < nSrcResponseCount; ++iResponse ) - { - Response *pSrcResponse = &pSrcResponseGroup->group[iResponse]; - if ( pSrcResponse ) - { - // Add Response - Response dstResponse; - - dstResponse.weight = pSrcResponse->weight; - dstResponse.type = pSrcResponse->type; - dstResponse.value = CopyString( pSrcResponse->value ); - dstResponse.depletioncount = pSrcResponse->depletioncount; - dstResponse.first = pSrcResponse->first; - dstResponse.last = pSrcResponse->last; - - dstResponseGroup.group.AddToTail( dstResponse ); - } - } - - int iInsertIndex = pCustomSystem->m_Responses.Insert( m_Responses.GetElementName( iSrcResponseGroup ), dstResponseGroup ); - pDstRule->m_Responses.AddToTail( iInsertIndex ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CResponseSystem::CopyEnumerationsFrom( CResponseSystem *pCustomSystem ) -{ - int nEnumerationCount = m_Enumerations.Count(); - for ( int iEnumeration = 0; iEnumeration < nEnumerationCount; ++iEnumeration ) - { - Enumeration *pSrcEnumeration = &m_Enumerations[iEnumeration]; - if ( pSrcEnumeration ) - { - Enumeration dstEnumeration; - dstEnumeration.value = pSrcEnumeration->value; - pCustomSystem->m_Enumerations.Insert( m_Enumerations.GetElementName( iEnumeration ), dstEnumeration ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CResponseSystem::CopyRuleFrom( Rule *pSrcRule, int iRule, CResponseSystem *pCustomSystem ) -{ - // Verify data. - Assert( pSrcRule ); - Assert( pCustomSystem ); - if ( !pSrcRule || !pCustomSystem ) - return; - - // New rule - Rule dstRule; - - dstRule.SetContext( pSrcRule->GetContext() ); - dstRule.m_bMatchOnce = pSrcRule->m_bMatchOnce; - dstRule.m_bEnabled = pSrcRule->m_bEnabled; - dstRule.m_bApplyContextToWorld = pSrcRule->m_bApplyContextToWorld; - - // Copy off criteria. - CopyCriteriaFrom( pSrcRule, &dstRule, pCustomSystem ); - - // Copy off responses. - CopyResponsesFrom( pSrcRule, &dstRule, pCustomSystem ); - - // Copy off enumerations - Don't think we use these. -// CopyEnumerationsFrom( pCustomSystem ); - - // Add rule. - pCustomSystem->m_Rules.Insert( m_Rules.GetElementName( iRule ), dstRule ); -} - -//----------------------------------------------------------------------------- -// Purpose: A special purpose response system associated with a custom entity -//----------------------------------------------------------------------------- -class CInstancedResponseSystem : public CResponseSystem -{ - typedef CResponseSystem BaseClass; - -public: - CInstancedResponseSystem( const char *scriptfile ) : - m_pszScriptFile( 0 ) - { - Assert( scriptfile ); - - int len = Q_strlen( scriptfile ) + 1; - m_pszScriptFile = new char[ len ]; - Assert( m_pszScriptFile ); - Q_strncpy( m_pszScriptFile, scriptfile, len ); - } - - ~CInstancedResponseSystem() - { - delete[] m_pszScriptFile; - } - virtual const char *GetScriptFile( void ) - { - Assert( m_pszScriptFile ); - return m_pszScriptFile; - } - - // CAutoGameSystem - virtual bool Init() - { - const char *basescript = GetScriptFile(); - LoadRuleSet( basescript ); - return true; - } - - virtual void LevelInitPostEntity() - { - ResetResponseGroups(); - } - - virtual void Release() - { - Clear(); - delete this; - } -private: - - char *m_pszScriptFile; -}; - -//----------------------------------------------------------------------------- -// Purpose: The default response system for expressive AIs -//----------------------------------------------------------------------------- -class CDefaultResponseSystem : public CResponseSystem, public CAutoGameSystem -{ - typedef CAutoGameSystem BaseClass; - -public: - CDefaultResponseSystem() : CAutoGameSystem( "CDefaultResponseSystem" ) - { - } - - virtual const char *GetScriptFile( void ) - { - return "scripts/talker/response_rules.txt"; - } - - // CAutoServerSystem - virtual bool Init(); - virtual void Shutdown(); - - virtual void LevelInitPostEntity() - { - } - - virtual void Release() - { - Assert( 0 ); - } - - void AddInstancedResponseSystem( const char *scriptfile, CInstancedResponseSystem *sys ) - { - m_InstancedSystems.Insert( scriptfile, sys ); - } - - CInstancedResponseSystem *FindResponseSystem( const char *scriptfile ) - { - int idx = m_InstancedSystems.Find( scriptfile ); - if ( idx == m_InstancedSystems.InvalidIndex() ) - return NULL; - return m_InstancedSystems[ idx ]; - } - - IResponseSystem *PrecacheCustomResponseSystem( const char *scriptfile ) - { - CInstancedResponseSystem *sys = ( CInstancedResponseSystem * )FindResponseSystem( scriptfile ); - if ( !sys ) - { - sys = new CInstancedResponseSystem( scriptfile ); - if ( !sys ) - { - Error( "Failed to load response system data from %s", scriptfile ); - } - - if ( !sys->Init() ) - { - Error( "CInstancedResponseSystem: Failed to init response system from %s!", scriptfile ); - } - - AddInstancedResponseSystem( scriptfile, sys ); - } - - sys->Precache(); - - return ( IResponseSystem * )sys; - } - - IResponseSystem *BuildCustomResponseSystemGivenCriteria( const char *pszBaseFile, const char *pszCustomName, AI_CriteriaSet &criteriaSet, float flCriteriaScore ); - void DestroyCustomResponseSystems(); - - virtual void LevelInitPreEntity() - { - // This will precache the default system - // All user installed systems are init'd by PrecacheCustomResponseSystem which will call sys->Precache() on the ones being used - - // FIXME: This is SLOW the first time you run the engine (can take 3 - 10 seconds!!!) - if ( ShouldPrecache() ) - { - Precache(); - } - - ResetResponseGroups(); - } - - void ReloadAllResponseSystems() - { - Clear(); - Init(); - - int c = m_InstancedSystems.Count(); - for ( int i = c - 1 ; i >= 0; i-- ) - { - CInstancedResponseSystem *sys = m_InstancedSystems[ i ]; - if ( !IsCustomManagable() ) - { - sys->Clear(); - sys->Init(); - } - else - { - // Custom reponse rules will manage/reload themselves - remove them. - m_InstancedSystems.RemoveAt( i ); - } - } - - } - -private: - - void ClearInstanced() - { - int c = m_InstancedSystems.Count(); - for ( int i = c - 1 ; i >= 0; i-- ) - { - CInstancedResponseSystem *sys = m_InstancedSystems[ i ]; - sys->Release(); - } - m_InstancedSystems.RemoveAll(); - } - - CUtlDict< CInstancedResponseSystem *, int > m_InstancedSystems; -}; - -IResponseSystem *CDefaultResponseSystem::BuildCustomResponseSystemGivenCriteria( const char *pszBaseFile, const char *pszCustomName, AI_CriteriaSet &criteriaSet, float flCriteriaScore ) -{ - // Create a instanced response system. - CInstancedResponseSystem *pCustomSystem = new CInstancedResponseSystem( pszCustomName ); - if ( !pCustomSystem ) - { - Error( "BuildCustomResponseSystemGivenCriterea: Failed to create custom response system %s!", pszCustomName ); - } - - pCustomSystem->Clear(); - - // Copy the relevant rules and data. - int nRuleCount = m_Rules.Count(); - for ( int iRule = 0; iRule < nRuleCount; ++iRule ) - { - Rule *pRule = &m_Rules[iRule]; - if ( pRule ) - { - float flScore = 0.0f; - - int nCriteriaCount = pRule->m_Criteria.Count(); - for ( int iCriteria = 0; iCriteria < nCriteriaCount; ++iCriteria ) - { - int iRuleCriteria = pRule->m_Criteria[iCriteria]; - - flScore += LookForCriteria( criteriaSet, iRuleCriteria ); - if ( flScore >= flCriteriaScore ) - { - CopyRuleFrom( pRule, iRule, pCustomSystem ); - break; - } - } - } - } - - // Set as a custom response system. - m_bCustomManagable = true; - AddInstancedResponseSystem( pszCustomName, pCustomSystem ); - -// pCustomSystem->DumpDictionary( pszCustomName ); - - return pCustomSystem; -} - -void CDefaultResponseSystem::DestroyCustomResponseSystems() -{ - ClearInstanced(); -} - - -static CDefaultResponseSystem defaultresponsesytem; -IResponseSystem *g_pResponseSystem = &defaultresponsesytem; - -CON_COMMAND( rr_reloadresponsesystems, "Reload all response system scripts." ) -{ - defaultresponsesytem.ReloadAllResponseSystems(); - -#if defined( TF_DLL ) - // This is kind of hacky, but I need to get it in for now! - if( g_pGameRules->IsMultiplayer() ) - { - CMultiplayRules *pMultiplayRules = static_cast( g_pGameRules ); - pMultiplayRules->InitCustomResponseRulesDicts(); - } -#endif -} - -static short RESPONSESYSTEM_SAVE_RESTORE_VERSION = 1; - -// note: this won't save/restore settings from instanced response systems. Could add that with a CDefSaveRestoreOps implementation if needed -// -class CDefaultResponseSystemSaveRestoreBlockHandler : public CDefSaveRestoreBlockHandler -{ -public: - const char *GetBlockName() - { - return "ResponseSystem"; - } - - void WriteSaveHeaders( ISave *pSave ) - { - pSave->WriteShort( &RESPONSESYSTEM_SAVE_RESTORE_VERSION ); - } - - void ReadRestoreHeaders( IRestore *pRestore ) - { - // No reason why any future version shouldn't try to retain backward compatability. The default here is to not do so. - short version; - pRestore->ReadShort( &version ); - m_fDoLoad = ( version == RESPONSESYSTEM_SAVE_RESTORE_VERSION ); - } - - void Save( ISave *pSave ) - { - CDefaultResponseSystem& rs = defaultresponsesytem; - - int count = rs.m_Responses.Count(); - pSave->WriteInt( &count ); - for ( int i = 0; i < count; ++i ) - { - pSave->StartBlock( "ResponseGroup" ); - - pSave->WriteString( rs.m_Responses.GetElementName( i ) ); - const ResponseGroup *group = &rs.m_Responses[ i ]; - pSave->WriteAll( group ); - - short groupCount = group->group.Count(); - pSave->WriteShort( &groupCount ); - for ( int j = 0; j < groupCount; ++j ) - { - const Response *response = &group->group[ j ]; - pSave->StartBlock( "Response" ); - pSave->WriteString( response->value ); - pSave->WriteAll( response ); - pSave->EndBlock(); - } - - pSave->EndBlock(); - } - } - - void Restore( IRestore *pRestore, bool createPlayers ) - { - if ( !m_fDoLoad ) - return; - - CDefaultResponseSystem& rs = defaultresponsesytem; - - int count = pRestore->ReadInt(); - for ( int i = 0; i < count; ++i ) - { - char szResponseGroupBlockName[SIZE_BLOCK_NAME_BUF]; - pRestore->StartBlock( szResponseGroupBlockName ); - if ( !Q_stricmp( szResponseGroupBlockName, "ResponseGroup" ) ) - { - - char groupname[ 256 ]; - pRestore->ReadString( groupname, sizeof( groupname ), 0 ); - - // Try and find it - int idx = rs.m_Responses.Find( groupname ); - if ( idx != rs.m_Responses.InvalidIndex() ) - { - ResponseGroup *group = &rs.m_Responses[ idx ]; - pRestore->ReadAll( group ); - - short groupCount = pRestore->ReadShort(); - for ( int j = 0; j < groupCount; ++j ) - { - char szResponseBlockName[SIZE_BLOCK_NAME_BUF]; - - char responsename[ 256 ]; - pRestore->StartBlock( szResponseBlockName ); - if ( !Q_stricmp( szResponseBlockName, "Response" ) ) - { - pRestore->ReadString( responsename, sizeof( responsename ), 0 ); - - // Find it by name - int ri; - for ( ri = 0; ri < group->group.Count(); ++ri ) - { - Response *response = &group->group[ ri ]; - if ( !Q_stricmp( response->value, responsename ) ) - { - break; - } - } - - if ( ri < group->group.Count() ) - { - Response *response = &group->group[ ri ]; - pRestore->ReadAll( response ); - } - } - - pRestore->EndBlock(); - } - } - } - - pRestore->EndBlock(); - } - } -private: - - bool m_fDoLoad; - -} g_DefaultResponseSystemSaveRestoreBlockHandler; - -ISaveRestoreBlockHandler *GetDefaultResponseSystemSaveRestoreBlockHandler() -{ - return &g_DefaultResponseSystemSaveRestoreBlockHandler; -} - -//----------------------------------------------------------------------------- -// CResponseSystemSaveRestoreOps -// -// Purpose: Handles save and load for instanced response systems... -// -// BUGBUG: This will save the same response system to file multiple times for "shared" response systems and -// therefore it'll restore the same data onto the same pointer N times on reload (probably benign for now, but we could -// write code to save/restore the instanced ones by filename in the block handler above maybe? -//----------------------------------------------------------------------------- - -class CResponseSystemSaveRestoreOps : public CDefSaveRestoreOps -{ -public: - - virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave ) - { - CResponseSystem *pRS = *(CResponseSystem **)fieldInfo.pField; - if ( !pRS || pRS == &defaultresponsesytem ) - return; - - int count = pRS->m_Responses.Count(); - pSave->WriteInt( &count ); - for ( int i = 0; i < count; ++i ) - { - pSave->StartBlock( "ResponseGroup" ); - - pSave->WriteString( pRS->m_Responses.GetElementName( i ) ); - const ResponseGroup *group = &pRS->m_Responses[ i ]; - pSave->WriteAll( group ); - - short groupCount = group->group.Count(); - pSave->WriteShort( &groupCount ); - for ( int j = 0; j < groupCount; ++j ) - { - const Response *response = &group->group[ j ]; - pSave->StartBlock( "Response" ); - pSave->WriteString( response->value ); - pSave->WriteAll( response ); - pSave->EndBlock(); - } - - pSave->EndBlock(); - } - } - - virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore ) - { - CResponseSystem *pRS = *(CResponseSystem **)fieldInfo.pField; - if ( !pRS || pRS == &defaultresponsesytem ) - return; - - int count = pRestore->ReadInt(); - for ( int i = 0; i < count; ++i ) - { - char szResponseGroupBlockName[SIZE_BLOCK_NAME_BUF]; - pRestore->StartBlock( szResponseGroupBlockName ); - if ( !Q_stricmp( szResponseGroupBlockName, "ResponseGroup" ) ) - { - - char groupname[ 256 ]; - pRestore->ReadString( groupname, sizeof( groupname ), 0 ); - - // Try and find it - int idx = pRS->m_Responses.Find( groupname ); - if ( idx != pRS->m_Responses.InvalidIndex() ) - { - ResponseGroup *group = &pRS->m_Responses[ idx ]; - pRestore->ReadAll( group ); - - short groupCount = pRestore->ReadShort(); - for ( int j = 0; j < groupCount; ++j ) - { - char szResponseBlockName[SIZE_BLOCK_NAME_BUF]; - - char responsename[ 256 ]; - pRestore->StartBlock( szResponseBlockName ); - if ( !Q_stricmp( szResponseBlockName, "Response" ) ) - { - pRestore->ReadString( responsename, sizeof( responsename ), 0 ); - - // Find it by name - int ri; - for ( ri = 0; ri < group->group.Count(); ++ri ) - { - Response *response = &group->group[ ri ]; - if ( !Q_stricmp( response->value, responsename ) ) - { - break; - } - } - - if ( ri < group->group.Count() ) - { - Response *response = &group->group[ ri ]; - pRestore->ReadAll( response ); - } - } - - pRestore->EndBlock(); - } - } - } - - pRestore->EndBlock(); - } - } - -} g_ResponseSystemSaveRestoreOps; - -ISaveRestoreOps *responseSystemSaveRestoreOps = &g_ResponseSystemSaveRestoreOps; - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CDefaultResponseSystem::Init() -{ -/* - Warning( "sizeof( Response ) == %d\n", sizeof( Response ) ); - Warning( "sizeof( ResponseGroup ) == %d\n", sizeof( ResponseGroup ) ); - Warning( "sizeof( Criteria ) == %d\n", sizeof( Criteria ) ); - Warning( "sizeof( AI_ResponseParams ) == %d\n", sizeof( AI_ResponseParams ) ); -*/ - const char *basescript = GetScriptFile(); - - LoadRuleSet( basescript ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDefaultResponseSystem::Shutdown() -{ - // Wipe instanced versions - ClearInstanced(); - - // Clear outselves - Clear(); - // IServerSystem chain - BaseClass::Shutdown(); -} - -//----------------------------------------------------------------------------- -// Purpose: Instance a custom response system -// Input : *scriptfile - -// Output : IResponseSystem -//----------------------------------------------------------------------------- -IResponseSystem *PrecacheCustomResponseSystem( const char *scriptfile ) -{ - return defaultresponsesytem.PrecacheCustomResponseSystem( scriptfile ); -} - -//----------------------------------------------------------------------------- -// Purpose: Instance a custom response system -// Input : *scriptfile - -// set - -// Output : IResponseSystem -//----------------------------------------------------------------------------- -IResponseSystem *BuildCustomResponseSystemGivenCriteria( const char *pszBaseFile, const char *pszCustomName, AI_CriteriaSet &criteriaSet, float flCriteriaScore ) -{ - return defaultresponsesytem.BuildCustomResponseSystemGivenCriteria( pszBaseFile, pszCustomName, criteriaSet, flCriteriaScore ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void DestroyCustomResponseSystems() -{ - defaultresponsesytem.DestroyCustomResponseSystems(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CResponseSystem::DumpRules() -{ - int c = m_Rules.Count(); - int i; - - for ( i = 0; i < c; i++ ) - { - Msg("%s\n", m_Rules.GetElementName( i ) ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CResponseSystem::DumpDictionary( const char *pszName ) -{ - Msg( "\nDictionary: %s\n", pszName ); - - int nRuleCount = m_Rules.Count(); - for ( int iRule = 0; iRule < nRuleCount; ++iRule ) - { - Msg(" Rule %d: %s\n", iRule, m_Rules.GetElementName( iRule ) ); - - Rule *pRule = &m_Rules[iRule]; - - int nCriteriaCount = pRule->m_Criteria.Count(); - for( int iCriteria = 0; iCriteria < nCriteriaCount; ++iCriteria ) - { - int iRuleCriteria = pRule->m_Criteria[iCriteria]; - Criteria *pCriteria = &m_Criteria[iRuleCriteria]; - Msg( " Criteria %d: %s %s\n", iCriteria, pCriteria->name, pCriteria->value ); - } - - int nResponseGroupCount = pRule->m_Responses.Count(); - for ( int iResponseGroup = 0; iResponseGroup < nResponseGroupCount; ++iResponseGroup ) - { - int iRuleResponse = pRule->m_Responses[iResponseGroup]; - ResponseGroup *pResponseGroup = &m_Responses[iRuleResponse]; - - Msg( " ResponseGroup %d: %s\n", iResponseGroup, m_Responses.GetElementName( iRuleResponse ) ); - - int nResponseCount = pResponseGroup->group.Count(); - for ( int iResponse = 0; iResponse < nResponseCount; ++iResponse ) - { - Response *pResponse = &pResponseGroup->group[iResponse]; - Msg( " Response %d: %s\n", iResponse, pResponse->value ); - } - } - } -} diff --git a/game/server/AI_ResponseSystem.h b/game/server/AI_ResponseSystem.h deleted file mode 100644 index 7818f096a..000000000 --- a/game/server/AI_ResponseSystem.h +++ /dev/null @@ -1,41 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef AI_RESPONSESYSTEM_H -#define AI_RESPONSESYSTEM_H - -#include "utlvector.h" - -#ifdef _WIN32 -#pragma once -#endif - -#include "AI_Criteria.h" - -abstract_class IResponseFilter -{ -public: - virtual bool IsValidResponse( ResponseType_t type, const char *pszValue ) = 0; -}; - -abstract_class IResponseSystem -{ -public: - virtual ~IResponseSystem() {} - - virtual bool FindBestResponse( const AI_CriteriaSet& set, AI_Response& response, IResponseFilter *pFilter = NULL ) = 0; - virtual void GetAllResponses( CUtlVector *pResponses ) = 0; - virtual void PrecacheResponses( bool bEnable ) = 0; -}; - -IResponseSystem *PrecacheCustomResponseSystem( const char *scriptfile ); -IResponseSystem *BuildCustomResponseSystemGivenCriteria( const char *pszBaseFile, const char *pszCustomName, AI_CriteriaSet &criteriaSet, float flCriteriaScore ); -void DestroyCustomResponseSystems(); - -class ISaveRestoreBlockHandler *GetDefaultResponseSystemSaveRestoreBlockHandler(); -class ISaveRestoreOps *GetResponseSystemSaveRestoreOps(); - -#endif // AI_RESPONSESYSTEM_H diff --git a/game/server/BaseAnimatingOverlay.cpp b/game/server/BaseAnimatingOverlay.cpp deleted file mode 100644 index 5e13deacb..000000000 --- a/game/server/BaseAnimatingOverlay.cpp +++ /dev/null @@ -1,1141 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// - -#include "cbase.h" -#include "animation.h" -#include "studio.h" -#include "bone_setup.h" -#include "ai_basenpc.h" -#include "npcevent.h" - -#include "saverestore_utlvector.h" -#include "dt_utlvector_send.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern ConVar ai_sequence_debug; - - -BEGIN_SIMPLE_DATADESC( CAnimationLayer ) - -// DEFINE_FIELD( m_pOwnerEntity, CBaseAnimatingOverlay ), - DEFINE_FIELD( m_fFlags, FIELD_INTEGER ), - DEFINE_FIELD( m_bSequenceFinished, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bLooping, FIELD_BOOLEAN ), - DEFINE_FIELD( m_nSequence, FIELD_INTEGER ), - DEFINE_FIELD( m_flCycle, FIELD_FLOAT ), - DEFINE_FIELD( m_flPrevCycle, FIELD_FLOAT ), - DEFINE_FIELD( m_flPlaybackRate, FIELD_FLOAT), - DEFINE_FIELD( m_flWeight, FIELD_FLOAT), - DEFINE_FIELD( m_flBlendIn, FIELD_FLOAT ), - DEFINE_FIELD( m_flBlendOut, FIELD_FLOAT ), - DEFINE_FIELD( m_flKillRate, FIELD_FLOAT ), - DEFINE_FIELD( m_flKillDelay, FIELD_FLOAT ), - DEFINE_CUSTOM_FIELD( m_nActivity, ActivityDataOps() ), - DEFINE_FIELD( m_nPriority, FIELD_INTEGER ), - DEFINE_FIELD( m_nOrder, FIELD_INTEGER ), - DEFINE_FIELD( m_flLastEventCheck, FIELD_FLOAT ), - DEFINE_FIELD( m_flLastAccess, FIELD_TIME ), - DEFINE_FIELD( m_flLayerAnimtime, FIELD_FLOAT ), - DEFINE_FIELD( m_flLayerFadeOuttime, FIELD_FLOAT ), - -END_DATADESC() - - -BEGIN_DATADESC( CBaseAnimatingOverlay ) - - DEFINE_UTLVECTOR( m_AnimOverlay, FIELD_EMBEDDED ), - - // DEFINE_FIELD( m_nActiveLayers, FIELD_INTEGER ), - // DEFINE_FIELD( m_nActiveBaseLayers, FIELD_INTEGER ), - -END_DATADESC() - - -#define ORDER_BITS 4 -#define WEIGHT_BITS 8 - -BEGIN_SEND_TABLE_NOBASE(CAnimationLayer, DT_Animationlayer) - SendPropInt (SENDINFO(m_nSequence), ANIMATION_SEQUENCE_BITS,SPROP_UNSIGNED), - SendPropFloat (SENDINFO(m_flCycle), ANIMATION_CYCLE_BITS, SPROP_ROUNDDOWN, 0.0f, 1.0f), - SendPropFloat (SENDINFO(m_flPrevCycle), ANIMATION_CYCLE_BITS, SPROP_ROUNDDOWN, 0.0f, 1.0f), - SendPropFloat (SENDINFO(m_flWeight), WEIGHT_BITS, 0, 0.0f, 1.0f), - SendPropInt (SENDINFO(m_nOrder), ORDER_BITS, SPROP_UNSIGNED), -END_SEND_TABLE() - - -BEGIN_SEND_TABLE_NOBASE( CBaseAnimatingOverlay, DT_OverlayVars ) - SendPropUtlVector( - SENDINFO_UTLVECTOR( m_AnimOverlay ), - CBaseAnimatingOverlay::MAX_OVERLAYS, // max elements - SendPropDataTable( NULL, 0, &REFERENCE_SEND_TABLE( DT_Animationlayer ) ) ) -END_SEND_TABLE() - - -IMPLEMENT_SERVERCLASS_ST( CBaseAnimatingOverlay, DT_BaseAnimatingOverlay ) - // These are in their own separate data table so CCSPlayer can exclude all of these. - SendPropDataTable( "overlay_vars", 0, &REFERENCE_SEND_TABLE( DT_OverlayVars ) ) -END_SEND_TABLE() - - - - -CAnimationLayer::CAnimationLayer( ) -{ - Init( NULL ); -} - - -void CAnimationLayer::Init( CBaseAnimatingOverlay *pOverlay ) -{ - m_pOwnerEntity = pOverlay; - m_fFlags = 0; - m_flWeight = 0; - m_flCycle = 0; - m_flPrevCycle = 0; - m_bSequenceFinished = false; - m_nActivity = ACT_INVALID; - m_nSequence = 0; - m_nPriority = 0; - m_nOrder.Set( CBaseAnimatingOverlay::MAX_OVERLAYS ); - m_flKillRate = 100.0; - m_flKillDelay = 0.0; - m_flPlaybackRate = 1.0; - m_flLastAccess = gpGlobals->curtime; - m_flLayerAnimtime = 0; - m_flLayerFadeOuttime = 0; -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ - -void CAnimationLayer::StudioFrameAdvance( float flInterval, CBaseAnimating *pOwner ) -{ - float flCycleRate = pOwner->GetSequenceCycleRate( m_nSequence ); - - m_flPrevCycle = m_flCycle; - m_flCycle += flInterval * flCycleRate * m_flPlaybackRate; - - if (m_flCycle < 0.0) - { - if (m_bLooping) - { - m_flCycle -= (int)(m_flCycle); - } - else - { - m_flCycle = 0; - } - } - else if (m_flCycle >= 1.0) - { - m_bSequenceFinished = true; - - if (m_bLooping) - { - m_flCycle -= (int)(m_flCycle); - } - else - { - m_flCycle = 1.0; - } - } - - if (IsAutoramp()) - { - m_flWeight = 1; - - // blend in? - if ( m_flBlendIn != 0.0f ) - { - if (m_flCycle < m_flBlendIn) - { - m_flWeight = m_flCycle / m_flBlendIn; - } - } - - // blend out? - if ( m_flBlendOut != 0.0f ) - { - if (m_flCycle > 1.0 - m_flBlendOut) - { - m_flWeight = (1.0 - m_flCycle) / m_flBlendOut; - } - } - - m_flWeight = 3.0 * m_flWeight * m_flWeight - 2.0 * m_flWeight * m_flWeight * m_flWeight; - if (m_nSequence == 0) - m_flWeight = 0; - } -} - -//------------------------------------------------------------------------------ - -bool CAnimationLayer::IsAbandoned( void ) -{ - if (IsActive() && !IsAutokill() && !IsKillMe() && m_flLastAccess > 0.0 && (gpGlobals->curtime - m_flLastAccess > 0.2)) - return true; - else - return false; -} - -void CAnimationLayer::MarkActive( void ) -{ - m_flLastAccess = gpGlobals->curtime; -} - -//------------------------------------------------------------------------------ - -void CBaseAnimatingOverlay::VerifyOrder( void ) -{ -#ifdef _DEBUG - int i, j; - // test sorting of the layers - int layer[MAX_OVERLAYS]; - int maxOrder = -1; - for (i = 0; i < MAX_OVERLAYS; i++) - { - layer[i] = MAX_OVERLAYS; - } - for (i = 0; i < m_AnimOverlay.Count(); i++) - { - if (m_AnimOverlay[ i ].m_nOrder < MAX_OVERLAYS) - { - j = m_AnimOverlay[ i ].m_nOrder; - Assert( layer[j] == MAX_OVERLAYS ); - layer[j] = i; - if (j > maxOrder) - maxOrder = j; - } - } - - // make sure they're sequential - // Aim layers are allowed to have gaps, and we are moving aim blending to server -// for ( i = 0; i <= maxOrder; i++ ) -// { -// Assert( layer[i] != MAX_OVERLAYS); -// } - - /* - for ( i = 0; i < MAX_OVERLAYS; i++ ) - { - int j = layer[i]; - if (j != MAX_OVERLAYS) - { - char tempstr[512]; - Q_snprintf( tempstr, sizeof( tempstr ),"%d : %d :%.2f :%d:%d:%.1f", - j, - m_AnimOverlay[ j ].m_nSequence, - m_AnimOverlay[ j ].m_flWeight, - m_AnimOverlay[ j ].IsActive(), - m_AnimOverlay[ j ].IsKillMe(), - m_AnimOverlay[ j ].m_flKillDelay - ); - EntityText( i, tempstr, 0.1 ); - } - } - */ -#endif -} - - -//------------------------------------------------------------------------------ -// Purpose : advance the animation frame up to the current time -// if an flInterval is passed in, only advance animation that number of seconds -// Input : -// Output : -//------------------------------------------------------------------------------ - -void CBaseAnimatingOverlay::StudioFrameAdvance () -{ - float flAdvance = GetAnimTimeInterval(); - - VerifyOrder(); - - BaseClass::StudioFrameAdvance(); - - for ( int i = 0; i < m_AnimOverlay.Count(); i++ ) - { - CAnimationLayer *pLayer = &m_AnimOverlay[i]; - - if (pLayer->IsActive()) - { - // Assert( !m_AnimOverlay[ i ].IsAbandoned() ); - if (pLayer->IsKillMe()) - { - if (pLayer->m_flKillDelay > 0) - { - pLayer->m_flKillDelay -= flAdvance; - pLayer->m_flKillDelay = clamp( pLayer->m_flKillDelay, 0.0, 1.0 ); - } - else if (pLayer->m_flWeight != 0.0f) - { - // give it at least one frame advance cycle to propagate 0.0 to client - pLayer->m_flWeight -= pLayer->m_flKillRate * flAdvance; - pLayer->m_flWeight = clamp( pLayer->m_flWeight, 0.0, 1.0 ); - } - else - { - // shift the other layers down in order - if (ai_sequence_debug.GetBool() == true && m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) - { - Msg("removing %d (%d): %s : %5.3f (%.3f)\n", i, pLayer->m_nOrder.Get(), GetSequenceName( pLayer->m_nSequence ), pLayer->m_flCycle.Get(), pLayer->m_flWeight.Get() ); - } - FastRemoveLayer( i ); - // needs at least one thing cycle dead to trigger sequence change - pLayer->Dying(); - continue; - } - } - - pLayer->StudioFrameAdvance( flAdvance, this ); - if ( pLayer->m_bSequenceFinished && (pLayer->IsAutokill()) ) - { - pLayer->m_flWeight = 0.0f; - pLayer->KillMe(); - } - } - else if (pLayer->IsDying()) - { - pLayer->Dead(); - } - else if (pLayer->m_flWeight > 0.0) - { - // Now that the server blends, it is turning off layers all the time. Having a weight left over - // when you're no longer marked as active is now harmless and commonplace. Just clean up. - pLayer->Init( this ); - pLayer->Dying(); - } - } - - if (ai_sequence_debug.GetBool() == true && m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) - { - for ( int i = 0; i < m_AnimOverlay.Count(); i++ ) - { - if (m_AnimOverlay[ i ].IsActive()) - { - /* - if (m_AnimOverlay[ i ].IsAbandoned()) - { - Msg(" %d abandoned %.2f (%.2f)\n", i, gpGlobals->curtime, m_AnimOverlay[ i ].m_flLastAccess ); - } - */ - Msg(" %d (%d): %s : %5.3f (%.3f)\n", i, m_AnimOverlay[ i ].m_nOrder.Get(), GetSequenceName( m_AnimOverlay[ i ].m_nSequence ), m_AnimOverlay[ i ].m_flCycle.Get(), m_AnimOverlay[ i ].m_flWeight.Get() ); - } - } - } - - VerifyOrder(); -} - - - -//========================================================= -// DispatchAnimEvents -//========================================================= -void CBaseAnimatingOverlay::DispatchAnimEvents ( CBaseAnimating *eventHandler ) -{ - BaseClass::DispatchAnimEvents( eventHandler ); - - for ( int i = 0; i < m_AnimOverlay.Count(); i++ ) - { - if (m_AnimOverlay[ i ].IsActive()) - { - m_AnimOverlay[ i ].DispatchAnimEvents( eventHandler, this ); - } - } -} - -void CAnimationLayer::DispatchAnimEvents( CBaseAnimating *eventHandler, CBaseAnimating *pOwner ) -{ - animevent_t event; - - CStudioHdr *pstudiohdr = pOwner->GetModelPtr( ); - - if ( !pstudiohdr ) - { - Assert(!"CBaseAnimating::DispatchAnimEvents: model missing"); - return; - } - - if ( !pstudiohdr->SequencesAvailable() ) - { - return; - } - - if ( m_nSequence >= pstudiohdr->GetNumSeq() ) - return; - - // don't fire if here are no events - if ( pstudiohdr->pSeqdesc( m_nSequence ).numevents == 0 ) - { - return; - } - - // look from when it last checked to some short time in the future - float flCycleRate = pOwner->GetSequenceCycleRate( m_nSequence ) * m_flPlaybackRate; - float flStart = m_flLastEventCheck; - float flEnd = m_flCycle; - - if (!m_bLooping) - { - // fire off events early - float flLastVisibleCycle = 1.0f - (pstudiohdr->pSeqdesc( m_nSequence ).fadeouttime) * flCycleRate; - if (flEnd >= flLastVisibleCycle || flEnd < 0.0) - { - m_bSequenceFinished = true; - flEnd = 1.0f; - } - } - m_flLastEventCheck = flEnd; - - /* - if (pOwner->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) - { - Msg( "%s:%s : checking %.2f %.2f (%d)\n", STRING(pOwner->GetModelName()), pstudiohdr->pSeqdesc( m_nSequence ).pszLabel(), flStart, flEnd, m_bSequenceFinished ); - } - */ - - // FIXME: does not handle negative framerates! - int index = 0; - while ( (index = GetAnimationEvent( pstudiohdr, m_nSequence, &event, flStart, flEnd, index ) ) != 0 ) - { - event.pSource = pOwner; - // calc when this event should happen - if (flCycleRate > 0.0) - { - float flCycle = event.cycle; - if (flCycle > m_flCycle) - { - flCycle = flCycle - 1.0; - } - event.eventtime = pOwner->m_flAnimTime + (flCycle - m_flCycle) / flCycleRate + pOwner->GetAnimTimeInterval(); - } - - // Msg( "dispatch %d (%d : %.2f)\n", index - 1, event.event, event.eventtime ); - eventHandler->HandleAnimEvent( &event ); - } -} - - - -void CBaseAnimatingOverlay::GetSkeleton( CStudioHdr *pStudioHdr, Vector pos[], Quaternion q[], int boneMask ) -{ - if(!pStudioHdr) - { - Assert(!"CBaseAnimating::GetSkeleton() without a model"); - return; - } - - if (!pStudioHdr->SequencesAvailable()) - { - return; - } - - InitPose( pStudioHdr, pos, q, boneMask ); - - AccumulatePose( pStudioHdr, m_pIk, pos, q, GetSequence(), GetCycle(), GetPoseParameterArray(), boneMask, 1.0, gpGlobals->curtime ); - - // sort the layers - int layer[MAX_OVERLAYS]; - int i; - for (i = 0; i < m_AnimOverlay.Count(); i++) - { - layer[i] = MAX_OVERLAYS; - } - for (i = 0; i < m_AnimOverlay.Count(); i++) - { - CAnimationLayer &pLayer = m_AnimOverlay[i]; - if( (pLayer.m_flWeight > 0) && pLayer.IsActive() && pLayer.m_nOrder >= 0 && pLayer.m_nOrder < m_AnimOverlay.Count()) - { - layer[pLayer.m_nOrder] = i; - } - } - for (i = 0; i < m_AnimOverlay.Count(); i++) - { - if (layer[i] >= 0 && layer[i] < m_AnimOverlay.Count()) - { - CAnimationLayer &pLayer = m_AnimOverlay[layer[i]]; - // UNDONE: Is it correct to use overlay weight for IK too? - AccumulatePose( pStudioHdr, m_pIk, pos, q, pLayer.m_nSequence, pLayer.m_flCycle, GetPoseParameterArray(), boneMask, pLayer.m_flWeight, gpGlobals->curtime ); - } - } - - if ( m_pIk ) - { - CIKContext auto_ik; - auto_ik.Init( pStudioHdr, GetAbsAngles(), GetAbsOrigin(), gpGlobals->curtime, 0, boneMask ); - CalcAutoplaySequences( pStudioHdr, &auto_ik, pos, q, GetPoseParameterArray(), boneMask, gpGlobals->curtime ); - } - else - { - CalcAutoplaySequences( pStudioHdr, NULL, pos, q, GetPoseParameterArray(), boneMask, gpGlobals->curtime ); - } - CalcBoneAdj( pStudioHdr, pos, q, GetEncodedControllerArray(), boneMask ); -} - - - -//----------------------------------------------------------------------------- -// Purpose: zero's out all non-restore safe fields -// Output : -//----------------------------------------------------------------------------- -void CBaseAnimatingOverlay::OnRestore( ) -{ - int i; - - // force order of unused layers to current MAX_OVERLAYS - // and Tracker 48843 (Alyx skating after restore) restore the owner entity ptr (otherwise the network layer won't get NetworkStateChanged signals until the layer is re-Init()'ed - for (i = 0; i < m_AnimOverlay.Count(); i++) - { - m_AnimOverlay[i].m_pOwnerEntity = this; - - if ( !m_AnimOverlay[i].IsActive()) - { - m_AnimOverlay[i].m_nOrder.Set( MAX_OVERLAYS ); - } - } - - // get rid of all layers that shouldn't be restored - for (i = 0; i < m_AnimOverlay.Count(); i++) - { - if ( ( m_AnimOverlay[i].IsActive() && (m_AnimOverlay[i].m_fFlags & ANIM_LAYER_DONTRESTORE) ) || - ( GetModelPtr() && !IsValidSequence(m_AnimOverlay[i].m_nSequence) ) ) - { - FastRemoveLayer( i ); - } - } - - BaseClass::OnRestore(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CBaseAnimatingOverlay::AddGestureSequence( int sequence, bool autokill /*= true*/ ) -{ - int i = AddLayeredSequence( sequence, 0 ); - // No room? - if ( IsValidLayer( i ) ) - { - SetLayerAutokill( i, autokill ); - } - - return i; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CBaseAnimatingOverlay::AddGestureSequence( int nSequence, float flDuration, bool autokill /*= true*/ ) -{ - int iLayer = AddGestureSequence( nSequence, autokill ); - Assert( iLayer != -1 ); - - if (iLayer >= 0 && flDuration > 0) - { - m_AnimOverlay[iLayer].m_flPlaybackRate = SequenceDuration( nSequence ) / flDuration; - } - return iLayer; -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -int CBaseAnimatingOverlay::AddGesture( Activity activity, bool autokill /*= true*/ ) -{ - if ( IsPlayingGesture( activity ) ) - { - return FindGestureLayer( activity ); - } - - int seq = SelectWeightedSequence( activity ); - if ( seq <= 0 ) - { - const char *actname = CAI_BaseNPC::GetActivityName( activity ); - DevMsg( "CBaseAnimatingOverlay::AddGesture: model %s missing activity %s\n", STRING(GetModelName()), actname ); - return -1; - } - - int i = AddGestureSequence( seq, autokill ); - Assert( i != -1 ); - if ( i != -1 ) - { - m_AnimOverlay[ i ].m_nActivity = activity; - } - - return i; -} - - -int CBaseAnimatingOverlay::AddGesture( Activity activity, float flDuration, bool autokill /*= true*/ ) -{ - int iLayer = AddGesture( activity, autokill ); - SetLayerDuration( iLayer, flDuration ); - - return iLayer; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- - -void CBaseAnimatingOverlay::SetLayerDuration( int iLayer, float flDuration ) -{ - if (IsValidLayer( iLayer ) && flDuration > 0) - { - m_AnimOverlay[iLayer].m_flPlaybackRate = SequenceDuration( m_AnimOverlay[iLayer].m_nSequence ) / flDuration; - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- - -float CBaseAnimatingOverlay::GetLayerDuration( int iLayer ) -{ - if (IsValidLayer( iLayer )) - { - if (m_AnimOverlay[iLayer].m_flPlaybackRate != 0.0f) - { - return (1.0 - m_AnimOverlay[iLayer].m_flCycle) * SequenceDuration( m_AnimOverlay[iLayer].m_nSequence ) / m_AnimOverlay[iLayer].m_flPlaybackRate; - } - return SequenceDuration( m_AnimOverlay[iLayer].m_nSequence ); - } - return 0.0; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CBaseAnimatingOverlay::AddLayeredSequence( int sequence, int iPriority ) -{ - int i = AllocateLayer( iPriority ); - // No room? - if ( IsValidLayer( i ) ) - { - m_AnimOverlay[i].m_flCycle = 0; - m_AnimOverlay[i].m_flPrevCycle = 0; - m_AnimOverlay[i].m_flPlaybackRate = 1.0; - m_AnimOverlay[i].m_nActivity = ACT_INVALID; - m_AnimOverlay[i].m_nSequence = sequence; - m_AnimOverlay[i].m_flWeight = 1.0f; - m_AnimOverlay[i].m_flBlendIn = 0.0f; - m_AnimOverlay[i].m_flBlendOut = 0.0f; - m_AnimOverlay[i].m_bSequenceFinished = false; - m_AnimOverlay[i].m_flLastEventCheck = 0; - m_AnimOverlay[i].m_bLooping = ((GetSequenceFlags( GetModelPtr(), sequence ) & STUDIO_LOOPING) != 0); - if (ai_sequence_debug.GetBool() == true && m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) - { - Msg("%5.3f : adding %d (%d): %s : %5.3f (%.3f)\n", gpGlobals->curtime, i, m_AnimOverlay[ i ].m_nOrder.Get(), GetSequenceName( m_AnimOverlay[ i ].m_nSequence ), m_AnimOverlay[ i ].m_flCycle.Get(), m_AnimOverlay[ i ].m_flWeight.Get() ); - } - } - - return i; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -bool CBaseAnimatingOverlay::IsValidLayer( int iLayer ) -{ - return (iLayer >= 0 && iLayer < m_AnimOverlay.Count() && m_AnimOverlay[iLayer].IsActive()); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CBaseAnimatingOverlay::AllocateLayer( int iPriority ) -{ - int i; - - // look for an open slot and for existing layers that are lower priority - int iNewOrder = 0; - int iOpenLayer = -1; - int iNumOpen = 0; - for (i = 0; i < m_AnimOverlay.Count(); i++) - { - if ( m_AnimOverlay[i].IsActive() ) - { - if (m_AnimOverlay[i].m_nPriority <= iPriority) - { - iNewOrder = MAX( iNewOrder, m_AnimOverlay[i].m_nOrder + 1 ); - } - } - else if (m_AnimOverlay[ i ].IsDying()) - { - // skip - } - else if (iOpenLayer == -1) - { - iOpenLayer = i; - } - else - { - iNumOpen++; - } - } - - if (iOpenLayer == -1) - { - if (m_AnimOverlay.Count() >= MAX_OVERLAYS) - { - return -1; - } - - iOpenLayer = m_AnimOverlay.AddToTail(); - m_AnimOverlay[iOpenLayer].Init( this ); - } - - // make sure there's always an empty unused layer so that history slots will be available on the client when it is used - if (iNumOpen == 0) - { - if (m_AnimOverlay.Count() < MAX_OVERLAYS) - { - i = m_AnimOverlay.AddToTail(); - m_AnimOverlay[i].Init( this ); - } - } - - for (i = 0; i < m_AnimOverlay.Count(); i++) - { - if ( m_AnimOverlay[i].m_nOrder >= iNewOrder && m_AnimOverlay[i].m_nOrder < MAX_OVERLAYS) - { - m_AnimOverlay[i].m_nOrder++; - } - } - - m_AnimOverlay[iOpenLayer].m_fFlags = ANIM_LAYER_ACTIVE; - m_AnimOverlay[iOpenLayer].m_nOrder = iNewOrder; - m_AnimOverlay[iOpenLayer].m_nPriority = iPriority; - - m_AnimOverlay[iOpenLayer].MarkActive(); - VerifyOrder(); - - return iOpenLayer; -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -void CBaseAnimatingOverlay::SetLayerPriority( int iLayer, int iPriority ) -{ - if (!IsValidLayer( iLayer )) - { - return; - } - - if (m_AnimOverlay[iLayer].m_nPriority == iPriority) - { - return; - } - - // look for an open slot and for existing layers that are lower priority - int i; - for (i = 0; i < m_AnimOverlay.Count(); i++) - { - if ( m_AnimOverlay[i].IsActive() ) - { - if (m_AnimOverlay[i].m_nOrder > m_AnimOverlay[iLayer].m_nOrder) - { - m_AnimOverlay[i].m_nOrder--; - } - } - } - - int iNewOrder = 0; - for (i = 0; i < m_AnimOverlay.Count(); i++) - { - if ( i != iLayer && m_AnimOverlay[i].IsActive() ) - { - if (m_AnimOverlay[i].m_nPriority <= iPriority) - { - iNewOrder = MAX( iNewOrder, m_AnimOverlay[i].m_nOrder + 1 ); - } - } - } - - for (i = 0; i < m_AnimOverlay.Count(); i++) - { - if ( i != iLayer && m_AnimOverlay[i].IsActive() ) - { - if ( m_AnimOverlay[i].m_nOrder >= iNewOrder) - { - m_AnimOverlay[i].m_nOrder++; - } - } - } - - m_AnimOverlay[iLayer].m_nOrder = iNewOrder; - m_AnimOverlay[iLayer].m_nPriority = iPriority; - m_AnimOverlay[iLayer].MarkActive( ); - - VerifyOrder(); - - return; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : activity - -//----------------------------------------------------------------------------- -int CBaseAnimatingOverlay::FindGestureLayer( Activity activity ) -{ - for (int i = 0; i < m_AnimOverlay.Count(); i++) - { - if ( !(m_AnimOverlay[i].IsActive()) ) - continue; - - if ( m_AnimOverlay[i].IsKillMe() ) - continue; - - if ( m_AnimOverlay[i].m_nActivity == ACT_INVALID ) - continue; - - if ( m_AnimOverlay[i].m_nActivity == activity ) - return i; - } - - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : activity - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseAnimatingOverlay::IsPlayingGesture( Activity activity ) -{ - return FindGestureLayer( activity ) != -1 ? true : false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : activity - -//----------------------------------------------------------------------------- -void CBaseAnimatingOverlay::RestartGesture( Activity activity, bool addifmissing /*=true*/, bool autokill /*=true*/ ) -{ - int idx = FindGestureLayer( activity ); - if ( idx == -1 ) - { - if ( addifmissing ) - { - AddGesture( activity, autokill ); - } - return; - } - - m_AnimOverlay[ idx ].m_flCycle = 0.0f; - m_AnimOverlay[ idx ].m_flPrevCycle = 0.0f; - m_AnimOverlay[ idx ].m_flLastEventCheck = 0.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : activity - -//----------------------------------------------------------------------------- -void CBaseAnimatingOverlay::RemoveGesture( Activity activity ) -{ - int iLayer = FindGestureLayer( activity ); - if ( iLayer == -1 ) - return; - - RemoveLayer( iLayer ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseAnimatingOverlay::RemoveAllGestures( void ) -{ - for (int i = 0; i < m_AnimOverlay.Count(); i++) - { - RemoveLayer( i ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseAnimatingOverlay::SetLayerCycle( int iLayer, float flCycle ) -{ - if (!IsValidLayer( iLayer )) - return; - - if (!m_AnimOverlay[iLayer].m_bLooping) - { - flCycle = clamp( flCycle, 0.0, 1.0 ); - } - m_AnimOverlay[iLayer].m_flCycle = flCycle; - m_AnimOverlay[iLayer].MarkActive( ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseAnimatingOverlay::SetLayerCycle( int iLayer, float flCycle, float flPrevCycle ) -{ - if (!IsValidLayer( iLayer )) - return; - - if (!m_AnimOverlay[iLayer].m_bLooping) - { - flCycle = clamp( flCycle, 0.0, 1.0 ); - flPrevCycle = clamp( flPrevCycle, 0.0, 1.0 ); - } - m_AnimOverlay[iLayer].m_flCycle = flCycle; - m_AnimOverlay[iLayer].m_flPrevCycle = flPrevCycle; - m_AnimOverlay[iLayer].m_flLastEventCheck = flPrevCycle; - m_AnimOverlay[iLayer].MarkActive( ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CBaseAnimatingOverlay::GetLayerCycle( int iLayer ) -{ - if (!IsValidLayer( iLayer )) - return 0.0; - - return m_AnimOverlay[iLayer].m_flCycle; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseAnimatingOverlay::SetLayerPlaybackRate( int iLayer, float flPlaybackRate ) -{ - if (!IsValidLayer( iLayer )) - return; - - Assert( flPlaybackRate > -1.0 && flPlaybackRate < 40.0); - - m_AnimOverlay[iLayer].m_flPlaybackRate = flPlaybackRate; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseAnimatingOverlay::SetLayerWeight( int iLayer, float flWeight ) -{ - if (!IsValidLayer( iLayer )) - return; - - flWeight = clamp( flWeight, 0.0f, 1.0f ); - m_AnimOverlay[iLayer].m_flWeight = flWeight; - m_AnimOverlay[iLayer].MarkActive( ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CBaseAnimatingOverlay::GetLayerWeight( int iLayer ) -{ - if (!IsValidLayer( iLayer )) - return 0.0; - - return m_AnimOverlay[iLayer].m_flWeight; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseAnimatingOverlay::SetLayerBlendIn( int iLayer, float flBlendIn ) -{ - if (!IsValidLayer( iLayer )) - return; - - m_AnimOverlay[iLayer].m_flBlendIn = flBlendIn; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseAnimatingOverlay::SetLayerBlendOut( int iLayer, float flBlendOut ) -{ - if (!IsValidLayer( iLayer )) - return; - - m_AnimOverlay[iLayer].m_flBlendOut = flBlendOut; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseAnimatingOverlay::SetLayerAutokill( int iLayer, bool bAutokill ) -{ - if (!IsValidLayer( iLayer )) - return; - - if (bAutokill) - { - m_AnimOverlay[iLayer].m_fFlags |= ANIM_LAYER_AUTOKILL; - } - else - { - m_AnimOverlay[iLayer].m_fFlags &= ~ANIM_LAYER_AUTOKILL; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseAnimatingOverlay::SetLayerLooping( int iLayer, bool bLooping ) -{ - if (!IsValidLayer( iLayer )) - return; - - m_AnimOverlay[iLayer].m_bLooping = bLooping; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseAnimatingOverlay::SetLayerNoRestore( int iLayer, bool bNoRestore ) -{ - if (!IsValidLayer( iLayer )) - return; - - if (bNoRestore) - { - m_AnimOverlay[iLayer].m_fFlags |= ANIM_LAYER_DONTRESTORE; - } - else - { - m_AnimOverlay[iLayer].m_fFlags &= ~ANIM_LAYER_DONTRESTORE; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Activity CBaseAnimatingOverlay::GetLayerActivity( int iLayer ) -{ - if (!IsValidLayer( iLayer )) - { - return ACT_INVALID; - } - - return m_AnimOverlay[iLayer].m_nActivity; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBaseAnimatingOverlay::GetLayerSequence( int iLayer ) -{ - if (!IsValidLayer( iLayer )) - { - return ACT_INVALID; - } - - return m_AnimOverlay[iLayer].m_nSequence; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseAnimatingOverlay::RemoveLayer( int iLayer, float flKillRate, float flKillDelay ) -{ - if (!IsValidLayer( iLayer )) - return; - - if (flKillRate > 0) - { - m_AnimOverlay[iLayer].m_flKillRate = m_AnimOverlay[iLayer].m_flWeight / flKillRate; - } - else - { - m_AnimOverlay[iLayer].m_flKillRate = 100; - } - - m_AnimOverlay[iLayer].m_flKillDelay = flKillDelay; - - m_AnimOverlay[iLayer].KillMe(); -} - -void CBaseAnimatingOverlay::FastRemoveLayer( int iLayer ) -{ - if (!IsValidLayer( iLayer )) - return; - - // shift the other layers down in order - for (int j = 0; j < m_AnimOverlay.Count(); j++ ) - { - if ((m_AnimOverlay[ j ].IsActive()) && m_AnimOverlay[ j ].m_nOrder > m_AnimOverlay[ iLayer ].m_nOrder) - { - m_AnimOverlay[ j ].m_nOrder--; - } - } - m_AnimOverlay[ iLayer ].Init( this ); - - VerifyOrder(); -} - -CAnimationLayer *CBaseAnimatingOverlay::GetAnimOverlay( int iIndex ) -{ - iIndex = clamp( iIndex, 0, m_AnimOverlay.Count()-1 ); - - return &m_AnimOverlay[iIndex]; -} - - -void CBaseAnimatingOverlay::SetNumAnimOverlays( int num ) -{ - if ( m_AnimOverlay.Count() < num ) - { - m_AnimOverlay.AddMultipleToTail( num - m_AnimOverlay.Count() ); - } - else if ( m_AnimOverlay.Count() > num ) - { - m_AnimOverlay.RemoveMultiple( num, m_AnimOverlay.Count() - num ); - } -} - -bool CBaseAnimatingOverlay::HasActiveLayer( void ) -{ - for (int j = 0; j < m_AnimOverlay.Count(); j++ ) - { - if ( m_AnimOverlay[ j ].IsActive() ) - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- diff --git a/game/server/BaseAnimatingOverlay.h b/game/server/BaseAnimatingOverlay.h deleted file mode 100644 index 686847ac5..000000000 --- a/game/server/BaseAnimatingOverlay.h +++ /dev/null @@ -1,231 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -// #include "BaseAnimating.h" - -#ifndef BASE_ANIMATING_OVERLAY_H -#define BASE_ANIMATING_OVERLAY_H -#ifdef _WIN32 -#pragma once -#endif - -class CBaseAnimatingOverlay; - -class CAnimationLayer -{ -public: - DECLARE_CLASS_NOBASE( CAnimationLayer ); - - CAnimationLayer( void ); - void Init( CBaseAnimatingOverlay *pOverlay ); - - // float SetBlending( int iBlender, float flValue, CBaseAnimating *pOwner ); - void StudioFrameAdvance( float flInterval, CBaseAnimating *pOwner ); - void DispatchAnimEvents( CBaseAnimating *eventHandler, CBaseAnimating *pOwner ); - void SetOrder( int nOrder ); - - float GetFadeout( float flCurTime ); - - // For CNetworkVars. - void NetworkStateChanged(); - void NetworkStateChanged( void *pVar ); - -public: - -#define ANIM_LAYER_ACTIVE 0x0001 -#define ANIM_LAYER_AUTOKILL 0x0002 -#define ANIM_LAYER_KILLME 0x0004 -#define ANIM_LAYER_DONTRESTORE 0x0008 -#define ANIM_LAYER_CHECKACCESS 0x0010 -#define ANIM_LAYER_DYING 0x0020 - - int m_fFlags; - - bool m_bSequenceFinished; - bool m_bLooping; - - CNetworkVar( int, m_nSequence ); - CNetworkVar( float, m_flCycle ); - CNetworkVar( float, m_flPrevCycle ); - CNetworkVar( float, m_flWeight ); - - float m_flPlaybackRate; - - float m_flBlendIn; // start and end blend frac (0.0 for now blend) - float m_flBlendOut; - - float m_flKillRate; - float m_flKillDelay; - - float m_flLayerAnimtime; - float m_flLayerFadeOuttime; - - // For checking for duplicates - Activity m_nActivity; - - // order of layering on client - int m_nPriority; - CNetworkVar( int, m_nOrder ); - - bool IsActive( void ) { return ((m_fFlags & ANIM_LAYER_ACTIVE) != 0); } - bool IsAutokill( void ) { return ((m_fFlags & ANIM_LAYER_AUTOKILL) != 0); } - bool IsKillMe( void ) { return ((m_fFlags & ANIM_LAYER_KILLME) != 0); } - bool IsAutoramp( void ) { return (m_flBlendIn != 0.0 || m_flBlendOut != 0.0); } - void KillMe( void ) { m_fFlags |= ANIM_LAYER_KILLME; } - void Dying( void ) { m_fFlags |= ANIM_LAYER_DYING; } - bool IsDying( void ) { return ((m_fFlags & ANIM_LAYER_DYING) != 0); } - void Dead( void ) { m_fFlags &= ~ANIM_LAYER_DYING; } - - bool IsAbandoned( void ); - void MarkActive( void ); - - float m_flLastEventCheck; - - float m_flLastAccess; - - // Network state changes get forwarded here. - CBaseAnimatingOverlay *m_pOwnerEntity; - - DECLARE_SIMPLE_DATADESC(); -}; - -inline float CAnimationLayer::GetFadeout( float flCurTime ) -{ - float s; - - if (m_flLayerFadeOuttime <= 0.0f) - { - s = 0; - } - else - { - // blend in over 0.2 seconds - s = 1.0 - (flCurTime - m_flLayerAnimtime) / m_flLayerFadeOuttime; - if (s > 0 && s <= 1.0) - { - // do a nice spline curve - s = 3 * s * s - 2 * s * s * s; - } - else if ( s > 1.0f ) - { - // Shouldn't happen, but maybe curtime is behind animtime? - s = 1.0f; - } - } - return s; -} - - - -class CBaseAnimatingOverlay : public CBaseAnimating -{ - DECLARE_CLASS( CBaseAnimatingOverlay, CBaseAnimating ); - -public: - enum - { - MAX_OVERLAYS = 15, - }; - -private: - CUtlVector< CAnimationLayer > m_AnimOverlay; - //int m_nActiveLayers; - //int m_nActiveBaseLayers; - -public: - - virtual void OnRestore(); - - virtual void StudioFrameAdvance(); - virtual void DispatchAnimEvents ( CBaseAnimating *eventHandler ); - virtual void GetSkeleton( CStudioHdr *pStudioHdr, Vector pos[], Quaternion q[], int boneMask ); - - int AddGestureSequence( int sequence, bool autokill = true ); - int AddGestureSequence( int sequence, float flDuration, bool autokill = true ); - int AddGesture( Activity activity, bool autokill = true ); - int AddGesture( Activity activity, float flDuration, bool autokill = true ); - bool IsPlayingGesture( Activity activity ); - void RestartGesture( Activity activity, bool addifmissing = true, bool autokill = true ); - void RemoveGesture( Activity activity ); - void RemoveAllGestures( void ); - - int AddLayeredSequence( int sequence, int iPriority ); - - void SetLayerPriority( int iLayer, int iPriority ); - - bool IsValidLayer( int iLayer ); - - void SetLayerDuration( int iLayer, float flDuration ); - float GetLayerDuration( int iLayer ); - - void SetLayerCycle( int iLayer, float flCycle ); - void SetLayerCycle( int iLayer, float flCycle, float flPrevCycle ); - float GetLayerCycle( int iLayer ); - - void SetLayerPlaybackRate( int iLayer, float flPlaybackRate ); - void SetLayerWeight( int iLayer, float flWeight ); - float GetLayerWeight( int iLayer ); - void SetLayerBlendIn( int iLayer, float flBlendIn ); - void SetLayerBlendOut( int iLayer, float flBlendOut ); - void SetLayerAutokill( int iLayer, bool bAutokill ); - void SetLayerLooping( int iLayer, bool bLooping ); - void SetLayerNoRestore( int iLayer, bool bNoRestore ); - - Activity GetLayerActivity( int iLayer ); - int GetLayerSequence( int iLayer ); - - int FindGestureLayer( Activity activity ); - - void RemoveLayer( int iLayer, float flKillRate = 0.2, float flKillDelay = 0.0 ); - void FastRemoveLayer( int iLayer ); - - CAnimationLayer *GetAnimOverlay( int iIndex ); - int GetNumAnimOverlays() const; - void SetNumAnimOverlays( int num ); - - void VerifyOrder( void ); - - bool HasActiveLayer( void ); - -private: - int AllocateLayer( int iPriority = 0 ); // lower priorities are processed first - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - DECLARE_PREDICTABLE(); -}; - -EXTERN_SEND_TABLE(DT_BaseAnimatingOverlay); - -inline int CBaseAnimatingOverlay::GetNumAnimOverlays() const -{ - return m_AnimOverlay.Count(); -} - -// ------------------------------------------------------------------------------------------ // -// CAnimationLayer inlines. -// ------------------------------------------------------------------------------------------ // - -inline void CAnimationLayer::SetOrder( int nOrder ) -{ - m_nOrder = nOrder; -} - -inline void CAnimationLayer::NetworkStateChanged() -{ - if ( m_pOwnerEntity ) - m_pOwnerEntity->NetworkStateChanged(); -} - -inline void CAnimationLayer::NetworkStateChanged( void *pVar ) -{ - if ( m_pOwnerEntity ) - m_pOwnerEntity->NetworkStateChanged(); -} - -#endif // BASE_ANIMATING_OVERLAY_H diff --git a/game/server/BasePropDoor.h b/game/server/BasePropDoor.h deleted file mode 100644 index 99969a941..000000000 --- a/game/server/BasePropDoor.h +++ /dev/null @@ -1,275 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: A base class for model-based doors. The exact movement required to -// open or close the door is not dictated by this class, only that -// the door has open, closed, opening, and closing states. -// -// Doors must satisfy these requirements: -// -// - Derived classes must support being opened by NPCs. -// - Never autoclose in the face of a player. -// - Never close into an NPC. -// -//=============================================================================// - -#ifndef BASEPROPDOOR_H -#define BASEPROPDOOR_H -#ifdef _WIN32 -#pragma once -#endif - -#include "props.h" -#include "locksounds.h" -#include "entityoutput.h" - -extern ConVar g_debug_doors; - -struct opendata_t -{ - Vector vecStandPos; // Where the NPC should stand. - Vector vecFaceDir; // What direction the NPC should face. - Activity eActivity; // What activity the NPC should play. -}; - - -abstract_class CBasePropDoor : public CDynamicProp -{ -public: - - DECLARE_CLASS( CBasePropDoor, CDynamicProp ); - DECLARE_SERVERCLASS(); - - CBasePropDoor( void ); - - void Spawn(); - void Precache(); - void Activate(); - int ObjectCaps(); - - void HandleAnimEvent( animevent_t *pEvent ); - - // Base class services. - // Do not make the functions in this block virtual!! - // { - inline bool IsDoorOpen(); - inline bool IsDoorAjar(); - inline bool IsDoorOpening(); - inline bool IsDoorClosed(); - inline bool IsDoorClosing(); - inline bool IsDoorLocked(); - inline bool IsDoorBlocked() const; - inline bool IsNPCOpening(CAI_BaseNPC *pNPC); - inline bool IsPlayerOpening(); - inline bool IsOpener(CBaseEntity *pEnt); - - bool NPCOpenDoor(CAI_BaseNPC *pNPC); - bool TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ); - // } - - // Implement these in your leaf class. - // { - virtual bool DoorCanClose( bool bAutoClose ) { return true; } - virtual bool DoorCanOpen( void ) { return true; } - - virtual void GetNPCOpenData(CAI_BaseNPC *pNPC, opendata_t &opendata) = 0; - virtual float GetOpenInterval(void) = 0; - // } - -protected: - - enum DoorState_t - { - DOOR_STATE_CLOSED = 0, - DOOR_STATE_OPENING, - DOOR_STATE_OPEN, - DOOR_STATE_CLOSING, - DOOR_STATE_AJAR, - }; - - // dvs: FIXME: make these private - void DoorClose(); - - CBasePropDoor *GetMaster( void ) { return m_hMaster; } - bool HasSlaves( void ) { return ( m_hDoorList.Count() > 0 ); } - - inline void SetDoorState( DoorState_t eDoorState ); - - float m_flAutoReturnDelay; // How many seconds to wait before automatically closing, -1 never closes automatically. - CUtlVector< CHandle< CBasePropDoor > > m_hDoorList; // List of doors linked to us - - inline CBaseEntity *GetActivator(); - -private: - - // Implement these in your leaf class. - // { - // Called when the door becomes fully open. - virtual void OnDoorOpened() {} - - // Called when the door becomes fully closed. - virtual void OnDoorClosed() {} - - // Called to tell the door to start opening. - virtual void BeginOpening(CBaseEntity *pOpenAwayFrom) = 0; - - // Called to tell the door to start closing. - virtual void BeginClosing( void ) = 0; - - // Called when blocked to tell the door to stop moving. - virtual void DoorStop( void ) = 0; - - // Called when blocked to tell the door to continue moving. - virtual void DoorResume( void ) = 0; - - // Called to send the door instantly to its spawn positions. - virtual void DoorTeleportToSpawnPosition() = 0; - // } - -private: - - // Main entry points for the door base behaviors. - // Do not make the functions in this block virtual!! - // { - bool DoorActivate(); - void DoorOpen( CBaseEntity *pOpenAwayFrom ); - void OpenIfUnlocked(CBaseEntity *pActivator, CBaseEntity *pOpenAwayFrom); - - void DoorOpenMoveDone(); - void DoorCloseMoveDone(); - void DoorAutoCloseThink(); - - void Lock(); - void Unlock(); - - void Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value); - void OnUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - inline bool WillAutoReturn() { return m_flAutoReturnDelay != -1; } - - void StartBlocked(CBaseEntity *pOther); - void OnStartBlocked( CBaseEntity *pOther ); - void MasterStartBlocked( CBaseEntity *pOther ); - - void Blocked(CBaseEntity *pOther); - void EndBlocked(void); - void OnEndBlocked( void ); - - void UpdateAreaPortals(bool bOpen); - - // Input handlers - void InputClose(inputdata_t &inputdata); - void InputLock(inputdata_t &inputdata); - void InputOpen(inputdata_t &inputdata); - void InputOpenAwayFrom(inputdata_t &inputdata); - void InputToggle(inputdata_t &inputdata); - void InputUnlock(inputdata_t &inputdata); - - void SetDoorBlocker( CBaseEntity *pBlocker ); - - void SetMaster( CBasePropDoor *pMaster ) { m_hMaster = pMaster; } - - void CalcDoorSounds(); - // } - - int m_nHardwareType; - - DoorState_t m_eDoorState; // Holds whether the door is open, closed, opening, or closing. - - locksound_t m_ls; // The sounds the door plays when being locked, unlocked, etc. - EHANDLE m_hActivator; - - bool m_bLocked; // True if the door is locked. - EHANDLE m_hBlocker; // Entity blocking the door currently - bool m_bFirstBlocked; // Marker for being the first door (in a group) to be blocked (needed for motion control) - - bool m_bForceClosed; // True if this door must close no matter what. - - string_t m_SoundMoving; - string_t m_SoundOpen; - string_t m_SoundClose; - - // dvs: FIXME: can we remove m_flSpeed from CBaseEntity? - //float m_flSpeed; // Rotation speed when opening or closing in degrees per second. - - DECLARE_DATADESC(); - - string_t m_SlaveName; - - CHandle< CBasePropDoor > m_hMaster; - - static void RegisterPrivateActivities(); - - // Outputs - COutputEvent m_OnBlockedClosing; // Triggered when the door becomes blocked while closing. - COutputEvent m_OnBlockedOpening; // Triggered when the door becomes blocked while opening. - COutputEvent m_OnUnblockedClosing; // Triggered when the door becomes unblocked while closing. - COutputEvent m_OnUnblockedOpening; // Triggered when the door becomes unblocked while opening. - COutputEvent m_OnFullyClosed; // Triggered when the door reaches the fully closed position. - COutputEvent m_OnFullyOpen; // Triggered when the door reaches the fully open position. - COutputEvent m_OnClose; // Triggered when the door is told to close. - COutputEvent m_OnOpen; // Triggered when the door is told to open. - COutputEvent m_OnLockedUse; // Triggered when the user tries to open a locked door. -}; - - -void CBasePropDoor::SetDoorState( DoorState_t eDoorState ) -{ - m_eDoorState = eDoorState; -} - -bool CBasePropDoor::IsDoorOpen() -{ - return m_eDoorState == DOOR_STATE_OPEN; -} - -bool CBasePropDoor::IsDoorAjar() -{ - return ( m_eDoorState == DOOR_STATE_AJAR ); -} - -bool CBasePropDoor::IsDoorOpening() -{ - return m_eDoorState == DOOR_STATE_OPENING; -} - -bool CBasePropDoor::IsDoorClosed() -{ - return m_eDoorState == DOOR_STATE_CLOSED; -} - -bool CBasePropDoor::IsDoorClosing() -{ - return m_eDoorState == DOOR_STATE_CLOSING; -} - -bool CBasePropDoor::IsDoorLocked() -{ - return m_bLocked; -} - -CBaseEntity *CBasePropDoor::GetActivator() -{ - return m_hActivator; -} - -bool CBasePropDoor::IsDoorBlocked() const -{ - return ( m_hBlocker != NULL ); -} - -bool CBasePropDoor::IsNPCOpening( CAI_BaseNPC *pNPC ) -{ - return ( pNPC == ( CAI_BaseNPC * )GetActivator() ); -} - -inline bool CBasePropDoor::IsPlayerOpening() -{ - return ( GetActivator() && GetActivator()->IsPlayer() ); -} - -inline bool CBasePropDoor::IsOpener(CBaseEntity *pEnt) -{ - return ( GetActivator() == pEnt ); -} - -#endif // BASEPROPDOOR_H diff --git a/game/server/CRagdollMagnet.cpp b/game/server/CRagdollMagnet.cpp deleted file mode 100644 index 861be05e1..000000000 --- a/game/server/CRagdollMagnet.cpp +++ /dev/null @@ -1,222 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "game.h" -#include "CRagdollMagnet.h" -#include "cplane.h" - -ConVar ai_debug_ragdoll_magnets( "ai_debug_ragdoll_magnets", "0"); - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -LINK_ENTITY_TO_CLASS( phys_ragdollmagnet, CRagdollMagnet ); -BEGIN_DATADESC( CRagdollMagnet ) - DEFINE_KEYFIELD( m_radius, FIELD_FLOAT, "radius" ), - DEFINE_KEYFIELD( m_force, FIELD_FLOAT, "force" ), - DEFINE_KEYFIELD( m_axis, FIELD_VECTOR, "axis" ), - DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CRagdollMagnet::InputEnable( inputdata_t &inputdata ) -{ - Enable( true ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CRagdollMagnet::InputDisable( inputdata_t &inputdata ) -{ - Enable( false ); -} - -//----------------------------------------------------------------------------- -// Purpose: Find the ragdoll magnet entity that should pull this entity's ragdoll -// Input : *pNPC - the npc that's dying -// Output : CRagdollMagnet - the magnet that's best to use. -// -// NOTES: -// -// The nearest ragdoll magnet pulls me in IF: -// - Present -// - I'm within the magnet's RADIUS -// - LATER: There is clear line of sight from my center to the magnet -// - LATER: I'm not flagged to ignore ragdoll magnets -// - LATER: The magnet is not turned OFF -//----------------------------------------------------------------------------- -CRagdollMagnet *CRagdollMagnet::FindBestMagnet( CBaseEntity *pNPC ) -{ - CRagdollMagnet *pMagnet = NULL; - CRagdollMagnet *pBestMagnet; - - float flClosestDist; - - // Assume we won't find one. - pBestMagnet = NULL; - flClosestDist = FLT_MAX; - - do - { - pMagnet = (CRagdollMagnet *)gEntList.FindEntityByClassname( pMagnet, "phys_ragdollmagnet" ); - - if( pMagnet && pMagnet->IsEnabled() ) - { - if( pMagnet->m_target != NULL_STRING ) - { - // if this magnet has a target, only affect that target! - if( pNPC->GetEntityName() == pMagnet->m_target ) - { - return pMagnet; - } - else - { - continue; - } - } - - float flDist; - flDist = pMagnet->DistToPoint( pNPC->WorldSpaceCenter() ); - - if( flDist < flClosestDist && flDist <= pMagnet->GetRadius() ) - { - // This is the closest magnet that can pull this npc. - flClosestDist = flDist; - pBestMagnet = pMagnet; - } - } - - } while( pMagnet ); - - return pBestMagnet; -} - -//----------------------------------------------------------------------------- -// Purpose: Get the force that we should add to this NPC's ragdoll. -// Input : *pNPC - -// Output : Vector -// -// NOTE: This function assumes pNPC is within this magnet's radius. -//----------------------------------------------------------------------------- -Vector CRagdollMagnet::GetForceVector( CBaseEntity *pNPC ) -{ - Vector vecForceToApply; - - if( IsBarMagnet() ) - { - CPlane axis; - Vector vecForceDir; - Vector vecClosest; - - CalcClosestPointOnLineSegment( pNPC->WorldSpaceCenter(), GetAbsOrigin(), m_axis, vecClosest, NULL ); - - vecForceDir = (vecClosest - pNPC->WorldSpaceCenter() ); - VectorNormalize( vecForceDir ); - - vecForceToApply = vecForceDir * m_force; - } - else - { - Vector vecForce; - - vecForce = GetAbsOrigin() - pNPC->WorldSpaceCenter(); - VectorNormalize( vecForce ); - - vecForceToApply = vecForce * m_force; - } - - if( ai_debug_ragdoll_magnets.GetBool() ) - { - IPhysicsObject *pPhysObject; - - pPhysObject = pNPC->VPhysicsGetObject(); - - if( pPhysObject ) - { - Msg("Ragdoll magnet adding %f inches/sec to %s\n", m_force/pPhysObject->GetMass(), pNPC->GetClassname() ); - } - } - - return vecForceToApply; -} - -//----------------------------------------------------------------------------- -// Purpose: How far away is this point? This is different for point and bar magnets -// Input : &vecPoint - the point -// Output : float - the dist -//----------------------------------------------------------------------------- -float CRagdollMagnet::DistToPoint( const Vector &vecPoint ) -{ - if( IsBarMagnet() ) - { - // I'm a bar magnet, so the point's distance is really the plane constant. - // A bar magnet is a cylinder who's length is AbsOrigin() to m_axis, and whose - // diameter is m_radius. - - // first we build two planes. The TOP and BOTTOM planes. - // the idea is that vecPoint must be on the right side of both - // planes to be affected by this particular magnet. - // TOP and BOTTOM planes can be visualized as the 'caps' of the cylinder - // that describes the bar magnet, and they point towards each other. - // We're making sure vecPoint is between the caps. - Vector vecAxis; - - vecAxis = GetAxisVector(); - VectorNormalize( vecAxis ); - - CPlane top, bottom; - - bottom.InitializePlane( -vecAxis, m_axis ); - top.InitializePlane( vecAxis, GetAbsOrigin() ); - - if( top.PointInFront( vecPoint ) && bottom.PointInFront( vecPoint ) ) - { - // This point is between the two caps, so calculate the distance - // of vecPoint from the axis of the bar magnet - CPlane axis; - Vector vecUp; - Vector vecRight; - - // Horizontal and Vertical distances. - float hDist, vDist; - - // Need to get a vector that's right-hand to m_axis - VectorVectors( vecAxis, vecRight, vecUp ); - - //CrossProduct( vecAxis, vecUp, vecRight ); - //VectorNormalize( vecRight ); - //VectorNormalize( vecUp ); - - // Set up the plane to measure horizontal dist. - axis.InitializePlane( vecRight, GetAbsOrigin() ); - hDist = fabs( axis.PointDist( vecPoint ) ); - - axis.InitializePlane( vecUp, GetAbsOrigin() ); - vDist = fabs( axis.PointDist( vecPoint ) ); - - return MAX( hDist, vDist ); - } - else - { - return FLT_MAX; - } - } - else - { - // I'm a point magnet. Just return dist - return ( GetAbsOrigin() - vecPoint ).Length(); - } -} diff --git a/game/server/CRagdollMagnet.h b/game/server/CRagdollMagnet.h deleted file mode 100644 index 673a96aeb..000000000 --- a/game/server/CRagdollMagnet.h +++ /dev/null @@ -1,45 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Used to influence the initial force for a dying NPC's ragdoll. -// Passive entity. Just represents position in the world, radius, force -// -// $NoKeywords: $ -//=============================================================================// -#pragma once - -#ifndef CRAGDOLLMAGNET_H -#define CRAGDOLLMAGNET_H - -#define SF_RAGDOLLMAGNET_BAR 0x00000002 // this is a bar magnet. - -class CRagdollMagnet : public CPointEntity -{ -public: - DECLARE_CLASS( CRagdollMagnet, CPointEntity ); - DECLARE_DATADESC(); - - Vector GetForceVector( CBaseEntity *pNPC ); - float GetRadius( void ) { return m_radius; } - Vector GetAxisVector( void ) { return m_axis - GetAbsOrigin(); } - float DistToPoint( const Vector &vecPoint ); - - bool IsEnabled( void ) { return !m_bDisabled; } - - int IsBarMagnet( void ) { return (m_spawnflags & SF_RAGDOLLMAGNET_BAR); } - - static CRagdollMagnet *FindBestMagnet( CBaseEntity *pNPC ); - - void Enable( bool bEnable ) { m_bDisabled = !bEnable; } - - // Inputs - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - -private: - bool m_bDisabled; - float m_radius; - float m_force; - Vector m_axis; -}; - -#endif //CRAGDOLLMAGNET_H diff --git a/game/server/CommentarySystem.cpp b/game/server/CommentarySystem.cpp deleted file mode 100644 index f891a4f8e..000000000 --- a/game/server/CommentarySystem.cpp +++ /dev/null @@ -1,1651 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: The system for handling director's commentary style production info in-game. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -#ifndef _XBOX -#include "tier0/icommandline.h" -#include "igamesystem.h" -#include "filesystem.h" -#include -#include "in_buttons.h" -#include "engine/IEngineSound.h" -#include "soundenvelope.h" -#include "utldict.h" -#include "isaverestore.h" -#include "eventqueue.h" -#include "saverestore_utlvector.h" -#include "GameStats.h" -#include "ai_basenpc.h" -#include "Sprite.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -static bool g_bTracingVsCommentaryNodes = false; -static const char *s_pCommentaryUpdateViewThink = "CommentaryUpdateViewThink"; - -#define COMMENTARY_SPAWNED_SEMAPHORE "commentary_semaphore" - -extern ConVar commentary; -ConVar commentary_available("commentary_available", "0", FCVAR_NONE, "Automatically set by the game when a commentary file is available for the current map." ); - -enum teleport_stages_t -{ - TELEPORT_NONE, - TELEPORT_FADEOUT, - TELEPORT_TELEPORT, - TELEPORT_FADEIN, -}; - -// Convar restoration save/restore -#define MAX_MODIFIED_CONVAR_STRING 128 -struct modifiedconvars_t -{ - DECLARE_SIMPLE_DATADESC(); - - char pszConvar[MAX_MODIFIED_CONVAR_STRING]; - char pszCurrentValue[MAX_MODIFIED_CONVAR_STRING]; - char pszOrgValue[MAX_MODIFIED_CONVAR_STRING]; -}; - -bool g_bInCommentaryMode = false; -bool IsInCommentaryMode( void ) -{ - return g_bInCommentaryMode; -} - -//----------------------------------------------------------------------------- -// Purpose: An entity that marks a spot for a piece of commentary -//----------------------------------------------------------------------------- -class CPointCommentaryNode : public CBaseAnimating -{ - DECLARE_CLASS( CPointCommentaryNode, CBaseAnimating ); -public: - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - void Spawn( void ); - void Precache( void ); - void Activate( void ); - void SpinThink( void ); - void StartCommentary( void ); - void FinishCommentary( bool bBlendOut = true ); - void CleanupPostCommentary( void ); - void UpdateViewThink( void ); - void UpdateViewPostThink( void ); - bool TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ); - bool HasViewTarget( void ) { return (m_hViewTarget != NULL || m_hViewPosition.Get() != NULL); } - bool PreventsMovement( void ); - bool CannotBeStopped( void ) { return (m_bUnstoppable || m_bPreventChangesWhileMoving); } - int UpdateTransmitState( void ); - void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ); - void SetDisabled( bool bDisabled ); - void SetNodeNumber( int iCount ) { m_iNodeNumber = iCount; } - - // Called to tell the node when it's moved under/not-under the player's crosshair - void SetUnderCrosshair( bool bUnderCrosshair ); - - // Called when the player attempts to activate the node - void PlayerActivated( void ); - void StopPlaying( void ); - void AbortPlaying( void ); - void TeleportTo( CBasePlayer *pPlayer ); - bool CanTeleportTo( void ); - - // Inputs - void InputStartCommentary( inputdata_t &inputdata ); - void InputStartUnstoppableCommentary( inputdata_t &inputdata ); - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - -private: - string_t m_iszPreCommands; - string_t m_iszPostCommands; - CNetworkVar( string_t, m_iszCommentaryFile ); - CNetworkVar( string_t, m_iszCommentaryFileNoHDR ); - string_t m_iszViewTarget; - EHANDLE m_hViewTarget; - EHANDLE m_hViewTargetAngles; // Entity used to blend view angles to look at the target - string_t m_iszViewPosition; - CNetworkVar( EHANDLE, m_hViewPosition ); - EHANDLE m_hViewPositionMover; // Entity used to blend the view to the viewposition entity - bool m_bPreventMovement; - bool m_bUnderCrosshair; - bool m_bUnstoppable; - float m_flFinishedTime; - Vector m_vecFinishOrigin; - QAngle m_vecOriginalAngles; - QAngle m_vecFinishAngles; - bool m_bPreventChangesWhileMoving; - bool m_bDisabled; - Vector m_vecTeleportOrigin; - - COutputEvent m_pOnCommentaryStarted; - COutputEvent m_pOnCommentaryStopped; - - CNetworkVar( bool, m_bActive ); - CNetworkVar( float, m_flStartTime ); - CNetworkVar( string_t, m_iszSpeakers ); - CNetworkVar( int, m_iNodeNumber ); - CNetworkVar( int, m_iNodeNumberMax ); -}; - -BEGIN_DATADESC( CPointCommentaryNode ) - DEFINE_KEYFIELD( m_iszPreCommands, FIELD_STRING, "precommands" ), - DEFINE_KEYFIELD( m_iszPostCommands, FIELD_STRING, "postcommands" ), - DEFINE_KEYFIELD( m_iszCommentaryFile, FIELD_STRING, "commentaryfile" ), - DEFINE_KEYFIELD( m_iszCommentaryFileNoHDR, FIELD_STRING, "commentaryfile_nohdr" ), - DEFINE_KEYFIELD( m_iszViewTarget, FIELD_STRING, "viewtarget" ), - DEFINE_FIELD( m_hViewTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_hViewTargetAngles, FIELD_EHANDLE ), - DEFINE_KEYFIELD( m_iszViewPosition, FIELD_STRING, "viewposition" ), - DEFINE_FIELD( m_hViewPosition, FIELD_EHANDLE ), - DEFINE_FIELD( m_hViewPositionMover, FIELD_EHANDLE ), - DEFINE_KEYFIELD( m_bPreventMovement, FIELD_BOOLEAN, "prevent_movement" ), - DEFINE_FIELD( m_bUnderCrosshair, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bUnstoppable, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flFinishedTime, FIELD_TIME ), - DEFINE_FIELD( m_vecFinishOrigin, FIELD_VECTOR ), - DEFINE_FIELD( m_vecOriginalAngles, FIELD_VECTOR ), - DEFINE_FIELD( m_vecFinishAngles, FIELD_VECTOR ), - DEFINE_FIELD( m_bActive, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flStartTime, FIELD_TIME ), - DEFINE_KEYFIELD( m_iszSpeakers, FIELD_STRING, "speakers" ), - DEFINE_FIELD( m_iNodeNumber, FIELD_INTEGER ), - DEFINE_FIELD( m_iNodeNumberMax, FIELD_INTEGER ), - DEFINE_FIELD( m_bPreventChangesWhileMoving, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "start_disabled" ), - DEFINE_KEYFIELD( m_vecTeleportOrigin, FIELD_VECTOR, "teleport_origin" ), - - // Outputs - DEFINE_OUTPUT( m_pOnCommentaryStarted, "OnCommentaryStarted" ), - DEFINE_OUTPUT( m_pOnCommentaryStopped, "OnCommentaryStopped" ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "StartCommentary", InputStartCommentary ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartUnstoppableCommentary", InputStartUnstoppableCommentary ), - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - - // Functions - DEFINE_THINKFUNC( SpinThink ), - DEFINE_THINKFUNC( UpdateViewThink ), - DEFINE_THINKFUNC( UpdateViewPostThink ), -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CPointCommentaryNode, DT_PointCommentaryNode ) - SendPropBool( SENDINFO(m_bActive) ), - SendPropStringT( SENDINFO(m_iszCommentaryFile) ), - SendPropStringT( SENDINFO(m_iszCommentaryFileNoHDR) ), - SendPropTime( SENDINFO(m_flStartTime) ), - SendPropStringT( SENDINFO(m_iszSpeakers) ), - SendPropInt( SENDINFO(m_iNodeNumber), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_iNodeNumberMax), 8, SPROP_UNSIGNED ), - SendPropEHandle( SENDINFO(m_hViewPosition) ), -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( point_commentary_node, CPointCommentaryNode ); - -//----------------------------------------------------------------------------- -// Laser Dot -//----------------------------------------------------------------------------- -class CCommentaryViewPosition : public CSprite -{ - DECLARE_CLASS( CCommentaryViewPosition, CSprite ); -public: - virtual void Spawn( void ) - { - Precache(); - SetModelName( MAKE_STRING("sprites/redglow1.vmt") ); - - BaseClass::Spawn(); - - SetMoveType( MOVETYPE_NONE ); - AddSolidFlags( FSOLID_NOT_SOLID ); - AddEffects( EF_NOSHADOW ); - UTIL_SetSize( this, vec3_origin, vec3_origin ); - } - - virtual void Precache( void ) - { - PrecacheModel( "sprites/redglow1.vmt" ); - } -}; - -LINK_ENTITY_TO_CLASS( point_commentary_viewpoint, CCommentaryViewPosition ); - -//----------------------------------------------------------------------------- -// Purpose: In multiplayer, always return player 1 -//----------------------------------------------------------------------------- -CBasePlayer *GetCommentaryPlayer( void ) -{ - CBasePlayer *pPlayer; - - if ( gpGlobals->maxClients <= 1 ) - { - pPlayer = UTIL_GetLocalPlayer(); - } - else - { - // only respond to the first player - pPlayer = UTIL_PlayerByIndex(1); - } - - return pPlayer; -} - -//=========================================================================================================== -// COMMENTARY GAME SYSTEM -//=========================================================================================================== -void CV_GlobalChange_Commentary( IConVar *var, const char *pOldString, float flOldValue ); - -//----------------------------------------------------------------------------- -// Purpose: Game system to kickstart the director's commentary -//----------------------------------------------------------------------------- -class CCommentarySystem : public CAutoGameSystemPerFrame -{ -public: - DECLARE_DATADESC(); - - CCommentarySystem() : CAutoGameSystemPerFrame( "CCommentarySystem" ) - { - m_iCommentaryNodeCount = 0; - } - - virtual void LevelInitPreEntity() - { - m_hCurrentNode = NULL; - m_bCommentaryConvarsChanging = false; - m_iClearPressedButtons = 0; - - // If the map started via the map_commentary cmd, start in commentary - g_bInCommentaryMode = (engine->IsInCommentaryMode() != 0); - - CalculateCommentaryState(); - } - - void CalculateCommentaryState( void ) - { - // Set the available cvar if we can find commentary data for this level - char szFullName[512]; - Q_snprintf(szFullName,sizeof(szFullName), "maps/%s_commentary.txt", STRING( gpGlobals->mapname) ); - if ( filesystem->FileExists( szFullName ) ) - { - commentary_available.SetValue( true ); - - // If the user wanted commentary, kick it on - if ( commentary.GetBool() ) - { - g_bInCommentaryMode = true; - } - } - else - { - g_bInCommentaryMode = false; - commentary_available.SetValue( false ); - } - } - - virtual void LevelShutdownPreEntity() - { - ShutDownCommentary(); - } - - void ParseEntKVBlock( CBaseEntity *pNode, KeyValues *pkvNode ) - { - KeyValues *pkvNodeData = pkvNode->GetFirstSubKey(); - while ( pkvNodeData ) - { - // Handle the connections block - if ( !Q_strcmp(pkvNodeData->GetName(), "connections") ) - { - ParseEntKVBlock( pNode, pkvNodeData ); - } - else - { - #define COMMENTARY_STRING_LENGTH_MAX 1024 - - const char *pszValue = pkvNodeData->GetString(); - Assert( Q_strlen(pszValue) < COMMENTARY_STRING_LENGTH_MAX ); - if ( Q_strnchr(pszValue, '^', COMMENTARY_STRING_LENGTH_MAX) ) - { - // We want to support quotes in our strings so that we can specify multiple parameters in - // an output inside our commentary files. We convert ^s to "s here. - char szTmp[COMMENTARY_STRING_LENGTH_MAX]; - Q_strncpy( szTmp, pszValue, COMMENTARY_STRING_LENGTH_MAX ); - int len = Q_strlen( szTmp ); - for ( int i = 0; i < len; i++ ) - { - if ( szTmp[i] == '^' ) - { - szTmp[i] = '"'; - } - } - - pNode->KeyValue( pkvNodeData->GetName(), szTmp ); - } - else - { - pNode->KeyValue( pkvNodeData->GetName(), pszValue ); - } - } - - pkvNodeData = pkvNodeData->GetNextKey(); - } - } - - virtual void LevelInitPostEntity( void ) - { - if ( !IsInCommentaryMode() ) - return; - - // Don't spawn commentary entities when loading a savegame - if ( gpGlobals->eLoadType == MapLoad_LoadGame || gpGlobals->eLoadType == MapLoad_Background ) - return; - - m_bCommentaryEnabledMidGame = false; - InitCommentary(); - - IGameEvent *event = gameeventmanager->CreateEvent( "playing_commentary" ); - gameeventmanager->FireEventClientSide( event ); - } - - CPointCommentaryNode *GetNodeUnderCrosshair() - { - CBasePlayer *pPlayer = GetCommentaryPlayer(); - if ( !pPlayer ) - return NULL; - - // See if the player's looking at a commentary node - trace_t tr; - Vector vecSrc = pPlayer->EyePosition(); - Vector vecForward = pPlayer->GetAutoaimVector( AUTOAIM_SCALE_DIRECT_ONLY ); - - g_bTracingVsCommentaryNodes = true; - UTIL_TraceLine( vecSrc, vecSrc + vecForward * MAX_TRACE_LENGTH, MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &tr ); - g_bTracingVsCommentaryNodes = false; - - if ( !tr.m_pEnt ) - return NULL; - - return dynamic_cast(tr.m_pEnt); - } - - void PrePlayerRunCommand( CBasePlayer *pPlayer, CUserCmd *pUserCmds ) - { - if ( !IsInCommentaryMode() ) - return; - - if ( pPlayer->IsFakeClient() ) - return; - - CPointCommentaryNode *pCurrentNode = GetNodeUnderCrosshair(); - - // Changed nodes? - if ( m_hCurrentNode != pCurrentNode ) - { - // Stop animating the old one - if ( m_hCurrentNode.Get() ) - { - m_hCurrentNode->SetUnderCrosshair( false ); - } - - // Start animating the new one - if ( pCurrentNode ) - { - pCurrentNode->SetUnderCrosshair( true ); - } - - m_hCurrentNode = pCurrentNode; - } - - // Check for commentary node activations - if ( pPlayer ) - { - // Has the player pressed down an attack button? - int buttonsChanged = m_afPlayersLastButtons ^ pUserCmds->buttons; - int buttonsPressed = buttonsChanged & pUserCmds->buttons; - m_afPlayersLastButtons = pUserCmds->buttons; - - if ( !(pUserCmds->buttons & COMMENTARY_BUTTONS) ) - { - m_iClearPressedButtons &= ~COMMENTARY_BUTTONS; - } - - // Detect press events to start/stop commentary nodes - if (buttonsPressed & COMMENTARY_BUTTONS) - { - if ( buttonsPressed & IN_ATTACK2 ) - { - if ( !(GetActiveNode() && GetActiveNode()->CannotBeStopped()) ) - { - JumpToNextNode( pPlayer ); - pUserCmds->buttons &= ~COMMENTARY_BUTTONS; - m_iClearPressedButtons |= (buttonsPressed & COMMENTARY_BUTTONS); - } - } - else - { - // Looking at a node? - if ( m_hCurrentNode ) - { - // Ignore input while an unstoppable node is playing - if ( !GetActiveNode() || !GetActiveNode()->CannotBeStopped() ) - { - // If we have an active node already, stop it - if ( GetActiveNode() && GetActiveNode() != m_hCurrentNode ) - { - GetActiveNode()->StopPlaying(); - } - - m_hCurrentNode->PlayerActivated(); - } - - // Prevent weapon firing when toggling nodes - pUserCmds->buttons &= ~COMMENTARY_BUTTONS; - m_iClearPressedButtons |= (buttonsPressed & COMMENTARY_BUTTONS); - } - else if ( GetActiveNode() && GetActiveNode()->HasViewTarget() ) - { - if ( !GetActiveNode()->CannotBeStopped() ) - { - GetActiveNode()->StopPlaying(); - } - - // Prevent weapon firing when toggling nodes - pUserCmds->buttons &= ~COMMENTARY_BUTTONS; - m_iClearPressedButtons |= (buttonsPressed & COMMENTARY_BUTTONS); - } - } - } - - if ( GetActiveNode() && GetActiveNode()->PreventsMovement() ) - { - pUserCmds->buttons &= ~(IN_FORWARD | IN_BACK | IN_MOVELEFT | IN_MOVERIGHT | IN_JUMP | IN_DUCK ); - pUserCmds->upmove = 0; - pUserCmds->sidemove = 0; - pUserCmds->forwardmove = 0; - } - - // When we swallow button down events, we have to keep clearing that button - // until the player releases the button. Otherwise, the frame after we swallow - // it, the code detects the button down and goes ahead as normal. - pUserCmds->buttons &= ~m_iClearPressedButtons; - } - - if ( m_iTeleportStage != TELEPORT_NONE ) - { - if ( m_flNextTeleportTime <= gpGlobals->curtime ) - { - if ( m_iTeleportStage == TELEPORT_FADEOUT ) - { - m_iTeleportStage = TELEPORT_TELEPORT; - m_flNextTeleportTime = gpGlobals->curtime + 0.35; - - color32_s clr = { 0,0,0,255 }; - UTIL_ScreenFade( pPlayer, clr, 0.3, 0, FFADE_OUT | FFADE_PURGE | FFADE_STAYOUT ); - } - else if ( m_iTeleportStage == TELEPORT_TELEPORT ) - { - if ( m_hLastCommentaryNode ) - { - m_hLastCommentaryNode->TeleportTo( pPlayer ); - } - - m_iTeleportStage = TELEPORT_FADEIN; - m_flNextTeleportTime = gpGlobals->curtime + 0.6; - } - else if ( m_iTeleportStage == TELEPORT_FADEIN ) - { - m_iTeleportStage = TELEPORT_NONE; - m_flNextTeleportTime = gpGlobals->curtime + 0.25; - - color32_s clr = { 0,0,0,255 }; - UTIL_ScreenFade( pPlayer, clr, 0.3, 0, FFADE_IN | FFADE_PURGE ); - } - } - } - } - - CPointCommentaryNode *GetActiveNode( void ) - { - return m_hActiveCommentaryNode; - } - - void SetActiveNode( CPointCommentaryNode *pNode ) - { - m_hActiveCommentaryNode = pNode; - if ( pNode ) - { - m_hLastCommentaryNode = pNode; - } - } - - int GetCommentaryNodeCount( void ) - { - return m_iCommentaryNodeCount; - } - - bool CommentaryConvarsChanging( void ) - { - return m_bCommentaryConvarsChanging; - } - - void SetCommentaryConvarsChanging( bool bChanging ) - { - m_bCommentaryConvarsChanging = bChanging; - } - - void ConvarChanged( IConVar *pConVar, const char *pOldString, float flOldValue ) - { - ConVarRef var( pConVar ); - - // A convar has been changed by a commentary node. We need to store - // the old state. If the engine shuts down, we need to restore any - // convars that the commentary changed to their previous values. - for ( int i = 0; i < m_ModifiedConvars.Count(); i++ ) - { - // If we find it, just update the current value - if ( !Q_strncmp( var.GetName(), m_ModifiedConvars[i].pszConvar, MAX_MODIFIED_CONVAR_STRING ) ) - { - Q_strncpy( m_ModifiedConvars[i].pszCurrentValue, var.GetString(), MAX_MODIFIED_CONVAR_STRING ); - //Msg(" Updating Convar %s: value %s (org %s)\n", m_ModifiedConvars[i].pszConvar, m_ModifiedConvars[i].pszCurrentValue, m_ModifiedConvars[i].pszOrgValue ); - return; - } - } - - // We didn't find it in our list, so add it - modifiedconvars_t newConvar; - Q_strncpy( newConvar.pszConvar, var.GetName(), MAX_MODIFIED_CONVAR_STRING ); - Q_strncpy( newConvar.pszCurrentValue, var.GetString(), MAX_MODIFIED_CONVAR_STRING ); - Q_strncpy( newConvar.pszOrgValue, pOldString, MAX_MODIFIED_CONVAR_STRING ); - m_ModifiedConvars.AddToTail( newConvar ); - - /* - Msg(" Commentary changed '%s' to '%s' (was '%s')\n", var->GetName(), var->GetString(), pOldString ); - Msg(" Convars stored: %d\n", m_ModifiedConvars.Count() ); - for ( int i = 0; i < m_ModifiedConvars.Count(); i++ ) - { - Msg(" Convar %d: %s, value %s (org %s)\n", i, m_ModifiedConvars[i].pszConvar, m_ModifiedConvars[i].pszCurrentValue, m_ModifiedConvars[i].pszOrgValue ); - } - */ - } - - void InitCommentary( void ) - { - // Install the global cvar callback - cvar->InstallGlobalChangeCallback( CV_GlobalChange_Commentary ); - - m_flNextTeleportTime = 0; - m_iTeleportStage = TELEPORT_NONE; - m_hLastCommentaryNode = NULL; - - // If we find the commentary semaphore, the commentary entities already exist. - // This occurs when you transition back to a map that has saved commentary nodes in it. - if ( gEntList.FindEntityByName( NULL, COMMENTARY_SPAWNED_SEMAPHORE ) ) - return; - - // Spawn the commentary semaphore entity - CBaseEntity *pSemaphore = CreateEntityByName( "info_target" ); - pSemaphore->SetName( MAKE_STRING(COMMENTARY_SPAWNED_SEMAPHORE) ); - - bool oldLock = engine->LockNetworkStringTables( false ); - - // Find the commentary file - char szFullName[512]; - Q_snprintf(szFullName,sizeof(szFullName), "maps/%s_commentary.txt", STRING( gpGlobals->mapname )); - KeyValues *pkvFile = new KeyValues( "Commentary" ); - if ( pkvFile->LoadFromFile( filesystem, szFullName, "MOD" ) ) - { - Msg( "Commentary: Loading commentary data from %s. \n", szFullName ); - - // Load each commentary block, and spawn the entities - KeyValues *pkvNode = pkvFile->GetFirstSubKey(); - while ( pkvNode ) - { - // Get node name - const char *pNodeName = pkvNode->GetName(); - - // Skip the trackinfo - if ( !Q_strncmp( pNodeName, "trackinfo", 9 ) ) - { - pkvNode = pkvNode->GetNextKey(); - continue; - } - - KeyValues *pClassname = pkvNode->FindKey( "classname" ); - if ( pClassname ) - { - // Use the classname instead - pNodeName = pClassname->GetString(); - } - - // Spawn the commentary entity - CBaseEntity *pNode = CreateEntityByName( pNodeName ); - if ( pNode ) - { - ParseEntKVBlock( pNode, pkvNode ); - DispatchSpawn( pNode ); - - EHANDLE hHandle; - hHandle = pNode; - m_hSpawnedEntities.AddToTail( hHandle ); - - CPointCommentaryNode *pCommNode = dynamic_cast(pNode); - if ( pCommNode ) - { - m_iCommentaryNodeCount++; - pCommNode->SetNodeNumber( m_iCommentaryNodeCount ); - } - } - else - { - Warning("Commentary: Failed to spawn commentary entity, type: '%s'\n", pNodeName ); - } - - // Move to next entity - pkvNode = pkvNode->GetNextKey(); - } - - // Then activate all the entities - for ( int i = 0; i < m_hSpawnedEntities.Count(); i++ ) - { - m_hSpawnedEntities[i]->Activate(); - } - } - else - { - Msg( "Commentary: Could not find commentary data file '%s'. \n", szFullName ); - } - - engine->LockNetworkStringTables( oldLock ); - } - - void ShutDownCommentary( void ) - { - if ( GetActiveNode() ) - { - GetActiveNode()->AbortPlaying(); - } - - // Destroy all the entities created by commentary - for ( int i = m_hSpawnedEntities.Count()-1; i >= 0; i-- ) - { - if ( m_hSpawnedEntities[i] ) - { - UTIL_Remove( m_hSpawnedEntities[i] ); - } - } - m_hSpawnedEntities.Purge(); - m_iCommentaryNodeCount = 0; - - // Remove the commentary semaphore - CBaseEntity *pSemaphore = gEntList.FindEntityByName( NULL, COMMENTARY_SPAWNED_SEMAPHORE ); - if ( pSemaphore ) - { - UTIL_Remove( pSemaphore ); - } - - // Remove our global convar callback - cvar->RemoveGlobalChangeCallback( CV_GlobalChange_Commentary ); - - // Reset any convars that have been changed by the commentary - for ( int i = 0; i < m_ModifiedConvars.Count(); i++ ) - { - ConVar *pConVar = (ConVar *)cvar->FindVar( m_ModifiedConvars[i].pszConvar ); - if ( pConVar ) - { - pConVar->SetValue( m_ModifiedConvars[i].pszOrgValue ); - } - } - m_ModifiedConvars.Purge(); - - m_hCurrentNode = NULL; - m_hActiveCommentaryNode = NULL; - m_hLastCommentaryNode = NULL; - m_flNextTeleportTime = 0; - m_iTeleportStage = TELEPORT_NONE; - } - - void SetCommentaryMode( bool bCommentaryMode ) - { - g_bInCommentaryMode = bCommentaryMode; - CalculateCommentaryState(); - - // If we're turning on commentary, create all the entities. - if ( IsInCommentaryMode() ) - { - m_bCommentaryEnabledMidGame = true; - InitCommentary(); - } - else - { - ShutDownCommentary(); - } - } - - void OnRestore( void ) - { - cvar->RemoveGlobalChangeCallback( CV_GlobalChange_Commentary ); - - if ( !IsInCommentaryMode() ) - return; - - // Set any convars that have already been changed by the commentary before the save - for ( int i = 0; i < m_ModifiedConvars.Count(); i++ ) - { - ConVar *pConVar = (ConVar *)cvar->FindVar( m_ModifiedConvars[i].pszConvar ); - if ( pConVar ) - { - //Msg(" Restoring Convar %s: value %s (org %s)\n", m_ModifiedConvars[i].pszConvar, m_ModifiedConvars[i].pszCurrentValue, m_ModifiedConvars[i].pszOrgValue ); - pConVar->SetValue( m_ModifiedConvars[i].pszCurrentValue ); - } - } - - // Install the global cvar callback - cvar->InstallGlobalChangeCallback( CV_GlobalChange_Commentary ); - } - - bool CommentaryWasEnabledMidGame( void ) - { - return m_bCommentaryEnabledMidGame; - } - - void JumpToNextNode( CBasePlayer *pPlayer ) - { - if ( m_flNextTeleportTime > gpGlobals->curtime || m_iTeleportStage != TELEPORT_NONE ) - return; - - CBaseEntity *pEnt = m_hLastCommentaryNode; - while ( ( pEnt = gEntList.FindEntityByClassname( pEnt, "point_commentary_node" ) ) != m_hLastCommentaryNode ) - { - CPointCommentaryNode *pNode = dynamic_cast( pEnt ); - if ( pNode && pNode->CanTeleportTo() ) - { - m_iTeleportStage = TELEPORT_FADEOUT; - m_hLastCommentaryNode = pNode; - m_flNextTeleportTime = gpGlobals->curtime; - - // Stop any active nodes - if ( m_hActiveCommentaryNode ) - { - m_hActiveCommentaryNode->StopPlaying(); - } - break; - } - } - } - -private: - int m_afPlayersLastButtons; - int m_iCommentaryNodeCount; - bool m_bCommentaryConvarsChanging; - int m_iClearPressedButtons; - bool m_bCommentaryEnabledMidGame; - float m_flNextTeleportTime; - int m_iTeleportStage; - - CUtlVector< modifiedconvars_t > m_ModifiedConvars; - CUtlVector m_hSpawnedEntities; - CHandle m_hCurrentNode; - CHandle m_hActiveCommentaryNode; - CHandle m_hLastCommentaryNode; -}; - -CCommentarySystem g_CommentarySystem; - -void CommentarySystem_PePlayerRunCommand( CBasePlayer *player, CUserCmd *ucmd ) -{ - g_CommentarySystem.PrePlayerRunCommand( player, ucmd ); -} - -BEGIN_DATADESC_NO_BASE( CCommentarySystem ) - //int m_afPlayersLastButtons; DON'T SAVE - //bool m_bCommentaryConvarsChanging; DON'T SAVE - //int m_iClearPressedButtons; DON'T SAVE - - DEFINE_FIELD( m_bCommentaryEnabledMidGame, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flNextTeleportTime, FIELD_TIME ), - DEFINE_FIELD( m_iTeleportStage, FIELD_INTEGER ), - - DEFINE_UTLVECTOR( m_ModifiedConvars, FIELD_EMBEDDED ), - DEFINE_UTLVECTOR( m_hSpawnedEntities, FIELD_EHANDLE ), - DEFINE_FIELD( m_hCurrentNode, FIELD_EHANDLE ), - DEFINE_FIELD( m_hActiveCommentaryNode, FIELD_EHANDLE ), - DEFINE_FIELD( m_hLastCommentaryNode, FIELD_EHANDLE ), - DEFINE_FIELD( m_iCommentaryNodeCount, FIELD_INTEGER ), -END_DATADESC() - -BEGIN_SIMPLE_DATADESC( modifiedconvars_t ) - DEFINE_ARRAY( pszConvar, FIELD_CHARACTER, MAX_MODIFIED_CONVAR_STRING ), - DEFINE_ARRAY( pszCurrentValue, FIELD_CHARACTER, MAX_MODIFIED_CONVAR_STRING ), - DEFINE_ARRAY( pszOrgValue, FIELD_CHARACTER, MAX_MODIFIED_CONVAR_STRING ), -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CC_CommentaryChanged( IConVar *pConVar, const char *pOldString, float flOldValue ) -{ - ConVarRef var( pConVar ); - if ( var.GetBool() != g_bInCommentaryMode ) - { - g_CommentarySystem.SetCommentaryMode( var.GetBool() ); - } -} -ConVar commentary("commentary", "0", FCVAR_ARCHIVE | FCVAR_ARCHIVE_XBOX, "Desired commentary mode state.", CC_CommentaryChanged ); - -//----------------------------------------------------------------------------- -// Purpose: We need to revert back any convar changes that are made by the -// commentary system during commentary. This code stores convar changes -// made by the commentary system, and reverts them when finished. -//----------------------------------------------------------------------------- -void CV_GlobalChange_Commentary( IConVar *var, const char *pOldString, float flOldValue ) -{ - if ( !g_CommentarySystem.CommentaryConvarsChanging() ) - { - // A convar has changed, but not due to commentary nodes. Ignore it. - return; - } - - g_CommentarySystem.ConvarChanged( var, pOldString, flOldValue ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CC_CommentaryNotChanging( void ) -{ - g_CommentarySystem.SetCommentaryConvarsChanging( false ); -} -static ConCommand commentary_cvarsnotchanging("commentary_cvarsnotchanging", CC_CommentaryNotChanging, 0 ); - -bool IsListeningToCommentary( void ) -{ - return ( g_CommentarySystem.GetActiveNode() != NULL ); -} - -//=========================================================================================================== -// COMMENTARY NODES -//=========================================================================================================== - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointCommentaryNode::Spawn( void ) -{ - // No model specified? - const char *szModel = (char *)STRING( GetModelName() ); - if (!szModel || !*szModel) - { - szModel = "models/extras/info_speech.mdl"; - SetModelName( AllocPooledString(szModel) ); - } - - Precache(); - SetModel( szModel ); - UTIL_SetSize( this, -Vector(16,16,16), Vector(16,16,16) ); - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST ); - AddEffects( EF_NOSHADOW ); - - // Setup for animation - ResetSequence( LookupSequence("idle") ); - SetThink( &CPointCommentaryNode::SpinThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - m_iNodeNumber = 0; - m_iNodeNumberMax = 0; - - SetDisabled( m_bDisabled ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointCommentaryNode::Activate( void ) -{ - m_iNodeNumberMax = g_CommentarySystem.GetCommentaryNodeCount(); - - if ( m_iszViewTarget != NULL_STRING ) - { - m_hViewTarget = gEntList.FindEntityByName( NULL, m_iszViewTarget ); - if ( !m_hViewTarget ) - { - Warning("%s: %s could not find viewtarget %s.\n", GetClassname(), GetDebugName(), STRING(m_iszViewTarget) ); - } - } - - if ( m_iszViewPosition != NULL_STRING ) - { - m_hViewPosition = gEntList.FindEntityByName( NULL, m_iszViewPosition ); - if ( !m_hViewPosition.Get() ) - { - Warning("%s: %s could not find viewposition %s.\n", GetClassname(), GetDebugName(), STRING(m_iszViewPosition) ); - } - } - - BaseClass::Activate(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointCommentaryNode::Precache() -{ - PrecacheModel( STRING( GetModelName() ) ); - - if ( m_iszCommentaryFile.Get() != NULL_STRING ) - { - PrecacheScriptSound( STRING( m_iszCommentaryFile.Get() ) ); - } - else - { - Warning("%s: %s has no commentary file.\n", GetClassname(), GetDebugName() ); - } - - if ( m_iszCommentaryFileNoHDR.Get() != NULL_STRING ) - { - PrecacheScriptSound( STRING( m_iszCommentaryFileNoHDR.Get() ) ); - } - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: Called to tell the node when it's moved under/not-under the player's crosshair -//----------------------------------------------------------------------------- -void CPointCommentaryNode::SetUnderCrosshair( bool bUnderCrosshair ) -{ - if ( bUnderCrosshair ) - { - // Start animating - m_bUnderCrosshair = true; - - if ( !m_bActive ) - { - m_flAnimTime = gpGlobals->curtime; - } - } - else - { - // Stop animating - m_bUnderCrosshair = false; - } -} - -//------------------------------------------------------------------------------ -// Purpose: Prevent collisions of everything except the trace from the commentary system -//------------------------------------------------------------------------------ -bool CPointCommentaryNode::TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ) -{ - if ( !g_bTracingVsCommentaryNodes ) - return false; - if ( m_bDisabled ) - return false; - - return BaseClass::TestCollision( ray, mask, trace ); -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CPointCommentaryNode::SpinThink( void ) -{ - // Rotate if we're active, or under the crosshair. Don't rotate if we're - // under the crosshair, but we've already been listened to. - if ( m_bActive || (m_bUnderCrosshair && m_nSkin == 0) ) - { - if ( m_bActive ) - { - m_flPlaybackRate = 3.0; - } - else - { - m_flPlaybackRate = 1.0; - } - StudioFrameAdvance(); - DispatchAnimEvents(this); - } - - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CPointCommentaryNode::PlayerActivated( void ) -{ - gamestats->Event_Commentary(); - - if ( m_bActive ) - { - StopPlaying(); - } - else - { - StartCommentary(); - g_CommentarySystem.SetActiveNode( this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointCommentaryNode::StopPlaying( void ) -{ - if ( m_bActive ) - { - FinishCommentary(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Stop playing the node, but snap completely out of the node. -// Used when players shut down commentary while we're in the middle -// of playing a node, so we can't smoothly blend out (since the -// commentary entities need to be removed). -//----------------------------------------------------------------------------- -void CPointCommentaryNode::AbortPlaying( void ) -{ - if ( m_bActive ) - { - FinishCommentary( false ); - } - else if ( m_bPreventChangesWhileMoving ) - { - // We're a node that's not active, but is in the process of transitioning the view. Finish movement. - CleanupPostCommentary(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CPointCommentaryNode::CanTeleportTo( void ) -{ - //return ( m_vecTeleportOrigin != vec3_origin ); - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointCommentaryNode::TeleportTo( CBasePlayer *pPlayer ) -{ - Vector vecTarget = m_vecTeleportOrigin; - if ( m_vecTeleportOrigin == vec3_origin ) - { - vecTarget = GetAbsOrigin(); - } - - trace_t trace; - UTIL_TraceHull( vecTarget, vecTarget + Vector( 0, 0, -500 ), pPlayer->WorldAlignMins(), pPlayer->WorldAlignMaxs(), MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &trace ); - - pPlayer->Teleport( &trace.endpos, NULL, &vec3_origin ); - - Vector vecToNode = GetAbsOrigin() - pPlayer->EyePosition(); - VectorNormalize( vecToNode ); - QAngle vecAngle; - VectorAngles( vecToNode, Vector(0,0,1), vecAngle ); - - pPlayer->SnapEyeAngles( vecAngle ); -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CPointCommentaryNode::StartCommentary( void ) -{ - CBasePlayer *pPlayer = GetCommentaryPlayer(); - - if ( !pPlayer ) - return; - - m_bActive = true; - - m_flAnimTime = gpGlobals->curtime; - m_flPrevAnimTime = gpGlobals->curtime; - - // Switch to the greyed out skin - m_nSkin = 1; - - m_pOnCommentaryStarted.FireOutput( this, this ); - - // Fire off our precommands - if ( m_iszPreCommands != NULL_STRING ) - { - g_CommentarySystem.SetCommentaryConvarsChanging( true ); - engine->ClientCommand( pPlayer->edict(), STRING(m_iszPreCommands) ); - engine->ClientCommand( pPlayer->edict(), "commentary_cvarsnotchanging\n" ); - } - - // Start the commentary - m_flStartTime = gpGlobals->curtime; - - // If we have a view target, start blending towards it - if ( m_hViewTarget || m_hViewPosition.Get() ) - { - m_vecOriginalAngles = pPlayer->EyeAngles(); - SetContextThink( &CPointCommentaryNode::UpdateViewThink, gpGlobals->curtime, s_pCommentaryUpdateViewThink ); - } - - //SetContextThink( &CPointCommentaryNode::FinishCommentary, gpGlobals->curtime + flDuration, s_pFinishCommentaryThink ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CC_CommentaryFinishNode( void ) -{ - // We were told by the client DLL that our commentary has finished - if ( g_CommentarySystem.GetActiveNode() ) - { - g_CommentarySystem.GetActiveNode()->StopPlaying(); - } -} -static ConCommand commentary_finishnode("commentary_finishnode", CC_CommentaryFinishNode, 0 ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointCommentaryNode::UpdateViewThink( void ) -{ - if ( !m_bActive ) - return; - CBasePlayer *pPlayer = GetCommentaryPlayer(); - if ( !pPlayer ) - return; - - // Swing the view towards the target - if ( m_hViewTarget ) - { - if ( !m_hViewTargetAngles && !m_hViewPositionMover ) - { - // Make an invisible entity to attach view angles to - m_hViewTargetAngles = CreateEntityByName( "point_commentary_viewpoint" ); - m_hViewTargetAngles->SetAbsOrigin( pPlayer->EyePosition() ); - m_hViewTargetAngles->SetAbsAngles( pPlayer->EyeAngles() ); - pPlayer->SetViewEntity( m_hViewTargetAngles ); - - if ( pPlayer->GetActiveWeapon() ) - { - pPlayer->GetActiveWeapon()->Holster(); - } - } - - QAngle angGoal; - QAngle angCurrent; - if ( m_hViewPositionMover ) - { - angCurrent = m_hViewPositionMover->GetAbsAngles(); - VectorAngles( m_hViewTarget->WorldSpaceCenter() - m_hViewPositionMover->GetAbsOrigin(), angGoal ); - } - else if ( m_hViewTargetAngles ) - { - angCurrent = m_hViewTargetAngles->GetAbsAngles(); - m_hViewTargetAngles->SetAbsOrigin( pPlayer->EyePosition() ); - VectorAngles( m_hViewTarget->WorldSpaceCenter() - m_hViewTargetAngles->GetAbsOrigin(), angGoal ); - } - else - { - angCurrent = pPlayer->EyeAngles(); - VectorAngles( m_hViewTarget->WorldSpaceCenter() - pPlayer->EyePosition(), angGoal ); - } - - // Accelerate towards the target goal angles - float dx = AngleDiff( angGoal.x, angCurrent.x ); - float dy = AngleDiff( angGoal.y, angCurrent.y ); - float mod = 1.0 - ExponentialDecay( 0.5, 0.3, gpGlobals->frametime ); - float dxmod = dx * mod; - float dymod = dy * mod; - - angCurrent.x = AngleNormalize( angCurrent.x + dxmod ); - angCurrent.y = AngleNormalize( angCurrent.y + dymod ); - - if ( m_hViewPositionMover ) - { - m_hViewPositionMover->SetAbsAngles( angCurrent ); - } - else if ( m_hViewTargetAngles ) - { - m_hViewTargetAngles->SetAbsAngles( angCurrent ); - pPlayer->SnapEyeAngles( angCurrent ); - } - else - { - pPlayer->SnapEyeAngles( angCurrent ); - } - - SetNextThink( gpGlobals->curtime, s_pCommentaryUpdateViewThink ); - } - - if ( m_hViewPosition.Get() ) - { - if ( pPlayer->GetActiveWeapon() ) - { - pPlayer->GetActiveWeapon()->Holster(); - } - - if ( !m_hViewPositionMover ) - { - // Make an invisible info target entity for us to attach the view to, - // and move it to the desired view position. - m_hViewPositionMover = CreateEntityByName( "point_commentary_viewpoint" ); - m_hViewPositionMover->SetAbsAngles( pPlayer->EyeAngles() ); - pPlayer->SetViewEntity( m_hViewPositionMover ); - } - - // Blend to the target position over time. - float flCurTime = (gpGlobals->curtime - m_flStartTime); - float flBlendPerc = clamp( flCurTime / 2.0, 0, 1 ); - - // Figure out the current view position - Vector vecCurEye; - VectorLerp( pPlayer->EyePosition(), m_hViewPosition.Get()->GetAbsOrigin(), flBlendPerc, vecCurEye ); - m_hViewPositionMover->SetAbsOrigin( vecCurEye ); - - SetNextThink( gpGlobals->curtime, s_pCommentaryUpdateViewThink ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointCommentaryNode::UpdateViewPostThink( void ) -{ - CBasePlayer *pPlayer = GetCommentaryPlayer(); - if ( !pPlayer ) - return; - - if ( m_hViewPosition.Get() && m_hViewPositionMover ) - { - // Blend back to the player's position over time. - float flCurTime = (gpGlobals->curtime - m_flFinishedTime); - float flTimeToBlend = MIN( 2.0, m_flFinishedTime - m_flStartTime ); - float flBlendPerc = 1.0 - clamp( flCurTime / flTimeToBlend, 0, 1 ); - - //Msg("OUT: CurTime %.2f, BlendTime: %.2f, Blend: %.3f\n", flCurTime, flTimeToBlend, flBlendPerc ); - - // Only do this while we're still moving - if ( flBlendPerc > 0 ) - { - // Figure out the current view position - Vector vecPlayerPos = pPlayer->EyePosition(); - Vector vecToPosition = (m_vecFinishOrigin - vecPlayerPos); - Vector vecCurEye = pPlayer->EyePosition() + (vecToPosition * flBlendPerc); - m_hViewPositionMover->SetAbsOrigin( vecCurEye ); - - if ( m_hViewTarget ) - { - Quaternion quatFinish; - Quaternion quatOriginal; - Quaternion quatCurrent; - AngleQuaternion( m_vecOriginalAngles, quatOriginal ); - AngleQuaternion( m_vecFinishAngles, quatFinish ); - QuaternionSlerp( quatFinish, quatOriginal, 1.0 - flBlendPerc, quatCurrent ); - QAngle angCurrent; - QuaternionAngles( quatCurrent, angCurrent ); - m_hViewPositionMover->SetAbsAngles( angCurrent ); - } - - SetNextThink( gpGlobals->curtime, s_pCommentaryUpdateViewThink ); - return; - } - - pPlayer->SnapEyeAngles( m_hViewPositionMover->GetAbsAngles() ); - } - - // We're done - CleanupPostCommentary(); - - m_bPreventChangesWhileMoving = false; -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CPointCommentaryNode::FinishCommentary( bool bBlendOut ) -{ - CBasePlayer *pPlayer = GetCommentaryPlayer(); - if ( !pPlayer ) - return; - - // Fire off our postcommands - if ( m_iszPostCommands != NULL_STRING ) - { - g_CommentarySystem.SetCommentaryConvarsChanging( true ); - engine->ClientCommand( pPlayer->edict(), STRING(m_iszPostCommands) ); - engine->ClientCommand( pPlayer->edict(), "commentary_cvarsnotchanging\n" ); - } - - // Stop the commentary - m_flFinishedTime = gpGlobals->curtime; - - if ( bBlendOut && m_hViewPositionMover ) - { - m_bActive = false; - m_flPlaybackRate = 1.0; - m_vecFinishOrigin = m_hViewPositionMover->GetAbsOrigin(); - m_vecFinishAngles = m_hViewPositionMover->GetAbsAngles(); - - m_bPreventChangesWhileMoving = true; - - // We've moved away from the player's position. Move back to it before ending - SetContextThink( &CPointCommentaryNode::UpdateViewPostThink, gpGlobals->curtime, s_pCommentaryUpdateViewThink ); - return; - } - - CleanupPostCommentary(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointCommentaryNode::CleanupPostCommentary( void ) -{ - CBasePlayer *pPlayer = GetCommentaryPlayer(); - if ( !pPlayer ) - return; - - if ( ( m_hViewPositionMover || m_hViewTargetAngles ) && pPlayer->GetActiveWeapon() ) - { - pPlayer->GetActiveWeapon()->Deploy(); - } - - if ( m_hViewTargetAngles && pPlayer->GetViewEntity() == m_hViewTargetAngles ) - { - pPlayer->SetViewEntity( NULL ); - } - UTIL_Remove( m_hViewTargetAngles ); - - if ( m_hViewPositionMover && pPlayer->GetViewEntity() == m_hViewPositionMover ) - { - pPlayer->SetViewEntity( NULL ); - } - UTIL_Remove( m_hViewPositionMover ); - - m_bActive = false; - m_flPlaybackRate = 1.0; - m_bUnstoppable = false; - m_flFinishedTime = 0; - SetContextThink( NULL, 0, s_pCommentaryUpdateViewThink ); - - // Clear out any events waiting on our start commentary - g_EventQueue.CancelEvents( this ); - - m_pOnCommentaryStopped.FireOutput( this, this ); - - g_CommentarySystem.SetActiveNode( NULL ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointCommentaryNode::InputStartCommentary( inputdata_t &inputdata ) -{ - if ( !m_bActive ) - { - if ( g_CommentarySystem.GetActiveNode() ) - { - g_CommentarySystem.GetActiveNode()->StopPlaying(); - } - - PlayerActivated(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointCommentaryNode::InputStartUnstoppableCommentary( inputdata_t &inputdata ) -{ - if ( !m_bActive ) - { - m_bUnstoppable = true; - InputStartCommentary( inputdata ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointCommentaryNode::InputEnable( inputdata_t &inputdata ) -{ - SetDisabled( false ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointCommentaryNode::InputDisable( inputdata_t &inputdata ) -{ - SetDisabled( true ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointCommentaryNode::SetDisabled( bool bDisabled ) -{ - m_bDisabled = bDisabled; - - if ( m_bDisabled ) - { - AddEffects( EF_NODRAW ); - } - else - { - RemoveEffects( EF_NODRAW ); - } -} - -//----------------------------------------------------------------------------- -// Purpose Force our lighting landmark to be transmitted -//----------------------------------------------------------------------------- -int CPointCommentaryNode::UpdateTransmitState( void ) -{ - return SetTransmitState( FL_EDICT_ALWAYS ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointCommentaryNode::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ) -{ - // Are we already marked for transmission? - if ( pInfo->m_pTransmitEdict->Get( entindex() ) ) - return; - - BaseClass::SetTransmit( pInfo, bAlways ); - - // Force our camera view position entity to be sent - if ( m_hViewTarget ) - { - m_hViewTarget->SetTransmit( pInfo, bAlways ); - } - if ( m_hViewTargetAngles ) - { - m_hViewTargetAngles->SetTransmit( pInfo, bAlways ); - } - if ( m_hViewPosition.Get() ) - { - m_hViewPosition.Get()->SetTransmit( pInfo, bAlways ); - } - if ( m_hViewPositionMover ) - { - m_hViewPositionMover->SetTransmit( pInfo, bAlways ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CPointCommentaryNode::PreventsMovement( void ) -{ - // If we're moving the player's view at all, prevent movement - if ( m_hViewPosition.Get() ) - return true; - - return m_bPreventMovement; -} - -//----------------------------------------------------------------------------- -// COMMENTARY SAVE / RESTORE -//----------------------------------------------------------------------------- -static short COMMENTARY_SAVE_RESTORE_VERSION = 2; - -class CCommentary_SaveRestoreBlockHandler : public CDefSaveRestoreBlockHandler -{ -public: - const char *GetBlockName() - { - return "Commentary"; - } - - //--------------------------------- - - void Save( ISave *pSave ) - { - pSave->WriteBool( &g_bInCommentaryMode ); - if ( IsInCommentaryMode() ) - { - pSave->WriteAll( &g_CommentarySystem, g_CommentarySystem.GetDataDescMap() ); - pSave->WriteInt( &CAI_BaseNPC::m_nDebugBits ); - } - } - - //--------------------------------- - - void WriteSaveHeaders( ISave *pSave ) - { - pSave->WriteShort( &COMMENTARY_SAVE_RESTORE_VERSION ); - } - - //--------------------------------- - - void ReadRestoreHeaders( IRestore *pRestore ) - { - // No reason why any future version shouldn't try to retain backward compatability. The default here is to not do so. - short version; - pRestore->ReadShort( &version ); - m_fDoLoad = ( version == COMMENTARY_SAVE_RESTORE_VERSION ); - } - - //--------------------------------- - - void Restore( IRestore *pRestore, bool createPlayers ) - { - if ( m_fDoLoad ) - { - pRestore->ReadBool( &g_bInCommentaryMode ); - if ( g_bInCommentaryMode ) - { - pRestore->ReadAll( &g_CommentarySystem, g_CommentarySystem.GetDataDescMap() ); - CAI_BaseNPC::m_nDebugBits = pRestore->ReadInt(); - } - - // Force the commentary convar to match the saved game state - commentary.SetValue( g_bInCommentaryMode ); - } - } - -private: - bool m_fDoLoad; -}; - -//----------------------------------------------------------------------------- - -CCommentary_SaveRestoreBlockHandler g_Commentary_SaveRestoreBlockHandler; - -//------------------------------------- - -ISaveRestoreBlockHandler *GetCommentarySaveRestoreBlockHandler() -{ - return &g_Commentary_SaveRestoreBlockHandler; -} - -//----------------------------------------------------------------------------- -// Purpose: Commentary specific logic_auto replacement. -// Fires outputs based upon how commentary mode has been activated. -//----------------------------------------------------------------------------- -class CCommentaryAuto : public CBaseEntity -{ - DECLARE_CLASS( CCommentaryAuto, CBaseEntity ); -public: - DECLARE_DATADESC(); - - void Spawn(void); - void Think(void); - - void InputMultiplayerSpawned( inputdata_t &inputdata ); - -private: - // fired if commentary started due to new map - COutputEvent m_OnCommentaryNewGame; - - // fired if commentary was turned on in the middle of a map - COutputEvent m_OnCommentaryMidGame; - - // fired when the player spawns in a multiplayer game - COutputEvent m_OnCommentaryMultiplayerSpawn; -}; - -LINK_ENTITY_TO_CLASS(commentary_auto, CCommentaryAuto); - -BEGIN_DATADESC( CCommentaryAuto ) - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "MultiplayerSpawned", InputMultiplayerSpawned ), - - // Outputs - DEFINE_OUTPUT(m_OnCommentaryNewGame, "OnCommentaryNewGame"), - DEFINE_OUTPUT(m_OnCommentaryMidGame, "OnCommentaryMidGame"), - DEFINE_OUTPUT(m_OnCommentaryMultiplayerSpawn, "OnCommentaryMultiplayerSpawn"), -END_DATADESC() - -//------------------------------------------------------------------------------ -// Purpose : Fire my outputs here if I fire on map reload -//------------------------------------------------------------------------------ -void CCommentaryAuto::Spawn(void) -{ - BaseClass::Spawn(); - SetNextThink( gpGlobals->curtime + 0.1 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCommentaryAuto::Think(void) -{ - if ( g_CommentarySystem.CommentaryWasEnabledMidGame() ) - { - m_OnCommentaryMidGame.FireOutput(NULL, this); - } - else - { - m_OnCommentaryNewGame.FireOutput(NULL, this); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCommentaryAuto::InputMultiplayerSpawned( inputdata_t &inputdata ) -{ - m_OnCommentaryMultiplayerSpawn.FireOutput( NULL, this ); -} - -#else - -bool IsInCommentaryMode( void ) -{ - return false; -} - -#endif diff --git a/game/server/EffectsServer.cpp b/game/server/EffectsServer.cpp deleted file mode 100644 index 8e4c7e4fc..000000000 --- a/game/server/EffectsServer.cpp +++ /dev/null @@ -1,198 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Utility code. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "te.h" -#include "shake.h" -#include "decals.h" -#include "IEffects.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern short g_sModelIndexSmoke; // (in combatweapon.cpp) holds the index for the smoke cloud -extern short g_sModelIndexBloodDrop; // (in combatweapon.cpp) holds the sprite index for the initial blood -extern short g_sModelIndexBloodSpray; // (in combatweapon.cpp) holds the sprite index for splattered blood - - -//----------------------------------------------------------------------------- -// Client-server neutral effects interface -//----------------------------------------------------------------------------- -class CEffectsServer : public IEffects -{ -public: - CEffectsServer(); - virtual ~CEffectsServer(); - - // Members of the IEffect interface - virtual void Beam( const Vector &Start, const Vector &End, int nModelIndex, - int nHaloIndex, unsigned char frameStart, unsigned char frameRate, - float flLife, unsigned char width, unsigned char endWidth, unsigned char fadeLength, - unsigned char noise, unsigned char red, unsigned char green, - unsigned char blue, unsigned char brightness, unsigned char speed); - virtual void Smoke( const Vector &origin, int mModel, float flScale, float flFramerate ); - virtual void Sparks( const Vector &position, int nMagnitude = 1, int nTrailLength = 1, const Vector *pvecDir = NULL ); - virtual void Dust( const Vector &pos, const Vector &dir, float size, float speed ); - virtual void MuzzleFlash( const Vector &origin, const QAngle &angles, float scale, int type ); - virtual void MetalSparks( const Vector &position, const Vector &direction ); - virtual void EnergySplash( const Vector &position, const Vector &direction, bool bExplosive = false ); - virtual void Ricochet( const Vector &position, const Vector &direction ); - - // FIXME: Should these methods remain in this interface? Or go in some - // other client-server neutral interface? - virtual float Time(); - virtual bool IsServer(); - virtual void SuppressEffectsSounds( bool bSuppress ) { Assert(0); } - -private: - //----------------------------------------------------------------------------- - // Purpose: Returning true means don't even call TE func - // Input : filter - - // *suppress_host - - // Output : static bool - //----------------------------------------------------------------------------- - bool SuppressTE( CRecipientFilter& filter ) - { - if ( GetSuppressHost() ) - { - if ( !filter.IgnorePredictionCull() ) - { - filter.RemoveRecipient( (CBasePlayer *)GetSuppressHost() ); - } - - if ( !filter.GetRecipientCount() ) - { - // Suppress it - return true; - } - } - - // There's at least one recipient - return false; - } -}; - - -//----------------------------------------------------------------------------- -// Client-server neutral effects interface accessor -//----------------------------------------------------------------------------- -static CEffectsServer s_EffectServer; -EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CEffectsServer, IEffects, IEFFECTS_INTERFACE_VERSION, s_EffectServer); -IEffects *g_pEffects = &s_EffectServer; - - -//----------------------------------------------------------------------------- -// constructor, destructor -//----------------------------------------------------------------------------- -CEffectsServer::CEffectsServer() -{ -} - -CEffectsServer::~CEffectsServer() -{ -} - - -//----------------------------------------------------------------------------- -// Generates a beam -//----------------------------------------------------------------------------- -void CEffectsServer::Beam( const Vector &vecStart, const Vector &vecEnd, int nModelIndex, - int nHaloIndex, unsigned char frameStart, unsigned char frameRate, - float flLife, unsigned char width, unsigned char endWidth, unsigned char fadeLength, - unsigned char noise, unsigned char red, unsigned char green, - unsigned char blue, unsigned char brightness, unsigned char speed) -{ - CBroadcastRecipientFilter filter; - if ( !SuppressTE( filter ) ) - { - te->BeamPoints( filter, 0.0, - &vecStart, &vecEnd, nModelIndex, nHaloIndex, frameStart, frameRate, flLife, - width, endWidth, fadeLength, noise, red, green, blue, brightness, speed ); - } -} - - -//----------------------------------------------------------------------------- -// Generates various tempent effects -//----------------------------------------------------------------------------- -void CEffectsServer::Smoke( const Vector &origin, int mModel, float flScale, float flFramerate ) -{ - CPVSFilter filter( origin ); - if ( !SuppressTE( filter ) ) - { - te->Smoke( filter, 0.0, &origin, mModel, flScale * 0.1f, (int)flFramerate ); - } -} - -void CEffectsServer::Sparks( const Vector &position, int nMagnitude, int nTrailLength, const Vector *pvecDir ) -{ - CPVSFilter filter( position ); - if ( !SuppressTE( filter ) ) - { - te->Sparks( filter, 0.0, &position, nMagnitude, nTrailLength, pvecDir ); - } -} - -void CEffectsServer::Dust( const Vector &pos, const Vector &dir, float size, float speed ) -{ - CPVSFilter filter( pos ); - if ( !SuppressTE( filter ) ) - { - te->Dust( filter, 0.0, pos, dir, size, speed ); - } -} - -void CEffectsServer::MuzzleFlash( const Vector &origin, const QAngle &angles, float scale, int type ) -{ - CPVSFilter filter( origin ); - if ( !SuppressTE( filter ) ) - { - te->MuzzleFlash( filter, 0.0f, origin, angles, scale, type ); - } -} - -void CEffectsServer::MetalSparks( const Vector &position, const Vector &direction ) -{ - CPVSFilter filter( position ); - if ( !SuppressTE( filter ) ) - { - te->MetalSparks( filter, 0.0, &position, &direction ); - } -} - -void CEffectsServer::EnergySplash( const Vector &position, const Vector &direction, bool bExplosive ) -{ - CPVSFilter filter( position ); - if ( !SuppressTE( filter ) ) - { - te->EnergySplash( filter, 0.0, &position, &direction, bExplosive ); - } -} - -void CEffectsServer::Ricochet( const Vector &position, const Vector &direction ) -{ - CPVSFilter filter( position ); - if ( !SuppressTE( filter ) ) - { - te->ArmorRicochet( filter, 0.0, &position, &direction ); - } -} - - -//----------------------------------------------------------------------------- -// FIXME: Should these methods remain in this interface? Or go in some -// other client-server neutral interface? -//----------------------------------------------------------------------------- -float CEffectsServer::Time() -{ - return gpGlobals->curtime; -} - -bool CEffectsServer::IsServer() -{ - return true; -} diff --git a/game/server/EntityDissolve.cpp b/game/server/EntityDissolve.cpp deleted file mode 100644 index 0954c8757..000000000 --- a/game/server/EntityDissolve.cpp +++ /dev/null @@ -1,388 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Dissolve entity to be attached to target entity. Serves two purposes: -// -// 1) An entity that can be placed by a level designer and triggered -// to ignite a target entity. -// -// 2) An entity that can be created at runtime to ignite a target entity. -// -//=============================================================================// - -#include "cbase.h" -#include "EntityDissolve.h" -#include "baseanimating.h" -#include "physics_prop_ragdoll.h" -#include "ai_basenpc.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -static const char *s_pElectroThinkContext = "ElectroThinkContext"; - - -//----------------------------------------------------------------------------- -// Lifetime -//----------------------------------------------------------------------------- -#define DISSOLVE_FADE_IN_START_TIME 0.0f -#define DISSOLVE_FADE_IN_END_TIME 1.0f -#define DISSOLVE_FADE_OUT_MODEL_START_TIME 1.9f -#define DISSOLVE_FADE_OUT_MODEL_END_TIME 2.0f -#define DISSOLVE_FADE_OUT_START_TIME 2.0f -#define DISSOLVE_FADE_OUT_END_TIME 2.0f - -//----------------------------------------------------------------------------- -// Model -//----------------------------------------------------------------------------- -#define DISSOLVE_SPRITE_NAME "sprites/blueglow1.vmt" - -//----------------------------------------------------------------------------- -// Save/load -//----------------------------------------------------------------------------- -BEGIN_DATADESC( CEntityDissolve ) - - DEFINE_FIELD( m_flStartTime, FIELD_TIME ), - DEFINE_FIELD( m_flFadeInStart, FIELD_FLOAT ), - DEFINE_FIELD( m_flFadeInLength, FIELD_FLOAT ), - DEFINE_FIELD( m_flFadeOutModelStart, FIELD_FLOAT ), - DEFINE_FIELD( m_flFadeOutModelLength, FIELD_FLOAT ), - DEFINE_FIELD( m_flFadeOutStart, FIELD_FLOAT ), - DEFINE_FIELD( m_flFadeOutLength, FIELD_FLOAT ), - DEFINE_KEYFIELD( m_nDissolveType, FIELD_INTEGER, "dissolvetype" ), - DEFINE_FIELD( m_vDissolverOrigin, FIELD_VECTOR ), - DEFINE_KEYFIELD( m_nMagnitude, FIELD_INTEGER, "magnitude" ), - - DEFINE_FUNCTION( DissolveThink ), - DEFINE_FUNCTION( ElectrocuteThink ), - - DEFINE_INPUTFUNC( FIELD_STRING, "Dissolve", InputDissolve ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Networking -//----------------------------------------------------------------------------- -IMPLEMENT_SERVERCLASS_ST( CEntityDissolve, DT_EntityDissolve ) - SendPropTime( SENDINFO( m_flStartTime ) ), - SendPropFloat( SENDINFO( m_flFadeInStart ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO( m_flFadeInLength ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO( m_flFadeOutModelStart ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO( m_flFadeOutModelLength ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO( m_flFadeOutStart ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO( m_flFadeOutLength ), 0, SPROP_NOSCALE ), - SendPropInt( SENDINFO( m_nDissolveType ), ENTITY_DISSOLVE_BITS, SPROP_UNSIGNED ), - SendPropVector (SENDINFO(m_vDissolverOrigin), 0, SPROP_NOSCALE ), - SendPropInt( SENDINFO( m_nMagnitude ), 8, SPROP_UNSIGNED ), -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( env_entity_dissolver, CEntityDissolve ); - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CEntityDissolve::CEntityDissolve( void ) -{ - m_flStartTime = 0.0f; - m_nMagnitude = 250; -} - -CEntityDissolve::~CEntityDissolve( void ) -{ -} - - -//----------------------------------------------------------------------------- -// Precache -//----------------------------------------------------------------------------- -void CEntityDissolve::Precache() -{ - if ( NULL_STRING == GetModelName() ) - { - PrecacheModel( DISSOLVE_SPRITE_NAME ); - } - else - { - PrecacheModel( STRING( GetModelName() ) ); - } -} - - -//----------------------------------------------------------------------------- -// Spawn -//----------------------------------------------------------------------------- -void CEntityDissolve::Spawn() -{ - BaseClass::Spawn(); - Precache(); - UTIL_SetModel( this, STRING( GetModelName() ) ); - - if ( (m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL) || (m_nDissolveType == ENTITY_DISSOLVE_ELECTRICAL_LIGHT) ) - { - if ( dynamic_cast< CRagdollProp* >( GetMoveParent() ) ) - { - SetContextThink( &CEntityDissolve::ElectrocuteThink, gpGlobals->curtime + 0.01f, s_pElectroThinkContext ); - } - } - - // Setup our times - m_flFadeInStart = DISSOLVE_FADE_IN_START_TIME; - m_flFadeInLength = DISSOLVE_FADE_IN_END_TIME - DISSOLVE_FADE_IN_START_TIME; - - m_flFadeOutModelStart = DISSOLVE_FADE_OUT_MODEL_START_TIME; - m_flFadeOutModelLength = DISSOLVE_FADE_OUT_MODEL_END_TIME - DISSOLVE_FADE_OUT_MODEL_START_TIME; - - m_flFadeOutStart = DISSOLVE_FADE_OUT_START_TIME; - m_flFadeOutLength = DISSOLVE_FADE_OUT_END_TIME - DISSOLVE_FADE_OUT_START_TIME; - - if ( m_nDissolveType == ENTITY_DISSOLVE_CORE ) - { - m_flFadeInStart = 0.0f; - m_flFadeOutStart = CORE_DISSOLVE_FADE_START; - m_flFadeOutModelStart = CORE_DISSOLVE_MODEL_FADE_START; - m_flFadeOutModelLength = CORE_DISSOLVE_MODEL_FADE_LENGTH; - m_flFadeInLength = CORE_DISSOLVE_FADEIN_LENGTH; - } - - m_nRenderMode = kRenderTransColor; - SetRenderColor( 255, 255, 255, 255 ); - m_nRenderFX = kRenderFxNone; - - SetThink( &CEntityDissolve::DissolveThink ); - if ( gpGlobals->curtime > m_flStartTime ) - { - // Necessary for server-side ragdolls - DissolveThink(); - } - else - { - SetNextThink( gpGlobals->curtime + 0.01f ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : inputdata - -//----------------------------------------------------------------------------- -void CEntityDissolve::InputDissolve( inputdata_t &inputdata ) -{ - string_t strTarget = inputdata.value.StringID(); - - if (strTarget == NULL_STRING) - { - strTarget = m_target; - } - - CBaseEntity *pTarget = NULL; - while ((pTarget = gEntList.FindEntityGeneric(pTarget, STRING(strTarget), this, inputdata.pActivator)) != NULL) - { - CBaseAnimating *pBaseAnim = pTarget->GetBaseAnimating(); - if (pBaseAnim) - { - pBaseAnim->Dissolve( NULL, gpGlobals->curtime, false, m_nDissolveType, GetAbsOrigin(), m_nMagnitude ); - } - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: Creates a flame and attaches it to a target entity. -// Input : pTarget - -//----------------------------------------------------------------------------- -CEntityDissolve *CEntityDissolve::Create( CBaseEntity *pTarget, const char *pMaterialName, - float flStartTime, int nDissolveType, bool *pRagdollCreated ) -{ - if ( pRagdollCreated ) - { - *pRagdollCreated = false; - } - - if ( !pMaterialName ) - { - pMaterialName = DISSOLVE_SPRITE_NAME; - } - - if ( pTarget->IsPlayer() ) - { - // Simply immediately kill the player. - CBasePlayer *pPlayer = assert_cast< CBasePlayer* >( pTarget ); - pPlayer->SetArmorValue( 0 ); - CTakeDamageInfo info( pPlayer, pPlayer, pPlayer->GetHealth(), DMG_GENERIC | DMG_REMOVENORAGDOLL | DMG_PREVENT_PHYSICS_FORCE ); - pPlayer->TakeDamage( info ); - return NULL; - } - - CEntityDissolve *pDissolve = (CEntityDissolve *) CreateEntityByName( "env_entity_dissolver" ); - - if ( pDissolve == NULL ) - return NULL; - - pDissolve->m_nDissolveType = nDissolveType; - if ( (nDissolveType == ENTITY_DISSOLVE_ELECTRICAL) || (nDissolveType == ENTITY_DISSOLVE_ELECTRICAL_LIGHT) ) - { - if ( pTarget->IsNPC() && pTarget->MyNPCPointer()->CanBecomeRagdoll() ) - { - CTakeDamageInfo info; - CBaseEntity *pRagdoll = CreateServerRagdoll( pTarget->MyNPCPointer(), 0, info, COLLISION_GROUP_DEBRIS, true ); - pRagdoll->SetCollisionBounds( pTarget->CollisionProp()->OBBMins(), pTarget->CollisionProp()->OBBMaxs() ); - - // Necessary to cause it to do the appropriate death cleanup - if ( pTarget->m_lifeState == LIFE_ALIVE ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); - CTakeDamageInfo ragdollInfo( pPlayer, pPlayer, 10000.0, DMG_SHOCK | DMG_REMOVENORAGDOLL | DMG_PREVENT_PHYSICS_FORCE ); - pTarget->TakeDamage( ragdollInfo ); - } - - if ( pRagdollCreated ) - { - *pRagdollCreated = true; - } - - UTIL_Remove( pTarget ); - pTarget = pRagdoll; - } - } - - pDissolve->SetModelName( AllocPooledString(pMaterialName) ); - pDissolve->AttachToEntity( pTarget ); - pDissolve->SetStartTime( flStartTime ); - pDissolve->Spawn(); - - // Send to the client even though we don't have a model - pDissolve->AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); - - // Play any appropriate noises when we start to dissolve - if ( (nDissolveType == ENTITY_DISSOLVE_ELECTRICAL) || (nDissolveType == ENTITY_DISSOLVE_ELECTRICAL_LIGHT) ) - { - pTarget->DispatchResponse( "TLK_ELECTROCUTESCREAM" ); - } - else - { - pTarget->DispatchResponse( "TLK_DISSOLVESCREAM" ); - } - return pDissolve; -} - - -//----------------------------------------------------------------------------- -// What type of dissolve? -//----------------------------------------------------------------------------- -CEntityDissolve *CEntityDissolve::Create( CBaseEntity *pTarget, CBaseEntity *pSource ) -{ - // Look for other boogies on the ragdoll + kill them - for ( CBaseEntity *pChild = pSource->FirstMoveChild(); pChild; pChild = pChild->NextMovePeer() ) - { - CEntityDissolve *pDissolve = dynamic_cast(pChild); - if ( !pDissolve ) - continue; - - return Create( pTarget, STRING( pDissolve->GetModelName() ), pDissolve->m_flStartTime, pDissolve->m_nDissolveType ); - } - - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Attaches the flame to an entity and moves with it -// Input : pTarget - target entity to attach to -//----------------------------------------------------------------------------- -void CEntityDissolve::AttachToEntity( CBaseEntity *pTarget ) -{ - // So our dissolver follows the entity around on the server. - SetParent( pTarget ); - SetLocalOrigin( vec3_origin ); - SetLocalAngles( vec3_angle ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : lifetime - -//----------------------------------------------------------------------------- -void CEntityDissolve::SetStartTime( float flStartTime ) -{ - m_flStartTime = flStartTime; -} - -//----------------------------------------------------------------------------- -// Purpose: Burn targets around us -//----------------------------------------------------------------------------- -void CEntityDissolve::DissolveThink( void ) -{ - CBaseAnimating *pTarget = ( GetMoveParent() ) ? GetMoveParent()->GetBaseAnimating() : NULL; - - if ( GetModelName() == NULL_STRING && pTarget == NULL ) - return; - - if ( pTarget == NULL ) - { - UTIL_Remove( this ); - return; - } - - // Turn them into debris - pTarget->SetCollisionGroup( COLLISION_GROUP_DISSOLVING ); - - if ( pTarget && pTarget->GetFlags() & FL_TRANSRAGDOLL ) - { - SetRenderColorA( 0 ); - } - - float dt = gpGlobals->curtime - m_flStartTime; - - if ( dt < m_flFadeInStart ) - { - SetNextThink( m_flStartTime + m_flFadeInStart ); - return; - } - - // If we're done fading, then kill our target entity and us - if ( dt >= m_flFadeOutStart + m_flFadeOutLength ) - { - // Necessary to cause it to do the appropriate death cleanup - // Yeah, the player may have nothing to do with it, but - // passing NULL to TakeDamage causes bad things to happen - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); - int iNoPhysicsDamage = g_pGameRules->Damage_GetNoPhysicsForce(); - CTakeDamageInfo info( pPlayer, pPlayer, 10000.0, DMG_GENERIC | DMG_REMOVENORAGDOLL | iNoPhysicsDamage ); - pTarget->TakeDamage( info ); - - if ( pTarget != pPlayer ) - { - UTIL_Remove( pTarget ); - } - - UTIL_Remove( this ); - - return; - } - - SetNextThink( gpGlobals->curtime + TICK_INTERVAL ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Burn targets around us -//----------------------------------------------------------------------------- -void CEntityDissolve::ElectrocuteThink( void ) -{ - CRagdollProp *pRagdoll = dynamic_cast< CRagdollProp* >( GetMoveParent() ); - if ( !pRagdoll ) - return; - - ragdoll_t *pRagdollPhys = pRagdoll->GetRagdoll( ); - for ( int j = 0; j < pRagdollPhys->listCount; ++j ) - { - Vector vecForce; - vecForce = RandomVector( -2400.0f, 2400.0f ); - pRagdollPhys->list[j].pObject->ApplyForceCenter( vecForce ); - } - - SetContextThink( &CEntityDissolve::ElectrocuteThink, gpGlobals->curtime + random->RandomFloat( 0.1, 0.2f ), - s_pElectroThinkContext ); -} diff --git a/game/server/EntityDissolve.h b/game/server/EntityDissolve.h deleted file mode 100644 index 56275e25c..000000000 --- a/game/server/EntityDissolve.h +++ /dev/null @@ -1,63 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ENTITYDISSOLVE_H -#define ENTITYDISSOLVE_H - -#ifdef _WIN32 -#pragma once -#endif - -class CEntityDissolve : public CBaseEntity -{ -public: - DECLARE_SERVERCLASS(); - DECLARE_CLASS( CEntityDissolve, CBaseEntity ); - - CEntityDissolve( void ); - ~CEntityDissolve( void ); - - static CEntityDissolve *Create( CBaseEntity *pTarget, const char *pMaterialName, - float flStartTime, int nDissolveType = 0, bool *pRagdollCreated = NULL ); - static CEntityDissolve *Create( CBaseEntity *pTarget, CBaseEntity *pSource ); - - void Precache(); - void Spawn(); - void AttachToEntity( CBaseEntity *pTarget ); - void SetStartTime( float flStartTime ); - void SetDissolverOrigin( Vector vOrigin ) { m_vDissolverOrigin = vOrigin; } - void SetMagnitude( int iMagnitude ){ m_nMagnitude = iMagnitude; } - void SetDissolveType( int iType ) { m_nDissolveType = iType; } - - Vector GetDissolverOrigin( void ) - { - Vector vReturn = m_vDissolverOrigin; - return vReturn; - } - int GetMagnitude( void ) { return m_nMagnitude; } - int GetDissolveType( void ) { return m_nDissolveType; } - - DECLARE_DATADESC(); - - CNetworkVar( float, m_flStartTime ); - CNetworkVar( float, m_flFadeInStart ); - CNetworkVar( float, m_flFadeInLength ); - CNetworkVar( float, m_flFadeOutModelStart ); - CNetworkVar( float, m_flFadeOutModelLength ); - CNetworkVar( float, m_flFadeOutStart ); - CNetworkVar( float, m_flFadeOutLength ); - -protected: - void InputDissolve( inputdata_t &inputdata ); - void DissolveThink( void ); - void ElectrocuteThink( void ); - - CNetworkVar( int, m_nDissolveType ); - CNetworkVector( m_vDissolverOrigin ); - CNetworkVar( int, m_nMagnitude ); -}; - -#endif // ENTITYDISSOLVE_H diff --git a/game/server/EntityFlame.cpp b/game/server/EntityFlame.cpp deleted file mode 100644 index 83393be13..000000000 --- a/game/server/EntityFlame.cpp +++ /dev/null @@ -1,335 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Flame entity to be attached to target entity. Serves two purposes: -// -// 1) An entity that can be placed by a level designer and triggered -// to ignite a target entity. -// -// 2) An entity that can be created at runtime to ignite a target entity. -// -//=============================================================================// - -#include "cbase.h" -#include "EntityFlame.h" -#include "ai_basenpc.h" -#include "fire.h" -#include "shareddefs.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -BEGIN_DATADESC( CEntityFlame ) - - DEFINE_KEYFIELD( m_flLifetime, FIELD_FLOAT, "lifetime" ), - - DEFINE_FIELD( m_flSize, FIELD_FLOAT ), - DEFINE_FIELD( m_hEntAttached, FIELD_EHANDLE ), - DEFINE_FIELD( m_bUseHitboxes, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iNumHitboxFires, FIELD_INTEGER ), - DEFINE_FIELD( m_flHitboxFireScale, FIELD_FLOAT ), - // DEFINE_FIELD( m_bPlayingSound, FIELD_BOOLEAN ), - - DEFINE_FUNCTION( FlameThink ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Ignite", InputIgnite ), - -END_DATADESC() - - -IMPLEMENT_SERVERCLASS_ST( CEntityFlame, DT_EntityFlame ) - SendPropEHandle( SENDINFO( m_hEntAttached ) ), -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( entityflame, CEntityFlame ); -LINK_ENTITY_TO_CLASS( env_entity_igniter, CEntityFlame ); -PRECACHE_REGISTER(entityflame); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CEntityFlame::CEntityFlame( void ) -{ - m_flSize = 0.0f; - m_iNumHitboxFires = 10; - m_flHitboxFireScale = 1.0f; - m_flLifetime = 0.0f; - m_bPlayingSound = false; -} - -void CEntityFlame::UpdateOnRemove() -{ - // Sometimes the entity I'm burning gets destroyed by other means, - // which kills me. Make sure to stop the burning sound. - if ( m_bPlayingSound ) - { - EmitSound( "General.StopBurning" ); - m_bPlayingSound = false; - } - - BaseClass::UpdateOnRemove(); -} - -void CEntityFlame::Precache() -{ - BaseClass::Precache(); - - PrecacheScriptSound( "General.StopBurning" ); - PrecacheScriptSound( "General.BurningFlesh" ); - PrecacheScriptSound( "General.BurningObject" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : inputdata - -//----------------------------------------------------------------------------- -void CEntityFlame::InputIgnite( inputdata_t &inputdata ) -{ - if (m_target != NULL_STRING) - { - CBaseEntity *pTarget = NULL; - while ((pTarget = gEntList.FindEntityGeneric(pTarget, STRING(m_target), this, inputdata.pActivator)) != NULL) - { - // Combat characters know how to catch themselves on fire. - CBaseCombatCharacter *pBCC = pTarget->MyCombatCharacterPointer(); - if (pBCC) - { - // DVS TODO: consider promoting Ignite to CBaseEntity and doing everything here - pBCC->Ignite(m_flLifetime); - } - // Everything else, we handle here. - else - { - CEntityFlame *pFlame = CEntityFlame::Create(pTarget); - if (pFlame) - { - pFlame->SetLifetime(m_flLifetime); - } - } - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Creates a flame and attaches it to a target entity. -// Input : pTarget - -//----------------------------------------------------------------------------- -CEntityFlame *CEntityFlame::Create( CBaseEntity *pTarget, bool useHitboxes ) -{ - CEntityFlame *pFlame = (CEntityFlame *) CreateEntityByName( "entityflame" ); - - if ( pFlame == NULL ) - return NULL; - - float xSize = pTarget->CollisionProp()->OBBMaxs().x - pTarget->CollisionProp()->OBBMins().x; - float ySize = pTarget->CollisionProp()->OBBMaxs().y - pTarget->CollisionProp()->OBBMins().y; - - float size = ( xSize + ySize ) * 0.5f; - - if ( size < 16.0f ) - { - size = 16.0f; - } - - UTIL_SetOrigin( pFlame, pTarget->GetAbsOrigin() ); - - pFlame->m_flSize = size; - pFlame->SetThink( &CEntityFlame::FlameThink ); - pFlame->SetNextThink( gpGlobals->curtime + 0.1f ); - - pFlame->AttachToEntity( pTarget ); - pFlame->SetLifetime( 2.0f ); - - //Send to the client even though we don't have a model - pFlame->AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); - - pFlame->SetUseHitboxes( useHitboxes ); - - return pFlame; -} - - -//----------------------------------------------------------------------------- -// Purpose: Attaches the flame to an entity and moves with it -// Input : pTarget - target entity to attach to -//----------------------------------------------------------------------------- -void CEntityFlame::AttachToEntity( CBaseEntity *pTarget ) -{ - // For networking to the client. - m_hEntAttached = pTarget; - - if( pTarget->IsNPC() ) - { - EmitSound( "General.BurningFlesh" ); - } - else - { - EmitSound( "General.BurningObject" ); - } - - m_bPlayingSound = true; - - // So our heat emitter follows the entity around on the server. - SetParent( pTarget ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : lifetime - -//----------------------------------------------------------------------------- -void CEntityFlame::SetLifetime( float lifetime ) -{ - m_flLifetime = gpGlobals->curtime + lifetime; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : use - -//----------------------------------------------------------------------------- -void CEntityFlame::SetUseHitboxes( bool use ) -{ - m_bUseHitboxes = use; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iNumHitBoxFires - -//----------------------------------------------------------------------------- -void CEntityFlame::SetNumHitboxFires( int iNumHitboxFires ) -{ - m_iNumHitboxFires = iNumHitboxFires; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flHitboxFireScale - -//----------------------------------------------------------------------------- -void CEntityFlame::SetHitboxFireScale( float flHitboxFireScale ) -{ - m_flHitboxFireScale = flHitboxFireScale; -} - -float CEntityFlame::GetRemainingLife( void ) -{ - return m_flLifetime - gpGlobals->curtime; -} - -int CEntityFlame::GetNumHitboxFires( void ) -{ - return m_iNumHitboxFires; -} - -float CEntityFlame::GetHitboxFireScale( void ) -{ - return m_flHitboxFireScale; -} - -//----------------------------------------------------------------------------- -// Purpose: Burn targets around us -//----------------------------------------------------------------------------- -void CEntityFlame::FlameThink( void ) -{ - // Assure that this function will be ticked again even if we early-out in the if below. - SetNextThink( gpGlobals->curtime + FLAME_DAMAGE_INTERVAL ); - - if ( m_hEntAttached ) - { - if ( m_hEntAttached->GetFlags() & FL_TRANSRAGDOLL ) - { - SetRenderColorA( 0 ); - return; - } - - CAI_BaseNPC *pNPC = m_hEntAttached->MyNPCPointer(); - if ( pNPC && !pNPC->IsAlive() ) - { - UTIL_Remove( this ); - // Notify the NPC that it's no longer burning! - pNPC->Extinguish(); - return; - } - - if( m_hEntAttached->GetWaterLevel() > 0 ) - { - Vector mins, maxs; - - mins = m_hEntAttached->WorldSpaceCenter(); - maxs = mins; - - maxs.z = m_hEntAttached->WorldSpaceCenter().z; - maxs.x += 32; - maxs.y += 32; - - mins.z -= 32; - mins.x -= 32; - mins.y -= 32; - - UTIL_Bubbles( mins, maxs, 12 ); - } - } - else - { - UTIL_Remove( this ); - return; - } - - // See if we're done burning, or our attached ent has vanished - if ( m_flLifetime < gpGlobals->curtime || m_hEntAttached == NULL ) - { - EmitSound( "General.StopBurning" ); - m_bPlayingSound = false; - SetThink( &CEntityFlame::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 0.5f ); - - // Notify anything we're attached to - if ( m_hEntAttached ) - { - CBaseCombatCharacter *pAttachedCC = m_hEntAttached->MyCombatCharacterPointer(); - - if( pAttachedCC ) - { - // Notify the NPC that it's no longer burning! - pAttachedCC->Extinguish(); - } - } - - return; - } - - if ( m_hEntAttached ) - { - // Do radius damage ignoring the entity I'm attached to. This will harm things around me. - RadiusDamage( CTakeDamageInfo( this, this, 4.0f, DMG_BURN ), GetAbsOrigin(), m_flSize/2, CLASS_NONE, m_hEntAttached ); - - // Directly harm the entity I'm attached to. This is so we can precisely control how much damage the entity - // that is on fire takes without worrying about the flame's position relative to the bodytarget (which is the - // distance that the radius damage code uses to determine how much damage to inflict) - m_hEntAttached->TakeDamage( CTakeDamageInfo( this, this, FLAME_DIRECT_DAMAGE, DMG_BURN | DMG_DIRECT ) ); - - if( !m_hEntAttached->IsNPC() && hl2_episodic.GetBool() ) - { - const int ENTITYFLAME_MOVE_AWAY_DIST = 24; - // Make a sound near my origin, and up a little higher (in case I'm on the ground, so NPC's still hear it) - CSoundEnt::InsertSound( SOUND_MOVE_AWAY, GetAbsOrigin(), ENTITYFLAME_MOVE_AWAY_DIST, 0.1f, this, SOUNDENT_CHANNEL_REPEATED_DANGER ); - CSoundEnt::InsertSound( SOUND_MOVE_AWAY, GetAbsOrigin() + Vector( 0, 0, 48.0f ), ENTITYFLAME_MOVE_AWAY_DIST, 0.1f, this, SOUNDENT_CHANNEL_REPEATING ); - } - } - else - { - RadiusDamage( CTakeDamageInfo( this, this, FLAME_RADIUS_DAMAGE, DMG_BURN ), GetAbsOrigin(), m_flSize/2, CLASS_NONE, NULL ); - } - - FireSystem_AddHeatInRadius( GetAbsOrigin(), m_flSize/2, 2.0f ); - -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pEnt - -//----------------------------------------------------------------------------- -void CreateEntityFlame(CBaseEntity *pEnt) -{ - CEntityFlame::Create( pEnt ); -} diff --git a/game/server/EntityFlame.h b/game/server/EntityFlame.h deleted file mode 100644 index 7e1b90402..000000000 --- a/game/server/EntityFlame.h +++ /dev/null @@ -1,66 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ENTITYFLAME_H -#define ENTITYFLAME_H -#ifdef _WIN32 -#pragma once -#endif - -#define FLAME_DAMAGE_INTERVAL 0.2f // How often to deal damage. -#define FLAME_DIRECT_DAMAGE_PER_SEC 5.0f -#define FLAME_RADIUS_DAMAGE_PER_SEC 4.0f - -#define FLAME_DIRECT_DAMAGE ( FLAME_DIRECT_DAMAGE_PER_SEC * FLAME_DAMAGE_INTERVAL ) -#define FLAME_RADIUS_DAMAGE ( FLAME_RADIUS_DAMAGE_PER_SEC * FLAME_DAMAGE_INTERVAL ) - -#define FLAME_MAX_LIFETIME_ON_DEAD_NPCS 10.0f - -class CEntityFlame : public CBaseEntity -{ -public: - DECLARE_SERVERCLASS(); - DECLARE_CLASS( CEntityFlame, CBaseEntity ); - - CEntityFlame( void ); - - static CEntityFlame *Create( CBaseEntity *pTarget, bool useHitboxes = true ); - - void AttachToEntity( CBaseEntity *pTarget ); - void SetLifetime( float lifetime ); - void SetUseHitboxes( bool use ); - void SetNumHitboxFires( int iNumHitBoxFires ); - void SetHitboxFireScale( float flHitboxFireScale ); - - float GetRemainingLife( void ); - int GetNumHitboxFires( void ); - float GetHitboxFireScale( void ); - - virtual void Precache(); - virtual void UpdateOnRemove(); - - void SetSize( float size ) { m_flSize = size; } - - DECLARE_DATADESC(); - -protected: - - void InputIgnite( inputdata_t &inputdata ); - - void FlameThink( void ); - - CNetworkHandle( CBaseEntity, m_hEntAttached ); // The entity that we are burning (attached to). - - CNetworkVar( float, m_flSize ); - CNetworkVar( bool, m_bUseHitboxes ); - CNetworkVar( int, m_iNumHitboxFires ); - CNetworkVar( float, m_flHitboxFireScale ); - - CNetworkVar( float, m_flLifetime ); - bool m_bPlayingSound; -}; - -#endif // ENTITYFLAME_H diff --git a/game/server/EntityParticleTrail.cpp b/game/server/EntityParticleTrail.cpp deleted file mode 100644 index e9e0ddb7a..000000000 --- a/game/server/EntityParticleTrail.cpp +++ /dev/null @@ -1,207 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Drops particles where the entity was. -// -//=============================================================================// - -#include "cbase.h" -#include "EntityParticleTrail.h" -#include "networkstringtable_gamedll.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Used to retire the entity -//----------------------------------------------------------------------------- -static const char *s_pRetireContext = "RetireContext"; - - -//----------------------------------------------------------------------------- -// Save/load -//----------------------------------------------------------------------------- -BEGIN_DATADESC( CEntityParticleTrail ) - - DEFINE_FIELD( m_iMaterialName, FIELD_MATERIALINDEX ), - DEFINE_EMBEDDED( m_Info ), - DEFINE_FIELD( m_hConstraintEntity, FIELD_EHANDLE ), - - // Think this should be handled by StartTouch/etc. -// DEFINE_FIELD( m_nRefCount, FIELD_INTEGER ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Networking -//----------------------------------------------------------------------------- -IMPLEMENT_SERVERCLASS_ST( CEntityParticleTrail, DT_EntityParticleTrail ) - SendPropInt(SENDINFO(m_iMaterialName), MAX_MATERIAL_STRING_BITS, SPROP_UNSIGNED ), - SendPropDataTable( SENDINFO_DT( m_Info ), &REFERENCE_SEND_TABLE( DT_EntityParticleTrailInfo ) ), - SendPropEHandle(SENDINFO(m_hConstraintEntity)), -END_SEND_TABLE() - - -LINK_ENTITY_TO_CLASS( env_particle_trail, CEntityParticleTrail ); - - -//----------------------------------------------------------------------------- -// Purpose: Creates a flame and attaches it to a target entity. -// Input : pTarget - -//----------------------------------------------------------------------------- -CEntityParticleTrail *CEntityParticleTrail::Create( CBaseEntity *pTarget, const EntityParticleTrailInfo_t &info, CBaseEntity *pConstraintEntity ) -{ - int iMaterialName = GetMaterialIndex( STRING(info.m_strMaterialName) ); - - // Look for other particle trails on the entity + copy state to the new entity - CEntityParticleTrail *pTrail; - CBaseEntity *pNext; - for ( CBaseEntity *pChild = pTarget->FirstMoveChild(); pChild; pChild = pNext ) - { - pNext = pChild->NextMovePeer(); - pTrail = dynamic_cast(pChild); - if ( pTrail && (pTrail->m_iMaterialName == iMaterialName) ) - { - // Prevent destruction if it re-enters the field - pTrail->IncrementRefCount(); - return pTrail; - } - } - - pTrail = (CEntityParticleTrail *)CreateEntityByName( "env_particle_trail" ); - if ( pTrail == NULL ) - return NULL; - - pTrail->m_hConstraintEntity = pConstraintEntity; - pTrail->m_iMaterialName = iMaterialName; - pTrail->m_Info.CopyFrom(info); - pTrail->m_nRefCount = 1; - pTrail->AttachToEntity( pTarget ); - pTrail->Spawn(); - return pTrail; -} - - -//----------------------------------------------------------------------------- -// Spawn -//----------------------------------------------------------------------------- -void CEntityParticleTrail::Spawn() -{ - BaseClass::Spawn(); - - /* - SetThink( &CEntityParticleTrail::BoogieThink ); - SetNextThink( gpGlobals->curtime + 0.01f ); - - if ( HasSpawnFlags( SF_RAGDOLL_BOOGIE_ELECTRICAL ) ) - { - SetContextThink( ZapThink, gpGlobals->curtime + random->RandomFloat( 0.1f, 0.3f ), s_pZapContext ); - } - */ -} - - -//----------------------------------------------------------------------------- -// Spawn -//----------------------------------------------------------------------------- -void CEntityParticleTrail::UpdateOnRemove() -{ - g_pNotify->ClearEntity( this ); - - BaseClass::UpdateOnRemove(); -} - - -//----------------------------------------------------------------------------- -// Force our constraint entity to be trasmitted -//----------------------------------------------------------------------------- -void CEntityParticleTrail::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ) -{ - // Are we already marked for transmission? - if ( pInfo->m_pTransmitEdict->Get( entindex() ) ) - return; - - BaseClass::SetTransmit( pInfo, bAlways ); - - // Force our constraint entity to be sent too. - if ( m_hConstraintEntity ) - { - m_hConstraintEntity->SetTransmit( pInfo, bAlways ); - } -} - - -//----------------------------------------------------------------------------- -// Retire -//----------------------------------------------------------------------------- -void CEntityParticleTrail::IncrementRefCount() -{ - if ( m_nRefCount == 0 ) - { - SetContextThink( NULL, gpGlobals->curtime, s_pRetireContext ); - } - ++m_nRefCount; -} - -void CEntityParticleTrail::DecrementRefCount() -{ - --m_nRefCount; - Assert( m_nRefCount >= 0 ); - if ( m_nRefCount == 0 ) - { - FollowEntity( NULL ); - g_pNotify->ClearEntity( this ); - SetContextThink( &CEntityParticleTrail::SUB_Remove, gpGlobals->curtime + m_Info.m_flLifetime, s_pRetireContext ); - } -} - - -//----------------------------------------------------------------------------- -// Clean up when the entity goes away. -//----------------------------------------------------------------------------- -void CEntityParticleTrail::NotifySystemEvent( CBaseEntity *pNotify, notify_system_event_t eventType, const notify_system_event_params_t ¶ms ) -{ - BaseClass::NotifySystemEvent( pNotify, eventType, params ); - Assert( pNotify == GetMoveParent() ); - if ( eventType == NOTIFY_EVENT_DESTROY ) - { - FollowEntity( NULL ); - g_pNotify->ClearEntity( this ); - if ( m_nRefCount != 0 ) - { - m_nRefCount = 0; - SetContextThink( &CEntityParticleTrail::SUB_Remove, gpGlobals->curtime + m_Info.m_flLifetime, s_pRetireContext ); - } - } -} - - -//----------------------------------------------------------------------------- -// Suppression count -//----------------------------------------------------------------------------- -void CEntityParticleTrail::Destroy( CBaseEntity *pTarget, const EntityParticleTrailInfo_t &info ) -{ - int iMaterialName = GetMaterialIndex( STRING(info.m_strMaterialName) ); - - // Look for the particle trail attached to this entity + decrease refcount - CBaseEntity *pNext; - for ( CBaseEntity *pChild = pTarget->FirstMoveChild(); pChild; pChild = pNext ) - { - pNext = pChild->NextMovePeer(); - CEntityParticleTrail *pTrail = dynamic_cast(pChild); - if ( !pTrail || (pTrail->m_iMaterialName != iMaterialName) ) - continue; - - pTrail->DecrementRefCount(); - } -} - - -//----------------------------------------------------------------------------- -// Attach to an entity -//----------------------------------------------------------------------------- -void CEntityParticleTrail::AttachToEntity( CBaseEntity *pTarget ) -{ - FollowEntity( pTarget ); - g_pNotify->AddEntity( this, pTarget ); -} diff --git a/game/server/EntityParticleTrail.h b/game/server/EntityParticleTrail.h deleted file mode 100644 index ee9ea76fb..000000000 --- a/game/server/EntityParticleTrail.h +++ /dev/null @@ -1,52 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ENTITYPARTICLETRAIL_H -#define ENTITYPARTICLETRAIL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "baseparticleentity.h" -#include "entityparticletrail_shared.h" - - -//----------------------------------------------------------------------------- -// Spawns particles after the entity -//----------------------------------------------------------------------------- -class CEntityParticleTrail : public CBaseParticleEntity -{ - DECLARE_DATADESC(); - DECLARE_CLASS( CEntityParticleTrail, CBaseParticleEntity ); - DECLARE_SERVERCLASS(); - -public: - static CEntityParticleTrail *Create( CBaseEntity *pTarget, const EntityParticleTrailInfo_t &info, CBaseEntity *pConstraint ); - static void Destroy( CBaseEntity *pTarget, const EntityParticleTrailInfo_t &info ); - - void Spawn(); - virtual void UpdateOnRemove(); - - // Force our constraint entity to be trasmitted - virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ); - - // Clean up when the entity goes away. - virtual void NotifySystemEvent( CBaseEntity *pNotify, notify_system_event_t eventType, const notify_system_event_params_t ¶ms ); - -private: - void AttachToEntity( CBaseEntity *pTarget ); - void IncrementRefCount(); - void DecrementRefCount(); - - CNetworkVar( int, m_iMaterialName ); - CNetworkVarEmbedded( EntityParticleTrailInfo_t, m_Info ); - CNetworkHandle( CBaseEntity, m_hConstraintEntity ); - - int m_nRefCount; -}; - -#endif // ENTITYPARTICLETRAIL_H diff --git a/game/server/EnvBeam.cpp b/game/server/EnvBeam.cpp deleted file mode 100644 index 6ae87725d..000000000 --- a/game/server/EnvBeam.cpp +++ /dev/null @@ -1,762 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements visual effects entities: sprites, beams, bubbles, etc. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "beam_shared.h" -#include "ndebugoverlay.h" -#include "filters.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// Keeps us from doing strcmps in the tracefilter. -string_t g_iszPhysicsPropClassname; - -enum Touch_t -{ - touch_none = 0, - touch_player_only, - touch_npc_only, - touch_player_or_npc, - touch_player_or_npc_or_physicsprop, -}; - -class CEnvBeam : public CBeam -{ -public: - DECLARE_CLASS( CEnvBeam, CBeam ); - - void Spawn( void ); - void Precache( void ); - void Activate( void ); - - void StrikeThink( void ); - void UpdateThink( void ); - void RandomArea( void ); - void RandomPoint( const Vector &vecSrc ); - void Zap( const Vector &vecSrc, const Vector &vecDest ); - - void Strike( void ); - - bool PassesTouchFilters(CBaseEntity *pOther); - - void InputTurnOn( inputdata_t &inputdata ); - void InputTurnOff( inputdata_t &inputdata ); - void InputToggle( inputdata_t &inputdata ); - void InputStrikeOnce( inputdata_t &inputdata ); - - void TurnOn( void ); - void TurnOff( void ); - void Toggle( void ); - - const char *GetDecalName( void ){ return STRING( m_iszDecal );} - - inline bool ServerSide( void ) - { - if ( m_life == 0 && !HasSpawnFlags(SF_BEAM_RING) ) - return true; - - return false; - } - - DECLARE_DATADESC(); - - void BeamUpdateVars( void ); - - int m_active; - int m_spriteTexture; - - string_t m_iszStartEntity; - string_t m_iszEndEntity; - float m_life; - float m_boltWidth; - float m_noiseAmplitude; - int m_speed; - float m_restrike; - string_t m_iszSpriteName; - int m_frameStart; - - float m_radius; - - Touch_t m_TouchType; - string_t m_iFilterName; - EHANDLE m_hFilter; - - string_t m_iszDecal; - - COutputEvent m_OnTouchedByEntity; -}; - -LINK_ENTITY_TO_CLASS( env_beam, CEnvBeam ); - -BEGIN_DATADESC( CEnvBeam ) - - DEFINE_FIELD( m_active, FIELD_INTEGER ), - DEFINE_FIELD( m_spriteTexture, FIELD_INTEGER ), - - DEFINE_KEYFIELD( m_iszStartEntity, FIELD_STRING, "LightningStart" ), - DEFINE_KEYFIELD( m_iszEndEntity, FIELD_STRING, "LightningEnd" ), - DEFINE_KEYFIELD( m_life, FIELD_FLOAT, "life" ), - DEFINE_KEYFIELD( m_boltWidth, FIELD_FLOAT, "BoltWidth" ), - DEFINE_KEYFIELD( m_noiseAmplitude, FIELD_FLOAT, "NoiseAmplitude" ), - DEFINE_KEYFIELD( m_speed, FIELD_INTEGER, "TextureScroll" ), - DEFINE_KEYFIELD( m_restrike, FIELD_FLOAT, "StrikeTime" ), - DEFINE_KEYFIELD( m_iszSpriteName, FIELD_STRING, "texture" ), - DEFINE_KEYFIELD( m_frameStart, FIELD_INTEGER, "framestart" ), - DEFINE_KEYFIELD( m_radius, FIELD_FLOAT, "Radius" ), - DEFINE_KEYFIELD( m_TouchType, FIELD_INTEGER, "TouchType" ), - DEFINE_KEYFIELD( m_iFilterName, FIELD_STRING, "filtername" ), - DEFINE_KEYFIELD( m_iszDecal, FIELD_STRING, "decalname" ), - - DEFINE_FIELD( m_hFilter, FIELD_EHANDLE ), - - // Function Pointers - DEFINE_FUNCTION( StrikeThink ), - DEFINE_FUNCTION( UpdateThink ), - - // Input functions - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - DEFINE_INPUTFUNC( FIELD_VOID, "StrikeOnce", InputStrikeOnce ), - - DEFINE_OUTPUT( m_OnTouchedByEntity, "OnTouchedByEntity" ), - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvBeam::Spawn( void ) -{ - if ( !m_iszSpriteName ) - { - SetThink( &CEnvBeam::SUB_Remove ); - return; - } - - BaseClass::Spawn(); - - m_noiseAmplitude = MIN(MAX_BEAM_NOISEAMPLITUDE, m_noiseAmplitude); - - // Check for tapering - if ( HasSpawnFlags( SF_BEAM_TAPEROUT ) ) - { - SetWidth( m_boltWidth ); - SetEndWidth( 0 ); - } - else - { - SetWidth( m_boltWidth ); - SetEndWidth( GetWidth() ); // Note: EndWidth is not scaled - } - - if ( ServerSide() ) - { - SetThink( &CEnvBeam::UpdateThink ); - SetNextThink( gpGlobals->curtime ); - SetFireTime( gpGlobals->curtime ); - - if ( GetEntityName() != NULL_STRING ) - { - if ( !(m_spawnflags & SF_BEAM_STARTON) ) - { - AddEffects( EF_NODRAW ); - m_active = 0; - SetNextThink( TICK_NEVER_THINK ); - } - else - { - m_active = 1; - } - } - } - else - { - m_active = 0; - if ( !GetEntityName() || FBitSet(m_spawnflags, SF_BEAM_STARTON) ) - { - SetThink( &CEnvBeam::StrikeThink ); - SetNextThink( gpGlobals->curtime + 1.0f ); - } - } - -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvBeam::Precache( void ) -{ - if ( !Q_stristr( STRING(m_iszSpriteName), ".vmt" ) ) - { - // HACK/YWB: This was almost always the laserbeam.spr, so alloc'ing the name a second time with the proper extension isn't going to - // kill us on memrory. - //Warning( "Level Design Error: %s (%i:%s) Sprite name (%s) missing .vmt extension!\n", - // STRING( m_iClassname ), entindex(), GetEntityName(), STRING(m_iszSpriteName) ); - - char fixedname[ 512 ]; - Q_strncpy( fixedname, STRING( m_iszSpriteName ), sizeof( fixedname ) ); - - Q_SetExtension( fixedname, ".vmt", sizeof( fixedname ) ); - - m_iszSpriteName = AllocPooledString( fixedname ); - } - - g_iszPhysicsPropClassname = AllocPooledString( "prop_physics" ); - - m_spriteTexture = PrecacheModel( STRING(m_iszSpriteName) ); - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvBeam::Activate( void ) -{ - // Get a handle to my filter entity if there is one - if (m_iFilterName != NULL_STRING) - { - m_hFilter = dynamic_cast(gEntList.FindEntityByName( NULL, m_iFilterName )); - } - - BaseClass::Activate(); - - if ( ServerSide() ) - BeamUpdateVars(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler to turn the lightning on either continually or for -// interval refiring. -//----------------------------------------------------------------------------- -void CEnvBeam::InputTurnOn( inputdata_t &inputdata ) -{ - if ( !m_active ) - { - TurnOn(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler to turn the lightning off. -//----------------------------------------------------------------------------- -void CEnvBeam::InputTurnOff( inputdata_t &inputdata ) -{ - if ( m_active ) - { - TurnOff(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler to toggle the lightning on/off. -//----------------------------------------------------------------------------- -void CEnvBeam::InputToggle( inputdata_t &inputdata ) -{ - if ( m_active ) - { - TurnOff(); - } - else - { - TurnOn(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for making the beam strike once. This will not affect -// any interval refiring that might be going on. If the lifetime is set -// to zero (infinite) it will turn on and stay on. -//----------------------------------------------------------------------------- -void CEnvBeam::InputStrikeOnce( inputdata_t &inputdata ) -{ - Strike(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Turns the lightning on. If it is set for interval refiring, it will -// begin doing so. If it is set to be continually on, it will do so. -//----------------------------------------------------------------------------- -void CEnvBeam::TurnOn( void ) -{ - m_active = 1; - - if ( ServerSide() ) - { - RemoveEffects( EF_NODRAW ); - DoSparks( GetAbsStartPos(), GetAbsEndPos() ); - - SetThink( &CEnvBeam::UpdateThink ); - SetNextThink( gpGlobals->curtime ); - SetFireTime( gpGlobals->curtime ); - } - else - { - SetThink( &CEnvBeam::StrikeThink ); - SetNextThink( gpGlobals->curtime ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvBeam::TurnOff( void ) -{ - m_active = 0; - - if ( ServerSide() ) - { - AddEffects( EF_NODRAW ); - } - - SetNextThink( TICK_NEVER_THINK ); - SetThink( NULL ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Think function for striking at intervals. -//----------------------------------------------------------------------------- -void CEnvBeam::StrikeThink( void ) -{ - if ( m_life != 0 ) - { - if ( m_spawnflags & SF_BEAM_RANDOM ) - SetNextThink( gpGlobals->curtime + m_life + random->RandomFloat( 0, m_restrike ) ); - else - SetNextThink( gpGlobals->curtime + m_life + m_restrike ); - } - m_active = 1; - - if (!m_iszEndEntity) - { - if (!m_iszStartEntity) - { - RandomArea( ); - } - else - { - CBaseEntity *pStart = RandomTargetname( STRING(m_iszStartEntity) ); - if (pStart != NULL) - { - RandomPoint( pStart->GetAbsOrigin() ); - } - else - { - Msg( "env_beam: unknown entity \"%s\"\n", STRING(m_iszStartEntity) ); - } - } - return; - } - - Strike(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Strikes once for its configured lifetime. -//----------------------------------------------------------------------------- -void CEnvBeam::Strike( void ) -{ - CBroadcastRecipientFilter filter; - - CBaseEntity *pStart = RandomTargetname( STRING(m_iszStartEntity) ); - CBaseEntity *pEnd = RandomTargetname( STRING(m_iszEndEntity) ); - - if ( pStart == NULL || pEnd == NULL ) - return; - - m_speed = (int)clamp( m_speed, 0, MAX_BEAM_SCROLLSPEED ); - - int pointStart = IsStaticPointEntity( pStart ); - int pointEnd = IsStaticPointEntity( pEnd ); - - if ( pointStart || pointEnd ) - { - if ( m_spawnflags & SF_BEAM_RING ) - { - // don't work - return; - } - - te->BeamEntPoint( filter, 0.0, - pointStart ? 0 : pStart->entindex(), - pointStart ? &pStart->GetAbsOrigin() : NULL, - pointEnd ? 0 : pEnd->entindex(), - pointEnd ? &pEnd->GetAbsOrigin() : NULL, - m_spriteTexture, - 0, // No halo - m_frameStart, - (int)m_flFrameRate, - m_life, - m_boltWidth, - m_boltWidth, // End width - 0, // No fade - m_noiseAmplitude, - m_clrRender->r, m_clrRender->g, m_clrRender->b, m_clrRender->a, - m_speed ); - } - else - { - if ( m_spawnflags & SF_BEAM_RING) - { - te->BeamRing( filter, 0.0, - pStart->entindex(), - pEnd->entindex(), - m_spriteTexture, - 0, // No halo - m_frameStart, - (int)m_flFrameRate, - m_life, - m_boltWidth, - 0, // No spread - m_noiseAmplitude, - m_clrRender->r, - m_clrRender->g, - m_clrRender->b, - m_clrRender->a, - m_speed ); - } - else - { - te->BeamEnts( filter, 0.0, - pStart->entindex(), - pEnd->entindex(), - m_spriteTexture, - 0, // No halo - m_frameStart, - (int)m_flFrameRate, - m_life, - m_boltWidth, - m_boltWidth, // End width - 0, // No fade - m_noiseAmplitude, - m_clrRender->r, - m_clrRender->g, - m_clrRender->b, - m_clrRender->a, - m_speed ); - - } - } - - DoSparks( pStart->GetAbsOrigin(), pEnd->GetAbsOrigin() ); - if ( m_flDamage > 0 ) - { - trace_t tr; - UTIL_TraceLine( pStart->GetAbsOrigin(), pEnd->GetAbsOrigin(), MASK_SOLID, NULL, COLLISION_GROUP_NONE, &tr ); - BeamDamageInstant( &tr, m_flDamage ); - } - -} - - -class CTraceFilterPlayersNPCs : public ITraceFilter -{ -public: - bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ) - { - CBaseEntity *pEntity = EntityFromEntityHandle( pServerEntity ); - if ( pEntity ) - { - if ( pEntity->IsPlayer() || pEntity->MyNPCPointer() ) - return true; - } - - return false; - } - virtual TraceType_t GetTraceType() const - { - return TRACE_ENTITIES_ONLY; - } -}; - -class CTraceFilterPlayersNPCsPhysicsProps : public ITraceFilter -{ -public: - bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ) - { - CBaseEntity *pEntity = EntityFromEntityHandle( pServerEntity ); - if ( pEntity ) - { - if ( pEntity->IsPlayer() || pEntity->MyNPCPointer() || pEntity->m_iClassname == g_iszPhysicsPropClassname ) - return true; - } - - return false; - } - virtual TraceType_t GetTraceType() const - { - return TRACE_ENTITIES_ONLY; - } -}; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CEnvBeam::PassesTouchFilters(CBaseEntity *pOther) -{ - bool fPassedSoFar = false; - - // Touched some player or NPC! - if( m_TouchType != touch_npc_only ) - { - if( pOther->IsPlayer() ) - { - fPassedSoFar = true; - } - } - - if( m_TouchType != touch_player_only ) - { - if( pOther->IsNPC() ) - { - fPassedSoFar = true; - } - } - - if( m_TouchType == touch_player_or_npc_or_physicsprop ) - { - if( pOther->m_iClassname == g_iszPhysicsPropClassname ) - { - fPassedSoFar = true; - } - } - - if( fPassedSoFar ) - { - CBaseFilter* pFilter = (CBaseFilter*)(m_hFilter.Get()); - return (!pFilter) ? true : pFilter->PassesFilter( this, pOther ); - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvBeam::UpdateThink( void ) -{ - // Apply damage every 1/10th of a second. - if ( ( m_flDamage > 0 ) && ( gpGlobals->curtime >= m_flFireTime + 0.1 ) ) - { - trace_t tr; - UTIL_TraceLine( GetAbsStartPos(), GetAbsEndPos(), MASK_SOLID, NULL, COLLISION_GROUP_NONE, &tr ); - BeamDamage( &tr ); - // BeamDamage calls RelinkBeam, so no need to call it again. - } - else - { - RelinkBeam(); - } - - if( m_TouchType != touch_none ) - { - trace_t tr; - Ray_t ray; - ray.Init( GetAbsStartPos(), GetAbsEndPos() ); - - if( m_TouchType == touch_player_or_npc_or_physicsprop ) - { - CTraceFilterPlayersNPCsPhysicsProps traceFilter; - enginetrace->TraceRay( ray, MASK_SHOT, &traceFilter, &tr ); - } - else - { - CTraceFilterPlayersNPCs traceFilter; - enginetrace->TraceRay( ray, MASK_SHOT, &traceFilter, &tr ); - } - - if( tr.fraction != 1.0 && PassesTouchFilters( tr.m_pEnt ) ) - { - m_OnTouchedByEntity.FireOutput( tr.m_pEnt, this, 0 ); - return; - } - } - - SetNextThink( gpGlobals->curtime ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &vecSrc - -// &vecDest - -//----------------------------------------------------------------------------- -void CEnvBeam::Zap( const Vector &vecSrc, const Vector &vecDest ) -{ - CBroadcastRecipientFilter filter; - - te->BeamPoints( filter, 0.0, - &vecSrc, - &vecDest, - m_spriteTexture, - 0, // No halo - m_frameStart, - (int)m_flFrameRate, - m_life, - m_boltWidth, - m_boltWidth, // End width - 0, // No fade - m_noiseAmplitude, - m_clrRender->r, - m_clrRender->g, - m_clrRender->b, - m_clrRender->a, - m_speed ); - - DoSparks( vecSrc, vecDest ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvBeam::RandomArea( void ) -{ - int iLoops = 0; - - for (iLoops = 0; iLoops < 10; iLoops++) - { - Vector vecSrc = GetAbsOrigin(); - - Vector vecDir1 = Vector( random->RandomFloat( -1.0, 1.0 ), random->RandomFloat( -1.0, 1.0 ),random->RandomFloat( -1.0, 1.0 ) ); - VectorNormalize( vecDir1 ); - trace_t tr1; - UTIL_TraceLine( vecSrc, vecSrc + vecDir1 * m_radius, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr1 ); - - if (tr1.fraction == 1.0) - continue; - - Vector vecDir2; - do { - vecDir2 = Vector( random->RandomFloat( -1.0, 1.0 ), random->RandomFloat( -1.0, 1.0 ),random->RandomFloat( -1.0, 1.0 ) ); - } while (DotProduct(vecDir1, vecDir2 ) > 0); - VectorNormalize( vecDir2 ); - trace_t tr2; - UTIL_TraceLine( vecSrc, vecSrc + vecDir2 * m_radius, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr2 ); - - if (tr2.fraction == 1.0) - continue; - - if ((tr1.endpos - tr2.endpos).Length() < m_radius * 0.1) - continue; - - UTIL_TraceLine( tr1.endpos, tr2.endpos, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr2 ); - - if (tr2.fraction != 1.0) - continue; - - Zap( tr1.endpos, tr2.endpos ); - - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : vecSrc - -//----------------------------------------------------------------------------- -void CEnvBeam::RandomPoint( const Vector &vecSrc ) -{ - int iLoops = 0; - - for (iLoops = 0; iLoops < 10; iLoops++) - { - Vector vecDir1 = Vector( random->RandomFloat( -1.0, 1.0 ), random->RandomFloat( -1.0, 1.0 ),random->RandomFloat( -1.0, 1.0 ) ); - VectorNormalize( vecDir1 ); - trace_t tr1; - UTIL_TraceLine( vecSrc, vecSrc + vecDir1 * m_radius, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr1 ); - - if ((tr1.endpos - vecSrc).Length() < m_radius * 0.1) - continue; - - if (tr1.fraction == 1.0) - continue; - - Zap( vecSrc, tr1.endpos ); - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvBeam::BeamUpdateVars( void ) -{ - CBaseEntity *pStart = gEntList.FindEntityByName( NULL, m_iszStartEntity ); - CBaseEntity *pEnd = gEntList.FindEntityByName( NULL, m_iszEndEntity ); - - if (( pStart == NULL ) || ( pEnd == NULL )) - { - return; - } - - m_nNumBeamEnts = 2; - - m_speed = (int)clamp( m_speed, 0, MAX_BEAM_SCROLLSPEED ); - - // NOTE: If the end entity is the beam itself (and the start entity - // isn't *also* the beam itself, we've got problems. This is a problem - // because SetAbsStartPos actually sets the entity's origin. - if ( ( pEnd == this ) && ( pStart != this ) ) - { - DevMsg("env_beams cannot have the end entity be the beam itself\n" - "unless the start entity is also the beam itself!\n" ); - Assert(0); - } - - SetModelName( m_iszSpriteName ); - SetTexture( m_spriteTexture ); - - SetType( BEAM_ENTPOINT ); - - if ( IsStaticPointEntity( pStart ) ) - { - SetAbsStartPos( pStart->GetAbsOrigin() ); - } - else - { - SetStartEntity( pStart ); - } - - if ( IsStaticPointEntity( pEnd ) ) - { - SetAbsEndPos( pEnd->GetAbsOrigin() ); - } - else - { - SetEndEntity( pEnd ); - } - - RelinkBeam(); - - SetWidth( MIN(MAX_BEAM_WIDTH, m_boltWidth) ); - SetNoise( MIN(MAX_BEAM_NOISEAMPLITUDE, m_noiseAmplitude) ); - SetFrame( m_frameStart ); - SetScrollRate( m_speed ); - if ( m_spawnflags & SF_BEAM_SHADEIN ) - { - SetBeamFlags( FBEAM_SHADEIN ); - } - else if ( m_spawnflags & SF_BEAM_SHADEOUT ) - { - SetBeamFlags( FBEAM_SHADEOUT ); - } -} diff --git a/game/server/EnvFade.cpp b/game/server/EnvFade.cpp deleted file mode 100644 index c4759cadc..000000000 --- a/game/server/EnvFade.cpp +++ /dev/null @@ -1,200 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements visual effects entities: sprites, beams, bubbles, etc. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "shake.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CEnvFade : public CLogicalEntity -{ -private: - - float m_Duration; - float m_HoldTime; - - COutputEvent m_OnBeginFade; - - DECLARE_DATADESC(); - -public: - DECLARE_CLASS( CEnvFade, CLogicalEntity ); - - virtual void Spawn( void ); - - inline float Duration( void ) { return m_Duration; } - inline float HoldTime( void ) { return m_HoldTime; } - - inline void SetDuration( float duration ) { m_Duration = duration; } - inline void SetHoldTime( float hold ) { m_HoldTime = hold; } - - int DrawDebugTextOverlays(void); - - // Inputs - void InputFade( inputdata_t &inputdata ); -}; - -LINK_ENTITY_TO_CLASS( env_fade, CEnvFade ); - -BEGIN_DATADESC( CEnvFade ) - - DEFINE_KEYFIELD( m_Duration, FIELD_FLOAT, "duration" ), - DEFINE_KEYFIELD( m_HoldTime, FIELD_FLOAT, "holdtime" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Fade", InputFade ), - - DEFINE_OUTPUT( m_OnBeginFade, "OnBeginFade"), - -END_DATADESC() - - - -#define SF_FADE_IN 0x0001 // Fade in, not out -#define SF_FADE_MODULATE 0x0002 // Modulate, don't blend -#define SF_FADE_ONLYONE 0x0004 -#define SF_FADE_STAYOUT 0x0008 - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvFade::Spawn( void ) -{ -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that does the screen fade. -//----------------------------------------------------------------------------- -void CEnvFade::InputFade( inputdata_t &inputdata ) -{ - int fadeFlags = 0; - - if ( m_spawnflags & SF_FADE_IN ) - { - fadeFlags |= FFADE_IN; - } - else - { - fadeFlags |= FFADE_OUT; - } - - if ( m_spawnflags & SF_FADE_MODULATE ) - { - fadeFlags |= FFADE_MODULATE; - } - - if ( m_spawnflags & SF_FADE_STAYOUT ) - { - fadeFlags |= FFADE_STAYOUT; - } - - if ( m_spawnflags & SF_FADE_ONLYONE ) - { - if ( inputdata.pActivator->IsNetClient() ) - { - UTIL_ScreenFade( inputdata.pActivator, m_clrRender, Duration(), HoldTime(), fadeFlags ); - } - } - else - { - UTIL_ScreenFadeAll( m_clrRender, Duration(), HoldTime(), fadeFlags|FFADE_PURGE ); - } - - m_OnBeginFade.FireOutput( inputdata.pActivator, this ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Fetches the arguments from the command line for the fadein and fadeout -// console commands. -// Input : flTime - Returns the fade time in seconds (the time to fade in or out) -// clrFade - Returns the color to fade to or from. -//----------------------------------------------------------------------------- -static void GetFadeParms( const CCommand &args, float &flTime, color32 &clrFade) -{ - flTime = 2.0f; - - if ( args.ArgC() > 1 ) - { - flTime = atof( args[1] ); - } - - clrFade.r = 0; - clrFade.g = 0; - clrFade.b = 0; - clrFade.a = 255; - - if ( args.ArgC() > 4 ) - { - clrFade.r = atoi( args[2] ); - clrFade.g = atoi( args[3] ); - clrFade.b = atoi( args[4] ); - - if ( args.ArgC() == 5 ) - { - clrFade.a = atoi( args[5] ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Console command to fade out to a given color. -//----------------------------------------------------------------------------- -static void CC_FadeOut( const CCommand &args ) -{ - float flTime; - color32 clrFade; - GetFadeParms( args, flTime, clrFade ); - - CBasePlayer *pPlayer = UTIL_GetCommandClient(); - UTIL_ScreenFade( pPlayer, clrFade, flTime, 0, FFADE_OUT | FFADE_PURGE | FFADE_STAYOUT ); -} -static ConCommand fadeout("fadeout", CC_FadeOut, "fadeout {time r g b}: Fades the screen to black or to the specified color over the given number of seconds.", FCVAR_CHEAT ); - - -//----------------------------------------------------------------------------- -// Purpose: Console command to fade in from a given color. -//----------------------------------------------------------------------------- -static void CC_FadeIn( const CCommand &args ) -{ - float flTime; - color32 clrFade; - GetFadeParms( args, flTime, clrFade ); - - CBasePlayer *pPlayer = UTIL_GetCommandClient(); - UTIL_ScreenFade( pPlayer, clrFade, flTime, 0, FFADE_IN | FFADE_PURGE ); -} - -static ConCommand fadein("fadein", CC_FadeIn, "fadein {time r g b}: Fades the screen in from black or from the specified color over the given number of seconds.", FCVAR_CHEAT ); - - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CEnvFade::DrawDebugTextOverlays( void ) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - - // print duration - Q_snprintf(tempstr,sizeof(tempstr)," duration: %f", m_Duration); - EntityText(text_offset,tempstr,0); - text_offset++; - - // print hold time - Q_snprintf(tempstr,sizeof(tempstr)," hold time: %f", m_HoldTime); - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} diff --git a/game/server/EnvHudHint.cpp b/game/server/EnvHudHint.cpp deleted file mode 100644 index 601787ad0..000000000 --- a/game/server/EnvHudHint.cpp +++ /dev/null @@ -1,123 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements visual effects entities: sprites, beams, bubbles, etc. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "engine/IEngineSound.h" -#include "baseentity.h" -#include "entityoutput.h" -#include "recipientfilter.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CEnvHudHint : public CPointEntity -{ -public: - DECLARE_CLASS( CEnvHudHint, CPointEntity ); - - void Spawn( void ); - void Precache( void ); - -private: - void InputShowHudHint( inputdata_t &inputdata ); - void InputHideHudHint( inputdata_t &inputdata ); - string_t m_iszMessage; - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( env_hudhint, CEnvHudHint ); - -BEGIN_DATADESC( CEnvHudHint ) - - DEFINE_KEYFIELD( m_iszMessage, FIELD_STRING, "message" ), - DEFINE_INPUTFUNC( FIELD_VOID, "ShowHudHint", InputShowHudHint ), - DEFINE_INPUTFUNC( FIELD_VOID, "HideHudHint", InputHideHudHint ), - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvHudHint::Spawn( void ) -{ - Precache(); - - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NONE ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvHudHint::Precache( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for showing the message and/or playing the sound. -//----------------------------------------------------------------------------- -void CEnvHudHint::InputShowHudHint( inputdata_t &inputdata ) -{ - CBaseEntity *pPlayer = NULL; - - if ( inputdata.pActivator && inputdata.pActivator->IsPlayer() ) - { - pPlayer = inputdata.pActivator; - } - else - { - pPlayer = UTIL_GetLocalPlayer(); - } - - if ( pPlayer ) - { - if ( !pPlayer || !pPlayer->IsNetClient() ) - return; - - CSingleUserRecipientFilter user( (CBasePlayer *)pPlayer ); - user.MakeReliable(); - UserMessageBegin( user, "KeyHintText" ); - WRITE_BYTE( 1 ); // one message - WRITE_STRING( STRING(m_iszMessage) ); - MessageEnd(); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CEnvHudHint::InputHideHudHint( inputdata_t &inputdata ) -{ - CBaseEntity *pPlayer = NULL; - - if ( inputdata.pActivator && inputdata.pActivator->IsPlayer() ) - { - pPlayer = inputdata.pActivator; - } - else - { - pPlayer = UTIL_GetLocalPlayer(); - } - - if ( pPlayer ) - { - if ( !pPlayer || !pPlayer->IsNetClient() ) - return; - - CSingleUserRecipientFilter user( (CBasePlayer *)pPlayer ); - user.MakeReliable(); - UserMessageBegin( user, "KeyHintText" ); - WRITE_BYTE( 1 ); // one message - WRITE_STRING( STRING(NULL_STRING) ); - MessageEnd(); - } -} diff --git a/game/server/EnvLaser.cpp b/game/server/EnvLaser.cpp deleted file mode 100644 index be9dcfb1b..000000000 --- a/game/server/EnvLaser.cpp +++ /dev/null @@ -1,250 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: A special kind of beam effect that traces from its start position to -// its end position and stops if it hits anything. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "EnvLaser.h" -#include "Sprite.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -LINK_ENTITY_TO_CLASS( env_laser, CEnvLaser ); - -BEGIN_DATADESC( CEnvLaser ) - - DEFINE_KEYFIELD( m_iszLaserTarget, FIELD_STRING, "LaserTarget" ), - DEFINE_FIELD( m_pSprite, FIELD_CLASSPTR ), - DEFINE_KEYFIELD( m_iszSpriteName, FIELD_STRING, "EndSprite" ), - DEFINE_FIELD( m_firePosition, FIELD_VECTOR ), - DEFINE_KEYFIELD( m_flStartFrame, FIELD_FLOAT, "framestart" ), - - // Function Pointers - DEFINE_FUNCTION( StrikeThink ), - - // Input functions - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvLaser::Spawn( void ) -{ - if ( !GetModelName() ) - { - SetThink( &CEnvLaser::SUB_Remove ); - return; - } - - SetSolid( SOLID_NONE ); // Remove model & collisions - SetThink( &CEnvLaser::StrikeThink ); - - SetEndWidth( GetWidth() ); // Note: EndWidth is not scaled - - PointsInit( GetLocalOrigin(), GetLocalOrigin() ); - - Precache( ); - - if ( !m_pSprite && m_iszSpriteName != NULL_STRING ) - { - m_pSprite = CSprite::SpriteCreate( STRING(m_iszSpriteName), GetAbsOrigin(), TRUE ); - } - else - { - m_pSprite = NULL; - } - - if ( m_pSprite ) - { - m_pSprite->SetParent( GetMoveParent() ); - m_pSprite->SetTransparency( kRenderGlow, m_clrRender->r, m_clrRender->g, m_clrRender->b, m_clrRender->a, m_nRenderFX ); - } - - if ( GetEntityName() != NULL_STRING && !(m_spawnflags & SF_BEAM_STARTON) ) - { - TurnOff(); - } - else - { - TurnOn(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvLaser::Precache( void ) -{ - SetModelIndex( PrecacheModel( STRING( GetModelName() ) ) ); - if ( m_iszSpriteName != NULL_STRING ) - PrecacheModel( STRING(m_iszSpriteName) ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CEnvLaser::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "width")) - { - SetWidth( atof(szValue) ); - } - else if (FStrEq(szKeyName, "NoiseAmplitude")) - { - SetNoise( atoi(szValue) ); - } - else if (FStrEq(szKeyName, "TextureScroll")) - { - SetScrollRate( atoi(szValue) ); - } - else if (FStrEq(szKeyName, "texture")) - { - SetModelName( AllocPooledString(szValue) ); - } - else - { - BaseClass::KeyValue( szKeyName, szValue ); - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns whether the laser is currently active. -//----------------------------------------------------------------------------- -int CEnvLaser::IsOn( void ) -{ - if ( IsEffectActive( EF_NODRAW ) ) - return 0; - return 1; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvLaser::InputTurnOn( inputdata_t &inputdata ) -{ - if (!IsOn()) - { - TurnOn(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvLaser::InputTurnOff( inputdata_t &inputdata ) -{ - if (IsOn()) - { - TurnOff(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvLaser::InputToggle( inputdata_t &inputdata ) -{ - if ( IsOn() ) - { - TurnOff(); - } - else - { - TurnOn(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvLaser::TurnOff( void ) -{ - AddEffects( EF_NODRAW ); - if ( m_pSprite ) - m_pSprite->TurnOff(); - - SetNextThink( TICK_NEVER_THINK ); - SetThink( NULL ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvLaser::TurnOn( void ) -{ - RemoveEffects( EF_NODRAW ); - if ( m_pSprite ) - m_pSprite->TurnOn(); - - m_flFireTime = gpGlobals->curtime; - - SetThink( &CEnvLaser::StrikeThink ); - - // - // Call StrikeThink here to update the end position, otherwise we will see - // the beam in the wrong place for one frame since we cleared the nodraw flag. - // - StrikeThink(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvLaser::FireAtPoint( trace_t &tr ) -{ - SetAbsEndPos( tr.endpos ); - if ( m_pSprite ) - { - UTIL_SetOrigin( m_pSprite, tr.endpos ); - } - - // Apply damage and do sparks every 1/10th of a second. - if ( gpGlobals->curtime >= m_flFireTime + 0.1 ) - { - BeamDamage( &tr ); - DoSparks( GetAbsStartPos(), tr.endpos ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvLaser::StrikeThink( void ) -{ - CBaseEntity *pEnd = RandomTargetname( STRING( m_iszLaserTarget ) ); - - Vector vecFireAt = GetAbsEndPos(); - if ( pEnd ) - { - vecFireAt = pEnd->GetAbsOrigin(); - } - - trace_t tr; - - UTIL_TraceLine( GetAbsOrigin(), vecFireAt, MASK_SOLID, NULL, COLLISION_GROUP_NONE, &tr ); - FireAtPoint( tr ); - SetNextThink( gpGlobals->curtime ); -} - - diff --git a/game/server/EnvLaser.h b/game/server/EnvLaser.h deleted file mode 100644 index a96d54a1c..000000000 --- a/game/server/EnvLaser.h +++ /dev/null @@ -1,51 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ENVLASER_H -#define ENVLASER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "baseentity.h" -#include "beam_shared.h" -#include "entityoutput.h" - - -class CSprite; - - -class CEnvLaser : public CBeam -{ - DECLARE_CLASS( CEnvLaser, CBeam ); -public: - void Spawn( void ); - void Precache( void ); - bool KeyValue( const char *szKeyName, const char *szValue ); - - void TurnOn( void ); - void TurnOff( void ); - int IsOn( void ); - - void FireAtPoint( trace_t &point ); - void StrikeThink( void ); - - void InputTurnOn( inputdata_t &inputdata ); - void InputTurnOff( inputdata_t &inputdata ); - void InputToggle( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - - string_t m_iszLaserTarget; // Name of entity or entities to strike at, randomly picked if more than one match. - CSprite *m_pSprite; - string_t m_iszSpriteName; - Vector m_firePosition; - - float m_flStartFrame; -}; - -#endif // ENVLASER_H diff --git a/game/server/EnvMessage.cpp b/game/server/EnvMessage.cpp deleted file mode 100644 index 51b2d898a..000000000 --- a/game/server/EnvMessage.cpp +++ /dev/null @@ -1,278 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements visual effects entities: sprites, beams, bubbles, etc. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "EnvMessage.h" -#include "engine/IEngineSound.h" -#include "KeyValues.h" -#include "filesystem.h" -#include "Color.h" -#include "GameStats.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -LINK_ENTITY_TO_CLASS( env_message, CMessage ); - -BEGIN_DATADESC( CMessage ) - - DEFINE_KEYFIELD( m_iszMessage, FIELD_STRING, "message" ), - DEFINE_KEYFIELD( m_sNoise, FIELD_SOUNDNAME, "messagesound" ), - DEFINE_KEYFIELD( m_MessageAttenuation, FIELD_INTEGER, "messageattenuation" ), - DEFINE_KEYFIELD( m_MessageVolume, FIELD_FLOAT, "messagevolume" ), - - DEFINE_FIELD( m_Radius, FIELD_FLOAT ), - - DEFINE_INPUTFUNC( FIELD_VOID, "ShowMessage", InputShowMessage ), - - DEFINE_OUTPUT(m_OnShowMessage, "OnShowMessage"), - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMessage::Spawn( void ) -{ - Precache(); - - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NONE ); - - switch( m_MessageAttenuation ) - { - case 1: // Medium radius - m_Radius = ATTN_STATIC; - break; - - case 2: // Large radius - m_Radius = ATTN_NORM; - break; - - case 3: //EVERYWHERE - m_Radius = ATTN_NONE; - break; - - default: - case 0: // Small radius - m_Radius = SNDLVL_IDLE; - break; - } - m_MessageAttenuation = 0; - - // Remap volume from [0,10] to [0,1]. - m_MessageVolume *= 0.1; - - // No volume, use normal - if ( m_MessageVolume <= 0 ) - { - m_MessageVolume = 1.0; - } -} - - -void CMessage::Precache( void ) -{ - if ( m_sNoise != NULL_STRING ) - { - PrecacheScriptSound( STRING(m_sNoise) ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for showing the message and/or playing the sound. -//----------------------------------------------------------------------------- -void CMessage::InputShowMessage( inputdata_t &inputdata ) -{ - CBaseEntity *pPlayer = NULL; - - if ( m_spawnflags & SF_MESSAGE_ALL ) - { - UTIL_ShowMessageAll( STRING( m_iszMessage ) ); - } - else - { - if ( inputdata.pActivator && inputdata.pActivator->IsPlayer() ) - { - pPlayer = inputdata.pActivator; - } - else - { - pPlayer = (gpGlobals->maxClients > 1) ? NULL : UTIL_GetLocalPlayer(); - } - - if ( pPlayer && pPlayer->IsPlayer() ) - { - UTIL_ShowMessage( STRING( m_iszMessage ), ToBasePlayer( pPlayer ) ); - } - } - - if ( m_sNoise != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_BODY; - ep.m_pSoundName = (char*)STRING(m_sNoise); - ep.m_flVolume = m_MessageVolume; - ep.m_SoundLevel = ATTN_TO_SNDLVL( m_Radius ); - - EmitSound( filter, entindex(), ep ); - } - - if ( m_spawnflags & SF_MESSAGE_ONCE ) - { - UTIL_Remove( this ); - } - - m_OnShowMessage.FireOutput( inputdata.pActivator, this ); -} - - -void CMessage::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - inputdata_t inputdata; - - inputdata.pActivator = NULL; - inputdata.pCaller = NULL; - - InputShowMessage( inputdata ); -} - - -class CCredits : public CPointEntity -{ -public: - DECLARE_CLASS( CMessage, CPointEntity ); - DECLARE_DATADESC(); - - void Spawn( void ); - void InputRollCredits( inputdata_t &inputdata ); - void InputRollOutroCredits( inputdata_t &inputdata ); - void InputShowLogo( inputdata_t &inputdata ); - void InputSetLogoLength( inputdata_t &inputdata ); - - COutputEvent m_OnCreditsDone; - - virtual void OnRestore(); -private: - - void RollOutroCredits(); - - bool m_bRolledOutroCredits; - float m_flLogoLength; -}; - -LINK_ENTITY_TO_CLASS( env_credits, CCredits ); - -BEGIN_DATADESC( CCredits ) - DEFINE_INPUTFUNC( FIELD_VOID, "RollCredits", InputRollCredits ), - DEFINE_INPUTFUNC( FIELD_VOID, "RollOutroCredits", InputRollOutroCredits ), - DEFINE_INPUTFUNC( FIELD_VOID, "ShowLogo", InputShowLogo ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetLogoLength", InputSetLogoLength ), - DEFINE_OUTPUT( m_OnCreditsDone, "OnCreditsDone"), - - DEFINE_FIELD( m_bRolledOutroCredits, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flLogoLength, FIELD_FLOAT ) -END_DATADESC() - -void CCredits::Spawn( void ) -{ - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NONE ); -} - -static void CreditsDone_f( void ) -{ - CCredits *pCredits = (CCredits*)gEntList.FindEntityByClassname( NULL, "env_credits" ); - - if ( pCredits ) - { - pCredits->m_OnCreditsDone.FireOutput( pCredits, pCredits ); - } -} - -static ConCommand creditsdone("creditsdone", CreditsDone_f ); - -extern ConVar sv_unlockedchapters; - -void CCredits::OnRestore() -{ - BaseClass::OnRestore(); - - if ( m_bRolledOutroCredits ) - { - // Roll them again so that the client .dll will send the "creditsdone" message and we'll - // actually get back to the main menu - RollOutroCredits(); - } -} - -void CCredits::RollOutroCredits() -{ - sv_unlockedchapters.SetValue( "15" ); - - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - - CSingleUserRecipientFilter user( pPlayer ); - user.MakeReliable(); - - UserMessageBegin( user, "CreditsMsg" ); - WRITE_BYTE( 3 ); - MessageEnd(); -} - -void CCredits::InputRollOutroCredits( inputdata_t &inputdata ) -{ - RollOutroCredits(); - - // In case we save restore - m_bRolledOutroCredits = true; - - gamestats->Event_Credits(); -} - -void CCredits::InputShowLogo( inputdata_t &inputdata ) -{ - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - - CSingleUserRecipientFilter user( pPlayer ); - user.MakeReliable(); - - if ( m_flLogoLength ) - { - UserMessageBegin( user, "LogoTimeMsg" ); - WRITE_FLOAT( m_flLogoLength ); - MessageEnd(); - } - else - { - UserMessageBegin( user, "CreditsMsg" ); - WRITE_BYTE( 1 ); - MessageEnd(); - } -} - -void CCredits::InputSetLogoLength( inputdata_t &inputdata ) -{ - m_flLogoLength = inputdata.value.Float(); -} - -void CCredits::InputRollCredits( inputdata_t &inputdata ) -{ - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - - CSingleUserRecipientFilter user( pPlayer ); - user.MakeReliable(); - - UserMessageBegin( user, "CreditsMsg" ); - WRITE_BYTE( 2 ); - MessageEnd(); -} diff --git a/game/server/EnvMessage.h b/game/server/EnvMessage.h deleted file mode 100644 index 951abc4bd..000000000 --- a/game/server/EnvMessage.h +++ /dev/null @@ -1,48 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ENVMESSAGE_H -#define ENVMESSAGE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "baseentity.h" -#include "entityoutput.h" - - -#define SF_MESSAGE_ONCE 0x0001 // Fade in, not out -#define SF_MESSAGE_ALL 0x0002 // Send to all clients - -class CMessage : public CPointEntity -{ -public: - DECLARE_CLASS( CMessage, CPointEntity ); - - void Spawn( void ); - void Precache( void ); - - inline void SetMessage( string_t iszMessage ) { m_iszMessage = iszMessage; } - - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - -private: - - void InputShowMessage( inputdata_t &inputdata ); - - string_t m_iszMessage; // Message to display. - float m_MessageVolume; - int m_MessageAttenuation; - float m_Radius; - - DECLARE_DATADESC(); - - string_t m_sNoise; - COutputEvent m_OnShowMessage; -}; - -#endif // ENVMESSAGE_H diff --git a/game/server/EnvShake.cpp b/game/server/EnvShake.cpp deleted file mode 100644 index 48f15d755..000000000 --- a/game/server/EnvShake.cpp +++ /dev/null @@ -1,413 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements a screen shake effect that can also shake physics objects. -// -// NOTE: UTIL_ScreenShake() will only shake players who are on the ground -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "shake.h" -#include "physics_saverestore.h" -#include "rope.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CPhysicsShake : public IMotionEvent -{ - DECLARE_SIMPLE_DATADESC(); - -public: - virtual simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) - { - Vector contact; - if ( !pObject->GetContactPoint( &contact, NULL ) ) - return SIM_NOTHING; - - // fudge the force a bit to make it more dramatic - pObject->CalculateForceOffset( m_force * (1.0f + pObject->GetMass()*0.4f), contact, &linear, &angular ); - - return SIM_LOCAL_FORCE; - } - - Vector m_force; -}; - -BEGIN_SIMPLE_DATADESC( CPhysicsShake ) - DEFINE_FIELD( m_force, FIELD_VECTOR ), -END_DATADESC() - - -class CEnvShake : public CPointEntity -{ -private: - float m_Amplitude; - float m_Frequency; - float m_Duration; - float m_Radius; // radius of 0 means all players - float m_stopTime; - float m_nextShake; - float m_currentAmp; - - Vector m_maxForce; - - IPhysicsMotionController *m_pShakeController; - CPhysicsShake m_shakeCallback; - - DECLARE_DATADESC(); - -public: - DECLARE_CLASS( CEnvShake, CPointEntity ); - - ~CEnvShake( void ); - virtual void Spawn( void ); - virtual void OnRestore( void ); - - inline float Amplitude( void ) { return m_Amplitude; } - inline float Frequency( void ) { return m_Frequency; } - inline float Duration( void ) { return m_Duration; } - float Radius( bool bPlayers = true ); - inline void SetAmplitude( float amplitude ) { m_Amplitude = amplitude; } - inline void SetFrequency( float frequency ) { m_Frequency = frequency; } - inline void SetDuration( float duration ) { m_Duration = duration; } - inline void SetRadius( float radius ) { m_Radius = radius; } - - int DrawDebugTextOverlays(void); - - // Input handlers - void InputStartShake( inputdata_t &inputdata ); - void InputStopShake( inputdata_t &inputdata ); - void InputAmplitude( inputdata_t &inputdata ); - void InputFrequency( inputdata_t &inputdata ); - - // Causes the camera/physics shakes to happen: - void ApplyShake( ShakeCommand_t command ); - void Think( void ); -}; - -LINK_ENTITY_TO_CLASS( env_shake, CEnvShake ); - -BEGIN_DATADESC( CEnvShake ) - - DEFINE_KEYFIELD( m_Amplitude, FIELD_FLOAT, "amplitude" ), - DEFINE_KEYFIELD( m_Frequency, FIELD_FLOAT, "frequency" ), - DEFINE_KEYFIELD( m_Duration, FIELD_FLOAT, "duration" ), - DEFINE_KEYFIELD( m_Radius, FIELD_FLOAT, "radius" ), - DEFINE_FIELD( m_stopTime, FIELD_TIME ), - DEFINE_FIELD( m_nextShake, FIELD_TIME ), - DEFINE_FIELD( m_currentAmp, FIELD_FLOAT ), - DEFINE_FIELD( m_maxForce, FIELD_VECTOR ), - DEFINE_PHYSPTR( m_pShakeController ), - DEFINE_EMBEDDED( m_shakeCallback ), - - DEFINE_INPUTFUNC( FIELD_VOID, "StartShake", InputStartShake ), - DEFINE_INPUTFUNC( FIELD_VOID, "StopShake", InputStopShake ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "Amplitude", InputAmplitude ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "Frequency", InputFrequency ), - -END_DATADESC() - - - -#define SF_SHAKE_EVERYONE 0x0001 // Don't check radius -#define SF_SHAKE_INAIR 0x0004 // Shake players in air -#define SF_SHAKE_PHYSICS 0x0008 // Shake physically (not just camera) -#define SF_SHAKE_ROPES 0x0010 // Shake ropes too. -#define SF_SHAKE_NO_VIEW 0x0020 // DON'T shake the view (only ropes and/or physics objects) -#define SF_SHAKE_NO_RUMBLE 0x0040 // DON'T Rumble the XBox Controller - - -//----------------------------------------------------------------------------- -// Purpose: Destructor. -//----------------------------------------------------------------------------- -CEnvShake::~CEnvShake( void ) -{ - if ( m_pShakeController ) - { - physenv->DestroyMotionController( m_pShakeController ); - } -} - - -float CEnvShake::Radius(bool bPlayers) -{ - // The radius for players is zero if SF_SHAKE_EVERYONE is set - if ( bPlayers && HasSpawnFlags(SF_SHAKE_EVERYONE)) - return 0; - return m_Radius; -} - - -//----------------------------------------------------------------------------- -// Purpose: Sets default member values when spawning. -//----------------------------------------------------------------------------- -void CEnvShake::Spawn( void ) -{ - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NONE ); - - if ( GetSpawnFlags() & SF_SHAKE_EVERYONE ) - { - m_Radius = 0; - } - - if ( HasSpawnFlags( SF_SHAKE_NO_VIEW ) && !HasSpawnFlags( SF_SHAKE_PHYSICS ) && !HasSpawnFlags( SF_SHAKE_ROPES ) ) - { - DevWarning( "env_shake %s with \"Don't shake view\" spawnflag set without \"Shake physics\" or \"Shake ropes\" spawnflags set.", GetDebugName() ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Restore the motion controller -//----------------------------------------------------------------------------- -void CEnvShake::OnRestore( void ) -{ - BaseClass::OnRestore(); - - if ( m_pShakeController ) - { - m_pShakeController->SetEventHandler( &m_shakeCallback ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvShake::ApplyShake( ShakeCommand_t command ) -{ - if ( !HasSpawnFlags( SF_SHAKE_NO_VIEW ) || !HasSpawnFlags( SF_SHAKE_NO_RUMBLE ) ) - { - bool air = (GetSpawnFlags() & SF_SHAKE_INAIR) ? true : false; - UTIL_ScreenShake( GetAbsOrigin(), Amplitude(), Frequency(), Duration(), Radius(), command, air ); - } - - if ( GetSpawnFlags() & SF_SHAKE_ROPES ) - { - CRopeKeyframe::ShakeRopes( GetAbsOrigin(), Radius(false), Frequency() ); - } - - if ( GetSpawnFlags() & SF_SHAKE_PHYSICS ) - { - if ( !m_pShakeController ) - { - m_pShakeController = physenv->CreateMotionController( &m_shakeCallback ); - } - // do physics shake - switch( command ) - { - case SHAKE_START: - case SHAKE_START_NORUMBLE: - case SHAKE_START_RUMBLEONLY: - { - m_stopTime = gpGlobals->curtime + Duration(); - m_nextShake = 0; - m_pShakeController->ClearObjects(); - SetNextThink( gpGlobals->curtime ); - m_currentAmp = Amplitude(); - CBaseEntity *list[1024]; - float radius = Radius(false); - - // probably checked "Shake Everywhere" do a big radius - if ( !radius ) - { - radius = 512; - } - Vector extents = Vector(radius, radius, radius); - extents.z = MAX(extents.z, 100); - Vector mins = GetAbsOrigin() - extents; - Vector maxs = GetAbsOrigin() + extents; - int count = UTIL_EntitiesInBox( list, 1024, mins, maxs, 0 ); - - for ( int i = 0; i < count; i++ ) - { - // - // Only shake physics entities that players can see. This is one frame out of date - // so it's possible that we could miss objects if a player changed PVS this frame. - // - if ( ( list[i]->GetMoveType() == MOVETYPE_VPHYSICS ) ) - { - IPhysicsObject *pPhys = list[i]->VPhysicsGetObject(); - if ( pPhys && pPhys->IsMoveable() ) - { - m_pShakeController->AttachObject( pPhys, false ); - pPhys->Wake(); - } - } - } - } - break; - case SHAKE_STOP: - m_pShakeController->ClearObjects(); - break; - case SHAKE_AMPLITUDE: - m_currentAmp = Amplitude(); - case SHAKE_FREQUENCY: - m_pShakeController->WakeObjects(); - break; - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that starts the screen shake. -//----------------------------------------------------------------------------- -void CEnvShake::InputStartShake( inputdata_t &inputdata ) -{ - if ( HasSpawnFlags( SF_SHAKE_NO_RUMBLE ) ) - { - ApplyShake( SHAKE_START_NORUMBLE ); - } - else if ( HasSpawnFlags( SF_SHAKE_NO_VIEW ) ) - { - ApplyShake( SHAKE_START_RUMBLEONLY ); - } - else - { - ApplyShake( SHAKE_START ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that stops the screen shake. -//----------------------------------------------------------------------------- -void CEnvShake::InputStopShake( inputdata_t &inputdata ) -{ - ApplyShake( SHAKE_STOP ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Handles changes to the shake amplitude from an external source. -//----------------------------------------------------------------------------- -void CEnvShake::InputAmplitude( inputdata_t &inputdata ) -{ - SetAmplitude( inputdata.value.Float() ); - ApplyShake( SHAKE_AMPLITUDE ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Handles changes to the shake frequency from an external source. -//----------------------------------------------------------------------------- -void CEnvShake::InputFrequency( inputdata_t &inputdata ) -{ - SetFrequency( inputdata.value.Float() ); - ApplyShake( SHAKE_FREQUENCY ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Calculates the physics shake values -//----------------------------------------------------------------------------- -void CEnvShake::Think( void ) -{ - int i; - - if ( gpGlobals->curtime > m_nextShake ) - { - // Higher frequency means we recalc the extents more often and perturb the display again - m_nextShake = gpGlobals->curtime + (1.0f / Frequency()); - - // Compute random shake extents (the shake will settle down from this) - for (i = 0; i < 2; i++ ) - { - m_maxForce[i] = random->RandomFloat( -1, 1 ); - } - // make the force it point mostly up - m_maxForce.z = 4; - VectorNormalize( m_maxForce ); - m_maxForce *= m_currentAmp * 400; // amplitude is the acceleration of a 100kg object - } - - float fraction = ( m_stopTime - gpGlobals->curtime ) / Duration(); - - if ( fraction < 0 ) - { - m_pShakeController->ClearObjects(); - return; - } - - float freq = 0; - // Ramp up frequency over duration - if ( fraction ) - { - freq = (Frequency() / fraction); - } - - // square fraction to approach zero more quickly - fraction *= fraction; - - // Sine wave that slowly settles to zero - fraction = fraction * sin( gpGlobals->curtime * freq ); - - // Add to view origin - for ( i = 0; i < 3; i++ ) - { - // store the force in the controller callback - m_shakeCallback.m_force[i] = m_maxForce[i] * fraction; - } - - // Drop amplitude a bit, less for higher frequency shakes - m_currentAmp -= m_currentAmp * ( gpGlobals->frametime / (Duration() * Frequency()) ); - SetNextThink( gpGlobals->curtime ); -} - - -//------------------------------------------------------------------------------ -// Purpose: Console command to cause a screen shake. -//------------------------------------------------------------------------------ -void CC_Shake( void ) -{ - CBasePlayer *pPlayer = UTIL_GetCommandClient(); - if (pPlayer) - { - UTIL_ScreenShake( pPlayer->WorldSpaceCenter(), 25.0, 150.0, 1.0, 750, SHAKE_START ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Returns current text offset from the top -//----------------------------------------------------------------------------- -int CEnvShake::DrawDebugTextOverlays( void ) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - - // print amplitude - Q_snprintf(tempstr,sizeof(tempstr)," magnitude: %f", m_Amplitude); - EntityText(text_offset,tempstr,0); - text_offset++; - - // print frequency - Q_snprintf(tempstr,sizeof(tempstr)," frequency: %f", m_Frequency); - EntityText(text_offset,tempstr,0); - text_offset++; - - // print duration - Q_snprintf(tempstr,sizeof(tempstr)," duration: %f", m_Duration); - EntityText(text_offset,tempstr,0); - text_offset++; - - // print radius - Q_snprintf(tempstr,sizeof(tempstr)," radius: %f", m_Radius); - EntityText(text_offset,tempstr,0); - text_offset++; - - } - return text_offset; -} - -static ConCommand shake("shake", CC_Shake, "Shake the screen.", FCVAR_CHEAT ); - - diff --git a/game/server/EnvSpark.cpp b/game/server/EnvSpark.cpp deleted file mode 100644 index 09e556fed..000000000 --- a/game/server/EnvSpark.cpp +++ /dev/null @@ -1,210 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: A point entity that periodically emits sparks and "bzzt" sounds. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "IEffects.h" -#include "engine/IEngineSound.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Emits sparks from the given location and plays a random spark sound. -// Input : pev - -// location - -//----------------------------------------------------------------------------- -void DoSpark( CBaseEntity *ent, const Vector &location, int nMagnitude, int nTrailLength, bool bPlaySound, const Vector &vecDir ) -{ - g_pEffects->Sparks( location, nMagnitude, nTrailLength, &vecDir ); - - if ( bPlaySound ) - { - ent->EmitSound( "DoSpark" ); - } -} - - -const int SF_SPARK_START_ON = 64; -const int SF_SPARK_GLOW = 128; -const int SF_SPARK_SILENT = 256; -const int SF_SPARK_DIRECTIONAL = 512; - - -class CEnvSpark : public CPointEntity -{ - DECLARE_CLASS( CEnvSpark, CPointEntity ); - -public: - CEnvSpark( void ); - - void Spawn(void); - void Precache(void); - void SparkThink(void); - - // Input handlers - void InputStartSpark( inputdata_t &inputdata ); - void InputStopSpark( inputdata_t &inputdata ); - void InputToggleSpark( inputdata_t &inputdata ); - void InputSparkOnce( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - - float m_flDelay; - int m_nGlowSpriteIndex; - int m_nMagnitude; - int m_nTrailLength; - - COutputEvent m_OnSpark; -}; - - -BEGIN_DATADESC( CEnvSpark ) - - DEFINE_KEYFIELD( m_flDelay, FIELD_FLOAT, "MaxDelay" ), - DEFINE_FIELD( m_nGlowSpriteIndex, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_nMagnitude, FIELD_INTEGER, "Magnitude" ), - DEFINE_KEYFIELD( m_nTrailLength, FIELD_INTEGER, "TrailLength" ), - - // Function Pointers - DEFINE_FUNCTION( SparkThink ), - - DEFINE_INPUTFUNC( FIELD_VOID, "StartSpark", InputStartSpark ), - DEFINE_INPUTFUNC( FIELD_VOID, "StopSpark", InputStopSpark ), - DEFINE_INPUTFUNC( FIELD_VOID, "ToggleSpark", InputToggleSpark ), - DEFINE_INPUTFUNC( FIELD_VOID, "SparkOnce", InputSparkOnce ), - - DEFINE_OUTPUT( m_OnSpark, "OnSpark" ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS(env_spark, CEnvSpark); - - -//----------------------------------------------------------------------------- -// Purpose: Constructor! Exciting, isn't it? -//----------------------------------------------------------------------------- -CEnvSpark::CEnvSpark( void ) -{ - m_nMagnitude = 1; - m_nTrailLength = 1; -} - - -//----------------------------------------------------------------------------- -// Purpose: Called when spawning, after keyvalues have been handled. -//----------------------------------------------------------------------------- -void CEnvSpark::Spawn(void) -{ - SetThink( NULL ); - SetUse( NULL ); - - if (FBitSet(m_spawnflags, SF_SPARK_START_ON)) - { - SetThink(&CEnvSpark::SparkThink); // start sparking - } - - SetNextThink( gpGlobals->curtime + 0.1 + random->RandomFloat( 0, 1.5 ) ); - - // Negative delays are not allowed - if (m_flDelay < 0) - { - m_flDelay = 0; - } - -#ifdef HL1_DLL - // Don't allow 0 delays in HL1 Port. Enforce a default - if( m_flDelay == 0 ) - { - m_flDelay = 1.0f; - } -#endif//HL1_DLL - - Precache( ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvSpark::Precache(void) -{ - m_nGlowSpriteIndex = PrecacheModel("sprites/glow01.vmt"); - - PrecacheScriptSound( "DoSpark" ); -} - -extern ConVar phys_pushscale; - -//----------------------------------------------------------------------------- -// Purpose: Emits sparks at random intervals. -//----------------------------------------------------------------------------- -void CEnvSpark::SparkThink(void) -{ - SetNextThink( gpGlobals->curtime + 0.1 + random->RandomFloat(0, m_flDelay) ); - - Vector vecDir = vec3_origin; - if ( FBitSet( m_spawnflags, SF_SPARK_DIRECTIONAL ) ) - { - AngleVectors( GetAbsAngles(), &vecDir ); - } - - DoSpark( this, WorldSpaceCenter(), m_nMagnitude, m_nTrailLength, !( m_spawnflags & SF_SPARK_SILENT ), vecDir ); - - m_OnSpark.FireOutput( this, this ); - - if (FBitSet(m_spawnflags, SF_SPARK_GLOW)) - { - CPVSFilter filter( GetAbsOrigin() ); - te->GlowSprite( filter, 0.0, &GetAbsOrigin(), m_nGlowSpriteIndex, 0.2, 1.5, 25 ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for starting the sparks. -//----------------------------------------------------------------------------- -void CEnvSpark::InputStartSpark( inputdata_t &inputdata ) -{ - SetThink(&CEnvSpark::SparkThink); - SetNextThink( gpGlobals->curtime ); -} - -//----------------------------------------------------------------------------- -// Purpose: Shoot one spark. -//----------------------------------------------------------------------------- -void CEnvSpark::InputSparkOnce( inputdata_t &inputdata ) -{ - SparkThink(); - SetNextThink( TICK_NEVER_THINK ); -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for starting the sparks. -//----------------------------------------------------------------------------- -void CEnvSpark::InputStopSpark( inputdata_t &inputdata ) -{ - SetThink(NULL); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for toggling the on/off state of the sparks. -//----------------------------------------------------------------------------- -void CEnvSpark::InputToggleSpark( inputdata_t &inputdata ) -{ - if (GetNextThink() == TICK_NEVER_THINK) - { - InputStartSpark( inputdata ); - } - else - { - InputStopSpark( inputdata ); - } -} - - diff --git a/game/server/EventLog.cpp b/game/server/EventLog.cpp deleted file mode 100644 index 8bf074577..000000000 --- a/game/server/EventLog.cpp +++ /dev/null @@ -1,252 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "EventLog.h" -#include "team.h" -#include "KeyValues.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -CEventLog::CEventLog() -{ -} - -CEventLog::~CEventLog() -{ -} - - -void CEventLog::FireGameEvent( IGameEvent *event ) -{ - PrintEvent ( event ); -} - -bool CEventLog::PrintEvent( IGameEvent *event ) -{ - const char * name = event->GetName(); - - if ( Q_strncmp(name, "server_", strlen("server_")) == 0 ) - { - return true; // we don't care about server events (engine does) - } - else if ( Q_strncmp(name, "player_", strlen("player_")) == 0 ) - { - return PrintPlayerEvent( event ); - } - else if ( Q_strncmp(name, "team_", strlen("team_")) == 0 ) - { - return PrintTeamEvent( event ); - } - else if ( Q_strncmp(name, "game_", strlen("game_")) == 0 ) - { - return PrintGameEvent( event ); - } - else - { - return PrintOtherEvent( event ); // bomb_, round_, et al - } -} - -bool CEventLog::PrintGameEvent( IGameEvent *event ) -{ -// const char * name = event->GetName() + Q_strlen("game_"); // remove prefix - - return false; -} - -bool CEventLog::PrintPlayerEvent( IGameEvent *event ) -{ - const char * eventName = event->GetName(); - const int userid = event->GetInt( "userid" ); - - if ( !Q_strncmp( eventName, "player_connect", Q_strlen("player_connect") ) ) // player connect is before the CBasePlayer pointer is setup - { - const char *name = event->GetString( "name" ); - const char *address = event->GetString( "address" ); - const char *networkid = event->GetString("networkid" ); - UTIL_LogPrintf( "\"%s<%i><%s><>\" connected, address \"%s\"\n", name, userid, networkid, address); - return true; - } - else if ( !Q_strncmp( eventName, "player_disconnect", Q_strlen("player_disconnect") ) ) - { - const char *reason = event->GetString("reason" ); - const char *name = event->GetString("name" ); - const char *networkid = event->GetString("networkid" ); - CTeam *team = NULL; - CBasePlayer *pPlayer = UTIL_PlayerByUserId( userid ); - - if ( pPlayer ) - { - team = pPlayer->GetTeam(); - } - - UTIL_LogPrintf( "\"%s<%i><%s><%s>\" disconnected (reason \"%s\")\n", name, userid, networkid, team ? team->GetName() : "", reason ); - return true; - } - - CBasePlayer *pPlayer = UTIL_PlayerByUserId( userid ); - if ( !pPlayer) - { - DevMsg( "CEventLog::PrintPlayerEvent: Failed to find player (userid: %i, event: %s)\n", userid, eventName ); - return false; - } - - if ( !Q_strncmp( eventName, "player_team", Q_strlen("player_team") ) ) - { - const bool bDisconnecting = event->GetBool( "disconnect" ); - - if ( !bDisconnecting ) - { - const int newTeam = event->GetInt( "team" ); - const int oldTeam = event->GetInt( "oldteam" ); - CTeam *team = GetGlobalTeam( newTeam ); - CTeam *oldteam = GetGlobalTeam( oldTeam ); - - UTIL_LogPrintf( "\"%s<%i><%s><%s>\" joined team \"%s\"\n", - pPlayer->GetPlayerName(), - pPlayer->GetUserID(), - pPlayer->GetNetworkIDString(), - oldteam->GetName(), - team->GetName() ); - } - - return true; - } - else if ( !Q_strncmp( eventName, "player_death", Q_strlen("player_death") ) ) - { - const int attackerid = event->GetInt("attacker" ); - -#ifdef HL2MP - const char *weapon = event->GetString( "weapon" ); -#endif - - CBasePlayer *pAttacker = UTIL_PlayerByUserId( attackerid ); - CTeam *team = pPlayer->GetTeam(); - CTeam *attackerTeam = NULL; - - if ( pAttacker ) - { - attackerTeam = pAttacker->GetTeam(); - } - if ( pPlayer == pAttacker && pPlayer ) - { - -#ifdef HL2MP - UTIL_LogPrintf( "\"%s<%i><%s><%s>\" committed suicide with \"%s\"\n", - pPlayer->GetPlayerName(), - userid, - pPlayer->GetNetworkIDString(), - team ? team->GetName() : "", - weapon - ); -#else - UTIL_LogPrintf( "\"%s<%i><%s><%s>\" committed suicide with \"%s\"\n", - pPlayer->GetPlayerName(), - userid, - pPlayer->GetNetworkIDString(), - team ? team->GetName() : "", - pAttacker->GetClassname() - ); -#endif - } - else if ( pAttacker ) - { - CTeam *attackerTeam = pAttacker->GetTeam(); - -#ifdef HL2MP - UTIL_LogPrintf( "\"%s<%i><%s><%s>\" killed \"%s<%i><%s><%s>\" with \"%s\"\n", - pAttacker->GetPlayerName(), - attackerid, - pAttacker->GetNetworkIDString(), - attackerTeam ? attackerTeam->GetName() : "", - pPlayer->GetPlayerName(), - userid, - pPlayer->GetNetworkIDString(), - team ? team->GetName() : "", - weapon - ); -#else - UTIL_LogPrintf( "\"%s<%i><%s><%s>\" killed \"%s<%i><%s><%s>\"\n", - pAttacker->GetPlayerName(), - attackerid, - pAttacker->GetNetworkIDString(), - attackerTeam ? attackerTeam->GetName() : "", - pPlayer->GetPlayerName(), - userid, - pPlayer->GetNetworkIDString(), - team ? team->GetName() : "" - ); -#endif - } - else - { - // killed by the world - UTIL_LogPrintf( "\"%s<%i><%s><%s>\" committed suicide with \"world\"\n", - pPlayer->GetPlayerName(), - userid, - pPlayer->GetNetworkIDString(), - team ? team->GetName() : "" - ); - } - return true; - } - else if ( !Q_strncmp( eventName, "player_activate", Q_strlen("player_activate") ) ) - { - UTIL_LogPrintf( "\"%s<%i><%s><>\" entered the game\n", - pPlayer->GetPlayerName(), - userid, - pPlayer->GetNetworkIDString() - ); - - return true; - } - else if ( !Q_strncmp( eventName, "player_changename", Q_strlen("player_changename") ) ) - { - const char *newName = event->GetString( "newname" ); - const char *oldName = event->GetString( "oldname" ); - CTeam *team = pPlayer->GetTeam(); - UTIL_LogPrintf( "\"%s<%i><%s><%s>\" changed name to \"%s\"\n", - oldName, - userid, - pPlayer->GetNetworkIDString(), - team ? team->GetName() : "", - newName - ); - return true; - } - -// ignored events -//player_hurt - return false; -} - -bool CEventLog::PrintTeamEvent( IGameEvent *event ) -{ -// const char * name = event->GetName() + Q_strlen("team_"); // remove prefix - - return false; -} - -bool CEventLog::PrintOtherEvent( IGameEvent *event ) -{ - return false; -} - - -bool CEventLog::Init() -{ - ListenForGameEvent( "player_changename" ); - ListenForGameEvent( "player_activate" ); - ListenForGameEvent( "player_death" ); - ListenForGameEvent( "player_team" ); - ListenForGameEvent( "player_disconnect" ); - ListenForGameEvent( "player_connect" ); - - return true; -} diff --git a/game/server/EventLog.h b/game/server/EventLog.h deleted file mode 100644 index 5ab760940..000000000 --- a/game/server/EventLog.h +++ /dev/null @@ -1,46 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#if !defined EVENTLOG_H -#define EVENTLOG_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "GameEventListener.h" -#include - -class CEventLog : public CGameEventListener, public CBaseGameSystem -{ - -public: - CEventLog(); - virtual ~CEventLog(); - -public: // IGameEventListener Interface - - virtual void FireGameEvent( IGameEvent * event ); - -public: // CBaseGameSystem overrides - - virtual bool Init(); - //virtual void Shutdown() {} - -protected: - - virtual bool PrintEvent( IGameEvent * event ); - virtual bool PrintGameEvent( IGameEvent * event ); - virtual bool PrintPlayerEvent( IGameEvent * event ); - virtual bool PrintTeamEvent( IGameEvent * event ); - virtual bool PrintOtherEvent( IGameEvent * event ); -}; - -extern IGameSystem* GameLogSystem(); - -#endif // EVENTLOG_H diff --git a/game/server/GameStats_BasicStatsFunctions.cpp b/game/server/GameStats_BasicStatsFunctions.cpp deleted file mode 100644 index a9b3efdb0..000000000 --- a/game/server/GameStats_BasicStatsFunctions.cpp +++ /dev/null @@ -1,183 +0,0 @@ -//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#include "GameStats.h" - -void BasicGameStatsRecord_t::Clear() -{ - m_nCount = 0; - m_nSeconds = 0; - m_nCommentary = 0; - m_nHDR = 0; - m_nCaptions = 0; - m_bSteam = true; - m_bCyberCafe = false; - Q_memset( m_nSkill, 0, sizeof( m_nSkill ) ); - m_nDeaths = 0; -} - -void BasicGameStatsRecord_t::SaveToBuffer( CUtlBuffer &buf ) -{ - buf.PutInt( m_nCount ); - buf.PutInt( m_nSeconds ); - buf.PutInt( m_nCommentary ); - buf.PutInt( m_nHDR ); - buf.PutInt( m_nCaptions ); - for ( int i = 0; i < 3; ++i ) - { - buf.PutInt( m_nSkill[ i ] ); - } - - buf.PutChar( m_bSteam ? 1 : 0 ); - buf.PutChar( m_bCyberCafe ? 1 : 0 ); - buf.PutInt( m_nDeaths ); -} - -bool BasicGameStatsRecord_t::ParseFromBuffer( CUtlBuffer &buf, int iBufferStatsVersion ) -{ - bool bret = true; - m_nCount = buf.GetInt(); - - if ( m_nCount > 100000 || m_nCount < 0 ) - { - bret = false; - } - - m_nSeconds = buf.GetInt(); - // Note, don't put the buf.GetInt() in the macro since it'll get evaluated twice!!! - m_nSeconds = MAX( m_nSeconds, 0 ); - - m_nCommentary = buf.GetInt(); - if ( m_nCommentary < 0 || m_nCommentary > 100000 ) - { - bret = false; - } - - m_nHDR = buf.GetInt(); - if ( m_nHDR < 0 || m_nHDR > 100000 ) - { - bret = false; - } - - m_nCaptions = buf.GetInt(); - if ( m_nCaptions < 0 || m_nCaptions > 100000 ) - { - bret = false; - } - - for ( int i = 0; i < 3; ++i ) - { - m_nSkill[ i ] = buf.GetInt(); - if ( m_nSkill[ i ] < 0 || m_nSkill[ i ] > 100000 ) - { - bret = false; - } - } - - if ( iBufferStatsVersion > GAMESTATS_FILE_VERSION_OLD ) - { - m_bSteam = buf.GetChar() ? true : false; - } - if ( iBufferStatsVersion > GAMESTATS_FILE_VERSION_OLD2 ) - { - m_bCyberCafe = buf.GetChar() ? true : false; - } - if ( iBufferStatsVersion > GAMESTATS_FILE_VERSION_OLD5 ) - { - m_nDeaths = buf.GetInt(); - } - - return bret; -} - -void BasicGameStats_t::Clear() -{ - m_nSecondsToCompleteGame = 0; - m_Summary.Clear(); - m_MapTotals.Purge(); -} - -void BasicGameStats_t::SaveToBuffer( CUtlBuffer& buf ) -{ - buf.PutInt( m_nSecondsToCompleteGame ); - - m_Summary.SaveToBuffer( buf ); - - int c = m_MapTotals.Count(); - buf.PutInt( c ); - for ( int i = m_MapTotals.First(); i != m_MapTotals.InvalidIndex(); i = m_MapTotals.Next( i ) ) - { - char const *name = m_MapTotals.GetElementName( i ); - BasicGameStatsRecord_t &rec = m_MapTotals[ i ]; - - buf.PutString( name ); - rec.SaveToBuffer( buf ); - } - - buf.PutChar( (char)m_nHL2ChaptureUnlocked ); - buf.PutChar( m_bSteam ? 1 : 0 ); - buf.PutChar( m_bCyberCafe ? 1 : 0 ); - buf.PutShort( (short)m_nDXLevel ); -} - -BasicGameStatsRecord_t *BasicGameStats_t::FindOrAddRecordForMap( char const *mapname ) -{ - int idx = m_MapTotals.Find( mapname ); - if ( idx == m_MapTotals.InvalidIndex() ) - { - idx = m_MapTotals.Insert( mapname ); - } - - return &m_MapTotals[ idx ]; -} - -bool BasicGameStats_t::ParseFromBuffer( CUtlBuffer& buf, int iBufferStatsVersion ) -{ - bool bret = true; - - m_nSecondsToCompleteGame = buf.GetInt(); - if ( m_nSecondsToCompleteGame < 0 || m_nSecondsToCompleteGame > 10000000 ) - { - bret = false; - } - - m_Summary.ParseFromBuffer( buf, iBufferStatsVersion ); - int c = buf.GetInt(); - if ( c > 1024 || c < 0 ) - { - bret = false; - } - - for ( int i = 0; i < c; ++i ) - { - char mapname[ 256 ]; - buf.GetString( mapname, sizeof( mapname ) ); - - BasicGameStatsRecord_t *rec = FindOrAddRecordForMap( mapname ); - bool valid= rec->ParseFromBuffer( buf, iBufferStatsVersion ); - if ( !valid ) - { - bret = false; - } - } - - if ( iBufferStatsVersion >= GAMESTATS_FILE_VERSION_OLD2 ) - { - m_nHL2ChaptureUnlocked = (int)buf.GetChar(); - m_bSteam = buf.GetChar() ? true : false; - } - if ( iBufferStatsVersion > GAMESTATS_FILE_VERSION_OLD2 ) - { - m_bCyberCafe = buf.GetChar() ? true : false; - } - if ( iBufferStatsVersion > GAMESTATS_FILE_VERSION_OLD3 ) - { - m_nDXLevel = (int)buf.GetShort(); - } - return bret; -} - diff --git a/game/server/MaterialModifyControl.cpp b/game/server/MaterialModifyControl.cpp deleted file mode 100644 index 6fa73c317..000000000 --- a/game/server/MaterialModifyControl.cpp +++ /dev/null @@ -1,289 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Material modify control entity. -// -//=============================================================================// - -#include "cbase.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//------------------------------------------------------------------------------ -// FIXME: This really should inherit from something more lightweight. -//------------------------------------------------------------------------------ - -#define MATERIAL_MODIFY_STRING_SIZE 255 -#define MATERIAL_MODIFY_ANIMATION_UNSET -1 - -// Must match C_MaterialModifyControl.cpp -enum MaterialModifyMode_t -{ - MATERIAL_MODIFY_MODE_NONE = 0, - MATERIAL_MODIFY_MODE_SETVAR = 1, - MATERIAL_MODIFY_MODE_ANIM_SEQUENCE = 2, - MATERIAL_MODIFY_MODE_FLOAT_LERP = 3, -}; - -ConVar debug_materialmodifycontrol( "debug_materialmodifycontrol", "0" ); - -class CMaterialModifyControl : public CBaseEntity -{ -public: - - DECLARE_CLASS( CMaterialModifyControl, CBaseEntity ); - - CMaterialModifyControl(); - - void Spawn( void ); - bool KeyValue( const char *szKeyName, const char *szValue ); - int UpdateTransmitState(); - int ShouldTransmit( const CCheckTransmitInfo *pInfo ); - - void SetMaterialVar( inputdata_t &inputdata ); - void SetMaterialVarToCurrentTime( inputdata_t &inputdata ); - void InputStartAnimSequence( inputdata_t &inputdata ); - void InputStartFloatLerp( inputdata_t &inputdata ); - - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - -private: - CNetworkString( m_szMaterialName, MATERIAL_MODIFY_STRING_SIZE ); - CNetworkString( m_szMaterialVar, MATERIAL_MODIFY_STRING_SIZE ); - CNetworkString( m_szMaterialVarValue, MATERIAL_MODIFY_STRING_SIZE ); - CNetworkVar( int, m_iFrameStart ); - CNetworkVar( int, m_iFrameEnd ); - CNetworkVar( bool, m_bWrap ); - CNetworkVar( float, m_flFramerate ); - CNetworkVar( bool, m_bNewAnimCommandsSemaphore ); - CNetworkVar( float, m_flFloatLerpStartValue ); - CNetworkVar( float, m_flFloatLerpEndValue ); - CNetworkVar( float, m_flFloatLerpTransitionTime ); - CNetworkVar( int, m_nModifyMode ); -}; - -LINK_ENTITY_TO_CLASS(material_modify_control, CMaterialModifyControl); - -BEGIN_DATADESC( CMaterialModifyControl ) - // Variables. - DEFINE_AUTO_ARRAY( m_szMaterialName, FIELD_CHARACTER ), - DEFINE_AUTO_ARRAY( m_szMaterialVar, FIELD_CHARACTER ), - DEFINE_AUTO_ARRAY( m_szMaterialVarValue, FIELD_CHARACTER ), - DEFINE_FIELD( m_iFrameStart, FIELD_INTEGER ), - DEFINE_FIELD( m_iFrameEnd, FIELD_INTEGER ), - DEFINE_FIELD( m_bWrap, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flFramerate, FIELD_FLOAT ), - DEFINE_FIELD( m_bNewAnimCommandsSemaphore, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flFloatLerpStartValue, FIELD_FLOAT ), - DEFINE_FIELD( m_flFloatLerpEndValue, FIELD_FLOAT ), - DEFINE_FIELD( m_flFloatLerpTransitionTime, FIELD_FLOAT ), - DEFINE_FIELD( m_nModifyMode, FIELD_INTEGER ), - // Inputs. - DEFINE_INPUTFUNC( FIELD_STRING, "SetMaterialVar", SetMaterialVar ), - DEFINE_INPUTFUNC( FIELD_VOID, "SetMaterialVarToCurrentTime", SetMaterialVarToCurrentTime ), - DEFINE_INPUTFUNC( FIELD_STRING, "StartAnimSequence", InputStartAnimSequence ), - DEFINE_INPUTFUNC( FIELD_STRING, "StartFloatLerp", InputStartFloatLerp ), -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST(CMaterialModifyControl, DT_MaterialModifyControl) - SendPropString( SENDINFO( m_szMaterialName ) ), - SendPropString( SENDINFO( m_szMaterialVar ) ), - SendPropString( SENDINFO( m_szMaterialVarValue ) ), - SendPropInt( SENDINFO(m_iFrameStart), 8 ), - SendPropInt( SENDINFO(m_iFrameEnd), 8 ), - SendPropInt( SENDINFO(m_bWrap), 1, SPROP_UNSIGNED ), - SendPropFloat( SENDINFO(m_flFramerate), 0, SPROP_NOSCALE ), - SendPropInt( SENDINFO(m_bNewAnimCommandsSemaphore), 1, SPROP_UNSIGNED ), - SendPropFloat( SENDINFO(m_flFloatLerpStartValue), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO(m_flFloatLerpEndValue), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO(m_flFloatLerpTransitionTime), 0, SPROP_NOSCALE ), - SendPropInt( SENDINFO(m_nModifyMode), 2, SPROP_UNSIGNED ), -END_SEND_TABLE() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CMaterialModifyControl::CMaterialModifyControl() -{ - m_iFrameStart = MATERIAL_MODIFY_ANIMATION_UNSET; - m_iFrameEnd = MATERIAL_MODIFY_ANIMATION_UNSET; - m_nModifyMode = MATERIAL_MODIFY_MODE_NONE; -} - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CMaterialModifyControl::Spawn( void ) -{ - Precache(); - SetSolid( SOLID_NONE ); -} - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -bool CMaterialModifyControl::KeyValue( const char *szKeyName, const char *szValue ) -{ - if ( FStrEq( szKeyName, "materialName" ) ) - { - Q_strncpy( m_szMaterialName.GetForModify(), szValue, MATERIAL_MODIFY_STRING_SIZE ); - return true; - } - - if ( FStrEq( szKeyName, "materialVar" ) ) - { - Q_strncpy( m_szMaterialVar.GetForModify(), szValue, MATERIAL_MODIFY_STRING_SIZE ); - return true; - } - - return BaseClass::KeyValue( szKeyName, szValue ); -} - -//------------------------------------------------------------------------------ -// Purpose : Send even though we don't have a model. -//------------------------------------------------------------------------------ -int CMaterialModifyControl::UpdateTransmitState() -{ - // ALWAYS transmit to all clients. - return SetTransmitState( FL_EDICT_FULLCHECK ); -} - -//----------------------------------------------------------------------------- -// Send if the parent is being sent: -//----------------------------------------------------------------------------- -int CMaterialModifyControl::ShouldTransmit( const CCheckTransmitInfo *pInfo ) -{ - CBaseEntity *pEnt = GetMoveParent(); - if ( pEnt ) - { - return pEnt->ShouldTransmit( pInfo ); - } - - return FL_EDICT_DONTSEND; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMaterialModifyControl::SetMaterialVar( inputdata_t &inputdata ) -{ - //if( debug_materialmodifycontrol.GetBool() && Q_stristr( GetDebugName(), "alyx" ) ) - //{ - //DevMsg( 1, "CMaterialModifyControl::SetMaterialVar %s %s %s=\"%s\"\n", - //GetDebugName(), m_szMaterialName.Get(), m_szMaterialVar.Get(), inputdata.value.String() ); - //} - Q_strncpy( m_szMaterialVarValue.GetForModify(), inputdata.value.String(), MATERIAL_MODIFY_STRING_SIZE ); - m_nModifyMode = MATERIAL_MODIFY_MODE_SETVAR; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMaterialModifyControl::SetMaterialVarToCurrentTime( inputdata_t &inputdata ) -{ - char temp[32]; - Q_snprintf( temp, 32, "%f", gpGlobals->curtime ); - Q_strncpy( m_szMaterialVarValue.GetForModify(), temp, MATERIAL_MODIFY_STRING_SIZE ); - m_nModifyMode = MATERIAL_MODIFY_MODE_SETVAR; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMaterialModifyControl::InputStartAnimSequence( inputdata_t &inputdata ) -{ - char parseString[255]; - Q_strncpy(parseString, inputdata.value.String(), sizeof(parseString)); - - // Get the start & end frames - char *pszParam = strtok(parseString," "); - if ( pszParam && pszParam[0] ) - { - int iFrameStart = atoi(pszParam); - - pszParam = strtok(NULL," "); - if ( pszParam && pszParam[0] ) - { - int iFrameEnd = atoi(pszParam); - - pszParam = strtok(NULL," "); - if ( pszParam && pszParam[0] ) - { - float flFramerate = atof(pszParam); - - pszParam = strtok(NULL," "); - if ( pszParam && pszParam[0] ) - { - bool bWrap = atoi(pszParam) != 0; - - // Got all the parameters. Save 'em and return; - m_iFrameStart = iFrameStart; - m_iFrameEnd = iFrameEnd; - m_flFramerate = flFramerate; - m_bWrap = bWrap; - m_nModifyMode = MATERIAL_MODIFY_MODE_ANIM_SEQUENCE; - m_bNewAnimCommandsSemaphore = !m_bNewAnimCommandsSemaphore; - return; - } - } - } - } - - Warning("%s (%s) received StartAnimSequence input without correct parameters. Syntax: \nSetting to -1 uses the last frame of the texture. should be 1 or 0.\n", GetClassname(), GetDebugName() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMaterialModifyControl::InputStartFloatLerp( inputdata_t &inputdata ) -{ - char parseString[255]; - Q_strncpy(parseString, inputdata.value.String(), sizeof(parseString)); - -// if( debug_materialmodifycontrol.GetBool() )//&& Q_stristr( GetDebugName(), "alyx" ) ) -// { -// DevMsg( 1, "CMaterialModifyControl::InputStartFloatLerp %s %s %s \"%s\"\n", -// GetDebugName(), m_szMaterialName.Get(), m_szMaterialVar.Get(), inputdata.value.String() ); -// } - - // Get the start & end values - char *pszParam = strtok(parseString," "); - if ( pszParam && pszParam[0] ) - { - float flStartValue = atof(pszParam); - - pszParam = strtok(NULL," "); - if ( pszParam && pszParam[0] ) - { - float flEndValue = atof(pszParam); - - pszParam = strtok(NULL," "); - if ( pszParam && pszParam[0] ) - { - float flTransitionTime = atof(pszParam); - - pszParam = strtok(NULL," "); - if ( pszParam && pszParam[0] ) - { - bool bWrap = atoi(pszParam) != 0; - // We don't implement wrap currently. - bWrap = bWrap; - - // Got all the parameters. Save 'em and return; - m_flFloatLerpStartValue = flStartValue; - m_flFloatLerpEndValue = flEndValue; - m_flFloatLerpTransitionTime = flTransitionTime; - m_nModifyMode = MATERIAL_MODIFY_MODE_FLOAT_LERP; - m_bNewAnimCommandsSemaphore = !m_bNewAnimCommandsSemaphore; - return; - } - } - } - } - - Warning("%s (%s) received StartFloatLerp input without correct parameters. Syntax: \n should be 1 or 0.\n", GetClassname(), GetDebugName() ); -} diff --git a/game/server/PointAngularVelocitySensor.cpp b/game/server/PointAngularVelocitySensor.cpp deleted file mode 100644 index 81d7d1003..000000000 --- a/game/server/PointAngularVelocitySensor.cpp +++ /dev/null @@ -1,529 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Used to fire events based on the orientation of a given entity. -// -// Looks at its target's anglular velocity every frame and fires outputs -// as the angular velocity passes a given threshold value. -// -//=============================================================================// - -#include "cbase.h" -#include "entityinput.h" -#include "entityoutput.h" -#include "eventqueue.h" -#include "mathlib/mathlib.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -enum -{ - AVELOCITY_SENSOR_NO_LAST_RESULT = -2 -}; - -ConVar g_debug_angularsensor( "g_debug_angularsensor", "0", FCVAR_CHEAT ); - -class CPointAngularVelocitySensor : public CPointEntity -{ - DECLARE_CLASS( CPointAngularVelocitySensor, CPointEntity ); - -public: - - CPointAngularVelocitySensor(); - void Activate(void); - void Spawn(void); - void Think(void); - -private: - - float SampleAngularVelocity(CBaseEntity *pEntity); - int CompareToThreshold(CBaseEntity *pEntity, float flThreshold, bool bFireVelocityOutput); - void FireCompareOutput(int nCompareResult, CBaseEntity *pActivator); - void DrawDebugLines( void ); - - // Input handlers - void InputTest( inputdata_t &inputdata ); - void InputTestWithInterval( inputdata_t &inputdata ); - - EHANDLE m_hTargetEntity; // Entity whose angles are being monitored. - float m_flThreshold; // The threshold angular velocity that we are looking for. - int m_nLastCompareResult; // The comparison result from our last measurement, expressed as -1, 0, or 1 - int m_nLastFireResult; // The last result for which we fire the output. - - float m_flFireTime; - float m_flFireInterval; - float m_flLastAngVelocity; - - QAngle m_lastOrientation; - - Vector m_vecAxis; - bool m_bUseHelper; - - // Outputs - COutputFloat m_AngularVelocity; - - // Compare the target's angular velocity to the threshold velocity and fire the appropriate output. - // These outputs are filtered by m_flFireInterval to ignore excessive oscillations. - COutputEvent m_OnLessThan; - COutputEvent m_OnLessThanOrEqualTo; - COutputEvent m_OnGreaterThan; - COutputEvent m_OnGreaterThanOrEqualTo; - COutputEvent m_OnEqualTo; - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS(point_angularvelocitysensor, CPointAngularVelocitySensor); - - -BEGIN_DATADESC( CPointAngularVelocitySensor ) - - // Fields - DEFINE_FIELD( m_hTargetEntity, FIELD_EHANDLE ), - DEFINE_KEYFIELD(m_flThreshold, FIELD_FLOAT, "threshold"), - DEFINE_FIELD(m_nLastCompareResult, FIELD_INTEGER), - DEFINE_FIELD( m_nLastFireResult, FIELD_INTEGER ), - DEFINE_FIELD( m_flFireTime, FIELD_TIME ), - DEFINE_KEYFIELD( m_flFireInterval, FIELD_FLOAT, "fireinterval" ), - DEFINE_FIELD( m_flLastAngVelocity, FIELD_FLOAT ), - DEFINE_FIELD( m_lastOrientation, FIELD_VECTOR ), - - // Inputs - DEFINE_INPUTFUNC(FIELD_VOID, "Test", InputTest), - DEFINE_INPUTFUNC(FIELD_VOID, "TestWithInterval", InputTestWithInterval), - - // Outputs - DEFINE_OUTPUT(m_OnLessThan, "OnLessThan"), - DEFINE_OUTPUT(m_OnLessThanOrEqualTo, "OnLessThanOrEqualTo"), - DEFINE_OUTPUT(m_OnGreaterThan, "OnGreaterThan"), - DEFINE_OUTPUT(m_OnGreaterThanOrEqualTo, "OnGreaterThanOrEqualTo"), - DEFINE_OUTPUT(m_OnEqualTo, "OnEqualTo"), - DEFINE_OUTPUT(m_AngularVelocity, "AngularVelocity"), - - DEFINE_KEYFIELD( m_vecAxis, FIELD_VECTOR, "axis" ), - DEFINE_KEYFIELD( m_bUseHelper, FIELD_BOOLEAN, "usehelper" ), - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Purpose: constructor provides default values -//----------------------------------------------------------------------------- -CPointAngularVelocitySensor::CPointAngularVelocitySensor() -{ - m_flFireInterval = 0.2f; -} - -//----------------------------------------------------------------------------- -// Purpose: Called when spawning after parsing keyvalues. -//----------------------------------------------------------------------------- -void CPointAngularVelocitySensor::Spawn(void) -{ - m_flThreshold = fabs(m_flThreshold); - m_nLastFireResult = AVELOCITY_SENSOR_NO_LAST_RESULT; - m_nLastCompareResult = AVELOCITY_SENSOR_NO_LAST_RESULT; - // m_flFireInterval = 0.2; - m_lastOrientation = vec3_angle; -} - - -//----------------------------------------------------------------------------- -// Purpose: Called after all entities in the map have spawned. -//----------------------------------------------------------------------------- -void CPointAngularVelocitySensor::Activate(void) -{ - BaseClass::Activate(); - - m_hTargetEntity = gEntList.FindEntityByName( NULL, m_target ); - - if (m_hTargetEntity) - { - SetNextThink( gpGlobals->curtime ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draws magic lines... -//----------------------------------------------------------------------------- -void CPointAngularVelocitySensor::DrawDebugLines( void ) -{ - if ( m_hTargetEntity ) - { - Vector vForward, vRight, vUp; - AngleVectors( m_hTargetEntity->GetAbsAngles(), &vForward, &vRight, &vUp ); - - NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vForward * 64, 255, 0, 0, false, 0 ); - NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vRight * 64, 0, 255, 0, false, 0 ); - NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vUp * 64, 0, 0, 255, false, 0 ); - } - - if ( m_bUseHelper == true ) - { - QAngle Angles; - Vector vAxisForward, vAxisRight, vAxisUp; - - Vector vLine = m_vecAxis - GetAbsOrigin(); - - VectorNormalize( vLine ); - - VectorAngles( vLine, Angles ); - AngleVectors( Angles, &vAxisForward, &vAxisRight, &vAxisUp ); - - NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vAxisForward * 64, 255, 0, 0, false, 0 ); - NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vAxisRight * 64, 0, 255, 0, false, 0 ); - NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + vAxisUp * 64, 0, 0, 255, false, 0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the magnitude of the entity's angular velocity. -//----------------------------------------------------------------------------- -float CPointAngularVelocitySensor::SampleAngularVelocity(CBaseEntity *pEntity) -{ - if (pEntity->GetMoveType() == MOVETYPE_VPHYSICS) - { - IPhysicsObject *pPhys = pEntity->VPhysicsGetObject(); - if (pPhys != NULL) - { - Vector vecVelocity; - AngularImpulse vecAngVelocity; - pPhys->GetVelocity(&vecVelocity, &vecAngVelocity); - - QAngle angles; - pPhys->GetPosition( NULL, &angles ); - - float dt = gpGlobals->curtime - GetLastThink(); - if ( dt == 0 ) - dt = 0.1; - - // HACKHACK: We don't expect a real 'delta' orientation here, just enough of an error estimate to tell if this thing - // is trying to move, but failing. - QAngle delta = angles - m_lastOrientation; - - if ( ( delta.Length() / dt ) < ( vecAngVelocity.Length() * 0.01 ) ) - { - return 0.0f; - } - m_lastOrientation = angles; - - if ( m_bUseHelper == false ) - { - return vecAngVelocity.Length(); - } - else - { - Vector vLine = m_vecAxis - GetAbsOrigin(); - VectorNormalize( vLine ); - - Vector vecWorldAngVelocity; - pPhys->LocalToWorldVector( &vecWorldAngVelocity, vecAngVelocity ); - float flDot = DotProduct( vecWorldAngVelocity, vLine ); - - return flDot; - } - } - } - else - { - QAngle vecAngVel = pEntity->GetLocalAngularVelocity(); - float flMax = MAX(fabs(vecAngVel[PITCH]), fabs(vecAngVel[YAW])); - - return MAX(flMax, fabs(vecAngVel[ROLL])); - } - - return 0; -} - - -//----------------------------------------------------------------------------- -// Purpose: Compares the given entity's angular velocity to the threshold velocity. -// Input : pEntity - Entity whose angular velocity is being measured. -// flThreshold - -// Output : Returns -1 if less than, 0 if equal to, or 1 if greater than the threshold. -//----------------------------------------------------------------------------- -int CPointAngularVelocitySensor::CompareToThreshold(CBaseEntity *pEntity, float flThreshold, bool bFireVelocityOutput) -{ - if (pEntity == NULL) - { - return 0; - } - - float flAngVelocity = SampleAngularVelocity(pEntity); - - if ( g_debug_angularsensor.GetBool() ) - { - DrawDebugLines(); - } - - if (bFireVelocityOutput && (flAngVelocity != m_flLastAngVelocity)) - { - m_AngularVelocity.Set(flAngVelocity, pEntity, this); - m_flLastAngVelocity = flAngVelocity; - } - - if (flAngVelocity > flThreshold) - { - return 1; - } - - if (flAngVelocity == flThreshold) - { - return 0; - } - - return -1; -} - - -//----------------------------------------------------------------------------- -// Called every frame to sense the angular velocity of the target entity. -// Output is filtered by m_flFireInterval to ignore excessive oscillations. -//----------------------------------------------------------------------------- -void CPointAngularVelocitySensor::Think(void) -{ - if (m_hTargetEntity != NULL) - { - // - // Check to see if the measure entity's angular velocity has been within - // tolerance of the threshold for the given period of time. - // - int nCompare = CompareToThreshold(m_hTargetEntity, m_flThreshold, true); - if (nCompare != m_nLastCompareResult) - { - // If we've oscillated back to where we last fired the output, don't - // fire the same output again. - if (nCompare == m_nLastFireResult) - { - m_flFireTime = 0; - } - else if (m_nLastCompareResult != AVELOCITY_SENSOR_NO_LAST_RESULT) - { - // - // The value has changed -- reset the timer. We'll fire the output if - // it stays at this value until the interval expires. - // - m_flFireTime = gpGlobals->curtime + m_flFireInterval; - } - - m_nLastCompareResult = nCompare; - } - else if ((m_flFireTime != 0) && (gpGlobals->curtime >= m_flFireTime)) - { - // - // The compare result has held steady long enough -- time to - // fire the output. - // - FireCompareOutput(nCompare, this); - m_nLastFireResult = nCompare; - m_flFireTime = 0; - } - - SetNextThink( gpGlobals->curtime ); - } -} - - -//----------------------------------------------------------------------------- -// Fires the output after the fire interval if the velocity is stable. -//----------------------------------------------------------------------------- -void CPointAngularVelocitySensor::InputTestWithInterval( inputdata_t &inputdata ) -{ - if (m_hTargetEntity != NULL) - { - m_flFireTime = gpGlobals->curtime + m_flFireInterval; - m_nLastFireResult = AVELOCITY_SENSOR_NO_LAST_RESULT; - m_nLastCompareResult = CompareToThreshold(m_hTargetEntity, m_flThreshold, true); - - SetNextThink( gpGlobals->curtime ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for forcing an instantaneous test of the condition. -//----------------------------------------------------------------------------- -void CPointAngularVelocitySensor::InputTest( inputdata_t &inputdata ) -{ - int nCompareResult = CompareToThreshold(m_hTargetEntity, m_flThreshold, false); - FireCompareOutput(nCompareResult, inputdata.pActivator); -} - - -//----------------------------------------------------------------------------- -// Purpose: Fires the appropriate output based on the given comparison result. -// Input : nCompareResult - -// pActivator - -//----------------------------------------------------------------------------- -void CPointAngularVelocitySensor::FireCompareOutput( int nCompareResult, CBaseEntity *pActivator ) -{ - if (nCompareResult == -1) - { - m_OnLessThan.FireOutput(pActivator, this); - m_OnLessThanOrEqualTo.FireOutput(pActivator, this); - } - else if (nCompareResult == 1) - { - m_OnGreaterThan.FireOutput(pActivator, this); - m_OnGreaterThanOrEqualTo.FireOutput(pActivator, this); - } - else - { - m_OnEqualTo.FireOutput(pActivator, this); - m_OnLessThanOrEqualTo.FireOutput(pActivator, this); - m_OnGreaterThanOrEqualTo.FireOutput(pActivator, this); - } -} - -// ============================================================================ -// -// Simple velocity sensor -// -// ============================================================================ - -class CPointVelocitySensor : public CPointEntity -{ - DECLARE_CLASS( CPointVelocitySensor, CPointEntity ); - -public: - - void Spawn(); - void Activate( void ); - void Think( void ); - -private: - - void SampleVelocity( void ); - - EHANDLE m_hTargetEntity; // Entity whose angles are being monitored. - Vector m_vecAxis; // Axis along which to measure the speed. - bool m_bEnabled; // Whether we're measuring or not - - // Outputs - float m_fPrevVelocity; // stores velocity from last frame, so we only write the output if it has changed - COutputFloat m_Velocity; - - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( point_velocitysensor, CPointVelocitySensor ); - -BEGIN_DATADESC( CPointVelocitySensor ) - - // Fields - DEFINE_FIELD( m_hTargetEntity, FIELD_EHANDLE ), - DEFINE_KEYFIELD( m_vecAxis, FIELD_VECTOR, "axis" ), - DEFINE_KEYFIELD( m_bEnabled, FIELD_BOOLEAN, "enabled" ), - DEFINE_FIELD( m_fPrevVelocity, FIELD_FLOAT ), - - // Outputs - DEFINE_OUTPUT( m_Velocity, "Velocity" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CPointVelocitySensor::Spawn() -{ - Vector vLine = m_vecAxis - GetAbsOrigin(); - VectorNormalize( vLine ); - m_vecAxis = vLine; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointVelocitySensor::Activate( void ) -{ - BaseClass::Activate(); - - m_hTargetEntity = gEntList.FindEntityByName( NULL, m_target ); - - if ( m_bEnabled && m_hTargetEntity ) - { - SetNextThink( gpGlobals->curtime ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointVelocitySensor::InputEnable( inputdata_t &inputdata ) -{ - // Don't interrupt us if we're already enabled - if ( m_bEnabled ) - return; - - m_bEnabled = true; - - if ( m_hTargetEntity ) - { - SetNextThink( gpGlobals->curtime ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointVelocitySensor::InputDisable( inputdata_t &inputdata ) -{ - m_bEnabled = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Called every frame -//----------------------------------------------------------------------------- -void CPointVelocitySensor::Think( void ) -{ - if ( m_hTargetEntity != NULL && m_bEnabled ) - { - SampleVelocity(); - SetNextThink( gpGlobals->curtime ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the magnitude of the entity's angular velocity. -//----------------------------------------------------------------------------- -void CPointVelocitySensor::SampleVelocity( void ) -{ - if ( m_hTargetEntity == NULL ) - return; - - Vector vecVelocity; - - if ( m_hTargetEntity->GetMoveType() == MOVETYPE_VPHYSICS ) - { - IPhysicsObject *pPhys = m_hTargetEntity->VPhysicsGetObject(); - if ( pPhys != NULL ) - { - pPhys->GetVelocity( &vecVelocity, NULL ); - } - } - else - { - vecVelocity = m_hTargetEntity->GetAbsVelocity(); - } - - /* - float flSpeed = VectorNormalize( vecVelocity ); - float flDot = ( m_vecAxis != vec3_origin ) ? DotProduct( vecVelocity, m_vecAxis ) : 1.0f; - */ - // We want the component of the velocity vector in the direction of the axis, which since the - // axis is normalized is simply their dot product (eg V . A = |V|*|A|*cos(theta) ) - m_fPrevVelocity = ( m_vecAxis != vec3_origin ) ? DotProduct( vecVelocity, m_vecAxis ) : 1.0f; - - // if it's changed since the last frame, poke the output - if ( m_fPrevVelocity != m_Velocity.Get() ) - { - m_Velocity.Set( m_fPrevVelocity, NULL, NULL ); - } -} diff --git a/game/server/RagdollBoogie.cpp b/game/server/RagdollBoogie.cpp deleted file mode 100644 index fa88c6422..000000000 --- a/game/server/RagdollBoogie.cpp +++ /dev/null @@ -1,268 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Dissolve entity to be attached to target entity. Serves two purposes: -// -// 1) An entity that can be placed by a level designer and triggered -// to ignite a target entity. -// -// 2) An entity that can be created at runtime to ignite a target entity. -// -//=============================================================================// - -#include "cbase.h" -#include "RagdollBoogie.h" -#include "physics_prop_ragdoll.h" -#include "effect_dispatch_data.h" -#include "te_effect_dispatch.h" -#include "IEffects.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Make electriciy every so often -//----------------------------------------------------------------------------- -static const char *s_pZapContext = "ZapContext"; - - -//----------------------------------------------------------------------------- -// Save/load -//----------------------------------------------------------------------------- -BEGIN_DATADESC( CRagdollBoogie ) - - DEFINE_FIELD( m_flStartTime, FIELD_TIME ), - DEFINE_FIELD( m_flBoogieLength, FIELD_FLOAT ), - DEFINE_FIELD( m_flMagnitude, FIELD_FLOAT ), - - // Think this should be handled by StartTouch/etc. -// DEFINE_FIELD( m_nSuppressionCount, FIELD_INTEGER ), - - DEFINE_FUNCTION( BoogieThink ), - DEFINE_FUNCTION( ZapThink ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( env_ragdoll_boogie, CRagdollBoogie ); - - -//----------------------------------------------------------------------------- -// Purpose: Creates a flame and attaches it to a target entity. -// Input : pTarget - -//----------------------------------------------------------------------------- -CRagdollBoogie *CRagdollBoogie::Create( CBaseEntity *pTarget, float flMagnitude, - float flStartTime, float flLengthTime, int nSpawnFlags ) -{ - CRagdollProp *pRagdoll = dynamic_cast< CRagdollProp* >( pTarget ); - if ( !pRagdoll ) - return NULL; - - CRagdollBoogie *pBoogie = (CRagdollBoogie *)CreateEntityByName( "env_ragdoll_boogie" ); - if ( pBoogie == NULL ) - return NULL; - - pBoogie->AddSpawnFlags( nSpawnFlags ); - pBoogie->AttachToEntity( pTarget ); - pBoogie->SetBoogieTime( flStartTime, flLengthTime ); - pBoogie->SetMagnitude( flMagnitude ); - pBoogie->Spawn(); - return pBoogie; -} - - -//----------------------------------------------------------------------------- -// Spawn -//----------------------------------------------------------------------------- -void CRagdollBoogie::Spawn() -{ - BaseClass::Spawn(); - - SetThink( &CRagdollBoogie::BoogieThink ); - SetNextThink( gpGlobals->curtime + 0.01f ); - - if ( HasSpawnFlags( SF_RAGDOLL_BOOGIE_ELECTRICAL ) ) - { - SetContextThink( &CRagdollBoogie::ZapThink, gpGlobals->curtime + random->RandomFloat( 0.1f, 0.3f ), s_pZapContext ); - } -} - - -//----------------------------------------------------------------------------- -// Zap! -//----------------------------------------------------------------------------- -void CRagdollBoogie::ZapThink() -{ - if ( !GetMoveParent() ) - return; - - CBaseAnimating *pRagdoll = GetMoveParent()->GetBaseAnimating(); - if ( !pRagdoll ) - return; - - // Make electricity on the client - CStudioHdr *pStudioHdr = pRagdoll->GetModelPtr( ); - if (!pStudioHdr) - return; - - mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( pRagdoll->GetHitboxSet() ); - - if ( set->numhitboxes == 0 ) - return; - - if ( m_nSuppressionCount == 0 ) - { - CEffectData data; - - data.m_nEntIndex = GetMoveParent()->entindex(); - data.m_flMagnitude = 4; - data.m_flScale = HasSpawnFlags(SF_RAGDOLL_BOOGIE_ELECTRICAL_NARROW_BEAM) ? 1.0f : 2.0f; - - DispatchEffect( "TeslaHitboxes", data ); - } - -#ifdef HL2_EPISODIC - EmitSound( "RagdollBoogie.Zap" ); -#endif - - SetContextThink( &CRagdollBoogie::ZapThink, gpGlobals->curtime + random->RandomFloat( 0.1f, 0.3f ), s_pZapContext ); -} - - -//----------------------------------------------------------------------------- -// Suppression count -//----------------------------------------------------------------------------- -void CRagdollBoogie::IncrementSuppressionCount( CBaseEntity *pTarget ) -{ - // Look for other boogies on the ragdoll + kill them - for ( CBaseEntity *pChild = pTarget->FirstMoveChild(); pChild; pChild = pChild->NextMovePeer() ) - { - CRagdollBoogie *pBoogie = dynamic_cast(pChild); - if ( !pBoogie ) - continue; - - ++pBoogie->m_nSuppressionCount; - } -} - -void CRagdollBoogie::DecrementSuppressionCount( CBaseEntity *pTarget ) -{ - // Look for other boogies on the ragdoll + kill them - CBaseEntity *pNext; - for ( CBaseEntity *pChild = pTarget->FirstMoveChild(); pChild; pChild = pNext ) - { - pNext = pChild->NextMovePeer(); - CRagdollBoogie *pBoogie = dynamic_cast(pChild); - if ( !pBoogie ) - continue; - - if ( --pBoogie->m_nSuppressionCount <= 0 ) - { - pBoogie->m_nSuppressionCount = 0; - - float dt = gpGlobals->curtime - pBoogie->m_flStartTime; - if ( dt >= pBoogie->m_flBoogieLength ) - { - PhysCallbackRemove( pBoogie->NetworkProp() ); - } - } - } -} - - -//----------------------------------------------------------------------------- -// Attach to an entity -//----------------------------------------------------------------------------- -void CRagdollBoogie::AttachToEntity( CBaseEntity *pTarget ) -{ - m_nSuppressionCount = 0; - - // Look for other boogies on the ragdoll + kill them - CBaseEntity *pNext; - for ( CBaseEntity *pChild = pTarget->FirstMoveChild(); pChild; pChild = pNext ) - { - pNext = pChild->NextMovePeer(); - CRagdollBoogie *pBoogie = dynamic_cast(pChild); - if ( !pBoogie ) - continue; - - m_nSuppressionCount = pBoogie->m_nSuppressionCount; - UTIL_Remove( pChild ); - } - - FollowEntity( pTarget ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : lifetime - -//----------------------------------------------------------------------------- -void CRagdollBoogie::SetBoogieTime( float flStartTime, float flLengthTime ) -{ - m_flStartTime = flStartTime; - m_flBoogieLength = flLengthTime; -} - - -//----------------------------------------------------------------------------- -// Purpose: Burn targets around us -//----------------------------------------------------------------------------- -void CRagdollBoogie::SetMagnitude( float flMagnitude ) -{ - m_flMagnitude = flMagnitude; -} - - -//----------------------------------------------------------------------------- -// Purpose: Burn targets around us -//----------------------------------------------------------------------------- -void CRagdollBoogie::BoogieThink( void ) -{ - CRagdollProp *pRagdoll = dynamic_cast< CRagdollProp* >( GetMoveParent() ); - if ( !pRagdoll ) - { - UTIL_Remove( this ); - return; - } - - float flMagnitude = m_flMagnitude; - if ( m_flBoogieLength != 0 ) - { - float dt = gpGlobals->curtime - m_flStartTime; - if ( dt >= m_flBoogieLength ) - { - // Don't remove while suppressed... this helps if we try to start another boogie - if ( m_nSuppressionCount == 0 ) - { - UTIL_Remove( this ); - } - SetThink( NULL ); - return; - } - - if ( dt < 0 ) - { - SetNextThink( gpGlobals->curtime + random->RandomFloat( 0.1, 0.2f ) ); - return; - } - - flMagnitude = SimpleSplineRemapVal( dt, 0.0f, m_flBoogieLength, m_flMagnitude, 0.0f ); - } - -#ifndef _XBOX - if ( m_nSuppressionCount == 0 ) - { - ragdoll_t *pRagdollPhys = pRagdoll->GetRagdoll( ); - for ( int j = 0; j < pRagdollPhys->listCount; ++j ) - { - float flMass = pRagdollPhys->list[j].pObject->GetMass(); - float flForce = m_flMagnitude * flMass; - - Vector vecForce; - vecForce = RandomVector( -flForce, flForce ); - pRagdollPhys->list[j].pObject->ApplyForceCenter( vecForce ); - } - } -#endif // !_XBOX - - SetNextThink( gpGlobals->curtime + random->RandomFloat( 0.1, 0.2f ) ); -} diff --git a/game/server/RagdollBoogie.h b/game/server/RagdollBoogie.h deleted file mode 100644 index 5fbcadbfe..000000000 --- a/game/server/RagdollBoogie.h +++ /dev/null @@ -1,50 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef RAGDOLLBOOGIE_H -#define RAGDOLLBOOGIE_H - -#ifdef _WIN32 -#pragma once -#endif - - -//----------------------------------------------------------------------------- -// Set this spawnflag before calling Spawn to get electrical effects -//----------------------------------------------------------------------------- -#define SF_RAGDOLL_BOOGIE_ELECTRICAL 0x10000 -#define SF_RAGDOLL_BOOGIE_ELECTRICAL_NARROW_BEAM 0x20000 - - -//----------------------------------------------------------------------------- -// Makes ragdolls DANCE! -//----------------------------------------------------------------------------- -class CRagdollBoogie : public CBaseEntity -{ - DECLARE_DATADESC(); - DECLARE_CLASS( CRagdollBoogie, CBaseEntity ); - -public: - static CRagdollBoogie *Create( CBaseEntity *pTarget, float flMagnitude, float flStartTime, float flLengthTime = 0.0f, int nSpawnFlags = 0 ); - static void IncrementSuppressionCount( CBaseEntity *pTarget ); - static void DecrementSuppressionCount( CBaseEntity *pTarget ); - - void Spawn(); - -private: - void AttachToEntity( CBaseEntity *pTarget ); - void SetBoogieTime( float flStartTime, float flLengthTime ); - void SetMagnitude( float flMagnitude ); - void BoogieThink( void ); - void ZapThink(); - - float m_flStartTime; - float m_flBoogieLength; - float m_flMagnitude; - int m_nSuppressionCount; -}; - -#endif // RAGDOLLBOOGIE_H diff --git a/game/server/ServerNetworkProperty.cpp b/game/server/ServerNetworkProperty.cpp deleted file mode 100644 index bc2445b76..000000000 --- a/game/server/ServerNetworkProperty.cpp +++ /dev/null @@ -1,305 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#include "cbase.h" -#include "ServerNetworkProperty.h" -#include "tier0/dbg.h" -#include "gameinterface.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern CTimedEventMgr g_NetworkPropertyEventMgr; - - -//----------------------------------------------------------------------------- -// Save/load -//----------------------------------------------------------------------------- -BEGIN_DATADESC_NO_BASE( CServerNetworkProperty ) -// DEFINE_FIELD( m_pOuter, FIELD_CLASSPTR ), -// DEFINE_FIELD( m_pPev, FIELD_CLASSPTR ), -// DEFINE_FIELD( m_PVSInfo, PVSInfo_t ), -// DEFINE_FIELD( m_pServerClass, FIELD_CLASSPTR ), - DEFINE_GLOBAL_FIELD( m_hParent, FIELD_EHANDLE ), -// DEFINE_FIELD( m_TimerEvent, CEventRegister ), -// DEFINE_FIELD( m_bPendingStateChange, FIELD_BOOLEAN ), -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Constructor, destructor -//----------------------------------------------------------------------------- -CServerNetworkProperty::CServerNetworkProperty() -{ - Init( NULL ); -} - - -CServerNetworkProperty::~CServerNetworkProperty() -{ - /* Free our transmit proxy. - if ( m_pTransmitProxy ) - { - m_pTransmitProxy->Release(); - }*/ - - engine->CleanUpEntityClusterList( &m_PVSInfo ); - - // remove the attached edict if it exists - DetachEdict(); -} - - -//----------------------------------------------------------------------------- -// Initialization -//----------------------------------------------------------------------------- -void CServerNetworkProperty::Init( CBaseEntity *pEntity ) -{ - m_pPev = NULL; - m_pOuter = pEntity; - m_pServerClass = NULL; -// m_pTransmitProxy = NULL; - m_bPendingStateChange = false; - m_PVSInfo.m_nClusterCount = 0; - m_TimerEvent.Init( &g_NetworkPropertyEventMgr, this ); -} - - -//----------------------------------------------------------------------------- -// Connects, disconnects edicts -//----------------------------------------------------------------------------- -void CServerNetworkProperty::AttachEdict( edict_t *pRequiredEdict ) -{ - Assert ( !m_pPev ); - - // see if there is an edict allocated for it, otherwise get one from the engine - if ( !pRequiredEdict ) - { - pRequiredEdict = engine->CreateEdict(); - } - - m_pPev = pRequiredEdict; - m_pPev->SetEdict( GetBaseEntity(), true ); -} - -void CServerNetworkProperty::DetachEdict() -{ - if ( m_pPev ) - { - m_pPev->SetEdict( NULL, false ); - engine->RemoveEdict( m_pPev ); - m_pPev = NULL; - } -} - - -//----------------------------------------------------------------------------- -// Entity handles -//----------------------------------------------------------------------------- -IHandleEntity *CServerNetworkProperty::GetEntityHandle( ) -{ - return m_pOuter; -} - -void CServerNetworkProperty::Release() -{ - delete m_pOuter; -} - - -//----------------------------------------------------------------------------- -// Returns the network parent -//----------------------------------------------------------------------------- -CServerNetworkProperty* CServerNetworkProperty::GetNetworkParent() -{ - CBaseEntity *pParent = m_hParent.Get(); - return pParent ? pParent->NetworkProp() : NULL; -} - - -//----------------------------------------------------------------------------- -// Marks for deletion -//----------------------------------------------------------------------------- -void CServerNetworkProperty::MarkForDeletion() -{ - m_pOuter->AddEFlags( EFL_KILLME ); -} - -bool CServerNetworkProperty::IsMarkedForDeletion() const -{ - return ( m_pOuter->GetEFlags() & EFL_KILLME ) != 0; -} - - -//----------------------------------------------------------------------------- -// PVS information -//----------------------------------------------------------------------------- -void CServerNetworkProperty::RecomputePVSInformation() -{ - if ( m_pPev && ( ( m_pPev->m_fStateFlags & FL_EDICT_DIRTY_PVS_INFORMATION ) != 0 ) ) - { - m_pPev->m_fStateFlags &= ~FL_EDICT_DIRTY_PVS_INFORMATION; - engine->BuildEntityClusterList( edict(), &m_PVSInfo ); - } -} - - -//----------------------------------------------------------------------------- -// Serverclass -//----------------------------------------------------------------------------- -ServerClass* CServerNetworkProperty::GetServerClass() -{ - if ( !m_pServerClass ) - m_pServerClass = m_pOuter->GetServerClass(); - return m_pServerClass; -} - -const char* CServerNetworkProperty::GetClassName() const -{ - return STRING(m_pOuter->m_iClassname); -} - - -//----------------------------------------------------------------------------- -// Transmit proxies -/*----------------------------------------------------------------------------- -void CServerNetworkProperty::SetTransmitProxy( CBaseTransmitProxy *pProxy ) -{ - if ( m_pTransmitProxy ) - { - m_pTransmitProxy->Release(); - } - - m_pTransmitProxy = pProxy; - - if ( m_pTransmitProxy ) - { - m_pTransmitProxy->AddRef(); - } -}*/ - -//----------------------------------------------------------------------------- -// PVS rules -//----------------------------------------------------------------------------- -bool CServerNetworkProperty::IsInPVS( const edict_t *pRecipient, const void *pvs, int pvssize ) -{ - RecomputePVSInformation(); - - // ignore if not touching a PV leaf - // negative leaf count is a node number - // If no pvs, add any entity - - Assert( pvs && ( edict() != pRecipient ) ); - - unsigned char *pPVS = ( unsigned char * )pvs; - - if ( m_PVSInfo.m_nClusterCount < 0 ) // too many clusters, use headnode - { - return ( engine->CheckHeadnodeVisible( m_PVSInfo.m_nHeadNode, pPVS, pvssize ) != 0); - } - - for ( int i = m_PVSInfo.m_nClusterCount; --i >= 0; ) - { - if (pPVS[m_PVSInfo.m_pClusters[i] >> 3] & (1 << (m_PVSInfo.m_pClusters[i] & 7) )) - return true; - } - - return false; // not visible -} - - -//----------------------------------------------------------------------------- -// PVS: this function is called a lot, so it avoids function calls -//----------------------------------------------------------------------------- -bool CServerNetworkProperty::IsInPVS( const CCheckTransmitInfo *pInfo ) -{ - // PVS data must be up to date - Assert( !m_pPev || ( ( m_pPev->m_fStateFlags & FL_EDICT_DIRTY_PVS_INFORMATION ) == 0 ) ); - - int i; - - // Early out if the areas are connected - if ( !m_PVSInfo.m_nAreaNum2 ) - { - for ( i=0; i< pInfo->m_AreasNetworked; i++ ) - { - int clientArea = pInfo->m_Areas[i]; - if ( clientArea == m_PVSInfo.m_nAreaNum || engine->CheckAreasConnected( clientArea, m_PVSInfo.m_nAreaNum ) ) - break; - } - } - else - { - // doors can legally straddle two areas, so - // we may need to check another one - for ( i=0; i< pInfo->m_AreasNetworked; i++ ) - { - int clientArea = pInfo->m_Areas[i]; - if ( clientArea == m_PVSInfo.m_nAreaNum || clientArea == m_PVSInfo.m_nAreaNum2 ) - break; - - if ( engine->CheckAreasConnected( clientArea, m_PVSInfo.m_nAreaNum ) ) - break; - - if ( engine->CheckAreasConnected( clientArea, m_PVSInfo.m_nAreaNum2 ) ) - break; - } - } - - if ( i == pInfo->m_AreasNetworked ) - { - // areas not connected - return false; - } - - // ignore if not touching a PV leaf - // negative leaf count is a node number - // If no pvs, add any entity - - Assert( edict() != pInfo->m_pClientEnt ); - - unsigned char *pPVS = ( unsigned char * )pInfo->m_PVS; - - if ( m_PVSInfo.m_nClusterCount < 0 ) // too many clusters, use headnode - { - return (engine->CheckHeadnodeVisible( m_PVSInfo.m_nHeadNode, pPVS, pInfo->m_nPVSSize ) != 0); - } - - for ( i = m_PVSInfo.m_nClusterCount; --i >= 0; ) - { - int nCluster = m_PVSInfo.m_pClusters[i]; - if ( ((int)(pPVS[nCluster >> 3])) & BitVec_BitInByte( nCluster ) ) - return true; - } - - return false; // not visible - -} - - -void CServerNetworkProperty::SetUpdateInterval( float val ) -{ - if ( val == 0 ) - m_TimerEvent.StopUpdates(); - else - m_TimerEvent.SetUpdateInterval( val ); -} - - -void CServerNetworkProperty::FireEvent() -{ - // Our timer went off. If our state has changed in the background, then - // trigger a state change in the edict. - if ( m_bPendingStateChange ) - { - m_pPev->StateChanged(); - m_bPendingStateChange = false; - } -} - - - diff --git a/game/server/ServerNetworkProperty.h b/game/server/ServerNetworkProperty.h deleted file mode 100644 index f267aeb7e..000000000 --- a/game/server/ServerNetworkProperty.h +++ /dev/null @@ -1,258 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef SERVERNETWORKPROPERTY_H -#define SERVERNETWORKPROPERTY_H -#ifdef _WIN32 -#pragma once -#endif - -#include "iservernetworkable.h" -#include "server_class.h" -#include "edict.h" -#include "timedeventmgr.h" - -// -// Lightweight base class for networkable data on the server. -// -class CServerNetworkProperty : public IServerNetworkable, public IEventRegisterCallback -{ -public: - DECLARE_CLASS_NOBASE( CServerNetworkProperty ); - DECLARE_DATADESC(); - -public: - CServerNetworkProperty(); - virtual ~CServerNetworkProperty(); - -public: -// IServerNetworkable implementation. - virtual IHandleEntity *GetEntityHandle( ); - virtual edict_t *GetEdict() const; - virtual CBaseNetworkable* GetBaseNetworkable(); - virtual CBaseEntity* GetBaseEntity(); - virtual ServerClass* GetServerClass(); - virtual const char* GetClassName() const; - virtual void Release(); - virtual int AreaNum() const; - virtual PVSInfo_t* GetPVSInfo(); - -public: - // Other public methods - void Init( CBaseEntity *pEntity ); - - void AttachEdict( edict_t *pRequiredEdict = NULL ); - - // Methods to get the entindex + edict - int entindex() const; - edict_t *edict(); - const edict_t *edict() const; - - // Sets the edict pointer (for swapping edicts) - void SetEdict( edict_t *pEdict ); - - // All these functions call through to CNetStateMgr. - // See CNetStateMgr for details about these functions. - void NetworkStateForceUpdate(); - void NetworkStateChanged(); - void NetworkStateChanged( unsigned short offset ); - - // Marks the PVS information dirty - void MarkPVSInformationDirty(); - - // Marks for deletion - void MarkForDeletion(); - bool IsMarkedForDeletion() const; - - // Sets the network parent - void SetNetworkParent( EHANDLE hParent ); - CServerNetworkProperty* GetNetworkParent(); - - // This is useful for entities that don't change frequently or that the client - // doesn't need updates on very often. If you use this mode, the server will only try to - // detect state changes every N seconds, so it will save CPU cycles and bandwidth. - // - // Note: N must be less than AUTOUPDATE_MAX_TIME_LENGTH. - // - // Set back to zero to disable the feature. - // - // This feature works on top of manual mode. - // - If you turn it on and manual mode is off, it will autodetect changes every N seconds. - // - If you turn it on and manual mode is on, then every N seconds it will only say there - // is a change if you've called NetworkStateChanged. - void SetUpdateInterval( float N ); - - // You can use this to override any entity's ShouldTransmit behavior. - // void SetTransmitProxy( CBaseTransmitProxy *pProxy ); - - // This version does a PVS check which also checks for connected areas - bool IsInPVS( const CCheckTransmitInfo *pInfo ); - - // This version doesn't do the area check - bool IsInPVS( const edict_t *pRecipient, const void *pvs, int pvssize ); - - // Called by the timed event manager when it's time to detect a state change. - virtual void FireEvent(); - - // Recomputes PVS information - void RecomputePVSInformation(); - -private: - // Detaches the edict.. should only be called by CBaseNetworkable's destructor. - void DetachEdict(); - CBaseEntity *GetOuter(); - - // Marks the networkable that it will should transmit - void SetTransmit( CCheckTransmitInfo *pInfo ); - -private: - CBaseEntity *m_pOuter; - // CBaseTransmitProxy *m_pTransmitProxy; - edict_t *m_pPev; - PVSInfo_t m_PVSInfo; - ServerClass *m_pServerClass; - - // NOTE: This state is 'owned' by the entity. It's only copied here - // also to help improve cache performance in networking code. - EHANDLE m_hParent; - - // Counters for SetUpdateInterval. - CEventRegister m_TimerEvent; - bool m_bPendingStateChange : 1; - -// friend class CBaseTransmitProxy; -}; - - -//----------------------------------------------------------------------------- -// inline methods // TODOMO does inline work on virtual functions ? -//----------------------------------------------------------------------------- -inline CBaseNetworkable* CServerNetworkProperty::GetBaseNetworkable() -{ - return NULL; -} - -inline CBaseEntity* CServerNetworkProperty::GetBaseEntity() -{ - return m_pOuter; -} - -inline CBaseEntity *CServerNetworkProperty::GetOuter() -{ - return m_pOuter; -} - -inline PVSInfo_t *CServerNetworkProperty::GetPVSInfo() -{ - return &m_PVSInfo; -} - - -//----------------------------------------------------------------------------- -// Marks the PVS information dirty -//----------------------------------------------------------------------------- -inline void CServerNetworkProperty::MarkPVSInformationDirty() -{ - if ( m_pPev ) - { - m_pPev->m_fStateFlags |= FL_EDICT_DIRTY_PVS_INFORMATION; - } -} - - -//----------------------------------------------------------------------------- -// Sets/gets the network parent -//----------------------------------------------------------------------------- -inline void CServerNetworkProperty::SetNetworkParent( EHANDLE hParent ) -{ - m_hParent = hParent; -} - - -//----------------------------------------------------------------------------- -// Methods related to the net state mgr -//----------------------------------------------------------------------------- -inline void CServerNetworkProperty::NetworkStateForceUpdate() -{ - if ( m_pPev ) - m_pPev->StateChanged(); -} - -inline void CServerNetworkProperty::NetworkStateChanged() -{ - // If we're using the timer, then ignore this call. - if ( m_TimerEvent.IsRegistered() ) - { - // If we're waiting for a timer event, then queue the change so it happens - // when the timer goes off. - m_bPendingStateChange = true; - } - else - { - if ( m_pPev ) - m_pPev->StateChanged(); - } -} - -inline void CServerNetworkProperty::NetworkStateChanged( unsigned short varOffset ) -{ - // If we're using the timer, then ignore this call. - if ( m_TimerEvent.IsRegistered() ) - { - // If we're waiting for a timer event, then queue the change so it happens - // when the timer goes off. - m_bPendingStateChange = true; - } - else - { - if ( m_pPev ) - m_pPev->StateChanged( varOffset ); - } -} - -//----------------------------------------------------------------------------- -// Methods to get the entindex + edict -//----------------------------------------------------------------------------- -inline int CServerNetworkProperty::entindex() const -{ - return ENTINDEX( m_pPev ); -} - -inline edict_t* CServerNetworkProperty::GetEdict() const -{ - // This one's virtual, that's why we have to two other versions - return m_pPev; -} - -inline edict_t *CServerNetworkProperty::edict() -{ - return m_pPev; -} - -inline const edict_t *CServerNetworkProperty::edict() const -{ - return m_pPev; -} - - -//----------------------------------------------------------------------------- -// Sets the edict pointer (for swapping edicts) -//----------------------------------------------------------------------------- -inline void CServerNetworkProperty::SetEdict( edict_t *pEdict ) -{ - m_pPev = pEdict; -} - - -inline int CServerNetworkProperty::AreaNum() const -{ - const_cast(this)->RecomputePVSInformation(); - return m_PVSInfo.m_nAreaNum; -} - - -#endif // SERVERNETWORKPROPERTY_H diff --git a/game/server/SkyCamera.cpp b/game/server/SkyCamera.cpp deleted file mode 100644 index 4678df3c5..000000000 --- a/game/server/SkyCamera.cpp +++ /dev/null @@ -1,149 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "igamesystem.h" -#include "entitylist.h" -#include "SkyCamera.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// automatically hooks in the system's callbacks -CEntityClassList g_SkyList; -template <> CSkyCamera *CEntityClassList::m_pClassList = NULL; - -//----------------------------------------------------------------------------- -// Retrives the current skycamera -//----------------------------------------------------------------------------- -CSkyCamera* GetCurrentSkyCamera() -{ - return g_SkyList.m_pClassList; -} - -CSkyCamera* GetSkyCameraList() -{ - return g_SkyList.m_pClassList; -} - -//============================================================================= - -LINK_ENTITY_TO_CLASS( sky_camera, CSkyCamera ); - -BEGIN_DATADESC( CSkyCamera ) - - DEFINE_KEYFIELD( m_skyboxData.scale, FIELD_INTEGER, "scale" ), - DEFINE_FIELD( m_skyboxData.origin, FIELD_VECTOR ), - DEFINE_FIELD( m_skyboxData.area, FIELD_INTEGER ), - - // Quiet down classcheck - // DEFINE_FIELD( m_skyboxData, sky3dparams_t ), - - // This is re-set up in the constructor - // DEFINE_FIELD( m_pNext, CSkyCamera ), - - // fog data for 3d skybox - DEFINE_KEYFIELD( m_bUseAngles, FIELD_BOOLEAN, "use_angles" ), - DEFINE_KEYFIELD( m_skyboxData.fog.enable, FIELD_BOOLEAN, "fogenable" ), - DEFINE_KEYFIELD( m_skyboxData.fog.blend, FIELD_BOOLEAN, "fogblend" ), - DEFINE_KEYFIELD( m_skyboxData.fog.dirPrimary, FIELD_VECTOR, "fogdir" ), - DEFINE_KEYFIELD( m_skyboxData.fog.colorPrimary, FIELD_COLOR32, "fogcolor" ), - DEFINE_KEYFIELD( m_skyboxData.fog.colorSecondary, FIELD_COLOR32, "fogcolor2" ), - DEFINE_KEYFIELD( m_skyboxData.fog.start, FIELD_FLOAT, "fogstart" ), - DEFINE_KEYFIELD( m_skyboxData.fog.end, FIELD_FLOAT, "fogend" ), - DEFINE_KEYFIELD( m_skyboxData.fog.maxdensity, FIELD_FLOAT, "fogmaxdensity" ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// List of maps in HL2 that we must apply our skybox fog fixup hack to -//----------------------------------------------------------------------------- -#ifdef HL2_DLL -static const char *s_pBogusFogMaps[] = -{ - "d1_canals_01", - "d1_canals_01a", - "d1_canals_02", - "d1_canals_03", - "d1_canals_09", - "d1_canals_10", - "d1_canals_11", - "d1_canals_12", - "d1_canals_13", - "d1_eli_01", - "d1_trainstation_01", - "d1_trainstation_03", - "d1_trainstation_04", - "d1_trainstation_05", - "d1_trainstation_06", - "d3_c17_04", - "d3_c17_11", - "d3_c17_12", - "d3_citadel_01", - NULL -}; -#endif - -//----------------------------------------------------------------------------- -// Constructor, destructor -//----------------------------------------------------------------------------- -CSkyCamera::CSkyCamera() -{ - g_SkyList.Insert( this ); - m_skyboxData.fog.maxdensity = 1.0f; -} - -CSkyCamera::~CSkyCamera() -{ - g_SkyList.Remove( this ); -} - -void CSkyCamera::Spawn( void ) -{ - m_skyboxData.origin = GetLocalOrigin(); - m_skyboxData.area = engine->GetArea( m_skyboxData.origin ); - - Precache(); -} - - -//----------------------------------------------------------------------------- -// Activate! -//----------------------------------------------------------------------------- -void CSkyCamera::Activate( ) -{ - BaseClass::Activate(); - - if ( m_bUseAngles ) - { - AngleVectors( GetAbsAngles(), &m_skyboxData.fog.dirPrimary.GetForModify() ); - m_skyboxData.fog.dirPrimary.GetForModify() *= -1.0f; - } - -#ifdef HL2_DLL - // NOTE! This is a hack. There was a bug in the skybox fog computation - // on the client DLL that caused it to use the average of the primary and - // secondary fog color when blending was enabled. The bug is fixed, but to make - // the maps look the same as before the bug fix without having to download new maps, - // I have to cheat here and slam the primary and secondary colors to be the average of - // the primary and secondary colors. - if ( m_skyboxData.fog.blend ) - { - for ( int i = 0; s_pBogusFogMaps[i]; ++i ) - { - if ( !Q_stricmp( s_pBogusFogMaps[i], STRING(gpGlobals->mapname) ) ) - { - m_skyboxData.fog.colorPrimary.SetR( (byte)(( m_skyboxData.fog.colorPrimary.GetR() + m_skyboxData.fog.colorSecondary.GetR() ) * 0.5f) ); - m_skyboxData.fog.colorPrimary.SetG( (byte)(( m_skyboxData.fog.colorPrimary.GetG() + m_skyboxData.fog.colorSecondary.GetG() ) * 0.5f) ); - m_skyboxData.fog.colorPrimary.SetB( (byte)(( m_skyboxData.fog.colorPrimary.GetB() + m_skyboxData.fog.colorSecondary.GetB() ) * 0.5f) ); - m_skyboxData.fog.colorPrimary.SetA( (byte)(( m_skyboxData.fog.colorPrimary.GetA() + m_skyboxData.fog.colorSecondary.GetA() ) * 0.5f) ); - m_skyboxData.fog.colorSecondary = m_skyboxData.fog.colorPrimary; - } - } - } -#endif -} diff --git a/game/server/SkyCamera.h b/game/server/SkyCamera.h deleted file mode 100644 index d89cede8e..000000000 --- a/game/server/SkyCamera.h +++ /dev/null @@ -1,47 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Resource collection entity -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SKYCAMERA_H -#define SKYCAMERA_H - -#ifdef _WIN32 -#pragma once -#endif - -class CSkyCamera; - -//============================================================================= -// -// Sky Camera Class -// -class CSkyCamera : public CLogicalEntity -{ - DECLARE_CLASS( CSkyCamera, CLogicalEntity ); - -public: - - DECLARE_DATADESC(); - CSkyCamera(); - ~CSkyCamera(); - virtual void Spawn( void ); - virtual void Activate(); - -public: - sky3dparams_t m_skyboxData; - bool m_bUseAngles; - CSkyCamera *m_pNext; -}; - - -//----------------------------------------------------------------------------- -// Retrives the current skycamera -//----------------------------------------------------------------------------- -CSkyCamera* GetCurrentSkyCamera(); -CSkyCamera* GetSkyCameraList(); - - -#endif // SKYCAMERA_H diff --git a/game/server/TemplateEntities.cpp b/game/server/TemplateEntities.cpp deleted file mode 100644 index 556a93c36..000000000 --- a/game/server/TemplateEntities.cpp +++ /dev/null @@ -1,510 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Template entities are used by spawners to create copies of entities -// that were configured by the level designer. This allows us to spawn -// entities with arbitrary sets of key/value data and entity I/O -// connections. -// -// Template entities are marked with a special spawnflag which causes -// them not to spawn, but to be saved as a string containing all the -// map data (keyvalues and I/O connections) from the BSP. Template -// entities are looked up by name by the spawner, which copies the -// map data into a local string (that's how the template data is saved -// and restored). Once all the entities in the map have been activated, -// the template database is freed. -// -//=============================================================================// - -#include "cbase.h" -#include "igamesystem.h" -#include "mapentities_shared.h" -#include "point_template.h" -#include "eventqueue.h" -#include "TemplateEntities.h" -#include "utldict.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar template_debug( "template_debug", "0" ); - -// This is appended to key's values that will need to be unique in template instances -const char *ENTITYIO_FIXUP_STRING = "&0000"; - -int MapEntity_GetNumKeysInEntity( const char *pEntData ); - -struct TemplateEntityData_t -{ - const char *pszName; - char *pszMapData; - string_t iszMapData; - int iMapDataLength; - bool bNeedsEntityIOFixup; // If true, this template has entity I/O in its mapdata that needs fixup before spawning. - char *pszFixedMapData; // A single copy of this template that we used to fix up the Entity I/O whenever someone wants a fixed version of this template - - DECLARE_SIMPLE_DATADESC(); -}; - -BEGIN_SIMPLE_DATADESC( TemplateEntityData_t ) - //DEFINE_FIELD( pszName, FIELD_STRING ), // Saved custom, see below - //DEFINE_FIELD( pszMapData, FIELD_STRING ), // Saved custom, see below - DEFINE_FIELD( iszMapData, FIELD_STRING ), - DEFINE_FIELD( iMapDataLength, FIELD_INTEGER ), - DEFINE_FIELD( bNeedsEntityIOFixup, FIELD_BOOLEAN ), - - //DEFINE_FIELD( pszFixedMapData, FIELD_STRING ), // Not saved at all -END_DATADESC() - -struct grouptemplate_t -{ - CEntityMapData *pMapDataParser; - char pszName[MAPKEY_MAXLENGTH]; - int iIndex; - bool bChangeTargetname; -}; - -static CUtlVector g_Templates; - -int g_iCurrentTemplateInstance; - -//----------------------------------------------------------------------------- -// Purpose: Saves the given entity's keyvalue data for later use by a spawner. -// Returns the index into the templates. -//----------------------------------------------------------------------------- -int Templates_Add(CBaseEntity *pEntity, const char *pszMapData, int nLen) -{ - const char *pszName = STRING(pEntity->GetEntityName()); - if ((!pszName) || (!strlen(pszName))) - { - DevWarning(1, "RegisterTemplateEntity: template entity with no name, class %s\n", pEntity->GetClassname()); - return -1; - } - - TemplateEntityData_t *pEntData = (TemplateEntityData_t *)malloc(sizeof(TemplateEntityData_t)); - pEntData->pszName = strdup( pszName ); - - // We may modify the values of the keys in this mapdata chunk later on to fix Entity I/O - // connections. For this reason, we need to ensure we have enough memory to do that. - int iKeys = MapEntity_GetNumKeysInEntity( pszMapData ); - int iExtraSpace = (strlen(ENTITYIO_FIXUP_STRING)+1) * iKeys; - - // Extra 1 because the mapdata passed in isn't null terminated - pEntData->iMapDataLength = nLen + iExtraSpace + 1; - pEntData->pszMapData = (char *)malloc( pEntData->iMapDataLength ); - memcpy(pEntData->pszMapData, pszMapData, nLen + 1); - pEntData->pszMapData[nLen] = '\0'; - - // We don't alloc these suckers right now because that gives us no time to - // tweak them for Entity I/O purposes. - pEntData->iszMapData = NULL_STRING; - pEntData->bNeedsEntityIOFixup = false; - pEntData->pszFixedMapData = NULL; - - return g_Templates.AddToTail(pEntData); -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns true if the specified index needs to be fixed up to be unique -// when the template is spawned. -//----------------------------------------------------------------------------- -bool Templates_IndexRequiresEntityIOFixup( int iIndex ) -{ - Assert( iIndex < g_Templates.Count() ); - return g_Templates[iIndex]->bNeedsEntityIOFixup; -} - -//----------------------------------------------------------------------------- -// Purpose: Looks up a template entity by its index in the templates -// Used by point_templates because they often have multiple templates with the same name -//----------------------------------------------------------------------------- -string_t Templates_FindByIndex( int iIndex ) -{ - Assert( iIndex < g_Templates.Count() ); - - // First time through we alloc the mapdata onto the pool. - // It's safe to do it now because this isn't called until post Entity I/O cleanup. - if ( g_Templates[iIndex]->iszMapData == NULL_STRING ) - { - g_Templates[iIndex]->iszMapData = AllocPooledString( g_Templates[iIndex]->pszMapData ); - } - - return g_Templates[iIndex]->iszMapData; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int Templates_GetStringSize( int iIndex ) -{ - Assert( iIndex < g_Templates.Count() ); - return g_Templates[iIndex]->iMapDataLength; -} - -//----------------------------------------------------------------------------- -// Purpose: Looks up a template entity by name, returning the map data blob as -// a null-terminated string containing key/value pairs. -// NOTE: This can't handle multiple templates with the same targetname. -//----------------------------------------------------------------------------- -string_t Templates_FindByTargetName(const char *pszName) -{ - int nCount = g_Templates.Count(); - for (int i = 0; i < nCount; i++) - { - TemplateEntityData_t *pTemplate = g_Templates.Element(i); - if ( !stricmp(pTemplate->pszName, pszName) ) - return Templates_FindByIndex( i ); - } - - return NULL_STRING; -} - -//----------------------------------------------------------------------------- -// Purpose: A CPointTemplate has asked us to reconnect all the entity I/O links -// inside it's templates. Go through the keys and add look for values -// that match a name within the group's entity names. Append %d to any -// found values, which will later be filled out by a unique identifier -// whenever the template is instanced. -//----------------------------------------------------------------------------- -void Templates_ReconnectIOForGroup( CPointTemplate *pGroup ) -{ - int iCount = pGroup->GetNumTemplates(); - if ( !iCount ) - return; - - // First assemble a list of the targetnames of all the templates in the group. - // We need to store off the original names here, because we're going to change - // them as we go along. - CUtlVector< grouptemplate_t > GroupTemplates; - int i; - for ( i = 0; i < iCount; i++ ) - { - grouptemplate_t newGroupTemplate; - newGroupTemplate.iIndex = pGroup->GetTemplateIndexForTemplate(i); - newGroupTemplate.pMapDataParser = new CEntityMapData( g_Templates[ newGroupTemplate.iIndex ]->pszMapData, g_Templates[ newGroupTemplate.iIndex ]->iMapDataLength ); - Assert( newGroupTemplate.pMapDataParser ); - newGroupTemplate.pMapDataParser->ExtractValue( "targetname", newGroupTemplate.pszName ); - newGroupTemplate.bChangeTargetname = false; - - GroupTemplates.AddToTail( newGroupTemplate ); - } - - if (pGroup->AllowNameFixup()) - { - char keyName[MAPKEY_MAXLENGTH]; - char value[MAPKEY_MAXLENGTH]; - char valueclipped[MAPKEY_MAXLENGTH]; - - // Now go through all the entities in the group and parse their mapdata keyvalues. - // We're looking for any values that match targetnames of any of the group entities. - for ( i = 0; i < iCount; i++ ) - { - // We need to know what instance of each key we're changing. - // Store a table of the count of the keys we've run into. - CUtlDict< int, int > KeyInstanceCount; - CEntityMapData *mapData = GroupTemplates[i].pMapDataParser; - - // Loop through our keys - if ( !mapData->GetFirstKey(keyName, value) ) - continue; - - do - { - // Ignore targetnames - if ( !stricmp( keyName, "targetname" ) ) - continue; - - // Add to the count for this - int idx = KeyInstanceCount.Find( keyName ); - if ( idx == KeyInstanceCount.InvalidIndex() ) - { - idx = KeyInstanceCount.Insert( keyName, 0 ); - } - KeyInstanceCount[idx]++; - - // Entity I/O values are stored as "Targetname,", so we need to see if there's a ',' in the string - char *sValue = value; - // FIXME: This is very brittle. Any key with a , will not be found. - char *s = strchr( value, ',' ); - if ( s ) - { - // Grab just the targetname of the receiver - Q_strncpy( valueclipped, value, (s - value+1) ); - sValue = valueclipped; - } - - // Loop through our group templates - for ( int iTName = 0; iTName < iCount; iTName++ ) - { - char *pName = GroupTemplates[iTName].pszName; - if ( stricmp( pName, sValue ) ) - continue; - - if ( template_debug.GetInt() ) - { - Msg("Template Connection Found: Key %s (\"%s\") in entity named \"%s\"(%d) matches entity %d's targetname\n", keyName, sValue, GroupTemplates[i].pszName, i, iTName ); - } - - char newvalue[MAPKEY_MAXLENGTH]; - - // Get the current key instance. (-1 because it's this one we're changing) - int nKeyInstance = KeyInstanceCount[idx] - 1; - - // Add our IO value to the targetname - // We need to append it if this isn't an Entity I/O value, or prepend it to the ',' if it is - if ( s ) - { - Q_strncpy( newvalue, valueclipped, MAPKEY_MAXLENGTH ); - Q_strncat( newvalue, ENTITYIO_FIXUP_STRING, sizeof(newvalue), COPY_ALL_CHARACTERS ); - Q_strncat( newvalue, s, sizeof(newvalue), COPY_ALL_CHARACTERS ); - mapData->SetValue( keyName, newvalue, nKeyInstance ); - } - else - { - Q_strncpy( newvalue, sValue, MAPKEY_MAXLENGTH ); - Q_strncat( newvalue, ENTITYIO_FIXUP_STRING, sizeof(newvalue), COPY_ALL_CHARACTERS ); - mapData->SetValue( keyName, newvalue, nKeyInstance ); - } - - // Remember we changed this targetname - GroupTemplates[iTName].bChangeTargetname = true; - - // Set both entity's flags telling them their template needs fixup when it's spawned - g_Templates[ GroupTemplates[i].iIndex ]->bNeedsEntityIOFixup = true; - g_Templates[ GroupTemplates[iTName].iIndex ]->bNeedsEntityIOFixup = true; - } - } - while ( mapData->GetNextKey(keyName, value) ); - } - - // Now change targetnames for all entities that need them changed - for ( i = 0; i < iCount; i++ ) - { - char value[MAPKEY_MAXLENGTH]; - - if ( GroupTemplates[i].bChangeTargetname ) - { - CEntityMapData *mapData = GroupTemplates[i].pMapDataParser; - mapData->ExtractValue( "targetname", value ); - Q_strncat( value, ENTITYIO_FIXUP_STRING, sizeof(value), COPY_ALL_CHARACTERS ); - mapData->SetValue( "targetname", value ); - } - } - } - - // Delete our group parsers - for ( i = 0; i < iCount; i++ ) - { - delete GroupTemplates[i].pMapDataParser; - } - GroupTemplates.Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: Someone's about to start instancing a new group of entities. -// Generate a unique identifier for this group. -//----------------------------------------------------------------------------- -void Templates_StartUniqueInstance( void ) -{ - g_iCurrentTemplateInstance++; - - // Make sure there's enough room to fit it into the string - int iMax = (int)pow(10.0f, (int)((strlen(ENTITYIO_FIXUP_STRING) - 1))); // -1 for the & - if ( g_iCurrentTemplateInstance >= iMax ) - { - // We won't hit this. - Assert(0); - // Hopefully there were still be instance number 0 around. - g_iCurrentTemplateInstance = 0; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Someone wants to spawn an instance of a template that requires -// entity IO fixup. Fill out the pMapData with a copy of the template -// with unique key/values where the template requires them. -//----------------------------------------------------------------------------- -char *Templates_GetEntityIOFixedMapData( int iIndex ) -{ - Assert( Templates_IndexRequiresEntityIOFixup( iIndex ) ); - - // First time through? - if ( !g_Templates[iIndex]->pszFixedMapData ) - { - g_Templates[iIndex]->pszFixedMapData = new char[g_Templates[iIndex]->iMapDataLength]; - Q_strncpy( g_Templates[iIndex]->pszFixedMapData, g_Templates[iIndex]->pszMapData, g_Templates[iIndex]->iMapDataLength ); - } - - int iFixupSize = strlen(ENTITYIO_FIXUP_STRING); - char *sOurFixup = new char[iFixupSize]; - Q_snprintf( sOurFixup, iFixupSize, "%c%.4d", ENTITYIO_FIXUP_STRING[0], g_iCurrentTemplateInstance ); - - // Now rip through the map data string and replace any instances of the fixup string with our unique identifier - char *c = g_Templates[iIndex]->pszFixedMapData; - do - { - if ( *c == ENTITYIO_FIXUP_STRING[0] ) - { - // Make sure it's our fixup string - bool bValid = true; - for ( int i = 1; i < iFixupSize; i++ ) - { - // Look for any number, because we've already used this string - if ( !(*(c+i) >= '0' && *(c+i) <= '9') ) - { - // Some other string - bValid = false; - break; - } - } - - // Stomp it with our unique string - if ( bValid ) - { - memcpy( c, sOurFixup, iFixupSize ); - c += iFixupSize; - } - } - c++; - } while (*c); - - return g_Templates[iIndex]->pszFixedMapData; -} - -//----------------------------------------------------------------------------- -// Purpose: Frees all the template data. Called on level shutdown. -//----------------------------------------------------------------------------- -void Templates_RemoveAll(void) -{ - int nCount = g_Templates.Count(); - for (int i = 0; i < nCount; i++) - { - TemplateEntityData_t *pTemplate = g_Templates.Element(i); - - free((void *)pTemplate->pszName); - free(pTemplate->pszMapData); - if ( pTemplate->pszFixedMapData ) - { - free(pTemplate->pszFixedMapData); - } - - free(pTemplate); - } - - g_Templates.RemoveAll(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Hooks in the template manager's callbacks. -//----------------------------------------------------------------------------- -class CTemplatesHook : public CAutoGameSystem -{ -public: - CTemplatesHook( char const *name ) : CAutoGameSystem( name ) - { - } - - virtual void LevelShutdownPostEntity( void ) - { - Templates_RemoveAll(); - } -}; - -CTemplatesHook g_TemplateEntityHook( "CTemplatesHook" ); - - -//----------------------------------------------------------------------------- -// TEMPLATE SAVE / RESTORE -//----------------------------------------------------------------------------- -static short TEMPLATE_SAVE_RESTORE_VERSION = 1; - -class CTemplate_SaveRestoreBlockHandler : public CDefSaveRestoreBlockHandler -{ -public: - const char *GetBlockName() - { - return "Templates"; - } - - //--------------------------------- - - void Save( ISave *pSave ) - { - pSave->WriteInt( &g_iCurrentTemplateInstance ); - - short nCount = g_Templates.Count(); - pSave->WriteShort( &nCount ); - for ( int i = 0; i < nCount; i++ ) - { - TemplateEntityData_t *pTemplate = g_Templates[i]; - pSave->WriteAll( pTemplate ); - pSave->WriteString( pTemplate->pszName ); - pSave->WriteString( pTemplate->pszMapData ); - } - } - - //--------------------------------- - - void WriteSaveHeaders( ISave *pSave ) - { - pSave->WriteShort( &TEMPLATE_SAVE_RESTORE_VERSION ); - } - - //--------------------------------- - - void ReadRestoreHeaders( IRestore *pRestore ) - { - // No reason why any future version shouldn't try to retain backward compatability. The default here is to not do so. - short version; - pRestore->ReadShort( &version ); - m_fDoLoad = ( version == TEMPLATE_SAVE_RESTORE_VERSION ); - } - - //--------------------------------- - - void Restore( IRestore *pRestore, bool createPlayers ) - { - if ( m_fDoLoad ) - { - Templates_RemoveAll(); - g_Templates.Purge(); - g_iCurrentTemplateInstance = pRestore->ReadInt(); - - int iTemplates = pRestore->ReadShort(); - while ( iTemplates-- ) - { - TemplateEntityData_t *pNewTemplate = (TemplateEntityData_t *)malloc(sizeof(TemplateEntityData_t)); - pRestore->ReadAll( pNewTemplate ); - - int sizeData = 0;//pRestore->SkipHeader(); - char szName[MAPKEY_MAXLENGTH]; - pRestore->ReadString( szName, MAPKEY_MAXLENGTH, sizeData ); - pNewTemplate->pszName = strdup( szName ); - //sizeData = pRestore->SkipHeader(); - pNewTemplate->pszMapData = (char *)malloc( pNewTemplate->iMapDataLength ); - pRestore->ReadString( pNewTemplate->pszMapData, pNewTemplate->iMapDataLength, sizeData ); - - // Set this to NULL so it'll be created the first time it gets used - pNewTemplate->pszFixedMapData = NULL; - - g_Templates.AddToTail( pNewTemplate ); - } - } - - } - -private: - bool m_fDoLoad; -}; - -//----------------------------------------------------------------------------- - -CTemplate_SaveRestoreBlockHandler g_Template_SaveRestoreBlockHandler; - -//------------------------------------- - -ISaveRestoreBlockHandler *GetTemplateSaveRestoreBlockHandler() -{ - return &g_Template_SaveRestoreBlockHandler; -} diff --git a/game/server/TemplateEntities.h b/game/server/TemplateEntities.h deleted file mode 100644 index 44f1bf98b..000000000 --- a/game/server/TemplateEntities.h +++ /dev/null @@ -1,36 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Template entities are used by spawners to create copies of entities -// that were configured by the level designer. This allows us to spawn -// entities with arbitrary sets of key/value data and entity I/O -// connections. -// -//=============================================================================// - -#ifndef TEMPLATEENTITIES_H -#define TEMPLATEENTITIES_H -#ifdef _WIN32 -#pragma once -#endif - -#include "isaverestore.h" - -class CBaseEntity; -class CPointTemplate; - -int Templates_Add(CBaseEntity *pEntity, const char *pszMapData, int nLen); -string_t Templates_FindByIndex( int iIndex ); -int Templates_GetStringSize( int iIndex ); -string_t Templates_FindByTargetName(const char *pszName); -void Templates_ReconnectIOForGroup( CPointTemplate *pGroup ); - -// Some templates have Entity I/O connecting the entities within the template. -// Unique versions of these templates need to be created whenever they're instanced. -void Templates_StartUniqueInstance( void ); -bool Templates_IndexRequiresEntityIOFixup( int iIndex ); -char *Templates_GetEntityIOFixedMapData( int iIndex ); - -// Save / Restore -ISaveRestoreBlockHandler *GetTemplateSaveRestoreBlockHandler( void ); - -#endif // TEMPLATEENTITIES_H diff --git a/game/server/WaterLODControl.cpp b/game/server/WaterLODControl.cpp deleted file mode 100644 index 329c2f6db..000000000 --- a/game/server/WaterLODControl.cpp +++ /dev/null @@ -1,118 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Shadow control entity. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//------------------------------------------------------------------------------ -// FIXME: This really should inherit from something more lightweight -//------------------------------------------------------------------------------ - - -//------------------------------------------------------------------------------ -// Purpose : Water LOD control entity -//------------------------------------------------------------------------------ -class CWaterLODControl : public CBaseEntity -{ -public: - DECLARE_CLASS( CWaterLODControl, CBaseEntity ); - - CWaterLODControl(); - - void Spawn( void ); - bool KeyValue( const char *szKeyName, const char *szValue ); - int UpdateTransmitState(); - void SetCheapWaterStartDistance( inputdata_t &inputdata ); - void SetCheapWaterEndDistance( inputdata_t &inputdata ); - - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - -private: - CNetworkVar( float, m_flCheapWaterStartDistance ); - CNetworkVar( float, m_flCheapWaterEndDistance ); -}; - -LINK_ENTITY_TO_CLASS(water_lod_control, CWaterLODControl); - -BEGIN_DATADESC( CWaterLODControl ) - - DEFINE_KEYFIELD( m_flCheapWaterStartDistance, FIELD_FLOAT, "cheapwaterstartdistance" ), - DEFINE_KEYFIELD( m_flCheapWaterEndDistance, FIELD_FLOAT, "cheapwaterenddistance" ), - - // Inputs - DEFINE_INPUT( m_flCheapWaterStartDistance, FIELD_FLOAT, "SetCheapWaterStartDistance" ), - DEFINE_INPUT( m_flCheapWaterEndDistance, FIELD_FLOAT, "SetCheapWaterEndDistance" ), - -END_DATADESC() - - -IMPLEMENT_SERVERCLASS_ST_NOBASE(CWaterLODControl, DT_WaterLODControl) - SendPropFloat(SENDINFO(m_flCheapWaterStartDistance), 0, SPROP_NOSCALE ), - SendPropFloat(SENDINFO(m_flCheapWaterEndDistance), 0, SPROP_NOSCALE ), -END_SEND_TABLE() - - -CWaterLODControl::CWaterLODControl() -{ - m_flCheapWaterStartDistance = 1000.0f; - m_flCheapWaterEndDistance = 2000.0f; -} - - -//------------------------------------------------------------------------------ -// Purpose : Send even though we don't have a model -//------------------------------------------------------------------------------ -int CWaterLODControl::UpdateTransmitState() -{ - // ALWAYS transmit to all clients. - return SetTransmitState( FL_EDICT_ALWAYS ); -} - - -bool CWaterLODControl::KeyValue( const char *szKeyName, const char *szValue ) -{ - if ( FStrEq( szKeyName, "cheapwaterstartdistance" ) ) - { - m_flCheapWaterStartDistance = atof( szValue ); - return true; - } - - if ( FStrEq( szKeyName, "cheapwaterenddistance" ) ) - { - m_flCheapWaterEndDistance = atof( szValue ); - return true; - } - - return BaseClass::KeyValue( szKeyName, szValue ); -} - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CWaterLODControl::Spawn( void ) -{ - Precache(); - SetSolid( SOLID_NONE ); -} - -//------------------------------------------------------------------------------ -// Input values -//------------------------------------------------------------------------------ -void CWaterLODControl::SetCheapWaterStartDistance( inputdata_t &inputdata ) -{ - m_flCheapWaterStartDistance = atof( inputdata.value.String() ); -} - -void CWaterLODControl::SetCheapWaterEndDistance( inputdata_t &inputdata ) -{ - m_flCheapWaterEndDistance = atof( inputdata.value.String() ); -} diff --git a/game/server/actanimating.cpp b/game/server/actanimating.cpp deleted file mode 100644 index e78c23f82..000000000 --- a/game/server/actanimating.cpp +++ /dev/null @@ -1,31 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "actanimating.h" -#include "animation.h" -#include "activitylist.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -BEGIN_DATADESC( CActAnimating ) - DEFINE_CUSTOM_FIELD( m_Activity, ActivityDataOps() ), -END_DATADESC() - - -void CActAnimating::SetActivity( Activity act ) -{ - int sequence = SelectWeightedSequence( act ); - if ( sequence != ACTIVITY_NOT_AVAILABLE ) - { - ResetSequence( sequence ); - m_Activity = act; - SetCycle( 0 ); - } -} - diff --git a/game/server/actanimating.h b/game/server/actanimating.h deleted file mode 100644 index 009ea2026..000000000 --- a/game/server/actanimating.h +++ /dev/null @@ -1,35 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ACTANIMATING_H -#define ACTANIMATING_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "baseanimating.h" - -class CActAnimating : public CBaseAnimating -{ -public: - DECLARE_CLASS( CActAnimating, CBaseAnimating ); - - void SetActivity( Activity act ); - inline Activity GetActivity( void ) { return m_Activity; } - - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } - - DECLARE_DATADESC(); - -private: - Activity m_Activity; -}; - - - -#endif // ACTANIMATING_H diff --git a/game/server/ai_activity.cpp b/game/server/ai_activity.cpp deleted file mode 100644 index f68436dac..000000000 --- a/game/server/ai_activity.cpp +++ /dev/null @@ -1,1697 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Activities that are available to all NPCs. -// -//=============================================================================// - -#include "cbase.h" -#include "ai_activity.h" -#include "ai_basenpc.h" -#include "stringregistry.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//============================================================================= -// Init static variables -//============================================================================= -CStringRegistry* CAI_BaseNPC::m_pActivitySR = NULL; -int CAI_BaseNPC::m_iNumActivities = 0; - -//----------------------------------------------------------------------------- -// Purpose: Add an activity to the activity string registry and increment -// the acitivty counter -//----------------------------------------------------------------------------- -void CAI_BaseNPC::AddActivityToSR(const char *actName, int actID) -{ - Assert( m_pActivitySR ); - if ( !m_pActivitySR ) - return; - - // technically order isn't dependent, but it's too damn easy to forget to add new ACT_'s to all three lists. - - // NOTE: This assertion generally means that the activity enums are out of order or that new enums were not added to all - // relevant tables. Make sure that you have included all new enums in: - // game_shared/ai_activity.h - // game_shared/activitylist.cpp - // dlls/ai_activity.cpp - MEM_ALLOC_CREDIT(); - - static int lastActID = -2; - Assert( actID >= LAST_SHARED_ACTIVITY || actID == lastActID + 1 || actID == ACT_INVALID ); - lastActID = actID; - - m_pActivitySR->AddString(actName, actID); - m_iNumActivities++; -} - -//----------------------------------------------------------------------------- -// Purpose: Given and activity ID, return the activity name -//----------------------------------------------------------------------------- -const char *CAI_BaseNPC::GetActivityName(int actID) -{ - if ( actID == -1 ) - return "ACT_INVALID"; - - // m_pActivitySR only contains public activities, ActivityList_NameForIndex() has them all - const char *name = ActivityList_NameForIndex(actID); - - if( !name ) - { - AssertOnce( !"CAI_BaseNPC::GetActivityName() returning NULL!" ); - } - - return name; -} - -//----------------------------------------------------------------------------- -// Purpose: Given and activity name, return the activity ID -//----------------------------------------------------------------------------- -int CAI_BaseNPC::GetActivityID(const char* actName) -{ - Assert( m_pActivitySR ); - if ( !m_pActivitySR ) - return ACT_INVALID; - - return m_pActivitySR->GetStringID(actName); -} - -#define ADD_ACTIVITY_TO_SR(activityname) AddActivityToSR(#activityname,activityname) - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::InitDefaultActivitySR(void) -{ - ADD_ACTIVITY_TO_SR( ACT_INVALID ); - ADD_ACTIVITY_TO_SR( ACT_RESET ); - ADD_ACTIVITY_TO_SR( ACT_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_TRANSITION ); - ADD_ACTIVITY_TO_SR( ACT_COVER ); - ADD_ACTIVITY_TO_SR( ACT_COVER_MED ); - ADD_ACTIVITY_TO_SR( ACT_COVER_LOW ); - ADD_ACTIVITY_TO_SR( ACT_WALK ); - ADD_ACTIVITY_TO_SR( ACT_WALK_AIM ); - ADD_ACTIVITY_TO_SR( ACT_WALK_CROUCH ); - ADD_ACTIVITY_TO_SR( ACT_WALK_CROUCH_AIM ); - ADD_ACTIVITY_TO_SR( ACT_RUN ); - ADD_ACTIVITY_TO_SR( ACT_RUN_AIM ); - ADD_ACTIVITY_TO_SR( ACT_RUN_CROUCH ); - ADD_ACTIVITY_TO_SR( ACT_RUN_CROUCH_AIM ); - ADD_ACTIVITY_TO_SR( ACT_RUN_PROTECTED ); - ADD_ACTIVITY_TO_SR( ACT_SCRIPT_CUSTOM_MOVE ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK1 ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK2 ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK1_LOW ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK2_LOW ); - ADD_ACTIVITY_TO_SR( ACT_DIESIMPLE ); - ADD_ACTIVITY_TO_SR( ACT_DIEBACKWARD ); - ADD_ACTIVITY_TO_SR( ACT_DIEFORWARD ); - ADD_ACTIVITY_TO_SR( ACT_DIEVIOLENT ); - ADD_ACTIVITY_TO_SR( ACT_DIERAGDOLL ); - ADD_ACTIVITY_TO_SR( ACT_FLY ); - ADD_ACTIVITY_TO_SR( ACT_HOVER ); - ADD_ACTIVITY_TO_SR( ACT_GLIDE ); - ADD_ACTIVITY_TO_SR( ACT_SWIM ); - ADD_ACTIVITY_TO_SR( ACT_JUMP ); - ADD_ACTIVITY_TO_SR( ACT_HOP ); - ADD_ACTIVITY_TO_SR( ACT_LEAP ); - ADD_ACTIVITY_TO_SR( ACT_LAND ); - ADD_ACTIVITY_TO_SR( ACT_CLIMB_UP ); - ADD_ACTIVITY_TO_SR( ACT_CLIMB_DOWN ); - ADD_ACTIVITY_TO_SR( ACT_CLIMB_DISMOUNT ); - ADD_ACTIVITY_TO_SR( ACT_SHIPLADDER_UP ); - ADD_ACTIVITY_TO_SR( ACT_SHIPLADDER_DOWN ); - ADD_ACTIVITY_TO_SR( ACT_STRAFE_LEFT ); - ADD_ACTIVITY_TO_SR( ACT_STRAFE_RIGHT ); - ADD_ACTIVITY_TO_SR( ACT_ROLL_LEFT ); - ADD_ACTIVITY_TO_SR( ACT_ROLL_RIGHT ); - ADD_ACTIVITY_TO_SR( ACT_TURN_LEFT ); - ADD_ACTIVITY_TO_SR( ACT_TURN_RIGHT ); - ADD_ACTIVITY_TO_SR( ACT_CROUCH ); - ADD_ACTIVITY_TO_SR( ACT_CROUCHIDLE ); - ADD_ACTIVITY_TO_SR( ACT_STAND ); - ADD_ACTIVITY_TO_SR( ACT_USE ); - ADD_ACTIVITY_TO_SR( ACT_SIGNAL1 ); - ADD_ACTIVITY_TO_SR( ACT_SIGNAL2 ); - ADD_ACTIVITY_TO_SR( ACT_SIGNAL3 ); - - ADD_ACTIVITY_TO_SR( ACT_SIGNAL_ADVANCE ); - ADD_ACTIVITY_TO_SR( ACT_SIGNAL_FORWARD ); - ADD_ACTIVITY_TO_SR( ACT_SIGNAL_GROUP ); - ADD_ACTIVITY_TO_SR( ACT_SIGNAL_HALT ); - ADD_ACTIVITY_TO_SR( ACT_SIGNAL_LEFT ); - ADD_ACTIVITY_TO_SR( ACT_SIGNAL_RIGHT ); - ADD_ACTIVITY_TO_SR( ACT_SIGNAL_TAKECOVER ); - - ADD_ACTIVITY_TO_SR( ACT_LOOKBACK_RIGHT ); - ADD_ACTIVITY_TO_SR( ACT_LOOKBACK_LEFT ); - ADD_ACTIVITY_TO_SR( ACT_COWER ); - ADD_ACTIVITY_TO_SR( ACT_SMALL_FLINCH ); - ADD_ACTIVITY_TO_SR( ACT_BIG_FLINCH ); - ADD_ACTIVITY_TO_SR( ACT_MELEE_ATTACK1 ); - ADD_ACTIVITY_TO_SR( ACT_MELEE_ATTACK2 ); - ADD_ACTIVITY_TO_SR( ACT_RELOAD ); - ADD_ACTIVITY_TO_SR( ACT_RELOAD_START ); - ADD_ACTIVITY_TO_SR( ACT_RELOAD_FINISH ); - ADD_ACTIVITY_TO_SR( ACT_RELOAD_LOW ); - ADD_ACTIVITY_TO_SR( ACT_ARM ); - ADD_ACTIVITY_TO_SR( ACT_DISARM ); - ADD_ACTIVITY_TO_SR( ACT_DROP_WEAPON ); - ADD_ACTIVITY_TO_SR( ACT_DROP_WEAPON_SHOTGUN ); - ADD_ACTIVITY_TO_SR( ACT_PICKUP_GROUND ); - ADD_ACTIVITY_TO_SR( ACT_PICKUP_RACK ); - ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY ); - - ADD_ACTIVITY_TO_SR( ACT_IDLE_RELAXED ); - ADD_ACTIVITY_TO_SR( ACT_IDLE_STIMULATED ); - ADD_ACTIVITY_TO_SR( ACT_IDLE_AGITATED ); - ADD_ACTIVITY_TO_SR( ACT_IDLE_STEALTH ); - ADD_ACTIVITY_TO_SR( ACT_IDLE_HURT ); - - ADD_ACTIVITY_TO_SR( ACT_WALK_RELAXED ); - ADD_ACTIVITY_TO_SR( ACT_WALK_STIMULATED ); - ADD_ACTIVITY_TO_SR( ACT_WALK_AGITATED ); - ADD_ACTIVITY_TO_SR( ACT_WALK_STEALTH ); - - ADD_ACTIVITY_TO_SR( ACT_RUN_RELAXED ); - ADD_ACTIVITY_TO_SR( ACT_RUN_STIMULATED ); - ADD_ACTIVITY_TO_SR( ACT_RUN_AGITATED ); - ADD_ACTIVITY_TO_SR( ACT_RUN_STEALTH ); - - ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_RELAXED ); - ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_STIMULATED ); - ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_AGITATED ); - ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_STEALTH ); - - ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_RELAXED ); - ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_STIMULATED ); - ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_AGITATED ); - ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_STEALTH ); - - ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_RELAXED ); - ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_STIMULATED ); - ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_AGITATED ); - ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_STEALTH ); - - ADD_ACTIVITY_TO_SR( ACT_CROUCHIDLE_STIMULATED ); - ADD_ACTIVITY_TO_SR( ACT_CROUCHIDLE_AIM_STIMULATED ); - ADD_ACTIVITY_TO_SR( ACT_CROUCHIDLE_AGITATED ); - - ADD_ACTIVITY_TO_SR( ACT_WALK_HURT ); - ADD_ACTIVITY_TO_SR( ACT_RUN_HURT ); - ADD_ACTIVITY_TO_SR( ACT_SPECIAL_ATTACK1 ); - ADD_ACTIVITY_TO_SR( ACT_SPECIAL_ATTACK2 ); - ADD_ACTIVITY_TO_SR( ACT_COMBAT_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_WALK_SCARED ); - ADD_ACTIVITY_TO_SR( ACT_RUN_SCARED ); - ADD_ACTIVITY_TO_SR( ACT_VICTORY_DANCE ); - - ADD_ACTIVITY_TO_SR( ACT_DIE_HEADSHOT ); - ADD_ACTIVITY_TO_SR( ACT_DIE_CHESTSHOT ); - ADD_ACTIVITY_TO_SR( ACT_DIE_GUTSHOT ); - ADD_ACTIVITY_TO_SR( ACT_DIE_BACKSHOT ); - - ADD_ACTIVITY_TO_SR( ACT_FLINCH_HEAD ); - ADD_ACTIVITY_TO_SR( ACT_FLINCH_CHEST ); - ADD_ACTIVITY_TO_SR( ACT_FLINCH_STOMACH ); - ADD_ACTIVITY_TO_SR( ACT_FLINCH_LEFTARM ); - ADD_ACTIVITY_TO_SR( ACT_FLINCH_RIGHTARM ); - ADD_ACTIVITY_TO_SR( ACT_FLINCH_LEFTLEG ); - ADD_ACTIVITY_TO_SR( ACT_FLINCH_RIGHTLEG ); - ADD_ACTIVITY_TO_SR( ACT_FLINCH_PHYSICS ); - - ADD_ACTIVITY_TO_SR( ACT_IDLE_ON_FIRE ); - ADD_ACTIVITY_TO_SR( ACT_WALK_ON_FIRE ); - ADD_ACTIVITY_TO_SR( ACT_RUN_ON_FIRE ); - - ADD_ACTIVITY_TO_SR( ACT_RAPPEL_LOOP ); - - ADD_ACTIVITY_TO_SR( ACT_180_LEFT ); - ADD_ACTIVITY_TO_SR( ACT_180_RIGHT ); - ADD_ACTIVITY_TO_SR( ACT_90_LEFT ); - ADD_ACTIVITY_TO_SR( ACT_90_RIGHT ); - ADD_ACTIVITY_TO_SR( ACT_STEP_LEFT ); - ADD_ACTIVITY_TO_SR( ACT_STEP_RIGHT ); - ADD_ACTIVITY_TO_SR( ACT_STEP_BACK ); - ADD_ACTIVITY_TO_SR( ACT_STEP_FORE ); - - ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK1 ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK2 ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_MELEE_ATTACK1 ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_MELEE_ATTACK2 ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK1_LOW ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK2_LOW ); - ADD_ACTIVITY_TO_SR( ACT_MELEE_ATTACK_SWING_GESTURE ); - - ADD_ACTIVITY_TO_SR( ACT_GESTURE_SMALL_FLINCH ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_BIG_FLINCH ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_FLINCH_BLAST ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_FLINCH_BLAST_SHOTGUN ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_FLINCH_BLAST_DAMAGED ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_FLINCH_BLAST_DAMAGED_SHOTGUN ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_FLINCH_HEAD ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_FLINCH_CHEST ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_FLINCH_STOMACH ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_FLINCH_LEFTARM ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_FLINCH_RIGHTARM ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_FLINCH_LEFTLEG ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_FLINCH_RIGHTLEG ); - - ADD_ACTIVITY_TO_SR( ACT_GESTURE_TURN_LEFT ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_TURN_RIGHT ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_TURN_LEFT45 ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_TURN_RIGHT45 ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_TURN_LEFT90 ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_TURN_RIGHT90 ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_TURN_LEFT45_FLAT ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_TURN_RIGHT45_FLAT ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_TURN_LEFT90_FLAT ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_TURN_RIGHT90_FLAT ); - - ADD_ACTIVITY_TO_SR( ACT_BARNACLE_HIT ); - ADD_ACTIVITY_TO_SR( ACT_BARNACLE_PULL ); - ADD_ACTIVITY_TO_SR( ACT_BARNACLE_CHOMP ); - ADD_ACTIVITY_TO_SR( ACT_BARNACLE_CHEW ); - - ADD_ACTIVITY_TO_SR( ACT_DO_NOT_DISTURB ); - - ADD_ACTIVITY_TO_SR( ACT_VM_DRAW ); - ADD_ACTIVITY_TO_SR( ACT_VM_HOLSTER ); - ADD_ACTIVITY_TO_SR( ACT_VM_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_VM_FIDGET ); - ADD_ACTIVITY_TO_SR( ACT_VM_PULLBACK ); - ADD_ACTIVITY_TO_SR( ACT_VM_PULLBACK_HIGH ); - ADD_ACTIVITY_TO_SR( ACT_VM_PULLBACK_LOW ); - ADD_ACTIVITY_TO_SR( ACT_VM_THROW ); - ADD_ACTIVITY_TO_SR( ACT_VM_PULLPIN ); - ADD_ACTIVITY_TO_SR( ACT_VM_PRIMARYATTACK ); - ADD_ACTIVITY_TO_SR( ACT_VM_SECONDARYATTACK ); - ADD_ACTIVITY_TO_SR( ACT_VM_RELOAD ); - ADD_ACTIVITY_TO_SR( ACT_VM_DRYFIRE ); - ADD_ACTIVITY_TO_SR( ACT_VM_HITLEFT ); - ADD_ACTIVITY_TO_SR( ACT_VM_HITLEFT2 ); - ADD_ACTIVITY_TO_SR( ACT_VM_HITRIGHT ); - ADD_ACTIVITY_TO_SR( ACT_VM_HITRIGHT2 ); - ADD_ACTIVITY_TO_SR( ACT_VM_HITCENTER ); - ADD_ACTIVITY_TO_SR( ACT_VM_HITCENTER2 ); - ADD_ACTIVITY_TO_SR( ACT_VM_MISSLEFT ); - ADD_ACTIVITY_TO_SR( ACT_VM_MISSLEFT2 ); - ADD_ACTIVITY_TO_SR( ACT_VM_MISSRIGHT ); - ADD_ACTIVITY_TO_SR( ACT_VM_MISSRIGHT2 ); - ADD_ACTIVITY_TO_SR( ACT_VM_MISSCENTER ); - ADD_ACTIVITY_TO_SR( ACT_VM_MISSCENTER2 ); - ADD_ACTIVITY_TO_SR( ACT_VM_HAULBACK ); - ADD_ACTIVITY_TO_SR( ACT_VM_SWINGHARD ); - ADD_ACTIVITY_TO_SR( ACT_VM_SWINGMISS ); - ADD_ACTIVITY_TO_SR( ACT_VM_SWINGHIT ); - ADD_ACTIVITY_TO_SR( ACT_VM_IDLE_TO_LOWERED ); - ADD_ACTIVITY_TO_SR( ACT_VM_IDLE_LOWERED ); - ADD_ACTIVITY_TO_SR( ACT_VM_LOWERED_TO_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_VM_RECOIL1 ); - ADD_ACTIVITY_TO_SR( ACT_VM_RECOIL2 ); - ADD_ACTIVITY_TO_SR( ACT_VM_RECOIL3 ); - ADD_ACTIVITY_TO_SR( ACT_VM_PICKUP ); - ADD_ACTIVITY_TO_SR( ACT_VM_RELEASE ); - - ADD_ACTIVITY_TO_SR( ACT_VM_ATTACH_SILENCER ); - ADD_ACTIVITY_TO_SR( ACT_VM_DETACH_SILENCER ); - -//=========================== -// HL2 Specific Activities -//=========================== - - // SLAM Specialty Activities - ADD_ACTIVITY_TO_SR( ACT_SLAM_STICKWALL_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_STICKWALL_ND_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_STICKWALL_ATTACH ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_STICKWALL_ATTACH2 ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_STICKWALL_ND_ATTACH ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_STICKWALL_ND_ATTACH2 ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_STICKWALL_DETONATE ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_STICKWALL_DETONATOR_HOLSTER ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_STICKWALL_DRAW ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_STICKWALL_ND_DRAW ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_STICKWALL_TO_THROW ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_STICKWALL_TO_THROW_ND ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_STICKWALL_TO_TRIPMINE_ND ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_THROW_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_THROW_ND_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_THROW_THROW ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_THROW_THROW2 ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_THROW_THROW_ND ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_THROW_THROW_ND2 ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_THROW_DRAW ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_THROW_ND_DRAW ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_THROW_TO_STICKWALL ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_THROW_TO_STICKWALL_ND ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_THROW_DETONATE ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_THROW_DETONATOR_HOLSTER ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_THROW_TO_TRIPMINE_ND ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_TRIPMINE_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_TRIPMINE_DRAW ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_TRIPMINE_ATTACH ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_TRIPMINE_ATTACH2 ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_TRIPMINE_TO_STICKWALL_ND ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_TRIPMINE_TO_THROW_ND ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_DETONATOR_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_DETONATOR_DRAW ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_DETONATOR_DETONATE ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_DETONATOR_HOLSTER ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_DETONATOR_STICKWALL_DRAW ); - ADD_ACTIVITY_TO_SR( ACT_SLAM_DETONATOR_THROW_DRAW ); - - // SHOTGUN Specialty Activities - ADD_ACTIVITY_TO_SR( ACT_SHOTGUN_RELOAD_START ); - ADD_ACTIVITY_TO_SR( ACT_SHOTGUN_RELOAD_FINISH ); - ADD_ACTIVITY_TO_SR( ACT_SHOTGUN_PUMP ); - - // SMG2 special activities - ADD_ACTIVITY_TO_SR( ACT_SMG2_IDLE2 ); - ADD_ACTIVITY_TO_SR( ACT_SMG2_FIRE2 ); - ADD_ACTIVITY_TO_SR( ACT_SMG2_DRAW2 ); - ADD_ACTIVITY_TO_SR( ACT_SMG2_RELOAD2 ); - ADD_ACTIVITY_TO_SR( ACT_SMG2_DRYFIRE2 ); - ADD_ACTIVITY_TO_SR( ACT_SMG2_TOAUTO ); - ADD_ACTIVITY_TO_SR( ACT_SMG2_TOBURST ); - - // Physcannon special activities - ADD_ACTIVITY_TO_SR( ACT_PHYSCANNON_UPGRADE ); - - ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_AR1 ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_AR2 ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_AR2_LOW ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_AR2_GRENADE ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_HMG1 ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_ML ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_SMG1 ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_SMG1_LOW ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_SMG2 ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_SHOTGUN ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_SHOTGUN_LOW ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_PISTOL_LOW ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_SLAM ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_TRIPWIRE ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_THROW ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_SNIPER_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_ATTACK_RPG ); - ADD_ACTIVITY_TO_SR( ACT_MELEE_ATTACK_SWING ); - - ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_LOW ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_SMG1_LOW ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_PISTOL_LOW ); - ADD_ACTIVITY_TO_SR( ACT_RANGE_AIM_AR2_LOW ); - - ADD_ACTIVITY_TO_SR( ACT_COVER_PISTOL_LOW ); - ADD_ACTIVITY_TO_SR( ACT_COVER_SMG1_LOW ); - - ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_AR1 ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_AR2 ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_AR2_GRENADE ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_HMG1 ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_ML ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_SMG1 ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_SMG1_LOW ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_SMG2 ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_SHOTGUN ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_PISTOL_LOW ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_SLAM ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_TRIPWIRE ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_THROW ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_RANGE_ATTACK_SNIPER_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_MELEE_ATTACK_SWING ); - - ADD_ACTIVITY_TO_SR( ACT_IDLE_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_IDLE_SMG1 ); - ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_SMG1 ); - ADD_ACTIVITY_TO_SR( ACT_IDLE_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_SHOTGUN ); - ADD_ACTIVITY_TO_SR( ACT_IDLE_STEALTH_PISTOL ); - - ADD_ACTIVITY_TO_SR( ACT_IDLE_PACKAGE ); - ADD_ACTIVITY_TO_SR( ACT_WALK_PACKAGE ); - ADD_ACTIVITY_TO_SR( ACT_IDLE_SUITCASE ); - ADD_ACTIVITY_TO_SR( ACT_WALK_SUITCASE ); - - ADD_ACTIVITY_TO_SR( ACT_IDLE_SMG1_RELAXED ); - ADD_ACTIVITY_TO_SR( ACT_IDLE_SMG1_STIMULATED ); - - ADD_ACTIVITY_TO_SR( ACT_WALK_RIFLE_RELAXED ); - ADD_ACTIVITY_TO_SR( ACT_RUN_RIFLE_RELAXED ); - ADD_ACTIVITY_TO_SR( ACT_WALK_RIFLE_STIMULATED ); - ADD_ACTIVITY_TO_SR( ACT_RUN_RIFLE_STIMULATED ); - - ADD_ACTIVITY_TO_SR( ACT_IDLE_AIM_RIFLE_STIMULATED ); - ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_RIFLE_STIMULATED ); - ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_RIFLE_STIMULATED ); - - ADD_ACTIVITY_TO_SR( ACT_IDLE_SHOTGUN_RELAXED ); - ADD_ACTIVITY_TO_SR( ACT_IDLE_SHOTGUN_STIMULATED ); - ADD_ACTIVITY_TO_SR( ACT_IDLE_SHOTGUN_AGITATED ); - - // Policing activities - ADD_ACTIVITY_TO_SR( ACT_WALK_ANGRY ); - ADD_ACTIVITY_TO_SR( ACT_POLICE_HARASS1 ); - ADD_ACTIVITY_TO_SR( ACT_POLICE_HARASS2 ); - - // Manned guns - ADD_ACTIVITY_TO_SR( ACT_IDLE_MANNEDGUN ); - - // Melee weapon activities - ADD_ACTIVITY_TO_SR( ACT_IDLE_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_MELEE ); - - // RPG activities - ADD_ACTIVITY_TO_SR( ACT_IDLE_RPG_RELAXED ); - ADD_ACTIVITY_TO_SR( ACT_IDLE_RPG ); - ADD_ACTIVITY_TO_SR( ACT_IDLE_ANGRY_RPG ); - ADD_ACTIVITY_TO_SR( ACT_COVER_LOW_RPG ); - ADD_ACTIVITY_TO_SR( ACT_WALK_RPG ); - ADD_ACTIVITY_TO_SR( ACT_RUN_RPG ); - ADD_ACTIVITY_TO_SR( ACT_WALK_CROUCH_RPG ); - ADD_ACTIVITY_TO_SR( ACT_RUN_CROUCH_RPG ); - ADD_ACTIVITY_TO_SR( ACT_WALK_RPG_RELAXED ); - ADD_ACTIVITY_TO_SR( ACT_RUN_RPG_RELAXED ); - - ADD_ACTIVITY_TO_SR( ACT_WALK_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_WALK_CROUCH_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_WALK_CROUCH_AIM_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_RUN_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_RUN_CROUCH_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_RUN_CROUCH_AIM_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_RUN_STEALTH_PISTOL ); - - ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_SHOTGUN ); - ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_SHOTGUN ); - - ADD_ACTIVITY_TO_SR( ACT_WALK_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_RUN_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_WALK_STEALTH_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_WALK_AIM_STEALTH_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_RUN_AIM_STEALTH_PISTOL ); - - ADD_ACTIVITY_TO_SR( ACT_RELOAD_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_RELOAD_PISTOL_LOW ); - ADD_ACTIVITY_TO_SR( ACT_RELOAD_SMG1 ); - ADD_ACTIVITY_TO_SR( ACT_RELOAD_SMG1_LOW ); - ADD_ACTIVITY_TO_SR( ACT_RELOAD_SHOTGUN ); - ADD_ACTIVITY_TO_SR( ACT_RELOAD_SHOTGUN_LOW ); - - ADD_ACTIVITY_TO_SR( ACT_GESTURE_RELOAD ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_RELOAD_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_RELOAD_SMG1 ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_RELOAD_SHOTGUN ); - - // Busy animations - ADD_ACTIVITY_TO_SR( ACT_BUSY_LEAN_LEFT ); - ADD_ACTIVITY_TO_SR( ACT_BUSY_LEAN_LEFT_ENTRY ); - ADD_ACTIVITY_TO_SR( ACT_BUSY_LEAN_LEFT_EXIT ); - ADD_ACTIVITY_TO_SR( ACT_BUSY_LEAN_BACK ); - ADD_ACTIVITY_TO_SR( ACT_BUSY_LEAN_BACK_ENTRY ); - ADD_ACTIVITY_TO_SR( ACT_BUSY_LEAN_BACK_EXIT ); - ADD_ACTIVITY_TO_SR( ACT_BUSY_SIT_GROUND ); - ADD_ACTIVITY_TO_SR( ACT_BUSY_SIT_GROUND_ENTRY ); - ADD_ACTIVITY_TO_SR( ACT_BUSY_SIT_GROUND_EXIT ); - ADD_ACTIVITY_TO_SR( ACT_BUSY_SIT_CHAIR ); - ADD_ACTIVITY_TO_SR( ACT_BUSY_SIT_CHAIR_ENTRY ); - ADD_ACTIVITY_TO_SR( ACT_BUSY_SIT_CHAIR_EXIT ); - ADD_ACTIVITY_TO_SR( ACT_BUSY_STAND ); - ADD_ACTIVITY_TO_SR( ACT_BUSY_QUEUE ); - - // Dodge animations - ADD_ACTIVITY_TO_SR( ACT_DUCK_DODGE ); - - ADD_ACTIVITY_TO_SR( ACT_DIE_BARNACLE_SWALLOW ); - ADD_ACTIVITY_TO_SR( ACT_GESTURE_BARNACLE_STRANGLE ); - ADD_ACTIVITY_TO_SR( ACT_PHYSCANNON_DETACH ); - ADD_ACTIVITY_TO_SR( ACT_PHYSCANNON_ANIMATE ); - ADD_ACTIVITY_TO_SR( ACT_PHYSCANNON_ANIMATE_PRE ); - ADD_ACTIVITY_TO_SR( ACT_PHYSCANNON_ANIMATE_POST ); - - ADD_ACTIVITY_TO_SR( ACT_DIE_FRONTSIDE ); - ADD_ACTIVITY_TO_SR( ACT_DIE_RIGHTSIDE ); - ADD_ACTIVITY_TO_SR( ACT_DIE_BACKSIDE ); - ADD_ACTIVITY_TO_SR( ACT_DIE_LEFTSIDE ); - - ADD_ACTIVITY_TO_SR( ACT_OPEN_DOOR ); - - // Dynamic interactions - ADD_ACTIVITY_TO_SR( ACT_DI_ALYX_ZOMBIE_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_DI_ALYX_ZOMBIE_TORSO_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_DI_ALYX_HEADCRAB_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_DI_ALYX_ANTLION ); - ADD_ACTIVITY_TO_SR( ACT_DI_ALYX_ZOMBIE_SHOTGUN64 ); - ADD_ACTIVITY_TO_SR( ACT_DI_ALYX_ZOMBIE_SHOTGUN26 ); - - ADD_ACTIVITY_TO_SR( ACT_READINESS_RELAXED_TO_STIMULATED ); - ADD_ACTIVITY_TO_SR( ACT_READINESS_RELAXED_TO_STIMULATED_WALK ); - ADD_ACTIVITY_TO_SR( ACT_READINESS_AGITATED_TO_STIMULATED ); - ADD_ACTIVITY_TO_SR( ACT_READINESS_STIMULATED_TO_RELAXED ); - - ADD_ACTIVITY_TO_SR( ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED ); - ADD_ACTIVITY_TO_SR( ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED_WALK ); - ADD_ACTIVITY_TO_SR( ACT_READINESS_PISTOL_AGITATED_TO_STIMULATED ); - ADD_ACTIVITY_TO_SR( ACT_READINESS_PISTOL_STIMULATED_TO_RELAXED ); - - ADD_ACTIVITY_TO_SR( ACT_IDLE_CARRY ); - ADD_ACTIVITY_TO_SR( ACT_WALK_CARRY ); - -//=========================== -// TF2 Specific Activities -//=========================== - ADD_ACTIVITY_TO_SR( ACT_STARTDYING ); - ADD_ACTIVITY_TO_SR( ACT_DYINGLOOP ); - ADD_ACTIVITY_TO_SR( ACT_DYINGTODEAD ); - ADD_ACTIVITY_TO_SR( ACT_RIDE_MANNED_GUN ); - - // All viewmodels - ADD_ACTIVITY_TO_SR( ACT_VM_SPRINT_ENTER ); - ADD_ACTIVITY_TO_SR( ACT_VM_SPRINT_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_VM_SPRINT_LEAVE ); - - // Looping weapon firing - ADD_ACTIVITY_TO_SR( ACT_FIRE_START ); - ADD_ACTIVITY_TO_SR( ACT_FIRE_LOOP ); - ADD_ACTIVITY_TO_SR( ACT_FIRE_END ); - - ADD_ACTIVITY_TO_SR( ACT_CROUCHING_GRENADEIDLE ); - ADD_ACTIVITY_TO_SR( ACT_CROUCHING_GRENADEREADY ); - ADD_ACTIVITY_TO_SR( ACT_CROUCHING_PRIMARYATTACK ); - ADD_ACTIVITY_TO_SR( ACT_OVERLAY_GRENADEIDLE ); - ADD_ACTIVITY_TO_SR( ACT_OVERLAY_GRENADEREADY ); - ADD_ACTIVITY_TO_SR( ACT_OVERLAY_PRIMARYATTACK ); - ADD_ACTIVITY_TO_SR( ACT_OVERLAY_SHIELD_UP ); - ADD_ACTIVITY_TO_SR( ACT_OVERLAY_SHIELD_DOWN ); - ADD_ACTIVITY_TO_SR( ACT_OVERLAY_SHIELD_UP_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_OVERLAY_SHIELD_ATTACK ); - ADD_ACTIVITY_TO_SR( ACT_OVERLAY_SHIELD_KNOCKBACK ); - ADD_ACTIVITY_TO_SR( ACT_SHIELD_UP ); - ADD_ACTIVITY_TO_SR( ACT_SHIELD_DOWN ); - ADD_ACTIVITY_TO_SR( ACT_SHIELD_UP_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_SHIELD_ATTACK ); - ADD_ACTIVITY_TO_SR( ACT_SHIELD_KNOCKBACK ); - ADD_ACTIVITY_TO_SR( ACT_CROUCHING_SHIELD_UP ); - ADD_ACTIVITY_TO_SR( ACT_CROUCHING_SHIELD_DOWN ); - ADD_ACTIVITY_TO_SR( ACT_CROUCHING_SHIELD_UP_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_CROUCHING_SHIELD_ATTACK ); - ADD_ACTIVITY_TO_SR( ACT_CROUCHING_SHIELD_KNOCKBACK ); - - ADD_ACTIVITY_TO_SR( ACT_TURNRIGHT45 ); - ADD_ACTIVITY_TO_SR( ACT_TURNLEFT45 ); - ADD_ACTIVITY_TO_SR( ACT_TURN ); - - // TF2 object animations - ADD_ACTIVITY_TO_SR( ACT_OBJ_ASSEMBLING ); - ADD_ACTIVITY_TO_SR( ACT_OBJ_DISMANTLING ); - ADD_ACTIVITY_TO_SR( ACT_OBJ_STARTUP ); - ADD_ACTIVITY_TO_SR( ACT_OBJ_RUNNING ); - ADD_ACTIVITY_TO_SR( ACT_OBJ_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_OBJ_PLACING ); - ADD_ACTIVITY_TO_SR( ACT_OBJ_DETERIORATING ); - ADD_ACTIVITY_TO_SR( ACT_OBJ_UPGRADING ); - - // Deploy - ADD_ACTIVITY_TO_SR( ACT_DEPLOY ); - ADD_ACTIVITY_TO_SR( ACT_DEPLOY_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_UNDEPLOY ); - - //=========================== - // HL1 Specific Activities - //=========================== - - // Grenades - ADD_ACTIVITY_TO_SR( ACT_GRENADE_ROLL ); - ADD_ACTIVITY_TO_SR( ACT_GRENADE_TOSS ); - - // Hand grenade - ADD_ACTIVITY_TO_SR( ACT_HANDGRENADE_THROW1 ); - ADD_ACTIVITY_TO_SR( ACT_HANDGRENADE_THROW2 ); - ADD_ACTIVITY_TO_SR( ACT_HANDGRENADE_THROW3 ); - - // Shotgun - ADD_ACTIVITY_TO_SR( ACT_SHOTGUN_IDLE_DEEP ); - ADD_ACTIVITY_TO_SR( ACT_SHOTGUN_IDLE4 ); - - // Glock - ADD_ACTIVITY_TO_SR( ACT_GLOCK_SHOOTEMPTY ); - ADD_ACTIVITY_TO_SR( ACT_GLOCK_SHOOT_RELOAD ); - - // RPG - ADD_ACTIVITY_TO_SR( ACT_RPG_DRAW_UNLOADED ); - ADD_ACTIVITY_TO_SR( ACT_RPG_HOLSTER_UNLOADED ); - ADD_ACTIVITY_TO_SR( ACT_RPG_IDLE_UNLOADED ); - ADD_ACTIVITY_TO_SR( ACT_RPG_FIDGET_UNLOADED ); - - // Crossbow - ADD_ACTIVITY_TO_SR( ACT_CROSSBOW_DRAW_UNLOADED ); - ADD_ACTIVITY_TO_SR( ACT_CROSSBOW_IDLE_UNLOADED ); - ADD_ACTIVITY_TO_SR( ACT_CROSSBOW_FIDGET_UNLOADED ); - - // Gauss - ADD_ACTIVITY_TO_SR( ACT_GAUSS_SPINUP ); - ADD_ACTIVITY_TO_SR( ACT_GAUSS_SPINCYCLE ); - - // Tripmine - ADD_ACTIVITY_TO_SR( ACT_TRIPMINE_GROUND ); - ADD_ACTIVITY_TO_SR( ACT_TRIPMINE_WORLD ); - - //=========================== - // CSPort Specific Activities - //=========================== - - ADD_ACTIVITY_TO_SR ( ACT_VM_PRIMARYATTACK_SILENCED ); // fire - ADD_ACTIVITY_TO_SR ( ACT_VM_RELOAD_SILENCED ); - ADD_ACTIVITY_TO_SR ( ACT_VM_DRYFIRE_SILENCED ); // fire with no ammo loaded. - ADD_ACTIVITY_TO_SR ( ACT_VM_IDLE_SILENCED ); - ADD_ACTIVITY_TO_SR ( ACT_VM_DRAW_SILENCED ); - - ADD_ACTIVITY_TO_SR ( ACT_VM_IDLE_EMPTY_LEFT ); - ADD_ACTIVITY_TO_SR ( ACT_VM_DRYFIRE_LEFT ); - - ADD_ACTIVITY_TO_SR ( ACT_PLAYER_IDLE_FIRE ); - ADD_ACTIVITY_TO_SR ( ACT_PLAYER_CROUCH_FIRE ); - ADD_ACTIVITY_TO_SR ( ACT_PLAYER_CROUCH_WALK_FIRE ); - ADD_ACTIVITY_TO_SR ( ACT_PLAYER_WALK_FIRE ); - ADD_ACTIVITY_TO_SR ( ACT_PLAYER_RUN_FIRE ); - ADD_ACTIVITY_TO_SR ( ACT_IDLETORUN ); - ADD_ACTIVITY_TO_SR ( ACT_RUNTOIDLE ); - - //=========================== - // DoD Specific Activities - //=========================== - ADD_ACTIVITY_TO_SR( ACT_SPRINT ); - - ADD_ACTIVITY_TO_SR( ACT_GET_DOWN_STAND ); - ADD_ACTIVITY_TO_SR( ACT_GET_UP_STAND ); - ADD_ACTIVITY_TO_SR( ACT_GET_DOWN_CROUCH ); - ADD_ACTIVITY_TO_SR( ACT_GET_UP_CROUCH ); - ADD_ACTIVITY_TO_SR( ACT_PRONE_FORWARD ); - ADD_ACTIVITY_TO_SR( ACT_PRONE_IDLE ); - - ADD_ACTIVITY_TO_SR( ACT_DEEPIDLE1 ); - ADD_ACTIVITY_TO_SR( ACT_DEEPIDLE2 ); - ADD_ACTIVITY_TO_SR( ACT_DEEPIDLE3 ); - ADD_ACTIVITY_TO_SR( ACT_DEEPIDLE4 ); - - ADD_ACTIVITY_TO_SR( ACT_VM_RELOAD_DEPLOYED ); - ADD_ACTIVITY_TO_SR( ACT_VM_RELOAD_IDLE ); - - ADD_ACTIVITY_TO_SR( ACT_VM_DRAW_DEPLOYED ); - - //Weapon is empty activities - ADD_ACTIVITY_TO_SR( ACT_VM_DRAW_EMPTY ); - ADD_ACTIVITY_TO_SR( ACT_VM_PRIMARYATTACK_EMPTY ); - ADD_ACTIVITY_TO_SR( ACT_VM_RELOAD_EMPTY ); - ADD_ACTIVITY_TO_SR( ACT_VM_IDLE_EMPTY ); - ADD_ACTIVITY_TO_SR( ACT_VM_IDLE_DEPLOYED_EMPTY ); - - ADD_ACTIVITY_TO_SR( ACT_VM_IDLE_8 ); - ADD_ACTIVITY_TO_SR( ACT_VM_IDLE_7 ); - ADD_ACTIVITY_TO_SR( ACT_VM_IDLE_6 ); - ADD_ACTIVITY_TO_SR( ACT_VM_IDLE_5 ); - ADD_ACTIVITY_TO_SR( ACT_VM_IDLE_4 ); - ADD_ACTIVITY_TO_SR( ACT_VM_IDLE_3 ); - ADD_ACTIVITY_TO_SR( ACT_VM_IDLE_2 ); - ADD_ACTIVITY_TO_SR( ACT_VM_IDLE_1 ); - - ADD_ACTIVITY_TO_SR( ACT_VM_IDLE_DEPLOYED ); - ADD_ACTIVITY_TO_SR( ACT_VM_IDLE_DEPLOYED_8 ); - ADD_ACTIVITY_TO_SR( ACT_VM_IDLE_DEPLOYED_7 ); - ADD_ACTIVITY_TO_SR( ACT_VM_IDLE_DEPLOYED_6 ); - ADD_ACTIVITY_TO_SR( ACT_VM_IDLE_DEPLOYED_5 ); - ADD_ACTIVITY_TO_SR( ACT_VM_IDLE_DEPLOYED_4 ); - ADD_ACTIVITY_TO_SR( ACT_VM_IDLE_DEPLOYED_3 ); - ADD_ACTIVITY_TO_SR( ACT_VM_IDLE_DEPLOYED_2 ); - ADD_ACTIVITY_TO_SR( ACT_VM_IDLE_DEPLOYED_1 ); - - // Animation from prone idle to standing/crouch idle. Number designates bullets left - ADD_ACTIVITY_TO_SR( ACT_VM_UNDEPLOY ); - ADD_ACTIVITY_TO_SR( ACT_VM_UNDEPLOY_8 ); - ADD_ACTIVITY_TO_SR( ACT_VM_UNDEPLOY_7 ); - ADD_ACTIVITY_TO_SR( ACT_VM_UNDEPLOY_6 ); - ADD_ACTIVITY_TO_SR( ACT_VM_UNDEPLOY_5 ); - ADD_ACTIVITY_TO_SR( ACT_VM_UNDEPLOY_4 ); - ADD_ACTIVITY_TO_SR( ACT_VM_UNDEPLOY_3 ); - ADD_ACTIVITY_TO_SR( ACT_VM_UNDEPLOY_2 ); - ADD_ACTIVITY_TO_SR( ACT_VM_UNDEPLOY_1 ); - ADD_ACTIVITY_TO_SR( ACT_VM_UNDEPLOY_EMPTY ); - - // Animation from standing/crouch idle to prone idle. Number designates bullets left - ADD_ACTIVITY_TO_SR( ACT_VM_DEPLOY ); - ADD_ACTIVITY_TO_SR( ACT_VM_DEPLOY_8 ); - ADD_ACTIVITY_TO_SR( ACT_VM_DEPLOY_7 ); - ADD_ACTIVITY_TO_SR( ACT_VM_DEPLOY_6 ); - ADD_ACTIVITY_TO_SR( ACT_VM_DEPLOY_5 ); - ADD_ACTIVITY_TO_SR( ACT_VM_DEPLOY_4 ); - ADD_ACTIVITY_TO_SR( ACT_VM_DEPLOY_3 ); - ADD_ACTIVITY_TO_SR( ACT_VM_DEPLOY_2 ); - ADD_ACTIVITY_TO_SR( ACT_VM_DEPLOY_1 ); - ADD_ACTIVITY_TO_SR( ACT_VM_DEPLOY_EMPTY ); - - // Shooting animations for standing/crouch position. Number designates bullets left at START of animation - ADD_ACTIVITY_TO_SR( ACT_VM_PRIMARYATTACK_8 ); - ADD_ACTIVITY_TO_SR( ACT_VM_PRIMARYATTACK_7 ); - ADD_ACTIVITY_TO_SR( ACT_VM_PRIMARYATTACK_6 ); - ADD_ACTIVITY_TO_SR( ACT_VM_PRIMARYATTACK_5 ); - ADD_ACTIVITY_TO_SR( ACT_VM_PRIMARYATTACK_4 ); - ADD_ACTIVITY_TO_SR( ACT_VM_PRIMARYATTACK_3 ); - ADD_ACTIVITY_TO_SR( ACT_VM_PRIMARYATTACK_2 ); - ADD_ACTIVITY_TO_SR( ACT_VM_PRIMARYATTACK_1 ); - - // Shooting animations for prone position. Number designates bullets left at START of animation - ADD_ACTIVITY_TO_SR( ACT_VM_PRIMARYATTACK_DEPLOYED ); - ADD_ACTIVITY_TO_SR( ACT_VM_PRIMARYATTACK_DEPLOYED_8 ); - ADD_ACTIVITY_TO_SR( ACT_VM_PRIMARYATTACK_DEPLOYED_7 ); - ADD_ACTIVITY_TO_SR( ACT_VM_PRIMARYATTACK_DEPLOYED_6 ); - ADD_ACTIVITY_TO_SR( ACT_VM_PRIMARYATTACK_DEPLOYED_5 ); - ADD_ACTIVITY_TO_SR( ACT_VM_PRIMARYATTACK_DEPLOYED_4 ); - ADD_ACTIVITY_TO_SR( ACT_VM_PRIMARYATTACK_DEPLOYED_3 ); - ADD_ACTIVITY_TO_SR( ACT_VM_PRIMARYATTACK_DEPLOYED_2 ); - ADD_ACTIVITY_TO_SR( ACT_VM_PRIMARYATTACK_DEPLOYED_1 ); - ADD_ACTIVITY_TO_SR( ACT_VM_PRIMARYATTACK_DEPLOYED_EMPTY ); - - // Player anim ACTs - ADD_ACTIVITY_TO_SR( ACT_DOD_DEPLOYED ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_DEPLOYED ); - ADD_ACTIVITY_TO_SR( ACT_DOD_IDLE_ZOOMED ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_ZOOMED ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_ZOOMED ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_ZOOMED ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_ZOOMED ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_FORWARD_ZOOMED ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_DEPLOYED ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PRONE_DEPLOYED ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_DEPLOYED ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PRONE_DEPLOYED ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PRONE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SECONDARYATTACK_PRONE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_CROUCH ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PRONE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_AIM ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_AIM ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_AIM ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_AIM ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_AIM ); - - // Positions - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_AIM_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_AIM_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_AIM_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_AIM_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_AIM_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_AIM_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_IDLE_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_IDLE_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_IDLE_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_IDLE_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_IDLE_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SPRINT_IDLE_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONEWALK_IDLE_PISTOL ); - - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_AIM_C96 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_AIM_C96 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_AIM_C96 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_AIM_C96 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_AIM_C96 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_AIM_C96 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_IDLE_C96 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_IDLE_C96 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_IDLE_C96 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_IDLE_C96 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_IDLE_C96 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SPRINT_IDLE_C96 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONEWALK_IDLE_C96 ); - - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_AIM_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_AIM_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_AIM_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_AIM_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_AIM_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_AIM_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_IDLE_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_IDLE_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_IDLE_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_IDLE_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_IDLE_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SPRINT_IDLE_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONEWALK_IDLE_RIFLE ); - - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_AIM_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_AIM_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_AIM_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_AIM_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_AIM_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_AIM_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_IDLE_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_IDLE_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_IDLE_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_IDLE_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_IDLE_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SPRINT_IDLE_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONEWALK_IDLE_BOLT ); - - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_AIM_TOMMY ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_AIM_TOMMY ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_AIM_TOMMY ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_AIM_TOMMY ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_AIM_TOMMY ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_AIM_TOMMY ); - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_IDLE_TOMMY ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_IDLE_TOMMY ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_IDLE_TOMMY ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_IDLE_TOMMY ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_IDLE_TOMMY ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SPRINT_IDLE_TOMMY ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONEWALK_IDLE_TOMMY ); - - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_AIM_MP40 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_AIM_MP40 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_AIM_MP40 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_AIM_MP40 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_AIM_MP40 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_AIM_MP40 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_IDLE_MP40 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_IDLE_MP40 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_IDLE_MP40 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_IDLE_MP40 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_IDLE_MP40 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SPRINT_IDLE_MP40 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONEWALK_IDLE_MP40 ); - - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_AIM_MP44 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_AIM_MP44 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_AIM_MP44 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_AIM_MP44 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_AIM_MP44 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_AIM_MP44 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_IDLE_MP44 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_IDLE_MP44 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_IDLE_MP44 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_IDLE_MP44 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_IDLE_MP44 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SPRINT_IDLE_MP44 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONEWALK_IDLE_MP44 ); - - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_AIM_GREASE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_AIM_GREASE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_AIM_GREASE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_AIM_GREASE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_AIM_GREASE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_AIM_GREASE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_IDLE_GREASE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_IDLE_GREASE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_IDLE_GREASE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_IDLE_GREASE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_IDLE_GREASE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SPRINT_IDLE_GREASE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONEWALK_IDLE_GREASE ); - - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_AIM_MG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_AIM_MG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_AIM_MG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_AIM_MG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_AIM_MG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_AIM_MG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_IDLE_MG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_IDLE_MG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_IDLE_MG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_IDLE_MG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_IDLE_MG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SPRINT_IDLE_MG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONEWALK_IDLE_MG ); - - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_AIM_30CAL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_AIM_30CAL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_AIM_30CAL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_AIM_30CAL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_AIM_30CAL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_AIM_30CAL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_IDLE_30CAL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_IDLE_30CAL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_IDLE_30CAL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_IDLE_30CAL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_IDLE_30CAL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SPRINT_IDLE_30CAL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONEWALK_IDLE_30CAL ); - - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_AIM_GREN_FRAG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_AIM_GREN_FRAG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_AIM_GREN_FRAG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_AIM_GREN_FRAG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_AIM_GREN_FRAG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_AIM_GREN_FRAG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SPRINT_AIM_GREN_FRAG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONEWALK_AIM_GREN_FRAG ); - - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_AIM_GREN_STICK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_AIM_GREN_STICK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_AIM_GREN_STICK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_AIM_GREN_STICK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_AIM_GREN_STICK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_AIM_GREN_STICK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SPRINT_AIM_GREN_STICK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONEWALK_AIM_GREN_STICK ); - - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_AIM_KNIFE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_AIM_KNIFE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_AIM_KNIFE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_AIM_KNIFE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_AIM_KNIFE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_AIM_KNIFE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SPRINT_AIM_KNIFE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONEWALK_AIM_KNIFE ); - - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_AIM_SPADE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_AIM_SPADE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_AIM_SPADE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_AIM_SPADE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_AIM_SPADE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_AIM_SPADE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SPRINT_AIM_SPADE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONEWALK_AIM_SPADE ); - - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_AIM_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_AIM_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_AIM_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_AIM_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_AIM_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_AIM_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_IDLE_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_IDLE_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_IDLE_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_IDLE_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_IDLE_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SPRINT_IDLE_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONEWALK_IDLE_BAZOOKA ); - - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_AIM_PSCHRECK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_AIM_PSCHRECK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_AIM_PSCHRECK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_AIM_PSCHRECK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_AIM_PSCHRECK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_AIM_PSCHRECK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_IDLE_PSCHRECK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_IDLE_PSCHRECK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_IDLE_PSCHRECK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_IDLE_PSCHRECK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_IDLE_PSCHRECK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SPRINT_IDLE_PSCHRECK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONEWALK_IDLE_PSCHRECK ); - - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_AIM_BAR ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_AIM_BAR ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_AIM_BAR ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_AIM_BAR ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_AIM_BAR ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_AIM_BAR ); - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_IDLE_BAR ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_IDLE_BAR ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_IDLE_BAR ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_IDLE_BAR ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_IDLE_BAR ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SPRINT_IDLE_BAR ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONEWALK_IDLE_BAR ); - - // Zoomed aims - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_ZOOM_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_ZOOM_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_ZOOM_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_ZOOM_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_ZOOM_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_ZOOM_RIFLE ); - - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_ZOOM_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_ZOOM_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_ZOOM_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_ZOOM_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_ZOOM_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_ZOOM_BOLT ); - - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_ZOOM_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_ZOOM_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_ZOOM_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_ZOOM_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_ZOOM_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_ZOOM_BAZOOKA ); - - ADD_ACTIVITY_TO_SR( ACT_DOD_STAND_ZOOM_PSCHRECK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCH_ZOOM_PSCHRECK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_CROUCHWALK_ZOOM_PSCHRECK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_WALK_ZOOM_PSCHRECK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RUN_ZOOM_PSCHRECK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_ZOOM_PSCHRECK ); - - // Deployed Aim - ADD_ACTIVITY_TO_SR( ACT_DOD_DEPLOY_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_DEPLOY_TOMMY ); - ADD_ACTIVITY_TO_SR( ACT_DOD_DEPLOY_MG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_DEPLOY_30CAL ); - - // Prone Deployed Aim - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_DEPLOY_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_DEPLOY_TOMMY ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_DEPLOY_MG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_DEPLOY_30CAL ); - - // Attacks - - // Rifle - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SECONDARYATTACK_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PRONE_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SECONDARYATTACK_PRONE_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PRONE_DEPLOYED_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_DEPLOYED_RIFLE ); - - // Bolt - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SECONDARYATTACK_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PRONE_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SECONDARYATTACK_PRONE_BOLT ); - - // Tommy - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_TOMMY ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PRONE_TOMMY ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SECONDARYATTACK_TOMMY ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SECONDARYATTACK_PRONE_TOMMY ); - - // MP40 - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_MP40 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PRONE_MP40 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SECONDARYATTACK_MP40 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SECONDARYATTACK_PRONE_MP40 ); - - // MP44 - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_MP44 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PRONE_MP44 ); - - // Greasegun - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_GREASE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PRONE_GREASE ); - - // Pistols (Colt ); Luger) - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PRONE_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_C96 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PRONE_C96 ); - - // Mgs (mg42 ); mg34) - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_MG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PRONE_MG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PRONE_DEPLOYED_MG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_DEPLOYED_MG ); - - // 30cal - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_30CAL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PRONE_30CAL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_DEPLOYED_30CAL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PRONE_DEPLOYED_30CAL ); - - // Grenades - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_GREN_FRAG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PRONE_GREN_FRAG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_GREN_STICK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PRONE_GREN_STICK ); - - // Knife - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_KNIFE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PRONE_KNIFE ); - - // Spade - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_SPADE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PRONE_SPADE ); - - // Bazooka - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PRONE_BAZOOKA ); - - // Pschreck - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PSCHRECK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PRONE_PSCHRECK ); - - // Bar - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_BAR ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_PRONE_BAR ); - - // Reloads - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_GARAND ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_K43 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_BAR ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_MP40 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_MP44 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_M1CARBINE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_TOMMY ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_GREASEGUN ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_FG42 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_RIFLEGRENADE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_C96 ); - - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_CROUCH_BAR ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_CROUCH_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_CROUCH_RIFLEGRENADE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_CROUCH_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_CROUCH_MP44 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_CROUCH_MP40 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_CROUCH_TOMMY ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_CROUCH_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_CROUCH_PSCHRECK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_CROUCH_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_CROUCH_M1CARBINE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_CROUCH_C96 ); - - // Bazookas - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_ZOOMLOAD_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PSCHRECK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_ZOOMLOAD_PSCHRECK ); - - // Deployed - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_DEPLOYED_FG42 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_DEPLOYED_30CAL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_DEPLOYED_MG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_DEPLOYED_MG34 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_DEPLOYED_BAR ); - - // Prone - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PRONE_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PRONE_GARAND ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PRONE_M1CARBINE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PRONE_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PRONE_K43 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PRONE_MP40 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PRONE_MP44 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PRONE_BAR ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PRONE_GREASEGUN ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PRONE_TOMMY ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PRONE_FG42 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PRONE_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PRONE_RIFLEGRENADE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PRONE_C96 ); - - // Prone bazooka - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PRONE_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_ZOOMLOAD_PRONE_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PRONE_PSCHRECK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_ZOOMLOAD_PRONE_PSCHRECK ); - - // Prone deployed - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PRONE_DEPLOYED_BAR ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PRONE_DEPLOYED_FG42 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PRONE_DEPLOYED_30CAL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PRONE_DEPLOYED_MG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_RELOAD_PRONE_DEPLOYED_MG34 ); - - // Prone zoomed aim - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_ZOOM_FORWARD_RIFLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_ZOOM_FORWARD_BOLT ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_ZOOM_FORWARD_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRONE_ZOOM_FORWARD_PSCHRECK ); - - // Crouch attack. - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_CROUCH ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_CROUCH_SPADE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_CROUCH_KNIFE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_CROUCH_GREN_FRAG ); - ADD_ACTIVITY_TO_SR( ACT_DOD_PRIMARYATTACK_CROUCH_GREN_STICK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SECONDARYATTACK_CROUCH ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SECONDARYATTACK_CROUCH_TOMMY ); - ADD_ACTIVITY_TO_SR( ACT_DOD_SECONDARYATTACK_CROUCH_MP40 ); - - // Hand Signals - ADD_ACTIVITY_TO_SR( ACT_DOD_HS_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_HS_CROUCH ); - ADD_ACTIVITY_TO_SR( ACT_DOD_HS_IDLE_30CAL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_HS_IDLE_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_HS_IDLE_PSCHRECK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_HS_IDLE_KNIFE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_HS_IDLE_MG42 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_HS_IDLE_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_HS_IDLE_STICKGRENADE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_HS_IDLE_TOMMY ); - ADD_ACTIVITY_TO_SR( ACT_DOD_HS_IDLE_MP44 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_HS_IDLE_K98 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_HS_CROUCH_30CAL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_HS_CROUCH_BAZOOKA ); - ADD_ACTIVITY_TO_SR( ACT_DOD_HS_CROUCH_PSCHRECK ); - ADD_ACTIVITY_TO_SR( ACT_DOD_HS_CROUCH_KNIFE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_HS_CROUCH_MG42 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_HS_CROUCH_PISTOL ); - ADD_ACTIVITY_TO_SR( ACT_DOD_HS_CROUCH_STICKGRENADE ); - ADD_ACTIVITY_TO_SR( ACT_DOD_HS_CROUCH_TOMMY ); - ADD_ACTIVITY_TO_SR( ACT_DOD_HS_CROUCH_MP44 ); - ADD_ACTIVITY_TO_SR( ACT_DOD_HS_CROUCH_K98 ); - - ADD_ACTIVITY_TO_SR ( ACT_DOD_STAND_IDLE_TNT ); - ADD_ACTIVITY_TO_SR ( ACT_DOD_CROUCH_IDLE_TNT ); - ADD_ACTIVITY_TO_SR ( ACT_DOD_CROUCHWALK_IDLE_TNT ); - ADD_ACTIVITY_TO_SR ( ACT_DOD_WALK_IDLE_TNT ); - ADD_ACTIVITY_TO_SR ( ACT_DOD_RUN_IDLE_TNT ); - ADD_ACTIVITY_TO_SR ( ACT_DOD_SPRINT_IDLE_TNT ); - ADD_ACTIVITY_TO_SR ( ACT_DOD_PRONEWALK_IDLE_TNT ); - - ADD_ACTIVITY_TO_SR ( ACT_DOD_PLANT_TNT ); - ADD_ACTIVITY_TO_SR ( ACT_DOD_DEFUSE_TNT ); - - //=========================== - // HL2MP Specific Activities - //=========================== - - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_IDLE ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_RUN ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_IDLE_CROUCH ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_WALK_CROUCH ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_GESTURE_RANGE_ATTACK ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_GESTURE_RELOAD ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_JUMP ); - - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_IDLE_PISTOL ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_RUN_PISTOL ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_IDLE_CROUCH_PISTOL ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_WALK_CROUCH_PISTOL ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_GESTURE_RANGE_ATTACK_PISTOL ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_GESTURE_RELOAD_PISTOL ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_JUMP_PISTOL ); - - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_IDLE_SMG1 ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_RUN_SMG1 ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_IDLE_CROUCH_SMG1 ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_WALK_CROUCH_SMG1 ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG1 ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_GESTURE_RELOAD_SMG1 ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_JUMP_SMG1 ); - - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_IDLE_AR2 ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_RUN_AR2 ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_IDLE_CROUCH_AR2 ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_WALK_CROUCH_AR2 ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_GESTURE_RANGE_ATTACK_AR2 ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_GESTURE_RELOAD_AR2 ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_JUMP_AR2 ); - - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_IDLE_SHOTGUN ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_RUN_SHOTGUN ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_IDLE_CROUCH_SHOTGUN ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_WALK_CROUCH_SHOTGUN ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_GESTURE_RANGE_ATTACK_SHOTGUN ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_GESTURE_RELOAD_SHOTGUN ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_JUMP_SHOTGUN ); - - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_IDLE_RPG ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_RUN_RPG ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_IDLE_CROUCH_RPG ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_WALK_CROUCH_RPG ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_GESTURE_RANGE_ATTACK_RPG ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_GESTURE_RELOAD_RPG ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_JUMP_RPG ); - - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_IDLE_GRENADE ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_RUN_GRENADE ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_IDLE_CROUCH_GRENADE ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_WALK_CROUCH_GRENADE ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_GESTURE_RANGE_ATTACK_GRENADE ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_GESTURE_RELOAD_GRENADE ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_JUMP_GRENADE ); - - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_IDLE_PHYSGUN ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_RUN_PHYSGUN ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_IDLE_CROUCH_PHYSGUN ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_WALK_CROUCH_PHYSGUN ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_GESTURE_RANGE_ATTACK_PHYSGUN ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_GESTURE_RELOAD_PHYSGUN ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_JUMP_PHYSGUN ); - - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_IDLE_CROSSBOW ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_RUN_CROSSBOW ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_IDLE_CROUCH_CROSSBOW ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_WALK_CROUCH_CROSSBOW ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_GESTURE_RANGE_ATTACK_CROSSBOW ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_GESTURE_RELOAD_CROSSBOW ); - ADD_ACTIVITY_TO_SR ( ACT_HL2MP_JUMP_CROSSBOW ); - - ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_HL2MP_RUN_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_CROUCH_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_CROUCH_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_MELEE ); - - ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_SLAM ); - ADD_ACTIVITY_TO_SR( ACT_HL2MP_RUN_SLAM ); - ADD_ACTIVITY_TO_SR( ACT_HL2MP_IDLE_CROUCH_SLAM ); - ADD_ACTIVITY_TO_SR( ACT_HL2MP_WALK_CROUCH_SLAM ); - ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RANGE_ATTACK_SLAM ); - ADD_ACTIVITY_TO_SR( ACT_HL2MP_GESTURE_RELOAD_SLAM ); - ADD_ACTIVITY_TO_SR( ACT_HL2MP_JUMP_SLAM ); - - // Portal! - ADD_ACTIVITY_TO_SR( ACT_VM_FIZZLE ); - - // Multiplayer - ADD_ACTIVITY_TO_SR( ACT_MP_STAND_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_MP_CROUCH_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_MP_CROUCH_DEPLOYED_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_MP_CROUCH_DEPLOYED ); - ADD_ACTIVITY_TO_SR( ACT_MP_DEPLOYED_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_MP_RUN ); - ADD_ACTIVITY_TO_SR( ACT_MP_WALK ); - ADD_ACTIVITY_TO_SR( ACT_MP_AIRWALK ); - ADD_ACTIVITY_TO_SR( ACT_MP_CROUCHWALK ); - ADD_ACTIVITY_TO_SR( ACT_MP_SPRINT ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP_START ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP_FLOAT ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP_LAND ); - ADD_ACTIVITY_TO_SR( ACT_MP_DOUBLEJUMP ); - ADD_ACTIVITY_TO_SR( ACT_MP_SWIM ); - ADD_ACTIVITY_TO_SR( ACT_MP_DEPLOYED ); - ADD_ACTIVITY_TO_SR( ACT_MP_SWIM_DEPLOYED ); - ADD_ACTIVITY_TO_SR( ACT_MP_VCD ); - - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_STAND_PRIMARYFIRE ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_STAND_PRIMARYFIRE_DEPLOYED ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_STAND_SECONDARYFIRE ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_STAND_GRENADE ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_CROUCH_PRIMARYFIRE ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_CROUCH_PRIMARYFIRE_DEPLOYED ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_CROUCH_SECONDARYFIRE ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_CROUCH_GRENADE ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_SWIM_PRIMARYFIRE ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_SWIM_SECONDARYFIRE ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_SWIM_GRENADE ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_AIRWALK_PRIMARYFIRE ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_AIRWALK_SECONDARYFIRE ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_AIRWALK_GRENADE ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_STAND ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_STAND_LOOP ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_STAND_END ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_CROUCH ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_CROUCH_LOOP ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_CROUCH_END ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_SWIM ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_SWIM_LOOP ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_SWIM_END ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_AIRWALK ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_AIRWALK_LOOP ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_AIRWALK_END ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_STAND_PREFIRE ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_STAND_POSTFIRE ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_STAND_STARTFIRE ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_CROUCH_PREFIRE ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_CROUCH_POSTFIRE ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_SWIM_PREFIRE ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_SWIM_POSTFIRE ); - - // Multiplayer - Primary - ADD_ACTIVITY_TO_SR( ACT_MP_STAND_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_CROUCH_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_RUN_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_WALK_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_AIRWALK_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_CROUCHWALK_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP_START_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP_FLOAT_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP_LAND_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_SWIM_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_DEPLOYED_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_SWIM_DEPLOYED_PRIMARY ); - - - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_STAND_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_STAND_PRIMARY_DEPLOYED ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_CROUCH_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_CROUCH_PRIMARY_DEPLOYED ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_SWIM_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_AIRWALK_PRIMARY ); - - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_STAND_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_STAND_PRIMARY_LOOP ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_STAND_PRIMARY_END ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_CROUCH_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_CROUCH_PRIMARY_LOOP ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_CROUCH_PRIMARY_END ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_SWIM_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_SWIM_PRIMARY_LOOP ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_SWIM_PRIMARY_END ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_AIRWALK_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_AIRWALK_PRIMARY_LOOP ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_AIRWALK_PRIMARY_END ); - - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_STAND_GRENADE_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_CROUCH_GRENADE_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_SWIM_GRENADE_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_AIRWALK_GRENADE_PRIMARY ); - - // Secondary - ADD_ACTIVITY_TO_SR( ACT_MP_STAND_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_CROUCH_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_RUN_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_WALK_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_AIRWALK_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_CROUCHWALK_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP_START_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP_FLOAT_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP_LAND_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_SWIM_SECONDARY ); - - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_STAND_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_CROUCH_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_SWIM_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_AIRWALK_SECONDARY ); - - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_STAND_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_STAND_SECONDARY_LOOP ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_STAND_SECONDARY_END ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_CROUCH_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_CROUCH_SECONDARY_LOOP ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_CROUCH_SECONDARY_END ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_SWIM_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_SWIM_SECONDARY_LOOP ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_SWIM_SECONDARY_END ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_AIRWALK_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_AIRWALK_SECONDARY_LOOP ); - ADD_ACTIVITY_TO_SR( ACT_MP_RELOAD_AIRWALK_SECONDARY_END ); - - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_STAND_GRENADE_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_CROUCH_GRENADE_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_SWIM_GRENADE_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_AIRWALK_GRENADE_SECONDARY ); - - // Melee - ADD_ACTIVITY_TO_SR( ACT_MP_STAND_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_MP_CROUCH_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_MP_RUN_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_MP_WALK_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_MP_AIRWALK_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_MP_CROUCHWALK_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP_START_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP_FLOAT_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP_LAND_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_MP_SWIM_MELEE ); - - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_STAND_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_STAND_MELEE_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_CROUCH_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_CROUCH_MELEE_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_SWIM_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_AIRWALK_MELEE ); - - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_STAND_GRENADE_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_CROUCH_GRENADE_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_SWIM_GRENADE_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_AIRWALK_GRENADE_MELEE ); - - // Flinches - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_FLINCH ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_FLINCH_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_FLINCH_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_FLINCH_MELEE ); - - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_FLINCH_HEAD ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_FLINCH_CHEST ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_FLINCH_STOMACH ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_FLINCH_LEFTARM ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_FLINCH_RIGHTARM ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_FLINCH_LEFTLEG ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_FLINCH_RIGHTLEG ); - - // Team Fortress specific - medic heal, medic infect, etc..... - ADD_ACTIVITY_TO_SR( ACT_MP_GRENADE1_DRAW ); - ADD_ACTIVITY_TO_SR( ACT_MP_GRENADE1_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_MP_GRENADE1_ATTACK ); - ADD_ACTIVITY_TO_SR( ACT_MP_GRENADE2_DRAW ); - ADD_ACTIVITY_TO_SR( ACT_MP_GRENADE2_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_MP_GRENADE2_ATTACK ); - - ADD_ACTIVITY_TO_SR( ACT_MP_PRIMARY_GRENADE1_DRAW ); - ADD_ACTIVITY_TO_SR( ACT_MP_PRIMARY_GRENADE1_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_MP_PRIMARY_GRENADE1_ATTACK ); - ADD_ACTIVITY_TO_SR( ACT_MP_PRIMARY_GRENADE2_DRAW ); - ADD_ACTIVITY_TO_SR( ACT_MP_PRIMARY_GRENADE2_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_MP_PRIMARY_GRENADE2_ATTACK ); - - ADD_ACTIVITY_TO_SR( ACT_MP_SECONDARY_GRENADE1_DRAW ); - ADD_ACTIVITY_TO_SR( ACT_MP_SECONDARY_GRENADE1_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_MP_SECONDARY_GRENADE1_ATTACK ); - ADD_ACTIVITY_TO_SR( ACT_MP_SECONDARY_GRENADE2_DRAW ); - ADD_ACTIVITY_TO_SR( ACT_MP_SECONDARY_GRENADE2_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_MP_SECONDARY_GRENADE2_ATTACK ); - - ADD_ACTIVITY_TO_SR( ACT_MP_MELEE_GRENADE1_DRAW ); - ADD_ACTIVITY_TO_SR( ACT_MP_MELEE_GRENADE1_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_MP_MELEE_GRENADE1_ATTACK ); - ADD_ACTIVITY_TO_SR( ACT_MP_MELEE_GRENADE2_DRAW ); - ADD_ACTIVITY_TO_SR( ACT_MP_MELEE_GRENADE2_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_MP_MELEE_GRENADE2_ATTACK ); - - // Building - ADD_ACTIVITY_TO_SR( ACT_MP_STAND_BUILDING ); - ADD_ACTIVITY_TO_SR( ACT_MP_CROUCH_BUILDING ); - ADD_ACTIVITY_TO_SR( ACT_MP_RUN_BUILDING ); - ADD_ACTIVITY_TO_SR( ACT_MP_WALK_BUILDING ); - ADD_ACTIVITY_TO_SR( ACT_MP_AIRWALK_BUILDING ); - ADD_ACTIVITY_TO_SR( ACT_MP_CROUCHWALK_BUILDING ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP_BUILDING ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP_START_BUILDING ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP_FLOAT_BUILDING ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP_LAND_BUILDING ); - ADD_ACTIVITY_TO_SR( ACT_MP_SWIM_BUILDING ); - - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_STAND_BUILDING ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_CROUCH_BUILDING ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_SWIM_BUILDING ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_AIRWALK_BUILDING ); - - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_STAND_GRENADE_BUILDING ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_CROUCH_GRENADE_BUILDING ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_SWIM_GRENADE_BUILDING ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_AIRWALK_GRENADE_BUILDING ); - - ADD_ACTIVITY_TO_SR( ACT_MP_STAND_PDA ); - ADD_ACTIVITY_TO_SR( ACT_MP_CROUCH_PDA ); - ADD_ACTIVITY_TO_SR( ACT_MP_RUN_PDA ); - ADD_ACTIVITY_TO_SR( ACT_MP_WALK_PDA ); - ADD_ACTIVITY_TO_SR( ACT_MP_AIRWALK_PDA ); - ADD_ACTIVITY_TO_SR( ACT_MP_CROUCHWALK_PDA ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP_PDA ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP_START_PDA ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP_FLOAT_PDA ); - ADD_ACTIVITY_TO_SR( ACT_MP_JUMP_LAND_PDA ); - ADD_ACTIVITY_TO_SR( ACT_MP_SWIM_PDA ); - - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_STAND_PDA ); - ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_SWIM_PDA ); - - - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_HANDMOUTH ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_FINGERPOINT ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_FISTPUMP ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_THUMBSUP ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_NODYES ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_NODNO ); - - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_HANDMOUTH_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_FINGERPOINT_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_FISTPUMP_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_THUMBSUP_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_NODYES_PRIMARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_NODNO_PRIMARY ); - - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_HANDMOUTH_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_FINGERPOINT_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_FISTPUMP_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_THUMBSUP_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_NODYES_SECONDARY ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_NODNO_SECONDARY ); - - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_HANDMOUTH_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_FINGERPOINT_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_FISTPUMP_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_THUMBSUP_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_NODYES_MELEE ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_NODNO_MELEE ); - - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_HANDMOUTH_BUILDING ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_FINGERPOINT_BUILDING ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_FISTPUMP_BUILDING ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_THUMBSUP_BUILDING ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_NODYES_BUILDING ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_NODNO_BUILDING ); - - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_HANDMOUTH_PDA ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_FINGERPOINT_PDA ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_FISTPUMP_PDA ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_THUMBSUP_PDA ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_NODYES_PDA ); - ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_NODNO_PDA ); - - ADD_ACTIVITY_TO_SR( ACT_VM_UNUSABLE ); - ADD_ACTIVITY_TO_SR( ACT_VM_UNUSABLE_TO_USABLE ); - ADD_ACTIVITY_TO_SR( ACT_VM_USABLE_TO_UNUSABLE ); - - ADD_ACTIVITY_TO_SR( ACT_PRIMARY_VM_DRAW ); - ADD_ACTIVITY_TO_SR( ACT_PRIMARY_VM_HOLSTER ); - ADD_ACTIVITY_TO_SR( ACT_PRIMARY_VM_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_PRIMARY_VM_PULLBACK ); - ADD_ACTIVITY_TO_SR( ACT_PRIMARY_VM_PRIMARYATTACK ); - ADD_ACTIVITY_TO_SR( ACT_PRIMARY_VM_SECONDARYATTACK ); - ADD_ACTIVITY_TO_SR( ACT_PRIMARY_VM_RELOAD ); - ADD_ACTIVITY_TO_SR( ACT_PRIMARY_VM_DRYFIRE ); - ADD_ACTIVITY_TO_SR( ACT_PRIMARY_VM_IDLE_TO_LOWERED ); - ADD_ACTIVITY_TO_SR( ACT_PRIMARY_VM_IDLE_LOWERED ); - ADD_ACTIVITY_TO_SR( ACT_PRIMARY_VM_LOWERED_TO_IDLE ); - - ADD_ACTIVITY_TO_SR( ACT_SECONDARY_VM_DRAW ); - ADD_ACTIVITY_TO_SR( ACT_SECONDARY_VM_HOLSTER ); - ADD_ACTIVITY_TO_SR( ACT_SECONDARY_VM_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_SECONDARY_VM_PULLBACK ); - ADD_ACTIVITY_TO_SR( ACT_SECONDARY_VM_PRIMARYATTACK ); - ADD_ACTIVITY_TO_SR( ACT_SECONDARY_VM_SECONDARYATTACK ); - ADD_ACTIVITY_TO_SR( ACT_SECONDARY_VM_RELOAD ); - ADD_ACTIVITY_TO_SR( ACT_SECONDARY_VM_DRYFIRE ); - ADD_ACTIVITY_TO_SR( ACT_SECONDARY_VM_IDLE_TO_LOWERED ); - ADD_ACTIVITY_TO_SR( ACT_SECONDARY_VM_IDLE_LOWERED ); - ADD_ACTIVITY_TO_SR( ACT_SECONDARY_VM_LOWERED_TO_IDLE ); - - ADD_ACTIVITY_TO_SR( ACT_MELEE_VM_DRAW ); - ADD_ACTIVITY_TO_SR( ACT_MELEE_VM_HOLSTER ); - ADD_ACTIVITY_TO_SR( ACT_MELEE_VM_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_MELEE_VM_PULLBACK ); - ADD_ACTIVITY_TO_SR( ACT_MELEE_VM_PRIMARYATTACK ); - ADD_ACTIVITY_TO_SR( ACT_MELEE_VM_SECONDARYATTACK ); - ADD_ACTIVITY_TO_SR( ACT_MELEE_VM_RELOAD ); - ADD_ACTIVITY_TO_SR( ACT_MELEE_VM_DRYFIRE ); - ADD_ACTIVITY_TO_SR( ACT_MELEE_VM_IDLE_TO_LOWERED ); - ADD_ACTIVITY_TO_SR( ACT_MELEE_VM_IDLE_LOWERED ); - ADD_ACTIVITY_TO_SR( ACT_MELEE_VM_LOWERED_TO_IDLE ); - - ADD_ACTIVITY_TO_SR( ACT_PDA_VM_DRAW ); - ADD_ACTIVITY_TO_SR( ACT_PDA_VM_HOLSTER ); - ADD_ACTIVITY_TO_SR( ACT_PDA_VM_IDLE ); - ADD_ACTIVITY_TO_SR( ACT_PDA_VM_PULLBACK ); - ADD_ACTIVITY_TO_SR( ACT_PDA_VM_PRIMARYATTACK ); - ADD_ACTIVITY_TO_SR( ACT_PDA_VM_SECONDARYATTACK ); - ADD_ACTIVITY_TO_SR( ACT_PDA_VM_RELOAD ); - ADD_ACTIVITY_TO_SR( ACT_PDA_VM_DRYFIRE ); - ADD_ACTIVITY_TO_SR( ACT_PDA_VM_IDLE_TO_LOWERED ); - ADD_ACTIVITY_TO_SR( ACT_PDA_VM_IDLE_LOWERED ); - ADD_ACTIVITY_TO_SR( ACT_PDA_VM_LOWERED_TO_IDLE ); -} diff --git a/game/server/ai_baseactor.cpp b/game/server/ai_baseactor.cpp deleted file mode 100644 index 3f33d00b9..000000000 --- a/game/server/ai_baseactor.cpp +++ /dev/null @@ -1,1936 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" - -#include "sceneentity.h" -#include "choreoevent.h" -#include "choreoscene.h" -#include "choreoactor.h" -#include "ai_baseactor.h" -#include "ai_navigator.h" -#include "saverestore_utlvector.h" -#include "bone_setup.h" -#include "physics_npc_solver.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar flex_minplayertime( "flex_minplayertime", "5" ); -ConVar flex_maxplayertime( "flex_maxplayertime", "7" ); -ConVar flex_minawaytime( "flex_minawaytime", "0.5" ); -ConVar flex_maxawaytime( "flex_maxawaytime", "1.0" ); -ConVar ai_debug_looktargets( "ai_debug_looktargets", "0" ); -ConVar ai_debug_expressions( "ai_debug_expressions", "0", FCVAR_NONE, "Show random expression decisions for NPCs." ); -static ConVar scene_showfaceto( "scene_showfaceto", "0", FCVAR_ARCHIVE, "When playing back, show the directions of faceto events." ); - - -BEGIN_DATADESC( CAI_BaseActor ) - - DEFINE_FIELD( m_fLatchedPositions, FIELD_INTEGER ), - DEFINE_FIELD( m_latchedEyeOrigin, FIELD_VECTOR ), - DEFINE_FIELD( m_latchedEyeDirection, FIELD_VECTOR ), - DEFINE_FIELD( m_latchedHeadDirection, FIELD_VECTOR ), - DEFINE_FIELD( m_goalHeadDirection, FIELD_VECTOR ), - DEFINE_FIELD( m_goalHeadInfluence, FIELD_FLOAT ), - DEFINE_FIELD( m_goalSpineYaw, FIELD_FLOAT ), - DEFINE_FIELD( m_goalBodyYaw, FIELD_FLOAT ), - DEFINE_FIELD( m_goalHeadCorrection, FIELD_VECTOR ), - DEFINE_FIELD( m_flBlinktime, FIELD_TIME ), - DEFINE_FIELD( m_hLookTarget, FIELD_EHANDLE ), - DEFINE_UTLVECTOR( m_lookQueue, FIELD_EMBEDDED ), - DEFINE_UTLVECTOR( m_randomLookQueue, FIELD_EMBEDDED ), - DEFINE_UTLVECTOR( m_syntheticLookQueue, FIELD_EMBEDDED ), - DEFINE_FIELD( m_flNextRandomLookTime, FIELD_TIME ), - DEFINE_FIELD( m_iszExpressionScene, FIELD_STRING ), - DEFINE_FIELD( m_hExpressionSceneEnt, FIELD_EHANDLE ), - DEFINE_FIELD( m_flNextRandomExpressionTime, FIELD_TIME ), - DEFINE_FIELD( m_iszIdleExpression, FIELD_STRING ), - DEFINE_FIELD( m_iszAlertExpression, FIELD_STRING ), - DEFINE_FIELD( m_iszCombatExpression, FIELD_STRING ), - DEFINE_FIELD( m_iszDeathExpression, FIELD_STRING ), - //DEFINE_FIELD( m_ParameterBodyTransY, FIELD_INTEGER ), - //DEFINE_FIELD( m_ParameterBodyTransX, FIELD_INTEGER ), - //DEFINE_FIELD( m_ParameterBodyLift, FIELD_INTEGER ), - DEFINE_FIELD( m_ParameterBodyYaw, FIELD_INTEGER ), - //DEFINE_FIELD( m_ParameterBodyPitch, FIELD_INTEGER ), - //DEFINE_FIELD( m_ParameterBodyRoll, FIELD_INTEGER ), - DEFINE_FIELD( m_ParameterSpineYaw, FIELD_INTEGER ), - //DEFINE_FIELD( m_ParameterSpinePitch, FIELD_INTEGER ), - //DEFINE_FIELD( m_ParameterSpineRoll, FIELD_INTEGER ), - DEFINE_FIELD( m_ParameterNeckTrans, FIELD_INTEGER ), - DEFINE_FIELD( m_ParameterHeadYaw, FIELD_INTEGER ), - DEFINE_FIELD( m_ParameterHeadPitch, FIELD_INTEGER ), - DEFINE_FIELD( m_ParameterHeadRoll, FIELD_INTEGER ), - //DEFINE_FIELD( m_FlexweightMoveRightLeft, FIELD_INTEGER ), - //DEFINE_FIELD( m_FlexweightMoveForwardBack, FIELD_INTEGER ), - //DEFINE_FIELD( m_FlexweightMoveUpDown, FIELD_INTEGER ), - DEFINE_FIELD( m_FlexweightBodyRightLeft, FIELD_INTEGER ), - //DEFINE_FIELD( m_FlexweightBodyUpDown, FIELD_INTEGER ), - //DEFINE_FIELD( m_FlexweightBodyTilt, FIELD_INTEGER ), - DEFINE_FIELD( m_FlexweightChestRightLeft, FIELD_INTEGER ), - //DEFINE_FIELD( m_FlexweightChestUpDown, FIELD_INTEGER ), - //DEFINE_FIELD( m_FlexweightChestTilt, FIELD_INTEGER ), - DEFINE_FIELD( m_FlexweightHeadForwardBack, FIELD_INTEGER ), - DEFINE_FIELD( m_FlexweightHeadRightLeft, FIELD_INTEGER ), - DEFINE_FIELD( m_FlexweightHeadUpDown, FIELD_INTEGER ), - DEFINE_FIELD( m_FlexweightHeadTilt, FIELD_INTEGER ), - - DEFINE_FIELD( m_ParameterGestureHeight, FIELD_INTEGER ), - DEFINE_FIELD( m_ParameterGestureWidth, FIELD_INTEGER ), - DEFINE_FIELD( m_FlexweightGestureUpDown, FIELD_INTEGER ), - DEFINE_FIELD( m_FlexweightGestureRightLeft, FIELD_INTEGER ), - DEFINE_FIELD( m_flAccumYawDelta, FIELD_FLOAT ), - DEFINE_FIELD( m_flAccumYawScale, FIELD_FLOAT ), - - DEFINE_ARRAY( m_flextarget, FIELD_FLOAT, 64 ), - - DEFINE_KEYFIELD( m_bDontUseSemaphore, FIELD_BOOLEAN, "DontUseSpeechSemaphore" ), - - DEFINE_KEYFIELD( m_iszExpressionOverride, FIELD_STRING, "ExpressionOverride" ), - - DEFINE_EMBEDDEDBYREF( m_pExpresser ), - - DEFINE_INPUTFUNC( FIELD_STRING, "SetExpressionOverride", InputSetExpressionOverride ), - -END_DATADESC() - - -BEGIN_SIMPLE_DATADESC( CAI_InterestTarget_t ) - DEFINE_FIELD( m_eType, FIELD_INTEGER ), - DEFINE_FIELD( m_hTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_vecPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_flStartTime, FIELD_TIME ), - DEFINE_FIELD( m_flEndTime, FIELD_TIME ), - DEFINE_FIELD( m_flRamp, FIELD_FLOAT ), - DEFINE_FIELD( m_flInterest, FIELD_FLOAT ), -END_DATADESC() - - - - -//----------------------------------------------------------------------------- -// Purpose: clear out latched state -//----------------------------------------------------------------------------- -void CAI_BaseActor::StudioFrameAdvance () -{ - // clear out head and eye latched values - m_fLatchedPositions &= ~(HUMANOID_LATCHED_ALL); - - BaseClass::StudioFrameAdvance(); -} - - -void CAI_BaseActor::Precache() -{ - BaseClass::Precache(); - - if ( NULL_STRING != m_iszExpressionOverride ) - { - PrecacheInstancedScene( STRING( m_iszExpressionOverride ) ); - } - - if ( m_iszIdleExpression != NULL_STRING ) - { - PrecacheInstancedScene( STRING(m_iszIdleExpression ) ); - } - - if ( m_iszCombatExpression != NULL_STRING ) - { - PrecacheInstancedScene( STRING(m_iszCombatExpression ) ); - } - - if ( m_iszAlertExpression != NULL_STRING ) - { - PrecacheInstancedScene( STRING(m_iszAlertExpression) ); - } - - if ( m_iszDeathExpression != NULL_STRING ) - { - PrecacheInstancedScene( STRING(m_iszDeathExpression) ); - } -} - -static char const *g_ServerSideFlexControllers[] = -{ - "body_rightleft", - //"body_updown", - //"body_tilt", - "chest_rightleft", - //"chest_updown", - //"chest_tilt", - "head_forwardback", - "head_rightleft", - "head_updown", - "head_tilt", - - "gesture_updown", - "gesture_rightleft" -}; - -//----------------------------------------------------------------------------- -// Purpose: Static method -// Input : *szName - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_BaseActor::IsServerSideFlexController( char const *szName ) -{ - int c = ARRAYSIZE( g_ServerSideFlexControllers ); - for ( int i = 0; i < c; ++i ) - { - if ( !Q_stricmp( szName, g_ServerSideFlexControllers[ i ] ) ) - return true; - } - return false; -} - -void CAI_BaseActor::SetModel( const char *szModelName ) -{ - BaseClass::SetModel( szModelName ); - - //Init( m_ParameterBodyTransY, "body_trans_Y" ); - //Init( m_ParameterBodyTransX, "body_trans_X" ); - //Init( m_ParameterBodyLift, "body_lift" ); - Init( m_ParameterBodyYaw, "body_yaw" ); - //Init( m_ParameterBodyPitch, "body_pitch" ); - //Init( m_ParameterBodyRoll, "body_roll" ); - Init( m_ParameterSpineYaw, "spine_yaw" ); - //Init( m_ParameterSpinePitch, "spine_pitch" ); - //Init( m_ParameterSpineRoll, "spine_roll" ); - Init( m_ParameterNeckTrans, "neck_trans" ); - Init( m_ParameterHeadYaw, "head_yaw" ); - Init( m_ParameterHeadPitch, "head_pitch" ); - Init( m_ParameterHeadRoll, "head_roll" ); - - //Init( m_FlexweightMoveRightLeft, "move_rightleft" ); - //Init( m_FlexweightMoveForwardBack, "move_forwardback" ); - //Init( m_FlexweightMoveUpDown, "move_updown" ); - Init( m_FlexweightBodyRightLeft, "body_rightleft" ); - //Init( m_FlexweightBodyUpDown, "body_updown" ); - //Init( m_FlexweightBodyTilt, "body_tilt" ); - Init( m_FlexweightChestRightLeft, "chest_rightleft" ); - //Init( m_FlexweightChestUpDown, "chest_updown" ); - //Init( m_FlexweightChestTilt, "chest_tilt" ); - Init( m_FlexweightHeadForwardBack, "head_forwardback" ); - Init( m_FlexweightHeadRightLeft, "head_rightleft" ); - Init( m_FlexweightHeadUpDown, "head_updown" ); - Init( m_FlexweightHeadTilt, "head_tilt" ); - - Init( m_ParameterGestureHeight, "gesture_height" ); - Init( m_ParameterGestureWidth, "gesture_width" ); - Init( m_FlexweightGestureUpDown, "gesture_updown" ); - Init( m_FlexweightGestureRightLeft, "gesture_rightleft" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -bool CAI_BaseActor::StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget ) -{ - Assert( info ); - Assert( info->m_pScene ); - Assert( info->m_pEvent ); - - // FIXME: this code looks duplicated - switch ( info->m_pEvent->GetType() ) - { - case CChoreoEvent::FACE: - { - return BaseClass::StartSceneEvent( info, scene, event, actor, pTarget ); - } - break; - - case CChoreoEvent::GENERIC: - { - if (stricmp( event->GetParameters(), "AI_BLINK") == 0) - { - info->m_nType = SCENE_AI_BLINK; - // blink eyes - Blink(); - // don't blink for duration, or next random blink time - float flDuration = (event->GetEndTime() - scene->GetTime()); - m_flBlinktime = gpGlobals->curtime + MAX( flDuration, random->RandomFloat( 1.5, 4.5 ) ); - } - else if (stricmp( event->GetParameters(), "AI_HOLSTER") == 0) - { - // FIXME: temp code for test - info->m_nType = SCENE_AI_HOLSTER; - info->m_iLayer = HolsterWeapon(); - return true; - } - else if (stricmp( event->GetParameters(), "AI_UNHOLSTER") == 0) - { - // FIXME: temp code for test - info->m_nType = SCENE_AI_UNHOLSTER; - info->m_iLayer = UnholsterWeapon(); - return true; - } - else if (stricmp( event->GetParameters(), "AI_AIM") == 0) - { - info->m_nType = SCENE_AI_AIM; - info->m_hTarget = pTarget; - } - else if (stricmp( event->GetParameters(), "AI_RANDOMLOOK") == 0) - { - info->m_nType = SCENE_AI_RANDOMLOOK; - info->m_flNext = 0.0; - } - else if (stricmp( event->GetParameters(), "AI_RANDOMFACEFLEX") == 0) - { - info->m_nType = SCENE_AI_RANDOMFACEFLEX; - info->m_flNext = 0.0; - info->InitWeight( this ); - } - else if (stricmp( event->GetParameters(), "AI_RANDOMHEADFLEX") == 0) - { - info->m_nType = SCENE_AI_RANDOMHEADFLEX; - info->m_flNext = 0.0; - } - else if (stricmp( event->GetParameters(), "AI_IGNORECOLLISION") == 0) - { - CBaseEntity *pTarget = FindNamedEntity( event->GetParameters2( ) ); - - if (pTarget) - { - info->m_nType = SCENE_AI_IGNORECOLLISION; - info->m_hTarget = pTarget; - float remaining = event->GetEndTime() - scene->GetTime(); - NPCPhysics_CreateSolver( this, pTarget, true, remaining ); - info->m_flNext = gpGlobals->curtime + remaining; - return true; - } - else - { - Warning( "CSceneEntity %s unable to find actor named \"%s\"\n", scene->GetFilename(), event->GetParameters2() ); - return false; - } - } - else if (stricmp( event->GetParameters(), "AI_DISABLEAI") == 0) - { - info->m_nType = SCENE_AI_DISABLEAI; - } - else - { - return BaseClass::StartSceneEvent( info, scene, event, actor, pTarget ); - } - return true; - } - break; - - default: - return BaseClass::StartSceneEvent( info, scene, event, actor, pTarget ); - } -} - - -bool CAI_BaseActor::ProcessSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ) -{ - Assert( info ); - Assert( info->m_pScene ); - Assert( info->m_pEvent ); - - // FIXME: this code looks duplicated - switch ( info->m_pEvent->GetType() ) - { - case CChoreoEvent::FACE: - { - // make sure target exists - if (info->m_hTarget == NULL) - return false; - - bool bInScene = false; - - // lockbodyfacing is designed to run on top of both normal AI and on top of - // scripted_sequences. By allowing torso turns during post-idles, pre-idles, - // act-busy's, scripted_sequences, normal AI movements, etc., it increases - // the functionality of those AI features without breaking their assuptions - // that the entity won't be made to "turn" by something outside of those - // AI's control. - // lockbody facing is also usefull when npcs are moving and you want them to turn - // towards something but still walk in the direction of travel. - if (!event->IsLockBodyFacing()) - bInScene = EnterSceneSequence( scene, event, true ); - - // make sure we're still able to play this command - if (!info->m_bStarted) - { - info->m_flInitialYaw = GetLocalAngles().y; - info->m_flTargetYaw = info->m_flInitialYaw; - info->m_flFacingYaw = info->m_flInitialYaw; - if (IsMoving()) - { - info->m_flWeight = 1.0; - } - else - { - info->m_flWeight = 0.0; - } - } - - // lock in place if aiming at self - if (info->m_hTarget == this) - { - return true; - } - - if (!bInScene || info->m_bIsMoving != IsMoving()) - { - info->m_flInitialYaw = GetLocalAngles().y; - } - info->m_bIsMoving = IsMoving(); - - // Msg("%f : %f - %f\n", scene->GetTime(), event->GetStartTime(), event->GetEndTime() ); - float flTime = clamp( scene->GetTime(), event->GetStartTime(), event->GetEndTime() - 0.1 ); - float intensity = event->GetIntensity( flTime ); - - // clamp in-ramp to 0.5 seconds - float flDuration = scene->GetTime() - event->GetStartTime(); - float flMaxIntensity = flDuration < 0.5f ? SimpleSpline( flDuration / 0.5f ) : 1.0f; - intensity = clamp( intensity, 0.0f, flMaxIntensity ); - - if (bInScene && info->m_bIsMoving) - { - info->m_flInitialYaw = GetLocalAngles().y; - } - - if (!event->IsLockBodyFacing()) - { - if (!info->m_bIsMoving && bInScene) - { - AccumulateIdealYaw( info->m_flFacingYaw, intensity ); - } - } - - float diff; - float dir; - float flSpineYaw; - float flBodyYaw; - - // move upper body to account for missing body yaw - diff = UTIL_AngleDiff( info->m_flTargetYaw, GetLocalAngles().y ); - if (diff < 0) - { - diff = -diff; - dir = -1; - } - else - { - dir = 1; - } - flSpineYaw = MIN( diff, 30 ); - flBodyYaw = MIN( diff - flSpineYaw, 30 ); - m_goalSpineYaw = m_goalSpineYaw * (1.0 - intensity) + intensity * flSpineYaw * dir; - m_goalBodyYaw = m_goalBodyYaw * (1.0 - intensity) + intensity * flBodyYaw * dir; - - /* - NDebugOverlay::YawArrow( GetAbsOrigin(), GetLocalAngles().y, 64, 16, 255, 255, 255, 0, true, 0.1 ); - NDebugOverlay::YawArrow( GetAbsOrigin() + Vector( 0, 0, 8 ), GetLocalAngles().y + m_goalBodyYaw, 64, 16, 255, 128, 128, 0, true, 0.1 ); - NDebugOverlay::YawArrow( GetAbsOrigin() + Vector( 0, 0, 16 ), GetLocalAngles().y + m_goalSpineYaw, 64, 16, 128, 255, 128, 0, true, 0.1 ); - NDebugOverlay::YawArrow( GetAbsOrigin() + Vector( 0, 0, 24 ), info->m_flTargetYaw, 64, 16, 128, 128, 255, 0, true, 0.1 ); - */ - - CAI_BaseNPC *pGoalNpc = info->m_hTarget->MyNPCPointer(); - - float goalYaw = GetLocalAngles().y; - - if ( pGoalNpc ) - { - goalYaw = CalcIdealYaw( pGoalNpc->FacingPosition() ); - } - else - { - goalYaw = CalcIdealYaw( info->m_hTarget->EyePosition() ); - } - - if (developer.GetInt() > 0 && scene_showfaceto.GetBool()) - { - NDebugOverlay::YawArrow( GetAbsOrigin() + Vector( 0, 0, 1 ), goalYaw, 8 + 32 * intensity, 8, 255, 255, 255, 0, true, 0.12 ); - } - - diff = UTIL_AngleDiff( goalYaw, info->m_flInitialYaw ) * intensity; - dir = 1.0; - - // debounce delta a bit - info->m_flTargetYaw = UTIL_AngleMod( info->m_flInitialYaw + diff ); - - if (diff < 0) - { - diff = -diff; - dir = -1; - } - - // calc how much to use the spine for turning - float spineintensity = (1.0 - MAX( 0.0, (intensity - 0.5) / 0.5 )); - // force spine to full if not in scene or locked - if (!bInScene || event->IsLockBodyFacing() ) - { - spineintensity = 1.0; - } - - flSpineYaw = MIN( diff * spineintensity, 30 ); - flBodyYaw = MIN( diff * spineintensity - flSpineYaw, 30 ); - info->m_flFacingYaw = info->m_flInitialYaw + (diff - flBodyYaw - flSpineYaw) * dir; - - if (!event->IsLockBodyFacing()) - { - AddFacingTarget( info->m_hTarget, intensity, 0.2 ); // facing targets are lagged by one frame - } - return true; - } - case CChoreoEvent::GENERIC: - { - switch(info->m_nType) - { - case SCENE_AI_BLINK: - { - // keep eyes not blinking for duration - float flDuration = (event->GetEndTime() - scene->GetTime()); - m_flBlinktime = MAX( m_flBlinktime, gpGlobals->curtime + flDuration ); - } - return true; - case SCENE_AI_HOLSTER: - { - } - return true; - case SCENE_AI_UNHOLSTER: - { - } - return true; - case SCENE_AI_AIM: - { - if ( info->m_hTarget ) - { - Vector vecAimTargetLoc = info->m_hTarget->EyePosition(); - Vector vecAimDir = vecAimTargetLoc - EyePosition(); - - VectorNormalize( vecAimDir ); - SetAim( vecAimDir); - } - } - return true; - case SCENE_AI_RANDOMLOOK: - { - if (info->m_flNext < gpGlobals->curtime) - { - info->m_flNext = gpGlobals->curtime + PickLookTarget( m_syntheticLookQueue ) - 0.4; - if (m_syntheticLookQueue.Count() > 0) - { - float flDuration = (event->GetEndTime() - scene->GetTime()); - int i = m_syntheticLookQueue.Count() - 1; - m_syntheticLookQueue[i].m_flEndTime = MIN( m_syntheticLookQueue[i].m_flEndTime, gpGlobals->curtime + flDuration ); - m_syntheticLookQueue[i].m_flInterest = 0.1; - } - } - } - return true; - case SCENE_AI_RANDOMFACEFLEX: - return RandomFaceFlex( info, scene, event ); - case SCENE_AI_RANDOMHEADFLEX: - return true; - case SCENE_AI_IGNORECOLLISION: - if (info->m_hTarget && info->m_flNext < gpGlobals->curtime) - { - float remaining = event->GetEndTime() - scene->GetTime(); - NPCPhysics_CreateSolver( this, info->m_hTarget, true, remaining ); - info->m_flNext = gpGlobals->curtime + remaining; - } - - // FIXME: needs to handle scene pause - return true; - case SCENE_AI_DISABLEAI: - if (!(GetState() == NPC_STATE_SCRIPT || IsCurSchedule( SCHED_SCENE_GENERIC )) ) - { - EnterSceneSequence( scene, event ); - } - return true; - default: - return false; - } - } - break; - default: - return BaseClass::ProcessSceneEvent( info, scene, event ); - } -} - - -bool CAI_BaseActor::RandomFaceFlex( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ) -{ - if (info->m_flNext < gpGlobals->curtime) - { - const flexsettinghdr_t *pSettinghdr = ( const flexsettinghdr_t * )FindSceneFile( event->GetParameters2() ); - if (pSettinghdr == NULL) - { - pSettinghdr = ( const flexsettinghdr_t * )FindSceneFile( "random" ); - } - if ( pSettinghdr ) - { - info->m_flNext = gpGlobals->curtime + random->RandomFloat( 0.3, 0.5 ) * (30.0 / pSettinghdr->numflexsettings); - - flexsetting_t const *pSetting = NULL; - pSetting = pSettinghdr->pSetting( random->RandomInt( 0, pSettinghdr->numflexsettings - 1 ) ); - - flexweight_t *pWeights = NULL; - int truecount = pSetting->psetting( (byte *)pSettinghdr, 0, &pWeights ); - if ( !pWeights ) - return false; - - int i; - for (i = 0; i < truecount; i++, pWeights++) - { - // Translate to local flex controller - // this is translating from the settings's local index to the models local index - int index = FlexControllerLocalToGlobal( pSettinghdr, pWeights->key ); - - // FIXME: this is supposed to blend based on pWeight->influence, but the order is wrong... - // float value = GetFlexWeight( index ) * (1 - scale * pWeights->influence) + scale * pWeights->weight; - - // Add scaled weighting in to total - m_flextarget[ index ] = pWeights->weight; - } - } - else - { - return false; - } - } - - // adjust intensity if this is a background scene and there's other flex animations playing - float intensity = info->UpdateWeight( this ) * event->GetIntensity( scene->GetTime() ); - - // slide it up. - for (LocalFlexController_t i = LocalFlexController_t(0); i < GetNumFlexControllers(); i++) - { - float weight = GetFlexWeight( i ); - - if (weight != m_flextarget[i]) - { - float delta = (m_flextarget[i] - weight) / random->RandomFloat( 2.0, 4.0 ); - weight = weight + delta * intensity; - } - weight = clamp( weight, 0.0f, 1.0f ); - SetFlexWeight( i, weight ); - } - - return true; -} - - - - - -bool CAI_BaseActor::ClearSceneEvent( CSceneEventInfo *info, bool fastKill, bool canceled ) -{ - Assert( info ); - Assert( info->m_pScene ); - Assert( info->m_pEvent ); - - // FIXME: this code looks duplicated - switch ( info->m_pEvent->GetType() ) - { - case CChoreoEvent::FACE: - { - return BaseClass::ClearSceneEvent( info, fastKill, canceled ); - } - break; - default: - return BaseClass::ClearSceneEvent( info, fastKill, canceled ); - } -} - - - -bool CAI_BaseActor::CheckSceneEventCompletion( CSceneEventInfo *info, float currenttime, CChoreoScene *scene, CChoreoEvent *event ) -{ - Assert( info ); - Assert( info->m_pScene ); - Assert( info->m_pEvent ); - - switch ( event->GetType() ) - { - case CChoreoEvent::GENERIC: - { - switch( info->m_nType) - { - case SCENE_AI_HOLSTER: - case SCENE_AI_UNHOLSTER: - { - if (info->m_iLayer == -1) - { - return true; - } - float preload = event->GetEndTime() - currenttime; - if (preload < 0) - { - return true; - } - float t = (1.0 - GetLayerCycle( info->m_iLayer )) * SequenceDuration( GetLayerSequence( info->m_iLayer ) ); - - return (t <= preload); - } - } - } - default: - break; - } - - return BaseClass::CheckSceneEventCompletion( info, currenttime, scene, event ); -} - - - -//----------------------------------------------------------------------------- -// Purpose: clear out latched state -//----------------------------------------------------------------------------- -void CAI_BaseActor::SetViewtarget( const Vector &viewtarget ) -{ - // clear out eye latch - m_fLatchedPositions &= ~HUMANOID_LATCHED_EYE; - - BaseClass::SetViewtarget( viewtarget ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns true position of the eyeballs -//----------------------------------------------------------------------------- -void CAI_BaseActor::UpdateLatchedValues( ) -{ - if (!(m_fLatchedPositions & HUMANOID_LATCHED_HEAD)) - { - // set head latch - m_fLatchedPositions |= HUMANOID_LATCHED_HEAD; - - if (!HasCondition( COND_IN_PVS ) || !GetAttachment( "eyes", m_latchedEyeOrigin, &m_latchedHeadDirection )) - { - m_latchedEyeOrigin = BaseClass::EyePosition( ); - AngleVectors( GetLocalAngles(), &m_latchedHeadDirection ); - } - // clear out eye latch - m_fLatchedPositions &= ~(HUMANOID_LATCHED_EYE); - // DevMsg( "eyeball %4f %4f %4f : %3f %3f %3f\n", origin.x, origin.y, origin.z, angles.x, angles.y, angles.z ); - } - - if (!(m_fLatchedPositions & HUMANOID_LATCHED_EYE)) - { - m_fLatchedPositions |= HUMANOID_LATCHED_EYE; - - if ( CapabilitiesGet() & bits_CAP_ANIMATEDFACE ) - { - m_latchedEyeDirection = GetViewtarget() - m_latchedEyeOrigin; - VectorNormalize( m_latchedEyeDirection ); - } - else - { - m_latchedEyeDirection = m_latchedHeadDirection; - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns true position of the eyeballs -//----------------------------------------------------------------------------- -Vector CAI_BaseActor::EyePosition( ) -{ - UpdateLatchedValues(); - - return m_latchedEyeOrigin; -} - - -#define MIN_LOOK_TARGET_DIST 1.0f -#define MAX_FULL_LOOK_TARGET_DIST 10.0f - -//----------------------------------------------------------------------------- -// Purpose: Returns true if target is in legal range of eye movement for the current head position -//----------------------------------------------------------------------------- -bool CAI_BaseActor::ValidEyeTarget(const Vector &lookTargetPos) -{ - Vector vHeadDir = HeadDirection3D( ); - Vector lookTargetDir = lookTargetPos - EyePosition(); - float flDist = VectorNormalize(lookTargetDir); - - if (flDist < MIN_LOOK_TARGET_DIST) - { - return false; - } - - // Only look if it doesn't crank my eyeballs too far - float dotPr = DotProduct(lookTargetDir, vHeadDir); - // DevMsg( "ValidEyeTarget( %4f %4f %4f ) %3f\n", lookTargetPos.x, lookTargetPos.y, lookTargetPos.z, dotPr ); - - if (dotPr > 0.259) // +- 75 degrees - // if (dotPr > 0.86) // +- 30 degrees - { - return true; - } - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns true if target is in legal range of possible head movements -//----------------------------------------------------------------------------- -bool CAI_BaseActor::ValidHeadTarget(const Vector &lookTargetPos) -{ - Vector vFacing = BodyDirection3D(); - Vector lookTargetDir = lookTargetPos - EyePosition(); - float flDist = VectorNormalize(lookTargetDir); - - if (flDist < MIN_LOOK_TARGET_DIST) - { - return false; - } - - // Only look if it doesn't crank my head too far - float dotPr = DotProduct(lookTargetDir, vFacing); - if (dotPr > 0 && fabs( lookTargetDir.z ) < 0.7) // +- 90 degrees side to side, +- 45 up/down - { - return true; - } - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns how much to try to look at the target -//----------------------------------------------------------------------------- -float CAI_BaseActor::HeadTargetValidity(const Vector &lookTargetPos) -{ - Vector vFacing = BodyDirection3D(); - - int iForward = LookupAttachment( "forward" ); - if (iForward) - { - Vector tmp1; - GetAttachment( iForward, tmp1, &vFacing, NULL, NULL ); - } - - Vector lookTargetDir = lookTargetPos - EyePosition(); - float flDist = lookTargetDir.Length2D(); - VectorNormalize(lookTargetDir); - - if (flDist <= MIN_LOOK_TARGET_DIST) - { - return 0; - } - - // Only look if it doesn't crank my head too far - float dotPr = DotProduct(lookTargetDir, vFacing); - // only look if target is within +-135 degrees - // scale 1..-0.707 == 1..1, -.707..-1 == 1..0 - // X * b + b = 1 == 1 / (X + 1) = b, 3.4142 - float flInterest = clamp( 3.4142 + 3.4142 * dotPr, 0, 1 ); - - // stop looking when point too close - if (flDist < MAX_FULL_LOOK_TARGET_DIST) - { - flInterest = flInterest * (flDist - MIN_LOOK_TARGET_DIST ) / (MAX_FULL_LOOK_TARGET_DIST - MIN_LOOK_TARGET_DIST); - } - - return flInterest; -} - -//----------------------------------------------------------------------------- -// Purpose: Integrate head turn over time -//----------------------------------------------------------------------------- -void CAI_BaseActor::SetHeadDirection( const Vector &vTargetPos, float flInterval) -{ - Assert(0); // Actors shouldn't be calling this, it doesn't do anything -} - -float CAI_BaseActor::ClampWithBias( PoseParameter_t index, float value, float base ) -{ - return EdgeLimitPoseParameter( (int)index, value, base ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Accumulate all the wanted yaw changes -//----------------------------------------------------------------------------- - -void CAI_BaseActor::AccumulateIdealYaw( float flYaw, float flIntensity ) -{ - float diff = AngleDiff( flYaw, GetLocalAngles().y ); - m_flAccumYawDelta += diff * flIntensity; - m_flAccumYawScale += flIntensity; -} - - -//----------------------------------------------------------------------------- -// Purpose: do any pending yaw movements -//----------------------------------------------------------------------------- - -bool CAI_BaseActor::SetAccumulatedYawAndUpdate( void ) -{ - if (m_flAccumYawScale > 0.0) - { - float diff = m_flAccumYawDelta / m_flAccumYawScale; - float facing = GetLocalAngles().y + diff; - - m_flAccumYawDelta = 0.0; - m_flAccumYawScale = 0.0; - - if (IsCurSchedule( SCHED_SCENE_GENERIC )) - { - if (!IsMoving()) - { - GetMotor()->SetIdealYawAndUpdate( facing ); - return true; - } - } - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: match actors "forward" attachment to point in direction of vHeadTarget -//----------------------------------------------------------------------------- - -void CAI_BaseActor::UpdateBodyControl( ) -{ - // FIXME: only during idle, or in response to accel/decel - //Set( m_ParameterBodyTransY, Get( m_FlexweightMoveRightLeft ) ); - //Set( m_ParameterBodyTransX, Get( m_FlexweightMoveForwardBack ) ); - //Set( m_ParameterBodyLift, Get( m_FlexweightMoveUpDown ) ); - Set( m_ParameterBodyYaw, Get( m_FlexweightBodyRightLeft ) + m_goalBodyYaw ); - //Set( m_ParameterBodyPitch, Get( m_FlexweightBodyUpDown ) ); - //Set( m_ParameterBodyRoll, Get( m_FlexweightBodyTilt ) ); - Set( m_ParameterSpineYaw, Get( m_FlexweightChestRightLeft ) + m_goalSpineYaw ); - //Set( m_ParameterSpinePitch, Get( m_FlexweightChestUpDown ) ); - //Set( m_ParameterSpineRoll, Get( m_FlexweightChestTilt ) ); - Set( m_ParameterNeckTrans, Get( m_FlexweightHeadForwardBack ) ); -} - - -static ConVar scene_clamplookat( "scene_clamplookat", "1", FCVAR_NONE, "Clamp head turns to a max of 20 degrees per think." ); - - -void CAI_BaseActor::UpdateHeadControl( const Vector &vHeadTarget, float flHeadInfluence ) -{ - float flTarget; - float flLimit; - - if (!(CapabilitiesGet() & bits_CAP_TURN_HEAD)) - { - return; - } - - // calc current animation head bias, movement needs to clamp accumulated with this - QAngle angBias; - QAngle vTargetAngles; - - int iEyes = LookupAttachment( "eyes" ); - int iChest = LookupAttachment( "chest" ); - int iForward = LookupAttachment( "forward" ); - - matrix3x4_t eyesToWorld; - matrix3x4_t forwardToWorld, worldToForward; - - if (iEyes <= 0 || iForward <= 0) - { - // Head control on model without "eyes" or "forward" attachment - // Most likely this is a cheaple or a generic_actor set to a model that doesn't support head/eye turning. - // DevWarning( "%s using model \"%s\" that doesn't support head turning\n", GetClassname(), STRING( GetModelName() ) ); - CapabilitiesRemove( bits_CAP_TURN_HEAD ); - return; - } - - GetAttachment( iEyes, eyesToWorld ); - - GetAttachment( iForward, forwardToWorld ); - MatrixInvert( forwardToWorld, worldToForward ); - - // Lookup chest attachment to do compounded range limit checks - if (iChest > 0) - { - matrix3x4_t chestToWorld, worldToChest; - GetAttachment( iChest, chestToWorld ); - MatrixInvert( chestToWorld, worldToChest ); - matrix3x4_t tmpM; - ConcatTransforms( worldToChest, eyesToWorld, tmpM ); - MatrixAngles( tmpM, angBias ); - - angBias.y -= Get( m_ParameterHeadYaw ); - angBias.x -= Get( m_ParameterHeadPitch ); - angBias.z -= Get( m_ParameterHeadRoll ); - - /* - if ( (m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) ) - { - // Msg("bias %f %f %f\n", angBias.x, angBias.y, angBias.z ); - - Vector tmp1, tmp2; - - VectorTransform( Vector( 0, 0, 0), chestToWorld, tmp1 ); - VectorTransform( Vector( 100, 0, 0), chestToWorld, tmp2 ); - NDebugOverlay::Line( tmp1, tmp2, 0,0,255, false, 0.12 ); - - VectorTransform( Vector( 0, 0, 0), eyesToWorld, tmp1 ); - VectorTransform( Vector( 100, 0, 0), eyesToWorld, tmp2 ); - NDebugOverlay::Line( tmp1, tmp2, 0,0,255, false, 0.12 ); - - // NDebugOverlay::Line( EyePosition(), pEntity->EyePosition(), 0,0,255, false, 0.5); - } - */ - } - else - { - angBias.Init( 0, 0, 0 ); - } - - matrix3x4_t targetXform; - targetXform = forwardToWorld; - Vector vTargetDir = vHeadTarget - EyePosition(); - - if (scene_clamplookat.GetBool()) - { - // scale down pitch when the target is behind the head - Vector vTargetLocal; - VectorNormalize( vTargetDir ); - VectorIRotate( vTargetDir, forwardToWorld, vTargetLocal ); - vTargetLocal.z *= clamp( vTargetLocal.x, 0.1, 1.0 ); - VectorNormalize( vTargetLocal ); - VectorRotate( vTargetLocal, forwardToWorld, vTargetDir ); - - // clamp local influence when target is behind the head - flHeadInfluence = flHeadInfluence * clamp( vTargetLocal.x * 2.0 + 2.0, 0.0, 1.0 ); - } - - Studio_AlignIKMatrix( targetXform, vTargetDir ); - - matrix3x4_t headXform; - ConcatTransforms( worldToForward, targetXform, headXform ); - MatrixAngles( headXform, vTargetAngles ); - - // partially debounce head goal - float s0 = 1.0 - flHeadInfluence + GetHeadDebounce() * flHeadInfluence; - float s1 = (1.0 - s0); - // limit velocity of head turns - m_goalHeadCorrection.x = UTIL_Approach( m_goalHeadCorrection.x * s0 + vTargetAngles.x * s1, m_goalHeadCorrection.x, 10.0 ); - m_goalHeadCorrection.y = UTIL_Approach( m_goalHeadCorrection.y * s0 + vTargetAngles.y * s1, m_goalHeadCorrection.y, 30.0 ); - m_goalHeadCorrection.z = UTIL_Approach( m_goalHeadCorrection.z * s0 + vTargetAngles.z * s1, m_goalHeadCorrection.z, 10.0 ); - - /* - if ( (m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) ) - { - // Msg( "yaw %.1f (%f) pitch %.1f (%.1f)\n", m_goalHeadCorrection.y, vTargetAngles.y, vTargetAngles.x, m_goalHeadCorrection.x ); - // Msg( "yaw %.2f (goal %.2f) (influence %.2f) (flex %.2f)\n", flLimit, m_goalHeadCorrection.y, flHeadInfluence, Get( m_FlexweightHeadRightLeft ) ); - } - */ - - flTarget = m_goalHeadCorrection.y + Get( m_FlexweightHeadRightLeft ); - flLimit = ClampWithBias( m_ParameterHeadYaw, flTarget, angBias.y ); - /* - if ( (m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) ) - { - Msg( "yaw %5.1f : (%5.1f : %5.1f) %5.1f (%5.1f)\n", flLimit, m_goalHeadCorrection.y, Get( m_FlexweightHeadRightLeft ), angBias.y, Get( m_ParameterHeadYaw ) ); - } - */ - Set( m_ParameterHeadYaw, flLimit ); - - flTarget = m_goalHeadCorrection.x + Get( m_FlexweightHeadUpDown ); - flLimit = ClampWithBias( m_ParameterHeadPitch, flTarget, angBias.x ); - /* - if ( (m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) ) - { - Msg( "pitch %5.1f : (%5.1f : %5.1f) %5.1f (%5.1f)\n", flLimit, m_goalHeadCorrection.x, Get( m_FlexweightHeadUpDown ), angBias.x, Get( m_ParameterHeadPitch ) ); - } - */ - Set( m_ParameterHeadPitch, flLimit ); - - flTarget = m_goalHeadCorrection.z + Get( m_FlexweightHeadTilt ); - flLimit = ClampWithBias( m_ParameterHeadRoll, flTarget, angBias.z ); - /* - if ( (m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) ) - { - Msg( "roll %5.1f : (%5.1f : %5.1f) %5.1f (%5.1f)\n", flLimit, m_goalHeadCorrection.z, Get( m_FlexweightHeadTilt ), angBias.z, Get( m_ParameterHeadRoll ) ); - } - */ - Set( m_ParameterHeadRoll, flLimit ); -} - - - -//------------------------------------------------------------------------------ -// Purpose : Calculate the NPC's eye direction in 2D world space -// Input : -// Output : -//------------------------------------------------------------------------------ -Vector CAI_BaseActor::EyeDirection2D( void ) -{ - Vector vEyeDirection = EyeDirection3D( ); - vEyeDirection.z = 0; - - vEyeDirection.AsVector2D().NormalizeInPlace(); - - return vEyeDirection; -} - -//------------------------------------------------------------------------------ -// Purpose : Calculate the NPC's eye direction in 2D world space -// Input : -// Output : -//------------------------------------------------------------------------------ -Vector CAI_BaseActor::EyeDirection3D( void ) -{ - UpdateLatchedValues( ); - - return m_latchedEyeDirection; -} - -//------------------------------------------------------------------------------ -// Purpose : Calculate the NPC's head direction in 2D world space -// Input : -// Output : -//------------------------------------------------------------------------------ -Vector CAI_BaseActor::HeadDirection2D( void ) -{ - Vector vHeadDirection = HeadDirection3D(); - vHeadDirection.z = 0; - vHeadDirection.AsVector2D().NormalizeInPlace(); - return vHeadDirection; -} - -//------------------------------------------------------------------------------ -// Purpose : Calculate the NPC's head direction in 3D world space -// Input : -// Output : -//------------------------------------------------------------------------------ -Vector CAI_BaseActor::HeadDirection3D( ) -{ - UpdateLatchedValues( ); - - return m_latchedHeadDirection; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_BaseActor::HasActiveLookTargets( void ) -{ - return m_lookQueue.Count() != 0; -} - -//----------------------------------------------------------------------------- -// Purpose: Clear any active look targets for the specified entity -//----------------------------------------------------------------------------- -void CAI_BaseActor::ClearLookTarget( CBaseEntity *pTarget ) -{ - int iIndex = m_lookQueue.Find( pTarget ); - if ( iIndex != m_lookQueue.InvalidIndex() ) - { - m_lookQueue.Remove(iIndex); - } - - iIndex = m_randomLookQueue.Find( pTarget ); - if ( iIndex != m_randomLookQueue.InvalidIndex() ) - { - m_randomLookQueue.Remove(iIndex); - - // Figure out the new random look time - m_flNextRandomLookTime = gpGlobals->curtime + 1.0; - for (int i = 0; i < m_randomLookQueue.Count(); i++) - { - if ( m_randomLookQueue[i].m_flEndTime > m_flNextRandomLookTime ) - { - m_flNextRandomLookTime = m_randomLookQueue[i].m_flEndTime + 0.4; - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Look at other NPCs and clients from time to time -//----------------------------------------------------------------------------- -float CAI_BaseActor::PickLookTarget( bool bExcludePlayers, float minTime, float maxTime ) -{ - return PickLookTarget( m_randomLookQueue, bExcludePlayers, minTime, maxTime ); -} - -float CAI_BaseActor::PickLookTarget( CAI_InterestTarget &queue, bool bExcludePlayers, float minTime, float maxTime ) -{ - AILookTargetArgs_t args; - - args.vTarget = vec3_invalid; - args.flDuration = random->RandomFloat( minTime, maxTime ); - args.flInfluence = random->RandomFloat( 0.3, 0.5 ); - args.flRamp = random->RandomFloat( 0.2, 0.4 ); - args.bExcludePlayers = bExcludePlayers; - args.pQueue = &queue; - - bool foundLookTarget = true; - - if ( !PickTacticalLookTarget( &args ) ) - { - if ( !PickRandomLookTarget( &args ) ) - { - foundLookTarget = false; - } - } - - if ( !foundLookTarget ) - { - // DevMsg("nothing to see\n" ); - MakeRandomLookTarget( &args, minTime, maxTime ); - } - - // See if derived NPCs want to do anything with this look target before I use it - OnSelectedLookTarget( &args ); - - if ( args.hTarget != NULL ) - { - Assert( args.vTarget == vec3_invalid ); - queue.Add( args.hTarget, args.flInfluence, args.flDuration, args.flRamp ); - } - else - { - Assert( args.vTarget != vec3_invalid ); - queue.Add( args.vTarget, args.flInfluence, args.flDuration, args.flRamp ); - } - - return args.flDuration; - -} - -bool CAI_BaseActor::PickTacticalLookTarget( AILookTargetArgs_t *pArgs ) -{ - CBaseEntity *pEnemy = GetEnemy(); - - if (pEnemy != NULL) - { - if ( ( FVisible( pEnemy ) || random->RandomInt(0, 3) == 0 ) && ValidHeadTarget(pEnemy->EyePosition())) - { - // look at enemy closer - pArgs->hTarget = pEnemy; - pArgs->flInfluence = random->RandomFloat( 0.7, 1.0 ); - pArgs->flRamp = 0; - return true; - } - else - { - // look at something else for a shorter time - pArgs->flDuration = random->RandomFloat( 0.5, 0.8 ); - // move head faster - pArgs->flRamp = 0.2; - } - } - return false; -} - -bool CAI_BaseActor::PickRandomLookTarget( AILookTargetArgs_t *pArgs ) -{ - bool bIsNavigating = ( GetNavigator()->IsGoalActive() && GetNavigator()->IsGoalSet() ); - - if ( bIsNavigating && random->RandomInt(1, 10) <= 3 ) - { - Vector navLookPoint; - Vector delta; - if ( GetNavigator()->GetPointAlongPath( &navLookPoint, 12 * 12 ) && (delta = navLookPoint - GetAbsOrigin()).Length() > 8.0 * 12.0 ) - { - if ( random->RandomInt(1, 10) <= 5 ) - { - pArgs->vTarget = navLookPoint; - pArgs->flDuration = random->RandomFloat( 0.2, 0.4 ); - } - else - { - pArgs->hTarget = this; - pArgs->flDuration = random->RandomFloat( 1.0, 2.0 ); - } - pArgs->flRamp = 0.2; - return true; - } - } - - if ( GetState() == NPC_STATE_COMBAT && random->RandomInt(1, 10) <= 8 ) - { - // if in combat, look forward 80% of the time? - pArgs->hTarget = this; - return true; - } - - CBaseEntity *pBestEntity = NULL; - CBaseEntity *pEntity = NULL; - int iHighestImportance = 0; - int iConsidered = 0; - for ( CEntitySphereQuery sphere( GetAbsOrigin(), 30 * 12, 0 ); (pEntity = sphere.GetCurrentEntity()) != NULL; sphere.NextEntity() ) - { - if (pEntity == this) - { - continue; - } - - if ( pArgs->bExcludePlayers && pEntity->GetFlags() & FL_CLIENT ) - { - // Don't look at any players. - continue; - } - - if (!pEntity->IsViewable()) - { - // Don't look at things without a model, or aren't tagged as interesting - continue; - } - - if ( pEntity->GetOwnerEntity() && !pEntity->GetOwnerEntity()->IsViewable() ) - { - // Don't look at things that are associated with non-viewable owners. - // Specifically, this prevents NPC's looking at beams or sprites that - // are part of a viewmodel. (sjb) - continue; - } - - // Don't look at any object that is ultimately parented to the player. - // These objects will almost always be at the player's origin (feet), and it - // looks bad when an actor looks at the player's feet. (sjb) - CBaseEntity *pParent = pEntity->GetParent(); - bool bObjectParentedToPlayer = false; - while( pParent ) - { - if( pParent->IsPlayer() ) - { - bObjectParentedToPlayer = true; - break; - } - - pParent = pParent->GetParent(); - } - - if( bObjectParentedToPlayer ) - continue; - - // skip entities we're already looking at - if ( pArgs->pQueue->Find( pEntity ) != pArgs->pQueue->InvalidIndex() ) - continue; - - // keep track of number of interesting things - iConsidered++; - - if ((pEntity->GetFlags() & FL_CLIENT) && (pEntity->IsMoving() || random->RandomInt( 0, 2) == 0)) - { - if (FVisible( pEntity ) && ValidHeadTarget(pEntity->EyePosition())) - { - pArgs->flDuration = random->RandomFloat( 1.0, 4.0 ); - pBestEntity = pEntity; - break; - } - } - - Vector delta = (pEntity->EyePosition() - EyePosition()); - VectorNormalize( delta ); - - int iImportance; -#if 0 - // consider things in front to be more important than things to the sides - iImportance = (DotProduct( delta, HeadDirection3D() ); -#else - // No, for now, give all targets random priority (as long as they're in front) - iImportance = random->RandomInt( 1, 100 ); - -#endif - // make other npcs, and moving npc's far more important - if (pEntity->MyNPCPointer()) - { - iImportance *= 10; - if (pEntity->IsMoving()) - { - iImportance *= 10; - } - } - - if ( iImportance > iHighestImportance ) - { - if (FVisible( pEntity ) && ValidHeadTarget(pEntity->EyePosition())) - { - iHighestImportance = iImportance; - pBestEntity = pEntity; - // NDebugOverlay::Line( EyePosition(), pEntity->EyePosition(), 0,0,255, false, 0.5); - } - } - } - - // if there were too few things to look at, don't trust the item - if (iConsidered < random->RandomInt( 0, 5)) - { - pBestEntity = NULL; - } - - if (pBestEntity) - { - //Msg("looking at %s\n", pBestEntity->GetClassname() ); - //NDebugOverlay::Line( EyePosition(), pBestEntity->WorldSpaceCenter(), 255, 0, 0, false, 5 ); - pArgs->hTarget = pBestEntity; - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// All attempts to find a target have failed, so just make something up. -//----------------------------------------------------------------------------- -void CAI_BaseActor::MakeRandomLookTarget( AILookTargetArgs_t *pArgs, float minTime, float maxTime ) -{ - Vector forward, right, up; - GetVectors( &forward, &right, &up ); - - // DevMsg("random view\n"); - - // For now, just look farther afield while driving in the vehicle. Without this we look around wildly! -#ifdef HL2_EPISODIC - if ( MyCombatCharacterPointer() && MyCombatCharacterPointer()->IsInAVehicle() ) - { - pArgs->vTarget = EyePosition() + forward * 2048 + right * random->RandomFloat(-650,650) + up * random->RandomFloat(-32,32); - } - else -#endif // HL2_EPISODIC - { - pArgs->vTarget = EyePosition() + forward * 128 + right * random->RandomFloat(-32,32) + up * random->RandomFloat(-16,16); - } - - pArgs->flDuration = random->RandomFloat( minTime, maxTime ); - pArgs->flInfluence = 0.01; - pArgs->flRamp = random->RandomFloat( 0.8, 2.8 ); -} - -//----------------------------------------------------------------------------- -// Purpose: Make sure we're looking at what we're shooting at -//----------------------------------------------------------------------------- - -void CAI_BaseActor::StartTaskRangeAttack1( const Task_t *pTask ) -{ - BaseClass::StartTaskRangeAttack1( pTask ); - if (GetEnemy()) - { - AddLookTarget( GetEnemy(), 1.0, 0.5, 0.2 ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Set direction that the NPC is looking -//----------------------------------------------------------------------------- -void CAI_BaseActor::AddLookTarget( CBaseEntity *pTarget, float flImportance, float flDuration, float flRamp ) -{ - m_lookQueue.Add( pTarget, flImportance, flDuration, flRamp ); -} - - -void CAI_BaseActor::AddLookTarget( const Vector &vecPosition, float flImportance, float flDuration, float flRamp ) -{ - m_lookQueue.Add( vecPosition, flImportance, flDuration, flRamp ); -} - -//----------------------------------------------------------------------------- -// Purpose: Maintain eye, head, body postures, etc. -//----------------------------------------------------------------------------- -void CAI_BaseActor::MaintainLookTargets( float flInterval ) -{ - int i; - - if ( m_iszExpressionScene != NULL_STRING && m_hExpressionSceneEnt == NULL ) - { - InstancedScriptedScene( this, STRING(m_iszExpressionScene), &m_hExpressionSceneEnt, 0.0, true ); - } - - // decay body/spine yaw - m_goalSpineYaw = m_goalSpineYaw * 0.8; - m_goalBodyYaw = m_goalBodyYaw * 0.8; - m_goalHeadCorrection = m_goalHeadCorrection * 0.8; - - // ARRGGHHH, this needs to be moved!!!! - SetAccumulatedYawAndUpdate( ); - ProcessSceneEvents( ); - MaintainTurnActivity( ); - DoBodyLean( ); - UpdateBodyControl( ); - InvalidateBoneCache(); - - // cached versions of the current eye position - Vector vEyePosition = EyePosition( ); - - // FIXME: make this client side and automatic - // set gesture positions - Set( m_ParameterGestureHeight, Get( m_FlexweightGestureUpDown ) ); - Set( m_ParameterGestureWidth, Get( m_FlexweightGestureRightLeft ) ); - - // initialize goal head direction to be current direction - this frames animation layering/pose parameters - - // but with the head controlls removed. - Vector vHead = HeadDirection3D( ); - float flHeadInfluence = 0.0; - - // NDebugOverlay::Line( vEyePosition, vEyePosition + vHead * 16, 0,0,255, false, 0.1); - - // clean up look targets - m_lookQueue.Cleanup(); - - // clean up random look targets - m_randomLookQueue.Cleanup(); - - // clean up synthetic look targets - m_syntheticLookQueue.Cleanup(); - - // if there's real things to look at, turn off the random targets - if (m_lookQueue.Count() != 0 || m_syntheticLookQueue.Count() != 0) - { - for (i = 0; i < m_randomLookQueue.Count(); i++) - { - if (gpGlobals->curtime < m_randomLookQueue[i].m_flEndTime - m_randomLookQueue[i].m_flRamp - 0.2) - { - m_randomLookQueue[i].m_flEndTime = gpGlobals->curtime + m_randomLookQueue[i].m_flRamp + 0.2; - } - } - m_flNextRandomLookTime = gpGlobals->curtime + 1.0; - } - else if (gpGlobals->curtime >= m_flNextRandomLookTime && GetState() != NPC_STATE_SCRIPT) - { - // Look at whatever! - m_flNextRandomLookTime = gpGlobals->curtime + PickLookTarget( m_randomLookQueue ) - 0.4; - } - - // don't bother with any of the rest if the player can't see you - if (!HasCondition( COND_IN_PVS )) - { - return; - } - - // Time to finish the current random expression? Or time to pick a new one? - if ( m_flNextRandomExpressionTime && gpGlobals->curtime > m_flNextRandomExpressionTime ) - { - // Random expressions need to be cleared, because they don't loop. So if we - // pick the same one again, we want to restart it. - ClearExpression(); - - PlayExpressionForState( GetState() ); - } - - CUtlVector active; - // clean up random look targets - for (i = 0; i < m_randomLookQueue.Count(); i++) - { - active.AddToTail( &m_randomLookQueue[i] ); - } - for (i = 0; i < m_lookQueue.Count(); i++) - { - active.AddToTail( &m_lookQueue[i] ); - } - for (i = 0; i < m_syntheticLookQueue.Count(); i++) - { - active.AddToTail( &m_syntheticLookQueue[i] ); - } - - // figure out ideal head yaw - bool bValidHeadTarget = false; - bool bExpectedHeadTarget = false; - for (i = 0; i < active.Count();i++) - { - Vector dir; - float flDist = 100.0f; - - bExpectedHeadTarget = true; - float flInterest = active[i]->Interest( ); - - if (active[i]->IsThis( this )) - { - int iForward = LookupAttachment( "forward" ); - if (iForward) - { - Vector tmp1; - GetAttachment( iForward, tmp1, &dir, NULL, NULL ); - } - else - { - dir = HeadDirection3D(); - } - } - else - { - dir = active[i]->GetPosition() - vEyePosition; - flDist = VectorNormalize( dir ); - flInterest = flInterest * HeadTargetValidity( active[i]->GetPosition() ); - } - - /* - if ( (m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) ) - { - DevMsg( "head (%d) %.2f : %s : %.1f %.1f %.1f\n", i, flInterest, active[i]->m_hTarget->GetClassname(), active[i]->GetPosition().x, active[i]->GetPosition().y, active[i]->GetPosition().z ); - } - */ - - if (flInterest > 0.0) - { - if (flHeadInfluence == 0.0) - { - vHead = dir; - flHeadInfluence = flInterest; - } - else - { - flHeadInfluence = flHeadInfluence * (1 - flInterest) + flInterest; - float w = flInterest / flHeadInfluence; - vHead = vHead * (1 - w) + dir * w; - } - - bValidHeadTarget = true; - - // NDebugOverlay::Line( vEyePosition, vEyePosition + dir * 64, 0,255,0, false, 0.1); - } - else - { - // NDebugOverlay::Line( vEyePosition, active[i]->GetPosition(), 255,0,0, false, 0.1); - } - } - - Assert( flHeadInfluence <= 1.0 ); - - // turn head toward target - if (bValidHeadTarget) - { - UpdateHeadControl( vEyePosition + vHead * 100, flHeadInfluence ); - m_goalHeadDirection = vHead; - m_goalHeadInfluence = flHeadInfluence; - } - else - { - // no target, decay all head control direction - m_goalHeadDirection = m_goalHeadDirection * 0.8 + vHead * 0.2; - - m_goalHeadInfluence = MAX( m_goalHeadInfluence - 0.2, 0 ); - - VectorNormalize( m_goalHeadDirection ); - UpdateHeadControl( vEyePosition + m_goalHeadDirection * 100, m_goalHeadInfluence ); - // NDebugOverlay::Line( vEyePosition, vEyePosition + m_goalHeadDirection * 100, 255,0,0, false, 0.1); - } - - // DevMsg( "%.1f %.1f ", GetPoseParameter( "head_pitch" ), GetPoseParameter( "head_roll" ) ); - - // figure out eye target - // eyes need to look directly at a target, even if the head doesn't quite aim there yet. - bool bFoundTarget = false; - EHANDLE hTarget = NULL; - - for (i = active.Count() - 1; i >= 0; i--) - { - if (active[i]->IsThis( this )) - { - // DevMsg( "eyes (%d) %s\n", i, STRING( active[i]->m_hTarget->GetEntityName().ToCStr() ) ); - bFoundTarget = true; - hTarget = this; - SetViewtarget( vEyePosition + HeadDirection3D() * 100 ); - // NDebugOverlay::Line( vEyePosition, vEyePosition + HeadDirection3D() * 100, 255,0,0, false, 0.1); - break; - } - else - { - // E3 Hack - if (ValidEyeTarget(active[i]->GetPosition())) - { - // DevMsg( "eyes (%d) %s\n", i, STRING( pTarget->GetEntityName().ToCStr() ) ); - - bFoundTarget = true; - hTarget = active[i]->m_hTarget; - SetViewtarget( active[i]->GetPosition() ); - break; - } - } - } - - // FIXME: add blink when changing targets - if (m_hLookTarget != hTarget) - { - m_flBlinktime -= 0.5; - m_hLookTarget = hTarget; - - if ( (m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) && ai_debug_looktargets.GetInt() == 2 && m_hLookTarget.Get() ) - { - if ( m_hLookTarget != this ) - { - Vector vecEyePos = m_hLookTarget->EyePosition(); - NDebugOverlay::Box( vecEyePos, -Vector(5,5,5), Vector(5,5,5), 0, 255, 0, 255, 20 ); - NDebugOverlay::Line( EyePosition(), vecEyePos, 0,255,0, true, 20 ); - NDebugOverlay::Text( vecEyePos, UTIL_VarArgs( "%s (%s)", m_hLookTarget->GetClassname(), m_hLookTarget->GetDebugName() ), false, 20 ); - } - } - - OnNewLookTarget(); - } - - // this should take into acount where it will try to be.... - if (!bFoundTarget && !ValidEyeTarget( GetViewtarget() )) - { - Vector right, up; - VectorVectors( HeadDirection3D(), right, up ); - // DevMsg("random view\n"); - SetViewtarget( EyePosition() + HeadDirection3D() * 128 + right * random->RandomFloat(-32,32) + up * random->RandomFloat(-16,16) ); - } - - if ( m_hLookTarget != NULL ) - { - Vector absVel = m_hLookTarget->GetAbsVelocity(); - CBaseEntity *ground = m_hLookTarget->GetGroundEntity(); - if ( ground && ground->GetMoveType() == MOVETYPE_PUSH) - { - absVel = absVel + ground->GetAbsVelocity(); - } - -#ifdef HL2_EPISODIC - // Translate our position if riding in a vehicle - if ( m_hLookTarget->MyCombatCharacterPointer() ) - { - CBaseCombatCharacter *pBCC = m_hLookTarget->MyCombatCharacterPointer(); - CBaseEntity *pVehicle = pBCC->GetVehicleEntity(); - if ( pVehicle ) - { - IPhysicsObject *pObj = pVehicle->VPhysicsGetObject(); - if ( pObj ) - { - Vector vecVelocity; - pObj->GetVelocity( &vecVelocity, NULL ); - - absVel += vecVelocity; - } - } - } -#endif //HL2_EPISODIC - - if ( !VectorCompare( absVel, vec3_origin ) ) - { - Vector viewTarget = GetViewtarget(); - - // Forward one think cycle - viewTarget += absVel * flInterval; - - SetViewtarget( viewTarget ); - } - } - - // NDebugOverlay::Triangle( vEyePosition, GetViewtarget(), GetAbsOrigin(), 255, 255, 255, 10, false, 0.1 ); - - // DevMsg("pitch %.1f yaw %.1f\n", GetFlexWeight( "eyes_updown" ), GetFlexWeight( "eyes_rightleft" ) ); - - // blink - if (m_flBlinktime < gpGlobals->curtime) - { - Blink(); - m_flBlinktime = gpGlobals->curtime + random->RandomFloat( 1.5, 4.5 ); - } - - if ( ai_debug_looktargets.GetInt() == 1 && (m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) ) - { - NDebugOverlay::Box( GetViewtarget(), -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, 0, 20 ); - NDebugOverlay::Line( EyePosition(),GetViewtarget(), 0,255,0, false, .1 ); - } -} - -//----------------------------------------------------------------------------- - -void CAI_BaseActor::PlayExpressionForState( NPC_STATE state ) -{ - // If we have an override expression, use it above everything else - if ( m_iszExpressionOverride != NULL_STRING && state != NPC_STATE_DEAD ) - { - SetExpression( STRING(m_iszExpressionOverride) ); - return; - } - - // If we have a random expression, use that - const char *pszExpression = SelectRandomExpressionForState( state ); - if ( pszExpression && *pszExpression ) - { - float flDuration = SetExpression( pszExpression ); - m_flNextRandomExpressionTime = gpGlobals->curtime + flDuration; - return; - } - else - { - // Stop looking for random expressions for this state - m_flNextRandomExpressionTime = 0; - } - - // Lastly, use the base expression loops - switch ( state ) - { - case NPC_STATE_IDLE: - if ( m_iszIdleExpression != NULL_STRING ) - { - SetExpression( STRING(m_iszIdleExpression) ); - } - break; - - case NPC_STATE_COMBAT: - if ( m_iszCombatExpression != NULL_STRING ) - { - SetExpression( STRING(m_iszCombatExpression) ); - } - break; - - case NPC_STATE_ALERT: - if ( m_iszAlertExpression != NULL_STRING ) - { - SetExpression( STRING(m_iszAlertExpression) ); - } - break; - - case NPC_STATE_PLAYDEAD: - case NPC_STATE_DEAD: - if ( m_iszDeathExpression != NULL_STRING ) - { - SetExpression( STRING(m_iszDeathExpression) ); - } - break; - default: - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Return a random expression for the specified state to play over -// the state's expression loop. -//----------------------------------------------------------------------------- -const char *CAI_BaseActor::SelectRandomExpressionForState( NPC_STATE state ) -{ - return NULL; -} - -//----------------------------------------------------------------------------- - -void CAI_BaseActor::OnStateChange( NPC_STATE OldState, NPC_STATE NewState ) -{ - PlayExpressionForState( NewState ); - -#ifdef HL2_EPISODIC - // If we've just switched states, ensure we stop any scenes that asked to be stopped - if ( OldState == NPC_STATE_IDLE ) - { - RemoveActorFromScriptedScenes( this, true, true ); - } -#endif - - BaseClass::OnStateChange( OldState, NewState ); -} - -//----------------------------------------------------------------------------- - -float CAI_BaseActor::SetExpression( const char *pszExpressionScene ) -{ - if ( !pszExpressionScene || !*pszExpressionScene ) - { - ClearExpression(); - return 0; - } - - if ( m_iszExpressionScene != NULL_STRING && stricmp( STRING(m_iszExpressionScene), pszExpressionScene ) == 0 ) - { - return 0; - } - - if ( m_hExpressionSceneEnt != NULL ) - { - StopScriptedScene( this, m_hExpressionSceneEnt ); - } - - if ( ai_debug_expressions.GetInt() ) - { - Msg("%s (%s) set expression to: %s\n", GetClassname(), GetDebugName(), pszExpressionScene ); - } - - m_iszExpressionScene = NULL_STRING; - if ( pszExpressionScene ) - { - float flDuration = InstancedScriptedScene( this, pszExpressionScene, &m_hExpressionSceneEnt, 0.0, true ); - - if ( m_hExpressionSceneEnt != NULL ) - { - m_iszExpressionScene = AllocPooledString( pszExpressionScene ); - } - - return flDuration; - } - - return 0; -} - -//----------------------------------------------------------------------------- - -void CAI_BaseActor::ClearExpression() -{ - if ( m_hExpressionSceneEnt != NULL ) - { - StopScriptedScene( this, m_hExpressionSceneEnt ); - } - m_iszExpressionScene = NULL_STRING; -} - -//----------------------------------------------------------------------------- - -const char *CAI_BaseActor::GetExpression() -{ - return STRING(m_iszExpressionScene); -} - -//----------------------------------------------------------------------------- - -void CAI_BaseActor::InputSetExpressionOverride( inputdata_t &inputdata ) -{ - bool fHadOverride = ( m_iszExpressionOverride != NULL_STRING ); - m_iszExpressionOverride = inputdata.value.StringID(); - if ( m_iszExpressionOverride != NULL_STRING ) - { - SetExpression( STRING(m_iszExpressionOverride) ); - } - else if ( fHadOverride ) - { - PlayExpressionForState( GetState() ); - } -} - -//----------------------------------------------------------------------------- - -bool CAI_BaseActor::UseSemaphore( void ) -{ - if ( m_bDontUseSemaphore ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- - -CAI_Expresser *CAI_BaseActor::CreateExpresser() -{ - m_pExpresser = new CAI_Expresser(this); - return m_pExpresser; -} - -//----------------------------------------------------------------------------- - -CAI_Expresser *CAI_BaseActor::GetExpresser() -{ - return m_pExpresser; -} - -//----------------------------------------------------------------------------- - -bool CAI_BaseActor::CreateComponents() -{ - if ( !BaseClass::CreateComponents() ) - return false; - - m_pExpresser = CreateExpresser(); - if ( !m_pExpresser) - return false; - - m_pExpresser->Connect(this); - - return true; -} - -//----------------------------------------------------------------------------- diff --git a/game/server/ai_baseactor.h b/game/server/ai_baseactor.h deleted file mode 100644 index 785061b62..000000000 --- a/game/server/ai_baseactor.h +++ /dev/null @@ -1,304 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Hooks and classes for the support of humanoid NPCs with -// groovy facial animation capabilities, aka, "Actors" -// -//=============================================================================// - -#ifndef AI_BASEACTOR_H -#define AI_BASEACTOR_H - -#include "ai_basehumanoid.h" -#include "ai_speech.h" -#include "AI_Interest_Target.h" -#include - - -#if defined( _WIN32 ) -#pragma once -#endif - -//----------------------------------------------------------------------------- -// CAI_BaseActor -// -// Purpose: The base class for all head/body/eye expressive NPCS. -// -//----------------------------------------------------------------------------- -enum PoseParameter_t { POSE_END=INT_MAX }; -enum FlexWeight_t { FLEX_END=INT_MAX }; - -struct AILookTargetArgs_t -{ - EHANDLE hTarget; - Vector vTarget; - float flDuration; - float flInfluence; - float flRamp; - bool bExcludePlayers; - CAI_InterestTarget *pQueue; -}; - -class CAI_BaseActor : public CAI_ExpresserHost -{ - DECLARE_CLASS( CAI_BaseActor, CAI_ExpresserHost ); - - //friend CPoseParameter; - //friend CFlexWeight; - -public: - - // FIXME: this method is lame, isn't there some sort of template thing that would get rid of the Outer pointer? - - void Init( PoseParameter_t &index, const char *szName ) { index = (PoseParameter_t)LookupPoseParameter( szName ); }; - void Set( PoseParameter_t index, float flValue ) { SetPoseParameter( (int)index, flValue ); } - float Get( PoseParameter_t index ) { return GetPoseParameter( (int)index ); } - - float ClampWithBias( PoseParameter_t index, float value, float base ); - - // Note, you must add all names to this static function in order for Init to work - static bool IsServerSideFlexController( char const *szName ); - - void Init( FlexWeight_t &index, const char *szName ) - { - // Make this fatal!!! - if ( !IsServerSideFlexController( szName ) ) - { - Error( "You forgot to add flex controller %s to list in CAI_BaseActor::IsServerSideFlexController()." ); - } - - index = (FlexWeight_t)FindFlexController( szName ); - } - void Set( FlexWeight_t index, float flValue ) { SetFlexWeight( (LocalFlexController_t)index, flValue ); } - float Get( FlexWeight_t index ) { return GetFlexWeight( (LocalFlexController_t)index ); } - - -public: - CAI_BaseActor() - : m_fLatchedPositions( 0 ), - m_latchedEyeOrigin( vec3_origin ), - m_latchedEyeDirection( vec3_origin ), - m_latchedHeadDirection( vec3_origin ), - m_flBlinktime( 0 ), - m_hLookTarget( NULL ), - m_iszExpressionScene( NULL_STRING ), - m_iszExpressionOverride( NULL_STRING ), - m_iszIdleExpression( NULL_STRING ), - m_iszAlertExpression( NULL_STRING ), - m_iszCombatExpression( NULL_STRING ), - m_iszDeathExpression( NULL_STRING ) - { - memset( m_flextarget, 0, 64 * sizeof( m_flextarget[0] ) ); - } - - ~CAI_BaseActor() - { - delete m_pExpresser; - } - - virtual void StudioFrameAdvance(); - - virtual void Precache(); - - virtual void SetModel( const char *szModelName ); - - virtual bool StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget ); - virtual bool ProcessSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ); - virtual bool ClearSceneEvent( CSceneEventInfo *info, bool fastKill, bool canceled ); - virtual bool CheckSceneEventCompletion( CSceneEventInfo *info, float currenttime, CChoreoScene *scene, CChoreoEvent *event ); - - Vector EyePosition( ); - virtual Vector HeadDirection2D( void ); - virtual Vector HeadDirection3D( void ); - virtual Vector EyeDirection2D( void ); - virtual Vector EyeDirection3D( void ); - - CBaseEntity *GetLooktarget() { return m_hLookTarget.Get(); } - virtual void OnNewLookTarget() {}; - - // CBaseFlex - virtual void SetViewtarget( const Vector &viewtarget ); - - // CAI_BaseNPC - virtual float PickLookTarget( bool bExcludePlayers = false, float minTime = 1.5, float maxTime = 2.5 ); - virtual float PickLookTarget( CAI_InterestTarget &queue, bool bExcludePlayers = false, float minTime = 1.5, float maxTime = 2.5 ); - virtual bool PickTacticalLookTarget( AILookTargetArgs_t *pArgs ); - virtual bool PickRandomLookTarget( AILookTargetArgs_t *pArgs ); - virtual void MakeRandomLookTarget( AILookTargetArgs_t *pArgs, float minTime, float maxTime ); - virtual bool HasActiveLookTargets( void ); - virtual void OnSelectedLookTarget( AILookTargetArgs_t *pArgs ) { return; } - virtual void ClearLookTarget( CBaseEntity *pTarget ); - virtual void ExpireCurrentRandomLookTarget() { m_flNextRandomLookTime = gpGlobals->curtime - 0.1f; } - - virtual void StartTaskRangeAttack1( const Task_t *pTask ); - - virtual void AddLookTarget( CBaseEntity *pTarget, float flImportance, float flDuration, float flRamp = 0.0 ); - virtual void AddLookTarget( const Vector &vecPosition, float flImportance, float flDuration, float flRamp = 0.0 ); - - virtual void SetHeadDirection( const Vector &vTargetPos, float flInterval ); - - void UpdateBodyControl( void ); - void UpdateHeadControl( const Vector &vHeadTarget, float flHeadInfluence ); - virtual float GetHeadDebounce( void ) { return 0.3; } // how much of previous head turn to use - - virtual void MaintainLookTargets( float flInterval ); - virtual bool ValidEyeTarget(const Vector &lookTargetPos); - virtual bool ValidHeadTarget(const Vector &lookTargetPos); - virtual float HeadTargetValidity(const Vector &lookTargetPos); - - virtual bool ShouldBruteForceFailedNav() { return true; } - - void AccumulateIdealYaw( float flYaw, float flIntensity ); - bool SetAccumulatedYawAndUpdate( void ); - - float m_flAccumYawDelta; - float m_flAccumYawScale; - - //--------------------------------- - - virtual void OnStateChange( NPC_STATE OldState, NPC_STATE NewState ); - - //--------------------------------- - - virtual void PlayExpressionForState( NPC_STATE state ); - virtual const char *SelectRandomExpressionForState( NPC_STATE state ); - - float SetExpression( const char * ); - void ClearExpression(); - const char * GetExpression(); - - enum - { - SCENE_AI_BLINK = 1, - SCENE_AI_HOLSTER, - SCENE_AI_UNHOLSTER, - SCENE_AI_AIM, - SCENE_AI_RANDOMLOOK, - SCENE_AI_RANDOMFACEFLEX, - SCENE_AI_RANDOMHEADFLEX, - SCENE_AI_IGNORECOLLISION, - SCENE_AI_DISABLEAI - }; - - - DECLARE_DATADESC(); -private: - enum - { - HUMANOID_LATCHED_EYE = 0x0001, - HUMANOID_LATCHED_HEAD = 0x0002, - HUMANOID_LATCHED_ALL = 0x0003, - }; - - //--------------------------------- - - void UpdateLatchedValues( void ); - - // Input handlers. - void InputSetExpressionOverride( inputdata_t &inputdata ); - - //--------------------------------- - - int m_fLatchedPositions; - Vector m_latchedEyeOrigin; - Vector m_latchedEyeDirection; // direction eyes are looking - Vector m_latchedHeadDirection; // direction head is aiming - - void ClearHeadAdjustment( void ); - Vector m_goalHeadDirection; - float m_goalHeadInfluence; - - //--------------------------------- - - float m_goalSpineYaw; - float m_goalBodyYaw; - Vector m_goalHeadCorrection; - - //--------------------------------- - - float m_flBlinktime; - EHANDLE m_hLookTarget; - CAI_InterestTarget m_lookQueue; - CAI_InterestTarget m_syntheticLookQueue; - - CAI_InterestTarget m_randomLookQueue; - float m_flNextRandomLookTime; // FIXME: move to scene - - //--------------------------------- - - string_t m_iszExpressionScene; - EHANDLE m_hExpressionSceneEnt; - float m_flNextRandomExpressionTime; - - string_t m_iszExpressionOverride; - -protected: - string_t m_iszIdleExpression; - string_t m_iszAlertExpression; - string_t m_iszCombatExpression; - string_t m_iszDeathExpression; - -private: - //--------------------------------- - - //PoseParameter_t m_ParameterBodyTransY; // "body_trans_Y" - //PoseParameter_t m_ParameterBodyTransX; // "body_trans_X" - //PoseParameter_t m_ParameterBodyLift; // "body_lift" - PoseParameter_t m_ParameterBodyYaw; // "body_yaw" - //PoseParameter_t m_ParameterBodyPitch; // "body_pitch" - //PoseParameter_t m_ParameterBodyRoll; // "body_roll" - PoseParameter_t m_ParameterSpineYaw; // "spine_yaw" - //PoseParameter_t m_ParameterSpinePitch; // "spine_pitch" - //PoseParameter_t m_ParameterSpineRoll; // "spine_roll" - PoseParameter_t m_ParameterNeckTrans; // "neck_trans" - PoseParameter_t m_ParameterHeadYaw; // "head_yaw" - PoseParameter_t m_ParameterHeadPitch; // "head_pitch" - PoseParameter_t m_ParameterHeadRoll; // "head_roll" - - //FlexWeight_t m_FlexweightMoveRightLeft; // "move_rightleft" - //FlexWeight_t m_FlexweightMoveForwardBack;// "move_forwardback" - //FlexWeight_t m_FlexweightMoveUpDown; // "move_updown" - FlexWeight_t m_FlexweightBodyRightLeft; // "body_rightleft" - //FlexWeight_t m_FlexweightBodyUpDown; // "body_updown" - //FlexWeight_t m_FlexweightBodyTilt; // "body_tilt" - FlexWeight_t m_FlexweightChestRightLeft; // "chest_rightleft" - //FlexWeight_t m_FlexweightChestUpDown; // "chest_updown" - //FlexWeight_t m_FlexweightChestTilt; // "chest_tilt" - FlexWeight_t m_FlexweightHeadForwardBack;// "head_forwardback" - FlexWeight_t m_FlexweightHeadRightLeft; // "head_rightleft" - FlexWeight_t m_FlexweightHeadUpDown; // "head_updown" - FlexWeight_t m_FlexweightHeadTilt; // "head_tilt" - - PoseParameter_t m_ParameterGestureHeight; // "gesture_height" - PoseParameter_t m_ParameterGestureWidth; // "gesture_width" - FlexWeight_t m_FlexweightGestureUpDown; // "gesture_updown" - FlexWeight_t m_FlexweightGestureRightLeft; // "gesture_rightleft" - -private: - //--------------------------------- - bool RandomFaceFlex( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ); - bool RandomHeadFlex( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ); - float m_flextarget[64]; - -public: - virtual bool UseSemaphore( void ); - -protected: - bool m_bDontUseSemaphore; - -public: - //--------------------------------- - // - // Speech support - // - virtual CAI_Expresser *GetExpresser(); - -protected: - bool CreateComponents(); - virtual CAI_Expresser *CreateExpresser(); -private: - //--------------------------------- - CAI_Expresser *m_pExpresser; -}; - -//----------------------------------------------------------------------------- -#endif // AI_BASEACTOR_H diff --git a/game/server/ai_basehumanoid.cpp b/game/server/ai_basehumanoid.cpp deleted file mode 100644 index 6b1ca9ab2..000000000 --- a/game/server/ai_basehumanoid.cpp +++ /dev/null @@ -1,335 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" - -#include "BasePropDoor.h" - -#include "ai_basehumanoid.h" -#include "ai_blended_movement.h" -#include "ai_navigator.h" -#include "ai_memory.h" - -#ifdef HL2_DLL -#include "ai_interactions.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -//----------------------------------------------------------------------------- -// Purpose: This is a generic function (to be implemented by sub-classes) to -// handle specific interactions between different types of characters -// (For example the barnacle grabbing an NPC) -// Input : Constant for the type of interaction -// Output : true - if sub-class has a response for the interaction -// false - if sub-class has no response -//----------------------------------------------------------------------------- -bool CAI_BaseHumanoid::HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt) -{ -#ifdef HL2_DLL - // Annoying to ifdef this out. Copy it into all the HL2 specific humanoid NPC's instead? - if ( interactionType == g_interactionBarnacleVictimDangle ) - { - // Force choosing of a new schedule - ClearSchedule( "Grabbed by a barnacle" ); - return true; - } - else if ( interactionType == g_interactionBarnacleVictimReleased ) - { - // Destroy the entity, the barnacle is going to use the ragdoll that it is releasing - // as the corpse. - UTIL_Remove( this ); - return true; - } -#endif - return BaseClass::HandleInteraction( interactionType, data, sourceEnt); -} - - -//----------------------------------------------------------------------------- -// Purpose: check ammo -//----------------------------------------------------------------------------- -void CAI_BaseHumanoid::CheckAmmo( void ) -{ - BaseClass::CheckAmmo(); - - // FIXME: put into GatherConditions()? - // FIXME: why isn't this a baseclass function? - if (!GetActiveWeapon()) - return; - - // Don't do this while holstering / unholstering - if ( IsWeaponStateChanging() ) - return; - - if (GetActiveWeapon()->UsesPrimaryAmmo()) - { - if (!GetActiveWeapon()->HasPrimaryAmmo() ) - { - SetCondition(COND_NO_PRIMARY_AMMO); - } - else if (GetActiveWeapon()->UsesClipsForAmmo1() && GetActiveWeapon()->Clip1() < (GetActiveWeapon()->GetMaxClip1() / 4 + 1)) - { - // don't check for low ammo if you're near the max range of the weapon - SetCondition(COND_LOW_PRIMARY_AMMO); - } - } - - if (!GetActiveWeapon()->HasSecondaryAmmo() ) - { - if ( GetActiveWeapon()->UsesClipsForAmmo2() ) - { - SetCondition(COND_NO_SECONDARY_AMMO); - } - } -} - - -//----------------------------------------------------------------------------- -// TASK_RANGE_ATTACK1 -//----------------------------------------------------------------------------- -void CAI_BaseHumanoid::BuildScheduleTestBits( ) -{ - BaseClass::BuildScheduleTestBits(); - - if ( CapabilitiesGet() & bits_CAP_USE_SHOT_REGULATOR ) - { - if ( GetShotRegulator()->IsInRestInterval() ) - { - ClearCustomInterruptCondition( COND_CAN_RANGE_ATTACK1 ); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -static bool IsSmall( CBaseEntity *pBlocker ) -{ - CCollisionProperty *pCollisionProp = pBlocker->CollisionProp(); - int nSmaller = 0; - Vector vecSize = pCollisionProp->OBBMaxs() - pCollisionProp->OBBMins(); - for ( int i = 0; i < 3; i++ ) - { - if ( vecSize[i] >= 42 ) - return false; - - if ( vecSize[i] <= 30 ) - { - nSmaller++; - } - } - - return ( nSmaller >= 2 ); -} - -bool CAI_BaseHumanoid::OnMoveBlocked( AIMoveResult_t *pResult ) -{ - if ( *pResult != AIMR_BLOCKED_NPC && GetNavigator()->GetBlockingEntity() && !GetNavigator()->GetBlockingEntity()->IsNPC() ) - { - CBaseEntity *pBlocker = GetNavigator()->GetBlockingEntity(); - - float massBonus = ( IsNavigationUrgent() ) ? 40.0 : 0; - - if ( pBlocker->GetMoveType() == MOVETYPE_VPHYSICS && - pBlocker != GetGroundEntity() && - !pBlocker->IsNavIgnored() && - !dynamic_cast(pBlocker) && - pBlocker->VPhysicsGetObject() && - pBlocker->VPhysicsGetObject()->IsMoveable() && - ( pBlocker->VPhysicsGetObject()->GetMass() <= 35.0 + massBonus + 0.1 || - ( pBlocker->VPhysicsGetObject()->GetMass() <= 50.0 + massBonus + 0.1 && IsSmall( pBlocker ) ) ) ) - { - DbgNavMsg1( this, "Setting ignore on object %s", pBlocker->GetDebugName() ); - pBlocker->SetNavIgnore( 2.5 ); - } -#if 0 - else - { - CPhysicsProp *pProp = dynamic_cast( pBlocker ); - if ( pProp && pProp->GetHealth() && pProp->GetExplosiveDamage() == 0.0 && GetActiveWeapon() && !GetActiveWeapon()->ClassMatches( "weapon_rpg" ) ) - { - Msg( "!\n" ); - // Destroy! - } - } -#endif - } - - return BaseClass::OnMoveBlocked( pResult ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -#define SNEAK_ATTACK_DIST 360.0f // 30 feet -void CAI_BaseHumanoid::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - bool bSneakAttacked = false; - - if( ptr->hitgroup == HITGROUP_HEAD ) - { - if ( info.GetAttacker() && info.GetAttacker()->IsPlayer() && info.GetAttacker() != GetEnemy() && !IsInAScript() ) - { - // Shot in the head by a player I've never seen. In this case the player - // has gotten the drop on this enemy and such an attack is always lethal (at close range) - bSneakAttacked = true; - - AIEnemiesIter_t iter; - for( AI_EnemyInfo_t *pMemory = GetEnemies()->GetFirst(&iter); pMemory != NULL; pMemory = GetEnemies()->GetNext(&iter) ) - { - if ( pMemory->hEnemy == info.GetAttacker() ) - { - bSneakAttacked = false; - break; - } - } - - float flDist; - - flDist = (info.GetAttacker()->GetAbsOrigin() - GetAbsOrigin()).Length(); - - if( flDist > SNEAK_ATTACK_DIST ) - { - bSneakAttacked = false; - } - } - } - - if( bSneakAttacked ) - { - CTakeDamageInfo newInfo = info; - - newInfo.SetDamage( GetHealth() ); - BaseClass::TraceAttack( newInfo, vecDir, ptr ); - return; - } - - BaseClass::TraceAttack( info, vecDir, ptr ); -} - -//----------------------------------------------------------------------------- -// TASK_RANGE_ATTACK1 -//----------------------------------------------------------------------------- -void CAI_BaseHumanoid::StartTaskRangeAttack1( const Task_t *pTask ) -{ - if ( ( CapabilitiesGet() & bits_CAP_USE_SHOT_REGULATOR ) == 0 ) - { - BaseClass::StartTask( pTask ); - return; - } - - // Can't shoot if we're in the rest interval; fail the schedule - if ( GetShotRegulator()->IsInRestInterval() ) - { - TaskFail( "Shot regulator in rest interval" ); - return; - } - - if ( GetShotRegulator()->ShouldShoot() ) - { - OnRangeAttack1(); - ResetIdealActivity( ACT_RANGE_ATTACK1 ); - } - else - { - // This can happen if we start while in the middle of a burst - // which shouldn't happen, but given the chaotic nature of our AI system, - // does occasionally happen. - ResetIdealActivity( ACT_IDLE_ANGRY ); - } -} - - -//----------------------------------------------------------------------------- -// Starting Tasks -//----------------------------------------------------------------------------- -void CAI_BaseHumanoid::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_RANGE_ATTACK1: - StartTaskRangeAttack1( pTask ); - break; - - default: - BaseClass::StartTask( pTask ); - } -} - - - -//----------------------------------------------------------------------------- -// TASK_RANGE_ATTACK1 / TASK_RANGE_ATTACK2 / etc. -//----------------------------------------------------------------------------- -void CAI_BaseHumanoid::RunTaskRangeAttack1( const Task_t *pTask ) -{ - if ( ( CapabilitiesGet() & bits_CAP_USE_SHOT_REGULATOR ) == 0 ) - { - BaseClass::RunTask( pTask ); - return; - } - - AutoMovement( ); - - Vector vecEnemyLKP = GetEnemyLKP(); - - // If our enemy was killed, but I'm not done animating, the last known position comes - // back as the origin and makes the me face the world origin if my attack schedule - // doesn't break when my enemy dies. (sjb) - if( vecEnemyLKP != vec3_origin ) - { - if ( ( pTask->iTask == TASK_RANGE_ATTACK1 || pTask->iTask == TASK_RELOAD ) && - ( CapabilitiesGet() & bits_CAP_AIM_GUN ) && - FInAimCone( vecEnemyLKP ) ) - { - // Arms will aim, so leave body yaw as is - GetMotor()->SetIdealYawAndUpdate( GetMotor()->GetIdealYaw(), AI_KEEP_YAW_SPEED ); - } - else - { - GetMotor()->SetIdealYawToTargetAndUpdate( vecEnemyLKP, AI_KEEP_YAW_SPEED ); - } - } - - if ( IsActivityFinished() ) - { - if ( !GetEnemy() || !GetEnemy()->IsAlive() ) - { - TaskComplete(); - return; - } - - if ( !GetShotRegulator()->IsInRestInterval() ) - { - if ( GetShotRegulator()->ShouldShoot() ) - { - OnRangeAttack1(); - ResetIdealActivity( ACT_RANGE_ATTACK1 ); - } - return; - } - TaskComplete(); - } -} - - -//----------------------------------------------------------------------------- -// Running Tasks -//----------------------------------------------------------------------------- -void CAI_BaseHumanoid::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_RANGE_ATTACK1: - RunTaskRangeAttack1( pTask ); - break; - - default: - BaseClass::RunTask( pTask ); - } -} diff --git a/game/server/ai_basehumanoid.h b/game/server/ai_basehumanoid.h deleted file mode 100644 index 5df1423fb..000000000 --- a/game/server/ai_basehumanoid.h +++ /dev/null @@ -1,50 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_BASEHUMANOID_H -#define AI_BASEHUMANOID_H - -#include "ai_behavior.h" -#include "ai_blended_movement.h" - -//----------------------------------------------------------------------------- -// CLASS: CAI_BaseHumanoid -//----------------------------------------------------------------------------- - -typedef CAI_BlendingHost< CAI_BehaviorHost > CAI_BaseHumanoidBase; - -class CAI_BaseHumanoid : public CAI_BaseHumanoidBase -{ - DECLARE_CLASS( CAI_BaseHumanoid, CAI_BaseHumanoidBase ); - -public: - bool HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt); - - // Tasks - virtual void StartTask( const Task_t *pTask ); - virtual void RunTask( const Task_t *pTask ); - virtual void BuildScheduleTestBits( ); - - // Navigation - bool OnMoveBlocked( AIMoveResult_t *pResult ); - - // Damage - void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - - // Various start tasks - virtual void StartTaskRangeAttack1( const Task_t *pTask ); - - // Various run tasks - virtual void RunTaskRangeAttack1( const Task_t *pTask ); - - // Purpose: check ammo - virtual void CheckAmmo( void ); -}; - -//----------------------------------------------------------------------------- - -#endif diff --git a/game/server/ai_basenpc.cpp b/game/server/ai_basenpc.cpp deleted file mode 100644 index 876274e15..000000000 --- a/game/server/ai_basenpc.cpp +++ /dev/null @@ -1,14125 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" - -#include "ai_basenpc.h" -#include "fmtstr.h" -#include "activitylist.h" -#include "animation.h" -#include "basecombatweapon.h" -#include "soundent.h" -#include "decals.h" -#include "entitylist.h" -#include "eventqueue.h" -#include "entityapi.h" -#include "bitstring.h" -#include "gamerules.h" // For g_pGameRules -#include "scripted.h" -#include "worldsize.h" -#include "game.h" -#include "shot_manipulator.h" - -#ifdef HL2_DLL -#include "ai_interactions.h" -#include "hl2_gamerules.h" -#endif // HL2_DLL - -#include "ai_network.h" -#include "ai_networkmanager.h" -#include "ai_pathfinder.h" -#include "ai_node.h" -#include "ai_default.h" -#include "ai_schedule.h" -#include "ai_task.h" -#include "ai_hull.h" -#include "ai_moveprobe.h" -#include "ai_hint.h" -#include "ai_navigator.h" -#include "ai_senses.h" -#include "ai_squadslot.h" -#include "ai_memory.h" -#include "ai_squad.h" -#include "ai_localnavigator.h" -#include "ai_tacticalservices.h" -#include "ai_behavior.h" -#include "ai_dynamiclink.h" -#include "AI_Criteria.h" -#include "basegrenade_shared.h" -#include "ammodef.h" -#include "player.h" -#include "sceneentity.h" -#include "ndebugoverlay.h" -#include "mathlib/mathlib.h" -#include "bone_setup.h" -#include "IEffects.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "tier1/strtools.h" -#include "doors.h" -#include "BasePropDoor.h" -#include "saverestore_utlvector.h" -#include "npcevent.h" -#include "movevars_shared.h" -#include "te_effect_dispatch.h" -#include "globals.h" -#include "saverestore_bitstring.h" -#include "checksum_crc.h" -#include "iservervehicle.h" -#include "filters.h" -#ifdef HL2_DLL -#include "npc_bullseye.h" -#include "hl2_player.h" -#include "weapon_physcannon.h" -#endif -#include "waterbullet.h" -#include "in_buttons.h" -#include "eventlist.h" -#include "globalstate.h" -#include "physics_prop_ragdoll.h" -#include "vphysics/friction.h" -#include "physics_npc_solver.h" -#include "tier0/vcrmode.h" -#include "death_pose.h" -#include "datacache/imdlcache.h" -#include "vstdlib/jobthread.h" - -#ifdef HL2_EPISODIC -#include "npc_alyx_episodic.h" -#endif - -#ifdef PORTAL - #include "prop_portal_shared.h" -#endif - -#include "env_debughistory.h" -#include "collisionutils.h" - -extern ConVar sk_healthkit; - -// dvs: for opening doors -- these should probably not be here -#include "ai_route.h" -#include "ai_waypoint.h" - -#include "utlbuffer.h" -#include "GameStats.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//#define DEBUG_LOOK - -bool RagdollManager_SaveImportant( CAI_BaseNPC *pNPC ); - -#define MIN_PHYSICS_FLINCH_DAMAGE 5.0f - -#define NPC_GRENADE_FEAR_DIST 200 -#define MAX_GLASS_PENETRATION_DEPTH 16.0f - -#define FINDNAMEDENTITY_MAX_ENTITIES 32 // max number of entities to be considered for random entity selection in FindNamedEntity - -extern bool g_fDrawLines; -extern short g_sModelIndexLaser; // holds the index for the laser beam -extern short g_sModelIndexLaserDot; // holds the index for the laser beam dot - -// Debugging tools -ConVar ai_no_select_box( "ai_no_select_box", "0" ); - -ConVar ai_show_think_tolerance( "ai_show_think_tolerance", "0" ); -ConVar ai_debug_think_ticks( "ai_debug_think_ticks", "0" ); -ConVar ai_debug_doors( "ai_debug_doors", "0" ); -ConVar ai_debug_enemies( "ai_debug_enemies", "0" ); - -ConVar ai_rebalance_thinks( "ai_rebalance_thinks", "1" ); -ConVar ai_use_efficiency( "ai_use_efficiency", "1" ); -ConVar ai_use_frame_think_limits( "ai_use_frame_think_limits", "1" ); -ConVar ai_default_efficient( "ai_default_efficient", ( IsX360() ) ? "1" : "0" ); -ConVar ai_efficiency_override( "ai_efficiency_override", "0" ); -ConVar ai_debug_efficiency( "ai_debug_efficiency", "0" ); -ConVar ai_debug_dyninteractions( "ai_debug_dyninteractions", "0", FCVAR_NONE, "Debug the NPC dynamic interaction system." ); -ConVar ai_frametime_limit( "ai_frametime_limit", "50", FCVAR_NONE, "frametime limit for min efficiency AIE_NORMAL (in sec's)." ); - -ConVar ai_use_think_optimizations( "ai_use_think_optimizations", "1" ); - -ConVar ai_test_moveprobe_ignoresmall( "ai_test_moveprobe_ignoresmall", "0" ); - -#ifdef HL2_EPISODIC -extern ConVar ai_vehicle_avoidance; -#endif // HL2_EPISODIC - -#ifndef _RETAIL -#define ShouldUseEfficiency() ( ai_use_think_optimizations.GetBool() && ai_use_efficiency.GetBool() ) -#define ShouldUseFrameThinkLimits() ( ai_use_think_optimizations.GetBool() && ai_use_frame_think_limits.GetBool() ) -#define ShouldRebalanceThinks() ( ai_use_think_optimizations.GetBool() && ai_rebalance_thinks.GetBool() ) -#define ShouldDefaultEfficient() ( ai_use_think_optimizations.GetBool() && ai_default_efficient.GetBool() ) -#else -#define ShouldUseEfficiency() ( true ) -#define ShouldUseFrameThinkLimits() ( true ) -#define ShouldRebalanceThinks() ( true ) -#define ShouldDefaultEfficient() ( true ) -#endif - -#ifndef _RETAIL -#define DbgEnemyMsg if ( !ai_debug_enemies.GetBool() ) ; else DevMsg -#else -#define DbgEnemyMsg if ( 0 ) ; else DevMsg -#endif - -#ifdef DEBUG_AI_FRAME_THINK_LIMITS -#define DbgFrameLimitMsg DevMsg -#else -#if defined __GNUC__ || (defined _MSC_VER && _MSC_VER >= 1400) -#define DbgFrameLimitMsg(...) -#else -#define DbgFrameLimitMsg (void) -#endif -#endif - -// NPC damage adjusters -ConVar sk_npc_head( "sk_npc_head","2" ); -ConVar sk_npc_chest( "sk_npc_chest","1" ); -ConVar sk_npc_stomach( "sk_npc_stomach","1" ); -ConVar sk_npc_arm( "sk_npc_arm","1" ); -ConVar sk_npc_leg( "sk_npc_leg","1" ); -ConVar showhitlocation( "showhitlocation", "0" ); - -// Squad debugging -ConVar ai_debug_squads( "ai_debug_squads", "0" ); -ConVar ai_debug_loners( "ai_debug_loners", "0" ); - -// Shoot trajectory -ConVar ai_lead_time( "ai_lead_time","0.0" ); -ConVar ai_shot_stats( "ai_shot_stats", "0" ); -ConVar ai_shot_stats_term( "ai_shot_stats_term", "1000" ); -ConVar ai_shot_bias( "ai_shot_bias", "1.0" ); - -ConVar ai_spread_defocused_cone_multiplier( "ai_spread_defocused_cone_multiplier","3.0" ); -ConVar ai_spread_cone_focus_time( "ai_spread_cone_focus_time","0.6" ); -ConVar ai_spread_pattern_focus_time( "ai_spread_pattern_focus_time","0.8" ); - -ConVar ai_reaction_delay_idle( "ai_reaction_delay_idle","0.3" ); -ConVar ai_reaction_delay_alert( "ai_reaction_delay_alert", "0.1" ); - -ConVar ai_strong_optimizations( "ai_strong_optimizations", ( IsX360() ) ? "1" : "0" ); -bool AIStrongOpt( void ) -{ - return ai_strong_optimizations.GetBool(); -} - -//----------------------------------------------------------------------------- -// -// Crude frame timings -// - -CFastTimer g_AIRunTimer; -CFastTimer g_AIPostRunTimer; -CFastTimer g_AIMoveTimer; - -CFastTimer g_AIConditionsTimer; -CFastTimer g_AIPrescheduleThinkTimer; -CFastTimer g_AIMaintainScheduleTimer; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -CAI_Manager g_AI_Manager; - -//------------------------------------- - -CAI_Manager::CAI_Manager() -{ - m_AIs.EnsureCapacity( MAX_AIS ); -} - -//------------------------------------- - -CAI_BaseNPC **CAI_Manager::AccessAIs() -{ - if (m_AIs.Count()) - return &m_AIs[0]; - return NULL; -} - -//------------------------------------- - -int CAI_Manager::NumAIs() -{ - return m_AIs.Count(); -} - -//------------------------------------- - -void CAI_Manager::AddAI( CAI_BaseNPC *pAI ) -{ - m_AIs.AddToTail( pAI ); -} - -//------------------------------------- - -void CAI_Manager::RemoveAI( CAI_BaseNPC *pAI ) -{ - int i = m_AIs.Find( pAI ); - - if ( i != -1 ) - m_AIs.FastRemove( i ); -} - - -//----------------------------------------------------------------------------- - -// ================================================================ -// Init static data -// ================================================================ -int CAI_BaseNPC::m_nDebugBits = 0; -CAI_BaseNPC* CAI_BaseNPC::m_pDebugNPC = NULL; -int CAI_BaseNPC::m_nDebugPauseIndex = -1; - -CAI_ClassScheduleIdSpace CAI_BaseNPC::gm_ClassScheduleIdSpace( true ); -CAI_GlobalScheduleNamespace CAI_BaseNPC::gm_SchedulingSymbols; -CAI_LocalIdSpace CAI_BaseNPC::gm_SquadSlotIdSpace( true ); - -string_t CAI_BaseNPC::gm_iszPlayerSquad; - -int CAI_BaseNPC::gm_iNextThinkRebalanceTick; -float CAI_BaseNPC::gm_flTimeLastSpawn; -int CAI_BaseNPC::gm_nSpawnedThisFrame; - -CSimpleSimTimer CAI_BaseNPC::m_AnyUpdateEnemyPosTimer; - -// -// Deferred Navigation calls go here -// - -CPostFrameNavigationHook g_PostFrameNavigationHook; -CPostFrameNavigationHook *PostFrameNavigationSystem( void ) -{ - return &g_PostFrameNavigationHook; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CPostFrameNavigationHook::Init( void ) -{ - m_Functors.Purge(); - m_bGameFrameRunning = false; - return true; -} - -// Main query job -CJob *g_pQueuedNavigationQueryJob = NULL; - -static void ProcessNavigationQueries( CFunctor **pData, unsigned int nCount ) -{ - // Run all queued navigation on a separate thread - for ( unsigned int i = 0; i < nCount; i++ ) - { - (*pData[i])(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPostFrameNavigationHook::FrameUpdatePreEntityThink( void ) -{ - // If the thread is executing, then wait for it to finish - if ( g_pQueuedNavigationQueryJob ) - { - g_pQueuedNavigationQueryJob->WaitForFinishAndRelease(); - g_pQueuedNavigationQueryJob = NULL; - m_Functors.Purge(); - } - - if ( ai_post_frame_navigation.GetBool() == false ) - return; - - SetGrameFrameRunning( true ); -} - -//----------------------------------------------------------------------------- -// Purpose: Now that the game frame has collected all the navigation queries, service them -//----------------------------------------------------------------------------- -void CPostFrameNavigationHook::FrameUpdatePostEntityThink( void ) -{ - if ( ai_post_frame_navigation.GetBool() == false ) - return; - - // The guts of the NPC will check against this to decide whether or not to queue its navigation calls - SetGrameFrameRunning( false ); - - // Throw this off to a thread job - g_pQueuedNavigationQueryJob = ThreadExecute( &ProcessNavigationQueries, m_Functors.Base(), m_Functors.Count() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Queue up our navigation call -//----------------------------------------------------------------------------- -void CPostFrameNavigationHook::EnqueueEntityNavigationQuery( CAI_BaseNPC *pNPC, CFunctor *pFunctor ) -{ - if ( ai_post_frame_navigation.GetBool() == false ) - return; - - m_Functors.AddToTail( pFunctor ); - pNPC->SetNavigationDeferred( true ); -} - -// -// Deferred Navigation calls go here -// - - -// ================================================================ -// Class Methods -// ================================================================ - -//----------------------------------------------------------------------------- -// Purpose: Static debug function to clear schedules for all NPCS -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_BaseNPC::ClearAllSchedules(void) -{ - CAI_BaseNPC *npc = gEntList.NextEntByClass( (CAI_BaseNPC *)NULL ); - - while (npc) - { - npc->ClearSchedule( "CAI_BaseNPC::ClearAllSchedules" ); - npc->GetNavigator()->ClearGoal(); - npc = gEntList.NextEntByClass(npc); - } -} - -// ============================================================================== - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::Event_Gibbed( const CTakeDamageInfo &info ) -{ - bool gibbed = CorpseGib( info ); - - if ( gibbed ) - { - // don't remove players! - UTIL_Remove( this ); - SetThink( NULL ); //We're going away, so don't think anymore. - } - else - { - CorpseFade(); - } - - return gibbed; -} - -//========================================================= -// GetFlinchActivity - determines the best type of flinch -// anim to play. -//========================================================= -Activity CAI_BaseNPC::GetFlinchActivity( bool bHeavyDamage, bool bGesture ) -{ - Activity flinchActivity; - - switch ( LastHitGroup() ) - { - // pick a region-specific flinch - case HITGROUP_HEAD: - flinchActivity = bGesture ? ACT_GESTURE_FLINCH_HEAD : ACT_FLINCH_HEAD; - break; - case HITGROUP_STOMACH: - flinchActivity = bGesture ? ACT_GESTURE_FLINCH_STOMACH : ACT_FLINCH_STOMACH; - break; - case HITGROUP_LEFTARM: - flinchActivity = bGesture ? ACT_GESTURE_FLINCH_LEFTARM : ACT_FLINCH_LEFTARM; - break; - case HITGROUP_RIGHTARM: - flinchActivity = bGesture ? ACT_GESTURE_FLINCH_RIGHTARM : ACT_FLINCH_RIGHTARM; - break; - case HITGROUP_LEFTLEG: - flinchActivity = bGesture ? ACT_GESTURE_FLINCH_LEFTLEG : ACT_FLINCH_LEFTLEG; - break; - case HITGROUP_RIGHTLEG: - flinchActivity = bGesture ? ACT_GESTURE_FLINCH_RIGHTLEG : ACT_FLINCH_RIGHTLEG; - break; - case HITGROUP_CHEST: - flinchActivity = bGesture ? ACT_GESTURE_FLINCH_CHEST : ACT_FLINCH_CHEST; - break; - case HITGROUP_GEAR: - case HITGROUP_GENERIC: - default: - // just get a generic flinch. - if ( bHeavyDamage ) - { - flinchActivity = bGesture ? ACT_GESTURE_BIG_FLINCH : ACT_BIG_FLINCH; - } - else - { - flinchActivity = bGesture ? ACT_GESTURE_SMALL_FLINCH : ACT_SMALL_FLINCH; - } - break; - } - - // do we have a sequence for the ideal activity? - if ( SelectWeightedSequence ( flinchActivity ) == ACTIVITY_NOT_AVAILABLE ) - { - if ( bHeavyDamage ) - { - flinchActivity = bGesture ? ACT_GESTURE_BIG_FLINCH : ACT_BIG_FLINCH; - - // If we fail at finding a big flinch, resort to a small one - if ( SelectWeightedSequence ( flinchActivity ) == ACTIVITY_NOT_AVAILABLE ) - { - flinchActivity = bGesture ? ACT_GESTURE_SMALL_FLINCH : ACT_SMALL_FLINCH; - } - } - else - { - flinchActivity = bGesture ? ACT_GESTURE_SMALL_FLINCH : ACT_SMALL_FLINCH; - } - } - - return flinchActivity; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -//----------------------------------------------------------------------------- -void CAI_BaseNPC::CleanupOnDeath( CBaseEntity *pCulprit, bool bFireDeathOutput ) -{ - if ( !m_bDidDeathCleanup ) - { - m_bDidDeathCleanup = true; - - if ( m_NPCState == NPC_STATE_SCRIPT && m_hCine ) - { - // bail out of this script here - m_hCine->CancelScript(); - // now keep going with the death code - } - - if ( GetHintNode() ) - { - GetHintNode()->Unlock(); - SetHintNode( NULL ); - } - - if( bFireDeathOutput ) - { - m_OnDeath.FireOutput( pCulprit, this ); - } - - // Vacate any strategy slot I might have - VacateStrategySlot(); - - // Remove from squad if in one - if (m_pSquad) - { - // If I'm in idle it means that I didn't see who killed me - // and my squad is still in idle state. Tell squad we have - // an enemy to wake them up and put the enemy position at - // my death position - if ( m_NPCState == NPC_STATE_IDLE && pCulprit) - { - // If we already have some danger memory, don't do this cheat - if ( GetEnemies()->GetDangerMemory() == NULL ) - { - UpdateEnemyMemory( pCulprit, GetAbsOrigin() ); - } - } - - // Remove from squad - m_pSquad->RemoveFromSquad(this, true); - m_pSquad = NULL; - } - - RemoveActorFromScriptedScenes( this, false /*all scenes*/ ); - } - else - DevMsg( "Unexpected double-death-cleanup\n" ); -} - -void CAI_BaseNPC::SelectDeathPose( const CTakeDamageInfo &info ) -{ - if ( !GetModelPtr() || (info.GetDamageType() & DMG_PREVENT_PHYSICS_FORCE) ) - return; - - if ( ShouldPickADeathPose() == false ) - return; - - Activity aActivity = ACT_INVALID; - int iDeathFrame = 0; - - SelectDeathPoseActivityAndFrame( this, info, LastHitGroup(), aActivity, iDeathFrame ); - if ( aActivity == ACT_INVALID ) - { - SetDeathPose( ACT_INVALID ); - SetDeathPoseFrame( 0 ); - return; - } - - SetDeathPose( SelectWeightedSequence( aActivity ) ); - SetDeathPoseFrame( iDeathFrame ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -//----------------------------------------------------------------------------- -void CAI_BaseNPC::Event_Killed( const CTakeDamageInfo &info ) -{ - if (IsCurSchedule(SCHED_NPC_FREEZE)) - { - // We're frozen; don't die. - return; - } - - Wake( false ); - - //Adrian: Select a death pose to extrapolate the ragdoll's velocity. - SelectDeathPose( info ); - - m_lifeState = LIFE_DYING; - - CleanupOnDeath( info.GetAttacker() ); - - StopLoopingSounds(); - DeathSound( info ); - - if ( ( GetFlags() & FL_NPC ) && ( ShouldGib( info ) == false ) ) - { - SetTouch( NULL ); - } - - BaseClass::Event_Killed( info ); - - if ( m_bFadeCorpse ) - { - m_bImportanRagdoll = RagdollManager_SaveImportant( this ); - } - - // Make sure this condition is fired too (OnTakeDamage breaks out before this happens on death) - SetCondition( COND_LIGHT_DAMAGE ); - SetIdealState( NPC_STATE_DEAD ); - - // Some characters rely on getting a state transition, even to death. - // zombies, for instance. When a character becomes a ragdoll, their - // server entity ceases to think, so we have to set the dead state here - // because the AI code isn't going to pick up the change on the next think - // for us. - - // Adrian - Only set this if we are going to become a ragdoll. We still want to - // select SCHED_DIE or do something special when this NPC dies and we wont - // catch the change of state if we set this to whatever the ideal state is. - if ( CanBecomeRagdoll() || IsRagdoll() ) - SetState( NPC_STATE_DEAD ); - - // If the remove-no-ragdoll flag is set in the damage type, we're being - // told to remove ourselves immediately on death. This is used when something - // else has some special reason for us to vanish instead of creating a ragdoll. - // i.e. The barnacle does this because it's already got a ragdoll for us. - if ( info.GetDamageType() & DMG_REMOVENORAGDOLL ) - { - if ( !IsEFlagSet( EFL_IS_BEING_LIFTED_BY_BARNACLE ) ) - { - // Go away - RemoveDeferred(); - } - } -} - -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::Ignite( float flFlameLifetime, bool bNPCOnly, float flSize, bool bCalledByLevelDesigner ) -{ - BaseClass::Ignite( flFlameLifetime, bNPCOnly, flSize, bCalledByLevelDesigner ); - -#ifdef HL2_EPISODIC - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer->IRelationType( this ) != D_LI ) - { - CNPC_Alyx *alyx = CNPC_Alyx::GetAlyx(); - - if ( alyx ) - { - alyx->EnemyIgnited( this ); - } - } -#endif -} - -//----------------------------------------------------------------------------- - -ConVar ai_block_damage( "ai_block_damage","0" ); - -bool CAI_BaseNPC::PassesDamageFilter( const CTakeDamageInfo &info ) -{ - if ( ai_block_damage.GetBool() ) - return false; - // FIXME: hook a friendly damage filter to the npc instead? - if ( (CapabilitiesGet() & bits_CAP_FRIENDLY_DMG_IMMUNE) && info.GetAttacker() && info.GetAttacker() != this ) - { - // check attackers relationship with me - CBaseCombatCharacter *npcEnemy = info.GetAttacker()->MyCombatCharacterPointer(); - bool bHitByVehicle = false; - if ( !npcEnemy ) - { - if ( info.GetAttacker()->GetServerVehicle() ) - { - bHitByVehicle = true; - } - } - - if ( bHitByVehicle || (npcEnemy && npcEnemy->IRelationType( this ) == D_LI) ) - { - m_fNoDamageDecal = true; - - if ( npcEnemy && npcEnemy->IsPlayer() ) - { - m_OnDamagedByPlayer.FireOutput( info.GetAttacker(), this ); - // This also counts as being harmed by player's squad. - m_OnDamagedByPlayerSquad.FireOutput( info.GetAttacker(), this ); - } - - return false; - } - } - - if ( !BaseClass::PassesDamageFilter( info ) ) - { - m_fNoDamageDecal = true; - return false; - } - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int CAI_BaseNPC::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - Forget( bits_MEMORY_INCOVER ); - - if ( !BaseClass::OnTakeDamage_Alive( info ) ) - return 0; - - if ( GetSleepState() == AISS_WAITING_FOR_THREAT ) - Wake(); - - // NOTE: This must happen after the base class is called; we need to reduce - // health before the pain sound, since some NPCs use the final health - // level as a modifier to determine which pain sound to use. - - // REVISIT: Combine soldiers shoot each other a lot and then talk about it - // this improves that case a bunch, but it seems kind of harsh. - if ( !m_pSquad || !m_pSquad->SquadIsMember( info.GetAttacker() ) ) - { - PainSound( info );// "Ouch!" - } - - // See if we're running a dynamic interaction that should break when I am damaged. - if ( IsActiveDynamicInteraction() ) - { - ScriptedNPCInteraction_t *pInteraction = GetRunningDynamicInteraction(); - if ( pInteraction->iLoopBreakTriggerMethod & SNPCINT_LOOPBREAK_ON_DAMAGE ) - { - // Can only break when we're in the action anim - if ( m_hCine->IsPlayingAction() ) - { - m_hCine->StopActionLoop( true ); - } - } - } - - // If we're not allowed to die, refuse to die - // Allow my interaction partner to kill me though - if ( m_iHealth <= 0 && HasInteractionCantDie() && info.GetAttacker() != m_hInteractionPartner ) - { - m_iHealth = 1; - } - -#if 0 - // HACKHACK Don't kill npcs in a script. Let them break their scripts first - // THIS is a Half-Life 1 hack that's not cutting the mustard in the scripts - // that have been authored for Half-Life 2 thus far. (sjb) - if ( m_NPCState == NPC_STATE_SCRIPT ) - { - SetCondition( COND_LIGHT_DAMAGE ); - } -#endif - - // ----------------------------------- - // Fire outputs - // ----------------------------------- - if ( m_flLastDamageTime != gpGlobals->curtime ) - { - // only fire once per frame - m_OnDamaged.FireOutput( info.GetAttacker(), this); - - if( info.GetAttacker()->IsPlayer() ) - { - m_OnDamagedByPlayer.FireOutput( info.GetAttacker(), this ); - - // This also counts as being harmed by player's squad. - m_OnDamagedByPlayerSquad.FireOutput( info.GetAttacker(), this ); - } - else - { - // See if the person that injured me is an NPC. - CAI_BaseNPC *pAttacker = dynamic_cast( info.GetAttacker() ); - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - - if( pAttacker && pAttacker->IsAlive() && pPlayer ) - { - if( pAttacker->GetSquad() != NULL && pAttacker->IsInPlayerSquad() ) - { - m_OnDamagedByPlayerSquad.FireOutput( info.GetAttacker(), this ); - } - } - } - } - - if( (info.GetDamageType() & DMG_CRUSH) && !(info.GetDamageType() & DMG_PHYSGUN) && info.GetDamage() >= MIN_PHYSICS_FLINCH_DAMAGE ) - { - SetCondition( COND_PHYSICS_DAMAGE ); - } - - if ( m_iHealth <= ( m_iMaxHealth / 2 ) ) - { - m_OnHalfHealth.FireOutput( info.GetAttacker(), this ); - } - - // react to the damage (get mad) - if ( ( (GetFlags() & FL_NPC) == 0 ) || !info.GetAttacker() ) - return 1; - - // If the attacker was an NPC or client update my position memory - if ( info.GetAttacker()->GetFlags() & (FL_NPC | FL_CLIENT) ) - { - // ------------------------------------------------------------------ - // DO NOT CHANGE THIS CODE W/O CONSULTING - // Only update information about my attacker I don't see my attacker - // ------------------------------------------------------------------ - if ( !FInViewCone( info.GetAttacker() ) || !FVisible( info.GetAttacker() ) ) - { - // ------------------------------------------------------------- - // If I have an inflictor (enemy / grenade) update memory with - // position of inflictor, otherwise update with an position - // estimate for where the attack came from - // ------------------------------------------------------ - Vector vAttackPos; - if (info.GetInflictor()) - { - vAttackPos = info.GetInflictor()->GetAbsOrigin(); - } - else - { - vAttackPos = (GetAbsOrigin() + ( g_vecAttackDir * 64 )); - } - - - // ---------------------------------------------------------------- - // If I already have an enemy, assume that the attack - // came from the enemy and update my enemy's position - // unless I already know about the attacker or I can see my enemy - // ---------------------------------------------------------------- - if ( GetEnemy() != NULL && - !GetEnemies()->HasMemory( info.GetAttacker() ) && - !HasCondition(COND_SEE_ENEMY) ) - { - UpdateEnemyMemory(GetEnemy(), vAttackPos, GetEnemy()); - } - // ---------------------------------------------------------------- - // If I already know about this enemy, update his position - // ---------------------------------------------------------------- - else if (GetEnemies()->HasMemory( info.GetAttacker() )) - { - UpdateEnemyMemory(info.GetAttacker(), vAttackPos); - } - // ----------------------------------------------------------------- - // Otherwise just note the position, but don't add enemy to my list - // ----------------------------------------------------------------- - else - { - UpdateEnemyMemory(NULL, vAttackPos); - } - } - - // add pain to the conditions - if ( IsLightDamage( info ) ) - { - SetCondition( COND_LIGHT_DAMAGE ); - } - if ( IsHeavyDamage( info ) ) - { - SetCondition( COND_HEAVY_DAMAGE ); - } - - ForceGatherConditions(); - - // Keep track of how much consecutive damage I have recieved - if ((gpGlobals->curtime - m_flLastDamageTime) < 1.0) - { - m_flSumDamage += info.GetDamage(); - } - else - { - m_flSumDamage = info.GetDamage(); - } - m_flLastDamageTime = gpGlobals->curtime; - if ( info.GetAttacker() && info.GetAttacker()->IsPlayer() ) - m_flLastPlayerDamageTime = gpGlobals->curtime; - GetEnemies()->OnTookDamageFrom( info.GetAttacker() ); - - if (m_flSumDamage > m_iMaxHealth*0.3) - { - SetCondition(COND_REPEATED_DAMAGE); - } - - NotifyFriendsOfDamage( info.GetAttacker() ); - } - - // --------------------------------------------------------------- - // Insert a combat sound so that nearby NPCs know I've been hit - // --------------------------------------------------------------- - CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 1024, 0.5, this, SOUNDENT_CHANNEL_INJURY ); - - return 1; -} - - -//========================================================= -// OnTakeDamage_Dying - takedamage function called when a npc's -// corpse is damaged. -//========================================================= -int CAI_BaseNPC::OnTakeDamage_Dying( const CTakeDamageInfo &info ) -{ - if ( info.GetDamageType() & DMG_PLASMA ) - { - if ( m_takedamage != DAMAGE_EVENTS_ONLY ) - { - m_iHealth -= info.GetDamage(); - - if (m_iHealth < -500) - { - UTIL_Remove(this); - } - } - } - return BaseClass::OnTakeDamage_Dying( info ); -} - -//========================================================= -// OnTakeDamage_Dead - takedamage function called when a npc's -// corpse is damaged. -//========================================================= -int CAI_BaseNPC::OnTakeDamage_Dead( const CTakeDamageInfo &info ) -{ - Vector vecDir; - - // grab the vector of the incoming attack. ( pretend that the inflictor is a little lower than it really is, so the body will tend to fly upward a bit). - vecDir = vec3_origin; - if ( info.GetInflictor() ) - { - vecDir = info.GetInflictor()->WorldSpaceCenter() - Vector ( 0, 0, 10 ) - WorldSpaceCenter(); - VectorNormalize( vecDir ); - g_vecAttackDir = vecDir; - } - -#if 0// turn this back on when the bounding box issues are resolved. - - SetGroundEntity( NULL ); - GetLocalOrigin().z += 1; - - // let the damage scoot the corpse around a bit. - if ( info.GetInflictor() && (info.GetAttacker()->GetSolid() != SOLID_TRIGGER) ) - { - ApplyAbsVelocityImpulse( vecDir * -DamageForce( flDamage ) ); - } - -#endif - - // kill the corpse if enough damage was done to destroy the corpse and the damage is of a type that is allowed to destroy the corpse. - if ( g_pGameRules->Damage_ShouldGibCorpse( info.GetDamageType() ) ) - { - // Accumulate corpse gibbing damage, so you can gib with multiple hits - if ( m_takedamage != DAMAGE_EVENTS_ONLY ) - { - m_iHealth -= info.GetDamage() * 0.1; - } - } - - if ( info.GetDamageType() & DMG_PLASMA ) - { - if ( m_takedamage != DAMAGE_EVENTS_ONLY ) - { - m_iHealth -= info.GetDamage(); - - if (m_iHealth < -500) - { - UTIL_Remove(this); - } - } - } - - return 1; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_BaseNPC::NotifyFriendsOfDamage( CBaseEntity *pAttackerEntity ) -{ - CAI_BaseNPC *pAttacker = pAttackerEntity->MyNPCPointer(); - if ( pAttacker ) - { - const Vector &origin = GetAbsOrigin(); - for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - const float NEAR_Z = 10*12; - const float NEAR_XY_SQ = Square( 50*12 ); - CAI_BaseNPC *pNpc = g_AI_Manager.AccessAIs()[i]; - if ( pNpc && pNpc != this ) - { - const Vector &originNpc = pNpc->GetAbsOrigin(); - if ( fabsf( originNpc.z - origin.z ) < NEAR_Z ) - { - if ( (originNpc.AsVector2D() - origin.AsVector2D()).LengthSqr() < NEAR_XY_SQ ) - { - if ( pNpc->GetSquad() == GetSquad() || IRelationType( pNpc ) == D_LI ) - pNpc->OnFriendDamaged( this, pAttacker ); - } - } - } - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_BaseNPC::OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker ) -{ - if ( GetSleepState() != AISS_WAITING_FOR_INPUT ) - { - float distSqToThreat = ( GetAbsOrigin() - pAttacker->GetAbsOrigin() ).LengthSqr(); - - if ( GetSleepState() != AISS_AWAKE && distSqToThreat < Square( 20 * 12 ) ) - Wake(); - - if ( distSqToThreat < Square( 50 * 12 ) ) - ForceGatherConditions(); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::IsLightDamage( const CTakeDamageInfo &info ) -{ - // ALL nonzero damage is light damage! Mask off COND_LIGHT_DAMAGE if you want to ignore light damage. - return ( info.GetDamage() > 0 ); -} - -bool CAI_BaseNPC::IsHeavyDamage( const CTakeDamageInfo &info ) -{ - return ( info.GetDamage() > 20 ); -} - -void CAI_BaseNPC::DoRadiusDamage( const CTakeDamageInfo &info, int iClassIgnore, CBaseEntity *pEntityIgnore ) -{ - RadiusDamage( info, GetAbsOrigin(), info.GetDamage() * 2.5, iClassIgnore, pEntityIgnore ); -} - - -void CAI_BaseNPC::DoRadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrc, int iClassIgnore, CBaseEntity *pEntityIgnore ) -{ - RadiusDamage( info, vecSrc, info.GetDamage() * 2.5, iClassIgnore, pEntityIgnore ); -} - - -//----------------------------------------------------------------------------- -// Set the contents types that are solid by default to all NPCs -//----------------------------------------------------------------------------- -unsigned int CAI_BaseNPC::PhysicsSolidMaskForEntity( void ) const -{ - return MASK_NPCSOLID; -} - - -//========================================================= - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::DecalTrace( trace_t *pTrace, char const *decalName ) -{ - if ( m_fNoDamageDecal ) - { - m_fNoDamageDecal = false; - // @Note (toml 04-23-03): e3, don't decal face on damage if still alive - return; - } - BaseClass::DecalTrace( pTrace, decalName ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::ImpactTrace( trace_t *pTrace, int iDamageType, const char *pCustomImpactName ) -{ - if ( m_fNoDamageDecal ) - { - m_fNoDamageDecal = false; - // @Note (toml 04-23-03): e3, don't decal face on damage if still alive - return; - } - BaseClass::ImpactTrace( pTrace, iDamageType, pCustomImpactName ); -} - -//--------------------------------------------------------- -// Return the number by which to multiply incoming damage -// based on the hitgroup it hits. This exists mainly so -// that individual NPC's can have more or less resistance -// to damage done to certain hitgroups. -//--------------------------------------------------------- -float CAI_BaseNPC::GetHitgroupDamageMultiplier( int iHitGroup, const CTakeDamageInfo &info ) -{ - switch( iHitGroup ) - { - case HITGROUP_GENERIC: - return 1.0f; - - case HITGROUP_HEAD: - return sk_npc_head.GetFloat(); - - case HITGROUP_CHEST: - return sk_npc_chest.GetFloat(); - - case HITGROUP_STOMACH: - return sk_npc_stomach.GetFloat(); - - case HITGROUP_LEFTARM: - case HITGROUP_RIGHTARM: - return sk_npc_arm.GetFloat(); - - case HITGROUP_LEFTLEG: - case HITGROUP_RIGHTLEG: - return sk_npc_leg.GetFloat(); - - default: - return 1.0f; - } -} - -//========================================================= -// TraceAttack -//========================================================= -void CAI_BaseNPC::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - m_fNoDamageDecal = false; - if ( m_takedamage == DAMAGE_NO ) - return; - - CTakeDamageInfo subInfo = info; - - SetLastHitGroup( ptr->hitgroup ); - m_nForceBone = ptr->physicsbone; // save this bone for physics forces - - Assert( m_nForceBone > -255 && m_nForceBone < 256 ); - - bool bDebug = showhitlocation.GetBool(); - - switch ( ptr->hitgroup ) - { - case HITGROUP_GENERIC: - if( bDebug ) DevMsg("Hit Location: Generic\n"); - break; - - // hit gear, react but don't bleed - case HITGROUP_GEAR: - subInfo.SetDamage( 0.01 ); - ptr->hitgroup = HITGROUP_GENERIC; - if( bDebug ) DevMsg("Hit Location: Gear\n"); - break; - - case HITGROUP_HEAD: - subInfo.ScaleDamage( GetHitgroupDamageMultiplier(ptr->hitgroup, info) ); - if( bDebug ) DevMsg("Hit Location: Head\n"); - break; - - case HITGROUP_CHEST: - subInfo.ScaleDamage( GetHitgroupDamageMultiplier(ptr->hitgroup, info) ); - if( bDebug ) DevMsg("Hit Location: Chest\n"); - break; - - case HITGROUP_STOMACH: - subInfo.ScaleDamage( GetHitgroupDamageMultiplier(ptr->hitgroup, info) ); - if( bDebug ) DevMsg("Hit Location: Stomach\n"); - break; - - case HITGROUP_LEFTARM: - case HITGROUP_RIGHTARM: - subInfo.ScaleDamage( GetHitgroupDamageMultiplier(ptr->hitgroup, info) ); - if( bDebug ) DevMsg("Hit Location: Left/Right Arm\n"); - break - ; - case HITGROUP_LEFTLEG: - case HITGROUP_RIGHTLEG: - subInfo.ScaleDamage( GetHitgroupDamageMultiplier(ptr->hitgroup, info) ); - if( bDebug ) DevMsg("Hit Location: Left/Right Leg\n"); - break; - - default: - if( bDebug ) DevMsg("Hit Location: UNKNOWN\n"); - break; - } - - if ( subInfo.GetDamage() >= 1.0 && !(subInfo.GetDamageType() & DMG_SHOCK ) ) - { - if( !IsPlayer() || ( IsPlayer() && g_pGameRules->IsMultiplayer() ) ) - { - // NPC's always bleed. Players only bleed in multiplayer. - SpawnBlood( ptr->endpos, vecDir, BloodColor(), subInfo.GetDamage() );// a little surface blood. - } - - TraceBleed( subInfo.GetDamage(), vecDir, ptr, subInfo.GetDamageType() ); - - if ( ptr->hitgroup == HITGROUP_HEAD && m_iHealth - subInfo.GetDamage() > 0 ) - { - m_fNoDamageDecal = true; - } - } - - // Airboat gun will impart major force if it's about to kill him.... - if ( info.GetDamageType() & DMG_AIRBOAT ) - { - if ( subInfo.GetDamage() >= GetHealth() ) - { - float flMagnitude = subInfo.GetDamageForce().Length(); - if ( (flMagnitude != 0.0f) && (flMagnitude < 400.0f * 65.0f) ) - { - subInfo.ScaleDamageForce( 400.0f * 65.0f / flMagnitude ); - } - } - } - - if( info.GetInflictor() ) - { - subInfo.SetInflictor( info.GetInflictor() ); - } - else - { - subInfo.SetInflictor( info.GetAttacker() ); - } - - AddMultiDamage( subInfo, this ); -} - -//----------------------------------------------------------------------------- -// Purpose: Checks if point is in spread angle between source and target Pos -// Used to prevent friendly fire -// Input : Source of attack, target position, spread angle -// Output : -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::PointInSpread( CBaseCombatCharacter *pCheckEntity, const Vector &sourcePos, const Vector &targetPos, const Vector &testPoint, float flSpread, float maxDistOffCenter ) -{ - float distOffLine = CalcDistanceToLine2D( testPoint.AsVector2D(), sourcePos.AsVector2D(), targetPos.AsVector2D() ); - if ( distOffLine < maxDistOffCenter ) - { - Vector toTarget = targetPos - sourcePos; - float distTarget = VectorNormalize(toTarget); - - Vector toTest = testPoint - sourcePos; - float distTest = VectorNormalize(toTest); - // Only reject if target is on other side - if (distTarget > distTest) - { - toTarget.z = 0.0; - toTest.z = 0.0; - - float dotProduct = DotProduct(toTarget,toTest); - if (dotProduct > flSpread) - { - return true; - } - else if( dotProduct > 0.0f ) - { - // If this guy is in front, do the hull/line test: - if( pCheckEntity ) - { - float flBBoxDist = NAI_Hull::Width( pCheckEntity->GetHullType() ); - flBBoxDist *= 1.414f; // sqrt(2) - - // !!!BUGBUG - this 2d check will stop a citizen shooting at a gunship or strider - // if another citizen is between them, even though the strider or gunship may be - // high up in the air (sjb) - distOffLine = CalcDistanceToLine( testPoint, sourcePos, targetPos ); - if( distOffLine < flBBoxDist ) - { - return true; - } - } - } - } - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Checks if player is in spread angle between source and target Pos -// Used to prevent friendly fire -// Input : Source of attack, target position, spread angle -// Output : -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::PlayerInSpread( const Vector &sourcePos, const Vector &targetPos, float flSpread, float maxDistOffCenter, bool ignoreHatedPlayers ) -{ - // loop through all players - for (int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - - if ( pPlayer && ( !ignoreHatedPlayers || IRelationType( pPlayer ) != D_HT ) ) - { - if ( PointInSpread( pPlayer, sourcePos, targetPos, pPlayer->WorldSpaceCenter(), flSpread, maxDistOffCenter ) ) - return true; - } - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Checks if player is in range of given location. Used by NPCs -// to prevent friendly fire -// Input : -// Output : -//----------------------------------------------------------------------------- -CBaseEntity *CAI_BaseNPC::PlayerInRange( const Vector &vecLocation, float flDist ) -{ - // loop through all players - for (int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - - if (pPlayer && (vecLocation - pPlayer->WorldSpaceCenter() ).Length2D() <= flDist) - { - return pPlayer; - } - } - return NULL; -} - - -#define BULLET_WIZZDIST 80.0 -#define SLOPE ( -1.0 / BULLET_WIZZDIST ) - -void BulletWizz( Vector vecSrc, Vector vecEndPos, edict_t *pShooter, bool isTracer ) -{ - CBasePlayer *pPlayer; - Vector vecBulletPath; - Vector vecPlayerPath; - Vector vecBulletDir; - Vector vecNearestPoint; - float flDist; - float flBulletDist; - - vecBulletPath = vecEndPos - vecSrc; - vecBulletDir = vecBulletPath; - VectorNormalize(vecBulletDir); - - // see how near this bullet passed by player in a single player game - // for multiplayer, we need to go through the list of clients. - for (int i = 1; i <= gpGlobals->maxClients; i++ ) - { - pPlayer = UTIL_PlayerByIndex( i ); - - if ( !pPlayer ) - continue; - - // Don't hear one's own bullets - if( pPlayer->edict() == pShooter ) - continue; - - vecPlayerPath = pPlayer->EarPosition() - vecSrc; - flDist = DotProduct( vecPlayerPath, vecBulletDir ); - vecNearestPoint = vecSrc + vecBulletDir * flDist; - // FIXME: minus m_vecViewOffset? - flBulletDist = ( vecNearestPoint - pPlayer->EarPosition() ).Length(); - } -} - -//----------------------------------------------------------------------------- -// Hits triggers with raycasts -//----------------------------------------------------------------------------- -class CTriggerTraceEnum : public IEntityEnumerator -{ -public: - CTriggerTraceEnum( Ray_t *pRay, const CTakeDamageInfo &info, const Vector& dir, int contentsMask ) : - m_VecDir(dir), m_ContentsMask(contentsMask), m_pRay(pRay), m_info( info ) - { - } - - virtual bool EnumEntity( IHandleEntity *pHandleEntity ) - { - trace_t tr; - - CBaseEntity *pEnt = gEntList.GetBaseEntity( pHandleEntity->GetRefEHandle() ); - - // Done to avoid hitting an entity that's both solid & a trigger. - if ( pEnt->IsSolid() ) - return true; - - enginetrace->ClipRayToEntity( *m_pRay, m_ContentsMask, pHandleEntity, &tr ); - if (tr.fraction < 1.0f) - { - pEnt->DispatchTraceAttack( m_info, m_VecDir, &tr ); - ApplyMultiDamage(); - } - - return true; - } - -private: - Vector m_VecDir; - int m_ContentsMask; - Ray_t *m_pRay; - CTakeDamageInfo m_info; -}; - -void CBaseEntity::TraceAttackToTriggers( const CTakeDamageInfo &info, const Vector& start, const Vector& end, const Vector& dir ) -{ - Ray_t ray; - ray.Init( start, end ); - - CTriggerTraceEnum triggerTraceEnum( &ray, info, dir, MASK_SHOT ); - enginetrace->EnumerateEntities( ray, true, &triggerTraceEnum ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CAI_BaseNPC::GetTracerType( void ) -{ - if ( GetActiveWeapon() ) - { - return GetActiveWeapon()->GetTracerType(); - } - - return BaseClass::GetTracerType(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &vecTracerSrc - -// &tr - -// iTracerType - -//----------------------------------------------------------------------------- -void CAI_BaseNPC::MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ) -{ - if ( GetActiveWeapon() ) - { - GetActiveWeapon()->MakeTracer( vecTracerSrc, tr, iTracerType ); - return; - } - - BaseClass::MakeTracer( vecTracerSrc, tr, iTracerType ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::FireBullets( const FireBulletsInfo_t &info ) -{ -#ifdef HL2_DLL - // If we're shooting at a bullseye, become perfectly accurate if the bullseye demands it - if ( GetEnemy() && GetEnemy()->Classify() == CLASS_BULLSEYE ) - { - CNPC_Bullseye *pBullseye = dynamic_cast(GetEnemy()); - if ( pBullseye && pBullseye->UsePerfectAccuracy() ) - { - FireBulletsInfo_t accurateInfo = info; - accurateInfo.m_vecSpread = vec3_origin; - BaseClass::FireBullets( accurateInfo ); - return; - } - } -#endif - - BaseClass::FireBullets( info ); -} - - -//----------------------------------------------------------------------------- -// Shot statistics -//----------------------------------------------------------------------------- -void CBaseEntity::UpdateShotStatistics( const trace_t &tr ) -{ - if ( ai_shot_stats.GetBool() ) - { - CAI_BaseNPC *pNpc = MyNPCPointer(); - if ( pNpc ) - { - pNpc->m_TotalShots++; - if ( tr.m_pEnt == pNpc->GetEnemy() ) - { - pNpc->m_TotalHits++; - } - } - } -} - - -//----------------------------------------------------------------------------- -// Handle shot entering water -//----------------------------------------------------------------------------- -void CBaseEntity::HandleShotImpactingGlass( const FireBulletsInfo_t &info, - const trace_t &tr, const Vector &vecDir, ITraceFilter *pTraceFilter ) -{ - // Move through the glass until we're at the other side - Vector testPos = tr.endpos + ( vecDir * MAX_GLASS_PENETRATION_DEPTH ); - - CEffectData data; - - data.m_vNormal = tr.plane.normal; - data.m_vOrigin = tr.endpos; - - DispatchEffect( "GlassImpact", data ); - - trace_t penetrationTrace; - - // Re-trace as if the bullet had passed right through - UTIL_TraceLine( testPos, tr.endpos, MASK_SHOT, pTraceFilter, &penetrationTrace ); - - // See if we found the surface again - if ( penetrationTrace.startsolid || tr.fraction == 0.0f || penetrationTrace.fraction == 1.0f ) - return; - - //FIXME: This is technically frustrating MultiDamage, but multiple shots hitting multiple targets in one call - // would do exactly the same anyway... - - // Impact the other side (will look like an exit effect) - DoImpactEffect( penetrationTrace, GetAmmoDef()->DamageType(info.m_iAmmoType) ); - - data.m_vNormal = penetrationTrace.plane.normal; - data.m_vOrigin = penetrationTrace.endpos; - - DispatchEffect( "GlassImpact", data ); - - // Refire the round, as if starting from behind the glass - FireBulletsInfo_t behindGlassInfo; - behindGlassInfo.m_iShots = 1; - behindGlassInfo.m_vecSrc = penetrationTrace.endpos; - behindGlassInfo.m_vecDirShooting = vecDir; - behindGlassInfo.m_vecSpread = vec3_origin; - behindGlassInfo.m_flDistance = info.m_flDistance*( 1.0f - tr.fraction ); - behindGlassInfo.m_iAmmoType = info.m_iAmmoType; - behindGlassInfo.m_iTracerFreq = info.m_iTracerFreq; - behindGlassInfo.m_iDamage = info.m_iDamage; - behindGlassInfo.m_pAttacker = info.m_pAttacker ? info.m_pAttacker : this; - behindGlassInfo.m_nFlags = info.m_nFlags; - - FireBullets( behindGlassInfo ); -} - - -//----------------------------------------------------------------------------- -// Computes the tracer start position -//----------------------------------------------------------------------------- -#define SHOT_UNDERWATER_BUBBLE_DIST 400 - -void CBaseEntity::CreateBubbleTrailTracer( const Vector &vecShotSrc, const Vector &vecShotEnd, const Vector &vecShotDir ) -{ - int nBubbles; - Vector vecBubbleEnd; - float flLengthSqr = vecShotSrc.DistToSqr( vecShotEnd ); - if ( flLengthSqr > SHOT_UNDERWATER_BUBBLE_DIST * SHOT_UNDERWATER_BUBBLE_DIST ) - { - VectorMA( vecShotSrc, SHOT_UNDERWATER_BUBBLE_DIST, vecShotDir, vecBubbleEnd ); - nBubbles = static_cast(WATER_BULLET_BUBBLES_PER_INCH * SHOT_UNDERWATER_BUBBLE_DIST); - } - else - { - float flLength = sqrt(flLengthSqr) - 0.1f; - nBubbles = static_cast(WATER_BULLET_BUBBLES_PER_INCH * flLength); - VectorMA( vecShotSrc, flLength, vecShotDir, vecBubbleEnd ); - } - - Vector vecTracerSrc; - ComputeTracerStartPosition( vecShotSrc, &vecTracerSrc ); - UTIL_BubbleTrail( vecTracerSrc, vecBubbleEnd, nBubbles ); -} - - -//========================================================= -//========================================================= -void CAI_BaseNPC::MakeDamageBloodDecal ( int cCount, float flNoise, trace_t *ptr, Vector vecDir ) -{ - // make blood decal on the wall! - trace_t Bloodtr; - Vector vecTraceDir; - int i; - - if ( !IsAlive() ) - { - // dealing with a dead npc. - if ( m_iMaxHealth <= 0 ) - { - // no blood decal for a npc that has already decalled its limit. - return; - } - else - { - m_iMaxHealth -= 1; - } - } - - for ( i = 0 ; i < cCount ; i++ ) - { - vecTraceDir = vecDir; - - vecTraceDir.x += random->RandomFloat( -flNoise, flNoise ); - vecTraceDir.y += random->RandomFloat( -flNoise, flNoise ); - vecTraceDir.z += random->RandomFloat( -flNoise, flNoise ); - - AI_TraceLine( ptr->endpos, ptr->endpos + vecTraceDir * 172, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &Bloodtr); - - if ( Bloodtr.fraction != 1.0 ) - { - UTIL_BloodDecalTrace( &Bloodtr, BloodColor() ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &tr - -// nDamageType - -//----------------------------------------------------------------------------- -void CAI_BaseNPC::DoImpactEffect( trace_t &tr, int nDamageType ) -{ - if ( GetActiveWeapon() != NULL ) - { - GetActiveWeapon()->DoImpactEffect( tr, nDamageType ); - return; - } - - BaseClass::DoImpactEffect( tr, nDamageType ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -#define InterruptFromCondition( iCondition ) \ - AI_RemapFromGlobal( ( AI_IdIsLocal( iCondition ) ? GetClassScheduleIdSpace()->ConditionLocalToGlobal( iCondition ) : iCondition ) ) - -void CAI_BaseNPC::SetCondition( int iCondition ) -{ - int interrupt = InterruptFromCondition( iCondition ); - - if ( interrupt == -1 ) - { - Assert(0); - return; - } - - m_Conditions.Set( interrupt ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CAI_BaseNPC::HasCondition( int iCondition ) -{ - int interrupt = InterruptFromCondition( iCondition ); - - if ( interrupt == -1 ) - { - Assert(0); - return false; - } - - bool bReturn = m_Conditions.IsBitSet(interrupt); - return (bReturn); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CAI_BaseNPC::HasCondition( int iCondition, bool bUseIgnoreConditions ) -{ - if ( bUseIgnoreConditions ) - return HasCondition( iCondition ); - - int interrupt = InterruptFromCondition( iCondition ); - - if ( interrupt == -1 ) - { - Assert(0); - return false; - } - - bool bReturn = m_ConditionsPreIgnore.IsBitSet(interrupt); - return (bReturn); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CAI_BaseNPC::ClearCondition( int iCondition ) -{ - int interrupt = InterruptFromCondition( iCondition ); - - if ( interrupt == -1 ) - { - Assert(0); - return; - } - - m_Conditions.Clear(interrupt); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CAI_BaseNPC::ClearConditions( int *pConditions, int nConditions ) -{ - for ( int i = 0; i < nConditions; ++i ) - { - int iCondition = pConditions[i]; - int interrupt = InterruptFromCondition( iCondition ); - - if ( interrupt == -1 ) - { - Assert(0); - continue; - } - - m_Conditions.Clear( interrupt ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CAI_BaseNPC::SetIgnoreConditions( int *pConditions, int nConditions ) -{ - for ( int i = 0; i < nConditions; ++i ) - { - int iCondition = pConditions[i]; - int interrupt = InterruptFromCondition( iCondition ); - - if ( interrupt == -1 ) - { - Assert(0); - continue; - } - - m_InverseIgnoreConditions.Clear( interrupt ); // clear means ignore - } -} - -void CAI_BaseNPC::ClearIgnoreConditions( int *pConditions, int nConditions ) -{ - for ( int i = 0; i < nConditions; ++i ) - { - int iCondition = pConditions[i]; - int interrupt = InterruptFromCondition( iCondition ); - - if ( interrupt == -1 ) - { - Assert(0); - continue; - } - - m_InverseIgnoreConditions.Set( interrupt ); // set means don't ignore - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CAI_BaseNPC::HasInterruptCondition( int iCondition ) -{ - if( !GetCurSchedule() ) - { - return false; - } - - int interrupt = InterruptFromCondition( iCondition ); - - if ( interrupt == -1 ) - { - Assert(0); - return false; - } - return ( m_Conditions.IsBitSet( interrupt ) && GetCurSchedule()->HasInterrupt( interrupt ) ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CAI_BaseNPC::ConditionInterruptsCurSchedule( int iCondition ) -{ - if( !GetCurSchedule() ) - { - return false; - } - - int interrupt = InterruptFromCondition( iCondition ); - - if ( interrupt == -1 ) - { - Assert(0); - return false; - } - return ( GetCurSchedule()->HasInterrupt( interrupt ) ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CAI_BaseNPC::ConditionInterruptsSchedule( int localScheduleID, int iCondition ) -{ - CAI_Schedule *pSchedule = GetSchedule( localScheduleID ); - if ( !pSchedule ) - return false; - - int interrupt = InterruptFromCondition( iCondition ); - - if ( interrupt == -1 ) - { - Assert(0); - return false; - } - return ( pSchedule->HasInterrupt( interrupt ) ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Sets the interrupt conditions for a scripted schedule -// Input : interrupt - the level of interrupt we allow -//----------------------------------------------------------------------------- -void CAI_BaseNPC::SetScriptedScheduleIgnoreConditions( Interruptability_t interrupt ) -{ - static int g_GeneralConditions[] = - { - COND_CAN_MELEE_ATTACK1, - COND_CAN_MELEE_ATTACK2, - COND_CAN_RANGE_ATTACK1, - COND_CAN_RANGE_ATTACK2, - COND_ENEMY_DEAD, - COND_HEAR_BULLET_IMPACT, - COND_HEAR_COMBAT, - COND_HEAR_DANGER, - COND_HEAR_PHYSICS_DANGER, - COND_NEW_ENEMY, - COND_PROVOKED, - COND_SEE_ENEMY, - COND_SEE_FEAR, - COND_SMELL, - }; - - static int g_DamageConditions[] = - { - COND_HEAVY_DAMAGE, - COND_LIGHT_DAMAGE, - COND_RECEIVED_ORDERS, - }; - - ClearIgnoreConditions( g_GeneralConditions, ARRAYSIZE(g_GeneralConditions) ); - ClearIgnoreConditions( g_DamageConditions, ARRAYSIZE(g_DamageConditions) ); - - if ( interrupt > GENERAL_INTERRUPTABILITY ) - SetIgnoreConditions( g_GeneralConditions, ARRAYSIZE(g_GeneralConditions) ); - - if ( interrupt > DAMAGEORDEATH_INTERRUPTABILITY ) - SetIgnoreConditions( g_DamageConditions, ARRAYSIZE(g_DamageConditions) ); -} - -//----------------------------------------------------------------------------- -// Returns whether we currently have any interrupt conditions that would -// interrupt the given schedule. -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::HasConditionsToInterruptSchedule( int nLocalScheduleID ) -{ - CAI_Schedule *pSchedule = GetSchedule( nLocalScheduleID ); - if ( !pSchedule ) - return false; - - CAI_ScheduleBits bitsMask; - pSchedule->GetInterruptMask( &bitsMask ); - - CAI_ScheduleBits bitsOut; - AccessConditionBits().And( bitsMask, &bitsOut ); - - return !bitsOut.IsAllClear(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::IsCustomInterruptConditionSet( int nCondition ) -{ - int interrupt = InterruptFromCondition( nCondition ); - - if ( interrupt == -1 ) - { - Assert(0); - return false; - } - - return m_CustomInterruptConditions.IsBitSet( interrupt ); -} - -//----------------------------------------------------------------------------- -// Purpose: Sets a flag in the custom interrupt flags, translating the condition -// to the proper global space, if necessary -//----------------------------------------------------------------------------- -void CAI_BaseNPC::SetCustomInterruptCondition( int nCondition ) -{ - int interrupt = InterruptFromCondition( nCondition ); - - if ( interrupt == -1 ) - { - Assert(0); - return; - } - - m_CustomInterruptConditions.Set( interrupt ); -} - -//----------------------------------------------------------------------------- -// Purpose: Clears a flag in the custom interrupt flags, translating the condition -// to the proper global space, if necessary -//----------------------------------------------------------------------------- -void CAI_BaseNPC::ClearCustomInterruptCondition( int nCondition ) -{ - int interrupt = InterruptFromCondition( nCondition ); - - if ( interrupt == -1 ) - { - Assert(0); - return; - } - - m_CustomInterruptConditions.Clear( interrupt ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Clears all the custom interrupt flags. -//----------------------------------------------------------------------------- -void CAI_BaseNPC::ClearCustomInterruptConditions() -{ - m_CustomInterruptConditions.ClearAll(); -} - - -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::SetDistLook( float flDistLook ) -{ - m_pSenses->SetDistLook( flDistLook ); -} - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::QueryHearSound( CSound *pSound ) -{ - if ( pSound->SoundContext() & SOUND_CONTEXT_COMBINE_ONLY ) - return false; - - if ( pSound->SoundContext() & SOUND_CONTEXT_ALLIES_ONLY ) - { - if ( !IsPlayerAlly() ) - return false; - } - - if ( pSound->IsSoundType( SOUND_PLAYER ) && GetState() == NPC_STATE_IDLE && !FVisible( pSound->GetSoundReactOrigin() ) ) - { - // NPC's that are IDLE should disregard player movement sounds if they can't see them. - // This does not affect them hearing the player's weapon. - // !!!BUGBUG - this probably makes NPC's not hear doors opening, because doors opening put SOUND_PLAYER - // in the world, but the door's model will block the FVisible() trace and this code will then - // deduce that the sound can not be heard - return false; - } - - // Disregard footsteps from our own class type - if ( pSound->IsSoundType( SOUND_COMBAT ) && pSound->SoundChannel() == SOUNDENT_CHANNEL_NPC_FOOTSTEP ) - { - if ( pSound->m_hOwner && pSound->m_hOwner->ClassMatches( m_iClassname ) ) - return false; - } - - if( ShouldIgnoreSound( pSound ) ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC ) -{ - if ( bOnlyHateOrFearIfNPC && pEntity->IsNPC() ) - { - Disposition_t disposition = IRelationType( pEntity ); - return ( disposition == D_HT || disposition == D_FR ); - } - return true; -} - -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::OnLooked( int iDistance ) -{ - // DON'T let visibility information from last frame sit around! - static int conditionsToClear[] = - { - COND_SEE_HATE, - COND_SEE_DISLIKE, - COND_SEE_ENEMY, - COND_SEE_FEAR, - COND_SEE_NEMESIS, - COND_SEE_PLAYER, - COND_LOST_PLAYER, - COND_ENEMY_WENT_NULL, - }; - - bool bHadSeePlayer = HasCondition(COND_SEE_PLAYER); - - ClearConditions( conditionsToClear, ARRAYSIZE( conditionsToClear ) ); - - AISightIter_t iter; - CBaseEntity *pSightEnt; - - pSightEnt = GetSenses()->GetFirstSeenEntity( &iter ); - - while( pSightEnt ) - { - if ( pSightEnt->IsPlayer() ) - { - // if we see a client, remember that (mostly for scripted AI) - SetCondition(COND_SEE_PLAYER); - m_flLastSawPlayerTime = gpGlobals->curtime; - } - - Disposition_t relation = IRelationType( pSightEnt ); - - // the looker will want to consider this entity - // don't check anything else about an entity that can't be seen, or an entity that you don't care about. - if ( relation != D_NU ) - { - if ( pSightEnt == GetEnemy() ) - { - // we know this ent is visible, so if it also happens to be our enemy, store that now. - SetCondition(COND_SEE_ENEMY); - } - - // don't add the Enemy's relationship to the conditions. We only want to worry about conditions when - // we see npcs other than the Enemy. - switch ( relation ) - { - case D_HT: - { - int priority = IRelationPriority( pSightEnt ); - if (priority < 0) - { - SetCondition(COND_SEE_DISLIKE); - } - else if (priority > 10) - { - SetCondition(COND_SEE_NEMESIS); - } - else - { - SetCondition(COND_SEE_HATE); - } - UpdateEnemyMemory(pSightEnt,pSightEnt->GetAbsOrigin()); - break; - - } - case D_FR: - UpdateEnemyMemory(pSightEnt,pSightEnt->GetAbsOrigin()); - SetCondition(COND_SEE_FEAR); - break; - case D_LI: - case D_NU: - break; - default: - DevWarning( 2, "%s can't assess %s\n", GetClassname(), pSightEnt->GetClassname() ); - break; - } - } - - pSightEnt = GetSenses()->GetNextSeenEntity( &iter ); - } - - // Did we lose the player? - if ( bHadSeePlayer && !HasCondition(COND_SEE_PLAYER) ) - { - SetCondition(COND_LOST_PLAYER); - } -} - -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::OnListened() -{ - AISoundIter_t iter; - - CSound *pCurrentSound; - - static int conditionsToClear[] = - { - COND_HEAR_DANGER, - COND_HEAR_COMBAT, - COND_HEAR_WORLD, - COND_HEAR_PLAYER, - COND_HEAR_THUMPER, - COND_HEAR_BUGBAIT, - COND_HEAR_PHYSICS_DANGER, - COND_HEAR_BULLET_IMPACT, - COND_HEAR_MOVE_AWAY, - - COND_NO_HEAR_DANGER, - - COND_SMELL, - }; - - ClearConditions( conditionsToClear, ARRAYSIZE( conditionsToClear ) ); - - pCurrentSound = GetSenses()->GetFirstHeardSound( &iter ); - - while ( pCurrentSound ) - { - // the npc cares about this sound, and it's close enough to hear. - int condition = COND_NONE; - - if ( pCurrentSound->FIsSound() ) - { - // this is an audible sound. - switch( pCurrentSound->SoundTypeNoContext() ) - { - case SOUND_DANGER: - if( gpGlobals->curtime > m_flIgnoreDangerSoundsUntil) - condition = COND_HEAR_DANGER; - break; - - case SOUND_THUMPER: condition = COND_HEAR_THUMPER; break; - case SOUND_BUGBAIT: condition = COND_HEAR_BUGBAIT; break; - case SOUND_COMBAT: - if ( pCurrentSound->SoundChannel() == SOUNDENT_CHANNEL_SPOOKY_NOISE ) - { - condition = COND_HEAR_SPOOKY; - } - else - { - condition = COND_HEAR_COMBAT; - } - break; - - case SOUND_WORLD: condition = COND_HEAR_WORLD; break; - case SOUND_PLAYER: condition = COND_HEAR_PLAYER; break; - case SOUND_BULLET_IMPACT: condition = COND_HEAR_BULLET_IMPACT; break; - case SOUND_PHYSICS_DANGER: condition = COND_HEAR_PHYSICS_DANGER; break; - case SOUND_DANGER_SNIPERONLY:/* silence warning */ break; - case SOUND_MOVE_AWAY: condition = COND_HEAR_MOVE_AWAY; break; - case SOUND_PLAYER_VEHICLE: condition = COND_HEAR_PLAYER; break; - - default: - DevMsg( "**ERROR: NPC %s hearing sound of unknown type %d!\n", GetClassname(), pCurrentSound->SoundType() ); - break; - } - } - else - { - // if not a sound, must be a smell - determine if it's just a scent, or if it's a food scent - condition = COND_SMELL; - } - - if ( condition != COND_NONE ) - { - SetCondition( condition ); - } - - pCurrentSound = GetSenses()->GetNextHeardSound( &iter ); - } - - if( !HasCondition( COND_HEAR_DANGER ) ) - { - SetCondition( COND_NO_HEAR_DANGER ); - } - - // Sound outputs - if ( HasCondition( COND_HEAR_WORLD ) ) - { - m_OnHearWorld.FireOutput(this, this); - } - - if ( HasCondition( COND_HEAR_PLAYER ) ) - { - m_OnHearPlayer.FireOutput(this, this); - } - - if ( HasCondition( COND_HEAR_COMBAT ) || - HasCondition( COND_HEAR_BULLET_IMPACT ) || - HasCondition( COND_HEAR_DANGER ) ) - { - m_OnHearCombat.FireOutput(this, this); - } -} - -//========================================================= -// FValidateHintType - tells use whether or not the npc cares -// about the type of Hint Node given -//========================================================= -bool CAI_BaseNPC::FValidateHintType ( CAI_Hint *pHint ) -{ - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Override in subclasses to associate specific hint types -// with activities -//----------------------------------------------------------------------------- -Activity CAI_BaseNPC::GetHintActivity( short sHintType, Activity HintsActivity ) -{ - if ( HintsActivity != ACT_INVALID ) - return HintsActivity; - - return ACT_IDLE; -} - -//----------------------------------------------------------------------------- -// Purpose: Override in subclasses to give specific hint types delays -// before they can be used again -// Input : -// Output : -//----------------------------------------------------------------------------- -float CAI_BaseNPC::GetHintDelay( short sHintType ) -{ - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: Return incoming grenade if spotted -// Input : -// Output : -//----------------------------------------------------------------------------- -CBaseGrenade* CAI_BaseNPC::IncomingGrenade(void) -{ - int iDist; - - AIEnemiesIter_t iter; - for( AI_EnemyInfo_t *pEMemory = GetEnemies()->GetFirst(&iter); pEMemory != NULL; pEMemory = GetEnemies()->GetNext(&iter) ) - { - CBaseGrenade* pBG = dynamic_cast((CBaseEntity*)pEMemory->hEnemy); - - // Make sure this memory is for a grenade and grenade is not dead - if (!pBG || pBG->m_lifeState == LIFE_DEAD) - continue; - - // Make sure it's visible - if (!FVisible(pBG)) - continue; - - // Check if it's near me - iDist = (int)(pBG->GetAbsOrigin() - GetAbsOrigin()).Length(); - if ( iDist <= NPC_GRENADE_FEAR_DIST ) - return pBG; - - // Check if it's headed towards me - Vector vGrenadeDir = GetAbsOrigin() - pBG->GetAbsOrigin(); - Vector vGrenadeVel; - pBG->GetVelocity( &vGrenadeVel, NULL ); - VectorNormalize(vGrenadeDir); - VectorNormalize(vGrenadeVel); - float flDotPr = DotProduct(vGrenadeDir, vGrenadeVel); - if (flDotPr > 0.85) - return pBG; - } - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Check my physical state with the environment -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_BaseNPC::TryRestoreHull(void) -{ - if ( IsUsingSmallHull() && GetCurSchedule() ) - { - trace_t tr; - Vector vUpBit = GetAbsOrigin(); - vUpBit.z += 1; - - AI_TraceHull( GetAbsOrigin(), vUpBit, GetHullMins(), - GetHullMaxs(), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - if ( !tr.startsolid && (tr.fraction == 1.0) ) - { - SetHullSizeNormal(); - } - } -} - -//========================================================= -//========================================================= -int CAI_BaseNPC::GetSoundInterests( void ) -{ - return SOUND_WORLD | SOUND_COMBAT | SOUND_PLAYER | SOUND_PLAYER_VEHICLE | - SOUND_BULLET_IMPACT; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CAI_BaseNPC::GetSoundPriority( CSound *pSound ) -{ - int iSoundTypeNoContext = pSound->SoundTypeNoContext(); - int iSoundContext = pSound->SoundContext(); - - if( iSoundTypeNoContext & SOUND_DANGER ) - { - return SOUND_PRIORITY_HIGHEST; - } - - if( iSoundTypeNoContext & SOUND_COMBAT ) - { - if( iSoundContext & SOUND_CONTEXT_EXPLOSION ) - { - return SOUND_PRIORITY_VERY_HIGH; - } - - return SOUND_PRIORITY_HIGH; - } - - return SOUND_PRIORITY_NORMAL; -} - -//--------------------------------------------------------- -// Return the loudest sound of this type in the sound list -//--------------------------------------------------------- -CSound *CAI_BaseNPC::GetLoudestSoundOfType( int iType ) -{ - return CSoundEnt::GetLoudestSoundOfType( iType, EarPosition() ); -} - -//========================================================= -// GetBestSound - returns a pointer to the sound the npc -// should react to. Right now responds only to nearest sound. -//========================================================= -CSound* CAI_BaseNPC::GetBestSound( int validTypes ) -{ - if ( m_pLockedBestSound->m_iType != SOUND_NONE ) - return m_pLockedBestSound; - CSound *pResult = GetSenses()->GetClosestSound( false, validTypes ); - if ( pResult == NULL) - DevMsg( "Warning: NULL Return from GetBestSound\n" ); // condition previously set now no longer true. Have seen this when play too many sounds... - return pResult; -} - -//========================================================= -// PBestScent - returns a pointer to the scent the npc -// should react to. Right now responds only to nearest scent -//========================================================= -CSound* CAI_BaseNPC::GetBestScent( void ) -{ - CSound *pResult = GetSenses()->GetClosestSound( true ); - if ( pResult == NULL) - DevMsg("Warning: NULL Return from GetBestScent\n" ); - return pResult; -} - -//----------------------------------------------------------------------------- -void CAI_BaseNPC::LockBestSound() -{ - UnlockBestSound(); - CSound *pBestSound = GetBestSound(); - if ( pBestSound ) - *m_pLockedBestSound = *pBestSound; -} - -//----------------------------------------------------------------------------- -void CAI_BaseNPC::UnlockBestSound() -{ - if ( m_pLockedBestSound->m_iType != SOUND_NONE ) - { - m_pLockedBestSound->m_iType = SOUND_NONE; - OnListened(); // reset hearing conditions - } -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if the specified sound is visible. Handles sounds generated by entities correctly. -// Input : *pSound - -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::SoundIsVisible( CSound *pSound ) -{ - CBaseEntity *pBlocker = NULL; - if ( !FVisible( pSound->GetSoundReactOrigin(), MASK_BLOCKLOS, &pBlocker ) ) - { - // Is the blocker the sound owner? - if ( pBlocker && pBlocker == pSound->m_hOwner ) - return true; - - return false; - } - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true if target is in legal range of eye movements -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::ValidEyeTarget(const Vector &lookTargetPos) -{ - Vector vHeadDir = HeadDirection3D( ); - Vector lookTargetDir = lookTargetPos - EyePosition(); - VectorNormalize(lookTargetDir); - - // Only look if it doesn't crank my eyeballs too far - float dotPr = DotProduct(lookTargetDir, vHeadDir); - if (dotPr > 0.7) - { - return true; - } - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Integrate head turn over time -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_BaseNPC::SetHeadDirection( const Vector &vTargetPos, float flInterval) -{ - if (!(CapabilitiesGet() & bits_CAP_TURN_HEAD)) - return; - -#ifdef DEBUG_LOOK - // Draw line in body, head, and eye directions - Vector vEyePos = EyePosition(); - Vector vHeadDir; - HeadDirection3D(&vHeadDir); - Vector vBodyDir; - BodyDirection2D(&vBodyDir); - - //UNDONE <> - // currently eye dir just returns head dir, so use vTargetPos for now - //Vector vEyeDir; w - //EyeDirection3D(&vEyeDir); - NDebugOverlay::Line( vEyePos, vEyePos+(50*vHeadDir), 255, 0, 0, false, 0.1 ); - NDebugOverlay::Line( vEyePos, vEyePos+(50*vBodyDir), 0, 255, 0, false, 0.1 ); - NDebugOverlay::Line( vEyePos, vTargetPos, 0, 0, 255, false, 0.1 ); -#endif - - //-------------------------------------- - // Set head yaw - //-------------------------------------- - float flDesiredYaw = VecToYaw(vTargetPos - GetLocalOrigin()) - GetLocalAngles().y; - if (flDesiredYaw > 180) - flDesiredYaw -= 360; - if (flDesiredYaw < -180) - flDesiredYaw += 360; - - float iRate = 0.8; - - // Make frame rate independent - float timeToUse = flInterval; - while (timeToUse > 0) - { - m_flHeadYaw = (iRate * m_flHeadYaw) + (1-iRate)*flDesiredYaw; - timeToUse -= 0.1; - } - if (m_flHeadYaw > 360) m_flHeadYaw = 0; - - m_flHeadYaw = SetBoneController( 0, m_flHeadYaw ); - - - //-------------------------------------- - // Set head pitch - //-------------------------------------- - Vector vEyePosition = EyePosition(); - float fTargetDist = (vTargetPos - vEyePosition).Length(); - float fVertDist = vTargetPos.z - vEyePosition.z; - float flDesiredPitch = -RAD2DEG(atan(fVertDist/fTargetDist)); - - // Make frame rate independent - timeToUse = flInterval; - while (timeToUse > 0) - { - m_flHeadPitch = (iRate * m_flHeadPitch) + (1-iRate)*flDesiredPitch; - timeToUse -= 0.1; - } - if (m_flHeadPitch > 360) m_flHeadPitch = 0; - - SetBoneController( 1, m_flHeadPitch ); - -} - -//------------------------------------------------------------------------------ -// Purpose : Calculate the NPC's eye direction in 2D world space -// Input : -// Output : -//------------------------------------------------------------------------------ -Vector CAI_BaseNPC::EyeDirection2D( void ) -{ - // UNDONE - // For now just return head direction.... - return HeadDirection2D( ); -} - -//------------------------------------------------------------------------------ -// Purpose : Calculate the NPC's eye direction in 2D world space -// Input : -// Output : -//------------------------------------------------------------------------------ -Vector CAI_BaseNPC::EyeDirection3D( void ) -{ - // UNDONE //<> - // For now just return head direction.... - return HeadDirection3D( ); -} - -//------------------------------------------------------------------------------ -// Purpose : Calculate the NPC's head direction in 2D world space -// Input : -// Output : -//------------------------------------------------------------------------------ -Vector CAI_BaseNPC::HeadDirection2D( void ) -{ - // UNDONE <> - // This does not account for head rotations in the animation, - // only those done via bone controllers - - // Head yaw is in local cooridnate so it must be added to the body's yaw - QAngle bodyAngles = BodyAngles(); - float flWorldHeadYaw = m_flHeadYaw + bodyAngles.y; - - // Convert head yaw into facing direction - return UTIL_YawToVector( flWorldHeadYaw ); -} - -//------------------------------------------------------------------------------ -// Purpose : Calculate the NPC's head direction in 3D world space -// Input : -// Output : -//------------------------------------------------------------------------------ -Vector CAI_BaseNPC::HeadDirection3D( void ) -{ - Vector vHeadDirection; - - // UNDONE <> - // This does not account for head rotations in the animation, - // only those done via bone controllers - - // Head yaw is in local cooridnate so it must be added to the body's yaw - QAngle bodyAngles = BodyAngles(); - float flWorldHeadYaw = m_flHeadYaw + bodyAngles.y; - - // Convert head yaw into facing direction - AngleVectors( QAngle( m_flHeadPitch, flWorldHeadYaw, 0), &vHeadDirection ); - return vHeadDirection; -} - - -//----------------------------------------------------------------------------- -// Purpose: Look at other NPCs and clients from time to time -// Input : -// Output : -//----------------------------------------------------------------------------- -CBaseEntity *CAI_BaseNPC::EyeLookTarget( void ) -{ - if (m_flNextEyeLookTime < gpGlobals->curtime) - { - CBaseEntity* pBestEntity = NULL; - float fBestDist = MAX_COORD_RANGE; - float fTestDist; - - CBaseEntity *pEntity = NULL; - - for ( CEntitySphereQuery sphere( GetAbsOrigin(), 1024, 0 ); (pEntity = sphere.GetCurrentEntity()) != NULL; sphere.NextEntity() ) - { - if (pEntity == this) - { - continue; - } - CAI_BaseNPC *pNPC = pEntity->MyNPCPointer(); - if (pNPC || (pEntity->GetFlags() & FL_CLIENT)) - { - fTestDist = (GetAbsOrigin() - pEntity->EyePosition()).Length(); - if (fTestDist < fBestDist) - { - if (ValidEyeTarget(pEntity->EyePosition())) - { - fBestDist = fTestDist; - pBestEntity = pEntity; - } - } - } - } - if (pBestEntity) - { - m_flNextEyeLookTime = gpGlobals->curtime + random->RandomInt(1,5); - m_hEyeLookTarget = pBestEntity; - } - } - return m_hEyeLookTarget; -} - - -//----------------------------------------------------------------------------- -// Purpose: Set direction that the NPC aiming their gun -// returns true is the passed Vector is in -// the caller's forward aim cone. The dot product is performed -// in 2d, making the view cone infinitely tall. By default, the -// callers aim cone is assumed to be very narrow -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::FInAimCone( const Vector &vecSpot ) -{ - Vector los = ( vecSpot - GetAbsOrigin() ); - - // do this in 2D - los.z = 0; - VectorNormalize( los ); - - Vector facingDir = BodyDirection2D( ); - - float flDot = DotProduct( los, facingDir ); - - if (CapabilitiesGet() & bits_CAP_AIM_GUN) - { - // FIXME: query current animation for ranges - return ( flDot > DOT_30DEGREE ); - } - - if ( flDot > 0.994 )//!!!BUGBUG - magic number same as FacingIdeal(), what is this? - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Cache whatever pose parameters we intend to use -//----------------------------------------------------------------------------- -void CAI_BaseNPC::PopulatePoseParameters( void ) -{ - m_poseAim_Pitch = LookupPoseParameter( "aim_pitch" ); - m_poseAim_Yaw = LookupPoseParameter( "aim_yaw" ); - m_poseMove_Yaw = LookupPoseParameter( "move_yaw" ); - - BaseClass::PopulatePoseParameters(); -} - -//----------------------------------------------------------------------------- -// Purpose: Set direction that the NPC aiming their gun -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::SetAim( const Vector &aimDir ) -{ - QAngle angDir; - VectorAngles( aimDir, angDir ); - float curPitch = GetPoseParameter( m_poseAim_Pitch ); - float curYaw = GetPoseParameter( m_poseAim_Yaw ); - - float newPitch; - float newYaw; - - if( GetEnemy() ) - { - // clamp and dampen movement - newPitch = curPitch + 0.8 * UTIL_AngleDiff( UTIL_ApproachAngle( angDir.x, curPitch, 20 ), curPitch ); - - float flRelativeYaw = UTIL_AngleDiff( angDir.y, GetAbsAngles().y ); - // float flNewTargetYaw = UTIL_ApproachAngle( flRelativeYaw, curYaw, 20 ); - // float newYaw = curYaw + 0.8 * UTIL_AngleDiff( flNewTargetYaw, curYaw ); - newYaw = curYaw + UTIL_AngleDiff( flRelativeYaw, curYaw ); - } - else - { - // Sweep your weapon more slowly if you're not fighting someone - newPitch = curPitch + 0.6 * UTIL_AngleDiff( UTIL_ApproachAngle( angDir.x, curPitch, 20 ), curPitch ); - - float flRelativeYaw = UTIL_AngleDiff( angDir.y, GetAbsAngles().y ); - newYaw = curYaw + 0.6 * UTIL_AngleDiff( flRelativeYaw, curYaw ); - } - - newPitch = AngleNormalize( newPitch ); - newYaw = AngleNormalize( newYaw ); - - SetPoseParameter( m_poseAim_Pitch, newPitch ); - SetPoseParameter( m_poseAim_Yaw, newYaw ); - - // Msg("yaw %.0f (%.0f %.0f)\n", newYaw, angDir.y, GetAbsAngles().y ); - - // Calculate our interaction yaw. - // If we've got a small adjustment off our abs yaw, use that. - // Otherwise, use our abs yaw. - if ( fabs(newYaw) < 20 ) - { - m_flInteractionYaw = angDir.y; - } - else - { - m_flInteractionYaw = GetAbsAngles().y; - } -} - - -void CAI_BaseNPC::RelaxAim( ) -{ - float curPitch = GetPoseParameter( m_poseAim_Pitch ); - float curYaw = GetPoseParameter( m_poseAim_Yaw ); - - // dampen existing aim - float newPitch = AngleNormalize( UTIL_ApproachAngle( 0, curPitch, 3 ) ); - float newYaw = AngleNormalize( UTIL_ApproachAngle( 0, curYaw, 2 ) ); - - SetPoseParameter( m_poseAim_Pitch, newPitch ); - SetPoseParameter( m_poseAim_Yaw, newYaw ); - // DevMsg("relax aim %.0f %0.f\n", newPitch, newYaw ); -} - -//----------------------------------------------------------------------------- -void CAI_BaseNPC::AimGun() -{ - if (GetEnemy()) - { - Vector vecShootOrigin; - - vecShootOrigin = Weapon_ShootPosition(); - Vector vecShootDir = GetShootEnemyDir( vecShootOrigin, false ); - - SetAim( vecShootDir ); - } - else - { - RelaxAim( ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Set direction that the NPC is looking -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_BaseNPC::MaintainLookTargets ( float flInterval ) -{ - // -------------------------------------------------------- - // Try to look at enemy if I have one - // -------------------------------------------------------- - if ((CBaseEntity*)GetEnemy()) - { - if ( ValidEyeTarget(GetEnemy()->EyePosition()) ) - { - SetHeadDirection(GetEnemy()->EyePosition(),flInterval); - SetViewtarget( GetEnemy()->EyePosition() ); - return; - } - } - -#if 0 - // -------------------------------------------------------- - // First check if I've been assigned to look at an entity - // -------------------------------------------------------- - CBaseEntity *lookTarget = EyeLookTarget(); - if (lookTarget && ValidEyeTarget(lookTarget->EyePosition())) - { - SetHeadDirection(lookTarget->EyePosition(),flInterval); - SetViewtarget( lookTarget->EyePosition() ); - return; - } -#endif - - // -------------------------------------------------------- - // If I'm moving, look at my target position - // -------------------------------------------------------- - if (GetNavigator()->IsGoalActive() && ValidEyeTarget(GetNavigator()->GetCurWaypointPos())) - { - SetHeadDirection(GetNavigator()->GetCurWaypointPos(),flInterval); - SetViewtarget( GetNavigator()->GetCurWaypointPos() ); - return; - } - - - // ------------------------------------- - // If I hear a combat sounds look there - // ------------------------------------- - if ( HasCondition(COND_HEAR_COMBAT) || HasCondition(COND_HEAR_DANGER) ) - { - CSound *pSound = GetBestSound(); - - if ( pSound && pSound->IsSoundType(SOUND_COMBAT | SOUND_DANGER) ) - { - if (ValidEyeTarget( pSound->GetSoundOrigin() )) - { - SetHeadDirection(pSound->GetSoundOrigin(),flInterval); - SetViewtarget( pSound->GetSoundOrigin() ); - return; - } - } - } - - // ------------------------------------- - // Otherwise just look around randomly - // ------------------------------------- - - // Check that look target position is still valid - if (m_flNextEyeLookTime > gpGlobals->curtime) - { - if (!ValidEyeTarget(m_vEyeLookTarget)) - { - // Force choosing of new look target - m_flNextEyeLookTime = 0; - } - } - - if (m_flNextEyeLookTime < gpGlobals->curtime) - { - Vector vBodyDir = BodyDirection2D( ); - - /* - Vector lookSpread = Vector(0.82,0.82,0.22); - float x = random->RandomFloat(-0.5,0.5) + random->RandomFloat(-0.5,0.5); - float y = random->RandomFloat(-0.5,0.5) + random->RandomFloat(-0.5,0.5); - float z = random->RandomFloat(-0.5,0.5) + random->RandomFloat(-0.5,0.5); - - QAngle angles; - VectorAngles( vBodyDir, angles ); - Vector forward, right, up; - AngleVectors( angles, &forward, &right, &up ); - - Vector vecDir = vBodyDir + (x * lookSpread.x * forward) + (y * lookSpread.y * right) + (z * lookSpread.z * up); - float lookDist = random->RandomInt(50,2000); - m_vEyeLookTarget = EyePosition() + lookDist*vecDir; - */ - m_vEyeLookTarget = EyePosition() + 500*vBodyDir; - m_flNextEyeLookTime = gpGlobals->curtime + 0.5; // random->RandomInt(1,5); - } - SetHeadDirection(m_vEyeLookTarget,flInterval); - - // ---------------------------------------------------- - // Integrate eye turn in frame rate independent manner - // ---------------------------------------------------- - float timeToUse = flInterval; - while (timeToUse > 0) - { - m_vCurEyeTarget = ((1 - m_flEyeIntegRate) * m_vCurEyeTarget + m_flEyeIntegRate * m_vEyeLookTarget); - timeToUse -= 0.1; - } - SetViewtarget( m_vCurEyeTarget ); -} - - -//----------------------------------------------------------------------------- -// Let the motor deal with turning presentation issues -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::MaintainTurnActivity( ) -{ - // Don't bother if we're in a vehicle - if ( IsInAVehicle() ) - return; - - AI_PROFILE_SCOPE( CAI_BaseNPC_MaintainTurnActivity ); - GetMotor()->MaintainTurnActivity( ); -} - - -//----------------------------------------------------------------------------- -// Here's where all motion occurs -//----------------------------------------------------------------------------- -void CAI_BaseNPC::PerformMovement() -{ - // don't bother to move if the npc isn't alive - if (!IsAlive()) - return; - - AI_PROFILE_SCOPE(CAI_BaseNPC_PerformMovement); - g_AIMoveTimer.Start(); - - float flInterval = ( m_flTimeLastMovement != FLT_MAX ) ? gpGlobals->curtime - m_flTimeLastMovement : 0.1; - - m_pNavigator->Move( ROUND_TO_TICKS( flInterval ) ); - m_flTimeLastMovement = gpGlobals->curtime; - - g_AIMoveTimer.End(); - -} - -//----------------------------------------------------------------------------- -// Updates to npc after movement is completed -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::PostMovement() -{ - AI_PROFILE_SCOPE( CAI_BaseNPC_PostMovement ); - - InvalidateBoneCache(); - - if ( GetModelPtr() && GetModelPtr()->SequencesAvailable() ) - { - float flInterval = GetAnimTimeInterval(); - - if ( CapabilitiesGet() & bits_CAP_AIM_GUN ) - { - AI_PROFILE_SCOPE( CAI_BaseNPC_PM_AimGun ); - AimGun(); - } - else - { - // NPCs with bits_CAP_AIM_GUN update this in SetAim, called by AimGun. - m_flInteractionYaw = GetAbsAngles().y; - } - - // set look targets for npcs with animated faces - if ( CapabilitiesGet() & bits_CAP_ANIMATEDFACE ) - { - AI_PROFILE_SCOPE( CAI_BaseNPC_PM_MaintainLookTargets ); - MaintainLookTargets(flInterval); - } - } - - { - AI_PROFILE_SCOPE( CAI_BaseNPC_PM_MaintainTurnActivity ); - // update turning as needed - MaintainTurnActivity( ); - } -} - - -//----------------------------------------------------------------------------- - -float g_AINextDisabledMessageTime; -extern bool IsInCommentaryMode( void ); - -bool CAI_BaseNPC::PreThink( void ) -{ - // ---------------------------------------------------------- - // Skip AI if its been disabled or networks haven't been - // loaded, and put a warning message on the screen - // - // Don't do this if the convar wants it hidden - // ---------------------------------------------------------- - if ( (CAI_BaseNPC::m_nDebugBits & bits_debugDisableAI || !g_pAINetworkManager->NetworksLoaded()) ) - { - if ( gpGlobals->curtime >= g_AINextDisabledMessageTime && !IsInCommentaryMode() ) - { - g_AINextDisabledMessageTime = gpGlobals->curtime + 0.5f; - - hudtextparms_s tTextParam; - tTextParam.x = 0.7; - tTextParam.y = 0.65; - tTextParam.effect = 0; - tTextParam.r1 = 255; - tTextParam.g1 = 255; - tTextParam.b1 = 255; - tTextParam.a1 = 255; - tTextParam.r2 = 255; - tTextParam.g2 = 255; - tTextParam.b2 = 255; - tTextParam.a2 = 255; - tTextParam.fadeinTime = 0; - tTextParam.fadeoutTime = 0; - tTextParam.holdTime = 0.6; - tTextParam.fxTime = 0; - tTextParam.channel = 1; - UTIL_HudMessageAll( tTextParam, "A.I. Disabled...\n" ); - } - SetActivity( ACT_IDLE ); - return false; - } - - // -------------------------------------------------------- - // If debug stepping - // -------------------------------------------------------- - if (CAI_BaseNPC::m_nDebugBits & bits_debugStepAI) - { - if (m_nDebugCurIndex >= CAI_BaseNPC::m_nDebugPauseIndex) - { - if (!GetNavigator()->IsGoalActive()) - { - m_flPlaybackRate = 0; - } - return false; - } - else - { - m_flPlaybackRate = 1; - } - } - - if ( m_hOpeningDoor.Get() && AIIsDebuggingDoors( this ) ) - { - NDebugOverlay::Line( EyePosition(), m_hOpeningDoor->WorldSpaceCenter(), 255, 255, 255, false, .1 ); - } - - return true; -} - -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::RunAnimation( void ) -{ - VPROF_BUDGET( "CAI_BaseNPC_RunAnimation", VPROF_BUDGETGROUP_SERVER_ANIM ); - - if ( !GetModelPtr() ) - return; - - float flInterval = GetAnimTimeInterval(); - - StudioFrameAdvance( ); // animate - - if ((CAI_BaseNPC::m_nDebugBits & bits_debugStepAI) && !GetNavigator()->IsGoalActive()) - { - flInterval = 0; - } - - // start or end a fidget - // This needs a better home -- switching animations over time should be encapsulated on a per-activity basis - // perhaps MaintainActivity() or a ShiftAnimationOverTime() or something. - if ( m_NPCState != NPC_STATE_SCRIPT && m_NPCState != NPC_STATE_DEAD && m_Activity == ACT_IDLE && IsActivityFinished() ) - { - int iSequence; - - // FIXME: this doesn't reissue a translation, so if the idle activity translation changes over time, it'll never get reset - if ( SequenceLoops() ) - { - // animation does loop, which means we're playing subtle idle. Might need to fidget. - iSequence = SelectWeightedSequence ( m_translatedActivity ); - } - else - { - // animation that just ended doesn't loop! That means we just finished a fidget - // and should return to our heaviest weighted idle (the subtle one) - iSequence = SelectHeaviestSequence ( m_translatedActivity ); - } - if ( iSequence != ACTIVITY_NOT_AVAILABLE ) - { - ResetSequence( iSequence ); // Set to new anim (if it's there) - - //Adrian: Basically everywhere else in the AI code this variable gets set to whatever our sequence is. - //But here it doesn't and not setting it causes any animation set through here to be stomped by the - //ideal sequence before it has a chance of playing out (since there's code that reselects the ideal - //sequence if it doesn't match the current one). - if ( hl2_episodic.GetBool() ) - { - m_nIdealSequence = iSequence; - } - } - } - - DispatchAnimEvents( this ); -} - -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::PostRun( void ) -{ - AI_PROFILE_SCOPE(CAI_BaseNPC_PostRun); - - g_AIPostRunTimer.Start(); - - if ( !IsMoving() ) - { - if ( GetIdealActivity() == ACT_WALK || - GetIdealActivity() == ACT_RUN || - GetIdealActivity() == ACT_WALK_AIM || - GetIdealActivity() == ACT_RUN_AIM ) - { - PostRunStopMoving(); - } - } - - RunAnimation(); - - // update slave items (weapons) - Weapon_FrameUpdate(); - - g_AIPostRunTimer.End(); -} - -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::PostRunStopMoving() -{ - DbgNavMsg1( this, "NPC %s failed to stop properly, slamming activity\n", GetDebugName() ); - if ( !GetNavigator()->SetGoalFromStoppingPath() ) - SetIdealActivity( GetStoppedActivity() ); // This is to prevent running in place -} - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::ShouldAlwaysThink() -{ - // @TODO (toml 07-08-03): This needs to be beefed up. - // There are simple cases already seen where an AI can briefly leave - // the PVS while navigating to the player. Perhaps should incorporate a heuristic taking into - // account mode, enemy, last time saw player, player range etc. For example, if enemy is player, - // and player is within 100 feet, and saw the player within the past 15 seconds, keep running... - return HasSpawnFlags(SF_NPC_ALWAYSTHINK); -} - - -//----------------------------------------------------------------------------- -// Purpose: Return true if the Player should be running the auto-move-out-of-way -// avoidance code, which also means that the NPC shouldn't care about running into the Player. -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::ShouldPlayerAvoid( void ) -{ - if ( GetState() == NPC_STATE_SCRIPT ) - return true; - - if ( IsInAScript() ) - return true; - - if ( IsInLockedScene() == true ) - return true; - - if ( HasSpawnFlags( SF_NPC_ALTCOLLISION ) ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::UpdateEfficiency( bool bInPVS ) -{ - // Sleeping NPCs always dormant - if ( GetSleepState() != AISS_AWAKE ) - { - SetEfficiency( AIE_DORMANT ); - return; - } - - m_bInChoreo = ( GetState() == NPC_STATE_SCRIPT || IsCurSchedule( SCHED_SCENE_GENERIC, false ) ); - - if ( !ShouldUseEfficiency() ) - { - SetEfficiency( AIE_NORMAL ); - SetMoveEfficiency( AIME_NORMAL ); - return; - } - - //--------------------------------- - - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - static Vector vPlayerEyePosition; - static Vector vPlayerForward; - static int iPrevFrame = -1; - if ( gpGlobals->framecount != iPrevFrame ) - { - iPrevFrame = gpGlobals->framecount; - if ( pPlayer ) - { - pPlayer->EyePositionAndVectors( &vPlayerEyePosition, &vPlayerForward, NULL, NULL ); - } - } - - Vector vToNPC = GetAbsOrigin() - vPlayerEyePosition; - float playerDist = VectorNormalize( vToNPC ); - bool bPlayerFacing; - - bool bClientPVSExpanded = UTIL_ClientPVSIsExpanded(); - - if ( pPlayer ) - { - bPlayerFacing = ( bClientPVSExpanded || ( bInPVS && vPlayerForward.Dot( vToNPC ) > 0 ) ); - } - else - { - playerDist = 0; - bPlayerFacing = true; - } - - //--------------------------------- - - bool bInVisibilityPVS = ( bClientPVSExpanded && UTIL_FindClientInVisibilityPVS( edict() ) != NULL ); - - //--------------------------------- - - if ( ( bInPVS && ( bPlayerFacing || playerDist < 25*12 ) ) || bClientPVSExpanded ) - { - SetMoveEfficiency( AIME_NORMAL ); - } - else - { - SetMoveEfficiency( AIME_EFFICIENT ); - } - - //--------------------------------- - - if ( !IsRetail() && ai_efficiency_override.GetInt() > AIE_NORMAL && ai_efficiency_override.GetInt() <= AIE_DORMANT ) - { - SetEfficiency( (AI_Efficiency_t)ai_efficiency_override.GetInt() ); - return; - } - - //--------------------------------- - - // Some conditions will always force normal - if ( gpGlobals->curtime - GetLastAttackTime() < .15 ) - { - SetEfficiency( AIE_NORMAL ); - return; - } - - bool bFramerateOk = ( gpGlobals->frametime < ai_frametime_limit.GetFloat() ); - - if ( m_bForceConditionsGather || - gpGlobals->curtime - GetLastAttackTime() < .2 || - gpGlobals->curtime - m_flLastDamageTime < .2 || - ( GetState() < NPC_STATE_IDLE || GetState() > NPC_STATE_SCRIPT ) || - ( ( bInPVS || bInVisibilityPVS ) && - ( ( GetTask() && !TaskIsRunning() ) || - GetTaskInterrupt() > 0 || - m_bInChoreo ) ) ) - { - SetEfficiency( ( bFramerateOk ) ? AIE_NORMAL : AIE_EFFICIENT ); - return; - } - - AI_Efficiency_t minEfficiency; - - if ( !ShouldDefaultEfficient() ) - { - minEfficiency = ( bFramerateOk ) ? AIE_NORMAL : AIE_EFFICIENT; - } - else - { - minEfficiency = ( bFramerateOk ) ? AIE_EFFICIENT : AIE_VERY_EFFICIENT; - } - - // Stay normal if there's any chance of a relevant danger sound - bool bPotentialDanger = false; - - if ( GetSoundInterests() & SOUND_DANGER ) - { - int iSound = CSoundEnt::ActiveList(); - - while ( iSound != SOUNDLIST_EMPTY ) - { - CSound *pCurrentSound = CSoundEnt::SoundPointerForIndex( iSound ); - - float hearingSensitivity = HearingSensitivity(); - Vector vEarPosition = EarPosition(); - - if ( pCurrentSound && (SOUND_DANGER & pCurrentSound->SoundType()) ) - { - float flHearDistanceSq = pCurrentSound->Volume() * hearingSensitivity; - flHearDistanceSq *= flHearDistanceSq; - if ( pCurrentSound->GetSoundOrigin().DistToSqr( vEarPosition ) <= flHearDistanceSq ) - { - bPotentialDanger = true; - break; - } - } - - iSound = pCurrentSound->NextSound(); - } - } - - if ( bPotentialDanger ) - { - SetEfficiency( minEfficiency ); - return; - } - - //--------------------------------- - - if ( !pPlayer ) - { - // No heuristic currently for dedicated servers - SetEfficiency( minEfficiency ); - return; - } - - enum - { - DIST_NEAR, - DIST_MID, - DIST_FAR - }; - - int range; - if ( bInPVS ) - { - if ( playerDist < 15*12 ) - { - SetEfficiency( minEfficiency ); - return; - } - - range = ( playerDist < 50*12 ) ? DIST_NEAR : - ( playerDist < 200*12 ) ? DIST_MID : DIST_FAR; - } - else - { - range = ( playerDist < 25*12 ) ? DIST_NEAR : - ( playerDist < 100*12 ) ? DIST_MID : DIST_FAR; - } - - // Efficiency mappings - int state = GetState(); - if (state == NPC_STATE_SCRIPT ) // Treat script as alert. Already confirmed not in PVS - state = NPC_STATE_ALERT; - - static AI_Efficiency_t mappings[] = - { - // Idle - // In PVS - // Facing - AIE_NORMAL, - AIE_EFFICIENT, - AIE_EFFICIENT, - // Not facing - AIE_EFFICIENT, - AIE_EFFICIENT, - AIE_VERY_EFFICIENT, - // Not in PVS - AIE_VERY_EFFICIENT, - AIE_SUPER_EFFICIENT, - AIE_SUPER_EFFICIENT, - // Alert - // In PVS - // Facing - AIE_NORMAL, - AIE_EFFICIENT, - AIE_EFFICIENT, - // Not facing - AIE_NORMAL, - AIE_EFFICIENT, - AIE_EFFICIENT, - // Not in PVS - AIE_EFFICIENT, - AIE_VERY_EFFICIENT, - AIE_SUPER_EFFICIENT, - // Combat - // In PVS - // Facing - AIE_NORMAL, - AIE_NORMAL, - AIE_EFFICIENT, - // Not facing - AIE_NORMAL, - AIE_EFFICIENT, - AIE_EFFICIENT, - // Not in PVS - AIE_NORMAL, - AIE_EFFICIENT, - AIE_VERY_EFFICIENT, - }; - - static const int stateBase[] = { 0, 9, 18 }; - const int NOT_FACING_OFFSET = 3; - const int NO_PVS_OFFSET = 6; - - int iStateOffset = stateBase[state - NPC_STATE_IDLE] ; - int iFacingOffset = (!bInPVS || bPlayerFacing) ? 0 : NOT_FACING_OFFSET; - int iPVSOffset = (bInPVS) ? 0 : NO_PVS_OFFSET; - int iMapping = iStateOffset + iPVSOffset + iFacingOffset + range; - - Assert( iMapping < (int)ARRAYSIZE( mappings ) ); - - AI_Efficiency_t efficiency = mappings[iMapping]; - - //--------------------------------- - - AI_Efficiency_t maxEfficiency = AIE_SUPER_EFFICIENT; - if ( bInVisibilityPVS && state >= NPC_STATE_ALERT ) - { - maxEfficiency = AIE_EFFICIENT; - } - else if ( bInVisibilityPVS || HasCondition( COND_SEE_PLAYER ) ) - { - maxEfficiency = AIE_VERY_EFFICIENT; - } - - //--------------------------------- - - SetEfficiency( clamp( efficiency, minEfficiency, maxEfficiency ) ); -} - - -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::UpdateSleepState( bool bInPVS ) -{ - if ( GetSleepState() > AISS_AWAKE ) - { - CBasePlayer *pLocalPlayer = AI_GetSinglePlayer(); - if ( !pLocalPlayer ) - { - if ( gpGlobals->maxClients > 1 ) - { - Wake(); - } - else - { - Warning( "CAI_BaseNPC::UpdateSleepState called with NULL pLocalPlayer\n" ); - } - return; - } - - if ( m_flWakeRadius > .1 && !(pLocalPlayer->GetFlags() & FL_NOTARGET) && ( pLocalPlayer->GetAbsOrigin() - GetAbsOrigin() ).LengthSqr() <= Square(m_flWakeRadius) ) - Wake(); - else if ( GetSleepState() == AISS_WAITING_FOR_PVS ) - { - if ( bInPVS ) - Wake(); - } - else if ( GetSleepState() == AISS_WAITING_FOR_THREAT ) - { - if ( HasCondition( COND_LIGHT_DAMAGE ) || HasCondition( COND_HEAVY_DAMAGE ) ) - Wake(); - else - { - if ( bInPVS ) - { - for (int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - if ( pPlayer && !(pPlayer->GetFlags() & FL_NOTARGET) && pPlayer->FVisible( this ) ) - Wake(); - } - } - - // Should check for visible danger sounds - if ( (GetSoundInterests() & SOUND_DANGER) && !(HasSpawnFlags(SF_NPC_WAIT_TILL_SEEN)) ) - { - int iSound = CSoundEnt::ActiveList(); - - while ( iSound != SOUNDLIST_EMPTY ) - { - CSound *pCurrentSound = CSoundEnt::SoundPointerForIndex( iSound ); - Assert( pCurrentSound ); - - if ( (pCurrentSound->SoundType() & SOUND_DANGER) && - GetSenses()->CanHearSound( pCurrentSound ) && - SoundIsVisible( pCurrentSound )) - { - Wake(); - break; - } - - iSound = pCurrentSound->NextSound(); - } - } - } - } - } - else - { - // NPC is awake - // Don't let an NPC sleep if they're running a script! - if( !IsInAScript() && m_NPCState != NPC_STATE_SCRIPT ) - { - if( HasSleepFlags(AI_SLEEP_FLAG_AUTO_PVS) ) - { - if( !HasCondition(COND_IN_PVS) ) - { - SetSleepState( AISS_WAITING_FOR_PVS ); - Sleep(); - } - } - if( HasSleepFlags(AI_SLEEP_FLAG_AUTO_PVS_AFTER_PVS) ) - { - if( HasCondition(COND_IN_PVS) ) - { - // OK, we're in the player's PVS. Now switch to regular old AUTO_PVS sleep rules. - AddSleepFlags(AI_SLEEP_FLAG_AUTO_PVS); - RemoveSleepFlags(AI_SLEEP_FLAG_AUTO_PVS_AFTER_PVS); - } - } - } - } -} - -//----------------------------------------------------------------------------- - -struct AIRebalanceInfo_t -{ - CAI_BaseNPC * pNPC; - int iNextThinkTick; - bool bInPVS; - float dotPlayer; - float distPlayer; -}; - -int __cdecl ThinkRebalanceCompare( const AIRebalanceInfo_t *pLeft, const AIRebalanceInfo_t *pRight ) -{ - int base = pLeft->iNextThinkTick - pRight->iNextThinkTick; - if ( base != 0 ) - return base; - - if ( !pLeft->bInPVS && !pRight->bInPVS ) - return 0; - - if ( !pLeft->bInPVS ) - return 1; - - if ( !pRight->bInPVS ) - return -1; - - if ( pLeft->dotPlayer < 0 && pRight->dotPlayer < 0 ) - return 0; - - if ( pLeft->dotPlayer < 0 ) - return 1; - - if ( pRight->dotPlayer < 0 ) - return -1; - - const float NEAR_PLAYER = 50*12; - - if ( pLeft->distPlayer < NEAR_PLAYER && pRight->distPlayer >= NEAR_PLAYER ) - return -1; - - if ( pRight->distPlayer < NEAR_PLAYER && pLeft->distPlayer >= NEAR_PLAYER ) - return 1; - - if ( pLeft->dotPlayer > pRight->dotPlayer ) - return -1; - - if ( pLeft->dotPlayer < pRight->dotPlayer ) - return 1; - - return 0; -} - -inline bool CAI_BaseNPC::CanThinkRebalance() -{ - if ( m_pfnThink != (BASEPTR)&CAI_BaseNPC::CallNPCThink ) - { - return false; - } - - if ( m_bInChoreo ) - { - return false; - } - - if ( m_NPCState == NPC_STATE_DEAD ) - { - return false; - } - - if ( GetSleepState() != AISS_AWAKE ) - { - return false; - } - - if ( !m_bUsingStandardThinkTime /*&& m_iFrameBlocked == -1 */ ) - { - return false; - } - - return true; -} - -void CAI_BaseNPC::RebalanceThinks() -{ - bool bDebugThinkTicks = ai_debug_think_ticks.GetBool(); - if ( bDebugThinkTicks ) - { - static int iPrevTick; - static int nThinksInTick; - static int nRebalanceableThinksInTick; - - if ( gpGlobals->tickcount != iPrevTick ) - { - DevMsg( "NPC per tick is %d [%d] (tick %d, frame %d)\n", nRebalanceableThinksInTick, nThinksInTick, iPrevTick, gpGlobals->framecount ); - iPrevTick = gpGlobals->tickcount; - nThinksInTick = 0; - nRebalanceableThinksInTick = 0; - } - nThinksInTick++; - if ( CanThinkRebalance() ) - nRebalanceableThinksInTick++; - } - - if ( ShouldRebalanceThinks() && gpGlobals->tickcount >= gm_iNextThinkRebalanceTick ) - { - AI_PROFILE_SCOPE(AI_Think_Rebalance ); - - static CUtlVector rebalanceCandidates( 16, 64 ); - gm_iNextThinkRebalanceTick = gpGlobals->tickcount + TIME_TO_TICKS( random->RandomFloat( 3, 5) ); - - int i; - - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - Vector vPlayerForward; - Vector vPlayerEyePosition; - - vPlayerForward.Init(); - vPlayerEyePosition.Init(); - - if ( pPlayer ) - { - pPlayer->EyePositionAndVectors( &vPlayerEyePosition, &vPlayerForward, NULL, NULL ); - } - - int iTicksPer10Hz = TIME_TO_TICKS( .1 ); - int iMinTickRebalance = gpGlobals->tickcount - 1; // -1 needed for alternate ticks - int iMaxTickRebalance = gpGlobals->tickcount + iTicksPer10Hz; - - for ( i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - CAI_BaseNPC *pCandidate = g_AI_Manager.AccessAIs()[i]; - if ( pCandidate->CanThinkRebalance() && - ( pCandidate->GetNextThinkTick() >= iMinTickRebalance && - pCandidate->GetNextThinkTick() < iMaxTickRebalance ) ) - { - int iInfo = rebalanceCandidates.AddToTail(); - - rebalanceCandidates[iInfo].pNPC = pCandidate; - rebalanceCandidates[iInfo].iNextThinkTick = pCandidate->GetNextThinkTick(); - - if ( pCandidate->IsFlaggedEfficient() ) - { - rebalanceCandidates[iInfo].bInPVS = false; - } - else if ( pPlayer ) - { - Vector vToCandidate = pCandidate->EyePosition() - vPlayerEyePosition; - rebalanceCandidates[iInfo].bInPVS = ( UTIL_FindClientInPVS( pCandidate->edict() ) != NULL ); - rebalanceCandidates[iInfo].distPlayer = VectorNormalize( vToCandidate ); - rebalanceCandidates[iInfo].dotPlayer = vPlayerForward.Dot( vToCandidate ); - } - else - { - rebalanceCandidates[iInfo].bInPVS = true; - rebalanceCandidates[iInfo].dotPlayer = 1; - rebalanceCandidates[iInfo].distPlayer = 0; - } - } - else if ( bDebugThinkTicks ) - DevMsg( " Ignoring %d\n", pCandidate->GetNextThinkTick() ); - } - - if ( rebalanceCandidates.Count() ) - { - rebalanceCandidates.Sort( ThinkRebalanceCompare ); - - int iMaxThinkersPerTick = (int)ceil( (float)((rebalanceCandidates.Count() + 1) / iTicksPer10Hz) ); // +1 to account for "this" - - int iCurTickDistributing = MIN( gpGlobals->tickcount, rebalanceCandidates[0].iNextThinkTick ); - int iRemainingThinksToDistribute = iMaxThinkersPerTick - 1; // Start with one fewer first time because "this" is - // always gets a slot in the current tick to avoid complications - // in the calculation of "last think" - - if ( bDebugThinkTicks ) - { - DevMsg( "Rebalance %d!\n", rebalanceCandidates.Count() + 1 ); - DevMsg( " Distributing %d\n", iCurTickDistributing ); - } - - for ( i = 0; i < rebalanceCandidates.Count(); i++ ) - { - if ( iRemainingThinksToDistribute == 0 || rebalanceCandidates[i].iNextThinkTick > iCurTickDistributing ) - { - if ( rebalanceCandidates[i].iNextThinkTick <= iCurTickDistributing ) - { - iCurTickDistributing = iCurTickDistributing + 1; - } - else - { - iCurTickDistributing = rebalanceCandidates[i].iNextThinkTick; - } - - if ( bDebugThinkTicks ) - DevMsg( " Distributing %d\n", iCurTickDistributing ); - - iRemainingThinksToDistribute = iMaxThinkersPerTick; - } - - if ( rebalanceCandidates[i].pNPC->GetNextThinkTick() != iCurTickDistributing ) - { - if ( bDebugThinkTicks ) - DevMsg( " Bumping %d to %d\n", rebalanceCandidates[i].pNPC->GetNextThinkTick(), iCurTickDistributing ); - - rebalanceCandidates[i].pNPC->SetNextThink( TICKS_TO_TIME( iCurTickDistributing ) ); - } - else if ( bDebugThinkTicks ) - { - DevMsg( " Leaving %d\n", rebalanceCandidates[i].pNPC->GetNextThinkTick() ); - } - - iRemainingThinksToDistribute--; - } - } - - rebalanceCandidates.RemoveAll(); - - if ( bDebugThinkTicks ) - { - DevMsg( "New distribution is:\n"); - for ( i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - DevMsg( " %d\n", g_AI_Manager.AccessAIs()[i]->GetNextThinkTick() ); - } - } - - Assert( GetNextThinkTick() == TICK_NEVER_THINK ); // never change this objects tick - } -} - -static float g_NpcTimeThisFrame; -static float g_StartTimeCurThink; - -bool CAI_BaseNPC::PreNPCThink() -{ - static int iPrevFrame = -1; - static float frameTimeLimit = FLT_MAX; - static const ConVar *pHostTimescale; - - if ( frameTimeLimit == FLT_MAX ) - { - pHostTimescale = cvar->FindVar( "host_timescale" ); - } - - bool bUseThinkLimits = ( !m_bInChoreo && ShouldUseFrameThinkLimits() ); - -#ifdef _DEBUG - const float NPC_THINK_LIMIT = 30.0 / 1000.0; -#else - const float NPC_THINK_LIMIT = ( !IsXbox() ) ? (10.0 / 1000.0) : (12.5 / 1000.0); -#endif - - g_StartTimeCurThink = 0; - - if ( bUseThinkLimits && VCRGetMode() == VCR_Disabled ) - { - if ( m_iFrameBlocked == gpGlobals->framecount ) - { - DbgFrameLimitMsg( "Stalled %d (%d)\n", this, gpGlobals->framecount ); - SetNextThink( gpGlobals->curtime ); - return false; - } - else if ( gpGlobals->framecount != iPrevFrame ) - { - DbgFrameLimitMsg( "--- FRAME: %d (%d)\n", this, gpGlobals->framecount ); - float timescale = pHostTimescale->GetFloat(); - if ( timescale < 1 ) - timescale = 1; - - iPrevFrame = gpGlobals->framecount; - frameTimeLimit = NPC_THINK_LIMIT * timescale; - g_NpcTimeThisFrame = 0; - } - else - { - if ( g_NpcTimeThisFrame > NPC_THINK_LIMIT ) - { - float timeSinceLastRealThink = gpGlobals->curtime - m_flLastRealThinkTime; - // Don't bump anyone more that a quarter second - if ( timeSinceLastRealThink <= .25 ) - { - DbgFrameLimitMsg( "Bumped %d (%d)\n", this, gpGlobals->framecount ); - m_iFrameBlocked = gpGlobals->framecount; - SetNextThink( gpGlobals->curtime ); - return false; - } - else - { - DbgFrameLimitMsg( "(Over %d )\n", this ); - } - } - } - - DbgFrameLimitMsg( "Running %d (%d)\n", this, gpGlobals->framecount ); - g_StartTimeCurThink = engine->Time(); - - m_iFrameBlocked = -1; - m_nLastThinkTick = TIME_TO_TICKS( m_flLastRealThinkTime ); - } - - return true; -} - -void CAI_BaseNPC::PostNPCThink( void ) -{ - if ( g_StartTimeCurThink != 0.0 && VCRGetMode() == VCR_Disabled ) - { - g_NpcTimeThisFrame += engine->Time() - g_StartTimeCurThink; - } -} - -void CAI_BaseNPC::CallNPCThink( void ) -{ - RebalanceThinks(); - - //--------------------------------- - - m_bUsingStandardThinkTime = false; - - //--------------------------------- - - if ( !PreNPCThink() ) - { - return; - } - - // reduce cache queries by locking model in memory - MDLCACHE_CRITICAL_SECTION(); - - this->NPCThink(); - - m_flLastRealThinkTime = gpGlobals->curtime; - - PostNPCThink(); -} - -bool NPC_CheckBrushExclude( CBaseEntity *pEntity, CBaseEntity *pBrush ) -{ - CAI_BaseNPC *pNPC = pEntity->MyNPCPointer(); - - if ( pNPC ) - { - return pNPC->GetMoveProbe()->ShouldBrushBeIgnored( pBrush ); - } - - return false; -} - -class CTraceFilterPlayerAvoidance : public CTraceFilterEntitiesOnly -{ -public: - CTraceFilterPlayerAvoidance( const CBaseEntity *pEntity ) { m_pIgnore = pEntity; } - - virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) - { - CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); - - if ( m_pIgnore == pEntity ) - return false; - - if ( pEntity->IsPlayer() ) - return true; - - return false; - } -private: - - const CBaseEntity *m_pIgnore; -}; - -void CAI_BaseNPC::GetPlayerAvoidBounds( Vector *pMins, Vector *pMaxs ) -{ - *pMins = WorldAlignMins(); - *pMaxs = WorldAlignMaxs(); -} - -ConVar ai_debug_avoidancebounds( "ai_debug_avoidancebounds", "0" ); - -void CAI_BaseNPC::SetPlayerAvoidState( void ) -{ - bool bShouldPlayerAvoid = false; - Vector vNothing; - - GetSequenceLinearMotion( GetSequence(), &vNothing ); - bool bIsMoving = ( IsMoving() || ( vNothing != vec3_origin ) ); - - //If we are coming out of a script, check if we are stuck inside the player. - if ( m_bPerformAvoidance || ( ShouldPlayerAvoid() && bIsMoving ) ) - { - trace_t trace; - Vector vMins, vMaxs; - - GetPlayerAvoidBounds( &vMins, &vMaxs ); - - CBasePlayer *pLocalPlayer = AI_GetSinglePlayer(); - - if ( pLocalPlayer ) - { - bShouldPlayerAvoid = IsBoxIntersectingBox( GetAbsOrigin() + vMins, GetAbsOrigin() + vMaxs, - pLocalPlayer->GetAbsOrigin() + pLocalPlayer->WorldAlignMins(), pLocalPlayer->GetAbsOrigin() + pLocalPlayer->WorldAlignMaxs() ); - } - - if ( ai_debug_avoidancebounds.GetBool() ) - { - int iRed = ( bShouldPlayerAvoid == true ) ? 255 : 0; - - NDebugOverlay::Box( GetAbsOrigin(), vMins, vMaxs, iRed, 0, 255, 64, 0.1 ); - } - } - - m_bPlayerAvoidState = ShouldPlayerAvoid(); - m_bPerformAvoidance = bShouldPlayerAvoid; - - if ( GetCollisionGroup() == COLLISION_GROUP_NPC || GetCollisionGroup() == COLLISION_GROUP_NPC_ACTOR ) - { - if ( m_bPerformAvoidance == true ) - { - SetCollisionGroup( COLLISION_GROUP_NPC_ACTOR ); - } - else - { - SetCollisionGroup( COLLISION_GROUP_NPC ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Enables player avoidance when the player's vphysics shadow penetrates our vphysics shadow. This can -// happen when the player is hit by a combine ball, which pushes them into an adjacent npc. Subclasses should -// override this if it causes problems, but in general this will solve cases of the player getting stuck in -// the NPC from being pushed. -//----------------------------------------------------------------------------- -void CAI_BaseNPC::PlayerPenetratingVPhysics( void ) -{ - m_bPerformAvoidance = true; -} - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::CheckPVSCondition() -{ - bool bInPVS = ( UTIL_FindClientInPVS( edict() ) != NULL ) || (UTIL_ClientPVSIsExpanded() && UTIL_FindClientInVisibilityPVS( edict() )); - - if ( bInPVS ) - SetCondition( COND_IN_PVS ); - else - ClearCondition( COND_IN_PVS ); - - return bInPVS; -} - - -//----------------------------------------------------------------------------- -// NPC Think - calls out to core AI functions and handles this -// npc's specific animation events -// - -void CAI_BaseNPC::NPCThink( void ) -{ - if ( m_bCheckContacts ) - { - CheckPhysicsContacts(); - } - - Assert( !(m_NPCState == NPC_STATE_DEAD && m_lifeState == LIFE_ALIVE) ); - - //--------------------------------- - - SetNextThink( TICK_NEVER_THINK ); - - //--------------------------------- - - bool bInPVS = CheckPVSCondition(); - - //--------------------------------- - - UpdateSleepState( bInPVS ); - - //--------------------------------- - bool bRanDecision = false; - - if ( GetEfficiency() < AIE_DORMANT && GetSleepState() == AISS_AWAKE ) - { - static CFastTimer timer; - float thinkLimit = ai_show_think_tolerance.GetFloat(); - - if ( thinkLimit > 0 ) - timer.Start(); - - if ( g_pAINetworkManager && g_pAINetworkManager->IsInitialized() ) - { - VPROF_BUDGET( "NPCs", VPROF_BUDGETGROUP_NPCS ); - - AI_PROFILE_SCOPE_BEGIN_( GetClassScheduleIdSpace()->GetClassName() ); // need to use a string stable from map load to map load - - SetPlayerAvoidState(); - - if ( PreThink() ) - { - if ( m_flNextDecisionTime <= gpGlobals->curtime ) - { - bRanDecision = true; - m_ScheduleState.bTaskRanAutomovement = false; - m_ScheduleState.bTaskUpdatedYaw = false; - RunAI(); - } - else - { - if ( m_ScheduleState.bTaskRanAutomovement ) - AutoMovement(); - if ( m_ScheduleState.bTaskUpdatedYaw ) - GetMotor()->UpdateYaw(); - } - - PostRun(); - - PerformMovement(); - - m_bIsMoving = IsMoving(); - - PostMovement(); - - SetSimulationTime( gpGlobals->curtime ); - } - else - m_flTimeLastMovement = FLT_MAX; - - AI_PROFILE_SCOPE_END(); - } - - if ( thinkLimit > 0 ) - { - timer.End(); - - float thinkTime = g_AIRunTimer.GetDuration().GetMillisecondsF(); - - if ( thinkTime > thinkLimit ) - { - int color = (int)RemapVal( thinkTime, thinkLimit, thinkLimit * 3, 96.0, 255.0 ); - if ( color > 255 ) - color = 255; - else if ( color < 96 ) - color = 96; - - Vector right; - Vector vecPoint; - - vecPoint = EyePosition() + Vector( 0, 0, 12 ); - GetVectors( NULL, &right, NULL ); - NDebugOverlay::Line( vecPoint, vecPoint + Vector( 0, 0, 64 ), color, 0, 0, false , 1.0 ); - NDebugOverlay::Line( vecPoint, vecPoint + Vector( 0, 0, 16 ) + right * 16, color, 0, 0, false , 1.0 ); - NDebugOverlay::Line( vecPoint, vecPoint + Vector( 0, 0, 16 ) - right * 16, color, 0, 0, false , 1.0 ); - } - } - } - - m_bUsingStandardThinkTime = ( GetNextThinkTick() == TICK_NEVER_THINK ); - - UpdateEfficiency( bInPVS ); - - if ( m_bUsingStandardThinkTime ) - { - static const char *ppszEfficiencies[] = - { - "AIE_NORMAL", - "AIE_EFFICIENT", - "AIE_VERY_EFFICIENT", - "AIE_SUPER_EFFICIENT", - "AIE_DORMANT", - }; - - static const char *ppszMoveEfficiencies[] = - { - "AIME_NORMAL", - "AIME_EFFICIENT", - }; - - if ( ai_debug_efficiency.GetBool() ) - DevMsg( this, "Eff: %s, Move: %s\n", ppszEfficiencies[GetEfficiency()], ppszMoveEfficiencies[GetMoveEfficiency()] ); - - static float g_DecisionIntervals[] = - { - .1, // AIE_NORMAL - .2, // AIE_EFFICIENT - .4, // AIE_VERY_EFFICIENT - .6, // AIE_SUPER_EFFICIENT - }; - - if ( bRanDecision ) - { - m_flNextDecisionTime = gpGlobals->curtime + g_DecisionIntervals[GetEfficiency()]; - } - - if ( GetMoveEfficiency() == AIME_NORMAL || GetEfficiency() == AIE_NORMAL ) - { - SetNextThink( gpGlobals->curtime + .1 ); - } - else - { - SetNextThink( gpGlobals->curtime + .2 ); - } - } - else - { - m_flNextDecisionTime = 0; - } -} - -//========================================================= -// CAI_BaseNPC - USE - will make a npc angry at whomever -// activated it. -//========================================================= -void CAI_BaseNPC::NPCUse ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - return; - - // Can't +USE NPCs running scripts - if ( GetState() == NPC_STATE_SCRIPT ) - return; - - if ( IsInAScript() ) - return; - - SetIdealState( NPC_STATE_ALERT ); -} - -//----------------------------------------------------------------------------- -// Purpose: Virtual function that allows us to have any npc ignore a set of -// shared conditions. -// -//----------------------------------------------------------------------------- -void CAI_BaseNPC::RemoveIgnoredConditions( void ) -{ - m_ConditionsPreIgnore = m_Conditions; - m_Conditions.And( m_InverseIgnoreConditions, &m_Conditions ); - - if ( m_NPCState == NPC_STATE_SCRIPT && m_hCine ) - m_hCine->RemoveIgnoredConditions(); -} - -//========================================================= -// RangeAttack1Conditions -//========================================================= -int CAI_BaseNPC::RangeAttack1Conditions ( float flDot, float flDist ) -{ - if ( flDist < 64) - { - return COND_TOO_CLOSE_TO_ATTACK; - } - else if (flDist > 784) - { - return COND_TOO_FAR_TO_ATTACK; - } - else if (flDot < 0.5) - { - return COND_NOT_FACING_ATTACK; - } - - return COND_CAN_RANGE_ATTACK1; -} - -//========================================================= -// RangeAttack2Conditions -//========================================================= -int CAI_BaseNPC::RangeAttack2Conditions ( float flDot, float flDist ) -{ - if ( flDist < 64) - { - return COND_TOO_CLOSE_TO_ATTACK; - } - else if (flDist > 512) - { - return COND_TOO_FAR_TO_ATTACK; - } - else if (flDot < 0.5) - { - return COND_NOT_FACING_ATTACK; - } - - return COND_CAN_RANGE_ATTACK2; -} - -//========================================================= -// MeleeAttack1Conditions -//========================================================= -int CAI_BaseNPC::MeleeAttack1Conditions ( float flDot, float flDist ) -{ - if ( flDist > 64) - { - return COND_TOO_FAR_TO_ATTACK; - } - else if (flDot < 0.7) - { - return 0; - } - else if (GetEnemy() == NULL) - { - return 0; - } - - // Decent fix to keep folks from kicking/punching hornets and snarks is to check the onground flag(sjb) - if ( GetEnemy()->GetFlags() & FL_ONGROUND ) - { - return COND_CAN_MELEE_ATTACK1; - } - return 0; -} - -//========================================================= -// MeleeAttack2Conditions -//========================================================= -int CAI_BaseNPC::MeleeAttack2Conditions ( float flDot, float flDist ) -{ - if ( flDist > 64) - { - return COND_TOO_FAR_TO_ATTACK; - } - else if (flDot < 0.7) - { - return 0; - } - return COND_CAN_MELEE_ATTACK2; -} - -// Get capability mask -int CAI_BaseNPC::CapabilitiesGet( void ) const -{ - int capability = m_afCapability; - if ( GetActiveWeapon() ) - { - capability |= GetActiveWeapon()->CapabilitiesGet(); - } - return capability; -} - -// Set capability mask -int CAI_BaseNPC::CapabilitiesAdd( int capability ) -{ - m_afCapability |= capability; - - return m_afCapability; -} - -// Set capability mask -int CAI_BaseNPC::CapabilitiesRemove( int capability ) -{ - m_afCapability &= ~capability; - - return m_afCapability; -} - -// Clear capability mask -void CAI_BaseNPC::CapabilitiesClear( void ) -{ - m_afCapability = 0; -} - - -//========================================================= -// ClearAttacks - clear out all attack conditions -//========================================================= -void CAI_BaseNPC::ClearAttackConditions( ) -{ - // Clear all attack conditions - ClearCondition( COND_CAN_RANGE_ATTACK1 ); - ClearCondition( COND_CAN_RANGE_ATTACK2 ); - ClearCondition( COND_CAN_MELEE_ATTACK1 ); - ClearCondition( COND_CAN_MELEE_ATTACK2 ); - ClearCondition( COND_WEAPON_HAS_LOS ); - ClearCondition( COND_WEAPON_BLOCKED_BY_FRIEND ); - ClearCondition( COND_WEAPON_PLAYER_IN_SPREAD ); // Player in shooting direction - ClearCondition( COND_WEAPON_PLAYER_NEAR_TARGET ); // Player near shooting position - ClearCondition( COND_WEAPON_SIGHT_OCCLUDED ); -} - -//========================================================= -// GatherAttackConditions - sets all of the bits for attacks that the -// npc is capable of carrying out on the passed entity. -//========================================================= - -void CAI_BaseNPC::GatherAttackConditions( CBaseEntity *pTarget, float flDist ) -{ - AI_PROFILE_SCOPE(CAI_BaseNPC_GatherAttackConditions); - - Vector vecLOS = ( pTarget->GetAbsOrigin() - GetAbsOrigin() ); - vecLOS.z = 0; - VectorNormalize( vecLOS ); - - Vector vBodyDir = BodyDirection2D( ); - float flDot = DotProduct( vecLOS, vBodyDir ); - - // we know the enemy is in front now. We'll find which attacks the npc is capable of by - // checking for corresponding Activities in the model file, then do the simple checks to validate - // those attack types. - - int capability; - Vector targetPos; - bool bWeaponHasLOS; - int condition; - - capability = CapabilitiesGet(); - - // Clear all attack conditions - AI_PROFILE_SCOPE_BEGIN( CAI_BaseNPC_GatherAttackConditions_PrimaryWeaponLOS ); - - // @TODO (toml 06-15-03): There are simple cases where - // the upper torso of the enemy is visible, and the NPC is at an angle below - // them, but the above test fails because BodyTarget returns the center of - // the target. This needs some better handling/closer evaluation - - // Try the eyes first, as likely to succeed (because can see or else wouldn't be here) thus reducing - // the odds of the need for a second trace - ClearAttackConditions(); - targetPos = pTarget->EyePosition(); - bWeaponHasLOS = CurrentWeaponLOSCondition( targetPos, true ); - - AI_PROFILE_SCOPE_END(); - - if ( !bWeaponHasLOS ) - { - AI_PROFILE_SCOPE( CAI_BaseNPC_GatherAttackConditions_SecondaryWeaponLOS ); - ClearAttackConditions( ); - targetPos = pTarget->BodyTarget( GetAbsOrigin() ); - bWeaponHasLOS = CurrentWeaponLOSCondition( targetPos, true ); - } - else - { - SetCondition( COND_WEAPON_HAS_LOS ); - } - - bool bWeaponIsReady = (GetActiveWeapon() && !IsWeaponStateChanging()); - - // FIXME: move this out of here - if ( (capability & bits_CAP_WEAPON_RANGE_ATTACK1) && bWeaponIsReady ) - { - AI_PROFILE_SCOPE( CAI_BaseNPC_GatherAttackConditions_WeaponRangeAttack1Condition ); - - condition = GetActiveWeapon()->WeaponRangeAttack1Condition(flDot, flDist); - - if ( condition == COND_NOT_FACING_ATTACK && FInAimCone( targetPos ) ) - DevMsg( "Warning: COND_NOT_FACING_ATTACK set but FInAimCone is true\n" ); - - if (condition != COND_CAN_RANGE_ATTACK1 || bWeaponHasLOS) - { - SetCondition(condition); - } - } - else if ( capability & bits_CAP_INNATE_RANGE_ATTACK1 ) - { - AI_PROFILE_SCOPE( CAI_BaseNPC_GatherAttackConditions_RangeAttack1Condition ); - - condition = RangeAttack1Conditions( flDot, flDist ); - if (condition != COND_CAN_RANGE_ATTACK1 || bWeaponHasLOS) - { - SetCondition(condition); - } - } - - if ( (capability & bits_CAP_WEAPON_RANGE_ATTACK2) && bWeaponIsReady && ( GetActiveWeapon()->CapabilitiesGet() & bits_CAP_WEAPON_RANGE_ATTACK2 ) ) - { - AI_PROFILE_SCOPE( CAI_BaseNPC_GatherAttackConditions_WeaponRangeAttack2Condition ); - - condition = GetActiveWeapon()->WeaponRangeAttack2Condition(flDot, flDist); - if (condition != COND_CAN_RANGE_ATTACK2 || bWeaponHasLOS) - { - SetCondition(condition); - } - } - else if ( capability & bits_CAP_INNATE_RANGE_ATTACK2 ) - { - AI_PROFILE_SCOPE( CAI_BaseNPC_GatherAttackConditions_RangeAttack2Condition ); - - condition = RangeAttack2Conditions( flDot, flDist ); - if (condition != COND_CAN_RANGE_ATTACK2 || bWeaponHasLOS) - { - SetCondition(condition); - } - } - - if ( (capability & bits_CAP_WEAPON_MELEE_ATTACK1) && bWeaponIsReady) - { - AI_PROFILE_SCOPE( CAI_BaseNPC_GatherAttackConditions_WeaponMeleeAttack1Condition ); - SetCondition(GetActiveWeapon()->WeaponMeleeAttack1Condition(flDot, flDist)); - } - else if ( capability & bits_CAP_INNATE_MELEE_ATTACK1 ) - { - AI_PROFILE_SCOPE( CAI_BaseNPC_GatherAttackConditions_MeleeAttack1Condition ); - SetCondition(MeleeAttack1Conditions ( flDot, flDist )); - } - - if ( (capability & bits_CAP_WEAPON_MELEE_ATTACK2) && bWeaponIsReady) - { - AI_PROFILE_SCOPE( CAI_BaseNPC_GatherAttackConditions_WeaponMeleeAttack2Condition ); - SetCondition(GetActiveWeapon()->WeaponMeleeAttack2Condition(flDot, flDist)); - } - else if ( capability & bits_CAP_INNATE_MELEE_ATTACK2 ) - { - AI_PROFILE_SCOPE( CAI_BaseNPC_GatherAttackConditions_MeleeAttack2Condition ); - SetCondition(MeleeAttack2Conditions ( flDot, flDist )); - } - - // ----------------------------------------------------------------- - // If any attacks are possible clear attack specific bits - // ----------------------------------------------------------------- - if (HasCondition(COND_CAN_RANGE_ATTACK2) || - HasCondition(COND_CAN_RANGE_ATTACK1) || - HasCondition(COND_CAN_MELEE_ATTACK2) || - HasCondition(COND_CAN_MELEE_ATTACK1) ) - { - ClearCondition(COND_TOO_CLOSE_TO_ATTACK); - ClearCondition(COND_TOO_FAR_TO_ATTACK); - ClearCondition(COND_WEAPON_BLOCKED_BY_FRIEND); - } -} - - -//========================================================= -// SetState -//========================================================= -void CAI_BaseNPC::SetState( NPC_STATE State ) -{ - NPC_STATE OldState; - - OldState = m_NPCState; - - if ( State != m_NPCState ) - { - m_flLastStateChangeTime = gpGlobals->curtime; - } - - switch( State ) - { - // Drop enemy pointers when going to idle - case NPC_STATE_IDLE: - - if ( GetEnemy() != NULL ) - { - SetEnemy( NULL ); // not allowed to have an enemy anymore. - DevMsg( 2, "Stripped\n" ); - } - break; - default: - break; - } - - bool fNotifyChange = false; - - if( m_NPCState != State ) - { - // Don't notify if we're changing to a state we're already in! - fNotifyChange = true; - } - - m_NPCState = State; - SetIdealState( State ); - - // Notify the character that its state has changed. - if( fNotifyChange ) - { - OnStateChange( OldState, m_NPCState ); - } -} - -bool CAI_BaseNPC::WokeThisTick() const -{ - return m_nWakeTick == gpGlobals->tickcount ? true : false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_BaseNPC::Wake( bool bFireOutput ) -{ - if ( GetSleepState() != AISS_AWAKE ) - { - m_nWakeTick = gpGlobals->tickcount; - SetSleepState( AISS_AWAKE ); - RemoveEffects( EF_NODRAW ); - if ( bFireOutput ) - m_OnWake.FireOutput( this, this ); - - if ( m_bWakeSquad && GetSquad() ) - { - AISquadIter_t iter; - for ( CAI_BaseNPC *pSquadMember = GetSquad()->GetFirstMember( &iter ); pSquadMember; pSquadMember = GetSquad()->GetNextMember( &iter ) ) - { - if ( pSquadMember->IsAlive() && pSquadMember != this ) - { - pSquadMember->m_bWakeSquad = false; - pSquadMember->Wake(); - } - } - - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_BaseNPC::Sleep() -{ - // Don't render. - AddEffects( EF_NODRAW ); - - if( GetState() == NPC_STATE_SCRIPT ) - { - Warning( "%s put to sleep while in Scripted state!\n"); - } - - VacateStrategySlot(); - - // Slam my schedule. - SetSchedule( SCHED_SLEEP ); - - m_OnSleep.FireOutput( this, this ); -} - -//----------------------------------------------------------------------------- -// Sets all sensing-related conditions -//----------------------------------------------------------------------------- -void CAI_BaseNPC::PerformSensing( void ) -{ - GetSenses()->PerformSensing(); -} - - -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::ClearSenseConditions( void ) -{ - static int conditionsToClear[] = - { - COND_SEE_HATE, - COND_SEE_DISLIKE, - COND_SEE_ENEMY, - COND_SEE_FEAR, - COND_SEE_NEMESIS, - COND_SEE_PLAYER, - COND_HEAR_DANGER, - COND_HEAR_COMBAT, - COND_HEAR_WORLD, - COND_HEAR_PLAYER, - COND_HEAR_THUMPER, - COND_HEAR_BUGBAIT, - COND_HEAR_PHYSICS_DANGER, - COND_HEAR_MOVE_AWAY, - COND_SMELL, - }; - - ClearConditions( conditionsToClear, ARRAYSIZE( conditionsToClear ) ); -} - -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::CheckOnGround( void ) -{ - bool bScriptedWait = ( IsCurSchedule( SCHED_WAIT_FOR_SCRIPT ) || ( m_hCine && m_scriptState == CAI_BaseNPC::SCRIPT_WAIT ) ); - if ( !bScriptedWait && !HasCondition( COND_FLOATING_OFF_GROUND ) ) - { - // parented objects are never floating - if (GetMoveParent() != NULL) - return; - - // NPCs in scripts with the fly flag shouldn't fall. - // FIXME: should NPCS with FL_FLY ever fall? Doesn't seem like they should. - if ( ( GetState() == NPC_STATE_SCRIPT ) && ( GetFlags() & FL_FLY ) ) - return; - - if ( ( GetNavType() == NAV_GROUND ) && ( GetMoveType() != MOVETYPE_VPHYSICS ) && ( GetMoveType() != MOVETYPE_NONE ) ) - { - if ( m_CheckOnGroundTimer.Expired() ) - { - m_CheckOnGroundTimer.Set(0.5); - - // check a shrunk box centered around the foot - Vector maxs = WorldAlignMaxs(); - Vector mins = WorldAlignMins(); - - if ( mins != maxs ) // some NPCs have no hull, so mins == maxs == vec3_origin - { - maxs -= Vector( 0.0f, 0.0f, 0.2f ); - - Vector vecStart = GetAbsOrigin() + Vector( 0, 0, .1f ); - Vector vecDown = GetAbsOrigin(); - vecDown.z -= 4.0; - - trace_t trace; - m_pMoveProbe->TraceHull( vecStart, vecDown, mins, maxs, MASK_NPCSOLID, &trace ); - - if (trace.fraction == 1.0) - { - SetCondition( COND_FLOATING_OFF_GROUND ); - SetGroundEntity( NULL ); - } - else - { - if ( trace.startsolid && trace.m_pEnt->GetMoveType() == MOVETYPE_VPHYSICS && - trace.m_pEnt->VPhysicsGetObject() && trace.m_pEnt->VPhysicsGetObject()->GetMass() < VPHYSICS_LARGE_OBJECT_MASS ) - { - // stuck inside a small physics object? - m_CheckOnGroundTimer.Set(0.1f); - NPCPhysics_CreateSolver( this, trace.m_pEnt, true, 0.25f ); - if ( VPhysicsGetObject() ) - { - VPhysicsGetObject()->RecheckContactPoints(); - } - } - // Check to see if someone changed the ground on us... - if ( trace.m_pEnt && trace.m_pEnt != GetGroundEntity() ) - { - SetGroundEntity( trace.m_pEnt ); - } - } - } - } - } - } - else - { - // parented objects are never floating - if ( bScriptedWait || GetMoveParent() != NULL || (GetFlags() & FL_ONGROUND ) || GetNavType() != NAV_GROUND ) - { - ClearCondition( COND_FLOATING_OFF_GROUND ); - } - } - -} - -void CAI_BaseNPC::NotifyPushMove() -{ - // don't recheck ground when I'm being push-moved - m_CheckOnGroundTimer.Set( 0.5f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::CanFlinch( void ) -{ - if ( IsCurSchedule( SCHED_BIG_FLINCH ) ) - return false; - - if ( m_flNextFlinchTime >= gpGlobals->curtime ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::CheckFlinches( void ) -{ - // If we're currently flinching, don't allow gesture flinches to be overlaid - if ( IsCurSchedule( SCHED_BIG_FLINCH ) ) - { - ClearCondition( COND_LIGHT_DAMAGE ); - ClearCondition( COND_HEAVY_DAMAGE ); - } - - // If we've taken heavy damage, try to do a full schedule flinch - if ( HasCondition(COND_HEAVY_DAMAGE) ) - { - // If we've already flinched recently, gesture flinch instead. - if ( HasMemory(bits_MEMORY_FLINCHED) ) - { - // Clear the heavy damage condition so we don't interrupt schedules - // when we play a gesture flinch because we recently did a full flinch. - // Prevents the player from stun-locking enemies, even though they don't full flinch. - ClearCondition( COND_HEAVY_DAMAGE ); - } - else if ( !HasInterruptCondition(COND_HEAVY_DAMAGE) ) - { - // If we have taken heavy damage, but the current schedule doesn't - // break on that, resort to just playing a gesture flinch. - PlayFlinchGesture(); - } - - // Otherwise, do nothing. The heavy damage will interrupt our schedule and we'll flinch. - } - else if ( HasCondition( COND_LIGHT_DAMAGE ) ) - { - // If we have taken light damage play gesture flinches - PlayFlinchGesture(); - } - - // If it's been a while since we did a full flinch, forget that we flinched so we'll flinch fully again - if ( HasMemory(bits_MEMORY_FLINCHED) && gpGlobals->curtime > m_flNextFlinchTime ) - { - Forget(bits_MEMORY_FLINCHED); - } -} - -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::GatherConditions( void ) -{ - m_bConditionsGathered = true; - g_AIConditionsTimer.Start(); - - if( gpGlobals->curtime > m_flTimePingEffect && m_flTimePingEffect > 0.0f ) - { - // Turn off the pinging. - DispatchUpdateTransmitState(); - m_flTimePingEffect = 0.0f; - } - - if ( m_NPCState != NPC_STATE_NONE && m_NPCState != NPC_STATE_DEAD ) - { - if ( FacingIdeal() ) - Forget( bits_MEMORY_TURNING ); - - bool bForcedGather = m_bForceConditionsGather; - m_bForceConditionsGather = false; - - if ( m_pfnThink != (BASEPTR)&CAI_BaseNPC::CallNPCThink ) - { - if ( UTIL_FindClientInPVS( edict() ) != NULL ) - SetCondition( COND_IN_PVS ); - else - ClearCondition( COND_IN_PVS ); - } - - // Sample the environment. Do this unconditionally if there is a player in this - // npc's PVS. NPCs in COMBAT state are allowed to simulate when there is no player in - // the same PVS. This is so that any fights in progress will continue even if the player leaves the PVS. - if ( !IsFlaggedEfficient() && - ( bForcedGather || - HasCondition( COND_IN_PVS ) || - ShouldAlwaysThink() || - m_NPCState == NPC_STATE_COMBAT ) ) - { - CheckOnGround(); - - if ( ShouldPlayIdleSound() ) - { - AI_PROFILE_SCOPE(CAI_BaseNPC_IdleSound); - IdleSound(); - } - - PerformSensing(); - - GetEnemies()->RefreshMemories(); - ChooseEnemy(); - - // Check to see if there is a better weapon available - if (Weapon_IsBetterAvailable()) - { - SetCondition(COND_BETTER_WEAPON_AVAILABLE); - } - - if ( GetCurSchedule() && - ( m_NPCState == NPC_STATE_IDLE || m_NPCState == NPC_STATE_ALERT) && - GetEnemy() && - !HasCondition( COND_NEW_ENEMY ) && - GetCurSchedule()->HasInterrupt( COND_NEW_ENEMY ) ) - { - // @Note (toml 05-05-04): There seems to be a case where an NPC can not respond - // to COND_NEW_ENEMY. Only evidence right now is save - // games after the fact, so for now, just patching it up - DevMsg( 2, "Had to force COND_NEW_ENEMY\n" ); - SetCondition(COND_NEW_ENEMY); - } - } - else - { - // if not done, can have problems if leave PVS in same frame heard/saw things, - // since only PerformSensing clears conditions - ClearSenseConditions(); - } - - // do these calculations if npc has an enemy. - if ( GetEnemy() != NULL ) - { - if ( !IsFlaggedEfficient() ) - { - GatherEnemyConditions( GetEnemy() ); - m_flLastEnemyTime = gpGlobals->curtime; - } - else - { - SetEnemy( NULL ); - } - } - - // do these calculations if npc has a target - if ( GetTarget() != NULL ) - { - CheckTarget( GetTarget() ); - } - - CheckAmmo(); - - CheckFlinches(); - - CheckSquad(); - } - else - ClearCondition( COND_IN_PVS ); - - g_AIConditionsTimer.End(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::PrescheduleThink( void ) -{ -#ifdef HL2_EPISODIC - CheckForScriptedNPCInteractions(); -#endif - - // If we use weapons, and our desired weapon state is not the current, fix it - if( (CapabilitiesGet() & bits_CAP_USE_WEAPONS) && (m_iDesiredWeaponState == DESIREDWEAPONSTATE_HOLSTERED || m_iDesiredWeaponState == DESIREDWEAPONSTATE_UNHOLSTERED || m_iDesiredWeaponState == DESIREDWEAPONSTATE_HOLSTERED_DESTROYED ) ) - { - if ( IsAlive() && !IsInAScript() ) - { - if ( !IsCurSchedule( SCHED_MELEE_ATTACK1, false ) && !IsCurSchedule( SCHED_MELEE_ATTACK2, false ) && - !IsCurSchedule( SCHED_RANGE_ATTACK1, false ) && !IsCurSchedule( SCHED_RANGE_ATTACK2, false ) ) - { - if ( m_iDesiredWeaponState == DESIREDWEAPONSTATE_HOLSTERED || m_iDesiredWeaponState == DESIREDWEAPONSTATE_HOLSTERED_DESTROYED ) - { - HolsterWeapon(); - } - else if ( m_iDesiredWeaponState == DESIREDWEAPONSTATE_UNHOLSTERED ) - { - UnholsterWeapon(); - } - } - } - else - { - // Throw away the request - m_iDesiredWeaponState = DESIREDWEAPONSTATE_IGNORE; - } - } -} - -//----------------------------------------------------------------------------- -// Main entry point for processing AI -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::RunAI( void ) -{ - AI_PROFILE_SCOPE(CAI_BaseNPC_RunAI); - g_AIRunTimer.Start(); - - if( ai_debug_squads.GetBool() ) - { - if( IsInSquad() && GetSquad() && !CAI_Squad::IsSilentMember(this ) && ( GetSquad()->IsLeader( this ) || GetSquad()->NumMembers() == 1 ) ) - { - AISquadIter_t iter; - CAI_Squad *pSquad = GetSquad(); - - Vector right; - Vector vecPoint; - - vecPoint = EyePosition() + Vector( 0, 0, 12 ); - GetVectors( NULL, &right, NULL ); - NDebugOverlay::Line( vecPoint, vecPoint + Vector( 0, 0, 64 ), 0, 255, 0, false , 0.1 ); - NDebugOverlay::Line( vecPoint, vecPoint + Vector( 0, 0, 32 ) + right * 32, 0, 255, 0, false , 0.1 ); - NDebugOverlay::Line( vecPoint, vecPoint + Vector( 0, 0, 32 ) - right * 32, 0, 255, 0, false , 0.1 ); - - for ( CAI_BaseNPC *pSquadMember = pSquad->GetFirstMember( &iter, false ); pSquadMember; pSquadMember = pSquad->GetNextMember( &iter, false ) ) - { - if ( pSquadMember != this ) - NDebugOverlay::Line( EyePosition(), pSquadMember->EyePosition(), 0, - CAI_Squad::IsSilentMember(pSquadMember) ? 127 : 255, 0, false , 0.1 ); - } - } - } - - if( ai_debug_loners.GetBool() && !IsInSquad() && AI_IsSinglePlayer() ) - { - Vector right; - Vector vecPoint; - - vecPoint = EyePosition() + Vector( 0, 0, 12 ); - - UTIL_GetLocalPlayer()->GetVectors( NULL, &right, NULL ); - - NDebugOverlay::Line( vecPoint, vecPoint + Vector( 0, 0, 64 ), 255, 0, 0, false , 0.1 ); - NDebugOverlay::Line( vecPoint, vecPoint + Vector( 0, 0, 32 ) + right * 32, 255, 0, 0, false , 0.1 ); - NDebugOverlay::Line( vecPoint, vecPoint + Vector( 0, 0, 32 ) - right * 32, 255, 0, 0, false , 0.1 ); - } - -#ifdef _DEBUG - m_bSelected = ( (m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) != 0 ); -#endif - - m_bConditionsGathered = false; - m_bSkippedChooseEnemy = false; - - if ( g_pDeveloper->GetInt() && !GetNavigator()->IsOnNetwork() ) - { - AddTimedOverlay( "NPC w/no reachable nodes!", 5 ); - } - - AI_PROFILE_SCOPE_BEGIN(CAI_BaseNPC_RunAI_GatherConditions); - GatherConditions(); - RemoveIgnoredConditions(); - AI_PROFILE_SCOPE_END(); - - if ( !m_bConditionsGathered ) - m_bConditionsGathered = true; // derived class didn't call to base - - TryRestoreHull(); - - g_AIPrescheduleThinkTimer.Start(); - - AI_PROFILE_SCOPE_BEGIN(CAI_RunAI_PrescheduleThink); - PrescheduleThink(); - AI_PROFILE_SCOPE_END(); - - g_AIPrescheduleThinkTimer.End(); - - MaintainSchedule(); - - PostscheduleThink(); - - ClearTransientConditions(); - - g_AIRunTimer.End(); -} - -//----------------------------------------------------------------------------- -void CAI_BaseNPC::ClearTransientConditions() -{ - // if the npc didn't use these conditions during the above call to MaintainSchedule() - // we throw them out cause we don't want them sitting around through the lifespan of a schedule - // that doesn't use them. - ClearCondition( COND_LIGHT_DAMAGE ); - ClearCondition( COND_HEAVY_DAMAGE ); - ClearCondition( COND_PHYSICS_DAMAGE ); - ClearCondition( COND_PLAYER_PUSHING ); -} - - -//----------------------------------------------------------------------------- -// Selecting the idle ideal state -//----------------------------------------------------------------------------- -NPC_STATE CAI_BaseNPC::SelectIdleIdealState() -{ - // IDLE goes to ALERT upon hearing a sound - // IDLE goes to ALERT upon being injured - // IDLE goes to ALERT upon seeing food - // IDLE goes to COMBAT upon sighting an enemy - if ( HasCondition(COND_NEW_ENEMY) || - HasCondition(COND_SEE_ENEMY) ) - { - // new enemy! This means an idle npc has seen someone it dislikes, or - // that a npc in combat has found a more suitable target to attack - return NPC_STATE_COMBAT; - } - - // Set our ideal yaw if we've taken damage - if ( HasCondition(COND_LIGHT_DAMAGE) || - HasCondition(COND_HEAVY_DAMAGE) || - (!GetEnemy() && gpGlobals->curtime - GetEnemies()->LastTimeSeen( AI_UNKNOWN_ENEMY ) < TIME_CARE_ABOUT_DAMAGE ) ) - { - Vector vecEnemyLKP; - - // Fill in where we're trying to look - if ( GetEnemy() ) - { - vecEnemyLKP = GetEnemyLKP(); - } - else - { - if ( GetEnemies()->Find( AI_UNKNOWN_ENEMY ) ) - { - vecEnemyLKP = GetEnemies()->LastKnownPosition( AI_UNKNOWN_ENEMY ); - } - else - { - // Don't have an enemy, so face the direction the last attack came from (don't face north) - vecEnemyLKP = WorldSpaceCenter() + ( g_vecAttackDir * 128 ); - } - } - - // Set the ideal - GetMotor()->SetIdealYawToTarget( vecEnemyLKP ); - - return NPC_STATE_ALERT; - } - - if ( HasCondition(COND_HEAR_DANGER) || - HasCondition(COND_HEAR_COMBAT) || - HasCondition(COND_HEAR_WORLD) || - HasCondition(COND_HEAR_PLAYER) || - HasCondition(COND_HEAR_THUMPER) || - HasCondition(COND_HEAR_BULLET_IMPACT) ) - { - // Interrupted by a sound. So make our ideal yaw the - // source of the sound! - CSound *pSound; - - pSound = GetBestSound(); - Assert( pSound != NULL ); - if ( pSound ) - { - // BRJ 1/7/04: This code used to set the ideal yaw. - // It's really side-effecty to set the yaw here. - // That is now done by the FACE_BESTSOUND schedule. - // Revert this change if it causes problems. - GetMotor()->SetIdealYawToTarget( pSound->GetSoundReactOrigin() ); - if ( pSound->IsSoundType( SOUND_COMBAT | SOUND_DANGER | SOUND_BULLET_IMPACT ) ) - { - return NPC_STATE_ALERT; - } - } - } - - if ( HasInterruptCondition(COND_SMELL) ) - { - return NPC_STATE_ALERT; - } - - return NPC_STATE_INVALID; -} - - -//----------------------------------------------------------------------------- -// Selecting the alert ideal state -//----------------------------------------------------------------------------- -NPC_STATE CAI_BaseNPC::SelectAlertIdealState() -{ - // ALERT goes to IDLE upon becoming bored - // ALERT goes to COMBAT upon sighting an enemy - if ( HasCondition(COND_NEW_ENEMY) || - HasCondition(COND_SEE_ENEMY) || - GetEnemy() != NULL ) - { - return NPC_STATE_COMBAT; - } - - // Set our ideal yaw if we've taken damage - if ( HasCondition(COND_LIGHT_DAMAGE) || - HasCondition(COND_HEAVY_DAMAGE) || - (!GetEnemy() && gpGlobals->curtime - GetEnemies()->LastTimeSeen( AI_UNKNOWN_ENEMY ) < TIME_CARE_ABOUT_DAMAGE ) ) - { - Vector vecEnemyLKP; - - // Fill in where we're trying to look - if ( GetEnemy() ) - { - vecEnemyLKP = GetEnemyLKP(); - } - else - { - if ( GetEnemies()->Find( AI_UNKNOWN_ENEMY ) ) - { - vecEnemyLKP = GetEnemies()->LastKnownPosition( AI_UNKNOWN_ENEMY ); - } - else - { - // Don't have an enemy, so face the direction the last attack came from (don't face north) - vecEnemyLKP = WorldSpaceCenter() + ( g_vecAttackDir * 128 ); - } - } - - // Set the ideal - GetMotor()->SetIdealYawToTarget( vecEnemyLKP ); - - return NPC_STATE_ALERT; - } - - if ( HasCondition(COND_HEAR_DANGER) || - HasCondition(COND_HEAR_COMBAT) ) - { - CSound *pSound = GetBestSound(); - AssertOnce( pSound != NULL ); - - if ( pSound ) - { - GetMotor()->SetIdealYawToTarget( pSound->GetSoundReactOrigin() ); - } - - return NPC_STATE_ALERT; - } - - if ( ShouldGoToIdleState() ) - { - return NPC_STATE_IDLE; - } - - return NPC_STATE_INVALID; -} - - -//----------------------------------------------------------------------------- -// Selecting the alert ideal state -//----------------------------------------------------------------------------- -NPC_STATE CAI_BaseNPC::SelectScriptIdealState() -{ - if ( HasCondition(COND_TASK_FAILED) || - HasCondition(COND_LIGHT_DAMAGE) || - HasCondition(COND_HEAVY_DAMAGE) ) - { - ExitScriptedSequence(); // This will set the ideal state - } - - if ( m_IdealNPCState == NPC_STATE_IDLE ) - { - // Exiting a script. Select the ideal state assuming we were idle now. - m_NPCState = NPC_STATE_IDLE; - NPC_STATE eIdealState = SelectIdealState(); - m_NPCState = NPC_STATE_SCRIPT; - return eIdealState; - } - - return NPC_STATE_INVALID; -} - - -//----------------------------------------------------------------------------- -// Purpose: Surveys the Conditions information available and finds the best -// new state for a npc. -// -// NOTICE the CAI_BaseNPC implementation of this function does not care about -// private conditions! -// -// Output : NPC_STATE - the suggested ideal state based on current conditions. -//----------------------------------------------------------------------------- -NPC_STATE CAI_BaseNPC::SelectIdealState( void ) -{ - // dvs: FIXME: lots of side effecty code in here!! this function should ONLY return an ideal state! - - // --------------------------- - // Do some squad stuff first - // --------------------------- - if (m_pSquad) - { - switch( m_NPCState ) - { - case NPC_STATE_IDLE: - case NPC_STATE_ALERT: - if ( HasCondition ( COND_NEW_ENEMY ) ) - { - m_pSquad->SquadNewEnemy( GetEnemy() ); - } - break; - default: - break; - } - } - - // --------------------------- - // Set ideal state - // --------------------------- - switch ( m_NPCState ) - { - case NPC_STATE_IDLE: - { - NPC_STATE nState = SelectIdleIdealState(); - if ( nState != NPC_STATE_INVALID ) - return nState; - } - break; - - case NPC_STATE_ALERT: - { - NPC_STATE nState = SelectAlertIdealState(); - if ( nState != NPC_STATE_INVALID ) - return nState; - } - break; - - case NPC_STATE_COMBAT: - // COMBAT goes to ALERT upon death of enemy - { - if ( GetEnemy() == NULL ) - { - DevWarning( 2, "***Combat state with no enemy!\n" ); - return NPC_STATE_ALERT; - } - break; - } - case NPC_STATE_SCRIPT: - { - NPC_STATE nState = SelectScriptIdealState(); - if ( nState != NPC_STATE_INVALID ) - return nState; - } - break; - - case NPC_STATE_DEAD: - return NPC_STATE_DEAD; - - default: - break; - } - - // The best ideal state is the current ideal state. - return m_IdealNPCState; -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CAI_BaseNPC::GiveWeapon( string_t iszWeaponName ) -{ - CBaseCombatWeapon *pWeapon = Weapon_Create( STRING(iszWeaponName) ); - if ( !pWeapon ) - { - Warning( "Couldn't create weapon %s to give NPC %s.\n", STRING(iszWeaponName), STRING(GetEntityName()) ); - return; - } - - // If I have a weapon already, drop it - if ( GetActiveWeapon() ) - { - Weapon_Drop( GetActiveWeapon() ); - } - - // If I have a name, make my weapon match it with "_weapon" appended - if ( GetEntityName() != NULL_STRING ) - { - pWeapon->SetName( AllocPooledString(UTIL_VarArgs("%s_weapon", STRING(GetEntityName()))) ); - } - - Weapon_Equip( pWeapon ); - - // Handle this case - OnGivenWeapon( pWeapon ); -} - -//----------------------------------------------------------------------------- -// Rather specific function that tells us if an NPC is in the process of -// moving to a weapon with the intent to pick it up. -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::IsMovingToPickupWeapon() -{ - return IsCurSchedule( SCHED_NEW_WEAPON ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::ShouldLookForBetterWeapon() -{ - if( m_flNextWeaponSearchTime > gpGlobals->curtime ) - return false; - - if( !(CapabilitiesGet() & bits_CAP_USE_WEAPONS) ) - return false; - - // Already armed and currently fighting. Don't try to upgrade. - if( GetActiveWeapon() && m_NPCState == NPC_STATE_COMBAT ) - return false; - - if( IsMovingToPickupWeapon() ) - return false; - - if( !IsPlayerAlly() && GetActiveWeapon() ) - return false; - - if( IsInAScript() ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Check if a better weapon is available. -// For now check if there is a weapon and I don't have one. In -// the future -// UNDONE: actually rate the weapons based on there strength -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::Weapon_IsBetterAvailable() -{ - if( m_iszPendingWeapon != NULL_STRING ) - { - // Some weapon is reserved for us. - return true; - } - - if( ShouldLookForBetterWeapon() ) - { - if( GetActiveWeapon() ) - { - m_flNextWeaponSearchTime = gpGlobals->curtime + 2; - } - else - { - if( IsInPlayerSquad() ) - { - // Look for a weapon frequently. - m_flNextWeaponSearchTime = gpGlobals->curtime + 1; - } - else - { - m_flNextWeaponSearchTime = gpGlobals->curtime + 2; - } - } - - if ( Weapon_FindUsable( WEAPON_SEARCH_DELTA ) ) - { - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true is weapon has a line of sight. If bSetConditions is -// true, also sets LOC conditions -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::WeaponLOSCondition(const Vector &ownerPos, const Vector &targetPos, bool bSetConditions ) -{ -#if 0 - // @TODO (toml 03-07-04): this code might be better (not tested) - Vector vecLocalRelativePosition; - VectorITransform( npcOwner->Weapon_ShootPosition(), npcOwner->EntityToWorldTransform(), vecLocalRelativePosition ); - - // Compute desired test transform - - // Compute desired x axis - Vector xaxis; - VectorSubtract( targetPos, ownerPos, xaxis ); - - // FIXME: Insert angle test here? - float flAngle = acos( xaxis.z / xaxis.Length() ); - - xaxis.z = 0.0f; - float flLength = VectorNormalize( xaxis ); - if ( flLength < 1e-3 ) - return false; - - Vector yaxis( -xaxis.y, xaxis.x, 0.0f ); - - matrix3x4_t losTestToWorld; - MatrixInitialize( losTestToWorld, ownerPos, xaxis, yaxis, zaxis ); - - Vector barrelPos; - VectorTransform( vecLocalRelativePosition, losTestToWorld, barrelPos ); - -#endif - - bool bHaveLOS; - - if (GetActiveWeapon()) - { - bHaveLOS = GetActiveWeapon()->WeaponLOSCondition(ownerPos, targetPos, bSetConditions); - } - else if (CapabilitiesGet() & bits_CAP_INNATE_RANGE_ATTACK1) - { - bHaveLOS = InnateWeaponLOSCondition(ownerPos, targetPos, bSetConditions); - } - else - { - if (bSetConditions) - { - SetCondition( COND_NO_WEAPON ); - } - bHaveLOS = false; - } - // ------------------------------------------- - // Check for friendly fire with the player - // ------------------------------------------- - if ( CapabilitiesGet() & ( bits_CAP_NO_HIT_PLAYER | bits_CAP_NO_HIT_SQUADMATES ) ) - { - float spread = 0.92; - if ( GetActiveWeapon() ) - { - Vector vSpread = GetAttackSpread( GetActiveWeapon() ); - if ( vSpread.x > VECTOR_CONE_15DEGREES.x ) - spread = TableCos(asin(vSpread.x)); - else // too much error because using point not box - spread = 0.99145; // "15 degrees" - } - if (CapabilitiesGet() & bits_CAP_NO_HIT_PLAYER) - { - // Check shoot direction relative to player - if (PlayerInSpread( ownerPos, targetPos, spread, 8*12 )) - { - if (bSetConditions) - { - SetCondition( COND_WEAPON_PLAYER_IN_SPREAD ); - } - bHaveLOS = false; - } - /* For grenades etc. check that player is clear? - // Check player position also - if (PlayerInRange( targetPos, 100 )) - { - SetCondition( COND_WEAPON_PLAYER_NEAR_TARGET ); - } - */ - } - - if ( bHaveLOS ) - { - if ( (CapabilitiesGet() & bits_CAP_NO_HIT_SQUADMATES) && m_pSquad && GetEnemy() ) - { - if ( IsSquadmateInSpread( ownerPos, targetPos, spread, 8*12 ) ) - { - SetCondition( COND_WEAPON_BLOCKED_BY_FRIEND ); - bHaveLOS = false; - } - } - } - } - return bHaveLOS; -} - -//----------------------------------------------------------------------------- -// Purpose: Check the innate weapon LOS for an owner at an arbitrary position -// If bSetConditions is true, LOS related conditions will also be set -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::InnateWeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions ) -{ - // -------------------- - // Check for occlusion - // -------------------- - // Base class version assumes innate weapon position is at eye level - Vector barrelPos = ownerPos + GetViewOffset(); - trace_t tr; - AI_TraceLine( barrelPos, targetPos, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); - - if ( tr.fraction == 1.0 ) - { - return true; - } - - CBaseEntity *pHitEntity = tr.m_pEnt; - - // Translate a hit vehicle into its passenger if found - if ( GetEnemy() != NULL ) - { - CBaseCombatCharacter *pCCEnemy = GetEnemy()->MyCombatCharacterPointer(); - if ( pCCEnemy != NULL && pCCEnemy->IsInAVehicle() ) - { - // Ok, player in vehicle, check if vehicle is target we're looking at, fire if it is - // Also, check to see if the owner of the entity is the vehicle, in which case it's valid too. - // This catches vehicles that use bone followers. - CBaseEntity *pVehicleEnt = pCCEnemy->GetVehicleEntity(); - if ( pHitEntity == pVehicleEnt || pHitEntity->GetOwnerEntity() == pVehicleEnt ) - return true; - } - } - - if ( pHitEntity == GetEnemy() ) - { - return true; - } - else if ( pHitEntity && pHitEntity->MyCombatCharacterPointer() ) - { - if (IRelationType( pHitEntity ) == D_HT) - { - return true; - } - else if (bSetConditions) - { - SetCondition(COND_WEAPON_BLOCKED_BY_FRIEND); - } - } - else if (bSetConditions) - { - SetCondition(COND_WEAPON_SIGHT_OCCLUDED); - SetEnemyOccluder(tr.m_pEnt); - } - - return false; -} - -//========================================================= -// CanCheckAttacks - prequalifies a npc to do more fine -// checking of potential attacks. -//========================================================= -bool CAI_BaseNPC::FCanCheckAttacks( void ) -{ - // Not allowed to check attacks while climbing or jumping - // Otherwise schedule is interrupted while on ladder/etc - // which is NOT a legal place to attack from - if ( GetNavType() == NAV_CLIMB || GetNavType() == NAV_JUMP ) - return false; - - if ( HasCondition(COND_SEE_ENEMY) && !HasCondition( COND_ENEMY_TOO_FAR)) - { - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Return dist. to enemy (closest of origin/head/feet) -// Input : -// Output : -//----------------------------------------------------------------------------- -float CAI_BaseNPC::EnemyDistance( CBaseEntity *pEnemy ) -{ - Vector enemyDelta = pEnemy->WorldSpaceCenter() - WorldSpaceCenter(); - - // NOTE: We ignore rotation for computing height. Assume it isn't an effect - // we care about, so we simply use OBBSize().z for height. - // Otherwise you'd do this: - // pEnemy->CollisionProp()->WorldSpaceSurroundingBounds( &enemyMins, &enemyMaxs ); - // float enemyHeight = enemyMaxs.z - enemyMins.z; - - float enemyHeight = pEnemy->CollisionProp()->OBBSize().z; - float myHeight = CollisionProp()->OBBSize().z; - - // max distance our centers can be apart with the boxes still overlapping - float flMaxZDist = ( enemyHeight + myHeight ) * 0.5f; - - // see if the enemy is closer to my head, feet or in between - if ( enemyDelta.z > flMaxZDist ) - { - // enemy feet above my head, compute distance from my head to his feet - enemyDelta.z -= flMaxZDist; - } - else if ( enemyDelta.z < -flMaxZDist ) - { - // enemy head below my feet, return distance between my feet and his head - enemyDelta.z += flMaxZDist; - } - else - { - // boxes overlap in Z, no delta - enemyDelta.z = 0; - } - - return enemyDelta.Length(); -} - -//----------------------------------------------------------------------------- - -float CAI_BaseNPC::GetReactionDelay( CBaseEntity *pEnemy ) -{ - return ( m_NPCState == NPC_STATE_ALERT || m_NPCState == NPC_STATE_COMBAT ) ? - ai_reaction_delay_alert.GetFloat() : - ai_reaction_delay_idle.GetFloat(); -} - -//----------------------------------------------------------------------------- -// Purpose: Update information on my enemy -// Input : -// Output : Returns true is new enemy, false is known enemy -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::UpdateEnemyMemory( CBaseEntity *pEnemy, const Vector &position, CBaseEntity *pInformer ) -{ - bool firstHand = ( pInformer == NULL || pInformer == this ); - - AI_PROFILE_SCOPE(CAI_BaseNPC_UpdateEnemyMemory); - - if ( GetEnemies() ) - { - // If the was eluding me and allow the NPC to play a sound - if (GetEnemies()->HasEludedMe(pEnemy)) - { - FoundEnemySound(); - } - float reactionDelay = ( !pInformer || pInformer == this ) ? GetReactionDelay( pEnemy ) : 0.0; - bool result = GetEnemies()->UpdateMemory(GetNavigator()->GetNetwork(), pEnemy, position, reactionDelay, firstHand); - - if ( !firstHand && pEnemy && result && GetState() == NPC_STATE_IDLE ) // if it's a new potential enemy - ForceDecisionThink(); - - if ( firstHand && pEnemy && m_pSquad ) - { - m_pSquad->UpdateEnemyMemory( this, pEnemy, position ); - } - return result; - } - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Remembers the thing my enemy is hiding behind. Called when either -// COND_ENEMY_OCCLUDED or COND_WEAPON_SIGHT_OCCLUDED is set. -//----------------------------------------------------------------------------- -void CAI_BaseNPC::SetEnemyOccluder(CBaseEntity *pBlocker) -{ - m_hEnemyOccluder = pBlocker; -} - - -//----------------------------------------------------------------------------- -// Purpose: Gets the thing my enemy is hiding behind (assuming they are hiding). -//----------------------------------------------------------------------------- -CBaseEntity *CAI_BaseNPC::GetEnemyOccluder(void) -{ - return m_hEnemyOccluder.Get(); -} - - -//----------------------------------------------------------------------------- -// Purpose: part of the Condition collection process -// gets and stores data and conditions pertaining to a npc's -// enemy. -// @TODO (toml 07-27-03): this should become subservient to the senses. right -// now, it yields different result -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_BaseNPC::GatherEnemyConditions( CBaseEntity *pEnemy ) -{ - AI_PROFILE_SCOPE(CAI_BaseNPC_GatherEnemyConditions); - - ClearCondition( COND_ENEMY_FACING_ME ); - ClearCondition( COND_BEHIND_ENEMY ); - - // --------------------------- - // Set visibility conditions - // --------------------------- - if ( HasCondition( COND_NEW_ENEMY ) || GetSenses()->GetTimeLastUpdate( GetEnemy() ) == gpGlobals->curtime ) - { - AI_PROFILE_SCOPE_BEGIN(CAI_BaseNPC_GatherEnemyConditions_Visibility); - - ClearCondition( COND_HAVE_ENEMY_LOS ); - ClearCondition( COND_ENEMY_OCCLUDED ); - - CBaseEntity *pBlocker = NULL; - SetEnemyOccluder(NULL); - - bool bSensesDidSee = GetSenses()->DidSeeEntity( pEnemy ); - - if ( !bSensesDidSee && ( ( EnemyDistance( pEnemy ) >= GetSenses()->GetDistLook() ) || !FVisible( pEnemy, MASK_BLOCKLOS, &pBlocker ) ) ) - { - // No LOS to enemy - SetEnemyOccluder(pBlocker); - SetCondition( COND_ENEMY_OCCLUDED ); - ClearCondition( COND_SEE_ENEMY ); - - if (HasMemory( bits_MEMORY_HAD_LOS )) - { - AI_PROFILE_SCOPE(CAI_BaseNPC_GatherEnemyConditions_Outputs); - // Send output event - if (GetEnemy()->IsPlayer()) - { - m_OnLostPlayerLOS.FireOutput( GetEnemy(), this ); - } - m_OnLostEnemyLOS.FireOutput( GetEnemy(), this ); - } - Forget( bits_MEMORY_HAD_LOS ); - } - else - { - // Have LOS but may not be in view cone - SetCondition( COND_HAVE_ENEMY_LOS ); - - if ( bSensesDidSee ) - { - // Have LOS and in view cone - SetCondition( COND_SEE_ENEMY ); - } - else - { - ClearCondition( COND_SEE_ENEMY ); - } - - if (!HasMemory( bits_MEMORY_HAD_LOS )) - { - AI_PROFILE_SCOPE(CAI_BaseNPC_GatherEnemyConditions_Outputs); - // Send output event - EHANDLE hEnemy; - hEnemy.Set( GetEnemy() ); - - if (GetEnemy()->IsPlayer()) - { - m_OnFoundPlayer.Set(hEnemy, this, this); - m_OnFoundEnemy.Set(hEnemy, this, this); - } - else - { - m_OnFoundEnemy.Set(hEnemy, this, this); - } - } - Remember( bits_MEMORY_HAD_LOS ); - } - - AI_PROFILE_SCOPE_END(); - } - - // ------------------- - // If enemy is dead - // ------------------- - if ( !pEnemy->IsAlive() ) - { - SetCondition( COND_ENEMY_DEAD ); - ClearCondition( COND_SEE_ENEMY ); - ClearCondition( COND_ENEMY_OCCLUDED ); - return; - } - - float flDistToEnemy = EnemyDistance(pEnemy); - - AI_PROFILE_SCOPE_BEGIN(CAI_BaseNPC_GatherEnemyConditions_SeeEnemy); - - if ( HasCondition( COND_SEE_ENEMY ) ) - { - // Trail the enemy a bit if he's moving - if (pEnemy->GetSmoothedVelocity() != vec3_origin) - { - Vector vTrailPos = pEnemy->GetAbsOrigin() - pEnemy->GetSmoothedVelocity() * random->RandomFloat( -0.05, 0 ); - UpdateEnemyMemory(pEnemy,vTrailPos); - } - else - { - UpdateEnemyMemory(pEnemy,pEnemy->GetAbsOrigin()); - } - - // If it's not an NPC, assume it can't see me - if ( pEnemy->MyCombatCharacterPointer() && pEnemy->MyCombatCharacterPointer()->FInViewCone ( this ) ) - { - SetCondition ( COND_ENEMY_FACING_ME ); - ClearCondition ( COND_BEHIND_ENEMY ); - } - else - { - ClearCondition( COND_ENEMY_FACING_ME ); - SetCondition ( COND_BEHIND_ENEMY ); - } - } - else if ( (!HasCondition(COND_ENEMY_OCCLUDED) && !HasCondition(COND_SEE_ENEMY)) && ( flDistToEnemy <= 256 ) ) - { - // if the enemy is not occluded, and unseen, that means it is behind or beside the npc. - // if the enemy is near enough the npc, we go ahead and let the npc know where the - // enemy is. Send the enemy in as the informer so this knowledge will be regarded as - // secondhand so that the NPC doesn't - UpdateEnemyMemory( pEnemy, pEnemy->GetAbsOrigin(), pEnemy ); - } - - AI_PROFILE_SCOPE_END(); - - float tooFar = m_flDistTooFar; - if ( GetActiveWeapon() && HasCondition(COND_SEE_ENEMY) ) - { - tooFar = MAX( m_flDistTooFar, GetActiveWeapon()->m_fMaxRange1 ); - } - - if ( flDistToEnemy >= tooFar ) - { - // enemy is very far away from npc - SetCondition( COND_ENEMY_TOO_FAR ); - } - else - { - ClearCondition( COND_ENEMY_TOO_FAR ); - } - - if ( FCanCheckAttacks() ) - { - // This may also call SetEnemyOccluder! - GatherAttackConditions( GetEnemy(), flDistToEnemy ); - } - else - { - ClearAttackConditions(); - } - - // If my enemy has moved significantly, or if the enemy has changed update my path - UpdateEnemyPos(); - - // If my target entity has moved significantly, update my path - // This is an odd place to put this, but where else should it go? - UpdateTargetPos(); - - // ---------------------------------------------------------------------------- - // Check if enemy is reachable via the node graph unless I'm not on a network - // ---------------------------------------------------------------------------- - if (GetNavigator()->IsOnNetwork()) - { - // Note that unreachablity times out - if (IsUnreachable(GetEnemy())) - { - SetCondition(COND_ENEMY_UNREACHABLE); - } - } - - //----------------------------------------------------------------------- - // If I haven't seen the enemy in a while he may have eluded me - //----------------------------------------------------------------------- - if (gpGlobals->curtime - GetEnemyLastTimeSeen() > 8) - { - //----------------------------------------------------------------------- - // I'm at last known position at enemy isn't in sight then has eluded me - // ---------------------------------------------------------------------- - Vector flEnemyLKP = GetEnemyLKP(); - if (((flEnemyLKP - GetAbsOrigin()).Length2D() < 48) && - !HasCondition(COND_SEE_ENEMY)) - { - MarkEnemyAsEluded(); - } - //------------------------------------------------------------------- - // If enemy isn't reachable, I can see last known position and enemy - // isn't there, then he has eluded me - // ------------------------------------------------------------------ - if (!HasCondition(COND_SEE_ENEMY) && HasCondition(COND_ENEMY_UNREACHABLE)) - { - if ( !FVisible( flEnemyLKP ) ) - { - MarkEnemyAsEluded(); - } - } - } -} - - -//----------------------------------------------------------------------------- -// In the case of goaltype enemy, update the goal position -//----------------------------------------------------------------------------- -float CAI_BaseNPC::GetGoalRepathTolerance( CBaseEntity *pGoalEnt, GoalType_t type, const Vector &curGoal, const Vector &curTargetPos ) -{ - float distToGoal = ( GetAbsOrigin() - curTargetPos ).Length() - GetNavigator()->GetArrivalDistance(); - float distMoved1Sec = GetSmoothedVelocity().Length(); - float result = 120; // FIXME: why 120? - - if (distMoved1Sec > 0.0) - { - float t = distToGoal / distMoved1Sec; - - result = clamp( 120 * t, 0, 120 ); - // Msg("t %.2f : d %.0f (%.0f)\n", t, result, distMoved1Sec ); - } - - if ( !pGoalEnt->IsPlayer() ) - result *= 1.20; - - return result; -} - -//----------------------------------------------------------------------------- -// In the case of goaltype enemy, update the goal position -//----------------------------------------------------------------------------- -void CAI_BaseNPC::UpdateEnemyPos() -{ - // Don't perform path recomputations during a climb or a jump - if ( !GetNavigator()->IsInterruptable() ) - return; - - if ( m_AnyUpdateEnemyPosTimer.Expired() && m_UpdateEnemyPosTimer.Expired() ) - { - // FIXME: does GetGoalRepathTolerance() limit re-routing enough to remove this? - // m_UpdateEnemyPosTimer.Set( 0.5, 1.0 ); - - // If my enemy has moved significantly, or if the enemy has changed update my path - if ( GetNavigator()->GetGoalType() == GOALTYPE_ENEMY ) - { - if (m_hEnemy != GetNavigator()->GetGoalTarget()) - { - GetNavigator()->SetGoalTarget( m_hEnemy, vec3_origin ); - } - else - { - Vector vEnemyLKP = GetEnemyLKP(); - TranslateNavGoal( GetEnemy(), vEnemyLKP ); - float tolerance = GetGoalRepathTolerance( GetEnemy(), GOALTYPE_ENEMY, GetNavigator()->GetGoalPos(), vEnemyLKP); - if ( (GetNavigator()->GetGoalPos() - vEnemyLKP).Length() > tolerance ) - { - // FIXME: when fleeing crowds, won't this severely limit the effectiveness of each individual? Shouldn't this be a mutex that's held for some period so that at least one attacker is effective? - m_AnyUpdateEnemyPosTimer.Set( 0.1 ); // FIXME: what's a reasonable interval? - if ( !GetNavigator()->RefindPathToGoal( false ) ) - { - TaskFail( FAIL_NO_ROUTE ); - } - } - } - } - } -} - - -//----------------------------------------------------------------------------- -// In the case of goaltype targetent, update the goal position -//----------------------------------------------------------------------------- -void CAI_BaseNPC::UpdateTargetPos() -{ - // BRJ 10/7/02 - // FIXME: make this check time based instead of distance based! - - // Don't perform path recomputations during a climb or a jump - if ( !GetNavigator()->IsInterruptable() ) - return; - - // If my target entity has moved significantly, or has changed, update my path - // This is an odd place to put this, but where else should it go? - if ( GetNavigator()->GetGoalType() == GOALTYPE_TARGETENT ) - { - if (m_hTargetEnt != GetNavigator()->GetGoalTarget()) - { - GetNavigator()->SetGoalTarget( m_hTargetEnt, vec3_origin ); - } - else if ( GetNavigator()->GetGoalFlags() & AIN_UPDATE_TARGET_POS ) - { - if ( GetTarget() == NULL || (GetNavigator()->GetGoalPos() - GetTarget()->GetAbsOrigin()).Length() > GetGoalRepathTolerance( GetTarget(), GOALTYPE_TARGETENT, GetNavigator()->GetGoalPos(), GetTarget()->GetAbsOrigin()) ) - { - if ( !GetNavigator()->RefindPathToGoal( false ) ) - { - TaskFail( FAIL_NO_ROUTE ); - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: part of the Condition collection process -// gets and stores data and conditions pertaining to a npc's -// enemy. -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_BaseNPC::CheckTarget( CBaseEntity *pTarget ) -{ - AI_PROFILE_SCOPE(CAI_Enemies_CheckTarget); - - ClearCondition ( COND_HAVE_TARGET_LOS ); - ClearCondition ( COND_TARGET_OCCLUDED ); - - // --------------------------- - // Set visibility conditions - // --------------------------- - if ( ( EnemyDistance( pTarget ) >= GetSenses()->GetDistLook() ) || !FVisible( pTarget ) ) - { - // No LOS to target - SetCondition( COND_TARGET_OCCLUDED ); - } - else - { - // Have LOS (may not be in view cone) - SetCondition( COND_HAVE_TARGET_LOS ); - } - - UpdateTargetPos(); -} - -//----------------------------------------------------------------------------- -// Purpose: Creates a bullseye of limited lifespan at the provided position -// Input : vecOrigin - Where to create the bullseye -// duration - The lifespan of the bullseye -// Output : A BaseNPC pointer to the bullseye -// -// NOTES : It is the caller's responsibility to set up relationships with -// this bullseye! -//----------------------------------------------------------------------------- -CAI_BaseNPC *CAI_BaseNPC::CreateCustomTarget( const Vector &vecOrigin, float duration ) -{ -#ifdef HL2_DLL - CNPC_Bullseye *pTarget = (CNPC_Bullseye*)CreateEntityByName( "npc_bullseye" ); - - ASSERT( pTarget != NULL ); - - // Build a nonsolid bullseye and place it in the desired location - // The bullseye must take damage or the SetHealth 0 call will not be able - pTarget->AddSpawnFlags( SF_BULLSEYE_NONSOLID ); - pTarget->SetAbsOrigin( vecOrigin ); - pTarget->Spawn(); - - // Set it up to remove itself, unless told to be infinite (-1) - if( duration > -1 ) - { - variant_t value; - value.SetFloat(0); - g_EventQueue.AddEvent( pTarget, "SetHealth", value, duration, this, this ); - } - - return pTarget; -#else - return NULL; -#endif// HL2_DLL -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : eNewActivity - -// Output : Activity -//----------------------------------------------------------------------------- -Activity CAI_BaseNPC::NPC_TranslateActivity( Activity eNewActivity ) -{ - Assert( eNewActivity != ACT_INVALID ); - - if (eNewActivity == ACT_RANGE_ATTACK1) - { - if ( IsCrouching() ) - { - eNewActivity = ACT_RANGE_ATTACK1_LOW; - } - } - else if (eNewActivity == ACT_RELOAD) - { - if (IsCrouching()) - { - eNewActivity = ACT_RELOAD_LOW; - } - } - else if ( eNewActivity == ACT_IDLE ) - { - if ( IsCrouching() ) - { - eNewActivity = ACT_CROUCHIDLE; - } - } - // ==== - // HACK : LEIPZIG 06 - The underlying problem is that the AR2 and SMG1 cannot map IDLE_ANGRY to a crouched equivalent automatically - // which causes the character to pop up and down in their idle state of firing while crouched. -- jdw - else if ( eNewActivity == ACT_IDLE_ANGRY_SMG1 ) - { - if ( IsCrouching() ) - { - eNewActivity = ACT_RANGE_AIM_LOW; - } - } - // ==== - - if (CapabilitiesGet() & bits_CAP_DUCK) - { - if (eNewActivity == ACT_RELOAD) - { - return GetReloadActivity(GetHintNode()); - } - else if ((eNewActivity == ACT_COVER ) || - (eNewActivity == ACT_IDLE && HasMemory(bits_MEMORY_INCOVER))) - { - Activity nCoverActivity = GetCoverActivity(GetHintNode()); - // --------------------------------------------------------------- - // Some NPCs don't have a cover activity defined so just use idle - // --------------------------------------------------------------- - if (SelectWeightedSequence( nCoverActivity ) == ACTIVITY_NOT_AVAILABLE) - { - nCoverActivity = ACT_IDLE; - } - - return nCoverActivity; - } - } - return eNewActivity; -} - - -//----------------------------------------------------------------------------- - -Activity CAI_BaseNPC::TranslateActivity( Activity idealActivity, Activity *pIdealWeaponActivity ) -{ - const int MAX_TRIES = 5; - int count = 0; - - bool bIdealWeaponRequired = false; - Activity idealWeaponActivity; - Activity baseTranslation; - bool bWeaponRequired = false; - Activity weaponTranslation; - Activity last; - Activity current; - - idealWeaponActivity = Weapon_TranslateActivity( idealActivity, &bIdealWeaponRequired ); - if ( pIdealWeaponActivity ) - *pIdealWeaponActivity = idealWeaponActivity; - - baseTranslation = idealActivity; - weaponTranslation = idealActivity; - last = idealActivity; - while ( count++ < MAX_TRIES ) - { - current = NPC_TranslateActivity( last ); - if ( current != last ) - baseTranslation = current; - - weaponTranslation = Weapon_TranslateActivity( current, &bWeaponRequired ); - - if ( weaponTranslation == last ) - break; - - last = weaponTranslation; - } - AssertMsg( count < MAX_TRIES, "Circular activity translation!" ); - - if ( last == ACT_SCRIPT_CUSTOM_MOVE ) - return ACT_SCRIPT_CUSTOM_MOVE; - - if ( HaveSequenceForActivity( weaponTranslation ) ) - return weaponTranslation; - - if ( bWeaponRequired ) - { - // only complain about an activity once - static CUtlVector< Activity > sUniqueActivities; - - if (!sUniqueActivities.Find( weaponTranslation)) - { - // FIXME: warning - DevWarning( "%s missing activity \"%s\" needed by weapon\"%s\"\n", - GetClassname(), GetActivityName( weaponTranslation ), GetActiveWeapon()->GetClassname() ); - - sUniqueActivities.AddToTail( weaponTranslation ); - } - } - - if ( baseTranslation != weaponTranslation && HaveSequenceForActivity( baseTranslation ) ) - return baseTranslation; - - if ( idealWeaponActivity != baseTranslation && HaveSequenceForActivity( idealWeaponActivity ) ) - return idealActivity; - - if ( idealActivity != idealWeaponActivity && HaveSequenceForActivity( idealActivity ) ) - return idealActivity; - - Assert( !HaveSequenceForActivity( idealActivity ) ); - if ( idealActivity == ACT_RUN ) - { - idealActivity = ACT_WALK; - } - else if ( idealActivity == ACT_WALK ) - { - idealActivity = ACT_RUN; - } - - return idealActivity; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : NewActivity - -// iSequence - -// translatedActivity - -// weaponActivity - -//----------------------------------------------------------------------------- -void CAI_BaseNPC::ResolveActivityToSequence(Activity NewActivity, int &iSequence, Activity &translatedActivity, Activity &weaponActivity) -{ - AI_PROFILE_SCOPE( CAI_BaseNPC_ResolveActivityToSequence ); - - iSequence = ACTIVITY_NOT_AVAILABLE; - - translatedActivity = TranslateActivity( NewActivity, &weaponActivity ); - - if ( ( NewActivity == ACT_SCRIPT_CUSTOM_MOVE ) ) - { - iSequence = GetScriptCustomMoveSequence(); - } - else - { - iSequence = SelectWeightedSequence( translatedActivity ); - - if ( iSequence == ACTIVITY_NOT_AVAILABLE ) - { - static CAI_BaseNPC *pLastWarn; - static Activity lastWarnActivity; - static float timeLastWarn; - - if ( ( pLastWarn != this && lastWarnActivity != translatedActivity ) || gpGlobals->curtime - timeLastWarn > 5.0 ) - { - DevWarning( "%s:%s:%s has no sequence for act:%s\n", GetClassname(), GetDebugName(), STRING( GetModelName() ), ActivityList_NameForIndex(translatedActivity) ); - pLastWarn = this; - lastWarnActivity = translatedActivity; - timeLastWarn = gpGlobals->curtime; - } - - if ( translatedActivity == ACT_RUN ) - { - translatedActivity = ACT_WALK; - iSequence = SelectWeightedSequence( translatedActivity ); - } - } - } - - if ( iSequence == ACT_INVALID ) - { - // Abject failure. Use sequence zero. - iSequence = 0; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : NewActivity - -// iSequence - -// translatedActivity - -// weaponActivity - -//----------------------------------------------------------------------------- -extern ConVar ai_sequence_debug; - -void CAI_BaseNPC::SetActivityAndSequence(Activity NewActivity, int iSequence, Activity translatedActivity, Activity weaponActivity) -{ - m_translatedActivity = translatedActivity; - - if (ai_sequence_debug.GetBool() == true && (m_debugOverlays & OVERLAY_NPC_SELECTED_BIT)) - { - DevMsg("SetActivityAndSequence : %s: %s:%s -> %s:%s / %s:%s\n", GetClassname(), - GetActivityName(GetActivity()), GetSequenceName(GetSequence()), - GetActivityName(NewActivity), GetSequenceName(iSequence), - GetActivityName(translatedActivity), GetActivityName(weaponActivity) ); - - } - - // Set to the desired anim, or default anim if the desired is not present - if ( iSequence > ACTIVITY_NOT_AVAILABLE ) - { - if ( GetSequence() != iSequence || !SequenceLoops() ) - { - // - // Don't reset frame between movement phased animations - if (!IsActivityMovementPhased( m_Activity ) || - !IsActivityMovementPhased( NewActivity )) - { - SetCycle( 0 ); - } - } - - ResetSequence( iSequence ); - Weapon_SetActivity( weaponActivity, SequenceDuration( iSequence ) ); - } - else - { - // Not available try to get default anim - ResetSequence( 0 ); - } - - // Set the view position based on the current activity - SetViewOffset( EyeOffset(m_translatedActivity) ); - - if (m_Activity != NewActivity) - { - OnChangeActivity(NewActivity); - } - - // NOTE: We DO NOT write the translated activity here. - // This is to abstract the activity translation from the AI code. - // As far as the code is concerned, a translation is merely a new set of sequences - // that should be regarded as the activity in question. - - // Go ahead and set this so it doesn't keep trying when the anim is not present - m_Activity = NewActivity; - - // this cannot be called until m_Activity stores NewActivity! - GetMotor()->RecalculateYawSpeed(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Sets the activity to the desired activity immediately, skipping any -// transition sequences. -// Input : NewActivity - -//----------------------------------------------------------------------------- -void CAI_BaseNPC::SetActivity( Activity NewActivity ) -{ - // If I'm already doing the NewActivity I can bail. - // FIXME: Should this be based on the current translated activity and ideal translated activity (calculated below)? - // The old code only cared about the logical activity, not translated. - - if (m_Activity == NewActivity) - { - return; - } - - // Don't do this if I'm playing a transition, unless it's ACT_RESET. - if ( NewActivity != ACT_RESET && m_Activity == ACT_TRANSITION && m_IdealActivity != ACT_DO_NOT_DISTURB ) - { - return; - } - - if (ai_sequence_debug.GetBool() == true && (m_debugOverlays & OVERLAY_NPC_SELECTED_BIT)) - { - DevMsg("SetActivity : %s: %s -> %s\n", GetClassname(), GetActivityName(GetActivity()), GetActivityName(NewActivity)); - } - - if ( !GetModelPtr() ) - return; - - // In case someone calls this with something other than the ideal activity. - m_IdealActivity = NewActivity; - - // Resolve to ideals and apply directly, skipping transitions. - ResolveActivityToSequence(m_IdealActivity, m_nIdealSequence, m_IdealTranslatedActivity, m_IdealWeaponActivity); - - //DevMsg("%s: SLAM %s -> %s\n", GetClassname(), GetSequenceName(GetSequence()), GetSequenceName(m_nIdealSequence)); - - SetActivityAndSequence(m_IdealActivity, m_nIdealSequence, m_IdealTranslatedActivity, m_IdealWeaponActivity); -} - - -//----------------------------------------------------------------------------- -// Purpose: Sets the activity that we would like to transition toward. -// Input : NewActivity - -//----------------------------------------------------------------------------- -void CAI_BaseNPC::SetIdealActivity( Activity NewActivity ) -{ - // ignore if it's an ACT_TRANSITION, it means somewhere we're setting IdealActivity with a bogus intermediate value - if (NewActivity == ACT_TRANSITION) - { - Assert( 0 ); - return; - } - - if (ai_sequence_debug.GetBool() == true && (m_debugOverlays & OVERLAY_NPC_SELECTED_BIT)) - { - DevMsg("SetIdealActivity : %s: %s -> %s\n", GetClassname(), GetActivityName(GetActivity()), GetActivityName(NewActivity)); - } - - - if (NewActivity == ACT_RESET) - { - // They probably meant to call SetActivity(ACT_RESET)... we'll fix it for them. - SetActivity(ACT_RESET); - return; - } - - m_IdealActivity = NewActivity; - - if( NewActivity == ACT_DO_NOT_DISTURB ) - { - // Don't resolve anything! Leave it the way the user has it right now. - return; - } - - if ( !GetModelPtr() ) - return; - - // Perform translation in case we need to change sequences within a single activity, - // such as between a standing idle and a crouching idle. - ResolveActivityToSequence(m_IdealActivity, m_nIdealSequence, m_IdealTranslatedActivity, m_IdealWeaponActivity); -} - - -//----------------------------------------------------------------------------- -// Purpose: Moves toward the ideal activity through any transition sequences. -//----------------------------------------------------------------------------- -void CAI_BaseNPC::AdvanceToIdealActivity(void) -{ - // If there is a transition sequence between the current sequence and the ideal sequence... - int nNextSequence = FindTransitionSequence(GetSequence(), m_nIdealSequence, NULL); - if (nNextSequence != -1) - { - // We found a transition sequence or possibly went straight to - // the ideal sequence. - if (nNextSequence != m_nIdealSequence) - { -// DevMsg("%s: TRANSITION %s -> %s -> %s\n", GetClassname(), GetSequenceName(GetSequence()), GetSequenceName(nNextSequence), GetSequenceName(m_nIdealSequence)); - - Activity eWeaponActivity = ACT_TRANSITION; - Activity eTranslatedActivity = ACT_TRANSITION; - - // Figure out if the transition sequence has an associated activity that - // we can use for our weapon. Do activity translation also. - Activity eTransitionActivity = GetSequenceActivity(nNextSequence); - if (eTransitionActivity != ACT_INVALID) - { - int nDiscard; - ResolveActivityToSequence(eTransitionActivity, nDiscard, eTranslatedActivity, eWeaponActivity); - } - - // Set activity and sequence to the transition stuff. Set the activity to ACT_TRANSITION - // so we know we're in a transition. - SetActivityAndSequence(ACT_TRANSITION, nNextSequence, eTranslatedActivity, eWeaponActivity); - } - else - { - //DevMsg("%s: IDEAL %s -> %s\n", GetClassname(), GetSequenceName(GetSequence()), GetSequenceName(m_nIdealSequence)); - - // Set activity and sequence to the ideal stuff that was set up in MaintainActivity. - SetActivityAndSequence(m_IdealActivity, m_nIdealSequence, m_IdealTranslatedActivity, m_IdealWeaponActivity); - } - } - // Else go straight there to the ideal activity. - else - { - //DevMsg("%s: Unable to get from sequence %s to %s!\n", GetClassname(), GetSequenceName(GetSequence()), GetSequenceName(m_nIdealSequence)); - SetActivity(m_IdealActivity); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Tries to achieve our ideal animation state, playing any transition -// sequences that we need to play to get there. -//----------------------------------------------------------------------------- -void CAI_BaseNPC::MaintainActivity(void) -{ - AI_PROFILE_SCOPE( CAI_BaseNPC_MaintainActivity ); - - if ( m_lifeState == LIFE_DEAD ) - { - // Don't maintain activities if we're daid. - // Blame Speyrer - return; - } - - if ((GetState() == NPC_STATE_SCRIPT)) - { - // HACK: finish any transitions we might be playing before we yield control to the script - if (GetActivity() != ACT_TRANSITION) - { - // Our animation state is being controlled by a script. - return; - } - } - - if( m_IdealActivity == ACT_DO_NOT_DISTURB || !GetModelPtr() ) - { - return; - } - - // We may have work to do if we aren't playing our ideal activity OR if we - // aren't playing our ideal sequence. - if ((GetActivity() != m_IdealActivity) || (GetSequence() != m_nIdealSequence)) - { - if (ai_sequence_debug.GetBool() == true && (m_debugOverlays & OVERLAY_NPC_SELECTED_BIT)) - { - DevMsg("MaintainActivity %s : %s:%s -> %s:%s\n", GetClassname(), - GetActivityName(GetActivity()), GetSequenceName(GetSequence()), - GetActivityName(m_IdealActivity), GetSequenceName(m_nIdealSequence)); - } - - bool bAdvance = false; - - // If we're in a transition activity, see if we are done with the transition. - if (GetActivity() == ACT_TRANSITION) - { - // If the current sequence is finished, try to go to the next one - // closer to our ideal sequence. - if (IsSequenceFinished()) - { - bAdvance = true; - } - // Else a transition sequence is in progress, do nothing. - } - // Else get a specific sequence for the activity and try to transition to that. - else - { - // Save off a target sequence and translated activities to apply when we finish - // playing all the transitions and finally arrive at our ideal activity. - ResolveActivityToSequence(m_IdealActivity, m_nIdealSequence, m_IdealTranslatedActivity, m_IdealWeaponActivity); - bAdvance = true; - } - - if (bAdvance) - { - // Try to go to the next sequence closer to our ideal sequence. - AdvanceToIdealActivity(); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns true if our ideal activity has finished playing. -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::IsActivityFinished( void ) -{ - return (IsSequenceFinished() && (GetSequence() == m_nIdealSequence)); -} - -//----------------------------------------------------------------------------- -// Purpose: Checks to see if the activity is one of the standard phase-matched movement activities -// Input : activity -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::IsActivityMovementPhased( Activity activity ) -{ - switch( activity ) - { - case ACT_WALK: - case ACT_WALK_AIM: - case ACT_WALK_CROUCH: - case ACT_WALK_CROUCH_AIM: - case ACT_RUN: - case ACT_RUN_AIM: - case ACT_RUN_CROUCH: - case ACT_RUN_CROUCH_AIM: - case ACT_RUN_PROTECTED: - return true; - default: - break; - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::OnChangeActivity( Activity eNewActivity ) -{ - if ( eNewActivity == ACT_RUN || - eNewActivity == ACT_RUN_AIM || - eNewActivity == ACT_WALK ) - { - Stand(); - } -} - -//========================================================= -// SetSequenceByName -//========================================================= -void CAI_BaseNPC::SetSequenceByName( const char *szSequence ) -{ - int iSequence = LookupSequence( szSequence ); - - if ( iSequence > ACTIVITY_NOT_AVAILABLE ) - SetSequenceById( iSequence ); - else - { - DevWarning( 2, "%s has no sequence to match request\n", GetClassname(), szSequence ); - SetSequence( 0 ); // Set to the reset anim (if it's there) - } -} - -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::SetSequenceById( int iSequence ) -{ - // Set to the desired anim, or default anim if the desired is not present - if ( iSequence > ACTIVITY_NOT_AVAILABLE ) - { - if ( GetSequence() != iSequence || !SequenceLoops() ) - { - SetCycle( 0 ); - } - - ResetSequence( iSequence ); // Set to the reset anim (if it's there) - GetMotor()->RecalculateYawSpeed(); - } - else - { - // Not available try to get default anim - DevWarning( 2, "%s invalid sequence requested\n", GetClassname() ); - SetSequence( 0 ); // Set to the reset anim (if it's there) - } -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the target entity -// Input : -// Output : -//----------------------------------------------------------------------------- -CBaseEntity *CAI_BaseNPC::GetNavTargetEntity(void) -{ - if ( GetNavigator()->GetGoalType() == GOALTYPE_ENEMY ) - return m_hEnemy; - else if ( GetNavigator()->GetGoalType() == GOALTYPE_TARGETENT ) - return m_hTargetEnt; - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: returns zero if the caller can jump from -// vecStart to vecEnd ignoring collisions with pTarget -// -// if the throw fails, returns the distance -// that can be travelled before an obstacle is hit -//----------------------------------------------------------------------------- -#include "ai_initutils.h" -//#define _THROWDEBUG -float CAI_BaseNPC::ThrowLimit( const Vector &vecStart, - const Vector &vecEnd, - float fGravity, - float fArcSize, - const Vector &mins, - const Vector &maxs, - CBaseEntity *pTarget, - Vector *jumpVel, - CBaseEntity **pBlocker) -{ - // Get my jump velocity - Vector rawJumpVel = CalcThrowVelocity(vecStart, vecEnd, fGravity, fArcSize); - *jumpVel = rawJumpVel; - Vector vecFrom = vecStart; - - // Calculate the total time of the jump minus a tiny fraction - float jumpTime = (vecStart - vecEnd).Length2D()/rawJumpVel.Length2D(); - float timeStep = jumpTime / 10.0; - - Vector gravity = Vector(0,0,fGravity); - - // this loop takes single steps to the goal. - for (float flTime = 0 ; flTime < jumpTime-0.1 ; flTime += timeStep ) - { - // Calculate my position after the time step (average velocity over this time step) - Vector nextPos = vecFrom + (rawJumpVel - 0.5 * gravity * timeStep) * timeStep; - - // If last time step make next position the target position - if ((flTime + timeStep) > jumpTime) - { - nextPos = vecEnd; - } - - trace_t tr; - AI_TraceHull( vecFrom, nextPos, mins, maxs, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - - if (tr.startsolid || tr.fraction < 1.0) - { - CBaseEntity *pEntity = tr.m_pEnt; - - // If we hit the target we are good to go! - if (pEntity == pTarget) - { - return 0; - } - -#ifdef _THROWDEBUG - NDebugOverlay::Line( vecFrom, nextPos, 255, 0, 0, true, 1.0 ); -#endif - // ---------------------------------------------------------- - // If blocked by an npc remember - // ---------------------------------------------------------- - *pBlocker = pEntity; - - // Return distance sucessfully traveled before block encountered - return ((tr.endpos - vecStart).Length()); - } -#ifdef _THROWDEBUG - else - { - NDebugOverlay::Line( vecFrom, nextPos, 255, 255, 255, true, 1.0 ); - } -#endif - - - rawJumpVel = rawJumpVel - gravity * timeStep; - vecFrom = nextPos; - } - return 0; -} - - - -//----------------------------------------------------------------------------- -// Purpose: Called to initialize or re-initialize the vphysics hull when the size -// of the NPC changes -//----------------------------------------------------------------------------- -void CAI_BaseNPC::SetupVPhysicsHull() -{ - if ( GetMoveType() == MOVETYPE_VPHYSICS || GetMoveType() == MOVETYPE_NONE ) - return; - - if ( VPhysicsGetObject() ) - { - // Disable collisions to get - VPhysicsGetObject()->EnableCollisions(false); - VPhysicsDestroyObject(); - } - VPhysicsInitShadow( true, false ); - IPhysicsObject *pPhysObj = VPhysicsGetObject(); - if ( pPhysObj ) - { - float mass = Studio_GetMass(GetModelPtr()); - if ( mass > 0 ) - { - pPhysObj->SetMass( mass ); - } -#if _DEBUG - else - { - DevMsg("Warning: %s has no physical mass\n", STRING(GetModelName())); - } -#endif - IPhysicsShadowController *pController = pPhysObj->GetShadowController(); - float avgsize = (WorldAlignSize().x + WorldAlignSize().y) * 0.5; - pController->SetTeleportDistance( avgsize * 0.5 ); - m_bCheckContacts = true; - } -} - - -// Check for problematic physics objects resting on this NPC. -// They can screw up his navigation, so attach a controller to -// help separate the NPC & physics when you encounter these. -ConVar ai_auto_contact_solver( "ai_auto_contact_solver", "1" ); -void CAI_BaseNPC::CheckPhysicsContacts() -{ - if ( gpGlobals->frametime <= 0.0f || !ai_auto_contact_solver.GetBool() ) - return; - - m_bCheckContacts = false; - if ( GetMoveType() == MOVETYPE_STEP && VPhysicsGetObject()) - { - IPhysicsObject *pPhysics = VPhysicsGetObject(); - IPhysicsFrictionSnapshot *pSnapshot = pPhysics->CreateFrictionSnapshot(); - CBaseEntity *pGroundEntity = GetGroundEntity(); - float heightCheck = GetAbsOrigin().z + GetHullMaxs().z; - Vector npcVel; - pPhysics->GetVelocity( &npcVel, NULL ); - CBaseEntity *pOtherEntity = NULL; - bool createSolver = false; - float solverTime = 0.0f; - while ( pSnapshot->IsValid() ) - { - IPhysicsObject *pOther = pSnapshot->GetObject(1); - pOtherEntity = static_cast(pOther->GetGameData()); - - if ( pOtherEntity && pGroundEntity != pOtherEntity ) - { - float otherMass = PhysGetEntityMass(pOtherEntity); - - if ( pOtherEntity->GetMoveType() == MOVETYPE_VPHYSICS && pOther->IsMoveable() && - otherMass < VPHYSICS_LARGE_OBJECT_MASS && !pOtherEntity->GetServerVehicle() ) - { - m_bCheckContacts = true; - Vector vel, point; - pOther->GetVelocity( &vel, NULL ); - pSnapshot->GetContactPoint( point ); - - // compare the relative velocity - vel -= npcVel; - - // slow moving object probably won't clear itself. - // Either set ignore, or disable collisions entirely - if ( vel.LengthSqr() < 5.0f*5.0f ) - { - float topdist = fabs(point.z-heightCheck); - // 4 seconds to ignore this for nav - solverTime = 4.0f; - if ( topdist < 2.0f ) - { - // Resting on my head so disable collisions for a bit - solverTime = 0.5f; // UNDONE: Tune - if ( pOther->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - { - // player is being a monkey - solverTime = 0.25f; - } - - //Msg("Dropping %s from %s\n", pOtherEntity->GetClassname(), GetClassname() ); - Assert( !NPCPhysics_SolverExists(this, pOtherEntity) ); - createSolver = true; - break; - } - } - } - } - pSnapshot->NextFrictionData(); - } - pPhysics->DestroyFrictionSnapshot( pSnapshot ); - if ( createSolver ) - { - // turn collisions back on once we've been separated for enough time - NPCPhysics_CreateSolver( this, pOtherEntity, true, solverTime ); - pPhysics->RecheckContactPoints(); - } - } -} - -void CAI_BaseNPC::StartTouch( CBaseEntity *pOther ) -{ - BaseClass::StartTouch(pOther); - - if ( pOther->GetMoveType() == MOVETYPE_VPHYSICS ) - { - m_bCheckContacts = true; - } -} - -//----------------------------------------------------------------------------- -// Purpose: To be called instead of UTIL_SetSize, so pathfinding hull -// and actual hull agree -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_BaseNPC::SetHullSizeNormal( bool force ) -{ - if ( m_fIsUsingSmallHull || force ) - { - UTIL_SetSize(this, GetHullMins(),GetHullMaxs()); - m_fIsUsingSmallHull = false; - if ( VPhysicsGetObject() ) - { - SetupVPhysicsHull(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: To be called instead of UTIL_SetSize, so pathfinding hull -// and actual hull agree -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::SetHullSizeSmall( bool force ) -{ - if ( !m_fIsUsingSmallHull || force ) - { - UTIL_SetSize(this, NAI_Hull::SmallMins(GetHullType()),NAI_Hull::SmallMaxs(GetHullType())); - m_fIsUsingSmallHull = true; - if ( VPhysicsGetObject() ) - { - SetupVPhysicsHull(); - } - } - return true; -} - -//----------------------------------------------------------------------------- -// Checks to see that the nav hull is valid for the NPC -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::IsNavHullValid() const -{ - Assert( GetSolid() != SOLID_BSP ); - - Vector hullMin = GetHullMins(); - Vector hullMax = GetHullMaxs(); - Vector vecMins, vecMaxs; - if ( GetSolid() == SOLID_BBOX ) - { - vecMins = WorldAlignMins(); - vecMaxs = WorldAlignMaxs(); - } - else if ( GetSolid() == SOLID_VPHYSICS ) - { - Assert( VPhysicsGetObject() ); - const CPhysCollide *pPhysCollide = VPhysicsGetObject()->GetCollide(); - physcollision->CollideGetAABB( &vecMins, &vecMaxs, pPhysCollide, GetAbsOrigin(), GetAbsAngles() ); - vecMins -= GetAbsOrigin(); - vecMaxs -= GetAbsOrigin(); - } - else - { - vecMins = hullMin; - vecMaxs = hullMax; - } - - if ( (hullMin.x > vecMins.x) || (hullMax.x < vecMaxs.x) || - (hullMin.y > vecMins.y) || (hullMax.y < vecMaxs.y) || - (hullMin.z > vecMins.z) || (hullMax.z < vecMaxs.z) ) - { - return false; - } - - return true; -} - - -//========================================================= -// NPCInit - after a npc is spawned, it needs to -// be dropped into the world, checked for mobility problems, -// and put on the proper path, if any. This function does -// all of those things after the npc spawns. Any -// initialization that should take place for all npcs -// goes here. -//========================================================= -void CAI_BaseNPC::NPCInit ( void ) -{ - if (!g_pGameRules->FAllowNPCs()) - { - UTIL_Remove( this ); - return; - } - - if( IsWaitingToRappel() ) - { - // If this guy's supposed to rappel, keep him from - // falling to the ground when he spawns. - AddFlag( FL_FLY ); - } - -#ifdef _DEBUG - // Make sure that the bounding box is appropriate for the hull size... - // FIXME: We can't test vphysics objects because NPCInit occurs before VPhysics is set up - if ( GetSolid() != SOLID_VPHYSICS && !IsSolidFlagSet(FSOLID_NOT_SOLID) ) - { - if ( !IsNavHullValid() ) - { - Warning("NPC Entity %s (%d) has a bounding box which extends outside its nav box!\n", - STRING(m_iClassname), entindex() ); - } - } -#endif - - // Set fields common to all npcs - AddFlag( FL_AIMTARGET | FL_NPC ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - - m_flOriginalYaw = GetAbsAngles().y; - - SetBlocksLOS( false ); - - SetGravity(1.0); // Don't change - m_takedamage = DAMAGE_YES; - GetMotor()->SetIdealYaw( GetLocalAngles().y ); - m_iMaxHealth = m_iHealth; - m_lifeState = LIFE_ALIVE; - SetIdealState( NPC_STATE_IDLE );// Assume npc will be idle, until proven otherwise - SetIdealActivity( ACT_IDLE ); - SetActivity( ACT_IDLE ); - -#ifdef HL1_DLL - SetDeathPose( ACT_INVALID ); -#endif - - ClearCommandGoal(); - - ClearSchedule( "Initializing NPC" ); - GetNavigator()->ClearGoal(); - InitBoneControllers( ); // FIX: should be done in Spawn - if ( GetModelPtr() ) - { - ResetActivityIndexes(); - ResetEventIndexes(); - } - - SetHintNode( NULL ); - - m_afMemory = MEMORY_CLEAR; - - SetEnemy( NULL ); - - m_flDistTooFar = 1024.0; - SetDistLook( 2048.0 ); - - if ( HasSpawnFlags( SF_NPC_LONG_RANGE ) ) - { - m_flDistTooFar = 1e9f; - SetDistLook( 6000.0 ); - } - - // Clear conditions - m_Conditions.ClearAll(); - - // set eye position - SetDefaultEyeOffset(); - - // Only give weapon of allowed to have one - if (CapabilitiesGet() & bits_CAP_USE_WEAPONS) - { // Does this npc spawn with a weapon - if ( m_spawnEquipment != NULL_STRING && strcmp(STRING(m_spawnEquipment), "0")) - { - CBaseCombatWeapon *pWeapon = Weapon_Create( STRING(m_spawnEquipment) ); - if ( pWeapon ) - { - // If I have a name, make my weapon match it with "_weapon" appended - if ( GetEntityName() != NULL_STRING ) - { - pWeapon->SetName( AllocPooledString(UTIL_VarArgs("%s_weapon", STRING(GetEntityName()))) ); - } - - if ( GetEffects() & EF_NOSHADOW ) - { - // BUGBUG: if this NPC drops this weapon it will forevermore have no shadow - pWeapon->AddEffects( EF_NOSHADOW ); - } - - Weapon_Equip( pWeapon ); - } - } - } - - // Robin: Removed this, since it stomps the weapon's settings, and it's stomped - // by OnUpdateShotRegulator() as soon as they finish firing the first time. - //GetShotRegulator()->SetParameters( 2, 6, 0.3f, 0.8f ); - - SetUse ( &CAI_BaseNPC::NPCUse ); - - // NOTE: Can't call NPC Init Think directly... logic changed about - // what time it is when worldspawn happens.. - - // We must put off the rest of our initialization - // until we're sure everything else has had a chance to spawn. Otherwise - // we may try to reference entities that haven't spawned yet.(sjb) - SetThink( &CAI_BaseNPC::NPCInitThink ); - SetNextThink( gpGlobals->curtime + 0.01f ); - - ForceGatherConditions(); - - // HACKHACK: set up a pre idle animation - // NOTE: Must do this before CreateVPhysics() so bone followers have the correct initial positions. - if ( HasSpawnFlags( SF_NPC_WAIT_FOR_SCRIPT ) ) - { - const char *pStartSequence = CAI_ScriptedSequence::GetSpawnPreIdleSequenceForScript( this ); - if ( pStartSequence ) - { - SetSequence( LookupSequence( pStartSequence ) ); - } - } - - CreateVPhysics(); - - if ( HasSpawnFlags( SF_NPC_START_EFFICIENT ) ) - { - SetEfficiency( AIE_EFFICIENT ); - } - - m_bFadeCorpse = ShouldFadeOnDeath(); - - m_GiveUpOnDeadEnemyTimer.Set( 0.75, 2.0 ); - - m_flTimeLastMovement = FLT_MAX; - - m_flIgnoreDangerSoundsUntil = 0; - - SetDeathPose( ACT_INVALID ); - SetDeathPoseFrame( 0 ); - - m_EnemiesSerialNumber = -1; -} - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::CreateVPhysics() -{ - if ( IsAlive() && !VPhysicsGetObject() ) - { - SetupVPhysicsHull(); - } - return true; -} - - -//----------------------------------------------------------------------------- -// Set up the shot regulator based on the equipped weapon -//----------------------------------------------------------------------------- -void CAI_BaseNPC::OnUpdateShotRegulator( ) -{ - CBaseCombatWeapon *pWeapon = GetActiveWeapon(); - if ( !pWeapon ) - return; - - // Default values - m_ShotRegulator.SetBurstInterval( pWeapon->GetFireRate(), pWeapon->GetFireRate() ); - m_ShotRegulator.SetBurstShotCountRange( pWeapon->GetMinBurst(), pWeapon->GetMaxBurst() ); - m_ShotRegulator.SetRestInterval( pWeapon->GetMinRestTime(), pWeapon->GetMaxRestTime() ); - - // Let the behavior have a whack at it. - if ( GetRunningBehavior() ) - { - GetRunningBehavior()->OnUpdateShotRegulator(); - } -} - - -//----------------------------------------------------------------------------- -// Set up the shot regulator based on the equipped weapon -//----------------------------------------------------------------------------- -void CAI_BaseNPC::OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ) -{ - BaseClass::OnChangeActiveWeapon( pOldWeapon, pNewWeapon ); - - // Shot regulator code - if ( pNewWeapon ) - { - OnUpdateShotRegulator(); - m_ShotRegulator.Reset( true ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Tests to see if NPC can holster their weapon (if animation exists to holster weapon) -// Output : true if holster weapon animation exists -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::CanHolsterWeapon( void ) -{ - int seq = SelectWeightedSequence( ACT_DISARM ); - return (seq >= 0); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CAI_BaseNPC::HolsterWeapon( void ) -{ - if ( IsWeaponHolstered() ) - return -1; - - int iHolsterGesture = FindGestureLayer( ACT_DISARM ); - if ( iHolsterGesture != -1 ) - return iHolsterGesture; - - int iLayer = AddGesture( ACT_DISARM, true ); - //iLayer = AddGesture( ACT_GESTURE_DISARM, true ); - - if (iLayer != -1) - { - // Prevent firing during the holster / unholster - float flDuration = GetLayerDuration( iLayer ); - m_ShotRegulator.FireNoEarlierThan( gpGlobals->curtime + flDuration + 0.5 ); - - if( m_iDesiredWeaponState == DESIREDWEAPONSTATE_HOLSTERED_DESTROYED ) - { - m_iDesiredWeaponState = DESIREDWEAPONSTATE_CHANGING_DESTROY; - } - else - { - m_iDesiredWeaponState = DESIREDWEAPONSTATE_CHANGING; - } - - // Make sure we don't try to reload while we're holstering - ClearCondition(COND_LOW_PRIMARY_AMMO); - ClearCondition(COND_NO_PRIMARY_AMMO); - ClearCondition(COND_NO_SECONDARY_AMMO); - } - - return iLayer; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CAI_BaseNPC::UnholsterWeapon( void ) -{ - if ( !IsWeaponHolstered() ) - return -1; - - int iHolsterGesture = FindGestureLayer( ACT_ARM ); - if ( iHolsterGesture != -1 ) - return iHolsterGesture; - - // Deploy the first weapon you can find - for (int i = 0; i < WeaponCount(); i++) - { - if ( GetWeapon( i )) - { - SetActiveWeapon( GetWeapon(i) ); - - int iLayer = AddGesture( ACT_ARM, true ); - //iLayer = AddGesture( ACT_GESTURE_ARM, true ); - - if (iLayer != -1) - { - // Prevent firing during the holster / unholster - float flDuration = GetLayerDuration( iLayer ); - m_ShotRegulator.FireNoEarlierThan( gpGlobals->curtime + flDuration + 0.5 ); - - m_iDesiredWeaponState = DESIREDWEAPONSTATE_CHANGING; - } - - // Refill the clip - if ( GetActiveWeapon()->UsesClipsForAmmo1() ) - { - GetActiveWeapon()->m_iClip1 = GetActiveWeapon()->GetMaxClip1(); - } - - // Make sure we don't try to reload while we're unholstering - ClearCondition(COND_LOW_PRIMARY_AMMO); - ClearCondition(COND_NO_PRIMARY_AMMO); - ClearCondition(COND_NO_SECONDARY_AMMO); - - return iLayer; - } - } - - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::InputHolsterWeapon( inputdata_t &inputdata ) -{ - m_iDesiredWeaponState = DESIREDWEAPONSTATE_HOLSTERED; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::InputHolsterAndDestroyWeapon( inputdata_t &inputdata ) -{ - m_iDesiredWeaponState = DESIREDWEAPONSTATE_HOLSTERED_DESTROYED; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::InputUnholsterWeapon( inputdata_t &inputdata ) -{ - m_iDesiredWeaponState = DESIREDWEAPONSTATE_UNHOLSTERED; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::IsWeaponHolstered( void ) -{ - if( !GetActiveWeapon() ) - return true; - - if( GetActiveWeapon()->IsEffectActive(EF_NODRAW) ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::IsWeaponStateChanging( void ) -{ - return ( m_iDesiredWeaponState == DESIREDWEAPONSTATE_CHANGING || m_iDesiredWeaponState == DESIREDWEAPONSTATE_CHANGING_DESTROY ); -} - -//----------------------------------------------------------------------------- -// Set up the shot regulator based on the equipped weapon -//----------------------------------------------------------------------------- -void CAI_BaseNPC::OnRangeAttack1() -{ - SetLastAttackTime( gpGlobals->curtime ); - - // Houston, there is a problem! - AssertOnce( GetShotRegulator()->ShouldShoot() ); - - m_ShotRegulator.OnFiredWeapon(); - if ( m_ShotRegulator.IsInRestInterval() ) - { - OnUpdateShotRegulator(); - } - - SetNextAttack( m_ShotRegulator.NextShotTime() ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Initialze the relationship table from the keyvalues -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_BaseNPC::InitRelationshipTable(void) -{ - AddRelationship( STRING( m_RelationshipString ), NULL ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::AddRelationship( const char *pszRelationship, CBaseEntity *pActivator ) -{ - // Parse the keyvalue data - char parseString[1000]; - Q_strncpy(parseString, pszRelationship, sizeof(parseString)); - - // Look for an entity string - char *entityString = strtok(parseString," "); - while (entityString) - { - // Get the disposition - char *dispositionString = strtok(NULL," "); - Disposition_t disposition = D_NU; - if ( dispositionString ) - { - if (!stricmp(dispositionString,"D_HT")) - { - disposition = D_HT; - } - else if (!stricmp(dispositionString,"D_FR")) - { - disposition = D_FR; - } - else if (!stricmp(dispositionString,"D_LI")) - { - disposition = D_LI; - } - else if (!stricmp(dispositionString,"D_NU")) - { - disposition = D_NU; - } - else - { - disposition = D_NU; - Warning( "***ERROR***\nBad relationship type (%s) to unknown entity (%s)!\n", dispositionString,entityString ); - Assert( 0 ); - return; - } - } - else - { - Warning("Can't parse relationship info (%s) - Expecting 'name [D_HT, D_FR, D_LI, D_NU] [1-99]'\n", pszRelationship ); - Assert(0); - return; - } - - // Get the priority - char *priorityString = strtok(NULL," "); - int priority = ( priorityString ) ? atoi(priorityString) : DEF_RELATIONSHIP_PRIORITY; - - bool bFoundEntity = false; - - // Try to get pointer to an entity of this name - CBaseEntity *entity = gEntList.FindEntityByName( NULL, entityString ); - while( entity ) - { - // make sure you catch all entities of this name. - bFoundEntity = true; - AddEntityRelationship(entity, disposition, priority ); - entity = gEntList.FindEntityByName( entity, entityString ); - } - - if( !bFoundEntity ) - { - // Need special condition for player as we can only have one - if (!stricmp("player", entityString) || !stricmp("!player", entityString)) - { - AddClassRelationship( CLASS_PLAYER, disposition, priority ); - } - // Otherwise try to create one too see if a valid classname and get class type - else - { - // HACKHACK: - CBaseEntity *pEntity = CanCreateEntityClass( entityString ) ? CreateEntityByName( entityString ) : NULL; - if (pEntity) - { - AddClassRelationship( pEntity->Classify(), disposition, priority ); - UTIL_RemoveImmediate(pEntity); - } - else - { - DevWarning( "Couldn't set relationship to unknown entity or class (%s)!\n", entityString ); - } - } - } - // Check for another entity in the list - entityString = strtok(NULL," "); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_BaseNPC::AddEntityRelationship( CBaseEntity *pEntity, Disposition_t nDisposition, int nPriority ) -{ -#if 0 - ForceGatherConditions(); -#endif - BaseClass::AddEntityRelationship( pEntity, nDisposition, nPriority ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_BaseNPC::AddClassRelationship( Class_T nClass, Disposition_t nDisposition, int nPriority ) -{ -#if 0 - ForceGatherConditions(); -#endif - BaseClass::AddClassRelationship( nClass, nDisposition, nPriority ); -} - -//========================================================= -// NPCInitThink - Calls StartNPC. Startnpc is -// virtual, but this function cannot be -//========================================================= -void CAI_BaseNPC::NPCInitThink ( void ) -{ - // Initialize the relationship table - InitRelationshipTable(); - - StartNPC(); - - PostNPCInit(); - - if( GetSleepState() == AISS_AUTO_PVS ) - { - // This code is a bit wonky, but it makes it easier for level designers to - // select this option in Hammer. So we set a sleep flag to indicate the choice, - // and then set the sleep state to awake (normal) - AddSleepFlags( AI_SLEEP_FLAG_AUTO_PVS ); - SetSleepState( AISS_AWAKE ); - } - - if( GetSleepState() == AISS_AUTO_PVS_AFTER_PVS ) - { - AddSleepFlags( AI_SLEEP_FLAG_AUTO_PVS_AFTER_PVS ); - SetSleepState( AISS_AWAKE ); - } - - if ( GetSleepState() > AISS_AWAKE ) - { - Sleep(); - } - - m_flLastRealThinkTime = gpGlobals->curtime; -} - -//========================================================= -// StartNPC - final bit of initization before a npc -// is turned over to the AI. -//========================================================= -void CAI_BaseNPC::StartNPC( void ) -{ - // Raise npc off the floor one unit, then drop to floor - if ( (GetMoveType() != MOVETYPE_FLY) && (GetMoveType() != MOVETYPE_FLYGRAVITY) && - !(CapabilitiesGet() & bits_CAP_MOVE_FLY) && - !HasSpawnFlags( SF_NPC_FALL_TO_GROUND ) && !IsWaitingToRappel() && !GetMoveParent() ) - { - Vector origin = GetLocalOrigin(); - - if (!GetMoveProbe()->FloorPoint( origin + Vector(0, 0, 0.1), MASK_NPCSOLID, 0, -2048, &origin )) - { - Warning( "NPC %s stuck in wall--level design error at (%.2f %.2f %.2f)\n", GetClassname(), GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z ); - if ( g_pDeveloper->GetInt() > 1 ) - { - m_debugOverlays |= OVERLAY_BBOX_BIT; - } - } - - SetLocalOrigin( origin ); - } - else - { - SetGroundEntity( NULL ); - } - - if ( m_target != NULL_STRING )// this npc has a target - { - // Find the npc's initial target entity, stash it - SetGoalEnt( gEntList.FindEntityByName( NULL, m_target ) ); - - if ( !GetGoalEnt() ) - { - Warning( "ReadyNPC()--%s couldn't find target %s\n", GetClassname(), STRING(m_target)); - } - else - { - StartTargetHandling( GetGoalEnt() ); - } - } - - //SetState ( m_IdealNPCState ); - //SetActivity ( m_IdealActivity ); - - InitSquad(); - - //--------------------------------- - // - // Spread think times of simultaneously spawned NPCs so that they don't all happen at the same time - // - // Think distribution based on spawn order is: - // - // Tick offset Think time Spawn order - // 0 0 1 - // 1 0.015 13 - // 2 0.03 5 - // 3 0.045 9 - // 4 0.06 18 - // 5 0.075 3 - // 6 0.09 15 - // 7 0.105 11 - // 8 0.12 7 - // 9 0.135 17 - // 10 0.15 2 - // 11 0.165 14 - // 12 0.18 6 - // 13 0.195 19 - // 14 0.21 10 - // 15 0.225 4 - // 16 0.24 16 - // 17 0.255 12 - // 18 0.27 8 - // 19 0.285 20 - - - // If this NPC is spawning late in the game, just push through the rest of the initialization - // start thinking right now. Some spread is added to handle triggered spawns that bring - // a bunch of NPCs into the level - SetThink ( &CAI_BaseNPC::CallNPCThink ); - - if ( gm_flTimeLastSpawn != gpGlobals->curtime ) - { - gm_nSpawnedThisFrame = 0; - gm_flTimeLastSpawn = gpGlobals->curtime; - } - - static const float nextThinkTimes[20] = - { - .0, .150, .075, .225, .030, .180, .120, .270, .045, .210, .105, .255, .015, .165, .090, .240, .135, .060, .195, .285 - }; - - SetNextThink( gpGlobals->curtime + nextThinkTimes[gm_nSpawnedThisFrame % 20] ); - - gm_nSpawnedThisFrame++; - - //--------------------------------- - - m_ScriptArrivalActivity = AIN_DEF_ACTIVITY; - m_strScriptArrivalSequence = NULL_STRING; - - if ( HasSpawnFlags(SF_NPC_WAIT_FOR_SCRIPT) ) - { - SetState( NPC_STATE_IDLE ); - m_Activity = m_IdealActivity; - m_nIdealSequence = GetSequence(); - SetSchedule( SCHED_WAIT_FOR_SCRIPT ); - } -} - -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::StartTargetHandling( CBaseEntity *pTargetEnt ) -{ - // set the npc up to walk a path corner path. - // !!!BUGBUG - this is a minor bit of a hack. - // JAYJAY - - // NPC will start turning towards his destination - bool bIsFlying = (GetMoveType() == MOVETYPE_FLY) || (GetMoveType() == MOVETYPE_FLYGRAVITY); - AI_NavGoal_t goal( GOALTYPE_PATHCORNER, pTargetEnt->GetAbsOrigin(), - bIsFlying ? ACT_FLY : ACT_WALK, - AIN_DEF_TOLERANCE, AIN_YAW_TO_DEST); - - SetState( NPC_STATE_IDLE ); - SetSchedule( SCHED_IDLE_WALK ); - - if ( !GetNavigator()->SetGoal( goal ) ) - { - DevWarning( 2, "Can't Create Route!\n" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Connect my memory to the squad's -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::InitSquad( void ) -{ - // ------------------------------------------------------- - // If I form squads add me to a squad - // ------------------------------------------------------- - if (!m_pSquad && ( CapabilitiesGet() & bits_CAP_SQUAD )) - { - if ( !m_SquadName ) - { - DevMsg(2, "Found %s that isn't in a squad\n",GetClassname()); - } - else - { - m_pSquad = g_AI_SquadManager.FindCreateSquad(this, m_SquadName); - } - } - - return ( m_pSquad != NULL ); -} - -//----------------------------------------------------------------------------- -// Purpose: Get the memory for this NPC -//----------------------------------------------------------------------------- -CAI_Enemies *CAI_BaseNPC::GetEnemies( void ) -{ - return m_pEnemies; -} - -//----------------------------------------------------------------------------- -// Purpose: Remove this NPC's memory -//----------------------------------------------------------------------------- -void CAI_BaseNPC::RemoveMemory( void ) -{ - delete m_pEnemies; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::TaskComplete( bool fIgnoreSetFailedCondition ) -{ - EndTaskOverlay(); - - // Handy thing to use for debugging - //if (IsCurSchedule(SCHED_PUT_HERE) && - // GetTask()->iTask == TASK_PUT_HERE) - //{ - // int put_breakpoint_here = 5; - //} - - if ( fIgnoreSetFailedCondition || !HasCondition(COND_TASK_FAILED) ) - { - SetTaskStatus( TASKSTATUS_COMPLETE ); - } -} - -void CAI_BaseNPC::TaskMovementComplete( void ) -{ - switch( GetTaskStatus() ) - { - case TASKSTATUS_NEW: - case TASKSTATUS_RUN_MOVE_AND_TASK: - SetTaskStatus( TASKSTATUS_RUN_TASK ); - break; - - case TASKSTATUS_RUN_MOVE: - TaskComplete(); - break; - - case TASKSTATUS_RUN_TASK: - // FIXME: find out how to safely restart movement - //Warning( "Movement completed twice!\n" ); - //Assert( 0 ); - break; - - case TASKSTATUS_COMPLETE: - break; - } - - // JAY: Put this back in. - // UNDONE: Figure out how much of the timestep was consumed by movement - // this frame and restart the movement/schedule engine if necessary - if ( m_scriptState != SCRIPT_CUSTOM_MOVE_TO_MARK ) - { - SetIdealActivity( GetStoppedActivity() ); - } - - // Advance past the last node (in case there is some event at this node) - if ( GetNavigator()->IsGoalActive() ) - { - GetNavigator()->AdvancePath(); - } - - // Now clear the path, it's done. - GetNavigator()->ClearGoal(); - - OnMovementComplete(); -} - - -int CAI_BaseNPC::TaskIsRunning( void ) -{ - if ( GetTaskStatus() != TASKSTATUS_COMPLETE && - GetTaskStatus() != TASKSTATUS_RUN_MOVE ) - return 1; - - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_BaseNPC::TaskFail( AI_TaskFailureCode_t code ) -{ - EndTaskOverlay(); - - // Handy tool for debugging - //if (IsCurSchedule(SCHED_PUT_NAME_HERE)) - //{ - // int put_breakpoint_here = 5; - //} - - // If in developer mode save the fail text for debug output - if (g_pDeveloper->GetInt()) - { - m_failText = TaskFailureToString( code ); - - m_interuptSchedule = NULL; - m_failedSchedule = GetCurSchedule(); - - if (m_debugOverlays & OVERLAY_TASK_TEXT_BIT) - { - DevMsg(this, AIMF_IGNORE_SELECTED, " TaskFail -> %s\n", m_failText ); - } - - ADD_DEBUG_HISTORY( HISTORY_AI_DECISIONS, UTIL_VarArgs("%s(%d): TaskFail -> %s\n", GetDebugName(), entindex(), m_failText ) ); - - //AddTimedOverlay( fail_text, 5); - } - - m_ScheduleState.taskFailureCode = code; - SetCondition(COND_TASK_FAILED); - Forget( bits_MEMORY_TURNING ); -} - -//------------------------------------------------------------------------------ -// Purpose : Remember that this entity wasn't reachable -// Input : -// Output : -//------------------------------------------------------------------------------ -void CAI_BaseNPC::RememberUnreachable(CBaseEntity *pEntity, float duration ) -{ - if ( pEntity == GetEnemy() ) - { - ForceChooseNewEnemy(); - } - - const float NPC_UNREACHABLE_TIMEOUT = ( duration > 0.0 ) ? duration : 3; - // Only add to list if not already on it - for (int i=m_UnreachableEnts.Size()-1;i>=0;i--) - { - // If record already exists just update mark time - if (pEntity == m_UnreachableEnts[i].hUnreachableEnt) - { - m_UnreachableEnts[i].fExpireTime = gpGlobals->curtime + NPC_UNREACHABLE_TIMEOUT; - m_UnreachableEnts[i].vLocationWhenUnreachable = pEntity->GetAbsOrigin(); - return; - } - } - - // Add new unreachabe entity to list - int nNewIndex = m_UnreachableEnts.AddToTail(); - m_UnreachableEnts[nNewIndex].hUnreachableEnt = pEntity; - m_UnreachableEnts[nNewIndex].fExpireTime = gpGlobals->curtime + NPC_UNREACHABLE_TIMEOUT; - m_UnreachableEnts[nNewIndex].vLocationWhenUnreachable = pEntity->GetAbsOrigin(); -} - -//------------------------------------------------------------------------------ -// Purpose : Returns true is entity was remembered as unreachable. -// After a time delay reachability is checked -// Input : -// Output : -//------------------------------------------------------------------------------ -bool CAI_BaseNPC::IsUnreachable(CBaseEntity *pEntity) -{ - float UNREACHABLE_DIST_TOLERANCE_SQ = (120*120); - - // Note that it's ok to remove elements while I'm iterating - // as long as I iterate backwards and remove them using FastRemove - for (int i=m_UnreachableEnts.Size()-1;i>=0;i--) - { - // Remove any dead elements - if (m_UnreachableEnts[i].hUnreachableEnt == NULL) - { - m_UnreachableEnts.FastRemove(i); - } - else if (pEntity == m_UnreachableEnts[i].hUnreachableEnt) - { - // Test for reachablility on any elements that have timed out - if ( gpGlobals->curtime > m_UnreachableEnts[i].fExpireTime || - pEntity->GetAbsOrigin().DistToSqr(m_UnreachableEnts[i].vLocationWhenUnreachable) > UNREACHABLE_DIST_TOLERANCE_SQ) - { - m_UnreachableEnts.FastRemove(i); - return false; - } - return true; - } - } - return false; -} - -bool CAI_BaseNPC::IsValidEnemy( CBaseEntity *pEnemy ) -{ - CAI_BaseNPC *pEnemyNPC = pEnemy->MyNPCPointer(); - if ( pEnemyNPC && pEnemyNPC->CanBeAnEnemyOf( this ) == false ) - return false; - - // Test our enemy filter - if ( m_hEnemyFilter.Get()!= NULL && m_hEnemyFilter->PassesFilter( this, pEnemy ) == false ) - return false; - - return true; -} - - -bool CAI_BaseNPC::CanBeAnEnemyOf( CBaseEntity *pEnemy ) -{ - if ( GetSleepState() > AISS_WAITING_FOR_THREAT ) - return false; - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Picks best enemy from my list of enemies -// Prefers reachable enemies over enemies that are unreachable, -// regardless of priority. For enemies that are both reachable or -// unreachable picks by priority. If priority is the same, picks -// by distance. -// Input : -// Output : -//----------------------------------------------------------------------------- - -CBaseEntity *CAI_BaseNPC::BestEnemy( void ) -{ - AI_PROFILE_SCOPE( CAI_BaseNPC_BestEnemy ); - // TODO - may want to consider distance, attack types, back turned, etc. - - CBaseEntity* pBestEnemy = NULL; - int iBestDistSq = MAX_COORD_RANGE * MAX_COORD_RANGE;// so first visible entity will become the closest. - int iBestPriority = -1000; - bool bBestUnreachable = true; // Forces initial check - ThreeState_t fBestSeen = TRS_NONE; - ThreeState_t fBestVisible = TRS_NONE; - int iDistSq; - bool bUnreachable = false; - - AIEnemiesIter_t iter; - - DbgEnemyMsg( this, "BestEnemy() {\n" ); - - for( AI_EnemyInfo_t *pEMemory = GetEnemies()->GetFirst(&iter); pEMemory != NULL; pEMemory = GetEnemies()->GetNext(&iter) ) - { - CBaseEntity *pEnemy = pEMemory->hEnemy; - - if (!pEnemy || !pEnemy->IsAlive()) - { - if ( pEnemy ) - DbgEnemyMsg( this, " %s rejected: dead\n", pEnemy->GetDebugName() ); - continue; - } - - if ( (pEnemy->GetFlags() & FL_NOTARGET) ) - { - DbgEnemyMsg( this, " %s rejected: no target\n", pEnemy->GetDebugName() ); - continue; - } - - if ( m_bIgnoreUnseenEnemies ) - { - const float TIME_CONSIDER_ENEMY_UNSEEN = .4; - if ( pEMemory->timeLastSeen < gpGlobals->curtime - TIME_CONSIDER_ENEMY_UNSEEN ) - { - DbgEnemyMsg( this, " %s rejected: not seen and set to ignore unseen enemies\n", pEnemy->GetDebugName() ); - continue; - } - } - - // UNDONE: Move relationship checks into IsValidEnemy? - Disposition_t relation = IRelationType( pEnemy ); - if ( (relation != D_HT && relation != D_FR) ) - { - DbgEnemyMsg( this, " %s rejected: no hate/fear\n", pEnemy->GetDebugName() ); - continue; - } - - if ( m_flAcceptableTimeSeenEnemy > 0.0 && pEMemory->timeLastSeen < m_flAcceptableTimeSeenEnemy ) - { - DbgEnemyMsg( this, " %s rejected: old\n", pEnemy->GetDebugName() ); - continue; - } - - if ( pEMemory->timeValidEnemy > gpGlobals->curtime ) - { - DbgEnemyMsg( this, " %s rejected: not yet valid\n", pEnemy->GetDebugName() ); - continue; - } - - // Skip enemies that have eluded me to prevent infinite loops - if ( pEMemory->bEludedMe ) - { - DbgEnemyMsg( this, " %s rejected: eluded\n", pEnemy->GetDebugName() ); - continue; - } - - // Skip enemies I fear that I've never seen. (usually seen through an enemy finder) - if ( relation == D_FR && !pEMemory->bUnforgettable && pEMemory->timeFirstSeen == AI_INVALID_TIME ) - { - DbgEnemyMsg( this, " %s rejected: feared, but never seen\n", pEnemy->GetDebugName() ); - continue; - } - - if ( !IsValidEnemy( pEnemy ) ) - { - DbgEnemyMsg( this, " %s rejected: not valid\n", pEnemy->GetDebugName() ); - continue; - } - - // establish the reachability of this enemy - bUnreachable = IsUnreachable(pEnemy); - - // If best is reachable and current is unreachable, skip the unreachable enemy regardless of priority - if (!bBestUnreachable && bUnreachable) - { - DbgEnemyMsg( this, " %s rejected: unreachable\n", pEnemy->GetDebugName() ); - continue; - } - - // If best is unreachable and current is reachable, always pick the current regardless of priority - if (bBestUnreachable && !bUnreachable) - { - DbgEnemyMsg( this, " %s accepted (1)\n", pEnemy->GetDebugName() ); - if ( pBestEnemy ) - DbgEnemyMsg( this, " (%s displaced)\n", pBestEnemy->GetDebugName() ); - - iBestPriority = IRelationPriority ( pEnemy ); - iBestDistSq = (int)(pEnemy->GetAbsOrigin() - GetAbsOrigin()).LengthSqr(); - pBestEnemy = pEnemy; - bBestUnreachable = bUnreachable; - fBestSeen = TRS_NONE; - fBestVisible = TRS_NONE; - } - // If both are unreachable or both are reachable, choose enemy based on priority and distance - else if ( IRelationPriority( pEnemy ) > iBestPriority ) - { - DbgEnemyMsg( this, " %s accepted\n", pEnemy->GetDebugName() ); - if ( pBestEnemy ) - DbgEnemyMsg( this, " (%s displaced due to priority, %d > %d )\n", pBestEnemy->GetDebugName(), IRelationPriority( pEnemy ), iBestPriority ); - // this entity is disliked MORE than the entity that we - // currently think is the best visible enemy. No need to do - // a distance check, just get mad at this one for now. - iBestPriority = IRelationPriority ( pEnemy ); - iBestDistSq = (int)(pEnemy->GetAbsOrigin() - GetAbsOrigin()).LengthSqr(); - pBestEnemy = pEnemy; - bBestUnreachable = bUnreachable; - fBestSeen = TRS_NONE; - fBestVisible = TRS_NONE; - } - else if ( IRelationPriority( pEnemy ) == iBestPriority ) - { - // this entity is disliked just as much as the entity that - // we currently think is the best visible enemy, so we only - // get mad at it if it is closer. - iDistSq = (int)(pEnemy->GetAbsOrigin() - GetAbsOrigin()).LengthSqr(); - - bool bAcceptCurrent = false; - bool bCloser = ( ( iBestDistSq - iDistSq ) > EnemyDistTolerance() ); - ThreeState_t fCurSeen = TRS_NONE; - ThreeState_t fCurVisible = TRS_NONE; - - // The following code is constructed in such a verbose manner to - // ensure the expensive calls only occur if absolutely needed - - // If current is farther, and best has previously been confirmed as seen or visible, move on - if ( !bCloser) - { - if ( fBestSeen == TRS_TRUE || fBestVisible == TRS_TRUE ) - { - DbgEnemyMsg( this, " %s rejected: current is closer and seen\n", pEnemy->GetDebugName() ); - continue; - } - } - - // If current is closer, and best has previously been confirmed as not seen and not visible, take it - if ( bCloser) - { - if ( fBestSeen == TRS_FALSE && fBestVisible == TRS_FALSE ) - { - bAcceptCurrent = true; - } - } - - if ( !bAcceptCurrent ) - { - // If current is closer, and seen, take it - if ( bCloser ) - { - fCurSeen = ( GetSenses()->DidSeeEntity( pEnemy ) ) ? TRS_TRUE : TRS_FALSE; - - bAcceptCurrent = ( fCurSeen == TRS_TRUE ); - } - } - - if ( !bAcceptCurrent ) - { - // If current is farther, and best is seen, move on - if ( !bCloser ) - { - if ( fBestSeen == TRS_NONE ) - { - fBestSeen = ( GetSenses()->DidSeeEntity( pBestEnemy ) ) ? TRS_TRUE : TRS_FALSE; - } - - if ( fBestSeen == TRS_TRUE ) - { - DbgEnemyMsg( this, " %s rejected: current is closer and seen\n", pEnemy->GetDebugName() ); - continue; - } - } - - // At this point, need to start performing expensive tests - if ( bCloser && fBestVisible == TRS_NONE ) - { - // Perform shortest FVisible - fCurVisible = ( ( EnemyDistance( pEnemy ) < GetSenses()->GetDistLook() ) && FVisible( pEnemy ) ) ? TRS_TRUE : TRS_FALSE; - - bAcceptCurrent = ( fCurVisible == TRS_TRUE ); - } - - // Alas, must do the most expensive comparison - if ( !bAcceptCurrent ) - { - if ( fBestSeen == TRS_NONE ) - { - fBestSeen = ( GetSenses()->DidSeeEntity( pBestEnemy ) ) ? TRS_TRUE : TRS_FALSE; - } - - if ( fBestVisible == TRS_NONE ) - { - fBestVisible = ( ( EnemyDistance( pBestEnemy ) < GetSenses()->GetDistLook() ) && FVisible( pBestEnemy ) ) ? TRS_TRUE : TRS_FALSE; - } - - if ( fCurSeen == TRS_NONE ) - { - fCurSeen = ( GetSenses()->DidSeeEntity( pEnemy ) ) ? TRS_TRUE : TRS_FALSE; - } - - if ( fCurVisible == TRS_NONE ) - { - fCurVisible = ( ( EnemyDistance( pEnemy ) < GetSenses()->GetDistLook() ) && FVisible( pEnemy ) ) ? TRS_TRUE : TRS_FALSE; - } - - bool bBestSeenOrVisible = ( fBestSeen == TRS_TRUE || fBestVisible == TRS_TRUE ); - bool bCurSeenOrVisible = ( fCurSeen == TRS_TRUE || fCurVisible == TRS_TRUE ); - - if ( !bCloser) - { - if ( bBestSeenOrVisible ) - { - DbgEnemyMsg( this, " %s rejected: current is closer and seen\n", pEnemy->GetDebugName() ); - continue; - } - else if ( !bCurSeenOrVisible ) - { - DbgEnemyMsg( this, " %s rejected: current is closer and neither is seen\n", pEnemy->GetDebugName() ); - continue; - } - } - else // Closer - { - if ( !bCurSeenOrVisible && bBestSeenOrVisible ) - { - DbgEnemyMsg( this, " %s rejected: current is father but seen\n", pEnemy->GetDebugName() ); - continue; - } - } - } - } - - DbgEnemyMsg( this, " %s accepted\n", pEnemy->GetDebugName() ); - if ( pBestEnemy ) - DbgEnemyMsg( this, " (%s displaced due to distance/visibility)\n", pBestEnemy->GetDebugName() ); - fBestSeen = fCurSeen; - fBestVisible = fCurVisible; - iBestDistSq = iDistSq; - iBestPriority = IRelationPriority ( pEnemy ); - pBestEnemy = pEnemy; - bBestUnreachable = bUnreachable; - } - else - DbgEnemyMsg( this, " %s rejected: lower priority\n", pEnemy->GetDebugName() ); - } - - DbgEnemyMsg( this, "} == %s\n", pBestEnemy->GetDebugName() ); - - return pBestEnemy; -} - -//----------------------------------------------------------------------------- -// Purpose: Given a node returns the appropriate reload activity -// Input : -// Output : -//----------------------------------------------------------------------------- -Activity CAI_BaseNPC::GetReloadActivity( CAI_Hint* pHint ) -{ - Activity nReloadActivity = ACT_RELOAD; - - if (pHint && GetEnemy()!=NULL) - { - switch (pHint->HintType()) - { - case HINT_TACTICAL_COVER_LOW: - case HINT_TACTICAL_COVER_MED: - { - if (SelectWeightedSequence( ACT_RELOAD_LOW ) != ACTIVITY_NOT_AVAILABLE) - { - Vector vEyePos = GetAbsOrigin() + EyeOffset(ACT_RELOAD_LOW); - // Check if this location will block the threat's line of sight to me - trace_t tr; - AI_TraceLOS( vEyePos, GetEnemy()->EyePosition(), this, &tr ); - if (tr.fraction != 1.0) - { - nReloadActivity = ACT_RELOAD_LOW; - } - } - break; - } - default: - break; - } - } - return nReloadActivity; -} - -//----------------------------------------------------------------------------- -// Purpose: Given a node returns the appropriate cover activity -// Input : -// Output : -//----------------------------------------------------------------------------- -Activity CAI_BaseNPC::GetCoverActivity( CAI_Hint *pHint ) -{ - Activity nCoverActivity = ACT_INVALID; - - // --------------------------------------------------------------- - // Check if hint node specifies different cover type - // --------------------------------------------------------------- - if (pHint) - { - switch (pHint->HintType()) - { - case HINT_TACTICAL_COVER_MED: - { - nCoverActivity = ACT_COVER_MED; - break; - } - case HINT_TACTICAL_COVER_LOW: - { - nCoverActivity = ACT_COVER_LOW; - break; - } - default: - break; - } - } - - if ( nCoverActivity == ACT_INVALID ) - nCoverActivity = ACT_COVER; - - return nCoverActivity; -} - -//========================================================= -// CalcIdealYaw - gets a yaw value for the caller that would -// face the supplied vector. Value is stuffed into the npc's -// ideal_yaw -//========================================================= -float CAI_BaseNPC::CalcIdealYaw( const Vector &vecTarget ) -{ - Vector vecProjection = Vector(0.0f, 0.0f, 0.0f); - - // strafing npc needs to face 90 degrees away from its goal - if ( GetNavigator()->GetMovementActivity() == ACT_STRAFE_LEFT ) - { - vecProjection.x = -vecTarget.y; - vecProjection.y = vecTarget.x; - - return UTIL_VecToYaw( vecProjection - GetLocalOrigin() ); - } - else if ( GetNavigator()->GetMovementActivity() == ACT_STRAFE_RIGHT ) - { - vecProjection.x = vecTarget.y; - vecProjection.y = vecTarget.x; - - return UTIL_VecToYaw( vecProjection - GetLocalOrigin() ); - } - else - { - return UTIL_VecToYaw ( vecTarget - GetLocalOrigin() ); - } -} - -//========================================================= -// SetEyePosition -// -// queries the npc's model for $eyeposition and copies -// that vector to the npc's m_vDefaultEyeOffset and m_vecViewOffset -// -//========================================================= -void CAI_BaseNPC::SetDefaultEyeOffset ( void ) -{ - if ( GetModelPtr() ) - { - GetEyePosition( GetModelPtr(), m_vDefaultEyeOffset ); - - if ( m_vDefaultEyeOffset == vec3_origin ) - { - if ( Classify() != CLASS_NONE ) - { - DevMsg( "WARNING: %s(%s) has no eye offset in .qc!\n", GetClassname(), STRING(GetModelName()) ); - } - VectorAdd( WorldAlignMins(), WorldAlignMaxs(), m_vDefaultEyeOffset ); - m_vDefaultEyeOffset *= 0.75; - } - } - else - m_vDefaultEyeOffset = vec3_origin; - - SetViewOffset( m_vDefaultEyeOffset ); - -} - -//------------------------------------------------------------------------------ -// Purpose : Returns eye offset for an NPC for the given activity -// Input : -// Output : -//------------------------------------------------------------------------------ -Vector CAI_BaseNPC::EyeOffset( Activity nActivity ) -{ - if ( CapabilitiesGet() & bits_CAP_DUCK ) - { - if ( IsCrouchedActivity( nActivity ) ) - return GetCrouchEyeOffset(); - } - - // if the hint doesn't tell anything, assume current state - if ( IsCrouching() ) - return GetCrouchEyeOffset(); - - return m_vDefaultEyeOffset; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Vector -//----------------------------------------------------------------------------- -Vector CAI_BaseNPC::EyePosition( void ) -{ - if ( IsCrouching() ) - return GetAbsOrigin() + GetCrouchEyeOffset(); - - return BaseClass::EyePosition(); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CAI_BaseNPC::HandleAnimEvent( animevent_t *pEvent ) -{ - // UNDONE: Share this code into CBaseAnimating as appropriate? - switch( pEvent->event ) - { - case SCRIPT_EVENT_DEAD: - if ( m_NPCState == NPC_STATE_SCRIPT ) - { - m_lifeState = LIFE_DYING; - // Kill me now! (and fade out when CineCleanup() is called) -#if _DEBUG - DevMsg( 2, "Death event: %s\n", GetClassname() ); -#endif - m_iHealth = 0; - } -#if _DEBUG - else - DevWarning( 2, "INVALID death event:%s\n", GetClassname() ); -#endif - break; - case SCRIPT_EVENT_NOT_DEAD: - if ( m_NPCState == NPC_STATE_SCRIPT ) - { - m_lifeState = LIFE_ALIVE; - // This is for life/death sequences where the player can determine whether a character is dead or alive after the script - m_iHealth = m_iMaxHealth; - } - break; - - case SCRIPT_EVENT_SOUND: // Play a named wave file - { - EmitSound( pEvent->options ); - } - break; - - case SCRIPT_EVENT_SOUND_VOICE: - { - EmitSound( pEvent->options ); - } - break; - - case SCRIPT_EVENT_SENTENCE_RND1: // Play a named sentence group 33% of the time - if (random->RandomInt(0,2) == 0) - break; - // fall through... - case SCRIPT_EVENT_SENTENCE: // Play a named sentence group - SENTENCEG_PlayRndSz( edict(), pEvent->options, 1.0, SNDLVL_TALKING, 0, 100 ); - break; - - case SCRIPT_EVENT_FIREEVENT: - { - // - // Fire a script event. The number of the script event to fire is in the options string. - // - if ( m_hCine != NULL ) - { - m_hCine->FireScriptEvent( atoi( pEvent->options ) ); - } - else - { - // FIXME: look so see if it's playing a vcd and fire those instead - // AssertOnce( 0 ); - } - break; - } - case SCRIPT_EVENT_FIRE_INPUT: - { - variant_t emptyVariant; - this->AcceptInput( pEvent->options, this, this, emptyVariant, 0 ); - break; - } - - case SCRIPT_EVENT_NOINTERRUPT: // Can't be interrupted from now on - if ( m_hCine ) - m_hCine->AllowInterrupt( false ); - break; - - case SCRIPT_EVENT_CANINTERRUPT: // OK to interrupt now - if ( m_hCine ) - m_hCine->AllowInterrupt( true ); - break; - -#if 0 - case SCRIPT_EVENT_INAIR: // Don't engine->DropToFloor() - case SCRIPT_EVENT_ENDANIMATION: // Set ending animation sequence to - break; -#endif - case SCRIPT_EVENT_BODYGROUPON: - case SCRIPT_EVENT_BODYGROUPOFF: - case SCRIPT_EVENT_BODYGROUPTEMP: - DevMsg( "Bodygroup!\n" ); - break; - - case AE_NPC_ATTACK_BROADCAST: - break; - - case NPC_EVENT_BODYDROP_HEAVY: - if ( GetFlags() & FL_ONGROUND ) - { - EmitSound( "AI_BaseNPC.BodyDrop_Heavy" ); - } - break; - - case NPC_EVENT_BODYDROP_LIGHT: - if ( GetFlags() & FL_ONGROUND ) - { - EmitSound( "AI_BaseNPC.BodyDrop_Light" ); - } - break; - - case NPC_EVENT_SWISHSOUND: - { - // NO NPC may use this anim event unless that npc's precache precaches this sound!!! - EmitSound( "AI_BaseNPC.SwishSound" ); - break; - } - - - case NPC_EVENT_180TURN: - { - //DevMsg( "Turned!\n" ); - SetIdealActivity( ACT_IDLE ); - Forget( bits_MEMORY_TURNING ); - SetBoneController( 0, GetLocalAngles().y ); - AddEffects( EF_NOINTERP ); - break; - } - - case NPC_EVENT_ITEM_PICKUP: - { - CBaseEntity *pPickup = NULL; - - // - // Figure out what we're supposed to pick up. - // - if ( pEvent->options && strlen( pEvent->options ) > 0 ) - { - // Pick up the weapon or item that was specified in the anim event. - pPickup = gEntList.FindEntityGenericNearest( pEvent->options, GetAbsOrigin(), 256, this ); - } - else - { - // Pick up the weapon or item that was found earlier and cached in our target pointer. - pPickup = GetTarget(); - } - - // Make sure we found something to pick up. - if ( !pPickup ) - { - TaskFail("Item no longer available!\n"); - break; - } - - // Make sure the item hasn't moved. - float flDist = ( pPickup->WorldSpaceCenter() - GetAbsOrigin() ).Length2D(); - if ( flDist > ITEM_PICKUP_TOLERANCE ) - { - TaskFail("Item has moved!\n"); - break; - } - - CBaseCombatWeapon *pWeapon = dynamic_cast( pPickup ); - if ( pWeapon ) - { - // Picking up a weapon. - CBaseCombatCharacter *pOwner = pWeapon->GetOwner(); - if ( pOwner ) - { - TaskFail( "Weapon in use by someone else" ); - } - else if ( !pWeapon ) - { - TaskFail( "Weapon doesn't exist" ); - } - else if (!Weapon_CanUse( pWeapon )) - { - TaskFail( "Can't use this weapon type" ); - } - else - { - PickupWeapon( pWeapon ); - TaskComplete(); - break; - } - } - else - { - // Picking up an item. - PickupItem( pPickup ); - TaskComplete(); - } - - break; - } - - case NPC_EVENT_WEAPON_SET_SEQUENCE_NUMBER: - { - CBaseCombatWeapon *pWeapon = GetActiveWeapon(); - if ((pWeapon) && (pEvent->options)) - { - int nSequence = atoi(pEvent->options); - if (nSequence != -1) - { - pWeapon->ResetSequence(nSequence); - } - } - break; - } - - case NPC_EVENT_WEAPON_SET_SEQUENCE_NAME: - { - CBaseCombatWeapon *pWeapon = GetActiveWeapon(); - if ((pWeapon) && (pEvent->options)) - { - int nSequence = pWeapon->LookupSequence(pEvent->options); - if (nSequence != -1) - { - pWeapon->ResetSequence(nSequence); - } - } - break; - } - - case NPC_EVENT_WEAPON_SET_ACTIVITY: - { - CBaseCombatWeapon *pWeapon = GetActiveWeapon(); - if ((pWeapon) && (pEvent->options)) - { - Activity act = (Activity)pWeapon->LookupActivity(pEvent->options); - if (act != ACT_INVALID) - { - // FIXME: where should the duration come from? normally it would come from the current sequence - Weapon_SetActivity(act, 0); - } - } - break; - } - - case NPC_EVENT_WEAPON_DROP: - { - // - // Drop our active weapon (or throw it at the specified target entity). - // - CBaseEntity *pTarget = NULL; - if (pEvent->options) - { - pTarget = gEntList.FindEntityGeneric(NULL, pEvent->options, this); - } - - if (pTarget) - { - Vector vecTargetPos = pTarget->WorldSpaceCenter(); - Weapon_Drop(GetActiveWeapon(), &vecTargetPos); - } - else - { - Weapon_Drop(GetActiveWeapon()); - } - - break; - } - - case EVENT_WEAPON_RELOAD: - { - if ( GetActiveWeapon() ) - { - GetActiveWeapon()->WeaponSound( RELOAD_NPC ); - GetActiveWeapon()->m_iClip1 = GetActiveWeapon()->GetMaxClip1(); - ClearCondition(COND_LOW_PRIMARY_AMMO); - ClearCondition(COND_NO_PRIMARY_AMMO); - ClearCondition(COND_NO_SECONDARY_AMMO); - } - break; - } - - case EVENT_WEAPON_RELOAD_SOUND: - { - if ( GetActiveWeapon() ) - { - GetActiveWeapon()->WeaponSound( RELOAD_NPC ); - } - break; - } - - case EVENT_WEAPON_RELOAD_FILL_CLIP: - { - if ( GetActiveWeapon() ) - { - GetActiveWeapon()->m_iClip1 = GetActiveWeapon()->GetMaxClip1(); - ClearCondition(COND_LOW_PRIMARY_AMMO); - ClearCondition(COND_NO_PRIMARY_AMMO); - ClearCondition(COND_NO_SECONDARY_AMMO); - } - break; - } - - case NPC_EVENT_LEFTFOOT: - case NPC_EVENT_RIGHTFOOT: - // For right now, do nothing. All functionality for this lives in individual npcs. - break; - - case NPC_EVENT_OPEN_DOOR: - { - CBasePropDoor *pDoor = (CBasePropDoor *)(CBaseEntity *)GetNavigator()->GetPath()->GetCurWaypoint()->GetEHandleData(); - if (pDoor != NULL) - { - OpenPropDoorNow( pDoor ); - } - - break; - } - - default: - if ((pEvent->type & AE_TYPE_NEWEVENTSYSTEM) && (pEvent->type & AE_TYPE_SERVER)) - { - if (pEvent->event == AE_NPC_HOLSTER) - { - // Cache off the weapon. - CBaseCombatWeapon *pWeapon = GetActiveWeapon(); - - Assert( pWeapon != NULL ); - - GetActiveWeapon()->Holster(); - SetActiveWeapon( NULL ); - - //Force the NPC to recalculate it's arrival activity since it'll most likely be wrong now that we don't have a weapon out. - GetNavigator()->SetArrivalSequence( ACT_INVALID ); - - if ( m_iDesiredWeaponState == DESIREDWEAPONSTATE_CHANGING_DESTROY ) - { - // Get rid of it! - UTIL_Remove( pWeapon ); - } - - if ( m_iDesiredWeaponState != DESIREDWEAPONSTATE_IGNORE ) - { - m_iDesiredWeaponState = DESIREDWEAPONSTATE_IGNORE; - m_Activity = ACT_RESET; - } - - return; - } - else if (pEvent->event == AE_NPC_DRAW) - { - if (GetActiveWeapon()) - { - GetActiveWeapon()->Deploy(); - - //Force the NPC to recalculate it's arrival activity since it'll most likely be wrong now. - GetNavigator()->SetArrivalSequence( ACT_INVALID ); - - if ( m_iDesiredWeaponState != DESIREDWEAPONSTATE_IGNORE ) - { - m_iDesiredWeaponState = DESIREDWEAPONSTATE_IGNORE; - m_Activity = ACT_RESET; - } - } - return; - } - else if ( pEvent->event == AE_NPC_BODYDROP_HEAVY ) - { - if ( GetFlags() & FL_ONGROUND ) - { - EmitSound( "AI_BaseNPC.BodyDrop_Heavy" ); - } - return; - } - else if ( pEvent->event == AE_NPC_LEFTFOOT || pEvent->event == AE_NPC_RIGHTFOOT ) - { - return; - } - else if ( pEvent->event == AE_NPC_RAGDOLL ) - { - // Convert to ragdoll immediately - BecomeRagdollOnClient( vec3_origin ); - return; - } - else if ( pEvent->event == AE_NPC_ADDGESTURE ) - { - Activity act = ( Activity )LookupActivity( pEvent->options ); - if (act != ACT_INVALID) - { - act = TranslateActivity( act ); - if (act != ACT_INVALID) - { - AddGesture( act ); - } - } - return; - } - else if ( pEvent->event == AE_NPC_RESTARTGESTURE ) - { - Activity act = ( Activity )LookupActivity( pEvent->options ); - if (act != ACT_INVALID) - { - act = TranslateActivity( act ); - if (act != ACT_INVALID) - { - RestartGesture( act ); - } - } - return; - } - else if ( pEvent->event == AE_NPC_WEAPON_DROP ) - { - // Drop our active weapon (or throw it at the specified target entity). - CBaseEntity *pTarget = NULL; - if (pEvent->options) - { - pTarget = gEntList.FindEntityGeneric(NULL, pEvent->options, this); - } - - if (pTarget) - { - Vector vecTargetPos = pTarget->WorldSpaceCenter(); - Weapon_Drop(GetActiveWeapon(), &vecTargetPos); - } - else - { - Weapon_Drop(GetActiveWeapon()); - } - return; - } - else if ( pEvent->event == AE_NPC_WEAPON_SET_ACTIVITY ) - { - CBaseCombatWeapon *pWeapon = GetActiveWeapon(); - if ((pWeapon) && (pEvent->options)) - { - Activity act = (Activity)pWeapon->LookupActivity(pEvent->options); - if (act == ACT_INVALID) - { - // Try and translate it - act = Weapon_TranslateActivity( (Activity)CAI_BaseNPC::GetActivityID(pEvent->options), false ); - } - - if (act != ACT_INVALID) - { - // FIXME: where should the duration come from? normally it would come from the current sequence - Weapon_SetActivity(act, 0); - } - } - return; - } - else if ( pEvent->event == AE_NPC_SET_INTERACTION_CANTDIE ) - { - SetInteractionCantDie( (atoi(pEvent->options) != 0) ); - return; - } - else if ( pEvent->event == AE_NPC_HURT_INTERACTION_PARTNER ) - { - // If we're currently interacting with an enemy, hurt them/me - if ( m_hInteractionPartner ) - { - CAI_BaseNPC *pTarget = NULL; - CAI_BaseNPC *pAttacker = NULL; - if ( pEvent->options ) - { - char szEventOptions[128]; - Q_strncpy( szEventOptions, pEvent->options, sizeof(szEventOptions) ); - char *pszParam = strtok( szEventOptions, " " ); - if ( pszParam ) - { - if ( !Q_strncmp( pszParam, "ME", 2 ) ) - { - pTarget = this; - pAttacker = m_hInteractionPartner; - } - else if ( !Q_strncmp( pszParam, "THEM", 4 ) ) - { - pAttacker = this; - pTarget = m_hInteractionPartner; - } - - pszParam = strtok(NULL," "); - if ( pAttacker && pTarget && pszParam ) - { - int iDamage = atoi( pszParam ); - if ( iDamage ) - { - // We've got a target, and damage. Now hurt them. - CTakeDamageInfo info; - info.SetDamage( iDamage ); - info.SetAttacker( pAttacker ); - info.SetInflictor( pAttacker ); - info.SetDamageType( DMG_GENERIC | DMG_PREVENT_PHYSICS_FORCE ); - pTarget->TakeDamage( info ); - return; - } - } - } - } - - // Bad data. Explain how to use this anim event. - const char *pName = EventList_NameForIndex( pEvent->event ); - DevWarning( 1, "Bad %s format. Should be: { AE_NPC_HURT_INTERACTION_PARTNER \" \" }\n", pName ); - return; - } - - DevWarning( "%s received AE_NPC_HURT_INTERACTION_PARTNER anim event, but it's not interacting with anything.\n", GetDebugName() ); - return; - } - } - - // FIXME: why doesn't this code pass unhandled events down to its parent? - // Came from my weapon? - //Adrian I'll clean this up once the old event system is phased out. - if ( pEvent->pSource != this || ( pEvent->type & AE_TYPE_NEWEVENTSYSTEM && pEvent->type & AE_TYPE_WEAPON ) || (pEvent->event >= EVENT_WEAPON && pEvent->event <= EVENT_WEAPON_LAST) ) - { - Weapon_HandleAnimEvent( pEvent ); - } - else - { - BaseClass::HandleAnimEvent( pEvent ); - } - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Override base class to add display of routes -// Input : -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -void CAI_BaseNPC::DrawDebugGeometryOverlays(void) -{ - // Handy for debug - //NDebugOverlay::Cross3D(EyePosition(),Vector(-2,-2,-2),Vector(2,2,2),0,255,0,true); - - // ------------------------------ - // Remove me if requested - // ------------------------------ - if (m_debugOverlays & OVERLAY_NPC_ZAP_BIT) - { - VacateStrategySlot(); - Weapon_Drop( GetActiveWeapon() ); - m_iHealth = 0; - SetThink( &CAI_BaseNPC::SUB_Remove ); - } - - // ------------------------------ - // properly kill an NPC. - // ------------------------------ - if (m_debugOverlays & OVERLAY_NPC_KILL_BIT) - { - CTakeDamageInfo info; - - info.SetDamage( m_iHealth ); - info.SetAttacker( this ); - info.SetInflictor( ( AI_IsSinglePlayer() ) ? (CBaseEntity *)AI_GetSinglePlayer() : (CBaseEntity *)this ); - info.SetDamageType( DMG_GENERIC ); - - m_debugOverlays &= ~OVERLAY_NPC_KILL_BIT; - TakeDamage( info ); - return; - } - - - // ------------------------------ - // Draw route if requested - // ------------------------------ - if ((m_debugOverlays & OVERLAY_NPC_ROUTE_BIT)) - { - GetNavigator()->DrawDebugRouteOverlay(); - if ( IsMoving() ) - { - float yaw = GetMotor()->GetIdealYaw(); - Vector vecYaw = UTIL_YawToVector(yaw); - NDebugOverlay::Line(WorldSpaceCenter(),WorldSpaceCenter() + vecYaw * GetHullWidth() * .5,255,255,255,true,0.0); - } - } - - if (!(CAI_BaseNPC::m_nDebugBits & bits_debugDisableAI) && (IsCurSchedule(SCHED_FORCED_GO) || IsCurSchedule(SCHED_FORCED_GO_RUN))) - { - NDebugOverlay::Box(m_vecLastPosition, Vector(-5,-5,-5),Vector(5,5,5), 255, 0, 255, 0, 0); - NDebugOverlay::HorzArrow( GetAbsOrigin(), m_vecLastPosition, 16, 255, 0, 255, 64, true, 0 ); - } - - // ------------------------------ - // Draw red box around if selected - // ------------------------------ - if ((m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) && !ai_no_select_box.GetBool()) - { - NDebugOverlay::EntityBounds(this, 255, 0, 0, 20, 0); - } - - // ------------------------------ - // Draw nearest node if selected - // ------------------------------ - if ((m_debugOverlays & OVERLAY_NPC_NEAREST_BIT)) - { - int iNodeID = GetPathfinder()->NearestNodeToNPC(); - if (iNodeID != NO_NODE) - { - NDebugOverlay::Box(GetNavigator()->GetNetwork()->AccessNodes()[iNodeID]->GetPosition(GetHullType()), Vector(-10,-10,-10),Vector(10,10,10), 255, 255, 255, 0, 0); - } - } - - // ------------------------------ - // Draw viewcone if selected - // ------------------------------ - if ((m_debugOverlays & OVERLAY_NPC_VIEWCONE_BIT)) - { - float flViewRange = acos(m_flFieldOfView); - Vector vEyeDir = EyeDirection2D( ); - Vector vLeftDir, vRightDir; - float fSin, fCos; - SinCos( flViewRange, &fSin, &fCos ); - - vLeftDir.x = vEyeDir.x * fCos - vEyeDir.y * fSin; - vLeftDir.y = vEyeDir.x * fSin + vEyeDir.y * fCos; - vLeftDir.z = vEyeDir.z; - fSin = sin(-flViewRange); - fCos = cos(-flViewRange); - vRightDir.x = vEyeDir.x * fCos - vEyeDir.y * fSin; - vRightDir.y = vEyeDir.x * fSin + vEyeDir.y * fCos; - vRightDir.z = vEyeDir.z; - - // Visualize it - NDebugOverlay::VertArrow( EyePosition(), EyePosition() + ( vLeftDir * 200 ), 64, 255, 0, 0, 50, false, 0 ); - NDebugOverlay::VertArrow( EyePosition(), EyePosition() + ( vRightDir * 200 ), 64, 255, 0, 0, 50, false, 0 ); - NDebugOverlay::VertArrow( EyePosition(), EyePosition() + ( vEyeDir * 100 ), 8, 0, 255, 0, 50, false, 0 ); - NDebugOverlay::Box(EyePosition(), -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, 128, 0 ); - } - - // ---------------------------------------------- - // Draw the relationships for this NPC to others - // ---------------------------------------------- - if ( m_debugOverlays & OVERLAY_NPC_RELATION_BIT ) - { - // Show the relationships to entities around us - int r = 0; - int g = 0; - int b = 0; - - int nRelationship; - CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); - - // Rate all NPCs - for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - if ( ppAIs[i] == NULL || ppAIs[i] == this ) - continue; - - // Get our relation to the target - nRelationship = IRelationType( ppAIs[i] ); - - // Get the color for the arrow - UTIL_GetDebugColorForRelationship( nRelationship, r, g, b ); - - // Draw an arrow - NDebugOverlay::HorzArrow( GetAbsOrigin(), ppAIs[i]->GetAbsOrigin(), 16, r, g, b, 64, true, 0.0f ); - } - - // Also include all players - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - if ( pPlayer == NULL ) - continue; - - // Get our relation to the target - nRelationship = IRelationType( pPlayer ); - - // Get the color for the arrow - UTIL_GetDebugColorForRelationship( nRelationship, r, g, b ); - - // Draw an arrow - NDebugOverlay::HorzArrow( GetAbsOrigin(), pPlayer->GetAbsOrigin(), 16, r, g, b, 64, true, 0.0f ); - } - } - - // ------------------------------ - // Draw enemies if selected - // ------------------------------ - if ((m_debugOverlays & OVERLAY_NPC_ENEMIES_BIT)) - { - AIEnemiesIter_t iter; - for( AI_EnemyInfo_t *eMemory = GetEnemies()->GetFirst(&iter); eMemory != NULL; eMemory = GetEnemies()->GetNext(&iter) ) - { - if (eMemory->hEnemy) - { - CBaseCombatCharacter *npcEnemy = (eMemory->hEnemy)->MyCombatCharacterPointer(); - if (npcEnemy) - { - int r,g,b; - char debugText[255]; - debugText[0] = '\0'; - - if (npcEnemy == GetEnemy()) - { - Q_strncat(debugText,"Current Enemy", sizeof( debugText ), COPY_ALL_CHARACTERS ); - } - else if (npcEnemy == GetTarget()) - { - Q_strncat(debugText,"Current Target", sizeof( debugText ), COPY_ALL_CHARACTERS ); - } - else - { - Q_strncat(debugText,"Other Memory", sizeof( debugText ), COPY_ALL_CHARACTERS ); - } - if (IsUnreachable(npcEnemy)) - { - Q_strncat(debugText," (Unreachable)", sizeof( debugText ), COPY_ALL_CHARACTERS ); - } - if (eMemory->bEludedMe) - { - Q_strncat(debugText," (Eluded)", sizeof( debugText ), COPY_ALL_CHARACTERS ); - } - // Unreachable enemy drawn in green - if (IsUnreachable(npcEnemy)) - { - r = 0; - g = 255; - b = 0; - } - // Eluded enemy drawn in blue - else if (eMemory->bEludedMe) - { - r = 0; - g = 0; - b = 255; - } - // Current enemy drawn in red - else if (npcEnemy == GetEnemy()) - { - r = 255; - g = 0; - b = 0; - } - // Current traget drawn in magenta - else if (npcEnemy == GetTarget()) - { - r = 255; - g = 0; - b = 255; - } - // All other enemies drawn in pink - else - { - r = 255; - g = 100; - b = 100; - } - - - Vector drawPos = eMemory->vLastKnownLocation; - NDebugOverlay::Text( drawPos, debugText, false, 0.0 ); - - // If has a line on the player draw cross slightly in front so player can see - if (npcEnemy->IsPlayer() && - (eMemory->vLastKnownLocation - npcEnemy->GetAbsOrigin()).Length()<10 ) - { - Vector vEnemyFacing = npcEnemy->BodyDirection2D( ); - Vector eyePos = npcEnemy->EyePosition() + vEnemyFacing*10.0; - Vector upVec = Vector(0,0,2); - Vector sideVec; - CrossProduct( vEnemyFacing, upVec, sideVec); - NDebugOverlay::Line(eyePos+sideVec+upVec, eyePos-sideVec-upVec, r,g,b, false,0); - NDebugOverlay::Line(eyePos+sideVec-upVec, eyePos-sideVec+upVec, r,g,b, false,0); - - NDebugOverlay::Text( eyePos, debugText, false, 0.0 ); - } - else - { - NDebugOverlay::Cross3D(drawPos,NAI_Hull::Mins(npcEnemy->GetHullType()),NAI_Hull::Maxs(npcEnemy->GetHullType()),r,g,b,false,0); - } - } - } - } - } - - // ---------------------------------------------- - // Draw line to target and enemy entity if exist - // ---------------------------------------------- - if ((m_debugOverlays & OVERLAY_NPC_FOCUS_BIT)) - { - if (GetEnemy() != NULL) - { - NDebugOverlay::Line(EyePosition(),GetEnemy()->EyePosition(),255,0,0,true,0.0); - } - if (GetTarget() != NULL) - { - NDebugOverlay::Line(EyePosition(),GetTarget()->EyePosition(),0,0,255,true,0.0); - } - } - - - GetPathfinder()->DrawDebugGeometryOverlays(m_debugOverlays); - - CBaseEntity::DrawDebugGeometryOverlays(); -} - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Input : -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CAI_BaseNPC::DrawDebugTextOverlays(void) -{ - int text_offset = 0; - - // --------------------- - // Print Baseclass text - // --------------------- - text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_NPC_SQUAD_BIT) - { - // Print health - char tempstr[512]; - Q_snprintf(tempstr,sizeof(tempstr),"Health: %i",m_iHealth); - EntityText(text_offset,tempstr,0); - text_offset++; - - // Print squad name - Q_strncpy(tempstr,"Squad: ",sizeof(tempstr)); - if (m_pSquad) - { - Q_strncat(tempstr,m_pSquad->GetName(),sizeof(tempstr), COPY_ALL_CHARACTERS); - - if( m_pSquad->GetLeader() == this ) - { - Q_strncat(tempstr," (LEADER)",sizeof(tempstr), COPY_ALL_CHARACTERS); - } - - Q_strncat(tempstr,"\n",sizeof(tempstr), COPY_ALL_CHARACTERS); - } - else - { - Q_strncat(tempstr," - \n",sizeof(tempstr), COPY_ALL_CHARACTERS); - } - EntityText(text_offset,tempstr,0); - text_offset++; - - // Print enemy name - Q_strncpy(tempstr,"Enemy: ",sizeof(tempstr)); - if (GetEnemy()) - { - if (GetEnemy()->GetEntityName() != NULL_STRING) - { - Q_strncat(tempstr,STRING(GetEnemy()->GetEntityName()),sizeof(tempstr), COPY_ALL_CHARACTERS); - Q_strncat(tempstr,"\n",sizeof(tempstr), COPY_ALL_CHARACTERS); - } - else - { - Q_strncat(tempstr,STRING(GetEnemy()->m_iClassname),sizeof(tempstr), COPY_ALL_CHARACTERS); - Q_strncat(tempstr,"\n",sizeof(tempstr), COPY_ALL_CHARACTERS); - } - } - else - { - Q_strncat(tempstr," - \n",sizeof(tempstr), COPY_ALL_CHARACTERS); - } - EntityText(text_offset,tempstr,0); - text_offset++; - - // Print slot - Q_snprintf(tempstr,sizeof(tempstr),"Slot: %s (%d)\n", - SquadSlotName(m_iMySquadSlot), m_iMySquadSlot); - EntityText(text_offset,tempstr,0); - text_offset++; - - } - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - // -------------- - // Print Health - // -------------- - Q_snprintf(tempstr,sizeof(tempstr),"Health: %i (DACC:%1.2f)",m_iHealth, GetDamageAccumulator() ); - EntityText(text_offset,tempstr,0); - text_offset++; - - // -------------- - // Print State - // -------------- - static const char *pStateNames[] = { "None", "Idle", "Alert", "Combat", "Scripted", "PlayDead", "Dead" }; - if ( (size_t)m_NPCState < ARRAYSIZE(pStateNames) ) - { - Q_snprintf(tempstr,sizeof(tempstr),"Stat: %s, ", pStateNames[m_NPCState] ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - - // ----------------- - // Start Scripting? - // ----------------- - if( IsInAScript() ) - { - Q_snprintf(tempstr,sizeof(tempstr),"STARTSCRIPTING" ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - - // ----------------- - // Hint Group? - // ----------------- - if( GetHintGroup() != NULL_STRING ) - { - Q_snprintf(tempstr,sizeof(tempstr),"Hint Group: %s", STRING(GetHintGroup()) ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - - // ----------------- - // Print MotionType - // ----------------- - int navTypeIndex = (int)GetNavType() + 1; - static const char *pMoveNames[] = { "None", "Ground", "Jump", "Fly", "Climb" }; - Assert( navTypeIndex >= 0 && navTypeIndex < (int)ARRAYSIZE(pMoveNames) ); - if ( navTypeIndex < (int)ARRAYSIZE(pMoveNames) ) - { - Q_snprintf(tempstr,sizeof(tempstr),"Move: %s, ", pMoveNames[navTypeIndex] ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - - // -------------- - // Print Schedule - // -------------- - if ( GetCurSchedule() ) - { - CAI_BehaviorBase *pBehavior = GetRunningBehavior(); - if ( pBehavior ) - { - Q_snprintf(tempstr,sizeof(tempstr),"Behv: %s, ", pBehavior->GetName() ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - - const char *pName = NULL; - pName = GetCurSchedule()->GetName(); - if ( !pName ) - { - pName = "Unknown"; - } - Q_snprintf(tempstr,sizeof(tempstr),"Schd: %s, ", pName ); - EntityText(text_offset,tempstr,0); - text_offset++; - - if (m_debugOverlays & OVERLAY_NPC_TASK_BIT) - { - for (int i = 0 ; i < GetCurSchedule()->NumTasks(); i++) - { - Q_snprintf(tempstr,sizeof(tempstr),"%s%s%s%s", - ((i==0) ? "Task:":" "), - ((i==GetScheduleCurTaskIndex()) ? "->" :" "), - TaskName(GetCurSchedule()->GetTaskList()[i].iTask), - ((i==GetScheduleCurTaskIndex()) ? "<-" :"")); - - EntityText(text_offset,tempstr,0); - text_offset++; - } - } - else - { - const Task_t *pTask = GetTask(); - if ( pTask ) - { - Q_snprintf(tempstr,sizeof(tempstr),"Task: %s (#%d), ", TaskName(pTask->iTask), GetScheduleCurTaskIndex() ); - } - else - { - Q_strncpy(tempstr,"Task: None",sizeof(tempstr)); - } - EntityText(text_offset,tempstr,0); - text_offset++; - } - } - - // -------------- - // Print Acitivity - // -------------- - if( m_Activity != ACT_INVALID && m_IdealActivity != ACT_INVALID && m_Activity != ACT_RESET) - { - Activity iActivity = TranslateActivity( m_Activity ); - - Activity iIdealActivity = Weapon_TranslateActivity( m_IdealActivity ); - iIdealActivity = NPC_TranslateActivity( iIdealActivity ); - - const char *pszActivity = GetActivityName( iActivity ); - const char *pszIdealActivity = GetActivityName( iIdealActivity ); - const char *pszRootActivity = GetActivityName( m_Activity ); - - Q_snprintf(tempstr,sizeof(tempstr),"Actv: %s (%s) [%s]\n", pszActivity, pszIdealActivity, pszRootActivity ); - } - else if (m_Activity == ACT_RESET) - { - Q_strncpy(tempstr,"Actv: RESET",sizeof(tempstr) ); - } - else - { - Q_strncpy(tempstr,"Actv: INVALID", sizeof(tempstr) ); - } - EntityText(text_offset,tempstr,0); - text_offset++; - - // - // Print all the current conditions. - // - if (m_debugOverlays & OVERLAY_NPC_CONDITIONS_BIT) - { - bool bHasConditions = false; - for (int i = 0; i < MAX_CONDITIONS; i++) - { - if (m_Conditions.IsBitSet(i)) - { - Q_snprintf(tempstr, sizeof(tempstr), "Cond: %s\n", ConditionName(AI_RemapToGlobal(i))); - EntityText(text_offset, tempstr, 0); - text_offset++; - bHasConditions = true; - } - } - if (!bHasConditions) - { - Q_snprintf(tempstr,sizeof(tempstr),"(no conditions)",m_iHealth); - EntityText(text_offset,tempstr,0); - text_offset++; - } - } - - if ( GetFlags() & FL_FLY ) - { - EntityText(text_offset,"HAS FL_FLY",0); - text_offset++; - } - - // -------------- - // Print Interrupte - // -------------- - if (m_interuptSchedule) - { - const char *pName = NULL; - pName = m_interuptSchedule->GetName(); - if ( !pName ) - { - pName = "Unknown"; - } - - Q_snprintf(tempstr,sizeof(tempstr),"Intr: %s (%s)\n", pName, m_interruptText ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - - // -------------- - // Print Failure - // -------------- - if (m_failedSchedule) - { - const char *pName = NULL; - pName = m_failedSchedule->GetName(); - if ( !pName ) - { - pName = "Unknown"; - } - Q_snprintf(tempstr,sizeof(tempstr),"Fail: %s (%s)\n", pName,m_failText ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - - - // ------------------------------- - // Print any important condtions - // ------------------------------- - if (HasCondition(COND_ENEMY_TOO_FAR)) - { - EntityText(text_offset,"Enemy too far to attack",0); - text_offset++; - } - if ( GetAbsVelocity() != vec3_origin || GetLocalAngularVelocity() != vec3_angle ) - { - char tmp[512]; - Q_snprintf( tmp, sizeof(tmp), "Vel %.1f %.1f %.1f Ang: %.1f %.1f %.1f\n", - GetAbsVelocity().x, GetAbsVelocity().y, GetAbsVelocity().z, - GetLocalAngularVelocity().x, GetLocalAngularVelocity().y, GetLocalAngularVelocity().z ); - EntityText(text_offset,tmp,0); - text_offset++; - } - - // ------------------------------- - // Print shot accuracy - // ------------------------------- - if ( m_LastShootAccuracy != -1 && ai_shot_stats.GetBool() ) - { - CFmtStr msg; - EntityText(text_offset,msg.sprintf("Cur Accuracy: %.1f", m_LastShootAccuracy),0); - text_offset++; - if ( m_TotalShots ) - { - EntityText(text_offset,msg.sprintf("Act Accuracy: %.1f", ((float)m_TotalHits/(float)m_TotalShots)*100.0),0); - text_offset++; - } - - if ( GetActiveWeapon() && GetEnemy() ) - { - Vector curSpread = GetAttackSpread(GetActiveWeapon(), GetEnemy()); - float curCone = RAD2DEG(asin(curSpread.x)) * 2; - float bias = GetSpreadBias( GetActiveWeapon(), GetEnemy()); - EntityText(text_offset,msg.sprintf("Cone %.1f, Bias %.2f", curCone, bias),0); - text_offset++; - } - } - - if ( GetGoalEnt() && GetNavigator()->GetGoalType() == GOALTYPE_PATHCORNER ) - { - Q_strncpy(tempstr,"Pathcorner/goal ent: ",sizeof(tempstr)); - if (GetGoalEnt()->GetEntityName() != NULL_STRING) - { - Q_strncat(tempstr,STRING(GetGoalEnt()->GetEntityName()),sizeof(tempstr), COPY_ALL_CHARACTERS); - } - else - { - Q_strncat(tempstr,STRING(GetGoalEnt()->m_iClassname),sizeof(tempstr), COPY_ALL_CHARACTERS); - } - EntityText(text_offset, tempstr, 0); - text_offset++; - } - - if ( VPhysicsGetObject() ) - { - vphysics_objectstress_t stressOut; - CalculateObjectStress( VPhysicsGetObject(), this, &stressOut ); - Q_snprintf(tempstr, sizeof(tempstr),"Stress: %.2f", stressOut.receivedStress ); - EntityText(text_offset, tempstr, 0); - text_offset++; - } - if ( m_pSquad ) - { - if( m_pSquad->IsLeader(this) ) - { - Q_snprintf(tempstr, sizeof(tempstr),"**Squad Leader**" ); - EntityText(text_offset, tempstr, 0); - text_offset++; - } - - Q_snprintf(tempstr, sizeof(tempstr), "SquadSlot:%s", GetSquadSlotDebugName( GetMyStrategySlot() ) ); - EntityText(text_offset, tempstr, 0); - text_offset++; - } - } - return text_offset; -} - - -//----------------------------------------------------------------------------- -// Purpose: Displays information in the console about the state of this npc. -//----------------------------------------------------------------------------- -void CAI_BaseNPC::ReportAIState( void ) -{ - static const char *pStateNames[] = { "None", "Idle", "Alert", "Combat", "Scripted", "PlayDead", "Dead" }; - - DevMsg( "%s: ", GetClassname() ); - if ( (size_t)m_NPCState < ARRAYSIZE(pStateNames) ) - DevMsg( "State: %s, ", pStateNames[m_NPCState] ); - - if( m_Activity != ACT_INVALID && m_IdealActivity != ACT_INVALID ) - { - const char *pszActivity = GetActivityName(m_Activity); - const char *pszIdealActivity = GetActivityName(m_IdealActivity); - - DevMsg( "Activity: %s - Ideal Activity: %s\n", pszActivity, pszIdealActivity ); - } - - if ( GetCurSchedule() ) - { - const char *pName = NULL; - pName = GetCurSchedule()->GetName(); - if ( !pName ) - pName = "Unknown"; - DevMsg( "Schedule %s, ", pName ); - const Task_t *pTask = GetTask(); - if ( pTask ) - DevMsg( "Task %d (#%d), ", pTask->iTask, GetScheduleCurTaskIndex() ); - } - else - DevMsg( "No Schedule, " ); - - if ( GetEnemy() != NULL ) - { - g_pEffects->Sparks( GetEnemy()->GetAbsOrigin() + Vector( 0, 0, 64 ) ); - DevMsg( "\nEnemy is %s", GetEnemy()->GetClassname() ); - } - else - DevMsg( "No enemy " ); - - if ( IsMoving() ) - { - DevMsg( " Moving " ); - if ( m_flMoveWaitFinished > gpGlobals->curtime ) - DevMsg( ": Stopped for %.2f. ", m_flMoveWaitFinished - gpGlobals->curtime ); - else if ( m_IdealActivity == GetStoppedActivity() ) - DevMsg( ": In stopped anim. " ); - } - - DevMsg( "Leader." ); - - DevMsg( "\n" ); - DevMsg( "Yaw speed:%3.1f,Health: %3d\n", GetMotor()->GetYawSpeed(), m_iHealth ); - - if ( GetGroundEntity() ) - { - DevMsg( "Groundent:%s\n\n", GetGroundEntity()->GetClassname() ); - } - else - { - DevMsg( "Groundent: NULL\n\n" ); - } -} - -//----------------------------------------------------------------------------- - -ConVar ai_report_task_timings_on_limit( "ai_report_task_timings_on_limit", "0", FCVAR_ARCHIVE ); -ConVar ai_think_limit_label( "ai_think_limit_label", "0", FCVAR_ARCHIVE ); - -void CAI_BaseNPC::ReportOverThinkLimit( float time ) -{ - DevMsg( "%s thinking for %.02fms!!! (%s); r%.2f (c%.2f, pst%.2f, ms%.2f), p-r%.2f, m%.2f\n", - GetDebugName(), time, GetCurSchedule()->GetName(), - g_AIRunTimer.GetDuration().GetMillisecondsF(), - g_AIConditionsTimer.GetDuration().GetMillisecondsF(), - g_AIPrescheduleThinkTimer.GetDuration().GetMillisecondsF(), - g_AIMaintainScheduleTimer.GetDuration().GetMillisecondsF(), - g_AIPostRunTimer.GetDuration().GetMillisecondsF(), - g_AIMoveTimer.GetDuration().GetMillisecondsF() ); - - if (ai_think_limit_label.GetBool()) - { - Vector tmp; - CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 1.0f ), &tmp ); - tmp.z += 16; - - float max = -1; - const char *pszMax = "unknown"; - - if ( g_AIConditionsTimer.GetDuration().GetMillisecondsF() > max ) - { - max = g_AIConditionsTimer.GetDuration().GetMillisecondsF(); - pszMax = "Conditions"; - } - if ( g_AIPrescheduleThinkTimer.GetDuration().GetMillisecondsF() > max ) - { - max = g_AIPrescheduleThinkTimer.GetDuration().GetMillisecondsF(); - pszMax = "Pre-think"; - } - if ( g_AIMaintainScheduleTimer.GetDuration().GetMillisecondsF() > max ) - { - max = g_AIMaintainScheduleTimer.GetDuration().GetMillisecondsF(); - pszMax = "Schedule"; - } - if ( g_AIPostRunTimer.GetDuration().GetMillisecondsF() > max ) - { - max = g_AIPostRunTimer.GetDuration().GetMillisecondsF(); - pszMax = "Post-run"; - } - if ( g_AIMoveTimer.GetDuration().GetMillisecondsF() > max ) - { - max = g_AIMoveTimer.GetDuration().GetMillisecondsF(); - pszMax = "Move"; - } - NDebugOverlay::Text( tmp, (char*)(const char *)CFmtStr( "Slow %.1f, %s %.1f ", time, pszMax, max ), false, 1 ); - } - - if ( ai_report_task_timings_on_limit.GetBool() ) - DumpTaskTimings(); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns whether or not this npc can play the scripted sequence or AI -// sequence that is trying to possess it. If DisregardState is set, the npc -// will be sucked into the script no matter what state it is in. ONLY -// Scripted AI ents should allow this. -// Input : fDisregardNPCState - -// interruptLevel - -// eMode - If the function returns true, eMode will be one of the following values: -// CAN_PLAY_NOW -// CAN_PLAY_ENQUEUED -// Output : -//----------------------------------------------------------------------------- -CanPlaySequence_t CAI_BaseNPC::CanPlaySequence( bool fDisregardNPCState, int interruptLevel ) -{ - CanPlaySequence_t eReturn = CAN_PLAY_NOW; - - if ( m_hCine ) - { - if ( !m_hCine->CanEnqueueAfter() ) - { - // npc is already running one scripted sequence and has an important script to play next - return CANNOT_PLAY; - } - - eReturn = CAN_PLAY_ENQUEUED; - } - - if ( !IsAlive() ) - { - // npc is dead! - return CANNOT_PLAY; - } - - // An NPC in a vehicle cannot play a scripted sequence - if ( IsInAVehicle() ) - return CANNOT_PLAY; - - if ( fDisregardNPCState ) - { - // ok to go, no matter what the npc state. (scripted AI) - - // No clue as to how to proced if they're climbing or jumping - // Assert( GetNavType() != NAV_JUMP && GetNavType() != NAV_CLIMB ); - - return eReturn; - } - - if ( m_NPCState == NPC_STATE_NONE || m_NPCState == NPC_STATE_IDLE || m_IdealNPCState == NPC_STATE_IDLE ) - { - // ok to go, but only in these states - return eReturn; - } - - if ( m_NPCState == NPC_STATE_ALERT && interruptLevel >= SS_INTERRUPT_BY_NAME ) - { - return eReturn; - } - - // unknown situation - return CANNOT_PLAY; -} - - -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::SetHintGroup( string_t newGroup, bool bHintGroupNavLimiting ) -{ - string_t oldGroup = m_strHintGroup; - m_strHintGroup = newGroup; - m_bHintGroupNavLimiting = bHintGroupNavLimiting; - - if ( oldGroup != newGroup ) - OnChangeHintGroup( oldGroup, newGroup ); - -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -Vector CAI_BaseNPC::GetShootEnemyDir( const Vector &shootOrigin, bool bNoisy ) -{ - CBaseEntity *pEnemy = GetEnemy(); - - if ( pEnemy ) - { - Vector vecEnemyLKP = GetEnemyLKP(); - - Vector vecEnemyOffset = pEnemy->BodyTarget( shootOrigin, bNoisy ) - pEnemy->GetAbsOrigin(); - -#ifdef PORTAL - // Translate the enemy's position across the portals if it's only seen in the portal view cone - if ( !FInViewCone( vecEnemyLKP ) || !FVisible( vecEnemyLKP ) ) - { - CProp_Portal *pPortal = FInViewConeThroughPortal( vecEnemyLKP ); - if ( pPortal ) - { - UTIL_Portal_VectorTransform( pPortal->m_hLinkedPortal->MatrixThisToLinked(), vecEnemyOffset, vecEnemyOffset ); - UTIL_Portal_PointTransform( pPortal->m_hLinkedPortal->MatrixThisToLinked(), vecEnemyLKP, vecEnemyLKP ); - } - } -#endif - - Vector retval = vecEnemyOffset + vecEnemyLKP - shootOrigin; - VectorNormalize( retval ); - return retval; - } - else - { - Vector forward; - AngleVectors( GetLocalAngles(), &forward ); - return forward; - } -} - -//----------------------------------------------------------------------------- -// Simulates many times and reports statistical accuracy. -//----------------------------------------------------------------------------- -void CAI_BaseNPC::CollectShotStats( const Vector &vecShootOrigin, const Vector &vecShootDir ) -{ -#ifdef HL2_DLL - if( ai_shot_stats.GetBool() != 0 && GetEnemy()->IsPlayer() ) - { - int iterations = ai_shot_stats_term.GetInt(); - int iHits = 0; - Vector testDir = vecShootDir; - - CShotManipulator manipulator( testDir ); - - for( int i = 0 ; i < iterations ; i++ ) - { - // Apply appropriate accuracy. - manipulator.ApplySpread( GetAttackSpread( GetActiveWeapon(), GetEnemy() ), GetSpreadBias( GetActiveWeapon(), GetEnemy() ) ); - Vector shotDir = manipulator.GetResult(); - - Vector vecEnd = vecShootOrigin + shotDir * 8192; - - trace_t tr; - AI_TraceLine( vecShootOrigin, vecEnd, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); - - if( tr.m_pEnt && tr.m_pEnt == GetEnemy() ) - { - iHits++; - } - Vector vecProjectedPosition = GetActualShootPosition( vecShootOrigin ); - Vector testDir = vecProjectedPosition - vecShootOrigin; - VectorNormalize( testDir ); - manipulator.SetShootDir( testDir ); - } - - float flHitPercent = ((float)iHits / (float)iterations) * 100.0; - m_LastShootAccuracy = flHitPercent; - //DevMsg("Shots:%d Hits:%d Percentage:%.1f\n", iterations, iHits, flHitPercent); - } - else - { - m_LastShootAccuracy = -1; - } -#endif -} - -#ifdef HL2_DLL -//----------------------------------------------------------------------------- -// Purpose: Return the actual position the NPC wants to fire at when it's trying -// to hit it's current enemy. -//----------------------------------------------------------------------------- -Vector CAI_BaseNPC::GetActualShootPosition( const Vector &shootOrigin ) -{ - // Project the target's location into the future. - Vector vecEnemyLKP = GetEnemyLKP(); - Vector vecEnemyOffset = GetEnemy()->BodyTarget( shootOrigin ) - GetEnemy()->GetAbsOrigin(); - Vector vecTargetPosition = vecEnemyOffset + vecEnemyLKP; - -#ifdef PORTAL - // Check if it's also visible through portals - CProp_Portal *pPortal = FInViewConeThroughPortal( vecEnemyLKP ); - if ( pPortal ) - { - // Get the target's position through portals - Vector vecEnemyOffsetTransformed; - Vector vecEnemyLKPTransformed; - UTIL_Portal_VectorTransform( pPortal->m_hLinkedPortal->MatrixThisToLinked(), vecEnemyOffset, vecEnemyOffsetTransformed ); - UTIL_Portal_PointTransform( pPortal->m_hLinkedPortal->MatrixThisToLinked(), vecEnemyLKP, vecEnemyLKPTransformed ); - Vector vecTargetPositionTransformed = vecEnemyOffsetTransformed + vecEnemyLKPTransformed; - - // Get the distance to the target with and without portals - float fDistanceToEnemyThroughPortalSqr = GetAbsOrigin().DistToSqr( vecTargetPositionTransformed ); - float fDistanceToEnemySqr = GetAbsOrigin().DistToSqr( vecTargetPosition ); - - if ( fDistanceToEnemyThroughPortalSqr < fDistanceToEnemySqr || !FInViewCone( vecEnemyLKP ) || !FVisible( vecEnemyLKP ) ) - { - // We're better off shooting through the portals - vecTargetPosition = vecTargetPositionTransformed; - } - } -#endif - - // lead for some fraction of a second. - return (vecTargetPosition + ( GetEnemy()->GetSmoothedVelocity() * ai_lead_time.GetFloat() )); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CAI_BaseNPC::GetSpreadBias( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget ) -{ - float bias = BaseClass::GetSpreadBias( pWeapon, pTarget ); - AI_EnemyInfo_t *pEnemyInfo = m_pEnemies->Find( pTarget ); - if ( ai_shot_bias.GetFloat() != 1.0 ) - bias = ai_shot_bias.GetFloat(); - if ( pEnemyInfo ) - { - float timeToFocus = ai_spread_pattern_focus_time.GetFloat(); - if ( timeToFocus > 0.0 ) - { - float timeSinceValidEnemy = gpGlobals->curtime - pEnemyInfo->timeValidEnemy; - if ( timeSinceValidEnemy < 0.0f ) - { - timeSinceValidEnemy = 0.0f; - } - float timeSinceReacquire = gpGlobals->curtime - pEnemyInfo->timeLastReacquired; - if ( timeSinceValidEnemy < timeToFocus ) - { - float scale = timeSinceValidEnemy / timeToFocus; - Assert( scale >= 0.0 && scale <= 1.0 ); - bias *= scale; - } - else if ( timeSinceReacquire < timeToFocus ) // handled seperately as might be tuning seperately - { - float scale = timeSinceReacquire / timeToFocus; - Assert( scale >= 0.0 && scale <= 1.0 ); - bias *= scale; - } - - } - } - return bias; -} - -//----------------------------------------------------------------------------- -Vector CAI_BaseNPC::GetAttackSpread( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget ) -{ - Vector baseResult = BaseClass::GetAttackSpread( pWeapon, pTarget ); - - AI_EnemyInfo_t *pEnemyInfo = m_pEnemies->Find( pTarget ); - if ( pEnemyInfo ) - { - float timeToFocus = ai_spread_cone_focus_time.GetFloat(); - if ( timeToFocus > 0.0 ) - { - float timeSinceValidEnemy = gpGlobals->curtime - pEnemyInfo->timeValidEnemy; - if ( timeSinceValidEnemy < 0 ) - timeSinceValidEnemy = 0; - if ( timeSinceValidEnemy < timeToFocus ) - { - float coneMultiplier = ai_spread_defocused_cone_multiplier.GetFloat(); - if ( coneMultiplier > 1.0 ) - { - float scale = 1.0 - timeSinceValidEnemy / timeToFocus; - Assert( scale >= 0.0 && scale <= 1.0 ); - float multiplier = ( (coneMultiplier - 1.0) * scale ) + 1.0; - baseResult *= multiplier; - } - } - } - } - return baseResult; -} - -//----------------------------------------------------------------------------- -// Similar to calling GetShootEnemyDir, but returns the exact trajectory to -// fire the bullet along, after calculating for target speed, location, -// concealment, etc. -// -// Ultimately, this code results in the shooter aiming his weapon somewhere ahead of -// a moving target. Since bullet traces are instant, aiming ahead of a target -// will result in more misses than hits. This is designed to provide targets with -// a bonus when moving perpendicular to the shooter's line of sight. -// -// Do not confuse this with leading a target in an effort to more easily hit it. -// -// This code PENALIZES a target for moving directly along the shooter's line of sight. -// -// This code REWARDS a target for moving perpendicular to the shooter's line of sight. -//----------------------------------------------------------------------------- -Vector CAI_BaseNPC::GetActualShootTrajectory( const Vector &shootOrigin ) -{ - if( !GetEnemy() ) - return GetShootEnemyDir( shootOrigin ); - - // If we're above water shooting at a player underwater, bias some of the shots forward of - // the player so that they see the cool bubble trails in the water ahead of them. - if (GetEnemy()->IsPlayer() && (GetWaterLevel() != 3) && (GetEnemy()->GetWaterLevel() == 3)) - { -#if 1 - if (random->RandomInt(0, 4) < 3) - { - Vector vecEnemyForward; - GetEnemy()->GetVectors( &vecEnemyForward, NULL, NULL ); - vecEnemyForward.z = 0; - - // Lead up to a second ahead of them unless they are moving backwards. - Vector vecEnemyVelocity = GetEnemy()->GetSmoothedVelocity(); - VectorNormalize( vecEnemyVelocity ); - float flVelocityScale = vecEnemyForward.Dot( vecEnemyVelocity ); - if ( flVelocityScale < 0.0f ) - { - flVelocityScale = 0.0f; - } - - Vector vecAimPos = GetEnemy()->EyePosition() + ( 48.0f * vecEnemyForward ) + (flVelocityScale * GetEnemy()->GetSmoothedVelocity() ); - //NDebugOverlay::Cross3D(vecAimPos, Vector(-16,-16,-16), Vector(16,16,16), 255, 255, 0, true, 1.0f ); - - //vecAimPos.z = UTIL_WaterLevel( vecAimPos, vecAimPos.z, vecAimPos.z + 400.0f ); - //NDebugOverlay::Cross3D(vecAimPos, Vector(-32,-32,-32), Vector(32,32,32), 255, 0, 0, true, 1.0f ); - - Vector vecShotDir = vecAimPos - shootOrigin; - VectorNormalize( vecShotDir ); - return vecShotDir; - } -#else - if (random->RandomInt(0, 4) < 3) - { - // Aim at a point a few feet in front of the player's eyes - Vector vecEnemyForward; - GetEnemy()->GetVectors( &vecEnemyForward, NULL, NULL ); - - Vector vecAimPos = GetEnemy()->EyePosition() + (120.0f * vecEnemyForward ); - - Vector vecShotDir = vecAimPos - shootOrigin; - VectorNormalize( vecShotDir ); - - CShotManipulator manipulator( vecShotDir ); - manipulator.ApplySpread( VECTOR_CONE_10DEGREES, 1 ); - vecShotDir = manipulator.GetResult(); - - return vecShotDir; - } -#endif - } - - Vector vecProjectedPosition = GetActualShootPosition( shootOrigin ); - - Vector shotDir = vecProjectedPosition - shootOrigin; - VectorNormalize( shotDir ); - - CollectShotStats( shootOrigin, shotDir ); - - // NOW we have a shoot direction. Where a 100% accurate bullet should go. - // Modify it by weapon proficiency. - // construct a manipulator - CShotManipulator manipulator( shotDir ); - - // Apply appropriate accuracy. - bool bUsePerfectAccuracy = false; - if ( GetEnemy() && GetEnemy()->Classify() == CLASS_BULLSEYE ) - { - CNPC_Bullseye *pBullseye = dynamic_cast(GetEnemy()); - if ( pBullseye && pBullseye->UsePerfectAccuracy() ) - { - bUsePerfectAccuracy = true; - } - } - - if ( !bUsePerfectAccuracy ) - { - manipulator.ApplySpread( GetAttackSpread( GetActiveWeapon(), GetEnemy() ), GetSpreadBias( GetActiveWeapon(), GetEnemy() ) ); - shotDir = manipulator.GetResult(); - } - - // Look for an opportunity to make misses hit interesting things. - CBaseCombatCharacter *pEnemy; - - pEnemy = GetEnemy()->MyCombatCharacterPointer(); - - if( pEnemy && pEnemy->ShouldShootMissTarget( this ) ) - { - Vector vecEnd = shootOrigin + shotDir * 8192; - trace_t tr; - - AI_TraceLine(shootOrigin, vecEnd, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); - - if( tr.fraction != 1.0 && tr.m_pEnt && tr.m_pEnt->m_takedamage != DAMAGE_NO ) - { - // Hit something we can harm. Just shoot it. - return manipulator.GetResult(); - } - - // Find something interesting around the enemy to shoot instead of just missing. - CBaseEntity *pMissTarget = pEnemy->FindMissTarget(); - - if( pMissTarget ) - { - shotDir = pMissTarget->WorldSpaceCenter() - shootOrigin; - VectorNormalize( shotDir ); - } - } - - return shotDir; -} -#endif // HL2_DLL - -//----------------------------------------------------------------------------- - -Vector CAI_BaseNPC::BodyTarget( const Vector &posSrc, bool bNoisy ) -{ - Vector low = WorldSpaceCenter() - ( WorldSpaceCenter() - GetAbsOrigin() ) * .25; - Vector high = EyePosition(); - Vector delta = high - low; - Vector result; - if ( bNoisy ) - { - // bell curve - float rand1 = random->RandomFloat( 0.0, 0.5 ); - float rand2 = random->RandomFloat( 0.0, 0.5 ); - result = low + delta * rand1 + delta * rand2; - } - else - result = low + delta * 0.5; - - return result; -} - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::ShouldMoveAndShoot() -{ - return ( ( CapabilitiesGet() & bits_CAP_MOVE_SHOOT ) != 0 ); -} - - -//========================================================= -// FacingIdeal - tells us if a npc is facing its ideal -// yaw. Created this function because many spots in the -// code were checking the yawdiff against this magic -// number. Nicer to have it in one place if we're gonna -// be stuck with it. -//========================================================= -bool CAI_BaseNPC::FacingIdeal( void ) -{ - if ( fabs( GetMotor()->DeltaIdealYaw() ) <= 0.006 )//!!!BUGBUG - no magic numbers!!! - { - return true; - } - - return false; -} - -//--------------------------------- - -void CAI_BaseNPC::AddFacingTarget( CBaseEntity *pTarget, float flImportance, float flDuration, float flRamp ) -{ - GetMotor()->AddFacingTarget( pTarget, flImportance, flDuration, flRamp ); -} - -void CAI_BaseNPC::AddFacingTarget( const Vector &vecPosition, float flImportance, float flDuration, float flRamp ) -{ - GetMotor()->AddFacingTarget( vecPosition, flImportance, flDuration, flRamp ); -} - -void CAI_BaseNPC::AddFacingTarget( CBaseEntity *pTarget, const Vector &vecPosition, float flImportance, float flDuration, float flRamp ) -{ - GetMotor()->AddFacingTarget( pTarget, vecPosition, flImportance, flDuration, flRamp ); -} - -float CAI_BaseNPC::GetFacingDirection( Vector &vecDir ) -{ - return (GetMotor()->GetFacingDirection( vecDir )); -} - - -//--------------------------------- - - -int CAI_BaseNPC::PlaySentence( const char *pszSentence, float delay, float volume, soundlevel_t soundlevel, CBaseEntity *pListener ) -{ - int sentenceIndex = -1; - - if ( pszSentence && IsAlive() ) - { - - if ( pszSentence[0] == '!' ) - { - sentenceIndex = SENTENCEG_Lookup( pszSentence ); - CPASAttenuationFilter filter( this, soundlevel ); - CBaseEntity::EmitSentenceByIndex( filter, entindex(), CHAN_VOICE, sentenceIndex, volume, soundlevel, 0, PITCH_NORM ); - } - else - { - sentenceIndex = SENTENCEG_PlayRndSz( edict(), pszSentence, volume, soundlevel, 0, PITCH_NORM ); - } - } - - return sentenceIndex; -} - - -int CAI_BaseNPC::PlayScriptedSentence( const char *pszSentence, float delay, float volume, soundlevel_t soundlevel, bool bConcurrent, CBaseEntity *pListener ) -{ - return PlaySentence( pszSentence, delay, volume, soundlevel, pListener ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -CBaseEntity *CAI_BaseNPC::FindNamedEntity( const char *name, IEntityFindFilter *pFilter ) -{ - if ( !stricmp( name, "!player" )) - { - return ( CBaseEntity * )AI_GetSinglePlayer(); - } - else if ( !stricmp( name, "!enemy" ) ) - { - if (GetEnemy() != NULL) - return GetEnemy(); - } - else if ( !stricmp( name, "!self" ) || !stricmp( name, "!target1" ) ) - { - return this; - } - else if ( !stricmp( name, "!nearestfriend" ) || !stricmp( name, "!friend" ) ) - { - // FIXME: look at CBaseEntity *CNPCSimpleTalker::FindNearestFriend(bool fPlayer) - // punt for now - return ( CBaseEntity * )AI_GetSinglePlayer(); - } - else if (!stricmp( name, "self" )) - { - static int selfwarningcount = 0; - - // fix the vcd, the reserved names have changed - if ( ++selfwarningcount < 5 ) - { - DevMsg( "ERROR: \"self\" is no longer used, use \"!self\" in vcd instead!\n" ); - } - return this; - } - else if ( !stricmp( name, "Player" )) - { - static int playerwarningcount = 0; - if ( ++playerwarningcount < 5 ) - { - DevMsg( "ERROR: \"player\" is no longer used, use \"!player\" in vcd instead!\n" ); - } - return ( CBaseEntity * )AI_GetSinglePlayer(); - } - else - { - // search for up to 32 entities with the same name and choose one randomly - CBaseEntity *entityList[ FINDNAMEDENTITY_MAX_ENTITIES ]; - CBaseEntity *entity; - int iCount; - - entity = NULL; - for( iCount = 0; iCount < FINDNAMEDENTITY_MAX_ENTITIES; iCount++ ) - { - entity = gEntList.FindEntityByName( entity, name, NULL, NULL, NULL, pFilter ); - if ( !entity ) - { - break; - } - entityList[ iCount ] = entity; - } - - if ( iCount > 0 ) - { - int index = RandomInt( 0, iCount - 1 ); - entity = entityList[ index ]; - return entity; - } - } - - return NULL; -} - - -void CAI_BaseNPC::CorpseFallThink( void ) -{ - if ( GetFlags() & FL_ONGROUND ) - { - SetThink ( NULL ); - - SetSequenceBox( ); - } - else - { - SetNextThink( gpGlobals->curtime + 0.1f ); - } -} - -// Call after animation/pose is set up -void CAI_BaseNPC::NPCInitDead( void ) -{ - InitBoneControllers(); - - RemoveSolidFlags( FSOLID_NOT_SOLID ); - - // so he'll fall to ground - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); - - SetCycle( 0 ); - ResetSequenceInfo( ); - m_flPlaybackRate = 0; - - // Copy health - m_iMaxHealth = m_iHealth; - m_lifeState = LIFE_DEAD; - - UTIL_SetSize(this, vec3_origin, vec3_origin ); - - // Setup health counters, etc. - SetThink( &CAI_BaseNPC::CorpseFallThink ); - - SetNextThink( gpGlobals->curtime + 0.5f ); -} - -//========================================================= -// BBoxIsFlat - check to see if the npc's bounding box -// is lying flat on a surface (traces from all four corners -// are same length.) -//========================================================= -bool CAI_BaseNPC::BBoxFlat ( void ) -{ - trace_t tr; - Vector vecPoint; - float flXSize, flYSize; - float flLength; - float flLength2; - - flXSize = WorldAlignSize().x / 2; - flYSize = WorldAlignSize().y / 2; - - vecPoint.x = GetAbsOrigin().x + flXSize; - vecPoint.y = GetAbsOrigin().y + flYSize; - vecPoint.z = GetAbsOrigin().z; - - AI_TraceLine ( vecPoint, vecPoint - Vector ( 0, 0, 100 ), MASK_NPCSOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - flLength = (vecPoint - tr.endpos).Length(); - - vecPoint.x = GetAbsOrigin().x - flXSize; - vecPoint.y = GetAbsOrigin().y - flYSize; - - AI_TraceLine ( vecPoint, vecPoint - Vector ( 0, 0, 100 ), MASK_NPCSOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - flLength2 = (vecPoint - tr.endpos).Length(); - if ( flLength2 > flLength ) - { - return false; - } - flLength = flLength2; - - vecPoint.x = GetAbsOrigin().x - flXSize; - vecPoint.y = GetAbsOrigin().y + flYSize; - AI_TraceLine ( vecPoint, vecPoint - Vector ( 0, 0, 100 ), MASK_NPCSOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - flLength2 = (vecPoint - tr.endpos).Length(); - if ( flLength2 > flLength ) - { - return false; - } - flLength = flLength2; - - vecPoint.x = GetAbsOrigin().x + flXSize; - vecPoint.y = GetAbsOrigin().y - flYSize; - AI_TraceLine ( vecPoint, vecPoint - Vector ( 0, 0, 100 ), MASK_NPCSOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - flLength2 = (vecPoint - tr.endpos).Length(); - if ( flLength2 > flLength ) - { - return false; - } - flLength = flLength2; - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEnemy - -// bSetCondNewEnemy - -//----------------------------------------------------------------------------- -void CAI_BaseNPC::SetEnemy( CBaseEntity *pEnemy, bool bSetCondNewEnemy ) -{ - if (m_hEnemy != pEnemy) - { - ClearAttackConditions( ); - VacateStrategySlot(); - m_GiveUpOnDeadEnemyTimer.Stop(); - - // If we've just found a new enemy, set the condition - if ( pEnemy && bSetCondNewEnemy ) - { - SetCondition( COND_NEW_ENEMY ); - } - } - - // Assert( (pEnemy == NULL) || (m_NPCState == NPC_STATE_COMBAT) ); - - m_hEnemy = pEnemy; - m_flTimeEnemyAcquired = gpGlobals->curtime; - - m_LastShootAccuracy = -1; - m_TotalShots = 0; - m_TotalHits = 0; - - if ( !pEnemy ) - ClearCondition( COND_NEW_ENEMY ); -} - -const Vector &CAI_BaseNPC::GetEnemyLKP() const -{ - return (const_cast(this))->GetEnemies()->LastKnownPosition( GetEnemy() ); -} - -float CAI_BaseNPC::GetEnemyLastTimeSeen() const -{ - return (const_cast(this))->GetEnemies()->LastTimeSeen( GetEnemy() ); -} - -void CAI_BaseNPC::MarkEnemyAsEluded() -{ - GetEnemies()->MarkAsEluded( GetEnemy() ); -} - -void CAI_BaseNPC::ClearEnemyMemory() -{ - GetEnemies()->ClearMemory( GetEnemy() ); -} - -bool CAI_BaseNPC::EnemyHasEludedMe() const -{ - return (const_cast(this))->GetEnemies()->HasEludedMe( GetEnemy() ); -} - -void CAI_BaseNPC::SetTarget( CBaseEntity *pTarget ) -{ - m_hTargetEnt = pTarget; -} - - -//========================================================= -// Choose Enemy - tries to find the best suitable enemy for the npc. -//========================================================= - -bool CAI_BaseNPC::ShouldChooseNewEnemy() -{ - CBaseEntity *pEnemy = GetEnemy(); - if ( pEnemy ) - { - if ( GetEnemies()->GetSerialNumber() != m_EnemiesSerialNumber ) - { - return true; - } - - m_EnemiesSerialNumber = GetEnemies()->GetSerialNumber(); - - if ( EnemyHasEludedMe() || (IRelationType( pEnemy ) != D_HT && IRelationType( pEnemy ) != D_FR) || !IsValidEnemy( pEnemy ) ) - { - DbgEnemyMsg( this, "ShouldChooseNewEnemy() --> true (1)\n" ); - return true; - } - if ( HasCondition(COND_SEE_HATE) || HasCondition(COND_SEE_DISLIKE) || HasCondition(COND_SEE_NEMESIS) || HasCondition(COND_SEE_FEAR) ) - { - DbgEnemyMsg( this, "ShouldChooseNewEnemy() --> true (2)\n" ); - return true; - } - if ( !pEnemy->IsAlive() ) - { - if ( m_GiveUpOnDeadEnemyTimer.IsRunning() ) - { - if ( m_GiveUpOnDeadEnemyTimer.Expired() ) - { - DbgEnemyMsg( this, "ShouldChooseNewEnemy() --> true (3)\n" ); - return true; - } - } - else - m_GiveUpOnDeadEnemyTimer.Start(); - } - - AI_EnemyInfo_t *pInfo = GetEnemies()->Find( pEnemy ); - - if ( m_FailChooseEnemyTimer.Expired() ) - { - m_FailChooseEnemyTimer.Set( 1.5 ); - if ( HasCondition( COND_TASK_FAILED ) || - ( pInfo && ( pInfo->timeAtFirstHand == AI_INVALID_TIME || gpGlobals->curtime - pInfo->timeLastSeen > 10 ) ) ) - { - return true; - } - } - - if ( pInfo && pInfo->timeValidEnemy < gpGlobals->curtime ) - { - DbgEnemyMsg( this, "ShouldChooseNewEnemy() --> false\n" ); - return false; - } - } - - DbgEnemyMsg( this, "ShouldChooseNewEnemy() --> true (4)\n" ); - m_EnemiesSerialNumber = GetEnemies()->GetSerialNumber(); - - return true; -} - -//------------------------------------- - -bool CAI_BaseNPC::ChooseEnemy( void ) -{ - AI_PROFILE_SCOPE(CAI_Enemies_ChooseEnemy); - - DbgEnemyMsg( this, "ChooseEnemy() {\n" ); - - //--------------------------------- - // - // Gather initial conditions - // - - CBaseEntity *pInitialEnemy = GetEnemy(); - CBaseEntity *pChosenEnemy = pInitialEnemy; - - // Use memory bits in case enemy pointer altered outside this function, (e.g., ehandle goes NULL) - bool fHadEnemy = ( HasMemory( bits_MEMORY_HAD_ENEMY | bits_MEMORY_HAD_PLAYER ) ); - bool fEnemyWasPlayer = HasMemory( bits_MEMORY_HAD_PLAYER ); - bool fEnemyWentNull = ( fHadEnemy && !pInitialEnemy ); - bool fEnemyEluded = ( fEnemyWentNull || ( pInitialEnemy && GetEnemies()->HasEludedMe( pInitialEnemy ) ) ); - - //--------------------------------- - // - // Establish suitability of choosing a new enemy - // - - bool fHaveCondNewEnemy; - bool fHaveCondLostEnemy; - - if ( !m_ScheduleState.bScheduleWasInterrupted && GetCurSchedule() && !FScheduleDone() ) - { - Assert( InterruptFromCondition( COND_NEW_ENEMY ) == COND_NEW_ENEMY && InterruptFromCondition( COND_LOST_ENEMY ) == COND_LOST_ENEMY ); - fHaveCondNewEnemy = GetCurSchedule()->HasInterrupt( COND_NEW_ENEMY ); - fHaveCondLostEnemy = GetCurSchedule()->HasInterrupt( COND_LOST_ENEMY ); - - // See if they've been added as a custom interrupt - if ( !fHaveCondNewEnemy ) - { - fHaveCondNewEnemy = IsCustomInterruptConditionSet( COND_NEW_ENEMY ); - } - if ( !fHaveCondLostEnemy ) - { - fHaveCondLostEnemy = IsCustomInterruptConditionSet( COND_LOST_ENEMY ); - } - } - else - { - fHaveCondNewEnemy = true; // not having a schedule is the same as being interruptable by any condition - fHaveCondLostEnemy = true; - } - - if ( !fEnemyWentNull ) - { - if ( !fHaveCondNewEnemy && !( fHaveCondLostEnemy && fEnemyEluded ) ) - { - // DO NOT mess with the npc's enemy pointer unless the schedule the npc is currently - // running will be interrupted by COND_NEW_ENEMY or COND_LOST_ENEMY. This will - // eliminate the problem of npcs getting a new enemy while they are in a schedule - // that doesn't care, and then not realizing it by the time they get to a schedule - // that does. I don't feel this is a good permanent fix. - m_bSkippedChooseEnemy = true; - - DbgEnemyMsg( this, "Skipped enemy selection due to schedule restriction\n" ); - DbgEnemyMsg( this, "}\n" ); - return ( pChosenEnemy != NULL ); - } - } - else if ( !fHaveCondNewEnemy && !fHaveCondLostEnemy && GetCurSchedule() ) - { - DevMsg( 2, "WARNING: AI enemy went NULL but schedule (%s) is not interested\n", GetCurSchedule()->GetName() ); - } - - m_bSkippedChooseEnemy = false; - - //--------------------------------- - // - // Select a target - // - - if ( ShouldChooseNewEnemy() ) - { - pChosenEnemy = BestEnemy(); - } - - //--------------------------------- - // - // React to result of selection - // - - bool fChangingEnemy = ( pChosenEnemy != pInitialEnemy ); - - if ( fChangingEnemy || fEnemyWentNull ) - { - DbgEnemyMsg( this, "Enemy changed from %s to %s\n", pInitialEnemy->GetDebugName(), pChosenEnemy->GetDebugName() ); - Forget( bits_MEMORY_HAD_ENEMY | bits_MEMORY_HAD_PLAYER ); - - // Did our old enemy snuff it? - if ( pInitialEnemy && !pInitialEnemy->IsAlive() ) - { - SetCondition( COND_ENEMY_DEAD ); - } - - SetEnemy( pChosenEnemy ); - - if ( fHadEnemy ) - { - // Vacate any strategy slot on old enemy - VacateStrategySlot(); - - // Force output event for establishing LOS - Forget( bits_MEMORY_HAD_LOS ); - // m_flLastAttackTime = 0; - } - - if ( !pChosenEnemy ) - { - // Don't break on enemies going null if they've been killed - if ( !HasCondition(COND_ENEMY_DEAD) ) - { - SetCondition( COND_ENEMY_WENT_NULL ); - } - - if ( fEnemyEluded ) - { - SetCondition( COND_LOST_ENEMY ); - LostEnemySound(); - } - - if ( fEnemyWasPlayer ) - { - m_OnLostPlayer.FireOutput( pInitialEnemy, this ); - } - m_OnLostEnemy.FireOutput( pInitialEnemy, this); - } - else - { - Remember( ( pChosenEnemy->IsPlayer() ) ? bits_MEMORY_HAD_PLAYER : bits_MEMORY_HAD_ENEMY ); - } - } - - //--------------------------------- - - return ( pChosenEnemy != NULL ); -} - - -//========================================================= -void CAI_BaseNPC::PickupWeapon( CBaseCombatWeapon *pWeapon ) -{ - pWeapon->OnPickedUp( this ); - Weapon_Equip( pWeapon ); - m_iszPendingWeapon = NULL_STRING; -} - -//========================================================= -// DropItem - dead npc drops named item -//========================================================= -CBaseEntity *CAI_BaseNPC::DropItem ( const char *pszItemName, Vector vecPos, QAngle vecAng ) -{ - if ( !pszItemName ) - { - DevMsg( "DropItem() - No item name!\n" ); - return NULL; - } - - CBaseEntity *pItem = CBaseEntity::Create( pszItemName, vecPos, vecAng, this ); - - if ( pItem ) - { - if ( g_pGameRules->IsAllowedToSpawn( pItem ) == false ) - { - UTIL_Remove( pItem ); - return NULL; - } - - IPhysicsObject *pPhys = pItem->VPhysicsGetObject(); - - if ( pPhys ) - { - // Add an extra push in a random direction - Vector vel = RandomVector( -64.0f, 64.0f ); - AngularImpulse angImp = RandomAngularImpulse( -300.0f, 300.0f ); - - vel[2] = 0.0f; - pPhys->AddVelocity( &vel, &angImp ); - } - else - { - // do we want this behavior to be default?! (sjb) - pItem->ApplyAbsVelocityImpulse( GetAbsVelocity() ); - pItem->ApplyLocalAngularVelocityImpulse( AngularImpulse( 0, random->RandomFloat( 0, 100 ), 0 ) ); - } - - return pItem; - } - else - { - DevMsg( "DropItem() - Didn't create!\n" ); - return NULL; - } - -} - -bool CAI_BaseNPC::ShouldFadeOnDeath( void ) -{ - if ( g_RagdollLVManager.IsLowViolence() ) - { - return true; - } - else - { - // if flagged to fade out - return HasSpawnFlags(SF_NPC_FADE_CORPSE); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Indicates whether or not this npc should play an idle sound now. -// -// -// Output : Returns true if yes, false if no. -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::ShouldPlayIdleSound( void ) -{ - if ( ( m_NPCState == NPC_STATE_IDLE || m_NPCState == NPC_STATE_ALERT ) && - random->RandomInt(0,99) == 0 && !HasSpawnFlags(SF_NPC_GAG) ) - { - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Make a sound that other AI's can hear, to broadcast our presence -// Input : volume (radius) of the sound. -// Output : -//----------------------------------------------------------------------------- -void CAI_BaseNPC::MakeAIFootstepSound( float volume, float duration ) -{ - CSoundEnt::InsertSound( SOUND_COMBAT, EyePosition(), (int)volume, duration, this, SOUNDENT_CHANNEL_NPC_FOOTSTEP ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::FOkToMakeSound( int soundPriority ) -{ - // ask the squad to filter sounds if I'm in one - if ( m_pSquad ) - { - if ( !m_pSquad->FOkToMakeSound( soundPriority ) ) - return false; - } - else - { - // otherwise, check my own sound timer - // Am I making uninterruptable sound? - if (gpGlobals->curtime <= m_flSoundWaitTime) - { - if ( soundPriority <= m_nSoundPriority ) - return false; - } - } - - // no talking outside of combat if gagged. - if ( HasSpawnFlags(SF_NPC_GAG) && ( m_NPCState != NPC_STATE_COMBAT ) ) - return false; - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_BaseNPC::JustMadeSound( int soundPriority, float flSoundLength ) -{ - m_flSoundWaitTime = gpGlobals->curtime + flSoundLength + random->RandomFloat(1.5, 2.0); - m_nSoundPriority = soundPriority; - - if (m_pSquad) - { - m_pSquad->JustMadeSound( soundPriority, gpGlobals->curtime + flSoundLength + random->RandomFloat(1.5, 2.0) ); - } -} - -Activity CAI_BaseNPC::GetStoppedActivity( void ) -{ - if (GetNavigator()->IsGoalActive()) - { - Activity activity = GetNavigator()->GetArrivalActivity(); - - if (activity > ACT_RESET) - { - return activity; - } - } - - return ACT_IDLE; -} - - -//========================================================= -//========================================================= -void CAI_BaseNPC::OnScheduleChange ( void ) -{ - EndTaskOverlay(); - - m_pNavigator->OnScheduleChange(); - - m_flMoveWaitFinished = 0; - - VacateStrategySlot(); - - // If I still have have a route, clear it - // FIXME: Routes should only be cleared inside of tasks (kenb) - GetNavigator()->ClearGoal(); - - UnlockBestSound(); - - // If I locked a hint node clear it - if ( HasMemory(bits_MEMORY_LOCKED_HINT) && GetHintNode() != NULL) - { - float hintDelay = GetHintDelay(GetHintNode()->HintType()); - GetHintNode()->Unlock(hintDelay); - SetHintNode( NULL ); - } -} - - - -CBaseCombatCharacter* CAI_BaseNPC::GetEnemyCombatCharacterPointer() -{ - if ( GetEnemy() == NULL ) - return NULL; - - return GetEnemy()->MyCombatCharacterPointer(); -} - - -// Global Savedata for npc -// -// This should be an exact copy of the var's in the header. Fields -// that aren't save/restored are commented out - -BEGIN_DATADESC( CAI_BaseNPC ) - - // m_pSchedule (reacquired on restore) - DEFINE_EMBEDDED( m_ScheduleState ), - DEFINE_FIELD( m_IdealSchedule, FIELD_INTEGER ), // handled specially but left in for "virtual" schedules - DEFINE_FIELD( m_failSchedule, FIELD_INTEGER ), // handled specially but left in for "virtual" schedules - DEFINE_FIELD( m_bUsingStandardThinkTime, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flLastRealThinkTime, FIELD_TIME ), - // m_iFrameBlocked (not saved) - // m_bInChoreo (not saved) - // m_bDoPostRestoreRefindPath (not saved) - // gm_flTimeLastSpawn (static) - // gm_nSpawnedThisFrame (static) - // m_Conditions (custom save) - // m_CustomInterruptConditions (custom save) - // m_ConditionsPreIgnore (custom save) - // m_InverseIgnoreConditions (custom save) - // m_poseAim_Pitch (not saved; recomputed on restore) - // m_poseAim_Yaw (not saved; recomputed on restore) - // m_poseMove_Yaw (not saved; recomputed on restore) - DEFINE_FIELD( m_flTimePingEffect, FIELD_TIME ), - DEFINE_FIELD( m_bForceConditionsGather, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bConditionsGathered, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bSkippedChooseEnemy, FIELD_BOOLEAN ), - DEFINE_FIELD( m_NPCState, FIELD_INTEGER ), - DEFINE_FIELD( m_IdealNPCState, FIELD_INTEGER ), - DEFINE_FIELD( m_flLastStateChangeTime, FIELD_TIME ), - DEFINE_FIELD( m_Efficiency, FIELD_INTEGER ), - DEFINE_FIELD( m_MoveEfficiency, FIELD_INTEGER ), - DEFINE_FIELD( m_flNextDecisionTime, FIELD_TIME ), - DEFINE_KEYFIELD( m_SleepState, FIELD_INTEGER, "sleepstate" ), - DEFINE_FIELD( m_SleepFlags, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_flWakeRadius, FIELD_FLOAT, "wakeradius" ), - DEFINE_KEYFIELD( m_bWakeSquad, FIELD_BOOLEAN, "wakesquad" ), - DEFINE_FIELD( m_nWakeTick, FIELD_TICK ), - - DEFINE_CUSTOM_FIELD( m_Activity, ActivityDataOps() ), - DEFINE_CUSTOM_FIELD( m_translatedActivity, ActivityDataOps() ), - DEFINE_CUSTOM_FIELD( m_IdealActivity, ActivityDataOps() ), - DEFINE_CUSTOM_FIELD( m_IdealTranslatedActivity, ActivityDataOps() ), - DEFINE_CUSTOM_FIELD( m_IdealWeaponActivity, ActivityDataOps() ), - - DEFINE_FIELD( m_nIdealSequence, FIELD_INTEGER ), - DEFINE_EMBEDDEDBYREF( m_pSenses ), - DEFINE_EMBEDDEDBYREF( m_pLockedBestSound ), - DEFINE_FIELD( m_hEnemy, FIELD_EHANDLE ), - DEFINE_FIELD( m_flTimeEnemyAcquired, FIELD_TIME ), - DEFINE_FIELD( m_hTargetEnt, FIELD_EHANDLE ), - DEFINE_EMBEDDED( m_GiveUpOnDeadEnemyTimer ), - DEFINE_EMBEDDED( m_FailChooseEnemyTimer ), - DEFINE_FIELD( m_EnemiesSerialNumber, FIELD_INTEGER ), - DEFINE_FIELD( m_flAcceptableTimeSeenEnemy, FIELD_TIME ), - DEFINE_EMBEDDED( m_UpdateEnemyPosTimer ), - // m_flTimeAnyUpdateEnemyPos (static) - DEFINE_FIELD( m_vecCommandGoal, FIELD_VECTOR ), - DEFINE_EMBEDDED( m_CommandMoveMonitor ), - DEFINE_FIELD( m_flSoundWaitTime, FIELD_TIME ), - DEFINE_FIELD( m_nSoundPriority, FIELD_INTEGER ), - DEFINE_FIELD( m_flIgnoreDangerSoundsUntil, FIELD_TIME ), - DEFINE_FIELD( m_afCapability, FIELD_INTEGER ), - DEFINE_FIELD( m_flMoveWaitFinished, FIELD_TIME ), - DEFINE_FIELD( m_hOpeningDoor, FIELD_EHANDLE ), - DEFINE_EMBEDDEDBYREF( m_pNavigator ), - DEFINE_EMBEDDEDBYREF( m_pLocalNavigator ), - DEFINE_EMBEDDEDBYREF( m_pPathfinder ), - DEFINE_EMBEDDEDBYREF( m_pMoveProbe ), - DEFINE_EMBEDDEDBYREF( m_pMotor ), - DEFINE_UTLVECTOR(m_UnreachableEnts, FIELD_EMBEDDED), - DEFINE_FIELD( m_hInteractionPartner, FIELD_EHANDLE ), - DEFINE_FIELD( m_hLastInteractionTestTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_hForcedInteractionPartner, FIELD_EHANDLE ), - DEFINE_FIELD( m_flForcedInteractionTimeout, FIELD_TIME ), - DEFINE_FIELD( m_vecForcedWorldPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_bCannotDieDuringInteraction, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iInteractionState, FIELD_INTEGER ), - DEFINE_FIELD( m_iInteractionPlaying, FIELD_INTEGER ), - DEFINE_UTLVECTOR(m_ScriptedInteractions,FIELD_EMBEDDED), - DEFINE_FIELD( m_flInteractionYaw, FIELD_FLOAT ), - DEFINE_EMBEDDED( m_CheckOnGroundTimer ), - DEFINE_FIELD( m_vDefaultEyeOffset, FIELD_VECTOR ), - DEFINE_FIELD( m_flNextEyeLookTime, FIELD_TIME ), - DEFINE_FIELD( m_flEyeIntegRate, FIELD_FLOAT ), - DEFINE_FIELD( m_vEyeLookTarget, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vCurEyeTarget, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_hEyeLookTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_flHeadYaw, FIELD_FLOAT ), - DEFINE_FIELD( m_flHeadPitch, FIELD_FLOAT ), - DEFINE_FIELD( m_flOriginalYaw, FIELD_FLOAT ), - DEFINE_FIELD( m_bInAScript, FIELD_BOOLEAN ), - DEFINE_FIELD( m_scriptState, FIELD_INTEGER ), - DEFINE_FIELD( m_hCine, FIELD_EHANDLE ), - DEFINE_CUSTOM_FIELD( m_ScriptArrivalActivity, ActivityDataOps() ), - DEFINE_FIELD( m_strScriptArrivalSequence, FIELD_STRING ), - DEFINE_FIELD( m_flSceneTime, FIELD_TIME ), - DEFINE_FIELD( m_iszSceneCustomMoveSeq, FIELD_STRING ), - // m_pEnemies Saved specially in ai_saverestore.cpp - DEFINE_FIELD( m_afMemory, FIELD_INTEGER ), - DEFINE_FIELD( m_hEnemyOccluder, FIELD_EHANDLE ), - DEFINE_FIELD( m_flSumDamage, FIELD_FLOAT ), - DEFINE_FIELD( m_flLastDamageTime, FIELD_TIME ), - DEFINE_FIELD( m_flLastPlayerDamageTime, FIELD_TIME ), - DEFINE_FIELD( m_flLastSawPlayerTime, FIELD_TIME ), - DEFINE_FIELD( m_flLastAttackTime, FIELD_TIME ), - DEFINE_FIELD( m_flLastEnemyTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextWeaponSearchTime, FIELD_TIME ), - DEFINE_FIELD( m_iszPendingWeapon, FIELD_STRING ), - DEFINE_KEYFIELD( m_bIgnoreUnseenEnemies, FIELD_BOOLEAN , "ignoreunseenenemies"), - DEFINE_EMBEDDED( m_ShotRegulator ), - DEFINE_FIELD( m_iDesiredWeaponState, FIELD_INTEGER ), - // m_pSquad Saved specially in ai_saverestore.cpp - DEFINE_KEYFIELD(m_SquadName, FIELD_STRING, "squadname" ), - DEFINE_FIELD( m_iMySquadSlot, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_strHintGroup, FIELD_STRING, "hintgroup" ), - DEFINE_KEYFIELD( m_bHintGroupNavLimiting, FIELD_BOOLEAN, "hintlimiting" ), - DEFINE_EMBEDDEDBYREF( m_pTacticalServices ), - DEFINE_FIELD( m_flWaitFinished, FIELD_TIME ), - DEFINE_FIELD( m_flNextFlinchTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextDodgeTime, FIELD_TIME ), - DEFINE_EMBEDDED( m_MoveAndShootOverlay ), - DEFINE_FIELD( m_vecLastPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vSavePosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vInterruptSavePosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_pHintNode, FIELD_EHANDLE), - DEFINE_FIELD( m_cAmmoLoaded, FIELD_INTEGER ), - DEFINE_FIELD( m_flDistTooFar, FIELD_FLOAT ), - DEFINE_FIELD( m_hGoalEnt, FIELD_EHANDLE ), - DEFINE_FIELD( m_flTimeLastMovement, FIELD_TIME ), - DEFINE_KEYFIELD(m_spawnEquipment, FIELD_STRING, "additionalequipment" ), - DEFINE_FIELD( m_fNoDamageDecal, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hStoredPathTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_vecStoredPathGoal, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_nStoredPathType, FIELD_INTEGER ), - DEFINE_FIELD( m_fStoredPathFlags, FIELD_INTEGER ), - DEFINE_FIELD( m_bDidDeathCleanup, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bCrouchDesired, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bForceCrouch, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bIsCrouching, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bPerformAvoidance, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bIsMoving, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bFadeCorpse, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iDeathPose, FIELD_INTEGER ), - DEFINE_FIELD( m_iDeathFrame, FIELD_INTEGER ), - DEFINE_FIELD( m_bCheckContacts, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bSpeedModActive, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iSpeedModRadius, FIELD_INTEGER ), - DEFINE_FIELD( m_iSpeedModSpeed, FIELD_INTEGER ), - DEFINE_FIELD( m_hEnemyFilter, FIELD_EHANDLE ), - DEFINE_KEYFIELD( m_iszEnemyFilterName, FIELD_STRING, "enemyfilter" ), - DEFINE_FIELD( m_bImportanRagdoll, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bPlayerAvoidState, FIELD_BOOLEAN ), - - // Satisfy classcheck - // DEFINE_FIELD( m_ScheduleHistory, CUtlVector < AIScheduleChoice_t > ), - - // m_fIsUsingSmallHull TODO -- This needs more consideration than simple save/load - // m_failText DEBUG - // m_interruptText DEBUG - // m_failedSchedule DEBUG - // m_interuptSchedule DEBUG - // m_nDebugCurIndex DEBUG - - // m_LastShootAccuracy DEBUG - // m_RecentShotAccuracy DEBUG - // m_TotalShots DEBUG - // m_TotalHits DEBUG - // m_bSelected DEBUG - // m_TimeLastShotMark DEBUG - // m_bDeferredNavigation - - - // Outputs - DEFINE_OUTPUT( m_OnDamaged, "OnDamaged" ), - DEFINE_OUTPUT( m_OnDeath, "OnDeath" ), - DEFINE_OUTPUT( m_OnHalfHealth, "OnHalfHealth" ), - DEFINE_OUTPUT( m_OnFoundEnemy, "OnFoundEnemy" ), - DEFINE_OUTPUT( m_OnLostEnemyLOS, "OnLostEnemyLOS" ), - DEFINE_OUTPUT( m_OnLostEnemy, "OnLostEnemy" ), - DEFINE_OUTPUT( m_OnFoundPlayer, "OnFoundPlayer" ), - DEFINE_OUTPUT( m_OnLostPlayerLOS, "OnLostPlayerLOS" ), - DEFINE_OUTPUT( m_OnLostPlayer, "OnLostPlayer" ), - DEFINE_OUTPUT( m_OnHearWorld, "OnHearWorld" ), - DEFINE_OUTPUT( m_OnHearPlayer, "OnHearPlayer" ), - DEFINE_OUTPUT( m_OnHearCombat, "OnHearCombat" ), - DEFINE_OUTPUT( m_OnDamagedByPlayer, "OnDamagedByPlayer" ), - DEFINE_OUTPUT( m_OnDamagedByPlayerSquad, "OnDamagedByPlayerSquad" ), - DEFINE_OUTPUT( m_OnDenyCommanderUse, "OnDenyCommanderUse" ), - DEFINE_OUTPUT( m_OnRappelTouchdown, "OnRappelTouchdown" ), - DEFINE_OUTPUT( m_OnWake, "OnWake" ), - DEFINE_OUTPUT( m_OnSleep, "OnSleep" ), - DEFINE_OUTPUT( m_OnForcedInteractionStarted, "OnForcedInteractionStarted" ), - DEFINE_OUTPUT( m_OnForcedInteractionAborted, "OnForcedInteractionAborted" ), - DEFINE_OUTPUT( m_OnForcedInteractionFinished, "OnForcedInteractionFinished" ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_STRING, "SetRelationship", InputSetRelationship ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetEnemyFilter", InputSetEnemyFilter ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetHealth", InputSetHealth ), - DEFINE_INPUTFUNC( FIELD_VOID, "BeginRappel", InputBeginRappel ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetSquad", InputSetSquad ), - DEFINE_INPUTFUNC( FIELD_VOID, "Wake", InputWake ), - DEFINE_INPUTFUNC( FIELD_STRING, "ForgetEntity", InputForgetEntity ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "IgnoreDangerSounds", InputIgnoreDangerSounds ), - DEFINE_INPUTFUNC( FIELD_VOID, "Break", InputBreak ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartScripting", InputStartScripting ), - DEFINE_INPUTFUNC( FIELD_VOID, "StopScripting", InputStopScripting ), - DEFINE_INPUTFUNC( FIELD_VOID, "GagEnable", InputGagEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "GagDisable", InputGagDisable ), - DEFINE_INPUTFUNC( FIELD_VOID, "InsideTransition", InputInsideTransition ), - DEFINE_INPUTFUNC( FIELD_VOID, "OutsideTransition", InputOutsideTransition ), - DEFINE_INPUTFUNC( FIELD_VOID, "ActivateSpeedModifier", InputActivateSpeedModifier ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableSpeedModifier", InputDisableSpeedModifier ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetSpeedModRadius", InputSetSpeedModifierRadius ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetSpeedModSpeed", InputSetSpeedModifierSpeed ), - DEFINE_INPUTFUNC( FIELD_VOID, "HolsterWeapon", InputHolsterWeapon ), - DEFINE_INPUTFUNC( FIELD_VOID, "HolsterAndDestroyWeapon", InputHolsterAndDestroyWeapon ), - DEFINE_INPUTFUNC( FIELD_VOID, "UnholsterWeapon", InputUnholsterWeapon ), - DEFINE_INPUTFUNC( FIELD_STRING, "ForceInteractionWithNPC", InputForceInteractionWithNPC ), - DEFINE_INPUTFUNC( FIELD_STRING, "UpdateEnemyMemory", InputUpdateEnemyMemory ), - - // Function pointers - DEFINE_USEFUNC( NPCUse ), - DEFINE_THINKFUNC( CallNPCThink ), - DEFINE_THINKFUNC( CorpseFallThink ), - DEFINE_THINKFUNC( NPCInitThink ), - -END_DATADESC() - -BEGIN_SIMPLE_DATADESC( AIScheduleState_t ) - DEFINE_FIELD( iCurTask, FIELD_INTEGER ), - DEFINE_FIELD( fTaskStatus, FIELD_INTEGER ), - DEFINE_FIELD( timeStarted, FIELD_TIME ), - DEFINE_FIELD( timeCurTaskStarted, FIELD_TIME ), - DEFINE_FIELD( taskFailureCode, FIELD_INTEGER ), - DEFINE_FIELD( iTaskInterrupt, FIELD_INTEGER ), - DEFINE_FIELD( bTaskRanAutomovement, FIELD_BOOLEAN ), - DEFINE_FIELD( bTaskUpdatedYaw, FIELD_BOOLEAN ), - DEFINE_FIELD( bScheduleWasInterrupted, FIELD_BOOLEAN ), -END_DATADESC() - - -IMPLEMENT_SERVERCLASS_ST( CAI_BaseNPC, DT_AI_BaseNPC ) - SendPropInt( SENDINFO( m_lifeState ), 3, SPROP_UNSIGNED ), - SendPropBool( SENDINFO( m_bPerformAvoidance ) ), - SendPropBool( SENDINFO( m_bIsMoving ) ), - SendPropBool( SENDINFO( m_bFadeCorpse ) ), - SendPropInt( SENDINFO( m_iDeathPose ), ANIMATION_SEQUENCE_BITS ), - SendPropInt( SENDINFO( m_iDeathFrame ), 5 ), - SendPropBool( SENDINFO( m_bSpeedModActive ) ), - SendPropInt( SENDINFO( m_iSpeedModRadius ) ), - SendPropInt( SENDINFO( m_iSpeedModSpeed ) ), - SendPropBool( SENDINFO( m_bImportanRagdoll ) ), - SendPropFloat( SENDINFO( m_flTimePingEffect ) ), -END_SEND_TABLE() - -//------------------------------------- - -BEGIN_SIMPLE_DATADESC( UnreachableEnt_t ) - - DEFINE_FIELD( hUnreachableEnt, FIELD_EHANDLE ), - DEFINE_FIELD( fExpireTime, FIELD_TIME ), - DEFINE_FIELD( vLocationWhenUnreachable, FIELD_POSITION_VECTOR ), - -END_DATADESC() - -//------------------------------------- - -BEGIN_SIMPLE_DATADESC( ScriptedNPCInteraction_Phases_t ) -DEFINE_FIELD( iszSequence, FIELD_STRING ), -DEFINE_FIELD( iActivity, FIELD_INTEGER ), -END_DATADESC() - -//------------------------------------- - -BEGIN_SIMPLE_DATADESC( ScriptedNPCInteraction_t ) - DEFINE_FIELD( iszInteractionName, FIELD_STRING ), - DEFINE_FIELD( iFlags, FIELD_INTEGER ), - DEFINE_FIELD( iTriggerMethod, FIELD_INTEGER ), - DEFINE_FIELD( iLoopBreakTriggerMethod, FIELD_INTEGER ), - DEFINE_FIELD( vecRelativeOrigin, FIELD_VECTOR ), - DEFINE_FIELD( angRelativeAngles, FIELD_VECTOR ), - DEFINE_FIELD( vecRelativeVelocity, FIELD_VECTOR ), - DEFINE_FIELD( flDelay, FIELD_FLOAT ), - DEFINE_FIELD( flDistSqr, FIELD_FLOAT ), - DEFINE_FIELD( iszMyWeapon, FIELD_STRING ), - DEFINE_FIELD( iszTheirWeapon, FIELD_STRING ), - DEFINE_EMBEDDED_ARRAY( sPhases, SNPCINT_NUM_PHASES ), - DEFINE_FIELD( matDesiredLocalToWorld, FIELD_VMATRIX ), - DEFINE_FIELD( bValidOnCurrentEnemy, FIELD_BOOLEAN ), - DEFINE_FIELD( flNextAttemptTime, FIELD_TIME ), -END_DATADESC() - -//------------------------------------- - -void CAI_BaseNPC::PostConstructor( const char *szClassname ) -{ - BaseClass::PostConstructor( szClassname ); - CreateComponents(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::Activate( void ) -{ - BaseClass::Activate(); - - if ( GetModelPtr() ) - { - ParseScriptedNPCInteractions(); - } - - // Get a handle to my enemy filter entity if there is one. - if ( m_iszEnemyFilterName != NULL_STRING ) - { - CBaseEntity *pFilter = gEntList.FindEntityByName( NULL, m_iszEnemyFilterName ); - if ( pFilter != NULL ) - { - m_hEnemyFilter = dynamic_cast(pFilter); - } - } - -#ifdef AI_MONITOR_FOR_OSCILLATION - m_ScheduleHistory.RemoveAll(); -#endif//AI_MONITOR_FOR_OSCILLATION - -} - -void CAI_BaseNPC::Precache( void ) -{ - gm_iszPlayerSquad = AllocPooledString( PLAYER_SQUADNAME ); // cache for fast IsPlayerSquad calls - - if ( m_spawnEquipment != NULL_STRING && strcmp(STRING(m_spawnEquipment), "0") ) - { - UTIL_PrecacheOther( STRING(m_spawnEquipment) ); - } - - // Make sure schedules are loaded for this NPC type - if (!LoadedSchedules()) - { - DevMsg("ERROR: Rejecting spawn of %s as error in NPC's schedules.\n",GetDebugName()); - UTIL_Remove(this); - return; - } - - PrecacheScriptSound( "AI_BaseNPC.SwishSound" ); - PrecacheScriptSound( "AI_BaseNPC.BodyDrop_Heavy" ); - PrecacheScriptSound( "AI_BaseNPC.BodyDrop_Light" ); - PrecacheScriptSound( "AI_BaseNPC.SentenceStop" ); - - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- - -const short AI_EXTENDED_SAVE_HEADER_VERSION = 5; -const short AI_EXTENDED_SAVE_HEADER_RESET_VERSION = 3; - -const short AI_EXTENDED_SAVE_HEADER_FIRST_VERSION_WITH_CONDITIONS = 2; -const short AI_EXTENDED_SAVE_HEADER_FIRST_VERSION_WITH_SCHEDULE_ID_FIXUP = 3; -const short AI_EXTENDED_SAVE_HEADER_FIRST_VERSION_WITH_SEQUENCE = 4; -const short AI_EXTENDED_SAVE_HEADER_FIRST_VERSION_WITH_NAVIGATOR_SAVE = 5; - -struct AIExtendedSaveHeader_t -{ - AIExtendedSaveHeader_t() - : version(AI_EXTENDED_SAVE_HEADER_VERSION), - flags(0), - scheduleCrc(0) - { - szSchedule[0] = 0; - szIdealSchedule[0] = 0; - szFailSchedule[0] = 0; - szSequence[0] = 0; - } - - short version; - unsigned flags; - char szSchedule[128]; - CRC32_t scheduleCrc; - char szIdealSchedule[128]; - char szFailSchedule[128]; - char szSequence[128]; - - DECLARE_SIMPLE_DATADESC(); -}; - -enum AIExtendedSaveHeaderFlags_t -{ - AIESH_HAD_ENEMY = 0x01, - AIESH_HAD_TARGET = 0x02, - AIESH_HAD_NAVGOAL = 0x04, -}; - -//------------------------------------- - -BEGIN_SIMPLE_DATADESC( AIExtendedSaveHeader_t ) - DEFINE_FIELD( version, FIELD_SHORT ), - DEFINE_FIELD( flags, FIELD_INTEGER ), - DEFINE_AUTO_ARRAY( szSchedule, FIELD_CHARACTER ), - DEFINE_FIELD( scheduleCrc, FIELD_INTEGER ), - DEFINE_AUTO_ARRAY( szIdealSchedule, FIELD_CHARACTER ), - DEFINE_AUTO_ARRAY( szFailSchedule, FIELD_CHARACTER ), - DEFINE_AUTO_ARRAY( szSequence, FIELD_CHARACTER ), -END_DATADESC() - -//------------------------------------- - -int CAI_BaseNPC::Save( ISave &save ) -{ - AIExtendedSaveHeader_t saveHeader; - - if ( GetEnemy() ) - saveHeader.flags |= AIESH_HAD_ENEMY; - if ( GetTarget() ) - saveHeader.flags |= AIESH_HAD_TARGET; - if ( GetNavigator()->IsGoalActive() ) - saveHeader.flags |= AIESH_HAD_NAVGOAL; - - if ( m_pSchedule ) - { - const char *pszSchedule = m_pSchedule->GetName(); - - Assert( Q_strlen( pszSchedule ) < (int)sizeof( saveHeader.szSchedule ) - 1 ); - Q_strncpy( saveHeader.szSchedule, pszSchedule, sizeof( saveHeader.szSchedule ) ); - - CRC32_Init( &saveHeader.scheduleCrc ); - CRC32_ProcessBuffer( &saveHeader.scheduleCrc, (void *)m_pSchedule->GetTaskList(), m_pSchedule->NumTasks() * sizeof(Task_t) ); - CRC32_Final( &saveHeader.scheduleCrc ); - } - else - { - saveHeader.szSchedule[0] = 0; - saveHeader.scheduleCrc = 0; - } - - int idealSchedule = GetGlobalScheduleId( m_IdealSchedule ); - - if ( idealSchedule != -1 && idealSchedule != AI_RemapToGlobal( SCHED_NONE ) && idealSchedule != AI_RemapToGlobal( SCHED_AISCRIPT ) ) - { - CAI_Schedule *pIdealSchedule = GetSchedule( m_IdealSchedule ); - if ( pIdealSchedule ) - { - const char *pszIdealSchedule = pIdealSchedule->GetName(); - Assert( Q_strlen( pszIdealSchedule ) < (int)sizeof( saveHeader.szIdealSchedule ) - 1 ); - Q_strncpy( saveHeader.szIdealSchedule, pszIdealSchedule, sizeof( saveHeader.szIdealSchedule ) ); - } - } - - int failSchedule = GetGlobalScheduleId( m_failSchedule ); - if ( failSchedule != -1 && failSchedule != AI_RemapToGlobal( SCHED_NONE ) && failSchedule != AI_RemapToGlobal( SCHED_AISCRIPT ) ) - { - CAI_Schedule *pFailSchedule = GetSchedule( m_failSchedule ); - if ( pFailSchedule ) - { - const char *pszFailSchedule = pFailSchedule->GetName(); - Assert( Q_strlen( pszFailSchedule ) < (int)sizeof( saveHeader.szFailSchedule ) - 1 ); - Q_strncpy( saveHeader.szFailSchedule, pszFailSchedule, sizeof( saveHeader.szFailSchedule ) ); - } - } - - if ( GetSequence() != ACT_INVALID && GetModelPtr() ) - { - const char *pszSequenceName = GetSequenceName( GetSequence() ); - if ( pszSequenceName && *pszSequenceName ) - { - Assert( Q_strlen( pszSequenceName ) < (int)sizeof( saveHeader.szSequence ) - 1 ); - Q_strncpy( saveHeader.szSequence, pszSequenceName, sizeof(saveHeader.szSequence) ); - } - } - - save.WriteAll( &saveHeader ); - - save.StartBlock(); - SaveConditions( save, m_Conditions ); - SaveConditions( save, m_CustomInterruptConditions ); - SaveConditions( save, m_ConditionsPreIgnore ); - CAI_ScheduleBits ignoreConditions; - m_InverseIgnoreConditions.Not( &ignoreConditions ); - SaveConditions( save, ignoreConditions ); - save.EndBlock(); - - save.StartBlock(); - GetNavigator()->Save( save ); - save.EndBlock(); - - return BaseClass::Save(save); -} - -//------------------------------------- - -void CAI_BaseNPC::DiscardScheduleState() -{ - // We don't save/restore routes yet - GetNavigator()->ClearGoal(); - - // We don't save/restore schedules yet - ClearSchedule( "Restoring NPC" ); - - // Reset animation - m_Activity = ACT_RESET; - - // If we don't have an enemy, clear conditions like see enemy, etc. - if ( GetEnemy() == NULL ) - { - m_Conditions.ClearAll(); - } - - // went across a transition and lost my m_hCine - bool bLostScript = ( m_NPCState == NPC_STATE_SCRIPT && m_hCine == NULL ); - if ( bLostScript ) - { - // UNDONE: Do something better here? - // for now, just go back to idle and let the AI figure out what to do. - SetState( NPC_STATE_IDLE ); - SetIdealState( NPC_STATE_IDLE ); - DevMsg(1, "Scripted Sequence stripped on level transition for %s\n", GetDebugName() ); - } -} - -//------------------------------------- - -void CAI_BaseNPC::OnRestore() -{ - gm_iszPlayerSquad = AllocPooledString( PLAYER_SQUADNAME ); // cache for fast IsPlayerSquad calls - - if ( m_bDoPostRestoreRefindPath && CAI_NetworkManager::NetworksLoaded() ) - { - CAI_DynamicLink::InitDynamicLinks(); - if ( !GetNavigator()->RefindPathToGoal( false ) ) - DiscardScheduleState(); - } - else - { - GetNavigator()->ClearGoal(); - } - BaseClass::OnRestore(); - m_bCheckContacts = true; -} - - -//------------------------------------- - -int CAI_BaseNPC::Restore( IRestore &restore ) -{ - AIExtendedSaveHeader_t saveHeader; - restore.ReadAll( &saveHeader ); - - if ( saveHeader.version >= AI_EXTENDED_SAVE_HEADER_FIRST_VERSION_WITH_CONDITIONS ) - { - restore.StartBlock(); - RestoreConditions( restore, &m_Conditions ); - RestoreConditions( restore, &m_CustomInterruptConditions ); - RestoreConditions( restore, &m_ConditionsPreIgnore ); - CAI_ScheduleBits ignoreConditions; - RestoreConditions( restore, &ignoreConditions ); - ignoreConditions.Not( &m_InverseIgnoreConditions ); - restore.EndBlock(); - } - - if ( saveHeader.version >= AI_EXTENDED_SAVE_HEADER_FIRST_VERSION_WITH_NAVIGATOR_SAVE ) - { - restore.StartBlock(); - GetNavigator()->Restore( restore ); - restore.EndBlock(); - } - - // do a normal restore - int status = BaseClass::Restore(restore); - if ( !status ) - return 0; - - // Do schedule fix-up - if ( saveHeader.version >= AI_EXTENDED_SAVE_HEADER_FIRST_VERSION_WITH_SCHEDULE_ID_FIXUP ) - { - if ( saveHeader.szIdealSchedule[0] ) - { - CAI_Schedule *pIdealSchedule = g_AI_SchedulesManager.GetScheduleByName( saveHeader.szIdealSchedule ); - m_IdealSchedule = ( pIdealSchedule ) ? pIdealSchedule->GetId() : SCHED_NONE; - } - - if ( saveHeader.szFailSchedule[0] ) - { - CAI_Schedule *pFailSchedule = g_AI_SchedulesManager.GetScheduleByName( saveHeader.szFailSchedule ); - m_failSchedule = ( pFailSchedule ) ? pFailSchedule->GetId() : SCHED_NONE; - } - } - - bool bLostSequence = false; - if ( saveHeader.version >= AI_EXTENDED_SAVE_HEADER_FIRST_VERSION_WITH_SEQUENCE && saveHeader.szSequence[0] && GetModelPtr() ) - { - SetSequence( LookupSequence( saveHeader.szSequence ) ); - if ( GetSequence() == ACT_INVALID ) - { - DevMsg( this, AIMF_IGNORE_SELECTED, "Discarding missing sequence %s on load.\n", saveHeader.szSequence ); - SetSequence( 0 ); - bLostSequence = true; - } - - Assert( IsValidSequence( GetSequence() ) ); - } - - bool bLostScript = ( m_NPCState == NPC_STATE_SCRIPT && m_hCine == NULL ); - bool bDiscardScheduleState = ( bLostScript || - bLostSequence || - saveHeader.szSchedule[0] == 0 || - saveHeader.version < AI_EXTENDED_SAVE_HEADER_RESET_VERSION || - ( (saveHeader.flags & AIESH_HAD_ENEMY) && !GetEnemy() ) || - ( (saveHeader.flags & AIESH_HAD_TARGET) && !GetTarget() ) ); - - if ( m_ScheduleState.taskFailureCode >= NUM_FAIL_CODES ) - m_ScheduleState.taskFailureCode = FAIL_NO_TARGET; // must have been a string, gotta punt - - if ( !bDiscardScheduleState ) - { - m_pSchedule = g_AI_SchedulesManager.GetScheduleByName( saveHeader.szSchedule ); - if ( m_pSchedule ) - { - CRC32_t scheduleCrc; - CRC32_Init( &scheduleCrc ); - CRC32_ProcessBuffer( &scheduleCrc, (void *)m_pSchedule->GetTaskList(), m_pSchedule->NumTasks() * sizeof(Task_t) ); - CRC32_Final( &scheduleCrc ); - - if ( scheduleCrc != saveHeader.scheduleCrc ) - { - m_pSchedule = NULL; - } - } - } - - if ( !m_pSchedule ) - bDiscardScheduleState = true; - - if ( !bDiscardScheduleState ) - m_bDoPostRestoreRefindPath = ( ( saveHeader.flags & AIESH_HAD_NAVGOAL) != 0 ); - else - { - m_bDoPostRestoreRefindPath = false; - DiscardScheduleState(); - } - - return status; -} - -//------------------------------------- - -void CAI_BaseNPC::SaveConditions( ISave &save, const CAI_ScheduleBits &conditions ) -{ - for (int i = 0; i < MAX_CONDITIONS; i++) - { - if (conditions.IsBitSet(i)) - { - const char *pszConditionName = ConditionName(AI_RemapToGlobal(i)); - if ( !pszConditionName ) - break; - save.WriteString( pszConditionName ); - } - } - save.WriteString( "" ); -} - -//------------------------------------- - -void CAI_BaseNPC::RestoreConditions( IRestore &restore, CAI_ScheduleBits *pConditions ) -{ - pConditions->ClearAll(); - char szCondition[256]; - for (;;) - { - restore.ReadString( szCondition, sizeof(szCondition), 0 ); - if ( !szCondition[0] ) - break; - int iCondition = GetSchedulingSymbols()->ConditionSymbolToId( szCondition ); - if ( iCondition != -1 ) - pConditions->Set( AI_RemapFromGlobal( iCondition ) ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::KeyValue( const char *szKeyName, const char *szValue ) -{ - bool bResult = BaseClass::KeyValue( szKeyName, szValue ); - - if( !bResult ) - { - // Defer unhandled Keys to behaviors - CAI_BehaviorBase **ppBehaviors = AccessBehaviors(); - - for ( int i = 0; i < NumBehaviors(); i++ ) - { - if( ppBehaviors[ i ]->KeyValue( szKeyName, szValue ) ) - { - return true; - } - } - } - - return bResult; -} - -//----------------------------------------------------------------------------- -// Purpose: Debug function to make this NPC freeze in place (or unfreeze). -//----------------------------------------------------------------------------- -void CAI_BaseNPC::ToggleFreeze(void) -{ - if (!IsCurSchedule(SCHED_NPC_FREEZE)) - { - // Freeze them. - SetCondition(COND_NPC_FREEZE); - SetMoveType(MOVETYPE_NONE); - SetGravity(0); - SetLocalAngularVelocity(vec3_angle); - SetAbsVelocity( vec3_origin ); - } - else - { - // Unfreeze them. - SetCondition(COND_NPC_UNFREEZE); - m_Activity = ACT_RESET; - - // BUGBUG: this might not be the correct movetype! - SetMoveType( MOVETYPE_STEP ); - - // Doesn't restore gravity to the original value, but who cares? - SetGravity(1); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Written by subclasses macro to load schedules -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::LoadSchedules(void) -{ - return true; -} - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::LoadedSchedules(void) -{ - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Constructor -// Input : -// Output : -//----------------------------------------------------------------------------- -CAI_BaseNPC::CAI_BaseNPC(void) - : m_UnreachableEnts( 0, 4 ), - m_bDeferredNavigation( false ) -{ - m_pMotor = NULL; - m_pMoveProbe = NULL; - m_pNavigator = NULL; - m_pSenses = NULL; - m_pPathfinder = NULL; - m_pLocalNavigator = NULL; - - m_pSchedule = NULL; - m_IdealSchedule = SCHED_NONE; - -#ifdef _DEBUG - // necessary since in debug, we initialize vectors to NAN for debugging - m_vecLastPosition.Init(); - m_vSavePosition.Init(); - m_vEyeLookTarget.Init(); - m_vCurEyeTarget.Init(); - m_vDefaultEyeOffset.Init(); - -#endif - m_bDidDeathCleanup = false; - - m_afCapability = 0; // Make sure this is cleared in the base class - - SetHullType(HULL_HUMAN); // Give human hull by default, subclasses should override - - m_iMySquadSlot = SQUAD_SLOT_NONE; - m_flSumDamage = 0; - m_flLastDamageTime = 0; - m_flLastAttackTime = 0; - m_flSoundWaitTime = 0; - m_flNextEyeLookTime = 0; - m_flHeadYaw = 0; - m_flHeadPitch = 0; - m_spawnEquipment = NULL_STRING; - m_pEnemies = new CAI_Enemies; - m_bIgnoreUnseenEnemies = false; - m_flEyeIntegRate = 0.95; - SetTarget( NULL ); - - m_pSquad = NULL; - - m_flMoveWaitFinished = 0; - - m_fIsUsingSmallHull = true; - - m_bHintGroupNavLimiting = false; - - m_fNoDamageDecal = false; - - SetInAScript( false ); - - m_pLockedBestSound = new CSound; - m_pLockedBestSound->m_iType = SOUND_NONE; - - // ---------------------------- - // Debugging fields - // ---------------------------- - m_interruptText = NULL; - m_failText = NULL; - m_failedSchedule = NULL; - m_interuptSchedule = NULL; - m_nDebugPauseIndex = 0; - - g_AI_Manager.AddAI( this ); - - if ( g_AI_Manager.NumAIs() == 1 ) - { - m_AnyUpdateEnemyPosTimer.Force(); - gm_flTimeLastSpawn = -1; - gm_nSpawnedThisFrame = 0; - gm_iNextThinkRebalanceTick = 0; - } - - m_iFrameBlocked = -1; - m_bInChoreo = true; // assume so until call to UpdateEfficiency() - - SetCollisionGroup( COLLISION_GROUP_NPC ); -} - -//----------------------------------------------------------------------------- -// Purpose: Destructor -// Input : -// Output : -//----------------------------------------------------------------------------- -CAI_BaseNPC::~CAI_BaseNPC(void) -{ - g_AI_Manager.RemoveAI( this ); - - delete m_pLockedBestSound; - - RemoveMemory(); - - delete m_pPathfinder; - delete m_pNavigator; - delete m_pMotor; - delete m_pLocalNavigator; - delete m_pMoveProbe; - delete m_pSenses; - delete m_pTacticalServices; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::UpdateOnRemove(void) -{ - if ( !m_bDidDeathCleanup ) - { - if ( m_NPCState == NPC_STATE_DEAD ) - DevMsg( "May not have cleaned up on NPC death\n"); - - CleanupOnDeath( NULL, false ); - } - - // Chain at end to mimic destructor unwind order - BaseClass::UpdateOnRemove(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CAI_BaseNPC::UpdateTransmitState() -{ - if( gpGlobals->curtime < m_flTimePingEffect ) - { - return SetTransmitState( FL_EDICT_ALWAYS ); - } - - return BaseClass::UpdateTransmitState(); -} - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::CreateComponents() -{ - m_pSenses = CreateSenses(); - if ( !m_pSenses ) - return false; - - m_pMotor = CreateMotor(); - if ( !m_pMotor ) - return false; - - m_pLocalNavigator = CreateLocalNavigator(); - if ( !m_pLocalNavigator ) - return false; - - m_pMoveProbe = CreateMoveProbe(); - if ( !m_pMoveProbe ) - return false; - - m_pNavigator = CreateNavigator(); - if ( !m_pNavigator ) - return false; - - m_pPathfinder = CreatePathfinder(); - if ( !m_pPathfinder ) - return false; - - m_pTacticalServices = CreateTacticalServices(); - if ( !m_pTacticalServices ) - return false; - - m_MoveAndShootOverlay.SetOuter( this ); - - m_pMotor->Init( m_pLocalNavigator ); - m_pLocalNavigator->Init( m_pNavigator ); - m_pNavigator->Init( g_pBigAINet ); - m_pPathfinder->Init( g_pBigAINet ); - m_pTacticalServices->Init( g_pBigAINet ); - - return true; -} - -//----------------------------------------------------------------------------- - -CAI_Senses *CAI_BaseNPC::CreateSenses() -{ - CAI_Senses *pSenses = new CAI_Senses; - pSenses->SetOuter( this ); - return pSenses; -} - -//----------------------------------------------------------------------------- - -CAI_Motor *CAI_BaseNPC::CreateMotor() -{ - return new CAI_Motor( this ); -} - -//----------------------------------------------------------------------------- - -CAI_MoveProbe *CAI_BaseNPC::CreateMoveProbe() -{ - return new CAI_MoveProbe( this ); -} - -//----------------------------------------------------------------------------- - -CAI_LocalNavigator *CAI_BaseNPC::CreateLocalNavigator() -{ - return new CAI_LocalNavigator( this ); -} - -//----------------------------------------------------------------------------- - -CAI_TacticalServices *CAI_BaseNPC::CreateTacticalServices() -{ - return new CAI_TacticalServices( this ); -} - -//----------------------------------------------------------------------------- - -CAI_Navigator *CAI_BaseNPC::CreateNavigator() -{ - return new CAI_Navigator( this ); -} - -//----------------------------------------------------------------------------- - -CAI_Pathfinder *CAI_BaseNPC::CreatePathfinder() -{ - return new CAI_Pathfinder( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::InputSetRelationship( inputdata_t &inputdata ) -{ - AddRelationship( inputdata.value.String(), inputdata.pActivator ); -} - - -//----------------------------------------------------------------------------- -// Won't affect the current enemy, only future enemy acquisitions. -//----------------------------------------------------------------------------- -void CAI_BaseNPC::InputSetEnemyFilter( inputdata_t &inputdata ) -{ - // Get a handle to my enemy filter entity if there is one. - CBaseEntity *pFilter = gEntList.FindEntityByName( NULL, inputdata.value.StringID() ); - m_hEnemyFilter = dynamic_cast(pFilter); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::InputSetHealth( inputdata_t &inputdata ) -{ - int iNewHealth = inputdata.value.Int(); - int iDelta = abs(GetHealth() - iNewHealth); - if ( iNewHealth > GetHealth() ) - { - TakeHealth( iDelta, DMG_GENERIC ); - } - else if ( iNewHealth < GetHealth() ) - { - TakeDamage( CTakeDamageInfo( this, this, iDelta, DMG_GENERIC ) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::InputBeginRappel( inputdata_t &inputdata ) -{ - BeginRappel(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::InputSetSquad( inputdata_t &inputdata ) -{ - if ( !( CapabilitiesGet() & bits_CAP_SQUAD ) ) - { - Warning("SetSquad Input received for NPC %s, but that NPC can't use squads.\n", GetDebugName() ); - return; - } - - m_SquadName = inputdata.value.StringID(); - - // Removing from squad? - if ( m_SquadName == NULL_STRING ) - { - if ( m_pSquad ) - { - m_pSquad->RemoveFromSquad(this, true); - m_pSquad = NULL; - } - } - else - { - m_pSquad = g_AI_SquadManager.FindCreateSquad(this, m_SquadName); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::InputWake( inputdata_t &inputdata ) -{ - Wake(); - - // Check if we have a path to follow. This is normally done in StartNPC, - // but putting the NPC to sleep will cancel it, so we have to do it again. - if ( m_target != NULL_STRING )// this npc has a target - { - // Find the npc's initial target entity, stash it - SetGoalEnt( gEntList.FindEntityByName( NULL, m_target ) ); - - if ( !GetGoalEnt() ) - { - Warning( "ReadyNPC()--%s couldn't find target %s\n", GetClassname(), STRING(m_target)); - } - else - { - StartTargetHandling( GetGoalEnt() ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::InputForgetEntity( inputdata_t &inputdata ) -{ - const char *pszEntityToForget = inputdata.value.String(); - - if ( g_pDeveloper->GetInt() && pszEntityToForget[strlen( pszEntityToForget ) - 1] == '*' ) - DevMsg( "InputForgetEntity does not support wildcards\n" ); - - CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, pszEntityToForget ); - if ( pEntity ) - { - if ( GetEnemy() == pEntity ) - { - SetEnemy( NULL ); - SetIdealState( NPC_STATE_ALERT ); - } - GetEnemies()->ClearMemory( pEntity ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_BaseNPC::InputIgnoreDangerSounds( inputdata_t &inputdata ) -{ - // Default is 10 seconds. - float flDelay = 10.0f; - - if( inputdata.value.Float() > 0.0f ) - { - flDelay = inputdata.value.Float(); - } - - m_flIgnoreDangerSoundsUntil = gpGlobals->curtime + flDelay; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_BaseNPC::InputUpdateEnemyMemory( inputdata_t &inputdata ) -{ - const char *pszEnemy = inputdata.value.String(); - CBaseEntity *pEnemy = gEntList.FindEntityByName( NULL, pszEnemy ); - - if( pEnemy ) - { - UpdateEnemyMemory( pEnemy, pEnemy->GetAbsOrigin(), this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAI_BaseNPC::InputOutsideTransition( inputdata_t &inputdata ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: Called when this NPC transitions to another level with the player -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAI_BaseNPC::InputInsideTransition( inputdata_t &inputdata ) -{ - CleanupScriptsOnTeleport( true ); - - // If we're inside a vcd, tell it to stop - if ( IsCurSchedule( SCHED_SCENE_GENERIC, false ) ) - { - RemoveActorFromScriptedScenes( this, false ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::CleanupScriptsOnTeleport( bool bEnrouteAsWell ) -{ - // If I'm running a scripted sequence, I need to clean up - if ( m_NPCState == NPC_STATE_SCRIPT && m_hCine ) - { - if ( !bEnrouteAsWell ) - { - // - // Don't cancel scripts when they're teleporting an NPC - // to the script for the purposes of movement. - // - if ( ( m_scriptState == CAI_BaseNPC::SCRIPT_WALK_TO_MARK ) || - ( m_scriptState == CAI_BaseNPC::SCRIPT_RUN_TO_MARK ) || - ( m_scriptState == CAI_BaseNPC::SCRIPT_CUSTOM_MOVE_TO_MARK ) || - m_hCine->IsTeleportingDueToMoveTo() ) - { - return; - } - } - - m_hCine->ScriptEntityCancel( m_hCine, true ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt) -{ -#ifdef HL2_DLL - if ( interactionType == g_interactionBarnacleVictimGrab ) - { - // Make the victim stop thinking so they're as good as dead without - // shocking the system by destroying the entity. - StopLoopingSounds(); - BarnacleDeathSound(); - SetThink( NULL ); - - // Gag the NPC so they won't talk anymore - AddSpawnFlags( SF_NPC_GAG ); - - // Drop any weapon they're holding - if ( GetActiveWeapon() ) - { - Weapon_Drop( GetActiveWeapon() ); - } - - return true; - } -#endif // HL2_DLL - - return BaseClass::HandleInteraction( interactionType, data, sourceEnt ); -} - -CAI_BaseNPC *CAI_BaseNPC::GetInteractionPartner( void ) -{ - if ( m_hInteractionPartner == NULL ) - return NULL; - - return m_hInteractionPartner->MyNPCPointer(); -} - -//----------------------------------------------------------------------------- -// Purpose: Called when exiting a scripted sequence. -// Output : Returns true if alive, false if dead. -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::ExitScriptedSequence( ) -{ - if ( m_lifeState == LIFE_DYING ) - { - // is this legal? - // BUGBUG -- This doesn't call Killed() - SetIdealState( NPC_STATE_DEAD ); - return false; - } - - if (m_hCine) - { - m_hCine->CancelScript( ); - } - - return true; -} - - -ConVar sv_test_scripted_sequences( "sv_test_scripted_sequences", "0", FCVAR_NONE, "Tests for scripted sequences that are embedded in the world. Run through your map with this set to check for NPCs falling through the world." ); - -bool CAI_BaseNPC::CineCleanup() -{ - CAI_ScriptedSequence *pOldCine = m_hCine; - int nSavedFlags = ( m_hCine ? m_hCine->m_savedFlags : GetFlags() ); - - bool bDestroyCine = false; - if ( IsRunningDynamicInteraction() ) - { - bDestroyCine = true; - - // Re-enable physics collisions between me & the other NPC - if ( m_hInteractionPartner ) - { - PhysEnableEntityCollisions( this, m_hInteractionPartner ); - //Msg("%s(%s) enabled collisions with %s(%s) at %0.2f\n", GetClassname(), GetDebugName(), m_hInteractionPartner->GetClassName(), m_hInteractionPartner->GetDebugName(), gpGlobals->curtime ); - } - - if ( m_hForcedInteractionPartner ) - { - // We've finished a forced interaction. Let the mapmaker know. - m_OnForcedInteractionFinished.FireOutput( this, this ); - } - - // Clear interaction partner, because we're not running a scripted sequence anymore - m_hInteractionPartner = NULL; - CleanupForcedInteraction(); - } - - // am I linked to a cinematic? - if (m_hCine) - { - // okay, reset me to what it thought I was before - m_hCine->SetTarget( NULL ); - // NOTE that this will have had EF_NODRAW removed in script.dll when it's cached off - SetEffects( m_hCine->m_saved_effects ); - - SetCollisionGroup( m_hCine->m_savedCollisionGroup ); - } - else - { - // arg, punt - AddSolidFlags( FSOLID_NOT_STANDABLE ); - } - - m_hCine = NULL; - SetTarget( NULL ); - SetGoalEnt( NULL ); - if (m_lifeState == LIFE_DYING) - { - // last frame of death animation? - if ( m_iHealth > 0 ) - { - m_iHealth = 0; - } - - AddSolidFlags( FSOLID_NOT_SOLID ); - SetState( NPC_STATE_DEAD ); - m_lifeState = LIFE_DEAD; - UTIL_SetSize( this, WorldAlignMins(), Vector(WorldAlignMaxs().x, WorldAlignMaxs().y, WorldAlignMins().z + 2) ); - - if ( pOldCine && pOldCine->HasSpawnFlags( SF_SCRIPT_LEAVECORPSE ) ) - { - SetUse( NULL ); // BUGBUG -- This doesn't call Killed() - SetThink( NULL ); // This will probably break some stuff - SetTouch( NULL ); - } - else - SUB_StartFadeOut(); // SetThink( SUB_DoNothing ); - - - //Not becoming a ragdoll, so set the NOINTERP flag on. - if ( CanBecomeRagdoll() == false ) - { - StopAnimation(); - AddEffects( EF_NOINTERP ); // Don't interpolate either, assume the corpse is positioned in its final resting place - } - - SetMoveType( MOVETYPE_NONE ); - return false; - } - - // If we actually played a sequence - if ( pOldCine && pOldCine->m_iszPlay != NULL_STRING && pOldCine->PlayedSequence() ) - { - if ( !pOldCine->HasSpawnFlags(SF_SCRIPT_DONT_TELEPORT_AT_END) ) - { - // reset position - Vector new_origin; - QAngle new_angle; - GetBonePosition( 0, new_origin, new_angle ); - - // Figure out how far they have moved - // We can't really solve this problem because we can't query the movement of the origin relative - // to the sequence. We can get the root bone's position as we do here, but there are - // cases where the root bone is in a different relative position to the entity's origin - // before/after the sequence plays. So we are stuck doing this: - - // !!!HACKHACK: Float the origin up and drop to floor because some sequences have - // irregular motion that can't be properly accounted for. - - // UNDONE: THIS SHOULD ONLY HAPPEN IF WE ACTUALLY PLAYED THE SEQUENCE. - Vector oldOrigin = GetLocalOrigin(); - - // UNDONE: ugly hack. Don't move NPC if they don't "seem" to move - // this really needs to be done with the AX,AY,etc. flags, but that aren't consistantly - // being set, so animations that really do move won't be caught. - if ((oldOrigin - new_origin).Length2D() < 8.0) - new_origin = oldOrigin; - - Vector origin = GetLocalOrigin(); - - origin.x = new_origin.x; - origin.y = new_origin.y; - origin.z += 1; - - if ( nSavedFlags & FL_FLY ) - { - origin.z = new_origin.z; - SetLocalOrigin( origin ); - } - else - { - SetLocalOrigin( origin ); - - int drop = UTIL_DropToFloor( this, MASK_NPCSOLID, UTIL_GetLocalPlayer() ); - - // Origin in solid? Set to org at the end of the sequence - if ( ( drop < 0 ) || sv_test_scripted_sequences.GetBool() ) - { - SetLocalOrigin( oldOrigin ); - } - else if ( drop == 0 ) // Hanging in air? - { - Vector origin = GetLocalOrigin(); - origin.z = new_origin.z; - SetLocalOrigin( origin ); - SetGroundEntity( NULL ); - } - } - - origin = GetLocalOrigin(); - - // teleport if it's a non-trivial distance - if ((oldOrigin - origin).Length() > 8.0) - { - // Call teleport to notify - Teleport( &origin, NULL, NULL ); - SetLocalOrigin( origin ); - AddEffects( EF_NOINTERP ); - } - - if ( m_iHealth <= 0 ) - { - // Dropping out because he got killed - SetIdealState( NPC_STATE_DEAD ); - SetCondition( COND_LIGHT_DAMAGE ); - m_lifeState = LIFE_DYING; - } - } - - // We should have some animation to put these guys in, but for now it's idle. - // Due to NOINTERP above, there won't be any blending between this anim & the sequence - m_Activity = ACT_RESET; - } - - // set them back into a normal state - if ( m_iHealth > 0 ) - { - SetIdealState( NPC_STATE_IDLE ); - } - else - { - // Dropping out because he got killed - SetIdealState( NPC_STATE_DEAD ); - SetCondition( COND_LIGHT_DAMAGE ); - } - - // SetAnimation( m_NPCState ); - CLEARBITS(m_spawnflags, SF_NPC_WAIT_FOR_SCRIPT ); - - if ( bDestroyCine ) - { - UTIL_Remove( pOldCine ); - } - - return true; -} - -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ) -{ - CleanupScriptsOnTeleport( false ); - - BaseClass::Teleport( newPosition, newAngles, newVelocity ); -} - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::FindSpotForNPCInRadius( Vector *pResult, const Vector &vStartPos, CAI_BaseNPC *pNPC, float radius, bool bOutOfPlayerViewcone ) -{ - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - QAngle fan; - - fan.x = 0; - fan.z = 0; - - for( fan.y = 0 ; fan.y < 360 ; fan.y += 18.0 ) - { - Vector vecTest; - Vector vecDir; - - AngleVectors( fan, &vecDir ); - - vecTest = vStartPos + vecDir * radius; - - if ( bOutOfPlayerViewcone && pPlayer && !pPlayer->FInViewCone( vecTest ) ) - continue; - - trace_t tr; - - UTIL_TraceLine( vecTest, vecTest - Vector( 0, 0, 8192 ), MASK_SHOT, pNPC, COLLISION_GROUP_NONE, &tr ); - if( tr.fraction == 1.0 ) - { - continue; - } - - UTIL_TraceHull( tr.endpos, - tr.endpos + Vector( 0, 0, 10 ), - pNPC->GetHullMins(), - pNPC->GetHullMaxs(), - MASK_NPCSOLID, - pNPC, - COLLISION_GROUP_NONE, - &tr ); - - if( tr.fraction == 1.0 && pNPC->GetMoveProbe()->CheckStandPosition( tr.endpos, MASK_NPCSOLID ) ) - { - *pResult = tr.endpos; - return true; - } - } - return false; -} - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::IsNavigationUrgent() -{ - // return true if the navigation is for something that can't react well to failure - if ( IsCurSchedule( SCHED_SCRIPTED_WALK, false ) || - IsCurSchedule( SCHED_SCRIPTED_RUN, false ) || - IsCurSchedule( SCHED_SCRIPTED_CUSTOM_MOVE, false ) || - ( IsCurSchedule( SCHED_SCENE_GENERIC, false ) && IsInLockedScene() ) ) - { - return true; - } - return false; -} - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::ShouldFailNav( bool bMovementFailed ) -{ -#ifdef HL2_EPISODIC - - if ( ai_vehicle_avoidance.GetBool() ) - { - // Never be blocked this way by a vehicle (creates too many headaches around the levels) - CBaseEntity *pEntity = GetNavigator()->GetBlockingEntity(); - if ( pEntity && pEntity->GetServerVehicle() ) - { - // Vital allies never get stuck, and urgent moves cannot be blocked by a vehicle - if ( Classify() == CLASS_PLAYER_ALLY_VITAL || IsNavigationUrgent() ) - return false; - } - } - -#endif // HL2_EPISODIC - - // It's up to the schedule that requested movement to deal with failed movement. Currently, only a handfull of - // schedules are considered Urgent, and they need to deal with what to do when there's no route, which by inspection - // they'd don't. - - if ( IsNavigationUrgent()) - { - return false; - } - - return true; -} - -Navigation_t CAI_BaseNPC::GetNavType() const -{ - return m_pNavigator->GetNavType(); -} - -void CAI_BaseNPC::SetNavType( Navigation_t navType ) -{ - m_pNavigator->SetNavType( navType ); -} - -//----------------------------------------------------------------------------- -// NPCs can override this to tweak with how costly particular movements are -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::MovementCost( int moveType, const Vector &vecStart, const Vector &vecEnd, float *pCost ) -{ - // We have nothing to say on the matter, but derived classes might - return false; -} - -bool CAI_BaseNPC::OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval ) -{ - return false; -} - -bool CAI_BaseNPC::OverrideMove( float flInterval ) -{ - return false; -} - - -//========================================================= -// VecToYaw - turns a directional vector into a yaw value -// that points down that vector. -//========================================================= -float CAI_BaseNPC::VecToYaw( const Vector &vecDir ) -{ - if (vecDir.x == 0 && vecDir.y == 0 && vecDir.z == 0) - return GetLocalAngles().y; - - return UTIL_VecToYaw( vecDir ); -} - -//----------------------------------------------------------------------------- -// Inherited from IAI_MotorMovementServices -//----------------------------------------------------------------------------- -float CAI_BaseNPC::CalcYawSpeed( void ) -{ - // Negative values are invalud - return -1.0f; -} - -bool CAI_BaseNPC::OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, - float distClear, - AIMoveResult_t *pResult ) -{ - if ( pMoveGoal->directTrace.pObstruction ) - { - CBasePropDoor *pPropDoor = dynamic_cast( pMoveGoal->directTrace.pObstruction ); - if ( pPropDoor && OnUpcomingPropDoor( pMoveGoal, pPropDoor, distClear, pResult ) ) - { - return true; - } - } - - return false; -} - - -bool CAI_BaseNPC::OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal, - float distClear, - AIMoveResult_t *pResult ) -{ - if ( pMoveGoal->directTrace.pObstruction ) - { - CBaseDoor *pDoor = dynamic_cast( pMoveGoal->directTrace.pObstruction ); - if ( pDoor && OnObstructingDoor( pMoveGoal, pDoor, distClear, pResult ) ) - { - return true; - } - } - - return false; -} - - -bool CAI_BaseNPC::OnObstructingDoor( AILocalMoveGoal_t *pMoveGoal, - CBaseDoor *pDoor, - float distClear, - AIMoveResult_t *pResult ) -{ - if ( pMoveGoal->maxDist < distClear ) - return false; - - // By default, NPCs don't know how to open doors - if ( pDoor->m_toggle_state == TS_AT_BOTTOM || pDoor->m_toggle_state == TS_GOING_DOWN ) - { - if ( distClear < 0.1 ) - { - *pResult = AIMR_BLOCKED_ENTITY; - } - else - { - pMoveGoal->maxDist = distClear; - *pResult = AIMR_OK; - } - - return true; - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pMoveGoal - -// pDoor - -// distClear - -// default - -// spawn - -// oldorg - -// pfPosition - -// neworg - -// Output : Returns true if movement is solved, false otherwise. -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::OnUpcomingPropDoor( AILocalMoveGoal_t *pMoveGoal, - CBasePropDoor *pDoor, - float distClear, - AIMoveResult_t *pResult ) -{ - if ( (pMoveGoal->flags & AILMG_TARGET_IS_GOAL) && pMoveGoal->maxDist < distClear ) - return false; - - if ( pMoveGoal->maxDist + GetHullWidth() * .25 < distClear ) - return false; - - if (pDoor == m_hOpeningDoor) - { - if ( pDoor->IsNPCOpening( this ) ) - { - // We're in the process of opening the door, don't be blocked by it. - pMoveGoal->maxDist = distClear; - *pResult = AIMR_OK; - return true; - } - m_hOpeningDoor = NULL; - } - - if ((CapabilitiesGet() & bits_CAP_DOORS_GROUP) && !pDoor->IsDoorLocked() && (pDoor->IsDoorClosed() || pDoor->IsDoorClosing())) - { - AI_Waypoint_t *pOpenDoorRoute = NULL; - - opendata_t opendata; - pDoor->GetNPCOpenData(this, opendata); - - // dvs: FIXME: local route might not be sufficient - pOpenDoorRoute = GetPathfinder()->BuildLocalRoute( - GetLocalOrigin(), - opendata.vecStandPos, - NULL, - bits_WP_TO_DOOR | bits_WP_DONT_SIMPLIFY, - NO_NODE, - bits_BUILD_GROUND | bits_BUILD_IGNORE_NPCS, - 0.0); - - if ( pOpenDoorRoute ) - { - if ( AIIsDebuggingDoors(this) ) - { - NDebugOverlay::Cross3D(opendata.vecStandPos + Vector(0,0,1), 32, 255, 255, 255, false, 1.0 ); - Msg( "Opening door!\n" ); - } - - // Attach the door to the waypoint so we open it when we get there. - // dvs: FIXME: this is kind of bullshit, I need to find the exact waypoint to open the door - // should I just walk the path until I find it? - pOpenDoorRoute->m_hData = pDoor; - - GetNavigator()->GetPath()->PrependWaypoints( pOpenDoorRoute ); - - m_hOpeningDoor = pDoor; - pMoveGoal->maxDist = distClear; - *pResult = AIMR_CHANGE_TYPE; - - return true; - } - else - AIDoorDebugMsg( this, "Failed create door route!\n" ); - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Called by the navigator to initiate the opening of a prop_door -// that is in our way. -//----------------------------------------------------------------------------- -void CAI_BaseNPC::OpenPropDoorBegin( CBasePropDoor *pDoor ) -{ - // dvs: not quite working, disabled for now. - //opendata_t opendata; - //pDoor->GetNPCOpenData(this, opendata); - // - //if (HaveSequenceForActivity(opendata.eActivity)) - //{ - // SetIdealActivity(opendata.eActivity); - //} - //else - { - // We don't have an appropriate sequence, just open the door magically. - OpenPropDoorNow( pDoor ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Called when we are trying to open a prop_door and it's time to start -// the door moving. This is called either in response to an anim event -// or as a fallback when we don't have an appropriate open activity. -//----------------------------------------------------------------------------- -void CAI_BaseNPC::OpenPropDoorNow( CBasePropDoor *pDoor ) -{ - // Start the door moving. - pDoor->NPCOpenDoor(this); - - // Wait for the door to finish opening before trying to move through the doorway. - m_flMoveWaitFinished = gpGlobals->curtime + pDoor->GetOpenInterval(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Called when the door we were trying to open becomes fully open. -// Input : pDoor - -//----------------------------------------------------------------------------- -void CAI_BaseNPC::OnDoorFullyOpen(CBasePropDoor *pDoor) -{ - // We're done with the door. - m_hOpeningDoor = NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Called when the door we were trying to open becomes blocked before opening. -// Input : pDoor - -//----------------------------------------------------------------------------- -void CAI_BaseNPC::OnDoorBlocked(CBasePropDoor *pDoor) -{ - // dvs: FIXME: do something so that we don't loop forever trying to open this door - // not clearing out the door handle will cause the NPC to invalidate the connection - // We're done with the door. - //m_hOpeningDoor = NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Template NPCs are marked as templates by the level designer. They -// do not spawn, but their keyvalues are saved for use by a template -// spawner. -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::IsTemplate( void ) -{ - return HasSpawnFlags( SF_NPC_TEMPLATE ); -} - - - -//----------------------------------------------------------------------------- -// -// Movement code for walking + flying -// -//----------------------------------------------------------------------------- -int CAI_BaseNPC::FlyMove( const Vector& pfPosition, unsigned int mask ) -{ - Vector oldorg, neworg; - trace_t trace; - - // try the move - VectorCopy( GetAbsOrigin(), oldorg ); - VectorAdd( oldorg, pfPosition, neworg ); - UTIL_TraceEntity( this, oldorg, neworg, mask, &trace ); - if (trace.fraction == 1) - { - if ( (GetFlags() & FL_SWIM) && enginetrace->GetPointContents(trace.endpos) == CONTENTS_EMPTY ) - return false; // swim monster left water - - SetAbsOrigin( trace.endpos ); - PhysicsTouchTriggers(); - return true; - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : ent - -// Dir - Normalized direction vector for movement. -// dist - Distance along 'Dir' to move. -// iMode - -// Output : Returns nonzero on success, zero on failure. -//----------------------------------------------------------------------------- -int CAI_BaseNPC::WalkMove( const Vector& vecPosition, unsigned int mask ) -{ - if ( GetFlags() & (FL_FLY | FL_SWIM) ) - { - return FlyMove( vecPosition, mask ); - } - - if ( (GetFlags() & FL_ONGROUND) == 0 ) - { - return 0; - } - - trace_t trace; - Vector oldorg, neworg, end; - Vector move( vecPosition[0], vecPosition[1], 0.0f ); - VectorCopy( GetAbsOrigin(), oldorg ); - VectorAdd( oldorg, move, neworg ); - - // push down from a step height above the wished position - float flStepSize = sv_stepsize.GetFloat(); - neworg[2] += flStepSize; - VectorCopy(neworg, end); - end[2] -= flStepSize*2; - - UTIL_TraceEntity( this, neworg, end, mask, &trace ); - if ( trace.allsolid ) - return false; - - if (trace.startsolid) - { - neworg[2] -= flStepSize; - UTIL_TraceEntity( this, neworg, end, mask, &trace ); - if ( trace.allsolid || trace.startsolid ) - return false; - } - - if (trace.fraction == 1) - { - // if monster had the ground pulled out, go ahead and fall - if ( GetFlags() & FL_PARTIALGROUND ) - { - SetAbsOrigin( oldorg + move ); - PhysicsTouchTriggers(); - SetGroundEntity( NULL ); - return true; - } - - return false; // walked off an edge - } - - // check point traces down for dangling corners - SetAbsOrigin( trace.endpos ); - - if (UTIL_CheckBottom( this, NULL, flStepSize ) == 0) - { - if ( GetFlags() & FL_PARTIALGROUND ) - { - // entity had floor mostly pulled out from underneath it - // and is trying to correct - PhysicsTouchTriggers(); - return true; - } - - // Reset to original position - SetAbsOrigin( oldorg ); - return false; - } - - if ( GetFlags() & FL_PARTIALGROUND ) - { - // Con_Printf ("back on ground\n"); - RemoveFlag( FL_PARTIALGROUND ); - } - - // the move is ok - SetGroundEntity( trace.m_pEnt ); - PhysicsTouchTriggers(); - return true; -} - -//----------------------------------------------------------------------------- - -static void AIMsgGuts( CAI_BaseNPC *pAI, unsigned flags, const char *pszMsg ) -{ - int len = strlen( pszMsg ); - const char *pszFmt2 = NULL; - - if ( len && pszMsg[len-1] == '\n' ) - { - (const_cast(pszMsg))[len-1] = 0; - pszFmt2 = "%s (%s: %d/%s) [%d]\n"; - } - else - pszFmt2 = "%s (%s: %d/%s) [%d]"; - - DevMsg( pszFmt2, - pszMsg, - pAI->GetClassname(), - pAI->entindex(), - ( pAI->GetEntityName() == NULL_STRING ) ? "" : STRING(pAI->GetEntityName()), - gpGlobals->tickcount ); -} - -void DevMsg( CAI_BaseNPC *pAI, unsigned flags, const char *pszFormat, ... ) -{ - if ( (flags & AIMF_IGNORE_SELECTED) || (pAI->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) ) - { - AIMsgGuts( pAI, flags, CFmtStr( &pszFormat ) ); - } -} - -//----------------------------------------------------------------------------- - -void DevMsg( CAI_BaseNPC *pAI, const char *pszFormat, ... ) -{ - if ( (pAI->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) ) - { - AIMsgGuts( pAI, 0, CFmtStr( &pszFormat ) ); - } -} - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::IsPlayerAlly( CBasePlayer *pPlayer ) -{ - if ( pPlayer == NULL ) - { - // in multiplayer mode we need a valid pPlayer - // or override this virtual function - if ( !AI_IsSinglePlayer() ) - return false; - - // NULL means single player mode - pPlayer = UTIL_GetLocalPlayer(); - } - - return ( !pPlayer || IRelationType( pPlayer ) == D_LI ); -} - -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::SetCommandGoal( const Vector &vecGoal ) -{ - m_vecCommandGoal = vecGoal; - m_CommandMoveMonitor.ClearMark(); -} - -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::ClearCommandGoal() -{ - m_vecCommandGoal = vec3_invalid; - m_CommandMoveMonitor.ClearMark(); -} - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::IsInPlayerSquad() const -{ - return ( m_pSquad && MAKE_STRING(m_pSquad->GetName()) == GetPlayerSquadName() && !CAI_Squad::IsSilentMember(this) ); -} - - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::CanBeUsedAsAFriend( void ) -{ - if ( IsCurSchedule(SCHED_FORCED_GO) || IsCurSchedule(SCHED_FORCED_GO_RUN) ) - return false; - return true; -} - -//----------------------------------------------------------------------------- - -Vector CAI_BaseNPC::GetSmoothedVelocity( void ) -{ - if( GetNavType() == NAV_GROUND || GetNavType() == NAV_FLY ) - { - return m_pMotor->GetCurVel(); - } - - return BaseClass::GetSmoothedVelocity(); -} - - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::IsCoverPosition( const Vector &vecThreat, const Vector &vecPosition ) -{ - trace_t tr; - - // By default, we ignore the viewer (me) when determining cover positions - CTraceFilterLOS filter( NULL, COLLISION_GROUP_NONE, this ); - - // If I'm trying to find cover from the player, and the player is in a vehicle, - // ignore the vehicle for the purpose of determining line of sight. - CBaseEntity *pEnemy = GetEnemy(); - if ( pEnemy ) - { - // Hack to see if our threat position is our enemy - bool bThreatPosIsEnemy = ( (vecThreat - GetEnemy()->EyePosition()).LengthSqr() < 0.1f ); - if ( bThreatPosIsEnemy ) - { - CBaseCombatCharacter *pCCEnemy = GetEnemy()->MyCombatCharacterPointer(); - if ( pCCEnemy != NULL && pCCEnemy->IsInAVehicle() ) - { - // Ignore the vehicle - filter.SetPassEntity( pCCEnemy->GetVehicleEntity() ); - } - - if ( !filter.GetPassEntity() ) - { - filter.SetPassEntity( pEnemy ); - } - } - } - - AI_TraceLOS( vecThreat, vecPosition, this, &tr, &filter ); - - if( tr.fraction != 1.0 && hl2_episodic.GetBool() ) - { - if( tr.m_pEnt->m_iClassname == m_iClassname ) - { - // Don't hide behind buddies! - return false; - } - } - - return (tr.fraction != 1.0); -} - -//----------------------------------------------------------------------------- - -float CAI_BaseNPC::SetWait( float minWait, float maxWait ) -{ - int minThinks = Ceil2Int( minWait * 10 ); - - if ( maxWait == 0.0 ) - { - m_flWaitFinished = gpGlobals->curtime + ( 0.1 * minThinks ); - } - else - { - if ( minThinks == 0 ) // random 0..n is almost certain to not return 0 - minThinks = 1; - int maxThinks = Ceil2Int( maxWait * 10 ); - - m_flWaitFinished = gpGlobals->curtime + ( 0.1 * random->RandomInt( minThinks, maxThinks ) ); - } - return m_flWaitFinished; -} - -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::ClearWait() -{ - m_flWaitFinished = FLT_MAX; -} - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::IsWaitFinished() -{ - return ( gpGlobals->curtime >= m_flWaitFinished ); -} - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::IsWaitSet() -{ - return ( m_flWaitFinished != FLT_MAX ); -} - -void CAI_BaseNPC::TestPlayerPushing( CBaseEntity *pEntity ) -{ - if ( HasSpawnFlags( SF_NPC_NO_PLAYER_PUSHAWAY ) ) - return; - - // Heuristic for determining if the player is pushing me away - CBasePlayer *pPlayer = ToBasePlayer( pEntity ); - if ( pPlayer && !( pPlayer->GetFlags() & FL_NOTARGET ) ) - { - if ( (pPlayer->m_nButtons & (IN_FORWARD|IN_BACK|IN_MOVELEFT|IN_MOVERIGHT)) || - pPlayer->GetAbsVelocity().AsVector2D().LengthSqr() > 50*50 ) - { - SetCondition( COND_PLAYER_PUSHING ); - Vector vecPush = GetAbsOrigin() - pPlayer->GetAbsOrigin(); - VectorNormalize( vecPush ); - CascadePlayerPush( vecPush, pPlayer->WorldSpaceCenter() ); - } - } -} - -void CAI_BaseNPC::CascadePlayerPush( const Vector &push, const Vector &pushOrigin ) -{ - // - // Try to push any friends that are in the way. - // - float hullWidth = GetHullWidth(); - const Vector & origin = GetAbsOrigin(); - const Vector2D &origin2D = origin.AsVector2D(); - - const float MIN_Z_TO_TRANSMIT = GetHullHeight() * 0.5 + 0.1; - const float DIST_REQD_TO_TRANSMIT_PUSH_SQ = Square( hullWidth * 5 + 0.1 ); - const float DIST_FROM_PUSH_VECTOR_REQD_SQ = Square( hullWidth + 0.1 ); - - Vector2D pushTestPoint = vec2_invalid; - - for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - CAI_BaseNPC *pOther = g_AI_Manager.AccessAIs()[i]; - if ( pOther != this && pOther->IRelationType(this) == D_LI && !pOther->HasCondition( COND_PLAYER_PUSHING ) ) - { - const Vector &friendOrigin = pOther->GetAbsOrigin(); - if ( fabsf( friendOrigin.z - origin.z ) < MIN_Z_TO_TRANSMIT && - ( friendOrigin.AsVector2D() - origin.AsVector2D() ).LengthSqr() < DIST_REQD_TO_TRANSMIT_PUSH_SQ ) - { - if ( pushTestPoint == vec2_invalid ) - { - pushTestPoint = origin2D - pushOrigin.AsVector2D(); - // No normalize, since it wants to just be a big number and we can't be less that a hull away - pushTestPoint *= 2000; - pushTestPoint += origin2D; - - } - float t; - float distSq = CalcDistanceSqrToLine2D( friendOrigin.AsVector2D(), origin2D, pushTestPoint, &t ); - if ( t > 0 && distSq < DIST_FROM_PUSH_VECTOR_REQD_SQ ) - { - pOther->SetCondition( COND_PLAYER_PUSHING ); - } - } - } - } -} - - -//----------------------------------------------------------------------------- -// Break into pieces! -//----------------------------------------------------------------------------- -void CAI_BaseNPC::Break( CBaseEntity *pBreaker ) -{ - m_takedamage = DAMAGE_NO; - - Vector velocity; - AngularImpulse angVelocity; - IPhysicsObject *pPhysics = VPhysicsGetObject(); - Vector origin; - QAngle angles; - AddSolidFlags( FSOLID_NOT_SOLID ); - if ( pPhysics ) - { - pPhysics->GetVelocity( &velocity, &angVelocity ); - pPhysics->GetPosition( &origin, &angles ); - pPhysics->RecheckCollisionFilter(); - } - else - { - velocity = GetAbsVelocity(); - QAngleToAngularImpulse( GetLocalAngularVelocity(), angVelocity ); - origin = GetAbsOrigin(); - angles = GetAbsAngles(); - } - - breakablepropparams_t params( GetAbsOrigin(), GetAbsAngles(), velocity, angVelocity ); - params.impactEnergyScale = m_impactEnergyScale; - params.defCollisionGroup = GetCollisionGroup(); - if ( params.defCollisionGroup == COLLISION_GROUP_NONE ) - { - // don't automatically make anything COLLISION_GROUP_NONE or it will - // collide with debris being ejected by breaking - params.defCollisionGroup = COLLISION_GROUP_INTERACTIVE; - } - - // no damage/damage force? set a burst of 100 for some movement - params.defBurstScale = 100;//pDamageInfo ? 0 : 100; - PropBreakableCreateAll( GetModelIndex(), pPhysics, params, this, -1, false ); - - UTIL_Remove(this); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for breaking the breakable immediately. -//----------------------------------------------------------------------------- -void CAI_BaseNPC::InputBreak( inputdata_t &inputdata ) -{ - Break( inputdata.pActivator ); -} - - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::FindNearestValidGoalPos( const Vector &vTestPoint, Vector *pResult ) -{ - AIMoveTrace_t moveTrace; - Vector vCandidate = vec3_invalid; - if ( GetNavigator()->CanFitAtPosition( vTestPoint, MASK_SOLID_BRUSHONLY ) ) - { - if ( GetMoveProbe()->CheckStandPosition( vTestPoint, MASK_SOLID_BRUSHONLY ) ) - { - vCandidate = vTestPoint; - } - } - - if ( vCandidate == vec3_invalid ) - { - int iNearestNode = GetPathfinder()->NearestNodeToPoint( vTestPoint ); - if ( iNearestNode != NO_NODE ) - { - GetMoveProbe()->MoveLimit( NAV_GROUND, - g_pBigAINet->GetNodePosition(GetHullType(), iNearestNode ), - vTestPoint, - MASK_SOLID_BRUSHONLY, - NULL, - 0, - &moveTrace ); - if ( ( moveTrace.vEndPosition - vTestPoint ).Length2DSqr() < Square( GetHullWidth() * 3.0 ) && - GetMoveProbe()->CheckStandPosition( moveTrace.vEndPosition, MASK_SOLID_BRUSHONLY ) ) - { - vCandidate = moveTrace.vEndPosition; - } - } - } - - if ( vCandidate != vec3_invalid ) - { - AI_Waypoint_t *pPathToPoint = GetPathfinder()->BuildRoute( GetAbsOrigin(), vCandidate, AI_GetSinglePlayer(), 5*12, NAV_NONE, true ); - if ( pPathToPoint ) - { - GetPathfinder()->UnlockRouteNodes( pPathToPoint ); - CAI_Path tempPath; - tempPath.SetWaypoints( pPathToPoint ); // path object will delete waypoints - } - else - vCandidate = vec3_invalid; - } - - if ( vCandidate == vec3_invalid ) - { - GetMoveProbe()->MoveLimit( NAV_GROUND, - GetAbsOrigin(), - vTestPoint, - MASK_SOLID_BRUSHONLY, - NULL, - 0, - &moveTrace ); - vCandidate = moveTrace.vEndPosition; - } - - if ( vCandidate == vec3_invalid ) - return false; - - if ( pResult != NULL ) - { - *pResult = vCandidate; - } - - return true; -} - -//--------------------------------------------------------- -// Pass a direction to get how far an NPC would see if facing -// that direction. Pass nothing to get the length of the NPC's -// current line of sight. -//--------------------------------------------------------- -float CAI_BaseNPC::LineOfSightDist( const Vector &vecDir, float zEye ) -{ - Vector testDir; - if( vecDir == vec3_invalid ) - { - testDir = EyeDirection3D(); - } - else - { - testDir = vecDir; - } - - if ( zEye == FLT_MAX ) - zEye = EyePosition().z; - - trace_t tr; - // Need to center trace so don't get erratic results based on orientation - Vector testPos( GetAbsOrigin().x, GetAbsOrigin().y, zEye ); - AI_TraceLOS( testPos, testPos + testDir * MAX_COORD_RANGE, this, &tr ); - return (tr.startpos - tr.endpos ).Length(); -} - -ConVar ai_LOS_mode( "ai_LOS_mode", "0", FCVAR_REPLICATED ); - -//----------------------------------------------------------------------------- -// Purpose: Use this to perform AI tracelines that are trying to determine LOS between points. -// LOS checks between entities should use FVisible. -//----------------------------------------------------------------------------- -void AI_TraceLOS( const Vector& vecAbsStart, const Vector& vecAbsEnd, CBaseEntity *pLooker, trace_t *ptr, ITraceFilter *pFilter ) -{ - AI_PROFILE_SCOPE( AI_TraceLOS ); - - if ( ai_LOS_mode.GetBool() ) - { - // Don't use LOS tracefilter - UTIL_TraceLine( vecAbsStart, vecAbsEnd, MASK_BLOCKLOS, pLooker, COLLISION_GROUP_NONE, ptr ); - return; - } - - // Use the custom LOS trace filter - CTraceFilterLOS traceFilter( pLooker, COLLISION_GROUP_NONE ); - if ( !pFilter ) - pFilter = &traceFilter; - AI_TraceLine( vecAbsStart, vecAbsEnd, MASK_BLOCKLOS_AND_NPCS, pFilter, ptr ); -} - -void CAI_BaseNPC::InputSetSpeedModifierRadius( inputdata_t &inputdata ) -{ - m_iSpeedModRadius = inputdata.value.Int(); - m_iSpeedModRadius *= m_iSpeedModRadius; -} -void CAI_BaseNPC::InputSetSpeedModifierSpeed( inputdata_t &inputdata ) -{ - m_iSpeedModSpeed = inputdata.value.Int(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::IsAllowedToDodge( void ) -{ - // Can't do it if I'm not available - if ( m_NPCState != NPC_STATE_IDLE && m_NPCState != NPC_STATE_ALERT && m_NPCState != NPC_STATE_COMBAT ) - return false; - - return ( m_flNextDodgeTime <= gpGlobals->curtime ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::ParseScriptedNPCInteractions( void ) -{ - // Already parsed them? - if ( m_ScriptedInteractions.Count() ) - return; - - // Parse the model's key values and find any dynamic interactions - KeyValues *modelKeyValues = new KeyValues(""); - CUtlBuffer buf( 1024, 0, CUtlBuffer::TEXT_BUFFER ); - - if (! modelinfo->GetModelKeyValue( GetModel(), buf )) - return; - - if ( modelKeyValues->LoadFromBuffer( modelinfo->GetModelName( GetModel() ), buf ) ) - { - // Do we have a dynamic interactions section? - KeyValues *pkvInteractions = modelKeyValues->FindKey("dynamic_interactions"); - if ( pkvInteractions ) - { - KeyValues *pkvNode = pkvInteractions->GetFirstSubKey(); - while ( pkvNode ) - { - ScriptedNPCInteraction_t sInteraction; - sInteraction.iszInteractionName = AllocPooledString( pkvNode->GetName() ); - - // Trigger method - const char *pszTrigger = pkvNode->GetString( "trigger", NULL ); - if ( pszTrigger ) - { - if ( !Q_strncmp( pszTrigger, "auto_in_combat", 14) ) - { - sInteraction.iTriggerMethod = SNPCINT_AUTOMATIC_IN_COMBAT; - } - } - - // Loop Break trigger method - pszTrigger = pkvNode->GetString( "loop_break_trigger", NULL ); - if ( pszTrigger ) - { - char szTrigger[256]; - Q_strncpy( szTrigger, pszTrigger, sizeof(szTrigger) ); - char *pszParam = strtok( szTrigger, " " ); - while (pszParam) - { - if ( !Q_strncmp( pszParam, "on_damage", 9) ) - { - sInteraction.iLoopBreakTriggerMethod |= SNPCINT_LOOPBREAK_ON_DAMAGE; - } - if ( !Q_strncmp( pszParam, "on_flashlight_illum", 19) ) - { - sInteraction.iLoopBreakTriggerMethod |= SNPCINT_LOOPBREAK_ON_FLASHLIGHT_ILLUM; - } - - pszParam = strtok(NULL," "); - } - } - - // Origin - const char *pszOrigin = pkvNode->GetString( "origin_relative", "0 0 0" ); - UTIL_StringToVector( sInteraction.vecRelativeOrigin.Base(), pszOrigin ); - - // Angles - const char *pszAngles = pkvNode->GetString( "angles_relative", NULL ); - if ( pszAngles ) - { - sInteraction.iFlags |= SCNPC_FLAG_TEST_OTHER_ANGLES; - UTIL_StringToVector( sInteraction.angRelativeAngles.Base(), pszAngles ); - } - - // Velocity - const char *pszVelocity = pkvNode->GetString( "velocity_relative", NULL ); - if ( pszVelocity ) - { - sInteraction.iFlags |= SCNPC_FLAG_TEST_OTHER_VELOCITY; - UTIL_StringToVector( sInteraction.vecRelativeVelocity.Base(), pszVelocity ); - } - - // Entry Sequence - const char *pszSequence = pkvNode->GetString( "entry_sequence", NULL ); - if ( pszSequence ) - { - sInteraction.sPhases[SNPCINT_ENTRY].iszSequence = AllocPooledString( pszSequence ); - } - // Entry Activity - const char *pszActivity = pkvNode->GetString( "entry_activity", NULL ); - if ( pszActivity ) - { - sInteraction.sPhases[SNPCINT_ENTRY].iActivity = GetActivityID( pszActivity ); - } - - // Sequence - pszSequence = pkvNode->GetString( "sequence", NULL ); - if ( pszSequence ) - { - sInteraction.sPhases[SNPCINT_SEQUENCE].iszSequence = AllocPooledString( pszSequence ); - } - // Activity - pszActivity = pkvNode->GetString( "activity", NULL ); - if ( pszActivity ) - { - sInteraction.sPhases[SNPCINT_SEQUENCE].iActivity = GetActivityID( pszActivity ); - } - - // Exit Sequence - pszSequence = pkvNode->GetString( "exit_sequence", NULL ); - if ( pszSequence ) - { - sInteraction.sPhases[SNPCINT_EXIT].iszSequence = AllocPooledString( pszSequence ); - } - // Exit Activity - pszActivity = pkvNode->GetString( "exit_activity", NULL ); - if ( pszActivity ) - { - sInteraction.sPhases[SNPCINT_EXIT].iActivity = GetActivityID( pszActivity ); - } - - // Delay - sInteraction.flDelay = pkvNode->GetFloat( "delay", 10.0 ); - - // Delta - sInteraction.flDistSqr = pkvNode->GetFloat( "origin_max_delta", (DSS_MAX_DIST * DSS_MAX_DIST) ); - - // Loop? - if ( pkvNode->GetFloat( "loop_in_action", 0 ) ) - { - sInteraction.iFlags |= SCNPC_FLAG_LOOP_IN_ACTION; - } - - // Fixup position? - const char *pszDontFixup = pkvNode->GetString( "dont_teleport_at_end", NULL ); - if ( pszDontFixup ) - { - if ( !Q_stricmp( pszDontFixup, "me" ) || !Q_stricmp( pszDontFixup, "both" ) ) - { - sInteraction.iFlags |= SCNPC_FLAG_DONT_TELEPORT_AT_END_ME; - } - else if ( !Q_stricmp( pszDontFixup, "them" ) || !Q_stricmp( pszDontFixup, "both" ) ) - { - sInteraction.iFlags |= SCNPC_FLAG_DONT_TELEPORT_AT_END_THEM; - } - } - - // Needs a weapon? - const char *pszNeedsWeapon = pkvNode->GetString( "needs_weapon", NULL ); - if ( pszNeedsWeapon ) - { - if ( !Q_strncmp( pszNeedsWeapon, "ME", 2 ) ) - { - sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_ME; - } - else if ( !Q_strncmp( pszNeedsWeapon, "THEM", 4 ) ) - { - sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_THEM; - } - else if ( !Q_strncmp( pszNeedsWeapon, "BOTH", 4 ) ) - { - sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_ME; - sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_THEM; - } - } - - // Specific weapon types - const char *pszWeaponName = pkvNode->GetString( "weapon_mine", NULL ); - if ( pszWeaponName ) - { - sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_ME; - sInteraction.iszMyWeapon = AllocPooledString( pszWeaponName ); - } - pszWeaponName = pkvNode->GetString( "weapon_theirs", NULL ); - if ( pszWeaponName ) - { - sInteraction.iFlags |= SCNPC_FLAG_NEEDS_WEAPON_THEM; - sInteraction.iszTheirWeapon = AllocPooledString( pszWeaponName ); - } - - // Add it to the list - AddScriptedNPCInteraction( &sInteraction ); - - // Move to next interaction - pkvNode = pkvNode->GetNextKey(); - } - } - } - - modelKeyValues->deleteThis(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::AddScriptedNPCInteraction( ScriptedNPCInteraction_t *pInteraction ) -{ - int nNewIndex = m_ScriptedInteractions.AddToTail(); - - if ( ai_debug_dyninteractions.GetBool() ) - { - Msg("%s(%s): Added dynamic interaction: %s\n", GetClassname(), GetDebugName(), STRING(pInteraction->iszInteractionName) ); - } - - // Copy the interaction over - ScriptedNPCInteraction_t *pNewInt = &(m_ScriptedInteractions[nNewIndex]); - memcpy( pNewInt, pInteraction, sizeof(ScriptedNPCInteraction_t) ); - - // Calculate the local to world matrix - m_ScriptedInteractions[nNewIndex].matDesiredLocalToWorld.SetupMatrixOrgAngles( pInteraction->vecRelativeOrigin, pInteraction->angRelativeAngles ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const char *CAI_BaseNPC::GetScriptedNPCInteractionSequence( ScriptedNPCInteraction_t *pInteraction, int iPhase ) -{ - if ( pInteraction->sPhases[iPhase].iActivity != ACT_INVALID ) - { - int iSequence = SelectWeightedSequence( (Activity)pInteraction->sPhases[iPhase].iActivity ); - return GetSequenceName( iSequence ); - } - - if ( pInteraction->sPhases[iPhase].iszSequence != NULL_STRING ) - return STRING(pInteraction->sPhases[iPhase].iszSequence); - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::StartRunningInteraction( CAI_BaseNPC *pOtherNPC, bool bActive ) -{ - m_hInteractionPartner = pOtherNPC; - if ( bActive ) - { - m_iInteractionState = NPCINT_RUNNING_ACTIVE; - } - else - { - m_iInteractionState = NPCINT_RUNNING_PARTNER; - } - m_bCannotDieDuringInteraction = true; - - // Force the NPC into an idle schedule so they don't move. - // NOTE: We must set SCHED_IDLE_STAND directly, to prevent derived NPC - // classes from translating the idle stand schedule away to do something bad. - SetSchedule( GetSchedule(SCHED_IDLE_STAND) ); - - // Prepare the NPC for the script. Setting this allows the scripted sequences - // that we're about to create to immediately grab & use this NPC right away. - // This prevents the NPC from being able to make any schedule decisions - // before the DSS gets underway. - m_scriptState = SCRIPT_PLAYING; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::StartScriptedNPCInteraction( CAI_BaseNPC *pOtherNPC, ScriptedNPCInteraction_t *pInteraction, Vector vecOtherOrigin, QAngle angOtherAngles ) -{ - variant_t emptyVariant; - - StartRunningInteraction( pOtherNPC, true ); - if ( pOtherNPC ) - { - pOtherNPC->StartRunningInteraction( this, false ); - - //Msg("%s(%s) disabled collisions with %s(%s) at %0.2f\n", GetClassname(), GetDebugName(), pOtherNPC->GetClassName(), pOtherNPC->GetDebugName(), gpGlobals->curtime ); - PhysDisableEntityCollisions( this, pOtherNPC ); - } - - // Determine which sequences we're going to use - const char *pszEntrySequence = GetScriptedNPCInteractionSequence( pInteraction, SNPCINT_ENTRY ); - const char *pszSequence = GetScriptedNPCInteractionSequence( pInteraction, SNPCINT_SEQUENCE ); - const char *pszExitSequence = GetScriptedNPCInteractionSequence( pInteraction, SNPCINT_EXIT ); - - // Debug - if ( ai_debug_dyninteractions.GetBool() ) - { - if ( pOtherNPC ) - { - Msg("%s(%s) starting dynamic interaction \"%s\" with %s(%s).\n", GetClassname(), GetDebugName(), STRING(pInteraction->iszInteractionName), pOtherNPC->GetClassname(), pOtherNPC->GetDebugName() ); - if ( pszEntrySequence ) - { - Msg( " - Entry sequence: %s\n", pszEntrySequence ); - } - Msg( " - Core sequence: %s\n", pszSequence ); - if ( pszExitSequence ) - { - Msg( " - Exit sequence: %s\n", pszExitSequence ); - } - } - } - - // Create a scripted sequence name that's guaranteed to be unique - char szSSName[256]; - if ( pOtherNPC ) - { - Q_snprintf( szSSName, sizeof(szSSName), "dss_%s%d%s%d", GetDebugName(), entindex(), pOtherNPC->GetDebugName(), pOtherNPC->entindex() ); - } - else - { - Q_snprintf( szSSName, sizeof(szSSName), "dss_%s%d", GetDebugName(), entindex() ); - } - string_t iszSSName = AllocPooledString(szSSName); - - // Setup next attempt - pInteraction->flNextAttemptTime = gpGlobals->curtime + pInteraction->flDelay + RandomFloat(-2,2); - - // Spawn a scripted sequence for this NPC to play the interaction anim - CAI_ScriptedSequence *pMySequence = (CAI_ScriptedSequence*)CreateEntityByName( "scripted_sequence" ); - pMySequence->KeyValue( "m_iszEntry", pszEntrySequence ); - pMySequence->KeyValue( "m_iszPlay", pszSequence ); - pMySequence->KeyValue( "m_iszPostIdle", pszExitSequence ); - pMySequence->KeyValue( "m_fMoveTo", "5" ); - pMySequence->SetAbsOrigin( GetAbsOrigin() ); - - QAngle angDesired = GetAbsAngles(); - angDesired[YAW] = m_flInteractionYaw; - - pMySequence->SetAbsAngles( angDesired ); - pMySequence->ForceSetTargetEntity( this, true ); - pMySequence->SetName( iszSSName ); - pMySequence->AddSpawnFlags( SF_SCRIPT_NOINTERRUPT | SF_SCRIPT_HIGH_PRIORITY | SF_SCRIPT_OVERRIDESTATE ); - if ((pInteraction->iFlags & SCNPC_FLAG_DONT_TELEPORT_AT_END_ME) != 0) - { - pMySequence->AddSpawnFlags( SF_SCRIPT_DONT_TELEPORT_AT_END ); - } - pMySequence->SetLoopActionSequence( (pInteraction->iFlags & SCNPC_FLAG_LOOP_IN_ACTION) != 0 ); - pMySequence->SetSynchPostIdles( true ); - if ( ai_debug_dyninteractions.GetBool() ) - { - pMySequence->m_debugOverlays |= OVERLAY_TEXT_BIT | OVERLAY_PIVOT_BIT; - } - - // Spawn the matching scripted sequence for the other NPC - CAI_ScriptedSequence *pTheirSequence = NULL; - if ( pOtherNPC ) - { - pTheirSequence = (CAI_ScriptedSequence*)CreateEntityByName( "scripted_sequence" ); - pTheirSequence->KeyValue( "m_iszEntry", pszEntrySequence ); - pTheirSequence->KeyValue( "m_iszPlay", pszSequence ); - pTheirSequence->KeyValue( "m_iszPostIdle", pszExitSequence ); - pTheirSequence->KeyValue( "m_fMoveTo", "5" ); - pTheirSequence->SetAbsOrigin( vecOtherOrigin ); - pTheirSequence->SetAbsAngles( angOtherAngles ); - pTheirSequence->ForceSetTargetEntity( pOtherNPC, true ); - pTheirSequence->SetName( iszSSName ); - pTheirSequence->AddSpawnFlags( SF_SCRIPT_NOINTERRUPT | SF_SCRIPT_HIGH_PRIORITY | SF_SCRIPT_OVERRIDESTATE ); - if ((pInteraction->iFlags & SCNPC_FLAG_DONT_TELEPORT_AT_END_THEM) != 0) - { - pTheirSequence->AddSpawnFlags( SF_SCRIPT_DONT_TELEPORT_AT_END ); - } - pTheirSequence->SetLoopActionSequence( (pInteraction->iFlags & SCNPC_FLAG_LOOP_IN_ACTION) != 0 ); - pTheirSequence->SetSynchPostIdles( true ); - if ( ai_debug_dyninteractions.GetBool() ) - { - pTheirSequence->m_debugOverlays |= OVERLAY_TEXT_BIT | OVERLAY_PIVOT_BIT; - } - - // Tell their sequence to keep their position relative to me - pTheirSequence->SetupInteractionPosition( this, pInteraction->matDesiredLocalToWorld ); - } - - // Spawn both sequences at once - pMySequence->Spawn(); - if ( pTheirSequence ) - { - pTheirSequence->Spawn(); - } - - // Call activate on both sequences at once - pMySequence->Activate(); - if ( pTheirSequence ) - { - pTheirSequence->Activate(); - } - - // Setup the outputs for both sequences. The first kills them both when it finishes - pMySequence->KeyValue( "OnCancelFailedSequence", UTIL_VarArgs("%s,Kill,,0,-1", szSSName ) ); - if ( pszExitSequence ) - { - pMySequence->KeyValue( "OnPostIdleEndSequence", UTIL_VarArgs("%s,Kill,,0,-1", szSSName ) ); - if ( pTheirSequence ) - { - pTheirSequence->KeyValue( "OnPostIdleEndSequence", UTIL_VarArgs("%s,Kill,,0,-1", szSSName ) ); - } - } - else - { - pMySequence->KeyValue( "OnEndSequence", UTIL_VarArgs("%s,Kill,,0,-1", szSSName ) ); - if ( pTheirSequence ) - { - pTheirSequence->KeyValue( "OnEndSequence", UTIL_VarArgs("%s,Kill,,0,-1", szSSName ) ); - } - } - if ( pTheirSequence ) - { - pTheirSequence->KeyValue( "OnCancelFailedSequence", UTIL_VarArgs("%s,Kill,,0,-1", szSSName ) ); - } - - // Tell both sequences to start - pMySequence->AcceptInput( "BeginSequence", this, this, emptyVariant, 0 ); - if ( pTheirSequence ) - { - pTheirSequence->AcceptInput( "BeginSequence", this, this, emptyVariant, 0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::CanRunAScriptedNPCInteraction( bool bForced ) -{ - if ( m_NPCState != NPC_STATE_IDLE && m_NPCState != NPC_STATE_ALERT && m_NPCState != NPC_STATE_COMBAT ) - return false; - - if ( !IsAlive() ) - return false; - - if ( IsOnFire() ) - return false; - - if ( IsCrouching() ) - return false; - - // Not while running scripted sequences - if ( m_hCine ) - return false; - - if ( bForced ) - { - if ( !m_hForcedInteractionPartner ) - return false; - } - else - { - if ( m_hForcedInteractionPartner || m_hInteractionPartner ) - return false; - if ( IsInAScript() || !HasCondition(COND_IN_PVS) ) - return false; - if ( HasCondition(COND_HEAR_DANGER) || HasCondition(COND_HEAR_MOVE_AWAY) ) - return false; - - // Default AI prevents interactions while melee attacking, but not ranged attacking - if ( IsCurSchedule( SCHED_MELEE_ATTACK1 ) || IsCurSchedule( SCHED_MELEE_ATTACK2 ) ) - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::CheckForScriptedNPCInteractions( void ) -{ - // Are we being forced to interact with another NPC? If so, do that - if ( m_hForcedInteractionPartner ) - { - CheckForcedNPCInteractions(); - return; - } - - // Otherwise, see if we can interaction with our enemy - if ( !m_ScriptedInteractions.Count() || !GetEnemy() ) - return; - - CAI_BaseNPC *pNPC = GetEnemy()->MyNPCPointer(); - - if( !pNPC ) - return; - - // Recalculate interaction capability whenever we switch enemies - if ( m_hLastInteractionTestTarget != GetEnemy() ) - { - m_hLastInteractionTestTarget = GetEnemy(); - - CalculateValidEnemyInteractions(); - } - - // First, make sure I'm in a state where I can do this - if ( !CanRunAScriptedNPCInteraction() ) - return; - if ( pNPC && !pNPC->CanRunAScriptedNPCInteraction() ) - return; - - for ( int i = 0; i < m_ScriptedInteractions.Count(); i++ ) - { - ScriptedNPCInteraction_t *pInteraction = &m_ScriptedInteractions[i]; - - if ( !pInteraction->bValidOnCurrentEnemy ) - continue; - - if ( pInteraction->flNextAttemptTime > gpGlobals->curtime ) - continue; - - Vector vecOrigin; - QAngle angAngles; - if ( InteractionCouldStart( pNPC, pInteraction, vecOrigin, angAngles ) ) - { - m_iInteractionPlaying = i; - StartScriptedNPCInteraction( pNPC, pInteraction, vecOrigin, angAngles ); - break; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Calculate all the valid dynamic interactions we can perform with our current enemy -//----------------------------------------------------------------------------- -void CAI_BaseNPC::CalculateValidEnemyInteractions( void ) -{ - CAI_BaseNPC *pNPC = GetEnemy()->MyNPCPointer(); - if ( !pNPC ) - return; - - bool bDebug = (m_debugOverlays & OVERLAY_NPC_SELECTED_BIT && ai_debug_dyninteractions.GetBool()); - if ( bDebug ) - { - Msg("%s(%s): Computing valid interactions with %s(%s)\n", GetClassname(), GetDebugName(), pNPC->GetClassname(), pNPC->GetDebugName() ); - } - - bool bFound = false; - for ( int i = 0; i < m_ScriptedInteractions.Count(); i++ ) - { - ScriptedNPCInteraction_t *pInteraction = &m_ScriptedInteractions[i]; - pInteraction->bValidOnCurrentEnemy = false; - - // If the trigger method of the interaction isn't the one we're after, we're done - if ( pInteraction->iTriggerMethod != SNPCINT_AUTOMATIC_IN_COMBAT ) - continue; - - if ( !pNPC->GetModelPtr() ) - continue; - - // If we have a damage filter that prevents us hurting the enemy, - // don't interact with him, since most interactions kill the enemy. - // Create a fake damage info to test it with. - CTakeDamageInfo tempinfo( this, this, vec3_origin, vec3_origin, 1.0, DMG_BULLET ); - if ( !pNPC->PassesDamageFilter( tempinfo ) ) - continue; - - // Check the weapon requirements for the interaction - if ( pInteraction->iFlags & SCNPC_FLAG_NEEDS_WEAPON_ME ) - { - if ( !GetActiveWeapon()) - continue; - - // Check the specific weapon type - if ( pInteraction->iszMyWeapon != NULL_STRING && GetActiveWeapon()->m_iClassname != pInteraction->iszMyWeapon ) - continue; - } - if ( pInteraction->iFlags & SCNPC_FLAG_NEEDS_WEAPON_THEM ) - { - if ( !pNPC->GetActiveWeapon() ) - continue; - - // Check the specific weapon type - if ( pInteraction->iszTheirWeapon != NULL_STRING && pNPC->GetActiveWeapon()->m_iClassname != pInteraction->iszTheirWeapon ) - continue; - } - - // Script needs the other NPC, so make sure they're not dead - if ( !pNPC->IsAlive() ) - continue; - - // Use sequence? or activity? - if ( pInteraction->sPhases[SNPCINT_SEQUENCE].iActivity != ACT_INVALID ) - { - // Resolve the activity to a sequence, and make sure our enemy has it - const char *pszSequence = GetScriptedNPCInteractionSequence( pInteraction, SNPCINT_SEQUENCE ); - if ( !pszSequence ) - continue; - if ( pNPC->LookupSequence( pszSequence ) == -1 ) - continue; - } - else - { - if ( pNPC->LookupSequence( STRING(pInteraction->sPhases[SNPCINT_SEQUENCE].iszSequence) ) == -1 ) - continue; - } - - pInteraction->bValidOnCurrentEnemy = true; - bFound = true; - - if ( bDebug ) - { - Msg(" Found: %s\n", STRING(pInteraction->iszInteractionName) ); - } - } - - if ( bDebug && !bFound ) - { - Msg(" No valid interactions found.\n"); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::CheckForcedNPCInteractions( void ) -{ - // If we don't have an interaction, we're waiting for our partner to start it. Do nothing. - if ( m_iInteractionPlaying == NPCINT_NONE ) - return; - - CAI_BaseNPC *pNPC = m_hForcedInteractionPartner->MyNPCPointer(); - bool bAbort = false; - - // First, make sure both NPCs are able to do this - if ( !CanRunAScriptedNPCInteraction( true ) || !pNPC->CanRunAScriptedNPCInteraction( true ) ) - { - // If we were still moving to our target, abort. - if ( m_iInteractionState == NPCINT_MOVING_TO_MARK ) - { - bAbort = true; - } - else - { - return; - } - } - - // Check to see if we can start our interaction. If we can, dance. - Vector vecOrigin; - QAngle angAngles; - - ScriptedNPCInteraction_t *pInteraction = &m_ScriptedInteractions[m_iInteractionPlaying]; - - if ( !bAbort ) - { - if ( !InteractionCouldStart( pNPC, pInteraction, vecOrigin, angAngles ) ) - { - if ( ( gpGlobals->curtime > m_flForcedInteractionTimeout ) && ( m_iInteractionState == NPCINT_MOVING_TO_MARK ) ) - { - bAbort = true; - } - else - { - return; - } - } - } - - if ( bAbort ) - { - if ( m_hForcedInteractionPartner ) - { - // We've aborted a forced interaction. Let the mapmaker know. - m_OnForcedInteractionAborted.FireOutput( this, this ); - } - - CleanupForcedInteraction(); - pNPC->CleanupForcedInteraction(); - - return; - } - - StartScriptedNPCInteraction( pNPC, pInteraction, vecOrigin, angAngles ); - m_OnForcedInteractionStarted.FireOutput( this, this ); -} - - -//----------------------------------------------------------------------------- -// Returns whether two NPCs can fit at each other's origin. -// Kinda like that movie with Eddie Murphy and Dan Akroyd. -//----------------------------------------------------------------------------- -bool CanNPCsTradePlaces( CAI_BaseNPC *pNPC1, CAI_BaseNPC *pNPC2, bool bDebug ) -{ - bool bTest1At2 = true; - bool bTest2At1 = true; - - if ( ( pNPC1->GetHullMins().x <= pNPC2->GetHullMins().x ) && - ( pNPC1->GetHullMins().y <= pNPC2->GetHullMins().y ) && - ( pNPC1->GetHullMins().z <= pNPC2->GetHullMins().z ) && - ( pNPC1->GetHullMaxs().x >= pNPC2->GetHullMaxs().x ) && - ( pNPC1->GetHullMaxs().y >= pNPC2->GetHullMaxs().y ) && - ( pNPC1->GetHullMaxs().z >= pNPC2->GetHullMaxs().z ) ) - { - // 1 bigger than 2 in all axes, skip 2 in 1 test - bTest2At1 = false; - } - else if ( ( pNPC2->GetHullMins().x <= pNPC1->GetHullMins().x ) && - ( pNPC2->GetHullMins().y <= pNPC1->GetHullMins().y ) && - ( pNPC2->GetHullMins().z <= pNPC1->GetHullMins().z ) && - ( pNPC2->GetHullMaxs().x >= pNPC1->GetHullMaxs().x ) && - ( pNPC2->GetHullMaxs().y >= pNPC1->GetHullMaxs().y ) && - ( pNPC2->GetHullMaxs().z >= pNPC1->GetHullMaxs().z ) ) - { - // 2 bigger than 1 in all axes, skip 1 in 2 test - bTest1At2 = false; - } - - trace_t tr; - CTraceFilterSkipTwoEntities traceFilter( pNPC1, pNPC2, COLLISION_GROUP_NONE ); - - if ( bTest1At2 ) - { - AI_TraceHull( pNPC2->GetAbsOrigin(), pNPC2->GetAbsOrigin(), pNPC1->GetHullMins(), pNPC1->GetHullMaxs(), MASK_SOLID, &traceFilter, &tr ); - if ( tr.startsolid ) - { - if ( bDebug ) - { - NDebugOverlay::Box( pNPC2->GetAbsOrigin(), pNPC1->GetHullMins(), pNPC1->GetHullMaxs(), 255,0,0, true, 1.0 ); - } - return false; - } - } - - if ( bTest2At1 ) - { - AI_TraceHull( pNPC1->GetAbsOrigin(), pNPC1->GetAbsOrigin(), pNPC2->GetHullMins(), pNPC2->GetHullMaxs(), MASK_SOLID, &traceFilter, &tr ); - if ( tr.startsolid ) - { - if ( bDebug ) - { - NDebugOverlay::Box( pNPC1->GetAbsOrigin(), pNPC2->GetHullMins(), pNPC2->GetHullMaxs(), 255,0,0, true, 1.0 ); - } - return false; - } - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::InteractionCouldStart( CAI_BaseNPC *pOtherNPC, ScriptedNPCInteraction_t *pInteraction, Vector &vecOrigin, QAngle &angAngles ) -{ - // Get a matrix that'll convert from my local interaction space to world space - VMatrix matMeToWorld, matLocalToWorld; - QAngle angMyCurrent = GetAbsAngles(); - angMyCurrent[YAW] = m_flInteractionYaw; - matMeToWorld.SetupMatrixOrgAngles( GetAbsOrigin(), angMyCurrent ); - MatrixMultiply( matMeToWorld, pInteraction->matDesiredLocalToWorld, matLocalToWorld ); - - // Get the desired NPC position in worldspace - vecOrigin = matLocalToWorld.GetTranslation(); - MatrixToAngles( matLocalToWorld, angAngles ); - - bool bDebug = ai_debug_dyninteractions.GetBool(); - if ( bDebug ) - { - NDebugOverlay::Axis( vecOrigin, angAngles, 20, true, 0.1 ); - } - - // Determine whether or not the enemy is on the target - float flDistSqr = (vecOrigin - pOtherNPC->GetAbsOrigin()).LengthSqr(); - if ( flDistSqr > pInteraction->flDistSqr ) - { - if ( bDebug ) - { - if ( m_debugOverlays & OVERLAY_NPC_SELECTED_BIT || pOtherNPC->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT ) - { - if ( ai_debug_dyninteractions.GetFloat() == 2 ) - { - Msg(" %s distsqr: %0.2f (%0.2f %0.2f %0.2f), desired: <%0.2f (%0.2f %0.2f %0.2f)\n", GetDebugName(), flDistSqr, - pOtherNPC->GetAbsOrigin().x, pOtherNPC->GetAbsOrigin().y, pOtherNPC->GetAbsOrigin().z, pInteraction->flDistSqr, vecOrigin.x, vecOrigin.y, vecOrigin.z ); - } - } - } - return false; - } - - if ( bDebug ) - { - Msg("DYNINT: (%s) testing interaction \"%s\"\n", GetDebugName(), STRING(pInteraction->iszInteractionName) ); - Msg(" %s is at: %0.2f %0.2f %0.2f\n", GetDebugName(), GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z ); - Msg(" %s distsqr: %0.2f (%0.2f %0.2f %0.2f), desired: (%0.2f %0.2f %0.2f)\n", GetDebugName(), flDistSqr, - pOtherNPC->GetAbsOrigin().x, pOtherNPC->GetAbsOrigin().y, pOtherNPC->GetAbsOrigin().z, vecOrigin.x, vecOrigin.y, vecOrigin.z ); - - if ( pOtherNPC ) - { - float flOtherSpeed = pOtherNPC->GetSequenceGroundSpeed( pOtherNPC->GetSequence() ); - Msg(" %s Speed: %.2f\n", pOtherNPC->GetSequenceName( pOtherNPC->GetSequence() ), flOtherSpeed); - } - } - - // Angle check, if we're supposed to - if ( pInteraction->iFlags & SCNPC_FLAG_TEST_OTHER_ANGLES ) - { - QAngle angEnemyAngles = pOtherNPC->GetAbsAngles(); - bool bMatches = true; - for ( int ang = 0; ang < 3; ang++ ) - { - float flAngDiff = AngleDiff( angEnemyAngles[ang], angAngles[ang] ); - if ( fabs(flAngDiff) > DSS_MAX_ANGLE_DIFF ) - { - bMatches = false; - break; - } - } - if ( !bMatches ) - return false; - - if ( bDebug ) - { - Msg(" %s angle matched: (%0.2f %0.2f %0.2f), desired (%0.2f, %0.2f, %0.2f)\n", GetDebugName(), - anglemod(angEnemyAngles.x), anglemod(angEnemyAngles.y), anglemod(angEnemyAngles.z), anglemod(angAngles.x), anglemod(angAngles.y), anglemod(angAngles.z) ); - } - } - - // TODO: Velocity check, if we're supposed to - if ( pInteraction->iFlags & SCNPC_FLAG_TEST_OTHER_VELOCITY ) - { - - } - - // Valid so far. Now check to make sure there's nothing in the way. - // This isn't a very good method of checking, but it's cheap and rules out the problems we're seeing so far. - // If we start getting interactions that start a fair distance apart, we're going to need to do more work here. - trace_t tr; - AI_TraceLine( EyePosition(), pOtherNPC->EyePosition(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr); - if ( tr.fraction != 1.0 && tr.m_pEnt != pOtherNPC ) - { - if ( bDebug ) - { - Msg( " %s Interaction was blocked.\n", GetDebugName() ); - NDebugOverlay::Line( tr.startpos, tr.endpos, 0,255,0, true, 1.0 ); - NDebugOverlay::Line( pOtherNPC->EyePosition(), tr.endpos, 255,0,0, true, 1.0 ); - } - return false; - } - - if ( bDebug ) - { - NDebugOverlay::Line( tr.startpos, tr.endpos, 0,255,0, true, 1.0 ); - } - - // Do a knee-level trace to find low physics objects - Vector vecMyKnee, vecOtherKnee; - CollisionProp()->NormalizedToWorldSpace( Vector(0,0,0.25f), &vecMyKnee ); - pOtherNPC->CollisionProp()->NormalizedToWorldSpace( Vector(0,0,0.25f), &vecOtherKnee ); - AI_TraceLine( vecMyKnee, vecOtherKnee, MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr); - if ( tr.fraction != 1.0 && tr.m_pEnt != pOtherNPC ) - { - if ( bDebug ) - { - Msg( " %s Interaction was blocked.\n", GetDebugName() ); - NDebugOverlay::Line( tr.startpos, tr.endpos, 0,255,0, true, 1.0 ); - NDebugOverlay::Line( vecOtherKnee, tr.endpos, 255,0,0, true, 1.0 ); - } - return false; - } - - if ( bDebug ) - { - NDebugOverlay::Line( tr.startpos, tr.endpos, 0,255,0, true, 1.0 ); - } - - // Finally, make sure the NPC can actually fit at the interaction position - // This solves problems with NPCs who are a few units or so above the - // interaction point, and would sink into the ground when playing the anim. - CTraceFilterSkipTwoEntities traceFilter( pOtherNPC, this, COLLISION_GROUP_NONE ); - AI_TraceHull( vecOrigin, vecOrigin, pOtherNPC->GetHullMins(), pOtherNPC->GetHullMaxs(), MASK_SOLID, &traceFilter, &tr ); - if ( tr.startsolid ) - { - if ( bDebug ) - { - NDebugOverlay::Box( vecOrigin, pOtherNPC->GetHullMins(), pOtherNPC->GetHullMaxs(), 255,0,0, true, 1.0 ); - } - return false; - } - - // If the NPCs are swapping places during this interaction, make sure they can fit at each - // others' origins before allowing the interaction. - if ( !CanNPCsTradePlaces( this, pOtherNPC, bDebug ) ) - { - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if this NPC cannot die because it's in an interaction -// and the flag has been set by the animation. -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::HasInteractionCantDie( void ) -{ - return ( m_bCannotDieDuringInteraction && IsRunningDynamicInteraction() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAI_BaseNPC::InputForceInteractionWithNPC( inputdata_t &inputdata ) -{ - // Get the interaction name & target - char parseString[255]; - Q_strncpy(parseString, inputdata.value.String(), sizeof(parseString)); - - // First, the target's name - char *pszParam = strtok(parseString," "); - if ( !pszParam || !pszParam[0] ) - { - Warning("%s(%s) received ForceInteractionWithNPC input with bad parameters: %s\nFormat should be: ForceInteractionWithNPC \n", GetClassname(), GetDebugName(), inputdata.value.String() ); - return; - } - // Find the target - CBaseEntity *pTarget = FindNamedEntity( pszParam ); - if ( !pTarget ) - { - Warning("%s(%s) received ForceInteractionWithNPC input, but couldn't find entity named: %s\n", GetClassname(), GetDebugName(), pszParam ); - return; - } - CAI_BaseNPC *pNPC = pTarget->MyNPCPointer(); - if ( !pNPC || !pNPC->GetModelPtr() ) - { - Warning("%s(%s) received ForceInteractionWithNPC input, but entity named %s cannot run dynamic interactions.\n", GetClassname(), GetDebugName(), pszParam ); - return; - } - - // Second, the interaction name - pszParam = strtok(NULL," "); - if ( !pszParam || !pszParam[0] ) - { - Warning("%s(%s) received ForceInteractionWithNPC input with bad parameters: %s\nFormat should be: ForceInteractionWithNPC \n", GetClassname(), GetDebugName(), inputdata.value.String() ); - return; - } - - // Find the interaction from the name, and ensure it's one that the target NPC can play - int iInteraction = -1; - for ( int i = 0; i < m_ScriptedInteractions.Count(); i++ ) - { - if ( Q_strncmp( pszParam, STRING(m_ScriptedInteractions[i].iszInteractionName), strlen(pszParam) ) ) - continue; - - // Use sequence? or activity? - if ( m_ScriptedInteractions[i].sPhases[SNPCINT_SEQUENCE].iActivity != ACT_INVALID ) - { - if ( !pNPC->HaveSequenceForActivity( (Activity)m_ScriptedInteractions[i].sPhases[SNPCINT_SEQUENCE].iActivity ) ) - { - // Other NPC may have all the matching sequences, but just without the activity specified. - // Lets find a single sequence for us, and ensure they have a matching one. - int iMySeq = SelectWeightedSequence( (Activity)m_ScriptedInteractions[i].sPhases[SNPCINT_SEQUENCE].iActivity ); - if ( pNPC->LookupSequence( GetSequenceName(iMySeq) ) == -1 ) - continue; - } - } - else - { - if ( pNPC->LookupSequence( STRING(m_ScriptedInteractions[i].sPhases[SNPCINT_SEQUENCE].iszSequence) ) == -1 ) - continue; - } - - iInteraction = i; - break; - } - - if ( iInteraction == -1 ) - { - Warning("%s(%s) received ForceInteractionWithNPC input, but couldn't find an interaction named %s that entity named %s could run.\n", GetClassname(), GetDebugName(), pszParam, pNPC->GetDebugName() ); - return; - } - - // Found both pieces of data, lets dance. - StartForcedInteraction( pNPC, iInteraction ); - pNPC->StartForcedInteraction( this, NPCINT_NONE ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::StartForcedInteraction( CAI_BaseNPC *pNPC, int iInteraction ) -{ - m_hForcedInteractionPartner = pNPC; - ClearSchedule( "Starting a forced interaction" ); - - m_flForcedInteractionTimeout = gpGlobals->curtime + 8.0f; - m_iInteractionPlaying = iInteraction; - m_iInteractionState = NPCINT_MOVING_TO_MARK; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::CleanupForcedInteraction( void ) -{ - m_hForcedInteractionPartner = NULL; - m_iInteractionPlaying = NPCINT_NONE; - m_iInteractionState = NPCINT_NOT_RUNNING; - m_flForcedInteractionTimeout = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: Calculate a position to move to so that I can interact with my -// target NPC. -// -// FIXME: THIS ONLY WORKS FOR INTERACTIONS THAT REQUIRE THE TARGET -// NPC TO BE SOME DISTANCE DIRECTLY IN FRONT OF ME. -//----------------------------------------------------------------------------- -void CAI_BaseNPC::CalculateForcedInteractionPosition( void ) -{ - if ( m_iInteractionPlaying == NPCINT_NONE ) - return; - - ScriptedNPCInteraction_t *pInteraction = GetRunningDynamicInteraction(); - - // Pretend I was facing the target, and extrapolate from that the position I should be at - Vector vecToTarget = m_hForcedInteractionPartner->GetAbsOrigin() - GetAbsOrigin(); - VectorNormalize( vecToTarget ); - QAngle angToTarget; - VectorAngles( vecToTarget, angToTarget ); - - // Get the desired position in worldspace, relative to the target - VMatrix matMeToWorld, matLocalToWorld; - matMeToWorld.SetupMatrixOrgAngles( GetAbsOrigin(), angToTarget ); - MatrixMultiply( matMeToWorld, pInteraction->matDesiredLocalToWorld, matLocalToWorld ); - - Vector vecOrigin = GetAbsOrigin() - matLocalToWorld.GetTranslation(); - m_vecForcedWorldPosition = m_hForcedInteractionPartner->GetAbsOrigin() + vecOrigin; - - //NDebugOverlay::Axis( m_vecForcedWorldPosition, angToTarget, 20, true, 3.0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -//----------------------------------------------------------------------------- -void CAI_BaseNPC::PlayerHasIlluminatedNPC( CBasePlayer *pPlayer, float flDot ) -{ -#ifdef HL2_DLL - if ( IsActiveDynamicInteraction() ) - { - ScriptedNPCInteraction_t *pInteraction = GetRunningDynamicInteraction(); - if ( pInteraction->iLoopBreakTriggerMethod & SNPCINT_LOOPBREAK_ON_FLASHLIGHT_ILLUM ) - { - // Only do this in alyx darkness mode - if ( HL2GameRules()->IsAlyxInDarknessMode() ) - { - // Can only break when we're in the action anim - if ( m_hCine->IsPlayingAction() ) - { - m_hCine->StopActionLoop( true ); - } - } - } - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::ModifyOrAppendCriteria( AI_CriteriaSet& set ) -{ - BaseClass::ModifyOrAppendCriteria( set ); - - // Append time since seen player - if ( m_flLastSawPlayerTime ) - { - set.AppendCriteria( "timesinceseenplayer", UTIL_VarArgs( "%f", gpGlobals->curtime - m_flLastSawPlayerTime ) ); - } - else - { - set.AppendCriteria( "timesinceseenplayer", "-1" ); - } - - // Append distance to my enemy - if ( GetEnemy() ) - { - set.AppendCriteria( "distancetoenemy", UTIL_VarArgs( "%f", EnemyDistance(GetEnemy()) ) ); - } - else - { - set.AppendCriteria( "distancetoenemy", "-1" ); - } -} - -//----------------------------------------------------------------------------- -// If I were crouching at my current location, could I shoot this target? -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::CouldShootIfCrouching( CBaseEntity *pTarget ) -{ - bool bWasStanding = !IsCrouching(); - Crouch(); - - Vector vecTarget; - if (GetActiveWeapon()) - { - vecTarget = pTarget->BodyTarget( GetActiveWeapon()->GetLocalOrigin() ); - } - else - { - vecTarget = pTarget->BodyTarget( GetLocalOrigin() ); - } - - bool bResult = WeaponLOSCondition( GetLocalOrigin(), vecTarget, false ); - - if ( bWasStanding ) - { - Stand(); - } - - return bResult; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::IsCrouchedActivity( Activity activity ) -{ - Activity realActivity = TranslateActivity(activity); - - switch ( realActivity ) - { - case ACT_RELOAD_LOW: - case ACT_COVER_LOW: - case ACT_COVER_PISTOL_LOW: - case ACT_COVER_SMG1_LOW: - case ACT_RELOAD_SMG1_LOW: - return true; - default: - break; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Get shoot position of BCC at an arbitrary position -//----------------------------------------------------------------------------- -Vector CAI_BaseNPC::Weapon_ShootPosition( void ) -{ - Vector right; - GetVectors( NULL, &right, NULL ); - - bool bStanding = !IsCrouching(); - if ( bStanding && (CapabilitiesGet() & bits_CAP_DUCK) ) - { - if ( IsCrouchedActivity( GetActivity() ) ) - { - bStanding = false; - } - } - - if ( !bStanding ) - return (GetAbsOrigin() + GetCrouchGunOffset() + right * 8); - - return BaseClass::Weapon_ShootPosition(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::ShouldProbeCollideAgainstEntity( CBaseEntity *pEntity ) -{ - if ( pEntity->GetMoveType() == MOVETYPE_VPHYSICS ) - { - if ( ai_test_moveprobe_ignoresmall.GetBool() && IsNavigationUrgent() ) - { - IPhysicsObject *pPhysics = pEntity->VPhysicsGetObject(); - - if ( pPhysics->IsMoveable() && pPhysics->GetMass() < 40.0 ) - return false; - } - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::Crouch( void ) -{ - m_bIsCrouching = true; - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::IsCrouching( void ) -{ - return ( (CapabilitiesGet() & bits_CAP_DUCK) && m_bIsCrouching ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::Stand( void ) -{ - if ( m_bForceCrouch ) - return false; - - m_bIsCrouching = false; - DesireStand(); - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPC::DesireCrouch( void ) -{ - m_bCrouchDesired = true; -} - -bool CAI_BaseNPC::IsInChoreo() const -{ - return m_bInChoreo; -} diff --git a/game/server/ai_basenpc.h b/game/server/ai_basenpc.h deleted file mode 100644 index f0beb4fd4..000000000 --- a/game/server/ai_basenpc.h +++ /dev/null @@ -1,3125 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Base NPC character with AI -// -//=============================================================================// - -#ifndef AI_BASENPC_H -#define AI_BASENPC_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "simtimer.h" -#include "basecombatcharacter.h" -#include "ai_debug.h" -#include "ai_default.h" -#include "ai_schedule.h" -#include "ai_condition.h" -#include "ai_component.h" -#include "ai_task.h" -#include "ai_movetypes.h" -#include "ai_navtype.h" -#include "ai_namespaces.h" -#include "ai_npcstate.h" -#include "ai_hull.h" -#include "ai_utils.h" -#include "ai_moveshoot.h" -#include "entityoutput.h" -#include "utlvector.h" -#include "activitylist.h" -#include "bitstring.h" -#include "ai_basenpc.h" -#include "ai_navgoaltype.h" //GoalType_t enum -#include "eventlist.h" -#include "soundent.h" -#include "ai_navigator.h" -#include "tier1/functors.h" - - -#define PLAYER_SQUADNAME "player_squad" - -class CAI_Schedule; -class CAI_Network; -class CAI_Route; -class CAI_Hint; -class CAI_Node; -class CAI_Navigator; -class CAI_Pathfinder; -class CAI_Senses; -class CAI_Enemies; -class CAI_Squad; -class CAI_Expresser; -class CAI_BehaviorBase; -class CAI_GoalEntity; -class CAI_Motor; -class CAI_MoveProbe; -class CAI_LocalNavigator; -class CAI_TacticalServices; -class CVarBitVec; -class CAI_ScriptedSequence; -class CSceneEntity; -class CBaseGrenade; -class CBaseDoor; -class CBasePropDoor; -struct AI_Waypoint_t; -class AI_Response; -class CBaseFilter; - -typedef CBitVec CAI_ScheduleBits; - -// Used to control optimizations mostly dealing with pathfinding for NPCs -extern ConVar ai_strong_optimizations; - -extern bool AIStrongOpt( void ); - -// AI_MONITOR_FOR_OSCILLATION defaults to OFF. If you build with this ON, you can flag -// NPC's and monitor them to detect oscillations in their schedule (circular logic and conditions bugs) -// DO NOT SHIP WITH THIS ON! -#undef AI_MONITOR_FOR_OSCILLATION - -//============================================================================= -// -// Constants & enumerations -// -//============================================================================= -#define TURRET_CLOSE_RANGE 200 -#define TURRET_MEDIUM_RANGE 500 - -#define COMMAND_GOAL_TOLERANCE 48 // 48 inches. -#define TIME_CARE_ABOUT_DAMAGE 3.0 - -#define ITEM_PICKUP_TOLERANCE 48.0f - -// Max's of the box used to search for a weapon to pick up. 45x45x~8 ft. -#define WEAPON_SEARCH_DELTA Vector( 540, 540, 100 ) - -enum Interruptability_t -{ - GENERAL_INTERRUPTABILITY, - DAMAGEORDEATH_INTERRUPTABILITY, - DEATH_INTERRUPTABILITY -}; - -//------------------------------------- -// Memory -//------------------------------------- - -#define MEMORY_CLEAR 0 -#define bits_MEMORY_PROVOKED ( 1 << 0 )// right now only used for houndeyes. -#define bits_MEMORY_INCOVER ( 1 << 1 )// npc knows it is in a covered position. -#define bits_MEMORY_SUSPICIOUS ( 1 << 2 )// Ally is suspicious of the player, and will move to provoked more easily -#define bits_MEMORY_TASK_EXPENSIVE ( 1 << 3 )// NPC has completed a task which is considered costly, so don't do another task this frame -//#define bits_MEMORY_ ( 1 << 4 ) -#define bits_MEMORY_PATH_FAILED ( 1 << 5 )// Failed to find a path -#define bits_MEMORY_FLINCHED ( 1 << 6 )// Has already flinched -//#define bits_MEMORY_ ( 1 << 7 ) -#define bits_MEMORY_TOURGUIDE ( 1 << 8 )// I have been acting as a tourguide. -//#define bits_MEMORY_ ( 1 << 9 )// -#define bits_MEMORY_LOCKED_HINT ( 1 << 10 )// -//#define bits_MEMORY_ ( 1 << 12 ) - -#define bits_MEMORY_TURNING ( 1 << 13 )// Turning, don't interrupt me. -#define bits_MEMORY_TURNHACK ( 1 << 14 ) - -#define bits_MEMORY_HAD_ENEMY ( 1 << 15 )// Had an enemy -#define bits_MEMORY_HAD_PLAYER ( 1 << 16 )// Had player -#define bits_MEMORY_HAD_LOS ( 1 << 17 )// Had LOS to enemy - -#define bits_MEMORY_MOVED_FROM_SPAWN ( 1 << 18 )// Has moved since spawning. - -#define bits_MEMORY_CUSTOM4 ( 1 << 28 ) // NPC-specific memory -#define bits_MEMORY_CUSTOM3 ( 1 << 29 ) // NPC-specific memory -#define bits_MEMORY_CUSTOM2 ( 1 << 30 ) // NPC-specific memory -#define bits_MEMORY_CUSTOM1 ( 1 << 31 ) // NPC-specific memory - -//------------------------------------- -// Spawn flags -//------------------------------------- -#define SF_NPC_WAIT_TILL_SEEN ( 1 << 0 ) // spawnflag that makes npcs wait until player can see them before attacking. -#define SF_NPC_GAG ( 1 << 1 ) // no idle noises from this npc -#define SF_NPC_FALL_TO_GROUND ( 1 << 2 ) // used my NPC_Maker -#define SF_NPC_DROP_HEALTHKIT ( 1 << 3 ) // Drop a healthkit upon death -#define SF_NPC_START_EFFICIENT ( 1 << 4 ) // Set into efficiency mode from spawn -// ( 1 << 5 ) -// ( 1 << 6 ) -#define SF_NPC_WAIT_FOR_SCRIPT ( 1 << 7 ) // spawnflag that makes npcs wait to check for attacking until the script is done or they've been attacked -#define SF_NPC_LONG_RANGE ( 1 << 8 ) // makes npcs look far and relaxes weapon range limit -#define SF_NPC_FADE_CORPSE ( 1 << 9 ) // Fade out corpse after death -#define SF_NPC_ALWAYSTHINK ( 1 << 10 ) // Simulate even when player isn't in PVS. -#define SF_NPC_TEMPLATE ( 1 << 11 ) // This NPC will be used as a template by an npc_maker -- do not spawn. -#define SF_NPC_ALTCOLLISION ( 1 << 12 ) -#define SF_NPC_NO_WEAPON_DROP ( 1 << 13 ) // This NPC will not actually drop a weapon that can be picked up -#define SF_NPC_NO_PLAYER_PUSHAWAY ( 1 << 14 ) -// ( 1 << 15 ) -// !! Flags above ( 1 << 15 ) are reserved for NPC sub-classes - -//------------------------------------- -// -// Return codes from CanPlaySequence. -// -//------------------------------------- - -enum CanPlaySequence_t -{ - CANNOT_PLAY = 0, // Can't play for any number of reasons. - CAN_PLAY_NOW, // Can play the script immediately. - CAN_PLAY_ENQUEUED, // Can play the script after I finish playing my current script. -}; - -//------------------------------------- -// Weapon holstering -//------------------------------------- -enum DesiredWeaponState_t -{ - DESIREDWEAPONSTATE_IGNORE = 0, - DESIREDWEAPONSTATE_HOLSTERED, - DESIREDWEAPONSTATE_HOLSTERED_DESTROYED, // Put the weapon away, then destroy it. - DESIREDWEAPONSTATE_UNHOLSTERED, - DESIREDWEAPONSTATE_CHANGING, - DESIREDWEAPONSTATE_CHANGING_DESTROY, // Destroy the weapon when this change is complete. -}; - -//------------------------------------- -// -// Efficiency modes -// -//------------------------------------- - -enum AI_Efficiency_t -{ - // Run at full tilt - AIE_NORMAL, - - // Run decision process less often - AIE_EFFICIENT, - - // Run decision process even less often, ignore other NPCs - AIE_VERY_EFFICIENT, - - // Run decision process even less often, ignore other NPCs - AIE_SUPER_EFFICIENT, - - // Don't run at all - AIE_DORMANT, -}; - -enum AI_MoveEfficiency_t -{ - AIME_NORMAL, - AIME_EFFICIENT, -}; - -//------------------------------------- -// -// Sleep state -// -//------------------------------------- - -enum AI_SleepState_t -{ - AISS_AWAKE, - AISS_WAITING_FOR_THREAT, - AISS_WAITING_FOR_PVS, - AISS_WAITING_FOR_INPUT, - AISS_AUTO_PVS, - AISS_AUTO_PVS_AFTER_PVS, // Same as AUTO_PVS, except doesn't activate until/unless the NPC is IN the player's PVS. -}; - -#define AI_SLEEP_FLAGS_NONE 0x00000000 -#define AI_SLEEP_FLAG_AUTO_PVS 0x00000001 -#define AI_SLEEP_FLAG_AUTO_PVS_AFTER_PVS 0x00000002 - - -//------------------------------------- -// -// Debug bits -// -//------------------------------------- - -enum DebugBaseNPCBits_e -{ - bits_debugDisableAI = 0x00000001, // disable AI - bits_debugStepAI = 0x00000002, // step AI - -}; - -//------------------------------------- -// -// Base Sentence index for behaviors -// -//------------------------------------- -enum SentenceIndex_t -{ - SENTENCE_BASE_BEHAVIOR_INDEX = 1000, -}; - -#ifdef AI_MONITOR_FOR_OSCILLATION -struct AIScheduleChoice_t -{ - float m_flTimeSelected; - CAI_Schedule *m_pScheduleSelected; -}; -#endif//AI_MONITOR_FOR_OSCILLATION - -#define MARK_TASK_EXPENSIVE() \ - if ( GetOuter() ) \ - { \ - GetOuter()->Remember( bits_MEMORY_TASK_EXPENSIVE ); \ - } - -//============================================================================= -// -// Types used by CAI_BaseNPC -// -//============================================================================= - -struct AIScheduleState_t -{ - int iCurTask; - TaskStatus_e fTaskStatus; - float timeStarted; - float timeCurTaskStarted; - AI_TaskFailureCode_t taskFailureCode; - int iTaskInterrupt; - bool bTaskRanAutomovement; - bool bTaskUpdatedYaw; - bool bScheduleWasInterrupted; - - DECLARE_SIMPLE_DATADESC(); -}; - -// ----------------------------------------- -// An entity that this NPC can't reach -// ----------------------------------------- - -struct UnreachableEnt_t -{ - EHANDLE hUnreachableEnt; // Entity that's unreachable - float fExpireTime; // Time to forget this information - Vector vLocationWhenUnreachable; - - DECLARE_SIMPLE_DATADESC(); -}; - -//============================================================================= -// SCRIPTED NPC INTERACTIONS -//============================================================================= -// ----------------------------------------- -// Scripted NPC interaction flags -// ----------------------------------------- -#define SCNPC_FLAG_TEST_OTHER_ANGLES ( 1 << 1 ) -#define SCNPC_FLAG_TEST_OTHER_VELOCITY ( 1 << 2 ) -#define SCNPC_FLAG_LOOP_IN_ACTION ( 1 << 3 ) -#define SCNPC_FLAG_NEEDS_WEAPON_ME ( 1 << 4 ) -#define SCNPC_FLAG_NEEDS_WEAPON_THEM ( 1 << 5 ) -#define SCNPC_FLAG_DONT_TELEPORT_AT_END_ME ( 1 << 6 ) -#define SCNPC_FLAG_DONT_TELEPORT_AT_END_THEM ( 1 << 7 ) - -// ----------------------------------------- -// Scripted NPC interaction trigger methods -// ----------------------------------------- -enum -{ - SNPCINT_CODE = 0, - SNPCINT_AUTOMATIC_IN_COMBAT = 1, -}; - -// ----------------------------------------- -// Scripted NPC interaction loop breaking trigger methods -// ----------------------------------------- -#define SNPCINT_LOOPBREAK_ON_DAMAGE ( 1 << 1 ) -#define SNPCINT_LOOPBREAK_ON_FLASHLIGHT_ILLUM ( 1 << 2 ) - -// ----------------------------------------- -// Scripted NPC interaction anim phases -// ----------------------------------------- -enum -{ - SNPCINT_ENTRY = 0, - SNPCINT_SEQUENCE, - SNPCINT_EXIT, - - SNPCINT_NUM_PHASES -}; - -struct ScriptedNPCInteraction_Phases_t -{ - string_t iszSequence; - int iActivity; - - DECLARE_SIMPLE_DATADESC(); -}; - -// Allowable delta from the desired dynamic scripted sequence point -#define DSS_MAX_DIST 6 -#define DSS_MAX_ANGLE_DIFF 4 - -// Interaction Logic States -enum -{ - NPCINT_NOT_RUNNING = 0, - NPCINT_RUNNING_ACTIVE, // I'm in an interaction that I initiated - NPCINT_RUNNING_PARTNER, // I'm in an interaction that was initiated by the other NPC - NPCINT_MOVING_TO_MARK, // I'm moving to a position to do an interaction -}; - -#define NPCINT_NONE -1 - -#define MAXTACLAT_IGNORE -1 - -// ----------------------------------------- -// A scripted interaction between NPCs -// ----------------------------------------- -struct ScriptedNPCInteraction_t -{ - ScriptedNPCInteraction_t() - { - iszInteractionName = NULL_STRING; - iFlags = 0; - iTriggerMethod = SNPCINT_CODE; - iLoopBreakTriggerMethod = 0; - vecRelativeOrigin = vec3_origin; - bValidOnCurrentEnemy = false; - flDelay = 5.0; - flDistSqr = (DSS_MAX_DIST * DSS_MAX_DIST); - flNextAttemptTime = 0; - iszMyWeapon = NULL_STRING; - iszTheirWeapon = NULL_STRING; - - for ( int i = 0; i < SNPCINT_NUM_PHASES; i++) - { - sPhases[i].iszSequence = NULL_STRING; - sPhases[i].iActivity = ACT_INVALID; - } - } - - // Fill out these when passing to AddScriptedNPCInteraction - string_t iszInteractionName; - int iFlags; - int iTriggerMethod; - int iLoopBreakTriggerMethod; - Vector vecRelativeOrigin; // (forward, right, up) - QAngle angRelativeAngles; - Vector vecRelativeVelocity; // Desired relative velocity of the other NPC - float flDelay; // Delay before interaction can be used again - float flDistSqr; // Max distance sqr from the relative origin the NPC is allowed to be to trigger - string_t iszMyWeapon; // Classname of the weapon I'm holding, if any - string_t iszTheirWeapon; // Classname of the weapon my interaction partner is holding, if any - ScriptedNPCInteraction_Phases_t sPhases[SNPCINT_NUM_PHASES]; - - // These will be filled out for you in AddScriptedNPCInteraction - VMatrix matDesiredLocalToWorld; // Desired relative position / angles of the other NPC - bool bValidOnCurrentEnemy; - - float flNextAttemptTime; - - DECLARE_SIMPLE_DATADESC(); -}; - -//============================================================================= -// -// Utility functions -// -//============================================================================= - -Vector VecCheckToss ( CBaseEntity *pEdict, Vector vecSpot1, Vector vecSpot2, float flHeightMaxRatio, float flGravityAdj, bool bRandomize, Vector *vecMins = NULL, Vector *vecMaxs = NULL ); -Vector VecCheckToss ( CBaseEntity *pEntity, ITraceFilter *pFilter, Vector vecSpot1, Vector vecSpot2, float flHeightMaxRatio, float flGravityAdj, bool bRandomize, Vector *vecMins = NULL, Vector *vecMaxs = NULL ); -Vector VecCheckThrow( CBaseEntity *pEdict, const Vector &vecSpot1, Vector vecSpot2, float flSpeed, float flGravityAdj = 1.0f, Vector *vecMins = NULL, Vector *vecMaxs = NULL ); - -extern Vector g_vecAttackDir; - -bool FBoxVisible ( CBaseEntity *pLooker, CBaseEntity *pTarget ); -bool FBoxVisible ( CBaseEntity *pLooker, CBaseEntity *pTarget, Vector &vecTargetOrigin, float flSize = 0.0 ); - -// FIXME: move to utils? -float DeltaV( float v0, float v1, float d ); -float ChangeDistance( float flInterval, float flGoalDistance, float flGoalVelocity, float flCurVelocity, float flIdealVelocity, float flAccelRate, float &flNewDistance, float &flNewVelocity ); - -//============================================================================= -// -// class CAI_Manager -// -// Central location for components of the AI to operate across all AIs without -// iterating over the global list of entities. -// -//============================================================================= - -class CAI_Manager -{ -public: - CAI_Manager(); - - CAI_BaseNPC ** AccessAIs(); - int NumAIs(); - - void AddAI( CAI_BaseNPC *pAI ); - void RemoveAI( CAI_BaseNPC *pAI ); - - bool FindAI( CAI_BaseNPC *pAI ) { return ( m_AIs.Find( pAI ) != m_AIs.InvalidIndex() ); } - -private: - enum - { - MAX_AIS = 256 - }; - - typedef CUtlVector CAIArray; - - CAIArray m_AIs; - -}; - -//------------------------------------- - -extern CAI_Manager g_AI_Manager; - -//============================================================================= -// -// class CAI_BaseNPC -// -//============================================================================= - -class CAI_BaseNPC : public CBaseCombatCharacter, - public CAI_DefMovementSink -{ - DECLARE_CLASS( CAI_BaseNPC, CBaseCombatCharacter ); - -public: - //----------------------------------------------------- - // - // Initialization, cleanup, serialization, identity - // - - CAI_BaseNPC(); - ~CAI_BaseNPC(); - - //--------------------------------- - - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - virtual int Save( ISave &save ); - virtual int Restore( IRestore &restore ); - virtual void OnRestore(); - void SaveConditions( ISave &save, const CAI_ScheduleBits &conditions ); - void RestoreConditions( IRestore &restore, CAI_ScheduleBits *pConditions ); - - bool ShouldSavePhysics() { return false; } - virtual unsigned int PhysicsSolidMaskForEntity( void ) const; - - virtual bool KeyValue( const char *szKeyName, const char *szValue ); - - //--------------------------------- - - virtual void PostConstructor( const char *szClassname ); - virtual void Activate( void ); - virtual void Precache( void ); // derived calls at start of Spawn() - virtual bool CreateVPhysics(); - virtual void NPCInit( void ); // derived calls after Spawn() - void NPCInitThink( void ); - virtual void PostNPCInit() {};// called after NPC_InitThink - virtual void StartNPC( void ); - virtual bool IsTemplate( void ); - - virtual void CleanupOnDeath( CBaseEntity *pCulprit = NULL, bool bFireDeathOutput = true ); - virtual void UpdateOnRemove( void ); - - virtual int UpdateTransmitState(); - - //--------------------------------- - // Component creation factories - // - - // The master call, override if you introduce new component types. Call base first - virtual bool CreateComponents(); - - // Components defined by the base AI class - virtual CAI_Senses * CreateSenses(); - virtual CAI_MoveProbe * CreateMoveProbe(); - virtual CAI_Motor * CreateMotor(); - virtual CAI_LocalNavigator *CreateLocalNavigator(); - virtual CAI_Navigator * CreateNavigator(); - virtual CAI_Pathfinder *CreatePathfinder(); - virtual CAI_TacticalServices *CreateTacticalServices(); - - //--------------------------------- - - virtual bool IsNPC( void ) const { return true; } - - //--------------------------------- - - void TestPlayerPushing( CBaseEntity *pPlayer ); - void CascadePlayerPush( const Vector &push, const Vector &pushOrigin ); - void NotifyPushMove(); - -public: - //----------------------------------------------------- - // - // AI processing - thinking, schedule selection and task running - // - //----------------------------------------------------- - void CallNPCThink( void ); - - // Thinking, including core thinking, movement, animation - virtual void NPCThink( void ); - - // Core thinking (schedules & tasks) - virtual void RunAI( void );// core ai function! - - // Called to gather up all relevant conditons - virtual void GatherConditions( void ); - - // Called immediately prior to schedule processing - virtual void PrescheduleThink( void ); - - // Called immediately after schedule processing - virtual void PostscheduleThink( void ) { return; }; - - // Notification that the current schedule, if any, is ending and a new one is being selected - virtual void OnScheduleChange( void ); - - // Notification that a new schedule is about to run its first task - virtual void OnStartSchedule( int scheduleType ) {}; - - // This function implements a decision tree for the NPC. It is responsible for choosing the next behavior (schedule) - // based on the current conditions and state. - virtual int SelectSchedule( void ); - virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ); - - // After the schedule has been selected, it will be processed by this function so child NPC classes can - // remap base schedules into child-specific behaviors - virtual int TranslateSchedule( int scheduleType ); - - virtual void StartTask( const Task_t *pTask ); - virtual void RunTask( const Task_t *pTask ); - - void ClearTransientConditions(); - - virtual void HandleAnimEvent( animevent_t *pEvent ); - - virtual bool IsInterruptable(); - virtual void OnStartScene( void ) {} // Called when an NPC begins a cine scene (useful for clean-up) - virtual bool ShouldPlayerAvoid( void ); - virtual void SetPlayerAvoidState( void ); - virtual void PlayerPenetratingVPhysics( void ); - - virtual bool ShouldAlwaysThink(); - void ForceGatherConditions() { m_bForceConditionsGather = true; SetEfficiency( AIE_NORMAL ); } // Force an NPC out of PVS to call GatherConditions on next think - - virtual float LineOfSightDist( const Vector &vecDir = vec3_invalid, float zEye = FLT_MAX ); - - virtual void MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ); - virtual const char *GetTracerType( void ); - virtual void DoImpactEffect( trace_t &tr, int nDamageType ); - - enum - { - NEXT_SCHEDULE = LAST_SHARED_SCHEDULE, - NEXT_TASK = LAST_SHARED_TASK, - NEXT_CONDITION = LAST_SHARED_CONDITION, - }; - -protected: - // Used by derived classes to chain a task to a task that might not be the - // one they are currently handling: - void ChainStartTask( int task, float taskData = 0 ) { Task_t tempTask = { task, taskData }; StartTask( (const Task_t *)&tempTask ); } - void ChainRunTask( int task, float taskData = 0 ) { Task_t tempTask = { task, taskData }; RunTask( (const Task_t *) &tempTask ); } - - void StartTaskOverlay(); - void RunTaskOverlay(); - void EndTaskOverlay(); - - virtual void PostRunStopMoving(); - - bool CheckPVSCondition(); - -private: - bool CanThinkRebalance(); - void RebalanceThinks(); - - bool PreNPCThink(); - void PostNPCThink(); - - bool PreThink( void ); - void PerformSensing(); - void CheckOnGround( void ); - void MaintainSchedule( void ); - void RunAnimation( void ); - void PostRun( void ); - void PerformMovement(); - void PostMovement(); - - virtual int StartTask ( Task_t *pTask ) { DevMsg( "Called wrong StartTask()\n" ); StartTask( (const Task_t *)pTask ); return 0; } // to ensure correct signature in derived classes - virtual int RunTask ( Task_t *pTask ) { DevMsg( "Called wrong RunTask()\n" ); RunTask( (const Task_t *)pTask ); return 0; } // to ensure correct signature in derived classes - -public: - //----------------------------------------------------- - // - // Schedules & tasks - // - //----------------------------------------------------- - - void SetSchedule( CAI_Schedule *pNewSchedule ); - bool SetSchedule( int localScheduleID ); - - void SetDefaultFailSchedule( int failSchedule ) { m_failSchedule = failSchedule; } - - void ClearSchedule( const char *szReason ); - - CAI_Schedule * GetCurSchedule() { return m_pSchedule; } - bool IsCurSchedule( int schedId, bool fIdeal = true ); - virtual CAI_Schedule *GetSchedule(int localScheduleID); - virtual int GetLocalScheduleId( int globalScheduleID ) { return AI_IdIsLocal( globalScheduleID ) ? globalScheduleID : GetClassScheduleIdSpace()->ScheduleGlobalToLocal( globalScheduleID ); } - virtual int GetGlobalScheduleId( int localScheduleID ) { return AI_IdIsGlobal( localScheduleID ) ? localScheduleID : GetClassScheduleIdSpace()->ScheduleLocalToGlobal( localScheduleID ); } - - float GetTimeScheduleStarted() const { return m_ScheduleState.timeStarted; } - - //--------------------------------- - - const Task_t* GetTask( void ); - int TaskIsRunning( void ); - - virtual void TaskFail( AI_TaskFailureCode_t ); - void TaskFail( const char *pszGeneralFailText ) { TaskFail( MakeFailCode( pszGeneralFailText ) ); } - void TaskComplete( bool fIgnoreSetFailedCondition = false ); - - void TaskInterrupt() { m_ScheduleState.iTaskInterrupt++; } - void ClearTaskInterrupt() { m_ScheduleState.iTaskInterrupt = 0; } - int GetTaskInterrupt() const { return m_ScheduleState.iTaskInterrupt; } - - void TaskMovementComplete( void ); - inline int TaskIsComplete( void ) { return (GetTaskStatus() == TASKSTATUS_COMPLETE); } - - virtual const char *TaskName(int taskID); - - float GetTimeTaskStarted() const { return m_ScheduleState.timeCurTaskStarted; } - virtual int GetLocalTaskId( int globalTaskId) { return GetClassScheduleIdSpace()->TaskGlobalToLocal( globalTaskId ); } - - virtual const char *GetSchedulingErrorName() { return "CAI_BaseNPC"; } - -protected: - static bool LoadSchedules(void); - virtual bool LoadedSchedules(void); - virtual void BuildScheduleTestBits( void ); - - //--------------------------------- - - // This is the main call to select/translate a schedule - virtual CAI_Schedule *GetNewSchedule( void ); - virtual CAI_Schedule *GetFailSchedule( void ); - - //--------------------------------- - - virtual bool CanFlinch( void ); - virtual void CheckFlinches( void ); - virtual void PlayFlinchGesture( void ); - int SelectFlinchSchedule( void ); - - virtual bool IsAllowedToDodge( void ); - - bool IsInChoreo() const; - -private: - // This function maps the type through TranslateSchedule() and then retrieves the pointer - // to the actual CAI_Schedule from the database of schedules available to this class. - CAI_Schedule * GetScheduleOfType( int scheduleType ); - - bool FHaveSchedule( void ); - bool FScheduleDone ( void ); - CAI_Schedule * ScheduleInList( const char *pName, CAI_Schedule **pList, int listCount ); - - int GetScheduleCurTaskIndex() const { return m_ScheduleState.iCurTask; } - inline int IncScheduleCurTaskIndex(); - inline void ResetScheduleCurTaskIndex(); - void NextScheduledTask ( void ); - bool IsScheduleValid ( void ); - bool ShouldSelectIdealState( void ); - - // Selecting the ideal state - NPC_STATE SelectIdleIdealState(); - NPC_STATE SelectAlertIdealState(); - NPC_STATE SelectScriptIdealState(); - - // Various schedule selections based on NPC_STATE - int SelectIdleSchedule(); - int SelectAlertSchedule(); - int SelectCombatSchedule(); - virtual int SelectDeadSchedule(); - int SelectScriptSchedule(); - int SelectInteractionSchedule(); - - void OnStartTask( void ) { SetTaskStatus( TASKSTATUS_RUN_MOVE_AND_TASK ); } - void SetTaskStatus( TaskStatus_e status ) { m_ScheduleState.fTaskStatus = status; } - TaskStatus_e GetTaskStatus() const { return m_ScheduleState.fTaskStatus; } - - void DiscardScheduleState(); - - //--------------------------------- - - CAI_Schedule * m_pSchedule; - int m_IdealSchedule; - AIScheduleState_t m_ScheduleState; - int m_failSchedule; // Schedule type to choose if current schedule fails - bool m_bDoPostRestoreRefindPath; - - bool m_bUsingStandardThinkTime; - float m_flLastRealThinkTime; - int m_iFrameBlocked; - bool m_bInChoreo; - - static int gm_iNextThinkRebalanceTick; - static float gm_flTimeLastSpawn; - static int gm_nSpawnedThisFrame; - -protected: // pose parameters - int m_poseAim_Pitch; - int m_poseAim_Yaw; - int m_poseMove_Yaw; - virtual void PopulatePoseParameters( void ); - -public: - inline bool HasPoseMoveYaw() { return ( m_poseMove_Yaw >= 0 ); } - - // Return the stored pose parameter for "move_yaw" - inline int LookupPoseMoveYaw() { return m_poseMove_Yaw; } - - - //----------------------------------------------------- - // - // Hooks for CAI_Behaviors, *if* derived class supports them - // - //----------------------------------------------------- - template - bool GetBehavior( BEHAVIOR_TYPE **ppBehavior ) - { - CAI_BehaviorBase **ppBehaviors = AccessBehaviors(); - - *ppBehavior = NULL; - for ( int i = 0; i < NumBehaviors(); i++ ) - { - *ppBehavior = dynamic_cast(ppBehaviors[i]); - if ( *ppBehavior ) - return true; - } - return false; - } - - virtual CAI_BehaviorBase *GetRunningBehavior() { return NULL; } - - virtual bool ShouldAcceptGoal( CAI_BehaviorBase *pBehavior, CAI_GoalEntity *pGoal ) { return true; } - virtual void OnClearGoal( CAI_BehaviorBase *pBehavior, CAI_GoalEntity *pGoal ) {} - - // Notification that the status behavior ability to select schedules has changed. - // Return "true" to signal a schedule interrupt is desired - virtual bool OnBehaviorChangeStatus( CAI_BehaviorBase *pBehavior, bool fCanFinishSchedule ) { return false; } - -private: - virtual CAI_BehaviorBase ** AccessBehaviors() { return NULL; } - virtual int NumBehaviors() { return 0; } - -public: - //----------------------------------------------------- - // - // Conditions - // - //----------------------------------------------------- - - virtual const char* ConditionName(int conditionID); - - virtual void RemoveIgnoredConditions ( void ); - void SetCondition( int iCondition /*, bool state = true*/ ); - bool HasCondition( int iCondition ); - bool HasCondition( int iCondition, bool bUseIgnoreConditions ); - bool HasInterruptCondition( int iCondition ); - bool HasConditionsToInterruptSchedule( int nLocalScheduleID ); - - void ClearCondition( int iCondition ); - void ClearConditions( int *pConditions, int nConditions ); - void SetIgnoreConditions( int *pConditions, int nConditions ); - void ClearIgnoreConditions( int *pConditions, int nConditions ); - bool ConditionInterruptsCurSchedule( int iCondition ); - bool ConditionInterruptsSchedule( int schedule, int iCondition ); - - void SetCustomInterruptCondition( int nCondition ); - bool IsCustomInterruptConditionSet( int nCondition ); - void ClearCustomInterruptCondition( int nCondition ); - void ClearCustomInterruptConditions( void ); - - bool ConditionsGathered() const { return m_bConditionsGathered; } - const CAI_ScheduleBits &AccessConditionBits() const { return m_Conditions; } - CAI_ScheduleBits & AccessConditionBits() { return m_Conditions; } - - bool DidChooseEnemy() const { return !m_bSkippedChooseEnemy; } - -private: - CAI_ScheduleBits m_Conditions; - CAI_ScheduleBits m_CustomInterruptConditions; //Bit string assembled by the schedule running, then - //modified by leaf classes to suit their needs - CAI_ScheduleBits m_ConditionsPreIgnore; - CAI_ScheduleBits m_InverseIgnoreConditions; - - bool m_bForceConditionsGather; - bool m_bConditionsGathered; - bool m_bSkippedChooseEnemy; - -public: - //----------------------------------------------------- - // - // NPC State - // - //----------------------------------------------------- - inline void SetIdealState( NPC_STATE eIdealState ); - inline NPC_STATE GetIdealState(); - virtual NPC_STATE SelectIdealState( void ); - - void SetState( NPC_STATE State ); - virtual bool ShouldGoToIdleState( void ) { return ( false ); } - virtual void OnStateChange( NPC_STATE OldState, NPC_STATE NewState ) {/*Base class doesn't care*/}; - - NPC_STATE GetState( void ) { return m_NPCState; } - - AI_Efficiency_t GetEfficiency() const { return m_Efficiency; } - void SetEfficiency( AI_Efficiency_t efficiency ) { m_Efficiency = efficiency; } - AI_MoveEfficiency_t GetMoveEfficiency() const { return m_MoveEfficiency; } - void SetMoveEfficiency( AI_MoveEfficiency_t efficiency ) { m_MoveEfficiency = efficiency; } - virtual void UpdateEfficiency( bool bInPVS ); - void ForceDecisionThink() { m_flNextDecisionTime = 0; SetEfficiency( AIE_NORMAL ); } - - bool IsFlaggedEfficient() const { return HasSpawnFlags( SF_NPC_START_EFFICIENT ); } - - AI_SleepState_t GetSleepState() const { return m_SleepState; } - void SetSleepState( AI_SleepState_t sleepState ) { m_SleepState = sleepState; } - void AddSleepFlags( int flags ) { m_SleepFlags |= flags; } - void RemoveSleepFlags( int flags ) { m_SleepFlags &= ~flags; } - bool HasSleepFlags( int flags ) { return (m_SleepFlags & flags) == flags; } - - void UpdateSleepState( bool bInPVS ); - virtual void Wake( bool bFireOutput = true ); - void Sleep(); - bool WokeThisTick() const; - - //--------------------------------- - - NPC_STATE m_NPCState; // npc's current state - float m_flLastStateChangeTime; - -private: - NPC_STATE m_IdealNPCState; // npc should change to this state - AI_Efficiency_t m_Efficiency; - AI_MoveEfficiency_t m_MoveEfficiency; - float m_flNextDecisionTime; - - AI_SleepState_t m_SleepState; - int m_SleepFlags; - float m_flWakeRadius; - bool m_bWakeSquad; - int m_nWakeTick; - -public: - //----------------------------------------------------- - // - // Activities - // - //----------------------------------------------------- - - Activity TranslateActivity( Activity idealActivity, Activity *pIdealWeaponActivity = NULL ); - Activity NPC_TranslateActivity( Activity eNewActivity ); - Activity GetActivity( void ) { return m_Activity; } - virtual void SetActivity( Activity NewActivity ); - Activity GetIdealActivity( void ) { return m_IdealActivity; } - void SetIdealActivity( Activity NewActivity ); - void ResetIdealActivity( Activity newIdealActivity ); - void SetSequenceByName( const char *szSequence ); - void SetSequenceById( int iSequence ); - Activity GetScriptCustomMoveActivity( void ); - int GetScriptCustomMoveSequence( void ); - Activity GetStoppedActivity( void ); - inline bool HaveSequenceForActivity( Activity activity ); - inline bool IsActivityStarted(void); - virtual bool IsActivityFinished( void ); - virtual bool IsActivityMovementPhased( Activity activity ); - virtual void OnChangeActivity( Activity eNewActivity ); - void MaintainActivity(void); - void ResetActivity(void) { m_Activity = ACT_RESET; } - - void SetActivityAndSequence(Activity NewActivity, int iSequence, Activity translatedActivity, Activity weaponActivity); - -private: - - void AdvanceToIdealActivity(void); - void ResolveActivityToSequence(Activity NewActivity, int &iSequence, Activity &translatedActivity, Activity &weaponActivity); - - Activity m_Activity; // Current animation state - Activity m_translatedActivity; // Current actual translated animation - - Activity m_IdealActivity; // Desired animation state - int m_nIdealSequence; // Desired animation sequence - Activity m_IdealTranslatedActivity; // Desired actual translated animation state - Activity m_IdealWeaponActivity; // Desired weapon animation state - - CNetworkVar(int, m_iDeathPose ); - CNetworkVar(int, m_iDeathFrame ); - -public: - //----------------------------------------------------- - // - // Senses - // - //----------------------------------------------------- - - CAI_Senses * GetSenses() { return m_pSenses; } - const CAI_Senses * GetSenses() const { return m_pSenses; } - - void SetDistLook( float flDistLook ); - - virtual bool QueryHearSound( CSound *pSound ); - virtual bool QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC = false ); - - virtual void OnLooked( int iDistance ); - virtual void OnListened(); - - virtual void OnSeeEntity( CBaseEntity *pEntity ) {} - - // If true, AI will try to see this entity regardless of distance. - virtual bool ShouldNotDistanceCull() { return false; } - - virtual int GetSoundInterests( void ); - virtual int GetSoundPriority( CSound *pSound ); - - CSound * GetLoudestSoundOfType( int iType ); - virtual CSound * GetBestSound( int validTypes = ALL_SOUNDS ); - virtual CSound * GetBestScent( void ); - virtual float HearingSensitivity( void ) { return 1.0; } - virtual bool ShouldIgnoreSound( CSound * ) { return false; } - bool SoundIsVisible( CSound *pSound ); - -protected: - virtual void ClearSenseConditions( void ); - -private: - void LockBestSound(); - void UnlockBestSound(); - - CAI_Senses * m_pSenses; - CSound * m_pLockedBestSound; - -public: - //----------------------------------------------------- - // - // Enemy and target - // - //----------------------------------------------------- - - Vector GetSmoothedVelocity( void ); - - CBaseEntity* GetEnemy() { return m_hEnemy.Get(); } - CBaseEntity* GetEnemy() const { return m_hEnemy.Get(); } - float GetTimeEnemyAcquired() { return m_flTimeEnemyAcquired; } - void SetEnemy( CBaseEntity *pEnemy, bool bSetCondNewEnemy = true ); - - const Vector & GetEnemyLKP() const; - float GetEnemyLastTimeSeen() const; - void MarkEnemyAsEluded(); - void ClearEnemyMemory(); - bool EnemyHasEludedMe() const; - - virtual CBaseEntity *BestEnemy(); // returns best enemy in memory list - virtual bool IsValidEnemy( CBaseEntity *pEnemy ); - virtual bool CanBeAnEnemyOf( CBaseEntity *pEnemy ); - - void ForceChooseNewEnemy() { m_EnemiesSerialNumber = -1; } - - bool ChooseEnemy(); - virtual bool ShouldChooseNewEnemy(); - virtual void GatherEnemyConditions( CBaseEntity *pEnemy ); - virtual float EnemyDistTolerance() { return 0; } // Enemy distances within this tolerance of each other are considered equivalent. - - float EnemyDistance( CBaseEntity *pEnemy ); - CBaseCombatCharacter *GetEnemyCombatCharacterPointer(); - void SetEnemyOccluder(CBaseEntity *pBlocker); - CBaseEntity *GetEnemyOccluder(void); - - virtual void StartTargetHandling( CBaseEntity *pTargetEnt ); - - //--------------------------------- - - CBaseEntity* GetTarget() { return m_hTargetEnt.Get(); } - void SetTarget( CBaseEntity *pTarget ); - void CheckTarget( CBaseEntity *pTarget ); - float GetAcceptableTimeSeenEnemy( void ) { return m_flAcceptableTimeSeenEnemy; } - virtual CAI_BaseNPC *CreateCustomTarget( const Vector &vecOrigin, float duration = -1 ); - - void SetDeathPose( const int &iDeathPose ) { m_iDeathPose = iDeathPose; } - void SetDeathPoseFrame( const int &iDeathPoseFrame ) { m_iDeathFrame = iDeathPoseFrame; } - - void SelectDeathPose( const CTakeDamageInfo &info ); - virtual bool ShouldPickADeathPose( void ) { return true; } - - virtual bool AllowedToIgnite( void ) { return false; } - -protected: - virtual float GetGoalRepathTolerance( CBaseEntity *pGoalEnt, GoalType_t type, const Vector &curGoal, const Vector &curTargetPos ); - -private: - void * CheckEnemy( CBaseEntity *pEnemy ) { return NULL; } // OBSOLETE, replaced by GatherEnemyConditions(), left here to make derived code not compile - - // Updates the goal position in case of GOALTYPE_ENEMY - void UpdateEnemyPos(); - - // Updates the goal position in case of GOALTYPE_TARGETENT - void UpdateTargetPos(); - - //--------------------------------- - - EHANDLE m_hEnemy; // the entity that the npc is fighting. - float m_flTimeEnemyAcquired; // The time at which the entity the NPC is fighting became the NPC's enemy. - EHANDLE m_hTargetEnt; // the entity that the npc is trying to reach - - CRandStopwatch m_GiveUpOnDeadEnemyTimer; - CSimpleSimTimer m_FailChooseEnemyTimer; - int m_EnemiesSerialNumber; - - float m_flAcceptableTimeSeenEnemy; - - CSimpleSimTimer m_UpdateEnemyPosTimer; - static CSimpleSimTimer m_AnyUpdateEnemyPosTimer; - -public: - //----------------------------------------------------- - // - // Commander mode stuff. - // - //----------------------------------------------------- - virtual bool IsCommandable() { return false; } - virtual bool IsPlayerAlly( CBasePlayer *pPlayer = NULL ); - virtual bool IsMedic() { return false; } - virtual bool IsCommandMoving() { return false; } - virtual bool ShouldAutoSummon() { return false; } - virtual void SetCommandGoal( const Vector &vecGoal ); - virtual void ClearCommandGoal(); - virtual void OnTargetOrder() {} - virtual void OnMoveOrder() {} - virtual bool IsValidCommandTarget( CBaseEntity *pTarget ) { return false; } - const Vector &GetCommandGoal() const { return m_vecCommandGoal; } - virtual void OnMoveToCommandGoalFailed() {} - string_t GetPlayerSquadName() const { Assert( gm_iszPlayerSquad != NULL_STRING ); return gm_iszPlayerSquad; } - bool IsInPlayerSquad() const; - virtual CAI_BaseNPC *GetSquadCommandRepresentative() { return NULL; } - - virtual bool TargetOrder( CBaseEntity *pTarget, CAI_BaseNPC **Allies, int numAllies ) { OnTargetOrder(); return true; } - virtual void MoveOrder( const Vector &vecDest, CAI_BaseNPC **Allies, int numAllies ) { SetCommandGoal( vecDest ); SetCondition( COND_RECEIVED_ORDERS ); OnMoveOrder(); } - - // Return true if you're willing to be idly talked to by other friends. - virtual bool CanBeUsedAsAFriend( void ); - - -private: - Vector m_vecCommandGoal; - static string_t gm_iszPlayerSquad; - -public: - CAI_MoveMonitor m_CommandMoveMonitor; - - //----------------------------------------------------- - // Dynamic scripted NPC interactions - //----------------------------------------------------- -public: - float GetInteractionYaw( void ) const { return m_flInteractionYaw; } - -protected: - void ParseScriptedNPCInteractions( void ); - void AddScriptedNPCInteraction( ScriptedNPCInteraction_t *pInteraction ); - const char *GetScriptedNPCInteractionSequence( ScriptedNPCInteraction_t *pInteraction, int iPhase ); - void StartRunningInteraction( CAI_BaseNPC *pOtherNPC, bool bActive ); - void StartScriptedNPCInteraction( CAI_BaseNPC *pOtherNPC, ScriptedNPCInteraction_t *pInteraction, Vector vecOtherOrigin, QAngle angOtherAngles ); - void CheckForScriptedNPCInteractions( void ); - void CalculateValidEnemyInteractions( void ); - void CheckForcedNPCInteractions( void ); - bool InteractionCouldStart( CAI_BaseNPC *pOtherNPC, ScriptedNPCInteraction_t *pInteraction, Vector &vecOrigin, QAngle &angAngles ); - virtual bool CanRunAScriptedNPCInteraction( bool bForced = false ); - bool IsRunningDynamicInteraction( void ) { return (m_iInteractionState != NPCINT_NOT_RUNNING && (m_hCine != NULL)); } - bool IsActiveDynamicInteraction( void ) { return (m_iInteractionState == NPCINT_RUNNING_ACTIVE && (m_hCine != NULL)); } - ScriptedNPCInteraction_t *GetRunningDynamicInteraction( void ) { return &(m_ScriptedInteractions[m_iInteractionPlaying]); } - void SetInteractionCantDie( bool bCantDie ) { m_bCannotDieDuringInteraction = bCantDie; } - bool HasInteractionCantDie( void ); - - void InputForceInteractionWithNPC( inputdata_t &inputdata ); - void StartForcedInteraction( CAI_BaseNPC *pNPC, int iInteraction ); - void CleanupForcedInteraction( void ); - void CalculateForcedInteractionPosition( void ); - CAI_BaseNPC *GetInteractionPartner( void ); - -private: - // Forced interactions - CHandle m_hForcedInteractionPartner; - Vector m_vecForcedWorldPosition; - float m_flForcedInteractionTimeout; // Abort the interaction if it hasn't started by this time. - - CHandle m_hInteractionPartner; - EHANDLE m_hLastInteractionTestTarget; - bool m_bCannotDieDuringInteraction; - int m_iInteractionState; - int m_iInteractionPlaying; - CUtlVector m_ScriptedInteractions; - - float m_flInteractionYaw; - - -public: - //----------------------------------------------------- - // - // Sounds - // - //----------------------------------------------------- - virtual CanPlaySequence_t CanPlaySequence( bool fDisregardState, int interruptLevel ); - - virtual bool CanPlaySentence( bool fDisregardState ) { return IsAlive(); } - virtual int PlaySentence( const char *pszSentence, float delay, float volume, soundlevel_t soundlevel, CBaseEntity *pListener = NULL ); - virtual int PlayScriptedSentence( const char *pszSentence, float delay, float volume, soundlevel_t soundlevel, bool bConcurrent, CBaseEntity *pListener ); - - virtual bool FOkToMakeSound( int soundPriority = 0 ); - virtual void JustMadeSound( int soundPriority = 0, float flSoundLength = 0.0f ); - - virtual void DeathSound( const CTakeDamageInfo &info ) { return; }; - virtual void AlertSound( void ) { return; }; - virtual void IdleSound( void ) { return; }; - virtual void PainSound( const CTakeDamageInfo &info ) { return; }; - virtual void FearSound( void ) { return; }; - virtual void LostEnemySound( void ) { return; }; - virtual void FoundEnemySound( void ) { return; }; - virtual void BarnacleDeathSound( void ) { CTakeDamageInfo info; PainSound( info ); } - - virtual void SpeakSentence( int sentenceType ) { return; }; - virtual bool ShouldPlayIdleSound( void ); - - virtual void MakeAIFootstepSound( float volume, float duration = 0.5f ); - - //--------------------------------- - - virtual CAI_Expresser *GetExpresser() { return NULL; } - const CAI_Expresser *GetExpresser() const { return const_cast(this)->GetExpresser(); } - - //--------------------------------- - // NPC Event Response System - virtual bool CanRespondToEvent( const char *ResponseConcept ) { return false; } - virtual bool RespondedTo( const char *ResponseConcept, bool bForce, bool bCancelScene ) { return false; } - - virtual void PlayerHasIlluminatedNPC( CBasePlayer *pPlayer, float flDot ); - - virtual void ModifyOrAppendCriteria( AI_CriteriaSet& set ); - -protected: - float SoundWaitTime() const { return m_flSoundWaitTime; } - -public: - //----------------------------------------------------- - // - // Capabilities report (from CBaseCombatCharacter) - // - //----------------------------------------------------- - virtual int CapabilitiesGet( void ) const; - - // local capabilities access - int CapabilitiesAdd( int capabilities ); - int CapabilitiesRemove( int capabilities ); - void CapabilitiesClear( void ); - -private: - int m_afCapability; // tells us what a npc can/can't do. - -public: - //----------------------------------------------------- - // - // Pathfinding, navigation & movement - // - //----------------------------------------------------- - - CAI_Navigator * GetNavigator() { return m_pNavigator; } - const CAI_Navigator *GetNavigator() const { return m_pNavigator; } - - CAI_LocalNavigator *GetLocalNavigator() { return m_pLocalNavigator; } - const CAI_LocalNavigator *GetLocalNavigator() const { return m_pLocalNavigator; } - - CAI_Pathfinder * GetPathfinder() { return m_pPathfinder; } - const CAI_Pathfinder *GetPathfinder() const { return m_pPathfinder; } - - CAI_MoveProbe * GetMoveProbe() { return m_pMoveProbe; } - const CAI_MoveProbe *GetMoveProbe() const { return m_pMoveProbe; } - - CAI_Motor * GetMotor() { return m_pMotor; } - const CAI_Motor * GetMotor() const { return m_pMotor; } - - //--------------------------------- - - static bool FindSpotForNPCInRadius( Vector *pResult, const Vector &vStartPos, CAI_BaseNPC *pNPC, float radius, bool bOutOfPlayerViewcone = false ); - - //--------------------------------- - - virtual bool IsNavigationUrgent(); - virtual bool ShouldFailNav( bool bMovementFailed ); - virtual bool ShouldBruteForceFailedNav() { return false; } - - // The current navigation (movement) mode (e.g. fly, swim, locomote, etc) - Navigation_t GetNavType() const; - void SetNavType( Navigation_t navType ); - - CBaseEntity * GetNavTargetEntity(void); - - bool IsMoving( void ); - virtual float GetTimeToNavGoal(); - - // NPCs can override this to tweak with how costly particular movements are - virtual bool MovementCost( int moveType, const Vector &vecStart, const Vector &vecEnd, float *pCost ); - - // Turns a directional vector into a yaw value that points down that vector. - float VecToYaw( const Vector &vecDir ); - - // Turning - virtual float CalcIdealYaw( const Vector &vecTarget ); - virtual float MaxYawSpeed( void ); // Get max yaw speed - bool FacingIdeal( void ); - void SetUpdatedYaw() { m_ScheduleState.bTaskUpdatedYaw = true; } - - // Add multiple facing goals while moving/standing still. - virtual void AddFacingTarget( CBaseEntity *pTarget, float flImportance, float flDuration, float flRamp = 0.0 ); - virtual void AddFacingTarget( const Vector &vecPosition, float flImportance, float flDuration, float flRamp = 0.0 ); - virtual void AddFacingTarget( CBaseEntity *pTarget, const Vector &vecPosition, float flImportance, float flDuration, float flRamp = 0.0 ); - virtual float GetFacingDirection( Vector &vecDir ); - - // ------------ - // Methods used by motor to query properties/preferences/move-related state - // ------------ - virtual bool CanStandOn( CBaseEntity *pSurface ) const; - - virtual bool IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos ) const; // Override for specific creature types - bool IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos, float maxUp, float maxDown, float maxDist ) const; - bool ShouldMoveWait(); - virtual float StepHeight() const { return 18.0f; } - float GetStepDownMultiplier() const; - virtual float GetMaxJumpSpeed() const { return 350.0f; } - virtual float GetJumpGravity() const { return 1.0f; } - - //--------------------------------- - - virtual bool OverrideMove( float flInterval ); // Override to take total control of movement (return true if done so) - virtual bool OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval ); - - //--------------------------------- - - virtual bool IsUnusableNode(int iNodeID, CAI_Hint *pHint); // Override for special NPC behavior - virtual bool ValidateNavGoal(); - virtual bool IsCurTaskContinuousMove(); - virtual bool IsValidMoveAwayDest( const Vector &vecDest ) { return true; } - - //--------------------------------- - // - // Notifications from navigator - // - virtual void OnMovementFailed() {}; - virtual void OnMovementComplete() {}; - - //--------------------------------- - - bool FindNearestValidGoalPos( const Vector &vTestPoint, Vector *pResult ); - - void RememberUnreachable( CBaseEntity* pEntity, float duration = -1 ); // Remember that entity is unreachable - virtual bool IsUnreachable( CBaseEntity* pEntity ); // Is entity is unreachable? - - //--------------------------------- - // Inherited from IAI_MotorMovementServices - virtual float CalcYawSpeed( void ); - - virtual bool OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, - float distClear, - AIMoveResult_t *pResult ); - - virtual bool OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal, - float distClear, - AIMoveResult_t *pResult ); - - // Translations of the above into some useful game terms - virtual bool OnObstructingDoor( AILocalMoveGoal_t *pMoveGoal, - CBaseDoor *pDoor, - float distClear, - AIMoveResult_t *pResult ); - - virtual bool OnUpcomingPropDoor( AILocalMoveGoal_t *pMoveGoal, - CBasePropDoor *pDoor, - float distClear, - AIMoveResult_t *pResult ); - - void OpenPropDoorBegin( CBasePropDoor *pDoor ); - void OpenPropDoorNow( CBasePropDoor *pDoor ); - - //--------------------------------- - - void DelayMoveStart( float delay ) { m_flMoveWaitFinished = gpGlobals->curtime + delay; } - - float m_flMoveWaitFinished; - - - // - // Stuff for opening doors. - // - void OnDoorFullyOpen(CBasePropDoor *pDoor); - void OnDoorBlocked(CBasePropDoor *pDoor); - CHandle m_hOpeningDoor; // The CBasePropDoor that we are in the midst of opening for navigation. - -protected: - // BRJ 4/11 - // Semi-obsolete-looking Lars code I moved out of the engine and into here - int FlyMove( const Vector& vecPosition, unsigned int mask ); - int WalkMove( const Vector& vecPosition, unsigned int mask ); - - // Unreachable Entities - CUtlVector m_UnreachableEnts; // Array of unreachable entities - -private: - CAI_Navigator * m_pNavigator; - CAI_LocalNavigator *m_pLocalNavigator; - CAI_Pathfinder * m_pPathfinder; - CAI_MoveProbe * m_pMoveProbe; - CAI_Motor * m_pMotor; - - EHANDLE m_hGoalEnt; // path corner we are heading towards - - float m_flTimeLastMovement; - - - CSimpleSimTimer m_CheckOnGroundTimer; - -public: - //----------------------------------------------------- - // - // Eye position, view offset, head direction, eye direction - // - //----------------------------------------------------- - - void SetDefaultEyeOffset ( void ); - const Vector & GetDefaultEyeOffset( void ) { return m_vDefaultEyeOffset; } - virtual Vector GetNodeViewOffset() { return GetViewOffset(); } - - virtual Vector EyeOffset( Activity nActivity ); - virtual Vector EyePosition( void ); - - //--------------------------------- - - virtual Vector HeadDirection2D( void ); - virtual Vector HeadDirection3D( void ); - virtual Vector EyeDirection2D( void ); - virtual Vector EyeDirection3D( void ); - - virtual CBaseEntity *EyeLookTarget( void ); // Overridden by subclass to force look at an entity - virtual void AddLookTarget( CBaseEntity *pTarget, float flImportance, float flDuration, float flRamp = 0.0 ) { }; - virtual void AddLookTarget( const Vector &vecPosition, float flImportance, float flDuration, float flRamp = 0.0 ) { }; - virtual void SetHeadDirection( const Vector &vTargetPos, float flInterval ); - virtual void MaintainLookTargets( float flInterval ); - virtual bool ValidEyeTarget(const Vector &lookTargetPos); - - virtual Vector FacingPosition( void ) { return EyePosition(); }; // position that other npc's use when facing you - - virtual void MaintainTurnActivity( void ); - - virtual bool FInAimCone( const Vector &vecSpot ); - virtual void AimGun(); - virtual void SetAim( const Vector &aimDir ); - virtual void RelaxAim( void ); - virtual CBaseEntity *GetAlternateMoveShootTarget() { return NULL; } - -protected: - Vector m_vDefaultEyeOffset; - float m_flNextEyeLookTime; // Next time a pick a new place to look - - float m_flEyeIntegRate; // How fast does eye move to target - -private: - Vector m_vEyeLookTarget; // Where I want to be looking - Vector m_vCurEyeTarget; // Direction I'm looking at - EHANDLE m_hEyeLookTarget; // What I want to be looking at - float m_flHeadYaw; // Current head yaw - float m_flHeadPitch; // Current head pitch -protected: - float m_flOriginalYaw; // This is the direction facing when the level designer placed the NPC in the level. - -public: - //----------------------------------------------------- - // Mapmaker Scripting - // - // Set when the NPC is being scripted by a mapmaker, and - // shouldn't be responding to external stimuli that would - // break him out of his "script". NOT a scripted sequence. - //----------------------------------------------------- - inline bool IsInAScript( void ) { return m_bInAScript; } - inline void SetInAScript( bool bScript ) { m_bInAScript = bScript; } - void InputStartScripting( inputdata_t &inputdata ) { m_bInAScript = true; } - void InputStopScripting( inputdata_t &inputdata ) { m_bInAScript = false; } - - void InputGagEnable( inputdata_t &inputdata ) { AddSpawnFlags(SF_NPC_GAG); } - void InputGagDisable( inputdata_t &inputdata ) { RemoveSpawnFlags(SF_NPC_GAG); } - - bool HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt); - - virtual void InputOutsideTransition( inputdata_t &inputdata ); - virtual void InputInsideTransition( inputdata_t &inputdata ); - - void CleanupScriptsOnTeleport( bool bEnrouteAsWell ); - - virtual void SetScriptedScheduleIgnoreConditions( Interruptability_t interrupt ); - -private: - bool m_bInAScript; - -public: - //----------------------------------------------------- - // - // Scripting - // - //----------------------------------------------------- - - // Scripted sequence Info - enum SCRIPTSTATE - { - SCRIPT_PLAYING = 0, // Playing the action animation. - SCRIPT_WAIT, // Waiting on everyone in the script to be ready. Plays the pre idle animation if there is one. - SCRIPT_POST_IDLE, // Playing the post idle animation after playing the action animation. - SCRIPT_CLEANUP, // Cancelling the script / cleaning up. - SCRIPT_WALK_TO_MARK, // Walking to the scripted sequence position. - SCRIPT_RUN_TO_MARK, // Running to the scripted sequence position. - SCRIPT_CUSTOM_MOVE_TO_MARK, // Moving to the scripted sequence position while playing a custom movement animation. - }; - - bool ExitScriptedSequence(); - bool CineCleanup(); - - virtual void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ); - - // forces movement and sets a new schedule - virtual bool ScheduledMoveToGoalEntity( int scheduleType, CBaseEntity *pGoalEntity, Activity movementActivity ); - virtual bool ScheduledFollowPath( int scheduleType, CBaseEntity *pPathStart, Activity movementActivity ); - - static void ForceSelectedGo(CBaseEntity *pPlayer, const Vector &targetPos, const Vector &traceDir, bool bRun); - static void ForceSelectedGoRandom(void); - - bool AutoMovement( CBaseEntity *pTarget = NULL, AIMoveTrace_t *pTraceResult = NULL ); - bool AutoMovement( float flInterval, CBaseEntity *pTarget = NULL, AIMoveTrace_t *pTraceResult = NULL ); - bool TaskRanAutomovement( void ) { return m_ScheduleState.bTaskRanAutomovement; } - - SCRIPTSTATE m_scriptState; // internal cinematic state - CHandle m_hCine; - Activity m_ScriptArrivalActivity; - string_t m_strScriptArrivalSequence; - - //----------------------------------------------------- - // - // Scenes - // - //----------------------------------------------------- - - void AddSceneLock( float flDuration = 0.2f ) { m_flSceneTime = MAX( gpGlobals->curtime + flDuration, m_flSceneTime ); }; - void ClearSceneLock( float flDuration = 0.2f ) { m_flSceneTime = gpGlobals->curtime + flDuration; }; - bool IsInLockedScene( void ) { return m_flSceneTime > gpGlobals->curtime; }; - float m_flSceneTime; - string_t m_iszSceneCustomMoveSeq; - -public: - //----------------------------------------------------- - // - // Memory - // - //----------------------------------------------------- - - inline void Remember( int iMemory ) { m_afMemory |= iMemory; } - inline void Forget( int iMemory ) { m_afMemory &= ~iMemory; } - inline bool HasMemory( int iMemory ) { if ( m_afMemory & iMemory ) return TRUE; return FALSE; } - inline bool HasAllMemories( int iMemory ) { if ( (m_afMemory & iMemory) == iMemory ) return TRUE; return FALSE; } - - virtual CAI_Enemies *GetEnemies( void ); - virtual void RemoveMemory( void ); - - virtual bool UpdateEnemyMemory( CBaseEntity *pEnemy, const Vector &position, CBaseEntity *pInformer = NULL ); - virtual float GetReactionDelay( CBaseEntity *pEnemy ); - - void SetLastAttackTime( float time) { m_flLastAttackTime = time; } - - float GetLastAttackTime() const { return m_flLastAttackTime; } - float GetLastDamageTime() const { return m_flLastDamageTime; } - float GetLastPlayerDamageTime() const { return m_flLastPlayerDamageTime; } - float GetLastEnemyTime() const { return m_flLastEnemyTime; } - - // Set up the shot regulator based on the equipped weapon - virtual void OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ); - - // Weapon holstering - virtual bool CanHolsterWeapon( void ); - virtual int HolsterWeapon( void ); - virtual int UnholsterWeapon( void ); - void InputHolsterWeapon( inputdata_t &inputdata ); - void InputHolsterAndDestroyWeapon( inputdata_t &inputdata ); - void InputUnholsterWeapon( inputdata_t &inputdata ); - bool IsWeaponHolstered( void ); - bool IsWeaponStateChanging( void ); - void SetDesiredWeaponState( DesiredWeaponState_t iState ) { m_iDesiredWeaponState = iState; } - - // NOTE: The Shot Regulator is used to manage the RangeAttack1 weapon. - inline CAI_ShotRegulator* GetShotRegulator() { return &m_ShotRegulator; } - virtual void OnRangeAttack1(); - -protected: - // Shot regulator code - virtual void OnUpdateShotRegulator( ); - -protected: - CAI_Enemies * m_pEnemies; // Holds information about enemies / danger positions / shared between sqaud members - int m_afMemory; - EHANDLE m_hEnemyOccluder; // The entity my enemy is hiding behind. - - float m_flSumDamage; // How much consecutive damage I've received - float m_flLastDamageTime; // Last time I received damage - float m_flLastPlayerDamageTime; // Last time I received damage from the player - float m_flLastSawPlayerTime; // Last time I saw the player - float m_flLastAttackTime; // Last time that I attacked my current enemy - float m_flLastEnemyTime; - float m_flNextWeaponSearchTime; // next time to search for a better weapon - string_t m_iszPendingWeapon; // THe NPC should create and equip this weapon. - bool m_bIgnoreUnseenEnemies; - -private: - CAI_ShotRegulator m_ShotRegulator; // When should I shoot next? - - DesiredWeaponState_t m_iDesiredWeaponState; - -public: - //----------------------------------------------------- - // - // Squads & tactics - // - //----------------------------------------------------- - - virtual bool InitSquad( void ); - - virtual const char* SquadSlotName(int slotID) { return gm_SquadSlotNamespace.IdToSymbol(slotID); } - bool OccupyStrategySlot( int squadSlotID ); - bool OccupyStrategySlotRange( int slotIDStart, int slotIDEnd ); - bool HasStrategySlot( int squadSlotID ); - bool HasStrategySlotRange( int slotIDStart, int slotIDEnd ); - int GetMyStrategySlot() { return m_iMySquadSlot; } - void VacateStrategySlot( void ); - bool IsStrategySlotRangeOccupied( int slotIDStart, int slotIDEnd ); // Returns true if all in the range are occupied - - CAI_Squad * GetSquad() { return m_pSquad; } - virtual void SetSquad( CAI_Squad *pSquad ); - void AddToSquad( string_t name ); - void RemoveFromSquad(); - void CheckSquad(); - void SetSquadName( string_t name ) { m_SquadName = name; } - bool IsInSquad() const { return m_pSquad != NULL; } - virtual bool IsSilentSquadMember() const { return false; } - - int NumWeaponsInSquad( const char *pszWeaponClassname ); - - string_t GetHintGroup( void ) { return m_strHintGroup; } - void ClearHintGroup( void ) { SetHintGroup( NULL_STRING ); } - void SetHintGroup( string_t name, bool bHintGroupNavLimiting = false ); - bool IsLimitingHintGroups( void ) { return m_bHintGroupNavLimiting; } - - //--------------------------------- - - CAI_TacticalServices *GetTacticalServices() { return m_pTacticalServices; } - const CAI_TacticalServices *GetTacticalServices() const { return m_pTacticalServices; } - - //--------------------------------- - // Cover - - virtual bool FindCoverPos( CBaseEntity *pEntity, Vector *pResult ); - virtual bool FindCoverPosInRadius( CBaseEntity *pEntity, const Vector &goalPos, float coverRadius, Vector *pResult ); - virtual bool FindCoverPos( CSound *pSound, Vector *pResult ); - virtual bool IsValidCover ( const Vector &vecCoverLocation, CAI_Hint const *pHint ); - virtual bool IsValidShootPosition ( const Vector &vecCoverLocation, CAI_Node *pNode, CAI_Hint const *pHint ); - virtual bool TestShootPosition(const Vector &vecShootPos, const Vector &targetPos ) { return WeaponLOSCondition( vecShootPos, targetPos, false ); } - virtual bool IsCoverPosition( const Vector &vecThreat, const Vector &vecPosition ); - virtual float CoverRadius( void ) { return 1024; } // Default cover radius - virtual float GetMaxTacticalLateralMovement( void ) { return MAXTACLAT_IGNORE; } - -protected: - virtual void OnChangeHintGroup( string_t oldGroup, string_t newGroup ) {} - - CAI_Squad * m_pSquad; // The squad that I'm on - string_t m_SquadName; - - int m_iMySquadSlot; // this is the behaviour slot that the npc currently holds in the squad. - -private: - string_t m_strHintGroup; - bool m_bHintGroupNavLimiting; - CAI_TacticalServices *m_pTacticalServices; - -public: - //----------------------------------------------------- - // - // Base schedule & task support; Miscellaneous - // - //----------------------------------------------------- - - void InitRelationshipTable( void ); - void AddRelationship( const char *pszRelationship, CBaseEntity *pActivator ); - - virtual void AddEntityRelationship( CBaseEntity *pEntity, Disposition_t nDisposition, int nPriority ); - virtual void AddClassRelationship( Class_T nClass, Disposition_t nDisposition, int nPriority ); - - void NPCUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - CBaseGrenade* IncomingGrenade(void); - - virtual bool ShouldFadeOnDeath( void ); - - void NPCInitDead( void ); // Call after animation/pose is set up - void CorpseFallThink( void ); - - float ThrowLimit( const Vector &vecStart, const Vector &vecEnd, float fGravity, float fArcSize, const Vector &mins, const Vector &maxs, CBaseEntity *pTarget, Vector *jumpVel, CBaseEntity **pBlocker); - - // these functions will survey conditions and set appropriate conditions bits for attack types. - virtual int RangeAttack1Conditions( float flDot, float flDist ); - virtual int RangeAttack2Conditions( float flDot, float flDist ); - virtual int MeleeAttack1Conditions( float flDot, float flDist ); - virtual int MeleeAttack2Conditions( float flDot, float flDist ); - - virtual float InnateRange1MinRange( void ) { return 0.0f; } - virtual float InnateRange1MaxRange( void ) { return FLT_MAX; } - - virtual bool OnBeginMoveAndShoot( void ) { return true; } - virtual void OnEndMoveAndShoot( void ) {} - - virtual bool UseAttackSquadSlots() { return false; } - - //--------------------------------- - - virtual CBaseEntity *FindNamedEntity( const char *pszName, IEntityFindFilter *pFilter = NULL ); - - //--------------------------------- - // States - //--------------------------------- - - virtual void ClearAttackConditions( void ); - void GatherAttackConditions( CBaseEntity *pTarget, float flDist ); - virtual bool ShouldLookForBetterWeapon(); - bool Weapon_IsBetterAvailable ( void ) ; - virtual Vector Weapon_ShootPosition( void ); - virtual void GiveWeapon( string_t iszWeaponName ); - virtual void OnGivenWeapon( CBaseCombatWeapon *pNewWeapon ) { } - bool IsMovingToPickupWeapon(); - virtual bool WeaponLOSCondition(const Vector &ownerPos, const Vector &targetPos, bool bSetConditions); - virtual bool CurrentWeaponLOSCondition(const Vector &targetPos, bool bSetConditions) { return WeaponLOSCondition( GetAbsOrigin(), targetPos, bSetConditions ); } - virtual bool IsWaitingToRappel( void ) { return false; } - virtual void BeginRappel() {} - - // override to change the chase location of an enemy - // This is where your origin should go when you are chasing pEnemy when his origin is at chasePosition - // by default, leave this alone to make your origin coincide with his. - virtual void TranslateNavGoal( CBaseEntity *pEnemy, Vector &chasePosition); - virtual float GetDefaultNavGoalTolerance() { return (GetHullWidth() * 2.0); } - - virtual bool FCanCheckAttacks ( void ); - virtual void CheckAmmo( void ) {} - - virtual bool FValidateHintType( CAI_Hint *pHint ); - virtual Activity GetHintActivity( short sHintType, Activity HintsActivity ); - virtual float GetHintDelay( short sHintType ); - virtual Activity GetCoverActivity( CAI_Hint* pHint ); - virtual Activity GetReloadActivity( CAI_Hint* pHint ); - - virtual void SetTurnActivity( void ); - bool UpdateTurnGesture( void ); - - // Returns the time when the door will be open - float OpenDoorAndWait( CBaseEntity *pDoor ); - - bool BBoxFlat( void ); - - //--------------------------------- - - virtual void Ignite( float flFlameLifetime, bool bNPCOnly = true, float flSize = 0.0f, bool bCalledByLevelDesigner = false ); - virtual bool PassesDamageFilter( const CTakeDamageInfo &info ); - - //--------------------------------- - - void MakeDamageBloodDecal( int cCount, float flNoise, trace_t *ptr, Vector vecDir ); - virtual float GetHitgroupDamageMultiplier( int iHitGroup, const CTakeDamageInfo &info ); - void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - void DecalTrace( trace_t *pTrace, char const *decalName ); - void ImpactTrace( trace_t *pTrace, int iDamageType, const char *pCustomImpactName ); - virtual bool PlayerInSpread( const Vector &sourcePos, const Vector &targetPos, float flSpread, float maxDistOffCenter, bool ignoreHatedPlayers = true ); - CBaseEntity * PlayerInRange( const Vector &vecLocation, float flDist ); - bool PointInSpread( CBaseCombatCharacter *pCheckEntity, const Vector &sourcePos, const Vector &targetPos, const Vector &testPoint, float flSpread, float maxDistOffCenter ); - bool IsSquadmateInSpread( const Vector &sourcePos, const Vector &targetPos, float flSpread, float maxDistOffCenter ); - - //--------------------------------- - // combat functions - //--------------------------------- - virtual bool InnateWeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions ); - - virtual Activity GetFlinchActivity( bool bHeavyDamage, bool bGesture ); - - virtual bool ShouldGib( const CTakeDamageInfo &info ) { return false; } // Always ragdoll, unless specified by the leaf class - virtual bool Event_Gibbed( const CTakeDamageInfo &info ); - virtual void Event_Killed( const CTakeDamageInfo &info ); - - virtual Vector GetShootEnemyDir( const Vector &shootOrigin, bool bNoisy = true ); -#ifdef HL2_DLL - virtual Vector GetActualShootPosition( const Vector &shootOrigin ); - virtual Vector GetActualShootTrajectory( const Vector &shootOrigin ); - virtual Vector GetAttackSpread( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget = NULL ); - virtual float GetSpreadBias( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget ); -#endif //HL2_DLL - virtual void CollectShotStats( const Vector &vecShootOrigin, const Vector &vecShootDir ); - virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true ); - virtual Vector GetAutoAimCenter() { return BodyTarget(vec3_origin, false); } - virtual void FireBullets( const FireBulletsInfo_t &info ); - - // OLD VERSION! Use the struct version - void FireBullets( int cShots, const Vector &vecSrc, const Vector &vecDirShooting, - const Vector &vecSpread, float flDistance, int iAmmoType, int iTracerFreq = 4, - int firingEntID = -1, int attachmentID = -1, int iDamage = 0, - CBaseEntity *pAttacker = NULL, bool bFirstShotAccurate = false ); - - virtual bool ShouldMoveAndShoot( void ); - - //--------------------------------- - // Damage - //--------------------------------- - virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - virtual int OnTakeDamage_Dying( const CTakeDamageInfo &info ); - virtual int OnTakeDamage_Dead( const CTakeDamageInfo &info ); - - virtual void NotifyFriendsOfDamage( CBaseEntity *pAttackerEntity ); - virtual void OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker ); - - virtual bool IsLightDamage( const CTakeDamageInfo &info ); - virtual bool IsHeavyDamage( const CTakeDamageInfo &info ); - - void DoRadiusDamage( const CTakeDamageInfo &info, int iClassIgnore, CBaseEntity *pEntityIgnore ); - void DoRadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrc, int iClassIgnore, CBaseEntity *pEntityIgnore ); - - //--------------------------------- - - virtual void PickupWeapon( CBaseCombatWeapon *pWeapon ); - virtual void PickupItem( CBaseEntity *pItem ) { }; - CBaseEntity* DropItem( const char *pszItemName, Vector vecPos, QAngle vecAng );// drop an item. - - - //--------------------------------- - // Inputs - //--------------------------------- - void InputSetRelationship( inputdata_t &inputdata ); - void InputSetEnemyFilter( inputdata_t &inputdata ); - void InputSetHealth( inputdata_t &inputdata ); - void InputBeginRappel( inputdata_t &inputdata ); - void InputSetSquad( inputdata_t &inputdata ); - void InputWake( inputdata_t &inputdata ); - void InputForgetEntity( inputdata_t &inputdata ); - void InputIgnoreDangerSounds( inputdata_t &inputdata ); - void InputUpdateEnemyMemory( inputdata_t &inputdata ); - - //--------------------------------- - - virtual void NotifyDeadFriend( CBaseEntity *pFriend ) { return; } - - //--------------------------------- - // Utility methods - static Vector CalcThrowVelocity(const Vector &startPos, const Vector &endPos, float fGravity, float fArcSize); - - //--------------------------------- - - float SetWait( float minWait, float maxWait = 0.0 ); - void ClearWait(); - float GetWaitFinishTime() { return m_flWaitFinished; } - bool IsWaitFinished(); - bool IsWaitSet(); - - CBaseEntity* GetGoalEnt() { return m_hGoalEnt; } - void SetGoalEnt( CBaseEntity *pGoalEnt ) { m_hGoalEnt.Set( pGoalEnt ); } - - CAI_Hint *GetHintNode() { return m_pHintNode; } - const CAI_Hint *GetHintNode() const { return m_pHintNode; } - void SetHintNode( CAI_Hint *pHintNode ); - void ClearHintNode( float reuseDelay = 0.0 ); - - float m_flWaitFinished; // if we're told to wait, this is the time that the wait will be over. - - float m_flNextFlinchTime; // Time at which we'll flinch fully again (as opposed to just doing gesture flinches) - float m_flNextDodgeTime; // Time at which I can dodge again. Used so that the behavior doesn't happen over and over. - - CAI_MoveAndShootOverlay m_MoveAndShootOverlay; - - Vector m_vecLastPosition; // npc sometimes wants to return to where it started after an operation. - Vector m_vSavePosition; // position stored by code that called this schedules - Vector m_vInterruptSavePosition; // position stored by a task that was interrupted - -private: - CHandle m_pHintNode; // this is the hint that the npc is moving towards or performing active idle on. - -public: - int m_cAmmoLoaded; // how much ammo is in the weapon (used to trigger reload anim sequences) - float m_flDistTooFar; // if enemy farther away than this, bits_COND_ENEMY_TOOFAR set in GatherEnemyConditions - string_t m_spawnEquipment; - - bool m_fNoDamageDecal; - - EHANDLE m_hStoredPathTarget; // For TASK_SET_GOAL - Vector m_vecStoredPathGoal; // - GoalType_t m_nStoredPathType; // - int m_fStoredPathFlags; // - - CHandle m_hEnemyFilter; - string_t m_iszEnemyFilterName; - - bool m_bDidDeathCleanup; - - - IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_lifeState ); - - //--------------------------------- - // Outputs - //--------------------------------- - COutputEvent m_OnDamaged; - COutputEvent m_OnDeath; - COutputEvent m_OnHalfHealth; - COutputEHANDLE m_OnFoundEnemy; - COutputEvent m_OnLostEnemyLOS; - COutputEvent m_OnLostEnemy; - COutputEHANDLE m_OnFoundPlayer; - COutputEvent m_OnLostPlayerLOS; - COutputEvent m_OnLostPlayer; - COutputEvent m_OnHearWorld; - COutputEvent m_OnHearPlayer; - COutputEvent m_OnHearCombat; - COutputEvent m_OnDamagedByPlayer; - COutputEvent m_OnDamagedByPlayerSquad; - COutputEvent m_OnDenyCommanderUse; - COutputEvent m_OnRappelTouchdown; - COutputEvent m_OnSleep; - COutputEvent m_OnWake; - COutputEvent m_OnForcedInteractionStarted; - COutputEvent m_OnForcedInteractionAborted; - COutputEvent m_OnForcedInteractionFinished; - -public: - // use this to shrink the bbox temporarily - void SetHullSizeNormal( bool force = false ); - bool SetHullSizeSmall( bool force = false ); - - bool IsUsingSmallHull() const { return m_fIsUsingSmallHull; } - - const Vector & GetHullMins() const { return NAI_Hull::Mins(GetHullType()); } - const Vector & GetHullMaxs() const { return NAI_Hull::Maxs(GetHullType()); } - float GetHullWidth() const { return NAI_Hull::Width(GetHullType()); } - float GetHullHeight() const { return NAI_Hull::Height(GetHullType()); } - - void SetupVPhysicsHull(); - virtual void StartTouch( CBaseEntity *pOther ); - void CheckPhysicsContacts(); - -private: - void TryRestoreHull( void ); - bool m_fIsUsingSmallHull; - bool m_bCheckContacts; - -private: - // Task implementation helpers - void StartTurn( float flDeltaYaw ); - bool FindCoverFromEnemy( bool bNodesOnly = false, float flMinDistance = 0, float flMaxDistance = FLT_MAX ); - bool FindCoverFromBestSound( Vector *pCoverPos ); - void StartScriptMoveToTargetTask( int task ); - - void RunDieTask(); - void RunAttackTask( int task ); - -protected: - virtual float CalcReasonableFacing( bool bIgnoreOriginalFacing = false ); - virtual bool IsValidReasonableFacing( const Vector &vecSightDir, float sightDist ) { return true; } - virtual float GetReasonableFacingDist( void ); - -public: - inline int UsableNPCObjectCaps( int baseCaps ) - { - if ( IsAlive() ) - baseCaps |= FCAP_IMPULSE_USE; - return baseCaps; - } - - virtual int ObjectCaps() { return (BaseClass::ObjectCaps() | FCAP_NOTIFY_ON_TRANSITION); } - - //----------------------------------------------------- - // - // Core mapped data structures - // - // String Registries for default AI Shared by all CBaseNPCs - // These are used only during initialization and in debug - //----------------------------------------------------- - - static void InitSchedulingTables(); - - static CAI_GlobalScheduleNamespace *GetSchedulingSymbols() { return &gm_SchedulingSymbols; } - static CAI_ClassScheduleIdSpace &AccessClassScheduleIdSpaceDirect() { return gm_ClassScheduleIdSpace; } - virtual CAI_ClassScheduleIdSpace * GetClassScheduleIdSpace() { return &gm_ClassScheduleIdSpace; } - - static int GetScheduleID (const char* schedName); - static int GetActivityID (const char* actName); - static int GetConditionID (const char* condName); - static int GetTaskID (const char* taskName); - static int GetSquadSlotID (const char* slotName); - virtual const char* GetSquadSlotDebugName( int iSquadSlot ); - static const char* GetActivityName (int actID); - - static void AddActivityToSR(const char *actName, int conID); - - static void AddEventToSR(const char *eventName, int conID); - static const char* GetEventName (int actID); - static int GetEventID (const char* actName); - -public: - //----------------------------------------------------- - // Crouch handling - //----------------------------------------------------- - bool CrouchIsDesired( void ) const; - virtual bool IsCrouching( void ); - inline void ForceCrouch( void ); - inline void ClearForceCrouch( void ); - -protected: - virtual bool Crouch( void ); - virtual bool Stand( void ); - virtual void DesireCrouch( void ); - inline void DesireStand( void ); - bool CouldShootIfCrouching( CBaseEntity *pTarget ); - virtual bool IsCrouchedActivity( Activity activity ); - -protected: - // Override these in your derived NPC class - virtual Vector GetCrouchEyeOffset( void ) { return Vector(0,0,40); } - virtual Vector GetCrouchGunOffset( void ) { return Vector(0,0,36); } - -private: - bool m_bCrouchDesired; - bool m_bForceCrouch; - bool m_bIsCrouching; - //----------------------------------------------------- - - //----------------------------------------------------- - // ai_post_frame_navigation - //----------------------------------------------------- - -private: - bool m_bDeferredNavigation; // This NPCs has a navigation query that's being deferred until later in the frame - -public: - void SetNavigationDeferred( bool bState ) { m_bDeferredNavigation = bState; } - bool IsNavigationDeferred( void ) { return m_bDeferredNavigation; } - - //----------------------------------------------------- -protected: - static CAI_GlobalNamespace gm_SquadSlotNamespace; - static CAI_LocalIdSpace gm_SquadSlotIdSpace; - -private: - // Checks to see that the nav hull is valid for the NPC - bool IsNavHullValid() const; - - friend class CAI_SystemHook; - friend class CAI_SchedulesManager; - - static bool LoadDefaultSchedules(void); - - static void InitDefaultScheduleSR(void); - static void InitDefaultTaskSR(void); - static void InitDefaultConditionSR(void); - static void InitDefaultActivitySR(void); - static void InitDefaultSquadSlotSR(void); - - static CStringRegistry* m_pActivitySR; - static int m_iNumActivities; - - static CStringRegistry* m_pEventSR; - static int m_iNumEvents; - - static CAI_GlobalScheduleNamespace gm_SchedulingSymbols; - static CAI_ClassScheduleIdSpace gm_ClassScheduleIdSpace; - -public: - //---------------------------------------------------- - // Debugging tools - // - - // ----------------------------- - // Debuging Fields and Methods - // ----------------------------- - const char* m_failText; // Text of why it failed - const char* m_interruptText; // Text of why schedule interrupted - CAI_Schedule* m_failedSchedule; // The schedule that failed last - CAI_Schedule* m_interuptSchedule; // The schedule that was interrupted last - int m_nDebugCurIndex; // Index used for stepping through AI - virtual void ReportAIState( void ); - virtual void ReportOverThinkLimit( float time ); - void DumpTaskTimings(); - void DrawDebugGeometryOverlays(void); - virtual int DrawDebugTextOverlays(void); - void ToggleFreeze(void); - - static void ClearAllSchedules(void); - - static int m_nDebugBits; - - static CAI_BaseNPC* m_pDebugNPC; - static int m_nDebugPauseIndex; // Current step - static inline void SetDebugNPC( CAI_BaseNPC *pNPC ) { m_pDebugNPC = pNPC; } - static inline bool IsDebugNPC( CAI_BaseNPC *pNPC ) { return( pNPC == m_pDebugNPC ); } - - float m_LastShootAccuracy; - int m_TotalShots; - int m_TotalHits; -#ifdef _DEBUG - bool m_bSelected; -#endif - - float m_flSoundWaitTime; // Time when I'm allowed to make another sound - int m_nSoundPriority; - float m_flIgnoreDangerSoundsUntil; - -#ifdef AI_MONITOR_FOR_OSCILLATION - CUtlVector m_ScheduleHistory; -#endif//AI_MONITOR_FOR_OSCILLATION - -private: - - // Break into pieces! - void Break( CBaseEntity *pBreaker ); - void InputBreak( inputdata_t &inputdata ); - - friend void CC_NPC_Go(); - friend void CC_NPC_GoRandom(); - friend void CC_NPC_Freeze( const CCommand &args ); - -public: - - CNetworkVar( bool, m_bPerformAvoidance ); - CNetworkVar( bool, m_bIsMoving ); - CNetworkVar( bool, m_bFadeCorpse ); - CNetworkVar( bool, m_bImportanRagdoll ); - - CNetworkVar( bool, m_bSpeedModActive ); - CNetworkVar( int, m_iSpeedModRadius ); - CNetworkVar( int, m_iSpeedModSpeed ); - CNetworkVar( float, m_flTimePingEffect ); // Display the pinged effect until this time - - void InputActivateSpeedModifier( inputdata_t &inputdata ) { m_bSpeedModActive = true; } - void InputDisableSpeedModifier( inputdata_t &inputdata ) { m_bSpeedModActive = false; } - void InputSetSpeedModifierRadius( inputdata_t &inputdata ); - void InputSetSpeedModifierSpeed( inputdata_t &inputdata ); - - virtual bool ShouldProbeCollideAgainstEntity( CBaseEntity *pEntity ); - - bool m_bPlayerAvoidState; - void GetPlayerAvoidBounds( Vector *pMins, Vector *pMaxs ); - - void StartPingEffect( void ) { m_flTimePingEffect = gpGlobals->curtime + 2.0f; DispatchUpdateTransmitState(); } -}; - - -//----------------------------------------------------------------------------- -// Purpose: Returns whether our ideal activity has started. If not, we are in -// a transition sequence. -//----------------------------------------------------------------------------- -inline bool CAI_BaseNPC::IsActivityStarted(void) -{ - return (GetSequence() == m_nIdealSequence); -} - -//----------------------------------------------------------------------------- -// Bullet firing (legacy)... -//----------------------------------------------------------------------------- -inline void CAI_BaseNPC::FireBullets( int cShots, const Vector &vecSrc, - const Vector &vecDirShooting, const Vector &vecSpread, float flDistance, - int iAmmoType, int iTracerFreq, int firingEntID, int attachmentID, - int iDamage, CBaseEntity *pAttacker, bool bFirstShotAccurate ) -{ - FireBulletsInfo_t info; - info.m_iShots = cShots; - info.m_vecSrc = vecSrc; - info.m_vecDirShooting = vecDirShooting; - info.m_vecSpread = vecSpread; - info.m_flDistance = flDistance; - info.m_iAmmoType = iAmmoType; - info.m_iTracerFreq = iTracerFreq; - info.m_iDamage = iDamage; - info.m_pAttacker = pAttacker; - info.m_nFlags = bFirstShotAccurate ? FIRE_BULLETS_FIRST_SHOT_ACCURATE : 0; - - FireBullets( info ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Sets the ideal state of this NPC. -//----------------------------------------------------------------------------- -inline void CAI_BaseNPC::SetIdealState( NPC_STATE eIdealState ) -{ - if (eIdealState != m_IdealNPCState) - { - /*switch (eIdealState) - { - case NPC_STATE_NONE: - Msg("%s.SetIdealState: NPC_STATE_NONE\n", GetDebugName()); - break; - - case NPC_STATE_IDLE: - Msg("%s.SetIdealState: NPC_STATE_IDLE\n", GetDebugName()); - break; - - case NPC_STATE_ALERT: - Msg("%s.SetIdealState: NPC_STATE_ALERT\n", GetDebugName()); - break; - - case NPC_STATE_COMBAT: - Msg("%s.SetIdealState: NPC_STATE_COMBAT\n", GetDebugName()); - break; - - case NPC_STATE_SCRIPT: - Msg("%s.SetIdealState: NPC_STATE_SCRIPT\n", GetDebugName()); - break; - - case NPC_STATE_PLAYDEAD: - Msg("%s.SetIdealState: NPC_STATE_PLAYDEAD\n", GetDebugName()); - break; - - case NPC_STATE_PRONE: - Msg("%s.SetIdealState: NPC_STATE_PRONE\n", GetDebugName()); - break; - - case NPC_STATE_DEAD: - Msg("%s.SetIdealState: NPC_STATE_DEAD\n", GetDebugName()); - break; - - default: - Msg("%s.SetIdealState: \n", GetDebugName()); - break; - }*/ - - m_IdealNPCState = eIdealState; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns the current ideal state the NPC will try to achieve. -//----------------------------------------------------------------------------- -inline NPC_STATE CAI_BaseNPC::GetIdealState() -{ - return m_IdealNPCState; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline int CAI_BaseNPC::IncScheduleCurTaskIndex() -{ - m_ScheduleState.iTaskInterrupt = 0; - m_ScheduleState.bTaskRanAutomovement = false; - m_ScheduleState.bTaskUpdatedYaw = false; - return ++m_ScheduleState.iCurTask; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CAI_BaseNPC::ResetScheduleCurTaskIndex() -{ - m_ScheduleState.iCurTask = 0; - m_ScheduleState.iTaskInterrupt = 0; - m_ScheduleState.bTaskRanAutomovement = false; - m_ScheduleState.bTaskUpdatedYaw = false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline bool CAI_BaseNPC::CrouchIsDesired( void ) const -{ - return ( (CapabilitiesGet() & bits_CAP_DUCK) && (m_bCrouchDesired | m_bForceCrouch) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline void CAI_BaseNPC::DesireStand( void ) -{ - m_bCrouchDesired = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline void CAI_BaseNPC::ForceCrouch( void ) -{ - m_bForceCrouch = true; - Crouch(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline void CAI_BaseNPC::ClearForceCrouch( void ) -{ - m_bForceCrouch = false; - - if ( IsCrouching() ) - { - Stand(); - } -} - -inline bool CAI_BaseNPC::HaveSequenceForActivity( Activity activity ) -{ -#if STUDIO_SEQUENCE_ACTIVITY_LOOKUPS_ARE_SLOW - return ( (GetModelPtr()) ? (SelectWeightedSequence( activity ) != ACTIVITY_NOT_AVAILABLE) : false ); -#else - return ( (GetModelPtr()) ? GetModelPtr()->HaveSequenceForActivity(activity) : false ); -#endif -} - -typedef CHandle AIHANDLE; - - -// ============================================================================ -// Macros for introducing new schedules in sub-classes -// -// Strings registries and schedules use unique ID's for each item, but -// sub-class enumerations are non-unique, so we translate between the -// enumerations and unique ID's -// ============================================================================ - -#define AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( derivedClass ) \ - IMPLEMENT_CUSTOM_SCHEDULE_PROVIDER(derivedClass ) \ - void derivedClass::InitCustomSchedules( void ) \ - { \ - typedef derivedClass CNpc; \ - const char *pszClassName = #derivedClass; \ - \ - CUtlVector schedulesToLoad; \ - CUtlVector reqiredOthers; \ - CAI_NamespaceInfos scheduleIds; \ - CAI_NamespaceInfos taskIds; \ - CAI_NamespaceInfos conditionIds; - - -//----------------- - -#define AI_BEGIN_CUSTOM_NPC( className, derivedClass ) \ - IMPLEMENT_CUSTOM_AI(className, derivedClass ) \ - void derivedClass::InitCustomSchedules( void ) \ - { \ - typedef derivedClass CNpc; \ - const char *pszClassName = #derivedClass; \ - \ - CUtlVector schedulesToLoad; \ - CUtlVector reqiredOthers; \ - CAI_NamespaceInfos scheduleIds; \ - CAI_NamespaceInfos taskIds; \ - CAI_NamespaceInfos conditionIds; \ - CAI_NamespaceInfos squadSlotIds; - -//----------------- - -#define EXTERN_SCHEDULE( id ) \ - scheduleIds.PushBack( #id, id ); \ - extern const char * g_psz##id; \ - schedulesToLoad.AddToTail( (char *)g_psz##id ); - -//----------------- - -#define DEFINE_SCHEDULE( id, text ) \ - scheduleIds.PushBack( #id, id ); \ - const char * g_psz##id = \ - "\n Schedule" \ - "\n " #id \ - text \ - "\n"; \ - schedulesToLoad.AddToTail( (char *)g_psz##id ); - -//----------------- - -#define DECLARE_CONDITION( id ) \ - conditionIds.PushBack( #id, id ); - -//----------------- - -#define DECLARE_TASK( id ) \ - taskIds.PushBack( #id, id ); - -//----------------- - -#define DECLARE_ACTIVITY( id ) \ - ADD_CUSTOM_ACTIVITY( CNpc, id ); - -//----------------- - -#define DECLARE_SQUADSLOT( id ) \ - squadSlotIds.PushBack( #id, id ); - -//----------------- - -#define DECLARE_INTERACTION( interaction ) \ - ADD_CUSTOM_INTERACTION( interaction ); - -//----------------- - -#define DECLARE_ANIMEVENT( id ) \ - ADD_CUSTOM_ANIMEVENT( CNpc, id ); - -//----------------- - -#define DECLARE_USES_SCHEDULE_PROVIDER( classname ) reqiredOthers.AddToTail( ScheduleLoadHelper(classname) ); - -//----------------- - -// IDs are stored and then added in order due to constraints in the namespace implementation -#define AI_END_CUSTOM_SCHEDULE_PROVIDER() \ - \ - int i; \ - \ - CNpc::AccessClassScheduleIdSpaceDirect().Init( pszClassName, BaseClass::GetSchedulingSymbols(), &BaseClass::AccessClassScheduleIdSpaceDirect() ); \ - \ - scheduleIds.Sort(); \ - taskIds.Sort(); \ - conditionIds.Sort(); \ - \ - for ( i = 0; i < scheduleIds.Count(); i++ ) \ - { \ - ADD_CUSTOM_SCHEDULE_NAMED( CNpc, scheduleIds[i].pszName, scheduleIds[i].localId ); \ - } \ - \ - for ( i = 0; i < taskIds.Count(); i++ ) \ - { \ - ADD_CUSTOM_TASK_NAMED( CNpc, taskIds[i].pszName, taskIds[i].localId ); \ - } \ - \ - for ( i = 0; i < conditionIds.Count(); i++ ) \ - { \ - if ( ValidateConditionLimits( conditionIds[i].pszName ) ) \ - { \ - ADD_CUSTOM_CONDITION_NAMED( CNpc, conditionIds[i].pszName, conditionIds[i].localId ); \ - } \ - } \ - \ - for ( i = 0; i < reqiredOthers.Count(); i++ ) \ - { \ - (*reqiredOthers[i])(); \ - } \ - \ - for ( i = 0; i < schedulesToLoad.Count(); i++ ) \ - { \ - if ( CNpc::gm_SchedLoadStatus.fValid ) \ - { \ - CNpc::gm_SchedLoadStatus.fValid = g_AI_SchedulesManager.LoadSchedulesFromBuffer( pszClassName, schedulesToLoad[i], &AccessClassScheduleIdSpaceDirect() ); \ - } \ - else \ - break; \ - } \ - } - -inline bool ValidateConditionLimits( const char *pszNewCondition ) -{ - int nGlobalConditions = CAI_BaseNPC::GetSchedulingSymbols()->NumConditions(); - if ( nGlobalConditions >= MAX_CONDITIONS ) - { - AssertMsg2( 0, "Exceeded max number of conditions (%d), ignoring condition %s\n", MAX_CONDITIONS, pszNewCondition ); - DevWarning( "Exceeded max number of conditions (%d), ignoring condition %s\n", MAX_CONDITIONS, pszNewCondition ); - return false; - } - return true; -} - - -//------------------------------------- - -// IDs are stored and then added in order due to constraints in the namespace implementation -#define AI_END_CUSTOM_NPC() \ - \ - int i; \ - \ - CNpc::AccessClassScheduleIdSpaceDirect().Init( pszClassName, BaseClass::GetSchedulingSymbols(), &BaseClass::AccessClassScheduleIdSpaceDirect() ); \ - CNpc::gm_SquadSlotIdSpace.Init( &BaseClass::gm_SquadSlotNamespace, &BaseClass::gm_SquadSlotIdSpace); \ - \ - scheduleIds.Sort(); \ - taskIds.Sort(); \ - conditionIds.Sort(); \ - squadSlotIds.Sort(); \ - \ - for ( i = 0; i < scheduleIds.Count(); i++ ) \ - { \ - ADD_CUSTOM_SCHEDULE_NAMED( CNpc, scheduleIds[i].pszName, scheduleIds[i].localId ); \ - } \ - \ - for ( i = 0; i < taskIds.Count(); i++ ) \ - { \ - ADD_CUSTOM_TASK_NAMED( CNpc, taskIds[i].pszName, taskIds[i].localId ); \ - } \ - \ - for ( i = 0; i < conditionIds.Count(); i++ ) \ - { \ - if ( ValidateConditionLimits( conditionIds[i].pszName ) ) \ - { \ - ADD_CUSTOM_CONDITION_NAMED( CNpc, conditionIds[i].pszName, conditionIds[i].localId ); \ - } \ - } \ - \ - for ( i = 0; i < squadSlotIds.Count(); i++ ) \ - { \ - ADD_CUSTOM_SQUADSLOT_NAMED( CNpc, squadSlotIds[i].pszName, squadSlotIds[i].localId ); \ - } \ - \ - for ( i = 0; i < reqiredOthers.Count(); i++ ) \ - { \ - (*reqiredOthers[i])(); \ - } \ - \ - for ( i = 0; i < schedulesToLoad.Count(); i++ ) \ - { \ - if ( CNpc::gm_SchedLoadStatus.fValid ) \ - { \ - CNpc::gm_SchedLoadStatus.fValid = g_AI_SchedulesManager.LoadSchedulesFromBuffer( pszClassName, schedulesToLoad[i], &AccessClassScheduleIdSpaceDirect() ); \ - } \ - else \ - break; \ - } \ - } - -//------------------------------------- - -struct AI_NamespaceAddInfo_t -{ - AI_NamespaceAddInfo_t( const char *pszName, int localId ) - : pszName( pszName ), - localId( localId ) - { - } - - const char *pszName; - int localId; -}; - -class CAI_NamespaceInfos : public CUtlVector -{ -public: - void PushBack( const char *pszName, int localId ) - { - AddToTail( AI_NamespaceAddInfo_t( pszName, localId ) ); - } - - void Sort() - { - CUtlVector::Sort( Compare ); - } - -private: - static int __cdecl Compare(const AI_NamespaceAddInfo_t *pLeft, const AI_NamespaceAddInfo_t *pRight ) - { - return pLeft->localId - pRight->localId; - } - -}; - -//------------------------------------- - -// Declares the static variables that hold the string registry offset for the new subclass -// as well as the initialization in schedule load functions - -struct AI_SchedLoadStatus_t -{ - bool fValid; - int signature; -}; - -// Load schedules pulled out to support stepping through with debugger -inline bool AI_DoLoadSchedules( bool (*pfnBaseLoad)(), void (*pfnInitCustomSchedules)(), - AI_SchedLoadStatus_t *pLoadStatus ) -{ - (*pfnBaseLoad)(); - - if (pLoadStatus->signature != g_AI_SchedulesManager.GetScheduleLoadSignature()) - { - (*pfnInitCustomSchedules)(); - pLoadStatus->fValid = true; - pLoadStatus->signature = g_AI_SchedulesManager.GetScheduleLoadSignature(); - } - return pLoadStatus->fValid; -} - -//------------------------------------- - -typedef bool (*AIScheduleLoadFunc_t)(); - -// @Note (toml 02-16-03): The following class exists to allow us to establish an anonymous friendship -// in DEFINE_CUSTOM_SCHEDULE_PROVIDER. The particulars of this implementation is almost entirely -// defined by bugs in MSVC 6.0 -class ScheduleLoadHelperImpl -{ -public: - template - static AIScheduleLoadFunc_t AccessScheduleLoadFunc(T *) - { - return (&T::LoadSchedules); - } -}; - -#define ScheduleLoadHelper( type ) (ScheduleLoadHelperImpl::AccessScheduleLoadFunc((type *)0)) - -//------------------------------------- - -#define DEFINE_CUSTOM_SCHEDULE_PROVIDER\ - static AI_SchedLoadStatus_t gm_SchedLoadStatus; \ - static CAI_ClassScheduleIdSpace gm_ClassScheduleIdSpace; \ - static const char * gm_pszErrorClassName;\ - \ - static CAI_ClassScheduleIdSpace & AccessClassScheduleIdSpaceDirect() { return gm_ClassScheduleIdSpace; } \ - virtual CAI_ClassScheduleIdSpace * GetClassScheduleIdSpace() { return &gm_ClassScheduleIdSpace; } \ - virtual const char * GetSchedulingErrorName() { return gm_pszErrorClassName; } \ - \ - static void InitCustomSchedules(void);\ - \ - static bool LoadSchedules(void);\ - virtual bool LoadedSchedules(void); \ - \ - friend class ScheduleLoadHelperImpl; \ - \ - class CScheduleLoader \ - { \ - public: \ - CScheduleLoader(); \ - } m_ScheduleLoader; \ - \ - friend class CScheduleLoader; - -//------------------------------------- - -#define DEFINE_CUSTOM_AI\ - DEFINE_CUSTOM_SCHEDULE_PROVIDER \ - \ - static CAI_LocalIdSpace gm_SquadSlotIdSpace; \ - \ - const char* SquadSlotName (int squadSlotID); - -//------------------------------------- - -#define IMPLEMENT_CUSTOM_SCHEDULE_PROVIDER(derivedClass)\ - AI_SchedLoadStatus_t derivedClass::gm_SchedLoadStatus = { true, -1 }; \ - CAI_ClassScheduleIdSpace derivedClass::gm_ClassScheduleIdSpace; \ - const char * derivedClass::gm_pszErrorClassName = #derivedClass; \ - \ - derivedClass::CScheduleLoader::CScheduleLoader()\ - { \ - derivedClass::LoadSchedules(); \ - } \ - \ - /* --------------------------------------------- */ \ - /* Load schedules for this type of NPC */ \ - /* --------------------------------------------- */ \ - bool derivedClass::LoadSchedules(void)\ - {\ - return AI_DoLoadSchedules( derivedClass::BaseClass::LoadSchedules, \ - derivedClass::InitCustomSchedules, \ - &derivedClass::gm_SchedLoadStatus ); \ - }\ - \ - bool derivedClass::LoadedSchedules(void) \ - { \ - return derivedClass::gm_SchedLoadStatus.fValid;\ - } - - -//------------------------------------- - -// Initialize offsets and implement methods for loading and getting squad info for the subclass -#define IMPLEMENT_CUSTOM_AI(className, derivedClass)\ - IMPLEMENT_CUSTOM_SCHEDULE_PROVIDER(derivedClass)\ - \ - CAI_LocalIdSpace derivedClass::gm_SquadSlotIdSpace; \ - \ - /* -------------------------------------------------- */ \ - /* Given squadSlot enumeration return squadSlot name */ \ - /* -------------------------------------------------- */ \ - const char* derivedClass::SquadSlotName(int slotEN)\ - {\ - return gm_SquadSlotNamespace.IdToSymbol( derivedClass::gm_SquadSlotIdSpace.LocalToGlobal(slotEN) );\ - } - - -//------------------------------------- - -#define ADD_CUSTOM_SCHEDULE_NAMED(derivedClass,schedName,schedEN)\ - if ( !derivedClass::AccessClassScheduleIdSpaceDirect().AddSchedule( schedName, schedEN, derivedClass::gm_pszErrorClassName ) ) return; - -#define ADD_CUSTOM_SCHEDULE(derivedClass,schedEN) ADD_CUSTOM_SCHEDULE_NAMED(derivedClass,#schedEN,schedEN) - -#define ADD_CUSTOM_TASK_NAMED(derivedClass,taskName,taskEN)\ - if ( !derivedClass::AccessClassScheduleIdSpaceDirect().AddTask( taskName, taskEN, derivedClass::gm_pszErrorClassName ) ) return; - -#define ADD_CUSTOM_TASK(derivedClass,taskEN) ADD_CUSTOM_TASK_NAMED(derivedClass,#taskEN,taskEN) - -#define ADD_CUSTOM_CONDITION_NAMED(derivedClass,condName,condEN)\ - if ( !derivedClass::AccessClassScheduleIdSpaceDirect().AddCondition( condName, condEN, derivedClass::gm_pszErrorClassName ) ) return; - -#define ADD_CUSTOM_CONDITION(derivedClass,condEN) ADD_CUSTOM_CONDITION_NAMED(derivedClass,#condEN,condEN) - -//------------------------------------- - -#define INIT_CUSTOM_AI(derivedClass)\ - derivedClass::AccessClassScheduleIdSpaceDirect().Init( #derivedClass, BaseClass::GetSchedulingSymbols(), &BaseClass::AccessClassScheduleIdSpaceDirect() ); \ - derivedClass::gm_SquadSlotIdSpace.Init( &CAI_BaseNPC::gm_SquadSlotNamespace, &BaseClass::gm_SquadSlotIdSpace); - -#define ADD_CUSTOM_INTERACTION( interaction ) { interaction = CBaseCombatCharacter::GetInteractionID(); } - -#define ADD_CUSTOM_SQUADSLOT_NAMED(derivedClass,squadSlotName,squadSlotEN)\ - if ( !derivedClass::gm_SquadSlotIdSpace.AddSymbol( squadSlotName, squadSlotEN, "squadslot", derivedClass::gm_pszErrorClassName ) ) return; - -#define ADD_CUSTOM_SQUADSLOT(derivedClass,squadSlotEN) ADD_CUSTOM_SQUADSLOT_NAMED(derivedClass,#squadSlotEN,squadSlotEN) - -#define ADD_CUSTOM_ACTIVITY_NAMED(derivedClass,activityName,activityEnum)\ - REGISTER_PRIVATE_ACTIVITY(activityEnum);\ - CAI_BaseNPC::AddActivityToSR(activityName,activityEnum); - -#define ADD_CUSTOM_ACTIVITY(derivedClass,activityEnum) ADD_CUSTOM_ACTIVITY_NAMED(derivedClass,#activityEnum,activityEnum) - - -#define ADD_CUSTOM_ANIMEVENT_NAMED(derivedClass,eventName,eventEnum)\ - REGISTER_PRIVATE_ANIMEVENT(eventEnum);\ - CAI_BaseNPC::AddEventToSR(eventName,eventEnum); - -#define ADD_CUSTOM_ANIMEVENT(derivedClass,eventEnum) ADD_CUSTOM_ANIMEVENT_NAMED(derivedClass,#eventEnum,eventEnum) - - -//============================================================================= -// class CAI_Component -//============================================================================= - -inline const Vector &CAI_Component::GetLocalOrigin() const -{ - return GetOuter()->GetLocalOrigin(); -} - -//----------------------------------------------------------------------------- - -inline void CAI_Component::SetLocalOrigin(const Vector &origin) -{ - GetOuter()->SetLocalOrigin(origin); -} - -//----------------------------------------------------------------------------- - -inline const Vector &CAI_Component::GetAbsOrigin() const -{ - return GetOuter()->GetAbsOrigin(); -} - -//----------------------------------------------------------------------------- - -inline const QAngle &CAI_Component::GetAbsAngles() const -{ - return GetOuter()->GetAbsAngles(); -} - -//----------------------------------------------------------------------------- - -inline void CAI_Component::SetSolid( SolidType_t val ) -{ - GetOuter()->SetSolid(val); -} - -//----------------------------------------------------------------------------- - -inline SolidType_t CAI_Component::GetSolid() const -{ - return GetOuter()->GetSolid(); -} - -//----------------------------------------------------------------------------- - -inline const Vector &CAI_Component::WorldAlignMins() const -{ - return GetOuter()->WorldAlignMins(); -} - -//----------------------------------------------------------------------------- - -inline const Vector &CAI_Component::WorldAlignMaxs() const -{ - return GetOuter()->WorldAlignMaxs(); -} - -//----------------------------------------------------------------------------- - -inline Hull_t CAI_Component::GetHullType() const -{ - return GetOuter()->GetHullType(); -} - -//----------------------------------------------------------------------------- - -inline Vector CAI_Component::WorldSpaceCenter() const -{ - return GetOuter()->WorldSpaceCenter(); -} - -//----------------------------------------------------------------------------- - -inline float CAI_Component::GetGravity() const -{ - return GetOuter()->GetGravity(); -} - -//----------------------------------------------------------------------------- - -inline void CAI_Component::SetGravity( float flGravity ) -{ - GetOuter()->SetGravity( flGravity ); -} - -//----------------------------------------------------------------------------- - -inline float CAI_Component::GetHullWidth() const -{ - return NAI_Hull::Width(GetOuter()->GetHullType()); -} - -//----------------------------------------------------------------------------- - -inline float CAI_Component::GetHullHeight() const -{ - return NAI_Hull::Height(GetOuter()->GetHullType()); -} - -//----------------------------------------------------------------------------- - -inline const Vector &CAI_Component::GetHullMins() const -{ - return NAI_Hull::Mins(GetOuter()->GetHullType()); -} - -//----------------------------------------------------------------------------- - -inline const Vector &CAI_Component::GetHullMaxs() const -{ - return NAI_Hull::Maxs(GetOuter()->GetHullType()); -} - -//----------------------------------------------------------------------------- - -inline int CAI_Component::GetCollisionGroup() const -{ - return GetOuter()->GetCollisionGroup(); -} - -//----------------------------------------------------------------------------- - -inline CBaseEntity *CAI_Component::GetEnemy() -{ - return GetOuter()->GetEnemy(); -} - -//----------------------------------------------------------------------------- - -inline const Vector &CAI_Component::GetEnemyLKP() const -{ - return GetOuter()->GetEnemyLKP(); -} - -//----------------------------------------------------------------------------- - -inline void CAI_Component::TranslateNavGoal( CBaseEntity *pEnemy, Vector &chasePosition ) -{ - GetOuter()->TranslateNavGoal( pEnemy, chasePosition ); -} - -//----------------------------------------------------------------------------- - -inline CBaseEntity *CAI_Component::GetTarget() -{ - return GetOuter()->GetTarget(); -} -//----------------------------------------------------------------------------- - -inline void CAI_Component::SetTarget( CBaseEntity *pTarget ) -{ - GetOuter()->SetTarget( pTarget ); -} - -//----------------------------------------------------------------------------- - -inline const Task_t *CAI_Component::GetCurTask() -{ - return GetOuter()->GetTask(); -} - -//----------------------------------------------------------------------------- - -inline void CAI_Component::TaskFail( AI_TaskFailureCode_t code ) -{ - GetOuter()->TaskFail( code ); -} -//----------------------------------------------------------------------------- - -inline void CAI_Component::TaskFail( const char *pszGeneralFailText ) -{ - GetOuter()->TaskFail( pszGeneralFailText ); -} -//----------------------------------------------------------------------------- - -inline void CAI_Component::TaskComplete( bool fIgnoreSetFailedCondition ) -{ - GetOuter()->TaskComplete( fIgnoreSetFailedCondition ); -} -//----------------------------------------------------------------------------- - -inline int CAI_Component::TaskIsRunning() -{ - return GetOuter()->TaskIsRunning(); -} -//----------------------------------------------------------------------------- - -inline int CAI_Component::TaskIsComplete() -{ - return GetOuter()->TaskIsComplete(); -} - -//----------------------------------------------------------------------------- - -inline Activity CAI_Component::GetActivity() -{ - return GetOuter()->GetActivity(); -} -//----------------------------------------------------------------------------- - -inline void CAI_Component::SetActivity( Activity NewActivity ) -{ - GetOuter()->SetActivity( NewActivity ); -} -//----------------------------------------------------------------------------- - -inline float CAI_Component::GetIdealSpeed() const -{ - return GetOuter()->GetIdealSpeed(); -} - -//----------------------------------------------------------------------------- - -inline float CAI_Component::GetIdealAccel() const -{ - return GetOuter()->GetIdealAccel(); -} - -//----------------------------------------------------------------------------- - -inline int CAI_Component::GetSequence() -{ - return GetOuter()->GetSequence(); -} - -//----------------------------------------------------------------------------- - -inline int CAI_Component::GetEntFlags() const -{ - return GetOuter()->GetFlags(); -} - -//----------------------------------------------------------------------------- - -inline void CAI_Component::AddEntFlag( int flags ) -{ - GetOuter()->AddFlag( flags ); -} - -//----------------------------------------------------------------------------- - -inline void CAI_Component::RemoveEntFlag( int flagsToRemove ) -{ - GetOuter()->RemoveFlag( flagsToRemove ); -} - -//----------------------------------------------------------------------------- -// Purpose: Change the ground entity for the outer -// Input : *ground - -// Output : inline void -//----------------------------------------------------------------------------- -inline void CAI_Component::SetGroundEntity( CBaseEntity *ground ) -{ - GetOuter()->SetGroundEntity( ground ); -} - -//----------------------------------------------------------------------------- - -inline void CAI_Component::ToggleEntFlag( int flagToToggle ) -{ - GetOuter()->ToggleFlag( flagToToggle ); -} - -//----------------------------------------------------------------------------- - -inline CBaseEntity* CAI_Component::GetGoalEnt() -{ - return GetOuter()->GetGoalEnt(); -} -//----------------------------------------------------------------------------- - -inline void CAI_Component::SetGoalEnt( CBaseEntity *pGoalEnt ) -{ - GetOuter()->SetGoalEnt( pGoalEnt ); -} - -//----------------------------------------------------------------------------- - -inline void CAI_Component::Remember( int iMemory ) -{ - GetOuter()->Remember( iMemory ); -} -//----------------------------------------------------------------------------- - -inline void CAI_Component::Forget( int iMemory ) -{ - GetOuter()->Forget( iMemory ); -} -//----------------------------------------------------------------------------- - -inline bool CAI_Component::HasMemory( int iMemory ) -{ - return GetOuter()->HasMemory( iMemory ); -} - -//----------------------------------------------------------------------------- - -inline CAI_Enemies *CAI_Component::GetEnemies() -{ - return GetOuter()->GetEnemies(); -} - -//----------------------------------------------------------------------------- - -inline const char *CAI_Component::GetEntClassname() -{ - return GetOuter()->GetClassname(); -} - -//----------------------------------------------------------------------------- - -inline int CAI_Component::CapabilitiesGet() -{ - return GetOuter()->CapabilitiesGet(); -} - -//----------------------------------------------------------------------------- - -inline void CAI_Component::SetLocalAngles( const QAngle& angles ) -{ - GetOuter()->SetLocalAngles( angles ); -} - -//----------------------------------------------------------------------------- - -inline const QAngle &CAI_Component::GetLocalAngles( void ) const -{ - return GetOuter()->GetLocalAngles(); -} - -//----------------------------------------------------------------------------- - -inline edict_t *CAI_Component::GetEdict() -{ - return GetOuter()->NetworkProp()->edict(); -} - -//----------------------------------------------------------------------------- - -inline float CAI_Component::GetLastThink( const char *szContext ) -{ - return GetOuter()->GetLastThink( szContext ); -} - -// ============================================================================ -abstract_class INPCInteractive -{ -public: - virtual bool CanInteractWith( CAI_BaseNPC *pUser ) = 0; - virtual bool HasBeenInteractedWith() = 0; - virtual void NotifyInteraction( CAI_BaseNPC *pUser ) = 0; - - // Alyx specific interactions - virtual void AlyxStartedInteraction( void ) = 0; - virtual void AlyxFinishedInteraction( void ) = 0; -}; - -// Base Class for any NPC that wants to be interactable by other NPCS (i.e. Alyx Hackable) -// NOTE: YOU MUST DEFINE THE OUTPUTS IN YOUR CLASS'S DATADESC! -// THE DO SO, INSERT THE FOLLOWING MACRO INTO YOUR CLASS'S DATADESC. -// -#define DEFINE_BASENPCINTERACTABLE_DATADESC() \ - DEFINE_OUTPUT( m_OnAlyxStartedInteraction, "OnAlyxStartedInteraction" ), \ - DEFINE_OUTPUT( m_OnAlyxFinishedInteraction, "OnAlyxFinishedInteraction" ), \ - DEFINE_INPUTFUNC( FIELD_VOID, "InteractivePowerDown", InputPowerdown ) - -template -class CNPCBaseInteractive : public NPC_CLASS, public INPCInteractive -{ - DECLARE_CLASS( CNPCBaseInteractive, NPC_CLASS ); -public: - virtual bool CanInteractWith( CAI_BaseNPC *pUser ) { return false; }; - virtual bool HasBeenInteractedWith() { return false; }; - virtual void NotifyInteraction( CAI_BaseNPC *pUser ) { return; }; - - virtual void InputPowerdown( inputdata_t &inputdata ) - { - - } - - // Alyx specific interactions - virtual void AlyxStartedInteraction( void ) - { - m_OnAlyxStartedInteraction.FireOutput( this, this ); - } - virtual void AlyxFinishedInteraction( void ) - { - m_OnAlyxFinishedInteraction.FireOutput( this, this ); - } - -public: - // Outputs - // Alyx specific interactions - COutputEvent m_OnAlyxStartedInteraction; - COutputEvent m_OnAlyxFinishedInteraction; -}; - -// -// Deferred Navigation calls go here -// - -extern ConVar ai_post_frame_navigation; - -class CPostFrameNavigationHook : public CBaseGameSystemPerFrame -{ -public: - virtual const char *Name( void ) { return "CPostFrameNavigationHook"; } - - virtual bool Init( void ); - virtual void FrameUpdatePostEntityThink( void ); - virtual void FrameUpdatePreEntityThink( void ); - - bool IsGameFrameRunning( void ) { return m_bGameFrameRunning; } - void SetGrameFrameRunning( bool bState ) { m_bGameFrameRunning = bState; } - - void EnqueueEntityNavigationQuery( CAI_BaseNPC *pNPC, CFunctor *functor ); - -private: - CUtlVector m_Functors; - bool m_bGameFrameRunning; -}; - -extern CPostFrameNavigationHook *PostFrameNavigationSystem( void ); - -#endif // AI_BASENPC_H diff --git a/game/server/ai_basenpc_flyer.cpp b/game/server/ai_basenpc_flyer.cpp deleted file mode 100644 index b747209c1..000000000 --- a/game/server/ai_basenpc_flyer.cpp +++ /dev/null @@ -1,263 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Base class for many flying NPCs -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ai_basenpc_flyer.h" -#include "ai_route.h" -#include "ai_navigator.h" -#include "ai_motor.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -BEGIN_DATADESC( CAI_BaseFlyingBot ) - - DEFINE_FIELD( m_vCurrentVelocity, FIELD_VECTOR), - DEFINE_FIELD( m_vCurrentAngularVelocity, FIELD_VECTOR ), - DEFINE_FIELD( m_vCurrentBanking, FIELD_VECTOR), - DEFINE_FIELD( m_vNoiseMod, FIELD_VECTOR), - DEFINE_FIELD( m_fHeadYaw, FIELD_FLOAT), - DEFINE_FIELD( m_vLastPatrolDir, FIELD_VECTOR), - -END_DATADESC() - - -//------------------------------------------------------------------------------ -// Purpose : Override to return correct velocity -// Input : -// Output : -//------------------------------------------------------------------------------ -void CAI_BaseFlyingBot::GetVelocity(Vector *vVelocity, AngularImpulse *vAngVelocity) -{ - if (vVelocity != NULL) - { - VectorCopy(m_vCurrentVelocity,*vVelocity); - } - if (vAngVelocity != NULL) - { - QAngle tmp = GetLocalAngularVelocity(); - QAngleToAngularImpulse( tmp, *vAngVelocity ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Turn head yaw into facing direction -// Input : -// Output : -//----------------------------------------------------------------------------- -QAngle CAI_BaseFlyingBot::BodyAngles() -{ - return QAngle(0,m_fHeadYaw,0); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_BaseFlyingBot::TurnHeadToTarget(float flInterval, const Vector &MoveTarget ) -{ - float flDestYaw = VecToYaw( MoveTarget - GetLocalOrigin() ); - - float newYaw = AI_ClampYaw( GetHeadTurnRate() * 10.0f, m_fHeadYaw, flDestYaw, gpGlobals->curtime - GetLastThink() ); - - if ( newYaw != m_fHeadYaw ) - { - m_fHeadYaw = newYaw; - } - - // Set us to face that way - SetBoneController( 0, m_fHeadYaw ); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -float CAI_BaseFlyingBot::MinGroundDist(void) -{ - return 0; -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -Vector CAI_BaseFlyingBot::VelocityToAvoidObstacles(float flInterval) -{ - // -------------------------------- - // Avoid banging into stuff - // -------------------------------- - trace_t tr; - Vector vTravelDir = m_vCurrentVelocity*flInterval; - Vector endPos = GetAbsOrigin() + vTravelDir; - AI_TraceEntity( this, GetAbsOrigin(), endPos, MASK_NPCSOLID|CONTENTS_WATER, &tr ); - if (tr.fraction != 1.0) - { - // Bounce off in normal - Vector vBounce = tr.plane.normal * 0.5 * m_vCurrentVelocity.Length(); - return (vBounce); - } - - // -------------------------------- - // Try to remain above the ground. - // -------------------------------- - float flMinGroundDist = MinGroundDist(); - AI_TraceLine(GetAbsOrigin(), GetAbsOrigin() + Vector(0, 0, -flMinGroundDist), - MASK_NPCSOLID_BRUSHONLY|CONTENTS_WATER, this, COLLISION_GROUP_NONE, &tr); - if (tr.fraction < 1) - { - // Clamp veloctiy - if (tr.fraction < 0.1) - { - tr.fraction = 0.1; - } - - return Vector(0, 0, 50/tr.fraction); - } - return vec3_origin; -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CAI_BaseFlyingBot::StartTask( const Task_t *pTask ) -{ - switch (pTask->iTask) - { - // Skip as done via bone controller - case TASK_FACE_ENEMY: - { - TaskComplete(); - break; - } - // Activity is just idle (have no run) - case TASK_RUN_PATH: - { - GetNavigator()->SetMovementActivity(ACT_IDLE); - TaskComplete(); - break; - } - // Don't check for run/walk activity - case TASK_SCRIPT_RUN_TO_TARGET: - case TASK_SCRIPT_WALK_TO_TARGET: - { - if (GetTarget() == NULL) - { - TaskFail(FAIL_NO_TARGET); - } - else - { - if (!GetNavigator()->SetGoal( GOALTYPE_TARGETENT ) ) - { - TaskFail(FAIL_NO_ROUTE); - GetNavigator()->ClearGoal(); - } - } - TaskComplete(); - break; - } - // Override to get more to get a directional path - case TASK_GET_PATH_TO_RANDOM_NODE: - { - if ( GetNavigator()->SetRandomGoal( pTask->flTaskData, m_vLastPatrolDir ) ) - TaskComplete(); - else - TaskFail(FAIL_NO_REACHABLE_NODE); - break; - } - default: - { - BaseClass::StartTask(pTask); - } - } -} - -//------------------------------------------------------------------------------ - -void CAI_BaseFlyingBot::MoveToTarget(float flInterval, const Vector &MoveTarget) -{ - Assert(0); // This must be overridden in the leaf classes -} - -//------------------------------------------------------------------------------ - -AI_NavPathProgress_t CAI_BaseFlyingBot::ProgressFlyPath( - float flInterval, - const CBaseEntity *pNewTarget, - unsigned collisionMask, - bool bNewTrySimplify, - float strictPointTolerance) -{ - AI_ProgressFlyPathParams_t params( collisionMask, strictPointTolerance ); - - params.SetCurrent( pNewTarget, bNewTrySimplify ); - - AI_NavPathProgress_t progress = GetNavigator()->ProgressFlyPath( params ); - - switch ( progress ) - { - case AINPP_NO_CHANGE: - case AINPP_ADVANCED: - { - MoveToTarget(flInterval, GetNavigator()->GetCurWaypointPos()); - break; - } - - case AINPP_COMPLETE: - { - TaskMovementComplete(); - break; - } - - case AINPP_BLOCKED: // function is not supposed to test blocking, just simple path progression - default: - { - AssertMsg( 0, ( "Unexpected result" ) ); - break; - } - } - - return progress; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTarget - -// &chasePosition - -//----------------------------------------------------------------------------- -void CAI_BaseFlyingBot::TranslateNavGoal( CBaseEntity *pTarget, Vector &chasePosition ) -{ - Assert( pTarget != NULL ); - - if ( pTarget == NULL ) - { - chasePosition = vec3_origin; - return; - } - - // Chase their eyes - chasePosition = pTarget->GetAbsOrigin() + pTarget->GetViewOffset(); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -CAI_BaseFlyingBot::CAI_BaseFlyingBot() -{ -#ifdef _DEBUG - m_vCurrentVelocity.Init(); - m_vCurrentBanking.Init(); - m_vLastPatrolDir.Init(); -#endif -} diff --git a/game/server/ai_basenpc_flyer.h b/game/server/ai_basenpc_flyer.h deleted file mode 100644 index 862927a58..000000000 --- a/game/server/ai_basenpc_flyer.h +++ /dev/null @@ -1,132 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_BASENPC_FLYER_H -#define AI_BASENPC_FLYER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_basenpc.h" -#include "ai_navigator.h" - -//----------------------------------------------------------------------------- -// The combot. -//----------------------------------------------------------------------------- -abstract_class CAI_BaseFlyingBot : public CAI_BaseNPC -{ - DECLARE_CLASS( CAI_BaseFlyingBot, CAI_BaseNPC ); -public: - DECLARE_DATADESC(); - - void StartTask( const Task_t *pTask ); - void GetVelocity(Vector *vVelocity, AngularImpulse *vAngVelocity); - virtual QAngle BodyAngles(); - -protected: - - CAI_BaseFlyingBot(); - - Vector VelocityToAvoidObstacles(float flInterval); - virtual float MinGroundDist(void); - - void TurnHeadToTarget( float flInterval, const Vector &moveTarget ); - - void MoveInDirection( float flInterval, const Vector &targetDir, - float accelXY, float accelZ, float decay) - { - decay = ExponentialDecay( decay, 1.0, flInterval ); - accelXY *= flInterval; - accelZ *= flInterval; - - m_vCurrentVelocity.x = ( decay * m_vCurrentVelocity.x + accelXY * targetDir.x ); - m_vCurrentVelocity.y = ( decay * m_vCurrentVelocity.y + accelXY * targetDir.y ); - m_vCurrentVelocity.z = ( decay * m_vCurrentVelocity.z + accelZ * targetDir.z ); - } - - void MoveToLocation( float flInterval, const Vector &target, - float accelXY, float accelZ, float decay) - { - Vector targetDir = target - GetLocalOrigin(); - VectorNormalize(targetDir); - - MoveInDirection(flInterval, targetDir, accelXY, accelZ, decay); - } - - void Decelerate( float flInterval, float decay ) - { - decay *= flInterval; - m_vCurrentVelocity.x = (decay * m_vCurrentVelocity.x); - m_vCurrentVelocity.y = (decay * m_vCurrentVelocity.y); - m_vCurrentVelocity.z = (decay * m_vCurrentVelocity.z); - } - - void AddNoiseToVelocity( float noiseScale = 1.0 ) - { - if( m_vNoiseMod.x ) - { - m_vCurrentVelocity.x += noiseScale*sin(m_vNoiseMod.x * gpGlobals->curtime + m_vNoiseMod.x); - } - - if( m_vNoiseMod.y ) - { - m_vCurrentVelocity.y += noiseScale*cos(m_vNoiseMod.y * gpGlobals->curtime + m_vNoiseMod.y); - } - - if( m_vNoiseMod.z ) - { - m_vCurrentVelocity.z -= noiseScale*cos(m_vNoiseMod.z * gpGlobals->curtime + m_vNoiseMod.z); - } - } - - void LimitSpeed( float zLimit, float maxSpeed = -1 ) - { - if ( maxSpeed == -1 ) - maxSpeed = m_flSpeed; - if (m_vCurrentVelocity.Length() > maxSpeed) - { - VectorNormalize(m_vCurrentVelocity); - m_vCurrentVelocity *= maxSpeed; - } - // Limit fall speed - if (zLimit > 0 && m_vCurrentVelocity.z < -zLimit) - { - m_vCurrentVelocity.z = -zLimit; - } - } - - AI_NavPathProgress_t ProgressFlyPath( float flInterval, - const CBaseEntity *pNewTarget, - unsigned collisionMask, - bool bNewTrySimplify = true, - float strictPointTolerance = 32.0 ); - - virtual float GetHeadTurnRate( void ) { return 15.0f; } // Degrees per second - - const Vector &GetCurrentVelocity() const { return m_vCurrentVelocity; } - void SetCurrentVelocity(const Vector &vNewVel) { m_vCurrentVelocity = vNewVel; } - - const Vector &GetNoiseMod() const { return m_vNoiseMod; } - void SetNoiseMod( float x, float y, float z ) { m_vNoiseMod.Init( x, y, z ); } - void SetNoiseMod( const Vector &noise ) { m_vNoiseMod = noise; } - - virtual void MoveToTarget(float flInterval, const Vector &MoveTarget) = 0; - - void TranslateNavGoal( CBaseEntity *pTarget, Vector &chasePosition ); - - // ------------------------------- - // Movement vars - // ------------------------------- - Vector m_vCurrentVelocity; - Vector m_vCurrentAngularVelocity; - Vector m_vCurrentBanking; - Vector m_vNoiseMod; - float m_fHeadYaw; - Vector m_vLastPatrolDir; -}; - -#endif // AI_BASENPC_FLYER_H diff --git a/game/server/ai_basenpc_flyer_new.cpp b/game/server/ai_basenpc_flyer_new.cpp deleted file mode 100644 index 226e91131..000000000 --- a/game/server/ai_basenpc_flyer_new.cpp +++ /dev/null @@ -1,140 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Base class for many flying NPCs -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ai_basenpc_flyer_new.h" -#include "ai_route.h" -#include "ai_navigator.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define FLYER_ROUTE_REBUILD_TIME 3.0 // Time between route rebuilds - - -// NOTE: Never instantiate ai_base_npc_flyer_new directly!! -//IMPLEMENT_CUSTOM_AI( ai_base_npc_flyer_new, CAI_BaseNPCFlyerNew); - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -CAI_BaseNPCFlyerNew::CAI_BaseNPCFlyerNew() -{ -} - - -//------------------------------------------------------------------------------ -// Used to set up a flyer -//------------------------------------------------------------------------------ -void CAI_BaseNPCFlyerNew::SpawnFlyer() -{ - SetNavType( NAV_FLY ); - AddFlag( FL_FLY ); - SetMoveType( MOVETYPE_STEP ); - CapabilitiesAdd( bits_CAP_MOVE_FLY ); -} - - -/* -void CAI_BaseNPCFlyerNew::InitCustomSchedules(void) -{ - INIT_CUSTOM_AI(CAI_BaseNPCFlyerNew); - - ADD_CUSTOM_CONDITION(CAI_BaseNPCFlyerNew, COND_FLYER_MOVE_BLOCKED); - ADD_CUSTOM_CONDITION(CAI_BaseNPCFlyerNew, COND_FLYER_MOVE_IMPOSSIBLE); -} -*/ - -//------------------------------------------------------------------------------ -// Should be called during Select Schedule (BLEAH!) -//------------------------------------------------------------------------------ -void CAI_BaseNPCFlyerNew::ClearFlyerConditions(void) -{ -// ClearCondition( COND_FLYER_MOVE_BLOCKED ); -// ClearCondition( COND_FLYER_MOVE_IMPOSSIBLE ); -} - - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -float CAI_BaseNPCFlyerNew::MinGroundDist(void) -{ - return 0; -} - - -//----------------------------------------------------------------------------- -// Sets the ground speed appropriately: -//----------------------------------------------------------------------------- -float CAI_BaseNPCFlyerNew::GetIdealSpeed( ) const -{ - return m_flSpeed; -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CAI_BaseNPCFlyerNew::StartTask( const Task_t *pTask ) -{ - switch (pTask->iTask) - { - // Activity is just idle (have no run) - case TASK_RUN_PATH: - { - GetNavigator()->SetMovementActivity(ACT_IDLE); - TaskComplete(); - break; - } - - // Don't check for run/walk activity - case TASK_SCRIPT_RUN_TO_TARGET: - case TASK_SCRIPT_WALK_TO_TARGET: - { - if (GetTarget() == NULL) - { - TaskFail(FAIL_NO_TARGET); - } - else - { - if (!GetNavigator()->SetGoal( GOALTYPE_TARGETENT ) ) - { - TaskFail(FAIL_NO_ROUTE); - GetNavigator()->ClearGoal(); - } - } - TaskComplete(); - break; - } - - default: - { - BaseClass::StartTask(pTask); - } - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BaseNPCFlyerNew::RunTask( const Task_t *pTask ) -{ - BaseClass::RunTask(pTask); -} - - diff --git a/game/server/ai_basenpc_flyer_new.h b/game/server/ai_basenpc_flyer_new.h deleted file mode 100644 index f519ac908..000000000 --- a/game/server/ai_basenpc_flyer_new.h +++ /dev/null @@ -1,58 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_BASENPC_FLYER_NEW_H -#define AI_BASENPC_FLYER_NEW_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_basenpc.h" -#include "ai_condition.h" - - -enum BaseNPCFlyerConditions_t -{ - COND_FLYER_MOVE_BLOCKED = LAST_SHARED_CONDITION, - COND_FLYER_MOVE_IMPOSSIBLE, - - // ====================================== - // IMPORTANT: This must be the last enum - // ====================================== - LAST_FLYER_SHARED_CONDITION -}; - - -//----------------------------------------------------------------------------- -// The combot. -//----------------------------------------------------------------------------- -class CAI_BaseNPCFlyerNew : public CAI_BaseNPC -{ - DECLARE_CLASS( CAI_BaseNPCFlyerNew, CAI_BaseNPC ); -public: -// DEFINE_CUSTOM_AI; - - virtual void StartTask( const Task_t *pTask ); - virtual void RunTask( const Task_t *pTask ); - - virtual float GetIdealSpeed( ) const; - virtual float MinGroundDist(void); - - CAI_BaseNPCFlyerNew(); - -protected: - // Call this to set up a flyer - void SpawnFlyer(); - - // Yarg! Must be chained down from leaf classes... - void ClearFlyerConditions(void); - - // Override this when we had to abort movement - virtual void AbortedMovement( void ) {} -}; - -#endif // AI_BASENPC_FLYER_NEW_H diff --git a/game/server/ai_basenpc_movement.cpp b/game/server/ai_basenpc_movement.cpp deleted file mode 100644 index e8426dacc..000000000 --- a/game/server/ai_basenpc_movement.cpp +++ /dev/null @@ -1,499 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - - -#include "cbase.h" - -#include "game.h" -#include "ndebugoverlay.h" - -#include "ai_basenpc.h" -#include "ai_hull.h" -#include "ai_node.h" -#include "ai_motor.h" -#include "ai_navigator.h" -#include "ai_hint.h" -#include "scripted.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//============================================================================= -// PATHING & HIGHER LEVEL MOVEMENT -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// Purpose: Static debug function to force all selected npcs to go to the -// given node -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_BaseNPC::ForceSelectedGo(CBaseEntity *pPlayer, const Vector &targetPos, const Vector &traceDir, bool bRun) -{ - CAI_BaseNPC *npc = gEntList.NextEntByClass( (CAI_BaseNPC *)NULL ); - - while (npc) - { - if (npc->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) - { - Vector chasePosition = targetPos; - npc->TranslateNavGoal( pPlayer, chasePosition ); - // It it legal to drop me here - Vector vUpBit = chasePosition; - vUpBit.z += 1; - - trace_t tr; - AI_TraceHull( chasePosition, vUpBit, npc->GetHullMins(), - npc->GetHullMaxs(), MASK_NPCSOLID, npc, COLLISION_GROUP_NONE, &tr ); - if (tr.startsolid || tr.fraction != 1.0 ) - { - NDebugOverlay::BoxAngles(chasePosition, npc->GetHullMins(), - npc->GetHullMaxs(), npc->GetAbsAngles(), 255,0,0,20,0.5); - } - - npc->m_vecLastPosition = chasePosition; - - if (npc->m_hCine != NULL) - { - npc->ExitScriptedSequence(); - } - - if ( bRun ) - npc->SetSchedule( SCHED_FORCED_GO_RUN ); - else - npc->SetSchedule( SCHED_FORCED_GO ); - npc->m_flMoveWaitFinished = gpGlobals->curtime; - } - npc = gEntList.NextEntByClass(npc); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Static debug function to make all selected npcs run around -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_BaseNPC::ForceSelectedGoRandom(void) -{ - CAI_BaseNPC *npc = gEntList.NextEntByClass( (CAI_BaseNPC *)NULL ); - - while (npc) - { - if (npc->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) - { - npc->SetSchedule( SCHED_RUN_RANDOM ); - npc->GetNavigator()->SetMovementActivity(ACT_RUN); - } - npc = gEntList.NextEntByClass(npc); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::ScheduledMoveToGoalEntity( int scheduleType, CBaseEntity *pGoalEntity, Activity movementActivity ) -{ - if ( m_NPCState == NPC_STATE_NONE ) - { - // More than likely being grabbed before first think. Set ideal state to prevent schedule stomp - m_NPCState = m_IdealNPCState; - } - - SetSchedule( scheduleType ); - - SetGoalEnt( pGoalEntity ); - - // HACKHACK: Call through TranslateNavGoal to fixup this goal position - // UNDONE: Remove this and have NPCs that need this functionality fix up paths in the - // movement system instead of when they are specified. - AI_NavGoal_t goal(pGoalEntity->GetAbsOrigin(), movementActivity, AIN_DEF_TOLERANCE, AIN_YAW_TO_DEST); - - TranslateNavGoal( pGoalEntity, goal.dest ); - - return GetNavigator()->SetGoal( goal ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::ScheduledFollowPath( int scheduleType, CBaseEntity *pPathStart, Activity movementActivity ) -{ - if ( m_NPCState == NPC_STATE_NONE ) - { - // More than likely being grabbed before first think. Set ideal state to prevent schedule stomp - m_NPCState = m_IdealNPCState; - } - - SetSchedule( scheduleType ); - - SetGoalEnt( pPathStart ); - - // HACKHACK: Call through TranslateNavGoal to fixup this goal position - AI_NavGoal_t goal(GOALTYPE_PATHCORNER, pPathStart->GetLocalOrigin(), movementActivity, AIN_DEF_TOLERANCE, AIN_YAW_TO_DEST); - - TranslateNavGoal( pPathStart, goal.dest ); - - return GetNavigator()->SetGoal( goal ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::IsMoving( void ) -{ - return GetNavigator()->IsGoalSet(); -} - - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::IsCurTaskContinuousMove() -{ - const Task_t* pTask = GetTask(); - - // This bit of logic strikes me funny, but the case does exist. (sjb) - if( !pTask ) - return true; - - switch( pTask->iTask ) - { - case TASK_WAIT_FOR_MOVEMENT: - case TASK_MOVE_TO_TARGET_RANGE: - case TASK_MOVE_TO_GOAL_RANGE: - case TASK_WEAPON_RUN_PATH: - case TASK_PLAY_SCENE: - case TASK_RUN_PATH_TIMED: - case TASK_WALK_PATH_TIMED: - case TASK_RUN_PATH_FOR_UNITS: - case TASK_WALK_PATH_FOR_UNITS: - case TASK_RUN_PATH_FLEE: - case TASK_WALK_PATH_WITHIN_DIST: - case TASK_RUN_PATH_WITHIN_DIST: - return true; - break; - - default: - return false; - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Used to specify that the NPC has a reason not to use the a navigation node -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::IsUnusableNode(int iNodeID, CAI_Hint *pHint) -{ - if ( m_bHintGroupNavLimiting && m_strHintGroup != NULL_STRING && STRING(m_strHintGroup)[0] != 0 ) - { - if (!pHint || pHint->GetGroup() != GetHintGroup()) - { - return true; - } - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Checks the validity of the given route's goaltype -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::ValidateNavGoal() -{ - if (GetNavigator()->GetGoalType() == GOALTYPE_COVER) - { - // Check if this location will block my enemy's line of sight to me - if (GetEnemy()) - { - Activity nCoverActivity = GetCoverActivity( GetHintNode() ); - Vector vCoverLocation = GetNavigator()->GetGoalPos(); - - - // For now we have to drop the node to the floor so we can - // get an accurate postion of the NPC. Should change once Ken checks in - float floorZ = GetFloorZ(vCoverLocation); - vCoverLocation.z = floorZ; - - - Vector vEyePos = vCoverLocation + EyeOffset(nCoverActivity); - - if (!IsCoverPosition( GetEnemy()->EyePosition(), vEyePos ) ) - { - TaskFail(FAIL_BAD_PATH_GOAL); - return false; - } - } - } - return true; -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -float CAI_BaseNPC::OpenDoorAndWait( CBaseEntity *pDoor ) -{ - float flTravelTime = 0; - - //DevMsg( 2, "A door. "); - if (pDoor && !pDoor->IsLockedByMaster()) - { - pDoor->Use(this, this, USE_ON, 0.0); - flTravelTime = pDoor->GetMoveDoneTime(); - if ( pDoor->GetEntityName() != NULL_STRING ) - { - CBaseEntity *pTarget = NULL; - for (;;) - { - pTarget = gEntList.FindEntityByName( pTarget, pDoor->GetEntityName() ); - - if ( pTarget != pDoor ) - { - if ( !pTarget ) - break; - - if ( FClassnameIs( pTarget, pDoor->GetClassname() ) ) - { - pTarget->Use(this, this, USE_ON, 0.0); - } - } - } - } - } - - return gpGlobals->curtime + flTravelTime; -} - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::CanStandOn( CBaseEntity *pSurface ) const -{ - if ( !pSurface->IsAIWalkable() ) - { - return false; - } - - CAI_Navigator *pNavigator = const_cast(GetNavigator()); - - if ( pNavigator->IsGoalActive() && - pSurface == pNavigator->GetGoalTarget() ) - return false; - - return BaseClass::CanStandOn( pSurface ); -} - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos, - float maxUp, float maxDown, float maxDist ) const -{ - if ((endPos.z - startPos.z) > maxUp + 0.1) - return false; - if ((startPos.z - endPos.z) > maxDown + 0.1) - return false; - - if ((apex.z - startPos.z) > maxUp * 1.25 ) - return false; - - float dist = (startPos - endPos).Length(); - if ( dist > maxDist + 0.1) - return false; - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true if a reasonable jumping distance -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos ) const -{ - const float MAX_JUMP_RISE = 80.0f; - const float MAX_JUMP_DISTANCE = 250.0f; - const float MAX_JUMP_DROP = 192.0f; - - return IsJumpLegal( startPos, apex, endPos, MAX_JUMP_RISE, MAX_JUMP_DROP, MAX_JUMP_DISTANCE ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns a throw velocity from start to end position -// Input : -// Output : -//----------------------------------------------------------------------------- -Vector CAI_BaseNPC::CalcThrowVelocity(const Vector &startPos, const Vector &endPos, float fGravity, float fArcSize) -{ - // Get the height I have to throw to get to the target - float stepHeight = endPos.z - startPos.z; - float throwHeight = 0; - - // ----------------------------------------------------------------- - // Now calcluate the distance to a point halfway between our current - // and target position. (the apex of our throwing arc) - // ----------------------------------------------------------------- - Vector targetDir2D = endPos - startPos; - targetDir2D.z = 0; - - float distance = VectorNormalize(targetDir2D); - - - // If jumping up we want to throw a bit higher than the height diff - if (stepHeight > 0) - { - throwHeight = stepHeight + fArcSize; - } - else - { - throwHeight = fArcSize; - } - // Make sure that I at least catch some air - if (throwHeight < fArcSize) - { - throwHeight = fArcSize; - } - - - // ------------------------------------------------------------- - // calculate the vertical and horizontal launch velocities - // ------------------------------------------------------------- - float velVert = (float)sqrt(2.0f*fGravity*throwHeight); - - float divisor = velVert; - divisor += (float)sqrt((2.0f*(-fGravity)*(stepHeight-throwHeight))); - - float velHorz = (distance * fGravity)/divisor; - - // ----------------------------------------------------------- - // Make the horizontal throw vector and add vertical component - // ----------------------------------------------------------- - Vector throwVel = targetDir2D * velHorz; - throwVel.z = velVert; - - return throwVel; -} - -bool CAI_BaseNPC::ShouldMoveWait() -{ - return (m_flMoveWaitFinished > gpGlobals->curtime); -} - -float CAI_BaseNPC::GetStepDownMultiplier() const -{ - return m_pNavigator->GetStepDownMultiplier(); -} - - -//----------------------------------------------------------------------------- -// Purpose: execute any movement this sequence may have -// Output : -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::AutoMovement( CBaseEntity *pTarget, AIMoveTrace_t *pTraceResult ) -{ - return AutoMovement( GetAnimTimeInterval(), pTarget, pTraceResult ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flInterval - -// - -// *pTraceResult - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::AutoMovement( float flInterval, CBaseEntity *pTarget, AIMoveTrace_t *pTraceResult ) -{ - bool ignored; - Vector newPos; - QAngle newAngles; - - if (flInterval <= 0.0) - return true; - - m_ScheduleState.bTaskRanAutomovement = true; - - if (GetIntervalMovement( flInterval, ignored, newPos, newAngles )) - { - // DevMsg( "%.2f : (%.1f) %.1f %.1f %.1f\n", gpGlobals->curtime, (newPos - GetLocalOrigin()).Length(), newPos.x, newPos.y, newAngles.y ); - - if ( m_hCine ) - { - m_hCine->ModifyScriptedAutoMovement( &newPos ); - } - - if (GetMoveType() == MOVETYPE_STEP) - { - if (!(GetFlags() & FL_FLY)) - { - if ( !pTarget ) - { - pTarget = GetNavTargetEntity(); - } - - return ( GetMotor()->MoveGroundStep( newPos, pTarget, newAngles.y, false, true, pTraceResult ) == AIM_SUCCESS ); - } - else - { - // FIXME: here's no direct interface to a fly motor, plus this needs to support a state where going through the world is okay. - // FIXME: add callbacks into the script system for validation - // FIXME: add function on scripts to force only legal movements - // FIXME: GetIntervalMovement deals in Local space, nor global. Currently now way to communicate that through these interfaces. - SetLocalOrigin( newPos ); - SetLocalAngles( newAngles ); - return true; - } - } - else if (GetMoveType() == MOVETYPE_FLY) - { - Vector dist = newPos - GetLocalOrigin(); - - VectorScale( dist, 1.0 / flInterval, dist ); - - SetLocalVelocity( dist ); - return true; - } - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: return max 1/10 second rate of turning -// Input : -// Output : -//----------------------------------------------------------------------------- - -float CAI_BaseNPC::MaxYawSpeed( void ) -{ - return 45; -} - -//----------------------------------------------------------------------------- -// Returns the estimate in seconds before we reach our nav goal. -// -1 means we don't know / haven't calculated it yet. -//----------------------------------------------------------------------------- -float CAI_BaseNPC::GetTimeToNavGoal() -{ - float flDist = GetNavigator()->BuildAndGetPathDistToGoal(); - if ( flDist < 0 ) - { - return -1.0f; - } - - float flSpeed = GetIdealSpeed(); - - // FIXME: needs to consider stopping time! - if (flSpeed > 0 && flDist > 0) - { - return flDist / flSpeed; - } - return 0.0; -} - -//============================================================================= diff --git a/game/server/ai_basenpc_physicsflyer.cpp b/game/server/ai_basenpc_physicsflyer.cpp deleted file mode 100644 index d4850f6ae..000000000 --- a/game/server/ai_basenpc_physicsflyer.cpp +++ /dev/null @@ -1,380 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Base class for many flying NPCs -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ai_basenpc_physicsflyer.h" -#include "ai_route.h" -#include "ai_navigator.h" -#include "ai_motor.h" -#include "physics_saverestore.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -BEGIN_DATADESC( CAI_BasePhysicsFlyingBot ) - - DEFINE_FIELD( m_vCurrentVelocity, FIELD_VECTOR), - DEFINE_FIELD( m_vCurrentBanking, FIELD_VECTOR), - DEFINE_FIELD( m_vNoiseMod, FIELD_VECTOR), - DEFINE_FIELD( m_fHeadYaw, FIELD_FLOAT), - DEFINE_FIELD( m_vLastPatrolDir, FIELD_VECTOR), - - DEFINE_PHYSPTR( m_pMotionController ), - -END_DATADESC() - - -//------------------------------------------------------------------------------ -// Purpose : Override to return correct velocity -// Input : -// Output : -//------------------------------------------------------------------------------ -void CAI_BasePhysicsFlyingBot::GetVelocity(Vector *vVelocity, AngularImpulse *vAngVelocity) -{ - Assert( GetMoveType() == MOVETYPE_VPHYSICS ); - if ( VPhysicsGetObject() ) - { - VPhysicsGetObject()->GetVelocity( vVelocity, vAngVelocity ); - } - else - { - if ( vVelocity ) - { - vVelocity->Init(); - } - if ( vAngVelocity ) - { - vAngVelocity->Init(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Turn head yaw into facing direction -// Input : -// Output : -//----------------------------------------------------------------------------- -QAngle CAI_BasePhysicsFlyingBot::BodyAngles() -{ - return QAngle(0,m_fHeadYaw,0); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_BasePhysicsFlyingBot::TurnHeadToTarget(float flInterval, const Vector &MoveTarget ) -{ - float desYaw = UTIL_AngleDiff(VecToYaw(MoveTarget - GetLocalOrigin()), 0 ); - - m_fHeadYaw = desYaw; - - return; - - // If I've flipped completely around, reverse angles - float fYawDiff = m_fHeadYaw - desYaw; - if (fYawDiff > 180) - { - m_fHeadYaw -= 360; - } - else if (fYawDiff < -180) - { - m_fHeadYaw += 360; - } - - // RIGHT NOW, this affects every flying bot. This rate should be member data that individuals - // can manipulate. THIS change for MANHACKS E3 2003 (sjb) - float iRate = 0.8; - - // Make frame rate independent - float timeToUse = flInterval; - while (timeToUse > 0) - { - m_fHeadYaw = (iRate * m_fHeadYaw) + (1-iRate)*desYaw; - timeToUse -= 0.1; - } - - while( m_fHeadYaw > 360 ) - { - m_fHeadYaw -= 360.0f; - } - - while( m_fHeadYaw < 0 ) - { - m_fHeadYaw += 360.f; - } - - // SetBoneController( 0, m_fHeadYaw ); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -float CAI_BasePhysicsFlyingBot::MinGroundDist(void) -{ - return 0; -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -Vector CAI_BasePhysicsFlyingBot::VelocityToAvoidObstacles(float flInterval) -{ - // -------------------------------- - // Avoid banging into stuff - // -------------------------------- - trace_t tr; - Vector vTravelDir = m_vCurrentVelocity*flInterval; - Vector endPos = GetAbsOrigin() + vTravelDir; - AI_TraceEntity( this, GetAbsOrigin(), endPos, MASK_NPCSOLID|CONTENTS_WATER, &tr); - if (tr.fraction != 1.0) - { - // Bounce off in normal - Vector vBounce = tr.plane.normal * 0.5 * m_vCurrentVelocity.Length(); - return (vBounce); - } - - // -------------------------------- - // Try to remain above the ground. - // -------------------------------- - float flMinGroundDist = MinGroundDist(); - AI_TraceLine(GetAbsOrigin(), GetAbsOrigin() + Vector(0, 0, -flMinGroundDist), - MASK_NPCSOLID_BRUSHONLY|CONTENTS_WATER, this, COLLISION_GROUP_NONE, &tr); - if (tr.fraction < 1) - { - // Clamp veloctiy - if (tr.fraction < 0.1) - { - tr.fraction = 0.1; - } - - return Vector(0, 0, 50/tr.fraction); - } - return vec3_origin; -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CAI_BasePhysicsFlyingBot::StartTask( const Task_t *pTask ) -{ - switch (pTask->iTask) - { - // Skip as done via bone controller - case TASK_FACE_ENEMY: - { - TaskComplete(); - break; - } - // Activity is just idle (have no run) - case TASK_RUN_PATH: - { - GetNavigator()->SetMovementActivity(ACT_IDLE); - TaskComplete(); - break; - } - // Don't check for run/walk activity - case TASK_SCRIPT_RUN_TO_TARGET: - case TASK_SCRIPT_WALK_TO_TARGET: - { - if (GetTarget() == NULL) - { - TaskFail(FAIL_NO_TARGET); - } - else - { - if (!GetNavigator()->SetGoal( GOALTYPE_TARGETENT ) ) - { - TaskFail(FAIL_NO_ROUTE); - GetNavigator()->ClearGoal(); - } - } - TaskComplete(); - break; - } - // Override to get more to get a directional path - case TASK_GET_PATH_TO_RANDOM_NODE: - { - if ( GetNavigator()->SetRandomGoal( pTask->flTaskData, m_vLastPatrolDir ) ) - TaskComplete(); - else - TaskFail(FAIL_NO_REACHABLE_NODE); - break; - } - default: - { - BaseClass::StartTask(pTask); - } - } -} - -//------------------------------------------------------------------------------ - -void CAI_BasePhysicsFlyingBot::MoveToTarget(float flInterval, const Vector &MoveTarget) -{ - Assert(0); // This must be overridden in the leaf classes -} - -//------------------------------------------------------------------------------ - -AI_NavPathProgress_t CAI_BasePhysicsFlyingBot::ProgressFlyPath( - float flInterval, - const CBaseEntity *pNewTarget, - unsigned collisionMask, - bool bNewTrySimplify, - float strictPointTolerance) -{ - AI_ProgressFlyPathParams_t params( collisionMask ); - params.strictPointTolerance = strictPointTolerance; - params.SetCurrent( pNewTarget, bNewTrySimplify ); - - AI_NavPathProgress_t progress = GetNavigator()->ProgressFlyPath( params ); - - switch ( progress ) - { - case AINPP_NO_CHANGE: - case AINPP_ADVANCED: - { - MoveToTarget(flInterval, GetNavigator()->GetCurWaypointPos()); - break; - } - - case AINPP_COMPLETE: - { - TaskMovementComplete(); - break; - } - - case AINPP_BLOCKED: // function is not supposed to test blocking, just simple path progression - default: - { - AssertMsg( 0, ( "Unexpected result" ) ); - break; - } - } - - return progress; -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -CAI_BasePhysicsFlyingBot::CAI_BasePhysicsFlyingBot() -{ -#ifdef _DEBUG - m_vCurrentVelocity.Init(); - m_vCurrentBanking.Init(); - m_vLastPatrolDir.Init(); -#endif -} - - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CAI_BasePhysicsFlyingBot::~CAI_BasePhysicsFlyingBot( void ) -{ - physenv->DestroyMotionController( m_pMotionController ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -bool CAI_BasePhysicsFlyingBot::CreateVPhysics( void ) -{ - // Create the object in the physics system - IPhysicsObject *pPhysicsObject = VPhysicsInitNormal( SOLID_BBOX, FSOLID_NOT_STANDABLE, false ); - - m_pMotionController = physenv->CreateMotionController( this ); - m_pMotionController->AttachObject( pPhysicsObject, true ); - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTarget - -// &chasePosition - -//----------------------------------------------------------------------------- -void CAI_BasePhysicsFlyingBot::TranslateNavGoal( CBaseEntity *pTarget, Vector &chasePosition ) -{ - Assert( pTarget != NULL ); - - if ( pTarget == NULL ) - { - chasePosition = vec3_origin; - return; - } - - // Chase their eyes - chasePosition = pTarget->GetAbsOrigin() + pTarget->GetViewOffset(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pController - -// *pObject - -// deltaTime - -// &linear - -// &angular - -// Output : IMotionEvent::simresult_e -//----------------------------------------------------------------------------- -IMotionEvent::simresult_e CAI_BasePhysicsFlyingBot::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) -{ - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - // Assert( pPhysicsObject ); - if (!pPhysicsObject) - return SIM_NOTHING; - - // move - Vector actualVelocity; - AngularImpulse actualAngularVelocity; - pPhysicsObject->GetVelocity( &actualVelocity, &actualAngularVelocity ); - linear = (m_vCurrentVelocity - actualVelocity) * (0.1 / deltaTime) * 10.0; - - /* - DevMsg("Sim %d : %5.1f %5.1f %5.1f\n", count++, - m_vCurrentVelocity.x - actualVelocity.x, - m_vCurrentVelocity.y - actualVelocity.y, - m_vCurrentVelocity.z - actualVelocity.z ); - */ - - // do angles. - Vector actualPosition; - QAngle actualAngles; - pPhysicsObject->GetPosition( &actualPosition, &actualAngles ); - - // FIXME: banking currently disabled, forces simple upright posture - angular.x = (UTIL_AngleDiff( m_vCurrentBanking.z, actualAngles.z ) - actualAngularVelocity.x) * (1 / deltaTime); - angular.y = (UTIL_AngleDiff( m_vCurrentBanking.x, actualAngles.x ) - actualAngularVelocity.y) * (1 / deltaTime); - - // turn toward target - angular.z = UTIL_AngleDiff( m_fHeadYaw, actualAngles.y + actualAngularVelocity.z * 0.1 ) * (1 / deltaTime); - - // angular = m_vCurrentAngularVelocity - actualAngularVelocity; - - // DevMsg("Sim %d : %.1f %.1f %.1f (%.1f)\n", count++, actualAngles.x, actualAngles.y, actualAngles.z, m_fHeadYaw ); - - // FIXME: remove the stuff from MoveExecute(); - // FIXME: check MOVE? - - ClampMotorForces( linear, angular ); - - return SIM_GLOBAL_ACCELERATION; // on my local axis. SIM_GLOBAL_ACCELERATION -} - diff --git a/game/server/ai_basenpc_physicsflyer.h b/game/server/ai_basenpc_physicsflyer.h deleted file mode 100644 index 2ef526594..000000000 --- a/game/server/ai_basenpc_physicsflyer.h +++ /dev/null @@ -1,149 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_BASENPC_PHYSICSFLYER_H -#define AI_BASENPC_PHYSICSFLYER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_basenpc.h" -#include "ai_navigator.h" - -//----------------------------------------------------------------------------- -// The combot. -//----------------------------------------------------------------------------- -abstract_class CAI_BasePhysicsFlyingBot : public CAI_BaseNPC, public IMotionEvent -{ - DECLARE_CLASS( CAI_BasePhysicsFlyingBot, CAI_BaseNPC ); -public: - DECLARE_DATADESC(); - - void StartTask( const Task_t *pTask ); - void GetVelocity(Vector *vVelocity, AngularImpulse *vAngVelocity); - virtual QAngle BodyAngles(); - - virtual bool ShouldSavePhysics() { return true; } - -protected: - - CAI_BasePhysicsFlyingBot(); - ~CAI_BasePhysicsFlyingBot(); - - Vector VelocityToAvoidObstacles(float flInterval); - virtual float MinGroundDist(void); - - virtual void TurnHeadToTarget( float flInterval, const Vector &moveTarget ); - - void MoveInDirection( float flInterval, const Vector &targetDir, - float accelXY, float accelZ, float decay) - { - decay = ExponentialDecay( decay, 1.0, flInterval ); - accelXY *= flInterval; - accelZ *= flInterval; - - m_vCurrentVelocity.x = ( decay * m_vCurrentVelocity.x + accelXY * targetDir.x ); - m_vCurrentVelocity.y = ( decay * m_vCurrentVelocity.y + accelXY * targetDir.y ); - m_vCurrentVelocity.z = ( decay * m_vCurrentVelocity.z + accelZ * targetDir.z ); - } - - void MoveToLocation( float flInterval, const Vector &target, - float accelXY, float accelZ, float decay) - { - Vector targetDir = target - GetLocalOrigin(); - VectorNormalize(targetDir); - - MoveInDirection(flInterval, targetDir, accelXY, accelZ, decay); - } - - void Decelerate( float flInterval, float decay ) - { - decay *= flInterval; - m_vCurrentVelocity.x = (decay * m_vCurrentVelocity.x); - m_vCurrentVelocity.y = (decay * m_vCurrentVelocity.y); - m_vCurrentVelocity.z = (decay * m_vCurrentVelocity.z); - } - - void AddNoiseToVelocity( float noiseScale = 1.0 ) - { - if( m_vNoiseMod.x ) - { - m_vCurrentVelocity.x += noiseScale*sin(m_vNoiseMod.x * gpGlobals->curtime + m_vNoiseMod.x); - } - - if( m_vNoiseMod.y ) - { - m_vCurrentVelocity.y += noiseScale*cos(m_vNoiseMod.y * gpGlobals->curtime + m_vNoiseMod.y); - } - - if( m_vNoiseMod.z ) - { - m_vCurrentVelocity.z -= noiseScale*cos(m_vNoiseMod.z * gpGlobals->curtime + m_vNoiseMod.z); - } - } - - void LimitSpeed( float zLimit, float maxSpeed = -1 ) - { - if ( maxSpeed == -1 ) - maxSpeed = m_flSpeed; - if (m_vCurrentVelocity.Length() > maxSpeed) - { - VectorNormalize(m_vCurrentVelocity); - m_vCurrentVelocity *= maxSpeed; - } - // Limit fall speed - if (zLimit > 0 && m_vCurrentVelocity.z < -zLimit) - { - m_vCurrentVelocity.z = -zLimit; - } - } - - AI_NavPathProgress_t ProgressFlyPath( float flInterval, - const CBaseEntity *pNewTarget, - unsigned collisionMask, - bool bNewTrySimplify = true, - float strictPointTolerance = 32.0 ); - - const Vector &GetCurrentVelocity() const { return m_vCurrentVelocity; } - void SetCurrentVelocity(const Vector &vNewVel) { m_vCurrentVelocity = vNewVel; } - - const Vector &GetNoiseMod() const { return m_vNoiseMod; } - void SetNoiseMod( float x, float y, float z ) { m_vNoiseMod.Init( x, y, z ); } - void SetNoiseMod( const Vector &noise ) { m_vNoiseMod = noise; } - - void TranslateNavGoal( CBaseEntity *pTarget, Vector &chasePosition ); - - virtual void MoveToTarget(float flInterval, const Vector &MoveTarget) = 0; - - virtual float GetHeadTurnRate( void ) { return 15.0f; } // Degrees per second - - bool CreateVPhysics( void ); - IMotionEvent::simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ); - - virtual void ClampMotorForces( Vector &linear, AngularImpulse &angular ) - { - // limit reaction forces - linear.x = clamp( linear.x, -3000, 3000 ); - linear.y = clamp( linear.y, -3000, 3000 ); - linear.z = clamp( linear.z, -3000, 3000 ); - - // add in weightlessness - linear.z += 800; - } - - // ------------------------------- - // Movement vars - // ------------------------------- - Vector m_vCurrentVelocity; - Vector m_vCurrentBanking; - Vector m_vNoiseMod; - float m_fHeadYaw; - Vector m_vLastPatrolDir; - IPhysicsMotionController *m_pMotionController; -}; - -#endif // AI_BASENPC_PHYSICSFLYER_H diff --git a/game/server/ai_basenpc_schedule.cpp b/game/server/ai_basenpc_schedule.cpp deleted file mode 100644 index 3b9196869..000000000 --- a/game/server/ai_basenpc_schedule.cpp +++ /dev/null @@ -1,4765 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Functions and data pertaining to the NPCs' AI scheduling system. -// Implements default NPC tasks and schedules. -// -//=============================================================================// - - -#include "cbase.h" -#include "ai_default.h" -#include "animation.h" -#include "scripted.h" -#include "soundent.h" -#include "entitylist.h" -#include "basecombatweapon.h" -#include "bitstring.h" -#include "ai_task.h" -#include "ai_network.h" -#include "ai_schedule.h" -#include "ai_hull.h" -#include "ai_node.h" -#include "ai_motor.h" -#include "ai_hint.h" -#include "ai_memory.h" -#include "ai_navigator.h" -#include "ai_tacticalservices.h" -#include "ai_moveprobe.h" -#include "ai_squadslot.h" -#include "ai_squad.h" -#include "ai_speech.h" -#include "game.h" -#include "IEffects.h" -#include "vstdlib/random.h" -#include "ndebugoverlay.h" -#include "tier0/vcrmode.h" -#include "env_debughistory.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern ConVar ai_task_pre_script; -extern ConVar ai_use_efficiency; -extern ConVar ai_use_think_optimizations; -#define ShouldUseEfficiency() ( ai_use_think_optimizations.GetBool() && ai_use_efficiency.GetBool() ) - -ConVar ai_simulate_task_overtime( "ai_simulate_task_overtime", "0" ); - -#define MAX_TASKS_RUN 10 - -struct TaskTimings -{ - const char *pszTask; - CFastTimer selectSchedule; - CFastTimer startTimer; - CFastTimer runTimer; -}; - -TaskTimings g_AITaskTimings[MAX_TASKS_RUN]; -int g_nAITasksRun; - -void CAI_BaseNPC::DumpTaskTimings() -{ - DevMsg(" Tasks timings:\n" ); - for ( int i = 0; i < g_nAITasksRun; ++i ) - { - DevMsg( " %32s -- select %5.2f, start %5.2f, run %5.2f\n", g_AITaskTimings[i].pszTask, - g_AITaskTimings[i].selectSchedule.GetDuration().GetMillisecondsF(), - g_AITaskTimings[i].startTimer.GetDuration().GetMillisecondsF(), - g_AITaskTimings[i].runTimer.GetDuration().GetMillisecondsF() ); - - } -} - - -//========================================================= -// FHaveSchedule - Returns true if NPC's GetCurSchedule() -// is anything other than NULL. -//========================================================= -bool CAI_BaseNPC::FHaveSchedule( void ) -{ - if ( GetCurSchedule() == NULL ) - { - return false; - } - - return true; -} - -//========================================================= -// ClearSchedule - blanks out the caller's schedule pointer -// and index. -//========================================================= -void CAI_BaseNPC::ClearSchedule( const char *szReason ) -{ - if (szReason && m_debugOverlays & OVERLAY_TASK_TEXT_BIT) - { - DevMsg( this, AIMF_IGNORE_SELECTED, " Schedule cleared: %s\n", szReason ); - } - - if ( szReason ) - { - ADD_DEBUG_HISTORY( HISTORY_AI_DECISIONS, UTIL_VarArgs( "%s(%d): Schedule cleared: %s\n", GetDebugName(), entindex(), szReason ) ); - } - - m_ScheduleState.timeCurTaskStarted = m_ScheduleState.timeStarted = 0; - m_ScheduleState.bScheduleWasInterrupted = true; - SetTaskStatus( TASKSTATUS_NEW ); - m_IdealSchedule = SCHED_NONE; - m_pSchedule = NULL; - ResetScheduleCurTaskIndex(); - m_InverseIgnoreConditions.SetAll(); -} - -//========================================================= -// FScheduleDone - Returns true if the caller is on the -// last task in the schedule -//========================================================= -bool CAI_BaseNPC::FScheduleDone ( void ) -{ - Assert( GetCurSchedule() != NULL ); - - if ( GetScheduleCurTaskIndex() == GetCurSchedule()->NumTasks() ) - { - return true; - } - - return false; -} - -//========================================================= - -bool CAI_BaseNPC::SetSchedule( int localScheduleID ) -{ - CAI_Schedule *pNewSchedule = GetScheduleOfType( localScheduleID ); - if ( pNewSchedule ) - { - // ken: I'm don't know of any remaining cases, but if you find one, hunt it down as to why the schedule is getting slammed while they're in the middle of script - if (m_hCine != NULL) - { - if (!(localScheduleID == SCHED_SLEEP || localScheduleID == SCHED_WAIT_FOR_SCRIPT || localScheduleID == SCHED_SCRIPTED_WALK || localScheduleID == SCHED_SCRIPTED_RUN || localScheduleID == SCHED_SCRIPTED_CUSTOM_MOVE || localScheduleID == SCHED_SCRIPTED_WAIT || localScheduleID == SCHED_SCRIPTED_FACE) ) - { - Assert( 0 ); - // ExitScriptedSequence(); - } - } - - - m_IdealSchedule = GetGlobalScheduleId( localScheduleID ); - SetSchedule( pNewSchedule ); - return true; - } - return false; -} - -//========================================================= -// SetSchedule - replaces the NPC's schedule pointer -// with the passed pointer, and sets the ScheduleIndex back -// to 0 -//========================================================= -#define SCHEDULE_HISTORY_SIZE 10 -void CAI_BaseNPC::SetSchedule( CAI_Schedule *pNewSchedule ) -{ - Assert( pNewSchedule != NULL ); - - m_ScheduleState.timeCurTaskStarted = m_ScheduleState.timeStarted = gpGlobals->curtime; - m_ScheduleState.bScheduleWasInterrupted = false; - - m_pSchedule = pNewSchedule ; - ResetScheduleCurTaskIndex(); - SetTaskStatus( TASKSTATUS_NEW ); - m_failSchedule = SCHED_NONE; - bool bCondInPVS = HasCondition( COND_IN_PVS ); - m_Conditions.ClearAll(); - if ( bCondInPVS ) - SetCondition( COND_IN_PVS ); - m_bConditionsGathered = false; - GetNavigator()->ClearGoal(); - m_InverseIgnoreConditions.SetAll(); - Forget( bits_MEMORY_TURNING ); - -/* -#if _DEBUG - if ( !ScheduleFromName( pNewSchedule->GetName() ) ) - { - DevMsg( "Schedule %s not in table!!!\n", pNewSchedule->GetName() ); - } -#endif -*/ -// this is very useful code if you can isolate a test case in a level with a single NPC. It will notify -// you of every schedule selection the NPC makes. - - if (m_debugOverlays & OVERLAY_TASK_TEXT_BIT) - { - DevMsg(this, AIMF_IGNORE_SELECTED, "Schedule: %s (time: %.2f)\n", pNewSchedule->GetName(), gpGlobals->curtime ); - } - - ADD_DEBUG_HISTORY( HISTORY_AI_DECISIONS, UTIL_VarArgs("%s(%d): Schedule: %s (time: %.2f)\n", GetDebugName(), entindex(), pNewSchedule->GetName(), gpGlobals->curtime ) ); - -#ifdef AI_MONITOR_FOR_OSCILLATION - if( m_bSelected ) - { - AIScheduleChoice_t choice; - choice.m_flTimeSelected = gpGlobals->curtime; - choice.m_pScheduleSelected = pNewSchedule; - m_ScheduleHistory.AddToHead(choice); - - if( m_ScheduleHistory.Count() > SCHEDULE_HISTORY_SIZE ) - { - m_ScheduleHistory.Remove( SCHEDULE_HISTORY_SIZE ); - } - - assert( m_ScheduleHistory.Count() <= SCHEDULE_HISTORY_SIZE ); - - // No analysis until the vector is full! - if( m_ScheduleHistory.Count() == SCHEDULE_HISTORY_SIZE ) - { - int iNumSelections = m_ScheduleHistory.Count(); - float flTimeSpan = m_ScheduleHistory.Head().m_flTimeSelected - m_ScheduleHistory.Tail().m_flTimeSelected; - float flSelectionsPerSecond = ((float)iNumSelections) / flTimeSpan; - - Msg( "%d selections in %f seconds (avg. %f selections per second)\n", iNumSelections, flTimeSpan, flSelectionsPerSecond ); - - if( flSelectionsPerSecond >= 8.0f ) - { - DevMsg("\n\n %s is thrashing schedule selection:\n", GetDebugName() ); - - for( int i = 0 ; i < m_ScheduleHistory.Count() ; i++ ) - { - AIScheduleChoice_t choice = m_ScheduleHistory[i]; - Msg("--%s %f\n", choice.m_pScheduleSelected->GetName(), choice.m_flTimeSelected ); - } - - Msg("\n"); - - CAI_BaseNPC::m_nDebugBits |= bits_debugDisableAI; - } - } - } -#endif//AI_MONITOR_FOR_OSCILLATION -} - -//========================================================= -// NextScheduledTask - increments the ScheduleIndex -//========================================================= -void CAI_BaseNPC::NextScheduledTask ( void ) -{ - Assert( GetCurSchedule() != NULL ); - - SetTaskStatus( TASKSTATUS_NEW ); - IncScheduleCurTaskIndex(); - - if ( FScheduleDone() ) - { - // Reset memory of failed schedule - m_failedSchedule = NULL; - m_interuptSchedule = NULL; - - // just completed last task in schedule, so make it invalid by clearing it. - SetCondition( COND_SCHEDULE_DONE ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: This function allows NPCs to modify the interrupt mask for the -// current schedule. This enables them to use base schedules but with -// different interrupt conditions. Implement this function in your -// derived class, and Set or Clear condition bits as you please. -// -// NOTE: Always call the base class in your implementation, but be -// aware of the difference between changing the bits before vs. -// changing the bits after calling the base implementation. -// -// Input : pBitString - Receives the updated interrupt mask. -//----------------------------------------------------------------------------- -void CAI_BaseNPC::BuildScheduleTestBits( void ) -{ - //NOTENOTE: Always defined in the leaf classes -} - - -//========================================================= -// IsScheduleValid - returns true as long as the current -// schedule is still the proper schedule to be executing, -// taking into account all conditions -//========================================================= -bool CAI_BaseNPC::IsScheduleValid() -{ - if ( GetCurSchedule() == NULL || GetCurSchedule()->NumTasks() == 0 ) - { - return false; - } - - //Start out with the base schedule's set interrupt conditions - GetCurSchedule()->GetInterruptMask( &m_CustomInterruptConditions ); - - // Let the leaf class modify our interrupt test bits, but: - // - Don't allow any modifications when scripted - // - Don't modify interrupts for Schedules that set the COND_NO_CUSTOM_INTERRUPTS bit. - if ( m_NPCState != NPC_STATE_SCRIPT && !IsInLockedScene() && !m_CustomInterruptConditions.IsBitSet( COND_NO_CUSTOM_INTERRUPTS ) ) - { - BuildScheduleTestBits(); - } - - //Any conditions set here will always be forced on the interrupt conditions - SetCustomInterruptCondition( COND_NPC_FREEZE ); - - // This is like: m_CustomInterruptConditions &= m_Conditions; - CAI_ScheduleBits testBits; - m_CustomInterruptConditions.And( m_Conditions, &testBits ); - - if (!testBits.IsAllClear()) - { - // If in developer mode save the interrupt text for debug output - if (g_pDeveloper->GetInt()) - { - // Reset memory of failed schedule - m_failedSchedule = NULL; - m_interuptSchedule = GetCurSchedule(); - - // Find the first non-zero bit - for (int i=0;i %s\n", m_interruptText ); - } - - ADD_DEBUG_HISTORY( HISTORY_AI_DECISIONS, UTIL_VarArgs("%s(%d): Break condition -> %s\n", GetDebugName(), entindex(), m_interruptText ) ); - - break; - } - } - - if ( HasCondition( COND_NEW_ENEMY ) ) - { - if (m_debugOverlays & OVERLAY_TASK_TEXT_BIT) - { - DevMsg( this, AIMF_IGNORE_SELECTED, " New enemy: %s\n", GetEnemy() ? GetEnemy()->GetDebugName() : "" ); - } - - ADD_DEBUG_HISTORY( HISTORY_AI_DECISIONS, UTIL_VarArgs("%s(%d): New enemy: %s\n", GetDebugName(), entindex(), GetEnemy() ? GetEnemy()->GetDebugName() : "" ) ); - } - } - - return false; - } - - if ( HasCondition(COND_SCHEDULE_DONE) || - HasCondition(COND_TASK_FAILED) ) - { -#ifdef DEBUG - if ( HasCondition ( COND_TASK_FAILED ) && m_failSchedule == SCHED_NONE ) - { - // fail! Send a visual indicator. - DevWarning( 2, "Schedule: %s Failed\n", GetCurSchedule()->GetName() ); - - Vector tmp; - CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 1.0f ), &tmp ); - tmp.z += 16; - - g_pEffects->Sparks( tmp ); - } -#endif // DEBUG - - // some condition has interrupted the schedule, or the schedule is done - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Determines whether or not SelectIdealState() should be called before -// a NPC selects a new schedule. -// -// NOTE: This logic was a source of pure, distilled trouble in Half-Life. -// If you change this function, please supply good comments. -// -// Output : Returns true if yes, false if no -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::ShouldSelectIdealState( void ) -{ -/* - - HERE's the old Half-Life code that used to control this. - - if ( m_IdealNPCState != NPC_STATE_DEAD && - (m_IdealNPCState != NPC_STATE_SCRIPT || m_IdealNPCState == m_NPCState) ) - { - if ( (m_afConditions && !HasConditions(bits_COND_SCHEDULE_DONE)) || - (GetCurSchedule() && (GetCurSchedule()->iInterruptMask & bits_COND_SCHEDULE_DONE)) || - ((m_NPCState == NPC_STATE_COMBAT) && (GetEnemy() == NULL)) ) - { - GetIdealState(); - } - } -*/ - - // Don't get ideal state if you are supposed to be dead. - if ( m_IdealNPCState == NPC_STATE_DEAD ) - return false; - - // If I'm supposed to be in scripted state, but i'm not yet, do not allow - // SelectIdealState() to be called, because it doesn't know how to determine - // that a NPC should be in SCRIPT state and will stomp it with some other - // state. (Most likely ALERT) - if ( (m_IdealNPCState == NPC_STATE_SCRIPT) && (m_NPCState != NPC_STATE_SCRIPT) ) - return false; - - // If the NPC has any current conditions, and one of those conditions indicates - // that the previous schedule completed successfully, then don't run SelectIdealState(). - // Paths between states only exist for interrupted schedules, or when a schedule - // contains a task that suggests that the NPC change state. - if ( !HasCondition(COND_SCHEDULE_DONE) ) - return true; - - // This seems like some sort of hack... - // Currently no schedule that I can see in the AI uses this feature, but if a schedule - // interrupt mask contains bits_COND_SCHEDULE_DONE, then force a call to SelectIdealState(). - // If we want to keep this feature, I suggest we create a new condition with a name that - // indicates exactly what it does. - if ( GetCurSchedule() && GetCurSchedule()->HasInterrupt(COND_SCHEDULE_DONE) ) - return true; - - // Don't call SelectIdealState if a NPC in combat state has a valid enemy handle. Otherwise, - // we need to change state immediately because something unexpected happened to the enemy - // entity (it was blown apart by someone else, for example), and we need the NPC to change - // state. THE REST OF OUR CODE should be robust enough that this can go away!! - if ( (m_NPCState == NPC_STATE_COMBAT) && (GetEnemy() == NULL) ) - return true; - - if ( (m_NPCState == NPC_STATE_IDLE || m_NPCState == NPC_STATE_ALERT) && (GetEnemy() != NULL) ) - return true; - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns a new schedule based on current condition bits. -//----------------------------------------------------------------------------- -CAI_Schedule *CAI_BaseNPC::GetNewSchedule( void ) -{ - int scheduleType; - - // - // Schedule selection code here overrides all leaf schedule selection. - // - if (HasCondition(COND_NPC_FREEZE)) - { - scheduleType = SCHED_NPC_FREEZE; - } - else - { - // I dunno how this trend got started, but we need to find the problem. - // You may not be in combat state with no enemy!!! (sjb) 11/4/03 - if( m_NPCState == NPC_STATE_COMBAT && !GetEnemy() ) - { - DevMsg("**ERROR: Combat State with no enemy! slamming to ALERT\n"); - SetState( NPC_STATE_ALERT ); - } - - AI_PROFILE_SCOPE_BEGIN( CAI_BaseNPC_SelectSchedule); - - if ( m_NPCState == NPC_STATE_SCRIPT || m_NPCState == NPC_STATE_DEAD || m_iInteractionState == NPCINT_MOVING_TO_MARK ) - { - scheduleType = CAI_BaseNPC::SelectSchedule(); - } - else - { - scheduleType = SelectSchedule(); - } - - m_IdealSchedule = GetGlobalScheduleId( scheduleType ); - - AI_PROFILE_SCOPE_END(); - } - - return GetScheduleOfType( scheduleType ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CAI_Schedule *CAI_BaseNPC::GetFailSchedule( void ) -{ - int prevSchedule; - int failedTask; - - if ( GetCurSchedule() ) - prevSchedule = GetLocalScheduleId( GetCurSchedule()->GetId() ); - else - prevSchedule = SCHED_NONE; - - const Task_t *pTask = GetTask(); - if ( pTask ) - failedTask = pTask->iTask; - else - failedTask = TASK_INVALID; - - Assert( AI_IdIsLocal( prevSchedule ) ); - Assert( AI_IdIsLocal( failedTask ) ); - - int scheduleType = SelectFailSchedule( prevSchedule, failedTask, m_ScheduleState.taskFailureCode ); - return GetScheduleOfType( scheduleType ); -} - - -//========================================================= -// MaintainSchedule - does all the per-think schedule maintenance. -// ensures that the NPC leaves this function with a valid -// schedule! -//========================================================= - -static bool ShouldStopProcessingTasks( CAI_BaseNPC *pNPC, int taskTime, int timeLimit ) -{ -#ifdef DEBUG - if( ai_simulate_task_overtime.GetBool() ) - return true; -#endif - - // Always stop processing if we've queued up a navigation query on the last task - if ( pNPC->IsNavigationDeferred() ) - return true; - - if ( AIStrongOpt() ) - { - bool bInScript = ( pNPC->GetState() == NPC_STATE_SCRIPT || pNPC->IsCurSchedule( SCHED_SCENE_GENERIC, false ) ); - - // We ran a costly task, don't do it again! - if ( pNPC->HasMemory( bits_MEMORY_TASK_EXPENSIVE ) && bInScript == false ) - return true; - } - - if ( taskTime > timeLimit ) - { - if ( ShouldUseEfficiency() || - pNPC->IsMoving() || - ( pNPC->GetIdealActivity() != ACT_RUN && pNPC->GetIdealActivity() != ACT_WALK ) ) - { - return true; - } - } - return false; -} - -//------------------------------------- - -void CAI_BaseNPC::MaintainSchedule ( void ) -{ - AI_PROFILE_SCOPE(CAI_BaseNPC_RunAI_MaintainSchedule); - extern CFastTimer g_AIMaintainScheduleTimer; - CTimeScope timeScope(&g_AIMaintainScheduleTimer); - - //--------------------------------- - - CAI_Schedule *pNewSchedule; - int i; - bool runTask = true; - -#if defined( VPROF_ENABLED ) -#if defined(DISABLE_DEBUG_HISTORY) - bool bDebugTaskNames = ( developer.GetBool() || ( VProfAI() && g_VProfCurrentProfile.IsEnabled() ) ); -#else - bool bDebugTaskNames = true; -#endif -#else - bool bDebugTaskNames = false; -#endif - - memset( g_AITaskTimings, 0, sizeof(g_AITaskTimings) ); - - g_nAITasksRun = 0; - - const int timeLimit = ( IsDebug() ) ? 16 : 8; - int taskTime = Plat_MSTime(); - - // Reset this at the beginning of the frame - Forget( bits_MEMORY_TASK_EXPENSIVE ); - - // UNDONE: Tune/fix this MAX_TASKS_RUN... This is just here so infinite loops are impossible - bool bStopProcessing = false; - for ( i = 0; i < MAX_TASKS_RUN && !bStopProcessing; i++ ) - { - if ( GetCurSchedule() != NULL && TaskIsComplete() ) - { - // Schedule is valid, so advance to the next task if the current is complete. - NextScheduledTask(); - - // If we finished the current schedule, clear our ignored conditions so they - // aren't applied to the next schedule selection. - if ( HasCondition( COND_SCHEDULE_DONE ) ) - { - // Put our conditions back the way they were after GatherConditions, - // but add in COND_SCHEDULE_DONE. - m_Conditions = m_ConditionsPreIgnore; - SetCondition( COND_SCHEDULE_DONE ); - - m_InverseIgnoreConditions.SetAll(); - } - - // -------------------------------------------------------- - // If debug stepping advance when I complete a task - // -------------------------------------------------------- - if (CAI_BaseNPC::m_nDebugBits & bits_debugStepAI) - { - m_nDebugCurIndex++; - return; - } - } - - int curTiming = g_nAITasksRun; - g_nAITasksRun++; - - // validate existing schedule - if ( !IsScheduleValid() || m_NPCState != m_IdealNPCState ) - { - // Notify the NPC that his schedule is changing - m_ScheduleState.bScheduleWasInterrupted = true; - OnScheduleChange(); - - if ( !HasCondition(COND_NPC_FREEZE) && ( !m_bConditionsGathered || m_bSkippedChooseEnemy ) ) - { - // occurs if a schedule is exhausted within one think - GatherConditions(); - } - - if ( ShouldSelectIdealState() ) - { - NPC_STATE eIdealState = SelectIdealState(); - SetIdealState( eIdealState ); - } - - if ( HasCondition( COND_TASK_FAILED ) && m_NPCState == m_IdealNPCState ) - { - // Get a fail schedule if the previous schedule failed during execution and - // the NPC is still in its ideal state. Otherwise, the NPC would immediately - // select the same schedule again and fail again. - if (m_debugOverlays & OVERLAY_TASK_TEXT_BIT) - { - DevMsg( this, AIMF_IGNORE_SELECTED, " (failed)\n" ); - } - - ADD_DEBUG_HISTORY( HISTORY_AI_DECISIONS, UTIL_VarArgs("%s(%d): (failed)\n", GetDebugName(), entindex() ) ); - - pNewSchedule = GetFailSchedule(); - m_IdealSchedule = pNewSchedule->GetId(); - DevWarning( 2, "(%s) Schedule (%s) Failed at %d!\n", STRING( GetEntityName() ), GetCurSchedule() ? GetCurSchedule()->GetName() : "GetCurSchedule() == NULL", GetScheduleCurTaskIndex() ); - SetSchedule( pNewSchedule ); - } - else - { - // If the NPC is supposed to change state, it doesn't matter if the previous - // schedule failed or completed. Changing state means selecting an entirely new schedule. - SetState( m_IdealNPCState ); - - g_AITaskTimings[curTiming].selectSchedule.Start(); - - pNewSchedule = GetNewSchedule(); - - g_AITaskTimings[curTiming].selectSchedule.End(); - - SetSchedule( pNewSchedule ); - } - } - - if (!GetCurSchedule()) - { - g_AITaskTimings[curTiming].selectSchedule.Start(); - - pNewSchedule = GetNewSchedule(); - - g_AITaskTimings[curTiming].selectSchedule.End(); - - if (pNewSchedule) - { - SetSchedule( pNewSchedule ); - } - } - - if ( !GetCurSchedule() || GetCurSchedule()->NumTasks() == 0 ) - { - DevMsg("ERROR: Missing or invalid schedule!\n"); - SetActivity ( ACT_IDLE ); - return; - } - - AI_PROFILE_SCOPE_BEGIN_( CAI_BaseNPC::GetSchedulingSymbols()->ScheduleIdToSymbol( GetCurSchedule()->GetId() ) ); - - if ( GetTaskStatus() == TASKSTATUS_NEW ) - { - if ( GetScheduleCurTaskIndex() == 0 ) - { - int globalId = GetCurSchedule()->GetId(); - int localId = GetLocalScheduleId( globalId ); // if localId == -1, then it came from a behavior - OnStartSchedule( (localId != -1)? localId : globalId ); - } - - g_AITaskTimings[curTiming].startTimer.Start(); - const Task_t *pTask = GetTask(); - const char *pszTaskName = ( bDebugTaskNames ) ? TaskName( pTask->iTask ) : "ai_task"; - Assert( pTask != NULL ); - g_AITaskTimings[i].pszTask = pszTaskName; - - if (m_debugOverlays & OVERLAY_TASK_TEXT_BIT) - { - DevMsg(this, AIMF_IGNORE_SELECTED, " Task: %s\n", pszTaskName ); - } - - ADD_DEBUG_HISTORY( HISTORY_AI_DECISIONS, UTIL_VarArgs("%s(%d): Task: %s\n", GetDebugName(), entindex(), pszTaskName ) ); - - OnStartTask(); - - m_ScheduleState.taskFailureCode = NO_TASK_FAILURE; - m_ScheduleState.timeCurTaskStarted = gpGlobals->curtime; - - AI_PROFILE_SCOPE_BEGIN_( pszTaskName ); - AI_PROFILE_SCOPE_BEGIN(CAI_BaseNPC_StartTask); - - StartTask( pTask ); - - AI_PROFILE_SCOPE_END(); - AI_PROFILE_SCOPE_END(); - - if ( TaskIsRunning() && !HasCondition(COND_TASK_FAILED) ) - StartTaskOverlay(); - - g_AITaskTimings[curTiming].startTimer.End(); - // DevMsg( "%.2f StartTask( %s )\n", gpGlobals->curtime, m_pTaskSR->GetStringText( pTask->iTask ) ); - } - - AI_PROFILE_SCOPE_END(); - - // UNDONE: Twice?!!! - MaintainActivity(); - - AI_PROFILE_SCOPE_BEGIN_( CAI_BaseNPC::GetSchedulingSymbols()->ScheduleIdToSymbol( GetCurSchedule()->GetId() ) ); - - if ( !TaskIsComplete() && GetTaskStatus() != TASKSTATUS_NEW ) - { - if ( TaskIsRunning() && !HasCondition(COND_TASK_FAILED) && runTask ) - { - const Task_t *pTask = GetTask(); - const char *pszTaskName = ( bDebugTaskNames ) ? TaskName( pTask->iTask ) : "ai_task"; - Assert( pTask != NULL ); - g_AITaskTimings[i].pszTask = pszTaskName; - // DevMsg( "%.2f RunTask( %s )\n", gpGlobals->curtime, m_pTaskSR->GetStringText( pTask->iTask ) ); - g_AITaskTimings[curTiming].runTimer.Start(); - - AI_PROFILE_SCOPE_BEGIN_( pszTaskName ); - AI_PROFILE_SCOPE_BEGIN(CAI_BaseNPC_RunTask); - - int j; - for (j = 0; j < 8; j++) - { - RunTask( pTask ); - - if ( GetTaskInterrupt() == 0 || TaskIsComplete() || HasCondition(COND_TASK_FAILED) ) - break; - - if ( ShouldUseEfficiency() && ShouldStopProcessingTasks( this, Plat_MSTime() - taskTime, timeLimit ) ) - { - bStopProcessing = true; - break; - } - } - AssertMsg( j < 8, "Runaway task interrupt\n" ); - - AI_PROFILE_SCOPE_END(); - AI_PROFILE_SCOPE_END(); - - if ( TaskIsRunning() && !HasCondition(COND_TASK_FAILED) ) - { - if ( IsCurTaskContinuousMove() ) - Remember( bits_MEMORY_MOVED_FROM_SPAWN ); - RunTaskOverlay(); - } - - g_AITaskTimings[curTiming].runTimer.End(); - - // don't do this again this frame - // FIXME: RunTask() should eat some of the clock, depending on what it has done - // runTask = false; - - if ( !TaskIsComplete() ) - { - bStopProcessing = true; - } - } - else - { - bStopProcessing = true; - } - } - - AI_PROFILE_SCOPE_END(); - - // Decide if we should continue on this frame - if ( !bStopProcessing && ShouldStopProcessingTasks( this, Plat_MSTime() - taskTime, timeLimit ) ) - bStopProcessing = true; - } - - // UNDONE: We have to do this so that we have an animation set to blend to if RunTask changes the animation - // RunTask() will always change animations at the end of a script! - // Don't do this twice - MaintainActivity(); - - // -------------------------------------------------------- - // If I'm stopping to debug step, don't animate unless - // I'm in motion - // -------------------------------------------------------- - if (CAI_BaseNPC::m_nDebugBits & bits_debugStepAI) - { - if (!GetNavigator()->IsGoalActive() && - m_nDebugCurIndex >= CAI_BaseNPC::m_nDebugPauseIndex) - { - m_flPlaybackRate = 0; - } - } -} - - -//========================================================= - -bool CAI_BaseNPC::FindCoverPos( CBaseEntity *pEntity, Vector *pResult ) -{ - AI_PROFILE_SCOPE(CAI_BaseNPC_FindCoverPos); - - if ( !GetTacticalServices()->FindLateralCover( pEntity->EyePosition(), 0, pResult ) ) - { - if ( !GetTacticalServices()->FindCoverPos( pEntity->GetAbsOrigin(), pEntity->EyePosition(), 0, CoverRadius(), pResult ) ) - { - return false; - } - } - return true; -} - -//========================================================= - -bool CAI_BaseNPC::FindCoverPosInRadius( CBaseEntity *pEntity, const Vector &goalPos, float coverRadius, Vector *pResult ) -{ - AI_PROFILE_SCOPE(CAI_BaseNPC_FindCoverPosInRadius); - - if ( pEntity == NULL ) - { - // Find cover from self if no enemy available - pEntity = this; - } - - Vector coverPos = vec3_invalid; - CAI_TacticalServices * pTacticalServices = GetTacticalServices(); - const Vector & enemyPos = pEntity->GetAbsOrigin(); - Vector enemyEyePos = pEntity->EyePosition(); - - if( ( !GetSquad() || GetSquad()->GetFirstMember() == this ) && - IsCoverPosition( enemyEyePos, goalPos + GetViewOffset() ) && - IsValidCover( goalPos, NULL ) ) - { - coverPos = goalPos; - } - else if ( !pTacticalServices->FindCoverPos( goalPos, enemyPos, enemyEyePos, 0, coverRadius * 0.5, &coverPos ) ) - { - if ( !pTacticalServices->FindLateralCover( goalPos, enemyEyePos, 0, coverRadius * 0.5, 3, &coverPos ) ) - { - if ( !pTacticalServices->FindCoverPos( goalPos, enemyPos, enemyEyePos, coverRadius * 0.5 - 0.1, coverRadius, &coverPos ) ) - { - pTacticalServices->FindLateralCover( goalPos, enemyEyePos, 0, coverRadius, 5, &coverPos ); - } - } - } - - if ( coverPos == vec3_invalid ) - return false; - *pResult = coverPos; - return true; -} - -//========================================================= - -bool CAI_BaseNPC::FindCoverPos( CSound *pSound, Vector *pResult ) -{ - if ( !GetTacticalServices()->FindCoverPos( pSound->GetSoundReactOrigin(), - pSound->GetSoundReactOrigin(), - MIN( pSound->Volume(), 120.0 ), - CoverRadius(), - pResult ) ) - { - return GetTacticalServices()->FindLateralCover( pSound->GetSoundReactOrigin(), MIN( pSound->Volume(), 60.0 ), pResult ); - } - - return true; -} - -//========================================================= -// Start task - selects the correct activity and performs -// any necessary calculations to start the next task on the -// schedule. -//========================================================= - -//----------------------------------------------------------------------------- -// TASK_TURN_RIGHT / TASK_TURN_LEFT -//----------------------------------------------------------------------------- -void CAI_BaseNPC::StartTurn( float flDeltaYaw ) -{ - float flCurrentYaw; - - flCurrentYaw = UTIL_AngleMod( GetLocalAngles().y ); - GetMotor()->SetIdealYaw( UTIL_AngleMod( flCurrentYaw + flDeltaYaw ) ); - SetTurnActivity(); -} - - -//----------------------------------------------------------------------------- -// TASK_CLEAR_HINTNODE -//----------------------------------------------------------------------------- -void CAI_BaseNPC::ClearHintNode( float reuseDelay ) -{ - if ( m_pHintNode ) - { - if ( m_pHintNode->IsLockedBy(this) ) - m_pHintNode->Unlock(reuseDelay); - m_pHintNode = NULL; - } -} - - -void CAI_BaseNPC::SetHintNode( CAI_Hint *pHintNode ) -{ - m_pHintNode = pHintNode; -} - - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::FindCoverFromEnemy( bool bNodesOnly, float flMinDistance, float flMaxDistance ) -{ - CBaseEntity *pEntity = GetEnemy(); - - // Find cover from self if no enemy available - if ( pEntity == NULL ) - pEntity = this; - - Vector coverPos = vec3_invalid; - - ClearHintNode(); - - if ( bNodesOnly ) - { - if ( flMaxDistance == FLT_MAX ) - flMaxDistance = CoverRadius(); - - if ( !GetTacticalServices()->FindCoverPos( pEntity->GetAbsOrigin(), pEntity->EyePosition(), flMinDistance, flMaxDistance, &coverPos ) ) - return false; - } - else - { - if ( !FindCoverPos( pEntity, &coverPos ) ) - return false; - } - - AI_NavGoal_t goal( GOALTYPE_COVER, coverPos, ACT_RUN, AIN_HULL_TOLERANCE ); - - if ( !GetNavigator()->SetGoal( goal ) ) - return false; - - // FIXME: add to goal - if (GetHintNode()) - { - GetNavigator()->SetArrivalActivity( GetCoverActivity( GetHintNode() ) ); - GetNavigator()->SetArrivalDirection( GetHintNode()->GetDirection() ); - } - - return true; -} - - -//----------------------------------------------------------------------------- -// TASK_FIND_COVER_FROM_BEST_SOUND -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::FindCoverFromBestSound( Vector *pCoverPos ) -{ - CSound *pBestSound; - - pBestSound = GetBestSound(); - - if (pBestSound) - { - // UNDONE: Back away if cover fails? Grunts do this. - return FindCoverPos( pBestSound, pCoverPos ); - } - else - { - DevMsg( 2, "Attempting to find cover from best sound, but best sound not founc.\n" ); - } - - return false; -} - - -//----------------------------------------------------------------------------- -// TASK_FACE_REASONABLE -//----------------------------------------------------------------------------- -float CAI_BaseNPC::CalcReasonableFacing( bool bIgnoreOriginalFacing ) -{ - float flReasonableYaw; - - if( !bIgnoreOriginalFacing && !HasMemory( bits_MEMORY_MOVED_FROM_SPAWN ) && !HasCondition( COND_SEE_ENEMY) ) - { - flReasonableYaw = m_flOriginalYaw; - } - else - { - // If I'm facing a wall, change my original yaw and try to find a good direction to face. - trace_t tr; - Vector forward; - QAngle angles( 0, 0, 0 ); - - float idealYaw = GetMotor()->GetIdealYaw(); - - flReasonableYaw = idealYaw; - - // Try just using the facing we have - const float MIN_DIST = GetReasonableFacingDist(); - float longestTrace = 0; - - // Early out if we're overriding reasonable facing - if ( !MIN_DIST ) - return flReasonableYaw; - - // Otherwise, scan out back and forth until something better is found - const float SLICES = 8.0f; - const float SIZE_SLICE = 360.0 / SLICES; - const int SEARCH_MAX = (int)SLICES / 2; - - float zEye = GetAbsOrigin().z + m_vDefaultEyeOffset.z; // always use standing eye so as to not screw with crouch cover - - for( int i = 0 ; i <= SEARCH_MAX; i++ ) - { - float offset = i * SIZE_SLICE; - for ( int j = -1; j <= 1; j += 2) - { - angles.y = idealYaw + ( offset * j ); - AngleVectors( angles, &forward, NULL, NULL ); - float curTrace; - if( ( curTrace = LineOfSightDist( forward, zEye ) ) > longestTrace && IsValidReasonableFacing(forward, curTrace) ) - { - // Take this one. - flReasonableYaw = angles.y; - longestTrace = curTrace; - } - - if ( longestTrace > MIN_DIST) // found one - break; - - if ( i == 0 || i == SEARCH_MAX) // if trying forwards or backwards, skip the check of the other side... - break; - } - - if ( longestTrace > MIN_DIST ) // found one - break; - } - } - - return flReasonableYaw; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -float CAI_BaseNPC::GetReasonableFacingDist( void ) -{ - if ( GetTask() && GetTask()->iTask == TASK_FACE_ENEMY ) - { - const float dist = 3.5*12; - if ( GetEnemy() ) - { - float distEnemy = ( GetEnemy()->GetAbsOrigin().AsVector2D() - GetAbsOrigin().AsVector2D() ).Length() - 1.0; - return MIN( distEnemy, dist ); - } - - return dist; - } - return 5*12; -} - -//----------------------------------------------------------------------------- -// TASK_SCRIPT_RUN_TO_TARGET / TASK_SCRIPT_WALK_TO_TARGET / TASK_SCRIPT_CUSTOM_MOVE_TO_TARGET -//----------------------------------------------------------------------------- -void CAI_BaseNPC::StartScriptMoveToTargetTask( int task ) -{ - Activity newActivity; - - if ( m_hTargetEnt == NULL) - { - TaskFail(FAIL_NO_TARGET); - } - else if ( (m_hTargetEnt->GetAbsOrigin() - GetLocalOrigin()).Length() < 1 ) - { - TaskComplete(); - } - else - { - // - // Select the appropriate activity. - // - if ( task == TASK_SCRIPT_WALK_TO_TARGET ) - { - newActivity = ACT_WALK; - } - else if ( task == TASK_SCRIPT_RUN_TO_TARGET ) - { - newActivity = ACT_RUN; - } - else - { - newActivity = GetScriptCustomMoveActivity(); - } - - if ( ( newActivity != ACT_SCRIPT_CUSTOM_MOVE ) && TranslateActivity( newActivity ) == ACT_INVALID ) - { - // This NPC can't do this! - Assert( 0 ); - } - else - { - if (m_hTargetEnt == NULL) - { - TaskFail(FAIL_NO_TARGET); - } - else - { - - AI_NavGoal_t goal( GOALTYPE_TARGETENT, newActivity ); - - if ( GetState() == NPC_STATE_SCRIPT && - ( m_ScriptArrivalActivity != AIN_DEF_ACTIVITY || - m_strScriptArrivalSequence != NULL_STRING ) ) - { - if ( m_ScriptArrivalActivity != AIN_DEF_ACTIVITY ) - { - goal.arrivalActivity = m_ScriptArrivalActivity; - } - else - { - goal.arrivalSequence = LookupSequence( m_strScriptArrivalSequence.ToCStr() ); - } - } - - if (!GetNavigator()->SetGoal( goal, AIN_DISCARD_IF_FAIL )) - { - if ( GetNavigator()->GetNavFailCounter() == 0 ) - { - // no path was built, but OnNavFailed() did something so that next time it may work - DevWarning("%s %s failed Urgent Movement, retrying\n", GetDebugName(), TaskName( task ) ); - return; - } - - // FIXME: scripted sequences don't actually know how to handle failure, but we're failing. This is serious - DevWarning("%s %s failed Urgent Movement, abandoning schedule\n", GetDebugName(), TaskName( task ) ); - TaskFail(FAIL_NO_ROUTE); - } - else - { - GetNavigator()->SetArrivalDirection( m_hTargetEnt->GetAbsAngles() ); - } - } - } - } - - m_ScriptArrivalActivity = AIN_DEF_ACTIVITY; - m_strScriptArrivalSequence = NULL_STRING; - - TaskComplete(); -} - - -//----------------------------------------------------------------------------- -// Start task! -//----------------------------------------------------------------------------- -void CAI_BaseNPC::StartTask( const Task_t *pTask ) -{ - int task = pTask->iTask; - switch ( pTask->iTask ) - { - case TASK_RESET_ACTIVITY: - m_Activity = ACT_RESET; - TaskComplete(); - break; - - case TASK_CREATE_PENDING_WEAPON: - Assert( m_iszPendingWeapon != NULL_STRING ); - GiveWeapon( m_iszPendingWeapon ); - m_iszPendingWeapon = NULL_STRING; - TaskComplete(); - break; - - case TASK_RANDOMIZE_FRAMERATE: - { - float newRate = GetPlaybackRate(); - float percent = pTask->flTaskData / 100.0f; - - newRate += ( newRate * random->RandomFloat(-percent, percent) ); - - SetPlaybackRate(newRate); - - TaskComplete(); - } - break; - - case TASK_DEFER_DODGE: - m_flNextDodgeTime = gpGlobals->curtime + pTask->flTaskData; - TaskComplete(); - break; - - // Default case just completes. Override in sub-classes - // to play sound / animation / or pause - case TASK_ANNOUNCE_ATTACK: - TaskComplete(); - break; - - case TASK_TURN_RIGHT: - StartTurn( -pTask->flTaskData ); - break; - - case TASK_TURN_LEFT: - StartTurn( pTask->flTaskData ); - break; - - case TASK_REMEMBER: - Remember ( (int)pTask->flTaskData ); - TaskComplete(); - break; - - case TASK_FORGET: - Forget ( (int)pTask->flTaskData ); - TaskComplete(); - break; - - case TASK_FIND_HINTNODE: - case TASK_FIND_LOCK_HINTNODE: - { - if (!GetHintNode()) - { - SetHintNode( CAI_HintManager::FindHint( this, HINT_NONE, (int)pTask->flTaskData, 2000 ) ); - } - if (GetHintNode()) - { - TaskComplete(); - } - else - { - TaskFail(FAIL_NO_HINT_NODE); - } - if ( task == TASK_FIND_HINTNODE ) - break; - } - // Fall through on TASK_FIND_LOCK_HINTNODE... - - case TASK_LOCK_HINTNODE: - { - if (!GetHintNode()) - { - TaskFail(FAIL_NO_HINT_NODE); - } - else if( GetHintNode()->Lock(this) ) - { - TaskComplete(); - } - else - { - TaskFail(FAIL_ALREADY_LOCKED); - SetHintNode( NULL ); - } - break; - } - - case TASK_STORE_LASTPOSITION: - m_vecLastPosition = GetLocalOrigin(); - TaskComplete(); - break; - - case TASK_CLEAR_LASTPOSITION: - m_vecLastPosition = vec3_origin; - TaskComplete(); - break; - - case TASK_STORE_POSITION_IN_SAVEPOSITION: - m_vSavePosition = GetLocalOrigin(); - TaskComplete(); - break; - - case TASK_STORE_BESTSOUND_IN_SAVEPOSITION: - { - CSound *pBestSound = GetBestSound(); - if ( pBestSound ) - { - m_vSavePosition = pBestSound->GetSoundOrigin(); - CBaseEntity *pSoundEnt = pBestSound->m_hOwner; - if ( pSoundEnt ) - { - Vector vel; - pSoundEnt->GetVelocity( &vel, NULL ); - // HACKHACK: run away from cars in the right direction - m_vSavePosition += vel * 2; // add in 2 seconds of velocity - } - TaskComplete(); - } - else - { - TaskFail("No Sound!"); - return; - } - } - break; - - case TASK_STORE_BESTSOUND_REACTORIGIN_IN_SAVEPOSITION: - { - CSound *pBestSound = GetBestSound(); - if ( pBestSound ) - { - m_vSavePosition = pBestSound->GetSoundReactOrigin(); - TaskComplete(); - } - else - { - TaskFail("No Sound!"); - return; - } - } - break; - - case TASK_STORE_ENEMY_POSITION_IN_SAVEPOSITION: - if ( GetEnemy() != NULL ) - { - m_vSavePosition = GetEnemy()->GetAbsOrigin(); - TaskComplete(); - } - else - { - TaskFail(FAIL_NO_ENEMY); - } - break; - - case TASK_CLEAR_HINTNODE: - ClearHintNode(pTask->flTaskData); - TaskComplete(); - break; - - case TASK_STOP_MOVING: - if ( ( GetNavigator()->IsGoalSet() && GetNavigator()->IsGoalActive() ) || GetNavType() == NAV_JUMP ) - { - DbgNavMsg( this, "Start TASK_STOP_MOVING\n" ); - if ( pTask->flTaskData == 1 ) - { - DbgNavMsg( this, "Initiating stopping path\n" ); - GetNavigator()->StopMoving( false ); - } - else - { - GetNavigator()->ClearGoal(); - } - - // E3 Hack - if ( HasPoseMoveYaw() ) - { - SetPoseParameter( m_poseMove_Yaw, 0 ); - } - } - else - { - if ( pTask->flTaskData == 1 && GetNavigator()->SetGoalFromStoppingPath() ) - { - DbgNavMsg( this, "Start TASK_STOP_MOVING\n" ); - DbgNavMsg( this, "Initiating stopping path\n" ); - } - else - { - GetNavigator()->ClearGoal(); - SetIdealActivity( GetStoppedActivity() ); - TaskComplete(); - } - } - break; - - case TASK_PLAY_PRIVATE_SEQUENCE: - case TASK_PLAY_PRIVATE_SEQUENCE_FACE_ENEMY: - case TASK_PLAY_SEQUENCE_FACE_ENEMY: - case TASK_PLAY_SEQUENCE_FACE_TARGET: - case TASK_PLAY_SEQUENCE: - SetIdealActivity( (Activity)(int)pTask->flTaskData ); - break; - - case TASK_ADD_GESTURE_WAIT: - { - int iLayer = AddGesture( (Activity)(int)pTask->flTaskData ); - if (iLayer > 0) - { - float flDuration = GetLayerDuration( iLayer ); - SetWait( flDuration ); - } - else - { - TaskFail( "Unable to allocate gesture" ); - } - break; - } - - case TASK_ADD_GESTURE: - { - AddGesture( (Activity)(int)pTask->flTaskData ); - TaskComplete(); - break; - } - - case TASK_PLAY_HINT_ACTIVITY: - if ( GetHintNode()->HintActivityName() != NULL_STRING ) - { - Activity hintActivity = (Activity)CAI_BaseNPC::GetActivityID( STRING(GetHintNode()->HintActivityName()) ); - if ( hintActivity != ACT_INVALID ) - { - SetIdealActivity( GetHintActivity(GetHintNode()->HintType(), hintActivity) ); - } - else - { - int iSequence = LookupSequence(STRING(GetHintNode()->HintActivityName())); - if ( iSequence > ACT_INVALID ) - { - SetSequenceById( iSequence ); // ??? - SetIdealActivity( ACT_DO_NOT_DISTURB ); - } - else - SetIdealActivity( ACT_IDLE ); - } - } - else - { - SetIdealActivity( ACT_IDLE ); - } - break; - - case TASK_SET_SCHEDULE: - if ( !SetSchedule( (int)pTask->flTaskData ) ) - TaskFail(FAIL_SCHEDULE_NOT_FOUND); - break; - - case TASK_FIND_BACKAWAY_FROM_SAVEPOSITION: - { - if ( GetEnemy() != NULL ) - { - Vector backPos; - if ( !GetTacticalServices()->FindBackAwayPos( m_vSavePosition, &backPos ) ) - { - // no place to backaway - TaskFail(FAIL_NO_BACKAWAY_NODE); - } - else - { - if (GetNavigator()->SetGoal( AI_NavGoal_t( backPos, ACT_RUN ) ) ) - { - TaskComplete(); - } - else - { - // no place to backaway - TaskFail(FAIL_NO_ROUTE); - } - } - } - else - { - TaskFail(FAIL_NO_ENEMY); - } - } - break; - - case TASK_FIND_NEAR_NODE_COVER_FROM_ENEMY: - case TASK_FIND_FAR_NODE_COVER_FROM_ENEMY: - case TASK_FIND_NODE_COVER_FROM_ENEMY: - case TASK_FIND_COVER_FROM_ENEMY: - { - bool bNodeCover = ( task != TASK_FIND_COVER_FROM_ENEMY ); - float flMinDistance = ( task == TASK_FIND_FAR_NODE_COVER_FROM_ENEMY ) ? pTask->flTaskData : 0.0; - float flMaxDistance = ( task == TASK_FIND_NEAR_NODE_COVER_FROM_ENEMY ) ? pTask->flTaskData : FLT_MAX; - - if ( FindCoverFromEnemy( bNodeCover, flMinDistance, flMaxDistance ) ) - { - if ( task == TASK_FIND_COVER_FROM_ENEMY ) - m_flMoveWaitFinished = gpGlobals->curtime + pTask->flTaskData; - TaskComplete(); - } - else - TaskFail(FAIL_NO_COVER); - } - break; - - - case TASK_FIND_COVER_FROM_ORIGIN: - { - Vector coverPos; - - if ( GetTacticalServices()->FindCoverPos( GetLocalOrigin(), EyePosition(), 0, CoverRadius(), &coverPos ) ) - { - AI_NavGoal_t goal(coverPos, ACT_RUN, AIN_HULL_TOLERANCE); - GetNavigator()->SetGoal( goal ); - - m_flMoveWaitFinished = gpGlobals->curtime + pTask->flTaskData; - } - else - { - // no coverwhatsoever. - TaskFail(FAIL_NO_COVER); - } - } - - break; - - case TASK_FIND_COVER_FROM_BEST_SOUND: - { - } - break; - - case TASK_FACE_HINTNODE: - - // If the yaw is locked, this function will not act correctly - Assert( GetMotor()->IsYawLocked() == false ); - - GetMotor()->SetIdealYaw( GetHintNode()->Yaw() ); - GetMotor()->SetIdealYaw( CalcReasonableFacing( true ) ); // CalcReasonableFacing() is based on previously set ideal yaw - if ( FacingIdeal() ) - TaskComplete(); - else - SetTurnActivity(); - break; - - case TASK_FACE_LASTPOSITION: - GetMotor()->SetIdealYawToTarget( m_vecLastPosition ); - GetMotor()->SetIdealYaw( CalcReasonableFacing( true ) ); // CalcReasonableFacing() is based on previously set ideal yaw - SetTurnActivity(); - break; - - case TASK_FACE_SAVEPOSITION: - GetMotor()->SetIdealYawToTarget( m_vSavePosition ); - GetMotor()->SetIdealYaw( CalcReasonableFacing( true ) ); // CalcReasonableFacing() is based on previously set ideal yaw - SetTurnActivity(); - break; - - case TASK_FACE_AWAY_FROM_SAVEPOSITION: - GetMotor()->SetIdealYawToTarget( m_vSavePosition, 0, 180.0 ); - GetMotor()->SetIdealYaw( CalcReasonableFacing( true ) ); // CalcReasonableFacing() is based on previously set ideal yaw - SetTurnActivity(); - break; - - case TASK_SET_IDEAL_YAW_TO_CURRENT: - GetMotor()->SetIdealYaw( UTIL_AngleMod( GetLocalAngles().y ) ); - TaskComplete(); - break; - - case TASK_FACE_TARGET: - if ( m_hTargetEnt != NULL ) - { - GetMotor()->SetIdealYawToTarget( m_hTargetEnt->GetAbsOrigin() ); - SetTurnActivity(); - } - else - { - TaskFail(FAIL_NO_TARGET); - } - break; - - case TASK_FACE_PLAYER: - // track head to the client for a while. - SetWait( pTask->flTaskData ); - break; - - case TASK_FACE_ENEMY: - { - Vector vecEnemyLKP = GetEnemyLKP(); - if (!FInAimCone( vecEnemyLKP )) - { - GetMotor()->SetIdealYawToTarget( vecEnemyLKP ); - GetMotor()->SetIdealYaw( CalcReasonableFacing( true ) ); // CalcReasonableFacing() is based on previously set ideal yaw - SetTurnActivity(); - } - else - { - float flReasonableFacing = CalcReasonableFacing( true ); - if ( fabsf( flReasonableFacing - GetMotor()->GetIdealYaw() ) < 1 ) - TaskComplete(); - else - { - GetMotor()->SetIdealYaw( flReasonableFacing ); - SetTurnActivity(); - } - } - break; - } - - case TASK_FACE_IDEAL: - SetTurnActivity(); - break; - - case TASK_FACE_REASONABLE: - GetMotor()->SetIdealYaw( CalcReasonableFacing() ); - SetTurnActivity(); - break; - - case TASK_FACE_PATH: - { - if (!GetNavigator()->IsGoalActive()) - { - DevWarning( 2, "No route to face!\n"); - TaskFail(FAIL_NO_ROUTE); - } - else - { - const float NPC_TRIVIAL_TURN = 15; // (Degrees). Turns this small or smaller, don't bother with a transition. - - GetMotor()->SetIdealYawToTarget( GetNavigator()->GetCurWaypointPos()); - - if( fabs( GetMotor()->DeltaIdealYaw() ) <= NPC_TRIVIAL_TURN ) - { - // This character is already facing the path well enough that - // moving will look fairly natural. Don't bother with a transitional - // turn animation. - TaskComplete(); - break; - } - SetTurnActivity(); - } - } - break; - - // don't do anything. - case TASK_WAIT_PVS: - case TASK_WAIT_INDEFINITE: - break; - - // set a future time that tells us when the wait is over. - case TASK_WAIT: - case TASK_WAIT_FACE_ENEMY: - SetWait( pTask->flTaskData ); - break; - - // set a future time that tells us when the wait is over. - case TASK_WAIT_RANDOM: - case TASK_WAIT_FACE_ENEMY_RANDOM: - SetWait( 0, pTask->flTaskData ); - break; - - case TASK_MOVE_TO_TARGET_RANGE: - case TASK_MOVE_TO_GOAL_RANGE: - { - // Identical tasks, except that target_range uses m_hTargetEnt, - // and Goal range uses the nav goal - CBaseEntity *pTarget = NULL; - if ( task == TASK_MOVE_TO_GOAL_RANGE ) - { - pTarget = GetNavigator()->GetGoalTarget(); - } - if ( !pTarget ) - { - pTarget = m_hTargetEnt.Get(); - } - - if ( pTarget == NULL) - { - TaskFail(FAIL_NO_TARGET); - } - else if ( (pTarget->GetAbsOrigin() - GetLocalOrigin()).Length() < 1 ) - { - TaskComplete(); - } - - if (GetNavigator()->GetGoalType() == GOALTYPE_NONE) - { - TaskComplete(); - GetNavigator()->ClearGoal(); // Clear residual state - } - else - { - // set that we're probably going to stop before the goal - GetNavigator()->SetArrivalDistance( pTask->flTaskData ); - } - - break; - } - - case TASK_WAIT_UNTIL_NO_DANGER_SOUND: - if( !HasCondition( COND_HEAR_DANGER ) ) - { - TaskComplete(); - } - break; - - case TASK_TARGET_PLAYER: - { - CBaseEntity *pPlayer = gEntList.FindEntityByName( NULL, "!player" ); - if ( pPlayer ) - { - SetTarget( pPlayer ); - TaskComplete(); - } - else - TaskFail( FAIL_NO_PLAYER ); - break; - } - - case TASK_SCRIPT_RUN_TO_TARGET: - case TASK_SCRIPT_WALK_TO_TARGET: - case TASK_SCRIPT_CUSTOM_MOVE_TO_TARGET: - StartScriptMoveToTargetTask( pTask->iTask ); - break; - - case TASK_CLEAR_MOVE_WAIT: - m_flMoveWaitFinished = gpGlobals->curtime; - TaskComplete(); - break; - - case TASK_MELEE_ATTACK1: - SetLastAttackTime( gpGlobals->curtime ); - ResetIdealActivity( ACT_MELEE_ATTACK1 ); - break; - - case TASK_MELEE_ATTACK2: - SetLastAttackTime( gpGlobals->curtime ); - ResetIdealActivity( ACT_MELEE_ATTACK2 ); - break; - - case TASK_RANGE_ATTACK1: - SetLastAttackTime( gpGlobals->curtime ); - ResetIdealActivity( ACT_RANGE_ATTACK1 ); - break; - - case TASK_RANGE_ATTACK2: - SetLastAttackTime( gpGlobals->curtime ); - ResetIdealActivity( ACT_RANGE_ATTACK2 ); - break; - - case TASK_RELOAD: - ResetIdealActivity( ACT_RELOAD ); - break; - - case TASK_SPECIAL_ATTACK1: - ResetIdealActivity( ACT_SPECIAL_ATTACK1 ); - break; - - case TASK_SPECIAL_ATTACK2: - ResetIdealActivity( ACT_SPECIAL_ATTACK2 ); - break; - - case TASK_SET_ACTIVITY: - { - Activity goalActivity = (Activity)((int)pTask->flTaskData); - if (goalActivity != ACT_RESET) - { - SetIdealActivity( goalActivity ); - } - else - { - m_Activity = ACT_RESET; - } - break; - } - case TASK_GET_CHASE_PATH_TO_ENEMY: - { - CBaseEntity *pEnemy = GetEnemy(); - if ( !pEnemy ) - { - TaskFail(FAIL_NO_ROUTE); - return; - } - - if ( ( pEnemy->GetAbsOrigin() - GetEnemyLKP() ).LengthSqr() < Square(pTask->flTaskData) ) - { - ChainStartTask( TASK_GET_PATH_TO_ENEMY ); - } - else - { - ChainStartTask( TASK_GET_PATH_TO_ENEMY_LKP ); - } - - if ( !TaskIsComplete() && !HasCondition(COND_TASK_FAILED) ) - TaskFail(FAIL_NO_ROUTE); - break; - } - - case TASK_GET_PATH_TO_ENEMY_LKP: - { - CBaseEntity *pEnemy = GetEnemy(); - if (!pEnemy || IsUnreachable(pEnemy)) - { - TaskFail(FAIL_NO_ROUTE); - return; - } - AI_NavGoal_t goal( GetEnemyLKP() ); - - TranslateNavGoal( pEnemy, goal.dest ); - - if ( GetNavigator()->SetGoal( goal, AIN_CLEAR_TARGET ) ) - { - TaskComplete(); - } - else - { - // no way to get there =( - DevWarning( 2, "GetPathToEnemyLKP failed!!\n" ); - RememberUnreachable(GetEnemy()); - TaskFail(FAIL_NO_ROUTE); - } - break; - } - - case TASK_GET_PATH_TO_INTERACTION_PARTNER: - { - if ( !m_hForcedInteractionPartner || IsUnreachable(m_hForcedInteractionPartner) ) - { - TaskFail(FAIL_NO_ROUTE); - return; - } - - // Calculate the position we need to be at to start the interaction. - CalculateForcedInteractionPosition(); - - AI_NavGoal_t goal( m_vecForcedWorldPosition ); - TranslateNavGoal( m_hForcedInteractionPartner, goal.dest ); - - if ( GetNavigator()->SetGoal( goal, AIN_CLEAR_TARGET ) ) - { - TaskComplete(); - } - else - { - DevWarning( 2, "GetPathToInteractionPartner failed!!\n" ); - RememberUnreachable(m_hForcedInteractionPartner); - TaskFail(FAIL_NO_ROUTE); - } - break; - } - - case TASK_GET_PATH_TO_RANGE_ENEMY_LKP_LOS: - { - if ( GetEnemy() ) - { - // Find out which range to use (either innately or a held weapon) - float flRange = -1.0f; - if ( CapabilitiesGet() & (bits_CAP_INNATE_RANGE_ATTACK1|bits_CAP_INNATE_RANGE_ATTACK2) ) - { - flRange = InnateRange1MaxRange(); - } - else if ( GetActiveWeapon() ) - { - flRange = MAX( GetActiveWeapon()->m_fMaxRange1, GetActiveWeapon()->m_fMaxRange2 ); - } - else - { - // You can't call this task without either innate range attacks or a weapon! - Assert( 0 ); - TaskFail( FAIL_NO_ROUTE ); - } - - // Clamp to the specified range, if supplied - if ( pTask->flTaskData != 0 && pTask->flTaskData < flRange ) - flRange = pTask->flTaskData; - - // For now, just try running straight at enemy - float dist = EnemyDistance( GetEnemy() ); - if ( dist <= flRange || GetNavigator()->SetVectorGoalFromTarget( GetEnemy()->GetAbsOrigin(), dist - flRange ) ) - { - TaskComplete(); - break; - } - } - - TaskFail( FAIL_NO_ROUTE ); - break; - } - - case TASK_GET_PATH_TO_ENEMY_LOS: - case TASK_GET_FLANK_RADIUS_PATH_TO_ENEMY_LOS: - case TASK_GET_FLANK_ARC_PATH_TO_ENEMY_LOS: - case TASK_GET_PATH_TO_ENEMY_LKP_LOS: - { - if ( GetEnemy() == NULL ) - { - TaskFail(FAIL_NO_ENEMY); - return; - } - - AI_PROFILE_SCOPE(CAI_BaseNPC_FindLosToEnemy); - float flMaxRange = 2000; - float flMinRange = 0; - - if ( GetActiveWeapon() ) - { - flMaxRange = MAX( GetActiveWeapon()->m_fMaxRange1, GetActiveWeapon()->m_fMaxRange2 ); - flMinRange = MIN( GetActiveWeapon()->m_fMinRange1, GetActiveWeapon()->m_fMinRange2 ); - } - else if ( CapabilitiesGet() & bits_CAP_INNATE_RANGE_ATTACK1 ) - { - flMaxRange = InnateRange1MaxRange(); - flMinRange = InnateRange1MinRange(); - } - - //Check against NPC's max range - if ( flMaxRange > m_flDistTooFar ) - { - flMaxRange = m_flDistTooFar; - } - - Vector vecEnemy = ( task != TASK_GET_PATH_TO_ENEMY_LKP ) ? GetEnemy()->GetAbsOrigin() : GetEnemyLKP(); - Vector vecEnemyEye = vecEnemy + GetEnemy()->GetViewOffset(); - - Vector posLos; - bool found = false; - - if ( ( task != TASK_GET_FLANK_RADIUS_PATH_TO_ENEMY_LOS ) && ( task != TASK_GET_FLANK_ARC_PATH_TO_ENEMY_LOS ) ) - { - if ( GetTacticalServices()->FindLateralLos( vecEnemyEye, &posLos ) ) - { - float dist = ( posLos - vecEnemyEye ).Length(); - if ( dist < flMaxRange && dist > flMinRange ) - found = true; - } - } - - if ( !found ) - { - FlankType_t eFlankType = FLANKTYPE_NONE; - Vector vecFlankRefPos = vec3_origin; - float flFlankParam = 0; - - if ( task == TASK_GET_FLANK_RADIUS_PATH_TO_ENEMY_LOS ) - { - eFlankType = FLANKTYPE_RADIUS; - vecFlankRefPos = m_vSavePosition; - flFlankParam = pTask->flTaskData; - } - else if ( task == TASK_GET_FLANK_ARC_PATH_TO_ENEMY_LOS ) - { - eFlankType = FLANKTYPE_ARC; - vecFlankRefPos = m_vSavePosition; - flFlankParam = pTask->flTaskData; - } - - if ( GetTacticalServices()->FindLos( vecEnemy, vecEnemyEye, flMinRange, flMaxRange, 1.0, eFlankType, vecFlankRefPos, flFlankParam, &posLos ) ) - { - found = true; - } - } - - if ( !found ) - { - TaskFail( FAIL_NO_SHOOT ); - } - else - { - // else drop into run task to offer an interrupt - m_vInterruptSavePosition = posLos; - } - } - break; - -//================================================== -// TASK_SET_GOAL -//================================================== - - case TASK_SET_GOAL: - - switch ( (int) pTask->flTaskData ) - { - case GOAL_ENEMY: //Enemy - - if ( GetEnemy() == NULL ) - { - TaskFail( FAIL_NO_ENEMY ); - return; - } - - //Setup our stored info - m_vecStoredPathGoal = GetEnemy()->GetAbsOrigin(); - m_nStoredPathType = GOALTYPE_ENEMY; - m_fStoredPathFlags = 0; - m_hStoredPathTarget = GetEnemy(); - GetNavigator()->SetMovementActivity(ACT_RUN); - break; - - case GOAL_ENEMY_LKP: //Enemy's last known position - - if ( GetEnemy() == NULL ) - { - TaskFail( FAIL_NO_ENEMY ); - return; - } - - //Setup our stored info - m_vecStoredPathGoal = GetEnemyLKP(); - m_nStoredPathType = GOALTYPE_LOCATION; - m_fStoredPathFlags = 0; - m_hStoredPathTarget = NULL; - GetNavigator()->SetMovementActivity(ACT_RUN); - break; - - case GOAL_TARGET: //Target entity - - if ( m_hTargetEnt == NULL ) - { - TaskFail( FAIL_NO_TARGET ); - return; - } - - //Setup our stored info - m_vecStoredPathGoal = m_hTargetEnt->GetAbsOrigin(); - m_nStoredPathType = GOALTYPE_TARGETENT; - m_fStoredPathFlags = 0; - m_hStoredPathTarget = m_hTargetEnt; - GetNavigator()->SetMovementActivity(ACT_RUN); - break; - - case GOAL_SAVED_POSITION: //Saved position - - //Setup our stored info - m_vecStoredPathGoal = m_vSavePosition; - m_nStoredPathType = GOALTYPE_LOCATION; - m_fStoredPathFlags = 0; - m_hStoredPathTarget = NULL; - GetNavigator()->SetMovementActivity(ACT_RUN); - break; - } - - TaskComplete(); - - break; - -//================================================== -// TASK_GET_PATH_TO_GOAL -//================================================== - - case TASK_GET_PATH_TO_GOAL: - { - AI_NavGoal_t goal( m_nStoredPathType, - AIN_DEF_ACTIVITY, - AIN_HULL_TOLERANCE, - AIN_DEF_FLAGS, - m_hStoredPathTarget ); - - bool foundPath = false; - - //Find our path - switch ( (int) pTask->flTaskData ) - { - case PATH_TRAVEL: //A land path to our goal - goal.dest = m_vecStoredPathGoal; - foundPath = GetNavigator()->SetGoal( goal ); - break; - - case PATH_LOS: //A path to get LOS to our goal - { - float flMaxRange = 2000.0f; - float flMinRange = 0.0f; - - if ( GetActiveWeapon() ) - { - flMaxRange = MAX( GetActiveWeapon()->m_fMaxRange1, GetActiveWeapon()->m_fMaxRange2 ); - flMinRange = MIN( GetActiveWeapon()->m_fMinRange1, GetActiveWeapon()->m_fMinRange2 ); - } - else if ( CapabilitiesGet() & bits_CAP_INNATE_RANGE_ATTACK1 ) - { - flMaxRange = InnateRange1MaxRange(); - flMinRange = InnateRange1MinRange(); - } - - // Check against NPC's max range - if ( flMaxRange > m_flDistTooFar ) - { - flMaxRange = m_flDistTooFar; - } - - Vector eyePosition = ( m_hStoredPathTarget != NULL ) ? m_hStoredPathTarget->EyePosition() : m_vecStoredPathGoal; - - Vector posLos; - - // See if we've found it - if ( GetTacticalServices()->FindLos( m_vecStoredPathGoal, eyePosition, flMinRange, flMaxRange, 1.0f, &posLos ) ) - { - goal.dest = posLos; - foundPath = GetNavigator()->SetGoal( goal ); - } - else - { - // No LOS to goal - TaskFail( FAIL_NO_SHOOT ); - return; - } - } - - break; - - case PATH_COVER: //Get a path to cover FROM our goal - { - CBaseEntity *pEntity = ( m_hStoredPathTarget == NULL ) ? this : m_hStoredPathTarget; - - //Find later cover first - Vector coverPos; - - if ( GetTacticalServices()->FindLateralCover( pEntity->EyePosition(), 0, &coverPos ) ) - { - AI_NavGoal_t goal( coverPos, ACT_RUN ); - GetNavigator()->SetGoal( goal, AIN_CLEAR_PREVIOUS_STATE ); - - //FIXME: What exactly is this doing internally? - m_flMoveWaitFinished = gpGlobals->curtime + pTask->flTaskData; - TaskComplete(); - return; - } - else - { - //Try any cover - if ( GetTacticalServices()->FindCoverPos( pEntity->GetAbsOrigin(), pEntity->EyePosition(), 0, CoverRadius(), &coverPos ) ) - { - //If we've found it, find a safe route there - AI_NavGoal_t coverGoal( GOALTYPE_COVER, - coverPos, - ACT_RUN, - AIN_HULL_TOLERANCE, - AIN_DEF_FLAGS, - m_hStoredPathTarget ); - - foundPath = GetNavigator()->SetGoal( goal ); - - m_flMoveWaitFinished = gpGlobals->curtime + pTask->flTaskData; - } - else - { - TaskFail( FAIL_NO_COVER ); - } - } - } - - break; - } - - //Now validate our try - if ( foundPath ) - { - TaskComplete(); - } - else - { - TaskFail( FAIL_NO_ROUTE ); - } - } - break; - - case TASK_GET_PATH_TO_ENEMY: - { - if (IsUnreachable(GetEnemy())) - { - TaskFail(FAIL_NO_ROUTE); - return; - } - - CBaseEntity *pEnemy = GetEnemy(); - - if ( pEnemy == NULL ) - { - TaskFail(FAIL_NO_ENEMY); - return; - } - - if ( GetNavigator()->SetGoal( GOALTYPE_ENEMY ) ) - { - TaskComplete(); - } - else - { - // no way to get there =( - DevWarning( 2, "GetPathToEnemy failed!!\n" ); - RememberUnreachable(GetEnemy()); - TaskFail(FAIL_NO_ROUTE); - } - break; - } - case TASK_GET_PATH_TO_ENEMY_CORPSE: - { - Vector forward; - AngleVectors( GetLocalAngles(), &forward ); - Vector vecEnemyLKP = GetEnemyLKP(); - - GetNavigator()->SetGoal( vecEnemyLKP - forward * 64, AIN_CLEAR_TARGET); - } - break; - - case TASK_GET_PATH_TO_PLAYER: - { - CBaseEntity *pPlayer = gEntList.FindEntityByName( NULL, "!player" ); - - AI_NavGoal_t goal; - - goal.type = GOALTYPE_LOCATION; - goal.dest = pPlayer->WorldSpaceCenter(); - goal.pTarget = pPlayer; - - GetNavigator()->SetGoal( goal ); - break; - } - - case TASK_GET_PATH_TO_SAVEPOSITION_LOS: - { - if ( GetEnemy() == NULL ) - { - TaskFail(FAIL_NO_ENEMY); - return; - } - - float flMaxRange = 2000; - float flMinRange = 0; - if ( GetActiveWeapon() ) - { - flMaxRange = MAX(GetActiveWeapon()->m_fMaxRange1,GetActiveWeapon()->m_fMaxRange2); - flMinRange = MIN(GetActiveWeapon()->m_fMinRange1,GetActiveWeapon()->m_fMinRange2); - } - else if ( CapabilitiesGet() & bits_CAP_INNATE_RANGE_ATTACK1 ) - { - flMaxRange = InnateRange1MaxRange(); - flMinRange = InnateRange1MinRange(); - } - - // Check against NPC's max range - if (flMaxRange > m_flDistTooFar) - { - flMaxRange = m_flDistTooFar; - } - - Vector posLos; - - if (GetTacticalServices()->FindLos(m_vSavePosition,m_vSavePosition, flMinRange, flMaxRange, 1.0, &posLos)) - { - GetNavigator()->SetGoal( AI_NavGoal_t( posLos, ACT_RUN, AIN_HULL_TOLERANCE ) ); - } - else - { - // no coverwhatsoever. - TaskFail(FAIL_NO_SHOOT); - } - break; - } - - case TASK_GET_PATH_TO_TARGET_WEAPON: - { - // Finds the nearest node within the leniency distances, - // whether the node can see the target or not. - const float XY_LENIENCY = 64.0; - const float Z_LENIENCY = 72.0; - - if (m_hTargetEnt == NULL) - { - TaskFail(FAIL_NO_TARGET); - } - else - { - // Since this weapon MAY be on a table, we find the nearest node without verifying - // line-of-sight, since weapons on the table will not be able to see nodes very nearby. - int node = GetNavigator()->GetNetwork()->NearestNodeToPoint( this, m_hTargetEnt->GetAbsOrigin(), false ); - CAI_Node *pNode = GetNavigator()->GetNetwork()->GetNode( node ); - - if( !pNode ) - { - TaskFail( FAIL_NO_ROUTE ); - break; - } - - bool bHasPath = true; - Vector vecNodePos; - - vecNodePos = pNode->GetPosition( GetHullType() ); - - float flDistZ; - flDistZ = fabs( vecNodePos.z - m_hTargetEnt->GetAbsOrigin().z ); - if( flDistZ > Z_LENIENCY ) - { - // The gun is too far away from its nearest node on the Z axis. - TaskFail( "Target not within Z_LENIENCY!\n"); - CBaseCombatWeapon *pWeapon = dynamic_cast( m_hTargetEnt.Get() ); - if( pWeapon ) - { - // Lock this weapon for a long time so no one else tries to get it. - pWeapon->Lock( 30.0f, pWeapon ); - break; - } - } - - if( flDistZ >= 16.0 ) - { - // The gun is higher or lower, but it's within reach. (probably on a table). - float flDistXY = ( vecNodePos - m_hTargetEnt->GetAbsOrigin() ).Length2D(); - - // This means we have to stand on the nearest node and still be able to - // reach the gun. - if( flDistXY > XY_LENIENCY ) - { - TaskFail( "Target not within XY_LENIENCY!\n" ); - CBaseCombatWeapon *pWeapon = dynamic_cast( m_hTargetEnt.Get() ); - if( pWeapon ) - { - // Lock this weapon for a long time so no one else tries to get it. - pWeapon->Lock( 30.0f, pWeapon ); - break; - } - } - - AI_NavGoal_t goal( vecNodePos ); - goal.pTarget = m_hTargetEnt; - bHasPath = GetNavigator()->SetGoal( goal ); - } - else - { - // The gun is likely just lying on the floor. Just pick it up. - AI_NavGoal_t goal( m_hTargetEnt->GetAbsOrigin() ); - goal.pTarget = m_hTargetEnt; - bHasPath = GetNavigator()->SetGoal( goal ); - } - - if( !bHasPath ) - { - CBaseCombatWeapon *pWeapon = dynamic_cast( m_hTargetEnt.Get() ); - if( pWeapon ) - { - // Lock this weapon for a long time so no one else tries to get it. - pWeapon->Lock( 15.0f, pWeapon ); - } - } - } - } - break; - - case TASK_GET_PATH_TO_TARGET: - { - if (m_hTargetEnt == NULL) - { - TaskFail(FAIL_NO_TARGET); - } - else - { - AI_NavGoal_t goal( static_cast(m_hTargetEnt->EyePosition()) ); - goal.pTarget = m_hTargetEnt; - GetNavigator()->SetGoal( goal ); - } - break; - } - - case TASK_GET_PATH_TO_HINTNODE:// for active idles! - { - if (!GetHintNode()) - { - TaskFail(FAIL_NO_HINT_NODE); - } - else - { - Vector vHintPos; - GetHintNode()->GetPosition(this, &vHintPos); - - GetNavigator()->SetGoal( AI_NavGoal_t( vHintPos, ACT_RUN ) ); - if ( pTask->flTaskData == 0 ) - GetNavigator()->SetArrivalDirection( GetHintNode()->GetDirection() ); - if ( GetHintNode()->HintActivityName() != NULL_STRING ) - { - Activity hintActivity = (Activity)CAI_BaseNPC::GetActivityID( STRING(GetHintNode()->HintActivityName()) ); - if ( hintActivity != ACT_INVALID ) - { - GetNavigator()->SetArrivalActivity( GetHintActivity(GetHintNode()->HintType(), hintActivity) ); - } - else - { - int iSequence = LookupSequence(STRING(GetHintNode()->HintActivityName()));; - if ( iSequence != ACT_INVALID ) - GetNavigator()->SetArrivalSequence( iSequence ); - } - - } - } - break; - } - - case TASK_GET_PATH_TO_COMMAND_GOAL: - { - if (!GetNavigator()->SetGoal( m_vecCommandGoal )) - { - OnMoveToCommandGoalFailed(); - TaskFail(FAIL_NO_ROUTE); - } - break; - } - - case TASK_MARK_COMMAND_GOAL_POS: - // Start watching my position to detect whether another AI process has moved me from my mark. - m_CommandMoveMonitor.SetMark( this, COMMAND_GOAL_TOLERANCE ); - TaskComplete(); - break; - - case TASK_CLEAR_COMMAND_GOAL: - m_vecCommandGoal = vec3_invalid; - TaskComplete(); - break; - - case TASK_GET_PATH_TO_LASTPOSITION: - { - if (!GetNavigator()->SetGoal( m_vecLastPosition )) - { - TaskFail(FAIL_NO_ROUTE); - } - else - { - GetNavigator()->SetGoalTolerance( 48 ); - } - break; - } - - case TASK_GET_PATH_TO_SAVEPOSITION: - { - GetNavigator()->SetGoal( m_vSavePosition ); - break; - } - - - case TASK_GET_PATH_TO_RANDOM_NODE: // Task argument is lenth of path to build - { - if ( GetNavigator()->SetRandomGoal( pTask->flTaskData ) ) - TaskComplete(); - else - TaskFail(FAIL_NO_REACHABLE_NODE); - - break; - } - - case TASK_GET_PATH_TO_BESTSOUND: - { - - CSound *pSound = GetBestSound(); - if (!pSound) - { - TaskFail(FAIL_NO_SOUND); - } - else - { - GetNavigator()->SetGoal( pSound->GetSoundReactOrigin() ); - } - break; - } - case TASK_GET_PATH_TO_BESTSCENT: - { - - CSound *pScent = GetBestScent(); - if (!pScent) - { - TaskFail(FAIL_NO_SCENT); - } - else - { - GetNavigator()->SetGoal( pScent->GetSoundOrigin() ); - } - break; - } - - case TASK_GET_PATH_AWAY_FROM_BEST_SOUND: - { - CSound *pBestSound = GetBestSound(); - if ( !pBestSound ) - { - TaskFail("No Sound!"); - break; - } - - GetMotor()->SetIdealYawToTarget( pBestSound->GetSoundOrigin() ); - ChainStartTask( TASK_MOVE_AWAY_PATH, pTask->flTaskData ); - LockBestSound(); - break; - } - - case TASK_MOVE_AWAY_PATH: - { - // Drop into run task to support interrupt - DesireStand(); - } - break; - - case TASK_WEAPON_RUN_PATH: - case TASK_ITEM_RUN_PATH: - GetNavigator()->SetMovementActivity(ACT_RUN); - break; - - case TASK_RUN_PATH: - { - // UNDONE: This is in some default AI and some NPCs can't run? -- walk instead? - if ( TranslateActivity( ACT_RUN ) != ACT_INVALID ) - { - GetNavigator()->SetMovementActivity( ACT_RUN ); - } - else - { - GetNavigator()->SetMovementActivity(ACT_WALK); - } - // Cover is void once I move - Forget( bits_MEMORY_INCOVER ); - TaskComplete(); - break; - } - - case TASK_WALK_PATH_FOR_UNITS: - { - GetNavigator()->SetMovementActivity(ACT_WALK); - break; - } - - case TASK_RUN_PATH_FOR_UNITS: - { - GetNavigator()->SetMovementActivity(ACT_RUN); - break; - } - - case TASK_WALK_PATH: - { - bool bIsFlying = (GetMoveType() == MOVETYPE_FLY) || (GetMoveType() == MOVETYPE_FLYGRAVITY); - if ( bIsFlying && ( TranslateActivity( ACT_FLY ) != ACT_INVALID) ) - { - GetNavigator()->SetMovementActivity(ACT_FLY); - } - else if ( TranslateActivity( ACT_WALK ) != ACT_INVALID ) - { - GetNavigator()->SetMovementActivity(ACT_WALK); - } - else - { - GetNavigator()->SetMovementActivity(ACT_RUN); - } - // Cover is void once I move - Forget( bits_MEMORY_INCOVER ); - TaskComplete(); - break; - } - case TASK_WALK_PATH_WITHIN_DIST: - { - GetNavigator()->SetMovementActivity(ACT_WALK); - // set that we're probably going to stop before the goal - GetNavigator()->SetArrivalDistance( pTask->flTaskData ); - break; - } - case TASK_RUN_PATH_WITHIN_DIST: - { - GetNavigator()->SetMovementActivity(ACT_RUN); - // set that we're probably going to stop before the goal - GetNavigator()->SetArrivalDistance( pTask->flTaskData ); - break; - } - case TASK_RUN_PATH_FLEE: - { - Vector vecDiff; - vecDiff = GetLocalOrigin() - GetNavigator()->GetGoalPos(); - - if( vecDiff.Length() <= pTask->flTaskData ) - { - GetNavigator()->StopMoving(); - TaskFail("Flee path shorter than task parameter"); - } - else - { - GetNavigator()->SetMovementActivity(ACT_RUN); - } - - break; - } - case TASK_WALK_PATH_TIMED: - { - GetNavigator()->SetMovementActivity(ACT_WALK); - SetWait( pTask->flTaskData ); - break; - } - case TASK_RUN_PATH_TIMED: - { - GetNavigator()->SetMovementActivity(ACT_RUN); - SetWait( pTask->flTaskData ); - break; - } - case TASK_STRAFE_PATH: - { - Vector2D vec2DirToPoint; - Vector2D vec2RightSide; - - // to start strafing, we have to first figure out if the target is on the left side or right side - Vector right; - AngleVectors( GetLocalAngles(), NULL, &right, NULL ); - - vec2DirToPoint = ( GetNavigator()->GetCurWaypointPos() - GetLocalOrigin() ).AsVector2D(); - Vector2DNormalize(vec2DirToPoint); - vec2RightSide = right.AsVector2D(); - Vector2DNormalize(vec2RightSide); - - if ( DotProduct2D ( vec2DirToPoint, vec2RightSide ) > 0 ) - { - // strafe right - GetNavigator()->SetMovementActivity(ACT_STRAFE_RIGHT); - } - else - { - // strafe left - GetNavigator()->SetMovementActivity(ACT_STRAFE_LEFT); - } - TaskComplete(); - break; - } - - case TASK_WAIT_FOR_MOVEMENT_STEP: - { - if(!GetNavigator()->IsGoalActive()) - { - TaskComplete(); - return; - } - - if ( IsActivityFinished() ) - { - TaskComplete(); - return; - } - ValidateNavGoal(); - break; - } - - case TASK_WAIT_FOR_MOVEMENT: - { - if (GetNavigator()->GetGoalType() == GOALTYPE_NONE) - { - TaskComplete(); - GetNavigator()->ClearGoal(); // Clear residual state - } - else if (!GetNavigator()->IsGoalActive()) - { - SetIdealActivity( GetStoppedActivity() ); - } - else - { - // Check validity of goal type - ValidateNavGoal(); - } - break; - } - case TASK_SMALL_FLINCH: - { - Remember(bits_MEMORY_FLINCHED); - SetIdealActivity( GetFlinchActivity( false, false ) ); - m_flNextFlinchTime = gpGlobals->curtime + random->RandomFloat( 3, 5 ); - break; - } - case TASK_BIG_FLINCH: - { - Remember(bits_MEMORY_FLINCHED); - SetIdealActivity( GetFlinchActivity( true, false ) ); - m_flNextFlinchTime = gpGlobals->curtime + random->RandomFloat( 3, 5 ); - break; - } - case TASK_DIE: - { - GetNavigator()->StopMoving(); - SetIdealActivity( GetDeathActivity() ); - m_lifeState = LIFE_DYING; - - break; - } - case TASK_SOUND_WAKE: - { - AlertSound(); - TaskComplete(); - break; - } - case TASK_SOUND_DIE: - { - CTakeDamageInfo info; - DeathSound( info ); - TaskComplete(); - break; - } - case TASK_SOUND_IDLE: - { - IdleSound(); - TaskComplete(); - break; - } - case TASK_SOUND_PAIN: - { - CTakeDamageInfo info; - PainSound( info ); - TaskComplete(); - break; - } - case TASK_SOUND_ANGRY: - { - // sounds are complete as soon as we get here, cause we've already played them. - DevMsg( 2, "SOUND\n" ); - TaskComplete(); - break; - } - case TASK_SPEAK_SENTENCE: - { - SpeakSentence((int)pTask->flTaskData); - TaskComplete(); - break; - } - case TASK_WAIT_FOR_SPEAK_FINISH: - { - if ( !GetExpresser() ) - TaskComplete(); - else - { - // Are we waiting for our speech to end? Or for the mutex to be free? - if ( pTask->flTaskData ) - { - // Waiting for our speech to end - if ( GetExpresser()->CanSpeakAfterMyself() ) - { - TaskComplete(); - } - } - else - { - // Waiting for the speech & the delay afterwards - if ( !GetExpresser()->IsSpeaking() ) - { - TaskComplete(); - } - } - break; - - } - break; - } - case TASK_WAIT_FOR_SCRIPT: - { - if ( !m_hCine ) - { - DevMsg( "Scripted sequence destroyed while in use\n" ); - TaskFail( FAIL_SCHEDULE_NOT_FOUND ); - break; - } - - break; - } - case TASK_PUSH_SCRIPT_ARRIVAL_ACTIVITY: - { - if ( !m_hCine ) - { - DevMsg( "Scripted sequence destroyed while in use\n" ); - TaskFail( FAIL_SCHEDULE_NOT_FOUND ); - break; - } - - string_t iszArrivalText; - - if ( m_hCine->m_iszEntry != NULL_STRING ) - { - iszArrivalText = m_hCine->m_iszEntry; - } - else if ( m_hCine->m_iszPlay != NULL_STRING ) - { - iszArrivalText = m_hCine->m_iszPlay; - } - else if ( m_hCine->m_iszPostIdle != NULL_STRING ) - { - iszArrivalText = m_hCine->m_iszPostIdle; - } - else - iszArrivalText = NULL_STRING; - - m_ScriptArrivalActivity = AIN_DEF_ACTIVITY; - m_strScriptArrivalSequence = NULL_STRING; - - if ( iszArrivalText != NULL_STRING ) - { - m_ScriptArrivalActivity = (Activity)GetActivityID( STRING( iszArrivalText ) ); - if ( m_ScriptArrivalActivity == ACT_INVALID ) - m_strScriptArrivalSequence = iszArrivalText; - } - - TaskComplete(); - break; - } - - case TASK_PLAY_SCRIPT: - { - // Throw away any stopping paths we have saved, because we - // won't be able to resume them after the sequence. - GetNavigator()->IgnoreStoppingPath(); - - if ( HasMovement( GetSequence() ) || m_hCine->m_bIgnoreGravity ) - { - AddFlag( FL_FLY ); - SetGroundEntity( NULL ); - } - - if (m_hCine) - { - m_hCine->SynchronizeSequence( this ); - } - // - // Start playing a scripted sequence. - // - m_scriptState = SCRIPT_PLAYING; - break; - } - case TASK_PLAY_SCRIPT_POST_IDLE: - { - // - // Start playing a scripted post idle. - // - m_scriptState = SCRIPT_POST_IDLE; - break; - } - - // This is the first task of every schedule driven by a scripted_sequence. - // Delay starting the sequence until all actors have hit their marks. - case TASK_PRE_SCRIPT: - { - if ( !ai_task_pre_script.GetBool() ) - { - TaskComplete(); - } - else if ( !m_hCine ) - { - TaskComplete(); - //DevMsg( "Scripted sequence destroyed while in use\n" ); - //TaskFail( FAIL_SCHEDULE_NOT_FOUND ); - } - else - { - m_hCine->DelayStart( true ); - TaskComplete(); - } - break; - } - - case TASK_ENABLE_SCRIPT: - { - // - // Start waiting to play a script. Play the script's pre idle animation if one - // is specified, otherwise just go to our default idle activity. - // - if ( m_hCine->m_iszPreIdle != NULL_STRING ) - { - m_hCine->StartSequence( ( CAI_BaseNPC * )this, m_hCine->m_iszPreIdle, false ); - if ( FStrEq( STRING( m_hCine->m_iszPreIdle ), STRING( m_hCine->m_iszPlay ) ) ) - { - m_flPlaybackRate = 0; - } - } - else if ( m_scriptState != SCRIPT_CUSTOM_MOVE_TO_MARK ) - { - // FIXME: too many ss assume its safe to leave the npc is whatever sequence they were in before, so only slam their activity - // if they're playing a recognizable movement animation - // -#ifdef HL2_EPISODIC - // dvs: Check current activity rather than ideal activity. Since scripted NPCs early out in MaintainActivity, - // they'll never reach their ideal activity if it's different from their current activity. - if ( GetActivity() == ACT_WALK || - GetActivity() == ACT_RUN || - GetActivity() == ACT_WALK_AIM || - GetActivity() == ACT_RUN_AIM ) - { - SetActivity( ACT_IDLE ); - } -#else - if ( GetIdealActivity() == ACT_WALK || - GetIdealActivity() == ACT_RUN || - GetIdealActivity() == ACT_WALK_AIM || - GetIdealActivity() == ACT_RUN_AIM ) - { - SetActivity( ACT_IDLE ); - } -#endif // HL2_EPISODIC - } - break; - } - case TASK_PLANT_ON_SCRIPT: - { - if ( m_hTargetEnt != NULL ) - { - SetLocalOrigin( m_hTargetEnt->GetAbsOrigin() ); // Plant on target - } - - TaskComplete(); - break; - } - case TASK_FACE_SCRIPT: - { - if ( m_hTargetEnt != NULL ) - { - GetMotor()->SetIdealYaw( UTIL_AngleMod( m_hTargetEnt->GetLocalAngles().y ) ); - } - - if ( m_scriptState != SCRIPT_CUSTOM_MOVE_TO_MARK ) - { - SetTurnActivity(); - - // dvs: HACK: MaintainActivity won't do anything while scripted, so go straight there. - SetActivity( GetIdealActivity() ); - } - - GetNavigator()->StopMoving(); - break; - } - - case TASK_PLAY_SCENE: - { - // inside a scene with movement and sequence commands - break; - } - - - case TASK_SUGGEST_STATE: - { - SetIdealState( (NPC_STATE)(int)pTask->flTaskData ); - TaskComplete(); - break; - } - - case TASK_SET_FAIL_SCHEDULE: - m_failSchedule = (int)pTask->flTaskData; - TaskComplete(); - break; - - case TASK_SET_TOLERANCE_DISTANCE: - GetNavigator()->SetGoalTolerance( (int)pTask->flTaskData ); - TaskComplete(); - break; - - case TASK_SET_ROUTE_SEARCH_TIME: - GetNavigator()->SetMaxRouteRebuildTime( (int)pTask->flTaskData ); - TaskComplete(); - break; - - case TASK_CLEAR_FAIL_SCHEDULE: - m_failSchedule = SCHED_NONE; - TaskComplete(); - break; - - case TASK_WEAPON_FIND: - { - m_hTargetEnt = Weapon_FindUsable( Vector(1000,1000,1000) ); - if (m_hTargetEnt) - { - TaskComplete(); - } - else - { - TaskFail(FAIL_ITEM_NO_FIND); - } - } - break; - - case TASK_ITEM_PICKUP: - { - SetIdealActivity( ACT_PICKUP_GROUND ); - } - break; - - case TASK_WEAPON_PICKUP: - { - if( GetActiveWeapon() ) - { - Weapon_Drop( GetActiveWeapon() ); - } - - if( GetTarget() ) - { - CBaseCombatWeapon *pWeapon = dynamic_cast(GetTarget()); - if( pWeapon ) - { - if( Weapon_IsOnGround( pWeapon ) ) - { - // Squat down - SetIdealActivity( ACT_PICKUP_GROUND ); - } - else - { - // Reach and take this weapon from rack or shelf. - SetIdealActivity( ACT_PICKUP_RACK ); - } - - return; - } - } - - TaskFail("Weapon went away!\n"); - } - break; - - case TASK_WEAPON_CREATE: - { - if( !GetActiveWeapon() && GetTarget() ) - { - // Create a copy of the weapon this NPC is trying to pick up. - CBaseCombatWeapon *pTargetWeapon = dynamic_cast(GetTarget()); - - if( pTargetWeapon ) - { - CBaseCombatWeapon *pWeapon = Weapon_Create( pTargetWeapon->GetClassname() ); - if ( pWeapon ) - { - Weapon_Equip( pWeapon ); - } - } - } - SetTarget( NULL ); - TaskComplete(); - } - break; - - case TASK_USE_SMALL_HULL: - { - SetHullSizeSmall(); - TaskComplete(); - } - break; - - case TASK_FALL_TO_GROUND: - // Set a wait time to try to force a ground ent. - SetWait(4); - break; - - case TASK_WANDER: - { - // This task really uses 2 parameters, so we have to extract - // them from a single integer. To send both parameters, the - // formula is MIN_DIST * 10000 + MAX_DIST - { - int iMinDist, iMaxDist, iParameter; - - iParameter = (int)pTask->flTaskData; - - iMinDist = iParameter / 10000; - iMaxDist = iParameter - (iMinDist * 10000); - - if ( GetNavigator()->SetWanderGoal( iMinDist, iMaxDist ) ) - TaskComplete(); - else - TaskFail(FAIL_NO_REACHABLE_NODE); - } - } - break; - - case TASK_FREEZE: - m_flPlaybackRate = 0; - break; - - case TASK_GATHER_CONDITIONS: - GatherConditions(); - TaskComplete(); - break; - - case TASK_IGNORE_OLD_ENEMIES: - m_flAcceptableTimeSeenEnemy = gpGlobals->curtime; - if ( GetEnemy() && GetEnemyLastTimeSeen() < m_flAcceptableTimeSeenEnemy ) - { - CBaseEntity *pNewEnemy = BestEnemy(); - - Assert( pNewEnemy != GetEnemy() ); - - if( pNewEnemy != NULL ) - { - // New enemy! Clear the timers and set conditions. - SetEnemy( pNewEnemy ); - SetState( NPC_STATE_COMBAT ); - } - else - { - SetEnemy( NULL ); - ClearAttackConditions(); - } - } - TaskComplete(); - break; - - case TASK_ADD_HEALTH: - TakeHealth( (int)pTask->flTaskData, DMG_GENERIC ); - TaskComplete(); - break; - - default: - { - DevMsg( "No StartTask entry for %s\n", TaskName( task ) ); - } - break; - } -} - -void CAI_BaseNPC::StartTaskOverlay() -{ - if ( IsCurTaskContinuousMove() ) - { - if ( ShouldMoveAndShoot() ) - { - m_MoveAndShootOverlay.StartShootWhileMove(); - } - else - { - m_MoveAndShootOverlay.NoShootWhileMove(); - } - } -} - - -//----------------------------------------------------------------------------- -// TASK_DIE. -//----------------------------------------------------------------------------- -void CAI_BaseNPC::RunDieTask() -{ - AutoMovement(); - - if ( IsActivityFinished() && GetCycle() >= 1.0f ) - { - m_lifeState = LIFE_DEAD; - - SetThink ( NULL ); - StopAnimation(); - - if ( !BBoxFlat() ) - { - // a bit of a hack. If a corpses' bbox is positioned such that being left solid so that it can be attacked will - // block the player on a slope or stairs, the corpse is made nonsolid. -// SetSolid( SOLID_NOT ); - UTIL_SetSize ( this, Vector ( -4, -4, 0 ), Vector ( 4, 4, 1 ) ); - } - else // !!!HACKHACK - put NPC in a thin, wide bounding box until we fix the solid type/bounding volume problem - UTIL_SetSize ( this, WorldAlignMins(), Vector ( WorldAlignMaxs().x, WorldAlignMaxs().y, WorldAlignMins().z + 1 ) ); - } -} - - -//----------------------------------------------------------------------------- -// TASK_RANGE_ATTACK1 / TASK_RANGE_ATTACK2 / etc. -//----------------------------------------------------------------------------- -void CAI_BaseNPC::RunAttackTask( int task ) -{ - AutoMovement( ); - - Vector vecEnemyLKP = GetEnemyLKP(); - - // If our enemy was killed, but I'm not done animating, the last known position comes - // back as the origin and makes the me face the world origin if my attack schedule - // doesn't break when my enemy dies. (sjb) - if( vecEnemyLKP != vec3_origin ) - { - if ( ( task == TASK_RANGE_ATTACK1 || task == TASK_RELOAD ) && - ( CapabilitiesGet() & bits_CAP_AIM_GUN ) && - FInAimCone( vecEnemyLKP ) ) - { - // Arms will aim, so leave body yaw as is - GetMotor()->SetIdealYawAndUpdate( GetMotor()->GetIdealYaw(), AI_KEEP_YAW_SPEED ); - } - else - { - GetMotor()->SetIdealYawToTargetAndUpdate( vecEnemyLKP, AI_KEEP_YAW_SPEED ); - } - } - - if ( IsActivityFinished() ) - { - if ( task == TASK_RELOAD && GetShotRegulator() ) - { - GetShotRegulator()->Reset( false ); - } - - TaskComplete(); - } -} - - -//========================================================= -// RunTask -//========================================================= -void CAI_BaseNPC::RunTask( const Task_t *pTask ) -{ - VPROF_BUDGET( "CAI_BaseNPC::RunTask", VPROF_BUDGETGROUP_NPCS ); - switch ( pTask->iTask ) - { - case TASK_GET_PATH_TO_RANDOM_NODE: - { - break; - } - case TASK_TURN_RIGHT: - case TASK_TURN_LEFT: - { - // If the yaw is locked, this function will not act correctly - Assert( GetMotor()->IsYawLocked() == false ); - - GetMotor()->UpdateYaw(); - - if ( FacingIdeal() ) - { - TaskComplete(); - } - break; - } - - case TASK_PLAY_PRIVATE_SEQUENCE_FACE_ENEMY: - case TASK_PLAY_SEQUENCE_FACE_ENEMY: - case TASK_PLAY_SEQUENCE_FACE_TARGET: - { - CBaseEntity *pTarget; - - if ( pTask->iTask == TASK_PLAY_SEQUENCE_FACE_TARGET ) - pTarget = m_hTargetEnt; - else - pTarget = GetEnemy(); - if ( pTarget ) - { - GetMotor()->SetIdealYawAndUpdate( pTarget->GetAbsOrigin() - GetLocalOrigin() , AI_KEEP_YAW_SPEED ); - } - - if ( IsActivityFinished() ) - { - TaskComplete(); - } - } - break; - - case TASK_PLAY_HINT_ACTIVITY: - { - if (!GetHintNode()) - { - TaskFail(FAIL_NO_HINT_NODE); - } - - // Put a debugging check in here - if (GetHintNode()->User() != this) - { - DevMsg("Hint node (%s) being used by non-owner!\n",GetHintNode()->GetDebugName()); - } - - if ( IsActivityFinished() ) - { - TaskComplete(); - } - - break; - } - - case TASK_STOP_MOVING: - { - if ( pTask->flTaskData == 1 ) - { - ChainRunTask( TASK_WAIT_FOR_MOVEMENT ); - if ( GetTaskStatus() == TASKSTATUS_COMPLETE ) - { - DbgNavMsg( this, "TASK_STOP_MOVING Complete\n" ); - } - } - else - { - // if they're jumping, wait until they land - if (GetNavType() == NAV_JUMP) - { - if (GetFlags() & FL_ONGROUND) - { - DbgNavMsg( this, "Jump landed\n" ); - SetNavType( NAV_GROUND ); // this assumes that NAV_JUMP only happens with npcs that use NAV_GROUND as base movement - } - else if (GetSmoothedVelocity().Length() > 0.01) // use an EPSILON damnit!! - { - // wait until you land - break; - } - else - { - DbgNavMsg( this, "Jump stuck\n" ); - // stopped and stuck! - SetNavType( NAV_GROUND ); - TaskFail( FAIL_STUCK_ONTOP ); - } - } - - // @TODO (toml 10-30-02): this is unacceptable, but needed until navigation can handle commencing - // a navigation while in the middle of a climb - if (GetNavType() == NAV_CLIMB) - { - // wait until you reach the end - break; - } - - DbgNavMsg( this, "TASK_STOP_MOVING Complete\n" ); - SetIdealActivity( GetStoppedActivity() ); - - TaskComplete(); - } - break; - } - - case TASK_PLAY_SEQUENCE: - case TASK_PLAY_PRIVATE_SEQUENCE: - { - AutoMovement( ); - if ( IsActivityFinished() ) - { - TaskComplete(); - } - break; - } - - case TASK_ADD_GESTURE_WAIT: - { - if ( IsWaitFinished() ) - { - TaskComplete(); - } - break; - } - - case TASK_SET_ACTIVITY: - { - if ( IsActivityStarted() ) - { - TaskComplete(); - } - } - break; - - case TASK_FACE_ENEMY: - { - // If the yaw is locked, this function will not act correctly - Assert( GetMotor()->IsYawLocked() == false ); - - Vector vecEnemyLKP = GetEnemyLKP(); - if (!FInAimCone( vecEnemyLKP )) - { - GetMotor()->SetIdealYawToTarget( vecEnemyLKP ); - GetMotor()->SetIdealYaw( CalcReasonableFacing( true ) ); // CalcReasonableFacing() is based on previously set ideal yaw - } - else - { - float flReasonableFacing = CalcReasonableFacing( true ); - if ( fabsf( flReasonableFacing - GetMotor()->GetIdealYaw() ) > 1 ) - GetMotor()->SetIdealYaw( flReasonableFacing ); - } - - GetMotor()->UpdateYaw(); - - if ( FacingIdeal() ) - { - TaskComplete(); - } - break; - } - case TASK_FACE_PLAYER: - { - // Get edict for one player - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer ) - { - GetMotor()->SetIdealYawToTargetAndUpdate( pPlayer->GetAbsOrigin(), AI_KEEP_YAW_SPEED ); - SetTurnActivity(); - if ( IsWaitFinished() && GetMotor()->DeltaIdealYaw() < 10 ) - { - TaskComplete(); - } - } - else - { - TaskFail(FAIL_NO_PLAYER); - } - } - break; - - case TASK_FIND_COVER_FROM_BEST_SOUND: - { - switch( GetTaskInterrupt() ) - { - case 0: - { - if ( !FindCoverFromBestSound( &m_vInterruptSavePosition ) ) - TaskFail(FAIL_NO_COVER); - else - { - GetNavigator()->IgnoreStoppingPath(); - LockBestSound(); - TaskInterrupt(); - } - } - break; - - case 1: - { - AI_NavGoal_t goal(m_vInterruptSavePosition, ACT_RUN, AIN_HULL_TOLERANCE); - - CSound *pBestSound = GetBestSound(); - if ( pBestSound ) - goal.maxInitialSimplificationDist = pBestSound->Volume() * 0.5; - - if ( GetNavigator()->SetGoal( goal ) ) - { - m_flMoveWaitFinished = gpGlobals->curtime + pTask->flTaskData; - } - } - break; - } - } - break; - - case TASK_FACE_HINTNODE: - case TASK_FACE_LASTPOSITION: - case TASK_FACE_SAVEPOSITION: - case TASK_FACE_AWAY_FROM_SAVEPOSITION: - case TASK_FACE_TARGET: - case TASK_FACE_IDEAL: - case TASK_FACE_SCRIPT: - case TASK_FACE_PATH: - { - // If the yaw is locked, this function will not act correctly - Assert( GetMotor()->IsYawLocked() == false ); - - GetMotor()->UpdateYaw(); - - if ( FacingIdeal() ) - { - TaskComplete(); - } - break; - } - - case TASK_FACE_REASONABLE: - { - // If the yaw is locked, this function will not act correctly - Assert( GetMotor()->IsYawLocked() == false ); - - GetMotor()->UpdateYaw(); - - if ( FacingIdeal() ) - { - TaskComplete(); - } - break; - } - case TASK_WAIT_PVS: - { - if ( ShouldAlwaysThink() || - UTIL_FindClientInPVS(edict()) || - ( GetState() == NPC_STATE_COMBAT && GetEnemy() && gpGlobals->curtime - GetEnemies()->LastTimeSeen( GetEnemy() ) < 15 ) ) - { - TaskComplete(); - } - break; - } - case TASK_WAIT_INDEFINITE: - { - // don't do anything. - break; - } - case TASK_WAIT: - case TASK_WAIT_RANDOM: - { - if ( IsWaitFinished() ) - { - TaskComplete(); - } - break; - } - case TASK_WAIT_FACE_ENEMY: - case TASK_WAIT_FACE_ENEMY_RANDOM: - { - Vector vecEnemyLKP = GetEnemyLKP(); - if (!FInAimCone( vecEnemyLKP )) - { - GetMotor()->SetIdealYawToTargetAndUpdate( vecEnemyLKP , AI_KEEP_YAW_SPEED ); - } - - if ( IsWaitFinished() ) - { - TaskComplete(); - } - break; - } - case TASK_WAIT_UNTIL_NO_DANGER_SOUND: - if( !HasCondition( COND_HEAR_DANGER ) ) - { - TaskComplete(); - } - break; - - case TASK_MOVE_TO_TARGET_RANGE: - case TASK_MOVE_TO_GOAL_RANGE: - { - // Identical tasks, except that target_range uses m_hTargetEnt, - // and Goal range uses the nav goal - CBaseEntity *pTarget = NULL; - if ( pTask->iTask == TASK_MOVE_TO_GOAL_RANGE ) - { - pTarget = GetNavigator()->GetGoalTarget(); - } - if ( !pTarget ) - { - pTarget = m_hTargetEnt.Get(); - } - - float distance; - - if ( pTarget == NULL ) - { - TaskFail(FAIL_NO_TARGET); - } - else if (GetNavigator()->GetGoalType() == GOALTYPE_NONE) - { - TaskComplete(); - GetNavigator()->ClearGoal(); // Clear residual state - } - else - { - bool bForceRun = false; - - // Check Z first, and only check 2d if we're within that - Vector vecGoalPos = GetNavigator()->GetGoalPos(); - distance = fabs(vecGoalPos.z - GetLocalOrigin().z); - if ( distance < pTask->flTaskData ) - { - distance = ( vecGoalPos - GetLocalOrigin() ).Length2D(); - } - else - { - // If the target is significantly higher or lower than me, I must run. - bForceRun = true; - } - - // If we're jumping, wait until we're finished to update our goal position. - if ( GetNavigator()->GetNavType() != NAV_JUMP ) - { - // Re-evaluate when you think your finished, or the target has moved too far - if ( (distance < pTask->flTaskData) || (vecGoalPos - pTarget->GetAbsOrigin()).Length() > pTask->flTaskData * 0.5 ) - { - distance = ( pTarget->GetAbsOrigin() - GetLocalOrigin() ).Length2D(); - if ( !GetNavigator()->UpdateGoalPos( pTarget->GetAbsOrigin() ) ) - { - TaskFail( FAIL_NO_ROUTE ); - break; - } - } - } - - // Set the appropriate activity based on an overlapping range - // overlap the range to prevent oscillation - // BUGBUG: this is checking linear distance (ie. through walls) and not path distance or even visibility - if ( distance < pTask->flTaskData ) - { - TaskComplete(); -#ifndef HL2_DLL - // HL2 uses TASK_STOP_MOVING - GetNavigator()->StopMoving(); // Stop moving -#endif - } - else - { - // Pick the right movement activity. - Activity followActivity; - - if( bForceRun ) - { - followActivity = ACT_RUN; - } - else - { - followActivity = ( distance < 190 && m_NPCState != NPC_STATE_COMBAT ) ? ACT_WALK : ACT_RUN; - } - - // Don't confuse move and shoot by resetting the activity every think - Activity curActivity = GetNavigator()->GetMovementActivity(); - switch( curActivity ) - { - case ACT_WALK_AIM: curActivity = ACT_WALK; break; - case ACT_RUN_AIM: curActivity = ACT_RUN; break; - default: break; - } - - if ( curActivity != followActivity ) - { - GetNavigator()->SetMovementActivity(followActivity); - } - GetNavigator()->SetArrivalDirection( pTarget ); - } - } - break; - } - case TASK_GET_PATH_TO_ENEMY_LOS: - case TASK_GET_FLANK_RADIUS_PATH_TO_ENEMY_LOS: - case TASK_GET_FLANK_ARC_PATH_TO_ENEMY_LOS: - case TASK_GET_PATH_TO_ENEMY_LKP_LOS: - { - if ( GetEnemy() == NULL ) - { - TaskFail(FAIL_NO_ENEMY); - return; - } - if ( GetTaskInterrupt() > 0 ) - { - ClearTaskInterrupt(); - - Vector vecEnemy = ( pTask->iTask == TASK_GET_PATH_TO_ENEMY_LOS ) ? GetEnemy()->GetAbsOrigin() : GetEnemyLKP(); - AI_NavGoal_t goal( m_vInterruptSavePosition, ACT_RUN, AIN_HULL_TOLERANCE ); - - GetNavigator()->SetGoal( goal, AIN_CLEAR_TARGET ); - GetNavigator()->SetArrivalDirection( vecEnemy - goal.dest ); - } - else - TaskInterrupt(); - } - break; - - case TASK_GET_PATH_AWAY_FROM_BEST_SOUND: - { - ChainRunTask( TASK_MOVE_AWAY_PATH, pTask->flTaskData ); - if ( GetNavigator()->IsGoalActive() ) - { - Vector vecDest = GetNavigator()->GetGoalPos(); - float flDist = ( GetAbsOrigin() - vecDest ).Length(); - - if( flDist < 10.0 * 12.0 ) - { - TaskFail("Path away from best sound too short!\n"); - } - } - break; - } - - case TASK_MOVE_AWAY_PATH: - { - QAngle ang = GetLocalAngles(); - ang.y = GetMotor()->GetIdealYaw() + 180; - Vector move; - - switch ( GetTaskInterrupt() ) - { - case 0: - { - if( IsPlayerAlly() ) - { - // Look for a move away hint node. - CAI_Hint *pHint; - CHintCriteria hintCriteria; - - hintCriteria.AddHintType( HINT_PLAYER_ALLY_MOVE_AWAY_DEST ); - hintCriteria.SetFlag( bits_HINT_NODE_NEAREST ); - hintCriteria.AddIncludePosition( GetAbsOrigin(), (20.0f * 12.0f) ); // 20 feet max - hintCriteria.AddExcludePosition( GetAbsOrigin(), 28.0f ); // don't plant on an hint that you start on - - pHint = CAI_HintManager::FindHint( this, hintCriteria ); - - if( pHint ) - { - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - Vector vecGoal = pHint->GetAbsOrigin(); - - if( vecGoal.DistToSqr(GetAbsOrigin()) < vecGoal.DistToSqr(pPlayer->GetAbsOrigin()) ) - { - if( GetNavigator()->SetGoal(vecGoal) ) - { - pHint->DisableForSeconds( 0.1f ); // Force others to find their own. - TaskComplete(); - break; - } - } - } - } - -#ifdef HL2_EPISODIC - // See if we're moving away from a vehicle - CSound *pBestSound = GetBestSound( SOUND_MOVE_AWAY ); - if ( pBestSound && pBestSound->m_hOwner && pBestSound->m_hOwner->GetServerVehicle() ) - { - // Move away from the vehicle's center, regardless of our facing - move = ( GetAbsOrigin() - pBestSound->m_hOwner->WorldSpaceCenter() ); - VectorNormalize( move ); - } - else - { - // Use the first angles - AngleVectors( ang, &move ); - } -#else - AngleVectors( ang, &move ); -#endif //HL2_EPISODIC - if ( GetNavigator()->SetVectorGoal( move, (float)pTask->flTaskData, MIN(36,pTask->flTaskData), true ) && IsValidMoveAwayDest( GetNavigator()->GetGoalPos() )) - { - TaskComplete(); - } - else - { - ang.y = GetMotor()->GetIdealYaw() + 91; - AngleVectors( ang, &move ); - - if ( GetNavigator()->SetVectorGoal( move, (float)pTask->flTaskData, MIN(24,pTask->flTaskData), true ) && IsValidMoveAwayDest( GetNavigator()->GetGoalPos() ) ) - { - TaskComplete(); - } - else - { - TaskInterrupt(); - } - } - } - break; - - case 1: - { - ang.y = GetMotor()->GetIdealYaw() + 271; - AngleVectors( ang, &move ); - - if ( GetNavigator()->SetVectorGoal( move, (float)pTask->flTaskData, MIN(24,pTask->flTaskData), true ) && IsValidMoveAwayDest( GetNavigator()->GetGoalPos() ) ) - { - TaskComplete(); - } - else - { - ang.y = GetMotor()->GetIdealYaw() + 180; - while (ang.y < 0) - ang.y += 360; - while (ang.y >= 360) - ang.y -= 360; - if ( ang.y < 45 || ang.y >= 315 ) - ang.y = 0; - else if ( ang.y < 135 ) - ang.y = 90; - else if ( ang.y < 225 ) - ang.y = 180; - else - ang.y = 270; - - AngleVectors( ang, &move ); - - if ( GetNavigator()->SetVectorGoal( move, (float)pTask->flTaskData, MIN(6,pTask->flTaskData), false ) && IsValidMoveAwayDest( GetNavigator()->GetGoalPos() ) ) - { - TaskComplete(); - } - else - { - TaskInterrupt(); - } - } - } - break; - - case 2: - { - ClearTaskInterrupt(); - Vector coverPos; - - if ( GetTacticalServices()->FindCoverPos( GetLocalOrigin(), EyePosition(), 0, CoverRadius(), &coverPos ) && IsValidMoveAwayDest( GetNavigator()->GetGoalPos() ) ) - { - GetNavigator()->SetGoal( AI_NavGoal_t( coverPos, ACT_RUN ) ); - m_flMoveWaitFinished = gpGlobals->curtime + 2; - } - else - { - // no coverwhatsoever. - TaskFail(FAIL_NO_ROUTE); - } - } - break; - - } - } - break; - - case TASK_WEAPON_RUN_PATH: - case TASK_ITEM_RUN_PATH: - { - CBaseEntity *pTarget = m_hTargetEnt; - if ( pTarget ) - { - if ( pTarget->GetOwnerEntity() ) - { - TaskFail(FAIL_WEAPON_OWNED); - } - else if (GetNavigator()->GetGoalType() == GOALTYPE_NONE) - { - TaskComplete(); - } - } - else - { - TaskFail(FAIL_ITEM_NO_FIND); - } - } - break; - - case TASK_WAIT_FOR_MOVEMENT_STEP: - case TASK_WAIT_FOR_MOVEMENT: - { - bool fTimeExpired = ( pTask->flTaskData != 0 && pTask->flTaskData < gpGlobals->curtime - GetTimeTaskStarted() ); - - if (fTimeExpired || GetNavigator()->GetGoalType() == GOALTYPE_NONE) - { - TaskComplete(); - GetNavigator()->StopMoving(); // Stop moving - } - else if (!GetNavigator()->IsGoalActive()) - { - SetIdealActivity( GetStoppedActivity() ); - } - else - { - // Check validity of goal type - ValidateNavGoal(); - } - break; - } - - case TASK_DIE: - RunDieTask(); - break; - - case TASK_WAIT_FOR_SPEAK_FINISH: - Assert( GetExpresser() ); - if ( GetExpresser() ) - { - // Are we waiting for our speech to end? Or for the mutex to be free? - if ( pTask->flTaskData ) - { - // Waiting for our speech to end - if ( GetExpresser()->CanSpeakAfterMyself() ) - { - TaskComplete(); - } - } - else - { - // Waiting for the speech & the delay afterwards - if ( !GetExpresser()->IsSpeaking() ) - { - TaskComplete(); - } - } - } - break; - - case TASK_SCRIPT_RUN_TO_TARGET: - case TASK_SCRIPT_WALK_TO_TARGET: - case TASK_SCRIPT_CUSTOM_MOVE_TO_TARGET: - StartScriptMoveToTargetTask( pTask->iTask ); - break; - - case TASK_RANGE_ATTACK1: - case TASK_RANGE_ATTACK2: - case TASK_MELEE_ATTACK1: - case TASK_MELEE_ATTACK2: - case TASK_SPECIAL_ATTACK1: - case TASK_SPECIAL_ATTACK2: - case TASK_RELOAD: - RunAttackTask( pTask->iTask ); - break; - - case TASK_SMALL_FLINCH: - case TASK_BIG_FLINCH: - { - if ( IsActivityFinished() ) - { - TaskComplete(); - } - } - break; - - case TASK_WAIT_FOR_SCRIPT: - { - // - // Waiting to play a script. If the script is ready, start playing the sequence. - // - if ( m_hCine && m_hCine->IsTimeToStart() ) - { - TaskComplete(); - m_hCine->OnBeginSequence(); - - // If we have an entry, we have to play it first - if ( m_hCine->m_iszEntry != NULL_STRING ) - { - m_hCine->StartSequence( (CAI_BaseNPC *)this, m_hCine->m_iszEntry, true ); - } - else - { - m_hCine->StartSequence( (CAI_BaseNPC *)this, m_hCine->m_iszPlay, true ); - } - - // StartSequence() can call CineCleanup(). If that happened, just exit schedule - if ( !m_hCine ) - { - ClearSchedule( "Waiting for script, but lost script!" ); - } - - m_flPlaybackRate = 1.0; - //DevMsg( 2, "Script %s has begun for %s\n", STRING( m_hCine->m_iszPlay ), GetClassname() ); - } - else if (!m_hCine) - { - DevMsg( "Cine died!\n"); - TaskComplete(); - } - else if ( IsRunningDynamicInteraction() ) - { - // If we've lost our partner, abort - if ( !m_hInteractionPartner ) - { - CineCleanup(); - } - } - break; - } - case TASK_PLAY_SCRIPT: - { - // - // Playing a scripted sequence. - // - AutoMovement( ); - - if ( IsSequenceFinished() ) - { - // Check to see if we are done with the action sequence. - if ( m_hCine->FinishedActionSequence( this ) ) - { - // dvs: This is done in FixScriptNPCSchedule -- doing it here is too early because we still - // need to play our post-action idle sequence, which might also require FL_FLY. - // - // drop to ground if this guy is only marked "fly" because of the auto movement - /*if ( !(m_hCine->m_savedFlags & FL_FLY) ) - { - if ( ( GetFlags() & FL_FLY ) && !m_hCine->m_bIgnoreGravity ) - { - RemoveFlag( FL_FLY ); - } - }*/ - - if (m_hCine) - { - m_hCine->SequenceDone( this ); - } - - TaskComplete(); - } - else if ( m_hCine && m_hCine->m_bForceSynch ) - { - m_hCine->SynchronizeSequence( this ); - } - } - break; - } - - case TASK_PLAY_SCRIPT_POST_IDLE: - { - if ( !m_hCine ) - { - DevMsg( "Scripted sequence destroyed while in use\n" ); - TaskFail( FAIL_SCHEDULE_NOT_FOUND ); - break; - } - - // - // Playing a scripted post idle sequence. Quit early if another sequence has grabbed the NPC. - // - if ( IsSequenceFinished() || ( m_hCine->m_hNextCine != NULL ) ) - { - m_hCine->PostIdleDone( this ); - } - break; - } - - case TASK_ENABLE_SCRIPT: - { - if ( !m_hCine ) - { - DevMsg( "Scripted sequence destroyed while in use\n" ); - TaskFail( FAIL_SCHEDULE_NOT_FOUND ); - break; - } - - if (!m_hCine->IsWaitingForBegin()) - { - m_hCine->DelayStart( false ); - TaskComplete(); - } - break; - } - - - case TASK_PLAY_SCENE: - { - if (!IsInLockedScene()) - { - ClearSchedule( "Playing a scene, but not in a scene!" ); - } - if (GetNavigator()->GetGoalType() != GOALTYPE_NONE) - { - TaskComplete(); - } - break; - } - - case TASK_RUN_PATH_FOR_UNITS: - case TASK_WALK_PATH_FOR_UNITS: - { - float distance; - - distance = (m_vecLastPosition - GetLocalOrigin()).Length2D(); - - // Walk path until far enough away - if ( distance > pTask->flTaskData || - GetNavigator()->GetGoalType() == GOALTYPE_NONE ) - { - TaskComplete(); - } - break; - } - - case TASK_RUN_PATH_FLEE: - { - Vector vecDiff; - vecDiff = GetLocalOrigin() - GetNavigator()->GetGoalPos(); - - if( vecDiff.Length() <= pTask->flTaskData ) - { - TaskComplete(); - } - break; - } - - case TASK_WALK_PATH_WITHIN_DIST: - case TASK_RUN_PATH_WITHIN_DIST: - { - Vector vecDiff; - - vecDiff = GetLocalOrigin() - GetNavigator()->GetGoalPos(); - - if( vecDiff.Length() <= pTask->flTaskData ) - { - TaskComplete(); - } - break; - } - - case TASK_WALK_PATH_TIMED: - case TASK_RUN_PATH_TIMED: - { - if ( IsWaitFinished() || - GetNavigator()->GetGoalType() == GOALTYPE_NONE ) - { - TaskComplete(); - } - } - break; - - case TASK_WEAPON_PICKUP: - { - if ( IsActivityFinished() ) - { - CBaseCombatWeapon *pWeapon = dynamic_cast( (CBaseEntity *)m_hTargetEnt); - CBaseCombatCharacter *pOwner = pWeapon->GetOwner(); - if ( !pOwner ) - { - TaskComplete(); - } - else - { - TaskFail(FAIL_WEAPON_OWNED); - } - } - break; - } - break; - - case TASK_ITEM_PICKUP: - { - if ( IsActivityFinished() ) - { - TaskComplete(); - } - break; - } - break; - - case TASK_FALL_TO_GROUND: - if ( GetFlags() & FL_ONGROUND ) - { - TaskComplete(); - } - else if( GetFlags() & FL_FLY ) - { - // We're never going to fall if we're FL_FLY. - RemoveFlag( FL_FLY ); - } - else - { - if( IsWaitFinished() ) - { - // After 4 seconds of trying to fall to ground, Assume that we're in a bad case where the NPC - // isn't actually falling, and make an attempt to slam the ground entity to whatever's under the NPC. - Vector maxs = WorldAlignMaxs() - Vector( .1, .1, .2 ); - Vector mins = WorldAlignMins() + Vector( .1, .1, 0 ); - Vector vecStart = GetAbsOrigin() + Vector( 0, 0, .1 ); - Vector vecDown = GetAbsOrigin(); - vecDown.z -= 0.2; - - trace_t trace; - m_pMoveProbe->TraceHull( vecStart, vecDown, mins, maxs, MASK_NPCSOLID, &trace ); - - if( trace.m_pEnt ) - { - // Found something! - SetGroundEntity( trace.m_pEnt ); - TaskComplete(); - } - else - { - // Try again in a few seconds. - SetWait(4); - } - } - } - break; - - case TASK_WANDER: - break; - - case TASK_FREEZE: - break; - - default: - { - DevMsg( "No RunTask entry for %s\n", TaskName( pTask->iTask ) ); - TaskComplete(); - } - break; - } -} - -void CAI_BaseNPC::RunTaskOverlay() -{ - if ( IsCurTaskContinuousMove() ) - { - m_MoveAndShootOverlay.RunShootWhileMove(); - } -} - -void CAI_BaseNPC::EndTaskOverlay() -{ - m_MoveAndShootOverlay.EndShootWhileMove(); -} - -//========================================================= -// SetTurnActivity - measures the difference between the way -// the NPC is facing and determines whether or not to -// select one of the 180 turn animations. -//========================================================= -void CAI_BaseNPC::SetTurnActivity ( void ) -{ - if ( IsCrouching() ) - { - SetIdealActivity( ACT_IDLE ); // failure case - return; - } - - float flYD; - flYD = GetMotor()->DeltaIdealYaw(); - - // FIXME: unknown case, update yaw should catch these - /* - if (GetMotor()->AddTurnGesture( flYD )) - { - SetIdealActivity( ACT_IDLE ); - Remember( bits_MEMORY_TURNING ); - return; - } - */ - - if( flYD <= -80 && flYD >= -100 && SelectWeightedSequence( ACT_90_RIGHT ) != ACTIVITY_NOT_AVAILABLE ) - { - // 90 degree right. - Remember( bits_MEMORY_TURNING ); - SetIdealActivity( ACT_90_RIGHT ); - return; - } - if( flYD >= 80 && flYD <= 100 && SelectWeightedSequence( ACT_90_LEFT ) != ACTIVITY_NOT_AVAILABLE ) - { - // 90 degree left. - Remember( bits_MEMORY_TURNING ); - SetIdealActivity( ACT_90_LEFT ); - return; - } - if( fabs( flYD ) >= 160 && SelectWeightedSequence ( ACT_180_LEFT ) != ACTIVITY_NOT_AVAILABLE ) - { - Remember( bits_MEMORY_TURNING ); - SetIdealActivity( ACT_180_LEFT ); - return; - } - - if ( flYD <= -45 && SelectWeightedSequence ( ACT_TURN_RIGHT ) != ACTIVITY_NOT_AVAILABLE ) - {// big right turn - SetIdealActivity( ACT_TURN_RIGHT ); - return; - } - if ( flYD >= 45 && SelectWeightedSequence ( ACT_TURN_LEFT ) != ACTIVITY_NOT_AVAILABLE ) - {// big left turn - SetIdealActivity( ACT_TURN_LEFT ); - return; - } - - SetIdealActivity( ACT_IDLE ); // failure case - -} - - -//----------------------------------------------------------------------------- -// Purpose: For a specific delta, add a turn gesture and set the yaw speed -// Input : yaw delta -//----------------------------------------------------------------------------- - - -bool CAI_BaseNPC::UpdateTurnGesture( void ) -{ - float flYD = GetMotor()->DeltaIdealYaw(); - return GetMotor()->AddTurnGesture( flYD ); -} - - -//----------------------------------------------------------------------------- -// Purpose: For non-looping animations that may be replayed sequentially (like attacks) -// Set the activity to ACT_RESET if this is a replay, otherwise just set ideal activity -// Input : newIdealActivity - desired ideal activity -//----------------------------------------------------------------------------- -void CAI_BaseNPC::ResetIdealActivity( Activity newIdealActivity ) -{ - if ( m_Activity == newIdealActivity ) - { - m_Activity = ACT_RESET; - } - - SetIdealActivity( newIdealActivity ); -} - - -void CAI_BaseNPC::TranslateNavGoal( CBaseEntity *pEnemy, Vector &chasePosition ) -{ - if ( GetNavType() == NAV_FLY ) - { - // UNDONE: Cache these per enemy instead? - Vector offset = pEnemy->EyePosition() - pEnemy->GetAbsOrigin(); - chasePosition += offset; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns the custom movement activity for the script that this NPC -// is running. -// Output : Returns the activity, or ACT_INVALID is the sequence is unknown. -//----------------------------------------------------------------------------- -Activity CAI_BaseNPC::GetScriptCustomMoveActivity( void ) -{ - Activity eActivity = ACT_WALK; - - if ( ( m_hCine != NULL ) && ( m_hCine->m_iszCustomMove != NULL_STRING ) ) - { - // We have a valid script. Look up the custom movement activity. - eActivity = ( Activity )LookupActivity( STRING( m_hCine->m_iszCustomMove ) ); - if ( eActivity == ACT_INVALID ) - { - // Not an activity, at least make sure it's a valid sequence. - if ( LookupSequence( STRING( m_hCine->m_iszCustomMove ) ) != ACT_INVALID ) - { - eActivity = ACT_SCRIPT_CUSTOM_MOVE; - } - else - { - eActivity = ACT_WALK; - } - } - } - else if ( m_iszSceneCustomMoveSeq != NULL_STRING ) - { - eActivity = ACT_SCRIPT_CUSTOM_MOVE; - } - - return eActivity; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CAI_BaseNPC::GetScriptCustomMoveSequence( void ) -{ - int iSequence = ACTIVITY_NOT_AVAILABLE; - - // If we have a scripted sequence entity, use it's custom move - if ( m_hCine != NULL ) - { - iSequence = LookupSequence( STRING( m_hCine->m_iszCustomMove ) ); - if ( iSequence == ACTIVITY_NOT_AVAILABLE ) - { - DevMsg( "SCRIPT_CUSTOM_MOVE: %s has no sequence:%s\n", GetClassname(), STRING(m_hCine->m_iszCustomMove) ); - } - } - else if ( m_iszSceneCustomMoveSeq != NULL_STRING ) - { - // Otherwise, use the .vcd custom move - iSequence = LookupSequence( STRING( m_iszSceneCustomMoveSeq ) ); - if ( iSequence == ACTIVITY_NOT_AVAILABLE ) - { - Warning( "SCRIPT_CUSTOM_MOVE: %s failed scripted custom move. Has no sequence called: %s\n", GetClassname(), STRING(m_iszSceneCustomMoveSeq) ); - } - } - - // Failed? Use walk. - if ( iSequence == ACTIVITY_NOT_AVAILABLE ) - { - iSequence = SelectWeightedSequence( ACT_WALK ); - } - - return iSequence; -} - -//========================================================= -// GetTask - returns a pointer to the current -// scheduled task. NULL if there's a problem. -//========================================================= -const Task_t *CAI_BaseNPC::GetTask( void ) -{ - int iScheduleIndex = GetScheduleCurTaskIndex(); - if ( !GetCurSchedule() || iScheduleIndex < 0 || iScheduleIndex >= GetCurSchedule()->NumTasks() ) - // iScheduleIndex is not within valid range for the NPC's current schedule. - return NULL; - - return &GetCurSchedule()->GetTaskList()[ iScheduleIndex ]; -} - - -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::IsInterruptable() -{ - if ( GetState() == NPC_STATE_SCRIPT ) - { - if ( m_hCine ) - { - if (!m_hCine->CanInterrupt() ) - return false; - - // are the in an script FL_FLY state? - if ((GetFlags() & FL_FLY ) && !(m_hCine->m_savedFlags & FL_FLY)) - { - return false; - } - } - } - - return IsAlive(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CAI_BaseNPC::SelectInteractionSchedule( void ) -{ - SetTarget( m_hForcedInteractionPartner ); - - // If we have an interaction, we're the initiator. Move to our interaction point. - if ( m_iInteractionPlaying != NPCINT_NONE ) - return SCHED_INTERACTION_MOVE_TO_PARTNER; - - // Otherwise, turn towards our partner and wait for him to reach us. - //m_iInteractionState = NPCINT_MOVING_TO_MARK; - return SCHED_INTERACTION_WAIT_FOR_PARTNER; -} - -//----------------------------------------------------------------------------- -// Idle schedule selection -//----------------------------------------------------------------------------- -int CAI_BaseNPC::SelectIdleSchedule() -{ - if ( m_hForcedInteractionPartner ) - return SelectInteractionSchedule(); - - int nSched = SelectFlinchSchedule(); - if ( nSched != SCHED_NONE ) - return nSched; - - if ( HasCondition ( COND_HEAR_DANGER ) || - HasCondition ( COND_HEAR_COMBAT ) || - HasCondition ( COND_HEAR_WORLD ) || - HasCondition ( COND_HEAR_BULLET_IMPACT ) || - HasCondition ( COND_HEAR_PLAYER ) ) - { - return SCHED_ALERT_FACE_BESTSOUND; - } - - // no valid route! - if (GetNavigator()->GetGoalType() == GOALTYPE_NONE) - return SCHED_IDLE_STAND; - - // valid route. Get moving - return SCHED_IDLE_WALK; -} - - -//----------------------------------------------------------------------------- -// Alert schedule selection -//----------------------------------------------------------------------------- -int CAI_BaseNPC::SelectAlertSchedule() -{ - if ( m_hForcedInteractionPartner ) - return SelectInteractionSchedule(); - - int nSched = SelectFlinchSchedule(); - if ( nSched != SCHED_NONE ) - return nSched; - - // Scan around for new enemies - if ( HasCondition( COND_ENEMY_DEAD ) && SelectWeightedSequence( ACT_VICTORY_DANCE ) != ACTIVITY_NOT_AVAILABLE ) - return SCHED_ALERT_SCAN; - - if( IsPlayerAlly() && HasCondition(COND_HEAR_COMBAT) ) - { - return SCHED_ALERT_REACT_TO_COMBAT_SOUND; - } - - if ( HasCondition ( COND_HEAR_DANGER ) || - HasCondition ( COND_HEAR_PLAYER ) || - HasCondition ( COND_HEAR_WORLD ) || - HasCondition ( COND_HEAR_BULLET_IMPACT ) || - HasCondition ( COND_HEAR_COMBAT ) ) - { - return SCHED_ALERT_FACE_BESTSOUND; - } - - if ( gpGlobals->curtime - GetEnemies()->LastTimeSeen( AI_UNKNOWN_ENEMY ) < TIME_CARE_ABOUT_DAMAGE ) - return SCHED_ALERT_FACE; - - return SCHED_ALERT_STAND; -} - - -//----------------------------------------------------------------------------- -// Combat schedule selection -//----------------------------------------------------------------------------- -int CAI_BaseNPC::SelectCombatSchedule() -{ - if ( m_hForcedInteractionPartner ) - return SelectInteractionSchedule(); - - int nSched = SelectFlinchSchedule(); - if ( nSched != SCHED_NONE ) - return nSched; - - if ( HasCondition(COND_NEW_ENEMY) && gpGlobals->curtime - GetEnemies()->FirstTimeSeen(GetEnemy()) < 2.0 ) - { - return SCHED_WAKE_ANGRY; - } - - if ( HasCondition( COND_ENEMY_DEAD ) ) - { - // clear the current (dead) enemy and try to find another. - SetEnemy( NULL ); - - if ( ChooseEnemy() ) - { - ClearCondition( COND_ENEMY_DEAD ); - return SelectSchedule(); - } - - SetState( NPC_STATE_ALERT ); - return SelectSchedule(); - } - - // If I'm scared of this enemy run away - if ( IRelationType( GetEnemy() ) == D_FR ) - { - if (HasCondition( COND_SEE_ENEMY ) || - HasCondition( COND_LIGHT_DAMAGE )|| - HasCondition( COND_HEAVY_DAMAGE )) - { - FearSound(); - //ClearCommandGoal(); - return SCHED_RUN_FROM_ENEMY; - } - - // If I've seen the enemy recently, cower. Ignore the time for unforgettable enemies. - AI_EnemyInfo_t *pMemory = GetEnemies()->Find( GetEnemy() ); - if ( (pMemory && pMemory->bUnforgettable) || (GetEnemyLastTimeSeen() > (gpGlobals->curtime - 5.0)) ) - { - // If we're facing him, just look ready. Otherwise, face him. - if ( FInAimCone( GetEnemy()->EyePosition() ) ) - return SCHED_COMBAT_STAND; - - return SCHED_FEAR_FACE; - } - } - - // Check if need to reload - if ( HasCondition( COND_LOW_PRIMARY_AMMO ) || HasCondition( COND_NO_PRIMARY_AMMO ) ) - { - return SCHED_HIDE_AND_RELOAD; - } - - // Can we see the enemy? - if ( !HasCondition(COND_SEE_ENEMY) ) - { - // enemy is unseen, but not occluded! - // turn to face enemy - if ( !HasCondition(COND_ENEMY_OCCLUDED) ) - return SCHED_COMBAT_FACE; - - // chase! - if ( GetActiveWeapon() || (CapabilitiesGet() & (bits_CAP_INNATE_RANGE_ATTACK1|bits_CAP_INNATE_RANGE_ATTACK2))) - return SCHED_ESTABLISH_LINE_OF_FIRE; - else if ( (CapabilitiesGet() & (bits_CAP_INNATE_MELEE_ATTACK1|bits_CAP_INNATE_MELEE_ATTACK2))) - return SCHED_CHASE_ENEMY; - else - return SCHED_TAKE_COVER_FROM_ENEMY; - } - - if ( HasCondition(COND_TOO_CLOSE_TO_ATTACK) ) - return SCHED_BACK_AWAY_FROM_ENEMY; - - if ( HasCondition( COND_WEAPON_PLAYER_IN_SPREAD ) || - HasCondition( COND_WEAPON_BLOCKED_BY_FRIEND ) || - HasCondition( COND_WEAPON_SIGHT_OCCLUDED ) ) - { - return SCHED_ESTABLISH_LINE_OF_FIRE; - } - - if ( GetShotRegulator()->IsInRestInterval() ) - { - if ( HasCondition(COND_CAN_RANGE_ATTACK1) ) - return SCHED_COMBAT_FACE; - } - - // we can see the enemy - if ( HasCondition(COND_CAN_RANGE_ATTACK1) ) - { - if ( !UseAttackSquadSlots() || OccupyStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - return SCHED_RANGE_ATTACK1; - return SCHED_COMBAT_FACE; - } - - if ( HasCondition(COND_CAN_RANGE_ATTACK2) ) - return SCHED_RANGE_ATTACK2; - - if ( HasCondition(COND_CAN_MELEE_ATTACK1) ) - return SCHED_MELEE_ATTACK1; - - if ( HasCondition(COND_CAN_MELEE_ATTACK2) ) - return SCHED_MELEE_ATTACK2; - - if ( HasCondition(COND_NOT_FACING_ATTACK) ) - return SCHED_COMBAT_FACE; - - if ( !HasCondition(COND_CAN_RANGE_ATTACK1) && !HasCondition(COND_CAN_MELEE_ATTACK1) ) - { - // if we can see enemy but can't use either attack type, we must need to get closer to enemy - if ( GetActiveWeapon() ) - return SCHED_MOVE_TO_WEAPON_RANGE; - - // If we have an innate attack and we're too far (or occluded) then get line of sight - if ( HasCondition( COND_TOO_FAR_TO_ATTACK ) && ( CapabilitiesGet() & (bits_CAP_INNATE_RANGE_ATTACK1|bits_CAP_INNATE_RANGE_ATTACK2)) ) - return SCHED_MOVE_TO_WEAPON_RANGE; - - // if we can see enemy but can't use either attack type, we must need to get closer to enemy - if ( CapabilitiesGet() & (bits_CAP_INNATE_MELEE_ATTACK1|bits_CAP_INNATE_MELEE_ATTACK2) ) - return SCHED_CHASE_ENEMY; - else - return SCHED_TAKE_COVER_FROM_ENEMY; - } - - DevWarning( 2, "No suitable combat schedule!\n" ); - return SCHED_FAIL; -} - - -//----------------------------------------------------------------------------- -// Dead schedule selection -//----------------------------------------------------------------------------- -int CAI_BaseNPC::SelectDeadSchedule() -{ - if ( BecomeRagdollOnClient( vec3_origin ) ) - { - CleanupOnDeath(); - return SCHED_DIE_RAGDOLL; - } - - // Adrian - Alread dead (by animation event maybe?) - // Is it safe to set it to SCHED_NONE? - if ( m_lifeState == LIFE_DEAD ) - return SCHED_NONE; - - CleanupOnDeath(); - return SCHED_DIE; -} - - -//----------------------------------------------------------------------------- -// Script schedule selection -//----------------------------------------------------------------------------- -int CAI_BaseNPC::SelectScriptSchedule() -{ - Assert( m_hCine != NULL ); - if ( m_hCine ) - return SCHED_AISCRIPT; - - DevWarning( 2, "Script failed for %s\n", GetClassname() ); - CineCleanup(); - return SCHED_IDLE_STAND; -} - -//----------------------------------------------------------------------------- -// Purpose: Select a gesture to play in response to damage we've taken -// Output : int -//----------------------------------------------------------------------------- -void CAI_BaseNPC::PlayFlinchGesture() -{ - if ( !CanFlinch() ) - return; - - Activity iFlinchActivity = ACT_INVALID; - - float flNextFlinch = random->RandomFloat( 0.5f, 1.0f ); - - // If I haven't flinched for a while, play the big flinch gesture - if ( !HasMemory(bits_MEMORY_FLINCHED) ) - { - iFlinchActivity = GetFlinchActivity( true, true ); - - if ( HaveSequenceForActivity( iFlinchActivity ) ) - { - RestartGesture( iFlinchActivity ); - } - - Remember(bits_MEMORY_FLINCHED); - - } - else - { - iFlinchActivity = GetFlinchActivity( false, true ); - if ( HaveSequenceForActivity( iFlinchActivity ) ) - { - RestartGesture( iFlinchActivity ); - } - } - - if ( iFlinchActivity != ACT_INVALID ) - { - //Get the duration of the flinch and delay the next one by that (plus a bit more) - int iSequence = GetLayerSequence( FindGestureLayer( iFlinchActivity ) ); - - if ( iSequence != ACT_INVALID ) - { - flNextFlinch += SequenceDuration( iSequence ); - } - - m_flNextFlinchTime = gpGlobals->curtime + flNextFlinch; - } -} - -//----------------------------------------------------------------------------- -// Purpose: See if we should flinch in response to damage we've taken -// Output : int -//----------------------------------------------------------------------------- -int CAI_BaseNPC::SelectFlinchSchedule() -{ - if ( !HasCondition(COND_HEAVY_DAMAGE) ) - return SCHED_NONE; - - // If we've flinched recently, don't do it again. A gesture flinch will be played instead. - if ( HasMemory(bits_MEMORY_FLINCHED) ) - return SCHED_NONE; - - if ( !CanFlinch() ) - return SCHED_NONE; - - // Robin: This was in the original HL1 flinch code. Do we still want it? - //if ( fabs( GetMotor()->DeltaIdealYaw() ) < (1.0 - m_flFieldOfView) * 60 ) // roughly in the correct direction - // return SCHED_TAKE_COVER_FROM_ORIGIN; - - // Heavy damage. Break out of my current schedule and flinch. - Activity iFlinchActivity = GetFlinchActivity( true, false ); - if ( HaveSequenceForActivity( iFlinchActivity ) ) - return SCHED_BIG_FLINCH; - - /* - // Not used anymore, because gesture flinches are played instead for heavy damage - // taken shortly after we've already flinched full. - // - iFlinchActivity = GetFlinchActivity( false, false ); - if ( HaveSequenceForActivity( iFlinchActivity ) ) - return SCHED_SMALL_FLINCH; - */ - - return SCHED_NONE; -} - -//----------------------------------------------------------------------------- -// Purpose: Decides which type of schedule best suits the NPC's current -// state and conditions. Then calls NPC's member function to get a pointer -// to a schedule of the proper type. -//----------------------------------------------------------------------------- -int CAI_BaseNPC::SelectSchedule( void ) -{ - if ( HasCondition( COND_FLOATING_OFF_GROUND ) ) - { - SetGravity( 1.0 ); - SetGroundEntity( NULL ); - return SCHED_FALL_TO_GROUND; - } - - switch( m_NPCState ) - { - case NPC_STATE_NONE: - DevWarning( 2, "NPC_STATE IS NONE!\n" ); - break; - - case NPC_STATE_PRONE: - return SCHED_IDLE_STAND; - - case NPC_STATE_IDLE: - AssertMsgOnce( GetEnemy() == NULL, "NPC has enemy but is not in combat state?" ); - return SelectIdleSchedule(); - - case NPC_STATE_ALERT: - AssertMsgOnce( GetEnemy() == NULL, "NPC has enemy but is not in combat state?" ); - return SelectAlertSchedule(); - - case NPC_STATE_COMBAT: - return SelectCombatSchedule(); - - case NPC_STATE_DEAD: - return SelectDeadSchedule(); - - case NPC_STATE_SCRIPT: - return SelectScriptSchedule(); - - default: - DevWarning( 2, "Invalid State for SelectSchedule!\n" ); - break; - } - - return SCHED_FAIL; -} - - -//----------------------------------------------------------------------------- - -int CAI_BaseNPC::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ) -{ - return ( m_failSchedule != SCHED_NONE ) ? m_failSchedule : SCHED_FAIL; -} diff --git a/game/server/ai_basenpc_squad.cpp b/game/server/ai_basenpc_squad.cpp deleted file mode 100644 index 4692dd2ab..000000000 --- a/game/server/ai_basenpc_squad.cpp +++ /dev/null @@ -1,292 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ai_basenpc.h" -#include "ai_default.h" -#include "ai_hull.h" -#include "ai_squadslot.h" -#include "ai_squad.h" -#include "bitstring.h" -#include "entitylist.h" -#include "ai_hint.h" -#include "IEffects.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: If requested slot is available return true and take the slot -// Otherwise return false -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::OccupyStrategySlot( int squadSlotID ) -{ - return OccupyStrategySlotRange( squadSlotID, squadSlotID ); -} - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::OccupyStrategySlotRange( int slotIDStart, int slotIDEnd ) -{ - // If I'm not in a squad a I don't fill slots - return ( !m_pSquad || m_pSquad->OccupyStrategySlotRange( GetEnemy(), slotIDStart, slotIDEnd, &m_iMySquadSlot ) ); - -} - -//----------------------------------------------------------------------------- -// Returns true if all in the range are full -//----------------------------------------------------------------------------- -bool CAI_BaseNPC::IsStrategySlotRangeOccupied( int slotIDStart, int slotIDEnd ) -{ - return m_pSquad && m_pSquad->IsStrategySlotRangeOccupied( GetEnemy(), slotIDStart, slotIDEnd ); -} - - -//========================================================= -// HasStrategySlot -//========================================================= -bool CAI_BaseNPC::HasStrategySlot( int squadSlotID ) -{ - // If I wasn't taking up a squad slot I'm done - return (m_iMySquadSlot == squadSlotID); -} - -bool CAI_BaseNPC::HasStrategySlotRange( int slotIDStart, int slotIDEnd ) -{ - // If I wasn't taking up a squad slot I'm done - if (m_iMySquadSlot < slotIDStart || m_iMySquadSlot > slotIDEnd) - { - return false; - } - return true; -} - -//========================================================= -// VacateSlot -//========================================================= - -void CAI_BaseNPC::VacateStrategySlot(void) -{ - if (m_pSquad) - { - m_pSquad->VacateStrategySlot(GetEnemy(), m_iMySquadSlot); - m_iMySquadSlot = SQUAD_SLOT_NONE; - } -} - - -//------------------------------------------------------------------------------ -// Purpose : Is cover node valid -// Input : -// Output : -//------------------------------------------------------------------------------ -bool CAI_BaseNPC::IsValidCover( const Vector &vecCoverLocation, CAI_Hint const *pHint ) -{ - // firstly, limit choices to hint groups - string_t iszHint = GetHintGroup(); - char *pszHint = (char *)STRING(iszHint); - if ((iszHint != NULL_STRING) && (pszHint[0] != '\0')) - { - if (!pHint || pHint->GetGroup() != GetHintGroup()) - { - return false; - } - } - - /* - // If I'm in a squad don't pick cover node it other squad member - // is already nearby - if (m_pSquad) - { - return m_pSquad->IsValidCover( vecCoverLocation, pHint ); - } - */ - - // UNDONE: Do we really need this test? - // ---------------------------------------------------------------- - // Make sure my hull can fit at this node before accepting it. - // Could be another NPC there or it could be blocked - // ---------------------------------------------------------------- - // FIXME: shouldn't this see that if I crouch behind it it'll be safe? - Vector startPos = vecCoverLocation; - startPos.z -= GetHullMins().z; // Move hull bottom up to node - Vector endPos = startPos; - endPos.z += 0.01; - trace_t tr; - AI_TraceEntity( this, vecCoverLocation, endPos, MASK_NPCSOLID, &tr ); - if (tr.startsolid) - { - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Is squad member in my way from shooting here -// Input : -// Output : -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::IsValidShootPosition( const Vector &vecShootLocation, CAI_Node *pNode, CAI_Hint const *pHint ) -{ - // limit choices to hint groups - if (GetHintGroup() != NULL_STRING) - { - if (!pHint || pHint->GetGroup() != GetHintGroup()) - { - if ( ( vecShootLocation - GetAbsOrigin() ).Length2DSqr() > 1 ) - return false; - } - } - - return true; -} - -//----------------------------------------------------------------------------- - -bool CAI_BaseNPC::IsSquadmateInSpread( const Vector &sourcePos, const Vector &targetPos, float flSpread, float maxDistOffCenter ) -{ - if( !m_pSquad ) - return false; - - AISquadIter_t iter; - - CAI_BaseNPC *pSquadmate = m_pSquad->GetFirstMember( &iter ); - while ( pSquadmate ) - { - // Ignore squadmates that can't take damage. This is primarily to ignore npc_enemyfinders. - if ( pSquadmate->m_takedamage != DAMAGE_NO ) - { - if ( pSquadmate != this ) - { - if ( PointInSpread( pSquadmate, sourcePos, targetPos, pSquadmate->GetAbsOrigin(), flSpread, maxDistOffCenter ) ) - return true; - } - } - pSquadmate = m_pSquad->GetNextMember( &iter ); - } - return false; -} - - -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::AddToSquad( string_t name ) -{ - g_AI_SquadManager.FindCreateSquad( this, name ); -} - -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::SetSquad( CAI_Squad *pSquad ) -{ - if ( m_pSquad == pSquad ) - { - return; - } - - if ( m_pSquad && m_iMySquadSlot != SQUAD_SLOT_NONE) - { - VacateStrategySlot(); - } - - m_pSquad = pSquad; -} - -//----------------------------------------------------------------------------- - -void CAI_BaseNPC::RemoveFromSquad() -{ - if ( m_pSquad ) - { - m_pSquad->RemoveFromSquad( this, false ); - m_pSquad = NULL; - } -} - -//----------------------------------------------------------------------------- -void CAI_BaseNPC::CheckSquad() -{ - if( !IsInSquad() ) - return; - - if( !GetSquad()->IsLeader(this) ) - return; - - if( VPhysicsGetObject() != NULL && (VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD) ) - { - // I AM the leader, and I'm currently being held. This will screw up all of my relationship checks - // if I'm a manhack or a rollermine, so just bomb out and try next time. - return; - } - - AISquadIter_t iter; - CAI_BaseNPC *pSquadmate = m_pSquad->GetFirstMember( &iter ); - while ( pSquadmate ) - { - if( IRelationType(pSquadmate) < D_LI ) - { - bool bWarn = true; - - // Rollermines and manhacks set their Class to NONE when held by the player, which makes all of - // their squadmates complain that an enemy is in the squad. Suppress this. - if( pSquadmate->VPhysicsGetObject() != NULL ) - { - if (pSquadmate->VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD) - { - bWarn = false; - } - } - - if( bWarn ) - { - Warning( "ERROR: Squad '%s' has enemies in it!\n", GetSquad()->GetName() ); - Warning( "%s doesn't like %s\n\n", GetDebugName(), pSquadmate->GetDebugName() ); - } - } - - pSquadmate = m_pSquad->GetNextMember( &iter ); - } -} - -//----------------------------------------------------------------------------- -// Returns the number of weapons of this type currently owned by squad members. -//----------------------------------------------------------------------------- -int CAI_BaseNPC::NumWeaponsInSquad( const char *pszWeaponClassname ) -{ - string_t iszWeaponClassname = FindPooledString( pszWeaponClassname ); - - if( !GetSquad() ) - { - if( GetActiveWeapon() && GetActiveWeapon()->m_iClassname == iszWeaponClassname ) - { - // I'm alone in my squad, but I do have this weapon. - return 1; - } - - return 0; - } - - int count = 0; - AISquadIter_t iter; - CAI_BaseNPC *pSquadmate = m_pSquad->GetFirstMember( &iter ); - while ( pSquadmate ) - { - if( pSquadmate->GetActiveWeapon() && pSquadmate->GetActiveWeapon()->m_iClassname == iszWeaponClassname ) - { - count++; - } - pSquadmate = m_pSquad->GetNextMember( &iter ); - } - - return count; -} diff --git a/game/server/ai_behavior.cpp b/game/server/ai_behavior.cpp deleted file mode 100644 index 942d11018..000000000 --- a/game/server/ai_behavior.cpp +++ /dev/null @@ -1,533 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -#include "isaverestore.h" -#include "ai_behavior.h" -#include "scripted.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -bool g_bBehaviorHost_PreventBaseClassGatherConditions; - -//----------------------------------------------------------------------------- -// CAI_BehaviorBase -//----------------------------------------------------------------------------- - -BEGIN_DATADESC_NO_BASE( CAI_BehaviorBase ) - -END_DATADESC() - -//------------------------------------- - -CAI_ClassScheduleIdSpace *CAI_BehaviorBase::GetClassScheduleIdSpace() -{ - return GetOuter()->GetClassScheduleIdSpace(); -} - -//----------------------------------------------------------------------------- -// Purpose: Draw any text overlays (override in subclass to add additional text) -// Input : Previous text offset from the top -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CAI_BehaviorBase::DrawDebugTextOverlays( int text_offset ) -{ - char tempstr[ 512 ]; - int offset = text_offset; - - if ( GetOuter()->m_debugOverlays & OVERLAY_TEXT_BIT ) - { - Q_snprintf( tempstr, sizeof( tempstr ), "Behv: %s, ", GetName() ); - GetOuter()->EntityText( offset, tempstr, 0 ); - offset++; - } - - return offset; -} - -//------------------------------------- - -void CAI_BehaviorBase::GatherConditions() -{ - Assert( m_pBackBridge != NULL ); - - m_pBackBridge->BackBridge_GatherConditions(); -} - -//------------------------------------- - -void CAI_BehaviorBase::PrescheduleThink() -{ -} - -//------------------------------------- - -void CAI_BehaviorBase::OnScheduleChange() -{ -} - -//------------------------------------- - -void CAI_BehaviorBase::OnStartSchedule( int scheduleType ) -{ -} - -//------------------------------------- - -int CAI_BehaviorBase::SelectSchedule() -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_SelectSchedule(); -} - -//------------------------------------- - -int CAI_BehaviorBase::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ) -{ - m_fOverrode = false; - return SCHED_NONE; -} - -//------------------------------------- - -void CAI_BehaviorBase::StartTask( const Task_t *pTask ) -{ - m_fOverrode = false; -} - -//------------------------------------- - -void CAI_BehaviorBase::RunTask( const Task_t *pTask ) -{ - m_fOverrode = false; -} - -//------------------------------------- - -void CAI_BehaviorBase::AimGun( void ) -{ - m_fOverrode = false; -} - -//------------------------------------- - -int CAI_BehaviorBase::TranslateSchedule( int scheduleType ) -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_TranslateSchedule( scheduleType ); -} - -//------------------------------------- - -CAI_Schedule *CAI_BehaviorBase::GetSchedule(int schedule) -{ - if (!GetClassScheduleIdSpace()->IsGlobalBaseSet()) - { - Warning("ERROR: %s missing schedule!\n", GetSchedulingErrorName()); - return g_AI_SchedulesManager.GetScheduleFromID(SCHED_IDLE_STAND); - } - if ( AI_IdIsLocal( schedule ) ) - { - schedule = GetClassScheduleIdSpace()->ScheduleLocalToGlobal(schedule); - } - - if ( schedule == -1 ) - return NULL; - - return g_AI_SchedulesManager.GetScheduleFromID( schedule ); -} - -//------------------------------------- - -bool CAI_BehaviorBase::IsCurSchedule( int schedule, bool fIdeal ) -{ - if ( AI_IdIsLocal( schedule ) ) - schedule = GetClassScheduleIdSpace()->ScheduleLocalToGlobal(schedule); - - return GetOuter()->IsCurSchedule( schedule, fIdeal ); -} - -//------------------------------------- - -const char *CAI_BehaviorBase::GetSchedulingErrorName() -{ - return "CAI_Behavior"; -} - -//------------------------------------- - -Activity CAI_BehaviorBase::NPC_TranslateActivity( Activity activity ) -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_NPC_TranslateActivity( activity ); -} - -//------------------------------------- - -bool CAI_BehaviorBase::IsCurTaskContinuousMove() -{ - m_fOverrode = false; - return false; -} - -//------------------------------------- - -float CAI_BehaviorBase::GetDefaultNavGoalTolerance() -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_GetDefaultNavGoalTolerance(); -} - -//------------------------------------- - -bool CAI_BehaviorBase::FValidateHintType( CAI_Hint *pHint ) -{ - m_fOverrode = false; - return false; -} - -//------------------------------------- - -bool CAI_BehaviorBase::IsValidEnemy( CBaseEntity *pEnemy ) -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_IsValidEnemy( pEnemy ); -} - -//------------------------------------- - -CBaseEntity *CAI_BehaviorBase::BestEnemy( void ) -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_BestEnemy(); -} - -//------------------------------------- - -bool CAI_BehaviorBase::IsValidCover( const Vector &vLocation, CAI_Hint const *pHint ) -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_IsValidCover( vLocation, pHint ); -} - -//------------------------------------- - -bool CAI_BehaviorBase::IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint ) -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_IsValidShootPosition( vLocation, pNode, pHint ); -} - -//------------------------------------- - -float CAI_BehaviorBase::GetMaxTacticalLateralMovement( void ) -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_GetMaxTacticalLateralMovement(); -} - -//------------------------------------- - -bool CAI_BehaviorBase::ShouldIgnoreSound( CSound *pSound ) -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_ShouldIgnoreSound( pSound ); -} - -//------------------------------------- - -void CAI_BehaviorBase::OnSeeEntity( CBaseEntity *pEntity ) -{ - Assert( m_pBackBridge != NULL ); - - m_pBackBridge->BackBridge_OnSeeEntity( pEntity ); -} - -//------------------------------------- - -void CAI_BehaviorBase::OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker ) -{ - Assert( m_pBackBridge != NULL ); - - m_pBackBridge->BackBridge_OnFriendDamaged( pSquadmate, pAttacker ); -} - -//------------------------------------- - -bool CAI_BehaviorBase::IsInterruptable( void ) -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_IsInterruptable(); -} - -//------------------------------------- - -bool CAI_BehaviorBase::IsNavigationUrgent( void ) -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_IsNavigationUrgent(); -} - -//------------------------------------- - -bool CAI_BehaviorBase::CanFlinch( void ) -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_CanFlinch(); -} - -//------------------------------------- - -bool CAI_BehaviorBase::IsCrouching( void ) -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_IsCrouching(); -} - -//------------------------------------- - -bool CAI_BehaviorBase::IsCrouchedActivity( Activity activity ) -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_IsCrouchedActivity( activity ); -} - -//------------------------------------- - -bool CAI_BehaviorBase::QueryHearSound( CSound *pSound ) -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_QueryHearSound( pSound ); -} - -//------------------------------------- - -bool CAI_BehaviorBase::CanRunAScriptedNPCInteraction( bool bForced ) -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_CanRunAScriptedNPCInteraction( bForced ); -} - -//------------------------------------- - -bool CAI_BehaviorBase::ShouldPlayerAvoid( void ) -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_ShouldPlayerAvoid(); -} - -//------------------------------------- - -int CAI_BehaviorBase::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_OnTakeDamage_Alive( info ); -} - -//------------------------------------- - -float CAI_BehaviorBase::GetReasonableFacingDist( void ) -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_GetReasonableFacingDist(); -} - -//------------------------------------- - -bool CAI_BehaviorBase::ShouldAlwaysThink() -{ - m_fOverrode = false; - return false; -} - -//------------------------------------- - -Activity CAI_BehaviorBase::GetFlinchActivity( bool bHeavyDamage, bool bGesture ) -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_GetFlinchActivity( bHeavyDamage, bGesture ); -} - -//------------------------------------- - -bool CAI_BehaviorBase::OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_OnCalcBaseMove( pMoveGoal, distClear, pResult ); -} - -//------------------------------------- - -void CAI_BehaviorBase::ModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet ) -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_ModifyOrAppendCriteria( criteriaSet ); -} - -//------------------------------------- - -void CAI_BehaviorBase::Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ) -{ - Assert( m_pBackBridge != NULL ); - - return m_pBackBridge->BackBridge_Teleport( newPosition, newAngles, newVelocity ); -} - -//------------------------------------- - -void CAI_BehaviorBase::HandleAnimEvent( animevent_t *pEvent ) -{ - Assert( m_pBackBridge != NULL ); - - m_pBackBridge->BackBridge_HandleAnimEvent( pEvent ); -} - -//------------------------------------- - -bool CAI_BehaviorBase::NotifyChangeBehaviorStatus( bool fCanFinishSchedule ) -{ - bool fInterrupt = GetOuter()->OnBehaviorChangeStatus( this, fCanFinishSchedule ); - - if ( !GetOuter()->IsInterruptable()) - return false; - - if ( fInterrupt ) - { - if ( GetOuter()->m_hCine ) - { - if( GetOuter()->m_hCine->PlayedSequence() ) - { - DevWarning( "NPC: %s canceled running script %s due to behavior change\n", GetOuter()->GetDebugName(), GetOuter()->m_hCine->GetDebugName() ); - } - else - { - DevWarning( "NPC: %s canceled script %s without playing, due to behavior change\n", GetOuter()->GetDebugName(), GetOuter()->m_hCine->GetDebugName() ); - } - - GetOuter()->m_hCine->CancelScript(); - } - - //!!!HACKHACK - // this is dirty, but it forces NPC to pick a new schedule next time through. - GetOuter()->ClearSchedule( "Changed behavior status" ); - } - - return fInterrupt; -} - -//------------------------------------- - -int CAI_BehaviorBase::Save( ISave &save ) -{ - return save.WriteAll( this, GetDataDescMap() ); -} - -//------------------------------------- - -int CAI_BehaviorBase::Restore( IRestore &restore ) -{ - return restore.ReadAll( this, GetDataDescMap() ); -} - -//------------------------------------- - -#define BEHAVIOR_SAVE_BLOCKNAME "AI_Behaviors" -#define BEHAVIOR_SAVE_VERSION 2 - -void CAI_BehaviorBase::SaveBehaviors(ISave &save, CAI_BehaviorBase *pCurrentBehavior, CAI_BehaviorBase **ppBehavior, int nBehaviors ) -{ - save.StartBlock( BEHAVIOR_SAVE_BLOCKNAME ); - short temp = BEHAVIOR_SAVE_VERSION; - save.WriteShort( &temp ); - temp = (short)nBehaviors; - save.WriteShort( &temp ); - - for ( int i = 0; i < nBehaviors; i++ ) - { - if ( strcmp( ppBehavior[i]->GetDataDescMap()->dataClassName, CAI_BehaviorBase::m_DataMap.dataClassName ) != 0 ) - { - save.StartBlock(); - save.WriteString( ppBehavior[i]->GetDataDescMap()->dataClassName ); - bool bIsCurrent = ( pCurrentBehavior == ppBehavior[i] ); - save.WriteBool( &bIsCurrent ); - ppBehavior[i]->Save( save ); - save.EndBlock(); - } - } - - save.EndBlock(); -} - -//------------------------------------- - -int CAI_BehaviorBase::RestoreBehaviors(IRestore &restore, CAI_BehaviorBase **ppBehavior, int nBehaviors ) -{ - int iCurrent = -1; - char szBlockName[SIZE_BLOCK_NAME_BUF]; - restore.StartBlock( szBlockName ); - if ( strcmp( szBlockName, BEHAVIOR_SAVE_BLOCKNAME ) == 0 ) - { - short version; - restore.ReadShort( &version ); - if ( version == BEHAVIOR_SAVE_VERSION ) - { - short nToRestore; - char szClassNameCurrent[256]; - restore.ReadShort( &nToRestore ); - for ( int i = 0; i < nToRestore; i++ ) - { - restore.StartBlock(); - restore.ReadString( szClassNameCurrent, sizeof( szClassNameCurrent ), 0 ); - bool bIsCurrent; - restore.ReadBool( &bIsCurrent ); - - for ( int j = 0; j < nBehaviors; j++ ) - { - if ( strcmp( ppBehavior[j]->GetDataDescMap()->dataClassName, szClassNameCurrent ) == 0 ) - { - if ( bIsCurrent ) - iCurrent = j; - ppBehavior[j]->Restore( restore ); - } - } - - restore.EndBlock(); - - } - } - } - restore.EndBlock(); - return iCurrent; -} - - -//----------------------------------------------------------------------------- diff --git a/game/server/ai_behavior.h b/game/server/ai_behavior.h deleted file mode 100644 index 68e667edd..000000000 --- a/game/server/ai_behavior.h +++ /dev/null @@ -1,1977 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_BEHAVIOR_H -#define AI_BEHAVIOR_H - -#include "ai_component.h" -#include "ai_basenpc.h" -#include "ai_default.h" -#include "AI_Criteria.h" -#include "networkvar.h" - -#ifdef DEBUG -#ifdef _MSC_VER -#pragma warning(push) -#endif -#include -#ifdef _MSC_VER -#pragma warning(pop) -#pragma warning(disable:4290) -#endif -#endif - -#if defined( _WIN32 ) -#pragma once -#endif - -//----------------------------------------------------------------------------- -// CAI_Behavior... -// -// Purpose: The core component that defines a behavior in an NPC by selecting -// schedules and running tasks -// -// Intended to be used as an organizational tool as well as a way -// for various NPCs to share behaviors without sharing an inheritance -// relationship, and without cramming those behaviors into the base -// NPC class. -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -// Purpose: Base class defines interface to behaviors and provides bridging -// methods -//----------------------------------------------------------------------------- - -class IBehaviorBackBridge; - -//------------------------------------- - -abstract_class CAI_BehaviorBase : public CAI_Component -{ - DECLARE_CLASS( CAI_BehaviorBase, CAI_Component ) -public: - CAI_BehaviorBase(CAI_BaseNPC *pOuter = NULL) - : CAI_Component(pOuter), - m_pBackBridge(NULL) - { - } - - virtual const char *GetName() = 0; - - virtual bool KeyValue( const char *szKeyName, const char *szValue ) - { - return false; - } - - bool IsRunning() { Assert( GetOuter() ); return ( GetOuter()->GetRunningBehavior() == this ); } - virtual bool CanSelectSchedule() { return true; } - virtual void BeginScheduleSelection() {} - virtual void EndScheduleSelection() {} - - void SetBackBridge( IBehaviorBackBridge *pBackBridge ) - { - Assert( m_pBackBridge == NULL || pBackBridge == NULL ); - m_pBackBridge = pBackBridge; - } - - void BridgePrecache() { Precache(); } - void BridgeSpawn() { Spawn(); } - void BridgeUpdateOnRemove() { UpdateOnRemove(); } - void BridgeEvent_Killed( const CTakeDamageInfo &info ) { Event_Killed( info ); } - void BridgeCleanupOnDeath( CBaseEntity *pCulprit, bool bFireDeathOutput ) { CleanupOnDeath( pCulprit, bFireDeathOutput ); } - - void BridgeOnChangeHintGroup( string_t oldGroup, string_t newGroup ) { OnChangeHintGroup( oldGroup, newGroup ); } - - void BridgeGatherConditions() { GatherConditions(); } - void BridgePrescheduleThink() { PrescheduleThink(); } - void BridgeOnScheduleChange() { OnScheduleChange(); } - void BridgeOnStartSchedule( int scheduleType ); - - int BridgeSelectSchedule(); - bool BridgeSelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode, int *pResult ); - bool BridgeStartTask( const Task_t *pTask ); - bool BridgeRunTask( const Task_t *pTask); - bool BridgeAimGun( void ); - int BridgeTranslateSchedule( int scheduleType ); - bool BridgeGetSchedule( int localScheduleID, CAI_Schedule **ppResult ); - bool BridgeTaskName(int taskID, const char **); - Activity BridgeNPC_TranslateActivity( Activity activity ); - void BridgeBuildScheduleTestBits() { BuildScheduleTestBits(); } - bool BridgeIsCurTaskContinuousMove( bool *pResult ); - void BridgeOnMovementFailed() { OnMovementFailed(); } - void BridgeOnMovementComplete() { OnMovementComplete(); } - float BridgeGetDefaultNavGoalTolerance(); - bool BridgeFValidateHintType( CAI_Hint *pHint, bool *pResult ); - bool BridgeIsValidEnemy( CBaseEntity *pEnemy ); - CBaseEntity *BridgeBestEnemy(); - bool BridgeIsValidCover( const Vector &vLocation, CAI_Hint const *pHint ); - bool BridgeIsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint ); - float BridgeGetMaxTacticalLateralMovement( void ); - bool BridgeShouldIgnoreSound( CSound *pSound ); - void BridgeOnSeeEntity( CBaseEntity *pEntity ); - void BridgeOnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker ); - bool BridgeIsInterruptable( void ); - bool BridgeIsNavigationUrgent( void ); - bool BridgeShouldPlayerAvoid( void ); - int BridgeOnTakeDamage_Alive( const CTakeDamageInfo &info ); - float BridgeGetReasonableFacingDist( void ); - bool BridgeShouldAlwaysThink( bool *pResult ); - void BridgeOnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ); - void BridgeOnRestore(); - virtual bool BridgeSpeakMapmakerInterruptConcept( string_t iszConcept ); - bool BridgeCanFlinch( void ); - bool BridgeIsCrouching( void ); - bool BridgeIsCrouchedActivity( Activity activity ); - bool BridgeQueryHearSound( CSound *pSound ); - bool BridgeCanRunAScriptedNPCInteraction( bool bForced ); - Activity BridgeGetFlinchActivity( bool bHeavyDamage, bool bGesture ); - bool BridgeOnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ); - void BridgeModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet ); - void BridgeTeleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ); - void BridgeHandleAnimEvent( animevent_t *pEvent ); - - virtual void GatherConditions(); - virtual void GatherConditionsNotActive() { return; } // Override this and your behavior will call this in place of GatherConditions() when your behavior is NOT the active one. - virtual void OnUpdateShotRegulator() {} - - virtual CAI_ClassScheduleIdSpace *GetClassScheduleIdSpace(); - - virtual int DrawDebugTextOverlays( int text_offset ); - - virtual int Save( ISave &save ); - virtual int Restore( IRestore &restore ); - - static void SaveBehaviors(ISave &save, CAI_BehaviorBase *pCurrentBehavior, CAI_BehaviorBase **ppBehavior, int nBehaviors ); - static int RestoreBehaviors(IRestore &restore, CAI_BehaviorBase **ppBehavior, int nBehaviors ); // returns index of "current" behavior, or -1 - -protected: - - int GetNpcState() { return GetOuter()->m_NPCState; } - - virtual void Precache() {} - virtual void Spawn() {} - virtual void UpdateOnRemove() {} - virtual void Event_Killed( const CTakeDamageInfo &info ) {} - virtual void CleanupOnDeath( CBaseEntity *pCulprit, bool bFireDeathOutput ) {} - - virtual void PrescheduleThink(); - virtual void OnScheduleChange(); - virtual void OnStartSchedule( int scheduleType ); - - virtual int SelectSchedule(); - virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ); - virtual void StartTask( const Task_t *pTask ); - virtual void RunTask( const Task_t *pTask ); - virtual void AimGun( void ); - virtual int TranslateSchedule( int scheduleType ); - virtual CAI_Schedule *GetSchedule(int schedule); - virtual const char *GetSchedulingErrorName(); - virtual void BuildScheduleTestBits() {} - bool IsCurSchedule( int schedId, bool fIdeal = true ); - - - CAI_Hint * GetHintNode() { return GetOuter()->GetHintNode(); } - const CAI_Hint *GetHintNode() const { return GetOuter()->GetHintNode(); } - void SetHintNode( CAI_Hint *pHintNode ) { GetOuter()->SetHintNode( pHintNode ); } - void ClearHintNode( float reuseDelay = 0.0 ) { GetOuter()->ClearHintNode( reuseDelay ); } - -protected: - // Used by derived classes to chain a task to a task that might not be the - // one they are currently handling: - void ChainStartTask( int task, float taskData = 0 ); - void ChainRunTask( int task, float taskData = 0 ); - -protected: - - virtual Activity NPC_TranslateActivity( Activity activity ); - - virtual bool IsCurTaskContinuousMove(); - virtual void OnMovementFailed() {}; - virtual void OnMovementComplete() {}; - virtual float GetDefaultNavGoalTolerance(); - virtual bool FValidateHintType( CAI_Hint *pHint ); - - virtual bool IsValidEnemy( CBaseEntity *pEnemy ); - virtual CBaseEntity *BestEnemy(); - virtual bool IsValidCover( const Vector &vLocation, CAI_Hint const *pHint ); - virtual bool IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint ); - virtual float GetMaxTacticalLateralMovement( void ); - virtual bool ShouldIgnoreSound( CSound *pSound ); - virtual void OnSeeEntity( CBaseEntity *pEntity ); - virtual void OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker ); - virtual bool IsInterruptable( void ); - virtual bool IsNavigationUrgent( void ); - virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - virtual float GetReasonableFacingDist( void ); - virtual bool ShouldPlayerAvoid( void ); - virtual bool CanFlinch( void ); - virtual bool IsCrouching( void ); - virtual bool IsCrouchedActivity( Activity activity ); - virtual bool QueryHearSound( CSound *pSound ); - virtual bool CanRunAScriptedNPCInteraction( bool bForced ); - virtual Activity GetFlinchActivity( bool bHeavyDamage, bool bGesture ); - virtual bool OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ); - virtual void ModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet ); - virtual void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ); - virtual void HandleAnimEvent( animevent_t *pEvent ); - - virtual bool ShouldAlwaysThink(); - - virtual void OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ) {}; - virtual bool SpeakMapmakerInterruptConcept( string_t iszConcept ) { return false; }; - - virtual void OnRestore() {}; - - bool NotifyChangeBehaviorStatus( bool fCanFinishSchedule = false ); - - bool HaveSequenceForActivity( Activity activity ) { return GetOuter()->HaveSequenceForActivity( activity ); } - - //--------------------------------- - - string_t GetHintGroup() { return GetOuter()->GetHintGroup(); } - void ClearHintGroup() { GetOuter()->ClearHintGroup(); } - void SetHintGroup( string_t name ) { GetOuter()->SetHintGroup( name ); } - - virtual void OnChangeHintGroup( string_t oldGroup, string_t newGroup ) {} - - // - // These allow derived classes to implement custom schedules - // - static CAI_GlobalScheduleNamespace *GetSchedulingSymbols() { return CAI_BaseNPC::GetSchedulingSymbols(); } - static bool LoadSchedules() { return true; } - virtual bool IsBehaviorSchedule( int scheduleType ) { return false; } - - CAI_Navigator * GetNavigator() { return GetOuter()->GetNavigator(); } - CAI_Motor * GetMotor() { return GetOuter()->GetMotor(); } - CAI_TacticalServices * GetTacticalServices() { return GetOuter()->GetTacticalServices(); } - - bool m_fOverrode; - IBehaviorBackBridge *m_pBackBridge; - - DECLARE_DATADESC(); -}; - -//----------------------------------------------------------------------------- -// Purpose: Template provides provides back bridge to owning class and -// establishes namespace settings -//----------------------------------------------------------------------------- - -template -class CAI_Behavior : public CAI_ComponentWithOuter -{ -public: - DECLARE_CLASS_NOFRIEND( CAI_Behavior, NPC_CLASS ); - - enum - { - NEXT_TASK = ID_SPACE_OFFSET, - NEXT_SCHEDULE = ID_SPACE_OFFSET, - NEXT_CONDITION = ID_SPACE_OFFSET - }; - - void SetCondition( int condition ) - { - if ( condition >= ID_SPACE_OFFSET && condition < ID_SPACE_OFFSET + 10000 ) // it's local to us - condition = GetClassScheduleIdSpace()->ConditionLocalToGlobal( condition ); - CAI_ComponentWithOuter::GetOuter()->SetCondition( condition ); - } - - bool HasCondition( int condition ) - { - if ( condition >= ID_SPACE_OFFSET && condition < ID_SPACE_OFFSET + 10000 ) // it's local to us - condition = GetClassScheduleIdSpace()->ConditionLocalToGlobal( condition ); - return CAI_ComponentWithOuter::GetOuter()->HasCondition( condition ); - } - - bool HasInterruptCondition( int condition ) - { - if ( condition >= ID_SPACE_OFFSET && condition < ID_SPACE_OFFSET + 10000 ) // it's local to us - condition = GetClassScheduleIdSpace()->ConditionLocalToGlobal( condition ); - return CAI_ComponentWithOuter::GetOuter()->HasInterruptCondition( condition ); - } - - void ClearCondition( int condition ) - { - if ( condition >= ID_SPACE_OFFSET && condition < ID_SPACE_OFFSET + 10000 ) // it's local to us - condition = GetClassScheduleIdSpace()->ConditionLocalToGlobal( condition ); - CAI_ComponentWithOuter::GetOuter()->ClearCondition( condition ); - } - -protected: - CAI_Behavior(NPC_CLASS *pOuter = NULL) - : CAI_ComponentWithOuter(pOuter) - { - } - - static CAI_GlobalScheduleNamespace *GetSchedulingSymbols() - { - return NPC_CLASS::GetSchedulingSymbols(); - } - virtual CAI_ClassScheduleIdSpace *GetClassScheduleIdSpace() - { - return CAI_ComponentWithOuter::GetOuter()->GetClassScheduleIdSpace(); - } - - static CAI_ClassScheduleIdSpace &AccessClassScheduleIdSpaceDirect() - { - return NPC_CLASS::AccessClassScheduleIdSpaceDirect(); - } - -private: - virtual bool IsBehaviorSchedule( int scheduleType ) { return ( scheduleType >= ID_SPACE_OFFSET && scheduleType < ID_SPACE_OFFSET + 10000 ); } -}; - - -//----------------------------------------------------------------------------- -// Purpose: Some bridges a little more complicated to allow behavior to see -// what base class would do or control order in which it's donw -//----------------------------------------------------------------------------- - -abstract_class IBehaviorBackBridge -{ -public: - virtual void BackBridge_GatherConditions() = 0; - virtual int BackBridge_SelectSchedule() = 0; - virtual int BackBridge_TranslateSchedule( int scheduleType ) = 0; - virtual Activity BackBridge_NPC_TranslateActivity( Activity activity ) = 0; - virtual bool BackBridge_IsValidEnemy(CBaseEntity *pEnemy) = 0; - virtual CBaseEntity* BackBridge_BestEnemy(void) = 0; - virtual bool BackBridge_IsValidCover( const Vector &vLocation, CAI_Hint const *pHint ) = 0; - virtual bool BackBridge_IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint ) = 0; - virtual float BackBridge_GetMaxTacticalLateralMovement( void ) = 0; - virtual bool BackBridge_ShouldIgnoreSound( CSound *pSound ) = 0; - virtual void BackBridge_OnSeeEntity( CBaseEntity *pEntity ) = 0; - virtual void BackBridge_OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker ) = 0; - virtual bool BackBridge_IsInterruptable( void ) = 0; - virtual bool BackBridge_IsNavigationUrgent( void ) = 0; - virtual bool BackBridge_ShouldPlayerAvoid( void ) = 0; - virtual int BackBridge_OnTakeDamage_Alive( const CTakeDamageInfo &info ) = 0; - virtual float BackBridge_GetDefaultNavGoalTolerance() = 0; - virtual float BackBridge_GetReasonableFacingDist( void ) = 0; - virtual bool BackBridge_CanFlinch( void ) = 0; - virtual bool BackBridge_IsCrouching( void ) = 0; - virtual bool BackBridge_IsCrouchedActivity( Activity activity ) = 0; - virtual bool BackBridge_QueryHearSound( CSound *pSound ) = 0; - virtual bool BackBridge_CanRunAScriptedNPCInteraction( bool bForced ) = 0; - virtual Activity BackBridge_GetFlinchActivity( bool bHeavyDamage, bool bGesture ) = 0; - virtual bool BackBridge_OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) = 0; - virtual void BackBridge_ModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet ) = 0; - virtual void BackBridge_Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ) = 0; - - virtual void BackBridge_HandleAnimEvent( animevent_t *pEvent ) = 0; - -//------------------------------------- - -}; - -//----------------------------------------------------------------------------- -// Purpose: The common instantiation of the above template -//----------------------------------------------------------------------------- - -typedef CAI_Behavior<> CAI_SimpleBehavior; - -//----------------------------------------------------------------------------- -// Purpose: Base class for AIs that want to act as a host for CAI_Behaviors -// NPCs aren't required to use this, but probably want to. -//----------------------------------------------------------------------------- - -template -class CAI_BehaviorHost : public BASE_NPC, - private IBehaviorBackBridge -{ -public: - DECLARE_CLASS_NOFRIEND( CAI_BehaviorHost, BASE_NPC ); - - CAI_BehaviorHost() - : m_pCurBehavior(NULL) - { -#ifdef DEBUG - m_fDebugInCreateBehaviors = false; -#endif - } - - void CleanupOnDeath( CBaseEntity *pCulprit = NULL, bool bFireDeathOutput = true ); - - virtual int Save( ISave &save ); - virtual int Restore( IRestore &restore ); - virtual bool CreateComponents(); - - // Automatically called during entity construction, derived class calls AddBehavior() - virtual bool CreateBehaviors() { return true; } - - // forces movement and sets a new schedule - virtual bool ScheduledMoveToGoalEntity( int scheduleType, CBaseEntity *pGoalEntity, Activity movementActivity ); - virtual bool ScheduledFollowPath( int scheduleType, CBaseEntity *pPathStart, Activity movementActivity ); - virtual void ForceSelectedGo(CBaseEntity *pPlayer, const Vector &targetPos, const Vector &traceDir, bool bRun); - virtual void ForceSelectedGoRandom(void); - - // Bridges - void Precache(); - void NPCInit(); - void UpdateOnRemove(); - void Event_Killed( const CTakeDamageInfo &info ); - void GatherConditions(); - void PrescheduleThink(); - int SelectSchedule(); - void KeepRunningBehavior(); - int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ); - void OnScheduleChange(); - void OnStartSchedule( int scheduleType ); - int TranslateSchedule( int scheduleType ); - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - void AimGun( void ); - CAI_Schedule * GetSchedule(int localScheduleID); - const char * TaskName(int taskID); - void BuildScheduleTestBits(); - - void OnChangeHintGroup( string_t oldGroup, string_t newGroup ); - - Activity NPC_TranslateActivity( Activity activity ); - - bool IsCurTaskContinuousMove(); - void OnMovementFailed(); - void OnMovementComplete(); - bool FValidateHintType( CAI_Hint *pHint ); - float GetDefaultNavGoalTolerance(); - - bool IsValidEnemy(CBaseEntity *pEnemy); - CBaseEntity* BestEnemy(void); - bool IsValidCover( const Vector &vLocation, CAI_Hint const *pHint ); - bool IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint ); - float GetMaxTacticalLateralMovement( void ); - bool ShouldIgnoreSound( CSound *pSound ); - void OnSeeEntity( CBaseEntity *pEntity ); - void OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker ); - bool IsInterruptable( void ); - bool IsNavigationUrgent( void ); - bool ShouldPlayerAvoid( void ); - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - float GetReasonableFacingDist( void ); - bool CanFlinch( void ); - bool IsCrouching( void ); - bool IsCrouchedActivity( Activity activity ); - bool QueryHearSound( CSound *pSound ); - bool CanRunAScriptedNPCInteraction( bool bForced ); - Activity GetFlinchActivity( bool bHeavyDamage, bool bGesture ); - bool OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ); - void HandleAnimEvent( animevent_t *pEvent ); - - bool ShouldAlwaysThink(); - - void OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ); - virtual bool SpeakMapmakerInterruptConcept( string_t iszConcept ); - - void OnRestore(); - - void ModifyOrAppendCriteria( AI_CriteriaSet& set ); - void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ); - - //--------------------------------- - - virtual bool OnBehaviorChangeStatus( CAI_BehaviorBase *pBehavior, bool fCanFinishSchedule ); - virtual void OnChangeRunningBehavior( CAI_BehaviorBase *pOldBehavior, CAI_BehaviorBase *pNewBehavior ); - -protected: - void AddBehavior( CAI_BehaviorBase *pBehavior ); - - bool BehaviorSelectSchedule(); - virtual bool ShouldBehaviorSelectSchedule( CAI_BehaviorBase *pBehavior ) { return true; } - - bool IsRunningBehavior() const; - CAI_BehaviorBase *GetRunningBehavior(); - CAI_BehaviorBase *DeferSchedulingToBehavior( CAI_BehaviorBase *pNewBehavior ); - void ChangeBehaviorTo( CAI_BehaviorBase *pNewBehavior ); - - CAI_Schedule * GetNewSchedule(); - CAI_Schedule * GetFailSchedule(); -private: - void BackBridge_GatherConditions(); - int BackBridge_SelectSchedule(); - int BackBridge_TranslateSchedule( int scheduleType ); - Activity BackBridge_NPC_TranslateActivity( Activity activity ); - bool BackBridge_IsValidEnemy(CBaseEntity *pEnemy); - CBaseEntity* BackBridge_BestEnemy(void); - bool BackBridge_IsValidCover( const Vector &vLocation, CAI_Hint const *pHint ); - bool BackBridge_IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint ); - float BackBridge_GetMaxTacticalLateralMovement( void ); - bool BackBridge_ShouldIgnoreSound( CSound *pSound ); - void BackBridge_OnSeeEntity( CBaseEntity *pEntity ); - void BackBridge_OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker ); - bool BackBridge_IsInterruptable( void ); - bool BackBridge_IsNavigationUrgent( void ); - bool BackBridge_ShouldPlayerAvoid( void ); - int BackBridge_OnTakeDamage_Alive( const CTakeDamageInfo &info ); - float BackBridge_GetDefaultNavGoalTolerance(); - float BackBridge_GetReasonableFacingDist( void ); - bool BackBridge_CanFlinch( void ); - bool BackBridge_IsCrouching( void ); - bool BackBridge_IsCrouchedActivity( Activity activity ); - bool BackBridge_QueryHearSound( CSound *pSound ); - bool BackBridge_CanRunAScriptedNPCInteraction( bool bForced ); - Activity BackBridge_GetFlinchActivity( bool bHeavyDamage, bool bGesture ); - bool BackBridge_OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ); - void BackBridge_ModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet ); - void BackBridge_Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ); - - void BackBridge_HandleAnimEvent( animevent_t *pEvent ); - - CAI_BehaviorBase **AccessBehaviors(); - int NumBehaviors(); - - CAI_BehaviorBase * m_pCurBehavior; - CUtlVector m_Behaviors; - - bool m_bCalledBehaviorSelectSchedule; - -#ifdef DEBUG - bool m_fDebugInCreateBehaviors; -#endif - -}; - -//----------------------------------------------------------------------------- - -// The first frame a behavior begins schedule selection, it won't have had it's GatherConditions() -// called. To fix this, BeginScheduleSelection() manually calls the new behavior's GatherConditions(), -// but sets this global so that the baseclass GatherConditions() isn't called as well. -extern bool g_bBehaviorHost_PreventBaseClassGatherConditions; - -//----------------------------------------------------------------------------- - -inline void CAI_BehaviorBase::BridgeOnStartSchedule( int scheduleType ) -{ - int localId = AI_IdIsGlobal( scheduleType ) ? GetClassScheduleIdSpace()->ScheduleGlobalToLocal( scheduleType ) : scheduleType; - OnStartSchedule( localId ); -} - -//------------------------------------- - -inline int CAI_BehaviorBase::BridgeSelectSchedule() -{ - int result = SelectSchedule(); - - if ( IsBehaviorSchedule( result ) ) - return GetClassScheduleIdSpace()->ScheduleLocalToGlobal( result ); - - return result; -} - -//------------------------------------- - -inline bool CAI_BehaviorBase::BridgeSelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode, int *pResult ) -{ - m_fOverrode = true; - int result = SelectFailSchedule( failedSchedule, failedTask, taskFailCode ); - if ( m_fOverrode ) - { - if ( result != SCHED_NONE ) - { - if ( IsBehaviorSchedule( result ) ) - *pResult = GetClassScheduleIdSpace()->ScheduleLocalToGlobal( result ); - else - *pResult = result; - return true; - } - Warning( "An AI behavior is in control but has no recommended schedule\n" ); - } - return false; -} - -//------------------------------------- - -inline bool CAI_BehaviorBase::BridgeStartTask( const Task_t *pTask ) -{ - m_fOverrode = true; - StartTask( pTask ); - return m_fOverrode; -} - -//------------------------------------- - -inline bool CAI_BehaviorBase::BridgeRunTask( const Task_t *pTask) -{ - m_fOverrode = true; - RunTask( pTask ); - return m_fOverrode; -} - -//------------------------------------- - -inline bool CAI_BehaviorBase::BridgeAimGun( void ) -{ - m_fOverrode = true; - AimGun(); - return m_fOverrode; -} - -//------------------------------------- - -inline void CAI_BehaviorBase::ChainStartTask( int task, float taskData ) -{ - Task_t tempTask = { task, taskData }; - - bool fPrevOverride = m_fOverrode; - GetOuter()->StartTask( (const Task_t *)&tempTask ); - m_fOverrode = fPrevOverride;; -} - -//------------------------------------- - -inline void CAI_BehaviorBase::ChainRunTask( int task, float taskData ) -{ - Task_t tempTask = { task, taskData }; - bool fPrevOverride = m_fOverrode; - GetOuter()->RunTask( (const Task_t *) &tempTask ); - m_fOverrode = fPrevOverride;; -} - -//------------------------------------- - -inline int CAI_BehaviorBase::BridgeTranslateSchedule( int scheduleType ) -{ - int localId = AI_IdIsGlobal( scheduleType ) ? GetClassScheduleIdSpace()->ScheduleGlobalToLocal( scheduleType ) : scheduleType; - int result = TranslateSchedule( localId ); - - return result; -} - -//------------------------------------- - -inline bool CAI_BehaviorBase::BridgeGetSchedule( int localScheduleID, CAI_Schedule **ppResult ) -{ - *ppResult = GetSchedule( localScheduleID ); - return (*ppResult != NULL ); -} - -//------------------------------------- - -inline bool CAI_BehaviorBase::BridgeTaskName( int taskID, const char **ppResult ) -{ - if ( AI_IdIsLocal( taskID ) ) - { - *ppResult = GetSchedulingSymbols()->TaskIdToSymbol( GetClassScheduleIdSpace()->TaskLocalToGlobal( taskID ) ); - return (*ppResult != NULL ); - } - return false; -} - -//------------------------------------- - -inline Activity CAI_BehaviorBase::BridgeNPC_TranslateActivity( Activity activity ) -{ - return NPC_TranslateActivity( activity ); -} - -//------------------------------------- - -inline bool CAI_BehaviorBase::BridgeIsCurTaskContinuousMove( bool *pResult ) -{ - bool fPrevOverride = m_fOverrode; - m_fOverrode = true; - *pResult = IsCurTaskContinuousMove(); - bool result = m_fOverrode; - m_fOverrode = fPrevOverride; - return result; -} - -//------------------------------------- - -inline bool CAI_BehaviorBase::BridgeFValidateHintType( CAI_Hint *pHint, bool *pResult ) -{ - bool fPrevOverride = m_fOverrode; - m_fOverrode = true; - *pResult = FValidateHintType( pHint ); - bool result = m_fOverrode; - m_fOverrode = fPrevOverride; - return result; -} - -//------------------------------------- - -inline bool CAI_BehaviorBase::BridgeIsValidEnemy( CBaseEntity *pEnemy ) -{ - return IsValidEnemy( pEnemy ); -} - -//------------------------------------- - -inline CBaseEntity *CAI_BehaviorBase::BridgeBestEnemy() -{ - return BestEnemy(); -} - -//------------------------------------- - -inline bool CAI_BehaviorBase::BridgeIsValidCover( const Vector &vLocation, CAI_Hint const *pHint ) -{ - return IsValidCover( vLocation, pHint ); -} - -//------------------------------------- - -inline bool CAI_BehaviorBase::BridgeIsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint ) -{ - return IsValidShootPosition( vLocation, pNode, pHint ); -} - -//------------------------------------- - -inline float CAI_BehaviorBase::BridgeGetMaxTacticalLateralMovement( void ) -{ - return GetMaxTacticalLateralMovement(); -} - -//------------------------------------- - -inline bool CAI_BehaviorBase::BridgeShouldIgnoreSound( CSound *pSound ) -{ - return ShouldIgnoreSound( pSound ); -} - -//------------------------------------- - -inline void CAI_BehaviorBase::BridgeOnSeeEntity( CBaseEntity *pEntity ) -{ - OnSeeEntity( pEntity ); -} - -//------------------------------------- - -inline void CAI_BehaviorBase::BridgeOnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker ) -{ - OnFriendDamaged( pSquadmate, pAttacker ); -} - -//------------------------------------- - -inline bool CAI_BehaviorBase::BridgeIsInterruptable( void ) -{ - return IsInterruptable(); -} - -//------------------------------------- - -inline bool CAI_BehaviorBase::BridgeIsNavigationUrgent( void ) -{ - return IsNavigationUrgent(); -} - -//------------------------------------- - -inline bool CAI_BehaviorBase::BridgeCanFlinch( void ) -{ - return CanFlinch(); -} - -//------------------------------------- - -inline bool CAI_BehaviorBase::BridgeIsCrouching( void ) -{ - return IsCrouching(); -} - -//------------------------------------- - -inline bool CAI_BehaviorBase::BridgeIsCrouchedActivity( Activity activity ) -{ - return IsCrouchedActivity( activity ); -} - -inline bool CAI_BehaviorBase::BridgeQueryHearSound( CSound *pSound ) -{ - return QueryHearSound( pSound ); -} - -//------------------------------------- - -inline bool CAI_BehaviorBase::BridgeCanRunAScriptedNPCInteraction( bool bForced ) -{ - return CanRunAScriptedNPCInteraction( bForced ); -} - -//------------------------------------- - -inline bool CAI_BehaviorBase::BridgeShouldPlayerAvoid( void ) -{ - return ShouldPlayerAvoid(); -} - -//------------------------------------- - -inline int CAI_BehaviorBase::BridgeOnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - return OnTakeDamage_Alive( info ); -} - -//------------------------------------- - -inline float CAI_BehaviorBase::BridgeGetReasonableFacingDist( void ) -{ - return GetReasonableFacingDist(); -} - -//------------------------------------- - -inline bool CAI_BehaviorBase::BridgeShouldAlwaysThink( bool *pResult ) -{ - bool fPrevOverride = m_fOverrode; - m_fOverrode = true; - *pResult = ShouldAlwaysThink(); - bool result = m_fOverrode; - m_fOverrode = fPrevOverride; - return result; -} - -//------------------------------------- - -inline void CAI_BehaviorBase::BridgeOnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ) -{ - OnChangeActiveWeapon( pOldWeapon, pNewWeapon ); -} - -//------------------------------------- - -inline bool CAI_BehaviorBase::BridgeSpeakMapmakerInterruptConcept( string_t iszConcept ) -{ - return SpeakMapmakerInterruptConcept( iszConcept ); -} - -//------------------------------------- - -inline void CAI_BehaviorBase::BridgeOnRestore() -{ - OnRestore(); -} - -//------------------------------------- - -inline float CAI_BehaviorBase::BridgeGetDefaultNavGoalTolerance() -{ - return GetDefaultNavGoalTolerance(); -} - -//----------------------------------------------------------------------------- - -inline Activity CAI_BehaviorBase::BridgeGetFlinchActivity( bool bHeavyDamage, bool bGesture ) -{ - return GetFlinchActivity( bHeavyDamage, bGesture ); -} - -//----------------------------------------------------------------------------- - -inline bool CAI_BehaviorBase::BridgeOnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) -{ - return OnCalcBaseMove( pMoveGoal, distClear, pResult ); -} - -//----------------------------------------------------------------------------- - -inline void CAI_BehaviorBase::BridgeModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet ) -{ - ModifyOrAppendCriteria( criteriaSet ); -} - -//----------------------------------------------------------------------------- - -inline void CAI_BehaviorBase::BridgeTeleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ) -{ - Teleport( newPosition, newAngles, newVelocity ); -} - -//----------------------------------------------------------------------------- - -inline void CAI_BehaviorBase::BridgeHandleAnimEvent( animevent_t *pEvent ) -{ - HandleAnimEvent( pEvent ); -} - -//----------------------------------------------------------------------------- - -template -inline void CAI_BehaviorHost::CleanupOnDeath( CBaseEntity *pCulprit, bool bFireDeathOutput ) -{ - DeferSchedulingToBehavior( NULL ); - for( int i = 0; i < m_Behaviors.Count(); i++ ) - { - m_Behaviors[i]->BridgeCleanupOnDeath( pCulprit, bFireDeathOutput ); - } - BaseClass::CleanupOnDeath( pCulprit, bFireDeathOutput ); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::GatherConditions() -{ - // Iterate over behaviors and call GatherConditionsNotActive() on each behavior - // not currently active. - for( int i = 0; i < m_Behaviors.Count(); i++ ) - { - if( m_Behaviors[i] != m_pCurBehavior ) - { - m_Behaviors[i]->GatherConditionsNotActive(); - } - } - - if ( m_pCurBehavior ) - m_pCurBehavior->BridgeGatherConditions(); - else - BaseClass::GatherConditions(); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::BackBridge_GatherConditions() -{ - if ( g_bBehaviorHost_PreventBaseClassGatherConditions ) - return; - - BaseClass::GatherConditions(); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::OnScheduleChange() -{ - if ( m_pCurBehavior ) - m_pCurBehavior->BridgeOnScheduleChange(); - BaseClass::OnScheduleChange(); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::OnStartSchedule( int scheduleType ) -{ - if ( m_pCurBehavior ) - m_pCurBehavior->BridgeOnStartSchedule( scheduleType ); - BaseClass::OnStartSchedule( scheduleType ); -} - -//------------------------------------- - -template -inline int CAI_BehaviorHost::BackBridge_SelectSchedule() -{ - return BaseClass::SelectSchedule(); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::BehaviorSelectSchedule() -{ - for ( int i = 0; i < m_Behaviors.Count(); i++ ) - { - if ( m_Behaviors[i]->CanSelectSchedule() && ShouldBehaviorSelectSchedule( m_Behaviors[i] ) ) - { - DeferSchedulingToBehavior( m_Behaviors[i] ); - return true; - } - } - - DeferSchedulingToBehavior( NULL ); - return false; -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::IsRunningBehavior() const -{ - return ( m_pCurBehavior != NULL ); -} - -//------------------------------------- - -template -inline CAI_BehaviorBase *CAI_BehaviorHost::GetRunningBehavior() -{ - return m_pCurBehavior; -} - -//------------------------------------- - -template -inline CAI_Schedule *CAI_BehaviorHost::GetNewSchedule() -{ - m_bCalledBehaviorSelectSchedule = false; - CAI_Schedule *pResult = BaseClass::GetNewSchedule(); - if ( !m_bCalledBehaviorSelectSchedule && m_pCurBehavior ) - DeferSchedulingToBehavior( NULL ); - return pResult; -} - -//------------------------------------- - -template -inline CAI_Schedule *CAI_BehaviorHost::GetFailSchedule() -{ - m_bCalledBehaviorSelectSchedule = false; - CAI_Schedule *pResult = BaseClass::GetFailSchedule(); - if ( !m_bCalledBehaviorSelectSchedule && m_pCurBehavior ) - DeferSchedulingToBehavior( NULL ); - return pResult; -} - -//------------------------------------ - -template -inline void CAI_BehaviorHost::ChangeBehaviorTo( CAI_BehaviorBase *pNewBehavior ) -{ - bool change = ( m_pCurBehavior != pNewBehavior ); - CAI_BehaviorBase *pOldBehavior = m_pCurBehavior; - m_pCurBehavior = pNewBehavior; - - if ( change ) - { - if ( m_pCurBehavior ) - { - m_pCurBehavior->BeginScheduleSelection(); - - g_bBehaviorHost_PreventBaseClassGatherConditions = true; - m_pCurBehavior->GatherConditions(); - g_bBehaviorHost_PreventBaseClassGatherConditions = false; - } - - if ( pOldBehavior ) - { - pOldBehavior->EndScheduleSelection(); - this->VacateStrategySlot(); - } - - OnChangeRunningBehavior( pOldBehavior, pNewBehavior ); - } -} - -//------------------------------------- - -template -inline CAI_BehaviorBase *CAI_BehaviorHost::DeferSchedulingToBehavior( CAI_BehaviorBase *pNewBehavior ) -{ - CAI_BehaviorBase *pOldBehavior = m_pCurBehavior; - ChangeBehaviorTo( pNewBehavior ); - return pOldBehavior; -} - -//------------------------------------- - -template -inline int CAI_BehaviorHost::BackBridge_TranslateSchedule( int scheduleType ) -{ - return BaseClass::TranslateSchedule( scheduleType ); -} - -//------------------------------------- - -template -inline int CAI_BehaviorHost::TranslateSchedule( int scheduleType ) -{ - if ( m_pCurBehavior ) - { - return m_pCurBehavior->BridgeTranslateSchedule( scheduleType ); - } - return BaseClass::TranslateSchedule( scheduleType ); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::PrescheduleThink() -{ - BaseClass::PrescheduleThink(); - if ( m_pCurBehavior ) - m_pCurBehavior->BridgePrescheduleThink(); -} - -//------------------------------------- - -template -inline int CAI_BehaviorHost::SelectSchedule() -{ - m_bCalledBehaviorSelectSchedule = true; - if ( m_pCurBehavior ) - { - return m_pCurBehavior->BridgeSelectSchedule(); - } - - return BaseClass::SelectSchedule(); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::KeepRunningBehavior() -{ - if ( m_pCurBehavior ) - m_bCalledBehaviorSelectSchedule = true; -} - -//------------------------------------- - -template -inline int CAI_BehaviorHost::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ) -{ - m_bCalledBehaviorSelectSchedule = true; - int result = 0; - if ( m_pCurBehavior && m_pCurBehavior->BridgeSelectFailSchedule( failedSchedule, failedTask, taskFailCode, &result ) ) - return result; - return BaseClass::SelectFailSchedule( failedSchedule, failedTask, taskFailCode ); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::StartTask( const Task_t *pTask ) -{ - if ( m_pCurBehavior && m_pCurBehavior->BridgeStartTask( pTask ) ) - return; - BaseClass::StartTask( pTask ); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::RunTask( const Task_t *pTask ) -{ - if ( m_pCurBehavior && m_pCurBehavior->BridgeRunTask( pTask ) ) - return; - BaseClass::RunTask( pTask ); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::AimGun( void ) -{ - if ( m_pCurBehavior && m_pCurBehavior->BridgeAimGun() ) - return; - BaseClass::AimGun(); -} - -//------------------------------------- - -template -inline CAI_Schedule *CAI_BehaviorHost::GetSchedule(int localScheduleID) -{ - CAI_Schedule *pResult; - if ( m_pCurBehavior && m_pCurBehavior->BridgeGetSchedule( localScheduleID, &pResult ) ) - return pResult; - return BaseClass::GetSchedule( localScheduleID ); -} - -//------------------------------------- - -template -inline const char *CAI_BehaviorHost::TaskName(int taskID) -{ - const char *pszResult = NULL; - if ( m_pCurBehavior && m_pCurBehavior->BridgeTaskName( taskID, &pszResult ) ) - return pszResult; - return BaseClass::TaskName( taskID ); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::BuildScheduleTestBits() -{ - if ( m_pCurBehavior ) - m_pCurBehavior->BridgeBuildScheduleTestBits(); - BaseClass::BuildScheduleTestBits(); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::OnChangeHintGroup( string_t oldGroup, string_t newGroup ) -{ - for( int i = 0; i < m_Behaviors.Count(); i++ ) - { - m_Behaviors[i]->BridgeOnChangeHintGroup( oldGroup, newGroup ); - } - BaseClass::OnChangeHintGroup( oldGroup, newGroup ); -} - -//------------------------------------- - -template -inline Activity CAI_BehaviorHost::BackBridge_NPC_TranslateActivity( Activity activity ) -{ - return BaseClass::NPC_TranslateActivity( activity ); -} - -//------------------------------------- - -template -inline Activity CAI_BehaviorHost::NPC_TranslateActivity( Activity activity ) -{ - if ( m_pCurBehavior ) - { - return m_pCurBehavior->BridgeNPC_TranslateActivity( activity ); - } - return BaseClass::NPC_TranslateActivity( activity ); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::IsCurTaskContinuousMove() -{ - bool result = false; - if ( m_pCurBehavior && m_pCurBehavior->BridgeIsCurTaskContinuousMove( &result ) ) - return result; - return BaseClass::IsCurTaskContinuousMove(); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::OnMovementFailed() -{ - if ( m_pCurBehavior ) - m_pCurBehavior->BridgeOnMovementFailed(); - BaseClass::OnMovementFailed(); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::OnMovementComplete() -{ - if ( m_pCurBehavior ) - m_pCurBehavior->BridgeOnMovementComplete(); - BaseClass::OnMovementComplete(); -} - -//------------------------------------- - -template -inline float CAI_BehaviorHost::GetDefaultNavGoalTolerance() -{ - if ( m_pCurBehavior ) - return m_pCurBehavior->BridgeGetDefaultNavGoalTolerance(); - return BaseClass::GetDefaultNavGoalTolerance(); -} - -//------------------------------------- - -template -inline float CAI_BehaviorHost::BackBridge_GetDefaultNavGoalTolerance() -{ - return BaseClass::GetDefaultNavGoalTolerance(); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::FValidateHintType( CAI_Hint *pHint ) -{ - bool result = false; - if ( m_pCurBehavior && m_pCurBehavior->BridgeFValidateHintType( pHint, &result ) ) - return result; - return BaseClass::FValidateHintType( pHint ); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::BackBridge_IsValidEnemy(CBaseEntity *pEnemy) -{ - return BaseClass::IsValidEnemy( pEnemy ); -} - -//------------------------------------- - -template -inline CBaseEntity *CAI_BehaviorHost::BackBridge_BestEnemy(void) -{ - return BaseClass::BestEnemy(); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::BackBridge_IsValidCover( const Vector &vLocation, CAI_Hint const *pHint ) -{ - return BaseClass::IsValidCover( vLocation, pHint ); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::BackBridge_IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint ) -{ - return BaseClass::IsValidShootPosition( vLocation, pNode, pHint ); -} - -//------------------------------------- - -template -inline float CAI_BehaviorHost::BackBridge_GetMaxTacticalLateralMovement( void ) -{ - return BaseClass::GetMaxTacticalLateralMovement(); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::BackBridge_ShouldIgnoreSound( CSound *pSound ) -{ - return BaseClass::ShouldIgnoreSound( pSound ); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::BackBridge_OnSeeEntity( CBaseEntity *pEntity ) -{ - BaseClass::OnSeeEntity( pEntity ); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::BackBridge_OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker ) -{ - BaseClass::OnFriendDamaged( pSquadmate, pAttacker ); -} - - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::BackBridge_IsInterruptable( void ) -{ - return BaseClass::IsInterruptable(); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::BackBridge_IsNavigationUrgent( void ) -{ - return BaseClass::IsNavigationUrgent(); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::BackBridge_CanFlinch( void ) -{ - return BaseClass::CanFlinch(); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::BackBridge_IsCrouching( void ) -{ - return BaseClass::IsCrouching(); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::BackBridge_IsCrouchedActivity( Activity activity ) -{ - return BaseClass::IsCrouchedActivity( activity ); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::BackBridge_QueryHearSound( CSound *pSound ) -{ - return BaseClass::QueryHearSound( pSound ); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::BackBridge_CanRunAScriptedNPCInteraction( bool bForced ) -{ - return BaseClass::CanRunAScriptedNPCInteraction( bForced ); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::BackBridge_ShouldPlayerAvoid( void ) -{ - return BaseClass::ShouldPlayerAvoid(); -} - -//------------------------------------- - -template -inline int CAI_BehaviorHost::BackBridge_OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - return BaseClass::OnTakeDamage_Alive( info ); -} - -//------------------------------------- - -template -inline float CAI_BehaviorHost::BackBridge_GetReasonableFacingDist( void ) -{ - return BaseClass::GetReasonableFacingDist(); -} - -//------------------------------------- - -template -inline Activity CAI_BehaviorHost::BackBridge_GetFlinchActivity( bool bHeavyDamage, bool bGesture ) -{ - return BaseClass::GetFlinchActivity( bHeavyDamage, bGesture ); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::BackBridge_OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) -{ - return BaseClass::OnCalcBaseMove( pMoveGoal, distClear, pResult ); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::BackBridge_ModifyOrAppendCriteria( AI_CriteriaSet &criteriaSet ) -{ - BaseClass::ModifyOrAppendCriteria( criteriaSet ); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::BackBridge_Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ) -{ - BaseClass::Teleport( newPosition, newAngles, newVelocity ); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::BackBridge_HandleAnimEvent( animevent_t *pEvent ) -{ - BaseClass::HandleAnimEvent( pEvent ); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::IsValidEnemy( CBaseEntity *pEnemy ) -{ - if ( m_pCurBehavior ) - return m_pCurBehavior->BridgeIsValidEnemy( pEnemy ); - - return BaseClass::IsValidEnemy( pEnemy ); -} - -//------------------------------------- - -template -inline CBaseEntity *CAI_BehaviorHost::BestEnemy() -{ - if ( m_pCurBehavior ) - return m_pCurBehavior->BridgeBestEnemy(); - - return BaseClass::BestEnemy(); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::ShouldAlwaysThink() -{ - bool result = false; - if ( m_pCurBehavior && m_pCurBehavior->BridgeShouldAlwaysThink( &result ) ) - return result; - return BaseClass::ShouldAlwaysThink(); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ) -{ - for( int i = 0; i < m_Behaviors.Count(); i++ ) - { - m_Behaviors[i]->BridgeOnChangeActiveWeapon( pOldWeapon, pNewWeapon ); - } - BaseClass::OnChangeActiveWeapon( pOldWeapon, pNewWeapon ); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::SpeakMapmakerInterruptConcept( string_t iszConcept ) -{ - for( int i = 0; i < m_Behaviors.Count(); i++ ) - { - if ( m_Behaviors[i]->BridgeSpeakMapmakerInterruptConcept( iszConcept ) ) - return true; - } - - return false; -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::OnRestore() -{ - for( int i = 0; i < m_Behaviors.Count(); i++ ) - { - m_Behaviors[i]->BridgeOnRestore(); - } - BaseClass::OnRestore(); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::IsValidCover( const Vector &vLocation, CAI_Hint const *pHint ) -{ - if ( m_pCurBehavior ) - return m_pCurBehavior->BridgeIsValidCover( vLocation, pHint ); - - return BaseClass::IsValidCover( vLocation, pHint ); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint ) -{ - if ( m_pCurBehavior ) - return m_pCurBehavior->BridgeIsValidShootPosition( vLocation, pNode, pHint ); - - return BaseClass::IsValidShootPosition( vLocation, pNode, pHint ); -} - -//------------------------------------- - -template -inline float CAI_BehaviorHost::GetMaxTacticalLateralMovement( void ) -{ - if ( m_pCurBehavior ) - return m_pCurBehavior->BridgeGetMaxTacticalLateralMovement(); - - return BaseClass::GetMaxTacticalLateralMovement(); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::ShouldIgnoreSound( CSound *pSound ) -{ - if ( m_pCurBehavior ) - return m_pCurBehavior->BridgeShouldIgnoreSound( pSound ); - - return BaseClass::ShouldIgnoreSound( pSound ); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::OnSeeEntity( CBaseEntity *pEntity ) -{ - if ( m_pCurBehavior ) - return m_pCurBehavior->BridgeOnSeeEntity( pEntity ); - - BaseClass::OnSeeEntity( pEntity ); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker ) -{ - if ( m_pCurBehavior ) - return m_pCurBehavior->BridgeOnFriendDamaged( pSquadmate, pAttacker ); - - BaseClass::OnFriendDamaged( pSquadmate, pAttacker ); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::IsInterruptable( void ) -{ - if ( m_pCurBehavior ) - return m_pCurBehavior->BridgeIsInterruptable(); - - return BaseClass::IsInterruptable(); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::IsNavigationUrgent( void ) -{ - if ( m_pCurBehavior ) - return m_pCurBehavior->BridgeIsNavigationUrgent(); - - return BaseClass::IsNavigationUrgent(); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::CanFlinch( void ) -{ - if ( m_pCurBehavior ) - return m_pCurBehavior->BridgeCanFlinch(); - - return BaseClass::CanFlinch(); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::IsCrouching( void ) -{ - if ( m_pCurBehavior ) - return m_pCurBehavior->BridgeIsCrouching(); - - return BaseClass::IsCrouching(); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::IsCrouchedActivity( Activity activity ) -{ - if ( m_pCurBehavior ) - return m_pCurBehavior->BridgeIsCrouchedActivity( activity ); - - return BaseClass::IsCrouchedActivity( activity ); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::QueryHearSound( CSound *pSound ) -{ - if ( m_pCurBehavior ) - return m_pCurBehavior->BridgeQueryHearSound( pSound ); - - return BaseClass::QueryHearSound( pSound ); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::CanRunAScriptedNPCInteraction( bool bForced ) -{ - if ( m_pCurBehavior ) - return m_pCurBehavior->BridgeCanRunAScriptedNPCInteraction( bForced ); - - return BaseClass::CanRunAScriptedNPCInteraction( bForced ); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::ShouldPlayerAvoid( void ) -{ - if ( m_pCurBehavior ) - return m_pCurBehavior->BridgeShouldPlayerAvoid(); - - return BaseClass::ShouldPlayerAvoid(); -} - -//------------------------------------- - -template -inline int CAI_BehaviorHost::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - if ( m_pCurBehavior ) - return m_pCurBehavior->BridgeOnTakeDamage_Alive( info ); - - return BaseClass::OnTakeDamage_Alive( info ); -} - -//------------------------------------- - -template -inline float CAI_BehaviorHost::GetReasonableFacingDist( void ) -{ - if ( m_pCurBehavior ) - return m_pCurBehavior->BridgeGetReasonableFacingDist(); - - return BaseClass::GetReasonableFacingDist(); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::Precache() -{ - BaseClass::Precache(); - for( int i = 0; i < m_Behaviors.Count(); i++ ) - { - m_Behaviors[i]->BridgePrecache(); - } -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::ScheduledMoveToGoalEntity( int scheduleType, CBaseEntity *pGoalEntity, Activity movementActivity ) -{ - // If a behavior is active, we need to stop running it - ChangeBehaviorTo( NULL ); - - return BaseClass::ScheduledMoveToGoalEntity( scheduleType, pGoalEntity, movementActivity ); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::ScheduledFollowPath( int scheduleType, CBaseEntity *pPathStart, Activity movementActivity ) -{ - // If a behavior is active, we need to stop running it - ChangeBehaviorTo( NULL ); - - return BaseClass::ScheduledFollowPath( scheduleType, pPathStart, movementActivity ); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::ForceSelectedGo(CBaseEntity *pPlayer, const Vector &targetPos, const Vector &traceDir, bool bRun) -{ - // If a behavior is active, we need to stop running it - ChangeBehaviorTo( NULL ); - - BaseClass::ForceSelectedGo(pPlayer, targetPos, traceDir, bRun); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::ForceSelectedGoRandom(void) -{ - // If a behavior is active, we need to stop running it - ChangeBehaviorTo( NULL ); - - BaseClass::ForceSelectedGoRandom(); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::NPCInit() -{ - BaseClass::NPCInit(); - for( int i = 0; i < m_Behaviors.Count(); i++ ) - { - m_Behaviors[i]->BridgeSpawn(); - } -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::UpdateOnRemove() -{ - for( int i = 0; i < m_Behaviors.Count(); i++ ) - { - m_Behaviors[i]->BridgeUpdateOnRemove(); - } - BaseClass::UpdateOnRemove(); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::Event_Killed( const CTakeDamageInfo &info ) -{ - for( int i = 0; i < m_Behaviors.Count(); i++ ) - { - m_Behaviors[i]->BridgeEvent_Killed( info ); - } - BaseClass::Event_Killed( info ); -} - -//------------------------------------- - -template -inline Activity CAI_BehaviorHost::GetFlinchActivity( bool bHeavyDamage, bool bGesture ) -{ - if ( m_pCurBehavior ) - return m_pCurBehavior->BridgeGetFlinchActivity( bHeavyDamage, bGesture ); - - return BaseClass::GetFlinchActivity( bHeavyDamage, bGesture ); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) -{ - if ( m_pCurBehavior ) - return m_pCurBehavior->BridgeOnCalcBaseMove( pMoveGoal, distClear, pResult ); - - return BaseClass::OnCalcBaseMove( pMoveGoal, distClear, pResult ); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::ModifyOrAppendCriteria( AI_CriteriaSet &criteriaSet ) -{ - BaseClass::ModifyOrAppendCriteria( criteriaSet ); - - if ( m_pCurBehavior ) - { - // Append active behavior name - criteriaSet.AppendCriteria( "active_behavior", GetRunningBehavior()->GetName() ); - - m_pCurBehavior->BridgeModifyOrAppendCriteria( criteriaSet ); - return; - } -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ) -{ - if ( m_pCurBehavior ) - { - m_pCurBehavior->BridgeTeleport( newPosition, newAngles, newVelocity ); - return; - } - - BaseClass::Teleport( newPosition, newAngles, newVelocity ); -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::HandleAnimEvent( animevent_t *pEvent ) -{ - if ( m_pCurBehavior ) - return m_pCurBehavior->BridgeHandleAnimEvent( pEvent ); - - return BaseClass::HandleAnimEvent( pEvent ); -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::OnBehaviorChangeStatus( CAI_BehaviorBase *pBehavior, bool fCanFinishSchedule ) -{ - if ( pBehavior == GetRunningBehavior() && !pBehavior->CanSelectSchedule() && !fCanFinishSchedule ) - { - DeferSchedulingToBehavior( NULL ); - return true; - } - return false; -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::OnChangeRunningBehavior( CAI_BehaviorBase *pOldBehavior, CAI_BehaviorBase *pNewBehavior ) -{ -} - -//------------------------------------- - -template -inline void CAI_BehaviorHost::AddBehavior( CAI_BehaviorBase *pBehavior ) -{ -#ifdef DEBUG - Assert( m_Behaviors.Find( pBehavior ) == m_Behaviors.InvalidIndex() ); - Assert( m_fDebugInCreateBehaviors ); - for ( int i = 0; i < m_Behaviors.Count(); i++) - { - Assert( typeid(*m_Behaviors[i]) != typeid(*pBehavior) ); - } -#endif - m_Behaviors.AddToTail( pBehavior ); - pBehavior->SetOuter( this ); - pBehavior->SetBackBridge( this ); -} - -//------------------------------------- - -template -inline CAI_BehaviorBase **CAI_BehaviorHost::AccessBehaviors() -{ - if (m_Behaviors.Count()) - return m_Behaviors.Base(); - return NULL; -} - -//------------------------------------- - -template -inline int CAI_BehaviorHost::NumBehaviors() -{ - return m_Behaviors.Count(); -} - -//------------------------------------- - -template -inline int CAI_BehaviorHost::Save( ISave &save ) -{ - int result = BaseClass::Save( save ); - if ( result ) - CAI_BehaviorBase::SaveBehaviors( save, m_pCurBehavior, AccessBehaviors(), NumBehaviors() ); - return result; -} - -//------------------------------------- - -template -inline int CAI_BehaviorHost::Restore( IRestore &restore ) -{ - int result = BaseClass::Restore( restore ); - if ( result ) - { - int iCurrent = CAI_BehaviorBase::RestoreBehaviors( restore, AccessBehaviors(), NumBehaviors() ); - if ( iCurrent != -1 ) - m_pCurBehavior = AccessBehaviors()[iCurrent]; - else - m_pCurBehavior = NULL; - } - return result; -} - -//------------------------------------- - -template -inline bool CAI_BehaviorHost::CreateComponents() -{ - if ( BaseClass::CreateComponents() ) - { -#ifdef DEBUG - m_fDebugInCreateBehaviors = true; -#endif - bool result = CreateBehaviors(); -#ifdef DEBUG - m_fDebugInCreateBehaviors = false; -#endif - return result; - } - return false; -} - -//----------------------------------------------------------------------------- - -#endif // AI_BEHAVIOR_H diff --git a/game/server/ai_behavior_assault.cpp b/game/server/ai_behavior_assault.cpp deleted file mode 100644 index 9921d9e9a..000000000 --- a/game/server/ai_behavior_assault.cpp +++ /dev/null @@ -1,1844 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// -#include "cbase.h" -#include "ai_behavior_assault.h" -#include "ai_navigator.h" -#include "ai_memory.h" -#include "ai_squad.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar ai_debug_assault("ai_debug_assault", "0"); - -BEGIN_DATADESC( CRallyPoint ) - DEFINE_KEYFIELD( m_AssaultPointName, FIELD_STRING, "assaultpoint" ), - DEFINE_KEYFIELD( m_RallySequenceName, FIELD_STRING, "rallysequence" ), - DEFINE_KEYFIELD( m_flAssaultDelay, FIELD_FLOAT, "assaultdelay" ), - DEFINE_KEYFIELD( m_iPriority, FIELD_INTEGER, "priority" ), - DEFINE_KEYFIELD( m_iStrictness, FIELD_INTEGER, "strict" ), - DEFINE_KEYFIELD( m_bForceCrouch, FIELD_BOOLEAN, "forcecrouch" ), - DEFINE_KEYFIELD( m_bIsUrgent, FIELD_BOOLEAN, "urgent" ), - DEFINE_FIELD( m_hLockedBy, FIELD_EHANDLE ), - DEFINE_FIELD( m_sExclusivity, FIELD_SHORT ), - - DEFINE_OUTPUT( m_OnArrival, "OnArrival" ), -END_DATADESC(); - -//--------------------------------------------------------- -// Purpose: Communicate exclusivity -//--------------------------------------------------------- -int CRallyPoint::DrawDebugTextOverlays() -{ - int offset; - - offset = BaseClass::DrawDebugTextOverlays(); - if ( (m_debugOverlays & OVERLAY_TEXT_BIT) ) - { - switch( m_sExclusivity ) - { - case RALLY_EXCLUSIVE_NOT_EVALUATED: - EntityText( offset, "Exclusive: Not Evaluated", 0 ); - break; - case RALLY_EXCLUSIVE_YES: - EntityText( offset, "Exclusive: YES", 0 ); - break; - case RALLY_EXCLUSIVE_NO: - EntityText( offset, "Exclusive: NO", 0 ); - break; - default: - EntityText( offset, "Exclusive: !?INVALID?!", 0 ); - break; - } - offset++; - - if( IsLocked() ) - EntityText( offset, "LOCKED.", 0 ); - else - EntityText( offset, "Available", 0 ); - - offset++; - } - - return offset; -} - -//--------------------------------------------------------- -// Purpose: If a rally point is 'exclusive' that means that -// anytime an NPC is anywhere on the assault chain that -// begins with this rally point, the assault is considered -// 'exclusive' and no other NPCs will be allowed to use it -// until the current NPC clears the entire assault chain -// or dies. -// -// If exclusivity has not been determined the first time -// this function is called, it will be computed and cached -//--------------------------------------------------------- -bool CRallyPoint::IsExclusive() -{ -#ifndef HL2_EPISODIC // IF NOT EPISODIC - // This 'exclusivity' concept is new to EP2. We're only willing to - // risk causing problems in EP1, so emulate the old behavior if - // we are not EPISODIC. We must do this by setting m_sExclusivity - // so that ent_text will properly report the state. - m_sExclusivity = RALLY_EXCLUSIVE_NO; -#else - if( m_sExclusivity == RALLY_EXCLUSIVE_NOT_EVALUATED ) - { - // We need to evaluate! Walk the chain of assault points - // and if *ANY* assault points on this assault chain - // are set to Never Time Out then set this rally point to - // be exclusive to stop other NPC's walking down the chain - // and ending up clumped up at the infinite rally point. - CAssaultPoint *pAssaultEnt = (CAssaultPoint *)gEntList.FindEntityByName( NULL, m_AssaultPointName ); - - if( !pAssaultEnt ) - { - // Well, this is awkward. Leave it up to other assault code to tattle on the missing assault point. - // We will just assume this assault is not exclusive. - m_sExclusivity = RALLY_EXCLUSIVE_NO; - return false; - } - - // Otherwise, we start by assuming this assault chain is not exclusive. - m_sExclusivity = RALLY_EXCLUSIVE_NO; - - if( pAssaultEnt ) - { - CAssaultPoint *pFirstAssaultEnt = pAssaultEnt; //some assault chains are circularly linked - - do - { - if( pAssaultEnt->m_bNeverTimeout ) - { - // We found a never timeout assault point! That makes this whole chain exclusive. - m_sExclusivity = RALLY_EXCLUSIVE_YES; - break; - } - - pAssaultEnt = (CAssaultPoint *)gEntList.FindEntityByName( NULL, pAssaultEnt->m_NextAssaultPointName ); - - } while( (pAssaultEnt != NULL) && (pAssaultEnt != pFirstAssaultEnt) ); - - } - } -#endif// HL2_EPISODIC - - return (m_sExclusivity == RALLY_EXCLUSIVE_YES); -} - - -BEGIN_DATADESC( CAssaultPoint ) - DEFINE_KEYFIELD( m_AssaultHintGroup, FIELD_STRING, "assaultgroup" ), - DEFINE_KEYFIELD( m_NextAssaultPointName, FIELD_STRING, "nextassaultpoint" ), - DEFINE_KEYFIELD( m_flAssaultTimeout, FIELD_FLOAT, "assaulttimeout" ), - DEFINE_KEYFIELD( m_bClearOnContact, FIELD_BOOLEAN, "clearoncontact" ), - DEFINE_KEYFIELD( m_bAllowDiversion, FIELD_BOOLEAN, "allowdiversion" ), - DEFINE_KEYFIELD( m_flAllowDiversionRadius, FIELD_FLOAT, "allowdiversionradius" ), - DEFINE_KEYFIELD( m_bNeverTimeout, FIELD_BOOLEAN, "nevertimeout" ), - DEFINE_KEYFIELD( m_iStrictness, FIELD_INTEGER, "strict" ), - DEFINE_KEYFIELD( m_bForceCrouch, FIELD_BOOLEAN, "forcecrouch" ), - DEFINE_KEYFIELD( m_bIsUrgent, FIELD_BOOLEAN, "urgent" ), - DEFINE_FIELD( m_bInputForcedClear, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_flAssaultPointTolerance, FIELD_FLOAT, "assaulttolerance" ), - DEFINE_FIELD( m_flTimeLastUsed, FIELD_TIME ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_BOOLEAN, "SetClearOnContact", InputSetClearOnContact ), - DEFINE_INPUTFUNC( FIELD_BOOLEAN, "SetAllowDiversion", InputSetAllowDiversion ), - DEFINE_INPUTFUNC( FIELD_BOOLEAN, "SetForceClear", InputSetForceClear ), - - // Outputs - DEFINE_OUTPUT( m_OnArrival, "OnArrival" ), - DEFINE_OUTPUT( m_OnAssaultClear, "OnAssaultClear" ), -END_DATADESC(); - -LINK_ENTITY_TO_CLASS( assault_rallypoint, CRallyPoint ); // just a copy of info_target for now -LINK_ENTITY_TO_CLASS( assault_assaultpoint, CAssaultPoint ); // has its own class because it needs the entity I/O - -BEGIN_DATADESC( CAI_AssaultBehavior ) - DEFINE_FIELD( m_hAssaultPoint, FIELD_EHANDLE ), - DEFINE_FIELD( m_hRallyPoint, FIELD_EHANDLE ), - DEFINE_FIELD( m_AssaultCue, FIELD_INTEGER ), - DEFINE_FIELD( m_ReceivedAssaultCue, FIELD_INTEGER ), - DEFINE_FIELD( m_bHitRallyPoint, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bHitAssaultPoint, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bDiverting, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flLastSawAnEnemyAt, FIELD_FLOAT ), - DEFINE_FIELD( m_flTimeDeferScheduleSelection, FIELD_TIME ), - DEFINE_FIELD( m_AssaultPointName, FIELD_STRING ) -END_DATADESC(); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_AssaultBehavior::CanRunAScriptedNPCInteraction( bool bForced ) -{ - if ( m_AssaultCue == CUE_NO_ASSAULT ) - { - // It's OK with the assault behavior, so leave it up to the base class. - return BaseClass::CanRunAScriptedNPCInteraction( bForced ); - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CAI_AssaultBehavior::CAI_AssaultBehavior() -{ - m_AssaultCue = CUE_NO_ASSAULT; -} - -//----------------------------------------------------------------------------- -// Purpose: Draw any text overlays -// Input : Previous text offset from the top -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CAI_AssaultBehavior::DrawDebugTextOverlays( int text_offset ) -{ - char tempstr[ 512 ]; - int offset; - - offset = BaseClass::DrawDebugTextOverlays( text_offset ); - if ( GetOuter()->m_debugOverlays & OVERLAY_TEXT_BIT ) - { - Q_snprintf( tempstr, sizeof(tempstr), "Assault Point: %s %s", STRING( m_AssaultPointName ), VecToString( m_hAssaultPoint->GetAbsOrigin() ) ); - GetOuter()->EntityText( offset, tempstr, 0 ); - offset++; - } - - return offset; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : cue - -//----------------------------------------------------------------------------- -void CAI_AssaultBehavior::ReceiveAssaultCue( AssaultCue_t cue ) -{ - if ( GetOuter() ) - GetOuter()->ForceDecisionThink(); - - m_ReceivedAssaultCue = cue; - - SetCondition( COND_PROVOKED ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CAI_AssaultBehavior::AssaultHasBegun() -{ - if( m_AssaultCue == CUE_DONT_WAIT && IsRunning() && m_bHitRallyPoint ) - { - return true; - } - - return m_ReceivedAssaultCue == m_AssaultCue; -} - -//----------------------------------------------------------------------------- -// Purpose: Find an assaultpoint matching the iszAssaultPointName. -// If more than one assault point of this type is found, randomly -// use any of them EXCEPT the one most recently used. -//----------------------------------------------------------------------------- -CAssaultPoint *CAI_AssaultBehavior::FindAssaultPoint( string_t iszAssaultPointName ) -{ - CUtlVectorpAssaultPoints; - CUtlVectorpClearAssaultPoints; - - CAssaultPoint *pAssaultEnt = (CAssaultPoint *)gEntList.FindEntityByName( NULL, iszAssaultPointName ); - - while( pAssaultEnt != NULL ) - { - pAssaultPoints.AddToTail( pAssaultEnt ); - pAssaultEnt = (CAssaultPoint *)gEntList.FindEntityByName( pAssaultEnt, iszAssaultPointName ); - } - - // Didn't find any?! - if( pAssaultPoints.Count() < 1 ) - return NULL; - - // Only found one, just return it. - if( pAssaultPoints.Count() == 1 ) - return pAssaultPoints[0]; - - // Throw out any nodes that I cannot fit my bounding box on. - for( int i = 0 ; i < pAssaultPoints.Count() ; i++ ) - { - trace_t tr; - CAI_BaseNPC *pNPC = GetOuter(); - CAssaultPoint *pAssaultPoint = pAssaultPoints[i]; - - AI_TraceHull ( pAssaultPoint->GetAbsOrigin(), pAssaultPoint->GetAbsOrigin(), pNPC->WorldAlignMins(), pNPC->WorldAlignMaxs(), MASK_SOLID, pNPC, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction == 1.0 ) - { - // Copy this into the list of clear points. - pClearAssaultPoints.AddToTail(pAssaultPoint); - } - } - - // Only one clear assault point left! - if( pClearAssaultPoints.Count() == 1 ) - return pClearAssaultPoints[0]; - - // NONE left. Just return a random assault point, knowing that it's blocked. This is the old behavior, anyway. - if( pClearAssaultPoints.Count() < 1 ) - return pAssaultPoints[ random->RandomInt(0, (pAssaultPoints.Count() - 1)) ]; - - // We found several! First throw out the one most recently used. - // This prevents picking the same point at this branch twice in a row. - float flMostRecentTime = -1.0f; // Impossibly old - int iMostRecentIndex = -1; - for( int i = 0 ; i < pClearAssaultPoints.Count() ; i++ ) - { - if( pClearAssaultPoints[i]->m_flTimeLastUsed > flMostRecentTime ) - { - flMostRecentTime = pClearAssaultPoints[i]->m_flTimeLastUsed; - iMostRecentIndex = i; - } - } - - Assert( iMostRecentIndex > -1 ); - - // Remove the most recently used - pClearAssaultPoints.Remove( iMostRecentIndex ); - return pClearAssaultPoints[ random->RandomInt(0, (pClearAssaultPoints.Count() - 1)) ]; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_AssaultBehavior::SetAssaultPoint( CAssaultPoint *pAssaultPoint ) -{ - m_hAssaultPoint = pAssaultPoint; - pAssaultPoint->m_flTimeLastUsed = gpGlobals->curtime; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_AssaultBehavior::ClearAssaultPoint( void ) -{ - // To announce clear means that this NPC hasn't seen any live targets in - // the assault area for the length of time the level designer has - // specified that they should be vigilant. This effectively deactivates - // the assault behavior. - // This can also be happen if an assault point has ClearOnContact set, and - // an NPC assaulting to this point has seen an enemy. - - // keep track of the name of the assault point - m_AssaultPointName = m_hAssaultPoint->m_NextAssaultPointName; - - // Do we need to move to another assault point? - if( m_hAssaultPoint->m_NextAssaultPointName != NULL_STRING ) - { - CAssaultPoint *pNextPoint = FindAssaultPoint( m_hAssaultPoint->m_NextAssaultPointName ); - - if( pNextPoint ) - { - SetAssaultPoint( pNextPoint ); - - // Send our NPC to the next assault point! - m_bHitAssaultPoint = false; - - return; - } - else - { - DevMsg("**ERROR: Can't find next assault point: %s\n", STRING(m_hAssaultPoint->m_NextAssaultPointName) ); - - // Bomb out of assault behavior. - m_AssaultCue = CUE_NO_ASSAULT; - ClearSchedule( "Can't find next assault point" ); - - return; - } - } - - // Just set the cue back to NO_ASSAULT. This disables the behavior. - m_AssaultCue = CUE_NO_ASSAULT; - - // Exclusive or not, we unlock here. The assault is done. - UnlockRallyPoint(); - - // If this assault behavior has changed the NPC's hint group, - // slam that NPC's hint group back to null. - // !!!TODO: if the NPC had a different hint group before the - // assault began, we're slamming that, too! We might want - // to cache it off if this becomes a problem (sjb) - if( m_hAssaultPoint->m_AssaultHintGroup != NULL_STRING ) - { - GetOuter()->SetHintGroup( NULL_STRING ); - } - - m_hAssaultPoint->m_OnAssaultClear.FireOutput( GetOuter(), GetOuter(), 0 ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_AssaultBehavior::OnHitAssaultPoint( void ) -{ - GetOuter()->SpeakSentence( ASSAULT_SENTENCE_HIT_ASSAULT_POINT ); - m_bHitAssaultPoint = true; - m_hAssaultPoint->m_OnArrival.FireOutput( GetOuter(), m_hAssaultPoint, 0 ); - - // Set the assault hint group - if( m_hAssaultPoint->m_AssaultHintGroup != NULL_STRING ) - { - SetHintGroup( m_hAssaultPoint->m_AssaultHintGroup ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_AssaultBehavior::GatherConditions( void ) -{ - BaseClass::GatherConditions(); - - // If this NPC is moving towards an assault point which - // a) Has a Next Assault Point, and - // b) Is flagged to Clear On Arrival, - // then hit and clear the assault point (fire all entity I/O) and move on to the next one without - // interrupting the NPC's schedule. This provides a more fluid movement from point to point. - if( IsCurSchedule( SCHED_MOVE_TO_ASSAULT_POINT ) && hl2_episodic.GetBool() ) - { - if( m_hAssaultPoint && m_hAssaultPoint->HasSpawnFlags(SF_ASSAULTPOINT_CLEARONARRIVAL) && m_hAssaultPoint->m_NextAssaultPointName != NULL_STRING ) - { - float flDist = GetAbsOrigin().DistTo( m_hAssaultPoint->GetAbsOrigin() ); - - if( flDist <= GetOuter()->GetMotor()->MinStoppingDist() ) - { - OnHitAssaultPoint(); - ClearAssaultPoint(); - - AI_NavGoal_t goal( m_hAssaultPoint->GetAbsOrigin() ); - goal.pTarget = m_hAssaultPoint; - - if ( GetNavigator()->SetGoal( goal ) == false ) - { - TaskFail( "Can't refresh assault path" ); - } - } - } - } - - if ( IsForcingCrouch() && GetOuter()->IsCrouching() ) - { - ClearCondition( COND_HEAR_BULLET_IMPACT ); - } - - if( OnStrictAssault() ) - { - // Don't get distracted. Die trying if you have to. - ClearCondition( COND_HEAR_DANGER ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTask - -//----------------------------------------------------------------------------- -void CAI_AssaultBehavior::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_RANGE_ATTACK1: - BaseClass::StartTask( pTask ); - break; - - case TASK_ASSAULT_DEFER_SCHEDULE_SELECTION: - m_flTimeDeferScheduleSelection = gpGlobals->curtime + pTask->flTaskData; - TaskComplete(); - break; - - case TASK_ASSAULT_MOVE_AWAY_PATH: - break; - - case TASK_ANNOUNCE_CLEAR: - { - // If we're at an assault point that can never be cleared, keep waiting forever (if it's the last point in the assault) - if ( m_hAssaultPoint && - !m_hAssaultPoint->HasSpawnFlags( SF_ASSAULTPOINT_CLEARONARRIVAL ) && - m_hAssaultPoint->m_bNeverTimeout && - m_hAssaultPoint->m_NextAssaultPointName == NULL_STRING ) - { - TaskComplete(); - return; - } - - ClearAssaultPoint(); - TaskComplete(); - } - break; - - case TASK_WAIT_ASSAULT_DELAY: - { - if( m_hRallyPoint ) - { - GetOuter()->SetWait( m_hRallyPoint->m_flAssaultDelay ); - } - else - { - TaskComplete(); - } - } - break; - - case TASK_AWAIT_ASSAULT_TIMEOUT: - // Maintain vigil for as long as the level designer has asked. Wait - // and look for targets. - GetOuter()->SetWait( m_hAssaultPoint->m_flAssaultTimeout ); - break; - - case TASK_GET_PATH_TO_RALLY_POINT: - { - AI_NavGoal_t goal( m_hRallyPoint->GetAbsOrigin() ); - goal.pTarget = m_hRallyPoint; - if ( GetNavigator()->SetGoal( goal ) == false ) - { - // Try and get as close as possible otherwise - AI_NavGoal_t nearGoal( GOALTYPE_LOCATION_NEAREST_NODE, m_hRallyPoint->GetAbsOrigin(), AIN_DEF_ACTIVITY, 256 ); - if ( GetNavigator()->SetGoal( nearGoal, AIN_CLEAR_PREVIOUS_STATE ) ) - { - //FIXME: HACK! The internal pathfinding is setting this without our consent, so override it! - ClearCondition( COND_TASK_FAILED ); - GetNavigator()->SetArrivalDirection( m_hRallyPoint->GetAbsAngles() ); - TaskComplete(); - return; - } - } - GetNavigator()->SetArrivalDirection( m_hRallyPoint->GetAbsAngles() ); - } - break; - - case TASK_FACE_RALLY_POINT: - { - UpdateForceCrouch(); - - GetMotor()->SetIdealYaw( m_hRallyPoint->GetAbsAngles().y ); - GetOuter()->SetTurnActivity(); - } - break; - - case TASK_GET_PATH_TO_ASSAULT_POINT: - { - AI_NavGoal_t goal( m_hAssaultPoint->GetAbsOrigin() ); - goal.pTarget = m_hAssaultPoint; - if ( GetNavigator()->SetGoal( goal ) == false ) - { - // Try and get as close as possible otherwise - AI_NavGoal_t nearGoal( GOALTYPE_LOCATION_NEAREST_NODE, m_hAssaultPoint->GetAbsOrigin(), AIN_DEF_ACTIVITY, 256 ); - if ( GetNavigator()->SetGoal( nearGoal, AIN_CLEAR_PREVIOUS_STATE ) ) - { - //FIXME: HACK! The internal pathfinding is setting this without our consent, so override it! - ClearCondition( COND_TASK_FAILED ); - GetNavigator()->SetArrivalDirection( m_hAssaultPoint->GetAbsAngles() ); - TaskComplete(); - return; - } - } - GetNavigator()->SetArrivalDirection( m_hAssaultPoint->GetAbsAngles() ); - } - break; - - case TASK_FACE_ASSAULT_POINT: - { - UpdateForceCrouch(); - - if( HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - { - // If I can already fight when I arrive, don't bother running any facing code. Let - // The combat AI do that. Turning here will only make the NPC look dumb in a combat - // situation because it will take time to turn before attacking. - TaskComplete(); - } - else - { - GetMotor()->SetIdealYaw( m_hAssaultPoint->GetAbsAngles().y ); - GetOuter()->SetTurnActivity(); - } - } - break; - - case TASK_HIT_ASSAULT_POINT: - OnHitAssaultPoint(); - TaskComplete(); - break; - - case TASK_HIT_RALLY_POINT: - // Once we're stading on it and facing the correct direction, - // we have arrived at rally point. - GetOuter()->SpeakSentence( ASSAULT_SENTENCE_HIT_RALLY_POINT ); - - m_bHitRallyPoint = true; - m_hRallyPoint->m_OnArrival.FireOutput( GetOuter(), m_hRallyPoint, 0 ); - - TaskComplete(); - break; - - case TASK_AWAIT_CUE: - if( PollAssaultCue() ) - { - TaskComplete(); - } - else - { - // Don't do anything if we've been told to crouch - if ( IsForcingCrouch() ) - break; - - else if( m_hRallyPoint->m_RallySequenceName != NULL_STRING ) - { - // The cue hasn't been given yet, so set to the rally sequence. - int sequence = GetOuter()->LookupSequence( STRING( m_hRallyPoint->m_RallySequenceName ) ); - if( sequence != -1 ) - { - GetOuter()->ResetSequence( sequence ); - GetOuter()->SetIdealActivity( ACT_DO_NOT_DISTURB ); - } - } - else - { - // Only chain this task if I'm not playing a custom animation - if( GetOuter()->GetEnemy() ) - { - ChainStartTask( TASK_FACE_ENEMY, 0 ); - } - } - } - break; - - default: - BaseClass::StartTask( pTask ); - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTask - -//----------------------------------------------------------------------------- -void CAI_AssaultBehavior::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_WAIT_ASSAULT_DELAY: - case TASK_AWAIT_ASSAULT_TIMEOUT: - if ( m_hAssaultPoint ) - { - if ( m_hAssaultPoint->m_bInputForcedClear || (m_hAssaultPoint->m_bClearOnContact && HasCondition( COND_SEE_ENEMY )) ) - { - // If we're on an assault that should clear on contact, clear when we see an enemy - TaskComplete(); - } - } - - if( GetOuter()->IsWaitFinished() && ( pTask->iTask == TASK_WAIT_ASSAULT_DELAY || !m_hAssaultPoint->m_bNeverTimeout ) ) - { - TaskComplete(); - } - break; - - case TASK_FACE_RALLY_POINT: - case TASK_FACE_ASSAULT_POINT: - GetMotor()->UpdateYaw(); - - if( HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - { - // Out early if the NPC can attack. - TaskComplete(); - } - - if ( GetOuter()->FacingIdeal() ) - { - TaskComplete(); - } - break; - - case TASK_AWAIT_CUE: - // If we've lost our rally point, abort - if ( !m_hRallyPoint ) - { - TaskFail("No rally point."); - break; - } - - if( PollAssaultCue() ) - { - TaskComplete(); - } - - if ( IsForcingCrouch() ) - break; - - if( GetOuter()->GetEnemy() && m_hRallyPoint->m_RallySequenceName == NULL_STRING && !HasCondition(COND_ENEMY_OCCLUDED) ) - { - // I have an enemy and I'm NOT playing a custom animation. - ChainRunTask( TASK_FACE_ENEMY, 0 ); - } - break; - - case TASK_WAIT_FOR_MOVEMENT: - if ( ai_debug_assault.GetBool() ) - { - if ( IsCurSchedule( SCHED_MOVE_TO_ASSAULT_POINT ) ) - { - NDebugOverlay::Line( WorldSpaceCenter(), GetNavigator()->GetGoalPos(), 255,0,0, true,0.1); - NDebugOverlay::Box( GetNavigator()->GetGoalPos(), -Vector(10,10,10), Vector(10,10,10), 255,0,0, 8, 0.1 ); - } - else if ( IsCurSchedule( SCHED_MOVE_TO_RALLY_POINT ) ) - { - NDebugOverlay::Line( WorldSpaceCenter(), GetNavigator()->GetGoalPos(), 0,255,0, true,0.1); - NDebugOverlay::Box( GetNavigator()->GetGoalPos(), -Vector(10,10,10), Vector(10,10,10), 0,255,0, 8, 0.1 ); - } - } - - if ( m_hAssaultPoint && (m_hAssaultPoint->m_bInputForcedClear || (m_hAssaultPoint->m_bClearOnContact && HasCondition( COND_SEE_ENEMY ))) ) - { - DevMsg( "Assault Cleared due to Contact or Input!\n" ); - ClearAssaultPoint(); - TaskComplete(); - return; - } - - if ( ( ( !GetOuter()->DidChooseEnemy() && gpGlobals->curtime - GetOuter()->GetTimeEnemyAcquired() > 1 ) || !GetOuter()->GetEnemy() ) ) - { - CBaseEntity *pNewEnemy = GetOuter()->BestEnemy(); - - if( pNewEnemy != NULL && pNewEnemy != GetOuter()->GetEnemy() ) - { - GetOuter()->SetEnemy( pNewEnemy ); - GetOuter()->SetState( NPC_STATE_COMBAT ); - } - } - - BaseClass::RunTask( pTask ); - break; - - default: - BaseClass::RunTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CRallyPoint *CAI_AssaultBehavior::FindBestRallyPointInRadius( const Vector &vecCenter, float flRadius ) -{ - VPROF_BUDGET( "CAI_AssaultBehavior::FindBestRallyPointInRadius", VPROF_BUDGETGROUP_NPCS ); - - const int RALLY_SEARCH_ENTS = 30; - CBaseEntity *pEntities[RALLY_SEARCH_ENTS]; - int iNumEntities = UTIL_EntitiesInSphere( pEntities, RALLY_SEARCH_ENTS, vecCenter, flRadius, 0 ); - - CRallyPoint *pBest = NULL; - int iBestPriority = -1; - - for ( int i = 0; i < iNumEntities; i++ ) - { - CRallyPoint *pRallyEnt = dynamic_cast(pEntities[i]); - - if( pRallyEnt ) - { - if( !pRallyEnt->IsLocked() ) - { - // Consider this point. - if( pRallyEnt->m_iPriority > iBestPriority ) - { - pBest = pRallyEnt; - iBestPriority = pRallyEnt->m_iPriority; - } - } - } - } - - return pBest; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CAI_AssaultBehavior::IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint ) -{ - CBaseEntity *pCuePoint = NULL; - float flTolerance = 0.0f; - - if( m_bHitRallyPoint && !m_bHitAssaultPoint && !AssaultHasBegun() ) - { - if( m_hRallyPoint != NULL ) - { - pCuePoint = m_hRallyPoint; - flTolerance = CUE_POINT_TOLERANCE; - } - } - else if( m_bHitAssaultPoint ) - { - if( m_hAssaultPoint != NULL ) - { - pCuePoint = m_hAssaultPoint; - flTolerance = m_hAssaultPoint->m_flAssaultPointTolerance; - } - } - - if ( pCuePoint && (vLocation - pCuePoint->GetAbsOrigin()).Length2DSqr() > Square( flTolerance - 0.1 ) ) - return false; - - return BaseClass::IsValidShootPosition( vLocation, pNode, pHint ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -float CAI_AssaultBehavior::GetMaxTacticalLateralMovement( void ) -{ - return CUE_POINT_TOLERANCE - 0.1; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_AssaultBehavior::UpdateOnRemove() -{ - // Ignore exclusivity. Our NPC just died. - UnlockRallyPoint(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_AssaultBehavior::OnStrictAssault( void ) -{ - return (m_hAssaultPoint && m_hAssaultPoint->m_iStrictness); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_AssaultBehavior::UpdateForceCrouch( void ) -{ - if ( IsForcingCrouch() ) - { - // Only force crouch when we're near the point we're supposed to crouch at - float flDistanceToTargetSqr = GetOuter()->GetAbsOrigin().DistToSqr( AssaultHasBegun() ? m_hAssaultPoint->GetAbsOrigin() : m_hRallyPoint->GetAbsOrigin() ); - if ( flDistanceToTargetSqr < (64*64) ) - { - GetOuter()->ForceCrouch(); - } - else - { - GetOuter()->ClearForceCrouch(); - } - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_AssaultBehavior::IsForcingCrouch( void ) -{ - if ( AssaultHasBegun() ) - return (m_hAssaultPoint && m_hAssaultPoint->m_bForceCrouch); - - return (m_hRallyPoint && m_hRallyPoint->m_bForceCrouch); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_AssaultBehavior::IsUrgent( void ) -{ - if ( AssaultHasBegun() ) - return (m_hAssaultPoint && m_hAssaultPoint->m_bIsUrgent); - - return (m_hRallyPoint && m_hRallyPoint->m_bIsUrgent); -} - -//----------------------------------------------------------------------------- -// Purpose: Unlock any rally points the behavior is currently locking -//----------------------------------------------------------------------------- -void CAI_AssaultBehavior::UnlockRallyPoint( void ) -{ - CAI_AssaultBehavior *pBehavior; - if ( GetOuter()->GetBehavior( &pBehavior ) ) - { - if( pBehavior->m_hRallyPoint ) - { - pBehavior->m_hRallyPoint->Unlock( GetOuter() ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pRallyPoint - -// assaultcue - -//----------------------------------------------------------------------------- -void CAI_AssaultBehavior::SetParameters( CBaseEntity *pRallyEnt, AssaultCue_t assaultcue ) -{ - VPROF_BUDGET( "CAI_AssaultBehavior::SetParameters", VPROF_BUDGETGROUP_NPCS ); - - // Clean up any soon to be dangling rally points - UnlockRallyPoint(); - - // Firstly, find a rally point. - CRallyPoint *pRallyPoint = dynamic_cast(pRallyEnt); - - if( pRallyPoint ) - { - if( !pRallyPoint->IsLocked() ) - { - // Claim it. - m_hRallyPoint = pRallyPoint; - m_hRallyPoint->Lock( GetOuter() ); - - m_AssaultCue = assaultcue; - InitializeBehavior(); - return; - } - else - { - DevMsg("**ERROR: Specified a rally point that is LOCKED!\n" ); - } - } - else - { - DevMsg("**ERROR: Bad RallyPoint in SetParameters\n" ); - - // Bomb out of assault behavior. - m_AssaultCue = CUE_NO_ASSAULT; - ClearSchedule( "Bad rally point" ); - } - -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : rallypointname - -// assaultcue - -//----------------------------------------------------------------------------- -void CAI_AssaultBehavior::SetParameters( string_t rallypointname, AssaultCue_t assaultcue, int rallySelectMethod ) -{ - VPROF_BUDGET( "CAI_AssaultBehavior::SetParameters", VPROF_BUDGETGROUP_NPCS ); - - // Clean up any soon to be dangling rally points - UnlockRallyPoint(); - - // Firstly, find a rally point. - CRallyPoint *pRallyEnt = dynamic_cast(gEntList.FindEntityByName( NULL, rallypointname ) ); - - CRallyPoint *pBest = NULL; - int iBestPriority = -1; - - switch( rallySelectMethod ) - { - case RALLY_POINT_SELECT_DEFAULT: - { - while( pRallyEnt ) - { - if( !pRallyEnt->IsLocked() ) - { - // Consider this point. - if( pRallyEnt->m_iPriority > iBestPriority ) - { - // This point is higher priority. I must take it. - pBest = pRallyEnt; - iBestPriority = pRallyEnt->m_iPriority; - } - else if ( pRallyEnt->m_iPriority == iBestPriority ) - { - // This point is the same priority as my current best. - // I must take it if it is closer. - Vector vecStart = GetOuter()->GetAbsOrigin(); - - float flNewDist, flBestDist; - - flNewDist = ( pRallyEnt->GetAbsOrigin() - vecStart ).LengthSqr(); - flBestDist = ( pBest->GetAbsOrigin() - vecStart ).LengthSqr(); - - if( flNewDist < flBestDist ) - { - // Priority is already identical. Just take this point. - pBest = pRallyEnt; - } - } - } - - pRallyEnt = dynamic_cast(gEntList.FindEntityByName( pRallyEnt, rallypointname, NULL ) ); - } - } - break; - - case RALLY_POINT_SELECT_RANDOM: - { - // Gather all available points into a utilvector, then pick one at random. - - CUtlVector rallyPoints; // List of rally points that are available to choose from. - - while( pRallyEnt ) - { - if( !pRallyEnt->IsLocked() ) - { - rallyPoints.AddToTail( pRallyEnt ); - } - - pRallyEnt = dynamic_cast(gEntList.FindEntityByName( pRallyEnt, rallypointname ) ); - } - - if( rallyPoints.Count() > 0 ) - { - pBest = rallyPoints[ random->RandomInt(0, rallyPoints.Count()- 1) ]; - } - } - break; - - default: - DevMsg( "ERROR: INVALID RALLY POINT SELECTION METHOD. Assault will not function.\n"); - break; - } - - if( !pBest ) - { - DevMsg("%s Didn't find a best rally point!\n", GetOuter()->GetEntityName().ToCStr() ); - return; - } - - pBest->Lock( GetOuter() ); - m_hRallyPoint = pBest; - - if( !m_hRallyPoint ) - { - DevMsg("**ERROR: Can't find a rally point named '%s'\n", STRING( rallypointname )); - - // Bomb out of assault behavior. - m_AssaultCue = CUE_NO_ASSAULT; - ClearSchedule( "Can't find rally point" ); - return; - } - - m_AssaultCue = assaultcue; - InitializeBehavior(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_AssaultBehavior::InitializeBehavior() -{ - // initialize the variables that track whether the NPC has reached (hit) - // his rally and assault points already. Be advised, having hit the point - // only means you have been to it at some point. Doesn't mean you're standing - // there still. Mainly used to understand which 'phase' of the assault an NPC - // is in. - m_bHitRallyPoint = false; - m_bHitAssaultPoint = false; - - m_hAssaultPoint = false; - - m_bDiverting = false; - m_flLastSawAnEnemyAt = 0; - - // Also reset the status of externally received assault cues - m_ReceivedAssaultCue = CUE_NO_ASSAULT; - - CAssaultPoint *pAssaultEnt = FindAssaultPoint( m_hRallyPoint->m_AssaultPointName ); - - if( pAssaultEnt ) - { - SetAssaultPoint(pAssaultEnt); - } - else - { - DevMsg("**ERROR: Can't find any assault points named: %s\n", STRING( m_hRallyPoint->m_AssaultPointName )); - - // Bomb out of assault behavior. - m_AssaultCue = CUE_NO_ASSAULT; - ClearSchedule( "Can't find assault point" ); - return; - } - - // Slam the NPC's schedule so that he starts picking Assault schedules right now. - ClearSchedule( "Initializing assault behavior" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Check conditions and see if the cue to being an assault has come. -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_AssaultBehavior::PollAssaultCue( void ) -{ - // right now, always go when the commander says. - if( m_ReceivedAssaultCue == CUE_COMMANDER ) - { - return true; - } - - switch( m_AssaultCue ) - { - case CUE_NO_ASSAULT: - // NO_ASSAULT never ever triggers. - return false; - break; - - case CUE_ENTITY_INPUT: - return m_ReceivedAssaultCue == CUE_ENTITY_INPUT; - break; - - case CUE_PLAYER_GUNFIRE: - // Any gunfire will trigger this right now (sjb) - if( HasCondition( COND_HEAR_COMBAT ) ) - { - return true; - } - break; - - case CUE_DONT_WAIT: - // Just keep going! - m_ReceivedAssaultCue = CUE_DONT_WAIT; - return true; - break; - - case CUE_COMMANDER: - // Player told me to go, so go! - return m_ReceivedAssaultCue == CUE_COMMANDER; - break; - - default: - break; - } - - return false; -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -void CAI_AssaultBehavior::OnRestore() -{ - if ( !m_hAssaultPoint || !m_hRallyPoint ) - { - Disable(); - NotifyChangeBehaviorStatus(); - } - -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_AssaultBehavior::CanSelectSchedule() -{ - if ( !GetOuter()->IsInterruptable() ) - return false; - - if ( GetOuter()->HasCondition( COND_RECEIVED_ORDERS ) ) - return false; - - // We're letting other AI run for a little while because the assault AI failed recently. - if ( m_flTimeDeferScheduleSelection > gpGlobals->curtime ) - return false; - - // No schedule selection if no assault is being conducted. - if( m_AssaultCue == CUE_NO_ASSAULT ) - return false; - - if ( !m_hAssaultPoint || !m_hRallyPoint ) - { - Disable(); - return false; - } - - // Remember when we last saw an enemy - if ( GetEnemy() ) - { - m_flLastSawAnEnemyAt = gpGlobals->curtime; - } - - // If we've seen an enemy in the last few seconds, and we're allowed to divert, - // let the base AI decide what I should do. - if ( IsAllowedToDivert() ) - { - // Return true, but remember that we're actually allowing them to divert - // This is done because we don't want the assault behaviour to think it's finished with the assault. - m_bDiverting = true; - } - else if ( m_bDiverting ) - { - // If we were diverting, provoke us to make a new schedule selection - SetCondition( COND_PROVOKED ); - - m_bDiverting = false; - } - - // If we're diverting, let the base AI decide everything - if ( m_bDiverting ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_AssaultBehavior::BeginScheduleSelection() -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_AssaultBehavior::EndScheduleSelection() -{ - m_bHitAssaultPoint = false; - - if( m_hRallyPoint != NULL ) - { - if( !m_hRallyPoint->IsExclusive() ) - m_bHitRallyPoint = false; - - if( !hl2_episodic.GetBool() || !m_hRallyPoint->IsExclusive() || !GetOuter()->IsAlive() ) - { - // Here we unlock the rally point if it is NOT EXCLUSIVE - // -OR- the Outer is DEAD. (This gives us a head-start on - // preparing the point to take new NPCs right away. Otherwise - // we have to wait two seconds until the behavior is destroyed.) - // NOTICE that the legacy (non-episodic) support calls UnlockRallyPoint - // unconditionally on EndScheduleSelection() - UnlockRallyPoint(); - } - } - - GetOuter()->ClearForceCrouch(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : scheduleType - -// Output : int -//----------------------------------------------------------------------------- -int CAI_AssaultBehavior::TranslateSchedule( int scheduleType ) -{ - switch( scheduleType ) - { - case SCHED_ESTABLISH_LINE_OF_FIRE_FALLBACK: - // This nasty schedule can allow the NPC to violate their position near - // the assault point. Translate it away to something stationary. (sjb) - return SCHED_COMBAT_FACE; - break; - - case SCHED_RANGE_ATTACK1: - if ( GetOuter()->GetShotRegulator()->IsInRestInterval() ) - { - if ( GetOuter()->HasStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - GetOuter()->VacateStrategySlot(); - return SCHED_COMBAT_FACE; // @TODO (toml 07-02-03): Should do something more tactically sensible - } - break; - - case SCHED_MOVE_TO_WEAPON_RANGE: - case SCHED_CHASE_ENEMY: - if( m_bHitAssaultPoint ) - { - return SCHED_WAIT_AND_CLEAR; - } - else - { - return SCHED_MOVE_TO_ASSAULT_POINT; - } - break; - - case SCHED_HOLD_RALLY_POINT: - if( HasCondition(COND_NO_PRIMARY_AMMO) | HasCondition(COND_LOW_PRIMARY_AMMO) ) - { - return SCHED_RELOAD; - } - break; - - case SCHED_MOVE_TO_ASSAULT_POINT: - { - float flDist = ( m_hAssaultPoint->GetAbsOrigin() - GetAbsOrigin() ).Length(); - if ( flDist <= 12.0f ) - return SCHED_AT_ASSAULT_POINT; - } - break; - } - - return BaseClass::TranslateSchedule( scheduleType ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_AssaultBehavior::OnStartSchedule( int scheduleType ) -{ - if ( scheduleType == SCHED_HIDE_AND_RELOAD ) //!!!HACKHACK - { - // Dirty the assault point flag so that we return to assault point - m_bHitAssaultPoint = false; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_AssaultBehavior::ClearSchedule( const char *szReason ) -{ - // HACKHACK: In reality, we shouldn't be clearing the schedule ever if the assault - // behavior isn't actually in charge of the NPC. Fix after ship. For now, hacking - // a fix to Grigori failing to make it over the fence of the graveyard in d1_town_02a - if ( GetOuter()->ClassMatches( "npc_monk" ) && GetOuter()->GetState() == NPC_STATE_SCRIPT ) - return; - - // Don't allow it if we're in a vehicle - if ( GetOuter()->IsInAVehicle() ) - return; - - GetOuter()->ClearSchedule( szReason ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_AssaultBehavior::IsAllowedToDivert( void ) -{ - if ( m_hAssaultPoint && m_hAssaultPoint->m_bAllowDiversion ) - { - if ( m_hAssaultPoint->m_flAllowDiversionRadius == 0.0f || (m_bHitAssaultPoint && GetEnemy() != NULL && GetEnemy()->GetAbsOrigin().DistToSqr(m_hAssaultPoint->GetAbsOrigin()) <= Square(m_hAssaultPoint->m_flAllowDiversionRadius)) ) - { - if ( m_flLastSawAnEnemyAt && ((gpGlobals->curtime - m_flLastSawAnEnemyAt) < ASSAULT_DIVERSION_TIME) ) - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_AssaultBehavior::BuildScheduleTestBits() -{ - BaseClass::BuildScheduleTestBits(); - - // If we're allowed to divert, add the appropriate interrupts to our movement schedules - if ( IsAllowedToDivert() ) - { - if ( IsCurSchedule( SCHED_MOVE_TO_ASSAULT_POINT ) || - IsCurSchedule( SCHED_MOVE_TO_RALLY_POINT ) || - IsCurSchedule( SCHED_HOLD_RALLY_POINT ) ) - { - GetOuter()->SetCustomInterruptCondition( COND_NEW_ENEMY ); - GetOuter()->SetCustomInterruptCondition( COND_SEE_ENEMY ); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_AssaultBehavior::OnScheduleChange() -{ - if( IsCurSchedule(SCHED_WAIT_AND_CLEAR, false) ) - { - if( m_hAssaultPoint && m_hAssaultPoint->m_bClearOnContact ) - { - if( HasCondition(COND_SEE_ENEMY) ) - { - ClearAssaultPoint(); - } - } - } - - BaseClass::OnScheduleChange(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CAI_AssaultBehavior::SelectSchedule() -{ - if ( !OnStrictAssault() ) - { - if( HasCondition( COND_PLAYER_PUSHING ) ) - return SCHED_ASSAULT_MOVE_AWAY; - - if( HasCondition( COND_HEAR_DANGER ) ) - return SCHED_TAKE_COVER_FROM_BEST_SOUND; - } - - if( HasCondition( COND_CAN_MELEE_ATTACK1 ) ) - return SCHED_MELEE_ATTACK1; - - // If you're empty, reload before trying to carry out any assault functions. - if( HasCondition( COND_NO_PRIMARY_AMMO ) ) - return SCHED_RELOAD; - - if( m_bHitRallyPoint && !m_bHitAssaultPoint && !AssaultHasBegun() ) - { - // If I have hit my rally point, but I haven't hit my assault point yet, - // Make sure I'm still on my rally point, cause another behavior may have moved me. - // 2D check to be within 32 units of my rallypoint. - Vector vecDiff = GetAbsOrigin() - m_hRallyPoint->GetAbsOrigin(); - vecDiff.z = 0.0; - - if( vecDiff.LengthSqr() > Square(CUE_POINT_TOLERANCE) ) - { - // Someone moved me away. Get back to rally point. - m_bHitRallyPoint = false; - return SCHED_MOVE_TO_RALLY_POINT; - } - } - else if( m_bHitAssaultPoint ) - { - // Likewise. If I have hit my assault point, make sure I'm still there. Another - // behavior (hide and reload) may have moved me away. - Vector vecDiff = GetAbsOrigin() - m_hAssaultPoint->GetAbsOrigin(); - vecDiff.z = 0.0; - - if( vecDiff.LengthSqr() > Square(CUE_POINT_TOLERANCE) ) - { - // Someone moved me away. - m_bHitAssaultPoint = false; - } - } - - // Go to my rally point, unless the assault's begun. - if( !m_bHitRallyPoint && !AssaultHasBegun() ) - { - GetOuter()->SpeakSentence( ASSAULT_SENTENCE_SQUAD_ADVANCE_TO_RALLY ); - return SCHED_MOVE_TO_RALLY_POINT; - } - - if( !m_bHitAssaultPoint ) - { - if( m_ReceivedAssaultCue == m_AssaultCue || m_ReceivedAssaultCue == CUE_COMMANDER || m_AssaultCue == CUE_DONT_WAIT ) - { - GetOuter()->SpeakSentence( ASSAULT_SENTENCE_SQUAD_ADVANCE_TO_ASSAULT ); - - if ( m_hRallyPoint && !m_hRallyPoint->IsExclusive() ) - { - // If this assault chain is not exclusive, then free up the rallypoint so that others can follow me - // Otherwise, we do not unlock this rally point until we are FINISHED or DEAD. It's exclusively our chain of assault - UnlockRallyPoint();// Here we go! Free up the rally point since I'm moving to assault. - } - - if ( !UpdateForceCrouch() ) - { - GetOuter()->ClearForceCrouch(); - } - - return SCHED_MOVE_TO_ASSAULT_POINT; - } - else if( HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - { - return SCHED_RANGE_ATTACK1; - } - else if( HasCondition( COND_NO_PRIMARY_AMMO ) ) - { - // Don't run off to reload. - return SCHED_RELOAD; - } - else if( HasCondition( COND_LIGHT_DAMAGE ) || HasCondition( COND_HEAVY_DAMAGE ) ) - { - GetOuter()->SpeakSentence( ASSAULT_SENTENCE_UNDER_ATTACK ); - return SCHED_ALERT_FACE; - } - else if( GetOuter()->GetEnemy() && !HasCondition( COND_CAN_RANGE_ATTACK1 ) && !HasCondition( COND_CAN_RANGE_ATTACK2) && !HasCondition(COND_ENEMY_OCCLUDED) ) - { - return SCHED_COMBAT_FACE; - } - else - { - UpdateForceCrouch(); - return SCHED_HOLD_RALLY_POINT; - } - } - - if( HasCondition( COND_NO_PRIMARY_AMMO ) ) - { - GetOuter()->SpeakSentence( ASSAULT_SENTENCE_COVER_NO_AMMO ); - return SCHED_HIDE_AND_RELOAD; - } - - if( m_hAssaultPoint->HasSpawnFlags( SF_ASSAULTPOINT_CLEARONARRIVAL ) ) - { - return SCHED_CLEAR_ASSAULT_POINT; - } - - if ( (!GetEnemy() || HasCondition(COND_ENEMY_OCCLUDED)) && !GetOuter()->HasConditionsToInterruptSchedule( SCHED_WAIT_AND_CLEAR ) ) - { - // Don't have an enemy. Just keep an eye on things. - return SCHED_WAIT_AND_CLEAR; - } - - if ( OnStrictAssault() ) - { - // Don't allow the base class to select a schedule cause it will probably move the NPC. - if( !HasCondition(COND_CAN_RANGE_ATTACK1) && - !HasCondition(COND_CAN_RANGE_ATTACK2) && - !HasCondition(COND_CAN_MELEE_ATTACK1) && - !HasCondition(COND_CAN_MELEE_ATTACK2) && - !HasCondition(COND_TOO_CLOSE_TO_ATTACK) && - !HasCondition(COND_NOT_FACING_ATTACK) ) - { - return SCHED_WAIT_AND_CLEAR; - } - } - -#ifdef HL2_EPISODIC - // This ugly patch fixes a bug where Combine Soldiers on an assault would not shoot through glass, because of the way - // that shooting through glass is implemented in their AI. (sjb) - if( HasCondition(COND_SEE_ENEMY) && HasCondition(COND_WEAPON_SIGHT_OCCLUDED) && !HasCondition(COND_LOW_PRIMARY_AMMO) ) - { - // If they are hiding behind something that we can destroy, start shooting at it. - CBaseEntity *pBlocker = GetOuter()->GetEnemyOccluder(); - if ( pBlocker && pBlocker->GetHealth() > 0 ) - { - if( GetOuter()->Classify() == CLASS_COMBINE && FClassnameIs(GetOuter(), "npc_combine_s") ) - { - return SCHED_SHOOT_ENEMY_COVER; - } - } - } -#endif//HL2_EPISODIC - - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -// -// CAI_AssaultGoal -// -// Purpose: -// -// -//----------------------------------------------------------------------------- -class CAI_AssaultGoal : public CAI_GoalEntity -{ - typedef CAI_GoalEntity BaseClass; - - virtual void EnableGoal( CAI_BaseNPC *pAI ); - virtual void DisableGoal( CAI_BaseNPC *pAI ); - - string_t m_RallyPoint; - int m_AssaultCue; - int m_RallySelectMethod; - - void InputBeginAssault( inputdata_t &inputdata ); - - DECLARE_DATADESC(); -}; - -BEGIN_DATADESC( CAI_AssaultGoal ) - DEFINE_KEYFIELD( m_RallyPoint, FIELD_STRING, "rallypoint" ), - DEFINE_KEYFIELD( m_AssaultCue, FIELD_INTEGER, "AssaultCue" ), - DEFINE_KEYFIELD( m_RallySelectMethod, FIELD_INTEGER, "RallySelectMethod" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "BeginAssault", InputBeginAssault ), -END_DATADESC(); - - -//------------------------------------- -LINK_ENTITY_TO_CLASS( ai_goal_assault, CAI_AssaultGoal ); -//------------------------------------- - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_AssaultGoal::EnableGoal( CAI_BaseNPC *pAI ) -{ - CAI_AssaultBehavior *pBehavior; - - if ( !pAI->GetBehavior( &pBehavior ) ) - return; - - pBehavior->SetParameters( m_RallyPoint, (AssaultCue_t)m_AssaultCue, m_RallySelectMethod ); - - // Duplicate the output -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_AssaultGoal::DisableGoal( CAI_BaseNPC *pAI ) -{ - CAI_AssaultBehavior *pBehavior; - - if ( pAI->GetBehavior( &pBehavior ) ) - { - pBehavior->Disable(); - - // Don't leave any hanging rally points locked. - pBehavior->UnlockRallyPoint(); - - pBehavior->ClearSchedule( "Assault goal disabled" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: ENTITY I/O method for telling the assault behavior to cue assault -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAI_AssaultGoal::InputBeginAssault( inputdata_t &inputdata ) -{ - int i; - - for( i = 0 ; i < NumActors() ; i++ ) - { - CAI_BaseNPC *pActor = GetActor( i ); - - if( pActor ) - { - // Now use this actor to lookup the Behavior - CAI_AssaultBehavior *pBehavior; - - if( pActor->GetBehavior( &pBehavior ) ) - { - // GOT IT! Now tell the behavior that entity i/o wants to cue the assault. - pBehavior->ReceiveAssaultCue( CUE_ENTITY_INPUT ); - } - } - } -} - - -AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER(CAI_AssaultBehavior) - - DECLARE_TASK(TASK_GET_PATH_TO_RALLY_POINT) - DECLARE_TASK(TASK_FACE_RALLY_POINT) - DECLARE_TASK(TASK_GET_PATH_TO_ASSAULT_POINT) - DECLARE_TASK(TASK_FACE_ASSAULT_POINT) - DECLARE_TASK(TASK_AWAIT_CUE) - DECLARE_TASK(TASK_AWAIT_ASSAULT_TIMEOUT) - DECLARE_TASK(TASK_ANNOUNCE_CLEAR) - DECLARE_TASK(TASK_WAIT_ASSAULT_DELAY) - DECLARE_TASK(TASK_HIT_ASSAULT_POINT) - DECLARE_TASK(TASK_HIT_RALLY_POINT) - DECLARE_TASK(TASK_ASSAULT_DEFER_SCHEDULE_SELECTION) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_MOVE_TO_RALLY_POINT, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ASSAULT_FAILED_TO_MOVE" - " TASK_GET_PATH_TO_RALLY_POINT 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_FACE_RALLY_POINT 0" - " TASK_HIT_RALLY_POINT 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_HOLD_RALLY_POINT" - " " - " Interrupts" - " COND_HEAR_DANGER" - " COND_PROVOKED" - " COND_NO_PRIMARY_AMMO" - " COND_PLAYER_PUSHING" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_ASSAULT_FAILED_TO_MOVE, - - " Tasks" - " TASK_ASSAULT_DEFER_SCHEDULE_SELECTION 1" - " " - " Interrupts" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_FAIL_MOVE_TO_RALLY_POINT, - - " Tasks" - " TASK_WAIT 1" - " " - " Interrupts" - " COND_HEAR_DANGER" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_MELEE_ATTACK1" - ) - - -#ifdef HL2_EPISODIC - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HOLD_RALLY_POINT, - - " Tasks" - " TASK_FACE_RALLY_POINT 0" - " TASK_AWAIT_CUE 0" - " TASK_WAIT_ASSAULT_DELAY 0" - " " - " Interrupts" - //" COND_NEW_ENEMY" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_MELEE_ATTACK1" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_PLAYER_PUSHING" - " COND_HEAR_DANGER" - " COND_HEAR_BULLET_IMPACT" - " COND_NO_PRIMARY_AMMO" - ) -#else - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HOLD_RALLY_POINT, - - " Tasks" - " TASK_FACE_RALLY_POINT 0" - " TASK_AWAIT_CUE 0" - " TASK_WAIT_ASSAULT_DELAY 0" - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_MELEE_ATTACK1" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_PLAYER_PUSHING" - " COND_HEAR_DANGER" - " COND_HEAR_BULLET_IMPACT" - " COND_NO_PRIMARY_AMMO" - " COND_TOO_CLOSE_TO_ATTACK" - ) -#endif//HL2_EPISODIC - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HOLD_ASSAULT_POINT, - - " Tasks" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT 3" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK2" - " COND_TOO_CLOSE_TO_ATTACK" - " COND_LOST_ENEMY" - " COND_HEAR_DANGER" - " COND_HEAR_BULLET_IMPACT" - " COND_NO_PRIMARY_AMMO" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_MOVE_TO_ASSAULT_POINT, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ASSAULT_FAILED_TO_MOVE" - " TASK_GATHER_CONDITIONS 0" - " TASK_GET_PATH_TO_ASSAULT_POINT 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_FACE_ASSAULT_POINT 0" - " TASK_HIT_ASSAULT_POINT 0" - " " - " Interrupts" - " COND_NO_PRIMARY_AMMO" - " COND_HEAR_DANGER" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_AT_ASSAULT_POINT, - - " Tasks" - " TASK_FACE_ASSAULT_POINT 0" - " TASK_HIT_ASSAULT_POINT 0" - " " - " Interrupts" - " COND_NO_PRIMARY_AMMO" - " COND_HEAR_DANGER" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_WAIT_AND_CLEAR, - - " Tasks" - " TASK_FACE_ASSAULT_POINT 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_AWAIT_ASSAULT_TIMEOUT 0" - " TASK_ANNOUNCE_CLEAR 0" - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK2" - " COND_HEAR_DANGER" - " COND_HEAR_BULLET_IMPACT" - " COND_TOO_CLOSE_TO_ATTACK" - " COND_NOT_FACING_ATTACK" - " COND_PLAYER_PUSHING" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CLEAR_ASSAULT_POINT, - - " Tasks" - " TASK_ANNOUNCE_CLEAR 0" - " " - " Interrupts" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_ASSAULT_MOVE_AWAY, - - " Tasks" - " TASK_MOVE_AWAY_PATH 120" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " " - " Interrupts" - ) - -AI_END_CUSTOM_SCHEDULE_PROVIDER() diff --git a/game/server/ai_behavior_assault.h b/game/server/ai_behavior_assault.h deleted file mode 100644 index 91375bdb5..000000000 --- a/game/server/ai_behavior_assault.h +++ /dev/null @@ -1,299 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef AI_BEHAVIOR_ASSAULT_H -#define AI_BEHAVIOR_ASSAULT_H -#ifdef _WIN32 -#pragma once -#endif - -#include "simtimer.h" -#include "ai_behavior.h" -#include "ai_goalentity.h" -#include "ai_moveshoot.h" -#include "ai_utils.h" - -#define CUE_POINT_TOLERANCE (3.0*12.0) - -enum RallySelectMethod_t -{ - RALLY_POINT_SELECT_DEFAULT = 0, - RALLY_POINT_SELECT_RANDOM, -}; - -enum AssaultCue_t -{ - CUE_NO_ASSAULT = 0, // used to indicate that no assault is being conducted presently - - CUE_ENTITY_INPUT = 1, - CUE_PLAYER_GUNFIRE, - CUE_DONT_WAIT, - CUE_COMMANDER, - CUE_NONE, -}; - -enum -{ - ASSAULT_SENTENCE_HIT_RALLY_POINT = SENTENCE_BASE_BEHAVIOR_INDEX, - ASSAULT_SENTENCE_HIT_ASSAULT_POINT, - ASSAULT_SENTENCE_SQUAD_ADVANCE_TO_RALLY, - ASSAULT_SENTENCE_SQUAD_ADVANCE_TO_ASSAULT, - ASSAULT_SENTENCE_COVER_NO_AMMO, - ASSAULT_SENTENCE_UNDER_ATTACK, -}; - -// Allow diversion from the assault up to this amount of time after last having an enemy -#define ASSAULT_DIVERSION_TIME 4 - -#define SF_ASSAULTPOINT_CLEARONARRIVAL 0x00000001 - -//============================================================================= -//============================================================================= -class CRallyPoint : public CPointEntity -{ - DECLARE_CLASS( CRallyPoint, CPointEntity ); - -public: - CRallyPoint() - { - m_hLockedBy.Set(NULL); - m_sExclusivity = RALLY_EXCLUSIVE_NOT_EVALUATED; - } - - bool Lock( CBaseEntity *pLocker ) - { - if( IsLocked() ) - { - // Already locked. - return false; - } - - m_hLockedBy.Set( pLocker ); - return true; - } - - bool Unlock( CBaseEntity *pUnlocker ) - { - if( IsLocked() ) - { - if( m_hLockedBy.Get() != pUnlocker ) - { - // Refuse! Only the locker may unlock. - return false; - } - } - - m_hLockedBy.Set( NULL ); - return true; - } - - bool IsLocked( void ) { return (m_hLockedBy.Get() != NULL); } - - int DrawDebugTextOverlays(); - bool IsExclusive(); - - enum - { - RALLY_EXCLUSIVE_NOT_EVALUATED = -1, - RALLY_EXCLUSIVE_NO, - RALLY_EXCLUSIVE_YES, - }; - - string_t m_AssaultPointName; - string_t m_RallySequenceName; - float m_flAssaultDelay; - int m_iPriority; - int m_iStrictness; - bool m_bForceCrouch; - bool m_bIsUrgent; - short m_sExclusivity; - - COutputEvent m_OnArrival; - - DECLARE_DATADESC(); - -private: - EHANDLE m_hLockedBy; -}; - -//============================================================================= -//============================================================================= -class CAssaultPoint : public CPointEntity -{ - DECLARE_CLASS( CAssaultPoint, CPointEntity ); - -public: - CAssaultPoint() - { - // This used to be a constant in code. Now it's a keyfield in hammer. - // So in the constructor, we set this value to the former constant - // default value, for legacy maps. (sjb) - m_flAssaultPointTolerance = CUE_POINT_TOLERANCE; - } - - void InputSetClearOnContact( inputdata_t &inputdata ) - { - m_bClearOnContact = inputdata.value.Bool(); - } - - void InputSetAllowDiversion( inputdata_t &inputdata ) - { - m_bAllowDiversion = inputdata.value.Bool(); - } - - void InputSetForceClear( inputdata_t &inputdata ) - { - m_bInputForcedClear = inputdata.value.Bool(); - } - -public: - string_t m_AssaultHintGroup; - string_t m_NextAssaultPointName; - COutputEvent m_OnAssaultClear; - float m_flAssaultTimeout; - bool m_bClearOnContact; - bool m_bAllowDiversion; - float m_flAllowDiversionRadius; - bool m_bNeverTimeout; - int m_iStrictness; - bool m_bForceCrouch; - bool m_bIsUrgent; - bool m_bInputForcedClear; - float m_flAssaultPointTolerance; - float m_flTimeLastUsed; - - COutputEvent m_OnArrival; - - DECLARE_DATADESC(); -}; - -//============================================================================= -//============================================================================= -class CAI_AssaultBehavior : public CAI_SimpleBehavior -{ - DECLARE_CLASS( CAI_AssaultBehavior, CAI_SimpleBehavior ); - -public: - CAI_AssaultBehavior(); - - virtual const char *GetName() { return "Assault"; } - virtual int DrawDebugTextOverlays( int text_offset ); - - virtual void OnRestore(); - - bool CanRunAScriptedNPCInteraction( bool bForced ); - - virtual bool CanSelectSchedule(); - virtual void BeginScheduleSelection(); - virtual void EndScheduleSelection(); - - bool HasHitRallyPoint() { return m_bHitRallyPoint; } - bool HasHitAssaultPoint() { return m_bHitAssaultPoint; } - - void ClearAssaultPoint( void ); - void OnHitAssaultPoint( void ); - bool PollAssaultCue( void ); - void ReceiveAssaultCue( AssaultCue_t cue ); - bool HasAssaultCue( void ) { return m_AssaultCue != CUE_NO_ASSAULT; } - bool AssaultHasBegun(); - - CAssaultPoint *FindAssaultPoint( string_t iszAssaultPointName ); - void SetAssaultPoint( CAssaultPoint *pAssaultPoint ); - - void GatherConditions( void ); - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - void BuildScheduleTestBits(); - int TranslateSchedule( int scheduleType ); - void OnStartSchedule( int scheduleType ); - void ClearSchedule( const char *szReason ); - - void InitializeBehavior(); - void SetParameters( string_t rallypointname, AssaultCue_t assaultcue, int rallySelectMethod ); - void SetParameters( CBaseEntity *pRallyEnt, AssaultCue_t assaultcue ); - - bool IsAllowedToDivert( void ); - bool IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint ); - float GetMaxTacticalLateralMovement( void ); - - void UpdateOnRemove(); - - bool OnStrictAssault( void ); - bool UpdateForceCrouch( void ); - bool IsForcingCrouch( void ); - bool IsUrgent( void ); - - CRallyPoint *FindBestRallyPointInRadius( const Vector &vecCenter, float flRadius );; - - void Disable( void ) { m_AssaultCue = CUE_NO_ASSAULT; m_bHitRallyPoint = false; m_bHitAssaultPoint = false; } - - enum - { - SCHED_MOVE_TO_RALLY_POINT = BaseClass::NEXT_SCHEDULE, // Try to get out of the player's way - SCHED_ASSAULT_FAILED_TO_MOVE, - SCHED_FAIL_MOVE_TO_RALLY_POINT, - SCHED_MOVE_TO_ASSAULT_POINT, - SCHED_AT_ASSAULT_POINT, - SCHED_HOLD_RALLY_POINT, - SCHED_HOLD_ASSAULT_POINT, - SCHED_WAIT_AND_CLEAR, - SCHED_ASSAULT_MOVE_AWAY, - SCHED_CLEAR_ASSAULT_POINT, - NEXT_SCHEDULE, - - TASK_GET_PATH_TO_RALLY_POINT = BaseClass::NEXT_TASK, - TASK_FACE_RALLY_POINT, - TASK_GET_PATH_TO_ASSAULT_POINT, - TASK_FACE_ASSAULT_POINT, - TASK_HIT_ASSAULT_POINT, - TASK_HIT_RALLY_POINT, - TASK_AWAIT_CUE, - TASK_AWAIT_ASSAULT_TIMEOUT, - TASK_ANNOUNCE_CLEAR, - TASK_WAIT_ASSAULT_DELAY, - TASK_ASSAULT_MOVE_AWAY_PATH, - TASK_ASSAULT_DEFER_SCHEDULE_SELECTION, - NEXT_TASK, - -/* - COND_PUT_CONDITIONS_HERE = BaseClass::NEXT_CONDITION, - NEXT_CONDITION, -*/ - }; - - DEFINE_CUSTOM_SCHEDULE_PROVIDER; - -public: - CHandle m_hAssaultPoint; - CHandle m_hRallyPoint; - -public: - void UnlockRallyPoint( void ); - -private: - void OnScheduleChange(); - virtual int SelectSchedule(); - - AssaultCue_t m_AssaultCue; // the cue we're waiting for to begin the assault - AssaultCue_t m_ReceivedAssaultCue; // the last assault cue we received from someone/thing external. - - bool m_bHitRallyPoint; - bool m_bHitAssaultPoint; - - // Diversion - bool m_bDiverting; - float m_flLastSawAnEnemyAt; - - float m_flTimeDeferScheduleSelection; - - string_t m_AssaultPointName; - - //--------------------------------- - - DECLARE_DATADESC(); -}; - -#endif // AI_BEHAVIOR_ASSAULT_H diff --git a/game/server/ai_behavior_fear.cpp b/game/server/ai_behavior_fear.cpp deleted file mode 100644 index f4d0c8df6..000000000 --- a/game/server/ai_behavior_fear.cpp +++ /dev/null @@ -1,552 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "ai_motor.h" -#include "ai_behavior_fear.h" -#include "ai_hint.h" -#include "ai_navigator.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -BEGIN_DATADESC( CAI_FearBehavior ) - DEFINE_FIELD( m_flTimeToSafety, FIELD_TIME ), - DEFINE_FIELD( m_flTimePlayerLastVisible, FIELD_TIME ), - DEFINE_FIELD( m_hSafePlaceHint, FIELD_EHANDLE ), - DEFINE_FIELD( m_hMovingToHint, FIELD_EHANDLE ), - DEFINE_EMBEDDED( m_SafePlaceMoveMonitor ), - DEFINE_FIELD( m_flDeferUntil, FIELD_TIME ), -END_DATADESC(); - -#define BEHAVIOR_FEAR_SAFETY_TIME 5 -#define FEAR_SAFE_PLACE_TOLERANCE 36.0f -#define FEAR_ENEMY_TOLERANCE_CLOSE_DIST_SQR Square(300.0f) // (25 feet) -#define FEAR_ENEMY_TOLERANCE_TOO_CLOSE_DIST_SQR Square( 60.0f ) // (5 Feet) - -ConVar ai_enable_fear_behavior( "ai_enable_fear_behavior", "1" ); - -ConVar ai_fear_player_dist("ai_fear_player_dist", "720" ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CAI_FearBehavior::CAI_FearBehavior() -{ - ReleaseAllHints(); - m_SafePlaceMoveMonitor.ClearMark(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_FearBehavior::Precache( void ) -{ - -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTask - -//----------------------------------------------------------------------------- -void CAI_FearBehavior::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_FEAR_IN_SAFE_PLACE: - // We've arrived! Lock the hint and set the marker. we're safe for now. - m_hSafePlaceHint = m_hMovingToHint; - m_hSafePlaceHint->Lock( GetOuter() ); - m_SafePlaceMoveMonitor.SetMark( GetOuter(), FEAR_SAFE_PLACE_TOLERANCE ); - TaskComplete(); - break; - - case TASK_FEAR_GET_PATH_TO_SAFETY_HINT: - // Using TaskInterrupt() optimizations. See RunTask(). - break; - - case TASK_FEAR_WAIT_FOR_SAFETY: - m_flTimeToSafety = gpGlobals->curtime + BEHAVIOR_FEAR_SAFETY_TIME; - break; - - default: - BaseClass::StartTask( pTask ); - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTask - -//----------------------------------------------------------------------------- -void CAI_FearBehavior::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_FEAR_WAIT_FOR_SAFETY: - if( HasCondition(COND_SEE_ENEMY) ) - { - m_flTimeToSafety = gpGlobals->curtime + BEHAVIOR_FEAR_SAFETY_TIME; - } - else - { - if( gpGlobals->curtime > m_flTimeToSafety ) - { - TaskComplete(); - } - } - break; - - case TASK_FEAR_GET_PATH_TO_SAFETY_HINT: - { - switch( GetOuter()->GetTaskInterrupt() ) - { - case 0:// Find the hint node - { - ReleaseAllHints(); - CAI_Hint *pHint = FindFearWithdrawalDest(); - - if( pHint == NULL ) - { - TaskFail("Fear: Couldn't find hint node\n"); - m_flDeferUntil = gpGlobals->curtime + 3.0f;// Don't bang the hell out of this behavior. If we don't find a node, take a short break and run regular AI. - } - else - { - m_hMovingToHint.Set( pHint ); - GetOuter()->TaskInterrupt(); - } - } - break; - - case 1:// Do the pathfinding. - { - Assert( m_hMovingToHint != NULL ); - - AI_NavGoal_t goal(m_hMovingToHint->GetAbsOrigin()); - goal.pTarget = NULL; - if( GetNavigator()->SetGoal( goal ) == false ) - { - m_hMovingToHint.Set( NULL ); - // Do whatever we'd want to do if we can't find a path - /* - Msg("Can't path to the Fear Hint!\n"); - - AI_NavGoal_t nearGoal( GOALTYPE_LOCATION_NEAREST_NODE, m_hRallyPoint->GetAbsOrigin(), AIN_DEF_ACTIVITY, 256 ); - if ( GetNavigator()->SetGoal( nearGoal, AIN_CLEAR_PREVIOUS_STATE ) ) - { - //FIXME: HACK! The internal pathfinding is setting this without our consent, so override it! - ClearCondition( COND_TASK_FAILED ); - GetNavigator()->SetArrivalDirection( m_hRallyPoint->GetAbsAngles() ); - TaskComplete(); - return; - } - */ - } - else - { - GetNavigator()->SetArrivalDirection( m_hMovingToHint->GetAbsAngles() ); - } - } - break; - } - } - break; - - default: - BaseClass::RunTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : TRUE if I have an enemy and that enemy would attack me if it could -// Notes : Returns FALSE if the enemy is neutral or likes me. -//----------------------------------------------------------------------------- -bool CAI_FearBehavior::EnemyDislikesMe() -{ - CBaseEntity *pEnemy = GetEnemy(); - - if( pEnemy == NULL ) - return false; - - if( pEnemy->MyNPCPointer() == NULL ) - return false; - - Disposition_t disposition = pEnemy->MyNPCPointer()->IRelationType(GetOuter()); - - Assert(disposition != D_ER); - - if( disposition >= D_LI ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// This place is definitely no longer safe. Stop picking it for a while. -//----------------------------------------------------------------------------- -void CAI_FearBehavior::MarkAsUnsafe() -{ - Assert( m_hSafePlaceHint ); - - // Disable the node to stop anyone from picking it for a while. - m_hSafePlaceHint->DisableForSeconds( 5.0f ); -} - -//----------------------------------------------------------------------------- -// Am I in safe place from my enemy? -//----------------------------------------------------------------------------- -bool CAI_FearBehavior::IsInASafePlace() -{ - // No safe place in mind. - if( !m_SafePlaceMoveMonitor.IsMarkSet() ) - return false; - - // I have a safe place, but I'm not there. - if( m_SafePlaceMoveMonitor.TargetMoved(GetOuter()) ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_FearBehavior::SpoilSafePlace() -{ - m_SafePlaceMoveMonitor.ClearMark(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_FearBehavior::ReleaseAllHints() -{ - if( m_hSafePlaceHint ) - { - // If I have a safe place, unlock it for others. - m_hSafePlaceHint->Unlock(); - - // Don't make it available right away. I probably left for a good reason. - // We also don't want to oscillate - m_hSafePlaceHint->DisableForSeconds( 4.0f ); - m_hSafePlaceHint = NULL; - } - - if( m_hMovingToHint ) - { - m_hMovingToHint->Unlock(); - m_hMovingToHint = NULL; - } - - m_SafePlaceMoveMonitor.ClearMark(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -// Notes : This behavior runs when I have an enemy that I fear, but who -// does NOT hate or fear me (meaning they aren't going to fight me) -//----------------------------------------------------------------------------- -bool CAI_FearBehavior::CanSelectSchedule() -{ - if( !GetOuter()->IsInterruptable() ) - return false; - - if( m_flDeferUntil > gpGlobals->curtime ) - return false; - - CBaseEntity *pEnemy = GetEnemy(); - - if( pEnemy == NULL ) - return false; - - //if( !HasCondition(COND_SEE_PLAYER) ) - // return false; - - if( !ai_enable_fear_behavior.GetBool() ) - return false; - - if( GetOuter()->IRelationType(pEnemy) != D_FR ) - return false; - - if( !pEnemy->ClassMatches("npc_hunter") ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_FearBehavior::GatherConditions() -{ - BaseClass::GatherConditions(); - - ClearCondition( COND_FEAR_ENEMY_CLOSE ); - ClearCondition( COND_FEAR_ENEMY_TOO_CLOSE ); - if( GetEnemy() ) - { - float flEnemyDistSqr = GetAbsOrigin().DistToSqr(GetEnemy()->GetAbsOrigin()); - - if( flEnemyDistSqr < FEAR_ENEMY_TOLERANCE_TOO_CLOSE_DIST_SQR ) - { - SetCondition( COND_FEAR_ENEMY_TOO_CLOSE ); - if( IsInASafePlace() ) - { - SpoilSafePlace(); - } - } - else if( flEnemyDistSqr < FEAR_ENEMY_TOLERANCE_CLOSE_DIST_SQR && GetEnemy()->GetEnemy() == GetOuter() ) - { - // Only become scared of an enemy at this range if they're my enemy, too - SetCondition( COND_FEAR_ENEMY_CLOSE ); - if( IsInASafePlace() ) - { - SpoilSafePlace(); - } - } - } - - ClearCondition(COND_FEAR_SEPARATED_FROM_PLAYER); - - // Check for separation from the player - // -The player is farther away than 60 feet - // -I haven't seen the player in 2 seconds - // - // Here's the distance check: - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if( pPlayer != NULL && GetAbsOrigin().DistToSqr(pPlayer->GetAbsOrigin()) >= Square( ai_fear_player_dist.GetFloat() * 1.5f ) ) - { - SetCondition(COND_FEAR_SEPARATED_FROM_PLAYER); - } - - // Here's the visibility check. We can't skip this because it's time-sensitive - if( GetOuter()->FVisible(pPlayer) ) - { - m_flTimePlayerLastVisible = gpGlobals->curtime; - } - else - { - if( gpGlobals->curtime - m_flTimePlayerLastVisible >= 2.0f ) - { - SetCondition(COND_FEAR_SEPARATED_FROM_PLAYER); - } - } - - if( HasCondition(COND_FEAR_SEPARATED_FROM_PLAYER) ) - { - //Msg("I am separated from player\n"); - - if( IsInASafePlace() ) - { - SpoilSafePlace(); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_FearBehavior::BeginScheduleSelection() -{ - if( m_hSafePlaceHint ) - { - // We think we're safe. Is it true? - if( !IsInASafePlace() ) - { - // no! So mark it so. - ReleaseAllHints(); - } - } - - m_flTimePlayerLastVisible = gpGlobals->curtime; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_FearBehavior::EndScheduleSelection() -{ - // We don't have to release our hints or markers or anything here. - // Just because we ran other AI for a while doesn't mean we aren't still in a safe place. - //ReleaseAllHints(); -} - - - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -// Notes : If fear behavior is running at all, we know we're afraid of our enemy -//----------------------------------------------------------------------------- -int CAI_FearBehavior::SelectSchedule() -{ - bool bInSafePlace = IsInASafePlace(); - - if( !HasCondition(COND_HEAR_DANGER) ) - { - if( !bInSafePlace ) - { - // Always move to a safe place if we're not running from a danger sound - return SCHED_FEAR_MOVE_TO_SAFE_PLACE; - } - else - { - // We ARE in a safe place - if( HasCondition(COND_CAN_RANGE_ATTACK1) ) - return SCHED_RANGE_ATTACK1; - - return SCHED_FEAR_STAY_IN_SAFE_PLACE; - } - } - - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_FearBehavior::BuildScheduleTestBits() -{ - BaseClass::BuildScheduleTestBits(); - - if( GetOuter()->GetState() != NPC_STATE_SCRIPT ) - { - // Stop doing ANYTHING if we get scared. - //GetOuter()->SetCustomInterruptCondition( COND_HEAR_DANGER ); - - if( !IsCurSchedule(SCHED_FEAR_MOVE_TO_SAFE_PLACE_RETRY, false) && !IsCurSchedule(SCHED_FEAR_MOVE_TO_SAFE_PLACE, false) ) - { - GetOuter()->SetCustomInterruptCondition( GetClassScheduleIdSpace()->ConditionLocalToGlobal(COND_FEAR_SEPARATED_FROM_PLAYER) ); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CAI_FearBehavior::TranslateSchedule( int scheduleType ) -{ - switch( scheduleType ) - { - case SCHED_FEAR_MOVE_TO_SAFE_PLACE: - if( HasCondition(COND_FEAR_ENEMY_TOO_CLOSE) ) - { - // If I'm moving to a safe place AND have an enemy too close to me, - // make the move to safety while ignoring the condition. - // this stops an oscillation - // IS THIS CODE EVER EVEN BEING CALLED? (sjb) - return SCHED_FEAR_MOVE_TO_SAFE_PLACE_RETRY; - } - break; - } - - return BaseClass::TranslateSchedule( scheduleType ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CAI_Hint *CAI_FearBehavior::FindFearWithdrawalDest() -{ - CAI_Hint *pHint; - CHintCriteria hintCriteria; - CAI_BaseNPC *pOuter = GetOuter(); - - Assert(pOuter != NULL); - - hintCriteria.AddHintType( HINT_PLAYER_ALLY_FEAR_DEST ); - hintCriteria.SetFlag( bits_HINT_NODE_VISIBLE_TO_PLAYER | bits_HINT_NOT_CLOSE_TO_ENEMY /*| bits_HINT_NODE_IN_VIEWCONE | bits_HINT_NPC_IN_NODE_FOV*/ ); - hintCriteria.AddIncludePosition( AI_GetSinglePlayer()->GetAbsOrigin(), ( ai_fear_player_dist.GetFloat() ) ); - - pHint = CAI_HintManager::FindHint( pOuter, hintCriteria ); - - if( pHint ) - { - // Reserve this node while I try to get to it. When I get there I will lock it. - // Otherwise, if I fail to get there, the node will come available again soon. - pHint->DisableForSeconds( 4.0f ); - } -#if 0 - else - { - Msg("DID NOT FIND HINT\n"); - NDebugOverlay::Cross3D( GetOuter()->WorldSpaceCenter(), 32, 255, 255, 0, false, 10.0f ); - } -#endif - - return pHint; -} - -AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( CAI_FearBehavior ) - - DECLARE_TASK( TASK_FEAR_GET_PATH_TO_SAFETY_HINT ) - DECLARE_TASK( TASK_FEAR_WAIT_FOR_SAFETY ) - DECLARE_TASK( TASK_FEAR_IN_SAFE_PLACE ) - - DECLARE_CONDITION( COND_FEAR_ENEMY_CLOSE ) - DECLARE_CONDITION( COND_FEAR_ENEMY_TOO_CLOSE ) - DECLARE_CONDITION( COND_FEAR_SEPARATED_FROM_PLAYER ) - - //=============================================== - //=============================================== - DEFINE_SCHEDULE - ( - SCHED_FEAR_MOVE_TO_SAFE_PLACE, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_RUN_FROM_ENEMY" - " TASK_FEAR_GET_PATH_TO_SAFETY_HINT 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_FEAR_IN_SAFE_PLACE 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_FEAR_STAY_IN_SAFE_PLACE" - "" - " Interrupts" - "" - " COND_HEAR_DANGER" - " COND_NEW_ENEMY" - " COND_FEAR_ENEMY_TOO_CLOSE" - ); - - DEFINE_SCHEDULE - ( - SCHED_FEAR_MOVE_TO_SAFE_PLACE_RETRY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_RUN_FROM_ENEMY" - " TASK_FEAR_GET_PATH_TO_SAFETY_HINT 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_FEAR_IN_SAFE_PLACE 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_FEAR_STAY_IN_SAFE_PLACE" - "" - " Interrupts" - "" - " COND_HEAR_DANGER" - " COND_NEW_ENEMY" - ); - - //=============================================== - //=============================================== - DEFINE_SCHEDULE - ( - SCHED_FEAR_STAY_IN_SAFE_PLACE, - - " Tasks" - " TASK_FEAR_WAIT_FOR_SAFETY 0" - "" - " Interrupts" - "" - " COND_NEW_ENEMY" - " COND_HEAR_DANGER" - " COND_FEAR_ENEMY_CLOSE" - " COND_FEAR_ENEMY_TOO_CLOSE" - " COND_CAN_RANGE_ATTACK1" - " COND_FEAR_SEPARATED_FROM_PLAYER" - ); - - -AI_END_CUSTOM_SCHEDULE_PROVIDER() diff --git a/game/server/ai_behavior_fear.h b/game/server/ai_behavior_fear.h deleted file mode 100644 index f0548afc5..000000000 --- a/game/server/ai_behavior_fear.h +++ /dev/null @@ -1,98 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Deal intelligently with an enemy that we're afraid of -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - - -#ifndef AI_BEHAVIOR_FEAR_H -#define AI_BEHAVIOR_FEAR_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_behavior.h" - -class CAI_FearBehavior : public CAI_SimpleBehavior -{ - DECLARE_CLASS( CAI_FearBehavior, CAI_SimpleBehavior ); - -public: - CAI_FearBehavior(); - - void Precache( void ); - virtual const char *GetName() { return "Fear"; } - - virtual bool CanSelectSchedule(); - void GatherConditions(); - - virtual void BeginScheduleSelection(); - virtual void EndScheduleSelection(); - - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - - //void BuildScheduleTestBits(); - //int TranslateSchedule( int scheduleType ); - //void OnStartSchedule( int scheduleType ); - - //void InitializeBehavior(); - - bool EnemyDislikesMe(); - - void MarkAsUnsafe(); - bool IsInASafePlace(); - void SpoilSafePlace(); - void ReleaseAllHints(); - - CAI_Hint *FindFearWithdrawalDest(); - void BuildScheduleTestBits(); - int TranslateSchedule( int scheduleType ); - - - enum - { - SCHED_FEAR_MOVE_TO_SAFE_PLACE = BaseClass::NEXT_SCHEDULE, - SCHED_FEAR_MOVE_TO_SAFE_PLACE_RETRY, - SCHED_FEAR_STAY_IN_SAFE_PLACE, - NEXT_SCHEDULE, - - TASK_FEAR_GET_PATH_TO_SAFETY_HINT = BaseClass::NEXT_TASK, - TASK_FEAR_WAIT_FOR_SAFETY, - TASK_FEAR_IN_SAFE_PLACE, - NEXT_TASK, - - COND_FEAR_ENEMY_CLOSE = BaseClass::NEXT_CONDITION, // within 30 feet - COND_FEAR_ENEMY_TOO_CLOSE, // within 5 feet - COND_FEAR_SEPARATED_FROM_PLAYER, - NEXT_CONDITION, - }; - - DEFINE_CUSTOM_SCHEDULE_PROVIDER; - -public: - -private: - virtual int SelectSchedule(); - - float m_flTimeToSafety; - float m_flTimePlayerLastVisible; - float m_flDeferUntil; - - CAI_MoveMonitor m_SafePlaceMoveMonitor; - CHandle m_hSafePlaceHint; - CHandle m_hMovingToHint; - - DECLARE_DATADESC(); -}; - -#endif // AI_BEHAVIOR_FEAR_H - - diff --git a/game/server/ai_behavior_follow.cpp b/game/server/ai_behavior_follow.cpp deleted file mode 100644 index c3ad7a4f4..000000000 --- a/game/server/ai_behavior_follow.cpp +++ /dev/null @@ -1,3123 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "tier1/utllinkedlist.h" -#include "bitstring.h" -#include "utlvector.h" -#include "ai_navigator.h" -#include "scripted.h" -#include "ai_hint.h" -#include "ai_behavior_follow.h" -#include "ai_memory.h" -#include "ai_squad.h" -#include "ai_tacticalservices.h" -#include "ndebugoverlay.h" -#include "ai_senses.h" - -#ifdef HL2_EPISODIC - #include "info_darknessmode_lightsource.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar ai_debug_follow( "ai_debug_follow", "0" ); -ConVar ai_follow_use_points( "ai_follow_use_points", "1" ); -ConVar ai_follow_use_points_when_moving( "ai_follow_use_points_when_moving", "1" ); -#define FollowMsg(s) if ( !GetOuter() || !ai_debug_follow.GetBool() ) ; else DevMsg( GetOuter(), "Follow: " s ) - -#define WAIT_HINT_MIN_DIST (16*16) // Was: Square(GetHullWidth()) - -//----------------------------------------------------------------------------- -// -// Purpose: Formation management -// -// Right now, this is in a very preliminary sketch state. (toml 03-03-03) -//----------------------------------------------------------------------------- - -struct AI_FollowSlot_t; -struct AI_FollowFormation_t; -struct AI_FollowGroup_t; - -struct AI_Follower_t -{ - AI_Follower_t() - { - slot = -1; - memset( &navInfo, 0, sizeof(navInfo) ); - pGroup = NULL; - } - - AIHANDLE hFollower; - int slot; - AI_FollowNavInfo_t navInfo; - AI_FollowGroup_t * pGroup; // backpointer for efficiency -}; - -struct AI_FollowGroup_t -{ - AI_FollowFormation_t * pFormation; - EHANDLE hFollowTarget; - CUtlFixedLinkedList followers; - CVarBitVec slotUsage; -}; - - -//------------------------------------- - -class CAI_FollowManager -{ -public: - ~CAI_FollowManager() - { - for ( int i = 0; i < m_groups.Count(); i++ ) - delete m_groups[i]; - } - - bool AddFollower( CBaseEntity *pTarget, CAI_BaseNPC *pFollower, AI_Formations_t formation, AI_FollowManagerInfoHandle_t *pHandle ); - void ChangeFormation( AI_FollowManagerInfoHandle_t &handle, AI_Formations_t formation ); - void RemoveFollower( AI_FollowManagerInfoHandle_t &handle ); - bool CalcFollowPosition( AI_FollowManagerInfoHandle_t &handle, AI_FollowNavInfo_t *pNavInfo ); - - int CountFollowersInGroup( CAI_BaseNPC *pMember ) - { - AI_FollowGroup_t *pGroup = FindFollowerGroup( pMember ); - - if( !pGroup ) - { - return 0; - } - - return pGroup->followers.Count(); - } - - int CountFollowers( CBaseEntity *pFollowTarget, string_t iszClassname ) - { - AI_FollowGroup_t *pGroup = FindGroup( pFollowTarget ); - - if( !pGroup ) - { - return 0; - } - - if ( iszClassname == NULL_STRING ) - { - return pGroup->followers.Count(); - } - else - { - int result = 0; - for ( int i = pGroup->followers.Head(); i != pGroup->followers.InvalidIndex(); i = pGroup->followers.Next( i ) ) - { - if ( pGroup->followers[i].hFollower && pGroup->followers[i].hFollower->ClassMatches( iszClassname ) ) - { - result++; - } - } - return result; - } - } - - int GetFollowerSlot( CAI_BaseNPC *pFollower ) - { - AI_FollowGroup_t *pGroup = FindFollowerGroup( pFollower ); - - if( !pGroup ) - { - return 0; - } - - int h = pGroup->followers.Head(); - - while( h != pGroup->followers.InvalidIndex() ) - { - AI_Follower_t *it = &pGroup->followers[h]; - if ( it->hFollower.Get() == pFollower ) - { - return it->slot; - } - - h = pGroup->followers.Next( h ); - } - - return 0; - } - -private: - bool RedistributeSlots( AI_FollowGroup_t *pGroup ); - int FindBestSlot( AI_FollowGroup_t *pGroup ); - void CalculateFieldsFromSlot( AI_FollowSlot_t *pSlot, AI_FollowNavInfo_t *pFollowerInfo ); - - AI_FollowGroup_t *FindCreateGroup( CBaseEntity *pTarget, AI_Formations_t formation ); - AI_FollowGroup_t *FindGroup( CBaseEntity *pTarget ); - AI_FollowGroup_t *FindFollowerGroup( CBaseEntity *pFollower ); - void RemoveGroup( AI_FollowGroup_t * ); - - //--------------------------------- - - CUtlVector m_groups; -}; - -//------------------------------------- - -CAI_FollowManager g_AIFollowManager; - -//----------------------------------------------------------------------------- - -int AIGetNumFollowers( CBaseEntity *pEntity, string_t iszClassname ) -{ - return g_AIFollowManager.CountFollowers( pEntity, iszClassname ); -} - -//----------------------------------------------------------------------------- -// -// CAI_FollowBehavior -// -//----------------------------------------------------------------------------- - -BEGIN_SIMPLE_DATADESC( AI_FollowNavInfo_t ) - DEFINE_FIELD( flags, FIELD_INTEGER ), - DEFINE_FIELD( position, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( range, FIELD_FLOAT ), - DEFINE_FIELD( Zrange, FIELD_FLOAT ), - DEFINE_FIELD( tolerance, FIELD_FLOAT ), - DEFINE_FIELD( followPointTolerance, FIELD_FLOAT ), - DEFINE_FIELD( targetMoveTolerance, FIELD_FLOAT ), - DEFINE_FIELD( repathOnRouteTolerance, FIELD_FLOAT ), - DEFINE_FIELD( walkTolerance, FIELD_FLOAT ), - DEFINE_FIELD( coverTolerance, FIELD_FLOAT ), - DEFINE_FIELD( enemyLOSTolerance, FIELD_FLOAT ), - DEFINE_FIELD( chaseEnemyTolerance, FIELD_FLOAT ), -END_DATADESC(); - -BEGIN_SIMPLE_DATADESC( AI_FollowParams_t ) - DEFINE_FIELD( formation, FIELD_INTEGER ), - DEFINE_FIELD( bNormalMemoryDiscard, FIELD_BOOLEAN ), - -END_DATADESC(); - -BEGIN_DATADESC( CAI_FollowBehavior ) - DEFINE_FIELD( m_hFollowTarget, FIELD_EHANDLE ), - DEFINE_EMBEDDED( m_FollowNavGoal ), - DEFINE_FIELD( m_flTimeUpdatedFollowPosition, FIELD_TIME ), - DEFINE_FIELD( m_bFirstFacing, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flTimeFollowTargetVisible, FIELD_TIME ), - DEFINE_EMBEDDED( m_TargetMonitor ), - DEFINE_FIELD( m_bTargetUnreachable, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bFollowNavFailed, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bMovingToCover, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flOriginalEnemyDiscardTime, FIELD_FLOAT ), - DEFINE_FIELD( m_SavedDistTooFar, FIELD_FLOAT ), - DEFINE_EMBEDDED( m_FollowDelay ), - DEFINE_EMBEDDED( m_RepathOnFollowTimer ), - DEFINE_CUSTOM_FIELD( m_CurrentFollowActivity, ActivityDataOps() ), - DEFINE_EMBEDDED( m_TimeBlockUseWaitPoint ), - DEFINE_EMBEDDED( m_TimeCheckForWaitPoint ), - DEFINE_FIELD( m_pInterruptWaitPoint, FIELD_CLASSPTR ), - DEFINE_EMBEDDED( m_TimeBeforeSpreadFacing ), - DEFINE_EMBEDDED( m_TimeNextSpreadFacing ), - // m_hFollowManagerInfo (reset on load) - DEFINE_EMBEDDED( m_params ), - DEFINE_FIELD( m_hFollowGoalEnt, FIELD_EHANDLE ), - DEFINE_FIELD( m_nFailedFollowAttempts, FIELD_INTEGER ), - DEFINE_FIELD( m_flTimeFailFollowStarted, FIELD_TIME ), - DEFINE_FIELD( m_vFollowMoveAnchor, FIELD_POSITION_VECTOR ), -END_DATADESC(); - -//------------------------------------- - -CAI_FollowBehavior::CAI_FollowBehavior( const AI_FollowParams_t ¶ms ) -{ - memset( &m_FollowNavGoal, 0, sizeof( m_FollowNavGoal ) ); - - m_FollowDelay.Set( 1.0, 3.0 ); - m_hFollowManagerInfo.m_pGroup = NULL; - m_hFollowManagerInfo.m_hFollower = 0; - - m_TimeBlockUseWaitPoint.Set( 0.5, 1.5 ); - m_TimeCheckForWaitPoint.Set( 1.0 ); - m_pInterruptWaitPoint = NULL; - - m_TimeBeforeSpreadFacing.Set( 2.0, 4.0 ); - m_TimeNextSpreadFacing.Set( 3.0, 12.0 ); - - m_params = params; - - NoteSuccessfulFollow(); -} - -//------------------------------------- - -CAI_FollowBehavior::~CAI_FollowBehavior() -{ - Assert( !m_hFollowManagerInfo.m_pGroup ); -} - -//----------------------------------------------------------------------------- -// Purpose: Draw any text overlays -// Input : Previous text offset from the top -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CAI_FollowBehavior::DrawDebugTextOverlays( int text_offset ) -{ - char tempstr[ 512 ]; - int offset; - CBaseEntity * followEnt; - - offset = BaseClass::DrawDebugTextOverlays( text_offset ); - if ( GetOuter()->m_debugOverlays & OVERLAY_TEXT_BIT ) - { - followEnt = GetFollowTarget(); - if ( followEnt != NULL ) - { - Q_snprintf( tempstr, sizeof(tempstr), "Follow: (%d) %s (%s)", followEnt->entindex(), followEnt->GetDebugName(), followEnt->GetClassname() ); - } - else - { - Q_snprintf( tempstr, sizeof(tempstr), "Follow: NULL" ); - } - GetOuter()->EntityText( offset, tempstr, 0 ); - offset++; - } - - return offset; -} - - -void CAI_FollowBehavior::DrawDebugGeometryOverlays() -{ - if ( GetFollowTarget() ) - { - Vector vecFollowPos = GetGoalPosition(); - NDebugOverlay::HorzArrow( GetOuter()->GetAbsOrigin(), vecFollowPos, 16.0f, 0, 255, 0, 0, true, 0 ); - } -} - - -//------------------------------------- - -void CAI_FollowBehavior::SetParameters( const AI_FollowParams_t ¶ms ) -{ - m_params = params; - - if ( m_hFollowManagerInfo.m_pGroup ) - { - g_AIFollowManager.ChangeFormation( m_hFollowManagerInfo, params.formation ); - m_flTimeUpdatedFollowPosition = 0; - } -} - -//------------------------------------- - -CBaseEntity * CAI_FollowBehavior::GetFollowTarget() -{ - return m_hFollowTarget; -} - -//------------------------------------- - -// Returns true if the NPC is actively following a target. -bool CAI_FollowBehavior::IsActive( void ) -{ - if ( IsRunning() && GetFollowTarget() ) - { - // Only true if we're running a follow schedule - return IsCurScheduleFollowSchedule(); - } - - return false; -} - -//------------------------------------- - -void CAI_FollowBehavior::SetFollowTarget( CBaseEntity *pLeader, bool fFinishCurSchedule ) -{ - if ( pLeader == m_hFollowTarget ) - return; - - if ( !GetOuter()->IsAlive() ) - { - return; - } - - m_flTimeUpdatedFollowPosition = 0; - - if ( m_hFollowTarget ) - { - g_AIFollowManager.RemoveFollower( m_hFollowManagerInfo ); - m_hFollowTarget = NULL; - m_hFollowManagerInfo.m_pGroup = NULL; - if ( IsRunning() ) - { - if ( GetNavigator()->GetGoalType() == GOALTYPE_TARGETENT ) - { - GetNavigator()->StopMoving(); // Stop him from walking toward the player - } - - if ( GetEnemy() != NULL ) - { - GetOuter()->SetIdealState( NPC_STATE_COMBAT ); - } - } - } - - if ( pLeader ) - { - if ( g_AIFollowManager.AddFollower( pLeader, GetOuter(), m_params.formation, &m_hFollowManagerInfo ) ) - { - m_hFollowTarget = pLeader; - m_bFirstFacing = true; - m_flTimeFollowTargetVisible = 0; - SetCondition( COND_TARGET_MOVED_FROM_MARK ); - m_TargetMonitor.ClearMark(); - NoteSuccessfulFollow(); - } - } - - NotifyChangeBehaviorStatus(fFinishCurSchedule); -} - -//------------------------------------- -void CAI_FollowBehavior::SetFollowGoalDirect( CAI_FollowGoal *pGoal ) -{ - m_hFollowGoalEnt = pGoal; - m_flTimeUpdatedFollowPosition = 0; -} - -//------------------------------------- - -bool CAI_FollowBehavior::SetFollowGoal( CAI_FollowGoal *pGoal, bool fFinishCurSchedule ) -{ - if ( GetOuter()->ShouldAcceptGoal( this, pGoal ) ) - { - GetOuter()->ClearCommandGoal(); - - if( hl2_episodic.GetBool() ) - { - // Poke the NPC to interrupt any stubborn schedules - GetOuter()->SetCondition(COND_PROVOKED); - } - - SetFollowTarget( pGoal->GetGoalEntity() ); - Assert( pGoal->m_iFormation == AIF_SIMPLE || pGoal->m_iFormation == AIF_WIDE || pGoal->m_iFormation == AIF_MEDIUM || pGoal->m_iFormation == AIF_SIDEKICK || pGoal->m_iFormation == AIF_VORTIGAUNT ); - SetParameters( AI_FollowParams_t( (AI_Formations_t)pGoal->m_iFormation ) ); - m_hFollowGoalEnt = pGoal; - m_flTimeUpdatedFollowPosition = 0; - return true; - } - return false; -} - -//------------------------------------- - -void CAI_FollowBehavior::ClearFollowGoal( CAI_FollowGoal *pGoal ) -{ - GetOuter()->OnClearGoal( this, pGoal ); - if ( pGoal == m_hFollowGoalEnt ) - { - SetFollowTarget( NULL ); - m_hFollowGoalEnt = NULL; - m_flTimeUpdatedFollowPosition = 0; - } -} - -//------------------------------------- - -bool CAI_FollowBehavior::UpdateFollowPosition() -{ - AI_PROFILE_SCOPE( CAI_FollowBehavior_UpdateFollowPosition ); - - if ( m_flTimeUpdatedFollowPosition == gpGlobals->curtime ) - { - return true; - } - - if (m_hFollowTarget == NULL) - return false; - - if ( !g_AIFollowManager.CalcFollowPosition( m_hFollowManagerInfo, &m_FollowNavGoal ) ) - { - return false; - } - - CBaseEntity *pFollowTarget = GetFollowTarget(); - - if ( pFollowTarget->GetParent() ) - { - if ( pFollowTarget->GetParent()->GetServerVehicle() ) - { - m_FollowNavGoal.targetMoveTolerance *= 1.5; - m_FollowNavGoal.range += pFollowTarget->GetParent()->BoundingRadius() * 0.333; - } - } - -#if TODO - // @TODO (toml 07-27-03): this is too simplistic. fails when the new point is an inappropriate target - CBasePlayer *pPlayer = dynamic_cast(m_hFollowTarget.Get()); - Vector targetVelocity = pPlayer->GetSmoothedVelocity(); - m_FollowNavGoal.position += targetVelocity * 0.5; -#endif - - m_flTimeUpdatedFollowPosition = gpGlobals->curtime; - - return true; -} - -//------------------------------------- - -bool CAI_FollowBehavior::IsMovingToFollowTarget() -{ - return ( IsRunning() && ( IsCurSchedule(SCHED_FOLLOW, false) || IsCurSchedule(SCHED_FOLLOWER_GO_TO_WAIT_POINT, false) ) ); -} - -//------------------------------------- - -bool CAI_FollowBehavior::CanSelectSchedule() -{ - if ( !GetOuter()->IsInterruptable() ) - return false; - - if ( !ShouldFollow() ) - { - return false; - } - - return true; -} - -//------------------------------------- - -bool CAI_FollowBehavior::PlayerIsPushing() -{ - return (m_hFollowTarget && m_hFollowTarget->IsPlayer() && HasCondition( COND_PLAYER_PUSHING ) ); -} - -//------------------------------------- - -bool CAI_FollowBehavior::IsFollowTargetInRange( float rangeMultiplier ) -{ - if ( !GetFollowTarget()->IsPlayer() && HasCondition( COND_RECEIVED_ORDERS ) ) - return false; - - if( GetNpcState() == NPC_STATE_COMBAT ) - { - if( IsFollowGoalInRange( MAX( m_FollowNavGoal.coverTolerance, m_FollowNavGoal.enemyLOSTolerance ) * rangeMultiplier, GetGoalZRange(), GetGoalFlags() ) ) - { - return true; - } - } - else - { - if( IsFollowGoalInRange( MAX( m_FollowNavGoal.tolerance, GetGoalRange() ) * rangeMultiplier, GetGoalZRange(), GetGoalFlags() ) ) - { - if ( m_FollowNavGoal.flags & AIFF_REQUIRE_LOS_OUTSIDE_COMBAT ) - { - //trace_t tr; - //AI_TraceLOS( vecStart, vecStart + vecDir * 8192, m_hFollowTarget, &tr ); - //if ( AI_TraceLOS m_FollowNavGoal.position - if ( !HasCondition(COND_SEE_PLAYER) ) - return false; - } - - return true; - } - } - return false; -} - -//------------------------------------- - -bool CAI_FollowBehavior::IsFollowGoalInRange( float tolerance, float zTolerance, int flags ) -{ - const Vector &origin = WorldSpaceCenter(); - const Vector &goal = GetGoalPosition(); - if ( zTolerance == -1 ) - zTolerance = GetHullHeight(); - float distanceSq = ( goal.AsVector2D() - origin.AsVector2D() ).LengthSqr(); - tolerance += 0.1; - - // Increase Z tolerance slightly as XY distance decreases - float flToleranceSq = (tolerance*tolerance); - float flIncreaseRange = flToleranceSq * 0.25; - zTolerance += zTolerance * clamp((distanceSq / flIncreaseRange), 0, 1 ); - if ( fabs( origin.z - goal.z ) > zTolerance ) - return false; - - if ( distanceSq > flToleranceSq ) - return false; - - if ( flags & AIFF_REQUIRE_LOS_OUTSIDE_COMBAT && m_hFollowTarget.Get() ) - { - if ( !GetOuter()->GetSenses()->DidSeeEntity( m_hFollowTarget ) ) - return false; - } - - return true; -} - -//------------------------------------- - -bool CAI_FollowBehavior::IsChaseGoalInRange() -{ - if ( GetEnemy() && ( GetEnemy()->WorldSpaceCenter() - m_FollowNavGoal.position ).LengthSqr() > Square( m_FollowNavGoal.chaseEnemyTolerance ) ) - return false; - - return true; -} - -//------------------------------------- - -void CAI_FollowBehavior::NoteFailedFollow() -{ - m_nFailedFollowAttempts++; - if ( m_flTimeFailFollowStarted == FLT_MAX ) - m_flTimeFailFollowStarted = gpGlobals->curtime; - - if ( GetOuter() && ai_debug_follow.GetBool() ) - DevMsg( GetOuter(), "Follow: NoteFailedFollow() (%d, %f)\n", m_nFailedFollowAttempts, m_flTimeFailFollowStarted ); -} - -//------------------------------------- - -void CAI_FollowBehavior::NoteSuccessfulFollow() -{ - m_nFailedFollowAttempts = 0; - m_flTimeFailFollowStarted = FLT_MAX; - FollowMsg( "NoteSuccessfulFollow()\n" ); -} - -//------------------------------------- - -void CAI_FollowBehavior::BeginScheduleSelection() -{ - if ( GetOuter()->m_hCine ) - GetOuter()->m_hCine->CancelScript(); - - m_TimeBeforeSpreadFacing.Reset(); - - SetCondition( COND_TARGET_MOVED_FROM_MARK ); - m_TargetMonitor.ClearMark(); - NoteSuccessfulFollow(); - - if ( !m_params.bNormalMemoryDiscard ) - { - // Forget about enemies that I haven't seen for >5 seconds - m_flOriginalEnemyDiscardTime = GetOuter()->GetEnemies()->GetEnemyDiscardTime(); - GetOuter()->GetEnemies()->SetEnemyDiscardTime( 5.0f ); - } - - m_SavedDistTooFar = GetOuter()->m_flDistTooFar; - if ( GetFollowTarget() && GetFollowTarget()->IsPlayer() ) - { - GetOuter()->m_flDistTooFar = FLT_MAX; - } - - BaseClass::BeginScheduleSelection(); -} - -//------------------------------------- - -void CAI_FollowBehavior::EndScheduleSelection() -{ - if ( !m_params.bNormalMemoryDiscard ) - { - // Restore our original enemy discard time - GetOuter()->GetEnemies()->SetEnemyDiscardTime( m_flOriginalEnemyDiscardTime ); - } - - if ( m_SavedDistTooFar > 0.1 ) // backward savefile compatability - { - GetOuter()->m_flDistTooFar = m_SavedDistTooFar; - } - - BaseClass::EndScheduleSelection(); -} - -//------------------------------------- - -void CAI_FollowBehavior::CleanupOnDeath( CBaseEntity *pCulprit, bool bFireDeathOutput ) -{ - if ( m_hFollowManagerInfo.m_pGroup ) - { - g_AIFollowManager.RemoveFollower( m_hFollowManagerInfo ); - m_hFollowManagerInfo.m_pGroup = NULL; - m_hFollowTarget = NULL; - } - BaseClass::CleanupOnDeath( pCulprit, bFireDeathOutput ); -} - -//------------------------------------- - -void CAI_FollowBehavior::Precache() -{ - if ( m_hFollowTarget != NULL && m_hFollowManagerInfo.m_pGroup == NULL ) - { - // Post load fixup - if ( !g_AIFollowManager.AddFollower( m_hFollowTarget, GetOuter(), m_params.formation, &m_hFollowManagerInfo ) ) - { - m_hFollowTarget = NULL; - } - } -} - -//------------------------------------- - -void CAI_FollowBehavior::GatherConditions( void ) -{ - BaseClass::GatherConditions(); - - if ( !GetFollowTarget() ) - { - ClearCondition( COND_FOLLOW_PLAYER_IS_LIT ); - ClearCondition( COND_FOLLOW_PLAYER_IS_NOT_LIT ); - ClearCondition( COND_FOLLOW_TARGET_VISIBLE ); - ClearCondition( COND_FOLLOW_TARGET_NOT_VISIBLE ); - ClearCondition( COND_FOLLOW_DELAY_EXPIRED ); - ClearCondition( COND_TARGET_MOVED_FROM_MARK ); - ClearFollowPoint(); - m_pInterruptWaitPoint = NULL; - m_bTargetUnreachable = false; - m_flTimeFollowTargetVisible = 0; - - if ( IsRunning() ) - { - GetOuter()->ClearSchedule( "Follow target gone" ); - } - return; - } - - if ( !m_TargetMonitor.IsMarkSet() ) - { - FollowMsg( "No mark set\n" ); - } - - if ( m_FollowDelay.IsRunning() && m_FollowDelay.Expired()) - { - SetCondition( COND_FOLLOW_DELAY_EXPIRED ); - m_FollowDelay.Stop(); - } - - if ( m_TargetMonitor.TargetMoved2D( GetFollowTarget() ) ) - { - FollowMsg( "Target moved\n" ); - m_TargetMonitor.ClearMark(); - SetCondition( COND_TARGET_MOVED_FROM_MARK ); - m_bTargetUnreachable = false; - } - - if ( !m_TargetMonitor.IsMarkSet() ) - m_bTargetUnreachable = false; - - m_pInterruptWaitPoint = NULL; - - if ( GetHintNode() == NULL ) - { - if ( ShouldUseFollowPoints() && m_TimeBlockUseWaitPoint.Expired() && m_TimeCheckForWaitPoint.Expired() ) - { - m_TimeCheckForWaitPoint.Reset(); - m_pInterruptWaitPoint = FindFollowPoint(); - if ( m_pInterruptWaitPoint ) - SetCondition( COND_FOUND_WAIT_POINT ); - } - } - - if ( m_flTimeUpdatedFollowPosition == 0 || gpGlobals->curtime - m_flTimeUpdatedFollowPosition > 2.0 ) - UpdateFollowPosition(); - - if ( IsFollowTargetInRange() ) - { - NoteSuccessfulFollow(); - } - else if ( GetOuter()->GetTask() && !IsCurScheduleFollowSchedule() ) - { - if ( !m_FollowDelay.IsRunning() || m_FollowDelay.Expired() ) - { - switch ( GetOuter()->GetTask()->iTask ) - { - case TASK_WAIT_RANDOM: - case TASK_WAIT_INDEFINITE: - case TASK_WAIT: - case TASK_WAIT_FACE_ENEMY: - case TASK_WAIT_FACE_ENEMY_RANDOM: - { - m_TargetMonitor.ClearMark(); - if ( !HasCondition(COND_FOLLOW_PLAYER_IS_NOT_LIT) ) - { - SetCondition( COND_TARGET_MOVED_FROM_MARK ); - } - } - } - } - } - -#if 0 - else if ( !IsFollowPointInRange() ) - { - GetHintNode()->Unlock(); - SetHintNode( NULL ); - } -#endif - -#ifdef HL2_EPISODIC - // Let followers know if the player is lit in the darkness - if ( GetFollowTarget()->IsPlayer() && HL2GameRules()->IsAlyxInDarknessMode() ) - { - if ( LookerCouldSeeTargetInDarkness( GetOuter(), GetFollowTarget() ) ) - { - SetCondition( COND_FOLLOW_PLAYER_IS_LIT ); - ClearCondition( COND_FOLLOW_PLAYER_IS_NOT_LIT ); - } - else - { - SetCondition( COND_FOLLOW_PLAYER_IS_NOT_LIT ); - ClearCondition( COND_FOLLOW_PLAYER_IS_LIT ); - } - } -#endif - - // Set our follow target visibility state - if ( (GetFollowTarget()->IsPlayer() && HasCondition( COND_SEE_PLAYER )) || GetOuter()->FVisible( GetFollowTarget()) ) - { - SetCondition( COND_FOLLOW_TARGET_VISIBLE ); - ClearCondition( COND_FOLLOW_TARGET_NOT_VISIBLE ); - m_flTimeFollowTargetVisible = gpGlobals->curtime; - } - else - { - ClearCondition( COND_FOLLOW_TARGET_VISIBLE ); - SetCondition( COND_FOLLOW_TARGET_NOT_VISIBLE ); - } - - if ( HasFollowPoint() && ( m_flTimeFollowTargetVisible != 0 && gpGlobals->curtime - m_flTimeFollowTargetVisible > 5.0 ) ) - SetCondition( COND_FOLLOW_WAIT_POINT_INVALID ); - else - ClearCondition( COND_FOLLOW_WAIT_POINT_INVALID ); -} - -//------------------------------------- - -int CAI_FollowBehavior::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ) -{ - if ( failedTask == TASK_MOVE_TO_FOLLOW_POSITION || failedTask == TASK_GET_PATH_TO_FOLLOW_POSITION ) - { - if ( m_hFollowTarget ) - { - m_TargetMonitor.SetMark( m_hFollowTarget, m_FollowNavGoal.targetMoveTolerance * 0.5 ); - m_FollowDelay.Start(); - NoteFailedFollow(); - } - } - - return BaseClass::SelectFailSchedule( failedSchedule, failedTask, taskFailCode ); -} - -//------------------------------------- - -bool CAI_FollowBehavior::ShouldFollow() -{ - if ( !GetFollowTarget() ) - return false; - - if ( GetFollowTarget()->GetFlags() & FL_NOTARGET ) - return false; - - // If we recently failed to build a follow path, wait a while to - // give other schedules a chance to run. - if ( m_bFollowNavFailed && m_FollowDelay.IsRunning() && !m_FollowDelay.Expired() ) - { - return false; - } - - m_bFollowNavFailed = false; - - return true; -} - -//------------------------------------- - -bool CAI_FollowBehavior::ShouldMoveToFollowTarget() -{ - if ( GetFollowTarget() == NULL ) - return false; - - if( m_bTargetUnreachable ) - return false; - -#ifdef HL2_EPISODIC - if ( HL2GameRules()->IsAlyxInDarknessMode() ) - { - // If we're in darkness mode, the player needs to be lit by - // darkness, but we don't need line of sight to him. - if ( HasCondition(COND_FOLLOW_PLAYER_IS_NOT_LIT) ) - return false; - } -#endif - - if ( HasFollowPoint() ) - { - if ( IsFollowPointInRange() ) - return false; - } - else if ( IsFollowTargetInRange() ) - return false; - - if( m_FollowDelay.IsRunning() && !m_FollowDelay.Expired() && !HasCondition( COND_TARGET_MOVED_FROM_MARK ) ) - return false; - - return true; -} - -//------------------------------------- - -int CAI_FollowBehavior::SelectScheduleManagePosition() -{ - if ( PlayerIsPushing() ) - return SCHED_MOVE_AWAY; - - if ( !UpdateFollowPosition() ) - return SCHED_FAIL; - - return SCHED_NONE; -} - -//------------------------------------- - -bool CAI_FollowBehavior::ShouldUseFollowPoints() -{ - if ( !ai_follow_use_points.GetBool() || GetEnemy() != NULL ) - return false; - - return true; -} - -//------------------------------------- - -bool CAI_FollowBehavior::HasFollowPoint() -{ - return ( GetHintNode() && GetHintNode()->HintType() == HINT_FOLLOW_WAIT_POINT ); -} - -//------------------------------------- - -void CAI_FollowBehavior::ClearFollowPoint() -{ - if ( GetHintNode() && GetHintNode()->HintType() == HINT_FOLLOW_WAIT_POINT ) - { - GetHintNode()->Unlock(); - SetHintNode( NULL ); - } -} - -//------------------------------------- - -const Vector &CAI_FollowBehavior::GetFollowPoint() -{ - static Vector invalid = vec3_invalid; - if ( GetHintNode() && GetHintNode()->HintType() == HINT_FOLLOW_WAIT_POINT ) - return GetHintNode()->GetAbsOrigin(); - return invalid; -} - -//------------------------------------- - -CAI_Hint *CAI_FollowBehavior::FindFollowPoint() -{ - if ( !m_TimeBlockUseWaitPoint.Expired() ) - return NULL; - - CHintCriteria hintCriteria; - hintCriteria.SetHintType( HINT_FOLLOW_WAIT_POINT ); - hintCriteria.SetFlag( bits_HINT_NODE_VISIBLE | bits_HINT_NODE_NEAREST ); - - // Add the search position - hintCriteria.AddIncludePosition( GetGoalPosition(), MAX( m_FollowNavGoal.followPointTolerance, GetGoalRange() ) ); - hintCriteria.AddExcludePosition( GetGoalPosition(), (GetFollowTarget()->WorldAlignMins().AsVector2D() - GetFollowTarget()->WorldAlignMaxs().AsVector2D()).Length()); - - return CAI_HintManager::FindHint( GetOuter(), hintCriteria ); -} - -//------------------------------------- - -bool CAI_FollowBehavior::IsFollowPointInRange() -{ - return ( GetHintNode() && - GetHintNode()->HintType() == HINT_FOLLOW_WAIT_POINT && - (GetHintNode()->GetAbsOrigin() - GetFollowTarget()->GetAbsOrigin()).LengthSqr() < Square(MAX(m_FollowNavGoal.followPointTolerance, GetGoalRange())) ); -} - - -//------------------------------------- - -bool CAI_FollowBehavior::ShouldIgnoreFollowPointFacing() -{ - if ( !GetHintNode() ) - return true; - - HintIgnoreFacing_t hintSetting = GetHintNode()->GetIgnoreFacing(); - - if ( hintSetting == HIF_DEFAULT ) - return ( GetHintNode()->HintActivityName() == NULL_STRING ); - - return ( hintSetting == HIF_YES ); -} - -//------------------------------------- - -void CAI_FollowBehavior::SetFollowPoint( CAI_Hint *pHintNode ) -{ - if ( !pHintNode ) - return; - - Assert( pHintNode->HintType() == HINT_FOLLOW_WAIT_POINT ); - - if ( GetHintNode() == pHintNode ) - return; - - if ( GetHintNode() ) - GetHintNode()->Unlock(); - - if ( !pHintNode->Lock( GetOuter() ) ) - { - SetHintNode( NULL ); - m_TimeBlockUseWaitPoint.Reset(); - } - else - SetHintNode( pHintNode ); -} - -//------------------------------------- - -int CAI_FollowBehavior::SelectScheduleFollowPoints() -{ - bool bShouldUseFollowPoints = ( ShouldUseFollowPoints() && IsFollowGoalInRange( m_FollowNavGoal.followPointTolerance + 0.1, GetGoalZRange(), GetGoalFlags() ) ); - float distSqToPoint = FLT_MAX; - bool bHasFollowPoint = HasFollowPoint(); - - if ( bHasFollowPoint ) - { - distSqToPoint = (GetHintNode()->GetAbsOrigin() - GetAbsOrigin()).LengthSqr(); - if ( !bShouldUseFollowPoints || - distSqToPoint > Square(2.0 * GetHullWidth()) || - HasCondition( COND_FOLLOW_WAIT_POINT_INVALID ) ) - { - GetHintNode()->Unlock(); - SetHintNode( NULL ); - m_TimeBlockUseWaitPoint.Reset(); - bShouldUseFollowPoints = false; - } - } - - if ( bShouldUseFollowPoints ) - { - bool bNewHint = false; - if ( GetHintNode() && !bHasFollowPoint ) - { - GetHintNode()->Unlock(); - SetHintNode( NULL ); - } - - if (!GetHintNode()) - { - bNewHint = true; - SetFollowPoint( ( m_pInterruptWaitPoint ) ? m_pInterruptWaitPoint : FindFollowPoint() ); - - if ( GetHintNode() ) - distSqToPoint = (GetHintNode()->GetAbsOrigin() - GetAbsOrigin()).LengthSqr(); - } - - if ( GetHintNode() ) - { - if ( bNewHint || distSqToPoint > WAIT_HINT_MIN_DIST ) - return SCHED_FOLLOWER_GO_TO_WAIT_POINT; - if ( !ShouldIgnoreFollowPointFacing() ) - return SCHED_FOLLOWER_STAND_AT_WAIT_POINT; - } - } - else - ClearFollowPoint(); - - return SCHED_NONE; -} - -//------------------------------------- - -int CAI_FollowBehavior::SelectScheduleMoveToFormation() -{ - if( ( GetNpcState() != NPC_STATE_COMBAT && !( HasCondition( COND_LIGHT_DAMAGE ) || HasCondition( COND_HEAVY_DAMAGE ))) || - !IsFollowGoalInRange( GetGoalRange(), GetGoalZRange(), GetGoalFlags() ) ) - { - AISquadIter_t iter; - CAI_Squad *pSquad = GetOuter()->GetSquad(); - if ( pSquad ) - { - for ( CAI_BaseNPC *pSquadMember = pSquad->GetFirstMember( &iter ); pSquadMember; pSquadMember = pSquad->GetNextMember( &iter ) ) - { - if ( pSquadMember->HasCondition( COND_PLAYER_PUSHING ) ) - { - return SCHED_NONE; - } - } - } - if ( ShouldMoveToFollowTarget() || m_bFirstFacing ) - { - return SCHED_TARGET_FACE; // Code for "SCHED_MOVE_TO_FACE_FOLLOW_TARGET". Used by Talker clients to interject comment - } - } - return SCHED_NONE; -} - -//------------------------------------- - -int CAI_FollowBehavior::SelectSchedule() -{ - // Allow a range attack if we need to do it - if ( hl2_episodic.GetBool() ) - { - // Range attack - if ( GetOuter()->ShouldMoveAndShoot() == false && HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - return SCHED_RANGE_ATTACK1; - } - - if ( GetFollowTarget() ) - { - if ( !GetFollowTarget()->IsAlive() ) - { - // UNDONE: Comment about the recently dead player here? - SetFollowTarget( NULL ); - } - else if ( ShouldFollow() ) - { - int result = SCHED_NONE; - - result = SelectScheduleManagePosition(); - if ( result != SCHED_NONE ) - return result; - - result = SelectScheduleFollowPoints(); - if ( result != SCHED_NONE ) - return result; - - result = SelectScheduleMoveToFormation(); - if ( result != SCHED_NONE ) - return result; - - if ( HasCondition ( COND_NO_PRIMARY_AMMO ) && HaveSequenceForActivity( GetOuter()->TranslateActivity( ACT_RUN_AIM ) ) ) - return SCHED_HIDE_AND_RELOAD; - } - - if ( PlayerIsPushing() ) - return SCHED_MOVE_AWAY; - } - else - { - // Should not have landed here. Follow target ent must have been destroyed - NotifyChangeBehaviorStatus(); - } - - if ( HasCondition( COND_TARGET_MOVED_FROM_MARK ) ) - { - m_TargetMonitor.SetMark( m_hFollowTarget, m_FollowNavGoal.targetMoveTolerance * 0.5 ); - } - - return FollowCallBaseSelectSchedule(); -} - -//------------------------------------- - -int CAI_FollowBehavior::TranslateSchedule( int scheduleType ) -{ - switch( scheduleType ) - { - case SCHED_FOLLOWER_IDLE_STAND: - // If we have an enemy, at least face them! - if ( GetEnemy() ) - return SCHED_FOLLOWER_COMBAT_FACE; - - break; - - case SCHED_IDLE_STAND: - { - if ( ShouldMoveToFollowTarget() && !IsFollowGoalInRange( GetGoalRange(), GetGoalZRange(), GetGoalFlags() ) ) - { - return SCHED_MOVE_TO_FACE_FOLLOW_TARGET; - } - if ( HasFollowPoint() && !ShouldIgnoreFollowPointFacing() ) - return SCHED_FOLLOWER_GO_TO_WAIT_POINT; - - // If we have an enemy, at least face them! - if ( GetEnemy() ) - return SCHED_FOLLOWER_COMBAT_FACE; - - return SCHED_FOLLOWER_IDLE_STAND; - } - - case SCHED_COMBAT_STAND: - case SCHED_ALERT_STAND: - { - if ( ShouldMoveToFollowTarget() && !IsFollowGoalInRange( GetGoalRange(), GetGoalZRange(), GetGoalFlags() ) ) - { - return SCHED_MOVE_TO_FACE_FOLLOW_TARGET; - } - break; - } - - case SCHED_TARGET_FACE: - { - if ( ( ShouldMoveToFollowTarget() || m_bFirstFacing ) && !IsFollowGoalInRange( GetGoalRange(), GetGoalZRange(), GetGoalFlags() ) ) - { - return SCHED_MOVE_TO_FACE_FOLLOW_TARGET; - } - if ( HasFollowPoint() && !ShouldIgnoreFollowPointFacing() ) - return SCHED_FOLLOWER_GO_TO_WAIT_POINT; - if ( !m_TargetMonitor.IsMarkSet() ) - m_TargetMonitor.SetMark( m_hFollowTarget, m_FollowNavGoal.targetMoveTolerance ); - return SCHED_FACE_FOLLOW_TARGET; // @TODO (toml 03-03-03): should select a facing sched - } - - case SCHED_TARGET_CHASE: - { - return SCHED_FOLLOW; - } - - // SCHED_ESTABLISH_LINE_OF_FIRE_FALLBACK just tells the NPC to chase their enemy, so - // forbid this unless the destination is acceptable within the parameters of the follow behavior. - case SCHED_CHASE_ENEMY: - case SCHED_ESTABLISH_LINE_OF_FIRE_FALLBACK: - { - if ( IsChaseGoalInRange() == false ) - return SCHED_FOLLOWER_IDLE_STAND; - break; - } - - case SCHED_RANGE_ATTACK1: - { - if ( GetOuter()->GetShotRegulator()->IsInRestInterval() ) - { - if ( GetEnemy() ) - return SCHED_FOLLOWER_COMBAT_FACE; - - return SCHED_FOLLOWER_IDLE_STAND; // @TODO (toml 07-02-03): Should do something more tactically sensible - } - break; - } - - case SCHED_CHASE_ENEMY_FAILED: - { - if (HasMemory(bits_MEMORY_INCOVER)) - { - // Make sure I don't get too far from the player - if ( GetFollowTarget() ) - { - float fDist = (GetLocalOrigin() - GetFollowTarget()->GetAbsOrigin()).Length(); - if (fDist > 500) - { - return SCHED_FOLLOW; - } - } - } - break; - } - - case SCHED_MOVE_AWAY_FAIL: - { - return SCHED_FOLLOWER_MOVE_AWAY_FAIL; - } - case SCHED_MOVE_AWAY_END: - { - return SCHED_FOLLOWER_MOVE_AWAY_END; - } - } - return BaseClass::TranslateSchedule( scheduleType ); -} - -//------------------------------------- - -void CAI_FollowBehavior::OnStartSchedule( int scheduleType ) -{ - if ( !IsRunning() && HasFollowPoint() ) - { - ClearHintNode( 0.5 ); - } - - if ( !m_TargetMonitor.IsMarkSet() && !IsCurScheduleFollowSchedule() ) - { - m_TargetMonitor.SetMark( m_hFollowTarget, m_FollowNavGoal.targetMoveTolerance ); - } -} - -//------------------------------------- - -void CAI_FollowBehavior::GetFollowTargetViewLoc( Vector *pResult ) -{ - if ( !dynamic_cast(m_hFollowTarget.Get()) ) - { - trace_t tr; - Vector vecStart, vecDir; - - ASSERT( m_hFollowTarget != NULL ); - - vecStart = m_hFollowTarget->EyePosition(); - - CBasePlayer *pPlayer; - - pPlayer = dynamic_cast(m_hFollowTarget.Get()); - - if( pPlayer ) - { - // Follow target is a player. - pPlayer->EyeVectors( &vecDir, NULL, NULL ); - } - else - { - // Not a player. - m_hFollowTarget->GetVectors( &vecDir, NULL, NULL ); - } - - AI_TraceLOS( vecStart, vecStart + vecDir * 8192, m_hFollowTarget, &tr ); - - *pResult = tr.endpos; - } - else - *pResult = m_hFollowTarget->GetAbsOrigin(); -} - -//------------------------------------- - -bool CAI_FollowBehavior::ValidateFaceTarget( Vector *pFaceTarget ) -{ - if ( *pFaceTarget == vec3_invalid ) - { - if ( m_hFollowTarget != NULL ) - { - *pFaceTarget = m_hFollowTarget->GetAbsOrigin(); - } - return false; - } - - Vector testPoint = *pFaceTarget - GetAbsOrigin(); - testPoint.z = 0; - VectorNormalize( testPoint ); - testPoint *= 48; - testPoint += GetOuter()->EyePosition(); - - trace_t tr; - AI_TraceLine( GetOuter()->EyePosition(), testPoint, MASK_BLOCKLOS, m_hFollowTarget, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction < 1.0 ) - { - *pFaceTarget = m_hFollowTarget->GetAbsOrigin(); - return false; - } - return true; -} - -//------------------------------------- - -bool CAI_FollowBehavior::FindCoverFromEnemyAtFollowTarget( float coverRadius, Vector *pResult ) -{ - CBaseEntity *pEntity = GetEnemy(); - - return GetOuter()->FindCoverPosInRadius( pEntity, m_FollowNavGoal.position, coverRadius, pResult ); -} - -//------------------------------------- - -void CAI_FollowBehavior::StartTask( const Task_t *pTask ) -{ - AI_PROFILE_SCOPE( CAI_FollowBehavior_StartTask ); - - switch ( pTask->iTask ) - { - case TASK_RANGE_ATTACK1: - BaseClass::StartTask( pTask ); - break; - - case TASK_GET_PATH_TO_FOLLOW_POSITION: - { - if ( !UpdateFollowPosition() ) - { - TaskFail(FAIL_NO_TARGET); - } - else - { - m_TargetMonitor.SetMark( m_hFollowTarget, m_FollowNavGoal.targetMoveTolerance ); - m_bMovingToCover = false; - GetOuter()->m_vInterruptSavePosition = vec3_invalid; - } - - break; - } - - case TASK_CANT_FOLLOW: - { - SetFollowTarget( NULL, true ); - TaskComplete(); - break; - } - - case TASK_FOLLOWER_FACE_TACTICAL: - case TASK_FACE_FOLLOW_TARGET: - { - if ( !m_TimeBeforeSpreadFacing.Expired() ) - { - m_TimeNextSpreadFacing.Reset(); - } - - Vector faceTarget = vec3_invalid; - bool bFollowingPoint = ( dynamic_cast(m_hFollowTarget.Get()) != NULL ); - if ( GetNpcState() == NPC_STATE_COMBAT ) - { - if( gpGlobals->curtime - GetOuter()->GetEnemyLastTimeSeen() < 5.0 ) - { - faceTarget = GetEnemyLKP(); - } - else if ( !bFollowingPoint ) - { - GetFollowTargetViewLoc( &faceTarget ); - } - } - else if ( m_hFollowTarget && !bFollowingPoint ) - { - if ( m_bFirstFacing && m_hFollowTarget->IsPlayer() ) - { - faceTarget = m_hFollowTarget->GetAbsOrigin(); - } - else if ( m_TimeNextSpreadFacing.Expired() ) - { - m_TimeNextSpreadFacing.Reset(); - - bool bIsEpisodicVitalAlly; - -#ifdef HL2_DLL - bIsEpisodicVitalAlly = (hl2_episodic.GetBool() && GetOuter()->Classify() == CLASS_PLAYER_ALLY_VITAL); -#else - bIsEpisodicVitalAlly = false; -#endif//HL2_DLL - - if( bIsEpisodicVitalAlly ) - { - faceTarget = m_hFollowTarget->GetAbsOrigin(); - } - else - { - int roll = random->RandomInt(1, 4); - if ( roll == 1 ) - { - GetFollowTargetViewLoc( &faceTarget ); - } - else if ( roll == 2 ) - { - faceTarget = m_hFollowTarget->GetAbsOrigin(); - } - else - { - // Fan out and face to cover all directions. - int count = g_AIFollowManager.CountFollowersInGroup( GetOuter() ); - - if( count > 0 ) - { - // Slice up the directions among followers and leader. ( +1 because we count the leader!) - float flSlice = 360.0 / (count + 1); - - // Add one to slots so then are 1 to N instead of 0 to N - 1. - int slot = random->RandomInt( 0, count ); - - QAngle angle = m_hFollowTarget->GetAbsAngles(); - - // split up the remaining angles among followers in my group. - angle.y = UTIL_AngleMod( angle.y + ( flSlice * slot ) ); - - Vector vecDir; - AngleVectors( angle, &vecDir ); - - faceTarget = GetOuter()->GetAbsOrigin() + vecDir * 128; - } - } - } - } - else - { - // Stay where we are - TaskComplete(); - break; - } - } - - m_bFirstFacing = false; - - if ( ValidateFaceTarget( &faceTarget ) ) - { - Assert( faceTarget != vec3_invalid ); - - if ( !GetOuter()->FInAimCone( faceTarget ) ) - { - GetMotor()->SetIdealYawToTarget( faceTarget, 30 ); - GetOuter()->SetTurnActivity(); - } - else - TaskComplete(); - } - else - ChainStartTask( TASK_FACE_REASONABLE ); - - break; - } - - case TASK_MOVE_TO_FOLLOW_POSITION: - { - if ( m_hFollowTarget == NULL) - { - TaskFail(FAIL_NO_TARGET); - } - else if ( (m_hFollowTarget->GetAbsOrigin() - GetAbsOrigin()).Length() < 1 ) - { - TaskComplete(); - } - else if ( !GetNavigator()->IsGoalActive() ) - { - TaskFail(FAIL_NO_ROUTE); - } - else - { - m_vFollowMoveAnchor = GetAbsOrigin(); - m_CurrentFollowActivity = ACT_INVALID; - m_RepathOnFollowTimer.Force(); - } - break; - } - - case TASK_SET_FOLLOW_TARGET_MARK: - { - if ( m_hFollowTarget == NULL) - { - TaskFail(FAIL_NO_TARGET); - } - else - { - FollowMsg( "TASK_SET_FOLLOW_TARGET_MARK\n" ); - m_TargetMonitor.SetMark( m_hFollowTarget, m_FollowNavGoal.targetMoveTolerance ); - TaskComplete(); - } - break; - } - - case TASK_SET_FOLLOW_DELAY: - { - m_FollowDelay.Start( pTask->flTaskData ); - TaskComplete(); - break; - } - - case TASK_FIND_COVER_FROM_ENEMY: - { - CBaseEntity *pLeader = GetFollowTarget(); - if ( pLeader ) - { - Vector coverPos = vec3_invalid; - float coverRadius = MIN( GetOuter()->CoverRadius(), m_FollowNavGoal.coverTolerance ); - - if ( FindCoverFromEnemyAtFollowTarget( coverRadius, &coverPos ) ) - { - AI_NavGoal_t goal(GOALTYPE_COVER, coverPos, ACT_RUN, AIN_HULL_TOLERANCE, AIN_DEF_FLAGS); - GetNavigator()->SetGoal( goal ); - - GetOuter()->m_flMoveWaitFinished = gpGlobals->curtime + pTask->flTaskData; - TaskComplete(); - } - else - TaskFail(FAIL_NO_COVER); - } - else - BaseClass::StartTask( pTask ); - break; - } - - case TASK_GET_PATH_TO_FOLLOW_POINT: - { - ChainStartTask( TASK_GET_PATH_TO_HINTNODE, ShouldIgnoreFollowPointFacing() ); - break; - } - - case TASK_ARRIVE_AT_FOLLOW_POINT: - { - if ( GetHintNode() && !ShouldIgnoreFollowPointFacing() ) - ChainStartTask( TASK_FACE_HINTNODE, 0 ); - else - TaskComplete(); - break; - } - - case TASK_SET_FOLLOW_POINT_STAND_SCHEDULE: - { - if ( GetHintNode() && !ShouldIgnoreFollowPointFacing() ) - { - float distSqToPoint = (GetHintNode()->GetAbsOrigin() - GetAbsOrigin()).LengthSqr(); - if ( distSqToPoint < WAIT_HINT_MIN_DIST ) - { - GetOuter()->SetSchedule( SCHED_FOLLOWER_STAND_AT_WAIT_POINT ); - } - else - { - GetHintNode()->Unlock(); - SetHintNode( NULL ); - m_TimeBlockUseWaitPoint.Reset(); - TaskFail("Couldn't get to wait node." ); - } - } - else - { - GetOuter()->SetSchedule( SCHED_FACE_FOLLOW_TARGET ); - } - break; - } - - case TASK_BEGIN_STAND_AT_WAIT_POINT: - { - if ( !m_TargetMonitor.IsMarkSet() && IsFollowPointInRange() ) - m_TargetMonitor.SetMark( m_hFollowTarget, m_FollowNavGoal.targetMoveTolerance ); - if ( GetHintNode() && !ShouldIgnoreFollowPointFacing() ) - ChainStartTask( TASK_FACE_HINTNODE, 0 ); - else - TaskComplete(); - break; - } - - default: - BaseClass::StartTask( pTask ); - } -} - -//------------------------------------- - -void CAI_FollowBehavior::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_GET_PATH_TO_FOLLOW_POSITION: - { - switch( GetOuter()->GetTaskInterrupt() ) - { - case 0: - { - if ( GetEnemy() ) - { - Assert( GetOuter()->m_vInterruptSavePosition == vec3_invalid ); - Vector coverPos = vec3_invalid; - float coverRadius = MIN( (float)12*12, m_FollowNavGoal.coverTolerance ); - if ( FindCoverFromEnemyAtFollowTarget( coverRadius, &coverPos ) ) - { - GetOuter()->m_vInterruptSavePosition = coverPos; - } - GetOuter()->TaskInterrupt(); - break; - } - } - // Fall through... - - case 1: - { - if ( GetOuter()->m_vInterruptSavePosition != vec3_invalid ) - { - AI_NavGoal_t goal(GOALTYPE_COVER, GetOuter()->m_vInterruptSavePosition, ACT_RUN, AIN_HULL_TOLERANCE, AIN_DEF_FLAGS); - if ( GetNavigator()->SetGoal( goal, AIN_NO_PATH_TASK_FAIL ) ) - { - TaskComplete(); - m_bMovingToCover = true; - } - else - { - GetOuter()->TaskInterrupt(); - } - break; - } - // Fall through... - } - - case 2: - { - Assert( !m_bMovingToCover ); - Vector vGoalPosition; - if ( HasFollowPoint() && IsFollowPointInRange() ) - vGoalPosition = GetFollowPoint(); - else - vGoalPosition = GetGoalPosition(); - - AI_NavGoal_t goal( vGoalPosition, AIN_DEF_ACTIVITY, GetGoalTolerance() ); - if ( !m_hFollowTarget->GetParent() || !m_hFollowTarget->GetParent()->GetServerVehicle() ) - { - goal.pTarget = m_hFollowTarget; - } - else - { - goal.pTarget = m_hFollowTarget->GetParent(); - } - - bool bSuccess = true; - if ( !GetNavigator()->SetGoal( goal, AIN_NO_PATH_TASK_FAIL ) ) - { - const Vector &vTarget = GetFollowTarget()->WorldSpaceCenter(); - Vector vToGoal = vGoalPosition - vTarget; - if ( vToGoal.Length2DSqr() > 6*12 ) - { - goal.dest = vTarget + vToGoal * 0.5; - if ( !GetNavigator()->SetGoal( goal, AIN_NO_PATH_TASK_FAIL ) ) - { - bSuccess = false; - m_FollowDelay.Start( 2.0, 5.0 ); - } - } - else - { - bSuccess = false; - m_FollowDelay.Start( 2.0, 5.0 ); - } - } - - if ( !bSuccess ) - { - m_bFollowNavFailed = true; - TaskFail( FAIL_NO_ROUTE ); - } - else - { - TaskComplete(); - } - } - } - - break; - } - - case TASK_FOLLOWER_FACE_TACTICAL: - case TASK_FACE_FOLLOW_TARGET: - { - ChainRunTask( TASK_FACE_REASONABLE ); - break; - } - - case TASK_MOVE_TO_FOLLOW_POSITION: - { - if ( m_hFollowTarget == NULL ) - { - TaskFail(FAIL_NO_TARGET); - } - else - { - if ( m_bMovingToCover ) - { - ChainRunTask( TASK_WAIT_FOR_MOVEMENT ); - NoteSuccessfulFollow(); - return; - } - - // Re-evaluate when you think your finished, or the target has moved too far - if ( !UpdateFollowPosition() ) - { - TaskFail(FAIL_NO_TARGET); - break; - } - - if ( ShouldUseFollowPoints() && ai_follow_use_points_when_moving.GetBool() ) - { - if ( HasFollowPoint() ) - { - if ( !IsFollowPointInRange() ) - { - ClearFollowPoint(); - GetNavigator()->SetArrivalDirection( vec3_origin ); - GetNavigator()->SetArrivalActivity( ACT_INVALID ); - m_TimeBlockUseWaitPoint.Reset(); - m_TimeCheckForWaitPoint.Reset(); - } - } - if ( GetNavigator()->GetNavType() != NAV_JUMP && !HasFollowPoint() && m_pInterruptWaitPoint ) - { - SetFollowPoint( m_pInterruptWaitPoint ); - } - } - else - { - ClearFollowPoint(); - if ( GetNavigator()->IsGoalActive() ) - { - GetNavigator()->SetArrivalDirection( vec3_origin ); - GetNavigator()->SetArrivalActivity( ACT_INVALID ); - } - } - - if ( !GetNavigator()->IsGoalActive() ) - { - // What this probably means is that the navigation failed but within tolerance - // So for now, just call it good and block another attempt for a bit - TaskComplete(); - if ( !IsFollowPointInRange() ) - ClearFollowPoint(); - if ( !IsFollowGoalInRange( m_FollowNavGoal.tolerance, GetGoalZRange(), GetGoalFlags() ) ) - m_FollowDelay.Start( 0.25, 0.75 ); - else - { - m_TargetMonitor.SetMark( GetFollowTarget(), m_FollowNavGoal.targetMoveTolerance ); - m_bTargetUnreachable = false; - } - break; - } - - if ( !HasFollowPoint() ) - { - float range = GetGoalRange(); - - Vector vVelocity =- GetFollowTarget()->GetSmoothedVelocity(); - bool bDoSlowdown = ( vVelocity.LengthSqr() < Square(4*12) ); - if ( bDoSlowdown ) - { - range += GetMotor()->MinStoppingDist(12) - 12; - } - - if ( IsFollowGoalInRange( range, GetGoalZRange(), GetGoalFlags() ) ) - { - m_TimeBeforeSpreadFacing.Reset(); - TaskComplete(); - GetNavigator()->StopMoving( !bDoSlowdown ); // Stop moving - m_TargetMonitor.SetMark( GetFollowTarget(), m_FollowNavGoal.targetMoveTolerance ); - break; - } - - // Update the nav goal if needed - if ( m_RepathOnFollowTimer.Expired() ) - { - if ( (GetNavigator()->GetGoalPos() - GetGoalPosition()).LengthSqr() > Square( m_FollowNavGoal.repathOnRouteTolerance ) ) - { - if ( GetNavigator()->GetNavType() != NAV_JUMP ) - { - m_RepathOnFollowTimer.Set( .5 ); - if ( !GetNavigator()->UpdateGoalPos( GetGoalPosition() ) ) - { - bool bSuccess = false; - const Vector &vTarget = GetFollowTarget()->WorldSpaceCenter(); - Vector vToGoal = GetGoalPosition() - vTarget; - if ( vToGoal.Length2DSqr() > 6*12 ) - { - if ( GetNavigator()->UpdateGoalPos( vTarget + vToGoal * 0.5 ) ) - { - bSuccess = true; - } - } - - if ( !bSuccess ) - { - TaskFail(FAIL_NO_ROUTE); - m_bTargetUnreachable = true; - } - break; - } - NoteSuccessfulFollow(); - } - } - } - } - else - { - const Vector &vFollowPoint = GetFollowPoint(); - if ( GetNavigator()->GetGoalPos() != vFollowPoint ) - { - if ( !GetNavigator()->UpdateGoalPos( vFollowPoint ) ) - { - TaskFail(FAIL_NO_ROUTE); - m_bTargetUnreachable = true; - break; - } - NoteSuccessfulFollow(); - - if ( !ShouldIgnoreFollowPointFacing() ) - GetNavigator()->SetArrivalDirection( GetHintNode()->GetDirection() ); - if ( GetHintNode()->HintActivityName() != NULL_STRING ) - { - Activity hintActivity = (Activity)CAI_BaseNPC::GetActivityID( STRING(GetHintNode()->HintActivityName()) ); - if ( hintActivity != ACT_INVALID ) - { - GetNavigator()->SetArrivalActivity( GetOuter()->GetHintActivity(GetHintNode()->HintType(), hintActivity ) ); - } - else - { - int iSequence = GetOuter()->LookupSequence(STRING(GetHintNode()->HintActivityName())); - if ( iSequence != ACT_INVALID ) - { - GetNavigator()->SetArrivalSequence( iSequence ); - } - } - } - } - } - - // Set the appropriate activity based on an overlapping range - // overlap the range to prevent oscillation - // BUGBUG: this is checking linear distance (ie. through walls) and not path distance or even visibility - - // Never stop running once started - if ( m_CurrentFollowActivity != ACT_RUN ) - { - float distToTargetSq = ( GetNavigator()->GetGoalPos() - GetLocalOrigin() ).Length2DSqr(); - - // Pick the right movement activity. - Activity followActivity = ( distToTargetSq < Square(m_FollowNavGoal.walkTolerance) && GetOuter()->GetState() != NPC_STATE_COMBAT ) ? ACT_WALK : ACT_RUN; - - // If we're supposed to have LOS, run to catch up - if ( m_FollowNavGoal.flags & AIFF_REQUIRE_LOS_OUTSIDE_COMBAT ) - { - if ( !GetOuter()->GetSenses()->DidSeeEntity( m_hFollowTarget ) ) - { - followActivity = ACT_RUN; - } - } - - if ( followActivity != m_CurrentFollowActivity ) - { - m_CurrentFollowActivity = followActivity; - GetNavigator()->SetMovementActivity(followActivity); - } - } - - if ( ( m_vFollowMoveAnchor - GetAbsOrigin() ).LengthSqr() > Square( 15.0 * 12.0 ) ) - { - m_vFollowMoveAnchor = GetAbsOrigin(); - NoteSuccessfulFollow(); - } - - } - break; - } - - case TASK_ARRIVE_AT_FOLLOW_POINT: - { - ChainRunTask( TASK_FACE_HINTNODE, 0 ); - break; - } - - case TASK_BEGIN_STAND_AT_WAIT_POINT: - { - ChainRunTask( TASK_FACE_HINTNODE, 0 ); - break; - } - - default: - BaseClass::RunTask( pTask ); - } -} - -//------------------------------------- - -void CAI_FollowBehavior::TaskComplete( bool fIgnoreSetFailedCondition ) -{ - const Task_t *pTask = GetCurTask(); - if ( pTask->iTask == TASK_MOVE_TO_FOLLOW_POSITION || pTask->iTask == TASK_GET_PATH_TO_FOLLOW_POSITION ) - NoteSuccessfulFollow(); - BaseClass::TaskComplete( fIgnoreSetFailedCondition ); -} - -//------------------------------------- - -void CAI_FollowBehavior::BuildScheduleTestBits() -{ - BaseClass::BuildScheduleTestBits(); - bool bIsTakeCover = false; - bool bIsHideAndReload = false; - bool bIsReload = false; - bool bIgnoreMovedMark = false; - - if ( ( GetOuter()->ConditionInterruptsCurSchedule( COND_GIVE_WAY ) || - GetOuter()->ConditionInterruptsCurSchedule( COND_IDLE_INTERRUPT ) || - ( bIsHideAndReload = IsCurSchedule(SCHED_HIDE_AND_RELOAD ) ) == true || - ( bIsReload = IsCurSchedule(SCHED_RELOAD ) ) == true || - IsCurSchedule(SCHED_STANDOFF ) || - ( bIsTakeCover = IsCurSchedule(SCHED_TAKE_COVER_FROM_ENEMY ) ) == true || - IsCurSchedule(SCHED_COMBAT_FACE ) || - IsCurSchedule(SCHED_ALERT_FACE ) || - IsCurSchedule(SCHED_COMBAT_STAND ) || - IsCurSchedule(SCHED_ALERT_STAND) ) || - IsCurSchedule(SCHED_ALERT_FACE_BESTSOUND ) ) - { -#ifdef HL2_EPISODIC - if( IsCurSchedule(SCHED_RELOAD, false) && GetOuter()->Classify() == CLASS_PLAYER_ALLY_VITAL ) - { - // Alyx and Barney do not stop reloading because the player has moved. - // Citizens and other regular allies do. - bIgnoreMovedMark = true; - } -#endif//HL2_EPISODIC - - if( !bIgnoreMovedMark ) - { - GetOuter()->SetCustomInterruptCondition( GetClassScheduleIdSpace()->ConditionLocalToGlobal( COND_TARGET_MOVED_FROM_MARK ) ); - } - - if ( !bIsTakeCover && !bIsHideAndReload && !bIsReload ) - GetOuter()->SetCustomInterruptCondition( GetClassScheduleIdSpace()->ConditionLocalToGlobal( COND_FOLLOW_DELAY_EXPIRED) ); - } - - // Add logic for NPCs not able to move and shoot - if ( hl2_episodic.GetBool() ) - { - if ( IsCurScheduleFollowSchedule() && GetOuter()->ShouldMoveAndShoot() == false ) - { - GetOuter()->SetCustomInterruptCondition( COND_CAN_RANGE_ATTACK1 ); - } - -#ifdef HL2_EPISODIC - // In Alyx darkness mode, break on the player turning their flashlight off - if ( HL2GameRules()->IsAlyxInDarknessMode() ) - { - if ( IsCurSchedule(SCHED_FOLLOW, false) || IsCurSchedule(SCHED_MOVE_TO_FACE_FOLLOW_TARGET, false) || - IsCurSchedule(SCHED_FACE_FOLLOW_TARGET, false) ) - { - GetOuter()->SetCustomInterruptCondition( GetClassScheduleIdSpace()->ConditionLocalToGlobal( COND_FOLLOW_PLAYER_IS_NOT_LIT ) ); - } - } -#endif // HL2_EPISODIC - } - - if ( GetNpcState() == NPC_STATE_COMBAT && IsCurScheduleFollowSchedule() ) - { - GetOuter()->ClearCustomInterruptCondition( COND_LIGHT_DAMAGE ); - } -} - -//------------------------------------- - -Activity CAI_FollowBehavior::NPC_TranslateActivity( Activity activity ) -{ - if ( activity == ACT_IDLE && HasFollowPoint() && GetHintNode()->HintActivityName() != NULL_STRING ) - { - return GetOuter()->GetHintActivity(GetHintNode()->HintType(), (Activity)CAI_BaseNPC::GetActivityID( STRING(GetHintNode()->HintActivityName()) ) ); - } - return BaseClass::NPC_TranslateActivity( activity ); -} - -//------------------------------------- - -bool CAI_FollowBehavior::IsCurScheduleFollowSchedule() -{ - int curScheduleId = ( GetOuter()->GetCurSchedule() ) ? GetOuter()->GetCurSchedule()->GetId() : SCHED_NONE; - if ( curScheduleId >= GetClassScheduleIdSpace()->ScheduleLocalToGlobal( SCHED_FOLLOWER_MOVE_AWAY_FAIL ) && - curScheduleId <= GetClassScheduleIdSpace()->ScheduleLocalToGlobal( SCHED_FOLLOWER_STAND_AT_WAIT_POINT ) ) - { - return true; - } - return false; -} - -//------------------------------------- - -bool CAI_FollowBehavior::IsCurTaskContinuousMove() -{ - const Task_t *pCurTask = GetCurTask(); - if ( pCurTask && pCurTask->iTask == TASK_MOVE_TO_FOLLOW_POSITION ) - return true; - return BaseClass::IsCurTaskContinuousMove(); -} - -//------------------------------------- - -void CAI_FollowBehavior::OnMovementFailed() -{ - float acceptDist = m_FollowNavGoal.range; - if ( m_FollowNavGoal.tolerance > acceptDist ) - acceptDist = m_FollowNavGoal.tolerance; - - if ( GetNpcState() == NPC_STATE_COMBAT ) - { - if ( m_FollowNavGoal.coverTolerance > acceptDist ) - acceptDist = m_FollowNavGoal.coverTolerance; - if (m_FollowNavGoal.enemyLOSTolerance > acceptDist ) - acceptDist = m_FollowNavGoal.enemyLOSTolerance; - } - - float flZRange = GetGoalZRange(); - if ( GetGoalZRange() == -1 ) - { - flZRange = GetHullHeight() * 2; - } - - if ( IsFollowGoalInRange( acceptDist * 1.5, flZRange, GetGoalFlags() ) ) - m_bTargetUnreachable = true; - else - m_FollowDelay.Start(); -} - -//------------------------------------- - -void CAI_FollowBehavior::OnMovementComplete() -{ - if ( !IsCurSchedule(SCHED_FOLLOWER_GO_TO_WAIT_POINT) ) - m_TimeBeforeSpreadFacing.Reset(); - else - { - m_TimeBeforeSpreadFacing.Force(); - m_TimeNextSpreadFacing.Force(); - } -} - -//------------------------------------- - -bool CAI_FollowBehavior::FValidateHintType( CAI_Hint *pHint ) -{ - if ( pHint->HintType() == HINT_FOLLOW_WAIT_POINT ) - { - if ( GetFollowTarget() && GetFollowTarget()->FVisible( pHint->GetAbsOrigin() + Vector( 0, 0, 0.1 ) ) ) - return true; - else - return false; - } - return BaseClass::FValidateHintType( pHint ); -} - -//------------------------------------- - -bool CAI_FollowBehavior::IsValidCover( const Vector &vLocation, CAI_Hint const *pHint ) -{ - if ( (vLocation - m_FollowNavGoal.position).LengthSqr() > Square( m_FollowNavGoal.coverTolerance + 0.1 ) ) - return false; - return BaseClass::IsValidCover( vLocation, pHint ); -} - -//------------------------------------- - -bool CAI_FollowBehavior::IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint ) -{ - if ( (vLocation - m_FollowNavGoal.position).LengthSqr() > Square( m_FollowNavGoal.enemyLOSTolerance + 0.1 ) ) - return false; - return BaseClass::IsValidShootPosition( vLocation, pNode, pHint ); -} - -//------------------------------------- - -bool CAI_FollowBehavior::ShouldAlwaysThink() -{ - return ( m_hFollowTarget && m_hFollowTarget->IsPlayer() ); -} - - -//----------------------------------------------------------------------------- -// -// CAI_FollowGoal -// -// Purpose: A level tool to control the follow behavior. Use is not required -// in order to use behavior. -// -//----------------------------------------------------------------------------- - -BEGIN_DATADESC( CAI_FollowGoal ) - DEFINE_KEYFIELD( m_iFormation, FIELD_INTEGER, "Formation" ), - -#ifdef HL2_EPISODIC - DEFINE_INPUTFUNC( FIELD_VOID, "OutsideTransition", InputOutsideTransition ), -#endif -END_DATADESC() - -//------------------------------------- - -LINK_ENTITY_TO_CLASS( ai_goal_follow, CAI_FollowGoal ); - -//------------------------------------- - -void CAI_FollowGoal::EnableGoal( CAI_BaseNPC *pAI ) -{ - CAI_FollowBehavior *pBehavior; - if ( !pAI->GetBehavior( &pBehavior ) ) - return; - - CBaseEntity *pGoalEntity = GetGoalEntity(); - if ( !pGoalEntity && AI_IsSinglePlayer() ) - { - if ( pAI->IRelationType(UTIL_GetLocalPlayer()) == D_LI ) - { - pGoalEntity = UTIL_GetLocalPlayer(); - SetGoalEntity( pGoalEntity ); - } - } - - if ( pGoalEntity ) - pBehavior->SetFollowGoal( this ); -} - -//------------------------------------- - -void CAI_FollowGoal::DisableGoal( CAI_BaseNPC *pAI ) -{ - CAI_FollowBehavior *pBehavior; - if ( !pAI || !pAI->GetBehavior( &pBehavior ) ) - return; - - pBehavior->ClearFollowGoal( this ); -} - -//------------------------------------- - -#ifdef HL2_EPISODIC -void CAI_FollowGoal::InputOutsideTransition( inputdata_t &inputdata ) -{ - EnterDormant(); -} -#endif - -//----------------------------------------------------------------------------- -// -// CAI_FollowManager -// -//----------------------------------------------------------------------------- - -//------------------------------------- -// -// Purpose: Formation definitions -// - -// @TODO (toml 11-21-03): rework follow so we don't have to have class specifc formations in this file - -struct AI_FollowSlot_t -{ - int priority; - - TableVector position; - float positionVariability; - - float rangeMin; - float rangeMax; - - float Zrange; - - float tolerance; - - // @Q (toml 02-28-03): facing? -}; - -struct AI_FollowFormation_t -{ - const char * pszName; - unsigned flags; - int nSlots; - - // Range within which can exit formation to seek a follow point - float followPointTolerance; - - // Distance target must move to reset formation - float targetMoveTolerance; - - // Distance from current move goal target must move to force a repathfind - float repathOnRouteTolerance; - - // Distance from target within which should walk, not run to formation - float walkTolerance; - - // Distance within which can exit formation to seek cover - float coverTolerance; - - // Distance within which can exit formation to seek LOS to enemy - float enemyLOSTolerance; - - // Distance within which can exit formation to chase enemy - float chaseEnemyTolerance; - - AI_FollowSlot_t * pSlots; -}; - -//------------------------------------- - -static AI_FollowSlot_t g_SimpleFollowFormationSlots[] = -{ - { 1, { 0, 0, 0 }, 0, 96, 120, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 96, 120, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 96, 120, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 96, 120, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 96, 120, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 96, 120, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 96, 120, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 96, 120, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 96, 120, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 96, 120, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 96, 120, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 96, 120, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 96, 120, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 96, 120, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 96, 120, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 96, 120, -1, 128 }, -}; - -static AI_FollowFormation_t g_SimpleFollowFormation = -{ - "Simple", - AIFF_DEFAULT | AIFF_USE_FOLLOW_POINTS, - ARRAYSIZE(g_SimpleFollowFormationSlots), - 168, // followPointTolerance - 36, // targetMoveTolerance - 60, // repathOnRouteTolerance - 190, // walkTolerance - 300, // coverTolerance - 300, // enemyLOSTolerance - 300, // chaseEnemyTolerance - g_SimpleFollowFormationSlots, -}; - - -//------------------------------------- - -static AI_FollowSlot_t g_WideFollowFormationSlots[] = -{ - { 1, { 0, 0, 0 }, 0, 120, 240, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 240, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 240, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 240, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 240, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 240, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 240, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 240, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 240, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 240, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 240, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 240, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 240, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 240, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 240, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 240, -1, 128 }, -}; - -static AI_FollowFormation_t g_WideFollowFormation = -{ - "Wide", - AIFF_DEFAULT | AIFF_USE_FOLLOW_POINTS, - ARRAYSIZE(g_WideFollowFormationSlots), - 168, // followPointTolerance - 72, // targetMoveTolerance - 60, // repathOnRouteTolerance - 190, // walkTolerance - 600, // coverTolerance - 600, // enemyLOSTolerance - 600, // chaseEnemyTolerance - g_WideFollowFormationSlots, -}; - -//--------------------------------------------- -// Antlion use very loose following criteria - -static AI_FollowSlot_t g_AntlionFollowFormationSlots[] = -{ - { 1, { 0, 0, 0 }, 0, 150, 250, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 150, 250, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 150, 250, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 150, 250, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 150, 250, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 150, 250, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 150, 250, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 150, 250, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 150, 250, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 150, 250, -1, 128 }, -}; - -static AI_FollowFormation_t g_AntlionFollowFormation = -{ - "Antlion", - AIFF_DEFAULT | AIFF_USE_FOLLOW_POINTS, - ARRAYSIZE(g_AntlionFollowFormationSlots), - 168, // followPointTolerance - 36, // targetMoveTolerance - 60, // repathOnRouteTolerance - 190, // walkTolerance - 1024, // coverTolerance - 1024, // enemyLOSTolerance - 1024, // chaseEnemyTolerance - g_AntlionFollowFormationSlots, -}; - -//------------------------------------- - -#define COMMANDER_TOLERANCE (13.0 * 1.415) - -static AI_FollowSlot_t g_CommanderFollowFormationSlots[] = -{ - { 2, { 0, 0, 0 }, 0, COMMANDER_TOLERANCE, COMMANDER_TOLERANCE, -1, 48 }, - { 1, { 0, 0, 0 }, 0, COMMANDER_TOLERANCE, COMMANDER_TOLERANCE, -1, 48 }, - { 1, { 0, 0, 0 }, 0, COMMANDER_TOLERANCE, COMMANDER_TOLERANCE, -1, 48 }, - { 1, { 0, 0, 0 }, 0, COMMANDER_TOLERANCE, COMMANDER_TOLERANCE, -1, 48 }, -}; - -static AI_FollowFormation_t g_CommanderFollowFormation = -{ - "Commander", - AIFF_DEFAULT | AIFF_USE_FOLLOW_POINTS, - ARRAYSIZE(g_CommanderFollowFormationSlots), - 168, // followPointTolerance - 6, // targetMoveTolerance - 60, // repathOnRouteTolerance - 12, // walkTolerance - 300, // coverTolerance - 300, // enemyLOSTolerance - 300, // chaseEnemyTolerance - g_CommanderFollowFormationSlots, -}; - -//------------------------------------- - -static AI_FollowSlot_t g_TightFollowFormationSlots[] = -{ - { 1, { 0, 0, 0 }, 0, 0, 0, -1, 48 }, - { 1, { 0, 0, 0 }, 0, 0, 0, -1, 48 }, - { 1, { 0, 0, 0 }, 0, 0, 0, -1, 48 }, - { 1, { 0, 0, 0 }, 0, 0, 0, -1, 48 }, -}; - -static AI_FollowFormation_t g_TightFollowFormation = -{ - "Tight", - AIFF_DEFAULT | AIFF_USE_FOLLOW_POINTS, - ARRAYSIZE(g_CommanderFollowFormationSlots), - 48, // followPointTolerance - 6, // targetMoveTolerance - 60, // repathOnRouteTolerance - 12, // walkTolerance - 300, // coverTolerance - 32, // enemyLOSTolerance - 32, // chaseEnemyTolerance - g_TightFollowFormationSlots, -}; - -//------------------------------------- - -static AI_FollowSlot_t g_MediumFollowFormationSlots[] = -{ - { 1, { 0, 0, 0 }, 0, 156, 156, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 156, 156, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 156, 156, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 156, 156, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 156, 156, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 156, 156, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 156, 156, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 156, 156, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 156, 156, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 156, 156, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 156, 156, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 156, 156, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 156, 156, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 156, 156, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 156, 156, -1, 128 }, - { 1, { 0, 0, 0 }, 0, 156, 156, -1, 128 }, -}; - -static AI_FollowFormation_t g_MediumFollowFormation = -{ - "Medium", - AIFF_DEFAULT | AIFF_USE_FOLLOW_POINTS, - ARRAYSIZE(g_MediumFollowFormationSlots), - 168, // followPointTolerance - 36, // targetMoveTolerance - 60, // repathOnRouteTolerance - 190, // walkTolerance - 300, // coverTolerance - 300, // enemyLOSTolerance - 300, // chaseEnemyTolerance - g_MediumFollowFormationSlots, -}; - -//------------------------------------- - -static AI_FollowSlot_t g_SidekickFollowFormationSlots[] = -{ - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, -}; - -static AI_FollowFormation_t g_SidekickFollowFormation = -{ - "Sidekick", - AIFF_DEFAULT | AIFF_USE_FOLLOW_POINTS | AIFF_REQUIRE_LOS_OUTSIDE_COMBAT, - ARRAYSIZE(g_SidekickFollowFormationSlots), - 168, // followPointTolerance - 36, // targetMoveTolerance - 60, // repathOnRouteTolerance - 190, // walkTolerance - 300, // coverTolerance - 300, // enemyLOSTolerance - 300, // chaseEnemyTolerance - g_SidekickFollowFormationSlots, -}; - - -//------------------------------------- -// Used for hunters following striders -//------------------------------------- -static AI_FollowSlot_t g_HunterFollowFormationSlots[] = -{ - { 3, { 480, -240, -400 }, 0, 48, 64, 1000, 60 }, - { 3, { 480, 240, -400 }, 0, 48, 64, 1000, 60 }, - { 2, { 480, 0, -400 }, 0, 48, 64, 1000, 60 }, - { 1, { -240, 0, -400 }, 0, 48, 64, 1000, 60 }, -}; - -static AI_FollowFormation_t g_HunterFollowFormation = -{ - "Hunter", - AIFF_DEFAULT | AIFF_USE_FOLLOW_POINTS, - ARRAYSIZE(g_HunterFollowFormationSlots), - 48, // followPointTolerance - 48, // targetMoveTolerance - 60,//180, // repathOnRouteTolerance - 0, // walkTolerance - 960, // coverTolerance - 960, // enemyLOSTolerance - 1920, // chaseEnemyTolerance - g_HunterFollowFormationSlots, -}; - - -//------------------------------------- - -static AI_FollowSlot_t g_VortigauntFollowFormationSlots[] = -{ - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, - { 1, { 0, 0, 0 }, 0, 120, 160, 256, 128 }, -}; - -static AI_FollowFormation_t g_VortigauntFollowFormation = -{ - "Vortigaunt", - AIFF_DEFAULT | AIFF_USE_FOLLOW_POINTS | AIFF_REQUIRE_LOS_OUTSIDE_COMBAT, - ARRAYSIZE(g_VortigauntFollowFormationSlots), - 168, // followPointTolerance - 36, // targetMoveTolerance - 60, // repathOnRouteTolerance - 190, // walkTolerance - 300, // coverTolerance - (50*12), // enemyLOSTolerance - (50*12), // chaseEnemyTolerance - g_VortigauntFollowFormationSlots, -}; - - -//----------------------------------------------------------------------------- -// NOTE: these must correspond with the AI_Formations_t enumeration in AI_Behavior_Follow.h!! -//----------------------------------------------------------------------------- -AI_FollowFormation_t *g_AI_Formations[] = -{ - &g_SimpleFollowFormation, - &g_WideFollowFormation, - &g_AntlionFollowFormation, - &g_CommanderFollowFormation, - &g_TightFollowFormation, - &g_MediumFollowFormation, - &g_SidekickFollowFormation, - &g_HunterFollowFormation, - &g_VortigauntFollowFormation, -}; - -AI_FollowFormation_t *AIGetFormation( AI_Formations_t formation ) -{ - if ( formation < 0 ) - formation = (AI_Formations_t)0; - else if ( (size_t)formation >= ARRAYSIZE( g_AI_Formations ) ) - formation = (AI_Formations_t)(ARRAYSIZE( g_AI_Formations ) - 1 ); - - return g_AI_Formations[formation]; -} - -//--------------------------------------------------------- - -bool CAI_FollowManager::AddFollower( CBaseEntity *pTarget, CAI_BaseNPC *pFollower, AI_Formations_t formation, AI_FollowManagerInfoHandle_t *pHandle ) -{ - AI_FollowGroup_t *pGroup = FindCreateGroup( pTarget, formation ); - int slot = FindBestSlot( pGroup ); - - if ( slot != -1 ) - { - MEM_ALLOC_CREDIT(); - - AI_FollowSlot_t *pSlot = &pGroup->pFormation->pSlots[slot]; - - int i = pGroup->followers.AddToTail( ); - - AI_Follower_t *iterNode = &pGroup->followers[i]; - iterNode->hFollower = pFollower; - iterNode->slot = slot; - iterNode->pGroup = pGroup; - - pGroup->slotUsage.Set( slot ); - - CalculateFieldsFromSlot( pSlot, &iterNode->navInfo ); - - pHandle->m_hFollower = i; - pHandle->m_pGroup = pGroup; - return true; - } - - pHandle->m_hFollower = 0; - pHandle->m_pGroup = NULL; - return false; -} - -//------------------------------------- - -bool CAI_FollowManager::CalcFollowPosition( AI_FollowManagerInfoHandle_t& hInfo, AI_FollowNavInfo_t *pNavInfo ) -{ - if ( hInfo.m_pGroup && hInfo.m_hFollower ) - { - AI_FollowGroup_t *pGroup = hInfo.m_pGroup; - Assert( pGroup->hFollowTarget.Get() ); - CBaseEntity *pTarget = pGroup->hFollowTarget; - - AI_Follower_t *iterNode = &pGroup->followers[hInfo.m_hFollower]; - if ( iterNode->navInfo.position != vec3_origin ) - { - QAngle angles = pTarget->GetLocalAngles(); - angles.x = angles.z = 0; - - matrix3x4_t fRotateMatrix; - AngleMatrix(angles, fRotateMatrix); - - VectorRotate( iterNode->navInfo.position, fRotateMatrix, pNavInfo->position); - pNavInfo->position += pTarget->WorldSpaceCenter(); - } - else - { - pNavInfo->position = iterNode->navInfo.position + pTarget->WorldSpaceCenter(); - } - - pNavInfo->tolerance = iterNode->navInfo.tolerance; - pNavInfo->range = iterNode->navInfo.range; - pNavInfo->Zrange = iterNode->navInfo.Zrange; - pNavInfo->flags = pGroup->pFormation->flags; - pNavInfo->followPointTolerance = pGroup->pFormation->followPointTolerance; - pNavInfo->targetMoveTolerance = pGroup->pFormation->targetMoveTolerance; - pNavInfo->repathOnRouteTolerance = pGroup->pFormation->repathOnRouteTolerance; - pNavInfo->walkTolerance = pGroup->pFormation->walkTolerance; - pNavInfo->coverTolerance = pGroup->pFormation->coverTolerance; - pNavInfo->enemyLOSTolerance = pGroup->pFormation->enemyLOSTolerance; - pNavInfo->chaseEnemyTolerance = pGroup->pFormation->chaseEnemyTolerance; - return true; - } - return false; -} - -//------------------------------------- - -bool CAI_FollowManager::RedistributeSlots( AI_FollowGroup_t *pGroup ) -{ - bool result = false; - - CUtlRBTree movedFollowers; - SetDefLessFunc( movedFollowers ); - - const Vector &originFollowed = pGroup->hFollowTarget->GetAbsOrigin(); - int bestSlot; - - while ( ( bestSlot = FindBestSlot( pGroup ) ) != -1 && ((int)movedFollowers.Count() < pGroup->followers.Count()) ) - { - AI_FollowSlot_t * pSlot = &pGroup->pFormation->pSlots[bestSlot]; - Vector slotPos = originFollowed + pSlot->position; - int h = pGroup->followers.Head(); - int hBest = pGroup->followers.InvalidIndex(); - float distSqBest = FLT_MAX; - - while ( h != pGroup->followers.InvalidIndex() ) - { - AI_Follower_t *p = &pGroup->followers[h]; - - if ( movedFollowers.Find( p->hFollower ) == movedFollowers.InvalidIndex() && - ( p->slot == -1 || pSlot->priority > pGroup->pFormation->pSlots[p->slot].priority ) ) - { - float distSqCur = ( p->hFollower->GetAbsOrigin() - slotPos ).LengthSqr(); - if ( distSqCur < distSqBest ) - { - hBest = h; - } - } - - h = pGroup->followers.Next( h ); - } - - if ( hBest == pGroup->followers.InvalidIndex() ) - break; - - AI_Follower_t *pBest = &pGroup->followers[hBest]; - if ( pBest->slot != -1 ) - { - pGroup->slotUsage.Clear( pBest->slot ); - } - pBest->slot = bestSlot; - CalculateFieldsFromSlot( pSlot, &pBest->navInfo ); - pGroup->slotUsage.Set( bestSlot ); - movedFollowers.Insert( pBest->hFollower ); - result = true; - } - return result; -} - -//------------------------------------- - -void CAI_FollowManager::ChangeFormation( AI_FollowManagerInfoHandle_t& hInfo, AI_Formations_t formation ) -{ - if ( !hInfo.m_pGroup || !hInfo.m_hFollower ) - return; - - AI_FollowGroup_t *pGroup = hInfo.m_pGroup; - AI_FollowFormation_t *pNewFormation = AIGetFormation( formation ); - if ( pNewFormation == pGroup->pFormation ) - return; - - int h = pGroup->followers.Head(); - - while ( h != pGroup->followers.InvalidIndex() ) - { - CAI_FollowBehavior *pFollowBehavior; - - AI_Follower_t *p = &pGroup->followers[h]; - p->slot = -1; - p->hFollower->GetBehavior( &pFollowBehavior ); - Assert( pFollowBehavior ); - if ( pFollowBehavior ) - { - pFollowBehavior->m_params.formation = formation; - pFollowBehavior->m_TargetMonitor.ClearMark(); - pFollowBehavior->SetCondition( CAI_FollowBehavior::COND_TARGET_MOVED_FROM_MARK ); - pFollowBehavior->m_bTargetUnreachable = false; - } - - h = pGroup->followers.Next( h ); - } - - pGroup->slotUsage.ClearAll(); - pGroup->pFormation = pNewFormation; - pGroup->slotUsage.Resize( pGroup->pFormation->nSlots ); - - RedistributeSlots( pGroup ); - -#ifdef DEBUG - h = pGroup->followers.Head(); - while ( h != pGroup->followers.InvalidIndex() ) - { - AI_Follower_t *p = &pGroup->followers[h]; - Assert( p->slot != -1 ); - h = pGroup->followers.Next( h ); - } -#endif -} - -//------------------------------------- - -void CAI_FollowManager::RemoveFollower( AI_FollowManagerInfoHandle_t& hInfo ) -{ - if ( hInfo.m_pGroup && hInfo.m_hFollower ) - { - AI_FollowGroup_t *pGroup = hInfo.m_pGroup; - AI_Follower_t* iterNode = &pGroup->followers[hInfo.m_hFollower]; - - int slot = iterNode->slot; - pGroup->slotUsage.Clear( slot ); - pGroup->followers.Remove( hInfo.m_hFollower ); - if ( pGroup->followers.Count() == 0 ) - { - RemoveGroup( pGroup ); - } - else - { - if ( pGroup->hFollowTarget != NULL ) // NULL on level unload - { - RedistributeSlots( pGroup ); - } - } - } -} - -//------------------------------------- - -int CAI_FollowManager::FindBestSlot( AI_FollowGroup_t *pGroup ) -{ - // @TODO (toml 02-28-03): crude placeholder - int nSlots = pGroup->pFormation->nSlots; - - int best = -1; - int bestPriority = -1; - - for ( int i = 0; i < nSlots; i++ ) - { - if ( !pGroup->slotUsage.IsBitSet( i ) && pGroup->pFormation->pSlots[i].priority > bestPriority ) - { - bestPriority = pGroup->pFormation->pSlots[i].priority; - best = i; - } - } - return best; -} - -//------------------------------------- - -void CAI_FollowManager::CalculateFieldsFromSlot( AI_FollowSlot_t *pSlot, AI_FollowNavInfo_t *pFollowerInfo ) -{ - // @TODO (toml 02-28-03): placeholder. Force break if someone tries to actually use - Assert( pSlot->positionVariability == 0.0 ); - //Assert( pSlot->tolerance == AIN_DEF_TOLERANCE ); - - pFollowerInfo->position = pSlot->position; - pFollowerInfo->range = random->RandomFloat( pSlot->rangeMin, pSlot->rangeMax ); - pFollowerInfo->Zrange = pSlot->Zrange; - pFollowerInfo->tolerance = pSlot->tolerance; -} - -//------------------------------------- - -AI_FollowGroup_t *CAI_FollowManager::FindCreateGroup( CBaseEntity *pTarget, AI_Formations_t formation ) -{ - AI_FollowGroup_t *pGroup = FindGroup( pTarget ); - - if ( !pGroup ) - { - { - MEM_ALLOC_CREDIT(); - pGroup = new AI_FollowGroup_t; - } - - pGroup->pFormation = AIGetFormation( formation ); - pGroup->slotUsage.Resize( pGroup->pFormation->nSlots ); - pGroup->hFollowTarget = pTarget; - - m_groups.AddToHead( pGroup ); - } - - return pGroup; -} - -//------------------------------------- - -void CAI_FollowManager::RemoveGroup( AI_FollowGroup_t *pGroup ) -{ - for ( int i = 0; i < m_groups.Count(); i++ ) - { - if ( m_groups[i] == pGroup ) - { - delete m_groups[i]; - m_groups.FastRemove(i); - return; - } - } -} - -//------------------------------------- - -AI_FollowGroup_t *CAI_FollowManager::FindGroup( CBaseEntity *pTarget ) -{ - for ( int i = 0; i < m_groups.Count(); i++ ) - { - if ( m_groups[i]->hFollowTarget == pTarget ) - return m_groups[i]; - } - return NULL; -} - -//------------------------------------- - -AI_FollowGroup_t *CAI_FollowManager::FindFollowerGroup( CBaseEntity *pFollower ) -{ - for ( int i = 0; i < m_groups.Count(); i++ ) - { - int h = m_groups[i]->followers.Head(); - while( h != m_groups[i]->followers.InvalidIndex() ) - { - AI_Follower_t *p = &m_groups[i]->followers[h]; - if ( p->hFollower.Get() == pFollower ) - return m_groups[i]; - h = m_groups[i]->followers.Next( h ); - } - } - return NULL; -} - -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER(CAI_FollowBehavior) - - DECLARE_TASK(TASK_CANT_FOLLOW) - DECLARE_TASK(TASK_FACE_FOLLOW_TARGET) - DECLARE_TASK(TASK_MOVE_TO_FOLLOW_POSITION) - DECLARE_TASK(TASK_GET_PATH_TO_FOLLOW_POSITION) - DECLARE_TASK(TASK_SET_FOLLOW_TARGET_MARK) - DECLARE_TASK(TASK_FOLLOWER_FACE_TACTICAL) - DECLARE_TASK(TASK_SET_FOLLOW_DELAY) - DECLARE_TASK(TASK_GET_PATH_TO_FOLLOW_POINT) - DECLARE_TASK(TASK_ARRIVE_AT_FOLLOW_POINT) - DECLARE_TASK(TASK_BEGIN_STAND_AT_WAIT_POINT) - DECLARE_TASK(TASK_SET_FOLLOW_POINT_STAND_SCHEDULE) - - DECLARE_CONDITION(COND_TARGET_MOVED_FROM_MARK) - DECLARE_CONDITION(COND_FOUND_WAIT_POINT) - DECLARE_CONDITION(COND_FOLLOW_DELAY_EXPIRED) - DECLARE_CONDITION(COND_FOLLOW_TARGET_VISIBLE) - DECLARE_CONDITION(COND_FOLLOW_TARGET_NOT_VISIBLE) - DECLARE_CONDITION(COND_FOLLOW_WAIT_POINT_INVALID) - DECLARE_CONDITION(COND_FOLLOW_PLAYER_IS_LIT) - DECLARE_CONDITION(COND_FOLLOW_PLAYER_IS_NOT_LIT) - - //========================================================= - // > SCHED_FOLLOWER_MOVE_AWAY_END - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_FOLLOWER_MOVE_AWAY_END, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_FOLLOWER_MOVE_AWAY_FAIL " - " TASK_STOP_MOVING 0" - " TASK_FACE_FOLLOW_TARGET 0" - " TASK_SET_FOLLOW_DELAY 2" - "" - " Interrupts" - " COND_PLAYER_PUSHING" - ) - - //========================================================= - // > SCHED_FOLLOWER_MOVE_AWAY_FAIL - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_FOLLOWER_MOVE_AWAY_FAIL, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_FOLLOW_TARGET 0" - " TASK_SET_FOLLOW_DELAY 2" - "" - " Interrupts" - " COND_PLAYER_PUSHING" - ) - - //========================================================= - // > SCHED_FOLLOW - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_FOLLOW, - - " Tasks" - " TASK_GET_PATH_TO_FOLLOW_POSITION 0" - " TASK_MOVE_TO_FOLLOW_POSITION 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_TARGET_FACE " - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_PROVOKED" - " COND_PLAYER_PUSHING" - " COND_BETTER_WEAPON_AVAILABLE" - ); - - //========================================================= - // > SCHED_MOVE_TO_FACE_FOLLOW_TARGET - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_MOVE_TO_FACE_FOLLOW_TARGET, - - " Tasks" -// " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" -// " TASK_FACE_FOLLOW_TARGET 0" -// " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_FOLLOW" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_PROVOKED" - " COND_PLAYER_PUSHING" - ) - - //========================================================= - // > SCHED_FACE_FOLLOW_TARGET - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_FACE_FOLLOW_TARGET, - - " Tasks" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_FACE_FOLLOW_TARGET 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_FOLLOWER_IDLE_STAND " - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_PROVOKED" - " COND_PLAYER_PUSHING" - " COND_GIVE_WAY" - ) - - //========================================================= - // > SCHED_FOLLOWER_GO_TO_WAIT_POINT - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_FOLLOWER_GO_TO_WAIT_POINT, - - " Tasks" - " TASK_LOCK_HINTNODE 0 " // this will fail the schedule if no hint node or not already lockable - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_FOLLOWER_GO_TO_WAIT_POINT_FAIL" - " TASK_SET_TOLERANCE_DISTANCE 4" - " TASK_GET_PATH_TO_FOLLOW_POINT 0" - " TASK_SET_FOLLOW_TARGET_MARK 0" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_ARRIVE_AT_FOLLOW_POINT 0" - " TASK_SET_FOLLOW_POINT_STAND_SCHEDULE 0" - - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_PROVOKED" - " COND_PLAYER_PUSHING" - " COND_TARGET_MOVED_FROM_MARK" - ) - - //========================================================= - // > SCHED_FOLLOWER_GO_TO_WAIT_POINT_FAIL - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_FOLLOWER_GO_TO_WAIT_POINT_FAIL, - - " Tasks" - " TASK_CLEAR_HINTNODE .5" - " TASK_SET_FOLLOW_DELAY 1" - "" - " Interrupts" - ) - - //========================================================= - // > SCHED_FOLLOWER_STAND_AT_WAIT_POINT - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_FOLLOWER_STAND_AT_WAIT_POINT, - - " Tasks" - " TASK_BEGIN_STAND_AT_WAIT_POINT 0" - " TASK_PLAY_HINT_ACTIVITY 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_FOLLOWER_STAND_AT_WAIT_POINT " - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_PROVOKED" - " COND_PLAYER_PUSHING" - " COND_TARGET_MOVED_FROM_MARK" - " COND_GIVE_WAY" - " COND_FOLLOW_WAIT_POINT_INVALID" -// " COND_IDLE_INTERRUPT" - ) - - DEFINE_SCHEDULE - ( - SCHED_FOLLOWER_IDLE_STAND, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" -// " TASK_SET_FOLLOW_TARGET_MARK 0" - " TASK_WAIT 2.5" - " TASK_FACE_FOLLOW_TARGET 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT 3" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_FEAR" - " COND_CAN_RANGE_ATTACK1" - " COND_NO_PRIMARY_AMMO" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_SMELL" - " COND_PROVOKED" - " COND_GIVE_WAY" - " COND_HEAR_DANGER" - " COND_HEAR_COMBAT" - " COND_HEAR_BULLET_IMPACT" - " COND_PLAYER_PUSHING" - " COND_TARGET_MOVED_FROM_MARK" - " COND_FOLLOW_DELAY_EXPIRED" - " COND_FOUND_WAIT_POINT" - " COND_IDLE_INTERRUPT" - " COND_BETTER_WEAPON_AVAILABLE" - ) - - DEFINE_SCHEDULE - ( - SCHED_FOLLOWER_COMBAT_FACE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_FEAR" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - " COND_NO_PRIMARY_AMMO" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_SMELL" - " COND_PROVOKED" - " COND_GIVE_WAY" - " COND_HEAR_DANGER" - " COND_HEAR_COMBAT" - " COND_HEAR_BULLET_IMPACT" - " COND_PLAYER_PUSHING" - " COND_TARGET_MOVED_FROM_MARK" - " COND_FOLLOW_DELAY_EXPIRED" - " COND_FOUND_WAIT_POINT" - " COND_BETTER_WEAPON_AVAILABLE" - ) - - AI_END_CUSTOM_SCHEDULE_PROVIDER() - -//============================================================================= diff --git a/game/server/ai_behavior_follow.h b/game/server/ai_behavior_follow.h deleted file mode 100644 index 7556ec709..000000000 --- a/game/server/ai_behavior_follow.h +++ /dev/null @@ -1,383 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef AI_BEHAVIOR_FOLLOW_H -#define AI_BEHAVIOR_FOLLOW_H - -#include "simtimer.h" -#include "ai_behavior.h" -#include "ai_goalentity.h" -#include "ai_utils.h" -#include "ai_moveshoot.h" - -#ifdef HL2_EPISODIC - #include "hl2_gamerules.h" -#endif - -#if defined( _WIN32 ) -#pragma once -#endif - - -//----------------------------------------------------------------------------- -// NOTE: these must correspond with the AI_FollowFormation_t array in AI_Behavior_Follow.cpp!! -//----------------------------------------------------------------------------- -enum AI_Formations_t -{ - AIF_SIMPLE, - AIF_WIDE, - AIF_ANTLION, - AIF_COMMANDER, - AIF_TIGHT, - AIF_MEDIUM, - AIF_SIDEKICK, - AIF_HUNTER, - AIF_VORTIGAUNT, -}; - -enum AI_FollowFormationFlags_t -{ - AIFF_DEFAULT = 0, - AIFF_USE_FOLLOW_POINTS = 0x01, - AIFF_REQUIRE_LOS_OUTSIDE_COMBAT = 0x02, -}; - -//----------------------------------------------------------------------------- -// -// CAI_FollowGoal -// -// Purpose: A level tool to control the follow behavior. Use is not required -// in order to use behavior. -// -//----------------------------------------------------------------------------- - -class CAI_FollowGoal : public CAI_GoalEntity -{ - DECLARE_CLASS( CAI_FollowGoal, CAI_GoalEntity ); - -public: - - virtual void EnableGoal( CAI_BaseNPC *pAI ); - virtual void DisableGoal( CAI_BaseNPC *pAI ); -#ifdef HL2_EPISODIC - virtual void InputOutsideTransition( inputdata_t &inputdata ); -#endif - - int m_iFormation; - - DECLARE_DATADESC(); -}; - -//----------------------------------------------------------------------------- - -int AIGetNumFollowers( CBaseEntity *pEntity, string_t iszClassname = NULL_STRING ); - -//----------------------------------------------------------------------------- - -struct AI_FollowNavInfo_t -{ - int flags; - Vector position; - float range; - float Zrange; - float tolerance; - float followPointTolerance; - float targetMoveTolerance; - float repathOnRouteTolerance; - float walkTolerance; - float coverTolerance; - float enemyLOSTolerance; - float chaseEnemyTolerance; - - DECLARE_SIMPLE_DATADESC(); -}; - -struct AI_FollowGroup_t; - -struct AI_FollowManagerInfoHandle_t -{ - AI_FollowGroup_t *m_pGroup; - int m_hFollower; -}; - -//------------------------------------- - -struct AI_FollowParams_t -{ - AI_FollowParams_t( AI_Formations_t formation = AIF_SIMPLE, bool bNormalMemoryDiscard = false ) - : formation(formation), - bNormalMemoryDiscard( bNormalMemoryDiscard ) - { - } - - AI_Formations_t formation; - bool bNormalMemoryDiscard; - - DECLARE_SIMPLE_DATADESC(); -}; - -//------------------------------------- - -class CAI_FollowBehavior : public CAI_SimpleBehavior -{ - DECLARE_CLASS( CAI_FollowBehavior, CAI_SimpleBehavior ); -public: - CAI_FollowBehavior( const AI_FollowParams_t ¶ms = AIF_SIMPLE ); - ~CAI_FollowBehavior(); - - virtual int DrawDebugTextOverlays( int text_offset ); - virtual void DrawDebugGeometryOverlays(); - - // Returns true if the NPC is actively following a target. - bool IsActive( void ); - - void SetParameters( const AI_FollowParams_t ¶ms ); - - virtual const char *GetName() { return "Follow"; } - AI_Formations_t GetFormation() const { return m_params.formation; } - - virtual bool CanSelectSchedule(); - - const AI_FollowNavInfo_t &GetFollowGoalInfo(); - CBaseEntity * GetFollowTarget(); - void SetFollowTarget( CBaseEntity *pLeader, bool fFinishCurSchedule = false ); - - CAI_FollowGoal *GetFollowGoal() { return m_hFollowGoalEnt; } // if any - bool SetFollowGoal( CAI_FollowGoal *pGoal, bool fFinishCurSchedule = false ); - void ClearFollowGoal( CAI_FollowGoal *pGoal ); - void SetFollowGoalDirect( CAI_FollowGoal *pGoal ); - - virtual bool FarFromFollowTarget() { return ( m_hFollowTarget && (GetAbsOrigin() - m_hFollowTarget->GetAbsOrigin()).LengthSqr() > (75*12)*(75*12) ); } - - virtual bool TargetIsUnreachable() { return m_bTargetUnreachable; } - - int GetNumFailedFollowAttempts() { return m_nFailedFollowAttempts; } - float GetTimeFailFollowStarted() { return m_flTimeFailFollowStarted; } - bool FollowTargetVisible() { return HasCondition( COND_FOLLOW_TARGET_VISIBLE ); }; - - bool IsMovingToFollowTarget(); - - float GetGoalRange(); - float GetGoalZRange(); - - virtual Activity NPC_TranslateActivity( Activity activity ); - virtual int TranslateSchedule( int scheduleType ); - virtual void StartTask( const Task_t *pTask ); - virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ); - virtual void TaskComplete( bool fIgnoreSetFailedCondition = false ); - virtual void GatherConditions(); - -protected: - - const Vector &GetGoalPosition(); - - virtual bool ShouldFollow(); - - friend class CAI_FollowManager; - - virtual void BeginScheduleSelection(); - virtual void EndScheduleSelection(); - - virtual void CleanupOnDeath( CBaseEntity *pCulprit, bool bFireDeathOutput ); - - virtual void Precache(); - virtual int SelectSchedule(); - virtual int FollowCallBaseSelectSchedule() { return BaseClass::SelectSchedule(); } - virtual void OnStartSchedule( int scheduleType ); - virtual void RunTask( const Task_t *pTask ); - void BuildScheduleTestBits(); - - bool IsCurScheduleFollowSchedule(); - - virtual bool IsCurTaskContinuousMove(); - virtual void OnMovementFailed(); - virtual void OnMovementComplete(); - virtual bool FValidateHintType( CAI_Hint *pHint ); - - bool IsValidCover( const Vector &vLocation, CAI_Hint const *pHint ); - bool IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint ); - bool FindCoverFromEnemyAtFollowTarget( float coverRadius, Vector *pResult ); - - bool ShouldAlwaysThink(); - - bool ShouldMoveToFollowTarget(); - - int SelectScheduleManagePosition(); - int SelectScheduleFollowPoints(); - int SelectScheduleMoveToFormation(); - - void GetFollowTargetViewLoc( Vector *pResult); - bool ValidateFaceTarget( Vector *pFaceTarget ); - - //---------------------------- - - bool ShouldUseFollowPoints(); - bool HasFollowPoint(); - void SetFollowPoint( CAI_Hint *pHintNode ); - void ClearFollowPoint(); - const Vector & GetFollowPoint(); - CAI_Hint * FindFollowPoint(); - bool IsFollowPointInRange(); - bool ShouldIgnoreFollowPointFacing(); - - //---------------------------- - - bool UpdateFollowPosition(); - const int GetGoalFlags(); - float GetGoalTolerance(); - bool PlayerIsPushing(); - - bool IsFollowTargetInRange( float rangeMultiplier = 1.0 ); - - bool IsFollowGoalInRange( float tolerance, float zTolerance, int flags ); - virtual bool IsChaseGoalInRange(); - - void NoteFailedFollow(); - void NoteSuccessfulFollow(); - - //---------------------------- - -protected: - - enum - { - SCHED_FOLLOWER_MOVE_AWAY_FAIL = BaseClass::NEXT_SCHEDULE, // Turn back toward player - SCHED_FOLLOWER_MOVE_AWAY_END, - SCHED_FOLLOW, - SCHED_FOLLOWER_IDLE_STAND, - SCHED_MOVE_TO_FACE_FOLLOW_TARGET, - SCHED_FACE_FOLLOW_TARGET, - SCHED_FOLLOWER_GO_TO_WAIT_POINT, - SCHED_FOLLOWER_GO_TO_WAIT_POINT_FAIL, - SCHED_FOLLOWER_STAND_AT_WAIT_POINT, - SCHED_FOLLOWER_COMBAT_FACE, - NEXT_SCHEDULE, - - TASK_CANT_FOLLOW = BaseClass::NEXT_TASK, - TASK_FACE_FOLLOW_TARGET, - TASK_MOVE_TO_FOLLOW_POSITION, - TASK_GET_PATH_TO_FOLLOW_POSITION, - TASK_SET_FOLLOW_TARGET_MARK, - TASK_FOLLOWER_FACE_TACTICAL, - TASK_SET_FOLLOW_DELAY, - TASK_GET_PATH_TO_FOLLOW_POINT, - TASK_ARRIVE_AT_FOLLOW_POINT, - TASK_SET_FOLLOW_POINT_STAND_SCHEDULE, - TASK_BEGIN_STAND_AT_WAIT_POINT, - NEXT_TASK, - - COND_TARGET_MOVED_FROM_MARK = BaseClass::NEXT_CONDITION, - COND_FOUND_WAIT_POINT, - COND_FOLLOW_DELAY_EXPIRED, - COND_FOLLOW_TARGET_VISIBLE, - COND_FOLLOW_TARGET_NOT_VISIBLE, - COND_FOLLOW_WAIT_POINT_INVALID, - COND_FOLLOW_PLAYER_IS_LIT, - COND_FOLLOW_PLAYER_IS_NOT_LIT, - NEXT_CONDITION, - }; - - DEFINE_CUSTOM_SCHEDULE_PROVIDER; - -protected: - - //---------------------------- - - EHANDLE m_hFollowTarget; - AI_FollowNavInfo_t m_FollowNavGoal; - float m_flTimeUpdatedFollowPosition; - bool m_bFirstFacing; - float m_flTimeFollowTargetVisible; - - CAI_MoveMonitor m_TargetMonitor; - bool m_bTargetUnreachable; - bool m_bFollowNavFailed; // Set when pathfinding fails to limit impact of m_FollowDelay on ShouldFollow - - int m_nFailedFollowAttempts; - float m_flTimeFailFollowStarted; - Vector m_vFollowMoveAnchor; - - bool m_bMovingToCover; - float m_flOriginalEnemyDiscardTime; - float m_SavedDistTooFar; - - CRandStopwatch m_FollowDelay; - CSimpleSimTimer m_RepathOnFollowTimer; - - //--------------------------------- - - Activity m_CurrentFollowActivity; - - //--------------------------------- - - CRandSimTimer m_TimeBlockUseWaitPoint; - CSimTimer m_TimeCheckForWaitPoint; - CAI_Hint * m_pInterruptWaitPoint; - - //--------------------------------- - - CRandSimTimer m_TimeBeforeSpreadFacing; - CRandSimTimer m_TimeNextSpreadFacing; - - //--------------------------------- - - AI_FollowManagerInfoHandle_t m_hFollowManagerInfo; - AI_FollowParams_t m_params; - - //--------------------------------- - - CHandle m_hFollowGoalEnt; - - //--------------------------------- - - DECLARE_DATADESC(); -}; - -//------------------------------------- - -inline const AI_FollowNavInfo_t &CAI_FollowBehavior::GetFollowGoalInfo() -{ - return m_FollowNavGoal; -} - -//------------------------------------- - -inline const int CAI_FollowBehavior::GetGoalFlags() -{ - return m_FollowNavGoal.flags; -} - -//------------------------------------- - -inline const Vector &CAI_FollowBehavior::GetGoalPosition() -{ - return m_FollowNavGoal.position; -} - -//------------------------------------- - -inline float CAI_FollowBehavior::GetGoalTolerance() -{ - return m_FollowNavGoal.tolerance; -} - -//------------------------------------- - -inline float CAI_FollowBehavior::GetGoalRange() -{ - return m_FollowNavGoal.range; -} - -//------------------------------------- - -inline float CAI_FollowBehavior::GetGoalZRange() -{ - return m_FollowNavGoal.Zrange; -} - -//----------------------------------------------------------------------------- - -#endif // AI_BEHAVIOR_FOLLOW_H diff --git a/game/server/ai_behavior_lead.cpp b/game/server/ai_behavior_lead.cpp deleted file mode 100644 index 5ba1b8dca..000000000 --- a/game/server/ai_behavior_lead.cpp +++ /dev/null @@ -1,1693 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" - -#include "ai_behavior_lead.h" - -#include "ai_goalentity.h" -#include "ai_navigator.h" -#include "ai_speech.h" -#include "ai_senses.h" -#include "ai_playerally.h" -#include "ai_route.h" -#include "ai_pathfinder.h" -#include "sceneentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// Minimum time between leader nags -#define LEAD_NAG_TIME 3.0 - -#define LEAD_MIN_RETRIEVEDIST_OFFSET 24 - -//----------------------------------------------------------------------------- -// class CAI_LeadBehavior -// -// Purpose: -// -//----------------------------------------------------------------------------- - -BEGIN_SIMPLE_DATADESC( AI_LeadArgs_t ) - // Only the flags needs saving - DEFINE_FIELD( flags, FIELD_INTEGER ), - - //DEFINE_FIELD( pszGoal, FIELD_STRING ), - //DEFINE_FIELD( pszWaitPoint, FIELD_STRING ), - //DEFINE_FIELD( flWaitDistance, FIELD_FLOAT ), - //DEFINE_FIELD( flLeadDistance, FIELD_FLOAT ), - //DEFINE_FIELD( flRetrieveDistance, FIELD_FLOAT ), - //DEFINE_FIELD( flSuccessDistance, FIELD_FLOAT ), - //DEFINE_FIELD( bRun, FIELD_BOOLEAN ), - //DEFINE_FIELD( bDontSpeakStart, FIELD_BOOLEAN ), - //DEFINE_FIELD( bGagLeader, FIELD_BOOLEAN ), - - DEFINE_FIELD( iRetrievePlayer, FIELD_INTEGER ), - DEFINE_FIELD( iRetrieveWaitForSpeak, FIELD_INTEGER ), - DEFINE_FIELD( iComingBackWaitForSpeak, FIELD_INTEGER ), - DEFINE_FIELD( bStopScenesWhenPlayerLost, FIELD_BOOLEAN ), - DEFINE_FIELD( bLeadDuringCombat, FIELD_BOOLEAN ), - -END_DATADESC(); - - -BEGIN_DATADESC( CAI_LeadBehavior ) - DEFINE_EMBEDDED( m_args ), - // m_pSink (reconnected on load) - DEFINE_FIELD( m_hSinkImplementor, FIELD_EHANDLE ), - DEFINE_FIELD( m_goal, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_goalyaw, FIELD_FLOAT ), - DEFINE_FIELD( m_waitpoint, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_waitdistance, FIELD_FLOAT ), - DEFINE_FIELD( m_leaddistance, FIELD_FLOAT ), - DEFINE_FIELD( m_retrievedistance, FIELD_FLOAT ), - DEFINE_FIELD( m_successdistance, FIELD_FLOAT ), - DEFINE_FIELD( m_weaponname, FIELD_STRING ), - DEFINE_FIELD( m_run, FIELD_BOOLEAN ), - DEFINE_FIELD( m_gagleader, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hasspokenstart, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hasspokenarrival, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hasPausedScenes, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flSpeakNextNagTime, FIELD_TIME ), - DEFINE_FIELD( m_flWeaponSafetyTimeOut, FIELD_TIME ), - DEFINE_FIELD( m_flNextLeadIdle, FIELD_TIME ), - DEFINE_FIELD( m_bInitialAheadTest, FIELD_BOOLEAN ), - DEFINE_EMBEDDED( m_MoveMonitor ), - DEFINE_EMBEDDED( m_LostTimer ), - DEFINE_EMBEDDED( m_LostLOSTimer ), -END_DATADESC(); - -//----------------------------------------------------------------------------- - - -void CAI_LeadBehavior::OnRestore() -{ - CBaseEntity *pSinkImplementor = m_hSinkImplementor; - if ( pSinkImplementor ) - { - m_pSink = dynamic_cast(pSinkImplementor); - if ( !m_pSink ) - { - DevMsg( "Failed to reconnect to CAI_LeadBehaviorHandler\n" ); - m_hSinkImplementor = NULL; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draw any text overlays -// Input : Previous text offset from the top -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CAI_LeadBehavior::DrawDebugTextOverlays( int text_offset ) -{ - char tempstr[ 512 ]; - int offset; - - offset = BaseClass::DrawDebugTextOverlays( text_offset ); - if ( GetOuter()->m_debugOverlays & OVERLAY_TEXT_BIT ) - { - if ( HasGoal() ) - { - Q_snprintf( tempstr, sizeof(tempstr), "Goal: %s %s", m_args.pszGoal, VecToString( m_goal ) ); - GetOuter()->EntityText( offset, tempstr, 0 ); - offset++; - } - else - { - Q_snprintf( tempstr, sizeof(tempstr), "Goal: None" ); - GetOuter()->EntityText( offset, tempstr, 0 ); - offset++; - } - } - - return offset; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CAI_LeadBehavior::IsNavigationUrgent( void ) -{ -#if defined( HL2_DLL ) - if( HasGoal() && !hl2_episodic.GetBool() ) - { - return (GetOuter()->Classify() == CLASS_PLAYER_ALLY_VITAL); - } -#endif - return BaseClass::IsNavigationUrgent(); -} - -//------------------------------------- - -void CAI_LeadBehavior::LeadPlayer( const AI_LeadArgs_t &leadArgs, CAI_LeadBehaviorHandler *pSink ) -{ -#ifndef CSTRIKE_DLL - CAI_PlayerAlly *pOuter = dynamic_cast(GetOuter()); - if ( pOuter && AI_IsSinglePlayer() ) - { - pOuter->SetSpeechTarget( UTIL_GetLocalPlayer() ); - } -#endif - - if( SetGoal( leadArgs ) ) - { - SetCondition( COND_PROVOKED ); - Connect( pSink ); - NotifyChangeBehaviorStatus(); - } - else - { - DevMsg( "*** Warning! LeadPlayer() has a NULL Goal Ent\n" ); - } -} - -//------------------------------------- - -void CAI_LeadBehavior::StopLeading( void ) -{ - ClearGoal(); - m_pSink = NULL; - NotifyChangeBehaviorStatus(); -} - -//------------------------------------- - -bool CAI_LeadBehavior::CanSelectSchedule() -{ - if ( !AI_GetSinglePlayer() || AI_GetSinglePlayer()->IsDead() ) - return false; - - bool fAttacked = ( HasCondition( COND_LIGHT_DAMAGE ) || HasCondition( COND_HEAVY_DAMAGE ) ); - bool fNonCombat = ( GetNpcState() == NPC_STATE_IDLE || GetNpcState() == NPC_STATE_ALERT ); - - return ( !fAttacked && (fNonCombat || m_args.bLeadDuringCombat) && HasGoal() ); -} - -//------------------------------------- - -void CAI_LeadBehavior::BeginScheduleSelection() -{ - SetTarget( AI_GetSinglePlayer() ); - CAI_Expresser *pExpresser = GetOuter()->GetExpresser(); - if ( pExpresser ) - pExpresser->ClearSpokeConcept( TLK_LEAD_ARRIVAL ); -} - -//------------------------------------- - -bool CAI_LeadBehavior::SetGoal( const AI_LeadArgs_t &args ) -{ - CBaseEntity *pGoalEnt; - pGoalEnt = gEntList.FindEntityByName( NULL, args.pszGoal ); - - if ( !pGoalEnt ) - return false; - - m_args = args; // @Q (toml 08-13-02): need to copy string? - m_goal = pGoalEnt->GetLocalOrigin(); - m_goalyaw = (args.flags & AILF_USE_GOAL_FACING) ? pGoalEnt->GetLocalAngles().y : -1; - m_waitpoint = vec3_origin; - m_waitdistance = args.flWaitDistance; - m_leaddistance = args.flLeadDistance ? args.flLeadDistance : 64; - m_retrievedistance = args.flRetrieveDistance ? args.flRetrieveDistance : (m_leaddistance + LEAD_MIN_RETRIEVEDIST_OFFSET); - m_successdistance = args.flSuccessDistance ? args.flSuccessDistance : 0; - m_run = args.bRun; - m_gagleader = args.bGagLeader; - m_hasspokenstart = args.bDontSpeakStart; - m_hasspokenarrival = false; - m_hasPausedScenes = false; - m_flSpeakNextNagTime = 0; - m_flWeaponSafetyTimeOut = 0; - m_flNextLeadIdle = gpGlobals->curtime + 10; - m_bInitialAheadTest = true; - - if ( args.pszWaitPoint && args.pszWaitPoint[0] ) - { - CBaseEntity *pWaitPoint = gEntList.FindEntityByName( NULL, args.pszWaitPoint ); - if ( pWaitPoint ) - { - m_waitpoint = pWaitPoint->GetLocalOrigin(); - } - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_LeadBehavior::GetClosestPointOnRoute( const Vector &targetPos, Vector *pVecClosestPoint ) -{ - AI_Waypoint_t *waypoint = GetOuter()->GetNavigator()->GetPath()->GetCurWaypoint(); - AI_Waypoint_t *builtwaypoints = NULL; - if ( !waypoint ) - { - // We arrive here twice when lead behaviour starts: - // - When the lead behaviour is first enabled. We have no schedule. We want to know if the player is ahead of us. - // - A frame later when we've chosen to lead the player, but we still haven't built our route. We know that the - // the player isn't lagging, so it's safe to go ahead and simply say he's ahead of us. This avoids building - // the temp route twice. - if ( IsCurSchedule( SCHED_LEAD_PLAYER, false ) ) - return true; - - // Build a temp route to the gold and use that - builtwaypoints = GetOuter()->GetPathfinder()->BuildRoute( GetOuter()->GetAbsOrigin(), m_goal, NULL, GetOuter()->GetDefaultNavGoalTolerance(), GetOuter()->GetNavType(), true ); - if ( !builtwaypoints ) - return false; - - GetOuter()->GetPathfinder()->UnlockRouteNodes( builtwaypoints ); - waypoint = builtwaypoints; - } - - // Find the nearest node to the target (going forward) - float flNearestDist2D = 999999999; - float flNearestDist = 999999999; - float flPathDist, flPathDist2D; - - Vector vecNearestPoint = Vector(0.0f, 0.0f, 0.0f); - Vector vecPrevPos = GetOuter()->GetAbsOrigin(); - for ( ; (waypoint != NULL) ; waypoint = waypoint->GetNext() ) - { - // Find the closest point on the line segment on the path - Vector vecClosest; - CalcClosestPointOnLineSegment( targetPos, vecPrevPos, waypoint->GetPos(), vecClosest ); - /* - if ( builtwaypoints ) - { - NDebugOverlay::Line( vecPrevPos, waypoint->GetPos(), 0,0,255,true, 10.0 ); - } - */ - vecPrevPos = waypoint->GetPos(); - - // Find the distance between this test point and our goal point - flPathDist2D = vecClosest.AsVector2D().DistToSqr( targetPos.AsVector2D() ); - if ( flPathDist2D > flNearestDist2D ) - continue; - - flPathDist = vecClosest.z - targetPos.z; - flPathDist *= flPathDist; - flPathDist += flPathDist2D; - if (( flPathDist2D == flNearestDist2D ) && ( flPathDist >= flNearestDist )) - continue; - - flNearestDist2D = flPathDist2D; - flNearestDist = flPathDist; - vecNearestPoint = vecClosest; - } - - if ( builtwaypoints ) - { - //NDebugOverlay::Line( vecNearestPoint, targetPos, 0,255,0,true, 10.0 ); - DeleteAll( builtwaypoints ); - } - - *pVecClosestPoint = vecNearestPoint; - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if the player is further ahead on the lead route than I am -//----------------------------------------------------------------------------- -bool CAI_LeadBehavior::PlayerIsAheadOfMe( bool bForce ) -{ - // Find the nearest point on our route to the player, and see if that's further - // ahead of us than our nearest point. - - // If we're not leading, our route doesn't lead to the goal, so we can't use it. - // If we just started leading, go ahead and test, and we'll build a temp route. - if ( !m_bInitialAheadTest && !IsCurSchedule( SCHED_LEAD_PLAYER, false ) && !bForce ) - return false; - - m_bInitialAheadTest = false; - - Vector vecClosestPoint; - if ( GetClosestPointOnRoute( AI_GetSinglePlayer()->GetAbsOrigin(), &vecClosestPoint ) ) - { - // If the closest point is not right next to me, then - // the player is somewhere ahead of me on the route. - if ( (vecClosestPoint - GetOuter()->GetAbsOrigin()).LengthSqr() > (32*32) ) - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_LeadBehavior::GatherConditions( void ) -{ - BaseClass::GatherConditions(); - - if ( HasGoal() ) - { - // Fix for bad transition case (to investigate) - if ( ( WorldSpaceCenter() - m_goal ).LengthSqr() > (64*64) && IsCurSchedule( SCHED_LEAD_AWAIT_SUCCESS, false) ) - { - GetOuter()->ClearSchedule( "Lead behavior - bad transition?" ); - } - - // We have to collect data about the person we're leading around. - CBaseEntity *pFollower = AI_GetSinglePlayer(); - - if( pFollower ) - { - ClearCondition( COND_LEAD_FOLLOWER_VERY_CLOSE ); - ClearCondition( COND_LEAD_FOLLOWER_MOVING_TOWARDS_ME ); - - // Check distance to the follower - float flFollowerDist = ( WorldSpaceCenter() - pFollower->WorldSpaceCenter() ).Length(); - bool bLagging = flFollowerDist > (m_leaddistance*4); - if ( bLagging ) - { - if ( PlayerIsAheadOfMe() ) - { - bLagging = false; - } - } - - // Player heading towards me? - // Only factor this in if you're not too far from them - if ( flFollowerDist < (m_leaddistance*4) ) - { - Vector vecVelocity = pFollower->GetSmoothedVelocity(); - if ( VectorNormalize(vecVelocity) > 50 ) - { - Vector vecToPlayer = (GetAbsOrigin() - pFollower->GetAbsOrigin()); - VectorNormalize( vecToPlayer ); - if ( DotProduct( vecVelocity, vecToPlayer ) > 0.5 ) - { - SetCondition( COND_LEAD_FOLLOWER_MOVING_TOWARDS_ME ); - bLagging = false; - } - } - } - - // If he's outside our lag range, consider him lagging - if ( bLagging ) - { - SetCondition( COND_LEAD_FOLLOWER_LAGGING ); - ClearCondition( COND_LEAD_FOLLOWER_NOT_LAGGING ); - } - else - { - ClearCondition( COND_LEAD_FOLLOWER_LAGGING ); - SetCondition( COND_LEAD_FOLLOWER_NOT_LAGGING ); - - // If he's really close, note that - if ( flFollowerDist < m_leaddistance ) - { - SetCondition( COND_LEAD_FOLLOWER_VERY_CLOSE ); - } - } - - // To be considered not lagging, the follower must be visible, and within the lead distance - if ( GetOuter()->FVisible( pFollower ) && GetOuter()->GetSenses()->ShouldSeeEntity( pFollower ) ) - { - SetCondition( COND_LEAD_HAVE_FOLLOWER_LOS ); - m_LostLOSTimer.Stop(); - } - else - { - ClearCondition( COND_LEAD_HAVE_FOLLOWER_LOS ); - - // We don't have a LOS. But if we did have LOS, don't clear it until the timer is up. - if ( m_LostLOSTimer.IsRunning() ) - { - if ( m_LostLOSTimer.Expired() ) - { - SetCondition( COND_LEAD_FOLLOWER_LAGGING ); - ClearCondition( COND_LEAD_FOLLOWER_NOT_LAGGING ); - } - } - else - { - m_LostLOSTimer.Start(); - } - } - - // Now we want to see if the follower is lost. Being lost means being (far away || out of LOS ) - // && some time has passed. Also, lagging players are considered lost if the NPC's never delivered - // the start speech, because it means the NPC should run to the player to start the lead. - if( HasCondition( COND_LEAD_FOLLOWER_LAGGING ) ) - { - if ( !m_hasspokenstart ) - { - SetCondition( COND_LEAD_FOLLOWER_LOST ); - } - else - { - if ( m_args.bStopScenesWhenPlayerLost ) - { - // Try and stop me speaking my monolog, if I am - if ( !m_hasPausedScenes && IsRunningScriptedScene( GetOuter() ) ) - { - //Msg("Stopping scenes.\n"); - PauseActorsScriptedScenes( GetOuter(), false ); - m_hasPausedScenes = true; - } - } - - if( m_LostTimer.IsRunning() ) - { - if( m_LostTimer.Expired() ) - { - SetCondition( COND_LEAD_FOLLOWER_LOST ); - } - } - else - { - m_LostTimer.Start(); - } - } - } - else - { - // If I was speaking a monolog, resume it - if ( m_args.bStopScenesWhenPlayerLost && m_hasPausedScenes ) - { - if ( IsRunningScriptedScene( GetOuter() ) ) - { - //Msg("Resuming scenes.\n"); - ResumeActorsScriptedScenes( GetOuter(), false ); - } - - m_hasPausedScenes = false; - } - - m_LostTimer.Stop(); - ClearCondition( COND_LEAD_FOLLOWER_LOST ); - } - - // Evaluate for success - // Success right now means being stationary, close to the goal, and having the player close by - if ( !( m_args.flags & AILF_NO_DEF_SUCCESS ) ) - { - ClearCondition( COND_LEAD_SUCCESS ); - - // Check Z first, and only check 2d if we're within that - bool bWithinZ = fabs(GetLocalOrigin().z - m_goal.z) < 64; - if ( bWithinZ && (GetLocalOrigin() - m_goal).Length2D() <= 64 ) - { - if ( HasCondition( COND_LEAD_FOLLOWER_VERY_CLOSE ) ) - { - SetCondition( COND_LEAD_SUCCESS ); - } - else if ( m_successdistance ) - { - float flDistSqr = (pFollower->GetAbsOrigin() - GetLocalOrigin()).Length2DSqr(); - if ( flDistSqr < (m_successdistance*m_successdistance) ) - { - SetCondition( COND_LEAD_SUCCESS ); - } - } - } - } - if ( m_MoveMonitor.IsMarkSet() && m_MoveMonitor.TargetMoved( pFollower ) ) - SetCondition( COND_LEAD_FOLLOWER_MOVED_FROM_MARK ); - else - ClearCondition( COND_LEAD_FOLLOWER_MOVED_FROM_MARK ); - } - } - - if( m_args.bLeadDuringCombat ) - { - ClearCondition( COND_LIGHT_DAMAGE ); - ClearCondition( COND_HEAVY_DAMAGE ); - } -} - -//------------------------------------- - -int CAI_LeadBehavior::SelectSchedule() -{ - if ( HasGoal() ) - { - if( HasCondition(COND_LEAD_SUCCESS) ) - { - return SCHED_LEAD_SUCCEED; - } - - // Player's here, but does he have the weapon we want him to have? - if ( m_weaponname != NULL_STRING ) - { - CBasePlayer *pFollower = AI_GetSinglePlayer(); - if ( pFollower && !pFollower->Weapon_OwnsThisType( STRING(m_weaponname) ) ) - { - // If the safety timeout has run out, just give the player the weapon - if ( !m_flWeaponSafetyTimeOut || (m_flWeaponSafetyTimeOut > gpGlobals->curtime) ) - return SCHED_LEAD_PLAYERNEEDSWEAPON; - - string_t iszItem = AllocPooledString( "weapon_bugbait" ); - pFollower->GiveNamedItem( STRING(iszItem) ); - } - } - - // If we have a waitpoint, we want to wait at it for the player. - if( HasWaitPoint() && !PlayerIsAheadOfMe( true ) ) - { - bool bKeepWaiting = true; - - // If we have no wait distance, trigger as soon as the player comes in view - if ( !m_waitdistance ) - { - if ( HasCondition( COND_SEE_PLAYER ) ) - { - // We've spotted the player, so stop waiting - bKeepWaiting = false; - } - } - else - { - // We have to collect data about the person we're leading around. - CBaseEntity *pFollower = AI_GetSinglePlayer(); - if( pFollower ) - { - float flFollowerDist = ( WorldSpaceCenter() - pFollower->WorldSpaceCenter() ).Length(); - if ( flFollowerDist < m_waitdistance ) - { - bKeepWaiting = false; - } - } - } - - // Player still not here? - if ( bKeepWaiting ) - return SCHED_LEAD_WAITFORPLAYER; - - // We're finished waiting - m_waitpoint = vec3_origin; - Speak( TLK_LEAD_WAITOVER ); - - // Don't speak the start line, because we've said - m_hasspokenstart = true; - return SCHED_WAIT_FOR_SPEAK_FINISH; - } - - // If we haven't spoken our start speech, do that first - if ( !m_hasspokenstart ) - { - if ( HasCondition(COND_LEAD_HAVE_FOLLOWER_LOS) && HasCondition(COND_LEAD_FOLLOWER_VERY_CLOSE) ) - return SCHED_LEAD_SPEAK_START; - - // We haven't spoken to him, and we still need to. Go get him. - return SCHED_LEAD_RETRIEVE; - } - - if( HasCondition( COND_LEAD_FOLLOWER_LOST ) ) - { - if( m_args.iRetrievePlayer ) - { - // If not, we want to go get the player. - DevMsg( GetOuter(), "Follower lost. Spoke COMING_BACK.\n"); - - Speak( TLK_LEAD_COMINGBACK ); - m_MoveMonitor.ClearMark(); - - // If we spoke something, wait for it to finish - if ( m_args.iComingBackWaitForSpeak && IsSpeaking() ) - return SCHED_LEAD_SPEAK_THEN_RETRIEVE_PLAYER; - - return SCHED_LEAD_RETRIEVE; - } - else - { - // Just stay right here and wait. - return SCHED_LEAD_WAITFORPLAYERIDLE; - } - } - - if( HasCondition( COND_LEAD_FOLLOWER_LAGGING ) ) - { - DevMsg( GetOuter(), "Follower lagging. Spoke CATCHUP.\n"); - - Speak( TLK_LEAD_CATCHUP ); - return SCHED_LEAD_PAUSE; - } - else - { - // If we're at the goal, wait for the player to get here - if ( ( WorldSpaceCenter() - m_goal ).LengthSqr() < (64*64) ) - return SCHED_LEAD_AWAIT_SUCCESS; - - // If we were retrieving the player, speak the resume - if ( IsCurSchedule( SCHED_LEAD_RETRIEVE, false ) || IsCurSchedule( SCHED_LEAD_WAITFORPLAYERIDLE, false ) ) - { - Speak( TLK_LEAD_RETRIEVE ); - - // If we spoke something, wait for it to finish, if the mapmakers wants us to - if ( m_args.iRetrieveWaitForSpeak && IsSpeaking() ) - return SCHED_LEAD_SPEAK_THEN_LEAD_PLAYER; - } - - DevMsg( GetOuter(), "Leading Follower.\n"); - return SCHED_LEAD_PLAYER; - } - } - return BaseClass::SelectSchedule(); -} - -//------------------------------------- - -int CAI_LeadBehavior::TranslateSchedule( int scheduleType ) -{ - bool bInCombat = (m_args.bLeadDuringCombat && GetOuter()->GetState() == NPC_STATE_COMBAT); - switch( scheduleType ) - { - case SCHED_LEAD_PAUSE: - if( bInCombat ) - return SCHED_LEAD_PAUSE_COMBAT; - break; - } - return BaseClass::TranslateSchedule( scheduleType ); -} - -//------------------------------------- - -bool CAI_LeadBehavior::IsCurTaskContinuousMove() -{ - const Task_t *pCurTask = GetCurTask(); - if ( pCurTask && pCurTask->iTask == TASK_LEAD_MOVE_TO_RANGE ) - return true; - return BaseClass::IsCurTaskContinuousMove(); -} - -//------------------------------------- - -void CAI_LeadBehavior::StartTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_LEAD_FACE_GOAL: - { - if ( m_goalyaw != -1 ) - { - GetMotor()->SetIdealYaw( m_goalyaw ); - } - - TaskComplete(); - break; - } - - case TASK_LEAD_SUCCEED: - { - Speak( TLK_LEAD_SUCCESS ); - NotifyEvent( LBE_SUCCESS ); - - break; - } - - case TASK_LEAD_ARRIVE: - { - // Only speak the first time we arrive - if ( !m_hasspokenarrival ) - { - Speak( TLK_LEAD_ARRIVAL ); - NotifyEvent( LBE_ARRIVAL ); - - m_hasspokenarrival = true; - } - else - { - TaskComplete(); - } - - break; - } - - case TASK_STOP_LEADING: - { - ClearGoal(); - TaskComplete(); - break; - } - - case TASK_GET_PATH_TO_LEAD_GOAL: - { - if ( GetNavigator()->SetGoal( m_goal ) ) - { - TaskComplete(); - } - else - { - TaskFail("NO PATH"); - } - break; - } - - case TASK_LEAD_GET_PATH_TO_WAITPOINT: - { - if ( GetNavigator()->SetGoal( m_waitpoint ) ) - { - TaskComplete(); - } - else - { - TaskFail("NO PATH"); - } - break; - } - - case TASK_LEAD_WALK_PATH: - { - // If we're leading, and we're supposed to run, run instead of walking - if ( m_run && - ( IsCurSchedule( SCHED_LEAD_WAITFORPLAYER, false ) || IsCurSchedule( SCHED_LEAD_PLAYER, false ) || IsCurSchedule( SCHED_LEAD_SPEAK_THEN_LEAD_PLAYER, false )|| IsCurSchedule( SCHED_LEAD_RETRIEVE, false ) ) ) - { - ChainStartTask( TASK_RUN_PATH ); - } - else - { - ChainStartTask( TASK_WALK_PATH ); - } - break; - } - - case TASK_LEAD_WAVE_TO_PLAYER: - { - // Wave to the player if we can see him. Otherwise, just idle. - if ( HasCondition( COND_SEE_PLAYER ) ) - { - Speak( TLK_LEAD_ATTRACTPLAYER ); - if ( HaveSequenceForActivity(ACT_SIGNAL1) ) - { - SetActivity(ACT_SIGNAL1); - } - } - else - { - SetActivity(ACT_IDLE); - } - - TaskComplete(); - break; - } - - case TASK_LEAD_PLAYER_NEEDS_WEAPON: - { - float flAvailableTime = GetOuter()->GetExpresser()->GetSemaphoreAvailableTime( GetOuter() ); - - // if someone else is talking, don't speak - if ( flAvailableTime <= gpGlobals->curtime ) - { - Speak( TLK_LEAD_MISSINGWEAPON ); - } - - SetActivity(ACT_IDLE); - TaskComplete(); - break; - } - - case TASK_LEAD_SPEAK_START: - { - m_hasspokenstart = true; - - Speak( TLK_LEAD_START ); - SetActivity(ACT_IDLE); - TaskComplete(); - break; - } - - case TASK_LEAD_MOVE_TO_RANGE: - { - // If we haven't spoken our start speech, move closer - if ( !m_hasspokenstart) - { - ChainStartTask( TASK_MOVE_TO_GOAL_RANGE, m_leaddistance - 24 ); - } - else - { - ChainStartTask( TASK_MOVE_TO_GOAL_RANGE, m_retrievedistance ); - } - break; - } - - case TASK_LEAD_RETRIEVE_WAIT: - { - m_MoveMonitor.SetMark( AI_GetSinglePlayer(), 24 ); - ChainStartTask( TASK_WAIT_INDEFINITE ); - break; - } - - case TASK_STOP_MOVING: - { - BaseClass::StartTask( pTask); - - if ( IsCurSchedule( SCHED_LEAD_PAUSE, false ) && pTask->flTaskData == 1 ) - { - GetNavigator()->SetArrivalDirection( GetTarget() ); - } - break; - } - - case TASK_WAIT_FOR_SPEAK_FINISH: - { - BaseClass::StartTask( pTask); - - if( GetOuter()->GetState() == NPC_STATE_COMBAT ) - { - // Don't stand around jabbering in combat. - TaskComplete(); - } - - // If we're not supposed to wait for the player, don't wait for speech to finish. - // Instead, just wait a wee tad, and then start moving. NPC will speak on the go. - if ( TaskIsRunning() && !m_args.iRetrievePlayer ) - { - if ( gpGlobals->curtime - GetOuter()->GetTimeTaskStarted() > 0.3 ) - { - TaskComplete(); - } - } - break; - } - - default: - BaseClass::StartTask( pTask); - } -} - -//------------------------------------- - -void CAI_LeadBehavior::RunTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_LEAD_SUCCEED: - { - if ( !IsSpeaking() ) - { - TaskComplete(); - NotifyEvent( LBE_DONE ); - } - break; - } - case TASK_LEAD_ARRIVE: - { - if ( !IsSpeaking() ) - { - TaskComplete(); - NotifyEvent( LBE_ARRIVAL_DONE ); - } - break; - } - - case TASK_LEAD_MOVE_TO_RANGE: - { - // If we haven't spoken our start speech, move closer - if ( !m_hasspokenstart) - { - ChainRunTask( TASK_MOVE_TO_GOAL_RANGE, m_leaddistance - 24 ); - } - else - { - ChainRunTask( TASK_MOVE_TO_GOAL_RANGE, m_retrievedistance ); - - if ( !TaskIsComplete() ) - { - // Transition to a walk when we get near the player - // Check Z first, and only check 2d if we're within that - Vector vecGoalPos = GetNavigator()->GetGoalPos(); - float distance = fabs(vecGoalPos.z - GetLocalOrigin().z); - bool bWithinZ = false; - if ( distance < m_retrievedistance ) - { - distance = ( vecGoalPos - GetLocalOrigin() ).Length2D(); - bWithinZ = true; - } - - if ( distance > m_retrievedistance ) - { - Activity followActivity = ACT_WALK; - if ( GetOuter()->GetState() == NPC_STATE_COMBAT || (!bWithinZ || distance < (m_retrievedistance*4)) && GetOuter()->GetState() != NPC_STATE_COMBAT ) - { - followActivity = ACT_RUN; - } - - // Don't confuse move and shoot by resetting the activity every think - Activity curActivity = GetNavigator()->GetMovementActivity(); - switch( curActivity ) - { - case ACT_WALK_AIM: curActivity = ACT_WALK; break; - case ACT_RUN_AIM: curActivity = ACT_RUN; break; - default: break; - } - - if ( curActivity != followActivity ) - { - GetNavigator()->SetMovementActivity(followActivity); - } - GetNavigator()->SetArrivalDirection( GetOuter()->GetTarget() ); - } - } - } - break; - } - - case TASK_LEAD_RETRIEVE_WAIT: - { - ChainRunTask( TASK_WAIT_INDEFINITE ); - break; - } - - case TASK_LEAD_WALK_PATH: - { - // If we're leading, and we're supposed to run, run instead of walking - if ( m_run && - ( IsCurSchedule( SCHED_LEAD_WAITFORPLAYER, false ) || IsCurSchedule( SCHED_LEAD_PLAYER, false ) || IsCurSchedule( SCHED_LEAD_SPEAK_THEN_LEAD_PLAYER, false )|| IsCurSchedule( SCHED_LEAD_RETRIEVE, false ) ) ) - { - ChainRunTask( TASK_RUN_PATH ); - } - else - { - ChainRunTask( TASK_WALK_PATH ); - } - - // While we're walking - if ( TaskIsRunning() && IsCurSchedule( SCHED_LEAD_PLAYER, false ) ) - { - // If we're not speaking, and we haven't tried for a while, try to speak lead idle - if ( m_flNextLeadIdle < gpGlobals->curtime && !IsSpeaking() ) - { - m_flNextLeadIdle = gpGlobals->curtime + RandomFloat( 10,15 ); - - if ( !m_args.iRetrievePlayer && HasCondition( COND_LEAD_FOLLOWER_LOST ) && HasCondition(COND_SEE_PLAYER) ) - { - Speak( TLK_LEAD_COMINGBACK ); - } - else - { - Speak( TLK_LEAD_IDLE ); - } - } - } - - break; - } - - default: - BaseClass::RunTask( pTask); - } -} - -//------------------------------------- - -bool CAI_LeadBehavior::Speak( AIConcept_t concept ) -{ - CAI_Expresser *pExpresser = GetOuter()->GetExpresser(); - if ( !pExpresser ) - return false; - - // If the leader is gagged, don't speak any lead speech - if ( m_gagleader ) - return false; - - // If we haven't said the start speech, don't nag - bool bNag = ( FStrEq(concept,TLK_LEAD_COMINGBACK) || FStrEq(concept, TLK_LEAD_CATCHUP) || FStrEq(concept, TLK_LEAD_RETRIEVE) ); - if ( !m_hasspokenstart && bNag ) - return false; - - if ( hl2_episodic.GetBool() ) - { - // If we're a player ally, only speak the concept if we're allowed to. - // This allows the response rules to control it better (i.e. handles respeakdelay) - // We ignore nag timers for this, because the response rules will control refire rates. - CAI_PlayerAlly *pAlly = dynamic_cast(GetOuter()); - if ( pAlly ) - return pAlly->SpeakIfAllowed( concept, GetConceptModifiers( concept ) ); - } - - // Don't spam Nags - if ( bNag ) - { - if ( m_flSpeakNextNagTime > gpGlobals->curtime ) - { - DevMsg( GetOuter(), "Leader didn't speak due to Nag timer.\n"); - return false; - } - } - - if ( pExpresser->Speak( concept, GetConceptModifiers( concept ) ) ) - { - m_flSpeakNextNagTime = gpGlobals->curtime + LEAD_NAG_TIME; - return true; - } - - return false; -} - -//------------------------------------- - -bool CAI_LeadBehavior::IsSpeaking() -{ - CAI_Expresser *pExpresser = GetOuter()->GetExpresser(); - if ( !pExpresser ) - return false; - - return pExpresser->IsSpeaking(); -} - -//------------------------------------- - -bool CAI_LeadBehavior::Connect( CAI_LeadBehaviorHandler *pSink ) -{ - m_pSink = pSink; - m_hSinkImplementor = dynamic_cast(pSink); - - if ( m_hSinkImplementor == NULL ) - DevMsg( 2, "Note: CAI_LeadBehaviorHandler connected to a sink that isn't an entity. Manual fixup on load will be necessary\n" ); - - return true; -} - -//------------------------------------- - -bool CAI_LeadBehavior::Disconnect( CAI_LeadBehaviorHandler *pSink ) -{ - Assert( pSink == m_pSink ); - m_pSink = NULL; - m_hSinkImplementor = NULL; - return true; -} - -//------------------------------------- - -AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( CAI_LeadBehavior ) - - DECLARE_CONDITION( COND_LEAD_FOLLOWER_LOST ) - DECLARE_CONDITION( COND_LEAD_FOLLOWER_LAGGING ) - DECLARE_CONDITION( COND_LEAD_FOLLOWER_NOT_LAGGING ) - DECLARE_CONDITION( COND_LEAD_FOLLOWER_VERY_CLOSE ) - DECLARE_CONDITION( COND_LEAD_SUCCESS ) - DECLARE_CONDITION( COND_LEAD_HAVE_FOLLOWER_LOS ) - DECLARE_CONDITION( COND_LEAD_FOLLOWER_MOVED_FROM_MARK ) - DECLARE_CONDITION( COND_LEAD_FOLLOWER_MOVING_TOWARDS_ME ) - - //--------------------------------- - // - // Lead - // - DECLARE_TASK( TASK_GET_PATH_TO_LEAD_GOAL ) - DECLARE_TASK( TASK_STOP_LEADING ) - DECLARE_TASK( TASK_LEAD_ARRIVE ) - DECLARE_TASK( TASK_LEAD_SUCCEED ) - DECLARE_TASK( TASK_LEAD_FACE_GOAL ) - DECLARE_TASK( TASK_LEAD_GET_PATH_TO_WAITPOINT ) - DECLARE_TASK( TASK_LEAD_WAVE_TO_PLAYER ) - DECLARE_TASK( TASK_LEAD_PLAYER_NEEDS_WEAPON ) - DECLARE_TASK( TASK_LEAD_MOVE_TO_RANGE ) - DECLARE_TASK( TASK_LEAD_SPEAK_START ) - DECLARE_TASK( TASK_LEAD_RETRIEVE_WAIT ) - DECLARE_TASK( TASK_LEAD_WALK_PATH ) - - DEFINE_SCHEDULE - ( - SCHED_LEAD_RETRIEVE, - - " Tasks" - " TASK_GET_PATH_TO_PLAYER 0" - " TASK_LEAD_MOVE_TO_RANGE 0" - " TASK_STOP_MOVING 0" - " TASK_WAIT_FOR_SPEAK_FINISH 1" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_LEAD_RETRIEVE_WAIT" - " " - " Interrupts" - " COND_LEAD_FOLLOWER_VERY_CLOSE" - " COND_LEAD_FOLLOWER_MOVING_TOWARDS_ME" - " COND_LIGHT_DAMAGE" - " COND_NEW_ENEMY" - " COND_HEAR_DANGER" - ) - - //------------------------------------- - - DEFINE_SCHEDULE - ( - SCHED_LEAD_SPEAK_THEN_RETRIEVE_PLAYER, - - " Tasks" - " TASK_WAIT_FOR_SPEAK_FINISH 1" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_LEAD_RETRIEVE" - " " - " Interrupts" - " COND_LEAD_FOLLOWER_VERY_CLOSE" - " COND_LEAD_FOLLOWER_MOVING_TOWARDS_ME" - " COND_LIGHT_DAMAGE" - " COND_NEW_ENEMY" - " COND_HEAR_DANGER" - ) - - //------------------------------------- - - DEFINE_SCHEDULE - ( - SCHED_LEAD_RETRIEVE_WAIT, - - " Tasks" - " TASK_LEAD_RETRIEVE_WAIT 0" - " " - " Interrupts" - " COND_LEAD_FOLLOWER_LOST" - " COND_LEAD_FOLLOWER_LAGGING" - " COND_LEAD_FOLLOWER_VERY_CLOSE" - " COND_LEAD_FOLLOWER_MOVING_TOWARDS_ME" - " COND_LEAD_FOLLOWER_MOVED_FROM_MARK" - " COND_LIGHT_DAMAGE" - " COND_NEW_ENEMY" - " COND_HEAR_DANGER" - ) - - //--------------------------------- - - DEFINE_SCHEDULE - ( - SCHED_LEAD_PLAYER, - - " Tasks" - " TASK_WAIT_FOR_SPEAK_FINISH 1" - " TASK_GET_PATH_TO_LEAD_GOAL 0" - " TASK_LEAD_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - "" - " Interrupts" - " COND_LEAD_FOLLOWER_LOST" - " COND_LEAD_FOLLOWER_LAGGING" - " COND_LIGHT_DAMAGE" - " COND_NEW_ENEMY" - " COND_HEAR_DANGER" - ) - - //--------------------------------- - - DEFINE_SCHEDULE - ( - SCHED_LEAD_AWAIT_SUCCESS, - - " Tasks" - " TASK_LEAD_FACE_GOAL 0" - " TASK_FACE_IDEAL 0" - " TASK_LEAD_ARRIVE 0" - " TASK_WAIT_INDEFINITE 0" - "" - " Interrupts" - " COND_LEAD_FOLLOWER_LOST" - " COND_LEAD_FOLLOWER_LAGGING" - " COND_LEAD_SUCCESS" - " COND_LIGHT_DAMAGE" - " COND_NEW_ENEMY" - " COND_HEAR_DANGER" - ) - - //--------------------------------- - - DEFINE_SCHEDULE - ( - SCHED_LEAD_SUCCEED, - - " Tasks" - " TASK_LEAD_SUCCEED 0" - " TASK_STOP_LEADING 0" - "" - ) - - //--------------------------------- - // This is the schedule Odell uses to pause the tour momentarily - // if the player lags behind. If the player shows up in a - // couple of seconds, the tour will resume. Otherwise, Odell - // moves to retrieve. - //--------------------------------- - - DEFINE_SCHEDULE - ( - SCHED_LEAD_PAUSE, - - " Tasks" - " TASK_STOP_MOVING 1" - " TASK_FACE_TARGET 0" - " TASK_WAIT 5" - " TASK_WAIT_RANDOM 5" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_LEAD_RETRIEVE" - "" - " Interrupts" - " COND_LEAD_FOLLOWER_VERY_CLOSE" - " COND_LEAD_FOLLOWER_MOVING_TOWARDS_ME" - " COND_LEAD_FOLLOWER_NOT_LAGGING" - " COND_LEAD_FOLLOWER_LOST" - " COND_LIGHT_DAMAGE" - " COND_NEW_ENEMY" - " COND_HEAR_DANGER" - ) - - DEFINE_SCHEDULE - ( - SCHED_LEAD_PAUSE_COMBAT, - - " Tasks" - " TASK_STOP_MOVING 1" - " TASK_FACE_TARGET 0" - " TASK_WAIT 1" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_LEAD_RETRIEVE" - "" - " Interrupts" - " COND_LEAD_FOLLOWER_VERY_CLOSE" - " COND_LEAD_FOLLOWER_MOVING_TOWARDS_ME" - " COND_LEAD_FOLLOWER_NOT_LAGGING" - " COND_LEAD_FOLLOWER_LOST" - " COND_HEAR_DANGER" - ) - - //--------------------------------- - - DEFINE_SCHEDULE - ( - SCHED_LEAD_WAITFORPLAYER, - - " Tasks" - " TASK_LEAD_GET_PATH_TO_WAITPOINT 0" - " TASK_LEAD_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_WAIT 0.5" - " TASK_FACE_TARGET 0" - " TASK_LEAD_WAVE_TO_PLAYER 0" - " TASK_WAIT 5.0" - " " - " Interrupts" - " COND_LEAD_FOLLOWER_VERY_CLOSE" - " COND_LIGHT_DAMAGE" - " COND_NEW_ENEMY" - " COND_HEAR_DANGER" - ) - - //--------------------------------- - - DEFINE_SCHEDULE - ( - SCHED_LEAD_WAITFORPLAYERIDLE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_WAIT 0.5" - " TASK_FACE_TARGET 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_IDLE" - " TASK_WAIT 2" - " " - " Interrupts" - " COND_LEAD_FOLLOWER_VERY_CLOSE" - " COND_LIGHT_DAMAGE" - " COND_NEW_ENEMY" - " COND_HEAR_DANGER" - ) - - //--------------------------------- - - DEFINE_SCHEDULE - ( - SCHED_LEAD_PLAYERNEEDSWEAPON, - - " Tasks" - " TASK_FACE_PLAYER 0" - " TASK_LEAD_PLAYER_NEEDS_WEAPON 0" - " TASK_WAIT_FOR_SPEAK_FINISH 1" - " TASK_WAIT 8" - " " - " Interrupts" - ) - - //--------------------------------- - - DEFINE_SCHEDULE - ( - SCHED_LEAD_SPEAK_START, - - " Tasks" - " TASK_LEAD_SPEAK_START 0" - " TASK_WAIT_FOR_SPEAK_FINISH 1" - "" - " Interrupts" - ) - - //--------------------------------- - - DEFINE_SCHEDULE - ( - SCHED_LEAD_SPEAK_THEN_LEAD_PLAYER, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_WAIT_FOR_SPEAK_FINISH 1" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_LEAD_PLAYER" - "" - " Interrupts" - " COND_LEAD_FOLLOWER_LOST" - " COND_LEAD_FOLLOWER_LAGGING" - " COND_LIGHT_DAMAGE" - " COND_NEW_ENEMY" - " COND_HEAR_DANGER" - ) - -AI_END_CUSTOM_SCHEDULE_PROVIDER() - - -//----------------------------------------------------------------------------- -// -// Purpose: A level tool to control the lead behavior. Use is not required -// in order to use behavior. -// - -class CAI_LeadGoal : public CAI_GoalEntity, - public CAI_LeadBehaviorHandler -{ - DECLARE_CLASS( CAI_LeadGoal, CAI_GoalEntity ); -public: - CAI_LeadGoal() - : m_fArrived( false ) - { - // These fields got added after existing levels shipped, so we set - // the default values here in the constructor. - m_iRetrievePlayer = 1; - m_iRetrieveWaitForSpeak = 0; - m_iComingBackWaitForSpeak = 0; - m_bStopScenesWhenPlayerLost = false; - m_bDontSpeakStart = false; - m_bLeadDuringCombat = false; - m_bGagLeader = false; - } - - CAI_LeadBehavior *GetLeadBehavior(); - - virtual const char *GetConceptModifiers( const char *pszConcept ); - - virtual void InputActivate( inputdata_t &inputdata ); - virtual void InputDeactivate( inputdata_t &inputdata ); - - DECLARE_DATADESC(); -private: - - virtual void OnEvent( int event ); - void InputSetSuccess( inputdata_t &inputdata ); - void InputSetFailure( inputdata_t &inputdata ); - - bool m_fArrived; // @TODO (toml 08-16-02): move arrived tracking onto behavior - float m_flWaitDistance; - float m_flLeadDistance; - float m_flRetrieveDistance; - float m_flSuccessDistance; - bool m_bRun; - int m_iRetrievePlayer; - int m_iRetrieveWaitForSpeak; - int m_iComingBackWaitForSpeak; - bool m_bStopScenesWhenPlayerLost; - bool m_bDontSpeakStart; - bool m_bLeadDuringCombat; - bool m_bGagLeader; - - string_t m_iszWaitPointName; - - string_t m_iszStartConceptModifier; - string_t m_iszAttractPlayerConceptModifier; - string_t m_iszWaitOverConceptModifier; - string_t m_iszArrivalConceptModifier; - string_t m_iszPostArrivalConceptModifier; - string_t m_iszSuccessConceptModifier; - string_t m_iszFailureConceptModifier; - string_t m_iszRetrieveConceptModifier; - string_t m_iszComingBackConceptModifier; - - // Output handlers - COutputEvent m_OnArrival; - COutputEvent m_OnArrivalDone; - COutputEvent m_OnSuccess; - COutputEvent m_OnFailure; - COutputEvent m_OnDone; -}; - -//----------------------------------------------------------------------------- -// -// CAI_LeadGoal implementation -// - -LINK_ENTITY_TO_CLASS( ai_goal_lead, CAI_LeadGoal ); - -BEGIN_DATADESC( CAI_LeadGoal ) - - DEFINE_FIELD( m_fArrived, FIELD_BOOLEAN ), - - DEFINE_KEYFIELD(m_flWaitDistance, FIELD_FLOAT, "WaitDistance"), - DEFINE_KEYFIELD(m_iszWaitPointName, FIELD_STRING, "WaitPointName"), - DEFINE_KEYFIELD(m_flLeadDistance, FIELD_FLOAT, "LeadDistance"), - DEFINE_KEYFIELD(m_flRetrieveDistance, FIELD_FLOAT, "RetrieveDistance"), - DEFINE_KEYFIELD(m_flSuccessDistance, FIELD_FLOAT, "SuccessDistance"), - DEFINE_KEYFIELD(m_bRun, FIELD_BOOLEAN, "Run"), - DEFINE_KEYFIELD(m_iRetrievePlayer, FIELD_INTEGER, "Retrieve"), - DEFINE_KEYFIELD(m_iRetrieveWaitForSpeak, FIELD_INTEGER, "RetrieveWaitForSpeak"), - DEFINE_KEYFIELD(m_iComingBackWaitForSpeak, FIELD_INTEGER, "ComingBackWaitForSpeak"), - DEFINE_KEYFIELD(m_bStopScenesWhenPlayerLost, FIELD_BOOLEAN, "StopScenes"), - DEFINE_KEYFIELD(m_bDontSpeakStart, FIELD_BOOLEAN, "DontSpeakStart"), - DEFINE_KEYFIELD(m_bLeadDuringCombat, FIELD_BOOLEAN, "LeadDuringCombat"), - DEFINE_KEYFIELD(m_bGagLeader, FIELD_BOOLEAN, "GagLeader"), - - DEFINE_KEYFIELD(m_iszStartConceptModifier, FIELD_STRING, "StartConceptModifier"), - DEFINE_KEYFIELD(m_iszAttractPlayerConceptModifier, FIELD_STRING, "AttractPlayerConceptModifier"), - DEFINE_KEYFIELD(m_iszWaitOverConceptModifier, FIELD_STRING, "WaitOverConceptModifier"), - DEFINE_KEYFIELD(m_iszArrivalConceptModifier, FIELD_STRING, "ArrivalConceptModifier"), - DEFINE_KEYFIELD(m_iszPostArrivalConceptModifier, FIELD_STRING, "PostArrivalConceptModifier"), - DEFINE_KEYFIELD(m_iszSuccessConceptModifier, FIELD_STRING, "SuccessConceptModifier"), - DEFINE_KEYFIELD(m_iszFailureConceptModifier, FIELD_STRING, "FailureConceptModifier"), - DEFINE_KEYFIELD(m_iszRetrieveConceptModifier, FIELD_STRING, "RetrieveConceptModifier"), - DEFINE_KEYFIELD(m_iszComingBackConceptModifier, FIELD_STRING, "ComingBackConceptModifier"), - - DEFINE_OUTPUT( m_OnSuccess, "OnSuccess" ), - DEFINE_OUTPUT( m_OnArrival, "OnArrival" ), - DEFINE_OUTPUT( m_OnArrivalDone, "OnArrivalDone" ), - DEFINE_OUTPUT( m_OnFailure, "OnFailure" ), - DEFINE_OUTPUT( m_OnDone, "OnDone" ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "SetSuccess", InputSetSuccess ), - DEFINE_INPUTFUNC( FIELD_VOID, "SetFailure", InputSetFailure ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- - -CAI_LeadBehavior *CAI_LeadGoal::GetLeadBehavior() -{ - CAI_BaseNPC *pActor = GetActor(); - if ( !pActor ) - return NULL; - - CAI_LeadBehavior *pBehavior; - if ( !pActor->GetBehavior( &pBehavior ) ) - { - return NULL; - } - - return pBehavior; -} - -//----------------------------------------------------------------------------- - -void CAI_LeadGoal::InputSetSuccess( inputdata_t &inputdata ) -{ - CAI_LeadBehavior *pBehavior = GetLeadBehavior(); - if ( !pBehavior ) - return; - - // @TODO (toml 02-14-03): Hackly! - pBehavior->SetCondition( CAI_LeadBehavior::COND_LEAD_SUCCESS); -} - - -//----------------------------------------------------------------------------- - -void CAI_LeadGoal::InputSetFailure( inputdata_t &inputdata ) -{ - DevMsg( "SetFailure unimplemented\n" ); -} - - -//----------------------------------------------------------------------------- - -void CAI_LeadGoal::InputActivate( inputdata_t &inputdata ) -{ - BaseClass::InputActivate( inputdata ); - - CAI_LeadBehavior *pBehavior = GetLeadBehavior(); - if ( !pBehavior ) - { - DevMsg( "Lead goal entity activated for an NPC that doesn't have the lead behavior\n" ); - return; - } -#ifdef HL2_EPISODIC - if ( (m_flLeadDistance*4) < m_flRetrieveDistance ) - { - Warning("ai_goal_lead '%s': lead distance (%.2f) * 4 is < retrieve distance (%.2f). This will make the NPC act stupid. Either reduce the retrieve distance, or increase the lead distance.\n", GetDebugName(), m_flLeadDistance, m_flRetrieveDistance ); - } -#endif - - if ( m_flRetrieveDistance < (m_flLeadDistance + LEAD_MIN_RETRIEVEDIST_OFFSET) ) - { -#ifdef HL2_EPISODIC - Warning("ai_goal_lead '%s': retrieve distance (%.2f) < lead distance (%.2f) + %d. Retrieve distance should be at least %d greater than the lead distance, or NPC will ping-pong while retrieving.\n", GetDebugName(), m_flRetrieveDistance, m_flLeadDistance, LEAD_MIN_RETRIEVEDIST_OFFSET, LEAD_MIN_RETRIEVEDIST_OFFSET ); -#endif - m_flRetrieveDistance = m_flLeadDistance + LEAD_MIN_RETRIEVEDIST_OFFSET; - } - - AI_LeadArgs_t leadArgs = { - GetGoalEntityName(), - STRING(m_iszWaitPointName), - m_spawnflags, - m_flWaitDistance, - m_flLeadDistance, - m_flRetrieveDistance, - m_flSuccessDistance, - m_bRun, - m_iRetrievePlayer, - m_iRetrieveWaitForSpeak, - m_iComingBackWaitForSpeak, - m_bStopScenesWhenPlayerLost, - m_bDontSpeakStart, - m_bLeadDuringCombat, - m_bGagLeader, - }; - - pBehavior->LeadPlayer( leadArgs, this ); -} - -//----------------------------------------------------------------------------- - -void CAI_LeadGoal::InputDeactivate( inputdata_t &inputdata ) -{ - BaseClass::InputDeactivate( inputdata ); - - CAI_LeadBehavior *pBehavior = GetLeadBehavior(); - if ( !pBehavior ) - return; - - pBehavior->StopLeading(); -} - -//----------------------------------------------------------------------------- - -void CAI_LeadGoal::OnEvent( int event ) -{ - COutputEvent *pOutputEvent = NULL; - - switch ( event ) - { - case LBE_ARRIVAL: pOutputEvent = &m_OnArrival; break; - case LBE_ARRIVAL_DONE: pOutputEvent = &m_OnArrivalDone; break; - case LBE_SUCCESS: pOutputEvent = &m_OnSuccess; break; - case LBE_FAILURE: pOutputEvent = &m_OnFailure; break; - case LBE_DONE: pOutputEvent = &m_OnDone; break; - } - - // @TODO (toml 08-16-02): move arrived tracking onto behavior - if ( event == LBE_ARRIVAL ) - m_fArrived = true; - - if ( pOutputEvent ) - pOutputEvent->FireOutput( this, this ); -} - -//----------------------------------------------------------------------------- - -const char *CAI_LeadGoal::GetConceptModifiers( const char *pszConcept ) -{ - if ( m_iszStartConceptModifier != NULL_STRING && *STRING(m_iszStartConceptModifier) && strcmp( pszConcept, TLK_LEAD_START) == 0 ) - return STRING( m_iszStartConceptModifier ); - - if ( m_iszAttractPlayerConceptModifier != NULL_STRING && *STRING(m_iszAttractPlayerConceptModifier) && strcmp( pszConcept, TLK_LEAD_ATTRACTPLAYER) == 0 ) - return STRING( m_iszAttractPlayerConceptModifier ); - - if ( m_iszWaitOverConceptModifier != NULL_STRING && *STRING(m_iszWaitOverConceptModifier) && strcmp( pszConcept, TLK_LEAD_WAITOVER) == 0 ) - return STRING( m_iszWaitOverConceptModifier ); - - if ( m_iszArrivalConceptModifier != NULL_STRING && *STRING(m_iszArrivalConceptModifier) && strcmp( pszConcept, TLK_LEAD_ARRIVAL) == 0 ) - return STRING( m_iszArrivalConceptModifier ); - - if ( m_iszSuccessConceptModifier != NULL_STRING && *STRING(m_iszSuccessConceptModifier) && strcmp( pszConcept, TLK_LEAD_SUCCESS) == 0 ) - return STRING( m_iszSuccessConceptModifier ); - - if (m_iszFailureConceptModifier != NULL_STRING && *STRING(m_iszFailureConceptModifier) && strcmp( pszConcept, TLK_LEAD_FAILURE) == 0 ) - return STRING( m_iszFailureConceptModifier ); - - if (m_iszRetrieveConceptModifier != NULL_STRING && *STRING(m_iszRetrieveConceptModifier) && strcmp( pszConcept, TLK_LEAD_RETRIEVE) == 0 ) - return STRING( m_iszRetrieveConceptModifier ); - - if (m_iszComingBackConceptModifier != NULL_STRING && *STRING(m_iszComingBackConceptModifier) && strcmp( pszConcept, TLK_LEAD_COMINGBACK) == 0 ) - return STRING( m_iszComingBackConceptModifier ); - - if ( m_fArrived && m_iszPostArrivalConceptModifier != NULL_STRING && *STRING(m_iszPostArrivalConceptModifier) ) - return STRING( m_iszPostArrivalConceptModifier ); - - return NULL; -} - - -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// -// Purpose: A custom lead goal that waits until the player has a weapon. -// - -class CAI_LeadGoal_Weapon : public CAI_LeadGoal -{ - DECLARE_CLASS( CAI_LeadGoal_Weapon, CAI_LeadGoal ); -public: - - virtual const char *GetConceptModifiers( const char *pszConcept ); - virtual void InputActivate( inputdata_t &inputdata ); - -private: - string_t m_iszWeaponName; - string_t m_iszMissingWeaponConceptModifier; - - DECLARE_DATADESC(); -}; - -//----------------------------------------------------------------------------- -// -// CAI_LeadGoal_Weapon implementation -// - -LINK_ENTITY_TO_CLASS( ai_goal_lead_weapon, CAI_LeadGoal_Weapon ); - -BEGIN_DATADESC( CAI_LeadGoal_Weapon ) - - DEFINE_KEYFIELD( m_iszWeaponName, FIELD_STRING, "WeaponName"), - DEFINE_KEYFIELD( m_iszMissingWeaponConceptModifier, FIELD_STRING, "MissingWeaponConceptModifier"), - -END_DATADESC() - -//----------------------------------------------------------------------------- - -const char *CAI_LeadGoal_Weapon::GetConceptModifiers( const char *pszConcept ) -{ - if ( m_iszMissingWeaponConceptModifier != NULL_STRING && *STRING(m_iszMissingWeaponConceptModifier) && strcmp( pszConcept, TLK_LEAD_MISSINGWEAPON) == 0 ) - return STRING( m_iszMissingWeaponConceptModifier ); - - return BaseClass::GetConceptModifiers( pszConcept ); -} - - -//----------------------------------------------------------------------------- - -void CAI_LeadGoal_Weapon::InputActivate( inputdata_t &inputdata ) -{ - BaseClass::InputActivate( inputdata ); - - CAI_LeadBehavior *pBehavior = GetLeadBehavior(); - if ( pBehavior ) - { - pBehavior->SetWaitForWeapon( m_iszWeaponName ); - } -} diff --git a/game/server/ai_behavior_lead.h b/game/server/ai_behavior_lead.h deleted file mode 100644 index 216c626d8..000000000 --- a/game/server/ai_behavior_lead.h +++ /dev/null @@ -1,236 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef AI_BEHAVIOR_LEAD_H -#define AI_BEHAVIOR_LEAD_H - -#include "simtimer.h" -#include "ai_behavior.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -typedef const char *AIConcept_t; - -// Speak concepts -#define TLK_LEAD_START "TLK_LEAD_START" -#define TLK_LEAD_ARRIVAL "TLK_LEAD_ARRIVAL" -#define TLK_LEAD_SUCCESS "TLK_LEAD_SUCCESS" -#define TLK_LEAD_FAILURE "lead_fail" -#define TLK_LEAD_COMINGBACK "TLK_LEAD_COMINGBACK" -#define TLK_LEAD_CATCHUP "TLK_LEAD_CATCHUP" -#define TLK_LEAD_RETRIEVE "TLK_LEAD_RETRIEVE" -#define TLK_LEAD_ATTRACTPLAYER "TLK_LEAD_ATTRACTPLAYER" -#define TLK_LEAD_WAITOVER "TLK_LEAD_WAITOVER" -#define TLK_LEAD_MISSINGWEAPON "TLK_LEAD_MISSING_WEAPON" -#define TLK_LEAD_IDLE "TLK_LEAD_IDLE" - -//----------------------------------------------------------------------------- -// class CAI_LeadBehavior -// -// Purpose: -// -//----------------------------------------------------------------------------- - -enum LeadBehaviorEvents_t -{ - LBE_ARRIVAL, - LBE_ARRIVAL_DONE, - LBE_SUCCESS, - LBE_FAILURE, - LBE_DONE, -}; - -//------------------------------------- -// -// Handler class interface to listen to and modify actions of the lead behavior. -// Could be an NPC, or another entity (like a goal entity) -// - -class CAI_LeadBehaviorHandler -{ -public: - virtual void OnEvent( int event ) {} - virtual const char *GetConceptModifiers( const char *pszConcept ) { return NULL; } -}; - -//------------------------------------- - -enum AI_LeadFlags_t -{ - AILF_NO_DEF_SUCCESS = 0x01, - AILF_NO_DEF_FAILURE = 0x02, - AILF_USE_GOAL_FACING = 0x04, -}; - -struct AI_LeadArgs_t -{ - const char *pszGoal; - const char *pszWaitPoint; - unsigned flags; - float flWaitDistance; - float flLeadDistance; - float flRetrieveDistance; - float flSuccessDistance; - bool bRun; - int iRetrievePlayer; - int iRetrieveWaitForSpeak; - int iComingBackWaitForSpeak; - bool bStopScenesWhenPlayerLost; - bool bDontSpeakStart; - bool bLeadDuringCombat; - bool bGagLeader; - - DECLARE_SIMPLE_DATADESC(); -}; - - -class CAI_LeadBehavior : public CAI_SimpleBehavior -{ - DECLARE_CLASS( CAI_LeadBehavior, CAI_SimpleBehavior ); -public: - CAI_LeadBehavior() - : m_pSink(NULL), - m_LostTimer( 3.0, 4.0 ), - m_LostLOSTimer( 2.0, 3.0 ) - { - memset( &m_args, 0, sizeof(m_args) ); - ClearGoal(); - } - - virtual void OnRestore(); - - virtual const char *GetName() { return "Lead"; } - - virtual int DrawDebugTextOverlays( int text_offset ); - virtual bool IsNavigationUrgent(); - - void LeadPlayer( const AI_LeadArgs_t &leadArgs, CAI_LeadBehaviorHandler *pSink = NULL ); - void StopLeading( void ); - - virtual bool CanSelectSchedule(); - void BeginScheduleSelection(); - - virtual bool IsCurTaskContinuousMove(); - - bool SetGoal( const AI_LeadArgs_t &args ); - void ClearGoal() { m_goal = vec3_origin; m_waitpoint = vec3_origin; m_pSink = NULL; m_weaponname = NULL_STRING; } - bool HasGoal() const { return (m_goal != vec3_origin); } - bool HasWaitPoint() const { return (m_waitpoint != vec3_origin); } - - bool Connect( CAI_LeadBehaviorHandler *); - bool Disconnect( CAI_LeadBehaviorHandler *); - - void SetWaitForWeapon( string_t iszWeaponName ) { m_weaponname = iszWeaponName; m_flWeaponSafetyTimeOut = gpGlobals->curtime + 60; } - - enum - { - // Schedules - SCHED_LEAD_PLAYER = BaseClass::NEXT_SCHEDULE, - SCHED_LEAD_PAUSE, - SCHED_LEAD_PAUSE_COMBAT, - SCHED_LEAD_RETRIEVE, - SCHED_LEAD_RETRIEVE_WAIT, - SCHED_LEAD_SUCCEED, - SCHED_LEAD_AWAIT_SUCCESS, - SCHED_LEAD_WAITFORPLAYER, - SCHED_LEAD_WAITFORPLAYERIDLE, - SCHED_LEAD_PLAYERNEEDSWEAPON, - SCHED_LEAD_SPEAK_START, - SCHED_LEAD_SPEAK_THEN_RETRIEVE_PLAYER, - SCHED_LEAD_SPEAK_THEN_LEAD_PLAYER, - NEXT_SCHEDULE, - - // Tasks - TASK_GET_PATH_TO_LEAD_GOAL = BaseClass::NEXT_TASK, - TASK_STOP_LEADING, - TASK_LEAD_FACE_GOAL, - TASK_LEAD_ARRIVE, - TASK_LEAD_SUCCEED, - TASK_LEAD_GET_PATH_TO_WAITPOINT, - TASK_LEAD_WAVE_TO_PLAYER, - TASK_LEAD_PLAYER_NEEDS_WEAPON, - TASK_LEAD_SPEAK_START, - TASK_LEAD_MOVE_TO_RANGE, - TASK_LEAD_RETRIEVE_WAIT, - TASK_LEAD_WALK_PATH, - NEXT_TASK, - - // Conditions - COND_LEAD_FOLLOWER_LOST = BaseClass::NEXT_CONDITION, - COND_LEAD_FOLLOWER_LAGGING, - COND_LEAD_FOLLOWER_NOT_LAGGING, - COND_LEAD_FOLLOWER_VERY_CLOSE, - COND_LEAD_SUCCESS, - COND_LEAD_HAVE_FOLLOWER_LOS, - COND_LEAD_FOLLOWER_MOVED_FROM_MARK, - COND_LEAD_FOLLOWER_MOVING_TOWARDS_ME, - NEXT_CONDITION - - }; - -private: - - void GatherConditions(); - virtual int SelectSchedule(); - virtual int TranslateSchedule( int scheduleType ); - virtual void StartTask( const Task_t *pTask ); - virtual void RunTask( const Task_t *pTask ); - - bool GetClosestPointOnRoute( const Vector &targetPos, Vector *pVecClosestPoint ); - bool PlayerIsAheadOfMe( bool bForce = false ); - - bool Speak( AIConcept_t concept ); - bool IsSpeaking(); - - // -------------------------------- - // - // Sink notifiers. Isolated to limit exposure to actual sink storage, - // provide debugging pinch pount, and allow for class-local logic - // in addition to sink logic - // - void NotifyEvent( int event ) { if ( m_pSink ) m_pSink->OnEvent( event ) ; } - const char * GetConceptModifiers( const char *pszConcept ) { return ( m_pSink ) ? m_pSink->GetConceptModifiers( pszConcept ) : NULL; } - - // -------------------------------- - - AI_LeadArgs_t m_args; - CAI_LeadBehaviorHandler *m_pSink; - EHANDLE m_hSinkImplementor; - - // -------------------------------- - - Vector m_goal; - float m_goalyaw; - Vector m_waitpoint; - float m_waitdistance; - float m_leaddistance; - float m_retrievedistance; - float m_successdistance; - string_t m_weaponname; - bool m_run; - bool m_gagleader; - bool m_hasspokenstart; - bool m_hasspokenarrival; - bool m_hasPausedScenes; - float m_flSpeakNextNagTime; - float m_flWeaponSafetyTimeOut; - float m_flNextLeadIdle; - bool m_bInitialAheadTest; - CAI_MoveMonitor m_MoveMonitor; - - CRandStopwatch m_LostTimer; - CRandStopwatch m_LostLOSTimer; - - DEFINE_CUSTOM_SCHEDULE_PROVIDER; - - DECLARE_DATADESC(); -}; - -//----------------------------------------------------------------------------- - -#endif // AI_BEHAVIOR_LEAD_H diff --git a/game/server/ai_behavior_passenger.cpp b/game/server/ai_behavior_passenger.cpp deleted file mode 100644 index 9b26aa55c..000000000 --- a/game/server/ai_behavior_passenger.cpp +++ /dev/null @@ -1,1736 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: Behavior for NPCs riding in cars (with boys) -// -//============================================================================= - -#include "cbase.h" -#include "ai_playerally.h" -#include "ai_motor.h" -#include "bone_setup.h" -#include "vehicle_base.h" -#include "entityblocker.h" -#include "ai_behavior_passenger.h" -#include "ai_pathfinder.h" -#include "ai_network.h" -#include "ai_node.h" -#include "ai_moveprobe.h" -#include "env_debughistory.h" - -// Custom activities -int ACT_PASSENGER_IDLE; -int ACT_PASSENGER_RANGE_ATTACK1; - -ConVar passenger_debug_transition( "passenger_debug_transition", "0" ); -ConVar passenger_impact_response_threshold( "passenger_impact_response_threshold", "-350.0" ); - -#define ORIGIN_KEYNAME "origin" -#define ANGLES_KEYNAME "angles" - -BEGIN_DATADESC( CAI_PassengerBehavior ) - - DEFINE_EMBEDDED( m_vehicleState ), - DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ), - DEFINE_FIELD( m_PassengerIntent, FIELD_INTEGER ), - DEFINE_FIELD( m_PassengerState, FIELD_INTEGER ), - DEFINE_FIELD( m_hVehicle, FIELD_EHANDLE ), - DEFINE_FIELD( m_hBlocker, FIELD_EHANDLE ), - DEFINE_FIELD( m_vecTargetPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecTargetAngles, FIELD_VECTOR ), - DEFINE_FIELD( m_flOriginStartFrame, FIELD_FLOAT ), - DEFINE_FIELD( m_flOriginEndFrame, FIELD_FLOAT ), - DEFINE_FIELD( m_flAnglesStartFrame, FIELD_FLOAT ), - DEFINE_FIELD( m_flAnglesEndFrame, FIELD_FLOAT ), - DEFINE_FIELD( m_nTransitionSequence,FIELD_INTEGER ), - -END_DATADESC(); - -BEGIN_SIMPLE_DATADESC( passengerVehicleState_t ) - - DEFINE_FIELD( m_bWasBoosting, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bWasOverturned, FIELD_BOOLEAN ), - DEFINE_FIELD( m_vecLastLocalVelocity, FIELD_VECTOR ), - DEFINE_FIELD( m_vecDeltaVelocity, FIELD_VECTOR ), - DEFINE_FIELD( m_vecLastAngles, FIELD_VECTOR ), - DEFINE_FIELD( m_flNextWarningTime, FIELD_TIME ), - DEFINE_FIELD( m_flLastSpeedSqr, FIELD_FLOAT ), - DEFINE_FIELD( m_bPlayerInVehicle, FIELD_BOOLEAN ), - -END_DATADESC(); - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CAI_PassengerBehavior::CAI_PassengerBehavior( void ) : -m_PassengerState( PASSENGER_STATE_OUTSIDE ), -m_hVehicle( NULL ), -m_bEnabled( false ), -m_PassengerIntent( PASSENGER_INTENT_NONE ), -m_nTransitionSequence( -1 ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: Enables the behavior to run -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::Enable( CPropJeepEpisodic *pVehicle, bool bImmediateEnter /*= false*/ ) -{ - if ( m_bEnabled && m_hVehicle.Get() ) - return; - - m_bEnabled = true; - m_hVehicle = pVehicle; - SetPassengerState( PASSENGER_STATE_OUTSIDE ); - - // Init our starting information about the vehicle - InitVehicleState(); -} - -void CAI_PassengerBehavior::OnRestore() -{ - if ( m_bEnabled && !m_hVehicle.Get() ) - { - Disable(); - } - - BaseClass::OnRestore(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Stops the behavior from being run -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::Disable( void ) -{ - m_bEnabled = false; - m_hVehicle = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Starts the process of entering a vehicle -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::EnterVehicle( void ) -{ - // If we're already in the vehicle, simply cancel out our intents - if ( GetPassengerState() == PASSENGER_STATE_INSIDE || GetPassengerState() == PASSENGER_STATE_ENTERING ) - { - // Clear out an exit - if ( m_PassengerIntent == PASSENGER_INTENT_EXIT ) - { - m_PassengerIntent = PASSENGER_INTENT_NONE; - ClearCondition( COND_PASSENGER_ENTERING ); - ClearCondition( COND_PASSENGER_EXITING ); - } - - return; - } - - // Update our internal state - m_PassengerIntent = PASSENGER_INTENT_ENTER; - - // Otherwise set this condition and go! - SetCondition( COND_PASSENGER_ENTERING ); -} - -//----------------------------------------------------------------------------- -// Purpose: Starts the process of exiting a vehicle -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::ExitVehicle( void ) -{ - // Must be in the seat - if ( GetPassengerState() == PASSENGER_STATE_OUTSIDE || GetPassengerState() == PASSENGER_STATE_EXITING ) - { - // Clear out an entrance - if ( m_PassengerIntent == PASSENGER_INTENT_ENTER ) - { - m_PassengerIntent = PASSENGER_INTENT_NONE; - SetCondition( COND_PASSENGER_CANCEL_ENTER ); - ClearCondition( COND_PASSENGER_ENTERING ); - ClearCondition( COND_PASSENGER_EXITING ); - } - return; - } - - // Update our internal state - m_PassengerIntent = PASSENGER_INTENT_EXIT; - - // - // Everything below this point will still attempt to exit the vehicle, once able - // - - // Must have a valid vehicle - if ( m_hVehicle == NULL ) - return; - - // Cannot exit while we're upside down - if ( m_hVehicle->IsOverturned() ) - return; - - // Interrupt what we're doing - SetCondition( COND_PASSENGER_EXITING ); -} - -//----------------------------------------------------------------------------- -// Purpose: FIXME - This should move into something a bit more flexible -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::AddPhysicsPush( float force ) -{ - /* - // Kick the vehicle so the player knows we've arrived - Vector impulse = m_hVehicle->GetAbsOrigin() - GetOuter()->GetAbsOrigin(); - VectorNormalize( impulse ); - impulse.z = -0.75; - VectorNormalize( impulse ); - Vector vecForce = impulse * force; - - m_hVehicle->VPhysicsGetObject()->ApplyForceOffset( vecForce, GetOuter()->GetAbsOrigin() ); - */ - - Vector vecDir; - - IPhysicsObject *pObject = GetOuter()->VPhysicsGetObject(); - Vector vecVelocity; - pObject->GetVelocity( &vecVelocity, NULL ); - GetOuter()->GetVectors( NULL, NULL, &vecDir ); - vecDir.Negate(); - - Vector vecForce = vecDir * force; - - m_hVehicle->VPhysicsGetObject()->ApplyForceOffset( vecForce, GetOuter()->GetAbsOrigin() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PassengerBehavior::IsPassengerHostile( void ) -{ - CBaseEntity *pPlayer = AI_GetSinglePlayer(); - - // If the player hates or fears the passenger, they're hostile - if ( GetOuter()->IRelationType( pPlayer ) == D_HT || GetOuter()->IRelationType( pPlayer ) == D_FR ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::InitVehicleState( void ) -{ - // Set the player's state - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - m_vehicleState.m_bPlayerInVehicle = ( pPlayer && pPlayer->IsInAVehicle() && pPlayer->GetServerVehicle() == m_hVehicle->GetServerVehicle() ); - - // Update our vehicle state so we don't confuse our previous velocity on the first frame! - m_vehicleState.m_bWasBoosting = false; - m_vehicleState.m_bWasOverturned = false; - m_vehicleState.m_flNextWarningTime = 0.0f; - m_vehicleState.m_vecDeltaVelocity = vec3_origin; - m_vehicleState.m_flNextWarningTime = gpGlobals->curtime; - m_vehicleState.m_vecLastAngles = m_hVehicle->GetAbsAngles(); - - Vector localVelocity(0.0f, 0.0f, 0.0f); - GetLocalVehicleVelocity( &m_vehicleState.m_vecLastLocalVelocity ); - - m_vehicleState.m_flLastSpeedSqr = localVelocity.LengthSqr(); -} - -//----------------------------------------------------------------------------- -// Purpose: Puts the NPC in hierarchy with the vehicle and makes them intangible -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::FinishEnterVehicle( void ) -{ - if ( m_hVehicle == NULL ) - return; - - // Get the ultimate position we want to be in - Vector vecFinalPos; - QAngle vecFinalAngles; - GetEntryTarget( &vecFinalPos, &vecFinalAngles ); - - // Make sure we're exactly where we need to be - GetOuter()->SetLocalOrigin( vecFinalPos ); - GetOuter()->SetLocalAngles( vecFinalAngles ); - GetOuter()->SetMoveType( MOVETYPE_NONE ); - GetOuter()->GetMotor()->SetYawLocked( true ); - - // We're now riding inside the vehicle - SetPassengerState( PASSENGER_STATE_INSIDE ); - - // If we've not been told to leave immediately, we're done - if ( m_PassengerIntent == PASSENGER_INTENT_ENTER ) - { - m_PassengerIntent = PASSENGER_INTENT_NONE; - } - - // Tell the vehicle we've succeeded - m_hVehicle->NPC_FinishedEnterVehicle( GetOuter(), (IsPassengerHostile()==false) ); -} - -//----------------------------------------------------------------------------- -// Purpose: Removes the NPC from the car -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::FinishExitVehicle( void ) -{ - if ( m_hVehicle == NULL ) - return; - - // Destroy the blocker - if ( m_hBlocker != NULL ) - { - UTIL_Remove( m_hBlocker ); - m_hBlocker = NULL; - } - - // To do this, we need to be very sure we're in a good spot - GetOuter()->SetCondition( COND_PROVOKED ); - GetOuter()->SetMoveType( MOVETYPE_STEP ); - GetOuter()->RemoveFlag( FL_FLY ); - GetOuter()->GetMotor()->SetYawLocked( false ); - - // Re-enable the physical collisions for this NPC - IPhysicsObject *pPhysObj = GetOuter()->VPhysicsGetObject(); - if ( pPhysObj != NULL ) - { - pPhysObj->EnableCollisions( true ); - } - - m_hVehicle->NPC_RemovePassenger( GetOuter() ); - m_hVehicle->NPC_FinishedExitVehicle( GetOuter(), (IsPassengerHostile()==false) ); - - SetPassengerState( PASSENGER_STATE_OUTSIDE ); - - // Stop our custom move sequence - GetOuter()->m_iszSceneCustomMoveSeq = NULL_STRING; - - // If we've not been told to enter immediately, we're done - if ( m_PassengerIntent == PASSENGER_INTENT_EXIT ) - { - m_PassengerIntent = PASSENGER_INTENT_NONE; - Disable(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Build our custom interrupt cases for the behavior -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::BuildScheduleTestBits( void ) -{ - // Always interrupt when we need to get in or out - if ( GetPassengerState() == PASSENGER_STATE_OUTSIDE || GetPassengerState() == PASSENGER_STATE_INSIDE ) - { - GetOuter()->SetCustomInterruptCondition( GetClassScheduleIdSpace()->ConditionLocalToGlobal( COND_PASSENGER_ENTERING ) ); - GetOuter()->SetCustomInterruptCondition( GetClassScheduleIdSpace()->ConditionLocalToGlobal( COND_PASSENGER_EXITING ) ); - GetOuter()->SetCustomInterruptCondition( GetClassScheduleIdSpace()->ConditionLocalToGlobal( COND_PASSENGER_CANCEL_ENTER ) ); - } - - BaseClass::BuildScheduleTestBits(); -} - -//----------------------------------------------------------------------------- -// Purpose: Dictates whether or not the behavior is active and working -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PassengerBehavior::CanSelectSchedule( void ) -{ - return m_bEnabled; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PassengerBehavior::CanExitVehicle( void ) -{ - // Vehicle must not be overturned - if ( m_hVehicle->IsOverturned() ) - return false; - - // Vehicle must be at rest - Vector vecVelocity; - m_hVehicle->GetVelocity( &vecVelocity, NULL ); - if ( vecVelocity.LengthSqr() > Square( 8.0f ) ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Handles passengers deciding to enter or exit the vehicle -// Output : int -//----------------------------------------------------------------------------- -int CAI_PassengerBehavior::SelectTransitionSchedule( void ) -{ - // Handle our various states - if ( GetPassengerState() == PASSENGER_STATE_INSIDE ) - { - // Exiting schedule - if ( HasCondition( COND_PASSENGER_EXITING ) || m_PassengerIntent == PASSENGER_INTENT_EXIT ) - { - if ( CanExitVehicle( ) ) - { - ClearCondition( COND_PASSENGER_EXITING ); - return SCHED_PASSENGER_EXIT_VEHICLE; - } - } - } - else if ( GetPassengerState() == PASSENGER_STATE_ENTERING || GetPassengerState() == PASSENGER_STATE_EXITING ) - { - // The following code attempts to fix up a passenger being interrupted mid-transition - Warning( "SelectSchedule() called on transitioning passenger!\n" ); - ADD_DEBUG_HISTORY( HISTORY_AI_DECISIONS, UTIL_VarArgs( "%s(%d): SelectSchedule() called on transitioning passenger!\n", GetOuter()->GetDebugName(), GetOuter()->entindex() ) ); - Assert( 0 ); - - // Correct this issue immediately - if ( GetPassengerState() == PASSENGER_STATE_EXITING ) - { - // Force them out of the vehicle to where they want to be - // The teleport function is overridden for passengers, meaning that they will clean up properly when called to do so - GetOuter()->Teleport( &m_vecTargetPosition, &m_vecTargetAngles, NULL ); - } - else if ( GetPassengerState() == PASSENGER_STATE_ENTERING ) - { - // Force them into the proper position - GetOuter()->SetLocalOrigin( m_vecTargetPosition ); - GetOuter()->SetLocalAngles( m_vecTargetAngles ); - FinishEnterVehicle(); - } - - // Stop playing our animation - SetActivity( ACT_RESET ); - } - - return SCHED_NONE; -} - -//----------------------------------------------------------------------------- -// Purpose: Overrides the schedule selection -// Output : int - Schedule to play -//----------------------------------------------------------------------------- -int CAI_PassengerBehavior::SelectSchedule( void ) -{ - // Protect from this rare occurrence happening - if ( m_hVehicle == NULL ) - { - Assert( m_hVehicle != NULL ); - Warning( "Entity %s running passenger behavior without a valid vehicle!\n", GetName() ); - - Disable(); - return BaseClass::SelectSchedule(); - } - - // See if we're transitioning in / out of the vehicle - int nSchedule = SelectTransitionSchedule(); - if ( nSchedule != SCHED_NONE ) - return nSchedule; - - return SCHED_PASSENGER_IDLE; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CAI_PassengerBehavior::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ) -{ - switch( failedTask ) - { - // For now, just sit back down - case TASK_PASSENGER_DETACH_FROM_VEHICLE: - return SCHED_PASSENGER_IDLE; - break; - } - - return BaseClass::SelectFailSchedule( failedSchedule, failedTask, taskFailCode ); -} - -//----------------------------------------------------------------------------- -// Purpose: Finds a ground position at a given location with some delta up and down to check -// Input : &in - position to check at -// delta - amount of distance up and down to check -// *out - ground position -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PassengerBehavior::FindGroundAtPosition( const Vector &in, float flUpDelta, float flDownDelta, Vector *out ) -{ - Vector startPos = in + Vector( 0, 0, flUpDelta ); // Look up by delta - Vector endPos = in - Vector( 0, 0, flDownDelta ); // Look down by delta - Vector hullMin = GetOuter()->GetHullMins(); - Vector hullMax = GetOuter()->GetHullMaxs(); - - // Ignore ourself and the vehicle we're referencing - CTraceFilterVehicleTransition ignoreFilter( m_hVehicle, GetOuter(), COLLISION_GROUP_NONE ); - - trace_t tr; - UTIL_TraceHull( startPos, endPos, hullMin, hullMax, MASK_NPCSOLID, &ignoreFilter, &tr ); - - // Must not have ended up in solid space - if ( tr.allsolid ) - { - // Debug - if ( passenger_debug_transition.GetBool() ) - { - NDebugOverlay::SweptBox( tr.startpos, tr.endpos, hullMin, hullMax, vec3_angle, 255, 255, 0, 255, 1.0f ); - } - - return false; - } - - // Must have ended up with feet on the ground - if ( tr.DidHitWorld() || ( tr.m_pEnt && tr.m_pEnt->IsStandable() ) ) - { - // Debug - if ( passenger_debug_transition.GetBool() ) - { - NDebugOverlay::SweptBox( tr.startpos, tr.endpos, hullMin, hullMax, vec3_angle, 0, 255, 0, 255, 1.0f ); - } - - *out = tr.endpos; - return true; - } - - // Ended up in the air - if ( passenger_debug_transition.GetBool() ) - { - NDebugOverlay::SweptBox( tr.startpos, tr.endpos, hullMin, hullMax, vec3_angle, 255, 0, 0, 255, 1.0f ); - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Attempt to verify that a test position is on the node graph -//----------------------------------------------------------------------------- -bool CAI_PassengerBehavior::PointIsNavigable( const Vector &vecTargetPos ) -{ - // Attempt to local move between this point and the nearest node, ignoring anything but world architecture - AIMoveTrace_t moveTrace; - int iNearestNode = GetOuter()->GetPathfinder()->NearestNodeToPoint( vecTargetPos ); - if ( iNearestNode != NO_NODE ) - { - // Try a movement trace between the test position and the node - GetOuter()->GetMoveProbe()->MoveLimit( NAV_GROUND, - g_pBigAINet->GetNodePosition(GetOuter()->GetHullType(), iNearestNode ), - vecTargetPos, - MASK_SOLID_BRUSHONLY, - NULL, - 0, - &moveTrace ); - - // See if we got close enough to call it arrived - if ( ( moveTrace.vEndPosition - vecTargetPos ).LengthSqr() < Square( GetHullWidth() ) && - GetOuter()->GetMoveProbe()->CheckStandPosition( moveTrace.vEndPosition, MASK_SOLID_BRUSHONLY ) ) - { - // NDebugOverlay::HorzArrow( vecTargetPos, moveTrace.vEndPosition, 8.0f, 255, 0, 0, 16, true, 4.0f ); - // NDebugOverlay::HorzArrow( vecTargetPos, g_pBigAINet->GetNodePosition(GetOuter()->GetHullType(), iNearestNode ), 8.0f, 255, 255, 0, 16, true, 4.0f ); - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Gets the exit point for the passenger (on the ground) -// Input : &vecOut - position the entity should be at when finished exiting -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PassengerBehavior::GetExitPoint( int nSequence, Vector *vecExitPoint, QAngle *vecExitAngles ) -{ - bool bSucceeded = true; - - // Get the delta to the final position as will be dictated by this animation's auto movement - Vector vecDeltaPos; - QAngle vecDeltaAngles; - GetOuter()->GetSequenceMovement( nSequence, 0.0f, 1.0f, vecDeltaPos, vecDeltaAngles ); - - // Rotate the delta position by our starting angles - Vector vecRotPos = vecDeltaPos; - VectorRotate( vecRotPos, GetOuter()->GetAbsAngles(), vecDeltaPos ); - - if ( vecExitPoint != NULL ) - { - float flDownDelta = 64.0f; - float flUpDelta = 16.0f; - Vector vecGroundPos; - - bool bFoundGround = FindGroundAtPosition( GetOuter()->GetAbsOrigin() + vecDeltaPos, flUpDelta, flDownDelta, &vecGroundPos ); - if ( bFoundGround ) - { - if ( PointIsNavigable( vecGroundPos ) == false ) - { - bSucceeded = false; - } - } - else - { - bSucceeded = false; - } - - *vecExitPoint = vecGroundPos; - } - - if ( vecExitAngles != NULL ) - { - QAngle newAngles = GetOuter()->GetAbsAngles() + vecDeltaAngles; - newAngles.x = UTIL_AngleMod( newAngles.x ); - newAngles.y = UTIL_AngleMod( newAngles.y ); - newAngles.z = UTIL_AngleMod( newAngles.z ); - *vecExitAngles = newAngles; - } - - return bSucceeded; -} - -//----------------------------------------------------------------------------- -// Purpose: Reserve our entry point -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PassengerBehavior::ReserveEntryPoint( VehicleSeatQuery_e eSeatSearchType ) -{ - // FIXME: Move all this logic into the NPC_EnterVehicle function? - // Find any seat to get into - int nSeatID = m_hVehicle->GetServerVehicle()->NPC_GetAvailableSeat( GetOuter(), GetRoleName(), eSeatSearchType ); - if ( nSeatID != VEHICLE_SEAT_INVALID ) - return m_hVehicle->NPC_AddPassenger( GetOuter(), GetRoleName(), nSeatID ); - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Determines whether the NPC can move between a start and end position of a transition -// Input : &vecStartPos - start position -// &vecEndPos - end position -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PassengerBehavior::IsValidTransitionPoint( const Vector &vecStartPos, const Vector &vecEndPos ) -{ - // Now sweep a hull through space to see if we can validly exit there - Vector vecHullMins = GetOuter()->GetHullMins() + Vector( 0, 0, GetOuter()->StepHeight()*2.0f ); - Vector vecHullMaxs = GetOuter()->GetHullMaxs() - Vector( 0, 0, GetOuter()->StepHeight() ); - - trace_t tr; - CTraceFilterVehicleTransition skipFilter( GetOuter(), m_hVehicle, COLLISION_GROUP_NONE ); - UTIL_TraceHull( vecStartPos, vecEndPos, vecHullMins, vecHullMaxs, MASK_NPCSOLID, &skipFilter, &tr ); - - // If we're blocked, we can't get out there - if ( tr.fraction < 1.0f || tr.allsolid ) - { - if ( passenger_debug_transition.GetBool() ) - { - NDebugOverlay::SweptBox( vecStartPos, vecEndPos, vecHullMins, vecHullMaxs, vec3_angle, 255, 0, 0, 64, 2.0f ); - } - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Find the proper sequence to use (weighted by priority or distance from current position) -// to enter the vehicle. -// Input : bNearest - Use distance as the criteria for a "best" sequence. Otherwise the order of the -// seats is their priority. -// Output : int - sequence index -//----------------------------------------------------------------------------- -int CAI_PassengerBehavior::FindEntrySequence( bool bNearest /*= false*/ ) -{ - // Get a list of all our animations - const PassengerSeatAnims_t *pEntryAnims = m_hVehicle->GetServerVehicle()->NPC_GetPassengerSeatAnims( GetOuter(), PASSENGER_SEAT_ENTRY ); - if ( pEntryAnims == NULL ) - return -1; - - // Get the ultimate position we'll end up at - Vector vecStartPos, vecEndPos; - if ( m_hVehicle->GetServerVehicle()->NPC_GetPassengerSeatPosition( GetOuter(), &vecEndPos, NULL ) == false ) - return -1; - - const CPassengerSeatTransition *pTransition; - Vector vecSeatDir; - float flNearestDist = FLT_MAX; - float flSeatDist; - int nNearestSequence = -1; - int nSequence; - - // Test each animation (sorted by priority) for the best match - for ( int i = 0; i < pEntryAnims->Count(); i++ ) - { - // Find the activity for this animation name - pTransition = &pEntryAnims->Element(i); - nSequence = GetOuter()->LookupSequence( STRING( pTransition->GetAnimationName() ) ); - if ( nSequence == -1 ) - continue; - - // Test this entry for validity - if ( GetEntryPoint( nSequence, &vecStartPos ) == false ) - continue; - - // Check to see if we can use this - if ( IsValidTransitionPoint( vecStartPos, vecEndPos ) ) - { - // If we're just looking for the first, we're done - if ( bNearest == false ) - return nSequence; - - // Otherwise distance is the deciding factor - vecSeatDir = ( vecStartPos - GetOuter()->GetAbsOrigin() ); - flSeatDist = VectorNormalize( vecSeatDir ); - - // Closer, take it - if ( flSeatDist < flNearestDist ) - { - flNearestDist = flSeatDist; - nNearestSequence = nSequence; - } - } - - } - - return nNearestSequence; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -int CAI_PassengerBehavior::FindExitSequence( void ) -{ - // Get a list of all our animations - const PassengerSeatAnims_t *pExitAnims = m_hVehicle->GetServerVehicle()->NPC_GetPassengerSeatAnims( GetOuter(), PASSENGER_SEAT_EXIT ); - if ( pExitAnims == NULL ) - return -1; - - // Get the ultimate position we'll end up at - Vector vecStartPos, vecEndPos; - if ( m_hVehicle->GetServerVehicle()->NPC_GetPassengerSeatPosition( GetOuter(), &vecStartPos, NULL ) == false ) - return -1; - - // Test each animation (sorted by priority) for the best match - for ( int i = 0; i < pExitAnims->Count(); i++ ) - { - // Find the activity for this animation name - int nSequence = GetOuter()->LookupSequence( STRING( pExitAnims->Element(i).GetAnimationName() ) ); - if ( nSequence == -1 ) - continue; - - // Test this entry for validity - if ( GetExitPoint( nSequence, &vecEndPos ) == false ) - continue; - - // Check to see if we can use this - if ( IsValidTransitionPoint( vecStartPos, vecEndPos ) ) - return nSequence; - } - - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: Reserve our exit point so nothing moves into it while we're moving -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PassengerBehavior::ReserveExitPoint( void ) -{ - // Cannot exit while we're upside down - // FIXME: This is probably redundant! - if ( m_hVehicle->IsOverturned() ) - return false; - - // Find the exit activity to use - int nSequence = FindExitSequence(); - if ( nSequence == -1 ) - return false; - - // Get the exit position - Vector vecGroundPos; - if ( GetExitPoint( nSequence, &vecGroundPos, &m_vecTargetAngles ) == false ) - return false; - - // We have to do this specially because the activities are not named - SetTransitionSequence( nSequence ); - - // Reserve this space - Vector hullMin = GetOuter()->GetHullMins(); - Vector hullMax = GetOuter()->GetHullMaxs(); - m_hBlocker = CEntityBlocker::Create( vecGroundPos, hullMin, hullMax, GetOuter(), true ); - - // Save this destination position so we can interpolate towards it - m_vecTargetPosition = vecGroundPos; - - // Pitch and roll must be zero when we finish! - m_vecTargetAngles.x = m_vecTargetAngles.z = 0.0f; - - if ( passenger_debug_transition.GetBool() ) - { - Vector vecForward; - AngleVectors( m_vecTargetAngles, &vecForward, NULL, NULL ); - Vector vecArrowEnd = m_vecTargetPosition + ( vecForward * 64.0f ); - NDebugOverlay::HorzArrow( m_vecTargetPosition, vecArrowEnd, 8.0f, 255, 255, 0, 64, true, 4.0f ); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Find the exact point we'd like to start our animation from to enter -// the vehicle. -//----------------------------------------------------------------------------- -bool CAI_PassengerBehavior::GetEntryPoint( int nSequence, Vector *vecEntryPoint, QAngle *vecEntryAngles ) -{ - bool bSucceeded = true; - - // Get the delta to the final position as will be dictated by this animation's auto movement - Vector vecDeltaPos; - QAngle vecDeltaAngles; - GetOuter()->GetSequenceMovement( nSequence, 1.0f, 0.0f, vecDeltaPos, vecDeltaAngles ); - - // Get the final position we're trying to end up at - Vector vecTargetPos; - QAngle vecTargetAngles; - GetEntryTarget( &vecTargetPos, &vecTargetAngles ); - - // Rotate it to match - Vector vecPreDelta = vecDeltaPos; - VectorRotate( vecPreDelta, vecTargetAngles, vecDeltaPos ); - - // Offset this into the proper worldspace position - vecTargetPos = vecTargetPos + vecDeltaPos; - - // Output the position, if requested - if ( vecEntryPoint != NULL ) - { - m_hVehicle->EntityToWorldSpace( vecTargetPos, vecEntryPoint ); - - // Trace down to the ground to see where we'll stand - Vector vecGroundPos; - if ( FindGroundAtPosition( (*vecEntryPoint), 16.0f, 64.0f, &vecGroundPos ) == false ) - { - // We failed - if ( passenger_debug_transition.GetBool() ) - { - NDebugOverlay::SweptBox( (*vecEntryPoint), vecGroundPos, GetOuter()->GetHullMins(), GetOuter()->GetHullMaxs(), vec3_angle, 255, 0, 0, 64, 2.0f ); - } - - // The floor could not be found - bSucceeded = false; - } - - // Take this position - *vecEntryPoint = vecGroundPos; - } - - // Output the angles, if requested - if ( vecEntryAngles != NULL ) - { - // Add our delta angles to find what angles to start at - *vecEntryAngles = vecTargetAngles; - vecEntryAngles->y = UTIL_AngleMod( vecTargetAngles.y + vecDeltaAngles.y ); - - //Transform those angles to worldspace - matrix3x4_t angToParent, angToWorld; - AngleMatrix( (*vecEntryAngles), angToParent ); - ConcatTransforms( m_hVehicle->EntityToWorldTransform(), angToParent, angToWorld ); - MatrixAngles( angToWorld, (*vecEntryAngles) ); - } - - // Debug info - if ( passenger_debug_transition.GetBool() && vecEntryPoint && vecEntryAngles ) - { - NDebugOverlay::Axis( *vecEntryPoint, vecTargetAngles, 16, true, 4.0f ); - NDebugOverlay::Cross3D( *vecEntryPoint, 4, 255, 255, 0, true, 4.0f ); - - if ( vecEntryAngles != NULL ) - { - Vector vecForward; - AngleVectors( (*vecEntryAngles), &vecForward, NULL, NULL ); - Vector vecArrowEnd = (*vecEntryPoint ) + ( vecForward * 64.0f ); - NDebugOverlay::HorzArrow( (*vecEntryPoint), vecArrowEnd, 8.0f, 0, 255, 0, 64, true, 4.0f ); - } - } - - return bSucceeded; -} - -//----------------------------------------------------------------------------- -// Purpose: Do the low-level work to detach us from our vehicle -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::DetachFromVehicle( void ) -{ - // Detach from the parent - GetOuter()->SetParent( NULL ); - GetOuter()->SetMoveType( MOVETYPE_STEP ); - GetOuter()->AddFlag( FL_FLY ); - GetOuter()->SetGroundEntity( NULL ); - GetOuter()->SetCollisionGroup( COLLISION_GROUP_NPC ); - m_hVehicle->RemovePhysicsChild( GetOuter() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::AttachToVehicle( void ) -{ - // Parent to the vehicle - GetOuter()->ClearForceCrouch(); - GetOuter()->SetParent( m_hVehicle ); - GetOuter()->AddFlag( FL_FLY ); - GetOuter()->SetGroundEntity( NULL ); - GetOuter()->SetCollisionGroup( COLLISION_GROUP_IN_VEHICLE ); - - // Turn off physical interactions while we're in the vehicle - IPhysicsObject *pPhysObj = GetOuter()->VPhysicsGetObject(); - if ( pPhysObj != NULL ) - { - pPhysObj->EnableCollisions( false ); - } - - // Set our destination target - GetEntryTarget( &m_vecTargetPosition, &m_vecTargetAngles ); - - // Get physics messages from our attached physics object - m_hVehicle->AddPhysicsChild( GetOuter() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Handle task starting -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::StartTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_PASSENGER_ENTER_VEHICLE: - { - // You must have set your entrance animation before this point! - Assert( m_nTransitionSequence != -1 ); - - // Start us playing the correct sequence - GetOuter()->SetIdealActivity( ACT_SCRIPT_CUSTOM_MOVE ); - SetPassengerState( PASSENGER_STATE_ENTERING ); - - // Overlaying any gestures will mess us up, so don't allow it - GetOuter()->RemoveAllGestures(); - } - break; - - case TASK_PASSENGER_EXIT_VEHICLE: - { - // You must have set your entrance animation before this point! - Assert( m_nTransitionSequence != -1 ); - - // Start us playing the correct sequence - GetOuter()->SetIdealActivity( ACT_SCRIPT_CUSTOM_MOVE ); - - // Overlaying any gestures will mess us up, so don't allow it - GetOuter()->RemoveAllGestures(); - } - break; - - case TASK_PASSENGER_ATTACH_TO_VEHICLE: - { - AttachToVehicle(); - TaskComplete(); - } - break; - - case TASK_PASSENGER_DETACH_FROM_VEHICLE: - { - // Place an entity blocker where we're going to go - if ( ReserveExitPoint() == false ) - { - OnExitVehicleFailed(); - TaskFail("Failed to find valid exit point\n"); - return; - } - - // Physically detach from the vehicle - DetachFromVehicle(); - - // Mark that we're now disembarking - SetPassengerState( PASSENGER_STATE_EXITING ); - - TaskComplete(); - } - break; - - case TASK_PASSENGER_SET_IDEAL_ENTRY_YAW: - { - // Get the ideal facing to enter the vehicle - QAngle vecEntryAngles; - GetEntryPoint( m_nTransitionSequence, NULL, &vecEntryAngles ); - GetOuter()->GetMotor()->SetIdealYaw( vecEntryAngles.y ); - - TaskComplete(); - return; - } - break; - - default: - BaseClass::StartTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Handle task running -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::RunTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_PASSENGER_ENTER_VEHICLE: - { - // Correct for angular/spatial deviation - Assert( GetSequence() == m_nTransitionSequence ); - if ( GetSequence() != m_nTransitionSequence ) - { - Warning("Corrected entrance animation on vehicle enter!\n"); - GetOuter()->SetIdealActivity( ACT_SCRIPT_CUSTOM_MOVE ); - GetOuter()->GetNavigator()->ClearGoal(); - SetTransitionSequence( m_nTransitionSequence ); - } - - bool corrected = DoTransitionMovement(); - - // We must be done with the animation and in the correct position - if ( corrected == false ) - { - FinishEnterVehicle(); - TaskComplete(); - } - } - break; - - case TASK_PASSENGER_EXIT_VEHICLE: - { - // Correct for angular/spatial deviation - Assert( GetSequence() == m_nTransitionSequence ); - if ( GetSequence() != m_nTransitionSequence ) - { - Warning("Corrected exit animation on vehicle exit!\n"); - GetOuter()->SetIdealActivity( ACT_SCRIPT_CUSTOM_MOVE ); - GetOuter()->GetNavigator()->ClearGoal(); - SetTransitionSequence( m_nTransitionSequence ); - } - - // Correct for angular/spatial deviation - bool corrected = DoTransitionMovement(); - - // We must be done with the animation and in the correct position - if ( corrected == false ) - { - FinishExitVehicle(); - TaskComplete(); - } - } - break; - - default: - BaseClass::RunTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Find the blend amounts for position and angles, given a point in -// time within a sequence -//----------------------------------------------------------------------------- -bool CAI_PassengerBehavior::GetSequenceBlendAmount( float flCycle, float *posBlend, float *angBlend ) -{ - // Find positional blend, if requested - if ( posBlend != NULL ) - { - float flFrac = RemapValClamped( flCycle, m_flOriginStartFrame, m_flOriginEndFrame, 0.0f, 1.0f ); - (*posBlend) = SimpleSpline( flFrac ); - } - - // Find angular blend, if requested - if ( angBlend != NULL ) - { - float flFrac = RemapValClamped( flCycle, m_flAnglesStartFrame, m_flAnglesEndFrame, 0.0f, 1.0f ); - (*angBlend) = SimpleSpline( flFrac ); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the target destination for the entry animation -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::GetEntryTarget( Vector *vecOrigin, QAngle *vecAngles ) -{ - // Get the ultimate position we'll end up at - m_hVehicle->GetServerVehicle()->NPC_GetPassengerSeatPositionLocal( GetOuter(), vecOrigin, vecAngles ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the ideal position to be in to end up at the target at the -// end of the animation. -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::GetTransitionAnimationIdeal( float flCycle, const Vector &vecTargetPos, const QAngle &vecTargetAngles, Vector *idealOrigin, QAngle *idealAngles ) -{ - // Get the position in time working backwards from our goal - Vector vecDeltaPos; - QAngle vecDeltaAngles; - GetOuter()->GetSequenceMovement( GetSequence(), 1.0f, flCycle, vecDeltaPos, vecDeltaAngles ); - - // Rotate the delta by our local angles - Vector vecPreDelta = vecDeltaPos; - VectorRotate( vecPreDelta, vecTargetAngles, vecDeltaPos ); - - // Ideal origin - if ( idealOrigin != NULL ) - { - *idealOrigin = ( vecTargetPos + vecDeltaPos ); - } - - // Ideal angles - if ( idealAngles != NULL ) - { - (*idealAngles).x = anglemod( vecTargetAngles.x + vecDeltaAngles.x ); - (*idealAngles).y = anglemod( vecTargetAngles.y + vecDeltaAngles.y ); - (*idealAngles).z = anglemod( vecTargetAngles.z + vecDeltaAngles.z ); - } -} - -//----------------------------------------------------------------------------- -// FIXME: This is basically a complete duplication of GetIntervalMovement -// which doesn't remove the x and z components of the angles. This -// should be consolidated to not replicate so much code! -- jdw -//----------------------------------------------------------------------------- -bool CAI_PassengerBehavior::LocalIntervalMovement( float flInterval, bool &bMoveSeqFinished, Vector &newPosition, QAngle &newAngles ) -{ - CStudioHdr *pstudiohdr = GetOuter()->GetModelPtr(); - if ( pstudiohdr == NULL ) - return false; - - // Get our next cycle point - float flNextCycle = GetNextCycleForInterval( GetSequence(), flInterval ); - - // Fix-up loops - if ( ( GetOuter()->SequenceLoops() == false ) && flNextCycle > 1.0f ) - { - flInterval = GetOuter()->GetCycle() / ( GetOuter()->GetSequenceCycleRate( GetSequence() ) * GetOuter()->GetPlaybackRate() ); - flNextCycle = 1.0f; - bMoveSeqFinished = true; - } - else - { - bMoveSeqFinished = false; - } - - Vector deltaPos; - QAngle deltaAngles; - - // Find the delta position and delta angles for this sequence - if ( Studio_SeqMovement( pstudiohdr, GetOuter()->GetSequence(), GetOuter()->GetCycle(), flNextCycle, GetOuter()->GetPoseParameterArray(), deltaPos, deltaAngles )) - { - Vector vecPreDelta = deltaPos; - VectorRotate( vecPreDelta, GetOuter()->GetLocalAngles(), deltaPos ); - - newPosition = GetLocalOrigin() + deltaPos; - newAngles = GetLocalAngles() + deltaAngles; - - return true; - } - else - { - newPosition = GetLocalOrigin(); - newAngles = GetLocalAngles(); - - return false; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Get the next cycle point in a sequence for a given interval -//----------------------------------------------------------------------------- -float CAI_PassengerBehavior::GetNextCycleForInterval( int nSequence, float flInterval ) -{ - return GetOuter()->GetCycle() + flInterval * GetOuter()->GetSequenceCycleRate( GetSequence() ) * GetOuter()->GetPlaybackRate(); -} - -//----------------------------------------------------------------------------- -// Purpose: Draw debug information for the transitional movement -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::DrawDebugTransitionInfo( const Vector &vecIdealPos, const QAngle &vecIdealAngles, const Vector &vecAnimPos, const QAngle &vecAnimAngles ) -{ - // Debug info - if ( GetPassengerState() == PASSENGER_STATE_ENTERING ) - { - // Green - Ideal location - Vector foo; - m_hVehicle->EntityToWorldSpace( vecIdealPos, &foo ); - NDebugOverlay::Cross3D( foo, 2, 0, 255, 0, true, 0.1f ); - NDebugOverlay::Axis( foo, vecIdealAngles, 8, true, 0.1f ); - - // Blue - Actual location - m_hVehicle->EntityToWorldSpace( vecAnimPos, &foo ); - NDebugOverlay::Cross3D( foo, 2, 0, 0, 255, true, 0.1f ); - NDebugOverlay::Axis( foo, vecAnimAngles, 8, true, 0.1f ); - } - else - { - // Green - Ideal location - NDebugOverlay::Cross3D( vecIdealPos, 4, 0, 255, 0, true, 0.1f ); - NDebugOverlay::Axis( vecIdealPos, vecIdealAngles, 8, true, 0.1f ); - - // Blue - Actual location - NDebugOverlay::Cross3D( vecAnimPos, 2, 0, 0, 255, true, 0.1f ); - NDebugOverlay::Axis( vecAnimPos, vecAnimAngles, 8, true, 0.1f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Local movement to enter or exit the vehicle -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PassengerBehavior::DoTransitionMovement( void ) -{ - // Get our animation's extrapolated end position - Vector vecAnimPos; - QAngle vecAnimAngles; - float flInterval = GetOuter()->GetAnimTimeInterval(); - bool bSequenceFinished; - - // Get the position we're moving to for this frame with our animation's motion - if ( LocalIntervalMovement( flInterval, bSequenceFinished, vecAnimPos, vecAnimAngles ) ) - { - // Get the position we'd ideally be in - Vector vecIdealPos; - QAngle vecIdealAngles; - float flNextCycle = GetNextCycleForInterval( GetOuter()->GetSequence(), flInterval ); - flNextCycle = clamp( flNextCycle, 0.0f, 1.0f ); - GetTransitionAnimationIdeal( flNextCycle, m_vecTargetPosition, m_vecTargetAngles, &vecIdealPos, &vecIdealAngles ); - - // Get the amount of error to blend out - float flPosBlend = 1.0f; - float flAngBlend = 1.0f; - GetSequenceBlendAmount( flNextCycle, &flPosBlend, &flAngBlend ); - - // Find the error between our position and our ideal - Vector vecDelta = ( vecIdealPos - vecAnimPos ) * flPosBlend; - - QAngle vecDeltaAngles; - vecDeltaAngles.x = AngleDiff( vecIdealAngles.x, vecAnimAngles.x ) * flAngBlend; - vecDeltaAngles.y = AngleDiff( vecIdealAngles.y, vecAnimAngles.y ) * flAngBlend; - vecDeltaAngles.z = AngleDiff( vecIdealAngles.z, vecAnimAngles.z ) * flAngBlend; - - // Factor in the error - GetOuter()->SetLocalOrigin( vecAnimPos + vecDelta ); - GetOuter()->SetLocalAngles( vecAnimAngles + vecDeltaAngles ); - - // Draw our debug information - if ( passenger_debug_transition.GetBool() ) - { - DrawDebugTransitionInfo( vecIdealPos, vecIdealAngles, vecAnimPos, vecAnimAngles ); - } - - // We're done moving - if ( bSequenceFinished ) - return false; - - // We're still correcting out the error - return true; - } - - // There was no movement in the animation - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Translate normal schedules into vehicle schedules -//----------------------------------------------------------------------------- -int CAI_PassengerBehavior::TranslateSchedule( int scheduleType ) -{ - if ( GetPassengerState() == PASSENGER_STATE_INSIDE ) - { - // Always be seated when riding in the car! - if ( scheduleType == SCHED_IDLE_STAND ) - return SCHED_PASSENGER_IDLE; - } - - return BaseClass::TranslateSchedule( scheduleType ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the velocity of the vehicle with respect to its orientation -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::GetLocalVehicleVelocity( Vector *pOut ) -{ - Vector velocity; - m_hVehicle->GetVelocity( &velocity, NULL ); - m_hVehicle->WorldToEntitySpace( m_hVehicle->GetAbsOrigin() + velocity, pOut ); -} - -//----------------------------------------------------------------------------- -// Purpose: Gather conditions we can comment on or react to while riding in the vehicle -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::GatherVehicleStateConditions( void ) -{ - // Must have a vehicle to bother with this - if ( m_hVehicle == NULL ) - return; - - // Clear out transient conditions - ClearCondition( COND_PASSENGER_HARD_IMPACT ); - ClearCondition( COND_PASSENGER_ERRATIC_DRIVING ); - ClearCondition( COND_PASSENGER_JOSTLE_SMALL ); - ClearCondition( COND_PASSENGER_VEHICLE_STARTED ); - ClearCondition( COND_PASSENGER_VEHICLE_STOPPED ); - ClearCondition( COND_PASSENGER_PLAYER_ENTERED_VEHICLE ); - ClearCondition( COND_PASSENGER_PLAYER_EXITED_VEHICLE ); - - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer ) - { - if ( pPlayer->IsInAVehicle() && pPlayer->GetVehicle() == m_hVehicle->GetServerVehicle() ) - { - if ( m_vehicleState.m_bPlayerInVehicle == false ) - { - SetCondition( COND_PASSENGER_PLAYER_ENTERED_VEHICLE ); - m_vehicleState.m_bPlayerInVehicle = true; - } - } - else - { - if ( m_vehicleState.m_bPlayerInVehicle ) - { - SetCondition( COND_PASSENGER_PLAYER_EXITED_VEHICLE ); - m_vehicleState.m_bPlayerInVehicle = false; - } - } - } - - // Get the vehicle's boost state - if ( m_hVehicle->m_nBoostTimeLeft < 100.0f ) - { - if ( m_vehicleState.m_bWasBoosting == false ) - { - m_vehicleState.m_bWasBoosting = true; - } - } - else - { - m_vehicleState.m_bWasBoosting = false; - } - - // Detect being overturned - if ( m_hVehicle->IsOverturned() ) - { - SetCondition( COND_PASSENGER_OVERTURNED ); - - if ( m_vehicleState.m_bWasOverturned == false ) - { - m_vehicleState.m_bWasOverturned = true; - } - } - else - { - ClearCondition( COND_PASSENGER_OVERTURNED ); - m_vehicleState.m_bWasOverturned = false; - } - - // Get our local velocity - Vector localVelocity; - GetLocalVehicleVelocity( &localVelocity ); - - Vector deltaVelocity = ( localVelocity - m_vehicleState.m_vecLastLocalVelocity ); - - // Detect a sudden stop! - if ( deltaVelocity.y < passenger_impact_response_threshold.GetFloat() ) - { - SetCondition( COND_PASSENGER_HARD_IMPACT ); - } - else if ( fabs( deltaVelocity.x ) > 200.0f || fabs( deltaVelocity.z ) > 75.0f ) - { - // The X axis represents lateral movement and the Z axis represents vertical movement{ - SetCondition( COND_PASSENGER_ERRATIC_DRIVING ); - } - else if ( fabs( deltaVelocity.x ) > 50.0f || fabs( deltaVelocity.z ) > 25.0f ) - { - // Lightly jostled - SetCondition( COND_PASSENGER_JOSTLE_SMALL ); - } - - // Get our speed - float flSpeedSqr = localVelocity.LengthSqr(); - - // See if we've crossed over the threshold between movement to stillness - if ( m_vehicleState.m_flLastSpeedSqr > STOPPED_VELOCITY_THRESHOLD_SQR && flSpeedSqr < STOPPED_VELOCITY_THRESHOLD_SQR ) - { - SetCondition( COND_PASSENGER_VEHICLE_STOPPED ); - } - else if ( m_vehicleState.m_flLastSpeedSqr < STARTED_VELOCITY_THRESHOLD_SQR && flSpeedSqr > STARTED_VELOCITY_THRESHOLD_SQR ) - { - // See if we've crossed over the threshold between stillness to movement - SetCondition( COND_PASSENGER_VEHICLE_STARTED ); - } - - // Save this as our last speed - m_vehicleState.m_flLastSpeedSqr = flSpeedSqr; - - // Find our delta velocity from the last frame - m_vehicleState.m_vecDeltaVelocity = ( localVelocity - m_vehicleState.m_vecLastLocalVelocity ); - m_vehicleState.m_vecLastLocalVelocity = localVelocity; - - // Get our angular velocity - Vector vecVelocity; - AngularImpulse angVelocty; - m_hVehicle->GetVelocity( &vecVelocity, &angVelocty ); - QAngle angVel( angVelocty.x, angVelocty.y, angVelocty.z ); - - // Blend this into the old values - m_vehicleState.m_vecLastAngles = ( m_vehicleState.m_vecLastAngles * 0.2f ) + ( angVel * 0.8f ); -} - -//----------------------------------------------------------------------------- -// Purpose: Do some pre-schedule clean-up -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::PrescheduleThink( void ) -{ - BaseClass::PrescheduleThink(); - - // If we're outside the vehicle, we need to turn this behavior off immediately - if ( GetPassengerState() == PASSENGER_STATE_OUTSIDE && HasCondition( COND_PASSENGER_CANCEL_ENTER ) ) - { - // Clear out our passenger intent - m_PassengerIntent = PASSENGER_INTENT_NONE; - ClearCondition( COND_PASSENGER_CANCEL_ENTER ); - - // Stop pathfinding - GetOuter()->GetNavigator()->ClearGoal(); - - // We're outside and have no intent to enter, so we're done - Disable(); - - // This must be stomped to cause our behavior to relinquish control - GetOuter()->ClearSchedule("Passenger enter canceled"); - } - -#ifdef DEBUG - if ( GetPassengerState() == PASSENGER_STATE_INSIDE ) - { - Vector vecSeatOrigin; - QAngle vecSeatAngles; - if ( m_hVehicle && m_hVehicle->GetServerVehicle()->NPC_GetPassengerSeatPositionLocal( GetOuter(), &vecSeatOrigin, &vecSeatAngles ) ) - { - if ( ( GetLocalOrigin() - vecSeatOrigin ).LengthSqr() > Square( 0.1f ) ) - { - Warning( "Passenger has strayed from seat position!\n" ); - // GetOuter()->SetLocalOrigin( vecSeatOrigin ); - // GetOuter()->SetLocalAngles( vecSeatAngles ); - } - } - else - { - Warning( "Passenger is in vehicle without a valid seat position! -- EJECTED\n" ); - GetOuter()->SetParent( NULL ); - Disable(); - - return; - } - } -#endif // DEBUG -} - -//----------------------------------------------------------------------------- -// Purpose: Gather conditions for our use in making decisions -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::GatherConditions( void ) -{ - if ( IsEnabled() == false ) - return BaseClass::GatherConditions(); - - // Sense the state of the car - GatherVehicleStateConditions(); - - BaseClass::GatherConditions(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::ModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet ) -{ - if ( m_hVehicle == NULL ) - return; - - // Mark whether we're overturned or not - bool bOverturned = m_hVehicle->IsOverturned(); - criteriaSet.AppendCriteria( "vehicle_overturned", bOverturned ? "1" : "0" ); - - // Denote whether we're in the vehicle or not - bool bInsideVehicle = ( GetPassengerState() == PASSENGER_STATE_INSIDE ); - criteriaSet.AppendCriteria( "vehicle_inside", bInsideVehicle ? "1" : "0" ); - - // Note what angle we're at (extreme or normal) - Vector vecUp( 0.0f, 0.0f, 1.0f ); - Vector vecVehicleUp; - m_hVehicle->GetVectors( NULL, NULL, &vecVehicleUp ); - - float flVehicleUp = DotProduct( vecVehicleUp, vecUp ); - criteriaSet.AppendCriteria( "vehicle_tilt", UTIL_VarArgs( "%.2f", flVehicleUp ) ); - - // Set the vehicle's speed (necessary for certain types of movement judgments) - float flVehicleSpeed = sqrt( m_vehicleState.m_flLastSpeedSqr ); - criteriaSet.AppendCriteria( "vehicle_speed", UTIL_VarArgs( "%f", flVehicleSpeed ) ); - - // Whether or not the passenger is currently able to enter the vehicle (only accounts for locking really) - bool bCanExitVehicle = ( m_hVehicle->NPC_CanExitVehicle( GetOuter(), true ) ); - criteriaSet.AppendCriteria( "vehicle_can_exit", bCanExitVehicle ? "1" : "0" ); - - // Whether or not the passenger is currently able to exit the vehicle (only accounts for locking really) - bool bCanEnterVehicle = ( m_hVehicle->NPC_CanEnterVehicle( GetOuter(), true ) ); - criteriaSet.AppendCriteria( "vehicle_can_enter", bCanEnterVehicle ? "1" : "0" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Cache off our frame numbers from the sequence keyvalue blocks -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::CacheBlendTargets( void ) -{ - // Get the keyvalues for this sequence - KeyValues *seqValues = GetOuter()->GetSequenceKeyValues( m_nTransitionSequence ); - if ( seqValues == NULL ) - { - Assert( 0 ); - return; - } - - // Get the entry/exit subkeys - KeyValues *blendValues = seqValues->FindKey( "entryexit_blend" ); - if ( blendValues == NULL ) - { - Assert( 0 ); - return; - } - - // Find our frame range on this sequence - int nMaxFrames = Studio_MaxFrame( GetOuter()->GetModelPtr(), m_nTransitionSequence, GetOuter()->GetPoseParameterArray() ); - - // Find a key by this name - KeyValues *subKeys = blendValues->FindKey( ORIGIN_KEYNAME ); - if ( subKeys ) - { - // Retrieve our frame numbers - m_flOriginStartFrame = subKeys->GetFloat( "startframe", 0.0f ); - m_flOriginEndFrame = subKeys->GetFloat( "endframe", nMaxFrames ); - - // Convert to normalized values - m_flOriginStartFrame = RemapValClamped( m_flOriginStartFrame, 0, nMaxFrames, 0.0f, 1.0f ); - m_flOriginEndFrame = RemapValClamped( m_flOriginEndFrame, 0, nMaxFrames, 0.0f, 1.0f ); - } - - // Find a key by this name - subKeys = blendValues->FindKey( ANGLES_KEYNAME ); - if ( subKeys ) - { - // Retrieve our frame numbers - m_flAnglesStartFrame = subKeys->GetFloat( "startframe", 0.0f ); - m_flAnglesEndFrame = subKeys->GetFloat( "endframe", nMaxFrames ); - - // Convert to normalized values - m_flAnglesStartFrame = RemapValClamped( m_flAnglesStartFrame, 0, nMaxFrames, 0.0f, 1.0f ); - m_flAnglesEndFrame = RemapValClamped( m_flAnglesEndFrame, 0, nMaxFrames, 0.0f, 1.0f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::SetTransitionSequence( int nSequence ) -{ - // We need to use the ACT_SCRIPT_CUSTOM_MOVE scenario for this type of custom anim - m_nTransitionSequence = nSequence; - GetOuter()->m_iszSceneCustomMoveSeq = AllocPooledString( GetOuter()->GetSequenceName( m_nTransitionSequence ) ); - - // Cache off our blending information at this point - CacheBlendTargets(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_PassengerBehavior::SpeakIfAllowed( AIConcept_t concept, const char *modifiers /*= NULL*/, bool bRespondingToPlayer /*= false*/, char *pszOutResponseChosen /*= NULL*/, size_t bufsize /*= 0*/ ) -{ - // FIXME: Store this cast off? - CAI_PlayerAlly *pAlly = dynamic_cast(GetOuter()); - if ( pAlly != NULL ) - return pAlly->SpeakIfAllowed( concept, modifiers, bRespondingToPlayer, pszOutResponseChosen, bufsize ); - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Forces us to begin a dynamic scripted scene -// Input : *lpszInteractionName - Name of the sequence we'll play -// *pOther - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PassengerBehavior::ForceVehicleInteraction( const char *lpszInteractionName, CBaseCombatCharacter *pOther ) -{ - // Don't do this unless we're sitting in the cabin of the vehicle! - if ( GetPassengerState() != PASSENGER_STATE_INSIDE ) - return false; - - // Set a sequence and fire it off! - GetOuter()->m_iszSceneCustomMoveSeq = AllocPooledString( lpszInteractionName ); - GetOuter()->SetIdealActivity( ACT_SCRIPT_CUSTOM_MOVE ); - - // Slam our schedule (very unsafe!) - GetOuter()->SetSchedule( SCHED_PASSENGER_PLAY_SCRIPTED_ANIM ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Fix up teleport event when in the vehicle -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ) -{ - //First, safely remove me from the vehicle - if ( GetPassengerState() != PASSENGER_STATE_OUTSIDE ) - { - // Detach from the vehicle - DetachFromVehicle(); - FinishExitVehicle(); - - // Turn the behavior off - GetOuter()->ClearSchedule( "ai_behavior_passenger: teleport while in vehicle" ); - Disable(); - } - - //Then allow the teleportation - BaseClass::Teleport( newPosition, newAngles, newVelocity ); -} - -//----------------------------------------------------------------------------- -// Purpose: We override this function because it can completely wreak havoc if -// we're in the middle of a transition -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::ClearSchedule( const char *szReason ) -{ - // Cannot do this while we're transitioning, but it's also a bug because the code that called it was probably relying on this to work! - if ( GetPassengerState() == PASSENGER_STATE_ENTERING || GetPassengerState() == PASSENGER_STATE_EXITING ) - { - Warning("ClearSchedule rejected due to transitioning passenger: %s\n", szReason ); - return; - } - - // TODO: Even this will probably need more crafting depending on what we're doing in the vehicle - // Otherwise allow it - GetOuter()->ClearSchedule( szReason ); -} - -//----------------------------------------------------------------------------- -// Purpose: Dictate the terms for being interrupted by scripted schedules or scenes -//----------------------------------------------------------------------------- -bool CAI_PassengerBehavior::IsInterruptable( void ) -{ - // NOTE: We should never be interrupted this way when in a car. This would effectively makes us go comatose if we - // start a FACETO, MOVETO, or SEQUENCE command from a VCD. - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PassengerBehavior::CancelEnterVehicle( void ) -{ - // Stop! - if ( GetPassengerState() == PASSENGER_STATE_OUTSIDE ) - { - SetCondition( COND_PASSENGER_CANCEL_ENTER ); - } -} - -// ---------------------------------------------- -// Custom AI declarations -// ---------------------------------------------- - -AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( CAI_PassengerBehavior ) -{ - DECLARE_ACTIVITY( ACT_PASSENGER_IDLE ) - DECLARE_ACTIVITY( ACT_PASSENGER_RANGE_ATTACK1 ) - - DECLARE_CONDITION( COND_PASSENGER_HARD_IMPACT ) - DECLARE_CONDITION( COND_PASSENGER_ENTERING ) - DECLARE_CONDITION( COND_PASSENGER_EXITING ) - DECLARE_CONDITION( COND_PASSENGER_VEHICLE_STARTED ) - DECLARE_CONDITION( COND_PASSENGER_VEHICLE_STOPPED ) - DECLARE_CONDITION( COND_PASSENGER_OVERTURNED ) - DECLARE_CONDITION( COND_PASSENGER_CANCEL_ENTER ) - DECLARE_CONDITION( COND_PASSENGER_ERRATIC_DRIVING ) - DECLARE_CONDITION( COND_PASSENGER_PLAYER_ENTERED_VEHICLE ) - DECLARE_CONDITION( COND_PASSENGER_PLAYER_EXITED_VEHICLE ) - DECLARE_CONDITION( COND_PASSENGER_JOSTLE_SMALL ) - - DECLARE_TASK( TASK_PASSENGER_ENTER_VEHICLE ) - DECLARE_TASK( TASK_PASSENGER_EXIT_VEHICLE ) - DECLARE_TASK( TASK_PASSENGER_ATTACH_TO_VEHICLE ) - DECLARE_TASK( TASK_PASSENGER_DETACH_FROM_VEHICLE ) - DECLARE_TASK( TASK_PASSENGER_SET_IDEAL_ENTRY_YAW ) - - // FIXME: Move to companion - DEFINE_SCHEDULE - ( - SCHED_PASSENGER_ENTER_VEHICLE, - - " Tasks" - " TASK_PASSENGER_SET_IDEAL_ENTRY_YAW 0" - " TASK_FACE_IDEAL 0" - " TASK_PASSENGER_ATTACH_TO_VEHICLE 0" - " TASK_PASSENGER_ENTER_VEHICLE 0" - "" - " Interrupts" - " COND_NO_CUSTOM_INTERRUPTS" - ) - - DEFINE_SCHEDULE - ( - SCHED_PASSENGER_EXIT_VEHICLE, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_PASSENGER_IDLE" - " TASK_PASSENGER_DETACH_FROM_VEHICLE 0" - " TASK_WAIT 0.1" // We must wait one tick for us to start being updated - " TASK_PASSENGER_EXIT_VEHICLE 0" - "" - " Interrupts" - " COND_NO_CUSTOM_INTERRUPTS" - " COND_TASK_FAILED" - ) - - DEFINE_SCHEDULE - ( - SCHED_PASSENGER_IDLE, - - " Tasks" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT 2" - "" - " Interrupts" - " COND_PROVOKED" - " COND_NEW_ENEMY" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_MELEE_ATTACK1" - " COND_PASSENGER_EXITING" - " COND_HEAR_DANGER" - ) - - DEFINE_SCHEDULE - ( - SCHED_PASSENGER_PLAY_SCRIPTED_ANIM, - - " Tasks" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_SCRIPT_CUSTOM_MOVE" - "" - " Interrupts" - " COND_PASSENGER_HARD_IMPACT" - ) - - AI_END_CUSTOM_SCHEDULE_PROVIDER() -} diff --git a/game/server/ai_behavior_passenger.h b/game/server/ai_behavior_passenger.h deleted file mode 100644 index 2a83e0e8a..000000000 --- a/game/server/ai_behavior_passenger.h +++ /dev/null @@ -1,245 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef AI_BEHAVIOR_PASSENGER_H -#define AI_BEHAVIOR_PASSENGER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_speech.h" -#include "ai_behavior.h" -#include "ai_utils.h" -#include "vehicle_jeep_episodic.h" - -#define STOPPED_VELOCITY_THRESHOLD 32.0f -#define STOPPED_VELOCITY_THRESHOLD_SQR (STOPPED_VELOCITY_THRESHOLD*STOPPED_VELOCITY_THRESHOLD) - -#define STARTED_VELOCITY_THRESHOLD 64.0f -#define STARTED_VELOCITY_THRESHOLD_SQR (STARTED_VELOCITY_THRESHOLD*STARTED_VELOCITY_THRESHOLD) - -// Custom activities -extern int ACT_PASSENGER_IDLE; -extern int ACT_PASSENGER_RANGE_ATTACK1; - -// --------------------------------------------- -// Vehicle state -// --------------------------------------------- -struct passengerVehicleState_t -{ - Vector m_vecLastLocalVelocity; - Vector m_vecDeltaVelocity; - QAngle m_vecLastAngles; - float m_flNextWarningTime; - float m_flLastSpeedSqr; - bool m_bPlayerInVehicle; - bool m_bWasBoosting; - bool m_bWasOverturned; - - DECLARE_SIMPLE_DATADESC(); -}; - -// --------------------------------------------- -// Passenger intent -// --------------------------------------------- -enum passesngerVehicleIntent_e -{ - PASSENGER_INTENT_NONE, - PASSENGER_INTENT_ENTER, // We want to be in the vehicle - PASSENGER_INTENT_EXIT, // We want to be outside the vehicle -}; - -// --------------------------------------------- -// Passenger state functions -// --------------------------------------------- -enum PassengerState_e -{ - PASSENGER_STATE_OUTSIDE = 0, // Not in the vehicle - PASSENGER_STATE_ENTERING, - PASSENGER_STATE_INSIDE, - PASSENGER_STATE_EXITING, -}; - -class CAI_PassengerBehavior : public CAI_SimpleBehavior -{ - DECLARE_CLASS( CAI_PassengerBehavior, CAI_SimpleBehavior ); - DECLARE_DATADESC() - -public: - - CAI_PassengerBehavior( void ); - - enum - { - // Schedules - SCHED_PASSENGER_IDLE = BaseClass::NEXT_SCHEDULE, - SCHED_PASSENGER_ENTER_VEHICLE, - SCHED_PASSENGER_EXIT_VEHICLE, - SCHED_PASSENGER_RUN_TO_ENTER_VEHICLE, - SCHED_PASSENGER_ENTER_VEHICLE_PAUSE, - SCHED_PASSENGER_RUN_TO_ENTER_VEHICLE_FAILED, - SCHED_PASSENGER_PLAY_SCRIPTED_ANIM, - NEXT_SCHEDULE, - - // Tasks - TASK_PASSENGER_ENTER_VEHICLE = BaseClass::NEXT_TASK, - TASK_PASSENGER_EXIT_VEHICLE, - TASK_PASSENGER_ATTACH_TO_VEHICLE, - TASK_PASSENGER_DETACH_FROM_VEHICLE, - TASK_PASSENGER_SET_IDEAL_ENTRY_YAW, - NEXT_TASK, - - // Conditions - COND_PASSENGER_HARD_IMPACT = BaseClass::NEXT_CONDITION, - COND_PASSENGER_ENTERING, - COND_PASSENGER_EXITING, - COND_PASSENGER_VEHICLE_STARTED, - COND_PASSENGER_VEHICLE_STOPPED, - COND_PASSENGER_OVERTURNED, - COND_PASSENGER_CANCEL_ENTER, - COND_PASSENGER_ERRATIC_DRIVING, - COND_PASSENGER_PLAYER_ENTERED_VEHICLE, - COND_PASSENGER_PLAYER_EXITED_VEHICLE, - COND_PASSENGER_JOSTLE_SMALL, - - NEXT_CONDITION - }; - - bool ForceVehicleInteraction( const char *lpszInteractionName, CBaseCombatCharacter *pOther ); - - virtual bool CanSelectSchedule( void ); - virtual int SelectSchedule( void ); - virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ); - virtual void RunTask( const Task_t *pTask ); - virtual void StartTask( const Task_t *pTask ); - virtual void BuildScheduleTestBits( void ); - virtual int TranslateSchedule( int scheduleType ); - virtual void GetEntryTarget( Vector *vecOrigin, QAngle *vecAngles ); - virtual void GatherConditions( void ); - virtual void ModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet ); - virtual void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ); - virtual void ClearSchedule( const char *szReason ); - virtual bool IsInterruptable( void ); - virtual void PrescheduleThink( void ); - virtual void CancelEnterVehicle( void ); - - virtual const char *GetName( void ) { return "Passenger"; } - virtual string_t GetRoleName( void ) { return MAKE_STRING( "passenger" ); } - - // Enable/disable code - void Enable( CPropJeepEpisodic *pVehicle, bool bImmediateEntrance = false ); - void Disable( void ); - bool IsEnabled( void ) const { return m_bEnabled; } - - virtual void EnterVehicle( void ); - virtual void ExitVehicle( void ); - - void AddPhysicsPush( float force ); - - CPropVehicleDriveable *GetTargetVehicle( void ) const { return m_hVehicle; } - - PassengerState_e GetPassengerState( void ) const { return m_PassengerState; } - - virtual void OnRestore(); - -protected: - - virtual int SelectTransitionSchedule( void ); - - bool SpeakIfAllowed( AIConcept_t concept, const char *modifiers = NULL, bool bRespondingToPlayer = false, char *pszOutResponseChosen = NULL, size_t bufsize = 0 ); - - bool CanExitVehicle( void ); - void SetTransitionSequence( int nSequence ); - void AttachToVehicle( void ); - - virtual void OnExitVehicleFailed( void ) { } // NPC attempted to leave vehicle, but was unable to - virtual void GatherVehicleStateConditions( void ); - - // ------------------------------------------ - // Entry/exit transition code - // ------------------------------------------ - - virtual void FinishEnterVehicle( void ); - virtual void FinishExitVehicle( void ); - - void DetachFromVehicle( void ); - void DrawDebugTransitionInfo( const Vector &vecIdealPos, const QAngle &vecIdealAngles, const Vector &vecAnimPos, const QAngle &vecAnimAngles ); - bool GetEntryPoint( int nSequence, Vector *vecEntryPoint, QAngle *vecEntryAngles = NULL ); - bool GetExitPoint( int nSequence, Vector *vecExitPoint, QAngle *vecExitAngles = NULL ); - bool PointIsNavigable( const Vector &vecTargetPos ); - bool ReserveEntryPoint( VehicleSeatQuery_e eSeatSearchType ); - bool ReserveExitPoint( void ); - bool FindGroundAtPosition( const Vector &in, float flUpDelta, float flDownDelta, Vector *out ); - bool DoTransitionMovement( void ); - bool GetSequenceBlendAmount( float flCycle, float *posBlend, float *angBlend ); - bool LocalIntervalMovement( float flInterval, bool &bMoveSeqFinished, Vector &newPosition, QAngle &newAngles ); - void GetTransitionAnimationIdeal( float flCycle, const Vector &vecTargetPos, const QAngle &vecTargetAngles, Vector *idealOrigin, QAngle *idealAngles ); - float GetNextCycleForInterval( int nSequence, float flInterval ); - void GetLocalVehicleVelocity( Vector *pOut ); - void CacheBlendTargets( void ); - - void InitVehicleState( void ); - int FindEntrySequence( bool bNearest = false ); - int FindExitSequence( void ); - bool IsValidTransitionPoint( const Vector &vecStartPos, const Vector &vecEndPos ); - - void SetPassengerState( PassengerState_e state ) { m_PassengerState = state; } - - PassengerState_e m_PassengerState; // State we're in, for the vehicle - - // --------------------------------------------- - - bool IsPassengerHostile( void ); - - passengerVehicleState_t m_vehicleState; // Internal vehicle state - - CHandle m_hVehicle; // The vehicle we're bound to - CHandle m_hBlocker; // Blocking entity for space reservation - Vector m_vecTargetPosition; // Target destination for exiting the vehicle - QAngle m_vecTargetAngles; // Target angles for exiting the vehicle - bool m_bEnabled; // If the behavior is running - passesngerVehicleIntent_e m_PassengerIntent; // Gives us information about whether we're meant to get in/out, etc. - - int m_nTransitionSequence; // Animation we're using to transition with - float m_flOriginStartFrame; - float m_flOriginEndFrame; - float m_flAnglesStartFrame; - float m_flAnglesEndFrame; - -protected: - DEFINE_CUSTOM_SCHEDULE_PROVIDER; -}; - -class CTraceFilterVehicleTransition : public CTraceFilterSkipTwoEntities -{ -public: - DECLARE_CLASS( CTraceFilterVehicleTransition, CTraceFilterSkipTwoEntities ); - - CTraceFilterVehicleTransition( const IHandleEntity *passentity, const IHandleEntity *passentity2, int collisionGroup ) : - CTraceFilterSkipTwoEntities( passentity, passentity2, collisionGroup ) {} - - bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ) - { - bool bRet = BaseClass::ShouldHitEntity( pServerEntity, contentsMask ); - - CBaseEntity *pEntity = EntityFromEntityHandle( pServerEntity ); - if ( pEntity ) - { - IPhysicsObject *pPhys = pEntity->VPhysicsGetObject(); - if ( pPhys ) - { - // Ignore physics objects - // TODO: This will have to be fleshed out more as cases arise - if ( pPhys->IsMoveable() && pPhys->GetMass() < 80.0f ) - return false; - } - } - - return bRet; - } -}; - -#endif // AI_BEHAVIOR_PASSENGER_H diff --git a/game/server/ai_behavior_rappel.cpp b/game/server/ai_behavior_rappel.cpp deleted file mode 100644 index e1542ce22..000000000 --- a/game/server/ai_behavior_rappel.cpp +++ /dev/null @@ -1,459 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "ai_motor.h" -#include "ai_behavior_rappel.h" -#include "beam_shared.h" -#include "rope.h" -#include "eventqueue.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -BEGIN_DATADESC( CAI_RappelBehavior ) - DEFINE_FIELD( m_bWaitingToRappel, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bOnGround, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hLine, FIELD_EHANDLE ), - DEFINE_FIELD( m_vecRopeAnchor, FIELD_POSITION_VECTOR ), -END_DATADESC(); - -//========================================================= -//========================================================= -class CRopeAnchor : public CPointEntity -{ - DECLARE_CLASS( CRopeAnchor, CPointEntity ); - -public: - void Spawn( void ); - void FallThink( void ); - void RemoveThink( void ); - EHANDLE m_hRope; - - DECLARE_DATADESC(); -}; - -BEGIN_DATADESC( CRopeAnchor ) - DEFINE_FIELD( m_hRope, FIELD_EHANDLE ), - - DEFINE_THINKFUNC( FallThink ), - DEFINE_THINKFUNC( RemoveThink ), -END_DATADESC(); - -LINK_ENTITY_TO_CLASS( rope_anchor, CRopeAnchor ); - -//--------------------------------------------------------- -//--------------------------------------------------------- -#define RAPPEL_ROPE_WIDTH 1 -void CRopeAnchor::Spawn() -{ - BaseClass::Spawn(); - - // Decent enough default in case something happens to our owner! - float flDist = 384.0f; - - if( GetOwnerEntity() ) - { - flDist = fabs( GetOwnerEntity()->GetAbsOrigin().z - GetAbsOrigin().z ); - } - - m_hRope = CRopeKeyframe::CreateWithSecondPointDetached( this, -1, (int)flDist, RAPPEL_ROPE_WIDTH, "cable/cable.vmt", 5, true ); - - ASSERT( m_hRope != NULL ); - - SetThink( &CRopeAnchor::FallThink ); - SetNextThink( gpGlobals->curtime + 0.2 ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CRopeAnchor::FallThink() -{ - SetMoveType( MOVETYPE_FLYGRAVITY ); - - Vector vecVelocity = GetAbsVelocity(); - - vecVelocity.x = random->RandomFloat( -30.0f, 30.0f ); - vecVelocity.y = random->RandomFloat( -30.0f, 30.0f ); - - SetAbsVelocity( vecVelocity ); - - SetThink( &CRopeAnchor::RemoveThink ); - SetNextThink( gpGlobals->curtime + 3.0 ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CRopeAnchor::RemoveThink() -{ - UTIL_Remove( m_hRope ); - SetThink( &CRopeAnchor::SUB_Remove ); - SetNextThink( gpGlobals->curtime ); -} - -//========================================================= -//========================================================= - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CAI_RappelBehavior::CAI_RappelBehavior() -{ - m_hLine = NULL; - m_bWaitingToRappel = false; - m_bOnGround = true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CAI_RappelBehavior::KeyValue( const char *szKeyName, const char *szValue ) -{ - if( FStrEq( szKeyName, "waitingtorappel" ) ) - { - m_bWaitingToRappel = ( atoi(szValue) != 0); - m_bOnGround = !m_bWaitingToRappel; - return true; - } - - return BaseClass::KeyValue( szKeyName, szValue ); -} - -void CAI_RappelBehavior::Precache() -{ - CBaseEntity::PrecacheModel( "cable/cable.vmt" ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -#define RAPPEL_MAX_SPEED 600 // Go this fast if you're really high. -#define RAPPEL_MIN_SPEED 60 // Go no slower than this. -#define RAPPEL_DECEL_DIST (20.0f * 12.0f) // Start slowing down when you're this close to the ground. -void CAI_RappelBehavior::SetDescentSpeed() -{ - // Trace to the floor and see how close we're getting. Slow down if we're close. - // STOP if there's an NPC under us. - trace_t tr; - AI_TraceLine( GetOuter()->GetAbsOrigin(), GetOuter()->GetAbsOrigin() - Vector( 0, 0, 8192 ), MASK_SHOT, GetOuter(), COLLISION_GROUP_NONE, &tr ); - - float flDist = fabs( GetOuter()->GetAbsOrigin().z - tr.endpos.z ); - - float speed = RAPPEL_MAX_SPEED; - - if( flDist <= RAPPEL_DECEL_DIST ) - { - float factor; - factor = flDist / RAPPEL_DECEL_DIST; - - speed = MAX( RAPPEL_MIN_SPEED, speed * factor ); - } - - Vector vecNewVelocity = vec3_origin; - vecNewVelocity.z = -speed; - GetOuter()->SetAbsVelocity( vecNewVelocity ); -} - - -void CAI_RappelBehavior::CleanupOnDeath( CBaseEntity *pCulprit, bool bFireDeathOutput ) -{ - BaseClass::CleanupOnDeath( pCulprit, bFireDeathOutput ); - - //This will remove the beam and create a rope if the NPC dies while rappeling down. - if ( m_hLine ) - { - CAI_BaseNPC *pNPC = GetOuter(); - - if ( pNPC ) - { - CutZipline(); - } - } -} -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTask - -//----------------------------------------------------------------------------- -void CAI_RappelBehavior::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_MOVE_AWAY_PATH: - GetOuter()->GetMotor()->SetIdealYaw( UTIL_AngleMod( GetOuter()->GetLocalAngles().y - 180.0f ) ); - BaseClass::StartTask( pTask ); - break; - - case TASK_RANGE_ATTACK1: - BaseClass::StartTask( pTask ); - break; - - case TASK_RAPPEL: - { - CreateZipline(); - SetDescentSpeed(); - } - break; - - case TASK_HIT_GROUND: - m_bOnGround = true; - - if( GetOuter()->GetGroundEntity() != NULL && GetOuter()->GetGroundEntity()->IsNPC() && GetOuter()->GetGroundEntity()->m_iClassname == GetOuter()->m_iClassname ) - { - // Although I tried to get NPC's out from under me, I landed on one. Kill it, so long as it's the same type of character as me. - variant_t val; - val.SetFloat( 0 ); - g_EventQueue.AddEvent( GetOuter()->GetGroundEntity(), "sethealth", val, 0, GetOuter(), GetOuter() ); - } - - TaskComplete(); - break; - - default: - BaseClass::StartTask( pTask ); - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTask - -//----------------------------------------------------------------------------- -void CAI_RappelBehavior::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_RAPPEL: - { - // If we don't do this, the beam won't show up sometimes. Ideally, all beams would update their - // bboxes correctly, but we're close to shipping and we can't change that now. - if ( m_hLine ) - { - m_hLine->RelinkBeam(); - } - - if( GetEnemy() ) - { - // Face the enemy if there's one. - Vector vecEnemyLKP = GetEnemyLKP(); - GetOuter()->GetMotor()->SetIdealYawToTargetAndUpdate( vecEnemyLKP ); - } - - SetDescentSpeed(); - if( GetOuter()->GetFlags() & FL_ONGROUND ) - { - CBaseEntity *pGroundEnt = GetOuter()->GetGroundEntity(); - - if( pGroundEnt && pGroundEnt->IsPlayer() ) - { - // try to shove the player in the opposite direction as they are facing (so they'll see me) - Vector vecForward; - pGroundEnt->GetVectors( &vecForward, NULL, NULL ); - pGroundEnt->SetAbsVelocity( vecForward * -500 ); - break; - } - - GetOuter()->m_OnRappelTouchdown.FireOutput( GetOuter(), GetOuter(), 0 ); - GetOuter()->RemoveFlag( FL_FLY ); - - CutZipline(); - - TaskComplete(); - } - } - break; - - default: - BaseClass::RunTask( pTask ); - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_RappelBehavior::CanSelectSchedule() -{ - if ( !GetOuter()->IsInterruptable() ) - return false; - - if ( m_bWaitingToRappel ) - return true; - - if ( m_bOnGround ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_RappelBehavior::GatherConditions() -{ - BaseClass::GatherConditions(); - - if( HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - { - // Shoot at the enemy so long as I'm six feet or more above them. - if( (GetAbsOrigin().z - GetEnemy()->GetAbsOrigin().z >= 36.0f) && GetOuter()->GetShotRegulator()->ShouldShoot() ) - { - Activity activity = GetOuter()->TranslateActivity( ACT_GESTURE_RANGE_ATTACK1 ); - Assert( activity != ACT_INVALID ); - GetOuter()->AddGesture( activity ); - // FIXME: this seems a bit wacked - GetOuter()->Weapon_SetActivity( GetOuter()->Weapon_TranslateActivity( ACT_RANGE_ATTACK1 ), 0 ); - - GetOuter()->OnRangeAttack1(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CAI_RappelBehavior::SelectSchedule() -{ - if ( HasCondition( COND_BEGIN_RAPPEL ) ) - { - m_bWaitingToRappel = false; - return SCHED_RAPPEL; - } - - if ( m_bWaitingToRappel ) - { - return SCHED_RAPPEL_WAIT; - } - else - { - return SCHED_RAPPEL; - } - - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_RappelBehavior::BeginRappel() -{ - // Send the message to begin rappeling! - SetCondition( COND_BEGIN_RAPPEL ); - - m_vecRopeAnchor = GetOuter()->GetAbsOrigin(); - - trace_t tr; - - UTIL_TraceEntity( GetOuter(), GetAbsOrigin(), GetAbsOrigin()-Vector(0,0,4096), MASK_SHOT, GetOuter(), COLLISION_GROUP_NONE, &tr ); - - if( tr.m_pEnt != NULL && tr.m_pEnt->IsNPC() ) - { - Vector forward; - GetOuter()->GetVectors( &forward, NULL, NULL ); - - CSoundEnt::InsertSound( SOUND_DANGER, tr.m_pEnt->EarPosition() - forward * 12.0f, 32, 0.2f, GetOuter() ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_RappelBehavior::CutZipline() -{ - if( m_hLine ) - { - UTIL_Remove( m_hLine ); - } - - CBaseEntity *pAnchor = CreateEntityByName( "rope_anchor" ); - pAnchor->SetOwnerEntity( GetOuter() ); // Boy, this is a hack!! - pAnchor->SetAbsOrigin( m_vecRopeAnchor ); - pAnchor->Spawn(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_RappelBehavior::CreateZipline() -{ -#if 1 - if( !m_hLine ) - { - int attachment = GetOuter()->LookupAttachment( "zipline" ); - - if( attachment != -1 ) - { - CBeam *pBeam; - pBeam = CBeam::BeamCreate( "cable/cable.vmt", 1 ); - pBeam->SetColor( 150, 150, 150 ); - pBeam->SetWidth( 0.3 ); - pBeam->SetEndWidth( 0.3 ); - - CAI_BaseNPC *pNPC = GetOuter(); - pBeam->PointEntInit( pNPC->GetAbsOrigin() + Vector( 0, 0, 80 ), pNPC ); - - pBeam->SetEndAttachment( attachment ); - - m_hLine.Set( pBeam ); - } - } -#endif -} - - -AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( CAI_RappelBehavior ) - - DECLARE_TASK( TASK_RAPPEL ) - DECLARE_TASK( TASK_HIT_GROUND ) - - DECLARE_CONDITION( COND_BEGIN_RAPPEL ) - - //=============================================== - //=============================================== - DEFINE_SCHEDULE - ( - SCHED_RAPPEL_WAIT, - - " Tasks" - " TASK_SET_ACTIVITY ACTIVITY:ACT_RAPPEL_LOOP" - " TASK_WAIT_INDEFINITE 0" - "" - " Interrupts" - " COND_BEGIN_RAPPEL" - ); - - //=============================================== - //=============================================== - DEFINE_SCHEDULE - ( - SCHED_RAPPEL, - - " Tasks" - " TASK_SET_ACTIVITY ACTIVITY:ACT_RAPPEL_LOOP" - " TASK_RAPPEL 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_CLEAR_RAPPEL_POINT" - "" - " Interrupts" - "" - " COND_NEW_ENEMY" // Only so the enemy selection code will pick an enemy! - ); - - //=============================================== - //=============================================== - DEFINE_SCHEDULE - ( - SCHED_CLEAR_RAPPEL_POINT, - - " Tasks" - " TASK_HIT_GROUND 0" - " TASK_MOVE_AWAY_PATH 128" // Clear this spot for other rappellers - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - "" - ); - -AI_END_CUSTOM_SCHEDULE_PROVIDER() diff --git a/game/server/ai_behavior_rappel.h b/game/server/ai_behavior_rappel.h deleted file mode 100644 index 8c097bc7d..000000000 --- a/game/server/ai_behavior_rappel.h +++ /dev/null @@ -1,93 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Deal with weapon being out -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - - -#ifndef AI_BEHAVIOR_RAPPEL_H -#define AI_BEHAVIOR_RAPPEL_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_behavior.h" - -class CBeam; - -class CAI_RappelBehavior : public CAI_SimpleBehavior -{ - DECLARE_CLASS( CAI_RappelBehavior, CAI_SimpleBehavior ); - -public: - CAI_RappelBehavior(); - - void Precache( void ); - virtual const char *GetName() { return "Rappel"; } - - virtual bool KeyValue( const char *szKeyName, const char *szValue ); - - virtual bool CanSelectSchedule(); - void GatherConditions(); - void CleanupOnDeath( CBaseEntity *pCulprit = NULL, bool bFireDeathOutput = true ); - - //virtual void BeginScheduleSelection(); - //virtual void EndScheduleSelection(); - - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - - bool IsWaitingToRappel() { return m_bWaitingToRappel; } - void BeginRappel(); - void SetDescentSpeed(); - - void CreateZipline(); - void CutZipline(); - - //void BuildScheduleTestBits(); - //int TranslateSchedule( int scheduleType ); - //void OnStartSchedule( int scheduleType ); - - //void InitializeBehavior(); - - enum - { - SCHED_RAPPEL_WAIT = BaseClass::NEXT_SCHEDULE, - SCHED_RAPPEL, - SCHED_CLEAR_RAPPEL_POINT, // Get out of the way for the next guy - NEXT_SCHEDULE, - - TASK_RAPPEL = BaseClass::NEXT_TASK, - TASK_HIT_GROUND, - NEXT_TASK, - - COND_BEGIN_RAPPEL = BaseClass::NEXT_CONDITION, - NEXT_CONDITION, - }; - - DEFINE_CUSTOM_SCHEDULE_PROVIDER; - -public: - -private: - virtual int SelectSchedule(); - - //--------------------------------- - bool m_bWaitingToRappel; - bool m_bOnGround; - CHandle m_hLine; - Vector m_vecRopeAnchor; - - DECLARE_DATADESC(); -}; - -#endif // AI_BEHAVIOR_RAPPEL_H - - diff --git a/game/server/ai_behavior_standoff.cpp b/game/server/ai_behavior_standoff.cpp deleted file mode 100644 index 8c2c15d1e..000000000 --- a/game/server/ai_behavior_standoff.cpp +++ /dev/null @@ -1,1336 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Combat behaviors for AIs in a relatively self-preservationist mode. -// Lots of cover taking and attempted shots out of cover. -// -//=============================================================================// - -#include "cbase.h" - -#include "ai_hint.h" -#include "ai_node.h" -#include "ai_navigator.h" -#include "ai_tacticalservices.h" -#include "ai_behavior_standoff.h" -#include "ai_senses.h" -#include "ai_squad.h" -#include "ai_goalentity.h" -#include "ndebugoverlay.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define GOAL_POSITION_INVALID Vector( FLT_MAX, FLT_MAX, FLT_MAX ) - -ConVar DrawBattleLines( "ai_drawbattlelines", "0", FCVAR_CHEAT ); - - -static AI_StandoffParams_t AI_DEFAULT_STANDOFF_PARAMS = { AIHCR_MOVE_ON_COVER, true, 1.5, 2.5, 1, 3, 25, 0 }; - -#define MAKE_ACTMAP_KEY( posture, activity ) ( (((unsigned)(posture)) << 16) | ((unsigned)(activity)) ) - -// #define DEBUG_STANDOFF 1 - - -#ifdef DEBUG_STANDOFF -#define StandoffMsg( msg ) DevMsg( GetOuter(), msg ) -#define StandoffMsg1( msg, a ) DevMsg( GetOuter(), msg, a ) -#define StandoffMsg2( msg, a, b ) DevMsg( GetOuter(), msg, a, b ) -#define StandoffMsg3( msg, a, b, c ) DevMsg( GetOuter(), msg, a, b, c ) -#define StandoffMsg4( msg, a, b, c, d ) DevMsg( GetOuter(), msg, a, b, c, d ) -#define StandoffMsg5( msg, a, b, c, d, e ) DevMsg( GetOuter(), msg, a, b, c, d, e ) -#else -#define StandoffMsg( msg ) ((void)0) -#define StandoffMsg1( msg, a ) ((void)0) -#define StandoffMsg2( msg, a, b ) ((void)0) -#define StandoffMsg3( msg, a, b, c ) ((void)0) -#define StandoffMsg4( msg, a, b, c, d ) ((void)0) -#define StandoffMsg5( msg, a, b, c, d, e ) ((void)0) -#endif - -//----------------------------------------------------------------------------- -// -// CAI_BattleLine -// -//----------------------------------------------------------------------------- - -const float AIBL_THINK_INTERVAL = 0.3; - -class CAI_BattleLine : public CBaseEntity -{ - DECLARE_CLASS( CAI_BattleLine, CBaseEntity ); - -public: - string_t m_iszActor; - bool m_fActive; - bool m_fStrict; - - void Spawn() - { - if ( m_fActive ) - { - SetThink(&CAI_BattleLine::MovementThink); - SetNextThink( gpGlobals->curtime + AIBL_THINK_INTERVAL ); - m_SelfMoveMonitor.SetMark( this, 60 ); - } - } - - virtual void InputActivate( inputdata_t &inputdata ) - { - if ( !m_fActive ) - { - m_fActive = true; - NotifyChangeTacticalConstraints(); - - SetThink(&CAI_BattleLine::MovementThink); - SetNextThink( gpGlobals->curtime + AIBL_THINK_INTERVAL ); - m_SelfMoveMonitor.SetMark( this, 60 ); - } - } - - virtual void InputDeactivate( inputdata_t &inputdata ) - { - if ( m_fActive ) - { - m_fActive = false; - NotifyChangeTacticalConstraints(); - - SetThink(NULL); - } - } - - void UpdateOnRemove() - { - if ( m_fActive ) - { - m_fActive = false; - NotifyChangeTacticalConstraints(); - } - BaseClass::UpdateOnRemove(); - } - - bool Affects( CAI_BaseNPC *pNpc ) - { - const char *pszNamedActor = STRING( m_iszActor ); - - if ( pNpc->NameMatches( pszNamedActor ) || - pNpc->ClassMatches( pszNamedActor ) || - ( pNpc->GetSquad() && stricmp( pNpc->GetSquad()->GetName(), pszNamedActor ) == 0 ) ) - { - return true; - } - return false; - } - - void MovementThink() - { - if ( m_SelfMoveMonitor.TargetMoved( this ) ) - { - NotifyChangeTacticalConstraints(); - m_SelfMoveMonitor.SetMark( this, 60 ); - } - SetNextThink( gpGlobals->curtime + AIBL_THINK_INTERVAL ); - } - -private: - void NotifyChangeTacticalConstraints() - { - for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - CAI_BaseNPC *pNpc = (g_AI_Manager.AccessAIs())[i]; - if ( Affects( pNpc ) ) - { - CAI_StandoffBehavior *pBehavior; - if ( pNpc->GetBehavior( &pBehavior ) ) - { - pBehavior->OnChangeTacticalConstraints(); - } - } - } - } - - CAI_MoveMonitor m_SelfMoveMonitor; - - DECLARE_DATADESC(); -}; - -//------------------------------------- - -LINK_ENTITY_TO_CLASS( ai_battle_line, CAI_BattleLine ); - -BEGIN_DATADESC( CAI_BattleLine ) - DEFINE_KEYFIELD( m_iszActor, FIELD_STRING, "Actor" ), - DEFINE_KEYFIELD( m_fActive, FIELD_BOOLEAN, "Active" ), - DEFINE_KEYFIELD( m_fStrict, FIELD_BOOLEAN, "Strict" ), - DEFINE_EMBEDDED( m_SelfMoveMonitor ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ), - DEFINE_INPUTFUNC( FIELD_VOID, "Deactivate", InputDeactivate ), - - DEFINE_THINKFUNC( MovementThink ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// -// CAI_StandoffBehavior -// -//----------------------------------------------------------------------------- - -BEGIN_SIMPLE_DATADESC( AI_StandoffParams_t ) - DEFINE_FIELD( hintChangeReaction, FIELD_INTEGER ), - DEFINE_FIELD( fPlayerIsBattleline, FIELD_BOOLEAN ), - DEFINE_FIELD( fCoverOnReload, FIELD_BOOLEAN ), - DEFINE_FIELD( minTimeShots, FIELD_FLOAT ), - DEFINE_FIELD( maxTimeShots, FIELD_FLOAT ), - DEFINE_FIELD( minShots, FIELD_INTEGER ), - DEFINE_FIELD( maxShots, FIELD_INTEGER ), - DEFINE_FIELD( oddsCover, FIELD_INTEGER ), - DEFINE_FIELD( fStayAtCover, FIELD_BOOLEAN ), - DEFINE_FIELD( flAbandonTimeLimit, FIELD_FLOAT ), -END_DATADESC(); - -BEGIN_DATADESC( CAI_StandoffBehavior ) - DEFINE_FIELD( m_fActive, FIELD_BOOLEAN ), - DEFINE_FIELD( m_fTestNoDamage, FIELD_BOOLEAN ), - DEFINE_FIELD( m_vecStandoffGoalPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_posture, FIELD_INTEGER ), - DEFINE_EMBEDDED( m_params ), - DEFINE_FIELD( m_hStandoffGoal, FIELD_EHANDLE ), - DEFINE_FIELD( m_fTakeCover, FIELD_BOOLEAN ), - DEFINE_FIELD( m_SavedDistTooFar, FIELD_FLOAT ), - DEFINE_FIELD( m_fForceNewEnemy, FIELD_BOOLEAN ), - DEFINE_EMBEDDED( m_PlayerMoveMonitor ), - DEFINE_EMBEDDED( m_TimeForceCoverHint ), - DEFINE_EMBEDDED( m_TimePreventForceNewEnemy ), - DEFINE_EMBEDDED( m_RandomCoverChangeTimer ), - // m_UpdateBattleLinesSemaphore (not saved, only an in-think item) - // m_BattleLines (not saved, rebuilt) - DEFINE_FIELD( m_fIgnoreFronts, FIELD_BOOLEAN ), - // m_ActivityMap (not saved, rebuilt) - // m_bHasLowCoverActivity (not saved, rebuilt) - - DEFINE_FIELD( m_nSavedMinShots, FIELD_INTEGER ), - DEFINE_FIELD( m_nSavedMaxShots, FIELD_INTEGER ), - DEFINE_FIELD( m_flSavedMinRest, FIELD_FLOAT ), - DEFINE_FIELD( m_flSavedMaxRest, FIELD_FLOAT ), - -END_DATADESC(); - -//------------------------------------- - -CAI_StandoffBehavior::CAI_StandoffBehavior( CAI_BaseNPC *pOuter ) - : CAI_MappedActivityBehavior_Temporary( pOuter ) -{ - m_fActive = false; - SetParameters( AI_DEFAULT_STANDOFF_PARAMS ); - SetPosture( AIP_STANDING ); - m_SavedDistTooFar = FLT_MAX; - m_fForceNewEnemy = false; - m_TimePreventForceNewEnemy.Set( 3.0, 6.0 ); - m_fIgnoreFronts = false; - m_bHasLowCoverActivity = false; -} - -//------------------------------------- - -void CAI_StandoffBehavior::SetActive( bool fActive ) -{ - if ( fActive != m_fActive ) - { - if ( fActive ) - { - GetOuter()->SpeakSentence( STANDOFF_SENTENCE_BEGIN_STANDOFF ); - } - else - { - GetOuter()->SpeakSentence( STANDOFF_SENTENCE_END_STANDOFF ); - } - - m_fActive = fActive; - NotifyChangeBehaviorStatus(); - } -} - -//------------------------------------- - -void CAI_StandoffBehavior::SetParameters( const AI_StandoffParams_t ¶ms, CAI_GoalEntity *pGoalEntity ) -{ - m_params = params; - m_hStandoffGoal = pGoalEntity; - m_vecStandoffGoalPosition = GOAL_POSITION_INVALID; - if ( GetOuter() && GetOuter()->GetShotRegulator() ) - { - GetOuter()->GetShotRegulator()->SetBurstShotCountRange( m_params.minShots, m_params.maxShots ); - GetOuter()->GetShotRegulator()->SetRestInterval( m_params.minTimeShots, m_params.maxTimeShots ); - } -} - -//------------------------------------- - -bool CAI_StandoffBehavior::CanSelectSchedule() -{ - if ( !m_bHasLowCoverActivity ) - m_fActive = false; - - if ( !m_fActive ) - return false; - - return ( GetNpcState() == NPC_STATE_COMBAT && GetOuter()->GetActiveWeapon() != NULL ); -} - -//------------------------------------- - -void CAI_StandoffBehavior::Spawn() -{ - BaseClass::Spawn(); - UpdateTranslateActivityMap(); -} - -//------------------------------------- - -void CAI_StandoffBehavior::BeginScheduleSelection() -{ - m_fTakeCover = true; - - // FIXME: Improve!!! - GetOuter()->GetShotRegulator()->GetBurstShotCountRange( &m_nSavedMinShots, &m_nSavedMaxShots ); - GetOuter()->GetShotRegulator()->GetRestInterval( &m_flSavedMinRest, &m_flSavedMaxRest ); - - GetOuter()->GetShotRegulator()->SetBurstShotCountRange( m_params.minShots, m_params.maxShots ); - GetOuter()->GetShotRegulator()->SetRestInterval( m_params.minTimeShots, m_params.maxTimeShots ); - GetOuter()->GetShotRegulator()->Reset(); - - m_SavedDistTooFar = GetOuter()->m_flDistTooFar; - GetOuter()->m_flDistTooFar = FLT_MAX; - - m_TimeForceCoverHint.Set( 8, false ); - m_RandomCoverChangeTimer.Set( 8, 16, false ); - UpdateTranslateActivityMap(); -} - - -void CAI_StandoffBehavior::OnUpdateShotRegulator() -{ - GetOuter()->GetShotRegulator()->SetBurstShotCountRange( m_params.minShots, m_params.maxShots ); - GetOuter()->GetShotRegulator()->SetRestInterval( m_params.minTimeShots, m_params.maxTimeShots ); -} - - -//------------------------------------- - -void CAI_StandoffBehavior::EndScheduleSelection() -{ - UnlockHintNode(); - - m_vecStandoffGoalPosition = GOAL_POSITION_INVALID; - GetOuter()->m_flDistTooFar = m_SavedDistTooFar; - - // FIXME: Improve!!! - GetOuter()->GetShotRegulator()->SetBurstShotCountRange( m_nSavedMinShots, m_nSavedMaxShots ); - GetOuter()->GetShotRegulator()->SetRestInterval( m_flSavedMinRest, m_flSavedMaxRest ); -} - -//------------------------------------- - -void CAI_StandoffBehavior::PrescheduleThink() -{ - VPROF_BUDGET( "CAI_StandoffBehavior::PrescheduleThink", VPROF_BUDGETGROUP_NPCS ); - - BaseClass::PrescheduleThink(); - - if( DrawBattleLines.GetInt() != 0 ) - { - CBaseEntity *pEntity = NULL; - while ((pEntity = gEntList.FindEntityByClassname( pEntity, "ai_battle_line" )) != NULL) - { - // Visualize the battle line and its normal. - CAI_BattleLine *pLine = dynamic_cast(pEntity); - - if( pLine->m_fActive ) - { - Vector normal; - - pLine->GetVectors( &normal, NULL, NULL ); - - NDebugOverlay::Line( pLine->GetAbsOrigin() - Vector( 0, 0, 64 ), pLine->GetAbsOrigin() + Vector(0,0,64), 0,255,0, false, 0.1 ); - } - } - } -} - -//------------------------------------- - -void CAI_StandoffBehavior::GatherConditions() -{ - CBaseEntity *pLeader = GetPlayerLeader(); - if ( pLeader && m_TimeForceCoverHint.Expired() ) - { - if ( m_PlayerMoveMonitor.IsMarkSet() ) - { - if (m_PlayerMoveMonitor.TargetMoved( pLeader ) ) - { - OnChangeTacticalConstraints(); - m_PlayerMoveMonitor.ClearMark(); - } - } - else - { - m_PlayerMoveMonitor.SetMark( pLeader, 60 ); - } - } - - if ( m_fForceNewEnemy ) - { - m_TimePreventForceNewEnemy.Reset(); - GetOuter()->SetEnemy( NULL ); - } - BaseClass::GatherConditions(); - m_fForceNewEnemy = false; - - ClearCondition( COND_ABANDON_TIME_EXPIRED ); - - bool bAbandonStandoff = false; - CAI_Squad *pSquad = GetOuter()->GetSquad(); - AISquadIter_t iter; - if ( GetEnemy() ) - { - AI_EnemyInfo_t *pEnemyInfo = GetOuter()->GetEnemies()->Find( GetEnemy() ); - if ( pEnemyInfo && - m_params.flAbandonTimeLimit > 0 && - ( ( pEnemyInfo->timeAtFirstHand != AI_INVALID_TIME && - gpGlobals->curtime - pEnemyInfo->timeLastSeen > m_params.flAbandonTimeLimit ) || - ( pEnemyInfo->timeAtFirstHand == AI_INVALID_TIME && - gpGlobals->curtime - pEnemyInfo->timeFirstSeen > m_params.flAbandonTimeLimit * 2 ) ) ) - { - SetCondition( COND_ABANDON_TIME_EXPIRED ); - - bAbandonStandoff = true; - - if ( pSquad ) - { - for ( CAI_BaseNPC *pSquadMate = pSquad->GetFirstMember( &iter ); pSquadMate; pSquadMate = pSquad->GetNextMember( &iter ) ) - { - if ( pSquadMate->IsAlive() && pSquadMate != GetOuter() ) - { - CAI_StandoffBehavior *pSquadmateStandoff; - pSquadMate->GetBehavior( &pSquadmateStandoff ); - if ( pSquadmateStandoff && pSquadmateStandoff->IsActive() && - pSquadmateStandoff->m_hStandoffGoal == m_hStandoffGoal && - !pSquadmateStandoff->HasCondition( COND_ABANDON_TIME_EXPIRED ) ) - { - bAbandonStandoff = false; - break; - } - } - } - } - } - } - - if ( bAbandonStandoff ) - { - if ( pSquad ) - { - for ( CAI_BaseNPC *pSquadMate = pSquad->GetFirstMember( &iter ); pSquadMate; pSquadMate = pSquad->GetNextMember( &iter ) ) - { - CAI_StandoffBehavior *pSquadmateStandoff; - pSquadMate->GetBehavior( &pSquadmateStandoff ); - if ( pSquadmateStandoff && pSquadmateStandoff->IsActive() && pSquadmateStandoff->m_hStandoffGoal == m_hStandoffGoal ) - pSquadmateStandoff->SetActive( false ); - } - } - else - SetActive( false ); - } - else if ( GetOuter()->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT ) - { - if( DrawBattleLines.GetInt() != 0 ) - { - if ( IsBehindBattleLines( GetAbsOrigin() ) ) - { - NDebugOverlay::Box( GetOuter()->GetAbsOrigin(), -Vector(48,48,4), Vector(48,48,4), 255,0,0,8, 0.1 ); - } - else - { - NDebugOverlay::Box( GetOuter()->GetAbsOrigin(), -Vector(48,48,4), Vector(48,48,4), 0,255,0,8, 0.1 ); - } - } - } -} - -//------------------------------------- - -int CAI_StandoffBehavior::SelectScheduleUpdateWeapon( void ) -{ - // Check if need to reload - if ( HasCondition ( COND_NO_PRIMARY_AMMO ) || HasCondition ( COND_LOW_PRIMARY_AMMO )) - { - StandoffMsg( "Out of ammo, reloading\n" ); - if ( m_params.fCoverOnReload ) - { - GetOuter()->SpeakSentence( STANDOFF_SENTENCE_OUT_OF_AMMO ); - return SCHED_HIDE_AND_RELOAD; - } - - return SCHED_RELOAD; - } - - // Otherwise, update planned shots to fire before taking cover again - if ( HasCondition( COND_LIGHT_DAMAGE ) ) - { - // if hurt: - int iPercent = random->RandomInt(0,99); - - if ( iPercent <= m_params.oddsCover && GetEnemy() != NULL ) - { - SetReuseCurrentCover(); - StandoffMsg( "Hurt, firing one more shot before cover\n" ); - if ( !GetOuter()->GetShotRegulator()->IsInRestInterval() ) - { - GetOuter()->GetShotRegulator()->SetBurstShotsRemaining( 1 ); - } - } - } - - return SCHED_NONE; -} - -//------------------------------------- - -int CAI_StandoffBehavior::SelectScheduleCheckCover( void ) -{ - if ( m_fTakeCover ) - { - m_fTakeCover = false; - if ( GetEnemy() ) - { - GetOuter()->SpeakSentence( STANDOFF_SENTENCE_FORCED_TAKE_COVER ); - StandoffMsg( "Taking forced cover\n" ); - return SCHED_TAKE_COVER_FROM_ENEMY; - } - } - - if ( GetOuter()->GetShotRegulator()->IsInRestInterval() ) - { - StandoffMsg( "Regulated to not shoot\n" ); - if ( GetHintType() == HINT_TACTICAL_COVER_LOW ) - SetPosture( AIP_CROUCHING ); - else - SetPosture( AIP_STANDING ); - - if ( random->RandomInt(0,99) < 80 ) - SetReuseCurrentCover(); - return SCHED_TAKE_COVER_FROM_ENEMY; - } - - return SCHED_NONE; -} - -//------------------------------------- - -int CAI_StandoffBehavior::SelectScheduleEstablishAim( void ) -{ - if ( HasCondition( COND_ENEMY_OCCLUDED ) ) - { - if ( GetPosture() == AIP_CROUCHING ) - { - // force a stand up, just in case - GetOuter()->SpeakSentence( STANDOFF_SENTENCE_STAND_CHECK_TARGET ); - StandoffMsg( "Crouching, standing up to gain LOS\n" ); - SetPosture( AIP_PEEKING ); - return SCHED_STANDOFF; - } - else if ( GetPosture() == AIP_PEEKING ) - { - if ( m_TimePreventForceNewEnemy.Expired() ) - { - // Look for a new enemy - m_fForceNewEnemy = true; - StandoffMsg( "Looking for enemy\n" ); - } - } -#if 0 - else - { - return SCHED_ESTABLISH_LINE_OF_FIRE; - } -#endif - } - - return SCHED_NONE; -} - -//------------------------------------- - -int CAI_StandoffBehavior::SelectScheduleAttack( void ) -{ - if ( GetPosture() == AIP_PEEKING || GetPosture() == AIP_STANDING ) - { - if ( !HasCondition( COND_CAN_RANGE_ATTACK1 ) && - !HasCondition( COND_CAN_MELEE_ATTACK1 ) && - HasCondition( COND_TOO_FAR_TO_ATTACK ) ) - { - if ( GetOuter()->GetActiveWeapon() && ( GetOuter()->GetActiveWeapon()->CapabilitiesGet() & bits_CAP_WEAPON_RANGE_ATTACK1 ) ) - { - if ( !HasCondition( COND_ENEMY_OCCLUDED ) || random->RandomInt(0,99) < 50 ) - // Don't advance, just fire anyway - return SCHED_RANGE_ATTACK1; - } - } - } - - return SCHED_NONE; -} - -//------------------------------------- - -int CAI_StandoffBehavior::SelectSchedule( void ) -{ - switch ( GetNpcState() ) - { - case NPC_STATE_COMBAT: - { - int schedule = SCHED_NONE; - - schedule = SelectScheduleUpdateWeapon(); - if ( schedule != SCHED_NONE ) - return schedule; - - schedule = SelectScheduleCheckCover(); - if ( schedule != SCHED_NONE ) - return schedule; - - schedule = SelectScheduleEstablishAim(); - if ( schedule != SCHED_NONE ) - return schedule; - - schedule = SelectScheduleAttack(); - if ( schedule != SCHED_NONE ) - return schedule; - - break; - } - } - - return BaseClass::SelectSchedule(); -} - -//------------------------------------- - -int CAI_StandoffBehavior::TranslateSchedule( int schedule ) -{ - if ( schedule == SCHED_CHASE_ENEMY ) - { - StandoffMsg( "trying SCHED_ESTABLISH_LINE_OF_FIRE\n" ); - return SCHED_ESTABLISH_LINE_OF_FIRE; - } - return BaseClass::TranslateSchedule( schedule ); -} - -//------------------------------------- - -void CAI_StandoffBehavior::BuildScheduleTestBits() -{ - BaseClass::BuildScheduleTestBits(); - - if ( IsCurSchedule( SCHED_TAKE_COVER_FROM_ENEMY ) ) - GetOuter()->ClearCustomInterruptCondition( COND_NEW_ENEMY ); -} - -//------------------------------------- - -Activity CAI_MappedActivityBehavior_Temporary::GetMappedActivity( AI_Posture_t posture, Activity activity ) -{ - if ( posture != AIP_STANDING ) - { - unsigned short iActivityTranslation = m_ActivityMap.Find( MAKE_ACTMAP_KEY( posture, activity ) ); - if ( iActivityTranslation != m_ActivityMap.InvalidIndex() ) - { - Activity result = m_ActivityMap[iActivityTranslation]; - return result; - } - } - return ACT_INVALID; -} - -//------------------------------------- - -Activity CAI_StandoffBehavior::NPC_TranslateActivity( Activity activity ) -{ - Activity coverActivity = GetCoverActivity(); - if ( coverActivity != ACT_INVALID ) - { - if ( activity == ACT_IDLE ) - activity = coverActivity; - if ( GetPosture() == AIP_STANDING && coverActivity == ACT_COVER_LOW ) - SetPosture( AIP_CROUCHING ); - } - - Activity result = GetMappedActivity( GetPosture(), activity ); - if ( result != ACT_INVALID) - return result; - - return BaseClass::NPC_TranslateActivity( activity ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &vecPos - -//----------------------------------------------------------------------------- -void CAI_StandoffBehavior::SetStandoffGoalPosition( const Vector &vecPos ) -{ - m_vecStandoffGoalPosition = vecPos; - UpdateBattleLines(); - OnChangeTacticalConstraints(); - GetOuter()->ClearSchedule( "Standoff goal position changed" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &vecPos - -//----------------------------------------------------------------------------- -void CAI_StandoffBehavior::ClearStandoffGoalPosition() -{ - if ( m_vecStandoffGoalPosition != GOAL_POSITION_INVALID ) - { - m_vecStandoffGoalPosition = GOAL_POSITION_INVALID; - UpdateBattleLines(); - OnChangeTacticalConstraints(); - GetOuter()->ClearSchedule( "Standoff goal position cleared" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Vector -//----------------------------------------------------------------------------- -Vector CAI_StandoffBehavior::GetStandoffGoalPosition() -{ - if( m_vecStandoffGoalPosition != GOAL_POSITION_INVALID ) - { - return m_vecStandoffGoalPosition; - } - else if( PlayerIsLeading() ) - { - return UTIL_GetLocalPlayer()->GetAbsOrigin(); - } - else - { - CAI_BattleLine *pBattleLine = NULL; - for (;;) - { - pBattleLine = (CAI_BattleLine *)gEntList.FindEntityByClassname( pBattleLine, "ai_battle_line" ); - - if ( !pBattleLine ) - break; - - if ( pBattleLine->m_fActive && pBattleLine->Affects( GetOuter() ) ) - { - StandoffMsg1( "Using battleline %s as goal\n", STRING( pBattleLine->GetEntityName() ) ); - return pBattleLine->GetAbsOrigin(); - } - } - } - - return GetAbsOrigin(); -} - -//------------------------------------- - -void CAI_StandoffBehavior::UpdateBattleLines() -{ - if ( m_UpdateBattleLinesSemaphore.EnterThink() ) - { - // @TODO (toml 06-19-03): This is the quick to code thing. Could use some optimization/caching to not recalc everything (up to) each think - m_BattleLines.RemoveAll(); - - bool bHaveGoalPosition = ( m_vecStandoffGoalPosition != GOAL_POSITION_INVALID ); - - if ( bHaveGoalPosition ) - { - // If we have a valid standoff goal position, it takes precendence. - const float DIST_GOAL_PLANE = 180; - - BattleLine_t goalLine; - - if ( GetDirectionOfStandoff( &goalLine.normal ) ) - { - goalLine.point = GetStandoffGoalPosition() + goalLine.normal * DIST_GOAL_PLANE; - m_BattleLines.AddToTail( goalLine ); - } - } - else if ( PlayerIsLeading() && GetEnemy() ) - { - if ( m_params.fPlayerIsBattleline ) - { - const float DIST_PLAYER_PLANE = 180; - CBaseEntity *pPlayer = UTIL_GetLocalPlayer(); - - BattleLine_t playerLine; - - if ( GetDirectionOfStandoff( &playerLine.normal ) ) - { - playerLine.point = pPlayer->GetAbsOrigin() + playerLine.normal * DIST_PLAYER_PLANE; - m_BattleLines.AddToTail( playerLine ); - } - } - } - - CAI_BattleLine *pBattleLine = NULL; - for (;;) - { - pBattleLine = (CAI_BattleLine *)gEntList.FindEntityByClassname( pBattleLine, "ai_battle_line" ); - - if ( !pBattleLine ) - break; - - if ( pBattleLine->m_fActive && (pBattleLine->m_fStrict || !bHaveGoalPosition ) && pBattleLine->Affects( GetOuter() ) ) - { - BattleLine_t battleLine; - - battleLine.point = pBattleLine->GetAbsOrigin(); - battleLine.normal = UTIL_YawToVector( pBattleLine->GetAbsAngles().y ); - - m_BattleLines.AddToTail( battleLine ); - } - - } - } -} - -//------------------------------------- - -bool CAI_StandoffBehavior::IsBehindBattleLines( const Vector &point ) -{ - UpdateBattleLines(); - - Vector vecToPoint; - - for ( int i = 0; i < m_BattleLines.Count(); i++ ) - { - vecToPoint = point - m_BattleLines[i].point; - VectorNormalize( vecToPoint ); - vecToPoint.z = 0; - - if ( DotProduct( m_BattleLines[i].normal, vecToPoint ) > 0 ) - { - if( DrawBattleLines.GetInt() != 0 ) - { - NDebugOverlay::Box( point, -Vector(48,48,4), Vector(48,48,4), 0,255,0,8, 1 ); - NDebugOverlay::Line( point, GetOuter()->GetAbsOrigin(), 0,255,0,true, 1 ); - } - return false; - } - } - - if( DrawBattleLines.GetInt() != 0 ) - { - NDebugOverlay::Box( point, -Vector(48,48,4), Vector(48,48,4), 255,0,0,8, 1 ); - NDebugOverlay::Line( point, GetOuter()->GetAbsOrigin(), 255,0,0,true, 1 ); - } - - return true; -} - -//------------------------------------- - -bool CAI_StandoffBehavior::IsValidCover( const Vector &vecCoverLocation, const CAI_Hint *pHint ) -{ - if ( !BaseClass::IsValidCover( vecCoverLocation, pHint ) ) - return false; - - if ( IsCurSchedule( SCHED_TAKE_COVER_FROM_BEST_SOUND ) ) - return true; - - return ( m_fIgnoreFronts || IsBehindBattleLines( vecCoverLocation ) ); -} - -//------------------------------------- - -bool CAI_StandoffBehavior::IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, const CAI_Hint *pHint ) -{ - if ( !BaseClass::IsValidShootPosition( vLocation, pNode, pHint ) ) - return false; - - return ( m_fIgnoreFronts || IsBehindBattleLines( vLocation ) ); -} - -//------------------------------------- - -void CAI_StandoffBehavior::StartTask( const Task_t *pTask ) -{ - bool fCallBase = false; - - switch ( pTask->iTask ) - { - case TASK_RANGE_ATTACK1: - { - fCallBase = true; - break; - } - - case TASK_FIND_COVER_FROM_ENEMY: - { - StandoffMsg( "TASK_FIND_COVER_FROM_ENEMY\n" ); - - // If within time window to force change - if ( !m_params.fStayAtCover && (!m_TimeForceCoverHint.Expired() || m_RandomCoverChangeTimer.Expired()) ) - { - m_TimeForceCoverHint.Force(); - m_RandomCoverChangeTimer.Set( 8, 16, false ); - - // @TODO (toml 03-24-03): clean this up be tool-izing base tasks. Right now, this is here to force to not use lateral cover search - CBaseEntity *pEntity = GetEnemy(); - - if ( pEntity == NULL ) - { - // Find cover from self if no enemy available - pEntity = GetOuter(); - } - - CBaseEntity *pLeader = GetPlayerLeader(); - if ( pLeader ) - { - m_PlayerMoveMonitor.SetMark( pLeader, 60 ); - } - - Vector coverPos = vec3_origin; - CAI_TacticalServices * pTacticalServices = GetTacticalServices(); - const Vector & enemyPos = pEntity->GetAbsOrigin(); - Vector enemyEyePos = pEntity->EyePosition(); - float coverRadius = GetOuter()->CoverRadius(); - const Vector & goalPos = GetStandoffGoalPosition(); - bool bTryGoalPosFirst = true; - - if( pLeader && m_vecStandoffGoalPosition == GOAL_POSITION_INVALID ) - { - if( random->RandomInt(1, 100) <= 50 ) - { - // Half the time, if the player is leading, try to find a spot near them - bTryGoalPosFirst = false; - StandoffMsg( "Not trying goal pos\n" ); - } - } - - if( bTryGoalPosFirst ) - { - // Firstly, try to find cover near the goal position. - pTacticalServices->FindCoverPos( goalPos, enemyPos, enemyEyePos, 0, 15*12, &coverPos ); - - if ( coverPos == vec3_origin ) - pTacticalServices->FindCoverPos( goalPos, enemyPos, enemyEyePos, 15*12-0.1, 40*12, &coverPos ); - - StandoffMsg1( "Trying goal pos, %s\n", ( coverPos == vec3_origin ) ? "failed" : "succeeded" ); - } - - if ( coverPos == vec3_origin ) - { - // Otherwise, find a node near to self - StandoffMsg( "Looking for near cover\n" ); - if ( !GetTacticalServices()->FindCoverPos( enemyPos, enemyEyePos, 0, coverRadius, &coverPos ) ) - { - // Try local lateral cover - if ( !GetTacticalServices()->FindLateralCover( enemyEyePos, 0, &coverPos ) ) - { - // At this point, try again ignoring front lines. Any cover probably better than hanging out in the open - m_fIgnoreFronts = true; - if ( !GetTacticalServices()->FindCoverPos( enemyPos, enemyEyePos, 0, coverRadius, &coverPos ) ) - { - if ( !GetTacticalServices()->FindLateralCover( enemyEyePos, 0, &coverPos ) ) - { - Assert( coverPos == vec3_origin ); - } - } - m_fIgnoreFronts = false; - } - } - } - - if ( coverPos != vec3_origin ) - { - AI_NavGoal_t goal(GOALTYPE_COVER, coverPos, ACT_RUN, AIN_HULL_TOLERANCE, AIN_DEF_FLAGS); - GetNavigator()->SetGoal( goal ); - - GetOuter()->m_flMoveWaitFinished = gpGlobals->curtime + pTask->flTaskData; - TaskComplete(); - } - else - TaskFail(FAIL_NO_COVER); - } - else - { - fCallBase = true; - } - break; - } - - default: - { - fCallBase = true; - } - } - - if ( fCallBase ) - BaseClass::StartTask( pTask ); -} - -//------------------------------------- - -void CAI_StandoffBehavior::OnChangeHintGroup( string_t oldGroup, string_t newGroup ) -{ - OnChangeTacticalConstraints(); -} - -//------------------------------------- - -void CAI_StandoffBehavior::OnChangeTacticalConstraints() -{ - if ( m_params.hintChangeReaction > AIHCR_DEFAULT_AI ) - m_TimeForceCoverHint.Set( 8.0, false ); - if ( m_params.hintChangeReaction == AIHCR_MOVE_IMMEDIATE ) - m_fTakeCover = true; -} - -//------------------------------------- - -bool CAI_StandoffBehavior::PlayerIsLeading() -{ - CBaseEntity *pPlayer = AI_GetSinglePlayer(); - return ( pPlayer && GetOuter()->IRelationType( pPlayer ) == D_LI ); -} - -//------------------------------------- - -CBaseEntity *CAI_StandoffBehavior::GetPlayerLeader() -{ - CBaseEntity *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer && GetOuter()->IRelationType( pPlayer ) == D_LI ) - return pPlayer; - return NULL; -} - -//------------------------------------- - -bool CAI_StandoffBehavior::GetDirectionOfStandoff( Vector *pDir ) -{ - if ( GetEnemy() ) - { - *pDir = GetEnemy()->GetAbsOrigin() - GetAbsOrigin(); - VectorNormalize( *pDir ); - pDir->z = 0; - return true; - } - return false; -} - -//------------------------------------- - -Hint_e CAI_StandoffBehavior::GetHintType() -{ - CAI_Hint *pHintNode = GetHintNode(); - if ( pHintNode ) - return pHintNode->HintType(); - return HINT_NONE; -} - -//------------------------------------- - -void CAI_StandoffBehavior::SetReuseCurrentCover() -{ - CAI_Hint *pHintNode = GetHintNode(); - if ( pHintNode && pHintNode->GetNode() && pHintNode->GetNode()->IsLocked() ) - pHintNode->GetNode()->Unlock(); -} - -//------------------------------------- - -void CAI_StandoffBehavior::UnlockHintNode() -{ - CAI_Hint *pHintNode = GetHintNode(); - if ( pHintNode ) - { - if ( pHintNode->IsLocked() && pHintNode->IsLockedBy( GetOuter() ) ) - pHintNode->Unlock(); - CAI_Node *pNode = pHintNode->GetNode(); - if ( pNode && pNode->IsLocked() ) - pNode->Unlock(); - ClearHintNode(); - } -} - - -//------------------------------------- - -Activity CAI_StandoffBehavior::GetCoverActivity() -{ - CAI_Hint *pHintNode = GetHintNode(); - if ( pHintNode && pHintNode->HintType() == HINT_TACTICAL_COVER_LOW ) - return GetOuter()->GetCoverActivity( pHintNode ); - return ACT_INVALID; -} - - -//------------------------------------- - -struct AI_ActivityMapping_t -{ - AI_Posture_t posture; - Activity activity; - const char * pszWeapon; - Activity translation; -}; - -void CAI_MappedActivityBehavior_Temporary::UpdateTranslateActivityMap() -{ - AI_ActivityMapping_t mappings[] = // This array cannot be static, as some activity values are set on a per-map-load basis - { - { AIP_CROUCHING, ACT_IDLE, NULL, ACT_COVER_LOW, }, - { AIP_CROUCHING, ACT_IDLE_ANGRY, NULL, ACT_COVER_LOW, }, - { AIP_CROUCHING, ACT_WALK, NULL, ACT_WALK_CROUCH, }, - { AIP_CROUCHING, ACT_RUN, NULL, ACT_RUN_CROUCH, }, - { AIP_CROUCHING, ACT_WALK_AIM, NULL, ACT_WALK_CROUCH_AIM, }, - { AIP_CROUCHING, ACT_RUN_AIM, NULL, ACT_RUN_CROUCH_AIM, }, - { AIP_CROUCHING, ACT_RELOAD, NULL, ACT_RELOAD_LOW, }, - { AIP_CROUCHING, ACT_RANGE_ATTACK_SMG1, NULL, ACT_RANGE_ATTACK_SMG1_LOW, }, - { AIP_CROUCHING, ACT_RANGE_ATTACK_AR2, NULL, ACT_RANGE_ATTACK_AR2_LOW, }, - - //---- - { AIP_PEEKING, ACT_IDLE, NULL, ACT_RANGE_AIM_LOW, }, - { AIP_PEEKING, ACT_IDLE_ANGRY, NULL, ACT_RANGE_AIM_LOW, }, - { AIP_PEEKING, ACT_COVER_LOW, NULL, ACT_RANGE_AIM_LOW, }, - { AIP_PEEKING, ACT_RANGE_ATTACK1, NULL, ACT_RANGE_ATTACK1_LOW, }, - { AIP_PEEKING, ACT_RELOAD, NULL, ACT_RELOAD_LOW, }, - }; - - m_ActivityMap.RemoveAll(); - - CBaseCombatWeapon *pWeapon = GetOuter()->GetActiveWeapon(); - const char *pszWeaponClass = ( pWeapon ) ? pWeapon->GetClassname() : ""; - for ( size_t i = 0; i < ARRAYSIZE(mappings); i++ ) - { - if ( !mappings[i].pszWeapon || stricmp( mappings[i].pszWeapon, pszWeaponClass ) == 0 ) - { - if ( HaveSequenceForActivity( mappings[i].translation ) || HaveSequenceForActivity( GetOuter()->Weapon_TranslateActivity( mappings[i].translation ) ) ) - { - Assert( m_ActivityMap.Find( MAKE_ACTMAP_KEY( mappings[i].posture, mappings[i].activity ) ) == m_ActivityMap.InvalidIndex() ); - m_ActivityMap.Insert( MAKE_ACTMAP_KEY( mappings[i].posture, mappings[i].activity ), mappings[i].translation ); - } - } - } -} - -void CAI_StandoffBehavior::UpdateTranslateActivityMap() -{ - BaseClass::UpdateTranslateActivityMap(); - - Activity lowCoverActivity = GetMappedActivity( AIP_CROUCHING, ACT_COVER_LOW ); - if ( lowCoverActivity == ACT_INVALID ) - lowCoverActivity = ACT_COVER_LOW; - - m_bHasLowCoverActivity = ( ( CapabilitiesGet() & bits_CAP_DUCK ) && (GetOuter()->TranslateActivity( lowCoverActivity ) != ACT_INVALID)); - - CBaseCombatWeapon *pWeapon = GetOuter()->GetActiveWeapon(); - if ( pWeapon && (GetOuter()->TranslateActivity( lowCoverActivity ) == ACT_INVALID )) - DevMsg( "Note: NPC class %s lacks ACT_COVER_LOW, therefore cannot participate in standoff\n", GetOuter()->GetClassname() ); -} - -//------------------------------------- - -void CAI_MappedActivityBehavior_Temporary::OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ) -{ - UpdateTranslateActivityMap(); -} - -//------------------------------------- - -void CAI_StandoffBehavior::OnRestore() -{ - UpdateTranslateActivityMap(); -} - -//------------------------------------- - -AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER(CAI_StandoffBehavior) - - DECLARE_CONDITION( COND_ABANDON_TIME_EXPIRED ) - -AI_END_CUSTOM_SCHEDULE_PROVIDER() - -//----------------------------------------------------------------------------- -// -// CAI_StandoffGoal -// -// Purpose: A level tool to control the standoff behavior. Use is not required -// in order to use behavior. -// -//----------------------------------------------------------------------------- - -AI_StandoffParams_t g_StandoffParamsByAgression[] = -{ - // hintChangeReaction, fCoverOnReload, PlayerBtlLn, minTimeShots, maxTimeShots, minShots, maxShots, oddsCover flAbandonTimeLimit - { AIHCR_MOVE_ON_COVER, true, true, 4.0, 8.0, 2, 4, 50, false, 30 }, // AGGR_VERY_LOW - { AIHCR_MOVE_ON_COVER, true, true, 2.0, 5.0, 3, 5, 25, false, 20 }, // AGGR_LOW - { AIHCR_MOVE_ON_COVER, true, true, 0.6, 2.5, 3, 6, 25, false, 10 }, // AGGR_MEDIUM - { AIHCR_MOVE_ON_COVER, true, true, 0.2, 1.5, 5, 8, 10, false, 10 }, // AGGR_HIGH - { AIHCR_MOVE_ON_COVER, false, true, 0, 0, 100, 100, 0, false, 5 }, // AGGR_VERY_HIGH -}; - -//------------------------------------- - -class CAI_StandoffGoal : public CAI_GoalEntity -{ - DECLARE_CLASS( CAI_StandoffGoal, CAI_GoalEntity ); - -public: - CAI_StandoffGoal() - { - m_aggressiveness = AGGR_MEDIUM; - m_fPlayerIsBattleline = true; - m_HintChangeReaction = AIHCR_DEFAULT_AI; - m_fStayAtCover = false; - m_bAbandonIfEnemyHides = false; - m_customParams = AI_DEFAULT_STANDOFF_PARAMS; - } - - //--------------------------------- - - void EnableGoal( CAI_BaseNPC *pAI ) - { - CAI_StandoffBehavior *pBehavior; - if ( !pAI->GetBehavior( &pBehavior ) ) - return; - - pBehavior->SetActive( true ); - SetBehaviorParams( pBehavior); - } - - void DisableGoal( CAI_BaseNPC *pAI ) - { - // @TODO (toml 04-07-03): remove the no damage spawn flag once stable. The implementation isn't very good. - CAI_StandoffBehavior *pBehavior; - if ( !pAI->GetBehavior( &pBehavior ) ) - return; - pBehavior->SetActive( false ); - SetBehaviorParams( pBehavior); - } - - void InputActivate( inputdata_t &inputdata ) - { - ValidateAggression(); - BaseClass::InputActivate( inputdata ); - } - - void InputDeactivate( inputdata_t &inputdata ) - { - ValidateAggression(); - BaseClass::InputDeactivate( inputdata ); - } - - void InputSetAggressiveness( inputdata_t &inputdata ) - { - int newVal = inputdata.value.Int(); - - m_aggressiveness = (Aggressiveness_t)newVal; - ValidateAggression(); - - UpdateActors(); - - const CUtlVector &actors = AccessActors(); - for ( int i = 0; i < actors.Count(); i++ ) - { - CAI_BaseNPC *pAI = actors[i]; - CAI_StandoffBehavior *pBehavior; - if ( !pAI->GetBehavior( &pBehavior ) ) - continue; - SetBehaviorParams( pBehavior); - } - } - - void SetBehaviorParams( CAI_StandoffBehavior *pBehavior ) - { - AI_StandoffParams_t params; - - if ( m_aggressiveness != AGGR_CUSTOM ) - params = g_StandoffParamsByAgression[m_aggressiveness]; - else - params = m_customParams; - - params.hintChangeReaction = m_HintChangeReaction; - params.fPlayerIsBattleline = m_fPlayerIsBattleline; - params.fStayAtCover = m_fStayAtCover; - if ( !m_bAbandonIfEnemyHides ) - params.flAbandonTimeLimit = 0; - - pBehavior->SetParameters( params, this ); - pBehavior->OnChangeTacticalConstraints(); - if ( pBehavior->IsRunning() ) - pBehavior->GetOuter()->ClearSchedule( "Standoff behavior parms changed" ); - } - - void ValidateAggression() - { - if ( m_aggressiveness < AGGR_VERY_LOW || m_aggressiveness > AGGR_VERY_HIGH ) - { - if ( m_aggressiveness != AGGR_CUSTOM ) - { - DevMsg( "Invalid aggressiveness value %d\n", m_aggressiveness ); - - if ( m_aggressiveness < AGGR_VERY_LOW ) - m_aggressiveness = AGGR_VERY_LOW; - else if ( m_aggressiveness > AGGR_VERY_HIGH ) - m_aggressiveness = AGGR_VERY_HIGH; - } - } - } - -private: - //--------------------------------- - - DECLARE_DATADESC(); - - enum Aggressiveness_t - { - AGGR_VERY_LOW, - AGGR_LOW, - AGGR_MEDIUM, - AGGR_HIGH, - AGGR_VERY_HIGH, - - AGGR_CUSTOM, - }; - - Aggressiveness_t m_aggressiveness; - AI_HintChangeReaction_t m_HintChangeReaction; - bool m_fPlayerIsBattleline; - bool m_fStayAtCover; - bool m_bAbandonIfEnemyHides; - AI_StandoffParams_t m_customParams; -}; - -//------------------------------------- - -LINK_ENTITY_TO_CLASS( ai_goal_standoff, CAI_StandoffGoal ); - -BEGIN_DATADESC( CAI_StandoffGoal ) - DEFINE_KEYFIELD( m_aggressiveness, FIELD_INTEGER, "Aggressiveness" ), - // m_customParams (individually) - DEFINE_KEYFIELD( m_HintChangeReaction, FIELD_INTEGER, "HintGroupChangeReaction" ), - DEFINE_KEYFIELD( m_fPlayerIsBattleline, FIELD_BOOLEAN, "PlayerBattleline" ), - DEFINE_KEYFIELD( m_fStayAtCover, FIELD_BOOLEAN, "StayAtCover" ), - DEFINE_KEYFIELD( m_bAbandonIfEnemyHides, FIELD_BOOLEAN, "AbandonIfEnemyHides" ), - DEFINE_KEYFIELD( m_customParams.fCoverOnReload, FIELD_BOOLEAN, "CustomCoverOnReload" ), - DEFINE_KEYFIELD( m_customParams.minTimeShots, FIELD_FLOAT, "CustomMinTimeShots" ), - DEFINE_KEYFIELD( m_customParams.maxTimeShots, FIELD_FLOAT, "CustomMaxTimeShots" ), - DEFINE_KEYFIELD( m_customParams.minShots, FIELD_INTEGER, "CustomMinShots" ), - DEFINE_KEYFIELD( m_customParams.maxShots, FIELD_INTEGER, "CustomMaxShots" ), - DEFINE_KEYFIELD( m_customParams.oddsCover, FIELD_INTEGER, "CustomOddsCover" ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetAggressiveness", InputSetAggressiveness ), -END_DATADESC() - -///----------------------------------------------------------------------------- diff --git a/game/server/ai_behavior_standoff.h b/game/server/ai_behavior_standoff.h deleted file mode 100644 index b8dacf62f..000000000 --- a/game/server/ai_behavior_standoff.h +++ /dev/null @@ -1,232 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Combat behaviors for AIs in a relatively self-preservationist mode. -// Lots of cover taking and attempted shots out of cover. -// -//=============================================================================// - -#ifndef AI_BEHAVIOR_STANDOFF_H -#define AI_BEHAVIOR_STANDOFF_H - -#include "utlvector.h" -#include "utlmap.h" - -#include "ai_behavior.h" -#include "ai_utils.h" -#include "ai_hint.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -//----------------------------------------------------------------------------- - -enum AI_HintChangeReaction_t -{ - AIHCR_DEFAULT_AI, - AIHCR_MOVE_ON_COVER, - AIHCR_MOVE_IMMEDIATE, -}; - -struct AI_StandoffParams_t -{ - AI_HintChangeReaction_t hintChangeReaction; - bool fCoverOnReload; - bool fPlayerIsBattleline; - float minTimeShots; - float maxTimeShots; - int minShots; - int maxShots; - int oddsCover; - bool fStayAtCover; - float flAbandonTimeLimit; - - DECLARE_SIMPLE_DATADESC(); -}; - -//------------------------------------- - -enum AI_Posture_t -{ - AIP_INDIFFERENT, - AIP_STANDING, - AIP_CROUCHING, - AIP_PEEKING, -}; - -enum -{ - STANDOFF_SENTENCE_BEGIN_STANDOFF = SENTENCE_BASE_BEHAVIOR_INDEX, - STANDOFF_SENTENCE_END_STANDOFF, - STANDOFF_SENTENCE_OUT_OF_AMMO, - STANDOFF_SENTENCE_FORCED_TAKE_COVER, - STANDOFF_SENTENCE_STAND_CHECK_TARGET, -}; - -class CAI_MappedActivityBehavior_Temporary : public CAI_SimpleBehavior -{ - DECLARE_CLASS( CAI_MappedActivityBehavior_Temporary, CAI_SimpleBehavior ); -public: - CAI_MappedActivityBehavior_Temporary( CAI_BaseNPC *pOuter = NULL ) - : CAI_SimpleBehavior(pOuter) - { - SetDefLessFunc( m_ActivityMap ); - } - -protected: - Activity GetMappedActivity( AI_Posture_t posture, Activity activity ); - void OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ); - - virtual void UpdateTranslateActivityMap(); - -private: - CUtlMap m_ActivityMap; -}; - -class CAI_StandoffBehavior : public CAI_MappedActivityBehavior_Temporary -{ - DECLARE_CLASS( CAI_StandoffBehavior, CAI_MappedActivityBehavior_Temporary ); -public: - CAI_StandoffBehavior( CAI_BaseNPC *pOuter = NULL ); - - virtual const char *GetName() { return "Standoff"; } - - void SetActive( bool fActive ); - void SetParameters( const AI_StandoffParams_t ¶ms, CAI_GoalEntity *pGoalEntity = NULL ); - - Vector GetStandoffGoalPosition(); - void SetStandoffGoalPosition( const Vector &vecPos ); - void ClearStandoffGoalPosition(); - - AI_Posture_t GetPosture(); - - bool IsActive( void ) { return m_fActive; } - void OnChangeTacticalConstraints(); - - bool CanSelectSchedule(); - bool IsBehindBattleLines( const Vector &point ); - -protected: - void Spawn(); - void BeginScheduleSelection(); - void EndScheduleSelection(); - void PrescheduleThink(); - void GatherConditions(); - int SelectSchedule(); - int TranslateSchedule( int scheduleType ); - void StartTask( const Task_t *pTask ); - void BuildScheduleTestBits(); - virtual void OnUpdateShotRegulator(); - - Activity NPC_TranslateActivity( Activity eNewActivity ); - - bool IsValidCover( const Vector &vecCoverLocation, CAI_Hint const *pHint ); - bool IsValidShootPosition( const Vector &vecCoverLocation, CAI_Node *pNode, CAI_Hint const *pHint ); - - void SetPosture( AI_Posture_t posture ); - - void OnChangeHintGroup( string_t oldGroup, string_t newGroup ); - - virtual int SelectScheduleUpdateWeapon(); - virtual int SelectScheduleCheckCover(); - virtual int SelectScheduleEstablishAim(); - virtual int SelectScheduleAttack(); - - bool PlayerIsLeading(); - CBaseEntity *GetPlayerLeader(); - bool GetDirectionOfStandoff( Vector *pDir ); - - void UpdateBattleLines(); - - Hint_e GetHintType(); - void SetReuseCurrentCover(); - void UnlockHintNode(); - Activity GetCoverActivity(); - - void OnRestore(); - - void UpdateTranslateActivityMap(); - - // Standoff overrides base AI crouch handling - bool IsCrouching( void ) { return false; } - -private: - - //---------------------------- - - enum - { - NEXT_SCHEDULE = BaseClass::NEXT_SCHEDULE, - - NEXT_TASK = BaseClass::NEXT_TASK, - - COND_ABANDON_TIME_EXPIRED = BaseClass::NEXT_CONDITION, - NEXT_CONDITION - }; - - DEFINE_CUSTOM_SCHEDULE_PROVIDER; - - //--------------------------------- - // @TODO (toml 07-30-03): replace all these booleans with a singe 32 bit unsigned & bit flags - - bool m_fActive; - bool m_fTestNoDamage; - - Vector m_vecStandoffGoalPosition; - - AI_Posture_t m_posture; - - AI_StandoffParams_t m_params; - EHANDLE m_hStandoffGoal; - - bool m_fTakeCover; - float m_SavedDistTooFar; - bool m_fForceNewEnemy; - CAI_MoveMonitor m_PlayerMoveMonitor; - - CSimTimer m_TimeForceCoverHint; - CSimTimer m_TimePreventForceNewEnemy; - CRandSimTimer m_RandomCoverChangeTimer; - - // FIXME: TEMPORARY! REMOVE - int m_nSavedMinShots, m_nSavedMaxShots; - float m_flSavedMinRest, m_flSavedMaxRest; - - //--------------------------------- - - struct BattleLine_t - { - Vector point; - Vector normal; - }; - - CThinkOnceSemaphore m_UpdateBattleLinesSemaphore; - CUtlVector m_BattleLines; - bool m_fIgnoreFronts; - - //--------------------------------- - - bool m_bHasLowCoverActivity; - - //--------------------------------- - - DECLARE_DATADESC(); -}; - -//------------------------------------- - -inline void CAI_StandoffBehavior::SetPosture( AI_Posture_t posture ) -{ - m_posture = posture; -} - -//------------------------------------- - -inline AI_Posture_t CAI_StandoffBehavior::GetPosture() -{ - return m_posture; -} - -//----------------------------------------------------------------------------- - -#endif // AI_BEHAVIOR_STANDOFF_H diff --git a/game/server/ai_blended_movement.cpp b/game/server/ai_blended_movement.cpp deleted file mode 100644 index 64427df8c..000000000 --- a/game/server/ai_blended_movement.cpp +++ /dev/null @@ -1,1906 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" - -#include "movevars_shared.h" - -#include "ai_blended_movement.h" -#include "ai_route.h" -#include "ai_navigator.h" -#include "ai_moveprobe.h" -#include "KeyValues.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// -// class CAI_BlendedMotor -// - -BEGIN_SIMPLE_DATADESC( CAI_BlendedMotor ) - // DEFINE_FIELD( m_bDeceleratingToGoal, FIELD_BOOLEAN ), - - // DEFINE_FIELD( m_iPrimaryLayer, FIELD_INTEGER ), - // DEFINE_FIELD( m_iSecondaryLayer, FIELD_INTEGER ), - - // DEFINE_FIELD( m_nPrimarySequence, FIELD_INTEGER ), - // DEFINE_FIELD( m_nSecondarySequence, FIELD_INTEGER ), - // DEFINE_FIELD( m_flSecondaryWeight, FIELD_FLOAT ), - - // DEFINE_CUSTOM_FIELD( m_nSavedGoalActivity, ActivityDataOps() ), - // DEFINE_CUSTOM_FIELD( m_nSavedTranslatedGoalActivity, ActivityDataOps() ), - // DEFINE_FIELD( m_nGoalSequence, FIELD_INTEGER ), - - // DEFINE_FIELD( m_nPrevMovementSequence, FIELD_INTEGER ), - // DEFINE_FIELD( m_nInteriorSequence, FIELD_INTEGER ), - // DEFINE_FIELD( m_flCurrRate, FIELD_FLOAT ), - // DEFINE_FIELD( m_flStartCycle, FIELD_FLOAT ), - - // m_scriptMove - // m_scriptTurn - - // DEFINE_FIELD( m_flNextTurnGesture, FIELD_TIME ), - // DEFINE_FIELD( m_prevYaw, FIELD_FLOAT ), - // DEFINE_FIELD( m_doTurn, FIELD_FLOAT ), - // DEFINE_FIELD( m_doLeft, FIELD_FLOAT ), - // DEFINE_FIELD( m_doRight, FIELD_FLOAT ), - // DEFINE_FIELD( m_flNextTurnAct, FIELD_TIME ), - // DEFINE_FIELD( m_flPredictiveSpeedAdjust, FIELD_FLOAT ), - // DEFINE_FIELD( m_flReactiveSpeedAdjust, FIELD_FLOAT ), - // DEFINE_FIELD( m_vecPrevOrigin1, FIELD_POSITION ), - // DEFINE_FIELD( m_vecPrevOrigin2, FIELD_POSITION ), - -END_DATADESC() - -//------------------------------------- - -void CAI_BlendedMotor::ResetMoveCalculations() -{ - BaseClass::ResetMoveCalculations(); - m_scriptMove.RemoveAll(); - m_scriptTurn.RemoveAll(); -} - -//------------------------------------- - -void CAI_BlendedMotor::MoveStart() -{ - AI_PROFILE_SCOPE(CAI_BlendedMotor_MoveStart); - - if (m_nPrimarySequence == -1) - { - m_nPrimarySequence = GetSequence(); - m_flStartCycle = GetCycle(); - m_flCurrRate = 0.4; - - // Assert( !GetOuter()->HasMovement( m_nStartSequence ) ); - - m_nSecondarySequence = -1; - - m_iPrimaryLayer = AddLayeredSequence( m_nPrimarySequence, 0 ); - SetLayerWeight( m_iPrimaryLayer, 0.0 ); - SetLayerPlaybackRate( m_iPrimaryLayer, 0.0 ); - SetLayerNoRestore( m_iPrimaryLayer, true ); - SetLayerCycle( m_iPrimaryLayer, m_flStartCycle, m_flStartCycle ); - - m_flSecondaryWeight = 0.0; - } - else - { - // suspect that MoveStop() wasn't called when the previous route finished - // Assert( 0 ); - } - - - if (m_nGoalSequence == ACT_INVALID) - { - ResetGoalSequence(); - } - - m_vecPrevOrigin2 = GetAbsOrigin(); - m_vecPrevOrigin1 = GetAbsOrigin(); - - m_bDeceleratingToGoal = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -void CAI_BlendedMotor::ResetGoalSequence( void ) -{ - - m_nSavedGoalActivity = GetNavigator()->GetArrivalActivity( ); - if (m_nSavedGoalActivity == ACT_INVALID) - { - m_nSavedGoalActivity = GetOuter()->GetStoppedActivity(); - } - - m_nSavedTranslatedGoalActivity = GetOuter()->NPC_TranslateActivity( m_nSavedGoalActivity ); - - m_nGoalSequence = GetNavigator()->GetArrivalSequence( m_nPrimarySequence ); - // Msg("Start %s end %s\n", GetOuter()->GetSequenceName( m_nPrimarySequence ), GetOuter()->GetSequenceName( m_nGoalSequence ) ); - - m_nGoalSequence = GetInteriorSequence( m_nPrimarySequence ); - - Assert( m_nGoalSequence != ACT_INVALID ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - - -void CAI_BlendedMotor::MoveStop() -{ - AI_PROFILE_SCOPE(CAI_BlendedMotor_MoveStop); - - CAI_Motor::MoveStop(); - - if (m_iPrimaryLayer != -1) - { - RemoveLayer( m_iPrimaryLayer, 0.2, 0.1 ); - m_iPrimaryLayer = -1; - } - if (m_iSecondaryLayer != -1) - { - RemoveLayer( m_iSecondaryLayer, 0.2, 0.1 ); - m_iSecondaryLayer = -1; - } - m_nPrimarySequence = ACT_INVALID; - m_nSecondarySequence = ACT_INVALID; - m_nPrevMovementSequence = ACT_INVALID; - m_nInteriorSequence = ACT_INVALID; - - // int nNextSequence = FindTransitionSequence(GetSequence(), m_nIdealSequence, NULL); -} - -void CAI_BlendedMotor::MovePaused() -{ - CAI_Motor::MovePaused(); - SetMoveScriptAnim( 0.0 ); -} - - -void CAI_BlendedMotor::MoveContinue() -{ - AI_PROFILE_SCOPE(CAI_BlendedMotor_MoveContinue); - - m_nPrimarySequence = GetInteriorSequence( ACT_INVALID ); - m_nGoalSequence = m_nPrimarySequence; - - Assert( m_nPrimarySequence != ACT_INVALID ); - - if (m_nPrimarySequence == ACT_INVALID) - return; - - m_flStartCycle = 0.0; - - m_iPrimaryLayer = AddLayeredSequence( m_nPrimarySequence, 0 ); - SetLayerWeight( m_iPrimaryLayer, 0.0 ); - SetLayerPlaybackRate( m_iPrimaryLayer, 0.0 ); - SetLayerNoRestore( m_iPrimaryLayer, true ); - SetLayerCycle( m_iPrimaryLayer, m_flStartCycle, m_flStartCycle ); - - m_bDeceleratingToGoal = false; -} - - -//----------------------------------------------------------------------------- -// Purpose: for the MoveInterval, interpolate desired speed, calc actual distance traveled -//----------------------------------------------------------------------------- -float CAI_BlendedMotor::GetMoveScriptDist( float &flNewSpeed ) -{ - AI_PROFILE_SCOPE(CAI_BlendedMotor_GetMoveScriptDist); - - int i; - float flTotalDist = 0; - float t = GetMoveInterval(); - - Assert( m_scriptMove.Count() > 1); - - flNewSpeed = 0; - for (i = 0; i < m_scriptMove.Count()-1; i++) - { - if (t < m_scriptMove[i].flTime) - { - // get new velocity - float a = t / m_scriptMove[i].flTime; - flNewSpeed = m_scriptMove[i].flMaxVelocity * (1 - a) + m_scriptMove[i+1].flMaxVelocity * a; - - // get distance traveled over this entry - flTotalDist += (m_scriptMove[i].flMaxVelocity + flNewSpeed) * 0.5 * t; - break; - } - else - { - // used all of entries time, get entries total movement - flNewSpeed = m_scriptMove[i+1].flMaxVelocity; - flTotalDist += m_scriptMove[i].flDist; - t -= m_scriptMove[i].flTime; - } - } - - return flTotalDist; -} - - -//----------------------------------------------------------------------------- -// Purpose: return the total time that the move script covers -//----------------------------------------------------------------------------- - -float CAI_BlendedMotor::GetMoveScriptTotalTime() -{ - float flDist = GetNavigator()->GetArrivalDistance(); - - int i = m_scriptMove.Count() - 1; - - if (i < 0) - return -1; - - while (i > 0 && flDist > 1) - { - flDist -= m_scriptMove[i].flDist; - i--; - } - return m_scriptMove[i].flElapsedTime; -} - - -//----------------------------------------------------------------------------- -// Purpose: for the MoveInterval, interpolate desired angle -//----------------------------------------------------------------------------- - -float CAI_BlendedMotor::GetMoveScriptYaw( void ) -{ - int i; - - // interpolate desired angle - float flNewYaw = GetAbsAngles().y; - float t = GetMoveInterval(); - for (i = 0; i < m_scriptTurn.Count()-1; i++) - { - if (t < m_scriptTurn[i].flTime) - { - // get new direction - float a = t / m_scriptTurn[i].flTime; - float deltaYaw = UTIL_AngleDiff( m_scriptTurn[i+1].flYaw, m_scriptTurn[i].flYaw ); - flNewYaw = UTIL_AngleMod( m_scriptTurn[i].flYaw + a * deltaYaw ); - break; - } - else - { - t -= m_scriptTurn[i].flTime; - } - } - - return flNewYaw; -} - -//----------------------------------------------------------------------------- -// Purpose: blend in the "idle" or "arrival" animation depending on speed -//----------------------------------------------------------------------------- - -void CAI_BlendedMotor::SetMoveScriptAnim( float flNewSpeed ) -{ - AI_PROFILE_SCOPE(CAI_BlendedMotor_SetMoveScriptAnim); - - // don't bother if the npc is dead - if (!GetOuter()->IsAlive()) - return; - - // insert ideal layers - // FIXME: needs full transitions, as well as starting vs stopping sequences, leaning, etc. - - CAI_Navigator *pNavigator = GetNavigator(); - - SetPlaybackRate( m_flCurrRate ); - // calc weight of idle animation layer that suppresses the run animation - float flWeight = 0.0; - if (GetIdealSpeed() > 0.0) - { - flWeight = 1.0 - (flNewSpeed / (GetIdealSpeed() * GetPlaybackRate())); - } - if (flWeight < 0.0) - { - m_flCurrRate = flNewSpeed / GetIdealSpeed(); - m_flCurrRate = clamp( m_flCurrRate, 0.0, 1.0 ); - SetPlaybackRate( m_flCurrRate ); - flWeight = 0.0; - } - // Msg("weight %.3f rate %.3f\n", flWeight, m_flCurrRate ); - m_flCurrRate = MIN( m_flCurrRate + (1.0 - m_flCurrRate) * 0.8, 1.0 ); - - if (m_nSavedGoalActivity == ACT_INVALID) - { - ResetGoalSequence(); - } - - // detect state change - Activity activity = GetOuter()->NPC_TranslateActivity( m_nSavedGoalActivity ); - if ( activity != m_nSavedTranslatedGoalActivity ) - { - m_nSavedTranslatedGoalActivity = activity; - m_nInteriorSequence = ACT_INVALID; - m_nGoalSequence = pNavigator->GetArrivalSequence( m_nPrimarySequence ); - } - - if (m_bDeceleratingToGoal) - { - // find that sequence to play when at goal - m_nGoalSequence = pNavigator->GetArrivalSequence( m_nPrimarySequence ); - - if (m_nGoalSequence == ACT_INVALID) - { - m_nGoalSequence = GetInteriorSequence( m_nPrimarySequence ); - } - - Assert( m_nGoalSequence != ACT_INVALID ); - } - - if (m_flSecondaryWeight == 1.0 || (m_iSecondaryLayer != -1 && m_nPrimarySequence == m_nSecondarySequence)) - { - // secondary layer at full strength last time, delete the primary and shift down - RemoveLayer( m_iPrimaryLayer, 0.0, 0.0 ); - - m_iPrimaryLayer = m_iSecondaryLayer; - m_nPrimarySequence = m_nSecondarySequence; - m_iSecondaryLayer = -1; - m_nSecondarySequence = ACT_INVALID; - m_flSecondaryWeight = 0.0; - } - - // look for transition sequence if needed - if (m_nSecondarySequence == ACT_INVALID) - { - if (!m_bDeceleratingToGoal && m_nGoalSequence != GetInteriorSequence( m_nPrimarySequence )) - { - // strob interior sequence in case it changed - m_nGoalSequence = GetInteriorSequence( m_nPrimarySequence ); - } - - if (m_nGoalSequence != ACT_INVALID && m_nPrimarySequence != m_nGoalSequence) - { - // Msg("From %s to %s\n", GetOuter()->GetSequenceName( m_nPrimarySequence ), GetOuter()->GetSequenceName( m_nGoalSequence ) ); - m_nSecondarySequence = GetOuter()->FindTransitionSequence(m_nPrimarySequence, m_nGoalSequence, NULL); - if (m_nSecondarySequence == ACT_INVALID) - m_nSecondarySequence = m_nGoalSequence; - } - } - - // set blending for - if (m_nSecondarySequence != ACT_INVALID) - { - if (m_iSecondaryLayer == -1) - { - m_iSecondaryLayer = AddLayeredSequence( m_nSecondarySequence, 0 ); - SetLayerWeight( m_iSecondaryLayer, 0.0 ); - if (m_nSecondarySequence == m_nGoalSequence) - { - SetLayerPlaybackRate( m_iSecondaryLayer, 0.0 ); - } - else - { - SetLayerPlaybackRate( m_iSecondaryLayer, 1.0 ); - } - SetLayerNoRestore( m_iSecondaryLayer, true ); - m_flSecondaryWeight = 0.0; - } - - m_flSecondaryWeight = MIN( m_flSecondaryWeight + 0.3, 1.0 ); - - if (m_flSecondaryWeight < 1.0) - { - SetLayerWeight( m_iPrimaryLayer, (flWeight - m_flSecondaryWeight * flWeight) / (1.0f - m_flSecondaryWeight * flWeight) ); - SetLayerWeight( m_iSecondaryLayer, flWeight * m_flSecondaryWeight ); - } - else - { - SetLayerWeight( m_iPrimaryLayer, 0.0f ); - SetLayerWeight( m_iSecondaryLayer, flWeight ); - } - } - else - { - // recreate layer if missing - if (m_iPrimaryLayer == -1) - { - MoveContinue(); - } - - // try to catch a stale layer - if (m_iSecondaryLayer != -1) - { - // secondary layer at full strength last time, delete the primary and shift down - RemoveLayer( m_iSecondaryLayer, 0.0, 0.0 ); - m_iSecondaryLayer = -1; - m_nSecondarySequence = ACT_INVALID; - m_flSecondaryWeight = 0.0; - } - - // debounce - // flWeight = flWeight * 0.5 + 0.5 * GetOuter()->GetLayerWeight( m_iPrimaryLayer ); - SetLayerWeight( m_iPrimaryLayer, flWeight ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: get the "idle" animation to play as the compliment to the movement animation -//----------------------------------------------------------------------------- -int CAI_BlendedMotor::GetInteriorSequence( int fromSequence ) -{ - AI_PROFILE_SCOPE(CAI_BlendedMotor_GetInteriorSequence); - - // FIXME: add interior activity to path, just like arrival activity. - int sequence = GetNavigator()->GetMovementSequence(); - - if (m_nInteriorSequence != ACT_INVALID && sequence == m_nPrevMovementSequence) - { - return m_nInteriorSequence; - } - - m_nPrevMovementSequence = sequence; - - KeyValues *seqKeyValues = GetOuter()->GetSequenceKeyValues( sequence ); - // Msg("sequence %d : %s (%d)\n", sequence, GetOuter()->GetSequenceName( sequence ), seqKeyValues != NULL ); - if (seqKeyValues) - { - KeyValues *pkvInterior = seqKeyValues->FindKey("interior"); - if (pkvInterior) - { - const char *szActivity = pkvInterior->GetString(); - - Activity activity = ( Activity )GetOuter()->LookupActivity( szActivity ); - if ( activity != ACT_INVALID ) - { - m_nInteriorSequence = GetOuter()->SelectWeightedSequence( GetOuter()->TranslateActivity( activity ), fromSequence ); - } - else - { - activity = (Activity)GetOuter()->GetActivityID( szActivity ); - if ( activity != ACT_INVALID ) - { - m_nInteriorSequence = GetOuter()->SelectWeightedSequence( GetOuter()->TranslateActivity( activity ), fromSequence ); - } - } - - if (activity == ACT_INVALID || m_nInteriorSequence == ACT_INVALID) - { - m_nInteriorSequence = GetOuter()->LookupSequence( szActivity ); - } - } - } - - if (m_nInteriorSequence == ACT_INVALID) - { - Activity activity = GetNavigator()->GetMovementActivity(); - if (activity == ACT_WALK_AIM || activity == ACT_RUN_AIM) - { - activity = ACT_IDLE_ANGRY; - } - else - { - activity = ACT_IDLE; - } - m_nInteriorSequence = GetOuter()->SelectWeightedSequence( GetOuter()->TranslateActivity( activity ), fromSequence ); - - Assert( m_nInteriorSequence != ACT_INVALID ); - } - - return m_nInteriorSequence; -} - - - - -//----------------------------------------------------------------------------- -// Purpose: Move the npc to the next location on its route. -//----------------------------------------------------------------------------- - -AIMotorMoveResult_t CAI_BlendedMotor::MoveGroundExecute( const AILocalMoveGoal_t &move, AIMoveTrace_t *pTraceResult ) -{ - AI_PROFILE_SCOPE(CAI_BlendedMotor_MoveGroundExecute); - - if ( move.curExpectedDist < 0.001 ) - { - AIMotorMoveResult_t result = BaseClass::MoveGroundExecute( move, pTraceResult ); - // Msg(" BaseClass::MoveGroundExecute() - remaining %.2f\n", GetMoveInterval() ); - SetMoveScriptAnim( 0.0 ); - return result; - } - - BuildMoveScript( move, pTraceResult ); - - float flNewSpeed = GetCurSpeed(); - float flTotalDist = GetMoveScriptDist( flNewSpeed ); - - Assert( move.maxDist < 0.01 || flTotalDist > 0.0 ); - - // -------------------------------------------- - // turn in the direction of movement - // -------------------------------------------- - - float flNewYaw = GetMoveScriptYaw( ); - - // get facing based on movement yaw - AILocalMoveGoal_t move2 = move; - move2.facing = UTIL_YawToVector( flNewYaw ); - - // turn in the direction needed - MoveFacing( move2 ); - - // reset actual "sequence" ground speed based current movement sequence, orientation - - // FIXME: this should be based on - - GetOuter()->m_flGroundSpeed = GetSequenceGroundSpeed( GetSequence()); - - - - /* - if (1 || flNewSpeed > GetIdealSpeed()) - { - // DevMsg( "%6.2f : Speed %.1f : %.1f (%.1f) : %d\n", gpGlobals->curtime, flNewSpeed, move.maxDist, move.transitionDist, GetOuter()->m_pHintNode != NULL ); - // DevMsg( "%6.2f : Speed %.1f : %.1f\n", gpGlobals->curtime, flNewSpeed, GetIdealSpeed() ); - } - */ - - SetMoveScriptAnim( flNewSpeed ); - - /* - if ((GetOuter()->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT)) - { - DevMsg( "%6.2f : Speed %.1f : %.1f : %.2f\n", gpGlobals->curtime, flNewSpeed, GetIdealSpeed(), flNewSpeed / GetIdealSpeed() ); - } - */ - - AIMotorMoveResult_t result = MoveGroundExecuteWalk( move, flNewSpeed, flTotalDist, pTraceResult ); - - return result; - -} - - - - -AIMotorMoveResult_t CAI_BlendedMotor::MoveFlyExecute( const AILocalMoveGoal_t &move, AIMoveTrace_t *pTraceResult ) -{ - AI_PROFILE_SCOPE(CAI_BlendedMotor_MoveFlyExecute); - - if ( move.curExpectedDist < 0.001 ) - return BaseClass::MoveFlyExecute( move, pTraceResult ); - - BuildMoveScript( move, pTraceResult ); - - float flNewSpeed = GetCurSpeed(); - float flTotalDist = GetMoveScriptDist( flNewSpeed ); - - Assert( move.maxDist < 0.01 || flTotalDist > 0.0 ); - - // -------------------------------------------- - // turn in the direction of movement - // -------------------------------------------- - - float flNewYaw = GetMoveScriptYaw( ); - - // get facing based on movement yaw - AILocalMoveGoal_t move2 = move; - move2.facing = UTIL_YawToVector( flNewYaw ); - - // turn in the direction needed - MoveFacing( move2 ); - - GetOuter()->m_flGroundSpeed = GetSequenceGroundSpeed( GetSequence()); - - SetMoveScriptAnim( flNewSpeed ); - - // DevMsg( "%6.2f : Speed %.1f : %.1f\n", gpGlobals->curtime, flNewSpeed, GetIdealSpeed() ); - - // reset actual "sequence" ground speed based current movement sequence, orientation - - // FIXME: the above is redundant with MoveGroundExecute, and the below is a mix of MoveGroundExecuteWalk and MoveFlyExecute - - bool bReachingLocalGoal = ( flTotalDist > move.maxDist ); - - // can I move farther in this interval than I'm supposed to? - if ( bReachingLocalGoal ) - { - if ( !(move.flags & AILMG_CONSUME_INTERVAL) ) - { - // only use a portion of the time interval - SetMoveInterval( GetMoveInterval() * (1 - move.maxDist / flTotalDist) ); - } - else - SetMoveInterval( 0 ); - flTotalDist = move.maxDist; - } - else - { - // use all the time - SetMoveInterval( 0 ); - } - - SetMoveVel( move.dir * flNewSpeed ); - - // orig - Vector vecStart, vecEnd; - vecStart = GetLocalOrigin(); - VectorMA( vecStart, flTotalDist, move.dir, vecEnd ); - - AIMoveTrace_t moveTrace; - GetMoveProbe()->MoveLimit( NAV_FLY, vecStart, vecEnd, MASK_NPCSOLID, NULL, &moveTrace ); - if ( pTraceResult ) - *pTraceResult = moveTrace; - - // Check for total blockage - if (fabs(moveTrace.flDistObstructed - flTotalDist) <= 1e-1) - { - // But if we bumped into our target, then we succeeded! - if ( move.pMoveTarget && (moveTrace.pObstruction == move.pMoveTarget) ) - return AIM_PARTIAL_HIT_TARGET; - - return AIM_FAILED; - } - - // The true argument here causes it to touch all triggers - // in the volume swept from the previous position to the current position - UTIL_SetOrigin(GetOuter(), moveTrace.vEndPosition, true); - - return (IsMoveBlocked(moveTrace.fStatus)) ? AIM_PARTIAL_HIT_WORLD : AIM_SUCCESS; -} - - - - -float CAI_BlendedMotor::OverrideMaxYawSpeed( Activity activity ) -{ - // Don't do this is we're locked - if ( IsYawLocked() ) - return 0.0f; - - switch( activity ) - { - case ACT_TURN_LEFT: - case ACT_TURN_RIGHT: - return 45; - break; - default: - if (GetOuter()->IsMoving()) - { - return 15; - } - return 45; // too fast? - break; - } - return -1; -} - - - -void CAI_BlendedMotor::UpdateYaw( int speed ) -{ - // Don't do this is we're locked - if ( IsYawLocked() ) - return; - - GetOuter()->UpdateTurnGesture( ); - BaseClass::UpdateYaw( speed ); -} - - - -void CAI_BlendedMotor::RecalculateYawSpeed() -{ - // Don't do this is we're locked - if ( IsYawLocked() ) - { - SetYawSpeed( 0.0f ); - return; - } - - if (GetOuter()->HasMemory( bits_MEMORY_TURNING )) - return; - - SetYawSpeed( CalcYawSpeed() ); -} - - -//------------------------------------- - - -void CAI_BlendedMotor::MoveClimbStart( const Vector &climbDest, const Vector &climbDir, float climbDist, float yaw ) -{ - // TODO: merge transitions with movement script - if (m_iPrimaryLayer != -1) - { - SetLayerWeight( m_iPrimaryLayer, 0 ); - } - if (m_iSecondaryLayer != -1) - { - SetLayerWeight( m_iSecondaryLayer, 0 ); - } - - BaseClass::MoveClimbStart( climbDest, climbDir, climbDist, yaw ); -} - - -//------------------------------------- - - -void CAI_BlendedMotor::MoveJumpStart( const Vector &velocity ) -{ - // TODO: merge transitions with movement script - if (m_iPrimaryLayer != -1) - { - SetLayerWeight( m_iPrimaryLayer, 0 ); - } - if (m_iSecondaryLayer != -1) - { - SetLayerWeight( m_iSecondaryLayer, 0 ); - } - - BaseClass::MoveJumpStart( velocity ); -} - - -//------------------------------------- - -void CAI_BlendedMotor::BuildMoveScript( const AILocalMoveGoal_t &move, AIMoveTrace_t *pTraceResult ) -{ - m_scriptMove.RemoveAll(); - m_scriptTurn.RemoveAll(); - - BuildVelocityScript( move ); - BuildTurnScript( move ); - -/* - if (GetOuter()->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) - { - int i; -#if 1 - - for (i = 1; i < m_scriptMove.Count(); i++) - { - NDebugOverlay::Line( m_scriptMove[i-1].vecLocation, m_scriptMove[i].vecLocation, 255,255,255, true, 0.1 ); - - NDebugOverlay::Box( m_scriptMove[i].vecLocation, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), 0,255,255, 0, 0.1 ); - - //NDebugOverlay::Line( m_scriptMove[i].vecLocation, m_scriptMove[i].vecLocation + Vector( 0,0,m_scriptMove[i].flMaxVelocity), 0,255,255, true, 0.1 ); - - Vector vecMidway = m_scriptMove[i].vecLocation + ((m_scriptMove[i-1].vecLocation - m_scriptMove[i].vecLocation) * 0.5); - NDebugOverlay::Text( vecMidway, UTIL_VarArgs( "%d", i ), false, 0.1 ); - } -#endif -#if 0 - for (i = 1; i < m_scriptTurn.Count(); i++) - { - NDebugOverlay::Line( m_scriptTurn[i-1].vecLocation, m_scriptTurn[i].vecLocation, 255,255,255, true, 0.1 ); - - NDebugOverlay::Box( m_scriptTurn[i].vecLocation, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), 255,0,0, 0, 0.1 ); - - NDebugOverlay::Line( m_scriptTurn[i].vecLocation + Vector( 0,0,1), m_scriptTurn[i].vecLocation + Vector( 0,0,1) + UTIL_YawToVector( m_scriptTurn[i].flYaw ) * 32, 255,0,0, true, 0.1 ); - } -#endif - } -*/ -} - - -#define YAWSPEED 150 - - -void CAI_BlendedMotor::BuildTurnScript( const AILocalMoveGoal_t &move ) -{ - AI_PROFILE_SCOPE(CAI_BlendedMotor_BuildTurnScript); - - int i; - - AI_Movementscript_t script; - script.Init(); - - // current location - script.vecLocation = GetAbsOrigin(); - script.flYaw = GetAbsAngles().y; - m_scriptTurn.AddToTail( script ); - - //------------------------- - - // insert default turn parameters, try to turn 80% to goal at all corners before getting there - int prev = 0; - for (i = 0; i < m_scriptMove.Count(); i++) - { - AI_Waypoint_t *pCurWaypoint = m_scriptMove[i].pWaypoint; - if (pCurWaypoint) - { - script.Init(); - script.vecLocation = pCurWaypoint->vecLocation; - script.pWaypoint = pCurWaypoint; - script.flElapsedTime = m_scriptMove[i].flElapsedTime; - - m_scriptTurn[prev].flTime = script.flElapsedTime - m_scriptTurn[prev].flElapsedTime; - - if (pCurWaypoint->GetNext()) - { - Vector d1 = pCurWaypoint->GetNext()->vecLocation - script.vecLocation; - Vector d2 = script.vecLocation - m_scriptTurn[prev].vecLocation; - - d1.z = 0; - VectorNormalize( d1 ); - d2.z = 0; - VectorNormalize( d2 ); - - float y1 = UTIL_VecToYaw( d1 ); - float y2 = UTIL_VecToYaw( d2 ); - - float deltaYaw = fabs( UTIL_AngleDiff( y1, y2 ) ); - - if (deltaYaw > 0.1) - { - // turn to 80% of goal - script.flYaw = UTIL_ApproachAngle( y1, y2, deltaYaw * 0.8 ); - m_scriptTurn.AddToTail( script ); - // DevMsg("turn waypoint %.1f %.1f %.1f\n", script.vecLocation.x, script.vecLocation.y, script.vecLocation.z ); - prev++; - } - } - else - { - Vector vecDir = GetNavigator()->GetArrivalDirection(); - script.flYaw = UTIL_VecToYaw( vecDir ); - m_scriptTurn.AddToTail( script ); - // DevMsg("turn waypoint %.1f %.1f %.1f\n", script.vecLocation.x, script.vecLocation.y, script.vecLocation.z ); - prev++; - } - } - } - - // propagate ending facing back over any nearby nodes - // FIXME: this needs to minimize total turning, not just local/end turning. - // depending on waypoint spacing, complexity, it may turn the wrong way! - for (i = m_scriptTurn.Count()-1; i > 1; i--) - { - float deltaYaw = UTIL_AngleDiff( m_scriptTurn[i-1].flYaw, m_scriptTurn[i].flYaw ); - - float maxYaw = YAWSPEED * m_scriptTurn[i-1].flTime; - - if (fabs(deltaYaw) > maxYaw) - { - m_scriptTurn[i-1].flYaw = UTIL_ApproachAngle( m_scriptTurn[i-1].flYaw, m_scriptTurn[i].flYaw, maxYaw ); - } - } - - for (i = 0; i < m_scriptTurn.Count() - 1; ) - { - i = i + BuildTurnScript( i, i + 1 ) + 1; - } - //------------------------- -} - - - -int CAI_BlendedMotor::BuildTurnScript( int i, int j ) -{ - AI_PROFILE_SCOPE(CAI_BlendedMotor_BuildTurnScript2); - - int k; - - Vector vecDir = m_scriptTurn[j].vecLocation - m_scriptTurn[i].vecLocation; - float interiorYaw = UTIL_VecToYaw( vecDir ); - - float deltaYaw; - - deltaYaw = fabs( UTIL_AngleDiff( interiorYaw, m_scriptTurn[i].flYaw ) ); - float t1 = deltaYaw / YAWSPEED; - - deltaYaw = fabs( UTIL_AngleDiff( m_scriptTurn[j].flYaw, interiorYaw ) ); - float t2 = deltaYaw / YAWSPEED; - - float totalTime = m_scriptTurn[j].flElapsedTime - m_scriptTurn[i].flElapsedTime; - - Assert( totalTime > 0 ); - - if (t1 < 0.01) - { - if (t2 > totalTime * 0.8) - { - // too close, nothing to do - return 0; - } - - // go ahead and force yaw - m_scriptTurn[i].flYaw = interiorYaw; - - // we're already aiming close enough to the interior yaw, set the point where we need to blend out - k = BuildInsertNode( i, totalTime - t2 ); - m_scriptTurn[k].flYaw = interiorYaw; - - return 1; - } - else if (t2 < 0.01) - { - if (t1 > totalTime * 0.8) - { - // too close, nothing to do - return 0; - } - - // we'll finish up aiming close enough to the interior yaw, set the point where we need to blend in - k = BuildInsertNode( i, t1 ); - m_scriptTurn[k].flYaw = interiorYaw; - - return 1; - } - else if (t1 + t2 > totalTime) - { - // don't bother with interior node - return 0; - - // waypoints need to much turning, ignore interior yaw - float a = (t1 / (t1 + t2)); - t1 = a * totalTime; - - k = BuildInsertNode( i, t1 ); - - deltaYaw = UTIL_AngleDiff( m_scriptTurn[j].flYaw, m_scriptTurn[i].flYaw ); - m_scriptTurn[k].flYaw = UTIL_ApproachAngle( m_scriptTurn[j].flYaw, m_scriptTurn[i].flYaw, deltaYaw * (1 - a) ); - - return 1; - } - else if (t1 + t2 < totalTime * 0.8) - { - // turn to face interior, run a ways, then turn away - k = BuildInsertNode( i, t1 ); - m_scriptTurn[k].flYaw = interiorYaw; - - k = BuildInsertNode( i, t2 ); - m_scriptTurn[k].flYaw = interiorYaw; - - return 2; - } - return 0; -} - - -int CAI_BlendedMotor::BuildInsertNode( int i, float flTime ) -{ - AI_Movementscript_t script; - script.Init(); - - Assert( flTime > 0.0 ); - - for (; i < m_scriptTurn.Count() - 1; i++) - { - if (m_scriptTurn[i].flTime < flTime) - { - flTime -= m_scriptTurn[i].flTime; - } - else - { - float a = flTime / m_scriptTurn[i].flTime; - - script.flTime = (m_scriptTurn[i].flTime - flTime); - - m_scriptTurn[i].flTime = flTime; - - script.flElapsedTime = m_scriptTurn[i].flElapsedTime * (1 - a) + m_scriptTurn[i+1].flElapsedTime * a; - - script.vecLocation = m_scriptTurn[i].vecLocation * (1 - a) + m_scriptTurn[i+1].vecLocation * a; - - m_scriptTurn.InsertAfter( i, script ); - - return i + 1; - } - } - Assert( 0 ); - return 0; -} - - -ConVar ai_path_insert_pause_at_obstruction( "ai_path_insert_pause_at_obstruction", "1" ); -ConVar ai_path_adjust_speed_on_immediate_turns( "ai_path_adjust_speed_on_immediate_turns", "1" ); -ConVar ai_path_insert_pause_at_est_end( "ai_path_insert_pause_at_est_end", "1" ); - -#define MIN_VELOCITY 0.0f -#define MIN_STEER_DOT 0.0f - -void CAI_BlendedMotor::BuildVelocityScript( const AILocalMoveGoal_t &move ) -{ - AI_PROFILE_SCOPE(CAI_BlendedMotor_BuildVelocityScript); - - int i; - float a; - - float idealVelocity = GetIdealSpeed(); - if (idealVelocity == 0) - { - idealVelocity = 50; - } - - float idealAccel = GetIdealAccel(); - if (idealAccel == 0) - { - idealAccel = 100; - } - - AI_Movementscript_t script; - - // set current location as start of script - script.vecLocation = GetAbsOrigin(); - script.flMaxVelocity = GetCurSpeed(); - m_scriptMove.AddToTail( script ); - - //------------------------- - - extern ConVar npc_height_adjust; - if (npc_height_adjust.GetBool() && move.bHasTraced && move.directTrace.flTotalDist != move.thinkTrace.flTotalDist) - { - float flDist = (move.directTrace.vEndPosition - m_scriptMove[0].vecLocation).Length2D(); - float flHeight = move.directTrace.vEndPosition.z - m_scriptMove[0].vecLocation.z; - float flDelta; - - if (flDist > 0) - { - flDelta = flHeight / flDist; - } - else - { - flDelta = 0; - } - - m_flPredictiveSpeedAdjust = 1.1 - fabs( flDelta ); - m_flPredictiveSpeedAdjust = clamp( m_flPredictiveSpeedAdjust, (flHeight > 0.0) ? 0.5 : 0.8, 1.0 ); - - /* - if ((GetOuter()->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT)) - { - Msg("m_flPredictiveSpeedAdjust %.3f %.1f %.1f\n", m_flPredictiveSpeedAdjust, flHeight, flDist ); - NDebugOverlay::Box( move.directTrace.vEndPosition, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), 0,255,255, 0, 0.12 ); - } - */ - } - if (npc_height_adjust.GetBool()) - { - float flDist = (move.thinkTrace.vEndPosition - m_vecPrevOrigin2).Length2D(); - float flHeight = move.thinkTrace.vEndPosition.z - m_vecPrevOrigin2.z; - float flDelta; - - if (flDist > 0) - { - flDelta = flHeight / flDist; - } - else - { - flDelta = 0; - } - - float newSpeedAdjust = 1.1 - fabs( flDelta ); - newSpeedAdjust = clamp( newSpeedAdjust, (flHeight > 0.0) ? 0.5 : 0.8, 1.0 ); - - // debounce speed adjust - if (newSpeedAdjust < m_flReactiveSpeedAdjust) - { - m_flReactiveSpeedAdjust = m_flReactiveSpeedAdjust * 0.2 + newSpeedAdjust * 0.8; - } - else - { - m_flReactiveSpeedAdjust = m_flReactiveSpeedAdjust * 0.5 + newSpeedAdjust * 0.5; - } - - // filter through origins - m_vecPrevOrigin2 = m_vecPrevOrigin1; - m_vecPrevOrigin1 = GetAbsOrigin(); - - /* - if ((GetOuter()->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT)) - { - NDebugOverlay::Box( m_vecPrevOrigin2, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), 255,0,255, 0, 0.12 ); - NDebugOverlay::Box( move.thinkTrace.vEndPosition, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), 255,0,255, 0, 0.12 ); - Msg("m_flReactiveSpeedAdjust %.3f %.1f %.1f\n", m_flReactiveSpeedAdjust, flHeight, flDist ); - } - */ - } - - idealVelocity = idealVelocity * MIN( m_flReactiveSpeedAdjust, m_flPredictiveSpeedAdjust ); - - //------------------------- - - bool bAddedExpected = false; - - // add all waypoint locations and velocities - AI_Waypoint_t *pCurWaypoint = GetNavigator()->GetPath()->GetCurWaypoint(); - - // there has to be at least one waypoint - Assert( pCurWaypoint ); - - while (pCurWaypoint && (pCurWaypoint->NavType() == NAV_GROUND || pCurWaypoint->NavType() == NAV_FLY) /*&& flTotalDist / idealVelocity < 3.0*/) // limit lookahead to 3 seconds - { - script.Init(); - AI_Waypoint_t *pNext = pCurWaypoint->GetNext(); - - if (ai_path_adjust_speed_on_immediate_turns.GetBool() && !bAddedExpected) - { - // hack in next expected immediate location for move - script.vecLocation = GetAbsOrigin() + move.dir * move.curExpectedDist; - bAddedExpected = true; - pNext = pCurWaypoint; - } - else - { - script.vecLocation = pCurWaypoint->vecLocation; - script.pWaypoint = pCurWaypoint; - } - - //DevMsg("waypoint %.1f %.1f %.1f\n", script.vecLocation.x, script.vecLocation.y, script.vecLocation.z ); - - if (pNext) - { - switch( pNext->NavType()) - { - case NAV_GROUND: - case NAV_FLY: - { - Vector d1 = pNext->vecLocation - script.vecLocation; - Vector d2 = script.vecLocation - m_scriptMove[m_scriptMove.Count()-1].vecLocation; - - // remove very short, non terminal ground links - // FIXME: is this safe? Maybe just check for co-located ground points? - if (d1.Length2D() < 1.0) - { - /* - if (m_scriptMove.Count() > 1) - { - int i = m_scriptMove.Count() - 1; - m_scriptMove[i].vecLocation = pCurWaypoint->vecLocation; - m_scriptMove[i].pWaypoint = pCurWaypoint; - } - */ - pCurWaypoint = pNext; - continue; - } - - d1.z = 0; - VectorNormalize( d1 ); - d2.z = 0; - VectorNormalize( d2 ); - - // figure velocity - float dot = (DotProduct( d1, d2 ) + 0.2); - if (dot > 0) - { - dot = clamp( dot, 0.0f, 1.0f ); - script.flMaxVelocity = idealVelocity * dot; - } - else - { - script.flMaxVelocity = 0; - } - } - break; - case NAV_JUMP: - - // FIXME: information about what the jump should look like isn't stored in the waypoints - // this'll need to call - // GetMoveProbe()->MoveLimit( NAV_JUMP, GetLocalOrigin(), GetPath()->CurWaypointPos(), MASK_NPCSOLID, GetNavTargetEntity(), &moveTrace ); - // to get how far/fast the jump will be, but this is also stateless, so it'd call it per frame. - // So far it's not clear that the moveprobe doesn't also call this..... - - { - float minJumpHeight = 0; - float maxHorzVel = MAX( GetCurSpeed(), 100 ); - float gravity = sv_gravity.GetFloat() * GetOuter()->GetGravity(); - Vector vecApex; - Vector rawJumpVel = GetMoveProbe()->CalcJumpLaunchVelocity(script.vecLocation, pNext->vecLocation, gravity, &minJumpHeight, maxHorzVel, &vecApex ); - - script.flMaxVelocity = rawJumpVel.Length2D(); - // Msg("%.1f\n", script.flMaxVelocity ); - } - break; - case NAV_CLIMB: - { - /* - CAI_Node *pClimbNode = GetNavigator()->GetNetwork()->GetNode(pNext->iNodeID); - - check: pClimbNode->m_eNodeInfo - bits_NODE_CLIMB_BOTTOM, - bits_NODE_CLIMB_ON, - bits_NODE_CLIMB_OFF_FORWARD, - bits_NODE_CLIMB_OFF_LEFT, - bits_NODE_CLIMB_OFF_RIGHT - */ - - script.flMaxVelocity = 0; - } - break; - /* - case NAV_FLY: - // FIXME: can there be a NAV_GROUND -> NAV_FLY transition? - script.flMaxVelocity = 0; - break; - */ - default: - break; - } - } - else - { - script.flMaxVelocity = GetNavigator()->GetArrivalSpeed(); - // Assert( script.flMaxVelocity == 0 ); - } - - m_scriptMove.AddToTail( script ); - pCurWaypoint = pNext; - } - - - //------------------------- - - // update distances - float flTotalDist = 0; - for (i = 0; i < m_scriptMove.Count() - 1; i++ ) - { - flTotalDist += m_scriptMove[i].flDist = (m_scriptMove[i+1].vecLocation - m_scriptMove[i].vecLocation).Length2D(); - } - - //------------------------- - - if ( !m_bDeceleratingToGoal && m_scriptMove.Count() && flTotalDist > 0 ) - { - float flNeededAccel = DeltaV( m_scriptMove[0].flMaxVelocity, m_scriptMove[m_scriptMove.Count() - 1].flMaxVelocity, flTotalDist ); - m_bDeceleratingToGoal = (flNeededAccel < -idealAccel); - //Assert( flNeededAccel != idealAccel); - } - - //------------------------- - - // insert slowdown points due to blocking - if (ai_path_insert_pause_at_obstruction.GetBool() && move.directTrace.pObstruction) - { - float distToObstruction = (move.directTrace.vEndPosition - m_scriptMove[0].vecLocation).Length2D(); - - // HACK move obstruction out "stepsize" to account for it being based on stand position and not a trace - distToObstruction = distToObstruction + 16; - - InsertSlowdown( distToObstruction, idealAccel, false ); - } - - if (ai_path_insert_pause_at_est_end.GetBool() && GetNavigator()->GetArrivalDistance() > 0.0) - { - InsertSlowdown( flTotalDist - GetNavigator()->GetArrivalDistance(), idealAccel, true ); - } - - // calc initial velocity based on immediate direction changes - if ( ai_path_adjust_speed_on_immediate_turns.GetBool() && m_scriptMove.Count() > 1) - { - /* - if ((GetOuter()->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT)) - { - Vector tmp = m_scriptMove[1].vecLocation - m_scriptMove[0].vecLocation; - VectorNormalize( tmp ); - NDebugOverlay::Line( m_scriptMove[0].vecLocation + Vector( 0, 0, 10 ), m_scriptMove[0].vecLocation + tmp * 32 + Vector( 0, 0, 10 ), 255,255,255, true, 0.1 ); - - NDebugOverlay::Line( m_scriptMove[0].vecLocation + Vector( 0, 0, 10 ), m_scriptMove[1].vecLocation + Vector( 0, 0, 10 ), 255,0,0, true, 0.1 ); - - tmp = GetCurVel(); - VectorNormalize( tmp ); - NDebugOverlay::Line( m_scriptMove[0].vecLocation + Vector( 0, 0, 10 ), m_scriptMove[0].vecLocation + tmp * 32 + Vector( 0, 0, 10 ), 0,0,255, true, 0.1 ); - } - */ - - Vector d1 = m_scriptMove[1].vecLocation - m_scriptMove[0].vecLocation; - d1.z = 0; - VectorNormalize( d1 ); - - Vector d2 = GetCurVel(); - d2.z = 0; - VectorNormalize( d2 ); - - float dot = (DotProduct( d1, d2 ) + MIN_STEER_DOT); - dot = clamp( dot, 0.0f, 1.0f ); - m_scriptMove[0].flMaxVelocity = m_scriptMove[0].flMaxVelocity * dot; - } - - // clamp forward velocities - for (i = 0; i < m_scriptMove.Count() - 1; i++ ) - { - // find needed acceleration - float dv = m_scriptMove[i+1].flMaxVelocity - m_scriptMove[i].flMaxVelocity; - - if (dv > 0.0) - { - // find time, distance to accel to next max vel - float t1 = dv / idealAccel; - float d1 = m_scriptMove[i].flMaxVelocity * t1 + 0.5 * (idealAccel) * t1 * t1; - - // is there enough distance - if (d1 > m_scriptMove[i].flDist) - { - float r1, r2; - - // clamp the next velocity to the possible accel in the given distance - if (SolveQuadratic( 0.5 * idealAccel, m_scriptMove[i].flMaxVelocity, -m_scriptMove[i].flDist, r1, r2 )) - { - m_scriptMove[i+1].flMaxVelocity = m_scriptMove[i].flMaxVelocity + idealAccel * r1; - } - } - } - } - - // clamp decel velocities - for (i = m_scriptMove.Count() - 1; i > 0; i-- ) - { - // find needed deceleration - float dv = m_scriptMove[i].flMaxVelocity - m_scriptMove[i-1].flMaxVelocity; - - if (dv < 0.0) - { - // find time, distance to decal to next max vel - float t1 = -dv / idealAccel; - float d1 = m_scriptMove[i].flMaxVelocity * t1 + 0.5 * (idealAccel) * t1 * t1; - - // is there enough distance - if (d1 > m_scriptMove[i-1].flDist) - { - float r1, r2; - - // clamp the next velocity to the possible decal in the given distance - if (SolveQuadratic( 0.5 * idealAccel, m_scriptMove[i].flMaxVelocity, -m_scriptMove[i-1].flDist, r1, r2 )) - { - m_scriptMove[i-1].flMaxVelocity = m_scriptMove[i].flMaxVelocity + idealAccel * r1; - } - } - } - } - - /* - for (i = 0; i < m_scriptMove.Count(); i++) - { - NDebugOverlay::Text( m_scriptMove[i].vecLocation, (const char *)CFmtStr( "%.2f ", m_scriptMove[i].flMaxVelocity ), false, 0.1 ); - // DevMsg("%.2f ", m_scriptMove[i].flMaxVelocity ); - } - // DevMsg("\n"); - */ - - // insert intermediate ideal velocities - for (i = 0; i < m_scriptMove.Count() - 1;) - { - // accel to ideal - float t1 = (idealVelocity - m_scriptMove[i].flMaxVelocity) / idealAccel; - float d1 = m_scriptMove[i].flMaxVelocity * t1 + 0.5 * (idealAccel) * t1 * t1; - - // decel from ideal - float t2 = (idealVelocity - m_scriptMove[i+1].flMaxVelocity) / idealAccel; - float d2 = m_scriptMove[i+1].flMaxVelocity * t2 + 0.5 * (idealAccel) * t2 * t2; - - m_scriptMove[i].flDist = (m_scriptMove[i+1].vecLocation - m_scriptMove[i].vecLocation).Length2D(); - - // is it possible to accel and decal to idealVelocity between next two nodes - if (d1 + d2 < m_scriptMove[i].flDist) - { - Vector start = m_scriptMove[i].vecLocation; - Vector end = m_scriptMove[i+1].vecLocation; - float dist = m_scriptMove[i].flDist; - - // insert the two points needed to end accel and start decel - if (d1 > 1.0 && t1 > 0.1) - { - a = d1 / dist; - - script.Init(); - script.vecLocation = end * a + start * (1 - a); - script.flMaxVelocity = idealVelocity; - m_scriptMove.InsertAfter( i, script ); - i++; - } - - if (dist - d2 > 1.0 && t2 > 0.1) - { - // DevMsg("%.2f : ", a ); - - a = (dist - d2) / dist; - - script.Init(); - script.vecLocation = end * a + start * (1 - a); - script.flMaxVelocity = idealVelocity; - m_scriptMove.InsertAfter( i, script ); - i++; - } - - i++; - } - else - { - // check to see if the amount of change needed to reach target is less than the ideal acceleration - float flNeededAccel = fabs( DeltaV( m_scriptMove[i].flMaxVelocity, m_scriptMove[i+1].flMaxVelocity, m_scriptMove[i].flDist ) ); - if (flNeededAccel < idealAccel) - { - // if so, they it's possible to get a bit towards the ideal velocity - float v1 = m_scriptMove[i].flMaxVelocity; - float v2 = m_scriptMove[i+1].flMaxVelocity; - float dist = m_scriptMove[i].flDist; - - // based on solving: - // v1+A*t1-v2-A*t2=0 - // v1*t1+0.5*A*t1*t1+v2*t2+0.5*A*t2*t2-D=0 - - float tmp = idealAccel*dist+0.5*v1*v1+0.5*v2*v2; - Assert( tmp >= 0 ); - t1 = (-v1+sqrt( tmp )) / idealAccel; - t2 = (v1+idealAccel*t1-v2)/idealAccel; - - // if this assert hits, write down the v1, v2, dist, and idealAccel numbers and send them to me (Ken). - // go ahead the comment it out, it's safe, but I'd like to know a test case where it's happening - //Assert( t1 > 0 && t2 > 0 ); - - // check to make sure it's really worth it - if (t1 > 0.0 && t2 > 0.0) - { - d1 = v1 * t1 + 0.5 * idealAccel * t1 * t1; - - /* - d2 = v2 * t2 + 0.5 * idealAccel * t2 * t2; - Assert( fabs( d1 + d2 - dist ) < 0.001 ); - */ - - float a = d1 / m_scriptMove[i].flDist; - script.Init(); - script.vecLocation = m_scriptMove[i+1].vecLocation * a + m_scriptMove[i].vecLocation * (1 - a); - script.flMaxVelocity = m_scriptMove[i].flMaxVelocity + idealAccel * t1; - - if (script.flMaxVelocity < idealVelocity) - { - // DevMsg("insert %.2f %.2f %.2f\n", m_scriptMove[i].flMaxVelocity, script.flMaxVelocity, m_scriptMove[i+1].flMaxVelocity ); - m_scriptMove.InsertAfter( i, script ); - i += 1; - } - } - } - i += 1; - } - } - - // clamp min velocities - for (i = 0; i < m_scriptMove.Count(); i++) - { - m_scriptMove[i].flMaxVelocity = MAX( m_scriptMove[i].flMaxVelocity, MIN_VELOCITY ); - } - - // rebuild fields - m_scriptMove[0].flElapsedTime = 0; - for (i = 0; i < m_scriptMove.Count() - 1; ) - { - m_scriptMove[i].flDist = (m_scriptMove[i+1].vecLocation - m_scriptMove[i].vecLocation).Length2D(); - - if (m_scriptMove[i].flMaxVelocity == 0 && m_scriptMove[i+1].flMaxVelocity == 0) - { - // force a minimum velocity - Assert( 0 ); - m_scriptMove[i+1].flMaxVelocity = 1.0; - } - - float t = m_scriptMove[i].flDist / (0.5 * (m_scriptMove[i].flMaxVelocity + m_scriptMove[i+1].flMaxVelocity)); - m_scriptMove[i].flTime = t; - - /* - if (m_scriptMove[i].flDist < 0.01) - { - // Assert( m_scriptMove[i+1].pWaypoint == NULL ); - - m_scriptMove.Remove( i + 1 ); - continue; - } - */ - - m_scriptMove[i+1].flElapsedTime = m_scriptMove[i].flElapsedTime + m_scriptMove[i].flTime; - - i++; - } - - /* - for (i = 0; i < m_scriptMove.Count(); i++) - { - DevMsg("(%.2f : %.2f : %.2f)", m_scriptMove[i].flMaxVelocity, m_scriptMove[i].flDist, m_scriptMove[i].flTime ); - // DevMsg("(%.2f:%.2f)", m_scriptMove[i].flTime, m_scriptMove[i].flElapsedTime ); - } - DevMsg("\n"); - */ -} - - - -void CAI_BlendedMotor::InsertSlowdown( float distToObstruction, float idealAccel, bool bAlwaysSlowdown ) -{ - int i; - AI_Movementscript_t script; - - if (distToObstruction <= 0.0) - return; - - for (i = 0; i < m_scriptMove.Count() - 1; i++) - { - if (m_scriptMove[i].flDist > 0 && distToObstruction - m_scriptMove[i].flDist < 0) - { - float a = distToObstruction / m_scriptMove[i].flDist; - Assert( a >= 0 && a <= 1); - script.vecLocation = (1 - a) * m_scriptMove[i].vecLocation + a * m_scriptMove[i+1].vecLocation; - - //NDebugOverlay::Line( m_scriptMove[i].vecLocation + Vector( 0, 0, 5 ), script.vecLocation + Vector( 0, 0, 5 ), 0,255,0, true, 0.1 ); - //NDebugOverlay::Line( script.vecLocation + Vector( 0, 0, 5 ), m_scriptMove[i+1].vecLocation + Vector( 0, 0, 5 ), 0,0,255, true, 0.1 ); - - float r1, r2; - - // clamp the next velocity to the possible accel in the given distance - if (!bAlwaysSlowdown && SolveQuadratic( -0.5 * idealAccel, m_scriptMove[0].flMaxVelocity, -distToObstruction, r1, r2 )) - { - script.flMaxVelocity = MAX( 10, m_scriptMove[0].flMaxVelocity - idealAccel * r1 ); - } - else - { - script.flMaxVelocity = 10.0; - } - - script.flMaxVelocity = 1.0; // as much as reasonable - script.pWaypoint = NULL; - script.flDist = m_scriptMove[i].flDist - distToObstruction; - m_scriptMove[i].flDist = distToObstruction; - m_scriptMove.InsertAfter( i, script ); - break; - } - else - { - distToObstruction -= m_scriptMove[i].flDist; - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: issues turn gestures when it detects that the body has turned but the feet haven't compensated -//----------------------------------------------------------------------------- - - -void CAI_BlendedMotor::MaintainTurnActivity( void ) -{ - AI_PROFILE_SCOPE(CAI_BlendedMotor_MaintainTurnActivity); - - if (m_flNextTurnGesture > gpGlobals->curtime || m_flNextTurnAct > gpGlobals->curtime || GetOuter()->IsMoving() ) - { - // clear out turn detection if currently turing or moving - m_doTurn = m_doRight = m_doLeft = 0; - if ( GetOuter()->IsMoving()) - { - m_flNextTurnAct = gpGlobals->curtime + 0.3; - } - } - else - { - // detect undirected turns - if (m_prevYaw != GetAbsAngles().y) - { - float diff = UTIL_AngleDiff( m_prevYaw, GetAbsAngles().y ); - if (diff < 0.0) - { - m_doLeft += -diff; - } - else - { - m_doRight += diff; - } - m_prevYaw = GetAbsAngles().y; - } - // accumulate turn angle, delay response for short turns - m_doTurn += m_doRight + m_doLeft; - // accumulate random foot stick clearing - m_doTurn += random->RandomFloat( 0.4, 0.6 ); - } - - if (m_doTurn > 15.0f) - { - // mostly a foot stick clear - int iSeq = ACT_INVALID; - if (m_doLeft > m_doRight) - { - iSeq = SelectWeightedSequence( ACT_GESTURE_TURN_LEFT ); - } - else - { - iSeq = SelectWeightedSequence( ACT_GESTURE_TURN_RIGHT ); - } - m_doLeft = 0; - m_doRight = 0; - - if (iSeq != ACT_INVALID) - { - int iLayer = GetOuter()->AddGestureSequence( iSeq ); - if (iLayer != -1) - { - GetOuter()->SetLayerPriority( iLayer, 100 ); - // increase speed if we're getting behind or they're turning quickly - float rate = random->RandomFloat( 0.8, 1.2 ); - if (m_doTurn > 90.0) - { - rate *= 1.5; - } - GetOuter()->SetLayerPlaybackRate( iLayer, rate ); - // disable turing for the duration of the gesture - m_flNextTurnAct = gpGlobals->curtime + GetOuter()->GetLayerDuration( iLayer ); - } - else - { - // too many active gestures, try again in half a second - m_flNextTurnAct = gpGlobals->curtime + 0.3; - } - } - m_doTurn = m_doRight = m_doLeft = 0; - } -} - -ConVar scene_flatturn( "scene_flatturn", "1" ); - -bool CAI_BlendedMotor::AddTurnGesture( float flYD ) -{ - - // some funky bug with human turn gestures, disable for now - return false; - - // try using a turn gesture - Activity activity = ACT_INVALID; - float weight = 1.0; - float turnCompletion = 1.0; - - if (m_flNextTurnGesture > gpGlobals->curtime) - { - /* - if ( GetOuter()->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT ) - { - Msg( "%.1f : [ %.2f ]\n", flYD, m_flNextTurnAct - gpGlobals->curtime ); - } - */ - return false; - } - - if ( GetOuter()->IsMoving() || GetOuter()->IsCrouching() ) - { - return false; - } - - if (fabs( flYD ) < 15) - { - return false; - } - else if (flYD < -45) - { - activity = ACT_GESTURE_TURN_RIGHT90; - weight = flYD / -90; - turnCompletion = 0.36; - } - else if (flYD < 0) - { - activity = ACT_GESTURE_TURN_RIGHT45; - weight = flYD / -45; - turnCompletion = 0.4; - } - else if (flYD <= 45) - { - activity = ACT_GESTURE_TURN_LEFT45; - weight = flYD / 45; - turnCompletion = 0.4; - } - else - { - activity = ACT_GESTURE_TURN_LEFT90; - weight = flYD / 90; - turnCompletion = 0.36; - } - - int seq = SelectWeightedSequence( activity ); - - if (scene_flatturn.GetBool() && GetOuter()->IsCurSchedule( SCHED_SCENE_GENERIC )) - { - Activity flatactivity = activity; - - if (activity == ACT_GESTURE_TURN_RIGHT90) - { - flatactivity = ACT_GESTURE_TURN_RIGHT90_FLAT; - } - else if (activity == ACT_GESTURE_TURN_RIGHT45) - { - flatactivity = ACT_GESTURE_TURN_RIGHT45_FLAT; - } - else if (activity == ACT_GESTURE_TURN_LEFT90) - { - flatactivity = ACT_GESTURE_TURN_LEFT90_FLAT; - } - else if (activity == ACT_GESTURE_TURN_LEFT45) - { - flatactivity = ACT_GESTURE_TURN_LEFT45_FLAT; - } - - if (flatactivity != activity) - { - int newseq = SelectWeightedSequence( flatactivity ); - if (newseq != ACTIVITY_NOT_AVAILABLE) - { - seq = newseq; - } - } - } - - if (seq != ACTIVITY_NOT_AVAILABLE) - { - int iLayer = GetOuter()->AddGestureSequence( seq ); - if (iLayer != -1) - { - GetOuter()->SetLayerPriority( iLayer, 100 ); - // vary the playback a bit - SetLayerPlaybackRate( iLayer, 1.0 ); - float actualDuration = GetOuter()->GetLayerDuration( iLayer ); - - float rate = random->RandomFloat( 0.5, 1.1 ); - float diff = fabs( flYD ); - float speed = (diff / (turnCompletion * actualDuration / rate)) * 0.1; - - speed = clamp( speed, 15, 35 ); - speed = MIN( speed, diff ); - - actualDuration = (diff / (turnCompletion * speed)) * 0.1 ; - - GetOuter()->SetLayerDuration( iLayer, actualDuration ); - - SetLayerWeight( iLayer, weight ); - - SetYawSpeed( speed ); - - Remember( bits_MEMORY_TURNING ); - - // don't overlap the turn portion of the gestures, and don't play them too often - m_flNextTurnGesture = gpGlobals->curtime + MAX( turnCompletion * actualDuration, 0.3 ); - - /* - if ( GetOuter()->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT ) - { - Msg( "%.1f : %.2f %.2f : %.2f (%.2f)\n", flYD, weight, speed, actualDuration, turnCompletion * actualDuration ); - } - */ - return true; - } - else - { - return false; - } - } - return false; -} - - -//------------------------------------- - - - -#if 0 -Activity CAI_BlendedMotor::GetTransitionActivity( ) -{ - AI_Waypoint_t *waypoint = GetNavigator()->GetPath()->GetTransitionWaypoint(); - - if ( waypoint->Flags() & bits_WP_TO_GOAL ) - { - if ( waypoint->activity != ACT_INVALID) - { - return waypoint->activity; - } - - return GetStoppedActivity( ); - } - - if (waypoint) - waypoint = waypoint->GetNext(); - - switch(waypoint->NavType() ) - { - case NAV_JUMP: - return ACT_JUMP; // are jumps going to get a movement track added to them? - - case NAV_GROUND: - return GetNavigator()->GetMovementActivity(); // yuck - - case NAV_CLIMB: - return ACT_CLIMB_UP; // depends on specifics of climb node - - default: - return ACT_IDLE; - } -} -#endif - -//------------------------------------- -// Purpose: return a velocity that should be hit at the end of the interval to match goal -// Input : flInterval - time interval to consider -// : flGoalDistance - distance to goal -// : flGoalVelocity - desired velocity at goal -// : flCurVelocity - current velocity -// : flIdealVelocity - velocity to go at if goal is too far away -// : flAccelRate - maximum acceleration/deceleration rate -// Output : target velocity at time t+flInterval -//------------------------------------- - -float ChangeDistance( float flInterval, float flGoalDistance, float flGoalVelocity, float flCurVelocity, float flIdealVelocity, float flAccelRate, float &flNewDistance, float &flNewVelocity ) -{ - float scale = 1.0; - if (flGoalDistance < 0) - { - flGoalDistance = - flGoalDistance; - flCurVelocity = -flCurVelocity; - scale = -1.0; - } - - flNewVelocity = flCurVelocity; - flNewDistance = 0.0; - - // if I'm too close, just go ahead and set the velocity - if (flGoalDistance < 0.01) - { - return flGoalVelocity * scale; - } - - float flGoalAccel = DeltaV( flCurVelocity, flGoalVelocity, flGoalDistance ); - - flNewVelocity = flCurVelocity; - - // -------------------------------------------- - // if goal is close enough try to match the goal velocity, else try to go ideal velocity - // -------------------------------------------- - if (flGoalAccel < 0 && flGoalAccel < -flAccelRate) - { - // I need to slow down; - flNewVelocity = flCurVelocity + flGoalAccel * flInterval; - if (flNewVelocity < 0) - flNewVelocity = 0; - } - else if (flGoalAccel > 0 && flGoalAccel >= flAccelRate) - { - // I need to speed up - flNewVelocity = flCurVelocity + flGoalAccel * flInterval; - if (flNewVelocity > flGoalVelocity) - flGoalVelocity = flGoalVelocity; - } - else if (flNewVelocity < flIdealVelocity) - { - // speed up to ideal velocity; - flNewVelocity = flCurVelocity + flAccelRate * flInterval; - if (flNewVelocity > flIdealVelocity) - flNewVelocity = flIdealVelocity; - // don't overshoot - if (0.5*(flNewVelocity + flCurVelocity) * flInterval > flGoalDistance) - { - flNewVelocity = 0.5 * (2 * flGoalDistance / flInterval - flCurVelocity); - } - } - else if (flNewVelocity > flIdealVelocity) - { - // slow down to ideal velocity; - flNewVelocity = flCurVelocity - flAccelRate * flInterval; - if (flNewVelocity < flIdealVelocity) - flNewVelocity = flIdealVelocity; - } - - float flDist = 0.5*(flNewVelocity + flCurVelocity) * flInterval; - - if (flDist > flGoalDistance) - { - flDist = flGoalDistance; - flNewVelocity = flGoalVelocity; - } - - flNewVelocity = flNewVelocity * scale; - - flNewDistance = (flGoalDistance - flDist) * scale; - - return 0.0; -} - -//----------------------------------------------------------------------------- diff --git a/game/server/ai_blended_movement.h b/game/server/ai_blended_movement.h deleted file mode 100644 index 4152b40ad..000000000 --- a/game/server/ai_blended_movement.h +++ /dev/null @@ -1,260 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_BLENDED_MOVEMENT_H -#define AI_BLENDED_MOVEMENT_H - -#include "ai_basenpc.h" -#include "ai_motor.h" -#include "ai_navigator.h" - -struct AI_Waypoint_t; - -//----------------------------------------------------------------------------- -// CLASS: CAI_BlendedMotor -// -// Purpose: Home of fancy human animation transition code -// -//----------------------------------------------------------------------------- - -class CAI_BlendedMotor : public CAI_Motor -{ - typedef CAI_Motor BaseClass; -public: - CAI_BlendedMotor( CAI_BaseNPC *pOuter ) - : BaseClass( pOuter ) - { - m_iPrimaryLayer = -1; - m_nPrimarySequence = ACT_INVALID; - - m_iSecondaryLayer = -1; - m_nSecondarySequence = ACT_INVALID; - m_flSecondaryWeight = 0.0f; - - m_nSavedGoalActivity = ACT_INVALID; - m_nSavedTranslatedGoalActivity = ACT_INVALID; - m_nGoalSequence = ACT_INVALID; - - m_nPrevMovementSequence = ACT_INVALID; - m_nInteriorSequence = ACT_INVALID; - - m_bDeceleratingToGoal = false; - - m_flStartCycle = 0.0f; - - m_flPredictiveSpeedAdjust = 1.0f; - m_flReactiveSpeedAdjust = 1.0f; - m_vecPrevOrigin1.Init(); - m_vecPrevOrigin2.Init(); - - m_prevYaw = 0.0f; - m_doTurn = 0.0f; - m_doLeft = 0.0f; - m_doRight = 0.0f; - m_flNextTurnAct = 0.0f; - } - - void MoveClimbStart( const Vector &climbDest, const Vector &climbDir, float climbDist, float yaw ); - void MoveJumpStart( const Vector &velocity ); - - void ResetMoveCalculations(); - void MoveStart(); - void ResetGoalSequence(); - void MoveStop(); - void MovePaused(); - void MoveContinue(); - - float OverrideMaxYawSpeed( Activity activity ); - void UpdateYaw( int speed ); - void RecalculateYawSpeed(); - - bool IsDeceleratingToGoal() const { return m_bDeceleratingToGoal; } - float GetMoveScriptTotalTime(); - - void MaintainTurnActivity( void ); - bool AddTurnGesture( float flYD ); - - -private: - AIMotorMoveResult_t MoveGroundExecute( const AILocalMoveGoal_t &move, AIMoveTrace_t *pTraceResult ); - AIMotorMoveResult_t MoveFlyExecute( const AILocalMoveGoal_t &move, AIMoveTrace_t *pTraceResult ); - - - // -------------------------------- - - void BuildMoveScript( const AILocalMoveGoal_t &move, AIMoveTrace_t *pTraceResult ); - - void BuildVelocityScript( const AILocalMoveGoal_t &move ); - void InsertSlowdown( float distToObstruction, float idealAccel, bool bAlwaysSlowdown ); - - int BuildTurnScript( int i, int j ); - void BuildTurnScript( const AILocalMoveGoal_t &move ); - int BuildInsertNode( int i, float flTime ); - - Activity GetTransitionActivity( void ); - - // -------------------------------- - - // helpers to simplify code - float GetCycle() { return GetOuter()->GetCycle(); } - int AddLayeredSequence( int sequence, int iPriority ) { return GetOuter()->AddLayeredSequence( sequence, iPriority ); } - void SetLayerWeight( int iLayer, float flWeight ) { GetOuter()->SetLayerWeight( iLayer, flWeight ); } - void SetLayerPlaybackRate( int iLayer, float flPlaybackRate ) { GetOuter()->SetLayerPlaybackRate( iLayer, flPlaybackRate ); } - void SetLayerNoRestore( int iLayer, bool bNoRestore ) { GetOuter()->SetLayerNoRestore( iLayer, bNoRestore ); } - void SetLayerCycle( int iLayer, float flCycle ) { GetOuter()->SetLayerCycle( iLayer, flCycle ); } - void SetLayerCycle( int iLayer, float flCycle, float flPrevCycle ) { GetOuter()->SetLayerCycle( iLayer, flCycle, flPrevCycle ); } - void RemoveLayer( int iLayer, float flKillRate, float flKillDelay ) { GetOuter()->RemoveLayer( iLayer, flKillRate, flKillDelay ); } - - // -------------------------------- - - struct AI_Movementscript_t - { - public: - AI_Movementscript_t( ) - { - Init( ); - }; - - void Init( void ) - { - memset( this, 0, sizeof(*this) ); - }; - - float flTime; // time till next entry - float flElapsedTime; // time since first entry - - float flDist; // distance to next entry - - float flMaxVelocity; - - // float flVelocity; - - float flYaw; - float flAngularVelocity; - - bool bLooping; - int nFlags; - - AI_Waypoint_t *pWaypoint; - - public: - AI_Movementscript_t *pNext; - AI_Movementscript_t *pPrev; - - Vector vecLocation; - - }; - - //--------------------------------- - - CUtlVector m_scriptMove; - CUtlVector m_scriptTurn; - - //--------------------------------- - - bool m_bDeceleratingToGoal; - - int m_iPrimaryLayer; - int m_iSecondaryLayer; - - int m_nPrimarySequence; - int m_nSecondarySequence; - float m_flSecondaryWeight; - - Activity m_nSavedGoalActivity; - Activity m_nSavedTranslatedGoalActivity; - int m_nGoalSequence; - - int m_nPrevMovementSequence; - int m_nInteriorSequence; - - float m_flStartCycle; - - float m_flCurrRate; - - float m_flPredictiveSpeedAdjust; // predictive speed adjust from probing slope - float m_flReactiveSpeedAdjust; // reactive speed adjust when slope movement detected - Vector m_vecPrevOrigin1; - Vector m_vecPrevOrigin2; - - //--------------------------------- - - float m_flNextTurnGesture; // next time for large turn gesture - - //--------------------------------- - float m_prevYaw; - float m_doTurn; - float m_doLeft; - float m_doRight; - float m_flNextTurnAct; // next time for small turn gesture - - - float GetMoveScriptDist( float &flNewSpeed ); - float GetMoveScriptYaw( void ); - void SetMoveScriptAnim( float flNewSpeed ); - - int GetInteriorSequence( int fromSequence ); - - DECLARE_SIMPLE_DATADESC(); -}; - -//----------------------------------------------------------------------------- -// CLASS: CAI_BlendingHost -// -// Purpose: Bridge to the home of fancy human animation transition code -// -//----------------------------------------------------------------------------- - -template -class CAI_BlendingHost : public BASE_NPC -{ - DECLARE_CLASS_NOFRIEND( CAI_BlendingHost, BASE_NPC ); -public: - const CAI_BlendedMotor *GetBlendedMotor() const { return assert_cast(this->GetMotor()); } - CAI_BlendedMotor * GetBlendedMotor() { return assert_cast(this->GetMotor()); } - - CAI_Motor *CreateMotor() - { - MEM_ALLOC_CREDIT(); - return new CAI_BlendedMotor( this ); - } - - CAI_Navigator *CreateNavigator() - { - CAI_Navigator *pNavigator = BaseClass::CreateNavigator(); - pNavigator->SetValidateActivitySpeed( false ); - return pNavigator; - } - - float MaxYawSpeed( void ) - { - float override = GetBlendedMotor()->OverrideMaxYawSpeed( this->GetActivity() ); - if ( override != -1 ) - return override; - return BaseClass::MaxYawSpeed(); - } - - float GetTimeToNavGoal() - { - float result = GetBlendedMotor()->GetMoveScriptTotalTime(); - if ( result != -1 ) - return result; - return BaseClass::GetTimeToNavGoal(); - } - -}; - -//------------------------------------- -// to simplify basic usage: -class CAI_BlendedNPC : public CAI_BlendingHost -{ - DECLARE_CLASS( CAI_BlendedNPC, CAI_BlendingHost ); -}; - -//----------------------------------------------------------------------------- - -#endif diff --git a/game/server/ai_component.h b/game/server/ai_component.h deleted file mode 100644 index f39a04b36..000000000 --- a/game/server/ai_component.h +++ /dev/null @@ -1,171 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_COMPONENT_H -#define AI_COMPONENT_H - -#if defined( _WIN32 ) -#pragma once -#endif - -class CAI_BaseNPC; -class CAI_Enemies; -typedef int AI_TaskFailureCode_t; -struct Task_t; - -//----------------------------------------------------------------------------- -// CAI_Component -// -// Purpose: Shared functionality of all classes that assume some of the -// responsibilities of an owner AI. -//----------------------------------------------------------------------------- - -class CAI_Component -{ - DECLARE_CLASS_NOBASE( CAI_Component ); -protected: - CAI_Component( CAI_BaseNPC *pOuter = NULL ) - : m_pOuter(pOuter) - { - } - - virtual ~CAI_Component() {} - -public: - virtual void SetOuter( CAI_BaseNPC *pOuter ) { m_pOuter = pOuter; } - - CAI_BaseNPC * GetOuter() { return m_pOuter; } - const CAI_BaseNPC * GetOuter() const { return m_pOuter; } - - Hull_t GetHullType() const; - float GetHullWidth() const; - float GetHullHeight() const; - const Vector & GetHullMins() const; - const Vector & GetHullMaxs() const; - -protected: - // - // Common services provided by CAI_BaseNPC, Convenience methods to simplify derived code - // - edict_t * GetEdict(); - - const Vector & GetLocalOrigin() const; - void SetLocalOrigin( const Vector &origin ); - - const Vector & GetAbsOrigin() const; - const QAngle& GetAbsAngles() const; - - void SetLocalAngles( const QAngle& angles ); - const QAngle & GetLocalAngles( void ) const; - - const Vector& WorldAlignMins() const; - const Vector& WorldAlignMaxs() const; - Vector WorldSpaceCenter() const; - - int GetCollisionGroup() const; - - void SetSolid( SolidType_t val ); - SolidType_t GetSolid() const; - - float GetGravity() const; - void SetGravity( float ); - - CBaseEntity* GetEnemy(); - const Vector & GetEnemyLKP() const; - void TranslateNavGoal( CBaseEntity *pEnemy, Vector &chasePosition); - - CBaseEntity* GetTarget(); - void SetTarget( CBaseEntity *pTarget ); - - const Task_t* GetCurTask( void ); - virtual void TaskFail( AI_TaskFailureCode_t ); - void TaskFail( const char *pszGeneralFailText ); - virtual void TaskComplete( bool fIgnoreSetFailedCondition = false ); - int TaskIsRunning(); - inline int TaskIsComplete(); - - Activity GetActivity(); - void SetActivity( Activity NewActivity ); - float GetIdealSpeed() const; - float GetIdealAccel() const; - int GetSequence(); - - int GetEntFlags() const; - void AddEntFlag( int flags ); - void RemoveEntFlag( int flagsToRemove ); - void ToggleEntFlag( int flagToToggle ); - - void SetGroundEntity( CBaseEntity *ground ); - - CBaseEntity* GetGoalEnt(); - void SetGoalEnt( CBaseEntity *pGoalEnt ); - - void Remember( int iMemory ); - void Forget( int iMemory ); - bool HasMemory( int iMemory ); - - CAI_Enemies * GetEnemies(); - - const char * GetEntClassname(); - - int CapabilitiesGet(); - - float GetLastThink( const char *szContext = NULL ); - -public: -#if defined(new) -#error -#endif - - void *operator new( size_t nBytes ) - { - MEM_ALLOC_CREDIT(); - void *pResult = g_pMemAlloc->Alloc( nBytes ); - memset( pResult, 0, nBytes ); - return pResult; - }; - - void *operator new( size_t nBytes, int nBlockUse, const char *pFileName, int nLine ) - { - MEM_ALLOC_CREDIT(); - void *pResult = g_pMemAlloc->Alloc( nBytes, pFileName, nLine ); - memset( pResult, 0, nBytes ); - return pResult; - } - -private: - CAI_BaseNPC *m_pOuter; -}; - -//----------------------------------------------------------------------------- - -template -class CAI_ComponentWithOuter : public BASE_COMPONENT -{ -protected: - CAI_ComponentWithOuter(NPC_CLASS *pOuter = NULL) - : BASE_COMPONENT(pOuter) - { - } - -public: - // Hides base version - void SetOuter( NPC_CLASS *pOuter ) { BASE_COMPONENT::SetOuter((CAI_BaseNPC *)pOuter); } - NPC_CLASS * GetOuter() { return (NPC_CLASS *)(BASE_COMPONENT::GetOuter()); } - const NPC_CLASS * GetOuter() const { return (NPC_CLASS *)(BASE_COMPONENT::GetOuter()); } -}; - -//----------------------------------------------------------------------------- - -#define DEFINE_AI_COMPONENT_OUTER( NPC_CLASS ) \ - void SetOuter( NPC_CLASS *pOuter ) { CAI_Component::SetOuter((CAI_BaseNPC *)pOuter); } \ - NPC_CLASS * GetOuter() { return (NPC_CLASS *)(CAI_Component::GetOuter()); } \ - const NPC_CLASS * GetOuter() const { return (NPC_CLASS *)(CAI_Component::GetOuter()); } - -//----------------------------------------------------------------------------- - -#endif // AI_COMPONENT_H diff --git a/game/server/ai_concommands.cpp b/game/server/ai_concommands.cpp deleted file mode 100644 index 0269712e7..000000000 --- a/game/server/ai_concommands.cpp +++ /dev/null @@ -1,875 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: Console commands for debugging and manipulating NPCs. -// -//===========================================================================// - -#include "cbase.h" -#include "ai_basenpc.h" -#include "player.h" -#include "entitylist.h" -#include "ai_network.h" -#include "ai_node.h" -#include "ai_link.h" -#include "ai_networkmanager.h" -#include "ndebugoverlay.h" -#include "datacache/imdlcache.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern CAI_Node* FindPickerAINode( CBasePlayer* pPlayer, NodeType_e nNodeType ); -extern void SetDebugBits( CBasePlayer* pPlayer, const char *name, int bit ); -extern CBaseEntity *FindPickerEntity( CBasePlayer *pPlayer ); - -extern bool g_bAIDisabledByUser; - - -//------------------------------------------------------------------------------ -// Purpose: Disables all NPCs -//------------------------------------------------------------------------------ -void CC_AI_Disable( void ) -{ - if (CAI_BaseNPC::m_nDebugBits & bits_debugDisableAI) - { - CAI_BaseNPC::m_nDebugBits &= ~bits_debugDisableAI; - DevMsg("AI Enabled.\n"); - } - else - { - CAI_BaseNPC::m_nDebugBits |= bits_debugDisableAI; - DevMsg("AI Disabled.\n"); - g_bAIDisabledByUser = true; - } - - CBaseEntity::m_nDebugPlayer = UTIL_GetCommandClientIndex(); -} -static ConCommand ai_disable("ai_disable", CC_AI_Disable, "Bi-passes all AI logic routines and puts all NPCs into their idle animations. Can be used to get NPCs out of your way and to test effect of AI logic routines on frame rate", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose: Show hint nodes -//------------------------------------------------------------------------------ -void CC_AI_ShowHints( void ) -{ - // Eventually this will be done by name when mulitple - // networks are used, but for now have one big AINet - //static char entName[256]; - //Q_strncpy( entName, args[1],sizeof(entName) ); - if ( !g_pAINetworkManager ) - return; - - g_pAINetworkManager->GetEditOps()->SetDebugBits("BigNet",bits_debugOverlayHints); - CBaseEntity::m_nDebugPlayer = UTIL_GetCommandClientIndex(); -} -static ConCommand ai_show_hints("ai_show_hints", CC_AI_ShowHints, "Displays all hints as small boxes\n\tBlue - hint is available for use\n\tRed - hint is currently being used by an NPC\n\tOrange - hint not being used by timed out\n\tGrey - hint has been disabled", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose: Show node connections with hulls -//------------------------------------------------------------------------------ -void CC_AI_ShowHull( const CCommand &args ) -{ - // Eventually this will be done by name when mulitple - // networks are used, but for now have one big AINet - //static char entName[256]; - //Q_strncpy( entName, args[1),sizeof(entName) ); - - g_pAINetworkManager->GetEditOps()->SetDebugBits("BigNet",bits_debugOverlayHulls); - CBaseEntity::m_nDebugPlayer = UTIL_GetCommandClientIndex(); -} -static ConCommand ai_show_hull("ai_show_hull", CC_AI_ShowHull, "Displays the allowed hulls between each node for the currently selected hull type. Hulls are color code as follows:\n\tGreen - ground movement \n\tBlue - jumping movement\n\tCyan - flying movement\n\tMagenta - climbing movement\n\tArguments: -none-", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose: Show node connections with lines -//------------------------------------------------------------------------------ -void CC_AI_ShowConnect( const CCommand &args ) -{ - // Eventually this will be done by name when mulitple - // networks are used, but for now have one big AINet - //static char entName[256]; - //Q_strncpy( entName, args[1],sizeof(entName) ); - if ( !g_pAINetworkManager ) - return; - - g_pAINetworkManager->GetEditOps()->SetDebugBits("BigNet",bits_debugOverlayConnections); - CBaseEntity::m_nDebugPlayer = UTIL_GetCommandClientIndex(); - -} -static ConCommand ai_show_connect("ai_show_connect", CC_AI_ShowConnect, "Displays the allowed connections between each node for the currently selected hull type. Hulls are color code as follows:\n\tGreen - ground movement \n\tBlue - jumping movement\n\tCyan - flying movement\n\tMagenta - climbing movement\n\tRed - connection disabled", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose: Show node connections with lines -//------------------------------------------------------------------------------ -void CC_AI_ShowJumpConnect( const CCommand &args ) -{ - // Eventually this will be done by name when mulitple - // networks are used, but for now have one big AINet - //static char entName[256]; - //Q_strncpy( entName, args[1],sizeof(entName) ); - if ( !g_pAINetworkManager ) - return; - - g_pAINetworkManager->GetEditOps()->SetDebugBits("BigNet",bits_debugOverlayConnections); - g_pAINetworkManager->GetEditOps()->SetDebugBits("BigNet",bits_debugOverlayJumpConnections); - CBaseEntity::m_nDebugPlayer = UTIL_GetCommandClientIndex(); - -} -static ConCommand ai_show_connect_jump("ai_show_connect_jump", CC_AI_ShowJumpConnect, "Displays the allowed connections between each node for the currently selected hull type. Hulls are color code as follows:\n\tGreen - ground movement \n\tBlue - jumping movement\n\tCyan - flying movement\n\tMagenta - climbing movement\n\tRed - connection disabled", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose: Show node connections with lines -//------------------------------------------------------------------------------ -void CC_AI_ShowFlyConnect( const CCommand &args ) -{ - // Eventually this will be done by name when mulitple - // networks are used, but for now have one big AINet - //static char entName[256]; - //Q_strncpy( entName, args[1],sizeof(entName) ); - if ( !g_pAINetworkManager ) - return; - - g_pAINetworkManager->GetEditOps()->SetDebugBits("BigNet",bits_debugOverlayConnections); - g_pAINetworkManager->GetEditOps()->SetDebugBits("BigNet",bits_debugOverlayFlyConnections); - CBaseEntity::m_nDebugPlayer = UTIL_GetCommandClientIndex(); - -} -static ConCommand ai_show_connect_fly("ai_show_connect_fly", CC_AI_ShowFlyConnect, "Displays the allowed connections between each node for the currently selected hull type. Hulls are color code as follows:\n\tGreen - ground movement \n\tBlue - jumping movement\n\tCyan - flying movement\n\tMagenta - climbing movement\n\tRed - connection disabled", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose: Draw a grid on the screen (good for laying down nodes) -//------------------------------------------------------------------------------ -void CC_AI_ShowGrid( const CCommand &args ) -{ - // Eventually this will be done by name when mulitple - // networks are used, but for now have one big AINet - //static char entName[256]; - //Q_strncpy( entName, args[1],sizeof(entName) ); - if ( !g_pAINetworkManager ) - return; - - g_pAINetworkManager->GetEditOps()->SetDebugBits("BigNet",bits_debugOverlayGrid); - CBaseEntity::m_nDebugPlayer = UTIL_GetCommandClientIndex(); -} -static ConCommand ai_show_grid("ai_show_grid", CC_AI_ShowGrid, "Draw a grid on the floor where looking.", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose: NPC step trough AI -//------------------------------------------------------------------------------ -void CC_AI_Step( void ) -{ - DevMsg("AI Stepping...\n"); - - // Start NPC's stepping through tasks - CAI_BaseNPC::m_nDebugBits |= bits_debugStepAI; - CAI_BaseNPC::m_nDebugPauseIndex++; -} -static ConCommand ai_step("ai_step", CC_AI_Step, "NPCs will freeze after completing their current task. To complete the next task, use 'ai_step' again. To resume processing normally use 'ai_resume'", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose: Resume normal AI processing after stepping -//------------------------------------------------------------------------------ -void CC_AI_Resume( void ) -{ - DevMsg("AI Resume...\n"); - - // End NPC's stepping through tasks - CAI_BaseNPC::m_nDebugBits &= ~bits_debugStepAI; -} -static ConCommand ai_resume("ai_resume", CC_AI_Resume, "If NPC is stepping through tasks (see ai_step ) will resume normal processing.", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose: Switch to display of next hull type -//------------------------------------------------------------------------------ -void CC_AI_NextHull( const CCommand &args ) -{ - // Eventually this will be done by name when mulitple - // networks are used, but for now have one big AINet - //static char entName[256]; - //Q_strncpy( entName, args[1],sizeof(entName) ); - if ( !g_pAINetworkManager ) - return; - - g_pAINetworkManager->GetEditOps()->DrawNextHull("BigNet"); - CBaseEntity::m_nDebugPlayer = UTIL_GetCommandClientIndex(); -} -static ConCommand ai_next_hull("ai_next_hull", CC_AI_NextHull, "Cycles through the various hull sizes. Currently selected hull size is written to the screen. Controls which connections are shown when ai_show_hull or ai_show_connect commands are used\n\tArguments: -none-", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Display the hull type of the specified NPC. -//------------------------------------------------------------------------------ -void CC_AI_Hull( const CCommand &args ) -{ - if ( !g_pAINetworkManager ) - return; - - bool bSpawned = false; - CBaseEntity *pEnt = NULL; - - if ( !args[1] || !args[1][0] ) - { - // No arg means the entity under the crosshair. - pEnt = FindPickerEntity( UTIL_GetCommandClient() ); - if ( !pEnt ) - { - DevMsg( "No entity under the crosshair.\n" ); - return; - } - } - else - { - // Find the entity specified on the command line. - pEnt = gEntList.FindEntityGeneric( NULL, args[1] ); - - if ( !pEnt ) - { - // Not found, try to create one. - pEnt = (CAI_BaseNPC *)CreateEntityByName( args[1] ); - if ( !pEnt ) - { - DevMsg( "Entity %s not found, and couldn't create!\n", args[1] ); - return; - } - - bSpawned = true; - DispatchSpawn( pEnt ); - } - } - - CAI_BaseNPC *pNPC = dynamic_cast( pEnt ); - if ( !pNPC ) - { - DevMsg( "Entity %s is not an NPC.\n", pEnt->GetDebugName() ); - return; - } - - Hull_t eHull = pNPC->GetHullType(); - - if ( bSpawned ) - { - UTIL_Remove( pEnt ); - } - - g_pAINetworkManager->GetEditOps()->DrawHull( eHull ); - - CBaseEntity::m_nDebugPlayer = UTIL_GetCommandClientIndex(); -} -static ConCommand ai_hull("ai_hull", CC_AI_Hull, "Controls which connections are shown when ai_show_hull or ai_show_connect commands are used\n\tArguments: NPC name or classname, =NPC under crosshair", FCVAR_CHEAT); - - -//------------------------------------------------------------------------------ -// Purpose: Show AI nodes -//------------------------------------------------------------------------------ -void CC_AI_Nodes( const CCommand &args ) -{ - // Eventually this will be done by name when mulitple - // networks are used, but for now have one big AINet - // static char entName[256]; - //Q_strncpy( entName, args[1],sizeof(entName) ); - if ( !g_pAINetworkManager ) - return; - - g_pAINetworkManager->GetEditOps()->SetDebugBits("BigNet",bits_debugOverlayNodes); - CBaseEntity::m_nDebugPlayer = UTIL_GetCommandClientIndex(); -} -static ConCommand ai_nodes("ai_nodes", CC_AI_Nodes, "Toggles node display. First call displays the nodes for the given network as green objects. Second call displays the nodes and their IDs. Nodes are color coded as follows:\n\tGreen - ground node\n\tCyan - air node\n\tMagenta - climb node\n\tGrey - node not available for selected hull size\n\tOrange - node currently locked", FCVAR_CHEAT); - - -CON_COMMAND(ai_show_node, "Highlight the specified node") -{ - if ( args.ArgC() > 1 ) - { - int node = atoi(args[1]); - CAI_Node* pAINode = g_pBigAINet->GetNode( node, false ); - if ( pAINode ) - { - NDebugOverlay::Cross3D(pAINode->GetOrigin(), 1024, 255, 255, 255, true, 5.0 ); - } - } -} - -//------------------------------------------------------------------------------ -// Purpose: Show visibility from selected node to all other nodes -//------------------------------------------------------------------------------ -void CC_AI_ShowVisibility( const CCommand &args ) -{ - // Eventually this will be done by name when mulitple - // networks are used, but for now have one big AINet - // static char entName[256]; - //Q_strncpy( entName, args[1],sizeof(entName) ); - if ( !g_pAINetworkManager ) - return; - - g_pAINetworkManager->GetEditOps()->SetDebugBits("BigNet",bits_debugOverlayVisibility); - - CAI_Node* pAINode = FindPickerAINode(UTIL_GetCommandClient(), NODE_ANY); - if (pAINode != NULL) - { - g_pAINetworkManager->GetEditOps()->m_iVisibilityNode = pAINode->GetId(); - } - else - { - g_pAINetworkManager->GetEditOps()->m_iVisibilityNode = NO_NODE; - } - - CBaseEntity::m_nDebugPlayer = UTIL_GetCommandClientIndex(); -} -static ConCommand ai_show_visibility("ai_show_visibility", CC_AI_ShowVisibility, "Toggles visibility display for the node that the player is looking at. Nodes that are visible from the selected node will be drawn in red with yellow lines connecting to the selected node. Nodes that are not visible from the selected node will be drawn in blue.", FCVAR_CHEAT); - - -//------------------------------------------------------------------------------ -// Purpose: Show what nodes the selected node is connected to using the -// netowrk graph -//------------------------------------------------------------------------------ -void CC_AI_GraphConnect( const CCommand &args ) -{ - if ( !g_pAINetworkManager ) - return; - - // Eventually this will be done by name when mulitple - // networks are used, but for now have one big AINet - //static char entName[256]; - //Q_strncpy( entName, args[1],sizeof(entName) ); - g_pAINetworkManager->GetEditOps()->SetDebugBits("BigNet",bits_debugOverlayGraphConnect); - CAI_Node* pAINode = FindPickerAINode(UTIL_GetCommandClient(), NODE_ANY); - if (pAINode != NULL) - { - g_pAINetworkManager->GetEditOps()->m_iGConnectivityNode = pAINode->GetId(); - } - else - { - g_pAINetworkManager->GetEditOps()->m_iGConnectivityNode = NO_NODE; - } - - CBaseEntity::m_nDebugPlayer = UTIL_GetCommandClientIndex(); -} -static ConCommand ai_show_graph_connect("ai_show_graph_connect", CC_AI_GraphConnect, "Toggles graph connection display for the node that the player is looking at. Nodes that are connected to the selected node by the net graph will be drawn in red with magenta lines connecting to the selected node. Nodes that are not connected via the net graph from the selected node will be drawn in blue.", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose: Show route triangulation attempts -//------------------------------------------------------------------------------ -void CC_NPC_Bipass( const CCommand &args ) -{ - SetDebugBits( UTIL_GetCommandClient(),args[1],OVERLAY_NPC_TRIANGULATE_BIT); -} -static ConCommand npc_bipass("npc_bipass", CC_NPC_Bipass, "Displays the local movement attempts by the given NPC(s) (triangulation detours). Failed bypass routes are displayed in red, successful bypasses are shown in green.\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at.", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose: Destroy selected NPC -//------------------------------------------------------------------------------ -void CC_NPC_Destroy( const CCommand &args ) -{ - SetDebugBits( UTIL_GetCommandClient(),args[1],OVERLAY_NPC_ZAP_BIT); -} -static ConCommand npc_destroy("npc_destroy", CC_NPC_Destroy, "Removes the given NPC(s) from the universe\nArguments: {npc_name} / {npc_class_name} / no argument picks what player is looking at", FCVAR_CHEAT); - - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CC_NPC_Kill( const CCommand &args ) -{ - SetDebugBits( UTIL_GetCommandClient(),args[1],OVERLAY_NPC_KILL_BIT); -} -static ConCommand npc_kill("npc_kill", CC_NPC_Kill, "Kills the given NPC(s)\nArguments: {npc_name} / {npc_class_name} / no argument picks what player is looking at", FCVAR_CHEAT); - - -//------------------------------------------------------------------------------ -// Purpose: Show selected NPC's enemies -//------------------------------------------------------------------------------ -void CC_NPC_Enemies( const CCommand &args ) -{ - SetDebugBits( UTIL_GetCommandClient(),args[1],OVERLAY_NPC_ENEMIES_BIT); -} -static ConCommand npc_enemies("npc_enemies", CC_NPC_Enemies, "Shows memory of NPC. Draws an X on top of each memory.\n\tEluded entities drawn in blue (don't know where it went)\n\tUnreachable entities drawn in green (can't get to it)\n\tCurrent enemy drawn in red\n\tCurrent target entity drawn in magenta\n\tAll other entities drawn in pink\n\tArguments: {npc_name} / {npc class_name} / no argument picks what player is looking at", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose: Show seletected NPC's current enemy and target entity -//------------------------------------------------------------------------------ -void CC_NPC_Focus( const CCommand &args ) -{ - SetDebugBits( UTIL_GetCommandClient(),args[1],OVERLAY_NPC_FOCUS_BIT); -} -static ConCommand npc_focus("npc_focus", CC_NPC_Focus, "Displays red line to NPC's enemy (if has one) and blue line to NPC's target entity (if has one)\n\tArguments: {npc_name} / {npc class_name} / no argument picks what player is looking at", FCVAR_CHEAT); - -ConVar npc_create_equipment("npc_create_equipment", ""); -//------------------------------------------------------------------------------ -// Purpose: Create an NPC of the given type -//------------------------------------------------------------------------------ -void CC_NPC_Create( const CCommand &args ) -{ - MDLCACHE_CRITICAL_SECTION(); - - bool allowPrecache = CBaseEntity::IsPrecacheAllowed(); - CBaseEntity::SetAllowPrecache( true ); - - // Try to create entity - CAI_BaseNPC *baseNPC = dynamic_cast< CAI_BaseNPC * >( CreateEntityByName(args[1]) ); - if (baseNPC) - { - baseNPC->KeyValue( "additionalequipment", npc_create_equipment.GetString() ); - baseNPC->Precache(); - - if ( args.ArgC() == 3 ) - { - baseNPC->SetName( AllocPooledString( args[2] ) ); - } - - DispatchSpawn(baseNPC); - // Now attempt to drop into the world - CBasePlayer* pPlayer = UTIL_GetCommandClient(); - trace_t tr; - Vector forward; - pPlayer->EyeVectors( &forward ); - AI_TraceLine(pPlayer->EyePosition(), - pPlayer->EyePosition() + forward * MAX_TRACE_LENGTH,MASK_NPCSOLID, - pPlayer, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction != 1.0) - { - if (baseNPC->CapabilitiesGet() & bits_CAP_MOVE_FLY) - { - Vector pos = tr.endpos - forward * 36; - baseNPC->Teleport( &pos, NULL, NULL ); - } - else - { - // Raise the end position a little up off the floor, place the npc and drop him down - tr.endpos.z += 12; - baseNPC->Teleport( &tr.endpos, NULL, NULL ); - UTIL_DropToFloor( baseNPC, MASK_NPCSOLID ); - } - - // Now check that this is a valid location for the new npc to be - Vector vUpBit = baseNPC->GetAbsOrigin(); - vUpBit.z += 1; - - AI_TraceHull( baseNPC->GetAbsOrigin(), vUpBit, baseNPC->GetHullMins(), baseNPC->GetHullMaxs(), - MASK_NPCSOLID, baseNPC, COLLISION_GROUP_NONE, &tr ); - if ( tr.startsolid || (tr.fraction < 1.0) ) - { - baseNPC->SUB_Remove(); - DevMsg("Can't create %s. Bad Position!\n",args[1]); - NDebugOverlay::Box(baseNPC->GetAbsOrigin(), baseNPC->GetHullMins(), baseNPC->GetHullMaxs(), 255, 0, 0, 0, 0); - } - } - - baseNPC->Activate(); - } - CBaseEntity::SetAllowPrecache( allowPrecache ); -} -static ConCommand npc_create("npc_create", CC_NPC_Create, "Creates an NPC of the given type where the player is looking (if the given NPC can actually stand at that location). Note that this only works for npc classes that are already in the world. You can not create an entity that doesn't have an instance in the level.\n\tArguments: {npc_class_name}", FCVAR_CHEAT); - - -//------------------------------------------------------------------------------ -// Purpose: Create an NPC of the given type -//------------------------------------------------------------------------------ -void CC_NPC_Create_Aimed( const CCommand &args ) -{ - MDLCACHE_CRITICAL_SECTION(); - - bool allowPrecache = CBaseEntity::IsPrecacheAllowed(); - CBaseEntity::SetAllowPrecache( true ); - - // Try to create entity - CAI_BaseNPC *baseNPC = dynamic_cast< CAI_BaseNPC * >( CreateEntityByName(args[1]) ); - if (baseNPC) - { - baseNPC->KeyValue( "additionalequipment", npc_create_equipment.GetString() ); - baseNPC->Precache(); - DispatchSpawn( baseNPC ); - - // Now attempt to drop into the world - QAngle angles; - CBasePlayer* pPlayer = UTIL_GetCommandClient(); - trace_t tr; - Vector forward; - pPlayer->EyeVectors( &forward ); - VectorAngles( forward, angles ); - angles.x = 0; - angles.z = 0; - AI_TraceLine( pPlayer->EyePosition(), - pPlayer->EyePosition() + forward * MAX_TRACE_LENGTH,MASK_NPCSOLID, - pPlayer, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction != 1.0) - { - if (baseNPC->CapabilitiesGet() & bits_CAP_MOVE_FLY) - { - Vector pos = tr.endpos - forward * 36; - baseNPC->Teleport( &pos, &angles, NULL ); - } - else - { - // Raise the end position a little up off the floor, place the npc and drop him down - tr.endpos.z += 12; - baseNPC->Teleport( &tr.endpos, &angles, NULL ); - UTIL_DropToFloor( baseNPC, MASK_NPCSOLID ); - } - - // Now check that this is a valid location for the new npc to be - Vector vUpBit = baseNPC->GetAbsOrigin(); - vUpBit.z += 1; - - AI_TraceHull( baseNPC->GetAbsOrigin(), vUpBit, baseNPC->GetHullMins(), baseNPC->GetHullMaxs(), - MASK_NPCSOLID, baseNPC, COLLISION_GROUP_NONE, &tr ); - if ( tr.startsolid || (tr.fraction < 1.0) ) - { - baseNPC->SUB_Remove(); - DevMsg("Can't create %s. Bad Position!\n",args[1]); - NDebugOverlay::Box(baseNPC->GetAbsOrigin(), baseNPC->GetHullMins(), baseNPC->GetHullMaxs(), 255, 0, 0, 0, 0); - } - } - else - { - baseNPC->Teleport( NULL, &angles, NULL ); - } - - baseNPC->Activate(); - } - CBaseEntity::SetAllowPrecache( allowPrecache ); -} -static ConCommand npc_create_aimed("npc_create_aimed", CC_NPC_Create_Aimed, "Creates an NPC aimed away from the player of the given type where the player is looking (if the given NPC can actually stand at that location). Note that this only works for npc classes that are already in the world. You can not create an entity that doesn't have an instance in the level.\n\tArguments: {npc_class_name}", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose: Destroy unselected NPCs -//------------------------------------------------------------------------------ -void CC_NPC_DestroyUnselected( void ) -{ - CAI_BaseNPC *pNPC = gEntList.NextEntByClass( (CAI_BaseNPC *)NULL ); - - while (pNPC) - { - if (!(pNPC->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) && !pNPC->ClassMatches("npc_bullseye")) - { - pNPC->m_debugOverlays |= OVERLAY_NPC_ZAP_BIT; - } - pNPC = gEntList.NextEntByClass(pNPC); - } -} -static ConCommand npc_destroy_unselected("npc_destroy_unselected", CC_NPC_DestroyUnselected, "Removes all NPCs from the universe that aren't currently selected", FCVAR_CHEAT); - - -//------------------------------------------------------------------------------ -// Purpose: Freeze or unfreeze the selected NPCs. If no NPCs are selected, the -// NPC under the crosshair is frozen/unfrozen. -//------------------------------------------------------------------------------ -void CC_NPC_Freeze( const CCommand &args ) -{ - if (FStrEq(args[1], "")) - { - // - // No NPC was specified, try to freeze selected NPCs. - // - bool bFound = false; - CAI_BaseNPC *npc = gEntList.NextEntByClass( (CAI_BaseNPC *)NULL ); - while (npc) - { - if (npc->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) - { - bFound = true; - npc->ToggleFreeze(); - } - npc = gEntList.NextEntByClass(npc); - } - - if (!bFound) - { - // - // No selected NPCs, look for the NPC under the crosshair. - // - CBaseEntity *pEntity = FindPickerEntity( UTIL_GetCommandClient() ); - if ( pEntity ) - { - CAI_BaseNPC *pNPC = pEntity->MyNPCPointer(); - if (pNPC) - { - pNPC->ToggleFreeze(); - } - } - } - } - else - { - // TODO: look for NPCs by name, classname. - } -} -static ConCommand npc_freeze("npc_freeze", CC_NPC_Freeze, "Selected NPC(s) will freeze in place (or unfreeze). If there are no selected NPCs, uses the NPC under the crosshair.\n\tArguments: -none-", FCVAR_CHEAT); - - -CON_COMMAND( npc_freeze_unselected, "Freeze all NPCs not selected" ) -{ - CAI_BaseNPC *pNPC = gEntList.NextEntByClass( (CAI_BaseNPC *)NULL ); - - while (pNPC) - { - if (!(pNPC->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT)) - { - pNPC->ToggleFreeze(); - } - pNPC = gEntList.NextEntByClass(pNPC); - } -} - -//------------------------------------------------------------------------------ -CON_COMMAND(npc_thinknow, "Trigger NPC to think") -{ - CBaseEntity *pEntity = FindPickerEntity( UTIL_GetCommandClient() ); - if ( pEntity ) - { - CAI_BaseNPC *pNPC = pEntity->MyNPCPointer(); - if (pNPC) - { - pNPC->SetThink( &CAI_BaseNPC::CallNPCThink ); - pNPC->SetNextThink( gpGlobals->curtime ); - } - } -} - -//------------------------------------------------------------------------------ -// Purpose: Tell selected NPC to go to a where player is looking -//------------------------------------------------------------------------------ - -void CC_NPC_Teleport( void ) -{ - CBasePlayer* pPlayer = UTIL_GetCommandClient(); - trace_t tr; - Vector forward; - pPlayer->EyeVectors( &forward ); - AI_TraceLine(pPlayer->EyePosition(), - pPlayer->EyePosition() + forward * MAX_TRACE_LENGTH,MASK_NPCSOLID, - pPlayer, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction != 1.0) - { - CAI_BaseNPC *npc = gEntList.NextEntByClass( (CAI_BaseNPC *)NULL ); - - while (npc) - { - //Only Teleport one NPC if more than one is selected. - if (npc->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) - { - npc->Teleport( &tr.endpos, NULL, NULL ); - break; - } - - npc = gEntList.NextEntByClass(npc); - } - } -} - -static ConCommand npc_teleport("npc_teleport", CC_NPC_Teleport, "Selected NPC will teleport to the location that the player is looking (shown with a purple box)\n\tArguments: -none-", FCVAR_CHEAT); - -static ConVar npc_go_do_run( "npc_go_do_run", "1", 0, "Set whether should run on NPC go" ); - -void CC_NPC_Go( void ) -{ - CBasePlayer* pPlayer = UTIL_GetCommandClient(); - trace_t tr; - Vector forward; - pPlayer->EyeVectors( &forward ); - AI_TraceLine(pPlayer->EyePosition(), - pPlayer->EyePosition() + forward * MAX_TRACE_LENGTH,MASK_NPCSOLID, - pPlayer, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction != 1.0) - { - CAI_BaseNPC::ForceSelectedGo(pPlayer, tr.endpos, forward, npc_go_do_run.GetBool()); - } -} -static ConCommand npc_go("npc_go", CC_NPC_Go, "Selected NPC(s) will go to the location that the player is looking (shown with a purple box)\n\tArguments: -none-", FCVAR_CHEAT); - - -//------------------------------------------------------------------------------ -// Purpose: Tell seclected NPC to go to a random node location -//------------------------------------------------------------------------------ -void CC_NPC_GoRandom( void ) -{ - CAI_BaseNPC::ForceSelectedGoRandom(); -} -static ConCommand npc_go_random("npc_go_random", CC_NPC_GoRandom, "Sends all selected NPC(s) to a random node.\n\tArguments: -none-", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose: ?Does this work? -//------------------------------------------------------------------------------ -void CC_NPC_Reset( void ) -{ - CAI_BaseNPC::ClearAllSchedules(); - g_AI_SchedulesManager.LoadAllSchedules(); -} -static ConCommand npc_reset("npc_reset", CC_NPC_Reset, "Reloads schedules for all NPC's from their script files\n\tArguments: -none-", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose: Show the selected NPC's nearest node -//------------------------------------------------------------------------------ -void CC_NPC_Nearest( const CCommand &args ) -{ - SetDebugBits( UTIL_GetCommandClient(),args[1],OVERLAY_NPC_NEAREST_BIT); -} -static ConCommand npc_nearest("npc_nearest", CC_NPC_Nearest, "Draw's a while box around the NPC(s) nearest node\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at ", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose: Show the selected NPC's route -//------------------------------------------------------------------------------ -void CC_NPC_Route( const CCommand &args ) -{ - SetDebugBits( UTIL_GetCommandClient(),args[1],OVERLAY_NPC_ROUTE_BIT); -} -static ConCommand npc_route("npc_route", CC_NPC_Route, "Displays the current route of the given NPC as a line on the screen. Waypoints along the route are drawn as small cyan rectangles. Line is color coded in the following manner:\n\tBlue - path to a node\n\tCyan - detour around an object (triangulation)\n\tRed - jump\n\tMaroon - path to final target position\n\tArguments: {npc_name} / {npc_class_name} / no argument picks what player is looking at ", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose: Select an NPC -//------------------------------------------------------------------------------ -void CC_NPC_Select( const CCommand &args ) -{ - SetDebugBits( UTIL_GetCommandClient(),args[1],OVERLAY_NPC_SELECTED_BIT); -} -static ConCommand npc_select("npc_select", CC_NPC_Select, "Select or deselects the given NPC(s) for later manipulation. Selected NPC's are shown surrounded by a red translucent box\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at ", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose: Show combat related data for an NPC -//------------------------------------------------------------------------------ -void CC_NPC_Combat( const CCommand &args ) -{ - SetDebugBits( UTIL_GetCommandClient(),args[1],OVERLAY_NPC_SQUAD_BIT); -} -static ConCommand npc_combat("npc_combat", CC_NPC_Combat, "Displays text debugging information about the squad and enemy of the selected NPC (See Overlay Text)\n\tArguments: {npc_name} / {npc class_name} / no argument picks what player is looking at", FCVAR_CHEAT); -// For backwards compatibility -static ConCommand npc_squads("npc_squads", CC_NPC_Combat, "Obsolete. Replaced by npc_combat", FCVAR_CHEAT); - - -//------------------------------------------------------------------------------ -// Purpose: Show tasks for an NPC -//------------------------------------------------------------------------------ -void CC_NPC_Tasks( const CCommand &args ) -{ - SetDebugBits( UTIL_GetCommandClient(),args[1],OVERLAY_NPC_TASK_BIT); -} -static ConCommand npc_tasks("npc_tasks", CC_NPC_Tasks, "Displays detailed text debugging information about the all the tasks of the selected NPC current schedule (See Overlay Text)\n\tArguments: {npc_name} / {npc class_name} / no argument picks what player is looking at ", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose: Show tasks (on the console) for an NPC -//------------------------------------------------------------------------------ -void CC_NPC_Task_Text( const CCommand &args ) -{ - SetDebugBits( UTIL_GetCommandClient(), args[1], OVERLAY_TASK_TEXT_BIT); -} -static ConCommand npc_task_text("npc_task_text", CC_NPC_Task_Text, "Outputs text debugging information to the console about the all the tasks + break conditions of the selected NPC current schedule\n\tArguments: {npc_name} / {npc class_name} / no argument picks what player is looking at ", FCVAR_CHEAT); - - -//------------------------------------------------------------------------------ -// Purpose: Shows all current conditions for an NPC. -//------------------------------------------------------------------------------ -void CC_NPC_Conditions( const CCommand &args ) -{ - SetDebugBits( UTIL_GetCommandClient(), args[1], OVERLAY_NPC_CONDITIONS_BIT); -} -static ConCommand npc_conditions("npc_conditions", CC_NPC_Conditions, "Displays all the current AI conditions that an NPC has in the overlay text.\n\tArguments: {npc_name} / {npc class_name} / no argument picks what player is looking at", FCVAR_CHEAT); - - -//------------------------------------------------------------------------------ -// Purpose: Show an NPC's viewcone -//------------------------------------------------------------------------------ -void CC_NPC_Viewcone( const CCommand &args ) -{ - SetDebugBits( UTIL_GetCommandClient(),args[1],OVERLAY_NPC_VIEWCONE_BIT); -} -static ConCommand npc_viewcone("npc_viewcone", CC_NPC_Viewcone, "Displays the viewcone of the NPC (where they are currently looking and what the extents of there vision is)\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose: Show an NPC's relationships to other NPCs -//------------------------------------------------------------------------------ -void CC_NPC_Relationships( const CCommand &args ) -{ - SetDebugBits( UTIL_GetCommandClient(),args[1], OVERLAY_NPC_RELATION_BIT ); -} -static ConCommand npc_relationships("npc_relationships", CC_NPC_Relationships, "Displays the relationships between this NPC and all others.\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at", FCVAR_CHEAT ); - -//------------------------------------------------------------------------------ -// Purpose: Show an NPC's steering regulations -//------------------------------------------------------------------------------ -void CC_NPC_ViewSteeringRegulations( const CCommand &args ) -{ - SetDebugBits( UTIL_GetCommandClient(), args[1], OVERLAY_NPC_STEERING_REGULATIONS); -} -static ConCommand npc_steering("npc_steering", CC_NPC_ViewSteeringRegulations, "Displays the steering obstructions of the NPC (used to perform local avoidance)\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at", FCVAR_CHEAT); - -void CC_NPC_ViewSteeringRegulationsAll( void ) -{ - CAI_BaseNPC *pNPC = gEntList.NextEntByClass( (CAI_BaseNPC *)NULL ); - - while (pNPC) - { - if (!(pNPC->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT)) - { - pNPC->m_debugOverlays |= OVERLAY_NPC_STEERING_REGULATIONS; - } - else - { - pNPC->m_debugOverlays &= ~OVERLAY_NPC_STEERING_REGULATIONS; - } - pNPC = gEntList.NextEntByClass(pNPC); - } -} -static ConCommand npc_steering_all("npc_steering_all", CC_NPC_ViewSteeringRegulationsAll, "Displays the steering obstructions of all NPCs (used to perform local avoidance)\n", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ - -CON_COMMAND( npc_heal, "Heals the target back to full health" ) -{ - CBaseEntity *pEntity = FindPickerEntity( UTIL_GetCommandClient() ); - if ( pEntity ) - { - CAI_BaseNPC *pNPC = pEntity->MyNPCPointer(); - if (pNPC) - { - pNPC->SetHealth( pNPC->GetMaxHealth() ); - } - } -} - -CON_COMMAND( npc_ammo_deplete, "Subtracts half of the target's ammo" ) -{ - CBaseEntity *pEntity = FindPickerEntity( UTIL_GetCommandClient() ); - if ( pEntity ) - { - CAI_BaseNPC *pNPC = pEntity->MyNPCPointer(); - if (pNPC && pNPC->GetActiveWeapon()) - { - pNPC->GetActiveWeapon()->m_iClip1 *= 0.5; - } - } -} - -CON_COMMAND( ai_clear_bad_links, "Clears bits set on nav links indicating link is unusable " ) -{ - CAI_Node *pNode; - - for ( int i = 0; i < g_pBigAINet->NumNodes(); i++ ) - { - pNode = g_pBigAINet->GetNode( i ); - for ( int j = 0; j < pNode->NumLinks(); j++ ) - { - pNode->GetLinkByIndex( j )->m_LinkInfo &= ~bits_LINK_STALE_SUGGESTED; - } - } -} - -CON_COMMAND( ai_test_los, "Test AI LOS from the player's POV" ) -{ - trace_t tr; - // Use the custom LOS trace filter - CTraceFilterLOS traceFilter( UTIL_GetLocalPlayer(), COLLISION_GROUP_NONE ); - UTIL_TraceLine( UTIL_GetLocalPlayer()->EyePosition(), UTIL_GetLocalPlayer()->EyePosition() + UTIL_GetLocalPlayer()->EyeDirection3D() * MAX_COORD_RANGE, MASK_BLOCKLOS_AND_NPCS, &traceFilter, &tr ); - NDebugOverlay::Line( UTIL_GetLocalPlayer()->EyePosition(), tr.endpos, 127, 127, 127, true, 5 ); - NDebugOverlay::Cross3D( tr.endpos, 24, 255, 255, 255, true, 5 ); -} - -#ifdef VPROF_ENABLED - -CON_COMMAND(ainet_generate_report, "Generate a report to the console.") -{ - g_VProfCurrentProfile.OutputReport( VPRT_FULL, "AINet" ); -} - -CON_COMMAND(ainet_generate_report_only, "Generate a report to the console.") -{ - g_VProfCurrentProfile.OutputReport( VPRT_FULL, "AINet", g_VProfCurrentProfile.BudgetGroupNameToBudgetGroupID( "AINet" ) ); -} - -#endif diff --git a/game/server/ai_condition.cpp b/game/server/ai_condition.cpp deleted file mode 100644 index a06218da7..000000000 --- a/game/server/ai_condition.cpp +++ /dev/null @@ -1,105 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "stringregistry.h" -#include "ai_basenpc.h" -#include "ai_condition.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Given and condition name, return the condition ID -//----------------------------------------------------------------------------- -int CAI_BaseNPC::GetConditionID(const char* condName) -{ - return GetSchedulingSymbols()->ConditionSymbolToId(condName); -} - -//----------------------------------------------------------------------------- -// Purpose: Register the default conditions -// Input : -// Output : -//----------------------------------------------------------------------------- - -#define ADD_CONDITION_TO_SR( _n ) idSpace.AddCondition( #_n, _n, "CAI_BaseNPC" ) - -void CAI_BaseNPC::InitDefaultConditionSR(void) -{ - CAI_ClassScheduleIdSpace &idSpace = CAI_BaseNPC::AccessClassScheduleIdSpaceDirect(); - - ADD_CONDITION_TO_SR( COND_NONE ); - ADD_CONDITION_TO_SR( COND_IN_PVS ); - ADD_CONDITION_TO_SR( COND_IDLE_INTERRUPT ); - ADD_CONDITION_TO_SR( COND_LOW_PRIMARY_AMMO ); - ADD_CONDITION_TO_SR( COND_NO_PRIMARY_AMMO ); - ADD_CONDITION_TO_SR( COND_NO_SECONDARY_AMMO ); - ADD_CONDITION_TO_SR( COND_NO_WEAPON ); - ADD_CONDITION_TO_SR( COND_SEE_HATE ); - ADD_CONDITION_TO_SR( COND_SEE_FEAR ); - ADD_CONDITION_TO_SR( COND_SEE_DISLIKE ); - ADD_CONDITION_TO_SR( COND_SEE_ENEMY ); - ADD_CONDITION_TO_SR( COND_LOST_ENEMY ); - ADD_CONDITION_TO_SR( COND_ENEMY_WENT_NULL ); - ADD_CONDITION_TO_SR( COND_HAVE_ENEMY_LOS ); - ADD_CONDITION_TO_SR( COND_HAVE_TARGET_LOS ); - ADD_CONDITION_TO_SR( COND_ENEMY_OCCLUDED ); - ADD_CONDITION_TO_SR( COND_TARGET_OCCLUDED ); - ADD_CONDITION_TO_SR( COND_ENEMY_TOO_FAR ); - ADD_CONDITION_TO_SR( COND_LIGHT_DAMAGE ); - ADD_CONDITION_TO_SR( COND_HEAVY_DAMAGE ); - ADD_CONDITION_TO_SR( COND_PHYSICS_DAMAGE ); - ADD_CONDITION_TO_SR( COND_REPEATED_DAMAGE ); - ADD_CONDITION_TO_SR( COND_CAN_RANGE_ATTACK1 ); - ADD_CONDITION_TO_SR( COND_CAN_RANGE_ATTACK2 ); - ADD_CONDITION_TO_SR( COND_CAN_MELEE_ATTACK1 ); - ADD_CONDITION_TO_SR( COND_CAN_MELEE_ATTACK2 ); - ADD_CONDITION_TO_SR( COND_PROVOKED ); - ADD_CONDITION_TO_SR( COND_NEW_ENEMY ); - ADD_CONDITION_TO_SR( COND_ENEMY_FACING_ME ); - ADD_CONDITION_TO_SR( COND_BEHIND_ENEMY ); - ADD_CONDITION_TO_SR( COND_ENEMY_DEAD ); - ADD_CONDITION_TO_SR( COND_ENEMY_UNREACHABLE ); - ADD_CONDITION_TO_SR( COND_SEE_PLAYER ); - ADD_CONDITION_TO_SR( COND_LOST_PLAYER ); - ADD_CONDITION_TO_SR( COND_SEE_NEMESIS ); - ADD_CONDITION_TO_SR( COND_TASK_FAILED ); - ADD_CONDITION_TO_SR( COND_SCHEDULE_DONE ); - ADD_CONDITION_TO_SR( COND_SMELL ); - ADD_CONDITION_TO_SR( COND_TOO_CLOSE_TO_ATTACK ); - ADD_CONDITION_TO_SR( COND_TOO_FAR_TO_ATTACK ); - ADD_CONDITION_TO_SR( COND_NOT_FACING_ATTACK ); - ADD_CONDITION_TO_SR( COND_WEAPON_HAS_LOS ); - ADD_CONDITION_TO_SR( COND_WEAPON_BLOCKED_BY_FRIEND ); // Friend between gun and target - ADD_CONDITION_TO_SR( COND_WEAPON_PLAYER_IN_SPREAD ); // Player in shooting direction - ADD_CONDITION_TO_SR( COND_WEAPON_PLAYER_NEAR_TARGET ); // Player near shooting position - ADD_CONDITION_TO_SR( COND_WEAPON_SIGHT_OCCLUDED ); - ADD_CONDITION_TO_SR( COND_BETTER_WEAPON_AVAILABLE ); - ADD_CONDITION_TO_SR( COND_HEALTH_ITEM_AVAILABLE ); - ADD_CONDITION_TO_SR( COND_FLOATING_OFF_GROUND ); - ADD_CONDITION_TO_SR( COND_MOBBED_BY_ENEMIES ); - ADD_CONDITION_TO_SR( COND_GIVE_WAY ); - ADD_CONDITION_TO_SR( COND_WAY_CLEAR ); - ADD_CONDITION_TO_SR( COND_HEAR_DANGER ); - ADD_CONDITION_TO_SR( COND_HEAR_THUMPER ); - ADD_CONDITION_TO_SR( COND_HEAR_COMBAT ); - ADD_CONDITION_TO_SR( COND_HEAR_WORLD ); - ADD_CONDITION_TO_SR( COND_HEAR_PLAYER ); - ADD_CONDITION_TO_SR( COND_HEAR_BULLET_IMPACT ); - ADD_CONDITION_TO_SR( COND_HEAR_BUGBAIT ); - ADD_CONDITION_TO_SR( COND_HEAR_PHYSICS_DANGER ); - ADD_CONDITION_TO_SR( COND_HEAR_MOVE_AWAY ); - ADD_CONDITION_TO_SR( COND_NO_HEAR_DANGER ); - ADD_CONDITION_TO_SR( COND_PLAYER_PUSHING ); - ADD_CONDITION_TO_SR( COND_RECEIVED_ORDERS ); - ADD_CONDITION_TO_SR( COND_PLAYER_ADDED_TO_SQUAD ); - ADD_CONDITION_TO_SR( COND_PLAYER_REMOVED_FROM_SQUAD ); - ADD_CONDITION_TO_SR( COND_NPC_FREEZE ); - ADD_CONDITION_TO_SR( COND_NPC_UNFREEZE ); - ADD_CONDITION_TO_SR( COND_TALKER_RESPOND_TO_QUESTION ); - ADD_CONDITION_TO_SR( COND_NO_CUSTOM_INTERRUPTS ); -} diff --git a/game/server/ai_condition.h b/game/server/ai_condition.h deleted file mode 100644 index 2692259a8..000000000 --- a/game/server/ai_condition.h +++ /dev/null @@ -1,121 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: The default shared conditions -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef CONDITION_H -#define CONDITION_H - -// NOTE: Changing this constant will break save files!!! (changes type of CAI_ScheduleBits) -#ifndef MAX_CONDITIONS -#define MAX_CONDITIONS 32*8 -#endif - -//========================================================= -// These are the default shared conditions -//========================================================= -enum SCOND_t -{ - COND_NONE, // A way for a function to return no condition to get - - COND_IN_PVS, - COND_IDLE_INTERRUPT, // The schedule in question is a low priority idle, and therefore a candidate for translation into something else - - COND_LOW_PRIMARY_AMMO, - COND_NO_PRIMARY_AMMO, - COND_NO_SECONDARY_AMMO, - COND_NO_WEAPON, - COND_SEE_HATE, - COND_SEE_FEAR, - COND_SEE_DISLIKE, - COND_SEE_ENEMY, - COND_LOST_ENEMY, - COND_ENEMY_WENT_NULL, // What most people think COND_LOST_ENEMY is: This condition is set in the edge case where you had an enemy last think, but don't have one this think. - COND_ENEMY_OCCLUDED, // Can't see m_hEnemy - COND_TARGET_OCCLUDED, // Can't see m_hTargetEnt - COND_HAVE_ENEMY_LOS, - COND_HAVE_TARGET_LOS, - COND_LIGHT_DAMAGE, - COND_HEAVY_DAMAGE, - COND_PHYSICS_DAMAGE, - COND_REPEATED_DAMAGE, // Damaged several times in a row - - COND_CAN_RANGE_ATTACK1, // Hitscan weapon only - COND_CAN_RANGE_ATTACK2, // Grenade weapon only - COND_CAN_MELEE_ATTACK1, - COND_CAN_MELEE_ATTACK2, - - COND_PROVOKED, - COND_NEW_ENEMY, - - COND_ENEMY_TOO_FAR, // Can we get rid of this one!?!? - COND_ENEMY_FACING_ME, - COND_BEHIND_ENEMY, - COND_ENEMY_DEAD, - COND_ENEMY_UNREACHABLE, // Not connected to me via node graph - - COND_SEE_PLAYER, - COND_LOST_PLAYER, - COND_SEE_NEMESIS, - COND_TASK_FAILED, - COND_SCHEDULE_DONE, - COND_SMELL, - COND_TOO_CLOSE_TO_ATTACK, // FIXME: most of this next group are meaningless since they're shared between all attack checks! - COND_TOO_FAR_TO_ATTACK, - COND_NOT_FACING_ATTACK, - COND_WEAPON_HAS_LOS, - COND_WEAPON_BLOCKED_BY_FRIEND, // Friend between weapon and target - COND_WEAPON_PLAYER_IN_SPREAD, // Player in shooting direction - COND_WEAPON_PLAYER_NEAR_TARGET, // Player near shooting position - COND_WEAPON_SIGHT_OCCLUDED, - COND_BETTER_WEAPON_AVAILABLE, - COND_HEALTH_ITEM_AVAILABLE, // There's a healthkit available. - COND_GIVE_WAY, // Another npc requested that I give way - COND_WAY_CLEAR, // I no longer have to give way - COND_HEAR_DANGER, - COND_HEAR_THUMPER, - COND_HEAR_BUGBAIT, - COND_HEAR_COMBAT, - COND_HEAR_WORLD, - COND_HEAR_PLAYER, - COND_HEAR_BULLET_IMPACT, - COND_HEAR_PHYSICS_DANGER, - COND_HEAR_MOVE_AWAY, - COND_HEAR_SPOOKY, // Zombies make this when Alyx is in darkness mode - - COND_NO_HEAR_DANGER, // Since we can't use ~CONDITION. Mutually exclusive with COND_HEAR_DANGER - - COND_FLOATING_OFF_GROUND, - - COND_MOBBED_BY_ENEMIES, // Surrounded by a large number of enemies melee attacking me. (Zombies or Antlions, usually). - - // Commander stuff - COND_RECEIVED_ORDERS, - COND_PLAYER_ADDED_TO_SQUAD, - COND_PLAYER_REMOVED_FROM_SQUAD, - - COND_PLAYER_PUSHING, - COND_NPC_FREEZE, // We received an npc_freeze command while we were unfrozen - COND_NPC_UNFREEZE, // We received an npc_freeze command while we were frozen - - // This is a talker condition, but done here because we need to handle it in base AI - // due to it's interaction with behaviors. - COND_TALKER_RESPOND_TO_QUESTION, - - COND_NO_CUSTOM_INTERRUPTS, // Don't call BuildScheduleTestBits for this schedule. Used for schedules that must strictly control their interruptibility. - - // ====================================== - // IMPORTANT: This must be the last enum - // ====================================== - LAST_SHARED_CONDITION -}; - -#endif //CONDITION_H diff --git a/game/server/ai_debug.h b/game/server/ai_debug.h deleted file mode 100644 index 79732ea95..000000000 --- a/game/server/ai_debug.h +++ /dev/null @@ -1,88 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_DEBUG_H -#define AI_DEBUG_H - -#include "fmtstr.h" -#include "ai_debug_shared.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -// This dumps a summary result on exit -//#define PROFILE_AI 1 - -#define AI_PROFILE_SCOPE_BEGIN( tag ) if (0) ; else { AI_PROFILE_SCOPE( tag ) -#define AI_PROFILE_SCOPE_BEGIN_( pszName ) if (0) ; else { AI_PROFILE_SCOPE_( pszName ) -#define AI_PROFILE_SCOPE_END() } do {} while (0) - -#if defined(VPROF_AI) -#define VProfAI() true -#else -#define VProfAI() false -#endif -#if defined(VPROF_AI) -#include "tier0/vprof.h" -#define AI_PROFILE_SCOPE( tag ) VPROF( #tag ) -#define AI_PROFILE_SCOPE_( pszName ) VPROF( pszName ) -#define AI_PROFILE_MEASURE_SCOPE( tag ) VPROF( #tag ) -#elif defined(PROFILE_AI) -#include "tier0/fasttimer.h" -#define AI_PROFILE_SCOPE( tag ) PROFILE_SCOPE( tag ) -#define AI_PROFILE_MEASURE_SCOPE( tag ) PROFILE_SCOPE( tag ) -#else -#define AI_PROFILE_MEASURE_SCOPE( tag ) ((void)0) -#define AI_PROFILE_SCOPE( tag ) ((void)0) -#endif - -#ifndef AI_PROFILE_SCOPE_ -#define AI_PROFILE_SCOPE_( pszName ) ((void)0) -#endif - - -enum AIMsgFlags -{ - AIMF_IGNORE_SELECTED = 0x01 -}; - -void DevMsg( CAI_BaseNPC *pAI, unsigned flags, const char *pszFormat, ... ); -void DevMsg( CAI_BaseNPC *pAI, const char *pszFormat, ... ); - - -//----------------------------------------------------------------------------- -// Purpose: Use this to perform AI tracelines that are trying to determine LOS between points. -// LOS checks between entities should use FVisible. -//----------------------------------------------------------------------------- -void AI_TraceLOS( const Vector& vecAbsStart, const Vector& vecAbsEnd, CBaseEntity *pLooker, trace_t *ptr, ITraceFilter *pFilter = NULL ); - -//----------------------------------------------------------------------------- - -#ifdef DEBUG -extern bool g_fTestSteering; -#define TestingSteering() g_fTestSteering -#else -#define TestingSteering() false -#endif - -//----------------------------------------------------------------------------- - - -#ifdef _DEBUG -extern ConVar ai_debug_doors; -#define AIIsDebuggingDoors( pNPC ) ( ai_debug_doors.GetBool() && pNPC->m_bSelected ) -#define AIDoorDebugMsg( pNPC, msg ) if ( !AIIsDebuggingDoors( pNPC ) ) ; else Msg( msg ) -#else -#define AIIsDebuggingDoors( pNPC ) (false) -#define AIDoorDebugMsg( pNPC, msg ) ((void)(0)) -#endif - - -//----------------------------------------------------------------------------- - -#endif // AI_DEBUG_H diff --git a/game/server/ai_default.cpp b/game/server/ai_default.cpp deleted file mode 100644 index cbf48a0b3..000000000 --- a/game/server/ai_default.cpp +++ /dev/null @@ -1,2383 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Default schedules. -// -//=============================================================================// - -#include "cbase.h" -#include "ai_default.h" -#include "soundent.h" -#include "scripted.h" -#include "ai_schedule.h" -#include "ai_squad.h" -#include "ai_senses.h" -#include "ai_networkmanager.h" -#include "stringregistry.h" -#include "igamesystem.h" -#include "ai_network.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -CAI_Schedule *CAI_BaseNPC::ScheduleInList( const char *pName, CAI_Schedule **pList, int listCount ) -{ - int i; - - if ( !pName ) - { - DevMsg( "%s set to unnamed schedule!\n", GetClassname() ); - return NULL; - } - - - for ( i = 0; i < listCount; i++ ) - { - if ( !pList[i]->GetName() ) - { - DevMsg( "Unnamed schedule!\n" ); - continue; - } - if ( stricmp( pName, pList[i]->GetName() ) == 0 ) - return pList[i]; - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Given and schedule name, return the schedule ID -//----------------------------------------------------------------------------- -int CAI_BaseNPC::GetScheduleID(const char* schedName) -{ - return GetSchedulingSymbols()->ScheduleSymbolToId(schedName); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_BaseNPC::InitDefaultScheduleSR(void) -{ - #define ADD_DEF_SCHEDULE( name, localId ) idSpace.AddSchedule(name, localId, "CAI_BaseNPC" ) - - CAI_ClassScheduleIdSpace &idSpace = CAI_BaseNPC::AccessClassScheduleIdSpaceDirect(); - - ADD_DEF_SCHEDULE( "SCHED_NONE", SCHED_NONE); - ADD_DEF_SCHEDULE( "SCHED_IDLE_STAND", SCHED_IDLE_STAND); - ADD_DEF_SCHEDULE( "SCHED_IDLE_WALK", SCHED_IDLE_WALK); - ADD_DEF_SCHEDULE( "SCHED_IDLE_WANDER", SCHED_IDLE_WANDER); - ADD_DEF_SCHEDULE( "SCHED_WAKE_ANGRY", SCHED_WAKE_ANGRY); - ADD_DEF_SCHEDULE( "SCHED_ALERT_FACE", SCHED_ALERT_FACE); - ADD_DEF_SCHEDULE( "SCHED_ALERT_FACE_BESTSOUND", SCHED_ALERT_FACE_BESTSOUND); - ADD_DEF_SCHEDULE( "SCHED_ALERT_REACT_TO_COMBAT_SOUND", SCHED_ALERT_REACT_TO_COMBAT_SOUND); - ADD_DEF_SCHEDULE( "SCHED_ALERT_SCAN", SCHED_ALERT_SCAN); - ADD_DEF_SCHEDULE( "SCHED_ALERT_STAND", SCHED_ALERT_STAND); - ADD_DEF_SCHEDULE( "SCHED_ALERT_WALK", SCHED_ALERT_WALK); - ADD_DEF_SCHEDULE( "SCHED_INVESTIGATE_SOUND", SCHED_INVESTIGATE_SOUND); - ADD_DEF_SCHEDULE( "SCHED_COMBAT_FACE", SCHED_COMBAT_FACE); - ADD_DEF_SCHEDULE( "SCHED_COMBAT_SWEEP", SCHED_COMBAT_SWEEP); - ADD_DEF_SCHEDULE( "SCHED_FEAR_FACE", SCHED_FEAR_FACE); - ADD_DEF_SCHEDULE( "SCHED_COMBAT_STAND", SCHED_COMBAT_STAND); - ADD_DEF_SCHEDULE( "SCHED_COMBAT_WALK", SCHED_COMBAT_WALK); - ADD_DEF_SCHEDULE( "SCHED_CHASE_ENEMY", SCHED_CHASE_ENEMY); - ADD_DEF_SCHEDULE( "SCHED_CHASE_ENEMY_FAILED", SCHED_CHASE_ENEMY_FAILED); - ADD_DEF_SCHEDULE( "SCHED_VICTORY_DANCE", SCHED_VICTORY_DANCE); - ADD_DEF_SCHEDULE( "SCHED_TARGET_FACE", SCHED_TARGET_FACE); - ADD_DEF_SCHEDULE( "SCHED_TARGET_CHASE", SCHED_TARGET_CHASE); - ADD_DEF_SCHEDULE( "SCHED_SMALL_FLINCH", SCHED_SMALL_FLINCH); - ADD_DEF_SCHEDULE( "SCHED_BIG_FLINCH", SCHED_BIG_FLINCH); - ADD_DEF_SCHEDULE( "SCHED_BACK_AWAY_FROM_ENEMY", SCHED_BACK_AWAY_FROM_ENEMY); - ADD_DEF_SCHEDULE( "SCHED_MOVE_AWAY_FROM_ENEMY", SCHED_MOVE_AWAY_FROM_ENEMY); - ADD_DEF_SCHEDULE( "SCHED_BACK_AWAY_FROM_SAVE_POSITION", SCHED_BACK_AWAY_FROM_SAVE_POSITION); - ADD_DEF_SCHEDULE( "SCHED_TAKE_COVER_FROM_ENEMY", SCHED_TAKE_COVER_FROM_ENEMY); - ADD_DEF_SCHEDULE( "SCHED_TAKE_COVER_FROM_BEST_SOUND", SCHED_TAKE_COVER_FROM_BEST_SOUND); - ADD_DEF_SCHEDULE( "SCHED_FLEE_FROM_BEST_SOUND", SCHED_FLEE_FROM_BEST_SOUND); - ADD_DEF_SCHEDULE( "SCHED_TAKE_COVER_FROM_ORIGIN", SCHED_TAKE_COVER_FROM_ORIGIN); - ADD_DEF_SCHEDULE( "SCHED_FAIL_TAKE_COVER", SCHED_FAIL_TAKE_COVER); - ADD_DEF_SCHEDULE( "SCHED_RUN_FROM_ENEMY", SCHED_RUN_FROM_ENEMY); - ADD_DEF_SCHEDULE( "SCHED_RUN_FROM_ENEMY_FALLBACK", SCHED_RUN_FROM_ENEMY_FALLBACK); - ADD_DEF_SCHEDULE( "SCHED_MOVE_TO_WEAPON_RANGE", SCHED_MOVE_TO_WEAPON_RANGE); - ADD_DEF_SCHEDULE( "SCHED_ESTABLISH_LINE_OF_FIRE", SCHED_ESTABLISH_LINE_OF_FIRE); - ADD_DEF_SCHEDULE( "SCHED_SHOOT_ENEMY_COVER", SCHED_SHOOT_ENEMY_COVER); - ADD_DEF_SCHEDULE( "SCHED_ESTABLISH_LINE_OF_FIRE_FALLBACK", SCHED_ESTABLISH_LINE_OF_FIRE_FALLBACK); - ADD_DEF_SCHEDULE( "SCHED_PRE_FAIL_ESTABLISH_LINE_OF_FIRE", SCHED_PRE_FAIL_ESTABLISH_LINE_OF_FIRE); - ADD_DEF_SCHEDULE( "SCHED_FAIL_ESTABLISH_LINE_OF_FIRE", SCHED_FAIL_ESTABLISH_LINE_OF_FIRE); - ADD_DEF_SCHEDULE( "SCHED_COWER", SCHED_COWER); - ADD_DEF_SCHEDULE( "SCHED_MELEE_ATTACK1", SCHED_MELEE_ATTACK1); - ADD_DEF_SCHEDULE( "SCHED_MELEE_ATTACK2", SCHED_MELEE_ATTACK2); - ADD_DEF_SCHEDULE( "SCHED_RANGE_ATTACK1", SCHED_RANGE_ATTACK1); - ADD_DEF_SCHEDULE( "SCHED_RANGE_ATTACK2", SCHED_RANGE_ATTACK2); - ADD_DEF_SCHEDULE( "SCHED_SPECIAL_ATTACK1", SCHED_SPECIAL_ATTACK1); - ADD_DEF_SCHEDULE( "SCHED_SPECIAL_ATTACK2", SCHED_SPECIAL_ATTACK2); - ADD_DEF_SCHEDULE( "SCHED_STANDOFF", SCHED_STANDOFF); - ADD_DEF_SCHEDULE( "SCHED_ARM_WEAPON", SCHED_ARM_WEAPON); - ADD_DEF_SCHEDULE( "SCHED_DISARM_WEAPON", SCHED_DISARM_WEAPON); - ADD_DEF_SCHEDULE( "SCHED_HIDE_AND_RELOAD", SCHED_HIDE_AND_RELOAD); - ADD_DEF_SCHEDULE( "SCHED_RELOAD", SCHED_RELOAD); - ADD_DEF_SCHEDULE( "SCHED_AMBUSH", SCHED_AMBUSH); - ADD_DEF_SCHEDULE( "SCHED_DIE", SCHED_DIE); - ADD_DEF_SCHEDULE( "SCHED_DIE_RAGDOLL", SCHED_DIE_RAGDOLL); - ADD_DEF_SCHEDULE( "SCHED_WAIT_FOR_SCRIPT", SCHED_WAIT_FOR_SCRIPT); - ADD_DEF_SCHEDULE( "SCHED_AISCRIPT", SCHED_AISCRIPT); - ADD_DEF_SCHEDULE( "SCHED_SCRIPTED_WALK", SCHED_SCRIPTED_WALK); - ADD_DEF_SCHEDULE( "SCHED_SCRIPTED_RUN", SCHED_SCRIPTED_RUN); - ADD_DEF_SCHEDULE( "SCHED_SCRIPTED_CUSTOM_MOVE", SCHED_SCRIPTED_CUSTOM_MOVE); - ADD_DEF_SCHEDULE( "SCHED_SCRIPTED_WAIT", SCHED_SCRIPTED_WAIT); - ADD_DEF_SCHEDULE( "SCHED_SCRIPTED_FACE", SCHED_SCRIPTED_FACE); - ADD_DEF_SCHEDULE( "SCHED_SCENE_GENERIC", SCHED_SCENE_GENERIC); - ADD_DEF_SCHEDULE( "SCHED_NEW_WEAPON", SCHED_NEW_WEAPON); - ADD_DEF_SCHEDULE( "SCHED_NEW_WEAPON_CHEAT", SCHED_NEW_WEAPON_CHEAT); - ADD_DEF_SCHEDULE( "SCHED_SWITCH_TO_PENDING_WEAPON", SCHED_SWITCH_TO_PENDING_WEAPON ); - ADD_DEF_SCHEDULE( "SCHED_GET_HEALTHKIT", SCHED_GET_HEALTHKIT); - ADD_DEF_SCHEDULE( "SCHED_MOVE_AWAY", SCHED_MOVE_AWAY); - ADD_DEF_SCHEDULE( "SCHED_MOVE_AWAY_FAIL", SCHED_MOVE_AWAY_FAIL); - ADD_DEF_SCHEDULE( "SCHED_MOVE_AWAY_END", SCHED_MOVE_AWAY_END); - ADD_DEF_SCHEDULE( "SCHED_WAIT_FOR_SPEAK_FINISH", SCHED_WAIT_FOR_SPEAK_FINISH); - ADD_DEF_SCHEDULE( "SCHED_FORCED_GO", SCHED_FORCED_GO); - ADD_DEF_SCHEDULE( "SCHED_FORCED_GO_RUN", SCHED_FORCED_GO_RUN); - ADD_DEF_SCHEDULE( "SCHED_PATROL_WALK", SCHED_PATROL_WALK); - ADD_DEF_SCHEDULE( "SCHED_COMBAT_PATROL", SCHED_COMBAT_PATROL); - ADD_DEF_SCHEDULE( "SCHED_PATROL_RUN", SCHED_PATROL_RUN); - ADD_DEF_SCHEDULE( "SCHED_RUN_RANDOM", SCHED_RUN_RANDOM); - ADD_DEF_SCHEDULE( "SCHED_FAIL", SCHED_FAIL); - ADD_DEF_SCHEDULE( "SCHED_FAIL_NOSTOP", SCHED_FAIL_NOSTOP); - ADD_DEF_SCHEDULE( "SCHED_FALL_TO_GROUND", SCHED_FALL_TO_GROUND); - ADD_DEF_SCHEDULE( "SCHED_DROPSHIP_DUSTOFF", SCHED_DROPSHIP_DUSTOFF); - ADD_DEF_SCHEDULE( "SCHED_NPC_FREEZE", SCHED_NPC_FREEZE); - - ADD_DEF_SCHEDULE( "SCHED_FLINCH_PHYSICS", SCHED_FLINCH_PHYSICS); - - ADD_DEF_SCHEDULE( "SCHED_RUN_FROM_ENEMY_MOB", SCHED_RUN_FROM_ENEMY_MOB ); - - ADD_DEF_SCHEDULE( "SCHED_DUCK_DODGE", SCHED_DUCK_DODGE ); - - ADD_DEF_SCHEDULE( "SCHED_INTERACTION_MOVE_TO_PARTNER", SCHED_INTERACTION_MOVE_TO_PARTNER ); - ADD_DEF_SCHEDULE( "SCHED_INTERACTION_WAIT_FOR_PARTNER", SCHED_INTERACTION_WAIT_FOR_PARTNER ); - - ADD_DEF_SCHEDULE( "SCHED_SLEEP", SCHED_SLEEP ); -} - -bool CAI_BaseNPC::LoadDefaultSchedules(void) -{ -// AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_NONE); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_IDLE_STAND); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_IDLE_WALK); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_IDLE_WANDER); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_WAKE_ANGRY); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_ALERT_FACE); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_ALERT_FACE_BESTSOUND); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_ALERT_REACT_TO_COMBAT_SOUND); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_ALERT_SCAN); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_ALERT_STAND); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_ALERT_WALK); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_INVESTIGATE_SOUND); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_COMBAT_FACE); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_COMBAT_SWEEP); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_COMBAT_WALK); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_FEAR_FACE); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_COMBAT_STAND); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_CHASE_ENEMY); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_CHASE_ENEMY_FAILED); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_VICTORY_DANCE); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_TARGET_FACE); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_TARGET_CHASE); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_SMALL_FLINCH); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_BIG_FLINCH); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_BACK_AWAY_FROM_ENEMY); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_MOVE_AWAY_FROM_ENEMY); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_BACK_AWAY_FROM_SAVE_POSITION); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_TAKE_COVER_FROM_ENEMY); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_TAKE_COVER_FROM_BEST_SOUND); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_FLEE_FROM_BEST_SOUND); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_TAKE_COVER_FROM_ORIGIN); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_FAIL_TAKE_COVER); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_RUN_FROM_ENEMY); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_RUN_FROM_ENEMY_FALLBACK); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_MOVE_TO_WEAPON_RANGE); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_ESTABLISH_LINE_OF_FIRE); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_SHOOT_ENEMY_COVER); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_ESTABLISH_LINE_OF_FIRE_FALLBACK); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_PRE_FAIL_ESTABLISH_LINE_OF_FIRE); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_FAIL_ESTABLISH_LINE_OF_FIRE); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_COWER); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_MELEE_ATTACK1); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_MELEE_ATTACK2); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_RANGE_ATTACK1); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_RANGE_ATTACK2); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_SPECIAL_ATTACK1); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_SPECIAL_ATTACK2); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_STANDOFF); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_ARM_WEAPON); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_DISARM_WEAPON); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_HIDE_AND_RELOAD); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_RELOAD); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_AMBUSH); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_DIE); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_DIE_RAGDOLL); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_WAIT_FOR_SCRIPT); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_SCRIPTED_WALK); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_SCRIPTED_RUN); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_SCRIPTED_CUSTOM_MOVE); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_SCRIPTED_WAIT); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_SCRIPTED_FACE); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_SCENE_GENERIC); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_NEW_WEAPON); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_NEW_WEAPON_CHEAT); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_SWITCH_TO_PENDING_WEAPON); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_GET_HEALTHKIT); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_MOVE_AWAY); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_MOVE_AWAY_FAIL); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_MOVE_AWAY_END); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_WAIT_FOR_SPEAK_FINISH); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_FORCED_GO); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_FORCED_GO_RUN); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_PATROL_WALK); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_COMBAT_PATROL); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_PATROL_RUN); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_RUN_RANDOM); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_FAIL); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_FAIL_NOSTOP); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_FALL_TO_GROUND); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_DROPSHIP_DUSTOFF); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_FLINCH_PHYSICS); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_RUN_FROM_ENEMY_MOB ); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_DUCK_DODGE); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_NPC_FREEZE); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_INTERACTION_MOVE_TO_PARTNER); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_INTERACTION_WAIT_FOR_PARTNER); - AI_LOAD_DEF_SCHEDULE( CAI_BaseNPC, SCHED_SLEEP ); - - return true; -} - -int CAI_BaseNPC::TranslateSchedule( int scheduleType ) -{ - // FIXME: Where should this go now? -#if 0 - if (scheduleType >= LAST_SHARED_SCHEDULE) - { - char errMsg[256]; - Q_snprintf(errMsg,sizeof(errMsg),"ERROR: Subclass Schedule (%s) Hitting Base Class!\n",ScheduleName(scheduleType)); - DevMsg( errMsg ); - AddTimedOverlay( errMsg, 5); - return SCHED_FAIL; - } -#endif - - switch( scheduleType ) - { - // Hande some special cases - case SCHED_AISCRIPT: - { - Assert( m_hCine != NULL ); - if ( !m_hCine ) - { - DevWarning( 2, "Script failed for %s\n", GetClassname() ); - CineCleanup(); - return SCHED_IDLE_STAND; - } -// else -// DevMsg( 2, "Starting script %s for %s\n", STRING( m_hCine->m_iszPlay ), GetClassname() ); - - switch ( m_hCine->m_fMoveTo ) - { - case CINE_MOVETO_WAIT: - case CINE_MOVETO_TELEPORT: - { - return SCHED_SCRIPTED_WAIT; - } - - case CINE_MOVETO_WALK: - { - return SCHED_SCRIPTED_WALK; - } - - case CINE_MOVETO_RUN: - { - return SCHED_SCRIPTED_RUN; - } - - case CINE_MOVETO_CUSTOM: - { - return SCHED_SCRIPTED_CUSTOM_MOVE; - } - - case CINE_MOVETO_WAIT_FACING: - { - return SCHED_SCRIPTED_FACE; - } - } - } - break; - - case SCHED_IDLE_STAND: - { - // FIXME: crows are set into IDLE_STAND as an failure schedule, not sure if ALERT_STAND or COMBAT_STAND is a better choice - // Assert( m_NPCState == NPC_STATE_IDLE ); - } - break; - case SCHED_IDLE_WANDER: - { - // FIXME: citizen interaction only, no idea what the state is. - // Assert( m_NPCState == NPC_STATE_IDLE ); - } - break; - - case SCHED_IDLE_WALK: - { - switch( m_NPCState ) - { - case NPC_STATE_ALERT: - return SCHED_ALERT_WALK; - case NPC_STATE_COMBAT: - return SCHED_COMBAT_WALK; - default: - break; - } - } - break; - - case SCHED_ALERT_FACE: - { - // FIXME: default AI can pick this when in idle state - // Assert( m_NPCState == NPC_STATE_ALERT ); - } - break; - case SCHED_ALERT_SCAN: - case SCHED_ALERT_STAND: - { - // FIXME: rollermines use this when they're being held - // Assert( m_NPCState == NPC_STATE_ALERT ); - } - break; - case SCHED_ALERT_WALK: - { - Assert( m_NPCState == NPC_STATE_ALERT ); - } - break; - case SCHED_COMBAT_FACE: - { - // FIXME: failure schedule for SCHED_PATROL which can be called when in alert - // Assert( m_NPCState == NPC_STATE_COMBAT ); - } - break; - case SCHED_COMBAT_STAND: - { - // FIXME: never used? - } - break; - case SCHED_COMBAT_WALK: - { - Assert( m_NPCState == NPC_STATE_COMBAT ); - } - break; - } - - return scheduleType; -} - -//========================================================= -// GetScheduleOfType - returns a pointer to one of the -// NPC's available schedules of the indicated type. -//========================================================= -CAI_Schedule *CAI_BaseNPC::GetScheduleOfType( int scheduleType ) -{ - // allow the derived classes to pick an appropriate version of this schedule or override - // base schedule types. - AI_PROFILE_SCOPE_BEGIN(CAI_BaseNPC_TranslateSchedule); - scheduleType = TranslateSchedule( scheduleType ); - AI_PROFILE_SCOPE_END(); - - // Get a pointer to that schedule - CAI_Schedule *schedule = GetSchedule(scheduleType); - - if (!schedule) - { - DevMsg( "GetScheduleOfType(): No CASE for Schedule Type %d!\n", scheduleType ); - return GetSchedule(SCHED_IDLE_STAND); - } - return schedule; -} - -CAI_Schedule *CAI_BaseNPC::GetSchedule(int schedule) -{ - if (!GetClassScheduleIdSpace()->IsGlobalBaseSet()) - { - Warning("ERROR: %s missing schedule!\n", GetSchedulingErrorName()); - return g_AI_SchedulesManager.GetScheduleFromID(SCHED_IDLE_STAND); - } - if ( AI_IdIsLocal( schedule ) ) - { - schedule = GetClassScheduleIdSpace()->ScheduleLocalToGlobal(schedule); - } - - return g_AI_SchedulesManager.GetScheduleFromID( schedule ); -} - -bool CAI_BaseNPC::IsCurSchedule( int schedId, bool fIdeal ) -{ - if ( !m_pSchedule ) - return ( schedId == SCHED_NONE || schedId == AI_RemapToGlobal(SCHED_NONE) ); - - schedId = ( AI_IdIsLocal( schedId ) ) ? - GetClassScheduleIdSpace()->ScheduleLocalToGlobal(schedId) : - schedId; - if ( fIdeal ) - return ( schedId == m_IdealSchedule ); - - return ( m_pSchedule->GetId() == schedId ); -} - - -const char* CAI_BaseNPC::ConditionName(int conditionID) -{ - if ( AI_IdIsLocal( conditionID ) ) - conditionID = GetClassScheduleIdSpace()->ConditionLocalToGlobal(conditionID); - return GetSchedulingSymbols()->ConditionIdToSymbol(conditionID); -} - -const char *CAI_BaseNPC::TaskName(int taskID) -{ - if ( AI_IdIsLocal( taskID ) ) - taskID = GetClassScheduleIdSpace()->TaskLocalToGlobal(taskID); - return GetSchedulingSymbols()->TaskIdToSymbol( taskID ); -} - - - -// This hooks the main game systems callbacks to allow the AI system to manage memory -class CAI_SystemHook : public CAutoGameSystem -{ -public: - CAI_SystemHook( char const *name ) : CAutoGameSystem( name ) - { - } - - // UNDONE: Schedule / strings stuff should probably happen once each GAME, not each level - void LevelInitPreEntity() - { - extern float g_AINextDisabledMessageTime; - g_AINextDisabledMessageTime = 0; - - g_AI_SchedulesManager.CreateStringRegistries(); - - CAI_BaseNPC::gm_iNextThinkRebalanceTick = 0; - } - - virtual void LevelInitPostEntity() - { - g_AI_SensedObjectsManager.Init(); - } - - void LevelShutdownPreEntity() - { - CBaseCombatCharacter::ResetVisibilityCache(); - } - - void LevelShutdownPostEntity( void ) - { - g_AI_SensedObjectsManager.Term(); - g_pAINetworkManager->DeleteAllAINetworks(); - g_AI_SchedulesManager.DeleteAllSchedules(); - g_AI_SquadManager.DeleteAllSquads(); - g_AI_SchedulesManager.DestroyStringRegistries(); - } -}; - - -static CAI_SystemHook g_AISystemHook( "CAI_SystemHook" ); - - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -//========================================================= -// > Fail -// This schedule itself can fail because the NPC may -// be unable to finish the stop moving. If so, fall back -// the a fail schedule that has no stop moving in it. -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_FAIL, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_FAIL_NOSTOP" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT 1" - " TASK_WAIT_PVS 0" - "" - " Interrupts" - " COND_CAN_RANGE_ATTACK1 " - " COND_CAN_RANGE_ATTACK2 " - " COND_CAN_MELEE_ATTACK1 " - " COND_CAN_MELEE_ATTACK2" - " COND_GIVE_WAY" -); - -//========================================================= -// > Fail without stop moving, which can fail. -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_FAIL_NOSTOP, - - " Tasks" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT 1" - " TASK_WAIT_PVS 0" - "" - " Interrupts" - " COND_CAN_RANGE_ATTACK1 " - " COND_CAN_RANGE_ATTACK2 " - " COND_CAN_MELEE_ATTACK1 " - " COND_CAN_MELEE_ATTACK2" - " COND_GIVE_WAY" - ); - -//=============================================== -// > Idle_Stand -//=============================================== -AI_DEFINE_SCHEDULE -( - SCHED_IDLE_STAND, - - " Tasks" - " TASK_STOP_MOVING 1" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT 5" - " TASK_WAIT_PVS 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_FEAR" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_SMELL" - " COND_PROVOKED" - " COND_GIVE_WAY" - " COND_HEAR_PLAYER" - " COND_HEAR_DANGER" - " COND_HEAR_COMBAT" - " COND_HEAR_BULLET_IMPACT" - " COND_IDLE_INTERRUPT" -); - -//=============================================== -// > Wait_For_Script -//=============================================== -AI_DEFINE_SCHEDULE -( - SCHED_WAIT_FOR_SCRIPT, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_WAIT_INDEFINITE 0" - "" - " Interrupts" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" -); - -//=============================================== -// > IdleWalk -//=============================================== -AI_DEFINE_SCHEDULE -( - SCHED_IDLE_WALK, - - " Tasks" - " TASK_WALK_PATH 9999" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_WAIT_PVS 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_ENEMY" // in deference to scripted schedule where the enemy was slammed, thus no COND_NEW_ENEMY - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_SMELL" - " COND_PROVOKED" - " COND_HEAR_COMBAT" - " COND_HEAR_BULLET_IMPACT" -); - -//=============================================== -// > NewWeapon -//=============================================== -AI_DEFINE_SCHEDULE -( - SCHED_NEW_WEAPON, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_TOLERANCE_DISTANCE 5" - " TASK_GET_PATH_TO_TARGET_WEAPON 0" -// " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_NEW_WEAPON_CHEAT" - " TASK_WEAPON_RUN_PATH 0" - " TASK_STOP_MOVING 0" - " TASK_FACE_TARGET 0" - " TASK_WEAPON_PICKUP 0" - " TASK_WAIT 1"// Don't move before done standing up - "" - " Interrupts" - " COND_HEAR_DANGER" -); - -//=============================================== -// Heavy-handed temporary fail case for SCHED_NEW_WEAPON -// Just manufacture a weapon of the desired type. -//=============================================== -AI_DEFINE_SCHEDULE -( - SCHED_NEW_WEAPON_CHEAT, - - " Tasks" - " TASK_WEAPON_CREATE 0" - "" - " Interrupts" -); - -//=============================================== -// > SCHED_SWITCH_TO_PENDING_WEAPON -//=============================================== -AI_DEFINE_SCHEDULE -( - SCHED_SWITCH_TO_PENDING_WEAPON, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_DROP_WEAPON" - " TASK_CREATE_PENDING_WEAPON 0" - "" - " Interrupts" -); - -//=============================================== -//=============================================== -AI_DEFINE_SCHEDULE -( - SCHED_GET_HEALTHKIT, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_TOLERANCE_DISTANCE 5" - " TASK_GET_PATH_TO_TARGET_WEAPON 0" - " TASK_ITEM_RUN_PATH 0" - " TASK_STOP_MOVING 0" - " TASK_FACE_TARGET 0" - " TASK_ITEM_PICKUP 0" - "" - " Interrupts" -); - -//=============================================== -// > RangeAttack1 -//=============================================== -AI_DEFINE_SCHEDULE -( - SCHED_RANGE_ATTACK1, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_ANNOUNCE_ATTACK 1" // 1 = primary attack - " TASK_RANGE_ATTACK1 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_ENEMY_OCCLUDED" - " COND_NO_PRIMARY_AMMO" - " COND_HEAR_DANGER" - " COND_WEAPON_BLOCKED_BY_FRIEND" - " COND_WEAPON_SIGHT_OCCLUDED" -); - -//=============================================== -// > RangeAttack2 -//=============================================== -AI_DEFINE_SCHEDULE -( - SCHED_RANGE_ATTACK2, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_ANNOUNCE_ATTACK 2" // 2 = secondary attack - " TASK_RANGE_ATTACK2 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_ENEMY_OCCLUDED" - " COND_NO_SECONDARY_AMMO" - " COND_HEAR_DANGER" -); - -//========================================================= -// > Ambush - monster stands in place and waits for a new -// enemy or chance to attack an existing enemy. -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_AMBUSH, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT_INDEFINITE 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_PROVOKED" -); - -//========================================================= -// > Idle_Stand schedule - !!!BUGBUG - if this schedule doesn't -// complete on its own the monster's HintNode will not be -// cleared and the rest of the monster's group will avoid -// that node because they think the group member that was -// previously interrupted is still using that node to active -// idle. -///========================================================= -//AI_DEFINE_SCHEDULE -// Idle_Stand -// -//Tasks -// TASK_FIND_HINTNODE 0 -// TASK_GET_PATH_TO_HINTNODE 0 -// TASK_STORE_LASTPOSITION 0 -// TASK_WALK_PATH 0 -// TASK_WAIT_FOR_MOVEMENT 0 -// TASK_FACE_HINTNODE 0 -// TASK_PLAY_ACTIVE_IDLE 0 -// TASK_GET_PATH_TO_LASTPOSITION 0 -// TASK_WALK_PATH 0 -// TASK_WAIT_FOR_MOVEMENT 0 -// TASK_CLEAR_LASTPOSITION 0 -// TASK_CLEAR_HINTNODE 0 - - -//Interrupts -// New_Enemy -// Light_Damage -// Heavy_Damage -// Provoked -// HEAR_COMBAT -// HEAR_WORLD -// HEAR_PLAYER -// HEAR_DANGER -// HEAR_BULLET_IMPACT - - -//========================================================= -// > WakeAngry -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_WAKE_ANGRY, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE " - " TASK_SOUND_WAKE 0" - " TASK_FACE_IDEAL 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE " - "" - " Interrupts" -); - -//========================================================= -// > AlertFace -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_ALERT_FACE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_IDEAL 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_FEAR" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_PROVOKED" -); - -//========================================================= -// > AlertFace best sound -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_ALERT_FACE_BESTSOUND, - - " Tasks" - " TASK_STORE_BESTSOUND_REACTORIGIN_IN_SAVEPOSITION 0" - " TASK_STOP_MOVING 0" - " TASK_FACE_SAVEPOSITION 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT 1.5" - " TASK_FACE_REASONABLE 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_FEAR" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_PROVOKED" -); - -//========================================================= -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_ALERT_REACT_TO_COMBAT_SOUND, - - " Tasks" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_ALERT_FACE_BESTSOUND" - "" - " Interrupts" - ); - - -//========================================================= -// > Alert_Scan -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_ALERT_SCAN, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_WAIT 0.5" - " TASK_TURN_LEFT 180" - " TASK_WAIT 0.5" - " TASK_TURN_LEFT 180" - "" - " Interrupts" - " COND_NEW_ENEMY" -); - -//========================================================= -// > AlertStand -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_ALERT_STAND, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_REASONABLE 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT 20" - " TASK_SUGGEST_STATE STATE:IDLE" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_ENEMY" - " COND_SEE_FEAR" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_PROVOKED" - " COND_SMELL" - " COND_HEAR_COMBAT" // sound flags - " COND_HEAR_WORLD" - " COND_HEAR_PLAYER" - " COND_HEAR_DANGER" - " COND_HEAR_BULLET_IMPACT" - " COND_IDLE_INTERRUPT" - " COND_GIVE_WAY" -); - - - -//========================================================= -// > AlertWAlk -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_ALERT_WALK, - - " Tasks" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_WAIT_PVS 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_ENEMY" - " COND_SEE_FEAR" - " COND_ENEMY_DEAD" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" -); - -//========================================================= -// > InvestigateSound -// -// sends a monster to the location of the -// sound that was just heard to check things out. -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_INVESTIGATE_SOUND, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_STORE_LASTPOSITION 0" -// " TASK_SET_TOLERANCE_DISTANCE 32" - " TASK_GET_PATH_TO_BESTSOUND 0" - " TASK_FACE_IDEAL 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_WAIT 5" - " TASK_GET_PATH_TO_LASTPOSITION 0" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_CLEAR_LASTPOSITION 0" - " TASK_FACE_REASONABLE 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_FEAR" - " COND_SEE_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" -); - -//========================================================= -// > CombatStand -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_COMBAT_STAND, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT_INDEFINITE 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_SEE_ENEMY" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - " COND_IDLE_INTERRUPT" -); - -//========================================================= -// > CombatWAlk -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_COMBAT_WALK, - - " Tasks" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_WAIT_PVS 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" -); - -//========================================================= -// > CombatFace -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_COMBAT_FACE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" -); - -//========================================================= -// COMBAT_SWEEP -// -// Do a small sweep of the area -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_COMBAT_SWEEP, - - " Tasks" - " TASK_TURN_LEFT 45" - " TASK_WAIT 2" - " TASK_TURN_RIGHT 45" - " TASK_WAIT 2" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_HEAR_DANGER" - " COND_HEAR_WORLD" -); - -//========================================================= -// > Standoff -// -// Used in combat when a monster is -// hiding in cover or the enemy has moved out of sight. -// Should we look around in this schedule? -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_STANDOFF, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" // Translated to cover - " TASK_WAIT_FACE_ENEMY 2" - "" - " Interrupts" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - " COND_ENEMY_DEAD" - " COND_NEW_ENEMY" - " COND_HEAR_DANGER" -); - -//========================================================= -// > Arm weapon (draw gun) -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_ARM_WEAPON, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_IDEAL 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_ARM" - "" - " Interrupts" -); - -//========================================================= -// > Disarm weapon (holster gun) -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_DISARM_WEAPON, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_IDEAL 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_DISARM" - "" - " Interrupts" -); - -//========================================================= -// SCHED_HIDE_AND_RELOAD -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_HIDE_AND_RELOAD, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_RELOAD" - " TASK_FIND_COVER_FROM_ENEMY 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_REMEMBER MEMORY:INCOVER" - " TASK_FACE_ENEMY 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_RELOAD" - "" - " Interrupts" - " COND_HEAR_DANGER" -); - -//========================================================= -// > Reload -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_RELOAD, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_RELOAD 0" - "" - " Interrupts" - " COND_HEAR_DANGER" -); - -//========================================================= -// > Melee_Attack1 -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_MELEE_ATTACK1, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_ANNOUNCE_ATTACK 1" // 1 = primary attack - " TASK_MELEE_ATTACK1 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_ENEMY_OCCLUDED" -); - -//========================================================= -// > Melee_Attack2 -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_MELEE_ATTACK2, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_ANNOUNCE_ATTACK 2" // 2 = secondary attack - " TASK_MELEE_ATTACK2 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_ENEMY_OCCLUDED" -); - -//========================================================= -// > SpecialAttack1 -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_SPECIAL_ATTACK1, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_SPECIAL_ATTACK1 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_ENEMY_OCCLUDED" - " COND_NO_PRIMARY_AMMO" - " COND_HEAR_DANGER" -); - -//========================================================= -// > SpecialAttack2 -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_SPECIAL_ATTACK2, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_SPECIAL_ATTACK2 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_ENEMY_OCCLUDED" - " COND_NO_SECONDARY_AMMO" - " COND_HEAR_DANGER" -); - -//========================================================= -// > ChaseEnemy -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_CHASE_ENEMY, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY_FAILED" -// " TASK_SET_TOLERANCE_DISTANCE 24" - " TASK_GET_CHASE_PATH_TO_ENEMY 300" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_ENEMY_UNREACHABLE" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK2" - " COND_TOO_CLOSE_TO_ATTACK" - " COND_TASK_FAILED" - " COND_LOST_ENEMY" - " COND_BETTER_WEAPON_AVAILABLE" - " COND_HEAR_DANGER" -); - -//========================================================= -// > CombatFace -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_TARGET_FACE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_FACE_TARGET 0" - "" - " Interrupts" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" -); - -//========================================================= -// > ChaseEnemy -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_TARGET_CHASE, - - " Tasks" - " TASK_STOP_MOVING 0" -// " TASK_SET_TOLERANCE_DISTANCE 24" - " TASK_GET_PATH_TO_TARGET 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_ENEMY_UNREACHABLE" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK2" - " COND_TOO_CLOSE_TO_ATTACK" - " COND_TASK_FAILED" - " COND_LOST_ENEMY" - " COND_BETTER_WEAPON_AVAILABLE" - " COND_HEAR_DANGER" -); - -//========================================================= -// > ChaseEnemyFailed -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_CHASE_ENEMY_FAILED, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_WAIT 0.2" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_STANDOFF" -// " TASK_SET_TOLERANCE_DISTANCE 24" - " TASK_FIND_COVER_FROM_ENEMY 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_REMEMBER MEMORY:INCOVER" - " TASK_FACE_ENEMY 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" // Translated to cover - " TASK_WAIT 1" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK2" - " COND_HEAR_DANGER" - " COND_BETTER_WEAPON_AVAILABLE" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" -); - -//========================================================= -// > SCHED_BACK_AWAY_FROM_SAVE_POSITION -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_BACK_AWAY_FROM_SAVE_POSITION, - - " Tasks" - " TASK_STOP_MOVING 0" -// " TASK_SET_TOLERANCE_DISTANCE 24" - " TASK_FIND_BACKAWAY_FROM_SAVEPOSITION 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" -); - -//========================================================= -// > BackAwayFromEnemy -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_BACK_AWAY_FROM_ENEMY, - - " Tasks" - // If I can't back away from the enemy try to get behind him - " TASK_STOP_MOVING 0" -// " TASK_SET_TOLERANCE_DISTANCE 24" - " TASK_STORE_ENEMY_POSITION_IN_SAVEPOSITION 0" - " TASK_FIND_BACKAWAY_FROM_SAVEPOSITION 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" -); - -//========================================================= -// > SmallFlinch -// played when heavy damage is taken recently after taking damage -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_SMALL_FLINCH, - - " Tasks" - " TASK_REMEMBER MEMORY:FLINCHED " - " TASK_STOP_MOVING 0" - " TASK_SMALL_FLINCH 0" - "" - " Interrupts" -); - -//========================================================= -// > BigFlinch -// played when heavy damage is taken for the first time in a while -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_BIG_FLINCH, - - " Tasks" - " TASK_REMEMBER MEMORY:FLINCHED " - " TASK_STOP_MOVING 0" - " TASK_BIG_FLINCH 0" - "" - " Interrupts" -); - -//========================================================= -// > Freeze -// -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_NPC_FREEZE, - - " Tasks" - " TASK_FREEZE 0" - - " Interrupts" - " COND_NPC_UNFREEZE" -); - -//========================================================= -// > Die -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_DIE, - - " Tasks" - " TASK_STOP_MOVING 0 " - " TASK_SOUND_DIE 0 " - " TASK_DIE 0 " - "" - " Interrupts" - " COND_NO_CUSTOM_INTERRUPTS" -); - -//========================================================= -// > Die -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_DIE_RAGDOLL, - - " Tasks" - " TASK_STOP_MOVING 0 " - " TASK_SOUND_DIE 0 " - "" - " Interrupts" - " COND_NO_CUSTOM_INTERRUPTS" -); - - -//========================================================= -// > VictoryDance -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_VICTORY_DANCE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_VICTORY_DANCE" - " TASK_WAIT 0" - "" - " Interrupts" -); - -//========================================================= -// > Error -//========================================================= -//AI_DEFINE_SCHEDULE -// Error -// -//Tasks -// TASK_STOP_MOVING 0 -// TASK_WAIT_INDEFINITE 0 -// -//Interrupts - -//========================================================= -// > ScriptedWalk -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_SCRIPTED_WALK, - - " Tasks" - " TASK_PRE_SCRIPT 0" - " TASK_SET_TOLERANCE_DISTANCE 2" - " TASK_PUSH_SCRIPT_ARRIVAL_ACTIVITY 0" - - " TASK_SCRIPT_WALK_TO_TARGET 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_PLANT_ON_SCRIPT 0" - " TASK_FACE_SCRIPT 0" - " TASK_ENABLE_SCRIPT 0" - " TASK_WAIT_FOR_SCRIPT 0" - " TASK_PLAY_SCRIPT 0" - " TASK_PLAY_SCRIPT_POST_IDLE 0" - "" - " Interrupts" - " COND_LIGHT_DAMAGE " - " COND_HEAVY_DAMAGE" -); - -//========================================================= -// > ScriptedRun -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_SCRIPTED_RUN, - - " Tasks" - " TASK_PRE_SCRIPT 0" - " TASK_SET_TOLERANCE_DISTANCE 2" - " TASK_PUSH_SCRIPT_ARRIVAL_ACTIVITY 0" - " TASK_SCRIPT_RUN_TO_TARGET 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_PLANT_ON_SCRIPT 0" - " TASK_FACE_SCRIPT 0" - " TASK_ENABLE_SCRIPT 0" - " TASK_WAIT_FOR_SCRIPT 0" - " TASK_PLAY_SCRIPT 0" - " TASK_PLAY_SCRIPT_POST_IDLE 0" - "" - " Interrupts" - " COND_LIGHT_DAMAGE " - " COND_HEAVY_DAMAGE" -); - -//========================================================= -// > ScriptedMoveCustom -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_SCRIPTED_CUSTOM_MOVE, - - " Tasks" - " TASK_PRE_SCRIPT 0" - " TASK_SET_TOLERANCE_DISTANCE 2" - " TASK_PUSH_SCRIPT_ARRIVAL_ACTIVITY 0" - " TASK_SCRIPT_CUSTOM_MOVE_TO_TARGET 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_PLANT_ON_SCRIPT 0" - " TASK_FACE_SCRIPT 0" - " TASK_ENABLE_SCRIPT 0" - " TASK_WAIT_FOR_SCRIPT 0" - " TASK_PLAY_SCRIPT 0" - " TASK_PLAY_SCRIPT_POST_IDLE 0" - "" - " Interrupts" - " COND_LIGHT_DAMAGE " - " COND_HEAVY_DAMAGE" -); - -//========================================================= -// > ScriptedWait -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_SCRIPTED_WAIT, - - " Tasks" - " TASK_PRE_SCRIPT 0" - " TASK_STOP_MOVING 0" - " TASK_ENABLE_SCRIPT 0" - " TASK_WAIT_FOR_SCRIPT 0" - " TASK_PLAY_SCRIPT 0" - " TASK_PLAY_SCRIPT_POST_IDLE 0" - "" - " Interrupts" - " COND_LIGHT_DAMAGE " - " COND_HEAVY_DAMAGE" -); - -//========================================================= -// > ScriptedFace -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_SCRIPTED_FACE, - - " Tasks" - " TASK_PRE_SCRIPT 0" - " TASK_STOP_MOVING 0" - " TASK_FACE_SCRIPT 0" - " TASK_ENABLE_SCRIPT 0" - " TASK_WAIT_FOR_SCRIPT 0" - " TASK_PLAY_SCRIPT 0" - " TASK_PLAY_SCRIPT_POST_IDLE 0" - "" - " Interrupts" - " COND_LIGHT_DAMAGE " - " COND_HEAVY_DAMAGE" -); - - - -//========================================================= -// > SCENE_FACE_TARGET -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_SCENE_GENERIC, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_SCENE_GENERIC" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_PLAY_SCENE 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_SCENE_GENERIC" - "" - " Interrupts" -); - -//========================================================= -// > Cower -// -// This is what is usually done when attempts -// to escape danger fail. -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_COWER, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_COWER" - " TASK_WAIT_UNTIL_NO_DANGER_SOUND 0" - "" - " Interrupts" -); - -//========================================================= -// > TakeCoverFromOrigin -// -// move away from where you're currently standing. -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_TAKE_COVER_FROM_ORIGIN, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_FAIL_TAKE_COVER" - " TASK_STOP_MOVING 0" -// " TASK_SET_TOLERANCE_DISTANCE 24" - " TASK_FIND_COVER_FROM_ORIGIN 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_REMEMBER MEMORY:INCOVER" - " TASK_TURN_LEFT 179" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" // Translated to cover - "" - " Interrupts" - " COND_NEW_ENEMY" -); - -//========================================================= -// > TakeCoverFromBestSound -// -// hide from the loudest sound source -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_TAKE_COVER_FROM_BEST_SOUND, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_FLEE_FROM_BEST_SOUND" - " TASK_STOP_MOVING 0" - " TASK_STORE_BESTSOUND_REACTORIGIN_IN_SAVEPOSITION 0" - " TASK_FIND_COVER_FROM_BEST_SOUND 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_REMEMBER MEMORY:INCOVER" - " TASK_FACE_SAVEPOSITION 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" // Translated to cover - "" - " Interrupts" - " COND_NEW_ENEMY" -); - - -//========================================================= -// -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_FLEE_FROM_BEST_SOUND, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_COWER" - " TASK_STORE_BESTSOUND_REACTORIGIN_IN_SAVEPOSITION 0" - " TASK_GET_PATH_AWAY_FROM_BEST_SOUND 600" - " TASK_RUN_PATH_FLEE 100" - " TASK_STOP_MOVING 0" - " TASK_FACE_SAVEPOSITION 0" - "" - " Interrupts" - " COND_NEW_ENEMY" -); - - -//========================================================= -// > TakeCoverFromEnemy -// -// Take cover from enemy! -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_TAKE_COVER_FROM_ENEMY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_FAIL_TAKE_COVER" - " TASK_STOP_MOVING 0" - " TASK_WAIT 0.2" -// " TASK_SET_TOLERANCE_DISTANCE 24" - " TASK_FIND_COVER_FROM_ENEMY 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_REMEMBER MEMORY:INCOVER" - " TASK_FACE_ENEMY 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" // Translated to cover - " TASK_WAIT 1" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_HEAR_DANGER" -); - -//========================================================= -// FAIL_TAKE_COVER -// -// Default case. Overridden by subclasses for behavior -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_FAIL_TAKE_COVER, - - " Tasks " - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - "" - " Interrupts" - " COND_NEW_ENEMY" -); - -//========================================================= -// > RunFromEnemy -// -// Run to cover, but don't turn to face enemy and upon -// fail run around randomly -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_RUN_FROM_ENEMY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_RUN_FROM_ENEMY_FALLBACK" - " TASK_STOP_MOVING 0" - " TASK_FIND_COVER_FROM_ENEMY 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" -); - -AI_DEFINE_SCHEDULE -( - SCHED_RUN_FROM_ENEMY_FALLBACK, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_RUN_RANDOM" - " TASK_STOP_MOVING 0" - " TASK_STORE_ENEMY_POSITION_IN_SAVEPOSITION 0" - " TASK_FIND_BACKAWAY_FROM_SAVEPOSITION 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" -); - -AI_DEFINE_SCHEDULE -( - SCHED_RUN_FROM_ENEMY_MOB, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_RUN_RANDOM" - " TASK_STOP_MOVING 0" - " TASK_STORE_ENEMY_POSITION_IN_SAVEPOSITION 0" - " TASK_FIND_BACKAWAY_FROM_SAVEPOSITION 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_HEAR_DANGER" -); - -//========================================================= -// > Fear_Face -// -// Face an enemy that I'm scared of, until I see it. Used -// after I run to cover from a feared enemy -// UNDONE: Add a special ACT_IDLE_FEAR -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_FEAR_FACE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_SEE_ENEMY" -); - -//========================================================= -// > Forced_Go (Used for debug only) -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_FORCED_GO, - - " Tasks" - " TASK_SET_TOLERANCE_DISTANCE 48" - " TASK_SET_ROUTE_SEARCH_TIME 3" // Spend 3 seconds trying to build a path if stuck - " TASK_GET_PATH_TO_LASTPOSITION 0" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" -); - -//========================================================= -// > Forced_Go (Used for debug only) -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_FORCED_GO_RUN, - - " Tasks" - " TASK_SET_TOLERANCE_DISTANCE 48" - " TASK_SET_ROUTE_SEARCH_TIME 3" // Spend 3 seconds trying to build a path if stuck - " TASK_GET_PATH_TO_LASTPOSITION 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" -); - -//========================================================= -// SCHED_MOVE_TO_WEAPON_RANGE -// -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_MOVE_TO_WEAPON_RANGE, - - " Tasks " - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY" - " TASK_GET_PATH_TO_RANGE_ENEMY_LKP_LOS 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_COMBAT_FACE" - "" - " Interrupts " - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_LOST_ENEMY" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK2" - " COND_HEAR_DANGER" -); - -//========================================================= -// ESTABLISH_LINE_OF_FIRE -// -// Go to a location from which I can shoot my enemy -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_ESTABLISH_LINE_OF_FIRE, - - " Tasks " - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ESTABLISH_LINE_OF_FIRE_FALLBACK" - " TASK_GET_PATH_TO_ENEMY_LOS 0" - " TASK_SPEAK_SENTENCE 1" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_COMBAT_FACE" - "" - " Interrupts " - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_LOST_ENEMY" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK2" - " COND_HEAR_DANGER" -); - - -//----------------------------------------------------------------------------- -// Shoot at my enemy in order to destroy the breakable cover object -// that they are hiding behind. This will naturally destroy the cover object. -//----------------------------------------------------------------------------- -AI_DEFINE_SCHEDULE -( - SCHED_SHOOT_ENEMY_COVER, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_WAIT 0.5" - " TASK_RANGE_ATTACK1 0" - "" - " Interrupts" - " COND_ENEMY_DEAD" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_NO_PRIMARY_AMMO" - " COND_HEAR_DANGER" - " COND_WEAPON_BLOCKED_BY_FRIEND" -); - - -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_ESTABLISH_LINE_OF_FIRE_FALLBACK, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_PRE_FAIL_ESTABLISH_LINE_OF_FIRE" - " TASK_GET_CHASE_PATH_TO_ENEMY 300" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_ENEMY_UNREACHABLE" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK2" - " COND_TOO_CLOSE_TO_ATTACK" - " COND_TASK_FAILED" - " COND_LOST_ENEMY" - " COND_BETTER_WEAPON_AVAILABLE" - " COND_HEAR_DANGER" -); - -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_PRE_FAIL_ESTABLISH_LINE_OF_FIRE, - - " Tasks" - " TASK_FACE_ENEMY 0" - " TASK_FACE_REASONABLE 0" - " TASK_IGNORE_OLD_ENEMIES 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_FAIL_ESTABLISH_LINE_OF_FIRE" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK2" -); - -//========================================================= -// FAIL_ESTABLISH_LINE_OF_FIRE -// -// Default case. Overridden by subclasses for behavior - -AI_DEFINE_SCHEDULE -( - SCHED_FAIL_ESTABLISH_LINE_OF_FIRE, - - " Tasks " - "" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - "" - " Interrupts " - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_LOST_ENEMY" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK2" - " COND_HEAR_DANGER" -); - -//========================================================= -// > PATROL_RUN -// -// Run around randomly until we detect an enemy -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_PATROL_RUN, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_COMBAT_FACE" -// " TASK_SET_TOLERANCE_DISTANCE 48" - " TASK_SET_ROUTE_SEARCH_TIME 5" // Spend 5 seconds trying to build a path if stuck - " TASK_GET_PATH_TO_RANDOM_NODE 200" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_CAN_RANGE_ATTACK1 " - " COND_CAN_RANGE_ATTACK2 " - " COND_CAN_MELEE_ATTACK1 " - " COND_CAN_MELEE_ATTACK2" - " COND_GIVE_WAY" - " COND_NEW_ENEMY" - " COND_SEE_ENEMY" - " COND_SEE_FEAR" - " COND_HEAR_COMBAT" - " COND_HEAR_DANGER" - " COND_HEAR_PLAYER" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_SMELL" - " COND_PROVOKED" -); - -//========================================================= -// > IDLE_WANDER -// -// Walk around randomly -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_IDLE_WANDER, - - " Tasks" -// " TASK_SET_TOLERANCE_DISTANCE 48" - " TASK_SET_ROUTE_SEARCH_TIME 5" // Spend 5 seconds trying to build a path if stuck - " TASK_GET_PATH_TO_RANDOM_NODE 200" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_WAIT_PVS 0" - "" - " Interrupts" - " COND_GIVE_WAY" - " COND_HEAR_COMBAT" - " COND_HEAR_DANGER" - " COND_NEW_ENEMY" - " COND_SEE_ENEMY" - " COND_SEE_FEAR" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_IDLE_INTERRUPT" -); - -//========================================================= -// > PATROL_WALK -// -// Walk around randomly until we detect an enemy -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_PATROL_WALK, - - " Tasks" -// " TASK_SET_TOLERANCE_DISTANCE 48" - " TASK_SET_ROUTE_SEARCH_TIME 5" // Spend 5 seconds trying to build a path if stuck - " TASK_GET_PATH_TO_RANDOM_NODE 200" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_CAN_RANGE_ATTACK1 " - " COND_CAN_RANGE_ATTACK2 " - " COND_CAN_MELEE_ATTACK1 " - " COND_CAN_MELEE_ATTACK2" - " COND_GIVE_WAY" - " COND_HEAR_COMBAT" - " COND_HEAR_DANGER" - " COND_HEAR_PLAYER" - " COND_NEW_ENEMY" - " COND_SEE_ENEMY" - " COND_SEE_FEAR" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_SMELL" - " COND_PROVOKED" -); - -//========================================================= -// > COMBAT_PATROL -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_COMBAT_PATROL, - - " Tasks" - " TASK_SET_ROUTE_SEARCH_TIME 5" // Spend 5 seconds trying to build a path if stuck - " TASK_GET_PATH_TO_RANDOM_NODE 200" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_CAN_RANGE_ATTACK1 " - " COND_CAN_RANGE_ATTACK2 " - " COND_CAN_MELEE_ATTACK1 " - " COND_CAN_MELEE_ATTACK2" - " COND_GIVE_WAY" - " COND_HEAR_DANGER" - " COND_NEW_ENEMY" -); - -//========================================================= -// > RUN_RANDOM -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_RUN_RANDOM, - - " Tasks" -// " TASK_SET_TOLERANCE_DISTANCE 48" - " TASK_SET_ROUTE_SEARCH_TIME 1" // Spend 1 seconds trying to build a path if stuck - " TASK_GET_PATH_TO_RANDOM_NODE 500" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" -); - -//========================================================= -// > FALL_TO_GROUND -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_FALL_TO_GROUND, - - " Tasks" - " TASK_FALL_TO_GROUND 0" - "" - " Interrupts" -); - -//========================================================= -// > SCHED_DROPSHIP_DUSTOFF -// After leaving the dropship, dustoff to your specified point -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_DROPSHIP_DUSTOFF, - - " Tasks" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_WAIT_PVS 0" - "" - " Interrupts" -); - -//========================================================= -// Flinch to protect self from incoming physics object -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_FLINCH_PHYSICS, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_FLINCH_PHYSICS" - "" - " Interrupts" -); - -//========================================================= -// > SCHED_MOVE_AWAY -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_MOVE_AWAY_FROM_ENEMY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_MOVE_AWAY_FAIL" - " TASK_FACE_ENEMY 0" - " TASK_MOVE_AWAY_PATH 120" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_MOVE_AWAY_END" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" -); - -//========================================================= -// > SCHED_MOVE_AWAY -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_MOVE_AWAY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_MOVE_AWAY_FAIL" - " TASK_MOVE_AWAY_PATH 120" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_MOVE_AWAY_END" - "" - " Interrupts" -); - -//========================================================= -// > SCHED_MOVE_AWAY_FAIL -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_MOVE_AWAY_FAIL, - - " Tasks" - " TASK_STOP_MOVING 0" - "" - " Interrupts" -); - -//========================================================= -// > SCHED_MOVE_AWAY_END (allows derived class to translate to appropriate behavior) -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_MOVE_AWAY_END, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_REASONABLE 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_ENEMY" - " COND_SEE_FEAR" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_PROVOKED" - " COND_SMELL" - " COND_HEAR_COMBAT" // sound flags - " COND_HEAR_WORLD" - " COND_HEAR_PLAYER" - " COND_HEAR_DANGER" - " COND_HEAR_BULLET_IMPACT" - " COND_IDLE_INTERRUPT" -); - - -//========================================================= -// > SCHED_WAIT_FOR_SPEAK_FINISH -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_WAIT_FOR_SPEAK_FINISH, - - " Tasks" - " TASK_WAIT_FOR_SPEAK_FINISH 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_FEAR" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_SMELL" - " COND_PROVOKED" - " COND_GIVE_WAY" - " COND_HEAR_DANGER" - " COND_HEAR_COMBAT" - " COND_HEAR_BULLET_IMPACT" - -); - -//========================================================= -// > SCHED_DUCK_DODGE -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_DUCK_DODGE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_DUCK_DODGE" - " TASK_DEFER_DODGE 30" - "" - " Interrupts" - "" - ); - -//========================================================= -// > SCHED_INTERACTION_MOVE_TO_PARTNER -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_INTERACTION_MOVE_TO_PARTNER, - - " Tasks" - " TASK_GET_PATH_TO_INTERACTION_PARTNER 0" - " TASK_FACE_TARGET 0" - " TASK_WAIT 1" - "" - " Interrupts" - " COND_NO_CUSTOM_INTERRUPTS" -); - -//========================================================= -// > SCHED_INTERACTION_WAIT_FOR_PARTNER -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_INTERACTION_WAIT_FOR_PARTNER, - - " Tasks" - " TASK_FACE_TARGET 0" - " TASK_WAIT 1" - "" - " Interrupts" - " COND_NO_CUSTOM_INTERRUPTS" -); - -//========================================================= -// > SCHED_SLEEP -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_SLEEP, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_WAIT 0.2" - "" - " Interrupts" - "" - ); - - diff --git a/game/server/ai_default.h b/game/server/ai_default.h deleted file mode 100644 index 431573b3d..000000000 --- a/game/server/ai_default.h +++ /dev/null @@ -1,121 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Default schedules. -// -//=============================================================================// - -#ifndef AI_DEFAULT_H -#define AI_DEFAULT_H -#ifdef _WIN32 -#pragma once -#endif - -//========================================================= -// These are the schedule types -//========================================================= -enum -{ - SCHED_NONE = 0, - SCHED_IDLE_STAND, - SCHED_IDLE_WALK, - SCHED_IDLE_WANDER, - SCHED_WAKE_ANGRY, - SCHED_ALERT_FACE, - SCHED_ALERT_FACE_BESTSOUND, - SCHED_ALERT_REACT_TO_COMBAT_SOUND, - SCHED_ALERT_SCAN, - SCHED_ALERT_STAND, - SCHED_ALERT_WALK, - SCHED_INVESTIGATE_SOUND, - SCHED_COMBAT_FACE, - SCHED_COMBAT_SWEEP, - SCHED_FEAR_FACE, - SCHED_COMBAT_STAND, - SCHED_COMBAT_WALK, - SCHED_CHASE_ENEMY, - SCHED_CHASE_ENEMY_FAILED, - SCHED_VICTORY_DANCE, - SCHED_TARGET_FACE, - SCHED_TARGET_CHASE, - SCHED_SMALL_FLINCH, - SCHED_BIG_FLINCH, - SCHED_BACK_AWAY_FROM_ENEMY, - SCHED_MOVE_AWAY_FROM_ENEMY, - SCHED_BACK_AWAY_FROM_SAVE_POSITION, - SCHED_TAKE_COVER_FROM_ENEMY, - SCHED_TAKE_COVER_FROM_BEST_SOUND, - SCHED_FLEE_FROM_BEST_SOUND, - SCHED_TAKE_COVER_FROM_ORIGIN, - SCHED_FAIL_TAKE_COVER, - SCHED_RUN_FROM_ENEMY, - SCHED_RUN_FROM_ENEMY_FALLBACK, - SCHED_MOVE_TO_WEAPON_RANGE, - SCHED_ESTABLISH_LINE_OF_FIRE, - SCHED_ESTABLISH_LINE_OF_FIRE_FALLBACK, - SCHED_PRE_FAIL_ESTABLISH_LINE_OF_FIRE, - SCHED_FAIL_ESTABLISH_LINE_OF_FIRE, - SCHED_SHOOT_ENEMY_COVER, - SCHED_COWER, // usually a last resort! - SCHED_MELEE_ATTACK1, - SCHED_MELEE_ATTACK2, - SCHED_RANGE_ATTACK1, - SCHED_RANGE_ATTACK2, - SCHED_SPECIAL_ATTACK1, - SCHED_SPECIAL_ATTACK2, - SCHED_STANDOFF, - SCHED_ARM_WEAPON, - SCHED_DISARM_WEAPON, - SCHED_HIDE_AND_RELOAD, - SCHED_RELOAD, - SCHED_AMBUSH, - SCHED_DIE, - SCHED_DIE_RAGDOLL, - SCHED_WAIT_FOR_SCRIPT, - SCHED_AISCRIPT, - SCHED_SCRIPTED_WALK, - SCHED_SCRIPTED_RUN, - SCHED_SCRIPTED_CUSTOM_MOVE, - SCHED_SCRIPTED_WAIT, - SCHED_SCRIPTED_FACE, - SCHED_SCENE_GENERIC, - SCHED_NEW_WEAPON, - SCHED_NEW_WEAPON_CHEAT, - SCHED_SWITCH_TO_PENDING_WEAPON, - SCHED_GET_HEALTHKIT, - SCHED_WAIT_FOR_SPEAK_FINISH, - - SCHED_MOVE_AWAY, - SCHED_MOVE_AWAY_FAIL, - SCHED_MOVE_AWAY_END, - SCHED_FORCED_GO, - SCHED_FORCED_GO_RUN, - SCHED_NPC_FREEZE, - SCHED_PATROL_WALK, - SCHED_COMBAT_PATROL, - SCHED_PATROL_RUN, - SCHED_RUN_RANDOM, - SCHED_FALL_TO_GROUND, - SCHED_DROPSHIP_DUSTOFF, - - SCHED_FLINCH_PHYSICS, - - SCHED_FAIL, - SCHED_FAIL_NOSTOP, - - SCHED_RUN_FROM_ENEMY_MOB, - - SCHED_DUCK_DODGE, - - SCHED_INTERACTION_MOVE_TO_PARTNER, - SCHED_INTERACTION_WAIT_FOR_PARTNER, - - SCHED_SLEEP, - - // ====================================== - // IMPORTANT: This must be the last enum - // ====================================== - LAST_SHARED_SCHEDULE - -}; - -#endif // AI_DEFAULT_H diff --git a/game/server/ai_dynamiclink.cpp b/game/server/ai_dynamiclink.cpp deleted file mode 100644 index c318bdb10..000000000 --- a/game/server/ai_dynamiclink.cpp +++ /dev/null @@ -1,730 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: A link that can be turned on and off. Unlike normal links -// dyanimc links must be entities so they can receive messages. -// They update the state of the actual links. Allows us to save -// a lot of memory by not making all links into entities -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "collisionutils.h" -#include "ai_dynamiclink.h" -#include "ai_node.h" -#include "ai_link.h" -#include "ai_network.h" -#include "ai_networkmanager.h" -#include "saverestore_utlvector.h" -#include "editor_sendcommand.h" -#include "bitstring.h" -#include "tier0/vprof.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- - -LINK_ENTITY_TO_CLASS(info_node_link_controller, CAI_DynamicLinkController); - -BEGIN_DATADESC( CAI_DynamicLinkController ) - - DEFINE_KEYFIELD( m_nLinkState, FIELD_INTEGER, "initialstate" ), - DEFINE_KEYFIELD( m_strAllowUse, FIELD_STRING, "AllowUse" ), - DEFINE_KEYFIELD( m_bInvertAllow, FIELD_BOOLEAN, "InvertAllow" ), - DEFINE_KEYFIELD( m_bUseAirLinkRadius, FIELD_BOOLEAN, "useairlinkradius" ), - // m_ControlledLinks (rebuilt) - - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - - DEFINE_INPUTFUNC( FIELD_STRING, "SetAllowed", InputSetAllowed ), - DEFINE_INPUTFUNC( FIELD_BOOLEAN, "SetInvert", InputSetInvert ), - -END_DATADESC() - -void CAI_DynamicLinkController::GenerateLinksFromVolume() -{ - Assert( m_ControlledLinks.Count() == 0 ); - - int nNodes = g_pBigAINet->NumNodes(); - CAI_Node **ppNodes = g_pBigAINet->AccessNodes(); - - float MinDistCareSq = 0; - if (m_bUseAirLinkRadius) - { - MinDistCareSq = Square(MAX_AIR_NODE_LINK_DIST + 0.1); - } - else - { - MinDistCareSq = Square(MAX_NODE_LINK_DIST + 0.1); - } - - const Vector &origin = WorldSpaceCenter(); - Vector vAbsMins, vAbsMaxs; - CollisionProp()->WorldSpaceAABB( &vAbsMins, &vAbsMaxs ); - vAbsMins -= Vector( 1, 1, 1 ); - vAbsMaxs += Vector( 1, 1, 1 ); - - for ( int i = 0; i < nNodes; i++ ) - { - CAI_Node *pNode = ppNodes[i]; - const Vector &nodeOrigin = pNode->GetOrigin(); - if ( origin.DistToSqr(nodeOrigin) < MinDistCareSq ) - { - int nLinks = pNode->NumLinks(); - for ( int j = 0; j < nLinks; j++ ) - { - CAI_Link *pLink = pNode->GetLinkByIndex( j ); - int iLinkDest = pLink->DestNodeID( i ); - if ( iLinkDest > i ) - { - const Vector &originOther = ppNodes[iLinkDest]->GetOrigin(); - if ( origin.DistToSqr(originOther) < MinDistCareSq ) - { - if ( IsBoxIntersectingRay( vAbsMins, vAbsMaxs, nodeOrigin, originOther - nodeOrigin ) ) - { - Assert( IsBoxIntersectingRay( vAbsMins, vAbsMaxs, originOther, nodeOrigin - originOther ) ); - - CAI_DynamicLink *pLink = (CAI_DynamicLink *)CreateEntityByName( "info_node_link" ); - pLink->m_nSrcID = i; - pLink->m_nDestID = iLinkDest; - pLink->m_nSrcEditID = g_pAINetworkManager->GetEditOps()->GetWCIdFromNodeId( pLink->m_nSrcID ); - pLink->m_nDestEditID = g_pAINetworkManager->GetEditOps()->GetWCIdFromNodeId( pLink->m_nDestID ); - pLink->m_nLinkState = m_nLinkState; - pLink->m_strAllowUse = m_strAllowUse; - pLink->m_bInvertAllow = m_bInvertAllow; - pLink->m_bFixedUpIds = true; - pLink->m_bNotSaved = true; - - pLink->Spawn(); - m_ControlledLinks.AddToTail( pLink ); - } - } - } - } - } - } -} - -void CAI_DynamicLinkController::InputTurnOn( inputdata_t &inputdata ) -{ - for ( int i = 0; i < m_ControlledLinks.Count(); i++ ) - { - if ( m_ControlledLinks[i] == NULL ) - { - m_ControlledLinks.FastRemove(i); - if ( i >= m_ControlledLinks.Count() ) - break; - } - m_ControlledLinks[i]->InputTurnOn( inputdata ); - } - - m_nLinkState = LINK_ON; -} - -void CAI_DynamicLinkController::InputTurnOff( inputdata_t &inputdata ) -{ - for ( int i = 0; i < m_ControlledLinks.Count(); i++ ) - { - if ( m_ControlledLinks[i] == NULL ) - { - m_ControlledLinks.FastRemove(i); - if ( i >= m_ControlledLinks.Count() ) - break; - } - m_ControlledLinks[i]->InputTurnOff( inputdata ); - } - - m_nLinkState = LINK_OFF; -} - -void CAI_DynamicLinkController::InputSetAllowed( inputdata_t &inputdata ) -{ - m_strAllowUse = inputdata.value.StringID(); - for ( int i = 0; i < m_ControlledLinks.Count(); i++ ) - { - if ( m_ControlledLinks[i] == NULL ) - { - m_ControlledLinks.FastRemove(i); - if ( i >= m_ControlledLinks.Count() ) - break; - } - m_ControlledLinks[i]->m_strAllowUse = m_strAllowUse; - } -} - -void CAI_DynamicLinkController::InputSetInvert( inputdata_t &inputdata ) -{ - m_bInvertAllow = inputdata.value.Bool(); - for ( int i = 0; i < m_ControlledLinks.Count(); i++ ) - { - if ( m_ControlledLinks[i] == NULL ) - { - m_ControlledLinks.FastRemove(i); - if ( i >= m_ControlledLinks.Count() ) - break; - } - m_ControlledLinks[i]->m_bInvertAllow = m_bInvertAllow; - } -} - -//----------------------------------------------------------------------------- - -LINK_ENTITY_TO_CLASS(info_node_link, CAI_DynamicLink); - -BEGIN_DATADESC( CAI_DynamicLink ) - -// m_pNextDynamicLink -DEFINE_KEYFIELD( m_nLinkState, FIELD_INTEGER, "initialstate" ), -DEFINE_KEYFIELD( m_nSrcEditID, FIELD_INTEGER, "startnode" ), -DEFINE_KEYFIELD( m_nDestEditID, FIELD_INTEGER, "endnode" ), -DEFINE_KEYFIELD( m_nLinkType, FIELD_INTEGER, "linktype" ), -DEFINE_FIELD( m_bInvertAllow, FIELD_BOOLEAN ), -// m_nSrcID (rebuilt) -// m_nDestID (rebuilt) -DEFINE_KEYFIELD( m_strAllowUse, FIELD_STRING, "AllowUse" ), -// m_bFixedUpIds (part of rebuild) -// m_bNotSaved (rebuilt) - -DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), -DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Init static variables -//----------------------------------------------------------------------------- -CAI_DynamicLink *CAI_DynamicLink::m_pAllDynamicLinks = NULL; -bool CAI_DynamicLink::gm_bInitialized; - - -//------------------------------------------------------------------------------ - -void CAI_DynamicLink::GenerateControllerLinks() -{ - CAI_DynamicLinkController *pController = NULL; - while ( ( pController = gEntList.NextEntByClass( pController ) ) != NULL ) - { - pController->GenerateLinksFromVolume(); - } - -} - -//------------------------------------------------------------------------------ -// Purpose : Initializes src and dest IDs for all dynamic links -// -// Input : -// Output : -//------------------------------------------------------------------------------ -void CAI_DynamicLink::InitDynamicLinks(void) -{ - if (!g_pAINetworkManager->GetEditOps()->m_pNodeIndexTable) - { - Warning("ERROR: Trying initialize links with no WC ID table!\n"); - return; - } - - if ( gm_bInitialized ) - return; - - gm_bInitialized = true; - - bool bUpdateZones = false; - - GenerateControllerLinks(); - - CAI_DynamicLink* pDynamicLink = CAI_DynamicLink::m_pAllDynamicLinks; - - while (pDynamicLink) - { - // ------------------------------------------------------------- - // First convert this links WC IDs to engine IDs - // ------------------------------------------------------------- - if ( !pDynamicLink->m_bFixedUpIds ) - { - int nSrcID = g_pAINetworkManager->GetEditOps()->GetNodeIdFromWCId( pDynamicLink->m_nSrcEditID ); - if (nSrcID == -1) - { - DevMsg( "ERROR: Dynamic link source WC node %d not found\n", pDynamicLink->m_nSrcEditID ); - nSrcID = NO_NODE; - } - - int nDestID = g_pAINetworkManager->GetEditOps()->GetNodeIdFromWCId( pDynamicLink->m_nDestEditID ); - if (nDestID == -1) - { - DevMsg( "ERROR: Dynamic link dest WC node %d not found\n", pDynamicLink->m_nDestEditID ); - nDestID = NO_NODE; - } - - pDynamicLink->m_nSrcID = nSrcID; - pDynamicLink->m_nDestID = nDestID; - pDynamicLink->m_bFixedUpIds = true; - } - - if ( pDynamicLink->m_nSrcID != NO_NODE && pDynamicLink->m_nDestID != NO_NODE ) - { - if ( ( pDynamicLink->GetSpawnFlags() & bits_HULL_BITS_MASK ) != 0 ) - { - CAI_Link *pLink = pDynamicLink->FindLink(); - if ( !pLink ) - { - CAI_Node *pNode1, *pNode2; - - pNode1 = g_pBigAINet->GetNode( pDynamicLink->m_nSrcID ); - pNode2 = g_pBigAINet->GetNode( pDynamicLink->m_nDestID ); - - if ( pNode1 && pNode2 ) - { - pLink = g_pBigAINet->CreateLink( pDynamicLink->m_nSrcID, pDynamicLink->m_nDestID ); - if ( !pLink ) - DevMsg( "Failed to create dynamic link (%d <--> %d)\n", pDynamicLink->m_nSrcEditID, pDynamicLink->m_nDestEditID ); - } - - } - - if ( pLink ) - { - bUpdateZones = true; - - int hullBits = ( pDynamicLink->GetSpawnFlags() & bits_HULL_BITS_MASK ); - for ( int i = 0; i < NUM_HULLS; i++ ) - { - if ( hullBits & ( 1 << i ) ) - { - pLink->m_iAcceptedMoveTypes[i] = pDynamicLink->m_nLinkType; - } - } - } - } - - // Now set the link's state - pDynamicLink->SetLinkState(); - - // Go on to the next dynamic link - pDynamicLink = pDynamicLink->m_pNextDynamicLink; - } - else - { - CAI_DynamicLink *pBadDynamicLink = pDynamicLink; - - // Go on to the next dynamic link - pDynamicLink = pDynamicLink->m_pNextDynamicLink; - - UTIL_RemoveImmediate( pBadDynamicLink ); - } - - } - - if ( bUpdateZones ) - { - g_AINetworkBuilder.InitZones( g_pBigAINet ); - } -} - - -//------------------------------------------------------------------------------ -// Purpose : Goes through each dynamic link and updates the state of all -// AINetwork links -// Input : -// Output : -//------------------------------------------------------------------------------ -void CAI_DynamicLink::ResetDynamicLinks(void) -{ - CAI_DynamicLink* pDynamicLink = CAI_DynamicLink::m_pAllDynamicLinks; - - while (pDynamicLink) - { - // Now set the link's state - pDynamicLink->SetLinkState(); - - // Go on to the next dynamic link - pDynamicLink = pDynamicLink->m_pNextDynamicLink; - } -} - - -//------------------------------------------------------------------------------ -// Purpose : Goes through each dynamic link and checks to make sure that -// there is still a corresponding node link, if not removes it -// Input : -// Output : -//------------------------------------------------------------------------------ -void CAI_DynamicLink::PurgeDynamicLinks(void) -{ - CAI_DynamicLink* pDynamicLink = CAI_DynamicLink::m_pAllDynamicLinks; - - while (pDynamicLink) - { - if (!pDynamicLink->IsLinkValid()) - { - // Didn't find the link, so remove it -#ifdef _WIN32 - int nWCSrcID = g_pAINetworkManager->GetEditOps()->m_pNodeIndexTable[pDynamicLink->m_nSrcID]; - int nWCDstID = g_pAINetworkManager->GetEditOps()->m_pNodeIndexTable[pDynamicLink->m_nDestID]; - int status = Editor_DeleteNodeLink(nWCSrcID, nWCDstID, false); - if (status == Editor_BadCommand) - { - DevMsg( "Worldcraft failed in PurgeDynamicLinks...\n" ); - } -#endif - // Safe to remove it here as this happens only after I leave this function - UTIL_Remove(pDynamicLink); - } - - // Go on to the next dynamic link - pDynamicLink = pDynamicLink->m_pNextDynamicLink; - } -} - -//------------------------------------------------------------------------------ -// Purpose : Returns false if the dynamic link doesn't have a corresponding -// node link -// Input : -// Output : -//------------------------------------------------------------------------------ -bool CAI_DynamicLink::IsLinkValid( void ) -{ - CAI_Node *pNode = g_pBigAINet->GetNode(m_nSrcID); - - return ( pNode->GetLink( m_nDestID ) != NULL ); -} - - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CAI_DynamicLink::InputTurnOn( inputdata_t &inputdata ) -{ - if (m_nLinkState == LINK_OFF) - { - m_nLinkState = LINK_ON; - CAI_DynamicLink::SetLinkState(); - } -} - - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CAI_DynamicLink::InputTurnOff( inputdata_t &inputdata ) -{ - if (m_nLinkState == LINK_ON) - { - m_nLinkState = LINK_OFF; - CAI_DynamicLink::SetLinkState(); - } -} - - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -CAI_Link *CAI_DynamicLink::FindLink() -{ - CAI_Node * pSrcNode = g_pBigAINet->GetNode(m_nSrcID, false); - if ( pSrcNode ) - { - int numLinks = pSrcNode->NumLinks(); - for (int i=0;iGetLinkByIndex(i); - - if (((pLink->m_iSrcID == m_nSrcID )&& - (pLink->m_iDestID == m_nDestID)) || - - ((pLink->m_iSrcID == m_nDestID)&& - (pLink->m_iDestID == m_nSrcID )) ) - { - return pLink; - } - } - } - return NULL; -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -int CAI_DynamicLink::ObjectCaps() -{ - int caps = BaseClass::ObjectCaps(); - - if ( m_bNotSaved ) - caps |= FCAP_DONT_SAVE; - - return caps; -} - -//------------------------------------------------------------------------------ -// Purpose : Updates network link state if dynamic link state has changed -// Input : -// Output : -//------------------------------------------------------------------------------ -void CAI_DynamicLink::SetLinkState(void) -{ - if ( !gm_bInitialized ) - { - // Safe to quietly return. Consistency will be enforced when InitDynamicLinks() is called - return; - } - - if (m_nSrcID == NO_NODE || m_nDestID == NO_NODE) - { - Vector pos = GetAbsOrigin(); - DevWarning("ERROR: Dynamic link at %f %f %f pointing to invalid node ID!!\n", pos.x, pos.y, pos.z); - return; - } - - // ------------------------------------------------------------------ - // Now update the node links... - // Nodes share links so we only have to find the node from the src - // For now just using one big AINetwork so find src node on that network - // ------------------------------------------------------------------ - CAI_Node * pSrcNode = g_pBigAINet->GetNode(m_nSrcID, false); - if ( pSrcNode ) - { - CAI_Link* pLink = FindLink(); - if ( pLink ) - { - pLink->m_pDynamicLink = this; - if (m_nLinkState == LINK_OFF) - { - pLink->m_LinkInfo |= bits_LINK_OFF; - } - else - { - pLink->m_LinkInfo &= ~bits_LINK_OFF; - } - } - else - { - DevMsg("Dynamic Link Error: (%s) unable to form between nodes %d and %d\n", GetDebugName(), m_nSrcID, m_nDestID ); - } - } - -} - -//------------------------------------------------------------------------------ -// Purpose : Given two node ID's return the related dynamic link if any or NULL -// -// Input : -// Output : -//------------------------------------------------------------------------------ -CAI_DynamicLink* CAI_DynamicLink::GetDynamicLink(int nSrcID, int nDstID) -{ - CAI_DynamicLink* pDynamicLink = CAI_DynamicLink::m_pAllDynamicLinks; - - while (pDynamicLink) - { - if ((nSrcID == pDynamicLink->m_nSrcID && nDstID == pDynamicLink->m_nDestID) || - (nSrcID == pDynamicLink->m_nDestID && nDstID == pDynamicLink->m_nSrcID ) ) - { - return pDynamicLink; - } - - // Go on to the next dynamic link - pDynamicLink = pDynamicLink->m_pNextDynamicLink; - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Constructor -// Input : -// Output : -//----------------------------------------------------------------------------- -CAI_DynamicLink::CAI_DynamicLink(void) -{ - m_bFixedUpIds = false; - m_bNotSaved = false; - m_nSrcID = NO_NODE; - m_nDestID = NO_NODE; - m_nLinkState = LINK_OFF; - m_nLinkType = bits_CAP_MOVE_GROUND; - m_bInvertAllow = false; - - // ------------------------------------- - // Add to linked list of dynamic links - // ------------------------------------- - m_pNextDynamicLink = CAI_DynamicLink::m_pAllDynamicLinks; - CAI_DynamicLink::m_pAllDynamicLinks = this; -}; - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -CAI_DynamicLink::~CAI_DynamicLink(void) { - - // ---------------------------------------------- - // Remove from linked list of all dynamic links - // ---------------------------------------------- - CAI_DynamicLink* pDynamicLink = CAI_DynamicLink::m_pAllDynamicLinks; - if (pDynamicLink == this) - { - m_pAllDynamicLinks = pDynamicLink->m_pNextDynamicLink; - } - else - { - while (pDynamicLink) - { - if (pDynamicLink->m_pNextDynamicLink == this) - { - pDynamicLink->m_pNextDynamicLink = pDynamicLink->m_pNextDynamicLink->m_pNextDynamicLink; - break; - } - pDynamicLink = pDynamicLink->m_pNextDynamicLink; - } - } -} - -LINK_ENTITY_TO_CLASS(info_radial_link_controller, CAI_RadialLinkController); - -BEGIN_DATADESC( CAI_RadialLinkController ) -DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "radius" ), -DEFINE_FIELD( m_vecAtRestOrigin, FIELD_POSITION_VECTOR ), -DEFINE_FIELD( m_bAtRest, FIELD_BOOLEAN ), - -DEFINE_THINKFUNC( PollMotionThink ), -END_DATADESC() - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CAI_RadialLinkController::Spawn() -{ - SetSolid( SOLID_NONE ); - AddEffects( EF_NODRAW ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CAI_RadialLinkController::Activate() -{ - BaseClass::Activate(); - - m_bAtRest = false; - m_vecAtRestOrigin = vec3_invalid; - - // Force re-evaluation - SetThink( &CAI_RadialLinkController::PollMotionThink ); - - // Spread think times out. - SetNextThink( gpGlobals->curtime + random->RandomFloat( 0.0f, 1.0f) ); - - if( GetParent() != NULL ) - { - float flDist = GetAbsOrigin().DistTo( GetParent()->GetAbsOrigin() ); - - if( flDist > 200.0f ) - { - // Warn at the console if a link controller is far away from its parent. This - // most likely means that a level designer has copied an entity without researching its hierarchy. - DevMsg("RadialLinkController (%s) is far from its parent!\n", GetDebugName() ); - } - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CAI_RadialLinkController::PollMotionThink() -{ - SetNextThink( gpGlobals->curtime + 0.5f ); - - CBaseEntity *pParent = GetParent(); - - if( pParent ) - { - if( pParent->VPhysicsGetObject()->IsAsleep() ) - { - if( !m_bAtRest ) - { - m_vecAtRestOrigin = GetAbsOrigin(); - ModifyNodeLinks( true ); - m_bAtRest = true; - //Msg("At Rest!\n"); - } - } - else - { - if( m_bAtRest ) - { - float flDist; - - flDist = GetAbsOrigin().DistTo(m_vecAtRestOrigin); - - if( flDist < 18.0f ) - { - // Ignore movement If moved less than 18 inches from the place where we came to rest. - //Msg("Reject.\n"); - return; - } - } - - //Msg("Polling!\n"); - - if( m_vecAtRestOrigin != vec3_invalid ) - { - ModifyNodeLinks( false ); - m_bAtRest = false; - m_vecAtRestOrigin = vec3_invalid; - } - } - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -ConVar ai_radial_max_link_dist( "ai_radial_max_link_dist", "512" ); -void CAI_RadialLinkController::ModifyNodeLinks( bool bMakeStale ) -{ - int nNodes = g_pBigAINet->NumNodes(); - CAI_Node **ppNodes = g_pBigAINet->AccessNodes(); - - VPROF_BUDGET("ModifyLinks", "ModifyLinks"); - - const float MinDistCareSq = Square( ai_radial_max_link_dist.GetFloat() + 0.1 ); - - for ( int i = 0; i < nNodes; i++ ) - { - CAI_Node *pNode = ppNodes[i]; - const Vector &nodeOrigin = pNode->GetOrigin(); - if ( m_vecAtRestOrigin.DistToSqr(nodeOrigin) < MinDistCareSq ) - { - int nLinks = pNode->NumLinks(); - for ( int j = 0; j < nLinks; j++ ) - { - CAI_Link *pLink = pNode->GetLinkByIndex( j ); - int iLinkDest = pLink->DestNodeID( i ); - - if ( iLinkDest > i ) - { - bool bQualify = true; - - if( ( (pLink->m_iAcceptedMoveTypes[HULL_HUMAN]||pLink->m_iAcceptedMoveTypes[HULL_WIDE_HUMAN]) & bits_CAP_MOVE_GROUND) == 0 ) - { - // Micro-optimization: Ignore any connection that's not a walking connection for humans.(sjb) - bQualify = false; - } - - const Vector &originOther = ppNodes[iLinkDest]->GetOrigin(); - if ( bQualify && m_vecAtRestOrigin.DistToSqr(originOther) < MinDistCareSq ) - { - if ( IsRayIntersectingSphere(nodeOrigin, originOther - nodeOrigin, m_vecAtRestOrigin, m_flRadius) ) - { - if( bMakeStale ) - { - pLink->m_LinkInfo |= bits_LINK_STALE_SUGGESTED; - pLink->m_timeStaleExpires = FLT_MAX; - } - else - { - pLink->m_LinkInfo &= ~bits_LINK_STALE_SUGGESTED; - } - } - } - } - } - } - } -} diff --git a/game/server/ai_dynamiclink.h b/game/server/ai_dynamiclink.h deleted file mode 100644 index 470ae2200..000000000 --- a/game/server/ai_dynamiclink.h +++ /dev/null @@ -1,125 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: A link that can be turned on and off. Unlike normal links -// dyanimc links must be entities so they and receive messages. -// They update the state of the actual links. Allows us to save -// a lot of memory by not making all links into entities -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_DYNAMICLINK_H -#define AI_DYNAMICLINK_H -#pragma once - -enum DynamicLinkState_t -{ - LINK_OFF = 0, - LINK_ON = 1, -}; - -class CAI_Link; - -//============================================================================= -// >> CAI_DynanicLink -//============================================================================= -class CAI_DynamicLink : public CServerOnlyEntity -{ - DECLARE_CLASS( CAI_DynamicLink, CServerOnlyEntity ); -public: - static void InitDynamicLinks(void); - static void ResetDynamicLinks(void); - static void PurgeDynamicLinks(void); - static void GenerateControllerLinks(); - - static bool gm_bInitialized; - - static CAI_DynamicLink* GetDynamicLink(int nSrcID, int nDstID); - - static CAI_DynamicLink* m_pAllDynamicLinks; // A linked list of all dynamic link - CAI_DynamicLink* m_pNextDynamicLink; // The next dynamic link in the list of dynamic links - - int m_nSrcEditID; // the node that 'owns' this link - int m_nDestEditID; // the node on the other end of the link. - - int m_nSrcID; // the node that 'owns' this link - int m_nDestID; // the node on the other end of the link. - DynamicLinkState_t m_nLinkState; // - string_t m_strAllowUse; // Only this entity name or classname may use the link - bool m_bInvertAllow; // Instead of only allowing the m_strAllowUse entity, exclude only it - - bool m_bFixedUpIds; - bool m_bNotSaved; - int m_nLinkType; - - void SetLinkState( void ); - bool IsLinkValid( void ); - - CAI_Link * FindLink(); - - int ObjectCaps(); - - // ---------------- - // Inputs - // ---------------- - void InputTurnOn( inputdata_t &inputdata ); - void InputTurnOff( inputdata_t &inputdata ); - DECLARE_DATADESC(); - - CAI_DynamicLink(); - ~CAI_DynamicLink(); -}; - -//============================================================================= -// >> CAI_DynanicLinkVolume -//============================================================================= -class CAI_DynamicLinkController : public CServerOnlyEntity -{ - DECLARE_CLASS( CAI_DynamicLinkController, CServerOnlyEntity ); -public: - void GenerateLinksFromVolume(); - - // ---------------- - // Inputs - // ---------------- - void InputTurnOn( inputdata_t &inputdata ); - void InputTurnOff( inputdata_t &inputdata ); - void InputSetAllowed( inputdata_t &inputdata ); - void InputSetInvert( inputdata_t &inputdata ); - - CUtlVector< CHandle > m_ControlledLinks; - DynamicLinkState_t m_nLinkState; - string_t m_strAllowUse; // Only this entity name or classname may use the link - bool m_bInvertAllow; // Instead of only allowing the m_strAllowUse entity, exclude only it - bool m_bUseAirLinkRadius; - - DECLARE_DATADESC(); -}; - -//============================================================================= -//============================================================================= -class CAI_RadialLinkController : public CBaseEntity -{ - DECLARE_CLASS( CAI_RadialLinkController, CBaseEntity ); - -public: - void Spawn(); - void Activate(); - void PollMotionThink(); - void ModifyNodeLinks( bool bMakeStale ); - -public: - float m_flRadius; - Vector m_vecAtRestOrigin; - bool m_bAtRest; - - DECLARE_DATADESC(); -}; - -#endif // AI_DYNAMICLINK_H diff --git a/game/server/ai_event.cpp b/game/server/ai_event.cpp deleted file mode 100644 index 1b2ed58e5..000000000 --- a/game/server/ai_event.cpp +++ /dev/null @@ -1,50 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Events that are available to all NPCs. -// -//=============================================================================// - -#include "cbase.h" -#include "ai_basenpc.h" -#include "eventlist.h" -#include "stringregistry.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//============================================================================= -// Init static variables -//============================================================================= -CStringRegistry* CAI_BaseNPC::m_pEventSR = NULL; -int CAI_BaseNPC::m_iNumEvents = 0; - -//----------------------------------------------------------------------------- -// Purpose: Add an activity to the activity string registry and increment -// the acitivty counter -//----------------------------------------------------------------------------- -void CAI_BaseNPC::AddEventToSR(const char *eventName, int eventID) -{ - MEM_ALLOC_CREDIT(); - Assert( m_pEventSR ); - - m_pEventSR->AddString( eventName, eventID ); - m_iNumEvents++; -} - -//----------------------------------------------------------------------------- -// Purpose: Given and activity ID, return the activity name -//----------------------------------------------------------------------------- -const char *CAI_BaseNPC::GetEventName(int eventID) -{ - const char *name = m_pEventSR->GetStringText( eventID ); - return name; -} - -//----------------------------------------------------------------------------- -// Purpose: Given and activity name, return the activity ID -//----------------------------------------------------------------------------- -int CAI_BaseNPC::GetEventID(const char* eventName) -{ - return m_pEventSR->GetStringID( eventName ); -} - diff --git a/game/server/ai_eventresponse.cpp b/game/server/ai_eventresponse.cpp deleted file mode 100644 index 99262aefa..000000000 --- a/game/server/ai_eventresponse.cpp +++ /dev/null @@ -1,215 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: AI system that makes NPCs verbally respond to game events -// -//============================================================================= - -#include "cbase.h" -#include "ai_eventresponse.h" -#include "ai_basenpc.h" - -ConVar ai_debug_eventresponses( "ai_debug_eventresponses", "0", FCVAR_NONE, "Set to 1 to see all NPC response events trigger, and which NPCs choose to respond to them." ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CNPCEventResponseSystem g_NPCEventResponseSystem( "CNPCEventResponseSystem" ); - -CNPCEventResponseSystem *NPCEventResponse() -{ - return &g_NPCEventResponseSystem; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPCEventResponseSystem::LevelInitPreEntity( void ) -{ - m_ActiveEvents.Purge(); - m_flNextEventPoll = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPCEventResponseSystem::TriggerEvent( const char *pResponse, bool bForce, bool bCancelScript ) -{ - m_flNextEventPoll = gpGlobals->curtime; - - // Find the event by name - int iIndex = m_ActiveEvents.Find( pResponse ); - if ( iIndex == m_ActiveEvents.InvalidIndex() ) - { - storedevent_t newEvent; - newEvent.flEventTime = gpGlobals->curtime; - newEvent.flNextResponseTime = 0; - newEvent.bForce = bForce; - newEvent.bCancelScript = bCancelScript; - newEvent.bPreventExpiration = false; - m_ActiveEvents.Insert( pResponse, newEvent ); - - if ( ai_debug_eventresponses.GetBool() ) - { - Msg( "NPCEVENTRESPONSE: (%.2f) Trigger fired for event named: %s\n", gpGlobals->curtime, pResponse ); - } - } - else - { - // Update the trigger time - m_ActiveEvents[iIndex].flEventTime = gpGlobals->curtime; - m_ActiveEvents[iIndex].bForce = bForce; - m_ActiveEvents[iIndex].bCancelScript = bCancelScript; - - if ( ai_debug_eventresponses.GetBool() ) - { - Msg( "NPCEVENTRESPONSE: (%.2f) Trigger resetting already-active event firing named: %s\n", gpGlobals->curtime, pResponse ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPCEventResponseSystem::FrameUpdatePreEntityThink() -{ - if ( !m_ActiveEvents.Count() || !AI_IsSinglePlayer() || !UTIL_GetLocalPlayer() ) - return; - - if ( m_flNextEventPoll > gpGlobals->curtime ) - return; - m_flNextEventPoll = gpGlobals->curtime + 0.2; - - // Move through all events, removing expired ones and finding NPCs for active ones. - for ( int i = m_ActiveEvents.First(); i != m_ActiveEvents.InvalidIndex(); ) - { - float flTime = m_ActiveEvents[i].flEventTime; - const char *pResponse = m_ActiveEvents.GetElementName(i); - - // Save off the next index so we can safely remove this one - int iNext = m_ActiveEvents.Next(i); - - // Should it have expired by now? - if ( !m_ActiveEvents[i].bPreventExpiration && (flTime + NPCEVENTRESPONSE_GIVEUP_TIME) < gpGlobals->curtime ) - { - if ( ai_debug_eventresponses.GetBool() ) - { - Msg( "NPCEVENTRESPONSE: (%.2f) Removing expired event named: %s\n", gpGlobals->curtime, pResponse ); - } - - m_ActiveEvents.RemoveAt(i); - } - else if ( m_ActiveEvents[i].flNextResponseTime < gpGlobals->curtime ) - { - // If we've fired once, and our current event should expire now, then expire. - if ( m_ActiveEvents[i].bPreventExpiration && (flTime + NPCEVENTRESPONSE_GIVEUP_TIME) < gpGlobals->curtime ) - { - if ( ai_debug_eventresponses.GetBool() ) - { - Msg( "NPCEVENTRESPONSE: (%.2f) Removing expired fired event named: %s\n", gpGlobals->curtime, pResponse ); - } - - m_ActiveEvents.RemoveAt(i); - } - else - { - float flNearestDist = NPCEVENTRESPONSE_DISTANCE_SQR; - CAI_BaseNPC *pNearestNPC = NULL; - Vector vecPlayerCenter = UTIL_GetLocalPlayer()->WorldSpaceCenter(); - - // Try and find the nearest NPC to the player - CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); - for ( int j = 0; j < g_AI_Manager.NumAIs(); j++ ) - { - if ( ppAIs[j]->CanRespondToEvent( pResponse )) - { - float flDistToPlayer = ( vecPlayerCenter - ppAIs[j]->WorldSpaceCenter()).LengthSqr(); - if ( flDistToPlayer < flNearestDist ) - { - flNearestDist = flDistToPlayer; - pNearestNPC = ppAIs[j]; - } - } - } - - // Found one? - if ( pNearestNPC ) - { - if ( pNearestNPC->RespondedTo( pResponse, m_ActiveEvents[i].bForce, m_ActiveEvents[i].bCancelScript ) ) - { - // Don't remove the response yet. Leave it around until the refire time has expired. - // This stops repeated firings of the same concept from spamming the NPCs. - m_ActiveEvents[i].bPreventExpiration = true; - m_ActiveEvents[i].flNextResponseTime = gpGlobals->curtime + NPCEVENTRESPONSE_REFIRE_TIME; - - if ( ai_debug_eventresponses.GetBool() ) - { - Msg( "NPCEVENTRESPONSE: (%.2f) Event '%s' responded to by NPC '%s'. Refire available at: %.2f\n", gpGlobals->curtime, pResponse, pNearestNPC->GetDebugName(), m_ActiveEvents[i].flNextResponseTime ); - } - - // Don't issue multiple responses at once - return; - } - } - } - } - - i = iNext; - } -} - -//--------------------------------------------------------------------------------------------- -// Entity version for mapmaker to hook into the system -//--------------------------------------------------------------------------------------------- -class CNPCEventResponseSystemEntity : public CBaseEntity -{ - DECLARE_CLASS( CNPCEventResponseSystemEntity, CBaseEntity ); -public: - DECLARE_DATADESC(); - - void Spawn(); - void InputTriggerResponseEvent( inputdata_t &inputdata ); - void InputForceTriggerResponseEvent( inputdata_t &inputdata ); - void InputForceTriggerResponseEventNoCancel( inputdata_t &inputdata ); -}; - -LINK_ENTITY_TO_CLASS( ai_npc_eventresponsesystem, CNPCEventResponseSystemEntity ); - -BEGIN_DATADESC( CNPCEventResponseSystemEntity ) - DEFINE_INPUTFUNC( FIELD_STRING, "TriggerResponseEvent", InputTriggerResponseEvent ), - DEFINE_INPUTFUNC( FIELD_STRING, "ForceTriggerResponseEvent", InputForceTriggerResponseEvent ), - DEFINE_INPUTFUNC( FIELD_STRING, "ForceTriggerResponseEventNoCancel", InputForceTriggerResponseEventNoCancel ), -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPCEventResponseSystemEntity::Spawn( void ) -{ - // Invisible, non solid. - AddSolidFlags( FSOLID_NOT_SOLID ); - AddEffects( EF_NODRAW ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPCEventResponseSystemEntity::InputTriggerResponseEvent( inputdata_t &inputdata ) -{ - NPCEventResponse()->TriggerEvent( inputdata.value.String(), false, false ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPCEventResponseSystemEntity::InputForceTriggerResponseEvent( inputdata_t &inputdata ) -{ - NPCEventResponse()->TriggerEvent( inputdata.value.String(), true, true ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPCEventResponseSystemEntity::InputForceTriggerResponseEventNoCancel( inputdata_t &inputdata ) -{ - NPCEventResponse()->TriggerEvent( inputdata.value.String(), true, false ); -} diff --git a/game/server/ai_eventresponse.h b/game/server/ai_eventresponse.h deleted file mode 100644 index f5190bc9f..000000000 --- a/game/server/ai_eventresponse.h +++ /dev/null @@ -1,48 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: AI system that makes NPCs verbally respond to game events -// -//=============================================================================// - -#ifndef AI_EVENTRESPONSE_H -#define AI_EVENTRESPONSE_H - -#include "utldict.h" - -#define NPCEVENTRESPONSE_DISTANCE_SQR (768 * 768) // Maximum distance for responding to NPCs -#define NPCEVENTRESPONSE_REFIRE_TIME 15.0 // Time after giving a response before giving any more -#define NPCEVENTRESPONSE_GIVEUP_TIME 4.0 // Time after a response trigger was fired before discarding it without responding - -//----------------------------------------------------------------------------- -// Purpose: AI system that makes NPCs verbally respond to game events -//----------------------------------------------------------------------------- -class CNPCEventResponseSystem : public CAutoGameSystemPerFrame -{ -public: - CNPCEventResponseSystem( char const *name ) : CAutoGameSystemPerFrame( name ) - { - } - - void LevelInitPreEntity(); - void FrameUpdatePreEntityThink(); - void TriggerEvent( const char *pResponse, bool bForce, bool bCancelScript ); - -private: - float m_flNextEventPoll; - - struct storedevent_t - { - float flEventTime; - float flNextResponseTime; - bool bForce; - bool bCancelScript; - bool bPreventExpiration; - }; - - typedef CUtlDict< storedevent_t, int > EventMap; - EventMap m_ActiveEvents; -}; - -CNPCEventResponseSystem *NPCEventResponse(); - -#endif // AI_EVENTRESPONSE_H diff --git a/game/server/ai_goalentity.cpp b/game/server/ai_goalentity.cpp deleted file mode 100644 index 7adc91e3f..000000000 --- a/game/server/ai_goalentity.cpp +++ /dev/null @@ -1,278 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" - -#include "utlrbtree.h" -#include "saverestore_utlvector.h" -#include "ai_goalentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// -// CAI_GoalEntity implementation -// - -BEGIN_DATADESC( CAI_GoalEntity ) - - DEFINE_KEYFIELD( m_iszActor, FIELD_STRING, "Actor" ), - DEFINE_KEYFIELD( m_iszGoal, FIELD_STRING, "Goal" ), - DEFINE_KEYFIELD( m_fStartActive, FIELD_BOOLEAN, "StartActive" ), - DEFINE_KEYFIELD( m_iszConceptModifiers, FIELD_STRING, "BaseConceptModifiers" ), - DEFINE_KEYFIELD( m_SearchType, FIELD_INTEGER, "SearchType" ), - DEFINE_UTLVECTOR( m_actors, FIELD_EHANDLE ), - DEFINE_FIELD( m_hGoalEntity, FIELD_EHANDLE ), - DEFINE_FIELD( m_flags, FIELD_INTEGER ), - - DEFINE_THINKFUNC( DelayedRefresh ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ), - DEFINE_INPUTFUNC( FIELD_VOID, "UpdateActors", InputUpdateActors ), - DEFINE_INPUTFUNC( FIELD_VOID, "Deactivate", InputDeactivate ), - -END_DATADESC() - - -//------------------------------------- - -void CAI_GoalEntity::Spawn() -{ - SetThink( &CAI_GoalEntity::DelayedRefresh ); - SetNextThink( gpGlobals->curtime + 0.1f ); -} - - -//------------------------------------- - -void CAI_GoalEntity::OnRestore() -{ - BaseClass::OnRestore(); - - ExitDormant(); - - if ( ( m_flags & ACTIVE ) ) - gEntList.AddListenerEntity( this ); -} - -//------------------------------------- - -void CAI_GoalEntity::DelayedRefresh() -{ - inputdata_t ignored; - if ( m_fStartActive ) - { - Assert( !(m_flags & ACTIVE) ); - InputActivate( ignored ); - m_fStartActive = false; - } - else - InputUpdateActors( ignored ); - - SetThink( NULL ); -} - -//------------------------------------- - -void CAI_GoalEntity::PruneActors() -{ - for ( int i = m_actors.Count() - 1; i >= 0; i-- ) - { - if ( m_actors[i] == NULL || m_actors[i]->IsMarkedForDeletion() || m_actors[i]->GetState() == NPC_STATE_DEAD ) - m_actors.FastRemove( i ); - } -} - -//------------------------------------- - -void CAI_GoalEntity::ResolveNames() -{ - m_actors.SetCount( 0 ); - - CBaseEntity *pEntity = NULL; - for (;;) - { - switch ( m_SearchType ) - { - case ST_ENTNAME: - { - pEntity = gEntList.FindEntityByName( pEntity, m_iszActor ); - break; - } - - case ST_CLASSNAME: - { - pEntity = gEntList.FindEntityByClassname( pEntity, STRING( m_iszActor ) ); - break; - } - } - - if ( !pEntity ) - break; - - CAI_BaseNPC *pActor = pEntity->MyNPCPointer(); - - if ( pActor && pActor->GetState() != NPC_STATE_DEAD ) - { - AIHANDLE temp; - temp = pActor; - m_actors.AddToTail( temp ); - } - } - - m_hGoalEntity = gEntList.FindEntityByName( NULL, m_iszGoal ); -} - -//------------------------------------- - -void CAI_GoalEntity::InputActivate( inputdata_t &inputdata ) -{ - if ( !( m_flags & ACTIVE ) ) - { - gEntList.AddListenerEntity( this ); - - UpdateActors(); - m_flags |= ACTIVE; - - for ( int i = 0; i < m_actors.Count(); i++ ) - { - EnableGoal( m_actors[i] ); - } - } -} - -//------------------------------------- - -void CAI_GoalEntity::InputUpdateActors( inputdata_t &inputdata ) -{ - int i; - CUtlRBTree prevActors; - CUtlRBTree::IndexType_t index; - - SetDefLessFunc( prevActors ); - - PruneActors(); - - for ( i = 0; i < m_actors.Count(); i++ ) - { - prevActors.Insert( m_actors[i] ); - } - - ResolveNames(); - - for ( i = 0; i < m_actors.Count(); i++ ) - { - index = prevActors.Find( m_actors[i] ); - if ( index == prevActors.InvalidIndex() ) - { - if ( m_flags & ACTIVE ) - EnableGoal( m_actors[i] ); - } - else - prevActors.Remove( m_actors[i] ); - } - - for ( index = prevActors.FirstInorder(); index != prevActors.InvalidIndex(); index = prevActors.NextInorder( index ) ) - { - if ( m_flags & ACTIVE ) - DisableGoal( prevActors[ index ] ); - } -} - -//------------------------------------- - -void CAI_GoalEntity::InputDeactivate( inputdata_t &inputdata ) -{ - if ( m_flags & ACTIVE ) - { - gEntList.RemoveListenerEntity( this ); - UpdateActors(); - m_flags &= ~ACTIVE; - - for ( int i = 0; i < m_actors.Count(); i++ ) - { - DisableGoal( m_actors[i] ); - } - } -} - -//------------------------------------- - -void CAI_GoalEntity::EnterDormant( void ) -{ - if ( m_flags & ACTIVE ) - { - m_flags |= DORMANT; - for ( int i = 0; i < m_actors.Count(); i++ ) - { - DisableGoal( m_actors[i] ); - } - } -} - -//------------------------------------- - -void CAI_GoalEntity::ExitDormant( void ) -{ - if ( m_flags & DORMANT ) - { - m_flags &= ~DORMANT; - - inputdata_t ignored; - InputUpdateActors( ignored ); - } -} - -//------------------------------------- - -void CAI_GoalEntity::UpdateOnRemove() -{ - if ( m_flags & ACTIVE ) - { - inputdata_t inputdata; - InputDeactivate( inputdata ); - } - BaseClass::UpdateOnRemove(); -} - -//------------------------------------- - -void CAI_GoalEntity::OnEntityCreated( CBaseEntity *pEntity ) -{ - Assert( m_flags & ACTIVE ); - - if ( pEntity->MyNPCPointer() ) - { - SetThink( &CAI_GoalEntity::DelayedRefresh ); - SetNextThink( gpGlobals->curtime + 0.1f ); - } - -} - -//------------------------------------- - -void CAI_GoalEntity::OnEntityDeleted( CBaseEntity *pEntity ) -{ - Assert( pEntity != this ); -} - -//----------------------------------------------------------------------------- - -int CAI_GoalEntity::DrawDebugTextOverlays() -{ - char tempstr[512]; - int offset = BaseClass::DrawDebugTextOverlays(); - - Q_snprintf( tempstr, sizeof(tempstr), "Active: %s", IsActive() ? "yes" : "no" ); - EntityText( offset, tempstr, 0 ); - offset++; - - return offset; -} - - diff --git a/game/server/ai_goalentity.h b/game/server/ai_goalentity.h deleted file mode 100644 index 0c97b9711..000000000 --- a/game/server/ai_goalentity.h +++ /dev/null @@ -1,194 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef AI_GOALENTITY_H -#define AI_GOALENTITY_H - -#include "ai_basenpc.h" -#include "utlvector.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -//----------------------------------------------------------------------------- -// -// CAI_GoalEntity -// -// Purpose: Serves as the base class for all entities the designer may place -// that establish an NPC goal. Provides standard input, output & -// fields common to all goals. -// - -class CAI_GoalEntity : public CBaseEntity, - public IEntityListener -{ - DECLARE_CLASS( CAI_GoalEntity, CBaseEntity ); -public: - CAI_GoalEntity() - : m_iszActor(NULL_STRING), - m_iszGoal(NULL_STRING), - m_fStartActive(false), - m_SearchType(ST_ENTNAME), - m_iszConceptModifiers(NULL_STRING), - m_hGoalEntity(NULL), - m_flags( 0 ) - { - } - - virtual int ObjectCaps() { return ((BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | FCAP_NOTIFY_ON_TRANSITION); } - - virtual void Spawn(); - virtual void OnRestore(); - virtual int DrawDebugTextOverlays(); - - virtual void InputActivate( inputdata_t &inputdata ); - virtual void InputUpdateActors( inputdata_t &inputdata ); - virtual void InputDeactivate( inputdata_t &inputdata ); - - // Goal entities can become Dormant if they're left behind on previous maps. - // Transitioning back to the map with cause a dormant goal entity to reactivate itself. - void EnterDormant( void ); - void ExitDormant( void ); - - bool IsActive(); - - int NumActors(); - CAI_BaseNPC * GetActor( int iActor = 0 ); - - void SetGoalEntity( CBaseEntity *pGoalEntity ); - CBaseEntity * GetGoalEntity(); - const char * GetGoalEntityName(); - - const char * GetConceptModifiers(); - -protected: - virtual void UpdateOnRemove(); - - virtual void OnEntityCreated( CBaseEntity *pEntity ); - virtual void OnEntityDeleted( CBaseEntity *pEntity ); - - virtual void EnableGoal( CAI_BaseNPC *pAI ) {} - virtual void DisableGoal( CAI_BaseNPC *pAI ) {} - - void UpdateActors(); - - const CUtlVector &AccessActors() - { - return m_actors; - } - -private: - enum Flags_t - { - ACTIVE = 0x01, - RESOLVED_NAME = 0x02, - DORMANT = 0x04, - }; - - enum SearchType_t - { - ST_ENTNAME, - ST_CLASSNAME, - }; - - void DelayedRefresh(); - void PruneActors(); - void ResolveNames(); - - // From Worldcraft - string_t m_iszActor; - string_t m_iszGoal; - bool m_fStartActive; - SearchType_t m_SearchType; - string_t m_iszConceptModifiers; - - CUtlVector m_actors; - EHANDLE m_hGoalEntity; - unsigned m_flags; - - -protected: - DECLARE_DATADESC(); -}; - -//------------------------------------- - -// @TODO (toml 03-18-03): Efficiency wart -- make this an explicit duty of the client? -inline void CAI_GoalEntity::UpdateActors() -{ - if ( !( m_flags & ACTIVE ) || !( m_flags & RESOLVED_NAME ) ) - { - ResolveNames(); - m_flags |= RESOLVED_NAME; - } - else - PruneActors(); -} - -//------------------------------------- - -inline bool CAI_GoalEntity::IsActive() -{ - if ( m_flags & ACTIVE ) - { - UpdateActors(); - return ( m_actors.Count() != 0 ); - } - return false; -} - -//------------------------------------- - -inline int CAI_GoalEntity::NumActors() -{ - UpdateActors(); - return m_actors.Count(); -} - -//------------------------------------- - -inline CAI_BaseNPC *CAI_GoalEntity::GetActor( int iActor ) -{ - UpdateActors(); - if ( m_actors.Count() > iActor ) - return m_actors[iActor]; - return NULL; -} - -//------------------------------------- - -inline void CAI_GoalEntity::SetGoalEntity( CBaseEntity *pGoalEntity ) -{ - m_iszGoal = pGoalEntity->GetEntityName(); - m_hGoalEntity = pGoalEntity; -} - -//------------------------------------- - -inline CBaseEntity *CAI_GoalEntity::GetGoalEntity() -{ - UpdateActors(); - return m_hGoalEntity; -} - -//------------------------------------- - -inline const char *CAI_GoalEntity::GetGoalEntityName() -{ - return STRING( m_iszGoal ); -} - -//------------------------------------- - -inline const char *CAI_GoalEntity::GetConceptModifiers() -{ - return STRING( m_iszConceptModifiers ); -} - -//----------------------------------------------------------------------------- - -#endif // AI_GOALENTITY_H diff --git a/game/server/ai_hint.cpp b/game/server/ai_hint.cpp deleted file mode 100644 index 9d2be7f64..000000000 --- a/game/server/ai_hint.cpp +++ /dev/null @@ -1,1686 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Hint node utilities and functions -// -// $NoKeywords: $ -//=============================================================================// - -// @TODO (toml 03-04-03): there is far too much duplicate code in here - -#include "cbase.h" -#include "ai_hint.h" -#include "ai_network.h" -#include "ai_node.h" -#include "ai_basenpc.h" -#include "ai_networkmanager.h" -#include "ndebugoverlay.h" -#include "animation.h" -#include "tier1/strtools.h" -#include "mapentities_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define REPORTFAILURE(text) if ( hintCriteria.HasFlag( bits_HINT_NODE_REPORT_FAILURES ) ) \ - NDebugOverlay::Text( GetAbsOrigin(), text, false, 60 ) - -//================================================== -// CHintCriteria -//================================================== - -CHintCriteria::CHintCriteria( void ) -{ - m_iFirstHintType = HINT_NONE; - m_iLastHintType = HINT_NONE; - m_strGroup = NULL_STRING; - m_iFlags = 0; - m_HintTypes.Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: Destructor -//----------------------------------------------------------------------------- -CHintCriteria::~CHintCriteria( void ) -{ - m_zoneInclude.Purge(); - m_zoneExclude.Purge(); - m_HintTypes.Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: Sets the hint type for this search criteria -// Input : nHintType - the hint type for this search criteria -//----------------------------------------------------------------------------- -void CHintCriteria::SetHintType( int nHintType ) -{ - m_iFirstHintType = nHintType; - m_iLastHintType = HINT_NONE; - m_HintTypes.Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: Add another type of hint that matches the search criteria -//----------------------------------------------------------------------------- -void CHintCriteria::AddHintType( int hintType ) -{ - m_HintTypes.AddToTail( hintType ); -} - -int CHintCriteria::NumHintTypes() const -{ - return m_HintTypes.Count(); -} - -int CHintCriteria::GetHintType( int idx ) const -{ - return m_HintTypes[ idx ]; -} - -bool CHintCriteria::MatchesSingleHintType() const -{ - if ( m_HintTypes.Count() != 0 ) - { - return false; - } - - if ( m_iFirstHintType != HINT_ANY && - m_iLastHintType == HINT_NONE ) - { - return true; - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CHintCriteria::MatchesHintType( int hintType ) const -{ - int c = m_HintTypes.Count(); - for ( int i = 0; i < c; ++i ) - { - if ( m_HintTypes[i] == hintType ) - return true; - } - - // See if we're trying to filter the nodes - if ( GetFirstHintType() != HINT_ANY ) - { - if( GetLastHintType() == HINT_NONE ) - { - // Searching for a single type of hint. - if( GetFirstHintType() != hintType ) - return false; - } - else - { - // This search is for a range of hint types. - if( hintType < GetFirstHintType() || hintType > GetLastHintType() ) - return false; - } - - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Allows us to search for nodes within a range of consecutive types. -//----------------------------------------------------------------------------- -void CHintCriteria::SetHintTypeRange( int firstType, int lastType ) -{ - if( lastType < firstType ) - { - DevMsg( 2, "Hint Type Range is backwards - Fixing up.\n" ); - - int temp; - - temp = firstType; - firstType = lastType; - lastType = temp; - } - - m_iFirstHintType = firstType; - m_iLastHintType = lastType; - m_HintTypes.Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : bitmask - -//----------------------------------------------------------------------------- -void CHintCriteria::SetFlag( int bitmask ) -{ - m_iFlags |= bitmask; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : bitmask - -//----------------------------------------------------------------------------- -void CHintCriteria::ClearFlag( int bitmask ) -{ - m_iFlags &= ~bitmask; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : group - -//----------------------------------------------------------------------------- -void CHintCriteria::SetGroup( string_t group ) -{ - m_strGroup = group; -} - -//----------------------------------------------------------------------------- -// Purpose: Adds a zone to a zone list -// Input : list - the list of zones to add the new zone to -// &position - the origin point of the zone -// radius - the radius of the zone -//----------------------------------------------------------------------------- -void CHintCriteria::AddZone( zoneList_t &list, const Vector &position, float radius ) -{ - int id = list.AddToTail(); - list[id].position = position; - list[id].radiussqr = radius*radius; -} - -//----------------------------------------------------------------------------- -// Purpose: Adds an include zone to the search criteria -// Input : &position - the origin point of the zone -// radius - the radius of the zone -//----------------------------------------------------------------------------- -void CHintCriteria::AddIncludePosition( const Vector &position, float radius ) -{ - AddZone( m_zoneInclude, position, radius ); -} - -//----------------------------------------------------------------------------- -// Purpose: Adds an exclude zone to the search criteria -// Input : &position - the origin point of the zone -// radius - the radius of the zone -//----------------------------------------------------------------------------- -void CHintCriteria::AddExcludePosition( const Vector &position, float radius ) -{ - AddZone( m_zoneExclude, position, radius ); -} - -//----------------------------------------------------------------------------- -// Purpose: Test to see if this position falls within any of the zones in the list -// Input : *zone - list of zones to test against -// &testPosition - position to test with -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -inline bool CHintCriteria::InZone( const zoneList_t &zone, const Vector &testPosition ) const -{ - int numZones = zone.Count(); - - //Iterate through all zones in the list - for ( int i = 0; i < numZones; i++ ) - { - if ( ((zone[i].position) - testPosition).LengthSqr() < (zone[i].radiussqr) ) - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Determine if a point within our include list -// Input : &testPosition - position to test with -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CHintCriteria::InIncludedZone( const Vector &testPosition ) const -{ - return InZone( m_zoneInclude, testPosition ); -} - -//----------------------------------------------------------------------------- -// Purpose: Determine if a point within our exclude list -// Input : &testPosition - position to test with -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CHintCriteria::InExcludedZone( const Vector &testPosition ) const -{ - return InZone( m_zoneExclude, testPosition ); -} - -//----------------------------------------------------------------------------- -// Init static variables -//----------------------------------------------------------------------------- -CAIHintVector CAI_HintManager::gm_AllHints; -CUtlMap< int, CAIHintVector > CAI_HintManager::gm_TypedHints( 0, 0, DefLessFunc( int ) ); -CAI_Hint* CAI_HintManager::gm_pLastFoundHints[ CAI_HintManager::HINT_HISTORY ]; -int CAI_HintManager::gm_nFoundHintIndex = 0; - -CAI_Hint *CAI_HintManager::AddFoundHint( CAI_Hint *hint ) -{ - if ( hint ) - { - CAI_HintManager::gm_nFoundHintIndex = ( CAI_HintManager::gm_nFoundHintIndex + 1 ) & CAI_HintManager::HINT_HISTORY_MASK; - gm_pLastFoundHints[ CAI_HintManager::gm_nFoundHintIndex ] = hint; - } - return hint; - -} - -int CAI_HintManager::GetFoundHintCount() -{ - return CAI_HintManager::HINT_HISTORY; -} - -CAI_Hint *CAI_HintManager::GetFoundHint( int index ) -{ - return gm_pLastFoundHints[ ( CAI_HintManager::gm_nFoundHintIndex + index ) & CAI_HintManager::HINT_HISTORY_MASK ]; -} - -CAI_Hint *CAI_HintManager::GetLastFoundHint() -{ - for ( int i = 0; i < CAI_HintManager::HINT_HISTORY; ++i ) - { - // Walk backward - int slot = ( ( CAI_HintManager::gm_nFoundHintIndex - i ) & CAI_HintManager::HINT_HISTORY_MASK ); - if ( gm_pLastFoundHints[ slot ] ) - return gm_pLastFoundHints[ slot ]; - } - return NULL; -} - -void CAI_HintManager::ResetFoundHints() -{ - Q_memset( gm_pLastFoundHints, 0, sizeof( gm_pLastFoundHints ) ); - CAI_HintManager::gm_nFoundHintIndex = 0; -} - -bool CAI_HintManager::IsInFoundHintList( CAI_Hint *hint ) -{ - for ( int i = 0; i < CAI_HintManager::HINT_HISTORY; ++i ) - { - if ( gm_pLastFoundHints[ i ] == hint ) - return true; - } - return false; -} - -//----------------------------------------------------------------------------- -int CAI_HintManager::FindAllHints( CAI_BaseNPC *pNPC, const Vector &position, const CHintCriteria &hintCriteria, CUtlVector *pResult ) -{ - // If we have no hints, bail - int c = CAI_HintManager::gm_AllHints.Count(); - if ( !c ) - return 0; - - // Remove the nearest flag. It makes now sense with random. - bool hadNearest = hintCriteria.HasFlag( bits_HINT_NODE_NEAREST ); - (const_cast(hintCriteria)).ClearFlag( bits_HINT_NODE_NEAREST ); - - // Now loop till we find a valid hint or return to the start - CAI_Hint *pTestHint; - for ( int i = 0; i < c; ++i ) - { - pTestHint = CAI_HintManager::gm_AllHints[ i ]; - Assert( pTestHint ); - if ( pTestHint->HintMatchesCriteria( pNPC, hintCriteria, position, NULL ) ) - pResult->AddToTail( pTestHint ); - } - - if ( hadNearest ) - (const_cast(hintCriteria)).SetFlag( bits_HINT_NODE_NEAREST ); - - return pResult->Count(); -} - -//----------------------------------------------------------------------------- -// Purpose: Finds a random hint within the requested radious of the npc -// Builds a list of all suitable hints and chooses randomly from amongst them. -// Input : *pNPC - -// nHintType - -// nFlags - -// flMaxDist - -// Output : CAI_Hint -//----------------------------------------------------------------------------- -CAI_Hint *CAI_HintManager::FindHintRandom( CAI_BaseNPC *pNPC, const Vector &position, const CHintCriteria &hintCriteria ) -{ - CUtlVector hintList; - - if ( FindAllHints( pNPC, position, hintCriteria, &hintList ) > 0 ) - { - // Pick one randomly - return ( CAI_HintManager::AddFoundHint( hintList[ random->RandomInt( 0, hintList.Size() - 1 ) ] ) ); - } - - // start at the top of the list for the next search - CAI_HintManager::ResetFoundHints(); - return NULL; -} - -// #define HINT_PROFILING 1 -#if defined( HINT_PROFILING ) -static void AppendTimer( int idx, char *buf, size_t bufsize, CFastTimer& timer ) -{ - char s[ 32 ]; - Q_snprintf( s, sizeof( s ), "%d %6.3f ms", idx, timer.GetDuration().GetMillisecondsF() ); - - Q_strncat( buf, s, bufsize ); -} -#endif - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *hintCriteria - -// Output : CAI_Hint -//----------------------------------------------------------------------------- -CAI_Hint *CAI_HintManager::FindHint( CAI_BaseNPC *pNPC, const Vector &position, const CHintCriteria &hintCriteria ) -{ -#if defined( HINT_PROFILING ) - CFastTimer timer; - timer.Start(); -#endif - bool singleType = hintCriteria.MatchesSingleHintType(); - bool lookingForNearest = hintCriteria.HasFlag( bits_HINT_NODE_NEAREST ); - bool bIgnoreHintType = true; - - CUtlVector< CAIHintVector * > lists; - if ( singleType ) - { - int slot = CAI_HintManager::gm_TypedHints.Find( hintCriteria.GetFirstHintType() ); - if ( slot != CAI_HintManager::gm_TypedHints.InvalidIndex() ) - { - lists.AddToTail( &CAI_HintManager::gm_TypedHints[ slot ] ); - } - } - else - { - int typeCount = hintCriteria.NumHintTypes(); - if ( typeCount > 0 ) - { - for ( int listType = 0; listType < typeCount; ++listType ) - { - int slot = CAI_HintManager::gm_TypedHints.Find( hintCriteria.GetHintType( listType ) ); - if ( slot != CAI_HintManager::gm_TypedHints.InvalidIndex() ) - { - lists.AddToTail( &CAI_HintManager::gm_TypedHints[ slot ] ); - } - } - } - else - { - // Still need to check hint type in this case - lists.AddToTail( &CAI_HintManager::gm_AllHints ); - bIgnoreHintType = false; - } - } - - CAI_Hint *pBestHint = NULL; - - int visited = 0; - - int listCount = lists.Count(); - - if ( listCount == 0 ) - return NULL; - - // Try the fast match path - int i, count; - // Start with hint after the last one used - CAI_Hint *pTestHint = NULL; - - float flBestDistance = MAX_TRACE_LENGTH; - - if ( !lookingForNearest ) - { - // Fast check of previous results - count = CAI_HintManager::GetFoundHintCount(); - for ( i = 0; i < count; ++i ) - { - pTestHint = CAI_HintManager::GetFoundHint( i ); - if ( pTestHint ) - { - Assert( dynamic_cast(pTestHint) != NULL ); - ++visited; - if ( pTestHint->HintMatchesCriteria( pNPC, hintCriteria, position, &flBestDistance ) ) - { -#if defined( HINT_PROFILING ) - Msg( "fast result visited %d\n", visited ); -#endif - return pTestHint; - } - } - } - } - - // Longer search, reset best distance - flBestDistance = MAX_TRACE_LENGTH; - - for ( int listNum = 0; listNum < listCount; ++listNum ) - { - CAIHintVector *list = lists[ listNum ]; - count = list->Count(); - // ------------------------------------------- - // If we have no hints, bail - // ------------------------------------------- - if ( !count ) - continue; - - // Now loop till we find a valid hint or return to the start - for ( i = 0 ; i < count; ++i ) - { - pTestHint = list->Element( i ); - Assert( pTestHint ); - - ++visited; - - Assert( dynamic_cast(pTestHint) != NULL ); - if ( pTestHint->HintMatchesCriteria( pNPC, hintCriteria, position, &flBestDistance, false, bIgnoreHintType ) ) - { - // If we were searching for the nearest, just note that this is now the nearest node - if ( lookingForNearest ) - { - pBestHint = pTestHint; - } - else - { - // If we're not looking for the nearest, we're done - CAI_HintManager::AddFoundHint( pTestHint ); -#if defined( HINT_PROFILING ) - Msg( "visited %d\n", visited ); -#endif - return pTestHint; - } - } - } - } - // Return the nearest node that we found - if ( pBestHint ) - { - CAI_HintManager::AddFoundHint( pBestHint ); - } - -#if defined( HINT_PROFILING ) - timer.End(); - - Msg( "visited %d\n", visited ); - if ( !pBestHint ) - { - Msg( "%i search failed for [%d] at pos %.3f %.3f %.3f [%.4f msec ~ %.4f msec per node]\n", - gpGlobals->tickcount, - pNPC ? pNPC->entindex() : -1, - position.x, position.y, position.z, - timer.GetDuration().GetMillisecondsF(), - timer.GetDuration().GetMillisecondsF()/MAX( (float)visited, 1.0f ) ); - } -#endif - return pBestHint; -} - -//----------------------------------------------------------------------------- -// Purpose: Searches for a hint node that this NPC cares about. If one is -// claims that hint node for this NPC so that no other NPCs -// try to use it. -// -// Input : nFlags - Search criterea. Can currently be one or more of the following: -// bits_HINT_NODE_VISIBLE - searches for visible hint nodes. -// bits_HINT_NODE_RANDOM - calls through the FindHintRandom and builds list of all matching -// nodes and picks randomly from among them. Note: Depending on number of hint nodes, this -// could be slower, so use with care. -// -// Output : Returns pointer to hint node if available hint node was found that matches the -// given criterea that this NPC also cares about. Otherwise, returns NULL -//----------------------------------------------------------------------------- -CAI_Hint* CAI_HintManager::FindHint( CAI_BaseNPC *pNPC, Hint_e nHintType, int nFlags, float flMaxDist, const Vector *pMaxDistFrom ) -{ - assert( pNPC != NULL ); - if ( pNPC == NULL ) - return NULL; - - CHintCriteria hintCriteria; - hintCriteria.SetHintType( nHintType ); - hintCriteria.SetFlag( nFlags ); - - // Using the NPC's hint group? - if ( nFlags & bits_HINT_NODE_USE_GROUP ) - { - hintCriteria.SetGroup( pNPC->GetHintGroup() ); - } - - // Add the search position - Vector vecPosition = ( pMaxDistFrom != NULL ) ? (*pMaxDistFrom) : pNPC->GetAbsOrigin(); - hintCriteria.AddIncludePosition( vecPosition, flMaxDist ); - - // If asking for a random node, use random logic instead - if ( nFlags & bits_HINT_NODE_RANDOM ) - return FindHintRandom( pNPC, vecPosition, hintCriteria ); - - return FindHint( pNPC, vecPosition, hintCriteria ); -} - -//----------------------------------------------------------------------------- -// Purpose: Position only search -// Output : CAI_Hint -//----------------------------------------------------------------------------- -CAI_Hint *CAI_HintManager::FindHint( const Vector &position, const CHintCriteria &hintCriteria ) -{ - return FindHint( NULL, position, hintCriteria ); -} - -//----------------------------------------------------------------------------- -// Purpose: NPC only search -// Output : CAI_Hint -//----------------------------------------------------------------------------- -CAI_Hint *CAI_HintManager::FindHint( CAI_BaseNPC *pNPC, const CHintCriteria &hintCriteria ) -{ - assert( pNPC != NULL ); - if ( pNPC == NULL ) - return NULL; - - return FindHint( pNPC, pNPC->GetAbsOrigin(), hintCriteria ); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -CAI_Hint* CAI_HintManager::CreateHint( HintNodeData *pNodeData, const char *pMapData ) -{ - // Reset last found hint if new node is added - CAI_HintManager::ResetFoundHints(); - - CAI_Hint *pHint = (CAI_Hint*)CreateEntityByName("ai_hint"); - if ( pHint ) - { - // First, parse the mapdata chunk we were passed - if ( pMapData ) - { - CEntityMapData entData( (char*)pMapData ); - pHint->ParseMapData( &entData ); - - // Restore the desired classname (parsing the mapdata stomps it) - pHint->SetClassname( "ai_hint" ); - } - - pHint->SetName( pNodeData->strEntityName ); - pHint->SetAbsOrigin( pNodeData->vecPosition ); - memcpy( &(pHint->m_NodeData), pNodeData, sizeof(HintNodeData) ); - DispatchSpawn( pHint ); - - return pHint; - } - - return NULL; -} - -//------------------------------------------------------------------------------ -void CAI_HintManager::AddHint( CAI_Hint *pHint ) -{ - // --------------------------------- - // Add to linked list of hints - // --------------------------------- - CAI_HintManager::gm_AllHints.AddToTail( pHint ); - CAI_HintManager::AddHintByType( pHint ); -} - -void CAI_Hint::SetHintType( int hintType, bool force /*= false*/ ) -{ - if ( !force && hintType == m_NodeData.nHintType ) - return; - - CAI_HintManager::RemoveHintByType( this ); - m_NodeData.nHintType = hintType; - CAI_HintManager::AddHintByType( this ); -} - -void CAI_HintManager::AddHintByType( CAI_Hint *pHint ) -{ - Hint_e type = pHint->HintType(); - - int slot = CAI_HintManager::gm_TypedHints.Find( type ); - if ( slot == CAI_HintManager::gm_TypedHints.InvalidIndex() ) - { - slot = CAI_HintManager::gm_TypedHints.Insert( type); - } - CAI_HintManager::gm_TypedHints[ slot ].AddToTail( pHint ); -} - -void CAI_HintManager::RemoveHintByType( CAI_Hint *pHintToRemove ) -{ - int slot = CAI_HintManager::gm_TypedHints.Find( pHintToRemove->HintType() ); - if ( slot != CAI_HintManager::gm_TypedHints.InvalidIndex() ) - { - CAI_HintManager::gm_TypedHints[ slot ].FindAndRemove( pHintToRemove ); - } -} - -//------------------------------------------------------------------------------ -void CAI_HintManager::RemoveHint( CAI_Hint *pHintToRemove ) -{ - // -------------------------------------- - // Remove from linked list of hints - // -------------------------------------- - gm_AllHints.FindAndRemove( pHintToRemove ); - RemoveHintByType( pHintToRemove ); - - if ( CAI_HintManager::IsInFoundHintList( pHintToRemove ) ) - { - CAI_HintManager::ResetFoundHints(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *token - -// Output : int -//----------------------------------------------------------------------------- -int CAI_HintManager::GetFlags( const char *token ) -{ - int len = strlen( token ); - if ( len <= 0 ) - { - return bits_HINT_NODE_NONE; - } - - char *lowercase = (char *)_alloca( len + 1 ); - Q_strncpy( lowercase, token, len+1 ); - Q_strlower( lowercase ); - - if ( strstr( "none", lowercase ) ) - { - return bits_HINT_NODE_NONE; - } - - int bits = 0; - - if ( strstr( "visible", lowercase ) ) - { - bits |= bits_HINT_NODE_VISIBLE; - } - - if ( strstr( "nearest", lowercase ) ) - { - bits |= bits_HINT_NODE_NEAREST; - } - - if ( strstr( "random", lowercase ) ) - { - bits |= bits_HINT_NODE_RANDOM; - } - - // Can't be nearest and random, defer to nearest - if ( ( bits & bits_HINT_NODE_NEAREST ) && - ( bits & bits_HINT_NODE_RANDOM ) ) - { - // Remove random - bits &= ~bits_HINT_NODE_RANDOM; - - DevMsg( "HINTFLAGS:%s, inconsistent, the nearest node is never a random hint node, treating as nearest request!\n", - token ); - } - - return bits; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CAI_Hint *CAI_HintManager::GetFirstHint( AIHintIter_t *pIter ) -{ - if ( !gm_AllHints.Count() ) - { - *pIter = (AIHintIter_t)gm_AllHints.InvalidIndex(); - return NULL; - } - *pIter = (AIHintIter_t)0; - return gm_AllHints[0]; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CAI_Hint *CAI_HintManager::GetNextHint( AIHintIter_t *pIter ) -{ - if ( (int)*pIter != gm_AllHints.InvalidIndex() ) - { - int i = ( (int)*pIter ) + 1; - if ( gm_AllHints.Count() <= i ) - { - *pIter = (AIHintIter_t)gm_AllHints.InvalidIndex(); - return NULL; - } - *pIter = (AIHintIter_t)i; - return gm_AllHints[i]; - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_HintManager::DumpHints() -{ - AIHintIter_t iter; - CAI_Hint *pCurHint = GetFirstHint( &iter ); - while (pCurHint) - { - const Vector &v = pCurHint->GetAbsOrigin(); - Msg( "(%.1f, %.1f, %.1f) -- Node ID: %d; WC id %d; type %d\n", - v.x, v.y, v.z, - pCurHint->GetNodeId(), - pCurHint->GetWCId(), - pCurHint->HintType() ); - pCurHint = GetNextHint( &iter ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_HintManager::ValidateHints() -{ -#ifdef _DEBUG - int nTyped = 0; - FOR_EACH_VEC( gm_AllHints, i ) - { - Assert( dynamic_cast(gm_AllHints[i]) != NULL ); - } - - for ( int i = gm_TypedHints.FirstInorder(); i != gm_TypedHints.InvalidIndex(); i = gm_TypedHints.NextInorder( i ) ) - { - FOR_EACH_VEC( gm_TypedHints[i], j ) - { - nTyped++; - Assert( dynamic_cast(gm_TypedHints[i][j]) != NULL ); - } - } - - Assert( gm_AllHints.Count() == nTyped ); -#endif -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CAI_HintManager::DrawHintOverlays(float flDrawDuration) -{ - int c = gm_AllHints.Count(); - for ( int i = 0; i < c; ++i ) - { - CAI_Hint *pHint = gm_AllHints[ i ]; - int r = 0; - int g = 0; - int b = 255; - Vector vHintPos; - - if (pHint->m_NodeData.nNodeID != NO_NODE) - { - vHintPos = g_pBigAINet->GetNode(pHint->m_NodeData.nNodeID)->GetPosition(g_pAINetworkManager->GetEditOps()->m_iHullDrawNum); - } - else - { - vHintPos = pHint->GetAbsOrigin(); - } - - if ( pHint->GetNodeId() != NO_NODE ) - NDebugOverlay::Text( vHintPos + Vector(0,6,8), CFmtStr("(%d), (%d)", pHint->HintType(), pHint->GetNodeId()), true, flDrawDuration ); - else - NDebugOverlay::Text( vHintPos + Vector(0,6,8), CFmtStr("(%d)", pHint->HintType()), true, flDrawDuration ); - - // If node is currently locked - if (pHint->m_NodeData.iDisabled) - { - r = 100; - g = 100; - b = 100; - } - else if (pHint->m_hHintOwner != NULL) - { - r = 255; - g = 0; - b = 0; - - CBaseEntity* pOwner = pHint->User(); - if (pOwner) - { - char owner[255]; - Q_strncpy(owner,pOwner->GetDebugName(),sizeof(owner)); - Vector loc = vHintPos; - loc.x+=6; - loc.y+=6; - loc.z+=6; - NDebugOverlay::Text( loc, owner, true, flDrawDuration ); - NDebugOverlay::Line( vHintPos, pOwner->WorldSpaceCenter(), 128, 128, 128, false, 0); - } - } - else if (pHint->IsLocked()) - { - r = 200; - g = 150; - b = 10; - } - - NDebugOverlay::Box(vHintPos, Vector(-3,-3,-3), Vector(3,3,3), r,g,b,0,flDrawDuration); - - // Draw line in facing direction - Vector offsetDir = 12.0 * Vector(cos(DEG2RAD(pHint->Yaw())),sin(DEG2RAD(pHint->Yaw())),0); - NDebugOverlay::Line(vHintPos, vHintPos+offsetDir, r,g,b,false,flDrawDuration); - } -} - -//################################################################## -// > CAI_Hint -//################################################################## -LINK_ENTITY_TO_CLASS( ai_hint, CAI_Hint ); - -BEGIN_DATADESC( CAI_Hint ) - - DEFINE_EMBEDDED( m_NodeData ), - // m_nTargetNodeID (reset on load) - - DEFINE_FIELD( m_hHintOwner, FIELD_EHANDLE), - DEFINE_FIELD( m_flNextUseTime, FIELD_TIME), - DEFINE_FIELD( m_vecForward, FIELD_VECTOR), - DEFINE_KEYFIELD( m_nodeFOV, FIELD_FLOAT, "nodeFOV" ), - - DEFINE_THINKFUNC( EnableThink ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "EnableHint", InputEnableHint ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableHint", InputDisableHint ), - - // Outputs - DEFINE_OUTPUT( m_OnNPCStartedUsing, "OnNPCStartedUsing" ), - DEFINE_OUTPUT( m_OnNPCStoppedUsing, "OnNPCStoppedUsing" ), - -END_DATADESC( ); - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CAI_Hint::InputEnableHint( inputdata_t &inputdata ) -{ - m_NodeData.iDisabled = false; -} - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CAI_Hint::InputDisableHint( inputdata_t &inputdata ) -{ - m_NodeData.iDisabled = true; -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CAI_Hint::Spawn( void ) -{ - // Cache off the forward vector - GetVectors( &m_vecForward, NULL, NULL ); - - if( m_nodeFOV != 360 ) - { - // As a micro-optimization, leave the FOV at 360 to save us - // a dot product later when checking node FOV. - m_nodeFOV = cos( DEG2RAD(m_nodeFOV/2) ); - } - - SetSolid( SOLID_NONE ); -} - -void CAI_Hint::Activate() -{ - BaseClass::Activate(); - CAI_HintManager::AddHint( this ); -} - -void CAI_Hint::UpdateOnRemove( void ) -{ - CAI_HintManager::RemoveHint( this ); - BaseClass::UpdateOnRemove(); -} - -//------------------------------------------------------------------------------ -// Purpose : If connected to a node returns node position, otherwise -// returns local hint position -// -// NOTE: Assumes not using multiple AI networks -// Input : -// Output : -//------------------------------------------------------------------------------ -void CAI_Hint::GetPosition(CBaseCombatCharacter *pBCC, Vector *vPosition) -{ - if ( m_NodeData.nNodeID != NO_NODE ) - { - *vPosition = g_pBigAINet->GetNodePosition( pBCC, m_NodeData.nNodeID ); - } - else - { - *vPosition = GetAbsOrigin(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : hull - -// *vPosition - -//----------------------------------------------------------------------------- -void CAI_Hint::GetPosition( Hull_t hull, Vector *vPosition ) -{ - if ( m_NodeData.nNodeID != NO_NODE ) - { - *vPosition = g_pBigAINet->GetNodePosition( hull, m_NodeData.nNodeID ); - } - else - { - *vPosition = GetAbsOrigin(); - } -} - -//------------------------------------------------------------------------------ -// Purpose : If connected to a node returns node direction, otherwise -// returns local hint direction -// -// NOTE: Assumes not using multiple AI networks -// Input : -// Output : -//------------------------------------------------------------------------------ -Vector CAI_Hint::GetDirection( ) -{ - return UTIL_YawToVector( Yaw() ); -} - -//------------------------------------------------------------------------------ -// Purpose : If connected to a node returns node yaw, otherwise -// returns local hint yaw -// -// NOTE: Assumes not using multiple AI networks -// Input : -// Output : -//------------------------------------------------------------------------------ -float CAI_Hint::Yaw(void) -{ - if (m_NodeData.nNodeID != NO_NODE) - { - return g_pBigAINet->GetNodeYaw(m_NodeData.nNodeID ); - } - else - { - return GetLocalAngles().y; - } -} - - - -//------------------------------------------------------------------------------ -// Purpose : Returns if this is something that's interesting to look at -// -// NOTE: Assumes not using multiple AI networks -// Input : -// Output : -//------------------------------------------------------------------------------ -bool CAI_Hint::IsViewable(void) -{ - if (m_NodeData.iDisabled) - { - return false; - } - - switch( HintType() ) - { - case HINT_WORLD_VISUALLY_INTERESTING: - case HINT_WORLD_VISUALLY_INTERESTING_DONT_AIM: - case HINT_WORLD_VISUALLY_INTERESTING_STEALTH: - return true; - default: - break; - } - - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CAI_Hint::IsInNodeFOV( CBaseEntity *pOther ) -{ - if( m_nodeFOV == 360 ) - { - return true; - } - -#if 0 - NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + m_vecForward * 16, 255, 255, 0, false, 1 ); -#endif - - Vector vecToNPC = pOther->GetAbsOrigin() - GetAbsOrigin(); - VectorNormalize( vecToNPC ); - float flDot = DotProduct( vecToNPC, m_vecForward ); - - if( flDot > m_nodeFOV ) - { -#if 0 - NDebugOverlay::Line( GetAbsOrigin(), pOther->GetAbsOrigin(), 0, 255, 0, false, 1 ); -#endif - return true; - } - -#if 0 - NDebugOverlay::Line( GetAbsOrigin(), pOther->GetAbsOrigin(), 255, 0, 0, false, 1 ); -#endif - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Locks the node for use by an AI for hints -// Output : Returns true if the node was available for locking, false on failure. -//----------------------------------------------------------------------------- -bool CAI_Hint::Lock( CBaseEntity* pNPC ) -{ - if ( m_hHintOwner != pNPC && m_hHintOwner != NULL ) - return false; - m_hHintOwner = pNPC; - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Unlocks the node, making it available for hint use by other AIs. -// after the given delay time -//----------------------------------------------------------------------------- -void CAI_Hint::Unlock( float delay ) -{ - m_hHintOwner = NULL; - m_flNextUseTime = gpGlobals->curtime + delay; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true is hint node is open for use -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CAI_Hint::IsLockedBy( CBaseEntity *pNPC ) -{ - return (m_hHintOwner == pNPC); -}; - -//----------------------------------------------------------------------------- -// Purpose: Returns true is hint node is open for use -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CAI_Hint::IsLocked( void ) -{ - if (m_NodeData.iDisabled) - { - return true; - } - - if (gpGlobals->curtime < m_flNextUseTime) - { - return true; - } - - if (m_hHintOwner != NULL) - { - return true; - } - return false; -}; - -//----------------------------------------------------------------------------- -// Purpose: Return true if pTestHint passes the criteria specified in hintCriteria -//----------------------------------------------------------------------------- -bool CAI_Hint::HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hintCriteria, const Vector &position, float *flNearestDistance, bool bIgnoreLock, bool bIgnoreHintType ) -{ - // Cannot be locked - if ( !bIgnoreLock && IsLocked() ) - { - REPORTFAILURE( "Node is locked." ); - return false; - } - - if ( !bIgnoreHintType && !hintCriteria.MatchesHintType( HintType() ) ) - { - return false; - } - - if ( GetMinState() > NPC_STATE_IDLE || GetMaxState() < NPC_STATE_COMBAT ) - { - if ( pNPC && ( pNPC->GetState() < GetMinState() || pNPC->GetState() > GetMaxState() ) ) - { - REPORTFAILURE( "NPC not in correct state." ); - return false; - } - } - - // See if we're filtering by group name - if ( hintCriteria.GetGroup() != NULL_STRING ) - { - AssertIsValidString( GetGroup() ); - AssertIsValidString( hintCriteria.GetGroup() ); - if ( GetGroup() == NULL_STRING || GetGroup() != hintCriteria.GetGroup() ) - { - Assert(GetGroup() == NULL_STRING || strcmp( STRING(GetGroup()), STRING(hintCriteria.GetGroup())) != 0 ); - REPORTFAILURE( "Doesn't match NPC hint group." ); - return false; - } - } - - // If we're watching for include zones, test it - if ( ( hintCriteria.HasIncludeZones() ) && ( hintCriteria.InIncludedZone( GetAbsOrigin() ) == false ) ) - { - REPORTFAILURE( "Not inside include zones." ); - return false; - } - - // If we're watching for exclude zones, test it - if ( ( hintCriteria.HasExcludeZones() ) && ( hintCriteria.InExcludedZone( GetAbsOrigin() ) ) ) - { - REPORTFAILURE( "Inside exclude zones." ); - return false; - } - - // See if the class handles this hint type - if ( ( pNPC != NULL ) && ( pNPC->FValidateHintType( this ) == false ) ) - { - REPORTFAILURE( "NPC doesn't know how to handle that type." ); - return false; - } - - if ( hintCriteria.HasFlag(bits_HINT_NPC_IN_NODE_FOV) ) - { - if ( pNPC == NULL ) - { - AssertMsg(0,"Hint node attempted to verify NPC in node FOV without NPC!\n"); - } - else - { - if( !IsInNodeFOV(pNPC) ) - { - REPORTFAILURE( "NPC Not in hint's FOV" ); - return false; - } - } - } - - if ( hintCriteria.HasFlag( bits_HINT_NODE_IN_AIMCONE ) ) - { - if ( pNPC == NULL ) - { - AssertMsg( 0, "Hint node attempted to find node in aimcone without specifying NPC!\n" ); - } - else - { - if( !pNPC->FInAimCone( GetAbsOrigin() ) ) - { - REPORTFAILURE( "Hint isn't in NPC's aimcone" ); - return false; - } - } - } - - if ( hintCriteria.HasFlag( bits_HINT_NODE_IN_VIEWCONE ) ) - { - if ( pNPC == NULL ) - { - AssertMsg( 0, "Hint node attempted to find node in viewcone without specifying NPC!\n" ); - } - else - { - if( !pNPC->FInViewCone( this ) ) - { - REPORTFAILURE( "Hint isn't in NPC's viewcone" ); - return false; - } - } - } - - if ( hintCriteria.HasFlag( bits_HINT_NOT_CLOSE_TO_ENEMY ) ) - { - if ( pNPC == NULL ) - { - AssertMsg( 0, "Hint node attempted to find node not close to enemy without specifying NPC!\n" ); - } - else - { - if( pNPC->GetEnemy() ) - { - float flDistHintToEnemySqr = GetAbsOrigin().DistToSqr( pNPC->GetEnemy()->GetAbsOrigin() ) ; - - if( flDistHintToEnemySqr < Square( 30.0f * 12.0f ) ) - { - REPORTFAILURE( "Hint takes NPC close to Enemy" ); - return false; - } - } - } - } - - { - AI_PROFILE_SCOPE( HINT_FVisible ); - // See if we're requesting a visible node - if ( hintCriteria.HasFlag( bits_HINT_NODE_VISIBLE ) ) - { - if ( pNPC == NULL ) - { - //NOTENOTE: If you're hitting this, you've asked for a visible node without specifing an NPC! - AssertMsg( 0, "Hint node attempted to find visible node without specifying NPC!\n" ); - } - else - { - if( m_NodeData.nNodeID == NO_NODE ) - { - // This is just an info_hint, not a node. - if( !pNPC->FVisible( this ) ) - { - REPORTFAILURE( "Hint isn't visible to NPC." ); - return false; - } - } - else - { - // This hint associated with a node. - trace_t tr; - Vector vHintPos; - GetPosition(pNPC,&vHintPos); - AI_TraceLine ( pNPC->EyePosition(), vHintPos + pNPC->GetViewOffset(), MASK_NPCSOLID_BRUSHONLY, pNPC, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction != 1.0f ) - { - REPORTFAILURE( "Node isn't visible to NPC." ); - return false; - } - } - } - } - } - - // Check for clear if requested - if ( hintCriteria.HasFlag( bits_HINT_NODE_CLEAR ) ) - { - if ( pNPC == NULL ) - { - //NOTENOTE: If you're hitting this, you've asked for a clear node without specifing an NPC! - AssertMsg( 0, "Hint node attempted to find clear node without specifying NPC!\n" ); - } - else - { - trace_t tr; - // Can my bounding box fit there? - AI_TraceHull ( GetAbsOrigin(), GetAbsOrigin(), pNPC->WorldAlignMins(), pNPC->WorldAlignMaxs(), - MASK_SOLID, pNPC, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction != 1.0 ) - { - REPORTFAILURE( "Node isn't clear." ); - return false; - } - } - } - - // See if this is our next, closest node - if ( hintCriteria.HasFlag( bits_HINT_NODE_NEAREST ) ) - { - Assert( flNearestDistance ); - - // Calculate our distance - float distance = (GetAbsOrigin() - position).Length(); - - // Must be closer than the current best - if ( distance > *flNearestDistance ) - { - REPORTFAILURE( "Not the nearest node." ); - return false; - } - - // Remember the distance - *flNearestDistance = distance; - } - - if ( hintCriteria.HasFlag(bits_HINT_HAS_LOS_TO_PLAYER|bits_HAS_EYEPOSITION_LOS_TO_PLAYER) ) - { - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - - if( pPlayer != NULL ) - { - Vector vecDest = GetAbsOrigin(); - - if( hintCriteria.HasFlag(bits_HAS_EYEPOSITION_LOS_TO_PLAYER) ) - { - vecDest += pNPC->GetDefaultEyeOffset(); - } - - if( !pPlayer->FVisible(vecDest) ) - { - REPORTFAILURE( "Do not have LOS to player" ); - return false; - } - } - } - - // Must either be visible or not if requested - if ( hintCriteria.HasFlag( bits_HINT_NODE_NOT_VISIBLE_TO_PLAYER|bits_HINT_NODE_VISIBLE_TO_PLAYER ) ) - { - bool bWasSeen = false; - // Test all potential seers - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex(i); - - if ( pPlayer ) - { - // Only spawn if the player's looking away from me - Vector vLookDir = pPlayer->EyeDirection3D(); - Vector vTargetDir = GetAbsOrigin() - pPlayer->EyePosition(); - VectorNormalize(vTargetDir); - - float fDotPr = DotProduct(vLookDir,vTargetDir); - if ( fDotPr > 0 ) - { - trace_t tr; - UTIL_TraceLine( pPlayer->EyePosition(), GetAbsOrigin(), MASK_SOLID_BRUSHONLY, pPlayer, COLLISION_GROUP_NONE, &tr); - - if ( tr.fraction == 1.0 ) - { - if ( hintCriteria.HasFlag( bits_HINT_NODE_NOT_VISIBLE_TO_PLAYER ) ) - { - REPORTFAILURE( "Node is visible to player." ); - return false; - } - bWasSeen = true; - } - } - } - } - - if ( !bWasSeen && hintCriteria.HasFlag( bits_HINT_NODE_VISIBLE_TO_PLAYER ) ) - { - REPORTFAILURE( "Node isn't visible to player." ); - return false; - } - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Input : -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CAI_Hint::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - Q_snprintf(tempstr,sizeof(tempstr),"%s (%i)", GetHintTypeDescription( HintType() ), HintType()); - EntityText(text_offset,tempstr,0); - text_offset++; - Q_snprintf(tempstr,sizeof(tempstr),"delay %f", MAX( 0.0f, m_flNextUseTime - gpGlobals->curtime ) ) ; - EntityText(text_offset,tempstr,0); - text_offset++; - - if ( m_NodeData.iDisabled ) - { - Q_snprintf(tempstr,sizeof(tempstr),"DISABLED" ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - - } - return text_offset; -} - -//----------------------------------------------------------------------------- -// Purpose: Constructor -// Input : -// Output : -//----------------------------------------------------------------------------- -CAI_Hint::CAI_Hint(void) -{ - m_flNextUseTime = 0; - m_nTargetNodeID = NO_NODE; -} - -//----------------------------------------------------------------------------- -// Purpose: Destructor -// Input : -// Output : -//----------------------------------------------------------------------------- -CAI_Hint::~CAI_Hint(void) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: Sometimes FValidateHint, etc. will want to examine the underlying node to -// see if it's truly suitable ( e.g., in the same air/ground network of nodes? ) -// Output : C_AINode * -//----------------------------------------------------------------------------- -CAI_Node *CAI_Hint::GetNode( void ) -{ - if ( m_NodeData.nNodeID != NO_NODE ) - { - return g_pBigAINet->GetNode( m_NodeData.nNodeID, false ); - } - return NULL; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_Hint::DisableForSeconds( float flSeconds ) -{ - Unlock( flSeconds ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_Hint::EnableThink() -{ - SetDisabled( false ); - SetThink( NULL ); -} - -void CAI_Hint::FixupTargetNode() -{ - if ( m_NodeData.nTargetWCNodeID != -1 ) - m_nTargetNodeID = g_pAINetworkManager->GetEditOps()->GetNodeIdFromWCId( m_NodeData.nTargetWCNodeID ); - else - m_nTargetNodeID = NO_NODE; -} - -void CAI_Hint::OnRestore() -{ - BaseClass::OnRestore(); - - m_NodeData.nNodeID = g_pAINetworkManager->GetEditOps()->GetNodeIdFromWCId( m_NodeData.nWCNodeID ); - FixupTargetNode(); - - CAI_Node *pNode = GetNode(); - - if ( !pNode ) - { - if ( m_NodeData.nWCNodeID > 0 ) - DevMsg("Warning: AI hint has incorrect or no AI node\n"); - } - else - { - m_NodeData.vecPosition = pNode->GetOrigin(); - Teleport( &m_NodeData.vecPosition, NULL, NULL ); - pNode->SetHint( this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_Hint::NPCStartedUsing( CAI_BaseNPC *pNPC ) -{ - m_OnNPCStartedUsing.Set( pNPC, pNPC, this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_Hint::NPCStoppedUsing( CAI_BaseNPC *pNPC ) -{ - m_OnNPCStoppedUsing.Set( pNPC, pNPC, this ); -} - - -CON_COMMAND(ai_dump_hints, "") -{ - CAI_HintManager::ValidateHints(); - CAI_HintManager::DumpHints(); -} - - -//----------------------------------------------------------------------------- -// -// hints - these MUST coincide with the HINTS listed under Hint_e -// -//----------------------------------------------------------------------------- -struct hinttypedescs_t -{ - Hint_e iType; - const char *pszDesc; -}; -hinttypedescs_t g_pszHintDescriptions[] = -{ - { HINT_NONE, "None" }, - //{ HINT_NOT_USED_WORLD_DOOR, "Obsolete / Unused" }, - { HINT_WORLD_WINDOW, "World: Window" }, - //{ HINT_NOT_USED_WORLD_BUTTON, "Obsolete / Unused" }, - //{ HINT_NOT_USED_WORLD_MACHINERY, "Obsolete / Unused" }, - //{ HINT_NOT_USED_WORLD_LEDGE, "Obsolete / Unused" }, - //{ HINT_NOT_USED_WORLD_LIGHT_SOURCE, "Obsolete / Unused" }, - //{ HINT_NOT_USED_WORLD_HEAT_SOURCE, "Obsolete / Unused" }, - //{ HINT_NOT_USED_WORLD_BLINKING_LIGHT, "Obsolete / Unused" }, - //{ HINT_NOT_USED_WORLD_BRIGHT_COLORS, "Obsolete / Unused" }, - //{ HINT_NOT_USED_WORLD_HUMAN_BLOOD, "Obsolete / Unused" }, - //{ HINT_NOT_USED_WORLD_ALIEN_BLOOD, "Obsolete / Unused" }, - - { HINT_WORLD_WORK_POSITION, "Act Busy" }, - { HINT_WORLD_VISUALLY_INTERESTING, "World: Visually Interesting" }, - { HINT_WORLD_VISUALLY_INTERESTING_DONT_AIM, "World: Visually Interesting (Don't Aim)" }, - { HINT_WORLD_INHIBIT_COMBINE_MINES, "World: Inhibit Combine Mines" }, - { HINT_WORLD_VISUALLY_INTERESTING_STEALTH, "World: Visually Interesting (Stealth)" }, - - { HINT_TACTICAL_COVER_MED, "Tactical: Cover Medium" }, - { HINT_TACTICAL_COVER_LOW, "Tactical: Cover Low" }, - { HINT_TACTICAL_SPAWN, "Tactical: Spawn" }, - { HINT_TACTICAL_PINCH, "Tactical: Pinch" }, - //{ HINT_NOT_USED_TACTICAL_GUARD, "Obsolete / Unused" }, - { HINT_TACTICAL_ENEMY_DISADVANTAGED, "Tactical: Enemy Disadvantage" }, - //{ HINT_NOT_USED_HEALTH_KIT, "Obsolete / Unused" }, - - //{ HINT_NOT_USED_URBAN_STREETCORNER, "Obsolete / Unused" }, - //{ HINT_NOT_USED_URBAN_STREETLAMP, "Obsolete / Unused" }, - //{ HINT_NOT_USED_URBAN_DARK_SPOT, "Obsolete / Unused" }, - //{ HINT_NOT_USED_URBAN_POSTER, "Obsolete / Unused" }, - //{ HINT_NOT_USED_URBAN_SHELTER, "Obsolete / Unused" }, - - //{ HINT_NOT_USED_ASSASSIN_SECLUDED, "Obsolete / Unused" }, - //{ HINT_NOT_USED_ASSASSIN_RAFTERS, "Obsolete / Unused" }, - //{ HINT_NOT_USED_ASSASSIN_GROUND, "Obsolete / Unused" }, - //{ HINT_NOT_USED_ASSASSIN_MONKEYBARS, "Obsolete / Unused" }, - - { HINT_ANTLION_BURROW_POINT, "Antlion: Burrow Point" }, - { HINT_ANTLION_THUMPER_FLEE_POINT, "Antlion: Thumper Flee Point" }, - - //{ HINT_HEADCRAB_BURROW_POINT, "Obsolete / Unused" }, - - //{ HINT_NOT_USED_ROLLER_PATROL_POINT, "Obsolete / Unused" }, - //{ HINT_NOT_USED_ROLLER_CLEANUP_POINT, "Obsolete / Unused" }, - - //{ HINT_NOT_USED_PSTORM_ROCK_SPAWN, "Obsolete / Unused" }, - - { HINT_CROW_FLYTO_POINT, "Crow: Flyto Point" }, - - //{ HINT_BUG_PATROL_POINT, "Obsolete / Unused" }, - - { HINT_FOLLOW_WAIT_POINT, "Follow: Wait Point" }, - { HINT_JUMP_OVERRIDE, "Jump Override" }, - { HINT_PLAYER_SQUAD_TRANSITON_POINT, "Squad Transition Point" }, - { HINT_NPC_EXIT_POINT, "Act Busy: Exit Point" }, - { HINT_STRIDER_NODE, "Strider" }, - - { HINT_PLAYER_ALLY_MOVE_AWAY_DEST, "Ally MoveAway Point" }, - - { HINT_HL1_WORLD_MACHINERY, "HL1: World: Machinery" }, - { HINT_HL1_WORLD_BLINKING_LIGHT, "HL1: World: Blinking Light" }, - { HINT_HL1_WORLD_HUMAN_BLOOD, "HL1: World: Human Blood" }, - { HINT_HL1_WORLD_ALIEN_BLOOD, "HL1: World: Alien Blood" }, - - { HINT_CSTRIKE_HOSTAGE_ESCAPE, "CS Port: Hostage Escape" }, -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const char *GetHintTypeDescription( Hint_e iHintType ) -{ - for ( size_t i = 0; i < ARRAYSIZE(g_pszHintDescriptions); i++ ) - { - if ( g_pszHintDescriptions[i].iType == iHintType ) - return g_pszHintDescriptions[i].pszDesc; - } - - return "Obsolete / Unused"; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const char *GetHintTypeDescription( CAI_Hint *pHint ) -{ - return GetHintTypeDescription( pHint->HintType() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Debug command to drop hints into the world -//----------------------------------------------------------------------------- -void CC_ai_drop_hint( const CCommand &args ) -{ - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - if ( !pPlayer ) - return; - - if ( args.ArgC() < 2 ) - { - Msg("Invalid hint type specified. Format: ai_drop_hint \nValid hint types:\n"); - - for ( size_t i = 0; i < ARRAYSIZE(g_pszHintDescriptions); i++ ) - { - Msg("%d : %s\n", g_pszHintDescriptions[i].iType, g_pszHintDescriptions[i].pszDesc ); - } - return; - } - - HintNodeData nodeData; - nodeData.strEntityName = MAKE_STRING("ai_drop_hint"); - nodeData.vecPosition = pPlayer->EyePosition(); - nodeData.nHintType = atoi( args[1] ); - nodeData.nNodeID = NO_NODE; - nodeData.strGroup = NULL_STRING; - nodeData.iDisabled = false; - nodeData.iszActivityName = NULL_STRING; - nodeData.fIgnoreFacing = HIF_DEFAULT; - nodeData.minState = NPC_STATE_IDLE; - nodeData.maxState = NPC_STATE_COMBAT; - CAI_Hint *pHint = CAI_HintManager::CreateHint( &nodeData, NULL ); - if ( pHint ) - { - ((CBaseEntity *)pHint)->Activate(); - pHint->KeyValue( "nodeFOV", "360" ); - pHint->m_debugOverlays |= (OVERLAY_TEXT_BIT | OVERLAY_BBOX_BIT); - } -} -ConCommand ai_drop_hint( "ai_drop_hint", CC_ai_drop_hint, "Drop an ai_hint at the player's current eye position.", FCVAR_CHEAT ); diff --git a/game/server/ai_hint.h b/game/server/ai_hint.h deleted file mode 100644 index df0c87b09..000000000 --- a/game/server/ai_hint.h +++ /dev/null @@ -1,341 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Hint node utilities and functions. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_HINT_H -#define AI_HINT_H -#pragma once - -#include "ai_initutils.h" -#include "tier1/utlmap.h" - -//Flags for FindHintNode -#define bits_HINT_NODE_NONE 0x00000000 -#define bits_HINT_NODE_VISIBLE 0x00000001 -#define bits_HINT_NODE_NEAREST 0x00000002 // Choose the node nearest me -#define bits_HINT_NODE_RANDOM 0x00000004 // Find a random hintnode meeting other criteria -#define bits_HINT_NODE_CLEAR 0x00000008 // Only choose nodes that have clear room for my bounding box (requires NPC) -#define bits_HINT_NODE_USE_GROUP 0x00000010 // Use the NPC's hintgroup when searching for a node (requires NPC) -#define bits_HINT_NODE_VISIBLE_TO_PLAYER 0x00000020 -#define bits_HINT_NODE_NOT_VISIBLE_TO_PLAYER 0x00000040 -#define bits_HINT_NODE_REPORT_FAILURES 0x00000080 -#define bits_HINT_NODE_IN_VIEWCONE 0x00000100 -#define bits_HINT_NODE_IN_AIMCONE 0x00000200 -#define bits_HINT_NPC_IN_NODE_FOV 0x00000400 // Is the searcher inside the hint node's FOV? -#define bits_HINT_NOT_CLOSE_TO_ENEMY 0x00000800 // Hint must not be within 30 feet of my enemy -#define bits_HINT_HAS_LOS_TO_PLAYER 0x00001000 // Like VISIBLE_TO_PLAYER but doesn't care about player's facing -#define bits_HAS_EYEPOSITION_LOS_TO_PLAYER 0x00002000 // Like HAS LOS TO PLAYER, but checks NPC's eye position at the node, not node origin. - -//----------------------------------------------------------------------------- -// -// hints - these MUST coincide with the HINTS listed under -// info_node in the FGD file! -// -// For debugging, they must also coincide with g_pszHintDescriptions. -// -//----------------------------------------------------------------------------- -enum Hint_e -{ - HINT_ANY = -1, - HINT_NONE = 0, - HINT_NOT_USED_WORLD_DOOR, - HINT_WORLD_WINDOW, - HINT_NOT_USED_WORLD_BUTTON, - HINT_NOT_USED_WORLD_MACHINERY, - HINT_NOT_USED_WORLD_LEDGE, - HINT_NOT_USED_WORLD_LIGHT_SOURCE, - HINT_NOT_USED_WORLD_HEAT_SOURCE, - HINT_NOT_USED_WORLD_BLINKING_LIGHT, - HINT_NOT_USED_WORLD_BRIGHT_COLORS, - HINT_NOT_USED_WORLD_HUMAN_BLOOD, - HINT_NOT_USED_WORLD_ALIEN_BLOOD, - - HINT_WORLD_WORK_POSITION, - HINT_WORLD_VISUALLY_INTERESTING, - HINT_WORLD_VISUALLY_INTERESTING_DONT_AIM, - HINT_WORLD_INHIBIT_COMBINE_MINES, - HINT_WORLD_VISUALLY_INTERESTING_STEALTH, - - HINT_TACTICAL_COVER_MED = 100, - HINT_TACTICAL_COVER_LOW, - HINT_TACTICAL_SPAWN, - HINT_TACTICAL_PINCH, // Exit / entrance to an arena - HINT_NOT_USED_TACTICAL_GUARD, - HINT_TACTICAL_ENEMY_DISADVANTAGED, //Disadvantageous position for the enemy - HINT_NOT_USED_HEALTH_KIT, - - HINT_NOT_USED_URBAN_STREETCORNER = 200, - HINT_NOT_USED_URBAN_STREETLAMP, - HINT_NOT_USED_URBAN_DARK_SPOT, - HINT_NOT_USED_URBAN_POSTER, - HINT_NOT_USED_URBAN_SHELTER, - - HINT_NOT_USED_ASSASSIN_SECLUDED = 300, - HINT_NOT_USED_ASSASSIN_RAFTERS, - HINT_NOT_USED_ASSASSIN_GROUND, - HINT_NOT_USED_ASSASSIN_MONKEYBARS, - - HINT_ANTLION_BURROW_POINT = 400, - HINT_ANTLION_THUMPER_FLEE_POINT, - - HINT_HEADCRAB_BURROW_POINT = 450, - HINT_HEADCRAB_EXIT_POD_POINT, - - HINT_NOT_USED_ROLLER_PATROL_POINT = 500, - HINT_NOT_USED_ROLLER_CLEANUP_POINT, - - HINT_NOT_USED_PSTORM_ROCK_SPAWN = 600, - - HINT_CROW_FLYTO_POINT = 700, - - // TF2 Hints - HINT_BUG_PATROL_POINT = 800, - - // HL2 Hints - HINT_FOLLOW_WAIT_POINT = 900, - HINT_JUMP_OVERRIDE = 901, - HINT_PLAYER_SQUAD_TRANSITON_POINT = 902, - HINT_NPC_EXIT_POINT = 903, - HINT_STRIDER_NODE = 904, - - HINT_PLAYER_ALLY_MOVE_AWAY_DEST = 950, - HINT_PLAYER_ALLY_FEAR_DEST, - - // HL1 port hints - HINT_HL1_WORLD_MACHINERY = 1000, - HINT_HL1_WORLD_BLINKING_LIGHT, - HINT_HL1_WORLD_HUMAN_BLOOD, - HINT_HL1_WORLD_ALIEN_BLOOD, - - // CS port hints - HINT_CSTRIKE_HOSTAGE_ESCAPE = 1100, -}; -const char *GetHintTypeDescription( Hint_e iHintType ); -const char *GetHintTypeDescription( CAI_Hint *pHint ); - -//----------------------------------------------------------------------------- -// CHintCriteria -//----------------------------------------------------------------------------- - -class CHintCriteria -{ -public: - - CHintCriteria(); - ~CHintCriteria(); - - bool HasFlag( int bitmask ) const { return ( m_iFlags & bitmask ) != 0; } - void SetFlag( int bitmask ); - void ClearFlag( int bitmask ); - - void SetGroup( string_t group ); - string_t GetGroup( void ) const { return m_strGroup; } - - int GetFirstHintType( void ) const { return m_iFirstHintType; } - int GetLastHintType( void ) const { return m_iLastHintType; } - bool MatchesHintType( int hintType ) const; - bool MatchesSingleHintType() const; - - bool HasIncludeZones( void ) const { return ( m_zoneInclude.Count() != 0 ); } - bool HasExcludeZones( void ) const { return ( m_zoneExclude.Count() != 0 ); } - - void AddIncludePosition( const Vector &position, float radius ); - void AddExcludePosition( const Vector &position, float radius ); - void SetHintType( int hintType ); - void SetHintTypeRange( int firstType, int lastType ); - void AddHintType( int hintType ); - - bool InIncludedZone( const Vector &testPosition ) const; - bool InExcludedZone( const Vector &testPosition ) const; - - int NumHintTypes() const; - int GetHintType( int idx ) const; - -private: - - struct hintZone_t - { - Vector position; - float radiussqr; - }; - - typedef CUtlVector < hintZone_t > zoneList_t; - - void AddZone( zoneList_t &list, const Vector &position, float radius ); - bool InZone( const zoneList_t &zone, const Vector &testPosition ) const; - - CUtlVector m_HintTypes; - - int m_iFlags; - int m_iFirstHintType; - int m_iLastHintType; - string_t m_strGroup; - - zoneList_t m_zoneInclude; - zoneList_t m_zoneExclude; -}; - -class CAI_Node; - -//----------------------------------------------------------------------------- -// CAI_HintManager -//----------------------------------------------------------------------------- - -DECLARE_POINTER_HANDLE(AIHintIter_t); - -class CAIHintVector : public CUtlVector< CAI_Hint * > -{ -public: - CAIHintVector() : CUtlVector< CAI_Hint * >( 1, 0 ) - { - } - - CAIHintVector( const CAIHintVector& src ) - { - CopyArray( src.Base(), src.Count() ); - } - - CAIHintVector &operator=( const CAIHintVector &src ) - { - CopyArray( src.Base(), src.Count() ); - return *this; - } -}; - -class CAI_HintManager -{ - friend class CAI_Hint; -public: - // Hint node creation - static CAI_Hint *CreateHint( HintNodeData *pNodeData, const char *pMapData = NULL ); - static void DrawHintOverlays(float flDrawDuration); - - static void AddHint( CAI_Hint *pTestHint ); - static void RemoveHint( CAI_Hint *pTestHint ); - static void AddHintByType( CAI_Hint *pHint ); - static void RemoveHintByType( CAI_Hint *pHintToRemove ); - - // Interface for searching the hint node list - static CAI_Hint *FindHint( CAI_BaseNPC *pNPC, const Vector &position, const CHintCriteria &hintCriteria ); - static CAI_Hint *FindHint( CAI_BaseNPC *pNPC, const CHintCriteria &hintCriteria ); - static CAI_Hint *FindHint( const Vector &position, const CHintCriteria &hintCriteria ); - static CAI_Hint *FindHint( CAI_BaseNPC *pNPC, Hint_e nHintType, int nFlags, float flMaxDist, const Vector *pMaxDistFrom = NULL ); - - // Purpose: Finds a random suitable hint within the requested radious of the npc - static CAI_Hint *FindHintRandom( CAI_BaseNPC *pNPC, const Vector &position, const CHintCriteria &hintCriteria ); - static int FindAllHints( CAI_BaseNPC *pNPC, const Vector &position, const CHintCriteria &hintCriteria, CUtlVector *pResult ); - static int FindAllHints( const Vector &position, const CHintCriteria &hintCriteria, CUtlVector *pResult ) { return FindAllHints( NULL, position, hintCriteria, pResult ); } - static int FindAllHints( CAI_BaseNPC *pNPC, const CHintCriteria &hintCriteria, CUtlVector *pResult ) { return FindAllHints( pNPC, pNPC->GetAbsOrigin(), hintCriteria, pResult ); } - static int GetFlags( const char *token ); - - static CAI_Hint *GetFirstHint( AIHintIter_t *pIter ); - static CAI_Hint *GetNextHint( AIHintIter_t *pIter ); - - static void DumpHints(); - - static void ValidateHints(); - -private: - enum - { - // MUST BE POWER OF 2 - HINT_HISTORY = (1<<3), - HINT_HISTORY_MASK = (HINT_HISTORY-1) - }; - - static CAI_Hint *AddFoundHint( CAI_Hint *hint ); - static int GetFoundHintCount(); - static CAI_Hint *GetFoundHint( int index ); - static CAI_Hint *GetLastFoundHint(); - static void ResetFoundHints(); - static bool IsInFoundHintList( CAI_Hint *hint ); - - static int gm_nFoundHintIndex; - static CAI_Hint *gm_pLastFoundHints[ HINT_HISTORY ]; // Last used hint - static CAIHintVector gm_AllHints; // A linked list of all hints - static CUtlMap< int, CAIHintVector > gm_TypedHints; -}; - -//----------------------------------------------------------------------------- -// CAI_Hint -//----------------------------------------------------------------------------- - -class CAI_Hint : public CServerOnlyEntity -{ - DECLARE_CLASS( CAI_Hint, CServerOnlyEntity ); -public: - CAI_Hint( void ); - ~CAI_Hint( void ); - - // Interface for specific nodes - bool Lock( CBaseEntity *pNPC ); // Makes unavailable for hints - void Unlock( float delay = 0.0 ); // Makes available for hints after delay - bool IsLocked(void); // Whether this node is available for use. - bool IsLockedBy( CBaseEntity *pNPC ); // Whether this node is available for use. - void GetPosition(CBaseCombatCharacter *pBCC, Vector *vPosition); - void GetPosition( Hull_t hull, Vector *vPosition ); - Vector GetDirection( void ); - float Yaw( void ); - CAI_Node *GetNode( void ); - string_t GetGroup( void ) const { return m_NodeData.strGroup; } - CBaseEntity *User( void ) const { return m_hHintOwner; }; - Hint_e HintType( void ) const { return (Hint_e)m_NodeData.nHintType; }; - void SetHintType( int hintType, bool force = false ); - string_t HintActivityName( void ) const { return m_NodeData.iszActivityName; } - int GetTargetNode( void ) const { return m_nTargetNodeID; } - bool IsDisabled( void ) const { return (m_NodeData.iDisabled != 0); } - void SetDisabled( bool bDisabled ) { m_NodeData.iDisabled = bDisabled; } - void DisableForSeconds( float flSeconds ); - void EnableThink(); - void FixupTargetNode(); - void NPCStartedUsing( CAI_BaseNPC *pNPC ); - void NPCStoppedUsing( CAI_BaseNPC *pNPC ); - - HintIgnoreFacing_t GetIgnoreFacing() const { return m_NodeData.fIgnoreFacing; } - - NPC_STATE GetMinState() const { return m_NodeData.minState; } - NPC_STATE GetMaxState() const { return m_NodeData.maxState; } - - int GetNodeId() { return m_NodeData.nNodeID; } - int GetWCId() { return m_NodeData.nWCNodeID; } - - bool HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hintCriteria, const Vector &position, float *flNearestDistance, bool bIgnoreLock = false, bool bIgnoreHintType = false ); - bool IsInNodeFOV( CBaseEntity *pOther ); - -private: - void Spawn( void ); - virtual void Activate(); - virtual void UpdateOnRemove( void ); - int DrawDebugTextOverlays(void); - virtual int ObjectCaps( void ) { return (BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION); } - virtual void OnRestore(); - bool IsViewable( void ); - - // Input handlers - void InputEnableHint( inputdata_t &inputdata ); - void InputDisableHint( inputdata_t &inputdata ); - -private: - - HintNodeData m_NodeData; - int m_nTargetNodeID; - EHANDLE m_hHintOwner; // Is hint locked (being used by NPC / NPC en-route to use it) - float m_flNextUseTime; // When can I be used again? - COutputEHANDLE m_OnNPCStartedUsing; // Triggered when an NPC has actively begun to use the node. - COutputEHANDLE m_OnNPCStoppedUsing; // Triggered when an NPC has finished using this node. - float m_nodeFOV; - Vector m_vecForward; - - // The next hint in list of all hints - friend class CAI_HintManager; - - DECLARE_DATADESC(); -}; - -#define SF_ALLOW_JUMP_UP 65536 - - -#endif //AI_HINT_H diff --git a/game/server/ai_hull.cpp b/game/server/ai_hull.cpp deleted file mode 100644 index fab1c9735..000000000 --- a/game/server/ai_hull.cpp +++ /dev/null @@ -1,185 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -//=============================================================================// - -#include "cbase.h" -#include "ai_hull.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -struct ai_hull_t -{ - ai_hull_t( int bit, const char *pName, const Vector &_mins, const Vector &_maxs, const Vector &_smallMins, const Vector &_smallMaxs ) - : hullBit( bit ), name( pName ), mins( _mins ), maxs( _maxs ), smallMins( _smallMins ), smallMaxs( _smallMaxs ) {} - int hullBit; - const char* name; - - Vector mins; - Vector maxs; - - Vector smallMins; - Vector smallMaxs; -}; - -//================================================================================= -// Create the hull types here. -//================================================================================= -#ifdef HL1_DLL -ai_hull_t Human_Hull (bits_HUMAN_HULL, "HUMAN_HULL", Vector(-13,-13, 0), Vector(13, 13, 72), Vector(-8,-8, 0), Vector( 8, 8, 72) ); -ai_hull_t Small_Centered_Hull (bits_SMALL_CENTERED_HULL, "SMALL_CENTERED_HULL", Vector(-20,-20, -20), Vector(20, 20, 20), Vector(-12,-12,-12), Vector(12, 12, 12) ); -ai_hull_t Wide_Human_Hull (bits_WIDE_HUMAN_HULL, "WIDE_HUMAN_HULL", Vector(-32,-32, 0), Vector(32, 32, 72), Vector(-10,-10, 0), Vector(10, 10, 72) ); -ai_hull_t Tiny_Hull (bits_TINY_HULL, "TINY_HULL", Vector(-12,-12, 0), Vector(12, 12, 24), Vector(-12,-12, 0), Vector(12, 12, 24) ); -ai_hull_t Wide_Short_Hull (bits_WIDE_SHORT_HULL, "WIDE_SHORT_HULL", Vector(-35,-35, 0), Vector(35, 35, 32), Vector(-20,-20, 0), Vector(20, 20, 32) ); -ai_hull_t Medium_Hull (bits_MEDIUM_HULL, "MEDIUM_HULL", Vector(-16,-16, 0), Vector(16, 16, 64), Vector(-8,-8, 0), Vector(8, 8, 64) ); -ai_hull_t Tiny_Centered_Hull (bits_TINY_CENTERED_HULL, "TINY_CENTERED_HULL", Vector(-8, -8, -4), Vector(8, 8, 4), Vector(-8,-8, -4), Vector( 8, 8, 4) ); -ai_hull_t Large_Hull (bits_LARGE_HULL, "LARGE_HULL", Vector(-40,-40, 0), Vector(40, 40, 100), Vector(-40,-40, 0), Vector(40, 40, 100) ); -ai_hull_t Large_Centered_Hull (bits_LARGE_CENTERED_HULL, "LARGE_CENTERED_HULL", Vector(-38,-38, -38), Vector(38, 38, 38), Vector(-30,-30,-30), Vector(30, 30, 30) ); -ai_hull_t Medium_Tall_Hull (bits_MEDIUM_TALL_HULL, "MEDIUM_TALL_HULL", Vector(-18,-18, 0), Vector(18, 18, 100), Vector(-12,-12, 0), Vector(12, 12, 100) ); -#else -ai_hull_t Human_Hull (bits_HUMAN_HULL, "HUMAN_HULL", Vector(-13,-13, 0), Vector(13, 13, 72), Vector(-8,-8, 0), Vector( 8, 8, 72) ); -ai_hull_t Small_Centered_Hull (bits_SMALL_CENTERED_HULL, "SMALL_CENTERED_HULL", Vector(-20,-20, -20), Vector(20, 20, 20), Vector(-12,-12,-12), Vector(12, 12, 12) ); -ai_hull_t Wide_Human_Hull (bits_WIDE_HUMAN_HULL, "WIDE_HUMAN_HULL", Vector(-15,-15, 0), Vector(15, 15, 72), Vector(-10,-10, 0), Vector(10, 10, 72) ); -ai_hull_t Tiny_Hull (bits_TINY_HULL, "TINY_HULL", Vector(-12,-12, 0), Vector(12, 12, 24), Vector(-12,-12, 0), Vector(12, 12, 24) ); -ai_hull_t Wide_Short_Hull (bits_WIDE_SHORT_HULL, "WIDE_SHORT_HULL", Vector(-35,-35, 0), Vector(35, 35, 32), Vector(-20,-20, 0), Vector(20, 20, 32) ); -ai_hull_t Medium_Hull (bits_MEDIUM_HULL, "MEDIUM_HULL", Vector(-16,-16, 0), Vector(16, 16, 64), Vector(-8,-8, 0), Vector(8, 8, 64) ); -ai_hull_t Tiny_Centered_Hull (bits_TINY_CENTERED_HULL, "TINY_CENTERED_HULL", Vector(-8, -8, -4), Vector(8, 8, 4), Vector(-8,-8, -4), Vector( 8, 8, 4) ); -ai_hull_t Large_Hull (bits_LARGE_HULL, "LARGE_HULL", Vector(-40,-40, 0), Vector(40, 40, 100), Vector(-40,-40, 0), Vector(40, 40, 100) ); -ai_hull_t Large_Centered_Hull (bits_LARGE_CENTERED_HULL, "LARGE_CENTERED_HULL", Vector(-38,-38, -38), Vector(38, 38, 38), Vector(-30,-30,-30), Vector(30, 30, 30) ); -ai_hull_t Medium_Tall_Hull (bits_MEDIUM_TALL_HULL, "MEDIUM_TALL_HULL", Vector(-18,-18, 0), Vector(18, 18, 100), Vector(-12,-12, 0), Vector(12, 12, 100) ); -#endif//HL1_DLL - -// -// Array of hulls. These hulls must correspond with the enumerations in AI_Hull.h! -// -ai_hull_t* hull[NUM_HULLS] = -{ - &Human_Hull, - &Small_Centered_Hull, - &Wide_Human_Hull, - &Tiny_Hull, - &Wide_Short_Hull, - &Medium_Hull, - &Tiny_Centered_Hull, - &Large_Hull, - &Large_Centered_Hull, - &Medium_Tall_Hull, -}; - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -const Vector &NAI_Hull::Mins(int id) -{ - return hull[id]->mins; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -const Vector &NAI_Hull::Maxs(int id) -{ - return hull[id]->maxs; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -const Vector &NAI_Hull::SmallMins(int id) -{ - return hull[id]->smallMins; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -const Vector &NAI_Hull::SmallMaxs(int id) -{ - return hull[id]->smallMaxs; -} - -//----------------------------------------------------------------------------- -// Purpose: - -// Input : -// Output : -//----------------------------------------------------------------------------- -float NAI_Hull::Length(int id) -{ - return (hull[id]->maxs.x - hull[id]->mins.x); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -float NAI_Hull::Width(int id) -{ - return (hull[id]->maxs.y - hull[id]->mins.y); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -float NAI_Hull::Height(int id) -{ - return (hull[id]->maxs.z - hull[id]->mins.z); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int NAI_Hull::Bits(int id) -{ - return hull[id]->hullBit; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -const char *NAI_Hull::Name(int id) -{ - return hull[id]->name; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -Hull_t NAI_Hull::LookupId(const char *szName) -{ - int i; - if (!szName) - { - return HULL_HUMAN; - } - for (i = 0; i < NUM_HULLS; i++) - { - if (stricmp( szName, NAI_Hull::Name( i )) == 0) - { - return (Hull_t)i; - } - } - return HULL_HUMAN; -} - - - diff --git a/game/server/ai_hull.h b/game/server/ai_hull.h deleted file mode 100644 index 44605fe7a..000000000 --- a/game/server/ai_hull.h +++ /dev/null @@ -1,75 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -//=============================================================================// - -#ifndef AI_HULL_H -#define AI_HULL_H -#pragma once - -class Vector; -//========================================================= -// Link Properties. These hulls must correspond to the hulls -// in AI_Hull.cpp! -//========================================================= -enum Hull_t -{ - HULL_HUMAN, // Combine, Stalker, Zombie... - HULL_SMALL_CENTERED, // Scanner - HULL_WIDE_HUMAN, // Vortigaunt - HULL_TINY, // Headcrab - HULL_WIDE_SHORT, // Bullsquid - HULL_MEDIUM, // Cremator - HULL_TINY_CENTERED, // Manhack - HULL_LARGE, // Antlion Guard - HULL_LARGE_CENTERED, // Mortar Synth - HULL_MEDIUM_TALL, // Hunter -//-------------------------------------------- - NUM_HULLS, - HULL_NONE // No Hull (appears after num hulls as we don't want to count it) -}; - -enum Hull_Bits_t -{ - bits_HUMAN_HULL = 0x00000001, - bits_SMALL_CENTERED_HULL = 0x00000002, - bits_WIDE_HUMAN_HULL = 0x00000004, - bits_TINY_HULL = 0x00000008, - bits_WIDE_SHORT_HULL = 0x00000010, - bits_MEDIUM_HULL = 0x00000020, - bits_TINY_CENTERED_HULL = 0x00000040, - bits_LARGE_HULL = 0x00000080, - bits_LARGE_CENTERED_HULL = 0x00000100, - bits_MEDIUM_TALL_HULL = 0x00000200, - bits_HULL_BITS_MASK = 0x000002ff, -}; - -inline int HullToBit( Hull_t hull ) -{ - return ( 1 << hull ); -} - - - -//============================================================================= -// >> CAI_Hull -//============================================================================= -namespace NAI_Hull -{ - const Vector &Mins(int id); - const Vector &Maxs(int id); - - const Vector &SmallMins(int id); - const Vector &SmallMaxs(int id); - - float Length(int id); - float Width(int id); - float Height(int id); - - int Bits(int id); - - const char* Name(int id); - - Hull_t LookupId(const char *szName); -}; - -#endif // AI_HULL_H diff --git a/game/server/ai_initutils.cpp b/game/server/ai_initutils.cpp deleted file mode 100644 index 5d5d53c77..000000000 --- a/game/server/ai_initutils.cpp +++ /dev/null @@ -1,342 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: AI Utility classes for building the initial AI Networks -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ai_node.h" -#include "ai_hull.h" -#include "ai_hint.h" -#include "ai_initutils.h" -#include "ai_networkmanager.h" - -// to help eliminate node clutter by level designers, this is used to cap how many other nodes -// any given node is allowed to 'see' in the first stage of graph creation "LinkVisibleNodes()". - -#include "ai_network.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -LINK_ENTITY_TO_CLASS( info_hint, CNodeEnt ); -LINK_ENTITY_TO_CLASS( info_node, CNodeEnt ); -LINK_ENTITY_TO_CLASS( info_node_hint, CNodeEnt ); -LINK_ENTITY_TO_CLASS( info_node_air, CNodeEnt ); -LINK_ENTITY_TO_CLASS( info_node_air_hint, CNodeEnt ); -LINK_ENTITY_TO_CLASS( info_node_climb, CNodeEnt ); -LINK_ENTITY_TO_CLASS( aitesthull, CAI_TestHull ); - -//----------------------------------------------------------------------------- -// Init static variables -//----------------------------------------------------------------------------- -CAI_TestHull* CAI_TestHull::pTestHull = NULL; - -#ifdef CSTRIKE_DLL -#define PLAYER_MODEL "models/player/ct_urban.mdl" -#else -#define PLAYER_MODEL "models/player.mdl" -#endif - -//----------------------------------------------------------------------------- -// Purpose: Make sure we have a "player.mdl" hull to test with -//----------------------------------------------------------------------------- -void CAI_TestHull::Precache() -{ - BaseClass::Precache(); - PrecacheModel( PLAYER_MODEL ); -} - -//========================================================= -// CAI_TestHull::Spawn -//========================================================= -void CAI_TestHull::Spawn(void) -{ - Precache(); - - SetModel( PLAYER_MODEL ); - - // Set an initial hull size (this will change later) - SetHullType(HULL_HUMAN); - SetHullSizeNormal(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_SOLID ); - - SetMoveType( MOVETYPE_STEP ); - m_iHealth = 50; - - bInUse = false; - - // Make this invisible - AddEffects( EF_NODRAW ); -} - -//----------------------------------------------------------------------------- -// Purpose: Get the test hull (create if none) -// Input : -// Output : -//----------------------------------------------------------------------------- -CAI_TestHull* CAI_TestHull::GetTestHull(void) -{ - if (!CAI_TestHull::pTestHull) - { - CAI_TestHull::pTestHull = CREATE_ENTITY( CAI_TestHull, "aitesthull" ); - CAI_TestHull::pTestHull->Spawn(); - CAI_TestHull::pTestHull->AddFlag( FL_NPC ); - } - - if (CAI_TestHull::pTestHull->bInUse == true) - { - DevMsg("WARNING: TestHull used and never returned!\n"); - Assert( 0 ); - } - - CAI_TestHull::pTestHull->RemoveSolidFlags( FSOLID_NOT_SOLID ); - CAI_TestHull::pTestHull->bInUse = true; - - return CAI_TestHull::pTestHull; -} - -//----------------------------------------------------------------------------- -// Purpose: Get the test hull (create if none) -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_TestHull::ReturnTestHull(void) -{ - CAI_TestHull::pTestHull->bInUse = false; - CAI_TestHull::pTestHull->AddSolidFlags( FSOLID_NOT_SOLID ); - UTIL_SetSize(CAI_TestHull::pTestHull, vec3_origin, vec3_origin); - - UTIL_RemoveImmediate( pTestHull ); - pTestHull = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &startPos - -// &endPos - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_TestHull::IsJumpLegal(const Vector &startPos, const Vector &apex, const Vector &endPos) const -{ - const float MAX_JUMP_RISE = 1024.0f; - const float MAX_JUMP_DISTANCE = 1024.0f; - const float MAX_JUMP_DROP = 1024.0f; - - return BaseClass::IsJumpLegal( startPos, apex, endPos, MAX_JUMP_RISE, MAX_JUMP_DISTANCE, MAX_JUMP_DROP ); -} -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -CAI_TestHull::~CAI_TestHull(void) -{ - CAI_TestHull::pTestHull = NULL; -} - -//########################################################### -// > CNodeEnt -// -// nodes start out as ents in the world. As they are spawned, -// the node info is recorded then the ents are discarded. -//########################################################### - -//---------------------------------------------------- -// Static vars -//---------------------------------------------------- -int CNodeEnt::m_nNodeCount = 0; - -// ------------- -// Data table -// ------------- -BEGIN_SIMPLE_DATADESC( HintNodeData ) - - DEFINE_FIELD( strEntityName, FIELD_STRING ), - // DEFINE_FIELD( vecPosition, FIELD_VECTOR ), // Don't save - DEFINE_KEYFIELD( nHintType, FIELD_SHORT, "hinttype" ), - DEFINE_KEYFIELD( strGroup, FIELD_STRING, "Group" ), - DEFINE_KEYFIELD( iDisabled, FIELD_INTEGER, "StartHintDisabled" ), - DEFINE_FIELD( nNodeID, FIELD_INTEGER ), - DEFINE_KEYFIELD( iszActivityName, FIELD_STRING, "hintactivity" ), - DEFINE_KEYFIELD( nTargetWCNodeID, FIELD_INTEGER, "TargetNode" ), - DEFINE_KEYFIELD( nWCNodeID, FIELD_INTEGER, "nodeid" ), - DEFINE_KEYFIELD( fIgnoreFacing, FIELD_INTEGER, "IgnoreFacing" ), - DEFINE_KEYFIELD( minState, FIELD_INTEGER, "MinimumState" ), - DEFINE_KEYFIELD( maxState, FIELD_INTEGER, "MaximumState" ), - -END_DATADESC() - -// ------------- -// Data table -// ------------- -BEGIN_DATADESC( CNodeEnt ) - - DEFINE_EMBEDDED( m_NodeData ), - -END_DATADESC() - -//========================================================= -//========================================================= -void CNodeEnt::Spawn( void ) -{ - Spawn( NULL ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pMapData - -//----------------------------------------------------------------------------- -int CNodeEnt::Spawn( const char *pMapData ) -{ - m_NodeData.strEntityName = GetEntityName(); - m_NodeData.vecPosition = GetAbsOrigin(); - m_NodeData.nNodeID = NO_NODE; - if ( m_NodeData.minState == NPC_STATE_NONE ) - m_NodeData.minState = NPC_STATE_IDLE; - if ( m_NodeData.maxState == NPC_STATE_NONE ) - m_NodeData.maxState = NPC_STATE_COMBAT; - // --------------------------------------------------------------------------------- - // If just a hint node (not used for navigation) just create a hint and bail - // --------------------------------------------------------------------------------- - if (FClassnameIs( this, "info_hint" )) - { - if (m_NodeData.nHintType) - { - CAI_HintManager::CreateHint( &m_NodeData, pMapData ); - } - else - { - Warning("info_hint (HammerID: %d, position (%.2f, %.2f, %.2f)) with no hint type.\n", m_NodeData.nWCNodeID, m_NodeData.vecPosition.x, m_NodeData.vecPosition.y, m_NodeData.vecPosition.z ); - } - UTIL_RemoveImmediate( this ); - return -1; - } - - // --------------------------------------------------------------------------------- - // First check if this node has a hint. If so create a hint entity - // --------------------------------------------------------------------------------- - CAI_Hint *pHint = NULL; - - if ( ClassMatches( "info_node_hint" ) || ClassMatches( "info_node_air_hint" ) ) - { - if ( m_NodeData.nHintType || m_NodeData.strGroup != NULL_STRING || m_NodeData.strEntityName != NULL_STRING ) - { - m_NodeData.nNodeID = m_nNodeCount; - pHint = CAI_HintManager::CreateHint( &m_NodeData, pMapData ); - pHint->AddSpawnFlags( GetSpawnFlags() ); - } - } - - - // --------------------------------------------------------------------------------- - // If we loaded from disk, we can discard all these node ents as soon as they spawn - // unless we are in WC edited mode - // --------------------------------------------------------------------------------- - if ( g_pAINetworkManager->NetworksLoaded() && !engine->IsInEditMode()) - { - // If hint exists for this node, set it - if (pHint) - { - CAI_Node *pNode = g_pBigAINet->GetNode(m_nNodeCount); - if (pNode) - pNode->SetHint( pHint ); - else - { - DevMsg("AI node graph corrupt\n"); - } - } - m_nNodeCount++; - UTIL_RemoveImmediate( this ); - return -1; - } - else - { - m_nNodeCount++; - } - - // --------------------------------------------------------------------------------- - // Add a new node to the network - // --------------------------------------------------------------------------------- - // For now just using one big AI network - CAI_Node *new_node = g_pBigAINet->AddNode( GetAbsOrigin(), GetAbsAngles().y ); - new_node->SetHint( pHint ); - - // ------------------------------------------------------------------------- - // Update table of how each WC id relates to each engine ID - // ------------------------------------------------------------------------- - if (g_pAINetworkManager->GetEditOps()->m_pNodeIndexTable) - { - g_pAINetworkManager->GetEditOps()->m_pNodeIndexTable[new_node->GetId()] = m_NodeData.nWCNodeID; - } - // Keep track of largest index used by WC - if (g_pAINetworkManager->GetEditOps()->m_nNextWCIndex <= m_NodeData.nWCNodeID) - { - g_pAINetworkManager->GetEditOps()->m_nNextWCIndex = m_NodeData.nWCNodeID+1; - } - - // ------------------------------------------------------------------------- - // If in WC edit mode: - // Remember the original positions of the nodes before - // they drop so we can send the undropped positions to wc. - // ------------------------------------------------------------------------- - if (engine->IsInEditMode()) - { - if (g_pAINetworkManager->GetEditOps()->m_pWCPosition) - { - g_pAINetworkManager->GetEditOps()->m_pWCPosition[new_node->GetId()] = new_node->GetOrigin(); - } - } - - if (FClassnameIs( this, "info_node_air" ) || FClassnameIs( this, "info_node_air_hint" )) - { - new_node->SetType( NODE_AIR ); - } - else if (FClassnameIs( this, "info_node_climb" )) - { - new_node->SetType( NODE_CLIMB ); - } - else - { - new_node->SetType( NODE_GROUND ); - } - - new_node->m_eNodeInfo = ( m_spawnflags << NODE_ENT_FLAGS_SHIFT ); - - // If changed as part of WC editing process note that network must be rebuilt - if (m_debugOverlays & OVERLAY_WC_CHANGE_ENTITY) - { - g_pAINetworkManager->GetEditOps()->SetRebuildFlags(); - new_node->m_eNodeInfo |= bits_NODE_WC_CHANGED; - - // Initialize the new nodes position. The graph may not be rebuild - // right away but the node should at least be positioned correctly - g_AINetworkBuilder.InitNodePosition( g_pBigAINet, new_node ); - } - - UTIL_RemoveImmediate( this ); - - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -CNodeEnt::CNodeEnt( void ) -{ - m_debugOverlays = 0; -} - - - diff --git a/game/server/ai_initutils.h b/game/server/ai_initutils.h deleted file mode 100644 index c0d3fb689..000000000 --- a/game/server/ai_initutils.h +++ /dev/null @@ -1,105 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: AI Utility classes for building the initial AI Networks -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_INITUTILS_H -#define AI_INITUTILS_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "ai_basenpc.h" -#include "ai_node.h" - -//########################################################### -// >> HintNodeData -// -// This is a chunk of data that's passed to a hint node entity -// when it's created from a CNodeEnt. -//########################################################### -enum HintIgnoreFacing_t -{ - HIF_NO, - HIF_YES, - HIF_DEFAULT, -}; - - -struct HintNodeData -{ - string_t strEntityName; - Vector vecPosition; - short nHintType; - int nNodeID; - string_t strGroup; - int iDisabled; - string_t iszActivityName; - int nTargetWCNodeID; - HintIgnoreFacing_t fIgnoreFacing; - NPC_STATE minState; - NPC_STATE maxState; - - int nWCNodeID; // Node ID assigned by worldcraft (not same as engine!) - - DECLARE_SIMPLE_DATADESC(); -}; - -//########################################################### -// >> CNodeEnt -// -// This is the entity that is loaded in from worldcraft. -// It is only used to build the network and is deleted -// immediately -//########################################################### -class CNodeEnt : public CServerOnlyPointEntity -{ - DECLARE_CLASS( CNodeEnt, CServerOnlyPointEntity ); - -public: - virtual void SetOwnerEntity( CBaseEntity* pOwner ) { BaseClass::SetOwnerEntity( NULL ); } - - static int m_nNodeCount; - - void Spawn( void ); - int Spawn( const char *pMapData ); - - DECLARE_DATADESC(); - - CNodeEnt(void); - -public: - HintNodeData m_NodeData; -}; - -//########################################################### -// >> CAI_TestHull -// -// a modelless clip hull that verifies reachable nodes by -// walking from every node to each of it's connections// -//########################################################### -class CAI_TestHull : public CAI_BaseNPC -{ - DECLARE_CLASS( CAI_TestHull, CAI_BaseNPC ); -private: - static CAI_TestHull* pTestHull; // Hull for testing connectivity - -public: - static CAI_TestHull* GetTestHull(void); // Get the test hull - static void ReturnTestHull(void); // Return the test hull - - bool bInUse; - virtual void Precache(); - void Spawn(void); - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~(FCAP_ACROSS_TRANSITION|FCAP_DONT_SAVE); } - - virtual bool IsJumpLegal(const Vector &startPos, const Vector &apex, const Vector &endPos) const; - - ~CAI_TestHull(void); -}; - - -#endif // AI_INITUTILS_H diff --git a/game/server/ai_link.cpp b/game/server/ai_link.cpp deleted file mode 100644 index f75c66657..000000000 --- a/game/server/ai_link.cpp +++ /dev/null @@ -1,57 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ai_link.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -ASSERT_INVARIANT( ( bits_LINK_STALE_SUGGESTED | bits_LINK_OFF ) <= 255 && ( AI_MOVE_TYPE_BITS <= 255 ) ); -//----------------------------------------------------------------------------- -// Purpose: Given the source node ID, returns the destination ID -// Input : -// Output : -//----------------------------------------------------------------------------- -int CAI_Link::DestNodeID(int srcID) -{ - if (srcID == m_iSrcID) - { - return m_iDestID; - } - else - { - return m_iSrcID; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Constructor -// Input : -// Output : -//----------------------------------------------------------------------------- -CAI_Link::CAI_Link(void) -{ - m_iSrcID = -1; - m_iDestID = -1; - m_LinkInfo = 0; - m_timeStaleExpires = 0; - m_pDynamicLink = NULL; - - for (int hull=0;hull> CAI_Link -//============================================================================= - -class CAI_DynamicLink; - -#define AI_MOVE_TYPE_BITS ( bits_CAP_MOVE_GROUND | bits_CAP_MOVE_JUMP | bits_CAP_MOVE_FLY | bits_CAP_MOVE_CLIMB | bits_CAP_MOVE_SWIM | bits_CAP_MOVE_CRAWL ) - -class CAI_Link -{ -public: - - short m_iSrcID; // the node that 'owns' this link - short m_iDestID; // the node on the other end of the link. - - int DestNodeID(int srcID); // Given the source node ID, returns the destination ID - - byte m_iAcceptedMoveTypes[NUM_HULLS]; // Capability_T of motions acceptable for each hull type - - byte m_LinkInfo; // other information about this link - - float m_timeStaleExpires; - - CAI_DynamicLink *m_pDynamicLink; - - //edict_t *m_pLinkEnt; // the entity that blocks this connection (doors, etc) - - // m_szLinkEntModelname is not necessarily NULL terminated (so we can store it in a more alignment-friendly 4 bytes) - //char m_szLinkEntModelname[ 4 ];// the unique name of the brush model that blocks the connection (this is kept for save/restore) - - //float m_flWeight; // length of the link line segment - -private: - friend class CAI_Network; - CAI_Link(void); -}; - -#endif // AI_LINK_H diff --git a/game/server/ai_localnavigator.cpp b/game/server/ai_localnavigator.cpp deleted file mode 100644 index b1854914c..000000000 --- a/game/server/ai_localnavigator.cpp +++ /dev/null @@ -1,448 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" - -#include "ai_localnavigator.h" - -#include "ai_basenpc.h" -#include "ai_planesolver.h" -#include "ai_moveprobe.h" -#include "ai_motor.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar ai_debug_directnavprobe("ai_debug_directnavprobe", "0"); - -const float TIME_DELAY_FULL_DIRECT_PROBE[2] = { 0.25, 0.35 }; - -//----------------------------------------------------------------------------- - -BEGIN_SIMPLE_DATADESC(CAI_LocalNavigator) - // m_fLastWasClear (not saved) - // m_LastMoveGoal (not saved) - // m_FullDirectTimer (not saved) - // m_pPlaneSolver (not saved) - // m_pMoveProbe (not saved) -END_DATADESC(); - -//------------------------------------- - -CAI_LocalNavigator::CAI_LocalNavigator(CAI_BaseNPC *pOuter) : CAI_Component( pOuter ) -{ - m_pMoveProbe = NULL; - m_pPlaneSolver = new CAI_PlaneSolver( pOuter ); - - m_fLastWasClear = false; - memset( &m_LastMoveGoal, 0, sizeof(m_LastMoveGoal) ); -} - -//------------------------------------- - -CAI_LocalNavigator::~CAI_LocalNavigator() -{ - delete m_pPlaneSolver; -} - -//------------------------------------- - -void CAI_LocalNavigator::Init( IAI_MovementSink *pMovementServices ) -{ - CAI_ProxyMovementSink::Init( pMovementServices ); - m_pMoveProbe = GetOuter()->GetMoveProbe(); // @TODO (toml 03-30-03): this is a "bad" way to grab this pointer. Components should have an explcit "init" phase. -} - -//------------------------------------- - -void CAI_LocalNavigator::ResetMoveCalculations() -{ - m_FullDirectTimer.Force(); - m_pPlaneSolver->Reset(); -} - -//------------------------------------- - -void CAI_LocalNavigator::AddObstacle( const Vector &pos, float radius, AI_MoveSuggType_t type ) -{ - m_pPlaneSolver->AddObstacle( pos, radius, NULL, type ); -} - -//------------------------------------- - -bool CAI_LocalNavigator::HaveObstacles() -{ - return m_pPlaneSolver->HaveObstacles(); -} - -//------------------------------------- - -bool CAI_LocalNavigator::MoveCalcDirect( AILocalMoveGoal_t *pMoveGoal, bool bOnlyCurThink, float *pDistClear, AIMoveResult_t *pResult ) -{ - AI_PROFILE_SCOPE(CAI_LocalNavigator_MoveCalcDirect); - - bool bRetVal = false; - - if ( pMoveGoal->speed ) - { - CAI_Motor *pMotor = GetOuter()->GetMotor(); - float minCheckDist = pMotor->MinCheckDist(); - float probeDist = m_pPlaneSolver->CalcProbeDist( pMoveGoal->speed ); // having this match steering allows one fewer traces - float checkDist = MAX( minCheckDist, probeDist ); - float checkStepDist = MAX( 16.0, probeDist * 0.5 ); - - if ( pMoveGoal->flags & ( AILMG_TARGET_IS_TRANSITION | AILMG_TARGET_IS_GOAL ) ) - { - // clamp checkDist to be no farther than max distance to goal - checkDist = MIN( checkDist, pMoveGoal->maxDist ); - } - - if ( checkDist <= 0.0 ) - { - *pResult = AIMR_OK; - return true; - } - - float moveThisInterval = pMotor->CalcIntervalMove(); - bool bExpectingArrival = (moveThisInterval >= checkDist); - - if ( !m_FullDirectTimer.Expired() ) - { - if ( !m_fLastWasClear || - ( !VectorsAreEqual(pMoveGoal->target, m_LastMoveGoal.target, 0.1) || - !VectorsAreEqual(pMoveGoal->dir, m_LastMoveGoal.dir, 0.1) ) || - bExpectingArrival ) - { - m_FullDirectTimer.Force(); - } - } - - if ( bOnlyCurThink ) // Outer code claims to have done a validation (probably a simplify operation) - { - m_FullDirectTimer.Set( TIME_DELAY_FULL_DIRECT_PROBE[AIStrongOpt()] ); - } - - // First, check the probable move for this cycle - bool bTraceClear = true; - Vector testPos; - - if ( !bExpectingArrival ) - { - testPos = GetLocalOrigin() + pMoveGoal->dir * moveThisInterval; - bTraceClear = GetMoveProbe()->MoveLimit( pMoveGoal->navType, GetLocalOrigin(), testPos, - MASK_NPCSOLID, pMoveGoal->pMoveTarget, - 100.0, - ( pMoveGoal->navType == NAV_GROUND ) ? AIMLF_2D : AIMLF_DEFAULT, - &pMoveGoal->directTrace ); - - if ( !bTraceClear ) - { - // Adjust probe top match expected probe dist (relied on later in process) - pMoveGoal->directTrace.flDistObstructed = (checkDist - moveThisInterval) + pMoveGoal->directTrace.flDistObstructed; - - } - - if ( !IsRetail() && ai_debug_directnavprobe.GetBool() ) - { - if ( !bTraceClear ) - { - DevMsg( GetOuter(), "Close obstruction %f\n", checkDist - pMoveGoal->directTrace.flDistObstructed ); - NDebugOverlay::Line( WorldSpaceCenter(), Vector( testPos.x, testPos.y, WorldSpaceCenter().z ), 255, 0, 0, false, 0.1 ); - if ( pMoveGoal->directTrace.pObstruction ) - NDebugOverlay::Line( WorldSpaceCenter(), pMoveGoal->directTrace.pObstruction->WorldSpaceCenter(), 255, 0, 255, false, 0.1 ); - - } - else - { - NDebugOverlay::Line( WorldSpaceCenter(), Vector( testPos.x, testPos.y, WorldSpaceCenter().z ), 0, 255, 0, false, 0.1 ); - } - } - - pMoveGoal->thinkTrace = pMoveGoal->directTrace; - } - - // Now project out for future obstructions - if ( bTraceClear ) - { - if ( m_FullDirectTimer.Expired() ) - { - testPos = GetLocalOrigin() + pMoveGoal->dir * checkDist; - float checkStepPct = (checkStepDist / checkDist) * 100.0; - if ( checkStepPct > 100.0 ) - checkStepPct = 100.0; - - bTraceClear = GetMoveProbe()->MoveLimit( pMoveGoal->navType, GetLocalOrigin(), testPos, - MASK_NPCSOLID, pMoveGoal->pMoveTarget, - checkStepPct, - ( pMoveGoal->navType == NAV_GROUND ) ? AIMLF_2D : AIMLF_DEFAULT, - &pMoveGoal->directTrace ); - if ( bExpectingArrival ) - pMoveGoal->thinkTrace = pMoveGoal->directTrace; - - if (ai_debug_directnavprobe.GetBool() ) - { - if ( !bTraceClear ) - { - NDebugOverlay::Line( GetOuter()->EyePosition(), Vector( testPos.x, testPos.y, GetOuter()->EyePosition().z ), 255, 0, 0, false, 0.1 ); - DevMsg( GetOuter(), "Obstruction %f\n", checkDist - pMoveGoal->directTrace.flDistObstructed ); - } - else - { - NDebugOverlay::Line( GetOuter()->EyePosition(), Vector( testPos.x, testPos.y, GetOuter()->EyePosition().z ), 0, 255, 0, false, 0.1 ); - DevMsg( GetOuter(), "No obstruction\n" ); - } - } - } - else - { - if ( ai_debug_directnavprobe.GetBool() ) - DevMsg( GetOuter(), "No obstruction (Near probe only)\n" ); - } - } - - pMoveGoal->bHasTraced = true; - - float distClear = checkDist - pMoveGoal->directTrace.flDistObstructed; - if (distClear < 0.001) - distClear = 0; - - if ( bTraceClear ) - { - *pResult = AIMR_OK; - bRetVal = true; - m_fLastWasClear = true; - } - else if ( ( pMoveGoal->flags & ( AILMG_TARGET_IS_TRANSITION | AILMG_TARGET_IS_GOAL ) ) && - pMoveGoal->maxDist < distClear ) - { - *pResult = AIMR_OK; - bRetVal = true; - m_fLastWasClear = true; - } - else - { - *pDistClear = distClear; - m_fLastWasClear = false; - } - } - else - { - // Should never end up in this function with speed of zero. Probably an activity problem. - *pResult = AIMR_ILLEGAL; - bRetVal = true; - } - - m_LastMoveGoal = *pMoveGoal; - if ( bRetVal && m_FullDirectTimer.Expired() ) - m_FullDirectTimer.Set( TIME_DELAY_FULL_DIRECT_PROBE[AIStrongOpt()] ); - - return bRetVal; -} - -//------------------------------------- - -ConVar ai_no_steer( "ai_no_steer", "0" ); - -bool CAI_LocalNavigator::MoveCalcSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) -{ - if ( (pMoveGoal->flags & AILMG_NO_STEER) ) - return false; - - if ( ai_no_steer.GetBool() ) - return false; - - if ( GetOuter()->IsFlaggedEfficient() ) - return false; - - AI_PROFILE_SCOPE(CAI_Motor_MoveCalcSteer); - Vector moveSolution; - if ( m_pPlaneSolver->Solve( *pMoveGoal, distClear, &moveSolution ) ) - { - if ( moveSolution != pMoveGoal->dir ) - { - float dot = moveSolution.AsVector2D().Dot( pMoveGoal->dir.AsVector2D() ); - - const float COS_HALF_30 = 0.966; - if ( dot > COS_HALF_30 ) - { - float probeDist = m_pPlaneSolver->CalcProbeDist( pMoveGoal->speed ); - if ( pMoveGoal->maxDist < probeDist * 0.33333 && distClear > probeDist * 0.6666) - { - // A waypoint is coming up, but there's probably time to steer - // away after hitting it - *pResult = AIMR_OK; - return true; - } - } - - pMoveGoal->facing = pMoveGoal->dir = moveSolution; - } - *pResult = AIMR_OK; - return true; - } - - return false; -} - -//------------------------------------- - -bool CAI_LocalNavigator::MoveCalcStop( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) -{ - if (distClear < pMoveGoal->maxDist) - { - if ( distClear < 0.1 ) - { - DebugNoteMovementFailure(); - *pResult = AIMR_ILLEGAL; - } - else - { - pMoveGoal->maxDist = distClear; - *pResult = AIMR_OK; - } - - return true; - } - *pResult = AIMR_OK; - return true; -} - -//------------------------------------- - -#ifdef DEBUG -#define SetSolveCookie() pMoveGoal->solveCookie = __LINE__; -#else -#define SetSolveCookie() ((void)0) -#endif - - -AIMoveResult_t CAI_LocalNavigator::MoveCalcRaw( AILocalMoveGoal_t *pMoveGoal, bool bOnlyCurThink ) -{ - AI_PROFILE_SCOPE(CAI_Motor_MoveCalc); - - AIMoveResult_t result = AIMR_OK; // Assume success - AIMoveTrace_t directTrace; - float distClear; - - // -------------------------------------------------- - - bool bDirectClear = MoveCalcDirect( pMoveGoal, bOnlyCurThink, &distClear, &result); - if ( OnCalcBaseMove( pMoveGoal, distClear, &result ) ) - { - SetSolveCookie(); - return DbgResult( result ); - } - - bool bShouldSteer = ( !(pMoveGoal->flags & AILMG_NO_STEER) && ( !bDirectClear || HaveObstacles() ) ); - - if ( bDirectClear && !bShouldSteer ) - { - SetSolveCookie(); - return DbgResult( result ); - } - - // -------------------------------------------------- - - if ( bShouldSteer ) - { - if ( !bDirectClear ) - { - if ( OnObstructionPreSteer( pMoveGoal, distClear, &result ) ) - { - SetSolveCookie(); - return DbgResult( result ); - } - } - - if ( MoveCalcSteer( pMoveGoal, distClear, &result ) ) - { - SetSolveCookie(); - return DbgResult( result ); - } - } - - if ( OnFailedSteer( pMoveGoal, distClear, &result ) ) - { - SetSolveCookie(); - return DbgResult( result ); - } - - // -------------------------------------------------- - - if ( OnFailedLocalNavigation( pMoveGoal, distClear, &result ) ) - { - SetSolveCookie(); - return DbgResult( result ); - } - - if ( distClear < GetOuter()->GetMotor()->MinStoppingDist() ) - { - if ( OnInsufficientStopDist( pMoveGoal, distClear, &result ) ) - { - SetSolveCookie(); - return DbgResult( result ); - } - - if ( MoveCalcStop( pMoveGoal, distClear, &result) ) - { - SetSolveCookie(); - return DbgResult( result ); - } - } - - // A hopeful result... may get in trouble at next waypoint and obstruction is still there - if ( distClear > pMoveGoal->curExpectedDist ) - { - SetSolveCookie(); - return DbgResult( AIMR_OK ); - } - - // -------------------------------------------------- - - DebugNoteMovementFailure(); - SetSolveCookie(); - return DbgResult( IsMoveBlocked( pMoveGoal->directTrace.fStatus ) ? pMoveGoal->directTrace.fStatus : AIMR_ILLEGAL ); -} - -//------------------------------------- - -AIMoveResult_t CAI_LocalNavigator::MoveCalc( AILocalMoveGoal_t *pMoveGoal, bool bPreviouslyValidated ) -{ - bool bOnlyCurThink = ( bPreviouslyValidated && !HaveObstacles() ); - - AIMoveResult_t result = MoveCalcRaw( pMoveGoal, bOnlyCurThink ); - - if ( pMoveGoal->curExpectedDist > pMoveGoal->maxDist ) - pMoveGoal->curExpectedDist = pMoveGoal->maxDist; - - // If success, try to dampen really fast turning movement - if ( result == AIMR_OK) - { - float interval = GetOuter()->GetMotor()->GetMoveInterval(); - float currentYaw = UTIL_AngleMod( GetLocalAngles().y ); - float goalYaw; - float deltaYaw; - float speed; - float clampedYaw; - - // Clamp yaw - goalYaw = UTIL_VecToYaw( pMoveGoal->facing ); - deltaYaw = fabs( UTIL_AngleDiff( goalYaw, currentYaw ) ); - if ( deltaYaw > 15 ) - { - speed = deltaYaw * 4.0; // i.e., any maneuver takes a quarter a second - clampedYaw = AI_ClampYaw( speed, currentYaw, goalYaw, interval ); - - if ( clampedYaw != goalYaw ) - { - pMoveGoal->facing = UTIL_YawToVector( clampedYaw ); - } - } - } - - return result; -} -//----------------------------------------------------------------------------- diff --git a/game/server/ai_localnavigator.h b/game/server/ai_localnavigator.h deleted file mode 100644 index 8aed80394..000000000 --- a/game/server/ai_localnavigator.h +++ /dev/null @@ -1,72 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef AI_LOCALNAVIGATOR_H -#define AI_LOCALNAVIGATOR_H - -#include "simtimer.h" -#include "ai_component.h" -#include "ai_movetypes.h" -#include "ai_obstacle_type.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -class CAI_PlaneSolver; -class CAI_MoveProbe; - -//----------------------------------------------------------------------------- -// CAI_LocalNavigator -// -// Purpose: Handles all the immediate tasks of navigation, independent of -// path. Implements steering. -//----------------------------------------------------------------------------- - -class CAI_LocalNavigator : public CAI_Component, - public CAI_ProxyMovementSink -{ -public: - CAI_LocalNavigator(CAI_BaseNPC *pOuter); - virtual ~CAI_LocalNavigator(); - - void Init( IAI_MovementSink *pMovementServices ); - - //--------------------------------- - - AIMoveResult_t MoveCalc( AILocalMoveGoal_t *pResult, bool bPreviouslyValidated = false ); - void ResetMoveCalculations(); - - //--------------------------------- - - void AddObstacle( const Vector &pos, float radius, AI_MoveSuggType_t type = AIMST_AVOID_OBJECT ); - bool HaveObstacles(); - -protected: - - AIMoveResult_t MoveCalcRaw( AILocalMoveGoal_t *pResult, bool bOnlyCurThink ); - bool MoveCalcDirect( AILocalMoveGoal_t *pMoveGoal, bool bOnlyCurThink, float *pDistClear, AIMoveResult_t *pResult ); - bool MoveCalcSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ); - bool MoveCalcStop( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ); - - CAI_MoveProbe * GetMoveProbe() { return m_pMoveProbe; } - const CAI_MoveProbe *GetMoveProbe() const { return m_pMoveProbe; } - -private: - - // -------------------------------- - - bool m_fLastWasClear; - AILocalMoveGoal_t m_LastMoveGoal; - CSimpleSimTimer m_FullDirectTimer; - - CAI_PlaneSolver * m_pPlaneSolver; - CAI_MoveProbe * m_pMoveProbe; - - DECLARE_SIMPLE_DATADESC(); -}; - -#endif // AI_LOCALNAVIGATOR_H diff --git a/game/server/ai_looktarget.cpp b/game/server/ai_looktarget.cpp deleted file mode 100644 index 983b4e899..000000000 --- a/game/server/ai_looktarget.cpp +++ /dev/null @@ -1,148 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "game.h" -#include "ai_looktarget.h" - -// Mothballing this entity to get rid of it. info_hint does its job better (sjb) -//LINK_ENTITY_TO_CLASS( ai_looktarget, CAI_LookTarget ); - -BEGIN_DATADESC( CAI_LookTarget ) - - // Keyfields - DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ), - DEFINE_KEYFIELD( m_iContext, FIELD_INTEGER, "context" ), - DEFINE_KEYFIELD( m_iPriority, FIELD_INTEGER, "priority" ), - DEFINE_KEYFIELD( m_flMaxDist, FIELD_FLOAT, "maxdist" ), - - // Fields - DEFINE_FIELD( m_flTimeNextAvailable, FIELD_TIME ), - -END_DATADESC() - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CAI_LookTarget::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_BBOX_BIT) - { - int color = random->RandomInt( 50, 255 ); - NDebugOverlay::Cross3D( GetAbsOrigin(), 12, color, color, color, false, 0.1 ); - } - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - - if( !IsEnabled() ) - { - Q_snprintf(tempstr,sizeof(tempstr),"DISABLED" ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - - if( IsEligible( NULL ) ) - { - Q_snprintf(tempstr,sizeof(tempstr),"Eligible" ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - else - { - Q_snprintf(tempstr,sizeof(tempstr),"NOT Eligible for selection"); - EntityText(text_offset,tempstr,0); - text_offset++; - } - } - return text_offset; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CAI_LookTarget::IsEligible( CBaseEntity *pLooker ) -{ - if( !IsEnabled() ) - return false; - - if( !IsAvailable() ) - return false; - - if( pLooker ) - { - float maxdistsqr = m_flMaxDist * m_flMaxDist; - - Vector vecPos = GetAbsOrigin(); - - if( vecPos.DistToSqr( pLooker->WorldSpaceCenter() ) > maxdistsqr ) - { - return false; - } - } - - return true; -} - -//--------------------------------------------------------- -// Someone's reserving this entity because they're going -// to attempt to look at it for flDuration seconds. We'll -// make it unavailable to anyone else for that time. -//--------------------------------------------------------- -void CAI_LookTarget::Reserve( float flDuration ) -{ - m_flTimeNextAvailable = gpGlobals->curtime + flDuration; - - if( HasSpawnFlags( SF_LOOKTARGET_ONLYONCE ) ) - { - // No one will look at this again. - Disable(); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -CAI_LookTarget *CAI_LookTarget::GetFirstLookTarget() -{ - CBaseEntity *pEnt; - - string_t iszLookTarget = FindPooledString( "ai_looktarget" ); - if( iszLookTarget == NULL_STRING ) - { - return NULL; - } - - pEnt = gEntList.FirstEnt(); - while( pEnt && pEnt->m_iClassname != iszLookTarget ) - { - pEnt = gEntList.NextEnt( pEnt ); - } - - return (CAI_LookTarget*)pEnt; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -CAI_LookTarget *CAI_LookTarget::GetNextLookTarget( CAI_LookTarget *pCurrentTarget ) -{ - CBaseEntity *pEnt; - - string_t iszLookTarget = FindPooledString( "ai_looktarget" ); - if( iszLookTarget == NULL_STRING ) - { - return NULL; - } - - pEnt = gEntList.NextEnt( pCurrentTarget ); - while( pEnt && pEnt->m_iClassname != iszLookTarget ) - { - pEnt = gEntList.NextEnt( pEnt ); - } - - return (CAI_LookTarget*)pEnt; -} diff --git a/game/server/ai_looktarget.h b/game/server/ai_looktarget.h deleted file mode 100644 index d4093c906..000000000 --- a/game/server/ai_looktarget.h +++ /dev/null @@ -1,47 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// -#pragma once -#ifndef AI_LOOKTARGET_H -#define AI_LOOKTARGET_H - -#define SF_LOOKTARGET_ONLYONCE 0x00000001 - -//============================================================================= -//============================================================================= -class CAI_LookTarget : public CPointEntity -{ -public: - DECLARE_CLASS( CAI_LookTarget, CPointEntity ); - DECLARE_DATADESC(); - - CAI_LookTarget() { m_flTimeNextAvailable = -1; } - - // Debugging - int DrawDebugTextOverlays(void); - - // Accessors & Availability - bool IsEligible( CBaseEntity *pLooker ); - bool IsEnabled() { return !m_bDisabled; } - bool IsAvailable() { return (gpGlobals->curtime > m_flTimeNextAvailable); } - void Reserve( float flDuration ); - - // Searching - static CAI_LookTarget *GetFirstLookTarget(); - static CAI_LookTarget *GetNextLookTarget( CAI_LookTarget *pCurrentTarget ); - - int m_iContext; - int m_iPriority; - - void Enable() { m_bDisabled = false; } - void Disable() { m_bDisabled = true; } - -private: - bool m_bDisabled; - float m_flTimeNextAvailable; - float m_flMaxDist; -}; - -#endif//AI_LOOKTARGET_H diff --git a/game/server/ai_memory.cpp b/game/server/ai_memory.cpp deleted file mode 100644 index d76c3fca4..000000000 --- a/game/server/ai_memory.cpp +++ /dev/null @@ -1,656 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: An NPC's memory of potential enemies -// -//=============================================================================// - -#include "cbase.h" -#include "isaverestore.h" -#include "ai_debug.h" -#include "ai_memory.h" -#include "ai_basenpc.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define EMEMORY_POOL_SIZE 64 -#define AI_FREE_KNOWLEDGE_DURATION 1.75 - -//----------------------------------------------------------------------------- -// AI_EnemyInfo_t -// -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- - -AI_EnemyInfo_t::AI_EnemyInfo_t(void) -{ - hEnemy = NULL; - vLastKnownLocation = vec3_origin; - vLastSeenLocation = vec3_origin; - timeLastSeen = 0; - timeFirstSeen = 0; - timeLastReacquired = 0; - timeValidEnemy = 0; - timeLastReceivedDamageFrom = 0; - timeAtFirstHand = AI_INVALID_TIME; - bDangerMemory = 0; - bEludedMe = 0; - bUnforgettable = 0; - bMobbedMe = 0; -} - - -//----------------------------------------------------------------------------- -// CAI_EnemiesListSaveRestoreOps -// -// Purpose: Handles save and load for enemy memories -// -//----------------------------------------------------------------------------- - -class CAI_EnemiesListSaveRestoreOps : public CDefSaveRestoreOps -{ -public: - CAI_EnemiesListSaveRestoreOps() - { - } - - virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave ) - { - CAI_Enemies::CMemMap *pMemMap = (CAI_Enemies::CMemMap *)fieldInfo.pField; - - int nMemories = pMemMap->Count(); - pSave->WriteInt( &nMemories ); - - for ( CAI_Enemies::CMemMap::IndexType_t i = pMemMap->FirstInorder(); i != pMemMap->InvalidIndex(); i = pMemMap->NextInorder( i ) ) - { - pSave->WriteAll( (*pMemMap)[i] ); - } - } - - virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore ) - { - CAI_Enemies::CMemMap *pMemMap = (CAI_Enemies::CMemMap *)fieldInfo.pField; - Assert( pMemMap->Count() == 0 ); - - int nMemories = pRestore->ReadInt(); - - while ( nMemories-- ) - { - AI_EnemyInfo_t *pAddMemory = new AI_EnemyInfo_t; - - pRestore->ReadAll( pAddMemory ); - - if ( pAddMemory->hEnemy != NULL ) - { - pMemMap->Insert( pAddMemory->hEnemy, pAddMemory ); - } - else - delete pAddMemory; - } - } - - virtual void MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - CAI_Enemies::CMemMap *pMemMap = (CAI_Enemies::CMemMap *)fieldInfo.pField; - - for ( CAI_Enemies::CMemMap::IndexType_t i = pMemMap->FirstInorder(); i != pMemMap->InvalidIndex(); i = pMemMap->NextInorder( i ) ) - { - delete (*pMemMap)[i]; - } - - pMemMap->RemoveAll(); - } - - virtual bool IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - CAI_Enemies::CMemMap *pMemMap = (CAI_Enemies::CMemMap *)fieldInfo.pField; - return ( pMemMap->Count() == 0 ); - } - -} g_AI_MemoryListSaveRestoreOps; - -//----------------------------------------------------------------------------- -// CAI_Enemies -// -// Purpose: Stores a set of AI_EnemyInfo_t's -// -//----------------------------------------------------------------------------- - -BEGIN_SIMPLE_DATADESC( CAI_Enemies ) - - DEFINE_CUSTOM_FIELD( m_Map, &g_AI_MemoryListSaveRestoreOps ), - DEFINE_FIELD( m_flFreeKnowledgeDuration, FIELD_FLOAT ), - DEFINE_FIELD( m_flEnemyDiscardTime, FIELD_FLOAT ), - DEFINE_FIELD( m_vecDefaultLKP, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecDefaultLSP, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_serial, FIELD_INTEGER ), - -END_DATADESC() - -BEGIN_SIMPLE_DATADESC( AI_EnemyInfo_t ) - DEFINE_FIELD( vLastKnownLocation, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( vLastSeenLocation, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( hEnemy, FIELD_EHANDLE ), - DEFINE_FIELD( timeLastSeen, FIELD_TIME ), - DEFINE_FIELD( timeFirstSeen, FIELD_TIME ), - DEFINE_FIELD( timeLastReacquired, FIELD_TIME ), - DEFINE_FIELD( timeValidEnemy, FIELD_TIME ), - DEFINE_FIELD( timeLastReceivedDamageFrom, FIELD_TIME ), - DEFINE_FIELD( timeAtFirstHand, FIELD_TIME ), - DEFINE_FIELD( bDangerMemory, FIELD_BOOLEAN ), - DEFINE_FIELD( bEludedMe, FIELD_BOOLEAN ), - DEFINE_FIELD( bUnforgettable, FIELD_BOOLEAN ), - DEFINE_FIELD( bMobbedMe, FIELD_BOOLEAN ), - // NOT SAVED nextEMemory -END_DATADESC() - -//----------------------------------------------------------------------------- - -CAI_Enemies::CAI_Enemies(void) -{ - m_flFreeKnowledgeDuration = AI_FREE_KNOWLEDGE_DURATION; - m_flEnemyDiscardTime = AI_DEF_ENEMY_DISCARD_TIME; - m_vecDefaultLKP = vec3_invalid; - m_vecDefaultLSP = vec3_invalid; - m_serial = 0; - SetDefLessFunc( m_Map ); -} - - -//----------------------------------------------------------------------------- - -CAI_Enemies::~CAI_Enemies() -{ - for ( CMemMap::IndexType_t i = m_Map.FirstInorder(); i != m_Map.InvalidIndex(); i = m_Map.NextInorder( i ) ) - { - delete m_Map[i]; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Purges any dead enemies from memory -//----------------------------------------------------------------------------- - -AI_EnemyInfo_t *CAI_Enemies::GetFirst( AIEnemiesIter_t *pIter ) -{ - CMemMap::IndexType_t i = m_Map.FirstInorder(); - *pIter = (AIEnemiesIter_t)(unsigned)i; - - if ( i == m_Map.InvalidIndex() ) - return NULL; - - if ( m_Map[i]->hEnemy == NULL ) - return GetNext( pIter ); - - return m_Map[i]; -} - -//----------------------------------------------------------------------------- - -AI_EnemyInfo_t *CAI_Enemies::GetNext( AIEnemiesIter_t *pIter ) -{ - CMemMap::IndexType_t i = (CMemMap::IndexType_t)((unsigned)(*pIter)); - - if ( i == m_Map.InvalidIndex() ) - return NULL; - - i = m_Map.NextInorder( i ); - *pIter = (AIEnemiesIter_t)(unsigned)i; - if ( i == m_Map.InvalidIndex() ) - return NULL; - - if ( m_Map[i]->hEnemy == NULL ) - return GetNext( pIter ); - - return m_Map[i]; -} - -//----------------------------------------------------------------------------- - -AI_EnemyInfo_t *CAI_Enemies::Find( CBaseEntity *pEntity, bool bTryDangerMemory ) -{ - if ( pEntity == AI_UNKNOWN_ENEMY ) - pEntity = NULL; - - CMemMap::IndexType_t i = m_Map.Find( pEntity ); - if ( i == m_Map.InvalidIndex() ) - { - if ( !bTryDangerMemory || ( i = m_Map.Find( NULL ) ) == m_Map.InvalidIndex() ) - return NULL; - Assert(m_Map[i]->bDangerMemory == true); - } - return m_Map[i]; -} - - -//----------------------------------------------------------------------------- - -AI_EnemyInfo_t *CAI_Enemies::GetDangerMemory() -{ - CMemMap::IndexType_t i = m_Map.Find( NULL ); - if ( i == m_Map.InvalidIndex() ) - return NULL; - Assert(m_Map[i]->bDangerMemory == true); - return m_Map[i]; -} - -//----------------------------------------------------------------------------- - -bool CAI_Enemies::ShouldDiscardMemory( AI_EnemyInfo_t *pMemory ) -{ - CBaseEntity *pEnemy = pMemory->hEnemy; - - if ( pEnemy ) - { - CAI_BaseNPC *pEnemyNPC = pEnemy->MyNPCPointer(); - if ( pEnemyNPC && pEnemyNPC->GetState() == NPC_STATE_DEAD ) - return true; - } - else - { - if ( !pMemory->bDangerMemory ) - return true; - } - - if ( !pMemory->bUnforgettable && - gpGlobals->curtime > pMemory->timeLastSeen + m_flEnemyDiscardTime ) - { - return true; - } - - return false; -} - - -//----------------------------------------------------------------------------- - -void CAI_Enemies::RefreshMemories(void) -{ - AI_PROFILE_SCOPE(CAI_Enemies_RefreshMemories); - - if ( m_flFreeKnowledgeDuration >= m_flEnemyDiscardTime ) - { - m_flFreeKnowledgeDuration = m_flEnemyDiscardTime - .1; - } - - // ------------------- - // Check each record - // ------------------- - - CMemMap::IndexType_t i = m_Map.FirstInorder(); - while ( i != m_Map.InvalidIndex() ) - { - AI_EnemyInfo_t *pMemory = m_Map[i]; - - CMemMap::IndexType_t iNext = m_Map.NextInorder( i ); // save so can remove - if ( ShouldDiscardMemory( pMemory ) ) - { - delete pMemory; - m_Map.RemoveAt(i); - } - else if ( pMemory->hEnemy ) - { - if ( gpGlobals->curtime <= pMemory->timeLastSeen + m_flFreeKnowledgeDuration ) - { - // Free knowledge is ignored if the target has notarget on - if ( !(pMemory->hEnemy->GetFlags() & FL_NOTARGET) ) - { - pMemory->vLastKnownLocation = pMemory->hEnemy->GetAbsOrigin(); - } - } - - if ( gpGlobals->curtime <= pMemory->timeLastSeen ) - { - pMemory->vLastSeenLocation = pMemory->hEnemy->GetAbsOrigin(); - } - } - i = iNext; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Updates information about our enemies -// Output : Returns true if new enemy, false if already know of enemy -//----------------------------------------------------------------------------- - -bool CAI_Enemies::UpdateMemory(CAI_Network* pAINet, CBaseEntity *pEnemy, const Vector &vPosition, float reactionDelay, bool firstHand ) -{ - if ( pEnemy == AI_UNKNOWN_ENEMY ) - pEnemy = NULL; - - const float DIST_TRIGGER_REACQUIRE_SQ = Square(20.0 * 12.0); - const float TIME_TRIGGER_REACQUIRE = 4.0; - const float MIN_DIST_TIME_TRIGGER_REACQUIRE_SQ = Square(4.0 * 12.0); - - AI_EnemyInfo_t *pMemory = Find( pEnemy ); - // ------------------------------------------- - // Otherwise just update my own - // ------------------------------------------- - // Update enemy information - if ( pMemory ) - { - Assert(pEnemy || pMemory->bDangerMemory == true); - - if ( firstHand ) - pMemory->timeLastSeen = gpGlobals->curtime; - pMemory->bEludedMe = false; - - float deltaDist = (pMemory->vLastKnownLocation - vPosition).LengthSqr(); - - if (deltaDist>DIST_TRIGGER_REACQUIRE_SQ || ( deltaDist>MIN_DIST_TIME_TRIGGER_REACQUIRE_SQ && ( gpGlobals->curtime - pMemory->timeLastSeen ) > TIME_TRIGGER_REACQUIRE ) ) - { - pMemory->timeLastReacquired = gpGlobals->curtime; - } - - // Only update if the enemy has moved - if (deltaDist>Square(12.0)) - { - pMemory->vLastKnownLocation = vPosition; - - } - - // Update the time at which we first saw him firsthand - if ( firstHand && pMemory->timeAtFirstHand == AI_INVALID_TIME ) - { - pMemory->timeAtFirstHand = gpGlobals->curtime; - } - - return false; - } - - // If not on my list of enemies add it - AI_EnemyInfo_t *pAddMemory = new AI_EnemyInfo_t; - pAddMemory->vLastKnownLocation = vPosition; - - if ( firstHand ) - { - pAddMemory->timeLastReacquired = pAddMemory->timeFirstSeen = pAddMemory->timeLastSeen = pAddMemory->timeAtFirstHand = gpGlobals->curtime; - } - else - { - // Block free knowledge - pAddMemory->timeLastReacquired = pAddMemory->timeFirstSeen = pAddMemory->timeLastSeen = ( gpGlobals->curtime - (m_flFreeKnowledgeDuration + 0.01) ); - pAddMemory->timeAtFirstHand = AI_INVALID_TIME; - } - - if ( reactionDelay > 0.0 ) - pAddMemory->timeValidEnemy = gpGlobals->curtime + reactionDelay; - - pAddMemory->bEludedMe = false; - - // I'm either remembering a postion of an enmey of just a danger position - pAddMemory->hEnemy = pEnemy; - pAddMemory->bDangerMemory = ( pEnemy == NULL ); - - // add to the list - m_Map.Insert( pEnemy, pAddMemory ); - m_serial++; - - return true; -} - -//------------------------------------------------------------------------------ -// Purpose : Returns true if this enemy is part of my memory -//------------------------------------------------------------------------------ -void CAI_Enemies::OnTookDamageFrom( CBaseEntity *pEnemy ) -{ - AI_EnemyInfo_t *pMemory = Find( pEnemy, true ); - if ( pMemory ) - pMemory->timeLastReceivedDamageFrom = gpGlobals->curtime; -} - -//------------------------------------------------------------------------------ -// Purpose : Returns true if this enemy is part of my memory -//------------------------------------------------------------------------------ -bool CAI_Enemies::HasMemory( CBaseEntity *pEnemy ) -{ - return ( Find( pEnemy ) != NULL ); -} - -//----------------------------------------------------------------------------- -// Purpose: Clear information about our enemy -//----------------------------------------------------------------------------- -void CAI_Enemies::ClearMemory(CBaseEntity *pEnemy) -{ - CMemMap::IndexType_t i = m_Map.Find( pEnemy ); - if ( i != m_Map.InvalidIndex() ) - { - delete m_Map[i]; - m_Map.RemoveAt( i ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Notes that the given enemy has eluded me -//----------------------------------------------------------------------------- -void CAI_Enemies::MarkAsEluded( CBaseEntity *pEnemy ) -{ - AI_EnemyInfo_t *pMemory = Find( pEnemy ); - if ( pMemory ) - { - pMemory->bEludedMe = true; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns last known posiiton of given enemy -//----------------------------------------------------------------------------- -const Vector &CAI_Enemies::LastKnownPosition( CBaseEntity *pEnemy ) -{ - AI_EnemyInfo_t *pMemory = Find( pEnemy, true ); - if ( pMemory ) - { - m_vecDefaultLKP = pMemory->vLastKnownLocation; - } - else - { - DevWarning( 2,"Asking LastKnownPosition for enemy that's not in my memory!!\n"); - } - return m_vecDefaultLKP; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the last position the enemy was SEEN at. This will always be -// different than LastKnownPosition() when the enemy is out of sight, because -// the last KNOWN position will be updated for a number of seconds after the -// player disappears. -//----------------------------------------------------------------------------- -const Vector &CAI_Enemies::LastSeenPosition( CBaseEntity *pEnemy ) -{ - AI_EnemyInfo_t *pMemory = Find( pEnemy, true ); - if ( pMemory ) - { - m_vecDefaultLSP = pMemory->vLastSeenLocation; - } - else - { - DevWarning( 2,"Asking LastSeenPosition for enemy that's not in my memory!!\n"); - } - return m_vecDefaultLSP; -} - -float CAI_Enemies::TimeLastReacquired( CBaseEntity *pEnemy ) -{ - // I've never seen something that doesn't exist - if (!pEnemy) - return 0; - - AI_EnemyInfo_t *pMemory = Find( pEnemy, true ); - if ( pMemory ) - return pMemory->timeLastReacquired; - - if ( pEnemy != AI_UNKNOWN_ENEMY ) - DevWarning( 2,"Asking TimeLastReacquired for enemy that's not in my memory!!\n"); - return AI_INVALID_TIME; -} - -//----------------------------------------------------------------------------- -// Purpose: Sets position to the last known position of an enemy. If enemy -// was not found returns last memory of danger position if it exists -// Output : Returns false is no position is known -//----------------------------------------------------------------------------- -float CAI_Enemies::LastTimeSeen( CBaseEntity *pEnemy, bool bCheckDangerMemory /*= true*/ ) -{ - // I've never seen something that doesn't exist - if (!pEnemy) - return 0; - - AI_EnemyInfo_t *pMemory = Find( pEnemy, bCheckDangerMemory ); - if ( pMemory ) - return pMemory->timeLastSeen; - - if ( pEnemy != AI_UNKNOWN_ENEMY ) - DevWarning( 2,"Asking LastTimeSeen for enemy that's not in my memory!!\n"); - return AI_INVALID_TIME; -} - -//----------------------------------------------------------------------------- -// Purpose: Get the time at which the enemy was first seen. -// Output : Returns false is no position is known -//----------------------------------------------------------------------------- -float CAI_Enemies::FirstTimeSeen( CBaseEntity *pEnemy) -{ - // I've never seen something that doesn't exist - if (!pEnemy) - return 0; - - AI_EnemyInfo_t *pMemory = Find( pEnemy, true ); - if ( pMemory ) - return pMemory->timeFirstSeen; - - if ( pEnemy != AI_UNKNOWN_ENEMY ) - DevWarning( 2,"Asking FirstTimeSeen for enemy that's not in my memory!!\n"); - return AI_INVALID_TIME; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEnemy - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_Enemies::HasFreeKnowledgeOf( CBaseEntity *pEnemy ) -{ - // I've never seen something that doesn't exist - if (!pEnemy) - return 0; - - AI_EnemyInfo_t *pMemory = Find( pEnemy, true ); - if ( pMemory ) - { - float flFreeKnowledgeTime = pMemory->timeLastSeen + m_flFreeKnowledgeDuration; - return ( gpGlobals->curtime < flFreeKnowledgeTime ); - } - - if ( pEnemy != AI_UNKNOWN_ENEMY ) - DevWarning( 2,"Asking HasFreeKnowledgeOf for enemy that's not in my memory!!\n"); - return AI_INVALID_TIME; -} - -//----------------------------------------------------------------------------- -float CAI_Enemies::LastTimeTookDamageFrom( CBaseEntity *pEnemy) -{ - // I've never seen something that doesn't exist - if (!pEnemy) - return 0; - - AI_EnemyInfo_t *pMemory = Find( pEnemy, true ); - if ( pMemory ) - return pMemory->timeLastReceivedDamageFrom; - - if ( pEnemy != AI_UNKNOWN_ENEMY ) - DevWarning( 2,"Asking LastTimeTookDamageFrom for enemy that's not in my memory!!\n"); - return AI_INVALID_TIME; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the time at which the enemy was first seen firsthand -// Input : *pEnemy - -// Output : float -//----------------------------------------------------------------------------- -float CAI_Enemies::TimeAtFirstHand( CBaseEntity *pEnemy ) -{ - // I've never seen something that doesn't exist - if (!pEnemy) - return 0; - - AI_EnemyInfo_t *pMemory = Find( pEnemy, true ); - if ( pMemory ) - return pMemory->timeAtFirstHand; - - if ( pEnemy != AI_UNKNOWN_ENEMY ) - DevWarning( 2,"Asking TimeAtFirstHand for enemy that's not in my memory!!\n"); - return AI_INVALID_TIME; -} - -//----------------------------------------------------------------------------- -// Purpose: Sets position to the last known position of an enemy. If enemy -// was not found returns last memory of danger position if it exists -// Output : Returns false is no position is known -//----------------------------------------------------------------------------- -bool CAI_Enemies::HasEludedMe( CBaseEntity *pEnemy ) -{ - AI_EnemyInfo_t *pMemory = Find( pEnemy ); - if ( pMemory ) - return pMemory->bEludedMe; - return false; -} - -void CAI_Enemies::SetTimeValidEnemy( CBaseEntity *pEnemy, float flTime ) -{ - AI_EnemyInfo_t *pMemory = Find( pEnemy ); - if ( pMemory ) - pMemory->timeValidEnemy = flTime; -} - -//----------------------------------------------------------------------------- -void CAI_Enemies::SetUnforgettable( CBaseEntity *pEnemy, bool bUnforgettable ) -{ - AI_EnemyInfo_t *pMemory = Find( pEnemy ); - if ( pMemory ) - pMemory->bUnforgettable = bUnforgettable; -} - -//----------------------------------------------------------------------------- -void CAI_Enemies::SetMobbedMe( CBaseEntity *pEnemy, bool bMobbedMe ) -{ - AI_EnemyInfo_t *pMemory = Find( pEnemy ); - if ( pMemory ) - pMemory->bMobbedMe = bMobbedMe; -} - -//----------------------------------------------------------------------------- - -void CAI_Enemies::SetFreeKnowledgeDuration( float flDuration ) -{ - m_flFreeKnowledgeDuration = flDuration; - - if ( m_flFreeKnowledgeDuration >= m_flEnemyDiscardTime ) - { - // If your free knowledge time is greater than your discard time, - // you'll forget about secondhand enemies passed to you by squadmates - // as soon as you're given them. - Assert( m_flFreeKnowledgeDuration < m_flEnemyDiscardTime ); - - m_flFreeKnowledgeDuration = m_flEnemyDiscardTime - .1; - } -} - -//----------------------------------------------------------------------------- - -void CAI_Enemies::SetEnemyDiscardTime( float flTime ) -{ - m_flEnemyDiscardTime = flTime; - - if ( m_flFreeKnowledgeDuration >= m_flEnemyDiscardTime ) - { - // If your free knowledge time is greater than your discard time, - // you'll forget about secondhand enemies passed to you by squadmates - // as soon as you're given them. - Assert( m_flFreeKnowledgeDuration < m_flEnemyDiscardTime ); - - m_flFreeKnowledgeDuration = m_flEnemyDiscardTime - .1; - } -} diff --git a/game/server/ai_memory.h b/game/server/ai_memory.h deleted file mode 100644 index 37e881296..000000000 --- a/game/server/ai_memory.h +++ /dev/null @@ -1,119 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: An NPC's memory of potential enemies -// -//=============================================================================// - -#include "mempool.h" -#include "utlmap.h" - -#ifndef AI_MEMORY_H -#define AI_MEMORY_H -#pragma once - -class CAI_Network; - -DECLARE_POINTER_HANDLE(AIEnemiesIter_t); - -const float AI_DEF_ENEMY_DISCARD_TIME = 60.0; - -#define AI_UNKNOWN_ENEMY (((CBaseEntity *)NULL)+1) // use this to probe for unseen attackers -#define AI_INVALID_TIME (FLT_MAX * -1.0) - -//----------------------------------------------------------------------------- -// AI_EnemyInfo_t -// -// Purpose: Stores relevant tactical information about an enemy -// -//----------------------------------------------------------------------------- -struct AI_EnemyInfo_t -{ - AI_EnemyInfo_t(); - - EHANDLE hEnemy; // Pointer to the enemy - - Vector vLastKnownLocation; - Vector vLastSeenLocation; - float timeLastSeen; // Last time enemy was seen - float timeFirstSeen; // First time enemy was seen - float timeLastReacquired; - float timeValidEnemy; // First time can be selected (reaction delay) - float timeLastReceivedDamageFrom; - float timeAtFirstHand; // Time at which the enemy was seen firsthand - bool bDangerMemory; // Memory of danger position w/o Enemy pointer - bool bEludedMe; // True if enemy not at last known location - bool bUnforgettable; - bool bMobbedMe; // True if enemy was part of a mob at some point - - DECLARE_SIMPLE_DATADESC(); -}; - -//----------------------------------------------------------------------------- -// CAI_Enemies -// -// Purpose: Stores a set of AI_EnemyInfo_t's -// -//----------------------------------------------------------------------------- -class CAI_Enemies -{ -public: - CAI_Enemies(void); - ~CAI_Enemies(); - - AI_EnemyInfo_t *GetFirst( AIEnemiesIter_t *pIter ); - AI_EnemyInfo_t *GetNext( AIEnemiesIter_t *pIter ); - AI_EnemyInfo_t *Find( CBaseEntity *pEntity, bool bTryDangerMemory = false ); - AI_EnemyInfo_t *GetDangerMemory(); - - int NumEnemies() const { return m_Map.Count(); } - int GetSerialNumber() const { return m_serial; } - - void RefreshMemories(void); - bool UpdateMemory( CAI_Network* pAINet, CBaseEntity *enemy, const Vector &vPosition, float reactionDelay, bool firstHand ); - void OnTookDamageFrom( CBaseEntity *pEnemy ); - - bool HasMemory( CBaseEntity *enemy ); - void ClearMemory( CBaseEntity *enemy ); - - const Vector & LastKnownPosition( CBaseEntity *pEnemy ); - const Vector & LastSeenPosition( CBaseEntity *pEnemy ); - - float TimeLastReacquired( CBaseEntity *pEnemy ); - float LastTimeSeen( CBaseEntity *pEnemy, bool bCheckDangerMemory = true ); - float FirstTimeSeen( CBaseEntity *pEnemy); - bool HasFreeKnowledgeOf( CBaseEntity *pEnemy ); - - float LastTimeTookDamageFrom( CBaseEntity *pEnemy); - - float TimeAtFirstHand( CBaseEntity *pEnemy ); - - void MarkAsEluded( CBaseEntity *enemy ); // Don't know where he is (whole squad) - bool HasEludedMe( CBaseEntity *pEnemy ); - - void SetTimeValidEnemy( CBaseEntity *pEnemy, float flTime ); - - void SetUnforgettable( CBaseEntity *pEnemy, bool bUnforgettable = true ); - void SetMobbedMe( CBaseEntity *pEnemy, bool bMobbedMe = true ); - - void SetFreeKnowledgeDuration( float flDuration ); - void SetEnemyDiscardTime( float flTime ); - float GetEnemyDiscardTime( void ) const { return m_flEnemyDiscardTime; } - - DECLARE_SIMPLE_DATADESC(); - - typedef CUtlMap CMemMap; - -private: - bool ShouldDiscardMemory( AI_EnemyInfo_t *pMemory ); - - CMemMap m_Map; - float m_flFreeKnowledgeDuration; - float m_flEnemyDiscardTime; - Vector m_vecDefaultLKP; - Vector m_vecDefaultLSP; - int m_serial; -}; - -//----------------------------------------------------------------------------- - -#endif // AI_MEMORY_H diff --git a/game/server/ai_motor.cpp b/game/server/ai_motor.cpp deleted file mode 100644 index 8572035b6..000000000 --- a/game/server/ai_motor.cpp +++ /dev/null @@ -1,1038 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -#include "animation.h" // for NOMOTION - -#include "ai_motor.h" -#include "ai_navigator.h" -#include "ai_basenpc.h" -#include "ai_localnavigator.h" -#include "ai_moveprobe.h" -#include "saverestore_utlvector.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#ifdef DEBUG -ConVar ai_draw_motor_movement( "ai_draw_motor_movement","0" ); -#endif - -extern float GetFloorZ(const Vector &origin); - -//----------------------------------------------------------------------------- - -// Use these functions to set breakpoints to find out where movement is failing -#ifdef DEBUG -void DebugNoteMovementFailure() -{ -} - -// a place to put breakpoints -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4189) -#endif -AIMoveResult_t DbgResult( AIMoveResult_t result ) -{ -#ifdef _MSC_VER - if ( result < AIMR_OK ) - { - //int breakHere = 1; - } -#endif - - switch ( result ) - { - case AIMR_BLOCKED_ENTITY: - return AIMR_BLOCKED_ENTITY; - case AIMR_BLOCKED_WORLD: - return AIMR_BLOCKED_WORLD; - case AIMR_BLOCKED_NPC: - return AIMR_BLOCKED_NPC; - case AIMR_ILLEGAL: - return AIMR_ILLEGAL; - case AIMR_OK: - return AIMR_OK; - case AIMR_CHANGE_TYPE: - return AIMR_CHANGE_TYPE; - }; - return AIMR_ILLEGAL; -}; -#endif - -//----------------------------------------------------------------------------- -// -// class CAI_Motor -// - -BEGIN_SIMPLE_DATADESC( CAI_Motor ) - // m_flMoveInterval (think transient) - DEFINE_FIELD( m_IdealYaw, FIELD_FLOAT ), - DEFINE_FIELD( m_YawSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_vecVelocity, FIELD_VECTOR ), - DEFINE_FIELD( m_vecAngularVelocity, FIELD_VECTOR ), - DEFINE_FIELD( m_nDismountSequence, FIELD_INTEGER ), - DEFINE_FIELD( m_vecDismount, FIELD_VECTOR ), - DEFINE_UTLVECTOR( m_facingQueue, FIELD_EMBEDDED ), - DEFINE_FIELD( m_bYawLocked, FIELD_BOOLEAN ), - // m_pMoveProbe -END_DATADESC() - -//----------------------------------------------------------------------------- - -CAI_Motor::CAI_Motor(CAI_BaseNPC *pOuter) - : CAI_Component( pOuter ) -{ - m_flMoveInterval = 0; - - m_IdealYaw = 0; - m_YawSpeed = 0; - m_vecVelocity = Vector( 0, 0, 0 ); - m_pMoveProbe = NULL; - m_bYawLocked = false; -} - -//----------------------------------------------------------------------------- - -CAI_Motor::~CAI_Motor() -{ -} - -//----------------------------------------------------------------------------- - -void CAI_Motor::Init( IAI_MovementSink *pMovementServices ) -{ - CAI_ProxyMovementSink::Init( pMovementServices ); - m_pMoveProbe = GetOuter()->GetMoveProbe(); // @TODO (toml 03-30-03): this is a "bad" way to grab this pointer. Components should have an explcit "init" phase. -} - -//----------------------------------------------------------------------------- -// Step iteratively toward a destination position -//----------------------------------------------------------------------------- -AIMotorMoveResult_t CAI_Motor::MoveGroundStep( const Vector &newPos, CBaseEntity *pMoveTarget, float yaw, bool bAsFarAsCan, bool bTestZ, AIMoveTrace_t *pTraceResult ) -{ - // By definition, this will produce different results than GroundMoveLimit() - // because there's no guarantee that it will step exactly one step - - // See how far toward the new position we can step... - // But don't actually test for ground geometric validity; - // if it isn't valid, there's not much we can do about it - AIMoveTrace_t moveTrace; - unsigned testFlags = AITGM_IGNORE_FLOOR; - - if ( !bTestZ ) - testFlags |= AITGM_2D; - -#ifdef DEBUG - if ( ai_draw_motor_movement.GetBool() ) - testFlags |= AITGM_DRAW_RESULTS; -#endif - - GetMoveProbe()->TestGroundMove( GetLocalOrigin(), newPos, MASK_NPCSOLID, testFlags, &moveTrace ); - if ( pTraceResult ) - { - *pTraceResult = moveTrace; - } - - bool bHitTarget = (moveTrace.pObstruction && (pMoveTarget == moveTrace.pObstruction )); - - // Move forward either if there was no obstruction or if we're told to - // move as far as we can, regardless - bool bIsBlocked = IsMoveBlocked(moveTrace.fStatus); - if ( !bIsBlocked || bAsFarAsCan || bHitTarget ) - { -#ifdef DEBUG - if ( GetMoveProbe()->CheckStandPosition( GetLocalOrigin(), MASK_NPCSOLID ) && !GetMoveProbe()->CheckStandPosition( moveTrace.vEndPosition, MASK_NPCSOLID ) ) - { - DevMsg( 2, "Warning: AI motor probably given invalid instructions\n" ); - } -#endif - - // The true argument here causes it to touch all triggers - // in the volume swept from the previous position to the current position - UTIL_SetOrigin(GetOuter(), moveTrace.vEndPosition, true); - - // check to see if our ground entity has changed - // NOTE: This is to detect changes in ground entity as the movement code has optimized out - // ground checks. So now we have to do a simple recheck to make sure we detect when we've - // stepped onto a new entity. - if ( GetOuter()->GetFlags() & FL_ONGROUND ) - { - GetOuter()->PhysicsStepRecheckGround(); - } - - // skip tiny steps, but notify the shadow object of any large steps - if ( moveTrace.flStepUpDistance > 0.1f ) - { - float height = clamp( moveTrace.flStepUpDistance, 0, StepHeight() ); - IPhysicsObject *pPhysicsObject = GetOuter()->VPhysicsGetObject(); - if ( pPhysicsObject ) - { - IPhysicsShadowController *pShadow = pPhysicsObject->GetShadowController(); - if ( pShadow ) - { - pShadow->StepUp( height ); - } - } - } - if ( yaw != -1 ) - { - QAngle angles = GetLocalAngles(); - angles.y = yaw; - SetLocalAngles( angles ); - } - if ( bHitTarget ) - return AIM_PARTIAL_HIT_TARGET; - - if ( !bIsBlocked ) - return AIM_SUCCESS; - - if ( moveTrace.fStatus == AIMR_BLOCKED_NPC ) - return AIM_PARTIAL_HIT_NPC; - - return AIM_PARTIAL_HIT_WORLD; - } - return AIM_FAILED; -} - - -//----------------------------------------------------------------------------- -// Purpose: Motion for climbing -// Input : -// Output : Returns bits (MoveStatus_b) regarding the move status -//----------------------------------------------------------------------------- - -void CAI_Motor::MoveClimbStart( const Vector &climbDest, const Vector &climbDir, float climbDist, float yaw ) -{ - // @Note (toml 06-11-02): the following code is somewhat suspect. It - // originated in CAI_BaseNPC::MoveClimb() from early June 2002 - // At the very least, state should be restored to original, not - // slammed. - // - // -----Original Message----- - // From: Jay Stelly - // Sent: Monday, June 10, 2002 3:57 PM - // To: Tom Leonard - // Subject: RE: - // - // yes. - // - // Also, there is some subtlety to using movetype. I think in - // general we want to keep things in MOVETYPE_STEP because it - // implies a bunch of things in the external game physics - // simulator. There is a flag FL_FLY we use to - // disable gravity on MOVETYPE_STEP characters. - // - // > -----Original Message----- - // > From: Tom Leonard - // > Sent: Monday, June 10, 2002 3:55 PM - // > To: Jay Stelly - // > Subject: - // > - // > Should I worry at all that the following highlighted bits of - // > code are not reciprocal for all state, and furthermore, stomp - // > other state? - - if ( fabsf( climbDir.z ) < .1 ) - { - SetActivity( GetNavigator()->GetMovementActivity() ); - } - else - { - SetActivity( (climbDir.z > -0.01 ) ? ACT_CLIMB_UP : ACT_CLIMB_DOWN ); - } - - m_nDismountSequence = SelectWeightedSequence( ACT_CLIMB_DISMOUNT ); - if (m_nDismountSequence != ACT_INVALID) - { - GetOuter()->GetSequenceLinearMotion( m_nDismountSequence, &m_vecDismount ); - } - else - { - m_vecDismount.Init(); - } - - GetOuter()->AddFlag( FL_FLY ); // No gravity - SetSolid( SOLID_BBOX ); - SetGravity( 0.0 ); - SetGroundEntity( NULL ); -} - -AIMoveResult_t CAI_Motor::MoveClimbExecute( const Vector &climbDest, const Vector &climbDir, float climbDist, float yaw, int climbNodesLeft ) -{ - if ( fabsf( climbDir.z ) > .1 ) - { - if ( GetActivity() != ACT_CLIMB_DISMOUNT ) - { - Activity desiredActivity = (climbDir.z > -0.01 ) ? ACT_CLIMB_UP : ACT_CLIMB_DOWN; - if ( GetActivity() != desiredActivity ) - { - SetActivity( desiredActivity ); - } - } - - if ( GetActivity() != ACT_CLIMB_UP && GetActivity() != ACT_CLIMB_DOWN && GetActivity() != ACT_CLIMB_DISMOUNT ) - { - DevMsg( "Climber not in a climb activity!\n" ); - return AIMR_ILLEGAL; - } - - if (m_nDismountSequence != ACT_INVALID) - { - if (GetActivity() == ACT_CLIMB_UP ) - { - if (climbNodesLeft <= 2 && climbDist < fabs( m_vecDismount.z )) - { - // fixme: No other way to force m_nIdealSequence? - GetOuter()->SetActivity( ACT_CLIMB_DISMOUNT ); - GetOuter()->SetCycle( GetOuter()->GetMovementFrame( m_vecDismount.z - climbDist ) ); - } - } - } - } - - float climbSpeed = GetOuter()->GetInstantaneousVelocity(); - - if (m_nDismountSequence != ACT_INVALID) - { - // catch situations where the climb mount/dismount finished before reaching goal - climbSpeed = MAX( climbSpeed, 30.0 ); - } - else - { - // FIXME: assume if they don't have a dismount animation then they probably don't really support climbing. - climbSpeed = 100.0; - } - - SetSmoothedVelocity( climbDir * climbSpeed ); - - if ( climbDist < climbSpeed * GetMoveInterval() ) - { - if (climbDist <= 1e-2) - climbDist = 0; - - const float climbTime = climbDist / climbSpeed; - - SetMoveInterval( GetMoveInterval() - climbTime ); - SetLocalOrigin( climbDest ); - - return AIMR_CHANGE_TYPE; - } - else - { - SetMoveInterval( 0 ); - } - - // -------------------------------------------- - // Turn to face the climb - // -------------------------------------------- - SetIdealYawAndUpdate( yaw ); - - return AIMR_OK; -} - -void CAI_Motor::MoveClimbStop() -{ - if ( GetNavigator()->GetMovementActivity() > ACT_RESET ) - SetActivity( GetNavigator()->GetMovementActivity() ); - else - SetActivity( ACT_IDLE ); - - GetOuter()->RemoveFlag( FL_FLY ); - SetSmoothedVelocity( vec3_origin ); - SetGravity( 1.0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: Motion for jumping -// Input : -// Output : Returns bits (MoveStatus_b) regarding the move status -//----------------------------------------------------------------------------- - -void CAI_Motor::MoveJumpStart( const Vector &velocity ) -{ - // take the npc off the ground and throw them in the air - SetSmoothedVelocity( velocity ); - SetGravity( GetOuter()->GetJumpGravity() ); - SetGroundEntity( NULL ); - - SetActivity( ACT_JUMP ); - - SetIdealYawAndUpdate( velocity ); -} - -int CAI_Motor::MoveJumpExecute( ) -{ - // needs to detect being hit - UpdateYaw( ); - - if (GetOuter()->GetActivity() == ACT_JUMP && GetOuter()->IsActivityFinished()) - { - SetActivity( ACT_GLIDE ); - } - - // use all the time - SetMoveInterval( 0 ); - - return AIMR_OK; -} - -AIMoveResult_t CAI_Motor::MoveJumpStop() -{ - SetSmoothedVelocity( Vector(0,0,0) ); - - if (GetOuter()->GetActivity() == ACT_GLIDE) - { - float flTime = GetOuter()->GetGroundChangeTime(); - GetOuter()->AddStepDiscontinuity( flTime, GetAbsOrigin(), GetAbsAngles() ); - - if ( SelectWeightedSequence( ACT_LAND ) == ACT_INVALID ) - return AIMR_CHANGE_TYPE; - - SetActivity( ACT_LAND ); - // FIXME: find out why the client doesn't interpolate immediatly after sequence change - // GetOuter()->SetCycle( flTime - gpGlobals->curtime ); - } - if (GetOuter()->GetActivity() != ACT_LAND || GetOuter()->IsActivityFinished()) - { - return AIMR_CHANGE_TYPE; - } - - SetMoveInterval( 0 ); - - SetGravity( 1.0f ); - - return AIMR_OK; -} - -//----------------------------------------------------------------------------- - -float CAI_Motor::GetIdealSpeed() const -{ - return GetOuter()->GetIdealSpeed(); -} - - -float CAI_Motor::GetIdealAccel() const -{ - return GetOuter()->GetIdealAccel(); -} - -//----------------------------------------------------------------------------- - -// how far will I go? -float CAI_Motor::MinStoppingDist( float flMinResult ) -{ - // FIXME: should this be a constant rate or a constant time like it is now? - float flDecelRate = GetIdealAccel(); - - if (flDecelRate > 0.0) - { - // assuming linear deceleration, how long till my V hits 0? - float t = GetCurSpeed() / flDecelRate; - // and how far will I travel? (V * t - 1/2 A t^2) - float flDist = GetCurSpeed() * t - 0.5 * flDecelRate * t * t; - - // this should always be some reasonable non-zero distance - if (flDist > flMinResult) - return flDist; - return flMinResult; - } - return flMinResult; -} - - -//----------------------------------------------------------------------------- -// Purpose: how fast should I be going ideally -//----------------------------------------------------------------------------- -float CAI_Motor::IdealVelocity( void ) -{ - // FIXME: this should be a per-entity setting so run speeds are not based on animation speeds - return GetIdealSpeed() * GetPlaybackRate(); -} - -//----------------------------------------------------------------------------- - -void CAI_Motor::ResetMoveCalculations() -{ -} - -//----------------------------------------------------------------------------- - -void CAI_Motor::MoveStart() -{ -} - -//----------------------------------------------------------------------------- - -void CAI_Motor::MoveStop() -{ - memset( &m_vecVelocity, 0, sizeof(m_vecVelocity) ); - GetOuter()->GetLocalNavigator()->ResetMoveCalculations(); -} - -//----------------------------------------------------------------------------- - -void CAI_Motor::MovePaused() -{ -} - -//----------------------------------------------------------------------------- -// Purpose: what linear accel/decel rate do I need to hit V1 in d distance? -//----------------------------------------------------------------------------- -float DeltaV( float v0, float v1, float d ) -{ - return 0.5 * (v1 * v1 - v0 * v0 ) / d; -} - - -//----------------------------------------------------------------------------- -float CAI_Motor::CalcIntervalMove() -{ - // assuming linear acceleration, how far will I travel? - return 0.5 * (GetCurSpeed() + GetIdealSpeed()) * GetMoveInterval(); -} - -//----------------------------------------------------------------------------- -// Purpose: Move the npc to the next location on its route. -// Input : vecDir - Normalized vector indicating the direction of movement. -// flDistance - distance to move -// flInterval - Time interval for this movement. -// flGoalDistance - target distance -// flGoalVelocity - target velocity -//----------------------------------------------------------------------------- - -AIMotorMoveResult_t CAI_Motor::MoveGroundExecute( const AILocalMoveGoal_t &move, AIMoveTrace_t *pTraceResult ) -{ - // -------------------------------------------- - // turn in the direction of movement - // -------------------------------------------- - MoveFacing( move ); - - // -------------------------------------------- - return MoveGroundExecuteWalk( move, GetIdealSpeed(), CalcIntervalMove(), pTraceResult ); -} - - -AIMotorMoveResult_t CAI_Motor::MoveGroundExecuteWalk( const AILocalMoveGoal_t &move, float speed, float dist, AIMoveTrace_t *pTraceResult ) -{ - bool bReachingLocalGoal = ( dist > move.maxDist ); - - // can I move farther in this interval than I'm supposed to? - if ( bReachingLocalGoal ) - { - if ( !(move.flags & AILMG_CONSUME_INTERVAL) ) - { - // only use a portion of the time interval - SetMoveInterval( GetMoveInterval() * (1 - move.maxDist / dist) ); - } - else - SetMoveInterval( 0 ); - dist = move.maxDist; - } - else - { - // use all the time - SetMoveInterval( 0 ); - } - - SetMoveVel( move.dir * speed ); - - // -------------------------------------------- - // walk the distance - // -------------------------------------------- - AIMotorMoveResult_t result = AIM_SUCCESS; - if ( dist > 0.0 ) - { - Vector vecFrom = GetLocalOrigin(); - Vector vecTo = vecFrom + move.dir * dist; - - result = MoveGroundStep( vecTo, move.pMoveTarget, -1, true, bReachingLocalGoal, pTraceResult ); - - if ( result == AIM_FAILED ) - MoveStop(); - } - else if ( !OnMoveStalled( move ) ) - { - result = AIM_FAILED; - } - - return result; -} - - -//----------------------------------------------------------------------------- -// Purpose: Move the npc to the next location on its route. -// Input : pTargetEnt - -// vecDir - Normalized vector indicating the direction of movement. -// flInterval - Time interval for this movement. -//----------------------------------------------------------------------------- - -AIMotorMoveResult_t CAI_Motor::MoveFlyExecute( const AILocalMoveGoal_t &move, AIMoveTrace_t *pTraceResult ) -{ - // turn in the direction of movement - MoveFacing( move ); - - // calc accel/decel rates - float flNewSpeed = GetIdealSpeed(); - SetMoveVel( move.dir * flNewSpeed ); - - float flTotal = 0.5 * (GetCurSpeed() + flNewSpeed) * GetMoveInterval(); - - float distance = move.maxDist; - - // can I move farther in this interval than I'm supposed to? - if (flTotal > distance) - { - // only use a portion of the time interval - SetMoveInterval( GetMoveInterval() * (1 - distance / flTotal) ); - flTotal = distance; - } - else - { - // use all the time - SetMoveInterval( 0 ); - } - - Vector vecStart, vecEnd; - vecStart = GetLocalOrigin(); - VectorMA( vecStart, flTotal, move.dir, vecEnd ); - - AIMoveTrace_t moveTrace; - GetMoveProbe()->MoveLimit( NAV_FLY, vecStart, vecEnd, MASK_NPCSOLID, NULL, &moveTrace ); - if ( pTraceResult ) - *pTraceResult = moveTrace; - - // Check for total blockage - if (fabs(moveTrace.flDistObstructed - flTotal) <= 1e-1) - { - // But if we bumped into our target, then we succeeded! - if ( move.pMoveTarget && (moveTrace.pObstruction == move.pMoveTarget) ) - return AIM_PARTIAL_HIT_TARGET; - - return AIM_FAILED; - } - - // The true argument here causes it to touch all triggers - // in the volume swept from the previous position to the current position - UTIL_SetOrigin(GetOuter(), moveTrace.vEndPosition, true); - - return (IsMoveBlocked(moveTrace.fStatus)) ? AIM_PARTIAL_HIT_WORLD : AIM_SUCCESS; -} - - -//----------------------------------------------------------------------------- -// Purpose: turn in the direction of movement -// Output : -//----------------------------------------------------------------------------- - -void CAI_Motor::MoveFacing( const AILocalMoveGoal_t &move ) -{ - if ( GetOuter()->OverrideMoveFacing( move, GetMoveInterval() ) ) - return; - - // required movement direction - float flMoveYaw = UTIL_VecToYaw( move.dir ); - - int nSequence = GetSequence(); - float fSequenceMoveYaw = GetSequenceMoveYaw( nSequence ); - if ( fSequenceMoveYaw == NOMOTION ) - { - fSequenceMoveYaw = 0; - } - - if (!HasPoseParameter( nSequence, GetOuter()->LookupPoseMoveYaw() )) - { - SetIdealYawAndUpdate( UTIL_AngleMod( flMoveYaw - fSequenceMoveYaw ) ); - } - else - { - // FIXME: move this up to navigator so that path goals can ignore these overrides. - Vector dir; - float flInfluence = GetFacingDirection( dir ); - dir = move.facing * (1 - flInfluence) + dir * flInfluence; - VectorNormalize( dir ); - - // ideal facing direction - float idealYaw = UTIL_AngleMod( UTIL_VecToYaw( dir ) ); - - // FIXME: facing has important max velocity issues - SetIdealYawAndUpdate( idealYaw ); - - // find movement direction to compensate for not being turned far enough - float flDiff = UTIL_AngleDiff( flMoveYaw, GetLocalAngles().y ); - SetPoseParameter( GetOuter()->LookupPoseMoveYaw(), flDiff ); - /* - if ((GetOuter()->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT)) - { - DevMsg( "move %.1f : diff %.1f : ideal %.1f\n", flMoveYaw, flDiff, m_IdealYaw ); - } - */ - } -} - -//----------------------------------------------------------------------------- -// Purpose: Set the ideal yaw and run the current or specified timestep -// worth of rotation. -//----------------------------------------------------------------------------- - -void CAI_Motor::SetIdealYawAndUpdate( float idealYaw, float yawSpeed) -{ - SetIdealYaw( idealYaw ); - if (yawSpeed == AI_CALC_YAW_SPEED) - RecalculateYawSpeed(); - else if (yawSpeed != AI_KEEP_YAW_SPEED) - SetYawSpeed( yawSpeed ); - UpdateYaw(-1); -} - - -//----------------------------------------------------------------------------- - -void CAI_Motor::RecalculateYawSpeed() -{ - SetYawSpeed( CalcYawSpeed() ); -} - -//----------------------------------------------------------------------------- - -float AI_ClampYaw( float yawSpeedPerSec, float current, float target, float time ) -{ - if (current != target) - { - float speed = yawSpeedPerSec * time; - float move = target - current; - - if (target > current) - { - if (move >= 180) - move = move - 360; - } - else - { - if (move <= -180) - move = move + 360; - } - - if (move > 0) - {// turning to the npc's left - if (move > speed) - move = speed; - } - else - {// turning to the npc's right - if (move < -speed) - move = -speed; - } - - return UTIL_AngleMod(current + move); - } - - return target; -} - -//----------------------------------------------------------------------------- -// Purpose: Turns a npc towards its ideal yaw. -// Input : yawSpeed - Yaw speed in degrees per 1/10th of a second. -// flInterval - Time interval to turn, -1 uses time since last think. -// Output : Returns the number of degrees turned. -//----------------------------------------------------------------------------- -void CAI_Motor::UpdateYaw( int yawSpeed ) -{ - // Don't do this if our yaw is locked - if ( IsYawLocked() ) - return; - - GetOuter()->SetUpdatedYaw(); - - float yaw = static_cast(yawSpeed); - float ideal, current, newYaw; - - if ( yaw == -1.0f ) - yaw = GetYawSpeed(); - - // NOTE: GetIdealYaw() will never exactly be reached because UTIL_AngleMod - // also truncates the angle to 16 bits of resolution. So lets truncate it here. - current = UTIL_AngleMod( GetLocalAngles().y ); - ideal = UTIL_AngleMod( GetIdealYaw() ); - - // FIXME: this needs a proper interval - float dt = MIN( 0.2, gpGlobals->curtime - GetLastThink() ); - - newYaw = AI_ClampYaw( yaw * 10.0f, current, ideal, dt ); - - if (newYaw != current) - { - QAngle angles = GetLocalAngles(); - angles.y = newYaw; - SetLocalAngles( angles ); - } -} - - -//========================================================= -// DeltaIdealYaw - returns the difference ( in degrees ) between -// npc's current yaw and ideal_yaw -// -// Positive result is left turn, negative is right turn -//========================================================= -float CAI_Motor::DeltaIdealYaw ( void ) -{ - float flCurrentYaw; - - flCurrentYaw = UTIL_AngleMod( GetLocalAngles().y ); - - if ( flCurrentYaw == GetIdealYaw() ) - { - return 0; - } - - - return UTIL_AngleDiff( GetIdealYaw(), flCurrentYaw ); -} - - -//----------------------------------------------------------------------------- - -void CAI_Motor::SetIdealYawToTarget( const Vector &target, float noise, float offset ) -{ - float base = CalcIdealYaw( target ); - base += offset; - if ( noise > 0 ) - { - noise *= 0.5; - base += random->RandomFloat( -noise, noise ); - if ( base < 0 ) - base += 360; - else if ( base >= 360 ) - base -= 360; - } - SetIdealYaw( base ); -} - -//----------------------------------------------------------------------------- - -void CAI_Motor::SetIdealYawToTargetAndUpdate( const Vector &target, float yawSpeed ) -{ - SetIdealYawAndUpdate( CalcIdealYaw( target ), yawSpeed ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Keep track of multiple objects that the npc is interested in facing -//----------------------------------------------------------------------------- -void CAI_Motor::AddFacingTarget( CBaseEntity *pTarget, float flImportance, float flDuration, float flRamp ) -{ - m_facingQueue.Add( pTarget, flImportance, flDuration, flRamp ); -} - - -void CAI_Motor::AddFacingTarget( const Vector &vecPosition, float flImportance, float flDuration, float flRamp ) -{ - m_facingQueue.Add( vecPosition, flImportance, flDuration, flRamp ); -} - -void CAI_Motor::AddFacingTarget( CBaseEntity *pTarget, const Vector &vecPosition, float flImportance, float flDuration, float flRamp ) -{ - m_facingQueue.Add( pTarget, vecPosition, flImportance, flDuration, flRamp ); -} - - -float CAI_Motor::GetFacingDirection( Vector &vecDir ) -{ - float flTotalInterest = 0.0; - vecDir = Vector( 0, 0, 0 ); - - int i; - - // clean up facing targets - for (i = 0; i < m_facingQueue.Count();) - { - if (!m_facingQueue[i].IsActive()) - { - m_facingQueue.Remove( i ); - } - else - { - i++; - } - } - - for (i = 0; i < m_facingQueue.Count(); i++) - { - float flInterest = m_facingQueue[i].Interest( ); - Vector tmp = m_facingQueue[i].GetPosition() - GetAbsOrigin(); - - // NDebugOverlay::Line( m_facingQueue[i].GetPosition(), GetAbsOrigin(), 255, 0, 0, false, 0.1 ); - - VectorNormalize( tmp ); - - vecDir = vecDir * (1 - flInterest) + tmp * flInterest; - - flTotalInterest = (1 - (1 - flTotalInterest) * (1 - flInterest)); - - VectorNormalize( vecDir ); - } - - return flTotalInterest; -} - - -//----------------------------------------------------------------------------- - -AIMoveResult_t CAI_Motor::MoveNormalExecute( const AILocalMoveGoal_t &move ) -{ - AI_PROFILE_SCOPE(CAI_Motor_MoveNormalExecute); - - // -------------------------------- - - AIMotorMoveResult_t fMotorResult; - AIMoveTrace_t moveTrace; - - if ( move.navType == NAV_GROUND ) - { - fMotorResult = MoveGroundExecute( move, &moveTrace ); - } - else - { - Assert( move.navType == NAV_FLY ); - fMotorResult = MoveFlyExecute( move, &moveTrace ); - } - - static AIMoveResult_t moveResults[] = - { - AIMR_ILLEGAL, // AIM_FAILED - AIMR_OK, // AIM_SUCCESS - AIMR_BLOCKED_NPC, // AIM_PARTIAL_HIT_NPC - AIMR_BLOCKED_WORLD, // AIM_PARTIAL_HIT_WORLD - AIMR_BLOCKED_WORLD, // AIM_PARTIAL_HIT_TARGET - }; - Assert( (AIMotorMoveResult_t)ARRAYSIZE( moveResults ) == AIM_NUM_RESULTS && fMotorResult >= 0 && fMotorResult <= (AIMotorMoveResult_t)ARRAYSIZE( moveResults ) ); - - AIMoveResult_t result = moveResults[fMotorResult]; - - if ( result != AIMR_OK ) - { - OnMoveExecuteFailed( move, moveTrace, fMotorResult, &result ); - SetMoveInterval( 0 ); // always consume interval on failure, even if overridden by OnMoveExecuteFailed() - } - - return DbgResult( result ); -} - -//----------------------------------------------------------------------------- -// Purpose: Look ahead my stopping distance, or at least my hull width -//----------------------------------------------------------------------------- -float CAI_Motor::MinCheckDist( void ) -{ - // Take the groundspeed into account - float flMoveDist = GetMoveInterval() * GetIdealSpeed(); - float flMinDist = MAX( MinStoppingDist(), flMoveDist); - if ( flMinDist < GetHullWidth() ) - flMinDist = GetHullWidth(); - return flMinDist; -} - -//----------------------------------------------------------------------------- - -CAI_Navigator *CAI_Motor::GetNavigator( void ) -{ - return GetOuter()->GetNavigator(); -} - -int CAI_Motor::SelectWeightedSequence ( Activity activity ) -{ - return GetOuter()->SelectWeightedSequence ( activity ); -} - -float CAI_Motor::GetSequenceGroundSpeed( int iSequence ) -{ - return GetOuter()->GetSequenceGroundSpeed( iSequence ); -} - - -//----------------------------------------------------------------------------- - -void CAI_Motor::SetSmoothedVelocity(const Vector &vecVelocity) -{ - GetOuter()->SetAbsVelocity(vecVelocity); -} - -Vector CAI_Motor::GetSmoothedVelocity() -{ - return GetOuter()->GetSmoothedVelocity(); -} - -float CAI_Motor::StepHeight() const -{ - return GetOuter()->StepHeight(); -} - -bool CAI_Motor::CanStandOn( CBaseEntity *pSurface ) const -{ - return GetOuter()->CanStandOn( pSurface ); -} - -float CAI_Motor::CalcIdealYaw( const Vector &vecTarget ) -{ - return GetOuter()->CalcIdealYaw( vecTarget ); -} - -float CAI_Motor::SetBoneController( int iController, float flValue ) -{ - return GetOuter()->SetBoneController( iController, flValue ); -} - -float CAI_Motor::GetSequenceMoveYaw( int iSequence ) -{ - return GetOuter()->GetSequenceMoveYaw( iSequence ); -} - -void CAI_Motor::SetPlaybackRate( float flRate ) -{ - return GetOuter()->SetPlaybackRate( flRate ); -} - -float CAI_Motor::GetPlaybackRate() -{ - return GetOuter()->GetPlaybackRate(); -} - -float CAI_Motor::SetPoseParameter( const char *szName, float flValue ) -{ - return GetOuter()->SetPoseParameter( szName, flValue ); -} - -float CAI_Motor::GetPoseParameter( const char *szName ) -{ - return GetOuter()->GetPoseParameter( szName ); -} - -bool CAI_Motor::HasPoseParameter( int iSequence, const char *szName ) -{ - return GetOuter()->HasPoseParameter( iSequence, szName ); -} - -float CAI_Motor::SetPoseParameter( int iParameter, float flValue ) -{ - return GetOuter()->SetPoseParameter( iParameter, flValue ); -} - -bool CAI_Motor::HasPoseParameter( int iSequence, int iParameter ) -{ - return GetOuter()->HasPoseParameter( iSequence, iParameter ); -} - -void CAI_Motor::SetMoveType( MoveType_t val, MoveCollide_t moveCollide ) -{ - GetOuter()->SetMoveType( val, moveCollide ); -} - -//============================================================================= - diff --git a/game/server/ai_motor.h b/game/server/ai_motor.h deleted file mode 100644 index 6548b6a64..000000000 --- a/game/server/ai_motor.h +++ /dev/null @@ -1,225 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_MOTOR_H -#define AI_MOTOR_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "simtimer.h" -#include "ai_component.h" -#include "ai_navtype.h" -#include "ai_movetypes.h" -#include "AI_Interest_Target.h" - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -enum Navigation_t; -class CAI_PlaneSolver; -class CAI_MoveProbe; -class CAI_Navigator; - -#define AI_CALC_YAW_SPEED -1 -#define AI_KEEP_YAW_SPEED -2 - -//----------------------------------------------------------------------------- - -float AI_ClampYaw( float yawSpeedPerSec, float current, float target, float time ); - -//----------------------------------------------------------------------------- -// CAI_Motor -// -// Purpose: Implements the primitive locomotion of AIs. -//----------------------------------------------------------------------------- - -class CAI_Motor : public CAI_Component, - public CAI_ProxyMovementSink -{ -public: - CAI_Motor(CAI_BaseNPC *pOuter); - virtual ~CAI_Motor(); - - void Init( IAI_MovementSink *pMovementServices ); - - // -------------------------------- - // The current timestep the motor is working on - // -------------------------------- - float GetMoveInterval() { return m_flMoveInterval; } - float SetMoveInterval( float flInterval ) { return (m_flMoveInterval = flInterval); } - - // ---------------------------------------------------- - // Translational movement - // ---------------------------------------------------- - AIMoveResult_t MoveNormalExecute( const AILocalMoveGoal_t &move ); - - virtual void MoveClimbStart( const Vector &climbDest, const Vector &climbDir, float climbDist, float yaw ); - virtual AIMoveResult_t MoveClimbExecute( const Vector &climbDest, const Vector &climbDir, float climbDist, float yaw, int climbNodesLeft ); - virtual void MoveClimbStop(); - - //--------------------------------- - - - virtual void MoveJumpStart( const Vector &velocity ); - virtual int MoveJumpExecute(); - virtual AIMoveResult_t MoveJumpStop(); - - virtual void ResetMoveCalculations(); - virtual void MoveStart(); - virtual void MoveStop(); - virtual void MovePaused(); - - //--------------------------------- - - float GetIdealSpeed() const; - float GetIdealAccel() const; - float GetCurSpeed() const { return m_vecVelocity.Length(); } - const Vector & GetCurVel() const { return m_vecVelocity; } - - virtual float OverrideMaxYawSpeed( Activity activity ) { return -1; } - bool IsDeceleratingToGoal() const { return false; } - - //--------------------------------- - // Raw ground step forward to the specifed position - // - - AIMotorMoveResult_t MoveGroundStep( const Vector &newPos, CBaseEntity *pMoveTarget = NULL, float yaw = -1, bool bAsFarAsCan = true, bool bTestZ = true, AIMoveTrace_t *pTraceResult = NULL ); - - // ---------------------------------------------------- - // Rotational movement (yaw); goal and speed - // ---------------------------------------------------- - - void SetYawSpeed( float yawSpeed ) { m_YawSpeed = yawSpeed; } - float GetYawSpeed() const { return m_YawSpeed; } - float GetIdealYaw() const { return m_IdealYaw; } - void SetIdealYaw( float idealYaw) { m_IdealYaw = idealYaw; } - - // Set ideal yaw specified as a vector - void SetIdealYaw( const Vector &vecFacing) { SetIdealYaw( UTIL_VecToYaw( vecFacing )); } - - // Set ideal yaw based on a specified target - void SetIdealYawToTarget( const Vector &target, float noise = 0.0, float offset = 0.0 ); - - // Set the ideal yaw and run the current or specified timestep worth of rotation. Note - // it is not correct to call any "update" variant of these methods more - // than once per think cycle - void SetIdealYawAndUpdate( float idealYaw, float yawSpeed = AI_CALC_YAW_SPEED ); - void SetIdealYawAndUpdate( const Vector &vecFacing, float yawSpeed = AI_CALC_YAW_SPEED ) { SetIdealYawAndUpdate( UTIL_VecToYaw( vecFacing ), yawSpeed ); } - void SetIdealYawToTargetAndUpdate( const Vector &target, float yawSpeed = AI_CALC_YAW_SPEED ); - - // Add multiple facing goals while moving/standing still. - virtual void AddFacingTarget( CBaseEntity *pTarget, float flImportance, float flDuration, float flRamp = 0.0 ); - virtual void AddFacingTarget( const Vector &vecPosition, float flImportance, float flDuration, float flRamp = 0.0 ); - virtual void AddFacingTarget( CBaseEntity *pTarget, const Vector &vecPosition, float flImportance, float flDuration, float flRamp = 0.0 ); - virtual float GetFacingDirection( Vector &vecDir ); - - // Force the heading to the ideal yaw - void SnapYaw() { UpdateYaw(360); } - - // Run the current or specified timestep worth of rotation - virtual void UpdateYaw( int speed = -1 ); - - // - virtual void RecalculateYawSpeed(); - - // Returns the difference ( in degrees ) between npc's current yaw and ideal_yaw - float DeltaIdealYaw(); - - // Issues turn gestures when needed due to turning - virtual void MaintainTurnActivity( void ) { }; - virtual bool AddTurnGesture( float flYD ) { return false; }; - - // -------------------------------- - // Move primitives - // -------------------------------- - virtual float MinStoppingDist( float flMinResult = 10.0 ); // how far before I can come to a complete stop? - virtual float MinCheckDist(); // how far should I look ahead in my route? - - //--------------------------------- - - CAI_Navigator *GetNavigator( void ); - int SelectWeightedSequence( Activity activity ); - float GetSequenceGroundSpeed( int iSequence ); - - float CalcIntervalMove(); - - // Yaw locking - bool IsYawLocked( void ) const { return m_bYawLocked; } - void SetYawLocked( bool state ) { m_bYawLocked = state; } - -protected: - - // - // Common services provided by CAI_BaseNPC, Convenience methods to simplify derived code - // - CAI_MoveProbe * GetMoveProbe() { return m_pMoveProbe; } - void SetSmoothedVelocity(const Vector &vecVelocity); - Vector GetSmoothedVelocity(); - float CalcIdealYaw( const Vector &vecTarget ); - float SetBoneController ( int iController, float flValue ); - float GetSequenceMoveYaw( int iSequence ); - void SetPlaybackRate( float flRate ); - float GetPlaybackRate(); //get - float SetPoseParameter( const char *szName, float flValue ); - float SetPoseParameter( int iParameter, float flValue ); - float GetPoseParameter( const char *szName ); - bool HasPoseParameter( int iSequence, const char *szName ); - bool HasPoseParameter( int iSequence, int iParameter ); - void SetMoveType( MoveType_t val, MoveCollide_t moveCollide = MOVECOLLIDE_DEFAULT ); - float StepHeight() const; - bool CanStandOn( CBaseEntity *pSurface ) const; - - // ---------------------------------------------------- - // Primitives - // ---------------------------------------------------- - - virtual void MoveFacing( const AILocalMoveGoal_t &move ); - - virtual AIMotorMoveResult_t MoveGroundExecute( const AILocalMoveGoal_t &move, AIMoveTrace_t *pTraceResult ); - AIMotorMoveResult_t MoveGroundExecuteWalk( const AILocalMoveGoal_t &move, float speed, float dist, AIMoveTrace_t *pTraceResult ); - virtual AIMotorMoveResult_t MoveFlyExecute( const AILocalMoveGoal_t &move, AIMoveTrace_t *pTraceResult ); - -protected: // made protected while animation transition details worked out, private: - - // -------------------------------- - void SetMoveVel(const Vector &velocity) { m_vecVelocity = velocity; } - float IdealVelocity(); // how fast should I be moving in an ideal state? - - // -------------------------------- - float m_flMoveInterval; - - float m_IdealYaw; - float m_YawSpeed; - - Vector m_vecVelocity; - Vector m_vecAngularVelocity; - - // -------------------------------- - - int m_nDismountSequence; - Vector m_vecDismount; - - // -------------------------------- - - CAI_InterestTarget m_facingQueue; - - // -------------------------------- - - CAI_MoveProbe * m_pMoveProbe; - - bool m_bYawLocked; - - //--------------------------------- -public: - DECLARE_SIMPLE_DATADESC(); -}; - -//============================================================================= - -#endif // AI_MOTOR_H diff --git a/game/server/ai_moveprobe.cpp b/game/server/ai_moveprobe.cpp deleted file mode 100644 index db2339515..000000000 --- a/game/server/ai_moveprobe.cpp +++ /dev/null @@ -1,1389 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" - -#include "modelentities.h" -#include "iservervehicle.h" -#include "movevars_shared.h" - -#include "ai_moveprobe.h" - -#include "ai_basenpc.h" -#include "ai_routedist.h" -#include "props.h" -#include "vphysics/object_hash.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#undef LOCAL_STEP_SIZE -// FIXME: this should be based in their hull width -#define LOCAL_STEP_SIZE 16.0 // 8 // 16 - -// If set to 1, results will be drawn for moveprobes done by player-selected NPCs -ConVar ai_moveprobe_debug( "ai_moveprobe_debug", "0" ); -ConVar ai_moveprobe_jump_debug( "ai_moveprobe_jump_debug", "0" ); -ConVar ai_moveprobe_usetracelist( "ai_moveprobe_usetracelist", "0" ); - -ConVar ai_strong_optimizations_no_checkstand( "ai_strong_optimizations_no_checkstand", "0" ); - -#ifdef DEBUG -ConVar ai_old_check_stand_position( "ai_old_check_stand_position", "0" ); -#define UseOldCheckStandPosition() (ai_old_check_stand_position.GetBool()) -#else -#define UseOldCheckStandPosition() (false) -#endif - -//----------------------------------------------------------------------------- - -// We may be able to remove this, but due to certain collision -// problems on displacements, and due to the fact that CheckStep is currently -// being called from code outside motor code, we may need to give it a little -// room to avoid boundary condition problems. Also note that this will -// cause us to start 2*EPSILON above the ground the next time that this -// function is called, but for now, that appears to not be a problem. -float MOVE_HEIGHT_EPSILON = 0.0625f; - -CON_COMMAND( ai_set_move_height_epsilon, "Set how high AI bumps up ground walkers when checking steps" ) -{ - if ( args.ArgC() > 1 ) - { - float newEps = atof( args[1] ); - if ( newEps >= 0.0 && newEps < 1.0 ) - { - MOVE_HEIGHT_EPSILON = newEps; - } - Msg( "Epsilon now %f\n", MOVE_HEIGHT_EPSILON ); - } -} - -//----------------------------------------------------------------------------- - -BEGIN_SIMPLE_DATADESC(CAI_MoveProbe) - // m_pTraceListData (not saved, a cached item) - DEFINE_FIELD( m_bIgnoreTransientEntities, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hLastBlockingEnt, FIELD_EHANDLE ), - -END_DATADESC(); - - -//----------------------------------------------------------------------------- -// Categorizes the blocker and sets the appropriate bits -//----------------------------------------------------------------------------- -AIMoveResult_t AIComputeBlockerMoveResult( CBaseEntity *pBlocker ) -{ - if (pBlocker->MyNPCPointer()) - return AIMR_BLOCKED_NPC; - else if (pBlocker->entindex() == 0) - return AIMR_BLOCKED_WORLD; - return AIMR_BLOCKED_ENTITY; -} - -//----------------------------------------------------------------------------- -bool CAI_MoveProbe::ShouldBrushBeIgnored( CBaseEntity *pEntity ) -{ - if ( pEntity->m_iClassname == g_iszFuncBrushClassname ) - { - CFuncBrush *pFuncBrush = assert_cast(pEntity); - - // this is true if my class or entity name matches the exclusion name on the func brush -#if HL2_EPISODIC - bool nameMatches = ( pFuncBrush->m_iszExcludedClass == GetOuter()->m_iClassname ) || GetOuter()->NameMatches(pFuncBrush->m_iszExcludedClass); -#else // do not match against entity name in base HL2 (just in case there is some case somewhere that might be broken by this) - bool nameMatches = ( pFuncBrush->m_iszExcludedClass == GetOuter()->m_iClassname ); -#endif - - // return true (ignore brush) if the name matches, or, if exclusion is inverted, if the name does not match - return ( pFuncBrush->m_bInvertExclusion ? !nameMatches : nameMatches ); - } - - return false; -} - -//----------------------------------------------------------------------------- - -void CAI_MoveProbe::TraceLine( const Vector &vecStart, const Vector &vecEnd, unsigned int mask, - bool bUseCollisionGroup, trace_t *pResult ) const -{ - int collisionGroup = (bUseCollisionGroup) ? - GetCollisionGroup() : - COLLISION_GROUP_NONE; - - CTraceFilterNav traceFilter( const_cast(GetOuter()), m_bIgnoreTransientEntities, GetOuter(), collisionGroup ); - - AI_TraceLine( vecStart, vecEnd, mask, &traceFilter, pResult ); - -#ifdef _DEBUG - // Just to make sure; I'm not sure that this is always the case but it should be - if (pResult->allsolid) - { - Assert( pResult->startsolid ); - } -#endif -} - -//----------------------------------------------------------------------------- - -CAI_MoveProbe::CAI_MoveProbe(CAI_BaseNPC *pOuter) - : CAI_Component( pOuter ), - m_bIgnoreTransientEntities( false ), - m_pTraceListData( NULL ) -{ -} - -//----------------------------------------------------------------------------- - -CAI_MoveProbe::~CAI_MoveProbe() -{ - delete m_pTraceListData; -} - -//----------------------------------------------------------------------------- - -void CAI_MoveProbe::TraceHull( - const Vector &vecStart, const Vector &vecEnd, const Vector &hullMin, - const Vector &hullMax, unsigned int mask, trace_t *pResult ) const -{ - AI_PROFILE_SCOPE( CAI_MoveProbe_TraceHull ); - - CTraceFilterNav traceFilter( const_cast(GetOuter()), m_bIgnoreTransientEntities, GetOuter(), GetCollisionGroup() ); - - Ray_t ray; - ray.Init( vecStart, vecEnd, hullMin, hullMax ); - - if ( !m_pTraceListData || m_pTraceListData->IsEmpty() ) - enginetrace->TraceRay( ray, mask, &traceFilter, pResult ); - else - { - enginetrace->TraceRayAgainstLeafAndEntityList( ray, *(const_cast(this)->m_pTraceListData), mask, &traceFilter, pResult ); -#if 0 - trace_t verificationTrace; - enginetrace->TraceRay( ray, mask, &traceFilter, &verificationTrace ); - Assert( fabsf(verificationTrace.fraction - pResult->fraction) < 0.01 && - VectorsAreEqual( verificationTrace.endpos, pResult->endpos, 0.01 ) && - verificationTrace.m_pEnt == pResult->m_pEnt ); - -#endif - } - - if ( r_visualizetraces.GetBool() ) - DebugDrawLine( pResult->startpos, pResult->endpos, 255, 255, 0, true, -1.0f ); - - //NDebugOverlay::SweptBox( vecStart, vecEnd, hullMin, hullMax, vec3_angle, 255, 255, 0, 0, 10 ); - // Just to make sure; I'm not sure that this is always the case but it should be - Assert( !pResult->allsolid || pResult->startsolid ); -} - -//----------------------------------------------------------------------------- - -void CAI_MoveProbe::TraceHull( const Vector &vecStart, const Vector &vecEnd, - unsigned int mask, trace_t *pResult ) const -{ - TraceHull( vecStart, vecEnd, WorldAlignMins(), WorldAlignMaxs(), mask, pResult); -} - -//----------------------------------------------------------------------------- - -void CAI_MoveProbe::SetupCheckStepTraceListData( const CheckStepArgs_t &args ) const -{ - if ( ai_moveprobe_usetracelist.GetBool() ) - { - Ray_t ray; - Vector hullMin = WorldAlignMins(); - Vector hullMax = WorldAlignMaxs(); - - hullMax.z += MOVE_HEIGHT_EPSILON; - hullMin.z -= MOVE_HEIGHT_EPSILON; - - hullMax.z += args.stepHeight; - hullMin.z -= args.stepHeight; - - if ( args.groundTest != STEP_DONT_CHECK_GROUND ) - hullMin.z -= args.stepHeight; - - hullMax.x += args.minStepLanding; - hullMin.x -= args.minStepLanding; - - hullMax.y += args.minStepLanding; - hullMin.y -= args.minStepLanding; - - Vector vecEnd; - Vector2DMA( args.vecStart.AsVector2D(), args.stepSize, args.vecStepDir.AsVector2D(), vecEnd.AsVector2D() ); - vecEnd.z = args.vecStart.z; - - ray.Init( args.vecStart, vecEnd, hullMin, hullMax ); - - if ( !m_pTraceListData ) - { - const_cast(this)->m_pTraceListData = new CTraceListData; - } - enginetrace->SetupLeafAndEntityListRay( ray, *(const_cast(this)->m_pTraceListData) ); - } -} - -//----------------------------------------------------------------------------- -// CheckStep() is a fundamentally 2D operation! vecEnd.z is ignored. -// We can step up one StepHeight or down one StepHeight from vecStart -//----------------------------------------------------------------------------- -bool g_bAIDebugStep = false; - -bool CAI_MoveProbe::CheckStep( const CheckStepArgs_t &args, CheckStepResult_t *pResult ) const -{ - AI_PROFILE_SCOPE( CAI_MoveProbe_CheckStep ); - - Vector vecEnd; - unsigned collisionMask = args.collisionMask; - VectorMA( args.vecStart, args.stepSize, args.vecStepDir, vecEnd ); - - pResult->endPoint = args.vecStart; - pResult->fStartSolid = false; - pResult->hitNormal = vec3_origin; - pResult->pBlocker = NULL; - - // This is fundamentally a 2D operation; we just want the end - // position in Z to be no more than a step height from the start position - Vector stepStart( args.vecStart.x, args.vecStart.y, args.vecStart.z + MOVE_HEIGHT_EPSILON ); - Vector stepEnd( vecEnd.x, vecEnd.y, args.vecStart.z + MOVE_HEIGHT_EPSILON ); - - if ( g_bAIDebugStep ) - { - NDebugOverlay::Line( stepStart, stepEnd, 255, 255, 255, true, 5 ); - NDebugOverlay::Cross3D( stepEnd, 32, 255, 255, 255, true, 5 ); - } - - trace_t trace; - - AI_PROFILE_SCOPE_BEGIN( CAI_Motor_CheckStep_Forward ); - - TraceHull( stepStart, stepEnd, collisionMask, &trace ); - - if (trace.startsolid || (trace.fraction < 1)) - { - // Either the entity is starting embedded in the world, or it hit something. - // Raise the box by the step height and try again - trace_t stepTrace; - - if ( !trace.startsolid ) - { - if ( g_bAIDebugStep ) - NDebugOverlay::Box( trace.endpos, WorldAlignMins(), WorldAlignMaxs(), 64, 64, 64, 0, 5 ); - - // Advance to first obstruction point - stepStart = trace.endpos; - - // Trace up to locate the maximum step up in the space - Vector stepUp( stepStart ); - stepUp.z += args.stepHeight; - TraceHull( stepStart, stepUp, collisionMask, &stepTrace ); - - if ( g_bAIDebugStep ) - NDebugOverlay::Box( stepTrace.endpos, WorldAlignMins(), WorldAlignMaxs(), 96, 96, 96, 0, 5 ); - - stepStart = stepTrace.endpos; - } - else - stepStart.z += args.stepHeight; - - // Now move forward - stepEnd.z = stepStart.z; - - TraceHull( stepStart, stepEnd, collisionMask, &stepTrace ); - bool bRejectStep = false; - - // Ok, raising it didn't work; we're obstructed - if (stepTrace.startsolid || stepTrace.fraction <= 0.01 ) - { - // If started in solid, and never escaped from solid, bail - if ( trace.startsolid ) - { - pResult->fStartSolid = true; - pResult->pBlocker = trace.m_pEnt; - pResult->hitNormal = trace.plane.normal; - return false; - } - - bRejectStep = true; - } - else - { - if ( g_bAIDebugStep ) - NDebugOverlay::Box( stepTrace.endpos, WorldAlignMins(), WorldAlignMaxs(), 128, 128, 128, 0, 5 ); - - // If didn't step forward enough to qualify as a step, try as if stepped forward to - // confirm there's potentially enough space to "land" - float landingDistSq = ( stepEnd.AsVector2D() - stepStart.AsVector2D() ).LengthSqr(); - float requiredLandingDistSq = args.minStepLanding*args.minStepLanding; - if ( landingDistSq < requiredLandingDistSq ) - { - trace_t landingTrace; - Vector stepEndWithLanding; - - VectorMA( stepStart, args.minStepLanding, args.vecStepDir, stepEndWithLanding ); - TraceHull( stepStart, stepEndWithLanding, collisionMask, &landingTrace ); - if ( landingTrace.fraction < 1 ) - { - if ( g_bAIDebugStep ) - NDebugOverlay::Box( landingTrace.endpos, WorldAlignMins() + Vector(0, 0, 0.1), WorldAlignMaxs() + Vector(0, 0, 0.1), 255, 0, 0, 0, 5 ); - - bRejectStep = true; - if ( landingTrace.m_pEnt ) - pResult->pBlocker = landingTrace.m_pEnt; - } - } - else if ( ( stepTrace.endpos.AsVector2D() - stepStart.AsVector2D() ).LengthSqr() < requiredLandingDistSq ) - { - if ( g_bAIDebugStep ) - NDebugOverlay::Box( stepTrace.endpos, WorldAlignMins() + Vector(0, 0, 0.1), WorldAlignMaxs() + Vector(0, 0, 0.1), 255, 0, 0, 0, 5 ); - - bRejectStep = true; - } - } - - // If trace.fraction == 0, we fall through and check the position - // we moved up to for suitability. This allows for sub-step - // traces if the position ends up being suitable - if ( !bRejectStep ) - trace = stepTrace; - - if ( trace.fraction < 1.0 ) - { - if ( !pResult->pBlocker ) - pResult->pBlocker = trace.m_pEnt; - pResult->hitNormal = trace.plane.normal; - } - - stepEnd = trace.endpos; - } - - AI_PROFILE_SCOPE_END(); - - AI_PROFILE_SCOPE_BEGIN( CAI_Motor_CheckStep_Down ); - // seems okay, now find the ground - // The ground is only valid if it's within a step height of the original position - Assert( VectorsAreEqual( trace.endpos, stepEnd, 1e-3 ) ); - stepStart = stepEnd; - stepEnd.z = args.vecStart.z - args.stepHeight * args.stepDownMultiplier - MOVE_HEIGHT_EPSILON; - - TraceHull( stepStart, stepEnd, collisionMask, &trace ); - - // in empty space, lie and say we hit the world - if (trace.fraction == 1.0f) - { - if ( g_bAIDebugStep ) - NDebugOverlay::Box( trace.endpos, WorldAlignMins(), WorldAlignMaxs(), 255, 0, 0, 0, 5 ); - - Assert( pResult->endPoint == args.vecStart ); - if ( const_cast(this)->GetOuter()->GetGroundEntity() ) - { - pResult->pBlocker = const_cast(this)->GetOuter()->GetGroundEntity(); - } - else - { - pResult->pBlocker = GetContainingEntity( INDEXENT(0) ); - } - return false; - } - - if ( g_bAIDebugStep ) - NDebugOverlay::Box( trace.endpos, WorldAlignMins(), WorldAlignMaxs(), 160, 160, 160, 0, 5 ); - - AI_PROFILE_SCOPE_END(); - - // Checks to see if the thing we're on is a *type* of thing we - // are capable of standing on. Always true ffor our current ground ent - // otherwise we'll be stuck forever - CBaseEntity *pFloor = trace.m_pEnt; - if ( pFloor != GetOuter()->GetGroundEntity() && !CanStandOn( pFloor ) ) - { - if ( g_bAIDebugStep ) - NDebugOverlay::Cross3D( trace.endpos, 32, 255, 0, 0, true, 5 ); - - Assert( pResult->endPoint == args.vecStart ); - pResult->pBlocker = pFloor; - return false; - } - - // Don't step up onto an odd slope - if ( trace.endpos.z - args.vecStart.z > args.stepHeight * 0.5 && - ( ( pFloor->IsWorld() && trace.hitbox > 0 ) || - dynamic_cast( pFloor ) ) ) - { - if ( fabsf( trace.plane.normal.Dot( Vector(1, 0, 0) ) ) > .4 ) - { - Assert( pResult->endPoint == args.vecStart ); - pResult->pBlocker = pFloor; - - if ( g_bAIDebugStep ) - NDebugOverlay::Cross3D( trace.endpos, 32, 0, 0, 255, true, 5 ); - return false; - } - } - - if (args.groundTest != STEP_DONT_CHECK_GROUND) - { - AI_PROFILE_SCOPE( CAI_Motor_CheckStep_Stand ); - // Next, check to see if we can *geometrically* stand on the floor - bool bIsFloorFlat = CheckStandPosition( trace.endpos, collisionMask ); - if (args.groundTest != STEP_ON_INVALID_GROUND && !bIsFloorFlat) - { - pResult->pBlocker = pFloor; - - if ( g_bAIDebugStep ) - NDebugOverlay::Cross3D( trace.endpos, 32, 255, 0, 255, true, 5 ); - return false; - } - // If we started on shaky ground (namely, it's not geometrically ok), - // then we can continue going even if we remain on shaky ground. - // This allows NPCs who have been blown into an invalid area to get out - // of that invalid area and into a valid area. As soon as we're in - // a valid area, though, we're not allowed to leave it. - } - - // Return a point that is *on the ground* - // We'll raise it by an epsilon in check step again - pResult->endPoint = trace.endpos; - pResult->endPoint.z += MOVE_HEIGHT_EPSILON; // always safe because always stepped down at least by epsilon - - if ( g_bAIDebugStep ) - NDebugOverlay::Cross3D( trace.endpos, 32, 0, 255, 0, true, 5 ); - - return ( pResult->pBlocker == NULL ); // totally clear if pBlocker is NULL, partial blockage otherwise -} - -//----------------------------------------------------------------------------- -// Checks a ground-based movement -// NOTE: The movement will be based on an *actual* start position and -// a *desired* end position; it works this way because the ground-based movement -// is 2 1/2D, and we may end up on a ledge above or below the actual desired endpoint. -//----------------------------------------------------------------------------- -bool CAI_MoveProbe::TestGroundMove( const Vector &vecActualStart, const Vector &vecDesiredEnd, - unsigned int collisionMask, float pctToCheckStandPositions, unsigned flags, AIMoveTrace_t *pMoveTrace ) const -{ - AIMoveTrace_t ignored; - if ( !pMoveTrace ) - pMoveTrace = &ignored; - - // Set a reasonable default set of values - pMoveTrace->flDistObstructed = 0.0f; - pMoveTrace->pObstruction = NULL; - pMoveTrace->vHitNormal = vec3_origin; - pMoveTrace->fStatus = AIMR_OK; - pMoveTrace->vEndPosition = vecActualStart; - pMoveTrace->flStepUpDistance = 0; - - Vector vecMoveDir; - pMoveTrace->flTotalDist = ComputePathDirection( NAV_GROUND, vecActualStart, vecDesiredEnd, &vecMoveDir ); - if (pMoveTrace->flTotalDist == 0.0f) - { - return true; - } - - // If it starts hanging over an edge, tough it out until it's not - // This allows us to blow an NPC in an invalid region + allow him to walk out - StepGroundTest_t groundTest; - if ( (flags & AITGM_IGNORE_FLOOR) || pctToCheckStandPositions < 0.001 ) - { - groundTest = STEP_DONT_CHECK_GROUND; - pctToCheckStandPositions = 0; // AITGM_IGNORE_FLOOR always overrides pct - } - else - { - if ( pctToCheckStandPositions > 99.999 ) - pctToCheckStandPositions = 100; - - if ((flags & AITGM_IGNORE_INITIAL_STAND_POS) || CheckStandPosition(vecActualStart, collisionMask)) - groundTest = STEP_ON_VALID_GROUND; - else - groundTest = STEP_ON_INVALID_GROUND; - } - - if ( ( flags & AITGM_DRAW_RESULTS ) && !CheckStandPosition(vecActualStart, collisionMask) ) - { - NDebugOverlay::Cross3D( vecActualStart, 16, 128, 0, 0, true, 2.0 ); - } - - // Take single steps towards the goal - float distClear = 0; - int i; - - CheckStepArgs_t checkStepArgs; - CheckStepResult_t checkStepResult; - - checkStepArgs.vecStart = vecActualStart; - checkStepArgs.vecStepDir = vecMoveDir; - checkStepArgs.stepSize = 0; - checkStepArgs.stepHeight = StepHeight(); - checkStepArgs.stepDownMultiplier = GetOuter()->GetStepDownMultiplier(); - checkStepArgs.minStepLanding = GetHullWidth() * 0.3333333; - checkStepArgs.collisionMask = collisionMask; - checkStepArgs.groundTest = groundTest; - - checkStepResult.endPoint = vecActualStart; - checkStepResult.hitNormal = vec3_origin; - checkStepResult.pBlocker = NULL; - - float distStartToIgnoreGround = (pctToCheckStandPositions == 100) ? pMoveTrace->flTotalDist : pMoveTrace->flTotalDist * ( pctToCheckStandPositions * 0.01); - bool bTryNavIgnore = ( ( vecActualStart - GetLocalOrigin() ).Length2DSqr() < 0.1 && fabsf(vecActualStart.z - GetLocalOrigin().z) < checkStepArgs.stepHeight * 0.5 ); - - CUtlVector ignoredEntities; - - for (;;) - { - float flStepSize = MIN( LOCAL_STEP_SIZE, pMoveTrace->flTotalDist - distClear ); - if ( flStepSize < 0.001 ) - break; - - checkStepArgs.stepSize = flStepSize; - if ( distClear - distStartToIgnoreGround > 0.001 ) - checkStepArgs.groundTest = STEP_DONT_CHECK_GROUND; - - Assert( !m_pTraceListData || m_pTraceListData->IsEmpty() ); - SetupCheckStepTraceListData( checkStepArgs ); - - for ( i = 0; i < 16; i++ ) - { - CheckStep( checkStepArgs, &checkStepResult ); - - if ( !bTryNavIgnore || !checkStepResult.pBlocker || !checkStepResult.fStartSolid ) - break; - - if ( checkStepResult.pBlocker->GetMoveType() != MOVETYPE_VPHYSICS && !checkStepResult.pBlocker->IsNPC() ) - break; - - // Only permit pass through of objects initially embedded in - if ( vecActualStart != checkStepArgs.vecStart ) - { - bTryNavIgnore = false; - break; - } - - // Only allow move away from physics objects - if ( checkStepResult.pBlocker->GetMoveType() == MOVETYPE_VPHYSICS ) - { - Vector vMoveDir = vecDesiredEnd - vecActualStart; - VectorNormalize( vMoveDir ); - - Vector vObstacleDir = (checkStepResult.pBlocker->WorldSpaceCenter() - GetOuter()->WorldSpaceCenter() ); - VectorNormalize( vObstacleDir ); - - if ( vMoveDir.Dot( vObstacleDir ) >= 0 ) - break; - } - - if ( ( flags & AITGM_DRAW_RESULTS ) && checkStepResult.fStartSolid && checkStepResult.pBlocker->IsNPC() ) - { - NDebugOverlay::EntityBounds( GetOuter(), 0, 0, 255, 0, .5 ); - NDebugOverlay::EntityBounds( checkStepResult.pBlocker, 255, 0, 0, 0, .5 ); - } - - ignoredEntities.AddToTail( checkStepResult.pBlocker ); - checkStepResult.pBlocker->SetNavIgnore(); - } - - ResetTraceListData(); - - if ( flags & AITGM_DRAW_RESULTS ) - { - if ( !CheckStandPosition(checkStepResult.endPoint, collisionMask) ) - { - NDebugOverlay::Box( checkStepResult.endPoint, WorldAlignMins(), WorldAlignMaxs(), 255, 0, 0, 0, 0.1 ); - NDebugOverlay::Cross3D( checkStepResult.endPoint, 16, 255, 0, 0, true, 0.1 ); - } - else - { - NDebugOverlay::Box( checkStepResult.endPoint, WorldAlignMins(), WorldAlignMaxs(), 0, 255, 0, 0, 0.1 ); - NDebugOverlay::Cross3D( checkStepResult.endPoint, 16, 0, 255, 0, true, 0.1 ); - } - } - - // If we're being blocked by something, move as close as we can and stop - if ( checkStepResult.pBlocker ) - { - distClear += ( checkStepResult.endPoint - checkStepArgs.vecStart ).Length2D(); - break; - } - - float dz = checkStepResult.endPoint.z - checkStepArgs.vecStart.z; - if ( dz < 0 ) - { - dz = 0; - } - - pMoveTrace->flStepUpDistance += dz; - distClear += flStepSize; - checkStepArgs.vecStart = checkStepResult.endPoint; - } - - for ( i = 0; i < ignoredEntities.Count(); i++ ) - { - ignoredEntities[i]->ClearNavIgnore(); - } - - pMoveTrace->vEndPosition = checkStepResult.endPoint; - - if (checkStepResult.pBlocker) - { - pMoveTrace->pObstruction = checkStepResult.pBlocker; - pMoveTrace->vHitNormal = checkStepResult.hitNormal; - pMoveTrace->fStatus = AIComputeBlockerMoveResult( checkStepResult.pBlocker ); - pMoveTrace->flDistObstructed = pMoveTrace->flTotalDist - distClear; - - if ( flags & AITGM_DRAW_RESULTS ) - { - NDebugOverlay::Box( checkStepResult.endPoint, WorldAlignMins(), WorldAlignMaxs(), 255, 0, 0, 0, 0.5 ); - } - - return false; - } - - // FIXME: If you started on a ledge and ended on a ledge, - // should it return an error condition (that you hit the world)? - // Certainly not for Step(), but maybe for GroundMoveLimit()? - - // Make sure we actually made it to the target position - // and not a ledge above or below the target. - if (!(flags & AITGM_2D)) - { - float threshold = MAX( 0.5f * GetHullHeight(), StepHeight() + 0.1 ); - if (fabs(pMoveTrace->vEndPosition.z - vecDesiredEnd.z) > threshold) - { -#if 0 - NDebugOverlay::Cross3D( vecDesiredEnd, 8, 0, 255, 0, false, 0.1 ); - NDebugOverlay::Cross3D( pMoveTrace->vEndPosition, 8, 255, 0, 0, false, 0.1 ); -#endif - // Ok, we ended up on a ledge above or below the desired destination - pMoveTrace->pObstruction = GetContainingEntity( INDEXENT(0) ); - pMoveTrace->vHitNormal = vec3_origin; - pMoveTrace->fStatus = AIMR_BLOCKED_WORLD; - pMoveTrace->flDistObstructed = ComputePathDistance( NAV_GROUND, pMoveTrace->vEndPosition, vecDesiredEnd ); - return false; - } - } - - return true; -} - -//----------------------------------------------------------------------------- -// Tries to generate a route from the specified start to end positions -// Will return the results of the attempt in the AIMoveTrace_t structure -//----------------------------------------------------------------------------- -void CAI_MoveProbe::GroundMoveLimit( const Vector &vecStart, const Vector &vecEnd, - unsigned int collisionMask, const CBaseEntity *pTarget, unsigned testGroundMoveFlags, float pctToCheckStandPositions, AIMoveTrace_t* pTrace ) const -{ - // NOTE: Never call this directly!!! Always use MoveLimit!! - // This assertion should ensure this happens - Assert( !IsMoveBlocked( *pTrace ) ); - - AI_PROFILE_SCOPE( CAI_Motor_GroundMoveLimit ); - - Vector vecActualStart, vecDesiredEnd; - - pTrace->flTotalDist = ComputePathDistance( NAV_GROUND, vecStart, vecEnd ); - - if ( !IterativeFloorPoint( vecStart, collisionMask, &vecActualStart ) ) - { - pTrace->flDistObstructed = pTrace->flTotalDist; - pTrace->pObstruction = GetContainingEntity( INDEXENT(0) ); - pTrace->vHitNormal = vec3_origin; - pTrace->fStatus = AIMR_BLOCKED_WORLD; - pTrace->vEndPosition = vecStart; - - //DevMsg( "Warning: attempting to path from/to a point that is in solid space or is too high\n" ); - return; - } - - // find out where they (in theory) should have ended up - if (!(testGroundMoveFlags & AITGM_2D)) - IterativeFloorPoint( vecEnd, collisionMask, &vecDesiredEnd ); - else - vecDesiredEnd = vecEnd; - - // When checking the route, look for ground geometric validity - // Let's try to avoid invalid routes - TestGroundMove( vecActualStart, vecDesiredEnd, collisionMask, pctToCheckStandPositions, testGroundMoveFlags, pTrace ); - - // Check to see if the target is in a vehicle and the vehicle is blocking our way - bool bVehicleMatchesObstruction = false; - - if ( pTarget != NULL ) - { - CBaseCombatCharacter *pCCTarget = ((CBaseEntity *)pTarget)->MyCombatCharacterPointer(); - if ( pCCTarget != NULL && pCCTarget->IsInAVehicle() ) - { - CBaseEntity *pVehicleEnt = pCCTarget->GetVehicleEntity(); - if ( pVehicleEnt == pTrace->pObstruction ) - bVehicleMatchesObstruction = true; - } - } - - if ( (pTarget && (pTarget == pTrace->pObstruction)) || bVehicleMatchesObstruction ) - { - // Collided with target entity, return there was no collision!! - // but leave the end trace position - pTrace->flDistObstructed = 0.0f; - pTrace->pObstruction = NULL; - pTrace->vHitNormal = vec3_origin; - pTrace->fStatus = AIMR_OK; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: returns zero if the caller can walk a straight line from -// vecStart to vecEnd ignoring collisions with pTarget -// -// if the move fails, returns the distance remaining to vecEnd -//----------------------------------------------------------------------------- -void CAI_MoveProbe::FlyMoveLimit( const Vector &vecStart, const Vector &vecEnd, - unsigned int collisionMask, const CBaseEntity *pTarget, AIMoveTrace_t *pMoveTrace ) const -{ - // NOTE: Never call this directly!!! Always use MoveLimit!! - // This assertion should ensure this happens - Assert( !IsMoveBlocked( *pMoveTrace) ); - - trace_t tr; - TraceHull( vecStart, vecEnd, collisionMask, &tr ); - - if ( tr.fraction < 1 ) - { - CBaseEntity *pBlocker = tr.m_pEnt; - if ( pBlocker ) - { - if ( pTarget == pBlocker ) - { - // Colided with target entity, movement is ok - pMoveTrace->vEndPosition = tr.endpos; - return; - } - - // If blocked by an npc remember - pMoveTrace->pObstruction = pBlocker; - pMoveTrace->vHitNormal = vec3_origin; - pMoveTrace->fStatus = AIComputeBlockerMoveResult( pBlocker ); - } - pMoveTrace->flDistObstructed = ComputePathDistance( NAV_FLY, tr.endpos, vecEnd ); - pMoveTrace->vEndPosition = tr.endpos; - return; - } - - // no collisions, movement is ok - pMoveTrace->vEndPosition = vecEnd; -} - - -//----------------------------------------------------------------------------- -// Purpose: returns zero if the caller can jump from -// vecStart to vecEnd ignoring collisions with pTarget -// -// if the jump fails, returns the distance -// that can be travelled before an obstacle is hit -//----------------------------------------------------------------------------- -void CAI_MoveProbe::JumpMoveLimit( const Vector &vecStart, const Vector &vecEnd, - unsigned int collisionMask, const CBaseEntity *pTarget, AIMoveTrace_t *pMoveTrace ) const -{ - pMoveTrace->vJumpVelocity.Init( 0, 0, 0 ); - - float flDist = ComputePathDistance( NAV_JUMP, vecStart, vecEnd ); - - if (!IsJumpLegal(vecStart, vecEnd, vecEnd)) - { - pMoveTrace->fStatus = AIMR_ILLEGAL; - pMoveTrace->flDistObstructed = flDist; - return; - } - - // -------------------------------------------------------------------------- - // Drop start and end vectors to the floor and check to see if they're legal - // -------------------------------------------------------------------------- - Vector vecFrom; - IterativeFloorPoint( vecStart, collisionMask, &vecFrom ); - - Vector vecTo; - IterativeFloorPoint( vecEnd, collisionMask, StepHeight() * 0.5, &vecTo ); - if (!CheckStandPosition( vecTo, collisionMask)) - { - pMoveTrace->fStatus = AIMR_ILLEGAL; - pMoveTrace->flDistObstructed = flDist; - return; - } - - if (vecFrom == vecTo) - { - pMoveTrace->fStatus = AIMR_ILLEGAL; - pMoveTrace->flDistObstructed = flDist; - return; - } - - if ((vecFrom - vecTo).Length2D() == 0.0) - { - pMoveTrace->fStatus = AIMR_ILLEGAL; - pMoveTrace->flDistObstructed = flDist; - return; - } - - // FIXME: add max jump velocity callback? Look at the velocity in the jump animation? use ideal running speed? - float maxHorzVel = GetOuter()->GetMaxJumpSpeed(); - - Vector gravity = Vector(0, 0, sv_gravity.GetFloat() * GetOuter()->GetJumpGravity() ); - - if ( gravity.z < 0.01 ) - { - pMoveTrace->fStatus = AIMR_ILLEGAL; - pMoveTrace->flDistObstructed = flDist; - return; - } - - // intialize error state to it being an illegal jump - CBaseEntity *pObstruction = NULL; - AIMoveResult_t fStatus = AIMR_ILLEGAL; - float flDistObstructed = flDist; - - // initialize jump state - float minSuccessfulJumpHeight = 1024.0; - float minJumpHeight = 0.0; - float minJumpStep = 1024.0; - - // initial jump, sets baseline for minJumpHeight - Vector vecApex; - Vector rawJumpVel = CalcJumpLaunchVelocity(vecFrom, vecTo, gravity.z, &minJumpHeight, maxHorzVel, &vecApex ); - float baselineJumpHeight = minJumpHeight; - - // FIXME: this is a binary search, which really isn't the right thing to do. If there's a gap - // the npc can jump through, this won't reliably find it. The only way I can think to do this is a - // linear search trying ever higher jumps until the gap is either found or the jump is illegal. - do - { - rawJumpVel = CalcJumpLaunchVelocity(vecFrom, vecTo, gravity.z, &minJumpHeight, maxHorzVel, &vecApex ); - // DevMsg( "%.0f ", minJumpHeight ); - - if (!IsJumpLegal(vecFrom, vecApex, vecTo)) - { - // too high, try lower - minJumpStep = minJumpStep / 2.0; - minJumpHeight = minJumpHeight - minJumpStep; - } - else - { - // Calculate the total time of the jump minus a tiny fraction - float jumpTime = (vecFrom - vecTo).Length2D()/rawJumpVel.Length2D(); - float timeStep = jumpTime / 10.0; - - Vector vecTest = vecFrom; - bool bMadeIt = true; - - // this sweeps out a rough approximation of the jump - // FIXME: this won't reliably hit the apex - for (float flTime = 0 ; flTime < jumpTime - 0.01; flTime += timeStep ) - { - trace_t trace; - - // Calculate my position after the time step (average velocity over this time step) - Vector nextPos = vecTest + (rawJumpVel - 0.5 * gravity * timeStep) * timeStep; - - TraceHull( vecTest, nextPos, collisionMask, &trace ); - - if (trace.startsolid || trace.fraction < 0.99) // FIXME: getting inconsistant trace fractions, revisit after Jay resolves collision eplisons - { - // NDebugOverlay::Box( trace.endpos, WorldAlignMins(), WorldAlignMaxs(), 255, 255, 0, 0, 10.0 ); - - // save error state - pObstruction = trace.m_pEnt; - fStatus = AIComputeBlockerMoveResult( pObstruction ); - flDistObstructed = ComputePathDistance( NAV_JUMP, vecTest, vecTo ); - - if (trace.plane.normal.z < 0.0) - { - // hit a ceiling looking thing, too high, try lower - minJumpStep = minJumpStep / 2.0; - minJumpHeight = minJumpHeight - minJumpStep; - } - else - { - // hit wall looking thing, try higher - minJumpStep = minJumpStep / 2.0; - minJumpHeight += minJumpStep; - } - - if ( ai_moveprobe_jump_debug.GetBool() ) - { - NDebugOverlay::Line( vecTest, nextPos, 255, 0, 0, true, 2.0f ); - } - - bMadeIt = false; - break; - } - else - { - if ( ai_moveprobe_jump_debug.GetBool() ) - { - NDebugOverlay::Line( vecTest, nextPos, 0, 255, 0, true, 2.0f ); - } - } - - rawJumpVel = rawJumpVel - gravity * timeStep; - vecTest = nextPos; - } - - if (bMadeIt) - { - // made it, try lower - minSuccessfulJumpHeight = minJumpHeight; - minJumpStep = minJumpStep / 2.0; - minJumpHeight -= minJumpStep; - } - } - } - while (minJumpHeight > baselineJumpHeight && minJumpHeight <= 1024.0 && minJumpStep >= 16.0); - - // DevMsg( "(%.0f)\n", minSuccessfulJumpHeight ); - - if (minSuccessfulJumpHeight != 1024.0) - { - // Get my jump velocity - pMoveTrace->vJumpVelocity = CalcJumpLaunchVelocity(vecFrom, vecTo, gravity.z, &minSuccessfulJumpHeight, maxHorzVel, &vecApex ); - } - else - { - // ---------------------------------------------------------- - // If blocked by an npc remember - // ---------------------------------------------------------- - pMoveTrace->pObstruction = pObstruction; - pMoveTrace->vHitNormal = vec3_origin; - pMoveTrace->fStatus = fStatus; - pMoveTrace->flDistObstructed = flDistObstructed; - } -} - -//----------------------------------------------------------------------------- -// Purpose: returns zero if the caller can climb from -// vecStart to vecEnd ignoring collisions with pTarget -// -// if the climb fails, returns the distance remaining -// before the obstacle is hit -//----------------------------------------------------------------------------- -void CAI_MoveProbe::ClimbMoveLimit( const Vector &vecStart, const Vector &vecEnd, - const CBaseEntity *pTarget, AIMoveTrace_t *pMoveTrace ) const -{ - trace_t tr; - TraceHull( vecStart, vecEnd, MASK_NPCSOLID, &tr ); - - if (tr.fraction < 1.0) - { - CBaseEntity *pEntity = tr.m_pEnt; - if (pEntity == pTarget) - { - return; - } - else - { - // ---------------------------------------------------------- - // If blocked by an npc remember - // ---------------------------------------------------------- - pMoveTrace->pObstruction = pEntity; - pMoveTrace->vHitNormal = vec3_origin; - pMoveTrace->fStatus = AIComputeBlockerMoveResult( pEntity ); - - float flDist = (1.0 - tr.fraction) * ComputePathDistance( NAV_CLIMB, vecStart, vecEnd ); - if (flDist <= 0.001) - { - flDist = 0.001; - } - pMoveTrace->flDistObstructed = flDist; - return; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_MoveProbe::MoveLimit( Navigation_t navType, const Vector &vecStart, - const Vector &vecEnd, unsigned int collisionMask, const CBaseEntity *pTarget, - float pctToCheckStandPositions, unsigned flags, AIMoveTrace_t* pTrace) -{ - AIMoveTrace_t ignoredTrace; - if ( !pTrace ) - pTrace = &ignoredTrace; - - // Set a reasonable default set of values - pTrace->flTotalDist = ComputePathDistance( navType, vecStart, vecEnd ); - pTrace->flDistObstructed = 0.0f; - pTrace->pObstruction = NULL; - pTrace->vHitNormal = vec3_origin; - pTrace->fStatus = AIMR_OK; - pTrace->vEndPosition = vecStart; - - switch (navType) - { - case NAV_GROUND: - { - unsigned testGroundMoveFlags = AITGM_DEFAULT; - if (flags & AIMLF_2D ) - testGroundMoveFlags |= AITGM_2D; - if ( flags & AIMLF_DRAW_RESULTS ) - testGroundMoveFlags |= AITGM_DRAW_RESULTS; - if ( ai_moveprobe_debug.GetBool() && (GetOuter()->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) ) - testGroundMoveFlags |= AITGM_DRAW_RESULTS; - - if ( flags & AIMLF_IGNORE_TRANSIENTS ) - const_cast(this)->m_bIgnoreTransientEntities = true; - - bool bDoIt = true; - if ( flags & AIMLF_QUICK_REJECT ) - { - Assert( vecStart == GetLocalOrigin() ); - trace_t tr; - TraceLine(const_cast(this)->GetOuter()->EyePosition(), vecEnd, collisionMask, true, &tr); - bDoIt = ( tr.fraction > 0.99 ); - } - - if ( bDoIt ) - GroundMoveLimit(vecStart, vecEnd, collisionMask, pTarget, testGroundMoveFlags, pctToCheckStandPositions, pTrace); - else - { - pTrace->pObstruction = GetContainingEntity( INDEXENT(0) ); - pTrace->vHitNormal = vec3_origin; - pTrace->fStatus = AIMR_BLOCKED_WORLD; - pTrace->flDistObstructed = ComputePathDistance( NAV_GROUND, vecStart, vecEnd ); - } - - const_cast(this)->m_bIgnoreTransientEntities = false; - - break; - } - - case NAV_FLY: - FlyMoveLimit(vecStart, vecEnd, collisionMask, pTarget, pTrace); - break; - - case NAV_JUMP: - JumpMoveLimit(vecStart, vecEnd, collisionMask, pTarget, pTrace); - break; - - case NAV_CLIMB: - ClimbMoveLimit(vecStart, vecEnd, pTarget, pTrace); - break; - - default: - pTrace->fStatus = AIMR_ILLEGAL; - pTrace->flDistObstructed = ComputePathDistance( navType, vecStart, vecEnd ); - break; - } - - if (IsMoveBlocked(pTrace->fStatus) && pTrace->pObstruction && !pTrace->pObstruction->IsWorld()) - { - m_hLastBlockingEnt = pTrace->pObstruction; - } - - return !IsMoveBlocked(pTrace->fStatus); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns a jump lauch velocity for the current target entity -// Input : -// Output : -//----------------------------------------------------------------------------- -Vector CAI_MoveProbe::CalcJumpLaunchVelocity(const Vector &startPos, const Vector &endPos, float flGravity, float *pminHeight, float maxHorzVelocity, Vector *pvecApex ) const -{ - // Get the height I have to jump to get to the target - float stepHeight = endPos.z - startPos.z; - - // get horizontal distance to target - Vector targetDir2D = endPos - startPos; - targetDir2D.z = 0; - float distance = VectorNormalize(targetDir2D); - - Assert( maxHorzVelocity > 0 ); - - // get minimum times and heights to meet ideal horz velocity - float minHorzTime = distance / maxHorzVelocity; - float minHorzHeight = 0.5 * flGravity * (minHorzTime * 0.5) * (minHorzTime * 0.5); - - // jump height must be enough to hang in the air - *pminHeight = MAX( *pminHeight, minHorzHeight ); - // jump height must be enough to cover the step up - *pminHeight = MAX( *pminHeight, stepHeight ); - - // time from start to apex - float t0 = sqrt( ( 2.0 * *pminHeight) / flGravity ); - // time from apex to end - float t1 = sqrt( ( 2.0 * fabs( *pminHeight - stepHeight) ) / flGravity ); - - float velHorz = distance / (t0 + t1); - - Vector jumpVel = targetDir2D * velHorz; - - jumpVel.z = (float)sqrt(2.0f * flGravity * (*pminHeight)); - - if (pvecApex) - { - *pvecApex = startPos + targetDir2D * velHorz * t0 + Vector( 0, 0, *pminHeight ); - } - - // ----------------------------------------------------------- - // Make the horizontal jump vector and add vertical component - // ----------------------------------------------------------- - - return jumpVel; -} - -//----------------------------------------------------------------------------- - -bool CAI_MoveProbe::CheckStandPosition( const Vector &vecStart, unsigned int collisionMask ) const -{ - // If we're not supposed to do ground checks, always say we can stand there - if ( (GetOuter()->CapabilitiesGet() & bits_CAP_SKIP_NAV_GROUND_CHECK) ) - return true; - - // This is an extra-strong optimization - if ( ai_strong_optimizations_no_checkstand.GetBool() ) - return true; - - if ( UseOldCheckStandPosition() ) - return OldCheckStandPosition( vecStart, collisionMask ); - - AI_PROFILE_SCOPE( CAI_Motor_CheckStandPosition ); - - Vector contactMin, contactMax; - - // this should assume the model is already standing - Vector vecUp = Vector( vecStart.x, vecStart.y, vecStart.z + 0.1 ); - Vector vecDown = Vector( vecStart.x, vecStart.y, vecStart.z - StepHeight() * GetOuter()->GetStepDownMultiplier() ); - - // check a half sized box centered around the foot - Vector vHullMins = WorldAlignMins(); - Vector vHullMaxs = WorldAlignMaxs(); - - if ( vHullMaxs == vec3_origin && vHullMins == vHullMaxs ) - { - // "Test hulls" have no collision property - vHullMins = GetHullMins(); - vHullMaxs = GetHullMaxs(); - } - - contactMin.x = vHullMins.x * 0.75 + vHullMaxs.x * 0.25; - contactMax.x = vHullMins.x * 0.25 + vHullMaxs.x * 0.75; - contactMin.y = vHullMins.y * 0.75 + vHullMaxs.y * 0.25; - contactMax.y = vHullMins.y * 0.25 + vHullMaxs.y * 0.75; - contactMin.z = vHullMins.z; - contactMax.z = vHullMins.z; - - trace_t trace1, trace2; - - if ( !GetOuter()->IsFlaggedEfficient() ) - { - AI_PROFILE_SCOPE( CAI_Motor_CheckStandPosition_Sides ); - - Vector vHullBottomCenter; - vHullBottomCenter.Init( 0, 0, vHullMins.z ); - - // Try diagonal from lower left to upper right - TraceHull( vecUp, vecDown, contactMin, vHullBottomCenter, collisionMask, &trace1 ); - if ( trace1.fraction != 1.0 && CanStandOn( trace1.m_pEnt ) ) - { - TraceHull( vecUp, vecDown, vHullBottomCenter, contactMax, collisionMask, &trace2 ); - if ( trace2.fraction != 1.0 && ( trace1.m_pEnt == trace2.m_pEnt || CanStandOn( trace2.m_pEnt ) ) ) - { - return true; - } - } - - // Okay, try the other one - Vector testMin; - Vector testMax; - testMin.Init(contactMin.x, 0, vHullMins.z); - testMax.Init(0, contactMax.y, vHullMins.z); - - TraceHull( vecUp, vecDown, testMin, testMax, collisionMask, &trace1 ); - if ( trace1.fraction != 1.0 && CanStandOn( trace1.m_pEnt ) ) - { - testMin.Init(0, contactMin.y, vHullMins.z); - testMax.Init(contactMax.x, 0, vHullMins.z); - TraceHull( vecUp, vecDown, testMin, testMax, collisionMask, &trace2 ); - if ( trace2.fraction != 1.0 && ( trace1.m_pEnt == trace2.m_pEnt || CanStandOn( trace2.m_pEnt ) ) ) - { - return true; - } - } - } - else - { - AI_PROFILE_SCOPE( CAI_Motor_CheckStandPosition_Center ); - TraceHull( vecUp, vecDown, contactMin, contactMax, collisionMask, &trace1 ); - if ( trace1.fraction != 1.0 && CanStandOn( trace1.m_pEnt ) ) - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- - -bool CAI_MoveProbe::OldCheckStandPosition( const Vector &vecStart, unsigned int collisionMask ) const -{ - AI_PROFILE_SCOPE( CAI_Motor_CheckStandPosition ); - - Vector contactMin, contactMax; - - // this should assume the model is already standing - Vector vecUp = Vector( vecStart.x, vecStart.y, vecStart.z + 0.1 ); - Vector vecDown = Vector( vecStart.x, vecStart.y, vecStart.z - StepHeight() * GetOuter()->GetStepDownMultiplier() ); - - // check a half sized box centered around the foot - const Vector &vHullMins = WorldAlignMins(); - const Vector &vHullMaxs = WorldAlignMaxs(); - - contactMin.x = vHullMins.x * 0.75 + vHullMaxs.x * 0.25; - contactMax.x = vHullMins.x * 0.25 + vHullMaxs.x * 0.75; - contactMin.y = vHullMins.y * 0.75 + vHullMaxs.y * 0.25; - contactMax.y = vHullMins.y * 0.25 + vHullMaxs.y * 0.75; - contactMin.z = vHullMins.z; - contactMax.z = vHullMins.z; - - trace_t trace; - - AI_PROFILE_SCOPE_BEGIN( CAI_Motor_CheckStandPosition_Center ); - TraceHull( vecUp, vecDown, contactMin, contactMax, collisionMask, &trace ); - AI_PROFILE_SCOPE_END(); - - if (trace.fraction == 1.0 || !CanStandOn( trace.m_pEnt )) - return false; - - float sumFraction = 0; - - if ( !GetOuter()->IsFlaggedEfficient() ) - { - AI_PROFILE_SCOPE( CAI_Motor_CheckStandPosition_Sides ); - - // check a box for each quadrant, allow one failure - int already_failed = false; - for (int x = 0; x <= 1 ;x++) - { - for (int y = 0; y <= 1; y++) - { - // create bounding boxes for each quadrant - contactMin[0] = x ? 0 :vHullMins.x; - contactMax[0] = x ? vHullMaxs.x : 0; - contactMin[1] = y ? 0 : vHullMins.y; - contactMax[1] = y ? vHullMaxs.y : 0; - - TraceHull( vecUp, vecDown, contactMin, contactMax, collisionMask, &trace ); - - sumFraction += trace.fraction; - - // this should hit something, if it doesn't allow one failure - if (trace.fraction == 1.0 || !CanStandOn( trace.m_pEnt )) - { - if (already_failed) - return false; - else - { - already_failed = true; - } - } - else - { - if ( sumFraction > 2.0 ) - return false; - } - } - } - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Computes a point on the floor below the start point, somewhere -// between vecStart.z + flStartZ and vecStart.z + flEndZ -//----------------------------------------------------------------------------- -bool CAI_MoveProbe::FloorPoint( const Vector &vecStart, unsigned int collisionMask, - float flStartZ, float flEndZ, Vector *pVecResult ) const -{ - AI_PROFILE_SCOPE( CAI_Motor_FloorPoint ); - - // make a pizzabox shaped bounding hull - Vector mins = WorldAlignMins(); - Vector maxs( WorldAlignMaxs().x, WorldAlignMaxs().y, mins.z ); - - // trace down step height and a bit more - Vector vecUp( vecStart.x, vecStart.y, vecStart.z + flStartZ + MOVE_HEIGHT_EPSILON ); - Vector vecDown( vecStart.x, vecStart.y, vecStart.z + flEndZ ); - - trace_t trace; - TraceHull( vecUp, vecDown, mins, maxs, collisionMask, &trace ); - - bool fStartedInObject = false; - - if (trace.startsolid) - { - if ( trace.m_pEnt && - ( trace.m_pEnt->GetMoveType() == MOVETYPE_VPHYSICS || trace.m_pEnt->IsNPC() ) && - ( vecStart - GetLocalOrigin() ).Length() < 0.1 ) - { - fStartedInObject = true; - } - - vecUp.z = vecStart.z + MOVE_HEIGHT_EPSILON; - TraceHull( vecUp, vecDown, mins, maxs, collisionMask, &trace ); - } - - // this should have hit a solid surface by now - if (trace.fraction == 1 || trace.allsolid || ( fStartedInObject && trace.startsolid ) ) - { - // set result to start position if it doesn't work - *pVecResult = vecStart; - if ( fStartedInObject ) - return true; // in this case, probably got intruded on by a physics object. Try ignoring it... - return false; - } - - *pVecResult = trace.endpos; - return true; -} - - -//----------------------------------------------------------------------------- -// A floorPoint that is useful only in the context of iterative movement -//----------------------------------------------------------------------------- -bool CAI_MoveProbe::IterativeFloorPoint( const Vector &vecStart, unsigned int collisionMask, Vector *pVecResult ) const -{ - return IterativeFloorPoint( vecStart, collisionMask, 0, pVecResult ); -} - -//----------------------------------------------------------------------------- -bool CAI_MoveProbe::IterativeFloorPoint( const Vector &vecStart, unsigned int collisionMask, float flAddedStep, Vector *pVecResult ) const -{ - // Used by the movement code, it guarantees we don't move outside a step - // height from our current position - return FloorPoint( vecStart, collisionMask, StepHeight() * GetOuter()->GetStepDownMultiplier() + flAddedStep, -(12*60), pVecResult ); -} - -//----------------------------------------------------------------------------- - -float CAI_MoveProbe::StepHeight() const -{ - return GetOuter()->StepHeight(); -} - -//----------------------------------------------------------------------------- - -bool CAI_MoveProbe::CanStandOn( CBaseEntity *pSurface ) const -{ - return GetOuter()->CanStandOn( pSurface ); -} - -//----------------------------------------------------------------------------- - -bool CAI_MoveProbe::IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos ) const -{ - return GetOuter()->IsJumpLegal( startPos, apex, endPos ); -} - -//----------------------------------------------------------------------------- - diff --git a/game/server/ai_moveprobe.h b/game/server/ai_moveprobe.h deleted file mode 100644 index eff01f25b..000000000 --- a/game/server/ai_moveprobe.h +++ /dev/null @@ -1,161 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef AI_MOVEPROBE_H -#define AI_MOVEPROBE_H - -#include "ai_component.h" -#include "ai_navtype.h" -#include "ai_movetypes.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -//----------------------------------------------------------------------------- -// Purpose: Set of basic tools for probing box movements through space. -// No moves actually take place -//----------------------------------------------------------------------------- - -enum AI_TestGroundMoveFlags_t -{ - AITGM_DEFAULT = 0, - AITGM_IGNORE_FLOOR = 0x01, - AITGM_IGNORE_INITIAL_STAND_POS = 0x02, - AITGM_2D = 0x04, - AITGM_DRAW_RESULTS = 0x08, -}; - -enum AI_MoveLimitFlags_t -{ - AIMLF_DEFAULT = 0, - AIMLF_2D = 0x01, - AIMLF_DRAW_RESULTS = 0x02, - AIMLF_IGNORE_TRANSIENTS = 0x04, - AIMLF_QUICK_REJECT = 0x08, -}; - -class CAI_MoveProbe : public CAI_Component -{ -public: - - CAI_MoveProbe( CAI_BaseNPC *pOuter ); - ~CAI_MoveProbe(); - - // ---------------------------------------------------- - // Queries & probes - // ---------------------------------------------------- - bool MoveLimit( Navigation_t navType, const Vector &vecStart, const Vector &vecEnd, unsigned int collisionMask, const CBaseEntity *pTarget, AIMoveTrace_t* pMove = NULL ); - bool MoveLimit( Navigation_t navType, const Vector &vecStart, const Vector &vecEnd, unsigned int collisionMask, const CBaseEntity *pTarget, float pctToCheckStandPositions, AIMoveTrace_t* pMove = NULL ); - bool MoveLimit( Navigation_t navType, const Vector &vecStart, const Vector &vecEnd, unsigned int collisionMask, const CBaseEntity *pTarget, float pctToCheckStandPositions, unsigned flags, AIMoveTrace_t* pMove = NULL ); - - bool CheckStandPosition( const Vector &vecStart, unsigned int collisionMask ) const; - bool FloorPoint( const Vector &vecStart, unsigned int collisionMask, float flStartZ, float flEndZ, Vector *pVecResult ) const; - - // -------------------------------- - // Tracing tools - // -------------------------------- - void TraceLine( const Vector &vecStart, const Vector &vecEnd, unsigned int mask, - bool bUseCollisionGroup, trace_t *pResult ) const; - - void TraceHull( const Vector &vecStart, const Vector &vecEnd, const Vector &hullMin, - const Vector &hullMax, unsigned int mask, - trace_t *ptr ) const; - - void TraceHull( const Vector &vecStart, const Vector &vecEnd, unsigned int mask, - trace_t *ptr ) const; - - // -------------------------------- - // Checks a ground-based movement - // -------------------------------- - bool TestGroundMove( const Vector &vecActualStart, const Vector &vecDesiredEnd, - unsigned int collisionMask, unsigned flags, AIMoveTrace_t *pMoveTrace ) const; - - bool TestGroundMove( const Vector &vecActualStart, const Vector &vecDesiredEnd, - unsigned int collisionMask, float pctToCheckStandPositions, unsigned flags, AIMoveTrace_t *pMoveTrace ) const; - - bool ShouldBrushBeIgnored( CBaseEntity *pEntity ); - - void ClearBlockingEntity() { m_hLastBlockingEnt = NULL; } - CBaseEntity * GetBlockingEntity() { return m_hLastBlockingEnt; } - -private: - struct CheckStepArgs_t - { - Vector vecStart; - Vector vecStepDir; - float stepSize; - float stepHeight; - float stepDownMultiplier; - float minStepLanding; - unsigned collisionMask; - StepGroundTest_t groundTest; - }; - - struct CheckStepResult_t - { - Vector endPoint; - Vector hitNormal; - bool fStartSolid; - CBaseEntity * pBlocker; - }; - - - bool CheckStep( const CheckStepArgs_t &args, CheckStepResult_t *pResult ) const; - void SetupCheckStepTraceListData( const CheckStepArgs_t &args ) const; - void ResetTraceListData() const { if ( m_pTraceListData ) const_cast(this)->m_pTraceListData->Reset(); } - bool OldCheckStandPosition( const Vector &vecStart, unsigned int collisionMask ) const; - - // these check connections between positions in space, regardless of routes - void GroundMoveLimit( const Vector &vecStart, const Vector &vecEnd, unsigned int collisionMask, const CBaseEntity *pTarget, unsigned testGroundMoveFlags, float pctToCheckStandPositions, AIMoveTrace_t* pMoveTrace ) const; - void FlyMoveLimit( const Vector &vecStart, const Vector &vecEnd, unsigned int collisionMask, const CBaseEntity *pTarget, AIMoveTrace_t* pMoveTrace) const; - void JumpMoveLimit( const Vector &vecStart, const Vector &vecEnd, unsigned int collisionMask, const CBaseEntity *pTarget, AIMoveTrace_t* pMoveTrace) const; - void ClimbMoveLimit( const Vector &vecStart, const Vector &vecEnd, const CBaseEntity *pTarget, AIMoveTrace_t* pMoveTrace) const; - - // A floorPoint that is useful only in the contect of iterative movement - bool IterativeFloorPoint( const Vector &vecStart, unsigned int collisionMask, Vector *pVecResult ) const; - bool IterativeFloorPoint( const Vector &vecStart, unsigned int collisionMask, float flAddedStep, Vector *pVecResult ) const; - bool IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos ) const; - -public: - Vector CalcJumpLaunchVelocity(const Vector &startPos, const Vector &endPos, float gravity, float *pminHeight, float maxHorzVelocity, Vector *vecApex ) const; -private: - - // Common services provided by CAI_BaseNPC, Convenience methods to simplify code - float StepHeight() const; - bool CanStandOn( CBaseEntity *pSurface ) const; - - bool m_bIgnoreTransientEntities; - - CTraceListData * m_pTraceListData; - - EHANDLE m_hLastBlockingEnt; - - DECLARE_SIMPLE_DATADESC(); -}; - -// ---------------------------------------------------------------------------- - -inline bool CAI_MoveProbe::MoveLimit( Navigation_t navType, const Vector &vecStart, const Vector &vecEnd, unsigned int collisionMask, const CBaseEntity *pTarget, float pctToCheckStandPositions, AIMoveTrace_t* pMove) -{ - return MoveLimit( navType, vecStart, vecEnd, collisionMask, pTarget, pctToCheckStandPositions, AIMLF_DEFAULT, pMove); -} - -// ------------------------------------ - -inline bool CAI_MoveProbe::MoveLimit( Navigation_t navType, const Vector &vecStart, const Vector &vecEnd, unsigned int collisionMask, const CBaseEntity *pTarget, AIMoveTrace_t* pMove) -{ - return MoveLimit( navType, vecStart, vecEnd, collisionMask, pTarget, 100.0f, AIMLF_DEFAULT, pMove); -} - -// ------------------------------------ - -inline bool CAI_MoveProbe::TestGroundMove( const Vector &vecActualStart, const Vector &vecDesiredEnd, unsigned int collisionMask, unsigned flags, AIMoveTrace_t *pMoveTrace ) const -{ - return TestGroundMove( vecActualStart, vecDesiredEnd, collisionMask, 100, flags, pMoveTrace ); // floor ignore flag will override 100% -} - -#endif // AI_MOVEPROBE_H diff --git a/game/server/ai_moveshoot.cpp b/game/server/ai_moveshoot.cpp deleted file mode 100644 index 60a6b6018..000000000 --- a/game/server/ai_moveshoot.cpp +++ /dev/null @@ -1,307 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ==== -// -// To give an NPC the ability to shoot while moving: -// -// - In the NPC's Spawn function, add: -// CapabilitiesAdd( bits_CAP_MOVE_SHOOT ); -// -// - The NPC must either have a weapon (return non-NULL from GetActiveWeapon) -// or must have bits_CAP_INNATE_RANGE_ATTACK1 or bits_CAP_INNATE_RANGE_ATTACK2. -// -// - Support the activities ACT_WALK_AIM and/or ACT_RUN_AIM in the NPC. -// -// - Support the activity ACT_GESTURE_RANGE_ATTACK1 as a gesture that plays -// over ACT_WALK_AIM and ACT_RUN_AIM. -// -//============================================================================= - -#include "cbase.h" - -#include "ai_moveshoot.h" -#include "ai_basenpc.h" -#include "ai_navigator.h" -#include "ai_memory.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- - -BEGIN_SIMPLE_DATADESC( CAI_MoveAndShootOverlay ) - DEFINE_FIELD( m_bMovingAndShooting, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bNoShootWhileMove, FIELD_BOOLEAN ), - DEFINE_FIELD( m_initialDelay, FIELD_FLOAT ), - DEFINE_FIELD( m_flSuspendUntilTime, FIELD_TIME ), -END_DATADESC() - -#define MOVESHOOT_DO_NOT_SUSPEND -1.0f - -//------------------------------------- - -CAI_MoveAndShootOverlay::CAI_MoveAndShootOverlay() : m_bMovingAndShooting(false), m_initialDelay(0) -{ - m_flSuspendUntilTime = MOVESHOOT_DO_NOT_SUSPEND; - m_bNoShootWhileMove = false; -} - -//------------------------------------- - -void CAI_MoveAndShootOverlay::NoShootWhileMove() -{ - m_bNoShootWhileMove = true; -} - -//------------------------------------- - -bool CAI_MoveAndShootOverlay::HasAvailableRangeAttack() -{ - return ( ( GetOuter()->GetActiveWeapon() != NULL ) || - ( GetOuter()->CapabilitiesGet() & bits_CAP_INNATE_RANGE_ATTACK1 ) || - ( GetOuter()->CapabilitiesGet() & bits_CAP_INNATE_RANGE_ATTACK2 ) ); -} - -//------------------------------------- - -void CAI_MoveAndShootOverlay::StartShootWhileMove() -{ - if ( GetOuter()->GetState() == NPC_STATE_SCRIPT || - !HasAvailableRangeAttack() || - !GetOuter()->HaveSequenceForActivity( GetOuter()->TranslateActivity( ACT_WALK_AIM ) ) || - !GetOuter()->HaveSequenceForActivity( GetOuter()->TranslateActivity( ACT_RUN_AIM ) ) ) - { - NoShootWhileMove(); - return; - } - - GetOuter()->GetShotRegulator()->FireNoEarlierThan( gpGlobals->curtime + m_initialDelay ); - m_bNoShootWhileMove = false; -} - -//------------------------------------- - -bool CAI_MoveAndShootOverlay::CanAimAtEnemy() -{ - CAI_BaseNPC *pOuter = GetOuter(); - bool result = false; - bool resetConditions = false; - CAI_ScheduleBits savedConditions; - - if ( !GetOuter()->ConditionsGathered() ) - { - savedConditions = GetOuter()->AccessConditionBits(); - GetOuter()->GatherEnemyConditions( GetOuter()->GetEnemy() ); - } - - if ( pOuter->HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - { - result = true; - } - else if ( !pOuter->HasCondition( COND_ENEMY_DEAD ) && - !pOuter->HasCondition( COND_TOO_FAR_TO_ATTACK ) && - !pOuter->HasCondition( COND_ENEMY_TOO_FAR ) && - !pOuter->HasCondition( COND_ENEMY_OCCLUDED ) ) - { - result = true; - } - - // If we don't have a weapon, stop - // This catches NPCs who holster their weapons while running - if ( !HasAvailableRangeAttack() ) - { - result = false; - } - - if ( resetConditions ) - { - GetOuter()->AccessConditionBits() = savedConditions; - } - - return result; -} - -//------------------------------------- - -void CAI_MoveAndShootOverlay::UpdateMoveShootActivity( bool bMoveAimAtEnemy ) -{ - // FIXME: should be able to query that transition/state is happening - // FIXME: needs to not try to shoot if the movement type isn't understood - Activity curActivity = GetOuter()->GetNavigator()->GetMovementActivity(); - Activity newActivity = curActivity; - - if (bMoveAimAtEnemy) - { - switch( curActivity ) - { - case ACT_WALK: - newActivity = ACT_WALK_AIM; - break; - case ACT_RUN: - newActivity = ACT_RUN_AIM; - break; - default: - break; - } - } - else - { - switch( curActivity ) - { - case ACT_WALK_AIM: - newActivity = ACT_WALK; - break; - case ACT_RUN_AIM: - newActivity = ACT_RUN; - break; - default: - break; - } - } - - if ( curActivity != newActivity ) - { - // Transitioning, wait a bit - GetOuter()->GetShotRegulator()->FireNoEarlierThan( gpGlobals->curtime + 0.3f ); - GetOuter()->GetNavigator()->SetMovementActivity( newActivity ); - } -} - -//------------------------------------- - -void CAI_MoveAndShootOverlay::RunShootWhileMove() -{ - if ( m_bNoShootWhileMove ) - return; - - if ( gpGlobals->curtime < m_flSuspendUntilTime ) - return; - - m_flSuspendUntilTime = MOVESHOOT_DO_NOT_SUSPEND; - - CAI_BaseNPC *pOuter = GetOuter(); - - // keep enemy if dead but try to look for a new one - if (!pOuter->GetEnemy() || !pOuter->GetEnemy()->IsAlive()) - { - CBaseEntity *pNewEnemy = pOuter->BestEnemy(); - - if( pNewEnemy != NULL ) - { - //New enemy! Clear the timers and set conditions. - pOuter->SetEnemy( pNewEnemy ); - pOuter->SetState( NPC_STATE_COMBAT ); - } - else - { - pOuter->ClearAttackConditions(); - } - // SetEnemy( NULL ); - } - - if( !pOuter->GetNavigator()->IsGoalActive() ) - return; - - if ( GetEnemy() == NULL ) - { - if ( pOuter->GetAlternateMoveShootTarget() ) - { - // Aim at this other thing if I can't aim at my enemy. - pOuter->AddFacingTarget( pOuter->GetAlternateMoveShootTarget(), pOuter->GetAlternateMoveShootTarget()->GetAbsOrigin(), 1.0, 0.2 ); - } - - return; - } - - bool bMoveAimAtEnemy = CanAimAtEnemy(); - UpdateMoveShootActivity( bMoveAimAtEnemy ); - if ( !bMoveAimAtEnemy ) - { - EndShootWhileMove(); - return; - } - - Assert( HasAvailableRangeAttack() ); // This should have been caught at task start - - Activity activity; - bool bIsReloading = false; - - if ( ( activity = pOuter->TranslateActivity( ACT_GESTURE_RELOAD ) ) != ACT_INVALID ) - { - bIsReloading = pOuter->IsPlayingGesture( activity ); - } - - if ( !bIsReloading && HasAvailableRangeAttack() ) - { - // time to fire? - if ( pOuter->HasCondition( COND_CAN_RANGE_ATTACK1, false ) ) - { - if ( pOuter->GetShotRegulator()->IsInRestInterval() ) - { - EndShootWhileMove(); - } - else if ( pOuter->GetShotRegulator()->ShouldShoot() ) - { - if ( m_bMovingAndShooting || pOuter->OnBeginMoveAndShoot() ) - { - m_bMovingAndShooting = true; - pOuter->OnRangeAttack1(); - - activity = pOuter->TranslateActivity( ACT_GESTURE_RANGE_ATTACK1 ); - Assert( activity != ACT_INVALID ); - - pOuter->RestartGesture( activity ); - - // FIXME: this seems a bit wacked - pOuter->Weapon_SetActivity( pOuter->Weapon_TranslateActivity( ACT_RANGE_ATTACK1 ), 0 ); - } - } - } - else if ( pOuter->HasCondition( COND_NO_PRIMARY_AMMO, false ) ) - { - if ( pOuter->GetNavigator()->GetPathTimeToGoal() > 1.0 ) - { - activity = pOuter->TranslateActivity( ACT_GESTURE_RELOAD ); - if ( activity != ACT_INVALID && GetOuter()->HaveSequenceForActivity( activity ) ) - pOuter->AddGesture( activity ); - } - } - } - - // try to keep facing towards the last known position of the enemy - Vector vecEnemyLKP = pOuter->GetEnemyLKP(); - pOuter->AddFacingTarget( pOuter->GetEnemy(), vecEnemyLKP, 1.0, 0.8 ); -} - - -//------------------------------------- - -void CAI_MoveAndShootOverlay::EndShootWhileMove() -{ - if ( m_bMovingAndShooting ) - { - // Reset the shot regulator so that we always start the next motion with a new burst - if ( !GetOuter()->GetShotRegulator()->IsInRestInterval() ) - { - GetOuter()->GetShotRegulator()->Reset( false ); - } - - m_bMovingAndShooting = false; - GetOuter()->OnEndMoveAndShoot(); - } -} - -//------------------------------------- - -void CAI_MoveAndShootOverlay::SuspendMoveAndShoot( float flDuration ) -{ - EndShootWhileMove(); - m_flSuspendUntilTime = gpGlobals->curtime + flDuration; -} - -//------------------------------------- - -void CAI_MoveAndShootOverlay::SetInitialDelay( float delay ) -{ - m_initialDelay = delay; -} - -//----------------------------------------------------------------------------- diff --git a/game/server/ai_moveshoot.h b/game/server/ai_moveshoot.h deleted file mode 100644 index 8fb1d5247..000000000 --- a/game/server/ai_moveshoot.h +++ /dev/null @@ -1,54 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef AI_MOVESHOOT_H -#define AI_MOVESHOOT_H - -#include "ai_component.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -//----------------------------------------------------------------------------- -// @TODO (toml 07-09-03): probably want to fold this into base NPC. evaluate when -// head above water - -class CAI_MoveAndShootOverlay : public CAI_Component -{ - typedef CAI_Component BaseClass; - -public: - CAI_MoveAndShootOverlay(); - - void StartShootWhileMove( ); - void NoShootWhileMove(); - void RunShootWhileMove(); - void EndShootWhileMove(); - void SuspendMoveAndShoot( float flDuration ); - bool IsSuspended() { return m_flSuspendUntilTime > gpGlobals->curtime; } - - void SetInitialDelay( float delay ); - - bool IsMovingAndShooting( void ) const { return m_bMovingAndShooting; } - -private: - - bool HasAvailableRangeAttack(); - bool CanAimAtEnemy(); - void UpdateMoveShootActivity( bool bMoveAimAtEnemy ); - - bool m_bMovingAndShooting; - bool m_bNoShootWhileMove; - float m_initialDelay; - float m_flSuspendUntilTime; - - DECLARE_SIMPLE_DATADESC(); -}; - -//----------------------------------------------------------------------------- - -#endif // AI_MOVESHOOT_H diff --git a/game/server/ai_movesolver.cpp b/game/server/ai_movesolver.cpp deleted file mode 100644 index 5451cdc16..000000000 --- a/game/server/ai_movesolver.cpp +++ /dev/null @@ -1,410 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -#include "ai_movesolver.h" -#include "ndebugoverlay.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- - -inline float round( float f ) -{ - return (float)( (int)( f + 0.5 ) ); -} - -//----------------------------------------------------------------------------- -// CAI_MoveSolver -//----------------------------------------------------------------------------- - -// The epsilon used by the solver -const float AIMS_EPS = 0.01; - - -//----------------------------------------------------------------------------- -// Visualization -//----------------------------------------------------------------------------- -void CAI_MoveSolver::VisualizeRegulations( const Vector& origin ) -{ - if ( m_Regulations.Count() ) - { - CAI_MoveSuggestions regulations; - regulations.AddVectorToTail( m_Regulations ); - NormalizeSuggestions( ®ulations[0], (®ulations[0]) + regulations.Count() ); - - Vector side1, mid, side2; - for (int i = regulations.Count(); --i >= 0; ) - { - // Compute the positions of the angles... - float flMinAngle = regulations[i].arc.center - regulations[i].arc.span * 0.5f; - float flMaxAngle = regulations[i].arc.center + regulations[i].arc.span * 0.5f; - - side1 = UTIL_YawToVector( flMinAngle ); - side2 = UTIL_YawToVector( flMaxAngle ); - mid = UTIL_YawToVector( regulations[i].arc.center ); - - // Stronger weighted ones are bigger - if ( regulations[i].weight < 0 ) - { - float flLength = 10 + 40 * ( regulations[i].weight * -1.0); - side1 *= flLength; - side2 *= flLength; - mid *= flLength; - - side1 += origin; - side2 += origin; - mid += origin; - - NDebugOverlay::Triangle(origin, mid, side1, 255, 0, 0, 48, true, 0.1f ); - NDebugOverlay::Triangle(origin, side2, mid, 255, 0, 0, 48, true, 0.1f ); - } - } - } -} - - -//------------------------------------- -// Purpose: The actual solver function. Reweights according to type and sums -// all the suggestions, identifying the best. -//------------------------------------- -bool CAI_MoveSolver::Solve( const AI_MoveSuggestion_t *pSuggestions, int nSuggestions, AI_MoveSolution_t *pResult) -{ - //--------------------------------- - // - // Quick out - // - if ( !nSuggestions ) - return false; - - if ( nSuggestions == 1 && m_Regulations.Count() == 0 && pSuggestions->type == AIMST_MOVE ) - { - pResult->dir = pSuggestions->arc.center; - return true; - } - - //--------------------------------- - // - // Setup - // - CAI_MoveSuggestions suggestions; - - suggestions.EnsureCapacity( m_Regulations.Count() + nSuggestions ); - - suggestions.CopyArray( pSuggestions, nSuggestions); - suggestions.AddVectorToTail( m_Regulations ); - - // Initialize the solver - const int NUM_SOLUTIONS = 120; - const int SOLUTION_ANG = 360 / NUM_SOLUTIONS; - - COMPILE_TIME_ASSERT( ( 360 % NUM_SOLUTIONS ) == 0 ); - - struct Solution_t - { - // The sum bias - float bias; - float highBias; - AI_MoveSuggestion_t *pHighSuggestion; - }; - - Solution_t solutions[NUM_SOLUTIONS] = { {0.0f, 0.0f, NULL} }; - - //--------------------------------- - - // The first thing we do is reweight and normalize the weights into a range of [-1..1], where - // a negative weight is a repulsion. This becomes a bias for the solver. - // @TODO (toml 06-18-02): this can be made sligtly more optimal by precalculating regulation adjusted weights - Assert( suggestions.Count() >= 1 ); - NormalizeSuggestions( &suggestions[0], (&suggestions[0]) + suggestions.Count() ); - - // - // Add the biased suggestions to the solutions - // - for ( int iSuggestion = 0; iSuggestion < suggestions.Count(); ++iSuggestion ) - { - AI_MoveSuggestion_t ¤t = suggestions[iSuggestion]; - - // Convert arc values to solution indices relative to right post. Right is angle down, left is angle up. - float halfSpan = current.arc.span * 0.5; - int center = (int)round( ( halfSpan * NUM_SOLUTIONS ) / 360 ); - int left = (int)( (current.arc.span * NUM_SOLUTIONS) / 360 ); - - float angRight = current.arc.center - halfSpan; - - if (angRight < 0.0) - angRight += 360; - - int base = (int)( (angRight * NUM_SOLUTIONS) / 360 ); - - // Sweep from left to right, summing the bias. For positive suggestions, - // the bias is further weighted to favor the center of the arc. - const float positiveDegradePer180 = 0.05; // i.e., lose 5% of weight by the time hit 180 degrees off center - const float positiveDegrade = ( positiveDegradePer180 / ( NUM_SOLUTIONS * 0.5 ) ); - - for ( int i = 0; i < left + 1; ++i ) - { - float bias = 0.0; - - if ( current.weight > 0) - { - int iOffset = center - i; - float degrade = abs( iOffset ) * positiveDegrade; - - if ( ( (current.flags & AIMS_FAVOR_LEFT ) && i > center ) || - ( (current.flags & AIMS_FAVOR_RIGHT) && i < center ) ) - { - degrade *= 0.9; - } - - bias = current.weight - ( current.weight * degrade ); - } - else - bias = current.weight; - - int iCurSolution = (base + i) % NUM_SOLUTIONS; - - solutions[iCurSolution].bias += bias; - if ( bias > solutions[iCurSolution].highBias ) - { - solutions[iCurSolution].highBias = bias; - solutions[iCurSolution].pHighSuggestion = ¤t; - } - } - } - - // - // Find the best solution - // - int best = -1; - float biasBest = 0; - - for ( int i = 0; i < NUM_SOLUTIONS; ++i ) - { - if ( solutions[i].bias > biasBest ) - { - best = i; - biasBest = solutions[i].bias; - } - } - - if ( best == -1 ) - return false; // no solution - - // - // Construct the results - // - float result = best * SOLUTION_ANG; - - // If the matching suggestion is within the solution, use that as the result, - // as it is valid and more precise. - const float suggestionCenter = solutions[best].pHighSuggestion->arc.center; - - if ( suggestionCenter > result && suggestionCenter <= result + SOLUTION_ANG ) - result = suggestionCenter; - - pResult->dir = result; - - return true; -} - -//------------------------------------- -// Purpose: Adjusts the suggestion weights according to the type of the suggestion, -// apply the appropriate sign, ensure values are in expected ranges -//------------------------------------- - -struct AI_MoveSuggWeights -{ - float min; - float max; -}; - -static AI_MoveSuggWeights g_AI_MoveSuggWeights[] = // @TODO (toml 06-18-02): these numbers need tuning -{ - { 0.20, 1.00 }, // AIMST_MOVE - { -0.00, -0.25 }, // AIMST_AVOID_DANGER - { -0.00, -0.25 }, // AIMST_AVOID_OBJECT - { -0.00, -0.25 }, // AIMST_AVOID_NPC - { -0.00, -0.25 }, // AIMST_AVOID_WORLD - { -1.00, -1.00 }, // AIMST_NO_KNOWLEDGE - { -0.60, -0.60 }, // AIMST_OSCILLATION_DETERRANCE - { 0.00, 0.00 }, // AIMST_INVALID -}; - -void CAI_MoveSolver::NormalizeSuggestions( AI_MoveSuggestion_t *pBegin, AI_MoveSuggestion_t *pEnd ) -{ - while ( pBegin != pEnd ) - { - const float min = g_AI_MoveSuggWeights[pBegin->type].min; - const float max = g_AI_MoveSuggWeights[pBegin->type].max; - - Assert( pBegin->weight >= -AIMS_EPS && pBegin->weight <= 1.0 + AIMS_EPS ); - - if ( pBegin->weight < AIMS_EPS ) // zero normalizes to zero - pBegin->weight = 0.0; - else - pBegin->weight = ( ( max - min ) * pBegin->weight ) + min; - - while (pBegin->arc.center < 0) - pBegin->arc.center += 360; - - while (pBegin->arc.center >= 360) - pBegin->arc.center -= 360; - - ++pBegin; - } -} - -//------------------------------------- - -bool CAI_MoveSolver::HaveRegulationForObstacle( CBaseEntity *pEntity) -{ - for ( int i = 0; i < m_Regulations.Count(); ++i ) - { - if ( m_Regulations[i].hObstacleEntity != NULL && - pEntity == m_Regulations[i].hObstacleEntity.Get() ) - { - return true; - } - } - return false; -} - -//----------------------------------------------------------------------------- -// -// Commands and tests -// - -#ifdef DEBUG -CON_COMMAND(ai_test_move_solver, "Tests the AI move solver system") -{ -#ifdef DEBUG - const float EPS = 0.001; -#endif - DevMsg( "Beginning move solver tests...\n" ); - - CAI_MoveSolver solver; - AI_MoveSolution_t solution; - int i; - - // - // Value in, no regulations, should yield value out - // - { - DevMsg( "Simple... " ); - - for (i = 0; i < 360; ++i) - { - Assert( solver.Solve( AI_MoveSuggestion_t( AIMST_MOVE, 1, i, 180 ), &solution ) ); - Assert( solution.dir == (float)i ); - - } - - DevMsg( "pass.\n" ); - solver.ClearRegulations(); - } - - // - // Two values in, should yield the first - // - { - DevMsg( "Two positive... " ); - - AI_MoveSuggestion_t suggestions[2]; - - suggestions[0].Set( AIMST_MOVE, 1.0, 180, 100 ); - suggestions[1].Set( AIMST_MOVE, 0.5, 0, 100 ); - - Assert( solver.Solve( suggestions, 2, &solution ) ); - Assert( solution.dir == (float)suggestions[0].arc.center ); - - - DevMsg( "pass.\n" ); - solver.ClearRegulations(); - } - - // - // Two values in, first regulated, should yield the second - // - { - DevMsg( "Avoid one of two... " ); - - AI_MoveSuggestion_t suggestions[2]; - - solver.AddRegulation(AI_MoveSuggestion_t( AIMST_AVOID_OBJECT, 1, 260, 60 ) ); - - suggestions[0].Set( AIMST_MOVE, 1.0, 270, 45 ); - suggestions[1].Set( AIMST_MOVE, 1.0, 0, 45 ); - - Assert( solver.Solve( suggestions, 2, &solution ) ); - Assert( solution.dir == (float)suggestions[1].arc.center ); - - - DevMsg( "pass.\n" ); - solver.ClearRegulations(); - } - - // - // No solution - // - { - DevMsg( "No solution... " ); - - AI_MoveSuggestion_t suggestions[2]; - - suggestions[0].Set( AIMST_MOVE, 1.0, 270, 90 ); - suggestions[1].Set( AIMST_AVOID_OBJECT, 1.0, 260, 180 ); - - Assert( !solver.Solve( suggestions, 2, &solution ) ); - - DevMsg( "pass.\n" ); - solver.ClearRegulations(); - } - - // - // Nearest solution, in tolerance - // - { - DevMsg( "Nearest solution, in tolerance... " ); - - AI_MoveSuggestion_t suggestions[2]; - - suggestions[0].Set( AIMST_MOVE, 1.0, 278, 90 ); - suggestions[1].Set( AIMST_AVOID_OBJECT, 1.0, 260, 24 ); - - Assert( solver.Solve( suggestions, 2, &solution ) ); - Assert( solution.dir == (float)suggestions[0].arc.center ); - - DevMsg( "pass.\n" ); - solver.ClearRegulations(); - } - - // - // Nearest solution - // - { - DevMsg( "Nearest solution... " ); - - AI_MoveSuggestion_t suggestions[2]; - - suggestions[0].Set( AIMST_MOVE, 1.0, 270, 90 ); - suggestions[1].Set( AIMST_AVOID_OBJECT, 1.0, 260, 40 ); - - Assert( solver.Solve( suggestions, 2, &solution ) ); - Assert( solution.dir - 282 < EPS ); // given 60 solutions - - DevMsg( "pass.\n" ); - solver.ClearRegulations(); - } - -} -#endif - -//============================================================================= - diff --git a/game/server/ai_movesolver.h b/game/server/ai_movesolver.h deleted file mode 100644 index 12a89888d..000000000 --- a/game/server/ai_movesolver.h +++ /dev/null @@ -1,312 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: "Force-field" obstacle avoidance & steering -// -// @Note (toml 06-18-02): Currently only controls direction. Ultimately could -// also incorporate body facing (yaw), speed, and translational/rotational -// acceleration. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_MOVESOLVER_H -#define AI_MOVESOLVER_H - -#if defined( _WIN32 ) -#pragma once -#endif - -#include "utlvector.h" -#include "ai_obstacle_type.h" - - -//----------------------------------------------------------------------------- - -inline float NormalizeAngle( float angle ) -{ - if ( angle < 0.0 ) - angle += 360.0; - else if ( angle >= 360.0 ) - angle -= 360.0; - return angle; -} - -//----------------------------------------------------------------------------- -// ENUMERATIONS -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// STRUCTURES -//----------------------------------------------------------------------------- - -//------------------------------------- -// AI_Arc_t -// -// Purpose: Represents an arc. -// -//------------------------------------- -struct AI_Arc_t -{ - AI_Arc_t() - : center( 0 ), - span( 0 ) - { - } - - // Set by center and span - void Set( float newCenter, float newSpan ); - - // Set by the right and left extremes (coordinates run counter clockwise) - void SetByLimits( float yawRight, float yawLeft ); - - // Center of the arc (as "yaw") - float center; - - // Span of the arc (in degrees) - float span; -}; - -//------------------------------------- -// AI_MoveSuggestion_t -// -// Purpose: Suggests a possible move/avoidance, with a range of acceptable alternatives -// -// @Note (toml 06-20-02): this probably will eventually want to incorporate facing and -// destination of the motivating goal. -// -//------------------------------------- - -enum AI_MoveSuggestionFlags_t -{ - AIMS_FAVOR_LEFT = 0x01, - AIMS_FAVOR_RIGHT = 0x02 -}; - -//----------------- - -struct AI_MoveSuggestion_t -{ - AI_MoveSuggestion_t(); - AI_MoveSuggestion_t( AI_MoveSuggType_t newType, float newWeight, float newDir, float newSpan, CBaseEntity *pEntity = NULL ); - AI_MoveSuggestion_t( AI_MoveSuggType_t newType, float newWeight, const AI_Arc_t &arc, CBaseEntity *pEntity = NULL ); - - void Set( AI_MoveSuggType_t newType, float newWeight, float newDir, float newSpan, CBaseEntity *pEntity = NULL ); - void Set( AI_MoveSuggType_t newType, float newWeight, const AI_Arc_t &arc, CBaseEntity *pEntity = NULL ); - - //--------------------------------- - - // The kind of suggestion - AI_MoveSuggType_t type; - - // The unadjusted weight of the suggestion [0..1], although [-1..1] within the solver - float weight; - - // The desired direction to move/avoid - AI_Arc_t arc; - - // The causing entity, if any - EHANDLE hObstacleEntity; - - // Flags - unsigned flags; - -}; - -//----------------- - -typedef CUtlVector CAI_MoveSuggestions; - -//------------------------------------- -// AI_MoveSolution_t -// -// Purpose: The result of resolving suggestions -// -// @Note (toml 06-18-02): Currently, this is a very dopey little structure. -// However, it will probably eventually incorporate much of the info -// passed or calculated piecemeal between Move...() and Move...Execute() -// functions. Once suggestions incorprate more information, the solution -// may want to include a copy of the winning suggestion, so that the -// caller need retain less state. If this is not the case, reduce it to just -// a yaw. -// -//------------------------------------- -struct AI_MoveSolution_t -{ - AI_MoveSolution_t() - : dir(0) - { - } - - // The direction to move - float dir; -}; - -//----------------------------------------------------------------------------- -// class CAI_MoveSolver -// -// Purpose: Given a set of precalculated "regulations" (typically negative), -// and a set of instantaneous suggestions (usually positive) -//----------------------------------------------------------------------------- - -class CAI_MoveSolver -{ -public: - CAI_MoveSolver(); - - //--------------------------------- - // Purpose: A regulation is a suggestion that is kept around as a rule until - // cleared. They are generally negative suggestions. - //--------------------------------- - void AddRegulation( const AI_MoveSuggestion_t &suggestion ); - void AddRegulations( const AI_MoveSuggestion_t *pSuggestion, int nSuggestions ); - - bool HaveRegulations() const; - void ClearRegulations(); - - //--------------------------------- - // Purpose: Solve the move, picking the best direction from a set of suggestions, - // after applying the regulations - //--------------------------------- - bool Solve( const AI_MoveSuggestion_t *pSuggestions, int nSuggestions, AI_MoveSolution_t *pResult ); - bool Solve( const AI_MoveSuggestion_t &suggestion, AI_MoveSolution_t *pResult ); - - //--------------------------------- - bool HaveRegulationForObstacle( CBaseEntity *pEntity); - - //--------------------------------- - // Visualization - void VisualizeRegulations( const Vector& origin ); - -private: - enum - { - REGS_RESERVE = 8, - }; - - //--------------------------------- - void NormalizeSuggestions( AI_MoveSuggestion_t *pBegin, AI_MoveSuggestion_t *pEnd ); - - //--------------------------------- - CAI_MoveSuggestions m_Regulations; -}; - -//----------------------------------------------------------------------------- -// AI_Arc_t inline methods -//----------------------------------------------------------------------------- - -inline void AI_Arc_t::Set( float newCenter, float newSpan ) -{ - center = NormalizeAngle( newCenter ); - span = NormalizeAngle( newSpan ); -} - -//------------------------------------- - -inline void AI_Arc_t::SetByLimits( float yawRight, float yawLeft ) -{ - // Yaw runs counter-clockwise - span = yawLeft - yawRight; - - if ( span < 0 ) - span += 360; - - center = yawRight + span * 0.5; - - if ( center >= 360 ) - center -= 360; -} - -//----------------------------------------------------------------------------- -// AI_MoveSuggestion_t inline methods -//----------------------------------------------------------------------------- - -inline void AI_MoveSuggestion_t::Set( AI_MoveSuggType_t newType, float newWeight, float newDir, float newSpan, CBaseEntity *pEntity ) -{ - type = newType; - weight = newWeight; - hObstacleEntity = pEntity; - flags = 0; - - arc.Set( newDir, newSpan ); -} - -//------------------------------------- - -inline AI_MoveSuggestion_t::AI_MoveSuggestion_t() - : type( AIMS_INVALID ), - weight( 0 ), - flags( 0 ) -{ -} - -//------------------------------------- - -inline AI_MoveSuggestion_t::AI_MoveSuggestion_t( AI_MoveSuggType_t newType, float newWeight, float newDir, float newSpan, CBaseEntity *pEntity ) -{ - Set( newType, newWeight, newDir, newSpan, pEntity ); -} - -//------------------------------------- - -inline AI_MoveSuggestion_t::AI_MoveSuggestion_t( AI_MoveSuggType_t newType, float newWeight, const AI_Arc_t &arc, CBaseEntity *pEntity ) -{ - Set( newType, newWeight, arc.center, arc.span, pEntity ); -} - -//------------------------------------- - -inline void AI_MoveSuggestion_t::Set( AI_MoveSuggType_t newType, float newWeight, const AI_Arc_t &arc, CBaseEntity *pEntity ) -{ - Set( newType, newWeight, arc.center, arc.span, pEntity ); -} - -//----------------------------------------------------------------------------- -// CAI_MoveSolver inline methods -//----------------------------------------------------------------------------- - -inline CAI_MoveSolver::CAI_MoveSolver() -{ - m_Regulations.EnsureCapacity( REGS_RESERVE ); -} - -//------------------------------------- - -inline void CAI_MoveSolver::AddRegulation( const AI_MoveSuggestion_t &suggestion ) -{ - m_Regulations.AddToTail( suggestion ); -} - -//------------------------------------- - -inline void CAI_MoveSolver::AddRegulations( const AI_MoveSuggestion_t *pSuggestions, int nSuggestions ) -{ - for (int i = 0; i < nSuggestions; ++i) - { - m_Regulations.AddToTail( pSuggestions[i] ); - } -} - -//------------------------------------- - -inline bool CAI_MoveSolver::HaveRegulations() const -{ - return (m_Regulations.Count() > 0); -} - -//------------------------------------- - -inline void CAI_MoveSolver::ClearRegulations() -{ - m_Regulations.RemoveAll(); -} - -//------------------------------------- - -inline bool CAI_MoveSolver::Solve( const AI_MoveSuggestion_t &suggestion, AI_MoveSolution_t *pResult) -{ - return Solve( &suggestion, 1, pResult); -} - -//============================================================================= - -#endif // AI_MOVESOLVER_H diff --git a/game/server/ai_movetypes.h b/game/server/ai_movetypes.h deleted file mode 100644 index 8815d3c4d..000000000 --- a/game/server/ai_movetypes.h +++ /dev/null @@ -1,383 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef AI_MOVETYPES_H -#define AI_MOVETYPES_H - -#if defined( _WIN32 ) -#pragma once -#endif - -#include "ai_navtype.h" - -class CAI_Path; - -//----------------------------------------------------------------------------- -// Debugging code -// -// Use this function to set breakpoints to find out where movement is failing -// -#ifdef DEBUG -extern void DebugNoteMovementFailure(); -#define DebugNoteMovementFailureIfBlocked( moveResult ) if ( !IsMoveBlocked( moveResult ) ) ((void)0); else DebugNoteMovementFailure() -#else -#define DebugNoteMovementFailure() ((void)0) -#define DebugNoteMovementFailureIfBlocked( moveResult ) ((void)0) -#endif - -enum AIMoveResult_t -{ - AIMR_BLOCKED_ENTITY = -1, // Move was blocked by an entity - AIMR_BLOCKED_WORLD = -2, // Move was blocked by the world - AIMR_BLOCKED_NPC = -3, // Move was blocked by an NPC - AIMR_ILLEGAL = -4, // Move is illegal for some reason - - AIMR_OK = 0, - - AIMR_CHANGE_TYPE, // Locomotion method has changed -}; - - -#ifdef DEBUG -extern AIMoveResult_t DbgResult( AIMoveResult_t result ); -#else -inline AIMoveResult_t DbgResult( AIMoveResult_t result ) { return result; } // inline not macro for compiler typing -#endif - - -//----------------------------------------------------------------------------- -// Movement related constants and base types -//----------------------------------------------------------------------------- -#ifdef PHYSICS_NPC_SHADOW_DISCREPENCY -const float AI_EPS_CASTS = 0.3; // The amount physics and hull cast can disagree -#endif - - -inline bool IsMoveBlocked( AIMoveResult_t moveResult ) -{ - return (moveResult < AIMR_OK ); -} - -//------------------------------------- - -enum StepGroundTest_t -{ - STEP_DONT_CHECK_GROUND = 0, - STEP_ON_VALID_GROUND, - STEP_ON_INVALID_GROUND, -}; - - -//------------------------------------- - -struct AIMoveTrace_t -{ - AIMoveTrace_t() - { - memset( this, 0, sizeof(*this) ); - } - - AIMoveResult_t fStatus; // See AIMoveResult_t - Vector vEndPosition; // The last point that could be moved to - Vector vHitNormal; // The normal of a hit, if any. vec3_origin if none. Can be none even if "hit" - CBaseEntity* pObstruction; // The obstruction I bumped into (if any) - float flTotalDist; - float flDistObstructed; // FIXME: This is a strange number. In the case - // of calling MoveLimit with navtype NAV_GROUND, - // it represents a 2D distance to the obstruction. - // In the case of other navtypes, it represents a - // 3D distance to the obstruction - Vector vJumpVelocity; // FIXME: Remove this; it's bogus - // It's only returned by JumpMoveLimit - // which seems to be a bogus concept to begin with - float flStepUpDistance; -}; - -inline bool IsMoveBlocked( const AIMoveTrace_t &moveTrace ) -{ - return (moveTrace.fStatus < AIMR_OK ); -} - - -// Categorizes the blocker and sets the appropriate bits -AIMoveResult_t AIComputeBlockerMoveResult( CBaseEntity *pBlocker ); - - -//------------------------------------- -// Purpose: Specifies an immediate, localized, straight line movement goal -//------------------------------------- - -enum AILocalMoveGoalFlags_t -{ - AILMG_NONE, - AILMG_TARGET_IS_GOAL = 0x01, - AILMG_CONSUME_INTERVAL = 0x02, - AILMG_TARGET_IS_TRANSITION = 0x04, - AILMG_NO_STEER = 0x08, - AILMG_NO_AVOIDANCE_PATHS = 0x10, -}; - -struct AILocalMoveGoal_t -{ - AILocalMoveGoal_t() - { - memset( this, 0, sizeof(*this) ); - } - - // Object of the goal - Vector target; - - // The actual move. Note these need not always agree with "target" - Vector dir; - Vector facing; - float speed; - - // The distance maximum distance intended to travel in path length - float maxDist; - - // The distance expected to move this think - float curExpectedDist; - - Navigation_t navType; - CBaseEntity * pMoveTarget; - - unsigned flags; - - // The path from which this goal was derived - CAI_Path * pPath; - - // The result if a forward probing trace has been done - bool bHasTraced; - AIMoveTrace_t directTrace; - AIMoveTrace_t thinkTrace; - -#ifdef DEBUG - int solveCookie; -#endif -}; - -//------------------------------------- - -enum AIMotorMoveResult_t -{ - AIM_FAILED, - AIM_SUCCESS, - - // Partial successes - AIM_PARTIAL_HIT_NPC, - AIM_PARTIAL_HIT_WORLD, - AIM_PARTIAL_HIT_TARGET, - - AIM_NUM_RESULTS -}; - -//----------------------------------------------------------------------------- -// Purpose: The set of callbacks used by lower-level movement classes to -// notify and receive guidance from higher level-classes -//----------------------------------------------------------------------------- - -abstract_class IAI_MovementSink -{ -public: - //--------------------------------- - // - // Queries - // - virtual float CalcYawSpeed( void ) = 0; - - //--------------------------------- - // - // Local navigation notifications, each allows services provider to overridde default result - // - virtual bool OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, - float distClear, - AIMoveResult_t *pResult ) = 0; - - virtual bool OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal, - float distClear, - AIMoveResult_t *pResult ) = 0; - - virtual bool OnFailedSteer( AILocalMoveGoal_t *pMoveGoal, - float distClear, - AIMoveResult_t *pResult ) = 0; - - virtual bool OnFailedLocalNavigation( AILocalMoveGoal_t *pMoveGoal, - float distClear, - AIMoveResult_t *pResult ) = 0; - - virtual bool OnInsufficientStopDist( AILocalMoveGoal_t *pMoveGoal, - float distClear, - AIMoveResult_t *pResult ) = 0; - - - virtual bool OnMoveBlocked( AIMoveResult_t *pResult ) = 0; - - //--------------------------------- - // - // Motor notifications, each allows services provider to overridde default result - // - virtual bool OnMoveStalled( const AILocalMoveGoal_t &move ) = 0; - virtual bool OnMoveExecuteFailed( const AILocalMoveGoal_t &move, - const AIMoveTrace_t &trace, - AIMotorMoveResult_t fMotorResult, - AIMoveResult_t *pResult ) = 0; -}; - -//----------------------------------------------------------------------------- -// Purpose: Default implementations of IAI_MovementSink -//----------------------------------------------------------------------------- - -class CAI_DefMovementSink : public IAI_MovementSink -{ -public: - //--------------------------------- - // - // Queries - // - virtual float CalcYawSpeed( void ) { return -1.0; } - - - //--------------------------------- - // - // Local navigation notifications, each allows services provider to overridde default result - // - virtual bool OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) { return false; } - virtual bool OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) { return false; } - virtual bool OnFailedSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) { return false; } - virtual bool OnFailedLocalNavigation( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) { return false; } - virtual bool OnInsufficientStopDist( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) { return false; } - virtual bool OnMoveBlocked( AIMoveResult_t *pResult ) { return false; } - - //--------------------------------- - // - // Motor notifications, each allows services provider to overridde default result - // - virtual bool OnMoveStalled( const AILocalMoveGoal_t &move ) { return false; } - virtual bool OnMoveExecuteFailed( const AILocalMoveGoal_t &move, const AIMoveTrace_t &trace, AIMotorMoveResult_t fMotorResult, AIMoveResult_t *pResult ) { return false; } - -}; - -//------------------------------------- - -class CAI_ProxyMovementSink : public CAI_DefMovementSink -{ -public: - CAI_ProxyMovementSink() - : m_pProxied( NULL ) - { - } - - //--------------------------------- - - void Init( IAI_MovementSink *pMovementServices ) { m_pProxied = pMovementServices; } - - //--------------------------------- - // - // Queries - // - virtual float CalcYawSpeed( void ); - - //--------------------------------- - // - // Local navigation notifications, each allows services provider to overridde default result - // - virtual bool OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, - float distClear, - AIMoveResult_t *pResult ); - - virtual bool OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal, - float distClear, - AIMoveResult_t *pResult ); - virtual bool OnFailedSteer( AILocalMoveGoal_t *pMoveGoal, - float distClear, - AIMoveResult_t *pResult ); - virtual bool OnFailedLocalNavigation( AILocalMoveGoal_t *pMoveGoal, - float distClear, - AIMoveResult_t *pResult ); - virtual bool OnInsufficientStopDist( AILocalMoveGoal_t *pMoveGoal, - float distClear, - AIMoveResult_t *pResult ); - virtual bool OnMoveBlocked( AIMoveResult_t *pResult ); - - //--------------------------------- - // - // Motor notifications, each allows services provider to overridde default result - // - virtual bool OnMoveStalled( const AILocalMoveGoal_t &move ); - virtual bool OnMoveExecuteFailed( const AILocalMoveGoal_t &move, const AIMoveTrace_t &trace, AIMotorMoveResult_t fMotorResult, AIMoveResult_t *pResult ); - - IAI_MovementSink *m_pProxied; -}; - -// ---------------------------------------------------------------------------- - -inline float CAI_ProxyMovementSink::CalcYawSpeed( void ) -{ - float result; - if ( m_pProxied && ( result = m_pProxied->CalcYawSpeed() ) != -1.0 ) - return result; - return CAI_DefMovementSink::CalcYawSpeed(); -} - -inline bool CAI_ProxyMovementSink::OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) -{ - if ( m_pProxied && m_pProxied->OnCalcBaseMove( pMoveGoal, distClear, pResult ) ) - return true; - return CAI_DefMovementSink::OnCalcBaseMove( pMoveGoal, distClear, pResult ); -} - -inline bool CAI_ProxyMovementSink::OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) -{ - if ( m_pProxied && m_pProxied->OnObstructionPreSteer( pMoveGoal, distClear, pResult ) ) - return true; - return CAI_DefMovementSink::OnObstructionPreSteer( pMoveGoal, distClear, pResult ); -} - -inline bool CAI_ProxyMovementSink::OnFailedSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) -{ - if ( m_pProxied && m_pProxied->OnFailedSteer( pMoveGoal, distClear, pResult ) ) - return true; - return CAI_DefMovementSink::OnFailedSteer( pMoveGoal, distClear, pResult ); -} - -inline bool CAI_ProxyMovementSink::OnFailedLocalNavigation( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) -{ - if ( m_pProxied && m_pProxied->OnFailedLocalNavigation( pMoveGoal, distClear, pResult ) ) - return true; - return CAI_DefMovementSink::OnFailedLocalNavigation( pMoveGoal, distClear, pResult ); -} - -inline bool CAI_ProxyMovementSink::OnInsufficientStopDist( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) -{ - if ( m_pProxied && m_pProxied->OnInsufficientStopDist( pMoveGoal, distClear, pResult ) ) - return true; - return CAI_DefMovementSink::OnInsufficientStopDist( pMoveGoal, distClear, pResult ); -} - -inline bool CAI_ProxyMovementSink::OnMoveStalled( const AILocalMoveGoal_t &move ) -{ - if ( m_pProxied && m_pProxied->OnMoveStalled( move ) ) - return true; - return CAI_DefMovementSink::OnMoveStalled( move ); -} - -inline bool CAI_ProxyMovementSink::OnMoveExecuteFailed( const AILocalMoveGoal_t &move, const AIMoveTrace_t &trace, AIMotorMoveResult_t fMotorResult, AIMoveResult_t *pResult ) -{ - if ( m_pProxied && m_pProxied->OnMoveExecuteFailed( move, trace, fMotorResult, pResult ) ) - return true; - return CAI_DefMovementSink::OnMoveExecuteFailed( move, trace, fMotorResult, pResult ); -} - -inline bool CAI_ProxyMovementSink::OnMoveBlocked( AIMoveResult_t *pResult ) -{ - if ( m_pProxied && m_pProxied->OnMoveBlocked( pResult ) ) - return true; - return CAI_DefMovementSink::OnMoveBlocked( pResult ); -} - -//============================================================================= - -#endif // AI_MOVETYPES_H diff --git a/game/server/ai_namespaces.cpp b/game/server/ai_namespaces.cpp deleted file mode 100644 index 338e4a547..000000000 --- a/game/server/ai_namespaces.cpp +++ /dev/null @@ -1,224 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -#include "stringregistry.h" -#include "ai_namespaces.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// CAI_GlobalNamespace -// - -CAI_GlobalNamespace::CAI_GlobalNamespace() - : m_pSymbols( new CStringRegistry ), - m_NextGlobalBase( GLOBAL_IDS_BASE ) -{ -} - -//------------------------------------- - -CAI_GlobalNamespace::~CAI_GlobalNamespace() -{ - delete m_pSymbols; -} - -//------------------------------------- - -void CAI_GlobalNamespace::Clear() -{ - m_pSymbols->ClearStrings(); - m_NextGlobalBase = GLOBAL_IDS_BASE; -} - -//------------------------------------- - -void CAI_GlobalNamespace::AddSymbol( const char *pszSymbol, int symbolID ) -{ - MEM_ALLOC_CREDIT(); - AssertMsg( symbolID != -1, "Invalid symbol id passed to CAI_GlobalNamespace::AddSymbol()" ); - if (symbolID == -1 ) - return; - - AssertMsg( AI_IdIsGlobal( symbolID ), ("Local symbol ID passed to CAI_GlobalNamespace::AddSymbol()") ); - AssertMsg( !IdToSymbol( symbolID ) , ("Duplicate symbol ID passed to CAI_GlobalNamespace::AddSymbol()") ); - AssertMsg( SymbolToId( pszSymbol ) == -1, ("Duplicate symbol passed to CAI_GlobalNamespace::AddSymbol()") ); - - m_pSymbols->AddString( pszSymbol, symbolID ); - - if ( m_NextGlobalBase < symbolID + 1 ) - m_NextGlobalBase = symbolID + 1; -} - -//------------------------------------- - -const char *CAI_GlobalNamespace::IdToSymbol( int symbolID ) const -{ - AssertMsg( AI_IdIsGlobal( symbolID ), ("Local symbol ID passed to CAI_GlobalNamespace::IdToSymbol()") ); - if ( symbolID == -1 ) - return "<>"; - return (const_cast(m_pSymbols))->GetStringText( symbolID ); -} - -//------------------------------------- - -int CAI_GlobalNamespace::SymbolToId( const char *pszSymbol ) const -{ - return (const_cast(m_pSymbols))->GetStringID( pszSymbol ); -} - -//------------------------------------- - -int CAI_GlobalNamespace::NextGlobalBase() const -{ - return m_NextGlobalBase; -} - -//----------------------------------------------------------------------------- -// CAI_LocalIdSpace -// -// Purpose: Maps per class IDs to global IDs, so that various classes can use -// the same integer in local space to represent different globally -// unique integers. Used for schedules, tasks, conditons and squads -// - -CAI_LocalIdSpace::CAI_LocalIdSpace( bool fIsRoot ) - : m_globalBase( (fIsRoot) ? 0 : -1 ), - m_localBase( (fIsRoot) ? 0 : MAX_STRING_INDEX ), - m_localTop( -1 ), - m_globalTop( -1 ), - m_pParentIDSpace( NULL ), - m_pGlobalNamespace( NULL ) -{ -}; - -//------------------------------------- - -bool CAI_LocalIdSpace::Init( CAI_GlobalNamespace *pGlobalNamespace, CAI_LocalIdSpace *pParentIDSpace ) -{ - if ( m_globalTop != -1 ) - { - m_localBase = (!pParentIDSpace) ? 0 : MAX_STRING_INDEX; - m_localTop = -1; - m_globalTop = -1; - } - - m_pParentIDSpace = pParentIDSpace; - m_pGlobalNamespace = pGlobalNamespace; - m_globalBase = m_pGlobalNamespace->NextGlobalBase(); - - return true; -} - -//------------------------------------- - -bool CAI_LocalIdSpace::AddSymbol( const char *pszSymbol, int localId, const char *pszDebugSymbolType, const char *pszDebugOwner ) -{ - AssertMsg( AI_IdIsLocal( localId ), ("Global symbol ID passed to CAI_LocalIdSpace::AddSymbol()") ); - - if ( !m_pGlobalNamespace ) - { - DevMsg( "ERROR: Adding symbol to uninitialized table %s\n", pszDebugOwner ); - return false; - } - - if ( !IsLocalBaseSet() && !SetLocalBase( localId ) ) - { - DevMsg( "ERROR: Bad %s LOCALID for %s\n", pszDebugSymbolType, pszDebugOwner ); - return false; - } - else if (localId < GetLocalBase() ) - { - DevMsg("ERROR: %s First added %s must be first LOCALID!\n", pszDebugSymbolType, pszDebugOwner); - return false; - } - - AssertMsg3( LocalToGlobal( localId ) == -1 || !m_pGlobalNamespace->IdToSymbol( LocalToGlobal( localId ) ) , "Duplicate symbol ID passed to CAI_LocalIdSpace::AddSymbol(): %s (%d), had %s", pszSymbol, localId, m_pGlobalNamespace->IdToSymbol( LocalToGlobal( localId ) ) ); - AssertMsg( m_pGlobalNamespace->SymbolToId( pszSymbol ) == -1, "Duplicate symbol passed to CAI_LocalIdSpace::AddSymbol()" ); - - if ( m_localTop != -1 ) - { - if ( localId > m_localTop ) - { - m_localTop = localId; - m_globalTop = ( m_localTop - m_localBase ) + m_globalBase; - } - } - else - { - m_localTop = m_localBase; - m_globalTop = m_globalBase; - } - - m_pGlobalNamespace->AddSymbol( pszSymbol, LocalToGlobal( localId ) ); - return true; -} - -//------------------------------------- - -bool CAI_LocalIdSpace::SetLocalBase( int newBase ) -{ - AssertMsg( AI_IdIsLocal( newBase ), ("Global symbol ID passed to CAI_LocalIdSpace::SetLocalBase()") ); - - if (m_localBase == MAX_STRING_INDEX) - { - // UNDONE: Make sure this is the largest Index in the list so far?? - m_localBase = newBase; - if ( !m_pParentIDSpace || !m_pParentIDSpace->IsLocalBaseSet() || m_localBase > m_pParentIDSpace->m_localBase )// @Note (toml 08-20-02): this doesn't actually catch namespace collisions, only woefully bad situations where a derived class' offset is less than the base - return true; - } - return false; -} - -//------------------------------------- - -int CAI_LocalIdSpace::GlobalToLocal( int globalID ) const -{ - if ( globalID == -1 ) - return -1; - - AssertMsg( AI_IdIsGlobal( globalID ), ("Local symbol ID passed to CAI_LocalIdSpace::GlobalToLocal()") ); - - const CAI_LocalIdSpace *pCurrentMap = this; - - do - { - if ( pCurrentMap->IsLocalBaseSet() && globalID >= pCurrentMap->GetGlobalBase() && globalID <= pCurrentMap->GetGlobalTop() ) - return ( globalID - pCurrentMap->GetGlobalBase() + pCurrentMap->GetLocalBase() ); - pCurrentMap = pCurrentMap->m_pParentIDSpace; - } while ( pCurrentMap != NULL ); - - // AssertMsg( 0, ("Invalid ID passed to CAI_LocalIdSpace::GlobalToLocal()") ); - return -1; -} - -//------------------------------------- - -int CAI_LocalIdSpace::LocalToGlobal( int localID ) const -{ - if ( localID == -1 ) - return -1; - - AssertMsg( AI_IdIsLocal( localID ), ("Global symbol ID passed to CAI_LocalIdSpace::LocalToGlobal()") ); - - const CAI_LocalIdSpace *pCurrentMap = this; - - do - { - if ( pCurrentMap->IsLocalBaseSet() && localID >= pCurrentMap->GetLocalBase() && localID <= pCurrentMap->GetLocalTop() ) - return ( localID + pCurrentMap->GetGlobalBase() - pCurrentMap->GetLocalBase() ); - pCurrentMap = pCurrentMap->m_pParentIDSpace; - } while ( pCurrentMap != NULL ); - - // AssertMsg( 0, ("Invalid ID passed to CAI_LocalIdSpace::LocalToGlobal()") ); - return -1; -} - -//----------------------------------------------------------------------------- diff --git a/game/server/ai_namespaces.h b/game/server/ai_namespaces.h deleted file mode 100644 index bb7fe0fe6..000000000 --- a/game/server/ai_namespaces.h +++ /dev/null @@ -1,287 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_NAMESPACES_H -#define AI_NAMESPACES_H - -class CStringRegistry; - -#if defined( _WIN32 ) -#pragma once -#endif - -#define MAX_STRING_INDEX 9999 -const int GLOBAL_IDS_BASE = 1000000000; // decimal for debugging readability - -//----------------------------------------------------------------------------- - -inline bool AI_IdIsGlobal( int id ) { return ( id >= GLOBAL_IDS_BASE || id == -1 ); } -inline bool AI_IdIsLocal( int id ) { return ( id < GLOBAL_IDS_BASE || id == -1 ); } -inline int AI_RemapToGlobal( int id ) { return ( id != -1 ) ? id + GLOBAL_IDS_BASE : -1; } -inline int AI_RemapFromGlobal( int id ) { return ( id != -1 ) ? id - GLOBAL_IDS_BASE : -1; } - -inline int AI_MakeGlobal( int id ) { return AI_IdIsLocal( id ) ? AI_RemapToGlobal( id ) : id; } - -//----------------------------------------------------------------------------- -// CAI_GlobalNamespace -// -// Purpose: Symbol table for all symbols across a given namespace, a -// bi-directional mapping of "text" to global ID -// - -class CAI_GlobalNamespace -{ -public: - CAI_GlobalNamespace(); - ~CAI_GlobalNamespace(); - - void Clear(); - - void AddSymbol( const char *pszSymbol, int symbolID ); - int NextGlobalBase() const; - - const char *IdToSymbol( int symbolID ) const; - int SymbolToId( const char *pszSymbol ) const; - -private: - CStringRegistry * m_pSymbols; - int m_NextGlobalBase; -}; - -//----------------------------------------------------------------------------- -// CAI_LocalIdSpace -// -// Purpose: Maps per class IDs to global IDs, so that various classes can use -// the same integer in local space to represent different globally -// unique integers. Used for schedules, tasks, conditions and squads -// - -class CAI_LocalIdSpace -{ -public: - CAI_LocalIdSpace( bool fIsRoot = false ); - - bool Init( CAI_GlobalNamespace *pGlobalNamespace, CAI_LocalIdSpace *pParentIDSpace = NULL ); - bool IsGlobalBaseSet() const { return ( m_globalBase != -1 ); } - - bool AddSymbol( const char *pszSymbol, int localId, const char *pszDebugSymbolType = "", const char *pszDebugOwner = "" ); - - int GlobalToLocal( int globalID ) const; - int LocalToGlobal( int localID ) const; - - CAI_GlobalNamespace *GetGlobalNamespace() { return m_pGlobalNamespace; } - const CAI_GlobalNamespace *GetGlobalNamespace() const { return m_pGlobalNamespace; } - -private: - bool IsLocalBaseSet() const { return ( m_localBase != MAX_STRING_INDEX ); } - int GetLocalBase() const { return m_localBase; } - int GetGlobalBase() const { return m_globalBase; } - int GetLocalTop() const { return m_localTop; } - int GetGlobalTop() const { return m_globalTop; } - - bool SetLocalBase( int newBase ); - - // -------------------------------- - - int m_globalBase; - int m_localBase; - int m_localTop; - int m_globalTop; - - CAI_LocalIdSpace * m_pParentIDSpace; - CAI_GlobalNamespace * m_pGlobalNamespace; -}; - -//----------------------------------------------------------------------------- -// -// Namespaces used by CAI_BaseNPC -// -//----------------------------------------------------------------------------- - -class CAI_GlobalScheduleNamespace -{ -public: - void Clear() - { - m_ScheduleNamespace.Clear(); - m_TaskNamespace.Clear(); - m_ConditionNamespace.Clear(); - } - - void AddSchedule( const char *pszSchedule, int scheduleID ); - const char *ScheduleIdToSymbol( int scheduleID ) const; - int ScheduleSymbolToId( const char *pszSchedule ) const; - - void AddTask( const char *pszTask, int taskID ); - const char *TaskIdToSymbol( int taskID ) const; - int TaskSymbolToId( const char *pszTask ) const; - - void AddCondition( const char *pszCondition, int conditionID ); - const char *ConditionIdToSymbol( int conditionID ) const; - int ConditionSymbolToId( const char *pszCondition ) const; - int NumConditions() const; - -private: - friend class CAI_ClassScheduleIdSpace; - - CAI_GlobalNamespace m_ScheduleNamespace; - CAI_GlobalNamespace m_TaskNamespace; - CAI_GlobalNamespace m_ConditionNamespace; -}; - -//------------------------------------- - -class CAI_ClassScheduleIdSpace -{ -public: - CAI_ClassScheduleIdSpace( bool fIsRoot = false ) - : m_ScheduleIds( fIsRoot ), - m_TaskIds( fIsRoot ), - m_ConditionIds( fIsRoot ) - { - } - - bool Init( const char *pszClassName, CAI_GlobalScheduleNamespace *pGlobalNamespace, CAI_ClassScheduleIdSpace *pParentIDSpace = NULL ); - - const char *GetClassName() const { return m_pszClassName; } - - bool IsGlobalBaseSet() const; - - bool AddSchedule( const char *pszSymbol, int localId, const char *pszDebugOwner = "" ); - int ScheduleGlobalToLocal( int globalID ) const; - int ScheduleLocalToGlobal( int localID ) const; - - bool AddTask( const char *pszSymbol, int localId, const char *pszDebugOwner = "" ); - int TaskGlobalToLocal( int globalID ) const; - int TaskLocalToGlobal( int localID ) const; - - bool AddCondition( const char *pszSymbol, int localId, const char *pszDebugOwner = "" ); - int ConditionGlobalToLocal( int globalID ) const; - int ConditionLocalToGlobal( int localID ) const; - -private: - const char * m_pszClassName; - CAI_LocalIdSpace m_ScheduleIds; - CAI_LocalIdSpace m_TaskIds; - CAI_LocalIdSpace m_ConditionIds; -}; - -//----------------------------------------------------------------------------- - -inline void CAI_GlobalScheduleNamespace::AddSchedule( const char *pszSchedule, int scheduleID ) -{ - m_ScheduleNamespace.AddSymbol( pszSchedule, scheduleID); -} - -inline const char *CAI_GlobalScheduleNamespace::ScheduleIdToSymbol( int scheduleID ) const -{ - return m_ScheduleNamespace.IdToSymbol( scheduleID ); -} - -inline int CAI_GlobalScheduleNamespace::ScheduleSymbolToId( const char *pszSchedule ) const -{ - return m_ScheduleNamespace.SymbolToId( pszSchedule ); -} - -inline void CAI_GlobalScheduleNamespace::AddTask( const char *pszTask, int taskID ) -{ - m_TaskNamespace.AddSymbol( pszTask, taskID); -} - -inline const char *CAI_GlobalScheduleNamespace::TaskIdToSymbol( int taskID ) const -{ - return m_TaskNamespace.IdToSymbol( taskID ); -} - -inline int CAI_GlobalScheduleNamespace::TaskSymbolToId( const char *pszTask ) const -{ - return m_TaskNamespace.SymbolToId( pszTask ); -} - -inline void CAI_GlobalScheduleNamespace::AddCondition( const char *pszCondition, int conditionID ) -{ - m_ConditionNamespace.AddSymbol( pszCondition, conditionID); -} - -inline const char *CAI_GlobalScheduleNamespace::ConditionIdToSymbol( int conditionID ) const -{ - return m_ConditionNamespace.IdToSymbol( conditionID ); -} - -inline int CAI_GlobalScheduleNamespace::ConditionSymbolToId( const char *pszCondition ) const -{ - return m_ConditionNamespace.SymbolToId( pszCondition ); -} - -inline int CAI_GlobalScheduleNamespace::NumConditions() const -{ - return m_ConditionNamespace.NextGlobalBase() - GLOBAL_IDS_BASE; -} - -inline bool CAI_ClassScheduleIdSpace::Init( const char *pszClassName, CAI_GlobalScheduleNamespace *pGlobalNamespace, CAI_ClassScheduleIdSpace *pParentIDSpace ) -{ - m_pszClassName = pszClassName; - return ( m_ScheduleIds.Init( &pGlobalNamespace->m_ScheduleNamespace, ( pParentIDSpace ) ? &pParentIDSpace->m_ScheduleIds : NULL ) && - m_TaskIds.Init( &pGlobalNamespace->m_TaskNamespace, ( pParentIDSpace ) ? &pParentIDSpace->m_TaskIds : NULL ) && - m_ConditionIds.Init( &pGlobalNamespace->m_ConditionNamespace, ( pParentIDSpace ) ? &pParentIDSpace->m_ConditionIds : NULL ) ); -} - -//----------------------------------------------------------------------------- - -inline bool CAI_ClassScheduleIdSpace::IsGlobalBaseSet() const -{ - return m_ScheduleIds.IsGlobalBaseSet(); -} - -inline bool CAI_ClassScheduleIdSpace::AddSchedule( const char *pszSymbol, int localId, const char *pszDebugOwner ) -{ - return m_ScheduleIds.AddSymbol( pszSymbol, localId, "schedule", pszDebugOwner ); -} - -inline int CAI_ClassScheduleIdSpace::ScheduleGlobalToLocal( int globalID ) const -{ - return m_ScheduleIds.GlobalToLocal( globalID ); -} - -inline int CAI_ClassScheduleIdSpace::ScheduleLocalToGlobal( int localID ) const -{ - return m_ScheduleIds.LocalToGlobal( localID ); -} - -inline bool CAI_ClassScheduleIdSpace::AddTask( const char *pszSymbol, int localId, const char *pszDebugOwner ) -{ - return m_TaskIds.AddSymbol( pszSymbol, localId, "task", pszDebugOwner ); -} - -inline int CAI_ClassScheduleIdSpace::TaskGlobalToLocal( int globalID ) const -{ - return m_TaskIds.GlobalToLocal( globalID ); -} - -inline int CAI_ClassScheduleIdSpace::TaskLocalToGlobal( int localID ) const -{ - return m_TaskIds.LocalToGlobal( localID ); -} - -inline bool CAI_ClassScheduleIdSpace::AddCondition( const char *pszSymbol, int localId, const char *pszDebugOwner ) -{ - return m_ConditionIds.AddSymbol( pszSymbol, localId, "condition", pszDebugOwner ); -} - -inline int CAI_ClassScheduleIdSpace::ConditionGlobalToLocal( int globalID ) const -{ - return m_ConditionIds.GlobalToLocal( globalID ); -} - -inline int CAI_ClassScheduleIdSpace::ConditionLocalToGlobal( int localID ) const -{ - return m_ConditionIds.LocalToGlobal( localID ); -} - -//============================================================================= - -#endif // AI_NAMESPACES_H diff --git a/game/server/ai_navgoaltype.h b/game/server/ai_navgoaltype.h deleted file mode 100644 index 554f6e381..000000000 --- a/game/server/ai_navgoaltype.h +++ /dev/null @@ -1,35 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_NAVGOALTYPE_H -#define AI_NAVGOALTYPE_H - -#if defined( _WIN32 ) -#pragma once -#endif - -// ======================================= -// Movement goals -// Used both to store the current -// movment goal in m_routeGoalType -// and to or/and with route -// ======================================= -enum GoalType_t -{ - GOALTYPE_NONE, - GOALTYPE_TARGETENT, - GOALTYPE_ENEMY, - GOALTYPE_PATHCORNER, - GOALTYPE_LOCATION, - GOALTYPE_LOCATION_NEAREST_NODE, - GOALTYPE_FLANK, - GOALTYPE_COVER, - - GOALTYPE_INVALID -}; - -#endif // AI_NAVGOALTYPE_H diff --git a/game/server/ai_navigator.cpp b/game/server/ai_navigator.cpp deleted file mode 100644 index 2155a80be..000000000 --- a/game/server/ai_navigator.cpp +++ /dev/null @@ -1,4168 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// @TODO (toml 06-26-02): The entry points in this file need to be organized -//=============================================================================// - -#include "cbase.h" - -#include // for FLT_MAX - -#include "animation.h" // for NOMOTION -#include "collisionutils.h" -#include "ndebugoverlay.h" -#include "isaverestore.h" -#include "saverestore_utlvector.h" - -#include "ai_navigator.h" -#include "ai_node.h" -#include "ai_route.h" -#include "ai_routedist.h" -#include "ai_waypoint.h" -#include "ai_pathfinder.h" -#include "ai_link.h" -#include "ai_memory.h" -#include "ai_motor.h" -#include "ai_localnavigator.h" -#include "ai_moveprobe.h" -#include "ai_hint.h" -#include "BasePropDoor.h" -#include "props.h" -#include "physics_npc_solver.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -const char * g_ppszGoalTypes[] = -{ - "GOALTYPE_NONE", - "GOALTYPE_TARGETENT", - "GOALTYPE_ENEMY", - "GOALTYPE_PATHCORNER", - "GOALTYPE_LOCATION", - "GOALTYPE_LOCATION_NEAREST_NODE", - "GOALTYPE_FLANK", - "GOALTYPE_COVER", -}; - -#define AIGetGoalTypeText(type) (g_ppszGoalTypes[(type)]) - -ConVar ai_vehicle_avoidance("ai_vehicle_avoidance", "1", FCVAR_CHEAT ); - -#ifdef DEBUG_AI_NAVIGATION -ConVar ai_debug_nav("ai_debug_nav", "0"); -#endif - -#ifdef DEBUG -ConVar ai_test_nav_failure_handling("ai_test_nav_failure_handling", "0"); -int g_PathFailureCounter; -int g_MoveFailureCounter; -#define ShouldTestFailPath() ( ai_test_nav_failure_handling.GetBool() && g_PathFailureCounter++ % 20 == 0 ) -#define ShouldTestFailMove() ( ai_test_nav_failure_handling.GetBool() && g_MoveFailureCounter++ % 100 == 0 ) -#else -#define ShouldTestFailPath() (0) -#define ShouldTestFailMove() (0) -#endif - -//----------------------------------------------------------------------------- - -#ifdef DEBUG -bool g_fTestSteering = 0; -#endif - -//----------------------------------------------------------------------------- - -class CAI_NavInHintGroupFilter : public INearestNodeFilter -{ -public: - CAI_NavInHintGroupFilter( string_t iszGroup = NULL_STRING ) : - m_iszGroup( iszGroup ) - { - } - - bool IsValid( CAI_Node *pNode ) - { - if ( !pNode->GetHint() ) - { - return false; - } - - if ( pNode->GetHint()->GetGroup() != m_iszGroup ) - { - return false; - } - - return true; - } - - bool ShouldContinue() - { - return true; - } - - string_t m_iszGroup; - -}; - -//----------------------------------------------------------------------------- - -const Vector AIN_NO_DEST( FLT_MAX, FLT_MAX, FLT_MAX ); -#define NavVecToString(v) ((v == AIN_NO_DEST) ? "AIN_NO_DEST" : VecToString(v)) - -#define FLIER_CUT_CORNER_DIST 16 // 8 means the npc's bounding box is contained without the box of the node in WC - -#define NAV_STOP_MOVING_TOLERANCE 6 // Goal tolerance for TASK_STOP_MOVING stopping paths - -//----------------------------------------------------------------------------- -// class CAI_Navigator -//----------------------------------------------------------------------------- - -BEGIN_SIMPLE_DATADESC( CAI_Navigator ) - - DEFINE_FIELD( m_navType, FIELD_INTEGER ), - // m_pMotor - // m_pMoveProbe - // m_pLocalNavigator - // m_pAINetwork - DEFINE_EMBEDDEDBYREF( m_pPath ), - // m_pClippedWaypoints (not saved) - // m_flTimeClipped (not saved) - // m_PreviousMoveActivity (not saved) - // m_PreviousArrivalActivity (not saved) - DEFINE_FIELD( m_bValidateActivitySpeed, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bCalledStartMove, FIELD_BOOLEAN ), - DEFINE_FIELD( m_fNavComplete, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bNotOnNetwork, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bLastNavFailed, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flNextSimplifyTime, FIELD_TIME ), - DEFINE_FIELD( m_bForcedSimplify, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flLastSuccessfulSimplifyTime, FIELD_TIME ), - DEFINE_FIELD( m_flTimeLastAvoidanceTriangulate, FIELD_TIME ), - DEFINE_FIELD( m_timePathRebuildMax, FIELD_FLOAT ), - DEFINE_FIELD( m_timePathRebuildDelay, FIELD_FLOAT ), - DEFINE_FIELD( m_timePathRebuildFail, FIELD_TIME ), - DEFINE_FIELD( m_timePathRebuildNext, FIELD_TIME ), - DEFINE_FIELD( m_fRememberStaleNodes, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bNoPathcornerPathfinds, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bLocalSucceedOnWithinTolerance, FIELD_BOOLEAN ), - // m_fPeerMoveWait (think transient) - // m_hPeerWaitingOn (peer move fields do not need to be saved, tied to current schedule and path, which are not saved) - // m_PeerWaitMoveTimer (ibid) - // m_PeerWaitClearTimer(ibid) - // m_NextSidestepTimer (ibid) - DEFINE_FIELD( m_hBigStepGroundEnt, FIELD_EHANDLE ), - DEFINE_FIELD( m_hLastBlockingEnt, FIELD_EHANDLE ), - // m_vPosBeginFailedSteer (reset on load) - // m_timeBeginFailedSteer (reset on load) - // m_nNavFailCounter (reset on load) - // m_flLastNavFailTime (reset on load) - -END_DATADESC() - - -//----------------------------------------------------------------------------- - -CAI_Navigator::CAI_Navigator(CAI_BaseNPC *pOuter) - : BaseClass(pOuter) -{ - m_pPath = new CAI_Path; - m_pAINetwork = NULL; - m_bNotOnNetwork = false; - m_flNextSimplifyTime = 0; - - m_flLastSuccessfulSimplifyTime = -1; - - m_pClippedWaypoints = new CAI_WaypointList; - m_flTimeClipped = -1; - - m_bValidateActivitySpeed = true; - m_bCalledStartMove = false; - - // ---------------------------- - - m_navType = NAV_GROUND; - m_fNavComplete = false; - m_bLastNavFailed = false; - - // ---------------------------- - - m_PeerWaitMoveTimer.Set(0.25); // 2 thinks - m_PeerWaitClearTimer.Set(3.0); - m_NextSidestepTimer.Set(5.0); - - m_vPosBeginFailedSteer = vec3_invalid; - m_timeBeginFailedSteer = FLT_MAX; - - m_flTimeLastAvoidanceTriangulate = -1; - - // ---------------------------- - - m_bNoPathcornerPathfinds = false; - m_bLocalSucceedOnWithinTolerance = false; - - m_fRememberStaleNodes = true; - - m_pMotor = NULL; - m_pMoveProbe = NULL; - m_pLocalNavigator = NULL; - - - m_nNavFailCounter = 0; - m_flLastNavFailTime = -1; -} - -//----------------------------------------------------------------------------- - -void CAI_Navigator::Init( CAI_Network *pNetwork ) -{ - m_pMotor = GetOuter()->GetMotor(); - m_pMoveProbe = GetOuter()->GetMoveProbe(); - m_pLocalNavigator = GetOuter()->GetLocalNavigator(); - m_pAINetwork = pNetwork; - -} - -//----------------------------------------------------------------------------- - -CAI_Navigator::~CAI_Navigator() -{ - delete m_pPath; - m_pClippedWaypoints->RemoveAll(); - delete m_pClippedWaypoints; -} - -//----------------------------------------------------------------------------- - -const short AI_NAVIGATOR_SAVE_VERSION = 1; - -void CAI_Navigator::Save( ISave &save ) -{ - save.WriteShort( &AI_NAVIGATOR_SAVE_VERSION ); - - CUtlVector minPathArray; - - AI_Waypoint_t *pCurWaypoint = GetPath()->GetCurWaypoint(); - if ( pCurWaypoint ) - { - if ( ( pCurWaypoint->NavType() == NAV_CLIMB || pCurWaypoint->NavType() == NAV_JUMP ) ) - { - CAI_WaypointList minCompletionPath; - if ( GetStoppingPath( &minCompletionPath ) && !minCompletionPath.IsEmpty() ) - { - AI_Waypoint_t *pCurrent = minCompletionPath.GetLast(); - while ( pCurrent ) - { - minPathArray.AddToTail( *pCurrent ); - pCurrent = pCurrent->GetPrev(); - } - minCompletionPath.RemoveAll(); - } - } - } - - SaveUtlVector( &save, &minPathArray, FIELD_EMBEDDED ); -} - -//----------------------------------------------------------------------------- - -void CAI_Navigator::Restore( IRestore &restore ) -{ - short version = restore.ReadShort(); - - if ( version != AI_NAVIGATOR_SAVE_VERSION ) - return; - - CUtlVector minPathArray; - RestoreUtlVector( &restore, &minPathArray, FIELD_EMBEDDED ); - - if ( minPathArray.Count() ) - { - for ( int i = 0; i < minPathArray.Count(); i++ ) - { - m_pClippedWaypoints->PrependWaypoint( minPathArray[i].GetPos(), minPathArray[i].NavType(), ( minPathArray[i].Flags() & ~bits_WP_TO_PATHCORNER ), minPathArray[i].flYaw ); - } - m_flTimeClipped = gpGlobals->curtime + 1000; // time passes between restore and onrestore - } - -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::ActivityIsLocomotive( Activity activity ) -{ - // FIXME: should be calling HasMovement() for a sequence - return ( activity > ACT_IDLE ); -} - -//----------------------------------------------------------------------------- - -CAI_Pathfinder *CAI_Navigator::GetPathfinder() -{ - return GetOuter()->GetPathfinder(); -} - -//----------------------------------------------------------------------------- - -const CAI_Pathfinder *CAI_Navigator::GetPathfinder() const -{ - return GetOuter()->GetPathfinder(); -} - -//----------------------------------------------------------------------------- - -CBaseEntity *CAI_Navigator::GetNavTargetEntity() -{ - if ( GetGoalType() == GOALTYPE_ENEMY || GetGoalType() == GOALTYPE_TARGETENT ) - return GetOuter()->GetNavTargetEntity(); - return GetPath()->GetTarget(); -} - -//----------------------------------------------------------------------------- - -void CAI_Navigator::TaskMovementComplete() -{ - GetOuter()->TaskMovementComplete(); -} - -//----------------------------------------------------------------------------- - -float CAI_Navigator::MaxYawSpeed() -{ - return GetOuter()->MaxYawSpeed(); -} - -//----------------------------------------------------------------------------- - -void CAI_Navigator::SetSpeed( float fl ) -{ - GetOuter()->m_flSpeed = fl; -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::FindPath( const AI_NavGoal_t &goal, unsigned flags ) -{ - CAI_Path *pPath = GetPath(); - - MARK_TASK_EXPENSIVE(); - - // Clear out previous state - if ( flags & AIN_CLEAR_PREVIOUS_STATE ) - pPath->Clear(); - else if ( flags & AIN_CLEAR_TARGET ) - pPath->ClearTarget(); - - // Set the activity - if ( goal.activity != AIN_DEF_ACTIVITY ) - pPath->SetMovementActivity( goal.activity ); - else if ( pPath->GetMovementActivity() == ACT_INVALID ) - pPath->SetMovementActivity( ( GetOuter()->GetState() == NPC_STATE_COMBAT ) ? ACT_RUN : ACT_WALK ); - - // Set the tolerance - if ( goal.tolerance == AIN_HULL_TOLERANCE ) - pPath->SetGoalTolerance( GetHullWidth() ); - else if ( goal.tolerance != AIN_DEF_TOLERANCE ) - pPath->SetGoalTolerance( goal.tolerance ); - else if (pPath->GetGoalTolerance() == 0 ) - pPath->SetGoalTolerance( GetOuter()->GetDefaultNavGoalTolerance() ); - - if (pPath->GetGoalTolerance() < 0.1 ) - DevMsg( GetOuter(), "Suspicious navigation goal tolerance specified\n"); - - pPath->SetWaypointTolerance( GetHullWidth() * 0.5 ); - - pPath->SetGoalType( GOALTYPE_NONE ); // avoids a spurious warning about setting the goal type twice - pPath->SetGoalType( goal.type ); - pPath->SetGoalFlags( goal.flags ); - - CBaseEntity *pPathTarget = goal.pTarget; - if ((goal.type == GOALTYPE_TARGETENT) || (goal.type == GOALTYPE_ENEMY)) - { - // Guarantee that the path target - if (goal.type == GOALTYPE_TARGETENT) - pPathTarget = GetTarget(); - else - pPathTarget = GetEnemy(); - - Assert( goal.pTarget == AIN_DEF_TARGET || goal.pTarget == pPathTarget ); - - // Set the goal offset - if ( goal.dest != AIN_NO_DEST ) - pPath->SetTargetOffset( goal.dest ); - - // We're not setting the goal position here because - // it's going to be computed + set in DoFindPath. - } - else - { - // When our goaltype is position based, we have to set - // the goal position here because it won't get set during DoFindPath(). - if ( goal.dest != AIN_NO_DEST ) - pPath->ResetGoalPosition( goal.dest ); - else if ( goal.destNode != AIN_NO_NODE ) - pPath->ResetGoalPosition( GetNodePos( goal.destNode ) ); - } - - if ( pPathTarget > AIN_DEF_TARGET ) - { - pPath->SetTarget( pPathTarget ); - } - - pPath->ClearWaypoints(); - bool result = FindPath( ( flags & AIN_NO_PATH_TASK_FAIL ) == 0 ); - - if ( result == false ) - { - if ( flags & AIN_DISCARD_IF_FAIL ) - pPath->Clear(); - else - pPath->SetGoalType( GOALTYPE_NONE ); - } - else - { - if ( goal.arrivalActivity != AIN_DEF_ACTIVITY && goal.arrivalActivity > ACT_RESET ) - { - pPath->SetArrivalActivity( goal.arrivalActivity ); - } - else if ( goal.arrivalSequence != -1 ) - { - pPath->SetArrivalSequence( goal.arrivalSequence ); - } - - // Initialize goal facing direction - // FIXME: This is a poor way to initialize the arrival direction, apps calling SetGoal() - // should do this themselves, and/or it should be part of AI_NavGoal_t - // FIXME: A number of calls to SetGoal() building routes to their enemy but don't set the flags! - if (goal.type == GOALTYPE_ENEMY) - { - pPath->SetGoalDirection( pPathTarget ); - pPath->SetGoalSpeed( pPathTarget ); - } - else - { - pPath->SetGoalDirection( pPath->ActualGoalPosition() - GetAbsOrigin() ); - } - } - - return result; -} - -ConVar ai_navigator_generate_spikes( "ai_navigator_generate_spikes", "0" ); -ConVar ai_navigator_generate_spikes_strength( "ai_navigator_generate_spikes_strength", "8" ); - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::SetGoal( const AI_NavGoal_t &goal, unsigned flags ) -{ - // Queue this up if we're in the middle of a frame - if ( PostFrameNavigationSystem()->IsGameFrameRunning() ) - { - // Send off the query for queuing - PostFrameNavigationSystem()->EnqueueEntityNavigationQuery( GetOuter(), CreateFunctor( this, &CAI_Navigator::SetGoal, RefToVal( goal ), flags ) ); - - // Complete immediately if we're waiting on that - // FIXME: This will probably cause a lot of subtle little nuisances... - if ( ( flags & AIN_NO_PATH_TASK_FAIL ) == 0 || GetOuter()->IsCurTaskContinuousMove() ) - { - TaskComplete(); - } - - // For now, always succeed -- we need to deal with failures on the next frame - return true; - } - - CAI_Path *pPath = GetPath(); - - OnNewGoal(); - - // Clear out previous state - if ( flags & AIN_CLEAR_PREVIOUS_STATE ) - ClearPath(); - - if ( GetOuter()->IsCurTaskContinuousMove() || ai_post_frame_navigation.GetBool() ) - flags |= AIN_NO_PATH_TASK_FAIL; - - bool result = FindPath( goal, flags ); - - if ( result == false ) - { - DbgNavMsg( GetOuter(), "Failed to pathfind to nav goal:\n" ); - DbgNavMsg1( GetOuter(), " Type: %s\n", AIGetGoalTypeText( goal.type) ); - DbgNavMsg1( GetOuter(), " Dest: %s\n", NavVecToString( goal.dest ) ); - DbgNavMsg1( GetOuter(), " Dest node: %d\n", goal.destNode ); - DbgNavMsg1( GetOuter(), " Target: %#x\n", goal.pTarget ); - - if ( flags & AIN_DISCARD_IF_FAIL ) - ClearPath(); - } - else - { - DbgNavMsg( GetOuter(), "New goal set:\n" ); - DbgNavMsg1( GetOuter(), " Type: %s\n", AIGetGoalTypeText( goal.type) ); - DbgNavMsg1( GetOuter(), " Dest: %s\n", NavVecToString( goal.dest ) ); - DbgNavMsg1( GetOuter(), " Dest node: %d\n", goal.destNode ); - DbgNavMsg1( GetOuter(), " Target: %#x\n", goal.pTarget ); - DbgNavMsg1( GetOuter(), " Tolerance: %.1f\n", GetPath()->GetGoalTolerance() ); - DbgNavMsg1( GetOuter(), " Waypoint tol: %.1f\n", GetPath()->GetWaypointTolerance() ); - DbgNavMsg1( GetOuter(), " Activity: %s\n", GetOuter()->GetActivityName(GetPath()->GetMovementActivity()) ); - DbgNavMsg1( GetOuter(), " Arrival act: %s\n", GetOuter()->GetActivityName(GetPath()->GetArrivalActivity()) ); - DbgNavMsg1( GetOuter(), " Arrival seq: %d\n", GetPath()->GetArrivalSequence() ); - DbgNavMsg1( GetOuter(), " Goal dir: %s\n", NavVecToString( GetPath()->GetGoalDirection(GetAbsOrigin())) ); - - // Set our ideal yaw. This has to be done *after* finding the path, - // because the goal position may not be set until then - if ( goal.flags & AIN_YAW_TO_DEST ) - { - DbgNavMsg( GetOuter(), " Yaw to dest\n" ); - GetMotor()->SetIdealYawToTarget( pPath->ActualGoalPosition() ); - } - - SimplifyPath( true, goal.maxInitialSimplificationDist ); - } - - return result; -} - - -//----------------------------------------------------------------------------- -// Change the target of the path -//----------------------------------------------------------------------------- -bool CAI_Navigator::SetGoalTarget( CBaseEntity *pEntity, const Vector &offset ) -{ - OnNewGoal(); - CAI_Path *pPath = GetPath(); - pPath->SetTargetOffset( offset ); - pPath->SetTarget( pEntity ); - pPath->ClearWaypoints(); - return FindPath( !GetOuter()->IsCurTaskContinuousMove() ); -} - - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::SetRadialGoal( const Vector &destination, const Vector ¢er, float radius, float arc, float stepDist, bool bClockwise, bool bAirRoute) -{ - DbgNavMsg( GetOuter(), "Set radial goal\n" ); - OnNewGoal(); - GetPath()->SetGoalType(GOALTYPE_LOCATION); - - GetPath()->SetWaypoints( GetPathfinder()->BuildRadialRoute( GetLocalOrigin(), center, destination, radius, arc, stepDist, bClockwise, GetPath()->GetGoalTolerance(), bAirRoute ), true); - GetPath()->SetGoalTolerance( GetOuter()->GetDefaultNavGoalTolerance() ); - - return IsGoalActive(); -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::SetRandomGoal( const Vector &from, float minPathLength, const Vector &dir ) -{ - DbgNavMsg( GetOuter(), "Set random goal\n" ); - OnNewGoal(); - if ( GetNetwork()->NumNodes() <= 0 ) - return false; - - INearestNodeFilter *pFilter = NULL; - CAI_NavInHintGroupFilter filter; - if ( GetOuter()->GetHintGroup() != NULL_STRING ) - { - filter.m_iszGroup = GetOuter()->GetHintGroup(); - pFilter = &filter; - } - - int fromNodeID = GetNetwork()->NearestNodeToPoint( GetOuter(), from, true, pFilter ); - - if (fromNodeID == NO_NODE) - return false; - - AI_Waypoint_t* pRoute = GetPathfinder()->FindShortRandomPath( fromNodeID, minPathLength, dir ); - - if (!pRoute) - return false; - - GetPath()->SetGoalType(GOALTYPE_LOCATION); - GetPath()->SetWaypoints(pRoute); - GetPath()->SetLastNodeAsGoal(); - GetPath()->SetGoalTolerance( GetOuter()->GetDefaultNavGoalTolerance() ); - - SimplifyPath( true ); - - return true; -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::SetDirectGoal( const Vector &goalPos, Navigation_t navType ) -{ - DbgNavMsg( GetOuter(), "Set direct goal\n" ); - OnNewGoal(); - ClearPath(); - GetPath()->SetGoalType( GOALTYPE_LOCATION ); - GetPath()->SetWaypoints( new AI_Waypoint_t( goalPos, 0, navType, bits_WP_TO_GOAL, NO_NODE ) ); - GetPath()->SetGoalTolerance( GetOuter()->GetDefaultNavGoalTolerance() ); - GetPath()->SetGoalPosition( goalPos ); - return true; -} - -//----------------------------------------------------------------------------- -// Placeholder implementation for wander goals: cast a few random vectors and -// accept the first one that still lies on the navmesh. -// Side effect: vector goal of navigator is set. -// Returns: true on goal set, false otherwise. -static bool SetWanderGoalByRandomVector(CAI_Navigator *pNav, float minRadius, float maxRadius, int numTries) -{ - while (--numTries >= 0) - { - float dist = random->RandomFloat( minRadius, maxRadius ); - Vector dir = UTIL_YawToVector( random->RandomFloat( 0, 359.99 ) ); - - if ( pNav->SetVectorGoal( dir, dist, minRadius ) ) - return true; - } - - return false; -} - -bool CAI_Navigator::SetWanderGoal( float minRadius, float maxRadius ) -{ - // @Note (toml 11-07-02): this is a bogus placeholder implementation!!! - // - // First try using a random setvector goal, and then try SetRandomGoal(). - // Except, if we have a hint group, first try SetRandomGoal() (which - // respects hint groups) and then fall back on the setvector. - if( !GetOuter()->GetHintGroup() ) - { - return ( SetWanderGoalByRandomVector( this, minRadius, maxRadius, 5 ) || - SetRandomGoal( 1 ) ); - } - else - { - return ( SetRandomGoal(1) || - SetWanderGoalByRandomVector( this, minRadius, maxRadius, 5 ) ); - } -} - - -//----------------------------------------------------------------------------- - -void CAI_Navigator::CalculateDeflection( const Vector &start, const Vector &dir, const Vector &normal, Vector *pResult ) -{ - Vector temp; - CrossProduct( dir, normal, temp ); - CrossProduct( normal, temp, *pResult ); - VectorNormalize( *pResult ); -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::SetVectorGoal( const Vector &dir, float targetDist, float minDist, bool fShouldDeflect ) -{ - DbgNavMsg( GetOuter(), "Set vector goal\n" ); - - Vector result; - - if ( FindVectorGoal( &result, dir, targetDist, minDist, fShouldDeflect ) ) - return SetGoal( result ); - - return false; -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::SetVectorGoalFromTarget( const Vector &goalPos, float minDist, bool fShouldDeflect ) -{ - Vector vDir = goalPos; - float dist = ComputePathDirection( GetNavType(), GetLocalOrigin(), goalPos, &vDir ); - return SetVectorGoal( vDir, dist, minDist, fShouldDeflect ); -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::FindVectorGoal( Vector *pResult, const Vector &dir, float targetDist, float minDist, bool fShouldDeflect ) -{ - AIMoveTrace_t moveTrace; - float distAchieved = 0; - - MARK_TASK_EXPENSIVE(); - - Vector testLoc = GetLocalOrigin() + ( dir * targetDist ); - GetMoveProbe()->MoveLimit( GetNavType(), GetLocalOrigin(), testLoc, MASK_NPCSOLID, NULL, &moveTrace ); - - if ( moveTrace.fStatus != AIMR_OK ) - { - distAchieved = targetDist - moveTrace.flDistObstructed; - if ( fShouldDeflect && moveTrace.vHitNormal != vec3_origin ) - { - Vector vecDeflect; - Vector vecNormal = moveTrace.vHitNormal; - if ( GetNavType() == NAV_GROUND ) - vecNormal.z = 0; - - CalculateDeflection( moveTrace.vEndPosition, dir, vecNormal, &vecDeflect ); - - testLoc = moveTrace.vEndPosition + ( vecDeflect * ( targetDist - distAchieved ) ); - - Vector temp = moveTrace.vEndPosition; - GetMoveProbe()->MoveLimit( GetNavType(), temp, testLoc, MASK_NPCSOLID, NULL, &moveTrace ); - - distAchieved += ( targetDist - distAchieved ) - moveTrace.flDistObstructed; - } - - if ( distAchieved < minDist + 0.01 ) - return false; - } - - *pResult = moveTrace.vEndPosition; - return true; -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::SetRandomGoal( float minPathLength, const Vector &dir ) -{ - return SetRandomGoal( GetLocalOrigin(), minPathLength, dir ); -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::PrependLocalAvoidance( float distObstacle, const AIMoveTrace_t &directTrace ) -{ - if ( AIStrongOpt() ) - return false; - - if ( GetOuter()->IsFlaggedEfficient() ) - return false; - - if ( m_flTimeLastAvoidanceTriangulate >= gpGlobals->curtime ) - return false; // Only triangulate once per think at most - - m_flTimeLastAvoidanceTriangulate = gpGlobals->curtime; - - AI_PROFILE_SCOPE(CAI_Navigator_PrependLocalAvoidance); - - AI_Waypoint_t *pAvoidanceRoute = NULL; - - Vector vStart = GetLocalOrigin(); - - if ( distObstacle < GetHullWidth() * 0.5 ) - { - AIMoveTrace_t backawayTrace; - Vector vTestBackaway = GetCurWaypointPos() - GetLocalOrigin(); - VectorNormalize( vTestBackaway ); - vTestBackaway *= -GetHullWidth(); - vTestBackaway += GetLocalOrigin(); - - int flags = ( GetNavType() == NAV_GROUND ) ? AIMLF_2D : AIMLF_DEFAULT; - - if ( GetMoveProbe()->MoveLimit( GetNavType(), GetLocalOrigin(), vTestBackaway, - MASK_NPCSOLID, GetNavTargetEntity(), - 100.0, - flags, &backawayTrace ) ) - { - vStart = backawayTrace.vEndPosition; - pAvoidanceRoute = new AI_Waypoint_t( vStart, 0, GetNavType(), bits_WP_TO_DETOUR, NO_NODE ); - } - } - - AI_Waypoint_t *pTriangulation = GetPathfinder()->BuildTriangulationRoute( - vStart, - GetCurWaypointPos(), - GetNavTargetEntity(), - bits_WP_TO_DETOUR, - NO_NODE, - 0.0, - distObstacle, - GetNavType() ); - - if ( !pTriangulation ) - { - delete pAvoidanceRoute; - return false; - } - - if ( pAvoidanceRoute ) - pAvoidanceRoute->SetNext( pTriangulation ); - else - pAvoidanceRoute = pTriangulation; - - // @TODO (toml 02-04-04): it would be better to do this on each triangulation test to - // improve the odds of success. however, difficult in current structure - float moveThisInterval = GetMotor()->CalcIntervalMove(); - Vector dir = pAvoidanceRoute->GetPos() - GetLocalOrigin(); - float dist = VectorNormalize( dir ); - Vector testPos; - if ( dist > moveThisInterval ) - { - dist = moveThisInterval; - testPos = GetLocalOrigin() + dir * dist; - } - else - { - testPos = pAvoidanceRoute->GetPos(); - } - - int flags = ( GetNavType() == NAV_GROUND ) ? AIMLF_2D : AIMLF_DEFAULT; - - if ( !GetMoveProbe()->MoveLimit( GetNavType(), GetLocalOrigin(), testPos, - MASK_NPCSOLID, GetNavTargetEntity(), - 100.0, - flags ) ) - { - DeleteAll( pAvoidanceRoute ); - return false; - } - - // FIXME: should the route get simplified? - DbgNavMsg( GetOuter(), "Adding triangulation\n" ); - GetPath()->PrependWaypoints( pAvoidanceRoute ); - return true; -} - -//----------------------------------------------------------------------------- - -void CAI_Navigator::PrependWaypoint( const Vector &newPoint, Navigation_t navType, unsigned waypointFlags ) -{ - GetPath()->PrependWaypoint( newPoint, navType, waypointFlags ); -} - -//----------------------------------------------------------------------------- - -const Vector &CAI_Navigator::GetGoalPos() const -{ - return GetPath()->BaseGoalPosition(); -} - -//----------------------------------------------------------------------------- - -CBaseEntity *CAI_Navigator::GetGoalTarget() -{ - return GetPath()->GetTarget(); -} - -//----------------------------------------------------------------------------- - -float CAI_Navigator::GetGoalTolerance() const -{ - return GetPath()->GetGoalTolerance(); -} - -//----------------------------------------------------------------------------- - -void CAI_Navigator::SetGoalTolerance(float tolerance) -{ - GetPath()->SetGoalTolerance(tolerance); -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::RefindPathToGoal( bool fSignalTaskStatus, bool bDontIgnoreBadLinks ) -{ - return FindPath( fSignalTaskStatus, bDontIgnoreBadLinks ); -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::UpdateGoalPos( const Vector &goalPos ) -{ - // Queue this up if we're in the middle of a frame - if ( PostFrameNavigationSystem()->IsGameFrameRunning() ) - { - // Send off the query for queuing - PostFrameNavigationSystem()->EnqueueEntityNavigationQuery( GetOuter(), CreateFunctor( this, &CAI_Navigator::UpdateGoalPos, RefToVal( goalPos ) ) ); - - // For now, always succeed -- we need to deal with failures on the next frame - return true; - } - - DbgNavMsg( GetOuter(), "Updating goal pos\n" ); - - if ( GetNavType() == NAV_JUMP ) - { - DevMsg( "Updating goal pos while jumping!\n" ); - AssertOnce( 0 ); - return false; - } - - // FindPath should be finding the goal position if the goal type is - // one of these two... We could just ignore the suggested position - // in these two cases I suppose! - Assert( (GetPath()->GoalType() != GOALTYPE_ENEMY) && (GetPath()->GoalType() != GOALTYPE_TARGETENT) ); - - GetPath()->ResetGoalPosition( goalPos ); - if ( FindPath( !GetOuter()->IsCurTaskContinuousMove() ) ) - { - SimplifyPath( true ); - return true; - } - return false; -} - -//----------------------------------------------------------------------------- - -Activity CAI_Navigator::SetMovementActivity(Activity activity) -{ - return GetPath()->SetMovementActivity( activity ); -} - -//----------------------------------------------------------------------------- - -void CAI_Navigator::StopMoving( bool bImmediate ) -{ - DbgNavMsg1( GetOuter(), "CAI_Navigator::StopMoving( %d )\n", bImmediate ); - if ( IsGoalSet() ) - { - if ( bImmediate || !SetGoalFromStoppingPath() ) - { - OnNavComplete(); - } - } - else - ClearGoal(); -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::ClearGoal() -{ - DbgNavMsg( GetOuter(), "CAI_Navigator::ClearGoal()\n" ); - ClearPath(); - OnNewGoal(); - return true; -} - -//----------------------------------------------------------------------------- - -int CAI_Navigator::GetMovementSequence( ) -{ - int sequence = GetPath()->GetMovementSequence( ); - if (sequence == ACT_INVALID) - { - Activity activity = GetPath()->GetMovementActivity(); - Assert( activity != ACT_INVALID ); - - sequence = GetOuter()->SelectWeightedSequence( GetOuter()->TranslateActivity( activity ) ); - if ( sequence == ACT_INVALID ) - { - DevMsg( GetOuter(), "No appropriate sequence for movement activity %s (%d)\n", GetOuter()->GetActivityName( GetPath()->GetArrivalActivity() ), GetPath()->GetArrivalActivity() ); - - if ( activity == ACT_SCRIPT_CUSTOM_MOVE ) - { - sequence = GetOuter()->GetScriptCustomMoveSequence(); - } - else - { - sequence = GetOuter()->SelectWeightedSequence( GetOuter()->TranslateActivity( ACT_WALK ) ); - } - } - Assert( sequence != ACT_INVALID ); - GetPath()->SetMovementSequence( sequence ); - } - return sequence; -} - -//----------------------------------------------------------------------------- - -void CAI_Navigator::SetMovementSequence( int sequence ) -{ - GetPath()->SetMovementSequence( sequence ); -} - -//----------------------------------------------------------------------------- - -Activity CAI_Navigator::GetMovementActivity() const -{ - return GetPath()->GetMovementActivity(); -} - -//----------------------------------------------------------------------------- - -void CAI_Navigator::SetArrivalActivity(Activity activity) -{ - GetPath()->SetArrivalActivity(activity); -} - - -//----------------------------------------------------------------------------- - -int CAI_Navigator::GetArrivalSequence( int curSequence ) -{ - int sequence = GetPath()->GetArrivalSequence( ); - if (sequence == ACT_INVALID) - { - Activity activity = GetOuter()->GetStoppedActivity(); - - Assert( activity != ACT_INVALID ); - if (activity == ACT_INVALID) - { - activity = ACT_IDLE; - } - - sequence = GetOuter()->SelectWeightedSequence( GetOuter()->TranslateActivity( activity ), curSequence ); - - if ( sequence == ACT_INVALID ) - { - DevMsg( GetOuter(), "No appropriate sequence for arrival activity %s (%d)\n", GetOuter()->GetActivityName( GetPath()->GetArrivalActivity() ), GetPath()->GetArrivalActivity() ); - sequence = GetOuter()->SelectWeightedSequence( GetOuter()->TranslateActivity( ACT_IDLE ), curSequence ); - } - Assert( sequence != ACT_INVALID ); - GetPath()->SetArrivalSequence( sequence ); - } - return sequence; -} - -//----------------------------------------------------------------------------- - -void CAI_Navigator::SetArrivalSequence( int sequence ) -{ - GetPath()->SetArrivalActivity( ACT_INVALID ); - GetPath()->SetArrivalSequence( sequence ); -} - -//----------------------------------------------------------------------------- - -Activity CAI_Navigator::GetArrivalActivity( ) const -{ - return GetPath()->GetArrivalActivity( ); -} - -//----------------------------------------------------------------------------- - -void CAI_Navigator::SetArrivalDirection( const Vector &goalDirection ) -{ - GetPath()->SetGoalDirection( goalDirection ); -} - -//----------------------------------------------------------------------------- - -void CAI_Navigator::SetArrivalDirection( const QAngle &goalAngle ) -{ - Vector goalDirection; - - AngleVectors( goalAngle, &goalDirection ); - - GetPath()->SetGoalDirection( goalDirection ); -} - -//----------------------------------------------------------------------------- - -void CAI_Navigator::SetArrivalDirection( CBaseEntity * pTarget ) -{ - GetPath()->SetGoalDirection( pTarget ); -} - -//----------------------------------------------------------------------------- - -Vector CAI_Navigator::GetArrivalDirection( ) -{ - return GetPath()->GetGoalDirection( GetAbsOrigin() ); -} - - -//----------------------------------------------------------------------------- - -void CAI_Navigator::SetArrivalSpeed( float flSpeed ) -{ - GetPath()->SetGoalSpeed( flSpeed ); -} - -//----------------------------------------------------------------------------- - -float CAI_Navigator::GetArrivalSpeed( void ) -{ - float flSpeed = GetPath()->GetGoalSpeed( GetAbsOrigin() ); - - if (flSpeed >= 0.0) - { - return flSpeed; - } - - int sequence = GetArrivalSequence( ACT_INVALID ); - - if (sequence != ACT_INVALID) - { - flSpeed = GetOuter()->GetEntryVelocity( sequence ); - SetArrivalSpeed( flSpeed ); - } - else - { - flSpeed = 0.0; - } - - return flSpeed; -} - - -//----------------------------------------------------------------------------- - -void CAI_Navigator::SetArrivalDistance( float flDistance ) -{ - GetPath()->SetGoalStoppingDistance( flDistance ); -} - -//----------------------------------------------------------------------------- - -float CAI_Navigator::GetArrivalDistance() const -{ - return GetPath()->GetGoalStoppingDistance(); -} - -//----------------------------------------------------------------------------- - -const Vector &CAI_Navigator::GetCurWaypointPos() const -{ - return GetPath()->CurWaypointPos(); -} - -//----------------------------------------------------------------------------- - -int CAI_Navigator::GetCurWaypointFlags() const -{ - return GetPath()->CurWaypointFlags(); -} - -//----------------------------------------------------------------------------- - -GoalType_t CAI_Navigator::GetGoalType() const -{ - return GetPath()->GoalType(); -} - -//----------------------------------------------------------------------------- - -int CAI_Navigator::GetGoalFlags() const -{ - return GetPath()->GoalFlags(); -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::CurWaypointIsGoal() const -{ - return GetPath()->CurWaypointIsGoal(); -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::IsGoalSet() const -{ - return ( GetPath()->GoalType() != GOALTYPE_NONE ); -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::IsGoalActive() const -{ - return ( GetPath() && !( const_cast(GetPath())->IsEmpty() ) ); -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::GetPointAlongPath( Vector *pResult, float distance, bool fReducibleOnly ) -{ - if ( !GetPath()->GetCurWaypoint() ) - return false; - - AI_Waypoint_t *pCurWaypoint = GetPath()->GetCurWaypoint(); - AI_Waypoint_t *pEndPoint = pCurWaypoint; - float distRemaining = distance; - float distToNext; - Vector vPosPrev = GetLocalOrigin(); - - while ( pEndPoint->GetNext() ) - { - distToNext = ComputePathDistance( GetNavType(), vPosPrev, pEndPoint->GetPos() ); - - if ( distToNext > distRemaining) - break; - - distRemaining -= distToNext; - vPosPrev = pEndPoint->GetPos(); - if ( fReducibleOnly && !pEndPoint->IsReducible() ) - break; - pEndPoint = pEndPoint->GetNext(); - } - - Vector &result = *pResult; - float distToEnd = ComputePathDistance( GetNavType(), vPosPrev, pEndPoint->GetPos() ); - if ( distToEnd - distRemaining < 0.1 ) - { - result = pEndPoint->GetPos(); - } - else - { - result = pEndPoint->GetPos() - vPosPrev; - VectorNormalize( result ); - result *= distRemaining; - result += vPosPrev; - } - - return true; -} - -//----------------------------------------------------------------------------- - -float CAI_Navigator::GetPathDistanceToGoal() -{ - return GetPath()->GetPathDistanceToGoal(GetAbsOrigin()); -} - -//----------------------------------------------------------------------------- - -float CAI_Navigator::GetPathTimeToGoal() -{ - if ( GetOuter()->m_flGroundSpeed ) - return (GetPathDistanceToGoal() / GetOuter()->m_flGroundSpeed); - return 0; -} - -//----------------------------------------------------------------------------- - -AI_PathNode_t CAI_Navigator::GetNearestNode() -{ - return (AI_PathNode_t)( GetPathfinder()->NearestNodeToNPC() ); -} - -//----------------------------------------------------------------------------- - -Vector CAI_Navigator::GetNodePos( AI_PathNode_t node ) -{ - return GetNetwork()->GetNode((int)node)->GetPosition(GetHullType()); -} - -//----------------------------------------------------------------------------- - -void CAI_Navigator::OnScheduleChange() -{ - DbgNavMsg( GetOuter(), "Schedule change\n" ); -} - -//----------------------------------------------------------------------------- - -void CAI_Navigator::OnClearPath(void) -{ -} - -//----------------------------------------------------------------------------- - -void CAI_Navigator::OnNewGoal() -{ - DbgNavMsg( GetOuter(), "New Goal\n" ); - ResetCalculations(); - m_fNavComplete = true; -} - -//----------------------------------------------------------------------------- - -void CAI_Navigator::OnNavComplete() -{ - DbgNavMsg( GetOuter(), "Nav complete\n" ); - ResetCalculations(); - TaskMovementComplete(); - m_fNavComplete = true; -} - -//----------------------------------------------------------------------------- - -void CAI_Navigator::OnNavFailed( bool bMovement ) -{ - DbgNavMsg( GetOuter(), "Nav failed\n" ); - if ( bMovement ) - GetOuter()->OnMovementFailed(); - -#ifdef DEBUG - if ( CurWaypointIsGoal() ) - { - float flWaypointDist = ComputePathDistance( GetNavType(), GetLocalOrigin(), GetPath()->ActualGoalPosition() ); - if ( flWaypointDist < GetGoalTolerance() + 0.1 ) - { - DevMsg( "Nav failed but NPC was within goal tolerance?\n" ); - } - } -#endif - - ResetCalculations(); - m_fNavComplete = true; - m_bLastNavFailed = true; -} - -//----------------------------------------------------------------------------- - -void CAI_Navigator::OnNavFailed( AI_TaskFailureCode_t code, bool bMovement ) -{ - if ( GetOuter()->ShouldFailNav( bMovement ) ) - { - OnNavFailed( bMovement ); - SetActivity( GetOuter()->GetStoppedActivity() ); - TaskFail(code); - } - else - { - m_nNavFailCounter++; - m_flLastNavFailTime = gpGlobals->curtime; - if ( GetOuter()->ShouldBruteForceFailedNav() ) - { - if (bMovement) - { - - m_timeBeginFailedSteer = FLT_MAX; - - // if failing, turn off collisions with the object - CBaseEntity *pBlocker = GetBlockingEntity(); - // FIXME: change this to only be for MOVETYPE_VPHYSICS? - if (pBlocker && !pBlocker->IsWorld() && !pBlocker->IsPlayer() && !FClassnameIs( pBlocker, "func_tracktrain" )) - { - //pBlocker->DrawBBoxOverlay( 2.0f ); - if (NPCPhysics_CreateSolver( GetOuter(), pBlocker, true, 10.0f ) != NULL) - { - ClearNavFailCounter(); - } - } - - // if still failing, try jumping forward through the route - if (GetNavFailCounter() > 0) - { - if (TeleportAlongPath()) - { - ClearNavFailCounter(); - } - } - } - else - { - CBaseEntity *pBlocker = GetMoveProbe()->GetBlockingEntity(); - if (pBlocker) - { - //pBlocker->DrawBBoxOverlay( 2.0f ); - if (NPCPhysics_CreateSolver( GetOuter(), pBlocker, true, 10.0f ) != NULL) - { - ClearNavFailCounter(); - } - } - } - } - } - -} -//----------------------------------------------------------------------------- - -void CAI_Navigator::OnNavFailed( const char *pszGeneralFailText, bool bMovement ) -{ - OnNavFailed( MakeFailCode( pszGeneralFailText ), bMovement ); -} - -//----------------------------------------------------------------------------- - -int CAI_Navigator::GetNavFailCounter() const -{ - return m_nNavFailCounter; -} - -//----------------------------------------------------------------------------- - -void CAI_Navigator::ClearNavFailCounter() -{ - m_nNavFailCounter = 0; -} - -//----------------------------------------------------------------------------- - -float CAI_Navigator::GetLastNavFailTime() const -{ - return m_flLastNavFailTime; -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::TeleportAlongPath() -{ - while (GetPath()->GetCurWaypoint()) - { - Vector vecStart; - Vector vTestPoint; - - vecStart = GetPath()->CurWaypointPos(); - AdvancePath(); - - GetOuter()->GetMoveProbe()->FloorPoint( vecStart, MASK_NPCSOLID, GetOuter()->StepHeight(), -64, &vTestPoint ); - - if ( CanFitAtPosition( vTestPoint, MASK_NPCSOLID, false, false ) ) - { - if ( GetOuter()->GetMoveProbe()->CheckStandPosition( vTestPoint, MASK_NPCSOLID ) ) - { - GetOuter()->Teleport( &vTestPoint, NULL, NULL ); - // clear ground entity, let normal fall code reestablish what the npc is now standing on - GetOuter()->SetGroundEntity( NULL ); - GetOuter()->PhysicsTouchTriggers( &vTestPoint ); - return true; - } - } - - if (CurWaypointIsGoal()) - break; - } - return false; -} - - -//----------------------------------------------------------------------------- - -void CAI_Navigator::ResetCalculations() -{ - m_hPeerWaitingOn = NULL; - m_PeerWaitMoveTimer.Force(); - m_PeerWaitClearTimer.Force(); - - m_hBigStepGroundEnt = NULL; - - m_NextSidestepTimer.Force(); - - m_bCalledStartMove = false; - - m_vPosBeginFailedSteer = vec3_invalid; - m_timeBeginFailedSteer = FLT_MAX; - - m_flLastSuccessfulSimplifyTime = -1; - - GetLocalNavigator()->ResetMoveCalculations(); - GetMotor()->ResetMoveCalculations(); - GetMoveProbe()->ClearBlockingEntity(); - - m_nNavFailCounter = 0; - m_flLastNavFailTime = -1; -} - -//----------------------------------------------------------------------------- -// Purpose: Sets navigation type, maintaining any necessary invariants -//----------------------------------------------------------------------------- -void CAI_Navigator::SetNavType( Navigation_t navType ) -{ - m_navType = navType; -} - - -//----------------------------------------------------------------------------- - -AIMoveResult_t CAI_Navigator::MoveClimb() -{ - // -------------------------------------------------- - // CLIMB START - // -------------------------------------------------- - const Vector &climbDest = GetPath()->CurWaypointPos(); - Vector climbDir = climbDest - GetLocalOrigin(); - float climbDist = VectorNormalize( climbDir ); - - if ( GetNavType() != NAV_CLIMB ) - { - DbgNavMsg( GetOuter(), "Climb start\n" ); - GetMotor()->MoveClimbStart( climbDest, climbDir, climbDist, GetPath()->CurWaypointYaw() ); - } - - SetNavType( NAV_CLIMB ); - - // Look for a block by another NPC, and attempt to recover - AIMoveTrace_t moveTrace; - if ( climbDist > 0.01 && - !GetMoveProbe()->MoveLimit( NAV_CLIMB, GetLocalOrigin(), GetLocalOrigin() + ( climbDir * MIN(0.1,climbDist - 0.005) ), MASK_NPCSOLID, GetNavTargetEntity(), &moveTrace ) ) - { - CAI_BaseNPC *pOther = ( moveTrace.pObstruction ) ? moveTrace.pObstruction->MyNPCPointer() : NULL; - if ( pOther ) - { - bool bAbort = false; - - if ( !pOther->IsMoving() ) - bAbort = true; - else if ( pOther->GetNavType() == NAV_CLIMB && climbDir.z <= 0.01 ) - { - const Vector &otherClimbDest = pOther->GetNavigator()->GetPath()->CurWaypointPos(); - Vector otherClimbDir = otherClimbDest - pOther->GetLocalOrigin(); - VectorNormalize( otherClimbDir ); - - if ( otherClimbDir.Dot( climbDir ) < 0 ) - { - bAbort = true; - if ( pOther->GetNavigator()->GetStoppingPath( m_pClippedWaypoints ) ) - { - m_flTimeClipped = gpGlobals->curtime; - SetNavType(NAV_GROUND); // end of clipped will be on ground - SetGravity( 1.0 ); - if ( RefindPathToGoal( false ) ) - { - bAbort = false; - } - SetGravity( 0.0 ); - SetNavType(NAV_CLIMB); - } - } - } - - if ( bAbort ) - { - DbgNavMsg( GetOuter(), "Climb fail\n" ); - GetMotor()->MoveClimbStop(); - SetNavType(NAV_GROUND); - return AIMR_BLOCKED_NPC; - } - } - } - - // count NAV_CLIMB nodes remaining - int climbNodesLeft = 0; - AI_Waypoint_t *pWaypoint = GetPath()->GetCurWaypoint(); - while (pWaypoint && pWaypoint->NavType() == NAV_CLIMB) - { - ++climbNodesLeft; - pWaypoint = pWaypoint->GetNext(); - } - - AIMoveResult_t result = GetMotor()->MoveClimbExecute( climbDest, climbDir, climbDist, GetPath()->CurWaypointYaw(), climbNodesLeft ); - - if ( result == AIMR_CHANGE_TYPE ) - { - if ( GetPath()->GetCurWaypoint()->GetNext() ) - AdvancePath(); - else - OnNavComplete(); - - if ( !GetPath()->GetCurWaypoint() || !GetPath()->GetCurWaypoint()->GetNext() || !(GetPath()->CurWaypointNavType() == NAV_CLIMB)) - { - DbgNavMsg( GetOuter(), "Climb stop\n" ); - GetMotor()->MoveClimbStop(); - SetNavType(NAV_GROUND); - } - } - else if ( result != AIMR_OK ) - { - DbgNavMsg( GetOuter(), "Climb fail (2)\n" ); - GetMotor()->MoveClimbStop(); - SetNavType(NAV_GROUND); - return result; - } - - return result; -} - -//----------------------------------------------------------------------------- - -AIMoveResult_t CAI_Navigator::MoveJump() -{ - // -------------------------------------------------- - // JUMPING - // -------------------------------------------------- - if ( (GetNavType() != NAV_JUMP) && (GetEntFlags() & FL_ONGROUND) ) - { - // -------------------------------------------------- - // Now check if I can actually jump this distance? - // -------------------------------------------------- - AIMoveTrace_t moveTrace; - GetMoveProbe()->MoveLimit( NAV_JUMP, GetLocalOrigin(), GetPath()->CurWaypointPos(), - MASK_NPCSOLID, GetNavTargetEntity(), &moveTrace ); - if ( IsMoveBlocked( moveTrace ) ) - { - return moveTrace.fStatus; - } - - SetNavType(NAV_JUMP); - - DbgNavMsg( GetOuter(), "Jump start\n" ); - GetMotor()->MoveJumpStart( moveTrace.vJumpVelocity ); - } - // -------------------------------------------------- - // LANDING (from jump) - // -------------------------------------------------- - else if (GetNavType() == NAV_JUMP && (GetEntFlags() & FL_ONGROUND)) - { - // DevMsg( "jump to %f %f %f landed %f %f %f", GetPath()->CurWaypointPos().x, GetPath()->CurWaypointPos().y, GetPath()->CurWaypointPos().z, GetLocalOrigin().x, GetLocalOrigin().y, GetLocalOrigin().z ); - - DbgNavMsg( GetOuter(), "Jump stop\n" ); - AIMoveResult_t result = GetMotor()->MoveJumpStop( ); - - if (result == AIMR_CHANGE_TYPE) - { - SetNavType(NAV_GROUND); - - // -------------------------------------------------- - // If I've jumped to my goal I'm done - // -------------------------------------------------- - if (CurWaypointIsGoal()) - { - OnNavComplete(); - return AIMR_OK; - } - // -------------------------------------------------- - // Otherwise advance my route and walk - // -------------------------------------------------- - else - { - AdvancePath(); - return AIMR_CHANGE_TYPE; - } - } - return AIMR_OK; - } - // -------------------------------------------------- - // IN-AIR (from jump) - // -------------------------------------------------- - else - { - GetMotor()->MoveJumpExecute( ); - } - - return AIMR_OK; -} - - -//----------------------------------------------------------------------------- - -void CAI_Navigator::MoveCalcBaseGoal( AILocalMoveGoal_t *pMoveGoal ) -{ - AI_PROFILE_SCOPE( CAI_Navigator_MoveCalcBaseGoal ); - - pMoveGoal->navType = GetNavType(); - pMoveGoal->target = GetPath()->CurWaypointPos(); - pMoveGoal->maxDist = ComputePathDirection( GetNavType(), GetLocalOrigin(), pMoveGoal->target, &pMoveGoal->dir ); - pMoveGoal->facing = pMoveGoal->dir; - pMoveGoal->speed = GetMotor()->GetSequenceGroundSpeed( GetMovementSequence() ); - pMoveGoal->curExpectedDist = pMoveGoal->speed * GetMotor()->GetMoveInterval(); - pMoveGoal->pMoveTarget = GetNavTargetEntity(); - - if ( pMoveGoal->curExpectedDist > pMoveGoal->maxDist ) - pMoveGoal->curExpectedDist = pMoveGoal->maxDist; - - if ( GetPath()->CurWaypointIsGoal()) - { - pMoveGoal->flags |= AILMG_TARGET_IS_GOAL; - } - else - { - AI_Waypoint_t *pCurWaypoint = GetPath()->GetCurWaypoint(); - if ( pCurWaypoint->GetNext() && pCurWaypoint->GetNext()->NavType() != pCurWaypoint->NavType() ) - pMoveGoal->flags |= AILMG_TARGET_IS_TRANSITION; - } - - const Task_t *pCurTask = GetOuter()->GetTask(); - if ( pCurTask && pCurTask->iTask == TASK_STOP_MOVING ) - { - // If we're running stop moving, don't steer or run avoidance paths - // This stops the NPC wiggling around as they attempt to reach a stopping - // path that's pushed right up against geometry. (Tracker #48656) - pMoveGoal->flags |= ( AILMG_NO_STEER | AILMG_NO_AVOIDANCE_PATHS ); - } - - pMoveGoal->pPath = GetPath(); -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) -{ - if ( GetOuter()->OnCalcBaseMove( pMoveGoal, distClear, pResult ) ) - { - DebugNoteMovementFailureIfBlocked( *pResult ); - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) -{ - bool fTargetIsGoal = ( ( pMoveGoal->flags & AILMG_TARGET_IS_GOAL ) != 0 ); - bool fShouldAttemptHit = false; - bool fShouldAdvancePath = false; - float tolerance = 0; - - if ( fTargetIsGoal ) - { - fShouldAttemptHit = true; - tolerance = GetPath()->GetGoalTolerance(); - } - else if ( !( pMoveGoal->flags & AILMG_TARGET_IS_TRANSITION ) ) - { - fShouldAttemptHit = true; - fShouldAdvancePath = true; - tolerance = GetPath()->GetWaypointTolerance(); - - // If the immediate goal is close, and the clearance brings into tolerance, - // just try and move on - if ( pMoveGoal->maxDist < 4*12 && pMoveGoal->maxDist - distClear < tolerance ) - tolerance = pMoveGoal->maxDist + 1; - } - - if ( fShouldAttemptHit ) - { - if ( distClear > pMoveGoal->maxDist ) - { -#ifdef PHYSICS_NPC_SHADOW_DISCREPENCY - if ( distClear < AI_EPS_CASTS ) // needed because vphysics can pull us back up to this far - { - DebugNoteMovementFailure(); - *pResult = pMoveGoal->directTrace.fStatus; - pMoveGoal->maxDist = 0; - return true; - } -#endif - *pResult = AIMR_OK; - return true; - } - - -#ifdef PHYSICS_NPC_SHADOW_DISCREPENCY - if ( pMoveGoal->maxDist + AI_EPS_CASTS < tolerance ) -#else - if ( pMoveGoal->maxDist < tolerance ) -#endif - { - if ( !fTargetIsGoal || - ( pMoveGoal->directTrace.fStatus != AIMR_BLOCKED_NPC ) || - ( !((CAI_BaseNPC *)pMoveGoal->directTrace.pObstruction)->IsMoving() ) ) - { - pMoveGoal->maxDist = distClear; - *pResult = AIMR_OK; - - if ( fShouldAdvancePath ) - { - AdvancePath(); - } - else if ( distClear < 0.025 ) - { - *pResult = pMoveGoal->directTrace.fStatus; - } - return true; - } - } - } - -#ifdef HL2_EPISODIC - // Build an avoidance path around a vehicle - if ( ai_vehicle_avoidance.GetBool() && pMoveGoal->directTrace.pObstruction != NULL && pMoveGoal->directTrace.pObstruction->GetServerVehicle() != NULL ) - { - //FIXME: This should change into a flag which forces an OBB route to be formed around the entity in question! - AI_Waypoint_t *pOBB = GetPathfinder()->BuildOBBAvoidanceRoute( GetOuter()->GetAbsOrigin(), - GetGoalPos(), - pMoveGoal->directTrace.pObstruction, - GetNavTargetEntity(), - GetNavType() ); - - // See if we need to complete this navigation - if ( pOBB == NULL ) - { - /* - if ( GetOuter()->ShouldFailNav( true ) == false ) - { - // Create a physics solver to allow us to pass - NPCPhysics_CreateSolver( GetOuter(), pMoveGoal->directTrace.pObstruction, true, 5.0f ); - return true; - } - */ - } - else - { - // Otherwise we have a clear path to move around - GetPath()->PrependWaypoints( pOBB ); - return true; - } - } -#endif // HL2_EPISODIC - - // Allow the NPC to override this behavior. Above logic takes priority - if ( GetOuter()->OnObstructionPreSteer( pMoveGoal, distClear, pResult ) ) - { - DebugNoteMovementFailureIfBlocked( *pResult ); - return true; - } - - if ( !m_hBigStepGroundEnt.Get() && - pMoveGoal->directTrace.pObstruction && - distClear < GetHullWidth() && - pMoveGoal->directTrace.pObstruction == GetOuter()->GetGroundEntity() && - ( pMoveGoal->directTrace.pObstruction->IsPlayer() || - dynamic_cast( pMoveGoal->directTrace.pObstruction ) ) ) - { - m_hBigStepGroundEnt = pMoveGoal->directTrace.pObstruction; - *pResult = AIMR_CHANGE_TYPE; - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::OnInsufficientStopDist( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) -{ - // Allow the NPC to override this behavior - if ( GetOuter()->OnInsufficientStopDist( pMoveGoal, distClear, pResult )) - { - DebugNoteMovementFailureIfBlocked( *pResult ); - return true; - } - -#ifdef PHYSICS_NPC_SHADOW_DISCREPENCY - if ( distClear < AI_EPS_CASTS ) // needed because vphysics can pull us back up to this far - { - DebugNoteMovementFailure(); - *pResult = pMoveGoal->directTrace.fStatus; - pMoveGoal->maxDist = 0; - return true; - } -#endif - - if ( !IsMovingOutOfWay( *pMoveGoal, distClear ) ) - { - float goalDist = ComputePathDistance( GetNavType(), GetAbsOrigin(), GetPath()->ActualGoalPosition() ); - - if ( goalDist < GetGoalTolerance() + 0.01 ) - { - pMoveGoal->maxDist = distClear; - pMoveGoal->flags |= AILMG_CONSUME_INTERVAL; - OnNavComplete(); - *pResult = AIMR_OK; - return true; - } - - if ( m_NextSidestepTimer.Expired() ) - { - // Try bumping to side - m_NextSidestepTimer.Reset(); - - AIMoveTrace_t moveTrace; - Vector vDeflection; - CalculateDeflection( GetLocalOrigin(), pMoveGoal->dir, pMoveGoal->directTrace.vHitNormal, &vDeflection ); - - for ( int i = 1; i > -2; i -= 2 ) - { - Vector testLoc = GetLocalOrigin() + ( vDeflection * GetHullWidth() * 2.0) * i; - GetMoveProbe()->MoveLimit( GetNavType(), GetLocalOrigin(), testLoc, MASK_NPCSOLID, NULL, &moveTrace ); - if ( moveTrace.fStatus == AIMR_OK ) - { - Vector vNewWaypoint = moveTrace.vEndPosition; - GetMoveProbe()->MoveLimit( GetNavType(), vNewWaypoint, pMoveGoal->target, MASK_NPCSOLID_BRUSHONLY, NULL, &moveTrace ); - if ( moveTrace.fStatus == AIMR_OK ) - { - PrependWaypoint( vNewWaypoint, GetNavType(), bits_WP_TO_DETOUR ); - *pResult = AIMR_CHANGE_TYPE; - return true; - } - } - } - } - - - if ( distClear < 1.0 ) - { - // too close, nothing happening, I'm screwed - DebugNoteMovementFailure(); - *pResult = pMoveGoal->directTrace.fStatus; - pMoveGoal->maxDist = 0; - return true; - } - return false; - } - - *pResult = AIMR_OK; - pMoveGoal->maxDist = distClear; - pMoveGoal->flags |= AILMG_CONSUME_INTERVAL; - return true; -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::OnFailedSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) -{ - // Allow the NPC to override this behavior - if ( GetOuter()->OnFailedSteer( pMoveGoal, distClear, pResult )) - { - DebugNoteMovementFailureIfBlocked( *pResult ); - return true; - } - - if ( pMoveGoal->flags & AILMG_TARGET_IS_GOAL ) - { - if ( distClear >= GetPathDistToGoal() ) - { - *pResult = AIMR_OK; - return true; - } - - if ( distClear > pMoveGoal->maxDist - GetPath()->GetGoalTolerance() ) - { - Assert( CurWaypointIsGoal() && fabs(pMoveGoal->maxDist - GetPathDistToCurWaypoint()) < 0.01 ); - - if ( pMoveGoal->maxDist > distClear ) - pMoveGoal->maxDist = distClear; - - if ( distClear < 0.125 ) - OnNavComplete(); - - pMoveGoal->flags |= AILMG_CONSUME_INTERVAL; - *pResult = AIMR_OK; - - return true; - } - } - - if ( !( pMoveGoal->flags & AILMG_TARGET_IS_TRANSITION ) ) - { - float distToWaypoint = GetPathDistToCurWaypoint(); - float halfHull = GetHullWidth() * 0.5; - - if ( distToWaypoint < halfHull ) - { - if ( distClear > distToWaypoint + halfHull ) - { - *pResult = AIMR_OK; - return true; - } - } - } - -#if 0 - if ( pMoveGoal->directTrace.pObstruction->MyNPCPointer() && - !GetOuter()->IsUsingSmallHull() && - GetOuter()->SetHullSizeSmall() ) - { - *pResult = AIMR_CHANGE_TYPE; - return true; - } -#endif - - if ( !TestingSteering() && pMoveGoal->directTrace.fStatus == AIMR_BLOCKED_NPC && pMoveGoal->directTrace.vHitNormal != vec3_origin ) - { - AIMoveTrace_t moveTrace; - Vector vDeflection; - CalculateDeflection( GetLocalOrigin(), pMoveGoal->dir, pMoveGoal->directTrace.vHitNormal, &vDeflection ); - - if ( pMoveGoal->dir.AsVector2D().Dot( vDeflection.AsVector2D() ) > 0.7 ) - { - Vector testLoc = GetLocalOrigin() + ( vDeflection * pMoveGoal->curExpectedDist ); - GetMoveProbe()->MoveLimit( GetNavType(), GetLocalOrigin(), testLoc, MASK_NPCSOLID, NULL, &moveTrace ); - if ( moveTrace.fStatus == AIMR_OK ) - { - pMoveGoal->dir = vDeflection; - pMoveGoal->maxDist = pMoveGoal->curExpectedDist; - *pResult = AIMR_OK; - return true; - } - } - } - - - // If fail steer more than once after a second with no measurable progres, fail completely - // This usually means a sucessful triangulation was not actually a valid avoidance. - const float MOVE_TOLERANCE = 12.0; - const float TIME_TOLERANCE = 1.0; - - if ( m_vPosBeginFailedSteer == vec3_invalid || ( m_vPosBeginFailedSteer - GetAbsOrigin() ).LengthSqr() > Square(MOVE_TOLERANCE) ) - { - m_vPosBeginFailedSteer = GetAbsOrigin(); - m_timeBeginFailedSteer = gpGlobals->curtime; - } - else if ( GetNavType() == NAV_GROUND && - gpGlobals->curtime - m_timeBeginFailedSteer > TIME_TOLERANCE && - GetOuter()->m_flGroundSpeed * TIME_TOLERANCE > MOVE_TOLERANCE ) - { - *pResult = AIMR_ILLEGAL; - return true; - } - - if ( !(pMoveGoal->flags & AILMG_NO_AVOIDANCE_PATHS) && distClear < pMoveGoal->maxDist && !TestingSteering() ) - { - if ( PrependLocalAvoidance( distClear, pMoveGoal->directTrace ) ) - { - *pResult = AIMR_CHANGE_TYPE; - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::OnFailedLocalNavigation( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) -{ - // Allow the NPC to override this behavior - if ( GetOuter()->OnFailedLocalNavigation( pMoveGoal, distClear, pResult )) - { - DebugNoteMovementFailureIfBlocked( *pResult ); - return true; - } - - if ( DelayNavigationFailure( pMoveGoal->directTrace ) ) - { - *pResult = AIMR_OK; - pMoveGoal->maxDist = distClear; - pMoveGoal->flags |= AILMG_CONSUME_INTERVAL; - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::DelayNavigationFailure( const AIMoveTrace_t &trace ) -{ - // This code only handles the case of a group of AIs in close proximity, preparing - // to move mostly as a group, but on slightly different think schedules. Without - // this patience factor, in the middle or at the rear might fail just because it - // happened to have its think function called a half cycle before the one - // in front of it. - - CAI_BaseNPC *pBlocker = trace.pObstruction ? trace.pObstruction->MyNPCPointer() : NULL; - Assert( m_fPeerMoveWait == false || pBlocker == m_hPeerWaitingOn ); // expected to be cleared each frame, and never call this function twice - - if ( !m_fPeerMoveWait || pBlocker != m_hPeerWaitingOn ) - { - if ( pBlocker ) - { - if ( m_hPeerWaitingOn != pBlocker || m_PeerWaitClearTimer.Expired() ) - { - m_fPeerMoveWait = true; - m_hPeerWaitingOn = pBlocker; - m_PeerWaitMoveTimer.Reset(); - m_PeerWaitClearTimer.Reset(); - - if ( pBlocker->GetGroundEntity() == GetOuter() ) - { - trace_t bumpTrace; - pBlocker->GetMoveProbe()->TraceHull( pBlocker->GetAbsOrigin(), - pBlocker->GetAbsOrigin() + Vector(0,0,2.0), - MASK_NPCSOLID, - &bumpTrace ); - if ( bumpTrace.fraction == 1.0 ) - { - UTIL_SetOrigin(pBlocker, bumpTrace.endpos, true); - } - } - } - else if ( m_hPeerWaitingOn == pBlocker && !m_PeerWaitMoveTimer.Expired() ) - { - m_fPeerMoveWait = true; - } - } - } - - return m_fPeerMoveWait; -} - -//----------------------------------------------------------------------------- - -// @TODO (toml 11-12-02): right now, physics can pull the box back pretty far even though a hull -// trace said we could make the move. Jay is looking into it. For now, if the NPC physics shadow -// is active, allow for a bugger tolerance -extern ConVar npc_vphysics; - -bool test_it = false; - -bool CAI_Navigator::MoveUpdateWaypoint( AIMoveResult_t *pResult ) -{ - // Note that goal & waypoint tolerances are handled in progress blockage cases (e.g., OnObstructionPreSteer) - - AI_Waypoint_t *pCurWaypoint = GetPath()->GetCurWaypoint(); - float waypointDist = ComputePathDistance( GetNavType(), GetLocalOrigin(), pCurWaypoint->GetPos() ); - bool bIsGoal = CurWaypointIsGoal(); - float tolerance = ( npc_vphysics.GetBool() ) ? 0.25 : 0.0625; - - bool fHit = false; - - if ( waypointDist <= tolerance ) - { - if ( test_it ) - { - if ( pCurWaypoint->GetNext() && pCurWaypoint->GetNext()->NavType() != pCurWaypoint->NavType() ) - { - if ( waypointDist < 0.001 ) - fHit = true; - } - else - fHit = true; - } - else - fHit = true; - } - - if ( fHit ) - { - if ( bIsGoal ) - { - OnNavComplete(); - *pResult = AIMR_OK; - - } - else - { - AdvancePath(); - *pResult = AIMR_CHANGE_TYPE; - } - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::OnMoveStalled( const AILocalMoveGoal_t &move ) -{ - SetActivity( GetOuter()->GetStoppedActivity() ); - return true; -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::OnMoveExecuteFailed( const AILocalMoveGoal_t &move, const AIMoveTrace_t &trace, AIMotorMoveResult_t fMotorResult, AIMoveResult_t *pResult ) -{ - // Allow the NPC to override this behavior - if ( GetOuter()->OnMoveExecuteFailed( move, trace, fMotorResult, pResult )) - { - DebugNoteMovementFailureIfBlocked( *pResult ); - return true; - } - - if ( !m_hBigStepGroundEnt.Get() && - trace.pObstruction && - trace.flTotalDist - trace.flDistObstructed < GetHullWidth() && - trace.pObstruction == GetOuter()->GetGroundEntity() && - ( trace.pObstruction->IsPlayer() || - dynamic_cast( trace.pObstruction ) ) ) - { - m_hBigStepGroundEnt = trace.pObstruction; - *pResult = AIMR_CHANGE_TYPE; - return true; - } - - if ( fMotorResult == AIM_PARTIAL_HIT_TARGET ) - { - OnNavComplete(); - *pResult = AIMR_OK; - } - else if ( fMotorResult == AIM_PARTIAL_HIT_NPC && DelayNavigationFailure( trace ) ) - { - *pResult = AIMR_OK; - } - - return true; -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::OnMoveBlocked( AIMoveResult_t *pResult ) -{ - if ( *pResult == AIMR_BLOCKED_NPC && - GetPath()->GetCurWaypoint() && - ( GetPath()->GetCurWaypoint()->Flags() & bits_WP_TO_DOOR ) ) - { - CBasePropDoor *pDoor = (CBasePropDoor *)(CBaseEntity *)GetPath()->GetCurWaypoint()->GetEHandleData(); - if (pDoor != NULL) - { - GetOuter()->OpenPropDoorBegin( pDoor ); - *pResult = AIMR_OK; - return true; - } - } - - - // Allow the NPC to override this behavior - if ( GetOuter()->OnMoveBlocked( pResult )) - return true; - - float flWaypointDist; - - if ( !GetPath()->CurWaypointIsGoal() && GetPath()->GetCurWaypoint()->IsReducible() ) - { - flWaypointDist = ComputePathDistance( GetNavType(), GetLocalOrigin(), GetCurWaypointPos() ); - if ( flWaypointDist < GetHullWidth() ) - { - AdvancePath(); - *pResult = AIMR_CHANGE_TYPE; - } - } - - SetActivity( GetOuter()->GetStoppedActivity() ); - - const float EPS = 0.1; - - flWaypointDist = ComputePathDistance( GetNavType(), GetLocalOrigin(), GetPath()->ActualGoalPosition() ); - - if ( flWaypointDist < GetGoalTolerance() + EPS ) - { - OnNavComplete(); - *pResult = AIMR_OK; - return true; - } - - return false; -} - -//------------------------------------- - -AIMoveResult_t CAI_Navigator::MoveEnact( const AILocalMoveGoal_t &baseMove ) -{ - AIMoveResult_t result = AIMR_ILLEGAL; - AILocalMoveGoal_t move = baseMove; - - result = GetLocalNavigator()->MoveCalc( &move, ( m_flLastSuccessfulSimplifyTime == gpGlobals->curtime ) ); - - if ( result != AIMR_OK ) - m_hLastBlockingEnt = move.directTrace.pObstruction; - else - { - m_hLastBlockingEnt = NULL; - GetMoveProbe()->ClearBlockingEntity(); - } - - if ( result == AIMR_OK && !m_fNavComplete ) - { - Assert( GetPath()->GetCurWaypoint() ); - result = GetMotor()->MoveNormalExecute( move ); - } - else if ( result != AIMR_CHANGE_TYPE ) - { - GetMotor()->MoveStop(); - } - - if ( IsMoveBlocked( result ) ) - { - OnMoveBlocked( &result ); - } - - return result; -} - -//----------------------------------------------------------------------------- - -AIMoveResult_t CAI_Navigator::MoveNormal() -{ - if (!PreMove()) - return AIMR_ILLEGAL; - - if ( ShouldTestFailMove() ) - return AIMR_ILLEGAL; - - // -------------------------------- - - AIMoveResult_t result = AIMR_ILLEGAL; - - if ( MoveUpdateWaypoint( &result ) ) - return result; - - // -------------------------------- - - // Set activity to be the Navigation activity - float preMoveSpeed = GetIdealSpeed(); - Activity preMoveActivity = GetActivity(); - int nPreMoveSequence = GetOuter()->GetSequence(); // this is an unfortunate necessity to ensure setting back the activity picks the right one if it had been sticky - Vector vStart = GetAbsOrigin(); - - // -------------------------------- - - // FIXME: only need since IdealSpeed isn't based on movement activity but immediate activity! - SetActivity( GetMovementActivity() ); - - if ( m_bValidateActivitySpeed && GetIdealSpeed() <= 0.0f ) - { - if ( GetActivity() == ACT_TRANSITION ) - return AIMR_OK; - DevMsg( "%s moving with speed <= 0 (%s)\n", GetEntClassname(), GetOuter()->GetSequenceName( GetSequence() ) ); - } - - // -------------------------------- - - AILocalMoveGoal_t move; - - MoveCalcBaseGoal( &move ); - - result = MoveEnact( move ); - - // -------------------------------- - // If we didn't actually move, but it was a success (i.e., blocked but within tolerance), make sure no visual artifact - - // FIXME: only needed because of the above slamming of SetActivity(), which is only needed - // because GetIdealSpeed() looks at the current activity instead of the movement activity. - - if ( result == AIMR_OK && preMoveSpeed < 0.01 ) - { - if ( ( GetAbsOrigin() - vStart ).Length() < 0.01 ) - { - GetOuter()->SetSequence( nPreMoveSequence ); - SetActivity( preMoveActivity ); - } - } - - // -------------------------------- - - return result; -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::PreMove() -{ - Navigation_t goalType = GetPath()->CurWaypointNavType(); - Navigation_t curType = GetNavType(); - - m_fPeerMoveWait = false; - - if ( goalType == NAV_GROUND && curType != NAV_GROUND ) - { - DevMsg( "Warning: %s(%s) appears to have wrong nav type in CAI_Navigator::MoveGround()\n", GetOuter()->GetClassname(), STRING( GetOuter()->GetEntityName() ) ); - switch ( curType ) - { - case NAV_CLIMB: - { - GetMotor()->MoveClimbStop(); - break; - } - - case NAV_JUMP: - { - GetMotor()->MoveJumpStop(); - break; - } - - default: - break; - } - - SetNavType( NAV_GROUND ); - } - else if ( goalType == NAV_FLY && curType != NAV_FLY ) - { - AssertMsg( 0, ( "GetNavType() == NAV_FLY" ) ); - return false; - } - - // -------------------------------- - - Assert( GetMotor()->GetMoveInterval() > 0 ); - - // -------------------------------- - - SimplifyPath(); - - - return true; -} - -//-------------------------------------------------------------------------------------------- - -bool CAI_Navigator::IsMovingOutOfWay( const AILocalMoveGoal_t &moveGoal, float distClear ) -{ - // FIXME: We can make this work for regular entities; although the - // original code was simply looking @ NPCs. I'm reproducing that code now - // although I want to make it work for both. - CAI_BaseNPC *pBlocker = moveGoal.directTrace.pObstruction ? moveGoal.directTrace.pObstruction->MyNPCPointer() : NULL; - - // if it's the world, it ain't moving - if (!pBlocker) - return false; - - // if they're doing something, assume it'll work out - if (pBlocker->IsMoving()) - { - if ( distClear > moveGoal.curExpectedDist * 0.75 ) - return true; - - Vector2D velBlocker = pBlocker->GetMotor()->GetCurVel().AsVector2D(); - Vector2D velBlockerNorm = velBlocker; - - Vector2DNormalize( velBlockerNorm ); - - float dot = moveGoal.dir.AsVector2D().Dot( velBlockerNorm ); - - if (dot > -0.25 ) - { - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Move towards the next waypoint on my route -// Input : -// Output : -//----------------------------------------------------------------------------- - -enum AINavResult_t -{ - AINR_OK, - AINR_NO_GOAL, - AINR_NO_ROUTE, - AINR_BLOCKED, - AINR_ILLEGAL -}; - -bool CAI_Navigator::Move( float flInterval ) -{ - if (flInterval > 1.0) - { - // Bound interval so we don't get ludicrous motion when debugging - // or when framerate drops catostrophically - flInterval = 1.0; - } - - if ( !GetOuter()->OverrideMove( flInterval ) ) - { - // UNDONE: Figure out how much of the timestep was consumed by movement - // this frame and restart the movement/schedule engine if necessary - bool bHasGoal = GetGoalType() != GOALTYPE_NONE; - bool bIsTurning = HasMemory( bits_MEMORY_TURNING ); - if ( bHasGoal ) - { - if ( bIsTurning ) - { - if ( gpGlobals->curtime - GetPath()->GetStartTime() > 5 ) - { - Forget( bits_MEMORY_TURNING ); - bIsTurning = false; - DbgNavMsg( GetOuter(), "NPC appears stuck turning. Proceeding.\n" ); - } - } - - if ( ActivityIsLocomotive( m_PreviousMoveActivity ) && !ActivityIsLocomotive( GetMovementActivity() ) ) - { - SetMovementActivity( GetOuter()->TranslateActivity( m_PreviousMoveActivity ) ); - } - } - else - { - m_PreviousMoveActivity = ACT_RESET; - m_PreviousArrivalActivity = ACT_RESET; - } - - bool fShouldMove = ( bHasGoal && - // !bIsTurning && - ActivityIsLocomotive( GetMovementActivity() ) ); - if ( fShouldMove ) - { - AINavResult_t result = AINR_OK; - - GetMotor()->SetMoveInterval( flInterval ); - - // --------------------------------------------------------------------- - // Move should never happen if I don't have a movement goal or route - // --------------------------------------------------------------------- - if ( GetPath()->GoalType() == GOALTYPE_NONE ) - { - DevWarning( "Move requested with no route!\n" ); - result = AINR_NO_GOAL; - } - else if (!GetPath()->GetCurWaypoint()) - { - DevWarning( "Move goal with no route!\n" ); - GetPath()->Clear(); - result = AINR_NO_ROUTE; - } - - if ( result == AINR_OK ) - { - // --------------------------------------------------------------------- - // If I've been asked to wait, let's wait - // --------------------------------------------------------------------- - if ( GetOuter()->ShouldMoveWait() ) - { - GetMotor()->MovePaused(); - return false; - } - - int nLoopCount = 0; - - bool bMoved = false; - AIMoveResult_t moveResult = AIMR_CHANGE_TYPE; - m_fNavComplete = false; - - while ( moveResult >= AIMR_OK && !m_fNavComplete ) - { - if ( GetMotor()->GetMoveInterval() <= 0 ) - { - moveResult = AIMR_OK; - break; - } - - // TODO: move higher up the call chain? - if ( !m_bCalledStartMove ) - { - GetMotor()->MoveStart(); - m_bCalledStartMove = true; - } - - if ( m_hBigStepGroundEnt && m_hBigStepGroundEnt != GetOuter()->GetGroundEntity() ) - m_hBigStepGroundEnt = NULL; - - switch (GetPath()->CurWaypointNavType()) - { - case NAV_CLIMB: - moveResult = MoveClimb(); - break; - - case NAV_JUMP: - moveResult = MoveJump(); - break; - - case NAV_GROUND: - case NAV_FLY: - moveResult = MoveNormal(); - break; - - default: - DevMsg( "Bogus route move type!"); - moveResult = AIMR_ILLEGAL; - break; - } - - if ( moveResult == AIMR_OK ) - bMoved = true; - - ++nLoopCount; - if ( nLoopCount > 16 ) - { - DevMsg( "ERROR: %s navigation not terminating. Possibly bad cyclical solving?\n", GetOuter()->GetDebugName() ); - moveResult = AIMR_ILLEGAL; - - switch (GetPath()->CurWaypointNavType()) - { - case NAV_GROUND: - case NAV_FLY: - OnMoveBlocked( &moveResult ); - break; - default: - break; - } - break; - } - - } - - // -------------------------------------------- - // Update move status - // -------------------------------------------- - if ( IsMoveBlocked( moveResult ) ) - { - bool bRecovered = false; - if (moveResult != AIMR_BLOCKED_NPC || GetNavType() == NAV_CLIMB || GetNavType() == NAV_JUMP || GetPath()->CurWaypointNavType() == NAV_JUMP ) - { - if ( MarkCurWaypointFailedLink() ) - { - AI_Waypoint_t *pSavedWaypoints = GetPath()->GetCurWaypoint(); - if ( pSavedWaypoints ) - { - GetPath()->SetWaypoints( NULL ); - if ( RefindPathToGoal( false, true ) ) - { - DeleteAll( pSavedWaypoints ); - bRecovered = true; - } - else - GetPath()->SetWaypoints( pSavedWaypoints ); - - } - } - - } - - if ( !bRecovered ) - { - OnNavFailed( ( moveResult == AIMR_ILLEGAL ) ? FAIL_NO_ROUTE_ILLEGAL : FAIL_NO_ROUTE_BLOCKED, true ); - } - } - return bMoved; - } - - static AI_TaskFailureCode_t failures[] = - { - NO_TASK_FAILURE, // AINR_OK (never should happen) - FAIL_NO_ROUTE_GOAL, // AINR_NO_GOAL - FAIL_NO_ROUTE, // AINR_NO_ROUTE - FAIL_NO_ROUTE_BLOCKED, // AINR_BLOCKED - FAIL_NO_ROUTE_ILLEGAL // AINR_ILLEGAL - }; - - OnNavFailed( failures[result], false ); - } - else - { - // @TODO (toml 10-30-02): the climb part of this is unacceptable, but needed until navigation can handle commencing - // a navigation while in the middle of a climb - - if ( GetNavType() == NAV_CLIMB ) - { - GetMotor()->MoveClimbStop(); - SetNavType( NAV_GROUND ); - } - GetMotor()->MoveStop(); - AssertMsg( TaskIsRunning() || TaskIsComplete(), ("Schedule stalled!!\n") ); - } - return false; - } - - return true; // assume override move handles stopping issues -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns yaw speed based on what they're doing. -//----------------------------------------------------------------------------- -float CAI_Navigator::CalcYawSpeed( void ) -{ - // Allow the NPC to override this behavior - float flNPCYaw = GetOuter()->CalcYawSpeed(); - if (flNPCYaw >= 0.0f) - return flNPCYaw; - - float maxYaw = MaxYawSpeed(); - - //return maxYaw; - - if( IsGoalSet() && GetIdealSpeed() != 0.0) - { - // --------------------------------------------------- - // If not moving to a waypoint use a base turing speed - // --------------------------------------------------- - if (!GetPath()->GetCurWaypoint()) - { - return maxYaw; - } - // -------------------------------------------------------------- - // If moving towards a waypoint, set the turn speed based on the - // distance of the waypoint and my forward velocity - // -------------------------------------------------------------- - if (GetIdealSpeed() > 0) - { - // ----------------------------------------------------------------- - // Get the projection of npc's heading direction on the waypoint dir - // ----------------------------------------------------------------- - float waypointDist = (GetPath()->CurWaypointPos() - GetLocalOrigin()).Length(); - - // If waypoint is close, aim for the waypoint - if (waypointDist < 100) - { - float scale = 1 + (0.01*(100 - waypointDist)); - return (maxYaw * scale); - } - } - } - return maxYaw; -} - -//----------------------------------------------------------------------------- -float CAI_Navigator::GetStepDownMultiplier() -{ - if ( m_hBigStepGroundEnt ) - { - if ( !m_hBigStepGroundEnt->IsPlayer() ) - return 2.6; - else - return 10.0; - } - return 1.0; -} - -//----------------------------------------------------------------------------- -// Purpose: Attempts to advance the route to the next waypoint, triangulating -// around entities that are in the way -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_Navigator::AdvancePath() -{ - DbgNavMsg( GetOuter(), "Advancing path\n" ); - - AI_Waypoint_t *pCurWaypoint = GetPath()->GetCurWaypoint(); - bool bPassingPathcorner = ( ( pCurWaypoint->Flags() & bits_WP_TO_PATHCORNER ) != 0 ); - - if ( bPassingPathcorner ) - { - Assert( !pCurWaypoint->GetNext() || (pCurWaypoint->GetNext()->Flags() & (bits_WP_TO_PATHCORNER | bits_WP_TO_GOAL )) == (bits_WP_TO_PATHCORNER | bits_WP_TO_GOAL )); - CBaseEntity *pEntity = pCurWaypoint->hPathCorner; - if ( pEntity ) - { - variant_t emptyVariant; - pEntity->AcceptInput( "InPass", GetOuter(), pEntity, emptyVariant, 0 ); - } - } - - if ( GetPath()->CurWaypointIsGoal() ) - return; - - if ( pCurWaypoint->Flags() & bits_WP_TO_DOOR ) - { - CBasePropDoor *pDoor = (CBasePropDoor *)(CBaseEntity *)pCurWaypoint->GetEHandleData(); - if (pDoor != NULL) - { - GetOuter()->OpenPropDoorBegin(pDoor); - } - else - { - DevMsg("%s trying to open a door that has been deleted!\n", GetOuter()->GetDebugName()); - } - } - - GetPath()->Advance(); - - // If we've just passed a path_corner, advance m_pGoalEnt - if ( bPassingPathcorner ) - { - pCurWaypoint = GetPath()->GetCurWaypoint(); - - if ( pCurWaypoint ) - { - Assert( (pCurWaypoint->Flags() & (bits_WP_TO_PATHCORNER | bits_WP_TO_GOAL )) == (bits_WP_TO_PATHCORNER | bits_WP_TO_GOAL )); - - SetGoalEnt( pCurWaypoint->hPathCorner ); - DoFindPathToPathcorner( pCurWaypoint->hPathCorner ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -#ifdef DEBUG -ConVar ai_disable_path_simplification( "ai_disable_path_simplification","0" ); -#define IsSimplifyPathDisabled() ai_disable_path_simplification.GetBool() -#else -#define IsSimplifyPathDisabled() false -#endif - -const float MIN_ANGLE_COS_SIMPLIFY = 0.766; // 40 deg left or right - -bool CAI_Navigator::ShouldAttemptSimplifyTo( const Vector &pos ) -{ - if ( m_bForcedSimplify ) - return true; - - Vector vecToPos = ( pos - GetLocalOrigin() ); - vecToPos.z = 0; - VectorNormalize( vecToPos ); - - Vector vecCurrentDirectionOfMovement = ( GetCurWaypointPos() - GetLocalOrigin() ); - vecCurrentDirectionOfMovement.z = 0; - VectorNormalize( vecCurrentDirectionOfMovement ); - - float dot = vecCurrentDirectionOfMovement.AsVector2D().Dot( vecToPos.AsVector2D() ); - - return ( m_bForcedSimplify || dot > MIN_ANGLE_COS_SIMPLIFY ); -} - -//------------------------------------- - -bool CAI_Navigator::ShouldSimplifyTo( bool passedDetour, const Vector &pos ) -{ - int flags = AIMLF_QUICK_REJECT; - -#ifndef NPCS_BLOCK_SIMPLIFICATION - if ( !passedDetour ) - flags |= AIMLF_IGNORE_TRANSIENTS; -#endif - - AIMoveTrace_t moveTrace; - GetMoveProbe()->MoveLimit( GetNavType(), - GetLocalOrigin(), pos, MASK_NPCSOLID, - GetPath()->GetTarget(), 100, flags, &moveTrace ); - - return !IsMoveBlocked(moveTrace); -} - -//------------------------------------- - -void CAI_Navigator::SimplifyPathInsertSimplification( AI_Waypoint_t *pSegmentStart, const Vector &point ) -{ - if ( point != pSegmentStart->GetPos() ) - { - AI_Waypoint_t *pNextWaypoint = pSegmentStart->GetNext(); - Assert( pNextWaypoint ); - Assert( pSegmentStart->NavType() == pNextWaypoint->NavType() ); - - AI_Waypoint_t *pNewWaypoint = new AI_Waypoint_t( point, 0, pSegmentStart->NavType(), 0, NO_NODE ); - - while ( GetPath()->GetCurWaypoint() != pNextWaypoint ) - { - Assert( GetPath()->GetCurWaypoint()->IsReducible() ); - GetPath()->Advance(); - } - pNewWaypoint->SetNext( pNextWaypoint ); - GetPath()->SetWaypoints( pNewWaypoint ); - } - else - { - while ( GetPath()->GetCurWaypoint() != pSegmentStart ) - { - Assert( GetPath()->GetCurWaypoint()->IsReducible() ); - GetPath()->Advance(); - } - } - -} - -//------------------------------------- - -bool CAI_Navigator::SimplifyPathForwardScan( const CAI_Navigator::SimplifyForwardScanParams ¶ms, - AI_Waypoint_t *pCurWaypoint, const Vector &curPoint, - float distRemaining, bool skipTest, bool passedDetour, int *pTestCount ) -{ - AI_Waypoint_t *pNextWaypoint = pCurWaypoint->GetNext(); - - if ( !passedDetour ) - passedDetour = ( ( pCurWaypoint->Flags() & bits_WP_TO_DETOUR) != 0 ); - - if ( distRemaining > 0) - { - if ( pCurWaypoint->IsReducible() ) - { - // Walk out to test point, or next waypoint - AI_Waypoint_t *pRecursionWaypoint; - Vector nextPoint; - - float distToNext = ComputePathDistance( GetNavType(), curPoint, pNextWaypoint->GetPos() ); - if (distToNext < params.increment * 1.10 ) - { - nextPoint = pNextWaypoint->GetPos(); - distRemaining -= distToNext; - pRecursionWaypoint = pNextWaypoint; - } - else - { - Vector offset = pNextWaypoint->GetPos() - pCurWaypoint->GetPos(); - VectorNormalize( offset ); - offset *= params.increment; - nextPoint = curPoint + offset; - distRemaining -= params.increment; - pRecursionWaypoint = pCurWaypoint; - } - - bool skipTestNext = ( ComputePathDistance( GetNavType(), GetLocalOrigin(), nextPoint ) > params.radius + 0.1 ); - - if ( SimplifyPathForwardScan( params, pRecursionWaypoint, nextPoint, distRemaining, skipTestNext, passedDetour, pTestCount ) ) - return true; - } - } - - if ( !skipTest && *pTestCount < params.maxSamples && ShouldAttemptSimplifyTo( curPoint ) ) - { - (*pTestCount)++; - - if ( ShouldSimplifyTo( passedDetour, curPoint ) ) - { - SimplifyPathInsertSimplification( pCurWaypoint, curPoint ); - return true; - } - } - - return false; -} - -//------------------------------------- - -bool CAI_Navigator::SimplifyPathForwardScan( const CAI_Navigator::SimplifyForwardScanParams ¶ms ) -{ - AI_Waypoint_t *pCurWaypoint = GetPath()->GetCurWaypoint(); - float distRemaining = params.scanDist - GetPathDistToCurWaypoint(); - int testCount = 0; - - if ( distRemaining < 0.1 ) - return false; - - if ( SimplifyPathForwardScan( params, pCurWaypoint, pCurWaypoint->GetPos(), distRemaining, true, false, &testCount ) ) - return true; - - return false; -} - -//------------------------------------- - -bool CAI_Navigator::SimplifyPathForward( float maxDist ) -{ - AI_Waypoint_t *pCurWaypoint = GetPath()->GetCurWaypoint(); - AI_Waypoint_t *pNextWaypoint = pCurWaypoint->GetNext(); - - if ( !pNextWaypoint ) - return false; - - AI_PROFILE_SCOPE(CAI_Navigator_SimplifyPathForward); - - static SimplifyForwardScanParams fullScanParams = - { - 32 * 12, // Distance to move out path - 12 * 12, // Radius within which a point must be to be valid - 3 * 12, // Increment to move out on - 4, // maximum number of point samples - }; - - SimplifyForwardScanParams scanParams = fullScanParams; - if ( maxDist > fullScanParams.radius ) - { - float ratio = (maxDist / fullScanParams.radius); - - fullScanParams.radius = maxDist; - fullScanParams.scanDist *= ratio; - fullScanParams.increment *= ratio; - } - - if ( SimplifyPathForwardScan( scanParams ) ) - return true; - - if ( ShouldAttemptSimplifyTo( pNextWaypoint->GetPos() ) && - ComputePathDistance( GetNavType(), GetLocalOrigin(), pNextWaypoint->GetPos() ) < scanParams.scanDist && - ShouldSimplifyTo( ( ( pCurWaypoint->Flags() & bits_WP_TO_DETOUR ) != 0 ), pNextWaypoint->GetPos() ) ) // @TODO (toml 04-25-03): need to handle this better. this is here because forward scan may look out so far that a close obvious solution is skipped (due to test limiting) - { - delete pCurWaypoint; - GetPath()->SetWaypoints(pNextWaypoint); - return true; - } - - return false; -} - -//------------------------------------- - -bool CAI_Navigator::SimplifyPathBacktrack() -{ - AI_PROFILE_SCOPE(CAI_Navigator_SimplifyPathBacktrack); - - AI_Waypoint_t *pCurWaypoint = GetPath()->GetCurWaypoint(); - AI_Waypoint_t *pNextWaypoint = pCurWaypoint->GetNext(); - - // ------------------------------------------------------------------------ - // If both waypoints are ground waypoints and my path sends me back tracking - // more than 24 inches, try to aim for (roughly) the nearest point on the line - // connecting the first two waypoints - // ------------------------------------------------------------------------ - if (pCurWaypoint->GetNext() && - (pNextWaypoint->Flags() & bits_WP_TO_NODE) && - (pNextWaypoint->NavType() == NAV_GROUND) && - (pCurWaypoint->NavType() == NAV_GROUND) && - (pCurWaypoint->Flags() & bits_WP_TO_NODE) ) - { - - Vector firstToMe = (GetLocalOrigin() - pCurWaypoint->GetPos()); - Vector firstToNext = pNextWaypoint->GetPos() - pCurWaypoint->GetPos(); - VectorNormalize(firstToNext); - firstToMe.z = 0; - firstToNext.z = 0; - float firstDist = firstToMe.Length(); - float firstProj = DotProduct(firstToMe,firstToNext); - float goalTolerance = GetPath()->GetGoalTolerance(); - if (firstProj>0.5*firstDist) - { - Vector targetPos = pCurWaypoint->GetPos() + (firstProj * firstToNext); - - // Only use a local or jump move - int buildFlags = 0; - if (CapabilitiesGet() & bits_CAP_MOVE_GROUND) - buildFlags |= bits_BUILD_GROUND; - if (CapabilitiesGet() & bits_CAP_MOVE_JUMP) - buildFlags |= bits_BUILD_JUMP; - - // Make sure I can get to the new point - AI_Waypoint_t *route1 = GetPathfinder()->BuildLocalRoute(GetLocalOrigin(), targetPos, GetPath()->GetTarget(), bits_WP_TO_DETOUR, NO_NODE, buildFlags, goalTolerance); - if (!route1) - return false; - - // Make sure the new point gets me to the target location - AI_Waypoint_t *route2 = GetPathfinder()->BuildLocalRoute(targetPos, pNextWaypoint->GetPos(), GetPath()->GetTarget(), bits_WP_TO_DETOUR, NO_NODE, buildFlags, goalTolerance); - if (!route2) - { - DeleteAll(route1); - return false; - } - - // Add the two route together - AddWaypointLists(route1,route2); - - // Now add the rest of the old route to the new one - AddWaypointLists(route1,pNextWaypoint->GetNext()); - - // Now advance the route linked list, putting the finished waypoints back in the waypoint pool - AI_Waypoint_t *freeMe = pCurWaypoint->GetNext(); - delete pCurWaypoint; - delete freeMe; - - GetPath()->SetWaypoints(route1); - return true; - } - } - return false; -} - -//------------------------------------- - -bool CAI_Navigator::SimplifyPathQuick() -{ - AI_PROFILE_SCOPE(CAI_Navigator_SimplifyPathQuick); - - static SimplifyForwardScanParams quickScanParams[2] = - { - { - (12.0 * 12.0) - 0.1, // Distance to move out path - 12 * 12, // Radius within which a point must be to be valid - 0.5 * 12, // Increment to move out on - 1, // maximum number of point samples - }, - // Strong optimization version - { - (6.0 * 12.0) - 0.1, // Distance to move out path - 8 * 12, // Radius within which a point must be to be valid - 1.0 * 12, // Increment to move out on - 1, // maximum number of point samples - } - }; - - if ( SimplifyPathForwardScan( quickScanParams[AIStrongOpt()] ) ) - return true; - - return false; -} - -//------------------------------------- - -// Second entry is the strong opt version -const float ROUTE_SIMPLIFY_TIME_DELAY[2] = { 0.5, 1.0f }; -const float NO_PVS_ROUTE_SIMPLIFY_TIME_DELAY[2] = { 1.0, 2.0f }; -const float QUICK_SIMPLIFY_TIME_DELAY[2] = { FLT_MIN, 0.3f }; - -int g_iFrameLastSimplified; - -bool CAI_Navigator::SimplifyPath( bool bFirstForPath, float scanDist ) -{ - AI_PROFILE_SCOPE(CAI_Navigator_SimplifyPath); - - if ( TestingSteering() || IsSimplifyPathDisabled() ) - return false; - - bool bInPVS = GetOuter()->HasCondition( COND_IN_PVS ); - bool bRetVal = false; - - Navigation_t navType = GetOuter()->GetNavType(); - if (navType == NAV_GROUND || navType == NAV_FLY) - { - AI_Waypoint_t *pCurWaypoint = GetPath()->GetCurWaypoint(); - if ( !pCurWaypoint || !pCurWaypoint->IsReducible() ) - return false; - - //----------------------------- - - bool bFullSimplify; - - bFullSimplify = ( m_flNextSimplifyTime <= gpGlobals->curtime ); - - if ( bFirstForPath && !bFullSimplify ) - { - bFullSimplify = bInPVS; - } - - if ( AIStrongOpt() && bFullSimplify ) - { - if ( g_iFrameLastSimplified != gpGlobals->framecount ) - { - g_iFrameLastSimplified = gpGlobals->framecount; - } - else - { - bFullSimplify = false; - } - } - - m_bForcedSimplify = bFirstForPath; - - //----------------------------- - - if ( bFullSimplify ) - { - float simplifyDelay = ( bInPVS ) ? ROUTE_SIMPLIFY_TIME_DELAY[AIStrongOpt()] : NO_PVS_ROUTE_SIMPLIFY_TIME_DELAY[AIStrongOpt()]; - - if ( GetOuter()->GetMoveEfficiency() > AIME_NORMAL ) - simplifyDelay *= 2; - - m_flNextSimplifyTime = gpGlobals->curtime + simplifyDelay; - - if ( SimplifyPathForward( scanDist ) ) - bRetVal = true; - else if ( SimplifyPathBacktrack() ) - bRetVal = true; - else if ( SimplifyPathQuick() ) - bRetVal = true; - } - else if ( bFirstForPath || ( bInPVS && GetOuter()->GetMoveEfficiency() == AIME_NORMAL ) ) - { - if ( !AIStrongOpt() || gpGlobals->curtime - m_flLastSuccessfulSimplifyTime > QUICK_SIMPLIFY_TIME_DELAY[AIStrongOpt()] ) - { - if ( SimplifyPathQuick() ) - bRetVal = true; - } - } - } - - if ( bRetVal ) - { - m_flLastSuccessfulSimplifyTime = gpGlobals->curtime; - DbgNavMsg( GetOuter(), "Simplified path\n" ); - } - - return bRetVal; -} -//----------------------------------------------------------------------------- - -AI_NavPathProgress_t CAI_Navigator::ProgressFlyPath( const AI_ProgressFlyPathParams_t ¶ms ) -{ - if ( IsGoalActive() ) - { - float waypointDist = ( GetCurWaypointPos() - GetLocalOrigin() ).Length(); - - if ( CurWaypointIsGoal() ) - { - float tolerance = MAX( params.goalTolerance, GetPath()->GetGoalTolerance() ); - if ( waypointDist <= tolerance ) - return AINPP_COMPLETE; - } - else - { - bool bIsStrictWaypoint = ( (GetPath()->CurWaypointFlags() & (bits_WP_TO_PATHCORNER|bits_WP_DONT_SIMPLIFY) ) != 0 ); - float tolerance = (bIsStrictWaypoint) ? params.strictPointTolerance : params.waypointTolerance; - if ( waypointDist <= tolerance ) - { - trace_t tr; - AI_TraceLine( GetAbsOrigin(), GetPath()->GetCurWaypoint()->GetNext()->GetPos(), MASK_NPCSOLID, GetOuter(), COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction == 1.0f ) - { - AdvancePath(); - return AINPP_ADVANCED; - } - } - - if ( SimplifyFlyPath( params ) ) - return AINPP_ADVANCED; - } - } - - return AINPP_NO_CHANGE; -} - -//----------------------------------------------------------------------------- - -void CAI_Navigator::SimplifyFlyPath( unsigned collisionMask, const CBaseEntity *pTarget, - float strictPointTolerance, float blockTolerance, - AI_NpcBlockHandling_t blockHandling) -{ - AI_ProgressFlyPathParams_t params( collisionMask, strictPointTolerance, blockTolerance, - 0, 0, blockHandling ); - params.SetCurrent( pTarget ); - SimplifyFlyPath( params ); -} - -//----------------------------------------------------------------------------- - -#define FLY_ROUTE_SIMPLIFY_TIME_DELAY 0.3 -#define FLY_ROUTE_SIMPLIFY_LOOK_DIST (12.0*12.0) - -bool CAI_Navigator::SimplifyFlyPath( const AI_ProgressFlyPathParams_t ¶ms ) -{ - if ( !GetPath()->GetCurWaypoint() ) - return false; - - if ( m_flNextSimplifyTime > gpGlobals->curtime) - return false; - - m_flNextSimplifyTime = gpGlobals->curtime + FLY_ROUTE_SIMPLIFY_TIME_DELAY; - - if ( params.bTrySimplify && SimplifyPathForward( FLY_ROUTE_SIMPLIFY_LOOK_DIST ) ) - return true; - - // don't shorten path_corners - bool bIsStrictWaypoint = ( !params.bTrySimplify || ( (GetPath()->CurWaypointFlags() & (bits_WP_TO_PATHCORNER|bits_WP_DONT_SIMPLIFY) ) != 0 ) ); - - Vector dir = GetCurWaypointPos() - GetLocalOrigin(); - float length = VectorNormalize( dir ); - - if ( !bIsStrictWaypoint || length < params.strictPointTolerance ) - { - // FIXME: This seems strange... Why should this condition ever be met? - // Don't advance your waypoint if you don't have one! - if (GetPath()->CurWaypointIsGoal()) - return false; - - AIMoveTrace_t moveTrace; - GetMoveProbe()->MoveLimit( NAV_FLY, GetLocalOrigin(), GetPath()->NextWaypointPos(), - params.collisionMask, params.pTarget, &moveTrace); - - if ( moveTrace.flDistObstructed - params.blockTolerance < 0.01 || - ( ( params.blockHandling == AISF_IGNORE) && ( moveTrace.fStatus == AIMR_BLOCKED_NPC ) ) ) - { - AdvancePath(); - return true; - } - else if ( moveTrace.pObstruction && params.blockHandling == AISF_AVOID ) - { - PrependLocalAvoidance( params.blockTolerance - moveTrace.flDistObstructed, moveTrace ); - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -float CAI_Navigator::MovementCost( int moveType, Vector &vecStart, Vector &vecEnd ) -{ - float cost; - - cost = (vecStart - vecEnd).Length(); - - if ( moveType == bits_CAP_MOVE_JUMP || moveType == bits_CAP_MOVE_CLIMB ) - { - cost *= 2.0; - } - - // Allow the NPC to override the movement cost - GetOuter()->MovementCost( moveType, vecStart, vecEnd, &cost ); - - return cost; -} - -//----------------------------------------------------------------------------- -// Purpose: Will the entities hull fit at the given node -// Input : -// Output : Returns true if hull fits at node -//----------------------------------------------------------------------------- -bool CAI_Navigator::CanFitAtNode(int nodeNum, unsigned int collisionMask ) -{ - // Make sure I have a network - if (!GetNetwork()) - { - DevMsg("CanFitAtNode() called with no network!\n"); - return false; - } - - CAI_Node* pTestNode = GetNetwork()->GetNode(nodeNum); - Vector startPos = pTestNode->GetPosition(GetHullType()); - - // ------------------------------------------------------------------- - // Check ground nodes for standable bottom - // ------------------------------------------------------------------- - if (pTestNode->GetType() == NODE_GROUND) - { - if (!GetMoveProbe()->CheckStandPosition( startPos, collisionMask )) - { - return false; - } - } - - - // ------------------------------------------------------------------- - // Check climb exit nodes for standable bottom - // ------------------------------------------------------------------- - if ((pTestNode->GetType() == NODE_CLIMB) && - (pTestNode->m_eNodeInfo & (bits_NODE_CLIMB_BOTTOM | bits_NODE_CLIMB_EXIT ))) - { - if (!GetMoveProbe()->CheckStandPosition( startPos, collisionMask )) - { - return false; - } - } - - - // ------------------------------------------------------------------- - // Check that hull fits at position of node - // ------------------------------------------------------------------- - if (!CanFitAtPosition( startPos, collisionMask )) - { - startPos.z += GetOuter()->StepHeight(); - if (!CanFitAtPosition( startPos, collisionMask )) - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true if NPC's hull fits in the given spot with the -// given collision mask -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CAI_Navigator::CanFitAtPosition( const Vector &vStartPos, unsigned int collisionMask, bool bIgnoreTransients, bool bAllowPlayerAvoid ) -{ - CTraceFilterNav traceFilter( const_cast(GetOuter()), bIgnoreTransients, GetOuter(), COLLISION_GROUP_NONE, bAllowPlayerAvoid ); - - Vector vEndPos = vStartPos; - vEndPos.z += 0.01; - trace_t tr; - AI_TraceHull( vStartPos, vEndPos, - GetHullMins(), GetHullMaxs(), - collisionMask, - &traceFilter, - &tr ); - - if (tr.startsolid) - { - return false; - } - return true; -} - -//----------------------------------------------------------------------------- - -float CAI_Navigator::GetPathDistToCurWaypoint() const -{ - return ( GetPath()->GetCurWaypoint() ) ? - ComputePathDistance( GetNavType(), GetLocalOrigin(), GetPath()->CurWaypointPos() ) : - 0; -} - - -//----------------------------------------------------------------------------- -// Computes the distance to our goal, rebuilding waypoint distances if necessary. -// Returns -1 if we still don't have a valid path length after rebuilding. -// -// NOTE: this should really be part of GetPathDistToGoal below, but I didn't -// want to affect OnFailedSteer this close to shipping! (dvs: 8/16/07) -//----------------------------------------------------------------------------- -float CAI_Navigator::BuildAndGetPathDistToGoal() -{ - if ( !GetPath() ) - return -1; - - // Make sure it's fresh. - GetPath()->GetPathLength(); - - if ( GetPath()->GetCurWaypoint() && ( GetPath()->GetCurWaypoint()->flPathDistGoal >= 0 ) ) - return GetPathDistToGoal(); - - return -1; -} - - -// FIXME: this ignores the fact that flPathDistGoal might be -1, yielding nonsensical results. -// See BuildAndGetPathDistToGoal above. -float CAI_Navigator::GetPathDistToGoal() const -{ - return ( GetPath()->GetCurWaypoint() ) ? - ( GetPathDistToCurWaypoint() + GetPath()->GetCurWaypoint()->flPathDistGoal ) : - 0; -} - - -//----------------------------------------------------------------------------- -// Purpose: Attempts to build a route -// Input : -// Output : True if successful / false if fail -//----------------------------------------------------------------------------- -bool CAI_Navigator::FindPath( bool fSignalTaskStatus, bool bDontIgnoreBadLinks ) -{ - // Test to see if we're resolving spiking problems via threading - if ( ai_navigator_generate_spikes.GetBool() ) - { - unsigned int nLargeCount = (INT_MAX>>(ai_navigator_generate_spikes_strength.GetInt())); - while ( nLargeCount-- ) {} - } - - bool bRetrying = (HasMemory(bits_MEMORY_PATH_FAILED) && m_timePathRebuildMax != 0 ); - if ( bRetrying ) - { - // If I've passed by fail time, fail this task - if (m_timePathRebuildFail < gpGlobals->curtime) - { - if ( fSignalTaskStatus ) - OnNavFailed( FAIL_NO_ROUTE ); - else - OnNavFailed(); - return false; - } - else if ( m_timePathRebuildNext > gpGlobals->curtime ) - { - return false; - } - } - - bool bFindResult = DoFindPath(); - - if ( !bDontIgnoreBadLinks && !bFindResult && GetOuter()->IsNavigationUrgent() ) - { - GetPathfinder()->SetIgnoreBadLinks(); - bFindResult = DoFindPath(); - } - - if (bFindResult) - { - Forget(bits_MEMORY_PATH_FAILED); - - if (fSignalTaskStatus) - { - TaskComplete(); - } - return true; - } - - if (m_timePathRebuildMax == 0) - { - if ( fSignalTaskStatus ) - OnNavFailed( FAIL_NO_ROUTE ); - else - OnNavFailed(); - return false; - } - else - { - if ( !bRetrying ) - { - Remember(bits_MEMORY_PATH_FAILED); - m_timePathRebuildFail = gpGlobals->curtime + m_timePathRebuildMax; - } - m_timePathRebuildNext = gpGlobals->curtime + m_timePathRebuildDelay; - return false; - } - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Called when route fails. Marks last link on which that failure -// occured as stale so when then next node route is build that link -// will be explictly checked for blockages -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CAI_Navigator::MarkCurWaypointFailedLink( void ) -{ - if ( TestingSteering() ) - return false; - - if ( !m_fRememberStaleNodes ) - return false; - - // Prevent a crash in release - if( !GetPath() || !GetPath()->GetCurWaypoint() ) - return false; - - bool didMark = false; - - int startID = GetPath()->GetLastNodeReached(); - int endID = GetPath()->GetCurWaypoint()->iNodeID; - - if ( endID != NO_NODE ) - { - bool bBlockAll = false; - - if ( m_hLastBlockingEnt != NULL && - !m_hLastBlockingEnt->IsPlayer() && !m_hLastBlockingEnt->IsNPC() && - m_hLastBlockingEnt->GetMoveType() == MOVETYPE_VPHYSICS && - m_hLastBlockingEnt->VPhysicsGetObject() && - ( !m_hLastBlockingEnt->VPhysicsGetObject()->IsMoveable() || - m_hLastBlockingEnt->VPhysicsGetObject()->GetMass() > 200 ) ) - { - // Make sure it's a "large" object - // - One dimension is >40 - // - Other 2 dimensions are >30 - CCollisionProperty *pCollisionProp = m_hLastBlockingEnt->CollisionProp(); - bool bFoundLarge = false; - bool bFoundSmall = false; - Vector vecSize = pCollisionProp->OBBMaxs() - pCollisionProp->OBBMins(); - for ( int i = 0; i < 3; i++ ) - { - if ( vecSize[i] > 40 ) - { - bFoundLarge = true; - } - - if ( vecSize[i] < 30 ) - { - bFoundSmall = true; - break; - } - } - - if ( bFoundLarge && !bFoundSmall ) - { - Vector vStartPos = GetNetwork()->GetNode( endID )->GetPosition( GetHullType() ); - Vector vEndPos = vStartPos; - vEndPos.z += 0.01; - trace_t tr; - - UTIL_TraceModel( vStartPos, vEndPos, GetHullMins(), GetHullMaxs(), m_hLastBlockingEnt, COLLISION_GROUP_NONE, &tr ); - - if ( tr.startsolid ) - bBlockAll = true; - } - } - - if ( bBlockAll ) - { - CAI_Node *pDestNode = GetNetwork()->GetNode( endID ); - for ( int i = 0; i < pDestNode->NumLinks(); i++ ) - { - CAI_Link *pLink = pDestNode->GetLinkByIndex( i ); - pLink->m_LinkInfo |= bits_LINK_STALE_SUGGESTED; - pLink->m_timeStaleExpires = gpGlobals->curtime + 4.0; - didMark = true; - } - - } - else if ( startID != NO_NODE ) - { - // Find link and mark it as stale - CAI_Node *pNode = GetNetwork()->GetNode(startID); - CAI_Link *pLink = pNode->GetLink( endID ); - if ( pLink ) - { - pLink->m_LinkInfo |= bits_LINK_STALE_SUGGESTED; - pLink->m_timeStaleExpires = gpGlobals->curtime + 4.0; - didMark = true; - } - } - } - - return didMark; -} - -//----------------------------------------------------------------------------- -// Purpose: Builds a route to the given vecGoal using either local movement -// or nodes -// Input : -// Output : True is route was found, false otherwise -//----------------------------------------------------------------------------- - -bool CAI_Navigator::DoFindPathToPos(void) -{ - CAI_Path * pPath = GetPath(); - CAI_Pathfinder *pPathfinder = GetPathfinder(); - const Vector & actualGoalPos = pPath->ActualGoalPosition(); - CBaseEntity * pTarget = pPath->GetTarget(); - float tolerance = pPath->GetGoalTolerance(); - Vector origin; - - if ( gpGlobals->curtime - m_flTimeClipped > 0.11 || m_bLastNavFailed ) - m_pClippedWaypoints->RemoveAll(); - - if ( m_pClippedWaypoints->IsEmpty() ) - origin = GetLocalOrigin(); - else - { - AI_Waypoint_t *pLastClipped = m_pClippedWaypoints->GetLast(); - origin = pLastClipped->GetPos(); - } - - m_bLastNavFailed = false; - - pPath->ClearWaypoints(); - - AI_Waypoint_t *pFirstWaypoint = pPathfinder->BuildRoute( origin, actualGoalPos, pTarget, tolerance, GetNavType(), m_bLocalSucceedOnWithinTolerance ); - - if (!pFirstWaypoint) - { - // Sorry no path - return false; - } - - pPath->SetWaypoints( pFirstWaypoint ); - - if ( ShouldTestFailPath() ) - { - pPath->ClearWaypoints(); - return false; - } - - if ( !m_pClippedWaypoints->IsEmpty() ) - { - AI_Waypoint_t *pFirstClipped = m_pClippedWaypoints->GetFirst(); - m_pClippedWaypoints->Set( NULL ); - pFirstClipped->ModifyFlags( bits_WP_DONT_SIMPLIFY, true ); - pPath->PrependWaypoints( pFirstClipped ); - pFirstWaypoint = pFirstClipped; - } - - if ( pFirstWaypoint->IsReducible() && pFirstWaypoint->GetNext() && pFirstWaypoint->GetNext()->NavType() == GetNavType() && - ShouldOptimizeInitialPathSegment( pFirstWaypoint ) ) - { - // If we're seemingly beyond the waypoint, and our hull is over the line, move on - const float EPS = 0.1; - Vector vClosest; - CalcClosestPointOnLineSegment( origin, - pFirstWaypoint->GetPos(), pFirstWaypoint->GetNext()->GetPos(), - vClosest ); - if ( ( pFirstWaypoint->GetPos() - vClosest ).Length() > EPS && - ( origin - vClosest ).Length() < GetHullWidth() * 0.5 ) - { - pPath->Advance(); - } - } - - return true; -} - - -//----------------------------------------------------------------------------- - -CBaseEntity *CAI_Navigator::GetNextPathcorner( CBaseEntity *pPathCorner ) -{ - CBaseEntity *pNextPathCorner = NULL; - - Assert( pPathCorner ); - if ( pPathCorner ) - { - pNextPathCorner = pPathCorner->GetNextTarget(); - - CAI_Hint *pHint; - if ( !pNextPathCorner && ( pHint = dynamic_cast( pPathCorner ) ) != NULL ) - { - int targetNode = pHint->GetTargetNode(); - if ( targetNode != NO_NODE ) - { - CAI_Node *pTestNode = GetNetwork()->GetNode(targetNode); - pNextPathCorner = pTestNode->GetHint(); - } - } - } - - return pNextPathCorner; -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::DoFindPathToPathcorner( CBaseEntity *pPathCorner ) -{ -// UNDONE: This is broken -// UNDONE: Remove this and change the pathing code to be able to refresh itself and support -// circular paths, etc. - bool returnCode = false; - Assert( GetPath()->GoalType() == GOALTYPE_PATHCORNER ); - - // NPC is on a path_corner loop - if ( pPathCorner != NULL ) - { - // Find path to first pathcorner - if ( ( GetGoalFlags() & AIN_NO_PATHCORNER_PATHFINDING ) || m_bNoPathcornerPathfinds ) - { - // HACKHACK: If the starting path_corner has a speed, copy that to the entity - if ( pPathCorner->m_flSpeed != 0 ) - SetSpeed( pPathCorner->m_flSpeed ); - - GetPath()->ClearWaypoints(); - - AI_Waypoint_t *pRoute = new AI_Waypoint_t( pPathCorner->GetLocalOrigin(), 0, GetNavType(), bits_WP_TO_PATHCORNER, NO_NODE ); - pRoute->hPathCorner = pPathCorner; - AI_Waypoint_t *pLast = pRoute; - pPathCorner = GetNextPathcorner(pPathCorner); - if ( pPathCorner ) - { - pLast = new AI_Waypoint_t( pPathCorner->GetLocalOrigin(), 0, GetNavType(), bits_WP_TO_PATHCORNER, NO_NODE ); - pLast->hPathCorner = pPathCorner; - pRoute->SetNext(pLast); - } - pLast->ModifyFlags( bits_WP_TO_GOAL, true ); - GetPath()->SetWaypoints( pRoute, true ); - returnCode = true; - } - else - { - Vector initPos = pPathCorner->GetLocalOrigin(); - - TranslateNavGoal( pPathCorner, initPos ); - - GetPath()->ResetGoalPosition( initPos ); - - float tolerance = GetPath()->GetGoalTolerance(); - float outerTolerance = GetOuter()->GetDefaultNavGoalTolerance(); - if ( outerTolerance > tolerance ) - { - GetPath()->SetGoalTolerance( outerTolerance ); - tolerance = outerTolerance; - } - - if ( ( returnCode = DoFindPathToPos() ) != false ) - { - // HACKHACK: If the starting path_corner has a speed, copy that to the entity - if ( pPathCorner->m_flSpeed != 0 ) - { - SetSpeed( pPathCorner->m_flSpeed ); - } - - AI_Waypoint_t *lastWaypoint = GetPath()->GetGoalWaypoint(); - Assert(lastWaypoint); - - lastWaypoint->ModifyFlags( bits_WP_TO_PATHCORNER, true ); - lastWaypoint->hPathCorner = pPathCorner; - - pPathCorner = GetNextPathcorner(pPathCorner); // first already accounted for in pathfind - if ( pPathCorner ) - { - // Place a dummy node in that will be used to signal the next pathfind, also prevents - // animation system from decellerating when approaching a pathcorner - lastWaypoint->ModifyFlags( bits_WP_TO_GOAL, false ); - // BRJ 10/4/02 - // FIXME: I'm not certain about the navtype here - AI_Waypoint_t *curWaypoint = new AI_Waypoint_t( pPathCorner->GetLocalOrigin(), 0, GetNavType(), (bits_WP_TO_PATHCORNER | bits_WP_TO_GOAL), NO_NODE ); - Vector waypointPos = curWaypoint->GetPos(); - TranslateNavGoal( pPathCorner, waypointPos ); - curWaypoint->SetPos( waypointPos ); - GetPath()->SetGoalTolerance( tolerance ); - curWaypoint->hPathCorner = pPathCorner; - lastWaypoint->SetNext(curWaypoint); - GetPath()->ResetGoalPosition( curWaypoint->GetPos() ); - } - } - } - } - return returnCode; -} - -//----------------------------------------------------------------------------- -// Purpose: Attemps to find a route -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CAI_Navigator::DoFindPath( void ) -{ - AI_PROFILE_SCOPE(CAI_Navigator_DoFindPath); - - DbgNavMsg( GetOuter(), "Finding new path\n" ); - - GetPath()->ClearWaypoints(); - - bool returnCode; - - returnCode = false; - - switch( GetPath()->GoalType() ) - { - case GOALTYPE_PATHCORNER: - { - returnCode = DoFindPathToPathcorner( GetGoalEnt() ); - } - break; - - case GOALTYPE_ENEMY: - { - // NOTE: This is going to set the goal position, which was *not* - // set in SetGoal for this movement type - CBaseEntity *pEnemy = GetPath()->GetTarget(); - if (pEnemy) - { - Assert( pEnemy == GetEnemy() ); - - Vector newPos = GetEnemyLKP(); - - float tolerance = GetPath()->GetGoalTolerance(); - float outerTolerance = GetOuter()->GetDefaultNavGoalTolerance(); - if ( outerTolerance > tolerance ) - { - GetPath()->SetGoalTolerance( outerTolerance ); - tolerance = outerTolerance; - } - - TranslateNavGoal( pEnemy, newPos ); - - // NOTE: Calling reset here because this can get called - // any time we have to update our goal position - GetPath()->ResetGoalPosition( newPos ); - GetPath()->SetGoalTolerance( tolerance ); - - returnCode = DoFindPathToPos(); - } - } - break; - - case GOALTYPE_LOCATION: - case GOALTYPE_FLANK: - case GOALTYPE_COVER: - returnCode = DoFindPathToPos(); - break; - - case GOALTYPE_LOCATION_NEAREST_NODE: - { - int myNodeID; - int destNodeID; - - returnCode = false; - - myNodeID = GetPathfinder()->NearestNodeToNPC(); - if (myNodeID != NO_NODE) - { - destNodeID = GetPathfinder()->NearestNodeToPoint( GetPath()->ActualGoalPosition() ); - if (destNodeID != NO_NODE) - { - AI_Waypoint_t *pRoute = GetPathfinder()->FindBestPath( myNodeID, destNodeID ); - - if ( pRoute != NULL ) - { - GetPath()->SetWaypoints( pRoute ); - GetPath()->SetLastNodeAsGoal(true); - returnCode = true; - } - } - } - } - break; - - case GOALTYPE_TARGETENT: - { - // NOTE: This is going to set the goal position, which was *not* - // set in SetGoal for this movement type - CBaseEntity *pTarget = GetPath()->GetTarget(); - - if ( pTarget ) - { - Assert( pTarget == GetTarget() ); - - // NOTE: Calling reset here because this can get called - // any time we have to update our goal position - - Vector initPos = pTarget->GetAbsOrigin(); - TranslateNavGoal( pTarget, initPos ); - - GetPath()->ResetGoalPosition( initPos ); - returnCode = DoFindPathToPos(); - } - } - break; - - default: - break; - } - - return returnCode; -} - -//----------------------------------------------------------------------------- - -void CAI_Navigator::ClearPath( void ) -{ - OnClearPath(); - - m_timePathRebuildMax = 0; // How long to try rebuilding path before failing task - m_timePathRebuildFail = 0; // Current global time when should fail building path - m_timePathRebuildNext = 0; // Global time to try rebuilding again - m_timePathRebuildDelay = 0; // How long to wait before trying to rebuild again - - Forget( bits_MEMORY_PATH_FAILED ); - - AI_Waypoint_t *pWaypoint = GetPath()->GetCurWaypoint(); - - if ( pWaypoint ) - { - SaveStoppingPath(); - m_PreviousMoveActivity = GetMovementActivity(); - m_PreviousArrivalActivity = GetArrivalActivity(); - - if( m_pClippedWaypoints && m_pClippedWaypoints->GetFirst() ) - { - Assert( m_PreviousMoveActivity > ACT_RESET ); - } - - while ( pWaypoint ) - { - if ( pWaypoint->iNodeID != NO_NODE ) - { - CAI_Node *pNode = GetNetwork()->GetNode(pWaypoint->iNodeID); - - if ( pNode ) - { - if ( pNode->IsLocked() ) - pNode->Unlock(); - } - } - pWaypoint = pWaypoint->GetNext(); - } - } - - GetPath()->Clear(); -} - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::GetStoppingPath( CAI_WaypointList * pClippedWaypoints ) -{ - pClippedWaypoints->RemoveAll(); - - AI_Waypoint_t *pCurWaypoint = GetPath()->GetCurWaypoint(); - if ( pCurWaypoint ) - { - bool bMustCompleteCurrent = ( pCurWaypoint->NavType() == NAV_CLIMB || pCurWaypoint->NavType() == NAV_JUMP ); - float distRemaining = GetMotor()->MinStoppingDist( 0 ); - - if ( bMustCompleteCurrent ) - { - float distToCurrent = ComputePathDistance( pCurWaypoint->NavType(), GetLocalOrigin(), pCurWaypoint->GetPos() ); - if ( pCurWaypoint->NavType() == NAV_CLIMB ) - { - if ( pCurWaypoint->GetNext() && pCurWaypoint->GetNext()->NavType() == NAV_CLIMB ) - distToCurrent += ComputePathDistance( NAV_CLIMB, pCurWaypoint->GetPos(), pCurWaypoint->GetNext()->GetPos() ); - distToCurrent += GetHullWidth() * 2.0; - } - - if ( distToCurrent > distRemaining ) - distRemaining = distToCurrent; - } - - if ( bMustCompleteCurrent || distRemaining > 0.1 ) - { - Vector vPosPrev = GetLocalOrigin(); - AI_Waypoint_t *pNextPoint = pCurWaypoint; - AI_Waypoint_t *pSavedWaypoints = NULL; - AI_Waypoint_t *pLastSavedWaypoint = NULL; - AI_Waypoint_t *pNewWaypoint; - - while ( distRemaining > 0.01 && pNextPoint ) - { - if ( ( pNextPoint->NavType() == NAV_CLIMB || pNextPoint->NavType() == NAV_JUMP ) && - !bMustCompleteCurrent ) - { - break; - } - -#if PARANOID_NAV_CHECK_ON_MOMENTUM - if ( !CanFitAtPosition( pNextPoint->GetPos(), MASK_NPCSOLID ) ) - { - break; - } -#endif - - if ( pNextPoint->NavType() != NAV_CLIMB || !pNextPoint->GetNext() || pNextPoint->GetNext()->NavType() != NAV_CLIMB ) - bMustCompleteCurrent = false; - - float distToNext = ComputePathDistance( pNextPoint->NavType(), vPosPrev, pNextPoint->GetPos() ); - - if ( distToNext <= distRemaining + 0.01 ) - { - pNewWaypoint = new AI_Waypoint_t(*pNextPoint); - - if ( pNewWaypoint->Flags() & bits_WP_TO_PATHCORNER ) - { - pNewWaypoint->ModifyFlags( bits_WP_TO_PATHCORNER, false ); - pNewWaypoint->hPathCorner = NULL; - } - - pNewWaypoint->ModifyFlags( bits_WP_TO_GOAL | bits_WP_TO_NODE, false ); - pNewWaypoint->iNodeID = NO_NODE; - - if ( pLastSavedWaypoint ) - pLastSavedWaypoint->SetNext( pNewWaypoint ); - else - pSavedWaypoints = pNewWaypoint; - pLastSavedWaypoint = pNewWaypoint; - - vPosPrev = pNextPoint->GetPos(); - -// NDebugOverlay::Cross3D( vPosPrev, 16, 255, 255, 0, false, 10.0f ); - - pNextPoint = pNextPoint->GetNext(); - distRemaining -= distToNext; - } - else - { - Assert( !( pNextPoint->NavType() == NAV_CLIMB || pNextPoint->NavType() == NAV_JUMP ) ); - Vector remainder = pNextPoint->GetPos() - vPosPrev; - VectorNormalize( remainder ); - float yaw = UTIL_VecToYaw( remainder ); - remainder *= distRemaining; - remainder += vPosPrev; - - AIMoveTrace_t trace; - if ( GetMoveProbe()->MoveLimit( pNextPoint->NavType(), vPosPrev, remainder, MASK_NPCSOLID, NULL, 100, AIMLF_DEFAULT | AIMLF_2D, &trace ) ) - { - pNewWaypoint = new AI_Waypoint_t( trace.vEndPosition, yaw, pNextPoint->NavType(), bits_WP_TO_GOAL, 0); - - if ( pLastSavedWaypoint ) - pLastSavedWaypoint->SetNext( pNewWaypoint ); - else - pSavedWaypoints = pNewWaypoint; - } - - distRemaining = 0; - } - - } - - if ( pSavedWaypoints ) - { - pClippedWaypoints->Set( pSavedWaypoints ); - return true; - } - } - } - return false; -} - -//----------------------------------------------------------------------------- -void CAI_Navigator::IgnoreStoppingPath( void ) -{ - if( m_pClippedWaypoints && m_pClippedWaypoints->GetFirst() ) - { - AI_Waypoint_t *pWaypoint = m_pClippedWaypoints->GetFirst(); - - if( pWaypoint->NavType() != NAV_JUMP && pWaypoint->NavType() != NAV_CLIMB ) - { - m_pClippedWaypoints->RemoveAll(); - } - } -} - -//----------------------------------------------------------------------------- - -ConVar ai_use_clipped_paths( "ai_use_clipped_paths", "1" ); - -void CAI_Navigator::SaveStoppingPath( void ) -{ - m_flTimeClipped = -1; - - m_pClippedWaypoints->RemoveAll(); - AI_Waypoint_t *pCurWaypoint = GetPath()->GetCurWaypoint(); - if ( pCurWaypoint ) - { - if ( ( pCurWaypoint->NavType() == NAV_CLIMB || pCurWaypoint->NavType() == NAV_JUMP ) || ai_use_clipped_paths.GetBool() ) - { - if ( GetStoppingPath( m_pClippedWaypoints ) ) - m_flTimeClipped = gpGlobals->curtime; - } - } -} - - -//----------------------------------------------------------------------------- - -bool CAI_Navigator::SetGoalFromStoppingPath() -{ - if ( m_pClippedWaypoints && m_pClippedWaypoints->IsEmpty() ) - SaveStoppingPath(); - if ( m_pClippedWaypoints && !m_pClippedWaypoints->IsEmpty() ) - { - if ( m_PreviousMoveActivity <= ACT_RESET && GetMovementActivity() <= ACT_RESET ) - { - m_pClippedWaypoints->RemoveAll(); - DevWarning( 2, "%s has a stopping path and no valid. Movement activity: %s (prev %s)\n", GetOuter()->GetDebugName(), ActivityList_NameForIndex(GetMovementActivity()), ActivityList_NameForIndex(m_PreviousMoveActivity) ); - return false; - } - - if ( ( m_pClippedWaypoints->GetFirst()->NavType() == NAV_CLIMB || m_pClippedWaypoints->GetFirst()->NavType() == NAV_JUMP ) ) - { - const Task_t *pCurTask = GetOuter()->GetTask(); - if ( pCurTask && pCurTask->iTask == TASK_STOP_MOVING ) - { - // Clipped paths are used for 2 reasons: Prepending movement that must be finished in the case of climbing/jumping, - // and bringing an NPC to a stop. In the second case, we should never be starting climb or jump movement. - m_pClippedWaypoints->RemoveAll(); - return false; - } - } - - if ( !GetPath()->IsEmpty() ) - GetPath()->ClearWaypoints(); - GetPath()->SetWaypoints( m_pClippedWaypoints->GetFirst(), true ); - m_pClippedWaypoints->Set( NULL ); - GetPath()->SetGoalType( GOALTYPE_NONE ); - GetPath()->SetGoalType( GOALTYPE_LOCATION ); - GetPath()->SetGoalTolerance( NAV_STOP_MOVING_TOLERANCE ); - Assert( GetPath()->GetCurWaypoint() ); - - Assert( m_PreviousMoveActivity != ACT_INVALID ); - - - if ( m_PreviousMoveActivity != ACT_RESET ) - GetPath()->SetMovementActivity( m_PreviousMoveActivity ); - if ( m_PreviousArrivalActivity != ACT_RESET ) - GetPath()->SetArrivalActivity( m_PreviousArrivalActivity ); - return true; - } - return false; -} - -//----------------------------------------------------------------------------- - -static Vector GetRouteColor(Navigation_t navType, int waypointFlags) -{ - if (navType == NAV_JUMP) - { - return Vector(255,0,0); - } - - if (waypointFlags & bits_WP_TO_GOAL) - { - return Vector(200,0,255); - } - - if (waypointFlags & bits_WP_TO_DETOUR) - { - return Vector(0,200,255); - } - - if (waypointFlags & bits_WP_TO_NODE) - { - return Vector(0,0,255); - } - - else //if (waypointBits & bits_WP_TO_PATHCORNER) - { - return Vector(0,255,150); - } -} - - -//----------------------------------------------------------------------------- -// Returns a color for debugging purposes -//----------------------------------------------------------------------------- -static Vector GetWaypointColor(Navigation_t navType) -{ - switch( navType ) - { - case NAV_JUMP: - return Vector(255,90,90); - - case NAV_GROUND: - return Vector(0,255,255); - - case NAV_CLIMB: - return Vector(90,255,255); - - case NAV_FLY: - return Vector(90,90,255); - - default: - return Vector(255,0,0); - } -} - -//----------------------------------------------------------------------------- - -void CAI_Navigator::DrawDebugRouteOverlay(void) -{ - AI_Waypoint_t *waypoint = GetPath()->GetCurWaypoint(); - - if (waypoint) - { - Vector RGB = GetRouteColor(waypoint->NavType(), waypoint->Flags()); - NDebugOverlay::Line(GetLocalOrigin(), waypoint->GetPos(), (int)RGB[0], (int)RGB[1], (int)RGB[2], true,0); - } - - while (waypoint) - { - Vector RGB = GetWaypointColor(waypoint->NavType()); - NDebugOverlay::Box(waypoint->GetPos(), Vector(-3,-3,-3), Vector(3,3,3), (int)RGB[0], (int)RGB[1], (int)RGB[2], true, 0); - - if (waypoint->GetNext()) - { - Vector RGB = GetRouteColor(waypoint->GetNext()->NavType(), waypoint->GetNext()->Flags()); - NDebugOverlay::Line(waypoint->GetPos(), waypoint->GetNext()->GetPos(), (int)RGB[0], (int)RGB[1], (int)RGB[2], true, 0); - } - waypoint = waypoint->GetNext(); - } - - if ( GetPath()->GoalType() != GOALTYPE_NONE ) - { - Vector vecGoalPos = GetPath()->ActualGoalPosition(); - Vector vecGoalDir = GetPath()->GetGoalDirection( GetOuter()->GetAbsOrigin() ); - NDebugOverlay::Line( vecGoalPos, vecGoalPos + vecGoalDir * 32, 0,0,255, true, 2.0 ); - - float flYaw = UTIL_VecToYaw( vecGoalDir ); - NDebugOverlay::Text( vecGoalPos, CFmtStr("yaw: %f", flYaw), true, 1 ); - } -} - -//----------------------------------------------------------------------------- diff --git a/game/server/ai_navigator.h b/game/server/ai_navigator.h deleted file mode 100644 index 498fab256..000000000 --- a/game/server/ai_navigator.h +++ /dev/null @@ -1,751 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_NAVIGATOR_H -#define AI_NAVIGATOR_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "simtimer.h" -#include "ai_component.h" -#include "ai_navgoaltype.h" -#include "ai_navtype.h" -#include "ai_motor.h" - -class CAI_BaseNPC; -class CAI_Motor; -class CAI_Route; -class CAI_Path; -class CAI_Pathfinder; -class CAI_LocalNavigator; -struct AI_Waypoint_t; -class CAI_WaypointList; -class CAI_Network; -struct AIMoveTrace_t; -struct AILocalMoveGoal_t; -typedef int AI_TaskFailureCode_t; - -//----------------------------------------------------------------------------- -// Debugging tools -//----------------------------------------------------------------------------- - -#define DEBUG_AI_NAVIGATION 1 -#ifdef DEBUG_AI_NAVIGATION -extern ConVar ai_debug_nav; -#define DbgNav() ai_debug_nav.GetBool() -#define DbgNavMsg( pAI, pszMsg ) \ - do \ - { \ - if (DbgNav()) \ - DevMsg( pAI, CFmtStr( "[Nav] %s", static_cast(pszMsg) ) ); \ - } while (0) -#define DbgNavMsg1( pAI, pszMsg, a ) DbgNavMsg( pAI, CFmtStr(static_cast(pszMsg), (a) ) ) -#define DbgNavMsg2( pAI, pszMsg, a, b ) DbgNavMsg( pAI, CFmtStr(static_cast(pszMsg), (a), (b) ) ) -#else -#define DbgNav() false -#define DbgNavMsg( pAI, pszMsg ) ((void)0) -#define DbgNavMsg1( pAI, pszMsg, a ) ((void)0) -#define DbgNavMsg2( pAI, pszMsg, a, b ) ((void)0) -#endif - - -//----------------------------------------------------------------------------- -// STRUCTURES & ENUMERATIONS -//----------------------------------------------------------------------------- - -DECLARE_POINTER_HANDLE( AI_PathNode_t ); - -//------------------------------------- -// Purpose: Constants used to specify the properties of a requested navigation -// goal. -//------------------------------------- - -// Navigator should use the default or previously set tolerance -const float AIN_DEF_TOLERANCE = -1.0; - -// Navigator should use the hull size as the tolerance -const float AIN_HULL_TOLERANCE = -2.0; - -// Goal does not specify a new activity -const Activity AIN_DEF_ACTIVITY = ACT_INVALID; - -// Goal has no target -CBaseEntity * const AIN_NO_TARGET = NULL; - -// Goal does not specify a new target, use the existing one, if any -CBaseEntity * const AIN_DEF_TARGET = (AIN_NO_TARGET + 1); - -// Goal does not specify a vector location -extern const Vector AIN_NO_DEST; - -// Goal does not specify a node location -#define AIN_NO_NODE ((AI_PathNode_t)-1) - - -//------------------------------------- - -enum AI_NavGoalFlags_t -{ - // While navigating, try to face the destination point - AIN_YAW_TO_DEST = 0x01, - - // If I'm a goal of type GOALTYPE_TARGETENT, update my goal position every time I think - AIN_UPDATE_TARGET_POS = 0x02, - - // If navigating on a designer placed path, don't use pathfinder between waypoints, just do it - AIN_NO_PATHCORNER_PATHFINDING = 0x04, - - AIN_DEF_FLAGS = 0, -}; - -//------------------------------------- - -enum AI_NavSetGoalFlags_t -{ - // Reset the navigator's navigation to the default state - AIN_CLEAR_PREVIOUS_STATE = 0x01, - - // Clear out the target entity, while retaining other settings - AIN_CLEAR_TARGET = 0x02, - - // If the navigate fails, return navigation to the default state - AIN_DISCARD_IF_FAIL = 0x04, - - // Don't signal TaskFail() if the pathfind fails, just return the result - AIN_NO_PATH_TASK_FAIL = 0x08, -}; - -//------------------------------------- - -enum AI_NpcBlockHandling_t -{ - AISF_BLOCK, - AISF_AVOID, - AISF_IGNORE, -}; - -//------------------------------------- - -enum AI_NavPathProgress_t -{ - AINPP_NO_CHANGE, - AINPP_ADVANCED, - AINPP_COMPLETE, - AINPP_BLOCKED, -}; - -//------------------------------------- -// Purpose: Describes a navigation request. The various constructors simply -// allow ease of use in the common cases. -//------------------------------------- - -struct AI_NavGoal_t -{ - // Goal is unspecifed, or not a specific location - AI_NavGoal_t( GoalType_t type = GOALTYPE_INVALID, - Activity activity = AIN_DEF_ACTIVITY, - float tolerance = AIN_DEF_TOLERANCE, - unsigned flags = AIN_DEF_FLAGS, - CBaseEntity * pTarget = AIN_DEF_TARGET); - - // Goal is a specific location, and GOALTYPE_LOCATION - AI_NavGoal_t( const Vector &dest, - Activity activity = AIN_DEF_ACTIVITY, - float tolerance = AIN_DEF_TOLERANCE, - unsigned flags = AIN_DEF_FLAGS, - CBaseEntity * pTarget = AIN_DEF_TARGET); - - // Goal is a specific location and goal type - AI_NavGoal_t( GoalType_t type, - const Vector &dest, - Activity activity = AIN_DEF_ACTIVITY, - float tolerance = AIN_DEF_TOLERANCE, - unsigned flags = AIN_DEF_FLAGS, - CBaseEntity * pTarget = AIN_DEF_TARGET); - - // Goal is a specific node, and GOALTYPE_LOCATION - AI_NavGoal_t( AI_PathNode_t destNode, - Activity activity = AIN_DEF_ACTIVITY, - float tolerance = AIN_DEF_TOLERANCE, - unsigned flags = AIN_DEF_FLAGS, - CBaseEntity * pTarget = AIN_DEF_TARGET); - - // Goal is a specific location and goal type - AI_NavGoal_t( GoalType_t type, - AI_PathNode_t destNode, - Activity activity = AIN_DEF_ACTIVITY, - float tolerance = AIN_DEF_TOLERANCE, - unsigned flags = AIN_DEF_FLAGS, - CBaseEntity * pTarget = AIN_DEF_TARGET); - - //---------------------------------- - - // What type of goal is this - GoalType_t type; - - // The destination, either as a vector, or as a path node - Vector dest; - AI_PathNode_t destNode; - - // The activity to use, or none if a previosly set activity should be used - Activity activity; - - // The predicted activity used after arrival - Activity arrivalActivity; - int arrivalSequence; - - // The tolerance of success, or none if a previosly set tolerance should be used - float tolerance; - - // How far to permit an initial simplification of path - // (will use default if this value is less than the default) - float maxInitialSimplificationDist; - - // Optional flags specifying - unsigned flags; - - // The target of the navigation, primarily used to ignore the entity in hull and line traces - CBaseEntity * pTarget; -}; - -//------------------------------------- -// Purpose: Used to describe rules for advance on a (fly) path. There's nothing -// specifically "flying" about it, other than it came from an attempte -// to consolodate duplicated code in the various fliers. It may serve -// a more general purpose in the future. The constructor takes those -// arguments that can usually be specified just once (as in a -// local static constructor) -//------------------------------------- - -struct AI_ProgressFlyPathParams_t -{ - AI_ProgressFlyPathParams_t( unsigned collisionMask, - float strictPointTolerance = 32.0, float blockTolerance = 0.0, - float waypointTolerance = 100, float goalTolerance = 12, - AI_NpcBlockHandling_t blockHandling = AISF_BLOCK ) - : collisionMask( collisionMask ), - strictPointTolerance( strictPointTolerance ), - blockTolerance( blockTolerance ), - waypointTolerance( waypointTolerance ), - goalTolerance( goalTolerance ), - blockHandling( blockHandling ), - pTarget( NULL ), - bTrySimplify( true ) - { - } - - void SetCurrent( const CBaseEntity *pNewTarget, bool bNewTrySimplify = true ) - { - pTarget = pNewTarget; - bTrySimplify = bNewTrySimplify; - } - - //---------------------------------- - - // Fields that tend to stay constant - unsigned collisionMask; - float strictPointTolerance; - float blockTolerance; // @TODO (toml 07-03-02): rename "blockTolerance". This is specifically the "simplify" block tolerance. See SimplifyFlyPath() - float waypointTolerance; - float goalTolerance; // @TODO (toml 07-03-02): goalTolerance appears to have come into existence because - // noone had set a good tolerance in the path itself. It is therefore redundant, - // and more than likely should be excised - AI_NpcBlockHandling_t blockHandling; // @TODO (toml 07-03-02): rename "blockHandling". This is specifically the "simplify" block handling. See SimplifyFlyPath() - - // Fields that tend to change - const CBaseEntity * pTarget; - bool bTrySimplify; -}; - -//----------------------------------------------------------------------------- -// CAI_Navigator -// -// Purpose: Implements pathing and path navigaton logic -//----------------------------------------------------------------------------- - -class CAI_Navigator : public CAI_Component, - public CAI_DefMovementSink -{ - typedef CAI_Component BaseClass; -public: - // -------------------------------- - - CAI_Navigator(CAI_BaseNPC *pOuter); - virtual ~CAI_Navigator(); - - virtual void Init( CAI_Network *pNetwork ); - - // -------------------------------- - - void SetPathcornerPathfinding( bool fNewVal) { m_bNoPathcornerPathfinds = !fNewVal; } - void SetRememberStaleNodes( bool fNewVal) { m_fRememberStaleNodes = fNewVal; } - void SetValidateActivitySpeed( bool bValidateActivitySpeed ) { m_bValidateActivitySpeed = bValidateActivitySpeed; } - void SetLocalSucceedOnWithinTolerance( bool fNewVal ) { m_bLocalSucceedOnWithinTolerance = fNewVal; } - - // -------------------------------- - - void Save( ISave &save ); - void Restore( IRestore &restore ); - - // -------------------------------- - // Methods to issue movement directives - // -------------------------------- - - // Simple pathfind - virtual bool SetGoal( const AI_NavGoal_t &goal, unsigned flags = 0 ); - - // Change the target of the path - virtual bool SetGoalTarget( CBaseEntity *pEntity, const Vector &offset ); - - // Fancy pathing - bool SetRadialGoal( const Vector &destination, const Vector ¢er, float radius, float arc, float stepDist, bool bClockwise, bool bAirRoute = false ); - bool SetRandomGoal( float minPathLength, const Vector &dir = vec3_origin ); - bool SetRandomGoal( const Vector &from, float minPathLength, const Vector &dir = vec3_origin ); - bool SetDirectGoal( const Vector &goalPos, Navigation_t navType = NAV_GROUND ); - - bool SetWanderGoal( float minRadius, float maxRadius ); - bool SetVectorGoal( const Vector &dir, float targetDist, float minDist = 0, bool fShouldDeflect = false ); - bool SetVectorGoalFromTarget( const Vector &goalPos, float minDist = 0, bool fShouldDeflect = false ); - - bool FindVectorGoal( Vector *pResult, const Vector &dir, float targetDist, float minDist = 0, bool fShouldDeflect = false ); - - // Path manipulation - bool PrependLocalAvoidance( float distObstacle, const AIMoveTrace_t &directTrace ); - void PrependWaypoint( const Vector &newPoint, Navigation_t navType, unsigned waypointFlags = 0 ); - - // Query or change the movement activity - Activity GetMovementActivity() const; - Activity SetMovementActivity(Activity activity); - int GetMovementSequence(); - void SetMovementSequence( int sequence ); - - // Query or change the Arrival activity - Activity GetArrivalActivity() const; - void SetArrivalActivity( Activity activity ); - int GetArrivalSequence( int curSequence ); - void SetArrivalSequence( int sequence ); - - // Set the facing direction at arrival - void SetArrivalDirection( const Vector &goalDirection ); - void SetArrivalDirection( const QAngle &goalAngle ); - void SetArrivalDirection( CBaseEntity *pTarget ); - Vector GetArrivalDirection( ); - - // Set the speed to reach at arrival ( - void SetArrivalSpeed( float flSpeed ); - float GetArrivalSpeed(); - - // Set the estimated distance to stop before the actual goal - void SetArrivalDistance( float flDistance ); - float GetArrivalDistance( ) const; - - // Query or change the goal tolerance - float GetGoalTolerance() const; - void SetGoalTolerance(float tolerance); - - GoalType_t GetGoalType() const; - const Vector & GetGoalPos() const; - CBaseEntity * GetGoalTarget(); - int GetGoalFlags() const; - - const Vector & GetCurWaypointPos() const; - int GetCurWaypointFlags() const; - - bool CurWaypointIsGoal() const; - - bool GetPointAlongPath( Vector *pResult, float distance, bool fReducibleOnly = false ); - - float GetPathDistanceToGoal(); - float GetPathTimeToGoal(); - - // Query if there is a current goal - bool IsGoalSet() const; - - // Query if the current goal is active, meaning the navigator has a path in can progress on - bool IsGoalActive() const; - - // Update the goal position to reflect current conditions - bool RefindPathToGoal( bool fSignalTaskStatus = true, bool bDontIgnoreBadLinks = false ); - bool UpdateGoalPos( const Vector & ); - - // Wrap up current locomotion - void StopMoving( bool bImmediate = true ); - - // Discard the current goal, use StopMoving() if just executing a normal stop - bool ClearGoal(); - - // -------------------------------- - - void SetAllowBigStep( CBaseEntity *pEntToStepOff ) { if ( !pEntToStepOff || !pEntToStepOff->IsWorld() ) m_hBigStepGroundEnt = pEntToStepOff; } - - // -------------------------------- - bool SetGoalFromStoppingPath(); - void IgnoreStoppingPath(); - - // -------------------------------- - // Navigation mode - // -------------------------------- - Navigation_t GetNavType() const { return m_navType; } - void SetNavType( Navigation_t navType ); - - bool IsInterruptable() const { return ( m_navType != NAV_CLIMB && m_navType != NAV_JUMP ); } - - // -------------------------------- - // Pathing - // -------------------------------- - - AI_NavPathProgress_t ProgressFlyPath( const AI_ProgressFlyPathParams_t ¶ms); // note: will not return "blocked" - - AI_PathNode_t GetNearestNode(); - Vector GetNodePos( AI_PathNode_t ); - - CAI_Network * GetNetwork() { return m_pAINetwork; } - const CAI_Network * GetNetwork() const { return m_pAINetwork; } - void SetNetwork( CAI_Network *pNetwork ) { m_pAINetwork = pNetwork; } - - CAI_Path * GetPath() { return m_pPath; } - const CAI_Path * GetPath() const { return m_pPath; } - - void AdvancePath(); - - virtual bool SimplifyPath( bool bFirstForPath = false, float maxDist = -1 ); - void SimplifyFlyPath( unsigned collisionMask, const CBaseEntity *pTarget, - float strictPointTolerance = 32.0, float blockTolerance = 0.0, - AI_NpcBlockHandling_t blockHandling = AISF_BLOCK); - bool SimplifyFlyPath( const AI_ProgressFlyPathParams_t ¶ms ); - - bool CanFitAtNode(int nodeNum, unsigned int collisionMask = MASK_NPCSOLID_BRUSHONLY); - float MovementCost( int moveType, Vector &vecStart, Vector &vecEnd ); - - bool CanFitAtPosition( const Vector &vStartPos, unsigned int collisionMask, bool bIgnoreTransients = false, bool bAllowPlayerAvoid = true ); - bool IsOnNetwork() const { return !m_bNotOnNetwork; } - - void SetMaxRouteRebuildTime(float time) { m_timePathRebuildMax = time; } - - // -------------------------------- - void DrawDebugRouteOverlay( void ); - - // -------------------------------- - // Miscellany - // -------------------------------- - - float CalcYawSpeed(); - float GetStepDownMultiplier(); - CBaseEntity * GetNextPathcorner( CBaseEntity *pPathCorner ); - virtual void OnScheduleChange(); - - // -------------------------------- - - // See comments at CAI_BaseNPC::Move() - virtual bool Move( float flInterval = 0.1 ); - - // -------------------------------- - - CBaseEntity * GetBlockingEntity() { return m_hLastBlockingEnt; } - -protected: - // -------------------------------- - // - // Common services provided by CAI_BaseNPC - // - CBaseEntity * GetNavTargetEntity(); - void TaskMovementComplete(); - float MaxYawSpeed(); - void SetSpeed( float ); - - // -------------------------------- - - CAI_Motor * GetMotor() { return m_pMotor; } - const CAI_Motor * GetMotor() const { return m_pMotor; } - - CAI_MoveProbe * GetMoveProbe() { return m_pMoveProbe; } - const CAI_MoveProbe *GetMoveProbe() const { return m_pMoveProbe; } - - CAI_LocalNavigator *GetLocalNavigator() { return m_pLocalNavigator; } - const CAI_LocalNavigator *GetLocalNavigator() const { return m_pLocalNavigator; } - - CAI_Pathfinder * GetPathfinder(); - const CAI_Pathfinder *GetPathfinder() const; - - virtual void OnClearPath(void); - - // -------------------------------- - - virtual void OnNewGoal(); - virtual void OnNavComplete(); - void OnNavFailed( bool bMovement = false ); - void OnNavFailed( AI_TaskFailureCode_t code, bool bMovement = false ); - void OnNavFailed( const char *pszGeneralFailText, bool bMovement = false ); - - // -------------------------------- - - virtual AIMoveResult_t MoveNormal(); - - // Navigation execution - virtual AIMoveResult_t MoveClimb(); - virtual AIMoveResult_t MoveJump(); - - // -------------------------------- - - virtual AIMoveResult_t MoveEnact( const AILocalMoveGoal_t &baseMove ); - -protected: - // made this virtual so strider can implement hover behavior with a navigator - virtual void MoveCalcBaseGoal( AILocalMoveGoal_t *pMoveGoal); - -private: - virtual bool OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ); - virtual bool OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ); - virtual bool OnFailedSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ); - virtual bool OnFailedLocalNavigation( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ); - virtual bool OnInsufficientStopDist( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ); - virtual bool OnMoveStalled( const AILocalMoveGoal_t &move ); - virtual bool OnMoveExecuteFailed( const AILocalMoveGoal_t &move, const AIMoveTrace_t &trace, AIMotorMoveResult_t fMotorResult, AIMoveResult_t *pResult ); - virtual bool OnMoveBlocked( AIMoveResult_t *pResult ); - - void ResetCalculations(); - - // Methods shared between ground and fly movement - bool PreMove(); - virtual bool MoveUpdateWaypoint( AIMoveResult_t *pResult ); - bool IsMovingOutOfWay( const AILocalMoveGoal_t &moveGoal, float distClear ); - bool DelayNavigationFailure( const AIMoveTrace_t &trace ); - - static void CalculateDeflection( const Vector &start, const Vector &dir, const Vector &normal, Vector *pResult ); - - // -------------------------------- - // Pathfinding - // -------------------------------- - -public: - float GetPathDistToCurWaypoint() const; - float GetPathDistToGoal() const; - float BuildAndGetPathDistToGoal(); - - // -------------------------------- - - int GetNavFailCounter() const; - void ClearNavFailCounter(); - float GetLastNavFailTime() const; - bool TeleportAlongPath(); - -private: - bool DoFindPath( void ); // Find a route - bool DoFindPathToPathcorner( CBaseEntity *pPathCorner ); - -protected: - virtual bool DoFindPathToPos(void); - virtual bool ShouldOptimizeInitialPathSegment( AI_Waypoint_t * ) { return true; } - -private: - void ClearPath(void); - void SaveStoppingPath( void ); - -protected: - virtual bool GetStoppingPath( CAI_WaypointList *pClippedWaypoints ); - -private: - bool FindPath( const AI_NavGoal_t &goal, unsigned flags ); - bool FindPath( bool fSignalTaskStatus = true, bool bDontIgnoreBadLinks = false ); - bool MarkCurWaypointFailedLink( void ); // Call when route fails - - struct SimplifyForwardScanParams - { - float scanDist; - float radius; - float increment; - int maxSamples; - }; - - bool ShouldAttemptSimplifyTo( const Vector &pos ); - bool ShouldSimplifyTo( bool passedDetour, const Vector &pos ); - bool SimplifyPathForwardScan( const CAI_Navigator::SimplifyForwardScanParams ¶ms ); - bool SimplifyPathForwardScan( const SimplifyForwardScanParams ¶ms, AI_Waypoint_t *pCurWaypoint, const Vector &curPoint, float distRemaining, bool skip, bool passedDetour, int *pTestCount ); - bool SimplifyPathForward( float maxDist = -1 ); - bool SimplifyPathBacktrack(); - bool SimplifyPathQuick(); - void SimplifyPathInsertSimplification( AI_Waypoint_t *pSegmentStart, const Vector &point ); - - // --------------------------------- - - static bool ActivityIsLocomotive( Activity ); - - // --------------------------------- - - Navigation_t m_navType; // My current navigation type (walk,fly) - bool m_fNavComplete; - bool m_bLastNavFailed; - - // Cached pointers to other components, for efficiency - CAI_Motor * m_pMotor; - CAI_MoveProbe * m_pMoveProbe; - CAI_LocalNavigator *m_pLocalNavigator; - - // --------------------------------- - - CAI_Network* m_pAINetwork; // My current AINetwork - CAI_Path* m_pPath; // My current route - - CAI_WaypointList * m_pClippedWaypoints; - float m_flTimeClipped; - Activity m_PreviousMoveActivity; - Activity m_PreviousArrivalActivity; - - bool m_bValidateActivitySpeed; - bool m_bCalledStartMove; - - bool m_bNotOnNetwork; // This NPC has no reachable nodes! - - float m_flNextSimplifyTime; // next time we should try to simplify our route - bool m_bForcedSimplify; - float m_flLastSuccessfulSimplifyTime; - - float m_flTimeLastAvoidanceTriangulate; - - // -------------- - - float m_timePathRebuildMax; // How long to try rebuilding path before failing task - float m_timePathRebuildDelay; // How long to wait before trying to rebuild again - - float m_timePathRebuildFail; // Current global time when should fail building path - float m_timePathRebuildNext; // Global time to try rebuilding again - - // -------------- - - bool m_fRememberStaleNodes; - bool m_bNoPathcornerPathfinds; - bool m_bLocalSucceedOnWithinTolerance; - - // -------------- - - bool m_fPeerMoveWait; - EHANDLE m_hPeerWaitingOn; - CSimTimer m_PeerWaitMoveTimer; - CSimTimer m_PeerWaitClearTimer; - - CSimTimer m_NextSidestepTimer; - - // -------------- - - EHANDLE m_hBigStepGroundEnt; - EHANDLE m_hLastBlockingEnt; - - // -------------- - - Vector m_vPosBeginFailedSteer; - float m_timeBeginFailedSteer; - - // -------------- - - int m_nNavFailCounter; - float m_flLastNavFailTime; -public: - DECLARE_SIMPLE_DATADESC(); -}; - - -//----------------------------------------------------------------------------- -// AI_NavGoal_t inline methods -//----------------------------------------------------------------------------- - -inline AI_NavGoal_t::AI_NavGoal_t( GoalType_t type, - Activity activity, - float tolerance, - unsigned flags, - CBaseEntity *pTarget) - : type(type), - dest(AIN_NO_DEST), - destNode(AIN_NO_NODE), - activity(activity), - arrivalActivity( AIN_DEF_ACTIVITY ), - arrivalSequence( ACT_INVALID ), - tolerance(tolerance), - maxInitialSimplificationDist(-1), - flags(flags), - pTarget(pTarget) -{ -} - -inline AI_NavGoal_t::AI_NavGoal_t( const Vector &dest, - Activity activity, - float tolerance, - unsigned flags, - CBaseEntity *pTarget) - : type(GOALTYPE_LOCATION), - dest(dest), - destNode(AIN_NO_NODE), - activity(activity), - arrivalActivity( AIN_DEF_ACTIVITY ), - arrivalSequence( ACT_INVALID ), - tolerance(tolerance), - maxInitialSimplificationDist(-1), - flags(flags), - pTarget(pTarget) -{ -} - -inline AI_NavGoal_t::AI_NavGoal_t( GoalType_t type, - const Vector &dest, - Activity activity, - float tolerance, - unsigned flags, - CBaseEntity *pTarget) - : type(type), - dest(dest), - destNode(AIN_NO_NODE), - activity(activity), - arrivalActivity( AIN_DEF_ACTIVITY ), - arrivalSequence( ACT_INVALID ), - tolerance(tolerance), - maxInitialSimplificationDist(-1), - flags(flags), - pTarget(pTarget) -{ -} - -inline AI_NavGoal_t::AI_NavGoal_t( AI_PathNode_t destNode, - Activity activity, - float tolerance, - unsigned flags, - CBaseEntity * pTarget) - : type(GOALTYPE_LOCATION), - dest(AIN_NO_DEST), - destNode(destNode), - activity(activity), - arrivalActivity( AIN_DEF_ACTIVITY ), - arrivalSequence( ACT_INVALID ), - tolerance(tolerance), - maxInitialSimplificationDist(-1), - flags(flags), - pTarget(pTarget) -{ -} - -inline AI_NavGoal_t::AI_NavGoal_t( GoalType_t type, - AI_PathNode_t destNode, - Activity activity, - float tolerance, - unsigned flags, - CBaseEntity * pTarget) - : type(type), - dest(AIN_NO_DEST), - destNode(destNode), - activity(activity), - arrivalActivity( AIN_DEF_ACTIVITY ), - arrivalSequence( ACT_INVALID ), - tolerance(tolerance), - maxInitialSimplificationDist(-1), - flags(flags), - pTarget(pTarget) -{ -} - -//----------------------------------------------------------------------------- - -#endif // AI_NAVIGATOR_H diff --git a/game/server/ai_navtype.h b/game/server/ai_navtype.h deleted file mode 100644 index 579cb0555..000000000 --- a/game/server/ai_navtype.h +++ /dev/null @@ -1,28 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_NAVTYPE_H -#define AI_NAVTYPE_H - -#if defined( _WIN32 ) -#pragma once -#endif - -// --------------------------- -// Navigation Type Bits -// --------------------------- -enum Navigation_t -{ - NAV_NONE = -1, // error condition - NAV_GROUND = 0, // walk/run - NAV_JUMP, // jump/leap - NAV_FLY, // can fly, move all around - NAV_CLIMB, // climb ladders -}; - - -#endif // AI_NAVTYPE_H diff --git a/game/server/ai_network.cpp b/game/server/ai_network.cpp deleted file mode 100644 index 4322d3619..000000000 --- a/game/server/ai_network.cpp +++ /dev/null @@ -1,644 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Base combat character with no AI -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -#include "ai_network.h" -#include "ai_node.h" -#include "ai_basenpc.h" -#include "ai_link.h" -#include "ai_navigator.h" -#include "world.h" -#include "ai_moveprobe.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar ai_no_node_cache( "ai_no_node_cache", "0" ); - -extern float MOVE_HEIGHT_EPSILON; - -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// For now we just have one AINetwork called "BigNet". At some -// later point we will probabaly have multiple AINetworkds per level -CAI_Network* g_pBigAINet; - -//----------------------------------------------------------------------------- - -abstract_class INodeListFilter -{ -public: - virtual bool NodeIsValid( CAI_Node &node ) = 0; - virtual float NodeDistanceSqr( CAI_Node &node ) = 0; -}; - -//------------------------------------- -// Purpose: Filters nodes for an NPC -//------------------------------------- - -class CNodeFilter : public INodeListFilter -{ -public: - CNodeFilter( CAI_BaseNPC *pNPC, const Vector &pos ) : m_pos(pos), m_pNPC(pNPC) - { - if ( m_pNPC ) - m_capabilities = m_pNPC->CapabilitiesGet(); - } - - CNodeFilter( const Vector &pos ) : m_pos(pos), m_pNPC(NULL) - { - } - - virtual bool NodeIsValid( CAI_Node &node ) - { - if ( node.GetType() == NODE_DELETED ) - return false; - - if ( !m_pNPC ) - return true; - - if ( m_pNPC->GetNavType() == NAV_FLY && node.GetType() != NODE_AIR ) - return false; - - // Check that node is of proper type for this NPC's navigation ability - if ((node.GetType() == NODE_AIR && !(m_capabilities & bits_CAP_MOVE_FLY)) || - (node.GetType() == NODE_GROUND && !(m_capabilities & bits_CAP_MOVE_GROUND)) ) - return false; - - if ( m_pNPC->IsUnusableNode( node.GetId(), node.GetHint() ) ) - return false; - - return true; - } - - virtual float NodeDistanceSqr( CAI_Node &node ) - { - // UNDONE: This call to Position() really seems excessive here. What is the real - // error % relative to 800 units (MAX_NODE_LINK_DIST) ? - if ( m_pNPC ) - return (node.GetPosition(m_pNPC->GetHullType()) - m_pos).LengthSqr(); - else - return (node.GetOrigin() - m_pos).LengthSqr(); - } - - const Vector &m_pos; - CAI_BaseNPC *m_pNPC; - int m_capabilities; // cache this -}; - -//----------------------------------------------------------------------------- -// CAI_Network -//----------------------------------------------------------------------------- - -// for searching for the nearest node -// PERFORMANCE: Tune this number -#define MAX_NEAR_NODES 10 // Trace to 10 nodes at most - -//----------------------------------------------------------------------------- - -CAI_Network::CAI_Network() -{ - m_iNumNodes = 0; // Number of nodes in this network - m_pAInode = NULL; // Array of all nodes in this network - - m_iNearestCacheNext = NEARNODE_CACHE_SIZE - 1; - // Force empty node caches to be rebuild - for (int node=0;nodeDestroySpatialPartition( m_pNodeTree ); - m_pNodeTree = NULL; - } -#endif - if ( m_pAInode ) - { - for ( int node = 0; node < m_iNumNodes; node++ ) - { - CAI_Node *pNode = m_pAInode[node]; - Assert( pNode && pNode->m_iID == node ); - - for ( int link = 0; link < pNode->NumLinks(); link++ ) - { - CAI_Link *pLink = pNode->m_Links[link]; - if ( pLink ) - { - int destID = pLink->DestNodeID( node ); - Assert( destID > node && destID < m_iNumNodes ); - if ( destID > node && destID < m_iNumNodes ) - { - CAI_Node *pDestNode = m_pAInode[destID]; - Assert( pDestNode ); - - for ( int destLink = 0; destLink < pDestNode->NumLinks(); destLink++ ) - { - if ( pDestNode->m_Links[destLink] == pLink ) - { - pDestNode->m_Links[destLink] = NULL; - } - } - } - delete pLink; - } - } - delete pNode; - } - } - delete[] m_pAInode; - m_pAInode = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Given an bitString and float array of size array_size, return the -// index of the smallest number in the array whose it is set -//----------------------------------------------------------------------------- - -int CAI_Network::FindBSSmallest(CVarBitVec *bitString, float *float_array, int array_size) -{ - int winIndex = -1; - float winSize = FLT_MAX; - for (int i=0;iIsBitSet(i) && (float_array[i] 0 or this will crash - bool full = false; - float flClosest = 1000000.0 * 1000000; - int closest = 0; - -// UNDONE: Store the nodes in a tree and query the tree instead of the entire list!!! - for ( int node = 0; node < m_iNumNodes; node++ ) - { - CAI_Node *pNode = m_pAInode[node]; - const Vector &origin = pNode->GetOrigin(); - // in box? - if ( origin.x < mins.x || origin.x > maxs.x || - origin.y < mins.y || origin.y > maxs.y || - origin.z < mins.z || origin.z > maxs.z ) - continue; - - if ( !pFilter->NodeIsValid(*pNode) ) - continue; - - float flDist = pFilter->NodeDistanceSqr(*pNode); - - if ( flDist < flClosest ) - { - closest = node; - flClosest = flDist; - } - - if ( !full || (flDist < result.ElementAtHead().dist) ) - { - if ( full ) - result.RemoveAtHead(); - - result.Insert( AI_NearNode_t(node, flDist) ); - - full = (result.Count() == maxListCount); - } - } - - list.RemoveAll(); - while ( result.Count() ) - { - list.Insert( result.ElementAtHead() ); - result.RemoveAtHead(); - } - - return list.Count(); -} - -//----------------------------------------------------------------------------- -// Purpose: Return ID of node nearest of vecOrigin for pNPC with the given -// tolerance distance. If a route is required to get to the node -// node_route is set. -//----------------------------------------------------------------------------- - -int CAI_Network::NearestNodeToPoint( CAI_BaseNPC *pNPC, const Vector &vecOrigin, bool bCheckVisibility, INearestNodeFilter *pFilter ) -{ - AI_PROFILE_SCOPE( CAI_Network_NearestNodeToNPCAtPoint ); - - // -------------------------------- - // Check if network has no nodes - // -------------------------------- - if (m_iNumNodes == 0) - return NO_NODE; - - // ---------------------------------------------------------------- - // First check cached nearest node positions - // ---------------------------------------------------------------- - int cachePos; - int cachedNode = GetCachedNearestNode( vecOrigin, pNPC, &cachePos ); - if ( cachedNode != NO_NODE ) - { - if ( bCheckVisibility ) - { - trace_t tr; - - Vector vTestLoc = ( pNPC ) ? - m_pAInode[cachedNode]->GetPosition(pNPC->GetHullType()) + pNPC->GetViewOffset() : - m_pAInode[cachedNode]->GetOrigin(); - - CTraceFilterNav traceFilter( pNPC, true, pNPC, COLLISION_GROUP_NONE ); - AI_TraceLine ( vecOrigin, vTestLoc, MASK_NPCSOLID_BRUSHONLY, &traceFilter, &tr ); - - if ( tr.fraction != 1.0 ) - cachedNode = NO_NODE; - } - - if ( cachedNode != NO_NODE && ( !pFilter || pFilter->IsValid( m_pAInode[cachedNode] ) ) ) - { - m_NearestCache[cachePos].expiration = gpGlobals->curtime + NEARNODE_CACHE_LIFE; - return cachedNode; - } - } - - // --------------------------------------------------------------- - // First get nodes distances and eliminate those that are beyond - // the maximum allowed distance for local movements - // --------------------------------------------------------------- - CNodeFilter filter( pNPC, vecOrigin ); - -#ifdef AI_PERF_MON - m_nPerfStatNN++; -#endif - - AI_NearNode_t *pBuffer = (AI_NearNode_t *)stackalloc( sizeof(AI_NearNode_t) * MAX_NEAR_NODES ); - CNodeList list( pBuffer, MAX_NEAR_NODES ); - - // OPTIMIZE: If not flying, this box should be smaller in Z (2 * height?) - Vector ext(MAX_NODE_LINK_DIST, MAX_NODE_LINK_DIST, MAX_NODE_LINK_DIST); - // If the NPC can fly, check further - if ( pNPC && ( pNPC->CapabilitiesGet() & bits_CAP_MOVE_FLY ) ) - { - ext.Init( MAX_AIR_NODE_LINK_DIST, MAX_AIR_NODE_LINK_DIST, MAX_AIR_NODE_LINK_DIST ); - } - - ListNodesInBox( list, MAX_NEAR_NODES, vecOrigin - ext, vecOrigin + ext, &filter ); - - // -------------------------------------------------------------- - // Now find a reachable node searching the close nodes first - // -------------------------------------------------------------- - //int smallestVisibleID = NO_NODE; - - for( ;list.Count(); list.RemoveAtHead() ) - { - int smallest = list.ElementAtHead().nodeIndex; - - // Check not already rejected above - if ( smallest == cachedNode ) - continue; - - // Check that this node is usable by the current hull size - if ( pNPC && !pNPC->GetNavigator()->CanFitAtNode(smallest)) - continue; - - if ( bCheckVisibility ) - { - trace_t tr; - - Vector vTestLoc = ( pNPC ) ? - m_pAInode[smallest]->GetPosition(pNPC->GetHullType()) + pNPC->GetNodeViewOffset() : - m_pAInode[smallest]->GetOrigin(); - - Vector vecVisOrigin = vecOrigin + Vector(0,0,1); - - CTraceFilterNav traceFilter( pNPC, true, pNPC, COLLISION_GROUP_NONE ); - AI_TraceLine ( vecVisOrigin, vTestLoc, MASK_NPCSOLID_BRUSHONLY, &traceFilter, &tr ); - - if ( tr.fraction != 1.0 ) - continue; - } - - if ( pFilter ) - { - if ( !pFilter->IsValid( m_pAInode[smallest] ) ) - { - if ( !pFilter->ShouldContinue() ) - break; - continue; - } - } - - SetCachedNearestNode( vecOrigin, smallest, (pNPC) ? pNPC->GetHullType() : HULL_NONE ); - - return smallest; - } - - // Store inability to reach in cache for later use - SetCachedNearestNode( vecOrigin, NO_NODE, (pNPC) ? pNPC->GetHullType() : HULL_NONE ); - - return NO_NODE; -} - - -//----------------------------------------------------------------------------- -// Purpose: Find the nearest node to an entity without regard to how whether -// the node can be reached -//----------------------------------------------------------------------------- - -int CAI_Network::NearestNodeToPoint(const Vector &vPosition, bool bCheckVisibility ) -{ - return NearestNodeToPoint( NULL, vPosition, bCheckVisibility ); -} - -//----------------------------------------------------------------------------- -// Purpose: Check nearest node cache for checkPos and return cached nearest -// node if it exists in the cache. Doesn't care about reachability, -// only if the node is visible -//----------------------------------------------------------------------------- -int CAI_Network::GetCachedNode(const Vector &checkPos, Hull_t nHull, int *pCachePos ) -{ - if ( ai_no_node_cache.GetBool() ) - return NOT_CACHED; - - // Walk from newest to oldest. - int iNewest = m_iNearestCacheNext + 1; - for ( int i = 0; i < NEARNODE_CACHE_SIZE; i++ ) - { - int iCurrent = ( iNewest + i ) % NEARNODE_CACHE_SIZE; - if ( m_NearestCache[iCurrent].hull == nHull && m_NearestCache[iCurrent].expiration > gpGlobals->curtime ) - { - if ( (m_NearestCache[iCurrent].vTestPosition - checkPos).LengthSqr() < Square(24.0) ) - { - if ( pCachePos ) - *pCachePos = iCurrent; - return m_NearestCache[iCurrent].node; - } - } - } - - - if ( pCachePos ) - *pCachePos = -1; - return NOT_CACHED; -} - -//----------------------------------------------------------------------------- - -int CAI_Network::GetCachedNearestNode(const Vector &checkPos, CAI_BaseNPC *pNPC, int *pCachePos ) -{ - if ( pNPC ) - { - CNodeFilter filter( pNPC, checkPos ); - - int nodeID = GetCachedNode( checkPos, pNPC->GetHullType(), pCachePos ); - if ( nodeID >= 0 ) - { - if ( filter.NodeIsValid( *m_pAInode[nodeID] ) && pNPC->GetNavigator()->CanFitAtNode(nodeID) ) - return nodeID; - } - } - return NO_NODE; -} - -//----------------------------------------------------------------------------- -// Purpose: Update nearest node cache with new data -// if nHull == HULL_NONE, reachability of this node wasn't checked -//----------------------------------------------------------------------------- - -void CAI_Network::SetCachedNearestNode(const Vector &checkPos, int nodeID, Hull_t nHull) -{ - if ( ai_no_node_cache.GetBool() ) - return; - - m_NearestCache[m_iNearestCacheNext].vTestPosition = checkPos; - m_NearestCache[m_iNearestCacheNext].node = nodeID; - m_NearestCache[m_iNearestCacheNext].hull = nHull; - m_NearestCache[m_iNearestCacheNext].expiration = gpGlobals->curtime + NEARNODE_CACHE_LIFE; - - m_iNearestCacheNext--; - if ( m_iNearestCacheNext < 0 ) - { - m_iNearestCacheNext = NEARNODE_CACHE_SIZE - 1; - } -} - -//----------------------------------------------------------------------------- - -Vector CAI_Network::GetNodePosition( Hull_t hull, int nodeID ) -{ - if ( !m_pAInode ) - { - Assert( 0 ); - return vec3_origin; - } - - if ( ( nodeID < 0 ) || ( nodeID > m_iNumNodes ) ) - { - Assert( 0 ); - return vec3_origin; - } - - return m_pAInode[nodeID]->GetPosition( hull ); -} - -//----------------------------------------------------------------------------- - -Vector CAI_Network::GetNodePosition( CBaseCombatCharacter *pNPC, int nodeID ) -{ - if ( pNPC == NULL ) - { - Assert( 0 ); - return vec3_origin; - } - - return GetNodePosition( pNPC->GetHullType(), nodeID ); -} - -//----------------------------------------------------------------------------- - -float CAI_Network::GetNodeYaw( int nodeID ) -{ - if ( !m_pAInode ) - { - Assert( 0 ); - return 0.0f; - } - - if ( ( nodeID < 0 ) || ( nodeID > m_iNumNodes ) ) - { - Assert( 0 ); - return 0.0f; - } - - return m_pAInode[nodeID]->GetYaw(); -} - -//----------------------------------------------------------------------------- -// Purpose: Adds an ainode to the network -//----------------------------------------------------------------------------- - -CAI_Node *CAI_Network::AddNode( const Vector &origin, float yaw ) -{ - // --------------------------------------------------------------------- - // When loaded from a file will know the number of nodes from - // the start. Otherwise init MAX_NODES of them if not initialized - // --------------------------------------------------------------------- - if (!m_pAInode || !m_pAInode[0]) - { - if ( m_pAInode ) - delete [] m_pAInode; - m_pAInode = new CAI_Node*[MAX_NODES]; - } - - if (m_iNumNodes >= MAX_NODES) - { - DevMsg( "ERROR: too many nodes in map, deleting last node.\n", MAX_NODES ); - m_iNumNodes--; - } - - m_pAInode[m_iNumNodes] = new CAI_Node( m_iNumNodes, origin, yaw ); - -#ifdef AI_NODE_TREE - if ( !m_pNodeTree ) - { - Vector worldMins, worldMaxs; - GetWorldEntity()->GetWorldBounds( worldMins, worldMaxs ); - m_pNodeTree = engine->CreateSpatialPartition( worldMins, worldMaxs ); - } - - m_pNodeTree->CreateHandle( (IHandleEntity *)m_iNumNodes, PARTITION_NODE, origin, origin ); // ignore result for now as we'll never move or remove -#endif - - m_iNumNodes++; - - return m_pAInode[m_iNumNodes-1]; -}; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -CAI_Link *CAI_Network::CreateLink( int srcID, int destID, CAI_DynamicLink *pDynamicLink ) -{ - CAI_Node *pSrcNode = g_pBigAINet->GetNode( srcID ); - CAI_Node *pDestNode = g_pBigAINet->GetNode( destID ); - - Assert( pSrcNode && pDestNode && pSrcNode != pDestNode ); - - if ( !pSrcNode || !pDestNode ) - { - DevMsg( "Attempted to create link to node that doesn't exist\n" ); - return NULL; - } - - if ( pSrcNode == pDestNode ) - { - DevMsg( "Attempted to link a node to itself\n" ); - return NULL; - } - - if ( pSrcNode->NumLinks() == AI_MAX_NODE_LINKS ) - { - DevMsg( "Node %d has too many links\n", srcID ); - return NULL; - } - - if ( pDestNode->NumLinks() == AI_MAX_NODE_LINKS ) - { - DevMsg( "Node %d has too many links\n", destID ); - return NULL; - } - - CAI_Link *pLink = new CAI_Link; - - pLink->m_iSrcID = srcID; - pLink->m_iDestID = destID; - pLink->m_pDynamicLink = pDynamicLink; - - pSrcNode->AddLink(pLink); - pDestNode->AddLink(pLink); - - return pLink; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true is two nodes are connected by the network graph -//----------------------------------------------------------------------------- - -bool CAI_Network::IsConnected(int srcID, int destID) -{ - if (srcID > m_iNumNodes || destID > m_iNumNodes) - { - DevMsg("IsConnected called with invalid node IDs!\n"); - return false; - } - - if ( srcID == destID ) - return true; - - int srcZone = m_pAInode[srcID]->GetZone(); - int destZone = m_pAInode[destID]->GetZone(); - - if ( srcZone == AI_NODE_ZONE_SOLO || destZone == AI_NODE_ZONE_SOLO ) - return false; - - if ( srcZone == AI_NODE_ZONE_UNIVERSAL || destZone == AI_NODE_ZONE_UNIVERSAL ) // only happens in WC edit case - return true; - -#ifdef DEBUG - if ( srcZone == AI_NODE_ZONE_UNKNOWN || destZone == AI_NODE_ZONE_UNKNOWN ) - { - DevMsg( "Warning: Node found in unknown zone\n" ); - return true; - } -#endif - - return ( srcZone == destZone ); -} - -//----------------------------------------------------------------------------- - -IterationRetval_t CAI_Network::EnumElement( IHandleEntity *pHandleEntity ) -{ -#ifdef AI_NODE_TREE - m_GatheredNodes.AddToTail( (int)pHandleEntity ); -#endif - return ITERATION_CONTINUE; -} - -//============================================================================= diff --git a/game/server/ai_network.h b/game/server/ai_network.h deleted file mode 100644 index 86c6c060d..000000000 --- a/game/server/ai_network.h +++ /dev/null @@ -1,221 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_NETWORK_H -#define AI_NETWORK_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "ispatialpartition.h" -#include "utlpriorityqueue.h" - -// ------------------------------------ - -class CAI_Node; -class CVarBitVec; -class INodeListFilter; - -struct AI_Waypoint_t; -class CAI_BaseNPC; -class CAI_Link; -class CAI_DynamicLink; - -//----------------------------------------------------------------------------- - -class CAI_NetworkManager; - -//----------------------------------------------------------------------------- - -#define AI_MAX_NODE_LINKS 30 -#define MAX_NODES 1500 - -//----------------------------------------------------------------------------- -// -// Utility classes used by CAI_Network -// -//----------------------------------------------------------------------------- - -abstract_class INearestNodeFilter -{ -public: - virtual bool IsValid( CAI_Node *pNode ) = 0; - virtual bool ShouldContinue() = 0; -}; - -//------------------------------------- - -struct AI_NearNode_t -{ - AI_NearNode_t() {} - AI_NearNode_t( int index, float nodedist ) { dist = nodedist; nodeIndex = index; } - float dist; - int nodeIndex; -}; - -//------------------------------------- - -class CNodeList : public CUtlPriorityQueue -{ -public: - static bool IsLowerPriority( const AI_NearNode_t &node1, const AI_NearNode_t &node2 ) - { - // nodes with greater distance are lower priority - return node1.dist > node2.dist; - } - static bool RevIsLowerPriority( const AI_NearNode_t &node1, const AI_NearNode_t &node2 ) - { - // nodes with lower distance are lower priority - return node2.dist > node1.dist; - } - - CNodeList( int growSize = 0, int initSize = 0 ) : CUtlPriorityQueue( growSize, initSize, IsLowerPriority ) {} - CNodeList( AI_NearNode_t *pMemory, int count ) : CUtlPriorityQueue( pMemory, count, IsLowerPriority ) {} -}; - -//----------------------------------------------------------------------------- -// CAI_Network -// -// Purpose: Stores a node graph through which an AI may pathfind -//----------------------------------------------------------------------------- - -class CAI_Network : public IPartitionEnumerator -{ -public: - CAI_Network(); - ~CAI_Network(); - - CAI_Node * AddNode( const Vector &origin, float yaw ); // Returns a new node in the network - CAI_Link * CreateLink( int srcID, int destID, CAI_DynamicLink *pDynamicLink = NULL ); - - bool IsConnected(int srcID, int destID); // Use during run time - void TestIsConnected(int startID, int endID); // Use only for initialization! - - Vector GetNodePosition( CBaseCombatCharacter *pNPC, int nodeID ); - Vector GetNodePosition( Hull_t hull, int nodeID ); - float GetNodeYaw( int nodeID ); - - static int FindBSSmallest(CVarBitVec *bitString, float *float_array, int array_size); - - int NearestNodeToPoint( CAI_BaseNPC* pNPC, const Vector &vecOrigin, bool bCheckVisiblity, INearestNodeFilter *pFilter ); - int NearestNodeToPoint( CAI_BaseNPC* pNPC, const Vector &vecOrigin, bool bCheckVisiblity = true ) { return NearestNodeToPoint( pNPC, vecOrigin, bCheckVisiblity, NULL ); } - int NearestNodeToPoint(const Vector &vPosition, bool bCheckVisiblity = true ); - - int NumNodes() const { return m_iNumNodes; } - CAI_Node* GetNode( int id, bool bHandleError = true ) - { - if ( id >= 0 && - id < m_iNumNodes ) - { - return m_pAInode[id]; - } - - if ( bHandleError ) - { - static int warningCount = 0; - if ( ++warningCount < 10 ) - { - AssertMsg2( 0, "Node (%i) out of range (%i total)\n", id, m_iNumNodes ); - } - } - return NULL; - } - - CAI_Node** AccessNodes() const { return m_pAInode; } - -private: - friend class CAI_NetworkManager; - - virtual IterationRetval_t EnumElement( IHandleEntity *pHandleEntity ); - - int GetCachedNearestNode(const Vector &checkPos, CAI_BaseNPC *pNPC, int *pCachePos ); - void SetCachedNearestNode(const Vector &checkPos, int nodeID, Hull_t nHull); - int GetCachedNode(const Vector &checkPos, Hull_t nHull, int *pCachePos); - - int ListNodesInBox( CNodeList &list, int maxListCount, const Vector &mins, const Vector &maxs, INodeListFilter *pFilter ); - - //--------------------------------- - - enum - { - NEARNODE_CACHE_SIZE = 32, - NEARNODE_CACHE_LIFE = 10, - }; - - struct NearNodeCache_T - { - Vector vTestPosition; - float expiration; // Time tested - int node; // Nearest Node to position - int hull; // Hull type tested (or HULL_NONE is only visibility tested) - - }; - - int m_iNumNodes; // Number of nodes in this network - CAI_Node** m_pAInode; // Array of all nodes in this network - - enum - { - PARTITION_NODE = ( 1 << 0 ) - }; - - NearNodeCache_T m_NearestCache[NEARNODE_CACHE_SIZE]; // Cache of nearest nodes - int m_iNearestCacheNext; // Oldest record in the cache - -#ifdef AI_NODE_TREE - ISpatialPartition * m_pNodeTree; - CUtlVector m_GatheredNodes; -#endif -}; - -//----------------------------------------------------------------------------- -// CAI_NetworkEditTools -// -// Purpose: Provides the operations used when building levels, whether in-game -// debugging tools or editor related items. -// -//----------------------------------------------------------------------------- - - -// ------------------------------------ -// Debug overlay bits - -enum DebugNetOverlayBits_e -{ - bits_debugOverlayNodes = 0x00000001, // show node - bits_debugOverlayNodesLev2 = 0x00000002, // show nodes and text - - bits_debugOverlayHulls = 0x00000004, // show hulls - bits_debugOverlayConnections = 0x00000008, // show connections - bits_debugOverlayVisibility = 0x00000010, // show visibility - bits_debugOverlayGraphConnect = 0x00000020, // show graph connectivity - bits_debugOverlayGrid = 0x00000040, // show grid - bits_debugOverlayHints = 0x00000080, // show hints - bits_debugOverlayJumpConnections= 0x00000100, // show jump connections - bits_debugOverlayFlyConnections = 0x00000200, // show fly connections - - bits_debugNeedRebuild = 0x10000000, // network needs rebuilding -}; - -// ------------------------------------ - -// ---------------- - -//----------------------------------------------------------------------------- -// Useful utility function defined by AI_network.cpp -Vector PointOnLineNearestPoint(const Vector& vStartPos, const Vector& vEndPos, const Vector& vPoint); - -//----------------------------------------------------------------------------- - -// For now just using one big AI network -extern CAI_NetworkManager * g_pAINetworkManager; -extern CAI_Network * g_pBigAINet; - -//============================================================================= - -#endif // AI_NETWORK_H diff --git a/game/server/ai_networkmanager.cpp b/game/server/ai_networkmanager.cpp deleted file mode 100644 index a2c58c9d4..000000000 --- a/game/server/ai_networkmanager.cpp +++ /dev/null @@ -1,3189 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - - -#include "cbase.h" -#include "fmtstr.h" -#include "filesystem.h" -#include "filesystem/IQueuedLoader.h" -#include "utlbuffer.h" -#include "utlrbtree.h" -#include "editor_sendcommand.h" - -#include "ai_networkmanager.h" -#include "ai_network.h" -#include "ai_node.h" -#include "ai_navigator.h" -#include "ai_link.h" -#include "ai_dynamiclink.h" -#include "ai_initutils.h" -#include "ai_moveprobe.h" -#include "ai_hull.h" -#include "ndebugoverlay.h" -#include "ai_hint.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// Increment this to force rebuilding of all networks -#define AINET_VERSION_NUMBER 37 - -//----------------------------------------------------------------------------- - -int g_DebugConnectNode1 = -1; -int g_DebugConnectNode2 = -1; -#define DebuggingConnect( node1, node2 ) ( ( node1 == g_DebugConnectNode1 && node2 == g_DebugConnectNode2 ) || ( node1 == g_DebugConnectNode2 && node2 == g_DebugConnectNode1 ) ) - -inline void DebugConnectMsg( int node1, int node2, const char *pszFormat, ... ) -{ - if ( DebuggingConnect( node1, node2 ) ) - { - DevMsg( CFmtStr( &pszFormat ) ); - } -} - -CON_COMMAND( ai_debug_node_connect, "Debug the attempted connection between two nodes" ) -{ - g_DebugConnectNode1 = atoi( args[1] ); - g_DebugConnectNode2 = atoi( args[2] ); - - DevMsg( "ai_debug_node_connect: debugging enbabled for %d <--> %d\n", g_DebugConnectNode1, g_DebugConnectNode2 ); -} - -//----------------------------------------------------------------------------- -// This CVAR allows level designers to override the building -// of node graphs due to date conflicts with the BSP and AIN -// files. That way they don't have to wait for the node graph -// to rebuild following small only-ents changes. This CVAR -// always defaults to 0 and must be set at the command -// line to properly override the node graph building. - -ConVar g_ai_norebuildgraph( "ai_norebuildgraph", "0" ); - - -//----------------------------------------------------------------------------- -// CAI_NetworkManager -// -//----------------------------------------------------------------------------- - -CAI_NetworkManager *g_pAINetworkManager; - -//----------------------------------------------------------------------------- - -bool CAI_NetworkManager::gm_fNetworksLoaded; - -LINK_ENTITY_TO_CLASS(ai_network,CAI_NetworkManager); - -BEGIN_DATADESC( CAI_NetworkManager ) - - DEFINE_FIELD( m_bNeedGraphRebuild, FIELD_BOOLEAN ), - // m_pEditOps - // m_pNetwork - // DEFINE_FIELD( m_bDontSaveGraph, FIELD_BOOLEAN ), - DEFINE_FIELD( m_fInitalized, FIELD_BOOLEAN ), - - // Function pointers - DEFINE_FUNCTION( DelayedInit ), - DEFINE_FUNCTION( RebuildThink ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- - -CAI_NetworkManager::CAI_NetworkManager(void) -{ - m_pNetwork = new CAI_Network; - m_pEditOps = new CAI_NetworkEditTools(this); - m_bNeedGraphRebuild = false; - m_fInitalized = false; - CAI_DynamicLink::gm_bInitialized = false; - - // --------------------------------- - // Add to linked list of networks - // --------------------------------- -}; - -//----------------------------------------------------------------------------- - -CAI_NetworkManager::~CAI_NetworkManager(void) -{ - // --------------------------------------- - // Remove from linked list of AINetworks - // --------------------------------------- - delete m_pEditOps; - delete m_pNetwork; - if ( g_pAINetworkManager == this ) - { - g_pAINetworkManager = NULL; - } -} - - -//------------------------------------------------------------------------------ -// Purpose : Think function so we can put message on screen saying we are -// going to rebuild the network, before we hang during the rebuild -//------------------------------------------------------------------------------ - -void CAI_NetworkManager::RebuildThink( void ) -{ - SetThink(NULL); - - GetEditOps()->m_debugNetOverlays &= ~bits_debugNeedRebuild; - StartRebuild( ); -} - -//------------------------------------------------------------------------------ -// Purpose : Delay function so we can put message on screen saying we are -// going to rebuild the network, before we hang during the rebuild -//------------------------------------------------------------------------------ - -void CAI_NetworkManager::RebuildNetworkGraph( void ) -{ - if (m_pfnThink != (void (CBaseEntity::*)())&CAI_NetworkManager::RebuildThink) - { - UTIL_CenterPrintAll( "Doing partial rebuild of Node Graph...\n" ); - SetThink(&CAI_NetworkManager::RebuildThink); - SetNextThink( gpGlobals->curtime + 0.1f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Used for WC edit move to rebuild the network around the given -// location. Rebuilding the entire network takes too long -//----------------------------------------------------------------------------- - -void CAI_NetworkManager::StartRebuild( void ) -{ - CAI_DynamicLink::gm_bInitialized = false; - - g_AINetworkBuilder.Rebuild( m_pNetwork ); - - // ------------------------------------------------------------ - // Purge any dynamic links for links that don't exist any more - // ------------------------------------------------------------ - CAI_DynamicLink::PurgeDynamicLinks(); - - - // ------------------------ - // Reset all dynamic links - // ------------------------ - CAI_DynamicLink::ResetDynamicLinks(); - - // -------------------------------------------------- - // Update display of usable nodes for displayed hull - // -------------------------------------------------- - GetEditOps()->RecalcUsableNodesForHull(); - - GetEditOps()->ClearRebuildFlags(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Called by save restore code if no valid load graph was loaded at restore time. -// Prevents writing out of a "bogus" node graph... -// Input : - -//----------------------------------------------------------------------------- -void CAI_NetworkManager::MarkDontSaveGraph() -{ - m_bDontSaveGraph = true; -} - -//----------------------------------------------------------------------------- -// Purpose: Only called if network has changed since last time level -// was loaded -// Input : -// Output : -//----------------------------------------------------------------------------- - -void CAI_NetworkManager::SaveNetworkGraph( void ) -{ - if ( m_bDontSaveGraph ) - return; - - if ( !m_bNeedGraphRebuild ) - return; - - //if ( g_AI_Manager.NumAIs() && m_pNetwork->m_iNumNodes == 0 ) - //{ - // return; - //} - - if ( !g_pGameRules->FAllowNPCs() ) - { - return; - } - - // ----------------------------- - // Make sure directories have been made - // ----------------------------- - char szNrpFilename [MAX_PATH];// text node report filename - Q_strncpy( szNrpFilename, "maps/graphs" ,sizeof(szNrpFilename)); - - // Usually adding on the map filename and stripping it does nothing, but if the map is under a subdir, - // this makes it create the correct subdir under maps/graphs. - char tempFilename[MAX_PATH]; - Q_snprintf( tempFilename, sizeof( tempFilename ), "%s/%s", szNrpFilename, STRING( gpGlobals->mapname ) ); - - // Remove the filename. - int len = strlen( tempFilename ); - for ( int i=0; i < len; i++ ) - { - if ( tempFilename[len-i-1] == '/' || tempFilename[len-i-1] == '\\' ) - { - tempFilename[len-i-1] = 0; - break; - } - } - - // Make sure the directories we need exist. - filesystem->CreateDirHierarchy( tempFilename, "DEFAULT_WRITE_PATH" ); - - // Now add the real map filename. - Q_strncat( szNrpFilename, "/", sizeof( szNrpFilename ), COPY_ALL_CHARACTERS ); - Q_strncat( szNrpFilename, STRING( gpGlobals->mapname ), sizeof( szNrpFilename ), COPY_ALL_CHARACTERS ); - Q_strncat( szNrpFilename, IsX360() ? ".360.ain" : ".ain", sizeof( szNrpFilename ), COPY_ALL_CHARACTERS ); - - CUtlBuffer buf; - - // --------------------------- - // Save the version number - // --------------------------- - buf.PutInt(AINET_VERSION_NUMBER); - buf.PutInt(gpGlobals->mapversion); - - // ------------------------------- - // Dump all the nodes to the file - // ------------------------------- - buf.PutInt( m_pNetwork->m_iNumNodes); - - int node; - int totalNumLinks = 0; - for ( node = 0; node < m_pNetwork->m_iNumNodes; node++) - { - CAI_Node *pNode = m_pNetwork->GetNode(node); - Assert( pNode->GetZone() != AI_NODE_ZONE_UNKNOWN ); - - buf.PutFloat( pNode->GetOrigin().x ); - buf.PutFloat( pNode->GetOrigin().y ); - buf.PutFloat( pNode->GetOrigin().z ); - buf.PutFloat( pNode->GetYaw() ); - buf.Put( pNode->m_flVOffset, sizeof( pNode->m_flVOffset ) ); - buf.PutChar( pNode->GetType() ); - if ( IsX360() ) - { - buf.SeekPut( CUtlBuffer::SEEK_CURRENT, 3 ); - } - buf.PutUnsignedShort( pNode->m_eNodeInfo ); - buf.PutShort( pNode->GetZone() ); - - for (int link = 0; link < pNode->NumLinks(); link++) - { - // Only dump if link source - if (node == pNode->GetLinkByIndex(link)->m_iSrcID) - { - totalNumLinks++; - } - } - } - - // ------------------------------- - // Dump all the links to the file - // ------------------------------- - buf.PutInt( totalNumLinks ); - - for (node = 0; node < m_pNetwork->m_iNumNodes; node++) - { - CAI_Node *pNode = m_pNetwork->GetNode(node); - - for (int link = 0; link < pNode->NumLinks(); link++) - { - // Only dump if link source - CAI_Link *pLink = pNode->GetLinkByIndex(link); - if (node == pLink->m_iSrcID) - { - buf.PutShort( pLink->m_iSrcID ); - buf.PutShort( pLink->m_iDestID ); - buf.Put( pLink->m_iAcceptedMoveTypes, sizeof( pLink->m_iAcceptedMoveTypes) ); - } - } - } - - // ------------------------------- - // Dump WC lookup table - // ------------------------------- - CUtlMap wcIDs; - SetDefLessFunc(wcIDs); - bool bCheckForProblems = false; - for (node = 0; node < m_pNetwork->m_iNumNodes; node++) - { - int iPreviousNodeBinding = wcIDs.Find( GetEditOps()->m_pNodeIndexTable[node] ); - if ( iPreviousNodeBinding != wcIDs.InvalidIndex() ) - { - if ( !bCheckForProblems ) - { - DevWarning( "******* MAP CONTAINS DUPLICATE HAMMER NODE IDS! CHECK FOR PROBLEMS IN HAMMER TO CORRECT *******\n" ); - bCheckForProblems = true; - } - DevWarning( " AI node %d is associated with Hammer node %d, but %d is already bound to node %d\n", node, GetEditOps()->m_pNodeIndexTable[node], GetEditOps()->m_pNodeIndexTable[node], wcIDs[iPreviousNodeBinding] ); - } - else - { - wcIDs.Insert( GetEditOps()->m_pNodeIndexTable[node], node ); - } - buf.PutInt( GetEditOps()->m_pNodeIndexTable[node] ); - } - - // ------------------------------- - // Write the file out - // ------------------------------- - - FileHandle_t fh = filesystem->Open( szNrpFilename, "wb" ); - if ( !fh ) - { - DevWarning( 2, "Couldn't create %s!\n", szNrpFilename ); - return; - } - - filesystem->Write( buf.Base(), buf.TellPut(), fh ); - filesystem->Close(fh); -} - -/* Keep this around for debugging -//----------------------------------------------------------------------------- -// Purpose: Only called if network has changed since last time level -// was loaded -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_NetworkManager::SaveNetworkGraph( void ) -{ - // ----------------------------- - // Make sure directories have been made - // ----------------------------- - char szNrpFilename [MAX_PATH];// text node report filename - Q_strncpy( szNrpFilename, "maps" ,sizeof(szNrpFilename)); - filesystem->CreateDirHierarchy( szNrpFilename ); - Q_strncat( szNrpFilename, "/graphs", COPY_ALL_CHARACTERS ); - filesystem->CreateDirHierarchy( szNrpFilename ); - - Q_strncat( szNrpFilename, "/", COPY_ALL_CHARACTERS ); - Q_strncat( szNrpFilename, STRING( gpGlobals->mapname ), COPY_ALL_CHARACTERS ); - Q_strncat( szNrpFilename, ".ain", COPY_ALL_CHARACTERS ); - - FileHandle_t file = filesystem->Open ( szNrpFilename, "w+" ); - - // ----------------------------- - // Make sure the file opened ok - // ----------------------------- - if ( !file ) - { - DevWarning( 2, "Couldn't create %s!\n", szNrpFilename ); - return; - } - - // --------------------------- - // Save the version number - // --------------------------- - filesystem->FPrintf(file,"Version %4d\n",AINET_VERSION_NUMBER); - - // ------------------------------- - // Dump all the nodes to the file - // ------------------------------- - filesystem->FPrintf ( file, "NumNodes: %d\n", m_iNumNodes); - int totalNumLinks = 0; - for (int node = 0; node < m_iNumNodes; node++) - { - filesystem->FPrintf ( file, "Location %4f,%4f,%4f\n",m_pAInode[node]->GetOrigin().x, m_pAInode[node]->GetOrigin().y, m_pAInode[node]->GetOrigin().z ); - for (int hull =0;hullFPrintf ( file, "Voffset %4f\n", m_pAInode[node]->m_flVOffset[hull]); - } - filesystem->FPrintf ( file, "HintType: %4d\n", m_pAInode[node]->m_eHintType ); - filesystem->FPrintf ( file, "HintYaw: %4f\n", m_pAInode[node]->GetYaw() ); - filesystem->FPrintf ( file, "NodeType %4d\n",m_pAInode[node]->GetType()); - filesystem->FPrintf ( file, "NodeInfo %4d\n",m_pAInode[node]->m_eNodeInfo); - filesystem->FPrintf ( file, "Neighbors "); - m_pAInode[node]->m_pNeighborBS->SaveBitString(file); - filesystem->FPrintf ( file, "Visible "); - m_pAInode[node]->m_pVisibleBS->SaveBitString(file); - filesystem->FPrintf ( file, "Connected "); - m_pAInode[node]->m_pConnectedBS->SaveBitString(file); - - filesystem->FPrintf ( file, "NumLinks %4d\n",m_pAInode[node]->NumLinks()); - - for (int link = 0; link < m_pAInode[node]->NumLinks(); link++) - { - // Only dump if link source - if (node == m_pAInode[node]->GetLinkByIndex(link)->m_iSrcID) - { - totalNumLinks++; - } - } - } - - // ------------------------------- - // Dump all the links to the file - // ------------------------------- - filesystem->FPrintf ( file, "TotalNumLinks %4d\n",totalNumLinks); - - for (node = 0; node < m_iNumNodes; node++) - { - for (int link = 0; link < m_pAInode[node]->NumLinks(); link++) - { - // Only dump if link source - if (node == m_pAInode[node]->GetLinkByIndex(link)->m_iSrcID) - { - filesystem->FPrintf ( file, "LinkSrcID %4d\n", m_pAInode[node]->GetLinkByIndex(link)->m_iSrcID); - filesystem->FPrintf ( file, "LinkDestID %4d\n", m_pAInode[node]->GetLinkByIndex(link)->m_iDestID); - - for (int hull =0;hullFPrintf ( file, "Hulls %4d\n", m_pAInode[node]->GetLinkByIndex(link)->m_iAcceptedMoveTypes[hull]); - } - } - } - } - - // ------------------------------- - // Dump WC lookup table - // ------------------------------- - for (node = 0; node < m_iNumNodes; node++) - { - filesystem->FPrintf( file, "%4d\n",m_pNodeIndexTable[node]); - } - - filesystem->Close(file); -} -*/ - -//----------------------------------------------------------------------------- -// Purpose: Only called if network has changed since last time level -// was loaded -//----------------------------------------------------------------------------- - -void CAI_NetworkManager::LoadNetworkGraph( void ) -{ - // --------------------------------------------------- - // If I'm in edit mode don't load, always recalculate - // --------------------------------------------------- - if (engine->IsInEditMode()) - { - return; - } - - if ( !g_pGameRules->FAllowNPCs() ) - { - return; - } - - // ----------------------------- - // Make sure directories have been made - // ----------------------------- - char szNrpFilename[MAX_PATH];// text node report filename - Q_strncpy( szNrpFilename, "maps" ,sizeof(szNrpFilename)); - filesystem->CreateDirHierarchy( szNrpFilename, "DEFAULT_WRITE_PATH" ); - Q_strncat( szNrpFilename, "/graphs", sizeof( szNrpFilename ), COPY_ALL_CHARACTERS ); - filesystem->CreateDirHierarchy( szNrpFilename, "DEFAULT_WRITE_PATH" ); - - Q_strncat( szNrpFilename, "/", sizeof( szNrpFilename ), COPY_ALL_CHARACTERS ); - Q_strncat( szNrpFilename, STRING( gpGlobals->mapname ), sizeof( szNrpFilename ), COPY_ALL_CHARACTERS ); - Q_strncat( szNrpFilename, IsX360() ? ".360.ain" : ".ain", sizeof( szNrpFilename ), COPY_ALL_CHARACTERS ); - - MEM_ALLOC_CREDIT(); - - // Read the file in one gulp - CUtlBuffer buf; - bool bHaveAIN = false; - if ( IsX360() && g_pQueuedLoader->IsMapLoading() ) - { - // .ain was loaded anonymously by bsp, should be ready - void *pData; - int nDataSize; - if ( g_pQueuedLoader->ClaimAnonymousJob( szNrpFilename, &pData, &nDataSize ) ) - { - if ( nDataSize != 0 ) - { - buf.Put( pData, nDataSize ); - bHaveAIN = true; - } - filesystem->FreeOptimalReadBuffer( pData ); - } - } - - if ( !bHaveAIN && !filesystem->ReadFile( szNrpFilename, "game", buf ) ) - { - DevWarning( 2, "Couldn't read %s!\n", szNrpFilename ); - return; - } - - // --------------------------- - // Check the version number - // --------------------------- - if ( buf.GetChar() == 'V' && buf.GetChar() == 'e' && buf.GetChar() == 'r' ) - { - DevMsg( "AI node graph %s is out of date\n", szNrpFilename ); - return; - } - - buf.SeekGet( CUtlBuffer::SEEK_HEAD, 0 ); - - int version = buf.GetInt(); - if ( version != AINET_VERSION_NUMBER) - { - DevMsg( "AI node graph %s is out of date\n", szNrpFilename ); - return; - } - - int mapversion = buf.GetInt(); - if ( mapversion != gpGlobals->mapversion && !g_ai_norebuildgraph.GetBool() ) - { - DevMsg( "AI node graph %s is out of date (map version changed)\n", szNrpFilename ); - return; - } - - // ---------------------------------------- - // Get the network size and allocate space - // ---------------------------------------- - int numNodes = buf.GetInt(); - - if ( numNodes > MAX_NODES || numNodes < 0 ) - { - Error( "AI node graph %s is corrupt\n", szNrpFilename ); - DevMsg( (const char *)buf.Base() ); - DevMsg( "\n" ); - Assert( 0 ); - return; - } - - // ------------------------------------------------------------------------ - // If in wc_edit mode allocate extra space for nodes that might be created - // ------------------------------------------------------------------------ - if ( engine->IsInEditMode() ) - { - numNodes = MAX( numNodes, 1024 ); - } - - m_pNetwork->m_pAInode = new CAI_Node*[MAX( numNodes, 1 )]; - memset( m_pNetwork->m_pAInode, 0, sizeof( CAI_Node* ) * MAX( numNodes, 1 ) ); - - // ------------------------------- - // Load all the nodes to the file - // ------------------------------- - int node; - for ( node = 0; node < numNodes; node++) - { - Vector origin; - float yaw; - origin.x = buf.GetFloat(); - origin.y = buf.GetFloat(); - origin.z = buf.GetFloat(); - yaw = buf.GetFloat(); - - CAI_Node *new_node = m_pNetwork->AddNode( origin, yaw ); - - buf.Get( new_node->m_flVOffset, sizeof(new_node->m_flVOffset) ); - new_node->m_eNodeType = (NodeType_e)buf.GetChar(); - if ( IsX360() ) - { - buf.SeekGet( CUtlBuffer::SEEK_CURRENT, 3 ); - } - - new_node->m_eNodeInfo = buf.GetUnsignedShort(); - new_node->m_zone = buf.GetShort(); - } - - // ------------------------------- - // Load all the links to the fild - // ------------------------------- - int totalNumLinks = buf.GetInt(); - - for (int link = 0; link < totalNumLinks; link++) - { - int srcID, destID; - - srcID = buf.GetShort(); - destID = buf.GetShort(); - - CAI_Link *pLink = m_pNetwork->CreateLink( srcID, destID );; - - byte ignored[NUM_HULLS]; - byte *pDest = ( pLink ) ? &pLink->m_iAcceptedMoveTypes[0] : &ignored[0]; - buf.Get( pDest, sizeof(ignored) ); - } - - // ------------------------------- - // Load WC lookup table - // ------------------------------- - delete [] GetEditOps()->m_pNodeIndexTable; - GetEditOps()->m_pNodeIndexTable = new int[MAX( m_pNetwork->m_iNumNodes, 1 )]; - memset( GetEditOps()->m_pNodeIndexTable, 0, sizeof( int ) *MAX( m_pNetwork->m_iNumNodes, 1 ) ); - - for (node = 0; node < m_pNetwork->m_iNumNodes; node++) - { - GetEditOps()->m_pNodeIndexTable[node] = buf.GetInt(); - } - - -#if 1 - CUtlRBTree usedIds; - CUtlRBTree reportedIds; - SetDefLessFunc( usedIds ); - SetDefLessFunc( reportedIds ); - - bool printedHeader = false; - - for (node = 0; node < m_pNetwork->m_iNumNodes; node++) - { - int editorId = GetEditOps()->m_pNodeIndexTable[node]; - if ( editorId != NO_NODE ) - { - if ( usedIds.Find( editorId ) != usedIds.InvalidIndex() ) - { - if ( !printedHeader ) - { - Warning( "** Duplicate Hammer Node IDs: " ); - printedHeader = true; - } - - if ( reportedIds.Find( editorId ) == reportedIds.InvalidIndex() ) - { - DevMsg( "%d, ", editorId ); - reportedIds.Insert( editorId ); - } - } - else - usedIds.Insert( editorId ); - } - } - - if ( printedHeader ) - DevMsg( "\n** Should run \"Check For Problems\" on the VMF then verify dynamic links\n" ); -#endif - - gm_fNetworksLoaded = true; - CAI_DynamicLink::gm_bInitialized = false; -} - -/* Keep this around for debugging -//----------------------------------------------------------------------------- -// Purpose: Only called if network has changed since last time level -// was loaded -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_NetworkManager::LoadNetworkGraph( void ) -{ - // --------------------------------------------------- - // If I'm in edit mode don't load, always recalculate - // --------------------------------------------------- - if (engine->IsInEditMode()) - { - return; - } - - // ----------------------------- - // Make sure directories have been made - // ----------------------------- - char szNrpFilename [MAX_PATH];// text node report filename - Q_strncpy( szNrpFilename, "maps" ,sizeof(szNrpFilename)); - filesystem->CreateDirHierarchy( szNrpFilename ); - Q_strncat( szNrpFilename, "/graphs", COPY_ALL_CHARACTERS ); - filesystem->CreateDirHierarchy( szNrpFilename ); - - Q_strncat( szNrpFilename, "/", COPY_ALL_CHARACTERS ); - Q_strncat( szNrpFilename, STRING( gpGlobals->mapname ), COPY_ALL_CHARACTERS ); - Q_strncat( szNrpFilename, ".ain", COPY_ALL_CHARACTERS ); - - FileHandle_t file = filesystem->Open ( szNrpFilename, "r" ); - - // ----------------------------- - // Make sure the file opened ok - // ----------------------------- - if ( !file ) - { - DevWarning( 2, "Couldn't create %s!\n", szNrpFilename ); - return; - } - - // --------------------------- - // Check the version number - // --------------------------- - char temps[256]; - int version; - fscanf(file,"%255s",&temps); - fscanf(file, "%i\n",&version); - if (version!=AINET_VERSION_NUMBER) - { - return; - } - - // ---------------------------------------- - // Get the network size and allocate space - // ---------------------------------------- - int numNodes; - fscanf(file,"%255s",&temps); - fscanf ( file, "%d\n", &numNodes); - - // ------------------------------------------------------------------------ - // If in wc_edit mode allocate extra space for nodes that might be created - // ------------------------------------------------------------------------ - if ( engine->IsInEditMode() ) - { - numNodes = MAX( numNodes, 1024 ); - } - - m_pAInode = new CAI_Node*[numNodes]; - if ( !m_pAInode ) - { - Warning( "LoadNetworkGraph: Not enough memory to create %i nodes\n", numNodes ); - Assert(0); - return; - } - - // ------------------------------- - // Load all the nodes to the file - // ------------------------------- - for (int node = 0; node < numNodes; node++) - { - CAI_Node *new_node = AddNode(); - - Vector origin; - fscanf(file,"%255s",&temps); - fscanf(file, "%f,%f,%f\n", &new_node->GetOrigin().x, &new_node->GetOrigin().y, &new_node->GetOrigin().z ); - for (int hull =0;hullm_flVOffset[hull]); - } - fscanf(file,"%255s",&temps); - fscanf(file, "%d\n", &new_node->m_eHintType ); - fscanf(file,"%255s",&temps); - fscanf(file, "%f\n", &new_node->GetYaw() ); - fscanf(file,"%255s",&temps); - fscanf(file, "%d\n",&new_node->GetType()); - fscanf(file,"%255s",&temps); - fscanf(file, "%d\n",&new_node->m_eNodeInfo); - - fscanf(file,"%255s",&temps); - new_node->m_pNeighborBS = new CVarBitVec(numNodes); - new_node->m_pNeighborBS->LoadBitString(file); - - fscanf(file,"%255s",&temps); - new_node->m_pVisibleBS = new CVarBitVec(numNodes); - new_node->m_pVisibleBS->LoadBitString(file); - - fscanf(file,"%255s",&temps); - new_node->m_pConnectedBS = new CVarBitVec(numNodes); - new_node->m_pConnectedBS->LoadBitString(file); - - fscanf(file,"%255s",&temps); - int numLinks; - fscanf (file, "%4d",&numLinks); - - // ------------------------------------------------------------------------ - // If in wc_edit mode allocate extra space for nodes that might be created - // ------------------------------------------------------------------------ - if ( engine->IsInEditMode() ) - { - numLinks = AI_MAX_NODE_LINKS; - } - - //Assert ( numLinks >= 1 ); - new_node->AllocateLinkSpace( numLinks ); - } - - // ------------------------------- - // Load all the links to the fild - // ------------------------------- - int totalNumLinks; - fscanf(file,"%255s",&temps); - fscanf ( file, "%d\n",&totalNumLinks); - - for (int link = 0; link < totalNumLinks; link++) - { - CAI_Link *new_link = new CAI_Link; - - fscanf(file,"%255s",&temps); - fscanf ( file, "%4d\n", &new_link->m_iSrcID); - - fscanf(file,"%255s",&temps); - fscanf ( file, "%4d\n", &new_link->m_iDestID); - - for (int hull =0;hullm_iAcceptedMoveTypes[hull]); - } - // Now add link to source and destination nodes - m_pAInode[new_link->m_iSrcID]->AddLink(new_link); - m_pAInode[new_link->m_iDestID]->AddLink(new_link); - } - - // ------------------------------- - // Load WC lookup table - // ------------------------------- - m_pNodeIndexTable = new int[m_iNumNodes]; - - for (node = 0; node < m_iNumNodes; node++) - { - fscanf( file, "%d\n",&m_pNodeIndexTable[node]); - } - - CAI_NetworkManager::NetworksLoaded() = true; - fclose(file); -} -*/ - -//----------------------------------------------------------------------------- -// Purpose: Deletes all AINetworks from memory -//----------------------------------------------------------------------------- - -void CAI_NetworkManager::DeleteAllAINetworks(void) -{ - CAI_DynamicLink::gm_bInitialized = false; - gm_fNetworksLoaded = false; - g_pBigAINet = NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Only called if network has changed since last time level -// was loaded -//----------------------------------------------------------------------------- - -void CAI_NetworkManager::BuildNetworkGraph( void ) -{ - if ( m_bDontSaveGraph ) - return; - - CAI_DynamicLink::gm_bInitialized = false; - g_AINetworkBuilder.Build( m_pNetwork ); - - // If I'm loading for the first time save. Otherwise I'm - // doing a wc edit and I don't want to save - if (!CAI_NetworkManager::NetworksLoaded()) - { - SaveNetworkGraph(); - - gm_fNetworksLoaded = true; - } -} - -//------------------------------------------------------------------------------ -bool g_bAIDisabledByUser = false; - -void CAI_NetworkManager::InitializeAINetworks() -{ - // For not just create a single AI Network called "BigNet" - // At some later point we may have mulitple AI networks - CAI_NetworkManager *pNetwork; - g_pAINetworkManager = pNetwork = CREATE_ENTITY( CAI_NetworkManager, "ai_network" ); - pNetwork->AddEFlags( EFL_KEEP_ON_RECREATE_ENTITIES ); - g_pBigAINet = pNetwork->GetNetwork(); - pNetwork->SetName( AllocPooledString("BigNet") ); - pNetwork->Spawn(); - if ( engine->IsInEditMode() ) - { - g_ai_norebuildgraph.SetValue( 0 ); - } - if ( CAI_NetworkManager::IsAIFileCurrent( STRING( gpGlobals->mapname ) ) ) - { - pNetwork->LoadNetworkGraph(); - if ( !g_bAIDisabledByUser ) - { - CAI_BaseNPC::m_nDebugBits &= ~bits_debugDisableAI; - } - } - - // Reset node counter used during load - CNodeEnt::m_nNodeCount = 0; - - pNetwork->SetThink( &CAI_NetworkManager::DelayedInit ); - pNetwork->SetNextThink( gpGlobals->curtime ); -} - -// UNDONE: Where should this be defined? -#ifndef MAX_PATH -#define MAX_PATH 256 -#endif - -//----------------------------------------------------------------------------- -// Purpose: Returns true if the AINetwork data files are up to date -//----------------------------------------------------------------------------- - -bool CAI_NetworkManager::IsAIFileCurrent ( const char *szMapName ) -{ - char szBspFilename[MAX_PATH]; - char szGraphFilename[MAX_PATH]; - - if ( !g_pGameRules->FAllowNPCs() ) - { - return false; - } - - if ( IsX360() && ( filesystem->GetDVDMode() == DVDMODE_STRICT ) ) - { - // dvd build process validates and guarantees correctness, timestamps are allowed to be wrong - return true; - } - - Q_snprintf( szBspFilename, sizeof( szBspFilename ), "maps/%s%s.bsp" ,szMapName, GetPlatformExt() ); - Q_snprintf( szGraphFilename, sizeof( szGraphFilename ), "maps/graphs/%s%s.ain", szMapName, GetPlatformExt() ); - - int iCompare; - if ( engine->CompareFileTime( szBspFilename, szGraphFilename, &iCompare ) ) - { - if ( iCompare > 0 ) - { - // BSP file is newer. - if ( g_ai_norebuildgraph.GetInt() ) - { - // The user has specified that they wish to override the - // rebuilding of outdated nodegraphs (see top of this file) - if ( filesystem->FileExists( szGraphFilename ) ) - { - // Display these messages only if the graph exists, and the - // user is asking to override the rebuilding. If the graph does - // not exist, we're going to build it whether the user wants to or - // not. - DevMsg( 2, ".AIN File will *NOT* be updated. User Override.\n\n" ); - DevMsg( "\n*****Node Graph Rebuild OVERRIDDEN by user*****\n\n" ); - } - return true; - } - else - { - // Graph is out of date. Rebuild at usual. - DevMsg( 2, ".AIN File will be updated\n\n" ); - return false; - } - } - return true; - } - return false; -} - -//------------------------------------------------------------------------------ - -void CAI_NetworkManager::Spawn ( void ) -{ - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NONE ); -} - -//------------------------------------------------------------------------------ - -void CAI_NetworkManager::DelayedInit( void ) -{ - if ( !g_pGameRules->FAllowNPCs() ) - { - SetThink ( NULL ); - return; - } - - if ( !g_ai_norebuildgraph.GetInt() ) - { - // ---------------------------------------------------------- - // Actually enter DelayedInit twice when rebuilding the - // node graph. The first time through we just print the - // warning message. We only actually do the rebuild on - // the second pass to make sure the message hits the screen - // ---------------------------------------------------------- - if (m_bNeedGraphRebuild) - { - Assert( !m_bDontSaveGraph ); - - BuildNetworkGraph(); // For now only one AI Network - - if (engine->IsInEditMode()) - { - engine->ServerCommand("exec map_edit.cfg\n"); - } - - SetThink ( NULL ); - if ( !g_bAIDisabledByUser ) - { - CAI_BaseNPC::m_nDebugBits &= ~bits_debugDisableAI; - } - } - - - // -------------------------------------------- - // If I haven't loaded a network, or I'm in - // WorldCraft edit mode rebuild the network - // -------------------------------------------- - else if ( !m_bDontSaveGraph && ( !CAI_NetworkManager::NetworksLoaded() || engine->IsInEditMode() ) ) - { -#ifdef _WIN32 - // -------------------------------------------------------- - // If in edit mode start WC session and make sure we are - // running the same map in WC and the engine - // -------------------------------------------------------- - if (engine->IsInEditMode()) - { - int status = Editor_BeginSession(STRING(gpGlobals->mapname), gpGlobals->mapversion, false); - if (status == Editor_NotRunning) - { - DevMsg("\nAborting map_edit\nWorldcraft not running...\n\n"); - UTIL_CenterPrintAll( "Worldcraft not running...\n" ); - engine->ServerCommand("disconnect\n"); - SetThink(NULL); - return; - } - else if (status == Editor_BadCommand) - { - DevMsg("\nAborting map_edit\nWC/Engine map versions different...\n\n"); - UTIL_CenterPrintAll( "WC/Engine map versions different...\n" ); - engine->ServerCommand("disconnect\n"); - SetThink(NULL); - return; - } - else - { - // Increment version number when session begins - gpGlobals->mapversion++; - } - } -#endif - - DevMsg( "Node Graph out of Date. Rebuilding...\n" ); - UTIL_CenterPrintAll( "Node Graph out of Date. Rebuilding...\n" ); - m_bNeedGraphRebuild = true; - g_pAINetworkManager->SetNextThink( gpGlobals->curtime + 1 ); - return; - } - - // -------------------------------------------- - // Initialize any dynamic links - // -------------------------------------------- - CAI_DynamicLink::InitDynamicLinks(); - FixupHints(); - } - - - GetEditOps()->OnInit(); - - m_fInitalized = true; - - if ( g_AI_Manager.NumAIs() != 0 && g_pBigAINet->NumNodes() == 0 ) - DevMsg( "WARNING: Level contains NPCs but has no path nodes\n" ); -} - -//------------------------------------------------------------------------------ - -void CAI_NetworkManager::FixupHints() -{ - AIHintIter_t iter; - CAI_Hint *pHint = CAI_HintManager::GetFirstHint( &iter ); - while ( pHint ) - { - pHint->FixupTargetNode(); - pHint = CAI_HintManager::GetNextHint( &iter ); - } -} - -//----------------------------------------------------------------------------- -// CAI_NetworkEditTools -//----------------------------------------------------------------------------- - -CAI_Node* CAI_NetworkEditTools::m_pLastDeletedNode = NULL; // For undo in wc edit mode -int CAI_NetworkEditTools::m_iHullDrawNum = HULL_HUMAN; // Which hulls to draw -int CAI_NetworkEditTools::m_iVisibilityNode = NO_NODE; -int CAI_NetworkEditTools::m_iGConnectivityNode = NO_NODE; -bool CAI_NetworkEditTools::m_bAirEditMode = false; -bool CAI_NetworkEditTools::m_bLinkEditMode = false; -float CAI_NetworkEditTools::m_flAirEditDistance = 300; - -#ifdef AI_PERF_MON - // Performance stats (only for development) - int CAI_NetworkEditTools::m_nPerfStatNN = 0; - int CAI_NetworkEditTools::m_nPerfStatPB = 0; - float CAI_NetworkEditTools::m_fNextPerfStatTime = -1; -#endif - -//------------------------------------------------------------------------------ - -void CAI_NetworkEditTools::OnInit() -{ - // -------------------------------------------- - // If I'm not in edit mode delete WC ID table - // -------------------------------------------- - if ( !engine->IsInEditMode() ) - { -// delete[] m_pNodeIndexTable; // For now only one AI Network called "BigNet" -// m_pNodeIndexTable = NULL; - } -} - -//------------------------------------------------------------------------------ -// Purpose : Given a WorldCraft node ID, return the associated engine ID -// Input : -// Output : -//------------------------------------------------------------------------------ -int CAI_NetworkEditTools::GetNodeIdFromWCId( int nWCId ) -{ - if ( nWCId == -1 ) - return -1; - - if (!m_pNodeIndexTable) - { - DevMsg("ERROR: Trying to get WC ID with no table!\n"); - return -1; - } - - if (!m_pNetwork->NumNodes()) - { - DevMsg("ERROR: Trying to get WC ID with no network!\n"); - return -1; - } - - for (int i=0;iNumNodes();i++) - { - if (m_pNodeIndexTable[i] == nWCId) - { - return i; - } - } - return -1; -} - -//----------------------------------------------------------------------------- - -int CAI_NetworkEditTools::GetWCIdFromNodeId( int nNodeId ) -{ - if ( nNodeId == -1 || nNodeId >= m_pNetwork->NumNodes() ) - return -1; - return m_pNodeIndexTable[nNodeId]; -} - -//----------------------------------------------------------------------------- -// Purpose: Find the nearest ainode that is faced from the given location -// and within the angular threshold (ignores worldspawn). -// DO NOT USE FOR ANY RUN TIME RELEASE CODE -// Used for selection of nodes in debugging display only! -// -//----------------------------------------------------------------------------- - -CAI_Node *CAI_NetworkEditTools::FindAINodeNearestFacing( const Vector &origin, const Vector &facing, float threshold, int nNodeType) -{ - float bestDot = threshold; - CAI_Node *best = NULL; - - CAI_Network* aiNet = g_pBigAINet; - - for (int node =0; node < aiNet->NumNodes();node++) - { - if (aiNet->GetNode(node)->GetType() != NODE_DELETED) - { - // Pick nodes that are in the current editing type - if ( nNodeType == NODE_ANY || - nNodeType == aiNet->GetNode(node)->GetType() ) - { - // Make vector to node - Vector to_node = (aiNet->GetNode(node)->GetPosition(m_iHullDrawNum) - origin); - - VectorNormalize( to_node ); - float dot = DotProduct (facing , to_node ); - if (dot > bestDot) - { - // Make sure I have a line of sight to it - trace_t tr; - AI_TraceLine ( origin, aiNet->GetNode(node)->GetPosition(m_iHullDrawNum), - MASK_BLOCKLOS, NULL, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction == 1.0 ) - { - bestDot = dot; - best = aiNet->GetNode(node); - } - } - } - } - } - return best; -} - - -Vector PointOnLineNearestPoint(const Vector& vStartPos, const Vector& vEndPos, const Vector& vPoint) -{ - Vector vEndToStart = (vEndPos - vStartPos); - Vector vOrgToStart = (vPoint - vStartPos); - float fNumerator = DotProduct(vEndToStart,vOrgToStart); - float fDenominator = vEndToStart.Length() * vOrgToStart.Length(); - float fIntersectDist = vOrgToStart.Length()*(fNumerator/fDenominator); - VectorNormalize( vEndToStart ); - Vector vIntersectPos = vStartPos + vEndToStart * fIntersectDist; - - return vIntersectPos; -} - -//----------------------------------------------------------------------------- -// Purpose: Find the nearest ainode that is faced from the given location -// and within the angular threshold (ignores worldspawn). -// DO NOT USE FOR ANY RUN TIME RELEASE CODE -// Used for selection of nodes in debugging display only! -//----------------------------------------------------------------------------- - -CAI_Link *CAI_NetworkEditTools::FindAILinkNearestFacing( const Vector &vOrigin, const Vector &vFacing, float threshold) -{ - float bestDot = threshold; - CAI_Link *best = NULL; - - CAI_Network* aiNet = g_pBigAINet; - - for (int node =0; node < aiNet->NumNodes();node++) - { - if (aiNet->GetNode(node)->GetType() != NODE_DELETED) - { - // Pick nodes that are in the current editing type - if (( m_bAirEditMode && aiNet->GetNode(node)->GetType() == NODE_AIR) || - (!m_bAirEditMode && aiNet->GetNode(node)->GetType() == NODE_GROUND)) - { - // Go through each link - for (int link=0; link < aiNet->GetNode(node)->NumLinks();link++) - { - CAI_Link *nodeLink = aiNet->GetNode(node)->GetLinkByIndex(link); - - // Find position on link that I am looking - int endID = nodeLink->DestNodeID(node); - Vector startPos = aiNet->GetNode(node)->GetPosition(m_iHullDrawNum); - Vector endPos = aiNet->GetNode(endID)->GetPosition(m_iHullDrawNum); - Vector vNearest = PointOnLineNearestPoint(startPos, endPos, vOrigin); - - // Get angle between viewing dir. and nearest point on line - Vector vOriginToNearest = (vNearest - vOrigin); - float fNumerator = DotProduct(vOriginToNearest,vFacing); - float fDenominator = vOriginToNearest.Length(); - float fAngleToNearest = acos(fNumerator/fDenominator); - - // If not facing the line reject - if (fAngleToNearest > 1.57) - { - continue; - } - - // Calculate intersection of facing direction to nearest point - float fIntersectDist = vOriginToNearest.Length() * tan(fAngleToNearest); - Vector dir = endPos-startPos; - float fLineLen = VectorNormalize( dir ); - Vector vIntersection = vNearest + (fIntersectDist * dir); - - // Reject of beyond end of line - if (((vIntersection - startPos).Length() > fLineLen) || - ((vIntersection - endPos ).Length() > fLineLen) ) - { - continue; - } - - // Now test dot to the look position - Vector toLink = vIntersection - vOrigin; - VectorNormalize(toLink); - float lookDot = DotProduct (vFacing , toLink); - if (lookDot > bestDot) - { - // Make sure I have a line of sight to it - trace_t tr; - AI_TraceLine ( vOrigin, vIntersection, MASK_BLOCKLOS, NULL, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction == 1.0 ) - { - bestDot = lookDot; - best = nodeLink; - } - } - } - } - } - } - return best; -} - - -//----------------------------------------------------------------------------- -// Purpose: Used for WC edit more. Marks that the network should be -// rebuild and turns of any displays that have been invalidated -// as the network is now out of date -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_NetworkEditTools::SetRebuildFlags( void ) -{ - m_debugNetOverlays |= bits_debugNeedRebuild; - m_debugNetOverlays &= ~bits_debugOverlayConnections; - m_debugNetOverlays &= ~bits_debugOverlayGraphConnect; - m_debugNetOverlays &= ~bits_debugOverlayVisibility; - m_debugNetOverlays &= ~bits_debugOverlayHulls; - - // Not allowed to edit links when graph outdated - m_bLinkEditMode = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Used for WC edit more. After node graph has been rebuild -// marks it as so and turns connection display back on -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_NetworkEditTools::ClearRebuildFlags( void ) -{ - m_debugNetOverlays |= bits_debugOverlayConnections; - - // ------------------------------------------ - // Clear all rebuild flags in nodes - // ------------------------------------------ - for (int i = 0; i < m_pNetwork->NumNodes(); i++) - { - m_pNetwork->GetNode(i)->m_eNodeInfo &= ~bits_NODE_WC_CHANGED; - m_pNetwork->GetNode(i)->ClearNeedsRebuild(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Sets the next hull to draw, or none if at end of hulls -//----------------------------------------------------------------------------- -void CAI_NetworkEditTools::DrawNextHull(const char *ainet_name) -{ - m_iHullDrawNum++; - if (m_iHullDrawNum == NUM_HULLS) - { - m_iHullDrawNum = 0; - } - - // Recalculate usable nodes for current hull - g_pAINetworkManager->GetEditOps()->RecalcUsableNodesForHull(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_NetworkEditTools::DrawHull(Hull_t eHull) -{ - m_iHullDrawNum = eHull; - if (m_iHullDrawNum >= NUM_HULLS) - { - m_iHullDrawNum = 0; - } - - // Recalculate usable nodes for current hull - g_pAINetworkManager->GetEditOps()->RecalcUsableNodesForHull(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Used just for debug display, to color nodes grey that the -// currently selected hull size can't use. -//----------------------------------------------------------------------------- - -void CAI_NetworkEditTools::RecalcUsableNodesForHull(void) -{ - // ----------------------------------------------------- - // Use test hull to check hull sizes - // ----------------------------------------------------- - CAI_TestHull *m_pTestHull = CAI_TestHull::GetTestHull(); - m_pTestHull->GetNavigator()->SetNetwork( g_pBigAINet ); - m_pTestHull->SetHullType((Hull_t)m_iHullDrawNum); - m_pTestHull->SetHullSizeNormal(); - - for (int node=0;nodeNumNodes();node++) - { - if ( ( m_pNetwork->GetNode(node)->m_eNodeInfo & ( HullToBit( (Hull_t)m_iHullDrawNum ) << NODE_ENT_FLAGS_SHIFT ) ) || - m_pTestHull->GetNavigator()->CanFitAtNode(node)) - { - m_pNetwork->GetNode(node)->m_eNodeInfo &= ~bits_NODE_WONT_FIT_HULL; - } - else - { - m_pNetwork->GetNode(node)->m_eNodeInfo |= bits_NODE_WONT_FIT_HULL; - } - } - CAI_TestHull::ReturnTestHull(); -} - -//----------------------------------------------------------------------------- -// Purpose: Sets debug bits -//----------------------------------------------------------------------------- - -void CAI_NetworkEditTools::SetDebugBits(const char *ainet_name,int debug_bit) -{ - CAI_NetworkEditTools *pEditOps = g_pAINetworkManager->GetEditOps(); - if ( !pEditOps ) - return; - - if (debug_bit & bits_debugOverlayNodes) - { - if (pEditOps->m_debugNetOverlays & bits_debugOverlayNodesLev2) - { - pEditOps->m_debugNetOverlays &= ~bits_debugOverlayNodes; - pEditOps->m_debugNetOverlays &= ~bits_debugOverlayNodesLev2; - } - else if (pEditOps->m_debugNetOverlays & bits_debugOverlayNodes) - { - pEditOps->m_debugNetOverlays |= bits_debugOverlayNodesLev2; - } - else - { - pEditOps->m_debugNetOverlays |= bits_debugOverlayNodes; - - // Recalculate usable nodes for current hull - pEditOps->RecalcUsableNodesForHull(); - } - } - else if (pEditOps->m_debugNetOverlays & debug_bit) - { - pEditOps->m_debugNetOverlays &= ~debug_bit; - } - else - { - pEditOps->m_debugNetOverlays |= debug_bit; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draws edit display info on screen -//----------------------------------------------------------------------------- - -void CAI_NetworkEditTools::DrawEditInfoOverlay(void) -{ - hudtextparms_s tTextParam; - tTextParam.x = 0.8; - tTextParam.y = 0.8; - tTextParam.effect = 0; - tTextParam.r1 = 255; - tTextParam.g1 = 255; - tTextParam.b1 = 255; - tTextParam.a1 = 255; - tTextParam.r2 = 255; - tTextParam.g2 = 255; - tTextParam.b2 = 255; - tTextParam.a2 = 255; - tTextParam.fadeinTime = 0; - tTextParam.fadeoutTime = 0; - tTextParam.holdTime = 1; - tTextParam.fxTime = 0; - tTextParam.channel = 0; - - char hullTypeTxt[50]; - char nodeTypeTxt[50]; - char editTypeTxt[50]; - char outTxt[255]; - - Q_snprintf(hullTypeTxt,sizeof(hullTypeTxt)," %s",NAI_Hull::Name(m_iHullDrawNum)); - Q_snprintf(outTxt,sizeof(outTxt),"Displaying:\n%s\n\n", hullTypeTxt); - - if (engine->IsInEditMode()) - { - char outTxt2[255]; - Q_snprintf(nodeTypeTxt,sizeof(nodeTypeTxt)," %s (l)", m_bLinkEditMode ? "Links":"Nodes"); - Q_snprintf(editTypeTxt,sizeof(editTypeTxt)," %s (m)", m_bAirEditMode ? "Air":"Ground"); - Q_snprintf(outTxt2,sizeof(outTxt2),"Editing:\n%s\n%s", editTypeTxt,nodeTypeTxt); - Q_strncat(outTxt,outTxt2,sizeof(outTxt), COPY_ALL_CHARACTERS); - - // Print in red if network needs rebuilding - if (m_debugNetOverlays & bits_debugNeedRebuild) - { - tTextParam.g1 = 0; - tTextParam.b1 = 0; - } - } - - UTIL_HudMessageAll( tTextParam, outTxt ); - - -} - -//----------------------------------------------------------------------------- -// Purpose: Draws AINetwork on the screen -//----------------------------------------------------------------------------- - -void CAI_NetworkEditTools::DrawAINetworkOverlay(void) -{ - // ------------------------------------ - // If network isn't loaded yet return - // ------------------------------------ - if (!CAI_NetworkManager::NetworksLoaded()) - { - return; - } - - // ---------------------------------------------- - // So we don't fill up the client message queue - // with node drawing messages, only send them - // in chuncks - // ---------------------------------------------- - static int startDrawNode = 0; - static int endDrawNode = 0; - static float flDrawDuration; - endDrawNode = startDrawNode + 20; - flDrawDuration = 0.1 * (m_pNetwork->NumNodes()-1)/20; - if ( flDrawDuration < .1 ) - flDrawDuration = .1; - if (endDrawNode > m_pNetwork->NumNodes()) - { - endDrawNode = m_pNetwork->NumNodes(); - } - - // --------------------- - // Draw grid - // --------------------- - if (m_debugNetOverlays & bits_debugOverlayGrid) - { - // Trace a line to where player is looking - CBasePlayer* pPlayer = UTIL_PlayerByIndex(CBaseEntity::m_nDebugPlayer); - - if (pPlayer) - { - Vector vForward; - Vector vSource = pPlayer->EyePosition(); - pPlayer->EyeVectors( &vForward ); - - trace_t tr; - AI_TraceLine ( vSource, vSource + vForward * 2048, MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &tr); - - float dotPr = DotProduct(Vector(0,0,1),tr.plane.normal); - if (tr.fraction != 1.0 && dotPr > 0.5) - { - NDebugOverlay::Grid( tr.endpos + Vector(0,0,1) ); - } - } - } - - // -------------------- - CAI_Node **pAINode = m_pNetwork->AccessNodes(); - - // -------------------- - // Draw the graph connectivity - // --------------------- - if (m_debugNetOverlays & bits_debugOverlayGraphConnect) - { - // --------------------------------------------------- - // If network needs rebuilding do so before display - // -------------------------------------------------- - if (m_debugNetOverlays & bits_debugNeedRebuild) - { - m_pManager->RebuildNetworkGraph(); - } - else if (m_iGConnectivityNode != NO_NODE) - { - for (int node=0;nodeNumNodes();node++) - { - if ( m_pNetwork->IsConnected( m_iGConnectivityNode, node) ) - { - Vector srcPos = pAINode[m_iGConnectivityNode]->GetPosition(m_iHullDrawNum); - Vector desPos = pAINode[node]->GetPosition(m_iHullDrawNum); - NDebugOverlay::Line(srcPos, desPos, 255,0,255, false,0); - } - } - } - } - - // -------------------- - // Draw the hulls - // --------------------- - if (m_debugNetOverlays & bits_debugOverlayHulls) - { - // --------------------------------------------------- - // If network needs rebuilding do so before display - // -------------------------------------------------- - if (m_debugNetOverlays & bits_debugNeedRebuild) - { - m_pManager->RebuildNetworkGraph(); - } - else - { - for (int node=startDrawNode;nodeNumLinks();link++) - { - // Only draw link once - if (pAINode[node]->GetLinkByIndex(link)->DestNodeID(node) < node) - { - - Vector srcPos = pAINode[pAINode[node]->GetLinkByIndex(link)->m_iSrcID]->GetPosition(m_iHullDrawNum); - Vector desPos = pAINode[pAINode[node]->GetLinkByIndex(link)->m_iDestID]->GetPosition(m_iHullDrawNum); - Vector direction = desPos - srcPos; - float length = VectorNormalize(direction); - Vector hullMins = NAI_Hull::Mins(m_iHullDrawNum); - Vector hullMaxs = NAI_Hull::Maxs(m_iHullDrawNum); - hullMaxs.x = length + hullMaxs.x; - - if (pAINode[node]->GetLinkByIndex(link)->m_iAcceptedMoveTypes[m_iHullDrawNum] & bits_CAP_MOVE_FLY) - { - NDebugOverlay::BoxDirection(srcPos, hullMins, hullMaxs, direction, 100,255,255,20,flDrawDuration); - } - - if (pAINode[node]->GetLinkByIndex(link)->m_iAcceptedMoveTypes[m_iHullDrawNum] & bits_CAP_MOVE_CLIMB) - { - // Display as a vertical slice up the climbing surface unless dismount node - if (pAINode[pAINode[node]->GetLinkByIndex(link)->m_iSrcID]->GetOrigin() != pAINode[pAINode[node]->GetLinkByIndex(link)->m_iDestID]->GetOrigin()) - { - hullMaxs.x = hullMaxs.x - length; - if (srcPos.z < desPos.z) - { - hullMaxs.z = length + hullMaxs.z; - } - else - { - hullMins.z = hullMins.z - length; - } - direction = Vector(0,1,0); - - } - NDebugOverlay::BoxDirection(srcPos, hullMins, hullMaxs, direction, 255,0,255,20,flDrawDuration); - } - - if (pAINode[node]->GetLinkByIndex(link)->m_iAcceptedMoveTypes[m_iHullDrawNum] & bits_CAP_MOVE_GROUND) - { - NDebugOverlay::BoxDirection(srcPos, hullMins, hullMaxs, direction, 0,255,50,20,flDrawDuration); - } - - else if (pAINode[node]->GetLinkByIndex(link)->m_iAcceptedMoveTypes[m_iHullDrawNum] & bits_CAP_MOVE_JUMP) - { - NDebugOverlay::BoxDirection(srcPos, hullMins, hullMaxs, direction, 0,0,255,20,flDrawDuration); - } - } - } - } - } - } - - // -------------------- - // Draw the hints - // --------------------- - if (m_debugNetOverlays & bits_debugOverlayHints) - { - CAI_HintManager::DrawHintOverlays(flDrawDuration); - } - - // ------------------------------- - // Draw the nodes and connections - // ------------------------------- - if (m_debugNetOverlays & (bits_debugOverlayNodes | bits_debugOverlayConnections)) - { - for (int node=startDrawNode;nodeGetType() != NODE_DELETED) - { - // -------------------- - // Draw the connections - // --------------------- - if (m_debugNetOverlays & bits_debugOverlayConnections) - { - // --------------------------------------------------- - // If network needs rebuilding do so before display - // -------------------------------------------------- - if (m_debugNetOverlays & bits_debugNeedRebuild) - { - m_pManager->RebuildNetworkGraph(); - } - else - { - for (int link=0;linkNumLinks();link++) { - - // Only draw link once - if (pAINode[node]->GetLinkByIndex(link)->DestNodeID(node) < node) - { - int srcID = pAINode[node]->GetLinkByIndex(link)->m_iSrcID; - int desID = pAINode[node]->GetLinkByIndex(link)->m_iDestID; - - Vector srcPos = pAINode[srcID]->GetPosition(m_iHullDrawNum); - Vector desPos = pAINode[desID]->GetPosition(m_iHullDrawNum); - - int srcType = pAINode[pAINode[node]->GetLinkByIndex(link)->m_iSrcID]->GetType(); - int desType = pAINode[pAINode[node]->GetLinkByIndex(link)->m_iDestID]->GetType(); - - int linkInfo = pAINode[node]->GetLinkByIndex(link)->m_LinkInfo; - int moveTypes = pAINode[node]->GetLinkByIndex(link)->m_iAcceptedMoveTypes[m_iHullDrawNum]; - - // when rendering, raise NODE_GROUND off the floor slighty as they seem to clip too much - if ( srcType == NODE_GROUND) - { - srcPos.z += 1.0; - } - - if ( desType == NODE_GROUND) - { - desPos.z += 1.0; - } - - // Draw in red if stale link - if (linkInfo & bits_LINK_STALE_SUGGESTED) - { - NDebugOverlay::Line(srcPos, desPos, 255,0,0, false, flDrawDuration); - } - // Draw in grey if link turned off - else if (linkInfo & bits_LINK_OFF) - { - NDebugOverlay::Line(srcPos, desPos, 100,100,100, false, flDrawDuration); - } - else if ((m_debugNetOverlays & bits_debugOverlayFlyConnections) && (moveTypes & bits_CAP_MOVE_FLY)) - { - NDebugOverlay::Line(srcPos, desPos, 100,255,255, false, flDrawDuration); - } - else if (moveTypes & bits_CAP_MOVE_CLIMB) - { - NDebugOverlay::Line(srcPos, desPos, 255,0,255, false, flDrawDuration); - } - else if (moveTypes & bits_CAP_MOVE_GROUND) - { - NDebugOverlay::Line(srcPos, desPos, 0,255,50, false, flDrawDuration); - } - else if ((m_debugNetOverlays & bits_debugOverlayJumpConnections) && (moveTypes & bits_CAP_MOVE_JUMP) ) - { - NDebugOverlay::Line(srcPos, desPos, 0,0,255, false, flDrawDuration); - } - else - { // Dark red if this hull can't use - bool isFly = ( srcType == NODE_AIR || desType == NODE_AIR ); - bool isJump = true; - for ( int i = HULL_HUMAN; i < NUM_HULLS; i++ ) - { - if ( pAINode[node]->GetLinkByIndex(link)->m_iAcceptedMoveTypes[i] & ~bits_CAP_MOVE_JUMP ) - { - isJump = false; - break; - } - } - if ( ( isFly && (m_debugNetOverlays & bits_debugOverlayFlyConnections) ) || - ( isJump && (m_debugNetOverlays & bits_debugOverlayJumpConnections) ) || - ( !isFly && !isJump ) ) - { - NDebugOverlay::Line(srcPos, desPos, 100,25,25, false, flDrawDuration); - } - } - } - } - } - } - if (m_debugNetOverlays & bits_debugOverlayNodes) - { - int r = 255; - int g = 0; - int b = 0; - - // If checking visibility base color off of visibility info - if (m_debugNetOverlays & bits_debugOverlayVisibility && - m_iVisibilityNode != NO_NODE) - { - // --------------------------------------------------- - // If network needs rebuilding do so before display - // -------------------------------------------------- - if (m_debugNetOverlays & bits_debugNeedRebuild) - { - m_pManager->RebuildNetworkGraph(); - } - } - - // If checking graph connectivity base color off of connectivity info - if (m_debugNetOverlays & bits_debugOverlayGraphConnect && - m_iGConnectivityNode != NO_NODE) - { - // --------------------------------------------------- - // If network needs rebuilding do so before display - // -------------------------------------------------- - if (m_debugNetOverlays & bits_debugNeedRebuild) - { - m_pManager->RebuildNetworkGraph(); - } - else if (m_pNetwork->IsConnected( m_iGConnectivityNode, node) ) - { - r = 0; - g = 0; - b = 255; - } - } - // Otherwise base color off of node type - else - { - // If node is new and hasn't been rebuild yet - if (pAINode[node]->m_eNodeInfo & bits_NODE_WC_CHANGED) - { - r = 200; - g = 200; - b = 200; - } - - // If node doesn't fit the current hull size - else if (pAINode[node]->m_eNodeInfo & bits_NODE_WONT_FIT_HULL) - { - r = 255; - g = 25; - b = 25; - } - - else if (pAINode[node]->GetType() == NODE_CLIMB) - { - r = 255; - g = 0; - b = 255; - } - else if (pAINode[node]->GetType() == NODE_AIR) - { - r = 0; - g = 255; - b = 255; - } - else if (pAINode[node]->GetType() == NODE_GROUND) - { - r = 0; - g = 255; - b = 100; - } - } - - - Vector nodePos; - - nodePos = pAINode[node]->GetPosition(m_iHullDrawNum); - - NDebugOverlay::Box(nodePos, Vector(-5,-5,-5), Vector(5,5,5), r,g,b,0,flDrawDuration); - - // If climb node draw line in facing direction - if (pAINode[node]->GetType() == NODE_CLIMB) - { - Vector offsetDir = 12.0 * Vector(cos(DEG2RAD(pAINode[node]->GetYaw())),sin(DEG2RAD(pAINode[node]->GetYaw())),flDrawDuration); - NDebugOverlay::Line(nodePos, nodePos+offsetDir, r,g,b,false,flDrawDuration); - } - - if ( pAINode[node]->GetHint() ) - { - NDebugOverlay::Box( nodePos, Vector(-7,-7,-7), Vector(7,7,7), 255,255,0,0,flDrawDuration); - } - - if (m_debugNetOverlays & bits_debugOverlayNodesLev2) - { - CFmtStr msg; - - if ( m_pNodeIndexTable ) - msg.sprintf("%i (wc:%i; z:%i)",node,m_pNodeIndexTable[pAINode[node]->GetId()], pAINode[node]->GetZone()); - else - msg.sprintf("%i (z:%i)",node,pAINode[node]->GetZone()); - - Vector loc = nodePos; - loc.x+=6; - loc.y+=6; - loc.z+=6; - NDebugOverlay::Text( loc, msg, true, flDrawDuration); - - // Print the hintgroup if we have one - if ( pAINode[node]->GetHint() ) - { - msg.sprintf("%s", STRING( pAINode[node]->GetHint()->GetGroup() )); - loc.z-=3; - NDebugOverlay::Text( loc, msg, true, flDrawDuration); - } - } - } - } - } - } - - // ------------------------------- - // Identify hull being displayed - // ------------------------------- - if (m_debugNetOverlays & (bits_debugOverlayNodes | bits_debugOverlayConnections | bits_debugOverlayHulls)) - { - DrawEditInfoOverlay(); - } - - // ---------------------------- - // Increment node draw chunk - // ---------------------------- - startDrawNode = endDrawNode; - if (startDrawNode >= m_pNetwork->NumNodes()) - { - startDrawNode = 0; - } - - // ---------------------------- - // Output performance stats - // ---------------------------- -#ifdef AI_PERF_MON - if (m_fNextPerfStatTime < gpGlobals->curtime) - { - char temp[512]; - Q_snprintf(temp,sizeof(temp),"%3.2f NN/m\n%3.2f P/m\n",(m_nPerfStatNN/1.0),(m_nPerfStatPB/1.0)); - UTIL_CenterPrintAll(temp); - - m_fNextPerfStatTime = gpGlobals->curtime + 1; - m_nPerfStatNN = 0; - m_nPerfStatPB = 0; - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- - -CAI_NetworkEditTools::CAI_NetworkEditTools(CAI_NetworkManager *pNetworkManager) -{ - // ---------------------------------------------------------------------------- - // If in wc_edit mode - // ---------------------------------------------------------------------------- - if (engine->IsInEditMode()) - { - // ---------------------------------------------------------------------------- - // Allocate extra space for storing undropped node positions - // ---------------------------------------------------------------------------- - m_pWCPosition = new Vector[MAX_NODES]; - } - else - { - m_pWCPosition = NULL; - } - - m_pNodeIndexTable = NULL; - m_debugNetOverlays = 0; - - // ---------------------------------------------------------------------------- - // Allocate table of WC Id's. If not in edit mode Deleted after initialization - // ---------------------------------------------------------------------------- - m_pNodeIndexTable = new int[MAX_NODES]; - for ( int i = 0; i < MAX_NODES; i++ ) - m_pNodeIndexTable[i] = NO_NODE; - m_nNextWCIndex = 0; - - m_pNetwork = pNetworkManager->GetNetwork(); // @tbd - m_pManager = pNetworkManager; - - -} - -//----------------------------------------------------------------------------- -// Purpose: Destructor -//----------------------------------------------------------------------------- - -CAI_NetworkEditTools::~CAI_NetworkEditTools() -{ - // -------------------------------------------------------- - // If in edit mode tell WC I'm ending my session - // -------------------------------------------------------- -#ifdef _WIN32 - Editor_EndSession(false); -#endif - delete[] m_pNodeIndexTable; -} - -//----------------------------------------------------------------------------- -// CAI_NetworkBuilder -// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -void CAI_NetworkBuilder::FloodFillZone( CAI_Node **ppNodes, CAI_Node *pNode, int zone ) -{ - pNode->SetZone( zone ); - - for (int link = 0; link < pNode->NumLinks(); link++) - { - CAI_Link *pLink = pNode->GetLinkByIndex(link); - CAI_Node *pLinkedNode = ( pLink->m_iDestID == pNode->GetId()) ? ppNodes[pLink->m_iSrcID] : ppNodes[pLink->m_iDestID]; - if ( pLinkedNode->GetZone() == AI_NODE_ZONE_UNKNOWN ) - FloodFillZone( ppNodes, pLinkedNode, zone ); - - Assert( pLinkedNode->GetZone() == pNode->GetZone() && pNode->GetZone() == zone ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -void CAI_NetworkBuilder::InitZones( CAI_Network *pNetwork ) -{ - int nNodes = pNetwork->NumNodes(); - CAI_Node **ppNodes = pNetwork->AccessNodes(); - - if ( !nNodes ) - return; - - int i; - - for (i = 0; i < nNodes; i++) - { - ppNodes[i]->SetZone( AI_NODE_ZONE_UNKNOWN ); - } - - // Mark solo nodes - for (i = 0; i < nNodes; i++) - { - if ( ppNodes[i]->NumLinks() == 0 ) - ppNodes[i]->SetZone( AI_NODE_ZONE_SOLO ); - } - - int curZone = AI_NODE_FIRST_ZONE; - - for (i = 0; i < nNodes; i++) - { - if ( ppNodes[i]->GetZone() == AI_NODE_ZONE_UNKNOWN ) - { - FloodFillZone( (CAI_Node **)ppNodes, ppNodes[i], curZone ); - curZone++; - } - } - -#ifdef DEBUG - for (i = 0; i < nNodes; i++) - { - Assert( ppNodes[i]->GetZone() != AI_NODE_ZONE_UNKNOWN ); - } -#endif -} - - -//----------------------------------------------------------------------------- -// Purpose: Used for WC edit move to rebuild the network around the given -// location. Rebuilding the entire network takes too long -//----------------------------------------------------------------------------- - -void CAI_NetworkBuilder::Rebuild( CAI_Network *pNetwork ) -{ - int nNodes = pNetwork->NumNodes(); - CAI_Node **ppNodes = pNetwork->AccessNodes(); - - if ( !nNodes ) - return; - - BeginBuild(); - - // ------------------------------------------------------------ - // First mark all nodes around vecPos as having to be rebuilt - // ------------------------------------------------------------ - int i; - for (i = 0; i < nNodes; i++) - { - // -------------------------------------------------------------------- - // If changed, mark all nodes that are within the max link distance to - // the changed node as having to be rebuild - // -------------------------------------------------------------------- - if (ppNodes[i]->m_eNodeInfo & bits_NODE_WC_CHANGED) - { - Vector vRebuildPos = ppNodes[i]->GetOrigin(); - ppNodes[i]->SetNeedsRebuild(); - ppNodes[i]->SetZone( AI_NODE_ZONE_UNIVERSAL ); - for (int node = 0; node < nNodes; node++) - { - if ( ppNodes[node]->GetType() == NODE_AIR ) - { - if ((ppNodes[node]->GetOrigin() - vRebuildPos).LengthSqr() < MAX_AIR_NODE_LINK_DIST_SQ) - { - ppNodes[node]->SetNeedsRebuild(); - ppNodes[node]->SetZone( AI_NODE_ZONE_UNIVERSAL ); - } - } - else - { - if ((ppNodes[node]->GetOrigin() - vRebuildPos).LengthSqr() < MAX_NODE_LINK_DIST_SQ) - { - ppNodes[node]->SetNeedsRebuild(); - ppNodes[node]->SetZone( AI_NODE_ZONE_UNIVERSAL ); - } - } - } - } - } - - // --------------------------- - // Initialize node positions - // --------------------------- - for (i = 0; i < nNodes; i++) - { - if (ppNodes[i]->NeedsRebuild()) - { - InitNodePosition( pNetwork, ppNodes[i] ); - } - } - nNodes = pNetwork->NumNodes(); // InitNodePosition can create nodes - - // --------------------------- - // Initialize node neighbors - // --------------------------- - m_DidSetNeighborsTable.Resize( nNodes ); - m_DidSetNeighborsTable.ClearAll(); - m_NeighborsTable.SetSize( nNodes ); - for (i = 0; i < nNodes; i++) - { - m_NeighborsTable[i].Resize( nNodes ); - } - for (i = 0; i < nNodes; i++) - { - // If near point of change recalculate - if (ppNodes[i]->NeedsRebuild()) - { - InitNeighbors( pNetwork, ppNodes[i] ); - } - } - - // --------------------------- - // Force node neighbors for dynamic links - // --------------------------- - ForceDynamicLinkNeighbors(); - - // --------------------------- - // Initialize accepted hulls - // --------------------------- - for (i = 0; i < nNodes; i++) - { - if (ppNodes[i]->NeedsRebuild()) - { - ppNodes[i]->ClearLinks(); - } - } - for (i = 0; i < nNodes; i++) - { - if (ppNodes[i]->NeedsRebuild()) - { - InitLinks( pNetwork, ppNodes[i] ); - } - } - - g_pAINetworkManager->FixupHints(); - - EndBuild(); -} - -//----------------------------------------------------------------------------- - -void CAI_NetworkBuilder::BeginBuild() -{ - m_pTestHull = CAI_TestHull::GetTestHull(); -} - -//----------------------------------------------------------------------------- - -void CAI_NetworkBuilder::EndBuild() -{ - m_NeighborsTable.SetSize(0); - m_DidSetNeighborsTable.Resize(0); - CAI_TestHull::ReturnTestHull(); -} - -//----------------------------------------------------------------------------- -// Purpose: Only called if network has changed since last time level -// was loaded -//----------------------------------------------------------------------------- - - -void CAI_NetworkBuilder::Build( CAI_Network *pNetwork ) -{ - int nNodes = pNetwork->NumNodes(); - CAI_Node **ppNodes = pNetwork->AccessNodes(); - - if ( !nNodes ) - return; - - CAI_NetworkBuildHelper *pHelper = (CAI_NetworkBuildHelper *)CreateEntityByName( "ai_network_build_helper" ); - - VPROF( "AINet" ); - - BeginBuild(); - - CFastTimer masterTimer; - CFastTimer timer; - - DevMsg( "Building AI node graph...\n"); - masterTimer.Start(); - - // --------------------------- - // Initialize node positions - // --------------------------- - DevMsg( "Initializing node positions...\n" ); - timer.Start(); - int i; - for ( i = 0; i < nNodes; i++) - { - InitNodePosition( pNetwork, ppNodes[i] ); - if ( pHelper ) - pHelper->PostInitNodePosition( pNetwork, ppNodes[i] ); - } - nNodes = pNetwork->NumNodes(); // InitNodePosition can create nodes - timer.End(); - DevMsg( "...done initializing node positions. %f seconds\n", timer.GetDuration().GetSeconds() ); - - // --------------------------- - // Initialize node neighbors - // --------------------------- - DevMsg( "Initializing node neighbors...\n" ); - timer.Start(); - m_DidSetNeighborsTable.Resize( nNodes ); - m_DidSetNeighborsTable.ClearAll(); - m_NeighborsTable.SetSize( nNodes ); - for (i = 0; i < nNodes; i++) - { - m_NeighborsTable[i].Resize( nNodes ); - m_NeighborsTable[i].ClearAll(); - } - for (i = 0; i < nNodes; i++) - { - InitNeighbors( pNetwork, ppNodes[i] ); - } - timer.End(); - DevMsg( "...done initializing node neighbors. %f seconds\n", timer.GetDuration().GetSeconds() ); - - // --------------------------- - // Force node neighbors for dynamic links - // --------------------------- - DevMsg( "Forcing dynamic link neighbors...\n" ); - timer.Start(); - ForceDynamicLinkNeighbors(); - timer.End(); - DevMsg( "...done forcing dynamic link neighbors. %f seconds\n", timer.GetDuration().GetSeconds() ); - - // --------------------------- - // Initialize accepted hulls - // --------------------------- - DevMsg( "Determining links...\n" ); - timer.Start(); - for (i = 0; i < nNodes; i++) - { - // Make sure all the links are clear - ppNodes[i]->ClearLinks(); - } - for (i = 0; i < nNodes; i++) - { - InitLinks( pNetwork, ppNodes[i] ); - } - timer.End(); - DevMsg( "...done determining links. %f seconds\n", timer.GetDuration().GetSeconds() ); - - // ------------------------------ - // Initialize disconnected nodes - // ------------------------------ - DevMsg( "Determining zones...\n" ); - timer.Start(); - InitZones( pNetwork); - timer.End(); - masterTimer.End(); - DevMsg( "...done determining zones. %f seconds\n", timer.GetDuration().GetSeconds() ); - DevMsg( "...done building AI node graph, %f seconds\n", masterTimer.GetDuration().GetSeconds() ); - - g_pAINetworkManager->FixupHints(); - - EndBuild(); - - if ( pHelper ) - UTIL_Remove( pHelper ); -} - -//------------------------------------------------------------------------------ -// Purpose : Forces testing of a connection between src and dest IDs for all dynamic links -// -// Input : -// Output : -//------------------------------------------------------------------------------ -void CAI_NetworkBuilder::ForceDynamicLinkNeighbors(void) -{ - if (!g_pAINetworkManager->GetEditOps()->m_pNodeIndexTable) - { - DevMsg("ERROR: Trying initialize links with no WC ID table!\n"); - return; - } - - CAI_DynamicLink* pDynamicLink = CAI_DynamicLink::m_pAllDynamicLinks; - - while (pDynamicLink) - { - // ------------------------------------------------------------- - // First convert this links WC IDs to engine IDs - // ------------------------------------------------------------- - int nSrcID = g_pAINetworkManager->GetEditOps()->GetNodeIdFromWCId( pDynamicLink->m_nSrcEditID ); - if (nSrcID == -1) - { - DevMsg("ERROR: Dynamic link source WC node %d not found\n", pDynamicLink->m_nSrcEditID ); - } - - int nDestID = g_pAINetworkManager->GetEditOps()->GetNodeIdFromWCId( pDynamicLink->m_nDestEditID ); - if (nDestID == -1) - { - DevMsg("ERROR: Dynamic link dest WC node %d not found\n", pDynamicLink->m_nDestEditID ); - } - - if ( nSrcID != -1 && nDestID != -1 ) - { - if ( nSrcID < g_pBigAINet->NumNodes() && nDestID < g_pBigAINet->NumNodes() ) - { - CAI_Node *pSrcNode = g_pBigAINet->GetNode( nSrcID ); - CAI_Node *pDestNode = g_pBigAINet->GetNode( nDestID ); - - // ------------------------------------------------------------- - // Force visibility and neighbor-ness between the nodes - // ------------------------------------------------------------- - Assert( pSrcNode ); - Assert( pDestNode ); - - m_NeighborsTable[pSrcNode->GetId()].Set(pDestNode->GetId()); - m_NeighborsTable[pDestNode->GetId()].Set(pSrcNode->GetId()); - } - } - - // Go on to the next dynamic link - pDynamicLink = pDynamicLink->m_pNextDynamicLink; - } -} - -CAI_NetworkBuilder g_AINetworkBuilder; - - -//----------------------------------------------------------------------------- -// Purpose: Initializes position of climb node in the world. Climb nodes are -// set to be just above the floor or at the same level at the -// dismount point for the node -// -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_NetworkBuilder::InitClimbNodePosition(CAI_Network *pNetwork, CAI_Node *pNode) -{ - AI_PROFILE_SCOPE( CAI_Node_InitClimbNodePosition ); - - // If this is a node for mounting/dismounting the climb skip it - if ( pNode->m_eNodeInfo & (bits_NODE_CLIMB_OFF_FORWARD | bits_NODE_CLIMB_OFF_LEFT | bits_NODE_CLIMB_OFF_RIGHT) ) - { - return; - } - - // Figure out which directions I can dismount from the climb node - - //float hullLength = NAI_Hull::Length(HULL_SMALL); - //Vector offsetDir = Vector(cos(DEG2RAD(m_flYaw)),sin(DEG2RAD(m_flYaw)),0); - - // ---------------- - // Check position - // ---------------- - trace_t trace; - Vector posOnLadder = pNode->GetPosition(HULL_SMALL_CENTERED); - AI_TraceHull( posOnLadder, posOnLadder + Vector( 0, 0, -37 ), - NAI_Hull::Mins(HULL_SMALL_CENTERED), NAI_Hull::Maxs(HULL_SMALL_CENTERED), - MASK_NPCSOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &trace ); - - // -------------------------------------------------------------------- - // If climb node is right above the floor, we don't need any dismount - // nodes. Accept this dropped position and note that this climb node - // is at the bottom - // -------------------------------------------------------------------- - if (!trace.startsolid && trace.fraction != 1) - { - pNode->m_eNodeInfo = bits_NODE_CLIMB_BOTTOM; - InitGroundNodePosition( pNetwork, pNode ); - return; - } - - // --------------------------------------------------------------------- - // If network was already loaded this means we are in wc edit mode - // so we shouldn't recreate the added climb nodes - // --------------------------------------------------------------------- - if (g_pAINetworkManager->NetworksLoaded()) - { - return; - } - - // --------------------------------------------------------------------- - // Otherwise we need to create climb nodes for dismounting the climb - // and place the height of the climb node at the dismount position - // --------------------------------------------------------------------- - int checkNodeTypes[3] = { bits_NODE_CLIMB_OFF_FORWARD, bits_NODE_CLIMB_OFF_LEFT, bits_NODE_CLIMB_OFF_RIGHT }; - - int numExits = 0; - - // DevMsg( "testing %f %f %f\n", GetOrigin().x, GetOrigin().y, GetOrigin().z ); - - for (int i = 0; i < 3; i++) - { - pNode->m_eNodeInfo = checkNodeTypes[i]; - - Vector origin = pNode->GetPosition(HULL_SMALL_CENTERED); - - // DevMsg( "testing %f %f %f\n", origin.x, origin.y, origin.z ); - // ---------------- - // Check outward - // ---------------- - AI_TraceLine ( posOnLadder, - origin, - MASK_NPCSOLID_BRUSHONLY, - NULL, - COLLISION_GROUP_NONE, - &trace ); - - // DevMsg( "to %f %f %f : %d %f", origin.x, origin.y, origin.z, trace.startsolid, trace.fraction ); - - if (!trace.startsolid && trace.fraction == 1.0) - { - float floorZ = GetFloorZ(origin); // FIXME: don't use this - - if (fabs(pNode->GetOrigin().z - floorZ) < 36.0f) - { - CAI_Node *new_node = pNetwork->AddNode( pNode->GetOrigin(), pNode->m_flYaw ); - new_node->m_pHint = NULL; - new_node->m_eNodeType = NODE_CLIMB; - new_node->m_eNodeInfo = pNode->m_eNodeInfo; - InitGroundNodePosition( pNetwork, new_node ); - - // copy over the offsets for the first CLIMB_OFF node - // FIXME: this method is broken for when the CLIMB_OFF nodes are at different heights - if (numExits == 0) - { - for (int hull = 0; hull < NUM_HULLS; hull++) - { - pNode->m_flVOffset[hull] = new_node->m_flVOffset[hull]; - } - } - else - { - for (int hull = 0; hull < NUM_HULLS; hull++) - { - if (fabs(pNode->m_flVOffset[hull] - new_node->m_flVOffset[hull]) > 1) - { - DevMsg(2, "Warning: Climb Node %i has different exit heights for hull %s\n", pNode->m_iID, NAI_Hull::Name(hull)); - } - } - } - - numExits++; - } - } - // DevMsg( "\n"); - } - - if (numExits == 0) - { - DevMsg("ERROR: Climb Node %i has no way off\n",pNode->m_iID); - } - - // this is a node that can't get gotten to directly - pNode->m_eNodeInfo = bits_NODE_CLIMB_ON; -} - -//----------------------------------------------------------------------------- -// Purpose: Initializes position of the node sitting on the ground. -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_NetworkBuilder::InitGroundNodePosition(CAI_Network *pNetwork, CAI_Node *pNode) -{ - AI_PROFILE_SCOPE( CAI_Node_InitGroundNodePosition ); - - if ( pNode->m_eNodeInfo & bits_DONT_DROP ) - return; - - // find actual floor for each hull type - for (int hull = 0; hull < NUM_HULLS; hull++) - { - trace_t tr; - Vector origin = pNode->GetOrigin(); - Vector mins, maxs; - - // turn hull into pancake to avoid problems with ceiling - mins = NAI_Hull::Mins(hull); - maxs = NAI_Hull::Maxs(hull); - maxs.z = mins.z; - - // Add an epsilon for cast - origin.z += 0.1; - - // shift up so bottom of box is at center of node - origin.z -= mins.z; - - AI_TraceHull( origin, origin + Vector( 0, 0, -384 ), mins, maxs, MASK_NPCSOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr ); - - if ( !tr.startsolid ) - pNode->m_flVOffset[hull] = tr.endpos.z - pNode->GetOrigin().z + 0.1; - else - pNode->m_flVOffset[hull] = -mins.z + 0.1; - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: Initializes position of the node in the world. Only called if -// the network was never initialized -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_NetworkBuilder::InitNodePosition(CAI_Network *pNetwork, CAI_Node *pNode) -{ - AI_PROFILE_SCOPE( CAI_Node_InitNodePosition ); - - if (pNode->m_eNodeType == NODE_AIR) - { - return; - } - else if (pNode->m_eNodeType == NODE_CLIMB) - { - InitClimbNodePosition(pNetwork, pNode); - return; - } - - // Otherwise mark as a land node and drop to the floor - - else if (pNode->m_eNodeType == NODE_GROUND) - { - InitGroundNodePosition( pNetwork, pNode ); - - if (pNode->m_flVOffset[HULL_SMALL_CENTERED] < -100) - { - Assert( pNetwork == g_pBigAINet ); - DevWarning("ERROR: Node %.0f %.0f %.0f, WC ID# %i, is either too low (fell through floor) or too high (>100 units above floor)\n", - pNode->GetOrigin().x, pNode->GetOrigin().y, pNode->GetOrigin().z, - g_pAINetworkManager->GetEditOps()->m_pNodeIndexTable[pNode->m_iID]); - - pNode->m_eNodeInfo |= bits_NODE_FALLEN; - } - return; - } - /* // If under water, not that the node is in water <> when we get water - else if ( UTIL_PointContents(GetOrigin()) & MASK_WATER ) - { - m_eNodeType |= NODE_WATER; - } - */ - else if (pNode->m_eNodeType != NODE_DELETED) - { - DevMsg( "Bad node type!\n" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Set the visibility for this node. (What nodes it can see with a -// line trace) -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_NetworkBuilder::InitVisibility(CAI_Network *pNetwork, CAI_Node *pNode) -{ - AI_PROFILE_SCOPE( CAI_Node_InitVisibility ); - - // If a deleted node bail - if (pNode->m_eNodeType == NODE_DELETED) - { - return; - } - // The actual position of some nodes may be inside geometry as they have - // hull specific position offsets (e.g. climb nodes). Get the hull specific - // position using the smallest hull to make sure were not in geometry - Vector srcPos = pNode->GetPosition(HULL_SMALL_CENTERED); - - // Check the visibility on every other node in the network - for (int testnode = 0; testnode < pNetwork->NumNodes(); testnode++ ) - { - CAI_Node *testNode = pNetwork->GetNode( testnode ); - - if ( DebuggingConnect( pNode->m_iID, testnode ) ) - { - DevMsg( "" ); // break here.. - } - - // We know we can view ourself - if (pNode->m_iID == testnode) - { - m_NeighborsTable[pNode->m_iID].Set(testNode->m_iID); - continue; - } - - // Remove duplicate nodes unless a climb node as they move - if (testNode->GetOrigin() == pNode->GetOrigin() && testNode->GetType() != NODE_CLIMB) - { - testNode->SetType( NODE_DELETED ); - DevMsg( 2, "Probable duplicate node placed at %s\n", VecToString(testNode->GetOrigin()) ); - continue; - } - - // If a deleted node we don't care about it - if (testNode->GetType() == NODE_DELETED) - { - continue; - } - - if ( m_DidSetNeighborsTable.IsBitSet( testNode->m_iID ) ) - { - if ( m_NeighborsTable[testNode->m_iID].IsBitSet(pNode->m_iID)) - m_NeighborsTable[pNode->m_iID].Set(testNode->m_iID); - - continue; - } - - float flDistToCheckNode = ( testNode->GetOrigin() - pNode->GetOrigin() ).LengthSqr(); - - if ( testNode->GetType() == NODE_AIR ) - { - if (flDistToCheckNode > MAX_AIR_NODE_LINK_DIST_SQ) - continue; - } - else - { - if (flDistToCheckNode > MAX_NODE_LINK_DIST_SQ) - continue; - } - - // The actual position of some nodes may be inside geometry as they have - // hull specific position offsets (e.g. climb nodes). Get the hull specific - // position using the smallest hull to make sure were not in geometry - Vector destPos = pNetwork->GetNode( testnode )->GetPosition(HULL_SMALL_CENTERED); - - trace_t tr; - tr.m_pEnt = NULL; - - // Try several line of sight checks - - bool isVisible = false; - - // ------------------ - // Bottom to bottom - // ------------------ - AI_TraceLine ( srcPos, destPos,MASK_NPCWORLDSTATIC,NULL,COLLISION_GROUP_NONE, &tr ); - if (!tr.startsolid && tr.fraction == 1.0) - { - isVisible = true; - } - - // ------------------ - // Top to top - // ------------------ - if (!isVisible) - { - AI_TraceLine ( srcPos + Vector( 0, 0, 70 ),destPos + Vector( 0, 0, 70 ),MASK_NPCWORLDSTATIC,NULL,COLLISION_GROUP_NONE, &tr ); - if (!tr.startsolid && tr.fraction == 1.0) - { - isVisible = true; - } - } - - // ------------------ - // Top to Bottom - // ------------------ - if (!isVisible) - { - AI_TraceLine ( srcPos + Vector( 0, 0, 70 ),destPos,MASK_NPCWORLDSTATIC,NULL,COLLISION_GROUP_NONE, &tr ); - if (!tr.startsolid && tr.fraction == 1.0) - { - isVisible = true; - } - } - - // ------------------ - // Bottom to Top - // ------------------ - if (!isVisible) - { - AI_TraceLine ( srcPos,destPos + Vector( 0, 0, 70 ),MASK_NPCWORLDSTATIC,NULL,COLLISION_GROUP_NONE, &tr ); - if (!tr.startsolid && tr.fraction == 1.0) - { - isVisible = true; - } - } - - // ------------------ - // Failure - // ------------------ - if (!isVisible) - { - continue; - } - - /* <> may not apply with editable connections....... - - // trace hit a brush ent, trace backwards to make sure that this ent is the only thing in the way. - if ( tr.fraction != 1.0 ) - { - pTraceEnt = tr.u.ent;// store the ent that the trace hit, for comparison - - AI_TraceLine ( srcPos, - destPos, - MASK_NPCSOLID_BRUSHONLY, - NULL, - &tr ); - - - // there is a solid_bsp ent in the way of these two nodes, so we must record several things about in order to keep - // track of it in the pathfinding code, as well as through save and restore of the node graph. ANY data that is manipulated - // as part of the process of adding a LINKENT to a connection here must also be done in CGraph::SetGraphPointers, where reloaded - // graphs are prepared for use. - if ( tr.u.ent == pTraceEnt && !FClassnameIs( tr.u.ent, "worldspawn" ) ) - { - // get a pointer - pLinkPool [ cTotalLinks ].m_pLinkEnt = tr.u.ent; - - // record the modelname, so that we can save/load node trees - memcpy( pLinkPool [ cTotalLinks ].m_szLinkEntModelname, STRING( tr.u.ent->model ), 4 ); - - // set the flag for this ent that indicates that it is attached to the world graph - // if this ent is removed from the world, it must also be removed from the connections - // that it formerly blocked. - CBaseEntity *e = CBaseEntity::Instance( tr.u.ent ); - if ( e ) - { - if ( !(e->GetFlags() & FL_GRAPHED ) ) - { - e->AddFlag( FL_GRAPHED ); - } - } - } - // even if the ent wasn't there, these nodes couldn't be connected. Skip. - else - { - continue; - } - } -*/ - m_NeighborsTable[pNode->m_iID].Set(testNode->m_iID); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Initializes the neighbors list -// Input : -// Output : -//----------------------------------------------------------------------------- - -void CAI_NetworkBuilder::InitNeighbors(CAI_Network *pNetwork, CAI_Node *pNode) -{ - m_NeighborsTable[pNode->m_iID].ClearAll(); - - // Begin by establishing viewability to limit the number of nodes tested - InitVisibility( pNetwork, pNode ); - - AI_PROFILE_SCOPE_BEGIN( CAI_Node_InitNeighbors ); - - // Now check each neighbor against all other neighbors to see if one of - // them is a redundant connection - for (int checknode = 0; checknode < pNetwork->NumNodes(); checknode++ ) - { - if ( DebuggingConnect( pNode->m_iID, checknode ) ) - { - DevMsg( "" ); // break here.. - } - - // I'm not a neighbor of myself - if ( pNode->m_iID == checknode ) - { - m_NeighborsTable[pNode->m_iID].Clear(checknode); - continue; - } - - // Only check if already on the neightbor list - if (!m_NeighborsTable[pNode->m_iID].IsBitSet(checknode)) - { - continue; - } - - CAI_Node *pCheckNode = pNetwork->GetNode(checknode); - - for (int testnode = 0; testnode < pNetwork->NumNodes(); testnode++ ) - { - // don't check against itself - if (( testnode == checknode ) || (testnode == pNode->m_iID)) - { - continue; - } - - // Only check if already on the neightbor list - if (!m_NeighborsTable[pNode->m_iID].IsBitSet(testnode)) - { - continue; - } - - CAI_Node *pTestNode = pNetwork->GetNode(testnode); - - // ---------------------------------------------------------- - // Don't check air nodes against nodes of a different types - // ---------------------------------------------------------- - if ((pCheckNode->GetType() == NODE_AIR && pTestNode->GetType() != NODE_AIR)|| - (pCheckNode->GetType() != NODE_AIR && pTestNode->GetType() == NODE_AIR)) - { - continue; - } - - // ---------------------------------------------------------- - // If climb node pairs, don't consider redundancy - // ---------------------------------------------------------- - if (pNode->GetType() == NODE_CLIMB && - (pCheckNode->GetType() == NODE_CLIMB || pTestNode->GetType() == NODE_CLIMB)) - { - continue; - } - - // ---------------------------------------------------------- - // If a climb node mounting point is involved, don't consider redundancy - // ---------------------------------------------------------- - if ( ( pCheckNode->GetOrigin() == pNode->GetOrigin() && pNode->GetType() == NODE_CLIMB && pCheckNode->GetType() == NODE_CLIMB ) || - ( pTestNode->GetOrigin() == pNode->GetOrigin() && pNode->GetType() == NODE_CLIMB && pTestNode->GetType() == NODE_CLIMB ) || - ( pTestNode->GetOrigin() == pCheckNode->GetOrigin() && pCheckNode->GetType() == NODE_CLIMB && pTestNode->GetType() == NODE_CLIMB ) ) - { - continue; - } - - // @HACKHACK (toml 02-25-04): Ignore redundancy if both nodes are air nodes with - // hint type "strider node". Really, really should do this in a clean manner - bool nodeIsStrider = ( pNode->GetHint() && pNode->GetHint()->HintType() == HINT_STRIDER_NODE ); - bool other1IsStrider = ( pCheckNode->GetHint() && pCheckNode->GetHint()->HintType() == HINT_STRIDER_NODE ); - bool other2IsStrider = ( pTestNode->GetHint() && pTestNode->GetHint()->HintType() == HINT_STRIDER_NODE ); - if ( nodeIsStrider && other1IsStrider != other2IsStrider ) - { - continue; - } - - Vector vec2DirToCheckNode = pCheckNode->GetOrigin() - pNode->GetOrigin(); - float flDistToCheckNode = VectorNormalize( vec2DirToCheckNode ); - - Vector vec2DirToTestNode = ( pTestNode->GetOrigin() - pNode->GetOrigin() ); - float flDistToTestNode = VectorNormalize( vec2DirToTestNode ); - - float tolerance = 0.92388; // 45 degrees - - if ( DotProduct ( vec2DirToCheckNode, vec2DirToTestNode ) >= tolerance ) - { - if ( flDistToTestNode < flDistToCheckNode ) - { - DebugConnectMsg( pNode->m_iID, checknode, " Revoking neighbor status to to closer redundant link %d\n", testnode ); - m_NeighborsTable[pNode->m_iID].Clear(checknode); - } - else - { - DebugConnectMsg( pNode->m_iID, testnode, " Revoking neighbor status to to closer redundant link %d\n", checknode ); - m_NeighborsTable[pNode->m_iID].Clear(testnode); - } - } - } - } - - AI_PROFILE_SCOPE_END(); - - m_DidSetNeighborsTable.Set(pNode->m_iID); -} - -//----------------------------------------------------------------------------- -// Purpose: For the current node, check its connection to all other nodes -// Input : -// Output : -//----------------------------------------------------------------------------- - -static bool IsInLineForClimb( const Vector &srcPos, const Vector &srcFacing, const Vector &destPos, const Vector &destFacing ) -{ -#ifdef DEBUG - Vector normSrcFacing( srcFacing ), normDestFacing( destFacing ); - - VectorNormalize( normSrcFacing ); - VectorNormalize( normDestFacing ); - - Assert( VectorsAreEqual( srcFacing, normSrcFacing, 0.01 ) && VectorsAreEqual( destFacing, normDestFacing, 0.01 ) ); -#endif - - // If they are not facing the same way... - if ( 1 - srcFacing.Dot( destFacing ) > 0.01 ) - return false; - - // If they aren't in line along the facing... - if ( CalcDistanceToLine2D( destPos.AsVector2D(), srcPos.AsVector2D(), srcPos.AsVector2D() + srcFacing.AsVector2D() ) > 0.01 ) - return false; - - // Check that the angle between them is either staight up, or on at angle of ladder-stairs - Vector vecDelta = srcPos - destPos; - - VectorNormalize( vecDelta ); - - float fabsCos = fabs( srcFacing.Dot( vecDelta ) ); - - const float CosAngLadderStairs = 0.4472; // rise 2 & run 1 - - if ( fabsCos > 0.05 && fabs( fabsCos - CosAngLadderStairs ) > 0.05 ) - return false; - - // *************************** -------------------------------- - return true; -} - -//------------------------------------- - -int CAI_NetworkBuilder::ComputeConnection( CAI_Node *pSrcNode, CAI_Node *pDestNode, Hull_t hull ) -{ - int srcId = pSrcNode->m_iID; - int destId = pDestNode->m_iID; - int result = 0; - trace_t tr; - - // Set the size of the test hull - if ( m_pTestHull->GetHullType() != hull ) - { - m_pTestHull->SetHullType( hull ); - m_pTestHull->SetHullSizeNormal( true ); - } - - if ( !( m_pTestHull->GetFlags() & FL_ONGROUND ) ) - { - DevWarning( 2, "OFFGROUND!\n" ); - } - m_pTestHull->AddFlag( FL_ONGROUND ); - - // ============================================================== - // FIRST CHECK IF HULL CAN EVEN FIT AT THESE NODES - // ============================================================== - // @Note (toml 02-10-03): this should be optimized, caching the results of CanFitAtNode() - if ( !( pSrcNode->m_eNodeInfo & ( HullToBit( hull ) << NODE_ENT_FLAGS_SHIFT ) ) && - !m_pTestHull->GetNavigator()->CanFitAtNode(srcId,MASK_NPCWORLDSTATIC) ) - { - DebugConnectMsg( srcId, destId, " Cannot fit at node %d\n", srcId ); - return 0; - } - - if ( !( pDestNode->m_eNodeInfo & ( HullToBit( hull ) << NODE_ENT_FLAGS_SHIFT ) ) && - !m_pTestHull->GetNavigator()->CanFitAtNode(destId,MASK_NPCWORLDSTATIC) ) - { - DebugConnectMsg( srcId, destId, " Cannot fit at node %d\n", destId ); - return 0; - } - - // ============================================================== - // AIR NODES (FLYING) - // ============================================================== - if (pSrcNode->m_eNodeType == NODE_AIR || pDestNode->GetType() == NODE_AIR) - { - AI_PROFILE_SCOPE( CAI_Node_InitLinks_Air ); - - // Air nodes only connect to other air nodes and nothing else - if (pSrcNode->m_eNodeType == NODE_AIR && pDestNode->GetType() == NODE_AIR) - { - AI_TraceHull( pSrcNode->GetOrigin(), pDestNode->GetOrigin(), NAI_Hull::Mins(hull),NAI_Hull::Maxs(hull), MASK_NPCWORLDSTATIC, m_pTestHull, COLLISION_GROUP_NONE, &tr ); - if (!tr.startsolid && tr.fraction == 1.0) - { - result |= bits_CAP_MOVE_FLY; - DebugConnectMsg( srcId, destId, " Connect by flying\n" ); - } - } - } - // ============================================================================= - // > CLIMBING - // ============================================================================= - // If both are climb nodes just make sure they are above each other - // and there is room for the hull to pass between them - else if ((pSrcNode->m_eNodeType == NODE_CLIMB) && (pDestNode->GetType() == NODE_CLIMB)) - { - AI_PROFILE_SCOPE( CAI_Node_InitLinks_Climb ); - - Vector srcPos = pSrcNode->GetPosition(hull); - Vector destPos = pDestNode->GetPosition(hull); - - // If a code genereted climb dismount node the two origins will be the same - if (pSrcNode->GetOrigin() == pDestNode->GetOrigin()) - { - AI_TraceHull( srcPos, destPos, - NAI_Hull::Mins(hull),NAI_Hull::Maxs(hull), - MASK_NPCWORLDSTATIC, m_pTestHull, COLLISION_GROUP_NONE, &tr ); - if (!tr.startsolid && tr.fraction == 1.0) - { - result |= bits_CAP_MOVE_CLIMB; - DebugConnectMsg( srcId, destId, " Connect by climbing\n" ); - } - } - else - { - if ( !IsInLineForClimb(srcPos, UTIL_YawToVector( pSrcNode->m_flYaw ), destPos, UTIL_YawToVector( pDestNode->m_flYaw ) ) ) - { - Assert( !IsInLineForClimb(destPos, UTIL_YawToVector( pDestNode->m_flYaw ), srcPos, UTIL_YawToVector( pSrcNode->m_flYaw ) ) ); - DebugConnectMsg( srcId, destId, " Not lined up for proper climbing\n" ); - return 0; - } - - AI_TraceHull( srcPos, destPos, NAI_Hull::Mins(hull),NAI_Hull::Maxs(hull), MASK_NPCWORLDSTATIC, m_pTestHull, COLLISION_GROUP_NONE, &tr ); - if (!tr.startsolid && tr.fraction == 1.0) - { - result |= bits_CAP_MOVE_CLIMB; - DebugConnectMsg( srcId, destId, " Connect by climbing\n" ); - } - } - } - // ==================================================== - // > TWO LAND NODES - // ===================================================== - else if ((pSrcNode->m_eNodeType == NODE_GROUND) || (pDestNode->GetType() == NODE_GROUND)) - { - // BUG: this could use GroundMoveLimit, except there's no version of world but not brushes (doors open, etc). - - // ==================================================== - // > WALKING : walk the space between the nodes - // ===================================================== - - // in this loop we take tiny steps from the current node to the nodes that it links to, one at a time. - bool fStandFailed = false; - bool fWalkFailed = true; - - AI_PROFILE_SCOPE_BEGIN( CAI_Node_InitLinks_Ground ); - - Vector srcPos = pSrcNode->GetPosition(hull); - Vector destPos = pDestNode->GetPosition(hull); - - if (!m_pTestHull->GetMoveProbe()->CheckStandPosition( srcPos, MASK_NPCWORLDSTATIC)) - { - DebugConnectMsg( srcId, destId, " Failed to stand at %d\n", srcId ); - fStandFailed = true; - } - - if (!m_pTestHull->GetMoveProbe()->CheckStandPosition( destPos, MASK_NPCWORLDSTATIC)) - { - DebugConnectMsg( srcId, destId, " Failed to stand at %d\n", destId ); - fStandFailed = true; - } - - //if (hull == 0) - // DevMsg("from %.1f %.1f %.1f to %.1f %.1f %.1f\n", srcPos.x, srcPos.y, srcPos.z, destPos.x, destPos.y, destPos.z ); - - if ( !fStandFailed ) - { - fWalkFailed = !m_pTestHull->GetMoveProbe()->TestGroundMove( srcPos, destPos, MASK_NPCWORLDSTATIC, AITGM_IGNORE_INITIAL_STAND_POS, NULL ); - if ( fWalkFailed ) - DebugConnectMsg( srcId, destId, " Failed to walk between nodes\n" ); - } - - // Add to our list of accepable hulls - if (!fWalkFailed && !fStandFailed) - { - result |= bits_CAP_MOVE_GROUND; - DebugConnectMsg( srcId, destId, " Nodes connect for ground movement\n" ); - } - - AI_PROFILE_SCOPE_END(); - - // ============================================================================= - // > JUMPING : jump the space between the nodes, but only if walk failed - // ============================================================================= - if (!fStandFailed && fWalkFailed && (pSrcNode->m_eNodeType == NODE_GROUND) && (pDestNode->GetType() == NODE_GROUND)) - { - AI_PROFILE_SCOPE( CAI_Node_InitLinks_Jump ); - - Vector srcPos = pSrcNode->GetPosition(hull); - Vector destPos = pDestNode->GetPosition(hull); - - // Jumps aren't bi-directional. We can jump down further than we can jump up so - // we have to test for either one - bool canDestJump = m_pTestHull->IsJumpLegal(srcPos, destPos, destPos); - bool canSrcJump = m_pTestHull->IsJumpLegal(destPos, srcPos, srcPos); - - if (canDestJump || canSrcJump) - { - CAI_MoveProbe *pMoveProbe = m_pTestHull->GetMoveProbe(); - - bool fJumpLegal = false; - m_pTestHull->SetGravity(1.0); - - AIMoveTrace_t moveTrace; - pMoveProbe->MoveLimit( NAV_JUMP, srcPos,destPos, MASK_NPCWORLDSTATIC, NULL, &moveTrace); - if (!IsMoveBlocked(moveTrace)) - { - fJumpLegal = true; - } - pMoveProbe->MoveLimit( NAV_JUMP, destPos,srcPos, MASK_NPCWORLDSTATIC, NULL, &moveTrace); - if (!IsMoveBlocked(moveTrace)) - { - fJumpLegal = true; - } - - // Add to our list of accepable hulls - if (fJumpLegal) - { - result |= bits_CAP_MOVE_JUMP; - DebugConnectMsg( srcId, destId, " Nodes connect for jumping\n" ); - } - } - } - } - return result; -} - - - -//------------------------------------- - -void CAI_NetworkBuilder::InitLinks(CAI_Network *pNetwork, CAI_Node *pNode) -{ - AI_PROFILE_SCOPE( CAI_Node_InitLinks ); - - // ----------------------------------------------------- - // Get test hull - // ----------------------------------------------------- - m_pTestHull->GetNavigator()->SetNetwork( pNetwork ); - - // ----------------------------------------------------- - // Initialize links to every node - // ----------------------------------------------------- - for (int i = 0; i < pNetwork->NumNodes(); i++ ) - { - // ------------------------------------------------- - // Check for redundant link building - // ------------------------------------------------- - DebugConnectMsg( pNode->m_iID, i, "Testing connection between %d and %d:\n", pNode->m_iID, i ); - - if (pNode->HasLink(i)) - { - // A link has been already created when the other node was processed... - DebugConnectMsg( pNode->m_iID, i, " Nodes already connected\n" ); - continue; - } - - // --------------------------------------------------------------------- - // If link has been already created in other node just share it - // --------------------------------------------------------------------- - CAI_Node *pDestNode = pNetwork->GetNode( i ); - - CAI_Link *pOldLink = pDestNode->HasLink(pNode->m_iID); - if (pOldLink) - { - DebugConnectMsg( pNode->m_iID, i, " Sharing previously establish connection\n" ); - ((CAI_Node *)pNode)->AddLink(pOldLink); - continue; - } - - // Only check if the node is a neighbor - if ( m_NeighborsTable[pNode->m_iID].IsBitSet(pDestNode->m_iID) ) - { - int acceptedMotions[NUM_HULLS]; - - bool bAllFailed = true; - - if ( DebuggingConnect( pNode->m_iID, i ) ) - { - DevMsg( "" ); // break here.. - } - - if ( !(pNode->m_eNodeInfo & bits_NODE_FALLEN) && !(pDestNode->m_eNodeInfo & bits_NODE_FALLEN) ) - { - for (int hull = 0 ; hull < NUM_HULLS; hull++ ) - { - DebugConnectMsg( pNode->m_iID, i, " Testing for hull %s\n", NAI_Hull::Name( (Hull_t)hull ) ); - - acceptedMotions[hull] = ComputeConnection( pNode, pDestNode, (Hull_t)hull ); - if ( acceptedMotions[hull] != 0 ) - bAllFailed = false; - } - } - else - DebugConnectMsg( pNode->m_iID, i, " No connection: one or both are fallen nodes\n" ); - - // If there were any passible hulls create link - if (!bAllFailed) - { - CAI_Link *pLink = pNetwork->CreateLink( pNode->m_iID, pDestNode->m_iID); - if ( pLink ) - { - for (int hull=0;hullm_iAcceptedMoveTypes[hull] = acceptedMotions[hull]; - } - DebugConnectMsg( pNode->m_iID, i, " Added link\n" ); - } - } - else - { - m_NeighborsTable[pNode->m_iID].Clear(pDestNode->m_iID); - DebugConnectMsg(pNode->m_iID, i, " NO LINK\n" ); - } - } - else - DebugConnectMsg( pNode->m_iID, i, " NO LINK (not neighbors)\n" ); - } -} - -//----------------------------------------------------------------------------- diff --git a/game/server/ai_networkmanager.h b/game/server/ai_networkmanager.h deleted file mode 100644 index 6c599af02..000000000 --- a/game/server/ai_networkmanager.h +++ /dev/null @@ -1,199 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef AI_NETWORKMANAGER_H -#define AI_NETWORKMANAGER_H - -#include "utlvector.h" -#include "bitstring.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -class CAI_NetworkEditTools; -class CAI_Network; -class CAI_Node; -class CAI_Link; -class CAI_TestHull; - -//----------------------------------------------------------------------------- -// CAI_NetworkManager -// -// Purpose: The entity in the level responsible for building the network if it -// isn't there, saving & loading of the network, and holding the -// CAI_Network instance. -// -//----------------------------------------------------------------------------- - -class CAI_NetworkManager : public CPointEntity -{ -public: - static void InitializeAINetworks(); - - DECLARE_DATADESC(); - - DECLARE_CLASS( CAI_NetworkManager, CPointEntity ); - -public: - CAI_NetworkManager(void); - virtual ~CAI_NetworkManager(void); - - void Spawn (); - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() | FCAP_DONT_SAVE; } - void RebuildNetworkGraph(); // Used in WC edit mode - void StartRebuild(); // Used in WC edit mode - void LoadNetworkGraph(); - - static bool NetworksLoaded() { return gm_fNetworksLoaded; } - bool IsInitialized() { return m_fInitalized; } - - void BuildNetworkGraph(); - - static void DeleteAllAINetworks(); - - void FixupHints(); - void MarkDontSaveGraph(); - -public: - CAI_NetworkEditTools * GetEditOps() { return m_pEditOps; } - CAI_Network * GetNetwork() { return m_pNetwork; } - -private: - - void DelayedInit(); - void RebuildThink(); - void SaveNetworkGraph( void) ; - static bool IsAIFileCurrent( const char *szMapName ); - - static bool gm_fNetworksLoaded; // Have AINetworks been loaded - - bool m_bNeedGraphRebuild; - CAI_NetworkEditTools * m_pEditOps; - CAI_Network * m_pNetwork; - - - bool m_fInitalized; - bool m_bDontSaveGraph; -}; - -//----------------------------------------------------------------------------- - -abstract_class CAI_NetworkBuildHelper : public CLogicalEntity -{ - DECLARE_CLASS( CAI_NetworkBuildHelper, CLogicalEntity ); - -public: - virtual void PostInitNodePosition( CAI_Network *pNetwork, CAI_Node *pNode ) = 0; -}; - -//----------------------------------------------------------------------------- - -class CAI_NetworkBuilder -{ -public: - void Build( CAI_Network *pNetwork ); - void Rebuild( CAI_Network *pNetwork ); - - void InitNodePosition( CAI_Network *pNetwork, CAI_Node *pNode ); - - void InitZones( CAI_Network *pNetwork ); - -private: - void InitVisibility( CAI_Network *pNetwork, CAI_Node *pNode ); - void InitNeighbors( CAI_Network *pNetwork, CAI_Node *pNode ); - void InitClimbNodePosition( CAI_Network *pNetwork, CAI_Node *pNode ); - void InitGroundNodePosition( CAI_Network *pNetwork, CAI_Node *pNode ); - void InitLinks( CAI_Network *pNetwork, CAI_Node *pNode ); - void ForceDynamicLinkNeighbors(); - - void FloodFillZone( CAI_Node **ppNodes, CAI_Node *pNode, int zone ); - - int ComputeConnection( CAI_Node *pSrcNode, CAI_Node *pDestNode, Hull_t hull ); - - void BeginBuild(); - void EndBuild(); - - CUtlVector m_NeighborsTable; - CVarBitVec m_DidSetNeighborsTable; - CAI_TestHull * m_pTestHull; -}; - -extern CAI_NetworkBuilder g_AINetworkBuilder; - -//----------------------------------------------------------------------------- -// CAI_NetworkEditTools -// -// Purpose: Bridge class to Hammer node editing functionality -// -//----------------------------------------------------------------------------- - -class CAI_NetworkEditTools -{ -public: - CAI_NetworkEditTools(CAI_NetworkManager *); - ~CAI_NetworkEditTools(); - // ---------------------- - // Debug & Edit fields - // ---------------------- - static CAI_Node * m_pLastDeletedNode; // For undo in wc edit mode - static int m_iHullDrawNum; // Which hulls to draw - static int m_iVisibilityNode; // Node I'm showing visibility for - static int m_iGConnectivityNode; // Node I'm showing graph connectivity for - static bool m_bAirEditMode; // Editing Air Nodes - static bool m_bLinkEditMode; // Editing Links - static float m_flAirEditDistance; // Distance editing Air Nodes - - static void DrawHull(Hull_t eHull); - static void DrawNextHull(const char *ainet_name); // Draws next hull set for the named ai network - static void SetDebugBits(const char *ainet_name,int debug_bit); - - static CAI_Node * FindAINodeNearestFacing( const Vector &origin, const Vector &facing, float threshold, int nNodeType); - static CAI_Link * FindAILinkNearestFacing( const Vector &origin, const Vector &facing, float threshold); - - //--------------- - // WC Editing - //--------------- - int m_nNextWCIndex; // Next unused index used by WC - Vector * m_pWCPosition; // Array of vectors only used in wc edit mode - - //----------------- - // Debugging Tools - //----------------- - int m_debugNetOverlays; // Which network debug overlays to draw - void DrawAINetworkOverlay(void); // Draw network on the client - - void RecalcUsableNodesForHull(void); // Used only for debug drawing - - //----------------- - void OnInit(); - - int GetNodeIdFromWCId( int nWCId ); - int GetWCIdFromNodeId( int nNodeId ); - int * m_pNodeIndexTable; // Table of WC Id's to Engine Id's - - void ClearRebuildFlags(); - void SetRebuildFlags(); - void DrawEditInfoOverlay(); - -#ifdef AI_PERF_MON - //---------------------- - // Performance stats - //---------------------- - static int m_nPerfStatNN; - static int m_nPerfStatPB; - static float m_fNextPerfStatTime; -#endif - - CAI_NetworkManager *m_pManager; - CAI_Network * m_pNetwork; - - -}; - -//----------------------------------------------------------------------------- - -#endif // AI_NETWORKMANAGER_H diff --git a/game/server/ai_node.cpp b/game/server/ai_node.cpp deleted file mode 100644 index ecfa7594b..000000000 --- a/game/server/ai_node.cpp +++ /dev/null @@ -1,275 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Base combat character with no AI -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ai_hull.h" -#include "ai_node.h" -#include "ai_link.h" -#include "ai_network.h" -#include "ai_initutils.h" -#include "bitstring.h" -#include "ai_basenpc.h" -#include "ai_navigator.h" -#include "ai_moveprobe.h" -#include "fmtstr.h" -#include "game.h" -#include "ai_networkmanager.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- - -CAI_Link *CAI_Node::GetLink( int destNodeId ) -{ - // Now make sure this node still has a link to the destID - for ( int link = 0; link < NumLinks(); link++ ) - { - // If we find the link the dynamic link is valid - if ( m_Links[link]->DestNodeID(m_iID) == destNodeId ) - { - return m_Links[link]; - } - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Add a link to this node -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_Node::AddLink(CAI_Link *newLink) -{ - if ( NumLinks() == AI_MAX_NODE_LINKS ) - { - DevMsg( "Node %d has too many links\n", m_iID ); - return; - } - -#ifdef _DEBUG - for (int link=0;linkm_iDestID == m_iID || newLink->m_iSrcID == m_iID, "Added link to node that doesn't reference the node" ); -#endif - - m_Links.AddToTail( newLink ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns link if node has a link to node of the given nNodeID. -// Otherwise returns NULL -// Input : -// Output : -//----------------------------------------------------------------------------- -CAI_Link* CAI_Node::HasLink(int nNodeID) -{ - for (int link=0;linkDestNodeID(m_iID) == nNodeID) - { - return m_Links[link]; - } - } - return NULL; -} - -//------------------------------------------------------------------------------ -// Purpose : Called before GetShuffeledLinks to change the order in which -// links are returned -// Input : -// Output : -//------------------------------------------------------------------------------ -void CAI_Node::ShuffleLinks(void) -{ - m_iFirstShuffledLink++; - if (m_iFirstShuffledLink >= NumLinks()) - { - m_iFirstShuffledLink = 0; - } -} - -//------------------------------------------------------------------------------ -// Purpose : Used to get links in different order each time. -// Call ShuffleLinks() first -// Input : -// Output : -//------------------------------------------------------------------------------ -CAI_Link* CAI_Node::GetShuffeledLink(int nNum) -{ - int nLinkID = m_iFirstShuffledLink + nNum; - if (nLinkID >= NumLinks()) - { - nLinkID -= NumLinks(); - } - return m_Links[nLinkID]; -} - -//---------------------------------------------------------------------------------- -// Purpose: Returns z value of floor below given point (up to fMaxDrop inches below) -// Input : -// Output : -//---------------------------------------------------------------------------------- -float GetFloorZ(const Vector &origin, float fMaxDrop) -{ - // trace to the ground, then pop up 8 units and place node there to make it - // easier for them to connect (think stairs, chairs, and bumps in the floor). - // After the routing is done, push them back down. - // - trace_t tr; - AI_TraceLine ( origin, - origin - Vector ( 0, 0, fMaxDrop ), - MASK_NPCSOLID_BRUSHONLY, - NULL, - COLLISION_GROUP_NONE, - &tr ); - - // This trace is ONLY used if we hit an entity flagged with FL_WORLDBRUSH - trace_t trEnt; - AI_TraceLine ( origin, - origin - Vector ( 0, 0, fMaxDrop ), - MASK_NPCSOLID, - NULL, - COLLISION_GROUP_NONE, - &trEnt ); - - - // Did we hit something closer than the floor? - if ( trEnt.fraction < tr.fraction ) - { - // If it was a world brush entity, copy the node location - if ( trEnt.m_pEnt ) - { - CBaseEntity *e = trEnt.m_pEnt; - if ( e && ( e->GetFlags() & FL_WORLDBRUSH ) ) - { - tr.endpos = trEnt.endpos; - } - } - } - - return tr.endpos.z; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns z value of floor below given point (up to 384 inches below) -// Input : -// Output : -//----------------------------------------------------------------------------- -float GetFloorZ(const Vector &origin) -{ - return GetFloorZ(origin, 384); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns distance of floor from the origin (up to 384 inches) -// Input : -// Output : -//----------------------------------------------------------------------------- -float GetFloorDistance(const Vector &origin) -{ - return (origin.z - GetFloorZ(origin)); -} - -//----------------------------------------------------------------------------- -// Purpose: Climb nodes are centered over the climb surface, the must be -// shifted away from the climb surface according to the hull size -// of the NPC using the climb -// Input : -// Output : -//----------------------------------------------------------------------------- -Vector CAI_Node::GetPosition(int hull) -{ - if (m_eNodeType == NODE_CLIMB) - { - // Shift by the length of the hull and some small fudge - float shift = (0.5*NAI_Hull::Length(hull)) + (NODE_CLIMB_OFFSET); - - Vector offsetDir = Vector(cos(DEG2RAD(m_flYaw)),sin(DEG2RAD(m_flYaw)),0); - - Vector origin; - if (m_eNodeInfo & bits_NODE_CLIMB_OFF_FORWARD) - { - origin = m_vOrigin + (shift * offsetDir); - } - else if (m_eNodeInfo & bits_NODE_CLIMB_OFF_LEFT) - { - Vector upDir(0,0,1); - Vector leftDir; - CrossProduct( offsetDir, upDir, leftDir); - origin = m_vOrigin - (2 * shift * leftDir) - (shift * offsetDir); - } - else if (m_eNodeInfo & bits_NODE_CLIMB_OFF_RIGHT) - { - Vector upDir(0,0,1); - Vector leftDir; - CrossProduct( offsetDir, upDir, leftDir); - origin = m_vOrigin + (2 * shift * leftDir) - (shift * offsetDir); - } - else - { - origin = m_vOrigin - (shift * offsetDir); - } - - return Vector( origin.x, origin.y, origin.z + m_flVOffset[hull] ); - } - else if (m_eNodeType == NODE_GROUND) - { - // this is the floor resting position of this hull, adjusted to account for mins.z - return Vector( m_vOrigin.x, m_vOrigin.y, m_vOrigin.z + m_flVOffset[hull] ); - } - else - { - return m_vOrigin; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Constructor -// Input : -// Output : -//----------------------------------------------------------------------------- -CAI_Node::CAI_Node( int id, const Vector &origin, float yaw ) - : m_Links( 0, 4 ) -{ - m_vOrigin = origin; - m_iID = id; - - for (int i = 0; i < NUM_HULLS; i++) - { - m_flVOffset[i] = 0.0; - } - - m_eNodeType = NODE_GROUND; - m_eNodeInfo = 0; - - m_iFirstShuffledLink = 0; - - m_pHint = NULL; - m_flYaw = yaw; - - m_flNextUseTime = 0; - - m_zone = AI_NODE_ZONE_UNKNOWN; -}; - diff --git a/game/server/ai_node.h b/game/server/ai_node.h deleted file mode 100644 index aaae8b5d8..000000000 --- a/game/server/ai_node.h +++ /dev/null @@ -1,168 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Base combat character with no AI -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_NODE_H -#define AI_NODE_H -#pragma once - -#include "ai_hull.h" -#include "bitstring.h" -#include "utlvector.h" - -enum AI_ZoneIds_t -{ - AI_NODE_ZONE_UNKNOWN = 0, - AI_NODE_ZONE_SOLO = 1, - AI_NODE_ZONE_UNIVERSAL = 3, - AI_NODE_FIRST_ZONE = 4, -}; - -class CAI_Network; -class CAI_Link; -class CAI_Hint; -class CAI_BaseNPC; - -#define NOT_CACHED -2 // Returned if data not in cache -#define NO_NODE -1 // Returned when no node meets the qualification - -#define MAX_NODE_LINK_DIST 60*12 // Maximum connection length between nodes as well as furthest -#define MAX_NODE_LINK_DIST_SQ (MAX_NODE_LINK_DIST*MAX_NODE_LINK_DIST) // distance allowed to travel to node via local moves - -#define MAX_AIR_NODE_LINK_DIST 120*12 // Maximum connection length between air nodes as well as furthest -#define MAX_AIR_NODE_LINK_DIST_SQ (MAX_AIR_NODE_LINK_DIST*MAX_AIR_NODE_LINK_DIST) // distance allowed to travel to node via local moves - - - -#define NODE_HEIGHT 8 // how high to lift nodes off the ground after we drop them all (make stair/ramp mapping easier) -#define NODE_CLIMB_OFFSET 8 - -#define HULL_TEST_STEP_SIZE 16 // how far the test hull moves on each step - -//========================================================= -// The type of node -//========================================================= -enum NodeType_e -{ - NODE_ANY, // Used to specify any type of node (for search) - NODE_DELETED, // Used in wc_edit mode to remove nodes during runtime - NODE_GROUND, - NODE_AIR, - NODE_CLIMB, - NODE_WATER -}; - -enum NodeInfoBits_e -{ - bits_NODE_CLIMB_BOTTOM = (1 << 0), // Node at bottom of ladder - bits_NODE_CLIMB_ON = (1 << 1), // Node on ladder somewhere - bits_NODE_CLIMB_OFF_FORWARD = (1 << 2), // Dismount climb by going forward - bits_NODE_CLIMB_OFF_LEFT = (1 << 3), // Dismount climb by going left - bits_NODE_CLIMB_OFF_RIGHT = (1 << 4), // Dismount climb by going right - - bits_NODE_CLIMB_EXIT = bits_NODE_CLIMB_OFF_FORWARD| bits_NODE_CLIMB_OFF_LEFT | bits_NODE_CLIMB_OFF_RIGHT, - - NODE_ENT_FLAGS_SHIFT = 5, - - //bits_HUMAN_HULL 5 - //bits_SMALL_CENTERED_HULL 6 - //bits_WIDE_HUMAN_HULL 7 - //bits_TINY_HULL 8 - //bits_WIDE_SHORT_HULL 9 - //bits_MEDIUM_HULL 10 - //bits_TINY_CENTERED_HULL 11 - //bits_LARGE_HULL 12 - //bits_LARGE_CENTERED_HULL 13 - - bits_DONT_DROP = ( 1 << 14 ), - - /****** NOTE: will need to change node graph save/load code if exceed 16 bits here ******/ - - - - bits_NODE_WC_NEED_REBUILD = 0x10000000, // Used to more nodes in WC edit mode - bits_NODE_WC_CHANGED = 0x20000000, // Node changed during WC edit - - bits_NODE_WONT_FIT_HULL = 0x40000000, // Used only for debug display - bits_NODE_FALLEN = 0x80000000, // Fell through the world during initialization -}; - - -//============================================================================= -// >> CAI_Node -//============================================================================= - -class CAI_Node -{ -public: - - CAI_Node( int id, const Vector &origin, float yaw ); - - CAI_Hint* GetHint() { return m_pHint; } - void SetHint( CAI_Hint *pHint ) { m_pHint = pHint; } - - int NumLinks() const { return m_Links.Count(); } - void ClearLinks() { m_Links.Purge(); } - CAI_Link * GetLink( int destNodeId ); - CAI_Link * GetLinkByIndex( int i ) { return m_Links[i]; } - - bool IsLocked() const { return ( m_flNextUseTime > gpGlobals->curtime ); } - void Lock( float duration ) { m_flNextUseTime = gpGlobals->curtime + duration; } - void Unlock() { m_flNextUseTime = gpGlobals->curtime; } - - int GetZone() const { return m_zone; } - void SetZone( int zone ) { m_zone = zone; } - - Vector GetPosition(int hull); // Hull specific position for a node - CAI_Link* HasLink(int nNodeID); // Return link to nNodeID or NULL - - void ShuffleLinks(); // Called before GetShuffeledLinks to reorder - CAI_Link* GetShuffeledLink(int nNum); // Used to get links in different order each time - - int GetId() const { return m_iID; } - - const Vector & GetOrigin() const { return m_vOrigin; } - Vector & AccessOrigin() { return m_vOrigin; } - float GetYaw() const { return m_flYaw; } - - NodeType_e SetType( NodeType_e type ) { return ( m_eNodeType = type ); } - NodeType_e GetType() const { return m_eNodeType; } - - void SetNeedsRebuild() { m_eNodeInfo |= bits_NODE_WC_NEED_REBUILD; } - void ClearNeedsRebuild() { m_eNodeInfo &= ~bits_NODE_WC_NEED_REBUILD; } - bool NeedsRebuild() const { return ( ( m_eNodeInfo & bits_NODE_WC_NEED_REBUILD ) != 0 ); } - - void AddLink(CAI_Link *newLink); - - int m_iID; // ID for this node - Vector m_vOrigin; // location of this node in space - - float m_flVOffset[NUM_HULLS]; // vertical offset for each hull type, assuming ground node, 0 otherwise - float m_flYaw; // NPC on this node should face this yaw to face the hint, or climb a ladder - - NodeType_e m_eNodeType; // The type of node - - int m_eNodeInfo; // bits that tell us more about this nodes - - int m_zone; - CUtlVector m_Links; // growable array of links to this node - - float m_flNextUseTime; // When can I be used again? - CAI_Hint* m_pHint; // hint attached to this node - int m_iFirstShuffledLink; // first link to check -}; - - -extern float GetFloorZ(const Vector &origin); -extern float GetFloorDistance(const Vector &origin); - -#endif // AI_NODE_H diff --git a/game/server/ai_npcstate.h b/game/server/ai_npcstate.h deleted file mode 100644 index a84e87b74..000000000 --- a/game/server/ai_npcstate.h +++ /dev/null @@ -1,29 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_NPCSTATE_H -#define AI_NPCSTATE_H - -#if defined( _WIN32 ) -#pragma once -#endif - -enum NPC_STATE -{ - NPC_STATE_INVALID = -1, - NPC_STATE_NONE = 0, - NPC_STATE_IDLE, - NPC_STATE_ALERT, - NPC_STATE_COMBAT, - NPC_STATE_SCRIPT, - NPC_STATE_PLAYDEAD, - NPC_STATE_PRONE, // When in clutches of barnacle - NPC_STATE_DEAD - -}; - -#endif // AI_NPCSTATE_H diff --git a/game/server/ai_obstacle_type.h b/game/server/ai_obstacle_type.h deleted file mode 100644 index a5dbb3015..000000000 --- a/game/server/ai_obstacle_type.h +++ /dev/null @@ -1,36 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef AI_OBSTACLE_TYPE_H -#define AI_OBSTACLE_TYPE_H - -#if defined( _WIN32 ) -#pragma once -#endif - -//------------------------------------- -// AI_MoveSuggType_t -// -// Purpose: Specifies the type of suggestion. Different types have different weights -//------------------------------------- -enum AI_MoveSuggType_t -{ - // Positive suggestions - AIMST_MOVE, - - // Negative suggestions - AIMST_AVOID_DANGER, - AIMST_AVOID_OBJECT, - AIMST_AVOID_NPC, - AIMST_AVOID_WORLD, - - AIMST_NO_KNOWLEDGE, - AIMST_OSCILLATION_DETERRANCE, - - AIMS_INVALID -}; - -#endif // AI_OBSTACLE_TYPE_H diff --git a/game/server/ai_pathfinder.cpp b/game/server/ai_pathfinder.cpp deleted file mode 100644 index 9b4bc4664..000000000 --- a/game/server/ai_pathfinder.cpp +++ /dev/null @@ -1,2135 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -#include "ndebugoverlay.h" - -#include "ai_pathfinder.h" - -#include "ai_basenpc.h" -#include "ai_node.h" -#include "ai_network.h" -#include "ai_waypoint.h" -#include "ai_link.h" -#include "ai_routedist.h" -#include "ai_moveprobe.h" -#include "ai_dynamiclink.h" -#include "ai_hint.h" -#include "bitstring.h" - -//@todo: bad dependency! -#include "ai_navigator.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define NUM_NPC_DEBUG_OVERLAYS 50 - -const float MAX_LOCAL_NAV_DIST_GROUND[2] = { (50*12), (25*12) }; -const float MAX_LOCAL_NAV_DIST_FLY[2] = { (750*12), (750*12) }; - -//----------------------------------------------------------------------------- -// CAI_Pathfinder -// - -BEGIN_SIMPLE_DATADESC( CAI_Pathfinder ) - - // m_TriDebugOverlay - // m_bIgnoreStaleLinks - DEFINE_FIELD( m_flLastStaleLinkCheckTime, FIELD_TIME ), - // m_pNetwork - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Compute move type bits to nav type -//----------------------------------------------------------------------------- -Navigation_t MoveBitsToNavType( int fBits ) -{ - switch (fBits) - { - case bits_CAP_MOVE_GROUND: - return NAV_GROUND; - - case bits_CAP_MOVE_FLY: - return NAV_FLY; - - case bits_CAP_MOVE_CLIMB: - return NAV_CLIMB; - - case bits_CAP_MOVE_JUMP: - return NAV_JUMP; - - default: - // This will only happen if more than one bit is set - Assert(0); - return NAV_NONE; - } -} - - -//----------------------------------------------------------------------------- - -void CAI_Pathfinder::Init( CAI_Network *pNetwork ) -{ - Assert( pNetwork ); - m_pNetwork = pNetwork; -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -bool CAI_Pathfinder::UseStrongOptimizations() -{ - if ( !AIStrongOpt() ) - { - return false; - } - -#ifdef HL2_DLL - if( GetOuter()->Classify() == CLASS_PLAYER_ALLY_VITAL ) - { - return false; - } -#endif//HL2_DLL - return true; -} - -//----------------------------------------------------------------------------- -// Computes the link type -//----------------------------------------------------------------------------- -Navigation_t CAI_Pathfinder::ComputeWaypointType( CAI_Node **ppNodes, int parentID, int destID ) -{ - Navigation_t navType = NAV_NONE; - - CAI_Node *pNode = ppNodes[parentID]; - for (int link=0; link < pNode->NumLinks();link++) - { - if (pNode->GetLinkByIndex(link)->DestNodeID(parentID) == destID) - { - // BRJ 10/1/02 - // FIXME: pNPC->CapabilitiesGet() is actually the mechanism by which fliers - // filter out the bitfields in the waypoint type (most importantly, bits_MOVE_CAP_GROUND) - // that would cause the waypoint distance to be computed in a 2D, as opposed to 3D fashion - // This is a super-scary weak link if you ask me. - int linkMoveTypeBits = pNode->GetLinkByIndex(link)->m_iAcceptedMoveTypes[GetHullType()]; - int moveTypeBits = ( linkMoveTypeBits & CapabilitiesGet()); - if ( !moveTypeBits && linkMoveTypeBits == bits_CAP_MOVE_JUMP ) - { - Assert( pNode->GetHint() && pNode->GetHint()->HintType() == HINT_JUMP_OVERRIDE ); - ppNodes[destID]->Lock(0.3); - moveTypeBits = linkMoveTypeBits; - } - Navigation_t linkType = MoveBitsToNavType( moveTypeBits ); - - // This will only trigger if the links disagree about their nav type - Assert( (navType == NAV_NONE) || (navType == linkType) ); - navType = linkType; - break; - } - } - - // @TODO (toml 10-15-02): one would not expect to come out of the above logic - // with NAV_NONE. However, if a graph is newly built, it can contain malformed - // links that are referred to by the destination node, not the source node. - // This has to be fixed - if ( navType == NAV_NONE ) - { - pNode = ppNodes[destID]; - for (int link=0; link < pNode->NumLinks();link++) - { - if (pNode->GetLinkByIndex(link)->DestNodeID(parentID) == destID) - { - int npcMoveBits = CapabilitiesGet(); - int nodeMoveBits = pNode->GetLinkByIndex(link)->m_iAcceptedMoveTypes[GetHullType()]; - int moveTypeBits = ( npcMoveBits & nodeMoveBits ); - Navigation_t linkType = MoveBitsToNavType( moveTypeBits ); - - Assert( (navType == NAV_NONE) || (navType == linkType) ); - navType = linkType; - - DevMsg( "Note: Strange link found between nodes in AI node graph\n" ); - break; - } - } - } - - AssertMsg( navType != NAV_NONE, "Pathfinder appears to have output a path with consecutive nodes thate are not actually connected\n" ); - - return navType; -} - - -//----------------------------------------------------------------------------- -// Purpose: Given an array of parentID's and endID, contruct a linked -// list of waypoints through those parents -//----------------------------------------------------------------------------- -AI_Waypoint_t* CAI_Pathfinder::MakeRouteFromParents( int *parentArray, int endID ) -{ - AI_Waypoint_t *pOldWaypoint = NULL; - AI_Waypoint_t *pNewWaypoint = NULL; - int currentID = endID; - - CAI_Node **pAInode = GetNetwork()->AccessNodes(); - - while (currentID != NO_NODE) - { - // Try to link it to the previous waypoint - int prevID = parentArray[currentID]; - - int destID; - if (prevID != NO_NODE) - { - destID = prevID; - } - else - { - // If we have no previous node, then use the next node - if ( !pOldWaypoint ) - return NULL; - destID = pOldWaypoint->iNodeID; - } - - Navigation_t waypointType = ComputeWaypointType( pAInode, currentID, destID ); - - // BRJ 10/1/02 - // FIXME: It appears potentially possible for us to compute waypoints - // here which the NPC is not capable of traversing (because - // pNPC->CapabilitiesGet() in ComputeWaypointType() above filters it out). - // It's also possible if none of the lines have an appropriate DestNodeID. - // Um, shouldn't such a waypoint not be allowed?!?!? - Assert( waypointType != NAV_NONE ); - - pNewWaypoint = new AI_Waypoint_t( pAInode[currentID]->GetPosition(GetHullType()), - pAInode[currentID]->GetYaw(), waypointType, bits_WP_TO_NODE, currentID ); - - // Link it up... - pNewWaypoint->SetNext( pOldWaypoint ); - pOldWaypoint = pNewWaypoint; - - currentID = prevID; - } - - return pOldWaypoint; -} - - -//------------------------------------------------------------------------------ -// Purpose : Test if stale link is no longer stale -//------------------------------------------------------------------------------ - -bool CAI_Pathfinder::IsLinkStillStale(int moveType, CAI_Link *nodeLink) -{ - if ( m_bIgnoreStaleLinks ) - return false; - - if ( !(nodeLink->m_LinkInfo & bits_LINK_STALE_SUGGESTED ) ) - return false; - - if ( gpGlobals->curtime < nodeLink->m_timeStaleExpires ) - return true; - - // NPC should only check one stale link per think - if (gpGlobals->curtime == m_flLastStaleLinkCheckTime) - { - return true; - } - else - { - m_flLastStaleLinkCheckTime = gpGlobals->curtime; - } - - // Test movement, if suceeds, clear the stale bit - if (CheckStaleRoute(GetNetwork()->GetNode(nodeLink->m_iSrcID)->GetPosition(GetHullType()), - GetNetwork()->GetNode(nodeLink->m_iDestID)->GetPosition(GetHullType()), moveType)) - { - nodeLink->m_LinkInfo &= ~bits_LINK_STALE_SUGGESTED; - return false; - } - - nodeLink->m_timeStaleExpires = gpGlobals->curtime + 1.0; - - return true; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CAI_Pathfinder::NearestNodeToNPC() -{ - return GetNetwork()->NearestNodeToPoint( GetOuter(), GetAbsOrigin() ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CAI_Pathfinder::NearestNodeToPoint( const Vector &vecOrigin ) -{ - return GetNetwork()->NearestNodeToPoint( GetOuter(), vecOrigin ); -} - -//----------------------------------------------------------------------------- -// Purpose: Build a path between two nodes -//----------------------------------------------------------------------------- - -AI_Waypoint_t *CAI_Pathfinder::FindBestPath(int startID, int endID) -{ - AI_PROFILE_SCOPE( CAI_Pathfinder_FindBestPath ); - - if ( !GetNetwork()->NumNodes() ) - return NULL; - -#ifdef AI_PERF_MON - m_nPerfStatPB++; -#endif - - int nNodes = GetNetwork()->NumNodes(); - CAI_Node **pAInode = GetNetwork()->AccessNodes(); - - CVarBitVec openBS(nNodes); - CVarBitVec closeBS(nNodes); - - // ------------- INITIALIZE ------------------------ - float* nodeG = (float *)stackalloc( nNodes * sizeof(float) ); - float* nodeH = (float *)stackalloc( nNodes * sizeof(float) ); - float* nodeF = (float *)stackalloc( nNodes * sizeof(float) ); - int* nodeP = (int *)stackalloc( nNodes * sizeof(int) ); // Node parent - - for (int node=0;nodeGetPosition(GetHullType())-pAInode[endID]->GetPosition(GetHullType())).Length(); // Don't want to over estimate - nodeF[startID] = nodeG[startID] + nodeH[startID]; - - openBS.Set(startID); - closeBS.Set( startID ); - - // --------------- FIND BEST PATH ------------------ - while (!openBS.IsAllClear()) - { - int smallestID = CAI_Network::FindBSSmallest(&openBS,nodeF,nNodes); - - openBS.Clear(smallestID); - - CAI_Node *pSmallestNode = pAInode[smallestID]; - - if (GetOuter()->IsUnusableNode(smallestID, pSmallestNode->GetHint())) - continue; - - if (smallestID == endID) - { - AI_Waypoint_t* route = MakeRouteFromParents(&nodeP[0], endID); - return route; - } - - // Check this if the node is immediately in the path after the startNode - // that it isn't blocked - for (int link=0; link < pSmallestNode->NumLinks();link++) - { - CAI_Link *nodeLink = pSmallestNode->GetLinkByIndex(link); - - if (!IsLinkUsable(nodeLink,smallestID)) - continue; - - // FIXME: the cost function should take into account Node costs (danger, flanking, etc). - int moveType = nodeLink->m_iAcceptedMoveTypes[GetHullType()] & CapabilitiesGet(); - int testID = nodeLink->DestNodeID(smallestID); - - Vector r1 = pSmallestNode->GetPosition(GetHullType()); - Vector r2 = pAInode[testID]->GetPosition(GetHullType()); - float dist = GetOuter()->GetNavigator()->MovementCost( moveType, r1, r2 ); // MovementCost takes ref parameters!! - - if ( dist == FLT_MAX ) - continue; - - float new_g = nodeG[smallestID] + dist; - - if ( !closeBS.IsBitSet(testID) || (new_g < nodeG[testID]) ) - { - nodeP[testID] = smallestID; - nodeG[testID] = new_g; - nodeH[testID] = (pAInode[testID]->GetPosition(GetHullType())-pAInode[endID]->GetPosition(GetHullType())).Length(); - nodeF[testID] = nodeG[testID] + nodeH[testID]; - - closeBS.Set( testID ); - openBS.Set( testID ); - } - } - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Find a short random path of at least pathLength distance. If -// vDirection is given random path will expand in the given direction, -// and then attempt to go generally straight -//----------------------------------------------------------------------------- - -AI_Waypoint_t* CAI_Pathfinder::FindShortRandomPath(int startID, float minPathLength, const Vector &directionIn) -{ - int pNeighbor[AI_MAX_NODE_LINKS]; - int pStaleNeighbor[AI_MAX_NODE_LINKS]; - int numNeighbors = 1; // The start node - int numStaleNeighbors = 0; - int neighborID = NO_NODE; - - int nNodes = GetNetwork()->NumNodes(); - CAI_Node **pAInode = GetNetwork()->AccessNodes(); - - if ( !nNodes ) - return NULL; - - MARK_TASK_EXPENSIVE(); - - int *nodeParent = (int *)stackalloc( sizeof(int) * nNodes ); - CVarBitVec closeBS(nNodes); - Vector vDirection = directionIn; - - // ------------------------------------------ - // Bail immediately if node has no neighbors - // ------------------------------------------ - if (pAInode[startID]->NumLinks() == 0) - { - return NULL; - } - - // ------------- INITIALIZE ------------------------ - nodeParent[startID] = NO_NODE; - pNeighbor[0] = startID; - - // --------------- FIND PATH --------------------------------------------------------------- - // Quit when path is long enough, and I've run out of neighbors unless I'm on a climb node - // in which case I'm not allowed to stop - // ----------------------------------------------------------------------------------------- - float pathLength = 0; - int nSearchCount = 0; - while ( (pathLength < minPathLength) || - (neighborID != NO_NODE && pAInode[neighborID]->GetType() == NODE_CLIMB)) - { - nSearchCount++; - - // If no neighbors try circling back to last node - if (neighborID != NO_NODE && - numNeighbors == 0 && - numStaleNeighbors == 0 ) - { - // If we dead ended on a climb node we've failed as we - // aren't allowed to stop on a climb node - if (pAInode[neighborID]->GetType() == NODE_CLIMB) - { - // If no neighbors exist we've failed. - return NULL; - } - // Otherwise accept this path to a dead end - else - { - AI_Waypoint_t* route = MakeRouteFromParents(&nodeParent[0], neighborID); - return route; - } - } - - // ---------------------- - // Pick a neighbor - // ---------------------- - int lastID = neighborID; - - // If vDirection is non-zero attempt to expand close to current direction - if (vDirection != vec3_origin) - { - float bestDot = -1; - Vector vLastPos; - - if (lastID == NO_NODE) - { - vLastPos = GetLocalOrigin(); - } - else - { - vLastPos = pAInode[lastID]->GetOrigin(); - } - - // If no neighbors, try using a stale one - if (numNeighbors == 0) - { - neighborID = pStaleNeighbor[random->RandomInt(0,numStaleNeighbors-1)]; - } - else - { - for (int i=0;iGetOrigin(); - VectorNormalize(nodeDir); - float fDotPr = DotProduct(vDirection,nodeDir); - if (fDotPr > bestDot) - { - bestDot = fDotPr; - neighborID = pNeighbor[i]; - } - } - } - - if (neighborID != NO_NODE) - { - vDirection = vLastPos - pAInode[neighborID]->GetOrigin(); - VectorNormalize(vDirection); - } - - } - // Pick random neighbor - else if (numNeighbors != 0) - { - neighborID = pNeighbor[random->RandomInt(0,numNeighbors-1)]; - } - // If no neighbors, try using a stale one - else - { - neighborID = pStaleNeighbor[random->RandomInt(0,numStaleNeighbors-1)]; - } - - // BUGBUG: This routine is totally hosed! - if ( neighborID < 0 ) - return NULL; - - // Set previous nodes parent - nodeParent[neighborID] = lastID; - closeBS.Set(neighborID); - - // Add the new length - if (lastID != NO_NODE) - { - pathLength += (pAInode[lastID]->GetOrigin() - pAInode[neighborID]->GetOrigin()).Length(); - } - - // If path is long enough or we've hit a maximum number of search nodes, - // we're done unless we've ended on a climb node - if ((pathLength >= minPathLength || nSearchCount > 20) && - pAInode[neighborID]->GetType() != NODE_CLIMB) - { - return MakeRouteFromParents(&nodeParent[0], neighborID); - } - - // Clear neighbors - numNeighbors = 0; - numStaleNeighbors = 0; - - // Now add in new neighbors, pick links in different order ever time - pAInode[neighborID]->ShuffleLinks(); - for (int link=0; link < pAInode[neighborID]->NumLinks();link++) - { - if ( numStaleNeighbors == ARRAYSIZE(pStaleNeighbor) ) - { - AssertMsg( 0, "Array overflow" ); - return NULL; - } - if ( numNeighbors == ARRAYSIZE(pStaleNeighbor) ) - { - AssertMsg( 0, "Array overflow" ); - return NULL; - } - - CAI_Link* nodeLink = pAInode[neighborID]->GetShuffeledLink(link); - int testID = nodeLink->DestNodeID(neighborID); - - // -------------------------------------------------------------------------- - // Don't loop - // -------------------------------------------------------------------------- - if (closeBS.IsBitSet(testID)) - { - continue; - } - - // -------------------------------------------------------------------------- - // Don't go back to the node I just visited - // -------------------------------------------------------------------------- - if (testID == lastID) - { - continue; - } - - // -------------------------------------------------------------------------- - // Make sure link is valid - // -------------------------------------------------------------------------- - if (!IsLinkUsable(nodeLink,neighborID)) - { - continue; - } - - // -------------------------------------------------------------------------- - // If its a stale node add to stale list - // -------------------------------------------------------------------------- - if (pAInode[testID]->IsLocked()) - { - pStaleNeighbor[numStaleNeighbors]=testID; - numStaleNeighbors++; - } - - // -------------------------------------- - // Add to list of non-stale neighbors - // -------------------------------------- - else - { - pNeighbor[numNeighbors]=testID; - numNeighbors++; - } - } - } - // Failed to get a path of full length, but return what we have - return MakeRouteFromParents(&nodeParent[0], neighborID); -} - -//------------------------------------------------------------------------------ -// Purpose : Returns true is link us usable by the given NPC from the -// startID node. -//------------------------------------------------------------------------------ - -bool CAI_Pathfinder::IsLinkUsable(CAI_Link *pLink, int startID) -{ - // -------------------------------------------------------------------------- - // Skip if link turned off - // -------------------------------------------------------------------------- - if (pLink->m_LinkInfo & bits_LINK_OFF) - { - CAI_DynamicLink *pDynamicLink = pLink->m_pDynamicLink; - - if ( !pDynamicLink || pDynamicLink->m_strAllowUse == NULL_STRING ) - return false; - - const char *pszAllowUse = STRING( pDynamicLink->m_strAllowUse ); - if ( pDynamicLink->m_bInvertAllow ) - { - // Exlude only the specified entity name or classname - if ( GetOuter()->NameMatches(pszAllowUse) || GetOuter()->ClassMatches( pszAllowUse ) ) - return false; - } - else - { - // Exclude everything but the allowed entity name or classname - if ( !GetOuter()->NameMatches( pszAllowUse) && !GetOuter()->ClassMatches( pszAllowUse ) ) - return false; - } - } - - // -------------------------------------------------------------------------- - // Get the destination nodeID - // -------------------------------------------------------------------------- - int endID = pLink->DestNodeID(startID); - - // -------------------------------------------------------------------------- - // Make sure I have the ability to do the type of movement specified by the link - // -------------------------------------------------------------------------- - int linkMoveTypes = pLink->m_iAcceptedMoveTypes[GetHullType()]; - int moveType = ( linkMoveTypes & CapabilitiesGet() ); - - CAI_Node *pStartNode,*pEndNode; - - pStartNode = GetNetwork()->GetNode(startID); - pEndNode = GetNetwork()->GetNode(endID); - - if ( (linkMoveTypes & bits_CAP_MOVE_JUMP) && !moveType ) - { - CAI_Hint *pStartHint = pStartNode->GetHint(); - CAI_Hint *pEndHint = pEndNode->GetHint(); - if ( pStartHint && pEndHint ) - { - if ( pStartHint->HintType() == HINT_JUMP_OVERRIDE && - pEndHint->HintType() == HINT_JUMP_OVERRIDE && - ( ( ( pStartHint->GetSpawnFlags() | pEndHint->GetSpawnFlags() ) & SF_ALLOW_JUMP_UP ) || pStartHint->GetAbsOrigin().z > pEndHint->GetAbsOrigin().z ) ) - { - if ( !pStartNode->IsLocked() ) - { - if ( pStartHint->GetTargetNode() == -1 || pStartHint->GetTargetNode() == endID ) - moveType = bits_CAP_MOVE_JUMP; - } - } - } - } - - if (!moveType) - { - return false; - } - - // -------------------------------------------------------------------------- - // Check if NPC has a reason not to use the desintion node - // -------------------------------------------------------------------------- - if (GetOuter()->IsUnusableNode(endID, pEndNode->GetHint())) - { - return false; - } - - // -------------------------------------------------------------------------- - // If a jump make sure the jump is within NPC's legal parameters for jumping - // -------------------------------------------------------------------------- - if (moveType == bits_CAP_MOVE_JUMP) - { - if (!GetOuter()->IsJumpLegal(pStartNode->GetPosition(GetHullType()), - pEndNode->GetPosition(GetHullType()), - pEndNode->GetPosition(GetHullType()))) - { - return false; - } - } - - // -------------------------------------------------------------------------- - // If an NPC suggested that this link is stale and I haven't checked it yet - // I should make sure the link is still valid before proceeding - // -------------------------------------------------------------------------- - if (pLink->m_LinkInfo & bits_LINK_STALE_SUGGESTED) - { - if (IsLinkStillStale(moveType, pLink)) - { - return false; - } - } - return true; -} - -//----------------------------------------------------------------------------- - -static int NPCBuildFlags( CAI_BaseNPC *pNPC, const Vector &vecOrigin ) -{ - // If vecOrigin the the npc's position and npc is climbing only climb nodes allowed - if (pNPC->GetLocalOrigin() == vecOrigin && pNPC->GetNavType() == NAV_CLIMB) - { - return bits_BUILD_CLIMB; - } - else if (pNPC->CapabilitiesGet() & bits_CAP_MOVE_FLY) - { - return bits_BUILD_FLY | bits_BUILD_GIVEWAY; - } - else if (pNPC->CapabilitiesGet() & bits_CAP_MOVE_GROUND) - { - int buildFlags = bits_BUILD_GROUND | bits_BUILD_GIVEWAY; - if (pNPC->CapabilitiesGet() & bits_CAP_MOVE_JUMP) - { - buildFlags |= bits_BUILD_JUMP; - } - - return buildFlags; - } - return 0; -} - - -//----------------------------------------------------------------------------- -// Creates a node waypoint -//----------------------------------------------------------------------------- -AI_Waypoint_t* CAI_Pathfinder::CreateNodeWaypoint( Hull_t hullType, int nodeID, int nodeFlags ) -{ - CAI_Node *pNode = GetNetwork()->GetNode(nodeID); - - Navigation_t navType; - switch(pNode->GetType()) - { - case NODE_CLIMB: - navType = NAV_CLIMB; - break; - - case NODE_AIR: - navType = NAV_FLY; - break; - - default: - navType = NAV_GROUND; - break; - } - - return new AI_Waypoint_t( pNode->GetPosition(hullType), pNode->GetYaw(), navType, ( bits_WP_TO_NODE | nodeFlags) , nodeID ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns a route to a node for the given npc with the given -// build flags -//----------------------------------------------------------------------------- -AI_Waypoint_t* CAI_Pathfinder::RouteToNode(const Vector &vecOrigin, int buildFlags, int nodeID, float goalTolerance) -{ - AI_PROFILE_SCOPE( CAI_Pathfinder_RouteToNode ); - - buildFlags |= NPCBuildFlags( GetOuter(), vecOrigin ); - buildFlags &= ~bits_BUILD_GET_CLOSE; - - // Check if vecOrigin is already at the smallest node - - // FIXME: an equals check is a bit sloppy, this should be a tolerance - const Vector &vecNodePosition = GetNetwork()->GetNode(nodeID)->GetPosition(GetHullType()); - if (vecOrigin == vecNodePosition) - { - return CreateNodeWaypoint( GetHullType(), nodeID, bits_WP_TO_GOAL ); - } - - // Otherwise try to build a local route to the node - AI_Waypoint_t *pResult = BuildLocalRoute(vecOrigin, - vecNodePosition, NULL, bits_WP_TO_NODE, nodeID, buildFlags, goalTolerance); - if ( pResult ) - pResult->iNodeID = nodeID; - return pResult; -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns a route to a node for the given npc with the given -// build flags -//----------------------------------------------------------------------------- - -AI_Waypoint_t* CAI_Pathfinder::RouteFromNode(const Vector &vecOrigin, int buildFlags, int nodeID, float goalTolerance) -{ - AI_PROFILE_SCOPE( CAI_Pathfinder_RouteFromNode ); - - buildFlags |= NPCBuildFlags( GetOuter(), vecOrigin ); - buildFlags |= bits_BUILD_GET_CLOSE; - - // Check if vecOrigin is already at the smallest node - // FIXME: an equals check is a bit sloppy, this should be a tolerance - CAI_Node *pNode = GetNetwork()->GetNode(nodeID); - const Vector &vecNodePosition = pNode->GetPosition(GetHullType()); - - if (vecOrigin == vecNodePosition) - { - return CreateNodeWaypoint( GetHullType(), nodeID, bits_WP_TO_GOAL ); - } - - // Otherwise try to build a local route from the node - AI_Waypoint_t* pResult = BuildLocalRoute( vecNodePosition, - vecOrigin, NULL, bits_WP_TO_GOAL, NO_NODE, buildFlags, goalTolerance); - - // Handle case of target hanging over edge near climb dismount - if ( !pResult && - pNode->GetType() == NODE_CLIMB && - ( vecOrigin - vecNodePosition ).Length2DSqr() < 32.0*32.0 && - GetOuter()->GetMoveProbe()->CheckStandPosition(vecNodePosition, MASK_NPCSOLID_BRUSHONLY ) ) - { - pResult = new AI_Waypoint_t( vecOrigin, 0, NAV_GROUND, bits_WP_TO_GOAL, nodeID ); - } - - return pResult; -} - -//----------------------------------------------------------------------------- -// Builds a simple route (no triangulation, no making way) -//----------------------------------------------------------------------------- -AI_Waypoint_t *CAI_Pathfinder::BuildSimpleRoute( Navigation_t navType, const Vector &vStart, - const Vector &vEnd, const CBaseEntity *pTarget, int endFlags, int nodeID, - int nodeTargetType, float flYaw ) -{ - Assert( navType == NAV_JUMP || navType == NAV_CLIMB ); // this is what this here function is for - // Only allowed to jump to ground nodes - if ((nodeID == NO_NODE) || (GetNetwork()->GetNode(nodeID)->GetType() == nodeTargetType) ) - { - AIMoveTrace_t moveTrace; - GetOuter()->GetMoveProbe()->MoveLimit( navType, vStart, vEnd, MASK_NPCSOLID, pTarget, &moveTrace ); - - // If I was able to make the move, or the vEnd is the - // goal and I'm within tolerance, just move to vEnd - if (!IsMoveBlocked(moveTrace)) - { - // It worked so return a route of length one to the endpoint - return new AI_Waypoint_t( vEnd, flYaw, navType, endFlags, nodeID ); - } - } - return NULL; -} - - -//----------------------------------------------------------------------------- -// Builds a complex route (triangulation, making way) -//----------------------------------------------------------------------------- -AI_Waypoint_t *CAI_Pathfinder::BuildComplexRoute( Navigation_t navType, const Vector &vStart, - const Vector &vEnd, const CBaseEntity *pTarget, int endFlags, int nodeID, - int buildFlags, float flYaw, float goalTolerance, float maxLocalNavDistance ) -{ - AI_PROFILE_SCOPE( CAI_Pathfinder_BuildComplexRoute ); - - float flTotalDist = ComputePathDistance( navType, vStart, vEnd ); - if ( flTotalDist < 0.0625 ) - { - return new AI_Waypoint_t( vEnd, flYaw, navType, endFlags, nodeID ); - } - - unsigned int collideFlags = (buildFlags & bits_BUILD_IGNORE_NPCS) ? MASK_NPCSOLID_BRUSHONLY : MASK_NPCSOLID; - - bool bCheckGround = (GetOuter()->CapabilitiesGet() & bits_CAP_SKIP_NAV_GROUND_CHECK) ? false : true; - - if ( flTotalDist <= maxLocalNavDistance ) - { - AIMoveTrace_t moveTrace; - - AI_PROFILE_SCOPE_BEGIN( CAI_Pathfinder_BuildComplexRoute_Direct ); - - GetOuter()->GetMoveProbe()->MoveLimit( navType, vStart, vEnd, collideFlags, pTarget, (bCheckGround) ? 100 : 0, &moveTrace); - - // If I was able to make the move... - if (!IsMoveBlocked(moveTrace)) - { - // It worked so return a route of length one to the endpoint - return new AI_Waypoint_t( vEnd, flYaw, navType, endFlags, nodeID ); - } - - // ...or the vEnd is thegoal and I'm within tolerance, just move to vEnd - if ( (buildFlags & bits_BUILD_GET_CLOSE) && - (endFlags & bits_WP_TO_GOAL) && - moveTrace.flDistObstructed <= goalTolerance ) - { - return new AI_Waypoint_t( vEnd, flYaw, navType, endFlags, nodeID ); - } - - AI_PROFILE_SCOPE_END(); - - // ------------------------------------------------------------------- - // Try to triangulate if requested - // ------------------------------------------------------------------- - - AI_PROFILE_SCOPE_BEGIN( CAI_Pathfinder_BuildComplexRoute_Triangulate ); - - if (buildFlags & bits_BUILD_TRIANG) - { - if ( !UseStrongOptimizations() || ( GetOuter()->GetState() == NPC_STATE_SCRIPT || GetOuter()->IsCurSchedule( SCHED_SCENE_GENERIC, false ) ) ) - { - float flTotalDist = ComputePathDistance( navType, vStart, vEnd ); - - AI_Waypoint_t *triangRoute = BuildTriangulationRoute(vStart, vEnd, pTarget, - endFlags, nodeID, flYaw, flTotalDist - moveTrace.flDistObstructed, navType); - - if (triangRoute) - { - return triangRoute; - } - } - } - - AI_PROFILE_SCOPE_END(); - - // ------------------------------------------------------------------- - // Try to giveway if requested - // ------------------------------------------------------------------- - if (moveTrace.fStatus == AIMR_BLOCKED_NPC && (buildFlags & bits_BUILD_GIVEWAY)) - { - // If I can't get there even ignoring NPCs, don't bother to request a giveway - AIMoveTrace_t moveTrace2; - GetOuter()->GetMoveProbe()->MoveLimit( navType, vStart, vEnd, MASK_NPCSOLID_BRUSHONLY, pTarget, (bCheckGround) ? 100 : 0, &moveTrace2 ); - - if (!IsMoveBlocked(moveTrace2)) - { - // If I can clear the way return a route of length one to the target location - if ( CanGiveWay(vStart, vEnd, moveTrace.pObstruction) ) - { - return new AI_Waypoint_t( vEnd, flYaw, navType, endFlags, nodeID ); - } - } - } - } - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Attempts to build a jump route between vStart -// and vEnd, ignoring entity pTarget -// Input : -// Output : Returns a route if sucessful or NULL if no local route was possible -//----------------------------------------------------------------------------- -AI_Waypoint_t *CAI_Pathfinder::BuildJumpRoute(const Vector &vStart, const Vector &vEnd, - const CBaseEntity *pTarget, int endFlags, int nodeID, int buildFlags, float flYaw) -{ - // Only allowed to jump to ground nodes - return BuildSimpleRoute( NAV_JUMP, vStart, vEnd, pTarget, - endFlags, nodeID, NODE_GROUND, flYaw ); -} - -//----------------------------------------------------------------------------- -// Purpose: Attempts to build a climb route between vStart -// and vEnd, ignoring entity pTarget -// Input : -// Output : Returns a route if sucessful or NULL if no climb route was possible -//----------------------------------------------------------------------------- -AI_Waypoint_t *CAI_Pathfinder::BuildClimbRoute(const Vector &vStart, const Vector &vEnd, const CBaseEntity *pTarget, int endFlags, int nodeID, int buildFlags, float flYaw) -{ - // Only allowed to climb to climb nodes - return BuildSimpleRoute( NAV_CLIMB, vStart, vEnd, pTarget, - endFlags, nodeID, NODE_CLIMB, flYaw ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Attempts to build a ground route between vStart -// and vEnd, ignoring entity pTarget the the given tolerance -// Input : -// Output : Returns a route if sucessful or NULL if no ground route was possible -//----------------------------------------------------------------------------- -AI_Waypoint_t *CAI_Pathfinder::BuildGroundRoute(const Vector &vStart, const Vector &vEnd, - const CBaseEntity *pTarget, int endFlags, int nodeID, int buildFlags, float flYaw, float goalTolerance) -{ - return BuildComplexRoute( NAV_GROUND, vStart, vEnd, pTarget, - endFlags, nodeID, buildFlags, flYaw, goalTolerance, MAX_LOCAL_NAV_DIST_GROUND[UseStrongOptimizations()] ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Attempts to build a fly route between vStart -// and vEnd, ignoring entity pTarget the the given tolerance -// Input : -// Output : Returns a route if sucessful or NULL if no ground route was possible -//----------------------------------------------------------------------------- -AI_Waypoint_t *CAI_Pathfinder::BuildFlyRoute(const Vector &vStart, const Vector &vEnd, - const CBaseEntity *pTarget, int endFlags, int nodeID, int buildFlags, float flYaw, float goalTolerance) -{ - return BuildComplexRoute( NAV_FLY, vStart, vEnd, pTarget, - endFlags, nodeID, buildFlags, flYaw, goalTolerance, MAX_LOCAL_NAV_DIST_FLY[UseStrongOptimizations()] ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Attempts to build a route between vStart and vEnd, requesting the -// pNPCBlocker to get out of the way -// Input : -// Output : Returns a route if sucessful or NULL if giveway failed -//----------------------------------------------------------------------------- -bool CAI_Pathfinder::CanGiveWay( const Vector& vStart, const Vector& vEnd, CBaseEntity *pBlocker) -{ - // FIXME: make this a CAI_BaseNPC member function - CAI_BaseNPC *pNPCBlocker = pBlocker->MyNPCPointer(); - if (pNPCBlocker && pNPCBlocker->edict()) - { - Disposition_t eDispBlockerToMe = pNPCBlocker->IRelationType( GetOuter() ); - if ( ( eDispBlockerToMe == D_LI ) || ( eDispBlockerToMe == D_NU ) ) - { - return true; - } - - return false; - - // FIXME: this is called in route creation, not navigation. It shouldn't actually make - // anyone get out of their way, just see if they'll honor the request. - // things like locked doors, enemies and such should refuse, all others shouldn't. - // things like breakables should know who is trying to break them, though a door hidden behind - // some boxes shouldn't be known to the AI even though a route should connect through them but - // be turned off. - - /* - Vector moveDir = (vEnd - vStart).Normalize(); - Vector blockerDir = (pNPCBlocker->GetLocalOrigin() - vStart); - float blockerDist = DotProduct(moveDir,blockerDir); - Vector blockPos = vStart + (moveDir*blockerDist); - - if (pNPCBlocker->RequestGiveWay ( m_owner->GetLocalOrigin(), blockPos, moveDir, m_owner->m_eHull)) - { - return true; - } - */ - } - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Attempts to build a triangulation route between vStart -// and vEnd, ignoring entity pTarget the the given tolerance and -// triangulating around a blocking object at blockDist -// Input : -// Output : Returns a route if sucessful or NULL if no local route was possible -//----------------------------------------------------------------------------- -AI_Waypoint_t *CAI_Pathfinder::BuildTriangulationRoute( - const Vector &vStart, // from where - const Vector &vEnd, // to where - const CBaseEntity *pTarget, // an entity I can ignore - int endFlags, // add these WP flags to the last waypoint - int nodeID, // node id for the last waypoint - float flYaw, // ideal yaw for the last waypoint - float flDistToBlocker,// how far away is the obstruction from the start? - Navigation_t navType) -{ - AI_PROFILE_SCOPE( CAI_Pathfinder_BuildTriangulationRoute ); - - Vector vApex; - if (!Triangulate(navType, vStart, vEnd, flDistToBlocker, pTarget, &vApex )) - return NULL; - - //----------------------------------------------------------------------------- - // it worked, create a route - //----------------------------------------------------------------------------- - AI_Waypoint_t *pWayPoint2 = new AI_Waypoint_t( vEnd, flYaw, navType, endFlags, nodeID ); - - // FIXME: Compute a reasonable yaw here - AI_Waypoint_t *waypoint1 = new AI_Waypoint_t( vApex, 0, navType, bits_WP_TO_DETOUR, NO_NODE ); - waypoint1->SetNext(pWayPoint2); - - return waypoint1; -} - -//----------------------------------------------------------------------------- -// Purpose: Get the next node (with wrapping) around a circularly wound path -// Input : nLastNode - The starting node -// nDirection - Direction we're moving -// nNumNodes - Total nodes in the chain -//----------------------------------------------------------------------------- -inline int GetNextPoint( int nLastNode, int nDirection, int nNumNodes ) -{ - int nNextNode = nLastNode + nDirection; - if ( nNextNode > (nNumNodes-1) ) - nNextNode = 0; - else if ( nNextNode < 0 ) - nNextNode = (nNumNodes-1); - - return nNextNode; -} - -//----------------------------------------------------------------------------- -// Purpose: Attempt to wind a route through a series of node points in a specified direction. -// Input : *vecCorners - Points to test between -// nNumCorners - Number of points to test -// &vecStart - Starting position -// &vecEnd - Ending position -// Output : Route through the points -//----------------------------------------------------------------------------- -AI_Waypoint_t *CAI_Pathfinder::BuildRouteThroughPoints( Vector *vecPoints, int nNumPoints, int nDirection, int nStartIndex, int nEndIndex, Navigation_t navType, CBaseEntity *pTarget ) -{ - AIMoveTrace_t endTrace; - endTrace.fStatus = AIMR_OK; - - CAI_MoveProbe *pMoveProbe = GetOuter()->GetMoveProbe(); - - AI_Waypoint_t *pFirstRoute = NULL; - AI_Waypoint_t *pHeadRoute = NULL; - - int nCurIndex = nStartIndex; - int nNextIndex; - - // FIXME: Must be able to move to the first position (these needs some parameterization) - pMoveProbe->MoveLimit( navType, GetOuter()->GetAbsOrigin(), vecPoints[nStartIndex], MASK_NPCSOLID, pTarget, &endTrace ); - if ( IsMoveBlocked( endTrace ) ) - { - // NDebugOverlay::HorzArrow( GetOuter()->GetAbsOrigin(), vecPoints[nStartIndex], 8.0f, 255, 0, 0, 0, true, 4.0f ); - return NULL; - } - - // NDebugOverlay::HorzArrow( GetOuter()->GetAbsOrigin(), vecPoints[nStartIndex], 8.0f, 0, 255, 0, 0, true, 4.0f ); - - int nRunAwayCount = 0; - while ( nRunAwayCount++ < nNumPoints ) - { - // Advance our index in the specified direction - nNextIndex = GetNextPoint( nCurIndex, nDirection, nNumPoints ); - - // Try and build a local route between the current and next point - pMoveProbe->MoveLimit( navType, vecPoints[nCurIndex], vecPoints[nNextIndex], MASK_NPCSOLID, pTarget, &endTrace ); - if ( IsMoveBlocked( endTrace ) ) - { - // TODO: Triangulate here if we failed? - - // We failed, so give up - if ( pHeadRoute ) - { - DeleteAll( pHeadRoute ); - } - - // NDebugOverlay::HorzArrow( vecPoints[nCurIndex], vecPoints[nNextIndex], 8.0f, 255, 0, 0, 0, true, 4.0f ); - return NULL; - } - - // NDebugOverlay::HorzArrow( vecPoints[nCurIndex], vecPoints[nNextIndex], 8.0f, 0, 255, 0, 0, true, 4.0f ); - - if ( pHeadRoute == NULL ) - { - // Start a new route head - pFirstRoute = pHeadRoute = new AI_Waypoint_t( vecPoints[nCurIndex], 0.0f, navType, bits_WP_TO_DETOUR, NO_NODE ); - } - else - { - // Link a new waypoint into the path - AI_Waypoint_t *pNewNode = new AI_Waypoint_t( vecPoints[nCurIndex], 0.0f, navType, bits_WP_TO_DETOUR|bits_WP_DONT_SIMPLIFY, NO_NODE ); - pHeadRoute->SetNext( pNewNode ); - pHeadRoute = pNewNode; - } - - // See if we're done - if ( nNextIndex == nEndIndex ) - { - AI_Waypoint_t *pNewNode = new AI_Waypoint_t( vecPoints[nEndIndex], 0.0f, navType, bits_WP_TO_DETOUR, NO_NODE ); - pHeadRoute->SetNext( pNewNode ); - pHeadRoute = pNewNode; - break; - } - - // Advance one node - nCurIndex = nNextIndex; - } - - return pFirstRoute; -} - -//----------------------------------------------------------------------------- -// Purpose: Find the closest point in a list of points, to a specified position -// Input : &vecPosition - Position to test against -// *vecPoints - List of vectors we'll check -// nNumPoints - Number of points in the list -// Output : Index to the closest point in the list -//----------------------------------------------------------------------------- -inline int ClosestPointToPosition( const Vector &vecPosition, Vector *vecPoints, int nNumPoints ) -{ - int nBestNode = -1; - float flBestDistSqr = FLT_MAX; - float flDistSqr; - for ( int i = 0; i < nNumPoints; i++ ) - { - flDistSqr = ( vecPoints[i] - vecPosition ).LengthSqr(); - if ( flDistSqr < flBestDistSqr ) - { - flBestDistSqr = flDistSqr; - nBestNode = i; - } - } - - return nBestNode; -} - -//----------------------------------------------------------------------------- -// Purpose: Find which winding through a circular list is shortest in physical distance travelled -// Input : &vecStart - Where we started from -// nStartPoint - Starting index into the points -// nEndPoint - Ending index into the points -// nNumPoints - Number of points in the list -// *vecPoints - List of vectors making up a list of points -//----------------------------------------------------------------------------- -inline int ShortestDirectionThroughPoints( const Vector &vecStart, int nStartPoint, int nEndPoint, Vector *vecPoints, int nNumPoints ) -{ - const int nClockwise = 1; - const int nCounterClockwise = -1; - - // Find the quickest direction around the object - int nCurPoint = nStartPoint; - int nNextPoint = GetNextPoint( nStartPoint, 1, nNumPoints ); - - float flStartDistSqr = ( vecStart - vecPoints[nStartPoint] ).LengthSqr(); - float flDistanceSqr = flStartDistSqr; - - // Try going clockwise first - for ( int i = 0; i < nNumPoints; i++ ) - { - flDistanceSqr += ( vecPoints[nCurPoint] - vecPoints[nNextPoint] ).LengthSqr(); - - if ( nNextPoint == nEndPoint ) - break; - - nNextPoint = GetNextPoint( nNextPoint, 1, nNumPoints ); - } - - // Save this to test against - float flBestDistanceSqr = flDistanceSqr; - - // Start from the beginning again - flDistanceSqr = flStartDistSqr; - - nCurPoint = nStartPoint; - nNextPoint = GetNextPoint( nStartPoint, -1, nNumPoints ); - - // Now go the other way and see if it's shorter to do so - for ( int i = 0; i < nNumPoints; i++ ) - { - flDistanceSqr += ( vecPoints[nCurPoint] - vecPoints[nNextPoint] ).LengthSqr(); - - // We've gone over our maximum so we can't be shorter - if ( flDistanceSqr > flBestDistanceSqr ) - break; - - // We hit the end, we're shorter - if ( nNextPoint == nEndPoint ) - return nCounterClockwise; - - nNextPoint = GetNextPoint( nNextPoint, -1, nNumPoints ); - } - - return nClockwise; -} - -//----------------------------------------------------------------------------- -// Purpose: Attempt to build an avoidance route around an object using its OBB -// Currently this function is meant for NPCs moving around a vehicle, -// and is very specialized as such -// -// Output : Returns a route if successful or NULL if no local route was possible -//----------------------------------------------------------------------------- -AI_Waypoint_t *CAI_Pathfinder::BuildOBBAvoidanceRoute( const Vector &vStart, const Vector &vEnd, - const CBaseEntity *pObstruction, // obstruction to avoid - const CBaseEntity *pTarget, // target to ignore - Navigation_t navType ) -{ - AI_PROFILE_SCOPE( CAI_Pathfinder_BuildOBBAvoidanceRoute ); - - // If the point we're navigating to is within our OBB, then fail - // TODO: We could potentially also just try to get as near as possible - if ( pObstruction->CollisionProp()->IsPointInBounds( vEnd ) ) - return NULL; - - // Find out how much we'll need to inflate the collision bounds to let us move past - Vector vecSize = pObstruction->CollisionProp()->OBBSize(); - float flWidth = GetOuter()->GetHullWidth() * 0.5f; - - float flWidthPercX = ( flWidth / vecSize.x ); - float flWidthPercY = ( flWidth / vecSize.y ); - - // Find the points around the object, bloating it by our hull width - // The ordering of these corners wind clockwise around the object, starting at the top left - Vector vecPoints[4]; - pObstruction->CollisionProp()->NormalizedToWorldSpace( Vector( -flWidthPercX, 1+flWidthPercY, 0.25f ), &vecPoints[0] ); - pObstruction->CollisionProp()->NormalizedToWorldSpace( Vector( 1+flWidthPercX, 1+flWidthPercY, 0.25f ), &vecPoints[1] ); - pObstruction->CollisionProp()->NormalizedToWorldSpace( Vector( 1+flWidthPercX, -flWidthPercY, 0.25f ), &vecPoints[2] ); - pObstruction->CollisionProp()->NormalizedToWorldSpace( Vector( -flWidthPercX, -flWidthPercY, 0.25f ), &vecPoints[3] ); - - // Find the two points nearest our goals - int nStartPoint = ClosestPointToPosition( vStart, vecPoints, ARRAYSIZE( vecPoints ) ); - int nEndPoint = ClosestPointToPosition( vEnd, vecPoints, ARRAYSIZE( vecPoints ) ); - - // We won't be able to build a route if we're moving no distance between points - if ( nStartPoint == nEndPoint ) - return NULL; - - // Find the shortest path around this wound polygon (direction is how to step through array) - int nDirection = ShortestDirectionThroughPoints( vStart, nStartPoint, nEndPoint, vecPoints, ARRAYSIZE( vecPoints ) ); - - // Attempt to build a route in our direction - AI_Waypoint_t *pRoute = BuildRouteThroughPoints( vecPoints, ARRAYSIZE(vecPoints), nDirection, nStartPoint, nEndPoint, navType, (CBaseEntity *) pTarget ); - if ( pRoute == NULL ) - { - // Failed that way, so try the opposite - pRoute = BuildRouteThroughPoints( vecPoints, ARRAYSIZE(vecPoints), (-nDirection), nStartPoint, nEndPoint, navType, (CBaseEntity *) pTarget ); - if ( pRoute == NULL ) - return NULL; - } - - return pRoute; -} - -//----------------------------------------------------------------------------- -// Purpose: Attempts to build a local route (not using nodes) between vStart -// and vEnd, ignoring entity pTarget the the given tolerance -// Input : -// Output : Returns a route if successful or NULL if no local route was possible -//----------------------------------------------------------------------------- -AI_Waypoint_t *CAI_Pathfinder::BuildLocalRoute(const Vector &vStart, const Vector &vEnd, const CBaseEntity *pTarget, int endFlags, int nodeID, int buildFlags, float goalTolerance) -{ - AI_PROFILE_SCOPE( CAI_Pathfinder_BuildLocalRoute ); - - // Get waypoint yaw - float flYaw; - if (nodeID != NO_NODE) - { - flYaw = GetNetwork()->GetNode(nodeID)->GetYaw(); - } - else - { - flYaw = 0; - } - - // Try a ground route if requested - if (buildFlags & bits_BUILD_GROUND) - { - AI_Waypoint_t *groundRoute = BuildGroundRoute(vStart,vEnd,pTarget,endFlags,nodeID,buildFlags,flYaw,goalTolerance); - - if (groundRoute) - { - return groundRoute; - } - } - - // Try a fly route if requested - if ( buildFlags & bits_BUILD_FLY ) - { - AI_Waypoint_t *flyRoute = BuildFlyRoute(vStart,vEnd,pTarget,endFlags,nodeID,buildFlags,flYaw,goalTolerance); - - if (flyRoute) - { - return flyRoute; - } - } - - // Try a jump route if NPC can jump and requested - if ((buildFlags & bits_BUILD_JUMP) && (CapabilitiesGet() & bits_CAP_MOVE_JUMP)) - { - AI_Waypoint_t *jumpRoute = BuildJumpRoute(vStart,vEnd,pTarget,endFlags,nodeID,buildFlags,flYaw); - - if (jumpRoute) - { - return jumpRoute; - } - } - - // Try a climb route if NPC can climb and requested - if ((buildFlags & bits_BUILD_CLIMB) && (CapabilitiesGet() & bits_CAP_MOVE_CLIMB)) - { - AI_Waypoint_t *climbRoute = BuildClimbRoute(vStart,vEnd,pTarget,endFlags,nodeID,buildFlags,flYaw); - - if (climbRoute) - { - return climbRoute; - } - } - - // Everything failed so return a NULL route - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Builds a route to the given vecGoal using either local movement -// or nodes -//----------------------------------------------------------------------------- - -ConVar ai_no_local_paths( "ai_no_local_paths", "0" ); - -AI_Waypoint_t *CAI_Pathfinder::BuildRoute( const Vector &vStart, const Vector &vEnd, CBaseEntity *pTarget, float goalTolerance, Navigation_t curNavType, bool bLocalSucceedOnWithinTolerance ) -{ - int buildFlags = 0; - bool bTryLocal = !ai_no_local_paths.GetBool(); - - // Set up build flags - if (curNavType == NAV_CLIMB) - { - // if I'm climbing, then only allow routes that are also climb routes - buildFlags = bits_BUILD_CLIMB; - bTryLocal = false; - } - else if ( (CapabilitiesGet() & bits_CAP_MOVE_FLY) || (CapabilitiesGet() & bits_CAP_MOVE_SWIM) ) - { - buildFlags = (bits_BUILD_FLY | bits_BUILD_GIVEWAY | bits_BUILD_TRIANG); - } - else if (CapabilitiesGet() & bits_CAP_MOVE_GROUND) - { - buildFlags = (bits_BUILD_GROUND | bits_BUILD_GIVEWAY | bits_BUILD_TRIANG); - if ( CapabilitiesGet() & bits_CAP_MOVE_JUMP ) - { - buildFlags |= bits_BUILD_JUMP; - } - } - - // If our local moves can succeed if we get within the goaltolerance, set the flag - if ( bLocalSucceedOnWithinTolerance ) - { - buildFlags |= bits_BUILD_GET_CLOSE; - } - - AI_Waypoint_t *pResult = NULL; - - // First try a local route - if ( bTryLocal && CanUseLocalNavigation() ) - { - pResult = BuildLocalRoute(vStart, vEnd, pTarget, - bits_WP_TO_GOAL, NO_NODE, - buildFlags, goalTolerance); - } - - // If the fails, try a node route - if ( !pResult ) - { - pResult = BuildNodeRoute( vStart, vEnd, buildFlags, goalTolerance ); - } - - m_bIgnoreStaleLinks = false; - - return pResult; -} - -void CAI_Pathfinder::UnlockRouteNodes( AI_Waypoint_t *pPath ) -{ - CAI_Node *pNode; - while ( pPath ) - { - if ( pPath->iNodeID != NO_NODE && ( pNode = GetNetwork()->GetNode(pPath->iNodeID) ) != NULL && pNode->IsLocked() ) - pNode->Unlock(); - pPath = pPath->GetNext(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Attempts to build a radial route around the given center position -// over a given arc size -// -// Input : vStartPos - where route should start from -// vCenterPos - the center of the arc -// vGoalPos - ultimate goal position -// flRadius - radius of the arc -// flArc - how long should the path be (in degrees) -// bClockwise - the direction we are heading -// Output : The route -//----------------------------------------------------------------------------- -AI_Waypoint_t *CAI_Pathfinder::BuildRadialRoute( const Vector &vStartPos, const Vector &vCenterPos, const Vector &vGoalPos, float flRadius, float flArc, float flStepDist, bool bClockwise, float goalTolerance, bool bAirRoute /*= false*/ ) -{ - MARK_TASK_EXPENSIVE(); - - // ------------------------------------------------------------------------------ - // Make sure we have a minimum distance between nodes. For the given - // radius, calculate the angular step necessary for this distance. - // IMPORTANT: flStepDist must be large enough that given the - // NPC's movment speed that it can come to a stop - // ------------------------------------------------------------------------------ - float flAngleStep = 2.0f * atan((0.5f*flStepDist)/flRadius); - - // Flip direction if clockwise - if ( bClockwise ) - { - flArc *= -1; - flAngleStep *= -1; - } - - // Calculate the start angle on the arc in world coordinates - Vector vStartDir = ( vStartPos - vCenterPos ); - VectorNormalize( vStartDir ); - - // Get our control angles - float flStartAngle = DEG2RAD(UTIL_VecToYaw(vStartDir)); - float flEndAngle = flStartAngle + DEG2RAD(flArc); - - // Offset set our first node by one arc step so NPC doesn't run perpendicular to the arc when starting a different radius - flStartAngle += flAngleStep; - - AI_Waypoint_t* pHeadRoute = NULL; // Pointer to the beginning of the route chains - AI_Waypoint_t* pNextRoute = NULL; // Next leg of the route - AI_Waypoint_t* pLastRoute = NULL; // The last route chain added to the head - Vector vLastPos = vStartPos; // Last position along the arc in worldspace - int fRouteBits = ( bAirRoute ) ? bits_BUILD_FLY : bits_BUILD_GROUND; // Whether this is an air route or not - float flCurAngle = flStartAngle; // Starting angle - Vector vNextPos; - - // Make sure that we've got somewhere to go. This generally means your trying to walk too small an arc. - Assert( ( bClockwise && flCurAngle > flEndAngle ) || ( !bClockwise && flCurAngle < flEndAngle ) ); - - // Start iterating through our arc - while( 1 ) - { - // See if we've ended our run - if ( ( bClockwise && flCurAngle <= flEndAngle ) || ( !bClockwise && flCurAngle >= flEndAngle ) ) - break; - - // Get our next position along the arc - vNextPos = vCenterPos; - vNextPos.x += flRadius * cos( flCurAngle ); - vNextPos.y += flRadius * sin( flCurAngle ); - - // Build a route from the last position to the current one - pNextRoute = BuildLocalRoute( vLastPos, vNextPos, NULL, 0, NO_NODE, fRouteBits, goalTolerance); - - // If we can't find a route, we failed - if ( pNextRoute == NULL ) - return NULL; - - // Don't simplify the route (otherwise we'll cut corners where we don't want to! - pNextRoute->ModifyFlags( bits_WP_DONT_SIMPLIFY, true ); - - if ( pHeadRoute ) - { - // Tack the routes together - AddWaypointLists( pHeadRoute, pNextRoute ); - } - else - { - // Otherwise we're now the previous route - pHeadRoute = pNextRoute; - } - - // Move our position - vLastPos = vNextPos; - pLastRoute = pNextRoute; - - // Move our current angle - flCurAngle += flAngleStep; - } - - // NOTE: We could also simply build a local route with no curve, but it's unlikely that's what was intended by the caller - if ( pHeadRoute == NULL ) - return NULL; - - // Append a path to the final position - pLastRoute = BuildLocalRoute( vLastPos, vGoalPos, NULL, 0, NO_NODE, bAirRoute ? bits_BUILD_FLY : bits_BUILD_GROUND, goalTolerance ); - if ( pLastRoute == NULL ) - return NULL; - - // Allow us to simplify the last leg of the route - pLastRoute->ModifyFlags( bits_WP_DONT_SIMPLIFY, false ); - pLastRoute->ModifyFlags( bits_WP_TO_GOAL, true ); - - // Add them together - AddWaypointLists( pHeadRoute, pLastRoute ); - - // Give back the complete route - return pHeadRoute; -} - - -//----------------------------------------------------------------------------- -// Checks a stale navtype route -//----------------------------------------------------------------------------- -bool CAI_Pathfinder::CheckStaleNavTypeRoute( Navigation_t navType, const Vector &vStart, const Vector &vEnd ) -{ - AIMoveTrace_t moveTrace; - GetOuter()->GetMoveProbe()->MoveLimit( navType, vStart, vEnd, MASK_NPCSOLID, NULL, 100, AIMLF_IGNORE_TRANSIENTS, &moveTrace); - - // Is the direct route clear? - if (!IsMoveBlocked(moveTrace)) - { - return true; - } - - // Next try to triangulate - // FIXME: Since blocked dist is an unreliable number, this computation is bogus - Vector vecDelta; - VectorSubtract( vEnd, vStart, vecDelta ); - float flTotalDist = vecDelta.Length(); - - Vector vApex; - if (Triangulate( navType, vStart, vEnd, flTotalDist - moveTrace.flDistObstructed, NULL, &vApex )) - { - return true; - } - - // Try a giveway request, if I can get there ignoring NPCs - if ( moveTrace.pObstruction && moveTrace.pObstruction->MyNPCPointer() ) - { - GetOuter()->GetMoveProbe()->MoveLimit( navType, vStart, vEnd, MASK_NPCSOLID_BRUSHONLY, NULL, &moveTrace); - - if (!IsMoveBlocked(moveTrace)) - { - return true; - } - } - - return false; -} - - - -//----------------------------------------------------------------------------- -// Purpose: Checks if a local route (not using nodes) between vStart -// and vEnd exists using the moveType -// Input : -// Output : Returns a route if sucessful or NULL if no local route was possible -//----------------------------------------------------------------------------- -bool CAI_Pathfinder::CheckStaleRoute(const Vector &vStart, const Vector &vEnd, int moveTypes) -{ - AI_PROFILE_SCOPE( CAI_Pathfinder_CheckStaleRoute ); - - // ------------------------------------------------------------------- - // First try to go there directly - // ------------------------------------------------------------------- - if (moveTypes & bits_CAP_MOVE_GROUND) - { - if (CheckStaleNavTypeRoute( NAV_GROUND, vStart, vEnd )) - return true; - } - - // ------------------------------------------------------------------- - // First try to go there directly - // ------------------------------------------------------------------- - if (moveTypes & bits_CAP_MOVE_FLY) - { - if (CheckStaleNavTypeRoute( NAV_FLY, vStart, vEnd )) - return true; - } - - // -------------------------------------------------------------- - // Try to jump if we can jump to a node - // -------------------------------------------------------------- - if (moveTypes & bits_CAP_MOVE_JUMP) - { - AIMoveTrace_t moveTrace; - GetOuter()->GetMoveProbe()->MoveLimit( NAV_JUMP, vStart, vEnd, MASK_NPCSOLID, NULL, &moveTrace); - if (!IsMoveBlocked(moveTrace)) - { - return true; - } - else - { - // Can't tell jump up from jump down at this point - GetOuter()->GetMoveProbe()->MoveLimit( NAV_JUMP, vEnd, vStart, MASK_NPCSOLID, NULL, &moveTrace); - if (!IsMoveBlocked(moveTrace)) - return true; - } - } - - // -------------------------------------------------------------- - // Try to climb if we can climb to a node - // -------------------------------------------------------------- - if (moveTypes & bits_CAP_MOVE_CLIMB) - { - AIMoveTrace_t moveTrace; - GetOuter()->GetMoveProbe()->MoveLimit( NAV_CLIMB, vStart, vEnd, MASK_NPCSOLID, NULL, &moveTrace); - if (!IsMoveBlocked(moveTrace)) - { - return true; - } - } - - // Man do we suck! Couldn't get there by any route - return false; -} - -//----------------------------------------------------------------------------- - -#define MAX_NODE_TRIES 4 -#define MAX_TRIANGULATIONS 2 - -class CPathfindNearestNodeFilter : public INearestNodeFilter -{ -public: - CPathfindNearestNodeFilter( CAI_Pathfinder *pPathfinder, const Vector &vGoal, bool bToNode, int buildFlags, float goalTolerance ) - : m_pPathfinder( pPathfinder ), - m_nTries(0), - m_vGoal( vGoal ), - m_bToNode( bToNode ), - m_goalTolerance( goalTolerance ), - m_moveTypes( buildFlags & ( bits_BUILD_GROUND | bits_BUILD_FLY | bits_BUILD_JUMP | bits_BUILD_CLIMB ) ), - m_pRoute( NULL ) - { - COMPILE_TIME_ASSERT( (int)bits_BUILD_GROUND == (int)bits_CAP_MOVE_GROUND && (int)bits_BUILD_FLY == (int)bits_CAP_MOVE_FLY && (int)bits_BUILD_JUMP == (int)bits_CAP_MOVE_JUMP && (int)bits_BUILD_CLIMB == (int)bits_CAP_MOVE_CLIMB ); - } - - bool IsValid( CAI_Node *pNode ) - { - int nStaleLinks = 0; - if ( !m_pPathfinder->m_bIgnoreStaleLinks ) - { - int hull = m_pPathfinder->GetOuter()->GetHullType(); - for ( int i = 0; i < pNode->NumLinks(); i++ ) - { - CAI_Link *pLink = pNode->GetLinkByIndex( i ); - if ( pLink->m_LinkInfo & ( bits_LINK_STALE_SUGGESTED | bits_LINK_OFF ) ) - { - nStaleLinks++; - } - else if ( ( pLink->m_iAcceptedMoveTypes[hull] & m_moveTypes ) == 0 ) - { - nStaleLinks++; - } - } - } - - if ( nStaleLinks && nStaleLinks == pNode->NumLinks() ) - return false; - - int buildFlags = ( m_nTries < MAX_TRIANGULATIONS ) ? ( bits_BUILD_IGNORE_NPCS | bits_BUILD_TRIANG ) : bits_BUILD_IGNORE_NPCS; - - if ( m_bToNode ) - m_pRoute = m_pPathfinder->RouteToNode( m_vGoal, buildFlags, pNode->GetId(), m_goalTolerance ); - else - m_pRoute = m_pPathfinder->RouteFromNode( m_vGoal, buildFlags, pNode->GetId(), m_goalTolerance ); - - m_nTries++; - - return ( m_pRoute != NULL ); - } - - bool ShouldContinue() - { - return ( !m_pRoute && m_nTries < MAX_NODE_TRIES ); - } - - CAI_Pathfinder *m_pPathfinder; - int m_nTries; - Vector m_vGoal; - bool m_bToNode; - float m_goalTolerance; - int m_moveTypes; - - AI_Waypoint_t * m_pRoute; -}; - - -AI_Waypoint_t *CAI_Pathfinder::BuildNearestNodeRoute( const Vector &vGoal, bool bToNode, int buildFlags, float goalTolerance, int *pNearestNode ) -{ - AI_PROFILE_SCOPE( CAI_Pathfinder_BuildNearestNodeRoute ); - - CPathfindNearestNodeFilter filter( this, vGoal, bToNode, buildFlags, goalTolerance ); - *pNearestNode = GetNetwork()->NearestNodeToPoint( GetOuter(), vGoal, true, &filter ); - - return filter.m_pRoute; -} - -//----------------------------------------------------------------------------- -// Purpose: Attemps to build a node route between vStart and vEnd -// Input : -// Output : Returns a route if sucessful or NULL if no node route was possible -//----------------------------------------------------------------------------- - -AI_Waypoint_t *CAI_Pathfinder::BuildNodeRoute(const Vector &vStart, const Vector &vEnd, int buildFlags, float goalTolerance) -{ - AI_PROFILE_SCOPE( CAI_Pathfinder_BuildNodeRoute ); - - // ---------------------------------------------------------------------- - // Make sure network has nodes - // ---------------------------------------------------------------------- - if (GetNetwork()->NumNodes() == 0) - return NULL; - - // ---------------------------------------------------------------------- - // Find the nearest source node - // ---------------------------------------------------------------------- - int srcID; - AI_Waypoint_t *srcRoute = BuildNearestNodeRoute( vStart, true, buildFlags, goalTolerance, &srcID ); - if ( !srcRoute ) - { - DbgNavMsg1( GetOuter(), "Node pathfind failed, no route to source %d\n", srcID ); - return NULL; - } - - // ---------------------------------------------------------------------- - // Find the nearest destination node - // ---------------------------------------------------------------------- - int destID; - AI_Waypoint_t *destRoute = BuildNearestNodeRoute( vEnd, false, buildFlags, goalTolerance, &destID ); - if ( !destRoute ) - { - DeleteAll( srcRoute ); - DbgNavMsg1( GetOuter(), "Node pathfind failed, no route to dest %d\n", destID ); - return NULL; - } - - // ---------------------------------------------------------------------- - // If source and destination are the same, we can bypass finding a route - // ---------------------------------------------------------------------- - if (destID == srcID) - { - AddWaypointLists(srcRoute,destRoute); - DbgNavMsg( GetOuter(), "Node pathfind succeeded: dest == source\n"); - return srcRoute; - } - - // If nodes are not connected by network graph, no route is possible - if (!GetNetwork()->IsConnected(srcID, destID)) - return NULL; - - AI_Waypoint_t *path = FindBestPath(srcID, destID); - - if (!path) - { - DeleteAll(srcRoute); - DeleteAll(destRoute); - DbgNavMsg2( GetOuter(), "Node pathfind failed, no route between %d and %d\n", srcID, destID ); - return NULL; - } - - // Now put all the pieces together to form our route - AddWaypointLists(srcRoute,path); - AddWaypointLists(srcRoute,destRoute); - - DbgNavMsg( GetOuter(), "Node pathfind succeeded\n"); - return srcRoute; -} - -//----------------------------------------------------------------------------- -// Test the triangulation route... -//----------------------------------------------------------------------------- -#ifdef _WIN32 -#pragma warning (disable:4701) -#endif - -bool CAI_Pathfinder::TestTriangulationRoute( Navigation_t navType, const Vector& vecStart, - const Vector &vecApex, const Vector &vecEnd, const CBaseEntity *pTargetEnt, AIMoveTrace_t *pStartTrace ) -{ - AIMoveTrace_t endTrace; - endTrace.fStatus = AIMR_OK; // just to make the debug overlay code easy - - // Check the triangulation - CAI_MoveProbe *pMoveProbe = GetOuter()->GetMoveProbe(); - - bool bPathClear = false; - - // See if we can get from the start point to the triangle apex - if ( pMoveProbe->MoveLimit(navType, vecStart, vecApex, MASK_NPCSOLID, pTargetEnt, pStartTrace ) ) - { - // Ok, we got from the start to the triangle apex, now try - // the triangle apex to the end - if ( pMoveProbe->MoveLimit(navType, vecApex, vecEnd, MASK_NPCSOLID, pTargetEnt, &endTrace ) ) - { - bPathClear = true; - } - } - - // Debug mode: display the tested path... - if (GetOuter()->m_debugOverlays & OVERLAY_NPC_TRIANGULATE_BIT) - m_TriDebugOverlay.AddTriOverlayLines( vecStart, vecApex, vecEnd, *pStartTrace, endTrace, bPathClear); - - return bPathClear; -} - -#ifdef _WIN32 -#pragma warning (default:4701) -#endif - - -//----------------------------------------------------------------------------- -// Purpose: tries to overcome local obstacles by triangulating a path around them. -// Input : flDist is is how far the obstruction that we are trying -// to triangulate around is from the npc -// Output : -//----------------------------------------------------------------------------- - -// FIXME: this has no concept that the blocker may not be exactly along the vecStart, vecEnd vector. -// FIXME: it should take a position (and size?) to avoid -// FIXME: this does the position checks in the same order as GiveWay() so they tend to fight each other when both are active -#define MAX_TRIAGULATION_DIST (32*12) -bool CAI_Pathfinder::Triangulate( Navigation_t navType, const Vector &vecStart, const Vector &vecEndIn, - float flDistToBlocker, const CBaseEntity *pTargetEnt, Vector *pApex ) -{ - if ( GetOuter()->IsFlaggedEfficient() ) - return false; - - Assert( pApex ); - - AI_PROFILE_SCOPE( CAI_Pathfinder_Triangulate ); - - Vector vecForward, vecUp, vecPerpendicular; - VectorSubtract( vecEndIn, vecStart, vecForward ); - float flTotalDist = VectorNormalize( vecForward ); - - Vector vecEnd; - - // If we're walking, then don't try to triangulate over large distances - if ( navType != NAV_FLY && flTotalDist > MAX_TRIAGULATION_DIST) - { - vecEnd = vecForward * MAX_TRIAGULATION_DIST; - flTotalDist = MAX_TRIAGULATION_DIST; - if ( !GetOuter()->GetMoveProbe()->MoveLimit(navType, vecEnd, vecEndIn, MASK_NPCSOLID, pTargetEnt) ) - { - return false; - } - - } - else - vecEnd = vecEndIn; - - // Compute a direction vector perpendicular to the desired motion direction - if ( 1.0f - fabs(vecForward.z) > 1e-3 ) - { - vecUp.Init( 0, 0, 1 ); - CrossProduct( vecForward, vecUp, vecPerpendicular ); // Orthogonal to facing - } - else - { - vecUp.Init( 0, 1, 0 ); - vecPerpendicular.Init( 1, 0, 0 ); - } - - // Grab the size of the navigation bounding box - float sizeX = 0.5f * NAI_Hull::Length(GetHullType()); - float sizeZ = 0.5f * NAI_Hull::Height(GetHullType()); - - // start checking right about where the object is, picking two equidistant - // starting points, one on the left, one on the right. As we progress - // through the loop, we'll push these away from the obstacle, hoping to - // find a way around on either side. m_vecSize.x is added to the ApexDist - // in order to help select an apex point that insures that the NPC is - // sufficiently past the obstacle before trying to turn back onto its original course. - - if (GetOuter()->m_debugOverlays & OVERLAY_NPC_TRIANGULATE_BIT) - { - m_TriDebugOverlay.FadeTriOverlayLines(); - } - - float flApexDist = flDistToBlocker + sizeX; - if (flApexDist > flTotalDist) - { - flApexDist = flTotalDist; - } - - // Compute triangulation apex points (NAV_FLY attempts vertical triangulation too) - Vector vecDelta[2]; - Vector vecApex[4]; - float pApexDist[4]; - - Vector vecCenter; - int nNumToTest = 2; - VectorMultiply( vecPerpendicular, sizeX, vecDelta[0] ); - - VectorMA( vecStart, flApexDist, vecForward, vecCenter ); - VectorSubtract( vecCenter, vecDelta[0], vecApex[0] ); - VectorAdd( vecCenter, vecDelta[0], vecApex[1] ); - vecDelta[0] *= 2.0f; - pApexDist[0] = pApexDist[1] = flApexDist; - - if (navType == NAV_FLY) - { - VectorMultiply( vecUp, 3.0f * sizeZ, vecDelta[1] ); - VectorSubtract( vecCenter, vecDelta[1], vecApex[2] ); - VectorAdd( vecCenter, vecDelta[1], vecApex[3] ); - pApexDist[2] = pApexDist[3] = flApexDist; - nNumToTest = 4; - } - - AIMoveTrace_t moveTrace; - for (int i = 0; i < 2; ++i ) - { - // NOTE: Do reverse order so fliers try to move over the top first - for (int j = nNumToTest; --j >= 0; ) - { - if (TestTriangulationRoute(navType, vecStart, vecApex[j], vecEnd, pTargetEnt, &moveTrace)) - { - *pApex = vecApex[j]; - return true; - } - - // Here, the starting half of the triangle was blocked. Lets - // pull back the apex toward the start... - if (IsMoveBlocked(moveTrace)) - { - Vector vecStartToObstruction; - VectorSubtract( moveTrace.vEndPosition, vecStart, vecStartToObstruction ); - float flDistToObstruction = DotProduct( vecStartToObstruction, vecForward ); - - float flNewApexDist = pApexDist[j]; - if (pApexDist[j] > flDistToObstruction) - flNewApexDist = flDistToObstruction; - - VectorMA( vecApex[j], flNewApexDist - pApexDist[j], vecForward, vecApex[j] ); - pApexDist[j] = flNewApexDist; - } - - // NOTE: This has to occur *after* the code above because - // the above code uses vecApex for some distance computations - if (j & 0x1) - vecApex[j] += vecDelta[j >> 1]; - else - vecApex[j] -= vecDelta[j >> 1]; - } - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Triangulation debugging -//----------------------------------------------------------------------------- - -void CAI_Pathfinder::DrawDebugGeometryOverlays(int npcDebugOverlays) -{ - m_TriDebugOverlay.Draw(npcDebugOverlays); -} - -void CAI_Pathfinder::CTriDebugOverlay::Draw(int npcDebugOverlays) -{ - if (m_debugTriOverlayLine) - { - if ( npcDebugOverlays & OVERLAY_NPC_TRIANGULATE_BIT) - { - for (int i=0;idraw) - { - NDebugOverlay::Line(m_debugTriOverlayLine[i]->origin, - m_debugTriOverlayLine[i]->dest, - m_debugTriOverlayLine[i]->r, - m_debugTriOverlayLine[i]->g, - m_debugTriOverlayLine[i]->b, - m_debugTriOverlayLine[i]->noDepthTest, - 0); - } - } - } - else - { - ClearTriOverlayLines(); - } - } -} - -void CAI_Pathfinder::CTriDebugOverlay::AddTriOverlayLines( const Vector &vecStart, const Vector &vecApex, const Vector &vecEnd, const AIMoveTrace_t &startTrace, const AIMoveTrace_t &endTrace, bool bPathClear ) -{ - static unsigned char s_TriangulationColor[2][3] = - { - { 255, 0, 0 }, - { 0, 255, 0 } - }; - - unsigned char *c = s_TriangulationColor[bPathClear]; - - AddTriOverlayLine(vecStart, vecApex, c[0],c[1],c[2], false); - AddTriOverlayLine(vecApex, vecEnd, c[0],c[1],c[2], false); - - // If we've blocked, draw an X where we were blocked... - if (IsMoveBlocked(startTrace.fStatus)) - { - Vector pt1, pt2; - pt1 = pt2 = startTrace.vEndPosition; - - pt1.x -= 10; pt1.y -= 10; - pt2.x += 10; pt2.y += 10; - AddTriOverlayLine(pt1, pt2, c[0],c[1],c[2], false); - - pt1.x += 20; - pt2.x -= 20; - AddTriOverlayLine(pt1, pt2, c[0],c[1],c[2], false); - } - - if (IsMoveBlocked(endTrace.fStatus)) - { - Vector pt1, pt2; - pt1 = pt2 = endTrace.vEndPosition; - - pt1.x -= 10; pt1.y -= 10; - pt2.x += 10; pt2.y += 10; - AddTriOverlayLine(pt1, pt2, c[0],c[1],c[2], false); - - pt1.x += 20; - pt2.x -= 20; - AddTriOverlayLine(pt1, pt2, c[0],c[1],c[2], false); - } -} - -void CAI_Pathfinder::CTriDebugOverlay::ClearTriOverlayLines(void) -{ - if (m_debugTriOverlayLine) - { - for (int i=0;idraw = false; - } - } -} -void CAI_Pathfinder::CTriDebugOverlay::FadeTriOverlayLines(void) -{ - if (m_debugTriOverlayLine) - { - for (int i=0;ir = static_cast(m_debugTriOverlayLine[i]->r * 0.5); - m_debugTriOverlayLine[i]->g = static_cast(m_debugTriOverlayLine[i]->g * 0.5); - m_debugTriOverlayLine[i]->b = static_cast(m_debugTriOverlayLine[i]->b * 0.5); - } - } -} -void CAI_Pathfinder::CTriDebugOverlay::AddTriOverlayLine(const Vector &origin, const Vector &dest, int r, int g, int b, bool noDepthTest) -{ - if (!m_debugTriOverlayLine) - { - m_debugTriOverlayLine = new OverlayLine_t*[NUM_NPC_DEBUG_OVERLAYS]; - for (int i=0;i= NUM_NPC_DEBUG_OVERLAYS) - { - overCounter = 0; - } - - m_debugTriOverlayLine[overCounter]->origin = origin; - m_debugTriOverlayLine[overCounter]->dest = dest; - m_debugTriOverlayLine[overCounter]->r = r; - m_debugTriOverlayLine[overCounter]->g = g; - m_debugTriOverlayLine[overCounter]->b = b; - m_debugTriOverlayLine[overCounter]->noDepthTest = noDepthTest; - m_debugTriOverlayLine[overCounter]->draw = true; - overCounter++; - -} - -//----------------------------------------------------------------------------- diff --git a/game/server/ai_pathfinder.h b/game/server/ai_pathfinder.h deleted file mode 100644 index c557a3979..000000000 --- a/game/server/ai_pathfinder.h +++ /dev/null @@ -1,204 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_PATHFINDER_H -#define AI_PATHFINDER_H - -#include "ai_component.h" -#include "ai_navtype.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -struct AIMoveTrace_t; -struct OverlayLine_t; -struct AI_Waypoint_t; -class CAI_Link; -class CAI_Network; -class CAI_Node; - - -//----------------------------------------------------------------------------- -// The type of route to build -enum RouteBuildFlags_e -{ - bits_BUILD_GROUND = 0x00000001, // - bits_BUILD_JUMP = 0x00000002, // - bits_BUILD_FLY = 0x00000004, // - bits_BUILD_CLIMB = 0x00000008, // - bits_BUILD_GIVEWAY = 0x00000010, // - bits_BUILD_TRIANG = 0x00000020, // - bits_BUILD_IGNORE_NPCS = 0x00000040, // Ignore collisions with NPCs - bits_BUILD_COLLIDE_NPCS = 0x00000080, // Use collisions with NPCs (redundant for argument clarity) - bits_BUILD_GET_CLOSE = 0x00000100, // the route will be built even if it can't reach the destination -}; - -//----------------------------------------------------------------------------- -// CAI_Pathfinder -// -// Purpose: Executes pathfinds through an associated network. -// -//----------------------------------------------------------------------------- - -class CAI_Pathfinder : public CAI_Component -{ -public: - CAI_Pathfinder( CAI_BaseNPC *pOuter ) - : CAI_Component(pOuter), - m_flLastStaleLinkCheckTime( 0 ), - m_pNetwork( NULL ) - { - } - - void Init( CAI_Network *pNetwork ); - - //--------------------------------- - - int NearestNodeToNPC(); - int NearestNodeToPoint( const Vector &vecOrigin ); - - AI_Waypoint_t* FindBestPath (int startID, int endID); - AI_Waypoint_t* FindShortRandomPath (int startID, float minPathLength, const Vector &vDirection = vec3_origin); - - // -------------------------------- - - bool IsLinkUsable(CAI_Link *pLink, int startID); - - // -------------------------------- - - AI_Waypoint_t *BuildRoute( const Vector &vStart, const Vector &vEnd, CBaseEntity *pTarget, float goalTolerance, Navigation_t curNavType = NAV_NONE, bool bLocalSucceedOnWithinTolerance = false ); - void UnlockRouteNodes( AI_Waypoint_t * ); - - // -------------------------------- - - void SetIgnoreBadLinks() { m_bIgnoreStaleLinks = true; } // lasts only for the next pathfind - - // -------------------------------- - - virtual AI_Waypoint_t *BuildNodeRoute( const Vector &vStart, const Vector &vEnd, int buildFlags, float goalTolerance ); - virtual AI_Waypoint_t *BuildLocalRoute( const Vector &vStart, const Vector &vEnd, CBaseEntity const *pTarget, int endFlags, int nodeID, int buildFlags, float goalTolerance); - virtual AI_Waypoint_t *BuildRadialRoute( const Vector &vStartPos, const Vector &vCenterPos, const Vector &vGoalPos, float flRadius, float flArc, float flStepDist, bool bClockwise, float goalTolerance, bool bAirRoute ); - - virtual AI_Waypoint_t *BuildTriangulationRoute( const Vector &vStart, - const Vector &vEnd, CBaseEntity const *pTarget, int endFlags, int nodeID, - float flYaw, float flDistToBlocker, Navigation_t navType); - - virtual AI_Waypoint_t *BuildOBBAvoidanceRoute( const Vector &vStart, const Vector &vEnd, - const CBaseEntity *pObstruction, const CBaseEntity *pTarget, - Navigation_t navType ); - - // -------------------------------- - - bool Triangulate( Navigation_t navType, const Vector &vecStart, const Vector &vecEnd, - float flDistToBlocker, CBaseEntity const *pTargetEnt, Vector *pApex ); - - // -------------------------------- - - void DrawDebugGeometryOverlays( int m_debugOverlays ); - -protected: - virtual bool CanUseLocalNavigation() { return true; } - -private: - friend class CPathfindNearestNodeFilter; - - //--------------------------------- - - AI_Waypoint_t* RouteToNode(const Vector &vecOrigin, int buildFlags, int nodeID, float goalTolerance); - AI_Waypoint_t* RouteFromNode(const Vector &vecOrigin, int buildFlags, int nodeID, float goalTolerance); - - AI_Waypoint_t * BuildNearestNodeRoute( const Vector &vGoal, bool bToNode, int buildFlags, float goalTolerance, int *pNearestNode ); - - //--------------------------------- - - AI_Waypoint_t* MakeRouteFromParents(int *parentArray, int endID); - AI_Waypoint_t* CreateNodeWaypoint( Hull_t hullType, int nodeID, int nodeFlags = 0 ); - - AI_Waypoint_t* BuildRouteThroughPoints( Vector *vecPoints, int nNumPoints, int nDirection, int nStartIndex, int nEndIndex, Navigation_t navType, CBaseEntity *pTarget ); - - bool IsLinkStillStale(int moveType, CAI_Link *nodeLink); - - // -------------------------------- - - // Builds a simple route (no triangulation, no making way) - AI_Waypoint_t *BuildSimpleRoute( Navigation_t navType, const Vector &vStart, const Vector &vEnd, - const CBaseEntity *pTarget, int endFlags, int nodeID, int nodeTargetType, float flYaw); - - // Builds a complex route (triangulation, making way) - AI_Waypoint_t *BuildComplexRoute( Navigation_t navType, const Vector &vStart, - const Vector &vEnd, const CBaseEntity *pTarget, int endFlags, int nodeID, - int buildFlags, float flYaw, float goalTolerance, float maxLocalNavDistance ); - - AI_Waypoint_t *BuildGroundRoute( const Vector &vStart, const Vector &vEnd, CBaseEntity const *pTarget, int endFlags, int nodeID, int buildFlags, float flYaw, float goalTolerance ); - AI_Waypoint_t *BuildFlyRoute( const Vector &vStart, const Vector &vEnd, CBaseEntity const *pTarget, int endFlags, int nodeID, int buildFlags, float flYaw, float goalTolerance ); - AI_Waypoint_t *BuildJumpRoute( const Vector &vStart, const Vector &vEnd, CBaseEntity const *pTarget, int endFlags, int nodeID, int buildFlags, float flYaw ); - AI_Waypoint_t *BuildClimbRoute( const Vector &vStart, const Vector &vEnd, CBaseEntity const *pTarget, int endFlags, int nodeID, int buildFlags, float flYaw ); - - // Computes the link type - Navigation_t ComputeWaypointType( CAI_Node **ppNodes, int parentID, int destID ); - - // -------------------------------- - - bool TestTriangulationRoute( Navigation_t navType, const Vector& vecStart, - const Vector &vecApex, const Vector &vecEnd, const CBaseEntity *pTargetEnt, AIMoveTrace_t *pStartTrace ); - - // -------------------------------- - - bool CheckStaleRoute( const Vector &vStart, const Vector &vEnd, int moveTypes); - bool CheckStaleNavTypeRoute( Navigation_t navType, const Vector &vStart, const Vector &vEnd ); - - // -------------------------------- - - bool CanGiveWay( const Vector& vStart, const Vector& vEnd, CBaseEntity *pNPCBlocker ); - - // -------------------------------- - - bool UseStrongOptimizations(); - - // -------------------------------- - // Debugging fields and functions - - class CTriDebugOverlay - { - public: - CTriDebugOverlay() - : m_debugTriOverlayLine( NULL ) - { - } - void AddTriOverlayLines( const Vector &vecStart, const Vector &vecApex, const Vector &vecEnd, const AIMoveTrace_t &startTrace, const AIMoveTrace_t &endTrace, bool bPathClear ); - void ClearTriOverlayLines(void); - void FadeTriOverlayLines(void); - - void Draw(int npcDebugOverlays); - private: - void AddTriOverlayLine(const Vector &origin, const Vector &dest, int r, int g, int b, bool noDepthTest); - - OverlayLine_t **m_debugTriOverlayLine; - }; - - CTriDebugOverlay m_TriDebugOverlay; - - //--------------------------------- - - float m_flLastStaleLinkCheckTime; // Last time I check for a stale link - bool m_bIgnoreStaleLinks; - - //--------------------------------- - - CAI_Network *GetNetwork() { return m_pNetwork; } - const CAI_Network *GetNetwork() const { return m_pNetwork; } - - CAI_Network *m_pNetwork; - -public: - DECLARE_SIMPLE_DATADESC(); -}; - -//----------------------------------------------------------------------------- - -#endif // AI_PATHFINDER_H diff --git a/game/server/ai_planesolver.cpp b/game/server/ai_planesolver.cpp deleted file mode 100644 index 8e218db44..000000000 --- a/game/server/ai_planesolver.cpp +++ /dev/null @@ -1,904 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -#include // for FLT_MAX - -#include "ai_planesolver.h" -#include "ai_moveprobe.h" -#include "ai_motor.h" -#include "ai_basenpc.h" -#include "ai_route.h" -#include "ndebugoverlay.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- - -const float PLANE_SOLVER_THINK_FREQUENCY[2] = { 0.0f, 0.2f }; -const float MAX_PROBE_DIST[2] = { (10.0f*12.0f), (8.0f*12.0f) }; - -//#define PROFILE_PLANESOLVER 1 - -#ifdef PROFILE_PLANESOLVER -#define PLANESOLVER_PROFILE_SCOPE( tag ) AI_PROFILE_SCOPE( tag ) -#else -#define PLANESOLVER_PROFILE_SCOPE( tag ) ((void)0) -#endif - -#define ProbeForNpcs() 0 - -//#define TESTING_SUGGESTIONS - -//----------------------------------------------------------------------------- - -inline float sq( float f ) -{ - return ( f * f ); -} - -inline float cube( float f ) -{ - return ( f * f * f ); -} - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- - -CAI_PlaneSolver::CAI_PlaneSolver( CAI_BaseNPC *pNpc ) - : m_pNpc( pNpc ), - m_PrevTarget( FLT_MAX, FLT_MAX, FLT_MAX ), - m_fSolvedPrev( false ), - m_PrevSolution( 0 ), - m_ClosestHaveBeenToCurrent( FLT_MAX ), - m_TimeLastProgress( FLT_MAX ), - m_fCannotSolveCurrent( false ), - m_RefreshSamplesTimer( PLANE_SOLVER_THINK_FREQUENCY[AIStrongOpt()] - 0.05 ) -{ -} - - -//----------------------------------------------------------------------------- -// Convenience accessors -//----------------------------------------------------------------------------- -inline CAI_BaseNPC *CAI_PlaneSolver::GetNpc() -{ - return m_pNpc; -} - -inline CAI_Motor *CAI_PlaneSolver::GetMotor() -{ - return m_pNpc->GetMotor(); -} - -inline const Vector &CAI_PlaneSolver::GetLocalOrigin() -{ - return m_pNpc->GetLocalOrigin(); -} - -//----------------------------------------------------------------------------- -// class CAI_PlaneSolver -//----------------------------------------------------------------------------- - -bool CAI_PlaneSolver::MoveLimit( Navigation_t navType, const Vector &target, bool ignoreTransients, bool fCheckStep, int contents, AIMoveTrace_t *pMoveTrace ) -{ - AI_PROFILE_SCOPE( CAI_PlaneSolver_MoveLimit ); - - int flags = ( navType == NAV_GROUND ) ? AIMLF_2D : AIMLF_DEFAULT; - - if ( ignoreTransients ) - { - Assert( !ProbeForNpcs() ); - flags |= AIMLF_IGNORE_TRANSIENTS; - } - - CAI_MoveProbe *pProbe = m_pNpc->GetMoveProbe(); - return pProbe->MoveLimit( navType, GetLocalOrigin(), target, contents, - m_pNpc->GetNavTargetEntity(), (fCheckStep) ? 100 : 0, - flags, - pMoveTrace ); -} - -bool CAI_PlaneSolver::MoveLimit( Navigation_t navType, const Vector &target, bool ignoreTransients, bool fCheckStep, AIMoveTrace_t *pMoveTrace ) -{ - return MoveLimit( navType, target, ignoreTransients, fCheckStep, MASK_NPCSOLID, pMoveTrace ); -} - -//----------------------------------------------------------------------------- - -bool CAI_PlaneSolver::DetectUnsolvable( const AILocalMoveGoal_t &goal ) -{ -#ifndef TESTING_SUGGESTIONS - float curDistance = ( goal.target.AsVector2D() - GetLocalOrigin().AsVector2D() ).Length(); - if ( m_PrevTarget != goal.target ) - { - m_TimeLastProgress = gpGlobals->curtime; - m_ClosestHaveBeenToCurrent = curDistance; - m_fCannotSolveCurrent = false; - } - else - { - if ( m_fCannotSolveCurrent ) - { - return true; - } - - if ( m_ClosestHaveBeenToCurrent - curDistance > 0 ) - { - m_TimeLastProgress = gpGlobals->curtime; - m_ClosestHaveBeenToCurrent = curDistance; - } - else - { - if ( gpGlobals->curtime - m_TimeLastProgress > 0.75 ) - { - m_fCannotSolveCurrent = true; - return true; - } - } - } -#endif - return false; -} - -//----------------------------------------------------------------------------- - -float CAI_PlaneSolver::AdjustRegulationWeight( CBaseEntity *pEntity, float weight ) -{ - if ( pEntity->MyNPCPointer() != NULL ) - { - // @TODO (toml 10-03-02): How to do this with non-NPC entities. Should be using intended solve velocity... - Vector2D velOwner = GetNpc()->GetMotor()->GetCurVel().AsVector2D(); - Vector2D velBlocker = ((CAI_BaseNPC *)pEntity)->GetMotor()->GetCurVel().AsVector2D(); - - Vector2D velOwnerNorm = velOwner; - Vector2D velBlockerNorm = velBlocker; - - float speedOwner = Vector2DNormalize( velOwnerNorm ); - float speedBlocker = Vector2DNormalize( velBlockerNorm ); - - float dot = velOwnerNorm.Dot( velBlockerNorm ); - - if ( speedBlocker > 0 ) - { - if ( dot > 0 && speedBlocker >= speedOwner * 0.9 ) - { - if ( dot > 0.86 ) - { - // @Note (toml 10-10-02): Even in the case of no obstacle, we generate - // a suggestion in because we still want to continue sweeping the - // search - weight = 0; - } - else if ( dot > 0.7 ) - { - weight *= sq( weight ); - } - else - weight *= weight; - } - } - } - - return weight; -} - -//----------------------------------------------------------------------------- - -float CAI_PlaneSolver::CalculateRegulationWeight( const AIMoveTrace_t &moveTrace, float pctBlocked ) -{ - float weight = 0; - - if ( pctBlocked > 0.9) - weight = 1; - else if ( pctBlocked < 0.1) - weight = 0; - else - { - weight = sq( ( pctBlocked - 0.1 ) / 0.8 ); - weight = AdjustRegulationWeight( moveTrace.pObstruction, weight ); - } - - return weight; -} - -//----------------------------------------------------------------------------- - -void CAI_PlaneSolver::GenerateSuggestionFromTrace( const AILocalMoveGoal_t &goal, - const AIMoveTrace_t &moveTrace, float probeDist, - float arcCenter, float arcSpan, int probeOffset ) -{ - AI_MoveSuggestion_t suggestion; - AI_MoveSuggType_t type; - - switch ( moveTrace.fStatus ) - { - case AIMR_BLOCKED_ENTITY: type = AIMST_AVOID_OBJECT; break; - case AIMR_BLOCKED_WORLD: type = AIMST_AVOID_WORLD; break; - case AIMR_BLOCKED_NPC: type = AIMST_AVOID_NPC; break; - case AIMR_ILLEGAL: type = AIMST_AVOID_DANGER; break; - default: type = AIMST_NO_KNOWLEDGE; AssertMsg( 0, "Unexpected mode status" ); break; - } - - if ( goal.pMoveTarget != NULL && goal.pMoveTarget == moveTrace.pObstruction ) - { - suggestion.Set( type, 0, - arcCenter, arcSpan, - moveTrace.pObstruction ); - - m_Solver.AddRegulation( suggestion ); - - return; - } - - float clearDist = probeDist - moveTrace.flDistObstructed; - float pctBlocked = 1.0 - ( clearDist / probeDist ); - - float weight = CalculateRegulationWeight( moveTrace, pctBlocked ); - - if ( weight < 0.001 ) - return; - - if ( pctBlocked < 0.5 ) - { - arcSpan *= pctBlocked * 2.0; - } - - Vector vecToEnd = moveTrace.vEndPosition - GetLocalOrigin(); - Vector crossProduct; - bool favorLeft = false, favorRight = false; - - if ( moveTrace.fStatus == AIMR_BLOCKED_NPC ) - { - Vector vecToOther = moveTrace.pObstruction->GetLocalOrigin() - GetLocalOrigin(); - - CrossProduct(vecToEnd, vecToOther, crossProduct); - - favorLeft = ( crossProduct.z < 0 ); - favorRight = ( crossProduct.z > 0 ); - } - else if ( moveTrace.vHitNormal != vec3_origin ) - { - CrossProduct(vecToEnd, moveTrace.vHitNormal, crossProduct); - favorLeft = ( crossProduct.z > 0 ); - favorRight = ( crossProduct.z < 0 ); - } - - float thirdSpan = arcSpan / 3.0; - float favoredWeight = weight * pctBlocked; - - suggestion.Set( type, weight, - arcCenter, thirdSpan, - moveTrace.pObstruction ); - - m_Solver.AddRegulation( suggestion ); - - suggestion.Set( type, ( favorRight ) ? favoredWeight : weight, - arcCenter - thirdSpan, thirdSpan, - moveTrace.pObstruction ); - - m_Solver.AddRegulation( suggestion ); - - suggestion.Set( type, ( favorLeft ) ? favoredWeight : weight, - arcCenter + thirdSpan, thirdSpan, - moveTrace.pObstruction ); - - m_Solver.AddRegulation( suggestion ); -} - -//----------------------------------------------------------------------------- - -void CAI_PlaneSolver::CalcYawsFromOffset( float yawScanCenter, float spanPerProbe, int probeOffset, - float *pYawTest, float *pYawCenter ) -{ - if ( probeOffset != 0 ) - { - float sign = ( probeOffset > 0 ) ? 1 : -1; - - *pYawCenter = yawScanCenter + probeOffset * spanPerProbe; - if ( *pYawCenter < 0 ) - *pYawCenter += 360; - else if ( *pYawCenter >= 360 ) - *pYawCenter -= 360; - - *pYawTest = *pYawCenter - ( sign * spanPerProbe * 0.5 ); - if ( *pYawTest < 0 ) - *pYawTest += 360; - else if ( *pYawTest >= 360 ) - *pYawTest -= 360; - } - else - { - *pYawCenter = *pYawTest = yawScanCenter; - } -} - -//----------------------------------------------------------------------------- - -void CAI_PlaneSolver::GenerateObstacleNpcs( const AILocalMoveGoal_t &goal, float probeDist ) -{ - if ( !ProbeForNpcs() ) - { - CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); - Vector minsSelf, maxsSelf; - m_pNpc->CollisionProp()->WorldSpaceSurroundingBounds( &minsSelf, &maxsSelf ); - float radiusSelf = (minsSelf.AsVector2D() - maxsSelf.AsVector2D()).Length() * 0.5; - - for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - CAI_BaseNPC *pAI = ppAIs[i]; - if ( pAI != m_pNpc && pAI->IsAlive() && ( !goal.pPath || pAI != goal.pPath->GetTarget() ) ) - { - Vector mins, maxs; - - pAI->CollisionProp()->WorldSpaceSurroundingBounds( &mins, &maxs ); - if ( mins.z < maxsSelf.z + 12.0 && maxs.z > minsSelf.z - 12.0 ) - { - float radius = (mins.AsVector2D() - maxs.AsVector2D()).Length() * 0.5; - float distance = ( pAI->GetAbsOrigin().AsVector2D() - m_pNpc->GetAbsOrigin().AsVector2D() ).Length(); - if ( distance - radius < radiusSelf + probeDist ) - { - AddObstacle( pAI->WorldSpaceCenter(), radius, pAI, AIMST_AVOID_NPC ); - } - } - } - } - - CBaseEntity *pPlayer = UTIL_PlayerByIndex( 1 ); - if ( pPlayer ) - { - Vector mins, maxs; - - pPlayer->CollisionProp()->WorldSpaceSurroundingBounds( &mins, &maxs ); - if ( mins.z < maxsSelf.z + 12.0 && maxs.z > minsSelf.z - 12.0 ) - { - float radius = (mins.AsVector2D() - maxs.AsVector2D()).Length(); - float distance = ( pPlayer->GetAbsOrigin().AsVector2D() - m_pNpc->GetAbsOrigin().AsVector2D() ).Length(); - if ( distance - radius < radiusSelf + probeDist ) - { - AddObstacle( pPlayer->WorldSpaceCenter(), radius, pPlayer, AIMST_AVOID_NPC ); - } - } - } - - } -} - -//----------------------------------------------------------------------------- - -AI_SuggestorResult_t CAI_PlaneSolver::GenerateObstacleSuggestion( const AILocalMoveGoal_t &goal, float yawScanCenter, - float probeDist, float spanPerProbe, int probeOffset) -{ - AIMoveTrace_t moveTrace; - float yawTest; - float arcCenter; - - CalcYawsFromOffset( yawScanCenter, spanPerProbe, probeOffset, &yawTest, &arcCenter ); - - Vector probeDir = UTIL_YawToVector( yawTest ); - float requiredMovement = goal.speed * GetMotor()->GetMoveInterval(); - - // Probe immediate move with footing, then look further out ignoring footing - bool fTraceClear = true; - if ( probeDist > requiredMovement ) - { - if ( !MoveLimit( goal.navType, GetLocalOrigin() + probeDir * requiredMovement, !ProbeForNpcs(), true, &moveTrace ) ) - { - fTraceClear = false; - moveTrace.flDistObstructed = (probeDist - requiredMovement) + moveTrace.flDistObstructed; - } - } - - if ( fTraceClear ) - { - fTraceClear = MoveLimit( goal.navType, GetLocalOrigin() + probeDir * probeDist, !ProbeForNpcs(), false, &moveTrace ); - } - - - if ( !fTraceClear ) - { - GenerateSuggestionFromTrace( goal, moveTrace, probeDist, arcCenter, spanPerProbe, probeOffset ); - return SR_OK; - } - - return SR_NONE; -} - -//----------------------------------------------------------------------------- - -AI_SuggestorResult_t CAI_PlaneSolver::GenerateObstacleSuggestions( const AILocalMoveGoal_t &goal, const AIMoveTrace_t &directTrace, - float distClear, float probeDist, float degreesToProbe, int nProbes ) -{ - Assert( nProbes % 2 == 1 ); - - PLANESOLVER_PROFILE_SCOPE( CAI_PlaneSolver_GenerateObstacleSuggestions ); - - AI_SuggestorResult_t seekResult = SR_NONE; - bool fNewTarget = ( !m_fSolvedPrev || m_PrevTarget != goal.target ); - - if ( fNewTarget ) - m_RefreshSamplesTimer.Force(); - - if ( PLANE_SOLVER_THINK_FREQUENCY[AIStrongOpt()] == 0.0 || m_RefreshSamplesTimer.Expired() ) - { - m_Solver.ClearRegulations(); - - if ( !ProbeForNpcs() ) - GenerateObstacleNpcs( goal, probeDist ); - - if ( GenerateCircleObstacleSuggestions( goal, probeDist ) ) - seekResult = SR_OK; - - float spanPerProbe = degreesToProbe / nProbes; - int nSideProbes = (nProbes - 1) / 2; - float yawGoalDir = UTIL_VecToYaw( goal.dir ); - - Vector probeTarget; - AIMoveTrace_t moveTrace; - int i; - - // Generate suggestion from direct trace, or probe if direct trace doesn't match - if ( fabs( probeDist - ( distClear + directTrace.flDistObstructed ) ) < 0.1 && - ( ProbeForNpcs() || directTrace.fStatus != AIMR_BLOCKED_NPC ) ) - { - if ( directTrace.fStatus != AIMR_OK ) - { - seekResult = SR_OK; - GenerateSuggestionFromTrace( goal, directTrace, probeDist, yawGoalDir, spanPerProbe, 0 ); - } - } - else if ( GenerateObstacleSuggestion( goal, yawGoalDir, probeDist, spanPerProbe, 0 ) == SR_OK ) - { - seekResult = SR_OK; - } - - // Scan left. Note that in the left and right scan, the algorithm stops as soon - // as there is a clear path. This is an optimization in anticipation of the - // behavior of the underlying solver. This will break more often the higher - // PLANE_SOLVER_THINK_FREQUENCY becomes - bool foundClear = false; - - for ( i = 1; i <= nSideProbes; i++ ) - { - if ( !foundClear ) - { - AI_SuggestorResult_t curSeekResult = GenerateObstacleSuggestion( goal, yawGoalDir, probeDist, - spanPerProbe, i ); - if ( curSeekResult == SR_OK ) - { - seekResult = SR_OK; - } - else - foundClear = true; - } - else - { - float ignored; - float arcCenter; - CalcYawsFromOffset( yawGoalDir, spanPerProbe, i, &ignored, &arcCenter ); - m_Solver.AddRegulation( AI_MoveSuggestion_t( AIMST_NO_KNOWLEDGE, 1, arcCenter, spanPerProbe ) ); - } - } - - // Scan right - foundClear = false; - - for ( i = -1; i >= -nSideProbes; i-- ) - { - if ( !foundClear ) - { - AI_SuggestorResult_t curSeekResult = GenerateObstacleSuggestion( goal, yawGoalDir, probeDist, - spanPerProbe, i ); - if ( curSeekResult == SR_OK ) - { - seekResult = SR_OK; - } - else - foundClear = true; - } - else - { - float ignored; - float arcCenter; - CalcYawsFromOffset( yawGoalDir, spanPerProbe, i, &ignored, &arcCenter ); - m_Solver.AddRegulation( AI_MoveSuggestion_t( AIMST_NO_KNOWLEDGE, 1, arcCenter, spanPerProbe ) ); - } - } - - if ( seekResult == SR_OK ) - { - float arcCenter = yawGoalDir - 180; - if ( arcCenter < 0 ) - arcCenter += 360; - - // Since these are not sampled every think, place a negative arc in all directions not sampled - m_Solver.AddRegulation( AI_MoveSuggestion_t( AIMST_NO_KNOWLEDGE, 1, arcCenter, 360 - degreesToProbe ) ); - - } - - m_RefreshSamplesTimer.Reset( PLANE_SOLVER_THINK_FREQUENCY[AIStrongOpt()] ); - } - else if ( m_Solver.HaveRegulations() ) - seekResult = SR_OK; - - return seekResult; -} - -//----------------------------------------------------------------------------- -// Visualizes the regulations for debugging purposes -//----------------------------------------------------------------------------- -void CAI_PlaneSolver::VisualizeRegulations() -{ - // Visualization of regulations - if ((GetNpc()->m_debugOverlays & OVERLAY_NPC_STEERING_REGULATIONS) != 0) - { - m_Solver.VisualizeRegulations( GetNpc()->WorldSpaceCenter() ); - } -} - -void CAI_PlaneSolver::VisualizeSolution( const Vector &vecGoal, const Vector& vecActual ) -{ - if ((GetNpc()->m_debugOverlays & OVERLAY_NPC_STEERING_REGULATIONS) != 0) - { - // Compute centroid... - Vector centroid = GetNpc()->WorldSpaceCenter(); - Vector goalPt, actualPt; - - VectorMA( centroid, 20, vecGoal, goalPt ); - VectorMA( centroid, 20, vecActual, actualPt ); - - NDebugOverlay::Line(centroid, goalPt, 255, 255, 255, true, 0.1f ); - NDebugOverlay::Line(centroid, actualPt, 255, 255, 0, true, 0.1f ); - } -} - -//----------------------------------------------------------------------------- -// Adjust the solution for fliers -//----------------------------------------------------------------------------- -#define MIN_ZDIR_TO_RADIUS 0.1f - -void CAI_PlaneSolver::AdjustSolutionForFliers( const AILocalMoveGoal_t &goal, float flSolutionYaw, Vector *pSolution ) -{ - // Fliers should move up if there are local obstructions... - // A hacky solution, but the bigger the angle of deflection, the more likely - // we're close to a problem and the higher we should go up. - Assert( pSolution->z == 0.0f ); - - // If we're largely needing to move down, then blow off the upward motion... - Vector vecDelta, vecDir; - VectorSubtract( goal.target, GetLocalOrigin(), vecDelta ); - vecDir = vecDelta; - VectorNormalize( vecDir ); - float flRadius = sqrt( vecDir.x * vecDir.x + vecDir.y * vecDir.y ); - *pSolution *= flRadius; - pSolution->z = vecDir.z; - AssertFloatEquals( pSolution->LengthSqr(), 1.0f, 1e-3 ); - - // Move up 0 when we have to move forward as much as we have to move down z (45 degree angle) - // Move up max when we have to move forward 5x as much as we have to move down z, - // or if we have to move up z. - float flUpAmount = 0.0f; - if ( vecDir.z >= -flRadius * MIN_ZDIR_TO_RADIUS) - { - flUpAmount = 1.0f; - } - else if ((vecDir.z <= -flRadius) || (fabs(vecDir.z) < 1e-3)) - { - flUpAmount = 0.0f; - } - else - { - flUpAmount = (-flRadius / vecDir.z) - 1.0f; - flUpAmount *= MIN_ZDIR_TO_RADIUS; - Assert( (flUpAmount >= 0.0f) && (flUpAmount <= 1.0f) ); - } - - // Check the deflection amount... - pSolution->z += flUpAmount * 5.0f; - - // FIXME: Also, if we've got a bunch of regulations, we may - // also wish to raise up a little bit..because this indicates - // that we've got a bunch of stuff to avoid - VectorNormalize( *pSolution ); -} - -//----------------------------------------------------------------------------- - -unsigned CAI_PlaneSolver::ComputeTurnBiasFlags( const AILocalMoveGoal_t &goal, const AIMoveTrace_t &directTrace ) -{ - if ( directTrace.fStatus == AIMR_BLOCKED_WORLD ) - { - // @TODO (toml 11-11-02): stuff plane normal of hit into trace Use here to compute a bias? - // - return 0; - } - - if ( directTrace.fStatus == AIMR_BLOCKED_NPC ) - { - return AIMS_FAVOR_LEFT; - } - - return 0; -} - -//----------------------------------------------------------------------------- - -bool CAI_PlaneSolver::RunMoveSolver( const AILocalMoveGoal_t &goal, const AIMoveTrace_t &directTrace, float degreesPositiveArc, - bool fDeterOscillation, Vector *pResult ) -{ - PLANESOLVER_PROFILE_SCOPE( CAI_PlaneSolver_RunMoveSolver ); - - AI_MoveSolution_t solution; - - if ( m_Solver.HaveRegulations() ) - { - // @TODO (toml 07-19-02): add a movement threshhold here (the target may be the same, - // but the ai is nowhere near where the last solution was derived) - bool fNewTarget = ( !m_fSolvedPrev || m_PrevTarget != goal.target ); - - // For debugging, visualize our regulations - VisualizeRegulations(); - - AI_MoveSuggestion_t moveSuggestions[2]; - int nSuggestions = 1; - - moveSuggestions[0].Set( AIMST_MOVE, 1, UTIL_VecToYaw( goal.dir ), degreesPositiveArc ); - moveSuggestions[0].flags |= ComputeTurnBiasFlags( goal, directTrace ); - - if ( fDeterOscillation && !fNewTarget ) - { -#ifndef TESTING_SUGGESTIONS - moveSuggestions[nSuggestions++].Set( AIMST_OSCILLATION_DETERRANCE, 1, m_PrevSolution - 180, 180 ); -#endif - } - - if ( m_Solver.Solve( moveSuggestions, nSuggestions, &solution ) ) - { - *pResult = UTIL_YawToVector( solution.dir ); - - if (goal.navType == NAV_FLY) - { - // FIXME: Does the z component have to occur during the goal - // setting because it's there & only there where MoveLimit - // will report contact with the world if we move up? - AdjustSolutionForFliers( goal, solution.dir, pResult ); - } - // A crude attempt at oscillation detection: if we solved last time, and this time, and the same target is - // involved, and we resulted in nearly a 180, we are probably oscillating -#ifndef TESTING_SUGGESTIONS - if ( !fNewTarget ) - { - float delta = solution.dir - m_PrevSolution; - if ( delta < 0 ) - delta += 360; - if ( delta > 165 && delta < 195 ) - return false; - } -#endif - m_PrevSolution = solution.dir; - m_PrevSolutionVector = *pResult; - - Vector curVelocity = m_pNpc->GetSmoothedVelocity(); - if ( curVelocity != vec3_origin ) - { - VectorNormalize( curVelocity ); - if ( !fNewTarget ) - { - *pResult = curVelocity * 0.1 + m_PrevSolutionVector * 0.1 + *pResult * 0.8; - } - else - { - *pResult = curVelocity * 0.2 + *pResult * 0.8; - } - } - - return true; - } - } - else - { - if (goal.navType != NAV_FLY) - { - *pResult = goal.dir; - } - else - { - VectorSubtract( goal.target, GetLocalOrigin(), *pResult ); - VectorNormalize( *pResult ); - } - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- - -float CAI_PlaneSolver::CalcProbeDist( float speed ) -{ - // one second or one hull - float result = GetLookaheadTime() * speed; - if ( result < m_pNpc->GetMoveProbe()->GetHullWidth() ) - return m_pNpc->GetMoveProbe()->GetHullWidth(); - if ( result > MAX_PROBE_DIST[AIStrongOpt()] ) - return MAX_PROBE_DIST[AIStrongOpt()]; - return result; -} - -//----------------------------------------------------------------------------- - -void CAI_PlaneSolver::AddObstacle( const Vector ¢er, float radius, CBaseEntity *pEntity, AI_MoveSuggType_t type ) -{ - m_Obstacles.AddToTail( CircleObstacles_t( center, radius, pEntity, type ) ); -} - -//----------------------------------------------------------------------------- -bool CAI_PlaneSolver::GenerateCircleObstacleSuggestions( const AILocalMoveGoal_t &moveGoal, float probeDist ) -{ - bool result = false; - Vector npcLoc = m_pNpc->WorldSpaceCenter(); - Vector mins, maxs; - - m_pNpc->CollisionProp()->WorldSpaceSurroundingBounds( &mins, &maxs ); - float radiusNpc = (mins.AsVector2D() - maxs.AsVector2D()).Length() * 0.5; - - for ( int i = 0; i < m_Obstacles.Count(); i++ ) - { - CBaseEntity *pObstacleEntity = NULL; - - float zDistTooFar; - if ( m_Obstacles[i].hEntity && m_Obstacles[i].hEntity->CollisionProp() ) - { - pObstacleEntity = m_Obstacles[i].hEntity.Get(); - - if( pObstacleEntity == moveGoal.pMoveTarget && (pObstacleEntity->IsNPC() || pObstacleEntity->IsPlayer()) ) - { - // HEY! I'm trying to avoid the very thing I'm trying to get to. This will make we wobble like a drunk as I approach. Don't do it. - continue; - } - - pObstacleEntity->CollisionProp()->WorldSpaceSurroundingBounds( &mins, &maxs ); - zDistTooFar = ( maxs.z - mins.z ) * 0.5 + GetNpc()->GetHullHeight() * 0.5; - } - else - zDistTooFar = GetNpc()->GetHullHeight(); - - if ( fabs( m_Obstacles[i].center.z - npcLoc.z ) > zDistTooFar ) - continue; - - Vector vecToNpc = npcLoc - m_Obstacles[i].center; - vecToNpc.z = 0; - float distToObstacleSq = sq(vecToNpc.x) + sq(vecToNpc.y); - float radius = m_Obstacles[i].radius + radiusNpc; - - if ( distToObstacleSq > 0.001 && distToObstacleSq < sq( radius + probeDist ) ) - { - Vector vecToObstacle = vecToNpc * -1; - float distToObstacle = VectorNormalize( vecToObstacle ); - float weight; - float arc; - float radiusSq = sq(radius); - - float flDot = DotProduct( vecToObstacle, moveGoal.dir ); - - // Don't steer around to avoid obstacles we've already passed, unless we're right up against them. - // That is, do this computation without the probeDist added in. - if( flDot < 0.0f && distToObstacleSq > radiusSq ) - { - continue; - } - - if ( radiusSq < distToObstacleSq ) - { - Vector vecTangent; - float distToTangent = FastSqrt( distToObstacleSq - radiusSq ); - - float oneOverDistToObstacleSq = 1 / distToObstacleSq; - - vecTangent.x = ( -distToTangent * vecToNpc.x + radius * vecToNpc.y ) * oneOverDistToObstacleSq; - vecTangent.y = ( -distToTangent * vecToNpc.y - radius * vecToNpc.x ) * oneOverDistToObstacleSq; - vecTangent.z = 0; - - float cosHalfArc = vecToObstacle.Dot( vecTangent ); - arc = RAD2DEG(acosf( cosHalfArc )) * 2.0; - weight = 1.0 - (distToObstacle - radius) / probeDist; - if ( weight > 0.75 ) - arc += (arc * 0.5) * (weight - 0.75) / 0.25; - - Assert( weight >= 0.0 && weight <= 1.0 ); - -#if DEBUG_OBSTACLES - // ------------------------- - Msg( "Adding arc %f, w %f\n", arc, weight ); - - Vector pointTangent = npcLoc + ( vecTangent * distToTangent ); - - NDebugOverlay::Line( npcLoc - Vector( 0, 0, 64 ), npcLoc + Vector(0,0,64), 0,255,0, false, 0.1 ); - NDebugOverlay::Line( center - Vector( 0, 0, 64 ), center + Vector(0,0,64), 0,255,0, false, 0.1 ); - NDebugOverlay::Line( pointTangent - Vector( 0, 0, 64 ), pointTangent + Vector(0,0,64), 0,255,0, false, 0.1 ); - - NDebugOverlay::Line( npcLoc + Vector(0,0,64), center + Vector(0,0,64), 0,0,255, false, 0.1 ); - NDebugOverlay::Line( center + Vector(0,0,64), pointTangent + Vector(0,0,64), 0,0,255, false, 0.1 ); - NDebugOverlay::Line( pointTangent + Vector(0,0,64), npcLoc + Vector(0,0,64), 0,0,255, false, 0.1 ); -#endif - } - else - { - arc = 210; - weight = 1.0; - } - - if ( m_Obstacles[i].hEntity != NULL ) - { - weight = AdjustRegulationWeight( m_Obstacles[i].hEntity, weight ); - } - - AI_MoveSuggestion_t suggestion( m_Obstacles[i].type, weight, UTIL_VecToYaw(vecToObstacle), arc ); - m_Solver.AddRegulation( suggestion ); - result = true; - } - } - - m_Obstacles.RemoveAll(); - return result; - -} - -//----------------------------------------------------------------------------- - -bool CAI_PlaneSolver::Solve( const AILocalMoveGoal_t &goal, float distClear, Vector *pSolution ) -{ - bool solved = false; - - //--------------------------------- - - if ( goal.speed == 0 ) - return false; - - if ( DetectUnsolvable( goal ) ) - return false; - - //--------------------------------- - - bool fVeryClose = ( distClear < 1.0 ); - float degreesPositiveArc = ( !fVeryClose ) ? DEGREES_POSITIVE_ARC : DEGREES_POSITIVE_ARC_CLOSE_OBSTRUCTION; - float probeDist = CalcProbeDist( goal.speed ); - - if ( goal.flags & ( AILMG_TARGET_IS_TRANSITION | AILMG_TARGET_IS_GOAL ) ) - { - probeDist = MIN( goal.maxDist, probeDist ); - } - - if ( GenerateObstacleSuggestions( goal, goal.directTrace, distClear, probeDist, degreesPositiveArc, NUM_PROBES ) != SR_FAIL ) - { - if ( RunMoveSolver( goal, goal.directTrace, degreesPositiveArc, !fVeryClose, pSolution ) ) - { - // Visualize desired + actual directions - VisualizeSolution( goal.dir, *pSolution ); - - AIMoveTrace_t moveTrace; - float requiredMovement = goal.speed * GetMotor()->GetMoveInterval(); - - MoveLimit( goal.navType, GetLocalOrigin() + *pSolution * requiredMovement, false, true, &moveTrace ); - - if ( !IsMoveBlocked( moveTrace ) ) - solved = true; - else - solved = false; - } - } - - m_fSolvedPrev = ( solved && goal.speed != 0 ); // a solution found when speed is zero is not meaningful - m_PrevTarget = goal.target; - - return solved; -} - -//============================================================================= diff --git a/game/server/ai_planesolver.h b/game/server/ai_planesolver.h deleted file mode 100644 index 3b873ddd9..000000000 --- a/game/server/ai_planesolver.h +++ /dev/null @@ -1,174 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_PLANE_SOLVER_H -#define AI_PLANE_SOLVER_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "utlvector.h" -#include "ai_movesolver.h" -#include "ehandle.h" -#include "mathlib/vector.h" -#include "simtimer.h" -#include "ai_navtype.h" - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class Vector2D; -class CBaseEntity; -struct edict_t; -class CAI_BaseNPC; -class CAI_Motor; -class CAI_Navigator; -struct AILocalMoveGoal_t; -struct AIMoveTrace_t; - -//------------------------------------- - -enum AI_SuggestorResult_t -{ - SR_NONE, - SR_OK, - SR_FAIL -}; - -class CAI_PlaneSolver -{ -public: - // constructor - CAI_PlaneSolver( CAI_BaseNPC *pNpc ); - - // Attempt to find a valid move direction for the specifed goal - bool Solve( const AILocalMoveGoal_t &goal, float distClear, Vector *pSolution ); - - float CalcProbeDist( float speed ); - - // Flush any cached results (e.g., hull changed, results not valid) - void Reset(); - - void AddObstacle( const Vector &pos, float radius, CBaseEntity *pEntity = NULL, AI_MoveSuggType_t type = AIMST_AVOID_OBJECT ); - bool HaveObstacles() { return ( m_Obstacles.Count() != 0 ); } - -private: - - enum - { - DEGREES_POSITIVE_ARC = 270, - DEGREES_POSITIVE_ARC_CLOSE_OBSTRUCTION = 340, - NUM_PROBES = 5 - }; - - // How far ahead does the ground solver look (seconds) - float GetLookaheadTime() { return 1.0; } - - // -------------------------------- - - // For debugging purposes - void VisualizeRegulations(); - void VisualizeSolution( const Vector &vecGoal, const Vector& vecActual ); - - // -------------------------------- - bool MoveLimit( Navigation_t navType, const Vector &target, bool ignoreTransients, bool fCheckStep, AIMoveTrace_t *pMoveTrace ); - bool MoveLimit( Navigation_t navType, const Vector &target, bool ignoreTransients, bool fCheckStep, int contents, AIMoveTrace_t *pMoveTrace ); - - //----------------------------------------------------------------------------- - // Adjust the solution for fliers - //----------------------------------------------------------------------------- - void AdjustSolutionForFliers( const AILocalMoveGoal_t &goal, float flSolutionYaw, Vector *pSolution ); - - // -------------------------------- - // Convenience accessors - - CAI_BaseNPC * GetNpc(); - CAI_Motor * GetMotor(); - const Vector & GetLocalOrigin(); - - // -------------------------------- - - void GenerateObstacleNpcs( const AILocalMoveGoal_t &goal, float probeDist ); - AI_SuggestorResult_t GenerateObstacleSuggestions( const AILocalMoveGoal_t &goal, const AIMoveTrace_t &directTrace, float distClear, float probeDist, float degreesToProbe, int nProbes ); - AI_SuggestorResult_t GenerateObstacleSuggestion( const AILocalMoveGoal_t &goal, float yawScanCenter, float probeDist, float spanPerProbe, int probeOffset ); - void GenerateSuggestionFromTrace( const AILocalMoveGoal_t &goal, - const AIMoveTrace_t &moveTrace, float probeDist, - float arcCenter, float arcSpan, int probeOffset ); - bool GenerateCircleObstacleSuggestions( const AILocalMoveGoal_t &moveGoal, float probeDist ); - - void CalcYawsFromOffset( float yawScanCenter, float spanPerProbe, int probeOffset, - float *pYawTest, float *pYawCenter ); - - float CalculateRegulationWeight( const AIMoveTrace_t &moveTrace, float pctBlockedt ); - float AdjustRegulationWeight( CBaseEntity *pEntity, float weight ); - unsigned ComputeTurnBiasFlags( const AILocalMoveGoal_t &goal, const AIMoveTrace_t &directTrace ); - - - bool RunMoveSolver( const AILocalMoveGoal_t &goal, const AIMoveTrace_t &directTrace, - float degreesPositiveArc, bool fDeterOscillation, - Vector *pResult ); - bool DetectUnsolvable( const AILocalMoveGoal_t &goal ); - - // -------------------------------- - - CAI_BaseNPC * m_pNpc; - - Vector m_PrevTarget; - bool m_fSolvedPrev; - float m_PrevSolution; - Vector m_PrevSolutionVector; - - float m_ClosestHaveBeenToCurrent; - float m_TimeLastProgress; - - bool m_fCannotSolveCurrent; - - CSimTimer m_RefreshSamplesTimer; - - // -------------------------------- - - struct CircleObstacles_t - { - CircleObstacles_t( const Vector ¢er, float radius, CBaseEntity *pEntity, AI_MoveSuggType_t type ) - : center(center), - radius(radius), - type(type), - hEntity(pEntity) - { - } - - Vector center; - float radius; - AI_MoveSuggType_t type; - EHANDLE hEntity; - }; - - CUtlVector m_Obstacles; - - // -------------------------------- - - CAI_MoveSolver m_Solver; -}; - -//------------------------------------- - -inline void CAI_PlaneSolver::Reset() -{ - m_RefreshSamplesTimer.Force(); - - m_fSolvedPrev = false; - m_PrevTarget.Init( FLT_MAX, FLT_MAX, FLT_MAX ), - m_PrevSolution = 0; - m_ClosestHaveBeenToCurrent = FLT_MAX; - m_TimeLastProgress = FLT_MAX; - m_fCannotSolveCurrent = false; -} - -//============================================================================= - -#endif // AI_PLANE_SOLVER_H diff --git a/game/server/ai_playerally.cpp b/game/server/ai_playerally.cpp deleted file mode 100644 index 4654f5bc9..000000000 --- a/game/server/ai_playerally.cpp +++ /dev/null @@ -1,1796 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" - -#include "sceneentity.h" -#include "ai_playerally.h" -#include "saverestore_utlmap.h" -#include "eventqueue.h" -#include "ai_behavior_lead.h" -#include "gameinterface.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern CServerGameDLL g_ServerGameDLL; - -extern ConVar rr_debugresponses; - -//----------------------------------------------------------------------------- - -ConVar sk_ally_regen_time( "sk_ally_regen_time", "0.3003", FCVAR_NONE, "Time taken for an ally to regenerate a point of health." ); -ConVar sv_npc_talker_maxdist( "sv_npc_talker_maxdist", "1024", 0, "NPCs over this distance from the player won't attempt to speak." ); -ConVar ai_no_talk_delay( "ai_no_talk_delay", "0" ); - -ConVar rr_debug_qa( "rr_debug_qa", "0", FCVAR_NONE, "Set to 1 to see debug related to the Question & Answer system used to create conversations between allied NPCs."); - -//----------------------------------------------------------------------------- - -ConceptCategoryInfo_t g_ConceptCategoryInfos[] = -{ - { 10, 20, 0, 0 }, - { 0, 0, 0, 0 }, - { 0, 0, 0, 0 }, -}; - -ConceptInfo_t g_ConceptInfos[] = -{ - { TLK_ANSWER, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT | AICF_ANSWER, }, - { TLK_ANSWER_HELLO, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT | AICF_ANSWER, }, - { TLK_QUESTION, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT | AICF_QUESTION, }, - { TLK_IDLE, SPEECH_IDLE, -1, -1, -1, -1, -1, -1, AICF_DEFAULT | AICF_TARGET_PLAYER, }, - { TLK_STARE, SPEECH_IDLE, -1, -1, -1, -1, 180, 0, AICF_DEFAULT | AICF_TARGET_PLAYER, }, - { TLK_LOOK, SPEECH_PRIORITY, -1, -1, -1, -1, -1, -1, AICF_DEFAULT | AICF_TARGET_PLAYER, }, - { TLK_HELLO, SPEECH_IDLE, 5, 10, -1, -1, -1, -1, AICF_DEFAULT | AICF_SPEAK_ONCE | AICF_PROPAGATE_SPOKEN | AICF_TARGET_PLAYER, }, - { TLK_PHELLO, SPEECH_IDLE, -1, -1, -1, -1, -1, -1, AICF_DEFAULT | AICF_SPEAK_ONCE | AICF_PROPAGATE_SPOKEN | AICF_TARGET_PLAYER, }, - { TLK_HELLO_NPC, SPEECH_IDLE, 5, 10, -1, -1, -1, -1, AICF_DEFAULT | AICF_QUESTION | AICF_SPEAK_ONCE, }, - { TLK_PIDLE, SPEECH_IDLE, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_PQUESTION, SPEECH_IDLE, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_SMELL, SPEECH_IDLE, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_USE, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_STARTFOLLOW, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_STOPFOLLOW, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_JOINPLAYER, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_STOP, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_NOSHOOT, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_PLHURT1, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_PLHURT2, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_PLHURT3, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_PLHURT, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_PLPUSH, SPEECH_IMPORTANT, -1, -1, -1, -1, 15, 30, AICF_DEFAULT, }, - { TLK_PLRELOAD, SPEECH_IMPORTANT, -1, -1, -1, -1, 60, 0, AICF_DEFAULT, }, - { TLK_SHOT, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_WOUND, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_MORTAL, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT | AICF_SPEAK_ONCE, }, - { TLK_SEE_COMBINE, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_ENEMY_DEAD, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_ALYX_ENEMY_DEAD,SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_SELECTED, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_COMMANDED, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_COMMAND_FAILED, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_DENY_COMMAND, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_BETRAYED, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_ALLY_KILLED, SPEECH_IMPORTANT, -1, -1, -1, -1, 15, 30, AICF_DEFAULT, }, - { TLK_ATTACKING, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_HEAL, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_GIVEAMMO, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_HELP_ME, SPEECH_IMPORTANT, -1, -1, -1, -1, 7, 10, AICF_DEFAULT, }, - { TLK_PLYR_PHYSATK, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_NEWWEAPON, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_STARTCOMBAT, SPEECH_IMPORTANT, -1, -1, -1, -1, 30, 0, AICF_DEFAULT, }, - { TLK_WATCHOUT, SPEECH_IMPORTANT, -1, -1, -1, -1, 30, 45, AICF_DEFAULT, }, - { TLK_MOBBED, SPEECH_IMPORTANT, -1, -1, -1, -1, 10, 12, AICF_DEFAULT, }, - { TLK_MANY_ENEMIES, SPEECH_IMPORTANT, -1, -1, -1, -1, 45, 60, AICF_DEFAULT, }, - { TLK_DANGER, SPEECH_PRIORITY, -1, -1, -1, -1, 5, 7, AICF_DEFAULT, }, - { TLK_PLDEAD, SPEECH_PRIORITY, -1, -1, -1, -1, 100, 0, AICF_DEFAULT, }, - { TLK_HIDEANDRELOAD, SPEECH_PRIORITY, -1, -1, -1, -1, 45, 60, AICF_DEFAULT, }, - { TLK_FLASHLIGHT_ILLUM, SPEECH_PRIORITY,-1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_FLASHLIGHT_ON, SPEECH_PRIORITY, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_FLASHLIGHT_OFF, SPEECH_PRIORITY, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_FOUNDPLAYER, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_TARGET_PLAYER, }, - { TLK_PLAYER_KILLED_NPC, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_ENEMY_BURNING, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_SPOTTED_ZOMBIE_WAKEUP, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_SPOTTED_HEADCRAB_LEAVING_ZOMBIE,SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_DANGER_ZOMBINE_GRENADE, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_BALLSOCKETED, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - - // Darkness mode - { TLK_DARKNESS_LOSTPLAYER, SPEECH_IMPORTANT,-1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_DARKNESS_FOUNDPLAYER, SPEECH_IMPORTANT,-1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_DARKNESS_UNKNOWN_WOUND, SPEECH_IMPORTANT,-1,-1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_DARKNESS_HEARDSOUND, SPEECH_IMPORTANT,-1, -1, -1, -1, 20, 30, AICF_DEFAULT, }, - { TLK_DARKNESS_LOSTENEMY_BY_FLASHLIGHT, SPEECH_IMPORTANT,-1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_DARKNESS_LOSTENEMY_BY_FLASHLIGHT_EXPIRED, SPEECH_IMPORTANT,-1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_DARKNESS_FOUNDENEMY_BY_FLASHLIGHT, SPEECH_IMPORTANT,-1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_DARKNESS_FLASHLIGHT_EXPIRED, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_SPOTTED_INCOMING_HEADCRAB, SPEECH_IMPORTANT,-1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - - // Lead behaviour - { TLK_LEAD_START, SPEECH_IMPORTANT,-1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_LEAD_ARRIVAL, SPEECH_IMPORTANT,-1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_LEAD_SUCCESS, SPEECH_IMPORTANT,-1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_LEAD_FAILURE, SPEECH_IMPORTANT,-1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_LEAD_COMINGBACK,SPEECH_IMPORTANT,-1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_LEAD_CATCHUP, SPEECH_IMPORTANT,-1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_LEAD_RETRIEVE, SPEECH_IMPORTANT,-1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_LEAD_ATTRACTPLAYER, SPEECH_IMPORTANT,-1,-1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_LEAD_WAITOVER, SPEECH_IMPORTANT,-1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_LEAD_MISSINGWEAPON, SPEECH_IMPORTANT,-1,-1, -1, -1, -1, -1, AICF_DEFAULT, }, - { TLK_LEAD_IDLE, SPEECH_IMPORTANT,-1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, - - // Passenger behaviour - { TLK_PASSENGER_NEW_RADAR_CONTACT, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_DEFAULT, }, -}; - -//----------------------------------------------------------------------------- - -bool ConceptStringLessFunc( const string_t &lhs, const string_t &rhs ) -{ - return CaselessStringLessThan( STRING(lhs), STRING(rhs) ); -} - -//----------------------------------------------------------------------------- - -class CConceptInfoMap : public CUtlMap { -public: - CConceptInfoMap() : - CUtlMap( CaselessStringLessThan ) - { - for ( size_t i = 0; i < ARRAYSIZE(g_ConceptInfos); i++ ) - { - Insert( g_ConceptInfos[i].concept, &g_ConceptInfos[i] ); - } - } -}; - -static CConceptInfoMap g_ConceptInfoMap; - -CAI_AllySpeechManager::CAI_AllySpeechManager() -{ - m_ConceptTimers.SetLessFunc( ConceptStringLessFunc ); - Assert( !gm_pSpeechManager ); - gm_pSpeechManager = this; -} - -CAI_AllySpeechManager::~CAI_AllySpeechManager() -{ - gm_pSpeechManager = NULL; -} - -void CAI_AllySpeechManager::Spawn() -{ - Assert( g_ConceptInfoMap.Count() != 0 ); - for ( size_t i = 0; i < ARRAYSIZE(g_ConceptInfos); i++ ) - m_ConceptTimers.Insert( AllocPooledString( g_ConceptInfos[i].concept ), CSimpleSimTimer() ); -} - -void CAI_AllySpeechManager::AddCustomConcept( const ConceptInfo_t &conceptInfo ) -{ - Assert( g_ConceptInfoMap.Count() != 0 ); - Assert( m_ConceptTimers.Count() != 0 ); - - if ( g_ConceptInfoMap.Find( conceptInfo.concept ) == g_ConceptInfoMap.InvalidIndex() ) - { - g_ConceptInfoMap.Insert( conceptInfo.concept, new ConceptInfo_t( conceptInfo ) ); - } - - if ( m_ConceptTimers.Find( AllocPooledString(conceptInfo.concept) ) == m_ConceptTimers.InvalidIndex() ) - { - m_ConceptTimers.Insert( AllocPooledString( conceptInfo.concept ), CSimpleSimTimer() ); - } -} - -ConceptCategoryInfo_t *CAI_AllySpeechManager::GetConceptCategoryInfo( ConceptCategory_t category ) -{ - return &g_ConceptCategoryInfos[category]; -} - -ConceptInfo_t *CAI_AllySpeechManager::GetConceptInfo( AIConcept_t concept ) -{ - int iResult = g_ConceptInfoMap.Find( concept ); - - return ( iResult != g_ConceptInfoMap.InvalidIndex() ) ? g_ConceptInfoMap[iResult] : NULL; -} - -void CAI_AllySpeechManager::OnSpokeConcept( CAI_PlayerAlly *pPlayerAlly, AIConcept_t concept, AI_Response *response ) -{ - ConceptInfo_t * pConceptInfo = GetConceptInfo( concept ); - ConceptCategory_t category = ( pConceptInfo ) ? pConceptInfo->category : SPEECH_IDLE; - ConceptCategoryInfo_t * pCategoryInfo = GetConceptCategoryInfo( category ); - - if ( pConceptInfo ) - { - if ( pConceptInfo->flags & AICF_PROPAGATE_SPOKEN ) - { - CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); - CAI_PlayerAlly *pTalker; - for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - pTalker = dynamic_cast(ppAIs[i]); - - if ( pTalker && pTalker != pPlayerAlly && - (pTalker->GetAbsOrigin() - pPlayerAlly->GetAbsOrigin()).LengthSqr() < Square(TALKRANGE_MIN * 2) && - pPlayerAlly->FVisible( pTalker ) ) - { - // Tell this guy he's already said the concept to the player, too. - pTalker->GetExpresser()->SetSpokeConcept( concept, NULL, false ); - } - } - } - } - - if ( !ai_no_talk_delay.GetBool() ) - { - if ( pConceptInfo && pConceptInfo->minGlobalCategoryDelay != -1 ) - { - Assert( pConceptInfo->maxGlobalCategoryDelay != -1 ); - SetCategoryDelay( pConceptInfo->category, pConceptInfo->minGlobalCategoryDelay, pConceptInfo->maxGlobalCategoryDelay ); - } - else if ( pCategoryInfo->maxGlobalDelay > 0 ) - { - SetCategoryDelay( category, pCategoryInfo->minGlobalDelay, pCategoryInfo->maxGlobalDelay ); - } - - if ( pConceptInfo && pConceptInfo->minPersonalCategoryDelay != -1 ) - { - Assert( pConceptInfo->maxPersonalCategoryDelay != -1 ); - pPlayerAlly->SetCategoryDelay( pConceptInfo->category, pConceptInfo->minPersonalCategoryDelay, pConceptInfo->maxPersonalCategoryDelay ); - } - else if ( pCategoryInfo->maxPersonalDelay > 0 ) - { - pPlayerAlly->SetCategoryDelay( category, pCategoryInfo->minPersonalDelay, pCategoryInfo->maxPersonalDelay ); - } - - if ( pConceptInfo && pConceptInfo->minConceptDelay != -1 ) - { - Assert( pConceptInfo->maxConceptDelay != -1 ); - char iConceptTimer = m_ConceptTimers.Find( MAKE_STRING(concept) ); - if ( iConceptTimer != m_ConceptTimers.InvalidIndex() ) - m_ConceptTimers[iConceptTimer].Set( pConceptInfo->minConceptDelay, pConceptInfo->minConceptDelay ); - } - } -} - -void CAI_AllySpeechManager::SetCategoryDelay( ConceptCategory_t category, float minDelay, float maxDelay ) -{ - if ( category != SPEECH_PRIORITY ) - m_ConceptCategoryTimers[category].Set( minDelay, maxDelay ); -} - -bool CAI_AllySpeechManager::CategoryDelayExpired( ConceptCategory_t category ) -{ - if ( category == SPEECH_PRIORITY ) - return true; - return m_ConceptCategoryTimers[category].Expired(); -} - -bool CAI_AllySpeechManager::ConceptDelayExpired( AIConcept_t concept ) -{ - char iConceptTimer = m_ConceptTimers.Find( MAKE_STRING(concept) ); - if ( iConceptTimer != m_ConceptTimers.InvalidIndex() ) - return m_ConceptTimers[iConceptTimer].Expired(); - return true; -} - -//----------------------------------------------------------------------------- - -LINK_ENTITY_TO_CLASS( ai_ally_speech_manager, CAI_AllySpeechManager ); - -BEGIN_DATADESC( CAI_AllySpeechManager ) - - DEFINE_EMBEDDED_AUTO_ARRAY(m_ConceptCategoryTimers), - DEFINE_UTLMAP( m_ConceptTimers, FIELD_STRING, FIELD_EMBEDDED ), - -END_DATADESC() - -//----------------------------------------------------------------------------- - -CAI_AllySpeechManager *CAI_AllySpeechManager::gm_pSpeechManager; - -//----------------------------------------------------------------------------- - -CAI_AllySpeechManager *GetAllySpeechManager() -{ - if ( !CAI_AllySpeechManager::gm_pSpeechManager ) - { - CreateEntityByName( "ai_ally_speech_manager" ); - Assert( CAI_AllySpeechManager::gm_pSpeechManager ); - if ( CAI_AllySpeechManager::gm_pSpeechManager ) - DispatchSpawn( CAI_AllySpeechManager::gm_pSpeechManager ); - } - - return CAI_AllySpeechManager::gm_pSpeechManager; -} - -//----------------------------------------------------------------------------- -// -// CLASS: CAI_PlayerAlly -// -//----------------------------------------------------------------------------- - -BEGIN_DATADESC( CAI_PlayerAlly ) - - DEFINE_EMBEDDED( m_PendingResponse ), - DEFINE_STDSTRING( m_PendingConcept ), - DEFINE_FIELD( m_TimePendingSet, FIELD_TIME ), - DEFINE_FIELD( m_hTalkTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_flNextRegenTime, FIELD_TIME ), - DEFINE_FIELD( m_flTimePlayerStartStare, FIELD_TIME ), - DEFINE_FIELD( m_hPotentialSpeechTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_flNextIdleSpeechTime, FIELD_TIME ), - DEFINE_FIELD( m_iQARandomNumber, FIELD_INTEGER ), - DEFINE_FIELD( m_hSpeechFilter, FIELD_EHANDLE ), - DEFINE_EMBEDDED_AUTO_ARRAY(m_ConceptCategoryTimers), - - DEFINE_KEYFIELD( m_bGameEndAlly, FIELD_BOOLEAN, "GameEndAlly" ), - DEFINE_FIELD( m_bCanSpeakWhileScripting, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_flHealthAccumulator, FIELD_FLOAT ), - DEFINE_FIELD( m_flTimeLastRegen, FIELD_TIME ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "IdleRespond", InputIdleRespond ), - DEFINE_INPUTFUNC( FIELD_STRING, "SpeakResponseConcept", InputSpeakResponseConcept ), - DEFINE_INPUTFUNC( FIELD_VOID, "MakeGameEndAlly", InputMakeGameEndAlly ), - DEFINE_INPUTFUNC( FIELD_VOID, "MakeRegularAlly", InputMakeRegularAlly ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "AnswerQuestion", InputAnswerQuestion ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "AnswerQuestionHello", InputAnswerQuestionHello ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableSpeakWhileScripting", InputEnableSpeakWhileScripting ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableSpeakWhileScripting", InputDisableSpeakWhileScripting ), - -END_DATADESC() - -CBaseEntity *CreatePlayerLoadSave( Vector vOrigin, float flDuration, float flHoldTime, float flLoadTime ); -ConVar npc_ally_deathmessage( "npc_ally_deathmessage", "1", FCVAR_CHEAT ); - -void CAI_PlayerAlly::InputMakeGameEndAlly( inputdata_t &inputdata ) -{ - m_bGameEndAlly = true; -} - -void CAI_PlayerAlly::InputMakeRegularAlly( inputdata_t &inputdata ) -{ - m_bGameEndAlly = false; -} - -void CAI_PlayerAlly::DisplayDeathMessage( void ) -{ - if ( m_bGameEndAlly == false ) - return; - - if ( npc_ally_deathmessage.GetBool() == 0 ) - return; - - CBaseEntity *pPlayer = AI_GetSinglePlayer(); - - if ( pPlayer ) - { - UTIL_ShowMessage( GetDeathMessageText(), ToBasePlayer( pPlayer ) ); - ToBasePlayer(pPlayer)->NotifySinglePlayerGameEnding(); - } - - CBaseEntity *pReload = CreatePlayerLoadSave( GetAbsOrigin(), 1.5f, 8.0f, 4.5f ); - - if ( pReload ) - { - pReload->SetRenderColor( 0, 0, 0, 255 ); - - g_EventQueue.AddEvent( pReload, "Reload", 1.5f, pReload, pReload ); - } - - // clear any pending autosavedangerous - g_ServerGameDLL.m_fAutoSaveDangerousTime = 0.0f; - g_ServerGameDLL.m_fAutoSaveDangerousMinHealthToCommit = 0.0f; -} - -//----------------------------------------------------------------------------- -// NPCs derived from CAI_PlayerAlly should call this in precache() -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::TalkInit( void ) -{ -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::GatherConditions( void ) -{ - BaseClass::GatherConditions(); - - if ( !HasCondition( COND_SEE_PLAYER ) ) - { - SetCondition( COND_TALKER_CLIENTUNSEEN ); - } - - CBasePlayer *pLocalPlayer = AI_GetSinglePlayer(); - - if ( !pLocalPlayer ) - { - if ( AI_IsSinglePlayer() ) - SetCondition( COND_TALKER_PLAYER_DEAD ); - return; - } - - if ( !pLocalPlayer->IsAlive() ) - { - SetCondition( COND_TALKER_PLAYER_DEAD ); - } - - if ( HasCondition( COND_SEE_PLAYER ) ) - { - - bool bPlayerIsLooking = false; - if ( ( pLocalPlayer->GetAbsOrigin() - GetAbsOrigin() ).Length2DSqr() < Square(TALKER_STARE_DIST) ) - { - if ( pLocalPlayer->FInViewCone( EyePosition() ) ) - { - if ( pLocalPlayer->GetSmoothedVelocity().LengthSqr() < Square( 100 ) ) - bPlayerIsLooking = true; - } - } - - if ( bPlayerIsLooking ) - { - SetCondition( COND_TALKER_PLAYER_STARING ); - if ( m_flTimePlayerStartStare == 0 ) - m_flTimePlayerStartStare = gpGlobals->curtime; - } - else - { - m_flTimePlayerStartStare = 0; - ClearCondition( COND_TALKER_PLAYER_STARING ); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::GatherEnemyConditions( CBaseEntity *pEnemy ) -{ - BaseClass::GatherEnemyConditions( pEnemy ); - if ( GetLastEnemyTime() == 0 || gpGlobals->curtime - GetLastEnemyTime() > 30 ) - { -#ifdef HL2_DLL - if ( HasCondition( COND_SEE_ENEMY ) && ( pEnemy->Classify() != CLASS_BULLSEYE ) ) - { - if( Classify() == CLASS_PLAYER_ALLY_VITAL && hl2_episodic.GetBool() ) - { - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - - if( pPlayer ) - { - - // If I can see the player, and the player would see this enemy if he turned around... - if( !pPlayer->FInViewCone(pEnemy) && FVisible( pPlayer ) && pPlayer->FVisible(pEnemy) ) - { - Vector2D vecPlayerView = pPlayer->EyeDirection2D().AsVector2D(); - Vector2D vecToEnemy = ( pEnemy->GetAbsOrigin() - pPlayer->GetAbsOrigin() ).AsVector2D(); - Vector2DNormalize( vecToEnemy ); - - if( DotProduct2D(vecPlayerView, vecToEnemy) <= -0.75 ) - { - SpeakIfAllowed( TLK_WATCHOUT, "dangerloc:behind" ); - return; - } - } - } - } - SpeakIfAllowed( TLK_STARTCOMBAT ); - } -#else - if ( HasCondition( COND_SEE_ENEMY ) ) - { - SpeakIfAllowed( TLK_STARTCOMBAT ); - } -#endif //HL2_DLL - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::OnStateChange( NPC_STATE OldState, NPC_STATE NewState ) -{ - BaseClass::OnStateChange( OldState, NewState ); - - if ( OldState == NPC_STATE_COMBAT ) - { - DeferAllIdleSpeech(); - } - - if ( GetState() == NPC_STATE_IDLE || GetState() == NPC_STATE_ALERT ) - { - m_flNextIdleSpeechTime = gpGlobals->curtime + RandomFloat(5,10); - } - else - { - m_flNextIdleSpeechTime = 0; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::PrescheduleThink( void ) -{ - BaseClass::PrescheduleThink(); - -#ifdef HL2_DLL - // Vital allies regenerate - if( GetHealth() >= GetMaxHealth() ) - { - // Avoid huge deltas on first regeneration of health after long period of time at full health. - m_flTimeLastRegen = gpGlobals->curtime; - } - else if ( ShouldRegenerateHealth() ) - { - float flDelta = gpGlobals->curtime - m_flTimeLastRegen; - float flHealthPerSecond = 1.0f / sk_ally_regen_time.GetFloat(); - - float flHealthRegen = flHealthPerSecond * flDelta; - - if ( g_pGameRules->IsSkillLevel(SKILL_HARD) ) - flHealthRegen *= 0.5f; - else if ( g_pGameRules->IsSkillLevel(SKILL_EASY) ) - flHealthRegen *= 1.5f; - - m_flTimeLastRegen = gpGlobals->curtime; - - TakeHealth( flHealthRegen, DMG_GENERIC ); - } - -#ifdef HL2_EPISODIC - if ( (GetState() == NPC_STATE_IDLE || GetState() == NPC_STATE_ALERT) - && !HasCondition(COND_RECEIVED_ORDERS) && !IsInAScript() ) - { - if ( m_flNextIdleSpeechTime && m_flNextIdleSpeechTime < gpGlobals->curtime ) - { - AISpeechSelection_t selection; - if ( SelectNonCombatSpeech( &selection ) ) - { - SetSpeechTarget( selection.hSpeechTarget ); - SpeakDispatchResponse( selection.concept.c_str(), selection.pResponse ); - m_flNextIdleSpeechTime = gpGlobals->curtime + RandomFloat( 20,30 ); - } - else - { - m_flNextIdleSpeechTime = gpGlobals->curtime + RandomFloat( 10,20 ); - } - } - } -#endif // HL2_EPISODIC - -#endif // HL2_DLL -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CAI_PlayerAlly::SelectSchedule( void ) -{ - if ( !HasCondition(COND_RECEIVED_ORDERS) ) - { - // sustained light wounds? - if ( m_iHealth <= m_iMaxHealth * 0.75 && IsAllowedToSpeak( TLK_WOUND ) && !GetExpresser()->SpokeConcept(TLK_WOUND) ) - { - CTakeDamageInfo info; - PainSound( info ); - } - // sustained heavy wounds? - else if ( m_iHealth <= m_iMaxHealth * 0.5 && IsAllowedToSpeak( TLK_MORTAL) ) - { - Speak( TLK_MORTAL ); - } - } - - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CAI_PlayerAlly::SelectSpeechResponse( AIConcept_t concept, const char *pszModifiers, CBaseEntity *pTarget, AISpeechSelection_t *pSelection ) -{ - if ( IsAllowedToSpeak( concept ) ) - { - AI_Response *pResponse = SpeakFindResponse( concept, pszModifiers ); - if ( pResponse ) - { - pSelection->Set( concept, pResponse, pTarget ); - return true; - } - } - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::SetPendingSpeech( AIConcept_t concept, AI_Response *pResponse ) -{ - m_PendingResponse = *pResponse; - pResponse->Release(); - m_PendingConcept = concept; - m_TimePendingSet = gpGlobals->curtime; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::ClearPendingSpeech() -{ - m_PendingConcept.erase(); - m_TimePendingSet = 0; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -bool CAI_PlayerAlly::SelectIdleSpeech( AISpeechSelection_t *pSelection ) -{ - if ( !IsOkToSpeak( SPEECH_IDLE ) ) - return false; - - CBasePlayer *pTarget = assert_cast(FindSpeechTarget( AIST_PLAYERS | AIST_FACING_TARGET )); - if ( pTarget ) - { - if ( SelectSpeechResponse( TLK_HELLO, NULL, pTarget, pSelection ) ) - return true; - - if ( GetTimePlayerStaring() > 6 && !IsMoving() ) - { - if ( SelectSpeechResponse( TLK_STARE, NULL, pTarget, pSelection ) ) - return true; - } - - int chance = ( IsMoving() ) ? 20 : 2; - if ( ShouldSpeakRandom( TLK_IDLE, chance ) && SelectSpeechResponse( TLK_IDLE, NULL, pTarget, pSelection ) ) - return true; - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_PlayerAlly::SelectAlertSpeech( AISpeechSelection_t *pSelection ) -{ -#ifdef HL2_EPISODIC - CBasePlayer *pTarget = assert_cast(FindSpeechTarget( AIST_PLAYERS | AIST_FACING_TARGET )); - if ( pTarget ) - { - if ( pTarget->IsAlive() ) - { - float flHealthPerc = ((float)pTarget->m_iHealth / (float)pTarget->m_iMaxHealth); - if ( flHealthPerc < 1.0 ) - { - if ( SelectSpeechResponse( TLK_PLHURT, NULL, pTarget, pSelection ) ) - return true; - } - } - } -#endif - - return SelectIdleSpeech( pSelection ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -bool CAI_PlayerAlly::SelectInterjection() -{ - if ( HasPendingSpeech() ) - return false; - - if ( HasCondition(COND_RECEIVED_ORDERS) ) - return false; - - if ( GetState() == NPC_STATE_IDLE || GetState() == NPC_STATE_ALERT ) - { - AISpeechSelection_t selection; - - if ( SelectIdleSpeech( &selection ) ) - { - SetSpeechTarget( selection.hSpeechTarget ); - SpeakDispatchResponse( selection.concept.c_str(), selection.pResponse ); - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -bool CAI_PlayerAlly::SelectPlayerUseSpeech() -{ - if( IsOkToSpeakInResponseToPlayer() ) - { - if ( Speak( TLK_USE ) ) - DeferAllIdleSpeech(); - else - return Speak( ( !GetExpresser()->SpokeConcept( TLK_HELLO ) ) ? TLK_HELLO : TLK_IDLE ); - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_PlayerAlly::SelectQuestionAndAnswerSpeech( AISpeechSelection_t *pSelection ) -{ - if ( !IsOkToSpeak( SPEECH_IDLE ) ) - return false; - - if ( IsMoving() ) - return false; - - // if there is a friend nearby to speak to, play sentence, set friend's response time, return - CAI_PlayerAlly *pFriend = dynamic_cast(FindSpeechTarget( AIST_NPCS )); - if ( pFriend && !pFriend->IsMoving() && !pFriend->HasSpawnFlags(SF_NPC_GAG) ) - return SelectQuestionFriend( pFriend, pSelection ); - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::PostSpeakDispatchResponse( AIConcept_t concept, AI_Response *response ) -{ -#ifdef HL2_EPISODIC - CAI_AllySpeechManager *pSpeechManager = GetAllySpeechManager(); - ConceptInfo_t *pConceptInfo = pSpeechManager->GetConceptInfo( concept ); - if ( pConceptInfo && (pConceptInfo->flags & AICF_QUESTION) && GetSpeechTarget() ) - { - bool bSaidHelloToNPC = !Q_strcmp(concept, "TLK_HELLO_NPC"); - - float duration = GetExpresser()->GetSemaphoreAvailableTime(this) - gpGlobals->curtime; - - if ( rr_debug_qa.GetBool() ) - { - if ( bSaidHelloToNPC ) - { - Warning("Q&A: '%s' said Hello to '%s' (concept %s)\n", GetDebugName(), GetSpeechTarget()->GetDebugName(), concept ); - } - else - { - Warning("Q&A: '%s' questioned '%s' (concept %s)\n", GetDebugName(), GetSpeechTarget()->GetDebugName(), concept ); - } - NDebugOverlay::HorzArrow( GetAbsOrigin(), GetSpeechTarget()->GetAbsOrigin(), 8, 0, 255, 0, 64, true, duration ); - } - - // If we spoke a Question, tell our friend to answer - const char *pszInput; - if ( bSaidHelloToNPC ) - { - pszInput = "AnswerQuestionHello"; - } - else - { - pszInput = "AnswerQuestion"; - } - - // Set the input parameter to the random number we used to find the Question - variant_t value; - value.SetInt( m_iQARandomNumber ); - g_EventQueue.AddEvent( GetSpeechTarget(), pszInput, value, duration + .2, this, this ); - - if ( GetSpeechTarget()->MyNPCPointer() ) - { - AddLookTarget( GetSpeechTarget()->MyNPCPointer(), 1.0, duration + random->RandomFloat( 0.4, 1.2 ), 0.5 ); - GetSpeechTarget()->MyNPCPointer()->AddLookTarget( this, 1.0, duration + random->RandomFloat( 0.4, 1 ), 0.7 ); - } - - // Don't let anyone else butt in. - DeferAllIdleSpeech( random->RandomFloat( TALKER_DEFER_IDLE_SPEAK_MIN, TALKER_DEFER_IDLE_SPEAK_MAX ), GetSpeechTarget()->MyNPCPointer() ); - } - else if ( pConceptInfo && (pConceptInfo->flags & AICF_ANSWER) && GetSpeechTarget() ) - { - float duration = GetExpresser()->GetSemaphoreAvailableTime(this) - gpGlobals->curtime; - if ( rr_debug_qa.GetBool() ) - { - NDebugOverlay::HorzArrow( GetAbsOrigin(), GetSpeechTarget()->GetAbsOrigin(), 8, 0, 255, 0, 64, true, duration ); - } - if ( GetSpeechTarget()->MyNPCPointer() ) - { - AddLookTarget( GetSpeechTarget()->MyNPCPointer(), 1.0, duration + random->RandomFloat( 0, 0.3 ), 0.5 ); - GetSpeechTarget()->MyNPCPointer()->AddLookTarget( this, 1.0, duration + random->RandomFloat( 0.2, 0.5 ), 0.7 ); - } - } - - m_hPotentialSpeechTarget = NULL; -#endif // HL2_EPISODIC -} - -//----------------------------------------------------------------------------- -// Purpose: Find a concept to question a nearby friend -//----------------------------------------------------------------------------- -bool CAI_PlayerAlly::SelectQuestionFriend( CBaseEntity *pFriend, AISpeechSelection_t *pSelection ) -{ - if ( !ShouldSpeakRandom( TLK_QUESTION, 3 ) ) - return false; - - // Tell the response rules who we're trying to question - m_hPotentialSpeechTarget = pFriend; - m_iQARandomNumber = RandomInt(0,100); - - // If we haven't said hello, say hello first. - // Only ever say hello to NPCs other than my type. - if ( !GetExpresser()->SpokeConcept( TLK_HELLO_NPC ) && !FClassnameIs( this, pFriend->GetClassname()) ) - { - if ( SelectSpeechResponse( TLK_HELLO_NPC, NULL, pFriend, pSelection ) ) - return true; - - GetExpresser()->SetSpokeConcept( TLK_HELLO_NPC, NULL ); - } - - return SelectSpeechResponse( TLK_QUESTION, NULL, pFriend, pSelection ); -} - -//----------------------------------------------------------------------------- -// Purpose: Find a concept to answer our friend's question -//----------------------------------------------------------------------------- -bool CAI_PlayerAlly::SelectAnswerFriend( CBaseEntity *pFriend, AISpeechSelection_t *pSelection, bool bRespondingToHello ) -{ - // Tell the response rules who we're trying to answer - m_hPotentialSpeechTarget = pFriend; - - if ( bRespondingToHello ) - { - if ( SelectSpeechResponse( TLK_ANSWER_HELLO, NULL, pFriend, pSelection ) ) - return true; - } - - return SelectSpeechResponse( TLK_ANSWER, NULL, pFriend, pSelection ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::InputAnswerQuestion( inputdata_t &inputdata ) -{ - AnswerQuestion( dynamic_cast(inputdata.pActivator), inputdata.value.Int(), false ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::InputAnswerQuestionHello( inputdata_t &inputdata ) -{ - AnswerQuestion( dynamic_cast(inputdata.pActivator), inputdata.value.Int(), true ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::AnswerQuestion( CAI_PlayerAlly *pQuestioner, int iQARandomNum, bool bAnsweringHello ) -{ - // Original questioner may have died - if ( !pQuestioner ) - return; - - AISpeechSelection_t selection; - - // Use the random number that the questioner used to determine his Question (so we can match answers via response rules) - m_iQARandomNumber = iQARandomNum; - - // The activator is the person we're responding to - if ( SelectAnswerFriend( pQuestioner, &selection, bAnsweringHello ) ) - { - if ( rr_debug_qa.GetBool() ) - { - if ( bAnsweringHello ) - { - Warning("Q&A: '%s' answered the Hello from '%s'\n", GetDebugName(), pQuestioner->GetDebugName() ); - } - else - { - Warning("Q&A: '%s' answered the Question from '%s'\n", GetDebugName(), pQuestioner->GetDebugName() ); - } - } - - Assert( selection.pResponse ); - SetSpeechTarget( selection.hSpeechTarget ); - SpeakDispatchResponse( selection.concept.c_str(), selection.pResponse ); - - // Prevent idle speech for a while - DeferAllIdleSpeech( random->RandomFloat( TALKER_DEFER_IDLE_SPEAK_MIN, TALKER_DEFER_IDLE_SPEAK_MAX ), GetSpeechTarget()->MyNPCPointer() ); - } - else if ( rr_debug_qa.GetBool() ) - { - Warning("Q&A: '%s' couldn't answer '%s'\n", GetDebugName(), pQuestioner->GetDebugName() ); - } -} - -//----------------------------------------------------------------------------- -// Output : int -//----------------------------------------------------------------------------- -int CAI_PlayerAlly::SelectNonCombatSpeech( AISpeechSelection_t *pSelection ) -{ - bool bResult = false; - - #ifdef HL2_EPISODIC - // See if we can Q&A first - if ( GetState() == NPC_STATE_IDLE || GetState() == NPC_STATE_ALERT ) - { - bResult = SelectQuestionAndAnswerSpeech( pSelection ); - } - #endif // HL2_EPISODIC - - if ( !bResult ) - { - if ( GetState() == NPC_STATE_ALERT ) - { - bResult = SelectAlertSpeech( pSelection ); - } - else - { - bResult = SelectIdleSpeech( pSelection ); - } - } - - return bResult; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CAI_PlayerAlly::SelectNonCombatSpeechSchedule() -{ - if ( !HasPendingSpeech() ) - { - AISpeechSelection_t selection; - if ( SelectNonCombatSpeech( &selection ) ) - { - Assert( selection.pResponse ); - SetSpeechTarget( selection.hSpeechTarget ); - SetPendingSpeech( selection.concept.c_str(), selection.pResponse ); - } - } - - if ( HasPendingSpeech() ) - { - if ( m_TimePendingSet == gpGlobals->curtime || IsAllowedToSpeak( m_PendingConcept.c_str() ) ) - return SCHED_TALKER_SPEAK_PENDING_IDLE; - } - - return SCHED_NONE; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CAI_PlayerAlly::TranslateSchedule( int schedule ) -{ - if ( ( GetState() == NPC_STATE_IDLE || GetState() == NPC_STATE_ALERT ) && - ConditionInterruptsSchedule( schedule, COND_IDLE_INTERRUPT ) && - !HasCondition(COND_RECEIVED_ORDERS) ) - { - int speechSchedule = SelectNonCombatSpeechSchedule(); - if ( speechSchedule != SCHED_NONE ) - return speechSchedule; - } - - switch( schedule ) - { - case SCHED_CHASE_ENEMY_FAILED: - { - int baseType = BaseClass::TranslateSchedule(schedule); - if ( baseType != SCHED_CHASE_ENEMY_FAILED ) - return baseType; - - return SCHED_TAKE_COVER_FROM_ENEMY; - } - break; - } - return BaseClass::TranslateSchedule( schedule ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::OnStartSchedule( int schedule ) -{ - if ( schedule == SCHED_HIDE_AND_RELOAD ) - SpeakIfAllowed( TLK_HIDEANDRELOAD ); - BaseClass::OnStartSchedule( schedule ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::StartTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_MOVE_AWAY_PATH: - { - if ( HasCondition( COND_PLAYER_PUSHING ) && AI_IsSinglePlayer() ) - { - // @TODO (toml 10-22-04): cope with multiplayer push - GetMotor()->SetIdealYawToTarget( UTIL_GetLocalPlayer()->WorldSpaceCenter() ); - } - BaseClass::StartTask( pTask ); - break; - } - - case TASK_PLAY_SCRIPT: - SetSpeechTarget( NULL ); - BaseClass::StartTask( pTask ); - break; - - case TASK_TALKER_SPEAK_PENDING: - if ( !m_PendingConcept.empty() ) - { - AI_Response *pResponse = new AI_Response; - *pResponse = m_PendingResponse; - SpeakDispatchResponse( m_PendingConcept.c_str(), pResponse ); - m_PendingConcept.erase(); - TaskComplete(); - } - else - TaskFail( FAIL_NO_SOUND ); - break; - - default: - BaseClass::StartTask( pTask ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::RunTask( const Task_t *pTask ) -{ - BaseClass::RunTask( pTask ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::TaskFail( AI_TaskFailureCode_t code ) -{ - if ( IsCurSchedule( SCHED_TALKER_SPEAK_PENDING_IDLE, false ) ) - ClearPendingSpeech(); - BaseClass::TaskFail( code ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::ClearTransientConditions() -{ - CAI_BaseNPC::ClearTransientConditions(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::Touch( CBaseEntity *pOther ) -{ - BaseClass::Touch( pOther ); - - // Did the player touch me? - if ( pOther->IsPlayer() ) - { - // Ignore if pissed at player - if ( m_afMemory & bits_MEMORY_PROVOKED ) - return; - - // Stay put during speech - if ( GetExpresser()->IsSpeaking() ) - return; - - TestPlayerPushing( pOther ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::OnKilledNPC( CBaseCombatCharacter *pKilled ) -{ - if ( pKilled ) - { - if ( !pKilled->IsNPC() || - ( pKilled->MyNPCPointer()->GetLastPlayerDamageTime() == 0 || - gpGlobals->curtime - pKilled->MyNPCPointer()->GetLastPlayerDamageTime() > 5 ) ) - { - SpeakIfAllowed( TLK_ENEMY_DEAD ); - } - } -} - -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - const char *pszHitLocCriterion = NULL; - - if ( ptr->hitgroup == HITGROUP_LEFTLEG || ptr->hitgroup == HITGROUP_RIGHTLEG ) - { - pszHitLocCriterion = "shotloc:leg"; - } - else if ( ptr->hitgroup == HITGROUP_LEFTARM || ptr->hitgroup == HITGROUP_RIGHTARM ) - { - pszHitLocCriterion = "shotloc:arm"; - } - else if ( ptr->hitgroup == HITGROUP_STOMACH ) - { - pszHitLocCriterion = "shotloc:gut"; - } - - // set up the speech modifiers - CFmtStrN<128> modifiers( "%s,damageammo:%s", pszHitLocCriterion, info.GetAmmoName() ); - - SpeakIfAllowed( TLK_SHOT, modifiers ); - - BaseClass::TraceAttack( info, vecDir, ptr ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CAI_PlayerAlly::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - CTakeDamageInfo subInfo = info; - // Vital allies never take more than 25% of their health in a single hit (except for physics damage) -#ifdef HL2_DLL - // Don't do damage reduction for DMG_GENERIC. This allows SetHealth inputs to still do full damage. - if ( subInfo.GetDamageType() != DMG_GENERIC ) - { - if ( Classify() == CLASS_PLAYER_ALLY_VITAL && !(subInfo.GetDamageType() & DMG_CRUSH) ) - { - float flDamage = subInfo.GetDamage(); - if ( flDamage > ( GetMaxHealth() * 0.25 ) ) - { - flDamage = ( GetMaxHealth() * 0.25 ); - subInfo.SetDamage( flDamage ); - } - } - } -#endif - - return BaseClass::OnTakeDamage_Alive( subInfo ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CAI_PlayerAlly::TakeHealth( float flHealth, int bitsDamageType ) -{ - int intPortion; - float floatPortion; - - intPortion = ((int)flHealth); - floatPortion = flHealth - intPortion; - - m_flHealthAccumulator += floatPortion; - - while ( m_flHealthAccumulator > 1.0f ) - { - m_flHealthAccumulator -= 1.0f; - intPortion += 1; - } - - return BaseClass::TakeHealth( ((float)intPortion), bitsDamageType ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::Event_Killed( const CTakeDamageInfo &info ) -{ - // notify the player - if ( IsInPlayerSquad() ) - { - CBasePlayer *player = AI_GetSinglePlayer(); - if ( player ) - { - variant_t emptyVariant; - player->AcceptInput( "OnSquadMemberKilled", this, this, emptyVariant, 0 ); - } - } - - if ( GetSpeechSemaphore( this )->GetOwner() == this ) - GetSpeechSemaphore( this )->Release(); - - CAI_PlayerAlly *pMourner = dynamic_cast(FindSpeechTarget( AIST_NPCS )); - if ( pMourner ) - { - pMourner->SpeakIfAllowed( TLK_ALLY_KILLED ); - } - - SetTarget( NULL ); - // Don't finish that sentence - SentenceStop(); - SetUse( NULL ); - BaseClass::Event_Killed( info ); - - DisplayDeathMessage(); -} - -// Player allies should use simple shadows to save CPU. This means they can't -// be killed by crush damage. -bool CAI_PlayerAlly::CreateVPhysics() -{ - bool bRet = BaseClass::CreateVPhysics(); - return bRet; -} - -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::PainSound( const CTakeDamageInfo &info ) -{ - SpeakIfAllowed( TLK_WOUND ); -} - -//----------------------------------------------------------------------------- -// Purpose: Implemented to look at talk target -//----------------------------------------------------------------------------- -CBaseEntity *CAI_PlayerAlly::EyeLookTarget( void ) -{ - // FIXME: this should be in the VCD - // FIXME: this is dead code - if (GetExpresser()->IsSpeaking() && GetSpeechTarget() != NULL) - { - return GetSpeechTarget(); - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: returns who we're talking to for vcd's -//----------------------------------------------------------------------------- -CBaseEntity *CAI_PlayerAlly::FindNamedEntity( const char *pszName, IEntityFindFilter *pFilter ) -{ - if ( !stricmp( pszName, "!speechtarget" )) - { - return GetSpeechTarget(); - } - - if ( !stricmp( pszName, "!friend" )) - { - return FindSpeechTarget( AIST_NPCS ); - } - - - return BaseClass::FindNamedEntity( pszName, pFilter ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CAI_PlayerAlly::IsValidSpeechTarget( int flags, CBaseEntity *pEntity ) -{ - if ( pEntity == this ) - return false; - - if ( !(flags & AIST_IGNORE_RELATIONSHIP) ) - { - if ( pEntity->IsPlayer() ) - { - if ( !IsPlayerAlly( (CBasePlayer *)pEntity ) ) - return false; - } - else - { - if ( IRelationType( pEntity ) != D_LI ) - return false; - } - } - - if ( !pEntity->IsAlive() ) - // don't dead people - return false; - - // Ignore no-target entities - if ( pEntity->GetFlags() & FL_NOTARGET ) - return false; - - CAI_BaseNPC *pNPC = pEntity->MyNPCPointer(); - if ( pNPC ) - { - // If not a NPC for some reason, or in a script. - if ( (pNPC->m_NPCState == NPC_STATE_SCRIPT || pNPC->m_NPCState == NPC_STATE_PRONE)) - return false; - - if ( pNPC->IsInAScript() ) - return false; - - // Don't bother people who don't want to be bothered - if ( !pNPC->CanBeUsedAsAFriend() ) - return false; - } - - if ( flags & AIST_FACING_TARGET ) - { - if ( pEntity->IsPlayer() ) - return HasCondition( COND_SEE_PLAYER ); - else if ( !FInViewCone( pEntity ) ) - return false; - } - - return FVisible( pEntity ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CBaseEntity *CAI_PlayerAlly::FindSpeechTarget( int flags ) -{ - const Vector & vAbsOrigin = GetAbsOrigin(); - float closestDistSq = FLT_MAX; - CBaseEntity * pNearest = NULL; - float distSq; - int i; - - if ( flags & AIST_PLAYERS ) - { - for ( i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBaseEntity *pPlayer = UTIL_PlayerByIndex( i ); - if ( pPlayer ) - { - distSq = ( vAbsOrigin - pPlayer->GetAbsOrigin() ).LengthSqr(); - - if ( distSq > Square(TALKRANGE_MIN) ) - continue; - - if ( !(flags & AIST_ANY_QUALIFIED) && distSq > closestDistSq ) - continue; - - if ( IsValidSpeechTarget( flags, pPlayer ) ) - { - if ( flags & AIST_ANY_QUALIFIED ) - return pPlayer; - - closestDistSq = distSq; - pNearest = pPlayer; - } - } - } - } - - if ( flags & AIST_NPCS ) - { - for ( i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - CAI_BaseNPC *pNPC = (g_AI_Manager.AccessAIs())[i]; - - distSq = ( vAbsOrigin - pNPC->GetAbsOrigin() ).LengthSqr(); - - if ( distSq > Square(TALKRANGE_MIN) ) - continue; - - if ( !(flags & AIST_ANY_QUALIFIED) && distSq > closestDistSq ) - continue; - - if ( IsValidSpeechTarget( flags, pNPC ) ) - { - if ( flags & AIST_ANY_QUALIFIED ) - return pNPC; - - closestDistSq = distSq; - pNearest = pNPC; - } - } - } - - return pNearest; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CAI_PlayerAlly::CanPlaySentence( bool fDisregardState ) -{ - if ( fDisregardState ) - return BaseClass::CanPlaySentence( fDisregardState ); - return IsOkToSpeak(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CAI_PlayerAlly::PlayScriptedSentence( const char *pszSentence, float delay, float volume, soundlevel_t soundlevel, bool bConcurrent, CBaseEntity *pListener ) -{ - ClearCondition( COND_PLAYER_PUSHING ); // Forget about moving! I've got something to say! - int sentenceIndex = BaseClass::PlayScriptedSentence( pszSentence, delay, volume, soundlevel, bConcurrent, pListener ); - SetSpeechTarget( pListener ); - - return sentenceIndex; -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CAI_PlayerAlly::DeferAllIdleSpeech( float flDelay, CAI_BaseNPC *pIgnore ) -{ - CAI_AllySpeechManager *pSpeechManager = GetAllySpeechManager(); - if ( flDelay == -1 ) - { - ConceptCategoryInfo_t *pCategoryInfo = pSpeechManager->GetConceptCategoryInfo( SPEECH_IDLE ); - pSpeechManager->SetCategoryDelay( SPEECH_IDLE, pCategoryInfo->minGlobalDelay, pCategoryInfo->maxGlobalDelay ); - } - else - pSpeechManager->SetCategoryDelay( SPEECH_IDLE, flDelay ); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -bool CAI_PlayerAlly::IsOkToSpeak( ConceptCategory_t category, bool fRespondingToPlayer ) -{ - CAI_AllySpeechManager *pSpeechManager = GetAllySpeechManager(); - - // if not alive, certainly don't speak - if ( !IsAlive() ) - return false; - - if ( m_spawnflags & SF_NPC_GAG ) - return false; - - // Don't speak if playing a script. - if ( ( m_NPCState == NPC_STATE_SCRIPT ) && !m_bCanSpeakWhileScripting ) - return false; - - // Don't speak if being eaten by a barnacle - if ( IsEFlagSet( EFL_IS_BEING_LIFTED_BY_BARNACLE ) ) - return false; - - if ( IsInAScript() && !m_bCanSpeakWhileScripting ) - return false; - - if ( !fRespondingToPlayer ) - { - if ( !pSpeechManager->CategoryDelayExpired( category ) || !CategoryDelayExpired( category ) ) - return false; - } - - if ( category == SPEECH_IDLE ) - { - if ( GetState() != NPC_STATE_IDLE && GetState() != NPC_STATE_ALERT ) - return false; - if ( GetSpeechFilter() && GetSpeechFilter()->GetIdleModifier() < 0.001 ) - return false; - } - - // if player is not in pvs, don't speak - if ( !UTIL_FindClientInPVS(edict()) ) - return false; - - if ( category != SPEECH_PRIORITY ) - { - // if someone else is talking, don't speak - if ( !GetExpresser()->SemaphoreIsAvailable( this ) ) - return false; - - if ( fRespondingToPlayer ) - { - if ( !GetExpresser()->CanSpeakAfterMyself() ) - return false; - } - else - { - if ( !GetExpresser()->CanSpeak() ) - return false; - } - - // Don't talk if we're too far from the player - CBaseEntity *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer ) - { - float flDist = sv_npc_talker_maxdist.GetFloat(); - flDist *= flDist; - if ( (pPlayer->WorldSpaceCenter() - WorldSpaceCenter()).LengthSqr() > flDist ) - return false; - } - } - - if ( fRespondingToPlayer ) - { - // If we're responding to the player, don't respond if the scene has speech in it - if ( IsRunningScriptedSceneWithSpeechAndNotPaused( this ) ) - { - if( rr_debugresponses.GetInt() > 0 ) - { - DevMsg("%s not allowed to speak because they are in a scripted scene\n", GetDebugName() ); - } - - return false; - } - } - else - { - // If we're not responding to the player, don't talk if running a logic_choreo - if ( IsRunningScriptedSceneAndNotPaused( this ) ) - { - if( rr_debugresponses.GetInt() > 0 ) - { - DevMsg("%s not allowed to speak because they are in a scripted scene\n", GetDebugName() ); - } - - return false; - } - } - - return true; -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -bool CAI_PlayerAlly::IsOkToSpeak( void ) -{ - return IsOkToSpeak( SPEECH_IDLE ); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -bool CAI_PlayerAlly::IsOkToCombatSpeak( void ) -{ - return IsOkToSpeak( SPEECH_IMPORTANT ); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -bool CAI_PlayerAlly::IsOkToSpeakInResponseToPlayer( void ) -{ - return IsOkToSpeak( SPEECH_IMPORTANT, true ); -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if I should speak based on the chance & the speech filter's modifier -//----------------------------------------------------------------------------- -bool CAI_PlayerAlly::ShouldSpeakRandom( AIConcept_t concept, int iChance ) -{ - CAI_AllySpeechManager * pSpeechManager = GetAllySpeechManager(); - ConceptInfo_t * pInfo = pSpeechManager->GetConceptInfo( concept ); - ConceptCategory_t category = ( pInfo ) ? pInfo->category : SPEECH_IDLE; - - if ( GetSpeechFilter() ) - { - if ( category == SPEECH_IDLE ) - { - float flModifier = GetSpeechFilter()->GetIdleModifier(); - if ( flModifier < 0.001 ) - return false; - - iChance = (int)floor( iChance / flModifier ); - } - } - - if ( iChance < 1 ) - return false; - - if ( iChance == 1 ) - return true; - - return (random->RandomInt(1,iChance) == 1); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CAI_PlayerAlly::IsAllowedToSpeak( AIConcept_t concept, bool bRespondingToPlayer ) -{ - CAI_AllySpeechManager * pSpeechManager = GetAllySpeechManager(); - ConceptInfo_t * pInfo = pSpeechManager->GetConceptInfo( concept ); - ConceptCategory_t category = ( pInfo ) ? pInfo->category : SPEECH_IDLE; - - if ( !IsOkToSpeak( category, bRespondingToPlayer ) ) - return false; - - if ( GetSpeechFilter() && GetSpeechFilter()->NeverSayHello() ) - { - if ( CompareConcepts( concept, TLK_HELLO ) ) - return false; - if ( CompareConcepts( concept, TLK_HELLO_NPC ) ) - return false; - } - - if ( !pSpeechManager->ConceptDelayExpired( concept ) ) - return false; - - if ( ( pInfo && pInfo->flags & AICF_SPEAK_ONCE ) && GetExpresser()->SpokeConcept( concept ) ) - return false; - - if ( !GetExpresser()->CanSpeakConcept( concept ) ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CAI_PlayerAlly::SpeakIfAllowed( AIConcept_t concept, const char *modifiers, bool bRespondingToPlayer, char *pszOutResponseChosen, size_t bufsize ) -{ - if ( IsAllowedToSpeak( concept, bRespondingToPlayer ) ) - { - return Speak( concept, modifiers, pszOutResponseChosen, bufsize ); - } - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::ModifyOrAppendCriteria( AI_CriteriaSet& set ) -{ - BaseClass::ModifyOrAppendCriteria( set ); - - if ( m_hPotentialSpeechTarget ) - { - set.AppendCriteria( "speechtarget", m_hPotentialSpeechTarget->GetClassname() ); - set.AppendCriteria( "speechtargetname", STRING(m_hPotentialSpeechTarget->GetEntityName()) ); - set.AppendCriteria( "randomnum", UTIL_VarArgs("%d", m_iQARandomNumber) ); - } - - // Do we have a speech filter? If so, append it's criteria too - if ( GetSpeechFilter() ) - { - GetSpeechFilter()->AppendContextToCriteria( set ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::OnSpokeConcept( AIConcept_t concept, AI_Response *response ) -{ - CAI_AllySpeechManager *pSpeechManager = GetAllySpeechManager(); - pSpeechManager->OnSpokeConcept( this, concept, response ); - - if( response != NULL && (response->GetParams()->flags & AI_ResponseParams::RG_WEAPONDELAY) ) - { - // Stop shooting, as instructed, so that my speech can be heard. - GetShotRegulator()->FireNoEarlierThan( gpGlobals->curtime + response->GetWeaponDelay() ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::OnStartSpeaking() -{ - // If you say anything, don't greet the player - you may have already spoken to them - if ( !GetExpresser()->SpokeConcept( TLK_HELLO ) ) - { - GetExpresser()->SetSpokeConcept( TLK_HELLO, NULL ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Mapmaker input to force this NPC to speak a response rules concept -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::InputSpeakResponseConcept( inputdata_t &inputdata ) -{ - SpeakMapmakerInterruptConcept( inputdata.value.StringID() ); -} - - -//----------------------------------------------------------------------------- -// Allows mapmakers to override NPC_STATE_SCRIPT or IsScripting() for responses. -//----------------------------------------------------------------------------- -void CAI_PlayerAlly::InputEnableSpeakWhileScripting( inputdata_t &inputdata ) -{ - m_bCanSpeakWhileScripting = true; -} - -void CAI_PlayerAlly::InputDisableSpeakWhileScripting( inputdata_t &inputdata ) -{ - m_bCanSpeakWhileScripting = false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_PlayerAlly::SpeakMapmakerInterruptConcept( string_t iszConcept ) -{ - // Let behaviors override - if ( BaseClass::SpeakMapmakerInterruptConcept(iszConcept) ) - return false; - - if (!IsOkToSpeakInResponseToPlayer()) - return false; - - Speak( STRING(iszConcept) ); - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_PlayerAlly::CanRespondToEvent( const char *ResponseConcept ) -{ - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_PlayerAlly::RespondedTo( const char *ResponseConcept, bool bForce, bool bCancelScene ) -{ - if ( bForce ) - { - // We're being forced to respond to the event, probably because it's the - // player dying or something equally important. - AI_Response *result = SpeakFindResponse( ResponseConcept, NULL ); - if ( result ) - { - // We've got something to say. Stop any scenes we're in, and speak the response. - if ( bCancelScene ) - RemoveActorFromScriptedScenes( this, false ); - - bool spoke = SpeakDispatchResponse( ResponseConcept, result ); - return spoke; - } - - return false; - } - - if ( SpeakIfAllowed( ResponseConcept, NULL, true ) ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC(talk_monster_base,CAI_PlayerAlly) - - DECLARE_TASK(TASK_TALKER_SPEAK_PENDING) - - DECLARE_CONDITION(COND_TALKER_CLIENTUNSEEN) - DECLARE_CONDITION(COND_TALKER_PLAYER_DEAD) - DECLARE_CONDITION(COND_TALKER_PLAYER_STARING) - - //========================================================= - // > SCHED_TALKER_SPEAK_PENDING_IDLE - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_TALKER_SPEAK_PENDING_IDLE, - - " Tasks" - " TASK_TALKER_SPEAK_PENDING 0" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT_FOR_SPEAK_FINISH 0" - " TASK_WAIT_RANDOM 0.5" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_HEAR_COMBAT" - " COND_PLAYER_PUSHING" - " COND_GIVE_WAY" - ) - - //========================================================= - // > SCHED_TALKER_SPEAK_PENDING_ALERT - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_TALKER_SPEAK_PENDING_ALERT, - - " Tasks" - " TASK_TALKER_SPEAK_PENDING 0" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT_FOR_SPEAK_FINISH 0" - " TASK_WAIT_RANDOM 0.5" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_PLAYER_PUSHING" - " COND_GIVE_WAY" - ) - - //========================================================= - // > SCHED_TALKER_SPEAK_PENDING_COMBAT - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_TALKER_SPEAK_PENDING_COMBAT, - - " Tasks" - " TASK_TALKER_SPEAK_PENDING 0" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT_FOR_SPEAK_FINISH 0" - "" - " Interrupts" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - ) - -AI_END_CUSTOM_NPC() - -//----------------------------------------------------------------------------- diff --git a/game/server/ai_playerally.h b/game/server/ai_playerally.h deleted file mode 100644 index 7282874c6..000000000 --- a/game/server/ai_playerally.h +++ /dev/null @@ -1,490 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef AI_PLAYERALLY_H -#define AI_PLAYERALLY_H - -#include "utlmap.h" -#include "simtimer.h" -#include "AI_Criteria.h" -#include "ai_baseactor.h" -#include "ai_speechfilter.h" -#ifndef _WIN32 -#undef min -#undef max -#endif -#include "stdstring.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -//----------------------------------------------------------------------------- - -#define TLK_ANSWER "TLK_ANSWER" -#define TLK_ANSWER_HELLO "TLK_ANSWER_HELLO" -#define TLK_QUESTION "TLK_QUESTION" -#define TLK_IDLE "TLK_IDLE" -#define TLK_STARE "TLK_STARE" -#define TLK_LOOK "TLK_LOOK" // player looking at player for a second -#define TLK_USE "TLK_USE" -#define TLK_STARTFOLLOW "TLK_STARTFOLLOW" -#define TLK_STOPFOLLOW "TLK_STOPFOLLOW" -#define TLK_JOINPLAYER "TLK_JOINPLAYER" -#define TLK_STOP "TLK_STOP" -#define TLK_NOSHOOT "TLK_NOSHOOT" -#define TLK_HELLO "TLK_HELLO" -#define TLK_PHELLO "TLK_PHELLO" -#define TLK_HELLO_NPC "TLK_HELLO_NPC" -#define TLK_PIDLE "TLK_PIDLE" -#define TLK_PQUESTION "TLK_PQUESTION" -#define TLK_PLHURT1 "TLK_PLHURT1" -#define TLK_PLHURT2 "TLK_PLHURT2" -#define TLK_PLHURT3 "TLK_PLHURT3" -#define TLK_PLHURT "TLK_PLHURT" -#define TLK_PLPUSH "TLK_PLPUSH" -#define TLK_PLRELOAD "TLK_PLRELOAD" -#define TLK_SMELL "TLK_SMELL" -#define TLK_SHOT "TLK_SHOT" -#define TLK_WOUND "TLK_WOUND" -#define TLK_MORTAL "TLK_MORTAL" -#define TLK_DANGER "TLK_DANGER" -#define TLK_SEE_COMBINE "TLK_SEE_COMBINE" -#define TLK_ENEMY_DEAD "TLK_ENEMY_DEAD" -#define TLK_ALYX_ENEMY_DEAD "TLK_ALYX_ENEMY_DEAD" -#define TLK_SELECTED "TLK_SELECTED" // selected by player in command mode. -#define TLK_COMMANDED "TLK_COMMANDED" // received orders from player in command mode -#define TLK_COMMAND_FAILED "TLK_COMMAND_FAILED" -#define TLK_DENY_COMMAND "TLK_DENY_COMMAND" // designer has asked this NPC to politely deny player commands to move the squad -#define TLK_BETRAYED "TLK_BETRAYED" // player killed an ally in front of me. -#define TLK_ALLY_KILLED "TLK_ALLY_KILLED" // witnessed an ally die some other way. -#define TLK_ATTACKING "TLK_ATTACKING" // about to fire my weapon at a target -#define TLK_HEAL "TLK_HEAL" // healing someone -#define TLK_GIVEAMMO "TLK_GIVEAMMO" // giving ammo to someone -#define TLK_DEATH "TLK_DEATH" // Death rattle -#define TLK_HELP_ME "TLK_HELP_ME" // call out to the player for help -#define TLK_PLYR_PHYSATK "TLK_PLYR_PHYSATK" // Player's attacked me with a thrown physics object -#define TLK_NEWWEAPON "TLK_NEWWEAPON" -#define TLK_PLDEAD "TLK_PLDEAD" -#define TLK_HIDEANDRELOAD "TLK_HIDEANDRELOAD" -#define TLK_STARTCOMBAT "TLK_STARTCOMBAT" -#define TLK_WATCHOUT "TLK_WATCHOUT" -#define TLK_MOBBED "TLK_MOBBED" -#define TLK_MANY_ENEMIES "TLK_MANY_ENEMIES" -#define TLK_FLASHLIGHT_ILLUM "TLK_FLASHLIGHT_ILLUM" -#define TLK_FLASHLIGHT_ON "TLK_FLASHLIGHT_ON" // player turned on flashlight -#define TLK_FLASHLIGHT_OFF "TLK_FLASHLIGHT_OFF" // player turned off flashlight -#define TLK_DARKNESS_LOSTPLAYER "TLK_DARKNESS_LOSTPLAYER" -#define TLK_DARKNESS_FOUNDPLAYER "TLK_DARKNESS_FOUNDPLAYER" -#define TLK_DARKNESS_UNKNOWN_WOUND "TLK_DARKNESS_UNKNOWN_WOUND" -#define TLK_DARKNESS_HEARDSOUND "TLK_DARKNESS_HEARDSOUND" -#define TLK_DARKNESS_LOSTENEMY_BY_FLASHLIGHT "TLK_DARKNESS_LOSTENEMY_BY_FLASHLIGHT" -#define TLK_DARKNESS_LOSTENEMY_BY_FLASHLIGHT_EXPIRED "TLK_DARKNESS_LOSTENEMY_BY_FLASHLIGHT_EXPIRED" -#define TLK_DARKNESS_FOUNDENEMY_BY_FLASHLIGHT "TLK_DARKNESS_FOUNDENEMY_BY_FLASHLIGHT" -#define TLK_DARKNESS_FLASHLIGHT_EXPIRED "TLK_DARKNESS_FLASHLIGHT_EXPIRED" // flashlight expired while not in combat -#define TLK_DARKNESS_ENEMY_IN_DARKNESS "TLK_DARKNESS_ENEMY_IN_DARKNESS" // have an enemy, but it's in the darkness -#define TLK_SPOTTED_INCOMING_HEADCRAB "TLK_SPOTTED_INCOMING_HEADCRAB" -#define TLK_CANT_INTERACT_NOW "TLK_CANT_INTERACT_NOW" // to busy to interact with an object the player is holding up to me -#define TLK_ALLY_IN_BARNACLE "TLK_ALLY_IN_BARNACLE" // Barnacle is lifting my buddy! -#define TLK_SELF_IN_BARNACLE "TLK_SELF_IN_BARNACLE" // I was grabbed by a barnacle! -#define TLK_FOUNDPLAYER "TLK_FOUNDPLAYER" -#define TLK_PLAYER_KILLED_NPC "TLK_PLAYER_KILLED_NPC" -#define TLK_ENEMY_BURNING "TLK_ENEMY_BURNING" -#define TLK_SPOTTED_ZOMBIE_WAKEUP "TLK_SPOTTED_ZOMBIE_WAKEUP" -#define TLK_SPOTTED_HEADCRAB_LEAVING_ZOMBIE "TLK_SPOTTED_HEADCRAB_LEAVING_ZOMBIE" -#define TLK_DANGER_ZOMBINE_GRENADE "TLK_DANGER_ZOMBINE_GRENADE" -#define TLK_BALLSOCKETED "TLK_BALLSOCKETED" - -// Vehicle passenger -#define TLK_PASSENGER_WARN_COLLISION "TLK_PASSENGER_WARN_COLLISION" // About to collide with something -#define TLK_PASSENGER_IMPACT "TLK_PASSENGER_IMPACT" // Just hit something -#define TLK_PASSENGER_OVERTURNED "TLK_PASSENGER_OVERTURNED" // Vehicle has just overturned -#define TLK_PASSENGER_REQUEST_UPRIGHT "TLK_PASSENGER_REQUEST_UPRIGHT" // Vehicle needs to be put upright -#define TLK_PASSENGER_ERRATIC_DRIVING "TLK_PASSENGER_ERRATIC_DRIVING" // Vehicle is moving erratically -#define TLK_PASSENGER_VEHICLE_STARTED "TLK_PASSENGER_VEHICLE_STARTED" // Vehicle has started moving -#define TLK_PASSENGER_VEHICLE_STOPPED "TLK_PASSENGER_VEHICLE_STOPPED" // Vehicle has stopped moving -#define TLK_PASSENGER_BEGIN_ENTRANCE "TLK_PASSENGER_BEGIN_ENTRANCE" // Passenger started entering -#define TLK_PASSENGER_FINISH_ENTRANCE "TLK_PASSENGER_FINISH_ENTRANCE" // Passenger finished entering (is in seat) -#define TLK_PASSENGER_BEGIN_EXIT "TLK_PASSENGER_BEGIN_EXIT" // Passenger started exiting -#define TLK_PASSENGER_FINISH_EXIT "TLK_PASSENGER_FINISH_EXIT" // Passenger finished exiting (seat is vacated) -#define TLK_PASSENGER_PLAYER_ENTERED "TLK_PASSENGER_PLAYER_ENTERED" // Player entered the vehicle -#define TLK_PASSENGER_PLAYER_EXITED "TLK_PASSENGER_PLAYER_EXITED" // Player exited the vehicle -#define TLK_PASSENGER_NEW_RADAR_CONTACT "TLK_PASSENGER_NEW_RADAR_CONTACT" // Noticed a brand new contact on the radar -#define TLK_PASSENGER_PUNTED "TLK_PASSENGER_PUNTED" // The player has punted us while we're sitting in the vehicle - -// Vortigaunt -#define TLK_VORTIGAUNT_DISPEL "TLK_VORTIGAUNT_DISPEL" // Dispel attack starting - -// resume is "as I was saying..." or "anyhow..." -#define TLK_RESUME "TLK_RESUME" - -// tourguide stuff below -#define TLK_TGSTAYPUT "TLK_TGSTAYPUT" -#define TLK_TGFIND "TLK_TGFIND" -#define TLK_TGSEEK "TLK_TGSEEK" -#define TLK_TGLOSTYOU "TLK_TGLOSTYOU" -#define TLK_TGCATCHUP "TLK_TGCATCHUP" -#define TLK_TGENDTOUR "TLK_TGENDTOUR" - -//----------------------------------------------------------------------------- - -#define TALKRANGE_MIN 500.0 // don't talk to anyone farther away than this - -//----------------------------------------------------------------------------- - -#define TALKER_STARE_DIST 128 // anyone closer than this and looking at me is probably staring at me. - -#define TALKER_DEFER_IDLE_SPEAK_MIN 10 -#define TALKER_DEFER_IDLE_SPEAK_MAX 20 - -//----------------------------------------------------------------------------- - -class CAI_PlayerAlly; - -//----------------------------------------------------------------------------- -// -// CLASS: CAI_AllySpeechManager -// -//----------------------------------------------------------------------------- - -enum ConceptCategory_t -{ - SPEECH_IDLE, - SPEECH_IMPORTANT, - SPEECH_PRIORITY, - - SPEECH_NUM_CATEGORIES -}; - -struct ConceptCategoryInfo_t -{ - float minGlobalDelay; - float maxGlobalDelay; - float minPersonalDelay; - float maxPersonalDelay; -}; - -enum AIConceptFlags_t -{ - AICF_DEFAULT = 0, - AICF_SPEAK_ONCE = 0x01, - AICF_PROPAGATE_SPOKEN = 0x02, - AICF_TARGET_PLAYER = 0x04, - AICF_QUESTION = 0x08, - AICF_ANSWER = 0x10, -}; - -struct ConceptInfo_t -{ - AIConcept_t concept; - ConceptCategory_t category; - float minGlobalCategoryDelay; - float maxGlobalCategoryDelay; - float minPersonalCategoryDelay; - float maxPersonalCategoryDelay; - float minConceptDelay; - float maxConceptDelay; - int flags; -}; - -//------------------------------------- - -class CAI_AllySpeechManager : public CLogicalEntity -{ - DECLARE_CLASS( CAI_AllySpeechManager, CLogicalEntity ); -public: - CAI_AllySpeechManager(); - ~CAI_AllySpeechManager(); - - void Spawn(); - - void AddCustomConcept( const ConceptInfo_t &conceptInfo ); - ConceptCategoryInfo_t *GetConceptCategoryInfo( ConceptCategory_t category ); - ConceptInfo_t *GetConceptInfo( AIConcept_t concept ); - void OnSpokeConcept( CAI_PlayerAlly *pPlayerAlly, AIConcept_t concept, AI_Response *response ); - - void SetCategoryDelay( ConceptCategory_t category, float minDelay, float maxDelay = 0.0 ); - bool CategoryDelayExpired( ConceptCategory_t category ); - bool ConceptDelayExpired( AIConcept_t concept ); - -private: - - CSimpleSimTimer m_ConceptCategoryTimers[SPEECH_NUM_CATEGORIES]; - - CUtlMap m_ConceptTimers; - - friend CAI_AllySpeechManager *GetAllySpeechManager(); - static CAI_AllySpeechManager *gm_pSpeechManager; - - DECLARE_DATADESC(); -}; - -//------------------------------------- - -CAI_AllySpeechManager *GetAllySpeechManager(); - -//----------------------------------------------------------------------------- -// -// CLASS: CAI_PlayerAlly -// -//----------------------------------------------------------------------------- - -class CAI_AllySpeechManager; - -enum AISpeechTargetSearchFlags_t -{ - AIST_PLAYERS = (1<<0), - AIST_NPCS = (1<<1), - AIST_IGNORE_RELATIONSHIP = (1<<2), - AIST_ANY_QUALIFIED = (1<<3), - AIST_FACING_TARGET = (1<<4), -}; - -struct AISpeechSelection_t -{ - AISpeechSelection_t() - : pResponse(NULL) - { - } - - void Set( AIConcept_t newConcept, AI_Response *pNewResponse, CBaseEntity *pTarget = NULL ) - { - pResponse = pNewResponse; - concept = newConcept; - hSpeechTarget = pTarget; - } - - std::string concept; - AI_Response * pResponse; - EHANDLE hSpeechTarget; -}; - -//------------------------------------- - -class CAI_PlayerAlly : public CAI_BaseActor -{ - DECLARE_CLASS( CAI_PlayerAlly, CAI_BaseActor ); - -public: - //--------------------------------- - - int ObjectCaps( void ) { return UsableNPCObjectCaps(BaseClass::ObjectCaps()); } - void TalkInit( void ); - - //--------------------------------- - // Behavior - //--------------------------------- - void GatherConditions( void ); - void GatherEnemyConditions( CBaseEntity *pEnemy ); - void OnStateChange( NPC_STATE OldState, NPC_STATE NewState ); - void PrescheduleThink( void ); - int SelectSchedule( void ); - int SelectNonCombatSpeech( AISpeechSelection_t *pSelection ); - virtual int SelectNonCombatSpeechSchedule(); - int TranslateSchedule( int scheduleType ); - void OnStartSchedule( int scheduleType ); - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - void TaskFail( AI_TaskFailureCode_t ); - void TaskFail( const char *pszGeneralFailText ) { BaseClass::TaskFail( pszGeneralFailText ); } - void ClearTransientConditions(); - void Touch( CBaseEntity *pOther ); - - //--------------------------------- - // Combat - //--------------------------------- - void OnKilledNPC( CBaseCombatCharacter *pKilled ); - - //--------------------------------- - // Damage handling - //--------------------------------- - void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - int TakeHealth( float flHealth, int bitsDamageType ); - void Event_Killed( const CTakeDamageInfo &info ); - bool CreateVPhysics(); - - //--------------------------------- - - virtual void PainSound( const CTakeDamageInfo &info ); - - //--------------------------------- - // Speech & Acting - //--------------------------------- - CBaseEntity *EyeLookTarget( void ); // Override to look at talk target - CBaseEntity *FindNamedEntity( const char *pszName, IEntityFindFilter *pFilter = NULL ); - - CBaseEntity *FindSpeechTarget( int flags ); - virtual bool IsValidSpeechTarget( int flags, CBaseEntity *pEntity ); - - CBaseEntity *GetSpeechTarget() { return m_hTalkTarget.Get(); } - void SetSpeechTarget( CBaseEntity *pSpeechTarget ) { m_hTalkTarget = pSpeechTarget; } - - void SetSpeechFilter( CAI_SpeechFilter *pFilter ) { m_hSpeechFilter = pFilter; } - CAI_SpeechFilter *GetSpeechFilter( void ) { return m_hSpeechFilter; } - - //--------------------------------- - - virtual bool SelectIdleSpeech( AISpeechSelection_t *pSelection ); - virtual bool SelectAlertSpeech( AISpeechSelection_t *pSelection ); - - virtual bool SelectInterjection(); - virtual bool SelectPlayerUseSpeech(); - - //--------------------------------- - - virtual bool SelectQuestionAndAnswerSpeech( AISpeechSelection_t *pSelection ); - virtual void PostSpeakDispatchResponse( AIConcept_t concept, AI_Response *response ); - bool SelectQuestionFriend( CBaseEntity *pFriend, AISpeechSelection_t *pSelection ); - bool SelectAnswerFriend( CBaseEntity *pFriend, AISpeechSelection_t *pSelection, bool bRespondingToHello ); - - //--------------------------------- - - bool SelectSpeechResponse( AIConcept_t concept, const char *pszModifiers, CBaseEntity *pTarget, AISpeechSelection_t *pSelection ); - void SetPendingSpeech( AIConcept_t concept, AI_Response *pResponse ); - void ClearPendingSpeech(); - bool HasPendingSpeech() { return !m_PendingConcept.empty(); } - - //--------------------------------- - - bool CanPlaySentence( bool fDisregardState ); - int PlayScriptedSentence( const char *pszSentence, float delay, float volume, soundlevel_t soundlevel, bool bConcurrent, CBaseEntity *pListener ); - - //--------------------------------- - - void DeferAllIdleSpeech( float flDelay = -1, CAI_BaseNPC *pIgnore = NULL ); - - //--------------------------------- - - bool IsOkToSpeak( ConceptCategory_t category, bool fRespondingToPlayer = false ); - - //--------------------------------- - - bool IsOkToSpeak( void ); - bool IsOkToCombatSpeak( void ); - bool IsOkToSpeakInResponseToPlayer( void ); - - bool ShouldSpeakRandom( AIConcept_t concept, int iChance ); - bool IsAllowedToSpeak( AIConcept_t concept, bool bRespondingToPlayer = false ); - virtual bool SpeakIfAllowed( AIConcept_t concept, const char *modifiers = NULL, bool bRespondingToPlayer = false, char *pszOutResponseChosen = NULL, size_t bufsize = 0 ); - void ModifyOrAppendCriteria( AI_CriteriaSet& set ); - - //--------------------------------- - - float GetTimePlayerStaring() { return ( m_flTimePlayerStartStare != 0 ) ? gpGlobals->curtime - m_flTimePlayerStartStare : 0; } - - //--------------------------------- - // NPC Event Response System - virtual bool CanRespondToEvent( const char *ResponseConcept ); - virtual bool RespondedTo( const char *ResponseConcept, bool bForce, bool bCancelScene ); - - //--------------------------------- - - void OnSpokeConcept( AIConcept_t concept, AI_Response *response ); - void OnStartSpeaking(); - - // Inputs - virtual void InputIdleRespond( inputdata_t &inputdata ) {}; - void InputSpeakResponseConcept( inputdata_t &inputdata ); - virtual bool SpeakMapmakerInterruptConcept( string_t iszConcept ); - - void DisplayDeathMessage( void ); - virtual const char *GetDeathMessageText( void ) { return "GAMEOVER_ALLY"; } - void InputMakeGameEndAlly( inputdata_t &inputdata ); - void InputMakeRegularAlly( inputdata_t &inputdata ); - void InputAnswerQuestion( inputdata_t &inputdata ); - void InputAnswerQuestionHello( inputdata_t &inputdata ); - void InputEnableSpeakWhileScripting( inputdata_t &inputdata ); - void InputDisableSpeakWhileScripting( inputdata_t &inputdata ); - - void AnswerQuestion( CAI_PlayerAlly *pQuestioner, int iQARandomNum, bool bAnsweringHello ); - -protected: - -#ifdef HL2_DLL - // Health regeneration for friendly allies - virtual bool ShouldRegenerateHealth( void ) { return ( Classify() == CLASS_PLAYER_ALLY_VITAL ); } -#endif - - inline bool CanSpeakWhileScripting(); - - // Whether we are a vital ally (useful for wrting Classify() for classes that are only sometimes vital, - // such as the Lone Vort in Ep2.) The usual means by which any other function should determine if a character - // is vital is to determine Classify() == CLASS_PLAYER_ALLY_VITAL. Do not use this function outside that - // context. - inline bool IsGameEndAlly( void ) { return m_bGameEndAlly; } - - //----------------------------------------------------- - // Conditions, Schedules, Tasks - //----------------------------------------------------- - enum - { - SCHED_TALKER_SPEAK_PENDING_IDLE = BaseClass::NEXT_SCHEDULE, - SCHED_TALKER_SPEAK_PENDING_ALERT, - SCHED_TALKER_SPEAK_PENDING_COMBAT, - NEXT_SCHEDULE, - - TASK_TALKER_SPEAK_PENDING = BaseClass::NEXT_TASK, - NEXT_TASK, - - COND_TALKER_CLIENTUNSEEN = BaseClass::NEXT_CONDITION, - COND_TALKER_PLAYER_DEAD, - COND_TALKER_PLAYER_STARING, - NEXT_CONDITION - }; - -private: - void SetCategoryDelay( ConceptCategory_t category, float minDelay, float maxDelay = 0.0 ) { m_ConceptCategoryTimers[category].Set( minDelay, maxDelay ); } - bool CategoryDelayExpired( ConceptCategory_t category ) { return m_ConceptCategoryTimers[category].Expired(); } - - friend class CAI_AllySpeechManager; - - //--------------------------------- - - AI_Response m_PendingResponse; - std::string m_PendingConcept; - float m_TimePendingSet; - - //--------------------------------- - - EHANDLE m_hTalkTarget; // who to look at while talking - float m_flNextRegenTime; - float m_flTimePlayerStartStare; - EHANDLE m_hPotentialSpeechTarget; // NPC to tell the response rules about when trying to find a response to talk to them with - float m_flNextIdleSpeechTime; - int m_iQARandomNumber; - - //--------------------------------- - - CSimpleSimTimer m_ConceptCategoryTimers[3]; - - //--------------------------------- - - CHandle m_hSpeechFilter; - - bool m_bGameEndAlly; - bool m_bCanSpeakWhileScripting; // Allows mapmakers to override NPC_STATE_SCRIPT or IsScripting() for responses. - - float m_flTimeLastRegen; // Last time I regenerated a bit of health. - float m_flHealthAccumulator; // Counterpart to the damage accumulator in CBaseCombatCharacter. So ally health regeneration is accurate over time. - -#ifdef _XBOX -protected: -#endif - DECLARE_DATADESC(); -protected: - DEFINE_CUSTOM_AI; -}; - - -bool CAI_PlayerAlly::CanSpeakWhileScripting() -{ - return m_bCanSpeakWhileScripting; -} - -//----------------------------------------------------------------------------- - -#endif // AI_PLAYERALLY_H diff --git a/game/server/ai_relationship.cpp b/game/server/ai_relationship.cpp deleted file mode 100644 index 356b55cec..000000000 --- a/game/server/ai_relationship.cpp +++ /dev/null @@ -1,496 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Entity which alters the relationships between entities via entity I/O -// -//=====================================================================================// - -#include "cbase.h" -#include "ndebugoverlay.h" -#include "ai_basenpc.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SF_RELATIONSHIP_NOTIFY_SUBJECT (1<<0) // Alert the subject of the change and give them a memory of the target entity -#define SF_RELATIONSHIP_NOTIFY_TARGET (1<<1) // Alert the target of the change and give them a memory of the subject entity - -enum -{ - NOT_REVERTING, - REVERTING_TO_PREV, - REVERTING_TO_DEFAULT, -}; - -//========================================================= -//========================================================= -class CAI_Relationship : public CBaseEntity, public IEntityListener -{ - DECLARE_CLASS( CAI_Relationship, CBaseEntity ); - -public: - CAI_Relationship() : m_iPreviousDisposition( -1 ) { } - - void Spawn(); - void Activate(); - - void SetActive( bool bActive ); - void ChangeRelationships( int disposition, int iReverting, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); - - void ApplyRelationship( CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); - void RevertRelationship( CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); - void RevertToDefaultRelationship( CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); - - void UpdateOnRemove(); - void OnRestore(); - - bool IsASubject( CBaseEntity *pEntity ); - bool IsATarget( CBaseEntity *pEntity ); - - void OnEntitySpawned( CBaseEntity *pEntity ); - void OnEntityDeleted( CBaseEntity *pEntity ); - -private: - - void ApplyRelationshipThink( void ); - CBaseEntity *FindEntityForProceduralName( string_t iszName, CBaseEntity *pActivator, CBaseEntity *pCaller ); - void DiscloseNPCLocation( CBaseCombatCharacter *pSubject, CBaseCombatCharacter *pTarget ); - - string_t m_iszSubject; - int m_iDisposition; - int m_iRank; - bool m_fStartActive; - bool m_bIsActive; - int m_iPreviousDisposition; - float m_flRadius; - int m_iPreviousRank; - bool m_bReciprocal; - -public: - // Input functions - void InputApplyRelationship( inputdata_t &inputdata ); - void InputRevertRelationship( inputdata_t &inputdata ); - void InputRevertToDefaultRelationship( inputdata_t &inputdata ); - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( ai_relationship, CAI_Relationship ); - -BEGIN_DATADESC( CAI_Relationship ) - DEFINE_THINKFUNC( ApplyRelationshipThink ), - - DEFINE_KEYFIELD( m_iszSubject, FIELD_STRING, "subject" ), - DEFINE_KEYFIELD( m_iDisposition, FIELD_INTEGER, "disposition" ), - DEFINE_KEYFIELD( m_iRank, FIELD_INTEGER, "rank" ), - DEFINE_KEYFIELD( m_fStartActive, FIELD_BOOLEAN, "StartActive" ), - DEFINE_FIELD( m_bIsActive, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "radius" ), - DEFINE_FIELD( m_iPreviousDisposition, FIELD_INTEGER ), - DEFINE_FIELD( m_iPreviousRank, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_bReciprocal, FIELD_BOOLEAN, "reciprocal" ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "ApplyRelationship", InputApplyRelationship ), - DEFINE_INPUTFUNC( FIELD_VOID, "RevertRelationship", InputRevertRelationship ), - DEFINE_INPUTFUNC( FIELD_VOID, "RevertToDefaultRelationship", InputRevertToDefaultRelationship ), -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_Relationship::Spawn() -{ - m_bIsActive = false; - - if (m_iszSubject == NULL_STRING) - { - DevWarning("ai_relationship '%s' with no subject specified, removing.\n", GetDebugName()); - UTIL_Remove(this); - } - else if (m_target == NULL_STRING) - { - DevWarning("ai_relationship '%s' with no target specified, removing.\n", GetDebugName()); - UTIL_Remove(this); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CAI_Relationship::Activate() -{ - if ( m_fStartActive ) - { - ApplyRelationship(); - - // Clear this flag so that nothing happens when the level is loaded (which calls activate again) - m_fStartActive = false; - } - - BaseClass::Activate(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : bActive - -//----------------------------------------------------------------------------- -void CAI_Relationship::SetActive( bool bActive ) -{ - if ( bActive && !m_bIsActive ) - { - // Start getting entity updates! - gEntList.AddListenerEntity( this ); - } - else if ( !bActive && m_bIsActive ) - { - // Stop getting entity updates! - gEntList.RemoveListenerEntity( this ); - } - - m_bIsActive = bActive; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CAI_Relationship::InputApplyRelationship( inputdata_t &inputdata ) -{ - ApplyRelationship( inputdata.pActivator, inputdata.pCaller ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CAI_Relationship::InputRevertRelationship( inputdata_t &inputdata ) -{ - RevertRelationship( inputdata.pActivator, inputdata.pCaller ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CAI_Relationship::InputRevertToDefaultRelationship( inputdata_t &inputdata ) -{ - RevertToDefaultRelationship( inputdata.pActivator, inputdata.pCaller ); -} - -//----------------------------------------------------------------------------- -// Purpose: This think function is used to wait until the player has properly -// spawned, after all the NPCs have spawned. Once that occurs, this -// function terminates. -//----------------------------------------------------------------------------- -void CAI_Relationship::ApplyRelationshipThink( void ) -{ - // Call down to the base until the player has properly spawned - ApplyRelationship(); -} - -//--------------------------------------------------------- -// Purpose: Applies the desired relationships to an entity -//--------------------------------------------------------- -void CAI_Relationship::ApplyRelationship( CBaseEntity *pActivator, CBaseEntity *pCaller ) -{ - // @TODO (toml 10-22-04): sort out MP relationships - - // The player spawns slightly after the NPCs, meaning that if we don't wait, the - // player will miss any relationships placed on them. - if ( AI_IsSinglePlayer() && !UTIL_GetLocalPlayer() ) - { - SetThink( &CAI_Relationship::ApplyRelationshipThink ); - SetNextThink( gpGlobals->curtime ); - } - - if ( !m_bIsActive ) - { - SetActive( true ); - } - - ChangeRelationships( m_iDisposition, NOT_REVERTING, pActivator, pCaller ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CAI_Relationship::RevertRelationship( CBaseEntity *pActivator, CBaseEntity *pCaller ) -{ - if ( m_bIsActive ) - { - ChangeRelationships( m_iPreviousDisposition, REVERTING_TO_PREV, pActivator, pCaller ); - SetActive( false ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CAI_Relationship::RevertToDefaultRelationship( CBaseEntity *pActivator, CBaseEntity *pCaller ) -{ - if ( m_bIsActive ) - { - ChangeRelationships( -1, REVERTING_TO_DEFAULT, pActivator, pCaller ); - SetActive( false ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CAI_Relationship::UpdateOnRemove() -{ - gEntList.RemoveListenerEntity( this ); - // @TODO (toml 07-21-04): Should this actually revert on kill? - // RevertRelationship(); - BaseClass::UpdateOnRemove(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CAI_Relationship::OnRestore() -{ - BaseClass::OnRestore(); - if ( m_bIsActive ) - { - gEntList.AddListenerEntity( this ); - } -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CAI_Relationship::IsASubject( CBaseEntity *pEntity ) -{ - if( pEntity->NameMatches( m_iszSubject ) ) - return true; - - if( pEntity->ClassMatches( m_iszSubject ) ) - return true; - - return false; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CAI_Relationship::IsATarget( CBaseEntity *pEntity ) -{ - if( pEntity->NameMatches( m_target ) ) - return true; - - if( pEntity->ClassMatches( m_target ) ) - return true; - - return false; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CAI_Relationship::OnEntitySpawned( CBaseEntity *pEntity ) -{ - // NOTE: This cannot use the procedural entity finding code since that only occurs on - // inputs and not passively. - - if ( IsATarget( pEntity ) || IsASubject( pEntity ) ) - { - ApplyRelationship(); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CAI_Relationship::OnEntityDeleted( CBaseEntity *pEntity ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: Translate special tokens for inputs -// Input : iszName - Name to check -// *pActivator - Activator -// *pCaller - Caller -// Output : CBaseEntity - Entity that matches (NULL if none) -//----------------------------------------------------------------------------- -#define ACTIVATOR_KEYNAME "!activator" -#define CALLER_KEYNAME "!caller" - -CBaseEntity *CAI_Relationship::FindEntityForProceduralName( string_t iszName, CBaseEntity *pActivator, CBaseEntity *pCaller ) -{ - // Handle the activator token - if ( iszName == AllocPooledString( ACTIVATOR_KEYNAME ) ) - return pActivator; - - // Handle the caller token - if ( iszName == AllocPooledString( CALLER_KEYNAME ) ) - return pCaller; - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Disclose the location of the target entity to the subject via a memory -// Input : *pSubject - Entity to gain the memory of the target's location -// *pTarget - Entity who's location will be disclosed -//----------------------------------------------------------------------------- -void CAI_Relationship::DiscloseNPCLocation( CBaseCombatCharacter *pSubject, CBaseCombatCharacter *pTarget ) -{ - if ( pSubject == NULL || pTarget == NULL ) - return; - - CAI_BaseNPC *pNPC = pSubject->MyNPCPointer(); - if ( pNPC != NULL ) - { - pNPC->UpdateEnemyMemory( pTarget, pTarget->GetAbsOrigin() ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CAI_Relationship::ChangeRelationships( int disposition, int iReverting, CBaseEntity *pActivator, CBaseEntity *pCaller ) -{ - if( iReverting != NOT_REVERTING && m_iPreviousDisposition == -1 ) - { - // Trying to revert without having ever set the relationships! - DevMsg( 2, "ai_relationship cannot revert changes before they are applied!\n"); - return; - } - - const int MAX_HANDLED = 512; - CUtlVectorFixed subjectList; - CUtlVectorFixed targetList; - - // Add any special subjects we found - CBaseEntity *pSpecialSubject = FindEntityForProceduralName( m_iszSubject, pActivator, pCaller ); - if ( pSpecialSubject && pSpecialSubject->MyCombatCharacterPointer() ) - { - subjectList.AddToTail( pSpecialSubject->MyCombatCharacterPointer() ); - } - - // Add any special targets we found - CBaseEntity *pSpecialTarget = FindEntityForProceduralName( m_target, pActivator, pCaller ); - if ( pSpecialTarget && pSpecialTarget->MyCombatCharacterPointer() ) - { - targetList.AddToTail( pSpecialTarget->MyCombatCharacterPointer() ); - } - - // ------------------------------- - // Search for targets and subjects - // ------------------------------- - - float radiusSq = Square( m_flRadius ); - - // Search players first - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - if ( subjectList.Count() == MAX_HANDLED || targetList.Count() == MAX_HANDLED ) - { - DevMsg( "Too many entities handled by ai_relationship %s\n", GetDebugName() ); - break; - } - - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - if ( pPlayer ) - { - if( IsASubject( pPlayer ) ) - { - if ( m_flRadius == 0.0 || GetAbsOrigin().DistToSqr( pPlayer->GetAbsOrigin() ) <= radiusSq ) - subjectList.AddToTail( pPlayer ); - } - else if( IsATarget( pPlayer ) ) - { - targetList.AddToTail( pPlayer ); - } - } - } - - // Search NPCs - for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - if ( subjectList.Count() == MAX_HANDLED || targetList.Count() == MAX_HANDLED ) - { - DevMsg( "Too many entities handled by ai_relationship %s\n", GetDebugName() ); - break; - } - - CAI_BaseNPC *pNPC = (g_AI_Manager.AccessAIs())[i]; - if ( pNPC ) - { - if( IsASubject( pNPC ) ) - { - if ( m_flRadius == 0.0 || GetAbsOrigin().DistToSqr( pNPC->GetAbsOrigin() ) <= radiusSq ) - subjectList.AddToTail( pNPC ); - } - else if( IsATarget( pNPC ) ) - { - targetList.AddToTail( pNPC ); - } - } - } - - // If either list is still empty, we have a problem. - if( subjectList.Count() == 0 ) - { - DevMsg( 2, "ai_relationship '%s' finds no subject(s) called: %s\n", GetDebugName(), STRING( m_iszSubject ) ); - return; - } - else if ( targetList.Count() == 0 ) - { - DevMsg( 2, "ai_relationship '%s' finds no target(s) called: %s\n", GetDebugName(), STRING( m_target ) ); - return; - } - - // Ok, lists are populated. Apply all relationships. - for ( int i = 0 ; i < subjectList.Count(); i++ ) - { - CBaseCombatCharacter *pSubject = subjectList[ i ]; - - for ( int j = 0 ; j < targetList.Count(); j++ ) - { - CBaseCombatCharacter *pTarget = targetList[ j ]; - - if ( m_iPreviousDisposition == -1 && iReverting == NOT_REVERTING ) - { - // Set previous disposition. - m_iPreviousDisposition = pSubject->IRelationType( pTarget ); - m_iPreviousRank = pSubject->IRelationPriority( pTarget ); - } - - if ( iReverting == REVERTING_TO_PREV ) - { - pSubject->AddEntityRelationship( pTarget, (Disposition_t)m_iPreviousDisposition, m_iPreviousRank ); - - if( m_bReciprocal ) - { - pTarget->AddEntityRelationship( pSubject, (Disposition_t)m_iPreviousDisposition, m_iPreviousRank ); - } - } - else if ( iReverting == REVERTING_TO_DEFAULT ) - { - pSubject->RemoveEntityRelationship( pTarget ); - - if( m_bReciprocal ) - { - pTarget->RemoveEntityRelationship( pSubject ); - } - } - else if( pSubject->IRelationType(pTarget) != disposition || - pSubject->IRelationPriority(pTarget) != m_iRank || - HasSpawnFlags( SF_RELATIONSHIP_NOTIFY_SUBJECT ) || - HasSpawnFlags( SF_RELATIONSHIP_NOTIFY_TARGET ) ) - { - // Apply the relationship to the subject - pSubject->AddEntityRelationship( pTarget, (Disposition_t)disposition, m_iRank ); - - // Make the subject aware of the target - if ( HasSpawnFlags( SF_RELATIONSHIP_NOTIFY_SUBJECT ) ) - { - DiscloseNPCLocation( pSubject, pTarget ); - } - - // Make the target aware of the subject - if ( HasSpawnFlags( SF_RELATIONSHIP_NOTIFY_TARGET ) ) - { - DiscloseNPCLocation( pTarget, pSubject ); - } - - // This relationship is applied to target and subject alike - if ( m_bReciprocal ) - { - // Apply the relationship to the target - pTarget->AddEntityRelationship( pSubject, (Disposition_t)disposition, m_iRank ); - } - } - } - } -} - diff --git a/game/server/ai_route.cpp b/game/server/ai_route.cpp deleted file mode 100644 index eda083918..000000000 --- a/game/server/ai_route.cpp +++ /dev/null @@ -1,683 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "ai_link.h" -#include "ai_navtype.h" -#include "ai_waypoint.h" -#include "ai_pathfinder.h" -#include "ai_navgoaltype.h" -#include "ai_routedist.h" -#include "ai_route.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -BEGIN_SIMPLE_DATADESC(CAI_Path) - // m_Waypoints (reconsititute on load) - DEFINE_FIELD( m_goalTolerance, FIELD_FLOAT ), - DEFINE_CUSTOM_FIELD( m_activity, ActivityDataOps() ), - DEFINE_FIELD( m_target, FIELD_EHANDLE ), - DEFINE_FIELD( m_sequence, FIELD_INTEGER ), - DEFINE_FIELD( m_vecTargetOffset, FIELD_VECTOR ), - DEFINE_FIELD( m_waypointTolerance, FIELD_FLOAT ), - DEFINE_CUSTOM_FIELD( m_arrivalActivity, ActivityDataOps() ), - DEFINE_FIELD( m_arrivalSequence, FIELD_INTEGER ), - // m_iLastNodeReached - DEFINE_FIELD( m_bGoalPosSet, FIELD_BOOLEAN ), - DEFINE_FIELD( m_goalPos, FIELD_POSITION_VECTOR), - DEFINE_FIELD( m_bGoalTypeSet, FIELD_BOOLEAN ), - DEFINE_FIELD( m_goalType, FIELD_INTEGER ), - DEFINE_FIELD( m_goalFlags, FIELD_INTEGER ), - DEFINE_FIELD( m_routeStartTime, FIELD_TIME ), - DEFINE_FIELD( m_goalDirection, FIELD_VECTOR ), - DEFINE_FIELD( m_goalDirectionTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_goalSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_goalSpeedTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_goalStoppingDistance, FIELD_FLOAT ), -END_DATADESC() - -//----------------------------------------------------------------------------- -AI_Waypoint_t CAI_Path::gm_InvalidWaypoint( Vector(0,0,0), 0, NAV_NONE, 0, 0 ); - -//----------------------------------------------------------------------------- - -void CAI_Path::SetWaypoints(AI_Waypoint_t* route, bool fSetGoalFromLast) -{ - m_Waypoints.Set(route); - - AI_Waypoint_t *pLast = m_Waypoints.GetLast(); - if ( pLast ) - { - pLast->flPathDistGoal = -1; - if ( fSetGoalFromLast ) - { - if ( pLast ) - { - m_bGoalPosSet = false; - pLast->ModifyFlags( bits_WP_TO_GOAL, true ); - SetGoalPosition(pLast->GetPos()); - } - } - } - - AssertRouteValid( m_Waypoints.GetFirst() ); -} - -//----------------------------------------------------------------------------- - -void CAI_Path::PrependWaypoints( AI_Waypoint_t *pWaypoints ) -{ - m_Waypoints.PrependWaypoints( pWaypoints ); - AI_Waypoint_t *pLast = m_Waypoints.GetLast(); - pLast->flPathDistGoal = -1; - - AssertRouteValid( m_Waypoints.GetFirst() ); -} - -//----------------------------------------------------------------------------- - -void CAI_Path::PrependWaypoint( const Vector &newPoint, Navigation_t navType, unsigned waypointFlags ) -{ - m_Waypoints.PrependWaypoint( newPoint, navType, waypointFlags ); - AI_Waypoint_t *pLast = m_Waypoints.GetLast(); - pLast->flPathDistGoal = -1; - - AssertRouteValid( m_Waypoints.GetFirst() ); -} - -//----------------------------------------------------------------------------- - -float CAI_Path::GetPathLength() -{ - AI_Waypoint_t *pLast = m_Waypoints.GetLast(); - if ( pLast && pLast->flPathDistGoal == -1 ) - { - ComputeRouteGoalDistances( pLast ); - } - AI_Waypoint_t *pCurrent = GetCurWaypoint(); - return ( ( pCurrent ) ? pCurrent->flPathDistGoal : 0 ); -} - -//----------------------------------------------------------------------------- - -float CAI_Path::GetPathDistanceToGoal( const Vector &startPos ) -{ - AI_Waypoint_t *pCurrent = GetCurWaypoint(); - if ( pCurrent ) - { - return ( GetPathLength() + ComputePathDistance(pCurrent->NavType(), startPos, pCurrent->GetPos()) ); - } - return 0; -} - -//----------------------------------------------------------------------------- - -Activity CAI_Path::SetMovementActivity(Activity activity) -{ - Assert( activity != ACT_RESET && activity != ACT_INVALID ); - //Msg("Set movement to %s\n", ActivityList_NameForIndex(activity) ); - - m_sequence = ACT_INVALID; - return (m_activity = activity); -} - -//----------------------------------------------------------------------------- - -Activity CAI_Path::GetArrivalActivity( ) const -{ - if ( !m_Waypoints.IsEmpty() ) - { - return m_arrivalActivity; - } - return ACT_INVALID; -} - -//----------------------------------------------------------------------------- - -void CAI_Path::SetArrivalActivity(Activity activity) -{ - m_arrivalActivity = activity; - m_arrivalSequence = ACT_INVALID; -} - -//----------------------------------------------------------------------------- - -int CAI_Path::GetArrivalSequence( ) const -{ - if ( !m_Waypoints.IsEmpty() ) - { - return m_arrivalSequence; - } - return ACT_INVALID; -} - -//----------------------------------------------------------------------------- - -void CAI_Path::SetArrivalSequence( int sequence ) -{ - m_arrivalSequence = sequence; -} - - -//----------------------------------------------------------------------------- - -void CAI_Path::SetGoalDirection( const Vector &goalDirection ) -{ - m_goalDirectionTarget = NULL; - m_goalDirection = goalDirection; - VectorNormalize( m_goalDirection ); - /* - AI_Waypoint_t *pLast = m_Waypoints.GetLast(); - if ( pLast ) - { - NDebugOverlay::Box( pLast->vecLocation, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), 0,0,255, 0, 2.0 ); - NDebugOverlay::Line( pLast->vecLocation, pLast->vecLocation + m_goalDirection * 32, 0,0,255, true, 2.0 ); - } - */ -} - - -//----------------------------------------------------------------------------- - -void CAI_Path::SetGoalDirection( CBaseEntity *pTarget ) -{ - m_goalDirectionTarget = pTarget; - - if (pTarget) - { - AI_Waypoint_t *pLast = m_Waypoints.GetLast(); - if ( pLast ) - { - m_goalDirection = pTarget->GetAbsOrigin() - pLast->vecLocation; - VectorNormalize( m_goalDirection ); - /* - NDebugOverlay::Box( pLast->vecLocation, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), 0,0,255, 0, 2.0 ); - NDebugOverlay::Line( pLast->vecLocation, pLast->vecLocation + m_goalDirection * 32, 0,0,255, true, 2.0 ); - */ - } - } -} - -//----------------------------------------------------------------------------- - -Vector CAI_Path::GetGoalDirection( const Vector &startPos ) -{ - if (m_goalDirectionTarget) - { - AI_Waypoint_t *pLast = m_Waypoints.GetLast(); - if ( pLast ) - { - AI_Waypoint_t *pPrev = pLast->GetPrev(); - if (pPrev) - { - Vector goalDirection = m_goalDirectionTarget->GetAbsOrigin() - pPrev->vecLocation; - VectorNormalize( goalDirection ); - return goalDirection; - } - else - { - Vector goalDirection = m_goalDirectionTarget->GetAbsOrigin() - startPos; - VectorNormalize( goalDirection ); - return goalDirection; - } - } - } - else if (m_goalDirection == vec3_origin) - { - // Assert(0); // comment out the default directions in SetGoal() to find test cases for missing initialization - AI_Waypoint_t *pLast = m_Waypoints.GetLast(); - if ( pLast ) - { - AI_Waypoint_t *pPrev = pLast->GetPrev(); - if (pPrev) - { - Vector goalDirection = pLast->vecLocation - pPrev->vecLocation; - VectorNormalize( goalDirection ); - return goalDirection; - } - else - { - Vector goalDirection =pLast->vecLocation - startPos; - VectorNormalize( goalDirection ); - return goalDirection; - } - } - } - - return m_goalDirection; -} - -//----------------------------------------------------------------------------- - -void CAI_Path::SetGoalSpeed( float flSpeed ) -{ - m_goalSpeed = flSpeed; -} - - -//----------------------------------------------------------------------------- - -void CAI_Path::SetGoalSpeed( CBaseEntity *pTarget ) -{ - m_goalSpeedTarget = pTarget; -} - -//----------------------------------------------------------------------------- - -float CAI_Path::GetGoalSpeed( const Vector &startPos ) -{ - if (m_goalSpeedTarget) - { - Vector goalDirection = GetGoalDirection( startPos ); - Vector targetVelocity = m_goalSpeedTarget->GetSmoothedVelocity(); - float dot = DotProduct( goalDirection, targetVelocity ); - dot = MAX( 0.0f, dot ); - // return a relative impact speed of m_goalSpeed - if (m_goalSpeed > 0.0) - { - return dot + m_goalSpeed; - } - return dot; - } - return m_goalSpeed; -} - - - -//----------------------------------------------------------------------------- - -void CAI_Path::SetGoalStoppingDistance( float flDistance ) -{ - m_goalStoppingDistance = flDistance; -} - -//----------------------------------------------------------------------------- - -float CAI_Path::GetGoalStoppingDistance( ) const -{ - return m_goalStoppingDistance; -} - - -//----------------------------------------------------------------------------- -const Vector &CAI_Path::CurWaypointPos() const -{ - if ( GetCurWaypoint() ) - return GetCurWaypoint()->GetPos(); - AssertMsg(0, "Invalid call to CurWaypointPos()"); - return gm_InvalidWaypoint.GetPos(); -} - -//----------------------------------------------------------------------------- -const Vector &CAI_Path::NextWaypointPos() const -{ - if ( GetCurWaypoint() && GetCurWaypoint()->GetNext()) - return GetCurWaypoint()->GetNext()->GetPos(); - static Vector invalid( 0, 0, 0 ); - AssertMsg(0, "Invalid call to NextWaypointPos()"); - return gm_InvalidWaypoint.GetPos(); -} - -//----------------------------------------------------------------------------- -float CAI_Path::CurWaypointYaw() const -{ - return GetCurWaypoint()->flYaw; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_Path::SetGoalPosition(const Vector &goalPos) -{ - -#ifdef _DEBUG - // Make sure goal position isn't set more than once - if (m_bGoalPosSet == true) - { - DevMsg( "GetCurWaypoint Goal Position Set Twice!\n"); - } -#endif - - m_bGoalPosSet = true; - VectorAdd( goalPos, m_vecTargetOffset, m_goalPos ); -} - -//----------------------------------------------------------------------------- -// Purpose: Sets last node as goal and goal position -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_Path::SetLastNodeAsGoal(bool bReset) -{ - #ifdef _DEBUG - // Make sure goal position isn't set more than once - if (!bReset && m_bGoalPosSet == true) - { - DevMsg( "GetCurWaypoint Goal Position Set Twice!\n"); - } - #endif - - // Find the last node - if (GetCurWaypoint()) - { - AI_Waypoint_t* waypoint = GetCurWaypoint(); - - while (waypoint) - { - if (!waypoint->GetNext()) - { - m_goalPos = waypoint->GetPos(); - m_bGoalPosSet = true; - waypoint->ModifyFlags( bits_WP_TO_GOAL, true ); - return; - } - waypoint = waypoint->GetNext(); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Explicitly change the goal position w/o check -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_Path::ResetGoalPosition(const Vector &goalPos) -{ - m_bGoalPosSet = true; - VectorAdd( goalPos, m_vecTargetOffset, m_goalPos ); -} - - -//----------------------------------------------------------------------------- -// Returns the *base* goal position (without the offset applied) -//----------------------------------------------------------------------------- -const Vector& CAI_Path::BaseGoalPosition() const -{ -#ifdef _DEBUG - // Make sure goal position was set - if (m_bGoalPosSet == false) - { - DevMsg( "GetCurWaypoint Goal Position Never Set!\n"); - } -#endif - - // FIXME: A little risky; store the base if this becomes a problem - static Vector vecResult; - VectorSubtract( m_goalPos, m_vecTargetOffset, vecResult ); - return vecResult; -} - - -//----------------------------------------------------------------------------- - // Returns the *actual* goal position (with the offset applied) -//----------------------------------------------------------------------------- -const Vector & CAI_Path::ActualGoalPosition(void) const -{ -#ifdef _DEBUG - // Make sure goal position was set - if (m_bGoalPosSet == false) - { - DevMsg( "GetCurWaypoint Goal Position Never Set!\n"); - } -#endif - - return m_goalPos; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_Path::SetGoalType(GoalType_t goalType) -{ - -#ifdef _DEBUG - // Make sure goal position isn't set more than once - if (m_goalType != GOALTYPE_NONE && goalType != GOALTYPE_NONE ) - { - DevMsg( "GetCurWaypoint Goal Type Set Twice!\n"); - } -#endif - - if (m_goalType != GOALTYPE_NONE) - { - m_routeStartTime = gpGlobals->curtime; - m_bGoalTypeSet = true; - } - else - m_bGoalTypeSet = false; - - m_goalType = goalType; - -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -GoalType_t CAI_Path::GoalType(void) const -{ - return m_goalType; -} - - -//----------------------------------------------------------------------------- - -void CAI_Path::Advance( void ) -{ - if ( CurWaypointIsGoal() ) - return; - - // ------------------------------------------------------- - // If I have another waypoint advance my path - // ------------------------------------------------------- - if (GetCurWaypoint()->GetNext()) - { - AI_Waypoint_t *pNext = GetCurWaypoint()->GetNext(); - - // If waypoint was a node take note of it - if (GetCurWaypoint()->Flags() & bits_WP_TO_NODE) - { - m_iLastNodeReached = GetCurWaypoint()->iNodeID; - } - - delete GetCurWaypoint(); - SetWaypoints(pNext); - - return; - } - // ------------------------------------------------- - // This is an error catch that should *not* happen - // It means a route was created with no goal - // ------------------------------------------------- - else - { - DevMsg( "!!ERROR!! Force end of route with no goal!\n"); - GetCurWaypoint()->ModifyFlags( bits_WP_TO_GOAL, true ); - } - - AssertRouteValid( m_Waypoints.GetFirst() ); -} - - - -//----------------------------------------------------------------------------- -// Purpose: Clears the route and resets all its fields to default values -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_Path::Clear( void ) -{ - m_Waypoints.RemoveAll(); - - m_goalType = GOALTYPE_NONE; // Type of goal - m_goalPos = vec3_origin; // Our ultimate goal position - m_bGoalPosSet = false; // Was goal position set - m_bGoalTypeSet = false; // Was goal position set - m_goalFlags = false; - m_vecTargetOffset = vec3_origin; - m_routeStartTime = FLT_MAX; - - m_goalTolerance = 0.0; // How close do we need to get to the goal - // FIXME: split m_goalTolerance into m_buildTolerance and m_moveTolerance, let them be seperatly controllable. - - m_activity = ACT_INVALID; - m_sequence = ACT_INVALID; - m_target = NULL; - - m_arrivalActivity = ACT_INVALID; - m_arrivalSequence = ACT_INVALID; - - m_goalDirectionTarget = NULL; - m_goalDirection = vec3_origin; - - m_goalSpeedTarget = NULL; - m_goalSpeed = -1.0f; // init to an invalid speed - - m_goalStoppingDistance = 0.0; // How close to we want to get to the goal -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -Navigation_t CAI_Path::CurWaypointNavType() const -{ - if (!GetCurWaypoint()) - { - return NAV_NONE; - } - else - { - return GetCurWaypoint()->NavType(); - } -} - -int CAI_Path::CurWaypointFlags() const -{ - if (!GetCurWaypoint()) - { - return 0; - } - else - { - return GetCurWaypoint()->Flags(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Get the goal's flags -// Output : unsigned -//----------------------------------------------------------------------------- -unsigned CAI_Path::GoalFlags( void ) const -{ - return m_goalFlags; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true if current waypoint is my goal -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CAI_Path::CurWaypointIsGoal( void ) const -{ -// Assert( GetCurWaypoint() ); - - if( !GetCurWaypoint() ) - return false; - - - if ( GetCurWaypoint()->Flags() & bits_WP_TO_GOAL ) - { - #ifdef _DEBUG - if (GetCurWaypoint()->GetNext()) - { - DevMsg( "!!ERROR!! Goal is not last waypoint!\n"); - } - if ((GetCurWaypoint()->GetPos() - m_goalPos).Length() > 0.1) - { - DevMsg( "!!ERROR!! Last waypoint isn't in goal position!\n"); - } - #endif - return true; - } - if ( GetCurWaypoint()->Flags() & bits_WP_TO_PATHCORNER ) - { - // UNDONE: Refresh here or somewhere else? - } -#ifdef _DEBUG - if (!GetCurWaypoint()->GetNext()) - { - DevMsg( "!!ERROR!! GetCurWaypoint has no goal!\n"); - } -#endif - - return false; -} - - -//----------------------------------------------------------------------------- -// Computes the goal distance for each waypoint along the route -//----------------------------------------------------------------------------- -void CAI_Path::ComputeRouteGoalDistances(AI_Waypoint_t *pGoalWaypoint) -{ - // The goal distance is the distance from any waypoint to the goal waypoint - - // Backup through the list and calculate distance to goal - AI_Waypoint_t *pPrev; - AI_Waypoint_t *pCurWaypoint = pGoalWaypoint; - pCurWaypoint->flPathDistGoal = 0; - while (pCurWaypoint->GetPrev()) - { - pPrev = pCurWaypoint->GetPrev(); - - float flWaypointDist = ComputePathDistance(pCurWaypoint->NavType(), pPrev->GetPos(), pCurWaypoint->GetPos()); - pPrev->flPathDistGoal = pCurWaypoint->flPathDistGoal + flWaypointDist; - - pCurWaypoint = pPrev; - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: Constructor -// Input : -// Output : -//----------------------------------------------------------------------------- -CAI_Path::CAI_Path() -{ - m_goalType = GOALTYPE_NONE; // Type of goal - m_goalPos = vec3_origin; // Our ultimate goal position - m_goalTolerance = 0.0; // How close do we need to get to the goal - m_activity = ACT_INVALID; // The activity to use during motion - m_sequence = ACT_INVALID; - m_target = NULL; - m_goalFlags = 0; - m_routeStartTime = FLT_MAX; - m_arrivalActivity = ACT_INVALID; - m_arrivalSequence = ACT_INVALID; - - m_iLastNodeReached = NO_NODE; - - m_waypointTolerance = DEF_WAYPOINT_TOLERANCE; - -} - -CAI_Path::~CAI_Path() -{ - DeleteAll( GetCurWaypoint() ); -} - - diff --git a/game/server/ai_route.h b/game/server/ai_route.h deleted file mode 100644 index 32ef9a33c..000000000 --- a/game/server/ai_route.h +++ /dev/null @@ -1,190 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_ROUTE_H -#define AI_ROUTE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_basenpc.h" -#include "mathlib/vector.h" -#include "ai_network.h" -#include "ai_node.h" -#include "ai_waypoint.h" - -struct AI_Waypoint_t; -struct OverlayLine_t; - -class CAI_BaseNPC; - -//============================================================================= -// >> CAI_Path -//============================================================================= - -#define DEF_WAYPOINT_TOLERANCE (0.1) - -class CAI_Path -{ -//----------------------------------------------------------------- - -public: - - void SetWaypoints(AI_Waypoint_t* route, bool fSetGoalFromLast = false) ; - - void PrependWaypoints( AI_Waypoint_t *pWaypoints ); - void PrependWaypoint( const Vector &newPoint, Navigation_t navType, unsigned waypointFlags ); - - bool IsEmpty() const { return m_Waypoints.IsEmpty(); } - - AI_Waypoint_t * GetCurWaypoint() { return m_Waypoints.GetFirst(); } - const AI_Waypoint_t *GetCurWaypoint() const { return m_Waypoints.GetFirst(); } - - AI_Waypoint_t * GetGoalWaypoint() { return m_Waypoints.GetLast(); } - const AI_Waypoint_t *GetGoalWaypoint() const { return m_Waypoints.GetLast(); } - - const Vector & CurWaypointPos() const; - const Vector & NextWaypointPos() const; - float CurWaypointYaw() const; - int CurWaypointFlags() const; - Navigation_t CurWaypointNavType() const; - - AI_Waypoint_t * GetTransitionWaypoint(); - - //--------------------------------- - - float GetPathLength(); - float GetPathDistanceToGoal( const Vector &); - - float GetStartTime() const { return m_routeStartTime; } - - //--------------------------------- - // How close do we need to get to the goal - //--------------------------------- - void SetGoalTolerance(float tolerance) { m_goalTolerance = tolerance; } - float GetGoalTolerance() const { return m_goalTolerance; } - - void SetWaypointTolerance(float tolerance) { m_waypointTolerance = tolerance; } - float GetWaypointTolerance() const { return m_waypointTolerance; } - - //--------------------------------- - // The activity to use during motion - //--------------------------------- - Activity GetMovementActivity() const { return m_activity; } - Activity SetMovementActivity(Activity activity); - int GetMovementSequence() const { return m_sequence; } - int SetMovementSequence(int sequence) { return (m_sequence = sequence); } - - Activity GetArrivalActivity( ) const; - void SetArrivalActivity(Activity activity); - int GetArrivalSequence( ) const; - void SetArrivalSequence(int sequence); - - void SetGoalDirection( const Vector &goalDirection ); - void SetGoalDirection( CBaseEntity *pTarget ); - Vector GetGoalDirection( const Vector &startPos ); - - void SetGoalSpeed( float flSpeed ); - void SetGoalSpeed( CBaseEntity *pTarget ); - float GetGoalSpeed( const Vector &startPos ); - - void SetGoalStoppingDistance( float flDistance ); - float GetGoalStoppingDistance( ) const; - - //--------------------------------- - // Target of this path - //--------------------------------- - void SetTarget(CBaseEntity * pTarget ) { m_target = pTarget; } - void ClearTarget() { m_target = NULL; m_vecTargetOffset = vec3_origin; } - void SetTargetOffset( const Vector &vecOffset) { m_vecTargetOffset = vecOffset; } - CBaseEntity * GetTarget() { return m_target; } - - void SetGoalType(GoalType_t goalType); // Set the goal type - void SetGoalPosition(const Vector &goalPos); // Set the goal position - void SetLastNodeAsGoal(bool bReset = false); // Sets last node as goal and goal position - void ResetGoalPosition(const Vector &goalPos); // Reset the goal position - - // Returns the *base* goal position (without the offset applied) - const Vector& BaseGoalPosition() const; - - // Returns the *actual* goal position (with the offset applied) - const Vector & ActualGoalPosition(void) const; // Get the goal position - - GoalType_t GoalType(void) const; // Get the goal type - - void SetGoalFlags( unsigned flags ) { m_goalFlags = flags; } - unsigned GoalFlags( void ) const; // Get the goal flags - - void Advance( void ); // Advance to next waypoint if possible - - bool CurWaypointIsGoal(void) const; - - void Clear(void); - - CAI_Path(); - ~CAI_Path(); - - //--------------------------------- - - int GetLastNodeReached() { return m_iLastNodeReached; } - void ClearWaypoints() - { - m_Waypoints.RemoveAll(); - m_iLastNodeReached = NO_NODE; - } - -private: - - // Computes the goal distance for each waypoint along the route - static void ComputeRouteGoalDistances(AI_Waypoint_t *pGoalWaypoint); - - //--------------------------------- - CAI_WaypointList m_Waypoints; - - //--------------------------------- - float m_goalTolerance; // How close do we need to get to the goal - Activity m_activity; // The activity to use during motion - int m_sequence; // The sequence to use during motion - EHANDLE m_target; // Target of this path - Vector m_vecTargetOffset; // offset from the target in world space - float m_waypointTolerance; - - //--------------------------------- - Activity m_arrivalActivity; - int m_arrivalSequence; - - //--------------------------------- - int m_iLastNodeReached; // What was the last node that I reached - - bool m_bGoalPosSet; // Was goal position set (used to check for errors) - Vector m_goalPos; // Our ultimate goal position - - bool m_bGoalTypeSet; // Was goal position set (used to check for errors) - GoalType_t m_goalType; // Type of goal - - unsigned m_goalFlags; // Goal flags - - //--------------------------------- - float m_routeStartTime; - - //--------------------------------- - Vector m_goalDirection; - EHANDLE m_goalDirectionTarget; - - float m_goalSpeed; - EHANDLE m_goalSpeedTarget; - - float m_goalStoppingDistance; // Distance we want to stop before the goal - - //--------------------------------- - static AI_Waypoint_t gm_InvalidWaypoint; - - DECLARE_SIMPLE_DATADESC(); - -}; - -#endif // AI_ROUTE_H diff --git a/game/server/ai_routedist.h b/game/server/ai_routedist.h deleted file mode 100644 index c5da25e0f..000000000 --- a/game/server/ai_routedist.h +++ /dev/null @@ -1,61 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_ROUTEDIST_H -#define AI_ROUTEDIST_H - -#include "ai_navtype.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -// ---------------------------------------------------------------------------- -// Computes the route distance + route direction based on nav type -// FIXME: Where should this go? -// ---------------------------------------------------------------------------- -inline float ComputePathDistance( Navigation_t navType, const Vector &start, const Vector &end ) -{ - if (navType == NAV_GROUND) - { - return (end - start).Length2D(); - } - else - { - return (end - start).Length(); - } -} - -inline void ComputePathVector( Navigation_t navType, const Vector &start, const Vector &end, Vector *pDelta ) -{ - if (navType == NAV_GROUND) - { - Vector2DSubtract( end.AsVector2D(), start.AsVector2D(), pDelta->AsVector2D() ); - pDelta->z = 0.0f; - } - else - { - VectorSubtract( end, start, *pDelta ); - } -} - -inline float ComputePathDirection( Navigation_t navType, const Vector &start, const Vector &end, Vector *pDirection ) -{ - if (navType == NAV_GROUND) - { - VectorSubtract( end, start, *pDirection ); - pDirection->z = 0.0f; - return Vector2DNormalize( pDirection->AsVector2D() ); - } - else - { - VectorSubtract( end, start, *pDirection ); - return VectorNormalize( *pDirection ); - } -} - -#endif // AI_ROUTEDIST_H diff --git a/game/server/ai_saverestore.cpp b/game/server/ai_saverestore.cpp deleted file mode 100644 index 64eecb862..000000000 --- a/game/server/ai_saverestore.cpp +++ /dev/null @@ -1,191 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -#include "isaverestore.h" -#include "saverestore_utlvector.h" -#include "ai_saverestore.h" -#include "ai_basenpc.h" -#include "ai_squad.h" -#include "ai_network.h" -#include "ai_networkmanager.h" - -#ifdef HL2_DLL -#include "npc_playercompanion.h" -#endif // HL2_DLL - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -static short AI_SAVE_RESTORE_VERSION = 2; - -//----------------------------------------------------------------------------- - -class CAI_SaveRestoreBlockHandler : public CDefSaveRestoreBlockHandler -{ -public: - const char *GetBlockName() - { - return "AI"; - } - - //--------------------------------- - - void Save( ISave *pSave ) - { - pSave->StartBlock( "Squads" ); - short nSquads = (short)g_AI_SquadManager.NumSquads(); - pSave->WriteShort( &nSquads ); - - AISquadsIter_t iter; - string_t squadName; - CAI_Squad* pSquad = g_AI_SquadManager.GetFirstSquad( &iter ); - while (pSquad) - { - squadName = MAKE_STRING( pSquad->GetName() ); - pSave->WriteString( "", &squadName ); // Strings require a header to be read properly - pSave->WriteAll( pSquad ); - pSquad = g_AI_SquadManager.GetNextSquad( &iter ); - } - - pSave->EndBlock(); - - //--------------------------------- - - pSave->StartBlock( "Enemies" ); - short nMemories = 0; - - CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); - int i; - - for ( i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - if ( ppAIs[i]->GetEnemies() ) - nMemories++; - } - - pSave->WriteShort( &nMemories ); - - for ( i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - if ( ppAIs[i]->GetEnemies() ) - { - CBaseEntity *p = ppAIs[i]; - pSave->WriteEntityPtr( &p ); - pSave->WriteAll( ppAIs[i]->GetEnemies() ); - } - } - pSave->EndBlock(); - } - - //--------------------------------- - - void WriteSaveHeaders( ISave *pSave ) - { - pSave->WriteShort( &AI_SAVE_RESTORE_VERSION ); - } - - //--------------------------------- - - void ReadRestoreHeaders( IRestore *pRestore ) - { - // No reason why any future version shouldn't try to retain backward compatability. The default here is to not do so. - short version; - pRestore->ReadShort( &version ); - m_fDoLoad = ( version == AI_SAVE_RESTORE_VERSION ); - } - - //--------------------------------- - - void Restore( IRestore *pRestore, bool createPlayers ) - { - // Initialize the squads (as there's no spawn) - CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); - int i; - - for ( i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - ppAIs[i]->InitSquad(); - } - - if ( m_fDoLoad ) - { - pRestore->StartBlock(); - // Fixup all the squads - CAI_Squad ignored; - CAI_Squad *pSquad; - string_t squadName; - int nSavedSquads = pRestore->ReadShort(); - - while ( nSavedSquads-- ) - { - int sizeData = pRestore->SkipHeader(); - pRestore->ReadString( &squadName, 1, sizeData ); - pSquad = g_AI_SquadManager.FindSquad( squadName ); - if ( !pSquad ) - pSquad = &ignored; // if all of the AIs in a squad failed to spawn, there would be no squad - pRestore->ReadAll( pSquad ); - } - pRestore->EndBlock(); - - //--------------------------------- - // Now load memories for unsquadded npcs - - pRestore->StartBlock(); - CAI_Enemies ignoredMem; - short nMemories = pRestore->ReadShort(); - - CBaseEntity *pAI; - - while ( nMemories-- ) - { - pRestore->ReadEntityPtr( &pAI ); - - if ( pAI ) - pRestore->ReadAll( ((CAI_BaseNPC *)pAI)->GetEnemies() ); - else - pRestore->ReadAll( &ignoredMem ); // AI probably failed to spawn - } - - pRestore->EndBlock(); - } - - if ( g_AI_Manager.NumAIs() && g_pBigAINet->NumNodes() == 0 && !g_pAINetworkManager->NetworksLoaded() ) - { - Msg( "***\n"); - Msg( "ERROR: Loaded save game with no node graph. Load map and build node graph first!\n"); - Msg( "***\n"); - CAI_BaseNPC::m_nDebugBits |= bits_debugDisableAI; - g_pAINetworkManager->MarkDontSaveGraph(); - } - } - - void PostRestore( void ) - { -#ifdef HL2_DLL - // We need this list to be regenerated - OverrideMoveCache_ForceRepopulateList(); -#endif // HL2_DLL - } - -private: - bool m_fDoLoad; -}; - -//----------------------------------------------------------------------------- - -CAI_SaveRestoreBlockHandler g_AI_SaveRestoreBlockHandler; - -//------------------------------------- - -ISaveRestoreBlockHandler *GetAISaveRestoreBlockHandler() -{ - return &g_AI_SaveRestoreBlockHandler; -} - -//============================================================================= diff --git a/game/server/ai_saverestore.h b/game/server/ai_saverestore.h deleted file mode 100644 index bd5fa73a5..000000000 --- a/game/server/ai_saverestore.h +++ /dev/null @@ -1,17 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_SAVERESTORE_H -#define AI_SAVERESTORE_H - -#if defined( _WIN32 ) -#pragma once -#endif - -ISaveRestoreBlockHandler *GetAISaveRestoreBlockHandler(); - -#endif // AI_SAVERESTORE_H diff --git a/game/server/ai_schedule.cpp b/game/server/ai_schedule.cpp deleted file mode 100644 index c79eea762..000000000 --- a/game/server/ai_schedule.cpp +++ /dev/null @@ -1,617 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Base combat character with no AI -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "convar.h" -#include "ai_basenpc.h" -#include "tier1/strtools.h" -#include "ai_activity.h" -#include "ai_schedule.h" -#include "ai_default.h" -#include "ai_hint.h" -#include "bitstring.h" -#include "stringregistry.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -//----------------------------------------------------------------------------- -// Init static variables -//----------------------------------------------------------------------------- -CAI_SchedulesManager g_AI_SchedulesManager; - -//----------------------------------------------------------------------------- -// Purpose: Delete all the string registries -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_SchedulesManager::DestroyStringRegistries(void) -{ - CAI_BaseNPC::GetSchedulingSymbols()->Clear(); - CAI_BaseNPC::gm_SquadSlotNamespace.Clear(); - - delete CAI_BaseNPC::m_pActivitySR; - CAI_BaseNPC::m_pActivitySR = NULL; - CAI_BaseNPC::m_iNumActivities = 0; -} - -void CAI_SchedulesManager::CreateStringRegistries( void ) -{ - CAI_BaseNPC::GetSchedulingSymbols()->Clear(); - CAI_BaseNPC::gm_SquadSlotNamespace.Clear(); - - CAI_BaseNPC::m_pActivitySR = new CStringRegistry(); - CAI_BaseNPC::m_pEventSR = new CStringRegistry(); -} - -//----------------------------------------------------------------------------- -// Purpose: Load all the schedules -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_BaseNPC::InitSchedulingTables() -{ - CAI_BaseNPC::gm_ClassScheduleIdSpace.Init( "CAI_BaseNPC", CAI_BaseNPC::GetSchedulingSymbols() ); - CAI_BaseNPC::InitDefaultScheduleSR(); - CAI_BaseNPC::InitDefaultConditionSR(); - CAI_BaseNPC::InitDefaultTaskSR(); - CAI_BaseNPC::InitDefaultActivitySR(); - CAI_BaseNPC::InitDefaultSquadSlotSR(); -} - -bool CAI_SchedulesManager::LoadAllSchedules(void) -{ - // If I haven't loaded schedules yet - if (!CAI_SchedulesManager::allSchedules) - { - // Init defaults - CAI_BaseNPC::InitSchedulingTables(); - if (!CAI_BaseNPC::LoadDefaultSchedules()) - { - CAI_BaseNPC::m_nDebugBits |= bits_debugDisableAI; - DevMsg("ERROR: Mistake in default schedule definitions, AI Disabled.\n"); - } - -// UNDONE: enable this after the schedules are all loaded (right now some load in monster spawns) -#if 0 - // If not in developer mode, free the string memory. Otherwise - // keep it around for debugging information - if (!g_pDeveloper->GetInt()) - { - ClearStringRegistries(); - } -#endif - - } - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Creates and returns schedule of the given name -// This should eventually be replaced when we convert to -// non-hard coded schedules -// Input : -// Output : -//----------------------------------------------------------------------------- -CAI_Schedule *CAI_SchedulesManager::CreateSchedule(char *name, int schedule_id) -{ - // Allocate schedule - CAI_Schedule *pSched = new CAI_Schedule(name,schedule_id,CAI_SchedulesManager::allSchedules); - CAI_SchedulesManager::allSchedules = pSched; - - // Return schedule - return pSched; -} - -//----------------------------------------------------------------------------- -// Purpose: Given text name of a NPC state returns its ID number -// Input : -// Output : -//----------------------------------------------------------------------------- -int CAI_SchedulesManager::GetStateID(const char *state_name) -{ - if (!stricmp(state_name,"NONE")) { return NPC_STATE_NONE; } - else if (!stricmp(state_name,"IDLE")) { return NPC_STATE_IDLE; } - else if (!stricmp(state_name,"COMBAT")) { return NPC_STATE_COMBAT; } - else if (!stricmp(state_name,"PRONE")) { return NPC_STATE_PRONE; } - else if (!stricmp(state_name,"ALERT")) { return NPC_STATE_ALERT; } - else if (!stricmp(state_name,"SCRIPT")) { return NPC_STATE_SCRIPT; } - else if (!stricmp(state_name,"PLAYDEAD")) { return NPC_STATE_PLAYDEAD; } - else if (!stricmp(state_name,"DEAD")) { return NPC_STATE_DEAD; } - else return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: Given text name of a memory bit returns its ID number -// Input : -// Output : -//----------------------------------------------------------------------------- -int CAI_SchedulesManager::GetMemoryID(const char *state_name) -{ - if (!stricmp(state_name,"PROVOKED")) { return bits_MEMORY_PROVOKED; } - else if (!stricmp(state_name,"INCOVER")) { return bits_MEMORY_INCOVER; } - else if (!stricmp(state_name,"SUSPICIOUS")) { return bits_MEMORY_SUSPICIOUS; } - else if (!stricmp(state_name,"PATH_FAILED")) { return bits_MEMORY_PATH_FAILED; } - else if (!stricmp(state_name,"FLINCHED")) { return bits_MEMORY_FLINCHED; } - else if (!stricmp(state_name,"TOURGUIDE")) { return bits_MEMORY_TOURGUIDE; } - else if (!stricmp(state_name,"LOCKED_HINT")) { return bits_MEMORY_LOCKED_HINT; } - else if (!stricmp(state_name,"TURNING")) { return bits_MEMORY_TURNING; } - else if (!stricmp(state_name,"TURNHACK")) { return bits_MEMORY_TURNHACK; } - else if (!stricmp(state_name,"CUSTOM4")) { return bits_MEMORY_CUSTOM4; } - else if (!stricmp(state_name,"CUSTOM3")) { return bits_MEMORY_CUSTOM3; } - else if (!stricmp(state_name,"CUSTOM2")) { return bits_MEMORY_CUSTOM2; } - else if (!stricmp(state_name,"CUSTOM1")) { return bits_MEMORY_CUSTOM1; } - else return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *token - -// Output : int -//----------------------------------------------------------------------------- -int CAI_SchedulesManager::GetPathID( const char *token ) -{ - if ( !stricmp( token, "TRAVEL" ) ) { return PATH_TRAVEL; } - else if ( !stricmp( token, "LOS" ) ) { return PATH_LOS; } -// else if ( !stricmp( token, "FLANK" ) ) { return PATH_FLANK; } -// else if ( !stricmp( token, "FLANK_LOS" ) ) { return PATH_FLANK_LOS; } - else if ( !stricmp( token, "COVER" ) ) { return PATH_COVER; } -// else if ( !stricmp( token, "COVER_LOS" ) ) { return PATH_COVER_LOS; } - - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *token - -// Output : int -//----------------------------------------------------------------------------- -int CAI_SchedulesManager::GetGoalID( const char *token ) -{ - if ( !stricmp( token, "ENEMY" ) ) { return GOAL_ENEMY; } - else if ( !stricmp( token, "ENEMY_LKP" ) ) { return GOAL_ENEMY_LKP; } - else if ( !stricmp( token, "TARGET" ) ) { return GOAL_TARGET; } - else if ( !stricmp( token, "SAVED_POSITION" ) ) { return GOAL_SAVED_POSITION; } - - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: Read data on schedules -// As I'm parsing a human generated file, give a lot of error output -// Output: true - if data successfully read -// false - if data load fails -//----------------------------------------------------------------------------- - -bool CAI_SchedulesManager::LoadSchedulesFromBuffer( const char *prefix, char *pStartFile, CAI_ClassScheduleIdSpace *pIdSpace ) -{ - char token[1024]; - char save_token[1024]; - const char *pfile = engine->ParseFile(pStartFile, token, sizeof( token ) ); - - while (!stricmp("Schedule",token)) - { - pfile = engine->ParseFile(pfile, token, sizeof( token ) ); - - // ----------------------------- - // Check for duplicate schedule - // ----------------------------- - if (GetScheduleByName(token)) - { - DevMsg("ERROR: file contains a schedule (%s) that has already been defined!\n",token); - DevMsg(" Aborting schedule load.\n"); - Assert(0); - return false; - } - - int scheduleID = CAI_BaseNPC::GetScheduleID(token); - if (scheduleID == -1) - { - DevMsg( "ERROR: LoadSchd (%s): Unknown schedule type (%s)\n", prefix, token); - // FIXME: .sch's not being in code/perforce makes it hard to share branches between developers - // for now, just stop processing this entities schedules if one is found that isn't in the schedule registry - break; - // return false; - } - - CAI_Schedule *new_schedule = CreateSchedule(token,scheduleID); - - pfile = engine->ParseFile(pfile, token, sizeof( token ) ); - if (stricmp(token,"Tasks")) - { - DevMsg( "ERROR: LoadSchd (%s): (%s) Malformed AI Schedule. Expecting 'Tasks' keyword.\n",prefix,new_schedule->GetName()); - Assert(0); - return false; - } - - // ========================== - // Now read in the tasks - // ========================== - // Store in temp array until number of tasks is known - Task_t tempTask[50]; - int taskNum = 0; - - pfile = engine->ParseFile(pfile, token, sizeof( token ) ); - while ((token[0] != '\0') && (stricmp("Interrupts", token))) - { - // Convert generic ID to sub-class specific enum - int taskID = CAI_BaseNPC::GetTaskID(token); - tempTask[taskNum].iTask = (pIdSpace) ? pIdSpace->TaskGlobalToLocal(taskID) : AI_RemapFromGlobal( taskID ); - - // If not a valid condition, send a warning message - if (tempTask[taskNum].iTask == -1) - { - DevMsg( "ERROR: LoadSchd (%s): (%s) Unknown task %s!\n", prefix,new_schedule->GetName(), token); - Assert(0); - return false; - } - - Assert( AI_IdIsLocal( tempTask[taskNum].iTask ) ); - - // Read in the task argument - pfile = engine->ParseFile(pfile, token, sizeof( token ) ); - - if (!stricmp("Activity",token)) - { - // Skip the ";", but make sure it's present - pfile = engine->ParseFile(pfile, token, sizeof( token ) ); - if (stricmp(token,":")) - { - DevMsg( "ERROR: LoadSchd (%s): (%s) Malformed AI Schedule. Expecting ':' after type 'ACTIVITY.\n",prefix,new_schedule->GetName()); - Assert(0); - return false; - } - - // Load the activity and make sure its valid - pfile = engine->ParseFile(pfile, token, sizeof( token ) ); - tempTask[taskNum].flTaskData = CAI_BaseNPC::GetActivityID(token); - if (tempTask[taskNum].flTaskData == -1) - { - DevMsg( "ERROR: LoadSchd (%s): (%s) Unknown activity %s!\n", prefix,new_schedule->GetName(), token); - Assert(0); - return false; - } - } - else if (!stricmp("Task",token)) - { - // Skip the ";", but make sure it's present - pfile = engine->ParseFile(pfile, token, sizeof( token ) ); - if (stricmp(token,":")) - { - DevMsg( "ERROR: LoadSchd (%s): (%s) Malformed AI Schedule. Expecting ':' after type 'ACTIVITY.\n",prefix,new_schedule->GetName()); - Assert(0); - return false; - } - - // Load the activity and make sure its valid - pfile = engine->ParseFile(pfile, token, sizeof( token ) ); - - // Convert generic ID to sub-class specific enum - int taskID = CAI_BaseNPC::GetTaskID(token); - tempTask[taskNum].flTaskData = (pIdSpace) ? pIdSpace->TaskGlobalToLocal(taskID) : AI_RemapFromGlobal( taskID ); - - if (tempTask[taskNum].flTaskData == -1) - { - DevMsg( "ERROR: LoadSchd (%s): (%s) Unknown task %s!\n", prefix,new_schedule->GetName(), token); - Assert(0); - return false; - } - } - else if (!stricmp("Schedule",token)) - { - // Skip the ";", but make sure it's present - pfile = engine->ParseFile(pfile, token, sizeof( token ) ); - if (stricmp(token,":")) - { - DevMsg( "ERROR: LoadSchd (%s): (%s) Malformed AI Schedule. Expecting ':' after type 'ACTIVITY.\n",prefix,new_schedule->GetName()); - Assert(0); - return false; - } - - // Load the schedule and make sure its valid - pfile = engine->ParseFile(pfile, token, sizeof( token ) ); - - // Convert generic ID to sub-class specific enum - int schedID = CAI_BaseNPC::GetScheduleID(token); - tempTask[taskNum].flTaskData = (pIdSpace) ? pIdSpace->ScheduleGlobalToLocal(schedID) : AI_RemapFromGlobal( schedID ); - - if (tempTask[taskNum].flTaskData == -1) - { - DevMsg( "ERROR: LoadSchd %d (%s): (%s) Unknown shedule %s!\n", __LINE__, prefix,new_schedule->GetName(), token); - Assert(0); - return false; - } - } - else if (!stricmp("State",token)) - { - // Skip the ";", but make sure it's present - pfile = engine->ParseFile(pfile, token, sizeof( token ) ); - if (stricmp(token,":")) - { - DevMsg( "ERROR: LoadSchd (%s): (%s) Malformed AI Schedule. Expecting ':' after type 'STATE.\n",prefix,new_schedule->GetName()); - Assert(0); - return false; - } - - // Load the activity and make sure its valid - pfile = engine->ParseFile(pfile, token, sizeof( token ) ); - tempTask[taskNum].flTaskData = CAI_SchedulesManager::GetStateID(token); - if (tempTask[taskNum].flTaskData == -1) - { - DevMsg( "ERROR: LoadSchd %d (%s): (%s) Unknown shedule %s!\n", __LINE__, prefix,new_schedule->GetName(), token); - Assert(0); - return false; - } - } - else if (!stricmp("Memory",token)) - { - - // Skip the ";", but make sure it's present - pfile = engine->ParseFile(pfile, token, sizeof( token ) ); - if (stricmp(token,":")) - { - DevMsg( "ERROR: LoadSchd (%s): (%s) Malformed AI Schedule. Expecting ':' after type 'STATE.\n",prefix,new_schedule->GetName()); - Assert(0); - return false; - } - - // Load the activity and make sure its valid - pfile = engine->ParseFile(pfile, token, sizeof( token ) ); - tempTask[taskNum].flTaskData = CAI_SchedulesManager::GetMemoryID(token); - if (tempTask[taskNum].flTaskData == -1) - { - DevMsg( "ERROR: LoadSchd %d (%s): (%s) Unknown shedule %s!\n", __LINE__, prefix,new_schedule->GetName(), token); - Assert(0); - return false; - } - } - else if (!stricmp("Path",token)) - { - // Skip the ";", but make sure it's present - pfile = engine->ParseFile(pfile, token, sizeof( token ) ); - if (stricmp(token,":")) - { - DevMsg( "ERROR: LoadSchd (%s): (%s) Malformed AI Schedule. Expecting ':' after type 'PATH.\n",prefix,new_schedule->GetName()); - Assert(0); - return false; - } - - // Load the activity and make sure its valid - pfile = engine->ParseFile(pfile, token, sizeof( token ) ); - tempTask[taskNum].flTaskData = CAI_SchedulesManager::GetPathID( token ); - if (tempTask[taskNum].flTaskData == -1) - { - DevMsg( "ERROR: LoadSchd (%s): (%s) Unknown path type %s!\n", prefix,new_schedule->GetName(), token); - Assert(0); - return false; - } - } - else if (!stricmp("Goal",token)) - { - // Skip the ";", but make sure it's present - pfile = engine->ParseFile(pfile, token, sizeof( token ) ); - if (stricmp(token,":")) - { - DevMsg( "ERROR: LoadSchd (%s): (%s) Malformed AI Schedule. Expecting ':' after type 'GOAL.\n",prefix,new_schedule->GetName()); - Assert(0); - return false; - } - - // Load the activity and make sure its valid - pfile = engine->ParseFile(pfile, token, sizeof( token ) ); - tempTask[taskNum].flTaskData = CAI_SchedulesManager::GetGoalID( token ); - if (tempTask[taskNum].flTaskData == -1) - { - DevMsg( "ERROR: LoadSchd (%s): (%s) Unknown goal type %s!\n", prefix,new_schedule->GetName(), token); - Assert(0); - return false; - } - } - else if ( !stricmp( "HintFlags",token ) ) - { - // Skip the ":", but make sure it's present - pfile = engine->ParseFile(pfile, token, sizeof( token ) ); - if (stricmp(token,":")) - { - DevMsg( "ERROR: LoadSchd (%s): (%s) Malformed AI Schedule. Expecting ':' after type 'HINTFLAG'\n",prefix,new_schedule->GetName()); - Assert(0); - return false; - } - - // Load the flags and make sure they are valid - pfile = engine->ParseFile( pfile, token, sizeof( token ) ); - tempTask[taskNum].flTaskData = CAI_HintManager::GetFlags( token ); - if (tempTask[taskNum].flTaskData == -1) - { - DevMsg( "ERROR: LoadSchd (%s): (%s) Unknown hint flag type %s!\n", prefix,new_schedule->GetName(), token); - Assert(0); - return false; - } - } - else if (!stricmp("Interrupts",token) || !strnicmp("TASK_",token,5) ) - { - // a parse error. Interrupts is the next section, TASK_ is probably the next task, missing task argument? - Warning( "ERROR: LoadSchd (%s): (%s) Bad syntax at task #%d (wasn't expecting %s)\n", prefix, new_schedule->GetName(), taskNum, token); - Assert(0); - return false; - } - else - { - tempTask[taskNum].flTaskData = atof(token); - } - taskNum++; - - // Read the next token - Q_strncpy(save_token,token,sizeof(save_token)); - pfile = engine->ParseFile(pfile, token, sizeof( token ) ); - - // Check for malformed task argument type - if (!stricmp(token,":")) - { - DevMsg( "ERROR: LoadSchd (%s): Schedule (%s),\n Task (%s), has a malformed AI Task Argument = (%s)\n", - prefix,new_schedule->GetName(),taskID,save_token); - Assert(0); - return false; - } - } - - // Now copy the tasks into the new schedule - new_schedule->m_iNumTasks = taskNum; - new_schedule->m_pTaskList = new Task_t[taskNum]; - for (int i=0;im_pTaskList[i].iTask = tempTask[i].iTask; - new_schedule->m_pTaskList[i].flTaskData = tempTask[i].flTaskData; - - Assert( AI_IdIsLocal( new_schedule->m_pTaskList[i].iTask ) ); - } - - // ========================== - // Now read in the interrupts - // ========================== - pfile = engine->ParseFile(pfile, token, sizeof( token ) ); - while ((token[0] != '\0') && (stricmp("Schedule", token))) - { - // Convert generic ID to sub-class specific enum - int condID = CAI_BaseNPC::GetConditionID(token); - - // If not a valid condition, send a warning message - if (condID == -1) - { - DevMsg( "ERROR: LoadSchd (%s): Schedule (%s), Unknown condition %s!\n", prefix,new_schedule->GetName(),token); - Assert(0); - } - - // Otherwise, add to this schedules list of conditions - else - { - int interrupt = AI_RemapFromGlobal(condID); - Assert( AI_IdIsGlobal( condID ) && interrupt >= 0 && interrupt < MAX_CONDITIONS ); - new_schedule->m_InterruptMask.Set(interrupt); - } - - // Read the next token - pfile = engine->ParseFile(pfile, token, sizeof( token ) ); - } - } - return true; -} - -bool CAI_SchedulesManager::LoadSchedules( const char *prefix, CAI_ClassScheduleIdSpace *pIdSpace ) -{ - char sz[128]; - - // Open the weapon's data file and read the weaponry details - Q_snprintf(sz,sizeof(sz), "scripts/%s.sch",prefix); - char *pfile = (char*)UTIL_LoadFileForMe(sz, NULL); - - if (!pfile) - { - DevMsg( "Unable to open AI Schedule data file for: %s\n", sz); - return false; - } - if (!LoadSchedulesFromBuffer( prefix, pfile, pIdSpace)) - { - DevMsg( " Schedule file: %s\n", sz ); - UTIL_FreeFile( (byte*)pfile ); - return false; - } - UTIL_FreeFile( (byte*)pfile ); - return true; -} - - - -//----------------------------------------------------------------------------- -// Purpose: Given a schedule ID, returns a schedule of the given type -//----------------------------------------------------------------------------- -CAI_Schedule *CAI_SchedulesManager::GetScheduleFromID( int schedID ) -{ - for ( CAI_Schedule *schedule = CAI_SchedulesManager::allSchedules; schedule != NULL; schedule = schedule->nextSchedule ) - { - if (schedule->m_iScheduleID == schedID) - return schedule; - } - - DevMsg( "Couldn't find schedule (%s)\n", CAI_BaseNPC::GetSchedulingSymbols()->ScheduleIdToSymbol(schedID) ); - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Given a schedule name, returns a schedule of the given type -//----------------------------------------------------------------------------- -CAI_Schedule *CAI_SchedulesManager::GetScheduleByName( const char *name ) -{ - for ( CAI_Schedule *schedule = CAI_SchedulesManager::allSchedules; schedule != NULL; schedule = schedule->nextSchedule ) - { - if (FStrEq(schedule->GetName(),name)) - return schedule; - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Delete all the schedules -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_SchedulesManager::DeleteAllSchedules(void) -{ - m_CurLoadSig++; - - if ( m_CurLoadSig < 0 ) - m_CurLoadSig = 0; - - CAI_Schedule *schedule = CAI_SchedulesManager::allSchedules; - CAI_Schedule *next; - - while (schedule) - { - next = schedule->nextSchedule; - delete schedule; - schedule = next; - } - CAI_SchedulesManager::allSchedules = NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- - -CAI_Schedule::CAI_Schedule(char *name, int schedule_id, CAI_Schedule *pNext) -{ - m_iScheduleID = schedule_id; - - int len = strlen(name); - m_pName = new char[len+1]; - Q_strncpy(m_pName,name,len+1); - - m_pTaskList = NULL; - m_iNumTasks = 0; - - // --------------------------------- - // Add to linked list of schedules - // --------------------------------- - nextSchedule = pNext; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CAI_Schedule::~CAI_Schedule( void ) -{ - delete[] m_pName; - delete[] m_pTaskList; -} diff --git a/game/server/ai_schedule.h b/game/server/ai_schedule.h deleted file mode 100644 index 66698d7f9..000000000 --- a/game/server/ai_schedule.h +++ /dev/null @@ -1,200 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: A schedule -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#include "bitstring.h" - -#ifndef AI_SCHEDULE_H -#define AI_SCHEDULE_H - -#pragma once - -class CStringRegistry; -class CAI_ClassScheduleIdSpace; -class CAI_BaseNPC; - -struct Task_t; - -#ifndef MAX_CONDITIONS -#define MAX_CONDITIONS 32*8 -#endif -typedef CBitVec CAI_ScheduleBits; - -//================================================== -// goalType_t -//================================================== - -enum goalType_t -{ - GOAL_NONE = -1, - GOAL_ENEMY, //Our current enemy's position - GOAL_TARGET, //Our current target's position - GOAL_ENEMY_LKP, //Our current enemy's last known position - GOAL_SAVED_POSITION, //Our saved position -}; - -//================================================== -// pathType_t -//================================================== - -enum pathType_t -{ - PATH_NONE = -1, - PATH_TRAVEL, //Path that will take us to the goal - PATH_LOS, //Path that gives us line of sight to our goal - //PATH_FLANK, //Path that will take us to a flanking position of our goal - //PATH_FLANK_LOS, //Path that will take us to within line of sight to the flanking position of our goal - PATH_COVER, //Path that will give us cover from our goal - //PATH_COVER_LOS, //Path that will give us line of sight to cover from our goal -}; - -//============================================================================= -// >> CAI_Schedule -//============================================================================= - -class CAI_Schedule; - -class CAI_SchedulesManager -{ -public: - CAI_SchedulesManager() - { - allSchedules = NULL; - m_CurLoadSig = 0; // Note when schedules reset - } - - int GetScheduleLoadSignature() { return m_CurLoadSig; } - CAI_Schedule* GetScheduleFromID( int schedID ); // Function to return schedule from linked list - CAI_Schedule* GetScheduleByName( const char *name ); - - bool LoadAllSchedules(void); - - bool LoadSchedules( const char* prefix, CAI_ClassScheduleIdSpace *pIdSpace ); - bool LoadSchedulesFromBuffer( const char *prefix, char *pfile, CAI_ClassScheduleIdSpace *pIdSpace ); - -private: - friend class CAI_SystemHook; - - int m_CurLoadSig; // Note when schedules reset - CAI_Schedule* allSchedules; // A linked list of all schedules - - CAI_Schedule * CreateSchedule(char *name, int schedule_id); - - void CreateStringRegistries( void ); - void DestroyStringRegistries( void ); - void DeleteAllSchedules(void); - - //static bool LoadSchedules( char* prefix, int taskIDOffset, int taskENOffset, - // int schedIDOffset, int schedENOffset, - // int condIDOffset, int condENOffset); - - // parsing helpers - int GetStateID(const char *state_name); - int GetMemoryID(const char *memory_name); - int GetPathID( const char *token ); - int GetGoalID( const char *token ); - -}; - -extern CAI_SchedulesManager g_AI_SchedulesManager; - -class CAI_Schedule -{ -// --------- -// Static -// --------- -// --------- -public: - int GetId() const - { - return m_iScheduleID; - } - - const Task_t *GetTaskList() const - { - return m_pTaskList; - } - - int NumTasks() const - { - return m_iNumTasks; - } - - void GetInterruptMask( CAI_ScheduleBits *pBits ) const - { - m_InterruptMask.CopyTo( pBits ); - } - - bool HasInterrupt( int condition ) const - { - return m_InterruptMask.IsBitSet( condition ); - } - - const char *GetName() const - { - return m_pName; - } - -private: - friend class CAI_SchedulesManager; - - int m_iScheduleID; // The id number of this schedule - - Task_t *m_pTaskList; - int m_iNumTasks; - - CAI_ScheduleBits m_InterruptMask; // a bit mask of conditions that can interrupt this schedule - char *m_pName; - - CAI_Schedule *nextSchedule; // The next schedule in the list of schedules - - CAI_Schedule(char *name,int schedule_id, CAI_Schedule *pNext); - ~CAI_Schedule( void ); -}; - -//----------------------------------------------------------------------------- -// -// In-memory schedules -// - -#define AI_DEFINE_SCHEDULE( name, text ) \ - const char * g_psz##name = \ - "\n Schedule" \ - "\n " #name \ - text \ - "\n" - - -#define AI_LOAD_SCHEDULE( classname, name ) \ - do \ - { \ - extern const char * g_psz##name; \ - if ( classname::gm_SchedLoadStatus.fValid ) \ - { \ - classname::gm_SchedLoadStatus.fValid = g_AI_SchedulesManager.LoadSchedulesFromBuffer( #classname,(char *)g_psz##name,&classname::gm_ClassScheduleIdSpace ); \ - } \ - } while (false) - - -// For loading default schedules in memory (see ai_default.cpp) -#define AI_LOAD_DEF_SCHEDULE( classname, name ) \ - do \ - { \ - extern const char * g_psz##name; \ - if (!g_AI_SchedulesManager.LoadSchedulesFromBuffer( #classname,(char *)g_psz##name,&classname::gm_ClassScheduleIdSpace )) \ - return false; \ - } while (false) - - -//----------------------------------------------------------------------------- - -#endif // AI_SCHEDULE_H diff --git a/game/server/ai_scriptconditions.cpp b/game/server/ai_scriptconditions.cpp deleted file mode 100644 index 0a2472de2..000000000 --- a/game/server/ai_scriptconditions.cpp +++ /dev/null @@ -1,846 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -#include "IEffects.h" -#include "collisionutils.h" - -#include "ai_basenpc.h" -#include "ai_scriptconditions.h" -#include "saverestore_utlvector.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SF_ACTOR_AS_ACTIVATOR ( 1 << 0 ) - -ConVar debugscriptconditions( "ai_debugscriptconditions", "0" ); - -#define ScrCondDbgMsg( msg ) \ - do \ -{ \ - if ( debugscriptconditions.GetBool() ) \ -{ \ - DevMsg msg; \ -} \ -} \ - while (0) - - -//============================================================================= -// -// CAI_ScriptConditions -// -//============================================================================= - -LINK_ENTITY_TO_CLASS(ai_script_conditions, CAI_ScriptConditions); - -BEGIN_DATADESC( CAI_ScriptConditions ) - - DEFINE_THINKFUNC( EvaluationThink ), - - DEFINE_OUTPUT( m_OnConditionsSatisfied, "OnConditionsSatisfied" ), - DEFINE_OUTPUT( m_OnConditionsTimeout, "OnConditionsTimeout" ), - DEFINE_OUTPUT( m_NoValidActors, "NoValidActors" ), - - //--------------------------------- - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - - //--------------------------------- - - // Inputs - DEFINE_KEYFIELD(m_fDisabled, FIELD_BOOLEAN, "StartDisabled" ), - - DEFINE_FIELD( m_hTarget, FIELD_EHANDLE ), - DEFINE_KEYFIELD(m_Actor, FIELD_STRING, "Actor" ), - - DEFINE_KEYFIELD(m_flRequiredTime, FIELD_FLOAT, "RequiredTime" ), - -#ifndef HL2_EPISODIC - DEFINE_FIELD( m_hActor, FIELD_EHANDLE ), - DEFINE_EMBEDDED(m_Timer ), - DEFINE_EMBEDDED(m_Timeout ), -#endif - - DEFINE_KEYFIELD(m_fMinState, FIELD_INTEGER, "MinimumState" ), - DEFINE_KEYFIELD(m_fMaxState, FIELD_INTEGER, "MaximumState" ), - - DEFINE_KEYFIELD(m_fScriptStatus, FIELD_INTEGER, "ScriptStatus" ), - DEFINE_KEYFIELD(m_fActorSeePlayer, FIELD_INTEGER, "ActorSeePlayer" ), - - - DEFINE_KEYFIELD(m_flPlayerActorProximity, FIELD_FLOAT, "PlayerActorProximity" ), - DEFINE_EMBEDDED(m_PlayerActorProxTester), - - DEFINE_KEYFIELD(m_flPlayerActorFOV, FIELD_FLOAT, "PlayerActorFOV" ), - DEFINE_KEYFIELD(m_bPlayerActorFOVTrueCone, FIELD_BOOLEAN, "PlayerActorFOVTrueCone" ), - - DEFINE_KEYFIELD(m_fPlayerActorLOS, FIELD_INTEGER, "PlayerActorLOS" ), - DEFINE_KEYFIELD(m_fActorSeeTarget, FIELD_INTEGER, "ActorSeeTarget" ), - - DEFINE_KEYFIELD(m_flActorTargetProximity, FIELD_FLOAT, "ActorTargetProximity" ), - DEFINE_EMBEDDED(m_ActorTargetProxTester), - - DEFINE_KEYFIELD(m_flPlayerTargetProximity, FIELD_FLOAT, "PlayerTargetProximity" ), - DEFINE_EMBEDDED(m_PlayerTargetProxTester), - - DEFINE_KEYFIELD(m_flPlayerTargetFOV, FIELD_FLOAT, "PlayerTargetFOV" ), - DEFINE_KEYFIELD(m_bPlayerTargetFOVTrueCone, FIELD_BOOLEAN, "PlayerTargetFOVTrueCone" ), - - DEFINE_KEYFIELD(m_fPlayerTargetLOS, FIELD_INTEGER, "PlayerTargetLOS" ), - DEFINE_KEYFIELD(m_fPlayerBlockingActor, FIELD_INTEGER, "PlayerBlockingActor" ), - - DEFINE_KEYFIELD(m_flMinTimeout, FIELD_FLOAT, "MinTimeout" ), - DEFINE_KEYFIELD(m_flMaxTimeout, FIELD_FLOAT, "MaxTimeout" ), - - DEFINE_KEYFIELD(m_fActorInPVS, FIELD_INTEGER, "ActorInPVS" ), - - DEFINE_KEYFIELD(m_fActorInVehicle, FIELD_INTEGER, "ActorInVehicle" ), - DEFINE_KEYFIELD(m_fPlayerInVehicle, FIELD_INTEGER, "PlayerInVehicle" ), - - DEFINE_UTLVECTOR( m_ElementList, FIELD_EMBEDDED ), - DEFINE_FIELD( m_bLeaveAsleep, FIELD_BOOLEAN ), - -END_DATADESC() - -BEGIN_SIMPLE_DATADESC( CAI_ProxTester ) - DEFINE_FIELD( m_distSq, FIELD_FLOAT ), - DEFINE_FIELD( m_fInside, FIELD_BOOLEAN ), -END_DATADESC() - -BEGIN_SIMPLE_DATADESC( CAI_ScriptConditionsElement ) - DEFINE_FIELD( m_hActor, FIELD_EHANDLE ), - DEFINE_EMBEDDED(m_Timer ), - DEFINE_EMBEDDED(m_Timeout ), -END_DATADESC() - - -//----------------------------------------------------------------------------- - -#define EVALUATOR( name ) { &CAI_ScriptConditions::Eval##name, #name } - -CAI_ScriptConditions::EvaluatorInfo_t CAI_ScriptConditions::gm_Evaluators[] = -{ - EVALUATOR( ActorSeePlayer ), - EVALUATOR( State ), - EVALUATOR( PlayerActorProximity ), - EVALUATOR( PlayerTargetProximity ), - EVALUATOR( ActorTargetProximity ), - EVALUATOR( PlayerBlockingActor ), - EVALUATOR( PlayerActorLook ), - EVALUATOR( PlayerTargetLook ), - EVALUATOR( ActorSeeTarget), - EVALUATOR( PlayerActorLOS ), - EVALUATOR( PlayerTargetLOS ), - -#ifdef HL2_EPISODIC - EVALUATOR( ActorInPVS ), - EVALUATOR( PlayerInVehicle ), - EVALUATOR( ActorInVehicle ), -#endif - -}; - -void CAI_ScriptConditions::OnRestore( void ) -{ - BaseClass::OnRestore(); - -#ifndef HL2_EPISODIC - //Old HL2 save game! Fix up to new system. - if ( m_hActor ) - { - CAI_ScriptConditionsElement conditionactor; - - conditionactor.SetActor( m_hActor ); - conditionactor.SetTimeOut( m_Timeout ); - conditionactor.SetTimer( m_Timer ); - - m_ElementList.AddToTail( conditionactor ); - - m_hActor = NULL; - } - - if ( m_ElementList.Count() == 0 && m_Actor == NULL_STRING && m_fDisabled == false ) - { - AddNewElement( NULL ); - } -#endif -} - -//----------------------------------------------------------------------------- - -bool CAI_ScriptConditions::EvalState( const EvalArgs_t &args ) -{ - if ( !args.pActor ) - return true; - - CAI_BaseNPC *pNpc = args.pActor->MyNPCPointer(); - - // !!!LATER - fix this code, we shouldn't need the table anymore - // now that we've placed the NPC state defs in a logical order (sjb) - static int stateVals[] = - { - -1, // NPC_STATE_NONE - 0, // NPC_STATE_IDLE - 1, // NPC_STATE_ALERT - 2, // NPC_STATE_COMBAT - -1, // NPC_STATE_SCRIPT - -1, // NPC_STATE_PLAYDEAD - -1, // NPC_STATE_PRONE - -1, // NPC_STATE_DEAD - }; - - int valState = stateVals[pNpc->m_NPCState]; - - if ( valState < 0 ) - { - if ( pNpc->m_NPCState == NPC_STATE_SCRIPT && m_fScriptStatus >= TRS_TRUE ) - return true; - - return false; - } - - const int valLow = stateVals[m_fMinState]; - const int valHigh = stateVals[m_fMaxState]; - - if ( valLow > valHigh ) - { - DevMsg( "Script condition warning: Invalid setting for Maximum/Minimum state\n" ); - Disable(); - return false; - } - - return ( valState >= valLow && valState <= valHigh ); -} - -//----------------------------------------------------------------------------- - -bool CAI_ScriptConditions::EvalActorSeePlayer( const EvalArgs_t &args ) -{ - if( m_fActorSeePlayer == TRS_NONE ) - { - // Don't care, so don't do any work. - return true; - } - - if ( !args.pActor ) - return true; - - bool fCanSeePlayer = args.pActor->MyNPCPointer()->HasCondition( COND_SEE_PLAYER ); - return ( (int)m_fActorSeePlayer == (int)fCanSeePlayer ); -} - -//----------------------------------------------------------------------------- - -bool CAI_ScriptConditions::EvalActorSeeTarget( const EvalArgs_t &args ) -{ - if( m_fActorSeeTarget == TRS_NONE ) - { - // Don't care, so don't do any work. - return true; - } - - if ( args.pTarget ) - { - if ( !args.pActor ) - return true; - - CAI_BaseNPC *pNPCActor = args.pActor->MyNPCPointer(); - -#ifdef HL2_EPISODIC - // This is the code we want to have written for HL2, but HL2 shipped without the QuerySeeEntity() call. This #ifdef really wants to be - // something like #ifndef HL2_RETAIL, since this change does want to be in any products that are built henceforth. (sjb) - bool fSee = pNPCActor->FInViewCone( args.pTarget ) && pNPCActor->FVisible( args.pTarget ) && pNPCActor->QuerySeeEntity( args.pTarget ); -#else - bool fSee = pNPCActor->FInViewCone( args.pTarget ) && pNPCActor->FVisible( args.pTarget ); -#endif//HL2_EPISODIC - - if( fSee ) - { - if( m_fActorSeeTarget == TRS_TRUE ) - { - return true; - } - - return false; - } - else - { - if( m_fActorSeeTarget == TRS_FALSE ) - { - return true; - } - - return false; - } - } - - return true; -} - - -//----------------------------------------------------------------------------- - -bool CAI_ScriptConditions::EvalPlayerActorProximity( const EvalArgs_t &args ) -{ - return ( !args.pActor || m_PlayerActorProxTester.Check( args.pPlayer, args.pActor ) ); -} - -//----------------------------------------------------------------------------- - -bool CAI_ScriptConditions::EvalPlayerTargetProximity( const EvalArgs_t &args ) -{ - return ( !args.pTarget || - m_PlayerTargetProxTester.Check( args.pPlayer, args.pTarget ) ); -} - - -//----------------------------------------------------------------------------- - -bool CAI_ScriptConditions::EvalActorTargetProximity( const EvalArgs_t &args ) -{ - return ( !args.pTarget || !args.pActor || - m_ActorTargetProxTester.Check( args.pActor, args.pTarget ) ); -} - -//----------------------------------------------------------------------------- - -bool CAI_ScriptConditions::EvalPlayerActorLook( const EvalArgs_t &args ) -{ - return ( !args.pActor || - IsInFOV( args.pPlayer, args.pActor, m_flPlayerActorFOV, m_bPlayerActorFOVTrueCone ) ); -} - -//----------------------------------------------------------------------------- - -bool CAI_ScriptConditions::EvalPlayerTargetLook( const EvalArgs_t &args ) -{ - return ( !args.pTarget || IsInFOV( args.pPlayer, args.pTarget, m_flPlayerTargetFOV, m_bPlayerTargetFOVTrueCone ) ); -} - -//----------------------------------------------------------------------------- - -bool CAI_ScriptConditions::EvalPlayerActorLOS( const EvalArgs_t &args ) -{ - if( m_fPlayerActorLOS == TRS_NONE ) - { - // Don't execute expensive code if we don't care. - return true; - } - - return ( !args.pActor || PlayerHasLineOfSight( args.pPlayer, args.pActor, m_fPlayerActorLOS == TRS_FALSE ) ); -} - -//----------------------------------------------------------------------------- - -bool CAI_ScriptConditions::EvalPlayerTargetLOS( const EvalArgs_t &args ) -{ - if( m_fPlayerTargetLOS == TRS_NONE ) - { - // Don't execute expensive code if we don't care. - return true; - } - - return ( !args.pTarget || PlayerHasLineOfSight( args.pPlayer, args.pTarget, m_fPlayerTargetLOS == TRS_FALSE ) ); -} - -bool CAI_ScriptConditions::EvalActorInPVS( const EvalArgs_t &args ) -{ - if( m_fActorInPVS == TRS_NONE ) - { - // Don't execute expensive code if we don't care. - return true; - } - - return ( !args.pActor || ActorInPlayersPVS( args.pActor, m_fActorInPVS == TRS_FALSE ) ); -} - -//----------------------------------------------------------------------------- - -bool CAI_ScriptConditions::EvalPlayerBlockingActor( const EvalArgs_t &args ) -{ - if ( m_fPlayerBlockingActor == TRS_NONE ) - return true; - -#if 0 - CAI_BaseNPC *pNpc = args.pActor->MyNPCPointer(); - - const float testDist = 30.0; - - Vector origin = args.pActor->WorldSpaceCenter(); - Vector delta = UTIL_YawToVector( args.pActor->GetAngles().y ) * testDist; - - Vector vecAbsMins, vecAbsMaxs; - args.pActor->CollisionProp()->WorldSpaceAABB( &vecAbsMins, &vecAbsMaxs ); - bool intersect = IsBoxIntersectingRay( vecAbsMins, vecAbsMaxs, origin, delta ); -#endif - - if ( m_fPlayerBlockingActor == TRS_FALSE ) - return true; - - return false; // for now, never say player is blocking -} - -//----------------------------------------------------------------------------- - -bool CAI_ScriptConditions::EvalPlayerInVehicle( const EvalArgs_t &args ) -{ - // We don't care - if ( m_fPlayerInVehicle == TRS_NONE ) - return true; - - // Need a player to test - if ( args.pPlayer == NULL ) - return false; - - // Desired states must match - return ( !!args.pPlayer->IsInAVehicle() == m_fPlayerInVehicle ); -} - -//----------------------------------------------------------------------------- - -bool CAI_ScriptConditions::EvalActorInVehicle( const EvalArgs_t &args ) -{ - // We don't care - if ( m_fActorInVehicle == TRS_NONE ) - return true; - - if ( !args.pActor ) - return true; - - // Must be able to be in a vehicle at all - CBaseCombatCharacter *pBCC = args.pActor->MyCombatCharacterPointer(); - if ( pBCC == NULL ) - return false; - - // Desired states must match - return ( !!pBCC->IsInAVehicle() == m_fActorInVehicle ); -} - -//----------------------------------------------------------------------------- - -void CAI_ScriptConditions::Spawn() -{ - Assert( ( m_fMinState == NPC_STATE_IDLE || m_fMinState == NPC_STATE_COMBAT || m_fMinState == NPC_STATE_ALERT ) && - ( m_fMaxState == NPC_STATE_IDLE || m_fMaxState == NPC_STATE_COMBAT || m_fMaxState == NPC_STATE_ALERT ) ); - - m_PlayerActorProxTester.Init( m_flPlayerActorProximity ); - m_PlayerTargetProxTester.Init( m_flPlayerTargetProximity ); - m_ActorTargetProxTester.Init( m_flActorTargetProximity ); - - m_bLeaveAsleep = m_fDisabled; -} - -//----------------------------------------------------------------------------- - -void CAI_ScriptConditions::Activate() -{ - BaseClass::Activate(); - - // When we spawn, m_fDisabled is initial state as given by worldcraft. - // following that, we keep it updated and it reflects current state. - if( !m_fDisabled ) - Enable(); - -#ifdef HL2_EPISODIC - gEntList.AddListenerEntity( this ); -#endif -} - -//----------------------------------------------------------------------------- - -void CAI_ScriptConditions::UpdateOnRemove( void ) -{ - gEntList.RemoveListenerEntity( this ); - BaseClass::UpdateOnRemove(); - - m_ElementList.Purge(); -} - -//----------------------------------------------------------------------------- - -void CAI_ScriptConditions::EvaluationThink() -{ - if ( m_fDisabled == true ) - return; - - int iActorsDone = 0; - -#ifdef HL2_DLL - if( AI_GetSinglePlayer()->GetFlags() & FL_NOTARGET ) - { - ScrCondDbgMsg( ("%s WARNING: Player is NOTARGET. This will affect all LOS conditiosn involving the player!\n", GetDebugName()) ); - } -#endif - - - for ( int i = 0; i < m_ElementList.Count(); ) - { - CAI_ScriptConditionsElement *pConditionElement = &m_ElementList[i]; - - if ( pConditionElement == NULL ) - { - i++; - continue; - } - - CBaseEntity *pActor = pConditionElement->GetActor(); - CBaseEntity *pActivator = this; - -#ifdef HL2_EPISODIC - if ( pActor && HasSpawnFlags( SF_ACTOR_AS_ACTIVATOR ) ) - { - pActivator = pActor; - } -#endif - - AssertMsg( !m_fDisabled, ("Violated invariant between CAI_ScriptConditions disabled state and think func setting") ); - - if ( m_Actor != NULL_STRING && !pActor ) - { - if ( m_ElementList.Count() == 1 ) - { - DevMsg( "Warning: Active AI script conditions associated with an non-existant or destroyed NPC\n" ); - m_NoValidActors.FireOutput( this, this, 0 ); - } - - iActorsDone++; - m_ElementList.Remove( i ); - continue; - } - - i++; - - if( m_flMinTimeout > 0 && pConditionElement->GetTimeOut()->Expired() ) - { - ScrCondDbgMsg( ( "%s firing output OnConditionsTimeout (%f seconds)\n", STRING( GetEntityName() ), pConditionElement->GetTimeOut()->GetInterval() ) ); - - iActorsDone++; - m_OnConditionsTimeout.FireOutput( pActivator, this ); - continue; - } - - bool result = true; - const int nEvaluators = sizeof( gm_Evaluators ) / sizeof( gm_Evaluators[0] ); - - EvalArgs_t args = - { - pActor, - GetPlayer(), - m_hTarget.Get() - }; - - for ( int i = 0; i < nEvaluators; ++i ) - { - if ( !(this->*gm_Evaluators[i].pfnEvaluator)( args ) ) - { - pConditionElement->GetTimer()->Reset(); - result = false; - - ScrCondDbgMsg( ( "%s failed on: %s\n", GetDebugName(), gm_Evaluators[ i ].pszName ) ); - - break; - } - } - - if ( result ) - { - ScrCondDbgMsg( ( "%s waiting... %f\n", GetDebugName(), pConditionElement->GetTimer()->GetRemaining() ) ); - } - - if ( result && pConditionElement->GetTimer()->Expired() ) - { - ScrCondDbgMsg( ( "%s firing output OnConditionsSatisfied\n", GetDebugName() ) ); - - // Default behavior for now, provide worldcraft option later. - iActorsDone++; - m_OnConditionsSatisfied.FireOutput( pActivator, this ); - } - } - - //All done! - if ( iActorsDone == m_ElementList.Count() ) - { - Disable(); - m_ElementList.Purge(); - } - - SetThinkTime(); -} - -//----------------------------------------------------------------------------- - -int CAI_ScriptConditions::AddNewElement( CBaseEntity *pActor ) -{ - CAI_ScriptConditionsElement conditionelement; - conditionelement.SetActor( pActor ); - - if( m_flMaxTimeout > 0 ) - { - conditionelement.GetTimeOut()->Set( random->RandomFloat( m_flMinTimeout, m_flMaxTimeout ), false ); - } - else - { - conditionelement.GetTimeOut()->Set( m_flMinTimeout, false ); - } - - conditionelement.GetTimer()->Set( m_flRequiredTime ); - - if ( m_flRequiredTime > 0 ) - { - conditionelement.GetTimer()->Reset(); - } - - return m_ElementList.AddToTail( conditionelement ); -} - -//----------------------------------------------------------------------------- - -void CAI_ScriptConditions::Enable( void ) -{ - m_hTarget = gEntList.FindEntityByName( NULL, m_target ); - - CBaseEntity *pActor = gEntList.FindEntityByName( NULL, m_Actor ); - if ( m_ElementList.Count() == 0 ) - { - if ( m_Actor != NULL_STRING && pActor == NULL ) - { - DevMsg( "Warning: Spawning AI script conditions (%s) associated with an non-existant NPC\n", GetDebugName() ); - m_NoValidActors.FireOutput( this, this, 0 ); - Disable(); - return; - } - - if ( pActor && pActor->MyNPCPointer() == NULL ) - { - Warning( "Script condition warning: warning actor is not an NPC\n" ); - Disable(); - return; - } - } - - while( pActor != NULL ) - { - if( !ActorInList(pActor) ) - { - AddNewElement( pActor ); - } - - pActor = gEntList.FindEntityByName( pActor, m_Actor ); - } - - //If we are hitting this it means we are using a Target->Player condition - if ( m_Actor == NULL_STRING ) - { - if( !ActorInList(pActor) ) - { - AddNewElement( NULL ); - } - } - - m_fDisabled = false; - - SetThink( &CAI_ScriptConditions::EvaluationThink ); - SetThinkTime(); -} - -//----------------------------------------------------------------------------- - -void CAI_ScriptConditions::Disable( void ) -{ - SetThink( NULL ); - - m_fDisabled = true; -} - -//----------------------------------------------------------------------------- - -void CAI_ScriptConditions::InputEnable( inputdata_t &inputdata ) -{ - m_bLeaveAsleep = false; - Enable(); -} - -//----------------------------------------------------------------------------- - -void CAI_ScriptConditions::InputDisable( inputdata_t &inputdata ) -{ - m_bLeaveAsleep = true; - Disable(); -} - -//----------------------------------------------------------------------------- - -bool CAI_ScriptConditions::IsInFOV( CBaseEntity *pViewer, CBaseEntity *pViewed, float fov, bool bTrueCone ) -{ - CBaseCombatCharacter *pCombatantViewer = (pViewer) ? pViewer->MyCombatCharacterPointer() : NULL; - - if ( fov < 360 && pCombatantViewer /*&& pViewed*/ ) - { - Vector vLookDir; - Vector vActorDir; - - // Halve the fov. As expressed here, fov is the full size of the viewcone. - float flFovDotResult; - flFovDotResult = cos( DEG2RAD( fov / 2 ) ); - float fDotPr = 1; - - if( bTrueCone ) - { - // 3D Check - vLookDir = pCombatantViewer->EyeDirection3D( ); - vActorDir = pViewed->EyePosition() - pViewer->EyePosition(); - vActorDir.NormalizeInPlace(); - fDotPr = vLookDir.Dot(vActorDir); - } - else - { - // 2D Check - vLookDir = pCombatantViewer->EyeDirection2D( ); - vActorDir = pViewed->EyePosition() - pViewer->EyePosition(); - vActorDir.z = 0.0; - vActorDir.AsVector2D().NormalizeInPlace(); - fDotPr = vLookDir.AsVector2D().Dot(vActorDir.AsVector2D()); - } - - if ( fDotPr < flFovDotResult ) - { - if( fov < 0 ) - { - // Designer has requested that the player - // NOT be looking at this place. - return true; - } - - return false; - } - } - - if( fov < 0 ) - { - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- - -bool CAI_ScriptConditions::PlayerHasLineOfSight( CBaseEntity *pViewer, CBaseEntity *pViewed, bool fNot ) -{ - CBaseCombatCharacter *pCombatantViewer = pViewer->MyCombatCharacterPointer(); - - if( pCombatantViewer ) - { - // We always trace towards the player, so we handle players-in-vehicles - if ( pViewed->FVisible( pCombatantViewer ) ) - { - // Line of sight exists. - if( fNot ) - { - return false; - } - else - { - return true; - } - } - else - { - // No line of sight. - if( fNot ) - { - return true; - } - else - { - return false; - } - } - } - - return true; -} - -//----------------------------------------------------------------------------- - -bool CAI_ScriptConditions::ActorInPlayersPVS( CBaseEntity *pActor, bool bNot ) -{ - if ( pActor == NULL ) - return true; - - bool bInPVS = !!UTIL_FindClientInPVS( pActor->edict()); - - if ( bInPVS ) - { - if( bNot ) - { - return false; - } - else - { - return true; - } - } - else - { - if( bNot ) - { - return true; - } - else - { - return false; - } - } -} - -//----------------------------------------------------------------------------- - -bool CAI_ScriptConditions::ActorInList( CBaseEntity *pActor ) -{ - for ( int i = 0; i < m_ElementList.Count(); i++ ) - { - if ( m_ElementList[i].GetActor() == pActor ) - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- - -void CAI_ScriptConditions::OnEntitySpawned( CBaseEntity *pEntity ) -{ - if( m_fDisabled && m_bLeaveAsleep ) - { - // Don't add elements if we're not currently running and don't want to automatically wake up. - // Any spawning NPC's we miss during this time will be found and added when manually Enabled(). - return; - } - - if ( pEntity->MyNPCPointer() == NULL ) - return; - - if ( pEntity->NameMatches( m_Actor ) ) - { - if ( ActorInList( pEntity ) == false ) - { - AddNewElement( pEntity ); - - if ( m_fDisabled == true && m_bLeaveAsleep == false ) - { - Enable(); - } - } - } -} - -//============================================================================= diff --git a/game/server/ai_scriptconditions.h b/game/server/ai_scriptconditions.h deleted file mode 100644 index 3d2befd44..000000000 --- a/game/server/ai_scriptconditions.h +++ /dev/null @@ -1,256 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_SCRIPTCONDITIONS_H -#define AI_SCRIPTCONDITIONS_H - -#include "baseentity.h" -#include "entityoutput.h" -#include "simtimer.h" -#include "ai_npcstate.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -//----------------------------------------------------------------------------- - -class CAI_ProxTester -{ -public: - CAI_ProxTester() - : m_distSq( 0 ), - m_fInside( false ) - { - } - - void Init( float dist ) - { - m_fInside = ( dist > 0 ); - m_distSq = dist * dist; - } - - bool Check( CBaseEntity *pEntity1, CBaseEntity *pEntity2 ) - { - if ( m_distSq != 0 ) - { - float distSq = ( pEntity1->GetAbsOrigin() - pEntity2->GetAbsOrigin() ).LengthSqr(); - bool fInside = ( distSq < m_distSq ); - - return ( m_fInside == fInside ); - } - return true; - } - - DECLARE_SIMPLE_DATADESC(); - -private: - - float m_distSq; - bool m_fInside; -}; - -//----------------------------------------------------------------------------- -class CAI_ScriptConditionsElement -{ -public: - - DECLARE_SIMPLE_DATADESC(); - - void SetActor( CBaseEntity *pEntity ) { m_hActor = pEntity; } - CBaseEntity *GetActor( void ){ return m_hActor.Get(); } - - void SetTimer( CSimTimer timer ) { m_Timer = timer; } - CSimTimer *GetTimer( void ) { return &m_Timer; } - - void SetTimeOut( CSimTimer timeout) { m_Timeout = timeout; } - CSimTimer *GetTimeOut( void ) { return &m_Timeout; } - -private: - EHANDLE m_hActor; - CSimTimer m_Timer; - CSimTimer m_Timeout; -}; - -//----------------------------------------------------------------------------- -// class CAI_ScriptConditions -// -// Purpose: Watches a set of conditions relative to a given NPC, and when they -// are all satisfied, fires the relevant output -//----------------------------------------------------------------------------- - -class CAI_ScriptConditions : public CBaseEntity, public IEntityListener -{ - DECLARE_CLASS( CAI_ScriptConditions, CBaseEntity ); - -public: - CAI_ScriptConditions() - : m_fDisabled( true ), - m_flRequiredTime( 0 ), - m_fMinState( NPC_STATE_IDLE ), - m_fMaxState( NPC_STATE_IDLE ), - m_fScriptStatus( TRS_NONE ), - m_fActorSeePlayer( TRS_NONE ), - m_flPlayerActorProximity( 0 ), - m_flPlayerActorFOV( -1 ), - m_fPlayerActorLOS( TRS_NONE ), - m_fActorSeeTarget( TRS_NONE ), - m_flActorTargetProximity( 0 ), - m_flPlayerTargetProximity( 0 ), - m_flPlayerTargetFOV( 0 ), - m_fPlayerTargetLOS( TRS_NONE ), - m_fPlayerBlockingActor( TRS_NONE ), - m_fActorInPVS( TRS_NONE ), - m_flMinTimeout( 0 ), - m_flMaxTimeout( 0 ), - m_fActorInVehicle( TRS_NONE ), - m_fPlayerInVehicle( TRS_NONE ) - { -#ifndef HL2_EPISODIC - m_hActor = NULL; -#endif - } - -private: - void Spawn(); - void Activate(); - - void EvaluationThink(); - - void Enable(); - void Disable(); - - void SetThinkTime() { SetNextThink( gpGlobals->curtime + 0.250 ); } - - // Evaluators - struct EvalArgs_t - { - CBaseEntity *pActor; - CBasePlayer *pPlayer; - CBaseEntity *pTarget; - }; - - bool EvalState( const EvalArgs_t &args ); - bool EvalActorSeePlayer( const EvalArgs_t &args ); - bool EvalPlayerActorLook( const EvalArgs_t &args ); - bool EvalPlayerTargetLook( const EvalArgs_t &args ); - bool EvalPlayerActorProximity( const EvalArgs_t &args ); - bool EvalPlayerTargetProximity( const EvalArgs_t &args ); - bool EvalActorTargetProximity( const EvalArgs_t &args ); - bool EvalActorSeeTarget( const EvalArgs_t &args ); - bool EvalPlayerActorLOS( const EvalArgs_t &args ); - bool EvalPlayerTargetLOS( const EvalArgs_t &args ); - bool EvalPlayerBlockingActor( const EvalArgs_t &args ); - bool EvalActorInPVS( const EvalArgs_t &args ); - bool EvalPlayerInVehicle( const EvalArgs_t &args ); - bool EvalActorInVehicle( const EvalArgs_t &args ); - - void OnEntitySpawned( CBaseEntity *pEntity ); - - int AddNewElement( CBaseEntity *pActor ); - - bool ActorInList( CBaseEntity *pActor ); - void UpdateOnRemove( void ); - - // Input handlers - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - - // Output handlers - COutputEvent m_OnConditionsSatisfied; - COutputEvent m_OnConditionsTimeout; - COutputEvent m_NoValidActors; - - //--------------------------------- - -#ifndef HL2_EPISODIC - CBaseEntity *GetActor() { return m_hActor.Get(); } -#endif - CBasePlayer *GetPlayer() { return UTIL_GetLocalPlayer(); } - - //--------------------------------- - - // @Note (toml 07-17-02): At some point, it may be desireable to switch to using function objects instead of functions. Probably - // if support for NPCs addiing custom conditions becomes necessary - typedef bool (CAI_ScriptConditions::*EvaluationFunc_t)( const EvalArgs_t &args ); - - struct EvaluatorInfo_t - { - EvaluationFunc_t pfnEvaluator; - const char *pszName; - }; - - static EvaluatorInfo_t gm_Evaluators[]; - - //--------------------------------- - // Evaluation helpers - - static bool IsInFOV( CBaseEntity *pViewer, CBaseEntity *pViewed, float fov, bool bTrueCone ); - static bool PlayerHasLineOfSight( CBaseEntity *pViewer, CBaseEntity *pViewed, bool fNot ); - static bool ActorInPlayersPVS( CBaseEntity *pActor, bool bNot ); - - virtual void OnRestore( void ); - - //--------------------------------- - // General conditions info - - bool m_fDisabled; - bool m_bLeaveAsleep; - EHANDLE m_hTarget; - - float m_flRequiredTime; // How long should the conditions me true - -#ifndef HL2_EPISODIC - EHANDLE m_hActor; - CSimTimer m_Timer; // @TODO (toml 07-16-02): save/load of timer once Jay has save/load of contained objects - CSimTimer m_Timeout; -#endif - - //--------------------------------- - // Specific conditions data - NPC_STATE m_fMinState; - NPC_STATE m_fMaxState; - ThreeState_t m_fScriptStatus; - ThreeState_t m_fActorSeePlayer; - string_t m_Actor; - - float m_flPlayerActorProximity; - CAI_ProxTester m_PlayerActorProxTester; - - float m_flPlayerActorFOV; - bool m_bPlayerActorFOVTrueCone; - ThreeState_t m_fPlayerActorLOS; - ThreeState_t m_fActorSeeTarget; - - float m_flActorTargetProximity; - CAI_ProxTester m_ActorTargetProxTester; - - float m_flPlayerTargetProximity; - CAI_ProxTester m_PlayerTargetProxTester; - - float m_flPlayerTargetFOV; - bool m_bPlayerTargetFOVTrueCone; - ThreeState_t m_fPlayerTargetLOS; - ThreeState_t m_fPlayerBlockingActor; - ThreeState_t m_fActorInPVS; - - float m_flMinTimeout; - float m_flMaxTimeout; - - ThreeState_t m_fActorInVehicle; - ThreeState_t m_fPlayerInVehicle; - - CUtlVector< CAI_ScriptConditionsElement > m_ElementList; - - //--------------------------------- - - DECLARE_DATADESC(); -}; - -//============================================================================= - -#endif // AI_SCRIPTCONDITIONS_H diff --git a/game/server/ai_senses.cpp b/game/server/ai_senses.cpp deleted file mode 100644 index 516c6f696..000000000 --- a/game/server/ai_senses.cpp +++ /dev/null @@ -1,751 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -#include "ai_senses.h" - -#include "soundent.h" -#include "team.h" -#include "ai_basenpc.h" -#include "saverestore_utlvector.h" - -#ifdef PORTAL - #include "portal_util_shared.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// Use this to disable caching and other optimizations in senses -#define DEBUG_SENSES 1 - -#ifdef DEBUG_SENSES -#define AI_PROFILE_SENSES(tag) AI_PROFILE_SCOPE(tag) -#else -#define AI_PROFILE_SENSES(tag) ((void)0) -#endif - -const float AI_STANDARD_NPC_SEARCH_TIME = .25; -const float AI_EFFICIENT_NPC_SEARCH_TIME = .35; -const float AI_HIGH_PRIORITY_SEARCH_TIME = 0.15; -const float AI_MISC_SEARCH_TIME = 0.45; - -//----------------------------------------------------------------------------- - -CAI_SensedObjectsManager g_AI_SensedObjectsManager; - -//----------------------------------------------------------------------------- - -#pragma pack(push, 1) - -struct AISightIterVal_t -{ - char array; - short iNext; - char SeenArray; -}; - -#pragma pack(pop) - - -//============================================================================= -// -// CAI_Senses -// -//============================================================================= - -BEGIN_SIMPLE_DATADESC( CAI_Senses ) - - DEFINE_FIELD( m_LookDist, FIELD_FLOAT ), - DEFINE_FIELD( m_LastLookDist, FIELD_FLOAT ), - DEFINE_FIELD( m_TimeLastLook, FIELD_TIME ), - DEFINE_FIELD( m_iSensingFlags, FIELD_INTEGER ), - // m_iAudibleList (no way to save?) - DEFINE_UTLVECTOR(m_SeenHighPriority, FIELD_EHANDLE ), - DEFINE_UTLVECTOR(m_SeenNPCs, FIELD_EHANDLE ), - DEFINE_UTLVECTOR(m_SeenMisc, FIELD_EHANDLE ), - // m_SeenArrays (not saved, rebuilt) - - // Could fold these three and above timer into one concept, but would invalidate savegames - DEFINE_FIELD( m_TimeLastLookHighPriority, FIELD_TIME ), - DEFINE_FIELD( m_TimeLastLookNPCs, FIELD_TIME ), - DEFINE_FIELD( m_TimeLastLookMisc, FIELD_TIME ), - -END_DATADESC() - -//----------------------------------------------------------------------------- - -bool CAI_Senses::CanHearSound( CSound *pSound ) -{ - if ( pSound->m_hOwner.Get() == GetOuter() ) - return false; - - if( GetOuter()->GetState() == NPC_STATE_SCRIPT && pSound->IsSoundType( SOUND_DANGER ) ) - { - // For now, don't hear danger in scripted sequences. This probably isn't a - // good long term solution, but it makes the Bank Exterior work better. - return false; - } - - if ( GetOuter()->IsInAScript() ) - return false; - - // @TODO (toml 10-18-02): what about player sounds and notarget? - float flHearDistanceSq = pSound->Volume() * GetOuter()->HearingSensitivity(); - flHearDistanceSq *= flHearDistanceSq; - if( pSound->GetSoundOrigin().DistToSqr( GetOuter()->EarPosition() ) <= flHearDistanceSq ) - { - return GetOuter()->QueryHearSound( pSound ); - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Listen - npcs dig through the active sound list for -// any sounds that may interest them. (smells, too!) - -void CAI_Senses::Listen( void ) -{ - m_iAudibleList = SOUNDLIST_EMPTY; - - int iSoundMask = GetOuter()->GetSoundInterests(); - - if ( iSoundMask != SOUND_NONE && !(GetOuter()->HasSpawnFlags(SF_NPC_WAIT_TILL_SEEN)) ) - { - int iSound = CSoundEnt::ActiveList(); - - while ( iSound != SOUNDLIST_EMPTY ) - { - CSound *pCurrentSound = CSoundEnt::SoundPointerForIndex( iSound ); - - if ( pCurrentSound && (iSoundMask & pCurrentSound->SoundType()) && CanHearSound( pCurrentSound ) ) - { - // the npc cares about this sound, and it's close enough to hear. - pCurrentSound->m_iNextAudible = m_iAudibleList; - m_iAudibleList = iSound; - } - - iSound = pCurrentSound->NextSound(); - } - } - - GetOuter()->OnListened(); -} - -//----------------------------------------------------------------------------- - -bool CAI_Senses::ShouldSeeEntity( CBaseEntity *pSightEnt ) -{ - if ( pSightEnt == GetOuter() || !pSightEnt->IsAlive() ) - return false; - - if ( pSightEnt->IsPlayer() && ( pSightEnt->GetFlags() & FL_NOTARGET ) ) - return false; - - // don't notice anyone waiting to be seen by the player - if ( pSightEnt->m_spawnflags & SF_NPC_WAIT_TILL_SEEN ) - return false; - - if ( !pSightEnt->CanBeSeenBy( GetOuter() ) ) - return false; - - if ( !GetOuter()->QuerySeeEntity( pSightEnt, true ) ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- - -bool CAI_Senses::CanSeeEntity( CBaseEntity *pSightEnt ) -{ - return ( GetOuter()->FInViewCone( pSightEnt ) && GetOuter()->FVisible( pSightEnt ) ); -} - -#ifdef PORTAL -bool CAI_Senses::CanSeeEntityThroughPortal( const CProp_Portal *pPortal, CBaseEntity *pSightEnt ) -{ - return GetOuter()->FVisibleThroughPortal( pPortal, pSightEnt ); -} -#endif - -//----------------------------------------------------------------------------- - -bool CAI_Senses::DidSeeEntity( CBaseEntity *pSightEnt ) const -{ - AISightIter_t iter; - CBaseEntity *pTestEnt; - - pTestEnt = GetFirstSeenEntity( &iter ); - - while( pTestEnt ) - { - if ( pSightEnt == pTestEnt ) - return true; - pTestEnt = GetNextSeenEntity( &iter ); - } - return false; -} - -//----------------------------------------------------------------------------- - -void CAI_Senses::NoteSeenEntity( CBaseEntity *pSightEnt ) -{ - pSightEnt->m_pLink = GetOuter()->m_pLink; - GetOuter()->m_pLink = pSightEnt; -} - -//----------------------------------------------------------------------------- - -bool CAI_Senses::WaitingUntilSeen( CBaseEntity *pSightEnt ) -{ - if ( GetOuter()->m_spawnflags & SF_NPC_WAIT_TILL_SEEN ) - { - if ( pSightEnt->IsPlayer() ) - { - CBasePlayer *pPlayer = ToBasePlayer( pSightEnt ); - Vector zero = Vector(0,0,0); - // don't link this client in the list if the npc is wait till seen and the player isn't facing the npc - if ( pPlayer - // && pPlayer->FVisible( GetOuter() ) - && pPlayer->FInViewCone( GetOuter() ) - && FBoxVisible( pSightEnt, static_cast(GetOuter()), zero ) ) - { - // player sees us, become normal now. - GetOuter()->m_spawnflags &= ~SF_NPC_WAIT_TILL_SEEN; - return false; - } - } - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- - -bool CAI_Senses::SeeEntity( CBaseEntity *pSightEnt ) -{ - GetOuter()->OnSeeEntity( pSightEnt ); - - // insert at the head of my sight list - NoteSeenEntity( pSightEnt ); - - return true; -} - -//----------------------------------------------------------------------------- - -CBaseEntity *CAI_Senses::GetFirstSeenEntity( AISightIter_t *pIter, seentype_t iSeenType ) const -{ - COMPILE_TIME_ASSERT( sizeof( AISightIter_t ) == sizeof( AISightIterVal_t ) ); - - AISightIterVal_t *pIterVal = (AISightIterVal_t *)pIter; - - // If we're searching for a specific type, start in that array - pIterVal->SeenArray = (char)iSeenType; - int iFirstArray = ( iSeenType == SEEN_ALL ) ? 0 : iSeenType; - - for ( int i = iFirstArray; i < (int)ARRAYSIZE( m_SeenArrays ); i++ ) - { - if ( m_SeenArrays[i]->Count() != 0 ) - { - pIterVal->array = i; - pIterVal->iNext = 1; - return (*m_SeenArrays[i])[0]; - } - } - - (*pIter) = (AISightIter_t)(-1); - return NULL; -} - -//----------------------------------------------------------------------------- - -CBaseEntity *CAI_Senses::GetNextSeenEntity( AISightIter_t *pIter ) const -{ - if ( ((int)*pIter) != -1 ) - { - AISightIterVal_t *pIterVal = (AISightIterVal_t *)pIter; - - for ( int i = pIterVal->array; i < (int)ARRAYSIZE( m_SeenArrays ); i++ ) - { - for ( int j = pIterVal->iNext; j < m_SeenArrays[i]->Count(); j++ ) - { - if ( (*m_SeenArrays[i])[j].Get() != NULL ) - { - pIterVal->array = i; - pIterVal->iNext = j+1; - return (*m_SeenArrays[i])[j]; - } - } - pIterVal->iNext = 0; - - // If we're searching for a specific type, don't move to the next array - if ( pIterVal->SeenArray != SEEN_ALL ) - break; - } - (*pIter) = (AISightIter_t)(-1); - } - return NULL; -} - -//----------------------------------------------------------------------------- - -void CAI_Senses::BeginGather() -{ - // clear my sight list - GetOuter()->m_pLink = NULL; -} - -//----------------------------------------------------------------------------- - -void CAI_Senses::EndGather( int nSeen, CUtlVector *pResult ) -{ - pResult->SetCount( nSeen ); - if ( nSeen ) - { - CBaseEntity *pCurrent = GetOuter()->m_pLink; - for (int i = 0; i < nSeen; i++ ) - { - Assert( pCurrent ); - (*pResult)[i].Set( pCurrent ); - pCurrent = pCurrent->m_pLink; - } - GetOuter()->m_pLink = NULL; - } -} - -//----------------------------------------------------------------------------- -// Look - Base class npc function to find enemies or -// food by sight. iDistance is distance ( in units ) that the -// npc can see. -// -// Sets the sight bits of the m_afConditions mask to indicate -// which types of entities were sighted. -// Function also sets the Looker's m_pLink -// to the head of a link list that contains all visible ents. -// (linked via each ent's m_pLink field) -// - -void CAI_Senses::Look( int iDistance ) -{ - if ( m_TimeLastLook != gpGlobals->curtime || m_LastLookDist != iDistance ) - { - //----------------------------- - - LookForHighPriorityEntities( iDistance ); - LookForNPCs( iDistance); - LookForObjects( iDistance ); - - //----------------------------- - - m_LastLookDist = iDistance; - m_TimeLastLook = gpGlobals->curtime; - } - - GetOuter()->OnLooked( iDistance ); -} - -//----------------------------------------------------------------------------- - -bool CAI_Senses::Look( CBaseEntity *pSightEnt ) -{ - if ( WaitingUntilSeen( pSightEnt ) ) - return false; - - if ( ShouldSeeEntity( pSightEnt ) && CanSeeEntity( pSightEnt ) ) - { - return SeeEntity( pSightEnt ); - } - return false; -} - -#ifdef PORTAL -bool CAI_Senses::LookThroughPortal( const CProp_Portal *pPortal, CBaseEntity *pSightEnt ) -{ - if ( WaitingUntilSeen( pSightEnt ) ) - return false; - - if ( ShouldSeeEntity( pSightEnt ) && CanSeeEntityThroughPortal( pPortal, pSightEnt ) ) - { - return SeeEntity( pSightEnt ); - } - return false; -} -#endif - -//----------------------------------------------------------------------------- - -int CAI_Senses::LookForHighPriorityEntities( int iDistance ) -{ - int nSeen = 0; - if ( gpGlobals->curtime - m_TimeLastLookHighPriority > AI_HIGH_PRIORITY_SEARCH_TIME ) - { - AI_PROFILE_SENSES(CAI_Senses_LookForHighPriorityEntities); - m_TimeLastLookHighPriority = gpGlobals->curtime; - - BeginGather(); - - float distSq = ( iDistance * iDistance ); - const Vector &origin = GetAbsOrigin(); - - // Players - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBaseEntity *pPlayer = UTIL_PlayerByIndex( i ); - - if ( pPlayer ) - { - if ( origin.DistToSqr(pPlayer->GetAbsOrigin()) < distSq && Look( pPlayer ) ) - { - nSeen++; - } -#ifdef PORTAL - else - { - CProp_Portal *pPortal = GetOuter()->FInViewConeThroughPortal( pPlayer ); - if ( pPortal && UTIL_Portal_DistanceThroughPortalSqr( pPortal, origin, pPlayer->GetAbsOrigin() ) < distSq && LookThroughPortal( pPortal, pPlayer ) ) - { - nSeen++; - } - } -#endif - } - } - - EndGather( nSeen, &m_SeenHighPriority ); - } - else - { - for ( int i = m_SeenHighPriority.Count() - 1; i >= 0; --i ) - { - if ( m_SeenHighPriority[i].Get() == NULL ) - m_SeenHighPriority.FastRemove( i ); - } - nSeen = m_SeenHighPriority.Count(); - } - - return nSeen; -} - -//----------------------------------------------------------------------------- - -int CAI_Senses::LookForNPCs( int iDistance ) -{ - bool bRemoveStaleFromCache = false; - float distSq = ( iDistance * iDistance ); - const Vector &origin = GetAbsOrigin(); - AI_Efficiency_t efficiency = GetOuter()->GetEfficiency(); - float timeNPCs = ( efficiency < AIE_VERY_EFFICIENT ) ? AI_STANDARD_NPC_SEARCH_TIME : AI_EFFICIENT_NPC_SEARCH_TIME; - if ( gpGlobals->curtime - m_TimeLastLookNPCs > timeNPCs ) - { - AI_PROFILE_SENSES(CAI_Senses_LookForNPCs); - - m_TimeLastLookNPCs = gpGlobals->curtime; - - if ( efficiency < AIE_SUPER_EFFICIENT ) - { - int i, nSeen = 0; - - BeginGather(); - - CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); - - for ( i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - if ( ppAIs[i] != GetOuter() && ( ppAIs[i]->ShouldNotDistanceCull() || origin.DistToSqr(ppAIs[i]->GetAbsOrigin()) < distSq ) ) - { - if ( Look( ppAIs[i] ) ) - { - nSeen++; - } - } - } - - EndGather( nSeen, &m_SeenNPCs ); - - return nSeen; - } - - bRemoveStaleFromCache = true; - // Fall through - } - - for ( int i = m_SeenNPCs.Count() - 1; i >= 0; --i ) - { - if ( m_SeenNPCs[i].Get() == NULL ) - { - m_SeenNPCs.FastRemove( i ); - } - else if ( bRemoveStaleFromCache ) - { - if ( ( !((CAI_BaseNPC *)m_SeenNPCs[i].Get())->ShouldNotDistanceCull() && - origin.DistToSqr(m_SeenNPCs[i]->GetAbsOrigin()) > distSq ) || - !Look( m_SeenNPCs[i] ) ) - { - m_SeenNPCs.FastRemove( i ); - } - } - } - - return m_SeenNPCs.Count(); -} - -//----------------------------------------------------------------------------- - -int CAI_Senses::LookForObjects( int iDistance ) -{ - const int BOX_QUERY_MASK = FL_OBJECT; - int nSeen = 0; - - if ( gpGlobals->curtime - m_TimeLastLookMisc > AI_MISC_SEARCH_TIME ) - { - AI_PROFILE_SENSES(CAI_Senses_LookForObjects); - m_TimeLastLookMisc = gpGlobals->curtime; - - BeginGather(); - - float distSq = ( iDistance * iDistance ); - const Vector &origin = GetAbsOrigin(); - int iter; - CBaseEntity *pEnt = g_AI_SensedObjectsManager.GetFirst( &iter ); - while ( pEnt ) - { - if ( pEnt->GetFlags() & BOX_QUERY_MASK ) - { - if ( origin.DistToSqr(pEnt->GetAbsOrigin()) < distSq && Look( pEnt) ) - { - nSeen++; - } - } - pEnt = g_AI_SensedObjectsManager.GetNext( &iter ); - } - - EndGather( nSeen, &m_SeenMisc ); - } - else - { - for ( int i = m_SeenMisc.Count() - 1; i >= 0; --i ) - { - if ( m_SeenMisc[i].Get() == NULL ) - m_SeenMisc.FastRemove( i ); - } - nSeen = m_SeenMisc.Count(); - } - - return nSeen; -} - -//----------------------------------------------------------------------------- - -float CAI_Senses::GetTimeLastUpdate( CBaseEntity *pEntity ) -{ - if ( !pEntity ) - return 0; - if ( pEntity->IsPlayer() ) - return m_TimeLastLookHighPriority; - if ( pEntity->IsNPC() ) - return m_TimeLastLookNPCs; - return m_TimeLastLookMisc; -} - -//----------------------------------------------------------------------------- - -CSound* CAI_Senses::GetFirstHeardSound( AISoundIter_t *pIter ) -{ - int iFirst = GetAudibleList(); - - if ( iFirst == SOUNDLIST_EMPTY ) - { - *pIter = NULL; - return NULL; - } - - *pIter = (AISoundIter_t)iFirst; - return CSoundEnt::SoundPointerForIndex( iFirst ); -} - -//----------------------------------------------------------------------------- - -CSound* CAI_Senses::GetNextHeardSound( AISoundIter_t *pIter ) -{ - if ( !*pIter ) - return NULL; - - int iCurrent = (int)*pIter; - - Assert( iCurrent != SOUNDLIST_EMPTY ); - if ( iCurrent == SOUNDLIST_EMPTY ) - { - *pIter = NULL; - return NULL; - } - - iCurrent = CSoundEnt::SoundPointerForIndex( iCurrent )->m_iNextAudible; - if ( iCurrent == SOUNDLIST_EMPTY ) - { - *pIter = NULL; - return NULL; - } - - *pIter = (AISoundIter_t)iCurrent; - return CSoundEnt::SoundPointerForIndex( iCurrent ); -} - -//----------------------------------------------------------------------------- - -CSound *CAI_Senses::GetClosestSound( bool fScent, int validTypes, bool bUsePriority ) -{ - float flBestDist = MAX_COORD_RANGE*MAX_COORD_RANGE;// so first nearby sound will become best so far. - float flDist; - int iBestPriority = SOUND_PRIORITY_VERY_LOW; - - AISoundIter_t iter; - - CSound *pResult = NULL; - CSound *pCurrent = GetFirstHeardSound( &iter ); - - Vector earPosition = GetOuter()->EarPosition(); - - while ( pCurrent ) - { - if ( ( !fScent && pCurrent->FIsSound() ) || - ( fScent && pCurrent->FIsScent() ) ) - { - if( pCurrent->IsSoundType( validTypes ) && !GetOuter()->ShouldIgnoreSound( pCurrent ) ) - { - if( !bUsePriority || GetOuter()->GetSoundPriority(pCurrent) >= iBestPriority ) - { - flDist = ( pCurrent->GetSoundOrigin() - earPosition ).LengthSqr(); - - if ( flDist < flBestDist ) - { - pResult = pCurrent; - flBestDist = flDist; - - iBestPriority = GetOuter()->GetSoundPriority(pCurrent); - } - } - } - } - - pCurrent = GetNextHeardSound( &iter ); - } - - return pResult; -} - -//----------------------------------------------------------------------------- - -void CAI_Senses::PerformSensing( void ) -{ - AI_PROFILE_SCOPE (CAI_BaseNPC_PerformSensing); - - // ----------------- - // Look - // ----------------- - if( !HasSensingFlags(SENSING_FLAGS_DONT_LOOK) ) - Look( static_cast(m_LookDist) ); - - // ------------------ - // Listen - // ------------------ - if( !HasSensingFlags(SENSING_FLAGS_DONT_LISTEN) ) - Listen(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -void CAI_SensedObjectsManager::Init() -{ - CBaseEntity *pEnt = NULL; - while ( ( pEnt = gEntList.NextEnt( pEnt ) ) != NULL ) - { - OnEntitySpawned( pEnt ); - } - - gEntList.AddListenerEntity( this ); -} - -//----------------------------------------------------------------------------- - -void CAI_SensedObjectsManager::Term() -{ - gEntList.RemoveListenerEntity( this ); - m_SensedObjects.RemoveAll(); -} - -//----------------------------------------------------------------------------- - -CBaseEntity *CAI_SensedObjectsManager::GetFirst( int *pIter ) -{ - if ( m_SensedObjects.Count() ) - { - *pIter = 1; - return m_SensedObjects[0]; - } - - *pIter = 0; - return NULL; -} - -//----------------------------------------------------------------------------- - -CBaseEntity *CAI_SensedObjectsManager::GetNext( int *pIter ) -{ - int i = *pIter; - if ( i && i < m_SensedObjects.Count() ) - { - (*pIter)++; - return m_SensedObjects[i]; - } - - *pIter = 0; - return NULL; -} - -//----------------------------------------------------------------------------- - -void CAI_SensedObjectsManager::OnEntitySpawned( CBaseEntity *pEntity ) -{ - if ( ( pEntity->GetFlags() & FL_OBJECT ) && !pEntity->IsPlayer() && !pEntity->IsNPC() ) - { - m_SensedObjects.AddToTail( pEntity ); - } -} - -//----------------------------------------------------------------------------- - -void CAI_SensedObjectsManager::OnEntityDeleted( CBaseEntity *pEntity ) -{ - if ( ( pEntity->GetFlags() & FL_OBJECT ) && !pEntity->IsPlayer() && !pEntity->IsNPC() ) - { - int i = m_SensedObjects.Find( pEntity ); - if ( i != m_SensedObjects.InvalidIndex() ) - m_SensedObjects.FastRemove( i ); - } -} - -void CAI_SensedObjectsManager::AddEntity( CBaseEntity *pEntity ) -{ - if ( m_SensedObjects.Find( pEntity ) != m_SensedObjects.InvalidIndex() ) - return; - - // We shouldn't be adding players or NPCs to this list - Assert( !pEntity->IsPlayer() && !pEntity->IsNPC() ); - - // Add the object flag so it gets removed when it dies - pEntity->AddFlag( FL_OBJECT ); - m_SensedObjects.AddToTail( pEntity ); -} - -//============================================================================= diff --git a/game/server/ai_senses.h b/game/server/ai_senses.h deleted file mode 100644 index 7277faa2b..000000000 --- a/game/server/ai_senses.h +++ /dev/null @@ -1,169 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_SENSES_H -#define AI_SENSES_H - -#include "tier1/utlvector.h" -#include "tier1/utlmap.h" -#include "simtimer.h" -#include "ai_component.h" -#include "soundent.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -class CBaseEntity; -class CSound; - -//------------------------------------- - -DECLARE_POINTER_HANDLE( AISightIter_t ); -DECLARE_POINTER_HANDLE( AISoundIter_t ); - -// GetFirstSeenEntity can take these as optional parameters to search for -// a specific type of entity. -enum seentype_t -{ - SEEN_ALL = -1, // Default - SEEN_HIGH_PRIORITY = 0, - SEEN_NPCS, - SEEN_MISC -}; - -#define SENSING_FLAGS_NONE 0x00000000 -#define SENSING_FLAGS_DONT_LOOK 0x00000001 // Effectively makes the NPC blind -#define SENSING_FLAGS_DONT_LISTEN 0x00000002 // Effectively makes the NPC deaf - -//----------------------------------------------------------------------------- -// class CAI_ScriptConditions -// -// Purpose: -//----------------------------------------------------------------------------- - -class CAI_Senses : public CAI_Component -{ -public: - CAI_Senses() - : m_LookDist(2048), - m_LastLookDist(-1), - m_TimeLastLook(-1), - m_iAudibleList(0), - m_TimeLastLookHighPriority( -1 ), - m_TimeLastLookNPCs( -1 ), - m_TimeLastLookMisc( -1 ) - { - m_SeenArrays[0] = &m_SeenHighPriority; - m_SeenArrays[1] = &m_SeenNPCs; - m_SeenArrays[2] = &m_SeenMisc; - m_iSensingFlags = SENSING_FLAGS_NONE; - } - - float GetDistLook() const { return m_LookDist; } - void SetDistLook( float flDistLook ) { m_LookDist = flDistLook; } - - void PerformSensing(); - - void Listen( void ); - void Look( int iDistance );// basic sight function for npcs - - bool ShouldSeeEntity( CBaseEntity *pEntity ); // logical query - bool CanSeeEntity( CBaseEntity *pSightEnt ); // more expensive cone & raycast test -#ifdef PORTAL - bool CanSeeEntityThroughPortal( const CProp_Portal *pPortal, CBaseEntity *pSightEnt ); // more expensive cone & raycast test -#endif - - bool DidSeeEntity( CBaseEntity *pSightEnt ) const; // a less expensive query that looks at cached results from recent conditionsa gathering - - CBaseEntity * GetFirstSeenEntity( AISightIter_t *pIter, seentype_t iSeenType = SEEN_ALL ) const; - CBaseEntity * GetNextSeenEntity( AISightIter_t *pIter ) const; - - CSound * GetFirstHeardSound( AISoundIter_t *pIter ); - CSound * GetNextHeardSound( AISoundIter_t *pIter ); - CSound * GetClosestSound( bool fScent = false, int validTypes = ALL_SOUNDS | ALL_SCENTS, bool bUsePriority = true ); - - bool CanHearSound( CSound *pSound ); - - //--------------------------------- - - float GetTimeLastUpdate( CBaseEntity *pEntity ); - - //--------------------------------- - - void AddSensingFlags( int iFlags ) { m_iSensingFlags |= iFlags; } - void RemoveSensingFlags( int iFlags ) { m_iSensingFlags &= ~iFlags; } - bool HasSensingFlags( int iFlags ) { return (m_iSensingFlags & iFlags) == iFlags; } - - DECLARE_SIMPLE_DATADESC(); - -private: - int GetAudibleList() const { return m_iAudibleList; } - - bool WaitingUntilSeen( CBaseEntity *pSightEnt ); - - void BeginGather(); - void NoteSeenEntity( CBaseEntity *pSightEnt ); - void EndGather( int nSeen, CUtlVector *pResult ); - - bool Look( CBaseEntity *pSightEnt ); -#ifdef PORTAL - bool LookThroughPortal( const CProp_Portal *pPortal, CBaseEntity *pSightEnt ); -#endif - - int LookForHighPriorityEntities( int iDistance ); - int LookForNPCs( int iDistance ); - int LookForObjects( int iDistance ); - - bool SeeEntity( CBaseEntity *pEntity ); - - float m_LookDist; // distance npc sees (Default 2048) - float m_LastLookDist; - float m_TimeLastLook; - - int m_iAudibleList; // first index of a linked list of sounds that the npc can hear. - - CUtlVector m_SeenHighPriority; - CUtlVector m_SeenNPCs; - CUtlVector m_SeenMisc; - - CUtlVector *m_SeenArrays[3]; - - float m_TimeLastLookHighPriority; - float m_TimeLastLookNPCs; - float m_TimeLastLookMisc; - - int m_iSensingFlags; -}; - -//----------------------------------------------------------------------------- - -class CAI_SensedObjectsManager : public IEntityListener -{ -public: - void Init(); - void Term(); - - CBaseEntity * GetFirst( int *pIter ); - CBaseEntity * GetNext( int *pIter ); - - virtual void AddEntity( CBaseEntity *pEntity ); - -private: - virtual void OnEntitySpawned( CBaseEntity *pEntity ); - virtual void OnEntityDeleted( CBaseEntity *pEntity ); - - CUtlVector m_SensedObjects; -}; - -extern CAI_SensedObjectsManager g_AI_SensedObjectsManager; - -//----------------------------------------------------------------------------- - - - -#endif // AI_SENSES_H diff --git a/game/server/ai_sentence.cpp b/game/server/ai_sentence.cpp deleted file mode 100644 index 10fdfcc3a..000000000 --- a/game/server/ai_sentence.cpp +++ /dev/null @@ -1,211 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ai_sentence.h" -#include "ai_squad.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar npc_sentences( "npc_sentences", "0" ); - - -//----------------------------------------------------------------------------- -// Save/load -//----------------------------------------------------------------------------- -BEGIN_SIMPLE_DATADESC(CAI_SentenceBase) - DEFINE_FIELD( m_voicePitch, FIELD_INTEGER ), - DEFINE_FIELD( m_nQueuedSentenceIndex, FIELD_INTEGER ), - DEFINE_FIELD( m_flQueueTimeout, FIELD_TIME ), - DEFINE_FIELD( m_nQueueSoundPriority, FIELD_INTEGER ), -END_DATADESC(); - - -//----------------------------------------------------------------------------- -// Speech -//----------------------------------------------------------------------------- -CAI_SentenceBase::CAI_SentenceBase() -{ - ClearQueue(); -} - - -//----------------------------------------------------------------------------- -// Debug output -//----------------------------------------------------------------------------- -void CAI_SentenceBase::SentenceMsg( const char *pStatus, const char *pSentence ) -{ - int nMode = npc_sentences.GetInt(); - switch( nMode ) - { - case 0: - return; - - case 1: - DevMsg( "SENTENCE [%d %.2f] %s: %s\n", GetOuter()->entindex(), gpGlobals->curtime, pStatus, pSentence ); - break; - - case 2: - DevMsg( GetOuter(), "SENTENCE [%d %.2f] %s: %s\n", GetOuter()->entindex(), gpGlobals->curtime, pStatus, pSentence ); - break; - } -} - - -//----------------------------------------------------------------------------- -// Check for queued-up-sentences + speak them -//----------------------------------------------------------------------------- -void CAI_SentenceBase::ClearQueue() -{ - m_nQueuedSentenceIndex = -1; -} - - -//----------------------------------------------------------------------------- -// Check for queued-up-sentences + speak them -//----------------------------------------------------------------------------- -void CAI_SentenceBase::UpdateSentenceQueue() -{ - if ( m_nQueuedSentenceIndex == -1 ) - return; - - // Check for timeout - if ( m_flQueueTimeout < gpGlobals->curtime ) - { - ClearQueue(); - return; - } - - if ( GetOuter()->FOkToMakeSound( m_nQueueSoundPriority ) ) - { - SENTENCEG_PlaySentenceIndex( GetOuter()->edict(), m_nQueuedSentenceIndex, GetVolume(), GetSoundLevel(), 0, GetVoicePitch() ); - - const char *pSentenceName = engine->SentenceNameFromIndex( m_nQueuedSentenceIndex ); - SentenceMsg( "Speaking [from QUEUE]", pSentenceName ); - - GetOuter()->JustMadeSound( m_nQueueSoundPriority ); - ClearQueue(); - } -} - - -//----------------------------------------------------------------------------- -// Speech criteria -//----------------------------------------------------------------------------- -bool CAI_SentenceBase::MatchesCriteria( SentenceCriteria_t nCriteria ) -{ - switch( nCriteria ) - { - case SENTENCE_CRITERIA_ALWAYS: - return true; - - case SENTENCE_CRITERIA_NORMAL: - return (GetOuter()->GetState() == NPC_STATE_COMBAT) || (GetOuter()->HasSpawnFlags( SF_NPC_GAG ) == 0); - - case SENTENCE_CRITERIA_IN_SQUAD: - if ( (GetOuter()->GetState() != NPC_STATE_COMBAT) && GetOuter()->HasSpawnFlags( SF_NPC_GAG ) ) - return false; - return GetOuter()->GetSquad() && (GetOuter()->GetSquad()->NumMembers() > 1); - - case SENTENCE_CRITERIA_SQUAD_LEADER: - { - if ( (GetOuter()->GetState() != NPC_STATE_COMBAT) && GetOuter()->HasSpawnFlags( SF_NPC_GAG ) ) - return false; - - CAI_Squad *pSquad = GetOuter()->GetSquad(); - return pSquad && (pSquad->NumMembers() > 1) && pSquad->IsLeader( GetOuter() ); - } - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Play the actual sentence -//----------------------------------------------------------------------------- -int CAI_SentenceBase::PlaySentence( const char *pSentence ) -{ - int nSentenceIndex = SENTENCEG_PlayRndSz( GetOuter()->edict(), pSentence, GetVolume(), GetSoundLevel(), 0, GetVoicePitch()); - if ( nSentenceIndex < 0 ) - { - SentenceMsg( "BOGUS", pSentence ); - return -1; - } - - const char *pSentenceName = engine->SentenceNameFromIndex( nSentenceIndex ); - SentenceMsg( "Speaking", pSentenceName ); - return nSentenceIndex; -} - - -//----------------------------------------------------------------------------- -// Speech -//----------------------------------------------------------------------------- -int CAI_SentenceBase::Speak( const char *pSentence, SentencePriority_t nSoundPriority, SentenceCriteria_t nCriteria ) -{ - if ( !MatchesCriteria(nCriteria) ) - return -1; - - // Speaking clears the queue - ClearQueue(); - - if ( nSoundPriority == SENTENCE_PRIORITY_INVALID ) - { - return PlaySentence( pSentence ); - } - - int nSentenceIndex = -1; - if ( GetOuter()->FOkToMakeSound( nSoundPriority ) ) - { - nSentenceIndex = PlaySentence( pSentence ); - - // Make sure sentence length utility works -// float flSentenceTime = enginesound->GetSoundDuration( nSentenceIndex ); - GetOuter()->JustMadeSound( nSoundPriority, 2.0f /*flSentenceTime*/ ); - } - else - { - SentenceMsg( "CULL", pSentence ); - } - - return nSentenceIndex; -} - - -//----------------------------------------------------------------------------- -// Speech w/ queue -//----------------------------------------------------------------------------- -int CAI_SentenceBase::SpeakQueued( const char *pSentence, SentencePriority_t nSoundPriority, SentenceCriteria_t nCriteria ) -{ - if ( !MatchesCriteria(nCriteria) ) - return -1; - - // Speaking clears the queue - ClearQueue(); - - int nSentenceIndex = Speak( pSentence, nSoundPriority, nCriteria ); - if ( nSentenceIndex >= 0 ) - return nSentenceIndex; - - // Queue up the sentence for later playing - int nQueuedSentenceIndex = SENTENCEG_PickRndSz( pSentence ); - if ( nQueuedSentenceIndex == -1 ) - return -1; - - int nSquadCount = GetOuter()->GetSquad() ? GetOuter()->GetSquad()->NumMembers() : 1; - m_flQueueTimeout = gpGlobals->curtime + nSquadCount * 2.0f; - m_nQueueSoundPriority = nSoundPriority; - m_nQueuedSentenceIndex = nQueuedSentenceIndex; - return -1; -} - - - - - diff --git a/game/server/ai_sentence.h b/game/server/ai_sentence.h deleted file mode 100644 index b4d15fe3c..000000000 --- a/game/server/ai_sentence.h +++ /dev/null @@ -1,172 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_SENTENCE_H -#define AI_SENTENCE_H - -#include "ai_component.h" -#include "ai_basenpc.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" - - -//----------------------------------------------------------------------------- -// Sentence helper class used by humanoids sometimes. To use: -// 1) Include it into the leaf class -// 2) Use DEFINE_EMBEDDED to save/load its state -// 3) Call Init in the CreateComponents method -// 4) Use Speak() when it's time to speak -// 5) Add m_Sentences.UpdateSentenceQueue(); to the PrescheduleThink method of an NPC -// to get queued sentence support working -//----------------------------------------------------------------------------- -enum SentenceCriteria_t -{ - SENTENCE_CRITERIA_ALWAYS = 0, - SENTENCE_CRITERIA_NORMAL, // Obeys gag rules - SENTENCE_CRITERIA_IN_SQUAD, - SENTENCE_CRITERIA_SQUAD_LEADER, -}; - -enum SentencePriority_t -{ - SENTENCE_PRIORITY_INVALID = -1, - SENTENCE_PRIORITY_NORMAL = 0, - SENTENCE_PRIORITY_MEDIUM = 1, - SENTENCE_PRIORITY_HIGH = 2, -}; - - -//----------------------------------------------------------------------------- -// This is the met of the class -//----------------------------------------------------------------------------- -abstract_class CAI_SentenceBase : public CAI_Component -{ - DECLARE_CLASS_NOBASE( CAI_SentenceBase ); - DECLARE_SIMPLE_DATADESC(); - -public: - CAI_SentenceBase(); - - void SetVoicePitch( int voicePitch ); - int GetVoicePitch() const; - - // Check for queued-up-sentences + speak them - void UpdateSentenceQueue(); - - // Returns the sentence index played, which can be used to determine - // the sentence length of time using engine->SentenceLength - int Speak( const char *pSentence, SentencePriority_t nSoundPriority = SENTENCE_PRIORITY_NORMAL, SentenceCriteria_t nCriteria = SENTENCE_CRITERIA_IN_SQUAD ); - - // Returns the sentence index played, which can be used to determine - // the sentence length of time using engine->SentenceLength. If the sentence - // was queued, then -1 is returned, which is the same result as if the sound wasn't played - int SpeakQueued( const char *pSentence, SentencePriority_t nSoundPriority = SENTENCE_PRIORITY_NORMAL, SentenceCriteria_t nCriteria = SENTENCE_CRITERIA_IN_SQUAD ); - - // Clears the sentence queue - void ClearQueue(); - -protected: - virtual float GetVolume() = 0; - virtual soundlevel_t GetSoundLevel() = 0; - -private: - // Speech criteria - bool MatchesCriteria( SentenceCriteria_t nCriteria ); - - // Play the actual sentence - int PlaySentence( const char *pSentence ); - - // Debug output - void SentenceMsg( const char *pStatus, const char *pSentence ); - - int m_voicePitch; - int m_nQueuedSentenceIndex; - float m_flQueueTimeout; - int m_nQueueSoundPriority; -}; - - -//----------------------------------------------------------------------------- -// NOTE: This is a template class so each user has a different set of globals -//----------------------------------------------------------------------------- -template< class NPC_CLASS > -class CAI_Sentence : public CAI_SentenceBase -{ - DECLARE_CLASS_NOFRIEND( CAI_Sentence, CAI_SentenceBase ); - -public: - void Init( NPC_CLASS *pOuter, const char *pGameSound ); - -protected: - virtual float GetVolume() { return m_sentenceVolume; } - virtual soundlevel_t GetSoundLevel() { return m_sentenceSoundlevel; } - -private: - static float m_sentenceVolume; - static soundlevel_t m_sentenceSoundlevel; - static int m_voicePitchMin; - static int m_voicePitchMax; -}; - - -//----------------------------------------------------------------------------- -// Voice pitch -//----------------------------------------------------------------------------- -inline void CAI_SentenceBase::SetVoicePitch( int voicePitch ) -{ - m_voicePitch = voicePitch; -} - -inline int CAI_SentenceBase::GetVoicePitch() const -{ - return m_voicePitch; -} - - -//----------------------------------------------------------------------------- -// Set up the class's sentence information -//----------------------------------------------------------------------------- -template< class NPC_CLASS > -void CAI_Sentence< NPC_CLASS >::Init( NPC_CLASS *pOuter, const char *pGameSound ) -{ - SetOuter( pOuter ); - - if ( m_voicePitchMin <= 0 || m_voicePitchMax <= 0 ) - { - // init the sentence parameters using a dummy gamesounds entry - CSoundParameters params; - if ( GetOuter()->GetParametersForSound( pGameSound, params, NULL ) ) - { - m_sentenceVolume = params.volume; - m_sentenceSoundlevel = params.soundlevel; - m_voicePitchMin = params.pitchlow; - m_voicePitchMax = params.pitchhigh; - } - } - - // Select a voice pitch - if ( random->RandomInt(0,1) ) - { - SetVoicePitch( random->RandomInt( m_voicePitchMin, m_voicePitchMax ) ); - } - else - { - SetVoicePitch( 100 ); - } -} - - -//----------------------------------------------------------------------------- -// Global instantiation -//----------------------------------------------------------------------------- -template< class NPC_CLASS > float CAI_Sentence< NPC_CLASS >::m_sentenceVolume = 1.0f; -template< class NPC_CLASS > soundlevel_t CAI_Sentence< NPC_CLASS >::m_sentenceSoundlevel = SNDLVL_NORM; -template< class NPC_CLASS > int CAI_Sentence< NPC_CLASS >::m_voicePitchMin = 0; -template< class NPC_CLASS > int CAI_Sentence< NPC_CLASS >::m_voicePitchMax = 0; - - - -#endif // AI_SENTENCE_H diff --git a/game/server/ai_speech.cpp b/game/server/ai_speech.cpp deleted file mode 100644 index c4a99fe80..000000000 --- a/game/server/ai_speech.cpp +++ /dev/null @@ -1,1026 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -#include "ai_speech.h" - -#include "game.h" -#include "engine/IEngineSound.h" -#include "KeyValues.h" -#include "ai_basenpc.h" -#include "AI_Criteria.h" -#include "isaverestore.h" -#include "sceneentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include - -#define DEBUG_AISPEECH 1 -#ifdef DEBUG_AISPEECH -ConVar ai_debug_speech( "ai_debug_speech", "0" ); -#define DebuggingSpeech() ai_debug_speech.GetBool() -#else -inline void SpeechMsg( ... ) {} -#define DebuggingSpeech() (false) -#endif - -extern ConVar rr_debugresponses; - -//----------------------------------------------------------------------------- - -CAI_TimedSemaphore g_AIFriendliesTalkSemaphore; -CAI_TimedSemaphore g_AIFoesTalkSemaphore; - -ConceptHistory_t::~ConceptHistory_t() -{ - if ( response ) - { - delete response; - } - response = NULL; -} - -ConceptHistory_t::ConceptHistory_t( const ConceptHistory_t& src ) -{ - timeSpoken = src.timeSpoken; - response = NULL; - if ( src.response ) - { - response = new AI_Response( *src.response ); - } -} - -ConceptHistory_t& ConceptHistory_t::operator =( const ConceptHistory_t& src ) -{ - if ( this == &src ) - return *this; - - timeSpoken = src.timeSpoken; - response = NULL; - if ( src.response ) - { - response = new AI_Response( *src.response ); - } - - return *this; -} - -BEGIN_SIMPLE_DATADESC( ConceptHistory_t ) - DEFINE_FIELD( timeSpoken, FIELD_TIME ), // Relative to server time - // DEFINE_EMBEDDED( response, FIELD_??? ), // This is manually saved/restored by the ConceptHistory saverestore ops below -END_DATADESC() - -class CConceptHistoriesDataOps : public CDefSaveRestoreOps -{ -public: - virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave ) - { - CUtlDict< ConceptHistory_t, int > *ch = ((CUtlDict< ConceptHistory_t, int > *)fieldInfo.pField); - int count = ch->Count(); - pSave->WriteInt( &count ); - for ( int i = 0 ; i < count; i++ ) - { - ConceptHistory_t *pHistory = &(*ch)[ i ]; - - pSave->StartBlock(); - { - - // Write element name - pSave->WriteString( ch->GetElementName( i ) ); - - // Write data - pSave->WriteAll( pHistory ); - // Write response blob - bool hasresponse = pHistory->response != NULL ? true : false; - pSave->WriteBool( &hasresponse ); - if ( hasresponse ) - { - pSave->WriteAll( pHistory->response ); - } - // TODO: Could blat out pHistory->criteria pointer here, if it's needed - } - pSave->EndBlock(); - } - } - - virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore ) - { - CUtlDict< ConceptHistory_t, int > *ch = ((CUtlDict< ConceptHistory_t, int > *)fieldInfo.pField); - - int count = pRestore->ReadInt(); - Assert( count >= 0 ); - for ( int i = 0 ; i < count; i++ ) - { - char conceptname[ 512 ]; - conceptname[ 0 ] = 0; - ConceptHistory_t history; - - pRestore->StartBlock(); - { - pRestore->ReadString( conceptname, sizeof( conceptname ), 0 ); - - pRestore->ReadAll( &history ); - - bool hasresponse = false; - - pRestore->ReadBool( &hasresponse ); - if ( hasresponse ) - { - history.response = new AI_Response(); - pRestore->ReadAll( history.response ); - } - } - - pRestore->EndBlock(); - - // TODO: Could restore pHistory->criteria pointer here, if it's needed - - // Add to utldict - if ( conceptname[0] != 0 ) - { - ch->Insert( conceptname, history ); - } - else - { - Assert( !"Error restoring ConceptHistory_t, discarding!" ); - } - } - } - - virtual void MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - } - - virtual bool IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - CUtlDict< ConceptHistory_t, int > *ch = ((CUtlDict< ConceptHistory_t, int > *)fieldInfo.pField); - return ch->Count() == 0 ? true : false; - } -}; - -CConceptHistoriesDataOps g_ConceptHistoriesSaveDataOps; - -//----------------------------------------------------------------------------- -// -// CLASS: CAI_Expresser -// - -BEGIN_SIMPLE_DATADESC( CAI_Expresser ) - // m_pSink (reconnected on load) -// DEFINE_FIELD( m_pOuter, CHandle < CBaseFlex > ), - DEFINE_CUSTOM_FIELD( m_ConceptHistories, &g_ConceptHistoriesSaveDataOps ), - DEFINE_FIELD( m_flStopTalkTime, FIELD_TIME ), - DEFINE_FIELD( m_flStopTalkTimeWithoutDelay, FIELD_TIME ), - DEFINE_FIELD( m_flBlockedTalkTime, FIELD_TIME ), - DEFINE_FIELD( m_voicePitch, FIELD_INTEGER ), - DEFINE_FIELD( m_flLastTimeAcceptedSpeak, FIELD_TIME ), -END_DATADESC() - -//------------------------------------- - -bool CAI_Expresser::SemaphoreIsAvailable( CBaseEntity *pTalker ) -{ - if ( !GetSink()->UseSemaphore() ) - return true; - - CAI_TimedSemaphore *pSemaphore = GetMySpeechSemaphore( pTalker->MyNPCPointer() ); - return (pSemaphore ? pSemaphore->IsAvailable( pTalker ) : true); -} - -//------------------------------------- - -float CAI_Expresser::GetSemaphoreAvailableTime( CBaseEntity *pTalker ) -{ - CAI_TimedSemaphore *pSemaphore = GetMySpeechSemaphore( pTalker->MyNPCPointer() ); - return (pSemaphore ? pSemaphore->GetReleaseTime() : 0); -} - -//------------------------------------- - -int CAI_Expresser::GetVoicePitch() const -{ - return m_voicePitch + random->RandomInt(0,3); -} - -#ifdef DEBUG -static int g_nExpressers; -#endif - -CAI_Expresser::CAI_Expresser( CBaseFlex *pOuter ) - : m_pSink( NULL ), - m_flStopTalkTime( 0 ), - m_flStopTalkTimeWithoutDelay( 0 ), - m_flBlockedTalkTime( 0 ), - m_voicePitch( 100 ), - m_pOuter( pOuter ) -{ -#ifdef DEBUG - g_nExpressers++; -#endif -} - -CAI_Expresser::~CAI_Expresser() -{ - m_ConceptHistories.Purge(); - - CAI_TimedSemaphore *pSemaphore = GetMySpeechSemaphore( GetOuter() ); - if ( pSemaphore ) - { - if ( pSemaphore->GetOwner() == GetOuter() ) - pSemaphore->Release(); - -#ifdef DEBUG - g_nExpressers--; - if ( g_nExpressers == 0 && pSemaphore->GetOwner() ) - DevMsg( 2, "Speech semaphore being held by non-talker entity\n" ); -#endif - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_Expresser::TestAllResponses() -{ - IResponseSystem *pResponseSystem = GetOuter()->GetResponseSystem(); - if ( pResponseSystem ) - { - CUtlVector responses; - pResponseSystem->GetAllResponses( &responses ); - for ( int i = 0; i < responses.Count(); i++ ) - { - char response[ 256 ]; - responses[i]->GetResponse( response, sizeof( response ) ); - - Msg( "Response: %s\n", response ); - SpeakDispatchResponse( "", responses[i] ); - } - } -} - -//----------------------------------------------------------------------------- - -static const int LEN_SPECIFIC_SCENE_MODIFIER = strlen( AI_SPECIFIC_SCENE_MODIFIER ); - -//----------------------------------------------------------------------------- -// Purpose: Searches for a possible response -// Input : concept - -// NULL - -// Output : AI_Response -//----------------------------------------------------------------------------- -AI_Response *CAI_Expresser::SpeakFindResponse( AIConcept_t concept, const char *modifiers /*= NULL*/ ) -{ - IResponseSystem *rs = GetOuter()->GetResponseSystem(); - if ( !rs ) - { - Assert( !"No response system installed for CAI_Expresser::GetOuter()!!!" ); - return NULL; - } - - AI_CriteriaSet set; - // Always include the concept name - set.AppendCriteria( "concept", concept, CONCEPT_WEIGHT ); - - // Always include any optional modifiers - if ( modifiers != NULL ) - { - char copy_modifiers[ 255 ]; - const char *pCopy; - char key[ 128 ] = { 0 }; - char value[ 128 ] = { 0 }; - - Q_strncpy( copy_modifiers, modifiers, sizeof( copy_modifiers ) ); - pCopy = copy_modifiers; - - while( pCopy ) - { - pCopy = SplitContext( pCopy, key, sizeof( key ), value, sizeof( value ), NULL ); - - if( *key && *value ) - { - set.AppendCriteria( key, value, CONCEPT_WEIGHT ); - } - } - } - - // Let our outer fill in most match criteria - GetOuter()->ModifyOrAppendCriteria( set ); - - // Append local player criteria to set, but not if this is a player doing the talking - if ( !GetOuter()->IsPlayer() ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); - if( pPlayer ) - pPlayer->ModifyOrAppendPlayerCriteria( set ); - } - - // Now that we have a criteria set, ask for a suitable response - AI_Response *result = new AI_Response; - Assert( result && "new AI_Response: Returned a NULL AI_Response!" ); - bool found = rs->FindBestResponse( set, *result, this ); - - if ( rr_debugresponses.GetInt() == 3 ) - { - if ( ( GetOuter()->MyNPCPointer() && GetOuter()->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT ) || GetOuter()->IsPlayer() ) - { - const char *pszName; - if ( GetOuter()->IsPlayer() ) - { - pszName = ((CBasePlayer*)GetOuter())->GetPlayerName(); - } - else - { - pszName = GetOuter()->GetDebugName(); - } - - if ( found ) - { - char response[ 256 ]; - result->GetResponse( response, sizeof( response ) ); - - Warning( "RESPONSERULES: %s spoke '%s'. Found response '%s'.\n", pszName, concept, response ); - } - else - { - Warning( "RESPONSERULES: %s spoke '%s'. Found no matching response.\n", pszName, concept ); - } - } - } - - if ( !found ) - { - //Assert( !"rs->FindBestResponse: Returned a NULL AI_Response!" ); - delete result; - return NULL; - } - - char response[ 256 ]; - result->GetResponse( response, sizeof( response ) ); - - if ( !response[0] ) - { - delete result; - return NULL; - } - - if ( result->GetOdds() < 100 && random->RandomInt( 1, 100 ) <= result->GetOdds() ) - { - delete result; - return NULL; - } - - return result; -} - -//----------------------------------------------------------------------------- -// Purpose: Dispatches the result -// Input : *response - -//----------------------------------------------------------------------------- -bool CAI_Expresser::SpeakDispatchResponse( AIConcept_t concept, AI_Response *result, IRecipientFilter *filter /* = NULL */ ) -{ - char response[ 256 ]; - result->GetResponse( response, sizeof( response ) ); - - float delay = result->GetDelay(); - - bool spoke = false; - - soundlevel_t soundlevel = result->GetSoundLevel(); - - if ( IsSpeaking() && concept[0] != 0 ) - { - DevMsg( "SpeakDispatchResponse: Entity ( %i/%s ) already speaking, forcing '%s'\n", GetOuter()->entindex(), STRING( GetOuter()->GetEntityName() ), concept ); - - // Tracker 15911: Can break the game if we stop an imported map placed lcs here, so only - // cancel actor out of instanced scripted scenes. ywb - RemoveActorFromScriptedScenes( GetOuter(), true /*instanced scenes only*/ ); - GetOuter()->SentenceStop(); - - if ( IsRunningScriptedScene( GetOuter() ) ) - { - DevMsg( "SpeakDispatchResponse: Entity ( %i/%s ) refusing to speak due to scene entity, tossing '%s'\n", GetOuter()->entindex(), STRING( GetOuter()->GetEntityName() ), concept ); - delete result; - return false; - } - } - - switch ( result->GetType() ) - { - default: - case RESPONSE_NONE: - break; - - case RESPONSE_SPEAK: - { - if ( !result->ShouldntUseScene() ) - { - // This generates a fake CChoreoScene wrapping the sound.txt name - spoke = SpeakAutoGeneratedScene( response, delay ); - } - else - { - float speakTime = GetResponseDuration( result ); - GetOuter()->EmitSound( response ); - - DevMsg( "SpeakDispatchResponse: Entity ( %i/%s ) playing sound '%s'\n", GetOuter()->entindex(), STRING( GetOuter()->GetEntityName() ), response ); - NoteSpeaking( speakTime, delay ); - spoke = true; - } - } - break; - - case RESPONSE_SENTENCE: - { - spoke = ( -1 != SpeakRawSentence( response, delay, VOL_NORM, soundlevel ) ) ? true : false; - } - break; - - case RESPONSE_SCENE: - { - spoke = SpeakRawScene( response, delay, result, filter ); - } - break; - - case RESPONSE_RESPONSE: - { - // This should have been recursively resolved already - Assert( 0 ); - } - break; - case RESPONSE_PRINT: - { - if ( g_pDeveloper->GetInt() > 0 ) - { - Vector vPrintPos; - GetOuter()->CollisionProp()->NormalizedToWorldSpace( Vector(0.5,0.5,1.0f), &vPrintPos ); - NDebugOverlay::Text( vPrintPos, response, true, 1.5 ); - spoke = true; - } - } - break; - } - - if ( spoke ) - { - m_flLastTimeAcceptedSpeak = gpGlobals->curtime; - if ( DebuggingSpeech() && g_pDeveloper->GetInt() > 0 && response[0] != '\0' && result->GetType() != RESPONSE_PRINT ) - { - Vector vPrintPos; - GetOuter()->CollisionProp()->NormalizedToWorldSpace( Vector(0.5,0.5,1.0f), &vPrintPos ); - NDebugOverlay::Text( vPrintPos, CFmtStr( "%s: %s", concept, response ), true, 1.5 ); - } - - if ( result->IsApplyContextToWorld() ) - { - CBaseEntity *pEntity = CBaseEntity::Instance( engine->PEntityOfEntIndex( 0 ) ); - if ( pEntity ) - { - pEntity->AddContext( result->GetContext() ); - } - } - else - { - GetOuter()->AddContext( result->GetContext() ); - } - SetSpokeConcept( concept, result ); - } - else - { - delete result; - } - - return spoke; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *response - -// Output : float -//----------------------------------------------------------------------------- -float CAI_Expresser::GetResponseDuration( AI_Response *result ) -{ - Assert( result ); - char response[ 256 ]; - result->GetResponse( response, sizeof( response ) ); - - switch ( result->GetType() ) - { - default: - case RESPONSE_NONE: - break; - case RESPONSE_SPEAK: - { - return GetOuter()->GetSoundDuration( response, STRING( GetOuter()->GetModelName() ) ); - } - break; - case RESPONSE_SENTENCE: - { - Assert( 0 ); - return 999.0f; - } - break; - case RESPONSE_SCENE: - { - return GetSceneDuration( response ); - } - break; - case RESPONSE_RESPONSE: - { - // This should have been recursively resolved already - Assert( 0 ); - } - break; - case RESPONSE_PRINT: - { - return 1.0; - } - break; - } - - return 0.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: Placeholder for rules based response system -// Input : concept - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_Expresser::Speak( AIConcept_t concept, const char *modifiers /*= NULL*/, char *pszOutResponseChosen /* = NULL*/, size_t bufsize /* = 0 */, IRecipientFilter *filter /* = NULL */ ) -{ - AI_Response *result = SpeakFindResponse( concept, modifiers ); - if ( !result ) - { - return false; - } - - SpeechMsg( GetOuter(), "%s (%x) spoke %s (%f)\n", STRING(GetOuter()->GetEntityName()), GetOuter(), concept, gpGlobals->curtime ); - - bool spoke = SpeakDispatchResponse( concept, result, filter ); - if ( pszOutResponseChosen ) - { - result->GetResponse( pszOutResponseChosen, bufsize ); - } - - return spoke; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_Expresser::SpeakRawScene( const char *pszScene, float delay, AI_Response *response, IRecipientFilter *filter /* = NULL */ ) -{ - float sceneLength = GetOuter()->PlayScene( pszScene, delay, response, filter ); - if ( sceneLength > 0 ) - { - SpeechMsg( GetOuter(), "SpeakRawScene( %s, %f) %f\n", pszScene, delay, sceneLength ); - -#if defined( HL2_EPISODIC ) || defined( TF_DLL ) - char szInstanceFilename[256]; - GetOuter()->GenderExpandString( pszScene, szInstanceFilename, sizeof( szInstanceFilename ) ); - // Only mark ourselves as speaking if the scene has speech - if ( GetSceneSpeechCount(szInstanceFilename) > 0 ) - { - NoteSpeaking( sceneLength, delay ); - } -#else - NoteSpeaking( sceneLength, delay ); -#endif - - return true; - } - return false; -} - -// This will create a fake .vcd/CChoreoScene to wrap the sound to be played -bool CAI_Expresser::SpeakAutoGeneratedScene( char const *soundname, float delay ) -{ - float speakTime = GetOuter()->PlayAutoGeneratedSoundScene( soundname ); - if ( speakTime > 0 ) - { - SpeechMsg( GetOuter(), "SpeakAutoGeneratedScene( %s, %f) %f\n", soundname, delay, speakTime ); - NoteSpeaking( speakTime, delay ); - return true; - } - return false; -} - -//------------------------------------- - -int CAI_Expresser::SpeakRawSentence( const char *pszSentence, float delay, float volume, soundlevel_t soundlevel, CBaseEntity *pListener ) -{ - int sentenceIndex = -1; - - if ( !pszSentence ) - return sentenceIndex; - - if ( pszSentence[0] == AI_SP_SPECIFIC_SENTENCE ) - { - sentenceIndex = SENTENCEG_Lookup( pszSentence ); - - if( sentenceIndex == -1 ) - { - // sentence not found - return -1; - } - - CPASAttenuationFilter filter( GetOuter(), soundlevel ); - CBaseEntity::EmitSentenceByIndex( filter, GetOuter()->entindex(), CHAN_VOICE, sentenceIndex, volume, soundlevel, 0, GetVoicePitch()); - } - else - { - sentenceIndex = SENTENCEG_PlayRndSz( GetOuter()->NetworkProp()->edict(), pszSentence, volume, soundlevel, 0, GetVoicePitch() ); - } - - SpeechMsg( GetOuter(), "SpeakRawSentence( %s, %f) %f\n", pszSentence, delay, engine->SentenceLength( sentenceIndex ) ); - NoteSpeaking( engine->SentenceLength( sentenceIndex ), delay ); - - return sentenceIndex; -} - -//------------------------------------- - -void CAI_Expresser::BlockSpeechUntil( float time ) -{ - SpeechMsg( GetOuter(), "BlockSpeechUntil(%f) %f\n", time, time - gpGlobals->curtime ); - m_flBlockedTalkTime = time; -} - - -//------------------------------------- - -void CAI_Expresser::NoteSpeaking( float duration, float delay ) -{ - duration += delay; - - GetSink()->OnStartSpeaking(); - - if ( duration <= 0 ) - { - // no duration :( - m_flStopTalkTime = gpGlobals->curtime + 3; - duration = 0; - } - else - { - m_flStopTalkTime = gpGlobals->curtime + duration; - } - - m_flStopTalkTimeWithoutDelay = m_flStopTalkTime - delay; - - SpeechMsg( GetOuter(), "NoteSpeaking( %f, %f ) (stop at %f)\n", duration, delay, m_flStopTalkTime ); - - if ( GetSink()->UseSemaphore() ) - { - CAI_TimedSemaphore *pSemaphore = GetMySpeechSemaphore( GetOuter() ); - if ( pSemaphore ) - { - pSemaphore->Acquire( duration, GetOuter() ); - } - } -} - -//------------------------------------- - -void CAI_Expresser::ForceNotSpeaking( void ) -{ - if ( IsSpeaking() ) - { - m_flStopTalkTime = gpGlobals->curtime; - m_flStopTalkTimeWithoutDelay = gpGlobals->curtime; - - CAI_TimedSemaphore *pSemaphore = GetMySpeechSemaphore( GetOuter() ); - if ( pSemaphore ) - { - if ( pSemaphore->GetOwner() == GetOuter() ) - { - pSemaphore->Release(); - } - } - } -} - -//------------------------------------- - -bool CAI_Expresser::IsSpeaking( void ) -{ - if ( m_flStopTalkTime > gpGlobals->curtime ) - SpeechMsg( GetOuter(), "IsSpeaking() %f\n", m_flStopTalkTime - gpGlobals->curtime ); - - if ( m_flLastTimeAcceptedSpeak == gpGlobals->curtime ) // only one speak accepted per think - return true; - - return ( m_flStopTalkTime > gpGlobals->curtime ); -} - -//------------------------------------- - -bool CAI_Expresser::CanSpeak() -{ - if ( m_flLastTimeAcceptedSpeak == gpGlobals->curtime ) // only one speak accepted per think - return false; - - float timeOk = MAX( m_flStopTalkTime, m_flBlockedTalkTime ); - return ( timeOk <= gpGlobals->curtime ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true if it's ok for this entity to speak after himself. -// The base CanSpeak() includes the default speech delay, and won't -// return true until that delay time has passed after finishing the -// speech. This returns true as soon as the speech finishes. -//----------------------------------------------------------------------------- -bool CAI_Expresser::CanSpeakAfterMyself() -{ - if ( m_flLastTimeAcceptedSpeak == gpGlobals->curtime ) // only one speak accepted per think - return false; - - float timeOk = MAX( m_flStopTalkTimeWithoutDelay, m_flBlockedTalkTime ); - return ( timeOk <= gpGlobals->curtime ); -} - -//------------------------------------- -bool CAI_Expresser::CanSpeakConcept( AIConcept_t concept ) -{ - // Not in history? - int iter = m_ConceptHistories.Find( concept ); - if ( iter == m_ConceptHistories.InvalidIndex() ) - { - return true; - } - - ConceptHistory_t *history = &m_ConceptHistories[iter]; - Assert( history ); - - AI_Response *response = history->response; - if ( !response ) - return true; - - if ( response->GetSpeakOnce() ) - return false; - - float respeakDelay = response->GetRespeakDelay(); - - if ( respeakDelay != 0.0f ) - { - if ( history->timeSpoken != -1 && ( gpGlobals->curtime < history->timeSpoken + respeakDelay ) ) - return false; - } - - return true; -} - -//------------------------------------- - -bool CAI_Expresser::SpokeConcept( AIConcept_t concept ) -{ - return GetTimeSpokeConcept( concept ) != -1.f; -} - -//------------------------------------- - -float CAI_Expresser::GetTimeSpokeConcept( AIConcept_t concept ) -{ - int iter = m_ConceptHistories.Find( concept ); - if ( iter == m_ConceptHistories.InvalidIndex() ) - return -1; - - ConceptHistory_t *h = &m_ConceptHistories[iter]; - return h->timeSpoken; -} - -//------------------------------------- - -void CAI_Expresser::SetSpokeConcept( AIConcept_t concept, AI_Response *response, bool bCallback ) -{ - int idx = m_ConceptHistories.Find( concept ); - if ( idx == m_ConceptHistories.InvalidIndex() ) - { - ConceptHistory_t h; - h.timeSpoken = gpGlobals->curtime; - idx = m_ConceptHistories.Insert( concept, h ); - } - - ConceptHistory_t *slot = &m_ConceptHistories[ idx ]; - - slot->timeSpoken = gpGlobals->curtime; - // Update response info - if ( response ) - { - AI_Response *r = slot->response; - if ( r ) - { - delete r; - } - - // FIXME: Are we leaking AI_Responses? - slot->response = response; - } - - if ( bCallback ) - GetSink()->OnSpokeConcept( concept, response ); -} - -//------------------------------------- - -void CAI_Expresser::ClearSpokeConcept( AIConcept_t concept ) -{ - m_ConceptHistories.Remove( concept ); -} - -//------------------------------------- - -void CAI_Expresser::DumpHistories() -{ - int c = 1; - for ( int i = m_ConceptHistories.First(); i != m_ConceptHistories.InvalidIndex(); i = m_ConceptHistories.Next(i ) ) - { - ConceptHistory_t *h = &m_ConceptHistories[ i ]; - - DevMsg( "%i: %s at %f\n", c++, m_ConceptHistories.GetElementName( i ), h->timeSpoken ); - } -} - -//------------------------------------- - -bool CAI_Expresser::IsValidResponse( ResponseType_t type, const char *pszValue ) -{ - if ( type == RESPONSE_SCENE ) - { - char szInstanceFilename[256]; - GetOuter()->GenderExpandString( pszValue, szInstanceFilename, sizeof( szInstanceFilename ) ); - return ( GetSceneDuration( szInstanceFilename ) > 0 ); - } - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CAI_TimedSemaphore *CAI_Expresser::GetMySpeechSemaphore( CBaseEntity *pNpc ) -{ - if ( !pNpc->MyNPCPointer() ) - return false; - - return (pNpc->MyNPCPointer()->IsPlayerAlly() ? &g_AIFriendliesTalkSemaphore : &g_AIFoesTalkSemaphore ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_Expresser::SpeechMsg( CBaseEntity *pFlex, const char *pszFormat, ... ) -{ - if ( !DebuggingSpeech() ) - return; - - if ( pFlex->MyNPCPointer() ) - { - DevMsg( pFlex->MyNPCPointer(), CFmtStr( &pszFormat ) ); - } - else - { - DevMsg( CFmtStr( &pszFormat ) ); - } - UTIL_LogPrintf( (char *) ( (const char *) CFmtStr( &pszFormat ) ) ); -} - - -//----------------------------------------------------------------------------- - -void CAI_ExpresserHost_NPC_DoModifyOrAppendCriteria( CAI_BaseNPC *pSpeaker, AI_CriteriaSet& set ) -{ - // Append current activity name - const char *pActivityName = pSpeaker->GetActivityName( pSpeaker->GetActivity() ); - if ( pActivityName ) - { - set.AppendCriteria( "activity", pActivityName ); - } - - static const char *pStateNames[] = { "None", "Idle", "Alert", "Combat", "Scripted", "PlayDead", "Dead" }; - if ( (int)pSpeaker->m_NPCState < (int)ARRAYSIZE(pStateNames) ) - { - set.AppendCriteria( "npcstate", UTIL_VarArgs( "[NPCState::%s]", pStateNames[pSpeaker->m_NPCState] ) ); - } - - if ( pSpeaker->GetEnemy() ) - { - set.AppendCriteria( "enemy", pSpeaker->GetEnemy()->GetClassname() ); - set.AppendCriteria( "timesincecombat", "-1" ); - } - else - { - if ( pSpeaker->GetLastEnemyTime() == 0.0 ) - set.AppendCriteria( "timesincecombat", "999999.0" ); - else - set.AppendCriteria( "timesincecombat", UTIL_VarArgs( "%f", gpGlobals->curtime - pSpeaker->GetLastEnemyTime() ) ); - } - - set.AppendCriteria( "speed", UTIL_VarArgs( "%.3f", pSpeaker->GetSmoothedVelocity().Length() ) ); - - CBaseCombatWeapon *weapon = pSpeaker->GetActiveWeapon(); - if ( weapon ) - { - set.AppendCriteria( "weapon", weapon->GetClassname() ); - } - else - { - set.AppendCriteria( "weapon", "none" ); - } - - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer ) - { - Vector distance = pPlayer->GetAbsOrigin() - pSpeaker->GetAbsOrigin(); - - set.AppendCriteria( "distancetoplayer", UTIL_VarArgs( "%f", distance.Length() ) ); - - } - else - { - set.AppendCriteria( "distancetoplayer", UTIL_VarArgs( "%i", MAX_COORD_RANGE ) ); - } - - if ( pSpeaker->HasCondition( COND_SEE_PLAYER ) ) - { - set.AppendCriteria( "seeplayer", "1" ); - } - else - { - set.AppendCriteria( "seeplayer", "0" ); - } - - if ( pPlayer && pPlayer->FInViewCone( pSpeaker ) && pPlayer->FVisible( pSpeaker ) ) - { - set.AppendCriteria( "seenbyplayer", "1" ); - } - else - { - set.AppendCriteria( "seenbyplayer", "0" ); - } -} - -//----------------------------------------------------------------------------- - -extern CBaseEntity *FindPickerEntity( CBasePlayer *pPlayer ); -CON_COMMAND( npc_speakall, "Force the npc to try and speak all their responses" ) -{ - CBaseEntity *pEntity; - - if ( args[1] && *args[1] ) - { - pEntity = gEntList.FindEntityByName( NULL, args[1], NULL ); - if ( !pEntity ) - { - pEntity = gEntList.FindEntityByClassname( NULL, args[1] ); - } - } - else - { - pEntity = FindPickerEntity( UTIL_GetCommandClient() ); - } - - if ( pEntity ) - { - CAI_BaseNPC *pNPC = pEntity->MyNPCPointer(); - if (pNPC) - { - if ( pNPC->GetExpresser() ) - { - bool save = engine->LockNetworkStringTables( false ); - pNPC->GetExpresser()->TestAllResponses(); - engine->LockNetworkStringTables( save ); - } - } - } -} - -//----------------------------------------------------------------------------- - -CMultiplayer_Expresser::CMultiplayer_Expresser( CBaseFlex *pOuter ) : CAI_Expresser( pOuter ) -{ - m_bAllowMultipleScenes = false; -} - -bool CMultiplayer_Expresser::IsSpeaking( void ) -{ - if ( m_bAllowMultipleScenes ) - { - return false; - } - - return CAI_Expresser::IsSpeaking(); -} - - -void CMultiplayer_Expresser::AllowMultipleScenes() -{ - m_bAllowMultipleScenes = true; -} - -void CMultiplayer_Expresser::DisallowMultipleScenes() -{ - m_bAllowMultipleScenes = false; -} diff --git a/game/server/ai_speech.h b/game/server/ai_speech.h deleted file mode 100644 index 9862eb53c..000000000 --- a/game/server/ai_speech.h +++ /dev/null @@ -1,401 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_SPEECH_H -#define AI_SPEECH_H - -#include "utlmap.h" - -#include "soundflags.h" -#include "AI_ResponseSystem.h" -#include "utldict.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -class KeyValues; -class AI_CriteriaSet; - -//----------------------------------------------------------------------------- -// Purpose: Used to share a global resource or prevent a system stepping on -// own toes. -//----------------------------------------------------------------------------- - -class CAI_TimedSemaphore -{ -public: - CAI_TimedSemaphore() - : m_ReleaseTime( 0 ) - { - m_hCurrentTalker = NULL; - } - - void Acquire( float time, CBaseEntity *pTalker ) { m_ReleaseTime = gpGlobals->curtime + time; m_hCurrentTalker = pTalker; } - void Release() { m_ReleaseTime = 0; m_hCurrentTalker = NULL; } - - // Current owner of the semaphore is always allowed to talk - bool IsAvailable( CBaseEntity *pTalker ) const { return ((gpGlobals->curtime > m_ReleaseTime) || (m_hCurrentTalker == pTalker)); } - float GetReleaseTime() const { return m_ReleaseTime; } - - CBaseEntity *GetOwner() { return m_hCurrentTalker; } - -private: - float m_ReleaseTime; - EHANDLE m_hCurrentTalker; -}; - -//----------------------------------------------------------------------------- - -extern CAI_TimedSemaphore g_AIFriendliesTalkSemaphore; -extern CAI_TimedSemaphore g_AIFoesTalkSemaphore; - -#define GetSpeechSemaphore( pNpc ) (((pNpc)->IsPlayerAlly()) ? &g_AIFriendliesTalkSemaphore : &g_AIFoesTalkSemaphore ) -//----------------------------------------------------------------------------- -// Basic speech system types -//----------------------------------------------------------------------------- - -//------------------------------------- -// Constants - - -const float AIS_DEF_MIN_DELAY = 2.8; // Minimum amount of time an NPCs will wait after someone has spoken before considering speaking again -const float AIS_DEF_MAX_DELAY = 3.2; // Maximum amount of time an NPCs will wait after someone has spoken before considering speaking again -const float AIS_NO_DELAY = 0; -const soundlevel_t AIS_DEF_SNDLVL = SNDLVL_TALKING; -#define AI_NULL_CONCEPT NULL - -#define AI_NULL_SENTENCE NULL - -// Sentence prefix constants -#define AI_SP_SPECIFIC_SENTENCE '!' -#define AI_SP_WAVFILE '^' -#define AI_SP_SCENE_GROUP '=' -#define AI_SP_SPECIFIC_SCENE '?' - -#define AI_SPECIFIC_SENTENCE(str_constant) "!" str_constant -#define AI_WAVFILE(str_constant) "^" str_constant -// @Note (toml 09-12-02): as scene groups are not currently implemented, the string is a semi-colon delimited list -#define AI_SCENE_GROUP(str_constant) "=" str_constant -#define AI_SPECIFIC_SCENE(str_constant) "?" str_constant - -// Designer overriding modifiers -#define AI_SPECIFIC_SCENE_MODIFIER "scene:" - -//------------------------------------- - -//------------------------------------- -// An id that represents the core meaning of a spoken phrase, -// eventually to be mapped to a sentence group or scene - -typedef const char *AIConcept_t; - -inline bool CompareConcepts( AIConcept_t c1, AIConcept_t c2 ) -{ - return ( (void *)c1 == (void *)c2 || ( c1 && c2 && Q_stricmp( c1, c2 ) == 0 ) ); -} - -//------------------------------------- -// Specifies and stores the base timing and attentuation values for concepts -// -class AI_Response; - -//----------------------------------------------------------------------------- -// CAI_Expresser -// -// Purpose: Provides the functionality of going from abstract concept ("hello") -// to specific sentence/scene/wave -// - -//------------------------------------- -// Sink supports behavior control and receives notifications of internal events - -class CAI_ExpresserSink -{ -public: - virtual void OnSpokeConcept( AIConcept_t concept, AI_Response *response ) {}; - virtual void OnStartSpeaking() {} - virtual bool UseSemaphore() { return true; } -}; - -struct ConceptHistory_t -{ - DECLARE_SIMPLE_DATADESC(); - - ConceptHistory_t(float timeSpoken = -1 ) - : timeSpoken( timeSpoken ), response( NULL ) - { - } - - ConceptHistory_t( const ConceptHistory_t& src ); - ConceptHistory_t& operator = ( const ConceptHistory_t& src ); - - ~ConceptHistory_t(); - - float timeSpoken; - AI_Response *response; -}; -//------------------------------------- - -class CAI_Expresser : public IResponseFilter -{ -public: - CAI_Expresser( CBaseFlex *pOuter = NULL ); - ~CAI_Expresser(); - - // -------------------------------- - - bool Connect( CAI_ExpresserSink *pSink ) { m_pSink = pSink; return true; } - bool Disconnect( CAI_ExpresserSink *pSink ) { m_pSink = NULL; return true;} - - void TestAllResponses(); - - // -------------------------------- - - bool Speak( AIConcept_t concept, const char *modifiers = NULL, char *pszOutResponseChosen = NULL, size_t bufsize = 0, IRecipientFilter *filter = NULL ); - - // These two methods allow looking up a response and dispatching it to be two different steps - AI_Response *SpeakFindResponse( AIConcept_t concept, const char *modifiers = NULL ); - bool SpeakDispatchResponse( AIConcept_t concept, AI_Response *response, IRecipientFilter *filter = NULL ); - float GetResponseDuration( AI_Response *response ); - - virtual int SpeakRawSentence( const char *pszSentence, float delay, float volume = VOL_NORM, soundlevel_t soundlevel = SNDLVL_TALKING, CBaseEntity *pListener = NULL ); - - bool SemaphoreIsAvailable( CBaseEntity *pTalker ); - float GetSemaphoreAvailableTime( CBaseEntity *pTalker ); - - // -------------------------------- - - virtual bool IsSpeaking(); - bool CanSpeak(); - bool CanSpeakAfterMyself(); - float GetTimeSpeechComplete() const { return m_flStopTalkTime; } - void BlockSpeechUntil( float time ); - - // -------------------------------- - - bool CanSpeakConcept( AIConcept_t concept ); - bool SpokeConcept( AIConcept_t concept ); - float GetTimeSpokeConcept( AIConcept_t concept ); // returns -1 if never - void SetSpokeConcept( AIConcept_t concept, AI_Response *response, bool bCallback = true ); - void ClearSpokeConcept( AIConcept_t concept ); - - // -------------------------------- - - void SetVoicePitch( int voicePitch ) { m_voicePitch = voicePitch; } - int GetVoicePitch() const; - - void NoteSpeaking( float duration, float delay = 0 ); - - // Force the NPC to release the semaphore & clear next speech time - void ForceNotSpeaking( void ); - -protected: - CAI_TimedSemaphore *GetMySpeechSemaphore( CBaseEntity *pNpc ); - - bool SpeakRawScene( const char *pszScene, float delay, AI_Response *response, IRecipientFilter *filter = NULL ); - // This will create a fake .vcd/CChoreoScene to wrap the sound to be played - bool SpeakAutoGeneratedScene( char const *soundname, float delay ); - - void DumpHistories(); - - void SpeechMsg( CBaseEntity *pFlex, const char *pszFormat, ... ); - - // -------------------------------- - - CAI_ExpresserSink *GetSink() { return m_pSink; } - -private: - // -------------------------------- - - virtual bool IsValidResponse( ResponseType_t type, const char *pszValue ); - - // -------------------------------- - - CAI_ExpresserSink *m_pSink; - - // -------------------------------- - // - // Speech concept data structures - // - - CUtlDict< ConceptHistory_t, int > m_ConceptHistories; - - // -------------------------------- - // - // Speaking states - // - - float m_flStopTalkTime; // when in the future that I'll be done saying this sentence. - float m_flStopTalkTimeWithoutDelay; // same as the above, but minus the delay before other people can speak - float m_flBlockedTalkTime; - int m_voicePitch; // pitch of voice for this head - float m_flLastTimeAcceptedSpeak; // because speech may not be blocked until NoteSpeaking called by scene ent, this handles in-think blocking - - DECLARE_SIMPLE_DATADESC(); - - // -------------------------------- - // -public: - virtual void SetOuter( CBaseFlex *pOuter ) { m_pOuter = pOuter; } - - CBaseFlex * GetOuter() { return m_pOuter; } - const CBaseFlex * GetOuter() const { return m_pOuter; } - -private: - CHandle m_pOuter; -}; - -class CMultiplayer_Expresser : public CAI_Expresser -{ -public: - CMultiplayer_Expresser( CBaseFlex *pOuter = NULL ); - //~CMultiplayer_Expresser(); - - virtual bool IsSpeaking(); - - void AllowMultipleScenes(); - void DisallowMultipleScenes(); - -private: - bool m_bAllowMultipleScenes; - -}; - -//----------------------------------------------------------------------------- -// -// An NPC base class to assist a branch of the inheritance graph -// in utilizing CAI_Expresser -// - -template -class CAI_ExpresserHost : public BASE_NPC, protected CAI_ExpresserSink -{ - DECLARE_CLASS_NOFRIEND( CAI_ExpresserHost, BASE_NPC ); - -public: - virtual void NoteSpeaking( float duration, float delay ); - - virtual bool Speak( AIConcept_t concept, const char *modifiers = NULL, char *pszOutResponseChosen = NULL, size_t bufsize = 0, IRecipientFilter *filter = NULL ); - - // These two methods allow looking up a response and dispatching it to be two different steps - AI_Response * SpeakFindResponse( AIConcept_t concept, const char *modifiers = NULL ); - bool SpeakDispatchResponse( AIConcept_t concept, AI_Response *response ); - virtual void PostSpeakDispatchResponse( AIConcept_t concept, AI_Response *response ) { return; } - float GetResponseDuration( AI_Response *response ); - - float GetTimeSpeechComplete() const { return this->GetExpresser()->GetTimeSpeechComplete(); } - - bool IsSpeaking() { return this->GetExpresser()->IsSpeaking(); } - bool CanSpeak() { return this->GetExpresser()->CanSpeak(); } - bool CanSpeakAfterMyself() { return this->GetExpresser()->CanSpeakAfterMyself(); } - - void SetSpokeConcept( AIConcept_t concept, AI_Response *response, bool bCallback = true ) { this->GetExpresser()->SetSpokeConcept( concept, response, bCallback ); } - float GetTimeSpokeConcept( AIConcept_t concept ) { return this->GetExpresser()->GetTimeSpokeConcept( concept ); } - bool SpokeConcept( AIConcept_t concept ) { return this->GetExpresser()->SpokeConcept( concept ); } - -protected: - int PlaySentence( const char *pszSentence, float delay, float volume = VOL_NORM, soundlevel_t soundlevel = SNDLVL_TALKING, CBaseEntity *pListener = NULL ); - virtual void ModifyOrAppendCriteria( AI_CriteriaSet& set ); - - virtual IResponseSystem *GetResponseSystem(); - // Override of base entity response input handler - virtual void DispatchResponse( const char *conceptName ); -}; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline void CAI_ExpresserHost::NoteSpeaking( float duration, float delay ) -{ - this->GetExpresser()->NoteSpeaking( duration, delay ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline bool CAI_ExpresserHost::Speak( AIConcept_t concept, const char *modifiers /*= NULL*/, char *pszOutResponseChosen /*=NULL*/, size_t bufsize /* = 0 */, IRecipientFilter *filter /* = NULL */ ) -{ - AssertOnce( this->GetExpresser()->GetOuter() == this ); - return this->GetExpresser()->Speak( concept, modifiers, pszOutResponseChosen, bufsize, filter ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline int CAI_ExpresserHost::PlaySentence( const char *pszSentence, float delay, float volume, soundlevel_t soundlevel, CBaseEntity *pListener ) -{ - return this->GetExpresser()->SpeakRawSentence( pszSentence, delay, volume, soundlevel, pListener ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -extern void CAI_ExpresserHost_NPC_DoModifyOrAppendCriteria( CAI_BaseNPC *pSpeaker, AI_CriteriaSet& criteriaSet ); - -template -inline void CAI_ExpresserHost::ModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet ) -{ - BaseClass::ModifyOrAppendCriteria( criteriaSet ); - - if ( this->MyNPCPointer() ) - { - CAI_ExpresserHost_NPC_DoModifyOrAppendCriteria( this->MyNPCPointer(), criteriaSet ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline IResponseSystem *CAI_ExpresserHost::GetResponseSystem() -{ - extern IResponseSystem *g_pResponseSystem; - // Expressive NPC's use the general response system - return g_pResponseSystem; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline AI_Response *CAI_ExpresserHost::SpeakFindResponse( AIConcept_t concept, const char *modifiers /*= NULL*/ ) -{ - return this->GetExpresser()->SpeakFindResponse( concept, modifiers ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline bool CAI_ExpresserHost::SpeakDispatchResponse( AIConcept_t concept, AI_Response *response ) -{ - if ( this->GetExpresser()->SpeakDispatchResponse( concept, response ) ) - { - PostSpeakDispatchResponse( concept, response ); - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline float CAI_ExpresserHost::GetResponseDuration( AI_Response *response ) -{ - return this->GetExpresser()->GetResponseDuration( response ); -} - -//----------------------------------------------------------------------------- -// Override of base entity response input handler -//----------------------------------------------------------------------------- -template -inline void CAI_ExpresserHost::DispatchResponse( const char *conceptName ) - { - Speak( (AIConcept_t)conceptName ); - } - -//----------------------------------------------------------------------------- - -#endif // AI_SPEECH_H diff --git a/game/server/ai_speechfilter.cpp b/game/server/ai_speechfilter.cpp deleted file mode 100644 index b6fc9b20e..000000000 --- a/game/server/ai_speechfilter.cpp +++ /dev/null @@ -1,200 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: An entity that can be used to control speech behaviour for a group -// of NPCs. -// -//=============================================================================// - -#include "cbase.h" -#include "ai_speechfilter.h" -#ifndef CSTRIKE -#include "ai_playerally.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -LINK_ENTITY_TO_CLASS( ai_speechfilter, CAI_SpeechFilter ); - -BEGIN_DATADESC( CAI_SpeechFilter ) - DEFINE_KEYFIELD( m_iszSubject, FIELD_STRING, "subject" ), - DEFINE_KEYFIELD( m_flIdleModifier, FIELD_FLOAT, "IdleModifier" ), - DEFINE_KEYFIELD( m_bNeverSayHello, FIELD_BOOLEAN, "NeverSayHello" ), - DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetIdleModifier", InputSetIdleModifier ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_SpeechFilter::Spawn( void ) -{ - BaseClass::Spawn(); - - gEntList.AddListenerEntity( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: Connect to all our NPCs -//----------------------------------------------------------------------------- -void CAI_SpeechFilter::Activate( void ) -{ - BaseClass::Activate(); - - PopulateSubjectList( m_bDisabled ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_SpeechFilter::UpdateOnRemove(void) -{ - gEntList.RemoveListenerEntity( this ); - BaseClass::UpdateOnRemove(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_SpeechFilter::Enable( bool bEnable ) -{ - m_bDisabled = !bEnable; - - PopulateSubjectList( m_bDisabled ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_SpeechFilter::InputEnable( inputdata_t &inputdata ) -{ - Enable( true ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_SpeechFilter::InputDisable( inputdata_t &inputdata ) -{ - Enable( false ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_SpeechFilter::InputSetIdleModifier( inputdata_t &inputdata ) -{ - m_flIdleModifier = inputdata.value.Float(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_SpeechFilter::PopulateSubjectList( bool purge ) -{ - // Populate the subject list. Try targetname first. - CBaseEntity *pSearch = NULL; - int iNumSubjects = 0; - do - { - pSearch = gEntList.FindEntityByName( pSearch, m_iszSubject ); - if ( pSearch ) - { -#ifndef CSTRIKE_DLL - CAI_PlayerAlly *pAlly = dynamic_cast(pSearch); - if ( pAlly ) - { - if( purge ) - { - pAlly->SetSpeechFilter( NULL ); - } - else - { - if( pAlly->GetSpeechFilter() != NULL ) - { - DevWarning("ai_speechfilter %s is slamming NPC %s's current speech filter.\n", STRING(GetEntityName()), STRING(pSearch->GetEntityName()) ); - } - - pAlly->SetSpeechFilter( this ); - } - } - else if ( pSearch->IsNPC() ) - { - DevWarning("ai_speechfilter %s tries to use %s as a subject, but it's not a talking NPC.\n", STRING(GetEntityName()), STRING(pSearch->GetEntityName()) ); - } -#endif - iNumSubjects++; - } - } while( pSearch ); - - if ( !iNumSubjects ) - { - // No subjects found by targetname! Assume classname. - do - { - pSearch = gEntList.FindEntityByClassname( pSearch, STRING(m_iszSubject) ); - if( pSearch ) - { -#ifndef CSTRIKE_DLL - CAI_PlayerAlly *pAlly = dynamic_cast(pSearch); - if ( pAlly ) - { - if( purge ) - { - pAlly->SetSpeechFilter( NULL ); - } - else - { - if( pAlly->GetSpeechFilter() != NULL ) - { - DevWarning("ai_speechfilter %s is slamming NPC %s's current speech filter.\n", STRING(GetEntityName()), STRING(pSearch->GetEntityName()) ); - } - - pAlly->SetSpeechFilter( this ); - } - } - else if ( pSearch->IsNPC() ) - { - DevWarning("ai_speechfilter %s tries to use %s as a subject, but it's not a talking NPC.\n", STRING(GetEntityName()), STRING(pSearch->GetEntityName()) ); - } -#endif - iNumSubjects++; - } - } while( pSearch ); - } - - // If the subject list is still empty, we have an error! - if ( !iNumSubjects ) - { - DevMsg( 2, "ai_speechfilter finds no subject(s) called: %s\n", STRING( m_iszSubject ) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEntity - -//----------------------------------------------------------------------------- -void CAI_SpeechFilter::OnEntityCreated( CBaseEntity *pEntity ) -{ - if ( !m_bDisabled && pEntity->NameMatches( m_iszSubject ) || pEntity->ClassMatches( m_iszSubject ) ) - { -#ifndef CSTRIKE_DLL - CAI_PlayerAlly *pAlly = dynamic_cast(pEntity); - if ( pAlly ) - { - pAlly->SetSpeechFilter( this ); - } - else if ( pEntity->IsNPC() ) - { - DevWarning("ai_speechfilter %s tries to use %s as a subject, but it's not a talking NPC.\n", STRING(GetEntityName()), STRING(pEntity->GetEntityName()) ); - } -#endif - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEntity - -//----------------------------------------------------------------------------- -void CAI_SpeechFilter::OnEntityDeleted( CBaseEntity *pEntity ) -{ -} diff --git a/game/server/ai_speechfilter.h b/game/server/ai_speechfilter.h deleted file mode 100644 index 278748182..000000000 --- a/game/server/ai_speechfilter.h +++ /dev/null @@ -1,48 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef AI_SPEECHFILTER_H -#define AI_SPEECHFILTER_H -#ifdef _WIN32 -#pragma once -#endif - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CAI_SpeechFilter : public CBaseEntity, public IEntityListener -{ - DECLARE_CLASS( CAI_SpeechFilter, CBaseEntity ); -public: - DECLARE_DATADESC(); - - void Spawn( void ); - void Activate( void ); - void UpdateOnRemove( void ); - - void Enable( bool bEnable ); - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - void InputSetIdleModifier( inputdata_t &inputdata ); - - void PopulateSubjectList( bool purge = false ); - - - // Accessors for our NPC - float GetIdleModifier( void ) { return m_flIdleModifier; } - bool NeverSayHello( void ) { return m_bNeverSayHello; } - - void OnEntityCreated( CBaseEntity *pEntity ); - void OnEntityDeleted( CBaseEntity *pEntity ); - -protected: - string_t m_iszSubject; - float m_flIdleModifier; // Multiplier to the percentage chance that our NPC will idle speak - bool m_bNeverSayHello; // If set, the NPC never says hello to the player - bool m_bDisabled; -}; - -#endif // AI_SPEECHFILTER_H diff --git a/game/server/ai_squad.cpp b/game/server/ai_squad.cpp deleted file mode 100644 index 31fb651a8..000000000 --- a/game/server/ai_squad.cpp +++ /dev/null @@ -1,787 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Squad classes -// -//=============================================================================// - -#include "cbase.h" -#include "ai_squad.h" -#include "ai_squadslot.h" -#include "ai_basenpc.h" -#include "saverestore_bitstring.h" -#include "saverestore_utlvector.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- - -CAI_SquadManager g_AI_SquadManager; - -//----------------------------------------------------------------------------- -// CAI_SquadManager -// -// Purpose: Manages all the squads in the system -// -//----------------------------------------------------------------------------- - -CAI_Squad *CAI_SquadManager::FindSquad( string_t squadName ) -{ - CAI_Squad* pSquad = m_pSquads; - - while (pSquad) - { - if (FStrEq(STRING(squadName),pSquad->GetName())) - { - return pSquad; - } - pSquad = pSquad->m_pNextSquad; - } - return NULL; -} - -//------------------------------------- - -CAI_Squad *CAI_SquadManager::CreateSquad(string_t squadName) -{ - CAI_Squad *pResult = new CAI_Squad(squadName); - - // --------------------------------- - // Only named squads get added to the squad list - if ( squadName != NULL_STRING ) - { - pResult->m_pNextSquad = m_pSquads; - m_pSquads = pResult; - } - else - pResult->m_pNextSquad = NULL; - return pResult; -} - -//------------------------------------- - -int CAI_SquadManager::NumSquads() -{ - int nSquads = 0; - CAI_Squad* pSquad = m_pSquads; - - while (pSquad) - { - nSquads++; - pSquad = pSquad->GetNext(); - } - return nSquads; -} - -//------------------------------------- - -void CAI_SquadManager::DeleteSquad( CAI_Squad *pSquad ) -{ - CAI_Squad *pCurSquad = m_pSquads; - if (pCurSquad == pSquad) - { - g_AI_SquadManager.m_pSquads = pCurSquad->m_pNextSquad; - } - else - { - while (pCurSquad) - { - if (pCurSquad->m_pNextSquad == pSquad) - { - pCurSquad->m_pNextSquad = pCurSquad->m_pNextSquad->m_pNextSquad; - break; - } - pCurSquad= pCurSquad->m_pNextSquad; - } - } - delete pSquad; -} - -//------------------------------------- -// Purpose: Delete all the squads (called between levels / loads) -//------------------------------------- - -void CAI_SquadManager::DeleteAllSquads(void) -{ - CAI_Squad *squad = CAI_SquadManager::m_pSquads; - - while (squad) - { - CAI_Squad *temp = squad->m_pNextSquad; - delete squad; - squad = temp; - } - CAI_SquadManager::m_pSquads = NULL; -} - -//----------------------------------------------------------------------------- -// CAI_Squad -// -// Purpose: Tracks enemies, squad slots, squad members -// -//----------------------------------------------------------------------------- - -#ifdef PER_ENEMY_SQUADSLOTS -BEGIN_SIMPLE_DATADESC( AISquadEnemyInfo_t ) - - DEFINE_FIELD( hEnemy, FIELD_EHANDLE ), - DEFINE_BITSTRING( slots), - -END_DATADESC() -#endif - -BEGIN_SIMPLE_DATADESC( CAI_Squad ) - - // m_pNextSquad (rebuilt) - // m_Name (rebuilt) - // m_SquadMembers (rebuilt) - // m_SquadMembers.Count() (rebuilt) - DEFINE_FIELD( m_flSquadSoundWaitTime, FIELD_TIME ), - DEFINE_FIELD( m_nSquadSoundPriority, FIELD_INTEGER ), - DEFINE_FIELD( m_hSquadInflictor, FIELD_EHANDLE ), - DEFINE_AUTO_ARRAY( m_SquadData, FIELD_INTEGER ), - // m_pLastFoundEnemyInfo (think transient) - -#ifdef PER_ENEMY_SQUADSLOTS - DEFINE_UTLVECTOR(m_EnemyInfos, FIELD_EMBEDDED ), - DEFINE_FIELD( m_flEnemyInfoCleanupTime, FIELD_TIME ), -#else - DEFINE_EMBEDDED( m_squadSlotsUsed ), -#endif - -END_DATADESC() - -//------------------------------------- - -CAI_Squad::CAI_Squad(string_t newName) -#ifndef PER_ENEMY_SQUADSLOTS - : m_squadSlotsUsed(MAX_SQUADSLOTS) -#endif -{ - Init( newName ); -} - -//------------------------------------- - -CAI_Squad::CAI_Squad() -#ifndef PER_ENEMY_SQUADSLOTS - : m_squadSlotsUsed(MAX_SQUADSLOTS) -#endif -{ - Init( NULL_STRING ); -} - -//------------------------------------- - -void CAI_Squad::Init(string_t newName) -{ - m_Name = AllocPooledString( STRING(newName) ); - m_pNextSquad = NULL; - m_flSquadSoundWaitTime = 0; - m_SquadMembers.RemoveAll(); - - m_flSquadSoundWaitTime = 0; - - SetSquadInflictor( NULL ); - -#ifdef PER_ENEMY_SQUADSLOTS - m_flEnemyInfoCleanupTime = 0; - m_pLastFoundEnemyInfo = NULL; -#endif - -} - -//------------------------------------- - -CAI_Squad::~CAI_Squad(void) -{ -} - -//------------------------------------- - -bool CAI_Squad::IsSilentMember( const CAI_BaseNPC *pNPC ) -{ - if ( !pNPC || ( pNPC->GetMoveType() == MOVETYPE_NONE && pNPC->GetSolid() == SOLID_NONE ) ) // a.k.a., enemy finder - return true; - return pNPC->IsSilentSquadMember(); -} - -//------------------------------------- -// Purpose: Removes an NPC from a squad -//------------------------------------- - -void CAI_Squad::RemoveFromSquad( CAI_BaseNPC *pNPC, bool bDeath ) -{ - if ( !pNPC ) - return; - - // Find the index of this squad member - int member; - int myIndex = m_SquadMembers.Find(pNPC); - if (myIndex == -1) - { - DevMsg("ERROR: Attempting to remove non-existing squad membmer!\n"); - return; - } - m_SquadMembers.Remove(myIndex); - - // Notify squad members of death - if ( bDeath ) - { - for (member = 0; member < m_SquadMembers.Count(); member++) - { - CAI_BaseNPC* pSquadMem = m_SquadMembers[member]; - if (pSquadMem) - { - pSquadMem->NotifyDeadFriend(pNPC); - } - } - } - - pNPC->SetSquad(NULL); - pNPC->SetSquadName( NULL_STRING ); -} - -//------------------------------------- -// Purpose: Addes the given NPC to the squad -//------------------------------------- -void CAI_Squad::AddToSquad(CAI_BaseNPC *pNPC) -{ - if ( !pNPC || !pNPC->IsAlive() ) - { - Assert(0); - return; - } - - if ( pNPC->GetSquad() == this ) - return; - - if ( pNPC->GetSquad() ) - { - pNPC->GetSquad()->RemoveFromSquad(pNPC); - } - - if (m_SquadMembers.Count() == MAX_SQUAD_MEMBERS) - { - DevMsg("Error!! Squad %s is too big!!! Replacing last member\n", STRING(this->m_Name)); - m_SquadMembers.Remove(m_SquadMembers.Count()-1); - } - m_SquadMembers.AddToTail(pNPC); - pNPC->SetSquad( this ); - pNPC->SetSquadName( m_Name ); - - if ( m_SquadMembers.Count() > 1 ) - { - CAI_BaseNPC *pCopyFrom = m_SquadMembers[0]; - CAI_Enemies *pEnemies = pCopyFrom->GetEnemies(); - AIEnemiesIter_t iter; - AI_EnemyInfo_t *pInfo = pEnemies->GetFirst( &iter ); - while ( pInfo ) - { - pNPC->UpdateEnemyMemory( pInfo->hEnemy, pInfo->vLastKnownLocation, pCopyFrom ); - pInfo = pEnemies->GetNext( &iter ); - } - } - -} - -//------------------------------------- - -CAI_BaseNPC *CAI_Squad::SquadMemberInRange( const Vector &vecLocation, float flDist ) -{ - for (int i = 0; i < m_SquadMembers.Count(); i++) - { - if (m_SquadMembers[i] != NULL && (vecLocation - m_SquadMembers[i]->GetAbsOrigin() ).Length2D() <= flDist) - return m_SquadMembers[i]; - } - return false; -} - -//------------------------------------- -// Purpose: Returns the nearest squad member to the given squad member -//------------------------------------- - -CAI_BaseNPC *CAI_Squad::NearestSquadMember( CAI_BaseNPC *pMember ) -{ - float fBestDist = MAX_COORD_RANGE; - CAI_BaseNPC *fNearestEnt = NULL; - Vector fStartLoc = pMember->GetAbsOrigin(); - for (int i = 0; i < m_SquadMembers.Count(); i++) - { - if (m_SquadMembers[i] != NULL) - { - float fDist = (fStartLoc - m_SquadMembers[i]->GetAbsOrigin()).Length(); - if (m_SquadMembers[i] != pMember && - fDist < fBestDist ) - { - fBestDist = fDist; - fNearestEnt = m_SquadMembers[i]; - } - } - } - return fNearestEnt; -} - -//------------------------------------- -// Purpose: Return the number of squad members visible to the specified member -//------------------------------------- -int CAI_Squad::GetVisibleSquadMembers( CAI_BaseNPC *pMember ) -{ - int iCount = 0; - - for (int i = 0; i < m_SquadMembers.Count(); i++) - { - // Make sure it's not the specified member - if ( m_SquadMembers[i] != NULL && pMember != m_SquadMembers[i] ) - { - if ( pMember->FVisible( m_SquadMembers[i] ) ) - { - iCount++; - } - } - } - - return iCount; -} - -//------------------------------------- -// -//------------------------------------- -CAI_BaseNPC *CAI_Squad::GetSquadMemberNearestTo( const Vector &vecLocation ) -{ - CAI_BaseNPC *pNearest = NULL; - float flNearest = FLT_MAX; - - for ( int i = 0; i < m_SquadMembers.Count(); i++ ) - { - float flDist; - flDist = m_SquadMembers[i]->GetAbsOrigin().DistToSqr( vecLocation ); - - if( flDist < flNearest ) - { - flNearest = flDist; - pNearest = m_SquadMembers[i]; - } - } - - Assert( pNearest != NULL ); - return pNearest; -} - -//------------------------------------- -// Purpose: Returns true if given entity is in the squad -//------------------------------------- -bool CAI_Squad::SquadIsMember( CBaseEntity *pMember ) -{ - CAI_BaseNPC *pNPC = pMember->MyNPCPointer(); - if ( pNPC && pNPC->GetSquad() == this ) - return true; - - return false; -} - -//------------------------------------- - -bool CAI_Squad::IsLeader( CAI_BaseNPC *pNPC ) -{ - if ( IsSilentMember( pNPC ) ) - return false; - - if ( !pNPC ) - return false; - - if ( GetLeader() == pNPC ) - return true; - - return false; -} - -//------------------------------------- - -CAI_BaseNPC *CAI_Squad::GetLeader( void ) -{ - CAI_BaseNPC *pLeader = NULL; - int nSilentMembers = 0; - for ( int i = 0; i < m_SquadMembers.Count(); i++ ) - { - if ( !IsSilentMember( m_SquadMembers[i] ) ) - { - if ( !pLeader ) - pLeader = m_SquadMembers[i]; - } - else - { - nSilentMembers++; - } - } - return ( m_SquadMembers.Count() - nSilentMembers > 1) ? pLeader : NULL; -} - -//----------------------------------------------------------------------------- -CAI_BaseNPC *CAI_Squad::GetFirstMember( AISquadIter_t *pIter, bool bIgnoreSilentMembers ) -{ - int i = 0; - if ( bIgnoreSilentMembers ) - { - for ( ; i < m_SquadMembers.Count(); i++ ) - { - if ( !IsSilentMember( m_SquadMembers[i] ) ) - break; - } - } - - if ( pIter ) - *pIter = (AISquadIter_t)i; - if ( i >= m_SquadMembers.Count() ) - return NULL; - - return m_SquadMembers[i]; -} - -//------------------------------------- - -CAI_BaseNPC *CAI_Squad::GetNextMember( AISquadIter_t *pIter, bool bIgnoreSilentMembers ) -{ - int &i = (int &)*pIter; - i++; - if ( bIgnoreSilentMembers ) - { - for ( ; i < m_SquadMembers.Count(); i++ ) - { - if ( !IsSilentMember( m_SquadMembers[i] ) ) - break; - } - } - - if ( i >= m_SquadMembers.Count() ) - return NULL; - - return m_SquadMembers[i]; -} - -//------------------------------------- -// Purpose: Alert everyone in the squad to the presence of a new enmey -//------------------------------------- - -int CAI_Squad::NumMembers( bool bIgnoreSilentMembers ) -{ - int nSilentMembers = 0; - if ( bIgnoreSilentMembers ) - { - for ( int i = 0; i < m_SquadMembers.Count(); i++ ) - { - if ( IsSilentMember( m_SquadMembers[i] ) ) - nSilentMembers++; - } - } - return ( m_SquadMembers.Count() - nSilentMembers ); -} - -//------------------------------------- -// Purpose: Alert everyone in the squad to the presence of a new enmey -//------------------------------------- - -void CAI_Squad::SquadNewEnemy( CBaseEntity *pEnemy ) -{ - if ( !pEnemy ) - { - DevMsg( "ERROR: SquadNewEnemy() - pEnemy is NULL!\n" ); - return; - } - - for (int i = 0; i < m_SquadMembers.Count(); i++) - { - CAI_BaseNPC *pMember = m_SquadMembers[i]; - if (pMember) - { - // reset members who aren't activly engaged in fighting (only do this if the NPC's using the squad memory, or it'll fail) - if ( !pMember->GetEnemy() || - ( pMember->GetEnemy() != pEnemy && - !pMember->HasCondition( COND_SEE_ENEMY) && - gpGlobals->curtime - pMember->GetEnemyLastTimeSeen() > 3.0 ) ) - { - // give them a new enemy - if( !hl2_episodic.GetBool() || pMember->IsValidEnemy(pEnemy) ) - { - pMember->SetEnemy( pEnemy ); - } - // pMember->SetLastAttackTime( 0 ); - } - } - } -} - -//------------------------------------- -// Purpose: Broadcast a message to all squad members -// Input: messageID - generic message handle -// data - generic data handle -// sender - who sent the message (NULL by default, if not, will not resend to the sender) -//------------------------------------- - -int CAI_Squad::BroadcastInteraction( int interactionType, void *data, CBaseCombatCharacter *sender ) -{ - //Must have a squad - if ( m_SquadMembers.Count() == 0 ) - return false; - - //Broadcast to all members of the squad - for ( int i = 0; i < m_SquadMembers.Count(); i++ ) - { - CAI_BaseNPC *pMember = m_SquadMembers[i]->MyNPCPointer(); - - //Validate and don't send again to the sender - if ( ( pMember != NULL) && ( pMember != sender ) ) - { - //Send it - pMember->DispatchInteraction( interactionType, data, sender ); - } - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: is it ok to make a sound of the given priority? Check for conflicts -// Input : soundPriority - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_Squad::FOkToMakeSound( int soundPriority ) -{ - if (gpGlobals->curtime <= m_flSquadSoundWaitTime) - { - if ( soundPriority <= m_nSquadSoundPriority ) - return false; - } - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: A squad member made an exclusive sound. Keep track so other squad -// members don't talk over it -// Input : soundPriority - for sorting -// time - -//----------------------------------------------------------------------------- -void CAI_Squad::JustMadeSound( int soundPriority, float time ) -{ - m_flSquadSoundWaitTime = time; - m_nSquadSoundPriority = soundPriority; -} - -//----------------------------------------------------------------------------- -// Purpose: Try to get one of a contiguous range of slots -// Input : slotIDStart - start of slot range -// slotIDEnd - end of slot range -// hEnemy - enemy this slot is for -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_Squad::OccupyStrategySlotRange( CBaseEntity *pEnemy, int slotIDStart, int slotIDEnd, int *pSlot ) -{ -#ifndef PER_ENEMY_SQUADSLOTS - // FIXME: combat slots need to be per enemy, not per squad. - // As it is, once a squad is occupied it stops making even simple attacks to other things nearby. - // This code may make soldiers too aggressive - if (GetLeader() && pEnemy != GetLeader()->GetEnemy()) - { - *pSlot = SQUAD_SLOT_NONE; - return true; - } -#endif - - // If I'm already occupying this slot - if ( *pSlot >= slotIDStart && *pSlot <= slotIDEnd) - return true; - - for ( int i = slotIDStart; i <= slotIDEnd; i++ ) - { - // Check enemy to see if slot already occupied - if (!IsSlotOccupied(pEnemy, i)) - { - // Clear any previous spot; - if (*pSlot != SQUAD_SLOT_NONE) - { - // As a debug measure check to see if slot was filled - if (!IsSlotOccupied(pEnemy, *pSlot)) - { - DevMsg( "ERROR! Vacating an empty slot!\n"); - } - - // Free the slot - VacateSlot(pEnemy, *pSlot); - } - - // Fill the slot - OccupySlot(pEnemy, i); - *pSlot = i; - return true; - } - } - return false; -} - -//------------------------------------------------------------------------------ - -bool CAI_Squad::IsStrategySlotRangeOccupied( CBaseEntity *pEnemy, int slotIDStart, int slotIDEnd ) -{ - for ( int i = slotIDStart; i <= slotIDEnd; i++ ) - { - if (!IsSlotOccupied(pEnemy, i)) - return false; - } - return true; -} - -//------------------------------------------------------------------------------ - -void CAI_Squad::VacateStrategySlot( CBaseEntity *pEnemy, int slot) -{ - // If I wasn't taking up a squad slot I'm done - if (slot == SQUAD_SLOT_NONE) - return; - - // As a debug measure check to see if slot was filled - if (!IsSlotOccupied(pEnemy, slot)) - { - DevMsg( "ERROR! Vacating an empty slot!\n"); - } - - // Free the slot - VacateSlot(pEnemy, slot); -} - -//------------------------------------------------------------------------------ - -void CAI_Squad::UpdateEnemyMemory( CAI_BaseNPC *pUpdater, CBaseEntity *pEnemy, const Vector &position ) -{ - //Broadcast to all members of the squad - for ( int i = 0; i < m_SquadMembers.Count(); i++ ) - { - if ( m_SquadMembers[i] != pUpdater ) - { - m_SquadMembers[i]->UpdateEnemyMemory( pEnemy, position, pUpdater ); - } - } -} - -//------------------------------------------------------------------------------ - -#ifdef PER_ENEMY_SQUADSLOTS - -AISquadEnemyInfo_t *CAI_Squad::FindEnemyInfo( CBaseEntity *pEnemy ) -{ - int i; - if ( gpGlobals->curtime > m_flEnemyInfoCleanupTime ) - { - if ( m_EnemyInfos.Count() ) - { - m_pLastFoundEnemyInfo = NULL; - CUtlRBTree activeEnemies; - SetDefLessFunc( activeEnemies ); - - // Gather up the set of active enemies - for ( i = 0; i < m_SquadMembers.Count(); i++ ) - { - CBaseEntity *pMemberEnemy = m_SquadMembers[i]->GetEnemy(); - if ( pMemberEnemy && activeEnemies.Find( pMemberEnemy ) == activeEnemies.InvalidIndex() ) - { - activeEnemies.Insert( pMemberEnemy ); - } - } - - // Remove the records for deleted or unused enemies - for ( i = m_EnemyInfos.Count() - 1; i >= 0; --i ) - { - if ( m_EnemyInfos[i].hEnemy == NULL || activeEnemies.Find( m_EnemyInfos[i].hEnemy ) == activeEnemies.InvalidIndex() ) - { - m_EnemyInfos.FastRemove( i ); - } - } - } - - m_flEnemyInfoCleanupTime = gpGlobals->curtime + 30; - } - - if ( m_pLastFoundEnemyInfo && m_pLastFoundEnemyInfo->hEnemy == pEnemy ) - return m_pLastFoundEnemyInfo; - - for ( i = 0; i < m_EnemyInfos.Count(); i++ ) - { - if ( m_EnemyInfos[i].hEnemy == pEnemy ) - { - m_pLastFoundEnemyInfo = &m_EnemyInfos[i]; - return &m_EnemyInfos[i]; - } - } - - m_pLastFoundEnemyInfo = NULL; - i = m_EnemyInfos.AddToTail(); - m_EnemyInfos[i].hEnemy = pEnemy; - - m_pLastFoundEnemyInfo = &m_EnemyInfos[i]; - return &m_EnemyInfos[i]; -} - -#endif - -//------------------------------------------------------------------------------ - -void CAI_Squad::OccupySlot( CBaseEntity *pEnemy, int i ) -{ -#ifdef PER_ENEMY_SQUADSLOTS - AISquadEnemyInfo_t *pInfo = FindEnemyInfo( pEnemy ); - pInfo->slots.Set(i); -#else - m_squadSlotsUsed.Set(i); -#endif -} - -//------------------------------------------------------------------------------ - -void CAI_Squad::VacateSlot( CBaseEntity *pEnemy, int i ) -{ -#ifdef PER_ENEMY_SQUADSLOTS - AISquadEnemyInfo_t *pInfo = FindEnemyInfo( pEnemy ); - pInfo->slots.Clear(i); -#else - m_squadSlotsUsed.Clear(i); -#endif -} - -//------------------------------------------------------------------------------ - -bool CAI_Squad::IsSlotOccupied( CBaseEntity *pEnemy, int i ) const -{ -#ifdef PER_ENEMY_SQUADSLOTS - const AISquadEnemyInfo_t *pInfo = FindEnemyInfo( pEnemy ); - return pInfo->slots.IsBitSet(i); -#else - return m_squadSlotsUsed.IsBitSet(i); -#endif -} - -void CAI_Squad::SquadRemember( int iMemory ) -{ - for (int i = 0; i < m_SquadMembers.Count(); i++) - { - if (m_SquadMembers[i] != NULL ) - { - m_SquadMembers[i]->Remember( iMemory ); - } - } -} - -//------------------------------------------------------------------------------ -void CAI_Squad::SetSquadInflictor( CBaseEntity *pInflictor ) -{ - m_hSquadInflictor.Set(pInflictor); -} - -//------------------------------------------------------------------------------ -bool CAI_Squad::IsSquadInflictor( CBaseEntity *pInflictor ) -{ - return (m_hSquadInflictor.Get() == pInflictor); -} - -//============================================================================= - diff --git a/game/server/ai_squad.h b/game/server/ai_squad.h deleted file mode 100644 index 36471cf59..000000000 --- a/game/server/ai_squad.h +++ /dev/null @@ -1,276 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Squad classes -// -//=============================================================================// - -#ifndef AI_SQUAD_H -#define AI_SQUAD_H - -#include "ai_memory.h" -#include "ai_squadslot.h" -#include "bitstring.h" - -class CAI_Squad; -typedef CHandle AIHANDLE; - -#define PER_ENEMY_SQUADSLOTS 1 - - -//----------------------------------------------------------------------------- - -DECLARE_POINTER_HANDLE(AISquadsIter_t); -DECLARE_POINTER_HANDLE(AISquadIter_t); - -#define MAX_SQUAD_MEMBERS 16 -#define MAX_SQUAD_DATA_SLOTS 4 - -//----------------------------------------------------------------------------- -// CAI_SquadManager -// -// Purpose: Manages all the squads in the system -// -//----------------------------------------------------------------------------- - -class CAI_SquadManager -{ -public: - CAI_SquadManager() - { - m_pSquads = NULL; - } - - CAI_Squad * GetFirstSquad( AISquadsIter_t *pIter ); - CAI_Squad * GetNextSquad( AISquadsIter_t *pIter ); - int NumSquads(); - - CAI_Squad * FindSquad( string_t squadName ); // Returns squad of the given name - CAI_Squad * CreateSquad( string_t squadName ); // Returns squad of the given name - CAI_Squad * FindCreateSquad( string_t squadName ); // Returns squad of the given name - CAI_Squad * FindCreateSquad( CAI_BaseNPC *pNPC, string_t squadName ); // Returns squad of the given name - - void DeleteSquad( CAI_Squad *pSquad ); - void DeleteAllSquads(void); - -private: - - CAI_Squad * m_pSquads; // A linked list of all squads - -}; - -//------------------------------------- - -extern CAI_SquadManager g_AI_SquadManager; - -//----------------------------------------------------------------------------- - -#ifdef PER_ENEMY_SQUADSLOTS - -struct AISquadEnemyInfo_t -{ - EHANDLE hEnemy; - CBitVec slots; // What squad slots are filled? - - DECLARE_SIMPLE_DATADESC(); -}; - -#endif - -//----------------------------------------------------------------------------- -// CAI_Squad -// -// Purpose: Tracks enemies, squad slots, squad members -// -//----------------------------------------------------------------------------- - -class CAI_Squad -{ -public: - - const char * GetName() const { return STRING(m_Name); } - - void RemoveFromSquad( CAI_BaseNPC *pNPC, bool bDeath = false ); - - CAI_BaseNPC * GetFirstMember( AISquadIter_t *pIter = NULL, bool bIgnoreSilentMembers = true ); - CAI_BaseNPC * GetNextMember( AISquadIter_t *pIter, bool bIgnoreSilentMembers = true ); - CAI_BaseNPC * GetAnyMember(); - int NumMembers( bool bIgnoreSilentMembers = true ); - int GetSquadIndex( CAI_BaseNPC * ); - - void SquadNewEnemy ( CBaseEntity *pEnemy ); - void UpdateEnemyMemory( CAI_BaseNPC *pUpdater, CBaseEntity *pEnemy, const Vector &position ); - - bool OccupyStrategySlotRange( CBaseEntity *pEnemy, int slotIDStart, int slotIDEnd, int *pSlot ); - void VacateStrategySlot( CBaseEntity *pEnemy, int slot); - bool IsStrategySlotRangeOccupied( CBaseEntity *pEnemy, int slotIDStart, int slotIDEnd ); - - CAI_BaseNPC * SquadMemberInRange( const Vector &vecLocation, float flDist ); - CAI_BaseNPC * NearestSquadMember( CAI_BaseNPC *pMember ); - int GetVisibleSquadMembers( CAI_BaseNPC *pMember ); - CAI_BaseNPC * GetSquadMemberNearestTo( const Vector &vecLocation ); - bool SquadIsMember( CBaseEntity *pMember ); - bool IsLeader( CAI_BaseNPC *pLeader ); - CAI_BaseNPC *GetLeader( void ); - - int BroadcastInteraction( int interactionType, void *data, CBaseCombatCharacter *sender = NULL ); - - void AddToSquad(CAI_BaseNPC *pNPC); - bool FOkToMakeSound( int soundPriority ); - void JustMadeSound( int soundPriority, float time ); - float GetSquadSoundWaitTime() const { return m_flSquadSoundWaitTime; } - void SetSquadSoundWaitTime( float time ) { m_flSquadSoundWaitTime = time; } - void SquadRemember( int iMemory ); - - void SetSquadInflictor( CBaseEntity *pInflictor ); - bool IsSquadInflictor( CBaseEntity *pInflictor ); - - static bool IsSilentMember( const CAI_BaseNPC *pNPC ); - - template - void SetSquadData( unsigned slot, const T &data ) - { - Assert( slot < MAX_SQUAD_DATA_SLOTS ); - if ( slot < MAX_SQUAD_DATA_SLOTS ) - { - m_SquadData[slot] = *((int *)&data); - } - } - - template - void GetSquadData( unsigned slot, T *pData ) - { - Assert( slot < MAX_SQUAD_DATA_SLOTS ); - if ( slot < MAX_SQUAD_DATA_SLOTS ) - { - *pData = *((T *)&m_SquadData[slot]); - } - } - - -private: - void OccupySlot( CBaseEntity *pEnemy, int i ); - void VacateSlot( CBaseEntity *pEnemy, int i ); - bool IsSlotOccupied( CBaseEntity *pEnemy, int i ) const; - -private: - friend class CAI_SaveRestoreBlockHandler; - friend class CAI_SquadManager; - - CAI_Squad(); - CAI_Squad(string_t squadName); - ~CAI_Squad(void); - - CAI_Squad* GetNext() { return m_pNextSquad; } - - void Init( string_t squadName ); - - CAI_Squad * m_pNextSquad; // The next squad is list of all squads - - string_t m_Name; - CUtlVectorFixed m_SquadMembers; - - float m_flSquadSoundWaitTime; // Time when I'm allowed to make another sound - int m_nSquadSoundPriority; // if we're still waiting, this is the priority of the current sound - - EHANDLE m_hSquadInflictor; - - int m_SquadData[MAX_SQUAD_DATA_SLOTS]; - -#ifdef PER_ENEMY_SQUADSLOTS - - AISquadEnemyInfo_t *FindEnemyInfo( CBaseEntity *pEnemy ); - const AISquadEnemyInfo_t *FindEnemyInfo( CBaseEntity *pEnemy ) const { return const_cast(this)->FindEnemyInfo( pEnemy ); } - - AISquadEnemyInfo_t * m_pLastFoundEnemyInfo; // Occupy/Vacate need to be reworked to not want this - - CUtlVector m_EnemyInfos; - float m_flEnemyInfoCleanupTime; - -#else - - CVarBitVec m_squadSlotsUsed; // What squad slots are filled? - -#endif - - //--------------------------------- -public: - DECLARE_SIMPLE_DATADESC(); -}; - -//----------------------------------------------------------------------------- -// -// Purpose: CAI_SquadManager inline functions -// -//----------------------------------------------------------------------------- - -inline CAI_Squad *CAI_SquadManager::GetFirstSquad( AISquadsIter_t *pIter ) -{ - *pIter = (AISquadsIter_t)m_pSquads; - return m_pSquads; -} - -//------------------------------------- - -inline CAI_Squad *CAI_SquadManager::GetNextSquad( AISquadsIter_t *pIter ) -{ - CAI_Squad *pSquad = (CAI_Squad *)*pIter; - if ( pSquad ) - pSquad = pSquad->m_pNextSquad; - *pIter = (AISquadsIter_t)pSquad; - return pSquad; -} - -//------------------------------------- -// Purpose: Returns squad of the given name or creates a new squad with the -// given name if none exists and add pNPC to the list of members -//------------------------------------- - -inline CAI_Squad *CAI_SquadManager::FindCreateSquad(CAI_BaseNPC *pNPC, string_t squadName) -{ - CAI_Squad* pSquad = FindSquad( squadName ); - - if ( !pSquad ) - pSquad = CreateSquad( squadName ); - - pSquad->AddToSquad( pNPC ); - - return pSquad; -} - -//----------------------------------------------------------------------------- - -inline CAI_Squad *CAI_SquadManager::FindCreateSquad(string_t squadName) -{ - CAI_Squad* pSquad = FindSquad( squadName ); - - if ( !pSquad ) - pSquad = CreateSquad( squadName ); - - return pSquad; -} - -//------------------------------------- - -inline CAI_BaseNPC *CAI_Squad::GetAnyMember() -{ - if ( m_SquadMembers.Count() ) - return m_SquadMembers[random->RandomInt( 0, m_SquadMembers.Count()-1 )]; - return NULL; -} - -//------------------------------------- - -inline int CAI_Squad::GetSquadIndex( CAI_BaseNPC *pAI ) -{ - for ( int i = 0; i < m_SquadMembers.Count(); i++ ) - { - if ( m_SquadMembers[i] == pAI ) - return i; - } - return -1; -} - - -//----------------------------------------------------------------------------- - -#endif // AI_SQUAD_H diff --git a/game/server/ai_squadslot.cpp b/game/server/ai_squadslot.cpp deleted file mode 100644 index a542e0fc0..000000000 --- a/game/server/ai_squadslot.cpp +++ /dev/null @@ -1,88 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Base combat character with no AI -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ai_squadslot.h" -#include "ai_basenpc.h" -#include "stringregistry.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//============================================================================= -// Init static variables -//============================================================================= -CAI_GlobalNamespace CAI_BaseNPC::gm_SquadSlotNamespace; - -//----------------------------------------------------------------------------- -// Purpose: Given and SquadSlot name, return the SquadSlot ID -//----------------------------------------------------------------------------- -int CAI_BaseNPC::GetSquadSlotID(const char* slotName) -{ - return gm_SquadSlotNamespace.SymbolToId(slotName); -} - - -//----------------------------------------------------------------------------- -// Purpose: Given and SquadSlot name, return the SquadSlot ID -//----------------------------------------------------------------------------- -const char* CAI_BaseNPC::GetSquadSlotDebugName( int iSquadSlot ) -{ - switch( iSquadSlot ) - { - case SQUAD_SLOT_NONE: return "None"; - break; - case SQUAD_SLOT_ATTACK1: return "SQUAD_SLOT_ATTACK1"; - break; - case SQUAD_SLOT_ATTACK2: return "SQUAD_SLOT_ATTACK2"; - break; - case SQUAD_SLOT_INVESTIGATE_SOUND: return "SQUAD_SLOT_INVESTIGATE_SOUND"; - break; - case SQUAD_SLOT_EXCLUSIVE_HANDSIGN: return "SQUAD_SLOT_EXCLUSIVE_HANDSIGN"; - break; - case SQUAD_SLOT_EXCLUSIVE_RELOAD: return "SQUAD_SLOT_EXCLUSIVE_RELOAD"; - break; - case SQUAD_SLOT_PICKUP_WEAPON1: return "SQUAD_SLOT_PICKUP_WEAPON1"; - break; - case SQUAD_SLOT_PICKUP_WEAPON2: return "SQUAD_SLOT_PICKUP_WEAPON2"; - break; - case SQUAD_SLOT_SPECIAL_ATTACK: return "SQUAD_SLOT_SPECIAL_ATTACK"; - break; - - default: - // If we default, that means that our derived class (which has already been called) - // didn't provide text for a squad slot that isn't part of the base ai squad slots. - // OR someone added a squad slot to base AI and didn't update here. - return "Failed to specify!"; - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_BaseNPC::InitDefaultSquadSlotSR(void) -{ - gm_SquadSlotNamespace.AddSymbol( "SQUAD_SLOT_ATTACK1", AI_RemapToGlobal(SQUAD_SLOT_ATTACK1) ); - gm_SquadSlotNamespace.AddSymbol( "SQUAD_SLOT_ATTACK2", AI_RemapToGlobal(SQUAD_SLOT_ATTACK2) ); - gm_SquadSlotNamespace.AddSymbol( "SQUAD_SLOT_INVESTIGATE_SOUND", AI_RemapToGlobal(SQUAD_SLOT_INVESTIGATE_SOUND) ); - gm_SquadSlotNamespace.AddSymbol( "SQUAD_SLOT_EXCLUSIVE_HANDSIGN", AI_RemapToGlobal(SQUAD_SLOT_EXCLUSIVE_HANDSIGN) ); - gm_SquadSlotNamespace.AddSymbol( "SQUAD_SLOT_EXCLUSIVE_RELOAD", AI_RemapToGlobal(SQUAD_SLOT_EXCLUSIVE_RELOAD) ); - gm_SquadSlotNamespace.AddSymbol( "SQUAD_SLOT_PICKUP_WEAPON1", AI_RemapToGlobal(SQUAD_SLOT_PICKUP_WEAPON1) ); - gm_SquadSlotNamespace.AddSymbol( "SQUAD_SLOT_PICKUP_WEAPON2", AI_RemapToGlobal(SQUAD_SLOT_PICKUP_WEAPON2) ); - gm_SquadSlotNamespace.AddSymbol( "SQUAD_SLOT_SPECIAL_ATTACK", AI_RemapToGlobal(SQUAD_SLOT_SPECIAL_ATTACK) ); -} - diff --git a/game/server/ai_squadslot.h b/game/server/ai_squadslot.h deleted file mode 100644 index 1f3c8bdb6..000000000 --- a/game/server/ai_squadslot.h +++ /dev/null @@ -1,50 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: The default shared conditions -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SQUADSLOT_H -#define SQUADSLOT_H - -#define MAX_SQUADSLOTS 32 - -//========================================================= -// These are the default shared squad slots -// -// NOTE: If you add a new squad slot here, make sure you -// update GetSquadSlotDebugName() -//========================================================= -enum SQUAD_SLOT_t { - - // Currently there are no shared squad slots - SQUAD_SLOT_NONE = -1, - - SQUAD_SLOT_ATTACK1 = 0, // reserve 2 attack slots for most squads - SQUAD_SLOT_ATTACK2, - - SQUAD_SLOT_INVESTIGATE_SOUND, - - SQUAD_SLOT_EXCLUSIVE_HANDSIGN, // only one person in a squad should do this! - SQUAD_SLOT_EXCLUSIVE_RELOAD, - - SQUAD_SLOT_PICKUP_WEAPON1, - SQUAD_SLOT_PICKUP_WEAPON2, - - SQUAD_SLOT_SPECIAL_ATTACK, // Combine Elite using the combine ball attack, for instance. - - // ====================================== - // IMPORTANT: This must be the last enum - // ====================================== - LAST_SHARED_SQUADSLOT, -}; - - -#endif //SQUADSLOT_H diff --git a/game/server/ai_tacticalservices.cpp b/game/server/ai_tacticalservices.cpp deleted file mode 100644 index c6f632a7c..000000000 --- a/game/server/ai_tacticalservices.cpp +++ /dev/null @@ -1,794 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ==== -// -//============================================================================= - -#include "cbase.h" - -#include "bitstring.h" - -#include "ai_tacticalservices.h" -#include "ai_basenpc.h" -#include "ai_node.h" -#include "ai_network.h" -#include "ai_link.h" -#include "ai_moveprobe.h" -#include "ai_pathfinder.h" -#include "ai_navigator.h" -#include "ai_networkmanager.h" -#include "ai_hint.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar ai_find_lateral_cover( "ai_find_lateral_cover", "1" ); -ConVar ai_find_lateral_los( "ai_find_lateral_los", "1" ); - -#ifdef _DEBUG -ConVar ai_debug_cover( "ai_debug_cover", "0" ); -int g_AIDebugFindCoverNode = -1; -#define DebugFindCover( node, from, to, r, g, b ) \ - if ( !ai_debug_cover.GetBool() || \ - (g_AIDebugFindCoverNode != -1 && g_AIDebugFindCoverNode != node) || \ - !GetOuter()->m_bSelected ) \ - ; \ - else \ - NDebugOverlay::Line( from, to, r, g, b, false, 1 ) - -#define DebugFindCover2( node, from, to, r, g, b ) \ - if ( ai_debug_cover.GetInt() < 2 || \ - (g_AIDebugFindCoverNode != -1 && g_AIDebugFindCoverNode != node) || \ - !GetOuter()->m_bSelected ) \ - ; \ - else \ - NDebugOverlay::Line( from, to, r, g, b, false, 1 ) - -ConVar ai_debug_tactical_los( "ai_debug_tactical_los", "0" ); -int g_AIDebugFindLosNode = -1; -#define ShouldDebugLos( node ) ( ai_debug_tactical_los.GetBool() && ( g_AIDebugFindLosNode == -1 || g_AIDebugFindLosNode == ( node ) ) && GetOuter()->m_bSelected ) -#else -#define DebugFindCover( node, from, to, r, g, b ) ((void)0) -#define DebugFindCover2( node, from, to, r, g, b ) ((void)0) -#define ShouldDebugLos( node ) false -#endif - -//----------------------------------------------------------------------------- - -BEGIN_SIMPLE_DATADESC(CAI_TacticalServices) - // m_pNetwork (not saved) - // m_pPathfinder (not saved) - DEFINE_FIELD( m_bAllowFindLateralLos, FIELD_BOOLEAN ), - -END_DATADESC(); - -//------------------------------------- - -void CAI_TacticalServices::Init( CAI_Network *pNetwork ) -{ - Assert( pNetwork ); - m_pNetwork = pNetwork; - m_pPathfinder = GetOuter()->GetPathfinder(); - Assert( m_pPathfinder ); -} - -//------------------------------------- - -bool CAI_TacticalServices::FindLos(const Vector &threatPos, const Vector &threatEyePos, float minThreatDist, float maxThreatDist, float blockTime, FlankType_t eFlankType, const Vector &vecFlankRefPos, float flFlankParam, Vector *pResult) -{ - AI_PROFILE_SCOPE( CAI_TacticalServices_FindLos ); - - MARK_TASK_EXPENSIVE(); - - int node = FindLosNode( threatPos, threatEyePos, - minThreatDist, maxThreatDist, - blockTime, eFlankType, vecFlankRefPos, flFlankParam ); - - if (node == NO_NODE) - return false; - - *pResult = GetNodePos( node ); - return true; -} - -//------------------------------------- - -bool CAI_TacticalServices::FindLos(const Vector &threatPos, const Vector &threatEyePos, float minThreatDist, float maxThreatDist, float blockTime, Vector *pResult) -{ - return FindLos( threatPos, threatEyePos, minThreatDist, maxThreatDist, blockTime, FLANKTYPE_NONE, vec3_origin, 0, pResult ); -} - -//------------------------------------- - -bool CAI_TacticalServices::FindBackAwayPos( const Vector &vecThreat, Vector *pResult ) -{ - MARK_TASK_EXPENSIVE(); - - Vector vMoveAway = GetAbsOrigin() - vecThreat; - vMoveAway.NormalizeInPlace(); - - if ( GetOuter()->GetNavigator()->FindVectorGoal( pResult, vMoveAway, 10*12, 10*12, true ) ) - return true; - - int node = FindBackAwayNode( vecThreat ); - - if (node != NO_NODE) - { - *pResult = GetNodePos( node ); - return true; - } - - if ( GetOuter()->GetNavigator()->FindVectorGoal( pResult, vMoveAway, GetHullWidth() * 4, GetHullWidth() * 2, true ) ) - return true; - - return false; -} - -//------------------------------------- - -bool CAI_TacticalServices::FindCoverPos( const Vector &vThreatPos, const Vector &vThreatEyePos, float flMinDist, float flMaxDist, Vector *pResult ) -{ - return FindCoverPos( GetLocalOrigin(), vThreatPos, vThreatEyePos, flMinDist, flMaxDist, pResult ); -} - -//------------------------------------- - -bool CAI_TacticalServices::FindCoverPos( const Vector &vNearPos, const Vector &vThreatPos, const Vector &vThreatEyePos, float flMinDist, float flMaxDist, Vector *pResult ) -{ - AI_PROFILE_SCOPE( CAI_TacticalServices_FindCoverPos ); - - MARK_TASK_EXPENSIVE(); - - int node = FindCoverNode( vNearPos, vThreatPos, vThreatEyePos, flMinDist, flMaxDist ); - - if (node == NO_NODE) - return false; - - *pResult = GetNodePos( node ); - return true; -} - -//------------------------------------- -// Checks lateral cover -//------------------------------------- -bool CAI_TacticalServices::TestLateralCover( const Vector &vecCheckStart, const Vector &vecCheckEnd, float flMinDist ) -{ - trace_t tr; - - if ( (vecCheckStart - vecCheckEnd).LengthSqr() > Square(flMinDist) ) - { - if (GetOuter()->IsCoverPosition(vecCheckStart, vecCheckEnd + GetOuter()->GetViewOffset())) - { - if ( GetOuter()->IsValidCover ( vecCheckEnd, NULL ) ) - { - AIMoveTrace_t moveTrace; - GetOuter()->GetMoveProbe()->MoveLimit( NAV_GROUND, GetLocalOrigin(), vecCheckEnd, MASK_NPCSOLID, NULL, &moveTrace ); - if (moveTrace.fStatus == AIMR_OK) - { - DebugFindCover( NO_NODE, vecCheckEnd + GetOuter()->GetViewOffset(), vecCheckStart, 0, 255, 0 ); - return true; - } - } - } - } - - DebugFindCover( NO_NODE, vecCheckEnd + GetOuter()->GetViewOffset(), vecCheckStart, 255, 0, 0 ); - - return false; -} - - -//------------------------------------- -// FindLateralCover - attempts to locate a spot in the world -// directly to the left or right of the caller that will -// conceal them from view of pSightEnt -//------------------------------------- - -#define COVER_CHECKS 5// how many checks are made -#define COVER_DELTA 48// distance between checks -bool CAI_TacticalServices::FindLateralCover( const Vector &vecThreat, float flMinDist, Vector *pResult ) -{ - return FindLateralCover( vecThreat, flMinDist, COVER_CHECKS * COVER_DELTA, COVER_CHECKS, pResult ); -} - -bool CAI_TacticalServices::FindLateralCover( const Vector &vecThreat, float flMinDist, float distToCheck, int numChecksPerDir, Vector *pResult ) -{ - return FindLateralCover( GetAbsOrigin(), vecThreat, flMinDist, distToCheck, numChecksPerDir, pResult ); -} - -bool CAI_TacticalServices::FindLateralCover( const Vector &vNearPos, const Vector &vecThreat, float flMinDist, float distToCheck, int numChecksPerDir, Vector *pResult ) -{ - AI_PROFILE_SCOPE( CAI_TacticalServices_FindLateralCover ); - - MARK_TASK_EXPENSIVE(); - - Vector vecLeftTest; - Vector vecRightTest; - Vector vecStepRight; - Vector vecCheckStart; - int i; - - if ( TestLateralCover( vecThreat, vNearPos, flMinDist ) ) - { - *pResult = GetLocalOrigin(); - return true; - } - - if( !ai_find_lateral_cover.GetBool() ) - { - // Force the NPC to use the nodegraph to find cover. NOTE: We let the above code run - // to detect the case where the NPC may already be standing in cover, but we don't - // make any additional lateral checks. - return false; - } - - Vector right = vecThreat - vNearPos; - float temp; - - right.z = 0; - VectorNormalize( right ); - temp = right.x; - right.x = -right.y; - right.y = temp; - - vecStepRight = right * (distToCheck / (float)numChecksPerDir); - vecStepRight.z = 0; - - vecLeftTest = vecRightTest = vNearPos; - vecCheckStart = vecThreat; - - for ( i = 0 ; i < numChecksPerDir ; i++ ) - { - vecLeftTest = vecLeftTest - vecStepRight; - vecRightTest = vecRightTest + vecStepRight; - - if (TestLateralCover( vecCheckStart, vecLeftTest, flMinDist )) - { - *pResult = vecLeftTest; - return true; - } - - if (TestLateralCover( vecCheckStart, vecRightTest, flMinDist )) - { - *pResult = vecRightTest; - return true; - } - } - - return false; -} - -//------------------------------------- -// Purpose: Find a nearby node that further away from the enemy than the -// min range of my current weapon if there is one or just futher -// away than my current location if I don't have a weapon. -// Used to back away for attacks -//------------------------------------- - -int CAI_TacticalServices::FindBackAwayNode(const Vector &vecThreat ) -{ - if ( !CAI_NetworkManager::NetworksLoaded() ) - { - DevWarning( 2, "Graph not ready for FindBackAwayNode!\n" ); - return NO_NODE; - } - - int iMyNode = GetPathfinder()->NearestNodeToNPC(); - int iThreatNode = GetPathfinder()->NearestNodeToPoint( vecThreat ); - - if ( iMyNode == NO_NODE ) - { - DevWarning( 2, "FindBackAwayNode() - %s has no nearest node!\n", GetEntClassname()); - return NO_NODE; - } - if ( iThreatNode == NO_NODE ) - { - // DevWarning( 2, "FindBackAwayNode() - Threat has no nearest node!\n" ); - iThreatNode = iMyNode; - // return false; - } - - // A vector pointing to the threat. - Vector vecToThreat; - vecToThreat = vecThreat - GetLocalOrigin(); - - // Get my current distance from the threat - float flCurDist = VectorNormalize( vecToThreat ); - - // Check my neighbors to find a node that's further away - for (int link = 0; link < GetNetwork()->GetNode(iMyNode)->NumLinks(); link++) - { - CAI_Link *nodeLink = GetNetwork()->GetNode(iMyNode)->GetLinkByIndex(link); - - if ( !m_pPathfinder->IsLinkUsable( nodeLink, iMyNode ) ) - continue; - - int destID = nodeLink->DestNodeID(iMyNode); - - float flTestDist = ( vecThreat - GetNetwork()->GetNode(destID)->GetPosition(GetHullType()) ).Length(); - - if ( flTestDist > flCurDist ) - { - // Make sure this node doesn't take me past the enemy's position. - Vector vecToNode; - vecToNode = GetNetwork()->GetNode(destID)->GetPosition(GetHullType()) - GetLocalOrigin(); - VectorNormalize( vecToNode ); - - if( DotProduct( vecToNode, vecToThreat ) < 0.0 ) - { - return destID; - } - } - } - return NO_NODE; -} - -//------------------------------------- -// FindCover - tries to find a nearby node that will hide -// the caller from its enemy. -// -// If supplied, search will return a node at least as far -// away as MinDist, but no farther than MaxDist. -// if MaxDist isn't supplied, it defaults to a reasonable -// value -//------------------------------------- - -int CAI_TacticalServices::FindCoverNode(const Vector &vThreatPos, const Vector &vThreatEyePos, float flMinDist, float flMaxDist ) -{ - return FindCoverNode(GetLocalOrigin(), vThreatPos, vThreatEyePos, flMinDist, flMaxDist ); -} - -//------------------------------------- - -int CAI_TacticalServices::FindCoverNode(const Vector &vNearPos, const Vector &vThreatPos, const Vector &vThreatEyePos, float flMinDist, float flMaxDist ) -{ - if ( !CAI_NetworkManager::NetworksLoaded() ) - return NO_NODE; - - AI_PROFILE_SCOPE( CAI_TacticalServices_FindCoverNode ); - - MARK_TASK_EXPENSIVE(); - - DebugFindCover( g_AIDebugFindCoverNode, GetOuter()->EyePosition(), vThreatEyePos, 0, 255, 255 ); - - int iMyNode = GetPathfinder()->NearestNodeToPoint( vNearPos ); - - if ( iMyNode == NO_NODE ) - { - Vector pos = GetOuter()->GetAbsOrigin(); - DevWarning( 2, "FindCover() - %s has no nearest node! (Check near %f %f %f)\n", GetEntClassname(), pos.x, pos.y, pos.z); - return NO_NODE; - } - - if ( !flMaxDist ) - { - // user didn't supply a MaxDist, so work up a crazy one. - flMaxDist = 784; - } - - if ( flMinDist > 0.5 * flMaxDist) - { - flMinDist = 0.5 * flMaxDist; - } - - // ------------------------------------------------------------------------------------ - // We're going to search for a cover node by expanding to our current node's neighbors - // and then their neighbors, until cover is found, or all nodes are beyond MaxDist - // ------------------------------------------------------------------------------------ - AI_NearNode_t *pBuffer = (AI_NearNode_t *)stackalloc( sizeof(AI_NearNode_t) * GetNetwork()->NumNodes() ); - CNodeList list( pBuffer, GetNetwork()->NumNodes() ); - CVarBitVec wasVisited(GetNetwork()->NumNodes()); // Nodes visited - - // mark start as visited - list.Insert( AI_NearNode_t(iMyNode, 0) ); - wasVisited.Set( iMyNode ); - float flMinDistSqr = flMinDist*flMinDist; - float flMaxDistSqr = flMaxDist*flMaxDist; - - static int nSearchRandomizer = 0; // tries to ensure the links are searched in a different order each time; - - // Search until the list is empty - while( list.Count() ) - { - // Get the node that is closest in the number of steps and remove from the list - int nodeIndex = list.ElementAtHead().nodeIndex; - list.RemoveAtHead(); - - CAI_Node *pNode = GetNetwork()->GetNode(nodeIndex); - Vector nodeOrigin = pNode->GetPosition(GetHullType()); - - float dist = (vNearPos - nodeOrigin).LengthSqr(); - if (dist >= flMinDistSqr && dist < flMaxDistSqr) - { - Activity nCoverActivity = GetOuter()->GetCoverActivity( pNode->GetHint() ); - Vector vEyePos = nodeOrigin + GetOuter()->EyeOffset(nCoverActivity); - - if ( GetOuter()->IsValidCover( nodeOrigin, pNode->GetHint() ) ) - { - // Check if this location will block the threat's line of sight to me - if (GetOuter()->IsCoverPosition(vThreatEyePos, vEyePos)) - { - // -------------------------------------------------------- - // Don't let anyone else use this node for a while - // -------------------------------------------------------- - pNode->Lock( 1.0 ); - - if ( pNode->GetHint() && ( pNode->GetHint()->HintType() == HINT_TACTICAL_COVER_MED || pNode->GetHint()->HintType() == HINT_TACTICAL_COVER_LOW ) ) - { - if ( GetOuter()->GetHintNode() ) - { - GetOuter()->GetHintNode()->Unlock(GetOuter()->GetHintDelay(GetOuter()->GetHintNode()->HintType())); - GetOuter()->SetHintNode( NULL ); - } - - GetOuter()->SetHintNode( pNode->GetHint() ); - } - - // The next NPC who searches should use a slight different pattern - nSearchRandomizer = nodeIndex; - DebugFindCover( pNode->GetId(), vEyePos, vThreatEyePos, 0, 255, 0 ); - return nodeIndex; - } - else - { - DebugFindCover( pNode->GetId(), vEyePos, vThreatEyePos, 255, 0, 0 ); - } - } - else - { - DebugFindCover( pNode->GetId(), vEyePos, vThreatEyePos, 0, 0, 255 ); - } - } - - // Add its children to the search list - // Go through each link - // UNDONE: Pass in a cost function to measure each link? - for ( int link = 0; link < GetNetwork()->GetNode(nodeIndex)->NumLinks(); link++ ) - { - int index = (link + nSearchRandomizer) % GetNetwork()->GetNode(nodeIndex)->NumLinks(); - CAI_Link *nodeLink = GetNetwork()->GetNode(nodeIndex)->GetLinkByIndex(index); - - if ( !m_pPathfinder->IsLinkUsable( nodeLink, iMyNode ) ) - continue; - - int newID = nodeLink->DestNodeID(nodeIndex); - - // If not already on the closed list, add to it and set its distance - if (!wasVisited.IsBitSet(newID)) - { - // Don't accept climb nodes or nodes that aren't ready to use yet - if ( GetNetwork()->GetNode(newID)->GetType() != NODE_CLIMB && !GetNetwork()->GetNode(newID)->IsLocked() ) - { - // UNDONE: Shouldn't we really accumulate the distance by path rather than - // absolute distance. After all, we are performing essentially an A* here. - nodeOrigin = GetNetwork()->GetNode(newID)->GetPosition(GetHullType()); - dist = (vNearPos - nodeOrigin).LengthSqr(); - - // use distance to threat as a heuristic to keep AIs from running toward - // the threat in order to take cover from it. - float threatDist = (vThreatPos - nodeOrigin).LengthSqr(); - - // Now check this node is not too close towards the threat - if ( dist < threatDist * 1.5 ) - { - list.Insert( AI_NearNode_t(newID, dist) ); - } - } - // mark visited - wasVisited.Set(newID); - } - } - } - - // We failed. Not cover node was found - // Clear hint node used to set ducking - GetOuter()->ClearHintNode(); - return NO_NODE; -} - - -//------------------------------------- -// Purpose: Return node ID that has line of sight to target I want to shoot -// -// Input : pNPC - npc that's looking for a place to shoot from -// vThreatPos - position of entity/location I'm trying to shoot -// vThreatEyePos - eye position of entity I'm trying to shoot. If -// entity has no eye position, just give vThreatPos again -// flMinThreatDist - minimum distance that node must be from vThreatPos -// flMaxThreadDist - maximum distance that node can be from vThreadPos -// vThreatFacing - optional argument. If given the returned node -// will also be behind the given facing direction (flanking) -// flBlockTime - how long to block this node from use -// Output : int - ID number of node that meets qualifications -//------------------------------------- - -int CAI_TacticalServices::FindLosNode(const Vector &vThreatPos, const Vector &vThreatEyePos, float flMinThreatDist, float flMaxThreatDist, float flBlockTime, FlankType_t eFlankType, const Vector &vecFlankRefPos, float flFlankParam ) -{ - if ( !CAI_NetworkManager::NetworksLoaded() ) - return NO_NODE; - - AI_PROFILE_SCOPE( CAI_TacticalServices_FindLosNode ); - - MARK_TASK_EXPENSIVE(); - - int iMyNode = GetPathfinder()->NearestNodeToNPC(); - if ( iMyNode == NO_NODE ) - { - Vector pos = GetOuter()->GetAbsOrigin(); - DevWarning( 2, "FindCover() - %s has no nearest node! (Check near %f %f %f)\n", GetEntClassname(), pos.x, pos.y, pos.z); - return NO_NODE; - } - - // ------------------------------------------------------------------------------------ - // We're going to search for a shoot node by expanding to our current node's neighbors - // and then their neighbors, until a shooting position is found, or all nodes are beyond MaxDist - // ------------------------------------------------------------------------------------ - AI_NearNode_t *pBuffer = (AI_NearNode_t *)stackalloc( sizeof(AI_NearNode_t) * GetNetwork()->NumNodes() ); - CNodeList list( pBuffer, GetNetwork()->NumNodes() ); - CVarBitVec wasVisited(GetNetwork()->NumNodes()); // Nodes visited - - // mark start as visited - wasVisited.Set( iMyNode ); - list.Insert( AI_NearNode_t(iMyNode, 0) ); - - static int nSearchRandomizer = 0; // tries to ensure the links are searched in a different order each time; - - while ( list.Count() ) - { - int nodeIndex = list.ElementAtHead().nodeIndex; - // remove this item from the list - list.RemoveAtHead(); - - const Vector &nodeOrigin = GetNetwork()->GetNode(nodeIndex)->GetPosition(GetHullType()); - - // HACKHACK: Can't we rework this loop and get rid of this? - // skip the starting node, or we probably wouldn't have called this function. - if ( nodeIndex != iMyNode ) - { - bool skip = false; - - // See if the node satisfies the flanking criteria. - switch ( eFlankType ) - { - case FLANKTYPE_NONE: - break; - - case FLANKTYPE_RADIUS: - { - Vector vecDist = nodeOrigin - vecFlankRefPos; - if ( vecDist.Length() < flFlankParam ) - { - skip = true; - } - - break; - } - - case FLANKTYPE_ARC: - { - Vector vecEnemyToRef = vecFlankRefPos - vThreatPos; - VectorNormalize( vecEnemyToRef ); - - Vector vecEnemyToNode = nodeOrigin - vThreatPos; - VectorNormalize( vecEnemyToNode ); - - float flDot = DotProduct( vecEnemyToRef, vecEnemyToNode ); - - if ( RAD2DEG( acos( flDot ) ) < flFlankParam ) - { - skip = true; - } - - break; - } - } - - // Don't accept climb nodes, and assume my nearest node isn't valid because - // we decided to make this check in the first place. Keep moving - if ( !skip && !GetNetwork()->GetNode(nodeIndex)->IsLocked() && - GetNetwork()->GetNode(nodeIndex)->GetType() != NODE_CLIMB ) - { - // Now check its distance and only accept if in range - float flThreatDist = ( nodeOrigin - vThreatPos ).Length(); - - if ( flThreatDist < flMaxThreatDist && - flThreatDist > flMinThreatDist ) - { - CAI_Node *pNode = GetNetwork()->GetNode(nodeIndex); - if ( GetOuter()->IsValidShootPosition( nodeOrigin, pNode, pNode->GetHint() ) ) - { - if (GetOuter()->TestShootPosition(nodeOrigin,vThreatEyePos)) - { - // Note when this node was used, so we don't try - // to use it again right away. - GetNetwork()->GetNode(nodeIndex)->Lock( flBlockTime ); - -#if 0 - if ( GetOuter()->GetHintNode() ) - { - GetOuter()->GetHintNode()->Unlock(GetOuter()->GetHintDelay(GetOuter()->GetHintNode()->HintType())); - GetOuter()->SetHintNode( NULL ); - } - - // This used to not be set, why? (kenb) - // @Note (toml 05-19-04): I think because stomping the hint can lead to - // unintended side effects. The hint node is primarily a high level - // tool, and certain NPCs break if it gets slammed here. If we need - // this, we should propagate it out and let the schedule selector - // or task decide to set the hint node - GetOuter()->SetHintNode( GetNetwork()->GetNode(nodeIndex)->GetHint() ); -#endif - if ( ShouldDebugLos( nodeIndex ) ) - { - NDebugOverlay::Text( nodeOrigin, CFmtStr( "%d:los!", nodeIndex), false, 1 ); - } - - // The next NPC who searches should use a slight different pattern - nSearchRandomizer = nodeIndex; - return nodeIndex; - } - else - { - if ( ShouldDebugLos( nodeIndex ) ) - { - NDebugOverlay::Text( nodeOrigin, CFmtStr( "%d:!shoot", nodeIndex), false, 1 ); - } - } - } - else - { - if ( ShouldDebugLos( nodeIndex ) ) - { - NDebugOverlay::Text( nodeOrigin, CFmtStr( "%d:!valid", nodeIndex), false, 1 ); - } - } - } - else - { - if ( ShouldDebugLos( nodeIndex ) ) - { - CFmtStr msg( "%d:%s", nodeIndex, ( flThreatDist < flMaxThreatDist ) ? "too close" : "too far" ); - NDebugOverlay::Text( nodeOrigin, msg, false, 1 ); - } - } - } - } - - // Go through each link and add connected nodes to the list - for (int link=0; link < GetNetwork()->GetNode(nodeIndex)->NumLinks();link++) - { - int index = (link + nSearchRandomizer) % GetNetwork()->GetNode(nodeIndex)->NumLinks(); - CAI_Link *nodeLink = GetNetwork()->GetNode(nodeIndex)->GetLinkByIndex(index); - - if ( !m_pPathfinder->IsLinkUsable( nodeLink, iMyNode ) ) - continue; - - int newID = nodeLink->DestNodeID(nodeIndex); - - // If not already visited, add to the list - if (!wasVisited.IsBitSet(newID)) - { - float dist = (GetLocalOrigin() - GetNetwork()->GetNode(newID)->GetPosition(GetHullType())).LengthSqr(); - list.Insert( AI_NearNode_t(newID, dist) ); - wasVisited.Set( newID ); - } - } - } - // We failed. No range attack node node was found - return NO_NODE; -} - -//------------------------------------- -// Checks lateral LOS -//------------------------------------- -bool CAI_TacticalServices::TestLateralLos( const Vector &vecCheckStart, const Vector &vecCheckEnd ) -{ - trace_t tr; - - // it's faster to check the SightEnt's visibility to the potential spot than to check the local move, so we do that first. - AI_TraceLOS( vecCheckStart, vecCheckEnd + GetOuter()->GetViewOffset(), NULL, &tr ); - - if (tr.fraction == 1.0) - { - if ( GetOuter()->IsValidShootPosition( vecCheckEnd, NULL, NULL ) ) - { - if (GetOuter()->TestShootPosition(vecCheckEnd,vecCheckStart)) - { - AIMoveTrace_t moveTrace; - GetOuter()->GetMoveProbe()->MoveLimit( NAV_GROUND, GetLocalOrigin(), vecCheckEnd, MASK_NPCSOLID, NULL, &moveTrace ); - if (moveTrace.fStatus == AIMR_OK) - { - return true; - } - } - } - } - - return false; -} - - -//------------------------------------- - -bool CAI_TacticalServices::FindLateralLos( const Vector &vecThreat, Vector *pResult ) -{ - AI_PROFILE_SCOPE( CAI_TacticalServices_FindLateralLos ); - - if( !m_bAllowFindLateralLos ) - { - return false; - } - - MARK_TASK_EXPENSIVE(); - - Vector vecLeftTest; - Vector vecRightTest; - Vector vecStepRight; - Vector vecCheckStart; - bool bLookingForEnemy = GetEnemy() && VectorsAreEqual(vecThreat, GetEnemy()->EyePosition(), 0.1f); - int i; - - if( !bLookingForEnemy || GetOuter()->HasCondition(COND_SEE_ENEMY) || GetOuter()->HasCondition(COND_HAVE_ENEMY_LOS) || - GetOuter()->GetTimeScheduleStarted() == gpGlobals->curtime ) // Conditions get nuked before tasks run, assume should try - { - // My current position might already be valid. - if ( TestLateralLos(vecThreat, GetLocalOrigin()) ) - { - *pResult = GetLocalOrigin(); - return true; - } - } - - if( !ai_find_lateral_los.GetBool() ) - { - // Allows us to turn off lateral LOS at the console. Allow the above code to run - // just in case the NPC has line of sight to begin with. - return false; - } - - int iChecks = COVER_CHECKS; - int iDelta = COVER_DELTA; - - // If we're limited in how far we're allowed to move laterally, don't bother checking past it - int iMaxLateralDelta = (int)GetOuter()->GetMaxTacticalLateralMovement(); - if ( iMaxLateralDelta != MAXTACLAT_IGNORE && iMaxLateralDelta < iDelta ) - { - iChecks = 1; - iDelta = iMaxLateralDelta; - } - - Vector right; - AngleVectors( GetLocalAngles(), NULL, &right, NULL ); - vecStepRight = right * iDelta; - vecStepRight.z = 0; - - vecLeftTest = vecRightTest = GetLocalOrigin(); - vecCheckStart = vecThreat; - - for ( i = 0 ; i < iChecks; i++ ) - { - vecLeftTest = vecLeftTest - vecStepRight; - vecRightTest = vecRightTest + vecStepRight; - - if (TestLateralLos( vecCheckStart, vecLeftTest )) - { - *pResult = vecLeftTest; - return true; - } - - if (TestLateralLos( vecCheckStart, vecRightTest )) - { - *pResult = vecRightTest; - return true; - } - } - - return false; -} - -//------------------------------------- - -Vector CAI_TacticalServices::GetNodePos( int node ) -{ - return GetNetwork()->GetNode((int)node)->GetPosition(GetHullType()); -} - -//----------------------------------------------------------------------------- diff --git a/game/server/ai_tacticalservices.h b/game/server/ai_tacticalservices.h deleted file mode 100644 index a9514af23..000000000 --- a/game/server/ai_tacticalservices.h +++ /dev/null @@ -1,80 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ==== -// -//============================================================================= - -#ifndef AI_TACTICALSERVICES_H -#define AI_TACTICALSERVICES_H - -#include "ai_component.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -class CAI_Network; -class CAI_Pathfinder; - - -enum FlankType_t -{ - FLANKTYPE_NONE = 0, - FLANKTYPE_ARC, // Stay flFlankParam degrees of arc away from vecFlankRefPos - FLANKTYPE_RADIUS, // Stay flFlankParam units away from vecFlankRefPos -}; - - -//----------------------------------------------------------------------------- - -class CAI_TacticalServices : public CAI_Component -{ -public: - CAI_TacticalServices( CAI_BaseNPC *pOuter ) - : CAI_Component(pOuter), - m_pNetwork( NULL ) - { - m_bAllowFindLateralLos = true; - } - - void Init( CAI_Network *pNetwork ); - - bool FindLos( const Vector &threatPos, const Vector &threatEyePos, float minThreatDist, float maxThreatDist, float blockTime, Vector *pResult ); - bool FindLos( const Vector &threatPos, const Vector &threatEyePos, float minThreatDist, float maxThreatDist, float blockTime, FlankType_t eFlankType, const Vector &VecFlankRefPos, float flFlankParam, Vector *pResult ); - bool FindLateralLos( const Vector &threatPos, Vector *pResult ); - bool FindBackAwayPos( const Vector &vecThreat, Vector *pResult ); - bool FindCoverPos( const Vector &vThreatPos, const Vector &vThreatEyePos, float flMinDist, float flMaxDist, Vector *pResult ); - bool FindCoverPos( const Vector &vNearPos, const Vector &vThreatPos, const Vector &vThreatEyePos, float flMinDist, float flMaxDist, Vector *pResult ); - bool FindLateralCover( const Vector &vecThreat, float flMinDist, Vector *pResult ); - bool FindLateralCover( const Vector &vecThreat, float flMinDist, float distToCheck, int numChecksPerDir, Vector *pResult ); - bool FindLateralCover( const Vector &vNearPos, const Vector &vecThreat, float flMinDist, float distToCheck, int numChecksPerDir, Vector *pResult ); - - void AllowFindLateralLos( bool bAllow ) { m_bAllowFindLateralLos = bAllow; } - -private: - // Checks lateral cover - bool TestLateralCover( const Vector &vecCheckStart, const Vector &vecCheckEnd, float flMinDist ); - bool TestLateralLos( const Vector &vecCheckStart, const Vector &vecCheckEnd ); - - int FindBackAwayNode( const Vector &vecThreat ); - int FindCoverNode( const Vector &vThreatPos, const Vector &vThreatEyePos, float flMinDist, float flMaxDist ); - int FindCoverNode( const Vector &vNearPos, const Vector &vThreatPos, const Vector &vThreatEyePos, float flMinDist, float flMaxDist ); - int FindLosNode( const Vector &vThreatPos, const Vector &vThreatEyePos, float flMinThreatDist, float flMaxThreatDist, float flBlockTime, FlankType_t eFlankType, const Vector &vThreatFacing, float flFlankParam ); - - Vector GetNodePos( int ); - - CAI_Network *GetNetwork() { return m_pNetwork; } - const CAI_Network *GetNetwork() const { return m_pNetwork; } - - CAI_Pathfinder *GetPathfinder() { return m_pPathfinder; } - const CAI_Pathfinder *GetPathfinder() const { return m_pPathfinder; } - - CAI_Network *m_pNetwork; - CAI_Pathfinder *m_pPathfinder; - - bool m_bAllowFindLateralLos; // Allows us to turn Lateral LOS checking on/off. - - DECLARE_SIMPLE_DATADESC(); -}; - -//----------------------------------------------------------------------------- - -#endif // AI_TACTICALSERVICES_H diff --git a/game/server/ai_task.cpp b/game/server/ai_task.cpp deleted file mode 100644 index 70c76c284..000000000 --- a/game/server/ai_task.cpp +++ /dev/null @@ -1,227 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Sets up the tasks for default AI. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "stringregistry.h" -#include "ai_basenpc.h" -#include "ai_task.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -const char * g_ppszTaskFailureText[] = -{ - "No failure", // NO_TASK_FAILURE - "No Target", // FAIL_NO_TARGET - "Weapon owned by someone else", // FAIL_WEAPON_OWNED - "Weapon/Item doesn't exist", // FAIL_ITEM_NO_FIND - "No hint node", // FAIL_NO_HINT_NODE - "Schedule not found", // FAIL_SCHEDULE_NOT_FOUND - "Don't have an enemy", // FAIL_NO_ENEMY - "Found no backaway node", // FAIL_NO_BACKAWAY_NODE - "Couldn't find cover", // FAIL_NO_COVER - "Couldn't find flank", // FAIL_NO_FLANK - "Couldn't find shoot position", // FAIL_NO_SHOOT - "Don't have a route", // FAIL_NO_ROUTE - "Don't have a route: no goal", // FAIL_NO_ROUTE_GOAL - "Don't have a route: blocked", // FAIL_NO_ROUTE_BLOCKED - "Don't have a route: illegal move", // FAIL_NO_ROUTE_ILLEGAL - "Couldn't walk to target", // FAIL_NO_WALK - "Node already locked", // FAIL_ALREADY_LOCKED - "No sound present", // FAIL_NO_SOUND - "No scent present", // FAIL_NO_SCENT - "Bad activity", // FAIL_BAD_ACTIVITY - "No goal entity", // FAIL_NO_GOAL - "No player", // FAIL_NO_PLAYER - "Can't reach any nodes", // FAIL_NO_REACHABLE_NODE - "No AI Network to Use", // FAIL_NO_AI_NETWORK - "Bad position to Target", // FAIL_BAD_POSITION - "Route Destination No Longer Valid", // FAIL_BAD_PATH_GOAL - "Stuck on top of something", // FAIL_STUCK_ONTOP - "Item has been taken", // FAIL_ITEM_TAKEN -}; - -const char *TaskFailureToString( AI_TaskFailureCode_t code ) -{ - const char *pszResult; - if ( code < 0 || code >= NUM_FAIL_CODES ) - pszResult = (const char *)code; - else - pszResult = g_ppszTaskFailureText[code]; - return pszResult; -} - -//----------------------------------------------------------------------------- -// Purpose: Given and task name, return the task ID -//----------------------------------------------------------------------------- -int CAI_BaseNPC::GetTaskID(const char* taskName) -{ - return GetSchedulingSymbols()->TaskSymbolToId( taskName ); -} - -//----------------------------------------------------------------------------- -// Purpose: Initialize the task name string registry -// Input : -// Output : -//----------------------------------------------------------------------------- -void CAI_BaseNPC::InitDefaultTaskSR(void) -{ - #define ADD_DEF_TASK( name ) idSpace.AddTask(#name, name, "CAI_BaseNPC" ) - - CAI_ClassScheduleIdSpace &idSpace = CAI_BaseNPC::AccessClassScheduleIdSpaceDirect(); - - ADD_DEF_TASK( TASK_INVALID ); - ADD_DEF_TASK( TASK_ANNOUNCE_ATTACK ); - ADD_DEF_TASK( TASK_RESET_ACTIVITY ); - ADD_DEF_TASK( TASK_WAIT ); - ADD_DEF_TASK( TASK_WAIT_FACE_ENEMY ); - ADD_DEF_TASK( TASK_WAIT_FACE_ENEMY_RANDOM ); - ADD_DEF_TASK( TASK_WAIT_PVS ); - ADD_DEF_TASK( TASK_SUGGEST_STATE ); - ADD_DEF_TASK( TASK_TARGET_PLAYER ); - ADD_DEF_TASK( TASK_SCRIPT_WALK_TO_TARGET ); - ADD_DEF_TASK( TASK_SCRIPT_RUN_TO_TARGET ); - ADD_DEF_TASK( TASK_SCRIPT_CUSTOM_MOVE_TO_TARGET ); - ADD_DEF_TASK( TASK_MOVE_TO_TARGET_RANGE ); - ADD_DEF_TASK( TASK_MOVE_TO_GOAL_RANGE ); - ADD_DEF_TASK( TASK_MOVE_AWAY_PATH ); - ADD_DEF_TASK( TASK_GET_PATH_AWAY_FROM_BEST_SOUND ); - ADD_DEF_TASK( TASK_SET_GOAL ); - ADD_DEF_TASK( TASK_GET_PATH_TO_GOAL ); - ADD_DEF_TASK( TASK_GET_PATH_TO_ENEMY ); - ADD_DEF_TASK( TASK_GET_PATH_TO_ENEMY_LKP ); - ADD_DEF_TASK( TASK_GET_CHASE_PATH_TO_ENEMY ); - ADD_DEF_TASK( TASK_GET_PATH_TO_ENEMY_LKP_LOS ); - ADD_DEF_TASK( TASK_GET_PATH_TO_RANGE_ENEMY_LKP_LOS ); - ADD_DEF_TASK( TASK_GET_PATH_TO_ENEMY_CORPSE ); - ADD_DEF_TASK( TASK_GET_PATH_TO_PLAYER ); - ADD_DEF_TASK( TASK_GET_PATH_TO_ENEMY_LOS ); - ADD_DEF_TASK( TASK_GET_FLANK_ARC_PATH_TO_ENEMY_LOS ); - ADD_DEF_TASK( TASK_GET_FLANK_RADIUS_PATH_TO_ENEMY_LOS ); - ADD_DEF_TASK( TASK_GET_PATH_TO_TARGET ); - ADD_DEF_TASK( TASK_GET_PATH_TO_TARGET_WEAPON ); - ADD_DEF_TASK( TASK_CREATE_PENDING_WEAPON ); - ADD_DEF_TASK( TASK_GET_PATH_TO_HINTNODE ); - ADD_DEF_TASK( TASK_STORE_LASTPOSITION ); - ADD_DEF_TASK( TASK_CLEAR_LASTPOSITION ); - ADD_DEF_TASK( TASK_STORE_POSITION_IN_SAVEPOSITION ); - ADD_DEF_TASK( TASK_STORE_BESTSOUND_IN_SAVEPOSITION ); - ADD_DEF_TASK( TASK_STORE_BESTSOUND_REACTORIGIN_IN_SAVEPOSITION ); - ADD_DEF_TASK( TASK_REACT_TO_COMBAT_SOUND ); - ADD_DEF_TASK( TASK_STORE_ENEMY_POSITION_IN_SAVEPOSITION ); - ADD_DEF_TASK( TASK_GET_PATH_TO_COMMAND_GOAL ); - ADD_DEF_TASK( TASK_MARK_COMMAND_GOAL_POS ); - ADD_DEF_TASK( TASK_CLEAR_COMMAND_GOAL ); - ADD_DEF_TASK( TASK_GET_PATH_TO_LASTPOSITION ); - ADD_DEF_TASK( TASK_GET_PATH_TO_SAVEPOSITION ); - ADD_DEF_TASK( TASK_GET_PATH_TO_SAVEPOSITION_LOS ); - ADD_DEF_TASK( TASK_GET_PATH_TO_BESTSOUND ); - ADD_DEF_TASK( TASK_GET_PATH_TO_BESTSCENT ); - ADD_DEF_TASK( TASK_GET_PATH_TO_RANDOM_NODE ); - ADD_DEF_TASK( TASK_RUN_PATH ); - ADD_DEF_TASK( TASK_WALK_PATH ); - ADD_DEF_TASK( TASK_WALK_PATH_TIMED ); - ADD_DEF_TASK( TASK_WALK_PATH_WITHIN_DIST ); - ADD_DEF_TASK( TASK_RUN_PATH_WITHIN_DIST ); - ADD_DEF_TASK( TASK_WALK_PATH_FOR_UNITS ); - ADD_DEF_TASK( TASK_RUN_PATH_FOR_UNITS ); - ADD_DEF_TASK( TASK_RUN_PATH_FLEE ); - ADD_DEF_TASK( TASK_RUN_PATH_TIMED ); - ADD_DEF_TASK( TASK_STRAFE_PATH ); - ADD_DEF_TASK( TASK_CLEAR_MOVE_WAIT ); - ADD_DEF_TASK( TASK_SMALL_FLINCH ); - ADD_DEF_TASK( TASK_BIG_FLINCH ); - ADD_DEF_TASK( TASK_DEFER_DODGE ); - ADD_DEF_TASK( TASK_FACE_IDEAL ); - ADD_DEF_TASK( TASK_FACE_REASONABLE ); - ADD_DEF_TASK( TASK_FACE_PATH ); - ADD_DEF_TASK( TASK_FACE_PLAYER ); - ADD_DEF_TASK( TASK_FACE_ENEMY ); - ADD_DEF_TASK( TASK_FACE_HINTNODE ); - ADD_DEF_TASK( TASK_PLAY_HINT_ACTIVITY ); - ADD_DEF_TASK( TASK_FACE_TARGET ); - ADD_DEF_TASK( TASK_FACE_LASTPOSITION ); - ADD_DEF_TASK( TASK_FACE_SAVEPOSITION ); - ADD_DEF_TASK( TASK_FACE_AWAY_FROM_SAVEPOSITION ); - ADD_DEF_TASK( TASK_SET_IDEAL_YAW_TO_CURRENT ); - ADD_DEF_TASK( TASK_RANGE_ATTACK1 ); - ADD_DEF_TASK( TASK_RANGE_ATTACK2 ); - ADD_DEF_TASK( TASK_MELEE_ATTACK1 ); - ADD_DEF_TASK( TASK_MELEE_ATTACK2 ); - ADD_DEF_TASK( TASK_RELOAD ); - ADD_DEF_TASK( TASK_SPECIAL_ATTACK1 ); - ADD_DEF_TASK( TASK_SPECIAL_ATTACK2 ); - ADD_DEF_TASK( TASK_FIND_HINTNODE ); - ADD_DEF_TASK( TASK_CLEAR_HINTNODE ); - ADD_DEF_TASK( TASK_FIND_LOCK_HINTNODE ); - ADD_DEF_TASK( TASK_LOCK_HINTNODE ); - ADD_DEF_TASK( TASK_SOUND_ANGRY ); - ADD_DEF_TASK( TASK_SOUND_DEATH ); - ADD_DEF_TASK( TASK_SOUND_IDLE ); - ADD_DEF_TASK( TASK_SOUND_WAKE ); - ADD_DEF_TASK( TASK_SOUND_PAIN ); - ADD_DEF_TASK( TASK_SOUND_DIE ); - ADD_DEF_TASK( TASK_SPEAK_SENTENCE ); - ADD_DEF_TASK( TASK_WAIT_FOR_SPEAK_FINISH ); - ADD_DEF_TASK( TASK_SET_ACTIVITY ); - ADD_DEF_TASK( TASK_RANDOMIZE_FRAMERATE ); - ADD_DEF_TASK( TASK_SET_SCHEDULE ); - ADD_DEF_TASK( TASK_SET_FAIL_SCHEDULE ); - ADD_DEF_TASK( TASK_SET_TOLERANCE_DISTANCE ); - ADD_DEF_TASK( TASK_SET_ROUTE_SEARCH_TIME ); - ADD_DEF_TASK( TASK_CLEAR_FAIL_SCHEDULE ); - ADD_DEF_TASK( TASK_PLAY_SEQUENCE ); - ADD_DEF_TASK( TASK_PLAY_PRIVATE_SEQUENCE ); - ADD_DEF_TASK( TASK_PLAY_PRIVATE_SEQUENCE_FACE_ENEMY ); - ADD_DEF_TASK( TASK_PLAY_SEQUENCE_FACE_ENEMY ); - ADD_DEF_TASK( TASK_PLAY_SEQUENCE_FACE_TARGET ); - ADD_DEF_TASK( TASK_FIND_COVER_FROM_BEST_SOUND ); - ADD_DEF_TASK( TASK_FIND_COVER_FROM_ENEMY ); - ADD_DEF_TASK( TASK_FIND_LATERAL_COVER_FROM_ENEMY ); - ADD_DEF_TASK( TASK_FIND_BACKAWAY_FROM_SAVEPOSITION ); - ADD_DEF_TASK( TASK_FIND_NODE_COVER_FROM_ENEMY ); - ADD_DEF_TASK( TASK_FIND_NEAR_NODE_COVER_FROM_ENEMY ); - ADD_DEF_TASK( TASK_FIND_FAR_NODE_COVER_FROM_ENEMY ); - ADD_DEF_TASK( TASK_FIND_COVER_FROM_ORIGIN ); - ADD_DEF_TASK( TASK_DIE ); - ADD_DEF_TASK( TASK_WAIT_FOR_SCRIPT ); - ADD_DEF_TASK( TASK_PUSH_SCRIPT_ARRIVAL_ACTIVITY ); - ADD_DEF_TASK( TASK_PLAY_SCRIPT ); - ADD_DEF_TASK( TASK_PLAY_SCRIPT_POST_IDLE ); - ADD_DEF_TASK( TASK_ENABLE_SCRIPT ); - ADD_DEF_TASK( TASK_PLANT_ON_SCRIPT ); - ADD_DEF_TASK( TASK_FACE_SCRIPT ); - ADD_DEF_TASK( TASK_PLAY_SCENE ); - ADD_DEF_TASK( TASK_WAIT_RANDOM ); - ADD_DEF_TASK( TASK_WAIT_INDEFINITE ); - ADD_DEF_TASK( TASK_STOP_MOVING ); - ADD_DEF_TASK( TASK_TURN_LEFT ); - ADD_DEF_TASK( TASK_TURN_RIGHT ); - ADD_DEF_TASK( TASK_REMEMBER ); - ADD_DEF_TASK( TASK_FORGET ); - ADD_DEF_TASK( TASK_WAIT_FOR_MOVEMENT ); - ADD_DEF_TASK( TASK_WAIT_FOR_MOVEMENT_STEP ); - ADD_DEF_TASK( TASK_WAIT_UNTIL_NO_DANGER_SOUND ); - ADD_DEF_TASK( TASK_WEAPON_FIND ); - ADD_DEF_TASK( TASK_WEAPON_PICKUP ); - ADD_DEF_TASK( TASK_WEAPON_RUN_PATH ); - ADD_DEF_TASK( TASK_WEAPON_CREATE ); - ADD_DEF_TASK( TASK_ITEM_RUN_PATH ); - ADD_DEF_TASK( TASK_ITEM_PICKUP ); - ADD_DEF_TASK( TASK_USE_SMALL_HULL ); - ADD_DEF_TASK( TASK_FALL_TO_GROUND ); - ADD_DEF_TASK( TASK_WANDER ); - ADD_DEF_TASK( TASK_FREEZE ); - ADD_DEF_TASK( TASK_GATHER_CONDITIONS ); - ADD_DEF_TASK( TASK_IGNORE_OLD_ENEMIES ); - ADD_DEF_TASK( TASK_DEBUG_BREAK ); - ADD_DEF_TASK( TASK_ADD_HEALTH ); - ADD_DEF_TASK( TASK_GET_PATH_TO_INTERACTION_PARTNER ); - ADD_DEF_TASK( TASK_PRE_SCRIPT ); -} - - diff --git a/game/server/ai_task.h b/game/server/ai_task.h deleted file mode 100644 index 8e0fd4acd..000000000 --- a/game/server/ai_task.h +++ /dev/null @@ -1,504 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Defines the tasks for default AI. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_TASK_H -#define AI_TASK_H -#ifdef _WIN32 -#pragma once -#endif - -class CStringRegistry; - -// ---------------------------------------------------------------------- -// Failure messages -// -// UNDONE: do this diffently so when not in developer mode we can -// not use any memory for these text strings -// ---------------------------------------------------------------------- - -// Codes are either one of the enumerated types below, or a string (similar to Windows resource IDs) -typedef int AI_TaskFailureCode_t; - -enum AI_BaseTaskFailureCodes_t -{ - NO_TASK_FAILURE, - FAIL_NO_TARGET, - FAIL_WEAPON_OWNED, - FAIL_ITEM_NO_FIND, - FAIL_NO_HINT_NODE, - FAIL_SCHEDULE_NOT_FOUND, - FAIL_NO_ENEMY, - FAIL_NO_BACKAWAY_NODE, - FAIL_NO_COVER, - FAIL_NO_FLANK, - FAIL_NO_SHOOT, - FAIL_NO_ROUTE, - FAIL_NO_ROUTE_GOAL, - FAIL_NO_ROUTE_BLOCKED, - FAIL_NO_ROUTE_ILLEGAL, - FAIL_NO_WALK, - FAIL_ALREADY_LOCKED, - FAIL_NO_SOUND, - FAIL_NO_SCENT, - FAIL_BAD_ACTIVITY, - FAIL_NO_GOAL, - FAIL_NO_PLAYER, - FAIL_NO_REACHABLE_NODE, - FAIL_NO_AI_NETWORK, - FAIL_BAD_POSITION, - FAIL_BAD_PATH_GOAL, - FAIL_STUCK_ONTOP, - FAIL_ITEM_TAKEN, - - NUM_FAIL_CODES, -}; - -inline bool IsPathTaskFailure( AI_TaskFailureCode_t code ) -{ - return ( code >= FAIL_NO_ROUTE && code <= FAIL_NO_ROUTE_ILLEGAL ); -} - -const char *TaskFailureToString( AI_TaskFailureCode_t code ); -inline int MakeFailCode( const char *pszGeneralError ) { return (int)pszGeneralError; } - - -enum TaskStatus_e -{ - TASKSTATUS_NEW = 0, // Just started - TASKSTATUS_RUN_MOVE_AND_TASK = 1, // Running task & movement - TASKSTATUS_RUN_MOVE = 2, // Just running movement - TASKSTATUS_RUN_TASK = 3, // Just running task - TASKSTATUS_COMPLETE = 4, // Completed, get next task -}; - -// an array of tasks is a task list -// an array of schedules is a schedule list -struct Task_t -{ - int iTask; - float flTaskData; -}; - -//========================================================= -// These are the shared tasks -//========================================================= -enum sharedtasks_e -{ - TASK_INVALID = 0, - - // Forces the activity to reset. - TASK_RESET_ACTIVITY, - - // Waits for the specified number of seconds. - TASK_WAIT, - - // Make announce attack sound - TASK_ANNOUNCE_ATTACK, - - // Waits for the specified number of seconds. Will constantly turn to - // face the enemy while waiting. - TASK_WAIT_FACE_ENEMY, - - // Waits up to the specified number of seconds. Will constantly turn to - // face the enemy while waiting. - TASK_WAIT_FACE_ENEMY_RANDOM, - - // Wait until the player enters the same PVS as this character. - TASK_WAIT_PVS, - - // DON'T use this, it needs to go away. - TASK_SUGGEST_STATE, - - // Set m_hTargetEnt to nearest player - TASK_TARGET_PLAYER, - - // Walk to m_hTargetEnt's location - TASK_SCRIPT_WALK_TO_TARGET, - - // Run to m_hTargetEnt's location - TASK_SCRIPT_RUN_TO_TARGET, - - // Move to m_hTargetEnt's location using the activity specified by m_hCine->m_iszCustomMove. - TASK_SCRIPT_CUSTOM_MOVE_TO_TARGET, - - // Move to within specified range of m_hTargetEnt - TASK_MOVE_TO_TARGET_RANGE, - - // Move to within specified range of our nav goal - TASK_MOVE_TO_GOAL_RANGE, - - // Path that moves the character a few steps forward of where it is. - TASK_MOVE_AWAY_PATH, - - TASK_GET_PATH_AWAY_FROM_BEST_SOUND, - - // Set the implied goal for TASK_GET_PATH_TO_GOAL - TASK_SET_GOAL, - - // Get the path to the goal specified by TASK_SET_GOAL - TASK_GET_PATH_TO_GOAL, - - // Path to the enemy's location. Even if the enemy is unseen! - TASK_GET_PATH_TO_ENEMY, - - // Path to the last place this character saw the enemy - TASK_GET_PATH_TO_ENEMY_LKP, - - // Path to the enemy's location or path to a LOS with the enemy's last known position, depending on range - TASK_GET_CHASE_PATH_TO_ENEMY, - - // Path to a LOS with the enemy's last known position - TASK_GET_PATH_TO_ENEMY_LKP_LOS, - - // Path to the dead enemy's carcass. - TASK_GET_PATH_TO_ENEMY_CORPSE, - - // Path to the player's origin - TASK_GET_PATH_TO_PLAYER, - - // Path to node with line of sight to enemy - TASK_GET_PATH_TO_ENEMY_LOS, - - // Path to node with line of sight to enemy, at least flTaskData units away from m_vSavePosition - TASK_GET_FLANK_RADIUS_PATH_TO_ENEMY_LOS, - - // Path to node with line of sight to enemy, at least flTaskData degrees away from m_vSavePosition from the enemy's POV - TASK_GET_FLANK_ARC_PATH_TO_ENEMY_LOS, - - // Path to the within shot range of last place this character saw the enemy - TASK_GET_PATH_TO_RANGE_ENEMY_LKP_LOS, - - // Build a path to m_hTargetEnt - TASK_GET_PATH_TO_TARGET, - - // Allow a little slop, and allow for some Z offset (like the target is a gun on a table). - TASK_GET_PATH_TO_TARGET_WEAPON, - - TASK_CREATE_PENDING_WEAPON, - - // Path to nodes[ m_pHintNode ] - TASK_GET_PATH_TO_HINTNODE, - - // Store current position for later reference - TASK_STORE_LASTPOSITION, - - // Clear stored position - TASK_CLEAR_LASTPOSITION, - - // Store current position for later reference - TASK_STORE_POSITION_IN_SAVEPOSITION, - - // Store best sound position for later reference - TASK_STORE_BESTSOUND_IN_SAVEPOSITION, - TASK_STORE_BESTSOUND_REACTORIGIN_IN_SAVEPOSITION, - - TASK_REACT_TO_COMBAT_SOUND, - - // Store current enemy position in saveposition - TASK_STORE_ENEMY_POSITION_IN_SAVEPOSITION, - - // Move to the goal specified by the player in command mode. - TASK_GET_PATH_TO_COMMAND_GOAL, - - TASK_MARK_COMMAND_GOAL_POS, - - TASK_CLEAR_COMMAND_GOAL, - - // Path to last position (Last position must be stored with TASK_STORE_LAST_POSITION) - TASK_GET_PATH_TO_LASTPOSITION, - - // Path to saved position (Save position must by set in code or by a task) - TASK_GET_PATH_TO_SAVEPOSITION, - - // Path to location that has line of sight to saved position (Save position must by set in code or by a task) - TASK_GET_PATH_TO_SAVEPOSITION_LOS, - - // Path to random node - TASK_GET_PATH_TO_RANDOM_NODE, - - // Path to source of loudest heard sound that I care about - TASK_GET_PATH_TO_BESTSOUND, - - // Path to source of the strongest scend that I care about - TASK_GET_PATH_TO_BESTSCENT, - - // Run the current path - TASK_RUN_PATH, - - // Walk the current path - TASK_WALK_PATH, - - // Walk the current path for a specified number of seconds - TASK_WALK_PATH_TIMED, - - // Walk the current path until you are x units from the goal. - TASK_WALK_PATH_WITHIN_DIST, - - // Walk the current path until for x units - TASK_WALK_PATH_FOR_UNITS, - - // Rung the current path until you are x units from the goal. - TASK_RUN_PATH_FLEE, - - // Run the current path for a specified number of seconds - TASK_RUN_PATH_TIMED, - - // Run the current path until for x units - TASK_RUN_PATH_FOR_UNITS, - - // Run the current path until you are x units from the goal. - TASK_RUN_PATH_WITHIN_DIST, - - // Walk the current path sideways (must be supported by animation) - TASK_STRAFE_PATH, - - // Clear m_flMoveWaitFinished (timer that inhibits movement) - TASK_CLEAR_MOVE_WAIT, - - // Decide on the appropriate small flinch animation, and play it. - TASK_SMALL_FLINCH, - - // Decide on the appropriate big flinch animation, and play it. - TASK_BIG_FLINCH, - - // Prevent dodging for a certain amount of time. - TASK_DEFER_DODGE, - - // Turn to face ideal yaw - TASK_FACE_IDEAL, - - // Find an interesting direction to face. Don't face into walls, corners if you can help it. - TASK_FACE_REASONABLE, - - // Turn to face the way I should walk or run - TASK_FACE_PATH, - - // Turn to face a player - TASK_FACE_PLAYER, - - // Turn to face the enemy - TASK_FACE_ENEMY, - - // Turn to face nodes[ m_pHintNode ] - TASK_FACE_HINTNODE, - - // Play activity associate with the current hint - TASK_PLAY_HINT_ACTIVITY, - - // Turn to face m_hTargetEnt - TASK_FACE_TARGET, - - // Turn to face stored last position (last position must be stored first!) - TASK_FACE_LASTPOSITION, - - // Turn to face stored save position (save position must be stored first!) - TASK_FACE_SAVEPOSITION, - - // Turn to face directly away from stored save position (save position must be stored first!) - TASK_FACE_AWAY_FROM_SAVEPOSITION, - - // Set the current facing to be the ideal - TASK_SET_IDEAL_YAW_TO_CURRENT, - - // Attack the enemy (should be facing the enemy) - TASK_RANGE_ATTACK1, - TASK_RANGE_ATTACK2, - TASK_MELEE_ATTACK1, - TASK_MELEE_ATTACK2, - - // Reload weapon - TASK_RELOAD, - - // Execute special attack (user-defined) - TASK_SPECIAL_ATTACK1, - TASK_SPECIAL_ATTACK2, - - TASK_FIND_HINTNODE, - TASK_FIND_LOCK_HINTNODE, - - TASK_CLEAR_HINTNODE, - - // Claim m_pHintNode exclusively for this NPC. - TASK_LOCK_HINTNODE, - - // Emit an angry sound - TASK_SOUND_ANGRY, - - // Emit a dying sound - TASK_SOUND_DEATH, - - // Emit an idle sound - TASK_SOUND_IDLE, - - // Emit a sound because you are pissed off because you just saw someone you don't like - TASK_SOUND_WAKE, - - // Emit a pain sound - TASK_SOUND_PAIN, - - // Emit a death sound - TASK_SOUND_DIE, - - // Speak a sentence - TASK_SPEAK_SENTENCE, - - // Wait for the current sentence I'm speaking to finish - TASK_WAIT_FOR_SPEAK_FINISH, - - // Set current animation activity to the specified activity - TASK_SET_ACTIVITY, - - // Adjust the framerate to plus/minus N% - TASK_RANDOMIZE_FRAMERATE, - - // Immediately change to a schedule of the specified type - TASK_SET_SCHEDULE, - - // Set the specified schedule to execute if the current schedule fails. - TASK_SET_FAIL_SCHEDULE, - - // How close to route goal do I need to get - TASK_SET_TOLERANCE_DISTANCE, - - // How many seconds should I spend search for a route - TASK_SET_ROUTE_SEARCH_TIME, - - // Return to use of default fail schedule - TASK_CLEAR_FAIL_SCHEDULE, - - // Play the specified animation sequence before continuing - TASK_PLAY_SEQUENCE, - - // Play the specified private animation sequence before continuing - TASK_PLAY_PRIVATE_SEQUENCE, - - // Turn to face the enemy while playing specified animation sequence - TASK_PLAY_PRIVATE_SEQUENCE_FACE_ENEMY, - TASK_PLAY_SEQUENCE_FACE_ENEMY, - TASK_PLAY_SEQUENCE_FACE_TARGET, - - // tries lateral cover first, then node cover - TASK_FIND_COVER_FROM_BEST_SOUND, - - // tries lateral cover first, then node cover - TASK_FIND_COVER_FROM_ENEMY, - - // Find a place to hide from the enemy, somewhere on either side of me - TASK_FIND_LATERAL_COVER_FROM_ENEMY, - - // Find a place further from the saved position - TASK_FIND_BACKAWAY_FROM_SAVEPOSITION, - - // Fine a place to hide from the enemy, anywhere. Use the node system. - TASK_FIND_NODE_COVER_FROM_ENEMY, - - // Find a place to hide from the enemy that's within the specified distance - TASK_FIND_NEAR_NODE_COVER_FROM_ENEMY, - - // data for this one is there MINIMUM aceptable distance to the cover. - TASK_FIND_FAR_NODE_COVER_FROM_ENEMY, - - // Find a place to go that can't see to where I am now. - TASK_FIND_COVER_FROM_ORIGIN, - - // Unhook from the AI system. - TASK_DIE, - - // Wait until scripted sequence plays - TASK_WAIT_FOR_SCRIPT, - - // Play scripted sequence animation - TASK_PUSH_SCRIPT_ARRIVAL_ACTIVITY, - TASK_PLAY_SCRIPT, - TASK_PLAY_SCRIPT_POST_IDLE, - TASK_ENABLE_SCRIPT, - TASK_PLANT_ON_SCRIPT, - TASK_FACE_SCRIPT, - - // Wait for scene to complete - TASK_PLAY_SCENE, - - // Wait for 0 to specified number of seconds - TASK_WAIT_RANDOM, - - // Wait forever (until this schedule is interrupted) - TASK_WAIT_INDEFINITE, - - TASK_STOP_MOVING, - - // Turn left the specified number of degrees - TASK_TURN_LEFT, - - // Turn right the specified number of degrees - TASK_TURN_RIGHT, - - // Remember the specified piece of data - TASK_REMEMBER, - - // Forget the specified piece of data - TASK_FORGET, - - // Wait until current movement is complete. - TASK_WAIT_FOR_MOVEMENT, - - // Wait until a single-step movement is complete. - TASK_WAIT_FOR_MOVEMENT_STEP, - - // Wait until I can't hear any danger sound. - TASK_WAIT_UNTIL_NO_DANGER_SOUND, - - // Pick up new weapons: - TASK_WEAPON_FIND, - TASK_WEAPON_PICKUP, - TASK_WEAPON_RUN_PATH, // run to weapon but break if someone else picks it up - TASK_WEAPON_CREATE, - - TASK_ITEM_PICKUP, - TASK_ITEM_RUN_PATH, - - // Use small hull for tight navigation - TASK_USE_SMALL_HULL, - - // wait until you are on ground - TASK_FALL_TO_GROUND, - - // Wander for a specfied amound of time - TASK_WANDER, - - TASK_FREEZE, - - // regather conditions at the start of a schedule (all conditions are cleared between schedules) - TASK_GATHER_CONDITIONS, - - // Require an enemy be seen after the task is run to be considered a candidate enemy - TASK_IGNORE_OLD_ENEMIES, - - TASK_DEBUG_BREAK, - - // Add a specified amount of health to this NPC - TASK_ADD_HEALTH, - - // Add a gesture layer and wait until it's finished - TASK_ADD_GESTURE_WAIT, - - // Add a gesture layer - TASK_ADD_GESTURE, - - // Get a path to my forced interaction partner - TASK_GET_PATH_TO_INTERACTION_PARTNER, - - // First task of all schedules for playing back scripted sequences - TASK_PRE_SCRIPT, - - // ====================================== - // IMPORTANT: This must be the last enum - // ====================================== - LAST_SHARED_TASK - -}; - -#endif // AI_TASK_H diff --git a/game/server/ai_trackpather.cpp b/game/server/ai_trackpather.cpp deleted file mode 100644 index c6f9567ce..000000000 --- a/game/server/ai_trackpather.cpp +++ /dev/null @@ -1,1696 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" - -#include "trains.h" -#include "ai_trackpather.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define TRACKPATHER_DEBUG_LEADING 1 -#define TRACKPATHER_DEBUG_PATH 2 -#define TRACKPATHER_DEBUG_TRACKS 3 -ConVar g_debug_trackpather( "g_debug_trackpather", "0", FCVAR_CHEAT ); - -//------------------------------------------------------------------------------ - -BEGIN_DATADESC( CAI_TrackPather ) - DEFINE_FIELD( m_vecDesiredPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecGoalOrientation, FIELD_VECTOR ), - - DEFINE_FIELD( m_pCurrentPathTarget, FIELD_CLASSPTR ), - DEFINE_FIELD( m_pDestPathTarget, FIELD_CLASSPTR ), - DEFINE_FIELD( m_pLastPathTarget, FIELD_CLASSPTR ), - DEFINE_FIELD( m_pTargetNearestPath, FIELD_CLASSPTR ), - - DEFINE_FIELD( m_strCurrentPathName, FIELD_STRING ), - DEFINE_FIELD( m_strDestPathName, FIELD_STRING ), - DEFINE_FIELD( m_strLastPathName, FIELD_STRING ), - DEFINE_FIELD( m_strTargetNearestPathName, FIELD_STRING ), - - DEFINE_FIELD( m_vecLastGoalCheckPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_flEnemyPathUpdateTime, FIELD_TIME ), - DEFINE_FIELD( m_bForcedMove, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bPatrolling, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bPatrolBreakable, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bLeading, FIELD_BOOLEAN ), - - // Derived class pathing data - DEFINE_FIELD( m_flTargetDistanceThreshold, FIELD_FLOAT ), - DEFINE_FIELD( m_flAvoidDistance, FIELD_FLOAT ), - - DEFINE_FIELD( m_flTargetTolerance, FIELD_FLOAT ), - DEFINE_FIELD( m_vecSegmentStartPoint, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecSegmentStartSplinePoint, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_bMovingForward, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bChooseFarthestPoint, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flFarthestPathDist, FIELD_FLOAT ), - DEFINE_FIELD( m_flPathMaxSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_flTargetDistFromPath, FIELD_FLOAT ), - DEFINE_FIELD( m_flLeadDistance, FIELD_FLOAT ), - DEFINE_FIELD( m_vecTargetPathDir, FIELD_VECTOR ), - DEFINE_FIELD( m_vecTargetPathPoint, FIELD_POSITION_VECTOR ), - - DEFINE_FIELD( m_nPauseState, FIELD_INTEGER ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_STRING, "SetTrack", InputSetTrack ), - DEFINE_INPUTFUNC( FIELD_STRING, "FlyToSpecificTrackViaPath", InputFlyToPathTrack ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartPatrol", InputStartPatrol ), - DEFINE_INPUTFUNC( FIELD_VOID, "StopPatrol", InputStopPatrol ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartBreakableMovement", InputStartBreakableMovement ), - DEFINE_INPUTFUNC( FIELD_VOID, "StopBreakableMovement", InputStopBreakableMovement ), - DEFINE_INPUTFUNC( FIELD_VOID, "ChooseFarthestPathPoint", InputChooseFarthestPathPoint ), - DEFINE_INPUTFUNC( FIELD_VOID, "ChooseNearestPathPoint", InputChooseNearestPathPoint ), - DEFINE_INPUTFUNC( FIELD_INTEGER,"InputStartLeading", InputStartLeading ), - DEFINE_INPUTFUNC( FIELD_VOID, "InputStopLeading", InputStopLeading ), - - // Obsolete, for backwards compatibility - DEFINE_INPUTFUNC( FIELD_VOID, "StartPatrolBreakable", InputStartPatrolBreakable ), - DEFINE_INPUTFUNC( FIELD_STRING, "FlyToPathTrack", InputFlyToPathTrack ), -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: Initialize pathing data -//----------------------------------------------------------------------------- -void CAI_TrackPather::InitPathingData( float flTrackArrivalTolerance, float flTargetDistance, float flAvoidDistance ) -{ - m_flTargetTolerance = flTrackArrivalTolerance; - m_flTargetDistanceThreshold = flTargetDistance; - m_flAvoidDistance = flAvoidDistance; - - m_pCurrentPathTarget = NULL; - m_pDestPathTarget = NULL; - m_pLastPathTarget = NULL; - m_pTargetNearestPath = NULL; - m_bLeading = false; - - m_flEnemyPathUpdateTime = gpGlobals->curtime; - m_bForcedMove = false; - m_bPatrolling = false; - m_bPatrolBreakable = false; - m_flLeadDistance = 0.0f; - m_bMovingForward = true; - m_vecSegmentStartPoint = m_vecSegmentStartSplinePoint = m_vecDesiredPosition = GetAbsOrigin(); - m_bChooseFarthestPoint = true; - m_flFarthestPathDist = 1e10; - m_flPathMaxSpeed = 0; - m_nPauseState = PAUSE_NO_PAUSE; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_TrackPather::OnRestore( void ) -{ - BaseClass::OnRestore(); - - // Restore current path - if ( m_strCurrentPathName != NULL_STRING ) - { - m_pCurrentPathTarget = (CPathTrack *) gEntList.FindEntityByName( NULL, m_strCurrentPathName ); - } - else - { - m_pCurrentPathTarget = NULL; - } - - // Restore destination path - if ( m_strDestPathName != NULL_STRING ) - { - m_pDestPathTarget = (CPathTrack *) gEntList.FindEntityByName( NULL, m_strDestPathName ); - } - else - { - m_pDestPathTarget = NULL; - } - - // Restore last path - if ( m_strLastPathName != NULL_STRING ) - { - m_pLastPathTarget = (CPathTrack *) gEntList.FindEntityByName( NULL, m_strLastPathName ); - } - else - { - m_pLastPathTarget = NULL; - } - - // Restore target nearest path - if ( m_strTargetNearestPathName != NULL_STRING ) - { - m_pTargetNearestPath = (CPathTrack *) gEntList.FindEntityByName( NULL, m_strTargetNearestPathName ); - } - else - { - m_pTargetNearestPath = NULL; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_TrackPather::OnSave( IEntitySaveUtils *pUtils ) -{ - BaseClass::OnSave( pUtils ); - - // Stash all the paths into strings for restoration later - m_strCurrentPathName = ( m_pCurrentPathTarget != NULL ) ? m_pCurrentPathTarget->GetEntityName() : NULL_STRING; - m_strDestPathName = ( m_pDestPathTarget != NULL ) ? m_pDestPathTarget->GetEntityName() : NULL_STRING; - m_strLastPathName = ( m_pLastPathTarget != NULL ) ? m_pLastPathTarget->GetEntityName() : NULL_STRING; - m_strTargetNearestPathName = ( m_pTargetNearestPath != NULL ) ? m_pTargetNearestPath->GetEntityName() : NULL_STRING; -} - - -//----------------------------------------------------------------------------- -// Leading distance -//----------------------------------------------------------------------------- -void CAI_TrackPather::EnableLeading( bool bEnable ) -{ - bool bWasLeading = m_bLeading; - m_bLeading = bEnable; - if ( m_bLeading ) - { - m_bPatrolling = false; - } - else if ( bWasLeading ) - { - - // Going from leading to not leading. Refresh the desired position - // to prevent us from hovering around our old, no longer valid lead position. - if ( m_pCurrentPathTarget ) - { - SetDesiredPosition( m_pCurrentPathTarget->GetAbsOrigin() ); - } - } -} - -void CAI_TrackPather::SetLeadingDistance( float flLeadDistance ) -{ - m_flLeadDistance = flLeadDistance; -} - -float CAI_TrackPather::GetLeadingDistance( ) const -{ - return m_flLeadDistance; -} - - -//----------------------------------------------------------------------------- -// Returns the next path along our current path -//----------------------------------------------------------------------------- -inline CPathTrack *CAI_TrackPather::NextAlongCurrentPath( CPathTrack *pPath ) const -{ - return CPathTrack::ValidPath( m_bMovingForward ? pPath->GetNext() : pPath->GetPrevious() ); -} - -inline CPathTrack *CAI_TrackPather::PreviousAlongCurrentPath( CPathTrack *pPath ) const -{ - return CPathTrack::ValidPath( m_bMovingForward ? pPath->GetPrevious() : pPath->GetNext() ); -} - -inline CPathTrack *CAI_TrackPather::AdjustForMovementDirection( CPathTrack *pPath ) const -{ - if ( !m_bMovingForward && CPathTrack::ValidPath( pPath->GetPrevious( ) ) ) - { - pPath = CPathTrack::ValidPath( pPath->GetPrevious() ); - } - return pPath; -} - - -//----------------------------------------------------------------------------- -// Enemy visibility check -//----------------------------------------------------------------------------- -CBaseEntity *CAI_TrackPather::FindTrackBlocker( const Vector &vecViewPoint, const Vector &vecTargetPos ) -{ - trace_t tr; - AI_TraceHull( vecViewPoint, vecTargetPos, -Vector(4,4,4), Vector(4,4,4), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - return (tr.fraction != 1.0f) ? tr.m_pEnt : NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &targetPos - -// Output : CBaseEntity -//----------------------------------------------------------------------------- -CPathTrack *CAI_TrackPather::BestPointOnPath( CPathTrack *pPath, const Vector &targetPos, float flAvoidRadius, bool visible, bool bFarthestPoint ) -{ - // Find the node nearest to the destination path target if a path is not specified - if ( pPath == NULL ) - { - pPath = m_pDestPathTarget; - } - - // If the path node we're trying to use is not valid, then we're done. - if ( CPathTrack::ValidPath( pPath ) == NULL ) - { - //FIXME: Implement - Assert(0); - return NULL; - } - - // Our target may be in a vehicle - CBaseEntity *pVehicle = NULL; - CBaseEntity *pTargetEnt = GetTrackPatherTargetEnt(); - if ( pTargetEnt != NULL ) - { - CBaseCombatCharacter *pCCTarget = pTargetEnt->MyCombatCharacterPointer(); - if ( pCCTarget != NULL && pCCTarget->IsInAVehicle() ) - { - pVehicle = pCCTarget->GetVehicleEntity(); - } - } - - // Faster math... - flAvoidRadius *= flAvoidRadius; - - // Find the nearest node to the target (going forward) - CPathTrack *pNearestPath = NULL; - float flNearestDist = bFarthestPoint ? 0 : 999999999; - float flPathDist; - - float flFarthestDistSqr = ( m_flFarthestPathDist - 2.0f * m_flTargetDistanceThreshold ); - flFarthestDistSqr *= flFarthestDistSqr; - - // NOTE: Gotta do it this crazy way because paths can be one-way. - for ( int i = 0; i < 2; ++i ) - { - int loopCheck = 0; - CPathTrack *pTravPath = pPath; - CPathTrack *pNextPath; - - BEGIN_PATH_TRACK_ITERATION(); - for ( ; CPathTrack::ValidPath( pTravPath ); pTravPath = pNextPath, loopCheck++ ) - { - // Circular loop checking - if ( pTravPath->HasBeenVisited() ) - break; - - pTravPath->Visit(); - - pNextPath = (i == 0) ? pTravPath->GetPrevious() : pTravPath->GetNext(); - - // Find the distance between this test point and our goal point - flPathDist = ( pTravPath->GetAbsOrigin() - targetPos ).LengthSqr(); - - // See if it's closer and it's also not within our avoidance radius - if ( bFarthestPoint ) - { - if ( ( flPathDist <= flNearestDist ) && ( flNearestDist <= flFarthestDistSqr ) ) - continue; - } - else - { - if ( flPathDist >= flNearestDist ) - continue; - } - - // Don't choose points that are within the avoid radius - if ( flAvoidRadius && ( pTravPath->GetAbsOrigin() - targetPos ).Length2DSqr() <= flAvoidRadius ) - continue; - - if ( visible ) - { - // If it has to be visible, run those checks - CBaseEntity *pBlocker = FindTrackBlocker( pTravPath->GetAbsOrigin(), targetPos ); - - // Check to see if we've hit the target, or the player's vehicle if it's a player in a vehicle - bool bHitTarget = ( pTargetEnt && ( pTargetEnt == pBlocker ) ) || - ( pVehicle && ( pVehicle == pBlocker ) ); - - // If we hit something, and it wasn't the target or his vehicle, then no dice - // If we hit the target and forced move was set, *still* no dice - if ( (pBlocker != NULL) && ( !bHitTarget || m_bForcedMove ) ) - continue; - } - - pNearestPath = pTravPath; - flNearestDist = flPathDist; - } - } - - return pNearestPath; -} - - -//----------------------------------------------------------------------------- -// Compute a point n units along a path -//----------------------------------------------------------------------------- -CPathTrack *CAI_TrackPather::ComputeLeadingPointAlongPath( const Vector &vecStartPoint, - CPathTrack *pFirstTrack, float flDistance, Vector *pTarget ) -{ - bool bMovingForward = (flDistance > 0.0f); - flDistance = fabs(flDistance); - - CPathTrack *pTravPath = pFirstTrack; - if ( (!bMovingForward) && pFirstTrack->GetPrevious() ) - { - pTravPath = pFirstTrack->GetPrevious(); - } - - *pTarget = vecStartPoint; - CPathTrack *pNextPath; - - // No circular loop checking needed; eventually, it'll run out of distance - for ( ; CPathTrack::ValidPath( pTravPath ); pTravPath = pNextPath ) - { - pNextPath = bMovingForward ? pTravPath->GetNext() : pTravPath->GetPrevious(); - - // Find the distance between this test point and our goal point - float flPathDist = pTarget->DistTo( pTravPath->GetAbsOrigin() ); - - // Find the distance between this test point and our goal point - if ( flPathDist <= flDistance ) - { - flDistance -= flPathDist; - *pTarget = pTravPath->GetAbsOrigin(); - if ( !CPathTrack::ValidPath(pNextPath) ) - return bMovingForward ? pTravPath : pTravPath->GetNext(); - - continue; - } - - ComputeClosestPoint( *pTarget, flDistance, pTravPath->GetAbsOrigin(), pTarget ); - return bMovingForward ? pTravPath : pTravPath->GetNext(); - } - - return NULL; -} - - -//----------------------------------------------------------------------------- -// Compute the distance to a particular point on the path -//----------------------------------------------------------------------------- -float CAI_TrackPather::ComputeDistanceAlongPathToPoint( CPathTrack *pStartTrack, - CPathTrack *pDestTrack, const Vector &vecDestPosition, bool bMovingForward ) -{ - float flTotalDist = 0.0f; - - Vector vecPoint; - ClosestPointToCurrentPath( &vecPoint ); - - CPathTrack *pTravPath = pStartTrack; - CPathTrack *pNextPath, *pTestPath; - BEGIN_PATH_TRACK_ITERATION(); - for ( ; CPathTrack::ValidPath( pTravPath ); pTravPath = pNextPath ) - { - // Circular loop checking - if ( pTravPath->HasBeenVisited() ) - break; - - // Mark it as being visited. - pTravPath->Visit(); - - pNextPath = bMovingForward ? pTravPath->GetNext() : pTravPath->GetPrevious(); - pTestPath = pTravPath; - Assert( pTestPath ); - - if ( pTravPath == pDestTrack ) - { - Vector vecDelta; - Vector vecPathDelta; - VectorSubtract( vecDestPosition, vecPoint, vecDelta ); - ComputePathDirection( pTravPath, &vecPathDelta ); - float flDot = DotProduct( vecDelta, vecPathDelta ); - flTotalDist += (flDot > 0.0f ? 1.0f : -1.0f) * vecDelta.Length2D(); - break; - } - - // NOTE: This would be made more accurate if we did the path direction check here too. - // The starting vecPoint is sometimes *not* within the bounds of the line segment. - - // Find the distance between this test point and our goal point - flTotalDist += (bMovingForward ? 1.0f : -1.0f) * vecPoint.AsVector2D().DistTo( pTestPath->GetAbsOrigin().AsVector2D() ); - vecPoint = pTestPath->GetAbsOrigin(); - } - - return flTotalDist; -} - - -//------------------------------------------------------------------------------ -// Track debugging info -//------------------------------------------------------------------------------ -void CAI_TrackPather::VisualizeDebugInfo( const Vector &vecNearestPoint, const Vector &vecTarget ) -{ - if ( g_debug_trackpather.GetInt() == TRACKPATHER_DEBUG_PATH ) - { - NDebugOverlay::Line( m_vecSegmentStartPoint, vecTarget, 0, 0, 255, true, 0.1f ); - NDebugOverlay::Cross3D( vecNearestPoint, -Vector(16,16,16), Vector(16,16,16), 255, 0, 0, true, 0.1f ); - NDebugOverlay::Cross3D( m_pCurrentPathTarget->GetAbsOrigin(), -Vector(16,16,16), Vector(16,16,16), 0, 255, 0, true, 0.1f ); - NDebugOverlay::Cross3D( m_vecDesiredPosition, -Vector(16,16,16), Vector(16,16,16), 0, 0, 255, true, 0.1f ); - NDebugOverlay::Cross3D( m_pDestPathTarget->GetAbsOrigin(), -Vector(16,16,16), Vector(16,16,16), 255, 255, 255, true, 0.1f ); - - if ( m_pTargetNearestPath ) - { - NDebugOverlay::Cross3D( m_pTargetNearestPath->GetAbsOrigin(), -Vector(24,24,24), Vector(24,24,24), 255, 0, 255, true, 0.1f ); - } - } - - if ( g_debug_trackpather.GetInt() == TRACKPATHER_DEBUG_TRACKS ) - { - if ( m_pCurrentPathTarget ) - { - CPathTrack *pPathTrack = m_pCurrentPathTarget; - for ( ; CPathTrack::ValidPath( pPathTrack ); pPathTrack = pPathTrack->GetNext() ) - { - NDebugOverlay::Box( pPathTrack->GetAbsOrigin(), -Vector(2,2,2), Vector(2,2,2), 0,255, 0, 8, 0.1 ); - if ( CPathTrack::ValidPath( pPathTrack->GetNext() ) ) - { - NDebugOverlay::Line( pPathTrack->GetAbsOrigin(), pPathTrack->GetNext()->GetAbsOrigin(), 0,255,0, true, 0.1 ); - } - - if ( pPathTrack->GetNext() == m_pCurrentPathTarget ) - break; - } - } - } -} - - -//------------------------------------------------------------------------------ -// Does this path track have LOS to the target? -//------------------------------------------------------------------------------ -bool CAI_TrackPather::HasLOSToTarget( CPathTrack *pTrack ) -{ - CBaseEntity *pTargetEnt = GetTrackPatherTargetEnt(); - if ( !pTargetEnt ) - return true; - - Vector targetPos; - if ( !GetTrackPatherTarget( &targetPos ) ) - return true; - - // Translate driver into vehicle for testing - CBaseEntity *pVehicle = NULL; - CBaseCombatCharacter *pCCTarget = pTargetEnt->MyCombatCharacterPointer(); - if ( pCCTarget != NULL && pCCTarget->IsInAVehicle() ) - { - pVehicle = pCCTarget->GetVehicleEntity(); - } - - // If it has to be visible, run those checks - CBaseEntity *pBlocker = FindTrackBlocker( pTrack->GetAbsOrigin(), targetPos ); - - // Check to see if we've hit the target, or the player's vehicle if it's a player in a vehicle - bool bHitTarget = ( pTargetEnt && ( pTargetEnt == pBlocker ) ) || - ( pVehicle && ( pVehicle == pBlocker ) ); - - return (pBlocker == NULL) || bHitTarget; -} - - -//------------------------------------------------------------------------------ -// Moves to the track -//------------------------------------------------------------------------------ -void CAI_TrackPather::UpdateCurrentTarget() -{ - // Find the point along the line that we're closest to. - const Vector &vecTarget = m_pCurrentPathTarget->GetAbsOrigin(); - Vector vecPoint; - float t = ClosestPointToCurrentPath( &vecPoint ); - if ( (t < 1.0f) && ( vecPoint.DistToSqr( vecTarget ) > m_flTargetTolerance * m_flTargetTolerance ) ) - goto visualizeDebugInfo; - - // Forced move is gone as soon as we've reached the first point on our path - if ( m_bLeading ) - { - m_bForcedMove = false; - } - - // Trip our "path_track reached" output - if ( m_pCurrentPathTarget != m_pLastPathTarget ) - { - // Get the path's specified max speed - m_flPathMaxSpeed = m_pCurrentPathTarget->m_flSpeed; - - variant_t emptyVariant; - m_pCurrentPathTarget->AcceptInput( "InPass", this, this, emptyVariant, 0 ); - m_pLastPathTarget = m_pCurrentPathTarget; - } - - if ( m_nPauseState == PAUSED_AT_POSITION ) - return; - - if ( m_nPauseState == PAUSE_AT_NEXT_LOS_POSITION ) - { - if ( HasLOSToTarget(m_pCurrentPathTarget) ) - { - m_nPauseState = PAUSED_AT_POSITION; - return; - } - } - - // Update our dest path target, if appropriate... - if ( m_pCurrentPathTarget == m_pDestPathTarget ) - { - m_bForcedMove = false; - SelectNewDestTarget(); - } - - // Did SelectNewDestTarget give us a new point to move to? - if ( m_pCurrentPathTarget != m_pDestPathTarget ) - { - // Update to the next path, if there is one... - m_pCurrentPathTarget = NextAlongCurrentPath( m_pCurrentPathTarget ); - if ( !m_pCurrentPathTarget ) - { - m_pCurrentPathTarget = m_pLastPathTarget; - } - } - else - { - // We're at rest (no patrolling behavior), which means we're moving forward now. - m_bMovingForward = true; - } - - SetDesiredPosition( m_pCurrentPathTarget->GetAbsOrigin() ); - m_vecSegmentStartSplinePoint = m_vecSegmentStartPoint; - m_vecSegmentStartPoint = m_pLastPathTarget->GetAbsOrigin(); - -visualizeDebugInfo: - VisualizeDebugInfo( vecPoint, vecTarget ); -} - - -//----------------------------------------------------------------------------- -// -// NOTE: All code below is used exclusively for leading/trailing behavior -// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// Compute the distance to the leading position -//----------------------------------------------------------------------------- -float CAI_TrackPather::ComputeDistanceToLeadingPosition() -{ - return ComputeDistanceAlongPathToPoint( m_pCurrentPathTarget, m_pDestPathTarget, GetDesiredPosition(), m_bMovingForward ); -} - - -//----------------------------------------------------------------------------- -// Compute the distance to the *target* position -//----------------------------------------------------------------------------- -float CAI_TrackPather::ComputeDistanceToTargetPosition() -{ - Assert( m_pTargetNearestPath ); - - CPathTrack *pDest = m_bMovingForward ? m_pTargetNearestPath.Get() : m_pTargetNearestPath->GetPrevious(); - if ( !pDest ) - { - pDest = m_pTargetNearestPath; - } - bool bMovingForward = IsForwardAlongPath( m_pCurrentPathTarget, pDest ); - - CPathTrack *pStart = m_pCurrentPathTarget; - if ( bMovingForward != m_bMovingForward ) - { - if (bMovingForward) - { - if ( pStart->GetNext() ) - { - pStart = pStart->GetNext(); - } - if ( pDest->GetNext() ) - { - pDest = pDest->GetNext(); - } - } - else - { - if ( pStart->GetPrevious() ) - { - pStart = pStart->GetPrevious(); - } - if ( pDest->GetPrevious() ) - { - pDest = pDest->GetPrevious(); - } - } - } - - return ComputeDistanceAlongPathToPoint( pStart, pDest, m_vecTargetPathPoint, bMovingForward ); -} - - -//----------------------------------------------------------------------------- -// Compute a path direction -//----------------------------------------------------------------------------- -void CAI_TrackPather::ComputePathDirection( CPathTrack *pPath, Vector *pVecPathDir ) -{ - if ( pPath->GetPrevious() ) - { - VectorSubtract( pPath->GetAbsOrigin(), pPath->GetPrevious()->GetAbsOrigin(), *pVecPathDir ); - } - else - { - if ( pPath->GetNext() ) - { - VectorSubtract( pPath->GetNext()->GetAbsOrigin(), pPath->GetAbsOrigin(), *pVecPathDir ); - } - else - { - pVecPathDir->Init( 1, 0, 0 ); - } - } - VectorNormalize( *pVecPathDir ); -} - - -//----------------------------------------------------------------------------- -// What's the current path direction? -//----------------------------------------------------------------------------- -void CAI_TrackPather::CurrentPathDirection( Vector *pVecPathDir ) -{ - if ( m_pCurrentPathTarget ) - { - ComputePathDirection( m_pCurrentPathTarget, pVecPathDir ); - } - else - { - pVecPathDir->Init( 0, 0, 1 ); - } -} - - - -//----------------------------------------------------------------------------- -// Compute a point n units along the current path from our current position -// (but don't pass the desired target point) -//----------------------------------------------------------------------------- -void CAI_TrackPather::ComputePointAlongCurrentPath( float flDistance, float flPerpDist, Vector *pTarget ) -{ - Vector vecPathDir; - Vector vecStartPoint; - ClosestPointToCurrentPath( &vecStartPoint ); - *pTarget = vecStartPoint; - - if ( flDistance != 0.0f ) - { - Vector vecPrevPoint = vecStartPoint; - CPathTrack *pTravPath = m_pCurrentPathTarget; - CPathTrack *pAdjustedDest = AdjustForMovementDirection( m_pDestPathTarget ); - for ( ; CPathTrack::ValidPath( pTravPath ); pTravPath = NextAlongCurrentPath( pTravPath ) ) - { - if ( pTravPath == pAdjustedDest ) - { - ComputePathDirection( pTravPath, &vecPathDir ); - - float flPathDist = pTarget->DistTo( GetDesiredPosition() ); - if ( flDistance > flPathDist ) - { - *pTarget = GetDesiredPosition(); - } - else - { - ComputeClosestPoint( *pTarget, flDistance, GetDesiredPosition(), pTarget ); - } - break; - } - - // Find the distance between this test point and our goal point - float flPathDist = pTarget->DistTo( pTravPath->GetAbsOrigin() ); - - // Find the distance between this test point and our goal point - if ( flPathDist <= flDistance ) - { - flDistance -= flPathDist; - *pTarget = pTravPath->GetAbsOrigin(); - - // FIXME: Reduce the distance further based on the angle between this segment + the next - continue; - } - - ComputePathDirection( pTravPath, &vecPathDir ); - ComputeClosestPoint( *pTarget, flDistance, pTravPath->GetAbsOrigin(), pTarget ); - break; - } - } - else - { - VectorSubtract( m_pCurrentPathTarget->GetAbsOrigin(), m_vecSegmentStartPoint, vecPathDir ); - VectorNormalize( vecPathDir ); - } - - // Add in the horizontal component - ComputePointFromPerpDistance( *pTarget, vecPathDir, flPerpDist, pTarget ); -} - - -//----------------------------------------------------------------------------- -// Methods to find a signed perp distance from the track -// and to compute a point off the path based on the signed perp distance -//----------------------------------------------------------------------------- -float CAI_TrackPather::ComputePerpDistanceFromPath( const Vector &vecPointOnPath, const Vector &vecPathDir, const Vector &vecPointOffPath ) -{ - // Make it be a signed distance of the target from the path - // Positive means on the right side, negative means on the left side - Vector vecAcross, vecDelta; - CrossProduct( vecPathDir, Vector( 0, 0, 1 ), vecAcross ); - VectorSubtract( vecPointOffPath, vecPointOnPath, vecDelta ); - VectorMA( vecDelta, -DotProduct( vecPathDir, vecDelta ), vecPathDir, vecDelta ); - - float flDistanceFromPath = vecDelta.Length2D(); - if ( DotProduct2D( vecAcross.AsVector2D(), vecDelta.AsVector2D() ) < 0.0f ) - { - flDistanceFromPath *= -1.0f; - } - - return flDistanceFromPath; -} - -void CAI_TrackPather::ComputePointFromPerpDistance( const Vector &vecPointOnPath, const Vector &vecPathDir, float flPerpDist, Vector *pResult ) -{ - Vector vecAcross; - CrossProduct( vecPathDir, Vector( 0, 0, 1 ), vecAcross ); - VectorMA( vecPointOnPath, flPerpDist, vecAcross, *pResult ); -} - - -//----------------------------------------------------------------------------- -// Finds the closest point on the path, returns a signed perpendicular distance -// where negative means on the left side of the path (when travelled from prev to next) -// and positive means on the right side -//----------------------------------------------------------------------------- -CPathTrack *CAI_TrackPather::FindClosestPointOnPath( CPathTrack *pPath, - const Vector &targetPos, Vector *pVecClosestPoint, Vector *pVecPathDir, float *pDistanceFromPath ) -{ - // Find the node nearest to the destination path target if a path is not specified - if ( pPath == NULL ) - { - pPath = m_pDestPathTarget; - } - - // If the path node we're trying to use is not valid, then we're done. - if ( CPathTrack::ValidPath( pPath ) == NULL ) - { - //FIXME: Implement - Assert(0); - return NULL; - } - - // Find the nearest node to the target (going forward) - CPathTrack *pNearestPath = NULL; - float flNearestDist2D = 999999999; - float flNearestDist = 999999999; - float flPathDist, flPathDist2D; - - // NOTE: Gotta do it this crazy way because paths can be one-way. - Vector vecNearestPoint = Vector(0.0f, 0.0f, 0.0f); - Vector vecNearestPathSegment; - for ( int i = 0; i < 2; ++i ) - { - int loopCheck = 0; - CPathTrack *pTravPath = pPath; - CPathTrack *pNextPath; - - BEGIN_PATH_TRACK_ITERATION(); - for ( ; CPathTrack::ValidPath( pTravPath ); pTravPath = pNextPath, loopCheck++ ) - { - // Circular loop checking - if ( pTravPath->HasBeenVisited() ) - break; - - // Mark it as being visited. - pTravPath->Visit(); - - pNextPath = (i == 0) ? pTravPath->GetPrevious() : pTravPath->GetNext(); - - // No alt paths allowed in leading mode. - if ( pTravPath->m_paltpath ) - { - Warning( "%s: Alternative paths in path_track not allowed when using the leading behavior!\n", GetEntityName().ToCStr() ); - } - - // Need line segments - if ( !CPathTrack::ValidPath(pNextPath) ) - break; - - // Find the closest point on the line segment on the path - Vector vecClosest; - CalcClosestPointOnLineSegment( targetPos, pTravPath->GetAbsOrigin(), pNextPath->GetAbsOrigin(), vecClosest ); - - // Find the distance between this test point and our goal point - flPathDist2D = vecClosest.AsVector2D().DistToSqr( targetPos.AsVector2D() ); - if ( flPathDist2D > flNearestDist2D ) - continue; - - flPathDist = vecClosest.z - targetPos.z; - flPathDist *= flPathDist; - flPathDist += flPathDist2D; - if (( flPathDist2D == flNearestDist2D ) && ( flPathDist >= flNearestDist )) - continue; - - pNearestPath = (i == 0) ? pTravPath : pNextPath; - flNearestDist2D = flPathDist2D; - flNearestDist = flPathDist; - vecNearestPoint = vecClosest; - VectorSubtract( pNextPath->GetAbsOrigin(), pTravPath->GetAbsOrigin(), vecNearestPathSegment ); - if ( i == 0 ) - { - vecNearestPathSegment *= -1.0f; - } - } - } - - VectorNormalize( vecNearestPathSegment ); - *pDistanceFromPath = ComputePerpDistanceFromPath( vecNearestPoint, vecNearestPathSegment, targetPos ); - *pVecClosestPoint = vecNearestPoint; - *pVecPathDir = vecNearestPathSegment; - return pNearestPath; -} - - -//----------------------------------------------------------------------------- -// Breakable paths? -//----------------------------------------------------------------------------- -void CAI_TrackPather::InputStartBreakableMovement( inputdata_t &inputdata ) -{ - m_bPatrolBreakable = true; -} - -void CAI_TrackPather::InputStopBreakableMovement( inputdata_t &inputdata ) -{ - m_bPatrolBreakable = false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAI_TrackPather::InputStartPatrol( inputdata_t &inputdata ) -{ - m_bPatrolling = true; -} - - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -void CAI_TrackPather::InputStopPatrol( inputdata_t &inputdata ) -{ - m_bPatrolling = false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAI_TrackPather::InputStartPatrolBreakable( inputdata_t &inputdata ) -{ - m_bPatrolBreakable = true; - m_bPatrolling = true; -} - - -//------------------------------------------------------------------------------ -// Leading behaviors -//------------------------------------------------------------------------------ -void CAI_TrackPather::InputStartLeading( inputdata_t &inputdata ) -{ - EnableLeading( true ); - SetLeadingDistance( inputdata.value.Int() ); -} - -void CAI_TrackPather::InputStopLeading( inputdata_t &inputdata ) -{ - EnableLeading( false ); -} - - -//------------------------------------------------------------------------------ -// Selects a new destination target -//------------------------------------------------------------------------------ -void CAI_TrackPather::SelectNewDestTarget() -{ - if ( !m_bPatrolling ) - return; - - // NOTE: This version is bugged, but I didn't want to make the fix - // here for fear of breaking a lot of maps late in the day. - // So, only the chopper does the "right" thing. -#ifdef HL2_EPISODIC - // Episodic uses the fixed logic for all trackpathers - if ( 1 ) -#else - if ( ShouldUseFixedPatrolLogic() ) -#endif - { - CPathTrack *pOldDest = m_pDestPathTarget; - - // Only switch polarity of movement if we're at the *end* of the path - // This is really useful for initial conditions of patrolling - // NOTE: We've got to do some extra work for circular paths - bool bIsCircular = false; - { - BEGIN_PATH_TRACK_ITERATION(); - CPathTrack *pTravPath = m_pDestPathTarget; - while( CPathTrack::ValidPath( pTravPath ) ) - { - // Circular loop checking - if ( pTravPath->HasBeenVisited() ) - { - bIsCircular = true; - break; - } - - pTravPath->Visit(); - pTravPath = NextAlongCurrentPath( pTravPath ); - } - } - - if ( bIsCircular || (NextAlongCurrentPath( m_pDestPathTarget ) == NULL) ) - { - m_bMovingForward = !m_bMovingForward; - } - - BEGIN_PATH_TRACK_ITERATION(); - - while ( true ) - { - CPathTrack *pNextTrack = NextAlongCurrentPath( m_pDestPathTarget ); - if ( !pNextTrack || (pNextTrack == pOldDest) || pNextTrack->HasBeenVisited() ) - break; - - pNextTrack->Visit(); - m_pDestPathTarget = pNextTrack; - } - } - else - { - CPathTrack *pOldDest = m_pDestPathTarget; - - // For patrolling, switch the polarity of movement - m_bMovingForward = !m_bMovingForward; - - int loopCount = 0; - while ( true ) - { - CPathTrack *pNextTrack = NextAlongCurrentPath( m_pDestPathTarget ); - if ( !pNextTrack ) - break; - if ( ++loopCount > 1024 ) - { - DevMsg(1,"WARNING: Looping path for %s\n", GetDebugName() ); - break; - } - - m_pDestPathTarget = pNextTrack; - } - - if ( m_pDestPathTarget == pOldDest ) - { - // This can occur if we move to the first point on the path - SelectNewDestTarget(); - } - } -} - - -//------------------------------------------------------------------------------ -// Moves to the track -//------------------------------------------------------------------------------ -void CAI_TrackPather::UpdateCurrentTargetLeading() -{ - bool bRestingAtDest = false; - CPathTrack *pAdjustedDest; - - // Find the point along the line that we're closest to. - const Vector &vecTarget = m_pCurrentPathTarget->GetAbsOrigin(); - Vector vecPoint; - float t = ClosestPointToCurrentPath( &vecPoint ); - if ( (t < 1.0f) && ( vecPoint.DistToSqr( vecTarget ) > m_flTargetTolerance * m_flTargetTolerance ) ) - goto visualizeDebugInfo; - - // Trip our "path_track reached" output - if ( m_pCurrentPathTarget != m_pLastPathTarget ) - { - // Get the path's specified max speed - m_flPathMaxSpeed = m_pCurrentPathTarget->m_flSpeed; - - variant_t emptyVariant; - m_pCurrentPathTarget->AcceptInput( "InPass", this, this, emptyVariant, 0 ); - m_pLastPathTarget = m_pCurrentPathTarget; - } - - // NOTE: CurrentPathTarget doesn't mean the same thing as dest path target! - // It's the "next"most when moving forward + "prev"most when moving backward - // Must do the tests in the same space - pAdjustedDest = AdjustForMovementDirection( m_pDestPathTarget ); - - // Update our dest path target, if appropriate... - if ( m_pCurrentPathTarget == pAdjustedDest ) - { - m_bForcedMove = false; - SelectNewDestTarget(); - - // NOTE: Must do this again since SelectNewDestTarget may change m_pDestPathTarget - pAdjustedDest = AdjustForMovementDirection( m_pDestPathTarget ); - } - - if ( m_pCurrentPathTarget != pAdjustedDest ) - { - // Update to the next path, if there is one... - m_pCurrentPathTarget = NextAlongCurrentPath( m_pCurrentPathTarget ); - if ( !m_pCurrentPathTarget ) - { - m_pCurrentPathTarget = m_pLastPathTarget; - } - } - else - { - // NOTE: Have to do this here because the NextAlongCurrentPath call above - // could make m_pCurrentPathTarget == m_pDestPathTarget. - // In this case, we're at rest (no patrolling behavior) - bRestingAtDest = true; - } - - if ( bRestingAtDest ) - { - // NOTE: Must use current path target, instead of dest - // to get the PreviousAlongCurrentPath working correctly - CPathTrack *pSegmentStart = PreviousAlongCurrentPath( m_pCurrentPathTarget ); - if ( !pSegmentStart ) - { - pSegmentStart = m_pCurrentPathTarget; - } - m_vecSegmentStartPoint = pSegmentStart->GetAbsOrigin(); - } - else - { - m_vecSegmentStartPoint = m_pLastPathTarget->GetAbsOrigin(); - } - -visualizeDebugInfo: - VisualizeDebugInfo( vecPoint, vecTarget ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_TrackPather::UpdateTargetPositionLeading( void ) -{ - Vector targetPos; - if ( !GetTrackPatherTarget( &targetPos ) ) - return; - - // NOTE: FindClosestPointOnPath *always* returns the point on the "far", - // end of the line segment containing the closest point (namely the 'next' - // track, as opposed to the 'prev' track) - Vector vecClosestPoint, vecPathDir; - float flTargetDistanceFromPath; - CPathTrack *pNextPath = FindClosestPointOnPath( m_pCurrentPathTarget, - targetPos, &vecClosestPoint, &vecPathDir, &flTargetDistanceFromPath ); - - // This means that a valid path could not be found to our target! - if ( CPathTrack::ValidPath( pNextPath ) == NULL ) - return; - -// NDebugOverlay::Cross3D( vecClosestPoint, -Vector(24,24,24), Vector(24,24,24), 0, 255, 255, true, 0.1f ); -// NDebugOverlay::Cross3D( pNextPath->GetAbsOrigin(), -Vector(24,24,24), Vector(24,24,24), 255, 255, 0, true, 0.1f ); - - // Here's how far we are from the path - m_flTargetDistFromPath = flTargetDistanceFromPath; - m_vecTargetPathDir = vecPathDir; - - // Here's info about where the target is along the path - m_vecTargetPathPoint = vecClosestPoint; - m_pTargetNearestPath = pNextPath; - - // Find the best position to be on our path - // NOTE: This will *also* return a path track on the "far" end of the line segment - // containing the leading position, namely the "next" end of the segment as opposed - // to the "prev" end of the segment. - CPathTrack *pDest = ComputeLeadingPointAlongPath( vecClosestPoint, pNextPath, m_flLeadDistance, &targetPos ); - SetDesiredPosition( targetPos ); - - // We only want to switch movement directions when absolutely necessary - // so convert dest into a more appropriate value based on the current movement direction - if ( pDest != m_pDestPathTarget ) - { - // NOTE: This is really tricky + subtle - // For leading, we don't want to ever change direction when the current target == the - // adjusted destination target. Namely, if we're going forward, both dest + curr - // mean the "next"most node so we can compare them directly against eath other. - // If we're moving backward, dest means "next"most, but curr means "prev"most. - // We first have to adjust the dest to mean "prev"most, and then do the comparison. - // If the adjusted dest == curr, then maintain direction. Otherwise, use the forward along path test. - bool bMovingForward = m_bMovingForward; - CPathTrack *pAdjustedDest = AdjustForMovementDirection( pDest ); - if ( m_pCurrentPathTarget != pAdjustedDest ) - { - bMovingForward = IsForwardAlongPath( m_pCurrentPathTarget, pAdjustedDest ); - } - - if ( bMovingForward != m_bMovingForward ) - { - // As a result of the tricky note above, this should never occur - Assert( pAdjustedDest != m_pCurrentPathTarget ); - - // Oops! Need to reverse direction - m_bMovingForward = bMovingForward; - m_vecSegmentStartPoint = m_pCurrentPathTarget->GetAbsOrigin(); - m_pCurrentPathTarget = NextAlongCurrentPath( m_pCurrentPathTarget ); - } - m_pDestPathTarget = pDest; - } - -// NDebugOverlay::Cross3D( m_pCurrentPathTarget->GetAbsOrigin(), -Vector(36,36,36), Vector(36,36,36), 255, 0, 0, true, 0.1f ); -// NDebugOverlay::Cross3D( m_pDestPathTarget->GetAbsOrigin(), -Vector(48,48,48), Vector(48,48,48), 0, 255, 0, true, 0.1f ); -// NDebugOverlay::Cross3D( targetPos, -Vector(36,36,36), Vector(36,36,36), 0, 0, 255, true, 0.1f ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_TrackPather::UpdateTargetPosition( void ) -{ - // Don't update our target if we're being told to go somewhere - if ( m_bForcedMove && !m_bPatrolBreakable ) - return; - - // Don't update our target if we're patrolling - if ( m_bPatrolling ) - { - // If we have an enemy, and our patrol is breakable, stop patrolling - if ( !m_bPatrolBreakable || !GetEnemy() ) - return; - - m_bPatrolling = false; - } - - Vector targetPos; - if ( !GetTrackPatherTarget( &targetPos ) ) - return; - - // Not time to update again - if ( m_flEnemyPathUpdateTime > gpGlobals->curtime ) - return; - - // See if the target has moved enough to make us recheck - float flDistSqr = ( targetPos - m_vecLastGoalCheckPosition ).LengthSqr(); - if ( flDistSqr < m_flTargetDistanceThreshold * m_flTargetDistanceThreshold ) - return; - - // Find the best position to be on our path - CPathTrack *pDest = BestPointOnPath( m_pCurrentPathTarget, targetPos, m_flAvoidDistance, true, m_bChooseFarthestPoint ); - - if ( CPathTrack::ValidPath( pDest ) == NULL ) - { - // This means that a valid path could not be found to our target! -// Assert(0); - return; - } - - if ( pDest != m_pDestPathTarget ) - { - // This is our new destination - bool bMovingForward = IsForwardAlongPath( m_pCurrentPathTarget, pDest ); - if ( bMovingForward != m_bMovingForward ) - { - // Oops! Need to reverse direction - m_bMovingForward = bMovingForward; - if ( pDest != m_pCurrentPathTarget ) - { - SetupNewCurrentTarget( NextAlongCurrentPath( m_pCurrentPathTarget ) ); - } - } - m_pDestPathTarget = pDest; - } - - // Keep this goal point for comparisons later - m_vecLastGoalCheckPosition = targetPos; - - // Only do this on set intervals - m_flEnemyPathUpdateTime = gpGlobals->curtime + 1.0f; -} - - -//------------------------------------------------------------------------------ -// Returns the direction of the path at the closest point to the target -//------------------------------------------------------------------------------ -const Vector &CAI_TrackPather::TargetPathDirection() const -{ - return m_vecTargetPathDir; -} - -const Vector &CAI_TrackPather::TargetPathAcrossDirection() const -{ - static Vector s_Result; - CrossProduct( m_vecTargetPathDir, Vector( 0, 0, 1 ), s_Result ); - return s_Result; -} - - -//------------------------------------------------------------------------------ -// Returns the speed of the target relative to the path -//------------------------------------------------------------------------------ -float CAI_TrackPather::TargetSpeedAlongPath() const -{ - if ( !GetEnemy() || !IsLeading() ) - return 0.0f; - - Vector vecSmoothedVelocity = GetEnemy()->GetSmoothedVelocity(); - return DotProduct( vecSmoothedVelocity, TargetPathDirection() ); -} - - -//------------------------------------------------------------------------------ -// Returns the speed of the target *across* the path -//------------------------------------------------------------------------------ -float CAI_TrackPather::TargetSpeedAcrossPath() const -{ - if ( !GetEnemy() || !IsLeading() ) - return 0.0f; - - Vector vecSmoothedVelocity = GetEnemy()->GetSmoothedVelocity(); - return DotProduct( vecSmoothedVelocity, TargetPathAcrossDirection() ); -} - - -//------------------------------------------------------------------------------ -// Returns the max distance we can be from the path -//------------------------------------------------------------------------------ -float CAI_TrackPather::MaxDistanceFromCurrentPath() const -{ - if ( !IsLeading() || !m_pCurrentPathTarget ) - return 0.0f; - - CPathTrack *pPrevPath = PreviousAlongCurrentPath( m_pCurrentPathTarget ); - if ( !pPrevPath ) - { - pPrevPath = m_pCurrentPathTarget; - } - - // NOTE: Can't use m_vecSegmentStartPoint because we don't have a radius defined for it - float t; - Vector vecTemp; - CalcClosestPointOnLine( GetAbsOrigin(), pPrevPath->GetAbsOrigin(), - m_pCurrentPathTarget->GetAbsOrigin(), vecTemp, &t ); - t = clamp( t, 0.0f, 1.0f ); - float flRadius = (1.0f - t) * pPrevPath->GetRadius() + t * m_pCurrentPathTarget->GetRadius(); - return flRadius; -} - - -//------------------------------------------------------------------------------ -// Purpose : A different version of the track pather which is more explicit about -// the meaning of dest, current, and prev path points -//------------------------------------------------------------------------------ -void CAI_TrackPather::UpdateTrackNavigation( void ) -{ - // No target? Use the string specified. We have no spawn method (sucky!!) so this is how that works - if ( ( CPathTrack::ValidPath( m_pDestPathTarget ) == NULL ) && ( m_target != NULL_STRING ) ) - { - FlyToPathTrack( m_target ); - m_target = NULL_STRING; - } - - if ( !IsLeading() ) - { - if ( !m_pCurrentPathTarget ) - return; - - // Updates our destination node if we're tracking something - UpdateTargetPosition(); - - // Move along our path towards our current destination - UpdateCurrentTarget(); - } - else - { - // Updates our destination position if we're leading something - UpdateTargetPositionLeading(); - - // Move along our path towards our current destination - UpdateCurrentTargetLeading(); - } -} - - -//------------------------------------------------------------------------------ -// Sets the farthest path distance -//------------------------------------------------------------------------------ -void CAI_TrackPather::SetFarthestPathDist( float flMaxPathDist ) -{ - m_flFarthestPathDist = flMaxPathDist; -} - - -//------------------------------------------------------------------------------ -// Sets up a new current path target -//------------------------------------------------------------------------------ -void CAI_TrackPather::SetupNewCurrentTarget( CPathTrack *pTrack ) -{ - Assert( pTrack ); - m_vecSegmentStartPoint = GetAbsOrigin(); - VectorMA( m_vecSegmentStartPoint, -2.0f, GetAbsVelocity(), m_vecSegmentStartSplinePoint ); - m_pCurrentPathTarget = pTrack; - SetDesiredPosition( m_pCurrentPathTarget->GetAbsOrigin() ); -} - - -//------------------------------------------------------------------------------ -// Moves to an explicit track point -//------------------------------------------------------------------------------ -void CAI_TrackPather::MoveToTrackPoint( CPathTrack *pTrack ) -{ - if ( IsOnSameTrack( pTrack, m_pDestPathTarget ) ) - { - // The track must be valid - if ( CPathTrack::ValidPath( pTrack ) == NULL ) - return; - - m_pDestPathTarget = pTrack; - m_bMovingForward = IsForwardAlongPath( m_pCurrentPathTarget, pTrack ); - m_bForcedMove = true; - } - else - { - CPathTrack *pClosestTrack = BestPointOnPath( pTrack, WorldSpaceCenter(), 0.0f, false, false ); - - // The track must be valid - if ( CPathTrack::ValidPath( pClosestTrack ) == NULL ) - return; - - SetupNewCurrentTarget( pClosestTrack ); - m_pDestPathTarget = pTrack; - m_bMovingForward = IsForwardAlongPath( pClosestTrack, pTrack ); - m_bForcedMove = true; - } -} - - -//------------------------------------------------------------------------------ -// Moves to the closest track point -//------------------------------------------------------------------------------ -void CAI_TrackPather::MoveToClosestTrackPoint( CPathTrack *pTrack ) -{ - if ( IsOnSameTrack( pTrack, m_pDestPathTarget ) ) - return; - - CPathTrack *pClosestTrack = BestPointOnPath( pTrack, WorldSpaceCenter(), 0.0f, false, false ); - - // The track must be valid - if ( CPathTrack::ValidPath( pClosestTrack ) == NULL ) - return; - - SetupNewCurrentTarget( pClosestTrack ); - m_pDestPathTarget = pClosestTrack; - m_bMovingForward = true; - - // Force us to switch tracks if we're leading - if ( IsLeading() ) - { - m_bForcedMove = true; - } -} - - -//----------------------------------------------------------------------------- -// Are the two path tracks connected? -//----------------------------------------------------------------------------- -bool CAI_TrackPather::IsOnSameTrack( CPathTrack *pPath1, CPathTrack *pPath2 ) const -{ - if ( pPath1 == pPath2 ) - return true; - - { - BEGIN_PATH_TRACK_ITERATION(); - CPathTrack *pTravPath = pPath1->GetPrevious(); - while( CPathTrack::ValidPath( pTravPath ) && (pTravPath != pPath1) ) - { - // Circular loop checking - if ( pTravPath->HasBeenVisited() ) - break; - - pTravPath->Visit(); - - if ( pTravPath == pPath2 ) - return true; - - pTravPath = pTravPath->GetPrevious(); - } - } - - { - BEGIN_PATH_TRACK_ITERATION(); - CPathTrack *pTravPath = pPath1->GetNext(); - while( CPathTrack::ValidPath( pTravPath ) && (pTravPath != pPath1) ) - { - // Circular loop checking - if ( pTravPath->HasBeenVisited() ) - break; - - pTravPath->Visit(); - - if ( pTravPath == pPath2 ) - return true; - - pTravPath = pTravPath->GetNext(); - } - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Deal with teleportation -//----------------------------------------------------------------------------- -void CAI_TrackPather::Teleported() -{ - // This updates the paths so they are reasonable - CPathTrack *pClosestTrack = BestPointOnPath( GetDestPathTarget(), WorldSpaceCenter(), 0.0f, false, false ); - m_pDestPathTarget = NULL; - MoveToClosestTrackPoint( pClosestTrack ); -} - - -//----------------------------------------------------------------------------- -// Returns distance along path to target, returns FLT_MAX if there's no path -//----------------------------------------------------------------------------- -float CAI_TrackPather::ComputePathDistance( CPathTrack *pPath, CPathTrack *pDest, bool bForward ) const -{ - float flDist = 0.0f; - CPathTrack *pLast = pPath; - - BEGIN_PATH_TRACK_ITERATION(); - while ( CPathTrack::ValidPath( pPath ) ) - { - // Ciruclar loop checking - if ( pPath->HasBeenVisited() ) - return FLT_MAX; - - pPath->Visit(); - - flDist += pLast->GetAbsOrigin().DistTo( pPath->GetAbsOrigin() ); - - if ( pDest == pPath ) - return flDist; - - pLast = pPath; - pPath = bForward ? pPath->GetNext() : pPath->GetPrevious(); - } - - return FLT_MAX; -} - - -//----------------------------------------------------------------------------- -// Is pPathTest in "front" of pPath on the same path? (Namely, does GetNext() get us there?) -//----------------------------------------------------------------------------- -bool CAI_TrackPather::IsForwardAlongPath( CPathTrack *pPath, CPathTrack *pPathTest ) const -{ - // Also, in the case of looping paths, we want to return the shortest path - float flForwardDist = ComputePathDistance( pPath, pPathTest, true ); - float flReverseDist = ComputePathDistance( pPath, pPathTest, false ); - - Assert( ( flForwardDist != FLT_MAX ) || ( flReverseDist != FLT_MAX ) ); - return ( flForwardDist <= flReverseDist ); -} - - -//----------------------------------------------------------------------------- -// Computes distance + nearest point from the current path.. -//----------------------------------------------------------------------------- -float CAI_TrackPather::ClosestPointToCurrentPath( Vector *pVecPoint ) const -{ - if (!m_pCurrentPathTarget) - { - *pVecPoint = GetAbsOrigin(); - return 0; - } - - float t; - CalcClosestPointOnLine( GetAbsOrigin(), m_vecSegmentStartPoint, - m_pCurrentPathTarget->GetAbsOrigin(), *pVecPoint, &t ); - return t; -} - - -//----------------------------------------------------------------------------- -// Computes a "path" velocity at a particular point along the current path -//----------------------------------------------------------------------------- -void CAI_TrackPather::ComputePathTangent( float t, Vector *pVecTangent ) const -{ - CPathTrack *pNextTrack = NextAlongCurrentPath(m_pCurrentPathTarget); - if ( !pNextTrack ) - { - pNextTrack = m_pCurrentPathTarget; - } - - t = clamp( t, 0.0f, 1.0f ); - pVecTangent->Init(0,0,0); - Catmull_Rom_Spline_Tangent( m_vecSegmentStartSplinePoint, m_vecSegmentStartPoint, - m_pCurrentPathTarget->GetAbsOrigin(), pNextTrack->GetAbsOrigin(), t, *pVecTangent ); - VectorNormalize( *pVecTangent ); -} - - -//----------------------------------------------------------------------------- -// Computes the *normalized* velocity at which the helicopter should approach the final point -//----------------------------------------------------------------------------- -void CAI_TrackPather::ComputeNormalizedDestVelocity( Vector *pVecVelocity ) const -{ - if ( m_nPauseState != PAUSE_NO_PAUSE ) - { - pVecVelocity->Init(0,0,0); - return; - } - - CPathTrack *pNextTrack = NextAlongCurrentPath(m_pCurrentPathTarget); - if ( !pNextTrack ) - { - pNextTrack = m_pCurrentPathTarget; - } - - if ( ( pNextTrack == m_pCurrentPathTarget ) || ( m_pCurrentPathTarget == m_pDestPathTarget ) ) - { - pVecVelocity->Init(0,0,0); - return; - } - - VectorSubtract( pNextTrack->GetAbsOrigin(), m_pCurrentPathTarget->GetAbsOrigin(), *pVecVelocity ); - VectorNormalize( *pVecVelocity ); - - // Slow it down if we're approaching a sharp corner - Vector vecDelta; - VectorSubtract( m_pCurrentPathTarget->GetAbsOrigin(), m_vecSegmentStartPoint, vecDelta ); - VectorNormalize( vecDelta ); - float flDot = DotProduct( *pVecVelocity, vecDelta ); - *pVecVelocity *= clamp( flDot, 0.0f, 1.0f ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAI_TrackPather::SetTrack( CBaseEntity *pGoalEnt ) -{ - // Ignore this input if we're *already* on that path. - CPathTrack *pTrack = dynamic_cast(pGoalEnt); - if ( !pTrack ) - { - DevWarning( "%s: Specified entity '%s' must be a path_track!\n", pGoalEnt->GetClassname(), pGoalEnt->GetEntityName().ToCStr() ); - return; - } - - MoveToClosestTrackPoint( pTrack ); -} - -void CAI_TrackPather::SetTrack( string_t strTrackName ) -{ - // Find our specified target - CBaseEntity *pGoalEnt = gEntList.FindEntityByName( NULL, strTrackName ); - if ( pGoalEnt == NULL ) - { - DevWarning( "%s: Could not find path_track '%s'!\n", GetClassname(), STRING( strTrackName ) ); - return; - } - - SetTrack( pGoalEnt ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAI_TrackPather::InputSetTrack( inputdata_t &inputdata ) -{ - string_t strTrackName = MAKE_STRING( inputdata.value.String() ); - SetTrack( MAKE_STRING( inputdata.value.String() ) ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : strTrackName - -//----------------------------------------------------------------------------- -void CAI_TrackPather::FlyToPathTrack( string_t strTrackName ) -{ - CBaseEntity *pGoalEnt = gEntList.FindEntityByName( NULL, strTrackName ); - if ( pGoalEnt == NULL ) - { - DevWarning( "%s: Could not find path_track '%s'!\n", GetClassname(), STRING( strTrackName ) ); - return; - } - - // Ignore this input if we're *already* on that path. - CPathTrack *pTrack = dynamic_cast(pGoalEnt); - if ( !pTrack ) - { - DevWarning( "%s: Specified entity '%s' must be a path_track!\n", GetClassname(), STRING( strTrackName ) ); - return; - } - - // Find our specified target - MoveToTrackPoint( pTrack ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAI_TrackPather::InputFlyToPathTrack( inputdata_t &inputdata ) -{ - // Find our specified target - string_t strTrackName = MAKE_STRING( inputdata.value.String() ); - m_nPauseState = PAUSE_NO_PAUSE; - FlyToPathTrack( strTrackName ); -} - - -//----------------------------------------------------------------------------- -// Changes the mode used to determine which path point to move to -//----------------------------------------------------------------------------- -void CAI_TrackPather::InputChooseFarthestPathPoint( inputdata_t &inputdata ) -{ - UseFarthestPathPoint( true ); -} - -void CAI_TrackPather::InputChooseNearestPathPoint( inputdata_t &inputdata ) -{ - UseFarthestPathPoint( false ); -} - -void CAI_TrackPather::UseFarthestPathPoint( bool useFarthest ) -{ - m_bChooseFarthestPoint = useFarthest; -} diff --git a/game/server/ai_trackpather.h b/game/server/ai_trackpather.h deleted file mode 100644 index a1c341452..000000000 --- a/game/server/ai_trackpather.h +++ /dev/null @@ -1,274 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef AI_TRACKPATHER_H -#define AI_TRACKPATHER_H - -#if defined( _WIN32 ) -#pragma once -#endif - - -#include "ai_basenpc.h" - - -class CPathTrack; - -//------------------------------------------------------------------------------ - -class CAI_TrackPather : public CAI_BaseNPC -{ - DECLARE_CLASS( CAI_TrackPather, CAI_BaseNPC ); - DECLARE_DATADESC(); -public: - - bool IsOnPathTrack() { return (m_pCurrentPathTarget != NULL); } - -protected: - void InitPathingData( float flTrackArrivalTolerance, float flTargetDistance, float flAvoidDistance ); - virtual bool GetTrackPatherTarget( Vector *pPos ) { return false; } - virtual CBaseEntity *GetTrackPatherTargetEnt() { return NULL; } - - const Vector & GetDesiredPosition() const { return m_vecDesiredPosition; } - void SetDesiredPosition( const Vector &v ) { m_vecDesiredPosition = v; } - const Vector & GetGoalOrientation() const { return m_vecGoalOrientation; } - void SetGoalOrientation( const Vector &v ) { m_vecGoalOrientation = v; } - - bool CurPathTargetIsDest() { return ( m_pDestPathTarget == m_pCurrentPathTarget ); } - - virtual bool HasReachedTarget( void ) { return (WorldSpaceCenter() - m_vecDesiredPosition).Length() < 128; } - - CPathTrack * GetDestPathTarget() { return m_pDestPathTarget; } - - bool IsInForcedMove() const { return m_bForcedMove; } - void ClearForcedMove() { m_bForcedMove = false; } - - float GetPathMaxSpeed() const { return m_flPathMaxSpeed; } - - void OnSave( IEntitySaveUtils *pUtils ); - void OnRestore( void ); - -protected: - enum PauseState_t - { - PAUSE_NO_PAUSE = 0, - PAUSED_AT_POSITION, - PAUSE_AT_NEXT_LOS_POSITION, - - PAUSE_FORCE_DWORD = 0xFFFFFFFF, - }; - - // Sets a track - void SetTrack( string_t strTrackName ); - void SetTrack( CBaseEntity *pGoalEnt ); - - // Fly to a particular track point via the path - virtual void InputFlyToPathTrack( inputdata_t &inputdata ); - - // Updates the nav target if we've reached it - void UpdateTrackNavigation( void ); - - // Computes distance + nearest point from the current path.. - float ClosestPointToCurrentPath( Vector *pVecPoint ) const; - - // Computes a "path" velocity at a particular point along the current path - void ComputePathTangent( float t, Vector *pVecTangent ) const; - - // Computes the *normalized* velocity at which the helicopter should approach the final point - void ComputeNormalizedDestVelocity( Vector *pVecVelocity ) const; - - // Sets the farthest path distance - void SetFarthestPathDist( float flMaxPathDist ); - - // Returns the next/previous path along our current path - CPathTrack *NextAlongCurrentPath( CPathTrack *pPath ) const; - CPathTrack *PreviousAlongCurrentPath( CPathTrack *pPath ) const; - - // Adjusts a "next"most node based on the current movement direction - CPathTrack *AdjustForMovementDirection( CPathTrack *pPath ) const; - - // Enemy visibility check - virtual CBaseEntity *FindTrackBlocker( const Vector &vecViewPoint, const Vector &vecTargetPos ); - - // Compute a point n units along a path - void ComputePointAlongPath( const Vector &vecStartPoint, float flDistance, Vector *pTarget ); - - // Are we leading? - bool IsLeading() const { return m_bLeading && !m_bForcedMove; } - - // Leading + leading distance - void EnableLeading( bool bEnable ); - void SetLeadingDistance( float flLeadDistance ); - float GetLeadingDistance( ) const; - - // Compute a point n units along the current path from our current position - // (but don't pass the desired target point) - void ComputePointAlongCurrentPath( float flDistance, float flPerpDist, Vector *pTarget ); - - // Returns the perpendicular distance of the target from the nearest path point - float TargetDistanceToPath() const { return m_flTargetDistFromPath; } - - // Returns the speed of the target relative to the path - float TargetSpeedAlongPath() const; - - // Returns the speed of the target *across* the path - float TargetSpeedAcrossPath() const; - - // Compute a path direction - void ComputePathDirection( CPathTrack *pPath, Vector *pVecPathDir ); - - // What's the current path direction? - void CurrentPathDirection( Vector *pVecPathDir ); - - // Returns the max distance we can be from the path - float MaxDistanceFromCurrentPath() const; - - // true to use farthest, false for nearest - void UseFarthestPathPoint( bool useFarthest ); - - // Moves to an explicit track point - void MoveToTrackPoint( CPathTrack *pTrack ); - - // Sets up a new current path target - void SetupNewCurrentTarget( CPathTrack *pTrack ); - - // Compute the distance to the leading position - float ComputeDistanceToLeadingPosition(); - - // Compute the distance to the target position - float ComputeDistanceToTargetPosition(); - - // Set the pause state. - void SetPauseState( PauseState_t pauseState ) { m_nPauseState = pauseState; } - - // Does this path track have LOS to the target? - bool HasLOSToTarget( CPathTrack *pTrack ); - - // FIXME: Work this back into the base class - virtual bool ShouldUseFixedPatrolLogic() { return false; } - - // Deal with teleportation - void Teleported(); - -private: - - CPathTrack *BestPointOnPath( CPathTrack *pPath, const Vector &targetPos, float avoidRadius, bool visible, bool bFarthestPointOnPath ); - - // Input methods - void InputSetTrack( inputdata_t &inputdata ); - void InputChooseFarthestPathPoint( inputdata_t &inputdata ); - void InputChooseNearestPathPoint( inputdata_t &inputdata ); - void InputStartBreakableMovement( inputdata_t &inputdata ); - void InputStopBreakableMovement( inputdata_t &inputdata ); - void InputStartPatrol( inputdata_t &inputdata ); - void InputStopPatrol( inputdata_t &inputdata ); - void InputStartLeading( inputdata_t &inputdata ); - void InputStopLeading( inputdata_t &inputdata ); - - // Obsolete, for backward compatibility - void InputStartPatrolBreakable( inputdata_t &inputdata ); - - // Flies to a point on a track - void FlyToPathTrack( string_t strTrackName ); - - // Selects a new destination target - void SelectNewDestTarget(); - - // Makes sure we've picked the right position along the path if we're chasing an enemy - void UpdateTargetPosition( ); - - // Moves to the track - void UpdateCurrentTarget(); - void UpdateCurrentTargetLeading(); - - // Track debugging info - void VisualizeDebugInfo( const Vector &vecNearestPoint, const Vector &vecTarget ); - - // Moves to the closest track point - void MoveToClosestTrackPoint( CPathTrack *pTrack ); - - // Are the two path tracks connected? - bool IsOnSameTrack( CPathTrack *pPath1, CPathTrack *pPath2 ) const; - - // Is pPathTest in "front" of pPath on the same path? (Namely, does GetNext() get us there?) - bool IsForwardAlongPath( CPathTrack *pPath, CPathTrack *pPathTest ) const; - - // Purpose: - void UpdateTargetPositionLeading( void ); - - // Compute a point n units along a path - CPathTrack *ComputeLeadingPointAlongPath( const Vector &vecStartPoint, CPathTrack *pFirstTrack, float flDistance, Vector *pTarget ); - - // Finds the closest point on the path, returns a signed perpendicular distance - CPathTrack *FindClosestPointOnPath( CPathTrack *pPath, const Vector &targetPos, Vector *pVecClosestPoint, Vector *pVecPathDir, float *pDistanceFromPath ); - - // Methods to find a signed perp distance from the track - // and to compute a point off the path based on the signed perp distance - float ComputePerpDistanceFromPath( const Vector &vecPointOnPath, const Vector &vecPathDir, const Vector &vecPointOffPath ); - void ComputePointFromPerpDistance( const Vector &vecPointOnPath, const Vector &vecPathDir, float flPerpDist, Vector *pResult ); - - // Returns the direction of the path at the closest point to the target - const Vector &TargetPathDirection() const; - const Vector &TargetPathAcrossDirection() const; - - // Returns distance along path to target, returns -1 if there's no path - float ComputePathDistance( CPathTrack *pStart, CPathTrack *pDest, bool bForward ) const; - - // Compute the distance to a particular point on the path - float ComputeDistanceAlongPathToPoint( CPathTrack *pStartTrack, CPathTrack *pDestTrack, const Vector &vecDestPosition, bool bMovingForward ); - -private: - //--------------------------------- - Vector m_vecDesiredPosition; - Vector m_vecGoalOrientation; // orientation of the goal entity. - - // NOTE: CurrentPathTarget changes meaning based on movement direction - // For this *after* means the "next" (m_pnext) side of the line segment - // and "before" means the "prev" (m_pprevious) side of the line segment - // CurrentPathTarget is *after* the desired point when moving forward, - // and *before* the desired point when moving backward. - // DestPathTarget + TargetNearestPath always represent points - // *after* the desired point. - CHandle m_pCurrentPathTarget; - CHandle m_pDestPathTarget; - CHandle m_pLastPathTarget; - CHandle m_pTargetNearestPath; // Used only by leading, it specifies the path point *after* where the target is - - string_t m_strCurrentPathName; - string_t m_strDestPathName; - string_t m_strLastPathName; - string_t m_strTargetNearestPathName; - - Vector m_vecLastGoalCheckPosition; // Last position checked for moving towards - float m_flEnemyPathUpdateTime; // Next time to update our enemies position - bool m_bForcedMove; // Means the destination point must be reached regardless of enemy position - bool m_bPatrolling; // If set, move back and forth along the current track until we see an enemy - bool m_bPatrolBreakable; // If set, I'll stop patrolling if I see an enemy - bool m_bLeading; // If set, we can lead our enemies - - // Derived class pathing data - float m_flTargetDistanceThreshold;// Distance threshold used to determine when a target has moved enough to update our navigation to it - float m_flAvoidDistance; // - - float m_flTargetTolerance; // How far from a path track do we need to be before we 'reached' it? - Vector m_vecSegmentStartPoint; // Starting point for the current segment - Vector m_vecSegmentStartSplinePoint; // Used to define a spline which is used to compute path velocity - bool m_bMovingForward; - bool m_bChooseFarthestPoint; - float m_flFarthestPathDist; // How far from a path track do we need to be before we 'reached' it? - - float m_flPathMaxSpeed; - float m_flTargetDistFromPath; // How far is the target from the closest point on the path? - float m_flLeadDistance; - Vector m_vecTargetPathDir; - Vector m_vecTargetPathPoint; // What point on the path is closest to the target? - - PauseState_t m_nPauseState; -}; - -//------------------------------------------------------------------------------ - -#endif // AI_TRACKPATHER_H diff --git a/game/server/ai_utils.cpp b/game/server/ai_utils.cpp deleted file mode 100644 index 09b5fc80e..000000000 --- a/game/server/ai_utils.cpp +++ /dev/null @@ -1,580 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "ai_utils.h" -#include "ai_memory.h" -#include "ai_basenpc.h" -#include "ai_senses.h" -#include "ai_moveprobe.h" -#include "vphysics/object_hash.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- - -BEGIN_SIMPLE_DATADESC( CAI_MoveMonitor ) - DEFINE_FIELD( m_vMark, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_flMarkTolerance, FIELD_FLOAT ) -END_DATADESC() - -//----------------------------------------------------------------------------- - -BEGIN_SIMPLE_DATADESC( CAI_ShotRegulator ) - DEFINE_FIELD( m_flNextShotTime, FIELD_TIME ), - DEFINE_FIELD( m_bInRestInterval, FIELD_BOOLEAN ), - DEFINE_FIELD( m_nBurstShotsRemaining, FIELD_SHORT ), - DEFINE_FIELD( m_nMinBurstShots, FIELD_SHORT ), - DEFINE_FIELD( m_nMaxBurstShots, FIELD_SHORT ), - DEFINE_FIELD( m_flMinRestInterval, FIELD_FLOAT ), - DEFINE_FIELD( m_flMaxRestInterval, FIELD_FLOAT ), - DEFINE_FIELD( m_flMinBurstInterval, FIELD_FLOAT ), - DEFINE_FIELD( m_flMaxBurstInterval, FIELD_FLOAT ), - DEFINE_FIELD( m_bDisabled, FIELD_BOOLEAN ), -END_DATADESC() - -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CAI_ShotRegulator::CAI_ShotRegulator() : m_nMinBurstShots(1), m_nMaxBurstShots(1) -{ - m_flMinRestInterval = 0.0f; - m_flMinRestInterval = 0.0f; - m_flMinBurstInterval = 0.0f; - m_flMaxBurstInterval = 0.0f; - m_flNextShotTime = -1; - m_nBurstShotsRemaining = 1; - m_bInRestInterval = false; - m_bDisabled = false; -} - - -//----------------------------------------------------------------------------- -// For backward compatibility -//----------------------------------------------------------------------------- -void CAI_ShotRegulator::SetParameters( int minShotsPerBurst, int maxShotsPerBurst, float minRestTime, float maxRestTime ) -{ - SetBurstShotCountRange( minShotsPerBurst, maxShotsPerBurst ); - SetRestInterval( minRestTime, maxRestTime ); - Reset( false ); -} - - -//----------------------------------------------------------------------------- -// Sets the number of shots to shoot in a single burst -//----------------------------------------------------------------------------- -void CAI_ShotRegulator::SetBurstShotCountRange( int minShotsPerBurst, int maxShotsPerBurst ) -{ - m_nMinBurstShots = minShotsPerBurst; - m_nMaxBurstShots = maxShotsPerBurst; -} - - -//----------------------------------------------------------------------------- -// How much time should I rest between bursts? -//----------------------------------------------------------------------------- -void CAI_ShotRegulator::SetRestInterval( float flMinRestInterval, float flMaxRestInterval ) -{ - m_flMinRestInterval = flMinRestInterval; - m_flMaxRestInterval = flMaxRestInterval; -} - - -//----------------------------------------------------------------------------- -// How much time should I wait in between shots in a single burst? -//----------------------------------------------------------------------------- -void CAI_ShotRegulator::SetBurstInterval( float flMinBurstInterval, float flMaxBurstInterval ) -{ - m_flMinBurstInterval = flMinBurstInterval; - m_flMaxBurstInterval = flMaxBurstInterval; -} - - -//----------------------------------------------------------------------------- -// Poll the current parameters -//----------------------------------------------------------------------------- -void CAI_ShotRegulator::GetBurstShotCountRange( int *pMinShotsPerBurst, int *pMaxShotsPerBurst ) const -{ - *pMinShotsPerBurst = m_nMinBurstShots; - *pMaxShotsPerBurst = m_nMaxBurstShots; -} - -void CAI_ShotRegulator::GetRestInterval( float *pMinRestInterval, float *pMaxRestInterval ) const -{ - *pMinRestInterval = m_flMinRestInterval; - *pMaxRestInterval = m_flMaxRestInterval; -} - -void CAI_ShotRegulator::GetBurstInterval( float *pMinBurstInterval, float *pMaxBurstInterval ) const -{ - *pMinBurstInterval = m_flMinBurstInterval; - *pMaxBurstInterval = m_flMaxBurstInterval; -} - - -//----------------------------------------------------------------------------- -// Resets the shot regulator to start a new burst -//----------------------------------------------------------------------------- -void CAI_ShotRegulator::Reset( bool bStartShooting ) -{ - m_bDisabled = false; - m_nBurstShotsRemaining = random->RandomInt( m_nMinBurstShots, m_nMaxBurstShots ); - if ( bStartShooting ) - { - m_flNextShotTime = gpGlobals->curtime; - m_bInRestInterval = false; - } - else - { - m_flNextShotTime = gpGlobals->curtime + random->RandomFloat( m_flMinRestInterval, m_flMaxRestInterval ); - m_bInRestInterval = true; - } -} - - -//----------------------------------------------------------------------------- -// Should we shoot? -//----------------------------------------------------------------------------- -bool CAI_ShotRegulator::ShouldShoot() const -{ - return ( !m_bDisabled && (m_flNextShotTime <= gpGlobals->curtime) ); -} - - -//----------------------------------------------------------------------------- -// Am I in the middle of a burst? -//----------------------------------------------------------------------------- -bool CAI_ShotRegulator::IsInRestInterval() const -{ - return (m_bInRestInterval && !ShouldShoot()); -} - - -//----------------------------------------------------------------------------- -// When will I shoot next? -//----------------------------------------------------------------------------- -float CAI_ShotRegulator::NextShotTime() const -{ - return m_flNextShotTime; -} - - -//----------------------------------------------------------------------------- -// Causes us to potentially delay our shooting time -//----------------------------------------------------------------------------- -void CAI_ShotRegulator::FireNoEarlierThan( float flTime ) -{ - if ( flTime > m_flNextShotTime ) - { - m_flNextShotTime = flTime; - } -} - - -//----------------------------------------------------------------------------- -// Burst shot count accessors -//----------------------------------------------------------------------------- -int CAI_ShotRegulator::GetBurstShotsRemaining() const -{ - return m_nBurstShotsRemaining; -} - -void CAI_ShotRegulator::SetBurstShotsRemaining( int shots ) -{ - m_nBurstShotsRemaining = shots; -} - - -//----------------------------------------------------------------------------- -// We fired the weapon! Update the next shot time -//----------------------------------------------------------------------------- -void CAI_ShotRegulator::OnFiredWeapon() -{ - --m_nBurstShotsRemaining; - if ( m_nBurstShotsRemaining <= 0 ) - { - Reset( false ); - } - else - { - m_bInRestInterval = false; - m_flNextShotTime += random->RandomFloat( m_flMinBurstInterval, m_flMaxBurstInterval ); - if ( m_flNextShotTime < gpGlobals->curtime ) - { - m_flNextShotTime = gpGlobals->curtime; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ShotRegulator::EnableShooting( void ) -{ - m_bDisabled = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ShotRegulator::DisableShooting( void ) -{ - m_bDisabled = true; -} - - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- - -BEGIN_SIMPLE_DATADESC( CAI_AccelDecay ) - DEFINE_FIELD( m_velocity, FIELD_FLOAT ), - DEFINE_FIELD( m_maxVelocity, FIELD_FLOAT ), - DEFINE_FIELD( m_minVelocity, FIELD_FLOAT ), - DEFINE_FIELD( m_invDecay, FIELD_FLOAT ), - DEFINE_FIELD( m_decayTime, FIELD_FLOAT ), - DEFINE_FIELD( m_accel, FIELD_FLOAT ), -END_DATADESC() - - -void CAI_AccelDecay::SetParameters( float minVelocity, float maxVelocity, float accelPercentPerTick, float decelPercentPerTick ) -{ - m_minVelocity = minVelocity; - m_maxVelocity = maxVelocity; - - m_accel = accelPercentPerTick; - m_invDecay = 1.0 - decelPercentPerTick; - - m_decayTime = 0.0; - float d = 1.0; - - int i = 0; - while (d * m_maxVelocity > m_minVelocity && i < 10) - { - d = d * m_invDecay; - m_decayTime = m_decayTime + 0.1 * d; // appox interval call - i++; - } -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- - -float CAI_AccelDecay::Update( float flCurrent, float flTarget, float flInterval ) -{ - float delta = flTarget - flCurrent; - float deltaSign = ( delta < 0 ) ? -1 : 1; - delta = fabsf( delta ); - - float curVelocity = m_velocity; - - if ( delta > 0.01 ) - { - if (fabsf( m_velocity ) < m_minVelocity) - m_velocity = m_minVelocity * deltaSign; - - if (delta < m_velocity * deltaSign * m_decayTime ) - { - m_velocity = m_velocity * m_invDecay; - - if (delta < m_velocity * deltaSign * flInterval) - { - m_velocity = delta * deltaSign / flInterval; - } - } - else - { - m_velocity = m_velocity * (1.0f - m_accel) + m_maxVelocity * m_accel * deltaSign; - if (delta < m_velocity * deltaSign * m_decayTime) - { - m_velocity = delta * deltaSign / m_decayTime; - } - } - - float newValue = flCurrent + (curVelocity + m_velocity) * 0.5 * flInterval; - return newValue; - } - - return flTarget; -} - - - -void CAI_AccelDecay::ResetVelocity( float flVelocity ) -{ - m_velocity = flVelocity; -} - - -void CAI_AccelDecay::SetMaxVelocity( float maxVelocity ) -{ - if (maxVelocity != m_maxVelocity) - { - SetParameters( m_minVelocity, maxVelocity, m_accel, 1.0 - m_invDecay ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -ConVar free_pass_peek_debug( "free_pass_peek_debug", "0" ); - -BEGIN_SIMPLE_DATADESC( AI_FreePassParams_t ) - - DEFINE_KEYFIELD( timeToTrigger, FIELD_FLOAT, "freepass_timetotrigger"), - DEFINE_KEYFIELD( duration, FIELD_FLOAT, "freepass_duration"), - DEFINE_KEYFIELD( moveTolerance, FIELD_FLOAT, "freepass_movetolerance"), - DEFINE_KEYFIELD( refillRate, FIELD_FLOAT, "freepass_refillrate"), - DEFINE_FIELD( coverDist, FIELD_FLOAT), - DEFINE_KEYFIELD( peekTime, FIELD_FLOAT, "freepass_peektime"), - DEFINE_FIELD( peekTimeAfterDamage, FIELD_FLOAT), - DEFINE_FIELD( peekEyeDist, FIELD_FLOAT), - DEFINE_FIELD( peekEyeDistZ, FIELD_FLOAT), - -END_DATADESC() - -BEGIN_SIMPLE_DATADESC( CAI_FreePass ) - - DEFINE_FIELD( m_hTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_FreePassTimeRemaining, FIELD_FLOAT ), - DEFINE_EMBEDDED( m_FreePassMoveMonitor ), - DEFINE_EMBEDDED( m_Params ), - -END_DATADESC() - -//--------------------------------------------------------- -//--------------------------------------------------------- - -void CAI_FreePass::Reset( float passTime, float moveTolerance ) -{ - CBaseEntity *pTarget = GetPassTarget(); - - if ( !pTarget || m_Params.duration < 0.1 ) - return; - - if ( passTime == -1 ) - { - m_FreePassTimeRemaining = m_Params.duration; - } - else - { - m_FreePassTimeRemaining = passTime; - } - - if ( moveTolerance == -1 ) - { - m_FreePassMoveMonitor.SetMark( pTarget, m_Params.moveTolerance ); - } - else - { - m_FreePassMoveMonitor.SetMark( pTarget, moveTolerance ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- - -void CAI_FreePass::Update( ) -{ - CBaseEntity *pTarget = GetPassTarget(); - if ( !pTarget || m_Params.duration < 0.1 ) - return; - - //--------------------------------- - // - // Free pass logic - // - AI_EnemyInfo_t *pTargetInfo = GetOuter()->GetEnemies()->Find( pTarget ); - - // This works with old data because need to do before base class so as to not choose as enemy - if ( !HasPass() ) - { - float timePlayerLastSeen = (pTargetInfo) ? pTargetInfo->timeLastSeen : AI_INVALID_TIME; - float lastTimeDamagedBy = (pTargetInfo) ? pTargetInfo->timeLastReceivedDamageFrom : AI_INVALID_TIME; - - if ( timePlayerLastSeen == AI_INVALID_TIME || gpGlobals->curtime - timePlayerLastSeen > .15 ) // If didn't see the player last think - { - trace_t tr; - UTIL_TraceLine( pTarget->EyePosition(), GetOuter()->EyePosition(), MASK_BLOCKLOS, GetOuter(), COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction != 1.0 && tr.m_pEnt != pTarget ) - { - float dist = (tr.endpos - tr.startpos).Length() * tr.fraction; - - if ( dist < m_Params.coverDist ) - { - if ( ( timePlayerLastSeen == AI_INVALID_TIME || gpGlobals->curtime - timePlayerLastSeen > m_Params.timeToTrigger ) && - ( lastTimeDamagedBy == AI_INVALID_TIME || gpGlobals->curtime - lastTimeDamagedBy > m_Params.timeToTrigger ) ) - { - m_FreePassTimeRemaining = m_Params.duration; - m_FreePassMoveMonitor.SetMark( pTarget, m_Params.moveTolerance ); - } - } - } - } - } - else - { - float temp = m_FreePassTimeRemaining; - m_FreePassTimeRemaining = 0; - CAI_Senses *pSenses = GetOuter()->GetSenses(); - bool bCanSee = ( pSenses && pSenses->ShouldSeeEntity( pTarget ) && pSenses->CanSeeEntity( pTarget ) ); - m_FreePassTimeRemaining = temp; - - if ( bCanSee ) - { - if ( !m_FreePassMoveMonitor.TargetMoved( pTarget ) ) - m_FreePassTimeRemaining -= 0.1; - else - Revoke( true ); - } - else - { - m_FreePassTimeRemaining += 0.1 * m_Params.refillRate; - if ( m_FreePassTimeRemaining > m_Params.duration ) - m_FreePassTimeRemaining = m_Params.duration; - m_FreePassMoveMonitor.SetMark( pTarget, m_Params.moveTolerance ); - } - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CAI_FreePass::HasPass() -{ - return ( m_FreePassTimeRemaining > 0 ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CAI_FreePass::Revoke( bool bUpdateMemory ) -{ - m_FreePassTimeRemaining = 0; - if ( bUpdateMemory && GetPassTarget() ) - { - GetOuter()->UpdateEnemyMemory( GetPassTarget(), GetPassTarget()->GetAbsOrigin() ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CAI_FreePass::ShouldAllowFVisible(bool bBaseResult ) -{ - CBaseEntity * pTarget = GetPassTarget(); - AI_EnemyInfo_t *pTargetInfo = GetOuter()->GetEnemies()->Find( pTarget ); - - if ( !bBaseResult || HasPass() ) - return false; - - bool bIsVisible = true; - - // Peek logic - if ( m_Params.peekTime > 0.1 ) - { - float lastTimeSeen = (pTargetInfo) ? pTargetInfo->timeLastSeen : AI_INVALID_TIME; - float lastTimeDamagedBy = (pTargetInfo) ? pTargetInfo->timeLastReceivedDamageFrom : AI_INVALID_TIME; - - if ( ( lastTimeSeen == AI_INVALID_TIME || gpGlobals->curtime - lastTimeSeen > m_Params.peekTime ) && - ( lastTimeDamagedBy == AI_INVALID_TIME || gpGlobals->curtime - lastTimeDamagedBy > m_Params.peekTimeAfterDamage ) ) - { - Vector vToTarget; - - VectorSubtract( pTarget->EyePosition(), GetOuter()->EyePosition(), vToTarget ); - vToTarget.z = 0.0f; - VectorNormalize( vToTarget ); - - Vector vecRight( -vToTarget.y, vToTarget.x, 0.0f ); - trace_t tr; - - UTIL_TraceLine( GetOuter()->EyePosition(), pTarget->EyePosition() + (vecRight * m_Params.peekEyeDist - Vector( 0, 0, m_Params.peekEyeDistZ )), MASK_BLOCKLOS, GetOuter(), COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction != 1.0 && tr.m_pEnt != pTarget ) - { - if ( free_pass_peek_debug.GetBool() ) - NDebugOverlay::Line( tr.startpos, tr.endpos - Vector( 0, 0, 2), 0, 255, 0, false, 0.1 ); - bIsVisible = false; - } - - if ( bIsVisible ) - { - UTIL_TraceLine( GetOuter()->EyePosition(), pTarget->EyePosition() + (-vecRight * m_Params.peekEyeDist - Vector( 0, 0, m_Params.peekEyeDistZ )), MASK_BLOCKLOS, GetOuter(), COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction != 1.0 && tr.m_pEnt != pTarget ) - { - if ( free_pass_peek_debug.GetBool() ) - NDebugOverlay::Line( tr.startpos, tr.endpos - Vector( 0, 0, 2), 0, 255, 0, false, 0.1 ); - bIsVisible = false; - } - } - } - - if ( bIsVisible && free_pass_peek_debug.GetBool() ) - NDebugOverlay::Line( GetOuter()->EyePosition(), pTarget->EyePosition() - Vector( 0, 0, 2), 255, 0, 0, false, 0.1 ); - } - - return bIsVisible; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -string_t g_iszFuncBrushClassname = NULL_STRING; - -//----------------------------------------------------------------------------- -CTraceFilterNav::CTraceFilterNav( CAI_BaseNPC *pProber, bool bIgnoreTransientEntities, const IServerEntity *passedict, int collisionGroup, bool bAllowPlayerAvoid ) : - CTraceFilterSimple( passedict, collisionGroup ), - m_pProber(pProber), - m_bIgnoreTransientEntities(bIgnoreTransientEntities), - m_bAllowPlayerAvoid(bAllowPlayerAvoid) -{ - m_bCheckCollisionTable = g_EntityCollisionHash->IsObjectInHash( pProber ); -} - -//----------------------------------------------------------------------------- -bool CTraceFilterNav::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) -{ - IServerEntity *pServerEntity = (IServerEntity*)pHandleEntity; - CBaseEntity *pEntity = (CBaseEntity *)pServerEntity; - - if ( m_pProber == pEntity ) - return false; - - if ( m_pProber->GetMoveProbe()->ShouldBrushBeIgnored( pEntity ) == true ) - return false; - -#ifdef HL1_DLL - if ( ( contentsMask & CONTENTS_MOVEABLE ) == 0 ) - { - if ( pEntity->ClassMatches( "func_pushable" ) ) - return false; - } -#endif - - if ( m_bIgnoreTransientEntities && (pEntity->IsPlayer() || pEntity->IsNPC() ) ) - return false; - - //Adrian - If I'm flagged as using the new collision method, then ignore the player when trying - //to check if I can get somewhere. - if ( m_bAllowPlayerAvoid && m_pProber->ShouldPlayerAvoid() && pEntity->IsPlayer() ) - return false; - - if ( pEntity->IsNavIgnored() ) - return false; - - if ( m_bCheckCollisionTable ) - { - if ( g_EntityCollisionHash->IsObjectPairInHash( m_pProber, pEntity ) ) - return false; - } - - if ( m_pProber->ShouldProbeCollideAgainstEntity( pEntity ) == false ) - return false; - - return CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask ); -} diff --git a/game/server/ai_utils.h b/game/server/ai_utils.h deleted file mode 100644 index a89a9f5a5..000000000 --- a/game/server/ai_utils.h +++ /dev/null @@ -1,298 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Simple, small, free-standing tools for building AIs -// -//=============================================================================// - -#ifndef AI_UTILS_H -#define AI_UTILS_H - -#include "simtimer.h" -#include "ai_component.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -//----------------------------------------------------------------------------- -// -// Function to get the local player. AI does not want asserts or warnings, -// just NULL result -// -//----------------------------------------------------------------------------- - -inline CBasePlayer *AI_GetSinglePlayer() -{ - if ( gpGlobals->maxClients > 1 ) - { - return NULL; - } - - return UTIL_GetLocalPlayer(); -} - -inline bool AI_IsSinglePlayer() -{ - return ( gpGlobals->maxClients == 1 ); -} - - -//----------------------------------------------------------------------------- -// -// CAI_MoveMonitor -// -// Purpose: Watch an entity, trigger if moved more than a tolerance -// -//----------------------------------------------------------------------------- - -class CAI_MoveMonitor -{ -public: - CAI_MoveMonitor() - : m_vMark( 0, 0, 0 ), - m_flMarkTolerance( NO_MARK ) - { - } - - void SetMark( CBaseEntity *pEntity, float tolerance ) - { - if ( pEntity ) - { - m_vMark = pEntity->GetAbsOrigin(); - m_flMarkTolerance = tolerance; - } - } - - void ClearMark() - { - m_flMarkTolerance = NO_MARK; - } - - bool IsMarkSet() - { - return ( m_flMarkTolerance != NO_MARK ); - } - - bool TargetMoved( CBaseEntity *pEntity ) - { - if ( IsMarkSet() && pEntity != NULL ) - { - float distance = ( m_vMark - pEntity->GetAbsOrigin() ).Length(); - if ( distance > m_flMarkTolerance ) - return true; - } - return false; - } - - bool TargetMoved2D( CBaseEntity *pEntity ) - { - if ( IsMarkSet() && pEntity != NULL ) - { - float distance = ( m_vMark.AsVector2D() - pEntity->GetAbsOrigin().AsVector2D() ).Length(); - if ( distance > m_flMarkTolerance ) - return true; - } - return false; - } - - Vector GetMarkPos() { return m_vMark; } - -private: - enum - { - NO_MARK = -1 - }; - - Vector m_vMark; - float m_flMarkTolerance; - - DECLARE_SIMPLE_DATADESC(); -}; - - -//----------------------------------------------------------------------------- -// -// CAI_ShotRegulator -// -// Purpose: Assists in creating non-constant bursty shooting style -// -//----------------------------------------------------------------------------- -class CAI_ShotRegulator -{ -public: - CAI_ShotRegulator(); - - // Sets the various parameters for burst (this one's for backwards compatibility) - // NOTE: This will modify the next shot time - void SetParameters( int minShotsPerBurst, int maxShotsPerBurst, float minRestTime, float maxRestTime = 0.0 ); - - // NOTE: The next 3 methods will *not* modify the next shot time - // Sets the number of shots to shoot in a single burst - void SetBurstShotCountRange( int minShotsPerBurst, int maxShotsPerBurst ); - - // How much time should I rest between bursts? - void SetRestInterval( float flMinRestInterval, float flMaxRestInterval ); - - // How much time should I wait in between shots in a single burst? - void SetBurstInterval( float flMinBurstInterval, float flMaxBurstInterval ); - - // Poll the current parameters - void GetBurstShotCountRange( int *pMinShotsPerBurst, int *pMaxShotsPerBurst ) const; - void GetRestInterval( float *pMinRestInterval, float *pMaxRestInterval ) const; - void GetBurstInterval( float *pMinBurstInterval, float *pMaxBurstInterval ) const; - - // Reset the state. If true, the next burst time is set to now, - // otherwise it'll wait one rest interval before shooting - void Reset( bool bStartShooting = true ); - - // Should we shoot? - bool ShouldShoot() const; - - // When will I shoot next? - float NextShotTime() const; - - // Am I in the middle of a rest period? - bool IsInRestInterval() const; - - // NOTE: These will not modify the next shot time - int GetBurstShotsRemaining() const; - void SetBurstShotsRemaining( int shots ); - - // Call this when the NPC fired the weapon; - void OnFiredWeapon(); - - // Causes us to potentially delay our shooting time - void FireNoEarlierThan( float flTime ); - - // Prevent/Allow shooting - void EnableShooting( void ); - void DisableShooting( void ); - -private: - float m_flNextShotTime; - bool m_bInRestInterval; - unsigned short m_nBurstShotsRemaining; - unsigned short m_nMinBurstShots, m_nMaxBurstShots; - float m_flMinRestInterval, m_flMaxRestInterval; - float m_flMinBurstInterval, m_flMaxBurstInterval; - bool m_bDisabled; - - DECLARE_SIMPLE_DATADESC(); -}; - - -//----------------------------------------------------------------------------- -// -// CAI_AccelDecay -// -// Purpose: Maintain a smooth acceleration, deceleration curve -// -//----------------------------------------------------------------------------- - -class CAI_AccelDecay -{ -public: - CAI_AccelDecay(); - - void SetParameters( float minVelocity, float maxVelocity, float accelPercent, float decelPercent ); - float Update( float flCurrent, float flTarget, float flInterval ); - void ResetVelocity( float flVelocity = 0.0f ); - void SetMaxVelocity( float maxVelocity ); - -private: - float m_velocity; - - float m_maxVelocity; // = 300; - float m_minVelocity; // = 10; - - float m_invDecay; // 0.8 // maintain X percent of velocity when slowing down - float m_decayTime;// 0.4161 // Sum( 1..cycle, HEIGHTINVDECAY^cycle ) - float m_accel; // 0.5 // accel toward maxVelocity by X percent each cycle - - DECLARE_SIMPLE_DATADESC(); -}; - - - -//----------------------------------------------------------------------------- -// -// Purpose: Utility to allow place grace in cover -// -//----------------------------------------------------------------------------- - -struct AI_FreePassParams_t -{ - float timeToTrigger; // How long after not detected to issue pass - float duration; // How long in the open pass before revoked - float moveTolerance; // How far in open needed to move to revoke pass - float refillRate; // After hiding again during pass, how quickly to reinstitute pass(seconds per second) - float coverDist; // When hiding, how far from an obstructing object needed to be considered in cover - - float peekTime; // How long allowed to peek - float peekTimeAfterDamage; // How long allowed to peek after damaged by - float peekEyeDist; // how far spaced out the eyes are - float peekEyeDistZ; // how far below eye position to test eyes (handles peek up) - - DECLARE_SIMPLE_DATADESC(); -}; - -//------------------------------------- - -class CAI_FreePass : public CAI_Component -{ -public: - CAI_FreePass() - : m_FreePassTimeRemaining(0) - { - } - - void Reset( float passTime = -1, float moveTolerance = -1 ); - - void SetPassTarget( CBaseEntity *pTarget ) { m_hTarget = pTarget; m_FreePassTimeRemaining = 0; } - CBaseEntity * GetPassTarget() { return m_hTarget; } - - void SetParams( const AI_FreePassParams_t ¶ms ) { m_Params = params; } - const AI_FreePassParams_t &GetParams() const { return m_Params; } - - //--------------------------------- - // Free pass - //--------------------------------- - void Update(); - - bool HasPass(); - void Revoke( bool bUpdateMemory = false ); - - float GetTimeRemaining() { return m_FreePassTimeRemaining; } - void SetTimeRemaining( float passTime ) { m_FreePassTimeRemaining = passTime; } - - bool ShouldAllowFVisible( bool bBaseResult ); - -private: - EHANDLE m_hTarget; - - float m_FreePassTimeRemaining; - CAI_MoveMonitor m_FreePassMoveMonitor; - - AI_FreePassParams_t m_Params; - - DECLARE_SIMPLE_DATADESC(); -}; - -//----------------------------------------------------------------------------- - -class CTraceFilterNav : public CTraceFilterSimple -{ -public: - CTraceFilterNav( CAI_BaseNPC *pProber, bool bIgnoreTransientEntities, const IServerEntity *passedict, int collisionGroup, bool m_bAllowPlayerAvoid = true ); - bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ); - -private: - CAI_BaseNPC *m_pProber; - bool m_bIgnoreTransientEntities; - bool m_bCheckCollisionTable; - bool m_bAllowPlayerAvoid; -}; - -extern string_t g_iszFuncBrushClassname; - -#endif // AI_UTILS_H diff --git a/game/server/ai_waypoint.cpp b/game/server/ai_waypoint.cpp deleted file mode 100644 index 59503d9a0..000000000 --- a/game/server/ai_waypoint.cpp +++ /dev/null @@ -1,209 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "mempool.h" -#include "ai_navtype.h" -#include "ai_node.h" -#include "ai_waypoint.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define WAYPOINT_POOL_SIZE 512 - -//----------------------------------------------------------------------------- -// Init static variables -//----------------------------------------------------------------------------- - -DEFINE_FIXEDSIZE_ALLOCATOR( AI_Waypoint_t, WAYPOINT_POOL_SIZE, CMemoryPool::GROW_FAST ); - -//------------------------------------- - -BEGIN_SIMPLE_DATADESC( AI_Waypoint_t ) - - DEFINE_FIELD( vecLocation, FIELD_POSITION_VECTOR), - DEFINE_FIELD( flYaw, FIELD_FLOAT ), - // iNodeID (not saved, cannot rely on consistent mapping) - // flPathDistGoal (not saved ) - DEFINE_FIELD( hPathCorner, FIELD_EHANDLE ), - DEFINE_FIELD( m_hData, FIELD_EHANDLE ), - DEFINE_FIELD( m_fWaypointFlags, FIELD_INTEGER ), - DEFINE_FIELD( m_iWPType, FIELD_INTEGER ), - // pNext - // pPrev - -END_DATADESC() - -//------------------------------------- - -AI_Waypoint_t::AI_Waypoint_t() -{ - memset( this, 0, sizeof(*this) ); - vecLocation = vec3_invalid; - iNodeID = NO_NODE; - flPathDistGoal = -1; -} - -//------------------------------------- - -AI_Waypoint_t::AI_Waypoint_t( const Vector &initPosition, float initYaw, Navigation_t initNavType, int initWaypointFlags, int initNodeID ) -{ - memset( this, 0, sizeof(*this) ); - - // A Route of length one to the endpoint - vecLocation = initPosition; - flYaw = initYaw; - m_iWPType = initNavType; - m_fWaypointFlags = initWaypointFlags; - iNodeID = initNodeID; - - flPathDistGoal = -1; -} - -//------------------------------------- - -AI_Waypoint_t * AI_Waypoint_t::GetLast() -{ - Assert( !pNext || pNext->pPrev == this ); - AI_Waypoint_t *pCurr = this; - while (pCurr->GetNext()) - { - pCurr = pCurr->GetNext(); - } - - return pCurr; -} - - -//----------------------------------------------------------------------------- - -void CAI_WaypointList::RemoveAll() -{ - DeleteAll( &m_pFirstWaypoint ); - Assert( m_pFirstWaypoint == NULL ); -} - -//------------------------------------- - -void CAI_WaypointList::PrependWaypoints( AI_Waypoint_t *pWaypoints ) -{ - AddWaypointLists( pWaypoints, GetFirst() ); - Set( pWaypoints ); -} - -//------------------------------------- - -void CAI_WaypointList::PrependWaypoint( const Vector &newPoint, Navigation_t navType, unsigned waypointFlags, float flYaw ) -{ - PrependWaypoints( new AI_Waypoint_t( newPoint, flYaw, navType, waypointFlags, NO_NODE ) ); -} - -//------------------------------------- - -void CAI_WaypointList::Set(AI_Waypoint_t* route) -{ - m_pFirstWaypoint = route; -} - -//------------------------------------- - -AI_Waypoint_t *CAI_WaypointList::GetLast() -{ - AI_Waypoint_t *p = GetFirst(); - if (!p) - return NULL; - while ( p->GetNext() ) - p = p->GetNext(); - - return p; -} - -//------------------------------------- - -const AI_Waypoint_t *CAI_WaypointList::GetLast() const -{ - return const_cast(this)->GetLast(); -} - -//------------------------------------- - -#ifdef DEBUG -void AssertRouteValid( AI_Waypoint_t* route ) -{ - // Check that the goal wasn't just clobbered - if (route) - { - AI_Waypoint_t* waypoint = route; - - while (waypoint) - { -#ifdef _GOALDEBUG - if (!waypoint->GetNext() && !(waypoint->Flags() & (bits_WP_TO_GOAL|bits_WP_TO_PATHCORNER))) - { - DevMsg( "!!ERROR!! Final waypoint is not a goal!\n"); - } -#endif - waypoint->AssertValid(); - waypoint = waypoint->GetNext(); - } - } -} -#endif - -//----------------------------------------------------------------------------- -// Purpose: Deletes a waypoint linked list -//----------------------------------------------------------------------------- -void DeleteAll( AI_Waypoint_t *pWaypointList ) -{ - while ( pWaypointList ) - { - AI_Waypoint_t *pPrevWaypoint = pWaypointList; - pWaypointList = pWaypointList->GetNext(); - delete pPrevWaypoint; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Adds addRoute to the end of oldRoute -//----------------------------------------------------------------------------- -void AddWaypointLists(AI_Waypoint_t *oldRoute, AI_Waypoint_t *addRoute) -{ - // Add to the end of the route - AI_Waypoint_t *waypoint = oldRoute; - - while (waypoint->GetNext()) - { - waypoint = waypoint->GetNext(); - } - - waypoint->ModifyFlags( bits_WP_TO_GOAL, false ); - - // Check for duplication, but copy the type - if (waypoint->iNodeID != NO_NODE && - waypoint->iNodeID == addRoute->iNodeID ) - { -// waypoint->iWPType = addRoute->iWPType; <> found case where this was bad - AI_Waypoint_t *pNext = addRoute->GetNext(); - delete addRoute; - waypoint->SetNext(pNext); - } - else - { - waypoint->SetNext(addRoute); - } - - while (waypoint->GetNext()) - { - waypoint = waypoint->GetNext(); - } - - waypoint->ModifyFlags( bits_WP_TO_GOAL, true ); - -} - -//----------------------------------------------------------------------------- diff --git a/game/server/ai_waypoint.h b/game/server/ai_waypoint.h deleted file mode 100644 index 966b059d9..000000000 --- a/game/server/ai_waypoint.h +++ /dev/null @@ -1,258 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_WAYPOINT_H -#define AI_WAYPOINT_H - -#if defined( _WIN32 ) -#pragma once -#endif - -#include - -// ---------------------------------------------------------------------------- -// Forward declarations -// ---------------------------------------------------------------------------- - -// ---------------------------------------------------------------------------- -// Flags used in the flags field in AI_Waypoint_T -// ---------------------------------------------------------------------------- -enum WaypointFlags_t -{ - // The type of waypoint - bits_WP_TO_DETOUR = 0x01, // move to detour point. - bits_WP_TO_PATHCORNER = 0x02, // move to a path corner - bits_WP_TO_NODE = 0x04, // move to a node - bits_WP_TO_GOAL = 0x08, // move to an arbitrary point - bits_WP_TO_DOOR = 0x10, // move to position to open a door - - // Other flags for waypoint - bits_WP_DONT_SIMPLIFY = 0x20, // Don't let the route code simplify this waypoint -}; - -// ---------------------------------------------------------------------------- -// Purpose: Waypoints that make up an NPC's route. -// ---------------------------------------------------------------------------- -struct AI_Waypoint_t -{ -public: - AI_Waypoint_t(); - AI_Waypoint_t( const Vector &vecPosition, float flYaw, Navigation_t navType, int fWaypointFlags, int nNodeID ); - AI_Waypoint_t( const AI_Waypoint_t &from ) - { - memcpy( this, &from, sizeof(*this) ); - flPathDistGoal = -1; - pNext = pPrev = NULL; - } - - AI_Waypoint_t &operator=( const AI_Waypoint_t &from ) - { - memcpy( this, &from, sizeof(*this) ); - flPathDistGoal = -1; - pNext = pPrev = NULL; - return *this; - } - - ~AI_Waypoint_t() - { - AssertValid(); - if ( pNext ) - { - pNext->AssertValid(); - pNext->pPrev = pPrev; - } - if ( pPrev ) - { - pPrev->AssertValid(); - pPrev->pNext = pNext; - } - } - - //--------------------------------- - - void AssertValid() const - { -#ifdef DEBUG - Assert( !pNext || pNext->pPrev == this ); - Assert( !pPrev || pPrev->pNext == this ); -#endif - } - - - //--------------------------------- - - int Flags() const; - Navigation_t NavType() const; - - // Flag modification method - void ModifyFlags( int fFlags, bool bEnable ); - - bool IsReducible() { return (pNext && m_iWPType == pNext->m_iWPType && !(m_fWaypointFlags & (bits_WP_TO_GOAL | bits_WP_TO_PATHCORNER | bits_WP_DONT_SIMPLIFY)) ); } - - //--------------------------------- - - void SetNext( AI_Waypoint_t *p ); - AI_Waypoint_t * GetNext() { return pNext; } - const AI_Waypoint_t *GetNext() const { return pNext; } - - AI_Waypoint_t * GetPrev() { return pPrev; } - const AI_Waypoint_t *GetPrev() const { return pPrev; } - - AI_Waypoint_t * GetLast(); - - //--------------------------------- - - const Vector & GetPos() const { return vecLocation; } - void SetPos(const Vector &newPos) { vecLocation = newPos; } - - EHANDLE GetEHandleData() { return m_hData; } - - //--------------------------------- - // - // Basic info - // - Vector vecLocation; - float flYaw; // Waypoint facing dir - int iNodeID; // If waypoint is a node, which one - - //--------------------------------- - // - // Precalculated distances - // - float flPathDistGoal; - - //--------------------------------- - // - // If following a designer laid path, the path-corner entity (if any) - // - EHANDLE hPathCorner; - - // Data specific to the waypoint type: - // - // PATHCORNER: The path corner entity. - // DOOR: If moving to position to open a door, the handle of the door to open. - EHANDLE m_hData; - -private: - int m_fWaypointFlags; // See WaypointFlags_t - Navigation_t m_iWPType; // The type of waypoint - - AI_Waypoint_t *pNext; - AI_Waypoint_t *pPrev; - - DECLARE_FIXEDSIZE_ALLOCATOR(AI_Waypoint_t); - -public: - DECLARE_SIMPLE_DATADESC(); -}; - - -// ---------------------------------------------------------------------------- -// Inline methods associated with AI_Waypoint_t -// ---------------------------------------------------------------------------- -inline int AI_Waypoint_t::Flags() const -{ - return m_fWaypointFlags; -} - -inline Navigation_t AI_Waypoint_t::NavType() const -{ - return m_iWPType; -} - -inline void AI_Waypoint_t::ModifyFlags( int fFlags, bool bEnable ) -{ - if (bEnable) - m_fWaypointFlags |= fFlags; - else - m_fWaypointFlags &= ~fFlags; -} - -inline void AI_Waypoint_t::SetNext( AI_Waypoint_t *p ) -{ - if (pNext) - { - pNext->pPrev = NULL; - } - - pNext = p; - - if ( pNext ) - { - if ( pNext->pPrev ) - pNext->pPrev->pNext = NULL; - - pNext->pPrev = this; - } -} - - -// ---------------------------------------------------------------------------- -// Purpose: Holds an maintains a chain of waypoints - -class CAI_WaypointList -{ -public: - CAI_WaypointList() - : m_pFirstWaypoint( NULL ) - { - } - - CAI_WaypointList( AI_Waypoint_t *pFirstWaypoint) - : m_pFirstWaypoint( pFirstWaypoint ) - { - } - - void Set(AI_Waypoint_t* route); - - void PrependWaypoints( AI_Waypoint_t *pWaypoints ); - void PrependWaypoint( const Vector &newPoint, Navigation_t navType, unsigned waypointFlags, float flYaw = 0 ); - - bool IsEmpty() const { return ( m_pFirstWaypoint == NULL ); } - - AI_Waypoint_t * GetFirst() { return m_pFirstWaypoint; } - const AI_Waypoint_t *GetFirst() const { return m_pFirstWaypoint; } - - AI_Waypoint_t * GetLast(); - const AI_Waypoint_t *GetLast() const; - - void RemoveAll(); - -private: - - AI_Waypoint_t* m_pFirstWaypoint; // Linked list of waypoints -}; - -// ---------------------------------------------------------------------------- -#ifdef DEBUG -void AssertRouteValid( AI_Waypoint_t* route ); -#else -#define AssertRouteValid( route ) ((void)0) -#endif - -// ---------------------------------------------------------------------------- -// Utilities - -void DeleteAll( AI_Waypoint_t *pWaypointList ); - -// ------------------------------------ - -inline void DeleteAll( AI_Waypoint_t **ppWaypointList ) -{ - DeleteAll( *ppWaypointList ); - *ppWaypointList = NULL; -} - -// ------------------------------------ - -void AddWaypointLists(AI_Waypoint_t *pLeft, AI_Waypoint_t *pRight); - -// ---------------------------------------------------------------------------- - - - -#endif // AI_WAYPOINT_H diff --git a/game/server/base_gameinterface.cpp b/game/server/base_gameinterface.cpp deleted file mode 100644 index 4a556683d..000000000 --- a/game/server/base_gameinterface.cpp +++ /dev/null @@ -1,27 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "gameinterface.h" -#include "mapentities.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -void CServerGameClients::GetPlayerLimits( int& minplayers, int& maxplayers, int &defaultMaxPlayers ) const -{ - minplayers = defaultMaxPlayers = 1; - maxplayers = MAX_PLAYERS; -} - - -// -------------------------------------------------------------------------------------------- // -// Mod-specific CServerGameDLL implementation. -// -------------------------------------------------------------------------------------------- // - -void CServerGameDLL::LevelInit_ParseAllEntities( const char *pMapEntities ) -{ -} diff --git a/game/server/base_transmit_proxy.cpp b/game/server/base_transmit_proxy.cpp deleted file mode 100644 index 8e4e930bb..000000000 --- a/game/server/base_transmit_proxy.cpp +++ /dev/null @@ -1,60 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "base_transmit_proxy.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -CBaseTransmitProxy::CBaseTransmitProxy( CBaseEntity *pEnt ) -{ - m_hEnt = pEnt; - m_refCount = 0; -} - - -CBaseTransmitProxy::~CBaseTransmitProxy() -{ - // Unlink from our parent entity. - if ( m_hEnt ) - { - m_refCount = 0xFFFF; // Prevent us from deleting ourselves again. - // m_hEnt->NetworkProp()->SetTransmitProxy( NULL ); - } -} - - -int CBaseTransmitProxy::ShouldTransmit( const CCheckTransmitInfo *pInfo, int nPrevShouldTransmitResult ) -{ - // Anyone implementing a transmit proxy should override this since that's the point!! - Assert( false ); - return FL_EDICT_DONTSEND; -} - - -void CBaseTransmitProxy::AddRef() -{ - m_refCount++; -} - - -void CBaseTransmitProxy::Release() -{ - if ( m_refCount == 0xFFFF ) - { - // This means we are inside our destructor already, so we don't want to do anything here. - } - else if ( m_refCount <= 1 ) - { - delete this; - } - else - { - --m_refCount; - } -} - diff --git a/game/server/base_transmit_proxy.h b/game/server/base_transmit_proxy.h deleted file mode 100644 index 93b723740..000000000 --- a/game/server/base_transmit_proxy.h +++ /dev/null @@ -1,41 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef BASE_TRANSMIT_PROXY_H -#define BASE_TRANSMIT_PROXY_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "ehandle.h" - - -class CBaseEntity; - - -class CBaseTransmitProxy -{ -public: - - CBaseTransmitProxy( CBaseEntity *pEnt ); - virtual ~CBaseTransmitProxy(); - - // Override this to control the ShouldTransmit behavior of whatever entity the proxy is attached to. - // bPrevShouldTransmitResult is what the proxy's entity's ShouldTransmit() returned. - virtual int ShouldTransmit( const CCheckTransmitInfo *pInfo, int nPrevShouldTransmitResult ); - - - void AddRef(); - void Release(); - -private: - EHANDLE m_hEnt; - unsigned short m_refCount; -}; - - -#endif // BASE_TRANSMIT_PROXY_H diff --git a/game/server/baseanimating.cpp b/game/server/baseanimating.cpp deleted file mode 100644 index a8b5261a6..000000000 --- a/game/server/baseanimating.cpp +++ /dev/null @@ -1,3530 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Base class for all animating characters and objects. -// -//=============================================================================// - -#include "cbase.h" -#include "baseanimating.h" -#include "animation.h" -#include "activitylist.h" -#include "studio.h" -#include "bone_setup.h" -#include "mathlib/mathlib.h" -#include "model_types.h" -#include "datacache/imdlcache.h" -#include "physics.h" -#include "ndebugoverlay.h" -#include "tier1/strtools.h" -#include "npcevent.h" -#include "isaverestore.h" -#include "KeyValues.h" -#include "tier0/vprof.h" -#include "EntityFlame.h" -#include "EntityDissolve.h" -#include "ai_basenpc.h" -#include "physics_prop_ragdoll.h" -#include "datacache/idatacache.h" -#include "smoke_trail.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar ai_sequence_debug( "ai_sequence_debug", "0" ); - -class CIKSaveRestoreOps : public CClassPtrSaveRestoreOps -{ - // save data type interface - void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave ) - { - Assert( fieldInfo.pTypeDesc->fieldSize == 1 ); - CIKContext **pIK = (CIKContext **)fieldInfo.pField; - bool bHasIK = (*pIK) != 0; - pSave->WriteBool( &bHasIK ); - } - - void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore ) - { - Assert( fieldInfo.pTypeDesc->fieldSize == 1 ); - CIKContext **pIK = (CIKContext **)fieldInfo.pField; - - bool bHasIK; - pRestore->ReadBool( &bHasIK ); - *pIK = (bHasIK) ? new CIKContext : NULL; - } -}; - -//----------------------------------------------------------------------------- -// Relative lighting entity -//----------------------------------------------------------------------------- -class CInfoLightingRelative : public CBaseEntity -{ -public: - DECLARE_CLASS( CInfoLightingRelative, CBaseEntity ); - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - virtual void Activate(); - virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ); - virtual int UpdateTransmitState( void ); - -private: - CNetworkHandle( CBaseEntity, m_hLightingLandmark ); - string_t m_strLightingLandmark; -}; - -LINK_ENTITY_TO_CLASS( info_lighting_relative, CInfoLightingRelative ); - -BEGIN_DATADESC( CInfoLightingRelative ) - DEFINE_KEYFIELD( m_strLightingLandmark, FIELD_STRING, "LightingLandmark" ), - DEFINE_FIELD( m_hLightingLandmark, FIELD_EHANDLE ), -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST(CInfoLightingRelative, DT_InfoLightingRelative) - SendPropEHandle( SENDINFO( m_hLightingLandmark ) ), -END_SEND_TABLE() - - -//----------------------------------------------------------------------------- -// Activate! -//----------------------------------------------------------------------------- -void CInfoLightingRelative::Activate() -{ - BaseClass::Activate(); - if ( m_strLightingLandmark == NULL_STRING ) - { - m_hLightingLandmark = NULL; - } - else - { - m_hLightingLandmark = gEntList.FindEntityByName( NULL, m_strLightingLandmark ); - if ( !m_hLightingLandmark ) - { - DevWarning( "%s: Could not find lighting landmark '%s'!\n", GetClassname(), STRING( m_strLightingLandmark ) ); - } - else - { - // Set a force transmit because we do not have a model. - m_hLightingLandmark->AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); - } - } -} - - -//----------------------------------------------------------------------------- -// Force our lighting landmark to be transmitted -//----------------------------------------------------------------------------- -void CInfoLightingRelative::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ) -{ - // Are we already marked for transmission? - if ( pInfo->m_pTransmitEdict->Get( entindex() ) ) - return; - - BaseClass::SetTransmit( pInfo, bAlways ); - - // Force our constraint entity to be sent too. - if ( m_hLightingLandmark ) - { - if ( m_hLightingLandmark->GetMoveParent() ) - { - // Set a full check because we have a move parent. - m_hLightingLandmark->SetTransmitState( FL_EDICT_FULLCHECK ); - } - else - { - m_hLightingLandmark->SetTransmitState( FL_EDICT_ALWAYS ); - } - - m_hLightingLandmark->SetTransmit( pInfo, bAlways ); - } -} - -//----------------------------------------------------------------------------- -// Purpose Force our lighting landmark to be transmitted -//----------------------------------------------------------------------------- -int CInfoLightingRelative::UpdateTransmitState( void ) -{ - return SetTransmitState( FL_EDICT_ALWAYS ); -} - -static CIKSaveRestoreOps s_IKSaveRestoreOp; - - -BEGIN_DATADESC( CBaseAnimating ) - - DEFINE_FIELD( m_flGroundSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_flLastEventCheck, FIELD_TIME ), - DEFINE_FIELD( m_bSequenceFinished, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bSequenceLoops, FIELD_BOOLEAN ), - -// DEFINE_FIELD( m_nForceBone, FIELD_INTEGER ), -// DEFINE_FIELD( m_vecForce, FIELD_VECTOR ), - - DEFINE_INPUT( m_nSkin, FIELD_INTEGER, "skin" ), - DEFINE_KEYFIELD( m_nBody, FIELD_INTEGER, "body" ), - DEFINE_INPUT( m_nBody, FIELD_INTEGER, "SetBodyGroup" ), - DEFINE_KEYFIELD( m_nHitboxSet, FIELD_INTEGER, "hitboxset" ), - DEFINE_KEYFIELD( m_nSequence, FIELD_INTEGER, "sequence" ), - DEFINE_ARRAY( m_flPoseParameter, FIELD_FLOAT, CBaseAnimating::NUM_POSEPAREMETERS ), - DEFINE_ARRAY( m_flEncodedController, FIELD_FLOAT, CBaseAnimating::NUM_BONECTRLS ), - DEFINE_KEYFIELD( m_flPlaybackRate, FIELD_FLOAT, "playbackrate" ), - DEFINE_KEYFIELD( m_flCycle, FIELD_FLOAT, "cycle" ), -// DEFINE_FIELD( m_flIKGroundContactTime, FIELD_TIME ), -// DEFINE_FIELD( m_flIKGroundMinHeight, FIELD_FLOAT ), -// DEFINE_FIELD( m_flIKGroundMaxHeight, FIELD_FLOAT ), -// DEFINE_FIELD( m_flEstIkFloor, FIELD_FLOAT ), -// DEFINE_FIELD( m_flEstIkOffset, FIELD_FLOAT ), -// DEFINE_FIELD( m_pStudioHdr, CStudioHdr ), -// DEFINE_FIELD( m_StudioHdrInitLock, CThreadFastMutex ), -// DEFINE_FIELD( m_BoneSetupMutex, CThreadFastMutex ), - DEFINE_CUSTOM_FIELD( m_pIk, &s_IKSaveRestoreOp ), - DEFINE_FIELD( m_iIKCounter, FIELD_INTEGER ), - DEFINE_FIELD( m_bClientSideAnimation, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bClientSideFrameReset, FIELD_BOOLEAN ), - DEFINE_FIELD( m_nNewSequenceParity, FIELD_INTEGER ), - DEFINE_FIELD( m_nResetEventsParity, FIELD_INTEGER ), - DEFINE_FIELD( m_nMuzzleFlashParity, FIELD_CHARACTER ), - - DEFINE_KEYFIELD( m_iszLightingOriginRelative, FIELD_STRING, "LightingOriginHack" ), - DEFINE_KEYFIELD( m_iszLightingOrigin, FIELD_STRING, "LightingOrigin" ), - - DEFINE_FIELD( m_hLightingOrigin, FIELD_EHANDLE ), - DEFINE_FIELD( m_hLightingOriginRelative, FIELD_EHANDLE ), - - DEFINE_FIELD( m_flModelWidthScale, FIELD_FLOAT ), - DEFINE_FIELD( m_flDissolveStartTime, FIELD_TIME ), - - // DEFINE_FIELD( m_boneCacheHandle, memhandle_t ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Ignite", InputIgnite ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "IgniteLifetime", InputIgniteLifetime ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "IgniteNumHitboxFires", InputIgniteNumHitboxFires ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "IgniteHitboxFireScale", InputIgniteHitboxFireScale ), - DEFINE_INPUTFUNC( FIELD_VOID, "BecomeRagdoll", InputBecomeRagdoll ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetLightingOriginHack", InputSetLightingOriginRelative ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetLightingOrigin", InputSetLightingOrigin ), - DEFINE_OUTPUT( m_OnIgnite, "OnIgnite" ), - - DEFINE_INPUT( m_fadeMinDist, FIELD_FLOAT, "fademindist" ), - DEFINE_INPUT( m_fadeMaxDist, FIELD_FLOAT, "fademaxdist" ), - DEFINE_KEYFIELD( m_flFadeScale, FIELD_FLOAT, "fadescale" ), - - DEFINE_FIELD( m_fBoneCacheFlags, FIELD_SHORT ), - - END_DATADESC() - -// Sendtable for fields we don't want to send to clientside animating entities -BEGIN_SEND_TABLE_NOBASE( CBaseAnimating, DT_ServerAnimationData ) - // ANIMATION_CYCLE_BITS is defined in shareddefs.h - SendPropFloat (SENDINFO(m_flCycle), ANIMATION_CYCLE_BITS, SPROP_CHANGES_OFTEN|SPROP_ROUNDDOWN, 0.0f, 1.0f) -END_SEND_TABLE() - -void *SendProxy_ClientSideAnimation( const SendProp *pProp, const void *pStruct, const void *pVarData, CSendProxyRecipients *pRecipients, int objectID ); - -// SendTable stuff. -IMPLEMENT_SERVERCLASS_ST(CBaseAnimating, DT_BaseAnimating) - SendPropInt ( SENDINFO(m_nForceBone), 8, 0 ), - SendPropVector ( SENDINFO(m_vecForce), -1, SPROP_NOSCALE ), - - SendPropInt ( SENDINFO(m_nSkin), ANIMATION_SKIN_BITS), - SendPropInt ( SENDINFO(m_nBody), ANIMATION_BODY_BITS), - - SendPropInt ( SENDINFO(m_nHitboxSet),ANIMATION_HITBOXSET_BITS, SPROP_UNSIGNED ), - - SendPropFloat ( SENDINFO(m_flModelWidthScale), 6, SPROP_ROUNDUP, 0.0f, 1.0f ), - - SendPropArray3 ( SENDINFO_ARRAY3(m_flPoseParameter), SendPropFloat(SENDINFO_ARRAY(m_flPoseParameter), ANIMATION_POSEPARAMETER_BITS, 0, 0.0f, 1.0f ) ), - - SendPropInt ( SENDINFO(m_nSequence), ANIMATION_SEQUENCE_BITS, SPROP_UNSIGNED ), - SendPropFloat ( SENDINFO(m_flPlaybackRate), ANIMATION_PLAYBACKRATE_BITS, SPROP_ROUNDUP, -4.0, 12.0f ), // NOTE: if this isn't a power of 2 than "1.0" can't be encoded correctly - - SendPropArray3 (SENDINFO_ARRAY3(m_flEncodedController), SendPropFloat(SENDINFO_ARRAY(m_flEncodedController), 11, SPROP_ROUNDDOWN, 0.0f, 1.0f ) ), - - SendPropInt( SENDINFO( m_bClientSideAnimation ), 1, SPROP_UNSIGNED ), - SendPropInt( SENDINFO( m_bClientSideFrameReset ), 1, SPROP_UNSIGNED ), - - SendPropInt( SENDINFO( m_nNewSequenceParity ), EF_PARITY_BITS, SPROP_UNSIGNED|SPROP_CHANGES_OFTEN ), - SendPropInt( SENDINFO( m_nResetEventsParity ), EF_PARITY_BITS, SPROP_UNSIGNED|SPROP_CHANGES_OFTEN ), - SendPropInt( SENDINFO( m_nMuzzleFlashParity ), EF_MUZZLEFLASH_BITS, SPROP_UNSIGNED|SPROP_CHANGES_OFTEN ), - - SendPropEHandle( SENDINFO( m_hLightingOrigin ) ), - SendPropEHandle( SENDINFO( m_hLightingOriginRelative ) ), - - SendPropDataTable( "serveranimdata", 0, &REFERENCE_SEND_TABLE( DT_ServerAnimationData ), SendProxy_ClientSideAnimation ), - - // Fading - SendPropFloat( SENDINFO( m_fadeMinDist ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO( m_fadeMaxDist ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO( m_flFadeScale ), 0, SPROP_NOSCALE ), - -END_SEND_TABLE() - - -CBaseAnimating::CBaseAnimating() -{ - m_vecForce.GetForModify().Init(); - m_nForceBone = 0; - - m_bClientSideAnimation = false; - m_pIk = NULL; - m_iIKCounter = 0; - - InitStepHeightAdjust(); - - m_flModelWidthScale = 1.0f; - // initialize anim clock - m_flAnimTime = gpGlobals->curtime; - m_flPrevAnimTime = gpGlobals->curtime; - m_nNewSequenceParity = 0; - m_nResetEventsParity = 0; - m_boneCacheHandle = 0; - m_pStudioHdr = NULL; - m_fadeMinDist = 0; - m_fadeMaxDist = 0; - m_flFadeScale = 0.0f; - m_fBoneCacheFlags = 0; -} - -CBaseAnimating::~CBaseAnimating() -{ - Studio_DestroyBoneCache( m_boneCacheHandle ); - delete m_pIk; - UnlockStudioHdr(); - delete m_pStudioHdr; -} - -void CBaseAnimating::Precache() -{ -#if !defined( TF_DLL ) - // Anything derived from this class can potentially burn - true, but do we want it to! - PrecacheParticleSystem( "burning_character" ); -#endif - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Activate! -//----------------------------------------------------------------------------- -void CBaseAnimating::Activate() -{ - BaseClass::Activate(); - SetLightingOrigin( m_iszLightingOrigin ); - SetLightingOriginRelative( m_iszLightingOriginRelative ); -} - - -//----------------------------------------------------------------------------- -// Force our lighting origin to be trasmitted -//----------------------------------------------------------------------------- -void CBaseAnimating::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ) -{ - // Are we already marked for transmission? - if ( pInfo->m_pTransmitEdict->Get( entindex() ) ) - return; - - BaseClass::SetTransmit( pInfo, bAlways ); - - // Force our lighting entities to be sent too. - if ( m_hLightingOrigin ) - { - m_hLightingOrigin->SetTransmit( pInfo, bAlways ); - } - if ( m_hLightingOriginRelative ) - { - m_hLightingOriginRelative->SetTransmit( pInfo, bAlways ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CBaseAnimating::Restore( IRestore &restore ) -{ - int result = BaseClass::Restore( restore ); - LockStudioHdr(); - return result; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CBaseAnimating::OnRestore() -{ - BaseClass::OnRestore(); - - if ( m_nSequence != -1 && GetModelPtr() && !IsValidSequence( m_nSequence ) ) - m_nSequence = 0; - - m_flEstIkFloor = GetLocalOrigin().z; - PopulatePoseParameters(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CBaseAnimating::Spawn() -{ - BaseClass::Spawn(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CBaseAnimating::UseClientSideAnimation() -{ - m_bClientSideAnimation = true; -} - -#define MAX_ANIMTIME_INTERVAL 0.2f - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CBaseAnimating::GetAnimTimeInterval( void ) const -{ - float flInterval; - if (m_flAnimTime < gpGlobals->curtime) - { - // estimate what it'll be this frame - flInterval = clamp( gpGlobals->curtime - m_flAnimTime, 0, MAX_ANIMTIME_INTERVAL ); - } - else - { - // report actual - flInterval = clamp( m_flAnimTime - m_flPrevAnimTime, 0, MAX_ANIMTIME_INTERVAL ); - } - return flInterval; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseAnimating::StudioFrameAdvanceInternal( CStudioHdr *pStudioHdr, float flCycleDelta ) -{ - float flNewCycle = GetCycle() + flCycleDelta; - if (flNewCycle < 0.0 || flNewCycle >= 1.0) - { - if (m_bSequenceLoops) - { - flNewCycle -= (int)(flNewCycle); - } - else - { - flNewCycle = (flNewCycle < 0.0f) ? 0.0f : 1.0f; - } - m_bSequenceFinished = true; // just in case it wasn't caught in GetEvents - } - else if (flNewCycle > GetLastVisibleCycle( pStudioHdr, GetSequence() )) - { - m_bSequenceFinished = true; - } - - SetCycle( flNewCycle ); - - /* - if (!IsPlayer()) - Msg("%s %6.3f : %6.3f %6.3f (%.3f) %.3f\n", - GetClassname(), gpGlobals->curtime, - m_flAnimTime.Get(), m_flPrevAnimTime, flInterval, GetCycle() ); - */ - - m_flGroundSpeed = GetSequenceGroundSpeed( pStudioHdr, GetSequence() ); - - // Msg("%s : %s : %5.1f\n", GetClassname(), GetSequenceName( GetSequence() ), GetCycle() ); - InvalidatePhysicsRecursive( ANIMATION_CHANGED ); - - InvalidateBoneCacheIfOlderThan( 0 ); -} - -void CBaseAnimating::InvalidateBoneCacheIfOlderThan( float deltaTime ) -{ - CBoneCache *pcache = Studio_GetBoneCache( m_boneCacheHandle ); - if ( !pcache || !pcache->IsValid( gpGlobals->curtime, deltaTime ) ) - { - InvalidateBoneCache(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseAnimating::StudioFrameAdvanceManual( float flInterval ) -{ - CStudioHdr *pStudioHdr = GetModelPtr(); - if ( !pStudioHdr ) - return; - - UpdateModelWidthScale(); - m_flAnimTime = gpGlobals->curtime; - m_flPrevAnimTime = m_flAnimTime - flInterval; - float flCycleRate = GetSequenceCycleRate( pStudioHdr, GetSequence() ) * m_flPlaybackRate; - StudioFrameAdvanceInternal( GetModelPtr(), flInterval * flCycleRate ); -} - - -//========================================================= -// StudioFrameAdvance - advance the animation frame up some interval (default 0.1) into the future -//========================================================= -void CBaseAnimating::StudioFrameAdvance() -{ - CStudioHdr *pStudioHdr = GetModelPtr(); - - if ( !pStudioHdr || !pStudioHdr->SequencesAvailable() ) - { - return; - } - - UpdateModelWidthScale(); - - if ( !m_flPrevAnimTime ) - { - m_flPrevAnimTime = m_flAnimTime; - } - - // Time since last animation - float flInterval = gpGlobals->curtime - m_flAnimTime; - flInterval = clamp( flInterval, 0, MAX_ANIMTIME_INTERVAL ); - - //Msg( "%i %s interval %f\n", entindex(), GetClassname(), flInterval ); - if (flInterval <= 0.001) - { - // Msg("%s : %s : %5.3f (skip)\n", GetClassname(), GetSequenceName( GetSequence() ), GetCycle() ); - return; - } - - // Latch prev - m_flPrevAnimTime = m_flAnimTime; - // Set current - m_flAnimTime = gpGlobals->curtime; - - // Drive cycle - float flCycleRate = GetSequenceCycleRate( pStudioHdr, GetSequence() ) * m_flPlaybackRate; - - StudioFrameAdvanceInternal( pStudioHdr, flInterval * flCycleRate ); - - if (ai_sequence_debug.GetBool() == true && m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) - { - Msg("%5.2f : %s : %s : %5.3f\n", gpGlobals->curtime, GetClassname(), GetSequenceName( GetSequence() ), GetCycle() ); - } -} - - -//----------------------------------------------------------------------------- -// Set the relative lighting origin -//----------------------------------------------------------------------------- -void CBaseAnimating::SetLightingOriginRelative( string_t strLightingOriginRelative ) -{ - if ( strLightingOriginRelative == NULL_STRING ) - { - SetLightingOriginRelative( NULL ); - } - else - { - CBaseEntity *pLightingOrigin = gEntList.FindEntityByName( NULL, strLightingOriginRelative ); - if ( !pLightingOrigin ) - { - DevWarning( "%s: Could not find info_lighting_relative '%s'!\n", GetClassname(), STRING( strLightingOriginRelative ) ); - return; - } - else if ( !dynamic_cast(pLightingOrigin) ) - { - if( !pLightingOrigin ) - { - DevWarning( "%s: Cannot find Lighting Origin named: %s\n", GetEntityName().ToCStr(), STRING(strLightingOriginRelative) ); - } - else - { - DevWarning( "%s: Specified entity '%s' must be a info_lighting_relative!\n", - pLightingOrigin->GetClassname(), pLightingOrigin->GetEntityName().ToCStr() ); - } - return; - } - - SetLightingOriginRelative( pLightingOrigin ); - } - - // Save the name so that save/load will correctly restore it in Activate() - m_iszLightingOriginRelative = strLightingOriginRelative; -} - -//----------------------------------------------------------------------------- -// Set the lighting origin -//----------------------------------------------------------------------------- -void CBaseAnimating::SetLightingOrigin( string_t strLightingOrigin ) -{ - if ( strLightingOrigin == NULL_STRING ) - { - SetLightingOrigin( NULL ); - } - else - { - CBaseEntity *pLightingOrigin = gEntList.FindEntityByName( NULL, strLightingOrigin ); - if ( !pLightingOrigin ) - { - DevWarning( "%s: Could not find lighting origin entity named '%s'!\n", GetClassname(), STRING( strLightingOrigin ) ); - return; - } - else - { - SetLightingOrigin( pLightingOrigin ); - } - } - - // Save the name so that save/load will correctly restore it in Activate() - m_iszLightingOrigin = strLightingOrigin; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CBaseAnimating::InputSetLightingOriginRelative( inputdata_t &inputdata ) -{ - // Find our specified target - string_t strLightingOriginRelative = MAKE_STRING( inputdata.value.String() ); - SetLightingOriginRelative( strLightingOriginRelative ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CBaseAnimating::InputSetLightingOrigin( inputdata_t &inputdata ) -{ - // Find our specified target - string_t strLightingOrigin = MAKE_STRING( inputdata.value.String() ); - SetLightingOrigin( strLightingOrigin ); -} - - -//========================================================= -// SelectWeightedSequence -//========================================================= -int CBaseAnimating::SelectWeightedSequence ( Activity activity ) -{ - Assert( activity != ACT_INVALID ); - Assert( GetModelPtr() ); - return ::SelectWeightedSequence( GetModelPtr(), activity, GetSequence() ); -} - - -int CBaseAnimating::SelectWeightedSequence ( Activity activity, int curSequence ) -{ - Assert( activity != ACT_INVALID ); - Assert( GetModelPtr() ); - return ::SelectWeightedSequence( GetModelPtr(), activity, curSequence ); -} - -//========================================================= -// ResetActivityIndexes -//========================================================= -void CBaseAnimating::ResetActivityIndexes ( void ) -{ - Assert( GetModelPtr() ); - ::ResetActivityIndexes( GetModelPtr() ); -} - -//========================================================= -// ResetEventIndexes -//========================================================= -void CBaseAnimating::ResetEventIndexes ( void ) -{ - Assert( GetModelPtr() ); - ::ResetEventIndexes( GetModelPtr() ); -} - -//========================================================= -// LookupHeaviestSequence -// -// Get sequence with highest 'weight' for this activity -// -//========================================================= -int CBaseAnimating::SelectHeaviestSequence ( Activity activity ) -{ - Assert( GetModelPtr() ); - return ::SelectHeaviestSequence( GetModelPtr(), activity ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Looks up an activity by name. -// Input : label - Name of the activity, ie "ACT_IDLE". -// Output : Returns the activity ID or ACT_INVALID. -//----------------------------------------------------------------------------- -int CBaseAnimating::LookupActivity( const char *label ) -{ - Assert( GetModelPtr() ); - return ::LookupActivity( GetModelPtr(), label ); -} - -//========================================================= -//========================================================= -int CBaseAnimating::LookupSequence( const char *label ) -{ - Assert( GetModelPtr() ); - return ::LookupSequence( GetModelPtr(), label ); -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -KeyValues *CBaseAnimating::GetSequenceKeyValues( int iSequence ) -{ - const char *szText = Studio_GetKeyValueText( GetModelPtr(), iSequence ); - - if (szText) - { - KeyValues *seqKeyValues = new KeyValues(""); - if ( seqKeyValues->LoadFromBuffer( modelinfo->GetModelName( GetModel() ), szText ) ) - { - return seqKeyValues; - } - seqKeyValues->deleteThis(); - } - return NULL; -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// -// Input : iSequence - -// -// Output : float - -//----------------------------------------------------------------------------- -float CBaseAnimating::GetSequenceMoveYaw( int iSequence ) -{ - Vector vecReturn; - - Assert( GetModelPtr() ); - ::GetSequenceLinearMotion( GetModelPtr(), iSequence, GetPoseParameterArray(), &vecReturn ); - - if (vecReturn.Length() > 0) - { - return UTIL_VecToYaw( vecReturn ); - } - - return NOMOTION; -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// Input : iSequence - -// -// Output : float -//----------------------------------------------------------------------------- -float CBaseAnimating::GetSequenceMoveDist( CStudioHdr *pStudioHdr, int iSequence ) -{ - Vector vecReturn; - - ::GetSequenceLinearMotion( pStudioHdr, iSequence, GetPoseParameterArray(), &vecReturn ); - - return vecReturn.Length(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// Input : iSequence - -// *pVec - -// -//----------------------------------------------------------------------------- -void CBaseAnimating::GetSequenceLinearMotion( int iSequence, Vector *pVec ) -{ - Assert( GetModelPtr() ); - ::GetSequenceLinearMotion( GetModelPtr(), iSequence, GetPoseParameterArray(), pVec ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// Input : iSequence - -// -// Output : char -//----------------------------------------------------------------------------- -const char *CBaseAnimating::GetSequenceName( int iSequence ) -{ - if( iSequence == -1 ) - { - return "Not Found!"; - } - - if ( !GetModelPtr() ) - return "No model!"; - - return ::GetSequenceName( GetModelPtr(), iSequence ); -} -//----------------------------------------------------------------------------- -// Purpose: -// -// Input : iSequence - -// -// Output : char -//----------------------------------------------------------------------------- -const char *CBaseAnimating::GetSequenceActivityName( int iSequence ) -{ - if( iSequence == -1 ) - { - return "Not Found!"; - } - - if ( !GetModelPtr() ) - return "No model!"; - - return ::GetSequenceActivityName( GetModelPtr(), iSequence ); -} - -//----------------------------------------------------------------------------- -// Purpose: Make this a client-side simulated entity -// Input : force - vector of force to be exerted in the physics simulation -// forceBone - bone to exert force upon -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseAnimating::BecomeRagdollOnClient( const Vector &force ) -{ - // If this character has a ragdoll animation, turn it over to the physics system - if ( CanBecomeRagdoll() ) - { - VPhysicsDestroyObject(); - AddSolidFlags( FSOLID_NOT_SOLID ); - m_nRenderFX = kRenderFxRagdoll; - - // Have to do this dance because m_vecForce is a network vector - // and can't be sent to ClampRagdollForce as a Vector * - Vector vecClampedForce; - ClampRagdollForce( force, &vecClampedForce ); - m_vecForce = vecClampedForce; - - SetParent( NULL ); - - AddFlag( FL_TRANSRAGDOLL ); - - SetMoveType( MOVETYPE_NONE ); - //UTIL_SetSize( this, vec3_origin, vec3_origin ); - SetThink( NULL ); - - SetNextThink( gpGlobals->curtime + 2.0f ); - //If we're here, then we can vanish safely - SetThink( &CBaseEntity::SUB_Remove ); - - // Remove our flame entity if it's attached to us - CEntityFlame *pFireChild = dynamic_cast( GetEffectEntity() ); - if ( pFireChild ) - { - pFireChild->SetThink( &CBaseEntity::SUB_Remove ); - pFireChild->SetNextThink( gpGlobals->curtime + 0.1f ); - } - - return true; - } - return false; -} - -bool CBaseAnimating::IsRagdoll() -{ - return ( m_nRenderFX == kRenderFxRagdoll ) ? true : false; -} - -bool CBaseAnimating::CanBecomeRagdoll( void ) -{ - MDLCACHE_CRITICAL_SECTION(); - int ragdollSequence = SelectWeightedSequence( ACT_DIERAGDOLL ); - - //Can't cause we don't have a ragdoll sequence. - if ( ragdollSequence == ACTIVITY_NOT_AVAILABLE ) - return false; - - if ( GetFlags() & FL_TRANSRAGDOLL ) - return false; - - return true; -} - -//========================================================= -//========================================================= -void CBaseAnimating::ResetSequenceInfo ( ) -{ - if (GetSequence() == -1) - { - // This shouldn't happen. Setting m_nSequence blindly is a horrible coding practice. - SetSequence( 0 ); - } - - CStudioHdr *pStudioHdr = GetModelPtr(); - m_flGroundSpeed = GetSequenceGroundSpeed( pStudioHdr, GetSequence() ); - m_bSequenceLoops = ((GetSequenceFlags( pStudioHdr, GetSequence() ) & STUDIO_LOOPING) != 0); - // m_flAnimTime = gpGlobals->time; - m_flPlaybackRate = 1.0; - m_bSequenceFinished = false; - m_flLastEventCheck = 0; - - m_nNewSequenceParity = ( m_nNewSequenceParity+1 ) & EF_PARITY_MASK; - m_nResetEventsParity = ( m_nResetEventsParity+1 ) & EF_PARITY_MASK; - - // FIXME: why is this called here? Nothing should have changed to make this nessesary - if ( pStudioHdr ) - { - SetEventIndexForSequence( pStudioHdr->pSeqdesc( GetSequence() ) ); - } -} - -//========================================================= -//========================================================= -bool CBaseAnimating::IsValidSequence( int iSequence ) -{ - Assert( GetModelPtr() ); - CStudioHdr* pstudiohdr = GetModelPtr( ); - if (iSequence < 0 || iSequence >= pstudiohdr->GetNumSeq()) - { - return false; - } - return true; -} - -//========================================================= -//========================================================= -void CBaseAnimating::SetSequence( int nSequence ) -{ - Assert( GetModelPtr( ) && ( nSequence < GetModelPtr( )->GetNumSeq() ) && ( GetModelPtr( )->GetNumSeq() < (1 << ANIMATION_SEQUENCE_BITS) ) ); - m_nSequence = nSequence; -} - - - -//========================================================= -//========================================================= -float CBaseAnimating::SequenceDuration( CStudioHdr *pStudioHdr, int iSequence ) -{ - if ( !pStudioHdr ) - { - DevWarning( 2, "CBaseAnimating::SequenceDuration( %d ) NULL pstudiohdr on %s!\n", iSequence, GetClassname() ); - return 0.1; - } - if ( !pStudioHdr->SequencesAvailable() ) - { - return 0.1; - } - if (iSequence >= pStudioHdr->GetNumSeq() || iSequence < 0 ) - { - DevWarning( 2, "CBaseAnimating::SequenceDuration( %d ) out of range\n", iSequence ); - return 0.1; - } - - return Studio_Duration( pStudioHdr, iSequence, GetPoseParameterArray() ); -} - -float CBaseAnimating::GetSequenceCycleRate( CStudioHdr *pStudioHdr, int iSequence ) -{ - float t = SequenceDuration( pStudioHdr, iSequence ); - - if (t > 0.0f) - { - return 1.0f / t; - } - else - { - return 1.0f / 0.1f; - } -} - - -float CBaseAnimating::GetLastVisibleCycle( CStudioHdr *pStudioHdr, int iSequence ) -{ - if ( !pStudioHdr ) - { - DevWarning( 2, "CBaseAnimating::LastVisibleCycle( %d ) NULL pstudiohdr on %s!\n", iSequence, GetClassname() ); - return 1.0; - } - - if (!(GetSequenceFlags( pStudioHdr, iSequence ) & STUDIO_LOOPING)) - { - return 1.0f - (pStudioHdr->pSeqdesc( iSequence ).fadeouttime) * GetSequenceCycleRate( iSequence ) * m_flPlaybackRate; - } - else - { - return 1.0; - } -} - - -float CBaseAnimating::GetSequenceGroundSpeed( CStudioHdr *pStudioHdr, int iSequence ) -{ - float t = SequenceDuration( pStudioHdr, iSequence ); - - if (t > 0) - { - return GetSequenceMoveDist( pStudioHdr, iSequence ) / t; - } - else - { - return 0; - } -} - -float CBaseAnimating::GetIdealSpeed( ) const -{ - return m_flGroundSpeed; -} - -float CBaseAnimating::GetIdealAccel( ) const -{ - // return ideal max velocity change over 1 second. - // tuned for run-walk range of humans - return GetIdealSpeed() + 50; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true if the given sequence has the anim event, false if not. -// Input : nSequence - sequence number to check -// nEvent - anim event number to look for -//----------------------------------------------------------------------------- -bool CBaseAnimating::HasAnimEvent( int nSequence, int nEvent ) -{ - CStudioHdr *pstudiohdr = GetModelPtr(); - if ( !pstudiohdr ) - { - return false; - } - - animevent_t event; - - int index = 0; - while ( ( index = GetAnimationEvent( pstudiohdr, nSequence, &event, 0.0f, 1.0f, index ) ) != 0 ) - { - if ( event.event == nEvent ) - { - return true; - } - } - - return false; -} - - -//========================================================= -// DispatchAnimEvents -//========================================================= -void CBaseAnimating::DispatchAnimEvents ( CBaseAnimating *eventHandler ) -{ - // don't fire events if the framerate is 0 - if (m_flPlaybackRate == 0.0) - return; - - animevent_t event; - - CStudioHdr *pstudiohdr = GetModelPtr( ); - - if ( !pstudiohdr ) - { - Assert(!"CBaseAnimating::DispatchAnimEvents: model missing"); - return; - } - - if ( !pstudiohdr->SequencesAvailable() ) - { - return; - } - - // skip this altogether if there are no events - if (pstudiohdr->pSeqdesc( GetSequence() ).numevents == 0) - { - return; - } - - // look from when it last checked to some short time in the future - float flCycleRate = GetSequenceCycleRate( GetSequence() ) * m_flPlaybackRate; - float flStart = m_flLastEventCheck; - float flEnd = GetCycle(); - - if (!m_bSequenceLoops && m_bSequenceFinished) - { - flEnd = 1.01f; - } - m_flLastEventCheck = flEnd; - - /* - if (m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) - { - Msg( "%s:%s : checking %.2f %.2f (%d)\n", STRING(GetModelName()), pstudiohdr->pSeqdesc( GetSequence() ).pszLabel(), flStart, flEnd, m_bSequenceFinished ); - } - */ - - // FIXME: does not handle negative framerates! - int index = 0; - while ( (index = GetAnimationEvent( pstudiohdr, GetSequence(), &event, flStart, flEnd, index ) ) != 0 ) - { - event.pSource = this; - // calc when this event should happen - if (flCycleRate > 0.0) - { - float flCycle = event.cycle; - if (flCycle > GetCycle()) - { - flCycle = flCycle - 1.0; - } - event.eventtime = m_flAnimTime + (flCycle - GetCycle()) / flCycleRate + GetAnimTimeInterval(); - } - - /* - if (m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) - { - Msg( "dispatch %i (%i) cycle %f event cycle %f cyclerate %f\n", - (int)(index - 1), - (int)event.event, - (float)GetCycle(), - (float)event.cycle, - (float)flCycleRate ); - } - */ - eventHandler->HandleAnimEvent( &event ); - - // FAILSAFE: - // If HandleAnimEvent has somehow reset my internal pointer - // to CStudioHdr to something other than it was when we entered - // this function, we will crash on the next call to GetAnimationEvent - // because pstudiohdr no longer points at something valid. - // So, catch this case, complain vigorously, and bail out of - // the loop. - CStudioHdr *pNowStudioHdr = GetModelPtr(); - if ( pNowStudioHdr != pstudiohdr ) - { - AssertMsg2(false, "%s has changed its model while processing AnimEvents on sequence %d. Aborting dispatch.\n", GetDebugName(), GetSequence() ); - Warning( "%s has changed its model while processing AnimEvents on sequence %d. Aborting dispatch.\n", GetDebugName(), GetSequence() ); - break; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseAnimating::HandleAnimEvent( animevent_t *pEvent ) -{ - if ((pEvent->type & AE_TYPE_NEWEVENTSYSTEM) && (pEvent->type & AE_TYPE_SERVER)) - { - if ( pEvent->event == AE_SV_PLAYSOUND ) - { - EmitSound( pEvent->options ); - return; - } - else if ( pEvent->event == AE_RAGDOLL ) - { - // Convert to ragdoll immediately - BecomeRagdollOnClient( vec3_origin ); - return; - } -#ifdef HL2_EPISODIC - else if ( pEvent->event == AE_SV_DUSTTRAIL ) - { - char szAttachment[128]; - float flDuration; - float flSize; - if (sscanf( pEvent->options, "%s %f %f", szAttachment, &flDuration, &flSize ) == 3) - { - CHandle hDustTrail; - - hDustTrail = DustTrail::CreateDustTrail(); - - if( hDustTrail ) - { - hDustTrail->m_SpawnRate = 4; // Particles per second - hDustTrail->m_ParticleLifetime = 1.5; // Lifetime of each particle, In seconds - hDustTrail->m_Color.Init(0.5f, 0.46f, 0.44f); - hDustTrail->m_StartSize = flSize; - hDustTrail->m_EndSize = hDustTrail->m_StartSize * 8; - hDustTrail->m_SpawnRadius = 3; // Each particle randomly offset from the center up to this many units - hDustTrail->m_MinSpeed = 4; // u/sec - hDustTrail->m_MaxSpeed = 10; // u/sec - hDustTrail->m_Opacity = 0.5f; - hDustTrail->SetLifetime(flDuration); // Lifetime of the spawner, in seconds - hDustTrail->m_StopEmitTime = gpGlobals->curtime + flDuration; - hDustTrail->SetParent( this, LookupAttachment( szAttachment ) ); - hDustTrail->SetLocalOrigin( vec3_origin ); - } - } - else - { - DevWarning( 1, "%s unable to parse AE_SV_DUSTTRAIL event \"%s\"\n", STRING( GetModelName() ), pEvent->options ); - } - - return; - } -#endif - } - - // Failed to find a handler - const char *pName = EventList_NameForIndex( pEvent->event ); - if ( pName) - { - DevWarning( 1, "Unhandled animation event %s for %s\n", pName, GetClassname() ); - } - else - { - DevWarning( 1, "Unhandled animation event %d for %s\n", pEvent->event, GetClassname() ); - } -} - -// SetPoseParamater() - -//========================================================= -//========================================================= -float CBaseAnimating::SetPoseParameter( CStudioHdr *pStudioHdr, const char *szName, float flValue ) -{ - int poseParam = LookupPoseParameter( pStudioHdr, szName ); - AssertMsg2(poseParam >= 0, "SetPoseParameter called with invalid argument %s by %s", szName, GetDebugName()); - return SetPoseParameter( pStudioHdr, poseParam, flValue ); -} - -float CBaseAnimating::SetPoseParameter( CStudioHdr *pStudioHdr, int iParameter, float flValue ) -{ - if ( !pStudioHdr ) - { - return flValue; - } - - if (iParameter >= 0) - { - float flNewValue; - flValue = Studio_SetPoseParameter( pStudioHdr, iParameter, flValue, flNewValue ); - m_flPoseParameter.Set( iParameter, flNewValue ); - } - - return flValue; -} - -//========================================================= -//========================================================= -float CBaseAnimating::GetPoseParameter( const char *szName ) -{ - return GetPoseParameter( LookupPoseParameter( szName ) ); -} - -float CBaseAnimating::GetPoseParameter( int iParameter ) -{ - CStudioHdr *pstudiohdr = GetModelPtr( ); - - if ( !pstudiohdr ) - { - Assert(!"CBaseAnimating::GetPoseParameter: model missing"); - return 0.0; - } - - if ( !pstudiohdr->SequencesAvailable() ) - { - return 0; - } - - if (iParameter >= 0) - { - return Studio_GetPoseParameter( pstudiohdr, iParameter, m_flPoseParameter[ iParameter ] ); - } - - return 0.0; -} - -bool CBaseAnimating::GetPoseParameterRange( int index, float &minValue, float &maxValue ) -{ - CStudioHdr *pStudioHdr = GetModelPtr(); - - if (pStudioHdr) - { - if (index >= 0 && index < pStudioHdr->GetNumPoseParameters()) - { - const mstudioposeparamdesc_t &pose = pStudioHdr->pPoseParameter( index ); - minValue = pose.start; - maxValue = pose.end; - return true; - } - } - minValue = 0.0f; - maxValue = 1.0f; - return false; -} - -//========================================================= -//========================================================= -int CBaseAnimating::LookupPoseParameter( CStudioHdr *pStudioHdr, const char *szName ) -{ - if ( !pStudioHdr ) - return 0; - - if ( !pStudioHdr->SequencesAvailable() ) - { - return 0; - } - - for (int i = 0; i < pStudioHdr->GetNumPoseParameters(); i++) - { - if (Q_stricmp( pStudioHdr->pPoseParameter( i ).pszName(), szName ) == 0) - { - return i; - } - } - - // AssertMsg( 0, UTIL_VarArgs( "poseparameter %s couldn't be mapped!!!\n", szName ) ); - return -1; // Error -} - -//========================================================= -//========================================================= -bool CBaseAnimating::HasPoseParameter( int iSequence, const char *szName ) -{ - int iParameter = LookupPoseParameter( szName ); - if (iParameter == -1) - { - return false; - } - - return HasPoseParameter( iSequence, iParameter ); -} - -//========================================================= -//========================================================= -bool CBaseAnimating::HasPoseParameter( int iSequence, int iParameter ) -{ - CStudioHdr *pstudiohdr = GetModelPtr( ); - - if ( !pstudiohdr ) - { - return false; - } - - if ( !pstudiohdr->SequencesAvailable() ) - { - return false; - } - - if (iSequence < 0 || iSequence >= pstudiohdr->GetNumSeq()) - { - return false; - } - - mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( iSequence ); - if (pstudiohdr->GetSharedPoseParameter( iSequence, seqdesc.paramindex[0] ) == iParameter || - pstudiohdr->GetSharedPoseParameter( iSequence, seqdesc.paramindex[1] ) == iParameter) - { - return true; - } - return false; -} - - -//========================================================= -// Each class that wants to use pose parameters should populate -// static variables in this entry point, rather than calling -// GetPoseParameter(const char*) every time you want to adjust -// an animation. -// -// Make sure to call BaseClass::PopulatePoseParameters() at -// the *bottom* of your function. -//========================================================= -void CBaseAnimating::PopulatePoseParameters( void ) -{ - -} - -//========================================================= -// Purpose: from input of 75% to 200% of maximum range, rescale smoothly from 75% to 100% -//========================================================= -float CBaseAnimating::EdgeLimitPoseParameter( int iParameter, float flValue, float flBase ) -{ - CStudioHdr *pstudiohdr = GetModelPtr( ); - if ( !pstudiohdr ) - { - return flValue; - } - - if (iParameter < 0 || iParameter >= pstudiohdr->GetNumPoseParameters()) - { - return flValue; - } - - const mstudioposeparamdesc_t &Pose = pstudiohdr->pPoseParameter( iParameter ); - - if (Pose.loop || Pose.start == Pose.end) - { - return flValue; - } - - return RangeCompressor( flValue, Pose.start, Pose.end, flBase ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns index number of a given named bone -// Input : name of a bone -// Output : Bone index number or -1 if bone not found -//----------------------------------------------------------------------------- -int CBaseAnimating::LookupBone( const char *szName ) -{ - Assert( GetModelPtr() ); - - return Studio_BoneIndexByName( GetModelPtr(), szName ); -} - - -//========================================================= -//========================================================= -void CBaseAnimating::GetBonePosition ( int iBone, Vector &origin, QAngle &angles ) -{ - CStudioHdr *pStudioHdr = GetModelPtr( ); - if (!pStudioHdr) - { - Assert(!"CBaseAnimating::GetBonePosition: model missing"); - return; - } - - if (iBone < 0 || iBone >= pStudioHdr->numbones()) - { - Assert(!"CBaseAnimating::GetBonePosition: invalid bone index"); - return; - } - - matrix3x4_t bonetoworld; - GetBoneTransform( iBone, bonetoworld ); - - MatrixAngles( bonetoworld, angles, origin ); -} - - - -//========================================================= -//========================================================= - -void CBaseAnimating::GetBoneTransform( int iBone, matrix3x4_t &pBoneToWorld ) -{ - CStudioHdr *pStudioHdr = GetModelPtr( ); - - if (!pStudioHdr) - { - Assert(!"CBaseAnimating::GetBoneTransform: model missing"); - return; - } - - if (iBone < 0 || iBone >= pStudioHdr->numbones()) - { - Assert(!"CBaseAnimating::GetBoneTransform: invalid bone index"); - return; - } - - CBoneCache *pcache = GetBoneCache( ); - - matrix3x4_t *pmatrix = pcache->GetCachedBone( iBone ); - - if ( !pmatrix ) - { - MatrixCopy( EntityToWorldTransform(), pBoneToWorld ); - return; - } - - Assert( pmatrix ); - - // FIXME - MatrixCopy( *pmatrix, pBoneToWorld ); -} - -class CTraceFilterSkipNPCs : public CTraceFilterSimple -{ -public: - CTraceFilterSkipNPCs( const IHandleEntity *passentity, int collisionGroup ) - : CTraceFilterSimple( passentity, collisionGroup ) - { - } - - virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ) - { - if ( CTraceFilterSimple::ShouldHitEntity(pServerEntity, contentsMask) ) - { - CBaseEntity *pEntity = EntityFromEntityHandle( pServerEntity ); - if ( pEntity->IsNPC() ) - return false; - - return true; - } - return false; - } -}; - - -//----------------------------------------------------------------------------- -// Purpose: Receives the clients IK floor position -//----------------------------------------------------------------------------- - -void CBaseAnimating::SetIKGroundContactInfo( float minHeight, float maxHeight ) -{ - m_flIKGroundContactTime = gpGlobals->curtime; - m_flIKGroundMinHeight = minHeight; - m_flIKGroundMaxHeight = maxHeight; -} - -//----------------------------------------------------------------------------- -// Purpose: Initializes IK floor position -//----------------------------------------------------------------------------- - -void CBaseAnimating::InitStepHeightAdjust( void ) -{ - m_flIKGroundContactTime = 0; - m_flIKGroundMinHeight = 0; - m_flIKGroundMaxHeight = 0; - - // FIXME: not safe to call GetAbsOrigin here. Hierarchy might not be set up! - m_flEstIkFloor = GetAbsOrigin().z; - m_flEstIkOffset = 0; -} - - -//----------------------------------------------------------------------------- -// Purpose: Interpolates client IK floor position and drops entity down so that the feet will reach -//----------------------------------------------------------------------------- - -ConVar npc_height_adjust( "npc_height_adjust", "1", FCVAR_ARCHIVE, "Enable test mode for ik height adjustment" ); - -void CBaseAnimating::UpdateStepOrigin() -{ - if (!npc_height_adjust.GetBool()) - { - m_flEstIkOffset = 0; - m_flEstIkFloor = GetLocalOrigin().z; - return; - } - - /* - if (m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) - { - Msg("%x : %x\n", GetMoveParent(), GetGroundEntity() ); - } - */ - - if (m_flIKGroundContactTime > 0.2 && m_flIKGroundContactTime > gpGlobals->curtime - 0.2) - { - if ((GetFlags() & (FL_FLY | FL_SWIM)) == 0 && GetMoveParent() == NULL && GetGroundEntity() != NULL && !GetGroundEntity()->IsMoving()) - { - Vector toAbs = GetAbsOrigin() - GetLocalOrigin(); - if (toAbs.z == 0.0) - { - CAI_BaseNPC *pNPC = MyNPCPointer(); - // FIXME: There needs to be a default step height somewhere - float height = 18.0f; - if (pNPC) - { - height = pNPC->StepHeight(); - } - - // debounce floor location - m_flEstIkFloor = m_flEstIkFloor * 0.2 + m_flIKGroundMinHeight * 0.8; - - // don't let heigth difference between min and max exceed step height - float bias = clamp( (m_flIKGroundMaxHeight - m_flIKGroundMinHeight) - height, 0, height ); - // save off reasonable offset - m_flEstIkOffset = clamp( m_flEstIkFloor - GetAbsOrigin().z, -height + bias, 0.0f ); - return; - } - } - } - - // don't use floor offset, decay the value - m_flEstIkOffset *= 0.5; - m_flEstIkFloor = GetLocalOrigin().z; -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns the origin to use for model rendering -//----------------------------------------------------------------------------- - -Vector CBaseAnimating::GetStepOrigin( void ) const -{ - Vector tmp = GetLocalOrigin(); - tmp.z += m_flEstIkOffset; - return tmp; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the origin to use for model rendering -//----------------------------------------------------------------------------- - -QAngle CBaseAnimating::GetStepAngles( void ) const -{ - // TODO: Add in body lean - return GetLocalAngles(); -} - -//----------------------------------------------------------------------------- -// Purpose: Find IK collisions with world -// Input : -// Output : fills out m_pIk targets, calcs floor offset for rendering -//----------------------------------------------------------------------------- - -void CBaseAnimating::CalculateIKLocks( float currentTime ) -{ - if ( m_pIk ) - { - Ray_t ray; - CTraceFilterSkipNPCs traceFilter( this, GetCollisionGroup() ); - Vector up; - GetVectors( NULL, NULL, &up ); - // FIXME: check number of slots? - for (int i = 0; i < m_pIk->m_target.Count(); i++) - { - trace_t trace; - CIKTarget *pTarget = &m_pIk->m_target[i]; - - if (!pTarget->IsActive()) - continue; - - switch( pTarget->type ) - { - case IK_GROUND: - { - Vector estGround; - estGround = (pTarget->est.pos - GetAbsOrigin()); - estGround = estGround - (estGround * up) * up; - estGround = GetAbsOrigin() + estGround + pTarget->est.floor * up; - - Vector p1, p2; - VectorMA( estGround, pTarget->est.height, up, p1 ); - VectorMA( estGround, -pTarget->est.height, up, p2 ); - - float r = MAX(pTarget->est.radius,1); - - // don't IK to other characters - ray.Init( p1, p2, Vector(-r,-r,0), Vector(r,r,1) ); - enginetrace->TraceRay( ray, MASK_SOLID, &traceFilter, &trace ); - - /* - debugoverlay->AddBoxOverlay( p1, Vector(-r,-r,0), Vector(r,r,1), QAngle( 0, 0, 0 ), 255, 0, 0, 0, 1.0f ); - debugoverlay->AddBoxOverlay( trace.endpos, Vector(-r,-r,0), Vector(r,r,1), QAngle( 0, 0, 0 ), 255, 0, 0, 0, 1.0f ); - debugoverlay->AddLineOverlay( p1, trace.endpos, 255, 0, 0, 0, 1.0f ); - */ - - if (trace.startsolid) - { - ray.Init( pTarget->trace.hip, pTarget->est.pos, Vector(-r,-r,0), Vector(r,r,1) ); - - enginetrace->TraceRay( ray, MASK_SOLID, &traceFilter, &trace ); - - p1 = trace.endpos; - VectorMA( p1, - pTarget->est.height, up, p2 ); - ray.Init( p1, p2, Vector(-r,-r,0), Vector(r,r,1) ); - - enginetrace->TraceRay( ray, MASK_SOLID, &traceFilter, &trace ); - } - - if (!trace.startsolid) - { - if (trace.DidHitWorld()) - { - pTarget->SetPosWithNormalOffset( trace.endpos, trace.plane.normal ); - pTarget->SetNormal( trace.plane.normal ); - } - else - { - pTarget->SetPos( trace.endpos ); - pTarget->SetAngles( GetAbsAngles() ); - } - - } - } - break; - case IK_ATTACHMENT: - { - // anything on the server? - } - break; - } - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Clear out animation states that are invalidated with Teleport -//----------------------------------------------------------------------------- - -void CBaseAnimating::Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ) -{ - BaseClass::Teleport( newPosition, newAngles, newVelocity ); - if (m_pIk) - { - m_pIk->ClearTargets( ); - } - InitStepHeightAdjust(); -} - - -//----------------------------------------------------------------------------- -// Purpose: build matrices first from the parent, then from the passed in arrays if the bone doesn't exist on the parent -//----------------------------------------------------------------------------- - -void CBaseAnimating::BuildMatricesWithBoneMerge( - const CStudioHdr *pStudioHdr, - const QAngle& angles, - const Vector& origin, - const Vector pos[MAXSTUDIOBONES], - const Quaternion q[MAXSTUDIOBONES], - matrix3x4_t bonetoworld[MAXSTUDIOBONES], - CBaseAnimating *pParent, - CBoneCache *pParentCache - ) -{ - CStudioHdr *fhdr = pParent->GetModelPtr(); - mstudiobone_t *pbones = pStudioHdr->pBone( 0 ); - - matrix3x4_t rotationmatrix; // model to world transformation - AngleMatrix( angles, origin, rotationmatrix); - - for ( int i=0; i < pStudioHdr->numbones(); i++ ) - { - // Now find the bone in the parent entity. - bool merged = false; - int parentBoneIndex = Studio_BoneIndexByName( fhdr, pbones[i].pszName() ); - if ( parentBoneIndex >= 0 ) - { - matrix3x4_t *pMat = pParentCache->GetCachedBone( parentBoneIndex ); - if ( pMat ) - { - MatrixCopy( *pMat, bonetoworld[ i ] ); - merged = true; - } - } - - if ( !merged ) - { - // If we get down here, then the bone wasn't merged. - matrix3x4_t bonematrix; - QuaternionMatrix( q[i], pos[i], bonematrix ); - - if (pbones[i].parent == -1) - { - ConcatTransforms (rotationmatrix, bonematrix, bonetoworld[i]); - } - else - { - ConcatTransforms (bonetoworld[pbones[i].parent], bonematrix, bonetoworld[i]); - } - } - } -} - -ConVar sv_pvsskipanimation( "sv_pvsskipanimation", "1", FCVAR_ARCHIVE, "Skips SetupBones when npc's are outside the PVS" ); -ConVar ai_setupbones_debug( "ai_setupbones_debug", "0", 0, "Shows that bones that are setup every think" ); - - - - -inline bool CBaseAnimating::CanSkipAnimation( void ) -{ - if ( !sv_pvsskipanimation.GetBool() ) - return false; - - CAI_BaseNPC *pNPC = MyNPCPointer(); - if ( pNPC && !pNPC->HasCondition( COND_IN_PVS ) && ( m_fBoneCacheFlags & (BCF_NO_ANIMATION_SKIP | BCF_IS_IN_SPAWN) ) == false ) - { - // If we have a player as a child, then we better setup our bones. If we don't, - // the PVS will be screwy. - return !DoesHavePlayerChild(); - } - else - { - return false; - } -} - - -void CBaseAnimating::SetupBones( matrix3x4_t *pBoneToWorld, int boneMask ) -{ - AUTO_LOCK( m_BoneSetupMutex ); - - VPROF_BUDGET( "CBaseAnimating::SetupBones", VPROF_BUDGETGROUP_SERVER_ANIM ); - - MDLCACHE_CRITICAL_SECTION(); - - Assert( GetModelPtr() ); - - CStudioHdr *pStudioHdr = GetModelPtr( ); - - if(!pStudioHdr) - { - Assert(!"CBaseAnimating::GetSkeleton() without a model"); - return; - } - - Assert( !IsEFlagSet( EFL_SETTING_UP_BONES ) ); - - AddEFlags( EFL_SETTING_UP_BONES ); - - Vector pos[MAXSTUDIOBONES]; - Quaternion q[MAXSTUDIOBONES]; - - // adjust hit boxes based on IK driven offset - Vector adjOrigin = GetAbsOrigin() + Vector( 0, 0, m_flEstIkOffset ); - - if ( CanSkipAnimation() ) - { - InitPose( pStudioHdr, pos, q, boneMask ); - // Msg( "%.03f : %s:%s not in pvs\n", gpGlobals->curtime, GetClassname(), GetEntityName().ToCStr() ); - } - else - if ( m_pIk ) - { - // FIXME: pass this into Studio_BuildMatrices to skip transforms - CBoneBitList boneComputed; - m_iIKCounter++; - m_pIk->Init( pStudioHdr, GetAbsAngles(), adjOrigin, gpGlobals->curtime, m_iIKCounter, boneMask ); - GetSkeleton( pStudioHdr, pos, q, boneMask ); - - m_pIk->UpdateTargets( pos, q, pBoneToWorld, boneComputed ); - CalculateIKLocks( gpGlobals->curtime ); - m_pIk->SolveDependencies( pos, q, pBoneToWorld, boneComputed ); - } - else - { - // Msg( "%.03f : %s:%s\n", gpGlobals->curtime, GetClassname(), GetEntityName().ToCStr() ); - GetSkeleton( pStudioHdr, pos, q, boneMask ); - } - - CBaseAnimating *pParent = dynamic_cast< CBaseAnimating* >( GetMoveParent() ); - if ( pParent ) - { - // We're doing bone merging, so do special stuff here. - CBoneCache *pParentCache = pParent->GetBoneCache(); - if ( pParentCache ) - { - BuildMatricesWithBoneMerge( - pStudioHdr, - GetAbsAngles(), - adjOrigin, - pos, - q, - pBoneToWorld, - pParent, - pParentCache ); - - RemoveEFlags( EFL_SETTING_UP_BONES ); - if (ai_setupbones_debug.GetBool()) - { - DrawRawSkeleton( pBoneToWorld, boneMask, true, 0.11 ); - } - return; - } - } - - Studio_BuildMatrices( - pStudioHdr, - GetAbsAngles(), - adjOrigin, - pos, - q, - -1, - pBoneToWorld, - boneMask ); - - if (ai_setupbones_debug.GetBool()) - { - // Msg("%s:%s:%s (%x)\n", GetClassname(), GetDebugName(), STRING(GetModelName()), boneMask ); - DrawRawSkeleton( pBoneToWorld, boneMask, true, 0.11 ); - } - RemoveEFlags( EFL_SETTING_UP_BONES ); -} - -//========================================================= -//========================================================= -int CBaseAnimating::GetNumBones ( void ) -{ - CStudioHdr *pStudioHdr = GetModelPtr( ); - if(pStudioHdr) - { - return pStudioHdr->numbones(); - } - else - { - Assert(!"CBaseAnimating::GetNumBones: model missing"); - return 0; - } -} - - -//========================================================= -//========================================================= - -//----------------------------------------------------------------------------- -// Purpose: Returns index number of a given named attachment -// Input : name of attachment -// Output : attachment index number or -1 if attachment not found -//----------------------------------------------------------------------------- -int CBaseAnimating::LookupAttachment( const char *szName ) -{ - CStudioHdr *pStudioHdr = GetModelPtr( ); - if (!pStudioHdr) - { - Assert(!"CBaseAnimating::LookupAttachment: model missing"); - return 0; - } - - // The +1 is to make attachment indices be 1-based (namely 0 == invalid or unused attachment) - return Studio_FindAttachment( pStudioHdr, szName ) + 1; -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns the world location and world angles of an attachment -// Input : attachment name -// Output : location and angles -//----------------------------------------------------------------------------- -bool CBaseAnimating::GetAttachment( const char *szName, Vector &absOrigin, QAngle &absAngles ) -{ - return GetAttachment( LookupAttachment( szName ), absOrigin, absAngles ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the world location and world angles of an attachment -// Input : attachment index -// Output : location and angles -//----------------------------------------------------------------------------- -bool CBaseAnimating::GetAttachment ( int iAttachment, Vector &absOrigin, QAngle &absAngles ) -{ - matrix3x4_t attachmentToWorld; - - bool bRet = GetAttachment( iAttachment, attachmentToWorld ); - MatrixAngles( attachmentToWorld, absAngles, absOrigin ); - return bRet; -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns the world location and world angles of an attachment -// Input : attachment index -// Output : location and angles -//----------------------------------------------------------------------------- -bool CBaseAnimating::GetAttachment( int iAttachment, matrix3x4_t &attachmentToWorld ) -{ - CStudioHdr *pStudioHdr = GetModelPtr( ); - if (!pStudioHdr) - { - MatrixCopy(EntityToWorldTransform(), attachmentToWorld); - AssertOnce(!"CBaseAnimating::GetAttachment: model missing"); - return false; - } - - if (iAttachment < 1 || iAttachment > pStudioHdr->GetNumAttachments()) - { - MatrixCopy(EntityToWorldTransform(), attachmentToWorld); -// Assert(!"CBaseAnimating::GetAttachment: invalid attachment index"); - return false; - } - - const mstudioattachment_t &pattachment = pStudioHdr->pAttachment( iAttachment-1 ); - int iBone = pStudioHdr->GetAttachmentBone( iAttachment-1 ); - - matrix3x4_t bonetoworld; - GetBoneTransform( iBone, bonetoworld ); - if ( (pattachment.flags & ATTACHMENT_FLAG_WORLD_ALIGN) == 0 ) - { - ConcatTransforms( bonetoworld, pattachment.local, attachmentToWorld ); - } - else - { - Vector vecLocalBonePos, vecWorldBonePos; - MatrixGetColumn( pattachment.local, 3, vecLocalBonePos ); - VectorTransform( vecLocalBonePos, bonetoworld, vecWorldBonePos ); - - SetIdentityMatrix( attachmentToWorld ); - MatrixSetColumn( vecWorldBonePos, 3, attachmentToWorld ); - } - - return true; -} - -// gets the bone for an attachment -int CBaseAnimating::GetAttachmentBone( int iAttachment ) -{ - CStudioHdr *pStudioHdr = GetModelPtr( ); - if (!pStudioHdr || iAttachment < 1 || iAttachment > pStudioHdr->GetNumAttachments() ) - { - AssertOnce(pStudioHdr && "CBaseAnimating::GetAttachment: model missing"); - return 0; - } - - return pStudioHdr->GetAttachmentBone( iAttachment-1 ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns the world location of an attachment -// Input : attachment index -// Output : location and angles -//----------------------------------------------------------------------------- -bool CBaseAnimating::GetAttachment( const char *szName, Vector &absOrigin, Vector *forward, Vector *right, Vector *up ) -{ - return GetAttachment( LookupAttachment( szName ), absOrigin, forward, right, up ); -} - -bool CBaseAnimating::GetAttachment( int iAttachment, Vector &absOrigin, Vector *forward, Vector *right, Vector *up ) -{ - matrix3x4_t attachmentToWorld; - - bool bRet = GetAttachment( iAttachment, attachmentToWorld ); - MatrixPosition( attachmentToWorld, absOrigin ); - if (forward) - { - MatrixGetColumn( attachmentToWorld, 0, forward ); - } - if (right) - { - MatrixGetColumn( attachmentToWorld, 1, right ); - } - if (up) - { - MatrixGetColumn( attachmentToWorld, 2, up ); - } - return bRet; -} - - -//----------------------------------------------------------------------------- -// Returns the attachment in local space -//----------------------------------------------------------------------------- -bool CBaseAnimating::GetAttachmentLocal( const char *szName, Vector &origin, QAngle &angles ) -{ - return GetAttachmentLocal( LookupAttachment( szName ), origin, angles ); -} - -bool CBaseAnimating::GetAttachmentLocal( int iAttachment, Vector &origin, QAngle &angles ) -{ - matrix3x4_t attachmentToEntity; - - bool bRet = GetAttachmentLocal( iAttachment, attachmentToEntity ); - MatrixAngles( attachmentToEntity, angles, origin ); - return bRet; -} - -bool CBaseAnimating::GetAttachmentLocal( int iAttachment, matrix3x4_t &attachmentToLocal ) -{ - matrix3x4_t attachmentToWorld; - bool bRet = GetAttachment(iAttachment, attachmentToWorld); - matrix3x4_t worldToEntity; - MatrixInvert( EntityToWorldTransform(), worldToEntity ); - ConcatTransforms( worldToEntity, attachmentToWorld, attachmentToLocal ); - return bRet; -} - - -//========================================================= -//========================================================= -void CBaseAnimating::GetEyeballs( Vector &origin, QAngle &angles ) -{ - CStudioHdr *pStudioHdr = GetModelPtr( ); - if (!pStudioHdr) - { - Assert(!"CBaseAnimating::GetAttachment: model missing"); - return; - } - - for (int iBodypart = 0; iBodypart < pStudioHdr->numbodyparts(); iBodypart++) - { - mstudiobodyparts_t *pBodypart = pStudioHdr->pBodypart( iBodypart ); - for (int iModel = 0; iModel < pBodypart->nummodels; iModel++) - { - mstudiomodel_t *pModel = pBodypart->pModel( iModel ); - for (int iEyeball = 0; iEyeball < pModel->numeyeballs; iEyeball++) - { - mstudioeyeball_t *pEyeball = pModel->pEyeball( iEyeball ); - matrix3x4_t bonetoworld; - GetBoneTransform( pEyeball->bone, bonetoworld ); - VectorTransform( pEyeball->org, bonetoworld, origin ); - MatrixAngles( bonetoworld, angles ); // ??? - } - } - } -} - - -//========================================================= -//========================================================= -int CBaseAnimating::FindTransitionSequence( int iCurrentSequence, int iGoalSequence, int *piDir ) -{ - Assert( GetModelPtr() ); - - if (piDir == NULL) - { - int iDir = 1; - int sequence = ::FindTransitionSequence( GetModelPtr(), iCurrentSequence, iGoalSequence, &iDir ); - if (iDir != 1) - return -1; - else - return sequence; - } - - return ::FindTransitionSequence( GetModelPtr(), iCurrentSequence, iGoalSequence, piDir ); -} - - -bool CBaseAnimating::GotoSequence( int iCurrentSequence, float flCurrentCycle, float flCurrentRate, int iGoalSequence, int &nNextSequence, float &flNextCycle, int &iNextDir ) -{ - return ::GotoSequence( GetModelPtr(), iCurrentSequence, flCurrentCycle, flCurrentRate, iGoalSequence, nNextSequence, flNextCycle, iNextDir ); -} - - -int CBaseAnimating::GetEntryNode( int iSequence ) -{ - CStudioHdr *pstudiohdr = GetModelPtr(); - if (! pstudiohdr) - return 0; - - return pstudiohdr->EntryNode( iSequence ); -} - - -int CBaseAnimating::GetExitNode( int iSequence ) -{ - CStudioHdr *pstudiohdr = GetModelPtr(); - if (! pstudiohdr) - return 0; - - return pstudiohdr->ExitNode( iSequence ); -} - - -//========================================================= -//========================================================= - -void CBaseAnimating::SetBodygroup( int iGroup, int iValue ) -{ - Assert( GetModelPtr() ); - - int newBody = m_nBody; - ::SetBodygroup( GetModelPtr( ), newBody, iGroup, iValue ); - m_nBody = newBody; -} - -int CBaseAnimating::GetBodygroup( int iGroup ) -{ - Assert( GetModelPtr() ); - - return ::GetBodygroup( GetModelPtr( ), m_nBody, iGroup ); -} - -const char *CBaseAnimating::GetBodygroupName( int iGroup ) -{ - Assert( GetModelPtr() ); - - return ::GetBodygroupName( GetModelPtr( ), iGroup ); -} - -int CBaseAnimating::FindBodygroupByName( const char *name ) -{ - Assert( GetModelPtr() ); - - return ::FindBodygroupByName( GetModelPtr( ), name ); -} - -int CBaseAnimating::GetBodygroupCount( int iGroup ) -{ - Assert( GetModelPtr() ); - - return ::GetBodygroupCount( GetModelPtr( ), iGroup ); -} - -int CBaseAnimating::GetNumBodyGroups( void ) -{ - Assert( GetModelPtr() ); - - return ::GetNumBodyGroups( GetModelPtr( ) ); -} - -int CBaseAnimating::ExtractBbox( int sequence, Vector& mins, Vector& maxs ) -{ - Assert( GetModelPtr() ); - - return ::ExtractBbox( GetModelPtr( ), sequence, mins, maxs ); -} - -//========================================================= -//========================================================= - -void CBaseAnimating::SetSequenceBox( void ) -{ - Vector mins, maxs; - - // Get sequence bbox - if ( ExtractBbox( GetSequence(), mins, maxs ) ) - { - // expand box for rotation - // find min / max for rotations - float yaw = GetLocalAngles().y * (M_PI / 180.0); - - Vector xvector, yvector; - xvector.x = cos(yaw); - xvector.y = sin(yaw); - yvector.x = -sin(yaw); - yvector.y = cos(yaw); - Vector bounds[2]; - - bounds[0] = mins; - bounds[1] = maxs; - - Vector rmin( 9999, 9999, 9999 ); - Vector rmax( -9999, -9999, -9999 ); - Vector base, transformed; - - for (int i = 0; i <= 1; i++ ) - { - base.x = bounds[i].x; - for ( int j = 0; j <= 1; j++ ) - { - base.y = bounds[j].y; - for ( int k = 0; k <= 1; k++ ) - { - base.z = bounds[k].z; - - // transform the point - transformed.x = xvector.x*base.x + yvector.x*base.y; - transformed.y = xvector.y*base.x + yvector.y*base.y; - transformed.z = base.z; - - for ( int l = 0; l < 3; l++ ) - { - if (transformed[l] < rmin[l]) - rmin[l] = transformed[l]; - if (transformed[l] > rmax[l]) - rmax[l] = transformed[l]; - } - } - } - } - rmin.z = 0; - rmax.z = rmin.z + 1; - UTIL_SetSize( this, rmin, rmax ); - } -} - -//========================================================= -//========================================================= -int CBaseAnimating::RegisterPrivateActivity( const char *pszActivityName ) -{ - return ActivityList_RegisterPrivateActivity( pszActivityName ); -} - -//----------------------------------------------------------------------------- -// Purpose: Notifies the console that this entity could not retrieve an -// animation sequence for the specified activity. This probably means -// there's a typo in the model QC file, or the sequence is missing -// entirely. -// -// -// Input : iActivity - The activity that failed to resolve to a sequence. -// -// -// NOTE : IMPORTANT - Something needs to be done so that private activities -// (which are allowed to collide in the activity list) remember each -// entity that registered an activity there, and the activity name -// each character registered. -//----------------------------------------------------------------------------- -void CBaseAnimating::ReportMissingActivity( int iActivity ) -{ - Msg( "%s has no sequence for act:%s\n", GetClassname(), ActivityList_NameForIndex(iActivity) ); -} - - -LocalFlexController_t CBaseAnimating::GetNumFlexControllers( void ) -{ - CStudioHdr *pstudiohdr = GetModelPtr( ); - if (! pstudiohdr) - return LocalFlexController_t(0); - - return pstudiohdr->numflexcontrollers(); -} - - -const char *CBaseAnimating::GetFlexDescFacs( int iFlexDesc ) -{ - CStudioHdr *pstudiohdr = GetModelPtr( ); - if (! pstudiohdr) - return 0; - - mstudioflexdesc_t *pflexdesc = pstudiohdr->pFlexdesc( iFlexDesc ); - - return pflexdesc->pszFACS( ); -} - -const char *CBaseAnimating::GetFlexControllerName( LocalFlexController_t iFlexController ) -{ - CStudioHdr *pstudiohdr = GetModelPtr( ); - if (! pstudiohdr) - return 0; - - mstudioflexcontroller_t *pflexcontroller = pstudiohdr->pFlexcontroller( iFlexController ); - - return pflexcontroller->pszName( ); -} - -const char *CBaseAnimating::GetFlexControllerType( LocalFlexController_t iFlexController ) -{ - CStudioHdr *pstudiohdr = GetModelPtr( ); - if (! pstudiohdr) - return 0; - - mstudioflexcontroller_t *pflexcontroller = pstudiohdr->pFlexcontroller( iFlexController ); - - return pflexcontroller->pszType( ); -} - -//----------------------------------------------------------------------------- -// Purpose: Converts the ground speed of the animating entity into a true velocity -// Output : Vector - velocity of the character at its current m_flGroundSpeed -//----------------------------------------------------------------------------- -Vector CBaseAnimating::GetGroundSpeedVelocity( void ) -{ - CStudioHdr *pstudiohdr = GetModelPtr(); - if (!pstudiohdr) - return vec3_origin; - - QAngle vecAngles; - Vector vecVelocity; - - vecAngles.y = GetSequenceMoveYaw( GetSequence() ); - vecAngles.x = 0; - vecAngles.z = 0; - - vecAngles.y += GetLocalAngles().y; - - AngleVectors( vecAngles, &vecVelocity ); - - vecVelocity = vecVelocity * m_flGroundSpeed; - - return vecVelocity; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : -//----------------------------------------------------------------------------- -float CBaseAnimating::GetInstantaneousVelocity( float flInterval ) -{ - CStudioHdr *pstudiohdr = GetModelPtr( ); - if (! pstudiohdr) - return 0; - - // FIXME: someone needs to check for last frame, etc. - float flNextCycle = GetCycle() + flInterval * GetSequenceCycleRate( GetSequence() ) * m_flPlaybackRate; - - Vector vecVelocity; - Studio_SeqVelocity( pstudiohdr, GetSequence(), flNextCycle, GetPoseParameterArray(), vecVelocity ); - vecVelocity *= m_flPlaybackRate; - - return vecVelocity.Length(); -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : -//----------------------------------------------------------------------------- -float CBaseAnimating::GetEntryVelocity( int iSequence ) -{ - CStudioHdr *pstudiohdr = GetModelPtr( ); - if (! pstudiohdr) - return 0; - - Vector vecVelocity; - Studio_SeqVelocity( pstudiohdr, iSequence, 0.0, GetPoseParameterArray(), vecVelocity ); - - return vecVelocity.Length(); -} - -float CBaseAnimating::GetExitVelocity( int iSequence ) -{ - CStudioHdr *pstudiohdr = GetModelPtr( ); - if (! pstudiohdr) - return 0; - - Vector vecVelocity; - Studio_SeqVelocity( pstudiohdr, iSequence, 1.0, GetPoseParameterArray(), vecVelocity ); - - return vecVelocity.Length(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : -//----------------------------------------------------------------------------- -bool CBaseAnimating::GetIntervalMovement( float flIntervalUsed, bool &bMoveSeqFinished, Vector &newPosition, QAngle &newAngles ) -{ - CStudioHdr *pstudiohdr = GetModelPtr( ); - if (! pstudiohdr || !pstudiohdr->SequencesAvailable()) - return false; - - float flComputedCycleRate = GetSequenceCycleRate( GetSequence() ); - - float flNextCycle = GetCycle() + flIntervalUsed * flComputedCycleRate * m_flPlaybackRate; - - if ((!m_bSequenceLoops) && flNextCycle > 1.0) - { - flIntervalUsed = GetCycle() / (flComputedCycleRate * m_flPlaybackRate); - flNextCycle = 1.0; - bMoveSeqFinished = true; - } - else - { - bMoveSeqFinished = false; - } - - Vector deltaPos; - QAngle deltaAngles; - - if (Studio_SeqMovement( pstudiohdr, GetSequence(), GetCycle(), flNextCycle, GetPoseParameterArray(), deltaPos, deltaAngles )) - { - VectorYawRotate( deltaPos, GetLocalAngles().y, deltaPos ); - newPosition = GetLocalOrigin() + deltaPos; - newAngles.Init(); - newAngles.y = GetLocalAngles().y + deltaAngles.y; - return true; - } - else - { - newPosition = GetLocalOrigin(); - newAngles = GetLocalAngles(); - return false; - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : -//----------------------------------------------------------------------------- -bool CBaseAnimating::GetSequenceMovement( int nSequence, float fromCycle, float toCycle, Vector &deltaPosition, QAngle &deltaAngles ) -{ - CStudioHdr *pstudiohdr = GetModelPtr( ); - if (! pstudiohdr) - return false; - - return Studio_SeqMovement( pstudiohdr, nSequence, fromCycle, toCycle, GetPoseParameterArray(), deltaPosition, deltaAngles ); -} - - -//----------------------------------------------------------------------------- -// Purpose: find frame where they animation has moved a given distance. -// Output : -//----------------------------------------------------------------------------- -float CBaseAnimating::GetMovementFrame( float flDist ) -{ - CStudioHdr *pstudiohdr = GetModelPtr( ); - if (! pstudiohdr) - return 0; - - float t = Studio_FindSeqDistance( pstudiohdr, GetSequence(), GetPoseParameterArray(), flDist ); - - return t; -} - - -//----------------------------------------------------------------------------- -// Purpose: does a specific sequence have movement? -// Output : -//----------------------------------------------------------------------------- -bool CBaseAnimating::HasMovement( int iSequence ) -{ - CStudioHdr *pstudiohdr = GetModelPtr( ); - if (! pstudiohdr) - return false; - - // FIXME: this needs to check to see if there are keys, and the object is walking - Vector deltaPos; - QAngle deltaAngles; - if (Studio_SeqMovement( pstudiohdr, iSequence, 0.0f, 1.0f, GetPoseParameterArray(), deltaPos, deltaAngles )) - { - return true; - } - - return false; -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *szModelName - -//----------------------------------------------------------------------------- -void CBaseAnimating::SetModel( const char *szModelName ) -{ - MDLCACHE_CRITICAL_SECTION(); - - UnlockStudioHdr(); - - if ( szModelName[0] ) - { - int modelIndex = modelinfo->GetModelIndex( szModelName ); - const model_t *model = modelinfo->GetModel( modelIndex ); - if ( model && ( modelinfo->GetModelType( model ) != mod_studio ) ) - { - Msg( "Setting CBaseAnimating to non-studio model %s (type:%i)\n", szModelName, modelinfo->GetModelType( model ) ); - } - } - Studio_DestroyBoneCache( m_boneCacheHandle ); - m_boneCacheHandle = 0; - - UTIL_SetModel( this, szModelName ); - - // delete exiting studio model container - if (m_pStudioHdr != NULL) - { - delete m_pStudioHdr; - m_pStudioHdr = NULL; - } - - - if ( GetModelPtr() ) - { - InitBoneControllers( ); - - // TODO: what other model data should be initialized? - SetSequence( 0 ); - } - - PopulatePoseParameters(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -//----------------------------------------------------------------------------- -void CBaseAnimating::LockStudioHdr() -{ - AUTO_LOCK( m_StudioHdrInitLock ); - const model_t *mdl = GetModel(); - if (mdl) - { - MDLHandle_t hStudioHdr = modelinfo->GetCacheHandle( mdl ); - if ( hStudioHdr != MDLHANDLE_INVALID ) - { - const studiohdr_t *pStudioHdr = mdlcache->LockStudioHdr( hStudioHdr ); - CStudioHdr *pStudioHdrContainer = NULL; - if ( !m_pStudioHdr ) - { - if ( pStudioHdr ) - { - pStudioHdrContainer = new CStudioHdr; - pStudioHdrContainer->Init( pStudioHdr, mdlcache ); - } - } - else - { - pStudioHdrContainer = m_pStudioHdr; - } - - Assert( ( pStudioHdr == NULL && pStudioHdrContainer == NULL ) || pStudioHdrContainer->GetRenderHdr() == pStudioHdr ); - - if ( pStudioHdrContainer && pStudioHdrContainer->GetVirtualModel() ) - { - MDLHandle_t hVirtualModel = (MDLHandle_t)reinterpret_cast(pStudioHdrContainer->GetRenderHdr()->virtualModel); - mdlcache->LockStudioHdr( hVirtualModel ); - } - m_pStudioHdr = pStudioHdrContainer; // must be last to ensure virtual model correctly set up - } - } -} - -void CBaseAnimating::UnlockStudioHdr() -{ - if ( m_pStudioHdr ) - { - const model_t *mdl = GetModel(); - if (mdl) - { - mdlcache->UnlockStudioHdr( modelinfo->GetCacheHandle( mdl ) ); - if ( m_pStudioHdr->GetVirtualModel() ) - { - MDLHandle_t hVirtualModel = (MDLHandle_t)reinterpret_cast(m_pStudioHdr->GetRenderHdr()->virtualModel); - mdlcache->UnlockStudioHdr( hVirtualModel ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: return the index to the shared bone cache -// Output : -//----------------------------------------------------------------------------- -CBoneCache *CBaseAnimating::GetBoneCache( void ) -{ - CStudioHdr *pStudioHdr = GetModelPtr( ); - Assert(pStudioHdr); - - CBoneCache *pcache = Studio_GetBoneCache( m_boneCacheHandle ); - int boneMask = BONE_USED_BY_HITBOX | BONE_USED_BY_ATTACHMENT; - - // TF queries these bones to position weapons when players are killed -#if defined( TF_DLL ) - boneMask |= BONE_USED_BY_BONE_MERGE; -#endif - if ( pcache ) - { - if ( pcache->IsValid( gpGlobals->curtime ) && (pcache->m_boneMask & boneMask) == boneMask && pcache->m_timeValid <= gpGlobals->curtime) - { - // Msg("%s:%s:%s (%x:%x:%8.4f) cache\n", GetClassname(), GetDebugName(), STRING(GetModelName()), boneMask, pcache->m_boneMask, pcache->m_timeValid ); - // in memory and still valid, use it! - return pcache; - } - // in memory, but missing some of the bone masks - if ( (pcache->m_boneMask & boneMask) != boneMask ) - { - Studio_DestroyBoneCache( m_boneCacheHandle ); - m_boneCacheHandle = 0; - pcache = NULL; - } - } - - matrix3x4_t bonetoworld[MAXSTUDIOBONES]; - SetupBones( bonetoworld, boneMask ); - - if ( pcache ) - { - // still in memory but out of date, refresh the bones. - pcache->UpdateBones( bonetoworld, pStudioHdr->numbones(), gpGlobals->curtime ); - } - else - { - bonecacheparams_t params; - params.pStudioHdr = pStudioHdr; - params.pBoneToWorld = bonetoworld; - params.curtime = gpGlobals->curtime; - params.boneMask = boneMask; - - m_boneCacheHandle = Studio_CreateBoneCache( params ); - pcache = Studio_GetBoneCache( m_boneCacheHandle ); - } - Assert(pcache); - return pcache; -} - - -void CBaseAnimating::InvalidateBoneCache( void ) -{ - Studio_InvalidateBoneCache( m_boneCacheHandle ); -} - -bool CBaseAnimating::TestCollision( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ) -{ - if ( IsSolidFlagSet( FSOLID_CUSTOMRAYTEST )) - { - if (!TestHitboxes( ray, fContentsMask, tr )) - return true; - - return tr.DidHit(); - } - - // We shouldn't get here. - Assert(0); - return false; -} - -bool CBaseAnimating::TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ) -{ - CStudioHdr *pStudioHdr = GetModelPtr( ); - if (!pStudioHdr) - { - Assert(!"CBaseAnimating::GetBonePosition: model missing"); - return false; - } - - mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( m_nHitboxSet ); - if ( !set || !set->numhitboxes ) - return false; - - CBoneCache *pcache = GetBoneCache( ); - - matrix3x4_t *hitboxbones[MAXSTUDIOBONES]; - pcache->ReadCachedBonePointers( hitboxbones, pStudioHdr->numbones() ); - - if ( TraceToStudio( physprops, ray, pStudioHdr, set, hitboxbones, fContentsMask, tr ) ) - { - mstudiobbox_t *pbox = set->pHitbox( tr.hitbox ); - mstudiobone_t *pBone = pStudioHdr->pBone(pbox->bone); - tr.surface.name = "**studio**"; - tr.surface.flags = SURF_HITBOX; - tr.surface.surfaceProps = physprops->GetSurfaceIndex( pBone->pszSurfaceProp() ); - } - return true; -} - -void CBaseAnimating::InitBoneControllers ( void ) // FIXME: rename -{ - int i; - - CStudioHdr *pStudioHdr = GetModelPtr( ); - if (!pStudioHdr) - return; - - int nBoneControllerCount = pStudioHdr->numbonecontrollers(); - if ( nBoneControllerCount > NUM_BONECTRLS ) - { - nBoneControllerCount = NUM_BONECTRLS; - -#ifdef _DEBUG - Warning( "Model %s has too many bone controllers! (Max %d allowed)\n", pStudioHdr->pszName(), NUM_BONECTRLS ); -#endif - } - - for (i = 0; i < nBoneControllerCount; i++) - { - SetBoneController( i, 0.0 ); - } - - Assert( pStudioHdr->SequencesAvailable() ); - - if ( pStudioHdr->SequencesAvailable() ) - { - for (i = 0; i < pStudioHdr->GetNumPoseParameters(); i++) - { - SetPoseParameter( i, 0.0 ); - } - } -} - -//========================================================= -//========================================================= -float CBaseAnimating::SetBoneController ( int iController, float flValue ) -{ - Assert( GetModelPtr() ); - - CStudioHdr *pmodel = (CStudioHdr*)GetModelPtr(); - - Assert(iController >= 0 && iController < NUM_BONECTRLS); - - float newValue; - float retVal = Studio_SetController( pmodel, iController, flValue, newValue ); - m_flEncodedController.Set( iController, newValue ); - - return retVal; -} - -//========================================================= -//========================================================= -float CBaseAnimating::GetBoneController ( int iController ) -{ - Assert( GetModelPtr() ); - - CStudioHdr *pmodel = (CStudioHdr*)GetModelPtr(); - - return Studio_GetController( pmodel, iController, m_flEncodedController[iController] ); -} - -//------------------------------------------------------------------------------ -// Purpose : Returns velcocity of the NPC from it's animation. -// If physically simulated gets velocity from physics object -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBaseAnimating::GetVelocity(Vector *vVelocity, AngularImpulse *vAngVelocity) -{ - if ( GetMoveType() == MOVETYPE_VPHYSICS ) - { - BaseClass::GetVelocity(vVelocity,vAngVelocity); - } - else if ( !(GetFlags() & FL_ONGROUND) ) - { - BaseClass::GetVelocity(vVelocity,vAngVelocity); - } - else - { - if (vVelocity != NULL) - { - Vector vRawVel; - - GetSequenceLinearMotion( GetSequence(), &vRawVel ); - - // Build a rotation matrix from NPC orientation - matrix3x4_t fRotateMatrix; - AngleMatrix(GetLocalAngles(), fRotateMatrix); - VectorRotate( vRawVel, fRotateMatrix, *vVelocity); - } - if (vAngVelocity != NULL) - { - QAngle tmp = GetLocalAngularVelocity(); - QAngleToAngularImpulse( tmp, *vAngVelocity ); - } - } -} - - -//========================================================= -//========================================================= - -void CBaseAnimating::GetSkeleton( CStudioHdr *pStudioHdr, Vector pos[], Quaternion q[], int boneMask ) -{ - if(!pStudioHdr) - { - Assert(!"CBaseAnimating::GetSkeleton() without a model"); - return; - } - - InitPose( pStudioHdr, pos, q, boneMask ); - - AccumulatePose( pStudioHdr, m_pIk, pos, q, GetSequence(), GetCycle(), GetPoseParameterArray(), boneMask, 1.0, gpGlobals->curtime ); - - if ( m_pIk ) - { - CIKContext auto_ik; - auto_ik.Init( pStudioHdr, GetAbsAngles(), GetAbsOrigin(), gpGlobals->curtime, 0, boneMask ); - CalcAutoplaySequences( pStudioHdr, &auto_ik, pos, q, GetPoseParameterArray(), boneMask, gpGlobals->curtime ); - } - else - { - CalcAutoplaySequences( pStudioHdr, NULL, pos, q, GetPoseParameterArray(), boneMask, gpGlobals->curtime ); - } - CalcBoneAdj( pStudioHdr, pos, q, GetEncodedControllerArray(), boneMask ); -} - -int CBaseAnimating::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - // ---------------- - // Print Look time - // ---------------- - char tempstr[1024]; - Q_snprintf(tempstr, sizeof(tempstr), "Sequence: (%3d) %s",GetSequence(), GetSequenceName( GetSequence() ) ); - EntityText(text_offset,tempstr,0); - text_offset++; - const char *pActname = GetSequenceActivityName(GetSequence()); - if ( pActname && strlen(pActname) ) - { - Q_snprintf(tempstr, sizeof(tempstr), "Activity %s", pActname ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - - Q_snprintf(tempstr, sizeof(tempstr), "Cycle: %.5f (%.5f)", (float)GetCycle(), m_flAnimTime.Get() ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - - // Visualize attachment points - if ( m_debugOverlays & OVERLAY_ATTACHMENTS_BIT ) - { - CStudioHdr *pStudioHdr = GetModelPtr(); - - if ( pStudioHdr ) - { - Vector vecPos, vecForward, vecRight, vecUp; - char tempstr[256]; - - // Iterate all the stored attachments - for ( int i = 1; i <= pStudioHdr->GetNumAttachments(); i++ ) - { - GetAttachment( i, vecPos, &vecForward, &vecRight, &vecUp ); - - // Red - forward, green - right, blue - up - NDebugOverlay::Line( vecPos, vecPos + ( vecForward * 4.0f ), 255, 0, 0, true, 0.05f ); - NDebugOverlay::Line( vecPos, vecPos + ( vecRight * 4.0f ), 0, 255, 0, true, 0.05f ); - NDebugOverlay::Line( vecPos, vecPos + ( vecUp * 4.0f ), 0, 0, 255, true, 0.05f ); - - Q_snprintf( tempstr, sizeof(tempstr), " < %s (%d)", pStudioHdr->pAttachment(i-1).pszName(), i ); - NDebugOverlay::Text( vecPos, tempstr, true, 0.05f ); - } - } - } - - return text_offset; -} - -//----------------------------------------------------------------------------- -// Purpose: Force a clientside-animating entity to reset it's frame -//----------------------------------------------------------------------------- -void CBaseAnimating::ResetClientsideFrame( void ) -{ - // TODO: Once we can chain MSG_ENTITY messages, use one of them - m_bClientSideFrameReset = !(bool)m_bClientSideFrameReset; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the origin at which to play an inputted dispatcheffect -//----------------------------------------------------------------------------- -void CBaseAnimating::GetInputDispatchEffectPosition( const char *sInputString, Vector &pOrigin, QAngle &pAngles ) -{ - // See if there's a specified attachment point - int iAttachment; - if ( GetModelPtr() && sscanf( sInputString, "%d", &iAttachment ) ) - { - if ( !GetAttachment( iAttachment, pOrigin, pAngles ) ) - { - Msg( "ERROR: Mapmaker tried to spawn DispatchEffect %s, but %s has no attachment %d\n", - sInputString, STRING(GetModelName()), iAttachment ); - } - return; - } - - BaseClass::GetInputDispatchEffectPosition( sInputString, pOrigin, pAngles ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : setnum - -//----------------------------------------------------------------------------- -void CBaseAnimating::SetHitboxSet( int setnum ) -{ -#ifdef _DEBUG - CStudioHdr *pStudioHdr = GetModelPtr(); - if ( !pStudioHdr ) - return; - - if (setnum > pStudioHdr->numhitboxsets()) - { - // Warn if an bogus hitbox set is being used.... - static bool s_bWarned = false; - if (!s_bWarned) - { - Warning("Using bogus hitbox set in entity %s!\n", GetClassname() ); - s_bWarned = true; - } - setnum = 0; - } -#endif - - m_nHitboxSet = setnum; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *setname - -//----------------------------------------------------------------------------- -void CBaseAnimating::SetHitboxSetByName( const char *setname ) -{ - Assert( GetModelPtr() ); - m_nHitboxSet = FindHitboxSetByName( GetModelPtr(), setname ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CBaseAnimating::GetHitboxSet( void ) -{ - return m_nHitboxSet; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : char const -//----------------------------------------------------------------------------- -const char *CBaseAnimating::GetHitboxSetName( void ) -{ - Assert( GetModelPtr() ); - return ::GetHitboxSetName( GetModelPtr(), m_nHitboxSet ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CBaseAnimating::GetHitboxSetCount( void ) -{ - Assert( GetModelPtr() ); - return ::GetHitboxSetCount( GetModelPtr() ); -} - -static Vector hullcolor[8] = -{ - Vector( 1.0, 1.0, 1.0 ), - Vector( 1.0, 0.5, 0.5 ), - Vector( 0.5, 1.0, 0.5 ), - Vector( 1.0, 1.0, 0.5 ), - Vector( 0.5, 0.5, 1.0 ), - Vector( 1.0, 0.5, 1.0 ), - Vector( 0.5, 1.0, 1.0 ), - Vector( 1.0, 1.0, 1.0 ) -}; - -//----------------------------------------------------------------------------- -// Purpose: Send the current hitboxes for this model to the client ( to compare with -// r_drawentities 3 client side boxes ). -// WARNING: This uses a ton of bandwidth, only use on a listen server -//----------------------------------------------------------------------------- -void CBaseAnimating::DrawServerHitboxes( float duration /*= 0.0f*/, bool monocolor /*= false*/ ) -{ - CStudioHdr *pStudioHdr = GetModelPtr(); - if ( !pStudioHdr ) - return; - - mstudiohitboxset_t *set =pStudioHdr->pHitboxSet( m_nHitboxSet ); - if ( !set ) - return; - - Vector position; - QAngle angles; - - int r = 0; - int g = 0; - int b = 255; - - for ( int i = 0; i < set->numhitboxes; i++ ) - { - mstudiobbox_t *pbox = set->pHitbox( i ); - - GetBonePosition( pbox->bone, position, angles ); - - if ( !monocolor ) - { - int j = (pbox->group % 8); - - r = ( int ) ( 255.0f * hullcolor[j][0] ); - g = ( int ) ( 255.0f * hullcolor[j][1] ); - b = ( int ) ( 255.0f * hullcolor[j][2] ); - } - - NDebugOverlay::BoxAngles( position, pbox->bbmin, pbox->bbmax, angles, r, g, b, 0 ,duration ); - } -} - - -void CBaseAnimating::DrawRawSkeleton( matrix3x4_t boneToWorld[], int boneMask, bool noDepthTest, float duration, bool monocolor ) -{ - CStudioHdr *pStudioHdr = GetModelPtr(); - if ( !pStudioHdr ) - return; - - int i; - int r = 255; - int g = 255; - int b = monocolor ? 255 : 0; - - - for (i = 0; i < pStudioHdr->numbones(); i++) - { - if (pStudioHdr->pBone( i )->flags & boneMask) - { - Vector p1; - MatrixPosition( boneToWorld[i], p1 ); - if ( pStudioHdr->pBone( i )->parent != -1 ) - { - Vector p2; - MatrixPosition( boneToWorld[pStudioHdr->pBone( i )->parent], p2 ); - NDebugOverlay::Line( p1, p2, r, g, b, noDepthTest, duration ); - } - } - } -} - - -int CBaseAnimating::GetHitboxBone( int hitboxIndex ) -{ - CStudioHdr *pStudioHdr = GetModelPtr(); - if ( pStudioHdr ) - { - mstudiohitboxset_t *set =pStudioHdr->pHitboxSet( m_nHitboxSet ); - if ( set && hitboxIndex < set->numhitboxes ) - { - return set->pHitbox( hitboxIndex )->bone; - } - } - return 0; -} - - -//----------------------------------------------------------------------------- -// Computes a box that surrounds all hitboxes -//----------------------------------------------------------------------------- -bool CBaseAnimating::ComputeHitboxSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs ) -{ - // Note that this currently should not be called during Relink because of IK. - // The code below recomputes bones so as to get at the hitboxes, - // which causes IK to trigger, which causes raycasts against the other entities to occur, - // which is illegal to do while in the Relink phase. - - CStudioHdr *pStudioHdr = GetModelPtr(); - if (!pStudioHdr) - return false; - - mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( m_nHitboxSet ); - if ( !set || !set->numhitboxes ) - return false; - - CBoneCache *pCache = GetBoneCache(); - - // Compute a box in world space that surrounds this entity - pVecWorldMins->Init( FLT_MAX, FLT_MAX, FLT_MAX ); - pVecWorldMaxs->Init( -FLT_MAX, -FLT_MAX, -FLT_MAX ); - - Vector vecBoxAbsMins, vecBoxAbsMaxs; - for ( int i = 0; i < set->numhitboxes; i++ ) - { - mstudiobbox_t *pbox = set->pHitbox(i); - matrix3x4_t *pMatrix = pCache->GetCachedBone(pbox->bone); - - if ( pMatrix ) - { - TransformAABB( *pMatrix, pbox->bbmin, pbox->bbmax, vecBoxAbsMins, vecBoxAbsMaxs ); - VectorMin( *pVecWorldMins, vecBoxAbsMins, *pVecWorldMins ); - VectorMax( *pVecWorldMaxs, vecBoxAbsMaxs, *pVecWorldMaxs ); - } - } - return true; -} - -//----------------------------------------------------------------------------- -// Computes a box that surrounds all hitboxes, in entity space -//----------------------------------------------------------------------------- -bool CBaseAnimating::ComputeEntitySpaceHitboxSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs ) -{ - // Note that this currently should not be called during position recomputation because of IK. - // The code below recomputes bones so as to get at the hitboxes, - // which causes IK to trigger, which causes raycasts against the other entities to occur, - // which is illegal to do while in the computeabsposition phase. - - CStudioHdr *pStudioHdr = GetModelPtr(); - if (!pStudioHdr) - return false; - - mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( m_nHitboxSet ); - if ( !set || !set->numhitboxes ) - return false; - - CBoneCache *pCache = GetBoneCache(); - matrix3x4_t *hitboxbones[MAXSTUDIOBONES]; - pCache->ReadCachedBonePointers( hitboxbones, pStudioHdr->numbones() ); - - // Compute a box in world space that surrounds this entity - pVecWorldMins->Init( FLT_MAX, FLT_MAX, FLT_MAX ); - pVecWorldMaxs->Init( -FLT_MAX, -FLT_MAX, -FLT_MAX ); - - matrix3x4_t worldToEntity, boneToEntity; - MatrixInvert( EntityToWorldTransform(), worldToEntity ); - - Vector vecBoxAbsMins, vecBoxAbsMaxs; - for ( int i = 0; i < set->numhitboxes; i++ ) - { - mstudiobbox_t *pbox = set->pHitbox(i); - - ConcatTransforms( worldToEntity, *hitboxbones[pbox->bone], boneToEntity ); - TransformAABB( boneToEntity, pbox->bbmin, pbox->bbmax, vecBoxAbsMins, vecBoxAbsMaxs ); - VectorMin( *pVecWorldMins, vecBoxAbsMins, *pVecWorldMins ); - VectorMax( *pVecWorldMaxs, vecBoxAbsMaxs, *pVecWorldMaxs ); - } - return true; -} - - -int CBaseAnimating::GetPhysicsBone( int boneIndex ) -{ - CStudioHdr *pStudioHdr = GetModelPtr(); - if ( pStudioHdr ) - { - if ( boneIndex >= 0 && boneIndex < pStudioHdr->numbones() ) - return pStudioHdr->pBone( boneIndex )->physicsbone; - } - return 0; -} - -bool CBaseAnimating::LookupHitbox( const char *szName, int& outSet, int& outBox ) -{ - CStudioHdr* pHdr = GetModelPtr(); - - outSet = -1; - outBox = -1; - - if( !pHdr ) - return false; - - for( int set=0; set < pHdr->numhitboxsets(); set++ ) - { - for( int i = 0; i < pHdr->iHitboxCount(set); i++ ) - { - mstudiobbox_t* pBox = pHdr->pHitbox( i, set ); - - if( !pBox ) - continue; - - const char* szBoxName = pBox->pszHitboxName(); - if( Q_stricmp( szBoxName, szName ) == 0 ) - { - outSet = set; - outBox = i; - return true; - } - } - } - - return false; -} - -void CBaseAnimating::CopyAnimationDataFrom( CBaseAnimating *pSource ) -{ - this->SetModelName( pSource->GetModelName() ); - this->SetModelIndex( pSource->GetModelIndex() ); - this->SetCycle( pSource->GetCycle() ); - this->SetEffects( pSource->GetEffects() | EF_NOINTERP ); - this->SetSequence( pSource->GetSequence() ); - this->m_flAnimTime = pSource->m_flAnimTime; - this->m_nBody = pSource->m_nBody; - this->m_nSkin = pSource->m_nSkin; - this->LockStudioHdr(); -} - -int CBaseAnimating::GetHitboxesFrontside( int *boxList, int boxMax, const Vector &normal, float dist ) -{ - int count = 0; - CStudioHdr *pStudioHdr = GetModelPtr(); - if ( pStudioHdr ) - { - mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( m_nHitboxSet ); - if ( set ) - { - matrix3x4_t matrix; - for ( int b = 0; b < set->numhitboxes; b++ ) - { - mstudiobbox_t *pbox = set->pHitbox( b ); - - GetBoneTransform( pbox->bone, matrix ); - Vector center = (pbox->bbmax + pbox->bbmin) * 0.5; - Vector centerWs; - VectorTransform( center, matrix, centerWs ); - if ( DotProduct( centerWs, normal ) >= dist ) - { - if ( count < boxMax ) - { - boxList[count] = b; - count++; - } - } - } - } - } - - return count; -} - -void CBaseAnimating::EnableServerIK() -{ - if (!m_pIk) - { - m_pIk = new CIKContext; - m_iIKCounter = 0; - } -} - -void CBaseAnimating::DisableServerIK() -{ - delete m_pIk; - m_pIk = NULL; -} - -Activity CBaseAnimating::GetSequenceActivity( int iSequence ) -{ - if( iSequence == -1 ) - { - return ACT_INVALID; - } - - if ( !GetModelPtr() ) - return ACT_INVALID; - - return (Activity)::GetSequenceActivity( GetModelPtr(), iSequence ); -} - -void CBaseAnimating::ModifyOrAppendCriteria( AI_CriteriaSet& set ) -{ - BaseClass::ModifyOrAppendCriteria( set ); - - // TODO - // Append any animation state parameters here -} - - -void CBaseAnimating::DoMuzzleFlash() -{ - m_nMuzzleFlashParity = (m_nMuzzleFlashParity+1) & ((1 << EF_MUZZLEFLASH_BITS) - 1); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : scale - -//----------------------------------------------------------------------------- -void CBaseAnimating::SetModelWidthScale( float scale, float change_duration /*= 0.0f*/ ) -{ - if ( change_duration > 0.0f ) - { - ModelWidthScale *mvs = ( ModelWidthScale * )CreateDataObject( MODELWIDTHSCALE ); - mvs->m_flModelWidthScaleStart = m_flModelWidthScale; - mvs->m_flModelWidthScaleGoal = scale; - mvs->m_flModelWidthScaleStartTime = gpGlobals->curtime; - mvs->m_flModelWidthScaleFinishTime = mvs->m_flModelWidthScaleStartTime + change_duration; - } - else - { - m_flModelWidthScale = scale; - if ( HasDataObjectType( MODELWIDTHSCALE ) ) - { - DestroyDataObject( MODELWIDTHSCALE ); - } - } -} - -void CBaseAnimating::UpdateModelWidthScale() -{ - ModelWidthScale *mvs = ( ModelWidthScale * )GetDataObject( MODELWIDTHSCALE ); - if ( !mvs ) - { - return; - } - - float dt = mvs->m_flModelWidthScaleFinishTime - mvs->m_flModelWidthScaleStartTime; - Assert( dt > 0.0f ); - - float frac = ( gpGlobals->curtime - mvs->m_flModelWidthScaleStartTime ) / dt; - frac = clamp( frac, 0.0f, 1.0f ); - - if ( gpGlobals->curtime >= mvs->m_flModelWidthScaleFinishTime ) - { - m_flModelWidthScale = mvs->m_flModelWidthScaleGoal; - DestroyDataObject( MODELWIDTHSCALE ); - } - else - { - m_flModelWidthScale = Lerp( frac, mvs->m_flModelWidthScaleStart, mvs->m_flModelWidthScaleGoal ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CBaseAnimating::GetModelWidthScale() const -{ - return m_flModelWidthScale; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CBaseAnimating::Ignite( float flFlameLifetime, bool bNPCOnly, float flSize, bool bCalledByLevelDesigner ) -{ - if( IsOnFire() ) - return; - - bool bIsNPC = IsNPC(); - - // Right now this prevents stuff we don't want to catch on fire from catching on fire. - if( bNPCOnly && bIsNPC == false ) - { - return; - } - - if( bIsNPC == true && bCalledByLevelDesigner == false ) - { - CAI_BaseNPC *pNPC = MyNPCPointer(); - - if ( pNPC && pNPC->AllowedToIgnite() == false ) - return; - } - - CEntityFlame *pFlame = CEntityFlame::Create( this ); - if (pFlame) - { - pFlame->SetLifetime( flFlameLifetime ); - AddFlag( FL_ONFIRE ); - - SetEffectEntity( pFlame ); - - if ( flSize > 0.0f ) - { - pFlame->SetSize( flSize ); - } - } - - m_OnIgnite.FireOutput( this, this ); -} - -void CBaseAnimating::IgniteLifetime( float flFlameLifetime ) -{ - if( !IsOnFire() ) - Ignite( 30, false, 0.0f, true ); - - CEntityFlame *pFlame = dynamic_cast( GetEffectEntity() ); - - if ( !pFlame ) - return; - - pFlame->SetLifetime( flFlameLifetime ); -} - -void CBaseAnimating::IgniteNumHitboxFires( int iNumHitBoxFires ) -{ - if( !IsOnFire() ) - Ignite( 30, false, 0.0f, true ); - - CEntityFlame *pFlame = dynamic_cast( GetEffectEntity() ); - - if ( !pFlame ) - return; - - pFlame->SetNumHitboxFires( iNumHitBoxFires ); -} - -void CBaseAnimating::IgniteHitboxFireScale( float flHitboxFireScale ) -{ - if( !IsOnFire() ) - Ignite( 30, false, 0.0f, true ); - - CEntityFlame *pFlame = dynamic_cast( GetEffectEntity() ); - - if ( !pFlame ) - return; - - pFlame->SetHitboxFireScale( flHitboxFireScale ); -} - -//----------------------------------------------------------------------------- -// Fades out! -//----------------------------------------------------------------------------- -bool CBaseAnimating::Dissolve( const char *pMaterialName, float flStartTime, bool bNPCOnly, int nDissolveType, Vector vDissolverOrigin, int iMagnitude ) -{ - // Right now this prevents stuff we don't want to catch on fire from catching on fire. - if( bNPCOnly && !(GetFlags() & FL_NPC) ) - return false; - - // Can't dissolve twice - if ( IsDissolving() ) - return false; - - bool bRagdollCreated = false; - CEntityDissolve *pDissolve = CEntityDissolve::Create( this, pMaterialName, flStartTime, nDissolveType, &bRagdollCreated ); - if (pDissolve) - { - SetEffectEntity( pDissolve ); - - AddFlag( FL_DISSOLVING ); - m_flDissolveStartTime = flStartTime; - pDissolve->SetDissolverOrigin( vDissolverOrigin ); - pDissolve->SetMagnitude( iMagnitude ); - } - - // if this is a ragdoll dissolving, fire an event - if ( ( CLASS_NONE == Classify() ) && ( ClassMatches( "prop_ragdoll" ) ) ) - { - IGameEvent *event = gameeventmanager->CreateEvent( "ragdoll_dissolved" ); - if ( event ) - { - event->SetInt( "entindex", entindex() ); - gameeventmanager->FireEvent( event ); - } - } - - return bRagdollCreated; -} - - -//----------------------------------------------------------------------------- -// Make a model look as though it's burning. -//----------------------------------------------------------------------------- -void CBaseAnimating::Scorch( int rate, int floor ) -{ - color32 color = GetRenderColor(); - - if( color.r > floor ) - color.r -= rate; - - if( color.g > floor ) - color.g -= rate; - - if( color.b > floor ) - color.b -= rate; - - SetRenderColor( color.r, color.g, color.b ); -} - - -void CBaseAnimating::ResetSequence(int nSequence) -{ - if (ai_sequence_debug.GetBool() == true && (m_debugOverlays & OVERLAY_NPC_SELECTED_BIT)) - { - DevMsg("ResetSequence : %s: %s -> %s\n", GetClassname(), GetSequenceName(GetSequence()), GetSequenceName(nSequence)); - } - - if ( !SequenceLoops() ) - { - SetCycle( 0 ); - } - - // Tracker 17868: If the sequence number didn't actually change, but you call resetsequence info, it changes - // the newsequenceparity bit which causes the client to call m_flCycle.Reset() which causes a very slight - // discontinuity in looping animations as they reset around to cycle 0.0. This was causing the parentattached - // helmet on barney to hitch every time barney's idle cycled back around to its start. - bool changed = nSequence != GetSequence() ? true : false; - - SetSequence( nSequence ); - if ( changed || !SequenceLoops() ) - { - ResetSequenceInfo(); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CBaseAnimating::InputIgnite( inputdata_t &inputdata ) -{ - Ignite( 30, false, 0.0f, true ); -} - -void CBaseAnimating::InputIgniteLifetime( inputdata_t &inputdata ) -{ - IgniteLifetime( inputdata.value.Float() ); -} - -void CBaseAnimating::InputIgniteNumHitboxFires( inputdata_t &inputdata ) -{ - IgniteNumHitboxFires( inputdata.value.Int() ); -} - -void CBaseAnimating::InputIgniteHitboxFireScale( inputdata_t &inputdata ) -{ - IgniteHitboxFireScale( inputdata.value.Float() ); -} - -void CBaseAnimating::InputBecomeRagdoll( inputdata_t &inputdata ) -{ - BecomeRagdollOnClient( vec3_origin ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseAnimating::SetFadeDistance( float minFadeDist, float maxFadeDist ) -{ - m_fadeMinDist = minFadeDist; - m_fadeMaxDist = maxFadeDist; -} - -//----------------------------------------------------------------------------- -// Purpose: Async prefetches all anim data used by a particular sequence. Returns true if all of the required data is memory resident -// Input : iSequence - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseAnimating::PrefetchSequence( int iSequence ) -{ - CStudioHdr *pStudioHdr = GetModelPtr(); - if ( !pStudioHdr ) - return true; - - return Studio_PrefetchSequence( pStudioHdr, iSequence ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseAnimating::IsSequenceLooping( CStudioHdr *pStudioHdr, int iSequence ) -{ - return (::GetSequenceFlags( pStudioHdr, iSequence ) & STUDIO_LOOPING) != 0; -} diff --git a/game/server/baseanimating.h b/game/server/baseanimating.h deleted file mode 100644 index 383571c00..000000000 --- a/game/server/baseanimating.h +++ /dev/null @@ -1,524 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef BASEANIMATING_H -#define BASEANIMATING_H -#ifdef _WIN32 -#pragma once -#endif - -#include "baseentity.h" -#include "entityoutput.h" -#include "studio.h" -#include "datacache/idatacache.h" -#include "tier0/threadtools.h" - - -struct animevent_t; -struct matrix3x4_t; -class CIKContext; -class KeyValues; -FORWARD_DECLARE_HANDLE( memhandle_t ); - -#define BCF_NO_ANIMATION_SKIP ( 1 << 0 ) // Do not allow PVS animation skipping (mostly for attachments being critical to an entity) -#define BCF_IS_IN_SPAWN ( 1 << 1 ) // Is currently inside of spawn, always evaluate animations - -class CBaseAnimating : public CBaseEntity -{ -public: - DECLARE_CLASS( CBaseAnimating, CBaseEntity ); - - CBaseAnimating(); - ~CBaseAnimating(); - - DECLARE_PREDICTABLE(); - - enum - { - NUM_POSEPAREMETERS = 24, - NUM_BONECTRLS = 4 - }; - - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - virtual void SetModel( const char *szModelName ); - virtual void Activate(); - virtual void Spawn(); - virtual void Precache(); - virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ); - - virtual int Restore( IRestore &restore ); - virtual void OnRestore(); - - CStudioHdr *GetModelPtr( void ); - void InvalidateMdlCache(); - - virtual CBaseAnimating* GetBaseAnimating() { return this; } - - // Cycle access - void SetCycle( float flCycle ); - float GetCycle() const; - - float GetAnimTimeInterval( void ) const; - - // Call this in your constructor to tell it that you will not use animtime. Then the - // interpolation will be done correctly on the client. - // This defaults to off. - void UseClientSideAnimation(); - - // Tells whether or not we're using client-side animation. Used for controlling - // the transmission of animtime. - bool IsUsingClientSideAnimation() { return m_bClientSideAnimation; } - - - // Basic NPC Animation functions - virtual float GetIdealSpeed( ) const; - virtual float GetIdealAccel( ) const; - virtual void StudioFrameAdvance(); // advance animation frame to some time in the future - void StudioFrameAdvanceManual( float flInterval ); - bool IsValidSequence( int iSequence ); - - inline float GetPlaybackRate(); - inline void SetPlaybackRate( float rate ); - - inline int GetSequence() { return m_nSequence; } - // inline void SetSequence(int nSequence) { Assert( GetModelPtr( ) && nSequence >= 0 && nSequence < GetModelPtr( )->GetNumSeq() ); m_nSequence = nSequence; } - void SetSequence(int nSequence); - /* inline */ void ResetSequence(int nSequence); - // FIXME: push transitions support down into CBaseAnimating? - virtual bool IsActivityFinished( void ) { return m_bSequenceFinished; } - inline bool IsSequenceFinished( void ) { return m_bSequenceFinished; } - inline bool SequenceLoops( void ) { return m_bSequenceLoops; } - bool IsSequenceLooping( CStudioHdr *pStudioHdr, int iSequence ); - inline bool IsSequenceLooping( int iSequence ) { return IsSequenceLooping(GetModelPtr(),iSequence); } - inline float SequenceDuration( void ) { return SequenceDuration( m_nSequence ); } - float SequenceDuration( CStudioHdr *pStudioHdr, int iSequence ); - inline float SequenceDuration( int iSequence ) { return SequenceDuration(GetModelPtr(), iSequence); } - float GetSequenceCycleRate( CStudioHdr *pStudioHdr, int iSequence ); - inline float GetSequenceCycleRate( int iSequence ) { return GetSequenceCycleRate(GetModelPtr(),iSequence); } - float GetLastVisibleCycle( CStudioHdr *pStudioHdr, int iSequence ); - virtual float GetSequenceGroundSpeed( CStudioHdr *pStudioHdr, int iSequence ); - inline float GetSequenceGroundSpeed( int iSequence ) { return GetSequenceGroundSpeed(GetModelPtr(), iSequence); } - void ResetActivityIndexes ( void ); - void ResetEventIndexes ( void ); - int SelectWeightedSequence ( Activity activity ); - int SelectWeightedSequence ( Activity activity, int curSequence ); - int SelectHeaviestSequence ( Activity activity ); - int LookupActivity( const char *label ); - int LookupSequence ( const char *label ); - KeyValues *GetSequenceKeyValues( int iSequence ); - - float GetSequenceMoveYaw( int iSequence ); - float GetSequenceMoveDist( CStudioHdr *pStudioHdr, int iSequence ); - inline float GetSequenceMoveDist( int iSequence ) { return GetSequenceMoveDist(GetModelPtr(),iSequence);} - void GetSequenceLinearMotion( int iSequence, Vector *pVec ); - const char *GetSequenceName( int iSequence ); - const char *GetSequenceActivityName( int iSequence ); - Activity GetSequenceActivity( int iSequence ); - - void ResetSequenceInfo ( ); - // This will stop animation until you call ResetSequenceInfo() at some point in the future - inline void StopAnimation( void ) { m_flPlaybackRate = 0; } - - virtual void ClampRagdollForce( const Vector &vecForceIn, Vector *vecForceOut ) { *vecForceOut = vecForceIn; } // Base class does nothing. - virtual bool BecomeRagdollOnClient( const Vector &force ); - virtual bool IsRagdoll(); - virtual bool CanBecomeRagdoll( void ); //Check if this entity will ragdoll when dead. - - virtual void GetSkeleton( CStudioHdr *pStudioHdr, Vector pos[], Quaternion q[], int boneMask ); - - virtual void GetBoneTransform( int iBone, matrix3x4_t &pBoneToWorld ); - virtual void SetupBones( matrix3x4_t *pBoneToWorld, int boneMask ); - virtual void CalculateIKLocks( float currentTime ); - virtual void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ); - - bool HasAnimEvent( int nSequence, int nEvent ); - virtual void DispatchAnimEvents ( CBaseAnimating *eventHandler ); // Handle events that have happend since last time called up until X seconds into the future - virtual void HandleAnimEvent( animevent_t *pEvent ); - - int LookupPoseParameter( CStudioHdr *pStudioHdr, const char *szName ); - inline int LookupPoseParameter( const char *szName ) { return LookupPoseParameter(GetModelPtr(), szName); } - - float SetPoseParameter( CStudioHdr *pStudioHdr, const char *szName, float flValue ); - inline float SetPoseParameter( const char *szName, float flValue ) { return SetPoseParameter( GetModelPtr(), szName, flValue ); } - float SetPoseParameter( CStudioHdr *pStudioHdr, int iParameter, float flValue ); - inline float SetPoseParameter( int iParameter, float flValue ) { return SetPoseParameter( GetModelPtr(), iParameter, flValue ); } - - float GetPoseParameter( const char *szName ); - float GetPoseParameter( int iParameter ); - bool GetPoseParameterRange( int index, float &minValue, float &maxValue ); - bool HasPoseParameter( int iSequence, const char *szName ); - bool HasPoseParameter( int iSequence, int iParameter ); - float EdgeLimitPoseParameter( int iParameter, float flValue, float flBase = 0.0f ); - -protected: - // The modus operandi for pose parameters is that you should not use the const char * version of the functions - // in general code -- it causes many many string comparisons, which is slower than you think. Better is to - // save off your pose parameters in member variables in your derivation of this function: - virtual void PopulatePoseParameters( void ); - - -public: - - int LookupBone( const char *szName ); - void GetBonePosition( const char *szName, Vector &origin, QAngle &angles ); - void GetBonePosition( int iBone, Vector &origin, QAngle &angles ); - int GetPhysicsBone( int boneIndex ); - - int GetNumBones ( void ); - - int FindTransitionSequence( int iCurrentSequence, int iGoalSequence, int *piDir ); - bool GotoSequence( int iCurrentSequence, float flCurrentCycle, float flCurrentRate, int iGoalSequence, int &iNextSequence, float &flCycle, int &iDir ); - int GetEntryNode( int iSequence ); - int GetExitNode( int iSequence ); - - void GetEyeballs( Vector &origin, QAngle &angles ); // ?? remove ?? - - int LookupAttachment( const char *szName ); - - // These return the attachment in world space - bool GetAttachment( const char *szName, Vector &absOrigin, QAngle &absAngles ); - bool GetAttachment( int iAttachment, Vector &absOrigin, QAngle &absAngles ); - int GetAttachmentBone( int iAttachment ); - virtual bool GetAttachment( int iAttachment, matrix3x4_t &attachmentToWorld ); - - // These return the attachment in the space of the entity - bool GetAttachmentLocal( const char *szName, Vector &origin, QAngle &angles ); - bool GetAttachmentLocal( int iAttachment, Vector &origin, QAngle &angles ); - bool GetAttachmentLocal( int iAttachment, matrix3x4_t &attachmentToLocal ); - - // Non-angle versions of the attachments in world space - bool GetAttachment( const char *szName, Vector &absOrigin, Vector *forward = NULL, Vector *right = NULL, Vector *up = NULL ); - bool GetAttachment( int iAttachment, Vector &absOrigin, Vector *forward = NULL, Vector *right = NULL, Vector *up = NULL ); - - void SetBodygroup( int iGroup, int iValue ); - int GetBodygroup( int iGroup ); - - const char *GetBodygroupName( int iGroup ); - int FindBodygroupByName( const char *name ); - int GetBodygroupCount( int iGroup ); - int GetNumBodyGroups( void ); - - void SetHitboxSet( int setnum ); - void SetHitboxSetByName( const char *setname ); - int GetHitboxSet( void ); - char const *GetHitboxSetName( void ); - int GetHitboxSetCount( void ); - int GetHitboxBone( int hitboxIndex ); - bool LookupHitbox( const char *szName, int& outSet, int& outBox ); - - // Computes a box that surrounds all hitboxes - bool ComputeHitboxSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs ); - bool ComputeEntitySpaceHitboxSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs ); - - // Clone a CBaseAnimating from another (copies model & sequence data) - void CopyAnimationDataFrom( CBaseAnimating *pSource ); - - int ExtractBbox( int sequence, Vector& mins, Vector& maxs ); - void SetSequenceBox( void ); - int RegisterPrivateActivity( const char *pszActivityName ); - - void ResetClientsideFrame( void ); - -// Controllers. - virtual void InitBoneControllers ( void ); - - // Return's the controller's angle/position in bone space. - float GetBoneController ( int iController ); - - // Maps the angle/position value you specify into the bone's start/end and sets the specified controller to the value. - float SetBoneController ( int iController, float flValue ); - - void GetVelocity(Vector *vVelocity, AngularImpulse *vAngVelocity); - - // these two need to move somewhere else - LocalFlexController_t GetNumFlexControllers( void ); - const char *GetFlexDescFacs( int iFlexDesc ); - const char *GetFlexControllerName( LocalFlexController_t iFlexController ); - const char *GetFlexControllerType( LocalFlexController_t iFlexController ); - - virtual Vector GetGroundSpeedVelocity( void ); - - bool GetIntervalMovement( float flIntervalUsed, bool &bMoveSeqFinished, Vector &newPosition, QAngle &newAngles ); - bool GetSequenceMovement( int nSequence, float fromCycle, float toCycle, Vector &deltaPosition, QAngle &deltaAngles ); - float GetInstantaneousVelocity( float flInterval = 0.0 ); - float GetEntryVelocity( int iSequence ); - float GetExitVelocity( int iSequence ); - float GetMovementFrame( float flDist ); - bool HasMovement( int iSequence ); - - void ReportMissingActivity( int iActivity ); - virtual bool TestCollision( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ); - virtual bool TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ); - class CBoneCache *GetBoneCache( void ); - void InvalidateBoneCache(); - void InvalidateBoneCacheIfOlderThan( float deltaTime ); - virtual int DrawDebugTextOverlays( void ); - - // See note in code re: bandwidth usage!!! - void DrawServerHitboxes( float duration = 0.0f, bool monocolor = false ); - void DrawRawSkeleton( matrix3x4_t boneToWorld[], int boneMask, bool noDepthTest = true, float duration = 0.0f, bool monocolor = false ); - - void SetModelWidthScale( float scale, float change_duration = 0.0f ); - float GetModelWidthScale() const; - - void UpdateModelWidthScale(); - - // also calculate IK on server? (always done on client) - void EnableServerIK(); - void DisableServerIK(); - - // for ragdoll vs. car - int GetHitboxesFrontside( int *boxList, int boxMax, const Vector &normal, float dist ); - - void GetInputDispatchEffectPosition( const char *sInputString, Vector &pOrigin, QAngle &pAngles ); - - virtual void ModifyOrAppendCriteria( AI_CriteriaSet& set ); - - // Send a muzzle flash event to the client for this entity. - void DoMuzzleFlash(); - - // Fire - virtual void Ignite( float flFlameLifetime, bool bNPCOnly = true, float flSize = 0.0f, bool bCalledByLevelDesigner = false ); - virtual void IgniteLifetime( float flFlameLifetime ); - virtual void IgniteNumHitboxFires( int iNumHitBoxFires ); - virtual void IgniteHitboxFireScale( float flHitboxFireScale ); - virtual void Extinguish() { RemoveFlag( FL_ONFIRE ); } - bool IsOnFire() { return ( (GetFlags() & FL_ONFIRE) != 0 ); } - void Scorch( int rate, int floor ); - void InputIgnite( inputdata_t &inputdata ); - void InputIgniteLifetime( inputdata_t &inputdata ); - void InputIgniteNumHitboxFires( inputdata_t &inputdata ); - void InputIgniteHitboxFireScale( inputdata_t &inputdata ); - void InputBecomeRagdoll( inputdata_t &inputdata ); - - // Dissolve, returns true if the ragdoll has been created - bool Dissolve( const char *pMaterialName, float flStartTime, bool bNPCOnly = true, int nDissolveType = 0, Vector vDissolverOrigin = vec3_origin, int iMagnitude = 0 ); - bool IsDissolving() { return ( (GetFlags() & FL_DISSOLVING) != 0 ); } - void TransferDissolveFrom( CBaseAnimating *pAnim ); - - // animation needs - float m_flGroundSpeed; // computed linear movement rate for current sequence - float m_flLastEventCheck; // cycle index of when events were last checked - - virtual void SetLightingOriginRelative( CBaseEntity *pLightingOriginRelative ); - void SetLightingOriginRelative( string_t strLightingOriginRelative ); - CBaseEntity *GetLightingOriginRelative(); - - virtual void SetLightingOrigin( CBaseEntity *pLightingOrigin ); - void SetLightingOrigin( string_t strLightingOrigin ); - CBaseEntity *GetLightingOrigin(); - - const float* GetPoseParameterArray() { return m_flPoseParameter.Base(); } - const float* GetEncodedControllerArray() { return m_flEncodedController.Base(); } - - void BuildMatricesWithBoneMerge( const CStudioHdr *pStudioHdr, const QAngle& angles, - const Vector& origin, const Vector pos[MAXSTUDIOBONES], - const Quaternion q[MAXSTUDIOBONES], matrix3x4_t bonetoworld[MAXSTUDIOBONES], - CBaseAnimating *pParent, CBoneCache *pParentCache ); - - void SetFadeDistance( float minFadeDist, float maxFadeDist ); - - int GetBoneCacheFlags( void ) { return m_fBoneCacheFlags; } - inline void SetBoneCacheFlags( unsigned short fFlag ) { m_fBoneCacheFlags |= fFlag; } - inline void ClearBoneCacheFlags( unsigned short fFlag ) { m_fBoneCacheFlags &= ~fFlag; } - - bool PrefetchSequence( int iSequence ); - -private: - void LockStudioHdr(); - void UnlockStudioHdr(); - - void StudioFrameAdvanceInternal( CStudioHdr *pStudioHdr, float flInterval ); - void InputSetLightingOriginRelative( inputdata_t &inputdata ); - void InputSetLightingOrigin( inputdata_t &inputdata ); - - bool CanSkipAnimation( void ); - -public: - CNetworkVar( int, m_nForceBone ); - CNetworkVector( m_vecForce ); - - CNetworkVar( int, m_nSkin ); - CNetworkVar( int, m_nBody ); - CNetworkVar( int, m_nHitboxSet ); - - // For making things thin during barnacle swallowing, e.g. - CNetworkVar( float, m_flModelWidthScale ); - - // was pev->framerate - CNetworkVar( float, m_flPlaybackRate ); - -public: - void InitStepHeightAdjust( void ); - void SetIKGroundContactInfo( float minHeight, float maxHeight ); - void UpdateStepOrigin( void ); - -protected: - float m_flIKGroundContactTime; - float m_flIKGroundMinHeight; - float m_flIKGroundMaxHeight; - - float m_flEstIkFloor; // debounced - float m_flEstIkOffset; - - CIKContext *m_pIk; - int m_iIKCounter; - -public: - Vector GetStepOrigin( void ) const; - QAngle GetStepAngles( void ) const; - -private: - bool m_bSequenceFinished;// flag set when StudioAdvanceFrame moves across a frame boundry - bool m_bSequenceLoops; // true if the sequence loops - float m_flDissolveStartTime; - - // was pev->frame - CNetworkVar( float, m_flCycle ); - CNetworkVar( int, m_nSequence ); - CNetworkArray( float, m_flPoseParameter, NUM_POSEPAREMETERS ); // must be private so manual mode works! - CNetworkArray( float, m_flEncodedController, NUM_BONECTRLS ); // bone controller setting (0..1) - - // Client-side animation (useful for looping animation objects) - CNetworkVar( bool, m_bClientSideAnimation ); - CNetworkVar( bool, m_bClientSideFrameReset ); - - CNetworkVar( int, m_nNewSequenceParity ); - CNetworkVar( int, m_nResetEventsParity ); - - // Incremented each time the entity is told to do a muzzle flash. - // The client picks up the change and draws the flash. - CNetworkVar( unsigned char, m_nMuzzleFlashParity ); - - CNetworkHandle( CBaseEntity, m_hLightingOrigin ); - CNetworkHandle( CBaseEntity, m_hLightingOriginRelative ); - - string_t m_iszLightingOriginRelative; // for reading from the file only - string_t m_iszLightingOrigin; // for reading from the file only - - memhandle_t m_boneCacheHandle; - unsigned short m_fBoneCacheFlags; // Used for bone cache state on model - -protected: - CNetworkVar( float, m_fadeMinDist ); // Point at which fading is absolute - CNetworkVar( float, m_fadeMaxDist ); // Point at which fading is inactive - CNetworkVar( float, m_flFadeScale ); // Scale applied to min / max - -public: - COutputEvent m_OnIgnite; - -private: - CStudioHdr *m_pStudioHdr; - CThreadFastMutex m_StudioHdrInitLock; - CThreadFastMutex m_BoneSetupMutex; - -// FIXME: necessary so that cyclers can hack m_bSequenceFinished -friend class CFlexCycler; -friend class CCycler; -friend class CBlendingCycler; -}; - -//----------------------------------------------------------------------------- -// Purpose: return a pointer to an updated studiomdl cache cache -//----------------------------------------------------------------------------- -inline CStudioHdr *CBaseAnimating::GetModelPtr( void ) -{ -#ifdef _DEBUG - // GetModelPtr() is often called before OnNewModel() so go ahead and set it up first chance. - static IDataCacheSection *pModelCache = datacache->FindSection( "ModelData" ); - AssertOnce( pModelCache->IsFrameLocking() ); -#endif - if ( !m_pStudioHdr && GetModel() ) - { - LockStudioHdr(); - } - return ( m_pStudioHdr && m_pStudioHdr->IsValid() ) ? m_pStudioHdr : NULL; -} - -inline void CBaseAnimating::InvalidateMdlCache() -{ - UnlockStudioHdr(); - if ( m_pStudioHdr != NULL ) - { - delete m_pStudioHdr; - m_pStudioHdr = NULL; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Serves the 90% case of calling SetSequence / ResetSequenceInfo. -//----------------------------------------------------------------------------- - -/* -inline void CBaseAnimating::ResetSequence(int nSequence) -{ - m_nSequence = nSequence; - ResetSequenceInfo(); -} -*/ - -inline float CBaseAnimating::GetPlaybackRate() -{ - return m_flPlaybackRate; -} - -inline void CBaseAnimating::SetPlaybackRate( float rate ) -{ - m_flPlaybackRate = rate; -} - -inline void CBaseAnimating::SetLightingOrigin( CBaseEntity *pLightingOrigin ) -{ - m_hLightingOrigin = pLightingOrigin; -} - -inline CBaseEntity *CBaseAnimating::GetLightingOrigin() -{ - return m_hLightingOrigin; -} - -inline void CBaseAnimating::SetLightingOriginRelative( CBaseEntity *pLightingOriginRelative ) -{ - m_hLightingOriginRelative = pLightingOriginRelative; -} - -inline CBaseEntity *CBaseAnimating::GetLightingOriginRelative() -{ - return m_hLightingOriginRelative; -} - -//----------------------------------------------------------------------------- -// Cycle access -//----------------------------------------------------------------------------- -inline float CBaseAnimating::GetCycle() const -{ - return m_flCycle; -} - -inline void CBaseAnimating::SetCycle( float flCycle ) -{ - m_flCycle = flCycle; -} - - -EXTERN_SEND_TABLE(DT_BaseAnimating); - - - -#define ANIMATION_SEQUENCE_BITS 12 // 4096 sequences -#define ANIMATION_SKIN_BITS 10 // 1024 body skin selections FIXME: this seems way high -#define ANIMATION_BODY_BITS 32 // body combinations -#define ANIMATION_HITBOXSET_BITS 2 // hit box sets -#if defined( TF_DLL ) -#define ANIMATION_POSEPARAMETER_BITS 8 // pose parameter resolution -#else -#define ANIMATION_POSEPARAMETER_BITS 11 // pose parameter resolution -#endif -#define ANIMATION_PLAYBACKRATE_BITS 8 // default playback rate, only used on leading edge detect sequence changes - -#endif // BASEANIMATING_H diff --git a/game/server/basebludgeonweapon.cpp b/game/server/basebludgeonweapon.cpp deleted file mode 100644 index 7a08d7b86..000000000 --- a/game/server/basebludgeonweapon.cpp +++ /dev/null @@ -1,384 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include "cbase.h" -#include "basehlcombatweapon.h" -#include "player.h" -#include "gamerules.h" -#include "ammodef.h" -#include "mathlib/mathlib.h" -#include "in_buttons.h" -#include "soundent.h" -#include "animation.h" -#include "ai_condition.h" -#include "basebludgeonweapon.h" -#include "ndebugoverlay.h" -#include "te_effect_dispatch.h" -#include "rumble_shared.h" -#include "GameStats.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -IMPLEMENT_SERVERCLASS_ST( CBaseHLBludgeonWeapon, DT_BaseHLBludgeonWeapon ) -END_SEND_TABLE() - -#define BLUDGEON_HULL_DIM 16 - -static const Vector g_bludgeonMins(-BLUDGEON_HULL_DIM,-BLUDGEON_HULL_DIM,-BLUDGEON_HULL_DIM); -static const Vector g_bludgeonMaxs(BLUDGEON_HULL_DIM,BLUDGEON_HULL_DIM,BLUDGEON_HULL_DIM); - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CBaseHLBludgeonWeapon::CBaseHLBludgeonWeapon() -{ - m_bFiresUnderwater = true; -} - -//----------------------------------------------------------------------------- -// Purpose: Spawn the weapon -//----------------------------------------------------------------------------- -void CBaseHLBludgeonWeapon::Spawn( void ) -{ - m_fMinRange1 = 0; - m_fMinRange2 = 0; - m_fMaxRange1 = 64; - m_fMaxRange2 = 64; - //Call base class first - BaseClass::Spawn(); -} - -//----------------------------------------------------------------------------- -// Purpose: Precache the weapon -//----------------------------------------------------------------------------- -void CBaseHLBludgeonWeapon::Precache( void ) -{ - //Call base class first - BaseClass::Precache(); -} - -int CBaseHLBludgeonWeapon::CapabilitiesGet() -{ - return bits_CAP_WEAPON_MELEE_ATTACK1; -} - - -int CBaseHLBludgeonWeapon::WeaponMeleeAttack1Condition( float flDot, float flDist ) -{ - if (flDist > 64) - { - return COND_TOO_FAR_TO_ATTACK; - } - else if (flDot < 0.7) - { - return COND_NOT_FACING_ATTACK; - } - - return COND_CAN_MELEE_ATTACK1; -} - -//------------------------------------------------------------------------------ -// Purpose : Update weapon -//------------------------------------------------------------------------------ -void CBaseHLBludgeonWeapon::ItemPostFrame( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - if ( (pOwner->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime) ) - { - PrimaryAttack(); - } - else if ( (pOwner->m_nButtons & IN_ATTACK2) && (m_flNextSecondaryAttack <= gpGlobals->curtime) ) - { - SecondaryAttack(); - } - else - { - WeaponIdle(); - return; - } -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBaseHLBludgeonWeapon::PrimaryAttack() -{ - Swing( false ); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBaseHLBludgeonWeapon::SecondaryAttack() -{ - Swing( true ); -} - - -//------------------------------------------------------------------------------ -// Purpose: Implement impact function -//------------------------------------------------------------------------------ -void CBaseHLBludgeonWeapon::Hit( trace_t &traceHit, Activity nHitActivity, bool bIsSecondary ) -{ - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - //Do view kick - AddViewKick(); - - //Make sound for the AI - CSoundEnt::InsertSound( SOUND_BULLET_IMPACT, traceHit.endpos, 400, 0.2f, pPlayer ); - - // This isn't great, but it's something for when the crowbar hits. - pPlayer->RumbleEffect( RUMBLE_AR2, 0, RUMBLE_FLAG_RESTART ); - - CBaseEntity *pHitEntity = traceHit.m_pEnt; - - //Apply damage to a hit target - if ( pHitEntity != NULL ) - { - Vector hitDirection; - pPlayer->EyeVectors( &hitDirection, NULL, NULL ); - VectorNormalize( hitDirection ); - - CTakeDamageInfo info( GetOwner(), GetOwner(), GetDamageForActivity( nHitActivity ), DMG_CLUB ); - - if( pPlayer && pHitEntity->IsNPC() ) - { - // If bonking an NPC, adjust damage. - info.AdjustPlayerDamageInflictedForSkillLevel(); - } - - CalculateMeleeDamageForce( &info, hitDirection, traceHit.endpos ); - - pHitEntity->DispatchTraceAttack( info, hitDirection, &traceHit ); - ApplyMultiDamage(); - - // Now hit all triggers along the ray that... - TraceAttackToTriggers( info, traceHit.startpos, traceHit.endpos, hitDirection ); - - if ( ToBaseCombatCharacter( pHitEntity ) ) - { - gamestats->Event_WeaponHit( pPlayer, !bIsSecondary, GetClassname(), info ); - } - } - - // Apply an impact effect - ImpactEffect( traceHit ); -} - -Activity CBaseHLBludgeonWeapon::ChooseIntersectionPointAndActivity( trace_t &hitTrace, const Vector &mins, const Vector &maxs, CBasePlayer *pOwner ) -{ - int i, j, k; - float distance; - const float *minmaxs[2] = {mins.Base(), maxs.Base()}; - trace_t tmpTrace; - Vector vecHullEnd = hitTrace.endpos; - Vector vecEnd; - - distance = 1e6f; - Vector vecSrc = hitTrace.startpos; - - vecHullEnd = vecSrc + ((vecHullEnd - vecSrc)*2); - UTIL_TraceLine( vecSrc, vecHullEnd, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &tmpTrace ); - if ( tmpTrace.fraction == 1.0 ) - { - for ( i = 0; i < 2; i++ ) - { - for ( j = 0; j < 2; j++ ) - { - for ( k = 0; k < 2; k++ ) - { - vecEnd.x = vecHullEnd.x + minmaxs[i][0]; - vecEnd.y = vecHullEnd.y + minmaxs[j][1]; - vecEnd.z = vecHullEnd.z + minmaxs[k][2]; - - UTIL_TraceLine( vecSrc, vecEnd, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &tmpTrace ); - if ( tmpTrace.fraction < 1.0 ) - { - float thisDistance = (tmpTrace.endpos - vecSrc).Length(); - if ( thisDistance < distance ) - { - hitTrace = tmpTrace; - distance = thisDistance; - } - } - } - } - } - } - else - { - hitTrace = tmpTrace; - } - - - return ACT_VM_HITCENTER; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &traceHit - -//----------------------------------------------------------------------------- -bool CBaseHLBludgeonWeapon::ImpactWater( const Vector &start, const Vector &end ) -{ - //FIXME: This doesn't handle the case of trying to splash while being underwater, but that's not going to look good - // right now anyway... - - // We must start outside the water - if ( UTIL_PointContents( start ) & (CONTENTS_WATER|CONTENTS_SLIME)) - return false; - - // We must end inside of water - if ( !(UTIL_PointContents( end ) & (CONTENTS_WATER|CONTENTS_SLIME))) - return false; - - trace_t waterTrace; - - UTIL_TraceLine( start, end, (CONTENTS_WATER|CONTENTS_SLIME), GetOwner(), COLLISION_GROUP_NONE, &waterTrace ); - - if ( waterTrace.fraction < 1.0f ) - { - CEffectData data; - - data.m_fFlags = 0; - data.m_vOrigin = waterTrace.endpos; - data.m_vNormal = waterTrace.plane.normal; - data.m_flScale = 8.0f; - - // See if we hit slime - if ( waterTrace.contents & CONTENTS_SLIME ) - { - data.m_fFlags |= FX_WATER_IN_SLIME; - } - - DispatchEffect( "watersplash", data ); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseHLBludgeonWeapon::ImpactEffect( trace_t &traceHit ) -{ - // See if we hit water (we don't do the other impact effects in this case) - if ( ImpactWater( traceHit.startpos, traceHit.endpos ) ) - return; - - //FIXME: need new decals - UTIL_ImpactTrace( &traceHit, DMG_CLUB ); -} - - -//------------------------------------------------------------------------------ -// Purpose : Starts the swing of the weapon and determines the animation -// Input : bIsSecondary - is this a secondary attack? -//------------------------------------------------------------------------------ -void CBaseHLBludgeonWeapon::Swing( int bIsSecondary ) -{ - trace_t traceHit; - - // Try a ray - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( !pOwner ) - return; - - pOwner->RumbleEffect( RUMBLE_CROWBAR_SWING, 0, RUMBLE_FLAG_RESTART ); - - Vector swingStart = pOwner->Weapon_ShootPosition( ); - Vector forward; - - forward = pOwner->GetAutoaimVector( AUTOAIM_SCALE_DEFAULT, GetRange() ); - - Vector swingEnd = swingStart + forward * GetRange(); - UTIL_TraceLine( swingStart, swingEnd, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &traceHit ); - Activity nHitActivity = ACT_VM_HITCENTER; - - // Like bullets, bludgeon traces have to trace against triggers. - CTakeDamageInfo triggerInfo( GetOwner(), GetOwner(), GetDamageForActivity( nHitActivity ), DMG_CLUB ); - triggerInfo.SetDamagePosition( traceHit.startpos ); - triggerInfo.SetDamageForce( forward ); - TraceAttackToTriggers( triggerInfo, traceHit.startpos, traceHit.endpos, forward ); - - if ( traceHit.fraction == 1.0 ) - { - float bludgeonHullRadius = 1.732f * BLUDGEON_HULL_DIM; // hull is +/- 16, so use cuberoot of 2 to determine how big the hull is from center to the corner point - - // Back off by hull "radius" - swingEnd -= forward * bludgeonHullRadius; - - UTIL_TraceHull( swingStart, swingEnd, g_bludgeonMins, g_bludgeonMaxs, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &traceHit ); - if ( traceHit.fraction < 1.0 && traceHit.m_pEnt ) - { - Vector vecToTarget = traceHit.m_pEnt->GetAbsOrigin() - swingStart; - VectorNormalize( vecToTarget ); - - float dot = vecToTarget.Dot( forward ); - - // YWB: Make sure they are sort of facing the guy at least... - if ( dot < 0.70721f ) - { - // Force amiss - traceHit.fraction = 1.0f; - } - else - { - nHitActivity = ChooseIntersectionPointAndActivity( traceHit, g_bludgeonMins, g_bludgeonMaxs, pOwner ); - } - } - } - - if ( !bIsSecondary ) - { - m_iPrimaryAttacks++; - } - else - { - m_iSecondaryAttacks++; - } - - gamestats->Event_WeaponFired( pOwner, !bIsSecondary, GetClassname() ); - - // ------------------------- - // Miss - // ------------------------- - if ( traceHit.fraction == 1.0f ) - { - nHitActivity = bIsSecondary ? ACT_VM_MISSCENTER2 : ACT_VM_MISSCENTER; - - // We want to test the first swing again - Vector testEnd = swingStart + forward * GetRange(); - - // See if we happened to hit water - ImpactWater( swingStart, testEnd ); - } - else - { - Hit( traceHit, nHitActivity, bIsSecondary ? true : false ); - } - - // Send the anim - SendWeaponAnim( nHitActivity ); - - //Setup our next attack times - m_flNextPrimaryAttack = gpGlobals->curtime + GetFireRate(); - m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration(); - - //Play swing sound - WeaponSound( SINGLE ); -} diff --git a/game/server/basebludgeonweapon.h b/game/server/basebludgeonweapon.h deleted file mode 100644 index 51fc7cd4a..000000000 --- a/game/server/basebludgeonweapon.h +++ /dev/null @@ -1,57 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: The class from which all bludgeon melee -// weapons are derived. -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#include "basehlcombatweapon.h" - -#ifndef BASEBLUDGEONWEAPON_H -#define BASEBLUDGEONWEAPON_H - -//========================================================= -// CBaseHLBludgeonWeapon -//========================================================= -class CBaseHLBludgeonWeapon : public CBaseHLCombatWeapon -{ - DECLARE_CLASS( CBaseHLBludgeonWeapon, CBaseHLCombatWeapon ); -public: - CBaseHLBludgeonWeapon(); - - DECLARE_SERVERCLASS(); - - virtual void Spawn( void ); - virtual void Precache( void ); - - //Attack functions - virtual void PrimaryAttack( void ); - virtual void SecondaryAttack( void ); - - virtual void ItemPostFrame( void ); - - //Functions to select animation sequences - virtual Activity GetPrimaryAttackActivity( void ) { return ACT_VM_HITCENTER; } - virtual Activity GetSecondaryAttackActivity( void ) { return ACT_VM_HITCENTER2; } - - virtual float GetFireRate( void ) { return 0.2f; } - virtual float GetRange( void ) { return 32.0f; } - virtual float GetDamageForActivity( Activity hitActivity ) { return 1.0f; } - - virtual int CapabilitiesGet( void ); - virtual int WeaponMeleeAttack1Condition( float flDot, float flDist ); - -protected: - virtual void ImpactEffect( trace_t &trace ); - -private: - bool ImpactWater( const Vector &start, const Vector &end ); - void Swing( int bIsSecondary ); - void Hit( trace_t &traceHit, Activity nHitActivity, bool bIsSecondary ); - Activity ChooseIntersectionPointAndActivity( trace_t &hitTrace, const Vector &mins, const Vector &maxs, CBasePlayer *pOwner ); -}; - -#endif diff --git a/game/server/basecombatcharacter.cpp b/game/server/basecombatcharacter.cpp deleted file mode 100644 index 4ef15cf07..000000000 --- a/game/server/basecombatcharacter.cpp +++ /dev/null @@ -1,3198 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Base combat character with no AI -// -//=============================================================================// - -#include "cbase.h" -#include "basecombatcharacter.h" -#include "basecombatweapon.h" -#include "animation.h" -#include "gib.h" -#include "entitylist.h" -#include "gamerules.h" -#include "ai_basenpc.h" -#include "ai_squadslot.h" -#include "ammodef.h" -#include "ndebugoverlay.h" -#include "player.h" -#include "physics.h" -#include "engine/IEngineSound.h" -#include "tier1/strtools.h" -#include "sendproxy.h" -#include "EntityFlame.h" -#include "CRagdollMagnet.h" -#include "IEffects.h" -#include "iservervehicle.h" -#include "igamesystem.h" -#include "globals.h" -#include "physics_prop_ragdoll.h" -#include "physics_impact_damage.h" -#include "saverestore_utlvector.h" -#include "eventqueue.h" -#include "world.h" -#include "globalstate.h" -#include "items.h" -#include "movevars_shared.h" -#include "RagdollBoogie.h" -#include "rumble_shared.h" -#include "saverestoretypes.h" - -#ifdef HL2_DLL -#include "weapon_physcannon.h" -#include "hl2_gamerules.h" -#endif - -#ifdef PORTAL - #include "portal_util_shared.h" - #include "prop_portal_shared.h" - #include "portal_shareddefs.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#ifdef HL2_DLL -extern int g_interactionBarnacleVictimReleased; -#endif //HL2_DLL - -extern ConVar weapon_showproficiency; - -ConVar ai_show_hull_attacks( "ai_show_hull_attacks", "0" ); -ConVar ai_force_serverside_ragdoll( "ai_force_serverside_ragdoll", "0" ); - -#ifndef _RETAIL -ConVar ai_use_visibility_cache( "ai_use_visibility_cache", "1" ); -#define ShouldUseVisibilityCache() ai_use_visibility_cache.GetBool() -#else -#define ShouldUseVisibilityCache() true -#endif - -BEGIN_DATADESC( CBaseCombatCharacter ) - -#ifdef INVASION_DLL - DEFINE_FIELD( m_iPowerups, FIELD_INTEGER ), - DEFINE_ARRAY( m_flPowerupAttemptTimes, FIELD_TIME, MAX_POWERUPS ), - DEFINE_ARRAY( m_flPowerupEndTimes, FIELD_TIME, MAX_POWERUPS ), - DEFINE_FIELD( m_flFractionalBoost, FIELD_FLOAT ), -#endif - - DEFINE_FIELD( m_flNextAttack, FIELD_TIME ), - DEFINE_FIELD( m_eHull, FIELD_INTEGER ), - DEFINE_FIELD( m_bloodColor, FIELD_INTEGER ), - DEFINE_FIELD( m_iDamageCount, FIELD_INTEGER ), - - DEFINE_FIELD( m_flFieldOfView, FIELD_FLOAT ), - DEFINE_FIELD( m_HackedGunPos, FIELD_VECTOR ), - DEFINE_KEYFIELD( m_RelationshipString, FIELD_STRING, "Relationship" ), - - DEFINE_FIELD( m_LastHitGroup, FIELD_INTEGER ), - DEFINE_FIELD( m_flDamageAccumulator, FIELD_FLOAT ), - DEFINE_INPUT( m_impactEnergyScale, FIELD_FLOAT, "physdamagescale" ), - DEFINE_FIELD( m_CurrentWeaponProficiency, FIELD_INTEGER), - - DEFINE_UTLVECTOR( m_Relationship, FIELD_EMBEDDED), - - DEFINE_AUTO_ARRAY( m_iAmmo, FIELD_INTEGER ), - DEFINE_AUTO_ARRAY( m_hMyWeapons, FIELD_EHANDLE ), - DEFINE_FIELD( m_hActiveWeapon, FIELD_EHANDLE ), - DEFINE_FIELD( m_bForceServerRagdoll, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bPreventWeaponPickup, FIELD_BOOLEAN ), - - DEFINE_INPUTFUNC( FIELD_VOID, "KilledNPC", InputKilledNPC ), - -END_DATADESC() - - -BEGIN_SIMPLE_DATADESC( Relationship_t ) - DEFINE_FIELD( entity, FIELD_EHANDLE ), - DEFINE_FIELD( classType, FIELD_INTEGER ), - DEFINE_FIELD( disposition, FIELD_INTEGER ), - DEFINE_FIELD( priority, FIELD_INTEGER ), -END_DATADESC() - -//----------------------------------------------------------------------------- -// Init static variables -//----------------------------------------------------------------------------- -int CBaseCombatCharacter::m_lastInteraction = 0; -Relationship_t** CBaseCombatCharacter::m_DefaultRelationship = NULL; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CCleanupDefaultRelationShips : public CAutoGameSystem -{ -public: - CCleanupDefaultRelationShips( char const *name ) : CAutoGameSystem( name ) - { - } - - virtual void Shutdown() - { - if ( !CBaseCombatCharacter::m_DefaultRelationship ) - return; - - for ( int i=0; iClearAllRecipients(); - - CBaseCombatCharacter *pBCC = ( CBaseCombatCharacter * )pStruct; - if ( pBCC != NULL) - { - if ( pBCC->IsPlayer() ) - { - pRecipients->SetOnly( pBCC->entindex() - 1 ); - } - else - { - // If it's a vehicle, send to "driver" (e.g., operator of tf2 manned guns) - IServerVehicle *pVehicle = pBCC->GetServerVehicle(); - if ( pVehicle != NULL ) - { - CBaseCombatCharacter *pDriver = pVehicle->GetPassenger(); - if ( pDriver != NULL ) - { - pRecipients->SetOnly( pDriver->entindex() - 1 ); - } - } - } - } - return ( void * )pVarData; -} -REGISTER_SEND_PROXY_NON_MODIFIED_POINTER( SendProxy_SendBaseCombatCharacterLocalDataTable ); - -// Only send active weapon index to local player -BEGIN_SEND_TABLE_NOBASE( CBaseCombatCharacter, DT_BCCLocalPlayerExclusive ) - SendPropTime( SENDINFO( m_flNextAttack ) ), -END_SEND_TABLE(); - -//----------------------------------------------------------------------------- -// This table encodes the CBaseCombatCharacter -//----------------------------------------------------------------------------- -IMPLEMENT_SERVERCLASS_ST(CBaseCombatCharacter, DT_BaseCombatCharacter) - // Data that only gets sent to the local player. - SendPropDataTable( "bcc_localdata", 0, &REFERENCE_SEND_TABLE(DT_BCCLocalPlayerExclusive), SendProxy_SendBaseCombatCharacterLocalDataTable ), - - SendPropEHandle( SENDINFO( m_hActiveWeapon ) ), - SendPropArray3( SENDINFO_ARRAY3(m_hMyWeapons), SendPropEHandle( SENDINFO_ARRAY(m_hMyWeapons) ) ), - -#ifdef INVASION_DLL - SendPropInt( SENDINFO(m_iPowerups), MAX_POWERUPS, SPROP_UNSIGNED ), -#endif - -END_SEND_TABLE() - - -//----------------------------------------------------------------------------- -// Interactions -//----------------------------------------------------------------------------- -void CBaseCombatCharacter::InitInteractionSystem() -{ - // interaction ids continue to go up with every map load, otherwise you get - // collisions if a future map has a different set of NPCs from a current map -} - - -//----------------------------------------------------------------------------- -// Purpose: Return an interaction ID (so we have no collisions) -//----------------------------------------------------------------------------- -int CBaseCombatCharacter::GetInteractionID(void) -{ - m_lastInteraction++; - return (m_lastInteraction); -} - -// ============================================================================ -bool CBaseCombatCharacter::HasHumanGibs( void ) -{ -#if defined( HL2_DLL ) - Class_T myClass = Classify(); - if ( myClass == CLASS_CITIZEN_PASSIVE || - myClass == CLASS_CITIZEN_REBEL || - myClass == CLASS_COMBINE || - myClass == CLASS_CONSCRIPT || - myClass == CLASS_METROPOLICE || - myClass == CLASS_PLAYER ) - return true; - -#elif defined( HL1_DLL ) - Class_T myClass = Classify(); - if ( myClass == CLASS_HUMAN_MILITARY || - myClass == CLASS_PLAYER_ALLY || - myClass == CLASS_HUMAN_PASSIVE || - myClass == CLASS_PLAYER ) - { - return true; - } - -#elif defined( CSPORT_DLL ) - Class_T myClass = Classify(); - if ( myClass == CLASS_PLAYER ) - { - return true; - } - -#endif - - return false; -} - - -bool CBaseCombatCharacter::HasAlienGibs( void ) -{ -#if defined( HL2_DLL ) - Class_T myClass = Classify(); - if ( myClass == CLASS_BARNACLE || - myClass == CLASS_STALKER || - myClass == CLASS_ZOMBIE || - myClass == CLASS_VORTIGAUNT || - myClass == CLASS_HEADCRAB ) - { - return true; - } - -#elif defined( HL1_DLL ) - Class_T myClass = Classify(); - if ( myClass == CLASS_ALIEN_MILITARY || - myClass == CLASS_ALIEN_MONSTER || - myClass == CLASS_INSECT || - myClass == CLASS_ALIEN_PREDATOR || - myClass == CLASS_ALIEN_PREY ) - { - return true; - } -#endif - - return false; -} - - -void CBaseCombatCharacter::CorpseFade( void ) -{ - StopAnimation(); - SetAbsVelocity( vec3_origin ); - SetMoveType( MOVETYPE_NONE ); - SetLocalAngularVelocity( vec3_angle ); - m_flAnimTime = gpGlobals->curtime; - AddEffects( EF_NOINTERP ); - SUB_StartFadeOut(); -} - -//----------------------------------------------------------------------------- -// Visibility caching -//----------------------------------------------------------------------------- - -struct VisibilityCacheEntry_t -{ - CBaseEntity *pEntity1; - CBaseEntity *pEntity2; - EHANDLE pBlocker; - float time; -}; - -class CVisibilityCacheEntryLess -{ -public: - CVisibilityCacheEntryLess( int ) {} - bool operator!() const { return false; } - bool operator()( const VisibilityCacheEntry_t &lhs, const VisibilityCacheEntry_t &rhs ) const - { - return ( memcmp( &lhs, &rhs, offsetof( VisibilityCacheEntry_t, pBlocker ) ) < 0 ); - } -}; - -static CUtlRBTree g_VisibilityCache; -const float VIS_CACHE_ENTRY_LIFE = ( !IsXbox() ) ? .090 : .500; - -bool CBaseCombatCharacter::FVisible( CBaseEntity *pEntity, int traceMask, CBaseEntity **ppBlocker ) -{ - VPROF( "CBaseCombatCharacter::FVisible" ); - - if ( traceMask != MASK_BLOCKLOS || !ShouldUseVisibilityCache() || pEntity == this -#if defined(HL2_DLL) - || Classify() == CLASS_BULLSEYE || pEntity->Classify() == CLASS_BULLSEYE -#endif - ) - { - return BaseClass::FVisible( pEntity, traceMask, ppBlocker ); - } - - VisibilityCacheEntry_t cacheEntry; - - if ( this < pEntity ) - { - cacheEntry.pEntity1 = this; - cacheEntry.pEntity2 = pEntity; - } - else - { - cacheEntry.pEntity1 = pEntity; - cacheEntry.pEntity2 = this; - } - - int iCache = g_VisibilityCache.Find( cacheEntry ); - - if ( iCache != g_VisibilityCache.InvalidIndex() ) - { - if ( gpGlobals->curtime - g_VisibilityCache[iCache].time < VIS_CACHE_ENTRY_LIFE ) - { - bool bCachedResult = !g_VisibilityCache[iCache].pBlocker.IsValid(); - if ( bCachedResult ) - { - if ( ppBlocker ) - { - *ppBlocker = g_VisibilityCache[iCache].pBlocker; - if ( !*ppBlocker ) - { - *ppBlocker = GetWorldEntity(); - } - } - } - else - { - if ( ppBlocker ) - { - *ppBlocker = NULL; - } - } - return bCachedResult; - } - } - else - { - if ( g_VisibilityCache.Count() != g_VisibilityCache.InvalidIndex() ) - { - iCache = g_VisibilityCache.Insert( cacheEntry ); - } - else - { - return BaseClass::FVisible( pEntity, traceMask, ppBlocker ); - } - } - - CBaseEntity *pBlocker = NULL; - if ( ppBlocker == NULL ) - { - ppBlocker = &pBlocker; - } - - bool bResult = BaseClass::FVisible( pEntity, traceMask, ppBlocker ); - - if ( !bResult ) - { - g_VisibilityCache[iCache].pBlocker = *ppBlocker; - } - else - { - g_VisibilityCache[iCache].pBlocker = NULL; - } - - g_VisibilityCache[iCache].time = gpGlobals->curtime; - - return bResult; -} - -void CBaseCombatCharacter::ResetVisibilityCache( CBaseCombatCharacter *pBCC ) -{ - VPROF( "CBaseCombatCharacter::ResetVisibilityCache" ); - if ( !pBCC ) - { - g_VisibilityCache.RemoveAll(); - return; - } - - int i = g_VisibilityCache.FirstInorder(); - CUtlVector removals; - while ( i != g_VisibilityCache.InvalidIndex() ) - { - if ( g_VisibilityCache[i].pEntity1 == pBCC || g_VisibilityCache[i].pEntity2 == pBCC ) - { - removals.AddToTail( i ); - } - i = g_VisibilityCache.NextInorder( i ); - } - - for ( i = 0; i < removals.Count(); i++ ) - { - g_VisibilityCache.RemoveAt( removals[i] ); - } -} - -#ifdef PORTAL -bool CBaseCombatCharacter::FVisibleThroughPortal( const CProp_Portal *pPortal, CBaseEntity *pEntity, int traceMask, CBaseEntity **ppBlocker ) -{ - VPROF( "CBaseCombatCharacter::FVisible" ); - - if ( pEntity->GetFlags() & FL_NOTARGET ) - return false; - -#if HL1_DLL - // FIXME: only block LOS through opaque water - // don't look through water - if ((m_nWaterLevel != 3 && pEntity->m_nWaterLevel == 3) - || (m_nWaterLevel == 3 && pEntity->m_nWaterLevel == 0)) - return false; -#endif - - Vector vecLookerOrigin = EyePosition();//look through the caller's 'eyes' - Vector vecTargetOrigin = pEntity->EyePosition(); - - // Use the custom LOS trace filter - CTraceFilterLOS traceFilter( this, COLLISION_GROUP_NONE, pEntity ); - - Vector vecTranslatedTargetOrigin; - UTIL_Portal_PointTransform( pPortal->m_hLinkedPortal->MatrixThisToLinked(), vecTargetOrigin, vecTranslatedTargetOrigin ); - Ray_t ray; - ray.Init( vecLookerOrigin, vecTranslatedTargetOrigin ); - - trace_t tr; - - // If we're doing an opaque search, include NPCs. - if ( traceMask == MASK_BLOCKLOS ) - { - traceMask = MASK_BLOCKLOS_AND_NPCS; - } - - UTIL_Portal_TraceRay_Bullets( pPortal, ray, traceMask, &traceFilter, &tr ); - - if (tr.fraction != 1.0 || tr.startsolid ) - { - // If we hit the entity we're looking for, it's visible - if ( tr.m_pEnt == pEntity ) - return true; - - // Got line of sight on the vehicle the player is driving! - if ( pEntity && pEntity->IsPlayer() ) - { - CBasePlayer *pPlayer = assert_cast( pEntity ); - if ( tr.m_pEnt == pPlayer->GetVehicleEntity() ) - return true; - } - - if (ppBlocker) - { - *ppBlocker = tr.m_pEnt; - } - - return false;// Line of sight is not established - } - - return true;// line of sight is valid. -} -#endif - -//----------------------------------------------------------------------------- - -//========================================================= -// FInViewCone - returns true is the passed ent is in -// the caller's forward view cone. The dot product is performed -// in 2d, making the view cone infinitely tall. -//========================================================= -bool CBaseCombatCharacter::FInViewCone( CBaseEntity *pEntity ) -{ - return FInViewCone( pEntity->WorldSpaceCenter() ); -} - -//========================================================= -// FInViewCone - returns true is the passed Vector is in -// the caller's forward view cone. The dot product is performed -// in 2d, making the view cone infinitely tall. -//========================================================= -bool CBaseCombatCharacter::FInViewCone( const Vector &vecSpot ) -{ - Vector los = ( vecSpot - EyePosition() ); - - // do this in 2D - los.z = 0; - VectorNormalize( los ); - - Vector facingDir = EyeDirection2D( ); - - float flDot = DotProduct( los, facingDir ); - - if ( flDot > m_flFieldOfView ) - return true; - - return false; -} - -#ifdef PORTAL -//========================================================= -// FInViewCone - returns true is the passed ent is in -// the caller's forward view cone. The dot product is performed -// in 2d, making the view cone infinitely tall. -//========================================================= -CProp_Portal* CBaseCombatCharacter::FInViewConeThroughPortal( CBaseEntity *pEntity ) -{ - return FInViewConeThroughPortal( pEntity->WorldSpaceCenter() ); -} - -//========================================================= -// FInViewCone - returns true is the passed Vector is in -// the caller's forward view cone. The dot product is performed -// in 2d, making the view cone infinitely tall. -//========================================================= -CProp_Portal* CBaseCombatCharacter::FInViewConeThroughPortal( const Vector &vecSpot ) -{ - int iPortalCount = CProp_Portal_Shared::AllPortals.Count(); - if( iPortalCount == 0 ) - return NULL; - - const Vector ptEyePosition = EyePosition(); - - float fDistToBeat = 1e20; //arbitrarily high number - CProp_Portal *pBestPortal = NULL; - - CProp_Portal **pPortals = CProp_Portal_Shared::AllPortals.Base(); - - // Check through both portals - for ( int iPortal = 0; iPortal < iPortalCount; ++iPortal ) - { - CProp_Portal *pPortal = pPortals[iPortal]; - - // Check if this portal is active, linked, and in the view cone - if( pPortal->IsActivedAndLinked() && FInViewCone( pPortal ) ) - { - // The facing direction is the eye to the portal to set up a proper FOV through the relatively small portal hole - Vector facingDir = pPortal->GetAbsOrigin() - ptEyePosition; - - // If the portal isn't facing the eye, bail - if ( facingDir.Dot( pPortal->m_plane_Origin.normal ) > 0.0f ) - continue; - - // If the point is behind the linked portal, bail - if ( ( vecSpot - pPortal->m_hLinkedPortal->GetAbsOrigin() ).Dot( pPortal->m_hLinkedPortal->m_plane_Origin.normal ) < 0.0f ) - continue; - - // Remove height from the equation - facingDir.z = 0.0f; - float fPortalDist = VectorNormalize( facingDir ); - - // Translate the target spot across the portal - Vector vTranslatedVecSpot; - UTIL_Portal_PointTransform( pPortal->m_hLinkedPortal->MatrixThisToLinked(), vecSpot, vTranslatedVecSpot ); - - // do this in 2D - Vector los = ( vTranslatedVecSpot - ptEyePosition ); - los.z = 0.0f; - float fSpotDist = VectorNormalize( los ); - - if( fSpotDist > fDistToBeat ) - continue; //no point in going further, we already have a better portal - - // If the target point is closer than the portal (banana juice), bail - // HACK: Extra 32 is a fix for the player who's origin can be on one side of a portal while his center mirrored across is closer than the portal. - if ( fPortalDist > fSpotDist + 32.0f ) - continue; - - // Get the worst case FOV from the portal's corners - float fFOVThroughPortal = 1.0f; - - for ( int i = 0; i < 4; ++i ) - { - //Vector vPortalCorner = pPortal->GetAbsOrigin() + vPortalRight * PORTAL_HALF_WIDTH * ( ( i / 2 == 0 ) ? ( 1.0f ) : ( -1.0f ) ) + - // vPortalUp * PORTAL_HALF_HEIGHT * ( ( i % 2 == 0 ) ? ( 1.0f ) : ( -1.0f ) ); - - Vector vEyeToCorner = pPortal->m_vPortalCorners[i] - ptEyePosition; - vEyeToCorner.z = 0.0f; - VectorNormalize( vEyeToCorner ); - - float flCornerDot = DotProduct( vEyeToCorner, facingDir ); - - if ( flCornerDot < fFOVThroughPortal ) - fFOVThroughPortal = flCornerDot; - } - - float flDot = DotProduct( los, facingDir ); - - // Use the tougher FOV of either the standard FOV or FOV clipped to the portal hole - if ( flDot > MAX( fFOVThroughPortal, m_flFieldOfView ) ) - { - float fActualDist = ptEyePosition.DistToSqr( vTranslatedVecSpot ); - if( fActualDist < fDistToBeat ) - { - fDistToBeat = fActualDist; - pBestPortal = pPortal; - } - } - } - } - - return pBestPortal; -} -#endif - - -//========================================================= -// FInAimCone - returns true is the passed ent is in -// the caller's forward aim cone. The dot product is performed -// in 2d, making the aim cone infinitely tall. -//========================================================= -bool CBaseCombatCharacter::FInAimCone( CBaseEntity *pEntity ) -{ - return FInAimCone( pEntity->BodyTarget( EyePosition() ) ); -} - - -//========================================================= -// FInAimCone - returns true is the passed Vector is in -// the caller's forward aim cone. The dot product is performed -// in 2d, making the view cone infinitely tall. By default, the -// callers aim cone is assumed to be very narrow -//========================================================= -bool CBaseCombatCharacter::FInAimCone( const Vector &vecSpot ) -{ - Vector los = ( vecSpot - GetAbsOrigin() ); - - // do this in 2D - los.z = 0; - VectorNormalize( los ); - - Vector facingDir = BodyDirection2D( ); - - float flDot = DotProduct( los, facingDir ); - - if ( flDot > 0.994 )//!!!BUGBUG - magic number same as FacingIdeal(), what is this? - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: This is a generic function (to be implemented by sub-classes) to -// handle specific interactions between different types of characters -// (For example the barnacle grabbing an NPC) -// Input : The type of interaction, extra info pointer, and who started it -// Output : true - if sub-class has a response for the interaction -// false - if sub-class has no response -//----------------------------------------------------------------------------- -bool CBaseCombatCharacter::HandleInteraction( int interactionType, void *data, CBaseCombatCharacter* sourceEnt ) -{ -#ifdef HL2_DLL - if ( interactionType == g_interactionBarnacleVictimReleased ) - { - // For now, throw away the NPC and leave the ragdoll. - UTIL_Remove( this ); - return true; - } -#endif // HL2_DLL - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Constructor : Initialize some fields -//----------------------------------------------------------------------------- -CBaseCombatCharacter::CBaseCombatCharacter( void ) -{ -#ifdef _DEBUG - // necessary since in debug, we initialize vectors to NAN for debugging - m_HackedGunPos.Init(); -#endif - - // Zero the damage accumulator. - m_flDamageAccumulator = 0.0f; - - // Init weapon and Ammo data - m_hActiveWeapon = NULL; - - // reset all ammo values to 0 - RemoveAllAmmo(); - - for (int i = 0; i < MAX_WEAPONS; i++) - { - m_hMyWeapons.Set( i, NULL ); - } - - // Default so that spawned entities have this set - m_impactEnergyScale = 1.0f; - - m_bForceServerRagdoll = ai_force_serverside_ragdoll.GetBool(); -} - -//------------------------------------------------------------------------------ -// Purpose : Destructor -// Input : -// Output : -//------------------------------------------------------------------------------ -CBaseCombatCharacter::~CBaseCombatCharacter( void ) -{ - ResetVisibilityCache( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseCombatCharacter::Precache() -{ - BaseClass::Precache(); - - PrecacheScriptSound( "BaseCombatCharacter.CorpseGib" ); - PrecacheScriptSound( "BaseCombatCharacter.StopWeaponSounds" ); - PrecacheScriptSound( "BaseCombatCharacter.AmmoPickup" ); - - for ( int i = m_Relationship.Count() - 1; i >= 0 ; i--) - { - if ( !m_Relationship[i].entity && m_Relationship[i].classType == CLASS_NONE ) - { - DevMsg( 2, "Removing relationship for lost entity\n" ); - m_Relationship.FastRemove( i ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBaseCombatCharacter::Restore( IRestore &restore ) -{ - int status = BaseClass::Restore(restore); - if ( !status ) - return 0; - - if ( gpGlobals->eLoadType == MapLoad_Transition ) - { - DevMsg( 2, "%s (%s) removing class relationships due to level transition\n", STRING( GetEntityName() ), GetClassname() ); - - for ( int i = m_Relationship.Count() - 1; i >= 0; --i ) - { - if ( !m_Relationship[i].entity && m_Relationship[i].classType != CLASS_NONE ) - { - m_Relationship.FastRemove( i ); - } - } - } - return status; -} - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseCombatCharacter::UpdateOnRemove( void ) -{ - int i; - // Make sure any weapons I didn't drop get removed. - for (i=0;iDeathNotice( this ); - SetOwnerEntity( NULL ); - } - - // Chain at end to mimic destructor unwind order - BaseClass::UpdateOnRemove(); -} - - -//========================================================= -// CorpseGib - create some gore and get rid of a character's -// model. -//========================================================= -bool CBaseCombatCharacter::CorpseGib( const CTakeDamageInfo &info ) -{ - trace_t tr; - bool gibbed = false; - - EmitSound( "BaseCombatCharacter.CorpseGib" ); - - // only humans throw skulls !!!UNDONE - eventually NPCs will have their own sets of gibs - if ( HasHumanGibs() ) - { - CGib::SpawnHeadGib( this ); - CGib::SpawnRandomGibs( this, 4, GIB_HUMAN ); // throw some human gibs. - gibbed = true; - } - else if ( HasAlienGibs() ) - { - CGib::SpawnRandomGibs( this, 4, GIB_ALIEN ); // Throw alien gibs - gibbed = true; - } - - return gibbed; -} - -//========================================================= -// GetDeathActivity - determines the best type of death -// anim to play. -//========================================================= -Activity CBaseCombatCharacter::GetDeathActivity ( void ) -{ - Activity deathActivity; - bool fTriedDirection; - float flDot; - trace_t tr; - Vector vecSrc; - - if (IsPlayer()) - { - // die in an interesting way - switch( random->RandomInt(0,7) ) - { - case 0: return ACT_DIESIMPLE; - case 1: return ACT_DIEBACKWARD; - case 2: return ACT_DIEFORWARD; - case 3: return ACT_DIEVIOLENT; - case 4: return ACT_DIE_HEADSHOT; - case 5: return ACT_DIE_CHESTSHOT; - case 6: return ACT_DIE_GUTSHOT; - case 7: return ACT_DIE_BACKSHOT; - } - } - - vecSrc = WorldSpaceCenter(); - - fTriedDirection = false; - deathActivity = ACT_DIESIMPLE;// in case we can't find any special deaths to do. - - Vector forward; - AngleVectors( GetLocalAngles(), &forward ); - flDot = -DotProduct( forward, g_vecAttackDir ); - - switch ( m_LastHitGroup ) - { - // try to pick a region-specific death. - case HITGROUP_HEAD: - deathActivity = ACT_DIE_HEADSHOT; - break; - - case HITGROUP_STOMACH: - deathActivity = ACT_DIE_GUTSHOT; - break; - - case HITGROUP_GENERIC: - // try to pick a death based on attack direction - fTriedDirection = true; - - if ( flDot > 0.3 ) - { - deathActivity = ACT_DIEFORWARD; - } - else if ( flDot <= -0.3 ) - { - deathActivity = ACT_DIEBACKWARD; - } - break; - - default: - // try to pick a death based on attack direction - fTriedDirection = true; - - if ( flDot > 0.3 ) - { - deathActivity = ACT_DIEFORWARD; - } - else if ( flDot <= -0.3 ) - { - deathActivity = ACT_DIEBACKWARD; - } - break; - } - - - // can we perform the prescribed death? - if ( SelectWeightedSequence ( deathActivity ) == ACTIVITY_NOT_AVAILABLE ) - { - // no! did we fail to perform a directional death? - if ( fTriedDirection ) - { - // if yes, we're out of options. Go simple. - deathActivity = ACT_DIESIMPLE; - } - else - { - // cannot perform the ideal region-specific death, so try a direction. - if ( flDot > 0.3 ) - { - deathActivity = ACT_DIEFORWARD; - } - else if ( flDot <= -0.3 ) - { - deathActivity = ACT_DIEBACKWARD; - } - } - } - - if ( SelectWeightedSequence ( deathActivity ) == ACTIVITY_NOT_AVAILABLE ) - { - // if we're still invalid, simple is our only option. - deathActivity = ACT_DIESIMPLE; - - if ( SelectWeightedSequence ( deathActivity ) == ACTIVITY_NOT_AVAILABLE ) - { - Msg( "ERROR! %s missing ACT_DIESIMPLE\n", STRING(GetModelName()) ); - } - } - - if ( deathActivity == ACT_DIEFORWARD ) - { - // make sure there's room to fall forward - UTIL_TraceHull ( vecSrc, vecSrc + forward * 64, Vector(-16,-16,-18), - Vector(16,16,18), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction != 1.0 ) - { - deathActivity = ACT_DIESIMPLE; - } - } - - if ( deathActivity == ACT_DIEBACKWARD ) - { - // make sure there's room to fall backward - UTIL_TraceHull ( vecSrc, vecSrc - forward * 64, Vector(-16,-16,-18), - Vector(16,16,18), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction != 1.0 ) - { - deathActivity = ACT_DIESIMPLE; - } - } - - return deathActivity; -} - - -// UNDONE: Should these operate on a list of weapon/items -Activity CBaseCombatCharacter::Weapon_TranslateActivity( Activity baseAct, bool *pRequired ) -{ - Activity translated = baseAct; - - if ( m_hActiveWeapon ) - { - translated = m_hActiveWeapon->ActivityOverride( baseAct, pRequired ); - } - else if (pRequired) - { - *pRequired = false; - } - - return translated; -} - -//----------------------------------------------------------------------------- -// Purpose: NPCs should override this function to translate activities -// such as ACT_WALK, etc. -// Input : -// Output : -//----------------------------------------------------------------------------- -Activity CBaseCombatCharacter::NPC_TranslateActivity( Activity baseAct ) -{ - return baseAct; -} - - -void CBaseCombatCharacter::Weapon_SetActivity( Activity newActivity, float duration ) -{ - if ( m_hActiveWeapon ) - { - m_hActiveWeapon->SetActivity( newActivity, duration ); - } -} - -void CBaseCombatCharacter::Weapon_FrameUpdate( void ) -{ - if ( m_hActiveWeapon ) - { - m_hActiveWeapon->Operator_FrameUpdate( this ); - } -} - - -//------------------------------------------------------------------------------ -// Purpose : expects a length to trace, amount -// of damage to do, and damage type. Returns a pointer to -// the damaged entity in case the NPC wishes to do -// other stuff to the victim (punchangle, etc) -// -// Used for many contact-range melee attacks. Bites, claws, etc. -// Input : -// Output : -//------------------------------------------------------------------------------ -CBaseEntity *CBaseCombatCharacter::CheckTraceHullAttack( float flDist, const Vector &mins, const Vector &maxs, int iDamage, int iDmgType, float forceScale, bool bDamageAnyNPC ) -{ - // If only a length is given assume we want to trace in our facing direction - Vector forward; - AngleVectors( GetAbsAngles(), &forward ); - Vector vStart = GetAbsOrigin(); - - // The ideal place to start the trace is in the center of the attacker's bounding box. - // however, we need to make sure there's enough clearance. Some of the smaller monsters aren't - // as big as the hull we try to trace with. (SJB) - float flVerticalOffset = WorldAlignSize().z * 0.5; - - if( flVerticalOffset < maxs.z ) - { - // There isn't enough room to trace this hull, it's going to drag the ground. - // so make the vertical offset just enough to clear the ground. - flVerticalOffset = maxs.z + 1.0; - } - - vStart.z += flVerticalOffset; - Vector vEnd = vStart + (forward * flDist ); - return CheckTraceHullAttack( vStart, vEnd, mins, maxs, iDamage, iDmgType, forceScale, bDamageAnyNPC ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pHandleEntity - -// contentsMask - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CTraceFilterMelee::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) -{ - if ( !StandardFilterRules( pHandleEntity, contentsMask ) ) - return false; - - if ( !PassServerEntityFilter( pHandleEntity, m_pPassEnt ) ) - return false; - - // Don't test if the game code tells us we should ignore this collision... - CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); - - if ( pEntity ) - { - if ( !pEntity->ShouldCollide( m_collisionGroup, contentsMask ) ) - return false; - - if ( !g_pGameRules->ShouldCollide( m_collisionGroup, pEntity->GetCollisionGroup() ) ) - return false; - - if ( pEntity->m_takedamage == DAMAGE_NO ) - return false; - - // FIXME: Do not translate this to the driver because the driver only accepts damage from the vehicle - // Translate the vehicle into its driver for damage - /* - if ( pEntity->GetServerVehicle() != NULL ) - { - CBaseEntity *pDriver = pEntity->GetServerVehicle()->GetPassenger(); - - if ( pDriver != NULL ) - { - pEntity = pDriver; - } - } - */ - - Vector attackDir = pEntity->WorldSpaceCenter() - m_dmgInfo->GetAttacker()->WorldSpaceCenter(); - VectorNormalize( attackDir ); - - CTakeDamageInfo info = (*m_dmgInfo); - CalculateMeleeDamageForce( &info, attackDir, info.GetAttacker()->WorldSpaceCenter(), m_flForceScale ); - - CBaseCombatCharacter *pBCC = info.GetAttacker()->MyCombatCharacterPointer(); - CBaseCombatCharacter *pVictimBCC = pEntity->MyCombatCharacterPointer(); - - // Only do these comparisons between NPCs - if ( pBCC && pVictimBCC ) - { - // Can only damage other NPCs that we hate - if ( m_bDamageAnyNPC || pBCC->IRelationType( pEntity ) == D_HT ) - { - if ( info.GetDamage() ) - { - pEntity->TakeDamage( info ); - } - - // Put a combat sound in - CSoundEnt::InsertSound( SOUND_COMBAT, info.GetDamagePosition(), 200, 0.2f, info.GetAttacker() ); - - m_pHit = pEntity; - return true; - } - } - else - { - m_pHit = pEntity; - - // Make sure if the player is holding this, he drops it - Pickup_ForcePlayerToDropThisObject( pEntity ); - - // Otherwise just damage passive objects in our way - if ( info.GetDamage() ) - { - pEntity->TakeDamage( info ); - } - } - } - - return false; -} - -//------------------------------------------------------------------------------ -// Purpose : start and end trace position, amount -// of damage to do, and damage type. Returns a pointer to -// the damaged entity in case the NPC wishes to do -// other stuff to the victim (punchangle, etc) -// -// Used for many contact-range melee attacks. Bites, claws, etc. -// Input : -// Output : -//------------------------------------------------------------------------------ -CBaseEntity *CBaseCombatCharacter::CheckTraceHullAttack( const Vector &vStart, const Vector &vEnd, const Vector &mins, const Vector &maxs, int iDamage, int iDmgType, float flForceScale, bool bDamageAnyNPC ) -{ - // Handy debuging tool to visualize HullAttack trace - if ( ai_show_hull_attacks.GetBool() ) - { - float length = (vEnd - vStart ).Length(); - Vector direction = (vEnd - vStart ); - VectorNormalize( direction ); - Vector hullMaxs = maxs; - hullMaxs.x = length + hullMaxs.x; - NDebugOverlay::BoxDirection(vStart, mins, hullMaxs, direction, 100,255,255,20,1.0); - NDebugOverlay::BoxDirection(vStart, mins, maxs, direction, 255,0,0,20,1.0); - } - -#if 1 - - CTakeDamageInfo dmgInfo( this, this, iDamage, DMG_SLASH ); - - // COLLISION_GROUP_PROJECTILE does some handy filtering that's very appropriate for this type of attack, as well. (sjb) 7/25/2007 - CTraceFilterMelee traceFilter( this, COLLISION_GROUP_PROJECTILE, &dmgInfo, flForceScale, bDamageAnyNPC ); - - Ray_t ray; - ray.Init( vStart, vEnd, mins, maxs ); - - trace_t tr; - enginetrace->TraceRay( ray, MASK_SHOT_HULL, &traceFilter, &tr ); - - CBaseEntity *pEntity = traceFilter.m_pHit; - - if ( pEntity == NULL ) - { - // See if perhaps I'm trying to claw/bash someone who is standing on my head. - Vector vecTopCenter; - Vector vecEnd; - Vector vecMins, vecMaxs; - - // Do a tracehull from the top center of my bounding box. - vecTopCenter = GetAbsOrigin(); - CollisionProp()->WorldSpaceAABB( &vecMins, &vecMaxs ); - vecTopCenter.z = vecMaxs.z + 1.0f; - vecEnd = vecTopCenter; - vecEnd.z += 2.0f; - - ray.Init( vecTopCenter, vEnd, mins, maxs ); - enginetrace->TraceRay( ray, MASK_SHOT_HULL, &traceFilter, &tr ); - - pEntity = traceFilter.m_pHit; - } - - if( pEntity && !pEntity->CanBeHitByMeleeAttack(this) ) - { - // If we touched something, but it shouldn't be hit, return nothing. - pEntity = NULL; - } - - return pEntity; - -#else - - trace_t tr; - UTIL_TraceHull( vStart, vEnd, mins, maxs, MASK_SHOT_HULL, this, COLLISION_GROUP_NONE, &tr ); - - CBaseEntity *pEntity = tr.m_pEnt; - - if ( !pEntity ) - { - // See if perhaps I'm trying to claw/bash someone who is standing on my head. - Vector vecTopCenter; - Vector vecEnd; - Vector vecMins, vecMaxs; - - // Do a tracehull from the top center of my bounding box. - vecTopCenter = GetAbsOrigin(); - CollisionProp()->WorldSpaceAABB( &vecMins, &vecMaxs ); - vecTopCenter.z = vecMaxs.z + 1.0f; - vecEnd = vecTopCenter; - vecEnd.z += 2.0f; - UTIL_TraceHull( vecTopCenter, vecEnd, mins, maxs, MASK_SHOT_HULL, this, COLLISION_GROUP_NONE, &tr ); - pEntity = tr.m_pEnt; - } - - if ( !pEntity || !pEntity->m_takedamage || !pEntity->IsAlive() ) - return NULL; - - // Translate the vehicle into its driver for damage - if ( pEntity->GetServerVehicle() != NULL ) - { - CBaseEntity *pDriver = pEntity->GetServerVehicle()->GetPassenger(); - - if ( pDriver != NULL ) - { - pEntity = pDriver; - //FIXME: Hook for damage scale in car here - } - } - - // Must hate the hit entity - if ( IRelationType( pEntity ) == D_HT ) - { - if ( iDamage > 0 ) - { - CTakeDamageInfo info( this, this, iDamage, iDmgType ); - CalculateMeleeDamageForce( &info, (vEnd - vStart), vStart, forceScale ); - pEntity->TakeDamage( info ); - } - } - return pEntity; - -#endif - -} - - -bool CBaseCombatCharacter::Event_Gibbed( const CTakeDamageInfo &info ) -{ - bool fade = false; - - if ( HasHumanGibs() ) - { - ConVarRef violence_hgibs( "violence_hgibs" ); - if ( violence_hgibs.IsValid() && violence_hgibs.GetInt() == 0 ) - { - fade = true; - } - } - else if ( HasAlienGibs() ) - { - ConVarRef violence_agibs( "violence_agibs" ); - if ( violence_agibs.IsValid() && violence_agibs.GetInt() == 0 ) - { - fade = true; - } - } - - m_takedamage = DAMAGE_NO; - AddSolidFlags( FSOLID_NOT_SOLID ); - m_lifeState = LIFE_DEAD; - - if ( fade ) - { - CorpseFade(); - return false; - } - else - { - AddEffects( EF_NODRAW ); // make the model invisible. - return CorpseGib( info ); - } -} - - -Vector CBaseCombatCharacter::CalcDamageForceVector( const CTakeDamageInfo &info ) -{ - // Already have a damage force in the data, use that. - bool bNoPhysicsForceDamage = g_pGameRules->Damage_NoPhysicsForce( info.GetDamageType() ); - if ( info.GetDamageForce() != vec3_origin || bNoPhysicsForceDamage ) - { - if( info.GetDamageType() & DMG_BLAST ) - { - // Fudge blast forces a little bit, so that each - // victim gets a slightly different trajectory. - // This simulates features that usually vary from - // person-to-person variables such as bodyweight, - // which are all indentical for characters using the same model. - float scale = random->RandomFloat( 0.85, 1.15 ); - Vector force = info.GetDamageForce(); - force.x *= scale; - force.y *= scale; - // Try to always exaggerate the upward force because we've got pretty harsh gravity - force.z *= (force.z > 0) ? 1.15 : scale; - return force; - } - - return info.GetDamageForce(); - } - - CBaseEntity *pForce = info.GetInflictor(); - if ( !pForce ) - { - pForce = info.GetAttacker(); - } - - if ( pForce ) - { - // Calculate an impulse large enough to push a 75kg man 4 in/sec per point of damage - float forceScale = info.GetDamage() * 75 * 4; - - Vector forceVector; - // If the damage is a blast, point the force vector higher than usual, this gives - // the ragdolls a bodacious "really got blowed up" look. - if( info.GetDamageType() & DMG_BLAST ) - { - // exaggerate the force from explosions a little (37.5%) - forceVector = (GetLocalOrigin() + Vector(0, 0, WorldAlignSize().z) ) - pForce->GetLocalOrigin(); - VectorNormalize(forceVector); - forceVector *= 1.375f; - } - else - { - // taking damage from self? Take a little random force, but still try to collapse on the spot. - if ( this == pForce ) - { - forceVector.x = random->RandomFloat( -1.0f, 1.0f ); - forceVector.y = random->RandomFloat( -1.0f, 1.0f ); - forceVector.z = 0.0; - forceScale = random->RandomFloat( 1000.0f, 2000.0f ); - } - else - { - // UNDONE: Collision forces are baked in to CTakeDamageInfo now - // UNDONE: Is this MOVETYPE_VPHYSICS code still necessary? - if ( pForce->GetMoveType() == MOVETYPE_VPHYSICS ) - { - // killed by a physics object - IPhysicsObject *pPhysics = VPhysicsGetObject(); - if ( !pPhysics ) - { - pPhysics = pForce->VPhysicsGetObject(); - } - pPhysics->GetVelocity( &forceVector, NULL ); - forceScale = pPhysics->GetMass(); - } - else - { - forceVector = GetLocalOrigin() - pForce->GetLocalOrigin(); - VectorNormalize(forceVector); - } - } - } - return forceVector * forceScale; - } - return vec3_origin; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -void CBaseCombatCharacter::FixupBurningServerRagdoll( CBaseEntity *pRagdoll ) -{ - if ( !IsOnFire() ) - return; - - // Move the fire effects entity to the ragdoll - CEntityFlame *pFireChild = dynamic_cast( GetEffectEntity() ); - if ( pFireChild ) - { - SetEffectEntity( NULL ); - pRagdoll->AddFlag( FL_ONFIRE ); - pFireChild->SetAbsOrigin( pRagdoll->GetAbsOrigin() ); - pFireChild->AttachToEntity( pRagdoll ); - pFireChild->AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); - pRagdoll->SetEffectEntity( pFireChild ); - - color32 color = GetRenderColor(); - pRagdoll->SetRenderColor( color.r, color.g, color.b ); - } -} - -bool CBaseCombatCharacter::BecomeRagdollBoogie( CBaseEntity *pKiller, const Vector &forceVector, float duration, int flags ) -{ - Assert( CanBecomeRagdoll() ); - - CTakeDamageInfo info( pKiller, pKiller, 1.0f, DMG_GENERIC ); - - info.SetDamageForce( forceVector ); - - CBaseEntity *pRagdoll = CreateServerRagdoll( this, 0, info, COLLISION_GROUP_INTERACTIVE_DEBRIS, true ); - - pRagdoll->SetCollisionBounds( CollisionProp()->OBBMins(), CollisionProp()->OBBMaxs() ); - - CRagdollBoogie::Create( pRagdoll, 200, gpGlobals->curtime, duration, flags ); - - CTakeDamageInfo ragdollInfo( pKiller, pKiller, 10000.0, DMG_GENERIC | DMG_REMOVENORAGDOLL ); - ragdollInfo.SetDamagePosition(WorldSpaceCenter()); - ragdollInfo.SetDamageForce( Vector( 0, 0, 1) ); - TakeDamage( ragdollInfo ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseCombatCharacter::BecomeRagdoll( const CTakeDamageInfo &info, const Vector &forceVector ) -{ - if ( (info.GetDamageType() & DMG_VEHICLE) && !g_pGameRules->IsMultiplayer() ) - { - CTakeDamageInfo info2 = info; - info2.SetDamageForce( forceVector ); - Vector pos = info2.GetDamagePosition(); - float flAbsMinsZ = GetAbsOrigin().z + WorldAlignMins().z; - if ( (pos.z - flAbsMinsZ) < 24 ) - { - // HACKHACK: Make sure the vehicle impact is at least 2ft off the ground - pos.z = flAbsMinsZ + 24; - info2.SetDamagePosition( pos ); - } - -// UNDONE: Put in a real sound cue here, don't do this bogus hack anymore -#if 0 - Vector soundOrigin = info.GetDamagePosition(); - CPASAttenuationFilter filter( soundOrigin ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_STATIC; - ep.m_pSoundName = "NPC_MetroPolice.HitByVehicle"; - ep.m_flVolume = 1.0f; - ep.m_SoundLevel = SNDLVL_NORM; - ep.m_pOrigin = &soundOrigin; - - EmitSound( filter, SOUND_FROM_WORLD, ep ); -#endif - // in single player create ragdolls on the server when the player hits someone - // with their vehicle - for more dramatic death/collisions - CBaseEntity *pRagdoll = CreateServerRagdoll( this, m_nForceBone, info2, COLLISION_GROUP_INTERACTIVE_DEBRIS, true ); - FixupBurningServerRagdoll( pRagdoll ); - RemoveDeferred(); - return true; - } - - //Fix up the force applied to server side ragdolls. This fixes magnets not affecting them. - CTakeDamageInfo newinfo = info; - newinfo.SetDamageForce( forceVector ); - -#ifdef HL2_EPISODIC - // Burning corpses are server-side in episodic, if we're in darkness mode - if ( IsOnFire() && HL2GameRules()->IsAlyxInDarknessMode() ) - { - CBaseEntity *pRagdoll = CreateServerRagdoll( this, m_nForceBone, newinfo, COLLISION_GROUP_DEBRIS ); - FixupBurningServerRagdoll( pRagdoll ); - RemoveDeferred(); - return true; - } -#endif - -#ifdef HL2_DLL - // Mega physgun requires everything to be a server-side ragdoll - if ( m_bForceServerRagdoll == true || ( HL2GameRules()->MegaPhyscannonActive() == true ) && !IsPlayer() && Classify() != CLASS_PLAYER_ALLY_VITAL && Classify() != CLASS_PLAYER_ALLY ) - { - if ( CanBecomeServerRagdoll() == false ) - return false; - - //FIXME: This is fairly leafy to be here, but time is short! - CBaseEntity *pRagdoll = CreateServerRagdoll( this, m_nForceBone, newinfo, COLLISION_GROUP_INTERACTIVE_DEBRIS, true ); - FixupBurningServerRagdoll( pRagdoll ); - PhysSetEntityGameFlags( pRagdoll, FVPHYSICS_NO_SELF_COLLISIONS ); - RemoveDeferred(); - - return true; - } - - if( hl2_episodic.GetBool() && Classify() == CLASS_PLAYER_ALLY_VITAL ) - { - CreateServerRagdoll( this, m_nForceBone, newinfo, COLLISION_GROUP_INTERACTIVE_DEBRIS, true ); - RemoveDeferred(); - return true; - } -#endif //HL2_DLL - - return BecomeRagdollOnClient( forceVector ); -} - - -/* -============ -Killed -============ -*/ -void CBaseCombatCharacter::Event_Killed( const CTakeDamageInfo &info ) -{ - // Advance life state to dying - m_lifeState = LIFE_DYING; - - // Calculate death force - Vector forceVector = CalcDamageForceVector( info ); - - // See if there's a ragdoll magnet that should influence our force. - CRagdollMagnet *pMagnet = CRagdollMagnet::FindBestMagnet( this ); - if( pMagnet ) - { - forceVector += pMagnet->GetForceVector( this ); - } - - CBaseCombatWeapon *pDroppedWeapon = m_hActiveWeapon.Get(); - - // Drop any weapon that I own - if ( VPhysicsGetObject() ) - { - Vector weaponForce = forceVector * VPhysicsGetObject()->GetInvMass(); - Weapon_Drop( m_hActiveWeapon, NULL, &weaponForce ); - } - else - { - Weapon_Drop( m_hActiveWeapon ); - } - - // if flagged to drop a health kit - if (HasSpawnFlags(SF_NPC_DROP_HEALTHKIT)) - { - CBaseEntity::Create( "item_healthvial", GetAbsOrigin(), GetAbsAngles() ); - } - // clear the deceased's sound channels.(may have been firing or reloading when killed) - EmitSound( "BaseCombatCharacter.StopWeaponSounds" ); - - // Tell my killer that he got me! - if( info.GetAttacker() ) - { - info.GetAttacker()->Event_KilledOther(this, info); - g_EventQueue.AddEvent( info.GetAttacker(), "KilledNPC", 0.3, this, this ); - } - SendOnKilledGameEvent( info ); - - // Ragdoll unless we've gibbed - if ( ShouldGib( info ) == false ) - { - bool bRagdollCreated = false; - if ( (info.GetDamageType() & DMG_DISSOLVE) && CanBecomeRagdoll() ) - { - int nDissolveType = ENTITY_DISSOLVE_NORMAL; - if ( info.GetDamageType() & DMG_SHOCK ) - { - nDissolveType = ENTITY_DISSOLVE_ELECTRICAL; - } - - bRagdollCreated = Dissolve( NULL, gpGlobals->curtime, false, nDissolveType ); - - // Also dissolve any weapons we dropped - if ( pDroppedWeapon ) - { - pDroppedWeapon->Dissolve( NULL, gpGlobals->curtime, false, nDissolveType ); - } - } -#ifdef HL2_DLL - else if ( PlayerHasMegaPhysCannon() ) - { - if ( pDroppedWeapon ) - { - pDroppedWeapon->Dissolve( NULL, gpGlobals->curtime, false, ENTITY_DISSOLVE_NORMAL ); - } - } -#endif - - if ( !bRagdollCreated && ( info.GetDamageType() & DMG_REMOVENORAGDOLL ) == 0 ) - { - BecomeRagdoll( info, forceVector ); - } - } -} - -void CBaseCombatCharacter::Event_Dying( void ) -{ -} - - -// =========================================================================== -// > Weapons -// =========================================================================== -bool CBaseCombatCharacter::Weapon_Detach( CBaseCombatWeapon *pWeapon ) -{ - for ( int i = 0; i < MAX_WEAPONS; i++ ) - { - if ( pWeapon == m_hMyWeapons[i] ) - { - m_hMyWeapons.Set( i, NULL ); - pWeapon->SetOwner( NULL ); - - if ( pWeapon == m_hActiveWeapon ) - ClearActiveWeapon(); - return true; - } - } - - return false; -} - - -//----------------------------------------------------------------------------- -// For weapon strip -//----------------------------------------------------------------------------- -void CBaseCombatCharacter::ThrowDirForWeaponStrip( CBaseCombatWeapon *pWeapon, const Vector &vecForward, Vector *pVecThrowDir ) -{ - // HACK! Always throw the physcannon directly in front of the player - // This is necessary for the physgun upgrade scene. - if ( FClassnameIs( pWeapon, "weapon_physcannon" ) ) - { - if( hl2_episodic.GetBool() ) - { - // It has been discovered that it's possible to throw the physcannon out of the world this way. - // So try to find a direction to throw the physcannon that's legal. - Vector vecOrigin = EyePosition(); - Vector vecRight; - - CrossProduct( vecForward, Vector( 0, 0, 1), vecRight ); - - Vector vecTest[ 4 ]; - vecTest[0] = vecForward; - vecTest[1] = -vecForward; - vecTest[2] = vecRight; - vecTest[3] = -vecRight; - - trace_t tr; - int i; - for( i = 0 ; i < 4 ; i++ ) - { - UTIL_TraceLine( vecOrigin, vecOrigin + vecTest[ i ] * 48.0f, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - - if ( !tr.startsolid && tr.fraction == 1.0f ) - { - *pVecThrowDir = vecTest[ i ]; - return; - } - } - } - - // Well, fall through to what we did before we tried to make this a bit more robust. - *pVecThrowDir = vecForward; - } - else - { - // Nowhere in particular; just drop it. - VMatrix zRot; - MatrixBuildRotateZ( zRot, random->RandomFloat( -60.0f, 60.0f ) ); - - Vector vecThrow; - Vector3DMultiply( zRot, vecForward, *pVecThrowDir ); - - pVecThrowDir->z = random->RandomFloat( -0.5f, 0.5f ); - VectorNormalize( *pVecThrowDir ); - } -} - - -//----------------------------------------------------------------------------- -// For weapon strip -//----------------------------------------------------------------------------- -void CBaseCombatCharacter::DropWeaponForWeaponStrip( CBaseCombatWeapon *pWeapon, - const Vector &vecForward, const QAngle &vecAngles, float flDiameter ) -{ - Vector vecOrigin; - CollisionProp()->RandomPointInBounds( Vector( 0.5f, 0.5f, 0.5f ), Vector( 0.5f, 0.5f, 1.0f ), &vecOrigin ); - - // Nowhere in particular; just drop it. - Vector vecThrow; - ThrowDirForWeaponStrip( pWeapon, vecForward, &vecThrow ); - - Vector vecOffsetOrigin; - VectorMA( vecOrigin, flDiameter, vecThrow, vecOffsetOrigin ); - - trace_t tr; - UTIL_TraceLine( vecOrigin, vecOffsetOrigin, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.startsolid || tr.allsolid || ( tr.fraction < 1.0f && tr.m_pEnt != pWeapon ) ) - { - //FIXME: Throw towards a known safe spot? - vecThrow.Negate(); - VectorMA( vecOrigin, flDiameter, vecThrow, vecOffsetOrigin ); - } - - vecThrow *= random->RandomFloat( 400.0f, 600.0f ); - - pWeapon->SetAbsOrigin( vecOrigin ); - pWeapon->SetAbsAngles( vecAngles ); - pWeapon->Drop( vecThrow ); - pWeapon->SetRemoveable( false ); - Weapon_Detach( pWeapon ); -} - - - -//----------------------------------------------------------------------------- -// For weapon strip -//----------------------------------------------------------------------------- -void CBaseCombatCharacter::Weapon_DropAll( bool bDisallowWeaponPickup ) -{ - if ( GetFlags() & FL_NPC ) - { - for (int i=0; iOBBSize().x * CollisionProp()->OBBSize().x + - CollisionProp()->OBBSize().y * CollisionProp()->OBBSize().y ); - - CBaseCombatWeapon *pActiveWeapon = GetActiveWeapon(); - for (int i=0; iRemoveSolidFlags( FSOLID_TRIGGER ); - - IPhysicsObject *pObj = pWeapon->VPhysicsGetObject(); - - if ( pObj != NULL ) - { - pObj->SetGameFlags( FVPHYSICS_NO_PLAYER_PICKUP ); - } - } - } - - // Drop the active weapon normally... - if ( pActiveWeapon ) - { - // Nowhere in particular; just drop it. - Vector vecThrow; - ThrowDirForWeaponStrip( pActiveWeapon, vecForward, &vecThrow ); - - // Throw a little more vigorously; it starts closer to the player - vecThrow *= random->RandomFloat( 800.0f, 1000.0f ); - - Weapon_Drop( pActiveWeapon, NULL, &vecThrow ); - pActiveWeapon->SetRemoveable( false ); - - // HACK: This hack is required to allow weapons to be disintegrated - // in the citadel weapon-strip scene - // Make them not pick-uppable again. This also has the effect of allowing weapons - // to collide with triggers. - if ( bDisallowWeaponPickup ) - { - pActiveWeapon->RemoveSolidFlags( FSOLID_TRIGGER ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Drop the active weapon, optionally throwing it at the given target position. -// Input : pWeapon - Weapon to drop/throw. -// pvecTarget - Position to throw it at, NULL for none. -//----------------------------------------------------------------------------- -void CBaseCombatCharacter::Weapon_Drop( CBaseCombatWeapon *pWeapon, const Vector *pvecTarget /* = NULL */, const Vector *pVelocity /* = NULL */ ) -{ - if ( !pWeapon ) - return; - - // If I'm an NPC, fill the weapon with ammo before I drop it. - if ( GetFlags() & FL_NPC ) - { - if ( pWeapon->UsesClipsForAmmo1() ) - { - pWeapon->m_iClip1 = pWeapon->GetDefaultClip1(); - - if( FClassnameIs( pWeapon, "weapon_smg1" ) ) - { - // Drop enough ammo to kill 2 of me. - // Figure out how much damage one piece of this type of ammo does to this type of enemy. - float flAmmoDamage = g_pGameRules->GetAmmoDamage( UTIL_PlayerByIndex(1), this, pWeapon->GetPrimaryAmmoType() ); - pWeapon->m_iClip1 = (GetMaxHealth() / flAmmoDamage) * 2; - } - } - if ( pWeapon->UsesClipsForAmmo2() ) - { - pWeapon->m_iClip2 = pWeapon->GetDefaultClip2(); - } - - if ( IsXbox() ) - { - pWeapon->AddEffects( EF_ITEM_BLINK ); - } - } - - if ( IsPlayer() ) - { - Vector vThrowPos = Weapon_ShootPosition() - Vector(0,0,12); - - if( UTIL_PointContents(vThrowPos) & CONTENTS_SOLID ) - { - Msg("Weapon spawning in solid!\n"); - } - - pWeapon->SetAbsOrigin( vThrowPos ); - - QAngle gunAngles; - VectorAngles( BodyDirection2D(), gunAngles ); - pWeapon->SetAbsAngles( gunAngles ); - } - else - { - int iBIndex = -1; - int iWeaponBoneIndex = -1; - - CStudioHdr *hdr = pWeapon->GetModelPtr(); - // If I have a hand, set the weapon position to my hand bone position. - if ( hdr && hdr->numbones() > 0 ) - { - // Assume bone zero is the root - for ( iWeaponBoneIndex = 0; iWeaponBoneIndex < hdr->numbones(); ++iWeaponBoneIndex ) - { - iBIndex = LookupBone( hdr->pBone( iWeaponBoneIndex )->pszName() ); - // Found one! - if ( iBIndex != -1 ) - { - break; - } - } - - if ( iBIndex == -1 ) - { - iBIndex = LookupBone( "ValveBiped.Weapon_bone" ); - } - } - else - { - iBIndex = LookupBone( "ValveBiped.Weapon_bone" ); - } - - if ( iBIndex != -1) - { - Vector origin; - QAngle angles; - matrix3x4_t transform; - - // Get the transform for the weapon bonetoworldspace in the NPC - GetBoneTransform( iBIndex, transform ); - - // find offset of root bone from origin in local space - // Make sure we're detached from hierarchy before doing this!!! - pWeapon->StopFollowingEntity(); - pWeapon->SetAbsOrigin( Vector( 0, 0, 0 ) ); - pWeapon->SetAbsAngles( QAngle( 0, 0, 0 ) ); - pWeapon->InvalidateBoneCache(); - matrix3x4_t rootLocal; - pWeapon->GetBoneTransform( iWeaponBoneIndex, rootLocal ); - - // invert it - matrix3x4_t rootInvLocal; - MatrixInvert( rootLocal, rootInvLocal ); - - matrix3x4_t weaponMatrix; - ConcatTransforms( transform, rootInvLocal, weaponMatrix ); - MatrixAngles( weaponMatrix, angles, origin ); - - pWeapon->Teleport( &origin, &angles, NULL ); - } - // Otherwise just set in front of me. - else - { - Vector vFacingDir = BodyDirection2D(); - vFacingDir = vFacingDir * 10.0; - pWeapon->SetAbsOrigin( Weapon_ShootPosition() + vFacingDir ); - } - } - - Vector vecThrow; - if (pvecTarget) - { - // I've been told to throw it somewhere specific. - vecThrow = VecCheckToss( this, pWeapon->GetAbsOrigin(), *pvecTarget, 0.2, 1.0, false ); - } - else - { - if ( pVelocity ) - { - vecThrow = *pVelocity; - float flLen = vecThrow.Length(); - if (flLen > 400) - { - VectorNormalize(vecThrow); - vecThrow *= 400; - } - } - else - { - // Nowhere in particular; just drop it. - float throwForce = ( IsPlayer() ) ? 400.0f : random->RandomInt( 64, 128 ); - vecThrow = BodyDirection3D() * throwForce; - } - } - - pWeapon->Drop( vecThrow ); - Weapon_Detach( pWeapon ); - - if ( HasSpawnFlags( SF_NPC_NO_WEAPON_DROP ) ) - { - // Don't drop weapons when the super physgun is happening. - UTIL_Remove( pWeapon ); - } - -} - - -//----------------------------------------------------------------------------- -// Lighting origin -//----------------------------------------------------------------------------- -void CBaseCombatCharacter::SetLightingOriginRelative( CBaseEntity *pLightingOrigin ) -{ - BaseClass::SetLightingOriginRelative( pLightingOrigin ); - if ( GetActiveWeapon() ) - { - GetActiveWeapon()->SetLightingOriginRelative( pLightingOrigin ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Add new weapon to the character -// Input : New weapon -//----------------------------------------------------------------------------- -void CBaseCombatCharacter::Weapon_Equip( CBaseCombatWeapon *pWeapon ) -{ - // Add the weapon to my weapon inventory - for (int i=0;iChangeTeam( GetTeamNumber() ); - - // ---------------------- - // Give Primary Ammo - // ---------------------- - // If gun doesn't use clips, just give ammo - if (pWeapon->GetMaxClip1() == -1) - { -#ifdef HL2_DLL - if( FStrEq(STRING(gpGlobals->mapname), "d3_c17_09") && FClassnameIs(pWeapon, "weapon_rpg") && pWeapon->NameMatches("player_spawn_items") ) - { - // !!!HACK - Don't give any ammo with the spawn equipment RPG in d3_c17_09. This is a chapter - // start and the map is way to easy if you start with 3 RPG rounds. It's fine if a player conserves - // them and uses them here, but it's not OK to start with enough ammo to bypass the snipers completely. - GiveAmmo( 0, pWeapon->m_iPrimaryAmmoType); - } - else -#endif // HL2_DLL - GiveAmmo(pWeapon->GetDefaultClip1(), pWeapon->m_iPrimaryAmmoType); - } - // If default ammo given is greater than clip - // size, fill clips and give extra ammo - else if (pWeapon->GetDefaultClip1() > pWeapon->GetMaxClip1() ) - { - pWeapon->m_iClip1 = pWeapon->GetMaxClip1(); - GiveAmmo( (pWeapon->GetDefaultClip1() - pWeapon->GetMaxClip1()), pWeapon->m_iPrimaryAmmoType); - } - - // ---------------------- - // Give Secondary Ammo - // ---------------------- - // If gun doesn't use clips, just give ammo - if (pWeapon->GetMaxClip2() == -1) - { - GiveAmmo(pWeapon->GetDefaultClip2(), pWeapon->m_iSecondaryAmmoType); - } - // If default ammo given is greater than clip - // size, fill clips and give extra ammo - else if ( pWeapon->GetDefaultClip2() > pWeapon->GetMaxClip2() ) - { - pWeapon->m_iClip2 = pWeapon->GetMaxClip2(); - GiveAmmo( (pWeapon->GetDefaultClip2() - pWeapon->GetMaxClip2()), pWeapon->m_iSecondaryAmmoType); - } - - pWeapon->Equip( this ); - - // Players don't automatically holster their current weapon - if ( IsPlayer() == false ) - { - if ( m_hActiveWeapon ) - { - m_hActiveWeapon->Holster(); - // FIXME: isn't this handeled by the weapon? - m_hActiveWeapon->AddEffects( EF_NODRAW ); - } - SetActiveWeapon( pWeapon ); - m_hActiveWeapon->RemoveEffects( EF_NODRAW ); - - } - - // Gotta do this *after* Equip because it may whack maxRange - if ( IsPlayer() == false ) - { - // If SF_NPC_LONG_RANGE spawn flags is set let weapon work from any distance - if ( HasSpawnFlags(SF_NPC_LONG_RANGE) ) - { - m_hActiveWeapon->m_fMaxRange1 = 999999999; - m_hActiveWeapon->m_fMaxRange2 = 999999999; - } - } - - WeaponProficiency_t proficiency; - proficiency = CalcWeaponProficiency( pWeapon ); - - if( weapon_showproficiency.GetBool() != 0 ) - { - Msg("%s equipped with %s, proficiency is %s\n", GetClassname(), pWeapon->GetClassname(), GetWeaponProficiencyName( proficiency ) ); - } - - SetCurrentWeaponProficiency( proficiency ); - - // Pass the lighting origin over to the weapon if we have one - pWeapon->SetLightingOriginRelative( GetLightingOriginRelative() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Leaves weapon, giving only ammo to the character -// Input : Weapon -//----------------------------------------------------------------------------- -bool CBaseCombatCharacter::Weapon_EquipAmmoOnly( CBaseCombatWeapon *pWeapon ) -{ - // Check for duplicates - for (int i=0;iGetClassname()) ) - { - // Just give the ammo from the clip - int primaryGiven = (pWeapon->UsesClipsForAmmo1()) ? pWeapon->m_iClip1 : pWeapon->GetPrimaryAmmoCount(); - int secondaryGiven = (pWeapon->UsesClipsForAmmo2()) ? pWeapon->m_iClip2 : pWeapon->GetSecondaryAmmoCount(); - - int takenPrimary = GiveAmmo( primaryGiven, pWeapon->m_iPrimaryAmmoType); - int takenSecondary = GiveAmmo( secondaryGiven, pWeapon->m_iSecondaryAmmoType); - - if( pWeapon->UsesClipsForAmmo1() ) - { - pWeapon->m_iClip1 -= takenPrimary; - } - else - { - pWeapon->SetPrimaryAmmoCount( pWeapon->GetPrimaryAmmoCount() - takenPrimary ); - } - - if( pWeapon->UsesClipsForAmmo2() ) - { - pWeapon->m_iClip2 -= takenSecondary; - } - else - { - pWeapon->SetSecondaryAmmoCount( pWeapon->GetSecondaryAmmoCount() - takenSecondary ); - } - - //Only succeed if we've taken ammo from the weapon - if ( takenPrimary > 0 || takenSecondary > 0 ) - return true; - - return false; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns whether the weapon passed in would occupy a slot already occupied by the carrier -// Input : *pWeapon - weapon to test for -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseCombatCharacter::Weapon_SlotOccupied( CBaseCombatWeapon *pWeapon ) -{ - if ( pWeapon == NULL ) - return false; - - //Check to see if there's a resident weapon already in this slot - if ( Weapon_GetSlot( pWeapon->GetSlot() ) == NULL ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the weapon (if any) in the requested slot -// Input : slot - which slot to poll -//----------------------------------------------------------------------------- -CBaseCombatWeapon *CBaseCombatCharacter::Weapon_GetSlot( int slot ) const -{ - int targetSlot = slot; - - // Check for that slot being occupied already - for ( int i=0; i < MAX_WEAPONS; i++ ) - { - if ( m_hMyWeapons[i].Get() != NULL ) - { - // If the slots match, it's already occupied - if ( m_hMyWeapons[i]->GetSlot() == targetSlot ) - return m_hMyWeapons[i]; - } - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Get a pointer to a weapon this character has that uses the specified ammo -//----------------------------------------------------------------------------- -CBaseCombatWeapon *CBaseCombatCharacter::Weapon_GetWpnForAmmo( int iAmmoIndex ) -{ - for ( int i = 0; i < MAX_WEAPONS; i++ ) - { - CBaseCombatWeapon *weapon = GetWeapon( i ); - if ( !weapon ) - continue; - - if ( weapon->GetPrimaryAmmoType() == iAmmoIndex ) - return weapon; - if ( weapon->GetSecondaryAmmoType() == iAmmoIndex ) - return weapon; - } - - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Can this character operate this weapon? -// Input : A weapon -// Output : true or false -//----------------------------------------------------------------------------- -bool CBaseCombatCharacter::Weapon_CanUse( CBaseCombatWeapon *pWeapon ) -{ - acttable_t *pTable = pWeapon->ActivityList(); - int actCount = pWeapon->ActivityListCount(); - - if( actCount < 1 ) - { - // If the weapon has no activity table, it definitely cannot be used. - return false; - } - - for ( int i = 0; i < actCount; i++, pTable++ ) - { - if ( pTable->required ) - { - // The NPC might translate the weapon activity into another activity - Activity translatedActivity = NPC_TranslateActivity( (Activity)(pTable->weaponAct) ); - - if ( SelectWeightedSequence(translatedActivity) == ACTIVITY_NOT_AVAILABLE ) - { - return false; - } - } - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -CBaseCombatWeapon *CBaseCombatCharacter::Weapon_Create( const char *pWeaponName ) -{ - CBaseCombatWeapon *pWeapon = static_cast( Create( pWeaponName, GetLocalOrigin(), GetLocalAngles(), this ) ); - - return pWeapon; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CBaseCombatCharacter::Weapon_HandleAnimEvent( animevent_t *pEvent ) -{ - // UNDONE: Some check to make sure that pEvent->pSource is a weapon I'm holding? - if ( m_hActiveWeapon ) - { - // UNDONE: Pass to pEvent->pSource instead? - m_hActiveWeapon->Operator_HandleAnimEvent( pEvent, this ); - } -} - -void CBaseCombatCharacter::RemoveAllWeapons() -{ - ClearActiveWeapon(); - for (int i = 0; i < MAX_WEAPONS; i++) - { - if ( m_hMyWeapons[i] ) - { - m_hMyWeapons[i]->Delete( ); - m_hMyWeapons.Set( i, NULL ); - } - } -} - - -// take health -int CBaseCombatCharacter::TakeHealth (float flHealth, int bitsDamageType) -{ - if (!m_takedamage) - return 0; - - return BaseClass::TakeHealth(flHealth, bitsDamageType); -} - - -/* -============ -OnTakeDamage - -The damage is coming from inflictor, but get mad at attacker -This should be the only function that ever reduces health. -bitsDamageType indicates the type of damage sustained, ie: DMG_SHOCK - -Time-based damage: only occurs while the NPC is within the trigger_hurt. -When a NPC is poisoned via an arrow etc it takes all the poison damage at once. - - - -GLOBALS ASSUMED SET: g_iSkillLevel -============ -*/ -int CBaseCombatCharacter::OnTakeDamage( const CTakeDamageInfo &info ) -{ - int retVal = 0; - - if (!m_takedamage) - return 0; - - m_iDamageCount++; - - if ( info.GetDamageType() & DMG_SHOCK ) - { - g_pEffects->Sparks( info.GetDamagePosition(), 2, 2 ); - UTIL_Smoke( info.GetDamagePosition(), random->RandomInt( 10, 15 ), 10 ); - } - - switch( m_lifeState ) - { - case LIFE_ALIVE: - retVal = OnTakeDamage_Alive( info ); - if ( m_iHealth <= 0 ) - { - IPhysicsObject *pPhysics = VPhysicsGetObject(); - if ( pPhysics ) - { - pPhysics->EnableCollisions( false ); - } - - bool bGibbed = false; - - Event_Killed( info ); - - // Only classes that specifically request it are gibbed - if ( ShouldGib( info ) ) - { - bGibbed = Event_Gibbed( info ); - } - - if ( bGibbed == false ) - { - Event_Dying(); - } - } - return retVal; - break; - - case LIFE_DYING: - return OnTakeDamage_Dying( info ); - - default: - case LIFE_DEAD: - retVal = OnTakeDamage_Dead( info ); - if ( m_iHealth <= 0 && g_pGameRules->Damage_ShouldGibCorpse( info.GetDamageType() ) && ShouldGib( info ) ) - { - Event_Gibbed( info ); - retVal = 0; - } - return retVal; - } -} - - -int CBaseCombatCharacter::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - // grab the vector of the incoming attack. ( pretend that the inflictor is a little lower than it really is, so the body will tend to fly upward a bit). - Vector vecDir = vec3_origin; - if (info.GetInflictor()) - { - vecDir = info.GetInflictor()->WorldSpaceCenter() - Vector ( 0, 0, 10 ) - WorldSpaceCenter(); - VectorNormalize(vecDir); - } - g_vecAttackDir = vecDir; - - //!!!LATER - make armor consideration here! - // do the damage - if ( m_takedamage != DAMAGE_EVENTS_ONLY ) - { - // Separate the fractional amount of damage from the whole - float flFractionalDamage = info.GetDamage() - floor( info.GetDamage() ); - float flIntegerDamage = info.GetDamage() - flFractionalDamage; - - // Add fractional damage to the accumulator - m_flDamageAccumulator += flFractionalDamage; - - // If the accumulator is holding a full point of damage, move that point - // of damage into the damage we're about to inflict. - if( m_flDamageAccumulator >= 1.0 ) - { - flIntegerDamage += 1.0; - m_flDamageAccumulator -= 1.0; - } - - if ( flIntegerDamage <= 0 ) - return 0; - - m_iHealth -= flIntegerDamage; - } - - return 1; -} - - -int CBaseCombatCharacter::OnTakeDamage_Dying( const CTakeDamageInfo &info ) -{ - return 1; -} - -int CBaseCombatCharacter::OnTakeDamage_Dead( const CTakeDamageInfo &info ) -{ - // do the damage - if ( m_takedamage != DAMAGE_EVENTS_ONLY ) - { - m_iHealth -= info.GetDamage(); - } - - return 1; -} - -//----------------------------------------------------------------------------- -// Purpose: Sets vBodyDir to the body direction (2D) of the combat character. -// Used as NPC's and players extract facing direction differently -// Input : -// Output : -//----------------------------------------------------------------------------- -QAngle CBaseCombatCharacter::BodyAngles() -{ - return GetAbsAngles(); -} - - -Vector CBaseCombatCharacter::BodyDirection2D( void ) -{ - Vector vBodyDir = BodyDirection3D( ); - vBodyDir.z = 0; - vBodyDir.AsVector2D().NormalizeInPlace(); - return vBodyDir; -} - - -Vector CBaseCombatCharacter::BodyDirection3D( void ) -{ - QAngle angles = BodyAngles(); - - // FIXME: cache this - Vector vBodyDir; - AngleVectors( angles, &vBodyDir ); - return vBodyDir; -} - - -void CBaseCombatCharacter::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ) -{ - // Skip this work if we're already marked for transmission. - if ( pInfo->m_pTransmitEdict->Get( entindex() ) ) - return; - - BaseClass::SetTransmit( pInfo, bAlways ); - - bool bLocalPlayer = ( pInfo->m_pClientEnt == edict() ); - - if ( bLocalPlayer ) - { - for ( int i=0; i < MAX_WEAPONS; i++ ) - { - CBaseCombatWeapon *pWeapon = m_hMyWeapons[i]; - if ( !pWeapon ) - continue; - - // The local player is sent all of his weapons. - pWeapon->SetTransmit( pInfo, bAlways ); - } - } - else - { - // The check for EF_NODRAW is useless because the weapon will be networked anyway. In CBaseCombatWeapon:: - // UpdateTransmitState all weapons with owners will transmit to clients in the PVS. - if ( m_hActiveWeapon && !m_hActiveWeapon->IsEffectActive( EF_NODRAW ) ) - m_hActiveWeapon->SetTransmit( pInfo, bAlways ); - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: Add or Change a class relationship for this entity -// Input : -// Output : -//----------------------------------------------------------------------------- -void CBaseCombatCharacter::AddClassRelationship ( Class_T class_type, Disposition_t disposition, int priority ) -{ - // First check to see if a relationship has already been declared for this class - // If so, update it with the new relationship - for (int i=m_Relationship.Count()-1;i >= 0;i--) - { - if (m_Relationship[i].classType == class_type) - { - m_Relationship[i].disposition = disposition; - if ( priority != DEF_RELATIONSHIP_PRIORITY ) - m_Relationship[i].priority = priority; - return; - } - } - - int index = m_Relationship.AddToTail(); - // Add the new class relationship to our relationship table - m_Relationship[index].classType = class_type; - m_Relationship[index].entity = NULL; - m_Relationship[index].disposition = disposition; - m_Relationship[index].priority = ( priority != DEF_RELATIONSHIP_PRIORITY ) ? priority : 0; -} - -//----------------------------------------------------------------------------- -// Purpose: Add or Change a entity relationship for this entity -// Input : -// Output : -//----------------------------------------------------------------------------- -void CBaseCombatCharacter::AddEntityRelationship ( CBaseEntity* pEntity, Disposition_t disposition, int priority ) -{ - // First check to see if a relationship has already been declared for this entity - // If so, update it with the new relationship - for (int i=m_Relationship.Count()-1;i >= 0;i--) - { - if (m_Relationship[i].entity == pEntity) - { - m_Relationship[i].disposition = disposition; - if ( priority != DEF_RELATIONSHIP_PRIORITY ) - m_Relationship[i].priority = priority; - return; - } - } - - int index = m_Relationship.AddToTail(); - // Add the new class relationship to our relationship table - m_Relationship[index].classType = CLASS_NONE; - m_Relationship[index].entity = pEntity; - m_Relationship[index].disposition = disposition; - m_Relationship[index].priority = ( priority != DEF_RELATIONSHIP_PRIORITY ) ? priority : 0; -} - -//----------------------------------------------------------------------------- -// Purpose: Removes an entity relationship from our list -// Input : *pEntity - Entity with whom the relationship should be ended -// Output : True is entity was removed, false if it was not found -//----------------------------------------------------------------------------- -bool CBaseCombatCharacter::RemoveEntityRelationship( CBaseEntity *pEntity ) -{ - // Find the entity in our list, if it exists - for ( int i = m_Relationship.Count()-1; i >= 0; i-- ) - { - if ( m_Relationship[i].entity == pEntity ) - { - // Done, remove it - m_Relationship.Remove( i ); - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Allocates default relationships -//----------------------------------------------------------------------------- -void CBaseCombatCharacter::AllocateDefaultRelationships( ) -{ - if (!m_DefaultRelationship) - { - m_DefaultRelationship = new Relationship_t*[NUM_AI_CLASSES]; - - for (int i=0; iClassify() != CLASS_NONE) - { - // Then check for relationship with this edict's class - for (i=0;iClassify() == m_Relationship[i].classType) - { - return &m_Relationship[i]; - } - } - } - AllocateDefaultRelationships(); - // If none found return the default - return &m_DefaultRelationship[ Classify() ][ pTarget->Classify() ]; -} - -Disposition_t CBaseCombatCharacter::IRelationType ( CBaseEntity *pTarget ) -{ - if ( pTarget ) - return FindEntityRelationship( pTarget )->disposition; - return D_NU; -} - -//----------------------------------------------------------------------------- -// Purpose: describes the relationship between two types of NPC. -// Input : -// Output : -//----------------------------------------------------------------------------- -int CBaseCombatCharacter::IRelationPriority( CBaseEntity *pTarget ) -{ - if ( pTarget ) - return FindEntityRelationship( pTarget )->priority; - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: Get shoot position of BCC at current position/orientation -// Input : -// Output : -//----------------------------------------------------------------------------- -Vector CBaseCombatCharacter::Weapon_ShootPosition( ) -{ - Vector forward, right, up; - - AngleVectors( GetAbsAngles(), &forward, &right, &up ); - - Vector vecSrc = GetAbsOrigin() - + forward * m_HackedGunPos.y - + right * m_HackedGunPos.x - + up * m_HackedGunPos.z; - - return vecSrc; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CBaseEntity *CBaseCombatCharacter::FindHealthItem( const Vector &vecPosition, const Vector &range ) -{ - CBaseEntity *list[1024]; - int count = UTIL_EntitiesInBox( list, 1024, vecPosition - range, vecPosition + range, 0 ); - - for ( int i = 0; i < count; i++ ) - { - CItem *pItem = dynamic_cast(list[ i ]); - - if( pItem ) - { - // Healthkits and healthvials - if( pItem->ClassMatches( "item_health*" ) && FVisible( pItem ) ) - { - return pItem; - } - } - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Compares the weapon's center with this character's current origin, so it -// will not give reliable results for weapons that are visible to the NPC -// but are upstairs/downstairs, etc. -// -// A weapon is said to be on the ground if it is no more than 12 inches above -// or below the caller's feet. -//----------------------------------------------------------------------------- -bool CBaseCombatCharacter::Weapon_IsOnGround( CBaseCombatWeapon *pWeapon ) -{ - if( pWeapon->IsConstrained() ) - { - // Constrained to a rack. - return false; - } - - if( fabs(pWeapon->WorldSpaceCenter().z - GetAbsOrigin().z) >= 12.0f ) - { - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &range - -// Output : CBaseEntity -//----------------------------------------------------------------------------- -CBaseEntity *CBaseCombatCharacter::Weapon_FindUsable( const Vector &range ) -{ - bool bConservative = false; - -#ifdef HL2_DLL - if( hl2_episodic.GetBool() && !GetActiveWeapon() ) - { - // Unarmed citizens are conservative in their weapon finding - if ( Classify() != CLASS_PLAYER_ALLY_VITAL ) - { - bConservative = true; - } - } -#endif - - CBaseCombatWeapon *weaponList[64]; - CBaseCombatWeapon *pBestWeapon = NULL; - - Vector mins = GetAbsOrigin() - range; - Vector maxs = GetAbsOrigin() + range; - int listCount = CBaseCombatWeapon::GetAvailableWeaponsInBox( weaponList, ARRAYSIZE(weaponList), mins, maxs ); - - float fBestDist = 1e6; - - for ( int i = 0; i < listCount; i++ ) - { - // Make sure not moving (ie flying through the air) - Vector velocity; - - CBaseCombatWeapon *pWeapon = weaponList[i]; - Assert(pWeapon); - pWeapon->GetVelocity( &velocity, NULL ); - - if ( pWeapon->CanBePickedUpByNPCs() == false ) - continue; - - if ( velocity.LengthSqr() > 1 || !Weapon_CanUse(pWeapon) ) - continue; - - if ( pWeapon->IsLocked(this) ) - continue; - - if ( GetActiveWeapon() ) - { - // Already armed. Would picking up this weapon improve my situation? - if( GetActiveWeapon()->m_iClassname == pWeapon->m_iClassname ) - { - // No, I'm already using this type of weapon. - continue; - } - - if( FClassnameIs( pWeapon, "weapon_pistol" ) ) - { - // No, it's a pistol. - continue; - } - } - - float fCurDist = (pWeapon->GetLocalOrigin() - GetLocalOrigin()).Length(); - - // Give any reserved weapon a bonus - if( pWeapon->HasSpawnFlags( SF_WEAPON_NO_PLAYER_PICKUP ) ) - { - fCurDist *= 0.5f; - } - - if ( pBestWeapon ) - { - // UNDONE: Better heuristic needed here - // Need to pick by power of weapons - // Don't want to pick a weapon right next to a NPC! - - // Give the AR2 a bonus to be selected by making it seem closer. - if( FClassnameIs( pWeapon, "weapon_ar2" ) ) - { - fCurDist *= 0.5; - } - - // choose the last range attack weapon you find or the first available other weapon - if ( ! (pWeapon->CapabilitiesGet() & bits_CAP_RANGE_ATTACK_GROUP) ) - { - continue; - } - else if (fCurDist > fBestDist ) - { - continue; - } - } - - if( Weapon_IsOnGround(pWeapon) ) - { - // Weapon appears to be lying on the ground. Make sure this weapon is reachable - // by tracing out a human sized hull just above the weapon. If not, reject - trace_t tr; - - Vector vAboveWeapon = pWeapon->GetAbsOrigin(); - UTIL_TraceEntity( this, vAboveWeapon, vAboveWeapon + Vector( 0, 0, 1 ), MASK_SOLID, pWeapon, COLLISION_GROUP_NONE, &tr ); - - if ( tr.startsolid || (tr.fraction < 1.0) ) - continue; - } - else if( bConservative ) - { - // Skip it. - continue; - } - - if( FVisible(pWeapon) ) - { - fBestDist = fCurDist; - pBestWeapon = pWeapon; - } - } - - if( pBestWeapon ) - { - // Lock this weapon for my exclusive use. Lock it for just a couple of seconds because my AI - // might not actually be able to go pick it up right now. - pBestWeapon->Lock( 2.0, this ); - } - - - return pBestWeapon; -} - -//----------------------------------------------------------------------------- -// Purpose: Give the player some ammo. -// Input : iCount - Amount of ammo to give. -// iAmmoIndex - Index of the ammo into the AmmoInfoArray -// iMax - Max carrying capability of the player -// Output : Amount of ammo actually given -//----------------------------------------------------------------------------- -int CBaseCombatCharacter::GiveAmmo( int iCount, int iAmmoIndex, bool bSuppressSound) -{ - if (iCount <= 0) - return 0; - - if ( !g_pGameRules->CanHaveAmmo( this, iAmmoIndex ) ) - { - // game rules say I can't have any more of this ammo type. - return 0; - } - - if ( iAmmoIndex < 0 || iAmmoIndex >= MAX_AMMO_SLOTS ) - return 0; - - int iMax = GetAmmoDef()->MaxCarry(iAmmoIndex); - int iAdd = MIN( iCount, iMax - m_iAmmo[iAmmoIndex] ); - if ( iAdd < 1 ) - return 0; - - // Ammo pickup sound - if ( !bSuppressSound ) - { - EmitSound( "BaseCombatCharacter.AmmoPickup" ); - } - - m_iAmmo.Set( iAmmoIndex, m_iAmmo[iAmmoIndex] + iAdd ); - - return iAdd; -} - -//----------------------------------------------------------------------------- -// Purpose: Give the player some ammo. -//----------------------------------------------------------------------------- -int CBaseCombatCharacter::GiveAmmo( int iCount, const char *szName, bool bSuppressSound ) -{ - int iAmmoType = GetAmmoDef()->Index(szName); - if (iAmmoType == -1) - { - Msg("ERROR: Attempting to give unknown ammo type (%s)\n",szName); - return 0; - } - return GiveAmmo( iCount, iAmmoType, bSuppressSound ); -} - - -ConVar phys_stressbodyweights( "phys_stressbodyweights", "5.0" ); -void CBaseCombatCharacter::VPhysicsUpdate( IPhysicsObject *pPhysics ) -{ - ApplyStressDamage( pPhysics, false ); - BaseClass::VPhysicsUpdate( pPhysics ); -} - -float CBaseCombatCharacter::CalculatePhysicsStressDamage( vphysics_objectstress_t *pStressOut, IPhysicsObject *pPhysics ) -{ - // stress damage hack. - float mass = pPhysics->GetMass(); - CalculateObjectStress( pPhysics, this, pStressOut ); - float stress = (pStressOut->receivedStress * m_impactEnergyScale) / mass; - - // Make sure the stress isn't from being stuck inside some static object. - // how many times your own weight can you hold up? - if ( pStressOut->hasNonStaticStress && stress > phys_stressbodyweights.GetFloat() ) - { - // if stuck, don't do this! - if ( !(pPhysics->GetGameFlags() & FVPHYSICS_PENETRATING) ) - return 200; - } - - return 0; -} - -void CBaseCombatCharacter::ApplyStressDamage( IPhysicsObject *pPhysics, bool bRequireLargeObject ) -{ -#ifdef HL2_DLL - if( Classify() == CLASS_PLAYER_ALLY || Classify() == CLASS_PLAYER_ALLY_VITAL ) - { - // Bypass stress completely for allies and vitals. - if( hl2_episodic.GetBool() ) - return; - } -#endif//HL2_DLL - - vphysics_objectstress_t stressOut; - float damage = CalculatePhysicsStressDamage( &stressOut, pPhysics ); - if ( damage > 0 ) - { - if ( bRequireLargeObject && !stressOut.hasLargeObjectContact ) - return; - - //Msg("Stress! %.2f / %.2f\n", stressOut.exertedStress, stressOut.receivedStress ); - CTakeDamageInfo dmgInfo( GetWorldEntity(), GetWorldEntity(), vec3_origin, vec3_origin, damage, DMG_CRUSH ); - dmgInfo.SetDamageForce( Vector( 0, 0, -stressOut.receivedStress * sv_gravity.GetFloat() * gpGlobals->frametime ) ); - dmgInfo.SetDamagePosition( GetAbsOrigin() ); - TakeDamage( dmgInfo ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const impactdamagetable_t -//----------------------------------------------------------------------------- -const impactdamagetable_t &CBaseCombatCharacter::GetPhysicsImpactDamageTable( void ) -{ - return gDefaultNPCImpactDamageTable; -} - -// how much to amplify impact forces -// This is to account for the ragdolls responding differently than -// the shadow objects. Also this makes the impacts more dramatic. -ConVar phys_impactforcescale( "phys_impactforcescale", "1.0" ); -ConVar phys_upimpactforcescale( "phys_upimpactforcescale", "0.375" ); - -void CBaseCombatCharacter::VPhysicsShadowCollision( int index, gamevcollisionevent_t *pEvent ) -{ - int otherIndex = !index; - CBaseEntity *pOther = pEvent->pEntities[otherIndex]; - IPhysicsObject *pOtherPhysics = pEvent->pObjects[otherIndex]; - if ( !pOther ) - return; - - // Ragdolls are marked as dying. - if ( pOther->m_lifeState == LIFE_DYING ) - return; - - if ( pOther->GetMoveType() != MOVETYPE_VPHYSICS ) - return; - - if ( !pOtherPhysics->IsMoveable() ) - return; - - if ( pOther == GetGroundEntity() ) - return; - - // Player can't damage himself if he's was physics attacker *on this frame* - // which can occur owing to ordering issues it appears. - float flOtherAttackerTime = 0.0f; - -#ifdef HL2_DLL - if ( HL2GameRules()->MegaPhyscannonActive() == true ) - { - flOtherAttackerTime = 1.0f; - } -#endif - - if ( this == pOther->HasPhysicsAttacker( flOtherAttackerTime ) ) - return; - - int damageType = 0; - float damage = 0; - - damage = CalculatePhysicsImpactDamage( index, pEvent, GetPhysicsImpactDamageTable(), m_impactEnergyScale, false, damageType ); - - if ( damage <= 0 ) - return; - - // NOTE: We really need some rotational motion for some of these collisions. - // REVISIT: Maybe resolve this collision on death with a different (not approximately infinite like AABB tensor) - // inertia tensor to get torque? - Vector damageForce = pEvent->postVelocity[index] * pEvent->pObjects[index]->GetMass() * phys_impactforcescale.GetFloat(); - - IServerVehicle *vehicleOther = pOther->GetServerVehicle(); - if ( vehicleOther ) - { - CBaseCombatCharacter *pPassenger = vehicleOther->GetPassenger(); - if ( pPassenger != NULL ) - { - // flag as vehicle damage - damageType |= DMG_VEHICLE; - // if hit by vehicle driven by player, add some upward velocity to force - float len = damageForce.Length(); - damageForce.z += len*phys_upimpactforcescale.GetFloat(); - //Msg("Force %.1f / %.1f\n", damageForce.Length(), damageForce.z ); - - if ( pPassenger->IsPlayer() ) - { - CBasePlayer *pPlayer = assert_cast(pPassenger); - if( damage >= GetMaxHealth() ) - { - pPlayer->RumbleEffect( RUMBLE_357, 0, RUMBLE_FLAG_RESTART ); - } - else - { - pPlayer->RumbleEffect( RUMBLE_PISTOL, 0, RUMBLE_FLAG_RESTART ); - } - } - } - } - - Vector damagePos; - pEvent->pInternalData->GetContactPoint( damagePos ); - CTakeDamageInfo dmgInfo( pOther, pOther, damageForce, damagePos, damage, damageType ); - - // FIXME: is there a better way for physics objects to keep track of what root entity responsible for them moving? - CBasePlayer *pPlayer = pOther->HasPhysicsAttacker( 1.0 ); - if (pPlayer) - { - dmgInfo.SetAttacker( pPlayer ); - } - - // UNDONE: Find one near damagePos? - m_nForceBone = 0; - PhysCallbackDamage( this, dmgInfo, *pEvent, index ); -} - - -//----------------------------------------------------------------------------- -// Purpose: this entity is exploding, or otherwise needs to inflict damage upon -// entities within a certain range. only damage ents that can clearly -// be seen by the explosion! -// Input : -// Output : -//----------------------------------------------------------------------------- -void RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrc, float flRadius, int iClassIgnore, CBaseEntity *pEntityIgnore ) -{ - // NOTE: I did this this way so I wouldn't have to change a whole bunch of - // code unnecessarily. We need TF2 specific rules for RadiusDamage, so I moved - // the implementation of radius damage into gamerules. All existing code calls - // this method, which calls the game rules method - g_pGameRules->RadiusDamage( info, vecSrc, flRadius, iClassIgnore, pEntityIgnore ); - - // Let the world know if this was an explosion. - if( info.GetDamageType() & DMG_BLAST ) - { - // Even the tiniest explosion gets attention. Don't let the radius - // be less than 128 units. - float soundRadius = MAX( 128.0f, flRadius * 1.5 ); - - CSoundEnt::InsertSound( SOUND_COMBAT | SOUND_CONTEXT_EXPLOSION, vecSrc, (int)soundRadius, 0.25, info.GetInflictor() ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Change active weapon and notify derived classes -// -//----------------------------------------------------------------------------- -void CBaseCombatCharacter::SetActiveWeapon( CBaseCombatWeapon *pNewWeapon ) -{ - CBaseCombatWeapon *pOldWeapon = m_hActiveWeapon; - if ( pNewWeapon != pOldWeapon ) - { - m_hActiveWeapon = pNewWeapon; - OnChangeActiveWeapon( pOldWeapon, pNewWeapon ); - } -} - -//----------------------------------------------------------------------------- -// Consider the weapon's built-in accuracy, this character's proficiency with -// the weapon, and the status of the target. Use this information to determine -// how accurately to shoot at the target. -//----------------------------------------------------------------------------- -Vector CBaseCombatCharacter::GetAttackSpread( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget ) -{ - if ( pWeapon ) - return pWeapon->GetBulletSpread(GetCurrentWeaponProficiency()); - return VECTOR_CONE_15DEGREES; -} - -//----------------------------------------------------------------------------- -float CBaseCombatCharacter::GetSpreadBias( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget ) -{ - if ( pWeapon ) - return pWeapon->GetSpreadBias(GetCurrentWeaponProficiency()); - return 1.0; -} - -//----------------------------------------------------------------------------- -// Assume everyone is average with every weapon. Override this to make exceptions. -//----------------------------------------------------------------------------- -WeaponProficiency_t CBaseCombatCharacter::CalcWeaponProficiency( CBaseCombatWeapon *pWeapon ) -{ - return WEAPON_PROFICIENCY_AVERAGE; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -#define MAX_MISS_CANDIDATES 16 -CBaseEntity *CBaseCombatCharacter::FindMissTarget( void ) -{ - CBaseEntity *pMissCandidates[ MAX_MISS_CANDIDATES ]; - int numMissCandidates = 0; - - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - CBaseEntity *pEnts[256]; - Vector radius( 100, 100, 100); - Vector vecSource = GetAbsOrigin(); - - int numEnts = UTIL_EntitiesInBox( pEnts, 256, vecSource-radius, vecSource+radius, 0 ); - - for ( int i = 0; i < numEnts; i++ ) - { - if ( pEnts[i] == NULL ) - continue; - - // New rule for this system. Don't shoot what the player won't see. - if ( pPlayer && !pPlayer->FInViewCone( pEnts[ i ] ) ) - continue; - - if ( numMissCandidates >= MAX_MISS_CANDIDATES ) - break; - - //See if it's a good target candidate - if ( FClassnameIs( pEnts[i], "prop_dynamic" ) || - FClassnameIs( pEnts[i], "prop_physics" ) || - FClassnameIs( pEnts[i], "physics_prop" ) ) - { - pMissCandidates[numMissCandidates++] = pEnts[i]; - continue; - } - } - - if( numMissCandidates == 0 ) - return NULL; - - return pMissCandidates[ random->RandomInt( 0, numMissCandidates - 1 ) ]; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CBaseCombatCharacter::ShouldShootMissTarget( CBaseCombatCharacter *pAttacker ) -{ - // Don't shoot at NPC's right now. - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CBaseCombatCharacter::InputKilledNPC( inputdata_t &inputdata ) -{ - OnKilledNPC( inputdata.pActivator ? inputdata.pActivator->MyCombatCharacterPointer() : NULL ); -} - -//----------------------------------------------------------------------------- -// Purpose: Overload our muzzle flash and send it to any actively held weapon -//----------------------------------------------------------------------------- -void CBaseCombatCharacter::DoMuzzleFlash() -{ - // Our weapon takes our muzzle flash command - CBaseCombatWeapon *pWeapon = GetActiveWeapon(); - if ( pWeapon ) - { - pWeapon->DoMuzzleFlash(); - //NOTENOTE: We do not chain to the base here - } - else - { - BaseClass::DoMuzzleFlash(); - } -} diff --git a/game/server/basecombatcharacter.h b/game/server/basecombatcharacter.h deleted file mode 100644 index 191af21c9..000000000 --- a/game/server/basecombatcharacter.h +++ /dev/null @@ -1,509 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Base combat character with no AI -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef BASECOMBATCHARACTER_H -#define BASECOMBATCHARACTER_H - -#include -#include "weapon_proficiency.h" - -#ifdef _WIN32 -#pragma once -#endif - -#ifdef INVASION_DLL -#include "tf_shareddefs.h" - -#define POWERUP_THINK_CONTEXT "PowerupThink" -#endif - -#include "cbase.h" -#include "baseentity.h" -#include "baseflex.h" -#include "damagemodifier.h" -#include "utllinkedlist.h" -#include "ai_hull.h" -#include "physics_impact_damage.h" - -class CScriptedTarget; -typedef CHandle CBaseCombatWeaponHandle; - -// ------------------------------------- -// Capability Bits -// ------------------------------------- - -enum Capability_t -{ - bits_CAP_MOVE_GROUND = 0x00000001, // walk/run - bits_CAP_MOVE_JUMP = 0x00000002, // jump/leap - bits_CAP_MOVE_FLY = 0x00000004, // can fly, move all around - bits_CAP_MOVE_CLIMB = 0x00000008, // climb ladders - bits_CAP_MOVE_SWIM = 0x00000010, // navigate in water // UNDONE - not yet implemented - bits_CAP_MOVE_CRAWL = 0x00000020, // crawl // UNDONE - not yet implemented - bits_CAP_MOVE_SHOOT = 0x00000040, // tries to shoot weapon while moving - bits_CAP_SKIP_NAV_GROUND_CHECK = 0x00000080, // optimization - skips ground tests while computing navigation - bits_CAP_USE = 0x00000100, // open doors/push buttons/pull levers - //bits_CAP_HEAR = 0x00000200, // can hear forced sounds - bits_CAP_AUTO_DOORS = 0x00000400, // can trigger auto doors - bits_CAP_OPEN_DOORS = 0x00000800, // can open manual doors - bits_CAP_TURN_HEAD = 0x00001000, // can turn head, always bone controller 0 - bits_CAP_WEAPON_RANGE_ATTACK1 = 0x00002000, // can do a weapon range attack 1 - bits_CAP_WEAPON_RANGE_ATTACK2 = 0x00004000, // can do a weapon range attack 2 - bits_CAP_WEAPON_MELEE_ATTACK1 = 0x00008000, // can do a weapon melee attack 1 - bits_CAP_WEAPON_MELEE_ATTACK2 = 0x00010000, // can do a weapon melee attack 2 - bits_CAP_INNATE_RANGE_ATTACK1 = 0x00020000, // can do a innate range attack 1 - bits_CAP_INNATE_RANGE_ATTACK2 = 0x00040000, // can do a innate range attack 1 - bits_CAP_INNATE_MELEE_ATTACK1 = 0x00080000, // can do a innate melee attack 1 - bits_CAP_INNATE_MELEE_ATTACK2 = 0x00100000, // can do a innate melee attack 1 - bits_CAP_USE_WEAPONS = 0x00200000, // can use weapons (non-innate attacks) - //bits_CAP_STRAFE = 0x00400000, // strafe ( walk/run sideways) - bits_CAP_ANIMATEDFACE = 0x00800000, // has animated eyes/face - bits_CAP_USE_SHOT_REGULATOR = 0x01000000, // Uses the shot regulator for range attack1 - bits_CAP_FRIENDLY_DMG_IMMUNE = 0x02000000, // don't take damage from npc's that are D_LI - bits_CAP_SQUAD = 0x04000000, // can form squads - bits_CAP_DUCK = 0x08000000, // cover and reload ducking - bits_CAP_NO_HIT_PLAYER = 0x10000000, // don't hit players - bits_CAP_AIM_GUN = 0x20000000, // Use arms to aim gun, not just body - bits_CAP_NO_HIT_SQUADMATES = 0x40000000, // none - bits_CAP_SIMPLE_RADIUS_DAMAGE = 0x80000000, // Do not use robust radius damage model on this character. -}; - -#define bits_CAP_DOORS_GROUP (bits_CAP_AUTO_DOORS | bits_CAP_OPEN_DOORS) -#define bits_CAP_RANGE_ATTACK_GROUP (bits_CAP_WEAPON_RANGE_ATTACK1 | bits_CAP_WEAPON_RANGE_ATTACK2) -#define bits_CAP_MELEE_ATTACK_GROUP (bits_CAP_WEAPON_MELEE_ATTACK1 | bits_CAP_WEAPON_MELEE_ATTACK2) - - -class CBaseCombatWeapon; - - -enum Disposition_t -{ - D_ER, // Undefined - error - D_HT, // Hate - D_FR, // Fear - D_LI, // Like - D_NU // Neutral -}; - -const int DEF_RELATIONSHIP_PRIORITY = INT_MIN; - -struct Relationship_t -{ - EHANDLE entity; // Relationship to a particular entity - Class_T classType; // Relationship to a class CLASS_NONE = not class based (Def. in baseentity.h) - Disposition_t disposition; // D_HT (Hate), D_FR (Fear), D_LI (Like), D_NT (Neutral) - int priority; // Relative importance of this relationship (higher numbers mean more important) - - DECLARE_SIMPLE_DATADESC(); -}; - -//----------------------------------------------------------------------------- -// Purpose: This should contain all of the combat entry points / functionality -// that are common between NPCs and players -//----------------------------------------------------------------------------- -class CBaseCombatCharacter : public CBaseFlex -{ - DECLARE_CLASS( CBaseCombatCharacter, CBaseFlex ); - -public: - CBaseCombatCharacter(void); - ~CBaseCombatCharacter(void); - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - DECLARE_PREDICTABLE(); - -public: - - void Spawn( void ) - { - BaseClass::Spawn(); - SetBlocksLOS( false ); - } - - - virtual void Precache(); - - virtual int Restore( IRestore &restore ); - - virtual const impactdamagetable_t &GetPhysicsImpactDamageTable( void ); - - int TakeHealth( float flHealth, int bitsDamageType ); - void CauseDeath( const CTakeDamageInfo &info ); - - virtual bool FVisible ( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ); - virtual bool FVisible( const Vector &vecTarget, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ) { return BaseClass::FVisible( vecTarget, traceMask, ppBlocker ); } - static void ResetVisibilityCache( CBaseCombatCharacter *pBCC = NULL ); - -#ifdef PORTAL - virtual bool FVisibleThroughPortal( const CProp_Portal *pPortal, CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ); -#endif - - virtual bool FInViewCone( CBaseEntity *pEntity ); - virtual bool FInViewCone( const Vector &vecSpot ); - -#ifdef PORTAL - virtual CProp_Portal* FInViewConeThroughPortal( CBaseEntity *pEntity ); - virtual CProp_Portal* FInViewConeThroughPortal( const Vector &vecSpot ); -#endif - - virtual bool FInAimCone( CBaseEntity *pEntity ); - virtual bool FInAimCone( const Vector &vecSpot ); - - virtual bool ShouldShootMissTarget( CBaseCombatCharacter *pAttacker ); - virtual CBaseEntity *FindMissTarget( void ); - - // Do not call HandleInteraction directly, use DispatchInteraction - bool DispatchInteraction( int interactionType, void *data, CBaseCombatCharacter* sourceEnt ) { return ( interactionType > 0 ) ? HandleInteraction( interactionType, data, sourceEnt ) : false; } - virtual bool HandleInteraction( int interactionType, void *data, CBaseCombatCharacter* sourceEnt ); - - virtual QAngle BodyAngles(); - virtual Vector BodyDirection2D( void ); - virtual Vector BodyDirection3D( void ); - virtual Vector HeadDirection2D( void ) { return BodyDirection2D( ); }; // No head motion so just return body dir - virtual Vector HeadDirection3D( void ) { return BodyDirection2D( ); }; // No head motion so just return body dir - virtual Vector EyeDirection2D( void ) { return HeadDirection2D( ); }; // No eye motion so just return head dir - virtual Vector EyeDirection3D( void ) { return HeadDirection3D( ); }; // No eye motion so just return head dir - - virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ); - - - // ----------------------- - // Ammo - // ----------------------- - virtual int GiveAmmo( int iCount, int iAmmoIndex, bool bSuppressSound = false ); - int GiveAmmo( int iCount, const char *szName, bool bSuppressSound = false ); - void RemoveAmmo( int iCount, int iAmmoIndex ); - void RemoveAmmo( int iCount, const char *szName ); - void RemoveAllAmmo( ); - int GetAmmoCount( int iAmmoIndex ) const; - int GetAmmoCount( char *szName ) const; - - virtual Activity NPC_TranslateActivity( Activity baseAct ); - - // ----------------------- - // Weapons - // ----------------------- - CBaseCombatWeapon* Weapon_Create( const char *pWeaponName ); - virtual Activity Weapon_TranslateActivity( Activity baseAct, bool *pRequired = NULL ); - void Weapon_SetActivity( Activity newActivity, float duration ); - virtual void Weapon_FrameUpdate( void ); - virtual void Weapon_HandleAnimEvent( animevent_t *pEvent ); - CBaseCombatWeapon* Weapon_OwnsThisType( const char *pszWeapon, int iSubType = 0 ) const; // True if already owns a weapon of this class - virtual bool Weapon_CanUse( CBaseCombatWeapon *pWeapon ); // True is allowed to use this class of weapon - virtual void Weapon_Equip( CBaseCombatWeapon *pWeapon ); // Adds weapon to player - virtual bool Weapon_EquipAmmoOnly( CBaseCombatWeapon *pWeapon ); // Adds weapon ammo to player, leaves weapon - bool Weapon_Detach( CBaseCombatWeapon *pWeapon ); // Clear any pointers to the weapon. - virtual void Weapon_Drop( CBaseCombatWeapon *pWeapon, const Vector *pvecTarget = NULL, const Vector *pVelocity = NULL ); - virtual bool Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmodelindex = 0 ); // Switch to given weapon if has ammo (false if failed) - virtual Vector Weapon_ShootPosition( ); // gun position at current position/orientation - bool Weapon_IsOnGround( CBaseCombatWeapon *pWeapon ); - CBaseEntity* Weapon_FindUsable( const Vector &range ); // search for a usable weapon in this range - virtual bool Weapon_CanSwitchTo(CBaseCombatWeapon *pWeapon); - virtual bool Weapon_SlotOccupied( CBaseCombatWeapon *pWeapon ); - virtual CBaseCombatWeapon *Weapon_GetSlot( int slot ) const; - CBaseCombatWeapon *Weapon_GetWpnForAmmo( int iAmmoIndex ); - - - // For weapon strip - void Weapon_DropAll( bool bDisallowWeaponPickup = false ); - - virtual bool AddPlayerItem( CBaseCombatWeapon *pItem ) { return false; } - virtual bool RemovePlayerItem( CBaseCombatWeapon *pItem ) { return false; } - - virtual bool CanBecomeServerRagdoll( void ) { return true; } - - // ----------------------- - // Damage - // ----------------------- - // Don't override this for characters, override the per-life-state versions below - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - - // Override these to control how your character takes damage in different states - virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - virtual int OnTakeDamage_Dying( const CTakeDamageInfo &info ); - virtual int OnTakeDamage_Dead( const CTakeDamageInfo &info ); - - virtual void OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker ) {} - virtual void NotifyFriendsOfDamage( CBaseEntity *pAttackerEntity ) {} - - virtual void OnPlayerKilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info ) {} - - // utility function to calc damage force - Vector CalcDamageForceVector( const CTakeDamageInfo &info ); - - virtual int BloodColor(); - virtual Activity GetDeathActivity( void ); - - virtual bool CorpseGib( const CTakeDamageInfo &info ); - virtual void CorpseFade( void ); // Called instead of GibNPC() when gibs are disabled - virtual bool HasHumanGibs( void ); - virtual bool HasAlienGibs( void ); - virtual bool ShouldGib( const CTakeDamageInfo &info ) { return false; } // Always ragdoll, unless specified by the leaf class - - float GetDamageAccumulator() { return m_flDamageAccumulator; } - int GetDamageCount( void ) { return m_iDamageCount; } // # of times NPC has been damaged. used for tracking 1-shot kills. - - // Character killed (only fired once) - virtual void Event_Killed( const CTakeDamageInfo &info ); - - // Killed a character - void InputKilledNPC( inputdata_t &inputdata ); - virtual void OnKilledNPC( CBaseCombatCharacter *pKilled ) {}; - - // Exactly one of these happens immediately after killed (gibbed may happen later when the corpse gibs) - // Character gibbed or faded out (violence controls) (only fired once) - // returns true if gibs were spawned - virtual bool Event_Gibbed( const CTakeDamageInfo &info ); - // Character entered the dying state without being gibbed (only fired once) - virtual void Event_Dying( void ); - // character died and should become a ragdoll now - // return true if converted to a ragdoll, false to use AI death - virtual bool BecomeRagdoll( const CTakeDamageInfo &info, const Vector &forceVector ); - virtual void FixupBurningServerRagdoll( CBaseEntity *pRagdoll ); - - virtual bool BecomeRagdollBoogie( CBaseEntity *pKiller, const Vector &forceVector, float duration, int flags ); - - CBaseEntity *FindHealthItem( const Vector &vecPosition, const Vector &range ); - - - virtual CBaseEntity *CheckTraceHullAttack( float flDist, const Vector &mins, const Vector &maxs, int iDamage, int iDmgType, float forceScale = 1.0f, bool bDamageAnyNPC = false ); - virtual CBaseEntity *CheckTraceHullAttack( const Vector &vStart, const Vector &vEnd, const Vector &mins, const Vector &maxs, int iDamage, int iDmgType, float flForceScale = 1.0f, bool bDamageAnyNPC = false ); - - virtual CBaseCombatCharacter *MyCombatCharacterPointer( void ) { return this; } - - // VPHYSICS - virtual void VPhysicsShadowCollision( int index, gamevcollisionevent_t *pEvent ); - virtual void VPhysicsUpdate( IPhysicsObject *pPhysics ); - float CalculatePhysicsStressDamage( vphysics_objectstress_t *pStressOut, IPhysicsObject *pPhysics ); - void ApplyStressDamage( IPhysicsObject *pPhysics, bool bRequireLargeObject ); - - virtual void PushawayTouch( CBaseEntity *pOther ) {} - - void SetImpactEnergyScale( float fScale ) { m_impactEnergyScale = fScale; } - - virtual void UpdateOnRemove( void ); - - virtual Disposition_t IRelationType( CBaseEntity *pTarget ); - virtual int IRelationPriority( CBaseEntity *pTarget ); - - virtual void SetLightingOriginRelative( CBaseEntity *pLightingOrigin ); - -protected: - Relationship_t *FindEntityRelationship( CBaseEntity *pTarget ); - -public: - - // Vehicle queries - virtual bool IsInAVehicle( void ) const { return false; } - virtual IServerVehicle *GetVehicle( void ) { return NULL; } - virtual CBaseEntity *GetVehicleEntity( void ) { return NULL; } - virtual bool ExitVehicle( void ) { return false; } - - // Blood color (see BLOOD_COLOR_* macros in baseentity.h) - void SetBloodColor( int nBloodColor ); - - // Weapons.. - CBaseCombatWeapon* GetActiveWeapon() const; - int WeaponCount() const; - CBaseCombatWeapon* GetWeapon( int i ) const; - bool RemoveWeapon( CBaseCombatWeapon *pWeapon ); - void RemoveAllWeapons(); - WeaponProficiency_t GetCurrentWeaponProficiency() { return m_CurrentWeaponProficiency; } - void SetCurrentWeaponProficiency( WeaponProficiency_t iProficiency ) { m_CurrentWeaponProficiency = iProficiency; } - virtual WeaponProficiency_t CalcWeaponProficiency( CBaseCombatWeapon *pWeapon ); - virtual Vector GetAttackSpread( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget = NULL ); - virtual float GetSpreadBias( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget ); - virtual void DoMuzzleFlash(); - - // Interactions - static void InitInteractionSystem(); - - // Relationships - static void AllocateDefaultRelationships( ); - static void SetDefaultRelationship( Class_T nClass, Class_T nClassTarget, Disposition_t nDisposition, int nPriority ); - Disposition_t GetDefaultRelationshipDisposition( Class_T nClassTarget ); - virtual void AddEntityRelationship( CBaseEntity *pEntity, Disposition_t nDisposition, int nPriority ); - virtual bool RemoveEntityRelationship( CBaseEntity *pEntity ); - virtual void AddClassRelationship( Class_T nClass, Disposition_t nDisposition, int nPriority ); - - // Nav hull type - Hull_t GetHullType() const { return m_eHull; } - void SetHullType( Hull_t hullType ) { m_eHull = hullType; } - - // FIXME: The following 3 methods are backdoor hack methods - - // This is a sort of hack back-door only used by physgun! - void SetAmmoCount( int iCount, int iAmmoIndex ); - - // This is a hack to blat out the current active weapon... - // Used by weapon_slam + game_ui - void SetActiveWeapon( CBaseCombatWeapon *pNewWeapon ); - void ClearActiveWeapon() { SetActiveWeapon( NULL ); } - virtual void OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ) {} - - // I can't use my current weapon anymore. Switch me to the next best weapon. - bool SwitchToNextBestWeapon(CBaseCombatWeapon *pCurrent); - - // This is a hack to copy the relationship strings used by monstermaker - void SetRelationshipString( string_t theString ) { m_RelationshipString = theString; } - - float GetNextAttack() const { return m_flNextAttack; } - void SetNextAttack( float flWait ) { m_flNextAttack = flWait; } - - bool m_bForceServerRagdoll; - - // Pickup prevention - bool IsAllowedToPickupWeapons( void ) { return !m_bPreventWeaponPickup; } - void SetPreventWeaponPickup( bool bPrevent ) { m_bPreventWeaponPickup = bPrevent; } - bool m_bPreventWeaponPickup; - -#ifdef INVASION_DLL -public: - - // TF2 Powerups - virtual bool CanBePoweredUp( void ); - bool HasPowerup( int iPowerup ); - virtual bool CanPowerupNow( int iPowerup ); // Return true if I can be powered by this powerup right now - virtual bool CanPowerupEver( int iPowerup ); // Return true if I ever accept this powerup type - - void SetPowerup( int iPowerup, bool bState, float flTime = 0, float flAmount = 0, CBaseEntity *pAttacker = NULL, CDamageModifier *pDamageModifier = NULL ); - virtual bool AttemptToPowerup( int iPowerup, float flTime, float flAmount = 0, CBaseEntity *pAttacker = NULL, CDamageModifier *pDamageModifier = NULL ); - virtual float PowerupDuration( int iPowerup, float flTime ); - virtual void PowerupStart( int iPowerup, float flAmount = 0, CBaseEntity *pAttacker = NULL, CDamageModifier *pDamageModifier = NULL ); - virtual void PowerupEnd( int iPowerup ); - - void PowerupThink( void ); - virtual void PowerupThink( int iPowerup ); - -public: - - CNetworkVar( int, m_iPowerups ); - float m_flPowerupAttemptTimes[ MAX_POWERUPS ]; - float m_flPowerupEndTimes[ MAX_POWERUPS ]; - float m_flFractionalBoost; // POWERUP_BOOST health fraction - specific powerup data - -#endif - -public: - // returns the last body region that took damage - int LastHitGroup() const { return m_LastHitGroup; } -protected: - void SetLastHitGroup( int nHitGroup ) { m_LastHitGroup = nHitGroup; } - -public: - CNetworkVar( float, m_flNextAttack ); // cannot attack again until this time - -protected: -private: - Hull_t m_eHull; - -protected: - int m_bloodColor; // color of blood particless - - // ------------------- - // combat ability data - // ------------------- - float m_flFieldOfView; // cosine of field of view for this character - Vector m_HackedGunPos; // HACK until we can query end of gun - string_t m_RelationshipString; // Used to load up relationship keyvalues - float m_impactEnergyScale;// scale the amount of energy used to calculate damage this ent takes due to physics - -public: - static int GetInteractionID(); // Returns the next interaction # - -private: - // For weapon strip - void ThrowDirForWeaponStrip( CBaseCombatWeapon *pWeapon, const Vector &vecForward, Vector *pVecThrowDir ); - void DropWeaponForWeaponStrip( CBaseCombatWeapon *pWeapon, const Vector &vecForward, const QAngle &vecAngles, float flDiameter ); - - friend class CScriptedTarget; // needs to access GetInteractionID() - - static int m_lastInteraction; // Last registered interaction # - static Relationship_t** m_DefaultRelationship; - - // attack/damage - int m_LastHitGroup; // the last body region that took damage - float m_flDamageAccumulator; // so very small amounts of damage do not get lost. - int m_iDamageCount; // # of times NPC has been damaged. used for tracking 1-shot kills. - - // Weapon proficiency gets calculated each time an NPC changes his weapon, and then - // cached off as the CurrentWeaponProficiency. - WeaponProficiency_t m_CurrentWeaponProficiency; - - // --------------- - // Relationships - // --------------- - CUtlVector m_Relationship; // Array of relationships - - // shared ammo slots - CNetworkArrayForDerived( int, m_iAmmo, MAX_AMMO_SLOTS ); - - // Usable character items - CNetworkArray( CBaseCombatWeaponHandle, m_hMyWeapons, MAX_WEAPONS ); - - CNetworkHandle( CBaseCombatWeapon, m_hActiveWeapon ); - - friend class CCleanupDefaultRelationShips; -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline int CBaseCombatCharacter::WeaponCount() const -{ - return MAX_WEAPONS; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : i - -//----------------------------------------------------------------------------- -inline CBaseCombatWeapon *CBaseCombatCharacter::GetWeapon( int i ) const -{ - Assert( (i >= 0) && (i < MAX_WEAPONS) ); - return m_hMyWeapons[i].Get(); -} - -#ifdef INVASION_DLL -// Powerup Inlines -inline bool CBaseCombatCharacter::CanBePoweredUp( void ) { return true; } -inline float CBaseCombatCharacter::PowerupDuration( int iPowerup, float flTime ) { return flTime; } -inline void CBaseCombatCharacter::PowerupEnd( int iPowerup ) { return; } -inline void CBaseCombatCharacter::PowerupThink( int iPowerup ) { return; } -#endif - -EXTERN_SEND_TABLE(DT_BaseCombatCharacter); - -void RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrc, float flRadius, int iClassIgnore, CBaseEntity *pEntityIgnore ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CTraceFilterMelee : public CTraceFilterEntitiesOnly -{ -public: - // It does have a base, but we'll never network anything below here.. - DECLARE_CLASS_NOBASE( CTraceFilterMelee ); - - CTraceFilterMelee( const IHandleEntity *passentity, int collisionGroup, CTakeDamageInfo *dmgInfo, float flForceScale, bool bDamageAnyNPC ) - : m_pPassEnt(passentity), m_collisionGroup(collisionGroup), m_dmgInfo(dmgInfo), m_pHit(NULL), m_flForceScale(flForceScale), m_bDamageAnyNPC(bDamageAnyNPC) - { - } - - virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ); - -public: - const IHandleEntity *m_pPassEnt; - int m_collisionGroup; - CTakeDamageInfo *m_dmgInfo; - CBaseEntity *m_pHit; - float m_flForceScale; - bool m_bDamageAnyNPC; -}; - -#endif // BASECOMBATCHARACTER_H diff --git a/game/server/basecombatweapon.cpp b/game/server/basecombatweapon.cpp deleted file mode 100644 index c88885853..000000000 --- a/game/server/basecombatweapon.cpp +++ /dev/null @@ -1,734 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "ai_basenpc.h" -#include "animation.h" -#include "basecombatweapon.h" -#include "player.h" // For gEvilImpulse101 / CBasePlayer -#include "gamerules.h" // For g_pGameRules -#include -#include "ammodef.h" -#include "baseviewmodel.h" -#include "in_buttons.h" -#include "soundent.h" -#include "weapon_parse.h" -#include "game.h" -#include "engine/IEngineSound.h" -#include "sendproxy.h" -#include "tier1/strtools.h" -#include "vphysics/constraints.h" -#include "npcevent.h" -#include "igamesystem.h" -#include "collisionutils.h" -#include "iservervehicle.h" -#include "func_break.h" - -#ifdef HL2MP - #include "hl2mp_gamerules.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern int gEvilImpulse101; // In Player.h - -// ----------------------------------------- -// Sprite Index info -// ----------------------------------------- -short g_sModelIndexLaser; // holds the index for the laser beam -const char *g_pModelNameLaser = "sprites/laserbeam.vmt"; -short g_sModelIndexLaserDot; // holds the index for the laser beam dot -short g_sModelIndexFireball; // holds the index for the fireball -short g_sModelIndexSmoke; // holds the index for the smoke cloud -short g_sModelIndexWExplosion; // holds the index for the underwater explosion -short g_sModelIndexBubbles; // holds the index for the bubbles model -short g_sModelIndexBloodDrop; // holds the sprite index for the initial blood -short g_sModelIndexBloodSpray; // holds the sprite index for splattered blood - - -ConVar weapon_showproficiency( "weapon_showproficiency", "0" ); -extern ConVar ai_debug_shoot_positions; - -//----------------------------------------------------------------------------- -// Purpose: Precache global weapon sounds -//----------------------------------------------------------------------------- -void W_Precache(void) -{ - PrecacheFileWeaponInfoDatabase( filesystem, g_pGameRules->GetEncryptionKey() ); - - - -#ifdef HL1_DLL - g_sModelIndexWExplosion = CBaseEntity::PrecacheModel ("sprites/WXplo1.vmt");// underwater fireball - g_sModelIndexBloodSpray = CBaseEntity::PrecacheModel ("sprites/bloodspray.vmt"); // initial blood - g_sModelIndexBloodDrop = CBaseEntity::PrecacheModel ("sprites/blood.vmt"); // splattered blood - g_sModelIndexLaserDot = CBaseEntity::PrecacheModel("sprites/laserdot.vmt"); -#endif // HL1_DLL - -#ifndef TF_DLL - g_sModelIndexFireball = CBaseEntity::PrecacheModel ("sprites/zerogxplode.vmt");// fireball - - g_sModelIndexSmoke = CBaseEntity::PrecacheModel ("sprites/steam1.vmt");// smoke - g_sModelIndexBubbles = CBaseEntity::PrecacheModel ("sprites/bubble.vmt");//bubbles - g_sModelIndexLaser = CBaseEntity::PrecacheModel( (char *)g_pModelNameLaser ); - - PrecacheParticleSystem( "blood_impact_red_01" ); - PrecacheParticleSystem( "blood_impact_green_01" ); - PrecacheParticleSystem( "blood_impact_yellow_01" ); - - CBaseEntity::PrecacheModel ("effects/bubble.vmt");//bubble trails - - CBaseEntity::PrecacheModel("models/weapons/w_bullet.mdl"); -#endif - - CBaseEntity::PrecacheScriptSound( "BaseCombatWeapon.WeaponDrop" ); - CBaseEntity::PrecacheScriptSound( "BaseCombatWeapon.WeaponMaterialize" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Transmit weapon data -//----------------------------------------------------------------------------- -int CBaseCombatWeapon::UpdateTransmitState( void) -{ - // If the weapon is being carried by a CBaseCombatCharacter, let the combat character do the logic - // about whether or not to transmit it. - if ( GetOwner() ) - { - return SetTransmitState( FL_EDICT_PVSCHECK ); - } - else - { - // If it's just lying around, then use CBaseEntity's visibility test to see if it should be sent. - return BaseClass::UpdateTransmitState(); - } -} - - -void CBaseCombatWeapon::Operator_FrameUpdate( CBaseCombatCharacter *pOperator ) -{ - StudioFrameAdvance( ); // animate - - if ( IsSequenceFinished() ) - { - if ( SequenceLoops() ) - { - // animation does loop, which means we're playing subtle idle. Might need to fidget. - int iSequence = SelectWeightedSequence( GetActivity() ); - if ( iSequence != ACTIVITY_NOT_AVAILABLE ) - { - ResetSequence( iSequence ); // Set to new anim (if it's there) - } - } -#if 0 - else - { - // animation that just ended doesn't loop! That means we just finished a fidget - // and should return to our heaviest weighted idle (the subtle one) - SelectHeaviestSequence( GetActivity() ); - } -#endif - } - - // Animation events are passed back to the weapon's owner/operator - DispatchAnimEvents( pOperator ); - - // Update and dispatch the viewmodel events - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex ); - - if ( vm != NULL ) - { - vm->StudioFrameAdvance(); - vm->DispatchAnimEvents( this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEvent - -// *pOperator - -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - if ( (pEvent->type & AE_TYPE_NEWEVENTSYSTEM) && (pEvent->type & AE_TYPE_SERVER) ) - { - if ( pEvent->event == AE_NPC_WEAPON_FIRE ) - { - bool bSecondary = (atoi( pEvent->options ) != 0); - Operator_ForceNPCFire( pOperator, bSecondary ); - return; - } - else if ( pEvent->event == AE_WPN_PLAYWPNSOUND ) - { - int iSnd = GetWeaponSoundFromString(pEvent->options); - if ( iSnd != -1 ) - { - WeaponSound( (WeaponSound_t)iSnd ); - } - } - } - - DevWarning( 2, "Unhandled animation event %d from %s --> %s\n", pEvent->event, pOperator->GetClassname(), GetClassname() ); -} - -// NOTE: This should never be called when a character is operating the weapon. Animation events should be -// routed through the character, and then back into CharacterAnimEvent() -void CBaseCombatWeapon::HandleAnimEvent( animevent_t *pEvent ) -{ - //If the player is receiving this message, pass it through - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner != NULL ) - { - Operator_HandleAnimEvent( pEvent, pOwner ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Make the weapon visible and tangible -//----------------------------------------------------------------------------- -CBaseEntity* CBaseCombatWeapon::Respawn( void ) -{ - // make a copy of this weapon that is invisible and inaccessible to players (no touch function). The weapon spawn/respawn code - // will decide when to make the weapon visible and touchable. - CBaseEntity *pNewWeapon = CBaseEntity::Create( GetClassname(), g_pGameRules->VecWeaponRespawnSpot( this ), GetLocalAngles(), GetOwnerEntity() ); - - if ( pNewWeapon ) - { - pNewWeapon->AddEffects( EF_NODRAW );// invisible for now - pNewWeapon->SetTouch( NULL );// no touch - pNewWeapon->SetThink( &CBaseCombatWeapon::AttemptToMaterialize ); - - UTIL_DropToFloor( this, MASK_SOLID ); - - // not a typo! We want to know when the weapon the player just picked up should respawn! This new entity we created is the replacement, - // but when it should respawn is based on conditions belonging to the weapon that was taken. - pNewWeapon->SetNextThink( gpGlobals->curtime + g_pGameRules->FlWeaponRespawnTime( this ) ); - } - else - { - Warning("Respawn failed to create %s!\n", GetClassname() ); - } - - return pNewWeapon; -} - -//----------------------------------------------------------------------------- -// Purpose: Weapons ignore other weapons when LOS tracing -//----------------------------------------------------------------------------- -class CWeaponLOSFilter : public CTraceFilterSkipTwoEntities -{ - DECLARE_CLASS( CWeaponLOSFilter, CTraceFilterSkipTwoEntities ); -public: - CWeaponLOSFilter( IHandleEntity *pHandleEntity, IHandleEntity *pHandleEntity2, int collisionGroup ) : - CTraceFilterSkipTwoEntities( pHandleEntity, pHandleEntity2, collisionGroup ), m_pVehicle( NULL ) - { - // If the tracing entity is in a vehicle, then ignore it - if ( pHandleEntity != NULL ) - { - CBaseCombatCharacter *pBCC = ((CBaseEntity *)pHandleEntity)->MyCombatCharacterPointer(); - if ( pBCC != NULL ) - { - m_pVehicle = pBCC->GetVehicleEntity(); - } - } - } - virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ) - { - CBaseEntity *pEntity = (CBaseEntity *)pServerEntity; - - if ( pEntity->GetCollisionGroup() == COLLISION_GROUP_WEAPON ) - return false; - - // Don't collide with the tracing entity's vehicle (if it exists) - if ( pServerEntity == m_pVehicle ) - return false; - - if ( pEntity->GetHealth() > 0 ) - { - CBreakable *pBreakable = dynamic_cast(pEntity); - if ( pBreakable && pBreakable->IsBreakable() && pBreakable->GetMaterialType() == matGlass) - { - return false; - } - } - - return BaseClass::ShouldHitEntity( pServerEntity, contentsMask ); - } - -private: - CBaseEntity *m_pVehicle; -}; - -//----------------------------------------------------------------------------- -// Purpose: Check the weapon LOS for an owner at an arbitrary position -// If bSetConditions is true, LOS related conditions will also be set -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::WeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions ) -{ - // -------------------- - // Check for occlusion - // -------------------- - CAI_BaseNPC* npcOwner = m_hOwner.Get()->MyNPCPointer(); - - // Find its relative shoot position - Vector vecRelativeShootPosition; - VectorSubtract( npcOwner->Weapon_ShootPosition(), npcOwner->GetAbsOrigin(), vecRelativeShootPosition ); - Vector barrelPos = ownerPos + vecRelativeShootPosition; - - // FIXME: If we're in a vehicle, we need some sort of way to handle shooting out of them - - // Use the custom LOS trace filter - CWeaponLOSFilter traceFilter( m_hOwner.Get(), npcOwner->GetEnemy(), COLLISION_GROUP_BREAKABLE_GLASS ); - trace_t tr; - UTIL_TraceLine( barrelPos, targetPos, MASK_SHOT, &traceFilter, &tr ); - - // See if we completed the trace without interruption - if ( tr.fraction == 1.0 ) - { - if ( ai_debug_shoot_positions.GetBool() ) - { - NDebugOverlay::Line( barrelPos, targetPos, 0, 255, 0, false, 1.0 ); - } - - return true; - } - - CBaseEntity *pHitEnt = tr.m_pEnt; - - CBasePlayer *pEnemyPlayer = ToBasePlayer( npcOwner->GetEnemy() ); - - // is player in a vehicle? if so, verify vehicle is target and return if so (so npc shoots at vehicle) - if ( pEnemyPlayer && pEnemyPlayer->IsInAVehicle() ) - { - // Ok, player in vehicle, check if vehicle is target we're looking at, fire if it is - // Also, check to see if the owner of the entity is the vehicle, in which case it's valid too. - // This catches vehicles that use bone followers. - CBaseEntity *pVehicle = pEnemyPlayer->GetVehicle()->GetVehicleEnt(); - if ( pHitEnt == pVehicle || pHitEnt->GetOwnerEntity() == pVehicle ) - return true; - } - - // Hitting our enemy is a success case - if ( pHitEnt == npcOwner->GetEnemy() ) - { - if ( ai_debug_shoot_positions.GetBool() ) - { - NDebugOverlay::Line( barrelPos, targetPos, 0, 255, 0, false, 1.0 ); - } - - return true; - } - - // If a vehicle is blocking the view, grab its driver and use that as the combat character - CBaseCombatCharacter *pBCC; - IServerVehicle *pVehicle = pHitEnt->GetServerVehicle(); - if ( pVehicle ) - { - pBCC = pVehicle->GetPassenger( ); - } - else - { - pBCC = ToBaseCombatCharacter( pHitEnt ); - } - - if ( pBCC ) - { - if ( npcOwner->IRelationType( pBCC ) == D_HT ) - return true; - - if ( bSetConditions ) - { - npcOwner->SetCondition( COND_WEAPON_BLOCKED_BY_FRIEND ); - } - } - else if ( bSetConditions ) - { - npcOwner->SetCondition( COND_WEAPON_SIGHT_OCCLUDED ); - npcOwner->SetEnemyOccluder( pHitEnt ); - - if( ai_debug_shoot_positions.GetBool() ) - { - NDebugOverlay::Line( tr.startpos, tr.endpos, 255, 0, 0, false, 1.0 ); - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Base class always returns not bits -//----------------------------------------------------------------------------- -int CBaseCombatWeapon::WeaponRangeAttack1Condition( float flDot, float flDist ) -{ - if ( UsesPrimaryAmmo() && !HasPrimaryAmmo() ) - { - return COND_NO_PRIMARY_AMMO; - } - else if ( flDist < m_fMinRange1) - { - return COND_TOO_CLOSE_TO_ATTACK; - } - else if (flDist > m_fMaxRange1) - { - return COND_TOO_FAR_TO_ATTACK; - } - else if (flDot < 0.5) // UNDONE: Why check this here? Isn't the AI checking this already? - { - return COND_NOT_FACING_ATTACK; - } - - return COND_CAN_RANGE_ATTACK1; -} - -//----------------------------------------------------------------------------- -// Purpose: Base class always returns not bits -//----------------------------------------------------------------------------- -int CBaseCombatWeapon::WeaponRangeAttack2Condition( float flDot, float flDist ) -{ - // currently disabled - return COND_NONE; - - if ( m_bReloadsSingly ) - { - if (m_iClip2 <=0) - { - return COND_NO_SECONDARY_AMMO; - } - else if ( flDist < m_fMinRange2) - { - return COND_TOO_CLOSE_TO_ATTACK; - } - else if (flDist > m_fMaxRange2) - { - return COND_TOO_FAR_TO_ATTACK; - } - else if (flDot < 0.5) - { - return COND_NOT_FACING_ATTACK; - } - return COND_CAN_RANGE_ATTACK2; - } - - return COND_NONE; -} - -//----------------------------------------------------------------------------- -// Purpose: Base class always returns not bits -//----------------------------------------------------------------------------- -int CBaseCombatWeapon::WeaponMeleeAttack1Condition( float flDot, float flDist ) -{ - return COND_NONE; -} - -//----------------------------------------------------------------------------- -// Purpose: Base class always returns not bits -//----------------------------------------------------------------------------- -int CBaseCombatWeapon::WeaponMeleeAttack2Condition( float flDot, float flDist ) -{ - return COND_NONE; -} - -//==================================================================================== -// WEAPON DROPPING / DESTRUCTION -//==================================================================================== -void CBaseCombatWeapon::Delete( void ) -{ - SetTouch( NULL ); - // FIXME: why doesn't this just remove itself now? - SetThink(&CBaseCombatWeapon::SUB_Remove); - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -void CBaseCombatWeapon::DestroyItem( void ) -{ - CBaseCombatCharacter *pOwner = m_hOwner.Get(); - - if ( pOwner ) - { - // if attached to a player, remove. - pOwner->RemovePlayerItem( this ); - } - - Kill( ); -} - -void CBaseCombatWeapon::Kill( void ) -{ - SetTouch( NULL ); - // FIXME: why doesn't this just remove itself now? - // FIXME: how is this different than Delete(), and why do they have the same code in them? - SetThink(&CBaseCombatWeapon::SUB_Remove); - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -//==================================================================================== -// FALL TO GROUND -//==================================================================================== -//----------------------------------------------------------------------------- -// Purpose: Setup for the fall -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::FallInit( void ) -{ - SetModel( GetWorldModel() ); - VPhysicsDestroyObject(); - - if ( !VPhysicsInitNormal( SOLID_BBOX, GetSolidFlags() | FSOLID_TRIGGER, false ) ) - { - SetMoveType( MOVETYPE_FLYGRAVITY ); - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_TRIGGER ); - } - else - { -#if !defined( CLIENT_DLL ) - // Constrained start? - if ( HasSpawnFlags( SF_WEAPON_START_CONSTRAINED ) ) - { - //Constrain the weapon in place - IPhysicsObject *pReferenceObject, *pAttachedObject; - - pReferenceObject = g_PhysWorldObject; - pAttachedObject = VPhysicsGetObject(); - - if ( pReferenceObject && pAttachedObject ) - { - constraint_fixedparams_t fixed; - fixed.Defaults(); - fixed.InitWithCurrentObjectState( pReferenceObject, pAttachedObject ); - - fixed.constraint.forceLimit = lbs2kg( 10000 ); - fixed.constraint.torqueLimit = lbs2kg( 10000 ); - - m_pConstraint = physenv->CreateFixedConstraint( pReferenceObject, pAttachedObject, NULL, fixed ); - - m_pConstraint->SetGameData( (void *) this ); - } - } -#endif //CLIENT_DLL - } - - SetPickupTouch(); - - SetThink( &CBaseCombatWeapon::FallThink ); - - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -//----------------------------------------------------------------------------- -// Purpose: Items that have just spawned run this think to catch them when -// they hit the ground. Once we're sure that the object is grounded, -// we change its solid type to trigger and set it in a large box that -// helps the player get it. -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::FallThink ( void ) -{ - SetNextThink( gpGlobals->curtime + 0.1f ); - - bool shouldMaterialize = false; - IPhysicsObject *pPhysics = VPhysicsGetObject(); - if ( pPhysics ) - { - shouldMaterialize = pPhysics->IsAsleep(); - } - else - { - shouldMaterialize = (GetFlags() & FL_ONGROUND) ? true : false; - } - - if ( shouldMaterialize ) - { - // clatter if we have an owner (i.e., dropped by someone) - // don't clatter if the gun is waiting to respawn (if it's waiting, it is invisible!) - if ( GetOwnerEntity() ) - { - EmitSound( "BaseCombatWeapon.WeaponDrop" ); - } - Materialize(); - } -} - -//==================================================================================== -// WEAPON SPAWNING -//==================================================================================== -//----------------------------------------------------------------------------- -// Purpose: Make a weapon visible and tangible -//-----------------------------------------------------------------------------// -void CBaseCombatWeapon::Materialize( void ) -{ - if ( IsEffectActive( EF_NODRAW ) ) - { - // changing from invisible state to visible. -#ifdef HL2MP - EmitSound( "AlyxEmp.Charge" ); -#else - EmitSound( "BaseCombatWeapon.WeaponMaterialize" ); -#endif - - RemoveEffects( EF_NODRAW ); - DoMuzzleFlash(); - } -#ifdef HL2MP - if ( HasSpawnFlags( SF_NORESPAWN ) == false ) - { - VPhysicsInitNormal( SOLID_BBOX, GetSolidFlags() | FSOLID_TRIGGER, false ); - SetMoveType( MOVETYPE_VPHYSICS ); - - HL2MPRules()->AddLevelDesignerPlacedObject( this ); - } -#else - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_TRIGGER ); -#endif - - SetPickupTouch(); - - SetThink (NULL); -} - -//----------------------------------------------------------------------------- -// Purpose: See if the game rules will let this weapon respawn -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::AttemptToMaterialize( void ) -{ - float time = g_pGameRules->FlWeaponTryRespawn( this ); - - if ( time == 0 ) - { - Materialize(); - return; - } - - SetNextThink( gpGlobals->curtime + time ); -} - -//----------------------------------------------------------------------------- -// Purpose: Weapon has been picked up, should it respawn? -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::CheckRespawn( void ) -{ - switch ( g_pGameRules->WeaponShouldRespawn( this ) ) - { - case GR_WEAPON_RESPAWN_YES: - Respawn(); - break; - case GR_WEAPON_RESPAWN_NO: - return; - break; - } -} - -class CWeaponList : public CAutoGameSystem -{ -public: - CWeaponList( char const *name ) : CAutoGameSystem( name ) - { - } - - - virtual void LevelShutdownPostEntity() - { - m_list.Purge(); - } - - void AddWeapon( CBaseCombatWeapon *pWeapon ) - { - m_list.AddToTail( pWeapon ); - } - - void RemoveWeapon( CBaseCombatWeapon *pWeapon ) - { - m_list.FindAndRemove( pWeapon ); - } - CUtlLinkedList< CBaseCombatWeapon * > m_list; -}; - -CWeaponList g_WeaponList( "CWeaponList" ); - -void OnBaseCombatWeaponCreated( CBaseCombatWeapon *pWeapon ) -{ - g_WeaponList.AddWeapon( pWeapon ); -} - -void OnBaseCombatWeaponDestroyed( CBaseCombatWeapon *pWeapon ) -{ - g_WeaponList.RemoveWeapon( pWeapon ); -} - -int CBaseCombatWeapon::GetAvailableWeaponsInBox( CBaseCombatWeapon **pList, int listMax, const Vector &mins, const Vector &maxs ) -{ - // linear search all weapons - int count = 0; - int index = g_WeaponList.m_list.Head(); - while ( index != g_WeaponList.m_list.InvalidIndex() ) - { - CBaseCombatWeapon *pWeapon = g_WeaponList.m_list[index]; - // skip any held weapon - if ( !pWeapon->GetOwner() ) - { - // restrict to mins/maxs - if ( IsPointInBox( pWeapon->GetAbsOrigin(), mins, maxs ) ) - { - if ( count < listMax ) - { - pList[count] = pWeapon; - count++; - } - } - } - index = g_WeaponList.m_list.Next( index ); - } - - return count; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBaseCombatWeapon::ObjectCaps( void ) -{ - int caps = BaseClass::ObjectCaps(); - if ( !IsFollowingEntity() && !HasSpawnFlags(SF_WEAPON_NO_PLAYER_PICKUP) ) - { - caps |= FCAP_IMPULSE_USE; - } - - return caps; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - CBasePlayer *pPlayer = ToBasePlayer( pActivator ); - - if ( pPlayer ) - { - m_OnPlayerUse.FireOutput( pActivator, pCaller ); - - // - // Bump the weapon to try equipping it before picking it up physically. This is - // important in a few spots in the game where the player could potentially +use pickup - // and then THROW AWAY a vital weapon, rendering them unable to continue the game. - // - if ( pPlayer->BumpWeapon( this ) ) - { - OnPickedUp( pPlayer ); - } - else - { - pPlayer->PickupObject( this ); - } - } -} - diff --git a/game/server/basecombatweapon.h b/game/server/basecombatweapon.h deleted file mode 100644 index c0273b5f0..000000000 --- a/game/server/basecombatweapon.h +++ /dev/null @@ -1,30 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef COMBATWEAPON_H -#define COMBATWEAPON_H -#ifdef _WIN32 -#pragma once -#endif - -#include "entityoutput.h" -#include "basecombatweapon_shared.h" - -//----------------------------------------------------------------------------- -// Bullet types -//----------------------------------------------------------------------------- - -// ----------------------------------------- -// Sounds -// ----------------------------------------- - -struct animevent_t; - -extern void SpawnBlood(Vector vecSpot, const Vector &vecDir, int bloodColor, float flDamage); - -#endif // COMBATWEAPON_H diff --git a/game/server/baseentity.cpp b/game/server/baseentity.cpp deleted file mode 100644 index 7e684a464..000000000 --- a/game/server/baseentity.cpp +++ /dev/null @@ -1,7148 +0,0 @@ -//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: The base class from which all game entities are derived. -// -//===========================================================================// - -#include "cbase.h" -#include "globalstate.h" -#include "isaverestore.h" -#include "client.h" -#include "decals.h" -#include "gamerules.h" -#include "entityapi.h" -#include "entitylist.h" -#include "eventqueue.h" -#include "hierarchy.h" -#include "basecombatweapon.h" -#include "const.h" -#include "player.h" // For debug draw sending -#include "ndebugoverlay.h" -#include "physics.h" -#include "model_types.h" -#include "team.h" -#include "sendproxy.h" -#include "IEffects.h" -#include "vstdlib/random.h" -#include "baseentity.h" -#include "collisionutils.h" -#include "coordsize.h" -#include "animation.h" -#include "tier1/strtools.h" -#include "engine/IEngineSound.h" -#include "physics_saverestore.h" -#include "saverestore_utlvector.h" -#include "bone_setup.h" -#include "vcollide_parse.h" -#include "filters.h" -#include "te_effect_dispatch.h" -#include "AI_Criteria.h" -#include "AI_ResponseSystem.h" -#include "world.h" -#include "globals.h" -#include "saverestoretypes.h" -#include "SkyCamera.h" -#include "sceneentity.h" -#include "game.h" -#include "tier0/vprof.h" -#include "ai_basenpc.h" -#include "iservervehicle.h" -#include "eventlist.h" -#include "scriptevent.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" -#include "UtlCachedFileData.h" -#include "utlbuffer.h" -#include "positionwatcher.h" -#include "movetype_push.h" -#include "tier0/icommandline.h" -#include "vphysics/friction.h" -#include -#include "datacache/imdlcache.h" -#include "ModelSoundsCache.h" -#include "env_debughistory.h" -#include "tier1/utlstring.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern bool g_bTestMoveTypeStepSimulation; -extern ConVar sv_vehicle_autoaim_scale; - -// Init static class variables -bool CBaseEntity::m_bInDebugSelect = false; // Used for selection in debug overlays -int CBaseEntity::m_nDebugPlayer = -1; // Player doing the selection - -// This can be set before creating an entity to force it to use a particular edict. -edict_t *g_pForceAttachEdict = NULL; - -bool CBaseEntity::m_bDebugPause = false; // Whether entity i/o is paused. -int CBaseEntity::m_nDebugSteps = 1; // Number of entity outputs to fire before pausing again. -bool CBaseEntity::sm_bDisableTouchFuncs = false; // Disables PhysicsTouch and PhysicsStartTouch function calls -bool CBaseEntity::sm_bAccurateTriggerBboxChecks = true; // set to false for legacy behavior in ep1 - -int CBaseEntity::m_nPredictionRandomSeed = -1; -CBasePlayer *CBaseEntity::m_pPredictionPlayer = NULL; - -// Used to make sure nobody calls UpdateTransmitState directly. -int g_nInsideDispatchUpdateTransmitState = 0; - -// When this is false, throw an assert in debug when GetAbsAnything is called. Used when hierachy is incomplete/invalid. -bool CBaseEntity::s_bAbsQueriesValid = true; - - -ConVar sv_netvisdist( "sv_netvisdist", "10000", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "Test networking visibility distance" ); - -// This table encodes edict data. -void SendProxy_AnimTime( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID ) -{ - CBaseEntity *pEntity = (CBaseEntity *)pStruct; - -#if defined( _DEBUG ) - CBaseAnimating *pAnimating = pEntity->GetBaseAnimating(); - Assert( pAnimating ); - - if ( pAnimating ) - { - Assert( !pAnimating->IsUsingClientSideAnimation() ); - } -#endif - - int ticknumber = TIME_TO_TICKS( pEntity->m_flAnimTime ); - // Tickbase is current tick rounded down to closes 100 ticks - int tickbase = gpGlobals->GetNetworkBase( gpGlobals->tickcount, pEntity->entindex() ); - int addt = 0; - // If it's within the last tick interval through the current one, then we can encode it - if ( ticknumber >= ( tickbase - 100 ) ) - { - addt = ( ticknumber - tickbase ) & 0xFF; - } - - pOut->m_Int = addt; -} - -// This table encodes edict data. -void SendProxy_SimulationTime( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID ) -{ - CBaseEntity *pEntity = (CBaseEntity *)pStruct; - - int ticknumber = TIME_TO_TICKS( pEntity->m_flSimulationTime ); - // tickbase is current tick rounded down to closest 100 ticks - int tickbase = gpGlobals->GetNetworkBase( gpGlobals->tickcount, pEntity->entindex() ); - int addt = 0; - if ( ticknumber >= tickbase ) - { - addt = ( ticknumber - tickbase ) & 0xff; - } - - pOut->m_Int = addt; -} - -void* SendProxy_ClientSideAnimation( const SendProp *pProp, const void *pStruct, const void *pVarData, CSendProxyRecipients *pRecipients, int objectID ) -{ - CBaseEntity *pEntity = (CBaseEntity *)pStruct; - CBaseAnimating *pAnimating = pEntity->GetBaseAnimating(); - - if ( pAnimating && !pAnimating->IsUsingClientSideAnimation() ) - return (void*)pVarData; - else - return NULL; // Don't send animtime unless the client needs it. -} -REGISTER_SEND_PROXY_NON_MODIFIED_POINTER( SendProxy_ClientSideAnimation ); - - -BEGIN_SEND_TABLE_NOBASE( CBaseEntity, DT_AnimTimeMustBeFirst ) - // NOTE: Animtime must be sent before origin and angles ( from pev ) because it has a - // proxy on the client that stores off the old values before writing in the new values and - // if it is sent after the new values, then it will only have the new origin and studio model, etc. - // interpolation will be busted - SendPropInt (SENDINFO(m_flAnimTime), 8, SPROP_UNSIGNED|SPROP_CHANGES_OFTEN|SPROP_ENCODED_AGAINST_TICKCOUNT, SendProxy_AnimTime), -END_SEND_TABLE() - -#if !defined( NO_ENTITY_PREDICTION ) -BEGIN_SEND_TABLE_NOBASE( CBaseEntity, DT_PredictableId ) - SendPropPredictableId( SENDINFO( m_PredictableID ) ), - SendPropInt( SENDINFO( m_bIsPlayerSimulated ), 1, SPROP_UNSIGNED ), -END_SEND_TABLE() - - -static void* SendProxy_SendPredictableId( const SendProp *pProp, const void *pStruct, const void *pVarData, CSendProxyRecipients *pRecipients, int objectID ) -{ - CBaseEntity *pEntity = (CBaseEntity *)pStruct; - if ( !pEntity || !pEntity->m_PredictableID->IsActive() ) - return NULL; - - int id_player_index = pEntity->m_PredictableID->GetPlayer(); - pRecipients->SetOnly( id_player_index ); - - return ( void * )pVarData; -} -REGISTER_SEND_PROXY_NON_MODIFIED_POINTER( SendProxy_SendPredictableId ); -#endif - -void SendProxy_Origin( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ) -{ - CBaseEntity *entity = (CBaseEntity*)pStruct; - Assert( entity ); - - const Vector *v = &entity->GetLocalOrigin(); - - if ( g_bTestMoveTypeStepSimulation && - entity && - ( entity->GetMoveType() == MOVETYPE_STEP ) && - entity->HasDataObjectType( STEPSIMULATION ) ) - { - StepSimulationData *step = ( StepSimulationData * )entity->GetDataObject( STEPSIMULATION ); - if ( entity->ComputeStepSimulationNetworkOrigin( step ) ) - { - v = &step->m_vecNetworkOrigin; - } - } - - pOut->m_Vector[ 0 ] = v->x; - pOut->m_Vector[ 1 ] = v->y; - pOut->m_Vector[ 2 ] = v->z; -} - -void SendProxy_Angles( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ) -{ - CBaseEntity *entity = (CBaseEntity*)pStruct; - Assert( entity ); - - const QAngle *a = &entity->GetLocalAngles(); - - if ( g_bTestMoveTypeStepSimulation && - entity && - ( entity->GetMoveType() == MOVETYPE_STEP ) && - entity->HasDataObjectType( STEPSIMULATION ) ) - { - StepSimulationData *step = ( StepSimulationData * )entity->GetDataObject( STEPSIMULATION ); - if ( entity->ComputeStepSimulationNetworkAngles( step ) ) - { - a = &step->m_angNetworkAngles; - } - } - - pOut->m_Vector[ 0 ] = anglemod( a->x ); - pOut->m_Vector[ 1 ] = anglemod( a->y ); - pOut->m_Vector[ 2 ] = anglemod( a->z ); -} - -// This table encodes the CBaseEntity data. -IMPLEMENT_SERVERCLASS_ST_NOBASE( CBaseEntity, DT_BaseEntity ) - SendPropDataTable( "AnimTimeMustBeFirst", 0, &REFERENCE_SEND_TABLE(DT_AnimTimeMustBeFirst), SendProxy_ClientSideAnimation ), - SendPropInt (SENDINFO(m_flSimulationTime), SIMULATION_TIME_WINDOW_BITS, SPROP_UNSIGNED|SPROP_CHANGES_OFTEN|SPROP_ENCODED_AGAINST_TICKCOUNT, SendProxy_SimulationTime), - -#if PREDICTION_ERROR_CHECK_LEVEL > 1 - SendPropVector (SENDINFO(m_vecOrigin), -1, SPROP_NOSCALE|SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_Origin ), -#else - SendPropVector (SENDINFO(m_vecOrigin), -1, SPROP_COORD|SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_Origin ), -#endif - - SendPropModelIndex(SENDINFO(m_nModelIndex)), - SendPropDataTable( SENDINFO_DT( m_Collision ), &REFERENCE_SEND_TABLE(DT_CollisionProperty) ), - SendPropInt (SENDINFO(m_nRenderFX), 8, SPROP_UNSIGNED ), - SendPropInt (SENDINFO(m_nRenderMode), 8, SPROP_UNSIGNED ), - SendPropInt (SENDINFO(m_fEffects), EF_MAX_BITS, SPROP_UNSIGNED), - SendPropInt (SENDINFO(m_clrRender), 32, SPROP_UNSIGNED), - SendPropInt (SENDINFO(m_iTeamNum), TEAMNUM_NUM_BITS, 0), - SendPropInt (SENDINFO(m_CollisionGroup), 5, SPROP_UNSIGNED), - SendPropFloat (SENDINFO(m_flElasticity), 0, SPROP_COORD), - SendPropFloat (SENDINFO(m_flShadowCastDistance), 12, SPROP_UNSIGNED ), - SendPropEHandle (SENDINFO(m_hOwnerEntity)), - SendPropEHandle (SENDINFO(m_hEffectEntity)), - SendPropEHandle (SENDINFO_NAME(m_hMoveParent, moveparent)), - SendPropInt (SENDINFO(m_iParentAttachment), NUM_PARENTATTACHMENT_BITS, SPROP_UNSIGNED), - - SendPropInt (SENDINFO_NAME( m_MoveType, movetype ), MOVETYPE_MAX_BITS, SPROP_UNSIGNED ), - SendPropInt (SENDINFO_NAME( m_MoveCollide, movecollide ), MOVECOLLIDE_MAX_BITS, SPROP_UNSIGNED ), -#if PREDICTION_ERROR_CHECK_LEVEL > 1 - SendPropVector (SENDINFO(m_angRotation), -1, SPROP_NOSCALE|SPROP_CHANGES_OFTEN, 0, HIGH_DEFAULT, SendProxy_Angles ), -#else - SendPropQAngles (SENDINFO(m_angRotation), 13, SPROP_CHANGES_OFTEN, SendProxy_Angles ), -#endif - - SendPropInt ( SENDINFO( m_iTextureFrameIndex ), 8, SPROP_UNSIGNED ), - -#if !defined( NO_ENTITY_PREDICTION ) - SendPropDataTable( "predictable_id", 0, &REFERENCE_SEND_TABLE( DT_PredictableId ), SendProxy_SendPredictableId ), -#endif - - // FIXME: Collapse into another flag field? - SendPropInt (SENDINFO(m_bSimulatedEveryTick), 1, SPROP_UNSIGNED ), - SendPropInt (SENDINFO(m_bAnimatedEveryTick), 1, SPROP_UNSIGNED ), - SendPropBool( SENDINFO( m_bAlternateSorting )), - -END_SEND_TABLE() - - - -CBaseEntity::CBaseEntity( bool bServerOnly ) -{ - COMPILE_TIME_ASSERT( MOVETYPE_LAST < (1 << MOVETYPE_MAX_BITS) ); - COMPILE_TIME_ASSERT( MOVECOLLIDE_COUNT < (1 << MOVECOLLIDE_MAX_BITS) ); - -#ifdef _DEBUG - // necessary since in debug, we initialize vectors to NAN for debugging - m_vecAngVelocity.Init(); -// m_vecAbsAngVelocity.Init(); - m_vecViewOffset.Init(); - m_vecBaseVelocity.GetForModify().Init(); - m_vecVelocity.Init(); - m_vecAbsVelocity.Init(); -#endif - - m_bAlternateSorting = false; - m_CollisionGroup = COLLISION_GROUP_NONE; - m_iParentAttachment = 0; - CollisionProp()->Init( this ); - NetworkProp()->Init( this ); - - // NOTE: THIS MUST APPEAR BEFORE ANY SetMoveType() or SetNextThink() calls - AddEFlags( EFL_NO_THINK_FUNCTION | EFL_NO_GAME_PHYSICS_SIMULATION | EFL_USE_PARTITION_WHEN_NOT_SOLID ); - - // clear debug overlays - m_debugOverlays = 0; - m_pTimedOverlay = NULL; - m_pPhysicsObject = NULL; - m_flElasticity = 1.0f; - m_flShadowCastDistance = m_flDesiredShadowCastDistance = 0; - SetRenderColor( 255, 255, 255, 255 ); - m_iTeamNum = m_iInitialTeamNum = TEAM_UNASSIGNED; - m_nLastThinkTick = gpGlobals->tickcount; - m_nSimulationTick = -1; - SetIdentityMatrix( m_rgflCoordinateFrame ); - m_pBlocker = NULL; -#if _DEBUG - m_iCurrentThinkContext = NO_THINK_CONTEXT; -#endif - m_nWaterTouch = m_nSlimeTouch = 0; - - SetSolid( SOLID_NONE ); - ClearSolidFlags(); - - SetMoveType( MOVETYPE_NONE ); - SetOwnerEntity( NULL ); - SetCheckUntouch( false ); - SetModelIndex( 0 ); - SetModelName( NULL_STRING ); - m_nTransmitStateOwnedCounter = 0; - - SetCollisionBounds( vec3_origin, vec3_origin ); - ClearFlags(); - - SetFriction( 1.0f ); - - if ( bServerOnly ) - { - AddEFlags( EFL_SERVER_ONLY ); - } - NetworkProp()->MarkPVSInformationDirty(); - -#ifndef _XBOX - AddEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID ); -#endif -} - -extern bool g_bDisableEhandleAccess; - -//----------------------------------------------------------------------------- -// Purpose: See note below -//----------------------------------------------------------------------------- -CBaseEntity::~CBaseEntity( ) -{ - // FIXME: This can't be called from UpdateOnRemove! There's at least one - // case where friction sounds are added between the call to UpdateOnRemove + ~CBaseEntity - PhysCleanupFrictionSounds( this ); - - // In debug make sure that we don't call delete on an entity without setting - // the disable flag first! - // EHANDLE accessors will check, in debug, for access to entities during destruction of - // another entity. - // That kind of operation should only occur in UpdateOnRemove calls - // Deletion should only occur via UTIL_Remove(Immediate) calls, not via naked delete calls - Assert( g_bDisableEhandleAccess ); - - VPhysicsDestroyObject(); - - // Need to remove references to this entity before EHANDLES go null - { - g_bDisableEhandleAccess = false; - CBaseEntity::PhysicsRemoveTouchedList( this ); - CBaseEntity::PhysicsRemoveGroundList( this ); - DestroyAllDataObjects(); - g_bDisableEhandleAccess = true; - - // Remove this entity from the ent list (NOTE: This Makes EHANDLES go NULL) - gEntList.RemoveEntity( GetRefEHandle() ); - } -} - -void CBaseEntity::PostConstructor( const char *szClassname ) -{ - if ( szClassname ) - { - SetClassname(szClassname); - } - - Assert( m_iClassname != NULL_STRING && STRING(m_iClassname) != NULL ); - - // Possibly get an edict, and add self to global list of entites. - if ( IsEFlagSet( EFL_SERVER_ONLY ) ) - { - gEntList.AddNonNetworkableEntity( this ); - } - else - { - // Certain entities set up their edicts in the constructor - if ( !IsEFlagSet( EFL_NO_AUTO_EDICT_ATTACH ) ) - { - NetworkProp()->AttachEdict( g_pForceAttachEdict ); - g_pForceAttachEdict = NULL; - } - - // Some ents like the player override the AttachEdict function and do it at a different time. - // While precaching, they don't ever have an edict, so we don't need to add them to - // the entity list in that case. - if ( edict() ) - { - gEntList.AddNetworkableEntity( this, entindex() ); - - // Cache our IServerNetworkable pointer for the engine for fast access. - if ( edict() ) - edict()->m_pNetworkable = NetworkProp(); - } - } - - CheckHasThinkFunction( false ); - CheckHasGamePhysicsSimulation(); -} - -//----------------------------------------------------------------------------- -// Purpose: Called after player becomes active in the game -//----------------------------------------------------------------------------- -void CBaseEntity::PostClientActive( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: Verifies that this entity's data description is valid in debug builds. -//----------------------------------------------------------------------------- -#ifdef _DEBUG -typedef CUtlVector< const char * > KeyValueNameList_t; - -static void AddDataMapFieldNamesToList( KeyValueNameList_t &list, datamap_t *pDataMap ) -{ - while (pDataMap != NULL) - { - for (int i = 0; i < pDataMap->dataNumFields; i++) - { - typedescription_t *pField = &pDataMap->dataDesc[i]; - - if (pField->fieldType == FIELD_EMBEDDED) - { - AddDataMapFieldNamesToList( list, pField->td ); - continue; - } - - if (pField->flags & FTYPEDESC_KEY) - { - list.AddToTail( pField->externalName ); - } - } - - pDataMap = pDataMap->baseMap; - } -} - -void CBaseEntity::ValidateDataDescription(void) -{ - // Multiple key fields that have the same name are not allowed - it creates an - // ambiguity when trying to parse keyvalues and outputs. - datamap_t *pDataMap = GetDataDescMap(); - if ((pDataMap == NULL) || pDataMap->bValidityChecked) - return; - - pDataMap->bValidityChecked = true; - - // Let's generate a list of all keyvalue strings in the entire hierarchy... - KeyValueNameList_t names(128); - AddDataMapFieldNamesToList( names, pDataMap ); - - for (int i = names.Count(); --i > 0; ) - { - for (int j = i - 1; --j >= 0; ) - { - if (!Q_stricmp(names[i], names[j])) - { - DevMsg( "%s has multiple data description entries for \"%s\"\n", STRING(m_iClassname), names[i]); - break; - } - } - } -} -#endif // _DEBUG - - - -//----------------------------------------------------------------------------- -// Sets the collision bounds + the size -//----------------------------------------------------------------------------- -void CBaseEntity::SetCollisionBounds( const Vector& mins, const Vector &maxs ) -{ - m_Collision.SetCollisionBounds( mins, maxs ); -} - - -void CBaseEntity::StopFollowingEntity( ) -{ - if( !IsFollowingEntity() ) - { - Assert( IsEffectActive( EF_BONEMERGE ) == 0 ); - return; - } - - SetParent( NULL ); - RemoveEffects( EF_BONEMERGE ); - RemoveSolidFlags( FSOLID_NOT_SOLID ); - SetMoveType( MOVETYPE_NONE ); - CollisionRulesChanged(); -} - -bool CBaseEntity::IsFollowingEntity() -{ - return IsEffectActive( EF_BONEMERGE ) && (GetMoveType() == MOVETYPE_NONE) && GetMoveParent(); -} - -CBaseEntity *CBaseEntity::GetFollowedEntity() -{ - if (!IsFollowingEntity()) - return NULL; - return GetMoveParent(); -} - -void CBaseEntity::SetClassname( const char *className ) -{ - m_iClassname = AllocPooledString( className ); -} - -// position to shoot at -Vector CBaseEntity::BodyTarget( const Vector &posSrc, bool bNoisy) -{ - return WorldSpaceCenter( ); -} - -// return the position of my head. someone's trying to attack it. -Vector CBaseEntity::HeadTarget( const Vector &posSrc ) -{ - return EyePosition(); -} - -void CBaseEntity::SetViewOffset( const Vector &vecOffset ) -{ - m_vecViewOffset = vecOffset; -} - - - -struct TimedOverlay_t -{ - char *msg; - int msgEndTime; - int msgStartTime; - TimedOverlay_t *pNextTimedOverlay; -}; - -//----------------------------------------------------------------------------- -// Purpose: Display an error message on the entity -// Input : -// Output : -//----------------------------------------------------------------------------- -void CBaseEntity::AddTimedOverlay( const char *msg, int endTime ) -{ - TimedOverlay_t *pNewTO = new TimedOverlay_t; - int len = strlen(msg); - pNewTO->msg = new char[len + 1]; - Q_strncpy(pNewTO->msg,msg, len+1); - pNewTO->msgEndTime = (int)gpGlobals->curtime + endTime; - pNewTO->msgStartTime = (int)gpGlobals->curtime; - pNewTO->pNextTimedOverlay = m_pTimedOverlay; - m_pTimedOverlay = pNewTO; -} - -//----------------------------------------------------------------------------- -// Purpose: Send debug overlay box to the client -// Input : -// Output : -//----------------------------------------------------------------------------- -void CBaseEntity::DrawBBoxOverlay( float flDuration ) -{ - if (edict()) - { - NDebugOverlay::EntityBounds(this, 255, 100, 0, 0, flDuration ); - - if ( CollisionProp()->IsSolidFlagSet( FSOLID_USE_TRIGGER_BOUNDS ) ) - { - Vector vecTriggerMins, vecTriggerMaxs; - CollisionProp()->WorldSpaceTriggerBounds( &vecTriggerMins, &vecTriggerMaxs ); - Vector center = 0.5f * (vecTriggerMins + vecTriggerMaxs); - Vector extents = vecTriggerMaxs - center; - NDebugOverlay::Box(center, -extents, extents, 0, 255, 255, 0, flDuration ); - } - } -} - - -void CBaseEntity::DrawAbsBoxOverlay() -{ - int red = 0; - int green = 200; - - if ( VPhysicsGetObject() && VPhysicsGetObject()->IsAsleep() ) - { - red = 90; - green = 120; - } - - if (edict()) - { - // Surrounding boxes are axially aligned, so ignore angles - Vector vecSurroundMins, vecSurroundMaxs; - CollisionProp()->WorldSpaceSurroundingBounds( &vecSurroundMins, &vecSurroundMaxs ); - Vector center = 0.5f * (vecSurroundMins + vecSurroundMaxs); - Vector extents = vecSurroundMaxs - center; - NDebugOverlay::Box(center, -extents, extents, red, green, 0, 0 ,0); - } -} - -void CBaseEntity::DrawRBoxOverlay() -{ - -} - -//----------------------------------------------------------------------------- -// Purpose: Draws an axis overlay at the origin and angles of the entity -//----------------------------------------------------------------------------- -void CBaseEntity::SendDebugPivotOverlay( void ) -{ - if ( edict() ) - { - NDebugOverlay::Axis( GetAbsOrigin(), GetAbsAngles(), 20, true, 0 ); - } -} - -//------------------------------------------------------------------------------ -// Purpose : Add new entity positioned overlay text -// Input : How many lines to offset text from origin -// The text to print -// How long to display text -// The color of the text -// Output : -//------------------------------------------------------------------------------ -void CBaseEntity::EntityText( int text_offset, const char *text, float duration, int r, int g, int b, int a ) -{ - Vector origin; - Vector vecLocalCenter; - - VectorAdd( m_Collision.OBBMins(), m_Collision.OBBMaxs(), vecLocalCenter ); - vecLocalCenter *= 0.5f; - - if ( ( m_Collision.GetCollisionAngles() == vec3_angle ) || ( vecLocalCenter == vec3_origin ) ) - { - VectorAdd( vecLocalCenter, m_Collision.GetCollisionOrigin(), origin ); - } - else - { - VectorTransform( vecLocalCenter, m_Collision.CollisionToWorldTransform(), origin ); - } - - NDebugOverlay::EntityTextAtPosition( origin, text_offset, text, duration, r, g, b, a ); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBaseEntity::DrawTimedOverlays(void) -{ - // Draw name first if I have an overlay or am in message mode - if ((m_debugOverlays & OVERLAY_MESSAGE_BIT)) - { - char tempstr[512]; - Q_snprintf( tempstr, sizeof( tempstr ), "[%s]", GetDebugName() ); - EntityText(0,tempstr, 0); - } - - // Now draw overlays - TimedOverlay_t* pTO = m_pTimedOverlay; - TimedOverlay_t* pNextTO = NULL; - TimedOverlay_t* pLastTO = NULL; - int nCount = 1; // Offset by one - while (pTO) - { - pNextTO = pTO->pNextTimedOverlay; - - // Remove old messages unless messages are paused - if ((!CBaseEntity::Debug_IsPaused() && gpGlobals->curtime > pTO->msgEndTime) || - (nCount > 10)) - { - if (pLastTO) - { - pLastTO->pNextTimedOverlay = pNextTO; - } - else - { - m_pTimedOverlay = pNextTO; - } - - delete pTO->msg; - delete pTO; - } - else - { - int nAlpha = 0; - - // If messages aren't paused fade out - if (!CBaseEntity::Debug_IsPaused()) - { - nAlpha = (int)(255*((gpGlobals->curtime - pTO->msgStartTime)/(pTO->msgEndTime - pTO->msgStartTime))); - } - int r = 185; - int g = 145; - int b = 145; - - // Brighter when new message - if (nAlpha < 50) - { - r = 255; - g = 205; - b = 205; - } - if (nAlpha < 0) nAlpha = 0; - EntityText(nCount,pTO->msg, 0.0, r, g, b, 255-nAlpha); - nCount++; - - pLastTO = pTO; - } - pTO = pNextTO; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draw all overlays (should be implemented by subclass to add -// any additional non-text overlays) -// Input : -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -void CBaseEntity::DrawDebugGeometryOverlays(void) -{ - DrawTimedOverlays(); - DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_NAME_BIT) - { - EntityText(0,GetDebugName(), 0); - } - if (m_debugOverlays & OVERLAY_BBOX_BIT) - { - DrawBBoxOverlay(); - } - if (m_debugOverlays & OVERLAY_ABSBOX_BIT ) - { - DrawAbsBoxOverlay(); - } - if (m_debugOverlays & OVERLAY_PIVOT_BIT) - { - SendDebugPivotOverlay(); - } - if( m_debugOverlays & OVERLAY_RBOX_BIT ) - { - DrawRBoxOverlay(); - } - if ( m_debugOverlays & (OVERLAY_BBOX_BIT|OVERLAY_PIVOT_BIT) ) - { - // draw mass center - if ( VPhysicsGetObject() ) - { - Vector massCenter = VPhysicsGetObject()->GetMassCenterLocalSpace(); - Vector worldPos; - VPhysicsGetObject()->LocalToWorld( &worldPos, massCenter ); - NDebugOverlay::Cross3D( worldPos, 12, 255, 0, 0, false, 0 ); - DebugDrawContactPoints(VPhysicsGetObject()); - if ( GetMoveType() != MOVETYPE_VPHYSICS ) - { - Vector pos; - QAngle angles; - VPhysicsGetObject()->GetPosition( &pos, &angles ); - float dist = (pos - GetAbsOrigin()).Length(); - - Vector axis; - float deltaAngle; - RotationDeltaAxisAngle( angles, GetAbsAngles(), axis, deltaAngle ); - if ( dist > 2 || fabsf(deltaAngle) > 2 ) - { - Vector mins, maxs; - physcollision->CollideGetAABB( &mins, &maxs, VPhysicsGetObject()->GetCollide(), vec3_origin, vec3_angle ); - NDebugOverlay::BoxAngles( pos, mins, maxs, angles, 255, 255, 0, 16, 0 ); - } - } - } - } - if ( m_debugOverlays & OVERLAY_SHOW_BLOCKSLOS ) - { - if ( BlocksLOS() ) - { - NDebugOverlay::EntityBounds(this, 255, 255, 255, 0, 0 ); - } - } - if ( m_debugOverlays & OVERLAY_AUTOAIM_BIT && (GetFlags()&FL_AIMTARGET) && AI_GetSinglePlayer() != NULL ) - { - // Crude, but it gets the point across. - Vector vecCenter = GetAutoAimCenter(); - Vector vecRight, vecUp, vecDiag; - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - float radius = GetAutoAimRadius(); - - QAngle angles = pPlayer->EyeAngles(); - AngleVectors( angles, NULL, &vecRight, &vecUp ); - - int r,g,b; - - if( ((int)gpGlobals->curtime) % 2 == 1 ) - { - r = 255; - g = 255; - b = 255; - - if( pPlayer->GetActiveWeapon() != NULL ) - radius *= pPlayer->GetActiveWeapon()->WeaponAutoAimScale(); - - } - else - { - r = 255;g=0;b=0; - - if( !ShouldAttractAutoAim(pPlayer) ) - { - g = 255; - } - } - - if( pPlayer->IsInAVehicle() ) - { - radius *= sv_vehicle_autoaim_scale.GetFloat(); - } - - NDebugOverlay::Line( vecCenter, vecCenter + vecRight * radius, r, g, b, true, 0.1 ); - NDebugOverlay::Line( vecCenter, vecCenter - vecRight * radius, r, g, b, true, 0.1 ); - NDebugOverlay::Line( vecCenter, vecCenter + vecUp * radius, r, g, b, true, 0.1 ); - NDebugOverlay::Line( vecCenter, vecCenter - vecUp * radius, r, g, b, true, 0.1 ); - - vecDiag = vecRight + vecUp; - VectorNormalize( vecDiag ); - NDebugOverlay::Line( vecCenter - vecDiag * radius, vecCenter + vecDiag * radius, r, g, b, true, 0.1 ); - - vecDiag = vecRight - vecUp; - VectorNormalize( vecDiag ); - NDebugOverlay::Line( vecCenter - vecDiag * radius, vecCenter + vecDiag * radius, r, g, b, true, 0.1 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draw any text overlays (override in subclass to add additional text) -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CBaseEntity::DrawDebugTextOverlays(void) -{ - int offset = 1; - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - Q_snprintf( tempstr, sizeof(tempstr), "(%d) Name: %s (%s)", entindex(), GetDebugName(), GetClassname() ); - EntityText(offset,tempstr, 0); - offset++; - - if( m_iGlobalname != NULL_STRING ) - { - Q_snprintf( tempstr, sizeof(tempstr), "GLOBALNAME: %s", STRING(m_iGlobalname) ); - EntityText(offset,tempstr, 0); - offset++; - } - - Vector vecOrigin = GetAbsOrigin(); - Q_snprintf( tempstr, sizeof(tempstr), "Position: %0.1f, %0.1f, %0.1f\n", vecOrigin.x, vecOrigin.y, vecOrigin.z ); - EntityText( offset, tempstr, 0 ); - offset++; - - if( GetModelName() != NULL_STRING || GetBaseAnimating() ) - { - Q_snprintf(tempstr, sizeof(tempstr), "Model:%s", STRING(GetModelName()) ); - EntityText(offset,tempstr,0); - offset++; - } - - if( m_hDamageFilter.Get() != NULL ) - { - Q_snprintf( tempstr, sizeof(tempstr), "DAMAGE FILTER:%s", m_hDamageFilter->GetDebugName() ); - EntityText( offset,tempstr,0 ); - offset++; - } - } - - if (m_debugOverlays & OVERLAY_VIEWOFFSET) - { - NDebugOverlay::Cross3D( EyePosition(), 16, 255, 0, 0, true, 0.05f ); - } - - return offset; -} - - -void CBaseEntity::SetParent( string_t newParent, CBaseEntity *pActivator, int iAttachment ) -{ - // find and notify the new parent - CBaseEntity *pParent = gEntList.FindEntityByName( NULL, newParent, NULL, pActivator ); - - // debug check - if ( newParent != NULL_STRING && pParent == NULL ) - { - Msg( "Entity %s(%s) has bad parent %s\n", STRING(m_iClassname), GetDebugName(), STRING(newParent) ); - } - else - { - // make sure there isn't any ambiguity - if ( gEntList.FindEntityByName( pParent, newParent, NULL, pActivator ) ) - { - Msg( "Entity %s(%s) has ambigious parent %s\n", STRING(m_iClassname), GetDebugName(), STRING(newParent) ); - } - SetParent( pParent, iAttachment ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Move our points from parent to worldspace -// Input : *pParent - Parent to use as reference -//----------------------------------------------------------------------------- -void CBaseEntity::TransformStepData_ParentToWorld( CBaseEntity *pParent ) -{ - // Fix up our step simulation points to be in the proper local space - StepSimulationData *step = (StepSimulationData *) GetDataObject( STEPSIMULATION ); - if ( step != NULL ) - { - // Convert our positions - UTIL_ParentToWorldSpace( pParent, step->m_Previous2.vecOrigin, step->m_Previous2.qRotation ); - UTIL_ParentToWorldSpace( pParent, step->m_Previous.vecOrigin, step->m_Previous.qRotation ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Move step data between two parent-spaces -// Input : *pOldParent - parent we were attached to -// *pNewParent - parent we're now attached to -//----------------------------------------------------------------------------- -void CBaseEntity::TransformStepData_ParentToParent( CBaseEntity *pOldParent, CBaseEntity *pNewParent ) -{ - // Fix up our step simulation points to be in the proper local space - StepSimulationData *step = (StepSimulationData *) GetDataObject( STEPSIMULATION ); - if ( step != NULL ) - { - // Convert our positions - UTIL_ParentToWorldSpace( pOldParent, step->m_Previous2.vecOrigin, step->m_Previous2.qRotation ); - UTIL_WorldToParentSpace( pNewParent, step->m_Previous2.vecOrigin, step->m_Previous2.qRotation ); - - UTIL_ParentToWorldSpace( pOldParent, step->m_Previous.vecOrigin, step->m_Previous.qRotation ); - UTIL_WorldToParentSpace( pNewParent, step->m_Previous.vecOrigin, step->m_Previous.qRotation ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: After parenting to an object, we need to also correctly translate our -// step stimulation positions and angles into that parent space. Otherwise -// we end up splining between two different world spaces. -//----------------------------------------------------------------------------- -void CBaseEntity::TransformStepData_WorldToParent( CBaseEntity *pParent ) -{ - // Fix up our step simulation points to be in the proper local space - StepSimulationData *step = (StepSimulationData *) GetDataObject( STEPSIMULATION ); - if ( step != NULL ) - { - // Convert our positions - UTIL_WorldToParentSpace( pParent, step->m_Previous2.vecOrigin, step->m_Previous2.qRotation ); - UTIL_WorldToParentSpace( pParent, step->m_Previous.vecOrigin, step->m_Previous.qRotation ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Sets the movement parent of this entity. This entity will be moved -// to a local coordinate calculated from its current absolute offset -// from the parent entity and will then follow the parent entity. -// Input : pParentEntity - This entity's new parent in the movement hierarchy. -//----------------------------------------------------------------------------- -void CBaseEntity::SetParent( CBaseEntity *pParentEntity, int iAttachment ) -{ - // If they didn't specify an attachment, use our current - if ( iAttachment == -1 ) - { - iAttachment = m_iParentAttachment; - } - - bool bWasNotParented = ( GetParent() == NULL ); - CBaseEntity *pOldParent = m_pParent; - - // notify the old parent of the loss - UnlinkFromParent( this ); - - // set the new name - m_pParent = pParentEntity; - - if ( m_pParent == this ) - { - // should never set parent to 'this' - makes no sense - Assert(0); - m_pParent = NULL; - } - - if ( m_pParent == NULL ) - { - m_iParent = NULL_STRING; - - // Transform step data from parent to worldspace - TransformStepData_ParentToWorld( pOldParent ); - return; - } - - m_iParent = m_pParent->m_iName; - - RemoveSolidFlags( FSOLID_ROOT_PARENT_ALIGNED ); - if ( pParentEntity ) - { - if ( const_cast(pParentEntity)->GetRootMoveParent()->GetSolid() == SOLID_BSP ) - { - AddSolidFlags( FSOLID_ROOT_PARENT_ALIGNED ); - } - else - { - if ( GetSolid() == SOLID_BSP ) - { - // Must be SOLID_VPHYSICS because parent might rotate - SetSolid( SOLID_VPHYSICS ); - } - } - } - // set the move parent if we have one - if ( edict() ) - { - // add ourselves to the list - LinkChild( m_pParent, this ); - - m_iParentAttachment = (char)iAttachment; - - EntityMatrix matrix, childMatrix; - matrix.InitFromEntity( const_cast(pParentEntity), m_iParentAttachment ); // parent->world - childMatrix.InitFromEntityLocal( this ); // child->world - Vector localOrigin = matrix.WorldToLocal( GetLocalOrigin() ); - - // I have the axes of local space in world space. (childMatrix) - // I want to compute those world space axes in the parent's local space - // and set that transform (as angles) on the child's object so the net - // result is that the child is now in parent space, but still oriented the same way - VMatrix tmp = matrix.Transpose(); // world->parent - tmp.MatrixMul( childMatrix, matrix ); // child->parent - QAngle angles; - MatrixToAngles( matrix, angles ); - SetLocalAngles( angles ); - UTIL_SetOrigin( this, localOrigin ); - - // Move our step data into the correct space - if ( bWasNotParented ) - { - // Transform step data from world to parent-space - TransformStepData_WorldToParent( this ); - } - else - { - // Transform step data between parent-spaces - TransformStepData_ParentToParent( pOldParent, this ); - } - } - if ( VPhysicsGetObject() ) - { - if ( VPhysicsGetObject()->IsStatic()) - { - if ( VPhysicsGetObject()->IsAttachedToConstraint(false) ) - { - Warning("SetParent on static object, all constraints attached to %s (%s)will now be broken!\n", GetDebugName(), GetClassname() ); - } - VPhysicsDestroyObject(); - VPhysicsInitShadow(false, false); - } - } - CollisionRulesChanged(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseEntity::ValidateEntityConnections() -{ - if ( m_target == NULL_STRING ) - return; - - if ( ClassMatches( "scripted_*" ) || - ClassMatches( "trigger_relay" ) || - ClassMatches( "trigger_auto" ) || - ClassMatches( "path_*" ) || - ClassMatches( "monster_*" ) || - ClassMatches( "trigger_teleport" ) || - ClassMatches( "func_train" ) || - ClassMatches( "func_tracktrain" ) || - ClassMatches( "func_plat*" ) || - ClassMatches( "npc_*" ) || - ClassMatches( "info_big*" ) || - ClassMatches( "env_texturetoggle" ) || - ClassMatches( "env_render" ) || - ClassMatches( "func_areaportalwindow") || - ClassMatches( "point_view*") || - ClassMatches( "func_traincontrols" ) || - ClassMatches( "multisource" ) || - ClassMatches( "xen_plant*" ) ) - return; - - datamap_t *dmap = GetDataDescMap(); - while ( dmap ) - { - int fields = dmap->dataNumFields; - for ( int i = 0; i < fields; i++ ) - { - typedescription_t *dataDesc = &dmap->dataDesc[i]; - if ( ( dataDesc->fieldType == FIELD_CUSTOM ) && ( dataDesc->flags & FTYPEDESC_OUTPUT ) ) - { - CBaseEntityOutput *pOutput = (CBaseEntityOutput *)((int)this + (int)dataDesc->fieldOffset[0]); - if ( pOutput->NumberOfElements() ) - return; - } - } - - dmap = dmap->baseMap; - } - - Vector vecLoc = WorldSpaceCenter(); - Warning("---------------------------------\n"); - Warning( "Entity %s - (%s) has a target and NO OUTPUTS\n", GetDebugName(), GetClassname() ); - Warning( "Location %f %f %f\n", vecLoc.x, vecLoc.y, vecLoc.z ); - Warning("---------------------------------\n"); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseEntity::FireNamedOutput( const char *pszOutput, variant_t variant, CBaseEntity *pActivator, CBaseEntity *pCaller, float flDelay ) -{ - if ( pszOutput == NULL ) - return; - - datamap_t *dmap = GetDataDescMap(); - while ( dmap ) - { - int fields = dmap->dataNumFields; - for ( int i = 0; i < fields; i++ ) - { - typedescription_t *dataDesc = &dmap->dataDesc[i]; - if ( ( dataDesc->fieldType == FIELD_CUSTOM ) && ( dataDesc->flags & FTYPEDESC_OUTPUT ) ) - { - CBaseEntityOutput *pOutput = ( CBaseEntityOutput * )( ( int )this + ( int )dataDesc->fieldOffset[0] ); - if ( !Q_stricmp( dataDesc->externalName, pszOutput ) ) - { - pOutput->FireOutput( variant, pActivator, pCaller, flDelay ); - return; - } - } - } - - dmap = dmap->baseMap; - } -} - -void CBaseEntity::Activate( void ) -{ -#ifdef DEBUG - extern bool g_bCheckForChainedActivate; - extern bool g_bReceivedChainedActivate; - - if ( g_bCheckForChainedActivate && g_bReceivedChainedActivate ) - { - Assert( !"Multiple calls to base class Activate()\n" ); - } - g_bReceivedChainedActivate = true; -#endif - - // NOTE: This forces a team change so that stuff in the level - // that starts out on a team correctly changes team - if (m_iInitialTeamNum) - { - ChangeTeam( m_iInitialTeamNum ); - } - - // Get a handle to my damage filter entity if there is one. - if ( m_iszDamageFilterName != NULL_STRING ) - { - m_hDamageFilter = gEntList.FindEntityByName( NULL, m_iszDamageFilterName ); - } - - // Add any non-null context strings to our context vector - if ( m_iszResponseContext != NULL_STRING ) - { - AddContext( m_iszResponseContext.ToCStr() ); - } - -#ifdef HL1_DLL - ValidateEntityConnections(); -#endif //HL1_DLL -} - -//////////////////////////// old CBaseEntity stuff /////////////////////////////////// - - -// give health. -// Returns the amount of health actually taken. -int CBaseEntity::TakeHealth( float flHealth, int bitsDamageType ) -{ - if ( !edict() || m_takedamage < DAMAGE_YES ) - return 0; - -// heal - if ( m_iHealth >= m_iMaxHealth ) - return 0; - - const int oldHealth = m_iHealth; - - m_iHealth += flHealth; - - if (m_iHealth > m_iMaxHealth) - m_iHealth = m_iMaxHealth; - - return m_iHealth - oldHealth; -} - -// inflict damage on this entity. bitsDamageType indicates type of damage inflicted, ie: DMG_CRUSH - -int CBaseEntity::OnTakeDamage( const CTakeDamageInfo &info ) -{ - Vector vecTemp; - - if ( !edict() || !m_takedamage ) - return 0; - - if ( info.GetInflictor() ) - { - vecTemp = info.GetInflictor()->WorldSpaceCenter() - ( WorldSpaceCenter() ); - } - else - { - vecTemp.Init( 1, 0, 0 ); - } - - // this global is still used for glass and other non-NPC killables, along with decals. - g_vecAttackDir = vecTemp; - VectorNormalize(g_vecAttackDir); - - // save damage based on the target's armor level - - // figure momentum add (don't let hurt brushes or other triggers move player) - - // physics objects have their own calcs for this: (don't let fire move things around!) - if ( !IsEFlagSet( EFL_NO_DAMAGE_FORCES ) ) - { - if ( ( GetMoveType() == MOVETYPE_VPHYSICS ) ) - { - VPhysicsTakeDamage( info ); - } - else - { - if ( info.GetInflictor() && (GetMoveType() == MOVETYPE_WALK || GetMoveType() == MOVETYPE_STEP) && - !info.GetAttacker()->IsSolidFlagSet(FSOLID_TRIGGER) ) - { - Vector vecDir, vecInflictorCentroid; - vecDir = WorldSpaceCenter( ); - vecInflictorCentroid = info.GetInflictor()->WorldSpaceCenter( ); - vecDir -= vecInflictorCentroid; - VectorNormalize( vecDir ); - - float flForce = info.GetDamage() * ((32 * 32 * 72.0) / (WorldAlignSize().x * WorldAlignSize().y * WorldAlignSize().z)) * 5; - - if (flForce > 1000.0) - flForce = 1000.0; - ApplyAbsVelocityImpulse( vecDir * flForce ); - } - } - } - - if ( m_takedamage != DAMAGE_EVENTS_ONLY ) - { - // do the damage - m_iHealth -= info.GetDamage(); - if (m_iHealth <= 0) - { - Event_Killed( info ); - return 0; - } - } - - return 1; -} - -//----------------------------------------------------------------------------- -// Purpose: Scale damage done and call OnTakeDamage -//----------------------------------------------------------------------------- -void CBaseEntity::TakeDamage( const CTakeDamageInfo &inputInfo ) -{ - if ( !g_pGameRules ) - return; - - bool bHasPhysicsForceDamage = !g_pGameRules->Damage_NoPhysicsForce( inputInfo.GetDamageType() ); - if ( bHasPhysicsForceDamage && inputInfo.GetDamageType() != DMG_GENERIC ) - { - // If you hit this assert, you've called TakeDamage with a damage type that requires a physics damage - // force & position without specifying one or both of them. Decide whether your damage that's causing - // this is something you believe should impart physics force on the receiver. If it is, you need to - // setup the damage force & position inside the CTakeDamageInfo (Utility functions for this are in - // takedamageinfo.cpp. If you think the damage shouldn't cause force (unlikely!) then you can set the - // damage type to DMG_GENERIC, or | DMG_CRUSH if you need to preserve the damage type for purposes of HUD display. - - if ( inputInfo.GetDamageForce() == vec3_origin || inputInfo.GetDamagePosition() == vec3_origin ) - { - static int warningCount = 0; - if ( ++warningCount < 10 ) - { - if ( inputInfo.GetDamageForce() == vec3_origin ) - { - DevWarning( "CBaseEntity::TakeDamage: with inputInfo.GetDamageForce() == vec3_origin\n" ); - } - if ( inputInfo.GetDamagePosition() == vec3_origin ) - { - DevWarning( "CBaseEntity::TakeDamage: with inputInfo.GetDamagePosition() == vec3_origin\n" ); - } - } - } - } - - // Make sure our damage filter allows the damage. - if ( !PassesDamageFilter( inputInfo )) - { - return; - } - - if( !g_pGameRules->AllowDamage(this, inputInfo) ) - { - return; - } - - if ( PhysIsInCallback() ) - { - PhysCallbackDamage( this, inputInfo ); - } - else - { - CTakeDamageInfo info = inputInfo; - - // Scale the damage by the attacker's modifier. - if ( info.GetAttacker() ) - { - info.ScaleDamage( info.GetAttacker()->GetAttackDamageScale( this ) ); - } - - // Scale the damage by my own modifiers - info.ScaleDamage( GetReceivedDamageScale( info.GetAttacker() ) ); - - //Msg("%s took %.2f Damage, at %.2f\n", GetClassname(), info.GetDamage(), gpGlobals->curtime ); - - OnTakeDamage( info ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Returns a value that scales all damage done by this entity. -//----------------------------------------------------------------------------- -float CBaseEntity::GetAttackDamageScale( CBaseEntity *pVictim ) -{ - float flScale = 1; - FOR_EACH_LL( m_DamageModifiers, i ) - { - if ( !m_DamageModifiers[i]->IsDamageDoneToMe() ) - { - flScale *= m_DamageModifiers[i]->GetModifier(); - } - } - return flScale; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns a value that scales all damage done to this entity -//----------------------------------------------------------------------------- -float CBaseEntity::GetReceivedDamageScale( CBaseEntity *pAttacker ) -{ - float flScale = 1; - FOR_EACH_LL( m_DamageModifiers, i ) - { - if ( m_DamageModifiers[i]->IsDamageDoneToMe() ) - { - flScale *= m_DamageModifiers[i]->GetModifier(); - } - } - return flScale; -} - - -//----------------------------------------------------------------------------- -// Purpose: Applies forces to our physics object in response to damage. -//----------------------------------------------------------------------------- -int CBaseEntity::VPhysicsTakeDamage( const CTakeDamageInfo &info ) -{ - // don't let physics impacts or fire cause objects to move (again) - bool bNoPhysicsForceDamage = g_pGameRules->Damage_NoPhysicsForce( info.GetDamageType() ); - if ( bNoPhysicsForceDamage || info.GetDamageType() == DMG_GENERIC ) - return 1; - - Assert(VPhysicsGetObject() != NULL); - if ( VPhysicsGetObject() ) - { - Vector force = info.GetDamageForce(); - Vector offset = info.GetDamagePosition(); - - // If you hit this assert, you've called TakeDamage with a damage type that requires a physics damage - // force & position without specifying one or both of them. Decide whether your damage that's causing - // this is something you believe should impart physics force on the receiver. If it is, you need to - // setup the damage force & position inside the CTakeDamageInfo (Utility functions for this are in - // takedamageinfo.cpp. If you think the damage shouldn't cause force (unlikely!) then you can set the - // damage type to DMG_GENERIC, or | DMG_CRUSH if you need to preserve the damage type for purposes of HUD display. - Assert( force != vec3_origin && offset != vec3_origin ); - - unsigned short gameFlags = VPhysicsGetObject()->GetGameFlags(); - if ( gameFlags & FVPHYSICS_PLAYER_HELD ) - { - // if the player is holding the object, use it's real mass (player holding reduced the mass) - - CBasePlayer *pPlayer = NULL; - - if ( AI_IsSinglePlayer() ) - { - pPlayer = UTIL_GetLocalPlayer(); - } - else - { - // See which MP player is holding the physics object and then use that player to get the real mass of the object. - // This is ugly but better than having linkage between an object and its "holding" player. - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *tempPlayer = UTIL_PlayerByIndex( i ); - if ( tempPlayer && (tempPlayer->GetHeldObject() == this ) ) - { - pPlayer = tempPlayer; - break; - } - } - } - - if ( pPlayer ) - { - float mass = pPlayer->GetHeldObjectMass( VPhysicsGetObject() ); - if ( mass != 0.0f ) - { - float ratio = VPhysicsGetObject()->GetMass() / mass; - force *= ratio; - } - } - } - else if ( (gameFlags & FVPHYSICS_PART_OF_RAGDOLL) && (gameFlags & FVPHYSICS_CONSTRAINT_STATIC) ) - { - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int count = VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - for ( int i = 0; i < count; i++ ) - { - if ( !(pList[i]->GetGameFlags() & FVPHYSICS_CONSTRAINT_STATIC) ) - { - pList[i]->ApplyForceOffset( force, offset ); - return 1; - } - } - - } - VPhysicsGetObject()->ApplyForceOffset( force, offset ); - } - - return 1; -} - - // Character killed (only fired once) -void CBaseEntity::Event_Killed( const CTakeDamageInfo &info ) -{ - if( info.GetAttacker() ) - { - info.GetAttacker()->Event_KilledOther(this, info); - } - - m_takedamage = DAMAGE_NO; - m_lifeState = LIFE_DEAD; - UTIL_Remove( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: helper method to send a game event when this entity is killed. Note: -// gets called specifically for particular entities (mostly NPC), this -// does not get called for every entity -//----------------------------------------------------------------------------- -void CBaseEntity::SendOnKilledGameEvent( const CTakeDamageInfo &info ) -{ - IGameEvent *event = gameeventmanager->CreateEvent( "entity_killed" ); - if ( event ) - { - event->SetInt( "entindex_killed", entindex() ); - if ( info.GetAttacker()) - { - event->SetInt( "entindex_attacker", info.GetAttacker()->entindex() ); - } - if ( info.GetInflictor()) - { - event->SetInt( "entindex_inflictor", info.GetInflictor()->entindex() ); - } - event->SetInt( "damagebits", info.GetDamageType() ); - gameeventmanager->FireEvent( event ); - } -} - - -bool CBaseEntity::HasTarget( string_t targetname ) -{ - if( targetname != NULL_STRING && m_target != NULL_STRING ) - return FStrEq(STRING(targetname), STRING(m_target) ); - else - return false; -} - - -CBaseEntity *CBaseEntity::GetNextTarget( void ) -{ - if ( !m_target ) - return NULL; - return gEntList.FindEntityByName( NULL, m_target ); -} - -class CThinkContextsSaveDataOps : public CDefSaveRestoreOps -{ - virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave ) - { - AssertMsg( fieldInfo.pTypeDesc->fieldSize == 1, "CThinkContextsSaveDataOps does not support arrays"); - - // Write out the vector - CUtlVector< thinkfunc_t > *pUtlVector = (CUtlVector< thinkfunc_t > *)fieldInfo.pField; - SaveUtlVector( pSave, pUtlVector, FIELD_EMBEDDED ); - - // Get our owner - CBaseEntity *pOwner = (CBaseEntity*)fieldInfo.pOwner; - - pSave->StartBlock(); - // Now write out all the functions - for ( int i = 0; i < pUtlVector->Size(); i++ ) - { - void **ppV = (void**)&((*pUtlVector)[i].m_pfnThink); - bool bHasFunc = (*ppV != NULL); - pSave->WriteBool( &bHasFunc, 1 ); - if ( bHasFunc ) - { - pSave->WriteFunction( pOwner->GetDataDescMap(), "m_pfnThink", (int *)(char *)ppV, 1 ); - } - } - pSave->EndBlock(); - } - - virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore ) - { - AssertMsg( fieldInfo.pTypeDesc->fieldSize == 1, "CThinkContextsSaveDataOps does not support arrays"); - - // Read in the vector - CUtlVector< thinkfunc_t > *pUtlVector = (CUtlVector< thinkfunc_t > *)fieldInfo.pField; - RestoreUtlVector( pRestore, pUtlVector, FIELD_EMBEDDED ); - - // Get our owner - CBaseEntity *pOwner = (CBaseEntity*)fieldInfo.pOwner; - - pRestore->StartBlock(); - // Now read in all the functions - for ( int i = 0; i < pUtlVector->Size(); i++ ) - { - bool bHasFunc; - pRestore->ReadBool( &bHasFunc, 1 ); - void **ppV = (void**)&((*pUtlVector)[i].m_pfnThink); - if ( bHasFunc ) - { - SaveRestoreRecordHeader_t header; - pRestore->ReadHeader( &header ); - pRestore->ReadFunction( pOwner->GetDataDescMap(), ppV, 1, header.size ); - } - else - { - *ppV = NULL; - } - } - pRestore->EndBlock(); - } - - virtual bool IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - CUtlVector< thinkfunc_t > *pUtlVector = (CUtlVector< thinkfunc_t > *)fieldInfo.pField; - return ( pUtlVector->Count() == 0 ); - } - - virtual void MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - BASEPTR pFunc = *((BASEPTR*)fieldInfo.pField); - pFunc = NULL; - } -}; -CThinkContextsSaveDataOps g_ThinkContextsSaveDataOps; -ISaveRestoreOps *thinkcontextFuncs = &g_ThinkContextsSaveDataOps; - -BEGIN_SIMPLE_DATADESC( thinkfunc_t ) - - DEFINE_FIELD( m_iszContext, FIELD_STRING ), - // DEFINE_FIELD( m_pfnThink, FIELD_FUNCTION ), // Manually written - DEFINE_FIELD( m_nNextThinkTick, FIELD_TICK ), - DEFINE_FIELD( m_nLastThinkTick, FIELD_TICK ), - -END_DATADESC() - -BEGIN_SIMPLE_DATADESC( ResponseContext_t ) - - DEFINE_FIELD( m_iszName, FIELD_STRING ), - DEFINE_FIELD( m_iszValue, FIELD_STRING ), - DEFINE_FIELD( m_fExpirationTime, FIELD_TIME ), - -END_DATADESC() - -BEGIN_DATADESC_NO_BASE( CBaseEntity ) - - DEFINE_KEYFIELD( m_iClassname, FIELD_STRING, "classname" ), - DEFINE_GLOBAL_KEYFIELD( m_iGlobalname, FIELD_STRING, "globalname" ), - DEFINE_KEYFIELD( m_iParent, FIELD_STRING, "parentname" ), - - DEFINE_KEYFIELD( m_iHammerID, FIELD_INTEGER, "hammerid" ), // save ID numbers so that entities can be tracked between save/restore and vmf - - DEFINE_KEYFIELD( m_flSpeed, FIELD_FLOAT, "speed" ), - DEFINE_KEYFIELD( m_nRenderFX, FIELD_CHARACTER, "renderfx" ), - DEFINE_KEYFIELD( m_nRenderMode, FIELD_CHARACTER, "rendermode" ), - - // Consider moving to CBaseAnimating? - DEFINE_FIELD( m_flPrevAnimTime, FIELD_TIME ), - DEFINE_FIELD( m_flAnimTime, FIELD_TIME ), - DEFINE_FIELD( m_flSimulationTime, FIELD_TIME ), - DEFINE_FIELD( m_nLastThinkTick, FIELD_TICK ), - - DEFINE_KEYFIELD( m_nNextThinkTick, FIELD_TICK, "nextthink" ), - DEFINE_KEYFIELD( m_fEffects, FIELD_INTEGER, "effects" ), - DEFINE_KEYFIELD( m_clrRender, FIELD_COLOR32, "rendercolor" ), - DEFINE_GLOBAL_KEYFIELD( m_nModelIndex, FIELD_SHORT, "modelindex" ), -#if !defined( NO_ENTITY_PREDICTION ) - // DEFINE_FIELD( m_PredictableID, CPredictableId ), -#endif - DEFINE_FIELD( touchStamp, FIELD_INTEGER ), - DEFINE_CUSTOM_FIELD( m_aThinkFunctions, thinkcontextFuncs ), - // m_iCurrentThinkContext (not saved, debug field only, and think transient to boot) - - DEFINE_UTLVECTOR(m_ResponseContexts, FIELD_EMBEDDED), - DEFINE_KEYFIELD( m_iszResponseContext, FIELD_STRING, "ResponseContext" ), - - DEFINE_FIELD( m_pfnThink, FIELD_FUNCTION ), - DEFINE_FIELD( m_pfnTouch, FIELD_FUNCTION ), - DEFINE_FIELD( m_pfnUse, FIELD_FUNCTION ), - DEFINE_FIELD( m_pfnBlocked, FIELD_FUNCTION ), - DEFINE_FIELD( m_pfnMoveDone, FIELD_FUNCTION ), - - DEFINE_FIELD( m_lifeState, FIELD_CHARACTER ), - DEFINE_FIELD( m_takedamage, FIELD_CHARACTER ), - DEFINE_KEYFIELD( m_iMaxHealth, FIELD_INTEGER, "max_health" ), - DEFINE_KEYFIELD( m_iHealth, FIELD_INTEGER, "health" ), - // DEFINE_FIELD( m_pLink, FIELD_CLASSPTR ), - DEFINE_KEYFIELD( m_target, FIELD_STRING, "target" ), - - DEFINE_KEYFIELD( m_iszDamageFilterName, FIELD_STRING, "damagefilter" ), - DEFINE_FIELD( m_hDamageFilter, FIELD_EHANDLE ), - - DEFINE_FIELD( m_debugOverlays, FIELD_INTEGER ), - - DEFINE_GLOBAL_FIELD( m_pParent, FIELD_EHANDLE ), - DEFINE_FIELD( m_iParentAttachment, FIELD_CHARACTER ), - DEFINE_GLOBAL_FIELD( m_hMoveParent, FIELD_EHANDLE ), - DEFINE_GLOBAL_FIELD( m_hMoveChild, FIELD_EHANDLE ), - DEFINE_GLOBAL_FIELD( m_hMovePeer, FIELD_EHANDLE ), - - DEFINE_FIELD( m_iEFlags, FIELD_INTEGER ), - - DEFINE_FIELD( m_iName, FIELD_STRING ), - DEFINE_EMBEDDED( m_Collision ), - DEFINE_EMBEDDED( m_Network ), - - DEFINE_FIELD( m_MoveType, FIELD_CHARACTER ), - DEFINE_FIELD( m_MoveCollide, FIELD_CHARACTER ), - DEFINE_FIELD( m_hOwnerEntity, FIELD_EHANDLE ), - DEFINE_FIELD( m_CollisionGroup, FIELD_INTEGER ), - DEFINE_PHYSPTR( m_pPhysicsObject), - DEFINE_FIELD( m_flElasticity, FIELD_FLOAT ), - DEFINE_KEYFIELD( m_flShadowCastDistance, FIELD_FLOAT, "shadowcastdist" ), - DEFINE_FIELD( m_flDesiredShadowCastDistance, FIELD_FLOAT ), - - DEFINE_INPUT( m_iInitialTeamNum, FIELD_INTEGER, "TeamNum" ), - DEFINE_FIELD( m_iTeamNum, FIELD_INTEGER ), - -// DEFINE_FIELD( m_bSentLastFrame, FIELD_INTEGER ), - - DEFINE_FIELD( m_hGroundEntity, FIELD_EHANDLE ), - DEFINE_FIELD( m_flGroundChangeTime, FIELD_TIME ), - DEFINE_GLOBAL_KEYFIELD( m_ModelName, FIELD_MODELNAME, "model" ), - - DEFINE_KEYFIELD( m_vecBaseVelocity, FIELD_VECTOR, "basevelocity" ), - DEFINE_FIELD( m_vecAbsVelocity, FIELD_VECTOR ), - DEFINE_KEYFIELD( m_vecAngVelocity, FIELD_VECTOR, "avelocity" ), -// DEFINE_FIELD( m_vecAbsAngVelocity, FIELD_VECTOR ), - DEFINE_ARRAY( m_rgflCoordinateFrame, FIELD_FLOAT, 12 ), // NOTE: MUST BE IN LOCAL SPACE, NOT POSITION_VECTOR!!! (see CBaseEntity::Restore) - - DEFINE_KEYFIELD( m_nWaterLevel, FIELD_CHARACTER, "waterlevel" ), - DEFINE_FIELD( m_nWaterType, FIELD_CHARACTER ), - DEFINE_FIELD( m_pBlocker, FIELD_EHANDLE ), - - DEFINE_KEYFIELD( m_flGravity, FIELD_FLOAT, "gravity" ), - DEFINE_KEYFIELD( m_flFriction, FIELD_FLOAT, "friction" ), - - // Local time is local to each object. It doesn't need to be re-based if the clock - // changes. Therefore it is saved as a FIELD_FLOAT, not a FIELD_TIME - DEFINE_KEYFIELD( m_flLocalTime, FIELD_FLOAT, "ltime" ), - DEFINE_FIELD( m_flVPhysicsUpdateLocalTime, FIELD_FLOAT ), - DEFINE_FIELD( m_flMoveDoneTime, FIELD_FLOAT ), - -// DEFINE_FIELD( m_nPushEnumCount, FIELD_INTEGER ), - - DEFINE_FIELD( m_vecAbsOrigin, FIELD_POSITION_VECTOR ), - DEFINE_KEYFIELD( m_vecVelocity, FIELD_VECTOR, "velocity" ), - DEFINE_KEYFIELD( m_iTextureFrameIndex, FIELD_CHARACTER, "texframeindex" ), - DEFINE_FIELD( m_bSimulatedEveryTick, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bAnimatedEveryTick, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bAlternateSorting, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_spawnflags, FIELD_INTEGER, "spawnflags" ), - DEFINE_FIELD( m_nTransmitStateOwnedCounter, FIELD_CHARACTER ), - DEFINE_FIELD( m_angAbsRotation, FIELD_VECTOR ), - DEFINE_FIELD( m_vecOrigin, FIELD_VECTOR ), // NOTE: MUST BE IN LOCAL SPACE, NOT POSITION_VECTOR!!! (see CBaseEntity::Restore) - DEFINE_FIELD( m_angRotation, FIELD_VECTOR ), - - DEFINE_KEYFIELD( m_vecViewOffset, FIELD_VECTOR, "view_ofs" ), - - DEFINE_FIELD( m_fFlags, FIELD_INTEGER ), -#if !defined( NO_ENTITY_PREDICTION ) -// DEFINE_FIELD( m_bIsPlayerSimulated, FIELD_INTEGER ), -// DEFINE_FIELD( m_hPlayerSimulationOwner, FIELD_EHANDLE ), -#endif - // DEFINE_FIELD( m_pTimedOverlay, TimedOverlay_t* ), - DEFINE_FIELD( m_nSimulationTick, FIELD_TICK ), - // DEFINE_FIELD( m_RefEHandle, CBaseHandle ), - -// DEFINE_FIELD( m_nWaterTouch, FIELD_INTEGER ), -// DEFINE_FIELD( m_nSlimeTouch, FIELD_INTEGER ), - DEFINE_FIELD( m_flNavIgnoreUntilTime, FIELD_TIME ), - -// DEFINE_FIELD( m_bToolRecording, FIELD_BOOLEAN ), -// DEFINE_FIELD( m_ToolHandle, FIELD_INTEGER ), - - // NOTE: This is tricky. TeamNum must be saved, but we can't directly - // read it in, because we can only set it after the team entity has been read in, - // which may or may not actually occur before the entity is parsed. - // Therefore, we set the TeamNum from the InitialTeamNum in Activate - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetTeam", InputSetTeam ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Kill", InputKill ), - DEFINE_INPUTFUNC( FIELD_VOID, "KillHierarchy", InputKillHierarchy ), - DEFINE_INPUTFUNC( FIELD_VOID, "Use", InputUse ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "Alpha", InputAlpha ), - DEFINE_INPUTFUNC( FIELD_BOOLEAN, "AlternativeSorting", InputAlternativeSorting ), - DEFINE_INPUTFUNC( FIELD_COLOR32, "Color", InputColor ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetParent", InputSetParent ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetParentAttachment", InputSetParentAttachment ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetParentAttachmentMaintainOffset", InputSetParentAttachmentMaintainOffset ), - DEFINE_INPUTFUNC( FIELD_VOID, "ClearParent", InputClearParent ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetDamageFilter", InputSetDamageFilter ), - - DEFINE_INPUTFUNC( FIELD_VOID, "EnableDamageForces", InputEnableDamageForces ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableDamageForces", InputDisableDamageForces ), - - DEFINE_INPUTFUNC( FIELD_STRING, "DispatchEffect", InputDispatchEffect ), - DEFINE_INPUTFUNC( FIELD_STRING, "DispatchResponse", InputDispatchResponse ), - - // Entity I/O methods to alter context - DEFINE_INPUTFUNC( FIELD_STRING, "AddContext", InputAddContext ), - DEFINE_INPUTFUNC( FIELD_STRING, "RemoveContext", InputRemoveContext ), - DEFINE_INPUTFUNC( FIELD_STRING, "ClearContext", InputClearContext ), - - DEFINE_INPUTFUNC( FIELD_VOID, "DisableShadow", InputDisableShadow ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableShadow", InputEnableShadow ), - - DEFINE_INPUTFUNC( FIELD_STRING, "AddOutput", InputAddOutput ), - - DEFINE_INPUTFUNC( FIELD_STRING, "FireUser1", InputFireUser1 ), - DEFINE_INPUTFUNC( FIELD_STRING, "FireUser2", InputFireUser2 ), - DEFINE_INPUTFUNC( FIELD_STRING, "FireUser3", InputFireUser3 ), - DEFINE_INPUTFUNC( FIELD_STRING, "FireUser4", InputFireUser4 ), - - DEFINE_OUTPUT( m_OnUser1, "OnUser1" ), - DEFINE_OUTPUT( m_OnUser2, "OnUser2" ), - DEFINE_OUTPUT( m_OnUser3, "OnUser3" ), - DEFINE_OUTPUT( m_OnUser4, "OnUser4" ), - - // Function Pointers - DEFINE_FUNCTION( SUB_Remove ), - DEFINE_FUNCTION( SUB_DoNothing ), - DEFINE_FUNCTION( SUB_StartFadeOut ), - DEFINE_FUNCTION( SUB_StartFadeOutInstant ), - DEFINE_FUNCTION( SUB_FadeOut ), - DEFINE_FUNCTION( SUB_Vanish ), - DEFINE_FUNCTION( SUB_CallUseToggle ), - DEFINE_THINKFUNC( ShadowCastDistThink ), - - DEFINE_FIELD( m_hEffectEntity, FIELD_EHANDLE ), - - //DEFINE_FIELD( m_DamageModifiers, FIELD_?? ), // can't save? - // DEFINE_FIELD( m_fDataObjectTypes, FIELD_INTEGER ), -END_DATADESC() - -// For code error checking -extern bool g_bReceivedChainedUpdateOnRemove; - -//----------------------------------------------------------------------------- -// Purpose: Called just prior to object destruction -// Entities that need to unlink themselves from other entities should do the unlinking -// here rather than in their destructor. The reason why is that when the global entity list -// is told to Clear(), it first takes a pass through all active entities and calls UTIL_Remove -// on each such entity. Then it calls the delete function on each deleted entity in the list. -// In the old code, the objects were simply destroyed in order and there was no guarantee that the -// destructor of one object would not try to access another object that might already have been -// destructed (especially since the entity list order is more or less random!). -// NOTE: You should never call delete directly on an entity (there's an assert now), see note -// at CBaseEntity::~CBaseEntity for more information. -// -// NOTE: You should chain to BaseClass::UpdateOnRemove after doing your own cleanup code, e.g.: -// -// void CDerived::UpdateOnRemove( void ) -// { -// ... cleanup code -// ... -// -// BaseClass::UpdateOnRemove(); -// } -// -// In general, this function updates global tables that need to know about entities being removed -//----------------------------------------------------------------------------- -void CBaseEntity::UpdateOnRemove( void ) -{ - g_bReceivedChainedUpdateOnRemove = true; - - // Virtual call to shut down any looping sounds. - StopLoopingSounds(); - - // Notifies entity listeners, etc - gEntList.NotifyRemoveEntity( GetRefEHandle() ); - - if ( edict() ) - { - AddFlag( FL_KILLME ); - if ( GetFlags() & FL_GRAPHED ) - { - /* <> - // this entity was a LinkEnt in the world node graph, so we must remove it from - // the graph since we are removing it from the world. - for ( int i = 0 ; i < WorldGraph.m_cLinks ; i++ ) - { - if ( WorldGraph.m_pLinkPool [ i ].m_pLinkEnt == pev ) - { - // if this link has a link ent which is the same ent that is removing itself, remove it! - WorldGraph.m_pLinkPool [ i ].m_pLinkEnt = NULL; - } - } - */ - } - } - - if ( m_iGlobalname != NULL_STRING ) - { - // NOTE: During level shutdown the global list will suppress this - // it assumes your changing levels or the game will end - // causing the whole list to be flushed - GlobalEntity_SetState( m_iGlobalname, GLOBAL_DEAD ); - } - - VPhysicsDestroyObject(); - - // This is only here to allow the MOVETYPE_NONE to be set without the - // assertion triggering. Why do we bother setting the MOVETYPE to none here? - RemoveEffects( EF_BONEMERGE ); - SetMoveType(MOVETYPE_NONE); - - // If we have a parent, unlink from it. - UnlinkFromParent( this ); - - // Any children still connected are orphans, mark all for delete - CUtlVector childrenList; - GetAllChildren( this, childrenList ); - if ( childrenList.Count() ) - { - DevMsg( 2, "Warning: Deleting orphaned children of %s\n", GetClassname() ); - for ( int i = childrenList.Count()-1; i >= 0; --i ) - { - UTIL_Remove( childrenList[i] ); - } - } - - SetGroundEntity( NULL ); -} - -//----------------------------------------------------------------------------- -// capabilities -//----------------------------------------------------------------------------- -int CBaseEntity::ObjectCaps( void ) -{ -#if 1 - model_t *pModel = GetModel(); - bool bIsBrush = ( pModel && modelinfo->GetModelType( pModel ) == mod_brush ); - - // We inherit our parent's use capabilities so that we can forward use commands - // to our parent. - CBaseEntity *pParent = GetParent(); - if ( pParent ) - { - int caps = pParent->ObjectCaps(); - - if ( !bIsBrush ) - caps &= ( FCAP_ACROSS_TRANSITION | FCAP_IMPULSE_USE | FCAP_CONTINUOUS_USE | FCAP_ONOFF_USE | FCAP_DIRECTIONAL_USE ); - else - caps &= ( FCAP_IMPULSE_USE | FCAP_CONTINUOUS_USE | FCAP_ONOFF_USE | FCAP_DIRECTIONAL_USE ); - - if ( pParent->IsPlayer() ) - caps |= FCAP_ACROSS_TRANSITION; - - return caps; - } - else if ( !bIsBrush ) - { - return FCAP_ACROSS_TRANSITION; - } - - return 0; -#else - // We inherit our parent's use capabilities so that we can forward use commands - // to our parent. - int parentCaps = 0; - if (GetParent()) - { - parentCaps = GetParent()->ObjectCaps(); - parentCaps &= ( FCAP_IMPULSE_USE | FCAP_CONTINUOUS_USE | FCAP_ONOFF_USE | FCAP_DIRECTIONAL_USE ); - } - - model_t *pModel = GetModel(); - if ( pModel && modelinfo->GetModelType( pModel ) == mod_brush ) - return parentCaps; - - return FCAP_ACROSS_TRANSITION | parentCaps; -#endif -} - -void CBaseEntity::StartTouch( CBaseEntity *pOther ) -{ - // notify parent - if ( m_pParent != NULL ) - m_pParent->StartTouch( pOther ); -} - -void CBaseEntity::Touch( CBaseEntity *pOther ) -{ - if ( m_pfnTouch ) - (this->*m_pfnTouch)( pOther ); - - // notify parent of touch - if ( m_pParent != NULL ) - m_pParent->Touch( pOther ); -} - -void CBaseEntity::EndTouch( CBaseEntity *pOther ) -{ - // notify parent - if ( m_pParent != NULL ) - { - m_pParent->EndTouch( pOther ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Dispatches blocked events to this entity's blocked handler, set via SetBlocked. -// Input : pOther - The entity that is blocking us. -//----------------------------------------------------------------------------- -void CBaseEntity::Blocked( CBaseEntity *pOther ) -{ - if ( m_pfnBlocked ) - { - (this->*m_pfnBlocked)( pOther ); - } - - // - // Forward the blocked event to our parent, if any. - // - if ( m_pParent != NULL ) - { - m_pParent->Blocked( pOther ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Dispatches use events to this entity's use handler, set via SetUse. -// Input : pActivator - -// pCaller - -// useType - -// value - -//----------------------------------------------------------------------------- -void CBaseEntity::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - if ( m_pfnUse != NULL ) - { - (this->*m_pfnUse)( pActivator, pCaller, useType, value ); - } - else - { - // - // We don't handle use events. Forward to our parent, if any. - // - if ( m_pParent != NULL ) - { - m_pParent->Use( pActivator, pCaller, useType, value ); - } - } -} - -static CBaseEntity *FindPhysicsBlocker( IPhysicsObject *pPhysics, physicspushlist_t &list, const Vector &pushVel ) -{ - IPhysicsFrictionSnapshot *pSnapshot = pPhysics->CreateFrictionSnapshot(); - CBaseEntity *pBlocker = NULL; - float maxForce = 0; - while ( pSnapshot->IsValid() ) - { - IPhysicsObject *pOther = pSnapshot->GetObject(1); - CBaseEntity *pOtherEntity = static_cast(pOther->GetGameData()); - bool inList = false; - for ( int i = 0; i < list.pushedCount; i++ ) - { - if ( pOtherEntity == list.pushedEnts[i] ) - { - inList = true; - break; - } - } - - Vector normal; - pSnapshot->GetSurfaceNormal(normal); - float dot = DotProduct( pushVel, pSnapshot->GetNormalForce() * normal ); - if ( !pBlocker || (!inList && dot > maxForce) ) - { - pBlocker = pOtherEntity; - if ( !inList ) - { - maxForce = dot; - } - } - - pSnapshot->NextFrictionData(); - } - pPhysics->DestroyFrictionSnapshot( pSnapshot ); - - return pBlocker; -} - - -struct pushblock_t -{ - physicspushlist_t *pList; - CBaseEntity *pRootParent; - CBaseEntity *pBlockedEntity; - float moveBackFraction; - float movetime; -}; - -static void ComputePushStartMatrix( matrix3x4_t &start, CBaseEntity *pEntity, const pushblock_t ¶ms ) -{ - Vector localOrigin; - QAngle localAngles; - if ( params.pList ) - { - localOrigin = params.pList->localOrigin; - localAngles = params.pList->localAngles; - } - else - { - localOrigin = params.pRootParent->GetAbsOrigin() - params.pRootParent->GetAbsVelocity() * params.movetime; - localAngles = params.pRootParent->GetAbsAngles() - params.pRootParent->GetLocalAngularVelocity() * params.movetime; - } - matrix3x4_t xform, delta; - AngleMatrix( localAngles, localOrigin, xform ); - - matrix3x4_t srcInv; - // xform = src(-1) * dest - MatrixInvert( params.pRootParent->EntityToWorldTransform(), srcInv ); - ConcatTransforms( xform, srcInv, delta ); - ConcatTransforms( delta, pEntity->EntityToWorldTransform(), start ); -} - -#define DEBUG_PUSH_MESSAGES 0 -static void CheckPushedEntity( CBaseEntity *pEntity, pushblock_t ¶ms ) -{ - IPhysicsObject *pPhysics = pEntity->VPhysicsGetObject(); - if ( !pPhysics ) - return; - // somehow we've got a static or motion disabled physics object in hierarchy! - // This is not allowed! Don't test blocking in that case. - Assert(pPhysics->IsMoveable()); - if ( !pPhysics->IsMoveable() || !pPhysics->GetShadowController() ) - { -#if DEBUG_PUSH_MESSAGES - Msg("Blocking %s, not moveable!\n", pEntity->GetClassname()); -#endif - return; - } - - bool checkrot = true; - bool checkmove = true; - Vector origin; - QAngle angles; - pPhysics->GetShadowPosition( &origin, &angles ); - float fraction = -1.0f; - - matrix3x4_t parentDelta; - if ( pEntity == params.pRootParent ) - { - if ( pEntity->GetLocalAngularVelocity() == vec3_angle ) - checkrot = false; - if ( pEntity->GetLocalVelocity() == vec3_origin) - checkmove = false; - } - else - { -#if DEBUG_PUSH_MESSAGES - if ( pPhysics->IsAttachedToConstraint(false)) - { - Msg("Warning, hierarchical entity is attached to a constraint %s\n", pEntity->GetClassname()); - } -#endif - } - - if ( checkmove ) - { - // project error onto the axis of movement - Vector dir = pEntity->GetAbsVelocity(); - float speed = VectorNormalize(dir); - Vector targetPos; - pPhysics->GetShadowController()->GetTargetPosition( &targetPos, NULL ); - float targetAmount = DotProduct(targetPos, dir); - float currentAmount = DotProduct(origin, dir); - float entityAmount = DotProduct(pEntity->GetAbsOrigin(), dir); - - // if target and entity origin are not in sync, then the position of the entity was updated - // by something outside of push physics - if ( (targetAmount - entityAmount) > 1 ) - { - pEntity->UpdatePhysicsShadowToCurrentPosition(0); -#if DEBUG_PUSH_MESSAGES - Warning("Someone slammed the position of a %s\n", pEntity->GetClassname() ); -#endif - } - else - { - float dist = targetAmount - currentAmount; - if ( dist > 1 ) - { - #if DEBUG_PUSH_MESSAGES - const char *pName = pEntity->GetClassname(); - Msg( "%s blocked by %.2f units\n", pName, dist ); - #endif - float movementAmount = targetAmount - (speed * params.movetime); - if ( pEntity == params.pRootParent ) - { - if ( params.pList ) - { - Vector localVel = pEntity->GetLocalVelocity(); - VectorNormalize(localVel); - float localTargetAmt = DotProduct(pEntity->GetLocalOrigin(), localVel); - movementAmount = targetAmount + DotProduct(params.pList->localOrigin, localVel) - localTargetAmt; - } - } - else - { - matrix3x4_t start; - ComputePushStartMatrix( start, pEntity, params ); - Vector startPos; - MatrixPosition( start, startPos ); - movementAmount = DotProduct(startPos, dir); - } - float expectedDist = targetAmount - movementAmount; - // compute the fraction to move back the AI to match the physics - if ( expectedDist <= 0 ) - { - fraction = 1; - } - else - { - fraction = dist / expectedDist; - fraction = clamp(fraction, 0, 1); - } - } - } - } - - if ( checkrot ) - { - Vector axis; - float deltaAngle; - RotationDeltaAxisAngle( angles, pEntity->GetAbsAngles(), axis, deltaAngle ); - if ( fabsf(deltaAngle) > 0.5f ) - { - Vector targetAxis; - QAngle targetRot; - float deltaTargetAngle; - pPhysics->GetShadowController()->GetTargetPosition( NULL, &targetRot ); - RotationDeltaAxisAngle( angles, targetRot, targetAxis, deltaTargetAngle ); - if ( fabsf(deltaTargetAngle) > 0.01f ) - { - float expectedDist = deltaAngle; -#if DEBUG_PUSH_MESSAGES - const char *pName = pEntity->GetClassname(); - Msg( "%s blocked by %.2f degrees\n", pName, deltaAngle ); - if ( pPhysics->IsAsleep() ) - { - Msg("Asleep while blocked?\n"); - } - if ( pPhysics->GetGameFlags() & FVPHYSICS_PENETRATING ) - { - Msg("Blocking for penetration!\n"); - } -#endif - if ( pEntity == params.pRootParent ) - { - expectedDist = pEntity->GetLocalAngularVelocity().Length() * params.movetime; - } - else - { - matrix3x4_t start; - ComputePushStartMatrix( start, pEntity, params ); - Vector startAxis; - float startAngle; - Vector startPos; - QAngle startAngles; - MatrixAngles( start, startAngles, startPos ); - RotationDeltaAxisAngle( startAngles, pEntity->GetAbsAngles(), startAxis, startAngle ); - expectedDist = startAngle * DotProduct( startAxis, axis ); - } - - float t = expectedDist != 0.0f ? fabsf(deltaAngle / expectedDist) : 1.0f; - t = clamp(t,0,1); - fraction = MAX(fraction, t); - } - else - { - pEntity->UpdatePhysicsShadowToCurrentPosition(0); -#if DEBUG_PUSH_MESSAGES - Warning("Someone slammed the position of a %s\n", pEntity->GetClassname() ); -#endif - } - } - } - if ( fraction >= params.moveBackFraction ) - { - params.moveBackFraction = fraction; - params.pBlockedEntity = pEntity; - } -} - -void CBaseEntity::VPhysicsUpdatePusher( IPhysicsObject *pPhysics ) -{ - float movetime = m_flLocalTime - m_flVPhysicsUpdateLocalTime; - if (movetime <= 0) - return; - - // only reconcile pushers on the final vphysics tick - if ( !PhysIsFinalTick() ) - return; - - Vector origin; - QAngle angles; - - // physics updated the shadow, so check to see if I got blocked - // NOTE: SOLID_BSP cannont compute consistent collisions wrt vphysics, so - // don't allow vphysics to block. Assume game physics has handled it. - if ( GetSolid() != SOLID_BSP && pPhysics->GetShadowPosition( &origin, &angles ) ) - { - CUtlVector list; - GetAllInHierarchy( this, list ); - //NDebugOverlay::BoxAngles( origin, CollisionProp()->OBBMins(), CollisionProp()->OBBMaxs(), angles, 255,0,0,0, gpGlobals->frametime); - - physicspushlist_t *pList = NULL; - if ( HasDataObjectType(PHYSICSPUSHLIST) ) - { - pList = (physicspushlist_t *)GetDataObject( PHYSICSPUSHLIST ); - Assert(pList); - } - bool checkrot = (GetLocalAngularVelocity() != vec3_angle) ? true : false; - bool checkmove = (GetLocalVelocity() != vec3_origin) ? true : false; - - pushblock_t params; - params.pRootParent = this; - params.pList = pList; - params.pBlockedEntity = NULL; - params.moveBackFraction = 0.0f; - params.movetime = movetime; - for ( int i = 0; i < list.Count(); i++ ) - { - if ( list[i]->IsSolid() ) - { - CheckPushedEntity( list[i], params ); - } - } - - float physLocalTime = m_flLocalTime; - if ( params.pBlockedEntity ) - { - float moveback = movetime * params.moveBackFraction; - if ( moveback > 0 ) - { - physLocalTime = m_flLocalTime - moveback; - // add 1% noise for bouncing in collision. - if ( physLocalTime <= (m_flVPhysicsUpdateLocalTime + movetime * 0.99f) ) - { - CBaseEntity *pBlocked = NULL; - IPhysicsObject *pOther; - if ( params.pBlockedEntity->VPhysicsGetObject()->GetContactPoint( NULL, &pOther ) ) - { - pBlocked = static_cast(pOther->GetGameData()); - } - // UNDONE: Need to traverse hierarchy here? Shouldn't. - if ( pList ) - { - SetLocalOrigin( pList->localOrigin ); - SetLocalAngles( pList->localAngles ); - physLocalTime = pList->localMoveTime; - for ( int i = 0; i < pList->pushedCount; i++ ) - { - CBaseEntity *pEntity = pList->pushedEnts[i]; - if ( !pEntity ) - continue; - - pEntity->SetAbsOrigin( pEntity->GetAbsOrigin() - pList->pushVec[i] ); - } - CBaseEntity *pPhysicsBlocker = FindPhysicsBlocker( VPhysicsGetObject(), *pList, pList->pushVec[0] ); - if ( pPhysicsBlocker ) - { - pBlocked = pPhysicsBlocker; - } - } - else - { - Vector origin = GetLocalOrigin(); - QAngle angles = GetLocalAngles(); - - if ( checkmove ) - { - origin -= GetLocalVelocity() * moveback; - } - if ( checkrot ) - { - // BUGBUG: This is pretty hack-tastic! - angles -= GetLocalAngularVelocity() * moveback; - } - - SetLocalOrigin( origin ); - SetLocalAngles( angles ); - } - - if ( pBlocked ) - { - Blocked( pBlocked ); - } - m_flLocalTime = physLocalTime; - } - } - } - } - - // this data is no longer useful, free the memory - if ( HasDataObjectType(PHYSICSPUSHLIST) ) - { - DestroyDataObject( PHYSICSPUSHLIST ); - } - - m_flVPhysicsUpdateLocalTime = m_flLocalTime; - if ( m_flMoveDoneTime <= m_flLocalTime && m_flMoveDoneTime > 0 ) - { - SetMoveDoneTime( -1 ); - MoveDone(); - } -} - - -void CBaseEntity::SetMoveDoneTime( float flDelay ) -{ - if (flDelay >= 0) - { - m_flMoveDoneTime = GetLocalTime() + flDelay; - } - else - { - m_flMoveDoneTime = -1; - } - CheckHasGamePhysicsSimulation(); -} - -//----------------------------------------------------------------------------- -// Purpose: Relinks all of a parents children into the collision tree -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsRelinkChildren( float dt ) -{ - CBaseEntity *child; - - // iterate through all children - for ( child = FirstMoveChild(); child != NULL; child = child->NextMovePeer() ) - { - if ( child->IsSolid() || child->IsSolidFlagSet(FSOLID_TRIGGER) ) - { - child->PhysicsTouchTriggers(); - } - - // - // Update their physics shadows. We should never have any children of - // movetype VPHYSICS. - // - if ( child->GetMoveType() != MOVETYPE_VPHYSICS ) - { - child->UpdatePhysicsShadowToCurrentPosition( dt ); - } - else if ( child->GetOwnerEntity() != this ) - { - // the only case where this is valid is if this entity is an attached ragdoll. - // So assert here to catch the non-ragdoll case. - Assert( 0 ); - } - - if ( child->FirstMoveChild() ) - { - child->PhysicsRelinkChildren(dt); - } - } -} - -void CBaseEntity::PhysicsTouchTriggers( const Vector *pPrevAbsOrigin ) -{ - edict_t *pEdict = edict(); - if ( pEdict && !IsWorld() ) - { - Assert(CollisionProp()); - bool isTriggerCheckSolids = IsSolidFlagSet( FSOLID_TRIGGER ); - bool isSolidCheckTriggers = IsSolid() && !isTriggerCheckSolids; // NOTE: Moving triggers (items, ammo etc) are not - // checked against other triggers ot reduce the number of touchlinks created - if ( !(isSolidCheckTriggers || isTriggerCheckSolids) ) - return; - - if ( GetSolid() == SOLID_BSP ) - { - if ( !GetModel() && Q_strlen( STRING( GetModelName() ) ) == 0 ) - { - Warning( "Inserted %s with no model\n", GetClassname() ); - return; - } - } - - SetCheckUntouch( true ); - if ( isSolidCheckTriggers ) - { - engine->SolidMoved( pEdict, CollisionProp(), pPrevAbsOrigin, sm_bAccurateTriggerBboxChecks ); - } - if ( isTriggerCheckSolids ) - { - engine->TriggerMoved( pEdict, sm_bAccurateTriggerBboxChecks ); - } - } -} - -void CBaseEntity::VPhysicsShadowCollision( int index, gamevcollisionevent_t *pEvent ) -{ -} - - - -void CBaseEntity::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) -{ - // filter out ragdoll props hitting other parts of itself too often - // UNDONE: Store a sound time for this entity (not just this pair of objects) - // and filter repeats on that? - int otherIndex = !index; - CBaseEntity *pHitEntity = pEvent->pEntities[otherIndex]; - - // Don't make sounds / effects if neither entity is MOVETYPE_VPHYSICS. The game - // physics should have done so. - if ( GetMoveType() != MOVETYPE_VPHYSICS && pHitEntity->GetMoveType() != MOVETYPE_VPHYSICS ) - return; - - if ( pEvent->deltaCollisionTime < 0.5 && (pHitEntity == this) ) - return; - - // don't make noise for hidden/invisible/sky materials - surfacedata_t *phit = physprops->GetSurfaceData( pEvent->surfaceProps[otherIndex] ); - const surfacedata_t *pprops = physprops->GetSurfaceData( pEvent->surfaceProps[index] ); - if ( phit->game.material == 'X' || pprops->game.material == 'X' ) - return; - - if ( pHitEntity == this ) - { - PhysCollisionSound( this, pEvent->pObjects[index], CHAN_BODY, pEvent->surfaceProps[index], pEvent->surfaceProps[otherIndex], pEvent->deltaCollisionTime, pEvent->collisionSpeed ); - } - else - { - PhysCollisionSound( this, pEvent->pObjects[index], CHAN_STATIC, pEvent->surfaceProps[index], pEvent->surfaceProps[otherIndex], pEvent->deltaCollisionTime, pEvent->collisionSpeed ); - } - PhysCollisionScreenShake( pEvent, index ); - -#if HL2_EPISODIC - // episodic does something different for when advisor shields are struck - if ( phit->game.material == 'Z' || pprops->game.material == 'Z') - { - PhysCollisionWarpEffect( pEvent, phit ); - } - else - { - PhysCollisionDust( pEvent, phit ); - } -#else - PhysCollisionDust( pEvent, phit ); -#endif -} - -void CBaseEntity::VPhysicsFriction( IPhysicsObject *pObject, float energy, int surfaceProps, int surfacePropsHit ) -{ - PhysFrictionSound( this, pObject, energy, surfaceProps, surfacePropsHit ); -} - - -void CBaseEntity::VPhysicsSwapObject( IPhysicsObject *pSwap ) -{ - if ( !pSwap ) - { - PhysRemoveShadow(this); - } - - if ( !m_pPhysicsObject ) - { - Warning( "Bad vphysics swap for %s\n", STRING(m_iClassname) ); - } - m_pPhysicsObject = pSwap; -} - - -// Tells the physics shadow to update it's target to the current position -void CBaseEntity::UpdatePhysicsShadowToCurrentPosition( float deltaTime ) -{ - if ( GetMoveType() != MOVETYPE_VPHYSICS ) - { - IPhysicsObject *pPhys = VPhysicsGetObject(); - if ( pPhys ) - { - pPhys->UpdateShadow( GetAbsOrigin(), GetAbsAngles(), false, deltaTime ); - } - } -} - -int CBaseEntity::VPhysicsGetObjectList( IPhysicsObject **pList, int listMax ) -{ - IPhysicsObject *pPhys = VPhysicsGetObject(); - if ( pPhys ) - { - // multi-object entities must implement this function - Assert( !(pPhys->GetGameFlags() & FVPHYSICS_MULTIOBJECT_ENTITY) ); - if ( listMax > 0 ) - { - pList[0] = pPhys; - return 1; - } - } - return 0; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CBaseEntity::VPhysicsIsFlesh( void ) -{ - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int count = VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - for ( int i = 0; i < count; i++ ) - { - int material = pList[i]->GetMaterialIndex(); - const surfacedata_t *pSurfaceData = physprops->GetSurfaceData( material ); - // Is flesh ?, don't allow pickup - if ( pSurfaceData->game.material == CHAR_TEX_ANTLION || pSurfaceData->game.material == CHAR_TEX_FLESH || pSurfaceData->game.material == CHAR_TEX_BLOODYFLESH || pSurfaceData->game.material == CHAR_TEX_ALIENFLESH ) - return true; - } - return false; -} - -bool CBaseEntity::Intersects( CBaseEntity *pOther ) -{ - if ( !edict() || !pOther->edict() ) - return false; - - CCollisionProperty *pMyProp = CollisionProp(); - CCollisionProperty *pOtherProp = pOther->CollisionProp(); - - return IsOBBIntersectingOBB( - pMyProp->GetCollisionOrigin(), pMyProp->GetCollisionAngles(), pMyProp->OBBMins(), pMyProp->OBBMaxs(), - pOtherProp->GetCollisionOrigin(), pOtherProp->GetCollisionAngles(), pOtherProp->OBBMins(), pOtherProp->OBBMaxs() ); -} - -extern ConVar ai_LOS_mode; - -//========================================================= -// FVisible - returns true if a line can be traced from -// the caller's eyes to the target -//========================================================= -bool CBaseEntity::FVisible( CBaseEntity *pEntity, int traceMask, CBaseEntity **ppBlocker ) -{ - VPROF( "CBaseEntity::FVisible" ); - - if ( pEntity->GetFlags() & FL_NOTARGET ) - return false; - -#if HL1_DLL - // FIXME: only block LOS through opaque water - // don't look through water - if ((m_nWaterLevel != 3 && pEntity->m_nWaterLevel == 3) - || (m_nWaterLevel == 3 && pEntity->m_nWaterLevel == 0)) - return false; -#endif - - Vector vecLookerOrigin = EyePosition();//look through the caller's 'eyes' - Vector vecTargetOrigin = pEntity->EyePosition(); - - trace_t tr; - if ( !IsXbox() && ai_LOS_mode.GetBool() ) - { - UTIL_TraceLine(vecLookerOrigin, vecTargetOrigin, traceMask, this, COLLISION_GROUP_NONE, &tr); - } - else - { - // If we're doing an LOS search, include NPCs. - if ( traceMask == MASK_BLOCKLOS ) - { - traceMask = MASK_BLOCKLOS_AND_NPCS; - } - - // Player sees through nodraw - if ( IsPlayer() ) - { - traceMask &= ~CONTENTS_BLOCKLOS; - } - - // Use the custom LOS trace filter - CTraceFilterLOS traceFilter( this, COLLISION_GROUP_NONE, pEntity ); - UTIL_TraceLine( vecLookerOrigin, vecTargetOrigin, traceMask, &traceFilter, &tr ); - } - - if (tr.fraction != 1.0 || tr.startsolid ) - { - // If we hit the entity we're looking for, it's visible - if ( tr.m_pEnt == pEntity ) - return true; - - // Got line of sight on the vehicle the player is driving! - if ( pEntity && pEntity->IsPlayer() ) - { - CBasePlayer *pPlayer = assert_cast( pEntity ); - if ( tr.m_pEnt == pPlayer->GetVehicleEntity() ) - return true; - } - - if (ppBlocker) - { - *ppBlocker = tr.m_pEnt; - } - - return false;// Line of sight is not established - } - - return true;// line of sight is valid. -} - -//========================================================= -// FVisible - returns true if a line can be traced from -// the caller's eyes to the wished position. -//========================================================= -bool CBaseEntity::FVisible( const Vector &vecTarget, int traceMask, CBaseEntity **ppBlocker ) -{ -#if HL1_DLL - - // don't look through water - // FIXME: only block LOS through opaque water - bool inWater = ( UTIL_PointContents( vecTarget ) & (CONTENTS_SLIME|CONTENTS_WATER) ) ? true : false; - - // Don't allow it if we're straddling two areas - if ( ( m_nWaterLevel == 3 && !inWater ) || ( m_nWaterLevel != 3 && inWater ) ) - return false; - -#endif - - trace_t tr; - Vector vecLookerOrigin = EyePosition();// look through the caller's 'eyes' - - if ( ai_LOS_mode.GetBool() ) - { - UTIL_TraceLine( vecLookerOrigin, vecTarget, traceMask, this, COLLISION_GROUP_NONE, &tr); - } - else - { - // If we're doing an LOS search, include NPCs. - if ( traceMask == MASK_BLOCKLOS ) - { - traceMask = MASK_BLOCKLOS_AND_NPCS; - } - - // Player sees through nodraw and blocklos - if ( IsPlayer() ) - { - traceMask |= CONTENTS_IGNORE_NODRAW_OPAQUE; - traceMask &= ~CONTENTS_BLOCKLOS; - } - - // Use the custom LOS trace filter - CTraceFilterLOS traceFilter( this, COLLISION_GROUP_NONE ); - UTIL_TraceLine( vecLookerOrigin, vecTarget, traceMask, &traceFilter, &tr ); - } - - if (tr.fraction != 1.0) - { - if (ppBlocker) - { - *ppBlocker = tr.m_pEnt; - } - return false;// Line of sight is not established - } - - return true;// line of sight is valid. -} - -extern ConVar ai_debug_los; -//----------------------------------------------------------------------------- -// Purpose: Turn on prop LOS debugging mode -//----------------------------------------------------------------------------- -void CC_AI_LOS_Debug( IConVar *var, const char *pOldString, float flOldValue ) -{ - int iLOSMode = ai_debug_los.GetInt(); - for ( CBaseEntity *pEntity = gEntList.FirstEnt(); pEntity != NULL; pEntity = gEntList.NextEnt(pEntity) ) - { - if ( iLOSMode == 1 && pEntity->IsSolid() ) - { - pEntity->m_debugOverlays |= OVERLAY_SHOW_BLOCKSLOS; - } - else if ( iLOSMode == 2 ) - { - pEntity->m_debugOverlays |= OVERLAY_SHOW_BLOCKSLOS; - } - else - { - pEntity->m_debugOverlays &= ~OVERLAY_SHOW_BLOCKSLOS; - } - } -} -ConVar ai_debug_los("ai_debug_los", "0", FCVAR_CHEAT, "NPC Line-Of-Sight debug mode. If 1, solid entities that block NPC LOC will be highlighted with white bounding boxes. If 2, it'll show non-solid entities that would do it if they were solid.", CC_AI_LOS_Debug ); - - -Class_T CBaseEntity::Classify ( void ) -{ - return CLASS_NONE; -} - -float CBaseEntity::GetAutoAimRadius() -{ - if( g_pGameRules->GetAutoAimMode() == AUTOAIM_ON_CONSOLE ) - return 48.0f; - else - return 24.0f; -} - -//----------------------------------------------------------------------------- -// Changes the shadow cast distance over time -//----------------------------------------------------------------------------- -void CBaseEntity::ShadowCastDistThink( ) -{ - SetShadowCastDistance( m_flDesiredShadowCastDistance ); - SetContextThink( NULL, gpGlobals->curtime, "ShadowCastDistThink" ); -} - -void CBaseEntity::SetShadowCastDistance( float flDesiredDistance, float flDelay ) -{ - m_flDesiredShadowCastDistance = flDesiredDistance; - if ( m_flDesiredShadowCastDistance != m_flShadowCastDistance ) - { - SetContextThink( &CBaseEntity::ShadowCastDistThink, gpGlobals->curtime + flDelay, "ShadowCastDistThink" ); - } -} - - -/* -================ -TraceAttack -================ -*/ - -//----------------------------------------------------------------------------- -// Purpose: Returns whether a damage info can damage this entity. -//----------------------------------------------------------------------------- -bool CBaseEntity::PassesDamageFilter( const CTakeDamageInfo &info ) -{ - if (m_hDamageFilter) - { - CBaseFilter *pFilter = (CBaseFilter *)(m_hDamageFilter.Get()); - return pFilter->PassesDamageFilter(info); - } - - return true; -} - -FORCEINLINE bool NamesMatch( const char *pszQuery, string_t nameToMatch ) -{ - if ( nameToMatch == NULL_STRING ) - return (*pszQuery == 0 || *pszQuery == '*'); - - const char *pszNameToMatch = STRING(nameToMatch); - - // If the pointers are identical, we're identical - if ( pszNameToMatch == pszQuery ) - return true; - - while ( *pszNameToMatch && *pszQuery ) - { - char cName = *pszNameToMatch; - char cQuery = *pszQuery; - if ( cName != cQuery && tolower(cName) != tolower(cQuery) ) // people almost always use lowercase, so assume that first - break; - ++pszNameToMatch; - ++pszQuery; - } - - if ( *pszQuery == 0 && *pszNameToMatch == 0 ) - return true; - - // @TODO (toml 03-18-03): Perhaps support real wildcards. Right now, only thing supported is trailing * - if ( *pszQuery == '*' ) - return true; - - return false; -} - -bool CBaseEntity::NameMatchesComplex( const char *pszNameOrWildcard ) -{ - if ( !Q_stricmp( "!player", pszNameOrWildcard) ) - return IsPlayer(); - - return NamesMatch( pszNameOrWildcard, m_iName ); -} - -bool CBaseEntity::ClassMatchesComplex( const char *pszClassOrWildcard ) -{ - return NamesMatch( pszClassOrWildcard, m_iClassname ); -} - -void CBaseEntity::MakeDormant( void ) -{ - AddEFlags( EFL_DORMANT ); - - // disable thinking for dormant entities - SetThink( NULL ); - - if ( !edict() ) - return; - - SETBITS( m_iEFlags, EFL_DORMANT ); - - // Don't touch - AddSolidFlags( FSOLID_NOT_SOLID ); - // Don't move - SetMoveType( MOVETYPE_NONE ); - // Don't draw - AddEffects( EF_NODRAW ); - // Don't think - SetNextThink( TICK_NEVER_THINK ); -} - -int CBaseEntity::IsDormant( void ) -{ - return IsEFlagSet( EFL_DORMANT ); -} - - -bool CBaseEntity::IsInWorld( void ) const -{ - if ( !edict() ) - return true; - - // position - if (GetAbsOrigin().x >= MAX_COORD_INTEGER) return false; - if (GetAbsOrigin().y >= MAX_COORD_INTEGER) return false; - if (GetAbsOrigin().z >= MAX_COORD_INTEGER) return false; - if (GetAbsOrigin().x <= MIN_COORD_INTEGER) return false; - if (GetAbsOrigin().y <= MIN_COORD_INTEGER) return false; - if (GetAbsOrigin().z <= MIN_COORD_INTEGER) return false; - // speed - if (GetAbsVelocity().x >= 2000) return false; - if (GetAbsVelocity().y >= 2000) return false; - if (GetAbsVelocity().z >= 2000) return false; - if (GetAbsVelocity().x <= -2000) return false; - if (GetAbsVelocity().y <= -2000) return false; - if (GetAbsVelocity().z <= -2000) return false; - - return true; -} - - -bool CBaseEntity::IsViewable( void ) -{ - if ( IsEffectActive( EF_NODRAW ) ) - { - return false; - } - - if (IsBSPModel()) - { - if (GetMoveType() != MOVETYPE_NONE) - { - return true; - } - } - else if (GetModelIndex() != 0) - { - // check for total transparency??? - return true; - } - return false; -} - - -int CBaseEntity::ShouldToggle( USE_TYPE useType, int currentState ) -{ - if ( useType != USE_TOGGLE && useType != USE_SET ) - { - if ( (currentState && useType == USE_ON) || (!currentState && useType == USE_OFF) ) - return 0; - } - return 1; -} - - -// NOTE: szName must be a pointer to constant memory, e.g. "NPC_class" because the entity -// will keep a pointer to it after this call. -CBaseEntity *CBaseEntity::Create( const char *szName, const Vector &vecOrigin, const QAngle &vecAngles, CBaseEntity *pOwner ) -{ - CBaseEntity *pEntity = CreateNoSpawn( szName, vecOrigin, vecAngles, pOwner ); - - DispatchSpawn( pEntity ); - return pEntity; -} - - - -// NOTE: szName must be a pointer to constant memory, e.g. "NPC_class" because the entity -// will keep a pointer to it after this call. -CBaseEntity * CBaseEntity::CreateNoSpawn( const char *szName, const Vector &vecOrigin, const QAngle &vecAngles, CBaseEntity *pOwner ) -{ - CBaseEntity *pEntity = CreateEntityByName( szName ); - if ( !pEntity ) - { - Assert( !"CreateNoSpawn: only works for CBaseEntities" ); - return NULL; - } - - pEntity->SetLocalOrigin( vecOrigin ); - pEntity->SetLocalAngles( vecAngles ); - pEntity->SetOwnerEntity( pOwner ); - - gEntList.NotifyCreateEntity( pEntity ); - - return pEntity; -} - -Vector CBaseEntity::GetSoundEmissionOrigin() const -{ - return WorldSpaceCenter(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Saves the current object out to disk, by iterating through the objects -// data description hierarchy -// Input : &save - save buffer which the class data is written to -// Output : int - 0 if the save failed, 1 on success -//----------------------------------------------------------------------------- -int CBaseEntity::Save( ISave &save ) -{ - // loop through the data description list, saving each data desc block - int status = SaveDataDescBlock( save, GetDataDescMap() ); - - return status; -} - -//----------------------------------------------------------------------------- -// Purpose: Recursively saves all the classes in an object, in reverse order (top down) -// Output : int 0 on failure, 1 on success -//----------------------------------------------------------------------------- -int CBaseEntity::SaveDataDescBlock( ISave &save, datamap_t *dmap ) -{ - return save.WriteAll( this, dmap ); -} - -//----------------------------------------------------------------------------- -// Purpose: Restores the current object from disk, by iterating through the objects -// data description hierarchy -// Input : &restore - restore buffer which the class data is read from -// Output : int - 0 if the restore failed, 1 on success -//----------------------------------------------------------------------------- -int CBaseEntity::Restore( IRestore &restore ) -{ - // This is essential to getting the spatial partition info correct - CollisionProp()->DestroyPartitionHandle(); - - // loops through the data description list, restoring each data desc block in order - int status = RestoreDataDescBlock( restore, GetDataDescMap() ); - - // --------------------------------------------------------------- - // HACKHACK: We don't know the space of these vectors until now - // if they are worldspace, fix them up. - // --------------------------------------------------------------- - { - CGameSaveRestoreInfo *pGameInfo = restore.GetGameSaveRestoreInfo(); - Vector parentSpaceOffset = pGameInfo->modelSpaceOffset; - if ( !GetParent() ) - { - // parent is the world, so parent space is worldspace - // so update with the worldspace leveltransition transform - parentSpaceOffset += pGameInfo->GetLandmark(); - } - - // NOTE: Do *not* use GetAbsOrigin() here because it will - // try to recompute m_rgflCoordinateFrame! - MatrixSetColumn( m_vecAbsOrigin, 3, m_rgflCoordinateFrame ); - - m_vecOrigin += parentSpaceOffset; - } - - // Gotta do this after the coordframe is set up as it depends on it. - - // By definition, the surrounding bounds are dirty - // Also, twiddling with the flags here ensures it gets added to the KD tree dirty list - // (We don't want to use the saved version of this flag) - RemoveEFlags( EFL_DIRTY_SPATIAL_PARTITION ); - CollisionProp()->MarkSurroundingBoundsDirty(); - - if ( edict() && GetModelIndex() != 0 && GetModelName() != NULL_STRING && restore.GetPrecacheMode() ) - { - PrecacheModel( STRING( GetModelName() ) ); - - //Adrian: We should only need to do this after we precache. No point in setting the model again. - SetModelIndex( modelinfo->GetModelIndex( STRING(GetModelName() ) ) ); - } - - // Restablish ground entity - if ( m_hGroundEntity != NULL ) - { - m_hGroundEntity->AddEntityToGroundList( this ); - } - - // Tracker 22129 - // This is a hack to make sure that the entity is added to the AddPostClientMessageEntity - // list so that EF_NOINTERP can be cleared at the end of the frame. Otherwise, a restored entity - // with this flag will not interpolate until the next time the flag is set. ywb - if ( IsEffectActive( EF_NOINTERP ) ) - { - AddEffects( EF_NOINTERP ); - } - - return status; -} - - -//----------------------------------------------------------------------------- -// handler to do stuff before you are saved -//----------------------------------------------------------------------------- -void CBaseEntity::OnSave( IEntitySaveUtils *pUtils ) -{ - // Here, we must force recomputation of all abs data so it gets saved correctly - // We can't leave the dirty bits set because the loader can't cope with it. - CalcAbsolutePosition(); - CalcAbsoluteVelocity(); -} - -//----------------------------------------------------------------------------- -// handler to do stuff after you are restored -//----------------------------------------------------------------------------- -void CBaseEntity::OnRestore() -{ - SimThink_EntityChanged( this ); - - // touchlinks get recomputed - if ( IsEFlagSet( EFL_CHECK_UNTOUCH ) ) - { - RemoveEFlags( EFL_CHECK_UNTOUCH ); - SetCheckUntouch( true ); - } - - // disable touch functions while we recreate the touch links between entities - // NOTE: We don't do this on transitions, because we'd miss the OnStartTouch call! -#if !defined(HL2_DLL) || ( defined(HL2_DLL) && defined(HL2_EPISODIC) ) - CBaseEntity::sm_bDisableTouchFuncs = ( gpGlobals->eLoadType != MapLoad_Transition ); - PhysicsTouchTriggers(); - CBaseEntity::sm_bDisableTouchFuncs = false; -#endif // HL2_EPISODIC - - //Adrian: If I'm restoring with these fields it means I've become a client side ragdoll. - //Don't create another one, just wait until is my time of being removed. - if ( GetFlags() & FL_TRANSRAGDOLL ) - { - m_nRenderFX = kRenderFxNone; - AddEffects( EF_NODRAW ); - RemoveFlag( FL_DISSOLVING | FL_ONFIRE ); - } - - if ( m_pParent ) - { - CBaseEntity *pChild = m_pParent->FirstMoveChild(); - while ( pChild ) - { - if ( pChild == this ) - break; - pChild = pChild->NextMovePeer(); - } - if ( pChild != this ) - { -#if _DEBUG - // generally this means you've got something marked FCAP_DONT_SAVE - // in a hierarchy. That's probably ok given this fixup, but the hierarhcy - // linked list is just saved/loaded in-place - Warning("Fixing up parent on %s\n", GetClassname() ); -#endif - // We only need to be back in the parent's list because we're already in the right place and with the right data - LinkChild( m_pParent, this ); - } - } - - // We're not save/loading the PVS dirty state. Assume everything is dirty after a restore - NetworkProp()->MarkPVSInformationDirty(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Recursively restores all the classes in an object, in reverse order (top down) -// Output : int 0 on failure, 1 on success -//----------------------------------------------------------------------------- -int CBaseEntity::RestoreDataDescBlock( IRestore &restore, datamap_t *dmap ) -{ - return restore.ReadAll( this, dmap ); -} - -//----------------------------------------------------------------------------- - -bool CBaseEntity::ShouldSavePhysics() -{ - return true; -} - -//----------------------------------------------------------------------------- - -#include "tier0/memdbgoff.h" - -//----------------------------------------------------------------------------- -// CBaseEntity new/delete -// allocates and frees memory for itself from the engine-> -// All fields in the object are all initialized to 0. -//----------------------------------------------------------------------------- -void *CBaseEntity::operator new( size_t stAllocateBlock ) -{ - // call into engine to get memory - Assert( stAllocateBlock != 0 ); - return engine->PvAllocEntPrivateData(stAllocateBlock); -}; - -void *CBaseEntity::operator new( size_t stAllocateBlock, int nBlockUse, const char *pFileName, int nLine ) -{ - // call into engine to get memory - Assert( stAllocateBlock != 0 ); - return engine->PvAllocEntPrivateData(stAllocateBlock); -} - -void CBaseEntity::operator delete( void *pMem ) -{ - // get the engine to free the memory - engine->FreeEntPrivateData( pMem ); -} - -#include "tier0/memdbgon.h" - - -#ifdef _DEBUG -void CBaseEntity::FunctionCheck( void *pFunction, const char *name ) -{ -#ifdef USES_SAVERESTORE - // Note, if you crash here and your class is using multiple inheritance, it is - // probably the case that CBaseEntity (or a descendant) is not the first - // class in your list of ancestors, which it must be. - if (pFunction && !UTIL_FunctionToName( GetDataDescMap(), pFunction ) ) - { - Warning( "FUNCTION NOT IN TABLE!: %s:%s (%08lx)\n", STRING(m_iClassname), name, (unsigned long)pFunction ); - Assert(0); - } -#endif -} -#endif - - -bool CBaseEntity::TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ) -{ - return false; -} - -//----------------------------------------------------------------------------- -// Perform hitbox test, returns true *if hitboxes were tested at all*!! -//----------------------------------------------------------------------------- -bool CBaseEntity::TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ) -{ - return false; -} - - -void CBaseEntity::SetOwnerEntity( CBaseEntity* pOwner ) -{ - if ( m_hOwnerEntity.Get() != pOwner ) - { - m_hOwnerEntity = pOwner; - - CollisionRulesChanged(); - } -} - -void CBaseEntity::SetMoveType( MoveType_t val, MoveCollide_t moveCollide ) -{ -#ifdef _DEBUG - // Make sure the move type + move collide are compatible... - if ((val != MOVETYPE_FLY) && (val != MOVETYPE_FLYGRAVITY)) - { - Assert( moveCollide == MOVECOLLIDE_DEFAULT ); - } - - if ( m_MoveType == MOVETYPE_VPHYSICS && val != m_MoveType ) - { - if ( VPhysicsGetObject() && val != MOVETYPE_NONE ) - { - // What am I supposed to do with the physics object if - // you're changing away from MOVETYPE_VPHYSICS without making the object - // shadow? This isn't likely to work, assert. - // You probably meant to call VPhysicsInitShadow() instead of VPhysicsInitNormal()! - Assert( VPhysicsGetObject()->GetShadowController() ); - } - } -#endif - - if ( m_MoveType == val ) - { - m_MoveCollide = moveCollide; - return; - } - - // This is needed to the removal of MOVETYPE_FOLLOW: - // We can't transition from follow to a different movetype directly - // or the leaf code will break. - Assert( !IsEffectActive( EF_BONEMERGE ) ); - m_MoveType = val; - m_MoveCollide = moveCollide; - - CollisionRulesChanged(); - - switch( m_MoveType ) - { - case MOVETYPE_WALK: - { - SetSimulatedEveryTick( true ); - SetAnimatedEveryTick( true ); - } - break; - case MOVETYPE_STEP: - { - // This will probably go away once I remove the cvar that controls the test code - SetSimulatedEveryTick( g_bTestMoveTypeStepSimulation ? true : false ); - SetAnimatedEveryTick( false ); - } - break; - case MOVETYPE_FLY: - case MOVETYPE_FLYGRAVITY: - { - // Initialize our water state, because these movetypes care about transitions in/out of water - UpdateWaterState(); - } - break; - default: - { - SetSimulatedEveryTick( true ); - SetAnimatedEveryTick( false ); - } - } - - // This will probably go away or be handled in a better way once I remove the cvar that controls the test code - CheckStepSimulationChanged(); - CheckHasGamePhysicsSimulation(); -} - -void CBaseEntity::Spawn( void ) -{ -} - - -CBaseEntity* CBaseEntity::Instance( const CBaseHandle &hEnt ) -{ - return gEntList.GetBaseEntity( hEnt ); -} - -int CBaseEntity::GetTransmitState( void ) -{ - edict_t *ed = edict(); - - if ( !ed ) - return 0; - - return ed->m_fStateFlags; -} - -int CBaseEntity::SetTransmitState( int nFlag) -{ - edict_t *ed = edict(); - - if ( !ed ) - return 0; - - // clear current flags = check ShouldTransmit() - ed->ClearTransmitState(); - - int oldFlags = ed->m_fStateFlags; - ed->m_fStateFlags |= nFlag; - - // Tell the engine (used for a network backdoor optimization). - if ( (oldFlags & FL_EDICT_DONTSEND) != (ed->m_fStateFlags & FL_EDICT_DONTSEND) ) - engine->NotifyEdictFlagsChange( entindex() ); - - return ed->m_fStateFlags; -} - -int CBaseEntity::UpdateTransmitState() -{ - // If you get this assert, you should be calling DispatchUpdateTransmitState - // instead of UpdateTransmitState. - Assert( g_nInsideDispatchUpdateTransmitState > 0 ); - - // If an object is the moveparent of something else, don't skip it just because it's marked EF_NODRAW or else - // the client won't have a proper origin for the child since the hierarchy won't be correctly transmitted down - if ( IsEffectActive( EF_NODRAW ) && - !m_hMoveChild.Get() ) - { - return SetTransmitState( FL_EDICT_DONTSEND ); - } - - if ( !IsEFlagSet( EFL_FORCE_CHECK_TRANSMIT ) ) - { - if ( !GetModelIndex() || !GetModelName() ) - { - return SetTransmitState( FL_EDICT_DONTSEND ); - } - } - - // Always send the world - if ( GetModelIndex() == 1 ) - { - return SetTransmitState( FL_EDICT_ALWAYS ); - } - - if ( IsEFlagSet( EFL_IN_SKYBOX ) ) - { - return SetTransmitState( FL_EDICT_ALWAYS ); - } - - // by default cull against PVS - return SetTransmitState( FL_EDICT_PVSCHECK ); -} - -int CBaseEntity::DispatchUpdateTransmitState() -{ - edict_t *ed = edict(); - if ( m_nTransmitStateOwnedCounter != 0 ) - return ed ? ed->m_fStateFlags : 0; - - g_nInsideDispatchUpdateTransmitState++; - int ret = UpdateTransmitState(); - g_nInsideDispatchUpdateTransmitState--; - - return ret; -} - -//----------------------------------------------------------------------------- -// Purpose: Note, an entity can override the send table ( e.g., to send less data or to send minimal data for -// objects ( prob. players ) that are not in the pvs. -// Input : **ppSendTable - -// *recipient - -// *pvs - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -int CBaseEntity::ShouldTransmit( const CCheckTransmitInfo *pInfo ) -{ - int fFlags = DispatchUpdateTransmitState(); - - if ( fFlags & FL_EDICT_PVSCHECK ) - { - return FL_EDICT_PVSCHECK; - } - else if ( fFlags & FL_EDICT_ALWAYS ) - { - return FL_EDICT_ALWAYS; - } - else if ( fFlags & FL_EDICT_DONTSEND ) - { - return FL_EDICT_DONTSEND; - } - -// if ( IsToolRecording() ) -// { -// return FL_EDICT_ALWAYS; -// } - - CBaseEntity *pRecipientEntity = CBaseEntity::Instance( pInfo->m_pClientEnt ); - - Assert( pRecipientEntity->IsPlayer() ); - - CBasePlayer *pRecipientPlayer = static_cast( pRecipientEntity ); - - - // FIXME: Refactor once notion of "team" is moved into HL2 code - // Team rules may tell us that we should - if ( pRecipientPlayer->GetTeam() ) - { - if ( pRecipientPlayer->GetTeam()->ShouldTransmitToPlayer( pRecipientPlayer, this )) - return FL_EDICT_ALWAYS; - } - - -/*#ifdef INVASION_DLL - // Check test network vis distance stuff. Eventually network LOD will do this. - float flTestDistSqr = pRecipientEntity->GetAbsOrigin().DistToSqr( WorldSpaceCenter() ); - if ( flTestDistSqr > sv_netvisdist.GetFloat() * sv_netvisdist.GetFloat() ) - return TRANSMIT_NO; // TODO doesn't work with HLTV -#endif*/ - - // by default do a PVS check - - return FL_EDICT_PVSCHECK; -} - - -//----------------------------------------------------------------------------- -// Rules about which entities need to transmit along with me -//----------------------------------------------------------------------------- -void CBaseEntity::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ) -{ - int index = entindex(); - - // Are we already marked for transmission? - if ( pInfo->m_pTransmitEdict->Get( index ) ) - return; - - CServerNetworkProperty *pNetworkParent = NetworkProp()->GetNetworkParent(); - - pInfo->m_pTransmitEdict->Set( index ); - - // HLTV needs to know if this entity is culled by PVS limits - if ( pInfo->m_pTransmitAlways ) - { - // in HLTV mode always transmit entitys with move-parents - // HLTV can't resolve the mode-parents relationships - if ( bAlways || pNetworkParent ) - { - // tell HLTV that this entity is always transmitted - pInfo->m_pTransmitAlways->Set( index ); - } - else - { - // HLTV will PVS cull this entity, so update the - // node/cluster infos if necessary - m_Network.RecomputePVSInformation(); - } - } - - // Force our aiment and move parent to be sent. - if ( pNetworkParent ) - { - CBaseEntity *pMoveParent = pNetworkParent->GetBaseEntity(); - pMoveParent->SetTransmit( pInfo, bAlways ); - } -} - - -//----------------------------------------------------------------------------- -// Returns which skybox the entity is in -//----------------------------------------------------------------------------- -CSkyCamera *CBaseEntity::GetEntitySkybox() -{ - int area = engine->GetArea( WorldSpaceCenter() ); - - CSkyCamera *pCur = GetSkyCameraList(); - while ( pCur ) - { - if ( engine->CheckAreasConnected( area, pCur->m_skyboxData.area ) ) - return pCur; - - pCur = pCur->m_pNext; - } - - return NULL; -} - -bool CBaseEntity::DetectInSkybox() -{ - if ( GetEntitySkybox() != NULL ) - { - AddEFlags( EFL_IN_SKYBOX ); - return true; - } - - RemoveEFlags( EFL_IN_SKYBOX ); - return false; -} - - -//------------------------------------------------------------------------------ -// Computes a world-aligned bounding box that surrounds everything in the entity -//------------------------------------------------------------------------------ -void CBaseEntity::ComputeWorldSpaceSurroundingBox( Vector *pMins, Vector *pMaxs ) -{ - // Should never get here.. only use USE_GAME_CODE with bounding boxes - // if you have an implementation for this method - Assert( 0 ); -} - - -//------------------------------------------------------------------------------ -// Purpose : If name exists returns name, otherwise returns classname -// Input : -// Output : -//------------------------------------------------------------------------------ -const char *CBaseEntity::GetDebugName(void) -{ - if ( this == NULL ) - return "<>"; - - if ( m_iName != NULL_STRING ) - { - return STRING(m_iName); - } - else - { - return STRING(m_iClassname); - } -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBaseEntity::DrawInputOverlay(const char *szInputName, CBaseEntity *pCaller, variant_t Value) -{ - char bigstring[1024]; - if ( Value.FieldType() == FIELD_INTEGER ) - { - Q_snprintf( bigstring,sizeof(bigstring), "%3.1f (%s,%d) <-- (%s)\n", gpGlobals->curtime, szInputName, Value.Int(), pCaller ? pCaller->GetDebugName() : NULL); - } - else if ( Value.FieldType() == FIELD_STRING ) - { - Q_snprintf( bigstring,sizeof(bigstring), "%3.1f (%s,%s) <-- (%s)\n", gpGlobals->curtime, szInputName, Value.String(), pCaller ? pCaller->GetDebugName() : NULL); - } - else - { - Q_snprintf( bigstring,sizeof(bigstring), "%3.1f (%s) <-- (%s)\n", gpGlobals->curtime, szInputName, pCaller ? pCaller->GetDebugName() : NULL); - } - AddTimedOverlay(bigstring, 10); - - if ( Value.FieldType() == FIELD_INTEGER ) - { - DevMsg( 2, "input: (%s,%d) -> (%s,%s), from (%s)\n", szInputName, Value.Int(), STRING(m_iClassname), GetDebugName(), pCaller ? pCaller->GetDebugName() : NULL); - } - else if ( Value.FieldType() == FIELD_STRING ) - { - DevMsg( 2, "input: (%s,%s) -> (%s,%s), from (%s)\n", szInputName, Value.String(), STRING(m_iClassname), GetDebugName(), pCaller ? pCaller->GetDebugName() : NULL); - } - else - DevMsg( 2, "input: (%s) -> (%s,%s), from (%s)\n", szInputName, STRING(m_iClassname), GetDebugName(), pCaller ? pCaller->GetDebugName() : NULL); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBaseEntity::DrawOutputOverlay(CEventAction *ev) -{ - // Print to entity - char bigstring[1024]; - if ( ev->m_flDelay ) - { - Q_snprintf( bigstring,sizeof(bigstring), "%3.1f (%s) --> (%s),%.1f) \n", gpGlobals->curtime, STRING(ev->m_iTargetInput), STRING(ev->m_iTarget), ev->m_flDelay); - } - else - { - Q_snprintf( bigstring,sizeof(bigstring), "%3.1f (%s) --> (%s)\n", gpGlobals->curtime, STRING(ev->m_iTargetInput), STRING(ev->m_iTarget)); - } - AddTimedOverlay(bigstring, 10); - - // Now print to the console - if ( ev->m_flDelay ) - { - DevMsg( 2, "output: (%s,%s) -> (%s,%s,%.1f)\n", STRING(m_iClassname), GetDebugName(), STRING(ev->m_iTarget), STRING(ev->m_iTargetInput), ev->m_flDelay ); - } - else - { - DevMsg( 2, "output: (%s,%s) -> (%s,%s)\n", STRING(m_iClassname), GetDebugName(), STRING(ev->m_iTarget), STRING(ev->m_iTargetInput) ); - } -} - - -//----------------------------------------------------------------------------- -// Entity events... these are events targetted to a particular entity -// Each event defines its own well-defined event data structure -//----------------------------------------------------------------------------- -void CBaseEntity::OnEntityEvent( EntityEvent_t event, void *pEventData ) -{ - switch( event ) - { - case ENTITY_EVENT_WATER_TOUCH: - { - int nContents = (int)pEventData; - if ( !nContents || (nContents & CONTENTS_WATER) ) - { - ++m_nWaterTouch; - } - if ( nContents & CONTENTS_SLIME ) - { - ++m_nSlimeTouch; - } - } - break; - - case ENTITY_EVENT_WATER_UNTOUCH: - { - int nContents = (int)pEventData; - if ( !nContents || (nContents & CONTENTS_WATER) ) - { - --m_nWaterTouch; - } - if ( nContents & CONTENTS_SLIME ) - { - --m_nSlimeTouch; - } - } - break; - - default: - return; - } - - // Only do this for vphysics objects - if ( GetMoveType() != MOVETYPE_VPHYSICS ) - return; - - int nNewContents = 0; - if ( m_nWaterTouch > 0 ) - { - nNewContents |= CONTENTS_WATER; - } - - if ( m_nSlimeTouch > 0 ) - { - nNewContents |= CONTENTS_SLIME; - } - - if (( nNewContents & MASK_WATER ) == 0) - { - SetWaterLevel( 0 ); - SetWaterType( CONTENTS_EMPTY ); - return; - } - - SetWaterLevel( 1 ); - SetWaterType( nNewContents ); -} - - -ConVar ent_messages_draw( "ent_messages_draw", "0", FCVAR_CHEAT, "Visualizes all entity input/output activity." ); - - -//----------------------------------------------------------------------------- -// Purpose: calls the appropriate message mapped function in the entity according -// to the fired action. -// Input : char *szInputName - input destination -// *pActivator - entity which initiated this sequence of actions -// *pCaller - entity from which this event is sent -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseEntity::AcceptInput( const char *szInputName, CBaseEntity *pActivator, CBaseEntity *pCaller, variant_t Value, int outputID ) -{ - if ( ent_messages_draw.GetBool() ) - { - if ( pCaller != NULL ) - { - NDebugOverlay::Line( pCaller->GetAbsOrigin(), GetAbsOrigin(), 255, 255, 255, false, 3 ); - NDebugOverlay::Box( pCaller->GetAbsOrigin(), Vector(-4, -4, -4), Vector(4, 4, 4), 255, 0, 0, 0, 3 ); - } - - NDebugOverlay::Text( GetAbsOrigin(), szInputName, false, 3 ); - NDebugOverlay::Box( GetAbsOrigin(), Vector(-4, -4, -4), Vector(4, 4, 4), 0, 255, 0, 0, 3 ); - } - - // loop through the data description list, restoring each data desc block - for ( datamap_t *dmap = GetDataDescMap(); dmap != NULL; dmap = dmap->baseMap ) - { - // search through all the actions in the data description, looking for a match - for ( int i = 0; i < dmap->dataNumFields; i++ ) - { - if ( dmap->dataDesc[i].flags & FTYPEDESC_INPUT ) - { - if ( !Q_stricmp(dmap->dataDesc[i].externalName, szInputName) ) - { - // found a match - - char szBuffer[256]; - // mapper debug message - if (pCaller != NULL) - { - Q_snprintf( szBuffer, sizeof(szBuffer), "(%0.2f) input %s: %s.%s(%s)\n", gpGlobals->curtime, STRING(pCaller->m_iName), GetDebugName(), szInputName, Value.String() ); - } - else - { - Q_snprintf( szBuffer, sizeof(szBuffer), "(%0.2f) input : %s.%s(%s)\n", gpGlobals->curtime, GetDebugName(), szInputName, Value.String() ); - } - DevMsg( 2, szBuffer ); - ADD_DEBUG_HISTORY( HISTORY_ENTITY_IO, szBuffer ); - - if (m_debugOverlays & OVERLAY_MESSAGE_BIT) - { - DrawInputOverlay(szInputName,pCaller,Value); - } - - // convert the value if necessary - if ( Value.FieldType() != dmap->dataDesc[i].fieldType ) - { - if ( !(Value.FieldType() == FIELD_VOID && dmap->dataDesc[i].fieldType == FIELD_STRING) ) // allow empty strings - { - if ( !Value.Convert( (fieldtype_t)dmap->dataDesc[i].fieldType ) ) - { - // bad conversion - Warning( "!! ERROR: bad input/output link:\n!! %s(%s,%s) doesn't match type from %s(%s)\n", - STRING(m_iClassname), GetDebugName(), szInputName, - ( pCaller != NULL ) ? STRING(pCaller->m_iClassname) : "", - ( pCaller != NULL ) ? STRING(pCaller->m_iName) : "" ); - return false; - } - } - } - - // call the input handler, or if there is none just set the value - inputfunc_t pfnInput = dmap->dataDesc[i].inputFunc; - - if ( pfnInput ) - { - // Package the data into a struct for passing to the input handler. - inputdata_t data; - data.pActivator = pActivator; - data.pCaller = pCaller; - data.value = Value; - data.nOutputID = outputID; - - (this->*pfnInput)( data ); - } - else if ( dmap->dataDesc[i].flags & FTYPEDESC_KEY ) - { - // set the value directly - Value.SetOther( ((char*)this) + dmap->dataDesc[i].fieldOffset[ TD_OFFSET_NORMAL ]); - - // TODO: if this becomes evil and causes too many full entity updates, then we should make - // a macro like this: - // - // define MAKE_INPUTVAR(x) void Note##x##Modified() { x.GetForModify(); } - // - // Then the datadesc points at that function and we call it here. The only pain is to add - // that function for all the DEFINE_INPUT calls. - NetworkStateChanged(); - } - - return true; - } - } - } - } - - DevMsg( 2, "unhandled input: (%s) -> (%s,%s)\n", szInputName, STRING(m_iClassname), GetDebugName()/*,", from (%s,%s)" STRING(pCaller->m_iClassname), STRING(pCaller->m_iName)*/ ); - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for the entity alpha. -// Input : nAlpha - Alpha value (0 - 255). -//----------------------------------------------------------------------------- -void CBaseEntity::InputAlpha( inputdata_t &inputdata ) -{ - SetRenderColorA( clamp( inputdata.value.Int(), 0, 255 ) ); -} - - -//----------------------------------------------------------------------------- -// Activate alternative sorting -//----------------------------------------------------------------------------- -void CBaseEntity::InputAlternativeSorting( inputdata_t &inputdata ) -{ - m_bAlternateSorting = inputdata.value.Bool(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for the entity color. Ignores alpha since that is handled -// by a separate input handler. -// Input : Color32 new value for color (alpha is ignored). -//----------------------------------------------------------------------------- -void CBaseEntity::InputColor( inputdata_t &inputdata ) -{ - color32 clr = inputdata.value.Color32(); - - SetRenderColor( clr.r, clr.g, clr.b ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Called whenever the entity is 'Used'. This can be when a player hits -// use, or when an entity targets it without an output name (legacy entities) -//----------------------------------------------------------------------------- -void CBaseEntity::InputUse( inputdata_t &inputdata ) -{ - Use( inputdata.pActivator, inputdata.pCaller, (USE_TYPE)inputdata.nOutputID, 0 ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Reads an output variable, by string name, from an entity -// Input : char *varName - the string name of the variable -// variant_t *var - the value is stored here -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseEntity::ReadKeyField( const char *varName, variant_t *var ) -{ - if ( !varName ) - return false; - - // loop through the data description list, restoring each data desc block - for ( datamap_t *dmap = GetDataDescMap(); dmap != NULL; dmap = dmap->baseMap ) - { - // search through all the readable fields in the data description, looking for a match - for ( int i = 0; i < dmap->dataNumFields; i++ ) - { - if ( dmap->dataDesc[i].flags & (FTYPEDESC_OUTPUT | FTYPEDESC_KEY) ) - { - if ( !Q_stricmp(dmap->dataDesc[i].externalName, varName) ) - { - var->Set( dmap->dataDesc[i].fieldType, ((char*)this) + dmap->dataDesc[i].fieldOffset[ TD_OFFSET_NORMAL ] ); - return true; - } - } - } - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Sets the damage filter on the object -//----------------------------------------------------------------------------- -void CBaseEntity::InputEnableDamageForces( inputdata_t &inputdata ) -{ - RemoveEFlags( EFL_NO_DAMAGE_FORCES ); -} - -void CBaseEntity::InputDisableDamageForces( inputdata_t &inputdata ) -{ - AddEFlags( EFL_NO_DAMAGE_FORCES ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Sets the damage filter on the object -//----------------------------------------------------------------------------- -void CBaseEntity::InputSetDamageFilter( inputdata_t &inputdata ) -{ - // Get a handle to my damage filter entity if there is one. - m_iszDamageFilterName = inputdata.value.StringID(); - if ( m_iszDamageFilterName != NULL_STRING ) - { - m_hDamageFilter = gEntList.FindEntityByName( NULL, m_iszDamageFilterName ); - } - else - { - m_hDamageFilter = NULL; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Dispatch effects on this entity -//----------------------------------------------------------------------------- -void CBaseEntity::InputDispatchEffect( inputdata_t &inputdata ) -{ - const char *sEffect = inputdata.value.String(); - if ( sEffect && sEffect[0] ) - { - CEffectData data; - GetInputDispatchEffectPosition( sEffect, data.m_vOrigin, data.m_vAngles ); - AngleVectors( data.m_vAngles, &data.m_vNormal ); - data.m_vStart = data.m_vOrigin; - data.m_nEntIndex = entindex(); - - // Clip off leading attachment point numbers - while ( sEffect[0] >= '0' && sEffect[0] <= '9' ) - { - sEffect++; - } - DispatchEffect( sEffect, data ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the origin at which to play an inputted dispatcheffect -//----------------------------------------------------------------------------- -void CBaseEntity::GetInputDispatchEffectPosition( const char *sInputString, Vector &pOrigin, QAngle &pAngles ) -{ - pOrigin = GetAbsOrigin(); - pAngles = GetAbsAngles(); -} - -//----------------------------------------------------------------------------- -// Purpose: Marks the entity for deletion -//----------------------------------------------------------------------------- -void CBaseEntity::InputKill( inputdata_t &inputdata ) -{ - // tell owner ( if any ) that we're dead.This is mostly for NPCMaker functionality. - CBaseEntity *pOwner = GetOwnerEntity(); - if ( pOwner ) - { - pOwner->DeathNotice( this ); - SetOwnerEntity( NULL ); - } - - UTIL_Remove( this ); -} - -void CBaseEntity::InputKillHierarchy( inputdata_t &inputdata ) -{ - CBaseEntity *pChild, *pNext; - for ( pChild = FirstMoveChild(); pChild; pChild = pNext ) - { - pNext = pChild->NextMovePeer(); - pChild->InputKillHierarchy( inputdata ); - } - - // tell owner ( if any ) that we're dead. This is mostly for NPCMaker functionality. - CBaseEntity *pOwner = GetOwnerEntity(); - if ( pOwner ) - { - pOwner->DeathNotice( this ); - SetOwnerEntity( NULL ); - } - - UTIL_Remove( this ); -} - -//------------------------------------------------------------------------------ -// Purpose: Input handler for changing this entity's movement parent. -//------------------------------------------------------------------------------ -void CBaseEntity::InputSetParent( inputdata_t &inputdata ) -{ - // If we had a parent attachment, clear it, because it's no longer valid. - if ( m_iParentAttachment ) - { - m_iParentAttachment = 0; - } - - SetParent( inputdata.value.StringID(), inputdata.pActivator ); -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CBaseEntity::SetParentAttachment( const char *szInputName, const char *szAttachment, bool bMaintainOffset ) -{ - // Must have a parent - if ( !m_pParent ) - { - Warning("ERROR: Tried to %s for entity %s (%s), but it has no parent.\n", szInputName, GetClassname(), GetDebugName() ); - return; - } - - // Valid only on CBaseAnimating - CBaseAnimating *pAnimating = m_pParent->GetBaseAnimating(); - if ( !pAnimating ) - { - Warning("ERROR: Tried to %s for entity %s (%s), but its parent has no model.\n", szInputName, GetClassname(), GetDebugName() ); - return; - } - - // Lookup the attachment - int iAttachment = pAnimating->LookupAttachment( szAttachment ); - if ( !iAttachment ) - { - Warning("ERROR: Tried to %s for entity %s (%s), but it has no attachment named %s.\n", szInputName, GetClassname(), GetDebugName(), szAttachment ); - return; - } - - m_iParentAttachment = iAttachment; - SetParent( m_pParent, m_iParentAttachment ); - - // Now move myself directly onto the attachment point - SetMoveType( MOVETYPE_NONE ); - - if ( !bMaintainOffset ) - { - SetLocalOrigin( vec3_origin ); - SetLocalAngles( vec3_angle ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for changing this entity's movement parent's attachment point -//----------------------------------------------------------------------------- -void CBaseEntity::InputSetParentAttachment( inputdata_t &inputdata ) -{ - SetParentAttachment( "SetParentAttachment", inputdata.value.String(), false ); -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for changing this entity's movement parent's attachment point -//----------------------------------------------------------------------------- -void CBaseEntity::InputSetParentAttachmentMaintainOffset( inputdata_t &inputdata ) -{ - SetParentAttachment( "SetParentAttachmentMaintainOffset", inputdata.value.String(), true ); -} - -//------------------------------------------------------------------------------ -// Purpose: Input handler for clearing this entity's movement parent. -//------------------------------------------------------------------------------ -void CBaseEntity::InputClearParent( inputdata_t &inputdata ) -{ - SetParent( NULL ); -} - - -//------------------------------------------------------------------------------ -// Purpose : Returns velcocity of base entity. If physically simulated gets -// velocity from physics object -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBaseEntity::GetVelocity(Vector *vVelocity, AngularImpulse *vAngVelocity) -{ - if (GetMoveType()==MOVETYPE_VPHYSICS && m_pPhysicsObject) - { - m_pPhysicsObject->GetVelocity(vVelocity,vAngVelocity); - } - else - { - if (vVelocity != NULL) - { - *vVelocity = GetAbsVelocity(); - } - if (vAngVelocity != NULL) - { - QAngle tmp = GetLocalAngularVelocity(); - QAngleToAngularImpulse( tmp, *vAngVelocity ); - } - } -} - -bool CBaseEntity::IsMoving() -{ - Vector velocity; - GetVelocity( &velocity, NULL ); - return velocity != vec3_origin; -} - -//----------------------------------------------------------------------------- -// Purpose: Retrieves the coordinate frame for this entity. -// Input : forward - Receives the entity's forward vector. -// right - Receives the entity's right vector. -// up - Receives the entity's up vector. -//----------------------------------------------------------------------------- -void CBaseEntity::GetVectors(Vector* pForward, Vector* pRight, Vector* pUp) const -{ - // This call is necessary to cause m_rgflCoordinateFrame to be recomputed - const matrix3x4_t &entityToWorld = EntityToWorldTransform(); - - if (pForward != NULL) - { - MatrixGetColumn( entityToWorld, 0, *pForward ); - } - - if (pRight != NULL) - { - MatrixGetColumn( entityToWorld, 1, *pRight ); - *pRight *= -1.0f; - } - - if (pUp != NULL) - { - MatrixGetColumn( entityToWorld, 2, *pUp ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Sets the model, validates that it's of the appropriate type -// Input : *szModelName - -//----------------------------------------------------------------------------- -void CBaseEntity::SetModel( const char *szModelName ) -{ - int modelIndex = modelinfo->GetModelIndex( szModelName ); - const model_t *model = modelinfo->GetModel( modelIndex ); - if ( model && modelinfo->GetModelType( model ) != mod_brush ) - { - Msg( "Setting CBaseEntity to non-brush model %s\n", szModelName ); - } - UTIL_SetModel( this, szModelName ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Called once per frame after the server frame loop has finished and after all messages being -// sent to clients have been sent. NOTE: Only called if scheduled via AddPostClientMessageEntity() ! -//----------------------------------------------------------------------------- -void CBaseEntity::PostClientMessagesSent( void ) -{ - // Remove nointerp flags from entity after every frame - if ( IsEffectActive( EF_NOINTERP ) ) - { - RemoveEffects( EF_NOINTERP ); - } -} - -//================================================================================ -// TEAM HANDLING -//================================================================================ -void CBaseEntity::InputSetTeam( inputdata_t &inputdata ) -{ - ChangeTeam( inputdata.value.Int() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Put the entity in the specified team -//----------------------------------------------------------------------------- -void CBaseEntity::ChangeTeam( int iTeamNum ) -{ - m_iTeamNum = iTeamNum; -} - -//----------------------------------------------------------------------------- -// Get the Team this entity is on -//----------------------------------------------------------------------------- -CTeam *CBaseEntity::GetTeam( void ) const -{ - return GetGlobalTeam( m_iTeamNum ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns true if these players are both in at least one team together -//----------------------------------------------------------------------------- -bool CBaseEntity::InSameTeam( CBaseEntity *pEntity ) const -{ - if ( !pEntity ) - return false; - - return ( pEntity->GetTeam() == GetTeam() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the string name of the players team -//----------------------------------------------------------------------------- -const char *CBaseEntity::TeamID( void ) const -{ - if ( GetTeam() == NULL ) - return ""; - - return GetTeam()->GetName(); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true if the player is on the same team -//----------------------------------------------------------------------------- -bool CBaseEntity::IsInTeam( CTeam *pTeam ) const -{ - return ( GetTeam() == pTeam ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBaseEntity::GetTeamNumber( void ) const -{ - return m_iTeamNum; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseEntity::IsInAnyTeam( void ) const -{ - return ( GetTeam() != NULL ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the type of damage that this entity inflicts. -//----------------------------------------------------------------------------- -int CBaseEntity::GetDamageType() const -{ - return DMG_GENERIC; -} - - -//----------------------------------------------------------------------------- -// process notification -//----------------------------------------------------------------------------- - -void CBaseEntity::NotifySystemEvent( CBaseEntity *pNotify, notify_system_event_t eventType, const notify_system_event_params_t ¶ms ) -{ -} - - -//----------------------------------------------------------------------------- -// Purpose: Holds an entity's previous abs origin and angles at the time of -// teleportation. Used for child & constrained entity fixup to prevent -// lazy updates of abs origins and angles from messing things up. -//----------------------------------------------------------------------------- -struct TeleportListEntry_t -{ - CBaseEntity *pEntity; - Vector prevAbsOrigin; - QAngle prevAbsAngles; -}; - - -static void TeleportEntity( CBaseEntity *pSourceEntity, TeleportListEntry_t &entry, const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ) -{ - CBaseEntity *pTeleport = entry.pEntity; - Vector prevOrigin = entry.prevAbsOrigin; - QAngle prevAngles = entry.prevAbsAngles; - - int nSolidFlags = pTeleport->GetSolidFlags(); - pTeleport->AddSolidFlags( FSOLID_NOT_SOLID ); - - // I'm teleporting myself - if ( pSourceEntity == pTeleport ) - { - if ( newAngles ) - { - pTeleport->SetLocalAngles( *newAngles ); - if ( pTeleport->IsPlayer() ) - { - CBasePlayer *pPlayer = (CBasePlayer *)pTeleport; - pPlayer->SnapEyeAngles( *newAngles ); - } - } - - if ( newVelocity ) - { - pTeleport->SetAbsVelocity( *newVelocity ); - pTeleport->SetBaseVelocity( vec3_origin ); - } - - if ( newPosition ) - { - pTeleport->AddEffects( EF_NOINTERP ); - UTIL_SetOrigin( pTeleport, *newPosition ); - } - } - else - { - // My parent is teleporting, just update my position & physics - pTeleport->CalcAbsolutePosition(); - } - IPhysicsObject *pPhys = pTeleport->VPhysicsGetObject(); - bool rotatePhysics = false; - - // handle physics objects / shadows - if ( pPhys ) - { - if ( newVelocity ) - { - pPhys->SetVelocity( newVelocity, NULL ); - } - const QAngle *rotAngles = &pTeleport->GetAbsAngles(); - // don't rotate physics on players or bbox entities - if (pTeleport->IsPlayer() || pTeleport->GetSolid() == SOLID_BBOX ) - { - rotAngles = &vec3_angle; - } - else - { - rotatePhysics = true; - } - - pPhys->SetPosition( pTeleport->GetAbsOrigin(), *rotAngles, true ); - } - - g_pNotify->ReportTeleportEvent( pTeleport, prevOrigin, prevAngles, rotatePhysics ); - - pTeleport->SetSolidFlags( nSolidFlags ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Recurses an entity hierarchy and fills out a list of all entities -// in the hierarchy with their current origins and angles. -// -// This list is necessary to keep lazy updates of abs origins and angles -// from messing up our child/constrained entity fixup. -//----------------------------------------------------------------------------- -static void BuildTeleportList_r( CBaseEntity *pTeleport, CUtlVector &teleportList ) -{ - TeleportListEntry_t entry; - - entry.pEntity = pTeleport; - entry.prevAbsOrigin = pTeleport->GetAbsOrigin(); - entry.prevAbsAngles = pTeleport->GetAbsAngles(); - - teleportList.AddToTail( entry ); - - CBaseEntity *pList = pTeleport->FirstMoveChild(); - while ( pList ) - { - BuildTeleportList_r( pList, teleportList ); - pList = pList->NextMovePeer(); - } -} - - -static CUtlVector g_TeleportStack; -void CBaseEntity::Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ) -{ - if ( g_TeleportStack.Find( this ) >= 0 ) - return; - int index = g_TeleportStack.AddToTail( this ); - - CUtlVector teleportList; - BuildTeleportList_r( this, teleportList ); - - int i; - for ( i = 0; i < teleportList.Count(); i++) - { - TeleportEntity( this, teleportList[i], newPosition, newAngles, newVelocity ); - } - - for (i = 0; i < teleportList.Count(); i++) - { - teleportList[i].pEntity->CollisionRulesChanged(); - } - - Assert( g_TeleportStack[index] == this ); - g_TeleportStack.FastRemove( index ); - - // FIXME: add an initializer function to StepSimulationData - StepSimulationData *step = ( StepSimulationData * )GetDataObject( STEPSIMULATION ); - if (step) - { - Q_memset( step, 0, sizeof( *step ) ); - } -} - -// Stuff implemented for weapon prediction code -void CBaseEntity::SetSize( const Vector &vecMin, const Vector &vecMax ) -{ - UTIL_SetSize( this, vecMin, vecMax ); -} - -CStudioHdr *ModelSoundsCache_LoadModel( const char *filename ) -{ - // Load the file - int idx = engine->PrecacheModel( filename, true ); - if ( idx != -1 ) - { - model_t *mdl = (model_t *)modelinfo->GetModel( idx ); - if ( mdl ) - { - CStudioHdr *studioHdr = new CStudioHdr( modelinfo->GetStudiomodel( mdl ), mdlcache ); - if ( studioHdr->IsValid() ) - { - return studioHdr; - } - } - } - return NULL; -} - -void ModelSoundsCache_FinishModel( CStudioHdr *hdr ) -{ - Assert( hdr ); - delete hdr; -} - -void ModelSoundsCache_PrecacheScriptSound( const char *soundname ) -{ - CBaseEntity::PrecacheScriptSound( soundname ); -} - -static CUtlCachedFileData< CModelSoundsCache > g_ModelSoundsCache( "modelsounds.cache", MODELSOUNDSCACHE_VERSION, 0, UTL_CACHED_FILE_USE_FILESIZE, false ); - -void ClearModelSoundsCache() -{ - if ( IsX360() ) - { - return; - } - - g_ModelSoundsCache.Reload(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool ModelSoundsCacheInit() -{ - if ( IsX360() ) - { - return true; - } - - return g_ModelSoundsCache.Init(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void ModelSoundsCacheShutdown() -{ - if ( IsX360() ) - { - return; - } - - g_ModelSoundsCache.Shutdown(); -} - -static CUtlSymbolTable g_ModelSoundsSymbolHelper( 0, 32, true ); -class CModelSoundsCacheSaver: public CAutoGameSystem -{ -public: - CModelSoundsCacheSaver( const char *name ) : CAutoGameSystem( name ) - { - } - virtual void LevelInitPostEntity() - { - if ( IsX360() ) - { - return; - } - - if ( g_ModelSoundsCache.IsDirty() ) - { - g_ModelSoundsCache.Save(); - } - } - virtual void LevelShutdownPostEntity() - { - if ( IsX360() ) - { - // Unforunate that this table must persist through duration of level. - // It is the common case that PrecacheModel() still gets called (and needs this table), - // after LevelInitPostEntity, as PrecacheModel() redundantly precaches. - g_ModelSoundsSymbolHelper.RemoveAll(); - return; - } - - if ( g_ModelSoundsCache.IsDirty() ) - { - g_ModelSoundsCache.Save(); - } - } -}; - -static CModelSoundsCacheSaver g_ModelSoundsCacheSaver( "CModelSoundsCacheSaver" ); - -//#define WATCHACCESS -#if defined( WATCHACCESS ) - -static bool g_bWatching = true; - -void ModelLogFunc( const char *fileName, const char *accessType ) -{ - if ( g_bWatching && !CBaseEntity::IsPrecacheAllowed() ) - { - if ( Q_stristr( fileName, ".vcd" ) ) - { - Msg( "%s\n", fileName ); - } - } -} - -class CWatchForModelAccess: public CAutoGameSystem -{ -public: - virtual bool Init() - { - filesystem->AddLoggingFunc(&ModelLogFunc); - return true; - } - - virtual void Shutdown() - { - filesystem->RemoveLoggingFunc(&ModelLogFunc); - } - -}; - -static CWatchForModelAccess g_WatchForModels; - -#endif - -// HACK: This must match the #define in cl_animevent.h in the client .dll code!!! -#define CL_EVENT_SOUND 5004 -#define CL_EVENT_FOOTSTEP_LEFT 6004 -#define CL_EVENT_FOOTSTEP_RIGHT 6005 -#define CL_EVENT_MFOOTSTEP_LEFT 6006 -#define CL_EVENT_MFOOTSTEP_RIGHT 6007 - -//----------------------------------------------------------------------------- -// Precache model sound. Requires a local symbol table to prevent -// a very expensive call to PrecacheScriptSound(). -//----------------------------------------------------------------------------- -void CBaseEntity::PrecacheSoundHelper( const char *pName ) -{ - if ( !IsX360() ) - { - // 360 only - Assert( 0 ); - return; - } - - if ( !pName || !pName[0] ) - { - return; - } - - if ( UTL_INVAL_SYMBOL == g_ModelSoundsSymbolHelper.Find( pName ) ) - { - g_ModelSoundsSymbolHelper.AddString( pName ); - - // very expensive, only call when required - PrecacheScriptSound( pName ); - } -} - -//----------------------------------------------------------------------------- -// Precache model components -//----------------------------------------------------------------------------- -void CBaseEntity::PrecacheModelComponents( int nModelIndex ) -{ - - model_t *pModel = (model_t *)modelinfo->GetModel( nModelIndex ); - if ( !pModel || modelinfo->GetModelType( pModel ) != mod_studio ) - { - return; - } - - // sounds - if ( IsPC() ) - { - const char *name = modelinfo->GetModelName( pModel ); - if ( !g_ModelSoundsCache.EntryExists( name ) ) - { - char extension[ 8 ]; - Q_ExtractFileExtension( name, extension, sizeof( extension ) ); - - if ( Q_stristr( extension, "mdl" ) ) - { - DevMsg( 2, "Late precache of %s, need to rebuild modelsounds.cache\n", name ); - } - else - { - if ( !extension[ 0 ] ) - { - Warning( "Precache of %s ambigious (no extension specified)\n", name ); - } - else - { - Warning( "Late precache of %s (file missing?)\n", name ); - } - return; - } - } - - CModelSoundsCache *entry = g_ModelSoundsCache.Get( name ); - Assert( entry ); - if ( entry ) - { - entry->PrecacheSoundList(); - } - } - - // particles - { - // Check keyvalues for auto-emitting particles - KeyValues *pModelKeyValues = new KeyValues(""); - KeyValues::AutoDelete autodelete_pModelKeyValues( pModelKeyValues ); - if ( pModelKeyValues->LoadFromBuffer( modelinfo->GetModelName( pModel ), modelinfo->GetModelKeyValueText( pModel ) ) ) - { - KeyValues *pParticleEffects = pModelKeyValues->FindKey("Particles"); - if ( pParticleEffects ) - { - // Start grabbing the sounds and slotting them in - for ( KeyValues *pSingleEffect = pParticleEffects->GetFirstSubKey(); pSingleEffect; pSingleEffect = pSingleEffect->GetNextKey() ) - { - const char *pParticleEffectName = pSingleEffect->GetString( "name", "" ); - PrecacheParticleSystem( pParticleEffectName ); - } - } - } - } - - // model anim event owned components - { - // Check animevents for particle events - CStudioHdr studioHdr( modelinfo->GetStudiomodel( pModel ), mdlcache ); - if ( studioHdr.IsValid() ) - { - // force animation event resolution!!! - VerifySequenceIndex( &studioHdr ); - - int nSeqCount = studioHdr.GetNumSeq(); - for ( int i = 0; i < nSeqCount; ++i ) - { - mstudioseqdesc_t &seq = studioHdr.pSeqdesc( i ); - int nEventCount = seq.numevents; - for ( int j = 0; j < nEventCount; ++j ) - { - mstudioevent_t *pEvent = seq.pEvent( j ); - - if ( !( pEvent->type & AE_TYPE_NEWEVENTSYSTEM ) || ( pEvent->type & AE_TYPE_CLIENT ) ) - { - if ( pEvent->event == AE_CL_CREATE_PARTICLE_EFFECT ) - { - char token[256]; - const char *pOptions = pEvent->pszOptions(); - nexttoken( token, pOptions, ' ' ); - if ( token[0] != '\0' ) - { - PrecacheParticleSystem( token ); - } - continue; - } - } - - // 360 precaches the model sounds now at init time, the cost is now ~250 msecs worst case. - // The disk based solution was not needed. Now at runtime partly due to already crawling the sequences - // for the particles and the expensive part was redundant PrecacheScriptSound(), which is now prevented - // by a local symbol table. - if ( IsX360() ) - { - switch ( pEvent->event ) - { - default: - { - if ( ( pEvent->type & AE_TYPE_NEWEVENTSYSTEM ) && ( pEvent->event == AE_SV_PLAYSOUND ) ) - { - PrecacheSoundHelper( pEvent->pszOptions() ); - } - } - break; - case CL_EVENT_FOOTSTEP_LEFT: - case CL_EVENT_FOOTSTEP_RIGHT: - { - char soundname[256]; - char const *options = pEvent->pszOptions(); - if ( !options || !options[0] ) - { - options = "NPC_CombineS"; - } - - Q_snprintf( soundname, sizeof( soundname ), "%s.RunFootstepLeft", options ); - PrecacheSoundHelper( soundname ); - Q_snprintf( soundname, sizeof( soundname ), "%s.RunFootstepRight", options ); - PrecacheSoundHelper( soundname ); - Q_snprintf( soundname, sizeof( soundname ), "%s.FootstepLeft", options ); - PrecacheSoundHelper( soundname ); - Q_snprintf( soundname, sizeof( soundname ), "%s.FootstepRight", options ); - PrecacheSoundHelper( soundname ); - } - break; - case AE_CL_PLAYSOUND: - { - if ( !( pEvent->type & AE_TYPE_CLIENT ) ) - break; - - if ( pEvent->pszOptions()[0] ) - { - PrecacheSoundHelper( pEvent->pszOptions() ); - } - else - { - Warning( "-- Error --: empty soundname, .qc error on AE_CL_PLAYSOUND in model %s, sequence %s, animevent # %i\n", - studioHdr.GetRenderHdr()->pszName(), seq.pszLabel(), j+1 ); - } - } - break; - case CL_EVENT_SOUND: - case SCRIPT_EVENT_SOUND: - case SCRIPT_EVENT_SOUND_VOICE: - { - PrecacheSoundHelper( pEvent->pszOptions() ); - } - break; - } - } - } - } - } - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: Add model to level precache list -// Input : *name - model name -// Output : int -- model index for model -//----------------------------------------------------------------------------- -int CBaseEntity::PrecacheModel( const char *name ) -{ - if ( !name || !*name ) - { - Msg( "Attempting to precache model, but model name is NULL\n"); - return -1; - } - - // Warn on out of order precache - if ( !CBaseEntity::IsPrecacheAllowed() ) - { - if ( !engine->IsModelPrecached( name ) ) - { - Assert( !"CBaseEntity::PrecacheModel: too late" ); - Warning( "Late precache of %s\n", name ); - } - } -#if defined( WATCHACCESS ) - else - { - g_bWatching = false; - } -#endif - - int idx = engine->PrecacheModel( name, true ); - if ( idx != -1 ) - { - PrecacheModelComponents( idx ); - } - -#if defined( WATCHACCESS ) - g_bWatching = true; -#endif - - return idx; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseEntity::Remove( ) -{ - UTIL_Remove( this ); -} - -// Entity degugging console commands -extern CBaseEntity *FindPickerEntity( CBasePlayer *pPlayer ); -extern void SetDebugBits( CBasePlayer* pPlayer, const char *name, int bit ); -extern CBaseEntity *GetNextCommandEntity( CBasePlayer *pPlayer, const char *name, CBaseEntity *ent ); - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void ConsoleFireTargets( CBasePlayer *pPlayer, const char *name) -{ - // If no name was given use the picker - if (FStrEq(name,"")) - { - CBaseEntity *pEntity = FindPickerEntity( pPlayer ); - if ( pEntity && !pEntity->IsMarkedForDeletion()) - { - Msg( "[%03d] Found: %s, firing\n", gpGlobals->tickcount%1000, pEntity->GetDebugName()); - pEntity->Use( pPlayer, pPlayer, USE_TOGGLE, 0 ); - return; - } - } - // Otherwise use name or classname - FireTargets( name, pPlayer, pPlayer, USE_TOGGLE, 0 ); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CC_Ent_Name( const CCommand& args ) -{ - SetDebugBits(UTIL_GetCommandClient(),args[1],OVERLAY_NAME_BIT); -} -static ConCommand ent_name("ent_name", CC_Ent_Name, 0, FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -void CC_Ent_Text( const CCommand& args ) -{ - SetDebugBits(UTIL_GetCommandClient(),args[1],OVERLAY_TEXT_BIT); -} -static ConCommand ent_text("ent_text", CC_Ent_Text, "Displays text debugging information about the given entity(ies) on top of the entity (See Overlay Text)\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at ", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -void CC_Ent_BBox( const CCommand& args ) -{ - SetDebugBits(UTIL_GetCommandClient(),args[1],OVERLAY_BBOX_BIT); -} -static ConCommand ent_bbox("ent_bbox", CC_Ent_BBox, "Displays the movement bounding box for the given entity(ies) in orange. Some entites will also display entity specific overlays.\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at ", FCVAR_CHEAT); - - -//------------------------------------------------------------------------------ -void CC_Ent_AbsBox( const CCommand& args ) -{ - SetDebugBits(UTIL_GetCommandClient(),args[1],OVERLAY_ABSBOX_BIT); -} -static ConCommand ent_absbox("ent_absbox", CC_Ent_AbsBox, "Displays the total bounding box for the given entity(s) in green. Some entites will also display entity specific overlays.\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at ", FCVAR_CHEAT); - - -//------------------------------------------------------------------------------ -void CC_Ent_RBox( const CCommand& args ) -{ - SetDebugBits(UTIL_GetCommandClient(),args[1],OVERLAY_RBOX_BIT); -} -static ConCommand ent_rbox("ent_rbox", CC_Ent_RBox, "Displays the total bounding box for the given entity(s) in green. Some entites will also display entity specific overlays.\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at ", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -void CC_Ent_AttachmentPoints( const CCommand& args ) -{ - SetDebugBits(UTIL_GetCommandClient(),args[1],OVERLAY_ATTACHMENTS_BIT); -} -static ConCommand ent_attachments("ent_attachments", CC_Ent_AttachmentPoints, "Displays the attachment points on an entity.\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at ", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -void CC_Ent_ViewOffset( const CCommand& args ) -{ - SetDebugBits(UTIL_GetCommandClient(),args[1],OVERLAY_VIEWOFFSET); -} -static ConCommand ent_viewoffset("ent_viewoffset", CC_Ent_ViewOffset, "Displays the eye position for the given entity(ies) in red.\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at ", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -void CC_Ent_Remove( const CCommand& args ) -{ - CBaseEntity *pEntity = NULL; - - // If no name was given set bits based on the picked - if ( FStrEq( args[1],"") ) - { - pEntity = FindPickerEntity( UTIL_GetCommandClient() ); - } - else - { - int index = atoi( args[1] ); - if ( index ) - { - pEntity = CBaseEntity::Instance( index ); - } - else - { - // Otherwise set bits based on name or classname - CBaseEntity *ent = NULL; - while ( (ent = gEntList.NextEnt(ent)) != NULL ) - { - if ( (ent->GetEntityName() != NULL_STRING && FStrEq(args[1], STRING(ent->GetEntityName()))) || - (ent->m_iClassname != NULL_STRING && FStrEq(args[1], STRING(ent->m_iClassname))) || - (ent->GetClassname()!=NULL && FStrEq(args[1], ent->GetClassname()))) - { - pEntity = ent; - break; - } - } - } - } - - // Found one? - if ( pEntity ) - { - Msg( "Removed %s(%s)\n", STRING(pEntity->m_iClassname), pEntity->GetDebugName() ); - UTIL_Remove( pEntity ); - } -} -static ConCommand ent_remove("ent_remove", CC_Ent_Remove, "Removes the given entity(s)\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at ", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -void CC_Ent_RemoveAll( const CCommand& args ) -{ - // If no name was given remove based on the picked - if ( args.ArgC() < 2 ) - { - Msg( "Removes all entities of the specified type\n\tArguments: {entity_name} / {class_name}\n" ); - } - else - { - // Otherwise remove based on name or classname - int iCount = 0; - CBaseEntity *ent = NULL; - while ( (ent = gEntList.NextEnt(ent)) != NULL ) - { - if ( (ent->GetEntityName() != NULL_STRING && FStrEq(args[1], STRING(ent->GetEntityName()))) || - (ent->m_iClassname != NULL_STRING && FStrEq(args[1], STRING(ent->m_iClassname))) || - (ent->GetClassname()!=NULL && FStrEq(args[1], ent->GetClassname()))) - { - UTIL_Remove( ent ); - iCount++; - } - } - - if ( iCount ) - { - Msg( "Removed %d %s's\n", iCount, args[1] ); - } - else - { - Msg( "No %s found.\n", args[1] ); - } - } -} -static ConCommand ent_remove_all("ent_remove_all", CC_Ent_RemoveAll, "Removes all entities of the specified type\n\tArguments: {entity_name} / {class_name} ", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -void CC_Ent_SetName( const CCommand& args ) -{ - CBaseEntity *pEntity = NULL; - - if ( args.ArgC() < 1 ) - { - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - if (!pPlayer) - return; - - ClientPrint( pPlayer, HUD_PRINTCONSOLE, "Usage:\n ent_setname \n" ); - } - else - { - // If no name was given set bits based on the picked - if ( FStrEq( args[2],"") ) - { - pEntity = FindPickerEntity( UTIL_GetCommandClient() ); - } - else - { - // Otherwise set bits based on name or classname - CBaseEntity *ent = NULL; - while ( (ent = gEntList.NextEnt(ent)) != NULL ) - { - if ( (ent->GetEntityName() != NULL_STRING && FStrEq(args[1], STRING(ent->GetEntityName()))) || - (ent->m_iClassname != NULL_STRING && FStrEq(args[1], STRING(ent->m_iClassname))) || - (ent->GetClassname()!=NULL && FStrEq(args[1], ent->GetClassname()))) - { - pEntity = ent; - break; - } - } - } - - // Found one? - if ( pEntity ) - { - Msg( "Set the name of %s to %s\n", STRING(pEntity->m_iClassname), args[1] ); - pEntity->SetName( AllocPooledString( args[1] ) ); - } - } -} -static ConCommand ent_setname("ent_setname", CC_Ent_SetName, "Sets the targetname of the given entity(s)\n\tArguments: {new entity name} {entity_name} / {class_name} / no argument picks what player is looking at ", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -void CC_Find_Ent( const CCommand& args ) -{ - if ( args.ArgC() < 2 ) - { - Msg( "Format: find_ent \n" ); - return; - } - - int iCount = 0; - const char *pszSubString = args[1]; - Msg("Searching for entities with class/target name containing substring: '%s'\n", pszSubString ); - - CBaseEntity *ent = NULL; - while ( (ent = gEntList.NextEnt(ent)) != NULL ) - { - const char *pszClassname = ent->GetClassname(); - const char *pszTargetname = STRING(ent->GetEntityName()); - - bool bMatches = false; - if ( pszClassname && pszClassname[0] ) - { - if ( Q_stristr( pszClassname, pszSubString ) ) - { - bMatches = true; - } - } - - if ( !bMatches && pszTargetname && pszTargetname[0] ) - { - if ( Q_stristr( pszTargetname, pszSubString ) ) - { - bMatches = true; - } - } - - if ( bMatches ) - { - iCount++; - Msg(" '%s' : '%s' (entindex %d) \n", ent->GetClassname(), ent->GetEntityName().ToCStr(), ent->entindex() ); - } - } - - Msg("Found %d matches.\n", iCount); -} -static ConCommand find_ent("find_ent", CC_Find_Ent, "Find and list all entities with classnames or targetnames that contain the specified substring.\nFormat: find_ent \n", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -void CC_Find_Ent_Index( const CCommand& args ) -{ - if ( args.ArgC() < 2 ) - { - Msg( "Format: find_ent_index \n" ); - return; - } - - int iIndex = atoi(args[1]); - CBaseEntity *pEnt = UTIL_EntityByIndex( iIndex ); - if ( pEnt ) - { - Msg(" '%s' : '%s' (entindex %d) \n", pEnt->GetClassname(), pEnt->GetEntityName().ToCStr(), iIndex ); - } - else - { - Msg("Found no entity at %d.\n", iIndex); - } -} -static ConCommand find_ent_index("find_ent_index", CC_Find_Ent_Index, "Display data for entity matching specified index.\nFormat: find_ent_index \n", FCVAR_CHEAT); - -// Purpose : -//------------------------------------------------------------------------------ -void CC_Ent_Dump( const CCommand& args ) -{ - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - if (!pPlayer) - { - return; - } - - if ( args.ArgC() < 2 ) - { - ClientPrint( pPlayer, HUD_PRINTCONSOLE, "Usage:\n ent_dump \n" ); - } - else - { - // iterate through all the ents of this name, printing out their details - CBaseEntity *ent = NULL; - bool bFound = false; - while ( ( ent = gEntList.FindEntityByName(ent, args[1] ) ) != NULL ) - { - bFound = true; - for ( datamap_t *dmap = ent->GetDataDescMap(); dmap != NULL; dmap = dmap->baseMap ) - { - // search through all the actions in the data description, printing out details - for ( int i = 0; i < dmap->dataNumFields; i++ ) - { - variant_t var; - if ( ent->ReadKeyField( dmap->dataDesc[i].externalName, &var) ) - { - char buf[256]; - buf[0] = 0; - switch( var.FieldType() ) - { - case FIELD_STRING: - Q_strncpy( buf, var.String() ,sizeof(buf)); - break; - case FIELD_INTEGER: - if ( var.Int() ) - Q_snprintf( buf,sizeof(buf), "%d", var.Int() ); - break; - case FIELD_FLOAT: - if ( var.Float() ) - Q_snprintf( buf,sizeof(buf), "%.2f", var.Float() ); - break; - case FIELD_EHANDLE: - { - // get the entities name - if ( var.Entity() ) - { - Q_snprintf( buf,sizeof(buf), "%s", STRING(var.Entity()->GetEntityName()) ); - } - } - break; - default: - break; - } - - // don't print out the duplicate keys - if ( !Q_stricmp("parentname",dmap->dataDesc[i].externalName) || !Q_stricmp("targetname",dmap->dataDesc[i].externalName) ) - continue; - - // don't print out empty keys - if ( buf[0] ) - { - ClientPrint( pPlayer, HUD_PRINTCONSOLE, UTIL_VarArgs(" %s: %s\n", dmap->dataDesc[i].externalName, buf) ); - } - } - } - } - } - - if ( !bFound ) - { - ClientPrint( pPlayer, HUD_PRINTCONSOLE, "ent_dump: no such entity" ); - } - } -} -static ConCommand ent_dump("ent_dump", CC_Ent_Dump, "Usage:\n ent_dump \n", FCVAR_CHEAT); - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CC_Ent_FireTarget( const CCommand& args ) -{ - ConsoleFireTargets(UTIL_GetCommandClient(),args[1]); -} -static ConCommand firetarget("firetarget", CC_Ent_FireTarget, 0, FCVAR_CHEAT); - -static bool UtlStringLessFunc( const CUtlString &lhs, const CUtlString &rhs ) -{ - return Q_stricmp( lhs.String(), rhs.String() ) < 0; -} - -class CEntFireAutoCompletionFunctor : public ICommandCallback, public ICommandCompletionCallback -{ -public: - virtual void CommandCallback( const CCommand &command ) - { - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - if (!pPlayer) - { - return; - } - - // fires a command from the console - if ( command.ArgC() < 2 ) - { - ClientPrint( pPlayer, HUD_PRINTCONSOLE, "Usage:\n ent_fire [action] [value] [delay]\n" ); - } - else - { - const char *target = "", *action = "Use"; - variant_t value; - int delay = 0; - - target = STRING( AllocPooledString(command.Arg( 1 ) ) ); - - // Don't allow them to run anything on a point_servercommand unless they're the host player. Otherwise they can ent_fire - // and run any command on the server. Admittedly, they can only do the ent_fire if sv_cheats is on, but - // people complained about users resetting the rcon password if the server briefly turned on cheats like this: - // give point_servercommand - // ent_fire point_servercommand command "rcon_password mynewpassword" - if ( gpGlobals->maxClients > 1 && V_stricmp( target, "point_servercommand" ) == 0 ) - { - if ( engine->IsDedicatedServer() ) - return; - - CBasePlayer *pHostPlayer = UTIL_GetListenServerHost(); - if ( pPlayer != pHostPlayer ) - return; - } - - if ( command.ArgC() >= 3 ) - { - action = STRING( AllocPooledString(command.Arg( 2 )) ); - } - if ( command.ArgC() >= 4 ) - { - value.SetString( AllocPooledString(command.Arg( 3 )) ); - } - if ( command.ArgC() >= 5 ) - { - delay = atoi( command.Arg( 4 ) ); - } - - g_EventQueue.AddEvent( target, action, value, delay, pPlayer, pPlayer ); - } - } - - virtual int CommandCompletionCallback( const char *partial, CUtlVector< CUtlString > &commands ) - { - if ( !g_pGameRules ) - { - return 0; - } - - const char *cmdname = "ent_fire"; - - char *substring = (char *)partial; - if ( Q_strstr( partial, cmdname ) ) - { - substring = (char *)partial + strlen( cmdname ) + 1; - } - - int checklen = 0; - char *space = Q_strstr( substring, " " ); - if ( space ) - { - return EntFire_AutoCompleteInput( partial, commands );; - } - else - { - checklen = Q_strlen( substring ); - } - - CUtlRBTree< CUtlString > symbols( 0, 0, UtlStringLessFunc ); - - CBaseEntity *pos = NULL; - while ( ( pos = gEntList.NextEnt( pos ) ) != NULL ) - { - // Check target name against partial string - if ( pos->GetEntityName() == NULL_STRING ) - continue; - - if ( Q_strnicmp( STRING( pos->GetEntityName() ), substring, checklen ) ) - continue; - - CUtlString sym = STRING( pos->GetEntityName() ); - int idx = symbols.Find( sym ); - if ( idx == symbols.InvalidIndex() ) - { - symbols.Insert( sym ); - } - - // Too many - if ( symbols.Count() >= COMMAND_COMPLETION_MAXITEMS ) - break; - } - - // Now fill in the results - for ( int i = symbols.FirstInorder(); i != symbols.InvalidIndex(); i = symbols.NextInorder( i ) ) - { - const char *name = symbols[ i ].String(); - - char buf[ 512 ]; - Q_strncpy( buf, name, sizeof( buf ) ); - Q_strlower( buf ); - - CUtlString command; - command = CFmtStr( "%s %s", cmdname, buf ); - commands.AddToTail( command ); - } - - return symbols.Count(); - } -private: - int EntFire_AutoCompleteInput( const char *partial, CUtlVector< CUtlString > &commands ) - { - const char *cmdname = "ent_fire"; - - char *substring = (char *)partial; - if ( Q_strstr( partial, cmdname ) ) - { - substring = (char *)partial + strlen( cmdname ) + 1; - } - - int checklen = 0; - char *space = Q_strstr( substring, " " ); - if ( !space ) - { - Assert( !"CC_EntFireAutoCompleteInputFunc is broken\n" ); - return 0; - } - - checklen = Q_strlen( substring ); - - char targetEntity[ 256 ]; - targetEntity[0] = 0; - int nEntityNameLength = (space-substring); - Q_strncat( targetEntity, substring, sizeof( targetEntity ), nEntityNameLength ); - - // Find the target entity by name - CBaseEntity *target = gEntList.FindEntityByName( NULL, targetEntity ); - if ( target == NULL ) - return 0; - - CUtlRBTree< CUtlString > symbols( 0, 0, UtlStringLessFunc ); - - // Find the next portion of the text chain, if any (removing space) - int nInputNameLength = (checklen-nEntityNameLength-1); - - // Starting past the last space, this is the remainder of the string - char *inputPartial = ( checklen > nEntityNameLength ) ? (space+1) : NULL; - - for ( datamap_t *dmap = target->GetDataDescMap(); dmap != NULL; dmap = dmap->baseMap ) - { - // Make sure we don't keep adding things in if the satisfied the limit - if ( symbols.Count() >= COMMAND_COMPLETION_MAXITEMS ) - break; - - int c = dmap->dataNumFields; - for ( int i = 0; i < c; i++ ) - { - typedescription_t *field = &dmap->dataDesc[ i ]; - - // Only want inputs - if ( !( field->flags & FTYPEDESC_INPUT ) ) - continue; - - // Only want input functions - if ( field->flags & FTYPEDESC_SAVE ) - continue; - - // See if we've got a partial string for the input name already - if ( inputPartial != NULL ) - { - if ( Q_strnicmp( inputPartial, field->externalName, nInputNameLength ) ) - continue; - } - - CUtlString sym = field->externalName; - - int idx = symbols.Find( sym ); - if ( idx == symbols.InvalidIndex() ) - { - symbols.Insert( sym ); - } - - // Too many items have been added - if ( symbols.Count() >= COMMAND_COMPLETION_MAXITEMS ) - break; - } - } - - // Now fill in the results - for ( int i = symbols.FirstInorder(); i != symbols.InvalidIndex(); i = symbols.NextInorder( i ) ) - { - const char *name = symbols[ i ].String(); - - char buf[ 512 ]; - Q_strncpy( buf, name, sizeof( buf ) ); - Q_strlower( buf ); - - CUtlString command; - command = CFmtStr( "%s %s %s", cmdname, targetEntity, buf ); - commands.AddToTail( command ); - } - - return symbols.Count(); - } -}; - -static CEntFireAutoCompletionFunctor g_EntFireAutoComplete; -static ConCommand ent_fire("ent_fire", &g_EntFireAutoComplete, "Usage:\n ent_fire [action] [value] [delay]\n", FCVAR_CHEAT, &g_EntFireAutoComplete ); - -void CC_Ent_CancelPendingEntFires( const CCommand& args ) -{ - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - if (!pPlayer) - return; - - g_EventQueue.CancelEvents( pPlayer ); -} -static ConCommand ent_cancelpendingentfires("ent_cancelpendingentfires", CC_Ent_CancelPendingEntFires, "Cancels all ent_fire created outputs that are currently waiting for their delay to expire." ); - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CC_Ent_Info( const CCommand& args ) -{ - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - if (!pPlayer) - { - return; - } - - if ( args.ArgC() < 2 ) - { - ClientPrint( pPlayer, HUD_PRINTCONSOLE, "Usage:\n ent_info \n" ); - } - else - { - // iterate through all the ents printing out their details - CBaseEntity *ent = CreateEntityByName( args[1] ); - - if ( ent ) - { - datamap_t *dmap; - for ( dmap = ent->GetDataDescMap(); dmap != NULL; dmap = dmap->baseMap ) - { - // search through all the actions in the data description, printing out details - for ( int i = 0; i < dmap->dataNumFields; i++ ) - { - if ( dmap->dataDesc[i].flags & FTYPEDESC_OUTPUT ) - { - ClientPrint( pPlayer, HUD_PRINTCONSOLE, UTIL_VarArgs(" output: %s\n", dmap->dataDesc[i].externalName) ); - } - } - } - - for ( dmap = ent->GetDataDescMap(); dmap != NULL; dmap = dmap->baseMap ) - { - // search through all the actions in the data description, printing out details - for ( int i = 0; i < dmap->dataNumFields; i++ ) - { - if ( dmap->dataDesc[i].flags & FTYPEDESC_INPUT ) - { - ClientPrint( pPlayer, HUD_PRINTCONSOLE, UTIL_VarArgs(" input: %s\n", dmap->dataDesc[i].externalName) ); - } - } - } - - delete ent; - } - else - { - ClientPrint( pPlayer, HUD_PRINTCONSOLE, UTIL_VarArgs("no such entity %s\n", args[1]) ); - } - } -} -static ConCommand ent_info("ent_info", CC_Ent_Info, "Usage:\n ent_info \n", FCVAR_CHEAT); - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CC_Ent_Messages( const CCommand& args ) -{ - SetDebugBits(UTIL_GetCommandClient(),args[1],OVERLAY_MESSAGE_BIT); -} -static ConCommand ent_messages("ent_messages", CC_Ent_Messages ,"Toggles input/output message display for the selected entity(ies). The name of the entity will be displayed as well as any messages that it sends or receives.\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at", FCVAR_CHEAT); - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CC_Ent_Pause( void ) -{ - if (CBaseEntity::Debug_IsPaused()) - { - Msg( "Resuming entity I/O events\n" ); - CBaseEntity::Debug_Pause(false); - } - else - { - Msg( "Pausing entity I/O events\n" ); - CBaseEntity::Debug_Pause(true); - } -} -static ConCommand ent_pause("ent_pause", CC_Ent_Pause, "Toggles pausing of input/output message processing for entities. When turned on processing of all message will stop. Any messages displayed with 'ent_messages' will stop fading and be displayed indefinitely. To step through the messages one by one use 'ent_step'.", FCVAR_CHEAT); - - -//------------------------------------------------------------------------------ -// Purpose : Enables the entity picker, revelaing debug information about the -// entity under the crosshair. -// Input : an optional command line argument "full" enables all debug info. -// Output : -//------------------------------------------------------------------------------ -void CC_Ent_Picker( void ) -{ - CBaseEntity::m_bInDebugSelect = CBaseEntity::m_bInDebugSelect ? false : true; - - // Remember the player that's making this request - CBaseEntity::m_nDebugPlayer = UTIL_GetCommandClientIndex(); -} -static ConCommand picker("picker", CC_Ent_Picker, "Toggles 'picker' mode. When picker is on, the bounding box, pivot and debugging text is displayed for whatever entity the player is looking at.\n\tArguments: full - enables all debug information", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CC_Ent_Pivot( const CCommand& args ) -{ - SetDebugBits(UTIL_GetCommandClient(),args[1],OVERLAY_PIVOT_BIT); -} -static ConCommand ent_pivot("ent_pivot", CC_Ent_Pivot, "Displays the pivot for the given entity(ies).\n\t(y=up=green, z=forward=blue, x=left=red). \n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at ", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CC_Ent_Step( const CCommand& args ) -{ - int nSteps = atoi(args[1]); - if (nSteps <= 0) - { - nSteps = 1; - } - CBaseEntity::Debug_SetSteps(nSteps); -} -static ConCommand ent_step("ent_step", CC_Ent_Step, "When 'ent_pause' is set this will step through one waiting input / output message at a time.", FCVAR_CHEAT); - -void CBaseEntity::SetCheckUntouch( bool check ) -{ - // Invalidate touchstamp - if ( check ) - { - touchStamp++; - if ( !IsEFlagSet( EFL_CHECK_UNTOUCH ) ) - { - AddEFlags( EFL_CHECK_UNTOUCH ); - EntityTouch_Add( this ); - } - } - else - { - RemoveEFlags( EFL_CHECK_UNTOUCH ); - } -} - -model_t *CBaseEntity::GetModel( void ) -{ - return (model_t *)modelinfo->GetModel( GetModelIndex() ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Calculates the absolute position of an edict in the world -// assumes the parent's absolute origin has already been calculated -//----------------------------------------------------------------------------- -void CBaseEntity::CalcAbsolutePosition( void ) -{ - if (!IsEFlagSet( EFL_DIRTY_ABSTRANSFORM )) - return; - - RemoveEFlags( EFL_DIRTY_ABSTRANSFORM ); - - // Plop the entity->parent matrix into m_rgflCoordinateFrame - AngleMatrix( m_angRotation, m_vecOrigin, m_rgflCoordinateFrame ); - - CBaseEntity *pMoveParent = GetMoveParent(); - if ( !pMoveParent ) - { - // no move parent, so just copy existing values - m_vecAbsOrigin = m_vecOrigin; - m_angAbsRotation = m_angRotation; - if ( HasDataObjectType( POSITIONWATCHER ) ) - { - ReportPositionChanged( this ); - } - return; - } - - // concatenate with our parent's transform - matrix3x4_t tmpMatrix, scratchSpace; - ConcatTransforms( GetParentToWorldTransform( scratchSpace ), m_rgflCoordinateFrame, tmpMatrix ); - MatrixCopy( tmpMatrix, m_rgflCoordinateFrame ); - - // pull our absolute position out of the matrix - MatrixGetColumn( m_rgflCoordinateFrame, 3, m_vecAbsOrigin ); - - // if we have any angles, we have to extract our absolute angles from our matrix - if (( m_angRotation == vec3_angle ) && ( m_iParentAttachment == 0 )) - { - // just copy our parent's absolute angles - VectorCopy( pMoveParent->GetAbsAngles(), m_angAbsRotation ); - } - else - { - MatrixAngles( m_rgflCoordinateFrame, m_angAbsRotation ); - } - if ( HasDataObjectType( POSITIONWATCHER ) ) - { - ReportPositionChanged( this ); - } -} - -void CBaseEntity::CalcAbsoluteVelocity() -{ - if (!IsEFlagSet( EFL_DIRTY_ABSVELOCITY )) - return; - - RemoveEFlags( EFL_DIRTY_ABSVELOCITY ); - - CBaseEntity *pMoveParent = GetMoveParent(); - if ( !pMoveParent ) - { - m_vecAbsVelocity = m_vecVelocity; - return; - } - - // This transforms the local velocity into world space - VectorRotate( m_vecVelocity, pMoveParent->EntityToWorldTransform(), m_vecAbsVelocity ); - - // Now add in the parent abs velocity - m_vecAbsVelocity += pMoveParent->GetAbsVelocity(); -} - -// FIXME: While we're using (dPitch, dYaw, dRoll) as our local angular velocity -// representation, we can't actually solve this problem -/* -void CBaseEntity::CalcAbsoluteAngularVelocity() -{ - if (!IsEFlagSet( EFL_DIRTY_ABSANGVELOCITY )) - return; - - RemoveEFlags( EFL_DIRTY_ABSANGVELOCITY ); - - CBaseEntity *pMoveParent = GetMoveParent(); - if ( !pMoveParent ) - { - m_vecAbsAngVelocity = m_vecAngVelocity; - return; - } - - // This transforms the local ang velocity into world space - matrix3x4_t angVelToParent, angVelToWorld; - AngleMatrix( m_vecAngVelocity, angVelToParent ); - ConcatTransforms( pMoveParent->EntityToWorldTransform(), angVelToParent, angVelToWorld ); - MatrixAngles( angVelToWorld, m_vecAbsAngVelocity ); -} -*/ - -//----------------------------------------------------------------------------- -// Computes the abs position of a point specified in local space -//----------------------------------------------------------------------------- -void CBaseEntity::ComputeAbsPosition( const Vector &vecLocalPosition, Vector *pAbsPosition ) -{ - CBaseEntity *pMoveParent = GetMoveParent(); - if ( !pMoveParent ) - { - *pAbsPosition = vecLocalPosition; - } - else - { - VectorTransform( vecLocalPosition, pMoveParent->EntityToWorldTransform(), *pAbsPosition ); - } -} - - -//----------------------------------------------------------------------------- -// Computes the abs position of a point specified in local space -//----------------------------------------------------------------------------- -void CBaseEntity::ComputeAbsDirection( const Vector &vecLocalDirection, Vector *pAbsDirection ) -{ - CBaseEntity *pMoveParent = GetMoveParent(); - if ( !pMoveParent ) - { - *pAbsDirection = vecLocalDirection; - } - else - { - VectorRotate( vecLocalDirection, pMoveParent->EntityToWorldTransform(), *pAbsDirection ); - } -} - - -matrix3x4_t& CBaseEntity::GetParentToWorldTransform( matrix3x4_t &tempMatrix ) -{ - CBaseEntity *pMoveParent = GetMoveParent(); - if ( !pMoveParent ) - { - Assert( false ); - SetIdentityMatrix( tempMatrix ); - return tempMatrix; - } - - if ( m_iParentAttachment != 0 ) - { - CBaseAnimating *pAnimating = pMoveParent->GetBaseAnimating(); - if ( pAnimating && pAnimating->GetAttachment( m_iParentAttachment, tempMatrix ) ) - { - return tempMatrix; - } - } - - // If we fall through to here, then just use the move parent's abs origin and angles. - return pMoveParent->EntityToWorldTransform(); -} - - -//----------------------------------------------------------------------------- -// These methods recompute local versions as well as set abs versions -//----------------------------------------------------------------------------- -void CBaseEntity::SetAbsOrigin( const Vector& absOrigin ) -{ - AssertMsg( absOrigin.IsValid(), "Invalid origin set" ); - - // This is necessary to get the other fields of m_rgflCoordinateFrame ok - CalcAbsolutePosition(); - - if ( m_vecAbsOrigin == absOrigin ) - return; - - // All children are invalid, but we are not - InvalidatePhysicsRecursive( POSITION_CHANGED ); - RemoveEFlags( EFL_DIRTY_ABSTRANSFORM ); - - m_vecAbsOrigin = absOrigin; - - MatrixSetColumn( absOrigin, 3, m_rgflCoordinateFrame ); - - Vector vecNewOrigin; - CBaseEntity *pMoveParent = GetMoveParent(); - if (!pMoveParent) - { - vecNewOrigin = absOrigin; - } - else - { - matrix3x4_t tempMat; - matrix3x4_t &parentTransform = GetParentToWorldTransform( tempMat ); - - // Moveparent case: transform the abs position into local space - VectorITransform( absOrigin, parentTransform, vecNewOrigin ); - } - - if (m_vecOrigin != vecNewOrigin) - { - m_vecOrigin = vecNewOrigin; - SetSimulationTime( gpGlobals->curtime ); - } -} - -void CBaseEntity::SetAbsAngles( const QAngle& absAngles ) -{ - // This is necessary to get the other fields of m_rgflCoordinateFrame ok - CalcAbsolutePosition(); - - // FIXME: The normalize caused problems in server code like momentary_rot_button that isn't - // handling things like +/-180 degrees properly. This should be revisited. - //QAngle angleNormalize( AngleNormalize( absAngles.x ), AngleNormalize( absAngles.y ), AngleNormalize( absAngles.z ) ); - - if ( m_angAbsRotation == absAngles ) - return; - - // All children are invalid, but we are not - InvalidatePhysicsRecursive( ANGLES_CHANGED ); - RemoveEFlags( EFL_DIRTY_ABSTRANSFORM ); - - m_angAbsRotation = absAngles; - AngleMatrix( absAngles, m_rgflCoordinateFrame ); - MatrixSetColumn( m_vecAbsOrigin, 3, m_rgflCoordinateFrame ); - - QAngle angNewRotation; - CBaseEntity *pMoveParent = GetMoveParent(); - if (!pMoveParent) - { - angNewRotation = absAngles; - } - else - { - if ( m_angAbsRotation == pMoveParent->GetAbsAngles() ) - { - angNewRotation.Init( ); - } - else - { - // Moveparent case: transform the abs transform into local space - matrix3x4_t worldToParent, localMatrix; - MatrixInvert( pMoveParent->EntityToWorldTransform(), worldToParent ); - ConcatTransforms( worldToParent, m_rgflCoordinateFrame, localMatrix ); - MatrixAngles( localMatrix, angNewRotation ); - } - } - - if (m_angRotation != angNewRotation) - { - m_angRotation = angNewRotation; - SetSimulationTime( gpGlobals->curtime ); - } -} - -void CBaseEntity::SetAbsVelocity( const Vector &vecAbsVelocity ) -{ - if ( m_vecAbsVelocity == vecAbsVelocity ) - return; - - // The abs velocity won't be dirty since we're setting it here - // All children are invalid, but we are not - InvalidatePhysicsRecursive( VELOCITY_CHANGED ); - RemoveEFlags( EFL_DIRTY_ABSVELOCITY ); - - m_vecAbsVelocity = vecAbsVelocity; - - // NOTE: Do *not* do a network state change in this case. - // m_vecVelocity is only networked for the player, which is not manual mode - CBaseEntity *pMoveParent = GetMoveParent(); - if (!pMoveParent) - { - m_vecVelocity = vecAbsVelocity; - return; - } - - // First subtract out the parent's abs velocity to get a relative - // velocity measured in world space - Vector relVelocity; - VectorSubtract( vecAbsVelocity, pMoveParent->GetAbsVelocity(), relVelocity ); - - // Transform relative velocity into parent space - Vector vNew; - VectorIRotate( relVelocity, pMoveParent->EntityToWorldTransform(), vNew ); - m_vecVelocity = vNew; -} - -// FIXME: While we're using (dPitch, dYaw, dRoll) as our local angular velocity -// representation, we can't actually solve this problem -/* -void CBaseEntity::SetAbsAngularVelocity( const QAngle &vecAbsAngVelocity ) -{ - // The abs velocity won't be dirty since we're setting it here - // All children are invalid, but we are not - InvalidatePhysicsRecursive( EFL_DIRTY_ABSANGVELOCITY ); - RemoveEFlags( EFL_DIRTY_ABSANGVELOCITY ); - - m_vecAbsAngVelocity = vecAbsAngVelocity; - - CBaseEntity *pMoveParent = GetMoveParent(); - if (!pMoveParent) - { - m_vecAngVelocity = vecAbsAngVelocity; - return; - } - - // NOTE: We *can't* subtract out parent ang velocity, it's nonsensical - matrix3x4_t entityToWorld; - AngleMatrix( vecAbsAngVelocity, entityToWorld ); - - // Moveparent case: transform the abs relative angular vel into local space - matrix3x4_t worldToParent, localMatrix; - MatrixInvert( pMoveParent->EntityToWorldTransform(), worldToParent ); - ConcatTransforms( worldToParent, entityToWorld, localMatrix ); - MatrixAngles( localMatrix, m_vecAngVelocity ); -} -*/ - - -//----------------------------------------------------------------------------- -// Methods that modify local physics state, and let us know to compute abs state later -//----------------------------------------------------------------------------- -void CBaseEntity::SetLocalOrigin( const Vector& origin ) -{ - if ( !origin.IsValid() ) - { - AssertMsg( 0, "Bad origin set" ); - return; - } - - if (m_vecOrigin != origin) - { - // Sanity check to make sure the origin is valid. -#ifdef _DEBUG - float largeVal = 1024 * 128; - Assert( origin.x >= -largeVal && origin.x <= largeVal ); - Assert( origin.y >= -largeVal && origin.y <= largeVal ); - Assert( origin.z >= -largeVal && origin.z <= largeVal ); -#endif - - InvalidatePhysicsRecursive( POSITION_CHANGED ); - m_vecOrigin = origin; - SetSimulationTime( gpGlobals->curtime ); - } -} - -void CBaseEntity::SetLocalAngles( const QAngle& angles ) -{ - // NOTE: The angle normalize is a little expensive, but we can save - // a bunch of time in interpolation if we don't have to invalidate everything - // and sometimes it's off by a normalization amount - - // FIXME: The normalize caused problems in server code like momentary_rot_button that isn't - // handling things like +/-180 degrees properly. This should be revisited. - //QAngle angleNormalize( AngleNormalize( angles.x ), AngleNormalize( angles.y ), AngleNormalize( angles.z ) ); - - if (m_angRotation != angles) - { - InvalidatePhysicsRecursive( ANGLES_CHANGED ); - m_angRotation = angles; - SetSimulationTime( gpGlobals->curtime ); - } -} - -void CBaseEntity::SetLocalVelocity( const Vector &vecVelocity ) -{ - if (m_vecVelocity != vecVelocity) - { - InvalidatePhysicsRecursive( VELOCITY_CHANGED ); - m_vecVelocity = vecVelocity; - } -} - -void CBaseEntity::SetLocalAngularVelocity( const QAngle &vecAngVelocity ) -{ - if (m_vecAngVelocity != vecAngVelocity) - { -// InvalidatePhysicsRecursive( EFL_DIRTY_ABSANGVELOCITY ); - m_vecAngVelocity = vecAngVelocity; - } -} - - -//----------------------------------------------------------------------------- -// Sets the local position from a transform -//----------------------------------------------------------------------------- -void CBaseEntity::SetLocalTransform( const matrix3x4_t &localTransform ) -{ - // FIXME: Should angles go away? Should we just use transforms? - Vector vecLocalOrigin; - QAngle vecLocalAngles; - MatrixGetColumn( localTransform, 3, vecLocalOrigin ); - MatrixAngles( localTransform, vecLocalAngles ); - SetLocalOrigin( vecLocalOrigin ); - SetLocalAngles( vecLocalAngles ); -} - - -//----------------------------------------------------------------------------- -// Is the entity floating? -//----------------------------------------------------------------------------- -bool CBaseEntity::IsFloating() -{ - if ( !IsEFlagSet(EFL_TOUCHING_FLUID) ) - return false; - - IPhysicsObject *pObject = VPhysicsGetObject(); - if ( !pObject ) - return false; - - int nMaterialIndex = pObject->GetMaterialIndex(); - - float flDensity; - float flThickness; - float flFriction; - float flElasticity; - physprops->GetPhysicsProperties( nMaterialIndex, &flDensity, - &flThickness, &flFriction, &flElasticity ); - - // FIXME: This really only works for water at the moment.. - // Owing the check for density == 1000 - return (flDensity < 1000.0f); -} - - -//----------------------------------------------------------------------------- -// Purpose: Created predictable and sets up Id. Note that persist is ignored on the server. -// Input : *classname - -// *module - -// line - -// persist - -// Output : CBaseEntity -//----------------------------------------------------------------------------- -CBaseEntity *CBaseEntity::CreatePredictedEntityByName( const char *classname, const char *module, int line, bool persist /* = false */ ) -{ -#if !defined( NO_ENTITY_PREDICTION ) - CBasePlayer *player = CBaseEntity::GetPredictionPlayer(); - Assert( player ); - - CBaseEntity *ent = NULL; - - int command_number = player->CurrentCommandNumber(); - int player_index = player->entindex() - 1; - - CPredictableId testId; - testId.Init( player_index, command_number, classname, module, line ); - - ent = CreateEntityByName( classname ); - // No factory??? - if ( !ent ) - return NULL; - - ent->SetPredictionEligible( true ); - - // Set up "shared" id number - ent->m_PredictableID.GetForModify().SetRaw( testId.GetRaw() ); - - return ent; -#else - return NULL; -#endif - -} - -void CBaseEntity::SetPredictionEligible( bool canpredict ) -{ -// Nothing in game code m_bPredictionEligible = canpredict; -} - -//----------------------------------------------------------------------------- -// These could be virtual, but only the player is overriding them -// NOTE: If you make any of these virtual, remove this implementation!!! -//----------------------------------------------------------------------------- -void CBaseEntity::AddPoints( int score, bool bAllowNegativeScore ) -{ - CBasePlayer *pPlayer = ToBasePlayer(this); - if ( pPlayer ) - { - pPlayer->CBasePlayer::AddPoints( score, bAllowNegativeScore ); - } -} - -void CBaseEntity::AddPointsToTeam( int score, bool bAllowNegativeScore ) -{ - CBasePlayer *pPlayer = ToBasePlayer(this); - if ( pPlayer ) - { - pPlayer->CBasePlayer::AddPointsToTeam( score, bAllowNegativeScore ); - } -} - -void CBaseEntity::ViewPunch( const QAngle &angleOffset ) -{ - CBasePlayer *pPlayer = ToBasePlayer(this); - if ( pPlayer ) - { - pPlayer->CBasePlayer::ViewPunch( angleOffset ); - } -} - -void CBaseEntity::VelocityPunch( const Vector &vecForce ) -{ - CBasePlayer *pPlayer = ToBasePlayer(this); - if ( pPlayer ) - { - pPlayer->CBasePlayer::VelocityPunch( vecForce ); - } -} -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -// Purpose: Tell clients to remove all decals from this entity -//----------------------------------------------------------------------------- -void CBaseEntity::RemoveAllDecals( void ) -{ - EntityMessageBegin( this ); - WRITE_BYTE( BASEENTITY_MSG_REMOVE_DECALS ); - MessageEnd(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : set - -//----------------------------------------------------------------------------- -void CBaseEntity::ModifyOrAppendCriteria( AI_CriteriaSet& set ) -{ - // TODO - // Append chapter/day? - - set.AppendCriteria( "randomnum", UTIL_VarArgs("%d", RandomInt(0,100)) ); - // Append map name - set.AppendCriteria( "map", gpGlobals->mapname.ToCStr() ); - // Append our classname and game name - set.AppendCriteria( "classname", GetClassname() ); - set.AppendCriteria( "name", GetEntityName().ToCStr() ); - - // Append our health - set.AppendCriteria( "health", UTIL_VarArgs( "%i", GetHealth() ) ); - - float healthfrac = 0.0f; - if ( GetMaxHealth() > 0 ) - { - healthfrac = (float)GetHealth() / (float)GetMaxHealth(); - } - - set.AppendCriteria( "healthfrac", UTIL_VarArgs( "%.3f", healthfrac ) ); - - // Go through all the global states and append them - - for ( int i = 0; i < GlobalEntity_GetNumGlobals(); i++ ) - { - const char *szGlobalName = GlobalEntity_GetName(i); - int iGlobalState = (int)GlobalEntity_GetStateByIndex(i); - set.AppendCriteria( szGlobalName, UTIL_VarArgs( "%i", iGlobalState ) ); - } - - // Append anything from I/O or keyvalues pairs - AppendContextToCriteria( set ); - - if( hl2_episodic.GetBool() ) - { - set.AppendCriteria( "episodic", "1" ); - } - - // Append anything from world I/O/keyvalues with "world" as prefix - CWorld *world = dynamic_cast< CWorld * >( CBaseEntity::Instance( engine->PEntityOfEntIndex( 0 ) ) ); - if ( world ) - { - world->AppendContextToCriteria( set, "world" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : set - -// "" - -//----------------------------------------------------------------------------- -void CBaseEntity::AppendContextToCriteria( AI_CriteriaSet& set, const char *prefix /*= ""*/ ) -{ - RemoveExpiredConcepts(); - - int c = GetContextCount(); - int i; - - char sz[ 128 ]; - for ( i = 0; i < c; i++ ) - { - const char *name = GetContextName( i ); - const char *value = GetContextValue( i ); - - Q_snprintf( sz, sizeof( sz ), "%s%s", prefix, name ); - - set.AppendCriteria( sz, value ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Removes expired concepts from list -// Output : -//----------------------------------------------------------------------------- -void CBaseEntity::RemoveExpiredConcepts( void ) -{ - int c = GetContextCount(); - int i; - - for ( i = 0; i < c; i++ ) - { - if ( ContextExpired( i ) ) - { - m_ResponseContexts.Remove( i ); - c--; - i--; - continue; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Get current context count -// Output : int -//----------------------------------------------------------------------------- -int CBaseEntity::GetContextCount() const -{ - return m_ResponseContexts.Count(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -// Output : const char -//----------------------------------------------------------------------------- -const char *CBaseEntity::GetContextName( int index ) const -{ - if ( index < 0 || index >= m_ResponseContexts.Count() ) - { - Assert( 0 ); - return ""; - } - - return m_ResponseContexts[ index ].m_iszName.ToCStr(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -// Output : const char -//----------------------------------------------------------------------------- -const char *CBaseEntity::GetContextValue( int index ) const -{ - if ( index < 0 || index >= m_ResponseContexts.Count() ) - { - Assert( 0 ); - return ""; - } - - return m_ResponseContexts[ index ].m_iszValue.ToCStr(); -} - -//----------------------------------------------------------------------------- -// Purpose: Check if context has expired -// Input : index - -// Output : bool -//----------------------------------------------------------------------------- -bool CBaseEntity::ContextExpired( int index ) const -{ - if ( index < 0 || index >= m_ResponseContexts.Count() ) - { - Assert( 0 ); - return true; - } - - if ( !m_ResponseContexts[ index ].m_fExpirationTime ) - { - return false; - } - - return ( m_ResponseContexts[ index ].m_fExpirationTime <= gpGlobals->curtime ); -} - -//----------------------------------------------------------------------------- -// Purpose: Search for index of named context string -// Input : *name - -// Output : int -//----------------------------------------------------------------------------- -int CBaseEntity::FindContextByName( const char *name ) const -{ - int c = m_ResponseContexts.Count(); - for ( int i = 0; i < c; i++ ) - { - if ( FStrEq( name, GetContextName( i ) ) ) - return i; - } - - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : inputdata - -//----------------------------------------------------------------------------- -void CBaseEntity::InputAddContext( inputdata_t& inputdata ) -{ - const char *contextName = inputdata.value.String(); - AddContext( contextName ); -} - - -//----------------------------------------------------------------------------- -// Purpose: User inputs. These fire the corresponding user outputs, and are -// a means of forwarding messages through !activator to a target known -// known by !activator but not by the targetting entity. -// -// For example, say you have three identical trains, following the same -// path. Each train has a sprite in hierarchy with it that needs to -// toggle on/off as it passes each path_track. You would hook each train's -// OnUser1 output to it's sprite's Toggle input, then connect each path_track's -// OnPass output to !activator's FireUser1 input. -//----------------------------------------------------------------------------- -void CBaseEntity::InputFireUser1( inputdata_t& inputdata ) -{ - m_OnUser1.FireOutput( inputdata.pActivator, this ); -} - - -void CBaseEntity::InputFireUser2( inputdata_t& inputdata ) -{ - m_OnUser2.FireOutput( inputdata.pActivator, this ); -} - - -void CBaseEntity::InputFireUser3( inputdata_t& inputdata ) -{ - m_OnUser3.FireOutput( inputdata.pActivator, this ); -} - - -void CBaseEntity::InputFireUser4( inputdata_t& inputdata ) -{ - m_OnUser4.FireOutput( inputdata.pActivator, this ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *contextName - -//----------------------------------------------------------------------------- -void CBaseEntity::AddContext( const char *contextName ) -{ - char key[ 128 ]; - char value[ 128 ]; - float duration; - - const char *p = contextName; - while ( p ) - { - duration = 0.0f; - p = SplitContext( p, key, sizeof( key ), value, sizeof( value ), &duration ); - if ( duration ) - { - duration += gpGlobals->curtime; - } - - int iIndex = FindContextByName( key ); - if ( iIndex != -1 ) - { - // Set the existing context to the new value - m_ResponseContexts[iIndex].m_iszValue = AllocPooledString( value ); - m_ResponseContexts[iIndex].m_fExpirationTime = duration; - continue; - } - - ResponseContext_t newContext; - newContext.m_iszName = AllocPooledString( key ); - newContext.m_iszValue = AllocPooledString( value ); - newContext.m_fExpirationTime = duration; - - m_ResponseContexts.AddToTail( newContext ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : inputdata - -//----------------------------------------------------------------------------- -void CBaseEntity::InputRemoveContext( inputdata_t& inputdata ) -{ - const char *contextName = inputdata.value.String(); - int idx = FindContextByName( contextName ); - if ( idx == -1 ) - return; - - m_ResponseContexts.Remove( idx ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : inputdata - -//----------------------------------------------------------------------------- -void CBaseEntity::InputClearContext( inputdata_t& inputdata ) -{ - m_ResponseContexts.RemoveAll(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : IResponseSystem -//----------------------------------------------------------------------------- -IResponseSystem *CBaseEntity::GetResponseSystem() -{ - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : inputdata - -//----------------------------------------------------------------------------- -void CBaseEntity::InputDispatchResponse( inputdata_t& inputdata ) -{ - DispatchResponse( inputdata.value.String() ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CBaseEntity::InputDisableShadow( inputdata_t &inputdata ) -{ - AddEffects( EF_NOSHADOW ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CBaseEntity::InputEnableShadow( inputdata_t &inputdata ) -{ - RemoveEffects( EF_NOSHADOW ); -} - -//----------------------------------------------------------------------------- -// Purpose: An input to add a new connection from this entity -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CBaseEntity::InputAddOutput( inputdata_t &inputdata ) -{ - char sOutputName[MAX_PATH]; - Q_strncpy( sOutputName, inputdata.value.String(), sizeof(sOutputName) ); - char *sChar = strchr( sOutputName, ' ' ); - if ( sChar ) - { - *sChar = '\0'; - // Now replace all the :'s in the string with ,'s. - // Has to be done this way because Hammer doesn't allow ,'s inside parameters. - char *sColon = strchr( sChar+1, ':' ); - while ( sColon ) - { - *sColon = ','; - sColon = strchr( sChar+1, ':' ); - } - KeyValue( sOutputName, sChar+1 ); - } - else - { - Warning("AddOutput input fired with bad string. Format: ,,,,\n"); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *conceptName - -//----------------------------------------------------------------------------- -void CBaseEntity::DispatchResponse( const char *conceptName ) -{ - IResponseSystem *rs = GetResponseSystem(); - if ( !rs ) - return; - - AI_CriteriaSet set; - // Always include the concept name - set.AppendCriteria( "concept", conceptName, CONCEPT_WEIGHT ); - // Let NPC fill in most match criteria - ModifyOrAppendCriteria( set ); - - // Append local player criteria to set,too - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - if( pPlayer ) - pPlayer->ModifyOrAppendPlayerCriteria( set ); - - // Now that we have a criteria set, ask for a suitable response - AI_Response result; - bool found = rs->FindBestResponse( set, result ); - if ( !found ) - { - return; - } - - // Handle the response here... - char response[ 256 ]; - result.GetResponse( response, sizeof( response ) ); - switch ( result.GetType() ) - { - case RESPONSE_SPEAK: - { - EmitSound( response ); - } - break; - case RESPONSE_SENTENCE: - { - int sentenceIndex = SENTENCEG_Lookup( response ); - if( sentenceIndex == -1 ) - { - // sentence not found - break; - } - - // FIXME: Get pitch from npc? - CPASAttenuationFilter filter( this ); - CBaseEntity::EmitSentenceByIndex( filter, entindex(), CHAN_VOICE, sentenceIndex, 1, result.GetSoundLevel(), 0, PITCH_NORM ); - } - break; - case RESPONSE_SCENE: - { - // Try to fire scene w/o an actor - InstancedScriptedScene( NULL, response ); - } - break; - case RESPONSE_PRINT: - { - - } - break; - default: - // Don't know how to handle .vcds!!! - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseEntity::DumpResponseCriteria( void ) -{ - Msg("----------------------------------------------\n"); - Msg("RESPONSE CRITERIA FOR: %s (%s)\n", GetClassname(), GetDebugName() ); - - AI_CriteriaSet set; - // Let NPC fill in most match criteria - ModifyOrAppendCriteria( set ); - - // Append local player criteria to set,too - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - if ( pPlayer ) - { - pPlayer->ModifyOrAppendPlayerCriteria( set ); - } - - // Now dump it all to console - set.Describe(); -} - -//------------------------------------------------------------------------------ -void CC_Ent_Show_Response_Criteria( const CCommand& args ) -{ - CBaseEntity *pEntity = NULL; - while ( (pEntity = GetNextCommandEntity( UTIL_GetCommandClient(), args[1], pEntity )) != NULL ) - { - pEntity->DumpResponseCriteria(); - } -} -static ConCommand ent_show_response_criteria("ent_show_response_criteria", CC_Ent_Show_Response_Criteria, "Print, to the console, an entity's current criteria set used to select responses.\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at ", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose: Show an entity's autoaim radius -//------------------------------------------------------------------------------ -void CC_Ent_Autoaim( const CCommand& args ) -{ - SetDebugBits( UTIL_GetCommandClient(),args[1], OVERLAY_AUTOAIM_BIT ); -} -static ConCommand ent_autoaim("ent_autoaim", CC_Ent_Autoaim, "Displays the entity's autoaim radius.\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at", FCVAR_CHEAT ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CAI_BaseNPC *CBaseEntity::MyNPCPointer( void ) -{ - if ( IsNPC() ) - return assert_cast(this); - - return NULL; -} - -ConVar step_spline( "step_spline", "0" ); - -//----------------------------------------------------------------------------- -// Purpose: Run one tick's worth of faked origin simulation -// Input : *step - -//----------------------------------------------------------------------------- -bool CBaseEntity::ComputeStepSimulationNetworkOrigin( StepSimulationData *step ) -{ - if ( !step ) - { - Assert( !"ComputeStepSimulationNetworkOriginAndAngles with NULL step\n" ); - return false; - } - - // It's inactive - if ( !step->m_bOriginActive ) - { - return false; - } - - step->m_nLastProcessTickCount = gpGlobals->tickcount; - - // First see if any external code moved the entity - if ( GetStepOrigin() != step->m_Next.vecOrigin ) - { - step->m_bOriginActive = false; - return false; - } - - // Compute interpolated info based on tick interval - float frac = 1.0f; - int tickdelta = step->m_Next.nTickCount - step->m_Previous.nTickCount; - if ( tickdelta > 0 ) - { - frac = (float)( gpGlobals->tickcount - step->m_Previous.nTickCount ) / (float) tickdelta; - frac = clamp( frac, 0.0f, 1.0f ); - } - - if (step->m_Previous2.nTickCount == 0 || step->m_Previous2.nTickCount >= step->m_Previous.nTickCount) - { - Vector delta = step->m_Next.vecOrigin - step->m_Previous.vecOrigin; - VectorMA( step->m_Previous.vecOrigin, frac, delta, step->m_vecNetworkOrigin ); - } - else if (!step_spline.GetBool()) - { - StepSimulationStep *pOlder = &step->m_Previous; - StepSimulationStep *pNewer = &step->m_Next; - - if (step->m_Discontinuity.nTickCount > step->m_Previous.nTickCount) - { - if (gpGlobals->tickcount > step->m_Discontinuity.nTickCount) - { - pOlder = &step->m_Discontinuity; - } - else - { - pNewer = &step->m_Discontinuity; - } - - tickdelta = pNewer->nTickCount - pOlder->nTickCount; - if ( tickdelta > 0 ) - { - frac = (float)( gpGlobals->tickcount - pOlder->nTickCount ) / (float) tickdelta; - frac = clamp( frac, 0.0f, 1.0f ); - } - } - - Vector delta = pNewer->vecOrigin - pOlder->vecOrigin; - VectorMA( pOlder->vecOrigin, frac, delta, step->m_vecNetworkOrigin ); - } - else - { - Hermite_Spline( step->m_Previous2.vecOrigin, step->m_Previous.vecOrigin, step->m_Next.vecOrigin, frac, step->m_vecNetworkOrigin ); - } - - return true; -} - - - -//----------------------------------------------------------------------------- -// Purpose: Run one tick's worth of faked angles simulation -// Input : *step - -//----------------------------------------------------------------------------- -bool CBaseEntity::ComputeStepSimulationNetworkAngles( StepSimulationData *step ) -{ - if ( !step ) - { - Assert( !"ComputeStepSimulationNetworkOriginAndAngles with NULL step\n" ); - return false; - } - - // It's inactive - if ( !step->m_bAnglesActive ) - { - return false; - } - - step->m_nLastProcessTickCount = gpGlobals->tickcount; - - // See if external code changed the orientation of the entity - if ( GetStepAngles() != step->m_angNextRotation ) - { - step->m_bAnglesActive = false; - return false; - } - - // Compute interpolated info based on tick interval - float frac = 1.0f; - int tickdelta = step->m_Next.nTickCount - step->m_Previous.nTickCount; - if ( tickdelta > 0 ) - { - frac = (float)( gpGlobals->tickcount - step->m_Previous.nTickCount ) / (float) tickdelta; - frac = clamp( frac, 0.0f, 1.0f ); - } - - if (step->m_Previous2.nTickCount == 0 || step->m_Previous2.nTickCount >= step->m_Previous.nTickCount) - { - // Pure blend between start/end orientations - Quaternion outangles; - QuaternionBlend( step->m_Previous.qRotation, step->m_Next.qRotation, frac, outangles ); - QuaternionAngles( outangles, step->m_angNetworkAngles ); - } - else if (!step_spline.GetBool()) - { - StepSimulationStep *pOlder = &step->m_Previous; - StepSimulationStep *pNewer = &step->m_Next; - - if (step->m_Discontinuity.nTickCount > step->m_Previous.nTickCount) - { - if (gpGlobals->tickcount > step->m_Discontinuity.nTickCount) - { - pOlder = &step->m_Discontinuity; - } - else - { - pNewer = &step->m_Discontinuity; - } - - tickdelta = pNewer->nTickCount - pOlder->nTickCount; - if ( tickdelta > 0 ) - { - frac = (float)( gpGlobals->tickcount - pOlder->nTickCount ) / (float) tickdelta; - frac = clamp( frac, 0.0f, 1.0f ); - } - } - - // Pure blend between start/end orientations - Quaternion outangles; - QuaternionBlend( pOlder->qRotation, pNewer->qRotation, frac, outangles ); - QuaternionAngles( outangles, step->m_angNetworkAngles ); - } - else - { - // FIXME: enable spline interpolation when turning is debounced. - Quaternion outangles; - Hermite_Spline( step->m_Previous2.qRotation, step->m_Previous.qRotation, step->m_Next.qRotation, frac, outangles ); - QuaternionAngles( outangles, step->m_angNetworkAngles ); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -bool CBaseEntity::AddStepDiscontinuity( float flTime, const Vector &vecOrigin, const QAngle &vecAngles ) -{ - if ((GetMoveType() != MOVETYPE_STEP ) || !HasDataObjectType( STEPSIMULATION ) ) - { - return false; - } - - StepSimulationData *step = ( StepSimulationData * )GetDataObject( STEPSIMULATION ); - - if (!step) - { - Assert( 0 ); - return false; - } - - step->m_Discontinuity.nTickCount = TIME_TO_TICKS( flTime ); - step->m_Discontinuity.vecOrigin = vecOrigin; - AngleQuaternion( vecAngles, step->m_Discontinuity.qRotation ); - - return true; -} - - -Vector CBaseEntity::GetStepOrigin( void ) const -{ - return GetLocalOrigin(); -} - -QAngle CBaseEntity::GetStepAngles( void ) const -{ - return GetLocalAngles(); -} - -//----------------------------------------------------------------------------- -// Purpose: For each client who appears to be a valid recipient, checks the client has disabled CC and if so, removes them from -// the recipient list. -// Input : filter - -//----------------------------------------------------------------------------- -void CBaseEntity::RemoveRecipientsIfNotCloseCaptioning( CRecipientFilter& filter ) -{ - int c = filter.GetRecipientCount(); - for ( int i = c - 1; i >= 0; --i ) - { - int playerIndex = filter.GetRecipientIndex( i ); - - CBasePlayer *player = static_cast< CBasePlayer * >( CBaseEntity::Instance( playerIndex ) ); - if ( !player ) - continue; -#if !defined( _XBOX ) - const char *cvarvalue = engine->GetClientConVarValue( playerIndex, "closecaption" ); - Assert( cvarvalue ); - if ( !cvarvalue[ 0 ] ) - continue; - - int value = atoi( cvarvalue ); -#else - static ConVar *s_pCloseCaption = NULL; - if ( !s_pCloseCaption ) - { - s_pCloseCaption = cvar->FindVar( "closecaption" ); - if ( !s_pCloseCaption ) - { - Error( "XBOX couldn't find closecaption convar!!!" ); - } - } - - int value = s_pCloseCaption->GetInt(); -#endif - // No close captions? - if ( value == 0 ) - { - filter.RemoveRecipient( player ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Wrapper to emit a sentence and also a close caption token for the sentence as appropriate. -// Input : filter - -// iEntIndex - -// iChannel - -// iSentenceIndex - -// flVolume - -// iSoundlevel - -// iFlags - -// iPitch - -// bUpdatePositions - -// soundtime - -//----------------------------------------------------------------------------- -void CBaseEntity::EmitSentenceByIndex( IRecipientFilter& filter, int iEntIndex, int iChannel, int iSentenceIndex, - float flVolume, soundlevel_t iSoundlevel, int iFlags /*= 0*/, int iPitch /*=PITCH_NORM*/, - const Vector *pOrigin /*=NULL*/, const Vector *pDirection /*=NULL*/, - bool bUpdatePositions /*=true*/, float soundtime /*=0.0f*/ ) -{ - CUtlVector< Vector > dummy; - enginesound->EmitSentenceByIndex( filter, iEntIndex, iChannel, iSentenceIndex, - flVolume, iSoundlevel, iFlags, iPitch, pOrigin, pDirection, &dummy, bUpdatePositions, soundtime ); -} - - -void CBaseEntity::SetRefEHandle( const CBaseHandle &handle ) -{ - m_RefEHandle = handle; - if ( edict() ) - { - edict()->m_NetworkSerialNumber = (m_RefEHandle.GetSerialNumber() & (1 << NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS) - 1); - } -} - - -bool CPointEntity::KeyValue( const char *szKeyName, const char *szValue ) -{ - if ( FStrEq( szKeyName, "mins" ) || FStrEq( szKeyName, "maxs" ) ) - { - Warning("Warning! Can't specify mins/maxs for point entities! (%s)\n", GetClassname() ); - return true; - } - - return BaseClass::KeyValue( szKeyName, szValue ); -} - -bool CServerOnlyPointEntity::KeyValue( const char *szKeyName, const char *szValue ) -{ - if ( FStrEq( szKeyName, "mins" ) || FStrEq( szKeyName, "maxs" ) ) - { - Warning("Warning! Can't specify mins/maxs for point entities! (%s)\n", GetClassname() ); - return true; - } - - return BaseClass::KeyValue( szKeyName, szValue ); -} - -bool CLogicalEntity::KeyValue( const char *szKeyName, const char *szValue ) -{ - if ( FStrEq( szKeyName, "mins" ) || FStrEq( szKeyName, "maxs" ) ) - { - Warning("Warning! Can't specify mins/maxs for point entities! (%s)\n", GetClassname() ); - return true; - } - - return BaseClass::KeyValue( szKeyName, szValue ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Sets the entity invisible, and makes it remove itself on the next frame -//----------------------------------------------------------------------------- -void CBaseEntity::RemoveDeferred( void ) -{ - // Set our next think to remove us - SetThink( &CBaseEntity::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - // Hide us completely - AddEffects( EF_NODRAW ); - AddSolidFlags( FSOLID_NOT_SOLID ); - SetMoveType( MOVETYPE_NONE ); -} - -#define MIN_CORPSE_FADE_TIME 10.0 -#define MIN_CORPSE_FADE_DIST 256.0 -#define MAX_CORPSE_FADE_DIST 1500.0 - -// -// fade out - slowly fades a entity out, then removes it. -// -// DON'T USE ME FOR GIBS AND STUFF IN MULTIPLAYER! -// SET A FUTURE THINK AND A RENDERMODE!! -void CBaseEntity::SUB_StartFadeOut( float delay, bool notSolid ) -{ - SetThink( &CBaseEntity::SUB_FadeOut ); - SetNextThink( gpGlobals->curtime + delay ); - SetRenderColorA( 255 ); - m_nRenderMode = kRenderNormal; - - if ( notSolid ) - { - AddSolidFlags( FSOLID_NOT_SOLID ); - SetLocalAngularVelocity( vec3_angle ); - } -} - -void CBaseEntity::SUB_StartFadeOutInstant() -{ - SUB_StartFadeOut( 0, true ); -} - -//----------------------------------------------------------------------------- -// Purpose: Vanish when players aren't looking -//----------------------------------------------------------------------------- -void CBaseEntity::SUB_Vanish( void ) -{ - //Always think again next frame - SetNextThink( gpGlobals->curtime + 0.1f ); - - CBasePlayer *pPlayer; - - //Get all players - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - //Get the next client - if ( ( pPlayer = UTIL_PlayerByIndex( i ) ) != NULL ) - { - Vector corpseDir = (GetAbsOrigin() - pPlayer->WorldSpaceCenter() ); - - float flDistSqr = corpseDir.LengthSqr(); - //If the player is close enough, don't fade out - if ( flDistSqr < (MIN_CORPSE_FADE_DIST*MIN_CORPSE_FADE_DIST) ) - return; - - // If the player's far enough away, we don't care about looking at it - if ( flDistSqr < (MAX_CORPSE_FADE_DIST*MAX_CORPSE_FADE_DIST) ) - { - VectorNormalize( corpseDir ); - - Vector plForward; - pPlayer->EyeVectors( &plForward ); - - float dot = plForward.Dot( corpseDir ); - - if ( dot > 0.0f ) - return; - } - } - } - - //If we're here, then we can vanish safely - m_iHealth = 0; - SetThink( &CBaseEntity::SUB_Remove ); -} - -void CBaseEntity::SUB_PerformFadeOut( void ) -{ - float dt = gpGlobals->frametime; - if ( dt > 0.1f ) - { - dt = 0.1f; - } - m_nRenderMode = kRenderTransTexture; - int speed = (int)MAX(1,256*dt); // fade out over 1 second - SetRenderColorA( (byte)UTIL_Approach( 0, m_clrRender->a, speed ) ); -} - -bool CBaseEntity::SUB_AllowedToFade( void ) -{ - if( VPhysicsGetObject() ) - { - if( VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD || GetEFlags() & EFL_IS_BEING_LIFTED_BY_BARNACLE ) - return false; - } - - // on Xbox, allow these to fade out -#ifndef _XBOX - CBasePlayer *pPlayer = ( AI_IsSinglePlayer() ) ? UTIL_GetLocalPlayer() : NULL; - - if ( pPlayer && pPlayer->FInViewCone( this ) ) - return false; -#endif - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Fade out slowly -//----------------------------------------------------------------------------- -void CBaseEntity::SUB_FadeOut( void ) -{ - if ( SUB_AllowedToFade() == false ) - { - SetNextThink( gpGlobals->curtime + 1 ); - SetRenderColorA( 255 ); - return; - } - - SUB_PerformFadeOut(); - - if ( m_clrRender->a == 0 ) - { - UTIL_Remove(this); - } - else - { - SetNextThink( gpGlobals->curtime ); - } -} - - -inline bool AnyPlayersInHierarchy_R( CBaseEntity *pEnt ) -{ - if ( pEnt->IsPlayer() ) - return true; - - for ( CBaseEntity *pCur = pEnt->FirstMoveChild(); pCur; pCur=pCur->NextMovePeer() ) - { - if ( AnyPlayersInHierarchy_R( pCur ) ) - return true; - } - - return false; -} - - -void CBaseEntity::RecalcHasPlayerChildBit() -{ - if ( AnyPlayersInHierarchy_R( this ) ) - AddEFlags( EFL_HAS_PLAYER_CHILD ); - else - RemoveEFlags( EFL_HAS_PLAYER_CHILD ); -} - - -bool CBaseEntity::DoesHavePlayerChild() -{ - return IsEFlagSet( EFL_HAS_PLAYER_CHILD ); -} - - -//------------------------------------------------------------------------------ -// Purpose: Create an NPC of the given type -//------------------------------------------------------------------------------ -void CC_Ent_Create( const CCommand& args ) -{ - MDLCACHE_CRITICAL_SECTION(); - - bool allowPrecache = CBaseEntity::IsPrecacheAllowed(); - CBaseEntity::SetAllowPrecache( true ); - - // Try to create entity - CBaseEntity *entity = dynamic_cast< CBaseEntity * >( CreateEntityByName(args[1]) ); - if (entity) - { - entity->Precache(); - DispatchSpawn(entity); - // Now attempt to drop into the world - CBasePlayer* pPlayer = UTIL_GetCommandClient(); - trace_t tr; - Vector forward; - pPlayer->EyeVectors( &forward ); - UTIL_TraceLine(pPlayer->EyePosition(), - pPlayer->EyePosition() + forward * MAX_TRACE_LENGTH,MASK_SOLID, - pPlayer, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction != 1.0 ) - { - // Raise the end position a little up off the floor, place the npc and drop him down - tr.endpos.z += 12; - entity->Teleport( &tr.endpos, NULL, NULL ); - UTIL_DropToFloor( entity, MASK_SOLID ); - } - } - CBaseEntity::SetAllowPrecache( allowPrecache ); -} -static ConCommand ent_create("ent_create", CC_Ent_Create, "Creates an entity of the given type where the player is looking.", FCVAR_GAMEDLL | FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose: Teleport a specified entity to where the player is looking -//------------------------------------------------------------------------------ -bool CC_GetCommandEnt( const CCommand& args, CBaseEntity **ent, Vector *vecTargetPoint, QAngle *vecPlayerAngle ) -{ - // Find the entity - *ent = NULL; - // First try using it as an entindex - int iEntIndex = atoi( args[1] ); - if ( iEntIndex ) - { - *ent = CBaseEntity::Instance( iEntIndex ); - } - else - { - // Try finding it by name - *ent = gEntList.FindEntityByName( NULL, args[1] ); - - if ( !*ent ) - { - // Finally, try finding it by classname - *ent = gEntList.FindEntityByClassname( NULL, args[1] ); - } - } - - if ( !*ent ) - { - Msg( "Couldn't find any entity named '%s'\n", args[1] ); - return false; - } - - CBasePlayer *pPlayer = UTIL_GetCommandClient(); - if ( vecTargetPoint ) - { - trace_t tr; - Vector forward; - pPlayer->EyeVectors( &forward ); - UTIL_TraceLine(pPlayer->EyePosition(), - pPlayer->EyePosition() + forward * MAX_TRACE_LENGTH,MASK_NPCSOLID, - pPlayer, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction != 1.0 ) - { - *vecTargetPoint = tr.endpos; - } - } - - if ( vecPlayerAngle ) - { - *vecPlayerAngle = pPlayer->EyeAngles(); - } - - return true; -} - -//------------------------------------------------------------------------------ -// Purpose: Teleport a specified entity to where the player is looking -//------------------------------------------------------------------------------ -void CC_Ent_Teleport( const CCommand& args ) -{ - if ( args.ArgC() < 2 ) - { - Msg( "Format: ent_teleport \n" ); - return; - } - - CBaseEntity *pEnt; - Vector vecTargetPoint; - if ( CC_GetCommandEnt( args, &pEnt, &vecTargetPoint, NULL ) ) - { - pEnt->Teleport( &vecTargetPoint, NULL, NULL ); - } -} - -static ConCommand ent_teleport("ent_teleport", CC_Ent_Teleport, "Teleport the specified entity to where the player is looking.\n\tFormat: ent_teleport ", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose: Orient a specified entity to match the player's angles -//------------------------------------------------------------------------------ -void CC_Ent_Orient( const CCommand& args ) -{ - if ( args.ArgC() < 2 ) - { - Msg( "Format: ent_orient \n" ); - return; - } - - CBaseEntity *pEnt; - QAngle vecPlayerAngles; - if ( CC_GetCommandEnt( args, &pEnt, NULL, &vecPlayerAngles ) ) - { - QAngle vecEntAngles = pEnt->GetAbsAngles(); - if ( args.ArgC() == 3 && !Q_strncmp( args[2], "allangles", 9 ) ) - { - vecEntAngles = vecPlayerAngles; - } - else - { - vecEntAngles[YAW] = vecPlayerAngles[YAW]; - } - - pEnt->SetAbsAngles( vecEntAngles ); - } -} - -static ConCommand ent_orient("ent_orient", CC_Ent_Orient, "Orient the specified entity to match the player's angles. By default, only orients target entity's YAW. Use the 'allangles' option to orient on all axis.\n\tFormat: ent_orient ", FCVAR_CHEAT); diff --git a/game/server/baseentity.h b/game/server/baseentity.h deleted file mode 100644 index e2d265fbd..000000000 --- a/game/server/baseentity.h +++ /dev/null @@ -1,2609 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef BASEENTITY_H -#define BASEENTITY_H -#ifdef _WIN32 -#pragma once -#endif - -#define TEAMNUM_NUM_BITS 6 - -#include "entitylist.h" -#include "entityoutput.h" -#include "networkvar.h" -#include "collisionproperty.h" -#include "ServerNetworkProperty.h" -#include "shareddefs.h" - -class CDamageModifier; - -struct CSoundParameters; - -class AI_CriteriaSet; -class IResponseSystem; -class IEntitySaveUtils; -class CRecipientFilter; - -// Matching the high level concept is significantly better than other criteria -// FIXME: Could do this in the script file by making it required and bumping up weighting there instead... -#define CONCEPT_WEIGHT 5.0f - -typedef CHandle EHANDLE; - -#define MANUALMODE_GETSET_PROP(type, accessorName, varName) \ - private:\ - type varName;\ - public:\ - inline const type& Get##accessorName##() const { return varName; } \ - inline type& Get##accessorName##() { return varName; } \ - inline void Set##accessorName##( const type &val ) { varName = val; m_NetStateMgr.StateChanged(); } - -#define MANUALMODE_GETSET_EHANDLE(type, accessorName, varName) \ - private:\ - CHandle varName;\ - public:\ - inline type* Get##accessorName##() { return varName.Get(); } \ - inline void Set##accessorName##( type *pType ) { varName = pType; m_NetStateMgr.StateChanged(); } - - -// saverestore.h declarations -class CSaveRestoreData; -struct typedescription_t; -class ISave; -class IRestore; -class CBaseEntity; -class CEntityMapData; -class CBaseCombatWeapon; -class IPhysicsObject; -class IPhysicsShadowController; -class CBaseCombatCharacter; -class CTeam; -class Vector; -struct gamevcollisionevent_t; -class CBaseAnimating; -class CBasePlayer; -class IServerVehicle; -struct solid_t; -struct notify_system_event_params_t; -class CAI_BaseNPC; -class CAI_Senses; -class CSquadNPC; -class variant_t; -class CEventAction; -typedef struct KeyValueData_s KeyValueData; -class CUserCmd; -class CSkyCamera; -class CEntityMapData; - -typedef CUtlVector< CBaseEntity* > EntityList_t; - -#if defined( HL2_DLL ) - -// For CLASSIFY -enum Class_T -{ - CLASS_NONE=0, - CLASS_PLAYER, - CLASS_PLAYER_ALLY, - CLASS_PLAYER_ALLY_VITAL, - CLASS_ANTLION, - CLASS_BARNACLE, - CLASS_BULLSEYE, - //CLASS_BULLSQUID, - CLASS_CITIZEN_PASSIVE, - CLASS_CITIZEN_REBEL, - CLASS_COMBINE, - CLASS_COMBINE_GUNSHIP, - CLASS_CONSCRIPT, - CLASS_HEADCRAB, - //CLASS_HOUNDEYE, - CLASS_MANHACK, - CLASS_METROPOLICE, - CLASS_MILITARY, - CLASS_SCANNER, - CLASS_STALKER, - CLASS_VORTIGAUNT, - CLASS_ZOMBIE, - CLASS_PROTOSNIPER, - CLASS_MISSILE, - CLASS_FLARE, - CLASS_EARTH_FAUNA, - CLASS_HACKED_ROLLERMINE, - CLASS_COMBINE_HUNTER, - - NUM_AI_CLASSES -}; - -#elif defined( HL1_DLL ) - -enum Class_T -{ - CLASS_NONE = 0, - CLASS_MACHINE, - CLASS_PLAYER, - CLASS_HUMAN_PASSIVE, - CLASS_HUMAN_MILITARY, - CLASS_ALIEN_MILITARY, - CLASS_ALIEN_MONSTER, - CLASS_ALIEN_PREY, - CLASS_ALIEN_PREDATOR, - CLASS_INSECT, - CLASS_PLAYER_ALLY, - CLASS_PLAYER_BIOWEAPON, - CLASS_ALIEN_BIOWEAPON, - - NUM_AI_CLASSES -}; - -#elif defined( INVASION_DLL ) - -enum Class_T -{ - CLASS_NONE = 0, - CLASS_PLAYER, - CLASS_PLAYER_ALLY, - CLASS_PLAYER_ALLY_VITAL, - CLASS_ANTLION, - CLASS_BARNACLE, - CLASS_BULLSEYE, - //CLASS_BULLSQUID, - CLASS_CITIZEN_PASSIVE, - CLASS_CITIZEN_REBEL, - CLASS_COMBINE, - CLASS_COMBINE_GUNSHIP, - CLASS_CONSCRIPT, - CLASS_HEADCRAB, - //CLASS_HOUNDEYE, - CLASS_MANHACK, - CLASS_METROPOLICE, - CLASS_MILITARY, - CLASS_SCANNER, - CLASS_STALKER, - CLASS_VORTIGAUNT, - CLASS_ZOMBIE, - CLASS_PROTOSNIPER, - CLASS_MISSILE, - CLASS_FLARE, - CLASS_EARTH_FAUNA, - NUM_AI_CLASSES -}; - -#elif defined( CSTRIKE_DLL ) - -enum Class_T -{ - CLASS_NONE = 0, - CLASS_PLAYER, - CLASS_PLAYER_ALLY, - NUM_AI_CLASSES -}; - -#else - -enum Class_T -{ - CLASS_NONE = 0, - CLASS_PLAYER, - CLASS_PLAYER_ALLY, - NUM_AI_CLASSES -}; - -#endif - -// -// Structure passed to input handlers. -// -struct inputdata_t -{ - CBaseEntity *pActivator; // The entity that initially caused this chain of output events. - CBaseEntity *pCaller; // The entity that fired this particular output. - variant_t value; // The data parameter for this output. - int nOutputID; // The unique ID of the output that was fired. -}; - -// Serializable list of context as set by entity i/o and used for deducing proper -// speech state, et al. -struct ResponseContext_t -{ - DECLARE_SIMPLE_DATADESC(); - - string_t m_iszName; - string_t m_iszValue; - float m_fExpirationTime; // when to expire context (0 == never) -}; - - -//----------------------------------------------------------------------------- -// Entity events... targetted to a particular entity -// Each event has a well defined structure to use for parameters -//----------------------------------------------------------------------------- -enum EntityEvent_t -{ - ENTITY_EVENT_WATER_TOUCH = 0, // No data needed - ENTITY_EVENT_WATER_UNTOUCH, // No data needed - ENTITY_EVENT_PARENT_CHANGED, // No data needed -}; - - -//----------------------------------------------------------------------------- - -typedef void (CBaseEntity::*BASEPTR)(void); -typedef void (CBaseEntity::*ENTITYFUNCPTR)(CBaseEntity *pOther ); -typedef void (CBaseEntity::*USEPTR)( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - -#define DEFINE_THINKFUNC( function ) DEFINE_FUNCTION_RAW( function, BASEPTR ) -#define DEFINE_ENTITYFUNC( function ) DEFINE_FUNCTION_RAW( function, ENTITYFUNCPTR ) -#define DEFINE_USEFUNC( function ) DEFINE_FUNCTION_RAW( function, USEPTR ) - -// Things that toggle (buttons/triggers/doors) need this -enum TOGGLE_STATE -{ - TS_AT_TOP, - TS_AT_BOTTOM, - TS_GOING_UP, - TS_GOING_DOWN -}; - - -// Debug overlay bits -enum DebugOverlayBits_t -{ - OVERLAY_TEXT_BIT = 0x00000001, // show text debug overlay for this entity - OVERLAY_NAME_BIT = 0x00000002, // show name debug overlay for this entity - OVERLAY_BBOX_BIT = 0x00000004, // show bounding box overlay for this entity - OVERLAY_PIVOT_BIT = 0x00000008, // show pivot for this entity - OVERLAY_MESSAGE_BIT = 0x00000010, // show messages for this entity - OVERLAY_ABSBOX_BIT = 0x00000020, // show abs bounding box overlay - OVERLAY_RBOX_BIT = 0x00000040, // show the rbox overlay - OVERLAY_SHOW_BLOCKSLOS = 0x00000080, // show entities that block NPC LOS - OVERLAY_ATTACHMENTS_BIT = 0x00000100, // show attachment points - OVERLAY_AUTOAIM_BIT = 0x00000200, // Display autoaim radius - - OVERLAY_NPC_SELECTED_BIT = 0x00001000, // the npc is current selected - OVERLAY_NPC_NEAREST_BIT = 0x00002000, // show the nearest node of this npc - OVERLAY_NPC_ROUTE_BIT = 0x00004000, // draw the route for this npc - OVERLAY_NPC_TRIANGULATE_BIT = 0x00008000, // draw the triangulation for this npc - OVERLAY_NPC_ZAP_BIT = 0x00010000, // destroy the NPC - OVERLAY_NPC_ENEMIES_BIT = 0x00020000, // show npc's enemies - OVERLAY_NPC_CONDITIONS_BIT = 0x00040000, // show NPC's current conditions - OVERLAY_NPC_SQUAD_BIT = 0x00080000, // show npc squads - OVERLAY_NPC_TASK_BIT = 0x00100000, // show npc task details - OVERLAY_NPC_FOCUS_BIT = 0x00200000, // show line to npc's enemy and target - OVERLAY_NPC_VIEWCONE_BIT = 0x00400000, // show npc's viewcone - OVERLAY_NPC_KILL_BIT = 0x00800000, // kill the NPC, running all appropriate AI. - - OVERLAY_WC_CHANGE_ENTITY = 0x01000000, // object changed during WC edit - OVERLAY_BUDDHA_MODE = 0x02000000, // take damage but don't die - - OVERLAY_NPC_STEERING_REGULATIONS = 0x04000000, // Show the steering regulations associated with the NPC - - OVERLAY_TASK_TEXT_BIT = 0x08000000, // show task and schedule names when they start - - OVERLAY_PROP_DEBUG = 0x10000000, - - OVERLAY_NPC_RELATION_BIT = 0x20000000, // show relationships between target and all children - - OVERLAY_VIEWOFFSET = 0x40000000, // show view offset -}; - -struct TimedOverlay_t; - -/* ========= CBaseEntity ======== - - All objects in the game are derived from this. - -a list of all CBaseEntitys is kept in gEntList -================================ */ - -// creates an entity by string name, but does not spawn it -// If iForceEdictIndex is not -1, then it will use the edict by that index. If the index is -// invalid or there is already an edict using that index, it will error out. -CBaseEntity *CreateEntityByName( const char *className, int iForceEdictIndex = -1 ); -CBaseNetworkable *CreateNetworkableByName( const char *className ); - -// creates an entity and calls all the necessary spawn functions -extern void SpawnEntityByName( const char *className, CEntityMapData *mapData = NULL ); - -// calls the spawn functions for an entity -extern int DispatchSpawn( CBaseEntity *pEntity ); - -inline CBaseEntity *GetContainingEntity( edict_t *pent ); - -//----------------------------------------------------------------------------- -// Purpose: think contexts -//----------------------------------------------------------------------------- -struct thinkfunc_t -{ - BASEPTR m_pfnThink; - string_t m_iszContext; - int m_nNextThinkTick; - int m_nLastThinkTick; - - DECLARE_SIMPLE_DATADESC(); -}; - -struct EmitSound_t; -struct rotatingpushmove_t; - -#define CREATE_PREDICTED_ENTITY( className ) \ - CBaseEntity::CreatePredictedEntityByName( className, __FILE__, __LINE__ ); - -// -// Base Entity. All entity types derive from this -// -class CBaseEntity : public IServerEntity -{ -public: - DECLARE_CLASS_NOBASE( CBaseEntity ); - - //---------------------------------------- - // Class vars and functions - //---------------------------------------- - static inline void Debug_Pause(bool bPause); - static inline bool Debug_IsPaused(void); - static inline void Debug_SetSteps(int nSteps); - static inline bool Debug_ShouldStep(void); - static inline bool Debug_Step(void); - - static bool m_bInDebugSelect; - static int m_nDebugPlayer; - -protected: - - static bool m_bDebugPause; // Whether entity i/o is paused for debugging. - static int m_nDebugSteps; // Number of entity outputs to fire before pausing again. - - static bool sm_bDisableTouchFuncs; // Disables PhysicsTouch and PhysicsStartTouch function calls -public: - static bool sm_bAccurateTriggerBboxChecks; // SOLID_BBOX entities do a fully accurate trigger vs bbox check when this is set - -public: - // If bServerOnly is true, then the ent never goes to the client. This is used - // by logical entities. - CBaseEntity( bool bServerOnly=false ); - virtual ~CBaseEntity(); - - // prediction system - DECLARE_PREDICTABLE(); - // network data - DECLARE_SERVERCLASS(); - // data description - DECLARE_DATADESC(); - - // memory handling - void *operator new( size_t stAllocateBlock ); - void *operator new( size_t stAllocateBlock, int nBlockUse, const char *pFileName, int nLine ); - void operator delete( void *pMem ); - void operator delete( void *pMem, int nBlockUse, const char *pFileName, int nLine ) { operator delete(pMem); } - - // Class factory - static CBaseEntity *CreatePredictedEntityByName( const char *classname, const char *module, int line, bool persist = false ); - -// IHandleEntity overrides. -public: - virtual void SetRefEHandle( const CBaseHandle &handle ); - virtual const CBaseHandle& GetRefEHandle() const; - -// IServerUnknown overrides - virtual ICollideable *GetCollideable(); - virtual IServerNetworkable *GetNetworkable(); - virtual CBaseEntity *GetBaseEntity(); - -// IServerEntity overrides. -public: - virtual void SetModelIndex( int index ); - virtual int GetModelIndex( void ) const; - virtual string_t GetModelName( void ) const; - -public: - // virtual methods for derived classes to override - virtual bool TestCollision( const Ray_t& ray, unsigned int mask, trace_t& trace ); - virtual bool TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ); - virtual void ComputeWorldSpaceSurroundingBox( Vector *pWorldMins, Vector *pWorldMaxs ); - - // non-virtual methods. Don't override these! -public: - // An inline version the game code can use - CCollisionProperty *CollisionProp(); - const CCollisionProperty*CollisionProp() const; - CServerNetworkProperty *NetworkProp(); - const CServerNetworkProperty *NetworkProp() const; - - bool IsCurrentlyTouching( void ) const; - const Vector& GetAbsOrigin( void ) const; - const QAngle& GetAbsAngles( void ) const; - - SolidType_t GetSolid() const; - int GetSolidFlags( void ) const; - - int GetEFlags() const; - void SetEFlags( int iEFlags ); - void AddEFlags( int nEFlagMask ); - void RemoveEFlags( int nEFlagMask ); - bool IsEFlagSet( int nEFlagMask ) const; - - // Quick way to ask if we have a player entity as a child anywhere in our hierarchy. - void RecalcHasPlayerChildBit(); - bool DoesHavePlayerChild(); - - bool IsTransparent() const; - - void SetNavIgnore( float duration = FLT_MAX ); - void ClearNavIgnore(); - bool IsNavIgnored() const; - - // Is the entity floating? - bool IsFloating(); - - // Called by physics to see if we should avoid a collision test.... - virtual bool ShouldCollide( int collisionGroup, int contentsMask ) const; - - // Move type / move collide - MoveType_t GetMoveType() const; - MoveCollide_t GetMoveCollide() const; - void SetMoveType( MoveType_t val, MoveCollide_t moveCollide = MOVECOLLIDE_DEFAULT ); - void SetMoveCollide( MoveCollide_t val ); - - // Returns the entity-to-world transform - matrix3x4_t &EntityToWorldTransform(); - const matrix3x4_t &EntityToWorldTransform() const; - - // Some helper methods that transform a point from entity space to world space + back - void EntityToWorldSpace( const Vector &in, Vector *pOut ) const; - void WorldToEntitySpace( const Vector &in, Vector *pOut ) const; - - // This function gets your parent's transform. If you're parented to an attachment, - // this calculates the attachment's transform and gives you that. - // - // You must pass in tempMatrix for scratch space - it may need to fill that in and return it instead of - // pointing you right at a variable in your parent. - matrix3x4_t& GetParentToWorldTransform( matrix3x4_t &tempMatrix ); - - // Externalized data objects ( see sharreddefs.h for DataObjectType_t ) - bool HasDataObjectType( int type ) const; - void AddDataObjectType( int type ); - void RemoveDataObjectType( int type ); - - void *GetDataObject( int type ); - void *CreateDataObject( int type ); - void DestroyDataObject( int type ); - void DestroyAllDataObjects( void ); - - // virtual methods; you can override these -public: - // Owner entity. - // FIXME: These are virtual only because of CNodeEnt - CBaseEntity *GetOwnerEntity() const; - virtual void SetOwnerEntity( CBaseEntity* pOwner ); - void SetEffectEntity( CBaseEntity *pEffectEnt ); - CBaseEntity *GetEffectEntity() const; - - // Only CBaseEntity implements these. CheckTransmit calls the virtual ShouldTransmit to see if the - // entity wants to be sent. If so, it calls SetTransmit, which will mark any dependents for transmission too. - virtual int ShouldTransmit( const CCheckTransmitInfo *pInfo ); - - // update the global transmit state if a transmission rule changed - int SetTransmitState( int nFlag); - int GetTransmitState( void ); - int DispatchUpdateTransmitState(); - - // Do NOT call this directly. Use DispatchUpdateTransmitState. - virtual int UpdateTransmitState(); - - // Entities (like ropes) use this to own the transmit state of another entity - // by forcing it to not call UpdateTransmitState. - void IncrementTransmitStateOwnedCounter(); - void DecrementTransmitStateOwnedCounter(); - - // This marks the entity for transmission and passes the SetTransmit call to any dependents. - virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ); - - // This function finds out if the entity is in the 3D skybox. If so, it sets the EFL_IN_SKYBOX - // flag so the entity gets transmitted to all the clients. - // Entities usually call this during their Activate(). - // Returns true if the entity is in the skybox (and EFL_IN_SKYBOX was set). - bool DetectInSkybox(); - - // Returns which skybox the entity is in - CSkyCamera *GetEntitySkybox(); - - bool IsSimulatedEveryTick() const; - bool IsAnimatedEveryTick() const; - void SetSimulatedEveryTick( bool sim ); - void SetAnimatedEveryTick( bool anim ); - -public: - - virtual const char *GetTracerType( void ); - - // returns a pointer to the entities edict, if it has one. should be removed! - inline edict_t *edict( void ) { return NetworkProp()->edict(); } - inline const edict_t *edict( void ) const { return NetworkProp()->edict(); } - inline int entindex( ) const { return m_Network.entindex(); }; - inline int GetSoundSourceIndex() const { return entindex(); } - - // These methods encapsulate MOVETYPE_FOLLOW, which became obsolete - void FollowEntity( CBaseEntity *pBaseEntity, bool bBoneMerge = true ); - void StopFollowingEntity( ); // will also change to MOVETYPE_NONE - bool IsFollowingEntity(); - CBaseEntity *GetFollowedEntity(); - - // initialization - virtual void Spawn( void ); - virtual void Precache( void ) {} - - virtual void SetModel( const char *szModelName ); - - virtual void PostConstructor( const char *szClassname ); - virtual void PostClientActive( void ); - virtual void ParseMapData( CEntityMapData *mapData ); - virtual bool KeyValue( const char *szKeyName, const char *szValue ); - virtual bool KeyValue( const char *szKeyName, float flValue ); - virtual bool KeyValue( const char *szKeyName, const Vector &vecValue ); - virtual bool GetKeyValue( const char *szKeyName, char *szValue, int iMaxLen ); - - void ValidateEntityConnections(); - void FireNamedOutput( const char *pszOutput, variant_t variant, CBaseEntity *pActivator, CBaseEntity *pCaller, float flDelay = 0.0f ); - - // Activate - called for each entity after each load game and level load - virtual void Activate( void ); - - // Called once per frame after the server frame loop has finished and after all messages being - // sent to clients have been sent. - // NOTE: This will not be called unless the entity requests it via gEntList.AddPostClientMessageEntity - void PostClientMessagesSent( void ); - - // Hierarchy traversal - CBaseEntity *GetMoveParent( void ); - CBaseEntity *GetRootMoveParent(); - CBaseEntity *FirstMoveChild( void ); - CBaseEntity *NextMovePeer( void ); - - void SetName( string_t newTarget ); - void SetParent( string_t newParent, CBaseEntity *pActivator, int iAttachment = -1 ); - - // Set the movement parent. Your local origin and angles will become relative to this parent. - // If iAttachment is a valid attachment on the parent, then your local origin and angles - // are relative to the attachment on this entity. If iAttachment == -1, it'll preserve the - // current m_iParentAttachment. - virtual void SetParent( CBaseEntity* pNewParent, int iAttachment = -1 ); - CBaseEntity* GetParent(); - int GetParentAttachment(); - - string_t GetEntityName(); - - bool NameMatches( const char *pszNameOrWildcard ); - bool ClassMatches( const char *pszClassOrWildcard ); - bool NameMatches( string_t nameStr ); - bool ClassMatches( string_t nameStr ); - -private: - bool NameMatchesComplex( const char *pszNameOrWildcard ); - bool ClassMatchesComplex( const char *pszClassOrWildcard ); - void TransformStepData_WorldToParent( CBaseEntity *pParent ); - void TransformStepData_ParentToParent( CBaseEntity *pOldParent, CBaseEntity *pNewParent ); - void TransformStepData_ParentToWorld( CBaseEntity *pParent ); - - -public: - int GetSpawnFlags( void ) const; - void AddSpawnFlags( int nFlags ); - void RemoveSpawnFlags( int nFlags ); - void ClearSpawnFlags( void ); - bool HasSpawnFlags( int nFlags ) const; - - int GetEffects( void ) const; - void AddEffects( int nEffects ); - void RemoveEffects( int nEffects ); - void ClearEffects( void ); - void SetEffects( int nEffects ); - bool IsEffectActive( int nEffects ) const; - - // makes the entity inactive - void MakeDormant( void ); - int IsDormant( void ); - - void RemoveDeferred( void ); // Sets the entity invisible, and makes it remove itself on the next frame - - // checks to see if the entity is marked for deletion - bool IsMarkedForDeletion( void ); - - // capabilities - virtual int ObjectCaps( void ); - - // Verifies that the data description is valid in debug builds. - #ifdef _DEBUG - void ValidateDataDescription(void); - #endif // _DEBUG - - // handles an input (usually caused by outputs) - // returns true if the the value in the pass in should be set, false if the input is to be ignored - virtual bool AcceptInput( const char *szInputName, CBaseEntity *pActivator, CBaseEntity *pCaller, variant_t Value, int outputID ); - - // - // Input handlers. - // - void InputAlternativeSorting( inputdata_t &inputdata ); - void InputAlpha( inputdata_t &inputdata ); - void InputColor( inputdata_t &inputdata ); - void InputSetParent( inputdata_t &inputdata ); - void SetParentAttachment( const char *szInputName, const char *szAttachment, bool bMaintainOffset ); - void InputSetParentAttachment( inputdata_t &inputdata ); - void InputSetParentAttachmentMaintainOffset( inputdata_t &inputdata ); - void InputClearParent( inputdata_t &inputdata ); - void InputSetTeam( inputdata_t &inputdata ); - void InputUse( inputdata_t &inputdata ); - void InputKill( inputdata_t &inputdata ); - void InputKillHierarchy( inputdata_t &inputdata ); - void InputSetDamageFilter( inputdata_t &inputdata ); - void InputDispatchEffect( inputdata_t &inputdata ); - void InputEnableDamageForces( inputdata_t &inputdata ); - void InputDisableDamageForces( inputdata_t &inputdata ); - void InputAddContext( inputdata_t &inputdata ); - void InputRemoveContext( inputdata_t &inputdata ); - void InputClearContext( inputdata_t &inputdata ); - void InputDispatchResponse( inputdata_t& inputdata ); - void InputDisableShadow( inputdata_t &inputdata ); - void InputEnableShadow( inputdata_t &inputdata ); - void InputAddOutput( inputdata_t &inputdata ); - void InputFireUser1( inputdata_t &inputdata ); - void InputFireUser2( inputdata_t &inputdata ); - void InputFireUser3( inputdata_t &inputdata ); - void InputFireUser4( inputdata_t &inputdata ); - - // Returns the origin at which to play an inputted dispatcheffect - virtual void GetInputDispatchEffectPosition( const char *sInputString, Vector &pOrigin, QAngle &pAngles ); - - // tries to read a field from the entities data description - result is placed in variant_t - bool ReadKeyField( const char *varName, variant_t *var ); - - // classname access - void SetClassname( const char *className ); - const char* GetClassname(); - - // Debug Overlays - void EntityText( int text_offset, const char *text, float flDuration, int r = 255, int g = 255, int b = 255, int a = 255 ); - const char *GetDebugName(void); // do not make this virtual -- designed to handle NULL this - virtual void DrawDebugGeometryOverlays(void); - virtual int DrawDebugTextOverlays(void); - void DrawTimedOverlays( void ); - void DrawBBoxOverlay( float flDuration = 0.0f ); - void DrawAbsBoxOverlay(); - void DrawRBoxOverlay(); - - void DrawInputOverlay(const char *szInputName, CBaseEntity *pCaller, variant_t Value); - void DrawOutputOverlay(CEventAction *ev); - void SendDebugPivotOverlay( void ); - void AddTimedOverlay( const char *msg, int endTime ); - - void SetSolid( SolidType_t val ); - - // save/restore - // only overload these if you have special data to serialize - virtual int Save( ISave &save ); - virtual int Restore( IRestore &restore ); - virtual bool ShouldSavePhysics(); - - // handler to reset stuff before you are restored - // NOTE: Always chain to base class when implementing this! - virtual void OnSave( IEntitySaveUtils *pSaveUtils ); - - // handler to reset stuff after you are restored - // called after all entities have been loaded from all affected levels - // called before activate - // NOTE: Always chain to base class when implementing this! - virtual void OnRestore(); - - int GetTextureFrameIndex( void ); - void SetTextureFrameIndex( int iIndex ); - - // Entities block Line-Of-Sight for NPCs by default. - // Set this to false if you want to change this behavior. - void SetBlocksLOS( bool bBlocksLOS ); - bool BlocksLOS( void ); - - - void SetAIWalkable( bool bBlocksLOS ); - bool IsAIWalkable( void ); -private: - int SaveDataDescBlock( ISave &save, datamap_t *dmap ); - int RestoreDataDescBlock( IRestore &restore, datamap_t *dmap ); - -public: - // Networking related methods - void NetworkStateChanged(); - void NetworkStateChanged( void *pVar ); - -public: - void CalcAbsolutePosition(); - - // returns the edict index the entity requires when used in save/restore (eg players, world) - // -1 means it doesn't require any special index - virtual int RequiredEdictIndex( void ) { return -1; } - - // interface function pts - void (CBaseEntity::*m_pfnMoveDone)(void); - virtual void MoveDone( void ) { if (m_pfnMoveDone) (this->*m_pfnMoveDone)();}; - - // Why do we have two separate static Instance functions? - static CBaseEntity *Instance( const CBaseHandle &hEnt ); - static CBaseEntity *Instance( const edict_t *pent ); - static CBaseEntity *Instance( edict_t *pent ); - static CBaseEntity* Instance( int iEnt ); - - // Think function handling - void (CBaseEntity::*m_pfnThink)(void); - virtual void Think( void ) { if (m_pfnThink) (this->*m_pfnThink)();}; - - // Think functions with contexts - int RegisterThinkContext( const char *szContext ); - BASEPTR ThinkSet( BASEPTR func, float flNextThinkTime = 0, const char *szContext = NULL ); - void SetNextThink( float nextThinkTime, const char *szContext = NULL ); - float GetNextThink( const char *szContext = NULL ); - float GetLastThink( const char *szContext = NULL ); - int GetNextThinkTick( const char *szContext = NULL ); - int GetLastThinkTick( const char *szContext = NULL ); - - float GetAnimTime() const; - void SetAnimTime( float at ); - - float GetSimulationTime() const; - void SetSimulationTime( float st ); - - void SetRenderMode( RenderMode_t nRenderMode ); - RenderMode_t GetRenderMode() const; - -private: - // NOTE: Keep this near vtable so it's in cache with vtable. - CServerNetworkProperty m_Network; - -public: - // members - string_t m_iClassname; // identifier for entity creation and save/restore - string_t m_iGlobalname; // identifier for carrying entity across level transitions - string_t m_iParent; // the name of the entities parent; linked into m_pParent during Activate() - - int m_iHammerID; // Hammer unique edit id number - -public: - // was pev->speed - float m_flSpeed; - // was pev->renderfx - CNetworkVar( unsigned char, m_nRenderFX ); - // was pev->rendermode - CNetworkVar( unsigned char, m_nRenderMode ); - CNetworkVar( short, m_nModelIndex ); - // was pev->rendercolor - CNetworkColor32( m_clrRender ); - const color32 GetRenderColor() const; - void SetRenderColor( byte r, byte g, byte b ); - void SetRenderColor( byte r, byte g, byte b, byte a ); - void SetRenderColorR( byte r ); - void SetRenderColorG( byte g ); - void SetRenderColorB( byte b ); - void SetRenderColorA( byte a ); - - // was pev->animtime: consider moving to CBaseAnimating - float m_flPrevAnimTime; - CNetworkVar( float, m_flAnimTime ); // this is the point in time that the client will interpolate to position,angle,frame,etc. - CNetworkVar( float, m_flSimulationTime ); - - int m_nLastThinkTick; - -#if !defined( NO_ENTITY_PREDICTION ) - // Certain entities (projectiles) can be created on the client and thus need a matching id number - CNetworkVar( CPredictableId, m_PredictableID ); -#endif - - // used so we know when things are no longer touching - int touchStamp; - -protected: - - // think function handling - enum thinkmethods_t - { - THINK_FIRE_ALL_FUNCTIONS, - THINK_FIRE_BASE_ONLY, - THINK_FIRE_ALL_BUT_BASE, - }; - int GetIndexForThinkContext( const char *pszContext ); - CUtlVector< thinkfunc_t > m_aThinkFunctions; - -#ifdef _DEBUG - int m_iCurrentThinkContext; -#endif - - void RemoveExpiredConcepts( void ); - int GetContextCount() const; // Call RemoveExpiredConcepts to clean out expired concepts - const char *GetContextName( int index ) const; // note: context may be expired - const char *GetContextValue( int index ) const; // note: context may be expired - bool ContextExpired( int index ) const; - int FindContextByName( const char *name ) const; -public: - void AddContext( const char *nameandvalue ); - -protected: - CUtlVector< ResponseContext_t > m_ResponseContexts; - - // Map defined context sets - string_t m_iszResponseContext; - -private: - CBaseEntity( CBaseEntity& ); - - // list handling - friend class CGlobalEntityList; - friend class CThinkSyncTester; - - // was pev->nextthink - CNetworkVarForDerived( int, m_nNextThinkTick ); - // was pev->effects - CNetworkVar( int, m_fEffects ); - -//////////////////////////////////////////////////////////////////////////// - - -public: - - // Returns a CBaseAnimating if the entity is derived from CBaseAnimating. - virtual CBaseAnimating* GetBaseAnimating() { return 0; } - - virtual IResponseSystem *GetResponseSystem(); - virtual void DispatchResponse( const char *conceptName ); - -// Classify - returns the type of group (i.e, "houndeye", or "human military" so that NPCs with different classnames -// still realize that they are teammates. (overridden for NPCs that form groups) - virtual Class_T Classify ( void ); - virtual void DeathNotice ( CBaseEntity *pVictim ) {}// NPC maker children use this to tell the NPC maker that they have died. - virtual bool ShouldAttractAutoAim( CBaseEntity *pAimingEnt ) { return ((GetFlags() & FL_AIMTARGET) != 0); } - virtual float GetAutoAimRadius(); - virtual Vector GetAutoAimCenter() { return WorldSpaceCenter(); } - - virtual ITraceFilter* GetBeamTraceFilter( void ); - - // Call this to do a TraceAttack on an entity, performs filtering. Don't call TraceAttack() directly except when chaining up to base class - void DispatchTraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - virtual bool PassesDamageFilter( const CTakeDamageInfo &info ); - - -protected: - virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - -public: - - virtual bool CanBeHitByMeleeAttack( CBaseEntity *pAttacker ) { return true; } - - // returns the amount of damage inflicted - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - - // This is what you should call to apply damage to an entity. - void TakeDamage( const CTakeDamageInfo &info ); - - virtual int TakeHealth( float flHealth, int bitsDamageType ); - - virtual bool IsAlive( void ); - // Entity killed (only fired once) - virtual void Event_Killed( const CTakeDamageInfo &info ); - - void SendOnKilledGameEvent( const CTakeDamageInfo &info ); - - // Notifier that I've killed some other entity. (called from Victim's Event_Killed). - virtual void Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info ) { return; } - - // UNDONE: Make this data? - virtual int BloodColor( void ); - - void TraceBleed( float flDamage, const Vector &vecDir, trace_t *ptr, int bitsDamageType ); - virtual bool IsTriggered( CBaseEntity *pActivator ) {return true;} - virtual bool IsNPC( void ) const { return false; } - CAI_BaseNPC *MyNPCPointer( void ); - virtual CBaseCombatCharacter *MyCombatCharacterPointer( void ) { return NULL; } - virtual float GetDelay( void ) { return 0; } - virtual bool IsMoving( void ); - bool IsWorld() { return entindex() == 0; } - virtual char const *DamageDecal( int bitsDamageType, int gameMaterial ); - virtual void DecalTrace( trace_t *pTrace, char const *decalName ); - virtual void ImpactTrace( trace_t *pTrace, int iDamageType, const char *pCustomImpactName = NULL ); - - void AddPoints( int score, bool bAllowNegativeScore ); - void AddPointsToTeam( int score, bool bAllowNegativeScore ); - void RemoveAllDecals( void ); - - virtual bool OnControls( CBaseEntity *pControls ) { return false; } - virtual bool HasTarget( string_t targetname ); - virtual bool IsPlayer( void ) const { return false; } - virtual bool IsNetClient( void ) const { return false; } - virtual bool IsTemplate( void ) { return false; } - virtual bool IsBaseObject( void ) const { return false; } - virtual bool IsBaseTrain( void ) const { return false; } - bool IsBSPModel() const; - bool IsInWorld( void ) const; - - // If this is a vehicle, returns the vehicle interface - virtual IServerVehicle* GetServerVehicle() { return NULL; } - - // UNDONE: Make this data instead of procedural? - virtual bool IsViewable( void ); // is this something that would be looked at (model, sprite, etc.)? - - // Team Handling - CTeam *GetTeam( void ) const; // Get the Team this entity is on - int GetTeamNumber( void ) const; // Get the Team number of the team this entity is on - virtual void ChangeTeam( int iTeamNum ); // Assign this entity to a team. - bool IsInTeam( CTeam *pTeam ) const; // Returns true if this entity's in the specified team - bool InSameTeam( CBaseEntity *pEntity ) const; // Returns true if the specified entity is on the same team as this one - bool IsInAnyTeam( void ) const; // Returns true if this entity is in any team - const char *TeamID( void ) const; // Returns the name of the team this entity is on. - - // Entity events... these are events targetted to a particular entity - // Each event defines its own well-defined event data structure - virtual void OnEntityEvent( EntityEvent_t event, void *pEventData ); - - // can stand on this entity? - bool IsStandable() const; - - // UNDONE: Do these three functions actually need to be virtual??? - virtual bool CanStandOn( CBaseEntity *pSurface ) const { return (pSurface && !pSurface->IsStandable()) ? false : true; } - virtual bool CanStandOn( edict_t *ent ) const { return CanStandOn( GetContainingEntity( ent ) ); } - virtual CBaseEntity *GetEnemy( void ) { return NULL; } - virtual CBaseEntity *GetEnemy( void ) const { return NULL; } - - - void ViewPunch( const QAngle &angleOffset ); - void VelocityPunch( const Vector &vecForce ); - - CBaseEntity *GetNextTarget( void ); - - // fundamental callbacks - void (CBaseEntity ::*m_pfnTouch)( CBaseEntity *pOther ); - void (CBaseEntity ::*m_pfnUse)( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - void (CBaseEntity ::*m_pfnBlocked)( CBaseEntity *pOther ); - - virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - virtual void StartTouch( CBaseEntity *pOther ); - virtual void Touch( CBaseEntity *pOther ); - virtual void EndTouch( CBaseEntity *pOther ); - virtual void StartBlocked( CBaseEntity *pOther ) {} - virtual void Blocked( CBaseEntity *pOther ); - virtual void EndBlocked( void ) {} - - // Physics simulation - virtual void PhysicsSimulate( void ); - -public: - // HACKHACK:Get the trace_t from the last physics touch call (replaces the even-hackier global trace vars) - static const trace_t & GetTouchTrace( void ); - - // FIXME: Should be private, but I can't make em private just yet - void PhysicsImpact( CBaseEntity *other, trace_t &trace ); - void PhysicsMarkEntitiesAsTouching( CBaseEntity *other, trace_t &trace ); - void PhysicsMarkEntitiesAsTouchingEventDriven( CBaseEntity *other, trace_t &trace ); - void PhysicsTouchTriggers( const Vector *pPrevAbsOrigin = NULL ); - - // Physics helper - static void PhysicsRemoveTouchedList( CBaseEntity *ent ); - static void PhysicsNotifyOtherOfUntouch( CBaseEntity *ent, CBaseEntity *other ); - static void PhysicsRemoveToucher( CBaseEntity *other, touchlink_t *link ); - - groundlink_t *AddEntityToGroundList( CBaseEntity *other ); - void PhysicsStartGroundContact( CBaseEntity *pentOther ); - - static void PhysicsNotifyOtherOfGroundRemoval( CBaseEntity *ent, CBaseEntity *other ); - static void PhysicsRemoveGround( CBaseEntity *other, groundlink_t *link ); - static void PhysicsRemoveGroundList( CBaseEntity *ent ); - - void StartGroundContact( CBaseEntity *ground ); - void EndGroundContact( CBaseEntity *ground ); - - void SetGroundChangeTime( float flTime ); - float GetGroundChangeTime( void ); - - // Remove this as ground entity for all object resting on this object - void WakeRestingObjects(); - bool HasNPCsOnIt(); - - virtual void UpdateOnRemove( void ); - virtual void StopLoopingSounds( void ) {} - - // common member functions - void SUB_Remove( void ); - void SUB_DoNothing( void ); - void SUB_StartFadeOut( float delay = 10.0f, bool bNotSolid = true ); - void SUB_StartFadeOutInstant(); - void SUB_FadeOut ( void ); - void SUB_Vanish( void ); - void SUB_CallUseToggle( void ) { this->Use( this, this, USE_TOGGLE, 0 ); } - void SUB_PerformFadeOut( void ); - virtual bool SUB_AllowedToFade( void ); - - // change position, velocity, orientation instantly - // passing NULL means no change - virtual void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ); - // notify that another entity (that you were watching) was teleported - virtual void NotifySystemEvent( CBaseEntity *pNotify, notify_system_event_t eventType, const notify_system_event_params_t ¶ms ); - - int ShouldToggle( USE_TYPE useType, int currentState ); - - // UNDONE: Move these virtuals to CBaseCombatCharacter? - virtual void MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ); - virtual int GetTracerAttachment( void ); - virtual void FireBullets( const FireBulletsInfo_t &info ); - virtual void DoImpactEffect( trace_t &tr, int nDamageType ); // give shooter a chance to do a custom impact. - - // OLD VERSION! Use the struct version - void FireBullets( int cShots, const Vector &vecSrc, const Vector &vecDirShooting, - const Vector &vecSpread, float flDistance, int iAmmoType, int iTracerFreq = 4, - int firingEntID = -1, int attachmentID = -1, int iDamage = 0, - CBaseEntity *pAttacker = NULL, bool bFirstShotAccurate = false, bool bPrimaryAttack = true ); - - virtual CBaseEntity *Respawn( void ) { return NULL; } - - // Method used to deal with attacks passing through triggers - void TraceAttackToTriggers( const CTakeDamageInfo &info, const Vector& start, const Vector& end, const Vector& dir ); - - // Do the bounding boxes of these two intersect? - bool Intersects( CBaseEntity *pOther ); - virtual bool IsLockedByMaster( void ) { return false; } - - // Health accessors. - int GetMaxHealth() const { return m_iMaxHealth; } - void SetMaxHealth( int amt ) { m_iMaxHealth = amt; } - - int GetHealth() const { return m_iHealth; } - void SetHealth( int amt ) { m_iHealth = amt; } - - // Ugly code to lookup all functions to make sure they are in the table when set. -#ifdef _DEBUG - void FunctionCheck( void *pFunction, const char *name ); - - ENTITYFUNCPTR TouchSet( ENTITYFUNCPTR func, const char *name ) - { - COMPILE_TIME_ASSERT( sizeof(func) == MFP_SIZE ); - m_pfnTouch = func; - FunctionCheck( *(reinterpret_cast(&m_pfnTouch)), name ); - return func; - } - USEPTR UseSet( USEPTR func, const char *name ) - { - COMPILE_TIME_ASSERT( sizeof(func) == MFP_SIZE ); - m_pfnUse = func; - FunctionCheck( *(reinterpret_cast(&m_pfnUse)), name ); - return func; - } - ENTITYFUNCPTR BlockedSet( ENTITYFUNCPTR func, const char *name ) - { - COMPILE_TIME_ASSERT( sizeof(func) == MFP_SIZE ); - m_pfnBlocked = func; - FunctionCheck( *(reinterpret_cast(&m_pfnBlocked)), name ); - return func; - } - -#endif - virtual void ModifyOrAppendCriteria( AI_CriteriaSet& set ); - void AppendContextToCriteria( AI_CriteriaSet& set, const char *prefix = "" ); - void DumpResponseCriteria( void ); - -private: - friend class CAI_Senses; - CBaseEntity *m_pLink;// used for temporary link-list operations. - -public: - // variables promoted from edict_t - string_t m_target; - CNetworkVarForDerived( int, m_iMaxHealth ); // CBaseEntity doesn't care about changes to this variable, but there are derived classes that do. - CNetworkVarForDerived( int, m_iHealth ); - - CNetworkVarForDerived( char, m_lifeState ); - CNetworkVarForDerived( char , m_takedamage ); - - // Damage filtering - string_t m_iszDamageFilterName; // The name of the entity to use as our damage filter. - EHANDLE m_hDamageFilter; // The entity that controls who can damage us. - - // Debugging / devolopment fields - int m_debugOverlays; // For debug only (bitfields) - TimedOverlay_t* m_pTimedOverlay; // For debug only - - // virtual functions used by a few classes - - // creates an entity of a specified class, by name - static CBaseEntity *Create( const char *szName, const Vector &vecOrigin, const QAngle &vecAngles, CBaseEntity *pOwner = NULL ); - static CBaseEntity *CreateNoSpawn( const char *szName, const Vector &vecOrigin, const QAngle &vecAngles, CBaseEntity *pOwner = NULL ); - - // Collision group accessors - int GetCollisionGroup() const; - void SetCollisionGroup( int collisionGroup ); - void CollisionRulesChanged(); - - // Damage accessors - virtual int GetDamageType() const; - virtual float GetDamage() { return 0; } - virtual void SetDamage(float flDamage) {} - - virtual Vector EyePosition( void ); // position of eyes - virtual const QAngle &EyeAngles( void ); // Direction of eyes in world space - virtual const QAngle &LocalEyeAngles( void ); // Direction of eyes - virtual Vector EarPosition( void ); // position of ears - - Vector EyePosition( void ) const; // position of eyes - const QAngle &EyeAngles( void ) const; // Direction of eyes in world space - const QAngle &LocalEyeAngles( void ) const; // Direction of eyes - Vector EarPosition( void ) const; // position of ears - - virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true); // position to shoot at - virtual Vector HeadTarget( const Vector &posSrc ); - virtual void GetVectors(Vector* forward, Vector* right, Vector* up) const; - - virtual const Vector &GetViewOffset() { return m_vecViewOffset.Get(); } - const Vector &GetViewOffset() const { return const_cast(this)->GetViewOffset(); } - void SetViewOffset( const Vector &vecOffset ); - - // NOTE: Setting the abs velocity in either space will cause a recomputation - // in the other space, so setting the abs velocity will also set the local vel - void SetLocalVelocity( const Vector &vecVelocity ); - void ApplyLocalVelocityImpulse( const Vector &vecImpulse ); - void SetAbsVelocity( const Vector &vecVelocity ); - void ApplyAbsVelocityImpulse( const Vector &vecImpulse ); - void ApplyLocalAngularVelocityImpulse( const AngularImpulse &angImpulse ); - - const Vector& GetLocalVelocity( ) const; - const Vector& GetAbsVelocity( ) const; - - // NOTE: Setting the abs velocity in either space will cause a recomputation - // in the other space, so setting the abs velocity will also set the local vel - void SetLocalAngularVelocity( const QAngle &vecAngVelocity ); - const QAngle& GetLocalAngularVelocity( ) const; - - // FIXME: While we're using (dPitch, dYaw, dRoll) as our local angular velocity - // representation, we can't actually solve this problem -// void SetAbsAngularVelocity( const QAngle &vecAngVelocity ); -// const QAngle& GetAbsAngularVelocity( ) const; - - const Vector& GetBaseVelocity() const; - void SetBaseVelocity( const Vector& v ); - - virtual Vector GetSmoothedVelocity( void ); - - // FIXME: Figure out what to do about this - virtual void GetVelocity(Vector *vVelocity, AngularImpulse *vAngVelocity = NULL); - - float GetGravity( void ) const; - void SetGravity( float gravity ); - float GetFriction( void ) const; - void SetFriction( float flFriction ); - - virtual bool FVisible ( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ); - virtual bool FVisible( const Vector &vecTarget, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ); - - virtual bool CanBeSeenBy( CAI_BaseNPC *pNPC ) { return true; } // allows entities to be 'invisible' to NPC senses. - - // This function returns a value that scales all damage done by this entity. - // Use CDamageModifier to hook in damage modifiers on a guy. - virtual float GetAttackDamageScale( CBaseEntity *pVictim ); - // This returns a value that scales all damage done to this entity - // Use CDamageModifier to hook in damage modifiers on a guy. - virtual float GetReceivedDamageScale( CBaseEntity *pAttacker ); - - void SetCheckUntouch( bool check ); - bool GetCheckUntouch() const; - - void SetGroundEntity( CBaseEntity *ground ); - CBaseEntity *GetGroundEntity( void ); - CBaseEntity *GetGroundEntity( void ) const { return const_cast(this)->GetGroundEntity(); } - - // Gets the velocity we impart to a player standing on us - virtual void GetGroundVelocityToApply( Vector &vecGroundVel ) { vecGroundVel = vec3_origin; } - - int GetWaterLevel() const; - void SetWaterLevel( int nLevel ); - int GetWaterType() const; - void SetWaterType( int nType ); - - virtual bool PhysicsSplash( const Vector ¢erPoint, const Vector &normal, float rawSpeed, float scaledSpeed ) { return false; } - virtual void Splash() {} - - void ClearSolidFlags( void ); - void RemoveSolidFlags( int flags ); - void AddSolidFlags( int flags ); - bool IsSolidFlagSet( int flagMask ) const; - void SetSolidFlags( int flags ); - bool IsSolid() const; - - void SetModelName( string_t name ); - - model_t *GetModel( void ); - - // These methods return a *world-aligned* box relative to the absorigin of the entity. - // This is used for collision purposes and is *not* guaranteed - // to surround the entire entity's visual representation - // NOTE: It is illegal to ask for the world-aligned bounds for - // SOLID_BSP objects - const Vector& WorldAlignMins( ) const; - const Vector& WorldAlignMaxs( ) const; - - // This defines collision bounds in OBB space - void SetCollisionBounds( const Vector& mins, const Vector &maxs ); - - // NOTE: The world space center *may* move when the entity rotates. - virtual const Vector& WorldSpaceCenter( ) const; - const Vector& WorldAlignSize( ) const; - - // Returns a radius of a sphere - // *centered at the world space center* bounding the collision representation - // of the entity. NOTE: The world space center *may* move when the entity rotates. - float BoundingRadius() const; - bool IsPointSized() const; - - // NOTE: Setting the abs origin or angles will cause the local origin + angles to be set also - void SetAbsOrigin( const Vector& origin ); - void SetAbsAngles( const QAngle& angles ); - - // Origin and angles in local space ( relative to parent ) - // NOTE: Setting the local origin or angles will cause the abs origin + angles to be set also - void SetLocalOrigin( const Vector& origin ); - const Vector& GetLocalOrigin( void ) const; - - void SetLocalAngles( const QAngle& angles ); - const QAngle& GetLocalAngles( void ) const; - - void SetElasticity( float flElasticity ); - float GetElasticity( void ) const; - - void SetShadowCastDistance( float flDistance ); - float GetShadowCastDistance( void ) const; - void SetShadowCastDistance( float flDesiredDistance, float flDelay ); - - float GetLocalTime( void ) const; - void IncrementLocalTime( float flTimeDelta ); - float GetMoveDoneTime( ) const; - void SetMoveDoneTime( float flTime ); - - // Used by the PAS filters to ask the entity where in world space the sounds it emits come from. - // This is used right now because if you have something sitting on an incline, using our axis-aligned - // bounding boxes can return a position in solid space, so you won't hear sounds emitted by the object. - // For now, we're hacking around it by moving the sound emission origin up on certain objects like vehicles. - // - // When OBBs get in, this can probably go away. - virtual Vector GetSoundEmissionOrigin() const; - - void AddFlag( int flags ); - void RemoveFlag( int flagsToRemove ); - void ToggleFlag( int flagToToggle ); - int GetFlags( void ) const; - void ClearFlags( void ); - - // Sets the local position from a transform - void SetLocalTransform( const matrix3x4_t &localTransform ); - - // See CSoundEmitterSystem - void EmitSound( const char *soundname, float soundtime = 0.0f, float *duration = NULL ); // Override for doing the general case of CPASAttenuationFilter filter( this ), and EmitSound( filter, entindex(), etc. ); - void EmitSound( const char *soundname, HSOUNDSCRIPTHANDLE& handle, float soundtime = 0.0f, float *duration = NULL ); // Override for doing the general case of CPASAttenuationFilter filter( this ), and EmitSound( filter, entindex(), etc. ); - void StopSound( const char *soundname ); - void StopSound( const char *soundname, HSOUNDSCRIPTHANDLE& handle ); - void GenderExpandString( char const *in, char *out, int maxlen ); - - - static float GetSoundDuration( const char *soundname, char const *actormodel ); - - static bool GetParametersForSound( const char *soundname, CSoundParameters ¶ms, char const *actormodel ); - static bool GetParametersForSound( const char *soundname, HSOUNDSCRIPTHANDLE& handle, CSoundParameters ¶ms, char const *actormodel ); - - static void EmitSound( IRecipientFilter& filter, int iEntIndex, const char *soundname, const Vector *pOrigin = NULL, float soundtime = 0.0f, float *duration = NULL ); - static void EmitSound( IRecipientFilter& filter, int iEntIndex, const char *soundname, HSOUNDSCRIPTHANDLE& handle, const Vector *pOrigin = NULL, float soundtime = 0.0f, float *duration = NULL ); - static void StopSound( int iEntIndex, const char *soundname ); - static soundlevel_t LookupSoundLevel( const char *soundname ); - static soundlevel_t LookupSoundLevel( const char *soundname, HSOUNDSCRIPTHANDLE& handle ); - - static void EmitSound( IRecipientFilter& filter, int iEntIndex, const EmitSound_t & params ); - static void EmitSound( IRecipientFilter& filter, int iEntIndex, const EmitSound_t & params, HSOUNDSCRIPTHANDLE& handle ); - - static void StopSound( int iEntIndex, int iChannel, const char *pSample ); - - static void EmitAmbientSound( int entindex, const Vector& origin, const char *soundname, int flags = 0, float soundtime = 0.0f, float *duration = NULL ); - - // These files need to be listed in scripts/game_sounds_manifest.txt - static HSOUNDSCRIPTHANDLE PrecacheScriptSound( const char *soundname ); - static void PrefetchScriptSound( const char *soundname ); - - // For each client who appears to be a valid recipient, checks the client has disabled CC and if so, removes them from - // the recipient list. - static void RemoveRecipientsIfNotCloseCaptioning( CRecipientFilter& filter ); - static void EmitCloseCaption( IRecipientFilter& filter, int entindex, char const *token, CUtlVector< Vector >& soundorigins, float duration, bool warnifmissing = false ); - static void EmitSentenceByIndex( IRecipientFilter& filter, int iEntIndex, int iChannel, int iSentenceIndex, - float flVolume, soundlevel_t iSoundlevel, int iFlags = 0, int iPitch = PITCH_NORM, - const Vector *pOrigin = NULL, const Vector *pDirection = NULL, bool bUpdatePositions = true, float soundtime = 0.0f ); - - static bool IsPrecacheAllowed(); - static void SetAllowPrecache( bool allow ); - - static bool m_bAllowPrecache; - - static bool IsSimulatingOnAlternateTicks(); - -// void Relink() {} - -public: - - // VPHYSICS Integration ----------------------------------------------- - // - // -------------------------------------------------------------------- - // UNDONE: Move to IEntityVPhysics? or VPhysicsProp() ? - // Called after spawn, and in the case of self-managing objects, after load - virtual bool CreateVPhysics(); - - // Convenience routines to init the vphysics simulation for this object. - // This creates a static object. Something that behaves like world geometry - solid, but never moves - IPhysicsObject *VPhysicsInitStatic( void ); - - // This creates a normal vphysics simulated object - physics determines where it goes (gravity, friction, etc) - // and the entity receives updates from vphysics. SetAbsOrigin(), etc do not affect the object! - IPhysicsObject *VPhysicsInitNormal( SolidType_t solidType, int nSolidFlags, bool createAsleep, solid_t *pSolid = NULL ); - - // This creates a vphysics object with a shadow controller that follows the AI - // Move the object to where it should be and call UpdatePhysicsShadowToCurrentPosition() - IPhysicsObject *VPhysicsInitShadow( bool allowPhysicsMovement, bool allowPhysicsRotation, solid_t *pSolid = NULL ); - - // Force a non-solid (ie. solid_trigger) physics object to collide with other entities. - virtual bool ForceVPhysicsCollide( CBaseEntity *pEntity ) { return false; } - -private: - // called by all vphysics inits - bool VPhysicsInitSetup(); -public: - - void VPhysicsSetObject( IPhysicsObject *pPhysics ); - // destroy and remove the physics object for this entity - virtual void VPhysicsDestroyObject( void ); - void VPhysicsSwapObject( IPhysicsObject *pSwap ); - - inline IPhysicsObject *VPhysicsGetObject( void ) const { return m_pPhysicsObject; } - virtual void VPhysicsUpdate( IPhysicsObject *pPhysics ); - void VPhysicsUpdatePusher( IPhysicsObject *pPhysics ); - - // react physically to damage (called from CBaseEntity::OnTakeDamage() by default) - virtual int VPhysicsTakeDamage( const CTakeDamageInfo &info ); - virtual void VPhysicsShadowCollision( int index, gamevcollisionevent_t *pEvent ); - virtual void VPhysicsShadowUpdate( IPhysicsObject *pPhysics ) {} - virtual void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); - virtual void VPhysicsFriction( IPhysicsObject *pObject, float energy, int surfaceProps, int surfacePropsHit ); - - // update the shadow so it will coincide with the current AI position at some time - // in the future (or 0 for now) - virtual void UpdatePhysicsShadowToCurrentPosition( float deltaTime ); - virtual int VPhysicsGetObjectList( IPhysicsObject **pList, int listMax ); - virtual bool VPhysicsIsFlesh( void ); - // -------------------------------------------------------------------- - -public: -#if !defined( NO_ENTITY_PREDICTION ) - // The player drives simulation of this entity - void SetPlayerSimulated( CBasePlayer *pOwner ); - void UnsetPlayerSimulated( void ); - bool IsPlayerSimulated( void ) const; - CBasePlayer *GetSimulatingPlayer( void ); -#endif - // FIXME: Make these private! - void PhysicsCheckForEntityUntouch( void ); - bool PhysicsRunThink( thinkmethods_t thinkMethod = THINK_FIRE_ALL_FUNCTIONS ); - bool PhysicsRunSpecificThink( int nContextIndex, BASEPTR thinkFunc ); - bool PhysicsTestEntityPosition( CBaseEntity **ppEntity = NULL ); - void PhysicsPushEntity( const Vector& push, trace_t *pTrace ); - bool PhysicsCheckWater( void ); - void PhysicsCheckWaterTransition( void ); - void PhysicsStepRecheckGround(); - // Computes the water level + type - void UpdateWaterState(); - bool IsEdictFree() const { return edict()->IsFree(); } - - // Callbacks for the physgun/cannon picking up an entity - virtual CBasePlayer *HasPhysicsAttacker( float dt ) { return NULL; } - - // UNDONE: Make this data? - virtual unsigned int PhysicsSolidMaskForEntity( void ) const; - - // Computes the abs position of a point specified in local space - void ComputeAbsPosition( const Vector &vecLocalPosition, Vector *pAbsPosition ); - - // Computes the abs position of a direction specified in local space - void ComputeAbsDirection( const Vector &vecLocalDirection, Vector *pAbsDirection ); - - void SetPredictionEligible( bool canpredict ); - -protected: - // Invalidates the abs state of all children - void InvalidatePhysicsRecursive( int nChangeFlags ); - - int PhysicsClipVelocity (const Vector& in, const Vector& normal, Vector& out, float overbounce ); - void PhysicsRelinkChildren( float dt ); - - // Performs the collision resolution for fliers. - void PerformFlyCollisionResolution( trace_t &trace, Vector &move ); - void ResolveFlyCollisionBounce( trace_t &trace, Vector &vecVelocity, float flMinTotalElasticity = 0.0f ); - void ResolveFlyCollisionSlide( trace_t &trace, Vector &vecVelocity ); - virtual void ResolveFlyCollisionCustom( trace_t &trace, Vector &vecVelocity ); - -private: - // Physics-related private methods - void PhysicsStep( void ); - void PhysicsPusher( void ); - void PhysicsNone( void ); - void PhysicsNoclip( void ); - void PhysicsStepRunTimestep( float timestep ); - void PhysicsToss( void ); - void PhysicsCustom( void ); - void PerformPush( float movetime ); - - // Simulation in local space of rigid children - void PhysicsRigidChild( void ); - - // Computes the base velocity - void UpdateBaseVelocity( void ); - - // Implement this if you use MOVETYPE_CUSTOM - virtual void PerformCustomPhysics( Vector *pNewPosition, Vector *pNewVelocity, QAngle *pNewAngles, QAngle *pNewAngVelocity ); - - void PhysicsDispatchThink( BASEPTR thinkFunc ); - - touchlink_t *PhysicsMarkEntityAsTouched( CBaseEntity *other ); - void PhysicsTouch( CBaseEntity *pentOther ); - void PhysicsStartTouch( CBaseEntity *pentOther ); - - CBaseEntity *PhysicsPushMove( float movetime ); - CBaseEntity *PhysicsPushRotate( float movetime ); - - CBaseEntity *PhysicsCheckRotateMove( rotatingpushmove_t &rotPushmove, CBaseEntity **pPusherList, int pusherListCount ); - CBaseEntity *PhysicsCheckPushMove( const Vector& move, CBaseEntity **pPusherList, int pusherListCount ); - int PhysicsTryMove( float flTime, trace_t *steptrace ); - - void PhysicsCheckVelocity( void ); - void PhysicsAddHalfGravity( float timestep ); - void PhysicsAddGravityMove( Vector &move ); - - void CalcAbsoluteVelocity(); - void CalcAbsoluteAngularVelocity(); - - // Checks a sweep without actually performing the move - void PhysicsCheckSweep( const Vector& vecAbsStart, const Vector &vecAbsDelta, trace_t *pTrace ); - - // Computes new angles based on the angular velocity - void SimulateAngles( float flFrameTime ); - - void CheckStepSimulationChanged(); - // Run regular think and latch off angle/origin changes so we can interpolate them on the server to fake simulation - void StepSimulationThink( float dt ); - // Compute network origin - bool ComputeStepSimulationNetworkOrigin( StepSimulationData *step ); - bool ComputeStepSimulationNetworkAngles( StepSimulationData *step ); -public: - // Add a discontinuity to a step - bool AddStepDiscontinuity( float flTime, const Vector &vecOrigin, const QAngle &vecAngles ); - int GetFirstThinkTick(); // get first tick thinking on any context -private: - // origin and angles to use in step calculations - virtual Vector GetStepOrigin( void ) const; - virtual QAngle GetStepAngles( void ) const; - - // These set entity flags (EFL_*) to help optimize queries - void CheckHasThinkFunction( bool isThinkingHint = false ); - void CheckHasGamePhysicsSimulation(); - bool WillThink(); - bool WillSimulateGamePhysics(); - - - friend void SendProxy_Origin( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); - friend void SendProxy_Angles( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); - - friend class CPushBlockerEnum; - - // Sets/Gets the next think based on context index - void SetNextThink( int nContextIndex, float thinkTime ); - void SetLastThink( int nContextIndex, float thinkTime ); - float GetNextThink( int nContextIndex ) const; - int GetNextThinkTick( int nContextIndex ) const; - - // Shot statistics - void UpdateShotStatistics( const trace_t &tr ); - - // Handle shot entering water - bool HandleShotImpactingWater( const FireBulletsInfo_t &info, const Vector &vecEnd, ITraceFilter *pTraceFilter, Vector *pVecTracerDest ); - - // Handle shot entering water - void HandleShotImpactingGlass( const FireBulletsInfo_t &info, const trace_t &tr, const Vector &vecDir, ITraceFilter *pTraceFilter ); - - // Should we draw bubbles underwater? - bool ShouldDrawUnderwaterBulletBubbles(); - - // Computes the tracer start position - void ComputeTracerStartPosition( const Vector &vecShotSrc, Vector *pVecTracerStart ); - - // Computes the tracer start position - void CreateBubbleTrailTracer( const Vector &vecShotSrc, const Vector &vecShotEnd, const Vector &vecShotDir ); - - virtual bool ShouldDrawWaterImpacts() { return true; } - - // Changes shadow cast distance over time - void ShadowCastDistThink( ); - - // Precache model sounds + particles - static void PrecacheModelComponents( int nModelIndex ); - static void PrecacheSoundHelper( const char *pName ); - -protected: - // Which frame did I simulate? - int m_nSimulationTick; - - // FIXME: Make this private! Still too many references to do so... - CNetworkVar( int, m_spawnflags ); - -private: - int m_iEFlags; // entity flags EFL_* - // was pev->flags - CNetworkVarForDerived( int, m_fFlags ); - - string_t m_iName; // name used to identify this entity - - // Damage modifiers - friend class CDamageModifier; - CUtlLinkedList m_DamageModifiers; - - EHANDLE m_pParent; // for movement hierarchy - byte m_nTransmitStateOwnedCounter; - CNetworkVar( unsigned char, m_iParentAttachment ); // 0 if we're relative to the parent's absorigin and absangles. - CNetworkVar( unsigned char, m_MoveType ); // One of the MOVETYPE_ defines. - CNetworkVar( unsigned char, m_MoveCollide ); - - // Our immediate parent in the movement hierarchy. - // FIXME: clarify m_pParent vs. m_pMoveParent - CNetworkHandle( CBaseEntity, m_hMoveParent ); - // cached child list - EHANDLE m_hMoveChild; - // generated from m_pMoveParent - EHANDLE m_hMovePeer; - - friend class CCollisionProperty; - friend class CServerNetworkProperty; - CNetworkVarEmbedded( CCollisionProperty, m_Collision ); - - CNetworkHandle( CBaseEntity, m_hOwnerEntity ); // only used to point to an edict it won't collide with - CNetworkHandle( CBaseEntity, m_hEffectEntity ); // Fire/Dissolve entity. - - CNetworkVar( int, m_CollisionGroup ); // used to cull collision tests - IPhysicsObject *m_pPhysicsObject; // pointer to the entity's physics object (vphysics.dll) - - CNetworkVar( float, m_flShadowCastDistance ); - float m_flDesiredShadowCastDistance; - - // Team handling - int m_iInitialTeamNum; // Team number of this entity's team read from file - CNetworkVar( int, m_iTeamNum ); // Team number of this entity's team. - - // Sets water type + level for physics objects - unsigned char m_nWaterTouch; - unsigned char m_nSlimeTouch; - unsigned char m_nWaterType; - CNetworkVarForDerived( unsigned char, m_nWaterLevel ); - float m_flNavIgnoreUntilTime; - - CNetworkHandleForDerived( CBaseEntity, m_hGroundEntity ); - float m_flGroundChangeTime; // Time that the ground entity changed - - string_t m_ModelName; - - // Velocity of the thing we're standing on (world space) - CNetworkVarForDerived( Vector, m_vecBaseVelocity ); - - // Global velocity - Vector m_vecAbsVelocity; - - // Local angular velocity - QAngle m_vecAngVelocity; - - // Global angular velocity -// QAngle m_vecAbsAngVelocity; - - // local coordinate frame of entity - matrix3x4_t m_rgflCoordinateFrame; - - // Physics state - EHANDLE m_pBlocker; - - // was pev->gravity; - float m_flGravity; // rename to m_flGravityScale; - // was pev->friction - CNetworkVarForDerived( float, m_flFriction ); - CNetworkVar( float, m_flElasticity ); - - // was pev->ltime - float m_flLocalTime; - // local time at the beginning of this frame - float m_flVPhysicsUpdateLocalTime; - // local time the movement has ended - float m_flMoveDoneTime; - - // A counter to help quickly build a list of potentially pushed objects for physics - int m_nPushEnumCount; - - Vector m_vecAbsOrigin; - CNetworkVectorForDerived( m_vecVelocity ); - - //Adrian - CNetworkVar( unsigned char, m_iTextureFrameIndex ); - - CNetworkVar( bool, m_bSimulatedEveryTick ); - CNetworkVar( bool, m_bAnimatedEveryTick ); - CNetworkVar( bool, m_bAlternateSorting ); - - // User outputs. Fired when the "FireInputX" input is triggered. - COutputEvent m_OnUser1; - COutputEvent m_OnUser2; - COutputEvent m_OnUser3; - COutputEvent m_OnUser4; - - QAngle m_angAbsRotation; - - CNetworkVector( m_vecOrigin ); - CNetworkQAngle( m_angRotation ); - CBaseHandle m_RefEHandle; - - // was pev->view_ofs ( FIXME: Move somewhere up the hierarch, CBaseAnimating, etc. ) - CNetworkVectorForDerived( m_vecViewOffset ); - -#if !defined( NO_ENTITY_PREDICTION ) - CNetworkVar( bool, m_bIsPlayerSimulated ); - // Player who is driving my simulation - CHandle< CBasePlayer > m_hPlayerSimulationOwner; -#endif - - int m_fDataObjectTypes; - - // So it can get at the physics methods - friend class CCollisionEvent; - -// Methods shared by client and server -public: - void SetSize( const Vector &vecMin, const Vector &vecMax ); // UTIL_SetSize( this, mins, maxs ); - static int PrecacheModel( const char *name ); - static bool PrecacheSound( const char *name ); - static void PrefetchSound( const char *name ); - void Remove( ); // UTIL_Remove( this ); - -private: - - // This is a random seed used by the networking code to allow client - side prediction code - // randon number generators to spit out the same random numbers on both sides for a particular - // usercmd input. - static int m_nPredictionRandomSeed; - static CBasePlayer *m_pPredictionPlayer; - - // FIXME: Make hierarchy a member of CBaseEntity - // or a contained private class... - friend void UnlinkChild( CBaseEntity *pParent, CBaseEntity *pChild ); - friend void LinkChild( CBaseEntity *pParent, CBaseEntity *pChild ); - friend void ClearParent( CBaseEntity *pEntity ); - friend void UnlinkAllChildren( CBaseEntity *pParent ); - friend void UnlinkFromParent( CBaseEntity *pRemove ); - friend void TransferChildren( CBaseEntity *pOldParent, CBaseEntity *pNewParent ); - -public: - // Accessors for above - static int GetPredictionRandomSeed( void ); - static void SetPredictionRandomSeed( const CUserCmd *cmd ); - static CBasePlayer *GetPredictionPlayer( void ); - static void SetPredictionPlayer( CBasePlayer *player ); - - - // For debugging shared code - static bool IsServer( void ) - { - return true; - } - - static bool IsClient( void ) - { - return false; - } - - static char const *GetDLLType( void ) - { - return "server"; - } - - // Used to access m_vecAbsOrigin during restore when it's unsafe to call GetAbsOrigin. - friend class CPlayerRestoreHelper; - - static bool s_bAbsQueriesValid; - - // Call this when hierarchy is not completely set up (such as during Restore) to throw asserts - // when people call GetAbsAnything. - static inline void SetAbsQueriesValid( bool bValid ) - { - s_bAbsQueriesValid = bValid; - } - - static inline bool IsAbsQueriesValid() - { - return s_bAbsQueriesValid; - } -}; - -// Send tables exposed in this module. -EXTERN_SEND_TABLE(DT_Edict); -EXTERN_SEND_TABLE(DT_BaseEntity); - - - -// Ugly technique to override base member functions -// Normally it's illegal to cast a pointer to a member function of a derived class to a pointer to a -// member function of a base class. static_cast is a sleezy way around that problem. - -#ifdef _DEBUG - -#define SetTouch( a ) TouchSet( static_cast (a), #a ) -#define SetUse( a ) UseSet( static_cast (a), #a ) -#define SetBlocked( a ) BlockedSet( static_cast (a), #a ) - -#else - -#define SetTouch( a ) m_pfnTouch = static_cast (a) -#define SetUse( a ) m_pfnUse = static_cast (a) -#define SetBlocked( a ) m_pfnBlocked = static_cast (a) - -#endif - -// handling entity/edict transforms -inline CBaseEntity *GetContainingEntity( edict_t *pent ) -{ - if ( pent && pent->GetUnknown() ) - { - return pent->GetUnknown()->GetBaseEntity(); - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Pauses or resumes entity i/o events. When paused, no outputs will -// fire unless Debug_SetSteps is called with a nonzero step value. -// Input : bPause - true to pause, false to resume. -//----------------------------------------------------------------------------- -inline void CBaseEntity::Debug_Pause(bool bPause) -{ - CBaseEntity::m_bDebugPause = bPause; -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns true if entity i/o is paused, false if not. -//----------------------------------------------------------------------------- -inline bool CBaseEntity::Debug_IsPaused(void) -{ - return(CBaseEntity::m_bDebugPause); -} - - -//----------------------------------------------------------------------------- -// Purpose: Decrements the debug step counter. Used when the entity i/o system -// is in single step mode, this is called every time an output is fired. -// Output : Returns true on to continue firing outputs, false to stop. -//----------------------------------------------------------------------------- -inline bool CBaseEntity::Debug_Step(void) -{ - if (CBaseEntity::m_nDebugSteps > 0) - { - CBaseEntity::m_nDebugSteps--; - } - return(CBaseEntity::m_nDebugSteps > 0); -} - - -//----------------------------------------------------------------------------- -// Purpose: Sets the number of entity outputs to allow to fire before pausing -// the entity i/o system. -// Input : nSteps - Number of steps to execute. -//----------------------------------------------------------------------------- -inline void CBaseEntity::Debug_SetSteps(int nSteps) -{ - CBaseEntity::m_nDebugSteps = nSteps; -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns true if we should allow outputs to be fired, false if not. -//----------------------------------------------------------------------------- -inline bool CBaseEntity::Debug_ShouldStep(void) -{ - return(!CBaseEntity::m_bDebugPause || CBaseEntity::m_nDebugSteps > 0); -} - -//----------------------------------------------------------------------------- -// Methods relating to traversing hierarchy -//----------------------------------------------------------------------------- -inline CBaseEntity *CBaseEntity::GetMoveParent( void ) -{ - return m_hMoveParent.Get(); -} - -inline CBaseEntity *CBaseEntity::FirstMoveChild( void ) -{ - return m_hMoveChild.Get(); -} - -inline CBaseEntity *CBaseEntity::NextMovePeer( void ) -{ - return m_hMovePeer.Get(); -} - -// FIXME: Remove this! There shouldn't be a difference between moveparent + parent -inline CBaseEntity* CBaseEntity::GetParent() -{ - return m_pParent.Get(); -} - -inline int CBaseEntity::GetParentAttachment() -{ - return m_iParentAttachment; -} - -//----------------------------------------------------------------------------- -// Inline methods -//----------------------------------------------------------------------------- -inline string_t CBaseEntity::GetEntityName() -{ - return m_iName; -} - -inline void CBaseEntity::SetName( string_t newName ) -{ - m_iName = newName; -} - - -inline bool CBaseEntity::NameMatches( const char *pszNameOrWildcard ) -{ - if ( IDENT_STRINGS(m_iName, pszNameOrWildcard) ) - return true; - return NameMatchesComplex( pszNameOrWildcard ); -} - -inline bool CBaseEntity::NameMatches( string_t nameStr ) -{ - if ( IDENT_STRINGS(m_iName, nameStr) ) - return true; - return NameMatchesComplex( STRING(nameStr) ); -} - -inline bool CBaseEntity::ClassMatches( const char *pszClassOrWildcard ) -{ - if ( IDENT_STRINGS(m_iClassname, pszClassOrWildcard ) ) - return true; - return ClassMatchesComplex( pszClassOrWildcard ); -} - -inline const char* CBaseEntity::GetClassname() -{ - return STRING(m_iClassname); -} - - -inline bool CBaseEntity::ClassMatches( string_t nameStr ) -{ - if ( IDENT_STRINGS(m_iClassname, nameStr ) ) - return true; - return ClassMatchesComplex( STRING(nameStr) ); -} - -inline int CBaseEntity::GetSpawnFlags( void ) const -{ - return m_spawnflags; -} - -inline void CBaseEntity::AddSpawnFlags( int nFlags ) -{ - m_spawnflags |= nFlags; -} -inline void CBaseEntity::RemoveSpawnFlags( int nFlags ) -{ - m_spawnflags &= ~nFlags; -} - -inline void CBaseEntity::ClearSpawnFlags( void ) -{ - m_spawnflags = 0; -} - -inline bool CBaseEntity::HasSpawnFlags( int nFlags ) const -{ - return (m_spawnflags & nFlags) != 0; -} - -//----------------------------------------------------------------------------- -// checks to see if the entity is marked for deletion -//----------------------------------------------------------------------------- -inline bool CBaseEntity::IsMarkedForDeletion( void ) -{ - return (m_iEFlags & EFL_KILLME); -} - -//----------------------------------------------------------------------------- -// EFlags -//----------------------------------------------------------------------------- -inline int CBaseEntity::GetEFlags() const -{ - return m_iEFlags; -} - -inline void CBaseEntity::SetEFlags( int iEFlags ) -{ - m_iEFlags = iEFlags; - - if ( iEFlags & ( EFL_FORCE_CHECK_TRANSMIT | EFL_IN_SKYBOX ) ) - { - DispatchUpdateTransmitState(); - } -} - -inline void CBaseEntity::AddEFlags( int nEFlagMask ) -{ - m_iEFlags |= nEFlagMask; - - if ( nEFlagMask & ( EFL_FORCE_CHECK_TRANSMIT | EFL_IN_SKYBOX ) ) - { - DispatchUpdateTransmitState(); - } -} - -inline void CBaseEntity::RemoveEFlags( int nEFlagMask ) -{ - m_iEFlags &= ~nEFlagMask; - - if ( nEFlagMask & ( EFL_FORCE_CHECK_TRANSMIT | EFL_IN_SKYBOX ) ) - DispatchUpdateTransmitState(); -} - -inline bool CBaseEntity::IsEFlagSet( int nEFlagMask ) const -{ - return (m_iEFlags & nEFlagMask) != 0; -} - -inline void CBaseEntity::SetNavIgnore( float duration ) -{ - float flNavIgnoreUntilTime = ( duration == FLT_MAX ) ? FLT_MAX : gpGlobals->curtime + duration; - if ( flNavIgnoreUntilTime > m_flNavIgnoreUntilTime ) - m_flNavIgnoreUntilTime = flNavIgnoreUntilTime; -} - -inline void CBaseEntity::ClearNavIgnore() -{ - m_flNavIgnoreUntilTime = 0; -} - -inline bool CBaseEntity::IsNavIgnored() const -{ - return ( gpGlobals->curtime <= m_flNavIgnoreUntilTime ); -} - -inline bool CBaseEntity::GetCheckUntouch() const -{ - return IsEFlagSet( EFL_CHECK_UNTOUCH ); -} - -//----------------------------------------------------------------------------- -// Network state optimization -//----------------------------------------------------------------------------- -inline CBaseCombatCharacter *ToBaseCombatCharacter( CBaseEntity *pEntity ) -{ - if ( !pEntity ) - return NULL; - - return pEntity->MyCombatCharacterPointer(); -} - - -//----------------------------------------------------------------------------- -// Physics state accessor methods -//----------------------------------------------------------------------------- -inline const Vector& CBaseEntity::GetLocalOrigin( void ) const -{ - return m_vecOrigin.Get(); -} - -inline const QAngle& CBaseEntity::GetLocalAngles( void ) const -{ - return m_angRotation.Get(); -} - -inline const Vector& CBaseEntity::GetAbsOrigin( void ) const -{ - Assert( CBaseEntity::IsAbsQueriesValid() ); - - if (IsEFlagSet(EFL_DIRTY_ABSTRANSFORM)) - { - const_cast(this)->CalcAbsolutePosition(); - } - return m_vecAbsOrigin; -} - -inline const QAngle& CBaseEntity::GetAbsAngles( void ) const -{ - Assert( CBaseEntity::IsAbsQueriesValid() ); - - if (IsEFlagSet(EFL_DIRTY_ABSTRANSFORM)) - { - const_cast(this)->CalcAbsolutePosition(); - } - return m_angAbsRotation; -} - - - -//----------------------------------------------------------------------------- -// Returns the entity-to-world transform -//----------------------------------------------------------------------------- -inline matrix3x4_t &CBaseEntity::EntityToWorldTransform() -{ - Assert( CBaseEntity::IsAbsQueriesValid() ); - - if (IsEFlagSet(EFL_DIRTY_ABSTRANSFORM)) - { - CalcAbsolutePosition(); - } - return m_rgflCoordinateFrame; -} - -inline const matrix3x4_t &CBaseEntity::EntityToWorldTransform() const -{ - Assert( CBaseEntity::IsAbsQueriesValid() ); - - if (IsEFlagSet(EFL_DIRTY_ABSTRANSFORM)) - { - const_cast(this)->CalcAbsolutePosition(); - } - return m_rgflCoordinateFrame; -} - - -//----------------------------------------------------------------------------- -// Some helper methods that transform a point from entity space to world space + back -//----------------------------------------------------------------------------- -inline void CBaseEntity::EntityToWorldSpace( const Vector &in, Vector *pOut ) const -{ - if ( GetAbsAngles() == vec3_angle ) - { - VectorAdd( in, GetAbsOrigin(), *pOut ); - } - else - { - VectorTransform( in, EntityToWorldTransform(), *pOut ); - } -} - -inline void CBaseEntity::WorldToEntitySpace( const Vector &in, Vector *pOut ) const -{ - if ( GetAbsAngles() == vec3_angle ) - { - VectorSubtract( in, GetAbsOrigin(), *pOut ); - } - else - { - VectorITransform( in, EntityToWorldTransform(), *pOut ); - } -} - - -//----------------------------------------------------------------------------- -// Velocity -//----------------------------------------------------------------------------- -inline Vector CBaseEntity::GetSmoothedVelocity( void ) -{ - Vector vel; - GetVelocity( &vel, NULL ); - return vel; -} - -inline const Vector &CBaseEntity::GetLocalVelocity( ) const -{ - return m_vecVelocity.Get(); -} - -inline const Vector &CBaseEntity::GetAbsVelocity( ) const -{ - Assert( CBaseEntity::IsAbsQueriesValid() ); - - if (IsEFlagSet(EFL_DIRTY_ABSVELOCITY)) - { - const_cast(this)->CalcAbsoluteVelocity(); - } - return m_vecAbsVelocity; -} - -inline const QAngle &CBaseEntity::GetLocalAngularVelocity( ) const -{ - return m_vecAngVelocity; -} - -/* -// FIXME: While we're using (dPitch, dYaw, dRoll) as our local angular velocity -// representation, we can't actually solve this problem -inline const QAngle &CBaseEntity::GetAbsAngularVelocity( ) const -{ - if (IsEFlagSet(EFL_DIRTY_ABSANGVELOCITY)) - { - const_cast(this)->CalcAbsoluteAngularVelocity(); - } - - return m_vecAbsAngVelocity; -} -*/ - -inline const Vector& CBaseEntity::GetBaseVelocity() const -{ - return m_vecBaseVelocity.Get(); -} - -inline void CBaseEntity::SetBaseVelocity( const Vector& v ) -{ - m_vecBaseVelocity = v; -} - -inline float CBaseEntity::GetGravity( void ) const -{ - return m_flGravity; -} - -inline void CBaseEntity::SetGravity( float gravity ) -{ - m_flGravity = gravity; -} - -inline float CBaseEntity::GetFriction( void ) const -{ - return m_flFriction; -} - -inline void CBaseEntity::SetFriction( float flFriction ) -{ - m_flFriction = flFriction; -} - -inline void CBaseEntity::SetElasticity( float flElasticity ) -{ - m_flElasticity = flElasticity; -} - -inline float CBaseEntity::GetElasticity( void ) const -{ - return m_flElasticity; -} - -inline void CBaseEntity::SetShadowCastDistance( float flDistance ) -{ - m_flShadowCastDistance = flDistance; -} - -inline float CBaseEntity::GetShadowCastDistance( void ) const -{ - return m_flShadowCastDistance; -} - -inline float CBaseEntity::GetLocalTime( void ) const -{ - return m_flLocalTime; -} - -inline void CBaseEntity::IncrementLocalTime( float flTimeDelta ) -{ - m_flLocalTime += flTimeDelta; -} - -inline float CBaseEntity::GetMoveDoneTime( ) const -{ - return (m_flMoveDoneTime >= 0) ? m_flMoveDoneTime - GetLocalTime() : -1; -} - -inline CBaseEntity *CBaseEntity::Instance( const edict_t *pent ) -{ - return GetContainingEntity( const_cast(pent) ); -} - -inline CBaseEntity *CBaseEntity::Instance( edict_t *pent ) -{ - if ( !pent ) - { - pent = INDEXENT(0); - } - return GetContainingEntity( pent ); -} - -inline CBaseEntity* CBaseEntity::Instance( int iEnt ) -{ - return Instance( INDEXENT( iEnt ) ); -} - -inline int CBaseEntity::GetWaterLevel() const -{ - return m_nWaterLevel; -} - -inline void CBaseEntity::SetWaterLevel( int nLevel ) -{ - m_nWaterLevel = nLevel; -} - -inline const color32 CBaseEntity::GetRenderColor() const -{ - return m_clrRender.Get(); -} - -inline void CBaseEntity::SetRenderColor( byte r, byte g, byte b ) -{ - m_clrRender.Init( r, g, b ); -} - -inline void CBaseEntity::SetRenderColor( byte r, byte g, byte b, byte a ) -{ - m_clrRender.Init( r, g, b, a ); -} - -inline void CBaseEntity::SetRenderColorR( byte r ) -{ - m_clrRender.SetR( r ); -} - -inline void CBaseEntity::SetRenderColorG( byte g ) -{ - m_clrRender.SetG( g ); -} - -inline void CBaseEntity::SetRenderColorB( byte b ) -{ - m_clrRender.SetB( b ); -} - -inline void CBaseEntity::SetRenderColorA( byte a ) -{ - m_clrRender.SetA( a ); -} - -inline void CBaseEntity::SetMoveCollide( MoveCollide_t val ) -{ - m_MoveCollide = val; -} - -inline bool CBaseEntity::IsTransparent() const -{ - return m_nRenderMode != kRenderNormal; -} - -inline int CBaseEntity::GetTextureFrameIndex( void ) -{ - return m_iTextureFrameIndex; -} - -inline void CBaseEntity::SetTextureFrameIndex( int iIndex ) -{ - m_iTextureFrameIndex = iIndex; -} - -//----------------------------------------------------------------------------- -// An inline version the game code can use -//----------------------------------------------------------------------------- -inline CCollisionProperty *CBaseEntity::CollisionProp() -{ - return &m_Collision; -} - -inline const CCollisionProperty *CBaseEntity::CollisionProp() const -{ - return &m_Collision; -} - -inline CServerNetworkProperty *CBaseEntity::NetworkProp() -{ - return &m_Network; -} - -inline const CServerNetworkProperty *CBaseEntity::NetworkProp() const -{ - return &m_Network; -} - -inline void CBaseEntity::ClearSolidFlags( void ) -{ - CollisionProp()->ClearSolidFlags(); -} - -inline void CBaseEntity::RemoveSolidFlags( int flags ) -{ - CollisionProp()->RemoveSolidFlags( flags ); -} - -inline void CBaseEntity::AddSolidFlags( int flags ) -{ - CollisionProp()->AddSolidFlags( flags ); -} - -inline int CBaseEntity::GetSolidFlags( void ) const -{ - return CollisionProp()->GetSolidFlags(); -} - -inline bool CBaseEntity::IsSolidFlagSet( int flagMask ) const -{ - return CollisionProp()->IsSolidFlagSet( flagMask ); -} - -inline bool CBaseEntity::IsSolid() const -{ - return CollisionProp()->IsSolid( ); -} - -inline void CBaseEntity::SetSolid( SolidType_t val ) -{ - CollisionProp()->SetSolid( val ); -} - -inline void CBaseEntity::SetSolidFlags( int flags ) -{ - CollisionProp()->SetSolidFlags( flags ); -} - -inline SolidType_t CBaseEntity::GetSolid() const -{ - return CollisionProp()->GetSolid(); -} - - -//----------------------------------------------------------------------------- -// Methods related to IServerUnknown -//----------------------------------------------------------------------------- -inline ICollideable *CBaseEntity::GetCollideable() -{ - return &m_Collision; -} - -inline IServerNetworkable *CBaseEntity::GetNetworkable() -{ - return &m_Network; -} - -inline CBaseEntity *CBaseEntity::GetBaseEntity() -{ - return this; -} - - -//----------------------------------------------------------------------------- -// Model related methods -//----------------------------------------------------------------------------- -inline void CBaseEntity::SetModelName( string_t name ) -{ - m_ModelName = name; - DispatchUpdateTransmitState(); -} - -inline string_t CBaseEntity::GetModelName( void ) const -{ - return m_ModelName; -} - -inline void CBaseEntity::SetModelIndex( int index ) -{ - m_nModelIndex = index; - DispatchUpdateTransmitState(); -} - -inline int CBaseEntity::GetModelIndex( void ) const -{ - return m_nModelIndex; -} - - - -//----------------------------------------------------------------------------- -// Methods relating to bounds -//----------------------------------------------------------------------------- -inline const Vector& CBaseEntity::WorldAlignMins( ) const -{ - Assert( !CollisionProp()->IsBoundsDefinedInEntitySpace() ); - Assert( CollisionProp()->GetCollisionAngles() == vec3_angle ); - return CollisionProp()->OBBMins(); -} - -inline const Vector& CBaseEntity::WorldAlignMaxs( ) const -{ - Assert( !CollisionProp()->IsBoundsDefinedInEntitySpace() ); - Assert( CollisionProp()->GetCollisionAngles() == vec3_angle ); - return CollisionProp()->OBBMaxs(); -} - -inline const Vector& CBaseEntity::WorldAlignSize( ) const -{ - Assert( !CollisionProp()->IsBoundsDefinedInEntitySpace() ); - Assert( CollisionProp()->GetCollisionAngles() == vec3_angle ); - return CollisionProp()->OBBSize(); -} - -// Returns a radius of a sphere *centered at the world space center* -// bounding the collision representation of the entity -inline float CBaseEntity::BoundingRadius() const -{ - return CollisionProp()->BoundingRadius(); -} - -inline bool CBaseEntity::IsPointSized() const -{ - return CollisionProp()->BoundingRadius() == 0.0f; -} - -inline void CBaseEntity::SetRenderMode( RenderMode_t nRenderMode ) -{ - m_nRenderMode = nRenderMode; -} - -inline RenderMode_t CBaseEntity::GetRenderMode() const -{ - return (RenderMode_t)m_nRenderMode.Get(); -} - - -//----------------------------------------------------------------------------- -// Methods to cast away const -//----------------------------------------------------------------------------- -inline Vector CBaseEntity::EyePosition( void ) const -{ - return const_cast(this)->EyePosition(); -} - -inline const QAngle &CBaseEntity::EyeAngles( void ) const // Direction of eyes in world space -{ - return const_cast(this)->EyeAngles(); -} - -inline const QAngle &CBaseEntity::LocalEyeAngles( void ) const // Direction of eyes -{ - return const_cast(this)->LocalEyeAngles(); -} - -inline Vector CBaseEntity::EarPosition( void ) const // position of ears -{ - return const_cast(this)->EarPosition(); -} - - -//----------------------------------------------------------------------------- -// Methods relating to networking -//----------------------------------------------------------------------------- -inline void CBaseEntity::NetworkStateChanged() -{ - NetworkProp()->NetworkStateChanged(); -} - - -inline void CBaseEntity::NetworkStateChanged( void *pVar ) -{ - // Make sure it's a semi-reasonable pointer. - Assert( (char*)pVar > (char*)this ); - Assert( (char*)pVar - (char*)this < 32768 ); - - // Good, they passed an offset so we can track this variable's change - // and avoid sending the whole entity. - NetworkProp()->NetworkStateChanged( (char*)pVar - (char*)this ); -} - - -//----------------------------------------------------------------------------- -// IHandleEntity overrides. -//----------------------------------------------------------------------------- -inline const CBaseHandle& CBaseEntity::GetRefEHandle() const -{ - return m_RefEHandle; -} - -inline void CBaseEntity::IncrementTransmitStateOwnedCounter() -{ - Assert( m_nTransmitStateOwnedCounter != 255 ); - m_nTransmitStateOwnedCounter++; -} - -inline void CBaseEntity::DecrementTransmitStateOwnedCounter() -{ - Assert( m_nTransmitStateOwnedCounter != 0 ); - m_nTransmitStateOwnedCounter--; -} - - -//----------------------------------------------------------------------------- -// Bullet firing (legacy)... -//----------------------------------------------------------------------------- -inline void CBaseEntity::FireBullets( int cShots, const Vector &vecSrc, - const Vector &vecDirShooting, const Vector &vecSpread, float flDistance, - int iAmmoType, int iTracerFreq, int firingEntID, int attachmentID, - int iDamage, CBaseEntity *pAttacker, bool bFirstShotAccurate, bool bPrimaryAttack ) -{ - FireBulletsInfo_t info; - info.m_iShots = cShots; - info.m_vecSrc = vecSrc; - info.m_vecDirShooting = vecDirShooting; - info.m_vecSpread = vecSpread; - info.m_flDistance = flDistance; - info.m_iAmmoType = iAmmoType; - info.m_iTracerFreq = iTracerFreq; - info.m_iDamage = iDamage; - info.m_pAttacker = pAttacker; - info.m_nFlags = bFirstShotAccurate ? FIRE_BULLETS_FIRST_SHOT_ACCURATE : 0; - info.m_bPrimaryAttack = bPrimaryAttack; - - FireBullets( info ); -} - -// Ugly technique to override base member functions -// Normally it's illegal to cast a pointer to a member function of a derived class to a pointer to a -// member function of a base class. static_cast is a sleezy way around that problem. - -#define SetThink( a ) ThinkSet( static_cast (a), 0, NULL ) -#define SetContextThink( a, b, context ) ThinkSet( static_cast (a), (b), context ) - -#ifdef _DEBUG -#define SetMoveDone( a ) \ - do \ - { \ - m_pfnMoveDone = static_cast (a); \ - FunctionCheck( (void *)*((int *)((char *)this + ( offsetof(CBaseEntity,m_pfnMoveDone)))), "BaseMoveFunc" ); \ - } while ( 0 ) -#else -#define SetMoveDone( a ) \ - (void)(m_pfnMoveDone = static_cast (a)) -#endif - - -inline bool FClassnameIs(CBaseEntity *pEntity, const char *szClassname) -{ - return pEntity->ClassMatches(szClassname); -} - -class CPointEntity : public CBaseEntity -{ -public: - DECLARE_CLASS( CPointEntity, CBaseEntity ); - - void Spawn( void ); - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } - virtual bool KeyValue( const char *szKeyName, const char *szValue ); -private: -}; - -// Has a position + size -class CServerOnlyEntity : public CBaseEntity -{ - DECLARE_CLASS( CServerOnlyEntity, CBaseEntity ); -public: - CServerOnlyEntity() : CBaseEntity( true ) {} - - virtual int ObjectCaps( void ) { return (BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION); } -}; - -// Has only a position, no size -class CServerOnlyPointEntity : public CServerOnlyEntity -{ - DECLARE_CLASS( CServerOnlyPointEntity, CServerOnlyEntity ); - -public: - virtual bool KeyValue( const char *szKeyName, const char *szValue ); -}; - -// Has no position or size -class CLogicalEntity : public CServerOnlyEntity -{ - DECLARE_CLASS( CLogicalEntity, CServerOnlyEntity ); - -public: - virtual bool KeyValue( const char *szKeyName, const char *szValue ); -}; - - -#endif // BASEENTITY_H diff --git a/game/server/baseflex.cpp b/game/server/baseflex.cpp deleted file mode 100644 index f7ae689d3..000000000 --- a/game/server/baseflex.cpp +++ /dev/null @@ -1,2795 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "animation.h" -#include "baseflex.h" -#include "filesystem.h" -#include "studio.h" -#include "choreoevent.h" -#include "choreoscene.h" -#include "choreoactor.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "tier1/strtools.h" -#include "KeyValues.h" -#include "ai_basenpc.h" -#include "ai_navigator.h" -#include "ai_moveprobe.h" -#include "sceneentity.h" -#include "ai_baseactor.h" -#include "datacache/imdlcache.h" -#include "tier1/byteswap.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -static ConVar scene_showlook( "scene_showlook", "0", FCVAR_ARCHIVE, "When playing back, show the directions of look events." ); -static ConVar scene_showmoveto( "scene_showmoveto", "0", FCVAR_ARCHIVE, "When moving, show the end location." ); -static ConVar scene_showunlock( "scene_showunlock", "0", FCVAR_ARCHIVE, "Show when a vcd is playing but normal AI is running." ); - -// static ConVar scene_checktagposition( "scene_checktagposition", "0", FCVAR_ARCHIVE, "When playing back a choreographed scene, check the current position of the tags relative to where they were authored." ); - -// Fake layer # to force HandleProcessSceneEvent to actually allocate the layer during npc think time instead of in between. -#define REQUEST_DEFERRED_LAYER_ALLOCATION -2 - -extern bool g_bClientFlex; - -// --------------------------------------------------------------------- -// -// CBaseFlex -- physically simulated brush rectangular solid -// -// --------------------------------------------------------------------- - -void* SendProxy_FlexWeights( const SendProp *pProp, const void *pStruct, const void *pVarData, CSendProxyRecipients *pRecipients, int objectID ) -{ - // Don't any flexweights to client unless scene_clientflex.GetBool() is false - if ( !g_bClientFlex ) - return (void*)pVarData; - else - return NULL; -} - -REGISTER_SEND_PROXY_NON_MODIFIED_POINTER( SendProxy_FlexWeights ); - -// SendTable stuff. -IMPLEMENT_SERVERCLASS_ST(CBaseFlex, DT_BaseFlex) -// Note we can't totally disabled flexweights transmission since some things like blink and eye tracking are still done by the server - SendPropArray3 (SENDINFO_ARRAY3(m_flexWeight), SendPropFloat(SENDINFO_ARRAY(m_flexWeight), 12, SPROP_ROUNDDOWN, 0.0f, 1.0f ) /*, SendProxy_FlexWeights*/ ), - SendPropInt (SENDINFO(m_blinktoggle), 1, SPROP_UNSIGNED ), - SendPropVector (SENDINFO(m_viewtarget), -1, SPROP_COORD), -#ifdef HL2_DLL - SendPropFloat ( SENDINFO_VECTORELEM2(m_vecViewOffset, 0, x), 0, SPROP_NOSCALE ), - SendPropFloat ( SENDINFO_VECTORELEM2(m_vecViewOffset, 1, y), 0, SPROP_NOSCALE ), - SendPropFloat ( SENDINFO_VECTORELEM2(m_vecViewOffset, 2, z), 0, SPROP_NOSCALE ), - - SendPropVector ( SENDINFO(m_vecLean), -1, SPROP_COORD ), - SendPropVector ( SENDINFO(m_vecShift), -1, SPROP_COORD ), -#endif - -END_SEND_TABLE() - - -BEGIN_DATADESC( CBaseFlex ) - - // m_blinktoggle - DEFINE_ARRAY( m_flexWeight, FIELD_FLOAT, MAXSTUDIOFLEXCTRL ), - DEFINE_FIELD( m_viewtarget, FIELD_POSITION_VECTOR ), - // m_SceneEvents - // m_FileList - DEFINE_FIELD( m_flAllowResponsesEndTime, FIELD_TIME ), - // m_ActiveChoreoScenes - // DEFINE_FIELD( m_LocalToGlobal, CUtlRBTree < FS_LocalToGlobal_t , unsigned short > ), - // m_bUpdateLayerPriorities - DEFINE_FIELD( m_flLastFlexAnimationTime, FIELD_TIME ), - -#ifdef HL2_DLL - //DEFINE_FIELD( m_vecPrevOrigin, FIELD_POSITION_VECTOR ), - //DEFINE_FIELD( m_vecPrevVelocity, FIELD_VECTOR ), - DEFINE_FIELD( m_vecLean, FIELD_VECTOR ), - DEFINE_FIELD( m_vecShift, FIELD_VECTOR ), -#endif - -END_DATADESC() - - - -LINK_ENTITY_TO_CLASS( funCBaseFlex, CBaseFlex ); // meaningless independant class!! - -CBaseFlex::CBaseFlex( void ) : - m_LocalToGlobal( 0, 0, FlexSettingLessFunc ) -{ -#ifdef _DEBUG - // default constructor sets the viewtarget to NAN - m_viewtarget.Init(); -#endif - m_bUpdateLayerPriorities = true; - m_flLastFlexAnimationTime = 0.0; -} - -CBaseFlex::~CBaseFlex( void ) -{ - m_LocalToGlobal.RemoveAll(); - Assert( m_SceneEvents.Count() == 0 ); -} - -void CBaseFlex::SetModel( const char *szModelName ) -{ - MDLCACHE_CRITICAL_SECTION(); - - BaseClass::SetModel( szModelName ); - - for (LocalFlexController_t i = LocalFlexController_t(0); i < GetNumFlexControllers(); i++) - { - SetFlexWeight( i, 0.0f ); - } -} - - -void CBaseFlex::SetViewtarget( const Vector &viewtarget ) -{ - m_viewtarget = viewtarget; // bah -} - -void CBaseFlex::SetFlexWeight( LocalFlexController_t index, float value ) -{ - if (index >= 0 && index < GetNumFlexControllers()) - { - CStudioHdr *pstudiohdr = GetModelPtr( ); - if (! pstudiohdr) - return; - - mstudioflexcontroller_t *pflexcontroller = pstudiohdr->pFlexcontroller( index ); - - if (pflexcontroller->max != pflexcontroller->min) - { - value = (value - pflexcontroller->min) / (pflexcontroller->max - pflexcontroller->min); - value = clamp( value, 0.0, 1.0 ); - } - - m_flexWeight.Set( index, value ); - } -} - -float CBaseFlex::GetFlexWeight( LocalFlexController_t index ) -{ - if (index >= 0 && index < GetNumFlexControllers()) - { - CStudioHdr *pstudiohdr = GetModelPtr( ); - if (! pstudiohdr) - return 0; - - mstudioflexcontroller_t *pflexcontroller = pstudiohdr->pFlexcontroller( index ); - - if (pflexcontroller->max != pflexcontroller->min) - { - return m_flexWeight[index] * (pflexcontroller->max - pflexcontroller->min) + pflexcontroller->min; - } - - return m_flexWeight[index]; - } - return 0.0; -} - -LocalFlexController_t CBaseFlex::FindFlexController( const char *szName ) -{ - for (LocalFlexController_t i = LocalFlexController_t(0); i < GetNumFlexControllers(); i++) - { - if (stricmp( GetFlexControllerName( i ), szName ) == 0) - { - return i; - } - } - - // AssertMsg( 0, UTIL_VarArgs( "flexcontroller %s couldn't be mapped!!!\n", szName ) ); - return LocalFlexController_t(0); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseFlex::StartChoreoScene( CChoreoScene *scene ) -{ - if ( m_ActiveChoreoScenes.Find( scene ) != m_ActiveChoreoScenes.InvalidIndex() ) - { - return; - } - - m_ActiveChoreoScenes.AddToTail( scene ); - m_bUpdateLayerPriorities = true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseFlex::RemoveChoreoScene( CChoreoScene *scene, bool canceled ) -{ - // Assert( m_ActiveChoreoScenes.Find( scene ) != m_ActiveChoreoScenes.InvalidIndex() ); - - m_ActiveChoreoScenes.FindAndRemove( scene ); - m_bUpdateLayerPriorities = true; - - if (canceled) - { - CAI_BaseNPC *myNpc = MyNPCPointer( ); - if ( myNpc ) - { - myNpc->ClearSceneLock( ); - } - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -int CBaseFlex::GetScenePriority( CChoreoScene *scene ) -{ - int iPriority = 0; - int c = m_ActiveChoreoScenes.Count(); - // count number of channels in scenes older than current - for ( int i = 0; i < c; i++ ) - { - CChoreoScene *pScene = m_ActiveChoreoScenes[ i ]; - if ( !pScene ) - { - continue; - } - - if ( pScene == scene ) - { - break; - } - - iPriority += pScene->GetNumChannels( ); - } - return iPriority; -} - - - - -//----------------------------------------------------------------------------- -// Purpose: Remove all active SceneEvents -//----------------------------------------------------------------------------- -void CBaseFlex::ClearSceneEvents( CChoreoScene *scene, bool canceled ) -{ - if ( !scene ) - { - m_SceneEvents.RemoveAll(); - return; - } - - for ( int i = m_SceneEvents.Count() - 1; i >= 0; i-- ) - { - CSceneEventInfo *info = &m_SceneEvents[ i ]; - - Assert( info ); - Assert( info->m_pScene ); - Assert( info->m_pEvent ); - - if ( info->m_pScene != scene ) - continue; - - if ( !ClearSceneEvent( info, false, canceled )) - { - // unknown expression to clear!! - Assert( 0 ); - } - - // Free this slot - info->m_pEvent = NULL; - info->m_pScene = NULL; - info->m_bStarted = false; - - m_SceneEvents.Remove( i ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Stop specifics of expression -//----------------------------------------------------------------------------- - -bool CBaseFlex::ClearSceneEvent( CSceneEventInfo *info, bool fastKill, bool canceled ) -{ - Assert( info ); - Assert( info->m_pScene ); - Assert( info->m_pEvent ); - - // FIXME: this code looks duplicated - switch ( info->m_pEvent->GetType() ) - { - case CChoreoEvent::GESTURE: - case CChoreoEvent::SEQUENCE: - { - if (info->m_iLayer >= 0) - { - if ( fastKill ) - { - FastRemoveLayer( info->m_iLayer ); - } - else if (info->m_pEvent->GetType() == CChoreoEvent::GESTURE) - { - if (canceled) - { - // remove slower if interrupted - RemoveLayer( info->m_iLayer, 0.5 ); - } - else - { - RemoveLayer( info->m_iLayer, 0.1 ); - } - } - else - { - RemoveLayer( info->m_iLayer, 0.3 ); - } - } - } - return true; - - case CChoreoEvent::MOVETO: - { - CAI_BaseNPC *myNpc = MyNPCPointer( ); - if (!myNpc) - return true; - - // cancel moveto if it's distance based, of if the event was part of a canceled vcd - if (IsMoving() && (canceled || info->m_pEvent->GetDistanceToTarget() > 0.0)) - { - if (!info->m_bHasArrived) - { - if (info->m_pScene) - { - Scene_Printf( "%s : %8.2f: MOVETO canceled but actor %s not at goal\n", info->m_pScene->GetFilename(), info->m_pScene->GetTime(), info->m_pEvent->GetActor()->GetName() ); - } - } - myNpc->GetNavigator()->StopMoving( false ); // Stop moving - } - } - return true; - case CChoreoEvent::FACE: - case CChoreoEvent::FLEXANIMATION: - case CChoreoEvent::EXPRESSION: - case CChoreoEvent::LOOKAT: - case CChoreoEvent::GENERIC: - { - // no special rules - } - return true; - case CChoreoEvent::SPEAK: - { - // Tracker 15420: Issue stopsound if we need to cut this short... - if ( canceled ) - { - StopSound( info->m_pEvent->GetParameters() ); - -#ifdef HL2_EPISODIC - // If we were holding the semaphore because of this speech, release it - CAI_BaseActor *pBaseActor = dynamic_cast(this); - if ( pBaseActor ) - { - pBaseActor->GetExpresser()->ForceNotSpeaking(); - } -#endif - } - } - return true; - default: - break; - } - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Add string indexed scene/expression/duration to list of active SceneEvents -// Input : scenefile - -// expression - -// duration - -//----------------------------------------------------------------------------- -void CBaseFlex::AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, CBaseEntity *pTarget ) -{ - if ( !scene || !event ) - { - Msg( "CBaseFlex::AddSceneEvent: scene or event was NULL!!!\n" ); - return; - } - - CChoreoActor *actor = event->GetActor(); - if ( !actor ) - { - Msg( "CBaseFlex::AddSceneEvent: event->GetActor() was NULL!!!\n" ); - return; - } - - - CSceneEventInfo info; - - memset( (void *)&info, 0, sizeof( info ) ); - - info.m_pEvent = event; - info.m_pScene = scene; - info.m_hTarget = pTarget; - info.m_bStarted = false; - - if (StartSceneEvent( &info, scene, event, actor, pTarget )) - { - m_SceneEvents.AddToTail( info ); - } - else - { - Scene_Printf( "CBaseFlex::AddSceneEvent: event failed\n" ); - // Assert( 0 ); // expression failed to start - } -} - - -//----------------------------------------------------------------------------- -// Starting various expression types -//----------------------------------------------------------------------------- - -bool CBaseFlex::RequestStartSequenceSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget ) -{ - info->m_nSequence = LookupSequence( event->GetParameters() ); - - // make sure sequence exists - if (info->m_nSequence < 0) - { - Warning( "CSceneEntity %s :\"%s\" unable to find sequence \"%s\"\n", STRING(GetEntityName()), actor->GetName(), event->GetParameters() ); - return false; - } - - // This is a bit of a hack, but we need to defer the actual allocation until Process which will sync the layer allocation - // to the NPCs think/m_flAnimTime instead of some arbitrary tick - info->m_iLayer = REQUEST_DEFERRED_LAYER_ALLOCATION; - info->m_pActor = actor; - return true; -} - -bool CBaseFlex::RequestStartGestureSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget ) -{ - info->m_nSequence = LookupSequence( event->GetParameters() ); - - // make sure sequence exists - if (info->m_nSequence < 0) - { - Warning( "CSceneEntity %s :\"%s\" unable to find gesture \"%s\"\n", STRING(GetEntityName()), actor->GetName(), event->GetParameters() ); - return false; - } - - // This is a bit of a hack, but we need to defer the actual allocation until Process which will sync the layer allocation - // to the NPCs think/m_flAnimTime instead of some arbitrary tick - info->m_iLayer = REQUEST_DEFERRED_LAYER_ALLOCATION; - info->m_pActor = actor; - return true; -} - -bool CBaseFlex::HandleStartSequenceSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor ) -{ - Assert( info->m_iLayer == REQUEST_DEFERRED_LAYER_ALLOCATION ); - - info->m_nSequence = LookupSequence( event->GetParameters() ); - info->m_iLayer = -1; - - if (info->m_nSequence < 0) - { - Warning( "CSceneEntity %s :\"%s\" unable to find sequence \"%s\"\n", STRING(GetEntityName()), actor->GetName(), event->GetParameters() ); - return false; - } - - if (!EnterSceneSequence( scene, event )) - { - if (!event->GetPlayOverScript()) - { - // this has failed to start - Warning( "CSceneEntity %s :\"%s\" failed to start sequence \"%s\"\n", STRING(GetEntityName()), actor->GetName(), event->GetParameters() ); - return false; - } - // Start anyways, just use normal no-movement, must be in IDLE rules - } - - info->m_iPriority = actor->FindChannelIndex( event->GetChannel() ); - info->m_iLayer = AddLayeredSequence( info->m_nSequence, info->m_iPriority + GetScenePriority( scene ) ); - SetLayerNoRestore( info->m_iLayer, true ); - SetLayerWeight( info->m_iLayer, 0.0 ); - - bool looping = ((GetSequenceFlags( GetModelPtr(), info->m_nSequence ) & STUDIO_LOOPING) != 0); - if (!looping) - { - // figure out the animtime when this was frame 0 - float dt = scene->GetTime() - event->GetStartTime(); - float seq_duration = SequenceDuration( info->m_nSequence ); - float flCycle = dt / seq_duration; - flCycle = flCycle - (int)flCycle; // loop - SetLayerCycle( info->m_iLayer, flCycle, flCycle ); - - SetLayerPlaybackRate( info->m_iLayer, 0.0 ); - } - else - { - SetLayerPlaybackRate( info->m_iLayer, 1.0 ); - } - - if (IsMoving()) - { - info->m_flWeight = 0.0; - } - else - { - info->m_flWeight = 1.0; - } - - return true; -} - -bool CBaseFlex::HandleStartGestureSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor ) -{ - Assert( info->m_iLayer == REQUEST_DEFERRED_LAYER_ALLOCATION ); - - info->m_nSequence = LookupSequence( event->GetParameters() ); - info->m_iLayer = -1; - - if (info->m_nSequence < 0) - { - Warning( "CSceneEntity %s :\"%s\" unable to find gesture \"%s\"\n", STRING(GetEntityName()), actor->GetName(), event->GetParameters() ); - return false; - } - - // FIXME: this seems like way too much code - info->m_bIsGesture = false; - KeyValues *seqKeyValues = GetSequenceKeyValues( info->m_nSequence ); - if (seqKeyValues) - { - // Do we have a build point section? - KeyValues *pkvAllFaceposer = seqKeyValues->FindKey("faceposer"); - if ( pkvAllFaceposer ) - { - KeyValues *pkvType = pkvAllFaceposer->FindKey("type"); - - if (pkvType) - { - info->m_bIsGesture = (stricmp( pkvType->GetString(), "gesture" ) == 0) ? true : false; - } - } - - // FIXME: fixup tags that should be set as "linear", should be done in faceposer - char szStartLoop[CEventAbsoluteTag::MAX_EVENTTAG_LENGTH] = { "loop" }; - char szEndLoop[CEventAbsoluteTag::MAX_EVENTTAG_LENGTH] = { "end" }; - - // check in the tag indexes - KeyValues *pkvFaceposer; - for ( pkvFaceposer = pkvAllFaceposer->GetFirstSubKey(); pkvFaceposer; pkvFaceposer = pkvFaceposer->GetNextKey() ) - { - if (!stricmp( pkvFaceposer->GetName(), "startloop" )) - { - strcpy( szStartLoop, pkvFaceposer->GetString() ); - } - else if (!stricmp( pkvFaceposer->GetName(), "endloop" )) - { - strcpy( szEndLoop, pkvFaceposer->GetString() ); - } - } - - CEventAbsoluteTag *ptag; - ptag = event->FindAbsoluteTag( CChoreoEvent::ORIGINAL, szStartLoop ); - if (ptag) - { - ptag->SetLinear( true ); - } - ptag = event->FindAbsoluteTag( CChoreoEvent::PLAYBACK, szStartLoop ); - if (ptag) - { - ptag->SetLinear( true ); - } - ptag = event->FindAbsoluteTag( CChoreoEvent::ORIGINAL, szEndLoop ); - if (ptag) - { - ptag->SetLinear( true ); - } - ptag = event->FindAbsoluteTag( CChoreoEvent::PLAYBACK, szEndLoop ); - if (ptag) - { - ptag->SetLinear( true ); - } - - if ( pkvAllFaceposer ) - { - CStudioHdr *pstudiohdr = GetModelPtr(); - - mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( info->m_nSequence ); - mstudioanimdesc_t &animdesc = pstudiohdr->pAnimdesc( pstudiohdr->iRelativeAnim( info->m_nSequence, seqdesc.anim(0,0) ) ); - - // check in the tag indexes - KeyValues *pkvFaceposer; - for ( pkvFaceposer = pkvAllFaceposer->GetFirstSubKey(); pkvFaceposer; pkvFaceposer = pkvFaceposer->GetNextKey() ) - { - if (!stricmp( pkvFaceposer->GetName(), "tags" )) - { - KeyValues *pkvTags; - for ( pkvTags = pkvFaceposer->GetFirstSubKey(); pkvTags; pkvTags = pkvTags->GetNextKey() ) - { - int maxFrame = animdesc.numframes - 2; // FIXME: this is off by one! - - if ( maxFrame > 0) - { - float percentage = (float)pkvTags->GetInt() / maxFrame; - - CEventAbsoluteTag *ptag = event->FindAbsoluteTag( CChoreoEvent::ORIGINAL, pkvTags->GetName() ); - if (ptag) - { - if (fabs(ptag->GetPercentage() - percentage) > 0.05) - { - DevWarning("%s repositioned tag: %s : %.3f -> %.3f (%s:%s:%s)\n", scene->GetFilename(), pkvTags->GetName(), ptag->GetPercentage(), percentage, scene->GetFilename(), actor->GetName(), event->GetParameters() ); - // reposition tag - ptag->SetPercentage( percentage ); - } - } - } - } - } - } - - if (!event->VerifyTagOrder()) - { - DevWarning("out of order tags : %s : (%s:%s:%s)\n", scene->GetFilename(), actor->GetName(), event->GetName(), event->GetParameters() ); - } - } - - seqKeyValues->deleteThis(); - } - - // initialize posture suppression - // FIXME: move priority of base animation so that layers can be inserted before - // FIXME: query stopping, post idle layer to figure out correct weight - // GetIdleLayerWeight()? - if (!info->m_bIsGesture && IsMoving()) - { - info->m_flWeight = 0.0; - } - else - { - info->m_flWeight = 1.0; - } - - // this happens before StudioFrameAdvance() - info->m_iPriority = actor->FindChannelIndex( event->GetChannel() ); - info->m_iLayer = AddLayeredSequence( info->m_nSequence, info->m_iPriority + GetScenePriority( scene ) ); - SetLayerNoRestore( info->m_iLayer, true ); - SetLayerDuration( info->m_iLayer, event->GetDuration() ); - SetLayerWeight( info->m_iLayer, 0.0 ); - - bool looping = ((GetSequenceFlags( GetModelPtr(), info->m_nSequence ) & STUDIO_LOOPING) != 0); - if ( looping ) - { - DevMsg( 1, "vcd error, gesture %s of model %s is marked as STUDIO_LOOPING!\n", - event->GetParameters(), STRING(GetModelName()) ); - } - - SetLayerLooping( info->m_iLayer, false ); // force to not loop - - float duration = event->GetDuration( ); - - // figure out the animtime when this was frame 0 - float flEventCycle = (scene->GetTime() - event->GetStartTime()) / duration; - float flCycle = event->GetOriginalPercentageFromPlaybackPercentage( flEventCycle ); - SetLayerCycle( info->m_iLayer, flCycle, 0.0 ); - SetLayerPlaybackRate( info->m_iLayer, 0.0 ); - - return true; -} - -bool CBaseFlex::StartFacingSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget ) -{ - if ( pTarget ) - { - // Don't allow FACE commands while sitting in the vehicle - CAI_BaseNPC *myNpc = MyNPCPointer(); - if ( myNpc && myNpc->IsInAVehicle() ) - return false; - - info->m_bIsMoving = false; - return true; - } - return false; -} - - -bool CBaseFlex::StartMoveToSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget ) -{ - if (pTarget) - { - info->m_bIsMoving = false; - info->m_bHasArrived = false; - CAI_BaseNPC *myNpc = MyNPCPointer( ); - if (!myNpc) - { - return false; - } - - EnterSceneSequence( scene, event, true ); - - // If they're already moving, stop them - // - // Don't stop them during restore because that will set a stopping path very - // nearby, causing us to signal arrival prematurely in CheckSceneEventCompletion. - // BEWARE: the behavior of this bug depended on the order in which the entities were restored!! - if ( myNpc->IsMoving() && !scene->IsRestoring() ) - { - myNpc->GetNavigator()->StopMoving( false ); - } - - return true; - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseFlex::StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget ) -{ - switch ( event->GetType() ) - { - case CChoreoEvent::SEQUENCE: - return RequestStartSequenceSceneEvent( info, scene, event, actor, pTarget ); - - case CChoreoEvent::GESTURE: - return RequestStartGestureSceneEvent( info, scene, event, actor, pTarget ); - - case CChoreoEvent::FACE: - return StartFacingSceneEvent( info, scene, event, actor, pTarget ); - - // FIXME: move this to an CBaseActor - case CChoreoEvent::MOVETO: - return StartMoveToSceneEvent( info, scene, event, actor, pTarget ); - - case CChoreoEvent::LOOKAT: - info->m_hTarget = pTarget; - return true; - - case CChoreoEvent::FLEXANIMATION: - info->InitWeight( this ); - return true; - - case CChoreoEvent::SPEAK: - return true; - - case CChoreoEvent::EXPRESSION: // These are handled client-side - return true; - - default: - break; - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Remove expression -// Input : scenefile - -// expression - -//----------------------------------------------------------------------------- -void CBaseFlex::RemoveSceneEvent( CChoreoScene *scene, CChoreoEvent *event, bool fastKill ) -{ - Assert( event ); - - for ( int i = 0 ; i < m_SceneEvents.Count(); i++ ) - { - CSceneEventInfo *info = &m_SceneEvents[ i ]; - - Assert( info ); - Assert( info->m_pEvent ); - - if ( info->m_pScene != scene ) - continue; - - if ( info->m_pEvent != event) - continue; - - if (ClearSceneEvent( info, fastKill, false )) - { - // Free this slot - info->m_pEvent = NULL; - info->m_pScene = NULL; - info->m_bStarted = false; - - m_SceneEvents.Remove( i ); - return; - } - } - - // many events refuse to start due to bogus parameters -} - -//----------------------------------------------------------------------------- -// Purpose: Checks to see if the event should be considered "completed" -//----------------------------------------------------------------------------- -bool CBaseFlex::CheckSceneEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event ) -{ - for ( int i = 0 ; i < m_SceneEvents.Count(); i++ ) - { - CSceneEventInfo *info = &m_SceneEvents[ i ]; - - Assert( info ); - Assert( info->m_pEvent ); - - if ( info->m_pScene != scene ) - continue; - - if ( info->m_pEvent != event) - continue; - - return CheckSceneEventCompletion( info, currenttime, scene, event ); - } - return true; -} - - - -bool CBaseFlex::CheckSceneEventCompletion( CSceneEventInfo *info, float currenttime, CChoreoScene *scene, CChoreoEvent *event ) -{ - switch ( event->GetType() ) - { - case CChoreoEvent::MOVETO: - { - CAI_BaseNPC *npc = MyNPCPointer( ); - - if (npc) - { - // check movement, check arrival - if (npc->GetNavigator()->IsGoalActive()) - { - const Task_t *pCurTask = npc->GetTask(); - if ( pCurTask && (pCurTask->iTask == TASK_PLAY_SCENE || pCurTask->iTask == TASK_WAIT_FOR_MOVEMENT ) ) - { - float preload = event->GetEndTime() - currenttime; - if (preload < 0) - { - //Msg("%.1f: no preload\n", currenttime ); - return false; - } - float t = npc->GetTimeToNavGoal(); - - // Msg("%.1f: preload (%s:%.1f) %.1f %.1f\n", currenttime, event->GetName(), event->GetEndTime(), preload, t ); - - // FIXME: t is zero if no path can be built! - - if (t > 0.0f && t <= preload) - { - return true; - } - return false; - } - } - else if (info->m_bHasArrived) - { - return true; - } - else if (info->m_bStarted && !npc->IsCurSchedule( SCHED_SCENE_GENERIC )) - { - // FIXME: There's still a hole in the logic is the save happens immediately after the SS steals the npc but before their AI has run again - Warning( "%s : %8.2f: waiting for actor %s to complete MOVETO but actor not in SCHED_SCENE_GENERIC\n", scene->GetFilename(), scene->GetTime(), event->GetActor()->GetName() ); - // no longer in a scene :P - return true; - } - // still trying - return false; - } - } - break; - default: - break; - } - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Default implementation -//----------------------------------------------------------------------------- -void CBaseFlex::ProcessSceneEvents( void ) -{ - VPROF( "CBaseFlex::ProcessSceneEvents" ); - // slowly decay to netural expression - for ( LocalFlexController_t i = LocalFlexController_t(0); i < GetNumFlexControllers(); i++) - { - SetFlexWeight( i, GetFlexWeight( i ) * 0.95 ); - } - - bool bHasForegroundEvents = false; - // Iterate SceneEvents and look for active slots - for ( int i = 0; i < m_SceneEvents.Count(); i++ ) - { - CSceneEventInfo *info = &m_SceneEvents[ i ]; - Assert( info ); - - // FIXME: Need a safe handle to m_pEvent in case of memory deletion? - CChoreoEvent *event = info->m_pEvent; - Assert( event ); - - CChoreoScene *scene = info->m_pScene; - Assert( scene ); - - if ( scene && !scene->IsBackground() ) - { - bHasForegroundEvents = true; - } - - if (ProcessSceneEvent( info, scene, event )) - { - info->m_bStarted = true; - } - } - - if ( bHasForegroundEvents && scene_showunlock.GetBool()) - { - CAI_BaseNPC *myNpc = MyNPCPointer( ); - if ( myNpc && !(myNpc->GetState() == NPC_STATE_SCRIPT || myNpc->IsCurSchedule( SCHED_SCENE_GENERIC )) ) - { - Vector p0 = myNpc->GetHullMins(); - Vector p1 = myNpc->GetHullMaxs(); - p0.z = p1.z + 2; - p1.z = p1.z + 2; - NDebugOverlay::Box( myNpc->GetAbsOrigin(), p0, p1, 255, 0, 0, 0, 0.12 ); - } - } - - - // any needed layer priorites have now been reset - m_bUpdateLayerPriorities = false; -} - -class CFlexSceneFileManager : CAutoGameSystem -{ -public: - - CFlexSceneFileManager( char const *name ) : CAutoGameSystem( name ) - { - } - - virtual bool Init() - { - // Trakcer 16692: Preload these at startup to avoid hitch first time we try to load them during actual gameplay - FindSceneFile( NULL, "phonemes", true ); - FindSceneFile( NULL, "phonemes_weak", true ); - FindSceneFile( NULL, "phonemes_strong", true ); -#if defined( HL2_DLL ) - FindSceneFile( NULL, "random", true ); - FindSceneFile( NULL, "randomAlert", true ); -#endif - return true; - } - - // Tracker 14992: We used to load 18K of .vfes for every CBaseFlex who lipsynced, but now we only load those files once globally. - // Note, we could wipe these between levels, but they don't ever load more than the weak/normal/strong phoneme classes that I can tell - // so I'll just leave them loaded forever for now - virtual void Shutdown() - { - DeleteSceneFiles(); - } - - //----------------------------------------------------------------------------- - // Purpose: Sets up translations - // Input : *instance - - // *pSettinghdr - - // Output : void - //----------------------------------------------------------------------------- - void EnsureTranslations( CBaseFlex *instance, const flexsettinghdr_t *pSettinghdr ) - { - // The only time instance is NULL is in Init() above, where we're just loading the .vfe files off of the hard disk. - if ( instance ) - { - instance->EnsureTranslations( pSettinghdr ); - } - } - - const void *FindSceneFile( CBaseFlex *instance, const char *filename, bool allowBlockingIO ) - { - // See if it's already loaded - int i; - for ( i = 0; i < m_FileList.Size(); i++ ) - { - CFlexSceneFile *file = m_FileList[ i ]; - if ( file && !stricmp( file->filename, filename ) ) - { - // Make sure translations (local to global flex controller) are set up for this instance - EnsureTranslations( instance, ( const flexsettinghdr_t * )file->buffer ); - return file->buffer; - } - } - - if ( !allowBlockingIO ) - { - return NULL; - } - - // Load file into memory - void *buffer = NULL; - int len = filesystem->ReadFileEx( UTIL_VarArgs( "expressions/%s.vfe", filename ), "GAME", &buffer, false, true ); - - if ( !len ) - return NULL; - - // Create scene entry - CFlexSceneFile *pfile = new CFlexSceneFile; - // Remember filename - Q_strncpy( pfile->filename, filename, sizeof( pfile->filename ) ); - // Remember data pointer - pfile->buffer = buffer; - // Add to list - m_FileList.AddToTail( pfile ); - - // Swap the entire file - if ( IsX360() ) - { - CByteswap swap; - swap.ActivateByteSwapping( true ); - byte *pData = (byte*)buffer; - flexsettinghdr_t *pHdr = (flexsettinghdr_t*)pData; - swap.SwapFieldsToTargetEndian( pHdr ); - - // Flex Settings - flexsetting_t *pFlexSetting = (flexsetting_t*)((byte*)pHdr + pHdr->flexsettingindex); - for ( int i = 0; i < pHdr->numflexsettings; ++i, ++pFlexSetting ) - { - swap.SwapFieldsToTargetEndian( pFlexSetting ); - - flexweight_t *pWeight = (flexweight_t*)(((byte*)pFlexSetting) + pFlexSetting->settingindex ); - for ( int j = 0; j < pFlexSetting->numsettings; ++j, ++pWeight ) - { - swap.SwapFieldsToTargetEndian( pWeight ); - } - } - - // indexes - pData = (byte*)pHdr + pHdr->indexindex; - swap.SwapBufferToTargetEndian( (int*)pData, (int*)pData, pHdr->numindexes ); - - // keymappings - pData = (byte*)pHdr + pHdr->keymappingindex; - swap.SwapBufferToTargetEndian( (int*)pData, (int*)pData, pHdr->numkeys ); - - // keyname indices - pData = (byte*)pHdr + pHdr->keynameindex; - swap.SwapBufferToTargetEndian( (int*)pData, (int*)pData, pHdr->numkeys ); - } - - // Fill in translation table - EnsureTranslations( instance, ( const flexsettinghdr_t * )pfile->buffer ); - - // Return data - return pfile->buffer; - } - -private: - - void DeleteSceneFiles() - { - while ( m_FileList.Size() > 0 ) - { - CFlexSceneFile *file = m_FileList[ 0 ]; - m_FileList.Remove( 0 ); - filesystem->FreeOptimalReadBuffer( file->buffer ); - delete file; - } - } - - CUtlVector< CFlexSceneFile * > m_FileList; -}; - -// Singleton manager -CFlexSceneFileManager g_FlexSceneFileManager( "CFlexSceneFileManager" ); - -//----------------------------------------------------------------------------- -// Purpose: Each CBaseFlex maintains a UtlRBTree of mappings, one for each loaded flex scene file it uses. This is used to -// sort the entries in the RBTree -// Input : lhs - -// rhs - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseFlex::FlexSettingLessFunc( const FS_LocalToGlobal_t& lhs, const FS_LocalToGlobal_t& rhs ) -{ - return lhs.m_Key < rhs.m_Key; -} - -//----------------------------------------------------------------------------- -// Purpose: Since everyone shared a pSettinghdr now, we need to set up the localtoglobal mapping per entity, but -// we just do this in memory with an array of integers (could be shorts, I suppose) -// Input : *pSettinghdr - -//----------------------------------------------------------------------------- -void CBaseFlex::EnsureTranslations( const flexsettinghdr_t *pSettinghdr ) -{ - Assert( pSettinghdr ); - - FS_LocalToGlobal_t entry( pSettinghdr ); - - unsigned short idx = m_LocalToGlobal.Find( entry ); - if ( idx != m_LocalToGlobal.InvalidIndex() ) - return; - - entry.SetCount( pSettinghdr->numkeys ); - - for ( int i = 0; i < pSettinghdr->numkeys; ++i ) - { - entry.m_Mapping[ i ] = FindFlexController( pSettinghdr->pLocalName( i ) ); - } - - m_LocalToGlobal.Insert( entry ); -} - -//----------------------------------------------------------------------------- -// Purpose: Look up instance specific mapping -// Input : *pSettinghdr - -// key - -// Output : int -//----------------------------------------------------------------------------- -LocalFlexController_t CBaseFlex::FlexControllerLocalToGlobal( const flexsettinghdr_t *pSettinghdr, int key ) -{ - FS_LocalToGlobal_t entry( pSettinghdr ); - - int idx = m_LocalToGlobal.Find( entry ); - if ( idx == m_LocalToGlobal.InvalidIndex() ) - { - // This should never happen!!! - Assert( 0 ); - Warning( "Unable to find mapping for flexcontroller %i, settings %p on %i/%s\n", key, pSettinghdr, entindex(), GetClassname() ); - EnsureTranslations( pSettinghdr ); - idx = m_LocalToGlobal.Find( entry ); - if ( idx == m_LocalToGlobal.InvalidIndex() ) - { - Error( "CBaseFlex::FlexControllerLocalToGlobal failed!\n" ); - } - } - - FS_LocalToGlobal_t& result = m_LocalToGlobal[ idx ]; - // Validate lookup - Assert( result.m_nCount != 0 && key < result.m_nCount ); - LocalFlexController_t index = result.m_Mapping[ key ]; - return index; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *filename - -//----------------------------------------------------------------------------- -const void *CBaseFlex::FindSceneFile( const char *filename ) -{ - // Ask manager to get the globally cached scene instead. - return g_FlexSceneFileManager.FindSceneFile( this, filename, false ); -} - -ConVar ai_expression_optimization( "ai_expression_optimization", "0", FCVAR_NONE, "Disable npc background expressions when you can't see them." ); -ConVar ai_expression_frametime( "ai_expression_frametime", "0.05", FCVAR_NONE, "Maximum frametime to still play background expressions." ); - -//----------------------------------------------------------------------------- -// Various methods to process facial SceneEvents: -//----------------------------------------------------------------------------- -bool CBaseFlex::ProcessFlexAnimationSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ) -{ - VPROF( "CBaseFlex::ProcessFlexAnimationSceneEvent" ); - - if ( event->HasEndTime() ) - { - // don't bother with flex animation if the player can't see you - CAI_BaseNPC *myNpc = MyNPCPointer( ); - if (myNpc) - { - if (!myNpc->HasCondition( COND_IN_PVS )) - return true; - - if (ai_expression_optimization.GetBool()) - { - if (scene->IsBackground()) - { - // if framerate too slow, disable - if (gpGlobals->frametime > ai_expression_frametime.GetFloat()) - { - info->m_bHasArrived = true; - info->m_flNext = gpGlobals->curtime + RandomFloat( 0.7, 1.2 ); - } - // only check occasionally - else if (info->m_flNext <= gpGlobals->curtime) - { - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - - // if not in view, disable - info->m_bHasArrived = (pPlayer && !pPlayer->FInViewCone( this ) ); - info->m_flNext = gpGlobals->curtime + RandomFloat( 0.7, 1.2 ); - } - - if (info->m_bHasArrived) - { - // NDebugOverlay::Box( myNpc->GetAbsOrigin(), myNpc->GetHullMins(), myNpc->GetHullMaxs(), 255, 0, 0, 0, 0.22 ); - return true; - } - // NDebugOverlay::Box( myNpc->GetAbsOrigin(), myNpc->GetHullMins(), myNpc->GetHullMaxs(), 0, 255, 0, 0, 0.22 ); - } - } - } - - AddFlexAnimation( info ); - } - return true; -} - -bool CBaseFlex::ProcessFlexSettingSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ) -{ - // Flexanimations have to have an end time!!! - if ( !event->HasEndTime() ) - return true; - - VPROF( "CBaseFlex::ProcessFlexSettingSceneEvent" ); - - // Look up the actual strings - const char *scenefile = event->GetParameters(); - const char *name = event->GetParameters2(); - - // Have to find both strings - if ( scenefile && name ) - { - // Find the scene file - const flexsettinghdr_t *pExpHdr = ( const flexsettinghdr_t * )FindSceneFile( scenefile ); - if ( pExpHdr ) - { - float scenetime = scene->GetTime(); - - float scale = event->GetIntensity( scenetime ); - - // Add the named expression - AddFlexSetting( name, scale, pExpHdr, !info->m_bStarted ); - } - } - - return true; -} - -bool CBaseFlex::ProcessFacingSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ) -{ - // make sure target exists - if (info->m_hTarget == NULL) - return false; - - VPROF( "CBaseFlex::ProcessFacingSceneEvent" ); - - // make sure we're still able to play this command - if (!EnterSceneSequence( scene, event, true )) - { - return false; - } - - if (!info->m_bStarted) - { - info->m_flInitialYaw = GetLocalAngles().y; - } - - // lock in place if aiming at self - if (info->m_hTarget == this) - { - return true; - } - - CAI_BaseNPC *myNpc = MyNPCPointer( ); - if (myNpc) - { - if (info->m_bIsMoving != IsMoving()) - { - info->m_flInitialYaw = GetLocalAngles().y; - } - info->m_bIsMoving = IsMoving(); - - // Msg("%f : %f - %f\n", scene->GetTime(), event->GetStartTime(), event->GetEndTime() ); - // FIXME: why are the splines ill behaved at the end? - float intensity = event->GetIntensity( scene->GetTime() ); - if (info->m_bIsMoving) - { - myNpc->AddFacingTarget( info->m_hTarget, intensity, 0.2 ); - } - else - { - float goalYaw = myNpc->CalcIdealYaw( info->m_hTarget->EyePosition() ); - - float diff = UTIL_AngleDiff( goalYaw, info->m_flInitialYaw ); - - float idealYaw = UTIL_AngleMod( info->m_flInitialYaw + diff * intensity ); - - // Msg("yaw %.1f : %.1f (%.1f)\n", info->m_flInitialYaw, idealYaw, intensity ); - - myNpc->GetMotor()->SetIdealYawAndUpdate( idealYaw ); - } - - return true; - } - return false; -} - -static Activity DetermineExpressionMoveActivity( CChoreoEvent *event, CAI_BaseNPC *pNPC ) -{ - Activity activity = ACT_WALK; - const char *sParam2 = event->GetParameters2(); - if ( !sParam2 || !sParam2[0] ) - return activity; - - // Custom distance styles are appended to param2 with a space as a separator - const char *pszAct = Q_strstr( sParam2, " " ); - if ( pszAct ) - { - char szActName[256]; - Q_strncpy( szActName, sParam2, sizeof(szActName) ); - szActName[ (pszAct-sParam2) ] = '\0'; - pszAct = szActName; - } - else - { - pszAct = sParam2; - } - - if ( !Q_stricmp( pszAct, "Walk" ) ) - { - activity = ACT_WALK; - } - else if ( !Q_stricmp( pszAct, "Run" ) ) - { - activity = ACT_RUN; - } - else if ( !Q_stricmp( pszAct, "CrouchWalk" ) ) - { - activity = ACT_WALK_CROUCH; - } - else - { - // Try and resolve the activity name - activity = (Activity)ActivityList_IndexForName( pszAct ); - if ( activity == ACT_INVALID ) - { - // Assume it's a sequence name - pNPC->m_iszSceneCustomMoveSeq = AllocPooledString( pszAct ); - activity = ACT_SCRIPT_CUSTOM_MOVE; - } - } - - return activity; -} - -bool CBaseFlex::ProcessMoveToSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ) -{ - // make sure target exists - if (info->m_hTarget == NULL) - return false; - - // FIXME: move to CBaseActor or BaseNPC - CAI_BaseNPC *myNpc = MyNPCPointer( ); - if (!myNpc) - return false; - - VPROF( "CBaseFlex::ProcessMoveToSceneEvent" ); - - // make sure we're still able to play this command - if (!EnterSceneSequence( scene, event, true )) - { - return false; - } - - // lock in place if aiming at self - if (info->m_hTarget == this) - { - return true; - } - - // If we're in a vehicle, make us exit and *then* begin the run - if ( myNpc->IsInAVehicle() ) - { - // Make us exit and wait - myNpc->ExitVehicle(); - return false; - } - - const Task_t *pCurTask = myNpc->GetTask(); - if (!info->m_bIsMoving && (!IsMoving() || pCurTask->iTask == TASK_STOP_MOVING) ) - { - if ( pCurTask && (pCurTask->iTask == TASK_PLAY_SCENE || pCurTask->iTask == TASK_WAIT_FOR_MOVEMENT || pCurTask->iTask == TASK_STOP_MOVING ) ) - { - Activity moveActivity = DetermineExpressionMoveActivity( event, myNpc ); - // AI_NavGoal_t goal( info->m_hTarget->EyePosition(), moveActivity, AIN_HULL_TOLERANCE ); - myNpc->SetTarget( info->m_hTarget ); - - float flDistTolerance; - flDistTolerance = myNpc->GetHullWidth() / 2.0; - // flDistTolerance = AIN_HULL_TOLERANCE; - - if (event->m_bForceShortMovement) - { - flDistTolerance = 0.1f; - } - - AI_NavGoal_t goal( GOALTYPE_TARGETENT, moveActivity, flDistTolerance, AIN_UPDATE_TARGET_POS ); - - float flDist = (info->m_hTarget->EyePosition() - GetAbsOrigin()).Length2D(); - - if (flDist > MAX( MAX( flDistTolerance, 0.1 ), event->GetDistanceToTarget())) - { - // Msg("flDist %.1f\n", flDist ); - int result = false; - - if ( !myNpc->IsUnreachable( info->m_hTarget ) ) - { - result = myNpc->GetNavigator()->SetGoal( goal, AIN_CLEAR_TARGET ); - if ( !result ) - { - myNpc->RememberUnreachable( info->m_hTarget, 1.5 ); - } - } - - if (result) - { - myNpc->GetNavigator()->SetMovementActivity( moveActivity ); - myNpc->GetNavigator()->SetArrivalDistance( event->GetDistanceToTarget() ); - info->m_bIsMoving = true; - } - else - { - // need route build failure case - // Msg("actor %s unable to build route\n", STRING( myNpc->GetEntityName() ) ); - // Assert(0); - - if (developer.GetInt() > 0 && scene_showmoveto.GetBool()) - { - Vector vTestPoint; - myNpc->GetMoveProbe()->FloorPoint( info->m_hTarget->EyePosition(), MASK_NPCSOLID, 0, -64, &vTestPoint ); - NDebugOverlay::HorzArrow( GetAbsOrigin() + Vector( 0, 0, 1 ), vTestPoint + Vector( 0, 0, 1 ), 4, 255, 0, 255, 0, false, 0.12 ); - NDebugOverlay::Box( vTestPoint, myNpc->GetHullMins(), myNpc->GetHullMaxs(), 255, 0, 255, 0, 0.12 ); - } - } - } - else - { - info->m_bHasArrived = true; - } - } - } - else if (IsMoving()) - { - // float flDist = (myNpc->GetNavigator()->GetGoalPos() - GetAbsOrigin()).Length2D(); - float flDist = (info->m_hTarget->EyePosition() - GetAbsOrigin()).Length2D(); - - if (flDist <= event->GetDistanceToTarget()) - { - myNpc->GetNavigator()->StopMoving( false ); // Stop moving - info->m_bHasArrived = true; - } - } - else - { - info->m_bIsMoving = false; - } - - // show movement target - if (developer.GetInt() > 0 && scene_showmoveto.GetBool() && IsMoving()) - { - Vector vecStart, vTestPoint; - vecStart = myNpc->GetNavigator()->GetGoalPos(); - - myNpc->GetMoveProbe()->FloorPoint( vecStart, MASK_NPCSOLID, 0, -64, &vTestPoint ); - - int r, g, b; - r = b = g = 0; - if ( myNpc->GetNavigator()->CanFitAtPosition( vTestPoint, MASK_NPCSOLID ) ) - { - if ( myNpc->GetMoveProbe()->CheckStandPosition( vTestPoint, MASK_NPCSOLID ) ) - { - if (event->IsResumeCondition()) - { - g = 255; - } - else - { - r = 255; g = 255; - } - } - else - { - b = 255; g = 255; - } - } - else - { - r = 255; - } - - NDebugOverlay::HorzArrow( GetAbsOrigin() + Vector( 0, 0, 1 ), vTestPoint + Vector( 0, 0, 1 ), 4, r, g, b, 0, false, 0.12 ); - NDebugOverlay::Box( vTestPoint, myNpc->GetHullMins(), myNpc->GetHullMaxs(), r, g, b, 0, 0.12 ); - } - - // handled in task - return true; -} - -bool CBaseFlex::ProcessLookAtSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ) -{ - VPROF( "CBaseFlex::ProcessLookAtSceneEvent" ); - CAI_BaseNPC *myNpc = MyNPCPointer( ); - if (myNpc && info->m_hTarget != NULL) - { - float intensity = event->GetIntensity( scene->GetTime() ); - - // clamp in-ramp to 0.3 seconds - float flDuration = scene->GetTime() - event->GetStartTime(); - float flMaxIntensity = flDuration < 0.3f ? SimpleSpline( flDuration / 0.3f ) : 1.0f; - intensity = clamp( intensity, 0.0f, flMaxIntensity ); - - myNpc->AddLookTarget( info->m_hTarget, intensity, 0.1 ); - if (developer.GetInt() > 0 && scene_showlook.GetBool() && info->m_hTarget) - { - Vector tmp = info->m_hTarget->EyePosition() - myNpc->EyePosition(); - VectorNormalize( tmp ); - Vector p0 = myNpc->EyePosition(); - NDebugOverlay::VertArrow( p0, p0 + tmp * (4 + 16 * intensity ), 4, 255, 255, 255, 0, true, 0.12 ); - } - } - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseFlex::ProcessSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ) -{ - VPROF( "CBaseFlex::ProcessSceneEvent" ); - switch ( event->GetType() ) - { - case CChoreoEvent::FLEXANIMATION: - return ProcessFlexAnimationSceneEvent( info, scene, event ); - - case CChoreoEvent::EXPRESSION: - return ProcessFlexSettingSceneEvent( info, scene, event ); - - case CChoreoEvent::SEQUENCE: - return ProcessSequenceSceneEvent( info, scene, event ); - - case CChoreoEvent::GESTURE: - return ProcessGestureSceneEvent( info, scene, event ); - - case CChoreoEvent::FACE: - return ProcessFacingSceneEvent( info, scene, event ); - - case CChoreoEvent::MOVETO: - return ProcessMoveToSceneEvent( info, scene, event ); - - case CChoreoEvent::LOOKAT: - return ProcessLookAtSceneEvent( info, scene, event ); - - case CChoreoEvent::SPEAK: - return true; - - default: - { - Msg( "unknown type %d in ProcessSceneEvent()\n", event->GetType() ); - Assert( 0 ); - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseFlex::IsRunningSceneMoveToEvent() -{ - for ( int i = m_SceneEvents.Count() - 1; i >= 0; i-- ) - { - CSceneEventInfo *info = &m_SceneEvents[ i ]; - CChoreoEvent *event = info->m_pEvent; - if ( event && event->GetType() == CChoreoEvent::MOVETO ) - return true; - } - - return false; -} - - -flexsetting_t const *CBaseFlex::FindNamedSetting( flexsettinghdr_t const *pSettinghdr, const char *expr ) -{ - int i; - const flexsetting_t *pSetting = NULL; - - for ( i = 0; i < pSettinghdr->numflexsettings; i++ ) - { - pSetting = pSettinghdr->pSetting( i ); - if ( !pSetting ) - continue; - - const char *name = pSetting->pszName(); - - if ( !stricmp( name, expr ) ) - break; - } - - if ( i>=pSettinghdr->numflexsettings ) - { - return NULL; - } - - return pSetting; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *event - -//----------------------------------------------------------------------------- -void CBaseFlex::AddFlexAnimation( CSceneEventInfo *info ) -{ - if ( !info ) - return; - - // don't bother with flex animation if the player can't see you - CAI_BaseNPC *myNpc = MyNPCPointer( ); - if (myNpc && !myNpc->HasCondition( COND_IN_PVS )) - return; - - CChoreoEvent *event = info->m_pEvent; - if ( !event ) - return; - - CChoreoScene *scene = info->m_pScene; - if ( !scene ) - return; - - if ( !event->GetTrackLookupSet() ) - { - // Create lookup data - for ( int i = 0; i < event->GetNumFlexAnimationTracks(); i++ ) - { - CFlexAnimationTrack *track = event->GetFlexAnimationTrack( i ); - if ( !track ) - continue; - - if ( track->IsComboType() ) - { - char name[ 512 ]; - Q_strncpy( name, "right_" ,sizeof(name)); - Q_strncat( name, track->GetFlexControllerName(),sizeof(name), COPY_ALL_CHARACTERS ); - - track->SetFlexControllerIndex( FindFlexController( name ), 0, 0 ); - - if ( CAI_BaseActor::IsServerSideFlexController( name ) ) - { - Assert( !"Should stereo controllers ever be server side only?" ); - track->SetServerSide( true ); - } - - Q_strncpy( name, "left_" ,sizeof(name)); - Q_strncat( name, track->GetFlexControllerName(),sizeof(name), COPY_ALL_CHARACTERS ); - - track->SetFlexControllerIndex( FindFlexController( name ), 0, 1 ); - - if ( CAI_BaseActor::IsServerSideFlexController( name ) ) - { - Assert( !"Should stereo controllers ever be server side only?" ); - track->SetServerSide( true ); - } - } - else - { - track->SetFlexControllerIndex( FindFlexController( (char *)track->GetFlexControllerName() ), 0 ); - - // Only non-combo tracks can be server side - track->SetServerSide( CAI_BaseActor::IsServerSideFlexController( track->GetFlexControllerName() ) ); - } - } - - event->SetTrackLookupSet( true ); - } - - float scenetime = scene->GetTime(); - // decay if this is a background scene and there's other flex animations playing - float weight = event->GetIntensity( scenetime ) * info->UpdateWeight( this ); - { - VPROF( "AddFlexAnimation_SetFlexWeight" ); - - // Compute intensity for each track in animation and apply - // Iterate animation tracks - for ( int i = 0; i < event->GetNumFlexAnimationTracks(); i++ ) - { - CFlexAnimationTrack *track = event->GetFlexAnimationTrack( i ); - if ( !track ) - continue; - - // Disabled - if ( !track->IsTrackActive() ) - continue; - - // If we are doing client side flexing, skip all tracks which are not server side - if ( g_bClientFlex && !track->IsServerSide() ) - continue; - - // Map track flex controller to global name - if ( track->IsComboType() ) - { - for ( int side = 0; side < 2; side++ ) - { - LocalFlexController_t controller = track->GetRawFlexControllerIndex( side ); - - // Get spline intensity for controller - float flIntensity = track->GetIntensity( scenetime, side ); - if ( controller >= LocalFlexController_t(0) ) - { - float orig = GetFlexWeight( controller ); - SetFlexWeight( controller, orig * (1 - weight) + flIntensity * weight ); - } - } - } - else - { - LocalFlexController_t controller = track->GetRawFlexControllerIndex( 0 ); - - // Get spline intensity for controller - float flIntensity = track->GetIntensity( scenetime, 0 ); - if ( controller >= LocalFlexController_t(0) ) - { - float orig = GetFlexWeight( controller ); - SetFlexWeight( controller, orig * (1 - weight) + flIntensity * weight ); - } - } - } - } - - info->m_bStarted = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *expr - -// scale - -// *pSettinghdr - -// newexpression - -//----------------------------------------------------------------------------- -void CBaseFlex::AddFlexSetting( const char *expr, float scale, - const flexsettinghdr_t *pSettinghdr, bool newexpression ) -{ - int i; - const flexsetting_t *pSetting = NULL; - - // Find the named setting in the base - for ( i = 0; i < pSettinghdr->numflexsettings; i++ ) - { - pSetting = pSettinghdr->pSetting( i ); - if ( !pSetting ) - continue; - - const char *name = pSetting->pszName(); - - if ( !stricmp( name, expr ) ) - break; - } - - if ( i>=pSettinghdr->numflexsettings ) - { - return; - } - - flexweight_t *pWeights = NULL; - int truecount = pSetting->psetting( (byte *)pSettinghdr, 0, &pWeights ); - if ( !pWeights ) - return; - - for (i = 0; i < truecount; i++, pWeights++) - { - // Translate to local flex controller - // this is translating from the settings's local index to the models local index - LocalFlexController_t index = FlexControllerLocalToGlobal( pSettinghdr, pWeights->key ); - - // blend scaled weighting in to total - float s = clamp( scale * pWeights->influence, 0.0f, 1.0f ); - float value = GetFlexWeight( index ) * (1.0f - s ) + pWeights->weight * s; - SetFlexWeight( index, value ); - } -} - - - - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -// *parameters - -//----------------------------------------------------------------------------- -bool CBaseFlex::ProcessGestureSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ) -{ - if ( !info || !event || !scene ) - return false; - - if ( info->m_iLayer == REQUEST_DEFERRED_LAYER_ALLOCATION ) - { - HandleStartGestureSceneEvent( info, scene, event, info->m_pActor ); - } - - if (info->m_iLayer >= 0) - { - // this happens after StudioFrameAdvance() - // FIXME; this needs to be adjusted by npc offset to scene time? Known? - // FIXME: what should this do when the scene loops? - float duration = event->GetDuration( ); - float flEventCycle = (scene->GetTime() - event->GetStartTime()) / duration; - float flCycle = event->GetOriginalPercentageFromPlaybackPercentage( flEventCycle ); - - SetLayerCycle( info->m_iLayer, flCycle ); - - float flWeight = event->GetIntensity( scene->GetTime() ); - - /* - if (stricmp( event->GetParameters(), "m_g_arms_crossed" ) == 0) - { - Msg("%.2f (%.2f) : %s : %.3f (%.3f) %.2f\n", scene->GetTime(), scene->GetTime() - event->GetStartTime(), event->GetParameters(), flCycle, flEventCycle, flWeight ); - } - */ - - // fade out/in if npc is moving - if (!info->m_bIsGesture) - { - if (IsMoving()) - { - info->m_flWeight = MAX( info->m_flWeight - 0.2, 0.0 ); - } - else - { - info->m_flWeight = MIN( info->m_flWeight + 0.2, 1.0 ); - } - } - - // 3x^2-2x^3 - float spline = 3 * info->m_flWeight * info->m_flWeight - 2 * info->m_flWeight * info->m_flWeight * info->m_flWeight; - SetLayerWeight( info->m_iLayer, flWeight * spline ); - - // update layer priority - if (m_bUpdateLayerPriorities) - { - SetLayerPriority( info->m_iLayer, info->m_iPriority + GetScenePriority( scene ) ); - } - - /* - Msg( "%d : %.2f (%.2f) : %.3f %.3f : %.3f\n", - info->m_iLayer, - scene->GetTime(), - (scene->GetTime() - event->GetStartTime()) / duration, - flCycle, - flNextCycle, - rate ); - */ - } - - return true; -} - - - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -// *parameters - -//----------------------------------------------------------------------------- -bool CBaseFlex::ProcessSequenceSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ) -{ - if ( !info || !event || !scene ) - return false; - - bool bNewlyAllocated = false; - if ( info->m_iLayer == REQUEST_DEFERRED_LAYER_ALLOCATION ) - { - bool result = HandleStartSequenceSceneEvent( info, scene, event, info->m_pActor ); - if (!result) - return false; - bNewlyAllocated = true; - } - - if (info->m_iLayer >= 0) - { - float flWeight = event->GetIntensity( scene->GetTime() ); - - // force layer to zero weight in newly allocated, fixed bug with inter-think spawned sequences blending in badly - if (bNewlyAllocated) - flWeight = 0.0; - - CAI_BaseNPC *myNpc = MyNPCPointer( ); - - // fade out/in if npc is moving - - bool bFadeOut = IsMoving(); - if (myNpc && !(myNpc->IsCurSchedule( SCHED_SCENE_GENERIC ) || myNpc->GetActivity() == ACT_IDLE_ANGRY || myNpc->GetActivity() == ACT_IDLE) ) - { - bFadeOut = true; - if (info->m_flWeight == 1.0) - { - Warning( "%s playing CChoreoEvent::SEQUENCE but AI has forced them to do something different\n", STRING(GetEntityName()) ); - } - } - - if (bFadeOut) - { - info->m_flWeight = MAX( info->m_flWeight - 0.2, 0.0 ); - } - else - { - info->m_flWeight = MIN( info->m_flWeight + 0.2, 1.0 ); - } - - float spline = 3 * info->m_flWeight * info->m_flWeight - 2 * info->m_flWeight * info->m_flWeight * info->m_flWeight; - SetLayerWeight( info->m_iLayer, flWeight * spline ); - - bool looping = ((GetSequenceFlags( GetModelPtr(), info->m_nSequence ) & STUDIO_LOOPING) != 0); - if (!looping) - { - float dt = scene->GetTime() - event->GetStartTime(); - float seq_duration = SequenceDuration( info->m_nSequence ); - float flCycle = dt / seq_duration; - flCycle = clamp( flCycle, 0, 1.0 ); - SetLayerCycle( info->m_iLayer, flCycle ); - } - - if (myNpc) - { - myNpc->AddSceneLock( 0.2 ); - } - - // update layer priority - if (m_bUpdateLayerPriorities) - { - SetLayerPriority( info->m_iLayer, info->m_iPriority + GetScenePriority( scene ) ); - } - } - - // FIXME: clean up cycle index from restart - return true; - -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns true if the actor is not currently in a scene OR if the actor -// is in a scene (checked externally), but a PERMIT_RESPONSES event is active and -// the permit time period has enough time remaining to handle the response in full. -// Input : response_length - -//----------------------------------------------------------------------------- -bool CBaseFlex::PermitResponse( float response_length ) -{ - // Nothing set, disallow it - if ( m_flAllowResponsesEndTime <= 0.0f ) - { - return false; - } - - // If response ends before end of allow time, then that's okay - if ( gpGlobals->curtime + response_length <= m_flAllowResponsesEndTime ) - { - return true; - } - - // Disallow responses for now - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Set response end time (0 to clear response blocking) -// Input : endtime - -//----------------------------------------------------------------------------- -void CBaseFlex::SetPermitResponse( float endtime ) -{ - // Mark time after which we'll be occupied again (if in a scene) - // Note a value of <= 0.0f means unset (always allow actor to speak if not in a scene, - // and always disallow if in a scene) - m_flAllowResponsesEndTime = endtime; -} - -//----------------------------------------------------------------------------- -// Purpose: Play a one-shot scene -// Input : -// Output : -//----------------------------------------------------------------------------- -float CBaseFlex::PlayScene( const char *pszScene, float flDelay, AI_Response *response, IRecipientFilter *filter /* = NULL */ ) -{ - return InstancedScriptedScene( this, pszScene, NULL, flDelay, false, response, false, filter ); -} - -//----------------------------------------------------------------------------- -// Purpose: Generate a one-shot scene in memory with one track which is to play the named sound on the actor -// Input : *soundname - -// Output : float -//----------------------------------------------------------------------------- -float CBaseFlex::PlayAutoGeneratedSoundScene( const char *soundname ) -{ - return InstancedAutoGeneratedSoundScene( this, soundname ); -} - - - - -// FIXME: move to CBaseActor -bool CBaseFlex::EnterSceneSequence( CChoreoScene *scene, CChoreoEvent *event, bool bRestart ) -{ - CAI_BaseNPC *myNpc = MyNPCPointer( ); - - if (!myNpc) - return false; - - // 2 seconds past current event, or 0.2 seconds past end of scene, whichever is shorter - float flDuration = MIN( 2.0, MIN( event->GetEndTime() - scene->GetTime() + 2.0, scene->FindStopTime() - scene->GetTime() + 0.2 ) ); - - if (myNpc->IsCurSchedule( SCHED_SCENE_GENERIC )) - { - myNpc->AddSceneLock( flDuration ); - return true; - } - - // for now, don't interrupt sequences that don't understand being interrupted - if (myNpc->GetCurSchedule()) - { - CAI_ScheduleBits testBits; - myNpc->GetCurSchedule()->GetInterruptMask( &testBits ); - - testBits.Clear( COND_PROVOKED ); - - if (testBits.IsAllClear()) - { - return false; - } - } - - if (myNpc->IsInterruptable()) - { - if (myNpc->m_hCine) - { - // Assert( !(myNpc->GetFlags() & FL_FLY ) ); - myNpc->ExitScriptedSequence( ); - } - - myNpc->OnStartScene(); - myNpc->SetSchedule( SCHED_SCENE_GENERIC ); - myNpc->AddSceneLock( flDuration ); - return true; - } - - return false; -} - -bool CBaseFlex::ExitSceneSequence( void ) -{ - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: keep track of last valid flex animation time and returns if the current info should play theirs -//----------------------------------------------------------------------------- - -bool CBaseFlex::IsSuppressedFlexAnimation( CSceneEventInfo *info ) -{ - // check for suppression if the current info is a background - if (info->m_pScene && info->m_pScene->IsBackground()) - { - // allow for slight jitter - return m_flLastFlexAnimationTime > gpGlobals->curtime - GetAnimTimeInterval() * 1.5; - } - // keep track of last non-suppressable flex animation - m_flLastFlexAnimationTime = gpGlobals->curtime; - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Clear out body lean states that are invalidated with Teleport -//----------------------------------------------------------------------------- - -void CBaseFlex::Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ) -{ - BaseClass::Teleport( newPosition, newAngles, newVelocity ); -#ifdef HL2_DLL - - // clear out Body Lean - m_vecPrevOrigin = vec3_origin; - -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: keep track of accel/decal and lean the body -//----------------------------------------------------------------------------- - -void CBaseFlex::DoBodyLean( void ) -{ -#ifdef HL2_DLL - CAI_BaseNPC *myNpc = MyNPCPointer( ); - - if (myNpc) - { - Vector vecDelta; - Vector vecPos; - Vector vecOrigin = GetAbsOrigin(); - - if (m_vecPrevOrigin == vec3_origin) - { - m_vecPrevOrigin = vecOrigin; - } - - vecDelta = vecOrigin - m_vecPrevOrigin; - vecDelta.x = clamp( vecDelta.x, -50, 50 ); - vecDelta.y = clamp( vecDelta.y, -50, 50 ); - vecDelta.z = clamp( vecDelta.z, -50, 50 ); - - float dt = gpGlobals->curtime - GetLastThink(); - bool bSkip = ((GetFlags() & (FL_FLY | FL_SWIM)) != 0) || (GetMoveParent() != NULL) || (GetGroundEntity() == NULL) || (GetGroundEntity()->IsMoving()); - bSkip |= myNpc->TaskRanAutomovement() || (myNpc->GetVehicleEntity() != NULL); - - if (!bSkip) - { - if (vecDelta.LengthSqr() > m_vecPrevVelocity.LengthSqr()) - { - float decay = ExponentialDecay( 0.6, 0.1, dt ); - m_vecPrevVelocity = m_vecPrevVelocity * (decay) + vecDelta * (1.f - decay); - } - else - { - float decay = ExponentialDecay( 0.4, 0.1, dt ); - m_vecPrevVelocity = m_vecPrevVelocity * (decay) + vecDelta * (1.f - decay); - } - - vecPos = m_vecPrevOrigin + m_vecPrevVelocity; - - float decay = ExponentialDecay( 0.5, 0.1, dt ); - m_vecShift = m_vecShift * (decay) + (vecOrigin - vecPos) * (1.f - decay); // FIXME: Scale this - m_vecLean = (vecOrigin - vecPos) * 1.0; // FIXME: Scale this - } - else - { - m_vecPrevVelocity = vecDelta; - float decay = ExponentialDecay( 0.5, 0.1, dt ); - m_vecShift = m_vecLean * decay; - m_vecLean = m_vecShift * decay; - } - - m_vecPrevOrigin = vecOrigin; - - /* - DevMsg( "%.2f %.2f %.2f (%.2f %.2f %.2f)\n", - m_vecLean.Get().x, m_vecLean.Get().y, m_vecLean.Get().z, - vecDelta.x, vecDelta.y, vecDelta.z ); - */ - } -#endif -} - - - - - - -//----------------------------------------------------------------------------- -// Purpose: initialize weight for background events -//----------------------------------------------------------------------------- - -void CSceneEventInfo::InitWeight( CBaseFlex *pActor ) -{ - if (pActor->IsSuppressedFlexAnimation( this )) - { - m_flWeight = 0.0; - } - else - { - m_flWeight = 1.0; - } -} - -//----------------------------------------------------------------------------- -// Purpose: update weight for background events. Only call once per think -//----------------------------------------------------------------------------- - -float CSceneEventInfo::UpdateWeight( CBaseFlex *pActor ) -{ - // decay if this is a background scene and there's other flex animations playing - if (pActor->IsSuppressedFlexAnimation( this )) - { - m_flWeight = MAX( m_flWeight - 0.2, 0.0 ); - } - else - { - m_flWeight = MIN( m_flWeight + 0.1, 1.0 ); - } - return m_flWeight; -} - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -class CFlexCycler : public CBaseFlex -{ -private: - DECLARE_CLASS( CFlexCycler, CBaseFlex ); -public: - DECLARE_DATADESC(); - - CFlexCycler() { m_iszSentence = NULL_STRING; m_sentence = 0; } - void GenericCyclerSpawn(char *szModel, Vector vecMin, Vector vecMax); - virtual int ObjectCaps( void ) { return (BaseClass::ObjectCaps() | FCAP_IMPULSE_USE); } - int OnTakeDamage( const CTakeDamageInfo &info ); - void Spawn( void ); - void Think( void ); - - virtual void ProcessSceneEvents( void ); - - // Don't treat as a live target - virtual bool IsAlive( void ) { return FALSE; } - - float m_flextime; - LocalFlexController_t m_flexnum; - float m_flextarget[64]; - float m_blinktime; - float m_looktime; - Vector m_lookTarget; - float m_speaktime; - int m_istalking; - int m_phoneme; - - string_t m_iszSentence; - int m_sentence; - - void SetFlexTarget( LocalFlexController_t flexnum ); - LocalFlexController_t LookupFlex( const char *szTarget ); -}; - -BEGIN_DATADESC( CFlexCycler ) - - DEFINE_FIELD( m_flextime, FIELD_TIME ), - DEFINE_FIELD( m_flexnum, FIELD_INTEGER ), - DEFINE_ARRAY( m_flextarget, FIELD_FLOAT, 64 ), - DEFINE_FIELD( m_blinktime, FIELD_TIME ), - DEFINE_FIELD( m_looktime, FIELD_TIME ), - DEFINE_FIELD( m_lookTarget, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_speaktime, FIELD_TIME ), - DEFINE_FIELD( m_istalking, FIELD_INTEGER ), - DEFINE_FIELD( m_phoneme, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_iszSentence, FIELD_STRING, "Sentence" ), - DEFINE_FIELD( m_sentence, FIELD_INTEGER ), - -END_DATADESC() - - -// -// we should get rid of all the other cyclers and replace them with this. -// -class CGenericFlexCycler : public CFlexCycler -{ -public: - DECLARE_CLASS( CGenericFlexCycler, CFlexCycler ); - - void Spawn( void ) { GenericCyclerSpawn( (char *)STRING( GetModelName() ), Vector(-16, -16, 0), Vector(16, 16, 72) ); } -}; - -LINK_ENTITY_TO_CLASS( cycler_flex, CGenericFlexCycler ); - - - -ConVar flex_expression( "flex_expression","-" ); -ConVar flex_talk( "flex_talk","0" ); - -// Cycler member functions - -void CFlexCycler::GenericCyclerSpawn(char *szModel, Vector vecMin, Vector vecMax) -{ - if (!szModel || !*szModel) - { - Warning( "cycler at %.0f %.0f %0.f missing modelname\n", GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z ); - UTIL_Remove( this ); - return; - } - - PrecacheModel( szModel ); - SetModel( szModel ); - - CFlexCycler::Spawn( ); - - UTIL_SetSize(this, vecMin, vecMax); - - Vector vecEyeOffset; - GetEyePosition( GetModelPtr(), vecEyeOffset ); - SetViewOffset( vecEyeOffset ); - - InitBoneControllers(); - - if (GetNumFlexControllers() < 5) - Warning( "cycler_flex used on model %s without enough flexes.\n", szModel ); -} - -void CFlexCycler::Spawn( ) -{ - Precache(); - /* - if ( m_spawnflags & FCYCLER_NOTSOLID ) - { - SetSolid( SOLID_NOT ); - } - else - { - SetSolid( SOLID_SLIDEBOX ); - } - */ - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - - SetMoveType( MOVETYPE_NONE ); - m_takedamage = DAMAGE_YES; - m_iHealth = 80000;// no cycler should die - - m_flPlaybackRate = 1.0f; - m_flGroundSpeed = 0; - - - SetNextThink( gpGlobals->curtime + 1.0f ); - - ResetSequenceInfo( ); - - m_flCycle = random->RandomFloat( 0, 1.0 ); -} - -const char *predef_flexcontroller_names[] = { - "right_lid_raiser", - "left_lid_raiser", - "right_lid_tightener", - "left_lid_tightener", - "right_lid_droop", - "left_lid_droop", - "right_inner_raiser", - "left_inner_raiser", - "right_outer_raiser", - "left_outer_raiser", - "right_lowerer", - "left_lowerer", - "right_cheek_raiser", - "left_cheek_raiser", - "wrinkler", - "right_upper_raiser", - "left_upper_raiser", - "right_corner_puller", - "left_corner_puller", - "corner_depressor", - "chin_raiser", - "right_puckerer", - "left_puckerer", - "right_funneler", - "left_funneler", - "tightener", - "jaw_clencher", - "jaw_drop", - "right_mouth_drop", - "left_mouth_drop", - NULL }; - -float predef_flexcontroller_values[7][30] = { -/* 0 */ { 0.700,0.560,0.650,0.650,0.650,0.585,0.000,0.000,0.400,0.040,0.000,0.000,0.450,0.450,0.000,0.000,0.000,0.750,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.150,1.000,0.000,0.000,0.000 }, -/* 1 */ { 0.450,0.450,0.450,0.450,0.000,0.000,0.000,0.000,0.300,0.300,0.000,0.000,0.250,0.250,0.000,0.000,0.000,0.750,0.750,0.000,0.000,0.000,0.000,0.400,0.400,0.000,1.000,0.000,0.050,0.050 }, -/* 2 */ { 0.200,0.200,0.500,0.500,0.150,0.150,0.100,0.100,0.150,0.150,0.000,0.000,0.700,0.700,0.000,0.000,0.000,0.750,0.750,0.000,0.200,0.000,0.000,0.000,0.000,0.000,0.850,0.000,0.000,0.000 }, -/* 3 */ { 0.000,0.000,0.000,0.000,0.000,0.000,0.300,0.300,0.000,0.000,0.000,0.000,0.000,0.000,0.100,0.000,0.000,0.000,0.000,0.700,0.300,0.000,0.000,0.200,0.200,0.000,0.000,0.300,0.000,0.000 }, -/* 4 */ { 0.450,0.450,0.000,0.000,0.450,0.450,0.000,0.000,0.000,0.000,0.450,0.450,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.300,0.000,0.000,0.000,0.000 }, -/* 5 */ { 0.000,0.000,0.350,0.350,0.150,0.150,0.300,0.300,0.450,0.450,0.000,0.000,0.200,0.200,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.200,0.200,0.000,0.000,0.300,0.000,0.000,0.000,0.000 }, -/* 6 */ { 0.000,0.000,0.650,0.650,0.750,0.750,0.000,0.000,0.000,0.000,0.300,0.300,0.000,0.000,0.000,0.250,0.250,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000,0.000 } -}; - -//----------------------------------------------------------------------------- -// Purpose: Changes sequences when shot -//----------------------------------------------------------------------------- -int CFlexCycler::OnTakeDamage( const CTakeDamageInfo &info ) -{ - int nSequence = GetSequence() + 1; - if (!IsValidSequence( nSequence )) - { - nSequence = 0; - } - - ResetSequence( nSequence ); - m_flCycle = 0; - - return 0; -} - - -void CFlexCycler::SetFlexTarget( LocalFlexController_t flexnum ) -{ - m_flextarget[flexnum] = random->RandomFloat( 0.5, 1.0 ); - - const char *pszType = GetFlexControllerType( flexnum ); - - // zero out all other flexes of the same type - for (LocalFlexController_t i = LocalFlexController_t(0); i < GetNumFlexControllers(); i++) - { - if (i != flexnum) - { - const char *pszOtherType = GetFlexControllerType( i ); - if (stricmp( pszType, pszOtherType ) == 0) - { - m_flextarget[i] = 0; - } - } - } - - // HACK, for now, consider then linked is named "right_" or "left_" - if (strncmp( "right_", GetFlexControllerName( flexnum ), 6 ) == 0) - { - m_flextarget[flexnum+1] = m_flextarget[flexnum]; - } - else if (strncmp( "left_", GetFlexControllerName( flexnum ), 5 ) == 0) - { - m_flextarget[flexnum-1] = m_flextarget[flexnum]; - } -} - - -LocalFlexController_t CFlexCycler::LookupFlex( const char *szTarget ) -{ - for (LocalFlexController_t i = LocalFlexController_t(0); i < GetNumFlexControllers(); i++) - { - const char *pszFlex = GetFlexControllerName( i ); - if (stricmp( szTarget, pszFlex ) == 0) - { - return i; - } - } - return LocalFlexController_t(-1); -} - - -void CFlexCycler::Think( void ) -{ - SetNextThink( gpGlobals->curtime + 0.1f ); - - StudioFrameAdvance ( ); - - if (IsSequenceFinished() && !SequenceLoops()) - { - // ResetSequenceInfo(); - // hack to avoid reloading model every frame - m_flAnimTime = gpGlobals->curtime; - m_flPlaybackRate = 1.0; - m_bSequenceFinished = false; - m_flLastEventCheck = 0; - m_flCycle = 0; - } - - // only do this if they have more than eyelid movement - if (GetNumFlexControllers() > 2) - { - const char *pszExpression = flex_expression.GetString(); - - if (pszExpression && pszExpression[0] == '+' && pszExpression[1] != '\0') - { - int i; - int j = atoi( &pszExpression[1] ); - for ( i = 0; i < GetNumFlexControllers(); i++) - { - m_flextarget[m_flexnum] = 0; - } - - for (i = 0; i < 35 && predef_flexcontroller_names[i]; i++) - { - m_flexnum = LookupFlex( predef_flexcontroller_names[i] ); - m_flextarget[m_flexnum] = predef_flexcontroller_values[j][i]; - // Msg( "%s %.3f\n", predef_flexcontroller_names[i], predef_flexcontroller_values[j][i] ); - } - } - else if ( pszExpression && (pszExpression[0] == '1') && (pszExpression[1] == '\0') ) // 1 for maxed controller values - { - for ( LocalFlexController_t i = LocalFlexController_t(0); i < GetNumFlexControllers(); i++ ) - { - // Max everything out... - m_flextarget[i] = 1.0f; - SetFlexWeight( i, m_flextarget[i] ); - } - } - else if ( pszExpression && (pszExpression[0] == '^') && (pszExpression[1] == '\0') ) // ^ for sine wave - { - for ( LocalFlexController_t i = LocalFlexController_t(0); i < GetNumFlexControllers(); i++ ) - { - // Throw a differently offset sine wave on all of the flex controllers - float fFlexTime = i * (1.0f / (float)GetNumFlexControllers()) + gpGlobals->curtime; - m_flextarget[i] = sinf( fFlexTime ) * 0.5f + 0.5f; - SetFlexWeight( i, m_flextarget[i] ); - } - } - else if (pszExpression && pszExpression[0] != '\0' && strcmp(pszExpression, "+") != 0) - { - char szExpression[128]; - char szTemp[32]; - - Q_strncpy( szExpression, pszExpression ,sizeof(szExpression)); - char *pszExpression = szExpression; - - while (*pszExpression != '\0') - { - if (*pszExpression == '+') - *pszExpression = ' '; - - pszExpression++; - } - - pszExpression = szExpression; - - while (*pszExpression) - { - if (*pszExpression != ' ') - { - if (*pszExpression == '-') - { - for (LocalFlexController_t i = LocalFlexController_t(0); i < GetNumFlexControllers(); i++) - { - m_flextarget[i] = 0; - } - } - else if (*pszExpression == '?') - { - for (LocalFlexController_t i = LocalFlexController_t(0); i < GetNumFlexControllers(); i++) - { - Msg( "\"%s\" ", GetFlexControllerName( i ) ); - } - Msg( "\n" ); - flex_expression.SetValue( "" ); - } - else - { - if (sscanf( pszExpression, "%31s", szTemp ) == 1) - { - m_flexnum = LookupFlex( szTemp ); - - if (m_flexnum != -1 && m_flextarget[m_flexnum] != 1) - { - m_flextarget[m_flexnum] = 1.0; - // SetFlexTarget( m_flexnum ); - } - pszExpression += strlen( szTemp ) - 1; - } - } - } - pszExpression++; - } - } - else if (m_flextime < gpGlobals->curtime) - { - // m_flextime = gpGlobals->curtime + 1.0; // RandomFloat( 0.1, 0.5 ); - m_flextime = gpGlobals->curtime + random->RandomFloat( 0.3, 0.5 ) * (30.0 / GetNumFlexControllers()); - m_flexnum = (LocalFlexController_t)random->RandomInt( 0, GetNumFlexControllers() - 1 ); - - // m_flexnum = (pflex->num + 1) % r_psubmodel->numflexes; - - if (m_flextarget[m_flexnum] == 1) - { - m_flextarget[m_flexnum] = 0; - // pflex->time = cl.time + 0.1; - } - else if (stricmp( GetFlexControllerType( m_flexnum ), "phoneme" ) != 0) - { - if (strstr( GetFlexControllerName( m_flexnum ), "upper_raiser" ) == NULL) - { - Msg( "%s:%s\n", GetFlexControllerType( m_flexnum ), GetFlexControllerName( m_flexnum ) ); - SetFlexTarget( m_flexnum ); - } - } - -#if 0 - char szWhat[256]; - szWhat[0] = '\0'; - for (int i = 0; i < GetNumFlexControllers(); i++) - { - if (m_flextarget[i] == 1.0) - { - if (stricmp( GetFlexFacs( i ), "upper") != 0 && stricmp( GetFlexFacs( i ), "lower") != 0) - { - if (szWhat[0] == '\0') - Q_strncat( szWhat, "-", sizeof( szWhat ), COPY_ALL_CHARACTERS ); - else - Q_strncat( szWhat, "+", sizeof( szWhat ), COPY_ALL_CHARACTERS ); - Q_strncat( szWhat, GetFlexFacs( i ), sizeof( szWhat ), COPY_ALL_CHARACTERS ); - } - } - } - Msg( "%s\n", szWhat ); -#endif - } - - // slide it up. - for (LocalFlexController_t i = LocalFlexController_t(0); i < GetNumFlexControllers(); i++) - { - float weight = GetFlexWeight( i ); - - if (weight != m_flextarget[i]) - { - weight = weight + (m_flextarget[i] - weight) / random->RandomFloat( 2.0, 4.0 ); - } - weight = clamp( weight, 0.0f, 1.0f ); - SetFlexWeight( i, weight ); - } - -#if 1 - if (flex_talk.GetInt() == -1) - { - m_istalking = 1; - char pszSentence[256]; - Q_snprintf( pszSentence,sizeof(pszSentence), "%s%d", STRING(m_iszSentence), m_sentence++ ); - int sentenceIndex = engine->SentenceIndexFromName( pszSentence ); - if (sentenceIndex >= 0) - { - Msg( "%d : %s\n", sentenceIndex, pszSentence ); - CPASAttenuationFilter filter( this ); - CBaseEntity::EmitSentenceByIndex( filter, entindex(), CHAN_VOICE, sentenceIndex, 1, SNDLVL_TALKING, 0, PITCH_NORM ); - } - else - { - m_sentence = 0; - } - - flex_talk.SetValue( "0" ); - } - else if (!FStrEq( flex_talk.GetString(), "0") ) - { - int sentenceIndex = engine->SentenceIndexFromName( flex_talk.GetString() ); - if (sentenceIndex >= 0) - { - CPASAttenuationFilter filter( this ); - CBaseEntity::EmitSentenceByIndex( filter, entindex(), CHAN_VOICE, sentenceIndex, 1, SNDLVL_TALKING, 0, PITCH_NORM ); - } - flex_talk.SetValue( "0" ); - } -#else - if (flex_talk.GetInt()) - { - if (m_speaktime < gpGlobals->curtime) - { - if (m_phoneme == 0) - { - for (m_phoneme = 0; m_phoneme < GetNumFlexControllers(); m_phoneme++) - { - if (stricmp( GetFlexFacs( m_phoneme ), "27") == 0) - break; - } - } - m_istalking = !m_istalking; - if (m_istalking) - { - m_looktime = gpGlobals->curtime - 1.0; - m_speaktime = gpGlobals->curtime + random->RandomFloat( 0.5, 2.0 ); - } - else - { - m_speaktime = gpGlobals->curtime + random->RandomFloat( 1.0, 3.0 ); - } - } - - for (i = m_phoneme; i < GetNumFlexControllers(); i++) - { - SetFlexWeight( i, 0.0f ); - } - - if (m_istalking) - { - m_flextime = gpGlobals->curtime + random->RandomFloat( 0.0, 0.2 ); - m_flexWeight[random->RandomInt(m_phoneme, GetNumFlexControllers()-1)] = random->RandomFloat( 0.5, 1.0 ); - float mouth = random->RandomFloat( 0.0, 1.0 ); - float jaw = random->RandomFloat( 0.0, 1.0 ); - - m_flexWeight[m_phoneme - 2] = jaw * (mouth); - m_flexWeight[m_phoneme - 1] = jaw * (1.0 - mouth); - } - } - else - { - m_istalking = 0; - } -#endif - - // blink - if (m_blinktime < gpGlobals->curtime) - { - Blink(); - m_blinktime = gpGlobals->curtime + random->RandomFloat( 1.5, 4.5 ); - } - } - - - Vector forward, right, up; - GetVectors( &forward, &right, &up ); - - CBaseEntity *pPlayer = (CBaseEntity *)UTIL_GetLocalPlayer(); - if (pPlayer) - { - if (pPlayer->GetSmoothedVelocity().Length() != 0 && DotProduct( forward, pPlayer->EyePosition() - EyePosition()) > 0.5) - { - m_lookTarget = pPlayer->EyePosition(); - m_looktime = gpGlobals->curtime + random->RandomFloat(2.0,4.0); - } - else if (m_looktime < gpGlobals->curtime) - { - if ((!m_istalking) && random->RandomInt( 0, 1 ) == 0) - { - m_lookTarget = EyePosition() + forward * 128 + right * random->RandomFloat(-64,64) + up * random->RandomFloat(-32,32); - m_looktime = gpGlobals->curtime + random->RandomFloat(0.3,1.0); - - if (m_blinktime - 0.5 < gpGlobals->curtime) - { - Blink(); - } - } - else - { - m_lookTarget = pPlayer->EyePosition(); - m_looktime = gpGlobals->curtime + random->RandomFloat(1.0,4.0); - } - } - -#if 0 - float dt = acos( DotProduct( (m_lookTarget - EyePosition()).Normalize(), (m_viewtarget - EyePosition()).Normalize() ) ); - - if (dt > M_PI / 4) - { - dt = (M_PI / 4) * dt; - m_viewtarget = ((1 - dt) * m_viewtarget + dt * m_lookTarget); - } -#endif - - SetViewtarget( m_lookTarget ); - } - - // Handle any facial animation from scene playback - // FIXME: do we still actually need flex cyclers? - // AddSceneSceneEvents(); -} - - -void CFlexCycler::ProcessSceneEvents( void ) -{ - // Don't do anything since we handle facial stuff in Think() -} - - -BEGIN_BYTESWAP_DATADESC( flexsettinghdr_t ) - DEFINE_FIELD( id, FIELD_INTEGER ), - DEFINE_FIELD( version, FIELD_INTEGER ), - DEFINE_ARRAY( name, FIELD_CHARACTER, 64 ), - DEFINE_FIELD( length, FIELD_INTEGER ), - DEFINE_FIELD( numflexsettings, FIELD_INTEGER ), - DEFINE_FIELD( flexsettingindex, FIELD_INTEGER ), - DEFINE_FIELD( nameindex, FIELD_INTEGER ), - DEFINE_FIELD( numindexes, FIELD_INTEGER ), - DEFINE_FIELD( indexindex, FIELD_INTEGER ), - DEFINE_FIELD( numkeys, FIELD_INTEGER ), - DEFINE_FIELD( keynameindex, FIELD_INTEGER ), - DEFINE_FIELD( keymappingindex, FIELD_INTEGER ), -END_BYTESWAP_DATADESC() - -BEGIN_BYTESWAP_DATADESC( flexsetting_t ) - DEFINE_FIELD( nameindex, FIELD_INTEGER ), - DEFINE_FIELD( obsolete1, FIELD_INTEGER ), - DEFINE_FIELD( numsettings, FIELD_INTEGER ), - DEFINE_FIELD( index, FIELD_INTEGER ), - DEFINE_FIELD( obsolete2, FIELD_INTEGER ), - DEFINE_FIELD( settingindex, FIELD_INTEGER ), -END_BYTESWAP_DATADESC() - -BEGIN_BYTESWAP_DATADESC( flexweight_t ) - DEFINE_FIELD( key, FIELD_INTEGER ), - DEFINE_FIELD( weight, FIELD_FLOAT ), - DEFINE_FIELD( influence, FIELD_FLOAT ), -END_BYTESWAP_DATADESC() - diff --git a/game/server/baseflex.h b/game/server/baseflex.h deleted file mode 100644 index 43c6f4b7b..000000000 --- a/game/server/baseflex.h +++ /dev/null @@ -1,300 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef BASEFLEX_H -#define BASEFLEX_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "BaseAnimatingOverlay.h" -#include "utlvector.h" -#include "utlrbtree.h" -#include "sceneentity_shared.h" - -struct flexsettinghdr_t; -struct flexsetting_t; -class AI_Response; - -//----------------------------------------------------------------------------- -// Purpose: A .vfe referenced by a scene during .vcd playback -//----------------------------------------------------------------------------- -class CFlexSceneFile -{ -public: - enum - { - MAX_FLEX_FILENAME = 128, - }; - - char filename[ MAX_FLEX_FILENAME ]; - void *buffer; -}; - -//----------------------------------------------------------------------------- -// Purpose: Animated characters who have vertex flex capability (e.g., facial expressions) -//----------------------------------------------------------------------------- -class CBaseFlex : public CBaseAnimatingOverlay -{ - DECLARE_CLASS( CBaseFlex, CBaseAnimatingOverlay ); -public: - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - DECLARE_PREDICTABLE(); - - // Construction - CBaseFlex( void ); - ~CBaseFlex( void ); - - virtual void SetModel( const char *szModelName ); - - void Blink( ); - - virtual void SetViewtarget( const Vector &viewtarget ); - const Vector &GetViewtarget( void ) const; - - void SetFlexWeight( char *szName, float value ); - void SetFlexWeight( LocalFlexController_t index, float value ); - float GetFlexWeight( char *szName ); - float GetFlexWeight( LocalFlexController_t index ); - - // Look up flex controller index by global name - LocalFlexController_t FindFlexController( const char *szName ); - void EnsureTranslations( const flexsettinghdr_t *pSettinghdr ); - - // Keep track of what scenes are being played - void StartChoreoScene( CChoreoScene *scene ); - void RemoveChoreoScene( CChoreoScene *scene, bool canceled = false ); - - // Start the specifics of an scene event - virtual bool StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget ); - - // Manipulation of events for the object - // Should be called by think function to process all scene events - // The default implementation resets m_flexWeight array and calls - // AddSceneEvents - virtual void ProcessSceneEvents( void ); - - // Assumes m_flexWeight array has been set up, this adds the actual currently playing - // expressions to the flex weights and adds other scene events as needed - virtual bool ProcessSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ); - - // Remove all playing events - void ClearSceneEvents( CChoreoScene *scene, bool canceled ); - - // Stop specifics of event - virtual bool ClearSceneEvent( CSceneEventInfo *info, bool fastKill, bool canceled ); - - // Add the event to the queue for this actor - void AddSceneEvent( CChoreoScene *scene, CChoreoEvent *event, CBaseEntity *pTarget = NULL ); - - // Remove the event from the queue for this actor - void RemoveSceneEvent( CChoreoScene *scene, CChoreoEvent *event, bool fastKill ); - - // Checks to see if the event should be considered "completed" - bool CheckSceneEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event ); - - // Checks to see if a event should be considered "completed" - virtual bool CheckSceneEventCompletion( CSceneEventInfo *info, float currenttime, CChoreoScene *scene, CChoreoEvent *event ); - - // Finds the layer priority of the current scene - int GetScenePriority( CChoreoScene *scene ); - - // Returns true if the actor is not currently in a scene OR if the actor - // is in a scene, but a PERMIT_RESPONSES event is active and the permit time - // period has enough time remaining to handle the response in full. - bool PermitResponse( float response_length ); - - // Set response end time (0 to clear response blocking) - void SetPermitResponse( float endtime ); - - void SentenceStop( void ) { EmitSound( "AI_BaseNPC.SentenceStop" ); } - - virtual float PlayScene( const char *pszScene, float flDelay = 0.0f, AI_Response *response = NULL, IRecipientFilter *filter = NULL ); - virtual float PlayAutoGeneratedSoundScene( const char *soundname ); - -protected: - // For handling .vfe files - // Search list, or add if not in list - const void *FindSceneFile( const char *filename ); - - // Find setting by name - const flexsetting_t *FindNamedSetting( const flexsettinghdr_t *pSettinghdr, const char *expr ); - - // Called at the lowest level to actually apply an expression - void AddFlexSetting( const char *expr, float scale, const flexsettinghdr_t *pSettinghdr, bool newexpression ); - - // Called at the lowest level to actually apply a flex animation - void AddFlexAnimation( CSceneEventInfo *info ); - - bool HasSceneEvents() const; - bool IsRunningSceneMoveToEvent(); - - LocalFlexController_t FlexControllerLocalToGlobal( const flexsettinghdr_t *pSettinghdr, int key ); - -private: - // Starting various expression types - - bool RequestStartSequenceSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget ); - bool RequestStartGestureSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget ); - - bool HandleStartSequenceSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor ); - bool HandleStartGestureSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor ); - bool StartFacingSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget ); - bool StartMoveToSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget ); - - // Processing various expression types - bool ProcessFlexAnimationSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ); - bool ProcessFlexSettingSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ); - bool ProcessSequenceSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ); - bool ProcessGestureSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ); - bool ProcessFacingSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ); - bool ProcessMoveToSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ); - bool ProcessLookAtSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event ); - - // Set playing the scene sequence -public: - bool EnterSceneSequence( CChoreoScene *scene, CChoreoEvent *event, bool bRestart = false ); -private: - bool ExitSceneSequence( void ); - -private: - CNetworkArray( float, m_flexWeight, MAXSTUDIOFLEXCTRL ); // indexed by model local flexcontroller - - // Vector from actor to eye target - CNetworkVector( m_viewtarget ); - - // Blink state - CNetworkVar( int, m_blinktoggle ); - - // Array of active SceneEvents, in order oldest to newest - CUtlVector < CSceneEventInfo > m_SceneEvents; - - // Mapping for each loaded scene file used by this actor - struct FS_LocalToGlobal_t - { - explicit FS_LocalToGlobal_t() : - m_Key( 0 ), - m_nCount( 0 ), - m_Mapping( 0 ) - { - } - - explicit FS_LocalToGlobal_t( const flexsettinghdr_t *key ) : - m_Key( key ), - m_nCount( 0 ), - m_Mapping( 0 ) - { - } - - void SetCount( int count ) - { - Assert( !m_Mapping ); - Assert( count > 0 ); - m_nCount = count; - m_Mapping = new LocalFlexController_t[ m_nCount ]; - Q_memset( m_Mapping, 0, m_nCount * sizeof( int ) ); - } - - FS_LocalToGlobal_t( const FS_LocalToGlobal_t& src ) - { - m_Key = src.m_Key; - delete m_Mapping; - m_Mapping = new LocalFlexController_t[ src.m_nCount ]; - Q_memcpy( m_Mapping, src.m_Mapping, src.m_nCount * sizeof( int ) ); - - m_nCount = src.m_nCount; - } - - ~FS_LocalToGlobal_t() - { - delete m_Mapping; - m_nCount = 0; - m_Mapping = 0; - } - - const flexsettinghdr_t *m_Key; - int m_nCount; - LocalFlexController_t *m_Mapping; - }; - - static bool FlexSettingLessFunc( const FS_LocalToGlobal_t& lhs, const FS_LocalToGlobal_t& rhs ); - - CUtlRBTree< FS_LocalToGlobal_t, unsigned short > m_LocalToGlobal; - - // The NPC is in a scene, but another .vcd (such as a short wave to say in response to the player doing something ) - // can be layered on top of this actor (assuming duration matches, etc. - float m_flAllowResponsesEndTime; - - // List of actively playing scenes - CUtlVector < CChoreoScene * > m_ActiveChoreoScenes; - bool m_bUpdateLayerPriorities; - -public: - bool IsSuppressedFlexAnimation( CSceneEventInfo *info ); - -private: - // last time a foreground flex animation was played - float m_flLastFlexAnimationTime; - - -public: - void DoBodyLean( void ); - - virtual void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ); - - -#ifdef HL2_DLL - Vector m_vecPrevOrigin; - Vector m_vecPrevVelocity; - CNetworkVector( m_vecLean ); - CNetworkVector( m_vecShift ); -#endif -}; - - -//----------------------------------------------------------------------------- -// For toggling blinking -//----------------------------------------------------------------------------- -inline void CBaseFlex::Blink() -{ - m_blinktoggle = !m_blinktoggle; -} - -//----------------------------------------------------------------------------- -// Do we have active expressions? -//----------------------------------------------------------------------------- -inline bool CBaseFlex::HasSceneEvents() const -{ - return m_SceneEvents.Count() != 0; -} - - -//----------------------------------------------------------------------------- -// Other inlines -//----------------------------------------------------------------------------- -inline const Vector &CBaseFlex::GetViewtarget( ) const -{ - return m_viewtarget.Get(); // bah -} - -inline void CBaseFlex::SetFlexWeight( char *szName, float value ) -{ - SetFlexWeight( FindFlexController( szName ), value ); -} - -inline float CBaseFlex::GetFlexWeight( char *szName ) -{ - return GetFlexWeight( FindFlexController( szName ) ); -} - - -EXTERN_SEND_TABLE(DT_BaseFlex); - - -#endif // BASEFLEX_H diff --git a/game/server/basegrenade_concussion.cpp b/game/server/basegrenade_concussion.cpp deleted file mode 100644 index 915c8d699..000000000 --- a/game/server/basegrenade_concussion.cpp +++ /dev/null @@ -1,131 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "baseentity.h" -#include "basegrenade_shared.h" -#include "soundent.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CBaseGrenadeConcussion : public CBaseGrenade -{ - DECLARE_DATADESC(); - -public: - DECLARE_CLASS( CBaseGrenadeConcussion, CBaseGrenade ); - - void Spawn( void ); - void Precache( void ); - void FallThink(void); - void ExplodeConcussion( CBaseEntity *pOther ); - -protected: - static int m_nTrailSprite; -}; - -int CBaseGrenadeConcussion::m_nTrailSprite = 0; - -LINK_ENTITY_TO_CLASS( npc_concussiongrenade, CBaseGrenadeConcussion ); - -BEGIN_DATADESC( CBaseGrenadeConcussion ) - - DEFINE_THINKFUNC( FallThink ), - DEFINE_ENTITYFUNC( ExplodeConcussion ), - -END_DATADESC() - - -void CBaseGrenadeConcussion::FallThink(void) -{ - if (!IsInWorld()) - { - Remove( ); - return; - } - CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin() + GetAbsVelocity() * 0.5, (int)GetAbsVelocity().Length(), 0.2 ); - - SetNextThink( gpGlobals->curtime + random->RandomFloat(0.05, 0.1) ); - - if (GetWaterLevel() != 0) - { - SetAbsVelocity( GetAbsVelocity() * 0.5 ); - } - - Vector pos = GetAbsOrigin() + Vector(random->RandomFloat(-4, 4), random->RandomFloat(-4, 4), random->RandomFloat(-4, 4)); - - CPVSFilter filter( GetAbsOrigin() ); - - te->Sprite( filter, 0.0, - &pos, - m_nTrailSprite, - random->RandomFloat(0.5, 0.8), - 200 ); -} - - -// -// Contact grenade, explode when it touches something -// -void CBaseGrenadeConcussion::ExplodeConcussion( CBaseEntity *pOther ) -{ - trace_t tr; - Vector vecSpot;// trace starts here! - - Vector velDir = GetAbsVelocity(); - VectorNormalize( velDir ); - vecSpot = GetAbsOrigin() - velDir * 32; - UTIL_TraceLine( vecSpot, vecSpot + velDir * 64, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - - Explode( &tr, DMG_BLAST ); -} - - -void CBaseGrenadeConcussion::Spawn( void ) -{ - // point sized, solid, bouncing - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); - SetSolid( SOLID_BBOX ); - SetCollisionGroup( COLLISION_GROUP_PROJECTILE ); - SetModel( "models/weapons/w_grenade.mdl" ); // BUG: wrong model - - UTIL_SetSize(this, vec3_origin, vec3_origin); - - // contact grenades arc lower - SetGravity( UTIL_ScaleForGravity( 400 ) ); // use a lower gravity for grenades to make them easier to see - QAngle angles; - VectorAngles(GetAbsVelocity(), angles ); - SetLocalAngles( angles ); - - m_nRenderFX = kRenderFxGlowShell; - SetRenderColor( 200, 200, 20, 255 ); - - // make NPCs afaid of it while in the air - SetThink( &CBaseGrenadeConcussion::FallThink ); - SetNextThink( gpGlobals->curtime ); - - // Tumble in air - QAngle vecAngVel( random->RandomFloat ( -100, -500 ), 0, 0 ); - SetLocalAngularVelocity( vecAngVel ); - - // Explode on contact - SetTouch( &CBaseGrenadeConcussion::ExplodeConcussion ); - - m_flDamage = 80; - - // Allow player to blow this puppy up in the air - m_takedamage = DAMAGE_YES; -} - - -void CBaseGrenadeConcussion::Precache( void ) -{ - BaseClass::Precache( ); - - PrecacheModel("models/weapons/w_grenade.mdl"); - m_nTrailSprite = PrecacheModel("sprites/twinkle01.vmt"); -} diff --git a/game/server/basegrenade_contact.cpp b/game/server/basegrenade_contact.cpp deleted file mode 100644 index bd00f89d6..000000000 --- a/game/server/basegrenade_contact.cpp +++ /dev/null @@ -1,71 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "basegrenade_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern ConVar sk_plr_dmg_grenade; - -// ========================================================================================== - -class CBaseGrenadeContact : public CBaseGrenade -{ - DECLARE_CLASS( CBaseGrenadeContact, CBaseGrenade ); -public: - - void Spawn( void ); - void Precache( void ); -}; -LINK_ENTITY_TO_CLASS( npc_contactgrenade, CBaseGrenadeContact ); - - -void CBaseGrenadeContact::Spawn( void ) -{ - // point sized, solid, bouncing - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); - SetSolid( SOLID_BBOX ); - SetCollisionGroup( COLLISION_GROUP_PROJECTILE ); - SetModel( "models/weapons/w_grenade.mdl" ); // BUG: wrong model - - UTIL_SetSize(this, vec3_origin, vec3_origin); - - // contact grenades arc lower - SetGravity( UTIL_ScaleForGravity( 400 ) ); // use a lower gravity for grenades to make them easier to see - - QAngle angles; - VectorAngles(GetAbsVelocity(), angles); - SetLocalAngles( angles ); - - // make NPCs afaid of it while in the air - SetThink( &CBaseGrenadeContact::DangerSoundThink ); - SetNextThink( gpGlobals->curtime ); - - // Tumble in air - QAngle vecAngVelocity( random->RandomFloat ( -100, -500 ), 0, 0 ); - SetLocalAngularVelocity( vecAngVelocity ); - - // Explode on contact - SetTouch( &CBaseGrenadeContact::ExplodeTouch ); - - m_flDamage = sk_plr_dmg_grenade.GetFloat(); - - // Allow player to blow this puppy up in the air - m_takedamage = DAMAGE_YES; - - m_iszBounceSound = NULL_STRING; -} - - -void CBaseGrenadeContact::Precache( void ) -{ - BaseClass::Precache( ); - - PrecacheModel("models/weapons/w_grenade.mdl"); -} diff --git a/game/server/basegrenade_timed.cpp b/game/server/basegrenade_timed.cpp deleted file mode 100644 index c153b0d5d..000000000 --- a/game/server/basegrenade_timed.cpp +++ /dev/null @@ -1,73 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "basegrenade_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CBaseGrenadeTimed : public CBaseGrenade -{ -public: - DECLARE_CLASS( CBaseGrenadeTimed, CBaseGrenade ); - - void Spawn( void ); - void Precache( void ); -}; -LINK_ENTITY_TO_CLASS( npc_handgrenade, CBaseGrenadeTimed ); - - -void CBaseGrenadeTimed::Spawn( void ) -{ - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); - SetSolid( SOLID_BBOX ); - SetCollisionGroup( COLLISION_GROUP_PROJECTILE ); - SetModel( "models/Weapons/w_grenade.mdl" ); - - UTIL_SetSize(this, Vector( -4, -4, -4), Vector(4, 4, 4)); - - QAngle angles; - Vector vel = GetAbsVelocity(); - - VectorAngles( vel, angles ); - SetLocalAngles( angles ); - - SetTouch( &CBaseGrenadeTimed::BounceTouch ); // Bounce if touched - - // Take one second off of the desired detonation time and set the think to PreDetonate. PreDetonate - // will insert a DANGER sound into the world sound list and delay detonation for one second so that - // the grenade explodes after the exact amount of time specified in the call to ShootTimed(). - - SetThink( &CBaseGrenadeTimed::TumbleThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - // if the delay is < 0.1 seconds, don't fly anywhere - if ((m_flDetonateTime - gpGlobals->curtime) < 0.1) - { - SetNextThink( gpGlobals->curtime ); - SetAbsVelocity( vec3_origin ); - } - - // Tumble through the air - // pGrenade->m_vecAngVelocity.x = -400; - SetGravity(1.0); // Don't change or throw calculations will be off! - SetFriction(0.8); - - m_flDamage = 100; // ???? - - m_takedamage = DAMAGE_NO; -} - - - -void CBaseGrenadeTimed::Precache( void ) -{ - BaseClass::Precache( ); - - PrecacheModel("models/weapons/w_grenade.mdl"); -} diff --git a/game/server/basemultiplayerplayer.cpp b/game/server/basemultiplayerplayer.cpp deleted file mode 100644 index a22042e9b..000000000 --- a/game/server/basemultiplayerplayer.cpp +++ /dev/null @@ -1,332 +0,0 @@ -//========= Copyright 1996-2001, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#include "cbase.h" -#include "mp_shareddefs.h" -#include "basemultiplayerplayer.h" -#include "steam/steam_api.h" - -CBaseMultiplayerPlayer::CBaseMultiplayerPlayer() -{ - m_iCurrentConcept = MP_CONCEPT_NONE; - m_flLastForcedChangeTeamTime = -1; - m_iBalanceScore = 0; - m_flConnectionTime = gpGlobals->curtime; - - // per life achievement counters - m_pAchievementKV = new KeyValues( "achievement_counts" ); - - m_flAreaCaptureScoreAccumulator = 0.0f; -} - -CBaseMultiplayerPlayer::~CBaseMultiplayerPlayer() -{ - m_pAchievementKV->deleteThis(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CAI_Expresser *CBaseMultiplayerPlayer::CreateExpresser( void ) -{ - m_pExpresser = new CMultiplayer_Expresser(this); - if ( !m_pExpresser) - return NULL; - - m_pExpresser->Connect(this); - return m_pExpresser; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseMultiplayerPlayer::PostConstructor( const char *szClassname ) -{ - BaseClass::PostConstructor( szClassname ); - CreateExpresser(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseMultiplayerPlayer::ModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet ) -{ - BaseClass::ModifyOrAppendCriteria( criteriaSet ); - - ModifyOrAppendPlayerCriteria( criteriaSet ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseMultiplayerPlayer::SpeakIfAllowed( AIConcept_t concept, const char *modifiers, char *pszOutResponseChosen, size_t bufsize, IRecipientFilter *filter ) -{ - if ( !IsAlive() ) - return false; - - //if ( IsAllowedToSpeak( concept, bRespondingToPlayer ) ) - return Speak( concept, modifiers, pszOutResponseChosen, bufsize, filter ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -IResponseSystem *CBaseMultiplayerPlayer::GetResponseSystem() -{ - return BaseClass::GetResponseSystem(); - // NOTE: This is where you would hook your custom responses. -// return <*>GameRules()->m_ResponseRules[iIndex].m_ResponseSystems[m_iCurrentConcept]; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -AI_Response *CBaseMultiplayerPlayer::SpeakConcept( int iConcept ) -{ - m_iCurrentConcept = iConcept; - return SpeakFindResponse( g_pszMPConcepts[iConcept] ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseMultiplayerPlayer::SpeakConceptIfAllowed( int iConcept, const char *modifiers, char *pszOutResponseChosen, size_t bufsize, IRecipientFilter *filter ) -{ - // Save the current concept. - m_iCurrentConcept = iConcept; - return SpeakIfAllowed( g_pszMPConcepts[iConcept], modifiers, pszOutResponseChosen, bufsize, filter ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseMultiplayerPlayer::CanHearAndReadChatFrom( CBasePlayer *pPlayer ) -{ - // can always hear the console unless we're ignoring all chat - if ( !pPlayer ) - return m_iIgnoreGlobalChat != CHAT_IGNORE_ALL; - - // check if we're ignoring all chat - if ( m_iIgnoreGlobalChat == CHAT_IGNORE_ALL ) - return false; - - // check if we're ignoring all but teammates - if ( m_iIgnoreGlobalChat == CHAT_IGNORE_TEAM && g_pGameRules->PlayerRelationship( this, pPlayer ) != GR_TEAMMATE ) - return false; - - // can't hear dead players if we're alive - if ( pPlayer->m_lifeState != LIFE_ALIVE && m_lifeState == LIFE_ALIVE ) - return false; - - return true; -} - -bool CBaseMultiplayerPlayer::ClientCommand( const CCommand &args ) -{ - const char *pcmd = args[0]; - - if ( FStrEq( pcmd, "ignoremsg" ) ) - { - m_iIgnoreGlobalChat = (m_iIgnoreGlobalChat + 1) % 3; - switch( m_iIgnoreGlobalChat ) - { - case CHAT_IGNORE_NONE: - ClientPrint( this, HUD_PRINTTALK, "#Accept_All_Messages" ); - break; - case CHAT_IGNORE_ALL: - ClientPrint( this, HUD_PRINTTALK, "#Ignore_Broadcast_Messages" ); - break; - case CHAT_IGNORE_TEAM: - ClientPrint( this, HUD_PRINTTALK, "#Ignore_Broadcast_Team_Messages" ); - break; - default: - break; - } - return true; - } - - return BaseClass::ClientCommand( args ); -} - -bool CBaseMultiplayerPlayer::ShouldShowVoiceSubtitleToEnemy( void ) -{ - return false; -} - -//----------------------------------------------------------------------------- -// calculate a score for this player. higher is more likely to be switched -//----------------------------------------------------------------------------- -int CBaseMultiplayerPlayer::CalculateTeamBalanceScore( void ) -{ - // base score is 0 - ( seconds on server ) - float flTimeConnected = gpGlobals->curtime - m_flConnectionTime; - int iScore = 0 - (int)flTimeConnected; - - // if we were switched recently, score us way down - float flLastSwitchedTime = GetLastForcedChangeTeamTime(); - if ( flLastSwitchedTime > 0 && ( gpGlobals->curtime - flLastSwitchedTime ) < 300 ) - { - iScore -= 10000; - } - return iScore; -} - -void CBaseMultiplayerPlayer::Spawn( void ) -{ - ResetPerLifeCounters(); - - BaseClass::Spawn(); -} - -void CBaseMultiplayerPlayer::AwardAchievement( int iAchievement ) -{ - Assert( iAchievement >= 0 && iAchievement < 0xFFFF ); // must fit in short - - CSingleUserRecipientFilter filter( this ); - - UserMessageBegin( filter, "AchievementEvent" ); - WRITE_SHORT( iAchievement ); - MessageEnd(); -} - -#ifdef _DEBUG - - #include "utlbuffer.h" - - void DumpAchievementCounters( const CCommand &args ) - { - int iPlayerIndex = 1; - - if ( args.ArgC() >= 2 ) - { - iPlayerIndex = atoi( args[1] ); - } - - CBaseMultiplayerPlayer *pPlayer = ToBaseMultiplayerPlayer( UTIL_PlayerByIndex( iPlayerIndex ) ); - if ( pPlayer && pPlayer->GetPerLifeCounterKeys() ) - { - CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); - pPlayer->GetPerLifeCounterKeys()->RecursiveSaveToFile( buf, 0 ); - - char szBuf[1024]; - - // probably not the best way to print out a CUtlBuffer - int pos = 0; - while ( buf.PeekStringLength() ) - { - szBuf[pos] = buf.GetChar(); - pos++; - } - szBuf[pos] = '\0'; - - Msg( "%s\n", szBuf ); - } - } - ConCommand dump_achievement_counters( "dump_achievement_counters", DumpAchievementCounters, "Spew the per-life achievement counters for multiplayer players", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY ); - -#endif // _DEBUG - -int CBaseMultiplayerPlayer::GetPerLifeCounterKV( const char *name ) -{ - return m_pAchievementKV->GetInt( name, 0 ); -} - -void CBaseMultiplayerPlayer::SetPerLifeCounterKV( const char *name, int value ) -{ - m_pAchievementKV->SetInt( name, value ); -} - -void CBaseMultiplayerPlayer::ResetPerLifeCounters( void ) -{ - m_pAchievementKV->Clear(); -} - - -ConVar tf_escort_score_rate( "tf_escort_score_rate", "1", FCVAR_CHEAT, "Score for escorting the train, in points per second" ); - -#define ESCORT_SCORE_CONTEXT "AreaScoreContext" -#define ESCORT_SCORE_INTERVAL 0.1 - -//----------------------------------------------------------------------------- -// Purpose: think to accumulate and award points for escorting the train -//----------------------------------------------------------------------------- -void CBaseMultiplayerPlayer::EscortScoringThink( void ) -{ - m_flAreaCaptureScoreAccumulator += ESCORT_SCORE_INTERVAL; - - if ( m_flCapPointScoreRate > 0 ) - { - float flTimeForOnePoint = 1.0f / m_flCapPointScoreRate; - - int iPoints = 0; - - while ( m_flAreaCaptureScoreAccumulator >= flTimeForOnePoint ) - { - m_flAreaCaptureScoreAccumulator -= flTimeForOnePoint; - iPoints++; - } - - if ( iPoints > 0 ) - { - IGameEvent *event = gameeventmanager->CreateEvent( "player_escort_score" ); - if ( event ) - { - event->SetInt( "player", entindex() ); - event->SetInt( "points", iPoints ); - gameeventmanager->FireEvent( event, true /* only to server */ ); - } - } - } - - SetContextThink( &CBaseMultiplayerPlayer::EscortScoringThink, gpGlobals->curtime + ESCORT_SCORE_INTERVAL, ESCORT_SCORE_CONTEXT ); -} - -//----------------------------------------------------------------------------- -// Purpose: We're escorting the train, start giving points -//----------------------------------------------------------------------------- -void CBaseMultiplayerPlayer::StartScoringEscortPoints( float flRate ) -{ - Assert( flRate > 0.0f ); - m_flCapPointScoreRate = flRate; - SetContextThink( &CBaseMultiplayerPlayer::EscortScoringThink, gpGlobals->curtime + ESCORT_SCORE_INTERVAL, ESCORT_SCORE_CONTEXT ); -} - -//----------------------------------------------------------------------------- -// Purpose: Stopped escorting the train -//----------------------------------------------------------------------------- -void CBaseMultiplayerPlayer::StopScoringEscortPoints( void ) -{ - SetContextThink( NULL, 0, ESCORT_SCORE_CONTEXT ); -} - -#if !defined(NO_STEAM) -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseMultiplayerPlayer::GetSteamID( CSteamID *pID ) -{ - const CSteamID *pClientID = engine->GetClientSteamID( edict() ); - if ( pClientID ) - { - *pID = *pClientID; - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -uint64 CBaseMultiplayerPlayer::GetSteamIDAsUInt64( void ) -{ - CSteamID steamIDForPlayer; - if ( GetSteamID( &steamIDForPlayer ) ) - return steamIDForPlayer.ConvertToUint64(); - return 0; -} -#endif // NO_STEAM diff --git a/game/server/basemultiplayerplayer.h b/game/server/basemultiplayerplayer.h deleted file mode 100644 index d716a0c8a..000000000 --- a/game/server/basemultiplayerplayer.h +++ /dev/null @@ -1,124 +0,0 @@ -//========= Copyright 1996-2005, Valve LLC, All rights reserved. ============ -// -//============================================================================= -#ifndef BASEMULTIPLAYERPLAYER_H -#define BASEMULTIPLAYERPLAYER_H -#pragma once - -#include "player.h" -#include "ai_speech.h" - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CBaseMultiplayerPlayer : public CAI_ExpresserHost -{ - - DECLARE_CLASS( CBaseMultiplayerPlayer, CAI_ExpresserHost ); - -public: - - CBaseMultiplayerPlayer(); - ~CBaseMultiplayerPlayer(); - - virtual void Spawn( void ); - - virtual void PostConstructor( const char *szClassname ); - virtual void ModifyOrAppendCriteria( AI_CriteriaSet& criteriaSet ); - - virtual bool SpeakIfAllowed( AIConcept_t concept, const char *modifiers = NULL, char *pszOutResponseChosen = NULL, size_t bufsize = 0, IRecipientFilter *filter = NULL ); - virtual IResponseSystem *GetResponseSystem(); - AI_Response *SpeakConcept( int iConcept ); - virtual bool SpeakConceptIfAllowed( int iConcept, const char *modifiers = NULL, char *pszOutResponseChosen = NULL, size_t bufsize = 0, IRecipientFilter *filter = NULL ); - - virtual bool CanHearAndReadChatFrom( CBasePlayer *pPlayer ); - virtual bool CanSpeak( void ) { return true; } - - virtual void Precache( void ) - { - PrecacheParticleSystem( "achieved" ); - - BaseClass::Precache(); - } - - virtual bool ClientCommand( const CCommand &args ); - - virtual bool CanSpeakVoiceCommand( void ) { return true; } - virtual bool ShouldShowVoiceSubtitleToEnemy( void ); - virtual void NoteSpokeVoiceCommand( const char *pszScenePlayed ) {} - - virtual void OnAchievementEarned( int iAchievement ) {} - - enum - { - CHAT_IGNORE_NONE = 0, - CHAT_IGNORE_ALL, - CHAT_IGNORE_TEAM, - }; - - int m_iIgnoreGlobalChat; - - //--------------------------------- - // Speech support - virtual CAI_Expresser *GetExpresser() { return m_pExpresser; } - virtual CMultiplayer_Expresser *GetMultiplayerExpresser() { return m_pExpresser; } - - void SetLastForcedChangeTeamTimeToNow( void ) { m_flLastForcedChangeTeamTime = gpGlobals->curtime; } - float GetLastForcedChangeTeamTime( void ) { return m_flLastForcedChangeTeamTime; } - - void SetTeamBalanceScore( int iScore ) { m_iBalanceScore = iScore; } - int GetTeamBalanceScore( void ) { return m_iBalanceScore; } - - virtual int CalculateTeamBalanceScore( void ); - - void AwardAchievement( int iAchievement ); - int GetPerLifeCounterKV( const char *name ); - void SetPerLifeCounterKV( const char *name, int value ); - void ResetPerLifeCounters( void ); - - KeyValues *GetPerLifeCounterKeys( void ) { return m_pAchievementKV; } - - void EscortScoringThink( void ); - void StartScoringEscortPoints( float flRate ); - void StopScoringEscortPoints( void ); - float m_flAreaCaptureScoreAccumulator; - float m_flCapPointScoreRate; - -#if !defined(NO_STEAM) - //---------------------------- - // Steam handling - bool GetSteamID( CSteamID *pID ); - uint64 GetSteamIDAsUInt64( void ); -#endif - -protected: - virtual CAI_Expresser *CreateExpresser( void ); - - int m_iCurrentConcept; -private: - //--------------------------------- - CMultiplayer_Expresser *m_pExpresser; - - float m_flConnectionTime; - float m_flLastForcedChangeTeamTime; - - int m_iBalanceScore; // a score used to determine which players are switched to balance the teams - - KeyValues *m_pAchievementKV; -}; - -//----------------------------------------------------------------------------- -// Inline methods -//----------------------------------------------------------------------------- -inline CBaseMultiplayerPlayer *ToBaseMultiplayerPlayer( CBaseEntity *pEntity ) -{ - if ( !pEntity || !pEntity->IsPlayer() ) - return NULL; -#if _DEBUG - return dynamic_cast( pEntity ); -#else - return static_cast( pEntity ); -#endif -} - -#endif // BASEMULTIPLAYERPLAYER_H diff --git a/game/server/baseprojectile.cpp b/game/server/baseprojectile.cpp deleted file mode 100644 index 9566e4cdf..000000000 --- a/game/server/baseprojectile.cpp +++ /dev/null @@ -1,136 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#include "baseprojectile.h" - -BEGIN_DATADESC( CBaseProjectile ) - DEFINE_FIELD( m_flDamage, FIELD_FLOAT ), - DEFINE_FIELD( m_iDamageType, FIELD_INTEGER ), - DEFINE_FIELD( m_flDamageScale, FIELD_FLOAT ), - - DEFINE_FUNCTION( ProjectileTouch ), - DEFINE_THINKFUNC( FlyThink ), -END_DATADESC() - -LINK_ENTITY_TO_CLASS( proj_base, CBaseProjectile ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseProjectile::Spawn( void ) -{ - Precache(); - - SetModel( STRING( GetModelName() ) ); - - SetSolid( SOLID_BBOX ); - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_CUSTOM ); - AddFlag( FL_OBJECT ); - - UTIL_SetSize( this, -Vector( 1.0f, 1.0f, 1.0f ), Vector( 1.0f, 1.0f, 1.0f ) ); - - // Setup attributes. - SetGravity( 0.001f ); - m_takedamage = DAMAGE_NO; - - // Setup the touch and think functions. - SetTouch( &CBaseProjectile::ProjectileTouch ); - SetThink( &CBaseProjectile::FlyThink ); - SetNextThink( gpGlobals->curtime ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseProjectile::Precache( void ) -{ - BaseClass::Precache(); - - PrecacheModel( STRING( GetModelName() ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseProjectile *CBaseProjectile::Create( baseprojectilecreate_t &pCreate ) -{ - CBaseProjectile *pProjectile = static_cast( CBaseEntity::CreateNoSpawn( "proj_base", pCreate.vecOrigin, vec3_angle, pCreate.pOwner ) ); - if ( !pProjectile ) - return NULL; - - pProjectile->SetModelName( pCreate.iszModel ); - pProjectile->SetDamage( pCreate.flDamage ); - pProjectile->SetDamageType( pCreate.iDamageType ); - pProjectile->SetDamageScale( pCreate.flDamageScale ); - pProjectile->SetAbsVelocity( pCreate.vecVelocity ); - - // Setup the initial angles. - QAngle angles; - VectorAngles( -pCreate.vecVelocity, angles ); - pProjectile->SetAbsAngles( angles ); - - // Spawn & Activate - DispatchSpawn( pProjectile ); - pProjectile->Activate(); - - return pProjectile; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -unsigned int CBaseProjectile::PhysicsSolidMaskForEntity( void ) const -{ - return BaseClass::PhysicsSolidMaskForEntity() | CONTENTS_HITBOX; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseProjectile::ProjectileTouch( CBaseEntity *pOther ) -{ - // Verify a correct "other." - Assert( pOther ); - if ( !pOther->IsSolid() || pOther->IsSolidFlagSet( FSOLID_VOLUME_CONTENTS ) ) - return; - - // Handle hitting skybox (disappear). - const trace_t *pTrace = &CBaseEntity::GetTouchTrace(); - trace_t *pNewTrace = const_cast( pTrace ); - - if( pTrace->surface.flags & SURF_SKY ) - { - UTIL_Remove( this ); - return; - } - - CTakeDamageInfo info; - info.SetAttacker( GetOwnerEntity() ); - info.SetInflictor( this ); - info.SetDamage( GetDamage() ); - info.SetDamageType( GetDamageType() ); - CalculateMeleeDamageForce( &info, GetAbsVelocity(), GetAbsOrigin(), GetDamageScale() ); - - Vector dir; - AngleVectors( GetAbsAngles(), &dir ); - - pOther->DispatchTraceAttack( info, dir, pNewTrace ); - ApplyMultiDamage(); - - UTIL_Remove( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: Orient the projectile along its velocity -//----------------------------------------------------------------------------- -void CBaseProjectile::FlyThink( void ) -{ - QAngle angles; - VectorAngles( -(GetAbsVelocity()), angles ); - SetAbsAngles( angles ); - SetNextThink( gpGlobals->curtime + 0.1f ); -} diff --git a/game/server/baseprojectile.h b/game/server/baseprojectile.h deleted file mode 100644 index 04ec92c7e..000000000 --- a/game/server/baseprojectile.h +++ /dev/null @@ -1,61 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef BASEPROJECTILE_H -#define BASEPROJECTILE_H -#ifdef _WIN32 -#pragma once -#endif - -// Creation. -struct baseprojectilecreate_t -{ - Vector vecOrigin; - Vector vecVelocity; - CBaseEntity *pOwner; - string_t iszModel; - float flDamage; - int iDamageType; - float flDamageScale; -}; - -//============================================================================= -// -// Generic projectile -// -class CBaseProjectile : public CBaseAnimating -{ - DECLARE_CLASS( CBaseProjectile, CBaseAnimating ); -public: - DECLARE_DATADESC(); - - void Spawn( void ); - void Precache( void ); - - static CBaseProjectile *Create( baseprojectilecreate_t &pCreate ); - - void SetDamage( float flDamage ) { m_flDamage = flDamage; } - void SetDamageScale( float &flScale ) { m_flDamageScale = flScale; } - void SetDamageType( int iType ) { m_iDamageType = iType; } - -private: - // Damage - virtual float GetDamage() { return m_flDamage; } - virtual float GetDamageScale( void ) { return m_flDamageScale; } - virtual int GetDamageType( void ) { return m_iDamageType; } - - unsigned int PhysicsSolidMaskForEntity( void ) const; - - virtual void ProjectileTouch( CBaseEntity *pOther ); - void FlyThink( void ); - -protected: - float m_flDamage; - int m_iDamageType; - float m_flDamageScale; -}; - -#endif // BASEPROJECTILE_H diff --git a/game/server/basetempentity.cpp b/game/server/basetempentity.cpp deleted file mode 100644 index 45c049764..000000000 --- a/game/server/basetempentity.cpp +++ /dev/null @@ -1,126 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "mathlib/mathlib.h" -#include "basetempentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -IMPLEMENT_SERVERCLASS_ST_NOBASE(CBaseTempEntity, DT_BaseTempEntity) -END_SEND_TABLE() - - - - -// Global list of temp entity event classes -CBaseTempEntity *CBaseTempEntity::s_pTempEntities = NULL; - -//----------------------------------------------------------------------------- -// Purpose: Returns head of list -// Output : CBaseTempEntity * -- head of list -//----------------------------------------------------------------------------- -CBaseTempEntity *CBaseTempEntity::GetList( void ) -{ - return s_pTempEntities; -} - -//----------------------------------------------------------------------------- -// Purpose: Creates temp entity, sets name, adds to global list -// Input : *name - -//----------------------------------------------------------------------------- -CBaseTempEntity::CBaseTempEntity( const char *name ) -{ - m_pszName = name; - Assert( m_pszName ); - - // Add to list - m_pNext = s_pTempEntities; - s_pTempEntities = this; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseTempEntity::~CBaseTempEntity( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: Get the name of this temp entity -// Output : const char * -//----------------------------------------------------------------------------- -const char *CBaseTempEntity::GetName( void ) -{ - return m_pszName ? m_pszName : "Unnamed"; -} - -//----------------------------------------------------------------------------- -// Purpose: Get next temp ent in chain -// Output : CBaseTempEntity * -//----------------------------------------------------------------------------- -CBaseTempEntity *CBaseTempEntity::GetNext( void ) -{ - return m_pNext; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseTempEntity::Precache( void ) -{ - // Nothing... -} - -//----------------------------------------------------------------------------- -// Purpose: Default test implementation. Should only be called by derived classes -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CBaseTempEntity::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - Vector origin, forward; - - Msg( "%s\n", m_pszName ); - AngleVectors( current_angles, &forward ); - - VectorMA( current_origin, 20, forward, origin ); - - CBroadcastRecipientFilter filter; - - Create( filter, 0.0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: Called at startup to allow temp entities to precache any models/sounds that they need -//----------------------------------------------------------------------------- -void CBaseTempEntity::PrecacheTempEnts( void ) -{ - CBaseTempEntity *te = GetList(); - while ( te ) - { - te->Precache(); - te = te->GetNext(); - } -} - - -void CBaseTempEntity::Create( IRecipientFilter& filter, float delay ) -{ - // temp entities can't be reliable or part of the signon message, use real entities instead - Assert( !filter.IsInitMessage() && !filter.IsInitMessage() ); - Assert( delay >= -1 && delay <= 1); // 1 second max delay - - engine->PlaybackTempEntity( filter, delay, - (void *)this, GetServerClass()->m_pTable, GetServerClass()->m_ClassID ); -} diff --git a/game/server/basetempentity.h b/game/server/basetempentity.h deleted file mode 100644 index 2eeef8ce4..000000000 --- a/game/server/basetempentity.h +++ /dev/null @@ -1,65 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#if !defined( BASETEMPENTITY_H ) -#define BASETEMPENTITY_H -#ifdef _WIN32 -#pragma once -#endif - -#include "edict.h" - -// This is the base class for TEMP ENTITIES that use the -// event system to propagate -class CBaseTempEntity -{ -public: - DECLARE_CLASS_NOBASE( CBaseTempEntity ); - DECLARE_SERVERCLASS(); - - CBaseTempEntity( const char *name ); - virtual ~CBaseTempEntity( void ); - - const char *GetName( void ); - - // Force all derived classes to implement a test - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - virtual void Create( IRecipientFilter& filter, float delay = 0.0 ); - - virtual void Precache( void ); - - CBaseTempEntity *GetNext( void ); - - // Get list of tempentities - static CBaseTempEntity *GetList( void ); - - // Called at startup to allow temp entities to precache any models/sounds that they need - static void PrecacheTempEnts( void ); - - void NetworkStateChanged() {} // TE's are sent out right away so we don't track whether state changes or not, - // but we want to allow CNetworkVars. - void NetworkStateChanged( void *pVar ) {} - -private: - // Descriptive name, for when running tests - const char *m_pszName; - - // Next in chain - CBaseTempEntity *m_pNext; - - // ConVars add themselves to this list for the executable. Then ConVarMgr::Init() runs through - // all the console variables and registers them. - static CBaseTempEntity *s_pTempEntities; -}; - -#endif // BASETEMPENTITY_H diff --git a/game/server/basetoggle.h b/game/server/basetoggle.h deleted file mode 100644 index a8f8d76d6..000000000 --- a/game/server/basetoggle.h +++ /dev/null @@ -1,69 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: For the slow removing of the CBaseToggle entity -// only old entities that need it for backwards-compatibility should -// include this file -//=============================================================================// - -#ifndef BASETOGGLE_H -#define BASETOGGLE_H -#pragma once - -#include "baseentity.h" - - -class CBaseToggle : public CBaseEntity -{ - DECLARE_CLASS( CBaseToggle, CBaseEntity ); -public: - CBaseToggle(); - - virtual bool KeyValue( const char *szKeyName, const char *szValue ); - virtual bool KeyValue( const char *szKeyName, Vector vec ) { return BaseClass::KeyValue( szKeyName, vec ); }; - virtual bool KeyValue( const char *szKeyName, float flValue ) { return BaseClass::KeyValue( szKeyName, flValue ); }; - - TOGGLE_STATE m_toggle_state; - float m_flMoveDistance;// how far a door should slide or rotate - float m_flWait; - float m_flLip; - - Vector m_vecPosition1; - Vector m_vecPosition2; - - QAngle m_vecMoveAng; - QAngle m_vecAngle1; - QAngle m_vecAngle2; - - float m_flHeight; - EHANDLE m_hActivator; - Vector m_vecFinalDest; - QAngle m_vecFinalAngle; - - int m_movementType; - - DECLARE_DATADESC(); - - virtual float GetDelay( void ) { return m_flWait; } - - // common member functions - void LinearMove( const Vector &vecDest, float flSpeed ); - void LinearMoveDone( void ); - void AngularMove( const QAngle &vecDestAngle, float flSpeed ); - void AngularMoveDone( void ); - bool IsLockedByMaster( void ); - virtual void MoveDone( void ); - - static float AxisValue( int flags, const QAngle &angles ); - void AxisDir( void ); - static float AxisDelta( int flags, const QAngle &angle1, const QAngle &angle2 ); - - string_t m_sMaster; // If this button has a master switch, this is the targetname. - // A master switch must be of the multisource type. If all - // of the switches in the multisource have been triggered, then - // the button will be allowed to operate. Otherwise, it will be - // deactivated. -}; - - - -#endif // BASETOGGLE_H diff --git a/game/server/baseviewmodel.cpp b/game/server/baseviewmodel.cpp deleted file mode 100644 index 311e5bba5..000000000 --- a/game/server/baseviewmodel.cpp +++ /dev/null @@ -1,116 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "animation.h" -#include "baseviewmodel.h" -#include "player.h" -#include -#include "studio.h" -#include "vguiscreen.h" -#include "saverestore_utlvector.h" -#include "hltvdirector.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -void SendProxy_AnimTime( const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID ); -void SendProxy_SequenceChanged( const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID ); - -//----------------------------------------------------------------------------- -// Purpose: Save Data for Base Weapon object -//-----------------------------------------------------------------------------// -BEGIN_DATADESC( CBaseViewModel ) - - DEFINE_FIELD( m_hOwner, FIELD_EHANDLE ), - -// Client only -// DEFINE_FIELD( m_LagAnglesHistory, CInterpolatedVar < QAngle > ), -// DEFINE_FIELD( m_vLagAngles, FIELD_VECTOR ), - - DEFINE_FIELD( m_nViewModelIndex, FIELD_INTEGER ), - DEFINE_FIELD( m_flTimeWeaponIdle, FIELD_FLOAT ), - DEFINE_FIELD( m_nAnimationParity, FIELD_INTEGER ), - - // Client only -// DEFINE_FIELD( m_nOldAnimationParity, FIELD_INTEGER ), - - DEFINE_FIELD( m_vecLastFacing, FIELD_VECTOR ), - DEFINE_FIELD( m_hWeapon, FIELD_EHANDLE ), - DEFINE_UTLVECTOR( m_hScreens, FIELD_EHANDLE ), - -// Read from weapons file -// DEFINE_FIELD( m_sVMName, FIELD_STRING ), -// DEFINE_FIELD( m_sAnimationPrefix, FIELD_STRING ), - -// --------------------------------------------------------------------- - -// Don't save these, init to 0 and regenerate -// DEFINE_FIELD( m_Activity, FIELD_INTEGER ), - -END_DATADESC() - -int CBaseViewModel::UpdateTransmitState() -{ - if ( IsEffectActive( EF_NODRAW ) ) - { - return SetTransmitState( FL_EDICT_DONTSEND ); - } - - return SetTransmitState( FL_EDICT_FULLCHECK ); -} - -int CBaseViewModel::ShouldTransmit( const CCheckTransmitInfo *pInfo ) -{ - // check if receipient owns this weapon viewmodel - CBasePlayer *pOwner = ToBasePlayer( m_hOwner ); - - if ( pOwner && pOwner->edict() == pInfo->m_pClientEnt ) - { - return FL_EDICT_ALWAYS; - } - - // check if recipient spectates the own of this viewmodel - CBaseEntity *pRecipientEntity = CBaseEntity::Instance( pInfo->m_pClientEnt ); - - if ( pRecipientEntity->IsPlayer() ) - { - CBasePlayer *pPlayer = static_cast( pRecipientEntity ); -#ifndef _XBOX - if ( pPlayer->IsHLTV() ) - { - // if this is the HLTV client, transmit all viewmodels in our PVS - return FL_EDICT_PVSCHECK; - } -#endif - if ( (pPlayer->GetObserverMode() == OBS_MODE_IN_EYE) && (pPlayer->GetObserverTarget() == pOwner) ) - { - return FL_EDICT_ALWAYS; - } - } - - // Don't send to anyone else except the local player or his spectators - return FL_EDICT_DONTSEND; -} - -void CBaseViewModel::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ) -{ - // Are we already marked for transmission? - if ( pInfo->m_pTransmitEdict->Get( entindex() ) ) - return; - - BaseClass::SetTransmit( pInfo, bAlways ); - - // Force our screens to be sent too. - for ( int i=0; i < m_hScreens.Count(); i++ ) - { - CVGuiScreen *pScreen = m_hScreens[i].Get(); - if ( pScreen ) - pScreen->SetTransmit( pInfo, bAlways ); - } -} diff --git a/game/server/baseviewmodel.h b/game/server/baseviewmodel.h deleted file mode 100644 index b4dce9344..000000000 --- a/game/server/baseviewmodel.h +++ /dev/null @@ -1,17 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Server side view model object -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// -#if !defined( BASEVIEWMODEL_H ) -#define BASEVIEWMODEL_H -#ifdef _WIN32 -#pragma once -#endif - -#include "baseviewmodel_shared.h" - -#endif // BASEVIEWMODEL_H diff --git a/game/server/bitstring.cpp b/game/server/bitstring.cpp deleted file mode 100644 index 0ab956e61..000000000 --- a/game/server/bitstring.cpp +++ /dev/null @@ -1,27 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Arbitrary length bit string -// ** NOTE: This class does NOT override the bitwise operators -// as doing so would require overriding the operators -// to allocate memory for the returned bitstring. This method -// would be prone to memory leaks as the calling party -// would have to remember to delete the memory. Funtions -// are used instead to require the calling party to allocate -// and destroy their own memory -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -#include - -#include "bitstring.h" -#include "utlbuffer.h" -#include "tier0/dbg.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - diff --git a/game/server/bitstring.h b/game/server/bitstring.h deleted file mode 100644 index 9dd80c140..000000000 --- a/game/server/bitstring.h +++ /dev/null @@ -1,28 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Arbitrary length bit string -// ** NOTE: This class does NOT override the bitwise operators -// as doing so would require overriding the operators -// to allocate memory for the returned bitstring. This method -// would be prone to memory leaks as the calling party -// would have to remember to delete the memory. Funtions -// are used instead to require the calling party to allocate -// and destroy their own memory -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef BITSTRING_H -#define BITSTRING_H -#pragma once - -#include "bitvec.h" - - -#endif // BITSTRING_H diff --git a/game/server/bmodels.cpp b/game/server/bmodels.cpp deleted file mode 100644 index 14e9f9441..000000000 --- a/game/server/bmodels.cpp +++ /dev/null @@ -1,1426 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Spawn, think, and use functions for common brush entities. -// -//=============================================================================// - -#include "cbase.h" -#include "doors.h" -#include "mathlib/mathlib.h" -#include "physics.h" -#include "ndebugoverlay.h" -#include "engine/IEngineSound.h" -#include "globals.h" -#include "filters.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SF_BRUSH_ACCDCC 16// brush should accelerate and decelerate when toggled -#define SF_BRUSH_HURT 32// rotating brush that inflicts pain based on rotation speed -#define SF_ROTATING_NOT_SOLID 64 // some special rotating objects are not solid. - -// =================== FUNC_WALL ============================================== -class CFuncWall : public CBaseEntity -{ -public: - DECLARE_DATADESC(); - DECLARE_CLASS( CFuncWall, CBaseEntity ); - void Spawn( void ); - bool CreateVPhysics( void ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - int m_nState; -}; - -LINK_ENTITY_TO_CLASS( func_wall, CFuncWall ); - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CFuncWall ) - - DEFINE_FIELD( m_nState, FIELD_INTEGER ), - -END_DATADESC() - -void CFuncWall::Spawn( void ) -{ - SetLocalAngles( vec3_angle ); - SetMoveType( MOVETYPE_PUSH ); // so it doesn't get pushed by anything - SetModel( STRING( GetModelName() ) ); - - // If it can't move/go away, it's really part of the world - AddFlag( FL_WORLDBRUSH ); - - // set manual mode - CreateVPhysics(); -} - - -bool CFuncWall::CreateVPhysics( void ) -{ - SetSolid( SOLID_BSP ); - IPhysicsObject *pPhys = VPhysicsInitStatic(); - if ( pPhys ) - { - int contents = modelinfo->GetModelContents( GetModelIndex() ); - if ( ! (contents & (MASK_SOLID|MASK_PLAYERSOLID|MASK_NPCSOLID)) ) - { - // leave the physics shadow there in case it has crap constrained to it - // but disable collisions with it - pPhys->EnableCollisions( false ); - } - } - - return true; -} - - -void CFuncWall::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - if ( ShouldToggle( useType, m_nState ) ) - { - m_nState = 1 - m_nState; - } -} - - -#define SF_WALL_START_OFF 0x0001 - -class CFuncWallToggle : public CFuncWall -{ -public: - DECLARE_CLASS( CFuncWallToggle, CFuncWall ); - - DECLARE_DATADESC(); - - void Spawn( void ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - void InputToggle( inputdata_t &inputdata ); - - void TurnOff( void ); - void TurnOn( void ); - bool IsOn( void ); -}; - -BEGIN_DATADESC( CFuncWallToggle ) - - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( func_wall_toggle, CFuncWallToggle ); - -void CFuncWallToggle::Spawn( void ) -{ - BaseClass::Spawn(); - if ( HasSpawnFlags( SF_WALL_START_OFF ) ) - TurnOff(); - - SetMoveType( MOVETYPE_PUSH ); -} - - -void CFuncWallToggle::TurnOff( void ) -{ - IPhysicsObject *pPhys = VPhysicsGetObject(); - if ( pPhys ) - { - pPhys->EnableCollisions( false ); - } - AddSolidFlags( FSOLID_NOT_SOLID ); - AddEffects( EF_NODRAW ); -} - - -void CFuncWallToggle::TurnOn( void ) -{ - IPhysicsObject *pPhys = VPhysicsGetObject(); - if ( pPhys ) - { - pPhys->EnableCollisions( true ); - } - RemoveSolidFlags( FSOLID_NOT_SOLID ); - RemoveEffects( EF_NODRAW ); -} - - -bool CFuncWallToggle::IsOn( void ) -{ - if ( IsSolidFlagSet( FSOLID_NOT_SOLID ) ) - return false; - return true; -} - -void CFuncWallToggle::InputToggle( inputdata_t &inputdata ) -{ - int status = IsOn(); - - if ( ShouldToggle( USE_TOGGLE, status ) ) - { - if ( status ) - TurnOff(); - else - TurnOn(); - } -} - -//Adrian - Is this function needed at all? -void CFuncWallToggle::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - int status = IsOn(); - - if ( ShouldToggle( useType, status ) ) - { - if ( status ) - TurnOff(); - else - TurnOn(); - } -} - -//============================== FUNC_VEHICLECLIP ===================================== -class CFuncVehicleClip : public CBaseEntity -{ -public: - DECLARE_CLASS( CFuncVehicleClip, CBaseEntity ); - DECLARE_DATADESC(); - - void Spawn(); - bool CreateVPhysics( void ); - - void InputEnable( inputdata_t &data ); - void InputDisable( inputdata_t &data ); - -private: -}; - -BEGIN_DATADESC( CFuncVehicleClip ) - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( func_vehicleclip, CFuncVehicleClip ); - -void CFuncVehicleClip::Spawn() -{ - - SetLocalAngles( vec3_angle ); - SetMoveType( MOVETYPE_PUSH ); // so it doesn't get pushed by anything - SetModel( STRING( GetModelName() ) ); - - // It's part of the world - AddFlag( FL_WORLDBRUSH ); - - CreateVPhysics(); - - AddEffects( EF_NODRAW ); // make entity invisible - - SetCollisionGroup( COLLISION_GROUP_VEHICLE_CLIP ); -} - -bool CFuncVehicleClip::CreateVPhysics( void ) -{ - SetSolid( SOLID_BSP ); - VPhysicsInitStatic(); - - return true; -} - -void CFuncVehicleClip::InputEnable( inputdata_t &data ) -{ - IPhysicsObject *pPhys = VPhysicsGetObject(); - if ( pPhys ) - { - pPhys->EnableCollisions( true ); - } - RemoveSolidFlags( FSOLID_NOT_SOLID ); -} - -void CFuncVehicleClip::InputDisable( inputdata_t &data ) -{ - IPhysicsObject *pPhys = VPhysicsGetObject(); - if ( pPhys ) - { - pPhys->EnableCollisions( false ); - } - AddSolidFlags( FSOLID_NOT_SOLID ); -} - -//============================= FUNC_CONVEYOR ======================================= - -#define SF_CONVEYOR_VISUAL 0x0001 -#define SF_CONVEYOR_NOTSOLID 0x0002 - -class CFuncConveyor : public CFuncWall -{ -public: - DECLARE_CLASS( CFuncConveyor, CFuncWall ); - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - CFuncConveyor(); - - void Spawn( void ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - void UpdateSpeed( float flNewSpeed ); - - void GetGroundVelocityToApply( Vector &vecGroundVel ); - - // Input handlers. - void InputToggleDirection( inputdata_t &inputdata ); - void InputSetSpeed( inputdata_t &inputdata ); - -private: - - Vector m_vecMoveDir; - CNetworkVar( float, m_flConveyorSpeed ); -}; - -LINK_ENTITY_TO_CLASS( func_conveyor, CFuncConveyor ); - -BEGIN_DATADESC( CFuncConveyor ) - - DEFINE_INPUTFUNC( FIELD_VOID, "ToggleDirection", InputToggleDirection ), - DEFINE_INPUTFUNC( FIELD_VOID, "SetSpeed", InputSetSpeed ), - - DEFINE_KEYFIELD( m_vecMoveDir, FIELD_VECTOR, "movedir" ), - DEFINE_FIELD( m_flConveyorSpeed, FIELD_FLOAT ), - -END_DATADESC() - - -IMPLEMENT_SERVERCLASS_ST(CFuncConveyor, DT_FuncConveyor) - SendPropFloat( SENDINFO(m_flConveyorSpeed), 0, SPROP_NOSCALE ), -END_SEND_TABLE() - - -CFuncConveyor::CFuncConveyor() -{ - m_flConveyorSpeed = 0.0; -} - -void CFuncConveyor::Spawn( void ) -{ - // Convert movedir from angles to a vector - QAngle angMoveDir = QAngle( m_vecMoveDir.x, m_vecMoveDir.y, m_vecMoveDir.z ); - AngleVectors( angMoveDir, &m_vecMoveDir ); - - BaseClass::Spawn(); - - if ( !HasSpawnFlags(SF_CONVEYOR_VISUAL) ) - AddFlag( FL_CONVEYOR ); - - // HACKHACK - This is to allow for some special effects - if ( HasSpawnFlags( SF_CONVEYOR_NOTSOLID ) ) - { - AddSolidFlags( FSOLID_NOT_SOLID ); - } - - if ( m_flSpeed == 0 ) - m_flSpeed = 100; - - UpdateSpeed( m_flSpeed ); -} - - -void CFuncConveyor::UpdateSpeed( float flNewSpeed ) -{ - m_flConveyorSpeed = flNewSpeed; -} - - -void CFuncConveyor::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - m_flSpeed = -m_flSpeed; - UpdateSpeed( m_flSpeed ); -} - - -void CFuncConveyor::InputToggleDirection( inputdata_t &inputdata ) -{ - Use( inputdata.pActivator, inputdata.pCaller, USE_TOGGLE, 0 ); -} - - -void CFuncConveyor::InputSetSpeed( inputdata_t &inputdata ) -{ - m_flSpeed = inputdata.value.Float(); - UpdateSpeed( m_flSpeed ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns the velocity imparted to players standing on us. -//----------------------------------------------------------------------------- -void CFuncConveyor::GetGroundVelocityToApply( Vector &vecGroundVel ) -{ - vecGroundVel = m_vecMoveDir * m_flSpeed; -} - - -// =================== FUNC_ILLUSIONARY ============================================== -// A simple entity that looks solid but lets you walk through it. -class CFuncIllusionary : public CBaseEntity -{ - DECLARE_CLASS( CFuncIllusionary, CBaseEntity ); -public: - void Spawn( void ); -}; - -LINK_ENTITY_TO_CLASS( func_illusionary, CFuncIllusionary ); - -void CFuncIllusionary::Spawn( void ) -{ - SetLocalAngles( vec3_angle ); - SetMoveType( MOVETYPE_NONE ); - SetSolid( SOLID_NONE ); - SetModel( STRING( GetModelName() ) ); -} - - -//----------------------------------------------------------------------------- -// Purpose: A rotating brush entity. -// -// You need to have an origin brush as part of this entity. The -// center of that brush will be the point around which it is rotated. -// -// It will rotate around the Z axis by default. Spawnflags can be set -// to make it rotate around the X or Y axes. -// -// The direction of rotation is also controlled by a spawnflag. -//----------------------------------------------------------------------------- -class CFuncRotating : public CBaseEntity -{ - DECLARE_CLASS( CFuncRotating, CBaseEntity ); -public: - // basic functions - void Spawn( void ); - void Precache( void ); - bool CreateVPhysics( void ); - void SpinUpMove( void ); - void SpinDownMove( void ); - bool KeyValue( const char *szKeyName, const char *szValue ); - void HurtTouch ( CBaseEntity *pOther ); - void RotatingUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - void RotateMove( void ); - void ReverseMove( void ); - void RampPitchVol( void ); - void Blocked( CBaseEntity *pOther ); - void SetTargetSpeed( float flSpeed ); - void UpdateSpeed( float flNewSpeed ); - - int DrawDebugTextOverlays(void); - - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - -protected: - - bool SpinDown( float flTargetSpeed ); - float GetMoveSpeed( float flSpeed ); - - float GetNextMoveInterval() const; - - // Input handlers - void InputSetSpeed( inputdata_t &inputdata ); - void InputStart( inputdata_t &inputdata ); - void InputStop( inputdata_t &inputdata ); - void InputStartForward( inputdata_t &inputdata ); - void InputStartBackward( inputdata_t &inputdata ); - void InputToggle( inputdata_t &inputdata ); - void InputReverse( inputdata_t &inputdata ); - void InputStopAtStartPos( inputdata_t &inputdata ); - - QAngle m_vecMoveAng; - - float m_flFanFriction; - float m_flAttenuation; - float m_flVolume; - float m_flTargetSpeed; // Target value for m_flSpeed, used for spinning up and down. - float m_flMaxSpeed; // Maximum value for m_flSpeed, used for ramping sound effects. - float m_flBlockDamage; // Damage inflicted when blocked. - string_t m_NoiseRunning; - bool m_bReversed; - - QAngle m_angStart; - bool m_bStopAtStartPos; - - bool m_bSolidBsp; // Brush is SOLID_BSP - -public: - Vector m_vecClientOrigin; - QAngle m_vecClientAngles; -}; - -LINK_ENTITY_TO_CLASS( func_rotating, CFuncRotating ); - - -BEGIN_DATADESC( CFuncRotating ) - - DEFINE_FIELD( m_vecMoveAng, FIELD_VECTOR ), - DEFINE_FIELD( m_flFanFriction, FIELD_FLOAT ), - DEFINE_FIELD( m_flAttenuation, FIELD_FLOAT ), - DEFINE_FIELD( m_flVolume, FIELD_FLOAT ), - DEFINE_FIELD( m_flTargetSpeed, FIELD_FLOAT ), - DEFINE_KEYFIELD( m_flMaxSpeed, FIELD_FLOAT, "maxspeed" ), - DEFINE_KEYFIELD( m_flBlockDamage, FIELD_FLOAT, "dmg" ), - DEFINE_KEYFIELD( m_NoiseRunning, FIELD_SOUNDNAME, "message" ), - DEFINE_FIELD( m_bReversed, FIELD_BOOLEAN ), - DEFINE_FIELD( m_angStart, FIELD_VECTOR ), - DEFINE_FIELD( m_bStopAtStartPos, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_bSolidBsp, FIELD_BOOLEAN, "solidbsp" ), - - // Function Pointers - DEFINE_FUNCTION( SpinUpMove ), - DEFINE_FUNCTION( SpinDownMove ), - DEFINE_FUNCTION( HurtTouch ), - DEFINE_FUNCTION( RotatingUse ), - DEFINE_FUNCTION( RotateMove ), - DEFINE_FUNCTION( ReverseMove ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetSpeed", InputSetSpeed ), - DEFINE_INPUTFUNC( FIELD_VOID, "Start", InputStart ), - DEFINE_INPUTFUNC( FIELD_VOID, "Stop", InputStop ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - DEFINE_INPUTFUNC( FIELD_VOID, "Reverse", InputReverse ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartForward", InputStartForward ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartBackward", InputStartBackward ), - DEFINE_INPUTFUNC( FIELD_VOID, "StopAtStartPos", InputStopAtStartPos ), - -END_DATADESC() - -extern void SendProxy_Origin( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); -void SendProxy_FuncRotatingOrigin( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ) -{ - CFuncRotating *entity = (CFuncRotating*)pStruct; - Assert( entity ); - if ( entity->HasSpawnFlags(SF_BRUSH_ROTATE_CLIENTSIDE) ) - { - const Vector *v = &entity->m_vecClientOrigin; - pOut->m_Vector[ 0 ] = v->x; - pOut->m_Vector[ 1 ] = v->y; - pOut->m_Vector[ 2 ] = v->z; - return; - } - - SendProxy_Origin( pProp, pStruct, pData, pOut, iElement, objectID ); -} - -extern void SendProxy_Angles( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); -void SendProxy_FuncRotatingAngles( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ) -{ - CFuncRotating *entity = (CFuncRotating*)pStruct; - Assert( entity ); - if ( entity->HasSpawnFlags(SF_BRUSH_ROTATE_CLIENTSIDE) ) - { - const QAngle *a = &entity->m_vecClientAngles; - pOut->m_Vector[ 0 ] = anglemod( a->x ); - pOut->m_Vector[ 1 ] = anglemod( a->y ); - pOut->m_Vector[ 2 ] = anglemod( a->z ); - return; - } - - SendProxy_Angles( pProp, pStruct, pData, pOut, iElement, objectID ); -} - -extern void SendProxy_SimulationTime( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID ); -void SendProxy_FuncRotatingSimulationTime( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID ) -{ - CFuncRotating *entity = (CFuncRotating*)pStruct; - Assert( entity ); - if ( entity->HasSpawnFlags(SF_BRUSH_ROTATE_CLIENTSIDE) ) - { - pOut->m_Int = 0; - return; - } - - SendProxy_SimulationTime( pProp, pStruct, pVarData, pOut, iElement, objectID ); -} - -IMPLEMENT_SERVERCLASS_ST(CFuncRotating, DT_FuncRotating) - SendPropExclude( "DT_BaseEntity", "m_angRotation" ), - SendPropExclude( "DT_BaseEntity", "m_vecOrigin" ), - SendPropExclude( "DT_BaseEntity", "m_flSimulationTime" ), - - SendPropVector(SENDINFO(m_vecOrigin), -1, SPROP_COORD|SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_FuncRotatingOrigin ), - SendPropQAngles(SENDINFO(m_angRotation), 13, SPROP_CHANGES_OFTEN, SendProxy_FuncRotatingAngles ), - SendPropInt(SENDINFO(m_flSimulationTime), SIMULATION_TIME_WINDOW_BITS, SPROP_UNSIGNED|SPROP_CHANGES_OFTEN|SPROP_ENCODED_AGAINST_TICKCOUNT, SendProxy_FuncRotatingSimulationTime), -END_SEND_TABLE() - - - -//----------------------------------------------------------------------------- -// Purpose: Handles keyvalues from the BSP. Called before spawning. -//----------------------------------------------------------------------------- -bool CFuncRotating::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "fanfriction")) - { - m_flFanFriction = atof(szValue)/100; - } - else if (FStrEq(szKeyName, "Volume")) - { - m_flVolume = atof(szValue) / 10.0; - m_flVolume = clamp(m_flVolume, 0.0, 1.0f); - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Called when spawning, after keyvalues have been set. -//----------------------------------------------------------------------------- -void CFuncRotating::Spawn( ) -{ -#ifdef TF_DLL - AddSpawnFlags( SF_BRUSH_ROTATE_CLIENTSIDE ); -#endif - - // - // Maintain compatibility with previous maps. - // - if (m_flVolume == 0.0) - { - m_flVolume = 1.0; - } - - // - // If the designer didn't set a sound attenuation, default to one. - // - if ( HasSpawnFlags(SF_BRUSH_ROTATE_SMALLRADIUS) ) - { - m_flAttenuation = ATTN_IDLE; - } - else if ( HasSpawnFlags(SF_BRUSH_ROTATE_MEDIUMRADIUS) ) - { - m_flAttenuation = ATTN_STATIC; - } - else if ( HasSpawnFlags(SF_BRUSH_ROTATE_LARGERADIUS) ) - { - m_flAttenuation = ATTN_NORM; - } - else - { - m_flAttenuation = ATTN_NORM; - } - - // - // Prevent divide by zero if level designer forgets friction! - // - if ( m_flFanFriction == 0 ) - { - m_flFanFriction = 1; - } - - // - // Build the axis of rotation based on spawnflags. - // - if ( HasSpawnFlags(SF_BRUSH_ROTATE_Z_AXIS) ) - { - m_vecMoveAng = QAngle(0,0,1); - } - else if ( HasSpawnFlags(SF_BRUSH_ROTATE_X_AXIS) ) - { - m_vecMoveAng = QAngle(1,0,0); - } - else - { - m_vecMoveAng = QAngle(0,1,0); // y-axis - } - - // - // Check for reverse rotation. - // - if ( HasSpawnFlags(SF_BRUSH_ROTATE_BACKWARDS) ) - { - m_vecMoveAng = m_vecMoveAng * -1; - } - - SetSolid( SOLID_VPHYSICS ); - - // - // Some rotating objects like fake volumetric lights will not be solid. - // - if ( HasSpawnFlags(SF_ROTATING_NOT_SOLID) ) - { - AddSolidFlags( FSOLID_NOT_SOLID ); - SetMoveType( MOVETYPE_PUSH ); - } - else - { - RemoveSolidFlags( FSOLID_NOT_SOLID ); - SetMoveType( MOVETYPE_PUSH ); - } - - SetModel( STRING( GetModelName() ) ); - - SetUse( &CFuncRotating::RotatingUse ); - - // - // Did level designer forget to assign a maximum speed? Prevent a divide by - // zero in RampPitchVol as well as allowing the rotator to work. - // - m_flMaxSpeed = fabs( m_flMaxSpeed ); - if (m_flMaxSpeed == 0) - { - m_flMaxSpeed = 100; - } - - // - // If the brush should be initially rotating, use it in a little while. - // - if ( HasSpawnFlags(SF_BRUSH_ROTATE_START_ON) ) - { - SetThink( &CFuncRotating::SUB_CallUseToggle ); - SetNextThink( gpGlobals->curtime + .2 ); // leave a magic delay for client to start up - } - - // - // Can this brush inflict pain? - // - if ( HasSpawnFlags(SF_BRUSH_HURT) ) - { - SetTouch( &CFuncRotating::HurtTouch ); - } - - // - // Set speed to 0 in case there's an old "speed" key lying around. - // - m_flSpeed = 0; - - Precache( ); - CreateVPhysics(); - - m_angStart = GetLocalAngles(); - - // Slam the object back to solid - if we really want it to be solid. - if ( m_bSolidBsp ) - { - SetSolid( SOLID_BSP ); - } - - if ( HasSpawnFlags(SF_BRUSH_ROTATE_CLIENTSIDE) ) - { - m_vecClientOrigin = GetLocalOrigin(); - m_vecClientAngles = GetLocalAngles(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CFuncRotating::CreateVPhysics( void ) -{ - if ( !IsSolidFlagSet( FSOLID_NOT_SOLID )) - { - VPhysicsInitShadow( false, false ); - } - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncRotating::Precache( void ) -{ - // - // Set up rotation sound. - // - char *szSoundFile = ( char * )STRING( m_NoiseRunning ); - if ( !m_NoiseRunning || strlen( szSoundFile ) == 0 ) - { - // No sound set up, use the null sound. - m_NoiseRunning = AllocPooledString("DoorSound.Null"); - } - PrecacheScriptSound( STRING( m_NoiseRunning ) ); - - if (GetLocalAngularVelocity() != vec3_angle ) - { - // - // If fan was spinning, and we went through transition or save/restore, - // make sure we restart the sound. 1.5 sec delay is a magic number. - // - SetMoveDone( &CFuncRotating::SpinUpMove ); - SetMoveDoneTime( 1.5 ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Will hurt others based on how fast the brush is spinning. -// Input : pOther - -//----------------------------------------------------------------------------- -void CFuncRotating::HurtTouch ( CBaseEntity *pOther ) -{ - // we can't hurt this thing, so we're not concerned with it - if ( !pOther->m_takedamage ) - return; - - // calculate damage based on rotation speed - m_flBlockDamage = GetLocalAngularVelocity().Length() / 10; - -#ifdef HL1_DLL - if( m_flBlockDamage > 0 ) -#endif - { - pOther->TakeDamage( CTakeDamageInfo( this, this, m_flBlockDamage, DMG_CRUSH ) ); - - Vector vecNewVelocity = pOther->GetAbsOrigin() - WorldSpaceCenter(); - VectorNormalize(vecNewVelocity); - vecNewVelocity *= m_flBlockDamage; - pOther->SetAbsVelocity( vecNewVelocity ); - } -} - - -#define FANPITCHMIN 30 -#define FANPITCHMAX 100 - - -//----------------------------------------------------------------------------- -// Purpose: Ramp pitch and volume up to maximum values, based on the difference -// between how fast we're going vs how fast we can go. -//----------------------------------------------------------------------------- -void CFuncRotating::RampPitchVol( void ) -{ - // - // Calc volume and pitch as % of maximum vol and pitch. - // - float fpct = fabs(m_flSpeed) / m_flMaxSpeed; - float fvol = clamp(m_flVolume * fpct, 0, 1); // slowdown volume ramps down to 0 - - float fpitch = FANPITCHMIN + (FANPITCHMAX - FANPITCHMIN) * fpct; - - int pitch = (int)clamp(fpitch, 0, 255); - if (pitch == PITCH_NORM) - { - pitch = PITCH_NORM - 1; - } - - // - // Update the fan's volume and pitch. - // - CPASAttenuationFilter filter( GetAbsOrigin(), m_flAttenuation ); - filter.MakeReliable(); - - EmitSound_t ep; - ep.m_nChannel = CHAN_STATIC; - ep.m_pSoundName = STRING(m_NoiseRunning); - ep.m_flVolume = fvol; - ep.m_SoundLevel = ATTN_TO_SNDLVL( m_flAttenuation ); - ep.m_nFlags = SND_CHANGE_PITCH | SND_CHANGE_VOL; - ep.m_nPitch = pitch; - - EmitSound( filter, entindex(), ep ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CFuncRotating::GetNextMoveInterval() const -{ - if ( m_bStopAtStartPos ) - { - return TICK_INTERVAL; - } - return 0.1f; -} - -//----------------------------------------------------------------------------- -// Purpose: Sets the current speed to the given value and manages the sound effects. -// Input : flNewSpeed - New speed in degrees per second. -//----------------------------------------------------------------------------- -void CFuncRotating::UpdateSpeed( float flNewSpeed ) -{ - float flOldSpeed = m_flSpeed; - m_flSpeed = clamp( flNewSpeed, -m_flMaxSpeed, m_flMaxSpeed ); - - if ( m_bStopAtStartPos ) - { - int checkAxis = 2; - // See if we got close to the starting orientation - if ( m_vecMoveAng[0] != 0 ) - { - checkAxis = 0; - } - else if ( m_vecMoveAng[1] != 0 ) - { - checkAxis = 1; - } - - float angDelta = anglemod( GetLocalAngles()[ checkAxis ] - m_angStart[ checkAxis ] ); - if ( angDelta > 180.0f ) - { - angDelta -= 360.0f; - } - - if ( flNewSpeed < 100 ) - { - if ( flNewSpeed <= 25 && fabs( angDelta ) < 1.0f ) - { - m_flTargetSpeed = 0; - m_bStopAtStartPos = false; - m_flSpeed = 0.0f; - - SetLocalAngles( m_angStart ); - } - else if ( fabs( angDelta ) > 90.0f ) - { - // Keep rotating at same speed for now - m_flSpeed = flOldSpeed; - } - else - { - float minSpeed = fabs( angDelta ); - if ( minSpeed < 20 ) - minSpeed = 20; - - m_flSpeed = flOldSpeed > 0.0f ? minSpeed : -minSpeed; - } - } - } - - - if ( ( flOldSpeed == 0 ) && ( m_flSpeed != 0 ) ) - { - // Starting to move - emit the sound. - CPASAttenuationFilter filter( GetAbsOrigin(), m_flAttenuation ); - filter.MakeReliable(); - - EmitSound_t ep; - ep.m_nChannel = CHAN_STATIC; - ep.m_pSoundName = STRING(m_NoiseRunning); - ep.m_flVolume = 0.01; - ep.m_SoundLevel = ATTN_TO_SNDLVL( m_flAttenuation ); - ep.m_nPitch = FANPITCHMIN; - - EmitSound( filter, entindex(), ep ); - RampPitchVol(); - } - else if ( ( flOldSpeed != 0 ) && ( m_flSpeed == 0 ) ) - { - // Stopping - stop the sound. - StopSound( entindex(), CHAN_STATIC, STRING(m_NoiseRunning) ); - - } - else - { - // Changing speed - adjust the pitch and volume. - RampPitchVol(); - } - - SetLocalAngularVelocity( m_vecMoveAng * m_flSpeed ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Think function. Accelerates a func_rotating to a higher angular velocity. -//----------------------------------------------------------------------------- -void CFuncRotating::SpinUpMove( void ) -{ - // - // Calculate our new speed. - // - bool bSpinUpDone = false; - float flNewSpeed = fabs( m_flSpeed ) + 0.2 * m_flMaxSpeed * m_flFanFriction; - if ( fabs( flNewSpeed ) >= fabs( m_flTargetSpeed ) ) - { - // Reached our target speed. - flNewSpeed = m_flTargetSpeed; - bSpinUpDone = !m_bStopAtStartPos; - } - else if ( m_flTargetSpeed < 0 ) - { - // Spinning up in reverse - negate the speed. - flNewSpeed *= -1; - } - - // - // Apply the new speed, adjust sound pitch and volume. - // - UpdateSpeed( flNewSpeed ); - - // - // If we've met or exceeded target speed, stop spinning up. - // - if ( bSpinUpDone ) - { - SetMoveDone( &CFuncRotating::RotateMove ); - RotateMove(); - } - - SetMoveDoneTime( GetNextMoveInterval() ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Decelerates the rotator from a higher speed to a lower one. -// Input : flTargetSpeed - Speed to spin down to. -// Output : Returns true if we reached the target speed, false otherwise. -//----------------------------------------------------------------------------- -bool CFuncRotating::SpinDown( float flTargetSpeed ) -{ - // - // Bleed off a little speed due to friction. - // - bool bSpinDownDone = false; - float flNewSpeed = fabs( m_flSpeed ) - 0.1 * m_flMaxSpeed * m_flFanFriction; - if ( flNewSpeed < 0 ) - { - flNewSpeed = 0; - } - - if ( fabs( flNewSpeed ) <= fabs( flTargetSpeed ) ) - { - // Reached our target speed. - flNewSpeed = flTargetSpeed; - bSpinDownDone = !m_bStopAtStartPos; - } - else if ( m_flSpeed < 0 ) - { - // Spinning down in reverse - negate the speed. - flNewSpeed *= -1; - } - - // - // Apply the new speed, adjust sound pitch and volume. - // - UpdateSpeed( flNewSpeed ); - - // - // If we've met or exceeded target speed, stop spinning down. - // - return bSpinDownDone; -} - - -//----------------------------------------------------------------------------- -// Purpose: Think function. Decelerates a func_rotating to a lower angular velocity. -//----------------------------------------------------------------------------- -void CFuncRotating::SpinDownMove( void ) -{ - // - // If we've met or exceeded target speed, stop spinning down. - // - if ( SpinDown( m_flTargetSpeed ) ) - { - SetMoveDone( &CFuncRotating::RotateMove ); - RotateMove(); - } - else - { - SetMoveDoneTime( GetNextMoveInterval() ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Think function for reversing directions. Spins down to zero, then -// starts spinning up to the target speed. -//----------------------------------------------------------------------------- -void CFuncRotating::ReverseMove( void ) -{ - if ( SpinDown( 0 ) ) - { - // We've reached zero - spin back up to the target speed. - SetTargetSpeed( m_flTargetSpeed ); - } - else - { - SetMoveDoneTime( GetNextMoveInterval() ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Think function. Called while rotating at a constant angular velocity. -//----------------------------------------------------------------------------- -void CFuncRotating::RotateMove( void ) -{ - SetMoveDoneTime( 10 ); - - if ( m_bStopAtStartPos ) - { - SetMoveDoneTime( GetNextMoveInterval() ); - int checkAxis = 2; - - // See if we got close to the starting orientation - if ( m_vecMoveAng[0] != 0 ) - { - checkAxis = 0; - } - else if ( m_vecMoveAng[1] != 0 ) - { - checkAxis = 1; - } - - float angDelta = anglemod( GetLocalAngles()[ checkAxis ] - m_angStart[ checkAxis ] ); - if ( angDelta > 180.0f ) - angDelta -= 360.0f; - - QAngle avel = GetLocalAngularVelocity(); - // Delta per tick - QAngle avelpertick = avel * TICK_INTERVAL; - - if ( fabs( angDelta ) < fabs( avelpertick[ checkAxis ] ) ) - { - SetTargetSpeed( 0 ); - SetLocalAngles( m_angStart ); - m_bStopAtStartPos = false; - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Used for debug output. Returns the given speed considering our current -// direction of rotation, so that positive values are forward and negative -// values are backward. -// Input : flSpeed - Angular speed in degrees per second. -//----------------------------------------------------------------------------- -float CFuncRotating::GetMoveSpeed( float flSpeed ) -{ - if ( m_vecMoveAng[0] != 0 ) - { - return flSpeed * m_vecMoveAng[0]; - } - - if ( m_vecMoveAng[1] != 0 ) - { - return flSpeed * m_vecMoveAng[1]; - } - - return flSpeed * m_vecMoveAng[2]; -} - - -//----------------------------------------------------------------------------- -// Purpose: Sets a new angular velocity to achieve. -// Input : flSpeed - Target angular velocity in degrees per second. -//----------------------------------------------------------------------------- -void CFuncRotating::SetTargetSpeed( float flSpeed ) -{ - // - // Make sure the sign is correct - positive for forward rotation, - // negative for reverse rotation. - // - flSpeed = fabs( flSpeed ); - if ( m_bReversed ) - { - flSpeed *= -1; - } - - m_flTargetSpeed = flSpeed; - - // - // If we don't accelerate, change to the new speed instantly. - // - if ( !HasSpawnFlags(SF_BRUSH_ACCDCC ) ) - { - UpdateSpeed( m_flTargetSpeed ); - SetMoveDone( &CFuncRotating::RotateMove ); - } - // - // Otherwise deal with acceleration/deceleration: - // - else - { - // - // Check for reversing directions. - // - if ((( m_flSpeed > 0 ) && ( m_flTargetSpeed < 0 )) || - (( m_flSpeed < 0 ) && ( m_flTargetSpeed > 0 ))) - { - SetMoveDone( &CFuncRotating::ReverseMove ); - } - // - // If we are below the new target speed, spin up to the target speed. - // - else if ( fabs( m_flSpeed ) < fabs( m_flTargetSpeed ) ) - { - SetMoveDone( &CFuncRotating::SpinUpMove ); - } - // - // If we are above the new target speed, spin down to the target speed. - // - else if ( fabs( m_flSpeed ) > fabs( m_flTargetSpeed ) ) - { - SetMoveDone( &CFuncRotating::SpinDownMove ); - } - // - // We are already at the new target speed. Just keep rotating. - // - else - { - SetMoveDone( &CFuncRotating::RotateMove ); - } - } - - SetMoveDoneTime( GetNextMoveInterval() ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Called when a rotating brush is used by the player. -// Input : pActivator - -// pCaller - -// useType - -// value - -//----------------------------------------------------------------------------- -void CFuncRotating::RotatingUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - // - // If the rotator is spinning, stop it. - // - if ( m_flSpeed != 0 ) - { - SetTargetSpeed( 0 ); - } - // - // Rotator is not moving, so start it. - // - else - { - SetTargetSpeed( m_flMaxSpeed ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that reverses the direction of rotation. -//----------------------------------------------------------------------------- -void CFuncRotating::InputReverse( inputdata_t &inputdata ) -{ - m_bStopAtStartPos = false; - m_bReversed = !m_bReversed; - SetTargetSpeed( m_flSpeed ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for setting the speed of the rotator. -// Input : Float target angular velocity as a ratio of maximum speed [0, 1]. -//----------------------------------------------------------------------------- -void CFuncRotating::InputSetSpeed( inputdata_t &inputdata ) -{ - m_bStopAtStartPos = false; - float flSpeed = inputdata.value.Float(); - m_bReversed = flSpeed < 0 ? true : false; - flSpeed = fabs(flSpeed); - SetTargetSpeed( clamp( flSpeed, 0, 1 ) * m_flMaxSpeed ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler to start the rotator spinning. -//----------------------------------------------------------------------------- -void CFuncRotating::InputStart( inputdata_t &inputdata ) -{ - m_bStopAtStartPos = false; - SetTargetSpeed( m_flMaxSpeed ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler to start the rotator spinning. -//----------------------------------------------------------------------------- -void CFuncRotating::InputStartForward( inputdata_t &inputdata ) -{ - m_bReversed = false; - SetTargetSpeed( m_flMaxSpeed ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler to start the rotator spinning. -//----------------------------------------------------------------------------- -void CFuncRotating::InputStartBackward( inputdata_t &inputdata ) -{ - m_bStopAtStartPos = false; - m_bReversed = true; - SetTargetSpeed( m_flMaxSpeed ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler to stop the rotator from spinning. -//----------------------------------------------------------------------------- -void CFuncRotating::InputStop( inputdata_t &inputdata ) -{ - m_bStopAtStartPos = false; - SetTargetSpeed( 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CFuncRotating::InputStopAtStartPos( inputdata_t &inputdata ) -{ - m_bStopAtStartPos = true; - SetTargetSpeed( 0 ); - SetMoveDoneTime( GetNextMoveInterval() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Starts the rotator if it is still, stops it if it is spinning. -//----------------------------------------------------------------------------- -void CFuncRotating::InputToggle( inputdata_t &inputdata ) -{ - if (m_flSpeed > 0) - { - SetTargetSpeed( 0 ); - } - else - { - SetTargetSpeed( m_flMaxSpeed ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: An entity has blocked the brush. -// Input : pOther - -//----------------------------------------------------------------------------- -void CFuncRotating::Blocked( CBaseEntity *pOther ) -{ -#ifdef HL1_DLL - if( m_flBlockDamage > 0 ) -#endif - pOther->TakeDamage( CTakeDamageInfo( this, this, m_flBlockDamage, DMG_CRUSH ) ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Input : -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CFuncRotating::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - Q_snprintf( tempstr, sizeof( tempstr ),"Speed cur (target): %3.2f (%3.2f)", GetMoveSpeed( m_flSpeed ), GetMoveSpeed( m_flTargetSpeed ) ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; - -} - - -class CFuncVPhysicsClip : public CBaseEntity -{ - DECLARE_DATADESC(); - DECLARE_CLASS( CFuncVPhysicsClip, CBaseEntity ); - -public: - void Spawn(); - void Activate(); - bool CreateVPhysics( void ); - - bool EntityPassesFilter( CBaseEntity *pOther ); - bool ForceVPhysicsCollide( CBaseEntity *pEntity ); - - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - -private: - - string_t m_iFilterName; - CHandle m_hFilter; - bool m_bDisabled; -}; - -// Global Savedata for base trigger -BEGIN_DATADESC( CFuncVPhysicsClip ) - - // Keyfields - DEFINE_KEYFIELD( m_iFilterName, FIELD_STRING, "filtername" ), - DEFINE_FIELD( m_hFilter, FIELD_EHANDLE ), - DEFINE_FIELD( m_bDisabled, FIELD_BOOLEAN ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( func_clip_vphysics, CFuncVPhysicsClip ); - -void CFuncVPhysicsClip::Spawn( void ) -{ - SetMoveType( MOVETYPE_PUSH ); // so it doesn't get pushed by anything - SetSolid( SOLID_VPHYSICS ); - AddSolidFlags( FSOLID_NOT_SOLID ); - SetModel( STRING( GetModelName() ) ); - AddEffects( EF_NODRAW ); - CreateVPhysics(); - VPhysicsGetObject()->EnableCollisions( !m_bDisabled ); -} - - -bool CFuncVPhysicsClip::CreateVPhysics( void ) -{ - VPhysicsInitStatic(); - return true; -} - - -void CFuncVPhysicsClip::Activate( void ) -{ - // Get a handle to my filter entity if there is one - if (m_iFilterName != NULL_STRING) - { - m_hFilter = dynamic_cast(gEntList.FindEntityByName( NULL, m_iFilterName )); - } - BaseClass::Activate(); -} - -bool CFuncVPhysicsClip::EntityPassesFilter( CBaseEntity *pOther ) -{ - CBaseFilter* pFilter = (CBaseFilter*)(m_hFilter.Get()); - - if ( pFilter ) - return pFilter->PassesFilter( this, pOther ); - - if ( pOther->GetMoveType() == MOVETYPE_VPHYSICS && pOther->VPhysicsGetObject()->IsMoveable() ) - return true; - - return false; -} - - -bool CFuncVPhysicsClip::ForceVPhysicsCollide( CBaseEntity *pEntity ) -{ - return EntityPassesFilter(pEntity); -} - -void CFuncVPhysicsClip::InputEnable( inputdata_t &inputdata ) -{ - VPhysicsGetObject()->EnableCollisions(true); - m_bDisabled = false; -} - -void CFuncVPhysicsClip::InputDisable( inputdata_t &inputdata ) -{ - VPhysicsGetObject()->EnableCollisions(false); - m_bDisabled = true; -} diff --git a/game/server/buttons.cpp b/game/server/buttons.cpp deleted file mode 100644 index 110079c86..000000000 --- a/game/server/buttons.cpp +++ /dev/null @@ -1,1587 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ==== -// -// Purpose: Implements buttons. -// -//============================================================================= - -#include "cbase.h" -#include "doors.h" -#include "ndebugoverlay.h" -#include "spark.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "tier1/strtools.h" -#include "buttons.h" -#include "eventqueue.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -void PlayLockSounds( CBaseEntity *pEdict, locksound_t *pls, int flocked, int fbutton ); -string_t MakeButtonSound( int sound ); // get string of button sound number - - -#define SF_BUTTON_DONTMOVE 1 -#define SF_ROTBUTTON_NOTSOLID 1 -#define SF_BUTTON_TOGGLE 32 // button stays pushed until reactivated -#define SF_BUTTON_TOUCH_ACTIVATES 256 // Button fires when touched. -#define SF_BUTTON_DAMAGE_ACTIVATES 512 // Button fires when damaged. -#define SF_BUTTON_USE_ACTIVATES 1024 // Button fires when used. -#define SF_BUTTON_LOCKED 2048 // Whether the button is initially locked. -#define SF_BUTTON_SPARK_IF_OFF 4096 // button sparks in OFF state -#define SF_BUTTON_JIGGLE_ON_USE_LOCKED 8192 // whether to jiggle if someone uses us when we're locked - -BEGIN_DATADESC( CBaseButton ) - - DEFINE_KEYFIELD( m_vecMoveDir, FIELD_VECTOR, "movedir" ), - DEFINE_FIELD( m_fStayPushed, FIELD_BOOLEAN ), - DEFINE_FIELD( m_fRotating, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_bLockedSound, FIELD_CHARACTER ), - DEFINE_FIELD( m_bLockedSentence, FIELD_CHARACTER ), - DEFINE_FIELD( m_bUnlockedSound, FIELD_CHARACTER ), - DEFINE_FIELD( m_bUnlockedSentence, FIELD_CHARACTER ), - DEFINE_FIELD( m_bLocked, FIELD_BOOLEAN ), - DEFINE_FIELD( m_sNoise, FIELD_SOUNDNAME ), - DEFINE_FIELD( m_flUseLockedTime, FIELD_TIME ), - DEFINE_FIELD( m_bSolidBsp, FIELD_BOOLEAN ), - - DEFINE_KEYFIELD( m_sounds, FIELD_INTEGER, "sounds" ), - -// DEFINE_FIELD( m_ls, FIELD_SOUNDNAME ), // This is restored in Precache() -// DEFINE_FIELD( m_nState, FIELD_INTEGER ), - - // Function Pointers - DEFINE_FUNCTION( ButtonTouch ), - DEFINE_FUNCTION( ButtonSpark ), - DEFINE_FUNCTION( TriggerAndWait ), - DEFINE_FUNCTION( ButtonReturn ), - DEFINE_FUNCTION( ButtonBackHome ), - DEFINE_FUNCTION( ButtonUse ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Lock", InputLock ), - DEFINE_INPUTFUNC( FIELD_VOID, "Unlock", InputUnlock ), - DEFINE_INPUTFUNC( FIELD_VOID, "Press", InputPress ), - DEFINE_INPUTFUNC( FIELD_VOID, "PressIn", InputPressIn ), - DEFINE_INPUTFUNC( FIELD_VOID, "PressOut", InputPressOut ), - - // Outputs - DEFINE_OUTPUT( m_OnDamaged, "OnDamaged" ), - DEFINE_OUTPUT( m_OnPressed, "OnPressed" ), - DEFINE_OUTPUT( m_OnUseLocked, "OnUseLocked" ), - DEFINE_OUTPUT( m_OnIn, "OnIn" ), - DEFINE_OUTPUT( m_OnOut, "OnOut" ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( func_button, CBaseButton ); - - - -void CBaseButton::Precache( void ) -{ - // get door button sounds, for doors which require buttons to open - if (m_bLockedSound) - { - m_ls.sLockedSound = MakeButtonSound( (int)m_bLockedSound ); - PrecacheScriptSound(m_ls.sLockedSound.ToCStr()); - } - - if (m_bUnlockedSound) - { - m_ls.sUnlockedSound = MakeButtonSound( (int)m_bUnlockedSound ); - PrecacheScriptSound(m_ls.sUnlockedSound.ToCStr()); - } - - // get sentence group names, for doors which are directly 'touched' to open - - switch (m_bLockedSentence) - { - case 1: m_ls.sLockedSentence = MAKE_STRING("NA"); break; // access denied - case 2: m_ls.sLockedSentence = MAKE_STRING("ND"); break; // security lockout - case 3: m_ls.sLockedSentence = MAKE_STRING("NF"); break; // blast door - case 4: m_ls.sLockedSentence = MAKE_STRING("NFIRE"); break; // fire door - case 5: m_ls.sLockedSentence = MAKE_STRING("NCHEM"); break; // chemical door - case 6: m_ls.sLockedSentence = MAKE_STRING("NRAD"); break; // radiation door - case 7: m_ls.sLockedSentence = MAKE_STRING("NCON"); break; // gen containment - case 8: m_ls.sLockedSentence = MAKE_STRING("NH"); break; // maintenance door - case 9: m_ls.sLockedSentence = MAKE_STRING("NG"); break; // broken door - - default: m_ls.sLockedSentence = NULL_STRING; break; - } - - switch (m_bUnlockedSentence) - { - case 1: m_ls.sUnlockedSentence = MAKE_STRING("EA"); break; // access granted - case 2: m_ls.sUnlockedSentence = MAKE_STRING("ED"); break; // security door - case 3: m_ls.sUnlockedSentence = MAKE_STRING("EF"); break; // blast door - case 4: m_ls.sUnlockedSentence = MAKE_STRING("EFIRE"); break; // fire door - case 5: m_ls.sUnlockedSentence = MAKE_STRING("ECHEM"); break; // chemical door - case 6: m_ls.sUnlockedSentence = MAKE_STRING("ERAD"); break; // radiation door - case 7: m_ls.sUnlockedSentence = MAKE_STRING("ECON"); break; // gen containment - case 8: m_ls.sUnlockedSentence = MAKE_STRING("EH"); break; // maintenance door - - default: m_ls.sUnlockedSentence = NULL_STRING; break; - } - - if ( m_sNoise != NULL_STRING ) - { - PrecacheScriptSound( STRING( m_sNoise ) ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Cache user-entity-field values until spawn is called. -// Input : szKeyName - -// szValue - -// Output : Returns true if handled, false if not. -//----------------------------------------------------------------------------- -bool CBaseButton::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "locked_sound")) - { - m_bLockedSound = atoi(szValue); - } - else if (FStrEq(szKeyName, "locked_sentence")) - { - m_bLockedSentence = atoi(szValue); - } - else if (FStrEq(szKeyName, "unlocked_sound")) - { - m_bUnlockedSound = atoi(szValue); - } - else if (FStrEq(szKeyName, "unlocked_sentence")) - { - m_bUnlockedSentence = atoi(szValue); - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Locks the button. If locked, the button will play the locked sound -// when the player tries to use it. -//----------------------------------------------------------------------------- -void CBaseButton::Lock() -{ - m_bLocked = true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Unlocks the button, making it able to be pressed again. -//----------------------------------------------------------------------------- -void CBaseButton::Unlock() -{ - m_bLocked = false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Locks the button. If locked, the button will play the locked sound -// when the player tries to use it. -//----------------------------------------------------------------------------- -void CBaseButton::InputLock( inputdata_t &inputdata ) -{ - Lock(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Unlocks the button, making it able to be pressed again. -//----------------------------------------------------------------------------- -void CBaseButton::InputUnlock( inputdata_t &inputdata ) -{ - Unlock(); -} - - -//----------------------------------------------------------------------------- -// Presses or unpresses the button. -//----------------------------------------------------------------------------- -void CBaseButton::Press( CBaseEntity *pActivator, BUTTON_CODE eCode ) -{ - if ( ( eCode == BUTTON_PRESS ) && ( m_toggle_state == TS_GOING_UP || m_toggle_state == TS_GOING_DOWN ) ) - { - return; - } - - if ( ( eCode == BUTTON_ACTIVATE ) && ( m_toggle_state == TS_GOING_UP || m_toggle_state == TS_AT_TOP ) ) - { - return; - } - - if ( ( eCode == BUTTON_RETURN ) && ( m_toggle_state == TS_GOING_DOWN || m_toggle_state == TS_AT_BOTTOM ) ) - { - return; - } - - // FIXME: consolidate all the button press code into one place! - if (m_bLocked) - { - // play button locked sound - PlayLockSounds(this, &m_ls, TRUE, TRUE); - return; - } - - // Temporarily disable the touch function, until movement is finished. - SetTouch( NULL ); - - if ( ( eCode == BUTTON_PRESS ) && ( m_toggle_state == TS_AT_TOP ) || - ( ( eCode == BUTTON_RETURN ) && ( m_toggle_state == TS_AT_TOP || m_toggle_state == TS_GOING_UP ) ) ) - { - if ( m_sNoise != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_VOICE; - ep.m_pSoundName = (char*)STRING(m_sNoise); - ep.m_flVolume = 1; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - } - - m_OnPressed.FireOutput(pActivator, this); - ButtonReturn(); - } - else if ( ( eCode == BUTTON_PRESS ) || - ( ( eCode == BUTTON_ACTIVATE ) && ( m_toggle_state == TS_AT_BOTTOM || m_toggle_state == TS_GOING_DOWN ) ) ) - { - m_OnPressed.FireOutput(pActivator, this); - ButtonActivate(); - } -} - - -//----------------------------------------------------------------------------- -// Presses the button. -//----------------------------------------------------------------------------- -void CBaseButton::InputPress( inputdata_t &inputdata ) -{ - Press( inputdata.pActivator, BUTTON_PRESS ); -} - - -//----------------------------------------------------------------------------- -// Presses the button, sending it to the top/pressed position. -//----------------------------------------------------------------------------- -void CBaseButton::InputPressIn( inputdata_t &inputdata ) -{ - Press( inputdata.pActivator, BUTTON_ACTIVATE ); -} - - -//----------------------------------------------------------------------------- -// Unpresses the button, sending it to the unpressed/bottom position. -//----------------------------------------------------------------------------- -void CBaseButton::InputPressOut( inputdata_t &inputdata ) -{ - Press( inputdata.pActivator, BUTTON_RETURN ); -} - - -//----------------------------------------------------------------------------- -// Purpose: We have been damaged. Possibly activate, depending on our flags. -// Input : pInflictor - -// pAttacker - -// flDamage - -// bitsDamageType - -// Output : -//----------------------------------------------------------------------------- -int CBaseButton::OnTakeDamage( const CTakeDamageInfo &info ) -{ - m_OnDamaged.FireOutput(m_hActivator, this); - - // dvsents2: remove obselete health keyvalue from func_button - if (!HasSpawnFlags(SF_BUTTON_DAMAGE_ACTIVATES) && (m_iHealth == 0)) - { - return(0); - } - - BUTTON_CODE code = ButtonResponseToTouch(); - - if ( code == BUTTON_NOTHING ) - return 0; - - m_hActivator = info.GetAttacker(); - - // dvsents2: why would activator be NULL here? - if ( m_hActivator == NULL ) - return 0; - - if (m_bLocked) - { - return(0); - } - - // Temporarily disable the touch function, until movement is finished. - SetTouch( NULL ); - - if ( code == BUTTON_RETURN ) - { - if ( m_sNoise != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_VOICE; - ep.m_pSoundName = (char*)STRING(m_sNoise); - ep.m_flVolume = 1; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - } - - m_OnPressed.FireOutput(m_hActivator, this); - ButtonReturn(); - } - else - { - // code == BUTTON_ACTIVATE - m_OnPressed.FireOutput(m_hActivator, this); - ButtonActivate( ); - } - - return 0; -} - - -void CBaseButton::Spawn( ) -{ - //---------------------------------------------------- - //determine sounds for buttons - //a sound of 0 should not make a sound - //---------------------------------------------------- - if ( m_sounds ) - { - m_sNoise = MakeButtonSound( m_sounds ); - PrecacheScriptSound(m_sNoise.ToCStr()); - } - else - { - m_sNoise = NULL_STRING; - } - - Precache(); - - if ( HasSpawnFlags( SF_BUTTON_SPARK_IF_OFF ) )// this button should spark in OFF state - { - SetThink ( &CBaseButton::ButtonSpark ); - SetNextThink( gpGlobals->curtime + 0.5f );// no hurry, make sure everything else spawns - } - - // Convert movedir from angles to a vector - QAngle angMoveDir = QAngle( m_vecMoveDir.x, m_vecMoveDir.y, m_vecMoveDir.z ); - AngleVectors( angMoveDir, &m_vecMoveDir ); - - SetMoveType( MOVETYPE_PUSH ); - SetSolid( SOLID_BSP ); - SetModel( STRING( GetModelName() ) ); - - if (m_flSpeed == 0) - { - m_flSpeed = 40; - } - - m_takedamage = DAMAGE_YES; - - if (m_flWait == 0) - { - m_flWait = 1; - } - - if (m_flLip == 0) - { - m_flLip = 4; - } - - m_toggle_state = TS_AT_BOTTOM; - m_vecPosition1 = GetLocalOrigin(); - - // Subtract 2 from size because the engine expands bboxes by 1 in all directions making the size too big - Vector vecButtonOBB = CollisionProp()->OBBSize(); - vecButtonOBB -= Vector( 2, 2, 2 ); - m_vecPosition2 = m_vecPosition1 + (m_vecMoveDir * (DotProductAbs( m_vecMoveDir, vecButtonOBB ) - m_flLip)); - - // Is this a non-moving button? - if ( ((m_vecPosition2 - m_vecPosition1).Length() < 1) || HasSpawnFlags(SF_BUTTON_DONTMOVE) ) - { - m_vecPosition2 = m_vecPosition1; - } - - m_fStayPushed = (m_flWait == -1 ? TRUE : FALSE); - m_fRotating = FALSE; - - if (HasSpawnFlags(SF_BUTTON_LOCKED)) - { - m_bLocked = true; - } - - // - // If using activates the button, set its use function. - // - if (HasSpawnFlags(SF_BUTTON_USE_ACTIVATES)) - { - SetUse(&CBaseButton::ButtonUse); - } - else - { - SetUse(NULL); - } - - // - // If touching activates the button, set its touch function. - // - if (HasSpawnFlags(SF_BUTTON_TOUCH_ACTIVATES)) - { - SetTouch( &CBaseButton::ButtonTouch ); - } - else - { - SetTouch ( NULL ); - } - - CreateVPhysics(); -} - -//----------------------------------------------------------------------------- - -bool CBaseButton::CreateVPhysics() -{ - VPhysicsInitShadow( false, false ); - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Button sound table. -// Also used by CBaseDoor to get 'touched' door lock/unlock sounds -// Input : sound - index of sound to look up. -// Output : Returns a pointer to the corresponding sound file. -//----------------------------------------------------------------------------- -string_t MakeButtonSound( int sound ) -{ - char tmp[1024]; - Q_snprintf( tmp, sizeof(tmp), "Buttons.snd%d", sound ); - return AllocPooledString(tmp); -} - - -//----------------------------------------------------------------------------- -// Purpose: Think function that emits sparks at random intervals. -//----------------------------------------------------------------------------- -void CBaseButton::ButtonSpark ( void ) -{ - SetThink ( &CBaseButton::ButtonSpark ); - SetNextThink( gpGlobals->curtime + 0.1 + random->RandomFloat ( 0, 1.5 ) );// spark again at random interval - - DoSpark( this, WorldSpaceCenter(), 1, 1, true, vec3_origin ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Called when someone uses us whilst we are locked. -//----------------------------------------------------------------------------- -bool CBaseButton::OnUseLocked( CBaseEntity *pActivator ) -{ - PlayLockSounds(this, &m_ls, TRUE, TRUE); - - if ( gpGlobals->curtime > m_flUseLockedTime ) - { - m_OnUseLocked.FireOutput( pActivator, this ); - m_flUseLockedTime = gpGlobals->curtime + 0.5; - return true; - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Use function that starts the button moving. -// Input : pActivator - -// pCaller - -// useType - -// value - -//----------------------------------------------------------------------------- -void CBaseButton::ButtonUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - // Ignore touches if button is moving, or pushed-in and waiting to auto-come-out. - // UNDONE: Should this use ButtonResponseToTouch() too? - if (m_toggle_state == TS_GOING_UP || m_toggle_state == TS_GOING_DOWN ) - return; - - if (m_bLocked) - { - OnUseLocked( pActivator ); - return; - } - - m_hActivator = pActivator; - - if ( m_toggle_state == TS_AT_TOP) - { - // - // If it's a toggle button it can return now. Otherwise, it will either - // return on its own or will stay pressed indefinitely. - // - if ( HasSpawnFlags(SF_BUTTON_TOGGLE)) - { - if ( m_sNoise != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_VOICE; - ep.m_pSoundName = (char*)STRING(m_sNoise); - ep.m_flVolume = 1; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - } - - m_OnPressed.FireOutput(m_hActivator, this); - ButtonReturn(); - } - } - else - { - m_OnPressed.FireOutput(m_hActivator, this); - ButtonActivate( ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns a code indicating how the button should respond to being touched. -// Output : Returns one of the following: -// BUTTON_NOTHING - do nothing -// BUTTON_RETURN - -// BUTTON_ACTIVATE - act as if pressed -//----------------------------------------------------------------------------- -CBaseButton::BUTTON_CODE CBaseButton::ButtonResponseToTouch( void ) -{ - // Ignore touches if button is moving, or pushed-in and waiting to auto-come-out. - if (m_toggle_state == TS_GOING_UP || - m_toggle_state == TS_GOING_DOWN || - (m_toggle_state == TS_AT_TOP && !m_fStayPushed && !HasSpawnFlags(SF_BUTTON_TOGGLE) ) ) - return BUTTON_NOTHING; - - if (m_toggle_state == TS_AT_TOP) - { - if ( HasSpawnFlags(SF_BUTTON_TOGGLE) && !m_fStayPushed) - { - return BUTTON_RETURN; - } - } - else - return BUTTON_ACTIVATE; - - return BUTTON_NOTHING; -} - - -//----------------------------------------------------------------------------- -// Purpose: Touch function that activates the button if it responds to touch. -// Input : pOther - The entity that touched us. -//----------------------------------------------------------------------------- -void CBaseButton::ButtonTouch( CBaseEntity *pOther ) -{ - // Ignore touches by anything but players - if ( !pOther->IsPlayer() ) - return; - - m_hActivator = pOther; - - BUTTON_CODE code = ButtonResponseToTouch(); - - if ( code == BUTTON_NOTHING ) - return; - - if (!UTIL_IsMasterTriggered(m_sMaster, pOther) || m_bLocked) - { - // play button locked sound - PlayLockSounds(this, &m_ls, TRUE, TRUE); - return; - } - - // Temporarily disable the touch function, until movement is finished. - SetTouch( NULL ); - - if ( code == BUTTON_RETURN ) - { - if ( m_sNoise != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_VOICE; - ep.m_pSoundName = (char*)STRING(m_sNoise); - ep.m_flVolume = 1; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - } - - m_OnPressed.FireOutput(m_hActivator, this); - ButtonReturn(); - } - else - { - // code == BUTTON_ACTIVATE - m_OnPressed.FireOutput(m_hActivator, this); - ButtonActivate( ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Starts the button moving "in/up". -// Input : *pOther - -//----------------------------------------------------------------------------- -void CBaseButton::ButtonActivate( void ) -{ - if ( m_sNoise != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_VOICE; - ep.m_pSoundName = (char*)STRING(m_sNoise); - ep.m_flVolume = 1; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - } - - if (!UTIL_IsMasterTriggered(m_sMaster, m_hActivator) || m_bLocked) - { - // button is locked, play locked sound - PlayLockSounds(this, &m_ls, TRUE, TRUE); - return; - } - else - { - // button is unlocked, play unlocked sound - PlayLockSounds(this, &m_ls, FALSE, TRUE); - } - - ASSERT(m_toggle_state == TS_AT_BOTTOM); - m_toggle_state = TS_GOING_UP; - - SetMoveDone( &CBaseButton::TriggerAndWait ); - if (!m_fRotating) - LinearMove( m_vecPosition2, m_flSpeed); - else - AngularMove( m_vecAngle2, m_flSpeed); -} - - -//----------------------------------------------------------------------------- -// Purpose: Enables or disables the use capability based on our spawnflags. -//----------------------------------------------------------------------------- -int CBaseButton::ObjectCaps(void) -{ - return((BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | - (HasSpawnFlags(SF_BUTTON_USE_ACTIVATES) ? (FCAP_IMPULSE_USE | FCAP_USE_IN_RADIUS) : 0)); -} - - -//----------------------------------------------------------------------------- -// Purpose: Button has reached the "pressed/top" position. Fire its OnIn output, -// and pause before returning to "unpressed/bottom". -//----------------------------------------------------------------------------- -void CBaseButton::TriggerAndWait( void ) -{ - ASSERT(m_toggle_state == TS_GOING_UP); - - if (!UTIL_IsMasterTriggered(m_sMaster, m_hActivator) || m_bLocked) - { - return; - } - - m_toggle_state = TS_AT_TOP; - - // - // Re-instate touches if the button is of the toggle variety. - // - if (m_fStayPushed || HasSpawnFlags(SF_BUTTON_TOGGLE ) ) - { - if (HasSpawnFlags(SF_BUTTON_TOUCH_ACTIVATES)) - { - SetTouch(&CBaseButton::ButtonTouch); - } - else - { - // BUGBUG: ALL buttons no longer respond to touch - SetTouch (NULL); - } - } - - // - // If button automatically comes back out, start it moving out. - // - else - { - SetNextThink( gpGlobals->curtime + m_flWait ); - SetThink( &CBaseButton::ButtonReturn ); - } - - m_nState = 1; // use alternate textures - - m_OnIn.FireOutput(m_hActivator, this); -} - - -//----------------------------------------------------------------------------- -// Purpose: Starts the button moving "out/down". -//----------------------------------------------------------------------------- -void CBaseButton::ButtonReturn( void ) -{ - ASSERT(m_toggle_state == TS_AT_TOP); - m_toggle_state = TS_GOING_DOWN; - - SetMoveDone( &CBaseButton::ButtonBackHome ); - if (!m_fRotating) - LinearMove( m_vecPosition1, m_flSpeed); - else - AngularMove( m_vecAngle1, m_flSpeed); - - m_nState = 0; // use normal textures -} - - -//----------------------------------------------------------------------------- -// Purpose: Button has returned to the "unpressed/bottom" position. Fire its -// OnOut output and stop moving. -//----------------------------------------------------------------------------- -void CBaseButton::ButtonBackHome( void ) -{ - ASSERT(m_toggle_state == TS_GOING_DOWN); - m_toggle_state = TS_AT_BOTTOM; - - m_OnOut.FireOutput(m_hActivator, this); - - // - // Re-instate touch method, movement cycle is complete. - // - if (HasSpawnFlags(SF_BUTTON_TOUCH_ACTIVATES)) - { - SetTouch( &CBaseButton::ButtonTouch ); - } - else - { - // BUGBUG: ALL buttons no longer respond to touch - SetTouch ( NULL ); - } - - // reset think for a sparking button - if (HasSpawnFlags( SF_BUTTON_SPARK_IF_OFF ) ) - { - SetThink ( &CBaseButton::ButtonSpark ); - SetNextThink( gpGlobals->curtime + 0.5f );// no hurry - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CBaseButton::DrawDebugTextOverlays() -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - static const char *pszStates[] = - { - "Pressed", - "Unpressed", - "Pressing...", - "Unpressing...", - "", - }; - - char tempstr[255]; - - int nState = m_toggle_state; - if ( ( nState < 0 ) || ( nState > 3 ) ) - { - nState = 4; - } - - Q_snprintf( tempstr, sizeof(tempstr), "State: %s", pszStates[nState] ); - EntityText( text_offset, tempstr, 0 ); - text_offset++; - - Q_snprintf( tempstr, sizeof(tempstr), "%s", m_bLocked ? "Locked" : "Unlocked" ); - EntityText( text_offset, tempstr, 0 ); - text_offset++; - } - return text_offset; -} - - -// -// Rotating button (aka "lever") -// -LINK_ENTITY_TO_CLASS( func_rot_button, CRotButton ); - - -void CRotButton::Spawn( void ) -{ - //---------------------------------------------------- - //determine sounds for buttons - //a sound of 0 should not make a sound - //---------------------------------------------------- - if ( m_sounds ) - { - m_sNoise = MakeButtonSound( m_sounds ); - PrecacheScriptSound(m_sNoise.ToCStr()); - } - else - { - m_sNoise = NULL_STRING; - } - - // set the axis of rotation - CBaseToggle::AxisDir(); - - // check for clockwise rotation - if ( HasSpawnFlags( SF_DOOR_ROTATE_BACKWARDS) ) - { - m_vecMoveAng = m_vecMoveAng * -1; - } - - SetMoveType( MOVETYPE_PUSH ); - -#ifdef HL1_DLL - SetSolid( SOLID_BSP ); -#else - SetSolid( SOLID_VPHYSICS ); -#endif - if ( HasSpawnFlags( SF_ROTBUTTON_NOTSOLID ) ) - { - AddEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID ); - AddSolidFlags( FSOLID_NOT_SOLID ); - } - - SetModel( STRING( GetModelName() ) ); - - if (m_flSpeed == 0) - m_flSpeed = 40; - - if (m_flWait == 0) - m_flWait = 1; - - if (m_iHealth > 0) - { - m_takedamage = DAMAGE_YES; - } - - m_toggle_state = TS_AT_BOTTOM; - m_vecAngle1 = GetLocalAngles(); - m_vecAngle2 = GetLocalAngles() + m_vecMoveAng * m_flMoveDistance; - ASSERTSZ(m_vecAngle1 != m_vecAngle2, "rotating button start/end positions are equal\n"); - - m_fStayPushed = (m_flWait == -1 ? TRUE : FALSE); - m_fRotating = TRUE; - - SetUse(&CRotButton::ButtonUse); - - // - // If touching activates the button, set its touch function. - // - if (!HasSpawnFlags(SF_BUTTON_TOUCH_ACTIVATES)) - { - SetTouch ( NULL ); - } - else - { - SetTouch( &CRotButton::ButtonTouch ); - } - - CreateVPhysics(); -} - - -bool CRotButton::CreateVPhysics( void ) -{ - VPhysicsInitShadow( false, false ); - return true; -} - - -//----------------------------------------------------------------------------- -// CMomentaryRotButton spawnflags -//----------------------------------------------------------------------------- -#define SF_MOMENTARY_DOOR 1 -#define SF_MOMENTARY_NOT_USABLE 2 -#define SF_MOMENTARY_AUTO_RETURN 16 - - -BEGIN_DATADESC( CMomentaryRotButton ) - - DEFINE_FIELD( m_lastUsed, FIELD_INTEGER ), - DEFINE_FIELD( m_start, FIELD_VECTOR ), - DEFINE_FIELD( m_end, FIELD_VECTOR ), - DEFINE_FIELD( m_IdealYaw, FIELD_FLOAT ), - DEFINE_FIELD( m_sNoise, FIELD_SOUNDNAME ), - DEFINE_FIELD( m_bUpdateTarget, FIELD_BOOLEAN ), - - DEFINE_KEYFIELD( m_direction, FIELD_INTEGER, "StartDirection" ), - DEFINE_KEYFIELD( m_returnSpeed, FIELD_FLOAT, "returnspeed" ), - DEFINE_KEYFIELD( m_flStartPosition, FIELD_FLOAT, "StartPosition"), - DEFINE_KEYFIELD( m_bSolidBsp, FIELD_BOOLEAN, "solidbsp" ), - - // Function Pointers - DEFINE_FUNCTION( UseMoveDone ), - DEFINE_FUNCTION( ReturnMoveDone ), - DEFINE_FUNCTION( SetPositionMoveDone ), - DEFINE_FUNCTION( UpdateThink ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetPosition", InputSetPosition ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetPositionImmediately", InputSetPositionImmediately ), - DEFINE_INPUTFUNC( FIELD_VOID, "_DisableUpdateTarget", InputDisableUpdateTarget ), - DEFINE_INPUTFUNC( FIELD_VOID, "_EnableUpdateTarget", InputEnableUpdateTarget ), - - // Outputs - DEFINE_OUTPUT( m_Position, "Position" ), - DEFINE_OUTPUT( m_OnUnpressed, "OnUnpressed" ), - DEFINE_OUTPUT( m_OnFullyClosed, "OnFullyClosed" ), - DEFINE_OUTPUT( m_OnFullyOpen, "OnFullyOpen" ), - DEFINE_OUTPUT( m_OnReachedPosition, "OnReachedPosition" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - DEFINE_FIELD( m_bDisabled, FIELD_BOOLEAN ) - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( momentary_rot_button, CMomentaryRotButton ); - - -//----------------------------------------------------------------------------- -// Purpose: Called when spawning, after keyvalues have been handled. -//----------------------------------------------------------------------------- -void CMomentaryRotButton::Spawn( void ) -{ - CBaseToggle::AxisDir(); - - m_bUpdateTarget = true; - - if ( m_flSpeed == 0 ) - { - m_flSpeed = 100; - } - - // Clamp start position and issue bounds warning - if (m_flStartPosition < 0.0 || m_flStartPosition > 1.0) - { - Warning("WARNING: Momentary door (%s) start position not between 0 and 1. Clamping.\n",GetDebugName()); - m_flStartPosition = clamp(m_IdealYaw, 0, 1); - } - - // Check direction fields (for backward compatibility) - if (m_direction != 1 && m_direction != -1) - { - m_direction = 1; - } - - if (m_flMoveDistance < 0) - { - m_vecMoveAng = m_vecMoveAng * -1; - m_flMoveDistance = -m_flMoveDistance; - } - - m_start = GetLocalAngles() - m_vecMoveAng * m_flMoveDistance * m_flStartPosition; - m_end = GetLocalAngles() + m_vecMoveAng * m_flMoveDistance * (1-m_flStartPosition); - - m_IdealYaw = m_flStartPosition; - - // Force start direction at end points - if (m_flStartPosition == 0.0) - { - m_direction = -1; - } - else if (m_flStartPosition == 1.0) - { - m_direction = 1; - } - - if (HasSpawnFlags(SF_BUTTON_LOCKED)) - { - m_bLocked = true; - } - - if ( HasSpawnFlags( SF_BUTTON_USE_ACTIVATES ) ) - { - if ( m_sounds ) - { - m_sNoise = MakeButtonSound( m_sounds ); - PrecacheScriptSound(m_sNoise.ToCStr()); - } - else - { - m_sNoise = NULL_STRING; - } - - m_lastUsed = 0; - UpdateTarget(0,this); - } - -#ifdef HL1_DLL - SetSolid( SOLID_BSP ); -#else - SetSolid( SOLID_VPHYSICS ); -#endif - if (HasSpawnFlags(SF_ROTBUTTON_NOTSOLID)) - { - AddEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID ); - AddSolidFlags( FSOLID_NOT_SOLID ); - } - - SetMoveType( MOVETYPE_PUSH ); - SetModel( STRING( GetModelName() ) ); - - CreateVPhysics(); - - // Slam the object back to solid - if we really want it to be solid. - if ( m_bSolidBsp ) - { - SetSolid( SOLID_BSP ); - } - - m_bDisabled = false; -} - -int CMomentaryRotButton::ObjectCaps( void ) -{ - int flags = BaseClass::ObjectCaps(); - if (!HasSpawnFlags(SF_BUTTON_USE_ACTIVATES)) - { - return flags; - } - else - { - return (flags | FCAP_CONTINUOUS_USE | FCAP_USE_IN_RADIUS); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CMomentaryRotButton::CreateVPhysics( void ) -{ - VPhysicsInitShadow( false, false ); - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMomentaryRotButton::PlaySound( void ) -{ - if ( m_sNoise == NULL_STRING ) - return; - - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_VOICE; - ep.m_pSoundName = (char*)STRING(m_sNoise); - ep.m_flVolume = 1; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns a given angular position as a value along our motion from 0 to 1. -// Input : vecAngles - -//----------------------------------------------------------------------------- -float CMomentaryRotButton::GetPos( const QAngle &vecAngles ) -{ - float flScale = 1; - if (( m_vecMoveAng[0] < 0 ) || ( m_vecMoveAng[1] < 0 ) || ( m_vecMoveAng[2] < 0 )) - { - flScale = -1; - } - - float flPos = flScale * CBaseToggle::AxisDelta( m_spawnflags, vecAngles, m_start ) / m_flMoveDistance; - return( clamp( flPos, 0, 1 )); -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : flPosition -//------------------------------------------------------------------------------ -void CMomentaryRotButton::InputSetPosition( inputdata_t &inputdata ) -{ - m_IdealYaw = clamp( inputdata.value.Float(), 0, 1 ); - - float flCurPos = GetPos( GetLocalAngles() ); - if ( flCurPos < m_IdealYaw ) - { - // Moving forward (from start to end). - SetLocalAngularVelocity( m_flSpeed * m_vecMoveAng ); - m_direction = 1; - } - else if ( flCurPos > m_IdealYaw ) - { - // Moving backward (from end to start). - SetLocalAngularVelocity( -m_flSpeed * m_vecMoveAng ); - m_direction = -1; - } - else - { - // We're there already; nothing to do. - SetLocalAngularVelocity( vec3_angle ); - return; - } - - SetMoveDone( &CMomentaryRotButton::SetPositionMoveDone ); - - SetThink( &CMomentaryRotButton::UpdateThink ); - SetNextThink( gpGlobals->curtime ); - - // - // Think again in 0.1 seconds or the time that it will take us to reach our movement goal, - // whichever is the shorter interval. This prevents us from overshooting and stuttering when we - // are told to change position in very small increments. - // - QAngle vecNewAngles = m_start + m_vecMoveAng * ( m_IdealYaw * m_flMoveDistance ); - float flAngleDelta = fabs( AxisDelta( m_spawnflags, vecNewAngles, GetLocalAngles() )); - float dt = flAngleDelta / m_flSpeed; - if ( dt < TICK_INTERVAL ) - { - dt = TICK_INTERVAL; - float speed = flAngleDelta / TICK_INTERVAL; - SetLocalAngularVelocity( speed * m_vecMoveAng * m_direction ); - } - dt = clamp( dt, TICK_INTERVAL, TICK_INTERVAL * 6); - - SetMoveDoneTime( dt ); -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : flPosition -//------------------------------------------------------------------------------ -void CMomentaryRotButton::InputSetPositionImmediately( inputdata_t &inputdata ) -{ - m_IdealYaw = clamp( inputdata.value.Float(), 0, 1 ); - SetLocalAngles( m_start + m_vecMoveAng * ( m_IdealYaw * m_flMoveDistance ) ); -} - - -//------------------------------------------------------------------------------ -// Purpose: Turns off target updates so that we can change the wheel's position -// without changing the target's position. Used for jiggling when locked. -//------------------------------------------------------------------------------ -void CMomentaryRotButton::InputDisableUpdateTarget( inputdata_t &inputdata ) -{ - m_bUpdateTarget = false; -} - - -//------------------------------------------------------------------------------ -// Purpose: Turns target updates back on (after jiggling). -//------------------------------------------------------------------------------ -void CMomentaryRotButton::InputEnableUpdateTarget( inputdata_t &inputdata ) -{ - m_bUpdateTarget = true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Locks the button. If locked, the button will play the locked sound -// when the player tries to use it. -//----------------------------------------------------------------------------- -void CMomentaryRotButton::Lock() -{ - BaseClass::Lock(); - - SetLocalAngularVelocity( vec3_angle ); - SetMoveDoneTime( -1 ); - SetMoveDone( NULL ); - - SetNextThink( TICK_NEVER_THINK ); - SetThink( NULL ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Unlocks the button, making it able to be pressed again. -//----------------------------------------------------------------------------- -void CMomentaryRotButton::Unlock() -{ - BaseClass::Unlock(); - - SetMoveDone( &CMomentaryRotButton::ReturnMoveDone ); - - // Delay before autoreturn. - SetMoveDoneTime( 0.1f ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Fires the appropriate outputs at the extremes of motion. -//----------------------------------------------------------------------------- -void CMomentaryRotButton::OutputMovementComplete( void ) -{ - if (m_IdealYaw == 1.0) - { - m_OnFullyClosed.FireOutput(this, this); - } - else if (m_IdealYaw == 0.0) - { - m_OnFullyOpen.FireOutput(this, this); - } - - m_OnReachedPosition.FireOutput( this, this ); -} - - -//------------------------------------------------------------------------------ -// Purpose: MoveDone function for the SetPosition input handler. Tracks our -// progress toward a movement goal and updates our outputs. -//------------------------------------------------------------------------------ -void CMomentaryRotButton::SetPositionMoveDone(void) -{ - float flCurPos = GetPos( GetLocalAngles() ); - - if ((( flCurPos >= m_IdealYaw ) && ( m_direction == 1 )) || - (( flCurPos <= m_IdealYaw ) && ( m_direction == -1 ))) - { - // - // We reached or surpassed our movement goal. - // - SetLocalAngularVelocity( vec3_angle ); - // BUGBUG: Won't this get the player stuck? - SetLocalAngles( m_start + m_vecMoveAng * ( m_IdealYaw * m_flMoveDistance ) ); - SetNextThink( TICK_NEVER_THINK ); - SetMoveDoneTime( -1 ); - UpdateTarget( m_IdealYaw, this ); - OutputMovementComplete(); - return; - } - - // TODO: change this to use a Think function like ReturnThink. - QAngle vecNewAngles = m_start + m_vecMoveAng * ( m_IdealYaw * m_flMoveDistance ); - float flAngleDelta = fabs( AxisDelta( m_spawnflags, vecNewAngles, GetLocalAngles() )); - float dt = flAngleDelta / m_flSpeed; - if ( dt < TICK_INTERVAL ) - { - dt = TICK_INTERVAL; - float speed = flAngleDelta / TICK_INTERVAL; - SetLocalAngularVelocity( speed * m_vecMoveAng * m_direction ); - } - dt = clamp( dt, TICK_INTERVAL, TICK_INTERVAL * 6); - - SetMoveDoneTime( dt ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pActivator - -// pCaller - -// useType - -// value - -//----------------------------------------------------------------------------- -void CMomentaryRotButton::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - if ( m_bDisabled == true ) - return; - - if (m_bLocked) - { - if ( OnUseLocked( pActivator ) && HasSpawnFlags( SF_BUTTON_JIGGLE_ON_USE_LOCKED ) ) - { - // Jiggle two degrees. - float flDist = 2.0 / m_flMoveDistance; - - // Must be first! - g_EventQueue.AddEvent( this, "_DisableUpdateTarget", 0, this, this ); - - variant_t value; - value.SetFloat( flDist ); - g_EventQueue.AddEvent( this, "SetPosition", value, 0.01, this, this ); - - value.SetFloat( 0.0 ); - g_EventQueue.AddEvent( this, "SetPosition", value, 0.1, this, this ); - - value.SetFloat( 0.5 * flDist ); - g_EventQueue.AddEvent( this, "SetPosition", value, 0.2, this, this ); - - value.SetFloat( 0.0 ); - g_EventQueue.AddEvent( this, "SetPosition", value, 0.3, this, this ); - - // Must be last! And must be late enough to cover the settling time. - g_EventQueue.AddEvent( this, "_EnableUpdateTarget", 0.5, this, this ); - } - - return; - } - - // - // Reverse our direction and play movement sound every time the player - // pauses between uses. - // - bool bPlaySound = false; - - if ( !m_lastUsed ) - { - bPlaySound = true; - m_direction = -m_direction; - - //Alert that we've been pressed - m_OnPressed.FireOutput( m_hActivator, this ); - } - - m_lastUsed = 1; - - float flPos = GetPos( GetLocalAngles() ); - UpdateSelf( flPos, bPlaySound ); - - // - // Think every frame while we are moving. - // HACK: Don't reset the think time if we already have a pending think. - // This works around an issue with host_thread_mode > 0 when the player's - // clock runs ahead of the server. - // - if ( !m_pfnThink ) - { - SetThink( &CMomentaryRotButton::UpdateThink ); - SetNextThink( gpGlobals->curtime ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Handles changing direction at the extremes of our range of motion -// and updating our avelocity while being used by the player. -// Input : value - Number from 0 to 1 indicating our desired position within -// our range of motion, 0 = start, 1 = end. -//----------------------------------------------------------------------------- -void CMomentaryRotButton::UpdateSelf( float value, bool bPlaySound ) -{ - // - // Set our move clock to 0.1 seconds in the future so we stop spinning unless we are - // used again before then. - // - SetMoveDoneTime( 0.1 ); - - // - // If we hit the end, zero our avelocity and snap to the end angles. - // - if ( m_direction > 0 && value >= 1.0 ) - { - SetLocalAngularVelocity( vec3_angle ); - SetLocalAngles( m_end ); - - m_OnFullyClosed.FireOutput(this, this); - return; - } - // - // If we returned to the start, zero our avelocity and snap to the start angles. - // - else if ( m_direction < 0 && value <= 0 ) - { - SetLocalAngularVelocity( vec3_angle ); - SetLocalAngles( m_start ); - - m_OnFullyOpen.FireOutput(this, this); - return; - } - - if ( bPlaySound ) - { - PlaySound(); - } - - SetLocalAngularVelocity( ( m_direction * m_flSpeed ) * m_vecMoveAng ); - SetMoveDone( &CMomentaryRotButton::UseMoveDone ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Updates the value of our position, firing any targets. -// Input : value - New position, from 0 - 1. -//----------------------------------------------------------------------------- -void CMomentaryRotButton::UpdateTarget( float value, CBaseEntity *pActivator ) -{ - if ( !m_bUpdateTarget ) - return; - - if (m_Position.Get() != value) - { - m_Position.Set(value, pActivator, this); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Handles the end of motion caused by player use. -//----------------------------------------------------------------------------- -void CMomentaryRotButton::UseMoveDone( void ) -{ - SetLocalAngularVelocity( vec3_angle ); - - // Make sure our targets stop where we stopped. - float flPos = GetPos( GetLocalAngles() ); - UpdateTarget( flPos, this ); - - // Alert that we've been unpressed - m_OnUnpressed.FireOutput( m_hActivator, this ); - - m_lastUsed = 0; - - if ( !HasSpawnFlags( SF_BUTTON_TOGGLE ) && m_returnSpeed > 0 ) - { - SetMoveDone( &CMomentaryRotButton::ReturnMoveDone ); - m_direction = -1; - - // Delay before autoreturn. - SetMoveDoneTime( 0.1f ); - } - else - { - SetThink( NULL ); - SetMoveDone( NULL ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: MoveDone function for rotating back to the start position. -//----------------------------------------------------------------------------- -void CMomentaryRotButton::ReturnMoveDone( void ) -{ - float value = GetPos( GetLocalAngles() ); - if ( value <= 0 ) - { - // - // Got back to the start, stop spinning. - // - SetLocalAngularVelocity( vec3_angle ); - SetLocalAngles( m_start ); - - UpdateTarget( 0, NULL ); - - SetMoveDoneTime( -1 ); - SetMoveDone( NULL ); - - SetNextThink( TICK_NEVER_THINK ); - SetThink( NULL ); - } - else - { - SetLocalAngularVelocity( -m_returnSpeed * m_vecMoveAng ); - SetMoveDoneTime( 0.1f ); - - SetThink( &CMomentaryRotButton::UpdateThink ); - SetNextThink( gpGlobals->curtime + 0.01f ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Think function for updating target as we move. -//----------------------------------------------------------------------------- -void CMomentaryRotButton::UpdateThink( void ) -{ - float value = GetPos( GetLocalAngles() ); - UpdateTarget( value, NULL ); - SetNextThink( gpGlobals->curtime ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CMomentaryRotButton::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[255]; - - Q_snprintf(tempstr,sizeof(tempstr),"QAngle: %.2f %.2f %.2f", GetLocalAngles()[0], GetLocalAngles()[1], GetLocalAngles()[2]); - EntityText(text_offset,tempstr,0); - text_offset++; - - Q_snprintf(tempstr,sizeof(tempstr),"AVelocity: %.2f %.2f %.2f", GetLocalAngularVelocity()[0], GetLocalAngularVelocity()[1], GetLocalAngularVelocity()[2]); - EntityText(text_offset,tempstr,0); - text_offset++; - - Q_snprintf(tempstr,sizeof(tempstr),"Target Pos: %3.3f",m_IdealYaw); - EntityText(text_offset,tempstr,0); - text_offset++; - - float flCurPos = GetPos(GetLocalAngles()); - Q_snprintf(tempstr,sizeof(tempstr),"Current Pos: %3.3f",flCurPos); - EntityText(text_offset,tempstr,0); - text_offset++; - - Q_snprintf(tempstr,sizeof(tempstr),"Direction: %s",(m_direction == 1) ? "Forward" : "Backward"); - EntityText(text_offset,tempstr,0); - text_offset++; - - } - return text_offset; -} - -//----------------------------------------------------------------------------- -// Purpose: Input hander that starts the spawner -//----------------------------------------------------------------------------- -void CMomentaryRotButton::InputEnable( inputdata_t &inputdata ) -{ - Enable(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input hander that stops the spawner -//----------------------------------------------------------------------------- -void CMomentaryRotButton::InputDisable( inputdata_t &inputdata ) -{ - Disable(); -} - -//----------------------------------------------------------------------------- -// Purpose: Start the spawner -//----------------------------------------------------------------------------- -void CMomentaryRotButton::Enable( void ) -{ - m_bDisabled = false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Stop the spawner -//----------------------------------------------------------------------------- -void CMomentaryRotButton::Disable( void ) -{ - m_bDisabled = true; -} diff --git a/game/server/buttons.h b/game/server/buttons.h deleted file mode 100644 index 7695216e6..000000000 --- a/game/server/buttons.h +++ /dev/null @@ -1,172 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ==== -// -// Purpose: -// -//============================================================================= - -#ifndef BUTTONS_H -#define BUTTONS_H -#ifdef _WIN32 -#pragma once -#endif - - -class CBaseButton : public CBaseToggle -{ -public: - - DECLARE_CLASS( CBaseButton, CBaseToggle ); - - void Spawn( void ); - virtual void Precache( void ); - bool CreateVPhysics(); - void RotSpawn( void ); - bool KeyValue( const char *szKeyName, const char *szValue ); - int DrawDebugTextOverlays(); - -protected: - - void ButtonActivate( ); - void SparkSoundCache( void ); - - void ButtonTouch( ::CBaseEntity *pOther ); - void ButtonSpark ( void ); - void TriggerAndWait( void ); - void ButtonReturn( void ); - void ButtonBackHome( void ); - void ButtonUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - bool OnUseLocked( CBaseEntity *pActivator ); - - virtual void Lock(); - virtual void Unlock(); - - // Input handlers - void InputLock( inputdata_t &inputdata ); - void InputUnlock( inputdata_t &inputdata ); - void InputPress( inputdata_t &inputdata ); - void InputPressIn( inputdata_t &inputdata ); - void InputPressOut( inputdata_t &inputdata ); - - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - - enum BUTTON_CODE { BUTTON_NOTHING, BUTTON_ACTIVATE, BUTTON_RETURN, BUTTON_PRESS }; - - BUTTON_CODE ButtonResponseToTouch( void ); - void Press( CBaseEntity *pActivator, BUTTON_CODE eCode ); - - DECLARE_DATADESC(); - - virtual int ObjectCaps(void); - - Vector m_vecMoveDir; - - bool m_fStayPushed; // button stays pushed in until touched again? - bool m_fRotating; // a rotating button? default is a sliding button. - - locksound_t m_ls; // door lock sounds - - byte m_bLockedSound; // ordinals from entity selection - byte m_bLockedSentence; - byte m_bUnlockedSound; - byte m_bUnlockedSentence; - bool m_bLocked; - int m_sounds; - float m_flUseLockedTime; // Controls how often we fire the OnUseLocked output. - - bool m_bSolidBsp; - - string_t m_sNoise; // The actual WAV file name of the sound. - - COutputEvent m_OnDamaged; - COutputEvent m_OnPressed; - COutputEvent m_OnUseLocked; - COutputEvent m_OnIn; - COutputEvent m_OnOut; - - int m_nState; -}; - - -// -// Rotating button (aka "lever") -// -class CRotButton : public CBaseButton -{ -public: - DECLARE_CLASS( CRotButton, CBaseButton ); - - void Spawn( void ); - bool CreateVPhysics( void ); - -}; - - -class CMomentaryRotButton : public CRotButton -{ - DECLARE_CLASS( CMomentaryRotButton, CRotButton ); - -public: - void Spawn ( void ); - bool CreateVPhysics( void ); - virtual int ObjectCaps( void ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - void UseMoveDone( void ); - void ReturnMoveDone( void ); - void OutputMovementComplete(void); - void SetPositionMoveDone(void); - void UpdateSelf( float value, bool bPlaySound ); - - void PlaySound( void ); - void UpdateTarget( float value, CBaseEntity *pActivator ); - - int DrawDebugTextOverlays(void); - - static CMomentaryRotButton *Instance( edict_t *pent ) { return (CMomentaryRotButton *)GetContainingEntity(pent); } - - float GetPos(const QAngle &vecAngles); - - DECLARE_DATADESC(); - - virtual void Lock(); - virtual void Unlock(); - - // Input handlers - void InputSetPosition( inputdata_t &inputdata ); - void InputSetPositionImmediately( inputdata_t &inputdata ); - void InputDisableUpdateTarget( inputdata_t &inputdata ); - void InputEnableUpdateTarget( inputdata_t &inputdata ); - - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - - virtual void Enable( void ); - virtual void Disable( void ); - - bool m_bDisabled; - - COutputFloat m_Position; - COutputEvent m_OnUnpressed; - COutputEvent m_OnFullyOpen; - COutputEvent m_OnFullyClosed; - COutputEvent m_OnReachedPosition; - - int m_lastUsed; - QAngle m_start; - QAngle m_end; - float m_IdealYaw; - string_t m_sNoise; - - bool m_bUpdateTarget; // Used when jiggling so that we don't jiggle the target (door, etc) - - int m_direction; - float m_returnSpeed; - float m_flStartPosition; - -protected: - - void UpdateThink( void ); -}; - - -#endif // BUTTONS_H diff --git a/game/server/cbase.cpp b/game/server/cbase.cpp deleted file mode 100644 index 2aa21c4b3..000000000 --- a/game/server/cbase.cpp +++ /dev/null @@ -1,1823 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -/* -Entity Data Descriptions - -Each entity has an array which defines it's data in way that is useful for -entity communication, parsing initial values from the map, and save/restore. - -each entity has to have the following line in it's class declaration: - - DECLARE_DATADESC(); - -this line defines that it has an m_DataDesc[] array, and declares functions through -which various subsystems can iterate the data. - -In it's implementation, each entity has to have: - - typedescription_t CBaseEntity::m_DataDesc[] = { ... } - -in which all it's data is defined (see below), followed by: - - -which implements the functions necessary for iterating through an entities data desc. - -There are several types of data: - - FIELD : this is a variable which gets saved & loaded from disk - KEY : this variable can be read in from the map file - GLOBAL : a global field is actually local; it is saved/restored, but is actually - unique to the entity on each level. - CUSTOM : the save/restore parsing functions are described by the user. - ARRAY : an array of values - OUTPUT : a variable or event that can be connected to other entities (see below) - INPUTFUNC : maps a string input to a function pointer. Outputs connected to this input - will call the notify function when fired. - INPUT : maps a string input to a member variable. Outputs connected to this input - will update the input data value when fired. - INPUTNOTIFY : maps a string input to a member variable/function pointer combo. Outputs - connected to this input will update the data value and call the notify - function when fired. - -some of these can overlap. all the data descriptions usable are: - - DEFINE_FIELD( name, fieldtype ) - DEFINE_KEYFIELD( name, fieldtype, mapname ) - DEFINE_KEYFIELD_NOTSAVED( name, fieldtype, mapname ) - DEFINE_ARRAY( name, fieldtype, count ) - DEFINE_GLOBAL_FIELD(name, fieldtype ) - DEFINE_CUSTOM_FIELD(name, datafuncs, mapname ) - DEFINE_GLOBAL_KEYFIELD(name, fieldtype, mapname ) - -where: - type is the name of the class (eg. CBaseEntity) - name is the name of the variable in the class (eg. m_iHealth) - fieldtype is the type of data (FIELD_STRING, FIELD_INTEGER, etc) - mapname is the string by which this variable is associated with map file data - count is the number of items in the array - datafuncs is a struct containing function pointers for a custom-defined save/restore/parse - -OUTPUTS: - - DEFINE_OUTPUT( outputvar, outputname ) - - This maps the string 'outputname' to the COutput-derived member variable outputvar. In the VMF - file these outputs can be hooked up to inputs (see above). Whenever the internal state - of an entity changes it will often fire off outputs so that map makers can hook up behaviors. - e.g. A door entity would have OnDoorOpen, OnDoorClose, OnTouched, etc outputs. -*/ - - -#include "cbase.h" -#include "entitylist.h" -#include "mapentities_shared.h" -#include "isaverestore.h" -#include "eventqueue.h" -#include "entityinput.h" -#include "entityoutput.h" -#include "mempool.h" -#include "tier1/strtools.h" -#include "datacache/imdlcache.h" -#include "env_debughistory.h" - -#include "tier0/vprof.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern ISaveRestoreOps *variantFuncs; // function pointer set for save/restoring variants - -BEGIN_SIMPLE_DATADESC( CEventAction ) - DEFINE_FIELD( m_iTarget, FIELD_STRING ), - DEFINE_FIELD( m_iTargetInput, FIELD_STRING ), - DEFINE_FIELD( m_iParameter, FIELD_STRING ), - DEFINE_FIELD( m_flDelay, FIELD_FLOAT ), - DEFINE_FIELD( m_nTimesToFire, FIELD_INTEGER ), - DEFINE_FIELD( m_iIDStamp, FIELD_INTEGER ), - - // This is dealt with by the Restore method - // DEFINE_FIELD( m_pNext, CEventAction ), -END_DATADESC() - - -// ID Stamp used to uniquely identify every output -int CEventAction::s_iNextIDStamp = 0; - - -//----------------------------------------------------------------------------- -// Purpose: Creates an event action and assigns it an unique ID stamp. -// Input : ActionData - the map file data block descibing the event action. -//----------------------------------------------------------------------------- -CEventAction::CEventAction( const char *ActionData ) -{ - m_pNext = NULL; - m_iIDStamp = ++s_iNextIDStamp; - - m_flDelay = 0; - m_iTarget = NULL_STRING; - m_iParameter = NULL_STRING; - m_iTargetInput = NULL_STRING; - m_nTimesToFire = EVENT_FIRE_ALWAYS; - - if (ActionData == NULL) - return; - - char szToken[256]; - - // - // Parse the target name. - // - const char *psz = nexttoken(szToken, ActionData, ','); - if (szToken[0] != '\0') - { - m_iTarget = AllocPooledString(szToken); - } - - // - // Parse the input name. - // - psz = nexttoken(szToken, psz, ','); - if (szToken[0] != '\0') - { - m_iTargetInput = AllocPooledString(szToken); - } - else - { - m_iTargetInput = AllocPooledString("Use"); - } - - // - // Parse the parameter override. - // - psz = nexttoken(szToken, psz, ','); - if (szToken[0] != '\0') - { - m_iParameter = AllocPooledString(szToken); - } - - // - // Parse the delay. - // - psz = nexttoken(szToken, psz, ','); - if (szToken[0] != '\0') - { - m_flDelay = atof(szToken); - } - - // - // Parse the number of times to fire. - // - nexttoken(szToken, psz, ','); - if (szToken[0] != '\0') - { - m_nTimesToFire = atoi(szToken); - if (m_nTimesToFire == 0) - { - m_nTimesToFire = EVENT_FIRE_ALWAYS; - } - } -} - - -// this memory pool stores blocks around the size of CEventAction/inputitem_t structs -// can be used for other blocks; will error if to big a block is tried to be allocated -CMemoryPool g_EntityListPool( MAX(sizeof(CEventAction),sizeof(CMultiInputVar::inputitem_t)), 512, CMemoryPool::GROW_FAST, "g_EntityListPool" ); - -#include "tier0/memdbgoff.h" - -void *CEventAction::operator new( size_t stAllocateBlock ) -{ - return g_EntityListPool.Alloc( stAllocateBlock ); -} - -void *CEventAction::operator new( size_t stAllocateBlock, int nBlockUse, const char *pFileName, int nLine ) -{ - return g_EntityListPool.Alloc( stAllocateBlock ); -} - -void CEventAction::operator delete( void *pMem ) -{ - g_EntityListPool.Free( pMem ); -} - -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Returns the highest-valued delay in our list of event actions. -//----------------------------------------------------------------------------- -float CBaseEntityOutput::GetMaxDelay(void) -{ - float flMaxDelay = 0; - CEventAction *ev = m_ActionList; - - while (ev != NULL) - { - if (ev->m_flDelay > flMaxDelay) - { - flMaxDelay = ev->m_flDelay; - } - ev = ev->m_pNext; - } - - return(flMaxDelay); -} - - -//----------------------------------------------------------------------------- -// Purpose: Destructor. -//----------------------------------------------------------------------------- -CBaseEntityOutput::~CBaseEntityOutput() -{ - CEventAction *ev = m_ActionList; - while (ev != NULL) - { - CEventAction *pNext = ev->m_pNext; - delete ev; - ev = pNext; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Fires the event, causing a sequence of action to occur in other ents. -// Input : pActivator - Entity that initiated this sequence of actions. -// pCaller - Entity that is actually causing the event. -//----------------------------------------------------------------------------- -void CBaseEntityOutput::FireOutput(variant_t Value, CBaseEntity *pActivator, CBaseEntity *pCaller, float fDelay) -{ - // - // Iterate through all eventactions and fire them off. - // - CEventAction *ev = m_ActionList; - CEventAction *prev = NULL; - - while (ev != NULL) - { - if (ev->m_iParameter == NULL_STRING) - { - // - // Post the event with the default parameter. - // - g_EventQueue.AddEvent( STRING(ev->m_iTarget), STRING(ev->m_iTargetInput), Value, ev->m_flDelay + fDelay, pActivator, pCaller, ev->m_iIDStamp ); - } - else - { - // - // Post the event with a parameter override. - // - variant_t ValueOverride; - ValueOverride.SetString( ev->m_iParameter ); - g_EventQueue.AddEvent( STRING(ev->m_iTarget), STRING(ev->m_iTargetInput), ValueOverride, ev->m_flDelay, pActivator, pCaller, ev->m_iIDStamp ); - } - - if ( ev->m_flDelay ) - { - char szBuffer[256]; - Q_snprintf( szBuffer, sizeof(szBuffer), "(%0.2f) output: (%s,%s) -> (%s,%s,%.1f)(%s)\n", gpGlobals->curtime, pCaller ? STRING(pCaller->m_iClassname) : "NULL", pCaller ? STRING(pCaller->GetEntityName()) : "NULL", STRING(ev->m_iTarget), STRING(ev->m_iTargetInput), ev->m_flDelay, STRING(ev->m_iParameter) ); - DevMsg( 2, szBuffer ); - ADD_DEBUG_HISTORY( HISTORY_ENTITY_IO, szBuffer ); - } - else - { - char szBuffer[256]; - Q_snprintf( szBuffer, sizeof(szBuffer), "(%0.2f) output: (%s,%s) -> (%s,%s)(%s)\n", gpGlobals->curtime, pCaller ? STRING(pCaller->m_iClassname) : "NULL", pCaller ? STRING(pCaller->GetEntityName()) : "NULL", STRING(ev->m_iTarget), STRING(ev->m_iTargetInput), STRING(ev->m_iParameter) ); - DevMsg( 2, szBuffer ); - ADD_DEBUG_HISTORY( HISTORY_ENTITY_IO, szBuffer ); - } - - if ( pCaller && pCaller->m_debugOverlays & OVERLAY_MESSAGE_BIT) - { - pCaller->DrawOutputOverlay(ev); - } - - // - // Remove the event action from the list if it was set to be fired a finite - // number of times (and has been). - // - bool bRemove = false; - if (ev->m_nTimesToFire != EVENT_FIRE_ALWAYS) - { - ev->m_nTimesToFire--; - if (ev->m_nTimesToFire == 0) - { - char szBuffer[256]; - Q_snprintf( szBuffer, sizeof(szBuffer), "Removing from action list: (%s,%s) -> (%s,%s)\n", pCaller ? STRING(pCaller->m_iClassname) : "NULL", pCaller ? STRING(pCaller->GetEntityName()) : "NULL", STRING(ev->m_iTarget), STRING(ev->m_iTargetInput)); - DevMsg( 2, szBuffer ); - ADD_DEBUG_HISTORY( HISTORY_ENTITY_IO, szBuffer ); - bRemove = true; - } - } - - if (!bRemove) - { - prev = ev; - ev = ev->m_pNext; - } - else - { - if (prev != NULL) - { - prev->m_pNext = ev->m_pNext; - } - else - { - m_ActionList = ev->m_pNext; - } - - CEventAction *next = ev->m_pNext; - delete ev; - ev = next; - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Parameterless firing of an event -// Input : pActivator - -// pCaller - -//----------------------------------------------------------------------------- -void COutputEvent::FireOutput(CBaseEntity *pActivator, CBaseEntity *pCaller, float fDelay) -{ - variant_t Val; - Val.Set( FIELD_VOID, NULL ); - CBaseEntityOutput::FireOutput(Val, pActivator, pCaller, fDelay); -} - - -void CBaseEntityOutput::ParseEventAction( const char *EventData ) -{ - AddEventAction( new CEventAction( EventData ) ); -} - -void CBaseEntityOutput::AddEventAction( CEventAction *pEventAction ) -{ - pEventAction->m_pNext = m_ActionList; - m_ActionList = pEventAction; -} - - -// save data description for the event queue -BEGIN_SIMPLE_DATADESC( CBaseEntityOutput ) - - DEFINE_CUSTOM_FIELD( m_Value, variantFuncs ), - - // This is saved manually by CBaseEntityOutput::Save - // DEFINE_FIELD( m_ActionList, CEventAction ), -END_DATADESC() - - -int CBaseEntityOutput::Save( ISave &save ) -{ - // save that value out to disk, so we know how many to restore - if ( !save.WriteFields( "Value", this, NULL, m_DataMap.dataDesc, m_DataMap.dataNumFields ) ) - return 0; - - for ( CEventAction *ev = m_ActionList; ev != NULL; ev = ev->m_pNext ) - { - if ( !save.WriteFields( "EntityOutput", ev, NULL, ev->m_DataMap.dataDesc, ev->m_DataMap.dataNumFields ) ) - return 0; - } - - return 1; -} - -int CBaseEntityOutput::Restore( IRestore &restore, int elementCount ) -{ - // load the number of items saved - if ( !restore.ReadFields( "Value", this, NULL, m_DataMap.dataDesc, m_DataMap.dataNumFields ) ) - return 0; - - m_ActionList = NULL; - - // read in all the fields - CEventAction *lastEv = NULL; - for ( int i = 0; i < elementCount; i++ ) - { - CEventAction *ev = new CEventAction(NULL); - - if ( !restore.ReadFields( "EntityOutput", ev, NULL, ev->m_DataMap.dataDesc, ev->m_DataMap.dataNumFields ) ) - return 0; - - // add it to the list in the same order it was saved in - if ( lastEv ) - { - lastEv->m_pNext = ev; - } - else - { - m_ActionList = ev; - } - ev->m_pNext = NULL; - lastEv = ev; - } - - return 1; -} - -int CBaseEntityOutput::NumberOfElements( void ) -{ - int count = 0; - for ( CEventAction *ev = m_ActionList; ev != NULL; ev = ev->m_pNext ) - { - count++; - } - return count; -} - -/// Delete every single action in the action list. -void CBaseEntityOutput::DeleteAllElements( void ) -{ - // walk front to back, deleting as we go. We needn't fix up pointers because - // EVERYTHING will die. - - CEventAction *pNext = m_ActionList; - // wipe out the head - m_ActionList = NULL; - while (pNext) - { - register CEventAction *strikeThis = pNext; - pNext = pNext->m_pNext; - delete strikeThis; - } - -} - -/// EVENTS save/restore parsing wrapper - -class CEventsSaveDataOps : public ISaveRestoreOps -{ - virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave ) - { - AssertMsg( fieldInfo.pTypeDesc->fieldSize == 1, "CEventsSaveDataOps does not support arrays"); - - CBaseEntityOutput *ev = (CBaseEntityOutput*)fieldInfo.pField; - const int fieldSize = fieldInfo.pTypeDesc->fieldSize; - for ( int i = 0; i < fieldSize; i++, ev++ ) - { - // save out the number of fields - int numElements = ev->NumberOfElements(); - pSave->WriteInt( &numElements, 1 ); - - // save the event data - ev->Save( *pSave ); - } - } - - virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore ) - { - AssertMsg( fieldInfo.pTypeDesc->fieldSize == 1, "CEventsSaveDataOps does not support arrays"); - - CBaseEntityOutput *ev = (CBaseEntityOutput*)fieldInfo.pField; - const int fieldSize = fieldInfo.pTypeDesc->fieldSize; - for ( int i = 0; i < fieldSize; i++, ev++ ) - { - int nElements = pRestore->ReadInt(); - - Assert( nElements < 100 ); - - ev->Restore( *pRestore, nElements ); - } - } - - virtual bool IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - AssertMsg( fieldInfo.pTypeDesc->fieldSize == 1, "CEventsSaveDataOps does not support arrays"); - - // check all the elements of the array (usually only 1) - CBaseEntityOutput *ev = (CBaseEntityOutput*)fieldInfo.pField; - const int fieldSize = fieldInfo.pTypeDesc->fieldSize; - for ( int i = 0; i < fieldSize; i++, ev++ ) - { - // It's not empty if it has events or if it has a non-void variant value - if (( ev->NumberOfElements() != 0 ) || ( ev->ValueFieldType() != FIELD_VOID )) - return 0; - } - - // variant has no data - return 1; - } - - virtual void MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - // Don't no how to. This is okay, since objects of this type - // are always born clean before restore, and not reused - } - - virtual bool Parse( const SaveRestoreFieldInfo_t &fieldInfo, char const* szValue ) - { - CBaseEntityOutput *ev = (CBaseEntityOutput*)fieldInfo.pField; - ev->ParseEventAction( szValue ); - return true; - } -}; - -CEventsSaveDataOps g_EventsSaveDataOps; -ISaveRestoreOps *eventFuncs = &g_EventsSaveDataOps; - -//----------------------------------------------------------------------------- -// CMultiInputVar implementation -// -// Purpose: holds a list of inputs and their ID tags -// used for entities that hold inputs from a set of other entities -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -// Purpose: destructor, frees the data list -//----------------------------------------------------------------------------- -CMultiInputVar::~CMultiInputVar() -{ - if ( m_InputList ) - { - while ( m_InputList->next != NULL ) - { - inputitem_t *input = m_InputList->next; - m_InputList->next = input->next; - delete input; - } - delete m_InputList; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Updates the data set with a new value -// Input : newVal - the new value to add to or update in the list -// outputID - the source of the value -//----------------------------------------------------------------------------- -void CMultiInputVar::AddValue( variant_t newVal, int outputID ) -{ - // see if it's already in the list - inputitem_t *inp; - for ( inp = m_InputList; inp != NULL; inp = inp->next ) - { - // already in list, so just update this link - if ( inp->outputID == outputID ) - { - inp->value = newVal; - return; - } - } - - // add to start of list - inp = new inputitem_t; - inp->value = newVal; - inp->outputID = outputID; - if ( !m_InputList ) - { - m_InputList = inp; - inp->next = NULL; - } - else - { - inp->next = m_InputList; - m_InputList = inp; - } -} - - -#include "tier0/memdbgoff.h" - -//----------------------------------------------------------------------------- -// Purpose: allocates memory from the entitylist pool -//----------------------------------------------------------------------------- -void *CMultiInputVar::inputitem_t::operator new( size_t stAllocateBlock ) -{ - return g_EntityListPool.Alloc( stAllocateBlock ); -} - -void *CMultiInputVar::inputitem_t::operator new( size_t stAllocateBlock, int nBlockUse, const char *pFileName, int nLine ) -{ - return g_EntityListPool.Alloc( stAllocateBlock ); -} - -//----------------------------------------------------------------------------- -// Purpose: frees memory from the entitylist pool -//----------------------------------------------------------------------------- -void CMultiInputVar::inputitem_t::operator delete( void *pMem ) -{ - g_EntityListPool.Free( pMem ); -} - -#include "tier0/memdbgon.h" - - -//----------------------------------------------------------------------------- -// CEventQueue implementation -// -// Purpose: holds and executes a global prioritized queue of entity actions -//----------------------------------------------------------------------------- -DEFINE_FIXEDSIZE_ALLOCATOR( EventQueuePrioritizedEvent_t, 128, CMemoryPool::GROW_SLOW ); - -CEventQueue g_EventQueue; - -CEventQueue::CEventQueue() -{ - m_Events.m_flFireTime = -FLT_MAX; - m_Events.m_pNext = NULL; - - Init(); -} - -CEventQueue::~CEventQueue() -{ - Clear(); -} - -// Robin: Left here for backwards compatability. -class CEventQueueSaveLoadProxy : public CLogicalEntity -{ - DECLARE_CLASS( CEventQueueSaveLoadProxy, CLogicalEntity ); - - int Save( ISave &save ) - { - if ( !BaseClass::Save(save) ) - return 0; - - // save out the message queue - return g_EventQueue.Save( save ); - } - - - int Restore( IRestore &restore ) - { - if ( !BaseClass::Restore(restore) ) - return 0; - - // restore the event queue - int iReturn = g_EventQueue.Restore( restore ); - - // Now remove myself, because the CEventQueue_SaveRestoreBlockHandler - // will handle future saves. - UTIL_Remove( this ); - - return iReturn; - } -}; - -LINK_ENTITY_TO_CLASS(event_queue_saveload_proxy, CEventQueueSaveLoadProxy); - -//----------------------------------------------------------------------------- -// EVENT QUEUE SAVE / RESTORE -//----------------------------------------------------------------------------- -static short EVENTQUEUE_SAVE_RESTORE_VERSION = 1; - -class CEventQueue_SaveRestoreBlockHandler : public CDefSaveRestoreBlockHandler -{ -public: - const char *GetBlockName() - { - return "EventQueue"; - } - - //--------------------------------- - - void Save( ISave *pSave ) - { - g_EventQueue.Save( *pSave ); - } - - //--------------------------------- - - void WriteSaveHeaders( ISave *pSave ) - { - pSave->WriteShort( &EVENTQUEUE_SAVE_RESTORE_VERSION ); - } - - //--------------------------------- - - void ReadRestoreHeaders( IRestore *pRestore ) - { - // No reason why any future version shouldn't try to retain backward compatability. The default here is to not do so. - short version; - pRestore->ReadShort( &version ); - m_fDoLoad = ( version == EVENTQUEUE_SAVE_RESTORE_VERSION ); - } - - //--------------------------------- - - void Restore( IRestore *pRestore, bool createPlayers ) - { - if ( m_fDoLoad ) - { - g_EventQueue.Restore( *pRestore ); - } - } - -private: - bool m_fDoLoad; -}; - -//----------------------------------------------------------------------------- - -CEventQueue_SaveRestoreBlockHandler g_EventQueue_SaveRestoreBlockHandler; - -//------------------------------------- - -ISaveRestoreBlockHandler *GetEventQueueSaveRestoreBlockHandler() -{ - return &g_EventQueue_SaveRestoreBlockHandler; -} - - -void CEventQueue::Init( void ) -{ - Clear(); -} - -void CEventQueue::Clear( void ) -{ - // delete all the events in the queue - EventQueuePrioritizedEvent_t *pe = m_Events.m_pNext; - - while ( pe != NULL ) - { - EventQueuePrioritizedEvent_t *next = pe->m_pNext; - delete pe; - pe = next; - } - - m_Events.m_pNext = NULL; -} - -void CEventQueue::Dump( void ) -{ - EventQueuePrioritizedEvent_t *pe = m_Events.m_pNext; - - Msg("Dumping event queue. Current time is: %.2f\n", gpGlobals->curtime ); - - while ( pe != NULL ) - { - EventQueuePrioritizedEvent_t *next = pe->m_pNext; - - Msg(" (%.2f) Target: '%s', Input: '%s', Parameter '%s'. Activator: '%s', Caller '%s'. \n", - pe->m_flFireTime, - STRING(pe->m_iTarget), - STRING(pe->m_iTargetInput), - pe->m_VariantValue.String(), - pe->m_pActivator ? pe->m_pActivator->GetDebugName() : "None", - pe->m_pCaller ? pe->m_pCaller->GetDebugName() : "None" ); - - pe = next; - } - - Msg("Finished dump.\n"); -} - - -//----------------------------------------------------------------------------- -// Purpose: adds the action into the correct spot in the priority queue, targeting entity via string name -//----------------------------------------------------------------------------- -void CEventQueue::AddEvent( const char *target, const char *targetInput, variant_t Value, float fireDelay, CBaseEntity *pActivator, CBaseEntity *pCaller, int outputID ) -{ - // build the new event - EventQueuePrioritizedEvent_t *newEvent = new EventQueuePrioritizedEvent_t; - newEvent->m_flFireTime = gpGlobals->curtime + fireDelay; // priority key in the priority queue - newEvent->m_iTarget = MAKE_STRING( target ); - newEvent->m_pEntTarget = NULL; - newEvent->m_iTargetInput = MAKE_STRING( targetInput ); - newEvent->m_pActivator = pActivator; - newEvent->m_pCaller = pCaller; - newEvent->m_VariantValue = Value; - newEvent->m_iOutputID = outputID; - - AddEvent( newEvent ); -} - -//----------------------------------------------------------------------------- -// Purpose: adds the action into the correct spot in the priority queue, targeting entity via pointer -//----------------------------------------------------------------------------- -void CEventQueue::AddEvent( CBaseEntity *target, const char *targetInput, variant_t Value, float fireDelay, CBaseEntity *pActivator, CBaseEntity *pCaller, int outputID ) -{ - // build the new event - EventQueuePrioritizedEvent_t *newEvent = new EventQueuePrioritizedEvent_t; - newEvent->m_flFireTime = gpGlobals->curtime + fireDelay; // primary priority key in the priority queue - newEvent->m_iTarget = NULL_STRING; - newEvent->m_pEntTarget = target; - newEvent->m_iTargetInput = MAKE_STRING( targetInput ); - newEvent->m_pActivator = pActivator; - newEvent->m_pCaller = pCaller; - newEvent->m_VariantValue = Value; - newEvent->m_iOutputID = outputID; - - AddEvent( newEvent ); -} - -void CEventQueue::AddEvent( CBaseEntity *target, const char *action, float fireDelay, CBaseEntity *pActivator, CBaseEntity *pCaller, int outputID ) -{ - variant_t Value; - Value.Set( FIELD_VOID, NULL ); - AddEvent( target, action, Value, fireDelay, pActivator, pCaller, outputID ); -} - - -//----------------------------------------------------------------------------- -// Purpose: private function, adds an event into the list -// Input : *newEvent - the (already built) event to add -//----------------------------------------------------------------------------- -void CEventQueue::AddEvent( EventQueuePrioritizedEvent_t *newEvent ) -{ - // loop through the actions looking for a place to insert - EventQueuePrioritizedEvent_t *pe; - for ( pe = &m_Events; pe->m_pNext != NULL; pe = pe->m_pNext ) - { - if ( pe->m_pNext->m_flFireTime > newEvent->m_flFireTime ) - { - break; - } - } - - Assert( pe ); - - // insert - newEvent->m_pNext = pe->m_pNext; - newEvent->m_pPrev = pe; - pe->m_pNext = newEvent; - if ( newEvent->m_pNext ) - { - newEvent->m_pNext->m_pPrev = newEvent; - } -} - -void CEventQueue::RemoveEvent( EventQueuePrioritizedEvent_t *pe ) -{ - Assert( pe->m_pPrev ); - pe->m_pPrev->m_pNext = pe->m_pNext; - if ( pe->m_pNext ) - { - pe->m_pNext->m_pPrev = pe->m_pPrev; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: fires off any events in the queue who's fire time is (or before) the present time -//----------------------------------------------------------------------------- -void CEventQueue::ServiceEvents( void ) -{ - if (!CBaseEntity::Debug_ShouldStep()) - { - return; - } - - EventQueuePrioritizedEvent_t *pe = m_Events.m_pNext; - - while ( pe != NULL && pe->m_flFireTime <= gpGlobals->curtime ) - { - MDLCACHE_CRITICAL_SECTION(); - - bool targetFound = false; - - // find the targets - if ( pe->m_iTarget != NULL_STRING ) - { - // In the context the event, the searching entity is also the caller - CBaseEntity *pSearchingEntity = pe->m_pCaller; - CBaseEntity *target = NULL; - while ( 1 ) - { - target = gEntList.FindEntityByName( target, pe->m_iTarget, pSearchingEntity, pe->m_pActivator, pe->m_pCaller ); - if ( !target ) - break; - - // pump the action into the target - target->AcceptInput( STRING(pe->m_iTargetInput), pe->m_pActivator, pe->m_pCaller, pe->m_VariantValue, pe->m_iOutputID ); - targetFound = true; - } - } - - // direct pointer - if ( pe->m_pEntTarget != NULL ) - { - pe->m_pEntTarget->AcceptInput( STRING(pe->m_iTargetInput), pe->m_pActivator, pe->m_pCaller, pe->m_VariantValue, pe->m_iOutputID ); - targetFound = true; - } - - if ( !targetFound ) - { - // See if we can find a target if we treat the target as a classname - if ( pe->m_iTarget != NULL_STRING ) - { - CBaseEntity *target = NULL; - while ( 1 ) - { - target = gEntList.FindEntityByClassname( target, STRING(pe->m_iTarget) ); - if ( !target ) - break; - - // pump the action into the target - target->AcceptInput( STRING(pe->m_iTargetInput), pe->m_pActivator, pe->m_pCaller, pe->m_VariantValue, pe->m_iOutputID ); - targetFound = true; - } - } - } - - if ( !targetFound ) - { - const char *pClass ="", *pName = ""; - - // might be NULL - if ( pe->m_pCaller ) - { - pClass = STRING(pe->m_pCaller->m_iClassname); - pName = STRING(pe->m_pCaller->GetEntityName()); - } - - char szBuffer[256]; - Q_snprintf( szBuffer, sizeof(szBuffer), "unhandled input: (%s) -> (%s), from (%s,%s); target entity not found\n", STRING(pe->m_iTargetInput), STRING(pe->m_iTarget), pClass, pName ); - DevMsg( 2, szBuffer ); - ADD_DEBUG_HISTORY( HISTORY_ENTITY_IO, szBuffer ); - } - - // remove the event from the list (remembering that the queue may have been added to) - RemoveEvent( pe ); - delete pe; - - // - // If we are in debug mode, exit the loop if we have fired the correct number of events. - // - if (CBaseEntity::Debug_IsPaused()) - { - if (!CBaseEntity::Debug_Step()) - { - break; - } - } - - // restart the list (to catch any new items have probably been added to the queue) - pe = m_Events.m_pNext; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Dumps the contents of the Entity I/O event queue to the console. -//----------------------------------------------------------------------------- -void CC_DumpEventQueue() -{ - g_EventQueue.Dump(); -} -static ConCommand dumpeventqueue( "dumpeventqueue", CC_DumpEventQueue, "Dump the contents of the Entity I/O event queue to the console." ); - -//----------------------------------------------------------------------------- -// Purpose: Removes all pending events from the I/O queue that were added by the -// given caller. -// -// TODO: This is only as reliable as callers are in passing the correct -// caller pointer when they fire the outputs. Make more foolproof. -//----------------------------------------------------------------------------- -void CEventQueue::CancelEvents( CBaseEntity *pCaller ) -{ - if (!pCaller) - return; - - EventQueuePrioritizedEvent_t *pCur = m_Events.m_pNext; - - while (pCur != NULL) - { - bool bDelete = false; - if (pCur->m_pCaller == pCaller) - { - // Pointers match; make sure everything else matches. - if (!stricmp(STRING(pCur->m_pCaller->GetEntityName()), STRING(pCaller->GetEntityName())) && - !stricmp(pCur->m_pCaller->GetClassname(), pCaller->GetClassname())) - { - // Found a matching event; delete it from the queue. - bDelete = true; - } - } - - EventQueuePrioritizedEvent_t *pCurSave = pCur; - pCur = pCur->m_pNext; - - if (bDelete) - { - RemoveEvent( pCurSave ); - delete pCurSave; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Removes all pending events of the specified type from the I/O queue of the specified target -// -// TODO: This is only as reliable as callers are in passing the correct -// caller pointer when they fire the outputs. Make more foolproof. -//----------------------------------------------------------------------------- -void CEventQueue::CancelEventOn( CBaseEntity *pTarget, const char *sInputName ) -{ - if (!pTarget) - return; - - EventQueuePrioritizedEvent_t *pCur = m_Events.m_pNext; - - while (pCur != NULL) - { - bool bDelete = false; - if (pCur->m_pEntTarget == pTarget) - { - if ( !Q_strncmp( STRING(pCur->m_iTargetInput), sInputName, strlen(sInputName) ) ) - { - // Found a matching event; delete it from the queue. - bDelete = true; - } - } - - EventQueuePrioritizedEvent_t *pCurSave = pCur; - pCur = pCur->m_pNext; - - if (bDelete) - { - RemoveEvent( pCurSave ); - delete pCurSave; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if the target has any pending inputs. -// Input : *pTarget - -// *sInputName - NULL for any input, or a specified one -//----------------------------------------------------------------------------- -bool CEventQueue::HasEventPending( CBaseEntity *pTarget, const char *sInputName ) -{ - if (!pTarget) - return false; - - EventQueuePrioritizedEvent_t *pCur = m_Events.m_pNext; - - while (pCur != NULL) - { - if (pCur->m_pEntTarget == pTarget) - { - if ( !sInputName ) - return true; - - if ( !Q_strncmp( STRING(pCur->m_iTargetInput), sInputName, strlen(sInputName) ) ) - return true; - } - - pCur = pCur->m_pNext; - } - - return false; -} - -void ServiceEventQueue( void ) -{ - VPROF("ServiceEventQueue()"); - - g_EventQueue.ServiceEvents(); -} - - - -// save data description for the event queue -BEGIN_SIMPLE_DATADESC( CEventQueue ) - // These are saved explicitly in CEventQueue::Save below - // DEFINE_FIELD( m_Events, EventQueuePrioritizedEvent_t ), - - DEFINE_FIELD( m_iListCount, FIELD_INTEGER ), // this value is only used during save/restore -END_DATADESC() - - -// save data for a single event in the queue -BEGIN_SIMPLE_DATADESC( EventQueuePrioritizedEvent_t ) - DEFINE_FIELD( m_flFireTime, FIELD_TIME ), - DEFINE_FIELD( m_iTarget, FIELD_STRING ), - DEFINE_FIELD( m_iTargetInput, FIELD_STRING ), - DEFINE_FIELD( m_pActivator, FIELD_EHANDLE ), - DEFINE_FIELD( m_pCaller, FIELD_EHANDLE ), - DEFINE_FIELD( m_pEntTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_iOutputID, FIELD_INTEGER ), - DEFINE_CUSTOM_FIELD( m_VariantValue, variantFuncs ), - -// DEFINE_FIELD( m_pNext, FIELD_??? ), -// DEFINE_FIELD( m_pPrev, FIELD_??? ), -END_DATADESC() - - -int CEventQueue::Save( ISave &save ) -{ - // count the number of items in the queue - EventQueuePrioritizedEvent_t *pe; - - m_iListCount = 0; - for ( pe = m_Events.m_pNext; pe != NULL; pe = pe->m_pNext ) - { - m_iListCount++; - } - - // save that value out to disk, so we know how many to restore - if ( !save.WriteFields( "EventQueue", this, NULL, m_DataMap.dataDesc, m_DataMap.dataNumFields ) ) - return 0; - - // cycle through all the events, saving them all - for ( pe = m_Events.m_pNext; pe != NULL; pe = pe->m_pNext ) - { - if ( !save.WriteFields( "PEvent", pe, NULL, pe->m_DataMap.dataDesc, pe->m_DataMap.dataNumFields ) ) - return 0; - } - - return 1; -} - - -int CEventQueue::Restore( IRestore &restore ) -{ - // clear the event queue - Clear(); - - // rebuild the event queue by restoring all the queue items - EventQueuePrioritizedEvent_t tmpEvent; - - // load the number of items saved - if ( !restore.ReadFields( "EventQueue", this, NULL, m_DataMap.dataDesc, m_DataMap.dataNumFields ) ) - return 0; - - for ( int i = 0; i < m_iListCount; i++ ) - { - if ( !restore.ReadFields( "PEvent", &tmpEvent, NULL, tmpEvent.m_DataMap.dataDesc, tmpEvent.m_DataMap.dataNumFields ) ) - return 0; - - // add the restored event into the list - if ( tmpEvent.m_pEntTarget ) - { - AddEvent( tmpEvent.m_pEntTarget, STRING(tmpEvent.m_iTargetInput), tmpEvent.m_VariantValue, tmpEvent.m_flFireTime - gpGlobals->curtime, tmpEvent.m_pActivator, tmpEvent.m_pCaller, tmpEvent.m_iOutputID ); - } - else - { - AddEvent( STRING(tmpEvent.m_iTarget), STRING(tmpEvent.m_iTargetInput), tmpEvent.m_VariantValue, tmpEvent.m_flFireTime - gpGlobals->curtime, tmpEvent.m_pActivator, tmpEvent.m_pCaller, tmpEvent.m_iOutputID ); - } - } - - return 1; -} - -////////////////////////// variant_t implementation ////////////////////////// - -// BUGBUG: Add support for function pointer save/restore to variants -// BUGBUG: Must pass datamap_t to read/write fields -void variant_t::Set( fieldtype_t ftype, void *data ) -{ - fieldType = ftype; - - switch ( ftype ) - { - case FIELD_BOOLEAN: bVal = *((bool *)data); break; - case FIELD_CHARACTER: iVal = *((char *)data); break; - case FIELD_SHORT: iVal = *((short *)data); break; - case FIELD_INTEGER: iVal = *((int *)data); break; - case FIELD_STRING: iszVal = *((string_t *)data); break; - case FIELD_FLOAT: flVal = *((float *)data); break; - case FIELD_COLOR32: rgbaVal = *((color32 *)data); break; - - case FIELD_VECTOR: - case FIELD_POSITION_VECTOR: - { - vecVal[0] = ((float *)data)[0]; - vecVal[1] = ((float *)data)[1]; - vecVal[2] = ((float *)data)[2]; - break; - } - - case FIELD_EHANDLE: eVal = *((EHANDLE *)data); break; - case FIELD_CLASSPTR: eVal = *((CBaseEntity **)data); break; - case FIELD_VOID: - default: - iVal = 0; fieldType = FIELD_VOID; - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Copies the value in the variant into a block of memory -// Input : *data - the block to write into -//----------------------------------------------------------------------------- -void variant_t::SetOther( void *data ) -{ - switch ( fieldType ) - { - case FIELD_BOOLEAN: *((bool *)data) = bVal != 0; break; - case FIELD_CHARACTER: *((char *)data) = iVal; break; - case FIELD_SHORT: *((short *)data) = iVal; break; - case FIELD_INTEGER: *((int *)data) = iVal; break; - case FIELD_STRING: *((string_t *)data) = iszVal; break; - case FIELD_FLOAT: *((float *)data) = flVal; break; - case FIELD_COLOR32: *((color32 *)data) = rgbaVal; break; - - case FIELD_VECTOR: - case FIELD_POSITION_VECTOR: - { - ((float *)data)[0] = vecVal[0]; - ((float *)data)[1] = vecVal[1]; - ((float *)data)[2] = vecVal[2]; - break; - } - - case FIELD_EHANDLE: *((EHANDLE *)data) = eVal; break; - case FIELD_CLASSPTR: *((CBaseEntity **)data) = eVal; break; - default: break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Converts the variant to a new type. This function defines which I/O -// types can be automatically converted between. Connections that require -// an unsupported conversion will cause an error message at runtime. -// Input : newType - the type to convert to -// Output : Returns true on success, false if the conversion is not legal -//----------------------------------------------------------------------------- -bool variant_t::Convert( fieldtype_t newType ) -{ - if ( newType == fieldType ) - { - return true; - } - - // - // Converting to a null value is easy. - // - if ( newType == FIELD_VOID ) - { - Set( FIELD_VOID, NULL ); - return true; - } - - // - // FIELD_INPUT accepts the variant type directly. - // - if ( newType == FIELD_INPUT ) - { - return true; - } - - switch ( fieldType ) - { - case FIELD_INTEGER: - { - switch ( newType ) - { - case FIELD_FLOAT: - { - SetFloat( (float) iVal ); - return true; - } - - case FIELD_BOOLEAN: - { - SetBool( iVal != 0 ); - return true; - } - - default: - break; - } - break; - - default: - break; - } - - case FIELD_FLOAT: - { - switch ( newType ) - { - case FIELD_INTEGER: - { - SetInt( (int) flVal ); - return true; - } - - case FIELD_BOOLEAN: - { - SetBool( flVal != 0 ); - return true; - } - - default: - break; - } - break; - } - - // - // Everyone must convert from FIELD_STRING if possible, since - // parameter overrides are always passed as strings. - // - case FIELD_STRING: - { - switch ( newType ) - { - case FIELD_INTEGER: - { - if (iszVal != NULL_STRING) - { - SetInt(atoi(STRING(iszVal))); - } - else - { - SetInt(0); - } - return true; - } - - case FIELD_FLOAT: - { - if (iszVal != NULL_STRING) - { - SetFloat(atof(STRING(iszVal))); - } - else - { - SetFloat(0); - } - return true; - } - - case FIELD_BOOLEAN: - { - if (iszVal != NULL_STRING) - { - SetBool( atoi(STRING(iszVal)) != 0 ); - } - else - { - SetBool(false); - } - return true; - } - - case FIELD_VECTOR: - { - Vector tmpVec = vec3_origin; - if (sscanf(STRING(iszVal), "[%f %f %f]", &tmpVec[0], &tmpVec[1], &tmpVec[2]) == 0) - { - // Try sucking out 3 floats with no []s - sscanf(STRING(iszVal), "%f %f %f", &tmpVec[0], &tmpVec[1], &tmpVec[2]); - } - SetVector3D( tmpVec ); - return true; - } - - case FIELD_COLOR32: - { - int nRed = 0; - int nGreen = 0; - int nBlue = 0; - int nAlpha = 255; - - sscanf(STRING(iszVal), "%d %d %d %d", &nRed, &nGreen, &nBlue, &nAlpha); - SetColor32( nRed, nGreen, nBlue, nAlpha ); - return true; - } - - case FIELD_EHANDLE: - { - // convert the string to an entity by locating it by classname - CBaseEntity *ent = NULL; - if ( iszVal != NULL_STRING ) - { - // FIXME: do we need to pass an activator in here? - ent = gEntList.FindEntityByName( NULL, iszVal ); - } - SetEntity( ent ); - return true; - } - - default: - break; - } - - break; - } - - case FIELD_EHANDLE: - { - switch ( newType ) - { - case FIELD_STRING: - { - // take the entities targetname as the string - string_t iszStr = NULL_STRING; - if ( eVal != NULL ) - { - SetString( eVal->GetEntityName() ); - } - return true; - } - - default: - break; - } - break; - } - } - - // invalid conversion - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: All types must be able to display as strings for debugging purposes. -// Output : Returns a pointer to the string that represents this value. -// -// NOTE: The returned pointer should not be stored by the caller as -// subsequent calls to this function will overwrite the contents -// of the buffer! -//----------------------------------------------------------------------------- -const char *variant_t::ToString( void ) const -{ - COMPILE_TIME_ASSERT( sizeof(string_t) == sizeof(int) ); - - static char szBuf[512]; - - switch (fieldType) - { - case FIELD_STRING: - { - return(STRING(iszVal)); - } - - case FIELD_BOOLEAN: - { - if (bVal == 0) - { - Q_strncpy(szBuf, "false",sizeof(szBuf)); - } - else - { - Q_strncpy(szBuf, "true",sizeof(szBuf)); - } - return(szBuf); - } - - case FIELD_INTEGER: - { - Q_snprintf( szBuf, sizeof( szBuf ), "%i", iVal ); - return(szBuf); - } - - case FIELD_FLOAT: - { - Q_snprintf(szBuf,sizeof(szBuf), "%g", flVal); - return(szBuf); - } - - case FIELD_COLOR32: - { - Q_snprintf(szBuf,sizeof(szBuf), "%d %d %d %d", (int)rgbaVal.r, (int)rgbaVal.g, (int)rgbaVal.b, (int)rgbaVal.a); - return(szBuf); - } - - case FIELD_VECTOR: - { - Q_snprintf(szBuf,sizeof(szBuf), "[%g %g %g]", (double)vecVal[0], (double)vecVal[1], (double)vecVal[2]); - return(szBuf); - } - - case FIELD_VOID: - { - szBuf[0] = '\0'; - return(szBuf); - } - - case FIELD_EHANDLE: - { - const char *pszName = (Entity()) ? STRING(Entity()->GetEntityName()) : "<>"; - Q_strncpy( szBuf, pszName, 512 ); - return (szBuf); - } - - default: - break; - } - - return("No conversion to string"); -} - -#define classNameTypedef variant_t // to satisfy DEFINE... macros - -typedescription_t variant_t::m_SaveBool[] = -{ - DEFINE_FIELD( bVal, FIELD_BOOLEAN ), -}; -typedescription_t variant_t::m_SaveInt[] = -{ - DEFINE_FIELD( iVal, FIELD_INTEGER ), -}; -typedescription_t variant_t::m_SaveFloat[] = -{ - DEFINE_FIELD( flVal, FIELD_FLOAT ), -}; -typedescription_t variant_t::m_SaveEHandle[] = -{ - DEFINE_FIELD( eVal, FIELD_EHANDLE ), -}; -typedescription_t variant_t::m_SaveString[] = -{ - DEFINE_FIELD( iszVal, FIELD_STRING ), -}; -typedescription_t variant_t::m_SaveColor[] = -{ - DEFINE_FIELD( rgbaVal, FIELD_COLOR32 ), -}; - -#undef classNameTypedef - -// -// Struct for saving and restoring vector variants, since they are -// stored as float[3] and we want to take advantage of position vector -// fixup across level transitions. -// -#define classNameTypedef variant_savevector_t // to satisfy DEFINE... macros - -struct variant_savevector_t -{ - Vector vecSave; -}; -typedescription_t variant_t::m_SaveVector[] = -{ - // Just here to shut up ClassCheck -// DEFINE_ARRAY( vecVal, FIELD_FLOAT, 3 ), - - DEFINE_FIELD( vecSave, FIELD_VECTOR ), -}; -typedescription_t variant_t::m_SavePositionVector[] = -{ - DEFINE_FIELD( vecSave, FIELD_POSITION_VECTOR ), -}; -#undef classNameTypedef - -#define classNameTypedef variant_savevmatrix_t // to satisfy DEFINE... macros -struct variant_savevmatrix_t -{ - VMatrix matSave; -}; -typedescription_t variant_t::m_SaveVMatrix[] = -{ - DEFINE_FIELD( matSave, FIELD_VMATRIX ), -}; -typedescription_t variant_t::m_SaveVMatrixWorldspace[] = -{ - DEFINE_FIELD( matSave, FIELD_VMATRIX_WORLDSPACE ), -}; -#undef classNameTypedef - -#define classNameTypedef variant_savevmatrix3x4_t // to satisfy DEFINE... macros -struct variant_savevmatrix3x4_t -{ - matrix3x4_t matSave; -}; -typedescription_t variant_t::m_SaveMatrix3x4Worldspace[] = -{ - DEFINE_FIELD( matSave, FIELD_MATRIX3X4_WORLDSPACE ), -}; -#undef classNameTypedef - -class CVariantSaveDataOps : public CDefSaveRestoreOps -{ - // saves the entire array of variables - virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave ) - { - variant_t *var = (variant_t*)fieldInfo.pField; - - int type = var->FieldType(); - pSave->WriteInt( &type, 1 ); - - switch ( var->FieldType() ) - { - case FIELD_VOID: - break; - case FIELD_BOOLEAN: - pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveBool, 1 ); - break; - case FIELD_INTEGER: - pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveInt, 1 ); - break; - case FIELD_FLOAT: - pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveFloat, 1 ); - break; - case FIELD_EHANDLE: - pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveEHandle, 1 ); - break; - case FIELD_STRING: - pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveString, 1 ); - break; - case FIELD_COLOR32: - pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveColor, 1 ); - break; - case FIELD_VECTOR: - { - variant_savevector_t Temp; - var->Vector3D(Temp.vecSave); - pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, &Temp, NULL, variant_t::m_SaveVector, 1 ); - break; - } - - case FIELD_POSITION_VECTOR: - { - variant_savevector_t Temp; - var->Vector3D(Temp.vecSave); - pSave->WriteFields( fieldInfo.pTypeDesc->fieldName, &Temp, NULL, variant_t::m_SavePositionVector, 1 ); - break; - } - - default: - Warning( "Bad type %d in saved variant_t\n", var->FieldType() ); - Assert(0); - } - } - - // restores a single instance of the variable - virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore ) - { - variant_t *var = (variant_t*)fieldInfo.pField; - - *var = variant_t(); - - var->fieldType = (_fieldtypes)pRestore->ReadInt(); - - switch ( var->fieldType ) - { - case FIELD_VOID: - break; - case FIELD_BOOLEAN: - pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveBool, 1 ); - break; - case FIELD_INTEGER: - pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveInt, 1 ); - break; - case FIELD_FLOAT: - pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveFloat, 1 ); - break; - case FIELD_EHANDLE: - pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveEHandle, 1 ); - break; - case FIELD_STRING: - pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveString, 1 ); - break; - case FIELD_COLOR32: - pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, var, NULL, variant_t::m_SaveColor, 1 ); - break; - case FIELD_VECTOR: - { - variant_savevector_t Temp; - pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, &Temp, NULL, variant_t::m_SaveVector, 1 ); - var->SetVector3D(Temp.vecSave); - break; - } - case FIELD_POSITION_VECTOR: - { - variant_savevector_t Temp; - pRestore->ReadFields( fieldInfo.pTypeDesc->fieldName, &Temp, NULL, variant_t::m_SavePositionVector, 1 ); - var->SetPositionVector3D(Temp.vecSave); - break; - } - default: - Warning( "Bad type %d in saved variant_t\n", var->FieldType() ); - Assert(0); - break; - } - } - - - virtual bool IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - // check all the elements of the array (usually only 1) - variant_t *var = (variant_t*)fieldInfo.pField; - for ( int i = 0; i < fieldInfo.pTypeDesc->fieldSize; i++, var++ ) - { - if ( var->FieldType() != FIELD_VOID ) - return 0; - } - - // variant has no data - return 1; - } - - virtual void MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - // Don't no how to. This is okay, since objects of this type - // are always born clean before restore, and not reused - } -}; - -CVariantSaveDataOps g_VariantSaveDataOps; -ISaveRestoreOps *variantFuncs = &g_VariantSaveDataOps; - -/////////////////////// entitylist ///////////////////// - -CMemoryPool g_EntListMemPool( sizeof(entitem_t), 256, CMemoryPool::GROW_NONE, "g_EntListMemPool" ); - -#include "tier0/memdbgoff.h" - -void *entitem_t::operator new( size_t stAllocateBlock ) -{ - return g_EntListMemPool.Alloc( stAllocateBlock ); -} - -void *entitem_t::operator new( size_t stAllocateBlock, int nBlockUse, const char *pFileName, int nLine ) -{ - return g_EntListMemPool.Alloc( stAllocateBlock ); -} - -void entitem_t::operator delete( void *pMem ) -{ - g_EntListMemPool.Free( pMem ); -} - -#include "tier0/memdbgon.h" - - -CEntityList::CEntityList() -{ - m_pItemList = NULL; - m_iNumItems = 0; -} - -CEntityList::~CEntityList() -{ - // remove all items from the list - entitem_t *next, *e = m_pItemList; - while ( e != NULL ) - { - next = e->pNext; - delete e; - e = next; - } - m_pItemList = NULL; -} - -void CEntityList::AddEntity( CBaseEntity *pEnt ) -{ - // check if it's already in the list; if not, add it - entitem_t *e = m_pItemList; - while ( e != NULL ) - { - if ( e->hEnt == pEnt ) - { - // it's already in the list - return; - } - - if ( e->pNext == NULL ) - { - // we've hit the end of the list, so tack it on - e->pNext = new entitem_t; - e->pNext->hEnt = pEnt; - e->pNext->pNext = NULL; - m_iNumItems++; - return; - } - - e = e->pNext; - } - - // empty list - m_pItemList = new entitem_t; - m_pItemList->hEnt = pEnt; - m_pItemList->pNext = NULL; - m_iNumItems = 1; -} - -void CEntityList::DeleteEntity( CBaseEntity *pEnt ) -{ - // find the entry in the list and delete it - entitem_t *prev = NULL, *e = m_pItemList; - while ( e != NULL ) - { - // delete the link if it's the matching entity OR if the link is NULL - if ( e->hEnt == pEnt || e->hEnt == NULL ) - { - if ( prev ) - { - prev->pNext = e->pNext; - } - else - { - m_pItemList = e->pNext; - } - - delete e; - m_iNumItems--; - - // REVISIT: Is this correct? Is this just here to clean out dead EHANDLEs? - // restart the loop - e = m_pItemList; - prev = NULL; - continue; - } - - prev = e; - e = e->pNext; - } -} - diff --git a/game/server/cbase.h b/game/server/cbase.h deleted file mode 100644 index 5e5b330ef..000000000 --- a/game/server/cbase.h +++ /dev/null @@ -1,154 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef CBASE_H -#define CBASE_H -#ifdef _WIN32 -#pragma once -#endif - -#ifdef _WIN32 -// Silence certain warnings -#pragma warning(disable : 4244) // int or float down-conversion -#pragma warning(disable : 4305) // int or float data truncation -#pragma warning(disable : 4201) // nameless struct/union -#pragma warning(disable : 4511) // copy constructor could not be generated -#pragma warning(disable : 4675) // resolved overload was found by argument dependent lookup -#endif - -#ifdef _DEBUG -#define DEBUG 1 -#endif - -// Misc C-runtime library headers -#include - -#include - -// tier 0 -#include "tier0/dbg.h" -#include "tier0/platform.h" -#include "basetypes.h" - -// tier 1 -#include "tier1/strtools.h" -#include "utlvector.h" -#include "mathlib/vmatrix.h" - -// tier 2 -#include "string_t.h" - -// tier 3 -#include "vphysics_interface.h" - -// Shared engine/DLL constants -#include "const.h" -#include "edict.h" - -// Shared header describing protocol between engine and DLLs -#include "eiface.h" -#include "iserverentity.h" - -#include "dt_send.h" - -// Shared header between the client DLL and the game DLLs -#include "shareddefs.h" -#include "ehandle.h" - -// app -#if defined(_X360) -#define DISABLE_DEBUG_HISTORY 1 -#endif - - -#include "datamap.h" -#include "util.h" -#include "predictable_entity.h" -#include "predictableid.h" -#include "variant_t.h" -#include "takedamageinfo.h" -#include "utllinkedlist.h" -#include "touchlink.h" -#include "groundlink.h" -#include "base_transmit_proxy.h" -#include "soundflags.h" -#include "networkvar.h" -#include "baseentity_shared.h" -#include "basetoggle.h" -#include "igameevents.h" - -// saverestore.h declarations -class ISave; -class IRestore; - -// maximum number of targets a single multi_manager entity may be assigned. -#define MAX_MULTI_TARGETS 16 - -// NPCEvent.h declarations -struct animevent_t; - -struct studiohdr_t; -class CStudioHdr; - -extern void FireTargets( const char *targetName, CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - -// people gib if their health is <= this at the time of death -#define GIB_HEALTH_VALUE -30 - -#define MAX_OLD_ENEMIES 4 // how many old enemies to remember - -// used by suit voice to indicate damage sustained and repaired type to player - -enum -{ - itbd_Paralyze = 0, - itbd_NerveGas, - itbd_PoisonRecover, - itbd_Radiation, - itbd_DrownRecover, - itbd_Acid, - itbd_SlowBurn, - itbd_SlowFreeze, - - // Must be last! - CDMG_TIMEBASED -}; - -// when calling KILLED(), a value that governs gib behavior is expected to be -// one of these three values -#define GIB_NORMAL 0// gib if entity was overkilled -#define GIB_NEVER 1// never gib, no matter how much death damage is done ( freezing, etc ) -#define GIB_ALWAYS 2// always gib - -class CAI_BaseNPC; -class CAI_ScriptedSequence; -class CSound; - -#ifdef _XBOX -//#define FUNCTANK_AUTOUSE We haven't made the decision to use this yet (sjb) -#else -#undef FUNCTANK_AUTOUSE -#endif//_XBOX - -// This is a precompiled header. Include a bunch of common stuff. -// This is kind of ugly in that it adds a bunch of dependency where it isn't needed. -// But on balance, the compile time is much lower (even incrementally) once the precompiled -// headers contain these headers. -#include "precache_register.h" -#include "baseanimating.h" -#include "basecombatweapon.h" -#include "basecombatcharacter.h" -#include "gamerules.h" -#include "entitylist.h" -#include "basetempentity.h" -#include "player.h" -#include "te.h" -#include "physics.h" -#include "ndebugoverlay.h" -#include "recipientfilter.h" - -#endif // CBASE_H diff --git a/game/server/client.cpp b/game/server/client.cpp deleted file mode 100644 index 2c734e025..000000000 --- a/game/server/client.cpp +++ /dev/null @@ -1,1491 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -/* - -===== client.cpp ======================================================== - - client/server game specific stuff - -*/ - -#include "cbase.h" -#include "player.h" -#include "client.h" -#include "soundent.h" -#include "gamerules.h" -#include "game.h" -#include "physics.h" -#include "entitylist.h" -#include "shake.h" -#include "globalstate.h" -#include "event_tempentity_tester.h" -#include "ndebugoverlay.h" -#include "engine/IEngineSound.h" -#include -#include "tier1/strtools.h" -#include "te_effect_dispatch.h" -#include "globals.h" -#include "nav_mesh.h" -#include "team.h" -#include "datacache/imdlcache.h" -#include "basemultiplayerplayer.h" -#include "voice_gamemgr.h" - -#ifdef TF_DLL -#include "tf_player.h" -#endif - -#ifdef HL2_DLL -#include "weapon_physcannon.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern int giPrecacheGrunt; - -// For not just using one big ai net -extern CBaseEntity* FindPickerEntity( CBasePlayer* pPlayer ); - -extern bool IsInCommentaryMode( void ); - -ConVar *sv_cheats = NULL; - -void ClientKill( edict_t *pEdict, const Vector &vecForce, bool bExplode = false ) -{ - CBasePlayer *pPlayer = static_cast( GetContainingEntity( pEdict ) ); - pPlayer->CommitSuicide( vecForce, bExplode ); -} - -char * CheckChatText( CBasePlayer *pPlayer, char *text ) -{ - char *p = text; - - // invalid if NULL or empty - if ( !text || !text[0] ) - return NULL; - - int length = Q_strlen( text ); - - // remove quotes (leading & trailing) if present - if (*p == '"') - { - p++; - length -=2; - p[length] = 0; - } - - // cut off after 127 chars - if ( length > 127 ) - text[127] = 0; - - GameRules()->CheckChatText( pPlayer, p ); - - return p; -} - -//// HOST_SAY -// String comes in as -// say blah blah blah -// or as -// blah blah blah -// -void Host_Say( edict_t *pEdict, const CCommand &args, bool teamonly ) -{ - CBasePlayer *client; - int j; - char *p; - char text[256]; - char szTemp[256]; - const char *cpSay = "say"; - const char *cpSayTeam = "say_team"; - const char *pcmd = args[0]; - bool bSenderDead = false; - - // We can get a raw string now, without the "say " prepended - if ( args.ArgC() == 0 ) - return; - - if ( !stricmp( pcmd, cpSay) || !stricmp( pcmd, cpSayTeam ) ) - { - if ( args.ArgC() >= 2 ) - { - p = (char *)args.ArgS(); - } - else - { - // say with a blank message, nothing to do - return; - } - } - else // Raw text, need to prepend argv[0] - { - if ( args.ArgC() >= 2 ) - { - Q_snprintf( szTemp,sizeof(szTemp), "%s %s", ( char * )pcmd, (char *)args.ArgS() ); - } - else - { - // Just a one word command, use the first word...sigh - Q_snprintf( szTemp,sizeof(szTemp), "%s", ( char * )pcmd ); - } - p = szTemp; - } - - CBasePlayer *pPlayer = NULL; - if ( pEdict ) - { - pPlayer = ((CBasePlayer *)CBaseEntity::Instance( pEdict )); - Assert( pPlayer ); - - // make sure the text has valid content - p = CheckChatText( pPlayer, p ); - } - - if ( !p ) - return; - - if ( pEdict ) - { - if ( !pPlayer->CanSpeak() ) - return; - - // See if the player wants to modify of check the text - pPlayer->CheckChatText( p, 127 ); // though the buffer szTemp that p points to is 256, - // chat text is capped to 127 in CheckChatText above - - Assert( strlen( pPlayer->GetPlayerName() ) > 0 ); - - bSenderDead = ( pPlayer->m_lifeState != LIFE_ALIVE ); - } - else - { - bSenderDead = false; - } - - const char *pszFormat = NULL; - const char *pszPrefix = NULL; - const char *pszLocation = NULL; - if ( g_pGameRules ) - { - pszFormat = g_pGameRules->GetChatFormat( teamonly, pPlayer ); - pszPrefix = g_pGameRules->GetChatPrefix( teamonly, pPlayer ); - pszLocation = g_pGameRules->GetChatLocation( teamonly, pPlayer ); - } - - const char *pszPlayerName = pPlayer ? pPlayer->GetPlayerName():"Console"; - - if ( pszPrefix && strlen( pszPrefix ) > 0 ) - { - if ( pszLocation && strlen( pszLocation ) ) - { - Q_snprintf( text, sizeof(text), "%s %s @ %s: ", pszPrefix, pszPlayerName, pszLocation ); - } - else - { - Q_snprintf( text, sizeof(text), "%s %s: ", pszPrefix, pszPlayerName ); - } - } - else - { - Q_snprintf( text, sizeof(text), "%s: ", pszPlayerName ); - } - - j = sizeof(text) - 2 - strlen(text); // -2 for /n and null terminator - if ( (int)strlen(p) > j ) - p[j] = 0; - - Q_strncat( text, p, sizeof( text ), COPY_ALL_CHARACTERS ); - Q_strncat( text, "\n", sizeof( text ), COPY_ALL_CHARACTERS ); - - // loop through all players - // Start with the first player. - // This may return the world in single player if the client types something between levels or during spawn - // so check it, or it will infinite loop - - client = NULL; - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - client = ToBaseMultiplayerPlayer( UTIL_PlayerByIndex( i ) ); - if ( !client || !client->edict() ) - continue; - - if ( client->edict() == pEdict ) - continue; - - if ( !(client->IsNetClient()) ) // Not a client ? (should never be true) - continue; - - if ( teamonly && g_pGameRules->PlayerCanHearChat( client, pPlayer ) != GR_TEAMMATE ) - continue; - - if ( pPlayer && !client->CanHearAndReadChatFrom( pPlayer ) ) - continue; - - if ( pPlayer && GetVoiceGameMgr() && GetVoiceGameMgr()->IsPlayerIgnoringPlayer( pPlayer->entindex(), i ) ) - continue; - - CSingleUserRecipientFilter user( client ); - user.MakeReliable(); - - if ( pszFormat ) - { - UTIL_SayText2Filter( user, pPlayer, true, pszFormat, pszPlayerName, p, pszLocation ); - } - else - { - UTIL_SayTextFilter( user, text, pPlayer, true ); - } - } - - if ( pPlayer ) - { - // print to the sending client - CSingleUserRecipientFilter user( pPlayer ); - user.MakeReliable(); - - if ( pszFormat ) - { - UTIL_SayText2Filter( user, pPlayer, true, pszFormat, pszPlayerName, p, pszLocation ); - } - else - { - UTIL_SayTextFilter( user, text, pPlayer, true ); - } - } - - // echo to server console - // Adrian: Only do this if we're running a dedicated server since we already print to console on the client. - if ( engine->IsDedicatedServer() ) - Msg( "%s", text ); - - Assert( p ); - - int userid = 0; - const char *networkID = "Console"; - const char *playerName = "Console"; - const char *playerTeam = "Console"; - if ( pPlayer ) - { - userid = pPlayer->GetUserID(); - networkID = pPlayer->GetNetworkIDString(); - playerName = pPlayer->GetPlayerName(); - CTeam *team = pPlayer->GetTeam(); - if ( team ) - { - playerTeam = team->GetName(); - } - } - - if ( teamonly ) - UTIL_LogPrintf( "\"%s<%i><%s><%s>\" say_team \"%s\"\n", playerName, userid, networkID, playerTeam, p ); - else - UTIL_LogPrintf( "\"%s<%i><%s><%s>\" say \"%s\"\n", playerName, userid, networkID, playerTeam, p ); - - IGameEvent * event = gameeventmanager->CreateEvent( "player_say" ); - - if ( event ) // will be null if there are no listeners! - { - event->SetInt("userid", userid ); - event->SetString("text", p ); - event->SetInt("priority", 1 ); // HLTV event priority, not transmitted - gameeventmanager->FireEvent( event ); - } -} - - -void ClientPrecache( void ) -{ - // Precache cable textures. - CBaseEntity::PrecacheModel( "cable/cable.vmt" ); - CBaseEntity::PrecacheModel( "cable/cable_lit.vmt" ); - CBaseEntity::PrecacheModel( "cable/chain.vmt" ); - CBaseEntity::PrecacheModel( "cable/rope.vmt" ); - CBaseEntity::PrecacheModel( "sprites/blueglow1.vmt" ); - CBaseEntity::PrecacheModel( "sprites/purpleglow1.vmt" ); - CBaseEntity::PrecacheModel( "sprites/purplelaser1.vmt" ); - - CBaseEntity::PrecacheScriptSound( "Hud.Hint" ); - CBaseEntity::PrecacheScriptSound( "Player.FallDamage" ); - CBaseEntity::PrecacheScriptSound( "Player.Swim" ); - - // General HUD sounds - CBaseEntity::PrecacheScriptSound( "Player.PickupWeapon" ); - CBaseEntity::PrecacheScriptSound( "Player.DenyWeaponSelection" ); - CBaseEntity::PrecacheScriptSound( "Player.WeaponSelected" ); - CBaseEntity::PrecacheScriptSound( "Player.WeaponSelectionClose" ); - CBaseEntity::PrecacheScriptSound( "Player.WeaponSelectionMoveSlot" ); - - // General legacy temp ents sounds - CBaseEntity::PrecacheScriptSound( "Bounce.Glass" ); - CBaseEntity::PrecacheScriptSound( "Bounce.Metal" ); - CBaseEntity::PrecacheScriptSound( "Bounce.Flesh" ); - CBaseEntity::PrecacheScriptSound( "Bounce.Wood" ); - CBaseEntity::PrecacheScriptSound( "Bounce.Shrapnel" ); - CBaseEntity::PrecacheScriptSound( "Bounce.ShotgunShell" ); - CBaseEntity::PrecacheScriptSound( "Bounce.Shell" ); - CBaseEntity::PrecacheScriptSound( "Bounce.Concrete" ); - - ClientGamePrecache(); -} - -CON_COMMAND_F( cast_ray, "Tests collision detection", FCVAR_CHEAT ) -{ - CBasePlayer *pPlayer = UTIL_GetCommandClient(); - - Vector forward; - trace_t tr; - - pPlayer->EyeVectors( &forward ); - Vector start = pPlayer->EyePosition(); - UTIL_TraceLine(start, start + forward * MAX_COORD_RANGE, MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &tr ); - - if ( tr.DidHit() ) - { - DevMsg(1, "Hit %s\nposition %.2f, %.2f, %.2f\nangles %.2f, %.2f, %.2f\n", tr.m_pEnt->GetClassname(), - tr.m_pEnt->GetAbsOrigin().x, tr.m_pEnt->GetAbsOrigin().y, tr.m_pEnt->GetAbsOrigin().z, - tr.m_pEnt->GetAbsAngles().x, tr.m_pEnt->GetAbsAngles().y, tr.m_pEnt->GetAbsAngles().z ); - DevMsg(1, "Hit: hitbox %d, hitgroup %d, physics bone %d, solid %d, surface %s, surfaceprop %s\n", tr.hitbox, tr.hitgroup, tr.physicsbone, tr.m_pEnt->GetSolid(), tr.surface.name, physprops->GetPropName( tr.surface.surfaceProps ) ); - NDebugOverlay::Line( start, tr.endpos, 0, 255, 0, false, 10 ); - NDebugOverlay::Line( tr.endpos, tr.endpos + tr.plane.normal * 12, 255, 255, 0, false, 10 ); - } -} - -CON_COMMAND_F( cast_hull, "Tests hull collision detection", FCVAR_CHEAT ) -{ - CBasePlayer *pPlayer = UTIL_GetCommandClient(); - - Vector forward; - trace_t tr; - - Vector extents; - extents.Init(16,16,16); - pPlayer->EyeVectors( &forward ); - Vector start = pPlayer->EyePosition(); - UTIL_TraceHull(start, start + forward * MAX_COORD_RANGE, -extents, extents, MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &tr ); - if ( tr.DidHit() ) - { - DevMsg(1, "Hit %s\nposition %.2f, %.2f, %.2f\nangles %.2f, %.2f, %.2f\n", tr.m_pEnt->GetClassname(), - tr.m_pEnt->GetAbsOrigin().x, tr.m_pEnt->GetAbsOrigin().y, tr.m_pEnt->GetAbsOrigin().z, - tr.m_pEnt->GetAbsAngles().x, tr.m_pEnt->GetAbsAngles().y, tr.m_pEnt->GetAbsAngles().z ); - DevMsg(1, "Hit: hitbox %d, hitgroup %d, physics bone %d, solid %d, surface %s, surfaceprop %s\n", tr.hitbox, tr.hitgroup, tr.physicsbone, tr.m_pEnt->GetSolid(), tr.surface.name, physprops->GetPropName( tr.surface.surfaceProps ) ); - NDebugOverlay::SweptBox( start, tr.endpos, -extents, extents, vec3_angle, 0, 0, 255, 0, 10 ); - Vector end = tr.endpos;// - tr.plane.normal * DotProductAbs( tr.plane.normal, extents ); - NDebugOverlay::Line( end, end + tr.plane.normal * 24, 255, 255, 64, false, 10 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Used to find targets for ent_* commands -// Without a name, returns the entity under the player's crosshair. -// With a name it finds entities via name/classname/index -//----------------------------------------------------------------------------- -CBaseEntity *GetNextCommandEntity( CBasePlayer *pPlayer, const char *name, CBaseEntity *ent ) -{ - if ( !pPlayer ) - return NULL; - - // If no name was given set bits based on the picked - if (FStrEq(name,"")) - { - // If we've already found an entity, return NULL. - // Makes it easier to write code using this func. - if ( ent ) - return NULL; - - return FindPickerEntity( pPlayer ); - } - - int index = atoi( name ); - if ( index ) - { - // If we've already found an entity, return NULL. - // Makes it easier to write code using this func. - if ( ent ) - return NULL; - - return CBaseEntity::Instance( index ); - } - - // Loop through all entities matching, starting from the specified previous - while ( (ent = gEntList.NextEnt(ent)) != NULL ) - { - if ( (ent->GetEntityName() != NULL_STRING && ent->NameMatches(name)) || - (ent->m_iClassname != NULL_STRING && ent->ClassMatches(name)) ) - { - return ent; - } - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: called each time a player uses a "cmd" command -// Input : pPlayer - the player who issued the command -//----------------------------------------------------------------------------- -void SetDebugBits( CBasePlayer* pPlayer, const char *name, int bit ) -{ - if ( !pPlayer ) - return; - - CBaseEntity *pEntity = NULL; - while ( (pEntity = GetNextCommandEntity( pPlayer, name, pEntity )) != NULL ) - { - if (pEntity->m_debugOverlays & bit) - { - pEntity->m_debugOverlays &= ~bit; - } - else - { - pEntity->m_debugOverlays |= bit; - -#ifdef AI_MONITOR_FOR_OSCILLATION - if( pEntity->IsNPC() ) - { - pEntity->MyNPCPointer()->m_ScheduleHistory.RemoveAll(); - } -#endif//AI_MONITOR_FOR_OSCILLATION - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pKillTargetName - -//----------------------------------------------------------------------------- -void KillTargets( const char *pKillTargetName ) -{ - CBaseEntity *pentKillTarget = NULL; - - DevMsg( 2, "KillTarget: %s\n", pKillTargetName ); - pentKillTarget = gEntList.FindEntityByName( NULL, pKillTargetName ); - while ( pentKillTarget ) - { - UTIL_Remove( pentKillTarget ); - - DevMsg( 2, "killing %s\n", STRING( pentKillTarget->m_iClassname ) ); - pentKillTarget = gEntList.FindEntityByName( pentKillTarget, pKillTargetName ); - } -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void ConsoleKillTarget( CBasePlayer *pPlayer, const char *name ) -{ - // If no name was given use the picker - if (FStrEq(name,"")) - { - CBaseEntity *pEntity = FindPickerEntity( pPlayer ); - if ( pEntity ) - { - UTIL_Remove( pEntity ); - Msg( "killing %s\n", pEntity->GetDebugName() ); - return; - } - } - // Otherwise use name or classname - KillTargets( name ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CPointClientCommand : public CPointEntity -{ -public: - DECLARE_CLASS( CPointClientCommand, CPointEntity ); - DECLARE_DATADESC(); - - void InputCommand( inputdata_t& inputdata ); -}; - -void CPointClientCommand::InputCommand( inputdata_t& inputdata ) -{ - if ( !inputdata.value.String()[0] ) - return; - - edict_t *pClient = NULL; - if ( gpGlobals->maxClients == 1 ) - { - pClient = engine->PEntityOfEntIndex( 1 ); - } - else - { - // In multiplayer, send it back to the activator - CBasePlayer *player = dynamic_cast< CBasePlayer * >( inputdata.pActivator ); - if ( player ) - { - pClient = player->edict(); - } - - if ( IsInCommentaryMode() && !pClient ) - { - // Commentary is stuffing a command in. We'll pretend it came from the first player. - pClient = engine->PEntityOfEntIndex( 1 ); - } - } - - if ( !pClient || !pClient->GetUnknown() ) - return; - - engine->ClientCommand( pClient, UTIL_VarArgs( "%s\n", inputdata.value.String() ) ); -} - -BEGIN_DATADESC( CPointClientCommand ) - DEFINE_INPUTFUNC( FIELD_STRING, "Command", InputCommand ), -END_DATADESC() - -LINK_ENTITY_TO_CLASS( point_clientcommand, CPointClientCommand ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CPointServerCommand : public CPointEntity -{ -public: - DECLARE_CLASS( CPointServerCommand, CPointEntity ); - DECLARE_DATADESC(); - void InputCommand( inputdata_t& inputdata ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : inputdata - -//----------------------------------------------------------------------------- -void CPointServerCommand::InputCommand( inputdata_t& inputdata ) -{ - if ( !inputdata.value.String()[0] ) - return; - - engine->ServerCommand( UTIL_VarArgs( "%s\n", inputdata.value.String() ) ); -} - -BEGIN_DATADESC( CPointServerCommand ) - DEFINE_INPUTFUNC( FIELD_STRING, "Command", InputCommand ), -END_DATADESC() - -LINK_ENTITY_TO_CLASS( point_servercommand, CPointServerCommand ); - -//------------------------------------------------------------------------------ -// Purpose : Draw a line betwen two points. White if no world collisions, red if collisions -// Input : -// Output : -//------------------------------------------------------------------------------ -void CC_DrawLine( const CCommand &args ) -{ - Vector startPos; - Vector endPos; - - startPos.x = atof(args[1]); - startPos.y = atof(args[2]); - startPos.z = atof(args[3]); - endPos.x = atof(args[4]); - endPos.y = atof(args[5]); - endPos.z = atof(args[6]); - - UTIL_AddDebugLine(startPos,endPos,true,true); -} -static ConCommand drawline("drawline", CC_DrawLine, "Draws line between two 3D Points.\n\tGreen if no collision\n\tRed is collides with something\n\tArguments: x1 y1 z1 x2 y2 z2", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose : Draw a cross at a points. -// Input : -// Output : -//------------------------------------------------------------------------------ -void CC_DrawCross( const CCommand &args ) -{ - Vector vPosition; - - vPosition.x = atof(args[1]); - vPosition.y = atof(args[2]); - vPosition.z = atof(args[3]); - - // Offset since min and max z in not about center - Vector mins = Vector(-5,-5,-5); - Vector maxs = Vector(5,5,5); - - Vector start = mins + vPosition; - Vector end = maxs + vPosition; - UTIL_AddDebugLine(start,end,true,true); - - start.x += (maxs.x - mins.x); - end.x -= (maxs.x - mins.x); - UTIL_AddDebugLine(start,end,true,true); - - start.y += (maxs.y - mins.y); - end.y -= (maxs.y - mins.y); - UTIL_AddDebugLine(start,end,true,true); - - start.x -= (maxs.x - mins.x); - end.x += (maxs.x - mins.x); - UTIL_AddDebugLine(start,end,true,true); -} -static ConCommand drawcross("drawcross", CC_DrawCross, "Draws a cross at the given location\n\tArguments: x y z", FCVAR_CHEAT); - - -//------------------------------------------------------------------------------ -// helper function for kill and explode -//------------------------------------------------------------------------------ -void kill_helper( const CCommand &args, bool bExplode ) -{ - if ( args.ArgC() > 1 && sv_cheats->GetBool() ) - { - // Find the matching netname - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = ToBasePlayer( UTIL_PlayerByIndex(i) ); - if ( pPlayer ) - { - if ( Q_strstr( pPlayer->GetPlayerName(), args[1] ) ) - { - pPlayer->CommitSuicide( bExplode ); - } - } - } - } - else - { - CBasePlayer *pPlayer = UTIL_GetCommandClient(); - if ( pPlayer ) - { - pPlayer->CommitSuicide( bExplode ); - } - } -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -CON_COMMAND( kill, "Kills the player with generic damage" ) -{ - kill_helper( args, false ); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -CON_COMMAND( explode, "Kills the player with explosive damage" ) -{ - kill_helper( args, true ); -} - -//------------------------------------------------------------------------------ -// helper function for killvector and explodevector -//------------------------------------------------------------------------------ -void killvector_helper( const CCommand &args, bool bExplode ) -{ - CBasePlayer *pPlayer = UTIL_GetCommandClient(); - if ( pPlayer && args.ArgC() == 5 ) - { - // Find the matching netname. - for ( int iClient = 1; iClient <= gpGlobals->maxClients; iClient++ ) - { - CBasePlayer *pPlayer = ToBasePlayer( UTIL_PlayerByIndex( iClient ) ); - if ( pPlayer ) - { - if ( Q_strstr( pPlayer->GetPlayerName(), args[1] ) ) - { - // Build world-space force vector. - Vector vecForce; - vecForce.x = atof( args[2] ); - vecForce.y = atof( args[3] ); - vecForce.z = atof( args[4] ); - - ClientKill( pPlayer->edict(), vecForce, bExplode ); - } - } - } - } -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -CON_COMMAND_F( killvector, "Kills a player applying force. Usage: killvector ", FCVAR_CHEAT ) -{ - killvector_helper( args, false ); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -CON_COMMAND_F( explodevector, "Kills a player applying an explosive force. Usage: explodevector ", FCVAR_CHEAT ) -{ - killvector_helper( args, false ); -} - - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -CON_COMMAND_F( buddha, "Toggle. Player takes damage but won't die. (Shows red cross when health is zero)", FCVAR_CHEAT ) -{ - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - if ( pPlayer ) - { - if (pPlayer->m_debugOverlays & OVERLAY_BUDDHA_MODE) - { - pPlayer->m_debugOverlays &= ~OVERLAY_BUDDHA_MODE; - Msg("Buddha Mode off...\n"); - } - else - { - pPlayer->m_debugOverlays |= OVERLAY_BUDDHA_MODE; - Msg("Buddha Mode on...\n"); - } - } -} - - -#define TALK_INTERVAL 0.66 // min time between say commands from a client -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -CON_COMMAND( say, "Display player message" ) -{ - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - if ( pPlayer ) - { - if (( pPlayer->LastTimePlayerTalked() + TALK_INTERVAL ) < gpGlobals->curtime) - { - Host_Say( pPlayer->edict(), args, 0 ); - pPlayer->NotePlayerTalked(); - } - } - else - { - Host_Say( NULL, args, 0 ); - } -} - - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -CON_COMMAND( say_team, "Display player message to team" ) -{ - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - if (pPlayer) - { - if (( pPlayer->LastTimePlayerTalked() + TALK_INTERVAL ) < gpGlobals->curtime) - { - Host_Say( pPlayer->edict(), args, 1 ); - pPlayer->NotePlayerTalked(); - } - } -} - - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -CON_COMMAND( give, "Give item to player.\n\tArguments: " ) -{ - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - if ( pPlayer - && (gpGlobals->maxClients == 1 || sv_cheats->GetBool()) - && args.ArgC() >= 2 ) - { - char item_to_give[ 256 ]; - Q_strncpy( item_to_give, args[1], sizeof( item_to_give ) ); - Q_strlower( item_to_give ); - - // Dirty hack to avoid suit playing it's pickup sound - if ( !Q_stricmp( item_to_give, "item_suit" ) ) - { - pPlayer->EquipSuit( false ); - return; - } - - string_t iszItem = AllocPooledString( item_to_give ); // Make a copy of the classname - pPlayer->GiveNamedItem( STRING(iszItem) ); - } -} - - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -CON_COMMAND( fov, "Change players FOV" ) -{ - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - if ( pPlayer && sv_cheats->GetBool() ) - { - if ( args.ArgC() > 1 ) - { - int nFOV = atoi( args[1] ); - pPlayer->SetDefaultFOV( nFOV ); - } - else - { - ClientPrint( pPlayer, HUD_PRINTCONSOLE, UTIL_VarArgs( "\"fov\" is \"%d\"\n", pPlayer->GetFOV() ) ); - } - } -} - - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CC_Player_SetModel( const CCommand &args ) -{ - if ( gpGlobals->deathmatch ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - if ( pPlayer && args.ArgC() == 2) - { - static char szName[256]; - Q_snprintf( szName, sizeof( szName ), "models/%s.mdl", args[1] ); - pPlayer->SetModel( szName ); - UTIL_SetSize(pPlayer, VEC_HULL_MIN, VEC_HULL_MAX); - } -} -static ConCommand setmodel("setmodel", CC_Player_SetModel, "Changes's player's model", FCVAR_CHEAT ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CC_Player_TestDispatchEffect( const CCommand &args ) -{ - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - if ( !pPlayer) - return; - - if ( args.ArgC() < 2 ) - { - Msg(" Usage: test_dispatcheffect \n " ); - Msg(" defaults are: \n" ); - return; - } - - // Optional distance - float flDistance = 1024; - if ( args.ArgC() >= 3 ) - { - flDistance = atoi( args[ 2 ] ); - } - - // Optional flags - float flags = 0; - if ( args.ArgC() >= 4 ) - { - flags = atoi( args[ 3 ] ); - } - - // Optional magnitude - float magnitude = 0; - if ( args.ArgC() >= 5 ) - { - magnitude = atof( args[ 4 ] ); - } - - // Optional scale - float scale = 0; - if ( args.ArgC() >= 6 ) - { - scale = atof( args[ 5 ] ); - } - - Vector vecForward; - QAngle vecAngles = pPlayer->EyeAngles(); - AngleVectors( vecAngles, &vecForward ); - - // Trace forward - trace_t tr; - Vector vecSrc = pPlayer->EyePosition(); - Vector vecEnd = vecSrc + (vecForward * flDistance); - UTIL_TraceLine( vecSrc, vecEnd, MASK_ALL, pPlayer, COLLISION_GROUP_NONE, &tr ); - - // Fill out the generic data - CEffectData data; - // If we hit something, use that data - if ( tr.fraction < 1.0 ) - { - data.m_vOrigin = tr.endpos; - VectorAngles( tr.plane.normal, data.m_vAngles ); - data.m_vNormal = tr.plane.normal; - } - else - { - data.m_vOrigin = vecEnd; - data.m_vAngles = vecAngles; - AngleVectors( vecAngles, &data.m_vNormal ); - } - data.m_nEntIndex = pPlayer->entindex(); - data.m_fFlags = (int)flags; - data.m_flMagnitude = magnitude; - data.m_flScale = scale; - DispatchEffect( (char *)args[1], data ); -} - -static ConCommand test_dispatcheffect("test_dispatcheffect", CC_Player_TestDispatchEffect, "Test a clientside dispatch effect.\n\tUsage: test_dispatcheffect \n\tDefaults are: \n", FCVAR_CHEAT); - -#ifdef HL2_DLL -//----------------------------------------------------------------------------- -// Purpose: Quickly switch to the physics cannon, or back to previous item -//----------------------------------------------------------------------------- -void CC_Player_PhysSwap( void ) -{ - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - - if ( pPlayer ) - { - CBaseCombatWeapon *pWeapon = pPlayer->GetActiveWeapon(); - - if ( pWeapon ) - { - // Tell the client to stop selecting weapons - engine->ClientCommand( UTIL_GetCommandClient()->edict(), "cancelselect" ); - - const char *strWeaponName = pWeapon->GetName(); - - if ( !Q_stricmp( strWeaponName, "weapon_physcannon" ) ) - { - PhysCannonForceDrop( pWeapon, NULL ); - pPlayer->SelectLastItem(); - } - else - { - pPlayer->SelectItem( "weapon_physcannon" ); - } - } - } -} -static ConCommand physswap("phys_swap", CC_Player_PhysSwap, "Automatically swaps the current weapon for the physcannon and back again." ); -#endif - -//----------------------------------------------------------------------------- -// Purpose: Quickly switch to the bug bait, or back to previous item -//----------------------------------------------------------------------------- -void CC_Player_BugBaitSwap( void ) -{ - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - - if ( pPlayer ) - { - CBaseCombatWeapon *pWeapon = pPlayer->GetActiveWeapon(); - - if ( pWeapon ) - { - // Tell the client to stop selecting weapons - engine->ClientCommand( UTIL_GetCommandClient()->edict(), "cancelselect" ); - - const char *strWeaponName = pWeapon->GetName(); - - if ( !Q_stricmp( strWeaponName, "weapon_bugbait" ) ) - { - pPlayer->SelectLastItem(); - } - else - { - pPlayer->SelectItem( "weapon_bugbait" ); - } - } - } -} -static ConCommand bugswap("bug_swap", CC_Player_BugBaitSwap, "Automatically swaps the current weapon for the bug bait and back again.", FCVAR_CHEAT ); - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CC_Player_Use( const CCommand &args ) -{ - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - if ( pPlayer) - { - pPlayer->SelectItem((char *)args[1]); - } -} -static ConCommand use("use", CC_Player_Use, "Use a particular weapon\t\nArguments: "); - - -//------------------------------------------------------------------------------ -// A small wrapper around SV_Move that never clips against the supplied entity. -//------------------------------------------------------------------------------ -static bool TestEntityPosition ( CBasePlayer *pPlayer ) -{ - trace_t trace; - UTIL_TraceEntity( pPlayer, pPlayer->GetAbsOrigin(), pPlayer->GetAbsOrigin(), MASK_PLAYERSOLID, &trace ); - return (trace.startsolid == 0); -} - - -//------------------------------------------------------------------------------ -// Searches along the direction ray in steps of "step" to see if -// the entity position is passible. -// Used for putting the player in valid space when toggling off noclip mode. -//------------------------------------------------------------------------------ -static int FindPassableSpace( CBasePlayer *pPlayer, const Vector& direction, float step, Vector& oldorigin ) -{ - int i; - for ( i = 0; i < 100; i++ ) - { - Vector origin = pPlayer->GetAbsOrigin(); - VectorMA( origin, step, direction, origin ); - pPlayer->SetAbsOrigin( origin ); - if ( TestEntityPosition( pPlayer ) ) - { - VectorCopy( pPlayer->GetAbsOrigin(), oldorigin ); - return 1; - } - } - return 0; -} - - -//------------------------------------------------------------------------------ -// Noclip -//------------------------------------------------------------------------------ -static void EnableNoClip( CBasePlayer *pPlayer ) -{ - // Disengage from hierarchy - pPlayer->SetParent( NULL ); - pPlayer->SetMoveType( MOVETYPE_NOCLIP ); - ClientPrint( pPlayer, HUD_PRINTCONSOLE, "noclip ON\n"); - pPlayer->AddEFlags( EFL_NOCLIP_ACTIVE ); -} - -void CC_Player_NoClip( void ) -{ - if ( !sv_cheats->GetBool() ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - if ( !pPlayer ) - return; - - CPlayerState *pl = pPlayer->PlayerData(); - Assert( pl ); - - if (pPlayer->GetMoveType() != MOVETYPE_NOCLIP) - { - EnableNoClip( pPlayer ); - return; - } - - pPlayer->RemoveEFlags( EFL_NOCLIP_ACTIVE ); - pPlayer->SetMoveType( MOVETYPE_WALK ); - - Vector oldorigin = pPlayer->GetAbsOrigin(); - ClientPrint( pPlayer, HUD_PRINTCONSOLE, "noclip OFF\n"); - if ( !TestEntityPosition( pPlayer ) ) - { - Vector forward, right, up; - - AngleVectors ( pl->v_angle, &forward, &right, &up); - - // Try to move into the world - if ( !FindPassableSpace( pPlayer, forward, 1, oldorigin ) ) - { - if ( !FindPassableSpace( pPlayer, right, 1, oldorigin ) ) - { - if ( !FindPassableSpace( pPlayer, right, -1, oldorigin ) ) // left - { - if ( !FindPassableSpace( pPlayer, up, 1, oldorigin ) ) // up - { - if ( !FindPassableSpace( pPlayer, up, -1, oldorigin ) ) // down - { - if ( !FindPassableSpace( pPlayer, forward, -1, oldorigin ) ) // back - { - Msg( "Can't find the world\n" ); - } - } - } - } - } - } - - pPlayer->SetAbsOrigin( oldorigin ); - } -} - -static ConCommand noclip("noclip", CC_Player_NoClip, "Toggle. Player becomes non-solid and flies.", FCVAR_CHEAT); - - -//------------------------------------------------------------------------------ -// Sets client to godmode -//------------------------------------------------------------------------------ -void CC_God_f (void) -{ - if ( !sv_cheats->GetBool() ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - if ( !pPlayer ) - return; - - if ( gpGlobals->deathmatch ) - return; - - pPlayer->ToggleFlag( FL_GODMODE ); - if (!(pPlayer->GetFlags() & FL_GODMODE ) ) - ClientPrint( pPlayer, HUD_PRINTCONSOLE, "godmode OFF\n"); - else - ClientPrint( pPlayer, HUD_PRINTCONSOLE, "godmode ON\n"); -} - -static ConCommand god("god", CC_God_f, "Toggle. Player becomes invulnerable.", FCVAR_CHEAT ); - - -//------------------------------------------------------------------------------ -// Sets client to godmode -//------------------------------------------------------------------------------ -CON_COMMAND_F( setpos, "Move player to specified origin (must have sv_cheats).", FCVAR_CHEAT ) -{ - if ( !sv_cheats->GetBool() ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - if ( !pPlayer ) - return; - - if ( args.ArgC() < 3 ) - { - ClientPrint( pPlayer, HUD_PRINTCONSOLE, "Usage: setpos x y \n"); - return; - } - - Vector oldorigin = pPlayer->GetAbsOrigin(); - - Vector newpos; - newpos.x = atof( args[1] ); - newpos.y = atof( args[2] ); - newpos.z = args.ArgC() == 4 ? atof( args[3] ) : oldorigin.z; - - pPlayer->SetAbsOrigin( newpos ); - - if ( !TestEntityPosition( pPlayer ) ) - { - ClientPrint( pPlayer, HUD_PRINTCONSOLE, "setpos into world, use noclip to unstick yourself!\n"); - } -} - - -//------------------------------------------------------------------------------ -// Sets client to godmode -//------------------------------------------------------------------------------ -void CC_setang_f (const CCommand &args) -{ - if ( !sv_cheats->GetBool() ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - if ( !pPlayer ) - return; - - if ( args.ArgC() < 3 ) - { - ClientPrint( pPlayer, HUD_PRINTCONSOLE, "Usage: setang pitch yaw \n"); - return; - } - - QAngle oldang = pPlayer->GetAbsAngles(); - - QAngle newang; - newang.x = atof( args[1] ); - newang.y = atof( args[2] ); - newang.z = args.ArgC() == 4 ? atof( args[3] ) : oldang.z; - - pPlayer->SnapEyeAngles( newang ); -} - -static ConCommand setang("setang", CC_setang_f, "Snap player eyes to specified pitch yaw (must have sv_cheats).", FCVAR_CHEAT ); - - -//------------------------------------------------------------------------------ -// Move position -//------------------------------------------------------------------------------ -CON_COMMAND_F( setpos_exact, "Move player to an exact specified origin (must have sv_cheats).", FCVAR_CHEAT ) -{ - if ( !sv_cheats->GetBool() ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - if ( !pPlayer ) - return; - - if ( args.ArgC() < 3 ) - { - ClientPrint( pPlayer, HUD_PRINTCONSOLE, "Usage: setpos_exact x y \n"); - return; - } - - Vector oldorigin = pPlayer->GetAbsOrigin(); - - Vector newpos; - newpos.x = atof( args[1] ); - newpos.y = atof( args[2] ); - newpos.z = args.ArgC() == 4 ? atof( args[3] ) : oldorigin.z; - - pPlayer->Teleport( &newpos, NULL, NULL ); - - if ( !TestEntityPosition( pPlayer ) ) - { - if ( pPlayer->GetMoveType() != MOVETYPE_NOCLIP ) - { - EnableNoClip( pPlayer ); - return; - } - } -} - -CON_COMMAND_F( setang_exact, "Snap player eyes and orientation to specified pitch yaw (must have sv_cheats).", FCVAR_CHEAT ) -{ - if ( !sv_cheats->GetBool() ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - if ( !pPlayer ) - return; - - if ( args.ArgC() < 3 ) - { - ClientPrint( pPlayer, HUD_PRINTCONSOLE, "Usage: setang_exact pitch yaw \n"); - return; - } - - QAngle oldang = pPlayer->GetAbsAngles(); - - QAngle newang; - newang.x = atof( args[1] ); - newang.y = atof( args[2] ); - newang.z = args.ArgC() == 4 ? atof( args[3] ) : oldang.z; - - pPlayer->Teleport( NULL, &newang, NULL ); - pPlayer->SnapEyeAngles( newang ); - -#ifdef TF_DLL - static_cast( pPlayer )->DoAnimationEvent( PLAYERANIMEVENT_SNAP_YAW ); -#endif -} - - -//------------------------------------------------------------------------------ -// Sets client to notarget mode. -//------------------------------------------------------------------------------ -void CC_Notarget_f (void) -{ - if ( !sv_cheats->GetBool() ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - if ( !pPlayer ) - return; - - if ( gpGlobals->deathmatch ) - return; - - pPlayer->ToggleFlag( FL_NOTARGET ); - if ( !(pPlayer->GetFlags() & FL_NOTARGET ) ) - ClientPrint( pPlayer, HUD_PRINTCONSOLE, "notarget OFF\n"); - else - ClientPrint( pPlayer, HUD_PRINTCONSOLE, "notarget ON\n"); -} - -ConCommand notarget("notarget", CC_Notarget_f, "Toggle. Player becomes hidden to NPCs.", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Damage the client the specified amount -//------------------------------------------------------------------------------ -void CC_HurtMe_f(const CCommand &args) -{ - if ( !sv_cheats->GetBool() ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - if ( !pPlayer ) - return; - - int iDamage = 10; - if ( args.ArgC() >= 2 ) - { - iDamage = atoi( args[ 1 ] ); - } - - pPlayer->TakeDamage( CTakeDamageInfo( pPlayer, pPlayer, iDamage, DMG_GENERIC ) ); -} - -static ConCommand hurtme("hurtme", CC_HurtMe_f, "Hurts the player.\n\tArguments: ", FCVAR_CHEAT); - -#ifdef _DEBUG -static bool IsInGroundList( CBaseEntity *ent, CBaseEntity *ground ) -{ - if ( !ground || !ent ) - return false; - - groundlink_t *root = ( groundlink_t * )ground->GetDataObject( GROUNDLINK ); - if ( root ) - { - groundlink_t *link = root->nextLink; - while ( link != root ) - { - CBaseEntity *other = link->entity; - if ( other == ent ) - return true; - link = link->nextLink; - } - } - - return false; - -} -#endif - -static int DescribeGroundList( CBaseEntity *ent ) -{ - if ( !ent ) - return 0; - - int c = 1; - - Msg( "%i : %s (ground %i %s)\n", ent->entindex(), ent->GetClassname(), - ent->GetGroundEntity() ? ent->GetGroundEntity()->entindex() : -1, - ent->GetGroundEntity() ? ent->GetGroundEntity()->GetClassname() : "NULL" ); - groundlink_t *root = ( groundlink_t * )ent->GetDataObject( GROUNDLINK ); - if ( root ) - { - groundlink_t *link = root->nextLink; - while ( link != root ) - { - CBaseEntity *other = link->entity; - if ( other ) - { - Msg( " %02i: %i %s\n", c++, other->entindex(), other->GetClassname() ); - - if ( other->GetGroundEntity() != ent ) - { - Assert( 0 ); - Msg( " mismatched!!!\n" ); - } - } - else - { - Assert( 0 ); - Msg( " %02i: NULL link\n", c++ ); - } - link = link->nextLink; - } - } - - if ( ent->GetGroundEntity() != NULL ) - { - Assert( IsInGroundList( ent, ent->GetGroundEntity() ) ); - } - - return c - 1; -} - -void CC_GroundList_f(const CCommand &args) -{ - if ( args.ArgC() == 2 ) - { - int idx = atoi( args[1] ); - - CBaseEntity *ground = CBaseEntity::Instance( idx ); - if ( ground ) - { - DescribeGroundList( ground ); - } - } - else - { - CBaseEntity *ent = NULL; - int linkCount = 0; - while ( (ent = gEntList.NextEnt(ent)) != NULL ) - { - linkCount += DescribeGroundList( ent ); - } - - extern int groundlinksallocated; - Assert( linkCount == groundlinksallocated ); - - Msg( "--- %i links\n", groundlinksallocated ); - } -} - -static ConCommand groundlist("groundlist", CC_GroundList_f, "Display ground entity list " ); - -//----------------------------------------------------------------------------- -// Purpose: called each time a player uses a "cmd" command -// Input : *pEdict - the player who issued the command -//----------------------------------------------------------------------------- -void ClientCommand( CBasePlayer *pPlayer, const CCommand &args ) -{ - const char *pCmd = args[0]; - - // Is the client spawned yet? - if ( !pPlayer ) - return; - - MDLCACHE_CRITICAL_SECTION(); - - /* - const char *pstr; - - if (((pstr = strstr(pcmd, "weapon_")) != NULL) && (pstr == pcmd)) - { - // Subtype may be specified - if ( args.ArgC() == 2 ) - { - pPlayer->SelectItem( pcmd, atoi( args[1] ) ); - } - else - { - pPlayer->SelectItem(pcmd); - } - } - */ - - if ( FStrEq( pCmd, "killtarget" ) ) - { - if ( g_pDeveloper->GetBool() && sv_cheats->GetBool() && UTIL_IsCommandIssuedByServerAdmin() ) - { - ConsoleKillTarget( pPlayer, args[1] ); - } - } - else if ( FStrEq( pCmd, "demorestart" ) ) - { - pPlayer->ForceClientDllUpdate(); - } - else if ( FStrEq( pCmd, "fade" ) ) - { - color32 black = {32,63,100,200}; - UTIL_ScreenFade( pPlayer, black, 3, 3, FFADE_OUT ); - } - else if ( FStrEq( pCmd, "te" ) ) - { - if ( sv_cheats->GetBool() && UTIL_IsCommandIssuedByServerAdmin() ) - { - if ( FStrEq( args[1], "stop" ) ) - { - // Destroy it - // - CBaseEntity *ent = gEntList.FindEntityByClassname( NULL, "te_tester" ); - while ( ent ) - { - CBaseEntity *next = gEntList.FindEntityByClassname( ent, "te_tester" ); - UTIL_Remove( ent ); - ent = next; - } - } - else - { - CTempEntTester::Create( pPlayer->WorldSpaceCenter(), pPlayer->EyeAngles(), args[1], args[2] ); - } - } - } - else - { - if ( !g_pGameRules->ClientCommand( pPlayer, args ) ) - { - if ( Q_strlen( pCmd ) > 128 ) - { - ClientPrint( pPlayer, HUD_PRINTCONSOLE, "Console command too long.\n" ); - } - else - { - // tell the user they entered an unknown command - ClientPrint( pPlayer, HUD_PRINTCONSOLE, UTIL_VarArgs( "Unknown command: %s\n", pCmd ) ); - } - } - } -} diff --git a/game/server/client.h b/game/server/client.h deleted file mode 100644 index 582c40927..000000000 --- a/game/server/client.h +++ /dev/null @@ -1,32 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef CLIENT_H -#define CLIENT_H - -#ifdef _WIN32 -#pragma once -#endif - - -class CCommand; -class CUserCmd; -class CBasePlayer; - - -void ClientActive( edict_t *pEdict, bool bLoadGame ); -void ClientPutInServer( edict_t *pEdict, const char *playername ); -void ClientCommand( CBasePlayer *pSender, const CCommand &args ); -void ClientPrecache( void ); -// Game specific precaches -void ClientGamePrecache( void ); -const char *GetGameDescription( void ); -void Host_Say( edict_t *pEdict, bool teamonly ); - - - -#endif // CLIENT_H diff --git a/game/server/colorcorrection.cpp b/game/server/colorcorrection.cpp deleted file mode 100644 index 044653af2..000000000 --- a/game/server/colorcorrection.cpp +++ /dev/null @@ -1,314 +0,0 @@ -//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: Color correction entity. -// -// $NoKeywords: $ -//===========================================================================// - -#include - -#include "cbase.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define COLOR_CORRECTION_ENT_THINK_RATE TICK_INTERVAL - -static const char *s_pFadeInContextThink = "ColorCorrectionFadeInThink"; -static const char *s_pFadeOutContextThink = "ColorCorrectionFadeOutThink"; - -//------------------------------------------------------------------------------ -// FIXME: This really should inherit from something more lightweight -//------------------------------------------------------------------------------ - - -//------------------------------------------------------------------------------ -// Purpose : Shadow control entity -//------------------------------------------------------------------------------ -class CColorCorrection : public CBaseEntity -{ - DECLARE_CLASS( CColorCorrection, CBaseEntity ); -public: - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - CColorCorrection(); - - void Spawn( void ); - int UpdateTransmitState(); - void Activate( void ); - - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } - - // Inputs - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - void InputSetFadeInDuration ( inputdata_t &inputdata ); - void InputSetFadeOutDuration ( inputdata_t &inputdata ); - -private: - void FadeIn ( void ); - void FadeOut ( void ); - - void FadeInThink( void ); // Fades lookup weight from Cur->MaxWeight - void FadeOutThink( void ); // Fades lookup weight from CurWeight->0.0 - - - - float m_flFadeInDuration; // Duration for a full 0->MaxWeight transition - float m_flFadeOutDuration; // Duration for a full Max->0 transition - float m_flStartFadeInWeight; - float m_flStartFadeOutWeight; - float m_flTimeStartFadeIn; - float m_flTimeStartFadeOut; - - float m_flMaxWeight; - - bool m_bStartDisabled; - CNetworkVar( bool, m_bEnabled ); - - CNetworkVar( float, m_MinFalloff ); - CNetworkVar( float, m_MaxFalloff ); - CNetworkVar( float, m_flCurWeight ); - CNetworkString( m_netlookupFilename, MAX_PATH ); - - string_t m_lookupFilename; -}; - -LINK_ENTITY_TO_CLASS(color_correction, CColorCorrection); - -BEGIN_DATADESC( CColorCorrection ) - - DEFINE_THINKFUNC( FadeInThink ), - DEFINE_THINKFUNC( FadeOutThink ), - - DEFINE_FIELD( m_flCurWeight, FIELD_FLOAT ), - DEFINE_FIELD( m_flTimeStartFadeIn, FIELD_FLOAT ), - DEFINE_FIELD( m_flTimeStartFadeOut, FIELD_FLOAT ), - DEFINE_FIELD( m_flStartFadeInWeight, FIELD_FLOAT ), - DEFINE_FIELD( m_flStartFadeOutWeight, FIELD_FLOAT ), - - DEFINE_KEYFIELD( m_MinFalloff, FIELD_FLOAT, "minfalloff" ), - DEFINE_KEYFIELD( m_MaxFalloff, FIELD_FLOAT, "maxfalloff" ), - DEFINE_KEYFIELD( m_flMaxWeight, FIELD_FLOAT, "maxweight" ), - DEFINE_KEYFIELD( m_flFadeInDuration, FIELD_FLOAT, "fadeInDuration" ), - DEFINE_KEYFIELD( m_flFadeOutDuration, FIELD_FLOAT, "fadeOutDuration" ), - DEFINE_KEYFIELD( m_lookupFilename, FIELD_STRING, "filename" ), - - DEFINE_KEYFIELD( m_bEnabled, FIELD_BOOLEAN, "enabled" ), - DEFINE_KEYFIELD( m_bStartDisabled, FIELD_BOOLEAN, "StartDisabled" ), -// DEFINE_ARRAY( m_netlookupFilename, FIELD_CHARACTER, MAX_PATH ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFadeInDuration", InputSetFadeInDuration ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFadeOutDuration", InputSetFadeOutDuration ), - -END_DATADESC() - -extern void SendProxy_Origin( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); -IMPLEMENT_SERVERCLASS_ST_NOBASE(CColorCorrection, DT_ColorCorrection) - SendPropVector( SENDINFO(m_vecOrigin), -1, SPROP_NOSCALE, 0.0f, HIGH_DEFAULT, SendProxy_Origin ), - SendPropFloat( SENDINFO(m_MinFalloff) ), - SendPropFloat( SENDINFO(m_MaxFalloff) ), - SendPropFloat( SENDINFO(m_flCurWeight) ), - SendPropString( SENDINFO(m_netlookupFilename) ), - SendPropBool( SENDINFO(m_bEnabled) ), -END_SEND_TABLE() - - -CColorCorrection::CColorCorrection() : BaseClass() -{ - m_bEnabled = true; - m_MinFalloff = 0.0f; - m_MaxFalloff = 1000.0f; - m_flMaxWeight = 1.0f; - m_flCurWeight.Set( 0.0f ); - m_flFadeInDuration = 0.0f; - m_flFadeOutDuration = 0.0f; - m_flStartFadeInWeight = 0.0f; - m_flStartFadeOutWeight = 0.0f; - m_flTimeStartFadeIn = 0.0f; - m_flTimeStartFadeOut = 0.0f; - m_netlookupFilename.GetForModify()[0] = 0; - m_lookupFilename = NULL_STRING; -} - - -//------------------------------------------------------------------------------ -// Purpose : Send even though we don't have a model -//------------------------------------------------------------------------------ -int CColorCorrection::UpdateTransmitState() -{ - // ALWAYS transmit to all clients. - return SetTransmitState( FL_EDICT_ALWAYS ); -} - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CColorCorrection::Spawn( void ) -{ - AddEFlags( EFL_FORCE_CHECK_TRANSMIT | EFL_DIRTY_ABSTRANSFORM ); - Precache(); - SetSolid( SOLID_NONE ); - - // To fade in/out the weight. - SetContextThink( &CColorCorrection::FadeInThink, TICK_NEVER_THINK, s_pFadeInContextThink ); - SetContextThink( &CColorCorrection::FadeOutThink, TICK_NEVER_THINK, s_pFadeOutContextThink ); - - if( m_bStartDisabled ) - { - m_bEnabled = false; - m_flCurWeight.Set ( 0.0f ); - } - else - { - m_bEnabled = true; - m_flCurWeight.Set ( 1.0f ); - } - - BaseClass::Spawn(); -} - -void CColorCorrection::Activate( void ) -{ - BaseClass::Activate(); - - Q_strncpy( m_netlookupFilename.GetForModify(), STRING( m_lookupFilename ), MAX_PATH ); -} - -//----------------------------------------------------------------------------- -// Purpose: Sets up internal vars needed for fade in lerping -//----------------------------------------------------------------------------- -void CColorCorrection::FadeIn ( void ) -{ - m_bEnabled = true; - m_flTimeStartFadeIn = gpGlobals->curtime; - m_flStartFadeInWeight = m_flCurWeight; - SetNextThink ( gpGlobals->curtime + COLOR_CORRECTION_ENT_THINK_RATE, s_pFadeInContextThink ); -} - -//----------------------------------------------------------------------------- -// Purpose: Sets up internal vars needed for fade out lerping -//----------------------------------------------------------------------------- -void CColorCorrection::FadeOut ( void ) -{ - m_bEnabled = false; - m_flTimeStartFadeOut = gpGlobals->curtime; - m_flStartFadeOutWeight = m_flCurWeight; - SetNextThink ( gpGlobals->curtime + COLOR_CORRECTION_ENT_THINK_RATE, s_pFadeOutContextThink ); -} - -//----------------------------------------------------------------------------- -// Purpose: Fades lookup weight from CurWeight->MaxWeight -//----------------------------------------------------------------------------- -void CColorCorrection::FadeInThink( void ) -{ - // Check for conditions where we shouldnt fade in - if ( m_flFadeInDuration <= 0 || // not set to fade in - m_flCurWeight >= m_flMaxWeight || // already past max weight - !m_bEnabled || // fade in/out mutex - m_flMaxWeight == 0.0f || // min==max - m_flStartFadeInWeight >= m_flMaxWeight ) // already at max weight - { - SetNextThink ( TICK_NEVER_THINK, s_pFadeInContextThink ); - return; - } - - // If we started fading in without fully fading out, use a truncated duration - float flTimeToFade = m_flFadeInDuration; - if ( m_flStartFadeInWeight > 0.0f ) - { - float flWeightRatio = m_flStartFadeInWeight / m_flMaxWeight; - flWeightRatio = clamp ( flWeightRatio, 0.0f, 0.99f ); - flTimeToFade = m_flFadeInDuration * (1.0 - flWeightRatio); - } - - Assert ( flTimeToFade > 0.0f ); - float flFadeRatio = (gpGlobals->curtime - m_flTimeStartFadeIn) / flTimeToFade; - flFadeRatio = clamp ( flFadeRatio, 0.0f, 1.0f ); - m_flStartFadeInWeight = clamp ( m_flStartFadeInWeight, 0.0f, 1.0f ); - - m_flCurWeight = Lerp( flFadeRatio, m_flStartFadeInWeight, m_flMaxWeight ); - - SetNextThink( gpGlobals->curtime + COLOR_CORRECTION_ENT_THINK_RATE, s_pFadeInContextThink ); -} - -//----------------------------------------------------------------------------- -// Purpose: Fades lookup weight from CurWeight->0.0 -//----------------------------------------------------------------------------- -void CColorCorrection::FadeOutThink( void ) -{ - // Check for conditions where we shouldn't fade out - if ( m_flFadeOutDuration <= 0 || // not set to fade out - m_flCurWeight <= 0.0f || // already faded out - m_bEnabled || // fade in/out mutex - m_flMaxWeight == 0.0f || // min==max - m_flStartFadeOutWeight <= 0.0f )// already at min weight - { - SetNextThink ( TICK_NEVER_THINK, s_pFadeOutContextThink ); - return; - } - - // If we started fading out without fully fading in, use a truncated duration - float flTimeToFade = m_flFadeOutDuration; - if ( m_flStartFadeOutWeight < m_flMaxWeight ) - { - float flWeightRatio = m_flStartFadeOutWeight / m_flMaxWeight; - flWeightRatio = clamp ( flWeightRatio, 0.01f, 1.0f ); - flTimeToFade = m_flFadeOutDuration * flWeightRatio; - } - - Assert ( flTimeToFade > 0.0f ); - float flFadeRatio = (gpGlobals->curtime - m_flTimeStartFadeOut) / flTimeToFade; - flFadeRatio = clamp ( flFadeRatio, 0.0f, 1.0f ); - m_flStartFadeOutWeight = clamp ( m_flStartFadeOutWeight, 0.0f, 1.0f ); - - m_flCurWeight = Lerp( 1.0f - flFadeRatio, 0.0f, m_flStartFadeOutWeight ); - - SetNextThink( gpGlobals->curtime + COLOR_CORRECTION_ENT_THINK_RATE, s_pFadeOutContextThink ); -} - -//------------------------------------------------------------------------------ -// Purpose : Input handlers -//------------------------------------------------------------------------------ -void CColorCorrection::InputEnable( inputdata_t &inputdata ) -{ - m_bEnabled = true; - - if ( m_flFadeInDuration > 0.0f ) - { - FadeIn(); - } - else - { - m_flCurWeight = m_flMaxWeight; - } - -} - -void CColorCorrection::InputDisable( inputdata_t &inputdata ) -{ - m_bEnabled = false; - - if ( m_flFadeOutDuration > 0.0f ) - { - FadeOut(); - } - else - { - m_flCurWeight = 0.0f; - } - -} - -void CColorCorrection::InputSetFadeInDuration( inputdata_t& inputdata ) -{ - m_flFadeInDuration = inputdata.value.Float(); -} - -void CColorCorrection::InputSetFadeOutDuration( inputdata_t& inputdata ) -{ - m_flFadeOutDuration = inputdata.value.Float(); -} diff --git a/game/server/colorcorrectionvolume.cpp b/game/server/colorcorrectionvolume.cpp deleted file mode 100644 index fac4b7b39..000000000 --- a/game/server/colorcorrectionvolume.cpp +++ /dev/null @@ -1,236 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Color correction entity. -// -// $NoKeywords: $ -//=============================================================================// - -#include - -#include "cbase.h" -#include "triggers.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//------------------------------------------------------------------------------ -// FIXME: This really should inherit from something more lightweight -//------------------------------------------------------------------------------ - - -//------------------------------------------------------------------------------ -// Purpose : Shadow control entity -//------------------------------------------------------------------------------ -class CColorCorrectionVolume : public CBaseTrigger -{ - DECLARE_CLASS( CColorCorrectionVolume, CBaseTrigger ); -public: - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - CColorCorrectionVolume(); - - void Spawn( void ); - bool KeyValue( const char *szKeyName, const char *szValue ); - int UpdateTransmitState(); - - void ThinkFunc(); - - virtual bool PassesTriggerFilters(CBaseEntity *pOther); - virtual void StartTouch( CBaseEntity *pEntity ); - virtual void EndTouch( CBaseEntity *pEntity ); - - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } - - // Inputs - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - -private: - - bool m_bEnabled; - bool m_bStartDisabled; - - CNetworkVar( float, m_Weight ); - CNetworkVar( float, m_MaxWeight ); - CNetworkString( m_lookupFilename, MAX_PATH ); - - float m_LastEnterWeight; - float m_LastEnterTime; - - float m_LastExitWeight; - float m_LastExitTime; - - float m_FadeDuration; -}; - -LINK_ENTITY_TO_CLASS(color_correction_volume, CColorCorrectionVolume); - -BEGIN_DATADESC( CColorCorrectionVolume ) - - DEFINE_THINKFUNC( ThinkFunc ), - - DEFINE_KEYFIELD( m_FadeDuration, FIELD_FLOAT, "fadeDuration" ), - DEFINE_KEYFIELD( m_MaxWeight, FIELD_FLOAT, "maxweight" ), - DEFINE_AUTO_ARRAY_KEYFIELD( m_lookupFilename, FIELD_CHARACTER, "filename" ), - - DEFINE_KEYFIELD( m_bEnabled, FIELD_BOOLEAN, "enabled" ), - DEFINE_KEYFIELD( m_bStartDisabled, FIELD_BOOLEAN, "StartDisabled" ), - - DEFINE_FIELD( m_Weight, FIELD_FLOAT ), - DEFINE_FIELD( m_LastEnterWeight, FIELD_FLOAT ), - DEFINE_FIELD( m_LastEnterTime, FIELD_FLOAT ), - DEFINE_FIELD( m_LastExitWeight, FIELD_FLOAT ), - DEFINE_FIELD( m_LastExitTime, FIELD_FLOAT ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - -END_DATADESC() - - -IMPLEMENT_SERVERCLASS_ST_NOBASE(CColorCorrectionVolume, DT_ColorCorrectionVolume) - SendPropFloat( SENDINFO(m_Weight) ), - SendPropString( SENDINFO(m_lookupFilename) ), -END_SEND_TABLE() - - -CColorCorrectionVolume::CColorCorrectionVolume() : BaseClass() -{ - m_bEnabled = true; - m_MaxWeight = 1.0f; - m_lookupFilename.GetForModify()[0] = 0; -} - - -//------------------------------------------------------------------------------ -// Purpose : Send even though we don't have a model -//------------------------------------------------------------------------------ -int CColorCorrectionVolume::UpdateTransmitState() -{ - // ALWAYS transmit to all clients. - return SetTransmitState( FL_EDICT_ALWAYS ); -} - - -bool CColorCorrectionVolume::KeyValue( const char *szKeyName, const char *szValue ) -{ - if ( FStrEq( szKeyName, "filename" ) ) - { - Q_strncpy( m_lookupFilename.GetForModify(), szValue, MAX_PATH ); - - return true; - } - else if ( FStrEq( szKeyName, "maxweight" ) ) - { - float max_weight; - sscanf( szValue, "%f", &max_weight ); - m_MaxWeight = max_weight; - - return true; - } - - return BaseClass::KeyValue( szKeyName, szValue ); -} - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CColorCorrectionVolume::Spawn( void ) -{ - BaseClass::Spawn(); - - AddEFlags( EFL_FORCE_CHECK_TRANSMIT | EFL_DIRTY_ABSTRANSFORM ); - Precache(); - - SetSolid( SOLID_BSP ); - SetSolidFlags( FSOLID_TRIGGER | FSOLID_NOT_SOLID ); - SetModel( STRING( GetModelName() ) ); - - SetThink( &CColorCorrectionVolume::ThinkFunc ); - SetNextThink( gpGlobals->curtime + 0.01f ); - - if( m_bStartDisabled ) - { - m_bEnabled = false; - } - else - { - m_bEnabled = true; - } -} - -bool CColorCorrectionVolume::PassesTriggerFilters( CBaseEntity *pEntity ) -{ - if( pEntity == UTIL_GetLocalPlayer() ) - return true; - - return false; -} - -void CColorCorrectionVolume::StartTouch( CBaseEntity *pEntity ) -{ - m_LastEnterTime = gpGlobals->curtime; - m_LastEnterWeight = m_Weight; -} - -void CColorCorrectionVolume::EndTouch( CBaseEntity *pEntity ) -{ - m_LastExitTime = gpGlobals->curtime; - m_LastExitWeight = m_Weight; -} - -void CColorCorrectionVolume::ThinkFunc( ) -{ - if( !m_bEnabled ) - { - m_Weight.Set( 0.0f ); - } - else - { - if( m_LastEnterTime > m_LastExitTime ) - { - // we most recently entered the volume - - if( m_Weight < 1.0f ) - { - float dt = gpGlobals->curtime - m_LastEnterTime; - float weight = m_LastEnterWeight + dt / ((1.0f-m_LastEnterWeight)*m_FadeDuration); - if( weight>1.0f ) - weight = 1.0f; - - m_Weight = weight; - } - } - else - { - // we most recently exitted the volume - - if( m_Weight > 0.0f ) - { - float dt = gpGlobals->curtime - m_LastExitTime; - float weight = (1.0f-m_LastExitWeight) + dt / (m_LastExitWeight*m_FadeDuration); - if( weight>1.0f ) - weight = 1.0f; - - m_Weight = 1.0f - weight; - } - } - } - - SetNextThink( gpGlobals->curtime + 0.01f ); -} - - -//------------------------------------------------------------------------------ -// Purpose : Input handlers -//------------------------------------------------------------------------------ -void CColorCorrectionVolume::InputEnable( inputdata_t &inputdata ) -{ - m_bEnabled = true; -} - -void CColorCorrectionVolume::InputDisable( inputdata_t &inputdata ) -{ - m_bEnabled = false; -} diff --git a/game/server/controlentities.cpp b/game/server/controlentities.cpp deleted file mode 100644 index ef9cfde06..000000000 --- a/game/server/controlentities.cpp +++ /dev/null @@ -1,149 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: contains entities who have no physical representation in the game, and who -// must be triggered by other entities to cause their effects. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "player.h" -#include "tier1/strtools.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: when fired, it changes which track the CD is playing -//----------------------------------------------------------------------------- -class CTargetCDAudioRep : public CPointEntity -{ -public: - DECLARE_CLASS( CTargetCDAudioRep, CPointEntity ); - - void InputChangeCDTrack( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - -private: - int m_iTrack; // CD track to change to when fired -}; - -LINK_ENTITY_TO_CLASS( target_cdaudio, CTargetCDAudioRep ); - -BEGIN_DATADESC( CTargetCDAudioRep ) - - DEFINE_KEYFIELD( m_iTrack, FIELD_INTEGER, "track" ), - DEFINE_INPUTFUNC( FIELD_VOID, "ChangeCDTrack", InputChangeCDTrack ), - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Purpose: Changes the current playing CD track -//----------------------------------------------------------------------------- -void CTargetCDAudioRep::InputChangeCDTrack( inputdata_t &inputdata ) -{ - int iTrack = m_iTrack; - - - edict_t *pClient = NULL; - if ( gpGlobals->maxClients == 1 ) - { - pClient = engine->PEntityOfEntIndex( 1 ); - } - else - { - // In multiplayer, send it back to the activator - CBasePlayer *player = dynamic_cast< CBasePlayer * >( inputdata.pActivator ); - if ( player ) - { - pClient = player->edict(); - } - } - - // Can't play if the client is not connected! - if ( !pClient ) - return; - - if ( iTrack < -1 || iTrack > 30 ) - { - Warning( "TargetCDAudio - Track %d out of range\n" ); - return; - } - - if ( iTrack == -1 ) - { - engine->ClientCommand( pClient, "cd pause\n"); - } - else - { - char string [ 64 ]; - - Q_snprintf( string,sizeof(string), "cd play %3d\n", iTrack ); - engine->ClientCommand ( pClient, string); - } -} - -//----------------------------------------------------------------------------- -// Purpose: changes the gravity of the player who activates this entity -//----------------------------------------------------------------------------- -class CTargetChangeGravity : public CPointEntity -{ -public: - DECLARE_CLASS( CTargetChangeGravity, CPointEntity ); - - DECLARE_DATADESC(); - - void InputChangeGrav( inputdata_t &inputdata ); - void InputResetGrav( inputdata_t &inputdata ); - - int m_iGravity; - - int m_iOldGrav; -}; - -LINK_ENTITY_TO_CLASS( target_changegravity, CTargetChangeGravity ); - -BEGIN_DATADESC( CTargetChangeGravity ) - - DEFINE_KEYFIELD( m_iGravity, FIELD_INTEGER, "gravity" ), - DEFINE_FIELD( m_iOldGrav, FIELD_INTEGER ), - DEFINE_INPUTFUNC( FIELD_VOID, "ChangeGrav", InputChangeGrav ), - DEFINE_INPUTFUNC( FIELD_VOID, "ResetGrav", InputResetGrav ), - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for changing the activator's gravity. -//----------------------------------------------------------------------------- -void CTargetChangeGravity::InputChangeGrav( inputdata_t &inputdata ) -{ - CBasePlayer *pl = ToBasePlayer( inputdata.pActivator ); - if ( !pl ) - return; - - // Save the gravity to restore it in InputResetGrav - if ( m_iOldGrav ) - m_iOldGrav = (int)pl->GetGravity(); - - pl->SetGravity(m_iGravity); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for resetting the activator's gravity. -//----------------------------------------------------------------------------- -void CTargetChangeGravity::InputResetGrav( inputdata_t &inputdata ) -{ - CBasePlayer *pl = ToBasePlayer( inputdata.pActivator ); - if ( !pl ) - return; - - pl->SetGravity(m_iOldGrav); -} - - diff --git a/game/server/cplane.cpp b/game/server/cplane.cpp deleted file mode 100644 index fbfc8e570..000000000 --- a/game/server/cplane.cpp +++ /dev/null @@ -1,71 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "game.h" -#include "cplane.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//========================================================= -// Plane -//========================================================= -CPlane::CPlane ( void ) -{ - m_fInitialized = FALSE; -} - -//========================================================= -// InitializePlane - Takes a normal for the plane and a -// point on the plane and -//========================================================= -void CPlane::InitializePlane ( const Vector &vecNormal, const Vector &vecPoint ) -{ - m_vecNormal = vecNormal; - m_flDist = DotProduct ( m_vecNormal, vecPoint ); - m_fInitialized = TRUE; -} - - -//========================================================= -// PointInFront - determines whether the given vector is -// in front of the plane. -//========================================================= -bool CPlane::PointInFront ( const Vector &vecPoint ) -{ - float flFace; - - if ( !m_fInitialized ) - { - return FALSE; - } - - flFace = DotProduct ( m_vecNormal, vecPoint ) - m_flDist; - - if ( flFace >= 0 ) - { - return TRUE; - } - - return FALSE; -} - -//========================================================= -//========================================================= -float CPlane::PointDist ( const Vector &vecPoint ) -{ - float flDist; - - if ( !m_fInitialized ) - { - return FALSE; - } - - flDist = DotProduct ( m_vecNormal, vecPoint ) - m_flDist; - - return flDist; -} diff --git a/game/server/cplane.h b/game/server/cplane.h deleted file mode 100644 index 61bfedf30..000000000 --- a/game/server/cplane.h +++ /dev/null @@ -1,44 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#pragma once - -#ifndef CPLANE_H -#define CPLANE_H - -//========================================================= -// Plane -//========================================================= -class CPlane -{ -public: - CPlane ( void ); - - //========================================================= - // InitializePlane - Takes a normal for the plane and a - // point on the plane and - //========================================================= - void InitializePlane ( const Vector &vecNormal, const Vector &vecPoint ); - - //========================================================= - // PointInFront - determines whether the given vector is - // in front of the plane. - //========================================================= - bool PointInFront ( const Vector &vecPoint ); - - //========================================================= - // How far off the plane is this point? - //========================================================= - float PointDist( const Vector &vecPoint ); - -private: - Vector m_vecNormal; - float m_flDist; - bool m_fInitialized; -}; - -#endif //CPLANE_H diff --git a/game/server/damagemodifier.cpp b/game/server/damagemodifier.cpp deleted file mode 100644 index 9daf4c09c..000000000 --- a/game/server/damagemodifier.cpp +++ /dev/null @@ -1,85 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "damagemodifier.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CDamageModifier::CDamageModifier() -{ - m_flModifier = 1; - m_bDoneToMe = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDamageModifier::AddModifierToEntity( CBaseEntity *pEntity ) -{ - RemoveModifier(); - - pEntity->m_DamageModifiers.AddToTail( this ); - m_hEnt = pEntity; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDamageModifier::RemoveModifier() -{ - if ( m_hEnt.Get() ) - { - m_hEnt->m_DamageModifiers.FindAndRemove( this ); - m_hEnt = 0; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDamageModifier::SetModifier( float flScale ) -{ - m_flModifier = flScale; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CDamageModifier::GetModifier() const -{ - return m_flModifier; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseEntity* CDamageModifier::GetCharacter() const -{ - return m_hEnt.Get(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDamageModifier::SetDoneToMe( bool bDoneToMe ) -{ - m_bDoneToMe = bDoneToMe; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDamageModifier::IsDamageDoneToMe() const -{ - return m_bDoneToMe; -} - diff --git a/game/server/damagemodifier.h b/game/server/damagemodifier.h deleted file mode 100644 index 0ff52c9c2..000000000 --- a/game/server/damagemodifier.h +++ /dev/null @@ -1,46 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef DAMAGEMODIFIER_H -#define DAMAGEMODIFIER_H -#ifdef _WIN32 -#pragma once -#endif - - -class CBaseEntity; - - -#include "ehandle.h" - -//----------------------------------------------------------------------------- -// Purpose: Class handling generic damage modification to & from a player -//----------------------------------------------------------------------------- -class CDamageModifier -{ -public: - CDamageModifier(); - - void AddModifierToEntity( CBaseEntity *pChar ); - void RemoveModifier(); - - void SetModifier( float flDamageScale ); - float GetModifier() const; - - void SetDoneToMe( bool bDoneToMe ); - bool IsDamageDoneToMe() const; - - CBaseEntity *GetCharacter() const; - -private: - float m_flModifier; - CHandle m_hEnt; - bool m_bDoneToMe; // True = modifies damage done to the entity, false = damage done by the entity -}; - - -#endif // DAMAGEMODIFIER_H diff --git a/game/server/data_collector.cpp b/game/server/data_collector.cpp deleted file mode 100644 index 4d65237ea..000000000 --- a/game/server/data_collector.cpp +++ /dev/null @@ -1,66 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -// data_collector.cpp -// Data collection system -// Author: Michael S. Booth, June 2004 - -#include "cbase.h" -#include "data_collector.h" - -static CDataCollector *collector = NULL; - -//---------------------------------------------------------------------------------------------------------------------- -void StartDataCollection( void ) -{ - if (collector) - { - // already collecting - return; - } - - collector = new CDataCollector; - Msg( "Data colletion started.\n" ); -} -ConCommand data_collection_start( "data_collection_start", StartDataCollection, "Start collecting game event data." ); - - -//---------------------------------------------------------------------------------------------------------------------- -void StopDataCollection( void ) -{ - if (collector) - { - delete collector; - collector = NULL; - - Msg( "Data collection stopped.\n" ); - } -} -ConCommand data_collection_stop( "data_collection_stop", StopDataCollection, "Stop collecting game event data." ); - - -//---------------------------------------------------------------------------------------------------------------------- -CDataCollector::CDataCollector( void ) -{ - // register for all events - gameeventmanager->AddListener( this, true ); -} - -//---------------------------------------------------------------------------------------------------------------------- -CDataCollector::~CDataCollector() -{ - gameeventmanager->RemoveListener( this ); -} - -//---------------------------------------------------------------------------------------------------------------------- -/** - * This is invoked for each event that occurs in the game - */ -void CDataCollector::FireGameEvent( KeyValues *event ) -{ - DevMsg( "Collected event '%s'\n", event->GetName() ); -} diff --git a/game/server/data_collector.h b/game/server/data_collector.h deleted file mode 100644 index 23ee19af5..000000000 --- a/game/server/data_collector.h +++ /dev/null @@ -1,37 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -// data_collector.h -// Data collection system -// Author: Michael S. Booth, June 2004 - -#ifndef _DATA_COLLECTOR_H_ -#define _DATA_COLLECTOR_H_ - -#include -#include - -/** - * This class is used to monitor the event stream and - * store interesting events to disk for later analysis. - */ -class CDataCollector : public IGameEventListener -{ -public: - CDataCollector( void ); - ~CDataCollector(); - - // IGameEventListener - virtual void FireGameEvent( KeyValues *event ); -}; - - -extern void StartDataCollection( void ); -extern void StopDataCollection( void ); - - -#endif // _DATA_COLLECTOR_H_ diff --git a/game/server/doors.cpp b/game/server/doors.cpp deleted file mode 100644 index 0e86429b2..000000000 --- a/game/server/doors.cpp +++ /dev/null @@ -1,1416 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements two types of doors: linear and rotating. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "doors.h" -#include "entitylist.h" -#include "physics.h" -#include "ndebugoverlay.h" -#include "engine/IEngineSound.h" -#include "physics_npc_solver.h" - -#ifdef HL1_DLL -#include "filters.h" -#endif - -#ifdef CSTRIKE_DLL -#include "KeyValues.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define CLOSE_AREAPORTAL_THINK_CONTEXT "CloseAreaportalThink" - -BEGIN_DATADESC( CBaseDoor ) - - DEFINE_KEYFIELD( m_vecMoveDir, FIELD_VECTOR, "movedir" ), - - DEFINE_FIELD( m_bLockedSentence, FIELD_CHARACTER ), - DEFINE_FIELD( m_bUnlockedSentence, FIELD_CHARACTER ), - DEFINE_KEYFIELD( m_NoiseMoving, FIELD_SOUNDNAME, "noise1" ), - DEFINE_KEYFIELD( m_NoiseArrived, FIELD_SOUNDNAME, "noise2" ), - DEFINE_KEYFIELD( m_NoiseMovingClosed, FIELD_SOUNDNAME, "startclosesound" ), - DEFINE_KEYFIELD( m_NoiseArrivedClosed, FIELD_SOUNDNAME, "closesound" ), - DEFINE_KEYFIELD( m_ChainTarget, FIELD_STRING, "chainstodoor" ), - // DEFINE_FIELD( m_isChaining, FIELD_BOOLEAN ), - // DEFINE_FIELD( m_ls, locksound_t ), -// DEFINE_FIELD( m_isChaining, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_ls.sLockedSound, FIELD_SOUNDNAME, "locked_sound" ), - DEFINE_KEYFIELD( m_ls.sUnlockedSound, FIELD_SOUNDNAME, "unlocked_sound" ), - DEFINE_FIELD( m_bLocked, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_flWaveHeight, FIELD_FLOAT, "WaveHeight" ), - DEFINE_KEYFIELD( m_flBlockDamage, FIELD_FLOAT, "dmg" ), - DEFINE_KEYFIELD( m_eSpawnPosition, FIELD_INTEGER, "spawnpos" ), - - DEFINE_KEYFIELD( m_bForceClosed, FIELD_BOOLEAN, "forceclosed" ), - DEFINE_FIELD( m_bDoorGroup, FIELD_BOOLEAN ), - -#ifdef HL1_DLL - DEFINE_KEYFIELD( m_iBlockFilterName, FIELD_STRING, "filtername" ), - DEFINE_FIELD( m_hBlockFilter, FIELD_EHANDLE ), -#endif - - DEFINE_KEYFIELD( m_bLoopMoveSound, FIELD_BOOLEAN, "loopmovesound" ), - DEFINE_KEYFIELD( m_bIgnoreDebris, FIELD_BOOLEAN, "ignoredebris" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Open", InputOpen ), - DEFINE_INPUTFUNC( FIELD_VOID, "Close", InputClose ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - DEFINE_INPUTFUNC( FIELD_VOID, "Lock", InputLock ), - DEFINE_INPUTFUNC( FIELD_VOID, "Unlock", InputUnlock ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetSpeed", InputSetSpeed ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetToggleState", InputSetToggleState ), - - DEFINE_OUTPUT( m_OnBlockedOpening, "OnBlockedOpening" ), - DEFINE_OUTPUT( m_OnBlockedClosing, "OnBlockedClosing" ), - DEFINE_OUTPUT( m_OnUnblockedOpening, "OnUnblockedOpening" ), - DEFINE_OUTPUT( m_OnUnblockedClosing, "OnUnblockedClosing" ), - DEFINE_OUTPUT( m_OnFullyClosed, "OnFullyClosed" ), - DEFINE_OUTPUT( m_OnFullyOpen, "OnFullyOpen" ), - DEFINE_OUTPUT( m_OnClose, "OnClose" ), - DEFINE_OUTPUT( m_OnOpen, "OnOpen" ), - DEFINE_OUTPUT( m_OnLockedUse, "OnLockedUse" ), - - // Function Pointers - DEFINE_FUNCTION( DoorTouch ), - DEFINE_FUNCTION( DoorGoUp ), - DEFINE_FUNCTION( DoorGoDown ), - DEFINE_FUNCTION( DoorHitTop ), - DEFINE_FUNCTION( DoorHitBottom ), - DEFINE_THINKFUNC( MovingSoundThink ), - DEFINE_THINKFUNC( CloseAreaPortalsThink ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( func_door, CBaseDoor ); - -// -// func_water is implemented as a linear door so we can raise/lower the water level. -// -LINK_ENTITY_TO_CLASS( func_water, CBaseDoor ); - - -// SendTable stuff. -IMPLEMENT_SERVERCLASS_ST(CBaseDoor, DT_BaseDoor) - SendPropFloat (SENDINFO(m_flWaveHeight), 8, SPROP_ROUNDUP, 0.0f, 8.0f), -END_SEND_TABLE() - -#define DOOR_SENTENCEWAIT 6 -#define DOOR_SOUNDWAIT 1 -#define BUTTON_SOUNDWAIT 0.5 - - -//----------------------------------------------------------------------------- -// Purpose: play door or button locked or unlocked sounds. -// NOTE: this routine is shared by doors and buttons -// Input : pEdict - -// pls - -// flocked - if true, play 'door is locked' sound, otherwise play 'door -// is unlocked' sound. -// fbutton - -//----------------------------------------------------------------------------- -void PlayLockSounds(CBaseEntity *pEdict, locksound_t *pls, int flocked, int fbutton) -{ - if ( pEdict->HasSpawnFlags( SF_DOOR_SILENT ) ) - { - return; - } - float flsoundwait = ( fbutton ) ? BUTTON_SOUNDWAIT : DOOR_SOUNDWAIT; - - if ( flocked ) - { - int fplaysound = (pls->sLockedSound != NULL_STRING && gpGlobals->curtime > pls->flwaitSound); - int fplaysentence = (pls->sLockedSentence != NULL_STRING && !pls->bEOFLocked && gpGlobals->curtime > pls->flwaitSentence); - float fvol = ( fplaysound && fplaysentence ) ? 0.25f : 1.0f; - - // if there is a locked sound, and we've debounced, play sound - if (fplaysound) - { - // play 'door locked' sound - CPASAttenuationFilter filter( pEdict ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_ITEM; - ep.m_pSoundName = (char*)STRING(pls->sLockedSound); - ep.m_flVolume = fvol; - ep.m_SoundLevel = SNDLVL_NORM; - - CBaseEntity::EmitSound( filter, pEdict->entindex(), ep ); - pls->flwaitSound = gpGlobals->curtime + flsoundwait; - } - - // if there is a sentence, we've not played all in list, and we've debounced, play sound - if (fplaysentence) - { - // play next 'door locked' sentence in group - int iprev = pls->iLockedSentence; - - pls->iLockedSentence = SENTENCEG_PlaySequentialSz( pEdict->edict(), - STRING(pls->sLockedSentence), - 0.85f, - SNDLVL_NORM, - 0, - 100, - pls->iLockedSentence, - FALSE); - pls->iUnlockedSentence = 0; - - // make sure we don't keep calling last sentence in list - pls->bEOFLocked = (iprev == pls->iLockedSentence); - - pls->flwaitSentence = gpGlobals->curtime + DOOR_SENTENCEWAIT; - } - } - else - { - // UNLOCKED SOUND - - int fplaysound = (pls->sUnlockedSound != NULL_STRING && gpGlobals->curtime > pls->flwaitSound); - int fplaysentence = (pls->sUnlockedSentence != NULL_STRING && !pls->bEOFUnlocked && gpGlobals->curtime > pls->flwaitSentence); - float fvol; - - // if playing both sentence and sound, lower sound volume so we hear sentence - fvol = ( fplaysound && fplaysentence ) ? 0.25f : 1.0f; - - // play 'door unlocked' sound if set - if (fplaysound) - { - CPASAttenuationFilter filter( pEdict ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_ITEM; - ep.m_pSoundName = (char*)STRING(pls->sUnlockedSound); - ep.m_flVolume = fvol; - ep.m_SoundLevel = SNDLVL_NORM; - - CBaseEntity::EmitSound( filter, pEdict->entindex(), ep ); - pls->flwaitSound = gpGlobals->curtime + flsoundwait; - } - - // play next 'door unlocked' sentence in group - if (fplaysentence) - { - int iprev = pls->iUnlockedSentence; - - pls->iUnlockedSentence = SENTENCEG_PlaySequentialSz(pEdict->edict(), STRING(pls->sUnlockedSentence), - 0.85, SNDLVL_NORM, 0, 100, pls->iUnlockedSentence, FALSE); - pls->iLockedSentence = 0; - - // make sure we don't keep calling last sentence in list - pls->bEOFUnlocked = (iprev == pls->iUnlockedSentence); - pls->flwaitSentence = gpGlobals->curtime + DOOR_SENTENCEWAIT; - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Cache user-entity-field values until spawn is called. -// Input : szKeyName - -// szValue - -// Output : Returns true. -//----------------------------------------------------------------------------- -bool CBaseDoor::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "locked_sentence")) - { - m_bLockedSentence = atoi(szValue); - } - else if (FStrEq(szKeyName, "unlocked_sentence")) - { - m_bUnlockedSentence = atoi(szValue); - } - else - return BaseClass::KeyValue( szKeyName, szValue ); - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseDoor::Spawn() -{ - Precache(); - -#ifdef HL1_DLL - SetSolid( SOLID_BSP ); -#else - if ( GetMoveParent() && GetRootMoveParent()->GetSolid() == SOLID_BSP ) - { - SetSolid( SOLID_BSP ); - } - else - { - SetSolid( SOLID_VPHYSICS ); - } -#endif - - // Convert movedir from angles to a vector - QAngle angMoveDir = QAngle( m_vecMoveDir.x, m_vecMoveDir.y, m_vecMoveDir.z ); - AngleVectors( angMoveDir, &m_vecMoveDir ); - - SetModel( STRING( GetModelName() ) ); - m_vecPosition1 = GetLocalOrigin(); - - // Subtract 2 from size because the engine expands bboxes by 1 in all directions making the size too big - Vector vecOBB = CollisionProp()->OBBSize(); - vecOBB -= Vector( 2, 2, 2 ); - m_vecPosition2 = m_vecPosition1 + (m_vecMoveDir * (DotProductAbs( m_vecMoveDir, vecOBB ) - m_flLip)); - - if ( !IsRotatingDoor() ) - { - if ( ( m_eSpawnPosition == FUNC_DOOR_SPAWN_OPEN ) || HasSpawnFlags( SF_DOOR_START_OPEN_OBSOLETE ) ) - { // swap pos1 and pos2, put door at pos2 - UTIL_SetOrigin( this, m_vecPosition2); - m_toggle_state = TS_AT_TOP; - } - else - { - m_toggle_state = TS_AT_BOTTOM; - } - } - - if (HasSpawnFlags(SF_DOOR_LOCKED)) - { - m_bLocked = true; - } - - SetMoveType( MOVETYPE_PUSH ); - - if (m_flSpeed == 0) - { - m_flSpeed = 100; - } - - SetTouch( &CBaseDoor::DoorTouch ); - - if ( !FClassnameIs( this, "func_water" ) ) - { - if ( HasSpawnFlags(SF_DOOR_PASSABLE) ) - { - //normal door - AddEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID ); - AddSolidFlags( FSOLID_NOT_SOLID ); - } - - if ( HasSpawnFlags( SF_DOOR_NONSOLID_TO_PLAYER ) ) - { - SetCollisionGroup( COLLISION_GROUP_PASSABLE_DOOR ); - // HACKHACK: Set this hoping that any children of the door that get blocked by the player - // will get fixed up by vphysics - // NOTE: We could decouple this as a separate behavior, but managing player collisions is already complex enough. - // NOTE: This is necessary to prevent the player from blocking the wrecked train car in ep2_outland_01 - AddFlag( FL_UNBLOCKABLE_BY_PLAYER ); - } - if ( m_bIgnoreDebris ) - { - // both of these flags want to set the collision group and - // there isn't a combo group - Assert( !HasSpawnFlags( SF_DOOR_NONSOLID_TO_PLAYER ) ); - if ( HasSpawnFlags( SF_DOOR_NONSOLID_TO_PLAYER ) ) - { - Warning("Door %s with conflicting collision settings, removing ignoredebris\n", GetDebugName() ); - } - else - { - SetCollisionGroup( COLLISION_GROUP_INTERACTIVE ); - } - } - } - - if ( ( m_eSpawnPosition == FUNC_DOOR_SPAWN_OPEN ) && HasSpawnFlags( SF_DOOR_START_OPEN_OBSOLETE ) ) - { - Warning("Door %s using obsolete 'Start Open' spawnflag with 'Spawn Position' set to 'Open'. Reverting to old behavior.\n", GetDebugName() ); - } - - CreateVPhysics(); -} - -void CBaseDoor::MovingSoundThink( void ) -{ - CPASAttenuationFilter filter( this ); - filter.MakeReliable(); - - EmitSound_t ep; - ep.m_nChannel = CHAN_STATIC; - if ( m_NoiseMovingClosed == NULL_STRING || m_toggle_state == TS_GOING_DOWN || m_toggle_state == TS_AT_BOTTOM ) - { - ep.m_pSoundName = (char*)STRING(m_NoiseMoving); - } - else - { - ep.m_pSoundName = (char*)STRING(m_NoiseMovingClosed); - } - ep.m_flVolume = 1; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - - //Only loop sounds in HL1 to maintain HL2 behavior - if( ShouldLoopMoveSound() ) - { - float duration = enginesound->GetSoundDuration( ep.m_pSoundName ); - SetContextThink( &CBaseDoor::MovingSoundThink, gpGlobals->curtime + duration, "MovingSound" ); - } -} - -void CBaseDoor::StartMovingSound( void ) -{ - MovingSoundThink(); - -#ifdef CSTRIKE_DLL // this event is only used by CS:S bots - - CBasePlayer *player = ToBasePlayer(m_hActivator); - IGameEvent * event = gameeventmanager->CreateEvent( "door_moving" ); - if( event ) - { - event->SetInt( "entindex", entindex() ); - event->SetInt( "userid", (player)?player->GetUserID():0 ); - gameeventmanager->FireEvent( event ); - } - -#endif -} - -void CBaseDoor::StopMovingSound(void) -{ - SetContextThink( NULL, gpGlobals->curtime, "MovingSound" ); - char *pSoundName; - if ( m_NoiseMovingClosed == NULL_STRING || m_toggle_state == TS_GOING_UP || m_toggle_state == TS_AT_TOP ) - { - pSoundName = (char*)STRING(m_NoiseMoving); - } - else - { - pSoundName = (char*)STRING(m_NoiseMovingClosed); - } - StopSound( entindex(), CHAN_STATIC, pSoundName ); -} - - -bool CBaseDoor::ShouldSavePhysics() -{ - // don't save physics if you're func_water - return !FClassnameIs( this, "func_water" ); -} - -//----------------------------------------------------------------------------- -bool CBaseDoor::CreateVPhysics( ) -{ - if ( !FClassnameIs( this, "func_water" ) ) - { - //normal door - // NOTE: Create this even when the door is not solid to support constraints. - VPhysicsInitShadow( false, false ); - } - else - { - // special contents - AddSolidFlags( FSOLID_VOLUME_CONTENTS ); - SETBITS( m_spawnflags, SF_DOOR_SILENT ); // water is silent for now - - IPhysicsObject *pPhysics = VPhysicsInitShadow( false, false ); - fluidparams_t fluid; - - Assert( CollisionProp()->GetCollisionAngles() == vec3_angle ); - fluid.damping = 0.01f; - fluid.surfacePlane[0] = 0; - fluid.surfacePlane[1] = 0; - fluid.surfacePlane[2] = 1; - fluid.surfacePlane[3] = CollisionProp()->GetCollisionOrigin().z + CollisionProp()->OBBMaxs().z - 1; - fluid.currentVelocity.Init(0,0,0); - fluid.torqueFactor = 0.1f; - fluid.viscosityFactor = 0.01f; - fluid.pGameData = static_cast(this); - - //FIXME: Currently there's no way to specify that you want slime - fluid.contents = CONTENTS_WATER; - - physenv->CreateFluidController( pPhysics, &fluid ); - } - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseDoor::Activate( void ) -{ - BaseClass::Activate(); - - CBaseDoor *pDoorList[64]; - m_bDoorGroup = true; - - // force movement groups to sync!!! - int doorCount = GetDoorMovementGroup( pDoorList, ARRAYSIZE(pDoorList) ); - for ( int i = 0; i < doorCount; i++ ) - { - if ( pDoorList[i]->m_vecMoveDir == m_vecMoveDir ) - { - bool error = false; - if ( pDoorList[i]->IsRotatingDoor() ) - { - error = ( pDoorList[i]->GetLocalAngles() != GetLocalAngles() ) ? true : false; - } - else - { - error = ( pDoorList[i]->GetLocalOrigin() != GetLocalOrigin() ) ? true : false; - } - if ( error ) - { - // don't do group blocking - m_bDoorGroup = false; -#ifdef HL1_DLL - // UNDONE: This should probably fixup m_vecPosition1 & m_vecPosition2 - Warning("Door group %s has misaligned origin!\n", STRING(GetEntityName()) ); -#endif - } - } - } - - switch ( m_toggle_state ) - { - case TS_AT_TOP: - UpdateAreaPortals( true ); - break; - case TS_AT_BOTTOM: - UpdateAreaPortals( false ); - break; - default: - break; - } - -#ifdef HL1_DLL - // Get a handle to my filter entity if there is one - if (m_iBlockFilterName != NULL_STRING) - { - m_hBlockFilter = dynamic_cast(gEntList.FindEntityByName( NULL, m_iBlockFilterName, NULL )); - } -#endif -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : state - -//----------------------------------------------------------------------------- -// This is ONLY used by the node graph to test movement through a door -void CBaseDoor::InputSetToggleState( inputdata_t &inputdata ) -{ - SetToggleState( inputdata.value.Int() ); -} - -void CBaseDoor::SetToggleState( int state ) -{ - if ( state == TS_AT_TOP ) - UTIL_SetOrigin( this, m_vecPosition2 ); - else - UTIL_SetOrigin( this, m_vecPosition1 ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseDoor::Precache( void ) -{ - //Fill in a default value if necessary - if ( IsRotatingDoor() ) - { - UTIL_ValidateSoundName( m_NoiseMoving, "RotDoorSound.DefaultMove" ); - UTIL_ValidateSoundName( m_NoiseArrived, "RotDoorSound.DefaultArrive" ); - UTIL_ValidateSoundName( m_ls.sLockedSound, "RotDoorSound.DefaultLocked" ); - UTIL_ValidateSoundName( m_ls.sUnlockedSound,"DoorSound.Null" ); - } - else - { - UTIL_ValidateSoundName( m_NoiseMoving, "DoorSound.DefaultMove" ); - UTIL_ValidateSoundName( m_NoiseArrived, "DoorSound.DefaultArrive" ); -#ifndef HL1_DLL - UTIL_ValidateSoundName( m_ls.sLockedSound, "DoorSound.DefaultLocked" ); -#endif - UTIL_ValidateSoundName( m_ls.sUnlockedSound,"DoorSound.Null" ); - } - -#ifdef HL1_DLL - if( m_ls.sLockedSound != NULL_STRING && strlen((char*)STRING(m_ls.sLockedSound)) < 4 ) - { - // Too short to be ANYTHING ".wav", so it must be an old index into a long-lost - // array of sound choices. slam it to a known "deny" sound. We lose the designer's - // original selection, but we don't get unresponsive doors. - m_ls.sLockedSound = AllocPooledString("buttons/button2.wav"); - } -#endif//HL1_DLL - - //Precache them all - PrecacheScriptSound( (char *) STRING(m_NoiseMoving) ); - PrecacheScriptSound( (char *) STRING(m_NoiseArrived) ); - PrecacheScriptSound( (char *) STRING(m_NoiseMovingClosed) ); - PrecacheScriptSound( (char *) STRING(m_NoiseArrivedClosed) ); - PrecacheScriptSound( (char *) STRING(m_ls.sLockedSound) ); - PrecacheScriptSound( (char *) STRING(m_ls.sUnlockedSound) ); - - //Get sentence group names, for doors which are directly 'touched' to open - switch (m_bLockedSentence) - { - case 1: m_ls.sLockedSentence = AllocPooledString("NA"); break; // access denied - case 2: m_ls.sLockedSentence = AllocPooledString("ND"); break; // security lockout - case 3: m_ls.sLockedSentence = AllocPooledString("NF"); break; // blast door - case 4: m_ls.sLockedSentence = AllocPooledString("NFIRE"); break; // fire door - case 5: m_ls.sLockedSentence = AllocPooledString("NCHEM"); break; // chemical door - case 6: m_ls.sLockedSentence = AllocPooledString("NRAD"); break; // radiation door - case 7: m_ls.sLockedSentence = AllocPooledString("NCON"); break; // gen containment - case 8: m_ls.sLockedSentence = AllocPooledString("NH"); break; // maintenance door - case 9: m_ls.sLockedSentence = AllocPooledString("NG"); break; // broken door - - default: m_ls.sLockedSentence = NULL_STRING; break; - } - - switch (m_bUnlockedSentence) - { - case 1: m_ls.sUnlockedSentence = AllocPooledString("EA"); break; // access granted - case 2: m_ls.sUnlockedSentence = AllocPooledString("ED"); break; // security door - case 3: m_ls.sUnlockedSentence = AllocPooledString("EF"); break; // blast door - case 4: m_ls.sUnlockedSentence = AllocPooledString("EFIRE"); break; // fire door - case 5: m_ls.sUnlockedSentence = AllocPooledString("ECHEM"); break; // chemical door - case 6: m_ls.sUnlockedSentence = AllocPooledString("ERAD"); break; // radiation door - case 7: m_ls.sUnlockedSentence = AllocPooledString("ECON"); break; // gen containment - case 8: m_ls.sUnlockedSentence = AllocPooledString("EH"); break; // maintenance door - - default: m_ls.sUnlockedSentence = NULL_STRING; break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Doors not tied to anything (e.g. button, another door) can be touched, -// to make them activate. -// Input : *pOther - -//----------------------------------------------------------------------------- -void CBaseDoor::DoorTouch( CBaseEntity *pOther ) -{ - if( m_ChainTarget != NULL_STRING ) - ChainTouch( pOther ); - - // Ignore touches by anything but players. - if ( !pOther->IsPlayer() ) - { -#ifdef HL1_DLL - if( PassesBlockTouchFilter( pOther ) && m_toggle_state == TS_GOING_DOWN ) - { - DoorGoUp(); - } -#endif - return; - } - - // If door is not opened by touch, do nothing. - if ( !HasSpawnFlags(SF_DOOR_PTOUCH) ) - { -#ifdef HL1_DLL - if( m_toggle_state == TS_AT_BOTTOM ) - { - PlayLockSounds(this, &m_ls, TRUE, FALSE); - } -#endif//HL1_DLL - - return; - } - - // If door has master, and it's not ready to trigger, - // play 'locked' sound. - if (m_sMaster != NULL_STRING && !UTIL_IsMasterTriggered(m_sMaster, pOther)) - { - PlayLockSounds(this, &m_ls, TRUE, FALSE); - } - - if (m_bLocked) - { - m_OnLockedUse.FireOutput( pOther, pOther ); - PlayLockSounds(this, &m_ls, TRUE, FALSE); - return; - } - - // Remember who activated the door. - m_hActivator = pOther; - - if (DoorActivate( )) - { - // Temporarily disable the touch function, until movement is finished. - SetTouch( NULL ); - } -} - -#ifdef HL1_DLL -bool CBaseDoor::PassesBlockTouchFilter(CBaseEntity *pOther) -{ - CBaseFilter* pFilter = (CBaseFilter*)(m_hBlockFilter.Get()); - return ( pFilter && pFilter->PassesFilter( this, pOther ) ); -} -#endif - - -//----------------------------------------------------------------------------- -// Purpose: Delays turning off area portals when closing doors to prevent visual artifacts -//----------------------------------------------------------------------------- -void CBaseDoor::CloseAreaPortalsThink( void ) -{ - UpdateAreaPortals( false ); - SetContextThink( NULL, gpGlobals->curtime, CLOSE_AREAPORTAL_THINK_CONTEXT ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : isOpen - -//----------------------------------------------------------------------------- -void CBaseDoor::UpdateAreaPortals( bool isOpen ) -{ - // cancel pending close - SetContextThink( NULL, gpGlobals->curtime, CLOSE_AREAPORTAL_THINK_CONTEXT ); - - if ( IsRotatingDoor() && HasSpawnFlags(SF_DOOR_START_OPEN_OBSOLETE) ) // logic inverted when using rot doors that start open - isOpen = !isOpen; - - string_t name = GetEntityName(); - if ( !name ) - return; - - CBaseEntity *pPortal = NULL; - while ( ( pPortal = gEntList.FindEntityByClassname( pPortal, "func_areaportal" ) ) != NULL ) - { - if ( pPortal->HasTarget( name ) ) - { - // USE_ON means open the portal, off means close it - pPortal->Use( this, this, isOpen?USE_ON:USE_OFF, 0 ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Called when the player uses the door. -// Input : pActivator - -// pCaller - -// useType - -// value - -//----------------------------------------------------------------------------- -void CBaseDoor::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - m_hActivator = pActivator; - - if( m_ChainTarget != NULL_STRING ) - ChainUse(); - - // We can't +use this if it can't be +used - if ( m_hActivator != NULL && m_hActivator->IsPlayer() && HasSpawnFlags( SF_DOOR_PUSE ) == false ) - { - PlayLockSounds( this, &m_ls, TRUE, FALSE ); - return; - } - - bool bAllowUse = false; - - // if not ready to be used, ignore "use" command. - if( HasSpawnFlags(SF_DOOR_NEW_USE_RULES) ) - { - //New behavior: - // If not ready to be used, ignore "use" command. - // Allow use in these cases: - // - when the door is closed/closing - // - when the door is open/opening and can be manually closed - if ( ( m_toggle_state == TS_AT_BOTTOM || m_toggle_state == TS_GOING_DOWN ) || ( HasSpawnFlags(SF_DOOR_NO_AUTO_RETURN) && ( m_toggle_state == TS_AT_TOP || m_toggle_state == TS_GOING_UP ) ) ) - bAllowUse = true; - } - else - { - // Legacy behavior: - if (m_toggle_state == TS_AT_BOTTOM || (HasSpawnFlags(SF_DOOR_NO_AUTO_RETURN) && m_toggle_state == TS_AT_TOP) ) - bAllowUse = true; - } - - if( bAllowUse ) - { - if (m_bLocked) - { - m_OnLockedUse.FireOutput( pActivator, pCaller ); - PlayLockSounds(this, &m_ls, TRUE, FALSE); - } - else - { - DoorActivate(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Passes Use along to certain named doors. -//----------------------------------------------------------------------------- -void CBaseDoor::ChainUse( void ) -{ - if ( m_isChaining ) - return; - - CBaseEntity *ent = NULL; - while ( ( ent = gEntList.FindEntityByName( ent, m_ChainTarget, NULL ) ) != NULL ) - { - if ( ent == this ) - continue; - - CBaseDoor *door = dynamic_cast< CBaseDoor * >( ent ); - if ( door ) - { - door->SetChaining( true ); - door->Use( m_hActivator, NULL, USE_TOGGLE, 0.0f ); // only the first param is used - door->SetChaining( false ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Passes Touch along to certain named doors. -//----------------------------------------------------------------------------- -void CBaseDoor::ChainTouch( CBaseEntity *pOther ) -{ - if ( m_isChaining ) - return; - - CBaseEntity *ent = NULL; - while ( ( ent = gEntList.FindEntityByName( ent, m_ChainTarget, NULL ) ) != NULL ) - { - if ( ent == this ) - continue; - - CBaseDoor *door = dynamic_cast< CBaseDoor * >( ent ); - if ( door ) - { - door->SetChaining( true ); - door->Touch( pOther ); - door->SetChaining( false ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Closes the door if it is not already closed. -//----------------------------------------------------------------------------- -void CBaseDoor::InputClose( inputdata_t &inputdata ) -{ - if ( m_toggle_state != TS_AT_BOTTOM ) - { - DoorGoDown(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that locks the door. -//----------------------------------------------------------------------------- -void CBaseDoor::InputLock( inputdata_t &inputdata ) -{ - Lock(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Opens the door if it is not already open. -//----------------------------------------------------------------------------- -void CBaseDoor::InputOpen( inputdata_t &inputdata ) -{ - if (m_toggle_state != TS_AT_TOP && m_toggle_state != TS_GOING_UP ) - { - // I'm locked, can't open - if (m_bLocked) - return; - - // Play door unlock sounds. - PlayLockSounds(this, &m_ls, false, false); - DoorGoUp(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Opens the door if it is not already open. -//----------------------------------------------------------------------------- -void CBaseDoor::InputToggle( inputdata_t &inputdata ) -{ - // I'm locked, can't open - if (m_bLocked) - return; - - if (m_toggle_state == TS_AT_BOTTOM) - { - DoorGoUp(); - } - else if (m_toggle_state == TS_AT_TOP) - { - DoorGoDown(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that unlocks the door. -//----------------------------------------------------------------------------- -void CBaseDoor::InputUnlock( inputdata_t &inputdata ) -{ - Unlock(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseDoor::InputSetSpeed( inputdata_t &inputdata ) -{ - m_flSpeed = inputdata.value.Float(); -} - -//----------------------------------------------------------------------------- -// Purpose: Locks the door so that it cannot be opened. -//----------------------------------------------------------------------------- -void CBaseDoor::Lock( void ) -{ - m_bLocked = true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Unlocks the door so that it can be opened. -//----------------------------------------------------------------------------- -void CBaseDoor::Unlock( void ) -{ - m_bLocked = false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Causes the door to "do its thing", i.e. start moving, and cascade activation. -// Output : int -//----------------------------------------------------------------------------- -int CBaseDoor::DoorActivate( ) -{ - if (!UTIL_IsMasterTriggered(m_sMaster, m_hActivator)) - return 0; - - if (HasSpawnFlags(SF_DOOR_NO_AUTO_RETURN) && m_toggle_state == TS_AT_TOP) - { - // door should close - DoorGoDown(); - } - else - { - // door should open - // play door unlock sounds - PlayLockSounds(this, &m_ls, FALSE, FALSE); - - if ( m_toggle_state != TS_AT_TOP && m_toggle_state != TS_GOING_UP ) - { - DoorGoUp(); - } - } - - return 1; -} - - -//----------------------------------------------------------------------------- -// Purpose: Starts the door going to its "up" position (simply ToggleData->vecPosition2). -//----------------------------------------------------------------------------- -void CBaseDoor::DoorGoUp( void ) -{ - edict_t *pevActivator; - - UpdateAreaPortals( true ); - // It could be going-down, if blocked. - ASSERT(m_toggle_state == TS_AT_BOTTOM || m_toggle_state == TS_GOING_DOWN); - - // emit door moving and stop sounds on CHAN_STATIC so that the multicast doesn't - // filter them out and leave a client stuck with looping door sounds! - if ( !HasSpawnFlags(SF_DOOR_SILENT ) ) - { - // If we're not moving already, start the moving noise - if ( m_toggle_state != TS_GOING_UP && m_toggle_state != TS_GOING_DOWN ) - { - StartMovingSound(); - } - } - - m_toggle_state = TS_GOING_UP; - - SetMoveDone( &CBaseDoor::DoorHitTop ); - if ( IsRotatingDoor() ) // !!! BUGBUG Triggered doors don't work with this yet - { - float sign = 1.0; - - if ( m_hActivator != NULL ) - { - pevActivator = m_hActivator->edict(); - - if ( !HasSpawnFlags( SF_DOOR_ONEWAY ) && m_vecMoveAng.y ) // Y axis rotation, move away from the player - { - // Positive is CCW, negative is CW, so make 'sign' 1 or -1 based on which way we want to open. - // Important note: All doors face East at all times, and twist their local angle to open. - // So you can't look at the door's facing to determine which way to open. - - Vector nearestPoint; - CollisionProp()->CalcNearestPoint( m_hActivator->GetAbsOrigin(), &nearestPoint ); - Vector activatorToNearestPoint = nearestPoint - m_hActivator->GetAbsOrigin(); - activatorToNearestPoint.z = 0; - - Vector activatorToOrigin = GetAbsOrigin() - m_hActivator->GetAbsOrigin(); - activatorToOrigin.z = 0; - - // Point right hand at door hinge, curl hand towards closest spot on door, if thumb - // is up, open door CW. -- Department of Basic Cross Product Understanding for Noobs - Vector cross = activatorToOrigin.Cross( activatorToNearestPoint ); - - if( cross.z > 0.0f ) - { - sign = -1.0f; - } - } - } - AngularMove(m_vecAngle2*sign, m_flSpeed); - } - else - { - LinearMove(m_vecPosition2, m_flSpeed); - } - - //Fire our open ouput - m_OnOpen.FireOutput( this, this ); -} - - -//----------------------------------------------------------------------------- -// Purpose: The door has reached the "up" position. Either go back down, or -// wait for another activation. -//----------------------------------------------------------------------------- -void CBaseDoor::DoorHitTop( void ) -{ - if ( !HasSpawnFlags( SF_DOOR_SILENT ) ) - { - CPASAttenuationFilter filter( this ); - filter.MakeReliable(); - StopMovingSound(); - - EmitSound_t ep; - ep.m_nChannel = CHAN_STATIC; - ep.m_pSoundName = (char*)STRING(m_NoiseArrived); - ep.m_flVolume = 1; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - } - - ASSERT(m_toggle_state == TS_GOING_UP); - m_toggle_state = TS_AT_TOP; - - // toggle-doors don't come down automatically, they wait for refire. - if (HasSpawnFlags( SF_DOOR_NO_AUTO_RETURN)) - { - // Re-instate touch method, movement is complete - SetTouch( &CBaseDoor::DoorTouch ); - } - else - { - // In flWait seconds, DoorGoDown will fire, unless wait is -1, then door stays open - SetMoveDoneTime( m_flWait ); - SetMoveDone( &CBaseDoor::DoorGoDown ); - - if ( m_flWait == -1 ) - { - SetNextThink( TICK_NEVER_THINK ); - } - } - - if (HasSpawnFlags(SF_DOOR_START_OPEN_OBSOLETE) ) - { - m_OnFullyClosed.FireOutput(this, this); - } - else - { - m_OnFullyOpen.FireOutput(this, this); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Starts the door going to its "down" position (simply ToggleData->vecPosition1). -//----------------------------------------------------------------------------- -void CBaseDoor::DoorGoDown( void ) -{ - if ( !HasSpawnFlags( SF_DOOR_SILENT ) ) - { - // If we're not moving already, start the moving noise - if ( m_toggle_state != TS_GOING_UP && m_toggle_state != TS_GOING_DOWN ) - { - StartMovingSound(); - } - } - -#ifdef DOOR_ASSERT - ASSERT(m_toggle_state == TS_AT_TOP); -#endif // DOOR_ASSERT - m_toggle_state = TS_GOING_DOWN; - - SetMoveDone( &CBaseDoor::DoorHitBottom ); - if ( IsRotatingDoor() )//rotating door - AngularMove( m_vecAngle1, m_flSpeed); - else - LinearMove( m_vecPosition1, m_flSpeed); - - //Fire our closed output - m_OnClose.FireOutput( this, this ); -} - - -//----------------------------------------------------------------------------- -// Purpose: The door has reached the "down" position. Back to quiescence. -//----------------------------------------------------------------------------- -void CBaseDoor::DoorHitBottom( void ) -{ - if ( !HasSpawnFlags( SF_DOOR_SILENT ) ) - { - CPASAttenuationFilter filter( this ); - filter.MakeReliable(); - - StopMovingSound(); - - EmitSound_t ep; - ep.m_nChannel = CHAN_STATIC; - if ( m_NoiseArrivedClosed == NULL_STRING ) - ep.m_pSoundName = (char*)STRING(m_NoiseArrived); - else - ep.m_pSoundName = (char*)STRING(m_NoiseArrivedClosed); - ep.m_flVolume = 1; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - } - - ASSERT(m_toggle_state == TS_GOING_DOWN); - m_toggle_state = TS_AT_BOTTOM; - - // Re-instate touch method, cycle is complete - SetTouch( &CBaseDoor::DoorTouch ); - - if (HasSpawnFlags(SF_DOOR_START_OPEN_OBSOLETE)) - { - m_OnFullyOpen.FireOutput(m_hActivator, this); - } - else - { - m_OnFullyClosed.FireOutput(m_hActivator, this); - } - - // Close the area portals just after the door closes, to prevent visual artifacts in multiplayer games - SetContextThink( &CBaseDoor::CloseAreaPortalsThink, gpGlobals->curtime + 0.5f, CLOSE_AREAPORTAL_THINK_CONTEXT ); -} - - -// Lists all doors in the same movement group as this one -int CBaseDoor::GetDoorMovementGroup( CBaseDoor *pDoorList[], int listMax ) -{ - int count = 0; - CBaseEntity *pTarget = NULL; - - // Block all door pieces with the same targetname here. - if ( GetEntityName() != NULL_STRING ) - { - for (;;) - { - pTarget = gEntList.FindEntityByName( pTarget, GetEntityName(), NULL ); - - if ( pTarget != this ) - { - if ( !pTarget ) - break; - - CBaseDoor *pDoor = dynamic_cast(pTarget); - - if ( pDoor && count < listMax ) - { - pDoorList[count] = pDoor; - count++; - } - } - } - } - - return count; -} - -//----------------------------------------------------------------------------- -// Purpose: Called the first frame that the door is blocked while opening or closing. -// Input : pOther - The blocking entity. -//----------------------------------------------------------------------------- -void CBaseDoor::StartBlocked( CBaseEntity *pOther ) -{ - // - // Fire whatever events we need to due to our blocked state. - // - if (m_toggle_state == TS_GOING_DOWN) - { - m_OnBlockedClosing.FireOutput(pOther, this); - } - else - { - m_OnBlockedOpening.FireOutput(pOther, this); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Called every frame when the door is blocked while opening or closing. -// Input : pOther - The blocking entity. -//----------------------------------------------------------------------------- -void CBaseDoor::Blocked( CBaseEntity *pOther ) -{ - // Hurt the blocker a little. - if ( m_flBlockDamage ) - { - // if the door is marked "force closed" or it has a negative wait, then there's nothing to do but - // push/damage the object. - // If block damage is set, but this object is a physics prop that can't be damaged, just - // give up and disable collisions - if ( (m_bForceClosed || m_flWait < 0) && pOther->GetMoveType() == MOVETYPE_VPHYSICS && - (pOther->m_takedamage == DAMAGE_NO || pOther->m_takedamage == DAMAGE_EVENTS_ONLY) ) - { - EntityPhysics_CreateSolver( this, pOther, true, 4.0f ); - } - else - { - pOther->TakeDamage( CTakeDamageInfo( this, this, m_flBlockDamage, DMG_CRUSH ) ); - } - } - - // If we're set to force ourselves closed, keep going - if ( m_bForceClosed ) - return; - - // if a door has a negative wait, it would never come back if blocked, - // so let it just squash the object to death real fast - if (m_flWait >= 0) - { - if (m_toggle_state == TS_GOING_DOWN) - { - DoorGoUp(); - } - else - { - DoorGoDown(); - } - } - - // Block all door pieces with the same targetname here. - if ( GetEntityName() != NULL_STRING ) - { - CBaseDoor *pDoorList[64]; - int doorCount = GetDoorMovementGroup( pDoorList, ARRAYSIZE(pDoorList) ); - - for ( int i = 0; i < doorCount; i++ ) - { - CBaseDoor *pDoor = pDoorList[i]; - - if ( pDoor->m_flWait >= 0) - { - if (m_bDoorGroup && pDoor->m_vecMoveDir == m_vecMoveDir && pDoor->GetAbsVelocity() == GetAbsVelocity() && pDoor->GetLocalAngularVelocity() == GetLocalAngularVelocity()) - { - pDoor->m_nSimulationTick = m_nSimulationTick; // don't run simulation this frame if you haven't run yet - - // this is the most hacked, evil, bastardized thing I've ever seen. kjb - if ( !pDoor->IsRotatingDoor() ) - {// set origin to realign normal doors - pDoor->SetLocalOrigin( GetLocalOrigin() ); - pDoor->SetAbsVelocity( vec3_origin );// stop! - - } - else - {// set angles to realign rotating doors - pDoor->SetLocalAngles( GetLocalAngles() ); - pDoor->SetLocalAngularVelocity( vec3_angle ); - } - } - - if ( pDoor->m_toggle_state == TS_GOING_DOWN) - pDoor->DoorGoUp(); - else - pDoor->DoorGoDown(); - } - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Called the first frame that the door is unblocked while opening or closing. -//----------------------------------------------------------------------------- -void CBaseDoor::EndBlocked( void ) -{ - // - // Fire whatever events we need to due to our unblocked state. - // - if (m_toggle_state == TS_GOING_DOWN) - { - m_OnUnblockedClosing.FireOutput(this, this); - } - else - { - m_OnUnblockedOpening.FireOutput(this, this); - } -} - - -/*func_door_rotating - -TOGGLE causes the door to wait in both the start and end states for -a trigger event. - -START_OPEN causes the door to move to its destination when spawned, -and operate in reverse. It is used to temporarily or permanently -close off an area when triggered (not usefull for touch or -takedamage doors). - -You need to have an origin brush as part of this entity. The -center of that brush will be -the point around which it is rotated. It will rotate around the Z -axis by default. You can -check either the X_AXIS or Y_AXIS box to change that. - -"distance" is how many degrees the door will be rotated. -"speed" determines how fast the door moves; default value is 100. - -REVERSE will cause the door to rotate in the opposite direction. - -"angle" determines the opening direction -"targetname" if set, no touch field will be spawned and a remote -button or trigger field activates the door. -"health" if set, door must be shot open -"speed" movement speed (100 default) -"wait" wait before returning (3 default, -1 = never return) -"dmg" damage to inflict when blocked (2 default) -*/ - -//================================================== -// CRotDoor -//================================================== - -class CRotDoor : public CBaseDoor -{ -public: - DECLARE_CLASS( CRotDoor, CBaseDoor ); - - void Spawn( void ); - bool CreateVPhysics(); - // This is ONLY used by the node graph to test movement through a door - virtual void SetToggleState( int state ); - virtual bool IsRotatingDoor() { return true; } - - bool m_bSolidBsp; - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( func_door_rotating, CRotDoor ); - -BEGIN_DATADESC( CRotDoor ) - DEFINE_KEYFIELD( m_bSolidBsp, FIELD_BOOLEAN, "solidbsp" ), -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CRotDoor::Spawn( void ) -{ - BaseClass::Spawn(); - - // set the axis of rotation - CBaseToggle::AxisDir(); - - // check for clockwise rotation - if ( HasSpawnFlags(SF_DOOR_ROTATE_BACKWARDS) ) - m_vecMoveAng = m_vecMoveAng * -1; - - //m_flWait = 2; who the hell did this? (sjb) - m_vecAngle1 = GetLocalAngles(); - m_vecAngle2 = GetLocalAngles() + m_vecMoveAng * m_flMoveDistance; - - ASSERTSZ(m_vecAngle1 != m_vecAngle2, "rotating door start/end positions are equal\n"); - - // Starting open allows a func_door to be lighted in the closed position but - // spawn in the open position - // - // SF_DOOR_START_OPEN_OBSOLETE is an old broken way of spawning open that has - // been deprecated. - if ( HasSpawnFlags(SF_DOOR_START_OPEN_OBSOLETE) ) - { - // swap pos1 and pos2, put door at pos2, invert movement direction - QAngle vecNewAngles = m_vecAngle2; - m_vecAngle2 = m_vecAngle1; - m_vecAngle1 = vecNewAngles; - m_vecMoveAng = -m_vecMoveAng; - - // We've already had our physics setup in BaseClass::Spawn, so teleport to our - // current position. If we don't do this, our vphysics shadow will not update. - Teleport( NULL, &m_vecAngle1, NULL ); - - m_toggle_state = TS_AT_BOTTOM; - } - else if ( m_eSpawnPosition == FUNC_DOOR_SPAWN_OPEN ) - { - // We've already had our physics setup in BaseClass::Spawn, so teleport to our - // current position. If we don't do this, our vphysics shadow will not update. - Teleport( NULL, &m_vecAngle2, NULL ); - m_toggle_state = TS_AT_TOP; - } - else - { - m_toggle_state = TS_AT_BOTTOM; - } - -#ifdef HL1_DLL - SetSolid( SOLID_VPHYSICS ); -#endif - - // Slam the object back to solid - if we really want it to be solid. - if ( m_bSolidBsp ) - { - SetSolid( SOLID_BSP ); - } -} - -//----------------------------------------------------------------------------- - -bool CRotDoor::CreateVPhysics() -{ - if ( !IsSolidFlagSet( FSOLID_NOT_SOLID ) ) - { - VPhysicsInitShadow( false, false ); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : state - -//----------------------------------------------------------------------------- -// This is ONLY used by the node graph to test movement through a door -void CRotDoor::SetToggleState( int state ) -{ - if ( state == TS_AT_TOP ) - SetLocalAngles( m_vecAngle2 ); - else - SetLocalAngles( m_vecAngle1 ); -} diff --git a/game/server/doors.h b/game/server/doors.h deleted file mode 100644 index be4ec32fe..000000000 --- a/game/server/doors.h +++ /dev/null @@ -1,161 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef DOORS_H -#define DOORS_H -#pragma once - - -#include "locksounds.h" -#include "entityoutput.h" - -//Since I'm here, might as well explain how these work. Base.fgd is the file that connects -//flags to entities. It is full of lines with this number, a label, and a default value. -//Voila, dynamicly generated checkboxes on the Flags tab of Entity Properties. - -// doors -#define SF_DOOR_ROTATE_YAW 0 // yaw by default -#define SF_DOOR_START_OPEN_OBSOLETE 1 -#define SF_DOOR_ROTATE_BACKWARDS 2 -#define SF_DOOR_NONSOLID_TO_PLAYER 4 -#define SF_DOOR_PASSABLE 8 -#define SF_DOOR_ONEWAY 16 -#define SF_DOOR_NO_AUTO_RETURN 32 -#define SF_DOOR_ROTATE_ROLL 64 -#define SF_DOOR_ROTATE_PITCH 128 -#define SF_DOOR_PUSE 256 // door can be opened by player's use button. -#define SF_DOOR_NONPCS 512 // NPC can't open -#define SF_DOOR_PTOUCH 1024 // player touch opens -#define SF_DOOR_LOCKED 2048 // Door is initially locked -#define SF_DOOR_SILENT 4096 // Door plays no audible sound, and does not alert NPCs when opened -#define SF_DOOR_USE_CLOSES 8192 // Door can be +used to close before its autoreturn delay has expired. -#define SF_DOOR_SILENT_TO_NPCS 16384 // Does not alert NPC's when opened. -#define SF_DOOR_IGNORE_USE 32768 // Completely ignores player +use commands. -#define SF_DOOR_NEW_USE_RULES 65536 // For func_door entities, behave more like prop_door_rotating with respect to +USE (changelist 242482) - - -enum FuncDoorSpawnPos_t -{ - FUNC_DOOR_SPAWN_CLOSED = 0, - FUNC_DOOR_SPAWN_OPEN, -}; - - -class CBaseDoor : public CBaseToggle -{ -public: - DECLARE_CLASS( CBaseDoor, CBaseToggle ); - - DECLARE_SERVERCLASS(); - - void Spawn( void ); - void Precache( void ); - bool CreateVPhysics(); - bool KeyValue( const char *szKeyName, const char *szValue ); - virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - virtual void StartBlocked( CBaseEntity *pOther ); - virtual void Blocked( CBaseEntity *pOther ); - virtual void EndBlocked( void ); - - void Activate( void ); - - virtual int ObjectCaps( void ) - { - int flags = BaseClass::ObjectCaps(); - if ( HasSpawnFlags( SF_DOOR_PUSE ) ) - return flags | FCAP_IMPULSE_USE | FCAP_USE_IN_RADIUS; - - return flags; - }; - - DECLARE_DATADESC(); - - // This is ONLY used by the node graph to test movement through a door - void InputSetToggleState( inputdata_t &inputdata ); - virtual void SetToggleState( int state ); - - virtual bool IsRotatingDoor() { return false; } - virtual bool ShouldSavePhysics(); - // used to selectivly override defaults - void DoorTouch( CBaseEntity *pOther ); - - // local functions - int DoorActivate( ); - void DoorGoUp( void ); - void DoorGoDown( void ); - void DoorHitTop( void ); - void DoorHitBottom( void ); - void UpdateAreaPortals( bool isOpen ); - void Unlock( void ); - void Lock( void ); - int GetDoorMovementGroup( CBaseDoor *pDoorList[], int listMax ); - - // Input handlers - void InputClose( inputdata_t &inputdata ); - void InputLock( inputdata_t &inputdata ); - void InputOpen( inputdata_t &inputdata ); - void InputToggle( inputdata_t &inputdata ); - void InputUnlock( inputdata_t &inputdata ); - void InputSetSpeed( inputdata_t &inputdata ); - - Vector m_vecMoveDir; // The direction of motion for linear moving doors. - - locksound_t m_ls; // door lock sounds - - byte m_bLockedSentence; - byte m_bUnlockedSentence; - - bool m_bForceClosed; // If set, always close, even if we're blocked. - bool m_bDoorGroup; - bool m_bLocked; // Whether the door is locked - bool m_bIgnoreDebris; - - FuncDoorSpawnPos_t m_eSpawnPosition; - - float m_flBlockDamage; // Damage inflicted when blocked. - string_t m_NoiseMoving; //Start/Looping sound - string_t m_NoiseArrived; //End sound - string_t m_NoiseMovingClosed; //Start/Looping sound - string_t m_NoiseArrivedClosed; //End sound - string_t m_ChainTarget; ///< Entity name to pass Touch and Use events to - - CNetworkVar( float, m_flWaveHeight ); - - // Outputs - COutputEvent m_OnBlockedClosing; // Triggered when the door becomes blocked while closing. - COutputEvent m_OnBlockedOpening; // Triggered when the door becomes blocked while opening. - COutputEvent m_OnUnblockedClosing; // Triggered when the door becomes unblocked while closing. - COutputEvent m_OnUnblockedOpening; // Triggered when the door becomes unblocked while opening. - COutputEvent m_OnFullyClosed; // Triggered when the door reaches the fully closed position. - COutputEvent m_OnFullyOpen; // Triggered when the door reaches the fully open position. - COutputEvent m_OnClose; // Triggered when the door is told to close. - COutputEvent m_OnOpen; // Triggered when the door is told to open. - COutputEvent m_OnLockedUse; // Triggered when the user tries to open a locked door. - - void StartMovingSound( void ); - virtual void StopMovingSound( void ); - void MovingSoundThink( void ); -#ifdef HL1_DLL - bool PassesBlockTouchFilter(CBaseEntity *pOther); - string_t m_iBlockFilterName; - EHANDLE m_hBlockFilter; -#endif - - bool ShouldLoopMoveSound( void ) { return m_bLoopMoveSound; } - bool m_bLoopMoveSound; // Move sound loops until stopped - -private: - void ChainUse( void ); ///< Chains +use on through to m_ChainTarget - void ChainTouch( CBaseEntity *pOther ); ///< Chains touch on through to m_ChainTarget - void SetChaining( bool chaining ) { m_isChaining = chaining; } ///< Latch to prevent recursion - bool m_isChaining; - - void CloseAreaPortalsThink( void ); ///< Delays turning off area portals when closing doors to prevent visual artifacts -}; - -#endif // DOORS_H diff --git a/game/server/dynamiclight.cpp b/game/server/dynamiclight.cpp deleted file mode 100644 index 0436f6587..000000000 --- a/game/server/dynamiclight.cpp +++ /dev/null @@ -1,203 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Dynamic light. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "dlight.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -#define NUM_DL_EXPONENT_BITS 8 -#define MIN_DL_EXPONENT_VALUE -((1 << (NUM_DL_EXPONENT_BITS-1)) - 1) -#define MAX_DL_EXPONENT_VALUE ((1 << (NUM_DL_EXPONENT_BITS-1)) - 1) - - -class CDynamicLight : public CBaseEntity -{ -public: - DECLARE_CLASS( CDynamicLight, CBaseEntity ); - - void Spawn( void ); - void DynamicLightThink( void ); - bool KeyValue( const char *szKeyName, const char *szValue ); - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - // Turn on and off the light - void InputTurnOn( inputdata_t &inputdata ); - void InputTurnOff( inputdata_t &inputdata ); - void InputToggle( inputdata_t &inputdata ); - -public: - unsigned char m_ActualFlags; - CNetworkVar( unsigned char, m_Flags ); - CNetworkVar( unsigned char, m_LightStyle ); - bool m_On; - CNetworkVar( float, m_Radius ); - CNetworkVar( int, m_Exponent ); - CNetworkVar( float, m_InnerAngle ); - CNetworkVar( float, m_OuterAngle ); - CNetworkVar( float, m_SpotRadius ); -}; - -LINK_ENTITY_TO_CLASS(light_dynamic, CDynamicLight); - -BEGIN_DATADESC( CDynamicLight ) - - DEFINE_FIELD( m_ActualFlags, FIELD_CHARACTER ), - DEFINE_FIELD( m_Flags, FIELD_CHARACTER ), - DEFINE_FIELD( m_On, FIELD_BOOLEAN ), - - DEFINE_THINKFUNC( DynamicLightThink ), - - // Inputs - DEFINE_INPUT( m_Radius, FIELD_FLOAT, "distance" ), - DEFINE_INPUT( m_Exponent, FIELD_INTEGER, "brightness" ), - DEFINE_INPUT( m_InnerAngle, FIELD_FLOAT, "_inner_cone" ), - DEFINE_INPUT( m_OuterAngle, FIELD_FLOAT, "_cone" ), - DEFINE_INPUT( m_SpotRadius, FIELD_FLOAT, "spotlight_radius" ), - DEFINE_INPUT( m_LightStyle, FIELD_CHARACTER,"style" ), - - // Input functions - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - -END_DATADESC() - - -IMPLEMENT_SERVERCLASS_ST(CDynamicLight, DT_DynamicLight) - SendPropInt( SENDINFO(m_Flags), 4, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_LightStyle), 4, SPROP_UNSIGNED ), - SendPropFloat( SENDINFO(m_Radius), 0, SPROP_NOSCALE), - SendPropInt( SENDINFO(m_Exponent), NUM_DL_EXPONENT_BITS), - SendPropFloat( SENDINFO(m_InnerAngle), 8, 0, 0.0, 360.0f ), - SendPropFloat( SENDINFO(m_OuterAngle), 8, 0, 0.0, 360.0f ), - SendPropFloat( SENDINFO(m_SpotRadius), 0, SPROP_NOSCALE), -END_SEND_TABLE() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDynamicLight::KeyValue( const char *szKeyName, const char *szValue ) -{ - if ( FStrEq( szKeyName, "_light" ) ) - { - color32 tmp; - UTIL_StringToColor32( &tmp, szValue ); - SetRenderColor( tmp.r, tmp.g, tmp.b ); - } - else if ( FStrEq( szKeyName, "pitch" ) ) - { - float angle = atof(szValue); - if ( angle ) - { - QAngle angles = GetAbsAngles(); - angles[PITCH] = -angle; - SetAbsAngles( angles ); - } - } - else if ( FStrEq( szKeyName, "spawnflags" ) ) - { - m_ActualFlags = m_Flags = atoi(szValue); - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } - - return true; -} - -//------------------------------------------------------------------------------ -// Turn on and off the light -//------------------------------------------------------------------------------ -void CDynamicLight::InputTurnOn( inputdata_t &inputdata ) -{ - m_Flags = m_ActualFlags; - m_On = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CDynamicLight::InputTurnOff( inputdata_t &inputdata ) -{ - // This basically shuts it off - m_Flags = DLIGHT_NO_MODEL_ILLUMINATION | DLIGHT_NO_WORLD_ILLUMINATION; - m_On = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CDynamicLight::InputToggle( inputdata_t &inputdata ) -{ - if (m_On) - { - InputTurnOff( inputdata ); - } - else - { - InputTurnOn( inputdata ); - } -} - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CDynamicLight::Spawn( void ) -{ - Precache(); - SetSolid( SOLID_NONE ); - m_On = true; - UTIL_SetSize( this, vec3_origin, vec3_origin ); - AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); - - // If we have a target, think so we can orient towards it - if ( m_target != NULL_STRING ) - { - SetThink( &CDynamicLight::DynamicLightThink ); - SetNextThink( gpGlobals->curtime + 0.1 ); - } - - int clampedExponent = clamp( m_Exponent, MIN_DL_EXPONENT_VALUE, MAX_DL_EXPONENT_VALUE ); - if ( m_Exponent != clampedExponent ) - { - Warning( "light_dynamic at [%d %d %d] has invalid exponent value (%d must be between %d and %d).\n", - (int)GetAbsOrigin().x, (int)GetAbsOrigin().x, (int)GetAbsOrigin().x, - m_Exponent.Get(), - MIN_DL_EXPONENT_VALUE, - MAX_DL_EXPONENT_VALUE ); - - m_Exponent = clampedExponent; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDynamicLight::DynamicLightThink( void ) -{ - if ( m_target == NULL_STRING ) - return; - - CBaseEntity *pEntity = GetNextTarget(); - if ( pEntity ) - { - Vector vecToTarget = (pEntity->GetAbsOrigin() - GetAbsOrigin()); - QAngle vecAngles; - VectorAngles( vecToTarget, vecAngles ); - SetAbsAngles( vecAngles ); - } - - SetNextThink( gpGlobals->curtime + 0.1 ); -} diff --git a/game/server/effects.cpp b/game/server/effects.cpp deleted file mode 100644 index 8cb2160bd..000000000 --- a/game/server/effects.cpp +++ /dev/null @@ -1,2379 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements a grab bag of visual effects entities. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "effects.h" -#include "gib.h" -#include "beam_shared.h" -#include "decals.h" -#include "func_break.h" -#include "EntityFlame.h" -#include "entitylist.h" -#include "basecombatweapon.h" -#include "model_types.h" -#include "player.h" -#include "physics.h" -#include "baseparticleentity.h" -#include "ndebugoverlay.h" -#include "IEffects.h" -#include "vstdlib/random.h" -#include "env_wind_shared.h" -#include "filesystem.h" -#include "engine/IEngineSound.h" -#include "fire.h" -#include "te_effect_dispatch.h" -#include "Sprite.h" -#include "precipitation_shared.h" -#include "shot_manipulator.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SF_FUNNEL_REVERSE 1 // funnel effect repels particles instead of attracting them. - -#define SF_GIBSHOOTER_REPEATABLE (1<<0) // allows a gibshooter to be refired -#define SF_SHOOTER_FLAMING (1<<1) // gib is on fire -#define SF_SHOOTER_STRICT_REMOVE (1<<2) // remove this gib even if it is in the player's view - -// UNDONE: This should be client-side and not use TempEnts -class CBubbling : public CBaseEntity -{ -public: - DECLARE_CLASS( CBubbling, CBaseEntity ); - - virtual void Spawn( void ); - virtual void Precache( void ); - - void FizzThink( void ); - - // Input handlers. - void InputActivate( inputdata_t &inputdata ); - void InputDeactivate( inputdata_t &inputdata ); - void InputToggle( inputdata_t &inputdata ); - - void InputSetCurrent( inputdata_t &inputdata ); - void InputSetDensity( inputdata_t &inputdata ); - void InputSetFrequency( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - -private: - - void TurnOn(); - void TurnOff(); - void Toggle(); - - int m_density; - int m_frequency; - int m_bubbleModel; - int m_state; -}; - -LINK_ENTITY_TO_CLASS( env_bubbles, CBubbling ); - -BEGIN_DATADESC( CBubbling ) - - DEFINE_KEYFIELD( m_flSpeed, FIELD_FLOAT, "current" ), - DEFINE_KEYFIELD( m_density, FIELD_INTEGER, "density" ), - DEFINE_KEYFIELD( m_frequency, FIELD_INTEGER, "frequency" ), - - DEFINE_FIELD( m_state, FIELD_INTEGER ), - // Let spawn restore this! - // DEFINE_FIELD( m_bubbleModel, FIELD_INTEGER ), - - // Function Pointers - DEFINE_FUNCTION( FizzThink ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ), - DEFINE_INPUTFUNC( FIELD_VOID, "Deactivate", InputDeactivate ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetCurrent", InputSetCurrent ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetDensity", InputSetDensity ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetFrequency", InputSetFrequency ), - -END_DATADESC() - - - -#define SF_BUBBLES_STARTOFF 0x0001 - -void CBubbling::Spawn( void ) -{ - Precache( ); - SetModel( STRING( GetModelName() ) ); // Set size - - // Make it invisible to client - SetRenderColorA( 0 ); - - SetSolid( SOLID_NONE ); // Remove model & collisions - - if ( !HasSpawnFlags(SF_BUBBLES_STARTOFF) ) - { - SetThink( &CBubbling::FizzThink ); - SetNextThink( gpGlobals->curtime + 2.0 ); - m_state = 1; - } - else - { - m_state = 0; - } -} - -void CBubbling::Precache( void ) -{ - m_bubbleModel = PrecacheModel("sprites/bubble.vmt"); // Precache bubble sprite -} - - -void CBubbling::Toggle() -{ - if (!m_state) - { - TurnOn(); - } - else - { - TurnOff(); - } -} - - -void CBubbling::TurnOn() -{ - m_state = 1; - SetThink( &CBubbling::FizzThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -void CBubbling::TurnOff() -{ - m_state = 0; - SetThink( NULL ); - SetNextThink( TICK_NEVER_THINK ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBubbling::InputActivate( inputdata_t &inputdata ) -{ - TurnOn(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBubbling::InputDeactivate( inputdata_t &inputdata ) -{ - TurnOff(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBubbling::InputToggle( inputdata_t &inputdata ) -{ - Toggle(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CBubbling::InputSetCurrent( inputdata_t &inputdata ) -{ - m_flSpeed = (float)inputdata.value.Int(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CBubbling::InputSetDensity( inputdata_t &inputdata ) -{ - m_density = inputdata.value.Int(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CBubbling::InputSetFrequency( inputdata_t &inputdata ) -{ - m_frequency = inputdata.value.Int(); - - // Reset think time - if ( m_state ) - { - if ( m_frequency > 19 ) - { - SetNextThink( gpGlobals->curtime + 0.5f ); - } - else - { - SetNextThink( gpGlobals->curtime + 2.5 - (0.1 * m_frequency) ); - } - } -} - -void CBubbling::FizzThink( void ) -{ - Vector center = WorldSpaceCenter(); - CPASFilter filter( center ); - te->Fizz( filter, 0.0, this, m_bubbleModel, m_density, (int)m_flSpeed ); - - if ( m_frequency > 19 ) - { - SetNextThink( gpGlobals->curtime + 0.5f ); - } - else - { - SetNextThink( gpGlobals->curtime + 2.5 - (0.1 * m_frequency) ); - } -} - - -// ENV_TRACER -// Fakes a tracer -class CEnvTracer : public CPointEntity -{ -public: - DECLARE_CLASS( CEnvTracer, CPointEntity ); - - void Spawn( void ); - void TracerThink( void ); - void Activate( void ); - - DECLARE_DATADESC(); - - Vector m_vecEnd; - float m_flDelay; -}; - -LINK_ENTITY_TO_CLASS( env_tracer, CEnvTracer ); - -BEGIN_DATADESC( CEnvTracer ) - - DEFINE_KEYFIELD( m_flDelay, FIELD_FLOAT, "delay" ), - - DEFINE_FIELD( m_vecEnd, FIELD_POSITION_VECTOR ), - - // Function Pointers - DEFINE_FUNCTION( TracerThink ), - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Purpose: Called after keyvalues are parsed. -//----------------------------------------------------------------------------- -void CEnvTracer::Spawn( void ) -{ - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NONE ); - - if (!m_flDelay) - m_flDelay = 1; -} - - -//----------------------------------------------------------------------------- -// Purpose: Called after all the entities have been loaded. -//----------------------------------------------------------------------------- -void CEnvTracer::Activate( void ) -{ - BaseClass::Activate(); - - CBaseEntity *pEnd = gEntList.FindEntityByName( NULL, m_target ); - if (pEnd != NULL) - { - m_vecEnd = pEnd->GetLocalOrigin(); - SetThink( &CEnvTracer::TracerThink ); - SetNextThink( gpGlobals->curtime + m_flDelay ); - } - else - { - Msg( "env_tracer: unknown entity \"%s\"\n", STRING(m_target) ); - } -} - -// Think -void CEnvTracer::TracerThink( void ) -{ - UTIL_Tracer( GetAbsOrigin(), m_vecEnd ); - - SetNextThink( gpGlobals->curtime + m_flDelay ); -} - - -//################################################################################# -// >> CGibShooter -//################################################################################# -enum GibSimulation_t -{ - GIB_SIMULATE_POINT, - GIB_SIMULATE_PHYSICS, - GIB_SIMULATE_RAGDOLL, -}; - -class CGibShooter : public CBaseEntity -{ -public: - DECLARE_CLASS( CGibShooter, CBaseEntity ); - - void Spawn( void ); - void Precache( void ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - virtual CGib *CreateGib( void ); - -protected: - // Purpose: - CBaseEntity *SpawnGib( const Vector &vecShootDir, float flSpeed ); - - DECLARE_DATADESC(); -private: - void InitPointGib( CGib *pGib, const Vector &vecShootDir, float flSpeed ); - void ShootThink( void ); - -protected: - int m_iGibs; - int m_iGibCapacity; - int m_iGibMaterial; - int m_iGibModelIndex; - float m_flGibVelocity; - QAngle m_angGibRotation; - float m_flGibAngVelocity; - float m_flVariance; - float m_flGibLife; - int m_nSimulationType; - int m_nMaxGibModelFrame; - float m_flDelay; - - bool m_bNoGibShadows; - - bool m_bIsSprite; - string_t m_iszLightingOrigin; - - // ---------------- - // Inputs - // ---------------- - void InputShoot( inputdata_t &inputdata ); -}; - -BEGIN_DATADESC( CGibShooter ) - - DEFINE_KEYFIELD( m_iGibs, FIELD_INTEGER, "m_iGibs" ), - DEFINE_KEYFIELD( m_flGibVelocity, FIELD_FLOAT, "m_flVelocity" ), - DEFINE_KEYFIELD( m_flVariance, FIELD_FLOAT, "m_flVariance" ), - DEFINE_KEYFIELD( m_flGibLife, FIELD_FLOAT, "m_flGibLife" ), - DEFINE_KEYFIELD( m_nSimulationType, FIELD_INTEGER, "Simulation" ), - DEFINE_KEYFIELD( m_flDelay, FIELD_FLOAT, "delay" ), - DEFINE_KEYFIELD( m_angGibRotation, FIELD_VECTOR, "gibangles" ), - DEFINE_KEYFIELD( m_flGibAngVelocity, FIELD_FLOAT, "gibanglevelocity"), - DEFINE_FIELD( m_bIsSprite, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_iGibCapacity, FIELD_INTEGER ), - DEFINE_FIELD( m_iGibMaterial, FIELD_INTEGER ), - DEFINE_FIELD( m_iGibModelIndex, FIELD_INTEGER ), - DEFINE_FIELD( m_nMaxGibModelFrame, FIELD_INTEGER ), - - DEFINE_KEYFIELD( m_iszLightingOrigin, FIELD_STRING, "LightingOrigin" ), - DEFINE_KEYFIELD( m_bNoGibShadows, FIELD_BOOLEAN, "nogibshadows" ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Shoot", InputShoot ), - - // Function Pointers - DEFINE_FUNCTION( ShootThink ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( gibshooter, CGibShooter ); - - -void CGibShooter::Precache ( void ) -{ - if ( g_Language.GetInt() == LANGUAGE_GERMAN ) - { - m_iGibModelIndex = PrecacheModel ("models/germanygibs.mdl"); - } - else - { - m_iGibModelIndex = PrecacheModel ("models/gibs/hgibs.mdl"); - } -} - - -void CGibShooter::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - SetThink( &CGibShooter::ShootThink ); - SetNextThink( gpGlobals->curtime ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for shooting gibs. -//----------------------------------------------------------------------------- -void CGibShooter::InputShoot( inputdata_t &inputdata ) -{ - SetThink( &CGibShooter::ShootThink ); - SetNextThink( gpGlobals->curtime ); -} - - -void CGibShooter::Spawn( void ) -{ - Precache(); - - SetSolid( SOLID_NONE ); - AddEffects( EF_NODRAW ); - - if ( m_flDelay < 0 ) - { - m_flDelay = 0.0; - } - - if ( m_flGibLife == 0 ) - { - m_flGibLife = 25; - } - - m_iGibCapacity = m_iGibs; - - m_nMaxGibModelFrame = modelinfo->GetModelFrameCount( modelinfo->GetModel( m_iGibModelIndex ) ); -} - -CGib *CGibShooter::CreateGib ( void ) -{ - ConVarRef violence_hgibs( "violence_hgibs" ); - if ( violence_hgibs.IsValid() && !violence_hgibs.GetInt() ) - return NULL; - - CGib *pGib = CREATE_ENTITY( CGib, "gib" ); - pGib->Spawn( "models/gibs/hgibs.mdl" ); - pGib->SetBloodColor( BLOOD_COLOR_RED ); - - if ( m_nMaxGibModelFrame <= 1 ) - { - DevWarning( 2, "GibShooter Body is <= 1!\n" ); - } - - pGib->m_nBody = random->RandomInt ( 1, m_nMaxGibModelFrame - 1 );// avoid throwing random amounts of the 0th gib. (skull). - - if ( m_iszLightingOrigin != NULL_STRING ) - { - // Make the gibs use the lighting origin - pGib->SetLightingOrigin( m_iszLightingOrigin ); - } - - return pGib; -} - - -void CGibShooter::InitPointGib( CGib *pGib, const Vector &vecShootDir, float flSpeed ) -{ - if ( pGib ) - { - pGib->SetLocalOrigin( GetAbsOrigin() ); - pGib->SetAbsVelocity( vecShootDir * flSpeed ); - - QAngle angVel( random->RandomFloat ( 100, 200 ), random->RandomFloat ( 100, 300 ), 0 ); - pGib->SetLocalAngularVelocity( angVel ); - - float thinkTime = ( pGib->GetNextThink() - gpGlobals->curtime ); - - pGib->m_lifeTime = (m_flGibLife * random->RandomFloat( 0.95, 1.05 )); // +/- 5% - - // HL1 gibs always die after a certain time, other games have to opt-in -#ifndef HL1_DLL - if( HasSpawnFlags( SF_SHOOTER_STRICT_REMOVE ) ) -#endif - { - pGib->SetNextThink( gpGlobals->curtime + pGib->m_lifeTime ); - pGib->SetThink ( &CGib::DieThink ); - } - - if ( pGib->m_lifeTime < thinkTime ) - { - pGib->SetNextThink( gpGlobals->curtime + pGib->m_lifeTime ); - pGib->m_lifeTime = 0; - } - - if ( m_bIsSprite == true ) - { - pGib->SetSprite( CSprite::SpriteCreate( STRING( GetModelName() ), pGib->GetAbsOrigin(), false ) ); - - CSprite *pSprite = (CSprite*)pGib->GetSprite(); - - if ( pSprite ) - { - pSprite->SetAttachment( pGib, 0 ); - pSprite->SetOwnerEntity( pGib ); - - pSprite->SetScale( 1 ); - pSprite->SetTransparency( m_nRenderMode, m_clrRender->r, m_clrRender->g, m_clrRender->b, m_clrRender->a, m_nRenderFX ); - pSprite->AnimateForTime( 5, m_flGibLife + 1 ); //This framerate is totally wrong - } - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseEntity *CGibShooter::SpawnGib( const Vector &vecShootDir, float flSpeed ) -{ - switch (m_nSimulationType) - { - case GIB_SIMULATE_RAGDOLL: - { - // UNDONE: Assume a mass of 200 for now - Vector force = vecShootDir * flSpeed * 200; - return CreateRagGib( STRING( GetModelName() ), GetAbsOrigin(), GetAbsAngles(), force, m_flGibLife ); - } - - case GIB_SIMULATE_PHYSICS: - { - CGib *pGib = CreateGib(); - - if ( pGib ) - { - pGib->SetAbsOrigin( GetAbsOrigin() ); - pGib->SetAbsAngles( m_angGibRotation ); - - pGib->m_lifeTime = (m_flGibLife * random->RandomFloat( 0.95, 1.05 )); // +/- 5% - - pGib->SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - IPhysicsObject *pPhysicsObject = pGib->VPhysicsInitNormal( SOLID_VPHYSICS, pGib->GetSolidFlags(), false ); - pGib->SetMoveType( MOVETYPE_VPHYSICS ); - - if ( pPhysicsObject ) - { - // Set gib velocity - Vector vVel = vecShootDir * flSpeed; - pPhysicsObject->AddVelocity(&vVel, NULL); - - AngularImpulse torque; - torque.x = m_flGibAngVelocity * random->RandomFloat( 0.1f, 1.0f ); - torque.y = m_flGibAngVelocity * random->RandomFloat( 0.1f, 1.0f ); - torque.z = 0.0f; - torque *= pPhysicsObject->GetMass(); - - pPhysicsObject->ApplyTorqueCenter( torque ); - -#ifndef HL1_DLL - if( HasSpawnFlags( SF_SHOOTER_STRICT_REMOVE ) ) -#endif - { - pGib->m_bForceRemove = true; - pGib->SetNextThink( gpGlobals->curtime + pGib->m_lifeTime ); - pGib->SetThink ( &CGib::DieThink ); - } - - } - else - { - InitPointGib( pGib, vecShootDir, flSpeed ); - } - } - return pGib; - } - - case GIB_SIMULATE_POINT: - { - CGib *pGib = CreateGib(); - - if ( pGib ) - { - pGib->SetAbsAngles( m_angGibRotation ); - - InitPointGib( pGib, vecShootDir, flSpeed ); - return pGib; - } - } - } - - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGibShooter::ShootThink ( void ) -{ - SetNextThink( gpGlobals->curtime + m_flDelay ); - - Vector vecShootDir, vForward,vRight,vUp; - AngleVectors( GetAbsAngles(), &vForward, &vRight, &vUp ); - vecShootDir = vForward; - vecShootDir = vecShootDir + vRight * random->RandomFloat( -1, 1) * m_flVariance; - vecShootDir = vecShootDir + vForward * random->RandomFloat( -1, 1) * m_flVariance; - vecShootDir = vecShootDir + vUp * random->RandomFloat( -1, 1) * m_flVariance; - - VectorNormalize( vecShootDir ); - - SpawnGib( vecShootDir, m_flGibVelocity ); - - if ( --m_iGibs <= 0 ) - { - if ( HasSpawnFlags(SF_GIBSHOOTER_REPEATABLE) ) - { - m_iGibs = m_iGibCapacity; - SetThink ( NULL ); - SetNextThink( gpGlobals->curtime ); - } - else - { - SetThink ( &CGibShooter::SUB_Remove ); - SetNextThink( gpGlobals->curtime ); - } - } -} - -class CEnvShooter : public CGibShooter -{ -public: - DECLARE_CLASS( CEnvShooter, CGibShooter ); - - CEnvShooter() { m_flGibGravityScale = 1.0f; } - void Precache( void ); - bool KeyValue( const char *szKeyName, const char *szValue ); - - CGib *CreateGib( void ); - - DECLARE_DATADESC(); - -public: - - int m_nSkin; - float m_flGibScale; - float m_flGibGravityScale; - -#if HL2_EPISODIC - float m_flMassOverride; // allow designer to force a mass for gibs in some cases -#endif -}; - -BEGIN_DATADESC( CEnvShooter ) - - DEFINE_KEYFIELD( m_nSkin, FIELD_INTEGER, "skin" ), - DEFINE_KEYFIELD( m_flGibScale, FIELD_FLOAT ,"scale" ), - DEFINE_KEYFIELD( m_flGibGravityScale, FIELD_FLOAT, "gibgravityscale" ), - -#if HL2_EPISODIC - DEFINE_KEYFIELD( m_flMassOverride, FIELD_FLOAT, "massoverride" ), -#endif - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( env_shooter, CEnvShooter ); - -bool CEnvShooter::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "shootmodel")) - { - m_bIsSprite = false; - SetModelName( AllocPooledString(szValue) ); - - //Adrian - not pretty... - if ( Q_stristr( szValue, ".vmt" ) ) - m_bIsSprite = true; - } - - else if (FStrEq(szKeyName, "shootsounds")) - { - int iNoise = atoi(szValue); - switch( iNoise ) - { - case 0: - m_iGibMaterial = matGlass; - break; - case 1: - m_iGibMaterial = matWood; - break; - case 2: - m_iGibMaterial = matMetal; - break; - case 3: - m_iGibMaterial = matFlesh; - break; - case 4: - m_iGibMaterial = matRocks; - break; - - default: - case -1: - m_iGibMaterial = matNone; - break; - } - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } - - return true; -} - - -void CEnvShooter::Precache ( void ) -{ - m_iGibModelIndex = PrecacheModel( STRING( GetModelName() ) ); -} - - -CGib *CEnvShooter::CreateGib ( void ) -{ - CGib *pGib = CREATE_ENTITY( CGib, "gib" ); - - if ( m_bIsSprite == true ) - { - //HACK HACK - pGib->Spawn( "" ); - } - else - { - pGib->Spawn( STRING( GetModelName() ) ); - } - - int bodyPart = 0; - - if ( m_nMaxGibModelFrame > 1 ) - { - bodyPart = random->RandomInt( 0, m_nMaxGibModelFrame-1 ); - } - - pGib->m_nBody = bodyPart; - pGib->SetBloodColor( DONT_BLEED ); - pGib->m_material = m_iGibMaterial; - - pGib->m_nRenderMode = m_nRenderMode; - pGib->m_clrRender = m_clrRender; - pGib->m_nRenderFX = m_nRenderFX; - pGib->m_nSkin = m_nSkin; - pGib->m_lifeTime = gpGlobals->curtime + m_flGibLife; - - pGib->SetGravity( m_flGibGravityScale ); - - // Spawn a flaming gib - if ( HasSpawnFlags( SF_SHOOTER_FLAMING ) ) - { - // Tag an entity flame along with us - CEntityFlame *pFlame = CEntityFlame::Create( pGib, false ); - if ( pFlame != NULL ) - { - pFlame->SetLifetime( pGib->m_lifeTime ); - pGib->SetFlame( pFlame ); - } - } - - if ( m_iszLightingOrigin != NULL_STRING ) - { - // Make the gibs use the lighting origin - pGib->SetLightingOrigin( m_iszLightingOrigin ); - } - - if( m_bNoGibShadows ) - { - pGib->AddEffects( EF_NOSHADOW ); - } - -#if HL2_EPISODIC - // if a mass override is set, apply it to the gib - if (m_flMassOverride != 0) - { - IPhysicsObject *pPhys = pGib->VPhysicsGetObject(); - if (pPhys) - { - pPhys->SetMass( m_flMassOverride ); - } - } -#endif - - return pGib; -} - - -//----------------------------------------------------------------------------- -// An entity that shoots out junk when hit by a rotor wash -//----------------------------------------------------------------------------- -class CRotorWashShooter : public CEnvShooter, public IRotorWashShooter -{ -public: - DECLARE_CLASS( CRotorWashShooter, CEnvShooter ); - DECLARE_DATADESC(); - - virtual void Spawn(); - -public: - // Inherited from IRotorWashShooter - virtual CBaseEntity *DoWashPush( float flTimeSincePushStarted, const Vector &vecForce ); - -private: - // Amount of time we need to spend under the rotor before we shoot - float m_flTimeUnderRotor; - float m_flTimeUnderRotorVariance; - - // Last time we were hit with a wash... - float m_flLastWashStartTime; - float m_flNextGibTime; -}; - - -LINK_ENTITY_TO_CLASS( env_rotorshooter, CRotorWashShooter ); - - -//----------------------------------------------------------------------------- -// Save/load -//----------------------------------------------------------------------------- -BEGIN_DATADESC( CRotorWashShooter ) - - DEFINE_KEYFIELD( m_flTimeUnderRotor, FIELD_FLOAT ,"rotortime" ), - DEFINE_KEYFIELD( m_flTimeUnderRotorVariance, FIELD_FLOAT ,"rotortimevariance" ), - DEFINE_FIELD( m_flLastWashStartTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextGibTime, FIELD_TIME ), - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Gets at the interface if the entity supports it -//----------------------------------------------------------------------------- -IRotorWashShooter *GetRotorWashShooter( CBaseEntity *pEntity ) -{ - CRotorWashShooter *pShooter = dynamic_cast(pEntity); - return pShooter; -} - - -//----------------------------------------------------------------------------- -// Inherited from IRotorWashShooter -//----------------------------------------------------------------------------- -void CRotorWashShooter::Spawn() -{ - BaseClass::Spawn(); - m_flLastWashStartTime = -1; -} - - - -//----------------------------------------------------------------------------- -// Inherited from IRotorWashShooter -//----------------------------------------------------------------------------- -CBaseEntity *CRotorWashShooter::DoWashPush( float flWashStartTime, const Vector &vecForce ) -{ - if ( flWashStartTime == m_flLastWashStartTime ) - { - if ( m_flNextGibTime > gpGlobals->curtime ) - return NULL; - } - - m_flLastWashStartTime = flWashStartTime; - m_flNextGibTime = gpGlobals->curtime + m_flTimeUnderRotor + random->RandomFloat( -1, 1) * m_flTimeUnderRotorVariance; - if ( m_flNextGibTime <= gpGlobals->curtime ) - { - m_flNextGibTime = gpGlobals->curtime + 0.01f; - } - - // Set the velocity to be what the force would cause it to accelerate to - // after one tick - Vector vecShootDir = vecForce; - VectorNormalize( vecShootDir ); - - vecShootDir.x += random->RandomFloat( -1, 1 ) * m_flVariance; - vecShootDir.y += random->RandomFloat( -1, 1 ) * m_flVariance; - vecShootDir.z += random->RandomFloat( -1, 1 ) * m_flVariance; - - VectorNormalize( vecShootDir ); - - CBaseEntity *pGib = SpawnGib( vecShootDir, m_flGibVelocity /*flLength*/ ); - - if ( --m_iGibs <= 0 ) - { - if ( HasSpawnFlags(SF_GIBSHOOTER_REPEATABLE) ) - { - m_iGibs = m_iGibCapacity; - } - else - { - SetThink ( &CGibShooter::SUB_Remove ); - SetNextThink( gpGlobals->curtime ); - } - } - - return pGib; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CTestEffect : public CBaseEntity -{ -public: - DECLARE_CLASS( CTestEffect, CBaseEntity ); - - void Spawn( void ); - void Precache( void ); - // bool KeyValue( const char *szKeyName, const char *szValue ); - void Think( void ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - int m_iLoop; - int m_iBeam; - CBeam *m_pBeam[24]; - float m_flBeamTime[24]; - float m_flStartTime; -}; - - -LINK_ENTITY_TO_CLASS( test_effect, CTestEffect ); - -void CTestEffect::Spawn( void ) -{ - Precache( ); -} - -void CTestEffect::Precache( void ) -{ - PrecacheModel( "sprites/lgtning.vmt" ); -} - -void CTestEffect::Think( void ) -{ - int i; - float t = (gpGlobals->curtime - m_flStartTime); - - if (m_iBeam < 24) - { - CBeam *pbeam = CBeam::BeamCreate( "sprites/lgtning.vmt", 10 ); - - trace_t tr; - - Vector vecSrc = GetAbsOrigin(); - Vector vecDir = Vector( random->RandomFloat( -1.0, 1.0 ), random->RandomFloat( -1.0, 1.0 ),random->RandomFloat( -1.0, 1.0 ) ); - VectorNormalize( vecDir ); - UTIL_TraceLine( vecSrc, vecSrc + vecDir * 128, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr); - - pbeam->PointsInit( vecSrc, tr.endpos ); - // pbeam->SetColor( 80, 100, 255 ); - pbeam->SetColor( 255, 180, 100 ); - pbeam->SetWidth( 10.0 ); - pbeam->SetScrollRate( 12 ); - - m_flBeamTime[m_iBeam] = gpGlobals->curtime; - m_pBeam[m_iBeam] = pbeam; - m_iBeam++; - -#if 0 - Vector vecMid = (vecSrc + tr.endpos) * 0.5; - CBroadcastRecipientFilter filter; - TE_DynamicLight( filter, 0.0, - vecMid, 255, 180, 100, 3, 2.0, 0.0 ); -#endif - } - - if (t < 3.0) - { - for (i = 0; i < m_iBeam; i++) - { - t = (gpGlobals->curtime - m_flBeamTime[i]) / ( 3 + m_flStartTime - m_flBeamTime[i]); - m_pBeam[i]->SetBrightness( (int)(255 * t) ); - // m_pBeam[i]->SetScrollRate( 20 * t ); - } - SetNextThink( gpGlobals->curtime + 0.1f ); - } - else - { - for (i = 0; i < m_iBeam; i++) - { - UTIL_Remove( m_pBeam[i] ); - } - m_flStartTime = gpGlobals->curtime; - m_iBeam = 0; - SetNextThink( TICK_NEVER_THINK ); - } -} - - -void CTestEffect::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - SetNextThink( gpGlobals->curtime + 0.1f ); - m_flStartTime = gpGlobals->curtime; -} - - - -// Blood effects -class CBlood : public CPointEntity -{ -public: - DECLARE_CLASS( CBlood, CPointEntity ); - - void Spawn( void ); - bool KeyValue( const char *szKeyName, const char *szValue ); - - inline int Color( void ) { return m_Color; } - inline float BloodAmount( void ) { return m_flAmount; } - - inline void SetColor( int color ) { m_Color = color; } - - // Input handlers - void InputEmitBlood( inputdata_t &inputdata ); - - Vector Direction( void ); - Vector BloodPosition( CBaseEntity *pActivator ); - - DECLARE_DATADESC(); - - Vector m_vecSprayDir; - float m_flAmount; - int m_Color; - -private: -}; - -LINK_ENTITY_TO_CLASS( env_blood, CBlood ); - -BEGIN_DATADESC( CBlood ) - - DEFINE_KEYFIELD( m_vecSprayDir, FIELD_VECTOR, "spraydir" ), - DEFINE_KEYFIELD( m_flAmount, FIELD_FLOAT, "amount" ), - DEFINE_FIELD( m_Color, FIELD_INTEGER ), - - DEFINE_INPUTFUNC( FIELD_VOID, "EmitBlood", InputEmitBlood ), - -END_DATADESC() - - -#define SF_BLOOD_RANDOM 0x0001 -#define SF_BLOOD_STREAM 0x0002 -#define SF_BLOOD_PLAYER 0x0004 -#define SF_BLOOD_DECAL 0x0008 -#define SF_BLOOD_CLOUD 0x0010 -#define SF_BLOOD_DROPS 0x0020 -#define SF_BLOOD_GORE 0x0040 - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBlood::Spawn( void ) -{ - // Convert spraydir from angles to a vector - QAngle angSprayDir = QAngle( m_vecSprayDir.x, m_vecSprayDir.y, m_vecSprayDir.z ); - AngleVectors( angSprayDir, &m_vecSprayDir ); - - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NONE ); - SetColor( BLOOD_COLOR_RED ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : szKeyName - -// szValue - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBlood::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "color")) - { - int color = atoi(szValue); - switch ( color ) - { - case 1: - { - SetColor( BLOOD_COLOR_YELLOW ); - break; - } - } - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } - - return true; -} - - -Vector CBlood::Direction( void ) -{ - if ( HasSpawnFlags( SF_BLOOD_RANDOM ) ) - return UTIL_RandomBloodVector(); - - return m_vecSprayDir; -} - - -Vector CBlood::BloodPosition( CBaseEntity *pActivator ) -{ - if ( HasSpawnFlags( SF_BLOOD_PLAYER ) ) - { - CBasePlayer *player; - - if ( pActivator && pActivator->IsPlayer() ) - { - player = ToBasePlayer( pActivator ); - } - else - { - player = UTIL_GetLocalPlayer(); - } - - if ( player ) - { - return (player->EyePosition()) + Vector( random->RandomFloat(-10,10), random->RandomFloat(-10,10), random->RandomFloat(-10,10) ); - } - } - - return GetLocalOrigin(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void UTIL_BloodSpray( const Vector &pos, const Vector &dir, int color, int amount, int flags ) -{ - if( color == DONT_BLEED ) - return; - - CEffectData data; - - data.m_vOrigin = pos; - data.m_vNormal = dir; - data.m_flScale = (float)amount; - data.m_fFlags = flags; - data.m_nColor = color; - - DispatchEffect( "bloodspray", data ); -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for triggering the blood effect. -//----------------------------------------------------------------------------- -void CBlood::InputEmitBlood( inputdata_t &inputdata ) -{ - if ( HasSpawnFlags( SF_BLOOD_STREAM ) ) - { - UTIL_BloodStream( BloodPosition(inputdata.pActivator), Direction(), Color(), (int)BloodAmount() ); - } - else - { - UTIL_BloodDrips( BloodPosition(inputdata.pActivator), Direction(), Color(), (int)BloodAmount() ); - } - - if ( HasSpawnFlags( SF_BLOOD_DECAL ) ) - { - Vector forward = Direction(); - Vector start = BloodPosition( inputdata.pActivator ); - trace_t tr; - - UTIL_TraceLine( start, start + forward * BloodAmount() * 2, MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction != 1.0 ) - { - UTIL_BloodDecalTrace( &tr, Color() ); - } - } - - // - // New-fangled blood effects. - // - if ( HasSpawnFlags( SF_BLOOD_CLOUD | SF_BLOOD_DROPS | SF_BLOOD_GORE ) ) - { - int nFlags = 0; - if (HasSpawnFlags(SF_BLOOD_CLOUD)) - { - nFlags |= FX_BLOODSPRAY_CLOUD; - } - - if (HasSpawnFlags(SF_BLOOD_DROPS)) - { - nFlags |= FX_BLOODSPRAY_DROPS; - } - - if (HasSpawnFlags(SF_BLOOD_GORE)) - { - nFlags |= FX_BLOODSPRAY_GORE; - } - - UTIL_BloodSpray(GetAbsOrigin(), Direction(), Color(), (int)BloodAmount(), nFlags); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Console command for emitting the blood spray effect from an NPC. -//----------------------------------------------------------------------------- -void CC_BloodSpray( const CCommand &args ) -{ - CBaseEntity *pEnt = NULL; - while ( ( pEnt = gEntList.FindEntityGeneric( pEnt, args[1] ) ) != NULL ) - { - Vector forward; - pEnt->GetVectors(&forward, NULL, NULL); - UTIL_BloodSpray( (forward * 4 ) + ( pEnt->EyePosition() + pEnt->WorldSpaceCenter() ) * 0.5f, forward, BLOOD_COLOR_RED, 4, FX_BLOODSPRAY_ALL ); - } -} - -static ConCommand bloodspray( "bloodspray", CC_BloodSpray, "blood", FCVAR_CHEAT ); - - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -class CEnvFunnel : public CBaseEntity -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( CEnvFunnel, CBaseEntity ); - - void Spawn( void ); - void Precache( void ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - int m_iSprite; // Don't save, precache -}; - -LINK_ENTITY_TO_CLASS( env_funnel, CEnvFunnel ); - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CEnvFunnel ) - -// DEFINE_FIELD( m_iSprite, FIELD_INTEGER ), - -END_DATADESC() - - - -void CEnvFunnel::Precache ( void ) -{ - m_iSprite = PrecacheModel ( "sprites/flare6.vmt" ); -} - -void CEnvFunnel::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - CBroadcastRecipientFilter filter; - te->LargeFunnel( filter, 0.0, - &GetAbsOrigin(), m_iSprite, HasSpawnFlags( SF_FUNNEL_REVERSE ) ? 1 : 0 ); - - SetThink( &CEnvFunnel::SUB_Remove ); - SetNextThink( gpGlobals->curtime ); -} - -void CEnvFunnel::Spawn( void ) -{ - Precache(); - SetSolid( SOLID_NONE ); - AddEffects( EF_NODRAW ); -} - -//========================================================= -// Beverage Dispenser -// overloaded m_iHealth, is now how many cans remain in the machine. -//========================================================= -class CEnvBeverage : public CBaseEntity -{ -public: - DECLARE_CLASS( CEnvBeverage, CBaseEntity ); - - void Spawn( void ); - void Precache( void ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - bool KeyValue( const char *szKeyName, const char *szValue ); - - // Input handlers. - void InputActivate( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - -public: - bool m_CanInDispenser; - int m_nBeverageType; -}; - -void CEnvBeverage::Precache ( void ) -{ - PrecacheModel( "models/can.mdl" ); -} - -BEGIN_DATADESC( CEnvBeverage ) - DEFINE_FIELD( m_CanInDispenser, FIELD_BOOLEAN ), - DEFINE_FIELD( m_nBeverageType, FIELD_INTEGER ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ), -END_DATADESC() - -LINK_ENTITY_TO_CLASS( env_beverage, CEnvBeverage ); - - -bool CEnvBeverage::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "beveragetype")) - { - m_nBeverageType = atoi(szValue); - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } - - return true; -} - -void CEnvBeverage::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - if ( m_CanInDispenser || m_iHealth <= 0 ) - { - // no more cans while one is waiting in the dispenser, or if I'm out of cans. - return; - } - - CBaseAnimating *pCan = (CBaseAnimating *)CBaseEntity::Create( "item_sodacan", GetLocalOrigin(), GetLocalAngles(), this ); - - if ( m_nBeverageType == 6 ) - { - // random - pCan->m_nSkin = random->RandomInt( 0, 5 ); - } - else - { - pCan->m_nSkin = m_nBeverageType; - } - - m_CanInDispenser = true; - m_iHealth -= 1; - - //SetThink (SUB_Remove); - //SetNextThink( gpGlobals->curtime ); -} - -void CEnvBeverage::InputActivate( inputdata_t &inputdata ) -{ - Use( inputdata.pActivator, inputdata.pCaller, USE_ON, 0 ); -} - -void CEnvBeverage::Spawn( void ) -{ - Precache(); - SetSolid( SOLID_NONE ); - AddEffects( EF_NODRAW ); - m_CanInDispenser = false; - - if ( m_iHealth == 0 ) - { - m_iHealth = 10; - } -} - -//========================================================= -// Soda can -//========================================================= -class CItemSoda : public CBaseAnimating -{ -public: - DECLARE_CLASS( CItemSoda, CBaseAnimating ); - - void Spawn( void ); - void Precache( void ); - void CanThink ( void ); - void CanTouch ( CBaseEntity *pOther ); - - DECLARE_DATADESC(); -}; - - -BEGIN_DATADESC( CItemSoda ) - - // Function Pointers - DEFINE_FUNCTION( CanThink ), - DEFINE_FUNCTION( CanTouch ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( item_sodacan, CItemSoda ); - -void CItemSoda::Precache ( void ) -{ - PrecacheModel( "models/can.mdl" ); - - PrecacheScriptSound( "ItemSoda.Bounce" ); -} - -void CItemSoda::Spawn( void ) -{ - Precache(); - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_FLYGRAVITY ); - - SetModel ( "models/can.mdl" ); - UTIL_SetSize ( this, Vector ( 0, 0, 0 ), Vector ( 0, 0, 0 ) ); - - SetThink (&CItemSoda::CanThink); - SetNextThink( gpGlobals->curtime + 0.5f ); -} - -void CItemSoda::CanThink ( void ) -{ - EmitSound( "ItemSoda.Bounce" ); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_TRIGGER ); - UTIL_SetSize ( this, Vector ( -8, -8, 0 ), Vector ( 8, 8, 8 ) ); - - SetThink ( NULL ); - SetTouch ( &CItemSoda::CanTouch ); -} - -void CItemSoda::CanTouch ( CBaseEntity *pOther ) -{ - if ( !pOther->IsPlayer() ) - { - return; - } - - // spoit sound here - - pOther->TakeHealth( 1, DMG_GENERIC );// a bit of health. - - if ( GetOwnerEntity() ) - { - // tell the machine the can was taken - CEnvBeverage *bev = (CEnvBeverage *)GetOwnerEntity(); - bev->m_CanInDispenser = false; - } - - AddSolidFlags( FSOLID_NOT_SOLID ); - SetMoveType( MOVETYPE_NONE ); - AddEffects( EF_NODRAW ); - SetTouch ( NULL ); - SetThink ( &CItemSoda::SUB_Remove ); - SetNextThink( gpGlobals->curtime ); -} - -#ifndef _XBOX -//========================================================= -// func_precipitation - temporary snow solution for first HL2 -// technology demo -//========================================================= - -class CPrecipitation : public CBaseEntity -{ -public: - DECLARE_CLASS( CPrecipitation, CBaseEntity ); - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - CPrecipitation(); - void Spawn( void ); - - CNetworkVar( PrecipitationType_t, m_nPrecipType ); -}; - -LINK_ENTITY_TO_CLASS( func_precipitation, CPrecipitation ); - -BEGIN_DATADESC( CPrecipitation ) - DEFINE_KEYFIELD( m_nPrecipType, FIELD_INTEGER, "preciptype" ), -END_DATADESC() - -// Just send the normal entity crap -IMPLEMENT_SERVERCLASS_ST( CPrecipitation, DT_Precipitation) - SendPropInt( SENDINFO( m_nPrecipType ), Q_log2( NUM_PRECIPITATION_TYPES ) + 1, SPROP_UNSIGNED ) -END_SEND_TABLE() - - -CPrecipitation::CPrecipitation() -{ - m_nPrecipType = PRECIPITATION_TYPE_RAIN; // default to rain. -} - -void CPrecipitation::Spawn( void ) -{ - PrecacheMaterial( "effects/fleck_ash1" ); - PrecacheMaterial( "effects/fleck_ash2" ); - PrecacheMaterial( "effects/fleck_ash3" ); - PrecacheMaterial( "effects/ember_swirling001" ); - - Precache(); - SetSolid( SOLID_NONE ); // Remove model & collisions - SetMoveType( MOVETYPE_NONE ); - SetModel( STRING( GetModelName() ) ); // Set size - - // Default to rain. - if ( m_nPrecipType < 0 || m_nPrecipType > NUM_PRECIPITATION_TYPES ) - m_nPrecipType = PRECIPITATION_TYPE_RAIN; - - m_nRenderMode = kRenderEnvironmental; -} -#endif - -//----------------------------------------------------------------------------- -// EnvWind - global wind info -//----------------------------------------------------------------------------- -class CEnvWind : public CBaseEntity -{ -public: - DECLARE_CLASS( CEnvWind, CBaseEntity ); - - void Spawn( void ); - void Precache( void ); - void WindThink( void ); - int UpdateTransmitState( void ); - - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - -private: -#ifdef _LINUX - CEnvWindShared m_EnvWindShared; // FIXME - fails to compile as networked var due to operator= problem -#else - CNetworkVarEmbedded( CEnvWindShared, m_EnvWindShared ); -#endif -}; - -LINK_ENTITY_TO_CLASS( env_wind, CEnvWind ); - -BEGIN_DATADESC( CEnvWind ) - - DEFINE_KEYFIELD( m_EnvWindShared.m_iMinWind, FIELD_INTEGER, "minwind" ), - DEFINE_KEYFIELD( m_EnvWindShared.m_iMaxWind, FIELD_INTEGER, "maxwind" ), - DEFINE_KEYFIELD( m_EnvWindShared.m_iMinGust, FIELD_INTEGER, "mingust" ), - DEFINE_KEYFIELD( m_EnvWindShared.m_iMaxGust, FIELD_INTEGER, "maxgust" ), - DEFINE_KEYFIELD( m_EnvWindShared.m_flMinGustDelay, FIELD_FLOAT, "mingustdelay" ), - DEFINE_KEYFIELD( m_EnvWindShared.m_flMaxGustDelay, FIELD_FLOAT, "maxgustdelay" ), - DEFINE_KEYFIELD( m_EnvWindShared.m_iGustDirChange, FIELD_INTEGER, "gustdirchange" ), - DEFINE_KEYFIELD( m_EnvWindShared.m_flGustDuration, FIELD_FLOAT, "gustduration" ), -// DEFINE_KEYFIELD( m_EnvWindShared.m_iszGustSound, FIELD_STRING, "gustsound" ), - -// Just here to quiet down classcheck - // DEFINE_FIELD( m_EnvWindShared, CEnvWindShared ), - - DEFINE_FIELD( m_EnvWindShared.m_iWindDir, FIELD_INTEGER ), - DEFINE_FIELD( m_EnvWindShared.m_flWindSpeed, FIELD_FLOAT ), - - DEFINE_OUTPUT( m_EnvWindShared.m_OnGustStart, "OnGustStart" ), - DEFINE_OUTPUT( m_EnvWindShared.m_OnGustEnd, "OnGustEnd" ), - - // Function Pointers - DEFINE_FUNCTION( WindThink ), - -END_DATADESC() - - -BEGIN_SEND_TABLE_NOBASE(CEnvWindShared, DT_EnvWindShared) - // These are parameters that are used to generate the entire motion - SendPropInt (SENDINFO(m_iMinWind), 10, SPROP_UNSIGNED ), - SendPropInt (SENDINFO(m_iMaxWind), 10, SPROP_UNSIGNED ), - SendPropInt (SENDINFO(m_iMinGust), 10, SPROP_UNSIGNED ), - SendPropInt (SENDINFO(m_iMaxGust), 10, SPROP_UNSIGNED ), - SendPropFloat (SENDINFO(m_flMinGustDelay), 0, SPROP_NOSCALE), // NOTE: Have to do this, so it's *exactly* the same on client - SendPropFloat (SENDINFO(m_flMaxGustDelay), 0, SPROP_NOSCALE), - SendPropInt (SENDINFO(m_iGustDirChange), 9, SPROP_UNSIGNED ), - SendPropInt (SENDINFO(m_iWindSeed), 32, SPROP_UNSIGNED ), - - // These are related to initial state - SendPropInt (SENDINFO(m_iInitialWindDir),9, SPROP_UNSIGNED ), - SendPropFloat (SENDINFO(m_flInitialWindSpeed),0, SPROP_NOSCALE ), - SendPropFloat (SENDINFO(m_flStartTime), 0, SPROP_NOSCALE ), - - SendPropFloat (SENDINFO(m_flGustDuration), 0, SPROP_NOSCALE), - // Sound related -// SendPropInt (SENDINFO(m_iszGustSound), 10, SPROP_UNSIGNED ), -END_SEND_TABLE() - -// This table encodes the CBaseEntity data. -IMPLEMENT_SERVERCLASS_ST_NOBASE(CEnvWind, DT_EnvWind) - SendPropDataTable(SENDINFO_DT(m_EnvWindShared), &REFERENCE_SEND_TABLE(DT_EnvWindShared)), -END_SEND_TABLE() - -void CEnvWind::Precache ( void ) -{ -// if (m_iszGustSound) -// { -// PrecacheScriptSound( STRING( m_iszGustSound ) ); -// } -} - -void CEnvWind::Spawn( void ) -{ - Precache(); - SetSolid( SOLID_NONE ); - AddEffects( EF_NODRAW ); - - m_EnvWindShared.Init( entindex(), 0, gpGlobals->frametime, (int)GetLocalAngles().y, 0 ); - - SetThink( &CEnvWind::WindThink ); - SetNextThink( gpGlobals->curtime ); -} - -int CEnvWind::UpdateTransmitState() -{ - return SetTransmitState( FL_EDICT_ALWAYS ); -} - -void CEnvWind::WindThink( void ) -{ - SetNextThink( m_EnvWindShared.WindThink( gpGlobals->curtime ) ); -} - - - -//================================================== -// CEmbers -//================================================== - -#define bitsSF_EMBERS_START_ON 0x00000001 -#define bitsSF_EMBERS_TOGGLE 0x00000002 - -// UNDONE: This is a brush effect-in-volume entity, move client side. -class CEmbers : public CBaseEntity -{ -public: - DECLARE_CLASS( CEmbers, CBaseEntity ); - - void Spawn( void ); - void Precache( void ); - - void EmberUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - CNetworkVar( int, m_nDensity ); - CNetworkVar( int, m_nLifetime ); - CNetworkVar( int, m_nSpeed ); - - CNetworkVar( bool, m_bEmit ); - - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); -}; - -LINK_ENTITY_TO_CLASS( env_embers, CEmbers ); - -//Data description -BEGIN_DATADESC( CEmbers ) - - DEFINE_KEYFIELD( m_nDensity, FIELD_INTEGER, "density" ), - DEFINE_KEYFIELD( m_nLifetime, FIELD_INTEGER, "lifetime" ), - DEFINE_KEYFIELD( m_nSpeed, FIELD_INTEGER, "speed" ), - - DEFINE_FIELD( m_bEmit, FIELD_BOOLEAN ), - - //Function pointers - DEFINE_FUNCTION( EmberUse ), - -END_DATADESC() - - -//Data table -IMPLEMENT_SERVERCLASS_ST( CEmbers, DT_Embers ) - SendPropInt( SENDINFO( m_nDensity ), 32, SPROP_UNSIGNED ), - SendPropInt( SENDINFO( m_nLifetime ), 32, SPROP_UNSIGNED ), - SendPropInt( SENDINFO( m_nSpeed ), 32, SPROP_UNSIGNED ), - SendPropInt( SENDINFO( m_bEmit ), 2, SPROP_UNSIGNED ), -END_SEND_TABLE() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEmbers::Spawn( void ) -{ - Precache(); - SetModel( STRING( GetModelName() ) ); - - SetSolid( SOLID_NONE ); - SetRenderColorA( 0 ); - m_nRenderMode = kRenderTransTexture; - - SetUse( &CEmbers::EmberUse ); - - //Start off if we're targetted (unless flagged) - m_bEmit = ( HasSpawnFlags( bitsSF_EMBERS_START_ON ) || ( !GetEntityName() ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEmbers::Precache( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pActivator - -// *pCaller - -// useType - -// value - -//----------------------------------------------------------------------------- -void CEmbers::EmberUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - //If we're not toggable, only allow one use - if ( !HasSpawnFlags( bitsSF_EMBERS_TOGGLE ) ) - { - SetUse( NULL ); - } - - //Handle it - switch ( useType ) - { - case USE_OFF: - m_bEmit = false; - break; - - case USE_ON: - m_bEmit = true; - break; - - case USE_SET: - m_bEmit = !!(int)value; - break; - - default: - case USE_TOGGLE: - m_bEmit = !m_bEmit; - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CPhysicsWire : public CBaseEntity -{ -public: - DECLARE_CLASS( CPhysicsWire, CBaseEntity ); - - void Spawn( void ); - void Precache( void ); - - DECLARE_DATADESC(); - -protected: - - bool SetupPhysics( void ); - - int m_nDensity; -}; - -LINK_ENTITY_TO_CLASS( env_physwire, CPhysicsWire ); - -BEGIN_DATADESC( CPhysicsWire ) - - DEFINE_KEYFIELD( m_nDensity, FIELD_INTEGER, "Density" ), -// DEFINE_KEYFIELD( m_frequency, FIELD_INTEGER, "frequency" ), - -// DEFINE_FIELD( m_flFoo, FIELD_FLOAT ), - - // Function Pointers -// DEFINE_FUNCTION( WireThink ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysicsWire::Spawn( void ) -{ - BaseClass::Spawn(); - - Precache(); - -// if ( SetupPhysics() == false ) -// return; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysicsWire::Precache( void ) -{ - BaseClass::Precache(); -} - -class CPhysBallSocket; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CPhysicsWire::SetupPhysics( void ) -{ -/* - CPointEntity *anchorEnt, *freeEnt; - CPhysBallSocket *socket; - - char anchorName[256]; - char freeName[256]; - - int iAnchorName, iFreeName; - - anchorEnt = (CPointEntity *) CreateEntityByName( "info_target" ); - - if ( anchorEnt == NULL ) - return false; - - //Create and connect all segments - for ( int i = 0; i < m_nDensity; i++ ) - { - // Create other end of our link - freeEnt = (CPointEntity *) CreateEntityByName( "info_target" ); - - // Create a ballsocket and attach the two - //socket = (CPhysBallSocket *) CreateEntityByName( "phys_ballsocket" ); - - Q_snprintf( anchorName,sizeof(anchorName), "__PWIREANCHOR%d", i ); - Q_snprintf( freeName,sizeof(freeName), "__PWIREFREE%d", i+1 ); - - iAnchorName = MAKE_STRING( anchorName ); - iFreeName = MAKE_STRING( freeName ); - - //Fake the names - //socket->m_nameAttach1 = anchorEnt->m_iGlobalname = iAnchorName; - //socket->m_nameAttach2 = freeEnt->m_iGlobalname = iFreeName - - //socket->Activate(); - - //The free ent is now the anchor for the next link - anchorEnt = freeEnt; - } -*/ - - return true; -} - -// -// Muzzle flash -// - -class CEnvMuzzleFlash : public CPointEntity -{ - DECLARE_CLASS( CEnvMuzzleFlash, CPointEntity ); - -public: - virtual void Spawn(); - - // Input handlers - void InputFire( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - - float m_flScale; - string_t m_iszParentAttachment; -}; - -BEGIN_DATADESC( CEnvMuzzleFlash ) - - DEFINE_KEYFIELD( m_flScale, FIELD_FLOAT, "scale" ), - DEFINE_KEYFIELD( m_iszParentAttachment, FIELD_STRING, "parentattachment" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Fire", InputFire ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( env_muzzleflash, CEnvMuzzleFlash ); - - -//----------------------------------------------------------------------------- -// Spawn! -//----------------------------------------------------------------------------- -void CEnvMuzzleFlash::Spawn() -{ - if ( (m_iszParentAttachment != NULL_STRING) && GetParent() && GetParent()->GetBaseAnimating() ) - { - CBaseAnimating *pAnim = GetParent()->GetBaseAnimating(); - int nParentAttachment = pAnim->LookupAttachment( STRING(m_iszParentAttachment) ); - if ( nParentAttachment != 0 ) - { - SetParent( GetParent(), nParentAttachment ); - SetLocalOrigin( vec3_origin ); - SetLocalAngles( vec3_angle ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CEnvMuzzleFlash::InputFire( inputdata_t &inputdata ) -{ - g_pEffects->MuzzleFlash( GetAbsOrigin(), GetAbsAngles(), m_flScale, MUZZLEFLASH_TYPE_DEFAULT ); -} - - -//========================================================= -// Splash! -//========================================================= -#define SF_ENVSPLASH_FINDWATERSURFACE 0x00000001 -#define SF_ENVSPLASH_DIMINISH 0x00000002 -class CEnvSplash : public CPointEntity -{ - DECLARE_CLASS( CEnvSplash, CPointEntity ); - -public: - // Input handlers - void InputSplash( inputdata_t &inputdata ); - -protected: - - float m_flScale; - - DECLARE_DATADESC(); -}; - -BEGIN_DATADESC( CEnvSplash ) - DEFINE_KEYFIELD( m_flScale, FIELD_FLOAT, "scale" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Splash", InputSplash ), -END_DATADESC() - -LINK_ENTITY_TO_CLASS( env_splash, CEnvSplash ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -#define SPLASH_MAX_DEPTH 120.0f -void CEnvSplash::InputSplash( inputdata_t &inputdata ) -{ - CEffectData data; - - data.m_fFlags = 0; - - float scale = m_flScale; - - if( HasSpawnFlags( SF_ENVSPLASH_FINDWATERSURFACE ) ) - { - if( UTIL_PointContents(GetAbsOrigin()) & MASK_WATER ) - { - // No splash if I'm supposed to find the surface of the water, but I'm underwater. - return; - } - - // Trace down and find the water's surface. This is designed for making - // splashes on the surface of water that can change water level. - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector( 0, 0, 4096 ), (MASK_WATER|MASK_SOLID_BRUSHONLY), this, COLLISION_GROUP_NONE, &tr ); - data.m_vOrigin = tr.endpos; - - if ( tr.contents & CONTENTS_SLIME ) - { - data.m_fFlags |= FX_WATER_IN_SLIME; - } - } - else - { - data.m_vOrigin = GetAbsOrigin(); - } - - if( HasSpawnFlags( SF_ENVSPLASH_DIMINISH ) ) - { - // Get smaller if I'm in deeper water. - float depth = 0.0f; - - trace_t tr; - UTIL_TraceLine( data.m_vOrigin, data.m_vOrigin - Vector( 0, 0, 4096 ), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - - depth = fabs( tr.startpos.z - tr.endpos.z ); - - float factor = 1.0f - (depth / SPLASH_MAX_DEPTH); - - if( factor < 0.1 ) - { - // Don't bother making one this small. - return; - } - - scale *= factor; - } - - data.m_vNormal = Vector( 0, 0, 1 ); - data.m_flScale = scale; - - DispatchEffect( "watersplash", data ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -class CEnvGunfire : public CPointEntity -{ -public: - DECLARE_CLASS( CEnvGunfire, CPointEntity ); - - CEnvGunfire() - { - // !!!HACKHACK - // These fields came along kind of late, so they get - // initialized in the constructor for now. (sjb) - m_flBias = 1.0f; - m_bCollide = false; - } - - void Precache(); - void Spawn(); - void Activate(); - void StartShooting(); - void StopShooting(); - void ShootThink(); - void UpdateTarget(); - - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - - int m_iMinBurstSize; - int m_iMaxBurstSize; - - float m_flMinBurstDelay; - float m_flMaxBurstDelay; - - float m_flRateOfFire; - - string_t m_iszShootSound; - string_t m_iszTracerType; - - bool m_bDisabled; - - int m_iShotsRemaining; - - int m_iSpread; - Vector m_vecSpread; - Vector m_vecTargetPosition; - float m_flTargetDist; - - float m_flBias; - bool m_bCollide; - - EHANDLE m_hTarget; - - - DECLARE_DATADESC(); -}; - -BEGIN_DATADESC( CEnvGunfire ) - DEFINE_KEYFIELD( m_iMinBurstSize, FIELD_INTEGER, "minburstsize" ), - DEFINE_KEYFIELD( m_iMaxBurstSize, FIELD_INTEGER, "maxburstsize" ), - DEFINE_KEYFIELD( m_flMinBurstDelay, FIELD_TIME, "minburstdelay" ), - DEFINE_KEYFIELD( m_flMaxBurstDelay, FIELD_TIME, "maxburstdelay" ), - DEFINE_KEYFIELD( m_flRateOfFire, FIELD_FLOAT, "rateoffire" ), - DEFINE_KEYFIELD( m_iszShootSound, FIELD_STRING, "shootsound" ), - DEFINE_KEYFIELD( m_iszTracerType, FIELD_STRING, "tracertype" ), - DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "startdisabled" ), - DEFINE_KEYFIELD( m_iSpread, FIELD_INTEGER, "spread" ), - DEFINE_KEYFIELD( m_flBias, FIELD_FLOAT, "bias" ), - DEFINE_KEYFIELD( m_bCollide, FIELD_BOOLEAN, "collisions" ), - - DEFINE_FIELD( m_iShotsRemaining, FIELD_INTEGER ), - DEFINE_FIELD( m_vecSpread, FIELD_VECTOR ), - DEFINE_FIELD( m_vecTargetPosition, FIELD_VECTOR ), - DEFINE_FIELD( m_flTargetDist, FIELD_FLOAT ), - - DEFINE_FIELD( m_hTarget, FIELD_EHANDLE ), - - DEFINE_THINKFUNC( ShootThink ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), -END_DATADESC() -LINK_ENTITY_TO_CLASS( env_gunfire, CEnvGunfire ); - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CEnvGunfire::Precache() -{ - PrecacheScriptSound( STRING( m_iszShootSound ) ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CEnvGunfire::Spawn() -{ - Precache(); - - m_iShotsRemaining = 0; - m_flRateOfFire = 1.0f / m_flRateOfFire; - - switch( m_iSpread ) - { - case 1: - m_vecSpread = VECTOR_CONE_1DEGREES; - break; - case 5: - m_vecSpread = VECTOR_CONE_5DEGREES; - break; - case 10: - m_vecSpread = VECTOR_CONE_10DEGREES; - break; - case 15: - m_vecSpread = VECTOR_CONE_15DEGREES; - break; - - default: - m_vecSpread = vec3_origin; - break; - } - - if( !m_bDisabled ) - { - StartShooting(); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CEnvGunfire::Activate( void ) -{ - // Find my target - if (m_target != NULL_STRING) - { - m_hTarget = gEntList.FindEntityByName( NULL, m_target ); - } - - BaseClass::Activate(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CEnvGunfire::StartShooting() -{ - m_iShotsRemaining = random->RandomInt( m_iMinBurstSize, m_iMaxBurstSize ); - - SetThink( &CEnvGunfire::ShootThink ); - SetNextThink( gpGlobals->curtime ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CEnvGunfire::UpdateTarget() -{ - if( m_hTarget ) - { - if( m_hTarget->WorldSpaceCenter() != m_vecTargetPosition ) - { - // Target has moved. - // Locate my target and cache the position and distance. - m_vecTargetPosition = m_hTarget->WorldSpaceCenter(); - m_flTargetDist = (GetAbsOrigin() - m_vecTargetPosition).Length(); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CEnvGunfire::StopShooting() -{ - SetThink( NULL ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CEnvGunfire::ShootThink() -{ - if( !m_hTarget ) - { - StopShooting(); - } - - SetNextThink( gpGlobals->curtime + m_flRateOfFire ); - - UpdateTarget(); - - Vector vecDir = m_vecTargetPosition - GetAbsOrigin(); - VectorNormalize( vecDir ); - - CShotManipulator manipulator( vecDir ); - - vecDir = manipulator.ApplySpread( m_vecSpread, m_flBias ); - - Vector vecEnd; - - if( m_bCollide ) - { - trace_t tr; - - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + vecDir * 8192, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - if( tr.fraction != 1.0 ) - { - DoImpactEffect( tr, DMG_BULLET ); - } - - vecEnd = tr.endpos; - } - else - { - vecEnd = GetAbsOrigin() + vecDir * m_flTargetDist; - } - - if( m_iszTracerType != NULL_STRING ) - { - UTIL_Tracer( GetAbsOrigin(), vecEnd, 0, TRACER_DONT_USE_ATTACHMENT, 5000, true, STRING(m_iszTracerType) ); - } - else - { - UTIL_Tracer( GetAbsOrigin(), vecEnd, 0, TRACER_DONT_USE_ATTACHMENT, 5000, true ); - } - - EmitSound( STRING(m_iszShootSound) ); - - m_iShotsRemaining--; - - if( m_iShotsRemaining == 0 ) - { - StartShooting(); - SetNextThink( gpGlobals->curtime + random->RandomFloat( m_flMinBurstDelay, m_flMaxBurstDelay ) ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CEnvGunfire::InputEnable( inputdata_t &inputdata ) -{ - m_bDisabled = false; - StartShooting(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CEnvGunfire::InputDisable( inputdata_t &inputdata ) -{ - m_bDisabled = true; - SetThink( NULL ); -} - -//----------------------------------------------------------------------------- -// Quadratic spline beam effect -//----------------------------------------------------------------------------- -BEGIN_DATADESC( CEnvQuadraticBeam ) - DEFINE_FIELD( m_targetPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_controlPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_scrollRate, FIELD_FLOAT ), - DEFINE_FIELD( m_flWidth, FIELD_FLOAT ), -END_DATADESC() - -LINK_ENTITY_TO_CLASS( env_quadraticbeam, CEnvQuadraticBeam ); - -IMPLEMENT_SERVERCLASS_ST( CEnvQuadraticBeam, DT_QuadraticBeam ) - SendPropVector(SENDINFO(m_targetPosition), -1, SPROP_COORD), - SendPropVector(SENDINFO(m_controlPosition), -1, SPROP_COORD), - SendPropFloat(SENDINFO(m_scrollRate), 8, 0, -4, 4), - SendPropFloat(SENDINFO(m_flWidth), -1, SPROP_NOSCALE), -END_SEND_TABLE() - -void CEnvQuadraticBeam::Spawn() -{ - BaseClass::Spawn(); - m_nRenderMode = kRenderTransAdd; - SetRenderColor( 255, 255, 255 ); -} - -CEnvQuadraticBeam *CreateQuadraticBeam( const char *pSpriteName, const Vector &start, const Vector &control, const Vector &end, float width, CBaseEntity *pOwner ) -{ - CEnvQuadraticBeam *pBeam = (CEnvQuadraticBeam *)CBaseEntity::Create( "env_quadraticbeam", start, vec3_angle, pOwner ); - UTIL_SetModel( pBeam, pSpriteName ); - pBeam->SetSpline( control, end ); - pBeam->SetScrollRate( 0.0 ); - pBeam->SetWidth(width); - return pBeam; -} - -void EffectsPrecache( void *pUser ) -{ - CBaseEntity::PrecacheScriptSound( "Underwater.BulletImpact" ); - - CBaseEntity::PrecacheScriptSound( "FX_RicochetSound.Ricochet" ); - - CBaseEntity::PrecacheScriptSound( "Physics.WaterSplash" ); - CBaseEntity::PrecacheScriptSound( "BaseExplosionEffect.Sound" ); - CBaseEntity::PrecacheScriptSound( "Splash.SplashSound" ); - - if ( gpGlobals->maxClients > 1 ) - { - CBaseEntity::PrecacheScriptSound( "HudChat.Message" ); - } -} - -PRECACHE_REGISTER_FN( EffectsPrecache ); - - -class CEnvViewPunch : public CPointEntity -{ -public: - - DECLARE_CLASS( CEnvViewPunch, CPointEntity ); - - virtual void Spawn(); - - // Input handlers - void InputViewPunch( inputdata_t &inputdata ); - -private: - - float m_flRadius; - QAngle m_angViewPunch; - - void DoViewPunch(); - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( env_viewpunch, CEnvViewPunch ); - -BEGIN_DATADESC( CEnvViewPunch ) - - DEFINE_KEYFIELD( m_angViewPunch, FIELD_VECTOR, "punchangle" ), - DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "radius" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "ViewPunch", InputViewPunch ), - -END_DATADESC() - -#define SF_PUNCH_EVERYONE 0x0001 // Don't check radius -#define SF_PUNCH_IN_AIR 0x0002 // Punch players in air - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CEnvViewPunch::Spawn( void ) -{ - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NONE ); - - if ( GetSpawnFlags() & SF_PUNCH_EVERYONE ) - { - m_flRadius = 0; - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CEnvViewPunch::DoViewPunch() -{ - bool bAir = (GetSpawnFlags() & SF_PUNCH_IN_AIR) ? true : false; - UTIL_ViewPunch( GetAbsOrigin(), m_angViewPunch, m_flRadius, bAir ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CEnvViewPunch::InputViewPunch( inputdata_t &inputdata ) -{ - DoViewPunch(); -} diff --git a/game/server/effects.h b/game/server/effects.h deleted file mode 100644 index a6ab7750f..000000000 --- a/game/server/effects.h +++ /dev/null @@ -1,68 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef EFFECTS_H -#define EFFECTS_H - -#ifdef _WIN32 -#pragma once -#endif - - -class CBaseEntity; -class Vector; - - -//----------------------------------------------------------------------------- -// The rotor wash shooter. It emits gibs when pushed by a rotor wash -//----------------------------------------------------------------------------- -abstract_class IRotorWashShooter -{ -public: - virtual CBaseEntity *DoWashPush( float flWashStartTime, const Vector &vecForce ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Gets at the interface if the entity supports it -//----------------------------------------------------------------------------- -IRotorWashShooter *GetRotorWashShooter( CBaseEntity *pEntity ); - -class CEnvQuadraticBeam : public CPointEntity -{ - DECLARE_CLASS( CEnvQuadraticBeam, CPointEntity ); - -public: - void Spawn(); - void SetSpline( const Vector &control, const Vector &target ) - { - m_targetPosition = target; - m_controlPosition = control; - } - void SetScrollRate( float rate ) - { - m_scrollRate = rate; - } - - void SetWidth( float width ) - { - m_flWidth = width; - } - -private: - CNetworkVector( m_targetPosition ); - CNetworkVector( m_controlPosition ); - CNetworkVar( float, m_scrollRate ); - CNetworkVar( float, m_flWidth ); - - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); -}; -CEnvQuadraticBeam *CreateQuadraticBeam( const char *pSpriteName, const Vector &start, const Vector &control, const Vector &end, float width, CBaseEntity *pOwner ); - - -#endif // EFFECTS_H diff --git a/game/server/enginecallback.h b/game/server/enginecallback.h deleted file mode 100644 index b621119fd..000000000 --- a/game/server/enginecallback.h +++ /dev/null @@ -1,129 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// -#ifndef ENGINECALLBACK_H -#define ENGINECALLBACK_H - -#ifndef EIFACE_H -#include "eiface.h" -#endif - -#if defined _LINUX || defined __APPLE__ -#define random random_valve// stdlib.h defined random()..., and so does vstdlib/random.h -#endif - -class IFileSystem; // include FileSystem.h -class IUniformRandomStream; // include vstdlib/random.h -class IEngineSound; // include engine/IEngineSound.h -class IVEngineServer; -class IVoiceServer; -class IStaticPropMgrServer; -class ISpatialPartition; -class IVModelInfo; -class IEngineTrace; -class IGameEventManager2; -class IVDebugOverlay; -class IDataCache; -class IMDLCache; -class IServerEngineTools; -class IXboxSystem; -class CSteamAPIContext; - -extern IVEngineServer *engine; -extern IVoiceServer *g_pVoiceServer; -extern IFileSystem *filesystem; -extern IStaticPropMgrServer *staticpropmgr; -extern ISpatialPartition *partition; -extern IEngineSound *enginesound; -extern IUniformRandomStream *random; -extern IVModelInfo *modelinfo; -extern IEngineTrace *enginetrace; -extern IGameEventManager2 *gameeventmanager; -extern IVDebugOverlay *debugoverlay; -extern IDataCache *datacache; -extern IMDLCache *mdlcache; -extern IServerEngineTools *serverenginetools; -extern IXboxSystem *xboxsystem; // 360 only -extern CSteamAPIContext *steamapicontext; - - -//----------------------------------------------------------------------------- -// Precaches a material -//----------------------------------------------------------------------------- -void PrecacheMaterial( const char *pMaterialName ); - -//----------------------------------------------------------------------------- -// Converts a previously precached material into an index -//----------------------------------------------------------------------------- -int GetMaterialIndex( const char *pMaterialName ); - -//----------------------------------------------------------------------------- -// Converts a previously precached material index into a string -//----------------------------------------------------------------------------- -const char *GetMaterialNameFromIndex( int nMaterialIndex ); - - -//----------------------------------------------------------------------------- -// Precache-related methods for particle systems -//----------------------------------------------------------------------------- -void PrecacheParticleSystem( const char *pParticleSystemName ); -int GetParticleSystemIndex( const char *pParticleSystemName ); -const char *GetParticleSystemNameFromIndex( int nIndex ); - - -class IRecipientFilter; -void EntityMessageBegin( CBaseEntity * entity, bool reliable = false ); -void UserMessageBegin( IRecipientFilter& filter, const char *messagename ); -void MessageEnd( void ); - -// bytewise -void MessageWriteByte( int iValue); -void MessageWriteChar( int iValue); -void MessageWriteShort( int iValue); -void MessageWriteWord( int iValue ); -void MessageWriteLong( int iValue); -void MessageWriteFloat( float flValue); -void MessageWriteAngle( float flValue); -void MessageWriteCoord( float flValue); -void MessageWriteVec3Coord( const Vector& rgflValue); -void MessageWriteVec3Normal( const Vector& rgflValue); -void MessageWriteAngles( const QAngle& rgflValue); -void MessageWriteString( const char *sz ); -void MessageWriteEntity( int iValue); -void MessageWriteEHandle( CBaseEntity *pEntity ); //encoded as a long - - -// bitwise -void MessageWriteBool( bool bValue ); -void MessageWriteUBitLong( unsigned int data, int numbits ); -void MessageWriteSBitLong( int data, int numbits ); -void MessageWriteBits( const void *pIn, int nBits ); - - -// Bytewise -#define WRITE_BYTE (MessageWriteByte) -#define WRITE_CHAR (MessageWriteChar) -#define WRITE_SHORT (MessageWriteShort) -#define WRITE_WORD (MessageWriteWord) -#define WRITE_LONG (MessageWriteLong) -#define WRITE_FLOAT (MessageWriteFloat) -#define WRITE_ANGLE (MessageWriteAngle) -#define WRITE_COORD (MessageWriteCoord) -#define WRITE_VEC3COORD (MessageWriteVec3Coord) -#define WRITE_VEC3NORMAL (MessageWriteVec3Normal) -#define WRITE_ANGLES (MessageWriteAngles) -#define WRITE_STRING (MessageWriteString) -#define WRITE_ENTITY (MessageWriteEntity) -#define WRITE_EHANDLE (MessageWriteEHandle) - -// Bitwise -#define WRITE_BOOL (MessageWriteBool) -#define WRITE_UBITLONG (MessageWriteUBitLong) -#define WRITE_SBITLONG (MessageWriteSBitLong) -#define WRITE_BITS (MessageWriteBits) - -#endif //ENGINECALLBACK_H diff --git a/game/server/entity_tools_server.cpp b/game/server/entity_tools_server.cpp deleted file mode 100644 index bd82d84fe..000000000 --- a/game/server/entity_tools_server.cpp +++ /dev/null @@ -1,324 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= -#include "cbase.h" -#include "const.h" -#include "toolframework/itoolentity.h" -#include "entitylist.h" -#include "toolframework/itoolsystem.h" -#include "KeyValues.h" -#include "icliententity.h" -#include "iserverentity.h" -#include "sceneentity.h" -#include "particles/particles.h" - - -//----------------------------------------------------------------------------- -// Interface from engine to tools for manipulating entities -//----------------------------------------------------------------------------- -class CServerTools : public IServerTools -{ -public: - // Inherited from IServerTools - virtual IServerEntity *GetIServerEntity( IClientEntity *pClientEntity ); - virtual bool GetPlayerPosition( Vector &org, QAngle &ang, IClientEntity *pClientPlayer = NULL ); - virtual bool SnapPlayerToPosition( const Vector &org, const QAngle &ang, IClientEntity *pClientPlayer = NULL ); - virtual int GetPlayerFOV( IClientEntity *pClientPlayer = NULL ); - virtual bool SetPlayerFOV( int fov, IClientEntity *pClientPlayer = NULL ); - virtual bool IsInNoClipMode( IClientEntity *pClientPlayer = NULL ); - virtual void *FirstEntity( void ); - virtual void *NextEntity( void *pEntity ); - virtual void *FindEntityByHammerID( int iHammerID ); - virtual bool GetKeyValue( void *pEntity, const char *szField, char *szValue, int iMaxLen ); - virtual bool SetKeyValue( void *pEntity, const char *szField, const char *szValue ); - virtual bool SetKeyValue( void *pEntity, const char *szField, float flValue ); - virtual bool SetKeyValue( void *pEntity, const char *szField, const Vector &vecValue ); - virtual void *CreateEntityByName( const char *szClassName ); - virtual void DispatchSpawn( void *pEntity ); - virtual void ReloadParticleDefintions( const char *pFileName, const void *pBufData, int nLen ); - virtual void AddOriginToPVS( const Vector &org ); -}; - - -//----------------------------------------------------------------------------- -// Singleton -//----------------------------------------------------------------------------- -static CServerTools g_ServerTools; - -EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CServerTools, IServerTools, VSERVERTOOLS_INTERFACE_VERSION, g_ServerTools ); - - -IServerEntity *CServerTools::GetIServerEntity( IClientEntity *pClientEntity ) -{ - if ( pClientEntity == NULL ) - return NULL; - - CBaseHandle ehandle = pClientEntity->GetRefEHandle(); - if ( ehandle.GetEntryIndex() >= MAX_EDICTS ) - return NULL; // the first MAX_EDICTS entities are networked, the rest are client or server only - -#if 0 - // this fails, since the server entities have extra bits in their serial numbers, - // since 20 bits are reserved for serial numbers, except for networked entities, which are restricted to 10 - - // Brian believes that everything should just restrict itself to 10 to make things simpler, - // so if/when he changes NUM_SERIAL_NUM_BITS to 10, we can switch back to this simpler code - - IServerNetworkable *pNet = gEntList.GetServerNetworkable( ehandle ); - if ( pNet == NULL ) - return NULL; - - CBaseEntity *pServerEnt = pNet->GetBaseEntity(); - return pServerEnt; -#else - IHandleEntity *pEnt = gEntList.LookupEntityByNetworkIndex( ehandle.GetEntryIndex() ); - if ( pEnt == NULL ) - return NULL; - - CBaseHandle h = gEntList.GetNetworkableHandle( ehandle.GetEntryIndex() ); - const int mask = ( 1 << NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS ) - 1; - if ( !h.IsValid() || ( ( h.GetSerialNumber() & mask ) != ( ehandle.GetSerialNumber() & mask ) ) ) - return NULL; - - IServerUnknown *pUnk = static_cast< IServerUnknown* >( pEnt ); - return pUnk->GetBaseEntity(); -#endif -} - -bool CServerTools::GetPlayerPosition( Vector &org, QAngle &ang, IClientEntity *pClientPlayer ) -{ - IServerEntity *pServerPlayer = GetIServerEntity( pClientPlayer ); - CBasePlayer *pPlayer = pServerPlayer ? ( CBasePlayer* )pServerPlayer : UTIL_GetLocalPlayer(); - if ( pPlayer == NULL ) - return false; - - org = pPlayer->EyePosition(); - ang = pPlayer->EyeAngles(); - return true; -} - -bool CServerTools::SnapPlayerToPosition( const Vector &org, const QAngle &ang, IClientEntity *pClientPlayer ) -{ - IServerEntity *pServerPlayer = GetIServerEntity( pClientPlayer ); - CBasePlayer *pPlayer = pServerPlayer ? ( CBasePlayer* )pServerPlayer : UTIL_GetLocalPlayer(); - if ( pPlayer == NULL ) - return false; - - pPlayer->SetAbsOrigin( org - pPlayer->GetViewOffset() ); - pPlayer->SnapEyeAngles( ang ); - - // Disengage from hierarchy - pPlayer->SetParent( NULL ); - - return true; -} - -int CServerTools::GetPlayerFOV( IClientEntity *pClientPlayer ) -{ - IServerEntity *pServerPlayer = GetIServerEntity( pClientPlayer ); - CBasePlayer *pPlayer = pServerPlayer ? ( CBasePlayer* )pServerPlayer : UTIL_GetLocalPlayer(); - if ( pPlayer == NULL ) - return 0; - - return pPlayer->GetFOV(); -} - -bool CServerTools::SetPlayerFOV( int fov, IClientEntity *pClientPlayer ) -{ - IServerEntity *pServerPlayer = GetIServerEntity( pClientPlayer ); - CBasePlayer *pPlayer = pServerPlayer ? ( CBasePlayer* )pServerPlayer : UTIL_GetLocalPlayer(); - if ( pPlayer == NULL ) - return false; - - pPlayer->SetDefaultFOV( fov ); - CBaseEntity *pFOVOwner = pPlayer->GetFOVOwner(); - return pPlayer->SetFOV( pFOVOwner ? pFOVOwner : pPlayer, fov ); -} - -bool CServerTools::IsInNoClipMode( IClientEntity *pClientPlayer ) -{ - IServerEntity *pServerPlayer = GetIServerEntity( pClientPlayer ); - CBasePlayer *pPlayer = pServerPlayer ? ( CBasePlayer* )pServerPlayer : UTIL_GetLocalPlayer(); - if ( pPlayer == NULL ) - return true; - - return pPlayer->GetMoveType() == MOVETYPE_NOCLIP; -} - -void *CServerTools::FirstEntity( void ) -{ - return (void *)gEntList.FirstEnt(); -} - -void *CServerTools::NextEntity( void *pEntity ) -{ - CBaseEntity *pEnt; - - if ( pEntity == NULL ) - { - pEnt = gEntList.FirstEnt(); - } - else - { - pEnt = gEntList.NextEnt( (CBaseEntity *)pEntity ); - } - return (void *)pEnt; -} - -void *CServerTools::FindEntityByHammerID( int iHammerID ) -{ - CBaseEntity *pEntity = gEntList.FirstEnt(); - - while (pEntity) - { - if (pEntity->m_iHammerID == iHammerID) - return (void *)pEntity; - pEntity = gEntList.NextEnt( pEntity ); - } - return NULL; -} - -bool CServerTools::GetKeyValue( void *pEntity, const char *szField, char *szValue, int iMaxLen ) -{ - CBaseEntity *pEnt = (CBaseEntity *)pEntity; - - return pEnt->GetKeyValue( szField, szValue, iMaxLen ); -} - -bool CServerTools::SetKeyValue( void *pEntity, const char *szField, const char *szValue ) -{ - CBaseEntity *pEnt = (CBaseEntity *)pEntity; - - return pEnt->KeyValue( szField, szValue ); -} - -bool CServerTools::SetKeyValue( void *pEntity, const char *szField, float flValue ) -{ - CBaseEntity *pEnt = (CBaseEntity *)pEntity; - - return pEnt->KeyValue( szField, flValue ); -} - -bool CServerTools::SetKeyValue( void *pEntity, const char *szField, const Vector &vecValue ) -{ - CBaseEntity *pEnt = (CBaseEntity *)pEntity; - - return pEnt->KeyValue( szField, vecValue ); -} - - -//----------------------------------------------------------------------------- -// entity spawning -//----------------------------------------------------------------------------- -void *CServerTools::CreateEntityByName( const char *szClassName ) -{ - return ::CreateEntityByName( szClassName ); -} - -void CServerTools::DispatchSpawn( void *pEntity ) -{ - ::DispatchSpawn( (CBaseEntity *)pEntity ); -} - - -//----------------------------------------------------------------------------- -// Reload particle definitions -//----------------------------------------------------------------------------- -void CServerTools::ReloadParticleDefintions( const char *pFileName, const void *pBufData, int nLen ) -{ - // FIXME: Use file name to determine if we care about this data - CUtlBuffer buf( pBufData, nLen, CUtlBuffer::READ_ONLY ); - g_pParticleSystemMgr->ReadParticleConfigFile( buf, true ); -} - -void CServerTools::AddOriginToPVS( const Vector &org ) -{ - engine->AddOriginToPVS( org ); -} - - -// Interface from engine to tools for manipulating entities -class CServerChoreoTools : public IServerChoreoTools -{ -public: - // Iterates through ALL entities (separate list for client vs. server) - virtual EntitySearchResult NextChoreoEntity( EntitySearchResult currentEnt ) - { - CBaseEntity *ent = reinterpret_cast< CBaseEntity* >( currentEnt ); - ent = gEntList.FindEntityByClassname( ent, "logic_choreographed_scene" ); - return reinterpret_cast< EntitySearchResult >( ent ); - } - - virtual const char *GetSceneFile( EntitySearchResult sr ) - { - CBaseEntity *ent = reinterpret_cast< CBaseEntity* >( sr ); - if ( !sr ) - return ""; - - if ( Q_stricmp( ent->GetClassname(), "logic_choreographed_scene" ) ) - return ""; - - return GetSceneFilename( ent ); - } - - // For interactive editing - virtual int GetEntIndex( EntitySearchResult sr ) - { - CBaseEntity *ent = reinterpret_cast< CBaseEntity* >( sr ); - if ( !ent ) - return -1; - - return ent->entindex(); - } - - virtual void ReloadSceneFromDisk( int entindex ) - { - CBaseEntity *ent = CBaseEntity::Instance( entindex ); - if ( !ent ) - return; - - ::ReloadSceneFromDisk( ent ); - } -}; - - -static CServerChoreoTools g_ServerChoreoTools; -EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CServerChoreoTools, IServerChoreoTools, VSERVERCHOREOTOOLS_INTERFACE_VERSION, g_ServerChoreoTools ); - - -//------------------------------------------------------------------------------ -// Applies keyvalues to the entity by hammer ID. -//------------------------------------------------------------------------------ -void CC_Ent_Keyvalue( const CCommand &args ) -{ - // Must have an odd number of arguments. - if ( ( args.ArgC() < 4 ) || ( args.ArgC() & 1 ) ) - { - Msg( "Format: ent_keyvalue \"key1\"=\"value1\" \"key2\" \"value2\" ... \"keyN\" \"valueN\"\n" ); - return; - } - - int nID = atoi( args[1] ); - - void *pEnt = g_ServerTools.FindEntityByHammerID( nID ); - if ( !pEnt ) - { - Msg( "Entity ID %d not found.\n" ); - return; - } - - int nArg = 2; - while ( nArg < args.ArgC() ) - { - const char *pszKey = args[ nArg ]; - const char *pszValue = args[ nArg + 1 ]; - nArg += 2; - - g_ServerTools.SetKeyValue( pEnt, pszKey, pszValue ); - } -} - -static ConCommand ent_keyvalue("ent_keyvalue", CC_Ent_Keyvalue, "Applies the comma delimited key=value pairs to the entity with the given Hammer ID.\n\tFormat: ent_keyvalue =,=,...,=\n", FCVAR_CHEAT); - diff --git a/game/server/entityapi.h b/game/server/entityapi.h deleted file mode 100644 index 3521faebf..000000000 --- a/game/server/entityapi.h +++ /dev/null @@ -1,33 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef ENTITYAPI_H -#define ENTITYAPI_H - - -class SendTable; - -extern void LoadMapEntities( const char *pMapEntities ); -extern void DispatchObjectCollisionBox( edict_t *pent ); -extern float DispatchObjectPhysicsVelocity( edict_t *pent, float moveTime ); -extern ServerClass* DispatchGetObjectServerClass(edict_t *pent); -extern ServerClass* GetAllServerClasses(); -extern void SaveWriteFields( CSaveRestoreData *pSaveData, const char *pname, void *pBaseData, datamap_t *pMap, typedescription_t *pFields, int fieldCount ); -extern void SaveReadFields( CSaveRestoreData *pSaveData, const char *pname, void *pBaseData, datamap_t *pMap, typedescription_t *pFields, int fieldCount ); -extern void SaveGlobalState( CSaveRestoreData *pSaveData ); -extern void RestoreGlobalState( CSaveRestoreData *pSaveData ); -extern void ResetGlobalState( void ); -extern CSaveRestoreData *SaveInit( int size ); -extern int CreateEntityTransitionList( CSaveRestoreData *pSaveData, int levelMask ); -extern void ClearEntities( void ); -extern void FreeContainingEntity( edict_t *ed ); - -class ISaveRestoreBlockHandler; -ISaveRestoreBlockHandler *GetEntitySaveRestoreBlockHandler(); - - -#endif // ENTITYAPI_H diff --git a/game/server/entityblocker.cpp b/game/server/entityblocker.cpp deleted file mode 100644 index 9674cf7e2..000000000 --- a/game/server/entityblocker.cpp +++ /dev/null @@ -1,76 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "entityblocker.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -LINK_ENTITY_TO_CLASS( entity_blocker, CEntityBlocker ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &origin - -// &mins - -// &maxs - -// NULL - -// Output : CEntityBlocker -//----------------------------------------------------------------------------- -CEntityBlocker *CEntityBlocker::Create( const Vector &origin, const Vector &mins, const Vector &maxs, CBaseEntity *pOwner, bool bBlockPhysics ) -{ - CEntityBlocker *pBlocker = (CEntityBlocker *) CBaseEntity::Create( "entity_blocker", origin, vec3_angle, pOwner ); - - if ( pBlocker != NULL ) - { - pBlocker->SetSize( mins, maxs ); - if ( bBlockPhysics ) - { - pBlocker->VPhysicsInitStatic(); - } - } - - return pBlocker; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEntityBlocker::Spawn( void ) -{ - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_CUSTOMRAYTEST ); -} - -//----------------------------------------------------------------------------- -// Purpose: Entity blockers don't block tracelines so they don't screw up weapon fire, etc -//----------------------------------------------------------------------------- -bool CEntityBlocker::TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ) -{ - return false; -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CC_Test_Entity_Blocker( void ) -{ - CBasePlayer *pPlayer = UTIL_GetCommandClient(); - Vector vecForward; - pPlayer->GetVectors( &vecForward, NULL, NULL ); - - trace_t tr; - Vector vecOrigin = pPlayer->GetAbsOrigin() + (vecForward * 256); - UTIL_TraceHull( vecOrigin + Vector(0,0,256), vecOrigin - Vector(0,0,256), VEC_HULL_MIN, VEC_HULL_MAX, MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &tr ); - if ( !tr.allsolid && !tr.startsolid ) - { - CEntityBlocker::Create( tr.endpos, VEC_HULL_MIN, VEC_HULL_MAX, NULL, true ); - NDebugOverlay::Box( tr.endpos, VEC_HULL_MIN, VEC_HULL_MAX, 0, 255, 0, 64, 1000.0 ); - } -} -static ConCommand test_entity_blocker("test_entity_blocker", CC_Test_Entity_Blocker, "Test command that drops an entity blocker out in front of the player.", FCVAR_CHEAT ); diff --git a/game/server/entityblocker.h b/game/server/entityblocker.h deleted file mode 100644 index e2116c220..000000000 --- a/game/server/entityblocker.h +++ /dev/null @@ -1,28 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ENTITYBLOCKER_H -#define ENTITYBLOCKER_H -#ifdef _WIN32 -#pragma once -#endif - -//================================================================================================================== -// Entity Blocker -//================================================================================================================== -class CEntityBlocker : public CBaseEntity -{ - DECLARE_CLASS( CEntityBlocker, CBaseEntity ); - -public: - - static CEntityBlocker *Create( const Vector &origin, const Vector &mins, const Vector &maxs, CBaseEntity *pOwner = NULL, bool bBlockPhysics = false ); - - void Spawn( void ); - bool TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ); -}; - -#endif // ENTITYBLOCKER_H diff --git a/game/server/entityinput.h b/game/server/entityinput.h deleted file mode 100644 index d51a0da64..000000000 --- a/game/server/entityinput.h +++ /dev/null @@ -1,50 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef INPUTVAR_H -#define INPUTVAR_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "baseentity.h" -#include "entitylist.h" - -//----------------------------------------------------------------------------- -// Purpose: Used to request a value, or a set of values, from a set of entities. -// used when a multi-input variable needs to refresh it's inputs -//----------------------------------------------------------------------------- -class CMultiInputVar -{ -public: - CMultiInputVar() : m_InputList(NULL) {} - ~CMultiInputVar(); - - struct inputitem_t - { - variant_t value; // local copy of variable (maybe make this a variant?) - int outputID; // the ID number of the output that sent this - inputitem_t *next; - - // allocate and free from MPool memory - static void *operator new( size_t stAllocBlock ); - static void *operator new( size_t stAllocateBlock, int nBlockUse, const char *pFileName, int nLine ); - static void operator delete( void *pMem ); - static void operator delete( void *pMem, int nBlockUse, const char *pFileName, int nLine ) { operator delete(pMem); } - }; - - inputitem_t *m_InputList; // list of data - int m_bUpdatedThisFrame; - - void AddValue( variant_t newVal, int outputID ); - - DECLARE_SIMPLE_DATADESC(); -}; - -#endif // INPUTVAR_H diff --git a/game/server/entitylist.cpp b/game/server/entitylist.cpp deleted file mode 100644 index 2404995b2..000000000 --- a/game/server/entitylist.cpp +++ /dev/null @@ -1,1638 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -#include "entitylist.h" -#include "utlvector.h" -#include "igamesystem.h" -#include "collisionutils.h" -#include "UtlSortVector.h" -#include "tier0/vprof.h" -#include "mapentities.h" -#include "client.h" -#include "ai_initutils.h" -#include "globalstate.h" -#include "datacache/imdlcache.h" - -#ifdef HL2_DLL -#include "npc_playercompanion.h" -#endif // HL2_DLL - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -CBaseEntity *FindPickerEntity( CBasePlayer *pPlayer ); -void SceneManager_ClientActive( CBasePlayer *player ); - -static CUtlVector g_DeleteList; - -CGlobalEntityList gEntList; -CBaseEntityList *g_pEntityList = &gEntList; - -class CAimTargetManager : public IEntityListener -{ -public: - // Called by CEntityListSystem - void LevelInitPreEntity() - { - gEntList.AddListenerEntity( this ); - Clear(); - } - void LevelShutdownPostEntity() - { - gEntList.RemoveListenerEntity( this ); - Clear(); - } - - void Clear() - { - m_targetList.Purge(); - } - - void ForceRepopulateList() - { - Clear(); - - CBaseEntity *pEnt = gEntList.FirstEnt(); - - while( pEnt ) - { - if( ShouldAddEntity(pEnt) ) - AddEntity(pEnt); - - pEnt = gEntList.NextEnt( pEnt ); - } - } - - bool ShouldAddEntity( CBaseEntity *pEntity ) - { - return ((pEntity->GetFlags() & FL_AIMTARGET) != 0); - } - - // IEntityListener - virtual void OnEntityCreated( CBaseEntity *pEntity ) {} - virtual void OnEntityDeleted( CBaseEntity *pEntity ) - { - if ( !(pEntity->GetFlags() & FL_AIMTARGET) ) - return; - RemoveEntity(pEntity); - } - void AddEntity( CBaseEntity *pEntity ) - { - if ( pEntity->IsMarkedForDeletion() ) - return; - m_targetList.AddToTail( pEntity ); - } - void RemoveEntity( CBaseEntity *pEntity ) - { - int index = m_targetList.Find( pEntity ); - if ( m_targetList.IsValidIndex(index) ) - { - m_targetList.FastRemove( index ); - } - } - int ListCount() { return m_targetList.Count(); } - int ListCopy( CBaseEntity *pList[], int listMax ) - { - int count = MIN(listMax, ListCount() ); - memcpy( pList, m_targetList.Base(), sizeof(CBaseEntity *) * count ); - return count; - } - -private: - CUtlVector m_targetList; -}; - -static CAimTargetManager g_AimManager; - -int AimTarget_ListCount() -{ - return g_AimManager.ListCount(); -} -int AimTarget_ListCopy( CBaseEntity *pList[], int listMax ) -{ - return g_AimManager.ListCopy( pList, listMax ); -} -void AimTarget_ForceRepopulateList() -{ - g_AimManager.ForceRepopulateList(); -} - - -// Manages a list of all entities currently doing game simulation or thinking -// NOTE: This is usually a small subset of the global entity list, so it's -// an optimization to maintain this list incrementally rather than polling each -// frame. -struct simthinkentry_t -{ - unsigned short entEntry; - unsigned short unused0; - int nextThinkTick; -}; -class CSimThinkManager : public IEntityListener -{ -public: - CSimThinkManager() - { - Clear(); - } - void Clear() - { - m_simThinkList.Purge(); - for ( size_t i = 0; i < ARRAYSIZE(m_entinfoIndex); i++ ) - { - m_entinfoIndex[i] = 0xFFFF; - } - } - void LevelInitPreEntity() - { - gEntList.AddListenerEntity( this ); - } - - void LevelShutdownPostEntity() - { - gEntList.RemoveListenerEntity( this ); - Clear(); - } - - void OnEntityCreated( CBaseEntity *pEntity ) - { - Assert( m_entinfoIndex[pEntity->GetRefEHandle().GetEntryIndex()] == 0xFFFF ); - } - void OnEntityDeleted( CBaseEntity *pEntity ) - { - RemoveEntinfoIndex( pEntity->GetRefEHandle().GetEntryIndex() ); - } - - void RemoveEntinfoIndex( int index ) - { - int listHandle = m_entinfoIndex[index]; - // If this guy is in the active list, remove him - if ( listHandle != 0xFFFF ) - { - Assert(m_simThinkList[listHandle].entEntry == index); - m_simThinkList.FastRemove( listHandle ); - m_entinfoIndex[index] = 0xFFFF; - - // fast remove shifted someone, update that someone - if ( listHandle < m_simThinkList.Count() ) - { - m_entinfoIndex[m_simThinkList[listHandle].entEntry] = listHandle; - } - } - } - int ListCount() - { - return m_simThinkList.Count(); - } - - int ListCopy( CBaseEntity *pList[], int listMax ) - { - int count = MIN(listMax, ListCount()); - int out = 0; - for ( int i = 0; i < count; i++ ) - { - // only copy out entities that will simulate or think this frame - if ( m_simThinkList[i].nextThinkTick <= gpGlobals->tickcount ) - { - Assert(m_simThinkList[i].nextThinkTick>=0); - int entinfoIndex = m_simThinkList[i].entEntry; - const CEntInfo *pInfo = gEntList.GetEntInfoPtrByIndex( entinfoIndex ); - pList[out] = (CBaseEntity *)pInfo->m_pEntity; - Assert(m_simThinkList[i].nextThinkTick==0 || pList[out]->GetFirstThinkTick()==m_simThinkList[i].nextThinkTick); - Assert( gEntList.IsEntityPtr( pList[out] ) ); - out++; - } - } - - return out; - } - - void EntityChanged( CBaseEntity *pEntity ) - { - // might change after deletion, don't put back into the list - if ( pEntity->IsMarkedForDeletion() ) - return; - - const CBaseHandle &eh = pEntity->GetRefEHandle(); - if ( !eh.IsValid() ) - return; - - int index = eh.GetEntryIndex(); - if ( pEntity->IsEFlagSet( EFL_NO_THINK_FUNCTION ) && pEntity->IsEFlagSet( EFL_NO_GAME_PHYSICS_SIMULATION ) ) - { - RemoveEntinfoIndex( index ); - } - else - { - // already in the list? (had think or sim last time, now has both - or had both last time, now just one) - if ( m_entinfoIndex[index] == 0xFFFF ) - { - MEM_ALLOC_CREDIT(); - m_entinfoIndex[index] = m_simThinkList.AddToTail(); - m_simThinkList[m_entinfoIndex[index]].entEntry = (unsigned short)index; - m_simThinkList[m_entinfoIndex[index]].nextThinkTick = 0; - if ( pEntity->IsEFlagSet(EFL_NO_GAME_PHYSICS_SIMULATION) ) - { - m_simThinkList[m_entinfoIndex[index]].nextThinkTick = pEntity->GetFirstThinkTick(); - Assert(m_simThinkList[m_entinfoIndex[index]].nextThinkTick>=0); - } - } - else - { - // updating existing entry - if no sim, reset think time - if ( pEntity->IsEFlagSet(EFL_NO_GAME_PHYSICS_SIMULATION) ) - { - m_simThinkList[m_entinfoIndex[index]].nextThinkTick = pEntity->GetFirstThinkTick(); - Assert(m_simThinkList[m_entinfoIndex[index]].nextThinkTick>=0); - } - else - { - m_simThinkList[m_entinfoIndex[index]].nextThinkTick = 0; - } - } - } - } - -private: - unsigned short m_entinfoIndex[NUM_ENT_ENTRIES]; - CUtlVector m_simThinkList; -}; - -CSimThinkManager g_SimThinkManager; - -int SimThink_ListCount() -{ - return g_SimThinkManager.ListCount(); -} - -int SimThink_ListCopy( CBaseEntity *pList[], int listMax ) -{ - return g_SimThinkManager.ListCopy( pList, listMax ); -} - -void SimThink_EntityChanged( CBaseEntity *pEntity ) -{ - g_SimThinkManager.EntityChanged( pEntity ); -} - -// This manages a list of entities queued up to receive PostClientMessages callbacks -class CPostClientMessageManager -{ -public: - void LevelShutdownPostEntity() - { - m_list.Purge(); - } - void AddEntity( CBaseEntity *pEntity ) - { - MEM_ALLOC_CREDIT(); - m_list.AddToTail( (unsigned short)pEntity->GetRefEHandle().GetEntryIndex() ); - } - void PostClientMessagesSent() - { - for ( int i = m_list.Count()-1; i >= 0; --i ) - { - CBaseEntity *pEntity = (CBaseEntity *)gEntList.GetEntInfoPtrByIndex( m_list[i] )->m_pEntity; - - if ( pEntity ) - { - pEntity->PostClientMessagesSent(); - } - } - m_list.RemoveAll(); - } -private: - // UNDONE: Need to use ehandles instead? - CUtlVector m_list; -}; - -static CPostClientMessageManager g_PostClientManager; - -static CBaseEntityClassList *s_pClassLists = NULL; -CBaseEntityClassList::CBaseEntityClassList() -{ - m_pNextClassList = s_pClassLists; - s_pClassLists = this; -} -CBaseEntityClassList::~CBaseEntityClassList() -{ -} - -CGlobalEntityList::CGlobalEntityList() -{ - m_iHighestEnt = m_iNumEnts = m_iNumEdicts = 0; - m_bClearingEntities = false; -} - - -// removes the entity from the global list -// only called from with the CBaseEntity destructor -static bool g_fInCleanupDelete; - - -// mark an entity as deleted -void CGlobalEntityList::AddToDeleteList( IServerNetworkable *ent ) -{ - if ( ent && ent->GetEntityHandle()->GetRefEHandle() != INVALID_EHANDLE_INDEX ) - { - g_DeleteList.AddToTail( ent ); - } -} - -extern bool g_bDisableEhandleAccess; -// call this before and after each frame to delete all of the marked entities. -void CGlobalEntityList::CleanupDeleteList( void ) -{ - VPROF( "CGlobalEntityList::CleanupDeleteList" ); - g_fInCleanupDelete = true; - // clean up the vphysics delete list as well - PhysOnCleanupDeleteList(); - - g_bDisableEhandleAccess = true; - for ( int i = 0; i < g_DeleteList.Count(); i++ ) - { - g_DeleteList[i]->Release(); - } - g_bDisableEhandleAccess = false; - g_DeleteList.RemoveAll(); - - g_fInCleanupDelete = false; -} - -int CGlobalEntityList::ResetDeleteList( void ) -{ - int result = g_DeleteList.Count(); - g_DeleteList.RemoveAll(); - return result; -} - - - // add a class that gets notified of entity events -void CGlobalEntityList::AddListenerEntity( IEntityListener *pListener ) -{ - if ( m_entityListeners.Find( pListener ) >= 0 ) - { - AssertMsg( 0, "Can't add listeners multiple times\n" ); - return; - } - m_entityListeners.AddToTail( pListener ); -} - -void CGlobalEntityList::RemoveListenerEntity( IEntityListener *pListener ) -{ - m_entityListeners.FindAndRemove( pListener ); -} - -void CGlobalEntityList::Clear( void ) -{ - m_bClearingEntities = true; - - // Add all remaining entities in the game to the delete list and call appropriate UpdateOnRemove - CBaseHandle hCur = FirstHandle(); - while ( hCur != InvalidHandle() ) - { - IServerNetworkable *ent = GetServerNetworkable( hCur ); - if ( ent ) - { - MDLCACHE_CRITICAL_SECTION(); - // Force UpdateOnRemove to be called - UTIL_Remove( ent ); - } - hCur = NextHandle( hCur ); - } - - CleanupDeleteList(); - // free the memory - g_DeleteList.Purge(); - - CBaseEntity::m_nDebugPlayer = -1; - CBaseEntity::m_bInDebugSelect = false; - m_iHighestEnt = 0; - m_iNumEnts = 0; - - m_bClearingEntities = false; -} - - -int CGlobalEntityList::NumberOfEntities( void ) -{ - return m_iNumEnts; -} - -int CGlobalEntityList::NumberOfEdicts( void ) -{ - return m_iNumEdicts; -} - -CBaseEntity *CGlobalEntityList::NextEnt( CBaseEntity *pCurrentEnt ) -{ - if ( !pCurrentEnt ) - { - const CEntInfo *pInfo = FirstEntInfo(); - if ( !pInfo ) - return NULL; - - return (CBaseEntity *)pInfo->m_pEntity; - } - - // Run through the list until we get a CBaseEntity. - const CEntInfo *pList = GetEntInfoPtr( pCurrentEnt->GetRefEHandle() ); - if ( pList ) - pList = NextEntInfo(pList); - - while ( pList ) - { -#if 0 - if ( pList->m_pEntity ) - { - IServerUnknown *pUnk = static_cast(const_cast(pList->m_pEntity)); - CBaseEntity *pRet = pUnk->GetBaseEntity(); - if ( pRet ) - return pRet; - } -#else - return (CBaseEntity *)pList->m_pEntity; -#endif - pList = pList->m_pNext; - } - - return NULL; - -} - - -void CGlobalEntityList::ReportEntityFlagsChanged( CBaseEntity *pEntity, unsigned int flagsOld, unsigned int flagsNow ) -{ - if ( pEntity->IsMarkedForDeletion() ) - return; - // UNDONE: Move this into IEntityListener instead? - unsigned int flagsChanged = flagsOld ^ flagsNow; - if ( flagsChanged & FL_AIMTARGET ) - { - unsigned int flagsAdded = flagsNow & flagsChanged; - unsigned int flagsRemoved = flagsOld & flagsChanged; - - if ( flagsAdded & FL_AIMTARGET ) - { - g_AimManager.AddEntity( pEntity ); - } - if ( flagsRemoved & FL_AIMTARGET ) - { - g_AimManager.RemoveEntity( pEntity ); - } - } -} - -void CGlobalEntityList::AddPostClientMessageEntity( CBaseEntity *pEntity ) -{ - g_PostClientManager.AddEntity( pEntity ); -} -void CGlobalEntityList::PostClientMessagesSent() -{ - g_PostClientManager.PostClientMessagesSent(); -} - -//----------------------------------------------------------------------------- -// Purpose: Used to confirm a pointer is a pointer to an entity, useful for -// asserts. -//----------------------------------------------------------------------------- -bool CGlobalEntityList::IsEntityPtr( void *pTest ) -{ - if ( pTest ) - { - const CEntInfo *pInfo = FirstEntInfo(); - for ( ;pInfo; pInfo = pInfo->m_pNext ) - { - if ( pTest == (void *)pInfo->m_pEntity ) - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Iterates the entities with a given classname. -// Input : pStartEntity - Last entity found, NULL to start a new iteration. -// szName - Classname to search for. -//----------------------------------------------------------------------------- -CBaseEntity *CGlobalEntityList::FindEntityByClassname( CBaseEntity *pStartEntity, const char *szName ) -{ - const CEntInfo *pInfo = pStartEntity ? GetEntInfoPtr( pStartEntity->GetRefEHandle() )->m_pNext : FirstEntInfo(); - - for ( ;pInfo; pInfo = pInfo->m_pNext ) - { - CBaseEntity *pEntity = (CBaseEntity *)pInfo->m_pEntity; - if ( !pEntity ) - { - DevWarning( "NULL entity in global entity list!\n" ); - continue; - } - - if ( pEntity->ClassMatches(szName) ) - return pEntity; - } - - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Finds an entity given a procedural name. -// Input : szName - The procedural name to search for, should start with '!'. -// pSearchingEntity - -// pActivator - The activator entity if this was called from an input -// or Use handler. -//----------------------------------------------------------------------------- -CBaseEntity *CGlobalEntityList::FindEntityProcedural( const char *szName, CBaseEntity *pSearchingEntity, CBaseEntity *pActivator, CBaseEntity *pCaller ) -{ - // - // Check for the name escape character. - // - if ( szName[0] == '!' ) - { - const char *pName = szName + 1; - - // - // It is a procedural name, look for the ones we understand. - // - if ( FStrEq( pName, "player" ) ) - { - return (CBaseEntity *)UTIL_PlayerByIndex( 1 ); - } - else if ( FStrEq( pName, "pvsplayer" ) ) - { - if ( pSearchingEntity ) - { - return CBaseEntity::Instance( UTIL_FindClientInPVS( pSearchingEntity->edict() ) ); - } - else if ( pActivator ) - { - // FIXME: error condition? - return CBaseEntity::Instance( UTIL_FindClientInPVS( pActivator->edict() ) ); - } - else - { - // FIXME: error condition? - return (CBaseEntity *)UTIL_PlayerByIndex( 1 ); - } - - } - else if ( FStrEq( pName, "activator" ) ) - { - return pActivator; - } - else if ( FStrEq( pName, "caller" ) ) - { - return pCaller; - } - else if ( FStrEq( pName, "picker" ) ) - { - return FindPickerEntity( UTIL_PlayerByIndex(1) ); - } - else if ( FStrEq( pName, "self" ) ) - { - return pSearchingEntity; - } - else - { - Warning( "Invalid entity search name %s\n", szName ); - Assert(0); - } - } - - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Iterates the entities with a given name. -// Input : pStartEntity - Last entity found, NULL to start a new iteration. -// szName - Name to search for. -// pActivator - Activator entity if this was called from an input -// handler or Use handler. -//----------------------------------------------------------------------------- -CBaseEntity *CGlobalEntityList::FindEntityByName( CBaseEntity *pStartEntity, const char *szName, CBaseEntity *pSearchingEntity, CBaseEntity *pActivator, CBaseEntity *pCaller, IEntityFindFilter *pFilter ) -{ - if ( !szName || szName[0] == 0 ) - return NULL; - - if ( szName[0] == '!' ) - { - // - // Avoid an infinite loop, only find one match per procedural search! - // - if (pStartEntity == NULL) - return FindEntityProcedural( szName, pSearchingEntity, pActivator, pCaller ); - - return NULL; - } - - const CEntInfo *pInfo = pStartEntity ? GetEntInfoPtr( pStartEntity->GetRefEHandle() )->m_pNext : FirstEntInfo(); - - for ( ;pInfo; pInfo = pInfo->m_pNext ) - { - CBaseEntity *ent = (CBaseEntity *)pInfo->m_pEntity; - if ( !ent ) - { - DevWarning( "NULL entity in global entity list!\n" ); - continue; - } - - if ( !ent->m_iName ) - continue; - - if ( ent->NameMatches( szName ) ) - { - if ( pFilter && !pFilter->ShouldFindEntity(ent) ) - continue; - - return ent; - } - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pStartEntity - -// szModelName - -//----------------------------------------------------------------------------- -CBaseEntity *CGlobalEntityList::FindEntityByModel( CBaseEntity *pStartEntity, const char *szModelName ) -{ - const CEntInfo *pInfo = pStartEntity ? GetEntInfoPtr( pStartEntity->GetRefEHandle() )->m_pNext : FirstEntInfo(); - - for ( ;pInfo; pInfo = pInfo->m_pNext ) - { - CBaseEntity *ent = (CBaseEntity *)pInfo->m_pEntity; - if ( !ent ) - { - DevWarning( "NULL entity in global entity list!\n" ); - continue; - } - - if ( !ent->edict() || !ent->GetModelName() ) - continue; - - if ( FStrEq( STRING(ent->GetModelName()), szModelName ) ) - return ent; - } - - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Iterates the entities with a given target. -// Input : pStartEntity - -// szName - -//----------------------------------------------------------------------------- -// FIXME: obsolete, remove -CBaseEntity *CGlobalEntityList::FindEntityByTarget( CBaseEntity *pStartEntity, const char *szName ) -{ - const CEntInfo *pInfo = pStartEntity ? GetEntInfoPtr( pStartEntity->GetRefEHandle() )->m_pNext : FirstEntInfo(); - - for ( ;pInfo; pInfo = pInfo->m_pNext ) - { - CBaseEntity *ent = (CBaseEntity *)pInfo->m_pEntity; - if ( !ent ) - { - DevWarning( "NULL entity in global entity list!\n" ); - continue; - } - - if ( !ent->m_target ) - continue; - - if ( FStrEq( STRING(ent->m_target), szName ) ) - return ent; - } - - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Used to iterate all the entities within a sphere. -// Input : pStartEntity - -// vecCenter - -// flRadius - -//----------------------------------------------------------------------------- -CBaseEntity *CGlobalEntityList::FindEntityInSphere( CBaseEntity *pStartEntity, const Vector &vecCenter, float flRadius ) -{ - const CEntInfo *pInfo = pStartEntity ? GetEntInfoPtr( pStartEntity->GetRefEHandle() )->m_pNext : FirstEntInfo(); - - for ( ;pInfo; pInfo = pInfo->m_pNext ) - { - CBaseEntity *ent = (CBaseEntity *)pInfo->m_pEntity; - if ( !ent ) - { - DevWarning( "NULL entity in global entity list!\n" ); - continue; - } - - if ( !ent->edict() ) - continue; - - Vector vecRelativeCenter; - ent->CollisionProp()->WorldToCollisionSpace( vecCenter, &vecRelativeCenter ); - if ( !IsBoxIntersectingSphere( ent->CollisionProp()->OBBMins(), ent->CollisionProp()->OBBMaxs(), vecRelativeCenter, flRadius ) ) - continue; - - return ent; - } - - // nothing found - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Finds the nearest entity by name within a radius -// Input : szName - Entity name to search for. -// vecSrc - Center of search radius. -// flRadius - Search radius for classname search, 0 to search everywhere. -// pSearchingEntity - The entity that is doing the search. -// pActivator - The activator entity if this was called from an input -// or Use handler, NULL otherwise. -// Output : Returns a pointer to the found entity, NULL if none. -//----------------------------------------------------------------------------- -CBaseEntity *CGlobalEntityList::FindEntityByNameNearest( const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity, CBaseEntity *pActivator, CBaseEntity *pCaller ) -{ - CBaseEntity *pEntity = NULL; - - // - // Check for matching class names within the search radius. - // - float flMaxDist2 = flRadius * flRadius; - if (flMaxDist2 == 0) - { - flMaxDist2 = MAX_TRACE_LENGTH * MAX_TRACE_LENGTH; - } - - CBaseEntity *pSearch = NULL; - while ((pSearch = gEntList.FindEntityByName( pSearch, szName, pSearchingEntity, pActivator, pCaller )) != NULL) - { - if ( !pSearch->edict() ) - continue; - - float flDist2 = (pSearch->GetAbsOrigin() - vecSrc).LengthSqr(); - - if (flMaxDist2 > flDist2) - { - pEntity = pSearch; - flMaxDist2 = flDist2; - } - } - - return pEntity; -} - - - -//----------------------------------------------------------------------------- -// Purpose: Finds the first entity by name within a radius -// Input : pStartEntity - The entity to start from when doing the search. -// szName - Entity name to search for. -// vecSrc - Center of search radius. -// flRadius - Search radius for classname search, 0 to search everywhere. -// pSearchingEntity - The entity that is doing the search. -// pActivator - The activator entity if this was called from an input -// or Use handler, NULL otherwise. -// Output : Returns a pointer to the found entity, NULL if none. -//----------------------------------------------------------------------------- -CBaseEntity *CGlobalEntityList::FindEntityByNameWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity, CBaseEntity *pActivator, CBaseEntity *pCaller ) -{ - // - // Check for matching class names within the search radius. - // - CBaseEntity *pEntity = pStartEntity; - float flMaxDist2 = flRadius * flRadius; - if (flMaxDist2 == 0) - { - return gEntList.FindEntityByName( pEntity, szName, pSearchingEntity, pActivator, pCaller ); - } - - while ((pEntity = gEntList.FindEntityByName( pEntity, szName, pSearchingEntity, pActivator, pCaller )) != NULL) - { - if ( !pEntity->edict() ) - continue; - - float flDist2 = (pEntity->GetAbsOrigin() - vecSrc).LengthSqr(); - - if (flMaxDist2 > flDist2) - { - return pEntity; - } - } - - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Finds the nearest entity by class name withing given search radius. -// Input : szName - Entity name to search for. Treated as a target name first, -// then as an entity class name, ie "info_target". -// vecSrc - Center of search radius. -// flRadius - Search radius for classname search, 0 to search everywhere. -// Output : Returns a pointer to the found entity, NULL if none. -//----------------------------------------------------------------------------- -CBaseEntity *CGlobalEntityList::FindEntityByClassnameNearest( const char *szName, const Vector &vecSrc, float flRadius ) -{ - CBaseEntity *pEntity = NULL; - - // - // Check for matching class names within the search radius. - // - float flMaxDist2 = flRadius * flRadius; - if (flMaxDist2 == 0) - { - flMaxDist2 = MAX_TRACE_LENGTH * MAX_TRACE_LENGTH; - } - - CBaseEntity *pSearch = NULL; - while ((pSearch = gEntList.FindEntityByClassname( pSearch, szName )) != NULL) - { - if ( !pSearch->edict() ) - continue; - - float flDist2 = (pSearch->GetAbsOrigin() - vecSrc).LengthSqr(); - - if (flMaxDist2 > flDist2) - { - pEntity = pSearch; - flMaxDist2 = flDist2; - } - } - - return pEntity; -} - - - -//----------------------------------------------------------------------------- -// Purpose: Finds the first entity within radius distance by class name. -// Input : pStartEntity - The entity to start from when doing the search. -// szName - Entity class name, ie "info_target". -// vecSrc - Center of search radius. -// flRadius - Search radius for classname search, 0 to search everywhere. -// Output : Returns a pointer to the found entity, NULL if none. -//----------------------------------------------------------------------------- -CBaseEntity *CGlobalEntityList::FindEntityByClassnameWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecSrc, float flRadius ) -{ - // - // Check for matching class names within the search radius. - // - CBaseEntity *pEntity = pStartEntity; - float flMaxDist2 = flRadius * flRadius; - if (flMaxDist2 == 0) - { - return gEntList.FindEntityByClassname( pEntity, szName ); - } - - while ((pEntity = gEntList.FindEntityByClassname( pEntity, szName )) != NULL) - { - if ( !pEntity->edict() ) - continue; - - float flDist2 = (pEntity->GetAbsOrigin() - vecSrc).LengthSqr(); - - if (flMaxDist2 > flDist2) - { - return pEntity; - } - } - - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Finds an entity by target name or class name. -// Input : pStartEntity - The entity to start from when doing the search. -// szName - Entity name to search for. Treated as a target name first, -// then as an entity class name, ie "info_target". -// vecSrc - Center of search radius. -// flRadius - Search radius for classname search, 0 to search everywhere. -// pSearchingEntity - The entity that is doing the search. -// pActivator - The activator entity if this was called from an input -// or Use handler, NULL otherwise. -// Output : Returns a pointer to the found entity, NULL if none. -//----------------------------------------------------------------------------- -CBaseEntity *CGlobalEntityList::FindEntityGeneric( CBaseEntity *pStartEntity, const char *szName, CBaseEntity *pSearchingEntity, CBaseEntity *pActivator, CBaseEntity *pCaller ) -{ - CBaseEntity *pEntity = NULL; - - pEntity = gEntList.FindEntityByName( pStartEntity, szName, pSearchingEntity, pActivator, pCaller ); - if (!pEntity) - { - pEntity = gEntList.FindEntityByClassname( pStartEntity, szName ); - } - - return pEntity; -} - - -//----------------------------------------------------------------------------- -// Purpose: Finds the first entity by target name or class name within a radius -// Input : pStartEntity - The entity to start from when doing the search. -// szName - Entity name to search for. Treated as a target name first, -// then as an entity class name, ie "info_target". -// vecSrc - Center of search radius. -// flRadius - Search radius for classname search, 0 to search everywhere. -// pSearchingEntity - The entity that is doing the search. -// pActivator - The activator entity if this was called from an input -// or Use handler, NULL otherwise. -// Output : Returns a pointer to the found entity, NULL if none. -//----------------------------------------------------------------------------- -CBaseEntity *CGlobalEntityList::FindEntityGenericWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity, CBaseEntity *pActivator, CBaseEntity *pCaller ) -{ - CBaseEntity *pEntity = NULL; - - pEntity = gEntList.FindEntityByNameWithin( pStartEntity, szName, vecSrc, flRadius, pSearchingEntity, pActivator, pCaller ); - if (!pEntity) - { - pEntity = gEntList.FindEntityByClassnameWithin( pStartEntity, szName, vecSrc, flRadius ); - } - - return pEntity; -} - -//----------------------------------------------------------------------------- -// Purpose: Finds the nearest entity by target name or class name within a radius. -// Input : pStartEntity - The entity to start from when doing the search. -// szName - Entity name to search for. Treated as a target name first, -// then as an entity class name, ie "info_target". -// vecSrc - Center of search radius. -// flRadius - Search radius for classname search, 0 to search everywhere. -// pSearchingEntity - The entity that is doing the search. -// pActivator - The activator entity if this was called from an input -// or Use handler, NULL otherwise. -// Output : Returns a pointer to the found entity, NULL if none. -//----------------------------------------------------------------------------- -CBaseEntity *CGlobalEntityList::FindEntityGenericNearest( const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity, CBaseEntity *pActivator, CBaseEntity *pCaller ) -{ - CBaseEntity *pEntity = NULL; - - pEntity = gEntList.FindEntityByNameNearest( szName, vecSrc, flRadius, pSearchingEntity, pActivator, pCaller ); - if (!pEntity) - { - pEntity = gEntList.FindEntityByClassnameNearest( szName, vecSrc, flRadius ); - } - - return pEntity; -} - - -//----------------------------------------------------------------------------- -// Purpose: Find the nearest entity along the facing direction from the given origin -// within the angular threshold (ignores worldspawn) with the -// given classname. -// Input : origin - -// facing - -// threshold - -// classname - -//----------------------------------------------------------------------------- -CBaseEntity *CGlobalEntityList::FindEntityClassNearestFacing( const Vector &origin, const Vector &facing, float threshold, char *classname) -{ - float bestDot = threshold; - CBaseEntity *best_ent = NULL; - - const CEntInfo *pInfo = FirstEntInfo(); - - for ( ;pInfo; pInfo = pInfo->m_pNext ) - { - CBaseEntity *ent = (CBaseEntity *)pInfo->m_pEntity; - if ( !ent ) - { - DevWarning( "NULL entity in global entity list!\n" ); - continue; - } - - // FIXME: why is this skipping pointsize entities? - if (ent->IsPointSized() ) - continue; - - // Make vector to entity - Vector to_ent = (ent->GetAbsOrigin() - origin); - - VectorNormalize( to_ent ); - float dot = DotProduct (facing , to_ent ); - if (dot > bestDot) - { - if (FClassnameIs(ent,classname)) - { - // Ignore if worldspawn - if (!FClassnameIs( ent, "worldspawn" ) && !FClassnameIs( ent, "soundent")) - { - bestDot = dot; - best_ent = ent; - } - } - } - } - return best_ent; -} - - -//----------------------------------------------------------------------------- -// Purpose: Find the nearest entity along the facing direction from the given origin -// within the angular threshold (ignores worldspawn) -// Input : origin - -// facing - -// threshold - -//----------------------------------------------------------------------------- -CBaseEntity *CGlobalEntityList::FindEntityNearestFacing( const Vector &origin, const Vector &facing, float threshold) -{ - float bestDot = threshold; - CBaseEntity *best_ent = NULL; - - const CEntInfo *pInfo = FirstEntInfo(); - - for ( ;pInfo; pInfo = pInfo->m_pNext ) - { - CBaseEntity *ent = (CBaseEntity *)pInfo->m_pEntity; - if ( !ent ) - { - DevWarning( "NULL entity in global entity list!\n" ); - continue; - } - - // Ignore logical entities - if (!ent->edict()) - continue; - - // Make vector to entity - Vector to_ent = ent->WorldSpaceCenter() - origin; - VectorNormalize(to_ent); - - float dot = DotProduct( facing, to_ent ); - if (dot <= bestDot) - continue; - - // Ignore if worldspawn - if (!FStrEq( STRING(ent->m_iClassname), "worldspawn") && !FStrEq( STRING(ent->m_iClassname), "soundent")) - { - bestDot = dot; - best_ent = ent; - } - } - return best_ent; -} - - -void CGlobalEntityList::OnAddEntity( IHandleEntity *pEnt, CBaseHandle handle ) -{ - int i = handle.GetEntryIndex(); - - // record current list details - m_iNumEnts++; - if ( i > m_iHighestEnt ) - m_iHighestEnt = i; - - // If it's a CBaseEntity, notify the listeners. - CBaseEntity *pBaseEnt = static_cast(pEnt)->GetBaseEntity(); - if ( pBaseEnt->edict() ) - m_iNumEdicts++; - - // NOTE: Must be a CBaseEntity on server - Assert( pBaseEnt ); - //DevMsg(2,"Created %s\n", pBaseEnt->GetClassname() ); - for ( i = m_entityListeners.Count()-1; i >= 0; i-- ) - { - m_entityListeners[i]->OnEntityCreated( pBaseEnt ); - } -} - - -void CGlobalEntityList::OnRemoveEntity( IHandleEntity *pEnt, CBaseHandle handle ) -{ -#ifdef DEBUG - if ( !g_fInCleanupDelete ) - { - int i; - for ( i = 0; i < g_DeleteList.Count(); i++ ) - { - if ( g_DeleteList[i]->GetEntityHandle() == pEnt ) - { - g_DeleteList.FastRemove( i ); - Msg( "ERROR: Entity being destroyed but previously threaded on g_DeleteList\n" ); - break; - } - } - } -#endif - - CBaseEntity *pBaseEnt = static_cast(pEnt)->GetBaseEntity(); - if ( pBaseEnt->edict() ) - m_iNumEdicts--; - - m_iNumEnts--; -} - -void CGlobalEntityList::NotifyCreateEntity( CBaseEntity *pEnt ) -{ - if ( !pEnt ) - return; - - //DevMsg(2,"Deleted %s\n", pBaseEnt->GetClassname() ); - for ( int i = m_entityListeners.Count()-1; i >= 0; i-- ) - { - m_entityListeners[i]->OnEntityCreated( pEnt ); - } -} - -void CGlobalEntityList::NotifySpawn( CBaseEntity *pEnt ) -{ - if ( !pEnt ) - return; - - //DevMsg(2,"Deleted %s\n", pBaseEnt->GetClassname() ); - for ( int i = m_entityListeners.Count()-1; i >= 0; i-- ) - { - m_entityListeners[i]->OnEntitySpawned( pEnt ); - } -} - -// NOTE: This doesn't happen in OnRemoveEntity() specifically because -// listeners may want to reference the object as it's being deleted -// OnRemoveEntity isn't called until the destructor and all data is invalid. -void CGlobalEntityList::NotifyRemoveEntity( CBaseHandle hEnt ) -{ - CBaseEntity *pBaseEnt = GetBaseEntity( hEnt ); - if ( !pBaseEnt ) - return; - - //DevMsg(2,"Deleted %s\n", pBaseEnt->GetClassname() ); - for ( int i = m_entityListeners.Count()-1; i >= 0; i-- ) - { - m_entityListeners[i]->OnEntityDeleted( pBaseEnt ); - } -} - - -//----------------------------------------------------------------------------- -// NOTIFY LIST -// -// Allows entities to get events fired when another entity changes -//----------------------------------------------------------------------------- -struct entitynotify_t -{ - CBaseEntity *pNotify; - CBaseEntity *pWatched; -}; -class CNotifyList : public INotify, public IEntityListener -{ -public: - // INotify - void AddEntity( CBaseEntity *pNotify, CBaseEntity *pWatched ); - void RemoveEntity( CBaseEntity *pNotify, CBaseEntity *pWatched ); - void ReportNamedEvent( CBaseEntity *pEntity, const char *pEventName ); - void ClearEntity( CBaseEntity *pNotify ); - void ReportSystemEvent( CBaseEntity *pEntity, notify_system_event_t eventType, const notify_system_event_params_t ¶ms ); - - // IEntityListener - virtual void OnEntityCreated( CBaseEntity *pEntity ); - virtual void OnEntityDeleted( CBaseEntity *pEntity ); - - // Called from CEntityListSystem - void LevelInitPreEntity(); - void LevelShutdownPreEntity(); - -private: - CUtlVector m_notifyList; -}; - -void CNotifyList::AddEntity( CBaseEntity *pNotify, CBaseEntity *pWatched ) -{ - // OPTIMIZE: Also flag pNotify for faster "RemoveAllNotify" ? - pWatched->AddEFlags( EFL_NOTIFY ); - int index = m_notifyList.AddToTail(); - entitynotify_t ¬ify = m_notifyList[index]; - notify.pNotify = pNotify; - notify.pWatched = pWatched; -} - -// Remove noitfication for an entity -void CNotifyList::RemoveEntity( CBaseEntity *pNotify, CBaseEntity *pWatched ) -{ - for ( int i = m_notifyList.Count(); --i >= 0; ) - { - if ( m_notifyList[i].pNotify == pNotify && m_notifyList[i].pWatched == pWatched) - { - m_notifyList.FastRemove(i); - } - } -} - - -void CNotifyList::ReportNamedEvent( CBaseEntity *pEntity, const char *pInputName ) -{ - variant_t emptyVariant; - - if ( !pEntity->IsEFlagSet(EFL_NOTIFY) ) - return; - - for ( int i = 0; i < m_notifyList.Count(); i++ ) - { - if ( m_notifyList[i].pWatched == pEntity ) - { - m_notifyList[i].pNotify->AcceptInput( pInputName, pEntity, pEntity, emptyVariant, 0 ); - } - } -} - -void CNotifyList::LevelInitPreEntity() -{ - gEntList.AddListenerEntity( this ); -} - -void CNotifyList::LevelShutdownPreEntity( void ) -{ - gEntList.RemoveListenerEntity( this ); - m_notifyList.Purge(); -} - -void CNotifyList::OnEntityCreated( CBaseEntity *pEntity ) -{ -} - -void CNotifyList::OnEntityDeleted( CBaseEntity *pEntity ) -{ - ReportDestroyEvent( pEntity ); - ClearEntity( pEntity ); -} - - -// UNDONE: Slow linear search? -void CNotifyList::ClearEntity( CBaseEntity *pNotify ) -{ - for ( int i = m_notifyList.Count(); --i >= 0; ) - { - if ( m_notifyList[i].pNotify == pNotify || m_notifyList[i].pWatched == pNotify) - { - m_notifyList.FastRemove(i); - } - } -} - -void CNotifyList::ReportSystemEvent( CBaseEntity *pEntity, notify_system_event_t eventType, const notify_system_event_params_t ¶ms ) -{ - if ( !pEntity->IsEFlagSet(EFL_NOTIFY) ) - return; - - for ( int i = 0; i < m_notifyList.Count(); i++ ) - { - if ( m_notifyList[i].pWatched == pEntity ) - { - m_notifyList[i].pNotify->NotifySystemEvent( pEntity, eventType, params ); - } - } -} - -static CNotifyList g_NotifyList; -INotify *g_pNotify = &g_NotifyList; - -class CEntityTouchManager : public IEntityListener -{ -public: - // called by CEntityListSystem - void LevelInitPreEntity() - { - gEntList.AddListenerEntity( this ); - Clear(); - } - void LevelShutdownPostEntity() - { - gEntList.RemoveListenerEntity( this ); - Clear(); - } - void FrameUpdatePostEntityThink(); - - void Clear() - { - m_updateList.Purge(); - } - - // IEntityListener - virtual void OnEntityCreated( CBaseEntity *pEntity ) {} - virtual void OnEntityDeleted( CBaseEntity *pEntity ) - { - if ( !pEntity->GetCheckUntouch() ) - return; - int index = m_updateList.Find( pEntity ); - if ( m_updateList.IsValidIndex(index) ) - { - m_updateList.FastRemove( index ); - } - } - void AddEntity( CBaseEntity *pEntity ) - { - if ( pEntity->IsMarkedForDeletion() ) - return; - m_updateList.AddToTail( pEntity ); - } - -private: - CUtlVector m_updateList; -}; - -static CEntityTouchManager g_TouchManager; - -void EntityTouch_Add( CBaseEntity *pEntity ) -{ - g_TouchManager.AddEntity( pEntity ); -} - - -void CEntityTouchManager::FrameUpdatePostEntityThink() -{ - VPROF( "CEntityTouchManager::FrameUpdatePostEntityThink" ); - // Loop through all entities again, checking their untouch if flagged to do so - - int count = m_updateList.Count(); - if ( count ) - { - // copy off the list - CBaseEntity **ents = (CBaseEntity **)stackalloc( sizeof(CBaseEntity *) * count ); - memcpy( ents, m_updateList.Base(), sizeof(CBaseEntity *) * count ); - // clear it - m_updateList.RemoveAll(); - - // now update those ents - for ( int i = 0; i < count; i++ ) - { - //Assert( ents[i]->GetCheckUntouch() ); - if ( ents[i]->GetCheckUntouch() ) - { - ents[i]->PhysicsCheckForEntityUntouch(); - } - } - stackfree( ents ); - } -} - -class CRespawnEntitiesFilter : public IMapEntityFilter -{ -public: - virtual bool ShouldCreateEntity( const char *pClassname ) - { - // Create everything but the world - return Q_stricmp( pClassname, "worldspawn" ) != 0; - } - - virtual CBaseEntity* CreateNextEntity( const char *pClassname ) - { - return CreateEntityByName( pClassname ); - } -}; - -// One hook to rule them all... -// Since most of the little list managers in here only need one or two of the game -// system callbacks, this hook is a game system that passes them the appropriate callbacks -class CEntityListSystem : public CAutoGameSystemPerFrame -{ -public: - CEntityListSystem( char const *name ) : CAutoGameSystemPerFrame( name ) - { - m_bRespawnAllEntities = false; - } - void LevelInitPreEntity() - { - g_NotifyList.LevelInitPreEntity(); - g_TouchManager.LevelInitPreEntity(); - g_AimManager.LevelInitPreEntity(); - g_SimThinkManager.LevelInitPreEntity(); -#ifdef HL2_DLL - OverrideMoveCache_LevelInitPreEntity(); -#endif // HL2_DLL - } - void LevelShutdownPreEntity() - { - g_NotifyList.LevelShutdownPreEntity(); - } - void LevelShutdownPostEntity() - { - g_TouchManager.LevelShutdownPostEntity(); - g_AimManager.LevelShutdownPostEntity(); - g_PostClientManager.LevelShutdownPostEntity(); - g_SimThinkManager.LevelShutdownPostEntity(); -#ifdef HL2_DLL - OverrideMoveCache_LevelShutdownPostEntity(); -#endif // HL2_DLL - CBaseEntityClassList *pClassList = s_pClassLists; - while ( pClassList ) - { - pClassList->LevelShutdownPostEntity(); - pClassList = pClassList->m_pNextClassList; - } - } - - void FrameUpdatePostEntityThink() - { - g_TouchManager.FrameUpdatePostEntityThink(); - - if ( m_bRespawnAllEntities ) - { - m_bRespawnAllEntities = false; - - // Don't change globalstate owing to deletion here - GlobalEntity_EnableStateUpdates( false ); - - // Remove all entities - int nPlayerIndex = -1; - CBaseEntity *pEnt = gEntList.FirstEnt(); - while ( pEnt ) - { - CBaseEntity *pNextEnt = gEntList.NextEnt( pEnt ); - if ( pEnt->IsPlayer() ) - { - nPlayerIndex = pEnt->entindex(); - } - if ( !pEnt->IsEFlagSet( EFL_KEEP_ON_RECREATE_ENTITIES ) ) - { - UTIL_Remove( pEnt ); - } - pEnt = pNextEnt; - } - - gEntList.CleanupDeleteList(); - - GlobalEntity_EnableStateUpdates( true ); - - // Allows us to immediately re-use the edict indices we just freed to avoid edict overflow - engine->AllowImmediateEdictReuse(); - - // Reset node counter used during load - CNodeEnt::m_nNodeCount = 0; - - CRespawnEntitiesFilter filter; - MapEntity_ParseAllEntities( engine->GetMapEntitiesString(), &filter, true ); - - // Allocate a CBasePlayer for pev, and call spawn - if ( nPlayerIndex >= 0 ) - { - edict_t *pEdict = engine->PEntityOfEntIndex( nPlayerIndex ); - ClientPutInServer( pEdict, "unnamed" ); - ClientActive( pEdict, false ); - - CBasePlayer *pPlayer = ( CBasePlayer * )CBaseEntity::Instance( pEdict ); - SceneManager_ClientActive( pPlayer ); - } - } - } - - bool m_bRespawnAllEntities; -}; - -static CEntityListSystem g_EntityListSystem( "CEntityListSystem" ); - -//----------------------------------------------------------------------------- -// Respawns all entities in the level -//----------------------------------------------------------------------------- -void RespawnEntities() -{ - g_EntityListSystem.m_bRespawnAllEntities = true; -} - -static ConCommand restart_entities( "respawn_entities", RespawnEntities, "Respawn all the entities in the map.", FCVAR_CHEAT | FCVAR_SPONLY ); - -class CSortedEntityList -{ -public: - CSortedEntityList() : m_sortedList(), m_emptyCount(0) {} - - typedef CBaseEntity *ENTITYPTR; - class CEntityReportLess - { - public: - bool Less( const ENTITYPTR &src1, const ENTITYPTR &src2, void *pCtx ) - { - if ( stricmp( src1->GetClassname(), src2->GetClassname() ) < 0 ) - return true; - - return false; - } - }; - - void AddEntityToList( CBaseEntity *pEntity ) - { - if ( !pEntity ) - { - m_emptyCount++; - } - else - { - m_sortedList.Insert( pEntity ); - } - } - void ReportEntityList() - { - const char *pLastClass = ""; - int count = 0; - int edicts = 0; - for ( int i = 0; i < m_sortedList.Count(); i++ ) - { - CBaseEntity *pEntity = m_sortedList[i]; - if ( !pEntity ) - continue; - - if ( pEntity->edict() ) - edicts++; - - const char *pClassname = pEntity->GetClassname(); - if ( !FStrEq( pClassname, pLastClass ) ) - { - if ( count ) - { - Msg("Class: %s (%d)\n", pLastClass, count ); - } - - pLastClass = pClassname; - count = 1; - } - else - count++; - } - if ( pLastClass[0] != 0 && count ) - { - Msg("Class: %s (%d)\n", pLastClass, count ); - } - if ( m_sortedList.Count() ) - { - Msg("Total %d entities (%d empty, %d edicts)\n", m_sortedList.Count(), m_emptyCount, edicts ); - } - } -private: - CUtlSortVector< CBaseEntity *, CEntityReportLess > m_sortedList; - int m_emptyCount; -}; - - - -CON_COMMAND(report_entities, "Lists all entities") -{ - CSortedEntityList list; - CBaseEntity *pEntity = gEntList.FirstEnt(); - while ( pEntity ) - { - list.AddEntityToList( pEntity ); - pEntity = gEntList.NextEnt( pEntity ); - } - list.ReportEntityList(); -} - - -CON_COMMAND(report_touchlinks, "Lists all touchlinks") -{ - CSortedEntityList list; - CBaseEntity *pEntity = gEntList.FirstEnt(); - const char *pClassname = NULL; - if ( args.ArgC() > 1 ) - { - pClassname = args.Arg(1); - } - while ( pEntity ) - { - if ( !pClassname || FClassnameIs(pEntity, pClassname) ) - { - touchlink_t *root = ( touchlink_t * )pEntity->GetDataObject( TOUCHLINK ); - if ( root ) - { - touchlink_t *link = root->nextLink; - while ( link != root ) - { - list.AddEntityToList( link->entityTouched ); - link = link->nextLink; - } - } - } - pEntity = gEntList.NextEnt( pEntity ); - } - list.ReportEntityList(); -} - -CON_COMMAND(report_simthinklist, "Lists all simulating/thinking entities") -{ - CBaseEntity *pTmp[NUM_ENT_ENTRIES]; - int count = SimThink_ListCopy( pTmp, ARRAYSIZE(pTmp) ); - - CSortedEntityList list; - for ( int i = 0; i < count; i++ ) - { - if ( !pTmp[i] ) - continue; - - list.AddEntityToList( pTmp[i] ); - } - list.ReportEntityList(); -} - diff --git a/game/server/entitylist.h b/game/server/entitylist.h deleted file mode 100644 index 2010007fa..000000000 --- a/game/server/entitylist.h +++ /dev/null @@ -1,366 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef ENTITYLIST_H -#define ENTITYLIST_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "baseentity.h" - -class IEntityListener; - -abstract_class CBaseEntityClassList -{ -public: - CBaseEntityClassList(); - ~CBaseEntityClassList(); - virtual void LevelShutdownPostEntity() = 0; - - CBaseEntityClassList *m_pNextClassList; -}; - -template< class T > -class CEntityClassList : public CBaseEntityClassList -{ -public: - virtual void LevelShutdownPostEntity() { m_pClassList = NULL; } - - void Insert( T *pEntity ) - { - pEntity->m_pNext = m_pClassList; - m_pClassList = pEntity; - } - - void Remove( T *pEntity ) - { - T **pPrev = &m_pClassList; - T *pCur = *pPrev; - while ( pCur ) - { - if ( pCur == pEntity ) - { - *pPrev = pCur->m_pNext; - return; - } - pPrev = &pCur->m_pNext; - pCur = *pPrev; - } - } - - static T *m_pClassList; -}; - -// Derive a class from this if you want to filter entity list searches -abstract_class IEntityFindFilter -{ -public: - virtual bool ShouldFindEntity( CBaseEntity *pEntity ) = 0; - virtual CBaseEntity *GetFilterResult( void ) = 0; -}; - -//----------------------------------------------------------------------------- -// Purpose: a global list of all the entities in the game. All iteration through -// entities is done through this object. -//----------------------------------------------------------------------------- -class CGlobalEntityList : public CBaseEntityList -{ -public: -private: - int m_iHighestEnt; // the topmost used array index - int m_iNumEnts; - int m_iNumEdicts; - - bool m_bClearingEntities; - CUtlVector m_entityListeners; - -public: - IServerNetworkable* GetServerNetworkable( CBaseHandle hEnt ) const; - CBaseNetworkable* GetBaseNetworkable( CBaseHandle hEnt ) const; - CBaseEntity* GetBaseEntity( CBaseHandle hEnt ) const; - edict_t* GetEdict( CBaseHandle hEnt ) const; - - int NumberOfEntities( void ); - int NumberOfEdicts( void ); - - // mark an entity as deleted - void AddToDeleteList( IServerNetworkable *ent ); - // call this before and after each frame to delete all of the marked entities. - void CleanupDeleteList( void ); - int ResetDeleteList( void ); - - // frees all entities in the game - void Clear( void ); - - // Returns true while in the Clear() call. - bool IsClearingEntities() {return m_bClearingEntities;} - - // add a class that gets notified of entity events - void AddListenerEntity( IEntityListener *pListener ); - void RemoveListenerEntity( IEntityListener *pListener ); - - void ReportEntityFlagsChanged( CBaseEntity *pEntity, unsigned int flagsOld, unsigned int flagsNow ); - // Schedule this entity for notification once client messages have been sent - void AddPostClientMessageEntity( CBaseEntity *pEntity ); - void PostClientMessagesSent(); - - // entity is about to be removed, notify the listeners - void NotifyCreateEntity( CBaseEntity *pEnt ); - void NotifySpawn( CBaseEntity *pEnt ); - void NotifyRemoveEntity( CBaseHandle hEnt ); - // iteration functions - - // returns the next entity after pCurrentEnt; if pCurrentEnt is NULL, return the first entity - CBaseEntity *NextEnt( CBaseEntity *pCurrentEnt ); - CBaseEntity *FirstEnt() { return NextEnt(NULL); } - - // returns the next entity of the specified class, using RTTI - template< class T > - T *NextEntByClass( T *start ) - { - for ( CBaseEntity *x = NextEnt( start ); x; x = NextEnt( x ) ) - { - start = dynamic_cast( x ); - if ( start ) - return start; - } - return NULL; - } - - // search functions - bool IsEntityPtr( void *pTest ); - CBaseEntity *FindEntityByClassname( CBaseEntity *pStartEntity, const char *szName ); - CBaseEntity *FindEntityByName( CBaseEntity *pStartEntity, const char *szName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL, IEntityFindFilter *pFilter = NULL ); - CBaseEntity *FindEntityByName( CBaseEntity *pStartEntity, string_t iszName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL, IEntityFindFilter *pFilter = NULL ) - { - return FindEntityByName( pStartEntity, STRING(iszName), pSearchingEntity, pActivator, pCaller, pFilter ); - } - CBaseEntity *FindEntityInSphere( CBaseEntity *pStartEntity, const Vector &vecCenter, float flRadius ); - CBaseEntity *FindEntityByTarget( CBaseEntity *pStartEntity, const char *szName ); - CBaseEntity *FindEntityByModel( CBaseEntity *pStartEntity, const char *szModelName ); - - CBaseEntity *FindEntityByNameNearest( const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); - CBaseEntity *FindEntityByNameWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); - CBaseEntity *FindEntityByClassnameNearest( const char *szName, const Vector &vecSrc, float flRadius ); - CBaseEntity *FindEntityByClassnameWithin( CBaseEntity *pStartEntity , const char *szName, const Vector &vecSrc, float flRadius ); - - CBaseEntity *FindEntityGeneric( CBaseEntity *pStartEntity, const char *szName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); - CBaseEntity *FindEntityGenericWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); - CBaseEntity *FindEntityGenericNearest( const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); - - CBaseEntity *FindEntityNearestFacing( const Vector &origin, const Vector &facing, float threshold); - CBaseEntity *FindEntityClassNearestFacing( const Vector &origin, const Vector &facing, float threshold, char *classname); - CBaseEntity *FindEntityByNetname( CBaseEntity *pStartEntity, const char *szModelName ); - - CBaseEntity *FindEntityProcedural( const char *szName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); - - CGlobalEntityList(); - -// CBaseEntityList overrides. -protected: - - virtual void OnAddEntity( IHandleEntity *pEnt, CBaseHandle handle ); - virtual void OnRemoveEntity( IHandleEntity *pEnt, CBaseHandle handle ); - -}; - -extern CGlobalEntityList gEntList; - - -//----------------------------------------------------------------------------- -// Inlines. -//----------------------------------------------------------------------------- -inline edict_t* CGlobalEntityList::GetEdict( CBaseHandle hEnt ) const -{ - IServerUnknown *pUnk = static_cast(LookupEntity( hEnt )); - if ( pUnk ) - return pUnk->GetNetworkable()->GetEdict(); - else - return NULL; -} - -inline CBaseNetworkable* CGlobalEntityList::GetBaseNetworkable( CBaseHandle hEnt ) const -{ - IServerUnknown *pUnk = static_cast(LookupEntity( hEnt )); - if ( pUnk ) - return pUnk->GetNetworkable()->GetBaseNetworkable(); - else - return NULL; -} - -inline IServerNetworkable* CGlobalEntityList::GetServerNetworkable( CBaseHandle hEnt ) const -{ - IServerUnknown *pUnk = static_cast(LookupEntity( hEnt )); - if ( pUnk ) - return pUnk->GetNetworkable(); - else - return NULL; -} - -inline CBaseEntity* CGlobalEntityList::GetBaseEntity( CBaseHandle hEnt ) const -{ - IServerUnknown *pUnk = static_cast(LookupEntity( hEnt )); - if ( pUnk ) - return pUnk->GetBaseEntity(); - else - return NULL; -} - - -//----------------------------------------------------------------------------- -// Common finds -#if 0 - -template -inline bool FindEntityByName( const char *pszName, ENT_TYPE **ppResult) -{ - CBaseEntity *pBaseEntity = gEntList.FindEntityByName( NULL, pszName ); - - if ( pBaseEntity ) - *ppResult = dynamic_cast( pBaseEntity ); - else - *ppResult = NULL; - - return ( *ppResult != NULL ); -} - -template <> -inline bool FindEntityByName( const char *pszName, CBaseEntity **ppResult) -{ - *ppResult = gEntList.FindEntityByName( NULL, pszName ); - return ( *ppResult != NULL ); -} - -template <> -inline bool FindEntityByName( const char *pszName, CAI_BaseNPC **ppResult) -{ - CBaseEntity *pBaseEntity = gEntList.FindEntityByName( NULL, pszName ); - - if ( pBaseEntity ) - *ppResult = pBaseEntity->MyNPCPointer(); - else - *ppResult = NULL; - - return ( *ppResult != NULL ); -} -#endif -//----------------------------------------------------------------------------- -// Purpose: Simple object for storing a list of objects -//----------------------------------------------------------------------------- -struct entitem_t -{ - EHANDLE hEnt; - struct entitem_t *pNext; - - // uses pool memory - static void* operator new( size_t stAllocateBlock ); - static void *operator new( size_t stAllocateBlock, int nBlockUse, const char *pFileName, int nLine ); - static void operator delete( void *pMem ); - static void operator delete( void *pMem, int nBlockUse, const char *pFileName, int nLine ) { operator delete( pMem ); } -}; - -class CEntityList -{ -public: - CEntityList(); - ~CEntityList(); - - int m_iNumItems; - entitem_t *m_pItemList; // null terminated singly-linked list - - void AddEntity( CBaseEntity * ); - void DeleteEntity( CBaseEntity * ); -}; - -enum notify_system_event_t -{ - NOTIFY_EVENT_TELEPORT = 0, - NOTIFY_EVENT_DESTROY, -}; - -struct notify_teleport_params_t -{ - Vector prevOrigin; - QAngle prevAngles; - bool physicsRotate; -}; - -struct notify_destroy_params_t -{ -}; - -struct notify_system_event_params_t -{ - union - { - const notify_teleport_params_t *pTeleport; - const notify_destroy_params_t *pDestroy; - }; - notify_system_event_params_t( const notify_teleport_params_t *pInTeleport ) { pTeleport = pInTeleport; } - notify_system_event_params_t( const notify_destroy_params_t *pInDestroy ) { pDestroy = pInDestroy; } -}; - - -abstract_class INotify -{ -public: - // Add notification for an entity - virtual void AddEntity( CBaseEntity *pNotify, CBaseEntity *pWatched ) = 0; - - // Remove notification for an entity - virtual void RemoveEntity( CBaseEntity *pNotify, CBaseEntity *pWatched ) = 0; - - // Call the named input in each entity who is watching pEvent's status - virtual void ReportNamedEvent( CBaseEntity *pEntity, const char *pEventName ) = 0; - - // System events don't make sense as inputs, so are handled through a generic notify function - virtual void ReportSystemEvent( CBaseEntity *pEntity, notify_system_event_t eventType, const notify_system_event_params_t ¶ms ) = 0; - - inline void ReportDestroyEvent( CBaseEntity *pEntity ) - { - notify_destroy_params_t destroy; - ReportSystemEvent( pEntity, NOTIFY_EVENT_DESTROY, notify_system_event_params_t(&destroy) ); - } - - inline void ReportTeleportEvent( CBaseEntity *pEntity, const Vector &prevOrigin, const QAngle &prevAngles, bool physicsRotate ) - { - notify_teleport_params_t teleport; - teleport.prevOrigin = prevOrigin; - teleport.prevAngles = prevAngles; - teleport.physicsRotate = physicsRotate; - ReportSystemEvent( pEntity, NOTIFY_EVENT_TELEPORT, notify_system_event_params_t(&teleport) ); - } - - // Remove this entity from the notify list - virtual void ClearEntity( CBaseEntity *pNotify ) = 0; -}; - -// Implement this class and register with gEntList to receive entity create/delete notification -class IEntityListener -{ -public: - virtual void OnEntityCreated( CBaseEntity *pEntity ) {}; - virtual void OnEntitySpawned( CBaseEntity *pEntity ) {}; - virtual void OnEntityDeleted( CBaseEntity *pEntity ) {}; -}; - -// singleton -extern INotify *g_pNotify; - -void EntityTouch_Add( CBaseEntity *pEntity ); -int AimTarget_ListCount(); -int AimTarget_ListCopy( CBaseEntity *pList[], int listMax ); -void AimTarget_ForceRepopulateList(); - -void SimThink_EntityChanged( CBaseEntity *pEntity ); -int SimThink_ListCount(); -int SimThink_ListCopy( CBaseEntity *pList[], int listMax ); - -#endif // ENTITYLIST_H diff --git a/game/server/entityoutput.h b/game/server/entityoutput.h deleted file mode 100644 index 75594927d..000000000 --- a/game/server/entityoutput.h +++ /dev/null @@ -1,195 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Declares basic entity communications classes, for input/output of data -// between entities -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ENTITYOUTPUT_H -#define ENTITYOUTPUT_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "baseentity.h" - - -#define EVENT_FIRE_ALWAYS -1 - - -//----------------------------------------------------------------------------- -// Purpose: A COutputEvent consists of an array of these CEventActions. -// Each CEventAction holds the information to fire a single input in -// a target entity, after a specific delay. -//----------------------------------------------------------------------------- -class CEventAction -{ -public: - CEventAction( const char *ActionData = NULL ); - - string_t m_iTarget; // name of the entity(s) to cause the action in - string_t m_iTargetInput; // the name of the action to fire - string_t m_iParameter; // parameter to send, 0 if none - float m_flDelay; // the number of seconds to wait before firing the action - int m_nTimesToFire; // The number of times to fire this event, or EVENT_FIRE_ALWAYS. - - int m_iIDStamp; // unique identifier stamp - - static int s_iNextIDStamp; - - CEventAction *m_pNext; - - // allocates memory from engine.MPool/g_EntityListPool - static void *operator new( size_t stAllocateBlock ); - static void *operator new( size_t stAllocateBlock, int nBlockUse, const char *pFileName, int nLine ); - static void operator delete( void *pMem ); - static void operator delete( void *pMem , int nBlockUse, const char *pFileName, int nLine ) { operator delete(pMem); } - - DECLARE_SIMPLE_DATADESC(); -}; - - -//----------------------------------------------------------------------------- -// Purpose: Stores a list of connections to other entities, for data/commands to be -// communicated along. -//----------------------------------------------------------------------------- -class CBaseEntityOutput -{ -public: - ~CBaseEntityOutput(); - - void ParseEventAction( const char *EventData ); - void AddEventAction( CEventAction *pEventAction ); - - int Save( ISave &save ); - int Restore( IRestore &restore, int elementCount ); - - int NumberOfElements( void ); - - float GetMaxDelay( void ); - - fieldtype_t ValueFieldType() { return m_Value.FieldType(); } - - void FireOutput( variant_t Value, CBaseEntity *pActivator, CBaseEntity *pCaller, float fDelay = 0 ); - - /// Delete every single action in the action list. - void DeleteAllElements( void ) ; - -protected: - variant_t m_Value; - CEventAction *m_ActionList; - DECLARE_SIMPLE_DATADESC(); - - CBaseEntityOutput() {} // this class cannot be created, only it's children - -private: - CBaseEntityOutput( CBaseEntityOutput& ); // protect from accidental copying -}; - - -//----------------------------------------------------------------------------- -// Purpose: wraps variant_t data handling in convenient, compiler type-checked template -//----------------------------------------------------------------------------- -template< class Type, fieldtype_t fieldType > -class CEntityOutputTemplate : public CBaseEntityOutput -{ -public: - // - // Sets an initial value without firing the output. - // - void Init( Type value ) - { - m_Value.Set( fieldType, &value ); - } - - // - // Sets a value and fires the output. - // - void Set( Type value, CBaseEntity *pActivator, CBaseEntity *pCaller ) - { - m_Value.Set( fieldType, &value ); - FireOutput( m_Value, pActivator, pCaller ); - } - - // - // Returns the current value. - // - Type Get( void ) - { - return *((Type*)&m_Value); - } -}; - - -// -// Template specializations for type Vector, so we can implement Get, Set, and Init differently. -// -template<> -class CEntityOutputTemplate : public CBaseEntityOutput -{ -public: - void Init( const Vector &value ) - { - m_Value.SetVector3D( value ); - } - - void Set( const Vector &value, CBaseEntity *pActivator, CBaseEntity *pCaller ) - { - m_Value.SetVector3D( value ); - FireOutput( m_Value, pActivator, pCaller ); - } - - void Get( Vector &vec ) - { - m_Value.Vector3D(vec); - } -}; - - -template<> -class CEntityOutputTemplate : public CBaseEntityOutput -{ -public: - void Init( const Vector &value ) - { - m_Value.SetPositionVector3D( value ); - } - - void Set( const Vector &value, CBaseEntity *pActivator, CBaseEntity *pCaller ) - { - m_Value.SetPositionVector3D( value ); - FireOutput( m_Value, pActivator, pCaller ); - } - - void Get( Vector &vec ) - { - m_Value.Vector3D(vec); - } -}; - - -//----------------------------------------------------------------------------- -// Purpose: parameterless entity event -//----------------------------------------------------------------------------- -class COutputEvent : public CBaseEntityOutput -{ -public: - // void Firing, no parameter - void FireOutput( CBaseEntity *pActivator, CBaseEntity *pCaller, float fDelay = 0 ); -}; - - -// useful typedefs for allowed output data types -typedef CEntityOutputTemplate COutputVariant; -typedef CEntityOutputTemplate COutputInt; -typedef CEntityOutputTemplate COutputFloat; -typedef CEntityOutputTemplate COutputString; -typedef CEntityOutputTemplate COutputEHANDLE; -typedef CEntityOutputTemplate COutputVector; -typedef CEntityOutputTemplate COutputPositionVector; -typedef CEntityOutputTemplate COutputColor32; - -#endif // ENTITYOUTPUT_H diff --git a/game/server/env_debughistory.cpp b/game/server/env_debughistory.cpp deleted file mode 100644 index d7498db0b..000000000 --- a/game/server/env_debughistory.cpp +++ /dev/null @@ -1,361 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= -#include "cbase.h" -#include "isaverestore.h" -#include "env_debughistory.h" -#include "tier0/vprof.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// Number of characters worth of debug to use per history category -#define DEBUG_HISTORY_VERSION 6 -#define DEBUG_HISTORY_FIRST_VERSIONED 5 -#define MAX_DEBUG_HISTORY_LINE_LENGTH 256 -#define MAX_DEBUG_HISTORY_LENGTH (1000 * MAX_DEBUG_HISTORY_LINE_LENGTH) - -//----------------------------------------------------------------------------- -// Purpose: Stores debug history in savegame files for debugging reference -//----------------------------------------------------------------------------- -class CDebugHistory : public CBaseEntity -{ - DECLARE_CLASS( CDebugHistory, CBaseEntity ); -public: - DECLARE_DATADESC(); - - void Spawn(); - void AddDebugHistoryLine( int iCategory, const char *szLine ); - void ClearHistories( void ); - void DumpDebugHistory( int iCategory ); - - int Save( ISave &save ); - int Restore( IRestore &restore ); - -private: - char m_DebugLines[MAX_HISTORY_CATEGORIES][MAX_DEBUG_HISTORY_LENGTH]; - char *m_DebugLineEnd[MAX_HISTORY_CATEGORIES]; -}; - -BEGIN_DATADESC( CDebugHistory ) - //DEFINE_FIELD( m_DebugLines, FIELD_CHARACTER ), // Not saved because we write it out manually - //DEFINE_FIELD( m_DebugLineEnd, FIELD_CHARACTER ), -END_DATADESC() - -LINK_ENTITY_TO_CLASS( env_debughistory, CDebugHistory ); - -// The handle to the debug history singleton. Created on first access via GetDebugHistory. -static CHandle< CDebugHistory > s_DebugHistory; - - -//----------------------------------------------------------------------------- -// Spawn -//----------------------------------------------------------------------------- -void CDebugHistory::Spawn() -{ - BaseClass::Spawn(); - -#ifdef DISABLE_DEBUG_HISTORY - UTIL_Remove( this ); -#else - if ( g_pGameRules && g_pGameRules->IsMultiplayer() ) - { - UTIL_Remove( this ); - } - else - { - Warning( "DEBUG HISTORY IS ENABLED. Disable before release (in env_debughistory.h).\n" ); - } -#endif - - ClearHistories(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDebugHistory::AddDebugHistoryLine( int iCategory, const char *szLine ) -{ - if ( iCategory < 0 || iCategory >= MAX_HISTORY_CATEGORIES ) - { - Warning("Attempted to add a debughistory line to category %d. Valid categories are %d to %d.\n", iCategory, 0, (MAX_HISTORY_CATEGORIES-1) ); - return; - } - - // Don't do debug history before the singleton is properly set up. - if ( !m_DebugLineEnd[iCategory] ) - return; - - const char *pszRemaining = szLine; - int iCharsToWrite = strlen( pszRemaining ) + 1; // Add 1 so that we copy the null terminator - - // Clip the line if it's too long. Wasteful doing it this way, but keeps code below nice & simple. - char szTmpBuffer[MAX_DEBUG_HISTORY_LINE_LENGTH]; - if ( iCharsToWrite > MAX_DEBUG_HISTORY_LINE_LENGTH) - { - memcpy( szTmpBuffer, szLine, sizeof(szTmpBuffer) ); - szTmpBuffer[MAX_DEBUG_HISTORY_LINE_LENGTH-1] = '\0'; - pszRemaining = szTmpBuffer; - iCharsToWrite = MAX_DEBUG_HISTORY_LINE_LENGTH; - } - - while ( iCharsToWrite ) - { - int iCharsLeftBeforeLoop = sizeof(m_DebugLines[iCategory]) - (m_DebugLineEnd[iCategory] - m_DebugLines[iCategory]); - - // Write into the buffer - int iWrote = MIN( iCharsToWrite, iCharsLeftBeforeLoop ); - memcpy( m_DebugLineEnd[iCategory], pszRemaining, iWrote ); - m_DebugLineEnd[iCategory] += iWrote; - pszRemaining += iWrote; - - // Did we loop? - if ( iWrote == iCharsLeftBeforeLoop ) - { - m_DebugLineEnd[iCategory] = m_DebugLines[iCategory]; - } - - iCharsToWrite -= iWrote; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDebugHistory::DumpDebugHistory( int iCategory ) -{ - if ( iCategory < 0 || iCategory >= MAX_HISTORY_CATEGORIES ) - { - Warning("Attempted to dump a history for category %d. Valid categories are %d to %d.\n", iCategory, 0, (MAX_HISTORY_CATEGORIES-1) ); - return; - } - - // Find the start of the oldest whole debug line. - const char *pszLine = m_DebugLineEnd[iCategory] + 1; - if ( (size_t)(pszLine - m_DebugLines[iCategory]) >= sizeof(m_DebugLines[iCategory]) ) - { - pszLine = m_DebugLines[iCategory]; - } - - // Are we at the start of a line? If there's a null terminator before us, then we're good to go. - while ( (!( pszLine == m_DebugLines[iCategory] && *(m_DebugLines[iCategory]+sizeof(m_DebugLines[iCategory])-1) == '\0' ) && - !( pszLine != m_DebugLines[iCategory] && *(pszLine-1) == '\0' )) - || *pszLine == '\0' ) - { - pszLine++; - - // Have we looped? - if ( (size_t)(pszLine - m_DebugLines[iCategory]) >= sizeof(m_DebugLines[iCategory]) ) - { - pszLine = m_DebugLines[iCategory]; - } - - if ( pszLine == m_DebugLineEnd[iCategory] ) - { - // We looped through the entire history, and found nothing. - Msg( "Debug History of Category %d is EMPTY\n", iCategory ); - return; - } - } - - // Now print everything up till the end - char szMsgBuffer[MAX_DEBUG_HISTORY_LINE_LENGTH]; - char *pszMsg = szMsgBuffer; - Msg( "Starting Debug History Dump of Category %d\n", iCategory ); - while ( pszLine != m_DebugLineEnd[iCategory] ) - { - *pszMsg = *pszLine; - if ( *pszLine == '\0' ) - { - if ( szMsgBuffer[0] != '\0' ) - { - // Found a full line, so print it - Msg( szMsgBuffer ); - } - - // Clear the buffer - pszMsg = szMsgBuffer; - *pszMsg = '\0'; - } - else - { - pszMsg++; - } - - pszLine++; - - // Have we looped? - if ( (size_t)(pszLine - m_DebugLines[iCategory]) >= sizeof(m_DebugLines[iCategory]) ) - { - pszLine = m_DebugLines[iCategory]; - } - } - Msg("Ended Debug History Dump of Category %d\n", iCategory ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDebugHistory::ClearHistories( void ) -{ - for ( int i = 0; i < MAX_HISTORY_CATEGORIES; i++ ) - { - memset( m_DebugLines[i], 0, sizeof(m_DebugLines[i]) ); - m_DebugLineEnd[i] = m_DebugLines[i]; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CDebugHistory::Save( ISave &save ) -{ - int iVersion = DEBUG_HISTORY_VERSION; - save.WriteInt( &iVersion ); - int iMaxCategorys = MAX_HISTORY_CATEGORIES; - save.WriteInt( &iMaxCategorys ); - for ( int iCategory = 0; iCategory < MAX_HISTORY_CATEGORIES; iCategory++ ) - { - int iEnd = m_DebugLineEnd[iCategory] - m_DebugLines[iCategory]; - save.WriteInt( &iEnd ); - save.WriteData( m_DebugLines[iCategory], MAX_DEBUG_HISTORY_LENGTH ); - } - - return BaseClass::Save(save); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CDebugHistory::Restore( IRestore &restore ) -{ - ClearHistories(); - - int iVersion = restore.ReadInt(); - - if ( iVersion >= DEBUG_HISTORY_FIRST_VERSIONED ) - { - int iMaxCategorys = restore.ReadInt(); - for ( int iCategory = 0; iCategory < MIN(iMaxCategorys,MAX_HISTORY_CATEGORIES); iCategory++ ) - { - int iEnd = restore.ReadInt(); - m_DebugLineEnd[iCategory] = m_DebugLines[iCategory] + iEnd; - restore.ReadData( m_DebugLines[iCategory], sizeof(m_DebugLines[iCategory]), 0 ); - } - } - else - { - int iMaxCategorys = iVersion; - for ( int iCategory = 0; iCategory < MIN(iMaxCategorys,MAX_HISTORY_CATEGORIES); iCategory++ ) - { - int iEnd = restore.ReadInt(); - m_DebugLineEnd[iCategory] = m_DebugLines[iCategory] + iEnd; - restore.ReadData( m_DebugLines[iCategory], sizeof(m_DebugLines[iCategory]), 0 ); - } - } - - return BaseClass::Restore(restore); -} - - -//----------------------------------------------------------------------------- -// Purpose: Singleton debug history. Created by first usage. -//----------------------------------------------------------------------------- -CDebugHistory *GetDebugHistory() -{ -#ifdef DISABLE_DEBUG_HISTORY - return NULL; -#endif - - if ( g_pGameRules && g_pGameRules->IsMultiplayer() ) - return NULL; - - if ( s_DebugHistory == NULL ) - { - CBaseEntity *pEnt = gEntList.FindEntityByClassname( NULL, "env_debughistory" ); - if ( pEnt ) - { - s_DebugHistory = dynamic_cast(pEnt); - } - else - { - s_DebugHistory = ( CDebugHistory * )CreateEntityByName( "env_debughistory" ); - if ( s_DebugHistory ) - { - s_DebugHistory->Spawn(); - } - } - } - - Assert( s_DebugHistory ); - return s_DebugHistory; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void AddDebugHistoryLine( int iCategory, const char *pszLine ) -{ -#ifdef DISABLE_DEBUG_HISTORY - return; -#else - if ( g_pGameRules && g_pGameRules->IsMultiplayer() ) - return; - - if ( !GetDebugHistory() ) - { - Warning("Failed to find or create an env_debughistory.\n" ); - return; - } - - GetDebugHistory()->AddDebugHistoryLine( iCategory, pszLine ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CC_DebugHistory_AddLine( const CCommand &args ) -{ - if ( args.ArgC() < 3 ) - { - Warning("Incorrect parameters. Format: \n"); - return; - } - - int iCategory = atoi(args[ 1 ]); - const char *pszLine = args[ 2 ]; - AddDebugHistoryLine( iCategory, pszLine ); -} -static ConCommand dbghist_addline( "dbghist_addline", CC_DebugHistory_AddLine, "Add a line to the debug history. Format: ", FCVAR_NONE ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CC_DebugHistory_Dump( const CCommand &args ) -{ - if ( args.ArgC() < 2 ) - { - Warning("Incorrect parameters. Format: \n"); - return; - } - - if ( GetDebugHistory() ) - { - int iCategory = atoi(args[ 1 ]); - GetDebugHistory()->DumpDebugHistory( iCategory ); - } -} - -static ConCommand dbghist_dump("dbghist_dump", CC_DebugHistory_Dump, - "Dump the debug history to the console. Format: \n" - " Categories:\n" - " 0: Entity I/O\n" - " 1: AI Decisions\n" - " 2: Scene Print\n" - " 3: Alyx Blind\n" - " 4: Log of damage done to player", - FCVAR_NONE ); - diff --git a/game/server/env_debughistory.h b/game/server/env_debughistory.h deleted file mode 100644 index 24576977e..000000000 --- a/game/server/env_debughistory.h +++ /dev/null @@ -1,35 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef ENV_DEBUGHISTORY_H -#define ENV_DEBUGHISTORY_H -#ifdef _WIN32 -#pragma once -#endif - -enum debughistorycategories_t -{ - HISTORY_ENTITY_IO, - HISTORY_AI_DECISIONS, - HISTORY_SCENE_PRINT, - HISTORY_ALYX_BLIND, // TEMP: until we find and fix this bug - HISTORY_PLAYER_DAMAGE, // record all damage done to the player - - // Add new categories here - - MAX_HISTORY_CATEGORIES, -}; - -#define DISABLE_DEBUG_HISTORY - -#if defined(DISABLE_DEBUG_HISTORY) -#define ADD_DEBUG_HISTORY( category, line ) ((void)0) -#else -#define ADD_DEBUG_HISTORY( category, line ) AddDebugHistoryLine( category, line ) -void AddDebugHistoryLine( int iCategory, const char *pszLine ); -#endif - -#endif // ENV_DEBUGHISTORY_H diff --git a/game/server/env_effectsscript.cpp b/game/server/env_effectsscript.cpp deleted file mode 100644 index 1fadfc1f4..000000000 --- a/game/server/env_effectsscript.cpp +++ /dev/null @@ -1,542 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "baseanimating.h" -#include "Sprite.h" -#include "SpriteTrail.h" -#include -#include "animation.h" -#include "eventlist.h" -#include "npcevent.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -enum EffectType -{ - EFFECT_TYPE_TRAIL = 1, - EFFECT_TYPE_SPRITE -}; - - -bool g_bUnget = false; -unsigned char *buffer; -char name[ 256 ]; -const char *currenttoken; -int tokencount; -char token[ 1204 ]; - -class CEffectScriptElement -{ -public: - - CEffectScriptElement(); - - char m_szEffectName[128]; - CHandle m_pTrail; - CHandle m_pSprite; - int m_iType; - int m_iRenderType; - - int m_iR; - int m_iG; - int m_iB; - int m_iA; - - char m_szAttachment[128]; - char m_szMaterial[128]; - - float m_flScale; - float m_flFadeTime; - float m_flTextureRes; - - bool m_bStopFollowOnKill; - - bool IsActive( void ) { return m_bActive; } - void Activate( void ) { m_bActive = true; } - void Deactivate( void ) { m_bActive = false; } -private: - - bool m_bActive; -}; - -CEffectScriptElement::CEffectScriptElement() -{ - m_pTrail = NULL; - m_pSprite = NULL; - m_iType = 0; - - Deactivate(); - m_iRenderType = kRenderTransAdd; - - m_iR = 255; - m_iG = 0; - m_iB = 0; - m_iA = 255; - - m_flScale = 1.0f; - m_flFadeTime = 1.0f; - m_flTextureRes = -1.0f; - m_bStopFollowOnKill = false; -} - - -//----------------------------------------------------------------------------- -// An entity which emits other entities at points -//----------------------------------------------------------------------------- -class CEnvEffectsScript : public CBaseAnimating -{ -public: - DECLARE_CLASS( CEnvEffectsScript, CBaseAnimating ); - DECLARE_DATADESC(); - - virtual void Precache(); - virtual void Spawn(); - virtual int UpdateTransmitState(); - - void InputSetSequence( inputdata_t &inputdata ); - void ParseScriptFile( void ); - void LoadFromBuffer( const char *scriptfile, const char *buffer ); - - virtual void Think( void ); - - void ParseNewEffect( void ); - - const char *GetScriptFile( void ) - { - return STRING( m_iszScriptName ); - } - - void HandleAnimEvent ( animevent_t *pEvent ); - void TrailEffectEvent( CEffectScriptElement *pEffect ); - void SpriteEffectEvent( CEffectScriptElement *pEffect ); - - CEffectScriptElement *GetScriptElementByName( const char *pName ); - -private: - - string_t m_iszScriptName; - - CUtlVector< CEffectScriptElement > m_ScriptElements; - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- - bool IsRootCommand( void ) - { - if ( !Q_stricmp( token, "effect" ) ) - return true; - - return false; - } -}; - -inline bool ParseToken( void ) -{ - if ( g_bUnget ) - { - g_bUnget = false; - return true; - } - - currenttoken = engine->ParseFile( currenttoken, token, sizeof( token ) ); - tokencount++; - return currenttoken != NULL ? true : false; -} - -inline void Unget() -{ - g_bUnget = true; -} - -inline bool TokenWaiting( void ) -{ - - const char *p = currenttoken; - while ( *p && *p!='\n') - { - // Special handler for // comment blocks - if ( *p == '/' && *(p+1) == '/' ) - return false; - - if ( !isspace( *p ) || isalnum( *p ) ) - return true; - - p++; - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Save/load -//----------------------------------------------------------------------------- -BEGIN_DATADESC( CEnvEffectsScript ) - // Inputs - DEFINE_INPUTFUNC( FIELD_STRING, "SetSequence", InputSetSequence ), - DEFINE_KEYFIELD( m_iszScriptName, FIELD_STRING, "scriptfile" ), - // DEFINE_FIELD( m_ScriptElements, CUtlVector < CEffectScriptElement > ), - - DEFINE_FUNCTION( Think ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( env_effectscript, CEnvEffectsScript ); - -//----------------------------------------------------------------------------- -// Should we transmit it to the client? -//----------------------------------------------------------------------------- -int CEnvEffectsScript::UpdateTransmitState() -{ - return SetTransmitState( FL_EDICT_ALWAYS ); -} - -//----------------------------------------------------------------------------- -// Precache -//----------------------------------------------------------------------------- -void CEnvEffectsScript::Precache() -{ - BaseClass::Precache(); - PrecacheModel( STRING( GetModelName() ) ); - - if ( m_iszScriptName != NULL_STRING ) - ParseScriptFile(); - else - Warning( "CEnvEffectsScript with no script!\n" ); -} - -//----------------------------------------------------------------------------- -// Spawn -//----------------------------------------------------------------------------- -void CEnvEffectsScript::Spawn() -{ - Precache(); - BaseClass::Spawn(); - - // We need a model for its animation sequences even though we don't render it - SetModel( STRING( GetModelName() ) ); - - AddEffects( EF_NODRAW ); - - SetThink( &CEnvEffectsScript::Think ); - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -void CEnvEffectsScript::Think( void ) -{ - StudioFrameAdvance(); - DispatchAnimEvents( this ); - - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -void CEnvEffectsScript::TrailEffectEvent( CEffectScriptElement *pEffect ) -{ - if ( pEffect->IsActive() == false ) - { - //Only one type of this effect active at a time. - if ( pEffect->m_pTrail == NULL ) - { - pEffect->m_pTrail = CSpriteTrail::SpriteTrailCreate( pEffect->m_szMaterial, GetAbsOrigin(), true ); - pEffect->m_pTrail->FollowEntity( this ); - pEffect->m_pTrail->SetTransparency( pEffect->m_iRenderType, pEffect->m_iR, pEffect->m_iG, pEffect->m_iB, pEffect->m_iA, kRenderFxNone ); - pEffect->m_pTrail->SetStartWidth( pEffect->m_flScale ); - if ( pEffect->m_flTextureRes < 0.0f ) - { - pEffect->m_pTrail->SetTextureResolution( 1.0f / ( 16.0f * pEffect->m_flScale ) ); - } - else - { - pEffect->m_pTrail->SetTextureResolution( pEffect->m_flTextureRes ); - } - pEffect->m_pTrail->SetLifeTime( pEffect->m_flFadeTime ); - pEffect->m_pTrail->TurnOn(); - pEffect->m_pTrail->SetAttachment( this, LookupAttachment( pEffect->m_szAttachment ) ); - - pEffect->Activate(); - } - } -} - -void CEnvEffectsScript::SpriteEffectEvent( CEffectScriptElement *pEffect ) -{ - if ( pEffect->IsActive() == false ) - { - //Only one type of this effect active at a time. - if ( pEffect->m_pSprite == NULL ) - { - pEffect->m_pSprite = CSprite::SpriteCreate( pEffect->m_szMaterial, GetAbsOrigin(), true ); - pEffect->m_pSprite->FollowEntity( this ); - pEffect->m_pSprite->SetTransparency( pEffect->m_iRenderType, pEffect->m_iR, pEffect->m_iG, pEffect->m_iB, pEffect->m_iA, kRenderFxNone ); - pEffect->m_pSprite->SetScale( pEffect->m_flScale ); - pEffect->m_pSprite->TurnOn(); - pEffect->m_pSprite->SetAttachment( this, LookupAttachment( pEffect->m_szAttachment ) ); - - pEffect->Activate(); - } - } -} - -void CEnvEffectsScript::HandleAnimEvent ( animevent_t *pEvent ) -{ - if ( pEvent->event == AE_START_SCRIPTED_EFFECT ) - { - CEffectScriptElement *pCurrent = GetScriptElementByName( pEvent->options ); - - if ( pCurrent ) - { - if ( pCurrent->m_iType == EFFECT_TYPE_TRAIL ) - TrailEffectEvent( pCurrent ); - else if ( pCurrent->m_iType == EFFECT_TYPE_SPRITE ) - SpriteEffectEvent( pCurrent ); - } - - return; - } - - if ( pEvent->event == AE_STOP_SCRIPTED_EFFECT ) - { - CEffectScriptElement *pCurrent = GetScriptElementByName( pEvent->options ); - - if ( pCurrent && pCurrent->IsActive() ) - { - pCurrent->Deactivate(); - - if ( pCurrent->m_iType == EFFECT_TYPE_TRAIL ) - { - if ( pCurrent->m_bStopFollowOnKill == true ) - { - Vector vOrigin; - GetAttachment( pCurrent->m_pTrail->m_nAttachment, vOrigin ); - - pCurrent->m_pTrail->StopFollowingEntity(); - - pCurrent->m_pTrail->m_hAttachedToEntity = NULL; - pCurrent->m_pTrail->m_nAttachment = 0; - - pCurrent->m_pTrail->SetAbsOrigin( vOrigin); - } - - pCurrent->m_pTrail->FadeAndDie( pCurrent->m_flFadeTime ); - pCurrent->m_pTrail = NULL; - } - - else if ( pCurrent->m_iType == EFFECT_TYPE_SPRITE ) - { - if ( pCurrent->m_bStopFollowOnKill == true ) - { - Vector vOrigin; - GetAttachment( pCurrent->m_pSprite->m_nAttachment, vOrigin ); - - pCurrent->m_pSprite->StopFollowingEntity(); - - pCurrent->m_pSprite->m_hAttachedToEntity = NULL; - pCurrent->m_pSprite->m_nAttachment = 0; - - pCurrent->m_pSprite->SetAbsOrigin( vOrigin); - } - - pCurrent->m_pSprite->FadeAndDie( pCurrent->m_flFadeTime ); - pCurrent->m_pSprite = NULL; - } - } - return; - } - - BaseClass::HandleAnimEvent( pEvent ); -} -//----------------------------------------------------------------------------- -// Purpose: Input that sets the sequence of the entity -//----------------------------------------------------------------------------- -void CEnvEffectsScript::InputSetSequence( inputdata_t &inputdata ) -{ - if ( inputdata.value.StringID() != NULL_STRING ) - { - int nSequence = LookupSequence( STRING( inputdata.value.StringID() ) ); - if ( nSequence != ACT_INVALID ) - { - SetSequence( nSequence ); - ResetSequenceInfo(); - SetCycle( 0.0f ); - m_flPlaybackRate = 1.0f; - } - } -} - -void CEnvEffectsScript::ParseScriptFile( void ) -{ - int length = 0; - m_ScriptElements.RemoveAll(); - const char *pScriptName = GetScriptFile(); - - //Reset everything. - g_bUnget = false; - currenttoken = NULL; - tokencount = 0; - memset( token, 0, 1204 ); - memset( name, 0, 256 ); - - - unsigned char *buffer = (unsigned char *)UTIL_LoadFileForMe( pScriptName, &length ); - if ( length <= 0 || !buffer ) - { - DevMsg( 1, "CEnvEffectsScript: failed to load %s\n", pScriptName ); - return; - } - - currenttoken = (const char *)buffer; - LoadFromBuffer( pScriptName, (const char *)buffer ); - - UTIL_FreeFile( buffer ); -} - -void CEnvEffectsScript::LoadFromBuffer( const char *scriptfile, const char *buffer ) -{ - while ( 1 ) - { - ParseToken(); - - if ( !token[0] ) - { - break; - } - - if ( !Q_stricmp( token, "effect" ) ) - { - ParseNewEffect(); - } - else - { - Warning( "CEnvEffectsScript: Unknown entry type '%s'\n", token ); - break; - } - } -} - -void CEnvEffectsScript::ParseNewEffect( void ) -{ - //Add a new effect to the list. - CEffectScriptElement NewElement; - - // Effect Group Name - ParseToken(); - Q_strncpy( NewElement.m_szEffectName, token, sizeof( NewElement.m_szEffectName ) ); - - while ( 1 ) - { - ParseToken(); - - // Oops, part of next definition - if( IsRootCommand() ) - { - Unget(); - break; - } - - if ( !Q_stricmp( token, "{" ) ) - { - while ( 1 ) - { - ParseToken(); - if ( !Q_stricmp( token, "}" ) ) - break; - - if ( !Q_stricmp( token, "type" ) ) - { - ParseToken(); - - if ( !Q_stricmp( token, "trail" ) ) - NewElement.m_iType = EFFECT_TYPE_TRAIL; - else if ( !Q_stricmp( token, "sprite" ) ) - NewElement.m_iType = EFFECT_TYPE_SPRITE; - - continue; - } - - if ( !Q_stricmp( token, "material" ) ) - { - ParseToken(); - Q_strncpy( NewElement.m_szMaterial, token, sizeof( NewElement.m_szMaterial ) ); - PrecacheModel( NewElement.m_szMaterial ); - - continue; - } - - if ( !Q_stricmp( token, "attachment" ) ) - { - ParseToken(); - Q_strncpy( NewElement.m_szAttachment, token, sizeof( NewElement.m_szAttachment ) ); - - continue; - } - - if ( !Q_stricmp( token, "color" ) ) - { - ParseToken(); - sscanf( token, "%i %i %i %i", &NewElement.m_iR, &NewElement.m_iG, &NewElement.m_iB, &NewElement.m_iA ); - - continue; - } - - if ( !Q_stricmp( token, "scale" ) ) - { - ParseToken(); - - NewElement.m_flScale = atof( token ); - continue; - } - - if ( !Q_stricmp( token, "texturescale" ) ) - { - ParseToken(); - - float flTextureScale = atof( token ); - NewElement.m_flTextureRes = (flTextureScale > 0.0f) ? 1.0f / flTextureScale : 0.0f; - continue; - } - - if ( !Q_stricmp( token, "fadetime" ) ) - { - ParseToken(); - - NewElement.m_flFadeTime = atof( token ); - continue; - } - - if ( !Q_stricmp( token, "stopfollowonkill" ) ) - { - ParseToken(); - - NewElement.m_bStopFollowOnKill = !!atoi( token ); - continue; - } - - } - break; - } - } - - m_ScriptElements.AddToTail( NewElement ); -} - -CEffectScriptElement *CEnvEffectsScript::GetScriptElementByName( const char *pName ) -{ - for ( int i = 0; i < m_ScriptElements.Count(); i++ ) - { - CEffectScriptElement *pCurrent = &m_ScriptElements.Element( i ); - - if ( pCurrent && !Q_stricmp( pCurrent->m_szEffectName, pName ) ) - { - return pCurrent; - } - } - - return NULL; -} diff --git a/game/server/env_entity_maker.cpp b/game/server/env_entity_maker.cpp deleted file mode 100644 index 3eda56e61..000000000 --- a/game/server/env_entity_maker.cpp +++ /dev/null @@ -1,366 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include "cbase.h" -#include "entityoutput.h" -#include "TemplateEntities.h" -#include "point_template.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SF_ENTMAKER_AUTOSPAWN 0x0001 -#define SF_ENTMAKER_WAITFORDESTRUCTION 0x0002 -#define SF_ENTMAKER_IGNOREFACING 0x0004 -#define SF_ENTMAKER_CHECK_FOR_SPACE 0x0008 -#define SF_ENTMAKER_CHECK_PLAYER_LOOKING 0x0010 - - -//----------------------------------------------------------------------------- -// Purpose: An entity that mapmakers can use to ensure there's a required entity never runs out. -// i.e. physics cannisters that need to be used. -//----------------------------------------------------------------------------- -class CEnvEntityMaker : public CPointEntity -{ - DECLARE_CLASS( CEnvEntityMaker, CPointEntity ); -public: - DECLARE_DATADESC(); - - virtual void Spawn( void ); - virtual void Activate( void ); - - void SpawnEntity( Vector vecAlternateOrigin = vec3_invalid, QAngle vecAlternateAngles = vec3_angle ); - void CheckSpawnThink( void ); - void InputForceSpawn( inputdata_t &inputdata ); - void InputForceSpawnAtEntityOrigin( inputdata_t &inputdata ); - -private: - - CPointTemplate *FindTemplate(); - - bool HasRoomToSpawn(); - bool IsPlayerLooking(); - - Vector m_vecEntityMins; - Vector m_vecEntityMaxs; - EHANDLE m_hCurrentInstance; - EHANDLE m_hCurrentBlocker; // Last entity that blocked us spawning something - Vector m_vecBlockerOrigin; - - // Movement after spawn - QAngle m_angPostSpawnDirection; - float m_flPostSpawnDirectionVariance; - float m_flPostSpawnSpeed; - bool m_bPostSpawnUseAngles; - - string_t m_iszTemplate; - - COutputEvent m_pOutputOnSpawned; - COutputEvent m_pOutputOnFailedSpawn; -}; - -BEGIN_DATADESC( CEnvEntityMaker ) - // DEFINE_FIELD( m_vecEntityMins, FIELD_VECTOR ), - // DEFINE_FIELD( m_vecEntityMaxs, FIELD_VECTOR ), - DEFINE_FIELD( m_hCurrentInstance, FIELD_EHANDLE ), - DEFINE_FIELD( m_hCurrentBlocker, FIELD_EHANDLE ), - DEFINE_FIELD( m_vecBlockerOrigin, FIELD_VECTOR ), - DEFINE_KEYFIELD( m_iszTemplate, FIELD_STRING, "EntityTemplate" ), - DEFINE_KEYFIELD( m_angPostSpawnDirection, FIELD_VECTOR, "PostSpawnDirection" ), - DEFINE_KEYFIELD( m_flPostSpawnDirectionVariance, FIELD_FLOAT, "PostSpawnDirectionVariance" ), - DEFINE_KEYFIELD( m_flPostSpawnSpeed, FIELD_FLOAT, "PostSpawnSpeed" ), - DEFINE_KEYFIELD( m_bPostSpawnUseAngles, FIELD_BOOLEAN, "PostSpawnInheritAngles" ), - - // Outputs - DEFINE_OUTPUT( m_pOutputOnSpawned, "OnEntitySpawned" ), - DEFINE_OUTPUT( m_pOutputOnFailedSpawn, "OnEntityFailedSpawn" ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "ForceSpawn", InputForceSpawn ), - DEFINE_INPUTFUNC( FIELD_STRING, "ForceSpawnAtEntityOrigin", InputForceSpawnAtEntityOrigin ), - - // Functions - DEFINE_THINKFUNC( CheckSpawnThink ), -END_DATADESC() - -LINK_ENTITY_TO_CLASS( env_entity_maker, CEnvEntityMaker ); - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvEntityMaker::Spawn( void ) -{ - m_vecEntityMins = vec3_origin; - m_vecEntityMaxs = vec3_origin; - m_hCurrentInstance = NULL; - m_hCurrentBlocker = NULL; - m_vecBlockerOrigin = vec3_origin; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvEntityMaker::Activate( void ) -{ - BaseClass::Activate(); - - // check for valid template - if ( m_iszTemplate == NULL_STRING ) - { - Warning( "env_entity_maker %s has no template entity!\n", GetEntityName().ToCStr() ); - UTIL_Remove( this ); - return; - } - - // Spawn an instance - if ( m_spawnflags & SF_ENTMAKER_AUTOSPAWN ) - { - SpawnEntity(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CPointTemplate *CEnvEntityMaker::FindTemplate() -{ - // Find our point_template - CPointTemplate *pTemplate = dynamic_cast(gEntList.FindEntityByName( NULL, STRING(m_iszTemplate) )); - if ( !pTemplate ) - { - Warning( "env_entity_maker %s failed to find template %s.\n", GetEntityName().ToCStr(), STRING(m_iszTemplate) ); - } - - return pTemplate; -} - - -//----------------------------------------------------------------------------- -// Purpose: Spawn an instance of the entity -//----------------------------------------------------------------------------- -void CEnvEntityMaker::SpawnEntity( Vector vecAlternateOrigin, QAngle vecAlternateAngles ) -{ - CPointTemplate *pTemplate = FindTemplate(); - if (!pTemplate) - return; - - // Spawn our template - Vector vecSpawnOrigin = GetAbsOrigin(); - QAngle vecSpawnAngles = GetAbsAngles(); - - if( vecAlternateOrigin != vec3_invalid ) - { - // We have a valid alternate origin and angles. Use those instead - // of spawning the items at my own origin and angles. - vecSpawnOrigin = vecAlternateOrigin; - vecSpawnAngles = vecAlternateAngles; - } - - CUtlVector hNewEntities; - if ( !pTemplate->CreateInstance( vecSpawnOrigin, vecSpawnAngles, &hNewEntities ) ) - return; - - //Adrian: oops we couldn't spawn the entity (or entities) for some reason! - if ( hNewEntities.Count() == 0 ) - return; - - m_hCurrentInstance = hNewEntities[0]; - - // Assume it'll block us - m_hCurrentBlocker = m_hCurrentInstance; - m_vecBlockerOrigin = m_hCurrentBlocker->GetAbsOrigin(); - - // Store off the mins & maxs the first time we spawn - if ( m_vecEntityMins == vec3_origin ) - { - m_hCurrentInstance->CollisionProp()->WorldSpaceAABB( &m_vecEntityMins, &m_vecEntityMaxs ); - m_vecEntityMins -= m_hCurrentInstance->GetAbsOrigin(); - m_vecEntityMaxs -= m_hCurrentInstance->GetAbsOrigin(); - } - - // Fire our output - m_pOutputOnSpawned.FireOutput( this, this ); - - // Start thinking - if ( m_spawnflags & SF_ENTMAKER_AUTOSPAWN ) - { - SetThink( &CEnvEntityMaker::CheckSpawnThink ); - SetNextThink( gpGlobals->curtime + 0.5f ); - } - - // If we have a specified post spawn speed, apply it to all spawned entities - if ( m_flPostSpawnSpeed ) - { - for ( int i = 0; i < hNewEntities.Count(); i++ ) - { - CBaseEntity *pEntity = hNewEntities[i]; - if ( pEntity->GetMoveType() == MOVETYPE_NONE ) - continue; - - // Calculate a velocity for this entity - Vector vForward,vRight,vUp; - QAngle angSpawnDir( m_angPostSpawnDirection ); - if ( m_bPostSpawnUseAngles ) - { - if ( GetParent() ) - { - angSpawnDir += GetParent()->GetAbsAngles(); - } - else - { - angSpawnDir += GetAbsAngles(); - } - } - AngleVectors( angSpawnDir, &vForward, &vRight, &vUp ); - Vector vecShootDir = vForward; - vecShootDir += vRight * random->RandomFloat(-1, 1) * m_flPostSpawnDirectionVariance; - vecShootDir += vForward * random->RandomFloat(-1, 1) * m_flPostSpawnDirectionVariance; - vecShootDir += vUp * random->RandomFloat(-1, 1) * m_flPostSpawnDirectionVariance; - VectorNormalize( vecShootDir ); - vecShootDir *= m_flPostSpawnSpeed; - - // Apply it to the entity - IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject(); - if ( pPhysicsObject ) - { - pPhysicsObject->AddVelocity(&vecShootDir, NULL); - } - else - { - pEntity->SetAbsVelocity( vecShootDir ); - } - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns whether or not the template entities can fit if spawned. -// Input : pBlocker - Returns blocker unless NULL. -//----------------------------------------------------------------------------- -bool CEnvEntityMaker::HasRoomToSpawn() -{ - // Do we have a blocker from last time? - if ( m_hCurrentBlocker ) - { - // If it hasn't moved, abort immediately - if ( m_vecBlockerOrigin == m_hCurrentBlocker->GetAbsOrigin() ) - { - return false; - } - } - - // Check to see if there's enough room to spawn - trace_t tr; - UTIL_TraceHull( GetAbsOrigin(), GetAbsOrigin(), m_vecEntityMins, m_vecEntityMaxs, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - if ( tr.m_pEnt || tr.startsolid ) - { - // Store off our blocker to check later - m_hCurrentBlocker = tr.m_pEnt; - if ( m_hCurrentBlocker ) - { - m_vecBlockerOrigin = m_hCurrentBlocker->GetAbsOrigin(); - } - - return false; - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns true if the player is looking towards us. -//----------------------------------------------------------------------------- -bool CEnvEntityMaker::IsPlayerLooking() -{ - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - if ( pPlayer ) - { - // Only spawn if the player's looking away from me - Vector vLookDir = pPlayer->EyeDirection3D(); - Vector vTargetDir = GetAbsOrigin() - pPlayer->EyePosition(); - VectorNormalize( vTargetDir ); - - float fDotPr = DotProduct( vLookDir,vTargetDir ); - if ( fDotPr > 0 ) - return true; - } - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Check to see if we should spawn another instance -//----------------------------------------------------------------------------- -void CEnvEntityMaker::CheckSpawnThink( void ) -{ - SetNextThink( gpGlobals->curtime + 0.5f ); - - // Do we have an instance? - if ( m_hCurrentInstance ) - { - // If Wait-For-Destruction is set, abort immediately - if ( m_spawnflags & SF_ENTMAKER_WAITFORDESTRUCTION ) - return; - } - - // Check to see if there's enough room to spawn - if ( !HasRoomToSpawn() ) - return; - - // We're clear, now check to see if the player's looking - if ( !( HasSpawnFlags( SF_ENTMAKER_IGNOREFACING ) ) && IsPlayerLooking() ) - return; - - // Clear, no player watching, so spawn! - SpawnEntity(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Spawns the entities, checking for space if flagged to do so. -//----------------------------------------------------------------------------- -void CEnvEntityMaker::InputForceSpawn( inputdata_t &inputdata ) -{ - CPointTemplate *pTemplate = FindTemplate(); - if (!pTemplate) - return; - - if ( HasSpawnFlags( SF_ENTMAKER_CHECK_FOR_SPACE ) && !HasRoomToSpawn() ) - { - m_pOutputOnFailedSpawn.FireOutput( this, this ); - return; - } - - if ( HasSpawnFlags( SF_ENTMAKER_CHECK_PLAYER_LOOKING ) && IsPlayerLooking() ) - { - m_pOutputOnFailedSpawn.FireOutput( this, this ); - return; - } - - SpawnEntity(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CEnvEntityMaker::InputForceSpawnAtEntityOrigin( inputdata_t &inputdata ) -{ - CBaseEntity *pTargetEntity = gEntList.FindEntityByName( NULL, inputdata.value.String(), this, inputdata.pActivator, inputdata.pCaller ); - - if( pTargetEntity ) - { - SpawnEntity( pTargetEntity->GetAbsOrigin(), pTargetEntity->GetAbsAngles() ); - } -} diff --git a/game/server/env_particlescript.cpp b/game/server/env_particlescript.cpp deleted file mode 100644 index 34db3c453..000000000 --- a/game/server/env_particlescript.cpp +++ /dev/null @@ -1,193 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "baseanimating.h" -#include "SkyCamera.h" -#include "studio.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// HACK HACK: Must match cl_dll/cl_animevent.h!!!! -#define CL_EVENT_SPRITEGROUP_CREATE 6002 - -//----------------------------------------------------------------------------- -// An entity which emits other entities at points -//----------------------------------------------------------------------------- -class CEnvParticleScript : public CBaseAnimating -{ -public: - DECLARE_CLASS( CEnvParticleScript, CBaseAnimating ); - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - CEnvParticleScript(); - - virtual void Precache(); - virtual void Spawn(); - virtual void Activate(); - virtual int UpdateTransmitState(); - - void InputSetSequence( inputdata_t &inputdata ); - -private: - - void PrecacheAnimationEventMaterials(); - - CNetworkVar( float, m_flSequenceScale ); -}; - - -//----------------------------------------------------------------------------- -// Save/load -//----------------------------------------------------------------------------- -BEGIN_DATADESC( CEnvParticleScript ) - - DEFINE_FIELD( m_flSequenceScale, FIELD_FLOAT ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_STRING, "SetSequence", InputSetSequence ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( env_particlescript, CEnvParticleScript ); - - -//----------------------------------------------------------------------------- -// Datatable -//----------------------------------------------------------------------------- -IMPLEMENT_SERVERCLASS_ST( CEnvParticleScript, DT_EnvParticleScript ) - SendPropFloat(SENDINFO(m_flSequenceScale), 0, SPROP_NOSCALE), -END_SEND_TABLE() - - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CEnvParticleScript::CEnvParticleScript() -{ - UseClientSideAnimation(); -} - - -void CEnvParticleScript::PrecacheAnimationEventMaterials() -{ - CStudioHdr *hdr = GetModelPtr(); - if ( hdr ) - { - int numseq = hdr->GetNumSeq(); - for ( int i = 0; i < numseq; ++i ) - { - mstudioseqdesc_t& seqdesc = hdr->pSeqdesc( i ); - int ecount = seqdesc.numevents; - for ( int j = 0 ; j < ecount; ++j ) - { - const mstudioevent_t* event = seqdesc.pEvent( j ); - if ( event->event == CL_EVENT_SPRITEGROUP_CREATE ) - { - char pAttachmentName[256]; - char pSpriteName[256]; - int nArgs = sscanf( event->pszOptions(), "%255s %255s", pAttachmentName, pSpriteName ); - if ( nArgs == 2 ) - { - PrecacheMaterial( pSpriteName ); - } - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Precache -//----------------------------------------------------------------------------- -void CEnvParticleScript::Precache() -{ - BaseClass::Precache(); - PrecacheModel( STRING( GetModelName() ) ); - - // We need a model for its animation sequences even though we don't render it - SetModel( STRING( GetModelName() ) ); - - PrecacheAnimationEventMaterials(); -} - - -//----------------------------------------------------------------------------- -// Spawn -//----------------------------------------------------------------------------- -void CEnvParticleScript::Spawn() -{ - Precache(); - BaseClass::Spawn(); - AddEffects( EF_NOSHADOW ); - // We need a model for its animation sequences even though we don't render it - SetModel( STRING( GetModelName() ) ); -} - - -//----------------------------------------------------------------------------- -// Activate -//----------------------------------------------------------------------------- -void CEnvParticleScript::Activate() -{ - BaseClass::Activate(); - - DetectInSkybox(); - CSkyCamera *pCamera = GetEntitySkybox(); - if ( pCamera ) - { - float flSkyboxScale = pCamera->m_skyboxData.scale; - if ( flSkyboxScale == 0.0f ) - { - flSkyboxScale = 1.0f; - } - - m_flSequenceScale = flSkyboxScale; - } - else - { - m_flSequenceScale = 1.0f; - } - - m_flPlaybackRate = 1.0f; -} - -//----------------------------------------------------------------------------- -// Should we transmit it to the client? -//----------------------------------------------------------------------------- -int CEnvParticleScript::UpdateTransmitState() -{ - if ( IsEffectActive( EF_NODRAW ) ) - { - return SetTransmitState( FL_EDICT_DONTSEND ); - } - - if ( IsEFlagSet( EFL_IN_SKYBOX ) ) - { - return SetTransmitState( FL_EDICT_ALWAYS ); - } - - return SetTransmitState( FL_EDICT_PVSCHECK ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input that sets the sequence of the entity -//----------------------------------------------------------------------------- -void CEnvParticleScript::InputSetSequence( inputdata_t &inputdata ) -{ - if ( inputdata.value.StringID() != NULL_STRING ) - { - int nSequence = LookupSequence( STRING( inputdata.value.StringID() ) ); - if ( nSequence != ACT_INVALID ) - { - SetSequence( nSequence ); - } - } -} diff --git a/game/server/env_player_surface_trigger.cpp b/game/server/env_player_surface_trigger.cpp deleted file mode 100644 index b6446ad38..000000000 --- a/game/server/env_player_surface_trigger.cpp +++ /dev/null @@ -1,135 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "decals.h" -#include "env_player_surface_trigger.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -LINK_ENTITY_TO_CLASS( env_player_surface_trigger, CEnvPlayerSurfaceTrigger ); - -BEGIN_DATADESC( CEnvPlayerSurfaceTrigger ) - DEFINE_KEYFIELD( m_iTargetGameMaterial, FIELD_INTEGER, "gamematerial" ), - DEFINE_FIELD( m_iCurrentGameMaterial, FIELD_INTEGER ), - DEFINE_FIELD( m_bDisabled, FIELD_BOOLEAN ), - - DEFINE_THINKFUNC( UpdateMaterialThink ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - - // Outputs - DEFINE_OUTPUT(m_OnSurfaceChangedToTarget, "OnSurfaceChangedToTarget"), - DEFINE_OUTPUT(m_OnSurfaceChangedFromTarget, "OnSurfaceChangedFromTarget"), -END_DATADESC() - -// Global list of surface triggers -CUtlVector< CHandle > g_PlayerSurfaceTriggers; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CEnvPlayerSurfaceTrigger::~CEnvPlayerSurfaceTrigger( void ) -{ - g_PlayerSurfaceTriggers.FindAndRemove( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvPlayerSurfaceTrigger::Spawn( void ) -{ - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NONE ); - - m_iCurrentGameMaterial = 0; - m_bDisabled = false; - - g_PlayerSurfaceTriggers.AddToTail( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvPlayerSurfaceTrigger::OnRestore( void ) -{ - BaseClass::OnRestore(); - - g_PlayerSurfaceTriggers.AddToTail( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvPlayerSurfaceTrigger::SetPlayerSurface( CBasePlayer *pPlayer, char gameMaterial ) -{ - // Ignore players in the air (stops bunny hoppers escaping triggers) - if ( gameMaterial == 0 ) - return; - - // Loop through the surface triggers and tell them all about the change - int iCount = g_PlayerSurfaceTriggers.Count(); - for ( int i = 0; i < iCount; i++ ) - { - g_PlayerSurfaceTriggers[i]->PlayerSurfaceChanged( pPlayer, gameMaterial ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvPlayerSurfaceTrigger::PlayerSurfaceChanged( CBasePlayer *pPlayer, char gameMaterial ) -{ - if ( m_bDisabled ) - return; - - // Fire the output if we've changed, but only if it involves the target material - if ( gameMaterial != (char)m_iCurrentGameMaterial && - ( gameMaterial == m_iTargetGameMaterial || m_iCurrentGameMaterial == m_iTargetGameMaterial ) ) - { - DevMsg( 2, "Player changed material to %d (was %d)\n", gameMaterial, m_iCurrentGameMaterial ); - - m_iCurrentGameMaterial = (int)gameMaterial; - - SetThink( &CEnvPlayerSurfaceTrigger::UpdateMaterialThink ); - SetNextThink( gpGlobals->curtime ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Think function to fire outputs. Done this way so that sv_alternate ticks -// doesn't allow multiple surface changes in the same tick to fire outputs. -//----------------------------------------------------------------------------- -void CEnvPlayerSurfaceTrigger::UpdateMaterialThink( void ) -{ - if ( m_iCurrentGameMaterial == m_iTargetGameMaterial ) - { - m_OnSurfaceChangedToTarget.FireOutput( NULL, this ); - } - else - { - m_OnSurfaceChangedFromTarget.FireOutput( NULL, this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvPlayerSurfaceTrigger::InputDisable( inputdata_t &inputdata ) -{ - m_bDisabled = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvPlayerSurfaceTrigger::InputEnable( inputdata_t &inputdata ) -{ - m_bDisabled = false; -} diff --git a/game/server/env_player_surface_trigger.h b/game/server/env_player_surface_trigger.h deleted file mode 100644 index d92d94aa7..000000000 --- a/game/server/env_player_surface_trigger.h +++ /dev/null @@ -1,49 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ENV_PLAYER_SURFACE_TRIGGER_H -#define ENV_PLAYER_SURFACE_TRIGGER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "baseentity.h" -#include "entityoutput.h" - -//----------------------------------------------------------------------------- -// Purpose: Entity that fires outputs whenever the player stands on a different surface -//----------------------------------------------------------------------------- -class CEnvPlayerSurfaceTrigger : public CPointEntity -{ - DECLARE_CLASS( CEnvPlayerSurfaceTrigger, CPointEntity ); -public: - DECLARE_DATADESC(); - - ~CEnvPlayerSurfaceTrigger( void ); - void Spawn( void ); - void OnRestore( void ); - - // Main interface to all surface triggers - static void SetPlayerSurface( CBasePlayer *pPlayer, char gameMaterial ); - - void UpdateMaterialThink( void ); - -private: - void PlayerSurfaceChanged( CBasePlayer *pPlayer, char gameMaterial ); - void InputDisable( inputdata_t &inputdata ); - void InputEnable( inputdata_t &inputdata ); - -private: - int m_iTargetGameMaterial; - int m_iCurrentGameMaterial; - bool m_bDisabled; - - // Outputs - COutputEvent m_OnSurfaceChangedToTarget; - COutputEvent m_OnSurfaceChangedFromTarget; -}; - -#endif // ENV_PLAYER_SURFACE_TRIGGER_H diff --git a/game/server/env_projectedtexture.cpp b/game/server/env_projectedtexture.cpp deleted file mode 100644 index c507d886d..000000000 --- a/game/server/env_projectedtexture.cpp +++ /dev/null @@ -1,270 +0,0 @@ -//====== Copyright 1996-2003, Valve Corporation, All rights reserved. ======= -// -// Purpose: Entity to control screen overlays on a player -// -//============================================================================= - -#include "cbase.h" -#include "shareddefs.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define ENV_PROJECTEDTEXTURE_STARTON (1<<0) - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CEnvProjectedTexture : public CPointEntity -{ - DECLARE_CLASS( CEnvProjectedTexture, CPointEntity ); -public: - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - CEnvProjectedTexture(); - bool KeyValue( const char *szKeyName, const char *szValue ); - - // Always transmit to clients - virtual int UpdateTransmitState(); - virtual void Activate( void ); - - void InputTurnOn( inputdata_t &inputdata ); - void InputTurnOff( inputdata_t &inputdata ); - void InputSetFOV( inputdata_t &inputdata ); - void InputSetTarget( inputdata_t &inputdata ); - void InputSetCameraSpace( inputdata_t &inputdata ); - void InputSetLightOnlyTarget( inputdata_t &inputdata ); - void InputSetLightWorld( inputdata_t &inputdata ); - void InputSetEnableShadows( inputdata_t &inputdata ); -// void InputSetLightColor( inputdata_t &inputdata ); - void InputSetSpotlightTexture( inputdata_t &inputdata ); - void InputSetAmbient( inputdata_t &inputdata ); - - void InitialThink( void ); - - CNetworkHandle( CBaseEntity, m_hTargetEntity ); - -private: - - CNetworkVar( bool, m_bState ); - CNetworkVar( float, m_flLightFOV ); - CNetworkVar( bool, m_bEnableShadows ); - CNetworkVar( bool, m_bLightOnlyTarget ); - CNetworkVar( bool, m_bLightWorld ); - CNetworkVar( bool, m_bCameraSpace ); - CNetworkVector( m_LinearFloatLightColor ); - CNetworkVar( float, m_flAmbient ); - CNetworkString( m_SpotlightTextureName, MAX_PATH ); - CNetworkVar( int, m_nSpotlightTextureFrame ); - CNetworkVar( float, m_flNearZ ); - CNetworkVar( float, m_flFarZ ); - CNetworkVar( int, m_nShadowQuality ); -}; - -LINK_ENTITY_TO_CLASS( env_projectedtexture, CEnvProjectedTexture ); - -BEGIN_DATADESC( CEnvProjectedTexture ) - DEFINE_FIELD( m_hTargetEntity, FIELD_EHANDLE ), - DEFINE_FIELD( m_bState, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_flLightFOV, FIELD_FLOAT, "lightfov" ), - DEFINE_KEYFIELD( m_bEnableShadows, FIELD_BOOLEAN, "enableshadows" ), - DEFINE_KEYFIELD( m_bLightOnlyTarget, FIELD_BOOLEAN, "lightonlytarget" ), - DEFINE_KEYFIELD( m_bLightWorld, FIELD_BOOLEAN, "lightworld" ), - DEFINE_KEYFIELD( m_bCameraSpace, FIELD_BOOLEAN, "cameraspace" ), - DEFINE_KEYFIELD( m_flAmbient, FIELD_FLOAT, "ambient" ), - DEFINE_AUTO_ARRAY_KEYFIELD( m_SpotlightTextureName, FIELD_CHARACTER, "texturename" ), - DEFINE_KEYFIELD( m_nSpotlightTextureFrame, FIELD_INTEGER, "textureframe" ), - DEFINE_KEYFIELD( m_flNearZ, FIELD_FLOAT, "nearz" ), - DEFINE_KEYFIELD( m_flFarZ, FIELD_FLOAT, "farz" ), - DEFINE_KEYFIELD( m_nShadowQuality, FIELD_INTEGER, "shadowquality" ), - DEFINE_FIELD( m_LinearFloatLightColor, FIELD_VECTOR ), - - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "FOV", InputSetFOV ), - DEFINE_INPUTFUNC( FIELD_EHANDLE, "Target", InputSetTarget ), - DEFINE_INPUTFUNC( FIELD_BOOLEAN, "CameraSpace", InputSetCameraSpace ), - DEFINE_INPUTFUNC( FIELD_BOOLEAN, "LightOnlyTarget", InputSetLightOnlyTarget ), - DEFINE_INPUTFUNC( FIELD_BOOLEAN, "LightWorld", InputSetLightWorld ), - DEFINE_INPUTFUNC( FIELD_BOOLEAN, "EnableShadows", InputSetEnableShadows ), - // this is broken . . need to be able to set color and intensity like light_dynamic -// DEFINE_INPUTFUNC( FIELD_COLOR32, "LightColor", InputSetLightColor ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "Ambient", InputSetAmbient ), - DEFINE_INPUTFUNC( FIELD_STRING, "SpotlightTexture", InputSetSpotlightTexture ), - DEFINE_THINKFUNC( InitialThink ), -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CEnvProjectedTexture, DT_EnvProjectedTexture ) - SendPropEHandle( SENDINFO( m_hTargetEntity ) ), - SendPropBool( SENDINFO( m_bState ) ), - SendPropFloat( SENDINFO( m_flLightFOV ) ), - SendPropBool( SENDINFO( m_bEnableShadows ) ), - SendPropBool( SENDINFO( m_bLightOnlyTarget ) ), - SendPropBool( SENDINFO( m_bLightWorld ) ), - SendPropBool( SENDINFO( m_bCameraSpace ) ), - SendPropVector( SENDINFO( m_LinearFloatLightColor ) ), - SendPropFloat( SENDINFO( m_flAmbient ) ), - SendPropString( SENDINFO( m_SpotlightTextureName ) ), - SendPropInt( SENDINFO( m_nSpotlightTextureFrame ) ), - SendPropFloat( SENDINFO( m_flNearZ ), 16, SPROP_ROUNDDOWN, 0.0f, 500.0f ), - SendPropFloat( SENDINFO( m_flFarZ ), 18, SPROP_ROUNDDOWN, 0.0f, 1500.0f ), - SendPropInt( SENDINFO( m_nShadowQuality ), 1, SPROP_UNSIGNED ), // Just one bit for now -END_SEND_TABLE() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CEnvProjectedTexture::CEnvProjectedTexture( void ) -{ - m_bState = true; - m_flLightFOV = 45.0f; - m_bEnableShadows = false; - m_bLightOnlyTarget = false; - m_bLightWorld = true; - m_bCameraSpace = false; - -// if ( g_pHardwareConfig->SupportsBorderColor() ) -#if defined( _X360 ) - Q_strcpy( m_SpotlightTextureName.GetForModify(), "effects/flashlight_border" ); -#else - Q_strcpy( m_SpotlightTextureName.GetForModify(), "effects/flashlight001" ); -#endif - - m_nSpotlightTextureFrame = 0; - m_LinearFloatLightColor.Init( 1.0f, 1.0f, 1.0f ); - m_flAmbient = 0.0f; - m_flNearZ = 4.0f; - m_flFarZ = 750.0f; - m_nShadowQuality = 0; -} - -void UTIL_ColorStringToLinearFloatColor( Vector &color, const char *pString ) -{ - float tmp[4]; - UTIL_StringToFloatArray( tmp, 4, pString ); - if( tmp[3] <= 0.0f ) - { - tmp[3] = 255.0f; - } - tmp[3] *= ( 1.0f / 255.0f ); - color.x = GammaToLinear( tmp[0] * ( 1.0f / 255.0f ) ) * tmp[3]; - color.y = GammaToLinear( tmp[1] * ( 1.0f / 255.0f ) ) * tmp[3]; - color.z = GammaToLinear( tmp[2] * ( 1.0f / 255.0f ) ) * tmp[3]; -} - -bool CEnvProjectedTexture::KeyValue( const char *szKeyName, const char *szValue ) -{ - if ( FStrEq( szKeyName, "lightcolor" ) ) - { - Vector tmp; - UTIL_ColorStringToLinearFloatColor( tmp, szValue ); - m_LinearFloatLightColor = tmp; - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } - - return true; -} - -void CEnvProjectedTexture::InputTurnOn( inputdata_t &inputdata ) -{ - m_bState = true; -} - -void CEnvProjectedTexture::InputTurnOff( inputdata_t &inputdata ) -{ - m_bState = false; -} - -void CEnvProjectedTexture::InputSetFOV( inputdata_t &inputdata ) -{ - m_flLightFOV = inputdata.value.Float(); -} - -void CEnvProjectedTexture::InputSetTarget( inputdata_t &inputdata ) -{ - m_hTargetEntity = inputdata.value.Entity(); -} - -void CEnvProjectedTexture::InputSetCameraSpace( inputdata_t &inputdata ) -{ - m_bCameraSpace = inputdata.value.Bool(); -} - -void CEnvProjectedTexture::InputSetLightOnlyTarget( inputdata_t &inputdata ) -{ - m_bLightOnlyTarget = inputdata.value.Bool(); -} - -void CEnvProjectedTexture::InputSetLightWorld( inputdata_t &inputdata ) -{ - m_bLightWorld = inputdata.value.Bool(); -} - -void CEnvProjectedTexture::InputSetEnableShadows( inputdata_t &inputdata ) -{ - m_bEnableShadows = inputdata.value.Bool(); -} - -//void CEnvProjectedTexture::InputSetLightColor( inputdata_t &inputdata ) -//{ -// m_cLightColor = inputdata.value.Color32(); -//} - -void CEnvProjectedTexture::InputSetAmbient( inputdata_t &inputdata ) -{ - m_flAmbient = inputdata.value.Float(); -} - -void CEnvProjectedTexture::InputSetSpotlightTexture( inputdata_t &inputdata ) -{ - Q_strcpy( m_SpotlightTextureName.GetForModify(), inputdata.value.String() ); -} - -void CEnvProjectedTexture::Activate( void ) -{ - if ( GetSpawnFlags() & ENV_PROJECTEDTEXTURE_STARTON ) - { - m_bState = true; - } - - SetThink( &CEnvProjectedTexture::InitialThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - BaseClass::Activate(); -} - -void CEnvProjectedTexture::InitialThink( void ) -{ - m_hTargetEntity = gEntList.FindEntityByName( NULL, m_target ); -} - -int CEnvProjectedTexture::UpdateTransmitState() -{ - return SetTransmitState( FL_EDICT_ALWAYS ); -} - - -// Console command for creating env_projectedtexture entities -void CC_CreateFlashlight( const CCommand &args ) -{ - CBasePlayer *pPlayer = UTIL_GetCommandClient(); - if( !pPlayer ) - return; - - QAngle angles = pPlayer->EyeAngles(); - Vector origin = pPlayer->EyePosition(); - - CEnvProjectedTexture *pFlashlight = dynamic_cast< CEnvProjectedTexture * >( CreateEntityByName("env_projectedtexture") ); - if( args.ArgC() > 1 ) - { - pFlashlight->SetName( AllocPooledString( args[1] ) ); - } - - pFlashlight->Teleport( &origin, &angles, NULL ); - -} -static ConCommand create_flashlight("create_flashlight", CC_CreateFlashlight, 0, FCVAR_CHEAT); diff --git a/game/server/env_screenoverlay.cpp b/game/server/env_screenoverlay.cpp deleted file mode 100644 index 1132c0939..000000000 --- a/game/server/env_screenoverlay.cpp +++ /dev/null @@ -1,292 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Entity to control screen overlays on a player -// -//=============================================================================// - -#include "cbase.h" -#include "shareddefs.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CEnvScreenOverlay : public CPointEntity -{ - DECLARE_CLASS( CEnvScreenOverlay, CPointEntity ); -public: - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - CEnvScreenOverlay(); - - // Always transmit to clients - virtual int UpdateTransmitState(); - virtual void Spawn( void ); - virtual void Precache( void ); - - void InputStartOverlay( inputdata_t &inputdata ); - void InputStopOverlay( inputdata_t &inputdata ); - void InputSwitchOverlay( inputdata_t &inputdata ); - - void SetActive( bool bActive ) { m_bIsActive = bActive; } - -protected: - CNetworkArray( string_t, m_iszOverlayNames, MAX_SCREEN_OVERLAYS ); - CNetworkArray( float, m_flOverlayTimes, MAX_SCREEN_OVERLAYS ); - CNetworkVar( float, m_flStartTime ); - CNetworkVar( int, m_iDesiredOverlay ); - CNetworkVar( bool, m_bIsActive ); -}; - -LINK_ENTITY_TO_CLASS( env_screenoverlay, CEnvScreenOverlay ); - -BEGIN_DATADESC( CEnvScreenOverlay ) - -// Silence, Classcheck! -// DEFINE_ARRAY( m_iszOverlayNames, FIELD_STRING, MAX_SCREEN_OVERLAYS ), -// DEFINE_ARRAY( m_flOverlayTimes, FIELD_FLOAT, MAX_SCREEN_OVERLAYS ), - - /* This causes a cannot apply offsetof when operator[] is overloaded error in GCC 4.2 - DEFINE_KEYFIELD( m_iszOverlayNames[0], FIELD_STRING, "OverlayName1" ), - DEFINE_KEYFIELD( m_iszOverlayNames[1], FIELD_STRING, "OverlayName2" ), - DEFINE_KEYFIELD( m_iszOverlayNames[2], FIELD_STRING, "OverlayName3" ), - DEFINE_KEYFIELD( m_iszOverlayNames[3], FIELD_STRING, "OverlayName4" ), - DEFINE_KEYFIELD( m_iszOverlayNames[4], FIELD_STRING, "OverlayName5" ), - DEFINE_KEYFIELD( m_iszOverlayNames[5], FIELD_STRING, "OverlayName6" ), - DEFINE_KEYFIELD( m_iszOverlayNames[6], FIELD_STRING, "OverlayName7" ), - DEFINE_KEYFIELD( m_iszOverlayNames[7], FIELD_STRING, "OverlayName8" ), - DEFINE_KEYFIELD( m_iszOverlayNames[8], FIELD_STRING, "OverlayName9" ), - DEFINE_KEYFIELD( m_iszOverlayNames[9], FIELD_STRING, "OverlayName10" ), - DEFINE_KEYFIELD( m_flOverlayTimes[0], FIELD_FLOAT, "OverlayTime1" ), - DEFINE_KEYFIELD( m_flOverlayTimes[1], FIELD_FLOAT, "OverlayTime2" ), - DEFINE_KEYFIELD( m_flOverlayTimes[2], FIELD_FLOAT, "OverlayTime3" ), - DEFINE_KEYFIELD( m_flOverlayTimes[3], FIELD_FLOAT, "OverlayTime4" ), - DEFINE_KEYFIELD( m_flOverlayTimes[4], FIELD_FLOAT, "OverlayTime5" ), - DEFINE_KEYFIELD( m_flOverlayTimes[5], FIELD_FLOAT, "OverlayTime6" ), - DEFINE_KEYFIELD( m_flOverlayTimes[6], FIELD_FLOAT, "OverlayTime7" ), - DEFINE_KEYFIELD( m_flOverlayTimes[7], FIELD_FLOAT, "OverlayTime8" ), - DEFINE_KEYFIELD( m_flOverlayTimes[8], FIELD_FLOAT, "OverlayTime9" ), - DEFINE_KEYFIELD( m_flOverlayTimes[9], FIELD_FLOAT, "OverlayTime10" ), - */ - - DEFINE_KEYFIELD_NETARRAY( m_iszOverlayNames, 0, FIELD_STRING, "OverlayName1" ), - DEFINE_KEYFIELD_NETARRAY( m_iszOverlayNames, 1, FIELD_STRING, "OverlayName2" ), - DEFINE_KEYFIELD_NETARRAY( m_iszOverlayNames, 2, FIELD_STRING, "OverlayName3" ), - DEFINE_KEYFIELD_NETARRAY( m_iszOverlayNames, 3, FIELD_STRING, "OverlayName4" ), - DEFINE_KEYFIELD_NETARRAY( m_iszOverlayNames, 4, FIELD_STRING, "OverlayName5" ), - DEFINE_KEYFIELD_NETARRAY( m_iszOverlayNames, 5, FIELD_STRING, "OverlayName6" ), - DEFINE_KEYFIELD_NETARRAY( m_iszOverlayNames, 6, FIELD_STRING, "OverlayName7" ), - DEFINE_KEYFIELD_NETARRAY( m_iszOverlayNames, 7, FIELD_STRING, "OverlayName8" ), - DEFINE_KEYFIELD_NETARRAY( m_iszOverlayNames, 8, FIELD_STRING, "OverlayName9" ), - DEFINE_KEYFIELD_NETARRAY( m_iszOverlayNames, 9, FIELD_STRING, "OverlayName10" ), - DEFINE_KEYFIELD_NETARRAY( m_flOverlayTimes, 0, FIELD_FLOAT, "OverlayTime1" ), - DEFINE_KEYFIELD_NETARRAY( m_flOverlayTimes, 1, FIELD_FLOAT, "OverlayTime2" ), - DEFINE_KEYFIELD_NETARRAY( m_flOverlayTimes, 2, FIELD_FLOAT, "OverlayTime3" ), - DEFINE_KEYFIELD_NETARRAY( m_flOverlayTimes, 3, FIELD_FLOAT, "OverlayTime4" ), - DEFINE_KEYFIELD_NETARRAY( m_flOverlayTimes, 4, FIELD_FLOAT, "OverlayTime5" ), - DEFINE_KEYFIELD_NETARRAY( m_flOverlayTimes, 5, FIELD_FLOAT, "OverlayTime6" ), - DEFINE_KEYFIELD_NETARRAY( m_flOverlayTimes, 6, FIELD_FLOAT, "OverlayTime7" ), - DEFINE_KEYFIELD_NETARRAY( m_flOverlayTimes, 7, FIELD_FLOAT, "OverlayTime8" ), - DEFINE_KEYFIELD_NETARRAY( m_flOverlayTimes, 8, FIELD_FLOAT, "OverlayTime9" ), - DEFINE_KEYFIELD_NETARRAY( m_flOverlayTimes, 9, FIELD_FLOAT, "OverlayTime10" ), - - // Class CEnvScreenOverlay: - DEFINE_FIELD( m_iDesiredOverlay, FIELD_INTEGER ), - DEFINE_FIELD( m_flStartTime, FIELD_TIME ), - DEFINE_FIELD( m_bIsActive, FIELD_BOOLEAN ), - - DEFINE_INPUTFUNC( FIELD_VOID, "StartOverlays", InputStartOverlay ), - DEFINE_INPUTFUNC( FIELD_VOID, "StopOverlays", InputStopOverlay ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SwitchOverlay", InputSwitchOverlay ), - -END_DATADESC() - -void SendProxy_String_tToString( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ) -{ - string_t *pString = (string_t*)pData; - pOut->m_pString = (char*)STRING( *pString ); -} - -IMPLEMENT_SERVERCLASS_ST( CEnvScreenOverlay, DT_EnvScreenOverlay ) - SendPropArray( SendPropString( SENDINFO_ARRAY( m_iszOverlayNames ), 0, SendProxy_String_tToString ), m_iszOverlayNames ), - SendPropArray( SendPropFloat( SENDINFO_ARRAY( m_flOverlayTimes ), 11, SPROP_ROUNDDOWN, -1.0f, 63.0f ), m_flOverlayTimes ), - SendPropFloat( SENDINFO( m_flStartTime ), 32, SPROP_NOSCALE ), - SendPropInt( SENDINFO( m_iDesiredOverlay ), 5 ), - SendPropBool( SENDINFO( m_bIsActive ) ), -END_SEND_TABLE() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CEnvScreenOverlay::CEnvScreenOverlay( void ) -{ - m_flStartTime = 0; - m_iDesiredOverlay = 0; - m_bIsActive = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvScreenOverlay::Spawn( void ) -{ - Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvScreenOverlay::Precache( void ) -{ - for ( int i = 0; i < 10; i++ ) - { - if ( m_iszOverlayNames[i] == NULL_STRING ) - continue; - - PrecacheMaterial( STRING( m_iszOverlayNames[i] ) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CEnvScreenOverlay::InputStartOverlay( inputdata_t &inputdata ) -{ - if ( m_iszOverlayNames[0] == NULL_STRING ) - { - Warning("env_screenoverlay %s has no overlays to display.\n", STRING(GetEntityName()) ); - return; - } - - m_flStartTime = gpGlobals->curtime; - m_bIsActive = true; - - // Turn off any other screen overlays out there - CBaseEntity *pEnt = NULL; - while ( (pEnt = gEntList.FindEntityByClassname( pEnt, "env_screenoverlay" )) != NULL ) - { - if ( pEnt != this ) - { - CEnvScreenOverlay *pOverlay = assert_cast(pEnt); - pOverlay->SetActive( false ); - } - } -} - -int CEnvScreenOverlay::UpdateTransmitState() -{ - return SetTransmitState( FL_EDICT_ALWAYS ); -} - - -void CEnvScreenOverlay::InputSwitchOverlay( inputdata_t &inputdata ) -{ - int iNewOverlay = inputdata.value.Int() - 1; - iNewOverlay = abs( iNewOverlay ); - - if ( m_iszOverlayNames[iNewOverlay] == NULL_STRING ) - { - Warning("env_screenoverlay %s has no overlays to display.\n", STRING(GetEntityName()) ); - return; - } - - m_iDesiredOverlay = iNewOverlay; - m_flStartTime = gpGlobals->curtime; -} - -void CEnvScreenOverlay::InputStopOverlay( inputdata_t &inputdata ) -{ - if ( m_iszOverlayNames[0] == NULL_STRING ) - { - Warning("env_screenoverlay %s has no overlays to display.\n", STRING(GetEntityName()) ); - return; - } - - m_flStartTime = -1; - m_bIsActive = false; -} - -// ==================================================================================== -// -// Screen-space effects -// -// ==================================================================================== - -class CEnvScreenEffect : public CPointEntity -{ - DECLARE_CLASS( CEnvScreenEffect, CPointEntity ); -public: - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - // We always want to be sent to the client - CEnvScreenEffect( void ) { AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); } - virtual int UpdateTransmitState( void ) { return SetTransmitState( FL_EDICT_ALWAYS ); } - virtual void Spawn( void ); - virtual void Precache( void ); - -private: - - void InputStartEffect( inputdata_t &inputdata ); - void InputStopEffect( inputdata_t &inputdata ); - - CNetworkVar( float, m_flDuration ); - CNetworkVar( int, m_nType ); -}; - -LINK_ENTITY_TO_CLASS( env_screeneffect, CEnvScreenEffect ); - -// CEnvScreenEffect -BEGIN_DATADESC( CEnvScreenEffect ) - DEFINE_FIELD( m_flDuration, FIELD_FLOAT ), - DEFINE_KEYFIELD( m_nType, FIELD_INTEGER, "type" ), - DEFINE_FIELD( m_flDuration, FIELD_FLOAT ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "StartEffect", InputStartEffect ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "StopEffect", InputStopEffect ), -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CEnvScreenEffect, DT_EnvScreenEffect ) - SendPropFloat( SENDINFO( m_flDuration ), 0, SPROP_NOSCALE ), - SendPropInt( SENDINFO( m_nType ), 32, SPROP_UNSIGNED ), -END_SEND_TABLE() - -void CEnvScreenEffect::Spawn( void ) -{ - Precache(); -} - -void CEnvScreenEffect::Precache( void ) -{ - PrecacheMaterial( "effects/stun" ); - PrecacheMaterial( "effects/introblur" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvScreenEffect::InputStartEffect( inputdata_t &inputdata ) -{ - // Take the duration as our value - m_flDuration = inputdata.value.Float(); - - EntityMessageBegin( this ); - WRITE_BYTE( 0 ); - MessageEnd(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvScreenEffect::InputStopEffect( inputdata_t &inputdata ) -{ - m_flDuration = inputdata.value.Float(); - - // Send the stop notification - EntityMessageBegin( this ); - WRITE_BYTE( 1 ); - MessageEnd(); -} diff --git a/game/server/env_texturetoggle.cpp b/game/server/env_texturetoggle.cpp deleted file mode 100644 index 89ac247fc..000000000 --- a/game/server/env_texturetoggle.cpp +++ /dev/null @@ -1,63 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CTextureToggle : public CPointEntity -{ -public: - DECLARE_CLASS( CTextureToggle, CPointEntity ); - - void InputIncrementBrushTexIndex( inputdata_t &inputdata ); - void InputSetBrushTexIndex( inputdata_t &inputdata ); - -private: - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( env_texturetoggle, CTextureToggle ); - -BEGIN_DATADESC( CTextureToggle ) - - DEFINE_INPUTFUNC( FIELD_VOID, "IncrementTextureIndex", InputIncrementBrushTexIndex ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetTextureIndex", InputSetBrushTexIndex ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CTextureToggle::InputIncrementBrushTexIndex( inputdata_t& inputdata ) -{ - CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, m_target ); - - while( pEntity ) - { - int iCurrentIndex = pEntity->GetTextureFrameIndex() + 1; - pEntity->SetTextureFrameIndex( iCurrentIndex ); - - pEntity = gEntList.FindEntityByName( pEntity, m_target ); - } -} - -void CTextureToggle::InputSetBrushTexIndex( inputdata_t& inputdata ) -{ - CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, m_target ); - - while( pEntity ) - { - int iData = inputdata.value.Int(); - - pEntity->SetTextureFrameIndex( iData ); - pEntity = gEntList.FindEntityByName( pEntity, m_target ); - } -} - diff --git a/game/server/env_tonemap_controller.cpp b/game/server/env_tonemap_controller.cpp deleted file mode 100644 index f0e47b355..000000000 --- a/game/server/env_tonemap_controller.cpp +++ /dev/null @@ -1,249 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#include "baseentity.h" -#include "entityoutput.h" -#include "convar.h" -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar mat_hdr_tonemapscale( "mat_hdr_tonemapscale", "1.0", FCVAR_CHEAT, "The HDR tonemap scale. 1 = Use autoexposure, 0 = eyes fully closed, 16 = eyes wide open." ); - -// 0 - eyes fully closed / fully black -// 1 - nominal -// 16 - eyes wide open / fully white - -//----------------------------------------------------------------------------- -// Purpose: Entity that controls player's tonemap -//----------------------------------------------------------------------------- -class CEnvTonemapController : public CPointEntity -{ - DECLARE_CLASS( CEnvTonemapController, CPointEntity ); -public: - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - void Spawn( void ); - int UpdateTransmitState( void ); - void UpdateTonemapScaleBlend( void ); - - // Inputs - void InputSetTonemapScale( inputdata_t &inputdata ); - void InputBlendTonemapScale( inputdata_t &inputdata ); - void InputSetTonemapRate( inputdata_t &inputdata ); - void InputSetAutoExposureMin( inputdata_t &inputdata ); - void InputSetAutoExposureMax( inputdata_t &inputdata ); - void InputUseDefaultAutoExposure( inputdata_t &inputdata ); - void InputSetBloomScale( inputdata_t &inputdata ); - void InputUseDefaultBloomScale( inputdata_t &inputdata ); - void InputSetBloomScaleRange( inputdata_t &inputdata ); - -private: - float m_flBlendTonemapStart; // HDR Tonemap at the start of the blend - float m_flBlendTonemapEnd; // Target HDR Tonemap at the end of the blend - float m_flBlendEndTime; // Time at which the blend ends - float m_flBlendStartTime; // Time at which the blend started - - CNetworkVar( bool, m_bUseCustomAutoExposureMin ); - CNetworkVar( bool, m_bUseCustomAutoExposureMax ); - CNetworkVar( bool, m_bUseCustomBloomScale ); - CNetworkVar( float, m_flCustomAutoExposureMin ); - CNetworkVar( float, m_flCustomAutoExposureMax ); - CNetworkVar( float, m_flCustomBloomScale); - CNetworkVar( float, m_flCustomBloomScaleMinimum); -}; - -LINK_ENTITY_TO_CLASS( env_tonemap_controller, CEnvTonemapController ); - -BEGIN_DATADESC( CEnvTonemapController ) - DEFINE_FIELD( m_flBlendTonemapStart, FIELD_FLOAT ), - DEFINE_FIELD( m_flBlendTonemapEnd, FIELD_FLOAT ), - DEFINE_FIELD( m_flBlendEndTime, FIELD_TIME ), - DEFINE_FIELD( m_flBlendStartTime, FIELD_TIME ), - DEFINE_FIELD( m_bUseCustomAutoExposureMin, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bUseCustomAutoExposureMax, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flCustomAutoExposureMin, FIELD_FLOAT ), - DEFINE_FIELD( m_flCustomAutoExposureMax, FIELD_FLOAT ), - DEFINE_FIELD( m_flCustomBloomScale, FIELD_FLOAT ), - DEFINE_FIELD( m_flCustomBloomScaleMinimum, FIELD_FLOAT ), - DEFINE_FIELD( m_bUseCustomBloomScale, FIELD_BOOLEAN ), - - DEFINE_THINKFUNC( UpdateTonemapScaleBlend ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetTonemapScale", InputSetTonemapScale ), - DEFINE_INPUTFUNC( FIELD_STRING, "BlendTonemapScale", InputBlendTonemapScale ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetTonemapRate", InputSetTonemapRate ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetAutoExposureMin", InputSetAutoExposureMin ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetAutoExposureMax", InputSetAutoExposureMax ), - DEFINE_INPUTFUNC( FIELD_VOID, "UseDefaultAutoExposure", InputUseDefaultAutoExposure ), - DEFINE_INPUTFUNC( FIELD_VOID, "UseDefaultBloomScale", InputUseDefaultBloomScale ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetBloomScale", InputSetBloomScale ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetBloomScaleRange", InputSetBloomScaleRange ), -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CEnvTonemapController, DT_EnvTonemapController ) - SendPropInt( SENDINFO(m_bUseCustomAutoExposureMin), 1, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_bUseCustomAutoExposureMax), 1, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_bUseCustomBloomScale), 1, SPROP_UNSIGNED ), - SendPropFloat( SENDINFO(m_flCustomAutoExposureMin), 0, SPROP_NOSCALE), - SendPropFloat( SENDINFO(m_flCustomAutoExposureMax), 0, SPROP_NOSCALE), - SendPropFloat( SENDINFO(m_flCustomBloomScale), 0, SPROP_NOSCALE), - SendPropFloat( SENDINFO(m_flCustomBloomScaleMinimum), 0, SPROP_NOSCALE), -END_SEND_TABLE() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvTonemapController::Spawn( void ) -{ - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NONE ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CEnvTonemapController::UpdateTransmitState() -{ - return SetTransmitState( FL_EDICT_ALWAYS ); -} - -//----------------------------------------------------------------------------- -// Purpose: Set the tonemap scale to the specified value -//----------------------------------------------------------------------------- -void CEnvTonemapController::InputSetTonemapScale( inputdata_t &inputdata ) -{ - float flRemapped = inputdata.value.Float(); - mat_hdr_tonemapscale.SetValue( flRemapped ); -} - -//----------------------------------------------------------------------------- -// Purpose: Blend the tonemap scale to the specified value -//----------------------------------------------------------------------------- -void CEnvTonemapController::InputBlendTonemapScale( inputdata_t &inputdata ) -{ - char parseString[255]; - Q_strncpy(parseString, inputdata.value.String(), sizeof(parseString)); - - // Get the target tonemap scale - char *pszParam = strtok(parseString," "); - if ( !pszParam || !pszParam[0] ) - { - Warning("%s (%s) received BlendTonemapScale input without a target tonemap scale. Syntax: \n", GetClassname(), GetDebugName() ); - return; - } - m_flBlendTonemapEnd = atof( pszParam ); - - // Get the blend time - pszParam = strtok(NULL," "); - if ( !pszParam || !pszParam[0] ) - { - Warning("%s (%s) received BlendTonemapScale input without a blend time. Syntax: \n", GetClassname(), GetDebugName() ); - return; - } - m_flBlendEndTime = gpGlobals->curtime + atof( pszParam ); - - m_flBlendStartTime = gpGlobals->curtime; - m_flBlendTonemapStart = mat_hdr_tonemapscale.GetFloat(); - - // Start thinking - SetNextThink( gpGlobals->curtime + 0.1 ); - SetThink( &CEnvTonemapController::UpdateTonemapScaleBlend ); -} - -//----------------------------------------------------------------------------- -// Purpose: set a base and minimum bloom scale -//----------------------------------------------------------------------------- -void CEnvTonemapController::InputSetBloomScaleRange( inputdata_t &inputdata ) -{ - float bloom_max=1, bloom_min=1; - int nargs=sscanf("%f %f",inputdata.value.String(), bloom_max, bloom_min ); - if (nargs != 2) - { - Warning("%s (%s) received SetBloomScaleRange input without 2 arguments. Syntax: \n", GetClassname(), GetDebugName() ); - return; - } - m_flCustomBloomScale=bloom_max; - m_flCustomBloomScale=bloom_min; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvTonemapController::InputSetTonemapRate( inputdata_t &inputdata ) -{ - // TODO: There should be a better way to do this. - ConVarRef mat_hdr_manual_tonemap_rate( "mat_hdr_manual_tonemap_rate" ); - if ( mat_hdr_manual_tonemap_rate.IsValid() ) - { - float flTonemapRate = inputdata.value.Float(); - mat_hdr_manual_tonemap_rate.SetValue( flTonemapRate ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Blend the tonemap scale to the specified value -//----------------------------------------------------------------------------- -void CEnvTonemapController::UpdateTonemapScaleBlend( void ) -{ - float flRemapped = RemapValClamped( gpGlobals->curtime, m_flBlendStartTime, m_flBlendEndTime, m_flBlendTonemapStart, m_flBlendTonemapEnd ); - mat_hdr_tonemapscale.SetValue( flRemapped ); - - //Msg("Setting tonemap scale to %f (curtime %f, %f -> %f)\n", flRemapped, gpGlobals->curtime, m_flBlendStartTime, m_flBlendEndTime ); - - // Stop when we're out of the blend range - if ( gpGlobals->curtime >= m_flBlendEndTime ) - return; - - SetNextThink( gpGlobals->curtime + 0.1 ); -} - -//----------------------------------------------------------------------------- -// Purpose: Set the auto exposure min to the specified value -//----------------------------------------------------------------------------- -void CEnvTonemapController::InputSetAutoExposureMin( inputdata_t &inputdata ) -{ - m_flCustomAutoExposureMin = inputdata.value.Float(); - m_bUseCustomAutoExposureMin = true; -} - -//----------------------------------------------------------------------------- -// Purpose: Set the auto exposure max to the specified value -//----------------------------------------------------------------------------- -void CEnvTonemapController::InputSetAutoExposureMax( inputdata_t &inputdata ) -{ - m_flCustomAutoExposureMax = inputdata.value.Float(); - m_bUseCustomAutoExposureMax = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvTonemapController::InputUseDefaultAutoExposure( inputdata_t &inputdata ) -{ - m_bUseCustomAutoExposureMin = false; - m_bUseCustomAutoExposureMax = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvTonemapController::InputSetBloomScale( inputdata_t &inputdata ) -{ - m_flCustomBloomScale = inputdata.value.Float(); - m_flCustomBloomScaleMinimum = m_flCustomBloomScale; - m_bUseCustomBloomScale = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvTonemapController::InputUseDefaultBloomScale( inputdata_t &inputdata ) -{ - m_bUseCustomBloomScale = false; -} diff --git a/game/server/env_zoom.cpp b/game/server/env_zoom.cpp deleted file mode 100644 index 82fc81986..000000000 --- a/game/server/env_zoom.cpp +++ /dev/null @@ -1,116 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "env_zoom.h" - -#ifdef HL2_DLL -#include "hl2_player.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define ENV_ZOOM_OVERRIDE (1<<0) - -class CEnvZoom : public CPointEntity -{ -public: - DECLARE_CLASS( CEnvZoom, CPointEntity ); - - void InputZoom( inputdata_t &inputdata ); - void InputUnZoom( inputdata_t &inputdata ); - - int GetFOV( void ) { return m_nFOV; } - float GetSpeed( void ) { return m_flSpeed; } -private: - - float m_flSpeed; - int m_nFOV; - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( env_zoom, CEnvZoom ); - -BEGIN_DATADESC( CEnvZoom ) - - DEFINE_KEYFIELD( m_flSpeed, FIELD_FLOAT, "Rate" ), - DEFINE_KEYFIELD( m_nFOV, FIELD_INTEGER, "FOV" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Zoom", InputZoom ), - DEFINE_INPUTFUNC( FIELD_VOID, "UnZoom", InputUnZoom ), - -END_DATADESC() - -bool CanOverrideEnvZoomOwner( CBaseEntity *pZoomOwner ) -{ - CEnvZoom *pZoom = dynamic_cast(pZoomOwner ); - - if ( pZoom == NULL || pZoom && pZoom->HasSpawnFlags( ENV_ZOOM_OVERRIDE ) == false ) - return false; - - return true; -} - -float GetZoomOwnerDesiredFOV( CBaseEntity *pZoomOwner ) -{ - if ( CanOverrideEnvZoomOwner( pZoomOwner ) ) - { - CEnvZoom *pZoom = dynamic_cast( pZoomOwner ); - - return pZoom->GetFOV(); - } - - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CEnvZoom::InputZoom( inputdata_t &inputdata ) -{ - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - - if ( pPlayer ) - { - -#ifdef HL2_DLL - if ( pPlayer == pPlayer->GetFOVOwner() ) - { - CHL2_Player *pHLPlayer = static_cast( pPlayer ); - - pHLPlayer->StopZooming(); - } -#endif - - // If the player's already holding a fov from another env_zoom, we're allowed to overwrite it - if ( pPlayer->GetFOVOwner() && FClassnameIs( pPlayer->GetFOVOwner(), "env_zoom" ) ) - { - pPlayer->ClearZoomOwner(); - } - - //Stuff the values - pPlayer->SetFOV( this, m_nFOV, m_flSpeed ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CEnvZoom::InputUnZoom( inputdata_t &inputdata ) -{ - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - - if ( pPlayer ) - { - // Stuff the values - pPlayer->SetFOV( this, 0 ); - } -} - diff --git a/game/server/env_zoom.h b/game/server/env_zoom.h deleted file mode 100644 index 64e5eefd1..000000000 --- a/game/server/env_zoom.h +++ /dev/null @@ -1,13 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ENV_ZOOM_H -#define ENV_ZOOM_H - -bool CanOverrideEnvZoomOwner( CBaseEntity *pZoomOwner ); -float GetZoomOwnerDesiredFOV( CBaseEntity *pZoomOwner ); - -#endif //ENV_ZOOM_H diff --git a/game/server/envmicrophone.cpp b/game/server/envmicrophone.cpp deleted file mode 100644 index cde447705..000000000 --- a/game/server/envmicrophone.cpp +++ /dev/null @@ -1,560 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ==== -// -// Purpose: Implements an entity that measures sound volume at a point in a map. -// -// This entity listens as though it is an NPC, meaning it will only -// hear sounds that were emitted using the CSound::InsertSound function. -// -// It does not hear danger sounds since they are not technically sounds. -// -//============================================================================= - -#include "cbase.h" -#include "entityinput.h" -#include "entityoutput.h" -#include "eventqueue.h" -#include "mathlib/mathlib.h" -#include "soundent.h" -#include "envmicrophone.h" -#include "soundflags.h" -#include "engine/IEngineSound.h" -#include "filters.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//#define DEBUG_MICROPHONE - -const float MICROPHONE_SETTLE_EPSILON = 0.005; - -// List of env_microphones who want to be told whenever a sound is started -static CUtlVector< CHandle > s_Microphones; - - -LINK_ENTITY_TO_CLASS(env_microphone, CEnvMicrophone); - -BEGIN_DATADESC( CEnvMicrophone ) - - DEFINE_KEYFIELD(m_bDisabled, FIELD_BOOLEAN, "StartDisabled"), - DEFINE_FIELD(m_hMeasureTarget, FIELD_EHANDLE), - DEFINE_KEYFIELD(m_nSoundMask, FIELD_INTEGER, "SoundMask"), - DEFINE_KEYFIELD(m_flSensitivity, FIELD_FLOAT, "Sensitivity"), - DEFINE_KEYFIELD(m_flSmoothFactor, FIELD_FLOAT, "SmoothFactor"), - DEFINE_KEYFIELD(m_iszSpeakerName, FIELD_STRING, "SpeakerName"), - DEFINE_KEYFIELD(m_iszListenFilter, FIELD_STRING, "ListenFilter"), - DEFINE_FIELD(m_hListenFilter, FIELD_EHANDLE), - DEFINE_FIELD(m_hSpeaker, FIELD_EHANDLE), - // DEFINE_FIELD(m_bAvoidFeedback, FIELD_BOOLEAN), // DONT SAVE - DEFINE_KEYFIELD(m_iSpeakerDSPPreset, FIELD_INTEGER, "speaker_dsp_preset" ), - DEFINE_KEYFIELD(m_flMaxRange, FIELD_FLOAT, "MaxRange"), - DEFINE_AUTO_ARRAY(m_szLastSound, FIELD_CHARACTER), - - DEFINE_INPUTFUNC(FIELD_VOID, "Enable", InputEnable), - DEFINE_INPUTFUNC(FIELD_VOID, "Disable", InputDisable), - DEFINE_INPUTFUNC(FIELD_STRING, "SetSpeakerName", InputSetSpeakerName), - - DEFINE_OUTPUT(m_SoundLevel, "SoundLevel"), - DEFINE_OUTPUT(m_OnRoutedSound, "OnRoutedSound" ), - DEFINE_OUTPUT(m_OnHeardSound, "OnHeardSound" ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CEnvMicrophone::~CEnvMicrophone( void ) -{ - s_Microphones.FindAndRemove( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: Called before spawning, after keyvalues have been handled. -//----------------------------------------------------------------------------- -void CEnvMicrophone::Spawn(void) -{ - // - // Build our sound type mask from our spawnflags. - // - static int nFlags[][2] = - { - { SF_MICROPHONE_SOUND_COMBAT, SOUND_COMBAT }, - { SF_MICROPHONE_SOUND_WORLD, SOUND_WORLD }, - { SF_MICROPHONE_SOUND_PLAYER, SOUND_PLAYER }, - { SF_MICROPHONE_SOUND_BULLET_IMPACT, SOUND_BULLET_IMPACT }, - { SF_MICROPHONE_SOUND_EXPLOSION, SOUND_CONTEXT_EXPLOSION }, - }; - - for (size_t i = 0; i < sizeof(nFlags) / sizeof(nFlags[0]); i++) - { - if (m_spawnflags & nFlags[i][0]) - { - m_nSoundMask |= nFlags[i][1]; - } - } - - if (m_flSensitivity == 0) - { - // - // Avoid a divide by zero in CanHearSound. - // - m_flSensitivity = 1; - } - else if (m_flSensitivity > 10) - { - m_flSensitivity = 10; - } - - m_flSmoothFactor = clamp(m_flSmoothFactor, 0, 0.9); - - if (!m_bDisabled) - { - SetNextThink( gpGlobals->curtime + 0.1f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Called after all entities have spawned and after a load game. -// Finds the reference point at which to measure sound level. -//----------------------------------------------------------------------------- -void CEnvMicrophone::Activate(void) -{ - BaseClass::Activate(); - - // Get a handle to my filter entity if there is one - if (m_iszListenFilter != NULL_STRING) - { - m_hListenFilter = dynamic_cast(gEntList.FindEntityByName( NULL, m_iszListenFilter )); - } - - if (m_target != NULL_STRING) - { - m_hMeasureTarget = gEntList.FindEntityByName(NULL, STRING(m_target) ); - - // - // If we were given a bad measure target, just measure sound where we are. - // - if ((m_hMeasureTarget == NULL) || (m_hMeasureTarget->edict() == NULL)) - { - // We've decided to disable this warning since this seems to be the 90% case. - //Warning( "EnvMicrophone - Measure target not found or measure target with no origin. Using Self.!\n"); - m_hMeasureTarget = this; - } - } - else - { - m_hMeasureTarget = this; - } - - ActivateSpeaker(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvMicrophone::OnRestore( void ) -{ - BaseClass::OnRestore(); - - ActivateSpeaker(); -} - -//----------------------------------------------------------------------------- -// Purpose: If we've got a speaker, add ourselves to the list of microphones that want to listen -//----------------------------------------------------------------------------- -void CEnvMicrophone::ActivateSpeaker( void ) -{ - // If we're enabled, set the dsp_speaker preset to my specified one - if ( !m_bDisabled ) - { - ConVarRef dsp_speaker( "dsp_speaker" ); - if ( dsp_speaker.IsValid() ) - { - int iDSPPreset = m_iSpeakerDSPPreset; - if ( !iDSPPreset ) - { - // Reset it to the default - iDSPPreset = atoi( dsp_speaker.GetDefault() ); - } - DevMsg( 2, "Microphone %s set dsp_speaker to %d.\n", STRING(GetEntityName()), iDSPPreset); - dsp_speaker.SetValue( m_iSpeakerDSPPreset ); - } - } - - if ( m_iszSpeakerName != NULL_STRING ) - { - // We've got a speaker to play heard sounds through. To do this, we need to add ourselves - // to the list of microphones who want to be told whenever a sound is played. - if ( s_Microphones.Find(this) == -1 ) - { - s_Microphones.AddToTail( this ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Stops the microphone from sampling the sound level and firing the -// SoundLevel output. -//----------------------------------------------------------------------------- -void CEnvMicrophone::InputEnable( inputdata_t &inputdata ) -{ - if (m_bDisabled) - { - m_bDisabled = false; - SetNextThink( gpGlobals->curtime + 0.1f ); - - ActivateSpeaker(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Resumes sampling the sound level and firing the SoundLevel output. -//----------------------------------------------------------------------------- -void CEnvMicrophone::InputDisable( inputdata_t &inputdata ) -{ - m_bDisabled = true; - if ( m_hSpeaker ) - { - CBaseEntity::StopSound( m_hSpeaker->entindex(), CHAN_STATIC, m_szLastSound ); - m_szLastSound[0] = 0; - - // Remove ourselves from the list of active mics - s_Microphones.FindAndRemove( this ); - } - SetNextThink( TICK_NEVER_THINK ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CEnvMicrophone::InputSetSpeakerName( inputdata_t &inputdata ) -{ - SetSpeakerName( inputdata.value.StringID() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Checks whether this microphone can hear a given sound, and at what -// relative volume level. -// Input : pSound - Sound to test. -// flVolume - Returns with the relative sound volume from 0 - 1. -// Output : Returns true if the sound could be heard at the sample point, false if not. -//----------------------------------------------------------------------------- -bool CEnvMicrophone::CanHearSound(CSound *pSound, float &flVolume) -{ - flVolume = 0; - - if ( m_bDisabled ) - { - return false; - } - - // Cull out sounds except from specific entities - CBaseFilter *pFilter = m_hListenFilter.Get(); - if ( pFilter ) - { - CBaseEntity *pSoundOwner = pSound->m_hOwner.Get(); - if ( !pSoundOwner || !pFilter->PassesFilter( this, pSoundOwner ) ) - { - return false; - } - } - - float flDistance = (pSound->GetSoundOrigin() - m_hMeasureTarget->GetAbsOrigin()).Length(); - - if (flDistance == 0) - { - flVolume = 1.0; - return true; - } - - // Over our max range? - if ( m_flMaxRange && flDistance > m_flMaxRange ) - { - return false; - } - - if (flDistance <= pSound->Volume() * m_flSensitivity) - { - flVolume = 1 - (flDistance / (pSound->Volume() * m_flSensitivity)); - flVolume = clamp(flVolume, 0, 1); - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if the microphone can hear the specified sound -//----------------------------------------------------------------------------- -bool CEnvMicrophone::CanHearSound( int entindex, soundlevel_t soundlevel, float &flVolume, const Vector *pOrigin ) -{ - if ( m_bDisabled ) - { - flVolume = 0; - return false; - } - - if ( ( m_spawnflags & SF_MICROPHONE_IGNORE_NONATTENUATED ) && soundlevel == SNDLVL_NONE ) - { - return false; - } - - // Sound might be coming from an origin or from an entity. - CBaseEntity *pEntity = NULL; - if ( entindex ) - { - pEntity = CBaseEntity::Instance( engine->PEntityOfEntIndex(entindex) ); - } - - // Cull out sounds except from specific entities - CBaseFilter *pFilter = m_hListenFilter.Get(); - if ( pFilter ) - { - if ( !pEntity || !pFilter->PassesFilter( this, pEntity ) ) - { - flVolume = 0; - return false; - } - } - - float flDistance = 0; - if ( pOrigin ) - { - flDistance = pOrigin->DistTo( m_hMeasureTarget->GetAbsOrigin() ); - } - else if ( pEntity ) - { - flDistance = pEntity->WorldSpaceCenter().DistTo( m_hMeasureTarget->GetAbsOrigin() ); - } - - // Over our max range? - if ( m_flMaxRange && flDistance > m_flMaxRange ) - { -#ifdef DEBUG_MICROPHONE - Msg("OUT OF RANGE.\n" ); -#endif - return false; - } - -#ifdef DEBUG_MICROPHONE - Msg(" flVolume %f ", flVolume ); -#endif - - // Reduce the volume by the amount it fell to get to the microphone - float gain = enginesound->GetDistGainFromSoundLevel( soundlevel, flDistance ); - flVolume *= gain; - -#ifdef DEBUG_MICROPHONE - Msg("dist %2f, soundlevel %d: gain %f", flDistance, (int)soundlevel, gain ); - if ( !flVolume ) - { - Msg(" : REJECTED\n" ); - } - else - { - Msg(" : SENT\n" ); - } -#endif - - return ( flVolume > 0 ); -} - -void CEnvMicrophone::SetSensitivity( float flSensitivity ) -{ - m_flSensitivity = flSensitivity; -} - -void CEnvMicrophone::SetSpeakerName( string_t iszSpeakerName ) -{ - m_iszSpeakerName = iszSpeakerName; - - // Set the speaker to null. This will force it to find the speaker next time a sound is routed. - m_hSpeaker = NULL; - ActivateSpeaker(); -} - -//----------------------------------------------------------------------------- -// Purpose: Listens for sounds and updates the value of the SoundLevel output. -//----------------------------------------------------------------------------- -void CEnvMicrophone::Think(void) -{ - int nSound = CSoundEnt::ActiveList(); - bool fHearSound = false; - - float flMaxVolume = 0; - - // - // Find the loudest sound that this microphone cares about. - // - while (nSound != SOUNDLIST_EMPTY) - { - CSound *pCurrentSound = CSoundEnt::SoundPointerForIndex(nSound); - - if (pCurrentSound) - { - if (m_nSoundMask & pCurrentSound->SoundType()) - { - float flVolume = 0; - if (CanHearSound(pCurrentSound, flVolume) && (flVolume > flMaxVolume)) - { - flMaxVolume = flVolume; - fHearSound = true; - } - } - } - - nSound = pCurrentSound->NextSound(); - } - - if( fHearSound ) - { - m_OnHeardSound.FireOutput( this, this ); - } - - if (flMaxVolume != m_SoundLevel.Get()) - { - // - // Don't smooth if we are within an epsilon. This allows the output to stop firing - // much more quickly. - // - if (fabs(flMaxVolume - m_SoundLevel.Get()) < MICROPHONE_SETTLE_EPSILON) - { - m_SoundLevel.Set(flMaxVolume, this, this); - } - else - { - m_SoundLevel.Set(flMaxVolume * (1 - m_flSmoothFactor) + m_SoundLevel.Get() * m_flSmoothFactor, this, this); - } - } - - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -//----------------------------------------------------------------------------- -// Purpose: Hook for the sound system to tell us when a sound's been played -//----------------------------------------------------------------------------- -MicrophoneResult_t CEnvMicrophone::SoundPlayed( int entindex, const char *soundname, soundlevel_t soundlevel, float flVolume, int iFlags, int iPitch, const Vector *pOrigin, float soundtime, CUtlVector< Vector >& soundorigins ) -{ - if ( m_bAvoidFeedback ) - return MicrophoneResult_Ok; - - // Don't hear sounds that have already been heard by a microphone to avoid feedback! - if ( iFlags & SND_SPEAKER ) - return MicrophoneResult_Ok; - -#ifdef DEBUG_MICROPHONE - Msg("%s heard %s: ", STRING(GetEntityName()), soundname ); -#endif - - if ( !CanHearSound( entindex, soundlevel, flVolume, pOrigin ) ) - return MicrophoneResult_Ok; - - // We've heard it. Play it out our speaker. If our speaker's gone away, we're done. - if ( !m_hSpeaker ) - { - // First time, find our speaker. Done here, because finding it in Activate() wouldn't - // find players, and we need to be able to specify !player for a speaker. - if ( m_iszSpeakerName != NULL_STRING ) - { - m_hSpeaker = gEntList.FindEntityByName(NULL, STRING(m_iszSpeakerName) ); - - if ( !m_hSpeaker ) - { - Warning( "EnvMicrophone %s specifies a non-existent speaker name: %s\n", STRING(GetEntityName()), STRING(m_iszSpeakerName) ); - m_iszSpeakerName = NULL_STRING; - } - } - - if ( !m_hSpeaker ) - { - return MicrophoneResult_Remove; - } - } - - m_bAvoidFeedback = true; - - // Add the speaker flag. Detected at playback and applies the speaker filter. - iFlags |= SND_SPEAKER; - CPASAttenuationFilter filter( m_hSpeaker ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_STATIC; - ep.m_pSoundName = soundname; - ep.m_flVolume = flVolume; - ep.m_SoundLevel = soundlevel; - ep.m_nFlags = iFlags; - ep.m_nPitch = iPitch; - ep.m_pOrigin = &m_hSpeaker->GetAbsOrigin(); - ep.m_flSoundTime = soundtime; - ep.m_nSpeakerEntity = entindex; - - CBaseEntity::EmitSound( filter, m_hSpeaker->entindex(), ep ); - - Q_strncpy( m_szLastSound, soundname, sizeof(m_szLastSound) ); - m_OnRoutedSound.FireOutput( this, this, 0 ); - - m_bAvoidFeedback = false; - - // Copy emitted origin to soundorigins array - for ( int i = 0; i < ep.m_UtlVecSoundOrigin.Count(); ++i ) - { - soundorigins.AddToTail( ep.m_UtlVecSoundOrigin[ i ] ); - } - - // Do we want to allow the original sound to play? - if ( m_spawnflags & SF_MICROPHONE_SWALLOW_ROUTED_SOUNDS ) - { - return MicrophoneResult_Swallow; - } - - return MicrophoneResult_Ok; -} - - -//----------------------------------------------------------------------------- -// Purpose: Called by the sound system whenever a sound is played so that -// active microphones can have a chance to pick up the sound. -// Output : Returns whether or not the sound was swallowed by the microphone. -// Swallowed sounds should not be played by the sound system. -//----------------------------------------------------------------------------- -bool CEnvMicrophone::OnSoundPlayed( int entindex, const char *soundname, soundlevel_t soundlevel, float flVolume, int iFlags, int iPitch, const Vector *pOrigin, float soundtime, CUtlVector< Vector >& soundorigins ) -{ - bool bSwallowed = false; - - // Loop through all registered microphones and tell them the sound was just played - int iCount = s_Microphones.Count(); - if ( iCount > 0 ) - { - // Iterate backwards because we might be deleting microphones. - for ( int i = iCount - 1; i >= 0; i-- ) - { - if ( s_Microphones[i] ) - { - MicrophoneResult_t eResult = s_Microphones[i]->SoundPlayed( - entindex, - soundname, - soundlevel, - flVolume, - iFlags, - iPitch, - pOrigin, - soundtime, - soundorigins ); - - if ( eResult == MicrophoneResult_Swallow ) - { - // Microphone told us to swallow it - bSwallowed = true; - } - else if ( eResult == MicrophoneResult_Remove ) - { - s_Microphones.FastRemove( i ); - } - } - } - } - - return bSwallowed; -} diff --git a/game/server/envmicrophone.h b/game/server/envmicrophone.h deleted file mode 100644 index bdeebe1e1..000000000 --- a/game/server/envmicrophone.h +++ /dev/null @@ -1,90 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ENVMICROPHONE_H -#define ENVMICROPHONE_H -#ifdef _WIN32 -#pragma once -#endif - -class CBaseFilter; - - -const int SF_MICROPHONE_SOUND_COMBAT = 0x01; -const int SF_MICROPHONE_SOUND_WORLD = 0x02; -const int SF_MICROPHONE_SOUND_PLAYER = 0x04; -const int SF_MICROPHONE_SOUND_BULLET_IMPACT = 0x08; -const int SF_MICROPHONE_SWALLOW_ROUTED_SOUNDS = 0x10; -const int SF_MICROPHONE_SOUND_EXPLOSION = 0x20; -const int SF_MICROPHONE_IGNORE_NONATTENUATED = 0x40; - - -// Return codes from SoundPlayed -enum MicrophoneResult_t -{ - MicrophoneResult_Ok = 0, - MicrophoneResult_Swallow, // The microphone swallowed the sound. Don't play it. - MicrophoneResult_Remove, // The microphone should be removed from the list of microphones. -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CEnvMicrophone : public CPointEntity -{ - DECLARE_CLASS( CEnvMicrophone, CPointEntity ); - -public: - ~CEnvMicrophone(); - - void Spawn(void); - void Activate(void); - void OnRestore( void ); - void ActivateSpeaker( void ); - void Think(void); - bool CanHearSound(CSound *pSound, float &flVolume); - bool CanHearSound( int entindex, soundlevel_t soundlevel, float &flVolume, const Vector *pOrigin ); - - void SetSensitivity( float flSensitivity ); - void SetSpeakerName( string_t iszSpeakerName ); - - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - void InputSetSpeakerName( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - - // Hook for the sound system to tell us when a sound's been played. Returns true if it's to swallow the passed in sound. - static bool OnSoundPlayed( int entindex, const char *soundname, soundlevel_t soundlevel, - float flVolume, int iFlags, int iPitch, const Vector *pOrigin, float soundtime, CUtlVector< Vector >& soundorigins ); - -private: - - // Per-microphone notification that a sound has played. - MicrophoneResult_t SoundPlayed( int entindex, const char *soundname, soundlevel_t soundlevel, - float flVolume, int iFlags, int iPitch, const Vector *pOrigin, float soundtime, CUtlVector< Vector >& soundorigins ); - - bool m_bDisabled; // If true, the microphone will not measure sound. - EHANDLE m_hMeasureTarget; // Point at which to measure sound level. - int m_nSoundMask; // Which sound types we are interested in. - float m_flSensitivity; // 0 = deaf, 1 = default, 10 = maximum sensitivity - float m_flSmoothFactor; // 0 = no smoothing of samples, 0.9 = maximum smoothing - float m_flMaxRange; // Maximum sound hearing range, irrelevant of attenuation - string_t m_iszSpeakerName; // Name of a speaker to output any heard sounds through - EHANDLE m_hSpeaker; // Speaker to output any heard sounds through - bool m_bAvoidFeedback; - int m_iSpeakerDSPPreset; // Speaker DSP preset to use when this microphone is enabled - string_t m_iszListenFilter; - CHandle m_hListenFilter; - - COutputFloat m_SoundLevel; // Fired when the sampled volume level changes. - COutputEvent m_OnRoutedSound; // Fired when a sound has been played through our speaker - COutputEvent m_OnHeardSound; // Heard sound. - - char m_szLastSound[256]; -}; - -#endif // ENVMICROPHONE_H diff --git a/game/server/episodic/ai_behavior_alyx_injured.cpp b/game/server/episodic/ai_behavior_alyx_injured.cpp deleted file mode 100644 index e48340825..000000000 --- a/game/server/episodic/ai_behavior_alyx_injured.cpp +++ /dev/null @@ -1,621 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: FIXME: This will ultimately become a more generic implementation -// -//============================================================================= - -#include "cbase.h" -#include "ai_memory.h" -#include "ai_speech.h" -#include "ai_behavior.h" -#include "ai_navigator.h" -#include "ai_playerally.h" -#include "ai_behavior_follow.h" -#include "ai_moveprobe.h" - -#include "ai_behavior_alyx_injured.h" - -ConVar g_debug_injured_follow( "g_debug_injured_follow", "0" ); -ConVar injured_help_plee_range( "injured_help_plee_range", "256" ); - -#define TLK_INJURED_FOLLOW_TOO_FAR "TLK_INJURED_FOLLOW_TOO_FAR" - -BEGIN_DATADESC( CAI_BehaviorAlyxInjured ) - DEFINE_FIELD( m_flNextWarnTime, FIELD_TIME ), - // m_ActivityMap - -END_DATADESC(); - -Activity ACT_INJURED_COWER; -Activity ACT_GESTURE_INJURED_COWER_FLINCH; - -#define COVER_DISTANCE 128.0f // Distance behind target to find cover -#define MIN_ENEMY_MOB 3 // Number of enemies considerd overwhelming -#define MAX_DIST_FROM_FOLLOW_TARGET 256 // If the follow target is farther than this, the NPC will run to it - -//============================================================================= - -CAI_BehaviorAlyxInjured::CAI_BehaviorAlyxInjured( void ) : m_flNextWarnTime( 0.0f ) -{ - SetDefLessFunc( m_ActivityMap ); -} - -struct ActivityMap_t -{ - Activity activity; - Activity translation; -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BehaviorAlyxInjured::PopulateActivityMap( void ) -{ - // Maps one activity to a translated one - ActivityMap_t map[] = - { - // Runs - { ACT_RUN, ACT_RUN_HURT }, - { ACT_RUN_AIM, ACT_RUN_AIM }, // FIMXE: No appropriate temp anim right now! - { ACT_RUN_CROUCH, ACT_RUN_HURT }, - { ACT_RUN_CROUCH_AIM, ACT_RUN_HURT }, - { ACT_RUN_PROTECTED, ACT_RUN_HURT }, - { ACT_RUN_RELAXED, ACT_RUN_HURT }, - { ACT_RUN_STIMULATED, ACT_RUN_HURT }, - { ACT_RUN_AGITATED, ACT_RUN_HURT }, - { ACT_RUN_AIM_RELAXED, ACT_RUN_AIM_RELAXED }, // FIMXE: No appropriate temp anim right now! - { ACT_RUN_AIM_STIMULATED, ACT_RUN_AIM_STIMULATED }, // FIMXE: No appropriate temp anim right now! - { ACT_RUN_AIM_AGITATED, ACT_RUN_AIM_AGITATED }, // FIMXE: No appropriate temp anim right now! - { ACT_RUN_HURT, ACT_RUN_HURT }, - - // Walks - { ACT_WALK, ACT_WALK_HURT }, - { ACT_WALK_AIM, ACT_WALK_HURT }, - { ACT_WALK_CROUCH, ACT_WALK_HURT }, - { ACT_WALK_CROUCH_AIM, ACT_WALK_HURT }, - { ACT_WALK_RELAXED, ACT_WALK_HURT }, - { ACT_WALK_STIMULATED, ACT_WALK_HURT }, - { ACT_WALK_AGITATED, ACT_WALK_HURT }, - { ACT_WALK_AIM_RELAXED, ACT_WALK_HURT }, - { ACT_WALK_AIM_STIMULATED, ACT_WALK_HURT }, - { ACT_WALK_AIM_AGITATED, ACT_WALK_HURT }, - { ACT_WALK_HURT, ACT_WALK_HURT }, - - { ACT_IDLE, ACT_IDLE_HURT }, - { ACT_COVER_LOW, ACT_INJURED_COWER }, - { ACT_COWER, ACT_INJURED_COWER }, - }; - - // Clear the map - m_ActivityMap.RemoveAll(); - - // Add all translations - for ( size_t i = 0; i < ARRAYSIZE( map ); i++ ) - { - Assert( m_ActivityMap.Find( map[i].activity ) == m_ActivityMap.InvalidIndex() ); - m_ActivityMap.Insert( map[i].activity, map[i].translation ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Populate the list after save/load -//----------------------------------------------------------------------------- -void CAI_BehaviorAlyxInjured::OnRestore( void ) -{ - PopulateActivityMap(); -} - -//----------------------------------------------------------------------------- -// Purpose: Populate the list on spawn -//----------------------------------------------------------------------------- -void CAI_BehaviorAlyxInjured::Spawn( void ) -{ - PopulateActivityMap(); -} - -//----------------------------------------------------------------------------- -// Purpose: Get the flinch activity for us to play -// Input : bHeavyDamage - -// bGesture - -// Output : Activity -//----------------------------------------------------------------------------- -Activity CAI_BehaviorAlyxInjured::GetFlinchActivity( bool bHeavyDamage, bool bGesture ) -{ - // - if ( ( bGesture == false ) || ( GetOuter()->GetActivity() != ACT_COWER ) ) - return BaseClass::GetFlinchActivity( bHeavyDamage, bGesture ); - - // Translate the flinch if we're cowering - return ACT_GESTURE_INJURED_COWER_FLINCH; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : nActivity - -//----------------------------------------------------------------------------- -Activity CAI_BehaviorAlyxInjured::NPC_TranslateActivity( Activity nActivity ) -{ - // Find out what the base class wants to do with the activity - Activity nNewActivity = BaseClass::NPC_TranslateActivity( nActivity ); - - // Look it up in the translation map - int nIndex = m_ActivityMap.Find( nNewActivity ); - - if ( m_ActivityMap.IsValidIndex( nIndex ) ) - return m_ActivityMap[nIndex]; - - return nNewActivity; -} - -//----------------------------------------------------------------------------- -// Purpose: Determines if Alyx should run away from enemies or stay put -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_BehaviorAlyxInjured::ShouldRunToCover( void ) -{ - Vector vecRetreatPos; - float flRetreatRadius = 128.0f; - - // See how far off from our cover position we are - if ( FindCoverFromEnemyBehindTarget( GetFollowTarget(), flRetreatRadius, &vecRetreatPos ) ) - { - float flDestDistSqr = ( GetOuter()->WorldSpaceCenter() - vecRetreatPos ).LengthSqr(); - if ( flDestDistSqr > Square( flRetreatRadius ) ) - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: See if we need to follow our goal -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_BehaviorAlyxInjured::ShouldRunToFollowGoal( void ) -{ - // If we're too far from our follow target, we need to chase after them - float flDistToFollowGoalSqr = ( GetOuter()->GetAbsOrigin() - GetFollowTarget()->GetAbsOrigin() ).LengthSqr(); - if ( flDistToFollowGoalSqr > Square(MAX_DIST_FROM_FOLLOW_TARGET) ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Translate base schedules into overridden forms -//----------------------------------------------------------------------------- -int CAI_BehaviorAlyxInjured::TranslateSchedule( int scheduleType ) -{ - switch( scheduleType ) - { - case SCHED_RUN_FROM_ENEMY: - case SCHED_RUN_FROM_ENEMY_MOB: - { - // Get under cover if we're able to - if ( ShouldRunToCover() ) - return SCHED_INJURED_RUN_FROM_ENEMY; - - // Run to our follow goal if we're too far away from it - if ( ShouldRunToFollowGoal() ) - return SCHED_FOLLOW; - - // Cower if surrounded - if ( HasCondition( COND_INJURED_OVERWHELMED ) ) - return SCHED_INJURED_COWER; - - // Face our enemies - return SCHED_INJURED_FEAR_FACE; - } - break; - - case SCHED_RUN_FROM_ENEMY_FALLBACK: - return SCHED_INJURED_COWER; - break; - } - - return BaseClass::TranslateSchedule( scheduleType ); -} - -//----------------------------------------------------------------------------- -// Purpose: Pick up failure cases and handle them -//----------------------------------------------------------------------------- -int CAI_BehaviorAlyxInjured::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ) -{ - // Failed schedules - switch( failedSchedule ) - { - case SCHED_RUN_FROM_ENEMY: - case SCHED_RUN_FROM_ENEMY_MOB: - case SCHED_FOLLOW: - return SCHED_INJURED_COWER; - } - - // Failed tasks - switch( failedTask ) - { - case TASK_FIND_COVER_FROM_ENEMY: - case TASK_FIND_INJURED_COVER_FROM_ENEMY: - - // Only cower if we're already near enough to our follow target - float flDistToFollowTargetSqr = ( GetOuter()->GetAbsOrigin() - GetFollowTarget()->GetAbsOrigin() ).LengthSqr(); - if ( flDistToFollowTargetSqr > Square( 256 ) ) - return SCHED_FOLLOW; - - return SCHED_INJURED_COWER; - break; - } - - return BaseClass::SelectFailSchedule( failedSchedule, failedTask, taskFailCode ); -} - -//----------------------------------------------------------------------------- -// Purpose: Find the general direction enemies are coming towards us at -//----------------------------------------------------------------------------- -bool CAI_BehaviorAlyxInjured::FindThreatDirection2D( const Vector &vecSource, Vector *vecOut ) -{ - // Find the general direction our threat is coming from - bool bValid = false; - Vector vecScratch; - AIEnemiesIter_t iter; - - // Iterate through all known enemies - for( AI_EnemyInfo_t *pMemory = GetOuter()->GetEnemies()->GetFirst(&iter); pMemory != NULL; pMemory = GetOuter()->GetEnemies()->GetNext(&iter) ) - { - if ( pMemory == NULL || pMemory->hEnemy == NULL ) - continue; - - vecScratch = ( vecSource - pMemory->hEnemy->WorldSpaceCenter() ); - VectorNormalize( vecScratch ); - - (*vecOut) += vecScratch; - bValid = true; - } - - // Find the general direction - (*vecOut).z = 0.0f; - VectorNormalize( (*vecOut) ); - return bValid; -} - -//----------------------------------------------------------------------------- -// Purpose: Find a position that hides us from our threats while interposing the -// target entity between us and the threat -// Input : pTarget - entity to hide behind -// flRadius - Radius around the target to search -// *vecOut - position -//----------------------------------------------------------------------------- -bool CAI_BehaviorAlyxInjured::FindCoverFromEnemyBehindTarget( CBaseEntity *pTarget, float flRadius, Vector *vecOut ) -{ - if ( pTarget == NULL ) - return false; - - Vector vecTargetPos = pTarget->GetAbsOrigin(); - Vector vecThreatDir = vec3_origin; - - // Find our threat direction and base our cover on that - if ( FindThreatDirection2D( vecTargetPos, &vecThreatDir ) ) - { - // Get a general location for taking cover - Vector vecTestPos = vecTargetPos + ( vecThreatDir * flRadius ); - - if ( g_debug_injured_follow.GetBool() ) - { - NDebugOverlay::HorzArrow( GetOuter()->GetAbsOrigin(), vecTestPos, 8.0f, 255, 255, 0, 32, true, 2.0f ); - } - - // Make sure we never move towards our threat to get to cover! - Vector vecMoveDir = GetOuter()->GetAbsOrigin() - vecTestPos; - VectorNormalize( vecMoveDir ); - float flDotToCover = DotProduct( vecMoveDir, vecThreatDir ); - if ( flDotToCover > 0.0f ) - { - if ( g_debug_injured_follow.GetBool() ) - { - NDebugOverlay::HorzArrow( GetOuter()->GetAbsOrigin(), vecTestPos, 8.0f, 255, 0, 0, 32, true, 2.0f ); - } - - return false; - } - - AIMoveTrace_t moveTrace; - GetOuter()->GetMoveProbe()->MoveLimit( NAV_GROUND, - GetOuter()->GetAbsOrigin(), - vecTestPos, - MASK_SOLID_BRUSHONLY, - NULL, - 0, - &moveTrace ); - - bool bWithinRangeToGoal = ( moveTrace.vEndPosition - vecTestPos ).Length2DSqr() < Square( GetOuter()->GetHullWidth() * 3.0f ); - bool bCanStandAtGoal = GetOuter()->GetMoveProbe()->CheckStandPosition( moveTrace.vEndPosition, MASK_SOLID_BRUSHONLY ); - - if ( bWithinRangeToGoal == false || bCanStandAtGoal == false ) - { - if ( g_debug_injured_follow.GetBool() ) - { - NDebugOverlay::SweptBox( GetOuter()->GetAbsOrigin(), vecTestPos, GetOuter()->GetHullMins(), GetOuter()->GetHullMaxs(), vec3_angle, 255, 0, 0, 0, 2.0f ); - } - - return false; - } - - // Accept it - *vecOut = moveTrace.vEndPosition; - - if ( g_debug_injured_follow.GetBool() ) - { - NDebugOverlay::SweptBox( GetOuter()->GetAbsOrigin(), (*vecOut), GetOuter()->GetHullMins(), GetOuter()->GetHullMaxs(), vec3_angle, 0, 255, 0, 0, 2.0f ); - } - - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTask - -//----------------------------------------------------------------------------- -void CAI_BehaviorAlyxInjured::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_FIND_COVER_FROM_ENEMY: - { - CBaseEntity *pLeader = GetFollowTarget(); - if ( !pLeader ) - { - BaseClass::StartTask( pTask ); - break; - } - - // Find a position behind our follow target - Vector coverPos = vec3_invalid; - if ( FindCoverFromEnemyBehindTarget( pLeader, COVER_DISTANCE, &coverPos ) ) - { - AI_NavGoal_t goal( GOALTYPE_LOCATION, coverPos, ACT_RUN, AIN_HULL_TOLERANCE, AIN_DEF_FLAGS ); - GetOuter()->GetNavigator()->SetGoal( goal ); - GetOuter()->m_flMoveWaitFinished = gpGlobals->curtime + pTask->flTaskData; - TaskComplete(); - return; - } - - // Couldn't find anything - TaskFail( FAIL_NO_COVER ); - break; - } - - default: - BaseClass::StartTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Whether or not Alyx is injured -//----------------------------------------------------------------------------- -bool CAI_BehaviorAlyxInjured::IsInjured( void ) const -{ - return IsAlyxInInjuredMode(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_BehaviorAlyxInjured::GatherConditions( void ) -{ - BaseClass::GatherConditions(); - - // Always stomp over this - ClearCondition( COND_INJURED_TOO_FAR_FROM_PLAYER ); - ClearCondition( COND_INJURED_OVERWHELMED ); - - // See if we're overwhelmed by foes - if ( NumKnownEnemiesInRadius( GetOuter()->GetAbsOrigin(), COVER_DISTANCE ) >= MIN_ENEMY_MOB ) - { - SetCondition( COND_INJURED_OVERWHELMED ); - } - - // Determines whether we consider ourselves in danger - bool bInDanger = ( HasCondition( COND_LIGHT_DAMAGE ) || - HasCondition( COND_HEAVY_DAMAGE ) || - HasCondition( COND_INJURED_OVERWHELMED ) ); - - // See if we're too far away from the player and in danger - if ( AI_IsSinglePlayer() && bInDanger ) - { - bool bWarnPlayer = false; - - // This only works in single-player - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); - if ( pPlayer != NULL ) - { - // FIXME: This distance may need to be the length of the shortest walked path between the follower and the target - - // Get our approximate distance to the player - float flDistToPlayer = UTIL_DistApprox2D( GetOuter()->GetAbsOrigin(), pPlayer->GetAbsOrigin() ); - if ( flDistToPlayer > injured_help_plee_range.GetFloat() ) - { - bWarnPlayer = true; - } - else if ( flDistToPlayer > (injured_help_plee_range.GetFloat()*0.5f) && HasCondition( COND_SEE_PLAYER ) == false ) - { - // Cut our distance in half if we can't see the player - bWarnPlayer = true; - } - } - - // Yell for help! - if ( bWarnPlayer ) - { - // FIXME: This should be routed through the normal speaking code with a system to emit from the player's suit. - - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); - //float flPlayerDistSqr = ( GetOuter()->GetAbsOrigin() - pPlayer->GetAbsOrigin() ).LengthSqr(); - - // If the player is too far away or we can't see him - //if ( HasCondition( COND_SEE_PLAYER ) == false || flPlayerDistSqr > Square( 128 ) ) - { - if ( m_flNextWarnTime < gpGlobals->curtime ) - { - pPlayer->EmitSound( "npc_alyx.injured_too_far" ); - m_flNextWarnTime = gpGlobals->curtime + random->RandomFloat( 3.0f, 5.0f ); - } - } - /* - else - { - SpeakIfAllowed( TLK_INJURED_FOLLOW_TOO_FAR ); - m_flNextWarnTime = gpGlobals->curtime + random->RandomFloat( 3.0f, 5.0f ); - } - */ - - SetCondition( COND_INJURED_TOO_FAR_FROM_PLAYER ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Speak a concept if we're able to -//----------------------------------------------------------------------------- -void CAI_BehaviorAlyxInjured::SpeakIfAllowed( AIConcept_t concept ) -{ - CAI_Expresser *pExpresser = GetOuter()->GetExpresser(); - if ( pExpresser == NULL ) - return; - - // Must be able to speak the concept - if ( pExpresser->CanSpeakConcept( concept ) ) - { - pExpresser->Speak( concept ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Get the number of known enemies within a radius to a point -//----------------------------------------------------------------------------- -int CAI_BehaviorAlyxInjured::NumKnownEnemiesInRadius( const Vector &vecSource, float flRadius ) -{ - int nNumEnemies = 0; - float flRadiusSqr = Square( flRadius ); - - AIEnemiesIter_t iter; - - // Iterate through all known enemies - for( AI_EnemyInfo_t *pMemory = GetEnemies()->GetFirst(&iter); pMemory != NULL; pMemory = GetEnemies()->GetNext(&iter) ) - { - if ( pMemory == NULL || pMemory->hEnemy == NULL ) - continue; - - // Must hate or fear them - if ( GetOuter()->IRelationType( pMemory->hEnemy ) != D_HT && GetOuter()->IRelationType( pMemory->hEnemy ) != D_FR ) - continue; - - // Count only the enemies I've seen recently - if ( gpGlobals->curtime - pMemory->timeLastSeen > 0.5f ) - continue; - - // Must be within the radius we've specified - float flEnemyDistSqr = ( vecSource - pMemory->hEnemy->GetAbsOrigin() ).Length2DSqr(); - if ( flEnemyDistSqr < flRadiusSqr ) - { - nNumEnemies++; - } - } - - return nNumEnemies; -} - -// ---------------------------------------------- -// Custom AI declarations -// ---------------------------------------------- - -AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( CAI_BehaviorAlyxInjured ) -{ - DECLARE_ACTIVITY( ACT_GESTURE_INJURED_COWER_FLINCH ) - DECLARE_ACTIVITY( ACT_INJURED_COWER ) - - DECLARE_CONDITION( COND_INJURED_TOO_FAR_FROM_PLAYER ) - DECLARE_CONDITION( COND_INJURED_OVERWHELMED ) - - DECLARE_TASK( TASK_FIND_INJURED_COVER_FROM_ENEMY ) - - DEFINE_SCHEDULE - ( - SCHED_INJURED_COWER, - - " Tasks" - // TOOD: Announce cower - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_COWER" - " TASK_WAIT 2" - "" - " Interrupts" - " COND_GIVE_WAY" - " COND_PLAYER_PUSHING" - ) - - DEFINE_SCHEDULE - ( - SCHED_INJURED_FEAR_FACE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" // FIXME: Scared idle? - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - " COND_GIVE_WAY" - " COND_PLAYER_PUSHING" - ); - - DEFINE_SCHEDULE - ( - SCHED_INJURED_RUN_FROM_ENEMY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_INJURED_COWER" - " TASK_STOP_MOVING 0" - " TASK_FIND_COVER_FROM_ENEMY 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - ); - - AI_END_CUSTOM_SCHEDULE_PROVIDER() -} - -//----------------------------------------------------------------------------- -// CAI_InjuredFollowGoal -//----------------------------------------------------------------------------- - -BEGIN_DATADESC( CAI_InjuredFollowGoal ) -END_DATADESC() - -LINK_ENTITY_TO_CLASS( ai_goal_injured_follow, CAI_InjuredFollowGoal ); - -//------------------------------------- - -void CAI_InjuredFollowGoal::EnableGoal( CAI_BaseNPC *pAI ) -{ - CAI_BehaviorAlyxInjured *pBehavior; - if ( !pAI->GetBehavior( &pBehavior ) ) - return; - - if ( GetGoalEntity() == NULL ) - return; - - pBehavior->SetFollowGoal( this ); -} - -//------------------------------------- - -void CAI_InjuredFollowGoal::DisableGoal( CAI_BaseNPC *pAI ) -{ - CAI_BehaviorAlyxInjured *pBehavior; - if ( !pAI->GetBehavior( &pBehavior ) ) - return; - - pBehavior->ClearFollowGoal( this ); -} diff --git a/game/server/episodic/ai_behavior_alyx_injured.h b/game/server/episodic/ai_behavior_alyx_injured.h deleted file mode 100644 index b8614d7ed..000000000 --- a/game/server/episodic/ai_behavior_alyx_injured.h +++ /dev/null @@ -1,95 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: FIXME: This will ultimately become a more generic implementation -// -//============================================================================= - -#ifndef AI_BEHAVIOR_ALYX_INJURED_H -#define AI_BEHAVIOR_ALYX_INJURED_H -#ifdef _WIN32 -#pragma once -#endif - -#include "utlmap.h" - -extern bool IsAlyxInInjuredMode( void ); - -// -// -// - -class CAI_InjuredFollowGoal : public CAI_FollowGoal -{ - DECLARE_CLASS( CAI_InjuredFollowGoal, CAI_FollowGoal ); - -public: - - virtual void EnableGoal( CAI_BaseNPC *pAI ); - virtual void DisableGoal( CAI_BaseNPC *pAI ); - - DECLARE_DATADESC(); -}; - -// -// -// - -class CAI_BehaviorAlyxInjured : public CAI_FollowBehavior -{ - DECLARE_CLASS( CAI_BehaviorAlyxInjured, CAI_FollowBehavior ); - DECLARE_DATADESC(); - -public: - CAI_BehaviorAlyxInjured( void ); - - virtual const char *GetName( void ) { return "AlyxInjuredFollow"; } - virtual Activity NPC_TranslateActivity( Activity nActivity ); - virtual int TranslateSchedule( int scheduleType ); - virtual void Spawn( void ); - virtual void OnRestore( void ); - virtual void StartTask( const Task_t *pTask ); - virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ); - virtual void GatherConditions( void ); - virtual Activity GetFlinchActivity( bool bHeavyDamage, bool bGesture ); - - enum - { - // Schedules - SCHED_INJURED_COWER = BaseClass::NEXT_SCHEDULE, - SCHED_INJURED_FEAR_FACE, - SCHED_INJURED_RUN_FROM_ENEMY, - NEXT_SCHEDULE, - - // Tasks - TASK_FIND_INJURED_COVER_FROM_ENEMY = BaseClass::NEXT_TASK, - NEXT_TASK, - - // Conditions - COND_INJURED_TOO_FAR_FROM_PLAYER = BaseClass::NEXT_CONDITION, - COND_INJURED_OVERWHELMED, - NEXT_CONDITION - }; - - bool IsReadinessCapable( void ) { return ( IsInjured() == false ); } // Never use the readiness system when injured - bool IsInjured( void ) const; - -private: - - void SpeakIfAllowed( AIConcept_t concept ); - bool ShouldRunToCover( void ); - bool ShouldRunToFollowGoal( void ); - bool FindThreatDirection2D( const Vector &vecSource, Vector *vecOut ); - bool FindCoverFromEnemyBehindTarget( CBaseEntity *pTarget, float flRadius, Vector *vecOut ); - void PopulateActivityMap( void ); - int NumKnownEnemiesInRadius( const Vector &vecSource, float flRadius ); - - CUtlMap m_ActivityMap; - - float m_flNextWarnTime; - -protected: - DEFINE_CUSTOM_SCHEDULE_PROVIDER; -}; - - -#endif // AI_BEHAVIOR_ALYX_INJURED_H diff --git a/game/server/episodic/ai_behavior_passenger_companion.cpp b/game/server/episodic/ai_behavior_passenger_companion.cpp deleted file mode 100644 index c004805bd..000000000 --- a/game/server/episodic/ai_behavior_passenger_companion.cpp +++ /dev/null @@ -1,2053 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: Companion NPCs riding in cars -// -//============================================================================= - -#include "cbase.h" -#include "ai_speech.h" -#include "ai_pathfinder.h" -#include "ai_waypoint.h" -#include "ai_navigator.h" -#include "ai_navgoaltype.h" -#include "ai_memory.h" -#include "ai_behavior_passenger_companion.h" -#include "ai_squadslot.h" -#include "npc_playercompanion.h" -#include "ai_route.h" -#include "saverestore_utlvector.h" -#include "cplane.h" -#include "util_shared.h" -#include "sceneentity.h" - -bool SphereWithinPlayerFOV( CBasePlayer *pPlayer, const Vector &vecCenter, float flRadius ); - -#define PASSENGER_NEAR_VEHICLE_THRESHOLD 64.0f - -#define MIN_OVERTURNED_DURATION 1.0f // seconds -#define MIN_FAILED_EXIT_ATTEMPTS 4 -#define MIN_OVERTURNED_WARN_DURATION 4.0f // seconds - -ConVar passenger_collision_response_threshold( "passenger_collision_response_threshold", "250.0" ); -ConVar passenger_debug_entry( "passenger_debug_entry", "0" ); -ConVar passenger_use_leaning("passenger_use_leaning", "1" ); -extern ConVar passenger_debug_transition; - -// Custom activities -Activity ACT_PASSENGER_IDLE_AIM; -Activity ACT_PASSENGER_RELOAD; -Activity ACT_PASSENGER_OVERTURNED; -Activity ACT_PASSENGER_IMPACT; -Activity ACT_PASSENGER_IMPACT_WEAPON; -Activity ACT_PASSENGER_POINT; -Activity ACT_PASSENGER_POINT_BEHIND; -Activity ACT_PASSENGER_IDLE_READY; -Activity ACT_PASSENGER_GESTURE_JOSTLE_LARGE; -Activity ACT_PASSENGER_GESTURE_JOSTLE_SMALL; -Activity ACT_PASSENGER_GESTURE_JOSTLE_LARGE_STIMULATED; -Activity ACT_PASSENGER_GESTURE_JOSTLE_SMALL_STIMULATED; -Activity ACT_PASSENGER_COWER_IN; -Activity ACT_PASSENGER_COWER_LOOP; -Activity ACT_PASSENGER_COWER_OUT; -Activity ACT_PASSENGER_IDLE_FIDGET; - -BEGIN_DATADESC( CAI_PassengerBehaviorCompanion ) - - DEFINE_EMBEDDED( m_VehicleMonitor ), - - DEFINE_UTLVECTOR( m_FailedEntryPositions, FIELD_EMBEDDED ), - - DEFINE_FIELD( m_flOverturnedDuration, FIELD_FLOAT ), - DEFINE_FIELD( m_flUnseenDuration, FIELD_FLOAT ), - DEFINE_FIELD( m_nExitAttempts, FIELD_INTEGER ), - DEFINE_FIELD( m_flNextOverturnWarning, FIELD_TIME ), - DEFINE_FIELD( m_flEnterBeginTime, FIELD_TIME ), - DEFINE_FIELD( m_hCompanion, FIELD_EHANDLE ), - DEFINE_FIELD( m_flNextJostleTime, FIELD_TIME ), - DEFINE_FIELD( m_nVisibleEnemies, FIELD_INTEGER ), - DEFINE_FIELD( m_flLastLateralLean, FIELD_FLOAT ), - DEFINE_FIELD( m_flEntraceUpdateTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextEnterAttempt, FIELD_TIME ), - DEFINE_FIELD( m_flNextFidgetTime, FIELD_TIME ), - -END_DATADESC(); - -BEGIN_SIMPLE_DATADESC( FailPosition_t ) - - DEFINE_FIELD( vecPosition, FIELD_VECTOR ), - DEFINE_FIELD( flTime, FIELD_TIME ), - -END_DATADESC(); - -CAI_PassengerBehaviorCompanion::CAI_PassengerBehaviorCompanion( void ) : -m_flNextJostleTime( 0.0f ), -m_flNextOverturnWarning( 0.0f ), -m_flOverturnedDuration( 0.0f ), -m_flUnseenDuration( 0.0f ), -m_nExitAttempts( 0 ), -m_flLastLateralLean( 0.0f ), -m_flNextEnterAttempt( 0.0f ) -{ - memset( &m_vehicleState, 0, sizeof( m_vehicleState ) ); - m_VehicleMonitor.ClearMark(); -} - -void CAI_PassengerBehaviorCompanion::Enable( CPropJeepEpisodic *pVehicle, bool bImmediateEnter /*= false*/ ) -{ - BaseClass::Enable( pVehicle ); - - // Store this up for quick reference later on - m_hCompanion = dynamic_cast(GetOuter()); - - // See if we want to sit in the vehicle immediately - if ( bImmediateEnter ) - { - // Find the seat and sit in it - if ( ReserveEntryPoint( VEHICLE_SEAT_ANY ) ) - { - // Attach - AttachToVehicle(); - - // This will slam us into the right position and clean up - FinishEnterVehicle(); - GetOuter()->AddEffects( EF_NOINTERP ); - - // Start our schedule immediately - ClearSchedule( "Immediate entry to vehicle" ); - } - } -} - -//----------------------------------------------------------------------------- -// Set up the shot regulator based on the equipped weapon -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorCompanion::OnUpdateShotRegulator( void ) -{ - if ( GetVehicleSpeed() > 250 ) - { - // Default values - GetOuter()->GetShotRegulator()->SetBurstInterval( 0.1f, 0.5f ); - GetOuter()->GetShotRegulator()->SetBurstShotCountRange( 1, 4 ); - GetOuter()->GetShotRegulator()->SetRestInterval( 0.25f, 1.0f ); - } - else - { - BaseClass::OnUpdateShotRegulator(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PassengerBehaviorCompanion::IsValidEnemy( CBaseEntity *pEntity ) -{ - // The target must be much closer in the vehicle - float flDistSqr = ( pEntity->GetAbsOrigin() - GetAbsOrigin() ).LengthSqr(); - if ( flDistSqr > Square( (40*12) ) && pEntity->Classify() != CLASS_BULLSEYE ) - return false; - - // Determine if the target is going to move past us? - return BaseClass::IsValidEnemy( pEntity ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the speed the vehicle is moving at -// Output : units per second -//----------------------------------------------------------------------------- -float CAI_PassengerBehaviorCompanion::GetVehicleSpeed( void ) -{ - if ( m_hVehicle == NULL ) - { - Assert(0); - return -1.0f; - } - - Vector vecVelocity; - m_hVehicle->GetVelocity( &vecVelocity, NULL ); - - // Get our speed - return vecVelocity.Length(); -} - -//----------------------------------------------------------------------------- -// Purpose: Detect oncoming collisions -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorCompanion::GatherVehicleCollisionConditions( const Vector &localVelocity ) -{ - // Look for walls in front of us - if ( localVelocity.y > passenger_collision_response_threshold.GetFloat() ) - { - // Detect an upcoming collision - Vector vForward; - m_hVehicle->GetVectors( &vForward, NULL, NULL ); - - // Use a smaller bounding box to make it detect mostly head-on impacts - Vector mins, maxs; - mins.Init( -24, -24, 32 ); - maxs.Init( 24, 24, 64 ); - - float dt = 0.6f; // Seconds - float distance = localVelocity.y * dt; - - // Find our angular velocity as a vector - Vector vecAngularVelocity; - vecAngularVelocity.z = 0.0f; - SinCos( DEG2RAD( m_vehicleState.m_vecLastAngles.z * dt ), &vecAngularVelocity.y, &vecAngularVelocity.x ); - - Vector vecOffset; - VectorRotate( vecAngularVelocity, m_hVehicle->GetAbsAngles() + QAngle( 0, 90, 0 ), vecOffset ); - - vForward += vecOffset; - VectorNormalize( vForward ); - - // Trace ahead of us to see what's there - CTraceFilterNoNPCsOrPlayer filter( m_hVehicle, COLLISION_GROUP_NONE ); // We don't care about NPCs or the player (certainly if they're in the vehicle!) - - trace_t tr; - UTIL_TraceHull( m_hVehicle->GetAbsOrigin(), m_hVehicle->GetAbsOrigin() + ( vForward * distance ), mins, maxs, MASK_SOLID, &filter, &tr ); - - bool bWarnCollision = true; - if ( tr.DidHit() ) - { - // We need to see how "head-on" to the surface we are - float impactDot = DotProduct( tr.plane.normal, vForward ); - - // Don't warn over grazing blows or slopes - if ( impactDot < -0.9f && tr.plane.normal.z < 0.75f ) - { - // Make sure this is a worthwhile thing to warn about - if ( tr.m_pEnt ) - { - // If it's physical and moveable, then ignore it because we'll probably smash or move it - IPhysicsObject *pObject = tr.m_pEnt->VPhysicsGetObject(); - if ( pObject && pObject->IsMoveable() ) - { - bWarnCollision = false; - } - } - - // Note that we should say something to the player about it - if ( bWarnCollision ) - { - SetCondition( COND_PASSENGER_WARN_COLLISION ); - } - } - } - } - - if ( passenger_use_leaning.GetBool() ) - { - // Calculate how our body is leaning - CalculateBodyLean(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Speak various lines about the state of the vehicle -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorCompanion::SpeakVehicleConditions( void ) -{ - Assert( m_hVehicle != NULL ); - if ( m_hVehicle == NULL ) - return; - - // Speak if we just hit something - if ( HasCondition( COND_PASSENGER_HARD_IMPACT ) ) - { - SpeakIfAllowed( TLK_PASSENGER_IMPACT ); - } - - // Speak if we're overturned - if ( HasCondition( COND_PASSENGER_OVERTURNED ) ) - { - SpeakIfAllowed( TLK_PASSENGER_OVERTURNED ); - } - - // Speak if we're about to hit something - if ( HasCondition( COND_PASSENGER_WARN_COLLISION ) ) - { - // Make Alyx look at the impending impact - Vector vecForward; - m_hVehicle->GetVectors( &vecForward, NULL, NULL ); - Vector vecLookPos = m_hVehicle->WorldSpaceCenter() + ( vecForward * 64.0f ); - GetOuter()->AddLookTarget( vecLookPos, 1.0f, 1.0f ); - - SpeakIfAllowed( TLK_PASSENGER_WARN_COLLISION ); - ClearCondition( COND_PASSENGER_WARN_COLLISION ); - } - - // Speak if the player is driving like a madman - if ( HasCondition( COND_PASSENGER_ERRATIC_DRIVING ) ) - { - SpeakIfAllowed( TLK_PASSENGER_ERRATIC_DRIVING ); - } - - // The vehicle has come to a halt - if ( HasCondition( COND_PASSENGER_VEHICLE_STOPPED ) ) - { - float flDist = ( WorldSpaceCenter() - m_hVehicle->WorldSpaceCenter() ).Length(); - CFmtStrN<128> modifiers( "vehicle_distance:%f", flDist ); - SpeakIfAllowed( TLK_PASSENGER_VEHICLE_STOPPED, modifiers ); - } - - // The vehicle has started to move - if ( HasCondition( COND_PASSENGER_VEHICLE_STARTED ) ) - { - float flDist = ( WorldSpaceCenter() - m_hVehicle->WorldSpaceCenter() ).Length(); - CFmtStrN<128> modifiers( "vehicle_distance:%f", flDist ); - SpeakIfAllowed( TLK_PASSENGER_VEHICLE_STARTED, modifiers ); - } - - // Player got in - if ( HasCondition( COND_PASSENGER_PLAYER_EXITED_VEHICLE ) ) - { - CPropJeepEpisodic *pJalopy = dynamic_cast(m_hVehicle.Get()); - if( pJalopy != NULL && pJalopy->NumRadarContacts() > 0 ) - { - SpeakIfAllowed( TLK_PASSENGER_PLAYER_EXITED, "radar_has_targets" ); - } - else - { - SpeakIfAllowed( TLK_PASSENGER_PLAYER_EXITED ); - } - } - - // Player got out - if ( HasCondition( COND_PASSENGER_PLAYER_ENTERED_VEHICLE ) ) - { - SpeakIfAllowed( TLK_PASSENGER_PLAYER_ENTERED ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Whether or not we should jostle at this moment -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PassengerBehaviorCompanion::CanPlayJostle( bool bLargeJostle ) -{ - // We've been told to suppress the jostle - if ( m_flNextJostleTime > gpGlobals->curtime ) - return false; - - // Can't do this if we're at a high readiness level - if ( m_hCompanion && m_hCompanion->ShouldBeAiming() ) - return false; - - // Can't do this when we're upside-down - if ( HasCondition( COND_PASSENGER_OVERTURNED ) ) - return false; - - // Allow our normal impact code to handle this one instead - if ( HasCondition( COND_PASSENGER_HARD_IMPACT ) || IsCurSchedule( SCHED_PASSENGER_IMPACT ) ) - return false; - - if ( bLargeJostle ) - { - // Don't bother under certain circumstances - if ( IsCurSchedule( SCHED_PASSENGER_COWER ) || - IsCurSchedule( SCHED_PASSENGER_FIDGET ) ) - return false; - } - else - { - // Don't interrupt a larger gesture - if ( GetOuter()->IsPlayingGesture( ACT_PASSENGER_GESTURE_JOSTLE_LARGE ) || GetOuter()->IsPlayingGesture( ACT_PASSENGER_GESTURE_JOSTLE_LARGE_STIMULATED ) ) - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Gather conditions we can comment on or react to while riding in the vehicle -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorCompanion::GatherVehicleStateConditions( void ) -{ - // Gather the base class - BaseClass::GatherVehicleStateConditions(); - - // See if we're going to collide with anything soon - GatherVehicleCollisionConditions( m_vehicleState.m_vecLastLocalVelocity ); - - // Say anything we're meant to through the response rules - SpeakVehicleConditions(); -} - -//----------------------------------------------------------------------------- -// Purpose: Handles exit failure notifications -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorCompanion::OnExitVehicleFailed( void ) -{ - m_nExitAttempts++; -} - -//----------------------------------------------------------------------------- -// Purpose: Track how long we've been overturned -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorCompanion::UpdateStuckStatus( void ) -{ - if ( m_hVehicle == NULL ) - return; - - // Always clear this to start out with - ClearCondition( COND_PASSENGER_CAN_LEAVE_STUCK_VEHICLE ); - - // If we can't exit the vehicle, then don't bother with these checks - if ( m_hVehicle->NPC_CanExitVehicle( GetOuter(), true ) == false ) - return; - - bool bVisibleToPlayer = false; - bool bPlayerInVehicle = false; - - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); - if ( pPlayer ) - { - bVisibleToPlayer = pPlayer->FInViewCone( GetOuter()->GetAbsOrigin() ); - bPlayerInVehicle = pPlayer->IsInAVehicle(); - } - - // If we're not overturned, just reset our counter - if ( m_vehicleState.m_bWasOverturned == false ) - { - m_flOverturnedDuration = 0.0f; - m_flUnseenDuration = 0.0f; - } - else - { - // Add up the time since we last checked - m_flOverturnedDuration += ( gpGlobals->curtime - GetLastThink() ); - } - - // Warn about being stuck upside-down if it's been long enough - if ( m_flOverturnedDuration > MIN_OVERTURNED_WARN_DURATION && m_flNextOverturnWarning < gpGlobals->curtime ) - { - SetCondition( COND_PASSENGER_WARN_OVERTURNED ); - } - - // If the player can see us or is still in the vehicle, we never exit - if ( bVisibleToPlayer || bPlayerInVehicle ) - { - // Reset our timer - m_flUnseenDuration = 0.0f; - return; - } - - // Add up the time since we last checked - m_flUnseenDuration += ( gpGlobals->curtime - GetLastThink() ); - - // If we've been overturned for long enough or tried to exit one too many times - if ( m_vehicleState.m_bWasOverturned ) - { - if ( m_flUnseenDuration > MIN_OVERTURNED_DURATION ) - { - SetCondition( COND_PASSENGER_CAN_LEAVE_STUCK_VEHICLE ); - } - } - else if ( m_nExitAttempts >= MIN_FAILED_EXIT_ATTEMPTS ) - { - // The player can't be looking at us - SetCondition( COND_PASSENGER_CAN_LEAVE_STUCK_VEHICLE ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Gather conditions for our use in making decisions -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorCompanion::GatherConditions( void ) -{ - // Code below relies on these conditions being set first! - BaseClass::GatherConditions(); - - // We're not enabled - if ( IsEnabled() == false ) - return; - - // In-car conditions - if ( GetPassengerState() == PASSENGER_STATE_INSIDE ) - { - // If we're jostling, then note that - if ( HasCondition( COND_PASSENGER_ERRATIC_DRIVING ) ) - { - if ( CanPlayJostle( true ) ) - { - // Add the gesture to be played. If it's already playing, the underlying function will simply opt-out - int nSequence = GetOuter()->AddGesture( GetOuter()->NPC_TranslateActivity( ACT_PASSENGER_GESTURE_JOSTLE_LARGE ), true ); - - GetOuter()->SetNextAttack( gpGlobals->curtime + ( GetOuter()->SequenceDuration( nSequence ) * 2.0f ) ); - GetOuter()->GetShotRegulator()->FireNoEarlierThan( GetOuter()->GetNextAttack() ); - - // Push out our fidget into the future so that we don't act unnaturally over bumpy terrain - ExtendFidgetDelay( random->RandomFloat( 1.5f, 3.0f ) ); - } - } - else if ( HasCondition( COND_PASSENGER_JOSTLE_SMALL ) ) - { - if ( CanPlayJostle( false ) ) - { - // Add the gesture to be played. If it's already playing, the underlying function will simply opt-out - GetOuter()->AddGesture( GetOuter()->NPC_TranslateActivity( ACT_PASSENGER_GESTURE_JOSTLE_SMALL ), true ); - - // Push out our fidget into the future so that we don't act unnaturally over bumpy terrain - ExtendFidgetDelay( random->RandomFloat( 1.5f, 3.0f ) ); - } - } - - // See if we're upside-down - UpdateStuckStatus(); - - // See if we're able to fidget - if ( CanFidget() ) - { - SetCondition( COND_PASSENGER_CAN_FIDGET ); - } - } - - // Clear this out - ClearCondition( COND_PASSENGER_CAN_ENTER_IMMEDIATELY ); - - // Make sure a vehicle doesn't stray from its mark - if ( IsCurSchedule( SCHED_PASSENGER_RUN_TO_ENTER_VEHICLE ) ) - { - if ( m_VehicleMonitor.TargetMoved( m_hVehicle ) ) - { - SetCondition( COND_PASSENGER_VEHICLE_MOVED_FROM_MARK ); - } - - // If we can get in the car right away, set us up to do so - int nNearestSequence; - if ( CanEnterVehicleImmediately( &nNearestSequence, &m_vecTargetPosition, &m_vecTargetAngles ) ) - { - SetTransitionSequence( nNearestSequence ); - SetCondition( COND_PASSENGER_ENTERING ); - SetCondition( COND_PASSENGER_CAN_ENTER_IMMEDIATELY ); - } - } - - // Clear the number for now - m_nVisibleEnemies = 0; - - AIEnemiesIter_t iter; - for( AI_EnemyInfo_t *pEMemory = GetEnemies()->GetFirst(&iter); pEMemory != NULL; pEMemory = GetEnemies()->GetNext(&iter) ) - { - if( GetOuter()->IRelationType( pEMemory->hEnemy ) == D_HT ) - { - if( pEMemory->timeLastSeen == gpGlobals->curtime ) - { - m_nVisibleEnemies++; - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorCompanion::AimGun( void ) -{ - // If there is no aiming target, return to center - if ( GetEnemy() == NULL ) - { - GetOuter()->RelaxAim(); - return; - } - - // Otherwise try and shoot down the barrel - Vector vecForward, vecRight, vecUp; - GetOuter()->GetVectors( &vecForward, &vecRight, &vecUp ); - Vector vecTorso = GetAbsOrigin() + ( vecUp * 48.0f ); - - Vector vecShootDir = GetOuter()->GetShootEnemyDir( vecTorso, false ); - - Vector vecDirToEnemy = GetEnemy()->GetAbsOrigin() - vecTorso; - VectorNormalize( vecDirToEnemy ); - - bool bRightSide = ( DotProduct( vecDirToEnemy, vecRight ) > 0.0f ); - float flTargetDot = ( bRightSide ) ? -0.7f : 0.0f; - - if ( DotProduct( vecForward, vecDirToEnemy ) <= flTargetDot ) - { - // Don't aim at something that's outside our reach - GetOuter()->RelaxAim(); - } - else - { - // Aim at it - GetOuter()->SetAim( vecShootDir ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Allow us to deny selecting a schedule if we're not in a state to do so -//----------------------------------------------------------------------------- -bool CAI_PassengerBehaviorCompanion::CanSelectSchedule( void ) -{ - if ( BaseClass::CanSelectSchedule() == false ) - return false; - - // We're in a period where we're allowing our base class to override us - if ( m_flNextEnterAttempt > gpGlobals->curtime ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Deal with enter/exit of the vehicle -//----------------------------------------------------------------------------- -int CAI_PassengerBehaviorCompanion::SelectTransitionSchedule( void ) -{ - // Attempt to instantly enter the vehicle - if ( HasCondition( COND_PASSENGER_CAN_ENTER_IMMEDIATELY ) ) - { - // Snap to position and begin to animate into the seat - EnterVehicleImmediately(); - return SCHED_PASSENGER_ENTER_VEHICLE_IMMEDIATELY; - } - - // Entering schedule - if ( HasCondition( COND_PASSENGER_ENTERING ) || m_PassengerIntent == PASSENGER_INTENT_ENTER ) - { - if ( GetPassengerState() == PASSENGER_STATE_INSIDE ) - { - ClearCondition( COND_PASSENGER_ENTERING ); - m_PassengerIntent = PASSENGER_INTENT_NONE; - return SCHED_NONE; - } - - // Don't attempt to enter for a period of time - if ( m_flNextEnterAttempt > gpGlobals->curtime ) - return SCHED_NONE; - - ClearCondition( COND_PASSENGER_ENTERING ); - - // Failing that, run to the right place - return SCHED_PASSENGER_RUN_TO_ENTER_VEHICLE; - } - - return BaseClass::SelectTransitionSchedule(); -} - -//----------------------------------------------------------------------------- -// Purpose: Select schedules when we're riding in the car -//----------------------------------------------------------------------------- -int CAI_PassengerBehaviorCompanion::SelectScheduleInsideVehicle( void ) -{ - // Overturned - if ( HasCondition( COND_PASSENGER_OVERTURNED ) ) - return SCHED_PASSENGER_OVERTURNED; - - if ( HasCondition( COND_PASSENGER_HARD_IMPACT ) ) - { - // Push out our fidget into the future so that we don't act unnaturally over bumpy terrain - ExtendFidgetDelay( random->RandomFloat( 1.5f, 3.0f ) ); - m_flNextJostleTime = gpGlobals->curtime + random->RandomFloat( 2.5f, 4.0f ); - return SCHED_PASSENGER_IMPACT; - } - - // Look for exiting the vehicle - if ( HasCondition( COND_PASSENGER_CAN_LEAVE_STUCK_VEHICLE ) ) - return SCHED_PASSENGER_EXIT_STUCK_VEHICLE; - - // Cower if we're about to get nailed - if ( HasCondition( COND_HEAR_DANGER ) && IsCurSchedule( SCHED_PASSENGER_COWER ) == false ) - { - SpeakIfAllowed( TLK_DANGER ); - return SCHED_PASSENGER_COWER; - } - - // Fire on targets - if ( GetEnemy() ) - { - // Limit how long we'll keep an enemy if there are many on screen - if ( HasCondition( COND_NEW_ENEMY ) && m_nVisibleEnemies > 1 ) - { - GetEnemies()->SetTimeValidEnemy( GetEnemy(), random->RandomFloat( 0.5f, 1.0f ) ); - } - - // Always face - GetOuter()->AddLookTarget( GetEnemy(), 1.0f, 2.0f ); - - if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) && ( GetOuter()->GetShotRegulator()->IsInRestInterval() == false ) ) - return SCHED_PASSENGER_RANGE_ATTACK1; - } - - // Reload when we have the chance - if ( HasCondition( COND_LOW_PRIMARY_AMMO ) && HasCondition( COND_SEE_ENEMY ) == false ) - return SCHED_PASSENGER_RELOAD; - - // Say an overturned line - if ( HasCondition( COND_PASSENGER_WARN_OVERTURNED ) ) - { - SpeakIfAllowed( TLK_PASSENGER_REQUEST_UPRIGHT ); - m_flNextOverturnWarning = gpGlobals->curtime + random->RandomFloat( 5.0f, 10.0f ); - ClearCondition( COND_PASSENGER_WARN_OVERTURNED ); - } - - // Should we fidget? - if ( HasCondition( COND_PASSENGER_CAN_FIDGET ) ) - { - ExtendFidgetDelay( random->RandomFloat( 6.0f, 12.0f ) ); - return SCHED_PASSENGER_FIDGET; - } - - return SCHED_NONE; -} - -//----------------------------------------------------------------------------- -// Purpose: Select schedules while we're outside the car -//----------------------------------------------------------------------------- -int CAI_PassengerBehaviorCompanion::SelectScheduleOutsideVehicle( void ) -{ - // FIXME: How can we get in here? - Assert( m_hVehicle ); - if ( m_hVehicle == NULL ) - return SCHED_NONE; - - // Handle our mark moving - if ( HasCondition( COND_PASSENGER_VEHICLE_MOVED_FROM_MARK ) ) - { - // Reset our mark - m_VehicleMonitor.SetMark( m_hVehicle, 36.0f ); - ClearCondition( COND_PASSENGER_VEHICLE_MOVED_FROM_MARK ); - } - - // If we want to get in, the try to do so - if ( m_PassengerIntent == PASSENGER_INTENT_ENTER ) - { - // If we're not attempting to enter the vehicle again, just fall to the base class - if ( m_flNextEnterAttempt > gpGlobals->curtime ) - return BaseClass::SelectSchedule(); - - // Otherwise try and enter thec car - return SCHED_PASSENGER_RUN_TO_ENTER_VEHICLE; - } - - // This means that we're outside the vehicle with no intent to enter, which should have disabled us! - Disable(); - Assert( 0 ); - - return SCHED_NONE; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -// &vecCenter - -// flRadius - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool SphereWithinPlayerFOV( CBasePlayer *pPlayer, const Vector &vecCenter, float flRadius ) -{ - // TODO: For safety sake, we might want to do a more fully qualified test against the frustum using the bbox - - // If the player can see us, then we can't enter immediately anyway - if ( pPlayer == NULL ) - return false; - - // Find the length to the point - Vector los = ( vecCenter - pPlayer->EyePosition() ); - float flLength = VectorNormalize( los ); - - // Get the player's forward direction - Vector vecPlayerForward; - pPlayer->EyeVectors( &vecPlayerForward, NULL, NULL ); - - // This is the additional number of degrees to add to account for our distance - float flArcAddition = atan2( flRadius, flLength ); - - // Find if the sphere is within our FOV - float flDot = DotProduct( los, vecPlayerForward ); - float flPlayerFOV = cos( DEG2RAD( pPlayer->GetFOV() / 2.0f ) ); - - return ( flDot > (flPlayerFOV-flArcAddition) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PassengerBehaviorCompanion::CanEnterVehicleImmediately( int *pResultSequence, Vector *pResultPos, QAngle *pResultAngles ) -{ - // Must wait a short time before trying to do this (otherwise we stack up on the player!) - if ( ( gpGlobals->curtime - m_flEnterBeginTime ) < 0.5f ) - return false; - - // Vehicle can't be moving too quickly - if ( GetVehicleSpeed() > 150 ) - return false; - - // If the player can see us, then we can't enter immediately anyway - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer == NULL ) - return false; - - Vector vecPosition = GetOuter()->WorldSpaceCenter(); - float flRadius = GetOuter()->CollisionProp()->BoundingRadius2D(); - if ( SphereWithinPlayerFOV( pPlayer, vecPosition, flRadius ) ) - return false; - - // Reserve an entry point - if ( ReserveEntryPoint( VEHICLE_SEAT_ANY ) == false ) - return false; - - // Get a list of all our animations - const PassengerSeatAnims_t *pEntryAnims = m_hVehicle->GetServerVehicle()->NPC_GetPassengerSeatAnims( GetOuter(), PASSENGER_SEAT_ENTRY ); - if ( pEntryAnims == NULL ) - return -1; - - // Get the ultimate position we'll end up at - Vector vecStartPos, vecEndPos; - QAngle vecStartAngles; - if ( m_hVehicle->GetServerVehicle()->NPC_GetPassengerSeatPosition( GetOuter(), &vecEndPos, NULL ) == false ) - return -1; - - // Categorize the passenger in terms of being on the left or right side of the vehicle - Vector vecRight; - m_hVehicle->GetVectors( NULL, &vecRight, NULL ); - - CPlane lateralPlane; - lateralPlane.InitializePlane( vecRight, m_hVehicle->WorldSpaceCenter() ); - - bool bPlaneSide = lateralPlane.PointInFront( GetOuter()->GetAbsOrigin() ); - - Vector vecPassengerOffset = ( GetOuter()->WorldSpaceCenter() - GetOuter()->GetAbsOrigin() ); - - const CPassengerSeatTransition *pTransition; - float flNearestDistSqr = FLT_MAX; - float flSeatDistSqr; - int nNearestSequence = -1; - int nSequence; - Vector vecNearestPos(0.0f, 0.0f, 0.0f); - QAngle vecNearestAngles(0.0f, 0.0f, 0.0f); - - // Test each animation (sorted by priority) for the best match - for ( int i = 0; i < pEntryAnims->Count(); i++ ) - { - // Find the activity for this animation name - pTransition = &pEntryAnims->Element(i); - nSequence = GetOuter()->LookupSequence( STRING( pTransition->GetAnimationName() ) ); - if ( nSequence == -1 ) - continue; - - // Test this entry for validity - if ( GetEntryPoint( nSequence, &vecStartPos, &vecStartAngles ) == false ) - continue; - - // See if the passenger would be visible if standing at this position - if ( SphereWithinPlayerFOV( pPlayer, (vecStartPos+vecPassengerOffset), flRadius ) ) - continue; - - // Otherwise distance is the deciding factor - flSeatDistSqr = ( vecStartPos - GetOuter()->GetAbsOrigin() ).LengthSqr(); - - // We must be within a certain distance to the vehicle - if ( flSeatDistSqr > Square( 25*12 ) ) - continue; - - // We cannot cross between the plane which splits the vehicle laterally in half down the middle - // This avoids cases where the character magically ends up on one side of the vehicle after they were - // clearly just on the other side. - if ( lateralPlane.PointInFront( vecStartPos ) != bPlaneSide ) - continue; - - // Closer, take it - if ( flSeatDistSqr < flNearestDistSqr ) - { - flNearestDistSqr = flSeatDistSqr; - nNearestSequence = nSequence; - vecNearestPos = vecStartPos; - vecNearestAngles = vecStartAngles; - } - } - - // Fail if we didn't find anything - if ( nNearestSequence == -1 ) - return false; - - // Return the results - if ( pResultSequence ) - { - *pResultSequence = nNearestSequence; - } - - if ( pResultPos ) - { - *pResultPos = vecNearestPos; - } - - if ( pResultAngles ) - { - *pResultAngles = vecNearestAngles; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Put us into the vehicle immediately -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorCompanion::EnterVehicleImmediately( void ) -{ - // Now play the animation - GetOuter()->SetIdealActivity( ACT_SCRIPT_CUSTOM_MOVE ); - GetOuter()->GetNavigator()->ClearGoal(); - - // Put us there and get going (no interpolation!) - GetOuter()->Teleport( &m_vecTargetPosition, &m_vecTargetAngles, &vec3_origin ); - GetOuter()->AddEffects( EF_NOINTERP ); -} - -//----------------------------------------------------------------------------- -// Purpose: Overrides the schedule selection -// Output : int - Schedule to play -//----------------------------------------------------------------------------- -int CAI_PassengerBehaviorCompanion::SelectSchedule( void ) -{ - // First, keep track of our transition state (enter/exit) - int nSched = SelectTransitionSchedule(); - if ( nSched != SCHED_NONE ) - return nSched; - - // Handle schedules based on our passenger state - if ( GetPassengerState() == PASSENGER_STATE_OUTSIDE ) - { - nSched = SelectScheduleOutsideVehicle(); - if ( nSched != SCHED_NONE ) - return nSched; - } - else if ( GetPassengerState() == PASSENGER_STATE_INSIDE ) - { - nSched = SelectScheduleInsideVehicle(); - if ( nSched != SCHED_NONE ) - return nSched; - } - - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CAI_PassengerBehaviorCompanion::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ) -{ - switch( failedTask ) - { - case TASK_GET_PATH_TO_VEHICLE_ENTRY_POINT: - { - // This is not allowed! - if ( GetPassengerState() != PASSENGER_STATE_OUTSIDE ) - { - Assert( 0 ); - return SCHED_FAIL; - } - - // If we're not close enough, then get nearer the target - if ( UTIL_DistApprox( m_hVehicle->GetAbsOrigin(), GetOuter()->GetAbsOrigin() ) > PASSENGER_NEAR_VEHICLE_THRESHOLD ) - return SCHED_PASSENGER_RUN_TO_ENTER_VEHICLE_FAILED; - } - - // Fall through - - case TASK_GET_PATH_TO_NEAR_VEHICLE: - m_flNextEnterAttempt = gpGlobals->curtime + 3.0f; - break; - } - - return BaseClass::SelectFailSchedule( failedSchedule, failedTask, taskFailCode ); -} - -//----------------------------------------------------------------------------- -// Purpose: Start to enter the vehicle -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorCompanion::EnterVehicle( void ) -{ - BaseClass::EnterVehicle(); - - m_nExitAttempts = 0; - m_VehicleMonitor.SetMark( m_hVehicle, 8.0f ); - m_flEnterBeginTime = gpGlobals->curtime; - - // Remove this flag because we're sitting so close we always think we're going to hit the player - // FIXME: We need to store this state so we don't incorrectly restore it later - GetOuter()->CapabilitiesRemove( bits_CAP_NO_HIT_PLAYER ); - - // Discard enemies quickly - GetOuter()->GetEnemies()->SetEnemyDiscardTime( 2.0f ); - - SpeakIfAllowed( TLK_PASSENGER_BEGIN_ENTRANCE ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorCompanion::FinishEnterVehicle( void ) -{ - BaseClass::FinishEnterVehicle(); - - // We succeeded - ResetVehicleEntryFailedState(); - - // Push this out into the future so we don't always fidget immediately in the vehicle - ExtendFidgetDelay( random->RandomFloat( 4.0, 15.0f ) ); - - SpeakIfAllowed( TLK_PASSENGER_FINISH_ENTRANCE ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorCompanion::ExitVehicle( void ) -{ - BaseClass::ExitVehicle(); - - SpeakIfAllowed( TLK_PASSENGER_BEGIN_EXIT ); -} - -//----------------------------------------------------------------------------- -// Purpose: Vehicle has been completely exited -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorCompanion::FinishExitVehicle( void ) -{ - BaseClass::FinishExitVehicle(); - - m_nExitAttempts = 0; - m_VehicleMonitor.ClearMark(); - - // FIXME: We need to store this state so we don't incorrectly restore it later - GetOuter()->CapabilitiesAdd( bits_CAP_NO_HIT_PLAYER ); - - // FIXME: Restore this properly - GetOuter()->GetEnemies()->SetEnemyDiscardTime( AI_DEF_ENEMY_DISCARD_TIME ); - - SpeakIfAllowed( TLK_PASSENGER_FINISH_EXIT ); -} - -//----------------------------------------------------------------------------- -// Purpose: Tries to build a route to the entry point of the target vehicle. -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PassengerBehaviorCompanion::FindPathToVehicleEntryPoint( void ) -{ - // Set our custom move name - // bool bFindNearest = ( GetOuter()->m_NPCState == NPC_STATE_COMBAT || GetOuter()->m_NPCState == NPC_STATE_ALERT ); - bool bFindNearest = true; // For the sake of quick gameplay, just make Alyx move directly! - int nSequence = FindEntrySequence( bFindNearest ); - if ( nSequence == -1 ) - return false; - - // We have to do this specially because the activities are not named - SetTransitionSequence( nSequence ); - - // Get the entry position - Vector vecEntryPoint; - QAngle vecEntryAngles; - if ( GetEntryPoint( m_nTransitionSequence, &vecEntryPoint, &vecEntryAngles ) == false ) - { - MarkVehicleEntryFailed( vecEntryPoint ); - return false; - } - - // If we're already close enough, just succeed - float flDistToGoalSqr = ( GetOuter()->GetAbsOrigin() - vecEntryPoint ).LengthSqr(); - if ( flDistToGoalSqr < Square(3*12) ) - return true; - - // Setup our goal - AI_NavGoal_t goal( GOALTYPE_LOCATION ); - // goal.arrivalActivity = ACT_SCRIPT_CUSTOM_MOVE; - goal.dest = vecEntryPoint; - - // See if we need a radial route around the car, to our goal - if ( UseRadialRouteToEntryPoint( vecEntryPoint ) ) - { - // Find the bounding radius of the vehicle - Vector vecCenterPoint = m_hVehicle->WorldSpaceCenter(); - vecCenterPoint.z = vecEntryPoint.z; - bool bClockwise; - float flArc = GetArcToEntryPoint( vecCenterPoint, vecEntryPoint, bClockwise ); - float flRadius = m_hVehicle->CollisionProp()->BoundingRadius2D(); - - // Try and set a radial route - if ( GetOuter()->GetNavigator()->SetRadialGoal( vecEntryPoint, vecCenterPoint, flRadius, flArc, 64.0f, bClockwise ) == false ) - { - // Try the opposite way - flArc = 360.0f - flArc; - - // Try the opposite way around - if ( GetOuter()->GetNavigator()->SetRadialGoal( vecEntryPoint, vecCenterPoint, flRadius, flArc, 64.0f, !bClockwise ) == false ) - { - // Try and set a direct route as a last resort - if ( GetOuter()->GetNavigator()->SetGoal( goal ) == false ) - return false; - } - } - - // We found a goal - GetOuter()->GetNavigator()->SetArrivalDirection( vecEntryAngles ); - GetOuter()->GetNavigator()->SetArrivalSpeed( 64.0f ); - return true; - } - else - { - // Try and set a direct route - if ( GetOuter()->GetNavigator()->SetGoal( goal ) ) - { - GetOuter()->GetNavigator()->SetArrivalDirection( vecEntryAngles ); - GetOuter()->GetNavigator()->SetArrivalSpeed( 64.0f ); - return true; - } - } - - // We failed, so remember it - MarkVehicleEntryFailed( vecEntryPoint ); - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Tests the route and position to see if it's valid -// Input : &vecTestPos - position to test -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PassengerBehaviorCompanion::CanExitAtPosition( const Vector &vecTestPos ) -{ - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer == NULL ) - return false; - - // Can't be in our potential view - if ( pPlayer->FInViewCone( vecTestPos ) ) - return false; - - // NOTE: There's no reason to do this since this is only called from a node's reported position - // Find the exact ground at this position - //Vector vecGroundPos; - //if ( FindGroundAtPosition( vecTestPos, 16.0f, 64.0f, &vecGroundPos ) == false ) - // return false; - - // Get the ultimate position we'll end up at - Vector vecStartPos; - if ( m_hVehicle->GetServerVehicle()->NPC_GetPassengerSeatPosition( GetOuter(), &vecStartPos, NULL ) == false ) - return false; - - // See if we can move from where we are to that position in space - if ( IsValidTransitionPoint( vecStartPos, vecTestPos ) == false ) - return false; - - // Trace down to the ground - // FIXME: This piece of code is redundant and happening in IsValidTransitionPoint() as well - /* - Vector vecGroundPos; - if ( FindGroundAtPosition( vecTestPos, GetOuter()->StepHeight(), 64.0f, &vecGroundPos ) == false ) - return false; - */ - - // Try and sweep a box through space and make sure it's clear of obstructions - /* - trace_t tr; - CTraceFilterVehicleTransition skipFilter( GetOuter(), m_hVehicle, COLLISION_GROUP_NONE ); - - // These are very approximated (and magical) numbers to allow passengers greater head room and leg room when transitioning - Vector vecMins = GetOuter()->GetHullMins() + Vector( 0, 0, GetOuter()->StepHeight()*2.0f ); // FIXME: - Vector vecMaxs = GetOuter()->GetHullMaxs() - Vector( 0, 0, GetOuter()->StepHeight() ); - - UTIL_TraceHull( GetOuter()->GetAbsOrigin(), vecGroundPos, vecMins, vecMaxs, MASK_NPCSOLID, &skipFilter, &tr ); - - // If we're blocked, we can't get out there - if ( tr.fraction < 1.0f || tr.allsolid || tr.startsolid ) - { - if ( passenger_debug_transition.GetBool() ) - { - NDebugOverlay::SweptBox( GetOuter()->GetAbsOrigin(), vecGroundPos, vecMins, GetOuter()->GetHullMaxs(), vec3_angle, 255, 0, 0, 64, 2.0f ); - } - return false; - } - */ - - return true; -} - -#define NUM_EXIT_ITERATIONS 8 - -//----------------------------------------------------------------------------- -// Purpose: Find a position we can use to exit the vehicle via teleportation -// Input : *vecResult - safe place to exit to -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PassengerBehaviorCompanion::GetStuckExitPos( Vector *vecResult ) -{ - // Get our right direction - Vector vecVehicleRight; - m_hVehicle->GetVectors( NULL, &vecVehicleRight, NULL ); - - // Get the vehicle's rough horizontal bounds - float flVehicleRadius = m_hVehicle->CollisionProp()->BoundingRadius2D(); - - // Use the vehicle's center as our hub - Vector vecCenter = m_hVehicle->WorldSpaceCenter(); - - // Angle whose tan is: y/x - float flCurAngle = atan2f( vecVehicleRight.y, vecVehicleRight.x ); - float flAngleIncr = (M_PI*2.0f)/(float)NUM_EXIT_ITERATIONS; - Vector vecTestPos; - - // Test a number of discrete exit routes - for ( int i = 0; i <= NUM_EXIT_ITERATIONS-1; i++ ) - { - // Get our position - SinCos( flCurAngle, &vecTestPos.y, &vecTestPos.x ); - vecTestPos.z = 0.0f; - vecTestPos *= flVehicleRadius; - vecTestPos += vecCenter; - - // Now find the nearest node and use that - int nNearNode = GetOuter()->GetPathfinder()->NearestNodeToPoint( vecTestPos ); - if ( nNearNode != NO_NODE ) - { - Vector vecNodePos = g_pBigAINet->GetNodePosition( GetOuter()->GetHullType(), nNearNode ); - - // Test the position - if ( CanExitAtPosition( vecNodePos ) ) - { - // Take the result - *vecResult = vecNodePos; - return true; - } - - // Move to the next iteration - flCurAngle += flAngleIncr; - } - } - - // None found - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Attempt to get out of an overturned vehicle when the player isn't looking -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PassengerBehaviorCompanion::ExitStuckVehicle( void ) -{ - // Try and find an exit position - Vector vecExitPos; - if ( GetStuckExitPos( &vecExitPos ) == false ) - return false; - - // Detach from the parent - GetOuter()->SetParent( NULL ); - - // Do all necessary clean-up - FinishExitVehicle(); - - // Teleport to the destination - // TODO: Make sure that the player can't see this! - GetOuter()->Teleport( &vecExitPos, &vec3_angle, &vec3_origin ); - GetOuter()->AddEffects( EF_NOINTERP ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorCompanion::StartTask( const Task_t *pTask ) -{ - // We need to override these so we never face - if ( GetPassengerState() == PASSENGER_STATE_INSIDE ) - { - if ( pTask->iTask == TASK_FACE_TARGET || - pTask->iTask == TASK_FACE_ENEMY || - pTask->iTask == TASK_FACE_IDEAL || - pTask->iTask == TASK_FACE_HINTNODE || - pTask->iTask == TASK_FACE_LASTPOSITION || - pTask->iTask == TASK_FACE_PATH || - pTask->iTask == TASK_FACE_PLAYER || - pTask->iTask == TASK_FACE_REASONABLE || - pTask->iTask == TASK_FACE_SAVEPOSITION || - pTask->iTask == TASK_FACE_SCRIPT ) - { - return TaskComplete(); - } - } - - switch ( pTask->iTask ) - { - case TASK_RUN_TO_VEHICLE_ENTRANCE: - { - // Get a move on! - GetOuter()->GetNavigator()->SetMovementActivity( ACT_RUN ); - } - break; - - case TASK_GET_PATH_TO_VEHICLE_ENTRY_POINT: - { - if ( GetPassengerState() != PASSENGER_STATE_OUTSIDE ) - { - Assert( 0 ); - TaskFail( "Trying to run while inside a vehicle!\n"); - return; - } - - // Reserve an entry point - if ( ReserveEntryPoint( VEHICLE_SEAT_ANY ) == false ) - { - TaskFail( "No valid entry point!\n" ); - return; - } - - // Find where we're going - if ( FindPathToVehicleEntryPoint() ) - { - TaskComplete(); - return; - } - - // We didn't find a path - TaskFail( "TASK_GET_PATH_TO_VEHICLE_ENTRY_POINT: Unable to run to entry point" ); - } - break; - - case TASK_GET_PATH_TO_TARGET: - { - GetOuter()->SetTarget( m_hVehicle ); - BaseClass::StartTask( pTask ); - } - break; - - case TASK_GET_PATH_TO_NEAR_VEHICLE: - { - if ( m_hVehicle == NULL ) - { - TaskFail("Lost vehicle pointer\n"); - return; - } - - // Find the passenger offset we're going for - Vector vecRight; - m_hVehicle->GetVectors( NULL, &vecRight, NULL ); - Vector vecTargetOffset = vecRight * 64.0f; - - // Try and find a path near there - AI_NavGoal_t goal( GOALTYPE_TARGETENT, vecTargetOffset, AIN_DEF_ACTIVITY, 64.0f, AIN_UPDATE_TARGET_POS, m_hVehicle ); - GetOuter()->SetTarget( m_hVehicle ); - if ( GetOuter()->GetNavigator()->SetGoal( goal ) ) - { - TaskComplete(); - return; - } - - TaskFail( "Unable to find path to get closer to vehicle!\n" ); - return; - } - - break; - - case TASK_PASSENGER_RELOAD: - { - GetOuter()->SetIdealActivity( ACT_PASSENGER_RELOAD ); - return; - } - break; - - case TASK_PASSENGER_EXIT_STUCK_VEHICLE: - { - if ( ExitStuckVehicle() ) - { - TaskComplete(); - return; - } - - TaskFail("Unable to exit overturned vehicle!\n"); - } - break; - - case TASK_PASSENGER_OVERTURNED: - { - // Go into our overturned animation - if ( GetOuter()->GetActivity() != ACT_PASSENGER_OVERTURNED ) - { - GetOuter()->SetActivity( ACT_RESET ); - GetOuter()->SetActivity( ACT_PASSENGER_OVERTURNED ); - } - - TaskComplete(); - } - break; - - case TASK_PASSENGER_IMPACT: - { - // Stomp anything currently playing on top of us, this has to take priority - GetOuter()->RemoveAllGestures(); - - // Go into our impact animation - GetOuter()->ResetIdealActivity( ACT_PASSENGER_IMPACT ); - - // Delay for twice the duration of our impact animation - int nSequence = GetOuter()->SelectWeightedSequence( ACT_PASSENGER_IMPACT ); - float flSeqDuration = GetOuter()->SequenceDuration( nSequence ); - float flStunTime = flSeqDuration + random->RandomFloat( 1.0f, 2.0f ); - GetOuter()->SetNextAttack( gpGlobals->curtime + flStunTime ); - ExtendFidgetDelay( flStunTime ); - } - break; - - default: - BaseClass::StartTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_PassengerBehaviorCompanion::IsCurTaskContinuousMove( void ) -{ - const Task_t *pCurTask = GetCurTask(); - if ( pCurTask && pCurTask->iTask == TASK_RUN_TO_VEHICLE_ENTRANCE ) - return true; - - return BaseClass::IsCurTaskContinuousMove(); -} - -//----------------------------------------------------------------------------- -// Purpose: Update our path if we're running towards the vehicle (since it can move) -//----------------------------------------------------------------------------- -bool CAI_PassengerBehaviorCompanion::UpdateVehicleEntrancePath( void ) -{ - // If it's too soon to check again, don't bother - if ( m_flEntraceUpdateTime > gpGlobals->curtime ) - return true; - - // Find out if we need to update - if ( m_VehicleMonitor.TargetMoved2D( m_hVehicle ) == false ) - { - m_flEntraceUpdateTime = gpGlobals->curtime + 0.5f; - return true; - } - - // Don't attempt again for some amount of time - m_flEntraceUpdateTime = gpGlobals->curtime + 1.0f; - - int nSequence = FindEntrySequence( true ); - if ( nSequence == -1 ) - return false; - - SetTransitionSequence( nSequence ); - - // Get the entry position - Vector vecEntryPoint; - QAngle vecEntryAngles; - if ( GetEntryPoint( m_nTransitionSequence, &vecEntryPoint, &vecEntryAngles ) == false ) - return false; - - // Move the entry point forward in time a bit to predict where it'll be - Vector vecVehicleSpeed = m_hVehicle->GetSmoothedVelocity(); - - // Tack on the smoothed velocity - vecEntryPoint += vecVehicleSpeed; // one second - - // Update our entry point - if ( GetOuter()->GetNavigator()->UpdateGoalPos( vecEntryPoint ) == false ) - return false; - - // Reset the goal angles - GetNavigator()->SetArrivalDirection( vecEntryAngles ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorCompanion::RunTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_PASSENGER_RELOAD: - { - if ( GetOuter()->IsSequenceFinished() ) - { - TaskComplete(); - } - } - break; - - case TASK_PASSENGER_IMPACT: - { - if ( GetOuter()->IsSequenceFinished() ) - { - TaskComplete(); - return; - } - } - break; - - case TASK_RUN_TO_VEHICLE_ENTRANCE: - { - // Update our entrance point if we can - if ( UpdateVehicleEntrancePath() == false ) - { - TaskFail("Unable to find entrance to vehicle"); - break; - } - - // See if we're close enough to our goal - if ( GetOuter ()->GetNavigator()->IsGoalActive() == false ) - { - // See if we're close enough now to enter the vehicle - Vector vecEntryPoint; - GetEntryPoint( m_nTransitionSequence, &vecEntryPoint ); - if ( ( vecEntryPoint - GetAbsOrigin() ).Length2DSqr() < Square( 36.0f ) ) - { - if ( GetNavigator()->GetArrivalActivity() != ACT_INVALID ) - { - SetActivity( GetNavigator()->GetArrivalActivity() ); - } - - TaskComplete(); - } - else - { - TaskFail( "Unable to navigate to vehicle" ); - } - } - - // Keep merrily going! - } - break; - - default: - BaseClass::RunTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Add custom interrupt conditions -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorCompanion::BuildScheduleTestBits( void ) -{ - // Always break on being able to exit - if ( GetPassengerState() == PASSENGER_STATE_INSIDE ) - { - GetOuter()->SetCustomInterruptCondition( GetClassScheduleIdSpace()->ConditionLocalToGlobal( COND_PASSENGER_CAN_LEAVE_STUCK_VEHICLE ) ); - GetOuter()->SetCustomInterruptCondition( GetClassScheduleIdSpace()->ConditionLocalToGlobal( COND_PASSENGER_HARD_IMPACT) ); - - if ( IsCurSchedule( SCHED_PASSENGER_OVERTURNED ) == false ) - { - GetOuter()->SetCustomInterruptCondition( GetClassScheduleIdSpace()->ConditionLocalToGlobal( COND_PASSENGER_OVERTURNED ) ); - } - - // Append the ability to break on fidgeting - if ( IsCurSchedule( SCHED_PASSENGER_IDLE ) ) - { - GetOuter()->SetCustomInterruptCondition( GetClassScheduleIdSpace()->ConditionLocalToGlobal( COND_PASSENGER_CAN_FIDGET ) ); - } - - // Add this so we're prompt about exiting the vehicle when able to - if ( m_PassengerIntent == PASSENGER_INTENT_EXIT ) - { - GetOuter()->SetCustomInterruptCondition( GetClassScheduleIdSpace()->ConditionLocalToGlobal( COND_PASSENGER_VEHICLE_STOPPED ) ); - } - } - - BaseClass::BuildScheduleTestBits(); -} -//----------------------------------------------------------------------------- -// Purpose: Determines if the passenger should take a radial route to the goal -// Input : &vecEntryPoint - Point of entry -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PassengerBehaviorCompanion::UseRadialRouteToEntryPoint( const Vector &vecEntryPoint ) -{ - // Get the center position of the vehicle we'll radiate around - Vector vecCenterPos = m_hVehicle->WorldSpaceCenter(); - vecCenterPos.z = vecEntryPoint.z; - - // Find out if we need to go around the vehicle - float flDistToVehicleCenter = ( vecCenterPos - GetOuter()->GetAbsOrigin() ).Length(); - float flDistToGoal = ( vecEntryPoint - GetOuter()->GetAbsOrigin() ).Length(); - if ( flDistToGoal > flDistToVehicleCenter ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Find the arc in degrees to reach our goal position -// Input : &vecCenterPoint - Point around which the arc rotates -// &vecEntryPoint - Point we're trying to reach -// &bClockwise - If we should move clockwise or not to get there -// Output : float - degrees around arc to follow -//----------------------------------------------------------------------------- -float CAI_PassengerBehaviorCompanion::GetArcToEntryPoint( const Vector &vecCenterPoint, const Vector &vecEntryPoint, bool &bClockwise ) -{ - // We want the entry point to be at the same level as the center to make this a two dimensional problem - Vector vecEntryPointAdjusted = vecEntryPoint; - vecEntryPointAdjusted.z = vecCenterPoint.z; - - // Direction from vehicle center to passenger - Vector vecVehicleToPassenger = ( GetOuter()->GetAbsOrigin() - vecCenterPoint ); - VectorNormalize( vecVehicleToPassenger ); - - // Direction from vehicle center to entry point - Vector vecVehicleToEntry = ( vecEntryPointAdjusted - vecCenterPoint ); - VectorNormalize( vecVehicleToEntry ); - - float flVehicleToPassengerYaw = UTIL_VecToYaw( vecVehicleToPassenger ); - float flVehicleToEntryYaw = UTIL_VecToYaw( vecVehicleToEntry ); - float flArcDist = UTIL_AngleDistance( flVehicleToEntryYaw, flVehicleToPassengerYaw ); - - bClockwise = ( flArcDist < 0.0f ); - return fabs( flArcDist ); -} - -//----------------------------------------------------------------------------- -// Purpose: Removes all failed points -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorCompanion::ResetVehicleEntryFailedState( void ) -{ - m_FailedEntryPositions.RemoveAll(); -} - -//----------------------------------------------------------------------------- -// Purpose: Adds a failed position to the list and marks when it occurred -// Input : &vecPosition - Position that failed -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorCompanion::MarkVehicleEntryFailed( const Vector &vecPosition ) -{ - FailPosition_t failPos; - failPos.flTime = gpGlobals->curtime; - failPos.vecPosition = vecPosition; - m_FailedEntryPositions.AddToTail( failPos ); - - // Show this as failed - if ( passenger_debug_entry.GetBool() ) - { - NDebugOverlay::Box( vecPosition, -Vector(8,8,8), Vector(8,8,8), 255, 0, 0, 0, 2.0f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: See if a vector is near enough to a previously failed position -// Input : &vecPosition - position to test -// Output : Returns true if the point is near enough another to be considered equivalent -//----------------------------------------------------------------------------- -bool CAI_PassengerBehaviorCompanion::PointIsWithinEntryFailureRadius( const Vector &vecPosition ) -{ - // Test this point against our known failed points and reject it if it's too near - for ( int i = 0; i < m_FailedEntryPositions.Count(); i++ ) - { - // If our time has expired, kill the position - if ( ( gpGlobals->curtime - m_FailedEntryPositions[i].flTime ) > 3.0f ) - { - // Show that we've cleared it - if ( passenger_debug_entry.GetBool() ) - { - NDebugOverlay::Box( m_FailedEntryPositions[i].vecPosition, -Vector(12,12,12), Vector(12,12,12), 255, 255, 0, 0, 2.0f ); - } - - m_FailedEntryPositions.Remove( i ); - continue; - } - - // See if this position is too near our last failed attempt - if ( ( vecPosition - m_FailedEntryPositions[i].vecPosition ).LengthSqr() < Square(3*12) ) - { - // Show that this was denied - if ( passenger_debug_entry.GetBool() ) - { - NDebugOverlay::Box( m_FailedEntryPositions[i].vecPosition, -Vector(12,12,12), Vector(12,12,12), 255, 0, 0, 128, 2.0f ); - } - - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Find the proper sequence to use (weighted by priority or distance from current position) -// to enter the vehicle. -// Input : bNearest - Use distance as the criteria for a "best" sequence. Otherwise the order of the -// seats is their priority. -// Output : int - sequence index -//----------------------------------------------------------------------------- -int CAI_PassengerBehaviorCompanion::FindEntrySequence( bool bNearest /*= false*/ ) -{ - // Get a list of all our animations - const PassengerSeatAnims_t *pEntryAnims = m_hVehicle->GetServerVehicle()->NPC_GetPassengerSeatAnims( GetOuter(), PASSENGER_SEAT_ENTRY ); - if ( pEntryAnims == NULL ) - return -1; - - // Get the ultimate position we'll end up at - Vector vecStartPos, vecEndPos; - if ( m_hVehicle->GetServerVehicle()->NPC_GetPassengerSeatPosition( GetOuter(), &vecEndPos, NULL ) == false ) - return -1; - - const CPassengerSeatTransition *pTransition; - float flNearestDistSqr = FLT_MAX; - float flSeatDistSqr; - int nNearestSequence = -1; - int nSequence; - - // Test each animation (sorted by priority) for the best match - for ( int i = 0; i < pEntryAnims->Count(); i++ ) - { - // Find the activity for this animation name - pTransition = &pEntryAnims->Element(i); - nSequence = GetOuter()->LookupSequence( STRING( pTransition->GetAnimationName() ) ); - if ( nSequence == -1 ) - continue; - - // Test this entry for validity - if ( GetEntryPoint( nSequence, &vecStartPos ) == false ) - continue; - - // See if this entry position is in our list of known unreachable places - if ( PointIsWithinEntryFailureRadius( vecStartPos ) ) - continue; - - // Check to see if we can use this - if ( IsValidTransitionPoint( vecStartPos, vecEndPos ) ) - { - // If we're just looking for the first, we're done - if ( bNearest == false ) - return nSequence; - - // Otherwise distance is the deciding factor - flSeatDistSqr = ( vecStartPos - GetOuter()->GetAbsOrigin() ).LengthSqr(); - - // Closer, take it - if ( flSeatDistSqr < flNearestDistSqr ) - { - flNearestDistSqr = flSeatDistSqr; - nNearestSequence = nSequence; - } - } - - } - - return nNearestSequence; -} - -//----------------------------------------------------------------------------- -// Purpose: Override certain animations -//----------------------------------------------------------------------------- -Activity CAI_PassengerBehaviorCompanion::NPC_TranslateActivity( Activity activity ) -{ - Activity newActivity = BaseClass::NPC_TranslateActivity( activity ); - - // Handle animations from inside the vehicle - if ( GetPassengerState() == PASSENGER_STATE_INSIDE ) - { - // Alter idle depending on the vehicle's state - if ( newActivity == ACT_IDLE ) - { - // Always play the overturned animation - if ( m_vehicleState.m_bWasOverturned ) - return ACT_PASSENGER_OVERTURNED; - } - } - - return newActivity; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PassengerBehaviorCompanion::CanExitVehicle( void ) -{ - if ( BaseClass::CanExitVehicle() == false ) - return false; - - // If we're tipped too much, we can't exit - Vector vecUp; - GetOuter()->GetVectors( NULL, NULL, &vecUp ); - if ( DotProduct( vecUp, Vector(0,0,1) ) < DOT_45DEGREE ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: NPC needs to get to their marks, so do so with urgent navigation -//----------------------------------------------------------------------------- -bool CAI_PassengerBehaviorCompanion::IsNavigationUrgent( void ) -{ - // If we're running to the vehicle, do so urgently - if ( GetPassengerState() == PASSENGER_STATE_OUTSIDE && m_PassengerIntent == PASSENGER_INTENT_ENTER ) - return true; - - return BaseClass::IsNavigationUrgent(); -} - -//----------------------------------------------------------------------------- -// Purpose: Calculate our body lean based on our delta velocity -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorCompanion::CalculateBodyLean( void ) -{ - // Calculate our lateral displacement from a perfectly centered start - float flLateralDisp = SimpleSplineRemapVal( m_vehicleState.m_vecLastAngles.z, 100.0f, -100.0f, -1.0f, 1.0f ); - flLateralDisp = clamp( flLateralDisp, -1.0f, 1.0f ); - - // FIXME: Framerate dependent! - m_flLastLateralLean = ( m_flLastLateralLean * 0.2f ) + ( flLateralDisp * 0.8f ); - - // Here we can make Alyx do something different on an "extreme" lean condition - if ( fabs( m_flLastLateralLean ) > 0.75f ) - { - // Large lean, make us react? - } - - // Set these parameters - GetOuter()->SetPoseParameter( "vehicle_lean", m_flLastLateralLean ); -} - -//----------------------------------------------------------------------------- -// Purpose: Whether or not we're allowed to fidget -//----------------------------------------------------------------------------- -bool CAI_PassengerBehaviorCompanion::CanFidget( void ) -{ - // Can't fidget again too quickly - if ( m_flNextFidgetTime > gpGlobals->curtime ) - return false; - - // FIXME: Really we want to check our readiness level at this point - if ( GetOuter()->GetEnemy() != NULL ) - return false; - - // Don't fidget unless we're at low readiness - if ( m_hCompanion && ( m_hCompanion->GetReadinessLevel() > AIRL_RELAXED ) ) - return false; - - // Don't fidget while we're in a script - if ( GetOuter()->IsInAScript() || GetOuter()->GetIdealState() == NPC_STATE_SCRIPT || IsRunningScriptedScene( GetOuter() ) ) - return false; - - // If we're upside down, don't bother - if ( HasCondition( COND_PASSENGER_OVERTURNED ) ) - return false; - - // Must be visible to the player - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer && pPlayer->FInViewCone( GetOuter()->EyePosition() ) == false ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Extends the fidget delay by the time specified -// Input : flDuration - in seconds -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorCompanion::ExtendFidgetDelay( float flDuration ) -{ - // If we're already expired, just set this as the next time - if ( m_flNextFidgetTime < gpGlobals->curtime ) - { - m_flNextFidgetTime = gpGlobals->curtime + flDuration; - } - else - { - // Otherwise bump the delay farther into the future - m_flNextFidgetTime += flDuration; - } -} - -//----------------------------------------------------------------------------- -// Purpose: We never want to be marked as crouching when inside a vehicle -//----------------------------------------------------------------------------- -bool CAI_PassengerBehaviorCompanion::IsCrouching( void ) -{ - return false; -} - -AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( CAI_PassengerBehaviorCompanion ) -{ - DECLARE_ACTIVITY( ACT_PASSENGER_IDLE_AIM ) - DECLARE_ACTIVITY( ACT_PASSENGER_RELOAD ) - DECLARE_ACTIVITY( ACT_PASSENGER_OVERTURNED ) - DECLARE_ACTIVITY( ACT_PASSENGER_IMPACT ) - DECLARE_ACTIVITY( ACT_PASSENGER_IMPACT_WEAPON ) - DECLARE_ACTIVITY( ACT_PASSENGER_POINT ) - DECLARE_ACTIVITY( ACT_PASSENGER_POINT_BEHIND ) - DECLARE_ACTIVITY( ACT_PASSENGER_IDLE_READY ) - DECLARE_ACTIVITY( ACT_PASSENGER_GESTURE_JOSTLE_LARGE ) - DECLARE_ACTIVITY( ACT_PASSENGER_GESTURE_JOSTLE_SMALL ) - DECLARE_ACTIVITY( ACT_PASSENGER_GESTURE_JOSTLE_LARGE_STIMULATED ) - DECLARE_ACTIVITY( ACT_PASSENGER_GESTURE_JOSTLE_SMALL_STIMULATED ) - DECLARE_ACTIVITY( ACT_PASSENGER_COWER_IN ) - DECLARE_ACTIVITY( ACT_PASSENGER_COWER_LOOP ) - DECLARE_ACTIVITY( ACT_PASSENGER_COWER_OUT ) - DECLARE_ACTIVITY( ACT_PASSENGER_IDLE_FIDGET ) - - DECLARE_TASK( TASK_GET_PATH_TO_VEHICLE_ENTRY_POINT ) - DECLARE_TASK( TASK_GET_PATH_TO_NEAR_VEHICLE ) - DECLARE_TASK( TASK_PASSENGER_RELOAD ) - DECLARE_TASK( TASK_PASSENGER_EXIT_STUCK_VEHICLE ) - DECLARE_TASK( TASK_PASSENGER_OVERTURNED ) - DECLARE_TASK( TASK_PASSENGER_IMPACT ) - DECLARE_TASK( TASK_RUN_TO_VEHICLE_ENTRANCE ) - - DECLARE_CONDITION( COND_PASSENGER_VEHICLE_MOVED_FROM_MARK ) - DECLARE_CONDITION( COND_PASSENGER_CAN_LEAVE_STUCK_VEHICLE ) - DECLARE_CONDITION( COND_PASSENGER_WARN_OVERTURNED ) - DECLARE_CONDITION( COND_PASSENGER_WARN_COLLISION ) - DECLARE_CONDITION( COND_PASSENGER_CAN_FIDGET ) - DECLARE_CONDITION( COND_PASSENGER_CAN_ENTER_IMMEDIATELY ) - - DEFINE_SCHEDULE - ( - SCHED_PASSENGER_RUN_TO_ENTER_VEHICLE, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_PASSENGER_RUN_TO_ENTER_VEHICLE_FAILED" - " TASK_STOP_MOVING 0" - " TASK_SET_TOLERANCE_DISTANCE 36" // 3 ft - " TASK_SET_ROUTE_SEARCH_TIME 5" - " TASK_GET_PATH_TO_VEHICLE_ENTRY_POINT 0" - " TASK_RUN_TO_VEHICLE_ENTRANCE 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_PASSENGER_ENTER_VEHICLE" - "" - " Interrupts" - " COND_PASSENGER_CAN_ENTER_IMMEDIATELY" - " COND_PASSENGER_CANCEL_ENTER" - ) - - DEFINE_SCHEDULE - ( - SCHED_PASSENGER_RUN_TO_ENTER_VEHICLE_FAILED, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_PASSENGER_ENTER_VEHICLE_PAUSE" - " TASK_STOP_MOVING 0" - " TASK_SET_TOLERANCE_DISTANCE 36" - " TASK_SET_ROUTE_SEARCH_TIME 3" - " TASK_GET_PATH_TO_NEAR_VEHICLE 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_PASSENGER_CANCEL_ENTER" - ) - - DEFINE_SCHEDULE - ( - SCHED_PASSENGER_ENTER_VEHICLE_PAUSE, - - " Tasks" - " TASK_STOP_MOVING 1" - " TASK_FACE_TARGET 0" - " TASK_WAIT 2" - "" - " Interrupts" - " COND_LIGHT_DAMAGE" - " COND_NEW_ENEMY" - " COND_PASSENGER_CANCEL_ENTER" - ) - - DEFINE_SCHEDULE - ( - SCHED_PASSENGER_RANGE_ATTACK1, - - " Tasks" - " TASK_ANNOUNCE_ATTACK 1" // 1 = primary attack - " TASK_RANGE_ATTACK1 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_ENEMY_OCCLUDED" - " COND_NO_PRIMARY_AMMO" - " COND_HEAR_DANGER" - " COND_WEAPON_BLOCKED_BY_FRIEND" - " COND_WEAPON_SIGHT_OCCLUDED" - ) - - DEFINE_SCHEDULE - ( - SCHED_PASSENGER_EXIT_STUCK_VEHICLE, - - " Tasks" - " TASK_PASSENGER_EXIT_STUCK_VEHICLE 0" - "" - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_PASSENGER_RELOAD, - - " Tasks" - " TASK_PASSENGER_RELOAD 0" - "" - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_PASSENGER_OVERTURNED, - - " Tasks" - " TASK_PASSENGER_OVERTURNED 0" - "" - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_PASSENGER_IMPACT, - - " Tasks" - " TASK_PASSENGER_IMPACT 0" - "" - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_PASSENGER_ENTER_VEHICLE_IMMEDIATELY, - - " Tasks" - " TASK_PASSENGER_ATTACH_TO_VEHICLE 0" - " TASK_PASSENGER_ENTER_VEHICLE 0" - "" - " Interrupts" - " COND_NO_CUSTOM_INTERRUPTS" - ) - - DEFINE_SCHEDULE - ( - SCHED_PASSENGER_COWER, - - " Tasks" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_PASSENGER_COWER_IN" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_PASSENGER_COWER_LOOP" - " TASK_WAIT_UNTIL_NO_DANGER_SOUND 0" - " TASK_WAIT 2" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_PASSENGER_COWER_OUT" - "" - " Interrupts" - " COND_NO_CUSTOM_INTERRUPTS" - ) - - DEFINE_SCHEDULE - ( - SCHED_PASSENGER_FIDGET, - - " Tasks" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_PASSENGER_IDLE_FIDGET" - "" - " Interrupts" - " COND_NO_CUSTOM_INTERRUPTS" - ) - - AI_END_CUSTOM_SCHEDULE_PROVIDER() -} diff --git a/game/server/episodic/ai_behavior_passenger_companion.h b/game/server/episodic/ai_behavior_passenger_companion.h deleted file mode 100644 index af6b70ad1..000000000 --- a/game/server/episodic/ai_behavior_passenger_companion.h +++ /dev/null @@ -1,168 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef AI_BEHAVIOR_PASSENGER_COMPANION_H -#define AI_BEHAVIOR_PASSENGER_COMPANION_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_behavior_passenger.h" - -class CNPC_PlayerCompanion; - -struct VehicleAvoidParams_t -{ - Vector vecStartPos; - Vector vecGoalPos; - Vector *pNodePositions; - int nNumNodes; - int nDirection; - int nStartNode; - int nEndNode; -}; - -struct FailPosition_t -{ - Vector vecPosition; - float flTime; - - DECLARE_SIMPLE_DATADESC(); -}; - -class CAI_PassengerBehaviorCompanion : public CAI_PassengerBehavior -{ - DECLARE_CLASS( CAI_PassengerBehaviorCompanion, CAI_PassengerBehavior ); - DECLARE_DATADESC() - -public: - - CAI_PassengerBehaviorCompanion( void ); - - enum - { - // Schedules - SCHED_PASSENGER_RUN_TO_ENTER_VEHICLE = BaseClass::NEXT_SCHEDULE, - SCHED_PASSENGER_RUN_TO_ENTER_VEHICLE_FAILED, - SCHED_PASSENGER_ENTER_VEHICLE_PAUSE, - SCHED_PASSENGER_RANGE_ATTACK1, - SCHED_PASSENGER_RELOAD, - SCHED_PASSENGER_EXIT_STUCK_VEHICLE, - SCHED_PASSENGER_OVERTURNED, - SCHED_PASSENGER_IMPACT, - SCHED_PASSENGER_ENTER_VEHICLE_IMMEDIATELY, - SCHED_PASSENGER_COWER, - SCHED_PASSENGER_FIDGET, - NEXT_SCHEDULE, - - // Tasks - TASK_GET_PATH_TO_VEHICLE_ENTRY_POINT = BaseClass::NEXT_TASK, - TASK_GET_PATH_TO_NEAR_VEHICLE, - TASK_PASSENGER_RELOAD, - TASK_PASSENGER_EXIT_STUCK_VEHICLE, - TASK_PASSENGER_OVERTURNED, - TASK_PASSENGER_IMPACT, - TASK_RUN_TO_VEHICLE_ENTRANCE, - NEXT_TASK, - - // Conditions - - COND_PASSENGER_CAN_LEAVE_STUCK_VEHICLE = BaseClass::NEXT_CONDITION, - COND_PASSENGER_WARN_OVERTURNED, - COND_PASSENGER_WARN_COLLISION, - COND_PASSENGER_VEHICLE_MOVED_FROM_MARK, - COND_PASSENGER_CAN_FIDGET, - COND_PASSENGER_CAN_ENTER_IMMEDIATELY, - NEXT_CONDITION, - }; - - virtual bool CanSelectSchedule( void ); - virtual void Enable( CPropJeepEpisodic *pVehicle, bool bImmediateEnter = false); - virtual void GatherConditions( void ); - virtual int SelectSchedule( void ); - virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ); - virtual void StartTask( const Task_t *pTask ); - virtual void RunTask( const Task_t *pTask ); - virtual void AimGun( void ); - virtual void EnterVehicle( void ); - virtual void ExitVehicle( void ); - virtual void FinishEnterVehicle( void ); - virtual void FinishExitVehicle( void ); - virtual void BuildScheduleTestBits( void ); - virtual Activity NPC_TranslateActivity( Activity activity ); - virtual bool CanExitVehicle( void ); - virtual bool IsValidEnemy( CBaseEntity *pEntity ); - virtual void OnUpdateShotRegulator( void ); - virtual bool IsNavigationUrgent( void ); - virtual bool IsCurTaskContinuousMove( void ); - virtual bool IsCrouching( void ); - -private: - - void SpeakVehicleConditions( void ); - virtual void OnExitVehicleFailed( void ); - - bool CanFidget( void ); - bool UseRadialRouteToEntryPoint( const Vector &vecEntryPoint ); - float GetArcToEntryPoint( const Vector &vecCenterPoint, const Vector &vecEntryPoint, bool &bClockwise ); - int SelectScheduleInsideVehicle( void ); - int SelectScheduleOutsideVehicle( void ); - bool FindPathToVehicleEntryPoint( void ); - bool CanEnterVehicleImmediately( int *pResultSequence, Vector *pResultPos, QAngle *pResultAngles ); - void EnterVehicleImmediately( void ); - - // ------------------------------------------ - // Passenger sensing - // ------------------------------------------ - - virtual void GatherVehicleStateConditions( void ); - - float GetVehicleSpeed( void ); - void GatherVehicleCollisionConditions( const Vector &localVelocity ); - - // ------------------------------------------ - // Overturned tracking - // ------------------------------------------ - void UpdateStuckStatus( void ); - bool CanExitAtPosition( const Vector &vecTestPos ); - bool GetStuckExitPos( Vector *vecResult ); - bool ExitStuckVehicle( void ); - - bool UpdateVehicleEntrancePath( void ); - bool PointIsWithinEntryFailureRadius( const Vector &vecPosition ); - void ResetVehicleEntryFailedState( void ); - void MarkVehicleEntryFailed( const Vector &vecPosition ); - virtual int FindEntrySequence( bool bNearest = false ); - void CalculateBodyLean( void ); - - float m_flNextJostleTime; - float m_flNextOverturnWarning; // The next time the NPC may complained about being upside-down - float m_flOverturnedDuration; // Amount of time we've been stuck in the vehicle (unable to exit) - float m_flUnseenDuration; // Amount of time we've been hidden from the player's view - - float m_flEnterBeginTime; // Time the NPC started to try and enter the vehicle - int m_nExitAttempts; // Number of times we've attempted to exit the vehicle but failed - int m_nVisibleEnemies; // Keeps a record of how many enemies I know about - float m_flLastLateralLean; // Our last lean value - - CAI_MoveMonitor m_VehicleMonitor; // Used to keep track of the vehicle's movement relative to a mark - CUtlVector m_FailedEntryPositions; // Used to keep track of the vehicle's movement relative to a mark - -protected: - virtual int SelectTransitionSchedule( void ); - - void ExtendFidgetDelay( float flDuration ); - bool CanPlayJostle( bool bLargeJostle ); - - float m_flEntraceUpdateTime; - float m_flNextEnterAttempt; - float m_flNextFidgetTime; - CHandle< CNPC_PlayerCompanion > m_hCompanion; - - DEFINE_CUSTOM_SCHEDULE_PROVIDER; -}; - -#endif // AI_BEHAVIOR_PASSENGER_COMPANION_H diff --git a/game/server/episodic/ai_behavior_passenger_zombie.cpp b/game/server/episodic/ai_behavior_passenger_zombie.cpp deleted file mode 100644 index db25f78b9..000000000 --- a/game/server/episodic/ai_behavior_passenger_zombie.cpp +++ /dev/null @@ -1,878 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: Zombies on cars! -// -//============================================================================= - -#include "cbase.h" -#include "npcevent.h" -#include "ai_motor.h" -#include "ai_senses.h" -#include "vehicle_jeep_episodic.h" -#include "npc_alyx_episodic.h" -#include "ai_behavior_passenger_zombie.h" - -#define JUMP_ATTACH_DIST_THRESHOLD 1000 -#define JUMP_ATTACH_FACING_THRESHOLD DOT_45DEGREE - -#define ATTACH_PREDICTION_INTERVAL 0.2f -#define ATTACH_PREDICTION_FACING_THRESHOLD 0.75f -#define ATTACH_PREDICTION_DIST_THRESHOLD 128 - -int ACT_PASSENGER_MELEE_ATTACK1; -int ACT_PASSENGER_THREATEN; -int ACT_PASSENGER_FLINCH; -int ACT_PASSENGER_ZOMBIE_LEAP_LOOP; - -BEGIN_DATADESC( CAI_PassengerBehaviorZombie ) - - DEFINE_FIELD( m_flLastVerticalLean, FIELD_FLOAT ), - DEFINE_FIELD( m_flLastLateralLean, FIELD_FLOAT ), - DEFINE_FIELD( m_flNextLeapTime, FIELD_TIME ), - -END_DATADESC(); - -extern int AE_PASSENGER_PHYSICS_PUSH; - -//============================================================================================== -// Passenger damage table -//============================================================================================== -static impactentry_t zombieLinearTable[] = -{ - { 200*200, 100 }, -}; - -static impactentry_t zombieAngularTable[] = -{ - { 100*100, 100 }, -}; - -impactdamagetable_t gZombiePassengerImpactDamageTable = -{ - zombieLinearTable, - zombieAngularTable, - - ARRAYSIZE(zombieLinearTable), - ARRAYSIZE(zombieAngularTable), - - 24*24, // minimum linear speed squared - 360*360, // minimum angular speed squared (360 deg/s to cause spin/slice damage) - 2, // can't take damage from anything under 2kg - - 5, // anything less than 5kg is "small" - 5, // never take more than 5 pts of damage from anything under 5kg - 36*36, // <5kg objects must go faster than 36 in/s to do damage - - VPHYSICS_LARGE_OBJECT_MASS, // large mass in kg - 4, // large mass scale (anything over 500kg does 4X as much energy to read from damage table) - 5, // large mass falling scale (emphasize falling/crushing damage over sideways impacts since the stress will kill you anyway) - 0.0f, // min vel -}; - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CAI_PassengerBehaviorZombie::CAI_PassengerBehaviorZombie( void ) : -m_flLastLateralLean( 0.0f ), -m_flLastVerticalLean( 0.0f ), -m_flNextLeapTime( 0.0f ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PassengerBehaviorZombie::CanEnterVehicle( void ) -{ - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Translate into vehicle passengers -//----------------------------------------------------------------------------- -int CAI_PassengerBehaviorZombie::TranslateSchedule( int scheduleType ) -{ - // We do different animations when inside the vehicle - if ( GetPassengerState() == PASSENGER_STATE_INSIDE ) - { - if ( scheduleType == SCHED_MELEE_ATTACK1 ) - return SCHED_PASSENGER_ZOMBIE_MELEE_ATTACK1; - - if ( scheduleType == SCHED_RANGE_ATTACK1 ) - return SCHED_PASSENGER_ZOMBIE_RANGE_ATTACK1; - } - - return BaseClass::TranslateSchedule( scheduleType ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : activity - -// Output : Activity -//----------------------------------------------------------------------------- -Activity CAI_PassengerBehaviorZombie::NPC_TranslateActivity( Activity activity ) -{ - Activity nNewActivity = BaseClass::NPC_TranslateActivity( activity ); - if ( activity == ACT_IDLE ) - return (Activity) ACT_PASSENGER_IDLE; - - return nNewActivity; -} - -//----------------------------------------------------------------------------- -// Purpose: Suppress melee attacks against enemies for the given duration -// Input : flDuration - Amount of time to suppress the attacks -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorZombie::SuppressAttack( float flDuration ) -{ - GetOuter()->SetNextAttack( gpGlobals->curtime + flDuration ); -} - -//----------------------------------------------------------------------------- -// Purpose: Determines if an enemy is inside a vehicle or not -// Output : Returns true if the enemy is outside the vehicle. -//----------------------------------------------------------------------------- -bool CAI_PassengerBehaviorZombie::EnemyInVehicle( void ) -{ - // Obviously they're not... - if ( GetOuter()->GetEnemy() == NULL ) - return false; - - // See if they're in a vehicle, currently - CBaseCombatCharacter *pCCEnemy = GetOuter()->GetEnemy()->MyCombatCharacterPointer(); - if ( pCCEnemy && pCCEnemy->IsInAVehicle() ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Select a schedule when we're outside of the vehicle -//----------------------------------------------------------------------------- -int CAI_PassengerBehaviorZombie::SelectOutsideSchedule( void ) -{ - // Attaching to target - if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - return SCHED_PASSENGER_ZOMBIE_RANGE_ATTACK1; - - // Attack the player if we're able - if ( HasCondition( COND_CAN_MELEE_ATTACK1 ) ) - return SCHED_MELEE_ATTACK1; - - // Attach to the vehicle - if ( HasCondition( COND_PASSENGER_ZOMBIE_CAN_ATTACH_TO_VEHICLE ) ) - return SCHED_PASSENGER_ZOMBIE_ATTACH; - - // Otherwise chase after him - return SCHED_PASSENGER_ZOMBIE_RUN_TO_VEHICLE; -} - -//----------------------------------------------------------------------------- -// Purpose: Pick a schedule for being "inside" the vehicle -//----------------------------------------------------------------------------- -int CAI_PassengerBehaviorZombie::SelectInsideSchedule( void ) -{ - // Attacking target - if ( HasCondition( COND_CAN_MELEE_ATTACK1 ) ) - return SCHED_PASSENGER_ZOMBIE_MELEE_ATTACK1; - - return SCHED_IDLE_STAND; -} - -//----------------------------------------------------------------------------- -// Purpose: Move the zombie to the vehicle -//----------------------------------------------------------------------------- -int CAI_PassengerBehaviorZombie::SelectSchedule( void ) -{ - // See if our enemy got out - if ( GetOuter()->GetEnemy() != NULL && EnemyInVehicle() == false ) - { - if ( GetPassengerState() == PASSENGER_STATE_INSIDE ) - { - // Exit the vehicle - SetCondition( COND_PASSENGER_EXITING ); - } - else if ( GetPassengerState() == PASSENGER_STATE_OUTSIDE ) - { - // Our target has left the vehicle and we're outside as well, so give up - Disable(); - return BaseClass::SelectSchedule(); - } - } - - // Entering schedule - if ( HasCondition( COND_PASSENGER_ENTERING ) ) - { - ClearCondition( COND_PASSENGER_ENTERING ); - return SCHED_PASSENGER_ZOMBIE_ENTER_VEHICLE; - } - - // Exiting schedule - if ( HasCondition( COND_PASSENGER_EXITING ) ) - { - ClearCondition( COND_PASSENGER_EXITING ); - return SCHED_PASSENGER_ZOMBIE_EXIT_VEHICLE; - } - - // Select different schedules based on our state - PassengerState_e nState = GetPassengerState(); - int nNewSchedule = SCHED_NONE; - - if ( nState == PASSENGER_STATE_INSIDE ) - { - nNewSchedule = SelectInsideSchedule(); - if ( nNewSchedule != SCHED_NONE ) - return nNewSchedule; - } - else if ( nState == PASSENGER_STATE_OUTSIDE ) - { - nNewSchedule = SelectOutsideSchedule(); - if ( nNewSchedule != SCHED_NONE ) - return nNewSchedule; - } - - // Worst case he just stands here - Assert(0); - return SCHED_IDLE_STAND; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PassengerBehaviorZombie::CanJumpToAttachToVehicle( void ) -{ - // FIXME: Probably move this up one level and out of this function - if ( m_flNextLeapTime > gpGlobals->curtime ) - return false; - - // Predict an attachment jump - CBaseEntity *pEnemy = GetOuter()->GetEnemy(); - - Vector vecPredictedPosition; - UTIL_PredictedPosition( pEnemy, 1.0f, &vecPredictedPosition ); - - float flDist = UTIL_DistApprox( vecPredictedPosition, GetOuter()->GetAbsOrigin() ); - - // If we're facing them enough, allow the jump - if ( ( flDist < JUMP_ATTACH_DIST_THRESHOLD ) && UTIL_IsFacingWithinTolerance( GetOuter(), pEnemy, JUMP_ATTACH_FACING_THRESHOLD ) ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Determine if we can jump to be on the enemy's vehicle -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -inline bool CAI_PassengerBehaviorZombie::CanBeOnEnemyVehicle( void ) -{ - CBaseCombatCharacter *pEnemy = ToBaseCombatCharacter( GetOuter()->GetEnemy() ); - if ( pEnemy != NULL ) - { - IServerVehicle *pVehicle = pEnemy->GetVehicle(); - if ( pVehicle && pVehicle->NPC_HasAvailableSeat( GetRoleName() ) ) - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorZombie::GatherConditions( void ) -{ - BaseClass::GatherConditions(); - - // Always clear the base conditions - ClearCondition( COND_CAN_MELEE_ATTACK1 ); - - // Behavior when outside the vehicle - if ( GetPassengerState() == PASSENGER_STATE_OUTSIDE ) - { - if ( CanBeOnEnemyVehicle() && CanJumpToAttachToVehicle() ) - { - SetCondition( COND_CAN_RANGE_ATTACK1 ); - } - - // Determine if we can latch on to the vehicle (out of sight) - ClearCondition( COND_PASSENGER_ZOMBIE_CAN_ATTACH_TO_VEHICLE ); - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - - if ( pPlayer != NULL && - GetOuter()->GetEnemy() == pPlayer && - pPlayer->GetVehicleEntity() == m_hVehicle ) - { - // Can't be visible to the player and must be close enough - bool bNotVisibleToPlayer = ( pPlayer->FInViewCone( GetOuter() ) == false ); - float flDistSqr = ( pPlayer->GetAbsOrigin() - GetOuter()->GetAbsOrigin() ).LengthSqr(); - bool bInRange = ( flDistSqr < Square(250.0f) ); - if ( bNotVisibleToPlayer && bInRange ) - { - // We can latch on and "enter" the vehicle - SetCondition( COND_PASSENGER_ZOMBIE_CAN_ATTACH_TO_VEHICLE ); - } - else if ( bNotVisibleToPlayer == false && flDistSqr < Square(128.0f) ) - { - // Otherwise just hit the vehicle in anger - SetCondition( COND_CAN_MELEE_ATTACK1 ); - } - } - } - - // Behavior when on the car - if ( GetPassengerState() == PASSENGER_STATE_INSIDE ) - { - // Check for melee attack - if ( GetOuter()->GetNextAttack() < gpGlobals->curtime ) - { - SetCondition( COND_CAN_MELEE_ATTACK1 ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Handle death case -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorZombie::Event_Killed( const CTakeDamageInfo &info ) -{ - if ( m_hVehicle ) - { - // Stop taking messages from the vehicle - m_hVehicle->RemovePhysicsChild( GetOuter() ); - m_hVehicle->NPC_RemovePassenger( GetOuter() ); - m_hVehicle->NPC_FinishedExitVehicle( GetOuter(), false ); - } - - BaseClass::Event_Killed( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: Build our custom interrupt cases for the behavior -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorZombie::BuildScheduleTestBits( void ) -{ - // Always interrupt when we need to get in or out - if ( GetPassengerState() == PASSENGER_STATE_OUTSIDE ) - { - GetOuter()->SetCustomInterruptCondition( GetClassScheduleIdSpace()->ConditionLocalToGlobal( COND_CAN_RANGE_ATTACK1 ) ); - GetOuter()->SetCustomInterruptCondition( GetClassScheduleIdSpace()->ConditionLocalToGlobal( COND_PASSENGER_ENTERING ) ); - } - - BaseClass::BuildScheduleTestBits(); -} - -//----------------------------------------------------------------------------- -// Purpose: Get the absolute position of the desired attachment point -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorZombie::GetAttachmentPoint( Vector *vecPoint ) -{ - Vector vecEntryOffset, vecFinalOffset; - GetEntryTarget( &vecEntryOffset, NULL ); - VectorRotate( vecEntryOffset, m_hVehicle->GetAbsAngles(), vecFinalOffset ); - *vecPoint = ( m_hVehicle->GetAbsOrigin() + vecFinalOffset ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -int CAI_PassengerBehaviorZombie::FindExitSequence( void ) -{ - // Get a list of all our animations - const PassengerSeatAnims_t *pExitAnims = m_hVehicle->GetServerVehicle()->NPC_GetPassengerSeatAnims( GetOuter(), PASSENGER_SEAT_EXIT ); - if ( pExitAnims == NULL ) - return -1; - - // Test each animation (sorted by priority) for the best match - for ( int i = 0; i < pExitAnims->Count(); i++ ) - { - // Find the activity for this animation name - int nSequence = GetOuter()->LookupSequence( STRING( pExitAnims->Element(i).GetAnimationName() ) ); - Assert( nSequence != -1 ); - if ( nSequence == -1 ) - continue; - - return nSequence; - } - - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorZombie::StartDismount( void ) -{ - // Leap off the vehicle - int nSequence = FindExitSequence(); - Assert( nSequence != -1 ); - - SetTransitionSequence( nSequence ); - GetOuter()->SetIdealActivity( ACT_SCRIPT_CUSTOM_MOVE ); - - // This removes the NPC from the vehicle's handling and fires all necessary outputs - m_hVehicle->RemovePhysicsChild( GetOuter() ); - m_hVehicle->NPC_RemovePassenger( GetOuter() ); - m_hVehicle->NPC_FinishedExitVehicle( GetOuter(), (IsPassengerHostile()==false) ); - - // Detach from the parent - GetOuter()->SetParent( NULL ); - GetOuter()->SetMoveType( MOVETYPE_STEP ); - GetMotor()->SetYawLocked( false ); - - QAngle vecAngles = GetAbsAngles(); - vecAngles.z = 0.0f; - GetOuter()->SetAbsAngles( vecAngles ); - - // HACK: Will this work? - IPhysicsObject *pPhysObj = GetOuter()->VPhysicsGetObject(); - if ( pPhysObj != NULL ) - { - pPhysObj->EnableCollisions( true ); - } - - // Clear this - m_PassengerIntent = PASSENGER_INTENT_NONE; - SetPassengerState( PASSENGER_STATE_EXITING ); - - // Get the velocity - Vector vecUp, vecJumpDir; - GetOuter()->GetVectors( &vecJumpDir, NULL, &vecUp ); - - // Move back and up - vecJumpDir *= random->RandomFloat( -400.0f, -500.0f ); - vecJumpDir += vecUp * 150.0f; - GetOuter()->SetAbsVelocity( vecJumpDir ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorZombie::FinishDismount( void ) -{ - SetPassengerState( PASSENGER_STATE_OUTSIDE ); - Disable(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorZombie::StartTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_FACE_HINTNODE: - case TASK_FACE_LASTPOSITION: - case TASK_FACE_SAVEPOSITION: - case TASK_FACE_TARGET: - case TASK_FACE_IDEAL: - case TASK_FACE_SCRIPT: - case TASK_FACE_PATH: - TaskComplete(); - break; - - case TASK_PASSENGER_ZOMBIE_RANGE_ATTACK1: - break; - - case TASK_MELEE_ATTACK1: - { - // Only override this if we're "in" the vehicle - if ( GetPassengerState() != PASSENGER_STATE_INSIDE ) - { - BaseClass::StartTask( pTask ); - break; - } - - // Swipe - GetOuter()->SetIdealActivity( (Activity) ACT_PASSENGER_MELEE_ATTACK1 ); - - // Randomly attack again in the future - float flWait = random->RandomFloat( 0.0f, 1.0f ); - SuppressAttack( flWait ); - } - break; - - case TASK_PASSENGER_ZOMBIE_DISMOUNT: - { - // Start the process of dismounting from the vehicle - StartDismount(); - } - break; - - case TASK_PASSENGER_ZOMBIE_ATTACH: - { - if ( AttachToVehicle() ) - { - TaskComplete(); - return; - } - - TaskFail( "Unable to attach to vehicle!" ); - } - break; - - default: - BaseClass::StartTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Handle task running -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorZombie::RunTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_PASSENGER_ZOMBIE_RANGE_ATTACK1: - { - // Face the entry point - Vector vecAttachPoint; - GetAttachmentPoint( &vecAttachPoint ); - GetOuter()->GetMotor()->SetIdealYawToTarget( vecAttachPoint ); - - // All done when you touch the ground - if ( GetOuter()->GetFlags() & FL_ONGROUND ) - { - m_flNextLeapTime = gpGlobals->curtime + 2.0f; - TaskComplete(); - return; - } - } - break; - - case TASK_MELEE_ATTACK1: - - if ( GetOuter()->IsSequenceFinished() ) - { - TaskComplete(); - } - - break; - - case TASK_PASSENGER_ZOMBIE_DISMOUNT: - { - if ( GetOuter()->IsSequenceFinished() ) - { - // Completely separate from the vehicle - FinishDismount(); - TaskComplete(); - } - - break; - } - - default: - BaseClass::RunTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Find the relative cost of an entry point based on facing -// Input : &vecEntryPos - Position we're evaluating -// Output : Returns the cost as a modified distance value -//----------------------------------------------------------------------------- -float CAI_PassengerBehaviorZombie::GetEntryPointCost( const Vector &vecEntryPos ) -{ - // FIXME: We don't care about cost any longer! - return 1.0f; - - // Find the direction from us to the entry point - Vector vecEntryDir = ( vecEntryPos - GetAbsOrigin() ); - float flCost = VectorNormalize( vecEntryDir ); - - // Get our current facing - Vector vecDir; - GetOuter()->GetVectors( &vecDir, NULL, NULL ); - - // Scale our cost by how closely it matches our facing - float flDot = DotProduct( vecEntryDir, vecDir ); - if ( flDot < 0.0f ) - return FLT_MAX; - - flCost *= RemapValClamped( flDot, 1.0f, 0.0f, 1.0f, 2.0f ); - - return flCost; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : bNearest - -// Output : int -//----------------------------------------------------------------------------- -int CAI_PassengerBehaviorZombie::FindEntrySequence( bool bNearest /*= false*/ ) -{ - // Get a list of all our animations - const PassengerSeatAnims_t *pEntryAnims = m_hVehicle->GetServerVehicle()->NPC_GetPassengerSeatAnims( GetOuter(), PASSENGER_SEAT_ENTRY ); - if ( pEntryAnims == NULL ) - return -1; - - Vector vecStartPos; - const CPassengerSeatTransition *pTransition; - float flBestCost = FLT_MAX; - float flCost; - int nBestSequence = -1; - int nSequence = -1; - - // Test each animation (sorted by priority) for the best match - for ( int i = 0; i < pEntryAnims->Count(); i++ ) - { - // Find the activity for this animation name - pTransition = &pEntryAnims->Element(i); - nSequence = GetOuter()->LookupSequence( STRING( pTransition->GetAnimationName() ) ); - - Assert( nSequence != -1 ); - if ( nSequence == -1 ) - continue; - - // Test this entry for validity - GetEntryPoint( nSequence, &vecStartPos ); - - // Evaluate the cost - flCost = GetEntryPointCost( vecStartPos ); - if ( flCost < flBestCost ) - { - nBestSequence = nSequence; - flBestCost = flCost; - continue; - } - } - - return nBestSequence; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorZombie::ExitVehicle( void ) -{ - BaseClass::ExitVehicle(); - - // Remove us as a passenger - m_hVehicle->NPC_RemovePassenger( GetOuter() ); - m_hVehicle->NPC_FinishedExitVehicle( GetOuter(), false ); - -} - -//----------------------------------------------------------------------------- -// Purpose: Calculate our body lean based on our delta velocity -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorZombie::CalculateBodyLean( void ) -{ - // Calculate our lateral displacement from a perfectly centered start - float flLateralDisp = SimpleSplineRemapVal( m_vehicleState.m_vecLastAngles.z, 100.0f, -100.0f, -1.0f, 1.0f ); - flLateralDisp = clamp( flLateralDisp, -1.0f, 1.0f ); - - // FIXME: Framerate dependant! - m_flLastLateralLean = ( m_flLastLateralLean * 0.2f ) + ( flLateralDisp * 0.8f ); - - // Factor in a "stun" if the zombie was moved too far off course - if ( fabs( m_flLastLateralLean ) > 0.75f ) - { - SuppressAttack( 0.5f ); - } - - // Calc our vertical displacement - float flVerticalDisp = SimpleSplineRemapVal( m_vehicleState.m_vecDeltaVelocity.z, -50.0f, 50.0f, -1.0f, 1.0f ); - flVerticalDisp = clamp( flVerticalDisp, -1.0f, 1.0f ); - - // FIXME: Framerate dependant! - m_flLastVerticalLean = ( m_flLastVerticalLean * 0.75f ) + ( flVerticalDisp * 0.25f ); - - // Set these parameters - GetOuter()->SetPoseParameter( "lean_lateral", m_flLastLateralLean ); - GetOuter()->SetPoseParameter( "lean_vertical", m_flLastVerticalLean ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorZombie::GatherVehicleStateConditions( void ) -{ - // Call to the base - BaseClass::GatherVehicleStateConditions(); - - // Only do this if we're on the vehicle - if ( GetPassengerState() != PASSENGER_STATE_INSIDE ) - return; - - // Calculate how our body is leaning - CalculateBodyLean(); - - // The forward delta of the vehicle - float flLateralDelta = ( m_vehicleState.m_vecDeltaVelocity.x + m_vehicleState.m_vecDeltaVelocity.y ); - - // Detect a sudden stop - if ( flLateralDelta < -350.0f ) - { - if ( m_hVehicle ) - { - Vector vecDamageForce; - m_hVehicle->GetVelocity( &vecDamageForce, NULL ); - VectorNormalize( vecDamageForce ); - vecDamageForce *= random->RandomFloat( 50000.0f, 60000.0f ); - - //NDebugOverlay::HorzArrow( GetAbsOrigin(), GetAbsOrigin() + ( vecDamageForce * 256.0f ), 16.0f, 255, 0, 0, 16, true, 2.0f ); - - // Fake it! - CTakeDamageInfo info( m_hVehicle, m_hVehicle, vecDamageForce, GetOuter()->WorldSpaceCenter(), 200, (DMG_CRUSH|DMG_VEHICLE) ); - GetOuter()->TakeDamage( info ); - } - } - else if ( flLateralDelta < -150.0f ) - { - // FIXME: Realistically this should interrupt and play a schedule to do it - GetOuter()->SetIdealActivity( (Activity) ACT_PASSENGER_FLINCH ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEvent - -//----------------------------------------------------------------------------- -void CAI_PassengerBehaviorZombie::HandleAnimEvent( animevent_t *pEvent ) -{ - if ( pEvent->event == AE_PASSENGER_PHYSICS_PUSH ) - { - // Add a push into the vehicle - float flForce = (float) atof( pEvent->options ); - AddPhysicsPush( flForce * 0.75f ); - return; - } - - BaseClass::HandleAnimEvent( pEvent ); -} - -//----------------------------------------------------------------------------- -// Purpose: Attach to the vehicle if we're able -//----------------------------------------------------------------------------- -bool CAI_PassengerBehaviorZombie::AttachToVehicle( void ) -{ - // Must be able to enter the vehicle - if ( m_hVehicle->NPC_CanEnterVehicle( GetOuter(), false ) == false ) - return false; - - // Reserve the seat - if ( ReserveEntryPoint( VEHICLE_SEAT_ANY ) == false ) - return false; - - // Use the best one we've found - int nSequence = FindEntrySequence(); - if ( nSequence == -1 ) - return false; - - // Take the transition sequence - SetTransitionSequence( nSequence ); - - // Get in the vehicle - EnterVehicle(); - - // Start our scripted sequence with any other passengers - // Find Alyx - // TODO: Iterate through the list of passengers in the vehicle and find one we can interact with - CNPC_Alyx *pAlyx = CNPC_Alyx::GetAlyx(); - if ( pAlyx ) - { - // Tell Alyx to play along! - pAlyx->ForceVehicleInteraction( GetOuter()->GetSequenceName( nSequence ), GetOuter() ); - } - - return true; -} - -AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( CAI_PassengerBehaviorZombie ) -{ - DECLARE_ACTIVITY( ACT_PASSENGER_MELEE_ATTACK1 ) - DECLARE_ACTIVITY( ACT_PASSENGER_THREATEN ) - DECLARE_ACTIVITY( ACT_PASSENGER_FLINCH ) - DECLARE_ACTIVITY( ACT_PASSENGER_ZOMBIE_LEAP_LOOP ) - - DECLARE_TASK( TASK_PASSENGER_ZOMBIE_RANGE_ATTACK1 ) - DECLARE_TASK( TASK_PASSENGER_ZOMBIE_DISMOUNT ) - DECLARE_TASK( TASK_PASSENGER_ZOMBIE_ATTACH ) - - DECLARE_CONDITION( COND_PASSENGER_ZOMBIE_CAN_ATTACH_TO_VEHICLE ) - - DEFINE_SCHEDULE - ( - SCHED_PASSENGER_ZOMBIE_ENTER_VEHICLE, - - " Tasks" - " TASK_PASSENGER_ATTACH_TO_VEHICLE 0" - " TASK_PASSENGER_ENTER_VEHICLE 0" - "" - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_PASSENGER_ZOMBIE_EXIT_VEHICLE, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_PASSENGER_IDLE" - " TASK_STOP_MOVING 0" - " TASK_PASSENGER_ZOMBIE_DISMOUNT 0" - "" - " Interrupts" - " COND_TASK_FAILED" - ) - - DEFINE_SCHEDULE - ( - SCHED_PASSENGER_ZOMBIE_MELEE_ATTACK1, - - " Tasks" - " TASK_ANNOUNCE_ATTACK 1" - " TASK_MELEE_ATTACK1 0" - "" - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_PASSENGER_ZOMBIE_RANGE_ATTACK1, - - " Tasks" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_PASSENGER_RANGE_ATTACK1" - " TASK_SET_ACTIVITY ACTIVITY:ACT_PASSENGER_ZOMBIE_LEAP_LOOP" - " TASK_PASSENGER_ZOMBIE_RANGE_ATTACK1 0" - " " - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_PASSENGER_ZOMBIE_RUN_TO_VEHICLE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY_FAILED" - " TASK_GET_CHASE_PATH_TO_ENEMY 2400" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_ENEMY_UNREACHABLE" - " COND_TASK_FAILED" - " COND_LOST_ENEMY" - " COND_PASSENGER_ZOMBIE_CAN_ATTACH_TO_VEHICLE" - ) - - DEFINE_SCHEDULE - ( - SCHED_PASSENGER_ZOMBIE_ATTACH, - - " Tasks" - " TASK_PASSENGER_ZOMBIE_ATTACH 0" - "" - " Interrupts" - ) - - AI_END_CUSTOM_SCHEDULE_PROVIDER() -} diff --git a/game/server/episodic/ai_behavior_passenger_zombie.h b/game/server/episodic/ai_behavior_passenger_zombie.h deleted file mode 100644 index 237952ab0..000000000 --- a/game/server/episodic/ai_behavior_passenger_zombie.h +++ /dev/null @@ -1,97 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: Zombies on cars! -// -//============================================================================= - -#ifndef AI_BEHAVIOR_PASSENGER_ZOMBIE_H -#define AI_BEHAVIOR_PASSENGER_ZOMBIE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_behavior_passenger.h" -#include "ai_utils.h" -#include "vehicle_base.h" - -extern impactdamagetable_t gZombiePassengerImpactDamageTable; - -class CAI_PassengerBehaviorZombie : public CAI_PassengerBehavior -{ - DECLARE_CLASS( CAI_PassengerBehaviorZombie, CAI_PassengerBehavior ); - DECLARE_DATADESC() - -public: - - CAI_PassengerBehaviorZombie( void ); - - enum - { - // Schedules - SCHED_PASSENGER_ZOMBIE_ENTER_VEHICLE = BaseClass::NEXT_SCHEDULE, - SCHED_PASSENGER_ZOMBIE_EXIT_VEHICLE, - SCHED_PASSENGER_ZOMBIE_MELEE_ATTACK1, - SCHED_PASSENGER_ZOMBIE_RANGE_ATTACK1, - SCHED_PASSENGER_ZOMBIE_ATTACH, - SCHED_PASSENGER_ZOMBIE_RUN_TO_VEHICLE, - NEXT_SCHEDULE, - - // Tasks - TASK_PASSENGER_ZOMBIE_RANGE_ATTACK1 = BaseClass::NEXT_TASK, - TASK_PASSENGER_ZOMBIE_DISMOUNT, - TASK_PASSENGER_ZOMBIE_ATTACH, - NEXT_TASK, - - // Conditions - COND_PASSENGER_ZOMBIE_CAN_ATTACH_TO_VEHICLE = BaseClass::NEXT_CONDITION, - NEXT_CONDITION - }; - - virtual const char *GetName( void ) { return "ZombiePassenger"; } - virtual string_t GetRoleName( void ) { return MAKE_STRING( "passenger_zombie" ); } - virtual int SelectSchedule( void ); - virtual int TranslateSchedule( int scheduleType ); - virtual void GatherConditions( void ); - virtual void Event_Killed( const CTakeDamageInfo &info ); - virtual void BuildScheduleTestBits( void ); - virtual void RunTask( const Task_t *pTask ); - virtual void StartTask( const Task_t *pTask ); - virtual bool CanEnterVehicle( void ); - virtual void ExitVehicle( void ); - virtual void HandleAnimEvent( animevent_t *pEvent ); - virtual Activity NPC_TranslateActivity( Activity activity ); - - virtual bool AttachToVehicle( void ); - - void SuppressAttack( float flDuration ); - - DEFINE_CUSTOM_SCHEDULE_PROVIDER; - -protected: - - int SelectOutsideSchedule( void ); - int SelectInsideSchedule( void ); - virtual int FindExitSequence( void ); - void StartDismount( void ); - void FinishDismount( void ); - virtual void CalculateBodyLean( void ); - virtual void GatherVehicleStateConditions( void ); - virtual int FindEntrySequence( bool bNearest = false ); - -private: - - void VehicleLeapAttackTouch( CBaseEntity *pOther ); - void VehicleLeapAttack( void ); - bool CanBeOnEnemyVehicle( void ); - float GetEntryPointCost( const Vector &vecEntryPos ); - bool EnemyInVehicle( void ); - void GetAttachmentPoint( Vector *vecPoint ); - bool CanJumpToAttachToVehicle( void ); - //bool WithinAttachRange( void ); - - float m_flLastLateralLean; - float m_flLastVerticalLean; - float m_flNextLeapTime; -}; - -#endif // AI_BEHAVIOR_PASSENGER_ZOMBIE_H diff --git a/game/server/episodic/ep1_gamestats.cpp b/game/server/episodic/ep1_gamestats.cpp deleted file mode 100644 index 954718948..000000000 --- a/game/server/episodic/ep1_gamestats.cpp +++ /dev/null @@ -1,74 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -//Gamestats was built for ep1, so this file is going to be amazingly short seeing as how ep1 set the standard - -#include "cbase.h" -#include "ep1_gamestats.h" -#include "tier1/utlbuffer.h" -static CEP1GameStats s_CEP1GS_ThisJustSitsInMemory; - -// A bit of a hack to redirect the gamestats API for ep2 (ep3, etc.) -extern CBaseGameStats *g_pEP2GameStats; - -CEP1GameStats::CEP1GameStats( void ) -{ - gamestats = &s_CEP1GS_ThisJustSitsInMemory; -} - -CBaseGameStats *CEP1GameStats::OnInit( CBaseGameStats *pCurrentGameStats, char const *gamedir ) -{ - if ( !Q_stricmp( gamedir, "ep2" ) ) - { - return g_pEP2GameStats; - } - - return pCurrentGameStats; -} - -const char *CEP1GameStats::GetStatSaveFileName( void ) -{ - return "ep1_gamestats.dat"; //overriding the default for backwards compatibility with release stat tracking code -} - -const char *CEP1GameStats::GetStatUploadRegistryKeyName( void ) -{ - return "GameStatsUpload_Ep1"; //overriding the default for backwards compatibility with release stat tracking code -} - - -static char const *ep1Maps[] = -{ - "ep1_citadel_00", - "ep1_citadel_01", - "ep1_citadel_02", - "ep1_citadel_02b", - "ep1_citadel_03", - "ep1_citadel_04", - "ep1_c17_00", - "ep1_c17_00a", - "ep1_c17_01", - "ep1_c17_02", - "ep1_c17_02b", - "ep1_c17_02a", - "ep1_c17_05", - "ep1_c17_06", -}; - - -bool CEP1GameStats::UserPlayedAllTheMaps( void ) -{ - int c = ARRAYSIZE( ep1Maps ); - for ( int i = 0; i < c; ++i ) - { - int idx = m_BasicStats.m_MapTotals.Find( ep1Maps[ i ] ); - if( idx == m_BasicStats.m_MapTotals.InvalidIndex() ) - return false; - } - - return true; -} - diff --git a/game/server/episodic/ep1_gamestats.h b/game/server/episodic/ep1_gamestats.h deleted file mode 100644 index b438ddb46..000000000 --- a/game/server/episodic/ep1_gamestats.h +++ /dev/null @@ -1,31 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef EP1_GAMESTATS_H -#define EP1_GAMESTATS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "GameStats.h" - -class CEP1GameStats : public CBaseGameStats -{ - typedef CBaseGameStats BaseClass; - -public: - CEP1GameStats( void ); - - virtual CBaseGameStats *OnInit( CBaseGameStats *pCurrentGameStats, char const *gamedir ); - - virtual bool StatTrackingEnabledForMod( void ) { return true; } - virtual bool UserPlayedAllTheMaps( void ); - - virtual const char *GetStatSaveFileName( void ); - virtual const char *GetStatUploadRegistryKeyName( void ); -}; - -#endif // EP1_GAMESTATS_H diff --git a/game/server/episodic/ep2_gamestats.cpp b/game/server/episodic/ep2_gamestats.cpp deleted file mode 100644 index d510a7a5a..000000000 --- a/game/server/episodic/ep2_gamestats.cpp +++ /dev/null @@ -1,585 +0,0 @@ -//====== Copyright 1996-2006, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= -#if defined( GAME_DLL ) -#include "cbase.h" -#endif -#include "ep2_gamestats.h" -#include "tier1/utlbuffer.h" -#include "vehicle_base.h" -#include "tier1/utlstring.h" -#include "filesystem.h" -#include "icommandline.h" - -static CEP2GameStats s_CEP2GameStats_Singleton; -CBaseGameStats *g_pEP2GameStats = &s_CEP2GameStats_Singleton; - - -CEP2GameStats::CEP2GameStats( void ) -{ - Q_memset( m_flInchesRemainder, 0, sizeof( m_flInchesRemainder ) ); - m_pCurrentMap = NULL; - m_dictMapStats.Purge(); -} - -const char *CEP2GameStats::GetStatSaveFileName( void ) -{ - //overriding the default for backwards compatibility with release stat tracking code - return "ep2_gamestats.dat"; -} - -const char *CEP2GameStats::GetStatUploadRegistryKeyName( void ) -{ - //overriding the default for backwards compatibility with release stat tracking code - return "GameStatsUpload_Ep2"; -} - - -static char const *ep2Maps[] = -{ - "ep2_outland_01", - "ep2_outland_02", - "ep2_outland_03", - "ep2_outland_04", - "ep2_outland_05", - "ep2_outland_06", - "ep2_outland_06a", - "ep2_outland_07", - "ep2_outland_08", - "ep2_outland_09", - "ep2_outland_10", - "ep2_outland_10a", - "ep2_outland_11", - "ep2_outland_11a", - "ep2_outland_12", - "ep2_outland_12a" -}; - - -bool CEP2GameStats::UserPlayedAllTheMaps( void ) -{ - int c = ARRAYSIZE( ep2Maps ); - for ( int i = 0; i < c; ++i ) - { - int idx = m_BasicStats.m_MapTotals.Find( ep2Maps[ i ] ); - if( idx == m_BasicStats.m_MapTotals.InvalidIndex() ) - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Destructor -// Input : - -//----------------------------------------------------------------------------- -CEP2GameStats::~CEP2GameStats() -{ - m_pCurrentMap = NULL; - m_dictMapStats.Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &SaveBuffer - -//----------------------------------------------------------------------------- -void CEP2GameStats::AppendCustomDataToSaveBuffer( CUtlBuffer &SaveBuffer ) -{ - // Save data per map. - for ( int iMap = m_dictMapStats.First(); iMap != m_dictMapStats.InvalidIndex(); iMap = m_dictMapStats.Next( iMap ) ) - { - // Get the current map. - Ep2LevelStats_t *pCurrentMap = &m_dictMapStats[iMap]; - Assert( pCurrentMap ); - pCurrentMap->AppendToBuffer( SaveBuffer ); - } -} - -void CEP2GameStats::LoadCustomDataFromBuffer( CUtlBuffer &LoadBuffer ) -{ - Ep2LevelStats_t::LoadData( m_dictMapStats, LoadBuffer ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEP2GameStats::Event_LevelInit( void ) -{ - BaseClass::Event_LevelInit(); - - char const *pchTag = NULL; - CommandLine()->CheckParm( "-gamestatstag", &pchTag ); - if ( !pchTag ) - { - pchTag = ""; - } - - m_pCurrentMap = FindOrAddMapStats( STRING( gpGlobals->mapname ) ); - m_pCurrentMap->Init( STRING( gpGlobals->mapname ), gpGlobals->curtime, pchTag, gpGlobals->mapversion ); -} - -Ep2LevelStats_t::EntityDeathsLump_t *CEP2GameStats::FindDeathsLump( char const *npcName ) -{ - if ( !m_pCurrentMap ) - return NULL; - - char const *name = npcName; - // Hack to fixup name - if ( !Q_stricmp( name, "npc_ministrider" ) ) - { - name = "npc_hunter"; - } - - if ( Q_strnicmp( name, "npc_", 4 ) ) - return NULL; - - int idx = m_pCurrentMap->m_dictEntityDeaths.Find( name ); - if ( idx == m_pCurrentMap->m_dictEntityDeaths.InvalidIndex() ) - { - idx = m_pCurrentMap->m_dictEntityDeaths.Insert( name ); - } - - return &m_pCurrentMap->m_dictEntityDeaths[ idx ]; -} - -Ep2LevelStats_t::WeaponLump_t *CEP2GameStats::FindWeaponsLump( char const *pchWeaponName, bool bPrimary ) -{ - if ( !m_pCurrentMap ) - return NULL; - - if ( !pchWeaponName ) - { - AssertOnce( !"FindWeaponsLump pchWeaponName == NULL" ); - return NULL; - } - - char lookup[ 512 ]; - Q_snprintf( lookup, sizeof( lookup ), "%s_%s", pchWeaponName, bPrimary ? "primary" : "secondary" ); - int idx = m_pCurrentMap->m_dictWeapons.Find( lookup ); - if ( idx == m_pCurrentMap->m_dictWeapons.InvalidIndex() ) - { - idx = m_pCurrentMap->m_dictWeapons.Insert( lookup ); - } - - return &m_pCurrentMap->m_dictWeapons[ idx ]; -} - -// Finds the generic stats lump -Ep2LevelStats_t::GenericStatsLump_t *CEP2GameStats::FindGenericLump( char const *pchStatName ) -{ - if ( !m_pCurrentMap ) - return NULL; - if ( !pchStatName || !*pchStatName ) - return NULL; - - int idx = m_pCurrentMap->m_dictGeneric.Find( pchStatName ); - if ( idx == m_pCurrentMap->m_dictGeneric.InvalidIndex() ) - { - idx = m_pCurrentMap->m_dictGeneric.Insert( pchStatName ); - } - - return &m_pCurrentMap->m_dictGeneric[ idx ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *szMapName - -// Output : Ep2LevelStats_t -//----------------------------------------------------------------------------- -Ep2LevelStats_t *CEP2GameStats::FindOrAddMapStats( const char *szMapName ) -{ - int iMap = m_dictMapStats.Find( szMapName ); - if( iMap == m_dictMapStats.InvalidIndex() ) - { - iMap = m_dictMapStats.Insert( szMapName ); - } - - return &m_dictMapStats[iMap]; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEP2GameStats::Event_PlayerDamage( CBasePlayer *pBasePlayer, const CTakeDamageInfo &info ) -{ - BaseClass::Event_PlayerDamage( pBasePlayer, info ); - - m_pCurrentMap->m_FloatCounters[ Ep2LevelStats_t::COUNTER_DAMAGETAKEN ] += info.GetDamage(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEP2GameStats::Event_PlayerKilledOther( CBasePlayer *pAttacker, CBaseEntity *pVictim, const CTakeDamageInfo &info ) -{ - BaseClass::Event_PlayerKilledOther( pAttacker, pVictim, info ); - - if ( pAttacker ) - { - StatsLog( "Attacker: %s\n", pAttacker->GetClassname() ); - } - - if ( !pVictim ) - { - return; - } - - char const *pchVictim = pVictim->GetClassname(); - Ep2LevelStats_t::EntityDeathsLump_t *lump = FindDeathsLump( pchVictim ); - if ( lump ) - { - ++lump->m_nBodyCount; - StatsLog( "Player has killed %d %s's\n", lump->m_nBodyCount, pchVictim ); - - CPropVehicleDriveable *veh = dynamic_cast< CPropVehicleDriveable * >( pAttacker ); - if ( !veh ) - veh = dynamic_cast< CPropVehicleDriveable * >( info.GetInflictor() ); - if ( veh ) - { - CBaseEntity *driver = veh->GetDriver(); - if ( driver && driver->IsPlayer() ) - { - ++m_pCurrentMap->m_IntCounters[ Ep2LevelStats_t::COUNTER_VEHICULARHOMICIDES ]; - StatsLog( " Vehicular homicide [%I64d] of %s's\n", m_pCurrentMap->m_IntCounters[ Ep2LevelStats_t::COUNTER_VEHICULARHOMICIDES ], pchVictim ); - } - } - } - else - { - StatsLog( "Player killed %s (not tracked)\n", pchVictim ); - } -} - -void CEP2GameStats::Event_Punted( CBaseEntity *pObject ) -{ - BaseClass::Event_Punted( pObject ); - ++m_pCurrentMap->m_IntCounters[ Ep2LevelStats_t::COUNTER_OBJECTSPUNTED ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEP2GameStats::Event_PlayerKilled( CBasePlayer *pPlayer, const CTakeDamageInfo &info ) -{ - BaseClass::Event_PlayerKilled( pPlayer, info ); - - if ( info.GetDamageType() & DMG_FALL ) - { - ++m_pCurrentMap->m_IntCounters[ Ep2LevelStats_t::COUNTER_FALLINGDEATHS ]; - } - - Ep2LevelStats_t::PlayerDeathsLump_t death; - - // set the location where the target died - const Vector &org = pPlayer->GetAbsOrigin(); - death.nPosition[ 0 ] = static_cast( org.x ); - death.nPosition[ 1 ] = static_cast( org.y ); - death.nPosition[ 2 ] = static_cast( org.z ); - - StatsLog( "CEP2GameStats::Event_PlayerKilled at location [%d %d %d]\n", (int)death.nPosition[ 0 ], (int)death.nPosition[ 1 ], (int)death.nPosition[ 2 ] ); - - // set the class of the attacker - CBaseEntity *pInflictor = info.GetInflictor(); - CBaseEntity *pKiller = info.GetAttacker(); - - if ( pInflictor ) - { - StatsLog( "Inflictor: %s\n", pInflictor->GetClassname() ); - } - - if ( pKiller ) - { - char const *pchKiller = pKiller->GetClassname(); - Ep2LevelStats_t::EntityDeathsLump_t *lump = FindDeathsLump( pchKiller ); - if ( lump ) - { - ++lump->m_nKilledPlayer; - StatsLog( "Player has been killed %d times by %s's\n", lump->m_nKilledPlayer, pchKiller ); - } - else - { - StatsLog( "Player killed by %s (not tracked)\n", pchKiller ); - } - } - - // add it to the list of deaths - Ep2LevelStats_t *map = FindOrAddMapStats( STRING( gpGlobals->mapname ) ); - int slot = map->m_aPlayerDeaths.AddToTail( death ); - - Ep2LevelStats_t::SaveGameInfoRecord2_t *rec = map->m_SaveGameInfo.m_pCurrentRecord; - if ( rec ) - { - if ( rec->m_nFirstDeathIndex == -1 ) - { - rec->m_nFirstDeathIndex = slot; - } - ++rec->m_nNumDeaths; - - StatsLog( "Player has died %d times since last save/load\n", rec->m_nNumDeaths ); - } -} - -void CEP2GameStats::Event_CrateSmashed() -{ - BaseClass::Event_CrateSmashed(); - - ++m_pCurrentMap->m_IntCounters[ Ep2LevelStats_t::COUNTER_CRATESSMASHED ]; -} - -void CEP2GameStats::Event_PlayerTraveled( CBasePlayer *pBasePlayer, float distanceInInches, bool bInVehicle, bool bSprinting ) -{ - BaseClass::Event_PlayerTraveled( pBasePlayer, distanceInInches, bInVehicle, bSprinting ); - - int iIndex = INVEHICLE; - if ( !bInVehicle ) - { - iIndex = bSprinting ? ONFOOTSPRINTING : ONFOOT; - } - - m_flInchesRemainder[ iIndex ] += distanceInInches; - uint64 intPart = (uint64)m_flInchesRemainder[ iIndex ]; - m_flInchesRemainder[ iIndex ] -= intPart; - if ( intPart > 0 ) - { - if ( bInVehicle ) - { - m_pCurrentMap->m_IntCounters[ Ep2LevelStats_t::COUNTER_DISTANCE_INVEHICLE ] += intPart; - } - else - { - if ( bSprinting ) - { - m_pCurrentMap->m_IntCounters[ Ep2LevelStats_t::COUNTER_DISTANCE_ONFOOTSPRINTING ] += intPart; - } - else - { - m_pCurrentMap->m_IntCounters[ Ep2LevelStats_t::COUNTER_DISTANCE_ONFOOT ] += intPart; - } - } - } - - Ep2LevelStats_t *map = m_pCurrentMap; - if ( !map ) - return; - - Ep2LevelStats_t::SaveGameInfoRecord2_t *rec = map->m_SaveGameInfo.m_pCurrentRecord; - - if ( rec && - rec->m_nSaveHealth == -1 ) - { - Vector pos = pBasePlayer->GetAbsOrigin(); - rec->m_nSavePos[ 0 ] = (short)pos.x; - rec->m_nSavePos[ 1 ] = (short)pos.y; - rec->m_nSavePos[ 2 ] = (short)pos.z; - rec->m_nSaveHealth = clamp( pBasePlayer->GetHealth(), 0, 100 ); - } -} - -void CEP2GameStats::Event_WeaponFired( CBasePlayer *pShooter, bool bPrimary, char const *pchWeaponName ) -{ - BaseClass::Event_WeaponFired( pShooter, bPrimary, pchWeaponName ); - - Ep2LevelStats_t::WeaponLump_t *lump = FindWeaponsLump( pchWeaponName, bPrimary ); - if ( lump ) - { - ++lump->m_nShots; - } -} - -void CEP2GameStats::Event_WeaponHit( CBasePlayer *pShooter, bool bPrimary, char const *pchWeaponName, const CTakeDamageInfo &info ) -{ - BaseClass::Event_WeaponHit( pShooter, bPrimary, pchWeaponName, info ); - Ep2LevelStats_t::WeaponLump_t *lump = FindWeaponsLump( pchWeaponName, bPrimary ); - if ( lump ) - { - ++lump->m_nHits; - lump->m_flDamageInflicted += info.GetDamage(); - } -} - -void CEP2GameStats::Event_SaveGame( void ) -{ - BaseClass::Event_SaveGame(); - - Ep2LevelStats_t *map = m_pCurrentMap; - if ( !map ) - return; - - ++map->m_IntCounters[ Ep2LevelStats_t::COUNTER_SAVES ]; - StatsLog( " %I64uth save on this map\n", map->m_IntCounters[ Ep2LevelStats_t::COUNTER_SAVES ] ); - - char const *pchSaveFile = engine->GetSaveFileName(); - if ( !pchSaveFile || !pchSaveFile[ 0 ] ) - return; - - char name[ 512 ]; - Q_strncpy( name, pchSaveFile, sizeof( name ) ); - Q_strlower( name ); - Q_FixSlashes( name ); - - unsigned int uFileTime = filesystem->GetFileTime( name, "GAME" ); - // Latch off previous - map->m_SaveGameInfo.Latch( name, uFileTime ); - - Ep2LevelStats_t::SaveGameInfoRecord2_t *rec = map->m_SaveGameInfo.m_pCurrentRecord; - - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - if ( pPlayer ) - { - Vector pos = pPlayer->GetAbsOrigin(); - rec->m_nSavePos[ 0 ] = (short)pos.x; - rec->m_nSavePos[ 1 ] = (short)pos.y; - rec->m_nSavePos[ 2 ] = (short)pos.z; - rec->m_nSaveHealth = clamp( pPlayer->GetHealth(), 0, 100 ); - rec->m_SaveType = Q_stristr( pchSaveFile, "autosave" ) ? - Ep2LevelStats_t::SaveGameInfoRecord2_t::TYPE_AUTOSAVE : Ep2LevelStats_t::SaveGameInfoRecord2_t::TYPE_USERSAVE; - - StatsLog( "save pos %i %i %i w/ health %d\n", - rec->m_nSavePos[ 0 ], - rec->m_nSavePos[ 1 ], - rec->m_nSavePos[ 2 ], - rec->m_nSaveHealth ); - - } -} - -void CEP2GameStats::Event_LoadGame( void ) -{ - BaseClass::Event_LoadGame(); - - Ep2LevelStats_t *map = m_pCurrentMap; - if ( !map ) - return; - - ++map->m_IntCounters[ Ep2LevelStats_t::COUNTER_LOADS ]; - StatsLog( " %I64uth load on this map\n", map->m_IntCounters[ Ep2LevelStats_t::COUNTER_LOADS ] ); - - char const *pchSaveFile = engine->GetMostRecentlyLoadedFileName(); - if ( !pchSaveFile || !pchSaveFile[ 0 ] ) - return; - - char name[ 512 ]; - Q_snprintf( name, sizeof( name ), "SAVE/%s", pchSaveFile ); - Q_DefaultExtension( name, IsX360() ? ".360.sav" : ".sav", sizeof( name ) ); - Q_FixSlashes( name ); - Q_strlower( name ); - - Ep2LevelStats_t::SaveGameInfo_t *pSaveGameInfo = &map->m_SaveGameInfo; - - if ( pSaveGameInfo->m_nCurrentSaveFileTime == 0 || - pSaveGameInfo->m_sCurrentSaveFile != name ) - { - unsigned int uFileTime = filesystem->GetFileTime( name, "GAME" ); - - // Latch off previous - StatsLog( "Relatching save game file due to time or filename change (%s : %u)\n", name, uFileTime ); - pSaveGameInfo->Latch( name, uFileTime ); - } -} - -void CEP2GameStats::Event_FlippedVehicle( CBasePlayer *pDriver, CPropVehicleDriveable *pVehicle ) -{ - BaseClass::Event_FlippedVehicle( pDriver, pVehicle ); - ++m_pCurrentMap->m_IntCounters[ Ep2LevelStats_t::COUNTER_VEHICLE_OVERTURNED ]; - StatsLog( "%I64u time vehicle overturned\n", m_pCurrentMap->m_IntCounters[ Ep2LevelStats_t::COUNTER_VEHICLE_OVERTURNED ] ); -} - -void CEP2GameStats::Event_PreSaveGameLoaded( char const *pSaveName, bool bInGame ) -{ - BaseClass::Event_PreSaveGameLoaded( pSaveName, bInGame ); - - // Not currently in a level - if ( !bInGame ) - return; - - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - if ( !pPlayer ) - return; - - // We're loading a saved game while the player is still alive (are they stuck?) - if ( pPlayer->IsAlive() ) - { - ++m_pCurrentMap->m_IntCounters[ Ep2LevelStats_t::COUNTER_LOADGAME_STILLALIVE ]; - StatsLog( "%I64u game loaded with living player\n", m_pCurrentMap->m_IntCounters[ Ep2LevelStats_t::COUNTER_LOADGAME_STILLALIVE ] ); - } -} - -void CEP2GameStats::Event_PlayerEnteredGodMode( CBasePlayer *pBasePlayer ) -{ - BaseClass::Event_PlayerEnteredGodMode( pBasePlayer ); - ++m_pCurrentMap->m_IntCounters[ Ep2LevelStats_t::COUNTER_GODMODES ]; - StatsLog( "%I64u time entering godmode\n", m_pCurrentMap->m_IntCounters[ Ep2LevelStats_t::COUNTER_GODMODES ] ); -} - -void CEP2GameStats::Event_PlayerEnteredNoClip( CBasePlayer *pBasePlayer ) -{ - BaseClass::Event_PlayerEnteredNoClip( pBasePlayer ); - ++m_pCurrentMap->m_IntCounters[ Ep2LevelStats_t::COUNTER_NOCLIPS ]; - StatsLog( "%I64u time entering NOCLIP\n", m_pCurrentMap->m_IntCounters[ Ep2LevelStats_t::COUNTER_NOCLIPS ] ); -} - -void CEP2GameStats::Event_DecrementPlayerEnteredNoClip( CBasePlayer *pBasePlayer ) -{ - BaseClass::Event_DecrementPlayerEnteredNoClip( pBasePlayer ); - if ( m_pCurrentMap->m_IntCounters[ Ep2LevelStats_t::COUNTER_NOCLIPS ] > 0 ) - { - --m_pCurrentMap->m_IntCounters[ Ep2LevelStats_t::COUNTER_NOCLIPS ]; - } - StatsLog( "%I64u decrement entering NOCLIP (entering vehicle doesn't count)\n", m_pCurrentMap->m_IntCounters[ Ep2LevelStats_t::COUNTER_NOCLIPS ] ); -} - -// Generic statistics lump -void CEP2GameStats::Event_IncrementCountedStatistic( const Vector& vecAbsOrigin, char const *pchStatisticName, float flIncrementAmount ) -{ - BaseClass::Event_IncrementCountedStatistic( vecAbsOrigin, pchStatisticName, flIncrementAmount ); - - // Find the generic lump - Ep2LevelStats_t::GenericStatsLump_t *lump = FindGenericLump( pchStatisticName ); - if ( lump ) - { - lump->m_Pos[ 0 ] = (short)vecAbsOrigin.x; - lump->m_Pos[ 1 ] = (short)vecAbsOrigin.y; - lump->m_Pos[ 2 ] = (short)vecAbsOrigin.z; - lump->m_flCurrentValue += (double)flIncrementAmount; - ++lump->m_unCount; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -static void CC_ListDeaths( const CCommand &args ) -{ - Ep2LevelStats_t *map = s_CEP2GameStats_Singleton.FindOrAddMapStats( STRING( gpGlobals->mapname ) ); - if ( !map ) - return; - - int nRendered = 0; - for ( int i = map->m_aPlayerDeaths.Count() - 1; i >= 0 ; --i, ++nRendered ) - { - Vector org( map->m_aPlayerDeaths[ i ].nPosition[ 0 ], - map->m_aPlayerDeaths[ i ].nPosition[ 1 ], - map->m_aPlayerDeaths[ i ].nPosition[ 2 ] + 36.0f ); - - // FIXME: This might overflow - NDebugOverlay::Box( org, Vector( -8, -8, -8 ), Vector( 8, 8, 8 ), 0, 255, 0, 128, 10.0f ); - - /* - Msg( "%s killed %s with %s at (%d,%d,%d)\n", - g_aClassNames[ map->m_aPlayerDeaths[ i ].iAttackClass ], - g_aClassNames[ map->m_aPlayerDeaths[ i ].iTargetClass ], - WeaponIdToAlias( map->m_aPlayerDeaths[ i ].iWeapon ), - map->m_aPlayerDeaths[ i ].nPosition[ 0 ], - map->m_aPlayerDeaths[ i ].nPosition[ 1 ], - map->m_aPlayerDeaths[ i ].nPosition[ 2 ] ); - */ - - if ( nRendered > 150 ) - break; - } - Msg( "\nlisted %d deaths\n", map->m_aPlayerDeaths.Count() ); -} - -static ConCommand listDeaths("listdeaths", CC_ListDeaths, "lists player deaths", 0 ); diff --git a/game/server/episodic/ep2_gamestats.h b/game/server/episodic/ep2_gamestats.h deleted file mode 100644 index e7b69c79d..000000000 --- a/game/server/episodic/ep2_gamestats.h +++ /dev/null @@ -1,532 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef EP2_GAMESTATS_H -#define EP2_GAMESTATS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ep1_gamestats.h" -#include "tier1/utlstring.h" - -// EP2 Game Stats -enum Ep2GameStatsVersions_t -{ - EP2_GAMESTATS_FILE_VERSION_01 = 001, - EP2_GAMESTATS_FILE_VERSION_02 = 002, - - EP2_GAMESTATS_CURRENT_VERSION = EP2_GAMESTATS_FILE_VERSION_02, -}; - -enum Ep2GameStatsLumpIds_t -{ - EP2STATS_LUMP_HEADER = 1, - EP2STATS_LUMP_DEATH, - EP2STATS_LUMP_NPC, - EP2STATS_LUMP_WEAPON, - EP2STATS_LUMP_SAVEGAMEINFO, - EP2STATS_LUMP_TAG, - EP2STATS_LUMP_GENERIC, - EP2_MAX_LUMP_COUNT -}; - -// EP2 Game Level Stats Data -struct Ep2LevelStats_t -{ -public: - enum FloatCounterTypes_t - { - COUNTER_DAMAGETAKEN = 0, - - NUM_FLOATCOUNTER_TYPES, - }; - - enum IntCounterTypes_t - { - COUNTER_CRATESSMASHED = 0, - COUNTER_OBJECTSPUNTED, - COUNTER_VEHICULARHOMICIDES, - COUNTER_DISTANCE_INVEHICLE, - COUNTER_DISTANCE_ONFOOT, - COUNTER_DISTANCE_ONFOOTSPRINTING, - COUNTER_FALLINGDEATHS, - COUNTER_VEHICLE_OVERTURNED, - COUNTER_LOADGAME_STILLALIVE, - COUNTER_LOADS, - COUNTER_SAVES, - COUNTER_GODMODES, - COUNTER_NOCLIPS, - - NUM_INTCOUNTER_TYPES, - }; - - Ep2LevelStats_t() : - m_bInitialized( false ), - m_flLevelStartTime( 0.0f ) - { - Q_memset( m_IntCounters, 0, sizeof( m_IntCounters ) ); - Q_memset( m_FloatCounters, 0, sizeof( m_FloatCounters ) ); - } - ~Ep2LevelStats_t() - { - } - - Ep2LevelStats_t( const Ep2LevelStats_t &other ) - { - m_bInitialized = other.m_bInitialized; - m_flLevelStartTime = other.m_flLevelStartTime; - m_Header = other.m_Header; - m_aPlayerDeaths = other.m_aPlayerDeaths; - Q_memcpy( m_IntCounters, other.m_IntCounters, sizeof( m_IntCounters ) ); - Q_memcpy( m_FloatCounters, other.m_FloatCounters, sizeof( m_FloatCounters ) ); - int i; - for ( i = other.m_dictEntityDeaths.First(); i != other.m_dictEntityDeaths.InvalidIndex(); i = other.m_dictEntityDeaths.Next( i ) ) - { - m_dictEntityDeaths.Insert( other.m_dictEntityDeaths.GetElementName( i ), other.m_dictEntityDeaths[ i ] ); - } - for ( i = other.m_dictWeapons.First(); i != other.m_dictWeapons.InvalidIndex(); i = other.m_dictWeapons.Next( i ) ) - { - m_dictWeapons.Insert( other.m_dictWeapons.GetElementName( i ), other.m_dictWeapons[ i ] ); - } - m_SaveGameInfo = other.m_SaveGameInfo; - } - - // Create and destroy. - void Init( const char *pszMapName, float flStartTime, char const *pchTag, int nMapVersion ) - { - // Initialize. - m_Header.m_iVersion = EP2_GAMESTATS_CURRENT_VERSION; - Q_strncpy( m_Header.m_szMapName, pszMapName, sizeof( m_Header.m_szMapName ) ); - m_Header.m_flTime = 0.0f; - - // Start the level timer. - m_flLevelStartTime = flStartTime; - - Q_strncpy( m_Tag.m_szTagText, pchTag, sizeof( m_Tag.m_szTagText ) ); - m_Tag.m_nMapVersion = nMapVersion; - } - - void Shutdown( float flEndTime ) - { - m_Header.m_flTime = flEndTime - m_flLevelStartTime; - } - - void AppendToBuffer( CUtlBuffer &SaveBuffer ) - { - // Always write out as current version - m_Header.m_iVersion = EP2_GAMESTATS_CURRENT_VERSION; - - // Write out the lumps. - CBaseGameStats::AppendLump( EP2_MAX_LUMP_COUNT, SaveBuffer, EP2STATS_LUMP_HEADER, 1, sizeof( Ep2LevelStats_t::LevelHeader_t ), static_cast( &m_Header ) ); - CBaseGameStats::AppendLump( EP2_MAX_LUMP_COUNT, SaveBuffer, EP2STATS_LUMP_TAG, 1, sizeof( Ep2LevelStats_t::Tag_t ), static_cast< void * >( &m_Tag ) ); - CBaseGameStats::AppendLump( EP2_MAX_LUMP_COUNT, SaveBuffer, EP2STATS_LUMP_DEATH, m_aPlayerDeaths.Count(), sizeof( Ep2LevelStats_t::PlayerDeathsLump_t ), static_cast( m_aPlayerDeaths.Base() ) ); - { - CUtlBuffer buf; - buf.Put( (const void *)m_IntCounters, sizeof( m_IntCounters ) ); - buf.Put( (const void *)m_FloatCounters, sizeof( m_FloatCounters ) ); - buf.PutInt( m_dictEntityDeaths.Count() ); - for ( int i = m_dictEntityDeaths.First(); i != m_dictEntityDeaths.InvalidIndex(); i = m_dictEntityDeaths.Next( i ) ) - { - buf.PutString( m_dictEntityDeaths.GetElementName( i ) ); - buf.Put( (const void *)&m_dictEntityDeaths[ i ], sizeof( Ep2LevelStats_t::EntityDeathsLump_t ) ); - } - CBaseGameStats::AppendLump( EP2_MAX_LUMP_COUNT, SaveBuffer, EP2STATS_LUMP_NPC, 1, buf.TellPut(), buf.Base() ); - } - { - CUtlBuffer buf; - buf.PutInt( m_dictWeapons.Count() ); - for ( int i = m_dictWeapons.First(); i != m_dictWeapons.InvalidIndex(); i = m_dictWeapons.Next( i ) ) - { - buf.PutString( m_dictWeapons.GetElementName( i ) ); - buf.Put( (const void *)&m_dictWeapons[ i ], sizeof( Ep2LevelStats_t::WeaponLump_t ) ); - } - CBaseGameStats::AppendLump( EP2_MAX_LUMP_COUNT, SaveBuffer, EP2STATS_LUMP_WEAPON, 1, buf.TellPut(), buf.Base() ); - } - { - CUtlBuffer buf; - buf.PutString( m_SaveGameInfo.m_sCurrentSaveFile.String() ); - buf.PutInt( m_SaveGameInfo.m_nCurrentSaveFileTime ); - buf.PutInt( m_SaveGameInfo.m_Records.Count() ); - for ( int i = 0 ; i < m_SaveGameInfo.m_Records.Count(); ++i ) - { - buf.Put( (const void *)&m_SaveGameInfo.m_Records[ i ], sizeof( Ep2LevelStats_t::SaveGameInfoRecord2_t ) ); - } - CBaseGameStats::AppendLump( EP2_MAX_LUMP_COUNT, SaveBuffer, EP2STATS_LUMP_SAVEGAMEINFO, 1, buf.TellPut(), buf.Base() ); - } - { - CUtlBuffer buf; - buf.PutShort( Ep2LevelStats_t::GenericStatsLump_t::LumpVersion ); - buf.PutInt( m_dictGeneric.Count() ); - for ( int i = m_dictGeneric.First(); i != m_dictGeneric.InvalidIndex(); i = m_dictGeneric.Next( i ) ) - { - buf.PutString( m_dictGeneric.GetElementName( i ) ); - buf.Put( (const void *)&m_dictGeneric[ i ], sizeof( Ep2LevelStats_t::GenericStatsLump_t ) ); - } - CBaseGameStats::AppendLump( EP2_MAX_LUMP_COUNT, SaveBuffer, EP2STATS_LUMP_GENERIC, 1, buf.TellPut(), buf.Base() ); - } - } - - static void LoadData( CUtlDict& items, CUtlBuffer &LoadBuffer ) - { - // Read the next lump. - unsigned short iLump = 0; - unsigned short iLumpCount = 0; - - Ep2LevelStats_t *pItem = NULL; - - while( CBaseGameStats::GetLumpHeader( EP2_MAX_LUMP_COUNT, LoadBuffer, iLump, iLumpCount, true ) ) - { - switch ( iLump ) - { - case EP2STATS_LUMP_HEADER: - { - Ep2LevelStats_t::LevelHeader_t header; - CBaseGameStats::LoadLump( LoadBuffer, iLumpCount, sizeof( Ep2LevelStats_t::LevelHeader_t ), &header ); - pItem = &items[ items.Insert( header.m_szMapName ) ]; - pItem->m_Header = header; - pItem->m_Tag.Clear(); - Assert( pItem ); - } - break; - case EP2STATS_LUMP_TAG: - { - Assert( pItem ); - CBaseGameStats::LoadLump( LoadBuffer, iLumpCount, sizeof( Ep2LevelStats_t::Tag_t ), &pItem->m_Tag ); - } - break; - case EP2STATS_LUMP_DEATH: - { - Assert( pItem ); - pItem->m_aPlayerDeaths.SetCount( iLumpCount ); - CBaseGameStats::LoadLump( LoadBuffer, iLumpCount, sizeof( Ep2LevelStats_t::PlayerDeathsLump_t ), static_cast( pItem->m_aPlayerDeaths.Base() ) ); - } - break; - case EP2STATS_LUMP_NPC: - { - Assert( pItem ); - LoadBuffer.Get( ( void * )pItem->m_IntCounters, sizeof( pItem->m_IntCounters ) ); - LoadBuffer.Get( ( void * )pItem->m_FloatCounters, sizeof( pItem->m_FloatCounters ) ); - int c = LoadBuffer.GetInt(); - for ( int i = 0 ; i < c; ++i ) - { - Ep2LevelStats_t::EntityDeathsLump_t data; - char npcName[ 512 ]; - LoadBuffer.GetString( npcName, sizeof( npcName ) ); - LoadBuffer.Get( &data, sizeof( data ) ); - pItem->m_dictEntityDeaths.Insert( npcName, data ); - } - } - break; - case EP2STATS_LUMP_WEAPON: - { - Assert( pItem ); - int c = LoadBuffer.GetInt(); - for ( int i = 0 ; i < c; ++i ) - { - Ep2LevelStats_t::WeaponLump_t data; - char weaponName[ 512 ]; - LoadBuffer.GetString( weaponName, sizeof( weaponName ) ); - LoadBuffer.Get( &data, sizeof( data ) ); - pItem->m_dictWeapons.Insert( weaponName, data ); - } - } - break; - case EP2STATS_LUMP_SAVEGAMEINFO: - { - Assert( pItem ); - Ep2LevelStats_t::SaveGameInfo_t *info = &pItem->m_SaveGameInfo; - char sz[ 512 ]; - LoadBuffer.GetString( sz, sizeof( sz ) ); - info->m_sCurrentSaveFile = sz; - info->m_nCurrentSaveFileTime = LoadBuffer.GetInt(); - int c = LoadBuffer.GetInt(); - for ( int i = 0 ; i < c; ++i ) - { - Ep2LevelStats_t::SaveGameInfoRecord2_t rec; - if ( pItem->m_Header.m_iVersion >= EP2_GAMESTATS_FILE_VERSION_02 ) - { - LoadBuffer.Get( &rec, sizeof( rec ) ); - } - else - { - size_t s = sizeof( Ep2LevelStats_t::SaveGameInfoRecord_t ); - LoadBuffer.Get( &rec, s ); - } - info->m_Records.AddToTail( rec ); - } - info->m_pCurrentRecord = NULL; - if ( info->m_Records.Count() > 0 ) - { - info->m_pCurrentRecord = &info->m_Records[ info->m_Records.Count() - 1 ]; - } - } - break; - case EP2STATS_LUMP_GENERIC: - { - Assert( pItem ); - int version = LoadBuffer.GetShort(); - if ( version == Ep2LevelStats_t::GenericStatsLump_t::LumpVersion ) - { - int c = LoadBuffer.GetInt(); - Assert( c < 2 * 1024 * 1024 ); - for ( int i = 0 ; i < c; ++i ) - { - Ep2LevelStats_t::GenericStatsLump_t data; - char pchStatName[ 512 ]; - LoadBuffer.GetString( pchStatName, sizeof( pchStatName ) ); - LoadBuffer.Get( &data, sizeof( data ) ); - pItem->m_dictGeneric.Insert( pchStatName, data ); - } - } - else - { - Error( "Unsupported GenericStatsLump_t::LumpVersion" ); - } - } - break; - } - } - } - -public: - // Level header data. - struct LevelHeader_t - { - static const unsigned short LumpId = EP2STATS_LUMP_HEADER; // Lump ids. - byte m_iVersion; // Version of the game stats file. - char m_szMapName[64]; // Name of the map. - float m_flTime; // Time spent in level. - }; - - // Simple "tag" applied to all data in database (e.g., "PLAYTEST") - struct Tag_t - { - static const unsigned short LumpId = EP2STATS_LUMP_TAG; - - void Clear() - { - Q_memset( m_szTagText, 0, sizeof( m_szTagText ) ); - m_nMapVersion = 0; - } - - char m_szTagText[ 8 ]; - int m_nMapVersion; - }; - - // Player deaths. - struct PlayerDeathsLump_t - { - static const unsigned short LumpId = EP2STATS_LUMP_DEATH; // Lump ids. - short nPosition[3]; // Position of death. -// short iWeapon; // Weapon that killed the player. -// byte iAttackClass; // Class that killed the player. -// byte iTargetClass; // Class of the player killed. - }; - - struct EntityDeathsLump_t - { - static const unsigned short LumpId = EP2STATS_LUMP_NPC; - - EntityDeathsLump_t() : - m_nBodyCount( 0u ), - m_nKilledPlayer( 0u ) - { - } - - EntityDeathsLump_t( const EntityDeathsLump_t &other ) - { - m_nBodyCount = other.m_nBodyCount; - m_nKilledPlayer = other.m_nKilledPlayer; - } - - unsigned int m_nBodyCount; // Number killed by player - unsigned int m_nKilledPlayer; // Number of times entity killed player - }; - - struct WeaponLump_t - { - static const unsigned short LumpId = EP2STATS_LUMP_WEAPON; - - WeaponLump_t() : - m_nShots( 0 ), - m_nHits( 0 ), - m_flDamageInflicted( 0.0 ) - { - } - - WeaponLump_t( const WeaponLump_t &other ) - { - m_nShots = other.m_nShots; - m_nHits = other.m_nHits; - m_flDamageInflicted = other.m_flDamageInflicted; - } - - unsigned int m_nShots; - unsigned int m_nHits; - double m_flDamageInflicted; - }; - - struct SaveGameInfoRecord_t - { - SaveGameInfoRecord_t() : - m_nFirstDeathIndex( -1 ), - m_nNumDeaths( 0 ), - m_nSaveHealth( -1 ) - { - Q_memset( m_nSavePos, 0, sizeof( m_nSavePos ) ); - } - - int m_nFirstDeathIndex; - int m_nNumDeaths; - // Health and player pos from the save file - short m_nSavePos[ 3 ]; - short m_nSaveHealth; - }; - -#pragma pack( 1 ) - // Adds save game type - struct SaveGameInfoRecord2_t : public SaveGameInfoRecord_t - { - enum SaveType_t - { - TYPE_UNKNOWN = 0, - TYPE_AUTOSAVE, - TYPE_USERSAVE - }; - - SaveGameInfoRecord2_t() : - m_SaveType( (byte)TYPE_UNKNOWN ) - { - } - - byte m_SaveType; - }; -#pragma pack() - - struct SaveGameInfo_t - { - static const unsigned short LumpId = EP2STATS_LUMP_SAVEGAMEINFO; - - SaveGameInfo_t() : - m_pCurrentRecord( NULL ), - m_nCurrentSaveFileTime( 0 ) - { - } - - void Latch( char const *pchSaveName, unsigned int uFileTime ) - { - m_pCurrentRecord = &m_Records[ m_Records.AddToTail() ]; - m_nCurrentSaveFileTime = uFileTime; - m_sCurrentSaveFile = pchSaveName; - } - - CUtlVector< SaveGameInfoRecord2_t > m_Records; - SaveGameInfoRecord2_t *m_pCurrentRecord; - unsigned int m_nCurrentSaveFileTime; - CUtlString m_sCurrentSaveFile; - }; - - struct GenericStatsLump_t - { - static const unsigned short LumpId = EP2STATS_LUMP_GENERIC; - static const unsigned short LumpVersion = 1; - - GenericStatsLump_t() : - m_unCount( 0u ), - m_flCurrentValue( 0.0 ) - { - m_Pos[ 0 ] = m_Pos[ 1 ] = m_Pos[ 2 ] = 0; - } - - short m_Pos[ 3 ]; - unsigned int m_unCount; - double m_flCurrentValue; - }; - - // Data. - LevelHeader_t m_Header; // Level header. - Tag_t m_Tag; - CUtlVector m_aPlayerDeaths; // List of player deaths. - CUtlDict< EntityDeathsLump_t, int > m_dictEntityDeaths; - CUtlDict< WeaponLump_t, int > m_dictWeapons; - CUtlDict< GenericStatsLump_t, int > m_dictGeneric; - - SaveGameInfo_t m_SaveGameInfo; - float m_FloatCounters[ NUM_FLOATCOUNTER_TYPES ]; - uint64 m_IntCounters[ NUM_INTCOUNTER_TYPES ]; - - // Temporary data. - bool m_bInitialized; // Has the map Map Stat Data been initialized. - float m_flLevelStartTime; -}; - -#if defined( GAME_DLL ) -class CEP2GameStats : public CEP1GameStats -{ - typedef CEP1GameStats BaseClass; - -public: - CEP2GameStats(); - virtual ~CEP2GameStats(); - - virtual CBaseGameStats *OnInit( CBaseGameStats *pCurrentGameStats, char const *gamedir ) { return pCurrentGameStats; } - - virtual bool UserPlayedAllTheMaps( void ); - virtual const char *GetStatSaveFileName( void ); - virtual const char *GetStatUploadRegistryKeyName( void ); - - // Buffers. - virtual void AppendCustomDataToSaveBuffer( CUtlBuffer &SaveBuffer ); - virtual void LoadCustomDataFromBuffer( CUtlBuffer &LoadBuffer ); - - // Events - virtual void Event_LevelInit( void ); - virtual void Event_PlayerKilled( CBasePlayer *pPlayer, const CTakeDamageInfo &info ); - virtual void Event_PlayerDamage( CBasePlayer *pBasePlayer, const CTakeDamageInfo &info ); - virtual void Event_PlayerKilledOther( CBasePlayer *pAttacker, CBaseEntity *pVictim, const CTakeDamageInfo &info ); - virtual void Event_CrateSmashed(); - virtual void Event_Punted( CBaseEntity *pObject ); - virtual void Event_PlayerTraveled( CBasePlayer *pBasePlayer, float distanceInInches, bool bInVehicle, bool bSprinting ); - virtual void Event_WeaponFired( CBasePlayer *pShooter, bool bPrimary, char const *pchWeaponName ); - virtual void Event_WeaponHit( CBasePlayer *pShooter, bool bPrimary, char const *pchWeaponName, const CTakeDamageInfo &info ); - virtual void Event_SaveGame( void ); - virtual void Event_LoadGame( void ); - virtual void Event_FlippedVehicle( CBasePlayer *pDriver, CPropVehicleDriveable *pVehicle ); - // Called before .sav file is actually loaded (player should still be in previous level, if any) - virtual void Event_PreSaveGameLoaded( char const *pSaveName, bool bInGame ); - virtual void Event_PlayerEnteredGodMode( CBasePlayer *pBasePlayer ); - virtual void Event_PlayerEnteredNoClip( CBasePlayer *pBasePlayer ); - virtual void Event_DecrementPlayerEnteredNoClip( CBasePlayer *pBasePlayer ); - // Generic statistics lump - virtual void Event_IncrementCountedStatistic( const Vector& vecAbsOrigin, char const *pchStatisticName, float flIncrementAmount ); - -public: //FIXME: temporary used for CC_ListDeaths command - Ep2LevelStats_t *FindOrAddMapStats( const char *szMapName ); - -public: - - Ep2LevelStats_t::EntityDeathsLump_t *FindDeathsLump( char const *npcName ); - Ep2LevelStats_t::WeaponLump_t *FindWeaponsLump( char const *pchWeaponName, bool bPrimary ); - Ep2LevelStats_t::GenericStatsLump_t *FindGenericLump( char const *pchStatName ); - // Utilities. - Ep2LevelStats_t *GetCurrentMap( void ) { return m_pCurrentMap; } - - Ep2LevelStats_t *m_pCurrentMap; - CUtlDict m_dictMapStats; - enum - { - INVEHICLE = 0, - ONFOOT, - ONFOOTSPRINTING, - - NUM_TRAVEL_TYPES - }; - float m_flInchesRemainder[ NUM_TRAVEL_TYPES ]; -}; -#endif - -#endif // EP2_GAMESTATS_H diff --git a/game/server/episodic/grenade_hopwire.cpp b/game/server/episodic/grenade_hopwire.cpp deleted file mode 100644 index 10e313914..000000000 --- a/game/server/episodic/grenade_hopwire.cpp +++ /dev/null @@ -1,581 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Gravity well device -// -//=====================================================================================// - -#include "cbase.h" -#include "grenade_hopwire.h" -#include "rope.h" -#include "rope_shared.h" -#include "beam_shared.h" -#include "physics.h" -#include "physics_saverestore.h" -#include "explode.h" -#include "physics_prop_ragdoll.h" -#include "movevars_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar hopwire_vortex( "hopwire_vortex", "0" ); -ConVar hopwire_trap( "hopwire_trap", "1" ); -ConVar hopwire_strider_kill_dist_h( "hopwire_strider_kill_dist_h", "300" ); -ConVar hopwire_strider_kill_dist_v( "hopwire_strider_kill_dist_v", "256" ); -ConVar hopwire_strider_hits( "hopwire_strider_hits", "1" ); -ConVar hopwire_hopheight( "hopwire_hopheight", "400" ); - -ConVar g_debug_hopwire( "g_debug_hopwire", "0" ); - -#define DENSE_BALL_MODEL "models/props_junk/metal_paintcan001b.mdl" - -#define MAX_HOP_HEIGHT (hopwire_hopheight.GetFloat()) // Maximum amount the grenade will "hop" upwards when detonated - -class CGravityVortexController : public CBaseEntity -{ - DECLARE_CLASS( CGravityVortexController, CBaseEntity ); - DECLARE_DATADESC(); - -public: - - CGravityVortexController( void ) : m_flMass( 0.0f ), m_flEndTime( 0.0f ), m_flRadius( 256.0f ), m_flStrength( 256.0f ) {} - float GetConsumedMass( void ) const; - - static CGravityVortexController *Create( const Vector &origin, float radius, float strength, float duration ); - -private: - - void ConsumeEntity( CBaseEntity *pEnt ); - void PullPlayersInRange( void ); - bool KillNPCInRange( CBaseEntity *pVictim, IPhysicsObject **pPhysObj ); - void CreateDenseBall( void ); - void PullThink( void ); - void StartPull( const Vector &origin, float radius, float strength, float duration ); - - float m_flMass; // Mass consumed by the vortex - float m_flEndTime; // Time when the vortex will stop functioning - float m_flRadius; // Area of effect for the vortex - float m_flStrength; // Pulling strength of the vortex -}; - -//----------------------------------------------------------------------------- -// Purpose: Returns the amount of mass consumed by the vortex -//----------------------------------------------------------------------------- -float CGravityVortexController::GetConsumedMass( void ) const -{ - return m_flMass; -} - -//----------------------------------------------------------------------------- -// Purpose: Adds the entity's mass to the aggregate mass consumed -//----------------------------------------------------------------------------- -void CGravityVortexController::ConsumeEntity( CBaseEntity *pEnt ) -{ - // Get our base physics object - IPhysicsObject *pPhysObject = pEnt->VPhysicsGetObject(); - if ( pPhysObject == NULL ) - return; - - // Ragdolls need to report the sum of all their parts - CRagdollProp *pRagdoll = dynamic_cast< CRagdollProp* >( pEnt ); - if ( pRagdoll != NULL ) - { - // Find the aggregate mass of the whole ragdoll - ragdoll_t *pRagdollPhys = pRagdoll->GetRagdoll(); - for ( int j = 0; j < pRagdollPhys->listCount; ++j ) - { - m_flMass += pRagdollPhys->list[j].pObject->GetMass(); - } - } - else - { - // Otherwise we just take the normal mass - m_flMass += pPhysObject->GetMass(); - } - - // Destroy the entity - UTIL_Remove( pEnt ); -} - -//----------------------------------------------------------------------------- -// Purpose: Causes players within the radius to be sucked in -//----------------------------------------------------------------------------- -void CGravityVortexController::PullPlayersInRange( void ) -{ - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - - Vector vecForce = GetAbsOrigin() - pPlayer->WorldSpaceCenter(); - float dist = VectorNormalize( vecForce ); - - // FIXME: Need a more deterministic method here - if ( dist < 128.0f ) - { - // Kill the player (with falling death sound and effects) - CTakeDamageInfo deathInfo( this, this, GetAbsOrigin(), GetAbsOrigin(), 200, DMG_FALL ); - pPlayer->TakeDamage( deathInfo ); - - if ( pPlayer->IsAlive() == false ) - { - color32 black = { 0, 0, 0, 255 }; - UTIL_ScreenFade( pPlayer, black, 0.1f, 0.0f, (FFADE_OUT|FFADE_STAYOUT) ); - return; - } - } - - // Must be within the radius - if ( dist > m_flRadius ) - return; - - float mass = pPlayer->VPhysicsGetObject()->GetMass(); - float playerForce = m_flStrength * 0.05f; - - // Find the pull force - // NOTE: We might want to make this non-linear to give more of a "grace distance" - vecForce *= ( 1.0f - ( dist / m_flRadius ) ) * playerForce * mass; - vecForce[2] *= 0.025f; - - pPlayer->SetBaseVelocity( vecForce ); - pPlayer->AddFlag( FL_BASEVELOCITY ); - - // Make sure the player moves - if ( vecForce.z > 0 && ( pPlayer->GetFlags() & FL_ONGROUND) ) - { - pPlayer->SetGroundEntity( NULL ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Attempts to kill an NPC if it's within range and other criteria -// Input : *pVictim - NPC to assess -// **pPhysObj - pointer to the ragdoll created if the NPC is killed -// Output : bool - whether or not the NPC was killed and the returned pointer is valid -//----------------------------------------------------------------------------- -bool CGravityVortexController::KillNPCInRange( CBaseEntity *pVictim, IPhysicsObject **pPhysObj ) -{ - CBaseCombatCharacter *pBCC = pVictim->MyCombatCharacterPointer(); - - // See if we can ragdoll - if ( pBCC != NULL && pBCC->CanBecomeRagdoll() ) - { - // Don't bother with striders - if ( FClassnameIs( pBCC, "npc_strider" ) ) - return false; - - // TODO: Make this an interaction between the NPC and the vortex - - // Become ragdoll - CTakeDamageInfo info( this, this, 1.0f, DMG_GENERIC ); - CBaseEntity *pRagdoll = CreateServerRagdoll( pBCC, 0, info, COLLISION_GROUP_INTERACTIVE_DEBRIS, true ); - pRagdoll->SetCollisionBounds( pVictim->CollisionProp()->OBBMins(), pVictim->CollisionProp()->OBBMaxs() ); - - // Necessary to cause it to do the appropriate death cleanup - CTakeDamageInfo ragdollInfo( this, this, 10000.0, DMG_GENERIC | DMG_REMOVENORAGDOLL ); - pVictim->TakeDamage( ragdollInfo ); - - // Return the pointer to the ragdoll - *pPhysObj = pRagdoll->VPhysicsGetObject(); - return true; - } - - // Wasn't able to ragdoll this target - *pPhysObj = NULL; - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Creates a dense ball with a mass equal to the aggregate mass consumed by the vortex -//----------------------------------------------------------------------------- -void CGravityVortexController::CreateDenseBall( void ) -{ - CBaseEntity *pBall = CreateEntityByName( "prop_physics" ); - - pBall->SetModel( DENSE_BALL_MODEL ); - pBall->SetAbsOrigin( GetAbsOrigin() ); - pBall->Spawn(); - - IPhysicsObject *pObj = pBall->VPhysicsGetObject(); - if ( pObj != NULL ) - { - pObj->SetMass( GetConsumedMass() ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Pulls physical objects towards the vortex center, killing them if they come too near -//----------------------------------------------------------------------------- -void CGravityVortexController::PullThink( void ) -{ - // Pull any players close enough to us - PullPlayersInRange(); - - Vector mins, maxs; - mins = GetAbsOrigin() - Vector( m_flRadius, m_flRadius, m_flRadius ); - maxs = GetAbsOrigin() + Vector( m_flRadius, m_flRadius, m_flRadius ); - - // Draw debug information - if ( g_debug_hopwire.GetBool() ) - { - NDebugOverlay::Box( GetAbsOrigin(), mins - GetAbsOrigin(), maxs - GetAbsOrigin(), 0, 255, 0, 16, 4.0f ); - } - - CBaseEntity *pEnts[128]; - int numEnts = UTIL_EntitiesInBox( pEnts, 128, mins, maxs, 0 ); - - for ( int i = 0; i < numEnts; i++ ) - { - IPhysicsObject *pPhysObject = NULL; - - // Attempt to kill and ragdoll any victims in range - if ( KillNPCInRange( pEnts[i], &pPhysObject ) == false ) - { - // If we didn't have a valid victim, see if we can just get the vphysics object - pPhysObject = pEnts[i]->VPhysicsGetObject(); - if ( pPhysObject == NULL ) - continue; - } - - float mass; - - CRagdollProp *pRagdoll = dynamic_cast< CRagdollProp* >( pEnts[i] ); - if ( pRagdoll != NULL ) - { - ragdoll_t *pRagdollPhys = pRagdoll->GetRagdoll(); - mass = 0.0f; - - // Find the aggregate mass of the whole ragdoll - for ( int j = 0; j < pRagdollPhys->listCount; ++j ) - { - mass += pRagdollPhys->list[j].pObject->GetMass(); - } - } - else - { - mass = pPhysObject->GetMass(); - } - - Vector vecForce = GetAbsOrigin() - pEnts[i]->WorldSpaceCenter(); - Vector vecForce2D = vecForce; - vecForce2D[2] = 0.0f; - float dist2D = VectorNormalize( vecForce2D ); - float dist = VectorNormalize( vecForce ); - - // FIXME: Need a more deterministic method here - if ( dist < 48.0f ) - { - ConsumeEntity( pEnts[i] ); - continue; - } - - // Must be within the radius - if ( dist > m_flRadius ) - continue; - - // Find the pull force - vecForce *= ( 1.0f - ( dist2D / m_flRadius ) ) * m_flStrength * mass; - - if ( pEnts[i]->VPhysicsGetObject() ) - { - // Pull the object in - pEnts[i]->VPhysicsTakeDamage( CTakeDamageInfo( this, this, vecForce, GetAbsOrigin(), m_flStrength, DMG_BLAST ) ); - } - } - - // Keep going if need-be - if ( m_flEndTime > gpGlobals->curtime ) - { - SetThink( &CGravityVortexController::PullThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); - } - else - { - //Msg( "Consumed %.2f kilograms\n", m_flMass ); - //CreateDenseBall(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Starts the vortex working -//----------------------------------------------------------------------------- -void CGravityVortexController::StartPull( const Vector &origin, float radius, float strength, float duration ) -{ - SetAbsOrigin( origin ); - m_flEndTime = gpGlobals->curtime + duration; - m_flRadius = radius; - m_flStrength= strength; - - SetThink( &CGravityVortexController::PullThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -//----------------------------------------------------------------------------- -// Purpose: Creation utility -//----------------------------------------------------------------------------- -CGravityVortexController *CGravityVortexController::Create( const Vector &origin, float radius, float strength, float duration ) -{ - // Create an instance of the vortex - CGravityVortexController *pVortex = (CGravityVortexController *) CreateEntityByName( "vortex_controller" ); - if ( pVortex == NULL ) - return NULL; - - // Start the vortex working - pVortex->StartPull( origin, radius, strength, duration ); - - return pVortex; -} - -BEGIN_DATADESC( CGravityVortexController ) - DEFINE_FIELD( m_flMass, FIELD_FLOAT ), - DEFINE_FIELD( m_flEndTime, FIELD_TIME ), - DEFINE_FIELD( m_flRadius, FIELD_FLOAT ), - DEFINE_FIELD( m_flStrength, FIELD_FLOAT ), - - DEFINE_THINKFUNC( PullThink ), -END_DATADESC() - -LINK_ENTITY_TO_CLASS( vortex_controller, CGravityVortexController ); - -#define GRENADE_MODEL_CLOSED "models/roller.mdl" -#define GRENADE_MODEL_OPEN "models/roller_spikes.mdl" - -BEGIN_DATADESC( CGrenadeHopwire ) - DEFINE_FIELD( m_hVortexController, FIELD_EHANDLE ), - - DEFINE_THINKFUNC( EndThink ), - DEFINE_THINKFUNC( CombatThink ), -END_DATADESC() - -LINK_ENTITY_TO_CLASS( npc_grenade_hopwire, CGrenadeHopwire ); - -IMPLEMENT_SERVERCLASS_ST( CGrenadeHopwire, DT_GrenadeHopwire ) -END_SEND_TABLE() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGrenadeHopwire::Spawn( void ) -{ - Precache(); - - SetModel( GRENADE_MODEL_CLOSED ); - SetCollisionGroup( COLLISION_GROUP_PROJECTILE ); - - CreateVPhysics(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CGrenadeHopwire::CreateVPhysics() -{ - // Create the object in the physics system - VPhysicsInitNormal( SOLID_BBOX, 0, false ); - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGrenadeHopwire::Precache( void ) -{ - // FIXME: Replace - //PrecacheSound("NPC_Strider.Shoot"); - //PrecacheSound("d3_citadel.weapon_zapper_beam_loop2"); - - PrecacheModel( GRENADE_MODEL_OPEN ); - PrecacheModel( GRENADE_MODEL_CLOSED ); - - PrecacheModel( DENSE_BALL_MODEL ); - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : timer - -//----------------------------------------------------------------------------- -void CGrenadeHopwire::SetTimer( float timer ) -{ - SetThink( &CBaseGrenade::PreDetonate ); - SetNextThink( gpGlobals->curtime + timer ); -} - -#define MAX_STRIDER_KILL_DISTANCE_HORZ (hopwire_strider_kill_dist_h.GetFloat()) // Distance a Strider will be killed if within -#define MAX_STRIDER_KILL_DISTANCE_VERT (hopwire_strider_kill_dist_v.GetFloat()) // Distance a Strider will be killed if within - -#define MAX_STRIDER_STUN_DISTANCE_HORZ (MAX_STRIDER_KILL_DISTANCE_HORZ*2) // Distance a Strider will be stunned if within -#define MAX_STRIDER_STUN_DISTANCE_VERT (MAX_STRIDER_KILL_DISTANCE_VERT*2) // Distance a Strider will be stunned if within - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGrenadeHopwire::KillStriders( void ) -{ - CBaseEntity *pEnts[128]; - Vector mins, maxs; - - ClearBounds( mins, maxs ); - AddPointToBounds( -Vector( MAX_STRIDER_STUN_DISTANCE_HORZ, MAX_STRIDER_STUN_DISTANCE_HORZ, MAX_STRIDER_STUN_DISTANCE_HORZ ), mins, maxs ); - AddPointToBounds( Vector( MAX_STRIDER_STUN_DISTANCE_HORZ, MAX_STRIDER_STUN_DISTANCE_HORZ, MAX_STRIDER_STUN_DISTANCE_HORZ ), mins, maxs ); - AddPointToBounds( -Vector( MAX_STRIDER_STUN_DISTANCE_VERT, MAX_STRIDER_STUN_DISTANCE_VERT, MAX_STRIDER_STUN_DISTANCE_VERT ), mins, maxs ); - AddPointToBounds( Vector( MAX_STRIDER_STUN_DISTANCE_VERT, MAX_STRIDER_STUN_DISTANCE_VERT, MAX_STRIDER_STUN_DISTANCE_VERT ), mins, maxs ); - - // FIXME: It's probably much faster to simply iterate over the striders in the map, rather than any entity in the radius - jdw - - // Find any striders in range of us - int numTargets = UTIL_EntitiesInBox( pEnts, ARRAYSIZE( pEnts ), GetAbsOrigin()+mins, GetAbsOrigin()+maxs, FL_NPC ); - float targetDistHorz, targetDistVert; - - for ( int i = 0; i < numTargets; i++ ) - { - // Only affect striders - if ( FClassnameIs( pEnts[i], "npc_strider" ) == false ) - continue; - - // We categorize our spatial relation to the strider in horizontal and vertical terms, so that we can specify both parameters separately - targetDistHorz = UTIL_DistApprox2D( pEnts[i]->GetAbsOrigin(), GetAbsOrigin() ); - targetDistVert = fabs( pEnts[i]->GetAbsOrigin()[2] - GetAbsOrigin()[2] ); - - if ( targetDistHorz < MAX_STRIDER_KILL_DISTANCE_HORZ && targetDistHorz < MAX_STRIDER_KILL_DISTANCE_VERT ) - { - // Kill the strider - float fracDamage = ( pEnts[i]->GetMaxHealth() / hopwire_strider_hits.GetFloat() ) + 1.0f; - CTakeDamageInfo killInfo( this, this, fracDamage, DMG_GENERIC ); - Vector killDir = pEnts[i]->GetAbsOrigin() - GetAbsOrigin(); - VectorNormalize( killDir ); - - killInfo.SetDamageForce( killDir * -1000.0f ); - killInfo.SetDamagePosition( GetAbsOrigin() ); - - pEnts[i]->TakeDamage( killInfo ); - } - else if ( targetDistHorz < MAX_STRIDER_STUN_DISTANCE_HORZ && targetDistHorz < MAX_STRIDER_STUN_DISTANCE_VERT ) - { - // Stun the strider - CTakeDamageInfo killInfo( this, this, 200.0f, DMG_GENERIC ); - pEnts[i]->TakeDamage( killInfo ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGrenadeHopwire::EndThink( void ) -{ - if ( hopwire_vortex.GetBool() ) - { - EntityMessageBegin( this, true ); - WRITE_BYTE( 1 ); - MessageEnd(); - } - - SetThink( &CBaseEntity::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 1.0f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGrenadeHopwire::CombatThink( void ) -{ - // Stop the grenade from moving - AddEFlags( EF_NODRAW ); - AddFlag( FSOLID_NOT_SOLID ); - VPhysicsDestroyObject(); - SetAbsVelocity( vec3_origin ); - SetMoveType( MOVETYPE_NONE ); - - // Do special behaviors if there are any striders in the area - KillStriders(); - - // FIXME: Replace - //EmitSound("NPC_Strider.Shoot"); - //EmitSound("d3_citadel.weapon_zapper_beam_loop2"); - - // Quick screen flash - CBasePlayer *pPlayer = ToBasePlayer( GetThrower() ); - color32 white = { 255,255,255,255 }; - UTIL_ScreenFade( pPlayer, white, 0.2f, 0.0f, FFADE_IN ); - - // Create the vortex controller to pull entities towards us - if ( hopwire_vortex.GetBool() ) - { - m_hVortexController = CGravityVortexController::Create( GetAbsOrigin(), 512, 150, 3.0f ); - - // Start our client-side effect - EntityMessageBegin( this, true ); - WRITE_BYTE( 0 ); - MessageEnd(); - - // Begin to stop in two seconds - SetThink( &CGrenadeHopwire::EndThink ); - SetNextThink( gpGlobals->curtime + 2.0f ); - } - else - { - // Remove us immediately - SetThink( &CBaseEntity::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 0.1f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGrenadeHopwire::SetVelocity( const Vector &velocity, const AngularImpulse &angVelocity ) -{ - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - - if ( pPhysicsObject != NULL ) - { - pPhysicsObject->AddVelocity( &velocity, &angVelocity ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Hop off the ground to start deployment -//----------------------------------------------------------------------------- -void CGrenadeHopwire::Detonate( void ) -{ - SetModel( GRENADE_MODEL_OPEN ); - - AngularImpulse hopAngle = RandomAngularImpulse( -300, 300 ); - - //Find out how tall the ceiling is and always try to hop halfway - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, MAX_HOP_HEIGHT*2 ), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - - // Jump half the height to the found ceiling - float hopHeight = MIN( MAX_HOP_HEIGHT, (MAX_HOP_HEIGHT*tr.fraction) ); - - //Add upwards velocity for the "hop" - Vector hopVel( 0.0f, 0.0f, hopHeight ); - SetVelocity( hopVel, hopAngle ); - - // Get the time until the apex of the hop - float apexTime = sqrt( hopHeight / sv_gravity.GetFloat() ); - - // Explode at the apex - SetThink( &CGrenadeHopwire::CombatThink ); - SetNextThink( gpGlobals->curtime + apexTime); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseGrenade *HopWire_Create( const Vector &position, const QAngle &angles, const Vector &velocity, const AngularImpulse &angVelocity, CBaseEntity *pOwner, float timer ) -{ - CGrenadeHopwire *pGrenade = (CGrenadeHopwire *) CBaseEntity::Create( "npc_grenade_hopwire", position, angles, pOwner ); - - // Only set ourselves to detonate on a timer if we're not a trap hopwire - if ( hopwire_trap.GetBool() == false ) - { - pGrenade->SetTimer( timer ); - } - - pGrenade->SetVelocity( velocity, angVelocity ); - pGrenade->SetThrower( ToBaseCombatCharacter( pOwner ) ); - - return pGrenade; -} diff --git a/game/server/episodic/grenade_hopwire.h b/game/server/episodic/grenade_hopwire.h deleted file mode 100644 index 1b6d40b79..000000000 --- a/game/server/episodic/grenade_hopwire.h +++ /dev/null @@ -1,46 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef GRENADE_HOPWIRE_H -#define GRENADE_HOPWIRE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "basegrenade_shared.h" -#include "Sprite.h" - -extern ConVar hopwire_trap; - -class CGravityVortexController; - -class CGrenadeHopwire : public CBaseGrenade -{ - DECLARE_CLASS( CGrenadeHopwire, CBaseGrenade ); - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - -public: - void Spawn( void ); - void Precache( void ); - bool CreateVPhysics( void ); - void SetTimer( float timer ); - void SetVelocity( const Vector &velocity, const AngularImpulse &angVelocity ); - void Detonate( void ); - - void EndThink( void ); // Last think before going away - void CombatThink( void ); // Makes the main explosion go off - -protected: - - void KillStriders( void ); - - CHandle m_hVortexController; -}; - -extern CBaseGrenade *HopWire_Create( const Vector &position, const QAngle &angles, const Vector &velocity, const AngularImpulse &angVelocity, CBaseEntity *pOwner, float timer ); - -#endif // GRENADE_HOPWIRE_H diff --git a/game/server/episodic/npc_advisor.cpp b/game/server/episodic/npc_advisor.cpp deleted file mode 100644 index 0edd09c8b..000000000 --- a/game/server/episodic/npc_advisor.cpp +++ /dev/null @@ -1,2055 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ==== -// -// Advisors. Large sluglike aliens with creepy psychic powers! -// -//============================================================================= - -#include "cbase.h" -#include "game.h" -#include "ai_basenpc.h" -#include "ai_schedule.h" -#include "ai_hull.h" -#include "ai_hint.h" -#include "ai_motor.h" -#include "ai_navigator.h" -#include "beam_shared.h" -#include "hl2_shareddefs.h" -#include "ai_route.h" -#include "npcevent.h" -#include "gib.h" -#include "ai_interactions.h" -#include "ndebugoverlay.h" -#include "physics_saverestore.h" -#include "saverestore_utlvector.h" -#include "soundent.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "movevars_shared.h" -#include "particle_parse.h" -#include "weapon_physcannon.h" -// #include "mathlib/noise.h" - -// this file contains the definitions for the message ID constants (eg ADVISOR_MSG_START_BEAM etc) -#include "npc_advisor_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// -// Custom activities. -// - -// -// Skill settings. -// -ConVar sk_advisor_health( "sk_advisor_health", "0" ); -ConVar advisor_use_impact_table("advisor_use_impact_table","1",FCVAR_NONE,"If true, advisor will use her custom impact damage table."); - -#if NPC_ADVISOR_HAS_BEHAVIOR -ConVar advisor_throw_velocity( "advisor_throw_velocity", "1100" ); -ConVar advisor_throw_rate( "advisor_throw_rate", "4" ); // Throw an object every 4 seconds. -ConVar advisor_throw_warn_time( "advisor_throw_warn_time", "1.0" ); // Warn players one second before throwing an object. -ConVar advisor_throw_lead_prefetch_time ( "advisor_throw_lead_prefetch_time", "0.66", FCVAR_NONE, "Save off the player's velocity this many seconds before throwing."); -ConVar advisor_throw_stage_distance("advisor_throw_stage_distance","180.0",FCVAR_NONE,"Advisor will try to hold an object this far in front of him just before throwing it at you. Small values will clobber the shield and be very bad."); -// ConVar advisor_staging_num("advisor_staging_num","1",FCVAR_NONE,"Advisor will queue up this many objects to throw at Gordon."); -ConVar advisor_throw_clearout_vel("advisor_throw_clearout_vel","200",FCVAR_NONE,"TEMP: velocity with which advisor clears things out of a throwable's way"); -// ConVar advisor_staging_duration(" - -// how long it will take an object to get hauled to the staging point -#define STAGING_OBJECT_FALLOFF_TIME 0.15f -#endif - - - -// -// Spawnflags. -// - -// -// Animation events. -// - - -#if NPC_ADVISOR_HAS_BEHAVIOR -// -// Custom schedules. -// -enum -{ - SCHED_ADVISOR_COMBAT = LAST_SHARED_SCHEDULE, - SCHED_ADVISOR_IDLE_STAND, - SCHED_ADVISOR_TOSS_PLAYER -}; - - -// -// Custom tasks. -// -enum -{ - TASK_ADVISOR_FIND_OBJECTS = LAST_SHARED_TASK, - TASK_ADVISOR_LEVITATE_OBJECTS, - TASK_ADVISOR_STAGE_OBJECTS, - TASK_ADVISOR_BARRAGE_OBJECTS, - - TASK_ADVISOR_PIN_PLAYER, -}; - -// -// Custom conditions. -// -enum -{ - COND_ADVISOR_PHASE_INTERRUPT = LAST_SHARED_CONDITION, -}; -#endif - -class CNPC_Advisor; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -class CAdvisorLevitate : public IMotionEvent -{ - DECLARE_SIMPLE_DATADESC(); - -public: - - // in the absence of goal entities, we float up before throwing and down after - inline bool OldStyle( void ) - { - return !(m_vecGoalPos1.IsValid() && m_vecGoalPos2.IsValid()); - } - - virtual simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ); - - EHANDLE m_Advisor; ///< handle to the advisor. - - Vector m_vecGoalPos1; - Vector m_vecGoalPos2; - - float m_flFloat; -}; - -BEGIN_SIMPLE_DATADESC( CAdvisorLevitate ) - DEFINE_FIELD( m_flFloat, FIELD_FLOAT ), - DEFINE_FIELD( m_vecGoalPos1, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecGoalPos2, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_Advisor, FIELD_EHANDLE ), -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// The advisor class. -//----------------------------------------------------------------------------- -class CNPC_Advisor : public CAI_BaseNPC -{ - DECLARE_CLASS( CNPC_Advisor, CAI_BaseNPC ); - -#if NPC_ADVISOR_HAS_BEHAVIOR - DECLARE_SERVERCLASS(); -#endif - -public: - - // - // CBaseEntity: - // - virtual void Activate(); - virtual void Spawn(); - virtual void Precache(); - virtual void OnRestore(); - virtual void UpdateOnRemove(); - - virtual int DrawDebugTextOverlays(); - - // - // CAI_BaseNPC: - // - virtual float MaxYawSpeed() { return 120.0f; } - - virtual Class_T Classify(); - -#if NPC_ADVISOR_HAS_BEHAVIOR - virtual int GetSoundInterests(); - virtual int SelectSchedule(); - virtual void StartTask( const Task_t *pTask ); - virtual void RunTask( const Task_t *pTask ); - virtual void OnScheduleChange( void ); -#endif - - virtual void PainSound( const CTakeDamageInfo &info ); - virtual void DeathSound( const CTakeDamageInfo &info ); - virtual void IdleSound(); - virtual void AlertSound(); - -#if NPC_ADVISOR_HAS_BEHAVIOR - virtual bool QueryHearSound( CSound *pSound ); - virtual void GatherConditions( void ); - - /// true iff I recently threw the given object (not so fast) - bool DidThrow(const CBaseEntity *pEnt); -#else - inline bool DidThrow(const CBaseEntity *pEnt) { return false; } -#endif - - virtual bool IsHeavyDamage( const CTakeDamageInfo &info ); - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - - virtual const impactdamagetable_t &GetPhysicsImpactDamageTable( void ); - COutputInt m_OnHealthIsNow; - -#if NPC_ADVISOR_HAS_BEHAVIOR - - DEFINE_CUSTOM_AI; - - void InputSetThrowRate( inputdata_t &inputdata ); - void InputWrenchImmediate( inputdata_t &inputdata ); ///< immediately wrench an object into the air - void InputSetStagingNum( inputdata_t &inputdata ); - void InputPinPlayer( inputdata_t &inputdata ); - void InputTurnBeamOn( inputdata_t &inputdata ); - void InputTurnBeamOff( inputdata_t &inputdata ); - void InputElightOn( inputdata_t &inputdata ); - void InputElightOff( inputdata_t &inputdata ); - - COutputEvent m_OnPickingThrowable, m_OnThrowWarn, m_OnThrow; - - enum { kMaxThrownObjectsTracked = 4 }; -#endif - - DECLARE_DATADESC(); - -protected: - -#if NPC_ADVISOR_HAS_BEHAVIOR - Vector GetThrowFromPos( CBaseEntity *pEnt ); ///< Get the position in which we shall hold an object prior to throwing it -#endif - - bool CanLevitateEntity( CBaseEntity *pEntity, int minMass, int maxMass ); - void StartLevitatingObjects( void ); - - -#if NPC_ADVISOR_HAS_BEHAVIOR - // void PurgeThrownObjects(); ///< clean out the recently thrown objects array - void AddToThrownObjects(CBaseEntity *pEnt); ///< add to the recently thrown objects array - - void HurlObjectAtPlayer( CBaseEntity *pEnt, const Vector &leadVel ); - void PullObjectToStaging( CBaseEntity *pEnt, const Vector &stagingPos ); - CBaseEntity *ThrowObjectPrepare( void ); - - CBaseEntity *PickThrowable( bool bRequireInView ); ///< choose an object to throw at the player (so it can get stuffed in the handle array) - - /// push everything out of the way between an object I'm about to throw and the player. - void PreHurlClearTheWay( CBaseEntity *pThrowable, const Vector &toPos ); -#endif - - CUtlVector m_physicsObjects; - IPhysicsMotionController *m_pLevitateController; - CAdvisorLevitate m_levitateCallback; - - EHANDLE m_hLevitateGoal1; - EHANDLE m_hLevitateGoal2; - EHANDLE m_hLevitationArea; - -#if NPC_ADVISOR_HAS_BEHAVIOR - // EHANDLE m_hThrowEnt; - CUtlVector m_hvStagedEnts; - CUtlVector m_hvStagingPositions; - // todo: write accessor functions for m_hvStagedEnts so that it doesn't have members added and removed willy nilly throughout - // code (will make the networking below more reliable) - - void Write_BeamOn( CBaseEntity *pEnt ); ///< write a message turning a beam on - void Write_BeamOff( CBaseEntity *pEnt ); ///< write a message turning a beam off - void Write_AllBeamsOff( void ); ///< tell client to kill all beams - - // for the pin-the-player-to-something behavior - EHANDLE m_hPlayerPinPos; - float m_playerPinFailsafeTime; - - // keep track of up to four objects after we have thrown them, to prevent oscillation or levitation of recently thrown ammo. - EHANDLE m_haRecentlyThrownObjects[kMaxThrownObjectsTracked]; - float m_flaRecentlyThrownObjectTimes[kMaxThrownObjectsTracked]; -#endif - - string_t m_iszLevitateGoal1; - string_t m_iszLevitateGoal2; - string_t m_iszLevitationArea; - - -#if NPC_ADVISOR_HAS_BEHAVIOR - string_t m_iszStagingEntities; - string_t m_iszPriorityEntityGroupName; - - float m_flStagingEnd; - float m_flThrowPhysicsTime; - float m_flLastThrowTime; - float m_flLastPlayerAttackTime; ///< last time the player attacked something. - - int m_iStagingNum; ///< number of objects advisor stages at once - bool m_bWasScripting; - - // unsigned char m_pickFailures; // the number of times we have tried to pick a throwable and failed - - Vector m_vSavedLeadVel; ///< save off player velocity for leading a bit before actually pelting them. -#endif -}; - - -LINK_ENTITY_TO_CLASS( npc_advisor, CNPC_Advisor ); - -BEGIN_DATADESC( CNPC_Advisor ) - - DEFINE_KEYFIELD( m_iszLevitateGoal1, FIELD_STRING, "levitategoal_bottom" ), - DEFINE_KEYFIELD( m_iszLevitateGoal2, FIELD_STRING, "levitategoal_top" ), - DEFINE_KEYFIELD( m_iszLevitationArea, FIELD_STRING, "levitationarea"), ///< we will float all the objects in this volume - - DEFINE_PHYSPTR( m_pLevitateController ), - DEFINE_EMBEDDED( m_levitateCallback ), - DEFINE_UTLVECTOR( m_physicsObjects, FIELD_EHANDLE ), - - DEFINE_FIELD( m_hLevitateGoal1, FIELD_EHANDLE ), - DEFINE_FIELD( m_hLevitateGoal2, FIELD_EHANDLE ), - DEFINE_FIELD( m_hLevitationArea, FIELD_EHANDLE ), - -#if NPC_ADVISOR_HAS_BEHAVIOR - DEFINE_KEYFIELD( m_iszStagingEntities, FIELD_STRING, "staging_ent_names"), ///< entities named this constitute the positions to which we stage objects to be thrown - DEFINE_KEYFIELD( m_iszPriorityEntityGroupName, FIELD_STRING, "priority_grab_name"), - - DEFINE_UTLVECTOR( m_hvStagedEnts, FIELD_EHANDLE ), - DEFINE_UTLVECTOR( m_hvStagingPositions, FIELD_EHANDLE ), - DEFINE_ARRAY( m_haRecentlyThrownObjects, FIELD_EHANDLE, CNPC_Advisor::kMaxThrownObjectsTracked ), - DEFINE_ARRAY( m_flaRecentlyThrownObjectTimes, FIELD_TIME, CNPC_Advisor::kMaxThrownObjectsTracked ), - - DEFINE_FIELD( m_hPlayerPinPos, FIELD_EHANDLE ), - DEFINE_FIELD( m_playerPinFailsafeTime, FIELD_TIME ), - - // DEFINE_FIELD( m_hThrowEnt, FIELD_EHANDLE ), - DEFINE_FIELD( m_flThrowPhysicsTime, FIELD_TIME ), - DEFINE_FIELD( m_flLastPlayerAttackTime, FIELD_TIME ), - DEFINE_FIELD( m_flStagingEnd, FIELD_TIME ), - DEFINE_FIELD( m_iStagingNum, FIELD_INTEGER ), - DEFINE_FIELD( m_bWasScripting, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_flLastThrowTime, FIELD_TIME ), - DEFINE_FIELD( m_vSavedLeadVel, FIELD_VECTOR ), - - DEFINE_OUTPUT( m_OnPickingThrowable, "OnPickingThrowable" ), - DEFINE_OUTPUT( m_OnThrowWarn, "OnThrowWarn" ), - DEFINE_OUTPUT( m_OnThrow, "OnThrow" ), - DEFINE_OUTPUT( m_OnHealthIsNow, "OnHealthIsNow" ), - - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetThrowRate", InputSetThrowRate ), - DEFINE_INPUTFUNC( FIELD_STRING, "WrenchImmediate", InputWrenchImmediate ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetStagingNum", InputSetStagingNum), - DEFINE_INPUTFUNC( FIELD_STRING, "PinPlayer", InputPinPlayer ), - DEFINE_INPUTFUNC( FIELD_STRING, "BeamOn", InputTurnBeamOn ), - DEFINE_INPUTFUNC( FIELD_STRING, "BeamOff", InputTurnBeamOff ), - DEFINE_INPUTFUNC( FIELD_STRING, "ElightOn", InputElightOn ), - DEFINE_INPUTFUNC( FIELD_STRING, "ElightOff", InputElightOff ), -#endif - -END_DATADESC() - - - -#if NPC_ADVISOR_HAS_BEHAVIOR -IMPLEMENT_SERVERCLASS_ST(CNPC_Advisor, DT_NPC_Advisor) - -END_SEND_TABLE() -#endif - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Advisor::Spawn() -{ - BaseClass::Spawn(); - -#ifdef _XBOX - // Always fade the corpse - AddSpawnFlags( SF_NPC_FADE_CORPSE ); -#endif // _XBOX - - Precache(); - - SetModel( STRING( GetModelName() ) ); - - m_iHealth = sk_advisor_health.GetFloat(); - m_takedamage = DAMAGE_NO; - - SetHullType( HULL_LARGE_CENTERED ); - SetHullSizeNormal(); - - SetSolid( SOLID_BBOX ); - // AddSolidFlags( FSOLID_NOT_SOLID ); - - SetMoveType( MOVETYPE_FLY ); - - m_flFieldOfView = VIEW_FIELD_FULL; - SetViewOffset( Vector( 0, 0, 80 ) ); // Position of the eyes relative to NPC's origin. - - SetBloodColor( BLOOD_COLOR_GREEN ); - m_NPCState = NPC_STATE_NONE; - - CapabilitiesClear(); - - NPCInit(); - - SetGoalEnt( NULL ); - - AddEFlags( EFL_NO_DISSOLVE ); -} - - -#if NPC_ADVISOR_HAS_BEHAVIOR -//----------------------------------------------------------------------------- -// comparison function for qsort used below. Compares "StagingPriority" keyfield -//----------------------------------------------------------------------------- -int __cdecl AdvisorStagingComparator(const EHANDLE *pe1, const EHANDLE *pe2) -{ - // bool ReadKeyField( const char *varName, variant_t *var ); - - variant_t var; - int val1 = 10, val2 = 10; // default priority is ten - - // read field one - if ( pe1->Get()->ReadKeyField( "StagingPriority", &var ) ) - { - val1 = var.Int(); - } - - // read field two - if ( pe2->Get()->ReadKeyField( "StagingPriority", &var ) ) - { - val2 = var.Int(); - } - - // return comparison (< 0 if pe1 0, "You did not specify any staging positions in the advisor's staging_ent_names !"); -#endif -} - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Advisor::UpdateOnRemove() -{ - if ( m_pLevitateController ) - { - physenv->DestroyMotionController( m_pLevitateController ); - } - - BaseClass::UpdateOnRemove(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Advisor::OnRestore() -{ - BaseClass::OnRestore(); - StartLevitatingObjects(); -} - - -//----------------------------------------------------------------------------- -// Returns this monster's classification in the relationship table. -//----------------------------------------------------------------------------- -Class_T CNPC_Advisor::Classify() -{ - return CLASS_COMBINE; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Advisor::IsHeavyDamage( const CTakeDamageInfo &info ) -{ - return (info.GetDamage() > 0); -} - - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Advisor::StartLevitatingObjects() -{ - if ( !m_pLevitateController ) - { - m_pLevitateController = physenv->CreateMotionController( &m_levitateCallback ); - } - - m_pLevitateController->ClearObjects(); - - int nCount = m_physicsObjects.Count(); - for ( int i = 0; i < nCount; i++ ) - { - CBaseEntity *pEnt = m_physicsObjects.Element( i ); - if ( !pEnt ) - continue; - - //NDebugOverlay::Box( pEnt->GetAbsOrigin(), pEnt->CollisionProp()->OBBMins(), pEnt->CollisionProp()->OBBMaxs(), 0, 255, 0, 1, 0.1 ); - - IPhysicsObject *pPhys = pEnt->VPhysicsGetObject(); - if ( pPhys && pPhys->IsMoveable() ) - { - m_pLevitateController->AttachObject( pPhys, false ); - pPhys->Wake(); - } - } -} - -// This function is used by both version of the entity finder below -bool CNPC_Advisor::CanLevitateEntity( CBaseEntity *pEntity, int minMass, int maxMass ) -{ - if (!pEntity || pEntity->IsNPC()) - return false; - - IPhysicsObject *pPhys = pEntity->VPhysicsGetObject(); - if (!pPhys) - return false; - - float mass = pPhys->GetMass(); - - return ( mass >= minMass && - mass <= maxMass && - //pEntity->VPhysicsGetObject()->IsAsleep() && - pPhys->IsMoveable() /* && - !DidThrow(pEntity) */ ); -} - -#if NPC_ADVISOR_HAS_BEHAVIOR -// find an object to throw at the player and start the warning on it. Return object's -// pointer if we got something. Otherwise, return NULL if nothing left to throw. Will -// always leave the prepared object at the head of m_hvStagedEnts -CBaseEntity *CNPC_Advisor::ThrowObjectPrepare() -{ - - CBaseEntity *pThrowable = NULL; - while (m_hvStagedEnts.Count() > 0) - { - pThrowable = m_hvStagedEnts[0]; - - if (pThrowable) - { - IPhysicsObject *pPhys = pThrowable->VPhysicsGetObject(); - if ( !pPhys ) - { - // reject! - - Write_BeamOff(m_hvStagedEnts[0]); - pThrowable = NULL; - } - } - - // if we still have pThrowable... - if (pThrowable) - { - // we're good - break; - } - else - { - m_hvStagedEnts.Remove(0); - } - } - - if (pThrowable) - { - Assert( pThrowable->VPhysicsGetObject() ); - - // play the sound, attach the light, fire the trigger - EmitSound( "NPC_Advisor.ObjectChargeUp" ); - - m_OnThrowWarn.FireOutput(pThrowable,this); - m_flThrowPhysicsTime = gpGlobals->curtime + advisor_throw_warn_time.GetFloat(); - - if ( GetEnemy() ) - { - PreHurlClearTheWay( pThrowable, GetEnemy()->EyePosition() ); - } - - return pThrowable; - } - else // we had nothing to throw - { - return NULL; - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Advisor::StartTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - // DVS: TODO: if this gets expensive we can start caching the results and doing it less often. - case TASK_ADVISOR_FIND_OBJECTS: - { - // if we have a trigger volume, use the contents of that. If not, use a hardcoded box (for debugging purposes) - // in both cases we validate the objects using the same helper funclet just above. When we can count on the - // trigger vol being there, we can elide the else{} clause here. - - CBaseEntity *pVolume = m_hLevitationArea; - AssertMsg(pVolume, "Combine advisor needs 'levitationarea' key pointing to a trigger volume." ); - - if (!pVolume) - { - TaskFail( "No levitation area found!" ); - break; - } - - touchlink_t *touchroot = ( touchlink_t * )pVolume->GetDataObject( TOUCHLINK ); - if ( touchroot ) - { - - m_physicsObjects.RemoveAll(); - - for ( touchlink_t *link = touchroot->nextLink; link != touchroot; link = link->nextLink ) - { - CBaseEntity *pTouch = link->entityTouched; - if ( CanLevitateEntity( pTouch, 10, 220 ) ) - { - if ( pTouch->GetMoveType() == MOVETYPE_VPHYSICS ) - { - //Msg( " %d added %s\n", m_physicsObjects.Count(), STRING( list[i]->GetModelName() ) ); - m_physicsObjects.AddToTail( pTouch ); - } - } - } - } - - /* - // this is the old mechanism, using a hardcoded box and an entity enumerator. - // since deprecated. - - else - { - CBaseEntity *list[128]; - - m_physicsObjects.RemoveAll(); - - //NDebugOverlay::Box( GetAbsOrigin(), Vector( -408, -368, -188 ), Vector( 92, 208, 168 ), 255, 255, 0, 1, 5 ); - - // one-off class used to determine which entities we want from the UTIL_EntitiesInBox - class CAdvisorLevitateEntitiesEnum : public CFlaggedEntitiesEnum - { - public: - CAdvisorLevitateEntitiesEnum( CBaseEntity **pList, int listMax, int nMinMass, int nMaxMass ) - : CFlaggedEntitiesEnum( pList, listMax, 0 ), - m_nMinMass( nMinMass ), - m_nMaxMass( nMaxMass ) - { - } - - virtual IterationRetval_t EnumElement( IHandleEntity *pHandleEntity ) - { - CBaseEntity *pEntity = gEntList.GetBaseEntity( pHandleEntity->GetRefEHandle() ); - if ( AdvisorCanLevitateEntity( pEntity, m_nMinMass, m_nMaxMass ) ) - { - return CFlaggedEntitiesEnum::EnumElement( pHandleEntity ); - } - return ITERATION_CONTINUE; - } - - int m_nMinMass; - int m_nMaxMass; - }; - - CAdvisorLevitateEntitiesEnum levitateEnum( list, ARRAYSIZE( list ), 10, 220 ); - - int nCount = UTIL_EntitiesInBox( GetAbsOrigin() - Vector( 554, 368, 188 ), GetAbsOrigin() + Vector( 92, 208, 168 ), &levitateEnum ); - for ( int i = 0; i < nCount; i++ ) - { - //Msg( "%d found %s\n", m_physicsObjects.Count(), STRING( list[i]->GetModelName() ) ); - if ( list[i]->GetMoveType() == MOVETYPE_VPHYSICS ) - { - //Msg( " %d added %s\n", m_physicsObjects.Count(), STRING( list[i]->GetModelName() ) ); - m_physicsObjects.AddToTail( list[i] ); - } - } - } - */ - - if ( m_physicsObjects.Count() > 0 ) - { - TaskComplete(); - } - else - { - TaskFail( "No physics objects found!" ); - } - - break; - } - - case TASK_ADVISOR_LEVITATE_OBJECTS: - { - StartLevitatingObjects(); - - m_flThrowPhysicsTime = gpGlobals->curtime + advisor_throw_rate.GetFloat(); - - break; - } - - case TASK_ADVISOR_STAGE_OBJECTS: - { - // m_pickFailures = 0; - // clear out previously staged throwables - /* - for (int ii = m_hvStagedEnts.Count() - 1; ii >= 0 ; --ii) - { - m_hvStagedEnts[ii] = NULL; - } - */ - Write_AllBeamsOff(); - m_hvStagedEnts.RemoveAll(); - - m_OnPickingThrowable.FireOutput(NULL,this); - m_flStagingEnd = gpGlobals->curtime + pTask->flTaskData; - - break; - } - - // we're about to pelt the player with everything. Start the warning effect on the first object. - case TASK_ADVISOR_BARRAGE_OBJECTS: - { - - CBaseEntity *pThrowable = ThrowObjectPrepare(); - - if (!pThrowable || m_hvStagedEnts.Count() < 1) - { - TaskFail( "Nothing to throw!" ); - return; - } - - m_vSavedLeadVel.Invalidate(); - - break; - } - - case TASK_ADVISOR_PIN_PLAYER: - { - - // should never be here - /* - Assert( m_hPlayerPinPos.IsValid() ); - m_playerPinFailsafeTime = gpGlobals->curtime + 10.0f; - - break; - */ - } - - default: - { - BaseClass::StartTask( pTask ); - } - } -} - - -//----------------------------------------------------------------------------- -// todo: find a way to guarantee that objects are made pickupable again when bailing out of a task -//----------------------------------------------------------------------------- -void CNPC_Advisor::RunTask( const Task_t *pTask ) -{ - - switch ( pTask->iTask ) - { - // Raise up the objects that we found and then hold them. - case TASK_ADVISOR_LEVITATE_OBJECTS: - { - float flTimeToThrow = m_flThrowPhysicsTime - gpGlobals->curtime; - if ( flTimeToThrow < 0 ) - { - TaskComplete(); - return; - } - - // set the top and bottom on the levitation volume from the entities. If we don't have - // both, zero it out so that we can use the old-style simpler mechanism. - if ( m_hLevitateGoal1 && m_hLevitateGoal2 ) - { - m_levitateCallback.m_vecGoalPos1 = m_hLevitateGoal1->GetAbsOrigin(); - m_levitateCallback.m_vecGoalPos2 = m_hLevitateGoal2->GetAbsOrigin(); - // swap them if necessary (1 must be the bottom) - if (m_levitateCallback.m_vecGoalPos1.z > m_levitateCallback.m_vecGoalPos2.z) - { - swap(m_levitateCallback.m_vecGoalPos1,m_levitateCallback.m_vecGoalPos2); - } - - m_levitateCallback.m_flFloat = 0.06f; // this is an absolute accumulation upon gravity - } - else - { - m_levitateCallback.m_vecGoalPos1.Invalidate(); - m_levitateCallback.m_vecGoalPos2.Invalidate(); - - // the below two stanzas are used for old-style floating, which is linked - // to float up before thrown and down after - if ( flTimeToThrow > 2.0f ) - { - m_levitateCallback.m_flFloat = 1.06f; - } - else - { - m_levitateCallback.m_flFloat = 0.94f; - } - } - - /* - // Draw boxes around the objects we're levitating. - for ( int i = 0; i < m_physicsObjects.Count(); i++ ) - { - CBaseEntity *pEnt = m_physicsObjects.Element( i ); - if ( !pEnt ) - continue; // The prop has been broken! - - IPhysicsObject *pPhys = pEnt->VPhysicsGetObject(); - if ( pPhys && pPhys->IsMoveable() ) - { - NDebugOverlay::Box( pEnt->GetAbsOrigin(), pEnt->CollisionProp()->OBBMins(), pEnt->CollisionProp()->OBBMaxs(), 0, 255, 0, 1, 0.1 ); - } - }*/ - - break; - } - - // Pick a random object that we are levitating. If we have a clear LOS from that object - // to our enemy's eyes, choose that one to throw. Otherwise, keep looking. - case TASK_ADVISOR_STAGE_OBJECTS: - { - if (m_iStagingNum > m_hvStagingPositions.Count()) - { - Warning( "Advisor tries to stage %d objects but only has %d positions named %s! Overriding.\n", m_iStagingNum, m_hvStagingPositions.Count(), m_iszStagingEntities ); - m_iStagingNum = m_hvStagingPositions.Count() ; - } - - -// advisor_staging_num - - // in the future i'll distribute the staging chronologically. For now, yank all the objects at once. - if (m_hvStagedEnts.Count() < m_iStagingNum) - { - // pull another object - bool bDesperate = m_flStagingEnd - gpGlobals->curtime < 0.50f; // less than one half second left - CBaseEntity *pThrowable = PickThrowable(!bDesperate); - if (pThrowable) - { - // don't let the player take it from me - IPhysicsObject *pPhys = pThrowable->VPhysicsGetObject(); - if ( pPhys ) - { - // no pickup! - pPhys->SetGameFlags(pPhys->GetGameFlags() | FVPHYSICS_NO_PLAYER_PICKUP );; - } - - m_hvStagedEnts.AddToTail( pThrowable ); - Write_BeamOn(pThrowable); - - - DispatchParticleEffect( "advisor_object_charge", PATTACH_ABSORIGIN_FOLLOW, - pThrowable, 0, - false ); - } - } - - - Assert(m_hvStagedEnts.Count() <= m_hvStagingPositions.Count()); - - // yank all objects into place - for (int ii = m_hvStagedEnts.Count() - 1 ; ii >= 0 ; --ii) - { - - // just ignore lost objects (if the player destroys one, that's fine, leave a hole) - CBaseEntity *pThrowable = m_hvStagedEnts[ii]; - if (pThrowable) - { - PullObjectToStaging(pThrowable, m_hvStagingPositions[ii]->GetAbsOrigin()); - } - } - - // are we done yet? - if (gpGlobals->curtime > m_flStagingEnd) - { - TaskComplete(); - break; - } - - break; - } - - // Fling the object that we picked at our enemy's eyes! - case TASK_ADVISOR_BARRAGE_OBJECTS: - { - Assert(m_hvStagedEnts.Count() > 0); - - // do I still have an enemy? - if ( !GetEnemy() ) - { - // no? bail all the objects. - for (int ii = m_hvStagedEnts.Count() - 1 ; ii >=0 ; --ii) - { - - IPhysicsObject *pPhys = m_hvStagedEnts[ii]->VPhysicsGetObject(); - if ( pPhys ) - { - pPhys->SetGameFlags(pPhys->GetGameFlags() & (~FVPHYSICS_NO_PLAYER_PICKUP) ); - } - } - - Write_AllBeamsOff(); - m_hvStagedEnts.RemoveAll(); - - TaskFail( "Lost enemy" ); - return; - } - - // do I still have something to throw at the player? - CBaseEntity *pThrowable = m_hvStagedEnts[0]; - while (!pThrowable) - { // player has destroyed whatever I planned to hit him with, get something else - if (m_hvStagedEnts.Count() > 0) - { - pThrowable = ThrowObjectPrepare(); - } - else - { - TaskComplete(); - break; - } - } - - // If we've gone NULL, then opt out - if ( pThrowable == NULL ) - { - TaskComplete(); - break; - } - - if ( (gpGlobals->curtime > m_flThrowPhysicsTime - advisor_throw_lead_prefetch_time.GetFloat()) && - !m_vSavedLeadVel.IsValid() ) - { - // save off the velocity we will use to lead the player a little early, so that if he jukes - // at the last moment he'll have a better shot of dodging the object. - m_vSavedLeadVel = GetEnemy()->GetAbsVelocity(); - } - - // if it's time to throw something, throw it and go on to the next one. - if (gpGlobals->curtime > m_flThrowPhysicsTime) - { - IPhysicsObject *pPhys = pThrowable->VPhysicsGetObject(); - Assert(pPhys); - - pPhys->SetGameFlags(pPhys->GetGameFlags() & (~FVPHYSICS_NO_PLAYER_PICKUP) ); - HurlObjectAtPlayer(pThrowable,Vector(0,0,0)/*m_vSavedLeadVel*/); - m_flLastThrowTime = gpGlobals->curtime; - m_flThrowPhysicsTime = gpGlobals->curtime + 0.75f; - // invalidate saved lead for next time - m_vSavedLeadVel.Invalidate(); - - EmitSound( "NPC_Advisor.Blast" ); - - Write_BeamOff(m_hvStagedEnts[0]); - m_hvStagedEnts.Remove(0); - if (!ThrowObjectPrepare()) - { - TaskComplete(); - break; - } - } - else - { - // wait, bide time - // PullObjectToStaging(pThrowable, m_hvStagingPositions[ii]->GetAbsOrigin()); - } - - break; - } - - case TASK_ADVISOR_PIN_PLAYER: - { - /* - // bail out if the pin entity went away. - CBaseEntity *pPinEnt = m_hPlayerPinPos; - if (!pPinEnt) - { - GetEnemy()->SetGravity(1.0f); - GetEnemy()->SetMoveType( MOVETYPE_WALK ); - TaskComplete(); - break; - } - - // failsafe: don't do this for more than ten seconds. - if ( gpGlobals->curtime > m_playerPinFailsafeTime ) - { - GetEnemy()->SetGravity(1.0f); - GetEnemy()->SetMoveType( MOVETYPE_WALK ); - Warning( "Advisor did not leave PIN PLAYER mode. Aborting due to ten second failsafe!\n" ); - TaskFail("Advisor did not leave PIN PLAYER mode. Aborting due to ten second failsafe!\n"); - break; - } - - // if the player isn't the enemy, bail out. - if ( !GetEnemy()->IsPlayer() ) - { - GetEnemy()->SetGravity(1.0f); - GetEnemy()->SetMoveType( MOVETYPE_WALK ); - TaskFail( "Player is not the enemy?!" ); - break; - } - - GetEnemy()->SetMoveType( MOVETYPE_FLY ); - GetEnemy()->SetGravity(0); - - // use exponential falloff to peg the player to the pin point - const Vector &desiredPos = pPinEnt->GetAbsOrigin(); - const Vector &playerPos = GetEnemy()->GetAbsOrigin(); - - Vector displacement = desiredPos - playerPos; - - float desiredDisplacementLen = ExponentialDecay(0.250f,gpGlobals->frametime);// * sqrt(displacementLen); - - Vector nuPos = playerPos + (displacement * (1.0f - desiredDisplacementLen)); - - GetEnemy()->SetAbsOrigin( nuPos ); - - break; - */ - } - - default: - { - BaseClass::RunTask( pTask ); - } - } -} - - -#endif - -// helper function for testing whether or not an avisor is allowed to grab an object -/*static bool AdvisorCanPickObject(CBasePlayer *pPlayer, CBaseEntity *pEnt) -{ - Assert( pPlayer != NULL ); - - // Is the player carrying something? - CBaseEntity *pHeldObject = GetPlayerHeldEntity(pPlayer); - - if( !pHeldObject ) - { - pHeldObject = PhysCannonGetHeldEntity( pPlayer->GetActiveWeapon() ); - } - - if( pHeldObject == pEnt ) - { - return false; - } - - if ( pEnt->GetCollisionGroup() == COLLISION_GROUP_DEBRIS ) - { - return false; - } - - return true; -}*/ - - -#if NPC_ADVISOR_HAS_BEHAVIOR -//----------------------------------------------------------------------------- -// Choose an object to throw. -// param bRequireInView : if true, only accept objects that are in the player's fov. -// -// Can always return NULL. -// todo priority_grab_name -//----------------------------------------------------------------------------- -CBaseEntity *CNPC_Advisor::PickThrowable( bool bRequireInView ) -{ - CBasePlayer *pPlayer = ToBasePlayer( GetEnemy() ); - Assert(pPlayer); - if (!pPlayer) - return NULL; - - const int numObjs = m_physicsObjects.Count(); ///< total number of physics objects in my system - if (numObjs < 1) - return NULL; // bail out if nothing available - - - // used for require-in-view - Vector eyeForward, eyeOrigin; - if (pPlayer) - { - eyeOrigin = pPlayer->EyePosition(); - pPlayer->EyeVectors(&eyeForward); - } - else - { - bRequireInView = false; - } - - // filter-and-choose algorithm: - // build a list of candidates - Assert(numObjs < 128); /// I'll come back and utlvector this shortly -- wanted easier debugging - unsigned int candidates[128]; - unsigned int numCandidates = 0; - - if (!!m_iszPriorityEntityGroupName) // if the string isn't null - { - // first look to see if we have any priority objects. - for (int ii = 0 ; ii < numObjs ; ++ii ) - { - CBaseEntity *pThrowEnt = m_physicsObjects[ii]; - // Assert(pThrowEnt); - if (!pThrowEnt) - continue; - - if (!pThrowEnt->NameMatches(m_iszPriorityEntityGroupName)) // if this is not a priority object - continue; - - bool bCanPick = AdvisorCanPickObject( pPlayer, pThrowEnt ) && !m_hvStagedEnts.HasElement( m_physicsObjects[ii] ); - if (!bCanPick) - continue; - - // bCanPick guaranteed true here - - if ( bRequireInView ) - { - bCanPick = (pThrowEnt->GetAbsOrigin() - eyeOrigin).Dot(eyeForward) > 0; - } - - if ( bCanPick ) - { - candidates[numCandidates++] = ii; - } - } - } - - // if we found no priority objects (or don't have a priority), just grab whatever - if (numCandidates == 0) - { - for (int ii = 0 ; ii < numObjs ; ++ii ) - { - CBaseEntity *pThrowEnt = m_physicsObjects[ii]; - // Assert(pThrowEnt); - if (!pThrowEnt) - continue; - - bool bCanPick = AdvisorCanPickObject( pPlayer, pThrowEnt ) && !m_hvStagedEnts.HasElement( m_physicsObjects[ii] ); - if (!bCanPick) - continue; - - // bCanPick guaranteed true here - - if ( bRequireInView ) - { - bCanPick = (pThrowEnt->GetAbsOrigin() - eyeOrigin).Dot(eyeForward) > 0; - } - - if ( bCanPick ) - { - candidates[numCandidates++] = ii; - } - } - } - - if ( numCandidates == 0 ) - return NULL; // must have at least one candidate - - // pick a random candidate. - int nRandomIndex = random->RandomInt( 0, numCandidates - 1 ); - return m_physicsObjects[candidates[nRandomIndex]]; - -} - -/*! \TODO - Correct bug where Advisor seemed to be throwing stuff at people's feet. - This is because the object was falling slightly in between the staging - and when he threw it, and that downward velocity was getting accumulated - into the throw speed. This is temporarily fixed here by using SetVelocity - instead of AddVelocity, but the proper fix is to pin the object to its - staging point during the warn period. That will require maintaining a map - of throwables to their staging points during the throw task. -*/ -//----------------------------------------------------------------------------- -// Impart necessary force on any entity to make it clobber Gordon. -// Also detaches from levitate controller. -// The optional lead velocity parameter is for cases when we pre-save off the -// player's speed, to make last-moment juking more effective -//----------------------------------------------------------------------------- -void CNPC_Advisor::HurlObjectAtPlayer( CBaseEntity *pEnt, const Vector &leadVel ) -{ - IPhysicsObject *pPhys = pEnt->VPhysicsGetObject(); - - // - // Lead the target accurately. This encourages hiding behind cover - // and/or catching the thrown physics object! - // - Vector vecObjOrigin = pEnt->CollisionProp()->WorldSpaceCenter(); - Vector vecEnemyPos = GetEnemy()->EyePosition(); - // disabled -- no longer compensate for gravity: // vecEnemyPos.y += 12.0f; - -// const Vector &leadVel = pLeadVelocity ? *pLeadVelocity : GetEnemy()->GetAbsVelocity(); - - Vector vecDelta = vecEnemyPos - vecObjOrigin; - float flDist = vecDelta.Length(); - - float flVelocity = advisor_throw_velocity.GetFloat(); - - if ( flVelocity == 0 ) - { - flVelocity = 1000; - } - - float flFlightTime = flDist / flVelocity; - - Vector vecThrowAt = vecEnemyPos + flFlightTime * leadVel; - Vector vecThrowDir = vecThrowAt - vecObjOrigin; - VectorNormalize( vecThrowDir ); - - Vector vecVelocity = flVelocity * vecThrowDir; - pPhys->SetVelocity( &vecVelocity, NULL ); - - AddToThrownObjects(pEnt); - - m_OnThrow.FireOutput(pEnt,this); - -} - - -//----------------------------------------------------------------------------- -// do a sweep from an object I'm about to throw, to the target, pushing aside -// anything floating in the way. -// TODO: this is probably a good profiling candidate. -//----------------------------------------------------------------------------- -void CNPC_Advisor::PreHurlClearTheWay( CBaseEntity *pThrowable, const Vector &toPos ) -{ - // look for objects in the way of chucking. - CBaseEntity *list[128]; - Ray_t ray; - - - float boundingRadius = pThrowable->BoundingRadius(); - - ray.Init( pThrowable->GetAbsOrigin(), toPos, - Vector(-boundingRadius,-boundingRadius,-boundingRadius), - Vector( boundingRadius, boundingRadius, boundingRadius) ); - - int nFoundCt = UTIL_EntitiesAlongRay( list, 128, ray, 0 ); - AssertMsg(nFoundCt < 128, "Found more than 128 obstructions between advisor and Gordon while throwing. (safe to continue)\n"); - - // for each thing in the way that I levitate, but is not something I'm staging - // or throwing, push it aside. - for (int i = 0 ; i < nFoundCt ; ++i ) - { - CBaseEntity *obstruction = list[i]; - if ( obstruction != pThrowable && - m_physicsObjects.HasElement( obstruction ) && // if it's floating - !m_hvStagedEnts.HasElement( obstruction ) && // and I'm not staging it - !DidThrow( obstruction ) ) // and I didn't just throw it - { - IPhysicsObject *pPhys = obstruction->VPhysicsGetObject(); - Assert(pPhys); - - // this is an object we want to push out of the way. Compute a vector perpendicular - // to the path of the throwables's travel, and thrust the object along that vector. - Vector thrust; - CalcClosestPointOnLine( obstruction->GetAbsOrigin(), - pThrowable->GetAbsOrigin(), - toPos, - thrust ); - // "thrust" is now the closest point on the line to the obstruction. - // compute the difference to get the direction of impulse - thrust = obstruction->GetAbsOrigin() - thrust; - - // and renormalize it to equal a giant kick out of the way - // (which I'll say is about ten feet per second -- if we want to be - // more precise we could do some kind of interpolation based on how - // far away the object is) - float thrustLen = thrust.Length(); - if (thrustLen > 0.0001f) - { - thrust *= advisor_throw_clearout_vel.GetFloat() / thrustLen; - } - - // heave! - pPhys->AddVelocity( &thrust, NULL ); - } - } - -/* - - // Otherwise only help out a little - Vector extents = Vector(256, 256, 256); - Ray_t ray; - ray.Init( vecStartPoint, vecStartPoint + 2048 * vecVelDir, -extents, extents ); - int nCount = UTIL_EntitiesAlongRay( list, 1024, ray, FL_NPC | FL_CLIENT ); - for ( int i = 0; i < nCount; i++ ) - { - if ( !IsAttractiveTarget( list[i] ) ) - continue; - - VectorSubtract( list[i]->WorldSpaceCenter(), vecStartPoint, vecDelta ); - distance = VectorNormalize( vecDelta ); - flDot = DotProduct( vecDelta, vecVelDir ); - - if ( flDot > flMaxDot ) - { - if ( distance < flBestDist ) - { - pBestTarget = list[i]; - flBestDist = distance; - } - } - } - -*/ - -} - -/* -// commented out because unnecessary: we will do this during the DidThrow check - -//----------------------------------------------------------------------------- -// clean out the recently thrown objects array -//----------------------------------------------------------------------------- -void CNPC_Advisor::PurgeThrownObjects() -{ - float threeSecondsAgo = gpGlobals->curtime - 3.0f; // two seconds ago - - for (int ii = 0 ; ii < kMaxThrownObjectsTracked ; ++ii) - { - if ( m_haRecentlyThrownObjects[ii].IsValid() && - m_flaRecentlyThrownObjectTimes[ii] < threeSecondsAgo ) - { - m_haRecentlyThrownObjects[ii].Set(NULL); - } - } - -} -*/ - - -//----------------------------------------------------------------------------- -// true iff an advisor threw the object in the last three seconds -//----------------------------------------------------------------------------- -bool CNPC_Advisor::DidThrow(const CBaseEntity *pEnt) -{ - // look through all my objects and see if they match this entity. Incidentally if - // they're more than three seconds old, purge them. - float threeSecondsAgo = gpGlobals->curtime - 3.0f; - - for (int ii = 0 ; ii < kMaxThrownObjectsTracked ; ++ii) - { - // if object is old, skip it. - CBaseEntity *pTestEnt = m_haRecentlyThrownObjects[ii]; - - if ( pTestEnt ) - { - if ( m_flaRecentlyThrownObjectTimes[ii] < threeSecondsAgo ) - { - m_haRecentlyThrownObjects[ii].Set(NULL); - continue; - } - else if (pTestEnt == pEnt) - { - return true; - } - } - } - - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Advisor::AddToThrownObjects(CBaseEntity *pEnt) -{ - Assert(pEnt); - - // try to find an empty slot, or if none exists, the oldest object - int oldestThrownObject = 0; - for (int ii = 0 ; ii < kMaxThrownObjectsTracked ; ++ii) - { - if (m_haRecentlyThrownObjects[ii].IsValid()) - { - if (m_flaRecentlyThrownObjectTimes[ii] < m_flaRecentlyThrownObjectTimes[oldestThrownObject]) - { - oldestThrownObject = ii; - } - } - else - { // just use this one - oldestThrownObject = ii; - break; - } - } - - m_haRecentlyThrownObjects[oldestThrownObject] = pEnt; - m_flaRecentlyThrownObjectTimes[oldestThrownObject] = gpGlobals->curtime; - -} - - -//----------------------------------------------------------------------------- -// Drag a particular object towards its staging location. -//----------------------------------------------------------------------------- -void CNPC_Advisor::PullObjectToStaging( CBaseEntity *pEnt, const Vector &stagingPos ) -{ - IPhysicsObject *pPhys = pEnt->VPhysicsGetObject(); - Assert(pPhys); - - Vector curPos = pEnt->CollisionProp()->WorldSpaceCenter(); - Vector displacement = stagingPos - curPos; - - // quick and dirty -- use exponential decay to haul the object into place - // ( a better looking solution would be to use a spring system ) - - float desiredDisplacementLen = ExponentialDecay(STAGING_OBJECT_FALLOFF_TIME, gpGlobals->frametime);// * sqrt(displacementLen); - - Vector vel; AngularImpulse angimp; - pPhys->GetVelocity(&vel,&angimp); - - vel = (1.0f / gpGlobals->frametime)*(displacement * (1.0f - desiredDisplacementLen)); - pPhys->SetVelocity(&vel,&angimp); -} - - - -#endif - -int CNPC_Advisor::OnTakeDamage( const CTakeDamageInfo &info ) -{ - // Clip our max - CTakeDamageInfo newInfo = info; - if ( newInfo.GetDamage() > 20.0f ) - { - newInfo.SetDamage( 20.0f ); - } - - // Hack to make him constantly flinch - m_flNextFlinchTime = gpGlobals->curtime; - - const float oldLastDamageTime = m_flLastDamageTime; - int retval = BaseClass::OnTakeDamage(newInfo); - - // we have a special reporting output - if ( oldLastDamageTime != gpGlobals->curtime ) - { - // only fire once per frame - - m_OnHealthIsNow.Set( GetHealth(), newInfo.GetAttacker(), this); - } - - return retval; -} - - - - -#if NPC_ADVISOR_HAS_BEHAVIOR -//----------------------------------------------------------------------------- -// Returns the best new schedule for this NPC based on current conditions. -//----------------------------------------------------------------------------- -int CNPC_Advisor::SelectSchedule() -{ - if ( IsInAScript() ) - return SCHED_ADVISOR_IDLE_STAND; - - switch ( m_NPCState ) - { - case NPC_STATE_IDLE: - case NPC_STATE_ALERT: - { - return SCHED_ADVISOR_IDLE_STAND; - } - - case NPC_STATE_COMBAT: - { - if ( GetEnemy() && GetEnemy()->IsAlive() ) - { - if ( false /* m_hPlayerPinPos.IsValid() */ ) - return SCHED_ADVISOR_TOSS_PLAYER; - else - return SCHED_ADVISOR_COMBAT; - - } - - return SCHED_ADVISOR_IDLE_STAND; - } - } - - return BaseClass::SelectSchedule(); -} - - -//----------------------------------------------------------------------------- -// return the position where an object should be staged before throwing -//----------------------------------------------------------------------------- -Vector CNPC_Advisor::GetThrowFromPos( CBaseEntity *pEnt ) -{ - Assert(pEnt); - Assert(pEnt->VPhysicsGetObject()); - const CCollisionProperty *cProp = pEnt->CollisionProp(); - Assert(cProp); - - float effecRadius = cProp->BoundingRadius(); // radius of object (important for kickout) - float howFarInFront = advisor_throw_stage_distance.GetFloat() + effecRadius * 1.43f;// clamp(lenToPlayer - posDist + effecRadius,effecRadius*2,90.f + effecRadius); - - Vector fwd; - GetVectors(&fwd,NULL,NULL); - - return GetAbsOrigin() + fwd*howFarInFront; -} -#endif - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Advisor::Precache() -{ - BaseClass::Precache(); - - PrecacheModel( STRING( GetModelName() ) ); - -#if NPC_ADVISOR_HAS_BEHAVIOR - PrecacheModel( "sprites/lgtning.vmt" ); -#endif - - PrecacheScriptSound( "NPC_Advisor.Blast" ); - PrecacheScriptSound( "NPC_Advisor.Gib" ); - PrecacheScriptSound( "NPC_Advisor.Idle" ); - PrecacheScriptSound( "NPC_Advisor.Alert" ); - PrecacheScriptSound( "NPC_Advisor.Die" ); - PrecacheScriptSound( "NPC_Advisor.Pain" ); - PrecacheScriptSound( "NPC_Advisor.ObjectChargeUp" ); - PrecacheParticleSystem( "Advisor_Psychic_Beam" ); - PrecacheParticleSystem( "advisor_object_charge" ); - PrecacheModel("sprites/greenglow1.vmt"); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Advisor::IdleSound() -{ - EmitSound( "NPC_Advisor.Idle" ); -} - - -void CNPC_Advisor::AlertSound() -{ - EmitSound( "NPC_Advisor.Alert" ); -} - - -void CNPC_Advisor::PainSound( const CTakeDamageInfo &info ) -{ - EmitSound( "NPC_Advisor.Pain" ); -} - - -void CNPC_Advisor::DeathSound( const CTakeDamageInfo &info ) -{ - EmitSound( "NPC_Advisor.Die" ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Advisor::DrawDebugTextOverlays() -{ - int nOffset = BaseClass::DrawDebugTextOverlays(); - return nOffset; -} - - -#if NPC_ADVISOR_HAS_BEHAVIOR -//----------------------------------------------------------------------------- -// Determines which sounds the advisor cares about. -//----------------------------------------------------------------------------- -int CNPC_Advisor::GetSoundInterests() -{ - return SOUND_WORLD | SOUND_COMBAT | SOUND_PLAYER | SOUND_DANGER; -} - - -//----------------------------------------------------------------------------- -// record the last time we heard a combat sound -//----------------------------------------------------------------------------- -bool CNPC_Advisor::QueryHearSound( CSound *pSound ) -{ - // Disregard footsteps from our own class type - CBaseEntity *pOwner = pSound->m_hOwner; - if ( pOwner && pSound->IsSoundType( SOUND_COMBAT ) && pSound->SoundChannel() != SOUNDENT_CHANNEL_NPC_FOOTSTEP && pSound->m_hOwner.IsValid() && pOwner->IsPlayer() ) - { - // Msg("Heard player combat.\n"); - m_flLastPlayerAttackTime = gpGlobals->curtime; - } - - return BaseClass::QueryHearSound(pSound); -} - -//----------------------------------------------------------------------------- -// designer hook for setting throw rate -//----------------------------------------------------------------------------- -void CNPC_Advisor::InputSetThrowRate( inputdata_t &inputdata ) -{ - advisor_throw_rate.SetValue(inputdata.value.Float()); -} - -void CNPC_Advisor::InputSetStagingNum( inputdata_t &inputdata ) -{ - m_iStagingNum = inputdata.value.Int(); -} - -// -// cause the player to be pinned to a point in space -// -void CNPC_Advisor::InputPinPlayer( inputdata_t &inputdata ) -{ - string_t targetname = inputdata.value.StringID(); - - // null string means designer is trying to unpin the player - if (!targetname) - { - m_hPlayerPinPos = NULL; - } - - // otherwise try to look up the entity and make it a target. - CBaseEntity *pEnt = gEntList.FindEntityByName(NULL,targetname); - - if (pEnt) - { - m_hPlayerPinPos = pEnt; - } - else - { - // if we couldn't find the target, just bail on the behavior. - Warning("Advisor tried to pin player to %s but that does not exist.\n", targetname.ToCStr()); - m_hPlayerPinPos = NULL; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Advisor::OnScheduleChange( void ) -{ - Write_AllBeamsOff(); - m_hvStagedEnts.RemoveAll(); - BaseClass::OnScheduleChange(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Advisor::GatherConditions( void ) -{ - BaseClass::GatherConditions(); - - // Handle script state changes - bool bInScript = IsInAScript(); - if ( ( m_bWasScripting && bInScript == false ) || ( m_bWasScripting == false && bInScript ) ) - { - SetCondition( COND_ADVISOR_PHASE_INTERRUPT ); - } - - // Retain this - m_bWasScripting = bInScript; -} - -//----------------------------------------------------------------------------- -// designer hook for yanking an object into the air right now -//----------------------------------------------------------------------------- -void CNPC_Advisor::InputWrenchImmediate( inputdata_t &inputdata ) -{ - string_t groupname = inputdata.value.StringID(); - - Assert(!!groupname); - - // for all entities with that name that aren't floating, punt them at me and add them to the levitation - - CBaseEntity *pEnt = NULL; - - const Vector &myPos = GetAbsOrigin() + Vector(0,36.0f,0); - - // conditional assignment: find an entity by name and save it into pEnt. Bail out when none are left. - while ( ( pEnt = gEntList.FindEntityByName(pEnt,groupname) ) != NULL ) - { - // if I'm not already levitating it, and if I didn't just throw it - if (!m_physicsObjects.HasElement(pEnt) ) - { - // add to levitation - IPhysicsObject *pPhys = pEnt->VPhysicsGetObject(); - if ( pPhys ) - { - // if the object isn't moveable, make it so. - if ( !pPhys->IsMoveable() ) - { - pPhys->EnableMotion( true ); - } - - // first, kick it at me - Vector objectToMe; - pPhys->GetPosition(&objectToMe,NULL); - objectToMe = myPos - objectToMe; - // compute a velocity that will get it here in about a second - objectToMe /= (1.5f * gpGlobals->frametime); - - objectToMe *= random->RandomFloat(0.25f,1.0f); - - pPhys->SetVelocity( &objectToMe, NULL ); - - // add it to tracked physics objects - m_physicsObjects.AddToTail( pEnt ); - - m_pLevitateController->AttachObject( pPhys, false ); - pPhys->Wake(); - } - else - { - Warning( "Advisor tried to wrench %s, but it is not moveable!", pEnt->GetEntityName().ToCStr()); - } - } - } - -} - - - -//----------------------------------------------------------------------------- -// write a message turning a beam on -//----------------------------------------------------------------------------- -void CNPC_Advisor::Write_BeamOn( CBaseEntity *pEnt ) -{ - Assert( pEnt ); - EntityMessageBegin( this, true ); - WRITE_BYTE( ADVISOR_MSG_START_BEAM ); - WRITE_LONG( pEnt->entindex() ); - MessageEnd(); -} - -//----------------------------------------------------------------------------- -// write a message turning a beam off -//----------------------------------------------------------------------------- -void CNPC_Advisor::Write_BeamOff( CBaseEntity *pEnt ) -{ - Assert( pEnt ); - EntityMessageBegin( this, true ); - WRITE_BYTE( ADVISOR_MSG_STOP_BEAM ); - WRITE_LONG( pEnt->entindex() ); - MessageEnd(); -} - -//----------------------------------------------------------------------------- -// tell client to kill all beams -//----------------------------------------------------------------------------- -void CNPC_Advisor::Write_AllBeamsOff( void ) -{ - EntityMessageBegin( this, true ); - WRITE_BYTE( ADVISOR_MSG_STOP_ALL_BEAMS ); - MessageEnd(); -} - -//----------------------------------------------------------------------------- -// input wrapper around Write_BeamOn -//----------------------------------------------------------------------------- -void CNPC_Advisor::InputTurnBeamOn( inputdata_t &inputdata ) -{ - // inputdata should specify a target - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, inputdata.value.StringID() ); - if ( pTarget ) - { - Write_BeamOn( pTarget ); - } - else - { - Warning("InputTurnBeamOn could not find object %s", inputdata.value.String() ); - } -} - - -//----------------------------------------------------------------------------- -// input wrapper around Write_BeamOff -//----------------------------------------------------------------------------- -void CNPC_Advisor::InputTurnBeamOff( inputdata_t &inputdata ) -{ - // inputdata should specify a target - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, inputdata.value.StringID() ); - if ( pTarget ) - { - Write_BeamOff( pTarget ); - } - else - { - Warning("InputTurnBeamOn could not find object %s", inputdata.value.String() ); - } -} - - -void CNPC_Advisor::InputElightOn( inputdata_t &inputdata ) -{ - EntityMessageBegin( this, true ); - WRITE_BYTE( ADVISOR_MSG_START_ELIGHT ); - MessageEnd(); -} - -void CNPC_Advisor::InputElightOff( inputdata_t &inputdata ) -{ - EntityMessageBegin( this, true ); - WRITE_BYTE( ADVISOR_MSG_STOP_ELIGHT ); - MessageEnd(); -} -#endif - - -//============================================================================================== -// MOTION CALLBACK -//============================================================================================== -CAdvisorLevitate::simresult_e CAdvisorLevitate::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) -{ - // this function can be optimized to minimize branching if necessary (PPE branch prediction) - CNPC_Advisor *pAdvisor = static_cast(m_Advisor.Get()); - Assert(pAdvisor); - - if ( !OldStyle() ) - { // independent movement of all objects - // if an object was recently thrown, just zero out its gravity. - if (pAdvisor->DidThrow(static_cast(pObject->GetGameData()))) - { - linear = Vector( 0, 0, sv_gravity.GetFloat() ); - - return SIM_GLOBAL_ACCELERATION; - } - else - { - Vector vel; AngularImpulse angvel; - pObject->GetVelocity(&vel,&angvel); - Vector pos; - pObject->GetPosition(&pos,NULL); - bool bMovingUp = vel.z > 0; - - // if above top limit and moving up, move down. if below bottom limit and moving down, move up. - if (bMovingUp) - { - if (pos.z > m_vecGoalPos2.z) - { - // turn around move down - linear = Vector( 0, 0, Square((1.0f - m_flFloat)) * sv_gravity.GetFloat() ); - angular = Vector( 0, -5, 0 ); - } - else - { // keep moving up - linear = Vector( 0, 0, (1.0f + m_flFloat) * sv_gravity.GetFloat() ); - angular = Vector( 0, 0, 10 ); - } - } - else - { - if (pos.z < m_vecGoalPos1.z) - { - // turn around move up - linear = Vector( 0, 0, Square((1.0f + m_flFloat)) * sv_gravity.GetFloat() ); - angular = Vector( 0, 5, 0 ); - } - else - { // keep moving down - linear = Vector( 0, 0, (1.0f - m_flFloat) * sv_gravity.GetFloat() ); - angular = Vector( 0, 0, 10 ); - } - } - - return SIM_GLOBAL_ACCELERATION; - } - - //NDebugOverlay::Cross3D(pos,24.0f,255,255,0,true,0.04f); - - } - else // old stateless technique - { - Warning("Advisor using old-style object movement!\n"); - - /* // obsolete - CBaseEntity *pEnt = (CBaseEntity *)pObject->GetGameData(); - Vector vecDir1 = m_vecGoalPos1 - pEnt->GetAbsOrigin(); - VectorNormalize( vecDir1 ); - - Vector vecDir2 = m_vecGoalPos2 - pEnt->GetAbsOrigin(); - VectorNormalize( vecDir2 ); - */ - - linear = Vector( 0, 0, m_flFloat * sv_gravity.GetFloat() );// + m_flFloat * 0.5 * ( vecDir1 + vecDir2 ); - angular = Vector( 0, 0, 10 ); - - return SIM_GLOBAL_ACCELERATION; - } - -} - - -//============================================================================================== -// ADVISOR PHYSICS DAMAGE TABLE -//============================================================================================== -static impactentry_t advisorLinearTable[] = -{ - { 100*100, 10 }, - { 250*250, 25 }, - { 350*350, 50 }, - { 500*500, 75 }, - { 1000*1000,100 }, -}; - -static impactentry_t advisorAngularTable[] = -{ - { 50* 50, 10 }, - { 100*100, 25 }, - { 150*150, 50 }, - { 200*200, 75 }, -}; - -static impactdamagetable_t gAdvisorImpactDamageTable = -{ - advisorLinearTable, - advisorAngularTable, - - ARRAYSIZE(advisorLinearTable), - ARRAYSIZE(advisorAngularTable), - - 200*200,// minimum linear speed squared - 180*180,// minimum angular speed squared (360 deg/s to cause spin/slice damage) - 15, // can't take damage from anything under 15kg - - 10, // anything less than 10kg is "small" - 5, // never take more than 1 pt of damage from anything under 15kg - 128*128,// <15kg objects must go faster than 36 in/s to do damage - - 45, // large mass in kg - 2, // large mass scale (anything over 500kg does 4X as much energy to read from damage table) - 1, // large mass falling scale - 0, // my min velocity -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const impactdamagetable_t -//----------------------------------------------------------------------------- -const impactdamagetable_t &CNPC_Advisor::GetPhysicsImpactDamageTable( void ) -{ - return advisor_use_impact_table.GetBool() ? gAdvisorImpactDamageTable : BaseClass::GetPhysicsImpactDamageTable(); -} - - - -#if NPC_ADVISOR_HAS_BEHAVIOR -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- -AI_BEGIN_CUSTOM_NPC( npc_advisor, CNPC_Advisor ) - - DECLARE_TASK( TASK_ADVISOR_FIND_OBJECTS ) - DECLARE_TASK( TASK_ADVISOR_LEVITATE_OBJECTS ) - /* - DECLARE_TASK( TASK_ADVISOR_PICK_THROW_OBJECT ) - DECLARE_TASK( TASK_ADVISOR_THROW_OBJECT ) - */ - - DECLARE_CONDITION( COND_ADVISOR_PHASE_INTERRUPT ) // A stage has interrupted us - - DECLARE_TASK( TASK_ADVISOR_STAGE_OBJECTS ) // haul all the objects into the throw-from slots - DECLARE_TASK( TASK_ADVISOR_BARRAGE_OBJECTS ) // hurl all the objects in sequence - - DECLARE_TASK( TASK_ADVISOR_PIN_PLAYER ) // pinion the player to a point in space - - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_ADVISOR_COMBAT, - - " Tasks" - " TASK_ADVISOR_FIND_OBJECTS 0" - " TASK_ADVISOR_LEVITATE_OBJECTS 0" - " TASK_ADVISOR_STAGE_OBJECTS 1" - " TASK_ADVISOR_BARRAGE_OBJECTS 0" - " " - " Interrupts" - " COND_ADVISOR_PHASE_INTERRUPT" - " COND_ENEMY_DEAD" - ) - - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_ADVISOR_IDLE_STAND, - - " Tasks" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT 3" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_FEAR" - " COND_ADVISOR_PHASE_INTERRUPT" - ) - - DEFINE_SCHEDULE - ( - SCHED_ADVISOR_TOSS_PLAYER, - - " Tasks" - " TASK_ADVISOR_FIND_OBJECTS 0" - " TASK_ADVISOR_LEVITATE_OBJECTS 0" - " TASK_ADVISOR_PIN_PLAYER 0" - " " - " Interrupts" - ) - -AI_END_CUSTOM_NPC() -#endif diff --git a/game/server/episodic/npc_combine_cannon.cpp b/game/server/episodic/npc_combine_cannon.cpp deleted file mode 100644 index 240fd306e..000000000 --- a/game/server/episodic/npc_combine_cannon.cpp +++ /dev/null @@ -1,1335 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ai_basenpc.h" -#include "ammodef.h" -#include "ai_memory.h" -#include "weapon_rpg.h" -#include "effect_color_tables.h" -#include "te_effect_dispatch.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern const char* g_pModelNameLaser; - -// No model, impervious to damage. -#define SF_STARTDISABLED (1 << 19) - -#define CANNON_PAINT_ENEMY_TIME 1.0f -#define CANNON_SUBSEQUENT_PAINT_TIME 0.4f -#define CANNON_PAINT_NPC_TIME_NOISE 1.0f - -#define NUM_ANCILLARY_BEAMS 4 - -int gHaloTexture = 0; - -//----------------------------------------------------------------------------- -// -// Combine Cannon -// -//----------------------------------------------------------------------------- -class CNPC_Combine_Cannon : public CAI_BaseNPC -{ - DECLARE_CLASS( CNPC_Combine_Cannon, CAI_BaseNPC ); - -public: - CNPC_Combine_Cannon( void ); - virtual void Precache( void ); - virtual void Spawn( void ); - virtual Class_T Classify( void ); - virtual float MaxYawSpeed( void ); - virtual Vector EyePosition( void ); - virtual void UpdateOnRemove( void ); - virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - virtual bool QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC = false ); - virtual void StartTask( const Task_t *pTask ); - virtual void RunTask( const Task_t *pTask ); - virtual int RangeAttack1Conditions( float flDot, float flDist ); - virtual int SelectSchedule( void ); - virtual int TranslateSchedule( int scheduleType ); - virtual void PrescheduleThink( void ); - virtual bool FCanCheckAttacks ( void ); - virtual int Restore( IRestore &restore ); - virtual void OnScheduleChange( void ); - virtual bool FVisible( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ); - - virtual bool WeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions) { return true; } - - virtual int GetSoundInterests( void ) { return (SOUND_PLAYER|SOUND_COMBAT|SOUND_DANGER); } - - virtual bool ShouldNotDistanceCull( void ) { return true; } - - virtual void UpdateEfficiency( bool bInPVS ) { SetEfficiency( ( GetSleepState() != AISS_AWAKE ) ? AIE_DORMANT : AIE_NORMAL ); SetMoveEfficiency( AIME_NORMAL ); } - - virtual const char *GetTracerType( void ) { return "HelicopterTracer"; } - -private: - - void ScopeGlint( void ); - void AdjustShotPosition( CBaseEntity *pTarget, Vector *vecIn ); - - float GetRefireTime( void ) { return 0.1f; } - - bool IsLaserOn( void ) { return m_pBeam != NULL; } - bool FireBullet( const Vector &vecTarget, bool bDirectShot ); - Vector DesiredBodyTarget( CBaseEntity *pTarget ); - Vector LeadTarget( CBaseEntity *pTarget ); - Vector GetBulletOrigin( void ); - - static const char *pAttackSounds[]; - - void ClearTargetGroup( void ); - - float GetWaitTimePercentage( float flTime, bool fLinear ); - - void GetPaintAim( const Vector &vecStart, const Vector &vecGoal, float flParameter, Vector *pProgress ); - - bool VerifyShot( CBaseEntity *pTarget ); - - void SetSweepTarget( const char *pszTarget ); - - // Inputs - void InputEnableSniper( inputdata_t &inputdata ); - void InputDisableSniper( inputdata_t &inputdata ); - - void LaserOff( void ); - void LaserOn( const Vector &vecTarget, const Vector &vecDeviance ); - - void PaintTarget( const Vector &vecTarget, float flPaintTime ); - -private: - - void CreateLaser( void ); - void CreateAncillaryBeams( void ); - void UpdateAncillaryBeams( float flConvergencePerc, const Vector &vecOrigin, const Vector &vecBasis ); - - int m_iAmmoType; - float m_flBarrageDuration; - Vector m_vecPaintCursor; - float m_flPaintTime; - - CHandle m_pBeam; - CHandle m_pAncillaryBeams[NUM_ANCILLARY_BEAMS]; - EHANDLE m_hBarrageTarget; - - bool m_fEnabled; - Vector m_vecPaintStart; // used to track where a sweep starts for the purpose of interpolating. - float m_flTimeLastAttackedPlayer; - float m_flTimeLastShotMissed; - float m_flSightDist; - - DEFINE_CUSTOM_AI; - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( npc_combine_cannon, CNPC_Combine_Cannon ); - -//========================================================= -//========================================================= -BEGIN_DATADESC( CNPC_Combine_Cannon ) - - DEFINE_FIELD( m_fEnabled, FIELD_BOOLEAN ), - DEFINE_FIELD( m_vecPaintStart, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_flPaintTime, FIELD_TIME ), - DEFINE_FIELD( m_vecPaintCursor, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_pBeam, FIELD_EHANDLE ), - DEFINE_FIELD( m_flTimeLastAttackedPlayer, FIELD_TIME ), - DEFINE_FIELD( m_flTimeLastShotMissed, FIELD_TIME ), - DEFINE_FIELD( m_iAmmoType, FIELD_INTEGER ), - DEFINE_FIELD( m_flBarrageDuration, FIELD_TIME ), - DEFINE_FIELD( m_hBarrageTarget, FIELD_EHANDLE ), - - DEFINE_ARRAY( m_pAncillaryBeams, FIELD_EHANDLE, NUM_ANCILLARY_BEAMS ), - - DEFINE_KEYFIELD( m_flSightDist, FIELD_FLOAT, "sightdist" ), - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "EnableSniper", InputEnableSniper ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableSniper", InputDisableSniper ), - -END_DATADESC() - - -//========================================================= -// Private conditions -//========================================================= -enum Sniper_Conds -{ - COND_CANNON_ENABLED = LAST_SHARED_CONDITION, - COND_CANNON_DISABLED, - COND_CANNON_NO_SHOT, -}; - - -//========================================================= -// schedules -//========================================================= -enum -{ - SCHED_CANNON_CAMP = LAST_SHARED_SCHEDULE, - SCHED_CANNON_ATTACK, - SCHED_CANNON_DISABLEDWAIT, - SCHED_CANNON_SNAPATTACK, -}; - -//========================================================= -// tasks -//========================================================= -enum -{ - TASK_CANNON_PAINT_ENEMY = LAST_SHARED_TASK, - TASK_CANNON_PAINT_DECOY, - TASK_CANNON_ATTACK_CURSOR, -}; - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CNPC_Combine_Cannon::CNPC_Combine_Cannon( void ) : - m_pBeam( NULL ), - m_hBarrageTarget( NULL ) -{ -#ifdef _DEBUG - m_vecPaintCursor.Init(); - m_vecPaintStart.Init(); -#endif -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Combine_Cannon::QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC ) -{ - Disposition_t disp = IRelationType(pEntity); - if ( disp != D_HT ) - { - // Don't bother with anything I wouldn't shoot. - return false; - } - - if ( !FInViewCone(pEntity) ) - { - // Yes, this does call FInViewCone twice a frame for all entities checked for - // visibility, but doing this allows us to cut out a bunch of traces that would - // be done by VerifyShot for entities that aren't even in our viewcone. - return false; - } - - if ( VerifyShot( pEntity ) ) - return BaseClass::QuerySeeEntity( pEntity, bOnlyHateOrFearIfNPC ); - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Hide the beams -//----------------------------------------------------------------------------- -void CNPC_Combine_Cannon::LaserOff( void ) -{ - if ( m_pBeam != NULL ) - { - m_pBeam->TurnOn(); - } - - for ( int i = 0; i < NUM_ANCILLARY_BEAMS; i++ ) - { - if ( m_pAncillaryBeams[i] == NULL ) - continue; - - m_pAncillaryBeams[i]->TurnOn(); - } - - SetNextThink( gpGlobals->curtime + 0.1f ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Switch on the laser and point it at a direction -//----------------------------------------------------------------------------- -void CNPC_Combine_Cannon::LaserOn( const Vector &vecTarget, const Vector &vecDeviance ) -{ - if ( m_pBeam != NULL ) - { - m_pBeam->TurnOff(); - - // Don't aim right at the guy right now. - Vector vecInitialAim; - - if( vecDeviance == vec3_origin ) - { - // Start the aim where it last left off! - vecInitialAim = m_vecPaintCursor; - } - else - { - vecInitialAim = vecTarget; - } - - vecInitialAim.x += random->RandomFloat( -vecDeviance.x, vecDeviance.x ); - vecInitialAim.y += random->RandomFloat( -vecDeviance.y, vecDeviance.y ); - vecInitialAim.z += random->RandomFloat( -vecDeviance.z, vecDeviance.z ); - - m_pBeam->SetStartPos( GetBulletOrigin() ); - m_pBeam->SetEndPos( vecInitialAim ); - - m_vecPaintStart = vecInitialAim; - } - - for ( int i = 0; i < NUM_ANCILLARY_BEAMS; i++ ) - { - if ( m_pAncillaryBeams[i] == NULL ) - continue; - - m_pAncillaryBeams[i]->TurnOff(); - } -} - -//----------------------------------------------------------------------------- -// Crikey! -//----------------------------------------------------------------------------- -float CNPC_Combine_Cannon::GetWaitTimePercentage( float flTime, bool fLinear ) -{ - float flElapsedTime; - float flTimeParameter; - - flElapsedTime = flTime - (GetWaitFinishTime() - gpGlobals->curtime); - - flTimeParameter = ( flElapsedTime / flTime ); - - if( fLinear ) - { - return flTimeParameter; - } - else - { - return (1 + sin( (M_PI * flTimeParameter) - (M_PI / 2) ) ) / 2; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Combine_Cannon::GetPaintAim( const Vector &vecStart, const Vector &vecGoal, float flParameter, Vector *pProgress ) -{ - // Quaternions - Vector vecIdealDir; - QAngle vecIdealAngles; - QAngle vecCurrentAngles; - Vector vecCurrentDir; - Vector vecBulletOrigin = GetBulletOrigin(); - - // vecIdealDir is where the gun should be aimed when the painting - // time is up. This can be approximate. This is only for drawing the - // laser, not actually aiming the weapon. A large discrepancy will look - // bad, though. - vecIdealDir = vecGoal - vecBulletOrigin; - VectorNormalize(vecIdealDir); - - // Now turn vecIdealDir into angles! - VectorAngles( vecIdealDir, vecIdealAngles ); - - // This is the vector of the beam's current aim. - vecCurrentDir = m_vecPaintStart - vecBulletOrigin; - VectorNormalize(vecCurrentDir); - - // Turn this to angles, too. - VectorAngles( vecCurrentDir, vecCurrentAngles ); - - Quaternion idealQuat; - Quaternion currentQuat; - Quaternion aimQuat; - - AngleQuaternion( vecIdealAngles, idealQuat ); - AngleQuaternion( vecCurrentAngles, currentQuat ); - - QuaternionSlerp( currentQuat, idealQuat, flParameter, aimQuat ); - - QuaternionAngles( aimQuat, vecCurrentAngles ); - - // Rebuild the current aim vector. - AngleVectors( vecCurrentAngles, &vecCurrentDir ); - - *pProgress = vecCurrentDir; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Combine_Cannon::CreateLaser( void ) -{ - if ( m_pBeam != NULL ) - return; - - m_pBeam = CBeam::BeamCreate( g_pModelNameLaser, 2.0f ); - - m_pBeam->SetColor( 0, 100, 255 ); - - m_pBeam->PointsInit( vec3_origin, GetBulletOrigin() ); - m_pBeam->SetBrightness( 255 ); - m_pBeam->SetNoise( 0 ); - m_pBeam->SetWidth( 1.0f ); - m_pBeam->SetEndWidth( 0 ); - m_pBeam->SetScrollRate( 0 ); - m_pBeam->SetFadeLength( 0 ); - m_pBeam->SetHaloTexture( gHaloTexture ); - m_pBeam->SetHaloScale( 16.0f ); - - // Think faster while painting - SetNextThink( gpGlobals->curtime + 0.02f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Combine_Cannon::CreateAncillaryBeams( void ) -{ - for ( int i = 0; i < NUM_ANCILLARY_BEAMS; i++ ) - { - if ( m_pAncillaryBeams[i] != NULL ) - continue; - - m_pAncillaryBeams[i] = CBeam::BeamCreate( g_pModelNameLaser, 2.0f ); - m_pAncillaryBeams[i]->SetColor( 0, 100, 255 ); - - m_pAncillaryBeams[i]->PointsInit( vec3_origin, GetBulletOrigin() ); - m_pAncillaryBeams[i]->SetBrightness( 255 ); - m_pAncillaryBeams[i]->SetNoise( 0 ); - m_pAncillaryBeams[i]->SetWidth( 1.0f ); - m_pAncillaryBeams[i]->SetEndWidth( 0 ); - m_pAncillaryBeams[i]->SetScrollRate( 0 ); - m_pAncillaryBeams[i]->SetFadeLength( 0 ); - m_pAncillaryBeams[i]->SetHaloTexture( gHaloTexture ); - m_pAncillaryBeams[i]->SetHaloScale( 16.0f ); - m_pAncillaryBeams[i]->TurnOff(); - } -} - -#define LINE_LENGTH 1600.0f - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flConvergencePerc - -// vecBasis - -//----------------------------------------------------------------------------- -void CNPC_Combine_Cannon::UpdateAncillaryBeams( float flConvergencePerc, const Vector &vecOrigin, const Vector &vecBasis ) -{ - // Multiple beams deviate from the basis direction by a certain number of degrees and "converge" - // at the basis vector over a duration of time, the position in that duration expressed by - // flConvergencePerc. The beams are most deviated at 0 and fully converged at 1. - - float flRotationOffset = (2*M_PI)/(float)NUM_ANCILLARY_BEAMS; // Degrees separating each beam, in radians - float flDeviation = DEG2RAD(90) * ( 1.0f - flConvergencePerc ); - float flOffset; - Vector vecFinal; - Vector vecOffset; - - matrix3x4_t matRotate; - QAngle vecAngles; - VectorAngles( vecBasis, vecAngles ); - vecAngles[PITCH] += 90.0f; - AngleMatrix( vecAngles, vecOrigin, matRotate ); - - trace_t tr; - - float flScale = LINE_LENGTH * flDeviation; - - // For each beam, find its offset and trace outwards to place its endpoint - for ( int i = 0; i < NUM_ANCILLARY_BEAMS; i++ ) - { - if ( flConvergencePerc >= 0.99f ) - { - m_pAncillaryBeams[i]->TurnOn(); - continue; - } - - m_pAncillaryBeams[i]->TurnOff(); - - // Find the number of radians offset we are - flOffset = (float) i * flRotationOffset + DEG2RAD( 30.0f ); - flOffset += (M_PI/8.0f) * sin( gpGlobals->curtime * 3.0f ); - - // Construct a circle that's also offset by the line's length - vecOffset.x = cos( flOffset ) * flScale; - vecOffset.y = sin( flOffset ) * flScale; - vecOffset.z = LINE_LENGTH; - - // Rotate this whole thing into the space of the basis vector - VectorRotate( vecOffset, matRotate, vecFinal ); - VectorNormalize( vecFinal ); - - // Trace a line down that vector to find where we'll eventually stop our line - UTIL_TraceLine( vecOrigin, vecOrigin + ( vecFinal * LINE_LENGTH ), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - // Move the beam to that position - m_pAncillaryBeams[i]->SetBrightness( static_cast(255.0f * flConvergencePerc) ); - m_pAncillaryBeams[i]->SetEndPos( tr.startpos ); - m_pAncillaryBeams[i]->SetStartPos( tr.endpos ); - } -} - -//----------------------------------------------------------------------------- -// Sweep the laser sight towards the point where the gun should be aimed -//----------------------------------------------------------------------------- -void CNPC_Combine_Cannon::PaintTarget( const Vector &vecTarget, float flPaintTime ) -{ - // vecStart is the barrel of the gun (or the laser sight) - Vector vecStart = GetBulletOrigin(); - - // keep painttime from hitting 0 exactly. - flPaintTime = MAX( flPaintTime, 0.000001f ); - - // Find out where we are in the arc of the paint duration - float flPaintPerc = GetWaitTimePercentage( flPaintTime, false ); - - ScopeGlint(); - - // Find out where along our line we're painting - Vector vecCurrentDir; - float flInterp = RemapValClamped( flPaintPerc, 0.0f, 0.5f, 0.0f, 1.0f ); - flInterp = clamp( flInterp, 0.0f, 1.0f ); - GetPaintAim( m_vecPaintStart, vecTarget, flInterp, &vecCurrentDir ); - -#define THRESHOLD 0.9f - float flNoiseScale; - - if ( flPaintPerc >= THRESHOLD ) - { - flNoiseScale = 1 - (1 / (1 - THRESHOLD)) * ( flPaintPerc - THRESHOLD ); - } - else if ( flPaintPerc <= 1 - THRESHOLD ) - { - flNoiseScale = flPaintPerc / (1 - THRESHOLD); - } - else - { - flNoiseScale = 1; - } - - // mult by P - vecCurrentDir.x += flNoiseScale * ( sin( 3 * M_PI * gpGlobals->curtime ) * 0.0006 ); - vecCurrentDir.y += flNoiseScale * ( sin( 2 * M_PI * gpGlobals->curtime + 0.5 * M_PI ) * 0.0006 ); - vecCurrentDir.z += flNoiseScale * ( sin( 1.5 * M_PI * gpGlobals->curtime + M_PI ) * 0.0006 ); - - // Find where our center is - trace_t tr; - UTIL_TraceLine( vecStart, vecStart + vecCurrentDir * 8192, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - m_vecPaintCursor = tr.endpos; - - // Update our beam position - m_pBeam->SetEndPos( tr.startpos ); - m_pBeam->SetStartPos( tr.endpos ); - m_pBeam->SetBrightness( static_cast(255.0f * flPaintPerc) ); - m_pBeam->RelinkBeam(); - - // Find points around that center point and make our designators converge at that point over time - UpdateAncillaryBeams( flPaintPerc, vecStart, vecCurrentDir ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Combine_Cannon::OnScheduleChange( void ) -{ - LaserOff(); - - m_hBarrageTarget = NULL; - - BaseClass::OnScheduleChange(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Combine_Cannon::Precache( void ) -{ - PrecacheModel("models/combine_soldier.mdl"); - PrecacheModel("effects/bluelaser1.vmt"); - - gHaloTexture = PrecacheModel("sprites/light_glow03.vmt"); - - PrecacheScriptSound( "NPC_Combine_Cannon.FireBullet" ); - - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Combine_Cannon::Spawn( void ) -{ - Precache(); - - /// HACK: - SetModel( "models/combine_soldier.mdl" ); - - // Setup our ancillary beams but keep them hidden for now - CreateLaser(); - CreateAncillaryBeams(); - - m_iAmmoType = GetAmmoDef()->Index( "CombineHeavyCannon" ); - - SetHullType( HULL_HUMAN ); - SetHullSizeNormal(); - - UTIL_SetSize( this, Vector( -16, -16 , 0 ), Vector( 16, 16, 64 ) ); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_FLY ); - m_bloodColor = DONT_BLEED; - m_iHealth = 10; - m_flFieldOfView = DOT_45DEGREE; - m_NPCState = NPC_STATE_NONE; - - if( HasSpawnFlags( SF_STARTDISABLED ) ) - { - m_fEnabled = false; - } - else - { - m_fEnabled = true; - } - - CapabilitiesClear(); - CapabilitiesAdd( bits_CAP_INNATE_RANGE_ATTACK1 | bits_CAP_SIMPLE_RADIUS_DAMAGE ); - - m_HackedGunPos = Vector ( 0, 0, 0 ); - - AddSpawnFlags( SF_NPC_LONG_RANGE | SF_NPC_ALWAYSTHINK ); - - NPCInit(); - - // Limit our look distance - SetDistLook( m_flSightDist ); - - AddEffects( EF_NODRAW ); - AddSolidFlags( FSOLID_NOT_SOLID ); - - // Point the cursor straight ahead so that the sniper's - // first sweep of the laser doesn't look weird. - Vector vecForward; - AngleVectors( GetLocalAngles(), &vecForward ); - m_vecPaintCursor = GetBulletOrigin() + vecForward * 1024; - - // none! - GetEnemies()->SetFreeKnowledgeDuration( 0.0f ); - GetEnemies()->SetEnemyDiscardTime( 2.0f ); - - m_flTimeLastAttackedPlayer = 0.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Class_T CNPC_Combine_Cannon::Classify( void ) -{ - if ( m_fEnabled ) - return CLASS_COMBINE; - - return CLASS_NONE; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Vector CNPC_Combine_Cannon::GetBulletOrigin( void ) -{ - return GetAbsOrigin(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Nothing kills the cannon but entity I/O -//----------------------------------------------------------------------------- -int CNPC_Combine_Cannon::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - // We are invulnerable to normal attacks for the moment - return 0; -} - -//--------------------------------------------------------- -// Purpose: -//--------------------------------------------------------- -void CNPC_Combine_Cannon::UpdateOnRemove( void ) -{ - // Remove the main laser - if ( m_pBeam != NULL ) - { - UTIL_Remove( m_pBeam); - m_pBeam = NULL; - } - - // Remove our ancillary beams - for ( int i = 0; i < NUM_ANCILLARY_BEAMS; i++ ) - { - if ( m_pAncillaryBeams[i] == NULL ) - continue; - - UTIL_Remove( m_pAncillaryBeams[i] ); - m_pAncillaryBeams[i] = NULL; - } - - BaseClass::UpdateOnRemove(); -} - -//--------------------------------------------------------- -// Purpose: -//--------------------------------------------------------- -int CNPC_Combine_Cannon::SelectSchedule ( void ) -{ - // Fire at our target - if( GetEnemy() && HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - return SCHED_RANGE_ATTACK1; - - // Wait for a target - // TODO: Sweep like a sniper? - return SCHED_COMBAT_STAND; -} - -//--------------------------------------------------------- -// Purpose: -//--------------------------------------------------------- -bool CNPC_Combine_Cannon::FCanCheckAttacks ( void ) -{ - return true; -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Combine_Cannon::VerifyShot( CBaseEntity *pTarget ) -{ - trace_t tr; - - Vector vecTarget = DesiredBodyTarget( pTarget ); - UTIL_TraceLine( GetBulletOrigin(), vecTarget, MASK_SHOT, pTarget, COLLISION_GROUP_NONE, &tr ); - - if( tr.fraction != 1.0 ) - { - if( pTarget->IsPlayer() ) - { - // if the target is the player, do another trace to see if we can shoot his eyeposition. This should help - // improve sniper responsiveness in cases where the player is hiding his chest from the sniper with his - // head in full view. - UTIL_TraceLine( GetBulletOrigin(), pTarget->EyePosition(), MASK_SHOT, pTarget, COLLISION_GROUP_NONE, &tr ); - - if( tr.fraction == 1.0 ) - { - return true; - } - } - - // Trace hit something. - if( tr.m_pEnt ) - { - if( tr.m_pEnt->m_takedamage == DAMAGE_YES ) - { - // Just shoot it if I can hurt it. Probably a breakable or glass pane. - return true; - } - } - - return false; - } - else - { - return true; - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CNPC_Combine_Cannon::RangeAttack1Conditions( float flDot, float flDist ) -{ - if ( GetNextAttack() > gpGlobals->curtime ) - return COND_NONE; - - if ( HasCondition( COND_SEE_ENEMY ) && !HasCondition( COND_ENEMY_OCCLUDED ) ) - { - if ( VerifyShot( GetEnemy() ) ) - { - // Can see the enemy, have a clear shot to his midsection - ClearCondition( COND_CANNON_NO_SHOT ); - return COND_CAN_RANGE_ATTACK1; - } - else - { - // Can see the enemy, but can't take a shot at his midsection - SetCondition( COND_CANNON_NO_SHOT ); - return COND_NONE; - } - } - - return COND_NONE; -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CNPC_Combine_Cannon::TranslateSchedule( int scheduleType ) -{ - switch( scheduleType ) - { - case SCHED_RANGE_ATTACK1: - return SCHED_CANNON_ATTACK; - break; - } - return BaseClass::TranslateSchedule( scheduleType ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Combine_Cannon::ScopeGlint( void ) -{ - CEffectData data; - - data.m_vOrigin = GetAbsOrigin(); - data.m_vNormal = vec3_origin; - data.m_vAngles = vec3_angle; - data.m_nColor = COMMAND_POINT_BLUE; - - DispatchEffect( "CommandPointer", data ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *vecIn - -//----------------------------------------------------------------------------- -void CNPC_Combine_Cannon::AdjustShotPosition( CBaseEntity *pTarget, Vector *vecIn ) -{ - if ( pTarget == NULL || vecIn == NULL ) - return; - - Vector low = pTarget->WorldSpaceCenter() - ( pTarget->WorldSpaceCenter() - pTarget->GetAbsOrigin() ) * .25; - Vector high = pTarget->EyePosition(); - Vector delta = high - low; - Vector result = low + delta * 0.5; - - // Only take the height - (*vecIn)[2] = result[2]; -} - -//--------------------------------------------------------- -// This starts the bullet state machine. The actual effects -// of the bullet will happen later. This function schedules -// those effects. -// -// fDirectShot indicates whether the bullet is a "direct shot" -// that is - fired with the intent that it will strike the -// enemy. Otherwise, the bullet is intended to strike a -// decoy object or nothing at all in particular. -//--------------------------------------------------------- -bool CNPC_Combine_Cannon::FireBullet( const Vector &vecTarget, bool bDirectShot ) -{ - Vector vecBulletOrigin = GetBulletOrigin(); - Vector vecDir = ( vecTarget - vecBulletOrigin ); - VectorNormalize( vecDir ); - - FireBulletsInfo_t info; - info.m_iShots = 1; - info.m_iTracerFreq = 1; - info.m_vecDirShooting = vecDir; - info.m_vecSrc = vecBulletOrigin; - info.m_flDistance = MAX_TRACE_LENGTH; - info.m_pAttacker = this; - info.m_iAmmoType = m_iAmmoType; - info.m_iPlayerDamage = 20; - info.m_vecSpread = Vector( 0.015f, 0.015f, 0.015f ); // medium cone - - FireBullets( info ); - - EmitSound( "NPC_Combine_Cannon.FireBullet" ); - - // Don't attack for a certain amount of time - SetNextAttack( gpGlobals->curtime + GetRefireTime() ); - - // Sniper had to be aiming here to fire here, so make it the cursor - m_vecPaintCursor = vecTarget; - - LaserOff(); - - return true; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Combine_Cannon::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_CANNON_ATTACK_CURSOR: - break; - - case TASK_RANGE_ATTACK1: - // Setup the information for this barrage - m_flBarrageDuration = gpGlobals->curtime + random->RandomFloat( 0.25f, 0.5f ); - m_hBarrageTarget = GetEnemy(); - break; - - case TASK_CANNON_PAINT_ENEMY: - { - if ( GetEnemy()->IsPlayer() ) - { - float delay = random->RandomFloat( 0.0f, 0.3f ); - - if ( ( gpGlobals->curtime - m_flTimeLastAttackedPlayer ) < 1.0f ) - { - SetWait( CANNON_SUBSEQUENT_PAINT_TIME ); - m_flPaintTime = CANNON_SUBSEQUENT_PAINT_TIME; - } - else - { - SetWait( CANNON_PAINT_ENEMY_TIME + delay ); - m_flPaintTime = CANNON_PAINT_ENEMY_TIME + delay; - } - } - else - { - // Use a random time - m_flPaintTime = CANNON_PAINT_ENEMY_TIME + random->RandomFloat( 0, CANNON_PAINT_NPC_TIME_NOISE ); - SetWait( m_flPaintTime ); - } - - // Try to start the laser where the player can't miss seeing it! - Vector vecCursor; - AngleVectors( GetEnemy()->GetLocalAngles(), &vecCursor ); - vecCursor *= 300; - vecCursor += GetEnemy()->EyePosition(); - LaserOn( vecCursor, Vector( 16, 16, 16 ) ); - } - break; - - default: - BaseClass::StartTask( pTask ); - break; - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Combine_Cannon::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_CANNON_ATTACK_CURSOR: - if( FireBullet( m_vecPaintCursor, true ) ) - { - TaskComplete(); - } - break; - - case TASK_RANGE_ATTACK1: - { - // Where we're focusing our fire - Vector vecTarget = ( m_hBarrageTarget == NULL ) ? m_vecPaintCursor : LeadTarget( m_hBarrageTarget ); - - // Fire at enemy - if ( FireBullet( vecTarget, true ) ) - { - bool bPlayerIsEnemy = ( m_hBarrageTarget && m_hBarrageTarget->IsPlayer() ); - bool bBarrageFinished = m_flBarrageDuration < gpGlobals->curtime; - bool bNoShot = ( QuerySeeEntity( m_hBarrageTarget ) == false ); // FIXME: Store this info off better - bool bSeePlayer = HasCondition( COND_SEE_PLAYER ); - - // Treat the player differently to normal NPCs - if ( bPlayerIsEnemy ) - { - // Store the last time we shot for doing an abbreviated attack telegraph - m_flTimeLastAttackedPlayer = gpGlobals->curtime; - - // If we've got no shot and we're done with our current barrage - if ( bNoShot && bBarrageFinished ) - { - TaskComplete(); - } - } - else if ( bBarrageFinished || bSeePlayer ) - { - // Done with the barrage or we saw the player as a better target - TaskComplete(); - } - } - } - break; - - case TASK_CANNON_PAINT_ENEMY: - { - // See if we're done painting our target - if ( IsWaitFinished() ) - { - TaskComplete(); - } - - // Continue to paint the target - PaintTarget( LeadTarget( GetEnemy() ), m_flPaintTime ); - } - break; - - default: - BaseClass::RunTask( pTask ); - break; - } -} - - -//----------------------------------------------------------------------------- -// The sniper throws away the circular list of old decoys when we restore. -//----------------------------------------------------------------------------- -int CNPC_Combine_Cannon::Restore( IRestore &restore ) -{ - return BaseClass::Restore( restore ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -float CNPC_Combine_Cannon::MaxYawSpeed( void ) -{ - return 60; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Combine_Cannon::PrescheduleThink( void ) -{ - BaseClass::PrescheduleThink(); - - // NOTE: We'll deal with this on the client - // Think faster if the beam is on, this gives the beam higher resolution. - if( m_pBeam ) - { - SetNextThink( gpGlobals->curtime + 0.03 ); - } - else - { - SetNextThink( gpGlobals->curtime + 0.1f ); - } - - // If the enemy has just stepped into view, or we've acquired a new enemy, - // Record the last time we've seen the enemy as right now. - // - // If the enemy has been out of sight for a full second, mark him eluded. - if( GetEnemy() != NULL ) - { - if( gpGlobals->curtime - GetEnemies()->LastTimeSeen( GetEnemy() ) > 30 ) - { - // Stop pestering enemies after 30 seconds of frustration. - GetEnemies()->ClearMemory( GetEnemy() ); - SetEnemy(NULL); - } - } -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -Vector CNPC_Combine_Cannon::EyePosition( void ) -{ - return GetAbsOrigin(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -Vector CNPC_Combine_Cannon::DesiredBodyTarget( CBaseEntity *pTarget ) -{ - // By default, aim for the center - Vector vecTarget = pTarget->WorldSpaceCenter(); - - float flTimeSinceLastMiss = gpGlobals->curtime - m_flTimeLastShotMissed; - - if( pTarget->GetFlags() & FL_CLIENT ) - { - if( !BaseClass::FVisible( vecTarget ) ) - { - // go to the player's eyes if his center is concealed. - // Bump up an inch so the player's not looking straight down a beam. - vecTarget = pTarget->EyePosition() + Vector( 0, 0, 1 ); - } - } - else - { - if( pTarget->Classify() == CLASS_HEADCRAB ) - { - // Headcrabs are tiny inside their boxes. - vecTarget = pTarget->GetAbsOrigin(); - vecTarget.z += 4.0; - } - else if( pTarget->Classify() == CLASS_ZOMBIE ) - { - if( flTimeSinceLastMiss > 0.0f && flTimeSinceLastMiss < 4.0f && hl2_episodic.GetBool() ) - { - vecTarget = pTarget->BodyTarget( GetBulletOrigin(), false ); - } - else - { - // Shoot zombies in the headcrab - vecTarget = pTarget->HeadTarget( GetBulletOrigin() ); - } - } - else if( pTarget->Classify() == CLASS_ANTLION ) - { - // Shoot about a few inches above the origin. This makes it easy to hit antlions - // even if they are on their backs. - vecTarget = pTarget->GetAbsOrigin(); - vecTarget.z += 18.0f; - } - else if( pTarget->Classify() == CLASS_EARTH_FAUNA ) - { - // Shoot birds in the center - } - else - { - // Shoot NPCs in the chest - vecTarget.z += 8.0f; - } - } - - return vecTarget; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -Vector CNPC_Combine_Cannon::LeadTarget( CBaseEntity *pTarget ) -{ - if ( pTarget != NULL ) - { - Vector vecFuturePos; - UTIL_PredictedPosition( pTarget, 0.05f, &vecFuturePos ); - AdjustShotPosition( pTarget, &vecFuturePos ); - - return vecFuturePos; - } - - return vec3_origin; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Combine_Cannon::InputEnableSniper( inputdata_t &inputdata ) -{ - ClearCondition( COND_CANNON_DISABLED ); - SetCondition( COND_CANNON_ENABLED ); - - m_fEnabled = true; -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Combine_Cannon::InputDisableSniper( inputdata_t &inputdata ) -{ - ClearCondition( COND_CANNON_ENABLED ); - SetCondition( COND_CANNON_DISABLED ); - - m_fEnabled = false; -} - -//--------------------------------------------------------- -// See all NPC's easily. -// -// Only see the player if you can trace to both of his -// eyeballs. That is, allow the player to peek around corners. -// This is a little more expensive than the base class' check! -//--------------------------------------------------------- -#define CANNON_EYE_DIST 0.75 -#define CANNON_TARGET_VERTICAL_OFFSET Vector( 0, 0, 5 ); -bool CNPC_Combine_Cannon::FVisible( CBaseEntity *pEntity, int traceMask, CBaseEntity **ppBlocker ) -{ - // NPC - if ( pEntity->IsPlayer() == false ) - return BaseClass::FVisible( pEntity, traceMask, ppBlocker ); - - if ( pEntity->GetFlags() & FL_NOTARGET ) - return false; - - Vector vecVerticalOffset; - Vector vecRight; - Vector vecEye; - trace_t tr; - - if( fabs( GetAbsOrigin().z - pEntity->WorldSpaceCenter().z ) <= 120.f ) - { - // If the player is around the same elevation, look straight at his eyes. - // At the same elevation, the vertical peeking allowance makes it too easy - // for a player to dispatch the sniper from cover. - vecVerticalOffset = vec3_origin; - } - else - { - // Otherwise, look at a spot below his eyes. This allows the player to back away - // from his cover a bit and have a peek at the sniper without being detected. - vecVerticalOffset = CANNON_TARGET_VERTICAL_OFFSET; - } - - AngleVectors( pEntity->GetLocalAngles(), NULL, &vecRight, NULL ); - - vecEye = vecRight * CANNON_EYE_DIST - vecVerticalOffset; - UTIL_TraceLine( EyePosition(), pEntity->EyePosition() + vecEye, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - -#if 0 - NDebugOverlay::Line(EyePosition(), tr.endpos, 0,255,0, true, 0.1); -#endif - - bool fCheckFailed = false; - - if ( tr.fraction != 1.0 && tr.m_pEnt != pEntity ) - { - fCheckFailed = true; - } - - // Don't check the other eye if the first eye failed. - if( !fCheckFailed ) - { - vecEye = -vecRight * CANNON_EYE_DIST - vecVerticalOffset; - UTIL_TraceLine( EyePosition(), pEntity->EyePosition() + vecEye, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - -#if 0 - NDebugOverlay::Line(EyePosition(), tr.endpos, 0,255,0, true, 0.1); -#endif - - if ( tr.fraction != 1.0 && tr.m_pEnt != pEntity ) - { - fCheckFailed = true; - } - } - - if( !fCheckFailed ) - { - // Can see the player. - return true; - } - - // Now, if the check failed, see if the player is ducking and has recently - // fired a muzzleflash. If yes, see if you'd be able to see the player if - // they were standing in their current position instead of ducking. Since - // the sniper doesn't have a clear shot in this situation, he will harrass - // near the player. - CBasePlayer *pPlayer; - - pPlayer = ToBasePlayer( pEntity ); - - if( (pPlayer->GetFlags() & FL_DUCKING) && pPlayer->MuzzleFlashTime() > gpGlobals->curtime ) - { - vecEye = pPlayer->EyePosition() + Vector( 0, 0, 32 ); - UTIL_TraceLine( EyePosition(), vecEye, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - if( tr.fraction != 1.0 ) - { - // Everything failed. - if (ppBlocker) - { - *ppBlocker = tr.m_pEnt; - } - return false; - } - else - { - // Fake being able to see the player. - return true; - } - } - - if (ppBlocker) - { - *ppBlocker = tr.m_pEnt; - } - - return false; -} - - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC( npc_combine_cannon, CNPC_Combine_Cannon ) - - DECLARE_CONDITION( COND_CANNON_ENABLED ); - DECLARE_CONDITION( COND_CANNON_DISABLED ); - DECLARE_CONDITION( COND_CANNON_NO_SHOT ); - - DECLARE_TASK( TASK_CANNON_PAINT_ENEMY ); - DECLARE_TASK( TASK_CANNON_ATTACK_CURSOR ); - - //========================================================= - // CAMP - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CANNON_CAMP, - - " Tasks" - " TASK_WAIT 1" - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_CAN_RANGE_ATTACK1" - " COND_HEAR_DANGER" - " COND_CANNON_DISABLED" - ) - - //========================================================= - // ATTACK - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CANNON_ATTACK, - - " Tasks" - " TASK_CANNON_PAINT_ENEMY 0" - " TASK_RANGE_ATTACK1 0" - " " - " Interrupts" - " COND_HEAR_DANGER" - " COND_CANNON_DISABLED" - ) - - //========================================================= - // ATTACK - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CANNON_SNAPATTACK, - - " Tasks" - " TASK_CANNON_ATTACK_CURSOR 0" - " " - " Interrupts" - " COND_ENEMY_OCCLUDED" - " COND_ENEMY_DEAD" - " COND_NEW_ENEMY" - " COND_HEAR_DANGER" - " COND_CANNON_DISABLED" - ) - - //========================================================= - // Sniper is allowed to process a couple conditions while - // disabled, but mostly he waits until he's enabled. - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CANNON_DISABLEDWAIT, - - " Tasks" - " TASK_WAIT 0.5" - " " - " Interrupts" - " COND_CANNON_ENABLED" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - ) - -AI_END_CUSTOM_NPC() diff --git a/game/server/episodic/npc_hunter.cpp b/game/server/episodic/npc_hunter.cpp deleted file mode 100644 index 11bfe8d12..000000000 --- a/game/server/episodic/npc_hunter.cpp +++ /dev/null @@ -1,7767 +0,0 @@ -//==== Copyright 1996-2007, Valve Corporation, All rights reserved. ========= -// -// Small, fast version of the strider. Goes where striders cannot, such -// as into buildings. Best killed with physics objects and explosives. -// -//============================================================================= - -#include "cbase.h" -#include "npc_strider.h" -#include "npc_hunter.h" -#include "ai_behavior_follow.h" -#include "ai_moveprobe.h" -#include "ai_senses.h" -#include "ai_speech.h" -#include "ai_task.h" -#include "ai_default.h" -#include "ai_schedule.h" -#include "ai_hull.h" -#include "ai_baseactor.h" -#include "ai_waypoint.h" -#include "ai_link.h" -#include "ai_hint.h" -#include "ai_squadslot.h" -#include "ai_squad.h" -#include "ai_tacticalservices.h" -#include "beam_shared.h" -#include "datacache/imdlcache.h" -#include "eventqueue.h" -#include "gib.h" -#include "globalstate.h" -#include "hierarchy.h" -#include "movevars_shared.h" -#include "npcevent.h" -#include "saverestore_utlvector.h" -#include "particle_parse.h" -#include "te_particlesystem.h" -#include "sceneentity.h" -#include "shake.h" -#include "soundenvelope.h" -#include "soundent.h" -#include "SpriteTrail.h" -#include "IEffects.h" -#include "engine/IEngineSound.h" -#include "bone_setup.h" -#include "studio.h" -#include "ai_route.h" -#include "ammodef.h" -#include "npc_bullseye.h" -#include "physobj.h" -#include "ai_memory.h" -#include "collisionutils.h" -#include "shot_manipulator.h" -#include "steamjet.h" -#include "physics_prop_ragdoll.h" -#include "vehicle_base.h" -#include "coordsize.h" -#include "hl2_shareddefs.h" -#include "te_effect_dispatch.h" -#include "beam_flags.h" -#include "prop_combine_ball.h" -#include "explode.h" -#include "weapon_physcannon.h" -#include "weapon_striderbuster.h" -#include "monstermaker.h" -#include "weapon_rpg.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CNPC_Hunter; - - -static const char *HUNTER_FLECHETTE_MODEL = "models/weapons/hunter_flechette.mdl"; - -// Think contexts -static const char *HUNTER_BLEED_THINK = "HunterBleed"; -static const char *HUNTER_ZAP_THINK = "HunterZap"; -static const char *HUNTER_JOSTLE_VEHICLE_THINK = "HunterJostle"; - - -ConVar sk_hunter_health( "sk_hunter_health", "210" ); - -// Melee attacks -ConVar sk_hunter_dmg_one_slash( "sk_hunter_dmg_one_slash", "20" ); -ConVar sk_hunter_dmg_charge( "sk_hunter_dmg_charge", "20" ); - -// Flechette volley attack -ConVar hunter_flechette_max_range( "hunter_flechette_max_range", "1200" ); -ConVar hunter_flechette_min_range( "hunter_flechette_min_range", "100" ); -ConVar hunter_flechette_volley_size( "hunter_flechette_volley_size", "8" ); -ConVar hunter_flechette_speed( "hunter_flechette_speed", "2000" ); -ConVar sk_hunter_dmg_flechette( "sk_hunter_dmg_flechette", "4.0" ); -ConVar sk_hunter_flechette_explode_dmg( "sk_hunter_flechette_explode_dmg", "12.0" ); -ConVar sk_hunter_flechette_explode_radius( "sk_hunter_flechette_explode_radius", "128.0" ); -ConVar hunter_flechette_explode_delay( "hunter_flechette_explode_delay", "2.5" ); -ConVar hunter_flechette_delay( "hunter_flechette_delay", "0.1" ); -ConVar hunter_first_flechette_delay( "hunter_first_flechette_delay", "0.5" ); -ConVar hunter_flechette_max_concurrent_volleys( "hunter_flechette_max_concurrent_volleys", "2" ); -ConVar hunter_flechette_volley_start_min_delay( "hunter_flechette_volley_start_min_delay", ".25" ); -ConVar hunter_flechette_volley_start_max_delay( "hunter_flechette_volley_start_max_delay", ".95" ); -ConVar hunter_flechette_volley_end_min_delay( "hunter_flechette_volley_end_min_delay", "1" ); -ConVar hunter_flechette_volley_end_max_delay( "hunter_flechette_volley_end_max_delay", "2" ); -ConVar hunter_flechette_test( "hunter_flechette_test", "0" ); -ConVar hunter_clamp_shots( "hunter_clamp_shots", "1" ); -ConVar hunter_cheap_explosions( "hunter_cheap_explosions", "1" ); - -// Damage received -ConVar sk_hunter_bullet_damage_scale( "sk_hunter_bullet_damage_scale", "0.6" ); -ConVar sk_hunter_charge_damage_scale( "sk_hunter_charge_damage_scale", "2.0" ); -ConVar sk_hunter_buckshot_damage_scale( "sk_hunter_buckshot_damage_scale", "0.5" ); -ConVar sk_hunter_vehicle_damage_scale( "sk_hunter_vehicle_damage_scale", "2.2" ); -ConVar sk_hunter_dmg_from_striderbuster( "sk_hunter_dmg_from_striderbuster", "150" ); -ConVar sk_hunter_citizen_damage_scale( "sk_hunter_citizen_damage_scale", "0.3" ); - -ConVar hunter_allow_dissolve( "hunter_allow_dissolve", "1" ); -ConVar hunter_random_expressions( "hunter_random_expressions", "0" ); -ConVar hunter_show_weapon_los_z( "hunter_show_weapon_los_z", "0" ); -ConVar hunter_show_weapon_los_condition( "hunter_show_weapon_los_condition", "0" ); - -ConVar hunter_melee_delay( "hunter_melee_delay", "2.0" ); - -// Bullrush charge. -ConVar hunter_charge( "hunter_charge", "1" ); -ConVar hunter_charge_min_delay( "hunter_charge_min_delay", "10.0" ); -ConVar hunter_charge_pct( "hunter_charge_pct", "25" ); -ConVar hunter_charge_test( "hunter_charge_test", "0" ); - -// Vehicle dodging. -ConVar hunter_dodge_warning( "hunter_dodge_warning", "1.1" ); -ConVar hunter_dodge_warning_width( "hunter_dodge_warning_width", "180" ); -ConVar hunter_dodge_warning_cone( "hunter_dodge_warning_cone", ".5" ); -ConVar hunter_dodge_debug( "hunter_dodge_debug", "0" ); - -// Jostle vehicles when hit by them -ConVar hunter_jostle_car_min_speed( "hunter_jostle_car_min_speed", "100" ); // If hit by a car going at least this fast, jostle the car -ConVar hunter_jostle_car_max_speed( "hunter_jostle_car_max_speed", "600" ); // Used for determining jostle scale - -ConVar hunter_free_knowledge( "hunter_free_knowledge", "10.0" ); -ConVar hunter_plant_adjust_z( "hunter_plant_adjust_z", "12" ); - -ConVar hunter_disable_patrol( "hunter_disable_patrol", "0" ); - -// Dealing with striderbusters -ConVar hunter_hate_held_striderbusters( "hunter_hate_held_striderbusters", "1" ); -ConVar hunter_hate_thrown_striderbusters( "hunter_hate_thrown_striderbusters", "1" ); -ConVar hunter_hate_attached_striderbusters( "hunter_hate_attached_striderbusters", "1" ); -ConVar hunter_hate_held_striderbusters_delay( "hunter_hate_held_striderbusters_delay", "0.5" ); -ConVar hunter_hate_held_striderbusters_tolerance( "hunter_hate_held_striderbusters_tolerance", "2000.0" ); -ConVar hunter_hate_thrown_striderbusters_tolerance( "hunter_hate_thrown_striderbusters_tolerance", "300.0" ); -ConVar hunter_seek_thrown_striderbusters_tolerance( "hunter_seek_thrown_striderbusters_tolerance", "400.0" ); -ConVar hunter_retreat_striderbusters( "hunter_retreat_striderbusters", "1", FCVAR_NONE, "If true, the hunter will retreat when a buster is glued to him." ); - -ConVar hunter_allow_nav_jump( "hunter_allow_nav_jump", "0" ); -ConVar g_debug_hunter_charge( "g_debug_hunter_charge", "0" ); - -ConVar hunter_stand_still( "hunter_stand_still", "0" ); // used for debugging, keeps them rooted in place - -ConVar hunter_siege_frequency( "hunter_siege_frequency", "12" ); - -#define HUNTER_FOV_DOT 0.0 // 180 degree field of view -#define HUNTER_CHARGE_MIN 256 -#define HUNTER_CHARGE_MAX 1024 -#define HUNTER_FACE_ENEMY_DIST 512.0f -#define HUNTER_MELEE_REACH 80 -#define HUNTER_BLOOD_LEFT_FOOT 0 -#define HUNTER_IGNORE_ENEMY_TIME 5 // How long the hunter will ignore another enemy when distracted by the player. - -#define HUNTER_FACING_DOT 0.8 // The angle within which we start shooting -#define HUNTER_SHOOT_MAX_YAW_DEG 60.0f // Once shooting, clamp to +/- these degrees of yaw deflection as our target moves -#define HUNTER_SHOOT_MAX_YAW_COS 0.5f // The cosine of the above angle - -#define HUNTER_FLECHETTE_WARN_TIME 1.0f - -#define HUNTER_SEE_ENEMY_TIME_INVALID -1 - -#define NUM_FLECHETTE_VOLLEY_ON_FOLLOW 4 - -#define HUNTER_SIEGE_MAX_DIST_MODIFIER 2.0f - -//----------------------------------------------------------------------------- -// Animation events -//----------------------------------------------------------------------------- -int AE_HUNTER_FOOTSTEP_LEFT; -int AE_HUNTER_FOOTSTEP_RIGHT; -int AE_HUNTER_FOOTSTEP_BACK; -int AE_HUNTER_MELEE_ANNOUNCE; -int AE_HUNTER_MELEE_ATTACK_LEFT; -int AE_HUNTER_MELEE_ATTACK_RIGHT; -int AE_HUNTER_DIE; -int AE_HUNTER_SPRAY_BLOOD; -int AE_HUNTER_START_EXPRESSION; -int AE_HUNTER_END_EXPRESSION; - - -//----------------------------------------------------------------------------- -// Interactions. -//----------------------------------------------------------------------------- -int g_interactionHunterFoundEnemy = 0; - - -//----------------------------------------------------------------------------- -// Local stuff. -//----------------------------------------------------------------------------- -static string_t s_iszStriderClassname; -static string_t s_iszStriderBusterClassname; -static string_t s_iszMagnadeClassname; -static string_t s_iszPhysPropClassname; -static string_t s_iszHuntersToRunOver; - - -//----------------------------------------------------------------------------- -// Custom Activities -//----------------------------------------------------------------------------- -Activity ACT_HUNTER_DEPLOYRA2; -Activity ACT_HUNTER_DODGER; -Activity ACT_HUNTER_DODGEL; -Activity ACT_HUNTER_GESTURE_SHOOT; -Activity ACT_HUNTER_FLINCH_STICKYBOMB; -Activity ACT_HUNTER_STAGGER; -Activity ACT_HUNTER_MELEE_ATTACK1_VS_PLAYER; -Activity ACT_DI_HUNTER_MELEE; -Activity ACT_DI_HUNTER_THROW; -Activity ACT_HUNTER_ANGRY; -Activity ACT_HUNTER_WALK_ANGRY; -Activity ACT_HUNTER_FOUND_ENEMY; -Activity ACT_HUNTER_FOUND_ENEMY_ACK; -Activity ACT_HUNTER_CHARGE_START; -Activity ACT_HUNTER_CHARGE_RUN; -Activity ACT_HUNTER_CHARGE_STOP; -Activity ACT_HUNTER_CHARGE_CRASH; -Activity ACT_HUNTER_CHARGE_HIT; -Activity ACT_HUNTER_RANGE_ATTACK2_UNPLANTED; -Activity ACT_HUNTER_IDLE_PLANTED; -Activity ACT_HUNTER_FLINCH_N; -Activity ACT_HUNTER_FLINCH_S; -Activity ACT_HUNTER_FLINCH_E; -Activity ACT_HUNTER_FLINCH_W; - - -//----------------------------------------------------------------------------- -// Squad slots -//----------------------------------------------------------------------------- -enum SquadSlot_t -{ - SQUAD_SLOT_HUNTER_CHARGE = LAST_SHARED_SQUADSLOT, - SQUAD_SLOT_HUNTER_FLANK_FIRST, - SQUAD_SLOT_HUNTER_FLANK_LAST = SQUAD_SLOT_HUNTER_FLANK_FIRST, - SQUAD_SLOT_RUN_SHOOT, -}; - -#define HUNTER_FOLLOW_DISTANCE 2000.0f -#define HUNTER_FOLLOW_DISTANCE_SQR (HUNTER_FOLLOW_DISTANCE * HUNTER_FOLLOW_DISTANCE) - -#define HUNTER_RUNDOWN_SQUADDATA 0 - - -//----------------------------------------------------------------------------- -// We're doing this quite a lot, so this makes the check a lot faster since -// we don't have to compare strings. -//----------------------------------------------------------------------------- -bool IsStriderBuster( CBaseEntity *pEntity ) -{ - if ( !pEntity ) - return false; - - if( pEntity->m_iClassname == s_iszStriderBusterClassname || - pEntity->m_iClassname == s_iszMagnadeClassname) - return true; - - return false; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool HateThisStriderBuster( CBaseEntity *pTarget ) -{ - if ( StriderBuster_WasKnockedOffStrider(pTarget) ) - return false; - - if ( pTarget->VPhysicsGetObject() ) - { - if ( hunter_hate_held_striderbusters.GetBool() || - hunter_hate_thrown_striderbusters.GetBool() || - hunter_hate_attached_striderbusters.GetBool() ) - { - if ( ( pTarget->VPhysicsGetObject()->GetGameFlags() & ( FVPHYSICS_PLAYER_HELD | FVPHYSICS_WAS_THROWN ) ) ) - { - return true; - } - - if ( StriderBuster_IsAttachedStriderBuster( pTarget ) ) - { - return true; - } - } - } - - return false; -} - - -//----------------------------------------------------------------------------- -// The hunter can fire a volley of explosive flechettes. -//----------------------------------------------------------------------------- -static const char *s_szHunterFlechetteBubbles = "HunterFlechetteBubbles"; -static const char *s_szHunterFlechetteSeekThink = "HunterFlechetteSeekThink"; -//static const char *s_szHunterFlechetteDangerSoundThink = "HunterFlechetteDangerSoundThink"; -//static const char *s_szHunterFlechetteSpriteTrail = "sprites/bluelaser1.vmt"; -static int s_nHunterFlechetteImpact = -2; -static int s_nFlechetteFuseAttach = -1; - -#define FLECHETTE_AIR_VELOCITY 2500 - -class CHunterFlechette : public CPhysicsProp, public IParentPropInteraction -{ - DECLARE_CLASS( CHunterFlechette, CPhysicsProp ); - -public: - - CHunterFlechette(); - ~CHunterFlechette(); - - Class_T Classify() { return CLASS_NONE; } - - bool WasThrownBack() - { - return m_bThrownBack; - } - -public: - - void Spawn(); - void Activate(); - void Precache(); - void Shoot( Vector &vecVelocity, bool bBright ); - void SetSeekTarget( CBaseEntity *pTargetEntity ); - void Explode(); - - bool CreateVPhysics(); - - unsigned int PhysicsSolidMaskForEntity() const; - static CHunterFlechette *FlechetteCreate( const Vector &vecOrigin, const QAngle &angAngles, CBaseEntity *pentOwner = NULL ); - - // IParentPropInteraction - void OnParentCollisionInteraction( parentCollisionInteraction_t eType, int index, gamevcollisionevent_t *pEvent ); - void OnParentPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ); - -protected: - - void SetupGlobalModelData(); - - void StickTo( CBaseEntity *pOther, trace_t &tr ); - - void BubbleThink(); - void DangerSoundThink(); - void ExplodeThink(); - void DopplerThink(); - void SeekThink(); - - bool CreateSprites( bool bBright ); - - void FlechetteTouch( CBaseEntity *pOther ); - - Vector m_vecShootPosition; - EHANDLE m_hSeekTarget; - bool m_bThrownBack; - - DECLARE_DATADESC(); - //DECLARE_SERVERCLASS(); -}; - -LINK_ENTITY_TO_CLASS( hunter_flechette, CHunterFlechette ); - -BEGIN_DATADESC( CHunterFlechette ) - - DEFINE_THINKFUNC( BubbleThink ), - DEFINE_THINKFUNC( DangerSoundThink ), - DEFINE_THINKFUNC( ExplodeThink ), - DEFINE_THINKFUNC( DopplerThink ), - DEFINE_THINKFUNC( SeekThink ), - - DEFINE_ENTITYFUNC( FlechetteTouch ), - - DEFINE_FIELD( m_vecShootPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_hSeekTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_bThrownBack, FIELD_BOOLEAN ), - -END_DATADESC() - -//IMPLEMENT_SERVERCLASS_ST( CHunterFlechette, DT_HunterFlechette ) -//END_SEND_TABLE() - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CHunterFlechette *CHunterFlechette::FlechetteCreate( const Vector &vecOrigin, const QAngle &angAngles, CBaseEntity *pentOwner ) -{ - // Create a new entity with CHunterFlechette private data - CHunterFlechette *pFlechette = (CHunterFlechette *)CreateEntityByName( "hunter_flechette" ); - UTIL_SetOrigin( pFlechette, vecOrigin ); - pFlechette->SetAbsAngles( angAngles ); - pFlechette->Spawn(); - pFlechette->Activate(); - pFlechette->SetOwnerEntity( pentOwner ); - - return pFlechette; -} - - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CC_Hunter_Shoot_Flechette( const CCommand& args ) -{ - MDLCACHE_CRITICAL_SECTION(); - - bool allowPrecache = CBaseEntity::IsPrecacheAllowed(); - CBaseEntity::SetAllowPrecache( true ); - - CBasePlayer *pPlayer = UTIL_GetCommandClient(); - - QAngle angEye = pPlayer->EyeAngles(); - CHunterFlechette *entity = CHunterFlechette::FlechetteCreate( pPlayer->EyePosition(), angEye, pPlayer ); - if ( entity ) - { - entity->Precache(); - DispatchSpawn( entity ); - - // Shoot the flechette. - Vector forward, velocity; - pPlayer->EyeVectors( &forward ); - velocity = forward * 2000.0f; - entity->Shoot( velocity, false ); - } - - CBaseEntity::SetAllowPrecache( allowPrecache ); -} - -static ConCommand ent_create("hunter_shoot_flechette", CC_Hunter_Shoot_Flechette, "Fires a hunter flechette where the player is looking.", FCVAR_GAMEDLL | FCVAR_CHEAT); - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CHunterFlechette::CHunterFlechette() -{ - UseClientSideAnimation(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CHunterFlechette::~CHunterFlechette() -{ -} - - -//----------------------------------------------------------------------------- -// If set, the flechette will seek unerringly toward the target as it flies. -//----------------------------------------------------------------------------- -void CHunterFlechette::SetSeekTarget( CBaseEntity *pTargetEntity ) -{ - if ( pTargetEntity ) - { - m_hSeekTarget = pTargetEntity; - SetContextThink( &CHunterFlechette::SeekThink, gpGlobals->curtime, s_szHunterFlechetteSeekThink ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CHunterFlechette::CreateVPhysics() -{ - // Create the object in the physics system - VPhysicsInitNormal( SOLID_BBOX, FSOLID_NOT_STANDABLE, false ); - - return true; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -unsigned int CHunterFlechette::PhysicsSolidMaskForEntity() const -{ - return ( BaseClass::PhysicsSolidMaskForEntity() | CONTENTS_HITBOX ) & ~CONTENTS_GRATE; -} - - -//----------------------------------------------------------------------------- -// Called from CPropPhysics code when we're attached to a physics object. -//----------------------------------------------------------------------------- -void CHunterFlechette::OnParentCollisionInteraction( parentCollisionInteraction_t eType, int index, gamevcollisionevent_t *pEvent ) -{ - if ( eType == COLLISIONINTER_PARENT_FIRST_IMPACT ) - { - m_bThrownBack = true; - Explode(); - } -} - -void CHunterFlechette::OnParentPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ) -{ - m_bThrownBack = true; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CHunterFlechette::CreateSprites( bool bBright ) -{ - if ( bBright ) - { - DispatchParticleEffect( "hunter_flechette_trail_striderbuster", PATTACH_ABSORIGIN_FOLLOW, this ); - } - else - { - DispatchParticleEffect( "hunter_flechette_trail", PATTACH_ABSORIGIN_FOLLOW, this ); - } - - return true; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHunterFlechette::Spawn() -{ - Precache( ); - - SetModel( HUNTER_FLECHETTE_MODEL ); - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_CUSTOM ); - UTIL_SetSize( this, -Vector(1,1,1), Vector(1,1,1) ); - SetSolid( SOLID_BBOX ); - SetGravity( 0.05f ); - SetCollisionGroup( COLLISION_GROUP_PROJECTILE ); - - // Make sure we're updated if we're underwater - UpdateWaterState(); - - SetTouch( &CHunterFlechette::FlechetteTouch ); - - // Make us glow until we've hit the wall - m_nSkin = 1; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHunterFlechette::Activate() -{ - BaseClass::Activate(); - SetupGlobalModelData(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHunterFlechette::SetupGlobalModelData() -{ - if ( s_nHunterFlechetteImpact == -2 ) - { - s_nHunterFlechetteImpact = LookupSequence( "impact" ); - s_nFlechetteFuseAttach = LookupAttachment( "attach_fuse" ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHunterFlechette::Precache() -{ - PrecacheModel( HUNTER_FLECHETTE_MODEL ); - PrecacheModel( "sprites/light_glow02_noz.vmt" ); - - PrecacheScriptSound( "NPC_Hunter.FlechetteNearmiss" ); - PrecacheScriptSound( "NPC_Hunter.FlechetteHitBody" ); - PrecacheScriptSound( "NPC_Hunter.FlechetteHitWorld" ); - PrecacheScriptSound( "NPC_Hunter.FlechettePreExplode" ); - PrecacheScriptSound( "NPC_Hunter.FlechetteExplode" ); - - PrecacheParticleSystem( "hunter_flechette_trail_striderbuster" ); - PrecacheParticleSystem( "hunter_flechette_trail" ); - PrecacheParticleSystem( "hunter_projectile_explosion_1" ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHunterFlechette::StickTo( CBaseEntity *pOther, trace_t &tr ) -{ - EmitSound( "NPC_Hunter.FlechetteHitWorld" ); - - SetMoveType( MOVETYPE_NONE ); - - if ( !pOther->IsWorld() ) - { - SetParent( pOther ); - SetSolid( SOLID_NONE ); - SetSolidFlags( FSOLID_NOT_SOLID ); - } - - // Do an impact effect. - //Vector vecDir = GetAbsVelocity(); - //float speed = VectorNormalize( vecDir ); - - //Vector vForward; - //AngleVectors( GetAbsAngles(), &vForward ); - //VectorNormalize ( vForward ); - - //CEffectData data; - //data.m_vOrigin = tr.endpos; - //data.m_vNormal = vForward; - //data.m_nEntIndex = 0; - //DispatchEffect( "BoltImpact", data ); - - Vector vecVelocity = GetAbsVelocity(); - bool bAttachedToBuster = StriderBuster_OnFlechetteAttach( pOther, vecVelocity ); - - SetTouch( NULL ); - - // We're no longer flying. Stop checking for water volumes. - SetContextThink( NULL, 0, s_szHunterFlechetteBubbles ); - - // Stop seeking. - m_hSeekTarget = NULL; - SetContextThink( NULL, 0, s_szHunterFlechetteSeekThink ); - - // Get ready to explode. - if ( !bAttachedToBuster ) - { - SetThink( &CHunterFlechette::DangerSoundThink ); - SetNextThink( gpGlobals->curtime + (hunter_flechette_explode_delay.GetFloat() - HUNTER_FLECHETTE_WARN_TIME) ); - } - else - { - DangerSoundThink(); - } - - // Play our impact animation. - ResetSequence( s_nHunterFlechetteImpact ); - - static int s_nImpactCount = 0; - s_nImpactCount++; - if ( s_nImpactCount & 0x01 ) - { - UTIL_ImpactTrace( &tr, DMG_BULLET ); - - // Shoot some sparks - if ( UTIL_PointContents( GetAbsOrigin() ) != CONTENTS_WATER) - { - g_pEffects->Sparks( GetAbsOrigin() ); - } - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHunterFlechette::FlechetteTouch( CBaseEntity *pOther ) -{ - if ( pOther->IsSolidFlagSet(FSOLID_VOLUME_CONTENTS | FSOLID_TRIGGER) ) - { - // Some NPCs are triggers that can take damage (like antlion grubs). We should hit them. - if ( ( pOther->m_takedamage == DAMAGE_NO ) || ( pOther->m_takedamage == DAMAGE_EVENTS_ONLY ) ) - return; - } - - if ( FClassnameIs( pOther, "hunter_flechette" ) ) - return; - - trace_t tr; - tr = BaseClass::GetTouchTrace(); - - if ( pOther->m_takedamage != DAMAGE_NO ) - { - Vector vecNormalizedVel = GetAbsVelocity(); - - ClearMultiDamage(); - VectorNormalize( vecNormalizedVel ); - - float flDamage = sk_hunter_dmg_flechette.GetFloat(); - CBreakable *pBreak = dynamic_cast (pOther); - if ( pBreak && ( pBreak->GetMaterialType() == matGlass ) ) - { - flDamage = MAX( pOther->GetHealth(), flDamage ); - } - - CTakeDamageInfo dmgInfo( this, GetOwnerEntity(), flDamage, DMG_DISSOLVE | DMG_NEVERGIB ); - CalculateMeleeDamageForce( &dmgInfo, vecNormalizedVel, tr.endpos, 0.7f ); - dmgInfo.SetDamagePosition( tr.endpos ); - pOther->DispatchTraceAttack( dmgInfo, vecNormalizedVel, &tr ); - - ApplyMultiDamage(); - - // Keep going through breakable glass. - if ( pOther->GetCollisionGroup() == COLLISION_GROUP_BREAKABLE_GLASS ) - return; - - SetAbsVelocity( Vector( 0, 0, 0 ) ); - - // play body "thwack" sound - EmitSound( "NPC_Hunter.FlechetteHitBody" ); - - StopParticleEffects( this ); - - Vector vForward; - AngleVectors( GetAbsAngles(), &vForward ); - VectorNormalize ( vForward ); - - trace_t tr2; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + vForward * 128, MASK_BLOCKLOS, pOther, COLLISION_GROUP_NONE, &tr2 ); - - if ( tr2.fraction != 1.0f ) - { - //NDebugOverlay::Box( tr2.endpos, Vector( -16, -16, -16 ), Vector( 16, 16, 16 ), 0, 255, 0, 0, 10 ); - //NDebugOverlay::Box( GetAbsOrigin(), Vector( -16, -16, -16 ), Vector( 16, 16, 16 ), 0, 0, 255, 0, 10 ); - - if ( tr2.m_pEnt == NULL || ( tr2.m_pEnt && tr2.m_pEnt->GetMoveType() == MOVETYPE_NONE ) ) - { - CEffectData data; - - data.m_vOrigin = tr2.endpos; - data.m_vNormal = vForward; - data.m_nEntIndex = tr2.fraction != 1.0f; - - //DispatchEffect( "BoltImpact", data ); - } - } - - if ( ( ( pOther->GetMoveType() == MOVETYPE_VPHYSICS ) || ( pOther->GetMoveType() == MOVETYPE_PUSH ) ) && ( ( pOther->GetHealth() > 0 ) || ( pOther->m_takedamage == DAMAGE_EVENTS_ONLY ) ) ) - { - CPhysicsProp *pProp = dynamic_cast( pOther ); - if ( pProp ) - { - pProp->SetInteraction( PROPINTER_PHYSGUN_NOTIFY_CHILDREN ); - } - - // We hit a physics object that survived the impact. Stick to it. - StickTo( pOther, tr ); - } - else - { - SetTouch( NULL ); - SetThink( NULL ); - SetContextThink( NULL, 0, s_szHunterFlechetteBubbles ); - - UTIL_Remove( this ); - } - } - else - { - // See if we struck the world - if ( pOther->GetMoveType() == MOVETYPE_NONE && !( tr.surface.flags & SURF_SKY ) ) - { - // We hit a physics object that survived the impact. Stick to it. - StickTo( pOther, tr ); - } - else if( pOther->GetMoveType() == MOVETYPE_PUSH && FClassnameIs(pOther, "func_breakable") ) - { - // We hit a func_breakable, stick to it. - // The MOVETYPE_PUSH is a micro-optimization to cut down on the classname checks. - StickTo( pOther, tr ); - } - else - { - // Put a mark unless we've hit the sky - if ( ( tr.surface.flags & SURF_SKY ) == false ) - { - UTIL_ImpactTrace( &tr, DMG_BULLET ); - } - - UTIL_Remove( this ); - } - } -} - - -//----------------------------------------------------------------------------- -// Fixup flechette position when seeking towards a striderbuster. -//----------------------------------------------------------------------------- -void CHunterFlechette::SeekThink() -{ - if ( m_hSeekTarget ) - { - Vector vecBodyTarget = m_hSeekTarget->BodyTarget( GetAbsOrigin() ); - - Vector vecClosest; - CalcClosestPointOnLineSegment( GetAbsOrigin(), m_vecShootPosition, vecBodyTarget, vecClosest, NULL ); - - Vector vecDelta = vecBodyTarget - m_vecShootPosition; - VectorNormalize( vecDelta ); - - QAngle angShoot; - VectorAngles( vecDelta, angShoot ); - - float flSpeed = hunter_flechette_speed.GetFloat(); - if ( !flSpeed ) - { - flSpeed = 2500.0f; - } - - Vector vecVelocity = vecDelta * flSpeed; - Teleport( &vecClosest, &angShoot, &vecVelocity ); - - SetNextThink( gpGlobals->curtime, s_szHunterFlechetteSeekThink ); - } -} - - -//----------------------------------------------------------------------------- -// Play a near miss sound as we travel past the player. -//----------------------------------------------------------------------------- -void CHunterFlechette::DopplerThink() -{ - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( !pPlayer ) - return; - - Vector vecVelocity = GetAbsVelocity(); - VectorNormalize( vecVelocity ); - - float flMyDot = DotProduct( vecVelocity, GetAbsOrigin() ); - float flPlayerDot = DotProduct( vecVelocity, pPlayer->GetAbsOrigin() ); - - if ( flPlayerDot <= flMyDot ) - { - EmitSound( "NPC_Hunter.FlechetteNearMiss" ); - - // We've played the near miss sound and we're not seeking. Stop thinking. - SetThink( NULL ); - } - else - { - SetNextThink( gpGlobals->curtime ); - } -} - - -//----------------------------------------------------------------------------- -// Think every 0.1 seconds to make bubbles if we're flying through water. -//----------------------------------------------------------------------------- -void CHunterFlechette::BubbleThink() -{ - SetNextThink( gpGlobals->curtime + 0.1f, s_szHunterFlechetteBubbles ); - - if ( GetWaterLevel() == 0 ) - return; - - UTIL_BubbleTrail( GetAbsOrigin() - GetAbsVelocity() * 0.1f, GetAbsOrigin(), 5 ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHunterFlechette::Shoot( Vector &vecVelocity, bool bBrightFX ) -{ - CreateSprites( bBrightFX ); - - m_vecShootPosition = GetAbsOrigin(); - - SetAbsVelocity( vecVelocity ); - - SetThink( &CHunterFlechette::DopplerThink ); - SetNextThink( gpGlobals->curtime ); - - SetContextThink( &CHunterFlechette::BubbleThink, gpGlobals->curtime + 0.1, s_szHunterFlechetteBubbles ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHunterFlechette::DangerSoundThink() -{ - EmitSound( "NPC_Hunter.FlechettePreExplode" ); - - CSoundEnt::InsertSound( SOUND_DANGER|SOUND_CONTEXT_EXCLUDE_COMBINE, GetAbsOrigin(), 150, 0.5, this ); - SetThink( &CHunterFlechette::ExplodeThink ); - SetNextThink( gpGlobals->curtime + HUNTER_FLECHETTE_WARN_TIME ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHunterFlechette::ExplodeThink() -{ - Explode(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHunterFlechette::Explode() -{ - SetSolid( SOLID_NONE ); - - // Don't catch self in own explosion! - m_takedamage = DAMAGE_NO; - - EmitSound( "NPC_Hunter.FlechetteExplode" ); - - // Move the explosion effect to the tip to reduce intersection with the world. - Vector vecFuse; - GetAttachment( s_nFlechetteFuseAttach, vecFuse ); - DispatchParticleEffect( "hunter_projectile_explosion_1", vecFuse, GetAbsAngles(), NULL ); - - int nDamageType = DMG_DISSOLVE; - - // Perf optimization - only every other explosion makes a physics force. This is - // hardly noticeable since flechettes usually explode in clumps. - static int s_nExplosionCount = 0; - s_nExplosionCount++; - if ( ( s_nExplosionCount & 0x01 ) && hunter_cheap_explosions.GetBool() ) - { - nDamageType |= DMG_PREVENT_PHYSICS_FORCE; - } - - RadiusDamage( CTakeDamageInfo( this, GetOwnerEntity(), sk_hunter_flechette_explode_dmg.GetFloat(), nDamageType ), GetAbsOrigin(), sk_hunter_flechette_explode_radius.GetFloat(), CLASS_NONE, NULL ); - - AddEffects( EF_NODRAW ); - - SetThink( &CBaseEntity::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 0.1f ); -} - - -//----------------------------------------------------------------------------- -// Calculate & apply damage & force for a charge to a target. -// Done outside of the hunter because we need to do this inside a trace filter. -//----------------------------------------------------------------------------- -void Hunter_ApplyChargeDamage( CBaseEntity *pHunter, CBaseEntity *pTarget, float flDamage ) -{ - Vector attackDir = ( pTarget->WorldSpaceCenter() - pHunter->WorldSpaceCenter() ); - VectorNormalize( attackDir ); - Vector offset = RandomVector( -32, 32 ) + pTarget->WorldSpaceCenter(); - - // Generate enough force to make a 75kg guy move away at 700 in/sec - Vector vecForce = attackDir * ImpulseScale( 75, 700 ); - - // Deal the damage - CTakeDamageInfo info( pHunter, pHunter, vecForce, offset, flDamage, DMG_CLUB ); - pTarget->TakeDamage( info ); -} - - -//----------------------------------------------------------------------------- -// A simple trace filter class to skip small moveable physics objects -//----------------------------------------------------------------------------- -class CHunterTraceFilterSkipPhysics : public CTraceFilter -{ -public: - // It does have a base, but we'll never network anything below here.. - DECLARE_CLASS_NOBASE( CHunterTraceFilterSkipPhysics ); - - CHunterTraceFilterSkipPhysics( const IHandleEntity *passentity, int collisionGroup, float minMass ) - : m_pPassEnt(passentity), m_collisionGroup(collisionGroup), m_minMass(minMass) - { - } - virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) - { - if ( !StandardFilterRules( pHandleEntity, contentsMask ) ) - return false; - - if ( !PassServerEntityFilter( pHandleEntity, m_pPassEnt ) ) - return false; - - // Don't test if the game code tells us we should ignore this collision... - CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); - if ( pEntity ) - { - if ( !pEntity->ShouldCollide( m_collisionGroup, contentsMask ) ) - return false; - - if ( !g_pGameRules->ShouldCollide( m_collisionGroup, pEntity->GetCollisionGroup() ) ) - return false; - - // don't test small moveable physics objects (unless it's an NPC) - if ( !pEntity->IsNPC() && pEntity->GetMoveType() == MOVETYPE_VPHYSICS ) - { - float entMass = PhysGetEntityMass( pEntity ) ; - if ( entMass < m_minMass ) - { - if ( entMass < m_minMass * 0.666f || pEntity->CollisionProp()->BoundingRadius() < (assert_cast(EntityFromEntityHandle( m_pPassEnt )))->GetHullHeight() ) - { - return false; - } - } - } - - // If we hit an antlion, don't stop, but kill it - if ( pEntity->Classify() == CLASS_ANTLION ) - { - CBaseEntity *pHunter = (CBaseEntity *)EntityFromEntityHandle( m_pPassEnt ); - Hunter_ApplyChargeDamage( pHunter, pEntity, pEntity->GetHealth() ); - return false; - } - } - - return true; - } - -private: - const IHandleEntity *m_pPassEnt; - int m_collisionGroup; - float m_minMass; -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void HunterTraceHull_SkipPhysics( const Vector &vecAbsStart, const Vector &vecAbsEnd, const Vector &hullMin, - const Vector &hullMax, unsigned int mask, const CBaseEntity *ignore, - int collisionGroup, trace_t *ptr, float minMass ) -{ - Ray_t ray; - ray.Init( vecAbsStart, vecAbsEnd, hullMin, hullMax ); - CHunterTraceFilterSkipPhysics traceFilter( ignore, collisionGroup, minMass ); - enginetrace->TraceRay( ray, mask, &traceFilter, ptr ); -} - - -//----------------------------------------------------------------------------- -// Hunter follow behavior -//----------------------------------------------------------------------------- -class CAI_HunterEscortBehavior : public CAI_FollowBehavior -{ - DECLARE_CLASS( CAI_HunterEscortBehavior, CAI_FollowBehavior ); - -public: - - CAI_HunterEscortBehavior() : - BaseClass( AI_FollowParams_t( AIF_HUNTER, true ) ), - m_flTimeEscortReturn( 0 ), - m_bEnabled( false ) - { - } - - CNPC_Hunter *GetOuter() { return (CNPC_Hunter *)( BaseClass::GetOuter() ); } - - void SetEscortTarget( CNPC_Strider *pLeader, bool fFinishCurSchedule = false ); - CNPC_Strider * GetEscortTarget() { return (CNPC_Strider *)GetFollowTarget(); } - - bool FarFromFollowTarget() - { - return ( GetFollowTarget() && (GetAbsOrigin() - GetFollowTarget()->GetAbsOrigin()).LengthSqr() > HUNTER_FOLLOW_DISTANCE_SQR ); - } - - void DrawDebugGeometryOverlays(); - bool ShouldFollow(); - void BuildScheduleTestBits(); - - void BeginScheduleSelection(); - - void GatherConditions(); - void GatherConditionsNotActive(); - int SelectSchedule(); - int FollowCallBaseSelectSchedule(); - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - - void CheckBreakEscort(); - - void OnDamage( const CTakeDamageInfo &info ); - static void DistributeFreeHunters(); - static void FindFreeHunters( CUtlVector *pFreeHunters ); - - float m_flTimeEscortReturn; - CSimpleSimTimer m_FollowAttackTimer; - bool m_bEnabled; - - static float gm_flLastDefendSound; // not saved and loaded, it's okay to yell again after a load - - //--------------------------------- - - DECLARE_DATADESC(); -}; - - -BEGIN_DATADESC( CAI_HunterEscortBehavior ) - DEFINE_FIELD( m_flTimeEscortReturn, FIELD_TIME ), - DEFINE_EMBEDDED( m_FollowAttackTimer ), - DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ), -END_DATADESC(); - -float CAI_HunterEscortBehavior::gm_flLastDefendSound; - -//----------------------------------------------------------------------------- -// Hunter PHYSICS DAMAGE TABLE -//----------------------------------------------------------------------------- -#define HUNTER_MIN_PHYSICS_DAMAGE 10 - -static impactentry_t s_HunterLinearTable[] = -{ - { 150*150, 75 }, - { 350*350, 105 }, - { 1000*1000, 300 }, -}; - -static impactentry_t s_HunterAngularTable[] = -{ - { 100*100, 75 }, - { 200*200, 105 }, - { 300*300, 300 }, -}; - -impactdamagetable_t s_HunterImpactDamageTable = -{ - s_HunterLinearTable, - s_HunterAngularTable, - - ARRAYSIZE(s_HunterLinearTable), - ARRAYSIZE(s_HunterAngularTable), - - 24*24, // minimum linear speed squared - 360*360, // minimum angular speed squared (360 deg/s to cause spin/slice damage) - 5, // can't take damage from anything under 5kg - - 10, // anything less than 10kg is "small" - HUNTER_MIN_PHYSICS_DAMAGE, // never take more than 10 pts of damage from anything under 10kg - 36*36, // <10kg objects must go faster than 36 in/s to do damage - - VPHYSICS_LARGE_OBJECT_MASS, // large mass in kg - 4, // large mass scale (anything over 500kg does 4X as much energy to read from damage table) - 5, // large mass falling scale (emphasize falling/crushing damage over sideways impacts since the stress will kill you anyway) - 0.0f, // min vel -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -class CNPC_Hunter : public CAI_BaseActor -{ - DECLARE_CLASS( CNPC_Hunter, CAI_BaseActor ); - -public: - CNPC_Hunter(); - ~CNPC_Hunter(); - - //--------------------------------- - - void Precache(); - void Spawn(); - void PostNPCInit(); - void Activate(); - void UpdateOnRemove(); - void OnRestore(); - bool CreateBehaviors(); - void IdleSound(); - bool ShouldPlayIdleSound(); - bool CanBecomeRagdoll(); - Activity GetDeathActivity(); - void StopLoopingSounds(); - - const impactdamagetable_t &GetPhysicsImpactDamageTable(); - - Class_T Classify(); - Vector BodyTarget( const Vector &posSrc, bool bNoisy /*= true*/ ); - - int DrawDebugTextOverlays(); - void DrawDebugGeometryOverlays(); - - void UpdateEfficiency( bool bInPVS ); - - //--------------------------------- - - virtual Vector GetNodeViewOffset() { return BaseClass::GetDefaultEyeOffset(); } - - int GetSoundInterests(); - - bool IsInLargeOutdoorMap(); - - //--------------------------------- - // CAI_BaseActor - //--------------------------------- - const char *SelectRandomExpressionForState( NPC_STATE state ); - void PlayExpressionForState( NPC_STATE state ); - - //--------------------------------- - // CBaseAnimating - //--------------------------------- - float GetIdealAccel() const { return GetIdealSpeed(); } - - //--------------------------------- - // Behavior - //--------------------------------- - void NPCThink(); - void PrescheduleThink(); - void GatherConditions(); - void CollectSiegeTargets(); - void ManageSiegeTargets(); - void KillCurrentSiegeTarget(); - bool QueryHearSound( CSound *pSound ); - void OnSeeEntity( CBaseEntity *pEntity ); - void CheckFlinches() {} // Hunter handles on own - void BuildScheduleTestBits(); - NPC_STATE SelectIdealState(); - int SelectSchedule(); - int SelectCombatSchedule(); - int SelectSiegeSchedule(); - int TranslateSchedule( int scheduleType ); - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - Activity NPC_TranslateActivity( Activity baseAct ); - void OnChangeActivity( Activity eNewActivity ); - - void HandleAnimEvent( animevent_t *pEvent ); - bool HandleInteraction(int interactionType, void *data, CBaseCombatCharacter *pSourceEnt); - - void PlayerHasIlluminatedNPC( CBasePlayer *pPlayer, float flDot ); - - void AddEntityRelationship( CBaseEntity *pEntity, Disposition_t nDisposition, int nPriority ); - float EnemyDistTolerance() { return 100.0f; } - - bool ScheduledMoveToGoalEntity( int scheduleType, CBaseEntity *pGoalEntity, Activity movementActivity ); - - void OnChangeHintGroup( string_t oldGroup, string_t newGroup ); - - bool IsUsingSiegeTargets() { return m_iszSiegeTargetName != NULL_STRING; } - - //--------------------------------- - // Inputs - //--------------------------------- - void InputDodge( inputdata_t &inputdata ); - void InputFlankEnemy( inputdata_t &inputdata ); - void InputDisableShooting( inputdata_t &inputdata ); - void InputEnableShooting( inputdata_t &inputdata ); - void InputFollowStrider( inputdata_t &inputdata ); - void InputUseSiegeTargets( inputdata_t &inputdata ); - void InputEnableSquadShootDelay( inputdata_t &inputdata ); - void InputDisableSquadShootDelay( inputdata_t &inputdata ); - void InputEnableUnplantedShooting( inputdata_t &inputdata ); - void InputDisableUnplantedShooting( inputdata_t &inputdata ); - - //--------------------------------- - // Combat - //--------------------------------- - bool FVisible( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ); - bool IsValidEnemy( CBaseEntity *pEnemy ); - - Disposition_t IRelationType( CBaseEntity *pTarget ); - int IRelationPriority( CBaseEntity *pTarget ); - - void SetSquad( CAI_Squad *pSquad ); - - bool UpdateEnemyMemory( CBaseEntity *pEnemy, const Vector &position, CBaseEntity *pInformer = NULL ); - - int RangeAttack1Conditions( float flDot, float flDist ); - int RangeAttack2Conditions( float flDot, float flDist ); - - int MeleeAttack1Conditions ( float flDot, float flDist ); - int MeleeAttack1ConditionsVsEnemyInVehicle( CBaseCombatCharacter *pEnemy, float flDot ); - - int MeleeAttack2Conditions( float flDot, float flDist ); - - bool WeaponLOSCondition(const Vector &ownerPos, const Vector &targetPos, bool bSetConditions); - bool TestShootPosition(const Vector &vecShootPos, const Vector &targetPos ); - - Vector Weapon_ShootPosition(); - - CBaseEntity * MeleeAttack( float flDist, int iDamage, QAngle &qaViewPunch, Vector &vecVelocityPunch, int BloodOrigin ); - - void MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ); - void DoMuzzleFlash( int nAttachment ); - - bool CanShootThrough( const trace_t &tr, const Vector &vecTarget ); - - int CountRangedAttackers(); - void DelayRangedAttackers( float minDelay, float maxDelay, bool bForced = false ); - - //--------------------------------- - // Sounds & speech - //--------------------------------- - void AlertSound(); - void PainSound( const CTakeDamageInfo &info ); - void DeathSound( const CTakeDamageInfo &info ); - - //--------------------------------- - // Damage handling - //--------------------------------- - void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - bool IsHeavyDamage( const CTakeDamageInfo &info ); - int OnTakeDamage( const CTakeDamageInfo &info ); - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - void Event_Killed( const CTakeDamageInfo &info ); - - void StartBleeding(); - inline bool IsBleeding() { return m_bIsBleeding; } - void Explode(); - - void SetupGlobalModelData(); - - //--------------------------------- - // Navigation & Movement - //--------------------------------- - bool OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval ); - float MaxYawSpeed(); - bool IsJumpLegal(const Vector &startPos, const Vector &apex, const Vector &endPos) const; - float GetJumpGravity() const { return 3.0f; } - bool ShouldProbeCollideAgainstEntity( CBaseEntity *pEntity ); - void TaskFail( AI_TaskFailureCode_t code ); - void TaskFail( const char *pszGeneralFailText ) { TaskFail( MakeFailCode( pszGeneralFailText ) ); } - - CAI_BaseNPC * GetEntity() { return this; } - - //--------------------------------- - // Magnade - //--------------------------------- - void StriderBusterAttached( CBaseEntity *pAttached ); - void StriderBusterDetached( CBaseEntity *pAttached ); - -private: - - void ConsiderFlinching( const CTakeDamageInfo &info ); - - void TaskFindDodgeActivity(); - - void GatherChargeConditions(); - void GatherIndoorOutdoorConditions(); - - // Charge attack. - bool ShouldCharge( const Vector &startPos, const Vector &endPos, bool useTime, bool bCheckForCancel ); - void ChargeLookAhead(); - float ChargeSteer(); - bool EnemyIsRightInFrontOfMe( CBaseEntity **pEntity ); - void ChargeDamage( CBaseEntity *pTarget ); - bool HandleChargeImpact( Vector vecImpact, CBaseEntity *pEntity ); - - void BeginVolley( int nNum, float flStartTime ); - bool ShootFlechette( CBaseEntity *pTargetEntity, bool bSingleShot ); - bool ShouldSeekTarget( CBaseEntity *pTargetEntity, bool bStriderBuster ); - void GetShootDir( Vector &vecDir, const Vector &vecSrc, CBaseEntity *pTargetEntity, bool bStriderbuster, int nShotNum, bool bSingleShot ); - bool ClampShootDir( Vector &vecDir ); - - void SetAim( const Vector &aimDir, float flInterval ); - void RelaxAim( float flInterval ); - void UpdateAim(); - void UpdateEyes(); - void LockBothEyes( float flDuration ); - void UnlockBothEyes( float flDuration ); - - void TeslaThink(); - void BleedThink(); - void JostleVehicleThink(); - - void FollowStrider( const char *szStrider ); - void FollowStrider( CNPC_Strider * pStrider ); - int NumHuntersInMySquad(); - - bool CanPlantHere( const Vector &vecPos ); - - //--------------------------------- - // Foot handling - //--------------------------------- - Vector LeftFootHit( float eventtime ); - Vector RightFootHit( float eventtime ); - Vector BackFootHit( float eventtime ); - - void FootFX( const Vector &origin ); - - CBaseEntity *GetEnemyVehicle(); - bool IsCorporealEnemy( CBaseEntity *pEnemy ); - - void PhysicsDamageEffect( const Vector &vecPos, const Vector &vecDir ); - bool PlayerFlashlightOnMyEyes( CBasePlayer *pPlayer ); - - //----------------------------------------------------- - // Conditions, Schedules, Tasks - //----------------------------------------------------- - enum - { - SCHED_HUNTER_RANGE_ATTACK1 = BaseClass::NEXT_SCHEDULE, - SCHED_HUNTER_RANGE_ATTACK2, - SCHED_HUNTER_MELEE_ATTACK1, - SCHED_HUNTER_DODGE, - SCHED_HUNTER_CHASE_ENEMY, - SCHED_HUNTER_CHASE_ENEMY_MELEE, - SCHED_HUNTER_COMBAT_FACE, - SCHED_HUNTER_FLANK_ENEMY, - SCHED_HUNTER_CHANGE_POSITION, - SCHED_HUNTER_CHANGE_POSITION_FINISH, - SCHED_HUNTER_SIDESTEP, - SCHED_HUNTER_PATROL, - SCHED_HUNTER_FLINCH_STICKYBOMB, - SCHED_HUNTER_STAGGER, - SCHED_HUNTER_PATROL_RUN, - SCHED_HUNTER_TAKE_COVER_FROM_ENEMY, - SCHED_HUNTER_HIDE_UNDER_COVER, - SCHED_HUNTER_FAIL_IMMEDIATE, // instant fail without waiting - SCHED_HUNTER_CHARGE_ENEMY, - SCHED_HUNTER_FAIL_CHARGE_ENEMY, - SCHED_HUNTER_FOUND_ENEMY, - SCHED_HUNTER_FOUND_ENEMY_ACK, - SCHED_HUNTER_RANGE_ATTACK2_VS_STRIDERBUSTER, - SCHED_HUNTER_RANGE_ATTACK2_VS_STRIDERBUSTER_LATENT, - SCHED_HUNTER_GOTO_HINT, - SCHED_HUNTER_CLEAR_HINTNODE, - SCHED_HUNTER_FAIL_DODGE, - SCHED_HUNTER_SIEGE_STAND, - SCHED_HUNTER_CHANGE_POSITION_SIEGE, - - TASK_HUNTER_AIM = BaseClass::NEXT_TASK, - TASK_HUNTER_FIND_DODGE_POSITION, - TASK_HUNTER_DODGE, - TASK_HUNTER_PRE_RANGE_ATTACK2, - TASK_HUNTER_SHOOT_COMMIT, - TASK_HUNTER_BEGIN_FLANK, - TASK_HUNTER_ANNOUNCE_FLANK, - TASK_HUNTER_STAGGER, - TASK_HUNTER_CORNERED_TIMER, - TASK_HUNTER_FIND_SIDESTEP_POSITION, - TASK_HUNTER_CHARGE, - TASK_HUNTER_CHARGE_DELAY, - TASK_HUNTER_FINISH_RANGE_ATTACK, - TASK_HUNTER_WAIT_FOR_MOVEMENT_FACING_ENEMY, - - COND_HUNTER_SHOULD_PATROL = BaseClass::NEXT_CONDITION, - COND_HUNTER_FORCED_FLANK_ENEMY, - COND_HUNTER_FORCED_DODGE, - COND_HUNTER_CAN_CHARGE_ENEMY, - COND_HUNTER_HIT_BY_STICKYBOMB, - COND_HUNTER_STAGGERED, - COND_HUNTER_IS_INDOORS, - COND_HUNTER_SEE_STRIDERBUSTER, - COND_HUNTER_INCOMING_VEHICLE, - COND_HUNTER_NEW_HINTGROUP, - COND_HUNTER_CANT_PLANT, - COND_HUNTER_SQUADMATE_FOUND_ENEMY, - }; - - enum HunterEyeStates_t - { - HUNTER_EYE_STATE_TOP_LOCKED = 0, - HUNTER_EYE_STATE_BOTTOM_LOCKED, - HUNTER_EYE_STATE_BOTH_LOCKED, - HUNTER_EYE_STATE_BOTH_UNLOCKED, - }; - - string_t m_iszFollowTarget; // Name of the strider we should follow. - CSimpleStopwatch m_BeginFollowDelay; - - int m_nKillingDamageType; - HunterEyeStates_t m_eEyeState; - - float m_aimYaw; - float m_aimPitch; - - float m_flShootAllowInterruptTime; - float m_flNextChargeTime; // Prevents us from doing our threat display too often. - float m_flNextDamageTime; - float m_flNextSideStepTime; - - CSimpleSimTimer m_HeavyDamageDelay; - CSimpleSimTimer m_FlinchTimer; - CSimpleSimTimer m_EyeSwitchTimer; // Controls how often we switch which eye is focusing on our enemy. - - bool m_bTopMuzzle; // Used to alternate between top muzzle FX and bottom muzzle FX. - bool m_bEnableSquadShootDelay; - bool m_bIsBleeding; - - Activity m_eDodgeActivity; - CSimpleSimTimer m_RundownDelay; - CSimpleSimTimer m_IgnoreVehicleTimer; - - bool m_bDisableShooting; // Range attack disabled via an input. Used for scripting melee attacks. - - bool m_bFlashlightInEyes; // The player is shining the flashlight on our eyes. - float m_flPupilDilateTime; // When to dilate our pupils if the flashlight is no longer on our eyes. - - Vector m_vecEnemyLastSeen; - Vector m_vecLastCanPlantHerePos; - Vector m_vecStaggerDir; - - bool m_bPlanted; - bool m_bLastCanPlantHere; - bool m_bMissLeft; - bool m_bEnableUnplantedShooting; - - static float gm_flMinigunDistZ; - static Vector gm_vecLocalRelativePositionMinigun; - - static int gm_nTopGunAttachment; - static int gm_nBottomGunAttachment; - static int gm_nAimYawPoseParam; - static int gm_nAimPitchPoseParam; - static int gm_nBodyYawPoseParam; - static int gm_nBodyPitchPoseParam; - static int gm_nStaggerYawPoseParam; - static int gm_nHeadCenterAttachment; - static int gm_nHeadBottomAttachment; - static float gm_flHeadRadius; - - static int gm_nUnplantedNode; - static int gm_nPlantedNode; - - CAI_HunterEscortBehavior m_EscortBehavior; - - int m_nFlechettesQueued; - int m_nClampedShots; // The number of consecutive shots fired at an out-of-max yaw target. - - float m_flNextRangeAttack2Time; // Time when we can fire another volley of flechettes. - float m_flNextFlechetteTime; // Time to fire the next flechette in this volley. - - float m_flNextMeleeTime; - float m_flTeslaStopTime; - - string_t m_iszCurrentExpression; - - // buster fu - CUtlVector< EHANDLE > m_hAttachedBusters; // List of busters attached to us - float m_fCorneredTimer; ///< hunter was cornered when fleeing player; it won't flee again until this time - - CSimpleSimTimer m_CheckHintGroupTimer; - - DEFINE_CUSTOM_AI; - - DECLARE_DATADESC(); - - friend class CAI_HunterEscortBehavior; - friend class CHunterMaker; - - bool m_bInLargeOutdoorMap; - float m_flTimeSawEnemyAgain; - - // Sounds - //CSoundPatch *m_pGunFiringSound; - - CUtlVector m_pSiegeTargets; - string_t m_iszSiegeTargetName; - float m_flTimeNextSiegeTargetAttack; - EHANDLE m_hCurrentSiegeTarget; - - EHANDLE m_hHitByVehicle; -}; - - -LINK_ENTITY_TO_CLASS( npc_hunter, CNPC_Hunter ); - - -BEGIN_DATADESC( CNPC_Hunter ) - - DEFINE_KEYFIELD( m_iszFollowTarget, FIELD_STRING, "FollowTarget" ), - - DEFINE_FIELD( m_aimYaw, FIELD_FLOAT ), - DEFINE_FIELD( m_aimPitch, FIELD_FLOAT ), - - DEFINE_FIELD( m_flShootAllowInterruptTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextChargeTime, FIELD_TIME ), - //DEFINE_FIELD( m_flNextDamageTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextSideStepTime, FIELD_TIME ), - - DEFINE_EMBEDDED( m_HeavyDamageDelay ), - DEFINE_EMBEDDED( m_FlinchTimer ), - - DEFINE_FIELD( m_eEyeState, FIELD_INTEGER ), - - DEFINE_FIELD( m_bTopMuzzle, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bEnableSquadShootDelay, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bIsBleeding, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_bDisableShooting, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bFlashlightInEyes, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flPupilDilateTime, FIELD_TIME ), - - DEFINE_FIELD( m_vecEnemyLastSeen, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecLastCanPlantHerePos, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecStaggerDir, FIELD_VECTOR ), - - DEFINE_FIELD( m_bPlanted, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bLastCanPlantHere, FIELD_BOOLEAN ), - //DEFINE_FIELD( m_bMissLeft, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bEnableUnplantedShooting, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_nKillingDamageType, FIELD_INTEGER ), - DEFINE_FIELD( m_eDodgeActivity, FIELD_INTEGER ), - DEFINE_EMBEDDED( m_RundownDelay ), - DEFINE_EMBEDDED( m_IgnoreVehicleTimer ), - - DEFINE_FIELD( m_flNextMeleeTime, FIELD_TIME ), - DEFINE_FIELD( m_flTeslaStopTime, FIELD_TIME ), - - // (auto saved by AI) - //DEFINE_FIELD( m_EscortBehavior, FIELD_EMBEDDED ), - - DEFINE_FIELD( m_iszCurrentExpression, FIELD_STRING ), - - DEFINE_FIELD( m_fCorneredTimer, FIELD_TIME), - - DEFINE_EMBEDDED( m_CheckHintGroupTimer ), - - // (Recomputed in Precache()) - //DEFINE_FIELD( m_bInLargeOutdoorMap, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flTimeSawEnemyAgain, FIELD_TIME ), - - //DEFINE_SOUNDPATCH( m_pGunFiringSound ), - - //DEFINE_UTLVECTOR( m_pSiegeTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_iszSiegeTargetName, FIELD_STRING ), - DEFINE_FIELD( m_flTimeNextSiegeTargetAttack, FIELD_TIME ), - DEFINE_FIELD( m_hCurrentSiegeTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_hHitByVehicle, FIELD_EHANDLE ), - - DEFINE_EMBEDDED( m_BeginFollowDelay ), - DEFINE_EMBEDDED( m_EyeSwitchTimer ), - - DEFINE_FIELD( m_nFlechettesQueued, FIELD_INTEGER ), - DEFINE_FIELD( m_nClampedShots, FIELD_INTEGER ), - DEFINE_FIELD( m_flNextRangeAttack2Time, FIELD_TIME ), - DEFINE_FIELD( m_flNextFlechetteTime, FIELD_TIME ), - DEFINE_UTLVECTOR( m_hAttachedBusters, FIELD_EHANDLE ), - DEFINE_UTLVECTOR( m_pSiegeTargets, FIELD_EHANDLE ), - - // inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Dodge", InputDodge ), - DEFINE_INPUTFUNC( FIELD_VOID, "FlankEnemy", InputFlankEnemy ), - DEFINE_INPUTFUNC( FIELD_STRING, "DisableShooting", InputDisableShooting ), - DEFINE_INPUTFUNC( FIELD_STRING, "EnableShooting", InputEnableShooting ), - DEFINE_INPUTFUNC( FIELD_STRING, "FollowStrider", InputFollowStrider ), - DEFINE_INPUTFUNC( FIELD_STRING, "UseSiegeTargets", InputUseSiegeTargets ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableSquadShootDelay", InputEnableSquadShootDelay ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableSquadShootDelay", InputDisableSquadShootDelay ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableUnplantedShooting", InputEnableUnplantedShooting ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableUnplantedShooting", InputDisableUnplantedShooting ), - - // Function Pointers - DEFINE_THINKFUNC( TeslaThink ), - DEFINE_THINKFUNC( BleedThink ), - DEFINE_THINKFUNC( JostleVehicleThink ), - -END_DATADESC() - -//----------------------------------------------------------------------------- - -int CNPC_Hunter::gm_nUnplantedNode = 0; -int CNPC_Hunter::gm_nPlantedNode = 0; - -int CNPC_Hunter::gm_nAimYawPoseParam = -1; -int CNPC_Hunter::gm_nAimPitchPoseParam = -1; -int CNPC_Hunter::gm_nBodyYawPoseParam = -1; -int CNPC_Hunter::gm_nBodyPitchPoseParam = -1; -int CNPC_Hunter::gm_nStaggerYawPoseParam = -1; -int CNPC_Hunter::gm_nHeadCenterAttachment = -1; -int CNPC_Hunter::gm_nHeadBottomAttachment = -1; -float CNPC_Hunter::gm_flHeadRadius = 0; - -int CNPC_Hunter::gm_nTopGunAttachment = -1; -int CNPC_Hunter::gm_nBottomGunAttachment = -1; - -float CNPC_Hunter::gm_flMinigunDistZ; -Vector CNPC_Hunter::gm_vecLocalRelativePositionMinigun; - -//----------------------------------------------------------------------------- - -static CUtlVector g_Hunters; -float g_TimeLastDistributeFreeHunters = -1; -const float FREE_HUNTER_DISTRIBUTE_INTERVAL = 2; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CNPC_Hunter::CNPC_Hunter() -{ - g_Hunters.AddToTail( this ); - g_TimeLastDistributeFreeHunters = -1; - m_flTimeSawEnemyAgain = HUNTER_SEE_ENEMY_TIME_INVALID; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CNPC_Hunter::~CNPC_Hunter() -{ - g_Hunters.FindAndRemove( this ); - g_TimeLastDistributeFreeHunters = -1; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::Precache() -{ - PrecacheModel( "models/hunter.mdl" ); - PropBreakablePrecacheAll( MAKE_STRING("models/hunter.mdl") ); - - PrecacheScriptSound( "NPC_Hunter.Idle" ); - PrecacheScriptSound( "NPC_Hunter.Scan" ); - PrecacheScriptSound( "NPC_Hunter.Alert" ); - PrecacheScriptSound( "NPC_Hunter.Pain" ); - PrecacheScriptSound( "NPC_Hunter.PreCharge" ); - PrecacheScriptSound( "NPC_Hunter.Angry" ); - PrecacheScriptSound( "NPC_Hunter.Death" ); - PrecacheScriptSound( "NPC_Hunter.FireMinigun" ); - PrecacheScriptSound( "NPC_Hunter.Footstep" ); - PrecacheScriptSound( "NPC_Hunter.BackFootstep" ); - PrecacheScriptSound( "NPC_Hunter.FlechetteVolleyWarn" ); - PrecacheScriptSound( "NPC_Hunter.FlechetteShoot" ); - PrecacheScriptSound( "NPC_Hunter.FlechetteShootLoop" ); - PrecacheScriptSound( "NPC_Hunter.FlankAnnounce" ); - PrecacheScriptSound( "NPC_Hunter.MeleeAnnounce" ); - PrecacheScriptSound( "NPC_Hunter.MeleeHit" ); - PrecacheScriptSound( "NPC_Hunter.TackleAnnounce" ); - PrecacheScriptSound( "NPC_Hunter.TackleHit" ); - PrecacheScriptSound( "NPC_Hunter.ChargeHitEnemy" ); - PrecacheScriptSound( "NPC_Hunter.ChargeHitWorld" ); - PrecacheScriptSound( "NPC_Hunter.FoundEnemy" ); - PrecacheScriptSound( "NPC_Hunter.FoundEnemyAck" ); - PrecacheScriptSound( "NPC_Hunter.DefendStrider" ); - PrecacheScriptSound( "NPC_Hunter.HitByVehicle" ); - - PrecacheParticleSystem( "hunter_muzzle_flash" ); - PrecacheParticleSystem( "blood_impact_synth_01" ); - PrecacheParticleSystem( "blood_impact_synth_01_arc_parent" ); - PrecacheParticleSystem( "blood_spurt_synth_01" ); - PrecacheParticleSystem( "blood_drip_synth_01" ); - - PrecacheInstancedScene( "scenes/npc/hunter/hunter_scan.vcd" ); - PrecacheInstancedScene( "scenes/npc/hunter/hunter_eyeclose.vcd" ); - PrecacheInstancedScene( "scenes/npc/hunter/hunter_roar.vcd" ); - PrecacheInstancedScene( "scenes/npc/hunter/hunter_pain.vcd" ); - PrecacheInstancedScene( "scenes/npc/hunter/hunter_eyedarts_top.vcd" ); - PrecacheInstancedScene( "scenes/npc/hunter/hunter_eyedarts_bottom.vcd" ); - - PrecacheMaterial( "effects/water_highlight" ); - - UTIL_PrecacheOther( "hunter_flechette" ); - UTIL_PrecacheOther( "sparktrail" ); - - m_bInLargeOutdoorMap = false; - if( !Q_strnicmp( STRING(gpGlobals->mapname), "ep2_outland_12", 14) ) - { - m_bInLargeOutdoorMap = true; - } - - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::Spawn() -{ - Precache(); - - SetModel( "models/hunter.mdl" ); - BaseClass::Spawn(); - - //m_debugOverlays |= OVERLAY_NPC_ROUTE_BIT | OVERLAY_BBOX_BIT | OVERLAY_PIVOT_BIT; - - SetHullType( HULL_MEDIUM_TALL ); - SetHullSizeNormal(); - SetDefaultEyeOffset(); - - SetNavType( NAV_GROUND ); - m_flGroundSpeed = 500; - m_NPCState = NPC_STATE_NONE; - - SetBloodColor( DONT_BLEED ); - - m_iHealth = m_iMaxHealth = sk_hunter_health.GetInt(); - - m_flFieldOfView = HUNTER_FOV_DOT; - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - - SetupGlobalModelData(); - - CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_SQUAD | bits_CAP_ANIMATEDFACE ); - CapabilitiesAdd( bits_CAP_INNATE_RANGE_ATTACK1 | bits_CAP_INNATE_RANGE_ATTACK2 | bits_CAP_INNATE_MELEE_ATTACK1 ); - CapabilitiesAdd( bits_CAP_SKIP_NAV_GROUND_CHECK ); - - if ( !hunter_allow_dissolve.GetBool() ) - { - AddEFlags( EFL_NO_DISSOLVE ); - } - - if( hunter_allow_nav_jump.GetBool() ) - { - CapabilitiesAdd( bits_CAP_MOVE_JUMP ); - } - - NPCInit(); - - m_bEnableSquadShootDelay = true; - - m_flDistTooFar = hunter_flechette_max_range.GetFloat(); - - // Discard time must be greater than free knowledge duration. Make it double. - float freeKnowledge = hunter_free_knowledge.GetFloat(); - if ( freeKnowledge < GetEnemies()->GetEnemyDiscardTime() ) - { - GetEnemies()->SetEnemyDiscardTime( MAX( freeKnowledge + 0.1, AI_DEF_ENEMY_DISCARD_TIME ) ); - } - GetEnemies()->SetFreeKnowledgeDuration( freeKnowledge ); - - // Find out what strider we should follow, if any. - if ( m_iszFollowTarget != NULL_STRING ) - { - m_BeginFollowDelay.Set( .1 ); // Allow time for strider to spawn - } - - //if ( !m_pGunFiringSound ) - //{ - // CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - // CPASAttenuationFilter filter( this ); - // - // m_pGunFiringSound = controller.SoundCreate( filter, entindex(), "NPC_Hunter.FlechetteShootLoop" ); - // controller.Play( m_pGunFiringSound, 0.0, 100 ); - //} -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::UpdateEfficiency( bool bInPVS ) -{ - SetEfficiency( ( GetSleepState() != AISS_AWAKE ) ? AIE_DORMANT : AIE_NORMAL ); - SetMoveEfficiency( AIME_NORMAL ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Hunter::CreateBehaviors() -{ - AddBehavior( &m_EscortBehavior ); - - return BaseClass::CreateBehaviors(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::SetupGlobalModelData() -{ - if ( gm_nBodyYawPoseParam != -1 ) - return; - - gm_nAimYawPoseParam = LookupPoseParameter( "aim_yaw" ); - gm_nAimPitchPoseParam = LookupPoseParameter( "aim_pitch" ); - - gm_nBodyYawPoseParam = LookupPoseParameter( "body_yaw" ); - gm_nBodyPitchPoseParam = LookupPoseParameter( "body_pitch" ); - - gm_nTopGunAttachment = LookupAttachment( "top_eye" ); - gm_nBottomGunAttachment = LookupAttachment( "bottom_eye" ); - gm_nStaggerYawPoseParam = LookupAttachment( "stagger_yaw" ); - - gm_nHeadCenterAttachment = LookupAttachment( "head_center" ); - gm_nHeadBottomAttachment = LookupAttachment( "head_radius_measure" ); - - // Measure the radius of the head. - Vector vecHeadCenter; - Vector vecHeadBottom; - GetAttachment( gm_nHeadCenterAttachment, vecHeadCenter ); - GetAttachment( gm_nHeadBottomAttachment, vecHeadBottom ); - gm_flHeadRadius = ( vecHeadCenter - vecHeadBottom ).Length(); - - int nSequence = SelectWeightedSequence( ACT_HUNTER_RANGE_ATTACK2_UNPLANTED ); - gm_nUnplantedNode = GetEntryNode( nSequence ); - - nSequence = SelectWeightedSequence( ACT_RANGE_ATTACK2 ); - gm_nPlantedNode = GetEntryNode( nSequence ); - - CollisionProp()->SetSurroundingBoundsType( USE_HITBOXES ); -} - - -//----------------------------------------------------------------------------- -// Shuts down looping sounds when we are killed in combat or deleted. -//----------------------------------------------------------------------------- -void CNPC_Hunter::StopLoopingSounds() -{ - BaseClass::StopLoopingSounds(); - - //if ( m_pGunFiringSound ) - //{ - // CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - // controller.SoundDestroy( m_pGunFiringSound ); - // m_pGunFiringSound = NULL; - //} -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::OnRestore() -{ - BaseClass::OnRestore(); - SetupGlobalModelData(); - CreateVPhysics(); - - if ( IsBleeding() ) - { - StartBleeding(); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::IdleSound() -{ - if ( HasCondition( COND_LOST_ENEMY ) ) - { - EmitSound( "NPC_Hunter.Scan" ); - } - else - { - EmitSound( "NPC_Hunter.Idle" ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Hunter::ShouldPlayIdleSound() -{ - if ( random->RandomInt(0, 99) == 0 && !HasSpawnFlags( SF_NPC_GAG ) ) - return true; - - return false; -} - - -//----------------------------------------------------------------------------- -// Stay facing our enemy when close enough. -//----------------------------------------------------------------------------- -bool CNPC_Hunter::OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval ) -{ - if ( GetActivity() == ACT_TRANSITION ) - { - // No turning while in transitions. - return true; - } - - bool bSideStepping = IsCurSchedule( SCHED_HUNTER_SIDESTEP, false ); - - // FIXME: this will break scripted sequences that walk when they have an enemy - if ( GetEnemy() && - ( bSideStepping || - ( ( ( GetNavigator()->GetMovementActivity() == ACT_RUN ) || ( GetNavigator()->GetMovementActivity() == ACT_WALK ) ) && - !IsCurSchedule( SCHED_HUNTER_TAKE_COVER_FROM_ENEMY, false ) ) ) ) - { - Vector vecEnemyLKP = GetEnemyLKP(); - - // Face my enemy if we're close enough - if ( bSideStepping || UTIL_DistApprox( vecEnemyLKP, GetAbsOrigin() ) < HUNTER_FACE_ENEMY_DIST ) - { - AddFacingTarget( GetEnemy(), vecEnemyLKP, 1.0, 0.2 ); - } - } - - return BaseClass::OverrideMoveFacing( move, flInterval ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::PostNPCInit() -{ - BaseClass::PostNPCInit(); - - IPhysicsObject *pPhysObject = VPhysicsGetObject(); - Assert( pPhysObject ); - if ( pPhysObject ) - { - pPhysObject->SetMass( 600.0 ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::Activate() -{ - BaseClass::Activate(); - - s_iszStriderBusterClassname = AllocPooledString( "weapon_striderbuster" ); - s_iszStriderClassname = AllocPooledString( "npc_strider" ); - s_iszMagnadeClassname = AllocPooledString( "npc_grenade_magna" ); - s_iszPhysPropClassname = AllocPooledString( "prop_physics" ); - s_iszHuntersToRunOver = AllocPooledString( "hunters_to_run_over" ); - - // If no one has initialized the hunters to run over counter, just zero it out. - if ( !GlobalEntity_IsInTable( s_iszHuntersToRunOver ) ) - { - GlobalEntity_Add( s_iszHuntersToRunOver, gpGlobals->mapname, GLOBAL_ON ); - GlobalEntity_SetCounter( s_iszHuntersToRunOver, 0 ); - } - - CMissile::AddCustomDetonator( this, ( GetHullMaxs().AsVector2D() - GetHullMins().AsVector2D() ).Length() * 0.5, GetHullHeight() ); - - SetupGlobalModelData(); - - if ( gm_flMinigunDistZ == 0 ) - { - // Have to create a virgin hunter to ensure proper pose - CNPC_Hunter *pHunter = (CNPC_Hunter *)CreateEntityByName( "npc_hunter" ); - Assert(pHunter); - pHunter->Spawn(); - - pHunter->SetActivity( ACT_WALK ); - pHunter->InvalidateBoneCache(); - - // Currently just using the gun for the vertical component! - Vector defEyePos; - pHunter->GetAttachment( "minigunbase", defEyePos ); - gm_flMinigunDistZ = defEyePos.z - pHunter->GetAbsOrigin().z; - - Vector position; - pHunter->GetAttachment( gm_nTopGunAttachment, position ); - VectorITransform( position, pHunter->EntityToWorldTransform(), gm_vecLocalRelativePositionMinigun ); - UTIL_Remove( pHunter ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::UpdateOnRemove() -{ - CMissile::RemoveCustomDetonator( this ); - BaseClass::UpdateOnRemove(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Class_T CNPC_Hunter::Classify() -{ - return CLASS_COMBINE_HUNTER; -} - -//----------------------------------------------------------------------------- -// Compensate for the hunter's long legs by moving the bodytarget up to his head. -//----------------------------------------------------------------------------- -Vector CNPC_Hunter::BodyTarget( const Vector &posSrc, bool bNoisy /*= true*/ ) -{ - Vector vecResult; - QAngle vecAngle; - GetAttachment( gm_nHeadCenterAttachment, vecResult, vecAngle ); - - if ( bNoisy ) - { - float rand1 = random->RandomFloat( 0, gm_flHeadRadius ) + random->RandomFloat( 0, gm_flHeadRadius ); - return vecResult + RandomVector( -rand1, rand1 ); - } - - return vecResult; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Hunter::DrawDebugTextOverlays() -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - EntityText( text_offset, CFmtStr("%s", m_bPlanted ? "Planted" : "Unplanted" ), 0 ); - text_offset++; - - EntityText( text_offset, CFmtStr("Eye state: %d", m_eEyeState ), 0 ); - text_offset++; - - if( IsUsingSiegeTargets() ) - { - EntityText( text_offset, CFmtStr("Next Siege Attempt:%f", m_flTimeNextSiegeTargetAttack - gpGlobals->curtime ), 0 ); - text_offset++; - } - } - - return text_offset; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::LockBothEyes( float flDuration ) -{ - m_eEyeState = HUNTER_EYE_STATE_BOTH_LOCKED; - m_EyeSwitchTimer.Set( flDuration ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::UnlockBothEyes( float flDuration ) -{ - m_eEyeState = HUNTER_EYE_STATE_BOTH_UNLOCKED; - m_EyeSwitchTimer.Set( flDuration ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::OnChangeActivity( Activity eNewActivity ) -{ - m_EyeSwitchTimer.Force(); - - BaseClass::OnChangeActivity( eNewActivity ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::UpdateEyes() -{ - // If the eyes are controlled by a script, do nothing. - if ( GetState() == NPC_STATE_SCRIPT ) - return; - - if ( m_EyeSwitchTimer.Expired() ) - { - RemoveActorFromScriptedScenes( this, false ); - - if ( GetActivity() == ACT_IDLE ) - { - // Idles have eye motion baked in. - m_eEyeState = HUNTER_EYE_STATE_BOTH_LOCKED; - } - else if ( GetEnemy() == NULL ) - { - m_eEyeState = HUNTER_EYE_STATE_BOTH_UNLOCKED; - } - else if ( m_eEyeState == HUNTER_EYE_STATE_BOTH_LOCKED ) - { - if ( random->RandomInt( 0, 1 ) == 0 ) - { - m_eEyeState = HUNTER_EYE_STATE_TOP_LOCKED; - } - else - { - m_eEyeState = HUNTER_EYE_STATE_BOTTOM_LOCKED; - } - } - else if ( m_eEyeState == HUNTER_EYE_STATE_TOP_LOCKED ) - { - m_eEyeState = HUNTER_EYE_STATE_BOTTOM_LOCKED; - } - else if ( m_eEyeState == HUNTER_EYE_STATE_BOTTOM_LOCKED ) - { - m_eEyeState = HUNTER_EYE_STATE_TOP_LOCKED; - } - - if ( ( m_eEyeState == HUNTER_EYE_STATE_BOTTOM_LOCKED ) || ( m_eEyeState == HUNTER_EYE_STATE_BOTH_UNLOCKED ) ) - { - SetExpression( "scenes/npc/hunter/hunter_eyedarts_top.vcd" ); - } - - if ( ( m_eEyeState == HUNTER_EYE_STATE_TOP_LOCKED ) || ( m_eEyeState == HUNTER_EYE_STATE_BOTH_UNLOCKED ) ) - { - SetExpression( "scenes/npc/hunter/hunter_eyedarts_bottom.vcd" ); - } - - m_EyeSwitchTimer.Set( random->RandomFloat( 1.0f, 3.0f ) ); - } - - /*Vector vecEyePos; - Vector vecEyeDir; - - GetAttachment( gm_nTopGunAttachment, vecEyePos, &vecEyeDir ); - NDebugOverlay::Line( vecEyePos, vecEyePos + vecEyeDir * 36, 255, 0, 0, 0, 0.1 ); - - GetAttachment( gm_nBottomGunAttachment, vecEyePos, &vecEyeDir ); - NDebugOverlay::Line( vecEyePos, vecEyePos + vecEyeDir * 36, 255, 0, 0, 0, 0.1 );*/ -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::NPCThink() -{ - BaseClass::NPCThink(); - - // Update our planted/unplanted state. - m_bPlanted = ( GetEntryNode( GetSequence() ) == gm_nPlantedNode ); - - UpdateAim(); - UpdateEyes(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::PrescheduleThink() -{ - BaseClass::PrescheduleThink(); - - if ( m_BeginFollowDelay.Expired() ) - { - FollowStrider( STRING( m_iszFollowTarget ) ); - m_BeginFollowDelay.Stop(); - } - - m_EscortBehavior.CheckBreakEscort(); - - // If we're being blinded by the flashlight, see if we should stop - if ( m_bFlashlightInEyes ) - { - if ( m_flPupilDilateTime < gpGlobals->curtime ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); - if ( pPlayer && !pPlayer->IsIlluminatedByFlashlight( this, NULL ) || !PlayerFlashlightOnMyEyes( pPlayer ) ) - { - //Msg( "NOT SHINING FLASHLIGHT ON ME\n" ); - - // Remove the actor from the flashlight scene - RemoveActorFromScriptedScenes( this, true, false, "scenes/npc/hunter/hunter_eyeclose.vcd" ); - m_bFlashlightInEyes = false; - } - } - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::GatherChargeConditions() -{ - ClearCondition( COND_HUNTER_CAN_CHARGE_ENEMY ); - - if ( !hunter_charge.GetBool() ) - return; - - if ( !GetEnemy() ) - return; - - if ( GetHintGroup() != NULL_STRING ) - return; - - if ( !HasCondition( COND_SEE_ENEMY ) ) - return; - - if ( !hunter_charge_test.GetBool() && gpGlobals->curtime < m_flNextChargeTime ) - return; - - // No charging Alyx or Barney - if( GetEnemy()->Classify() == CLASS_PLAYER_ALLY_VITAL ) - return; - - if ( m_EscortBehavior.GetEscortTarget() && GetEnemy()->MyCombatCharacterPointer() && !GetEnemy()->MyCombatCharacterPointer()->FInViewCone( this ) ) - return; - - if ( ShouldCharge( GetAbsOrigin(), GetEnemy()->GetAbsOrigin(), true, false ) ) - { - SetCondition( COND_HUNTER_CAN_CHARGE_ENEMY ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::GatherConditions() -{ - GatherIndoorOutdoorConditions(); - GatherChargeConditions(); - - BaseClass::GatherConditions(); - - // Enemy LKP that doesn't get updated by the free knowledge code. - // Used for shooting at where our enemy was when we can't see them. - ClearCondition( COND_HUNTER_INCOMING_VEHICLE ); - if ( m_IgnoreVehicleTimer.Expired() && GetEnemy() && HasCondition( COND_SEE_ENEMY ) ) - { - CBaseEntity *pVehicle = GetEnemyVehicle(); - if ( ( pVehicle ) && ( GlobalEntity_GetCounter( s_iszHuntersToRunOver ) <= 0 ) ) - { - static float timeDrawnArrow; - - // Extrapolate the position of the vehicle and see if it's heading toward us. - float predictTime = hunter_dodge_warning.GetFloat(); - Vector2D vecFuturePos = pVehicle->GetAbsOrigin().AsVector2D() + pVehicle->GetSmoothedVelocity().AsVector2D() * predictTime; - if ( pVehicle->GetSmoothedVelocity().LengthSqr() > Square( 200 ) ) - { - float t = 0; - Vector2D vDirMovement = pVehicle->GetSmoothedVelocity().AsVector2D(); - if ( hunter_dodge_debug.GetBool() ) - { - NDebugOverlay::Line( pVehicle->GetAbsOrigin(), pVehicle->GetAbsOrigin() + pVehicle->GetSmoothedVelocity(), 255, 255, 255, true, .1 ); - } - vDirMovement.NormalizeInPlace(); - Vector2D vDirToHunter = GetAbsOrigin().AsVector2D() - pVehicle->GetAbsOrigin().AsVector2D(); - vDirToHunter.NormalizeInPlace(); - if ( DotProduct2D( vDirMovement, vDirToHunter ) > hunter_dodge_warning_cone.GetFloat() && - CalcDistanceSqrToLine2D( GetAbsOrigin().AsVector2D(), pVehicle->GetAbsOrigin().AsVector2D(), vecFuturePos, &t ) < Square( hunter_dodge_warning_width.GetFloat() * .5 ) && - t > 0.0 && t < 1.0 ) - { - if ( fabs( predictTime - hunter_dodge_warning.GetFloat() ) < .05 || random->RandomInt( 0, 3 ) ) - { - SetCondition( COND_HUNTER_INCOMING_VEHICLE ); - } - else - { - if ( hunter_dodge_debug. GetBool() ) - { - Msg( "Hunter %d failing dodge (ignore)\n", entindex() ); - } - } - - if ( hunter_dodge_debug. GetBool() ) - { - NDebugOverlay::Cross3D( EyePosition(), 100, 255, 255, 255, true, .1 ); - if ( timeDrawnArrow != gpGlobals->curtime ) - { - timeDrawnArrow = gpGlobals->curtime; - Vector vEndpoint( vecFuturePos.x, vecFuturePos.y, UTIL_GetLocalPlayer()->WorldSpaceCenter().z - 24 ); - NDebugOverlay::HorzArrow( UTIL_GetLocalPlayer()->WorldSpaceCenter() - Vector(0, 0, 24), vEndpoint, hunter_dodge_warning_width.GetFloat(), 255, 0, 0, 64, true, .1 ); - } - } - } - else if ( hunter_dodge_debug.GetBool() ) - { - if ( t <= 0 ) - { - NDebugOverlay::Cross3D( EyePosition(), 100, 0, 0, 255, true, .1 ); - } - else - { - NDebugOverlay::Cross3D( EyePosition(), 100, 0, 255, 255, true, .1 ); - } - } - } - else if ( hunter_dodge_debug.GetBool() ) - { - NDebugOverlay::Cross3D( EyePosition(), 100, 0, 255, 0, true, .1 ); - } - if ( hunter_dodge_debug. GetBool() ) - { - if ( timeDrawnArrow != gpGlobals->curtime ) - { - timeDrawnArrow = gpGlobals->curtime; - Vector vEndpoint( vecFuturePos.x, vecFuturePos.y, UTIL_GetLocalPlayer()->WorldSpaceCenter().z - 24 ); - NDebugOverlay::HorzArrow( UTIL_GetLocalPlayer()->WorldSpaceCenter() - Vector(0, 0, 24), vEndpoint, hunter_dodge_warning_width.GetFloat(), 127, 127, 127, 64, true, .1 ); - } - } - - } - - m_vecEnemyLastSeen = GetEnemy()->GetAbsOrigin(); - } - - if( !HasCondition(COND_ENEMY_OCCLUDED) ) - { - // m_flTimeSawEnemyAgain always tells us what time I first saw this - // enemy again after some period of not seeing them. This is used to - // compute how long the enemy has been visible to me THIS TIME. - // Every time I lose sight of the enemy this time is set invalid until - // I see the enemy again and record that time. - if( m_flTimeSawEnemyAgain == HUNTER_SEE_ENEMY_TIME_INVALID ) - { - m_flTimeSawEnemyAgain = gpGlobals->curtime; - } - } - else - { - m_flTimeSawEnemyAgain = HUNTER_SEE_ENEMY_TIME_INVALID; - } - - ManageSiegeTargets(); -} - -//----------------------------------------------------------------------------- -// Search all entities in the map -//----------------------------------------------------------------------------- -void CNPC_Hunter::CollectSiegeTargets() -{ - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, m_iszSiegeTargetName ); - - while( pTarget != NULL ) - { - if( pTarget->Classify() == CLASS_BULLSEYE ) - { - m_pSiegeTargets.AddToTail( pTarget ); - } - - pTarget = gEntList.FindEntityByName( pTarget, m_iszSiegeTargetName ); - }; - - if( m_pSiegeTargets.Count() < 1 ) - { - m_iszSiegeTargetName = NULL_STRING; // And stop trying! - } -} - -//----------------------------------------------------------------------------- -// For use when Hunters are outside and the player is inside a structure -// Create a temporary bullseye in a location that makes it seem like -// I am aware of the location of a player I cannot see. (Then fire at -// at this bullseye, thus laying 'siege' to the part of the building he -// is in.) The locations are copied from suitable info_target entities. -// (these should be placed in exterior windows and doorways so that -// the Hunter fires into the building through these apertures) -//----------------------------------------------------------------------------- -void CNPC_Hunter::ManageSiegeTargets() -{ - if( gpGlobals->curtime < m_flTimeNextSiegeTargetAttack ) - return; - - if( m_pSiegeTargets.Count() == 0 ) - { - // If my list of siege targets is empty, go and cache all of them now - // so that I don't have to search the world every time. - CollectSiegeTargets(); - - if( m_pSiegeTargets.Count() == 0 ) - return; - } - - m_flTimeNextSiegeTargetAttack = gpGlobals->curtime + (hunter_siege_frequency.GetFloat() * RandomFloat( 0.8f, 1.2f) ); - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - - // Start by assuming we are not going to create a siege target - bool bCreateSiegeTarget = false; - if( GetEnemy() == NULL ) - { - // If I have no enemy at all, give it a try. - bCreateSiegeTarget = true; - } - - if( bCreateSiegeTarget ) - { - // We've decided that the situation calls for a siege target. So, we dig through all of my siege targets and - // take the closest one to the player that the player can see! (Obey they bullseye's FOV) - float flClosestDistSqr = Square( 1200.0f ); // Only use siege targets within 100 feet of player - CBaseEntity *pSiegeTargetLocation = NULL; - int iTraces = 0; - for( int i = 0 ; i < m_pSiegeTargets.Count() ; i++ ) - { - CBaseEntity *pCandidate = m_pSiegeTargets[i]; - if ( pCandidate == NULL ) - continue; - - float flDistSqr = pCandidate->GetAbsOrigin().DistToSqr(pPlayer->GetAbsOrigin()); - - if( flDistSqr < flClosestDistSqr ) - { - // CollectSiegeTargets() guarantees my list is populated only with bullseye entities. - CNPC_Bullseye *pBullseye = dynamic_cast(pCandidate); - if( !pBullseye->FInViewCone(this) ) - continue; - - if( pPlayer->FVisible(pCandidate) ) - { - iTraces++;// Only counting these as a loose perf measurement - flClosestDistSqr = flDistSqr; - pSiegeTargetLocation = pCandidate; - } - } - } - - if( pSiegeTargetLocation != NULL ) - { - // Ditch any leftover siege target. - KillCurrentSiegeTarget(); - - // Create a bullseye that will live for 20 seconds. If we can't attack it within 20 seconds, it's probably - // out of reach anyone, so have it clean itself up after that long. - CBaseEntity *pSiegeTarget = CreateCustomTarget( pSiegeTargetLocation->GetAbsOrigin(), 20.0f ); - pSiegeTarget->SetName( MAKE_STRING("siegetarget") ); - - m_hCurrentSiegeTarget.Set( pSiegeTarget ); - - AddEntityRelationship( pSiegeTarget, D_HT, 1 ); - GetEnemies()->UpdateMemory( GetNavigator()->GetNetwork(), pSiegeTarget, pSiegeTarget->GetAbsOrigin(), 0.0f, true ); - AI_EnemyInfo_t *pMemory = GetEnemies()->Find( pSiegeTarget ); - - if( pMemory ) - { - // Pretend we've known about this target longer than we really have so that our AI doesn't waste time running ALERT schedules. - pMemory->timeFirstSeen = gpGlobals->curtime - 5.0f; - pMemory->timeLastSeen = gpGlobals->curtime - 1.0f; - } - } - } -} - -//----------------------------------------------------------------------------- -// Destroy the bullseye that we're using as a temporary target -//----------------------------------------------------------------------------- -void CNPC_Hunter::KillCurrentSiegeTarget() -{ - if ( m_hCurrentSiegeTarget ) - { - GetEnemies()->ClearMemory( m_hCurrentSiegeTarget ); - - UTIL_Remove( m_hCurrentSiegeTarget ); - m_hCurrentSiegeTarget.Set( NULL ); - } -} - -//----------------------------------------------------------------------------- -// Return true if this NPC can hear the specified sound -//----------------------------------------------------------------------------- -bool CNPC_Hunter::QueryHearSound( CSound *pSound ) -{ - if ( pSound->SoundContext() & SOUND_CONTEXT_EXCLUDE_COMBINE ) - return false; - - if ( pSound->SoundContext() & SOUND_CONTEXT_PLAYER_VEHICLE ) - return false; - - return BaseClass::QueryHearSound( pSound ); -} - - -//----------------------------------------------------------------------------- -// This is a fairly bogus heuristic right now, but it works on 06a and 12 (sjb) -// -// Better options: Trace infinitely and check the material we hit for sky -// Put some leaf info in the BSP -// Use volumes in the levels? (yucky for designers) -//----------------------------------------------------------------------------- -// TODO: use this or nuke it! -void CNPC_Hunter::GatherIndoorOutdoorConditions() -{ - // Check indoor/outdoor before calling base class, since base class calls our - // RangeAttackConditions() functions, and we want those functions to know - // whether we're indoors or out. - trace_t tr; - - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, 40.0f * 12.0f ), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - if( tr.fraction < 1.0f ) - { - SetCondition( COND_HUNTER_IS_INDOORS ); - } - else - { - ClearCondition( COND_HUNTER_IS_INDOORS ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::BuildScheduleTestBits() -{ - BaseClass::BuildScheduleTestBits(); - - if ( m_lifeState != LIFE_ALIVE ) - { - return; - } - - // Our range attack is uninterruptable for the first few seconds. - if ( IsCurSchedule( SCHED_HUNTER_RANGE_ATTACK2, false ) && ( gpGlobals->curtime < m_flShootAllowInterruptTime ) ) - { - ClearCustomInterruptConditions(); - SetCustomInterruptCondition( COND_HEAVY_DAMAGE ); - } - else if ( IsCurSchedule( SCHED_HUNTER_RANGE_ATTACK2, false ) && ( GetActivity() == ACT_TRANSITION ) ) - { - // Don't stop unplanting just because we can range attack again. - ClearCustomInterruptCondition( COND_CAN_RANGE_ATTACK1 ); - ClearCustomInterruptCondition( COND_CAN_RANGE_ATTACK2 ); - } - else if ( !IsInLargeOutdoorMap() && IsCurSchedule( SCHED_HUNTER_FLANK_ENEMY, false ) && GetEnemy() != NULL ) - { - if( HasCondition(COND_CAN_RANGE_ATTACK2) && m_flTimeSawEnemyAgain != HUNTER_SEE_ENEMY_TIME_INVALID ) - { - if( (gpGlobals->curtime - m_flTimeSawEnemyAgain) >= 2.0f ) - { - // When we're running flank behavior, wait a moment AFTER being able to see the enemy before - // breaking my schedule to range attack. This helps assure that the hunter gets well inside - // the room before stopping to attack. Otherwise the Hunter may stop immediately in the doorway - // and stop the progress of any hunters behind it. - SetCustomInterruptCondition( COND_CAN_RANGE_ATTACK2 ); - } - } - } - - // If our enemy is anything but a striderbuster, drop everything if we see one. - if ( !IsStriderBuster( GetEnemy() ) ) - { - SetCustomInterruptCondition( COND_HUNTER_SEE_STRIDERBUSTER ); - } - - // If we're not too busy, allow ourselves to ACK found enemy signals. - if ( !GetEnemy() ) - { - SetCustomInterruptCondition( COND_HUNTER_SQUADMATE_FOUND_ENEMY ); - } - - // Interrupt everything if we need to dodge. - if ( !IsCurSchedule( SCHED_HUNTER_DODGE, false ) && - !IsCurSchedule( SCHED_HUNTER_STAGGER, false ) && - !IsCurSchedule( SCHED_ALERT_FACE_BESTSOUND, false ) ) - { - SetCustomInterruptCondition( COND_HUNTER_INCOMING_VEHICLE ); - SetCustomInterruptCondition( COND_HEAR_PHYSICS_DANGER ); - SetCustomInterruptCondition( COND_HUNTER_FORCED_DODGE ); - } - - // Always interrupt on a flank command. - SetCustomInterruptCondition( COND_HUNTER_FORCED_FLANK_ENEMY ); - - // Always interrupt if staggered. - SetCustomInterruptCondition( COND_HUNTER_STAGGERED ); - - // Always interrupt if hit by a sticky bomb. - SetCustomInterruptCondition( COND_HUNTER_HIT_BY_STICKYBOMB ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -static bool IsMovablePhysicsObject( CBaseEntity *pEntity ) -{ - return pEntity && pEntity->GetMoveType() == MOVETYPE_VPHYSICS && pEntity->VPhysicsGetObject() && pEntity->VPhysicsGetObject()->IsMoveable(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -NPC_STATE CNPC_Hunter::SelectIdealState() -{ - switch ( m_NPCState ) - { - case NPC_STATE_COMBAT: - { - if ( GetEnemy() == NULL ) - { - if ( !HasCondition( COND_ENEMY_DEAD ) && !hunter_disable_patrol.GetBool() ) - { - // Lost track of my enemy. Patrol. - SetCondition( COND_HUNTER_SHOULD_PATROL ); - } - - return NPC_STATE_ALERT; - } - else if ( HasCondition( COND_ENEMY_DEAD ) ) - { - // dvs: TODO: announce enemy kills? - //AnnounceEnemyKill(GetEnemy()); - } - } - - default: - { - return BaseClass::SelectIdealState(); - } - } - - return GetIdealState(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Hunter::ShouldCharge( const Vector &startPos, const Vector &endPos, bool useTime, bool bCheckForCancel ) -{ - // Must have a target - if ( !GetEnemy() ) - return false; - - // Don't check the distance once we start charging - if ( !bCheckForCancel && !hunter_charge_test.GetBool() ) - { - float distance = ( startPos.AsVector2D() - endPos.AsVector2D() ).LengthSqr(); - - // Must be within our tolerance range - if ( ( distance < Square(HUNTER_CHARGE_MIN) ) || ( distance > Square(HUNTER_CHARGE_MAX) ) ) - return false; - } - - // FIXME: We'd like to exclude small physics objects from this check! - - // We only need to hit the endpos with the edge of our bounding box - Vector vecDir = endPos - startPos; - VectorNormalize( vecDir ); - float flWidth = WorldAlignSize().x * 0.5; - Vector vecTargetPos = endPos - (vecDir * flWidth); - - // See if we can directly move there - AIMoveTrace_t moveTrace; - GetMoveProbe()->MoveLimit( NAV_GROUND, startPos, vecTargetPos, MASK_NPCSOLID_BRUSHONLY, GetEnemy(), &moveTrace ); - - // Draw the probe - if ( g_debug_hunter_charge.GetInt() == 1 ) - { - Vector enemyDir = (vecTargetPos - startPos); - float enemyDist = VectorNormalize( enemyDir ); - - NDebugOverlay::BoxDirection( startPos, GetHullMins(), GetHullMaxs() + Vector(enemyDist,0,0), enemyDir, 0, 255, 0, 8, 1.0f ); - } - - // If we're not blocked, charge - if ( IsMoveBlocked( moveTrace ) ) - { - // Don't allow it if it's too close to us - if ( UTIL_DistApprox( WorldSpaceCenter(), moveTrace.vEndPosition ) < HUNTER_CHARGE_MIN ) - return false; - - // Allow some special cases to not block us - if ( moveTrace.pObstruction != NULL ) - { - // If we've hit the world, see if it's a cliff - if ( moveTrace.pObstruction == GetContainingEntity( INDEXENT(0) ) ) - { - // Can't be too far above/below the target - if ( fabs( moveTrace.vEndPosition.z - vecTargetPos.z ) > StepHeight() ) - return false; - - // Allow it if we got pretty close - if ( UTIL_DistApprox( moveTrace.vEndPosition, vecTargetPos ) < 64 ) - return true; - } - - // Hit things that will take damage - if ( moveTrace.pObstruction->m_takedamage != DAMAGE_NO ) - return true; - - // Hit things that will move - if ( moveTrace.pObstruction->GetMoveType() == MOVETYPE_VPHYSICS ) - return true; - } - - return false; - } - - float zDelta = endPos.z - moveTrace.vEndPosition.z; - if ( fabsf(zDelta) > GetHullHeight() * 0.7) - { - return false; - } - - return true; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Hunter::HandleInteraction(int interactionType, void *data, CBaseCombatCharacter *pSourceEnt) -{ - if ( ( pSourceEnt != this ) && ( interactionType == g_interactionHunterFoundEnemy ) ) - { - SetCondition( COND_HUNTER_SQUADMATE_FOUND_ENEMY ); - return true; - } - - return BaseClass::HandleInteraction( interactionType, data, pSourceEnt ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Hunter::SelectCombatSchedule() -{ - // If we're here with no enemy, patrol and hope we find one. - CBaseEntity *pEnemy = GetEnemy(); - if ( pEnemy == NULL ) - { - if ( !hunter_disable_patrol.GetBool() ) - return SCHED_HUNTER_PATROL_RUN; - else - return SCHED_ALERT_STAND; - } - - if ( hunter_flechette_test.GetBool() ) - { - if ( HasCondition( COND_CAN_RANGE_ATTACK2 ) ) - { - return SCHED_HUNTER_RANGE_ATTACK2; - } - return SCHED_COMBAT_FACE; - } - - bool bStriderBuster = IsStriderBuster( pEnemy ); - if ( bStriderBuster ) - { - if ( gpGlobals->curtime - CAI_HunterEscortBehavior::gm_flLastDefendSound > 10.0 ) - { - EmitSound( "NPC_Hunter.DefendStrider" ); - CAI_HunterEscortBehavior::gm_flLastDefendSound = gpGlobals->curtime; - } - - if ( HasCondition( COND_CAN_RANGE_ATTACK2 ) || HasCondition( COND_NOT_FACING_ATTACK ) ) - { - return SCHED_HUNTER_RANGE_ATTACK2; - } - return SCHED_ESTABLISH_LINE_OF_FIRE; - } - - // Certain behaviors, like flanking and melee attacks, only make sense on visible, - // corporeal enemies (NOT bullseyes). - bool bIsCorporealEnemy = IsCorporealEnemy( pEnemy ); - - // Take a quick swipe at our enemy if able to do so. - if ( bIsCorporealEnemy && HasCondition( COND_CAN_MELEE_ATTACK1 ) ) - { - return SCHED_HUNTER_MELEE_ATTACK1; - } - - // React to newly acquired enemies. - if ( bIsCorporealEnemy && HasCondition( COND_NEW_ENEMY ) ) - { - AI_EnemyInfo_t *pEnemyInfo = GetEnemies()->Find( pEnemy ); - - if ( GetSquad() && pEnemyInfo && ( pEnemyInfo->timeFirstSeen == pEnemyInfo->timeAtFirstHand ) ) - { - GetSquad()->BroadcastInteraction( g_interactionHunterFoundEnemy, NULL, this ); - - // First contact for my squad. - return SCHED_HUNTER_FOUND_ENEMY; - } - } - - if ( HasCondition( COND_HUNTER_SQUADMATE_FOUND_ENEMY ) ) - { - // A squadmate found an enemy. Respond to their call. - return SCHED_HUNTER_FOUND_ENEMY_ACK; - } - - // Fire a flechette volley. Ignore squad slots if we're attacking a striderbuster. - // See if there is an opportunity to charge. - if ( !bStriderBuster && bIsCorporealEnemy && HasCondition( COND_HUNTER_CAN_CHARGE_ENEMY ) ) - { - if ( hunter_charge_test.GetBool() || random->RandomInt( 1, 100 ) < hunter_charge_pct.GetInt() ) - { - if ( hunter_charge_test.GetBool() || OccupyStrategySlot( SQUAD_SLOT_HUNTER_CHARGE ) ) - { - return SCHED_HUNTER_CHARGE_ENEMY; - } - } - } - - if ( HasCondition( COND_CAN_RANGE_ATTACK2 ) ) - { - if ( bStriderBuster || CountRangedAttackers() < hunter_flechette_max_concurrent_volleys.GetInt() ) - { - DelayRangedAttackers( hunter_flechette_volley_start_min_delay.GetFloat(), hunter_flechette_volley_start_max_delay.GetFloat(), true ); - return SCHED_HUNTER_RANGE_ATTACK2; - } - } - - if ( pEnemy->GetGroundEntity() == this ) - { - return SCHED_HUNTER_MELEE_ATTACK1; - } - - if ( HasCondition( COND_TOO_CLOSE_TO_ATTACK ) ) - { - return SCHED_MOVE_AWAY_FROM_ENEMY; - } - - // Sidestep every so often if my enemy is nearby and facing me. -/* - if ( gpGlobals->curtime > m_flNextSideStepTime ) - { - if ( HasCondition( COND_ENEMY_FACING_ME ) && ( UTIL_DistApprox( GetEnemy()->GetAbsOrigin(), GetAbsOrigin() ) < HUNTER_FACE_ENEMY_DIST ) ) - { - m_flNextSideStepTime = gpGlobals->curtime + random->RandomFloat( 1.0f, 3.0f ); - return SCHED_HUNTER_SIDESTEP; - } - } -*/ - if ( HasCondition( COND_HEAVY_DAMAGE ) && ( gpGlobals->curtime > m_flNextSideStepTime ) ) - { - m_flNextSideStepTime = gpGlobals->curtime + random->RandomFloat( 1.0f, 3.0f ); - return SCHED_HUNTER_SIDESTEP; - } - - if ( !bStriderBuster && bIsCorporealEnemy ) - { - if ( HasCondition( COND_HUNTER_CAN_CHARGE_ENEMY ) ) - { - if ( OccupyStrategySlot( SQUAD_SLOT_HUNTER_CHARGE ) ) - { - return SCHED_HUNTER_CHARGE_ENEMY; - } -/* - else - { - return SCHED_HUNTER_SIDESTEP; - } -*/ - } - - // Try to be a flanker. - if ( ( NumHuntersInMySquad() > 1 ) && OccupyStrategySlotRange( SQUAD_SLOT_HUNTER_FLANK_FIRST, SQUAD_SLOT_HUNTER_FLANK_LAST ) ) - { - return SCHED_HUNTER_FLANK_ENEMY; - } - } - - // Can't see my enemy. - if ( HasCondition( COND_ENEMY_OCCLUDED ) || HasCondition( COND_ENEMY_TOO_FAR ) || HasCondition( COND_TOO_FAR_TO_ATTACK ) || HasCondition( COND_NOT_FACING_ATTACK ) ) - { - return SCHED_HUNTER_CHASE_ENEMY; - } - - if ( HasCondition( COND_HUNTER_CANT_PLANT ) ) - { - return SCHED_ESTABLISH_LINE_OF_FIRE; - } - - //if ( HasCondition( COND_ENEMY_OCCLUDED ) && IsCurSchedule( SCHED_RANGE_ATTACK1, false ) ) - //{ - // return SCHED_HUNTER_COMBAT_FACE; - //} - - return SCHED_HUNTER_CHANGE_POSITION; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Hunter::SelectSiegeSchedule() -{ - bool bHasEnemy = (GetEnemy() != NULL); - - if( bHasEnemy ) - { - // We have an enemy, so we should be making every effort to attack it. - if( !HasCondition(COND_SEE_ENEMY) || !HasCondition(COND_CAN_RANGE_ATTACK2) ) - return SCHED_ESTABLISH_LINE_OF_FIRE; - - if( HasCondition(COND_CAN_RANGE_ATTACK2) ) - return SCHED_HUNTER_RANGE_ATTACK2; - - return SCHED_HUNTER_SIEGE_STAND; - } - else - { - // Otherwise we are loitering in siege mode. Break line of sight with the player - // if they expose our position. - if( HasCondition( COND_SEE_PLAYER ) ) - return SCHED_HUNTER_CHANGE_POSITION_SIEGE; - } - - return SCHED_HUNTER_SIEGE_STAND; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Hunter::SelectSchedule() -{ - if ( hunter_stand_still.GetBool() ) - { - m_bPlanted = false; - return SCHED_IDLE_STAND; - } - - if ( HasCondition( COND_HUNTER_FORCED_DODGE ) ) - return SCHED_HUNTER_DODGE; - - if ( HasCondition( COND_HUNTER_NEW_HINTGROUP ) || ( GetHintGroup() != NULL_STRING && m_CheckHintGroupTimer.Expired() ) ) - { - CAI_Hint *pHint; - CHintCriteria criteria; - criteria.SetGroup( GetHintGroup() ); - criteria.SetFlag( bits_HINT_NODE_NEAREST ); - - if ( HasCondition( COND_HUNTER_NEW_HINTGROUP ) ) - { - ClearCondition( COND_HUNTER_NEW_HINTGROUP ); - if ( GetEnemy() ) - { - pHint = CAI_HintManager::FindHint( NULL, GetEnemy()->GetAbsOrigin(), criteria ); - } - else - { - pHint = CAI_HintManager::FindHint( GetAbsOrigin(), criteria ); - } - - if ( pHint ) - { - pHint->Lock( this ); - } - } - else - { - pHint = CAI_HintManager::FindHint( GetAbsOrigin(), criteria ); - if ( pHint ) - { - if ( (pHint->GetAbsOrigin() - GetAbsOrigin()).Length2DSqr() < Square( 20*12 ) ) - { - m_CheckHintGroupTimer.Set( 5 ); - pHint = NULL; - } - else - { - m_CheckHintGroupTimer.Set( 15 ); - } - } - } - - if ( pHint ) - { - SetHintNode( pHint ); - return SCHED_HUNTER_GOTO_HINT; - } - } - - if ( HasCondition( COND_HUNTER_INCOMING_VEHICLE ) ) - { - if ( m_RundownDelay.Expired() ) - { - int iRundownCounter = 0; - if ( GetSquad() ) - { - GetSquad()->GetSquadData( HUNTER_RUNDOWN_SQUADDATA, &iRundownCounter ); - } - - if ( iRundownCounter % 2 == 0 ) - { - for ( int i = 0; i < g_Hunters.Count(); i++ ) - { - if ( g_Hunters[i] != this ) - { - g_Hunters[i]->m_RundownDelay.Set( 3 ); - g_Hunters[i]->m_IgnoreVehicleTimer.Force(); - } - } - m_IgnoreVehicleTimer.Set( hunter_dodge_warning.GetFloat() * 4 ); - if ( hunter_dodge_debug.GetBool() ) - { - Msg( "Hunter %d rundown\n", entindex() ); - } - - if ( HasCondition( COND_SEE_ENEMY ) ) - { - if ( m_bPlanted && HasCondition( COND_CAN_RANGE_ATTACK2 ) ) - { - return SCHED_HUNTER_RANGE_ATTACK2; - } - else if ( random->RandomInt( 0, 1 ) ) - { - return SCHED_HUNTER_CHARGE_ENEMY; - } - else - { - return SCHED_MOVE_AWAY; - } - } - else - { - SetTarget( UTIL_GetLocalPlayer() ); - return SCHED_TARGET_FACE; - } - } - else - { - if ( hunter_dodge_debug.GetBool() ) - { - Msg( "Hunter %d safe from rundown\n", entindex() ); - } - for ( int i = 0; i < g_Hunters.Count(); i++ ) - { - g_Hunters[i]->m_RundownDelay.Set( 4 ); - g_Hunters[i]->m_IgnoreVehicleTimer.Force(); - } - if ( GetSquad() ) - { - GetSquad()->SetSquadData( HUNTER_RUNDOWN_SQUADDATA, iRundownCounter + 1 ); - } - } - } - - if ( HasCondition( COND_SEE_ENEMY ) ) - { - if ( hunter_dodge_debug.GetBool() ) - { - Msg( "Hunter %d try dodge\n", entindex() ); - } - return SCHED_HUNTER_DODGE; - } - else - { - SetTarget( UTIL_GetLocalPlayer() ); - return SCHED_TARGET_FACE; - } - - CSound *pBestSound = GetBestSound( SOUND_PHYSICS_DANGER ); - if ( pBestSound && ( pBestSound->SoundContext() & SOUND_CONTEXT_PLAYER_VEHICLE ) ) - { - return SCHED_ALERT_FACE_BESTSOUND; - } - } - - if ( HasCondition( COND_HUNTER_FORCED_FLANK_ENEMY ) ) - { - return SCHED_HUNTER_FLANK_ENEMY; - } - - if ( HasCondition( COND_HUNTER_STAGGERED ) /*|| HasCondition( COND_HUNTER_HIT_BY_STICKYBOMB )*/ ) - { - return SCHED_HUNTER_STAGGER; - } - - // Now that we're past all of the forced reactions to things, if we're running the siege - // behavior, go pick an appropriate siege schedule UNLESS we have an enemy. If we have - // an enemy, we should focus on attacking that enemy. - if( IsUsingSiegeTargets() ) - { - return SelectSiegeSchedule(); - } - - // back away if there's a magnade glued to my head. - if ( hunter_retreat_striderbusters.GetBool() /*&& GetEnemy() && ( GetEnemy()->IsPlayer() )*/ - && (m_hAttachedBusters.Count() > 0) - && m_fCorneredTimer < gpGlobals->curtime) - { - return SCHED_HUNTER_TAKE_COVER_FROM_ENEMY; - } - - if ( !BehaviorSelectSchedule() ) - { - switch ( GetState() ) - { - case NPC_STATE_IDLE: - { - return SCHED_HUNTER_PATROL; - } - - case NPC_STATE_ALERT: - { - if ( HasCondition( COND_HUNTER_SHOULD_PATROL ) ) - return SCHED_HUNTER_PATROL; - - break; - } - - case NPC_STATE_COMBAT: - { - return SelectCombatSchedule(); - } - - default: - break; - } - } - - return BaseClass::SelectSchedule(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Hunter::TranslateSchedule( int scheduleType ) -{ - switch ( scheduleType ) - { - case SCHED_RANGE_ATTACK1: - { - return SCHED_HUNTER_RANGE_ATTACK1; - } - - case SCHED_RANGE_ATTACK2: - case SCHED_HUNTER_RANGE_ATTACK2: - { - if ( scheduleType == SCHED_RANGE_ATTACK2 ) - { - Msg( "HUNTER IGNORING SQUAD SLOTS\n" ); - } - - if ( IsStriderBuster( GetEnemy() ) ) - { - // Attack as FAST as possible. The point is to shoot down the buster. - return SCHED_HUNTER_RANGE_ATTACK2_VS_STRIDERBUSTER; - } - - return SCHED_HUNTER_RANGE_ATTACK2; - } - - case SCHED_MELEE_ATTACK1: - { - return SCHED_HUNTER_MELEE_ATTACK1; - } - - case SCHED_ESTABLISH_LINE_OF_FIRE_FALLBACK: - { - return SCHED_HUNTER_CHANGE_POSITION; - } - - case SCHED_ALERT_STAND: - { - if ( !hunter_disable_patrol.GetBool() ) - return SCHED_HUNTER_PATROL_RUN; - break; - } - - case SCHED_COMBAT_FACE: - { - return SCHED_HUNTER_COMBAT_FACE; - } - - case SCHED_HUNTER_PATROL: - { - if ( hunter_disable_patrol.GetBool() ) - { - return SCHED_IDLE_STAND; - } - break; - } - } - - return BaseClass::TranslateSchedule( scheduleType ); -} - - -//----------------------------------------------------------------------------- -// catch blockage while escaping magnade -//----------------------------------------------------------------------------- -void CNPC_Hunter::TaskFail( AI_TaskFailureCode_t code ) -{ - if ( IsCurSchedule( SCHED_HUNTER_TAKE_COVER_FROM_ENEMY, false ) && ( code == FAIL_NO_ROUTE_BLOCKED ) ) - { - // cornered! - if ( m_fCorneredTimer < gpGlobals->curtime ) - { - m_fCorneredTimer = gpGlobals->curtime + 6.0f; - } - } - - BaseClass::TaskFail( code ); -} - - -//----------------------------------------------------------------------------- -// The player is speeding toward us in a vehicle! Find a good activity for dodging. -//----------------------------------------------------------------------------- -void CNPC_Hunter::TaskFindDodgeActivity() -{ - if ( GetEnemy() == NULL ) - { - TaskFail( "No enemy to dodge" ); - return; - } - - Vector vecUp; - Vector vecRight; - GetVectors( NULL, &vecRight, &vecUp ); - - // TODO: find most perpendicular 8-way dodge when we get the anims - Vector vecEnemyDir = GetEnemy()->GetAbsOrigin() - GetAbsOrigin(); - //Vector vecDir = CrossProduct( vecEnemyDir, vecUp ); - VectorNormalize( vecEnemyDir ); - if ( fabs( DotProduct( vecEnemyDir, vecRight ) ) > 0.7 ) - { - TaskFail( "Can't dodge, enemy approaching perpendicularly" ); - return; - } - - // Check left or right randomly first. - bool bDodgeLeft = false; - CBaseEntity *pVehicle = GetEnemyVehicle(); - if ( pVehicle ) - { - Ray_t enemyRay; - Ray_t perpendicularRay; - enemyRay.Init( pVehicle->GetAbsOrigin(), pVehicle->GetAbsOrigin() + pVehicle->GetSmoothedVelocity() ); - Vector vPerpendicularPt = vecEnemyDir; - vPerpendicularPt.y = -vPerpendicularPt.y; - perpendicularRay.Init( GetAbsOrigin(), GetAbsOrigin() + vPerpendicularPt ); - - enemyRay.m_Start.z = enemyRay.m_Delta.z = enemyRay.m_StartOffset.z; - perpendicularRay.m_Start.z = perpendicularRay.m_Delta.z = perpendicularRay.m_StartOffset.z; - - float t, s; - - IntersectRayWithRay( perpendicularRay, enemyRay, t, s ); - - if ( t > 0 ) - { - bDodgeLeft = true; - } - } - else if ( random->RandomInt( 0, 1 ) == 0 ) - { - bDodgeLeft = true; - } - - bool bFoundDir = false; - int nTries = 0; - - while ( !bFoundDir && ( nTries < 2 ) ) - { - // Pick a dodge activity to try. - if ( bDodgeLeft ) - { - m_eDodgeActivity = ACT_HUNTER_DODGEL; - } - else - { - m_eDodgeActivity = ACT_HUNTER_DODGER; - } - - // See where the dodge will put us. - Vector vecLocalDelta; - int nSeq = SelectWeightedSequence( m_eDodgeActivity ); - GetSequenceLinearMotion( nSeq, &vecLocalDelta ); - - // Transform the sequence delta into local space. - matrix3x4_t fRotateMatrix; - AngleMatrix( GetLocalAngles(), fRotateMatrix ); - Vector vecDelta; - VectorRotate( vecLocalDelta, fRotateMatrix, vecDelta ); - - // Trace a bit high so this works better on uneven terrain. - Vector testHullMins = GetHullMins(); - testHullMins.z += ( StepHeight() * 2 ); - - // See if all is clear in that direction. - trace_t tr; - HunterTraceHull_SkipPhysics( GetAbsOrigin(), GetAbsOrigin() + vecDelta, testHullMins, GetHullMaxs(), MASK_NPCSOLID, this, GetCollisionGroup(), &tr, VPhysicsGetObject()->GetMass() * 0.5f ); - - // TODO: dodge anyway if we'll make it a certain percentage of the way through the dodge? - if ( tr.fraction == 1.0f ) - { - //NDebugOverlay::SweptBox( GetAbsOrigin(), GetAbsOrigin() + vecDelta, testHullMins, GetHullMaxs(), QAngle( 0, 0, 0 ), 0, 255, 0, 128, 5 ); - bFoundDir = true; - TaskComplete(); - } - else - { - //NDebugOverlay::SweptBox( GetAbsOrigin(), GetAbsOrigin() + vecDelta, testHullMins, GetHullMaxs(), QAngle( 0, 0, 0 ), 255, 0, 0, 128, 5 ); - nTries++; - bDodgeLeft = !bDodgeLeft; - } - } - - if ( nTries < 2 ) - { - TaskComplete(); - } - else - { - TaskFail( "Couldn't find dodge position\n" ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::StartTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_HUNTER_FINISH_RANGE_ATTACK: - { - if( GetEnemy() != NULL && GetEnemy()->Classify() == CLASS_PLAYER_ALLY_VITAL ) - { - // Just finished shooting at Alyx! So forget her for a little while and get back on the player - // !!!LATER - make sure there's someone else in enemy memory to go bother. - GetEnemies()->SetTimeValidEnemy( GetEnemy(), gpGlobals->curtime + 10.0f ); - } - - if( m_hCurrentSiegeTarget ) - { - // We probably just fired at our siege target, so dump it. - KillCurrentSiegeTarget(); - } - - TaskComplete(); - } - - case TASK_HUNTER_WAIT_FOR_MOVEMENT_FACING_ENEMY: - { - ChainStartTask( TASK_WAIT_FOR_MOVEMENT, pTask->flTaskData ); - break; - } - - case TASK_HUNTER_BEGIN_FLANK: - { - if ( IsInSquad() && GetSquad()->NumMembers() > 1 ) - { - // Flank relative to the other shooter in our squad. - // If there's no other shooter, just flank relative to any squad member. - AISquadIter_t iter; - CAI_BaseNPC *pNPC = GetSquad()->GetFirstMember( &iter ); - while ( pNPC == this ) - { - pNPC = GetSquad()->GetNextMember( &iter ); - } - - m_vSavePosition = pNPC->GetAbsOrigin(); - } - else - { - // Flank relative to our current position. - m_vSavePosition = GetAbsOrigin(); - } - - TaskComplete(); - break; - } - - case TASK_HUNTER_ANNOUNCE_FLANK: - { - EmitSound( "NPC_Hunter.FlankAnnounce" ); - TaskComplete(); - break; - } - - case TASK_HUNTER_DODGE: - { - if ( hunter_dodge_debug. GetBool() ) - { - Msg( "Hunter %d dodging\n", entindex() ); - } - SetIdealActivity( m_eDodgeActivity ); - break; - } - - // Guarantee a certain delay between volleys. If we aren't already planted, - // the plant transition animation will take care of that. - case TASK_HUNTER_PRE_RANGE_ATTACK2: - { - if ( !m_bPlanted || ( GetEnemy() && IsStriderBuster( GetEnemy() ) ) ) - { - TaskComplete(); - } - else - { - SetIdealActivity( ACT_HUNTER_ANGRY ); - } - break; - } - - case TASK_HUNTER_SHOOT_COMMIT: - { - // We're committing to shooting. Don't allow interrupts until after we've shot a bit (see TASK_RANGE_ATTACK1). - m_flShootAllowInterruptTime = gpGlobals->curtime + 100.0f; - TaskComplete(); - break; - } - - case TASK_RANGE_ATTACK2: - { - if ( GetEnemy() ) - { - bool bIsBuster = IsStriderBuster( GetEnemy() ); - if ( bIsBuster ) - { - AddFacingTarget( GetEnemy(), GetEnemy()->GetAbsOrigin() + GetEnemy()->GetSmoothedVelocity() * .5, 1.0, 0.8 ); - } - - // Start the firing sound. - //CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - //controller.SoundChangeVolume( m_pGunFiringSound, 1.0, hunter_first_flechette_delay.GetFloat() ); - - SetIdealActivity( ACT_RANGE_ATTACK2 ); - - // Decide how many shots to fire. - int nShots = hunter_flechette_volley_size.GetInt(); - if ( g_pGameRules->IsSkillLevel( SKILL_EASY ) ) - { - nShots--; - } - - // Decide when to fire the first shot. - float initialDelay = hunter_first_flechette_delay.GetFloat(); - if ( bIsBuster ) - { - initialDelay = 0; //*= 0.5; - } - - BeginVolley( nShots, gpGlobals->curtime + initialDelay ); - - // In case we need to miss on purpose, pick a direction now. - m_bMissLeft = false; - if ( random->RandomInt( 0, 1 ) == 0 ) - { - m_bMissLeft = true; - } - - LockBothEyes( initialDelay + ( nShots * hunter_flechette_delay.GetFloat() ) ); - } - else - { - TaskFail( FAIL_NO_ENEMY ); - } - - break; - } - - case TASK_HUNTER_STAGGER: - { - // Stagger in the direction the impact force would push us. - VMatrix worldToLocalRotation = EntityToWorldTransform(); - Vector vecLocalStaggerDir = worldToLocalRotation.InverseTR().ApplyRotation( m_vecStaggerDir ); - - float flStaggerYaw = VecToYaw( vecLocalStaggerDir ); - SetPoseParameter( gm_nStaggerYawPoseParam, flStaggerYaw ); - - // Go straight there! - SetActivity( ACT_RESET ); - SetActivity( ( Activity )ACT_HUNTER_STAGGER ); - break; - } - - case TASK_MELEE_ATTACK1: - { - SetLastAttackTime( gpGlobals->curtime ); - - if ( GetEnemy() && GetEnemy()->IsPlayer() ) - { - ResetIdealActivity( ( Activity )ACT_HUNTER_MELEE_ATTACK1_VS_PLAYER ); - } - else - { - ResetIdealActivity( ACT_MELEE_ATTACK1 ); - } - - break; - } - - case TASK_HUNTER_CORNERED_TIMER: - { - m_fCorneredTimer = gpGlobals->curtime + pTask->flTaskData; - - break; - } - - case TASK_HUNTER_FIND_SIDESTEP_POSITION: - { - if ( GetEnemy() == NULL ) - { - TaskFail( "No enemy to sidestep" ); - } - else - { - Vector vecUp; - GetVectors( NULL, NULL, &vecUp ); - - Vector vecEnemyDir = GetEnemy()->GetAbsOrigin() - GetAbsOrigin(); - Vector vecDir = CrossProduct( vecEnemyDir, vecUp ); - VectorNormalize( vecDir ); - - // Sidestep left or right randomly. - if ( random->RandomInt( 0, 1 ) == 0 ) - { - vecDir *= -1; - } - - // Start high and then trace down so that it works on uneven terrain. - Vector vecPos = GetAbsOrigin() + Vector( 0, 0, 64 ) + random->RandomFloat( 120, 200 ) * vecDir; - - // Try to find the ground at the sidestep position. - trace_t tr; - UTIL_TraceLine( vecPos, vecPos + Vector( 0, 0, -128 ), MASK_NPCSOLID, NULL, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction < 1.0f ) - { - //NDebugOverlay::Line( vecPos, tr.endpos, 0, 255, 0, true, 10 ); - - m_vSavePosition = tr.endpos; - - TaskComplete(); - } - else - { - TaskFail( "Couldn't find sidestep position\n" ); - } - } - - break; - } - - case TASK_HUNTER_FIND_DODGE_POSITION: - { - TaskFindDodgeActivity(); - break; - } - - case TASK_HUNTER_CHARGE: - { - SetIdealActivity( ( Activity )ACT_HUNTER_CHARGE_START ); - break; - } - - case TASK_HUNTER_CHARGE_DELAY: - { - m_flNextChargeTime = gpGlobals->curtime + pTask->flTaskData; - TaskComplete(); - break; - } - - case TASK_DIE: - { - GetNavigator()->StopMoving(); - ResetActivity(); - SetIdealActivity( GetDeathActivity() ); - m_lifeState = LIFE_DYING; - - break; - } - - //case TASK_HUNTER_END_FLANK: - //{ - // - //} - - default: - { - BaseClass::StartTask( pTask ); - break; - } - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::RunTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_HUNTER_PRE_RANGE_ATTACK2: - { - if ( IsActivityFinished() ) - { - TaskComplete(); - } - break; - } - - case TASK_RANGE_ATTACK2: - { - if( !hunter_hate_thrown_striderbusters.GetBool() && GetEnemy() != NULL && IsStriderBuster( GetEnemy() ) ) - { - if( !IsValidEnemy(GetEnemy()) ) - { - TaskFail("No longer hate this StriderBuster"); - } - } - - bool bIsBuster = IsStriderBuster( GetEnemy() ); - if ( bIsBuster ) - { - Vector vFuturePosition = GetEnemy()->GetAbsOrigin() + GetEnemy()->GetSmoothedVelocity() * .3; - AddFacingTarget( GetEnemy(), vFuturePosition, 1.0, 0.8 ); - - Vector2D vToFuturePositon = ( vFuturePosition.AsVector2D() - GetAbsOrigin().AsVector2D() ); - vToFuturePositon.NormalizeInPlace(); - Vector2D facingDir = BodyDirection2D().AsVector2D(); - - float flDot = DotProduct2D( vToFuturePositon, facingDir ); - - if ( flDot < .4 ) - { - GetMotor()->SetIdealYawToTarget( vFuturePosition ); - GetMotor()->UpdateYaw(); - break; - } - } - - if ( gpGlobals->curtime >= m_flNextFlechetteTime ) - { - // Must have an enemy and a shot queued up. - bool bDone = false; - if ( GetEnemy() != NULL && m_nFlechettesQueued > 0 ) - { - if ( ShootFlechette( GetEnemy(), false ) ) - { - m_nClampedShots++; - } - else - { - m_nClampedShots = 0; - } - - m_nFlechettesQueued--; - - // If we fired three or more clamped shots in a row, call it quits so we don't look dumb. - if ( ( m_nClampedShots >= 3 ) || ( m_nFlechettesQueued == 0 ) ) - { - bDone = true; - } - else - { - // More shooting to do. Schedule our next flechette. - m_flNextFlechetteTime = gpGlobals->curtime + hunter_flechette_delay.GetFloat(); - } - } - else - { - bDone = true; - } - - if ( bDone ) - { - // Stop the firing sound. - //CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - //controller.SoundChangeVolume( m_pGunFiringSound, 0.0f, 0.1f ); - - DelayRangedAttackers( hunter_flechette_volley_end_min_delay.GetFloat(), hunter_flechette_volley_end_max_delay.GetFloat(), true ); - TaskComplete(); - } - } - - break; - } - - case TASK_GET_PATH_TO_ENEMY_LOS: - { - ChainRunTask( TASK_GET_PATH_TO_ENEMY_LKP_LOS, pTask->flTaskData ); - break; - } - - case TASK_HUNTER_DODGE: - { - AutoMovement(); - - if ( IsActivityFinished() ) - { - TaskComplete(); - } - break; - } - - case TASK_HUNTER_CORNERED_TIMER: - { - TaskComplete(); - break; - } - - case TASK_HUNTER_STAGGER: - { - if ( IsActivityFinished() ) - { - TaskComplete(); - } - break; - } - - case TASK_HUNTER_CHARGE: - { - Activity eActivity = GetActivity(); - - // See if we're trying to stop after hitting/missing our target - if ( eActivity == ACT_HUNTER_CHARGE_STOP || eActivity == ACT_HUNTER_CHARGE_CRASH ) - { - if ( IsActivityFinished() ) - { - m_flNextChargeTime = gpGlobals->curtime + hunter_charge_min_delay.GetFloat() + random->RandomFloat( 0, 2.5 ) + random->RandomFloat( 0, 2.5 ); - float delayMultiplier = ( g_pGameRules->IsSkillLevel( SKILL_EASY ) ) ? 1.5 : 1.0; - float groupDelay = gpGlobals->curtime + ( 2.0 + random->RandomFloat( 0, 2 ) ) * delayMultiplier; - for ( int i = 0; i < g_Hunters.Count(); i++ ) - { - if ( g_Hunters[i] != this && g_Hunters[i]->m_flNextChargeTime < groupDelay ) - { - g_Hunters[i]->m_flNextChargeTime = groupDelay; - } - } - TaskComplete(); - return; - } - - // Still in the process of slowing down. Run movement until it's done. - AutoMovement(); - return; - } - - // Check for manual transition - if ( ( eActivity == ACT_HUNTER_CHARGE_START ) && ( IsActivityFinished() ) ) - { - SetIdealActivity( ACT_HUNTER_CHARGE_RUN ); - } - - // See if we're still running - if ( eActivity == ACT_HUNTER_CHARGE_RUN || eActivity == ACT_HUNTER_CHARGE_START ) - { - if ( HasCondition( COND_NEW_ENEMY ) || HasCondition( COND_LOST_ENEMY ) || HasCondition( COND_ENEMY_DEAD ) ) - { - SetIdealActivity( ACT_HUNTER_CHARGE_STOP ); - return; - } - else - { - if ( GetEnemy() != NULL ) - { - Vector goalDir = ( GetEnemy()->GetAbsOrigin() - GetAbsOrigin() ); - VectorNormalize( goalDir ); - - if ( DotProduct( BodyDirection2D(), goalDir ) < 0.25f ) - { - SetIdealActivity( ACT_HUNTER_CHARGE_STOP ); - } - } - } - } - - // Steer towards our target - float idealYaw; - if ( GetEnemy() == NULL ) - { - idealYaw = GetMotor()->GetIdealYaw(); - } - else - { - idealYaw = CalcIdealYaw( GetEnemy()->GetAbsOrigin() ); - } - - // Add in our steering offset - idealYaw += ChargeSteer(); - - // Turn to face - GetMotor()->SetIdealYawAndUpdate( idealYaw ); - - // See if we're going to run into anything soon - ChargeLookAhead(); - - // Let our animations simply move us forward. Keep the result - // of the movement so we know whether we've hit our target. - AIMoveTrace_t moveTrace; - if ( AutoMovement( GetEnemy(), &moveTrace ) == false ) - { - // Only stop if we hit the world - if ( HandleChargeImpact( moveTrace.vEndPosition, moveTrace.pObstruction ) ) - { - // If we're starting up, this is an error - if ( eActivity == ACT_HUNTER_CHARGE_START ) - { - TaskFail( "Unable to make initial movement of charge\n" ); - return; - } - - // Crash unless we're trying to stop already - if ( eActivity != ACT_HUNTER_CHARGE_STOP ) - { - if ( moveTrace.fStatus == AIMR_BLOCKED_WORLD && moveTrace.vHitNormal == vec3_origin ) - { - SetIdealActivity( ACT_HUNTER_CHARGE_STOP ); - } - else - { - // Shake the screen - if ( moveTrace.fStatus != AIMR_BLOCKED_NPC ) - { - EmitSound( "NPC_Hunter.ChargeHitWorld" ); - UTIL_ScreenShake( GetAbsOrigin(), 16.0f, 4.0f, 1.0f, 400.0f, SHAKE_START ); - } - SetIdealActivity( ACT_HUNTER_CHARGE_CRASH ); - } - } - } - else if ( moveTrace.pObstruction ) - { - // If we hit another hunter, stop - if ( moveTrace.pObstruction->Classify() == CLASS_COMBINE_HUNTER ) - { - // Crash unless we're trying to stop already - if ( eActivity != ACT_HUNTER_CHARGE_STOP ) - { - SetIdealActivity( ACT_HUNTER_CHARGE_STOP ); - } - } - // If we hit an antlion, don't stop, but kill it - // We never have hunters and antlions together, but you never know. - else if (moveTrace.pObstruction->Classify() == CLASS_ANTLION ) - { - if ( FClassnameIs( moveTrace.pObstruction, "npc_antlionguard" ) ) - { - // Crash unless we're trying to stop already - if ( eActivity != ACT_HUNTER_CHARGE_STOP ) - { - SetIdealActivity( ACT_HUNTER_CHARGE_STOP ); - } - } - else - { - Hunter_ApplyChargeDamage( this, moveTrace.pObstruction, moveTrace.pObstruction->GetHealth() ); - } - } - } - } - - break; - } - - case TASK_HUNTER_WAIT_FOR_MOVEMENT_FACING_ENEMY: - { - if ( GetEnemy() ) - { - Vector vecEnemyLKP = GetEnemyLKP(); - AddFacingTarget( GetEnemy(), vecEnemyLKP, 1.0, 0.8 ); - } - ChainRunTask( TASK_WAIT_FOR_MOVEMENT, pTask->flTaskData ); - break; - } - - default: - { - BaseClass::RunTask( pTask ); - break; - } - } -} - - -//----------------------------------------------------------------------------- -// Return true if our charge target is right in front of the hunter. -//----------------------------------------------------------------------------- -bool CNPC_Hunter::EnemyIsRightInFrontOfMe( CBaseEntity **pEntity ) -{ - if ( !GetEnemy() ) - return false; - - if ( (GetEnemy()->WorldSpaceCenter() - WorldSpaceCenter()).LengthSqr() < (156*156) ) - { - Vector vecLOS = ( GetEnemy()->GetAbsOrigin() - GetAbsOrigin() ); - vecLOS.z = 0; - VectorNormalize( vecLOS ); - Vector vBodyDir = BodyDirection2D(); - if ( DotProduct( vecLOS, vBodyDir ) > 0.8 ) - { - // He's in front of me, and close. Make sure he's not behind a wall. - trace_t tr; - UTIL_TraceHull( WorldSpaceCenter(), GetEnemy()->WorldSpaceCenter(), GetHullMins() * 0.5, GetHullMaxs() * 0.5, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - if ( tr.m_pEnt == GetEnemy() ) - { - *pEntity = tr.m_pEnt; - return true; - } - } - } - - return false; -} - - -//----------------------------------------------------------------------------- -// While charging, look ahead and see if we're going to run into anything. -// If we are, start the gesture so it looks like we're anticipating the hit. -//----------------------------------------------------------------------------- -void CNPC_Hunter::ChargeLookAhead( void ) -{ -#if 0 - trace_t tr; - Vector vecForward; - GetVectors( &vecForward, NULL, NULL ); - Vector vecTestPos = GetAbsOrigin() + ( vecForward * m_flGroundSpeed * 0.75 ); - Vector testHullMins = GetHullMins(); - testHullMins.z += (StepHeight() * 2); - HunterTraceHull_SkipPhysics( GetAbsOrigin(), vecTestPos, testHullMins, GetHullMaxs(), MASK_SHOT_HULL, this, COLLISION_GROUP_NONE, &tr, VPhysicsGetObject()->GetMass() * 0.5 ); - - //NDebugOverlay::Box( tr.startpos, testHullMins, GetHullMaxs(), 0, 255, 0, true, 0.1f ); - //NDebugOverlay::Box( vecTestPos, testHullMins, GetHullMaxs(), 255, 0, 0, true, 0.1f ); - - if ( tr.fraction != 1.0 ) - { - // dvs: TODO: - // Start playing the hit animation - //AddGesture( ACT_HUNTER_CHARGE_ANTICIPATION ); - } -#endif -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -float CNPC_Hunter::ChargeSteer() -{ - trace_t tr; - Vector testPos, steer, forward, right; - QAngle angles; - const float testLength = m_flGroundSpeed * 0.15f; - - //Get our facing - GetVectors( &forward, &right, NULL ); - - steer = forward; - - const float faceYaw = UTIL_VecToYaw( forward ); - - //Offset right - VectorAngles( forward, angles ); - angles[YAW] += 45.0f; - AngleVectors( angles, &forward ); - - // Probe out - testPos = GetAbsOrigin() + ( forward * testLength ); - - // Offset by step height - Vector testHullMins = GetHullMins(); - testHullMins.z += (StepHeight() * 2); - - // Probe - HunterTraceHull_SkipPhysics( GetAbsOrigin(), testPos, testHullMins, GetHullMaxs(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr, VPhysicsGetObject()->GetMass() * 0.5f ); - - // Debug info - if ( g_debug_hunter_charge.GetInt() == 1 ) - { - if ( tr.fraction == 1.0f ) - { - NDebugOverlay::BoxDirection( GetAbsOrigin(), testHullMins, GetHullMaxs() + Vector(testLength,0,0), forward, 0, 255, 0, 8, 0.1f ); - } - else - { - NDebugOverlay::BoxDirection( GetAbsOrigin(), testHullMins, GetHullMaxs() + Vector(testLength,0,0), forward, 255, 0, 0, 8, 0.1f ); - } - } - - // Add in this component - steer += ( right * 0.5f ) * ( 1.0f - tr.fraction ); - - // Offset left - angles[YAW] -= 90.0f; - AngleVectors( angles, &forward ); - - // Probe out - testPos = GetAbsOrigin() + ( forward * testLength ); - HunterTraceHull_SkipPhysics( GetAbsOrigin(), testPos, testHullMins, GetHullMaxs(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr, VPhysicsGetObject()->GetMass() * 0.5f ); - - // Debug - if ( g_debug_hunter_charge.GetInt() == 1 ) - { - if ( tr.fraction == 1.0f ) - { - NDebugOverlay::BoxDirection( GetAbsOrigin(), testHullMins, GetHullMaxs() + Vector(testLength,0,0), forward, 0, 255, 0, 8, 0.1f ); - } - else - { - NDebugOverlay::BoxDirection( GetAbsOrigin(), testHullMins, GetHullMaxs() + Vector(testLength,0,0), forward, 255, 0, 0, 8, 0.1f ); - } - } - - // Add in this component - steer -= ( right * 0.5f ) * ( 1.0f - tr.fraction ); - - // Debug - if ( g_debug_hunter_charge.GetInt() == 1 ) - { - NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + ( steer * 512.0f ), 255, 255, 0, true, 0.1f ); - NDebugOverlay::Cross3D( GetAbsOrigin() + ( steer * 512.0f ), Vector(2,2,2), -Vector(2,2,2), 255, 255, 0, true, 0.1f ); - - NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + ( BodyDirection3D() * 256.0f ), 255, 0, 255, true, 0.1f ); - NDebugOverlay::Cross3D( GetAbsOrigin() + ( BodyDirection3D() * 256.0f ), Vector(2,2,2), -Vector(2,2,2), 255, 0, 255, true, 0.1f ); - } - - return UTIL_AngleDiff( UTIL_VecToYaw( steer ), faceYaw ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::ChargeDamage( CBaseEntity *pTarget ) -{ - if ( pTarget == NULL ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( pTarget ); - - if ( pPlayer != NULL ) - { - //Kick the player angles - pPlayer->ViewPunch( QAngle( 20, 20, -30 ) ); - - Vector dir = pPlayer->WorldSpaceCenter() - WorldSpaceCenter(); - VectorNormalize( dir ); - dir.z = 0.0f; - - Vector vecNewVelocity = dir * 250.0f; - vecNewVelocity[2] += 128.0f; - pPlayer->SetAbsVelocity( vecNewVelocity ); - - color32 red = {128,0,0,128}; - UTIL_ScreenFade( pPlayer, red, 1.0f, 0.1f, FFADE_IN ); - } - - // Player takes less damage - float flDamage = ( pPlayer == NULL ) ? 250 : sk_hunter_dmg_charge.GetFloat(); - - // If it's being held by the player, break that bond - Pickup_ForcePlayerToDropThisObject( pTarget ); - - // Calculate the physics force - Hunter_ApplyChargeDamage( this, pTarget, flDamage ); -} - - -//----------------------------------------------------------------------------- -// Handles the hunter charging into something. Returns true if it hit the world. -//----------------------------------------------------------------------------- -bool CNPC_Hunter::HandleChargeImpact( Vector vecImpact, CBaseEntity *pEntity ) -{ - // Cause a shock wave from this point which will disrupt nearby physics objects - //ImpactShock( vecImpact, 128, 350 ); - - // Did we hit anything interesting? - if ( !pEntity || pEntity->IsWorld() ) - { - // Robin: Due to some of the finicky details in the motor, the hunter will hit - // the world when it is blocked by our enemy when trying to step up - // during a moveprobe. To get around this, we see if the enemy's within - // a volume in front of the hunter when we hit the world, and if he is, - // we hit him anyway. - EnemyIsRightInFrontOfMe( &pEntity ); - - // Did we manage to find him? If not, increment our charge miss count and abort. - if ( pEntity->IsWorld() ) - { - return true; - } - } - - // Hit anything we don't like - if ( IRelationType( pEntity ) == D_HT && ( GetNextAttack() < gpGlobals->curtime ) ) - { - EmitSound( "NPC_Hunter.ChargeHitEnemy" ); - - // dvs: TODO: - //if ( !IsPlayingGesture( ACT_HUNTER_CHARGE_HIT ) ) - //{ - // RestartGesture( ACT_HUNTER_CHARGE_HIT ); - //} - - ChargeDamage( pEntity ); - - if ( !pEntity->IsNPC() ) - { - pEntity->ApplyAbsVelocityImpulse( ( BodyDirection2D() * 400 ) + Vector( 0, 0, 200 ) ); - } - - if ( !pEntity->IsAlive() && GetEnemy() == pEntity ) - { - SetEnemy( NULL ); - } - - SetNextAttack( gpGlobals->curtime + 2.0f ); - - if ( !pEntity->IsAlive() || !pEntity->IsNPC() ) - { - SetIdealActivity( ACT_HUNTER_CHARGE_STOP ); - return false; - } - else - return true; - - } - - // Hit something we don't hate. If it's not moveable, crash into it. - if ( pEntity->GetMoveType() == MOVETYPE_NONE || pEntity->GetMoveType() == MOVETYPE_PUSH ) - { - CBreakable *pBreakable = dynamic_cast(pEntity); - if ( pBreakable && pBreakable->IsBreakable() && pBreakable->m_takedamage == DAMAGE_YES && pBreakable->GetHealth() > 0 ) - { - ChargeDamage( pEntity ); - } - return true; - } - - // If it's a vphysics object that's too heavy, crash into it too. - if ( pEntity->GetMoveType() == MOVETYPE_VPHYSICS ) - { - IPhysicsObject *pPhysics = pEntity->VPhysicsGetObject(); - if ( pPhysics ) - { - // If the object is being held by the player, knock it out of his hands - if ( pPhysics->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - { - Pickup_ForcePlayerToDropThisObject( pEntity ); - return false; - } - - if ( !pPhysics->IsMoveable() ) - return true; - - float entMass = PhysGetEntityMass( pEntity ) ; - float minMass = VPhysicsGetObject()->GetMass() * 0.5f; - if ( entMass < minMass ) - { - if ( entMass < minMass * 0.666f || pEntity->CollisionProp()->BoundingRadius() < GetHullHeight() ) - { - if ( pEntity->GetHealth() > 0 ) - { - CBreakableProp *pBreakable = dynamic_cast(pEntity); - if ( pBreakable && pBreakable->m_takedamage == DAMAGE_YES && pBreakable->GetHealth() > 0 && pBreakable->GetHealth() <= 50 ) - { - ChargeDamage( pEntity ); - } - } - pEntity->SetNavIgnore( 2.0 ); - return false; - } - } - return true; - - } - } - - return false; -} - - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -void CNPC_Hunter::Explode() -{ - Vector velocity = vec3_origin; - AngularImpulse angVelocity = RandomAngularImpulse( -150, 150 ); - - PropBreakableCreateAll( GetModelIndex(), NULL, EyePosition(), GetAbsAngles(), velocity, angVelocity, 1.0, 150, COLLISION_GROUP_NPC, this ); - - ExplosionCreate( EyePosition(), GetAbsAngles(), this, 500, 256, (SF_ENVEXPLOSION_NOPARTICLES|SF_ENVEXPLOSION_NOSPARKS|SF_ENVEXPLOSION_NODLIGHTS|SF_ENVEXPLOSION_NODAMAGE|SF_ENVEXPLOSION_NOSMOKE), false ); - - // Create liquid fountain gushtacular effect here! - CEffectData data; - - data.m_vOrigin = EyePosition(); - data.m_vNormal = Vector( 0, 0, 1 ); - data.m_flScale = 4.0f; - - DispatchEffect( "StriderBlood", data ); - - // Go away - m_lifeState = LIFE_DEAD; - - SetThink( &CNPC_Hunter::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - AddEffects( EF_NODRAW ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Activity CNPC_Hunter::NPC_TranslateActivity( Activity baseAct ) -{ - if ( ( baseAct == ACT_WALK ) || ( baseAct == ACT_RUN ) ) - { - if ( GetEnemy() ) - { - Vector vecEnemyLKP = GetEnemyLKP(); - - // Only start facing when we're close enough - if ( UTIL_DistApprox( vecEnemyLKP, GetAbsOrigin() ) < HUNTER_FACE_ENEMY_DIST ) - { - return (Activity)ACT_HUNTER_WALK_ANGRY; - } - } - } - else if ( ( baseAct == ACT_IDLE ) && m_bPlanted ) - { - return ( Activity )ACT_HUNTER_IDLE_PLANTED; - } - else if ( baseAct == ACT_RANGE_ATTACK2 ) - { - if ( !m_bPlanted && ( m_bEnableUnplantedShooting || IsStriderBuster( GetEnemy() ) ) ) - { - return (Activity)ACT_HUNTER_RANGE_ATTACK2_UNPLANTED; - } - } - - return BaseClass::NPC_TranslateActivity( baseAct ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::HandleAnimEvent( animevent_t *pEvent ) -{ - Vector footPosition; - QAngle angles; - - if ( pEvent->event == AE_HUNTER_FOOTSTEP_LEFT ) - { - LeftFootHit( pEvent->eventtime ); - return; - } - - if ( pEvent->event == AE_HUNTER_FOOTSTEP_RIGHT ) - { - RightFootHit( pEvent->eventtime ); - return; - } - - if ( pEvent->event == AE_HUNTER_FOOTSTEP_BACK ) - { - BackFootHit( pEvent->eventtime ); - return; - } - - if ( pEvent->event == AE_HUNTER_START_EXPRESSION ) - { - if ( pEvent->options && Q_strlen( pEvent->options ) ) - { - //m_iszCurrentExpression = AllocPooledString( pEvent->options ); - //SetExpression( pEvent->options ); - } - return; - } - - if ( pEvent->event == AE_HUNTER_END_EXPRESSION ) - { - if ( pEvent->options && Q_strlen( pEvent->options ) ) - { - //m_iszCurrentExpression = NULL_STRING; - //RemoveActorFromScriptedScenes( this, true, false, pEvent->options ); - } - return; - } - - if ( pEvent->event == AE_HUNTER_MELEE_ANNOUNCE ) - { - EmitSound( "NPC_Hunter.MeleeAnnounce" ); - return; - } - - if ( pEvent->event == AE_HUNTER_MELEE_ATTACK_LEFT ) - { - QAngle viewPunch(25.0f, 30.0f, -20.0f); - Vector right, forward, velocityPunch; - AngleVectors( GetLocalAngles(), &forward, &right, NULL ); - - right = right * -100; - forward = forward * 600; - velocityPunch = right + forward; - - MeleeAttack( HUNTER_MELEE_REACH, sk_hunter_dmg_one_slash.GetInt(), viewPunch, velocityPunch, HUNTER_BLOOD_LEFT_FOOT ); - return; - } - - if ( pEvent->event == AE_HUNTER_MELEE_ATTACK_RIGHT ) - { - QAngle viewPunch(25.0f, -30.0f, 20.0f); - Vector right, forward, velocityPunch; - AngleVectors( GetLocalAngles(), &forward, &right, NULL ); - - right = right * 100; - forward = forward * 600; - velocityPunch = right + forward; - - MeleeAttack( HUNTER_MELEE_REACH, sk_hunter_dmg_one_slash.GetInt(), viewPunch, velocityPunch, HUNTER_BLOOD_LEFT_FOOT ); - return; - } - - if ( pEvent->event == AE_HUNTER_SPRAY_BLOOD ) - { - Vector vecOrigin; - Vector vecDir; - - // spray blood from the attachment point - bool bGotAttachment = false; - if ( pEvent->options ) - { - QAngle angDir; - if ( GetAttachment( pEvent->options, vecOrigin, angDir ) ) - { - bGotAttachment = true; - AngleVectors( angDir, &vecDir, NULL, NULL ); - } - } - - // fall back to our center, tracing forward - if ( !bGotAttachment ) - { - vecOrigin = WorldSpaceCenter(); - GetVectors( &vecDir, NULL, NULL ); - } - - UTIL_BloodSpray( vecOrigin, vecDir, BLOOD_COLOR_RED, 4, FX_BLOODSPRAY_ALL ); - - for ( int i = 0 ; i < 3 ; i++ ) - { - Vector vecTraceDir = vecDir; - vecTraceDir.x += random->RandomFloat( -0.1, 0.1 ); - vecTraceDir.y += random->RandomFloat( -0.1, 0.1 ); - vecTraceDir.z += random->RandomFloat( -0.1, 0.1 ); - - trace_t tr; - AI_TraceLine( vecOrigin, vecOrigin + ( vecTraceDir * 192.0f ), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction != 1.0 ) - { - UTIL_BloodDecalTrace( &tr, BLOOD_COLOR_RED ); - } - } - - return; - } - - BaseClass::HandleAnimEvent( pEvent ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::AddEntityRelationship( CBaseEntity *pEntity, Disposition_t nDisposition, int nPriority ) -{ - if ( nDisposition == D_HT && pEntity->ClassMatches("npc_bullseye") ) - UpdateEnemyMemory( pEntity, pEntity->GetAbsOrigin() ); - BaseClass::AddEntityRelationship( pEntity, nDisposition, nPriority ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Hunter::ScheduledMoveToGoalEntity( int scheduleType, CBaseEntity *pGoalEntity, Activity movementActivity ) -{ - if ( IsCurSchedule( SCHED_HUNTER_RANGE_ATTACK1, false ) ) - { - SetGoalEnt( pGoalEntity ); - return true; - } - return BaseClass::ScheduledMoveToGoalEntity( scheduleType, pGoalEntity, movementActivity ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::OnChangeHintGroup( string_t oldGroup, string_t newGroup ) -{ - SetCondition( COND_HUNTER_NEW_HINTGROUP ); - m_CheckHintGroupTimer.Set( 10 ); -} - - -//----------------------------------------------------------------------------- -// Tells whether any given hunter is in a squad that contains other hunters. -// This is useful for preventing timid behavior for Hunters that are not -// supported by other hunters. -// -// NOTE: This counts the self! So a hunter that is alone in his squad -// receives a result of 1. -//----------------------------------------------------------------------------- -int CNPC_Hunter::NumHuntersInMySquad() -{ - AISquadIter_t iter; - CAI_BaseNPC *pSquadmate = m_pSquad ? m_pSquad->GetFirstMember( &iter ) : NULL; - - if( !pSquadmate ) - { - // Not in a squad at all, but the caller is not concerned with that. Just - // tell them that we're in a squad of one (ourself) - return 1; - } - - int count = 0; - - while ( pSquadmate ) - { - if( pSquadmate->m_iClassname == m_iClassname ) - count++; - - pSquadmate = m_pSquad->GetNextMember( &iter ); - } - - return count; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::FollowStrider( const char *szStrider ) -{ - if ( !szStrider ) - return; - - CBaseEntity *pEnt = gEntList.FindEntityByName( NULL, szStrider, this ); - CNPC_Strider *pStrider = dynamic_cast ( pEnt ); - FollowStrider(pStrider); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::FollowStrider( CNPC_Strider * pStrider ) -{ - if ( !IsAlive() ) - { - return; - } - - if ( pStrider ) - { - if ( m_EscortBehavior.GetFollowTarget() != pStrider ) - { - m_iszFollowTarget = pStrider->GetEntityName(); - if ( m_iszFollowTarget == NULL_STRING ) - { - m_iszFollowTarget = AllocPooledString( "unnamed_strider" ); - } - m_EscortBehavior.SetEscortTarget( pStrider ); - } - } - else - { - DevWarning("Hunter set to follow entity %s that is not a strider\n", STRING( m_iszFollowTarget ) ); - m_iszFollowTarget = AllocPooledString( "unknown_strider" ); - } -} - -void CAI_HunterEscortBehavior::SetEscortTarget( CNPC_Strider *pStrider, bool fFinishCurSchedule ) -{ - m_bEnabled = true; - - if ( GetOuter()->GetSquad() ) - { - GetOuter()->GetSquad()->RemoveFromSquad( GetOuter() ); - } - - for ( int i = 0; i < g_Hunters.Count(); i++ ) - { - if ( g_Hunters[i]->m_EscortBehavior.GetFollowTarget() == pStrider ) - { - Assert( g_Hunters[i]->GetSquad() ); - g_Hunters[i]->GetSquad()->AddToSquad( GetOuter() ); - break; - } - } - - if ( !GetOuter()->GetSquad() ) - { - GetOuter()->AddToSquad( AllocPooledString( CFmtStr( "%s_hunter_squad", STRING( pStrider->GetEntityName() ) ) ) ); - } - - BaseClass::SetFollowTarget( pStrider ); - m_flTimeEscortReturn = gpGlobals->curtime; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::InputEnableUnplantedShooting( inputdata_t &inputdata ) -{ - m_bEnableUnplantedShooting = true; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::InputDisableUnplantedShooting( inputdata_t &inputdata ) -{ - m_bEnableUnplantedShooting = false; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::InputFollowStrider( inputdata_t &inputdata ) -{ - m_iszFollowTarget = inputdata.value.StringID(); - if ( m_iszFollowTarget == s_iszStriderClassname ) - { - m_EscortBehavior.m_bEnabled = true; - m_iszFollowTarget = NULL_STRING; - } - m_BeginFollowDelay.Start( .1 ); // Allow time for strider to spawn -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::InputUseSiegeTargets( inputdata_t &inputdata ) -{ - m_iszSiegeTargetName = inputdata.value.StringID(); - m_flTimeNextSiegeTargetAttack = gpGlobals->curtime + random->RandomFloat( 1, hunter_siege_frequency.GetFloat() ); - - if( m_iszSiegeTargetName == NULL_STRING ) - { - // Turning the feature off. Restore m_flDistTooFar to default. - m_flDistTooFar = hunter_flechette_max_range.GetFloat(); - m_pSiegeTargets.RemoveAll(); - } - else - { - // We're going into siege mode. Adjust range accordingly. - m_flDistTooFar = hunter_flechette_max_range.GetFloat() * HUNTER_SIEGE_MAX_DIST_MODIFIER; - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::InputDodge( inputdata_t &inputdata ) -{ - SetCondition( COND_HUNTER_FORCED_DODGE ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::InputFlankEnemy( inputdata_t &inputdata ) -{ - SetCondition( COND_HUNTER_FORCED_FLANK_ENEMY ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::InputDisableShooting( inputdata_t &inputdata ) -{ - m_bDisableShooting = true; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::InputEnableShooting( inputdata_t &inputdata ) -{ - m_bDisableShooting = false; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::InputEnableSquadShootDelay( inputdata_t &inputdata ) -{ - m_bEnableSquadShootDelay = true; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::InputDisableSquadShootDelay( inputdata_t &inputdata ) -{ - m_bEnableSquadShootDelay = false; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Hunter::FVisible( CBaseEntity *pEntity, int traceMask, CBaseEntity **ppBlocker ) -{ - return BaseClass::FVisible( pEntity, traceMask, ppBlocker ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Hunter::IsValidEnemy( CBaseEntity *pTarget ) -{ - if ( IsStriderBuster( pTarget) ) - { - if ( !m_EscortBehavior.m_bEnabled || !m_EscortBehavior.GetEscortTarget() ) - { - // We only hate striderbusters when we are actively protecting a strider. - return false; - } - - if ( pTarget->VPhysicsGetObject() ) - { - if ( ( pTarget->VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) && - hunter_hate_held_striderbusters.GetBool() ) - { - if ( gpGlobals->curtime - StriderBuster_GetPickupTime( pTarget ) > hunter_hate_held_striderbusters_delay.GetFloat()) - { - if ( StriderBuster_NumFlechettesAttached( pTarget ) <= 2 ) - { - if ( m_EscortBehavior.GetEscortTarget() && - ( m_EscortBehavior.GetEscortTarget()->GetAbsOrigin().AsVector2D() - pTarget->GetAbsOrigin().AsVector2D() ).LengthSqr() < Square( hunter_hate_held_striderbusters_tolerance.GetFloat() ) ) - { - return true; - } - } - } - return false; - } - - bool bThrown = ( pTarget->VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_WAS_THROWN ) != 0; - bool bAttached = StriderBuster_IsAttachedStriderBuster( pTarget ); - - if ( ( bThrown && !bAttached ) && hunter_hate_thrown_striderbusters.GetBool() ) - { - float t; - float dist = CalcDistanceSqrToLineSegment2D( m_EscortBehavior.GetEscortTarget()->GetAbsOrigin().AsVector2D(), - pTarget->GetAbsOrigin().AsVector2D(), - pTarget->GetAbsOrigin().AsVector2D() + pTarget->GetSmoothedVelocity().AsVector2D(), &t ); - - if ( t > 0 && dist < Square( hunter_hate_thrown_striderbusters_tolerance.GetFloat() )) - { - return true; - } - return false; - } - - if ( bAttached && StriderBuster_IsAttachedStriderBuster( pTarget, m_EscortBehavior.GetEscortTarget() ) && hunter_hate_attached_striderbusters.GetBool() ) - { - return true; - } - } - return false; - } - - return BaseClass::IsValidEnemy( pTarget ); -} - - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Disposition_t CNPC_Hunter::IRelationType( CBaseEntity *pTarget ) -{ - if ( !pTarget ) - return D_NU; - - if ( IsStriderBuster( pTarget ) ) - { - if ( HateThisStriderBuster( pTarget ) ) - return D_HT; - - return D_NU; - } - - if ( hunter_retreat_striderbusters.GetBool() ) - { - if ( pTarget->IsPlayer() && (m_hAttachedBusters.Count() > 0) ) - { - return D_FR; - } - } - - return BaseClass::IRelationType( pTarget ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Hunter::IRelationPriority( CBaseEntity *pTarget ) -{ - if ( IsStriderBuster( pTarget ) ) - { - // If we're here, we already know that we hate striderbusters. - return 1000; - } - - return BaseClass::IRelationPriority( pTarget ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::SetSquad( CAI_Squad *pSquad ) -{ - BaseClass::SetSquad( pSquad ); - if ( pSquad && pSquad->NumMembers() == 1 ) - { - pSquad->SetSquadData( HUNTER_RUNDOWN_SQUADDATA, 0 ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::OnSeeEntity( CBaseEntity *pEntity ) -{ - BaseClass::OnSeeEntity(pEntity); - - if ( IsStriderBuster( pEntity ) && IsValidEnemy( pEntity ) ) - { - SetCondition( COND_HUNTER_SEE_STRIDERBUSTER ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Hunter::UpdateEnemyMemory( CBaseEntity *pEnemy, const Vector &position, CBaseEntity *pInformer ) -{ - //EmitSound( "NPC_Hunter.Alert" ); - return BaseClass::UpdateEnemyMemory( pEnemy, position, pInformer ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Hunter::CanPlantHere( const Vector &vecPos ) -{ - // TODO: cache results? - //if ( vecPos == m_vecLastCanPlantHerePos ) - //{ - // return m_bLastCanPlantHere; - //} - - Vector vecMins = GetHullMins(); - Vector vecMaxs = GetHullMaxs(); - - vecMins.x -= 16; - vecMins.y -= 16; - - vecMaxs.x += 16; - vecMaxs.y += 16; - vecMaxs.z -= hunter_plant_adjust_z.GetInt(); - - bool bResult = false; - - trace_t tr; - UTIL_TraceHull( vecPos, vecPos, vecMins, vecMaxs, MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - if ( tr.startsolid ) - { - // Try again, tracing down from above. - Vector vecStart = vecPos; - vecStart.z += hunter_plant_adjust_z.GetInt(); - - UTIL_TraceHull( vecStart, vecPos, vecMins, vecMaxs, MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - } - - if ( tr.startsolid ) - { - //NDebugOverlay::Box( vecPos, vecMins, vecMaxs, 255, 0, 0, 0, 0 ); - } - else - { - //NDebugOverlay::Box( vecPos, vecMins, vecMaxs, 0, 255, 0, 0, 0 ); - bResult = true; - } - - // Cache the results in case we ask again for the same spot. - //m_vecLastCanPlantHerePos = vecPos; - //m_bLastCanPlantHere = bResult; - - return bResult; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Hunter::MeleeAttack1ConditionsVsEnemyInVehicle( CBaseCombatCharacter *pEnemy, float flDot ) -{ - if( !IsCorporealEnemy( GetEnemy() ) ) - return COND_NONE; - - // Try and trace a box to the player, and if I hit the vehicle, attack it - Vector vecDelta = (pEnemy->WorldSpaceCenter() - WorldSpaceCenter()); - VectorNormalize( vecDelta ); - trace_t tr; - AI_TraceHull( WorldSpaceCenter(), WorldSpaceCenter() + (vecDelta * 64), -Vector(8,8,8), Vector(8,8,8), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction != 1.0 && tr.m_pEnt == pEnemy->GetVehicleEntity() ) - { - // We're near the vehicle. Are we facing it? - if (flDot < 0.7) - return COND_NOT_FACING_ATTACK; - - return COND_CAN_MELEE_ATTACK1; - } - - return COND_TOO_FAR_TO_ATTACK; -} - - -//----------------------------------------------------------------------------- -// For innate melee attack -//----------------------------------------------------------------------------- -int CNPC_Hunter::MeleeAttack1Conditions ( float flDot, float flDist ) -{ - if ( !IsCorporealEnemy( GetEnemy() ) ) - return COND_NONE; - - if ( ( gpGlobals->curtime < m_flNextMeleeTime ) && // allow berzerk bashing if cornered - !( m_hAttachedBusters.Count() > 0 && gpGlobals->curtime < m_fCorneredTimer ) ) - { - return COND_NONE; - } - - if ( GetEnemy()->Classify() == CLASS_PLAYER_ALLY_VITAL ) - { - return COND_NONE; - } - - if ( flDist > HUNTER_MELEE_REACH ) - { - // Translate a hit vehicle into its passenger if found - if ( GetEnemy() != NULL ) - { - CBaseCombatCharacter *pCCEnemy = GetEnemy()->MyCombatCharacterPointer(); - if ( pCCEnemy != NULL && pCCEnemy->IsInAVehicle() ) - { - return MeleeAttack1ConditionsVsEnemyInVehicle( pCCEnemy, flDot ); - } - -#if defined(HL2_DLL) && !defined(HL2MP) - // If the player is holding an object, knock it down. - if ( GetEnemy()->IsPlayer() ) - { - CBasePlayer *pPlayer = ToBasePlayer( GetEnemy() ); - - Assert( pPlayer != NULL ); - - // Is the player carrying something? - CBaseEntity *pObject = GetPlayerHeldEntity(pPlayer); - - if ( !pObject ) - { - pObject = PhysCannonGetHeldEntity( pPlayer->GetActiveWeapon() ); - } - - if ( pObject ) - { - float flDist = pObject->WorldSpaceCenter().DistTo( WorldSpaceCenter() ); - - if ( flDist <= HUNTER_MELEE_REACH ) - { - return COND_CAN_MELEE_ATTACK1; - } - } - } -#endif - } - - return COND_TOO_FAR_TO_ATTACK; - } - - if (flDot < 0.7) - { - return COND_NOT_FACING_ATTACK; - } - - // Build a cube-shaped hull, the same hull that MeleeAttack is going to use. - Vector vecMins = GetHullMins(); - Vector vecMaxs = GetHullMaxs(); - vecMins.z = vecMins.x; - vecMaxs.z = vecMaxs.x; - - Vector forward; - GetVectors( &forward, NULL, NULL ); - - trace_t tr; - AI_TraceHull( WorldSpaceCenter(), WorldSpaceCenter() + forward * HUNTER_MELEE_REACH, vecMins, vecMaxs, MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction == 1.0 || !tr.m_pEnt ) - { - // This attack would miss completely. Trick the hunter into moving around some more. - return COND_TOO_FAR_TO_ATTACK; - } - - if ( tr.m_pEnt == GetEnemy() || tr.m_pEnt->IsNPC() || (tr.m_pEnt->m_takedamage == DAMAGE_YES && (dynamic_cast(tr.m_pEnt))) ) - { - // Let the hunter swipe at his enemy if he's going to hit them. - // Also let him swipe at NPC's that happen to be between the hunter and the enemy. - // This makes mobs of hunters seem more rowdy since it doesn't leave guys in the back row standing around. - // Also let him swipe at things that takedamage, under the assumptions that they can be broken. - return COND_CAN_MELEE_ATTACK1; - } - - // dvs TODO: incorporate this - /*if ( tr.m_pEnt->IsBSPModel() ) - { - // The trace hit something solid, but it's not the enemy. If this item is closer to the hunter than - // the enemy is, treat this as an obstruction. - Vector vecToEnemy = GetEnemy()->WorldSpaceCenter() - WorldSpaceCenter(); - Vector vecTrace = tr.endpos - tr.startpos; - - if ( vecTrace.Length2DSqr() < vecToEnemy.Length2DSqr() ) - { - return COND_HUNTER_LOCAL_MELEE_OBSTRUCTION; - } - }*/ - - if ( !tr.m_pEnt->IsWorld() && GetEnemy() && GetEnemy()->GetGroundEntity() == tr.m_pEnt ) - { - // Try to swat whatever the player is standing on instead of acting like a dill. - return COND_CAN_MELEE_ATTACK1; - } - - // Move around some more - return COND_TOO_FAR_TO_ATTACK; -} - - -//----------------------------------------------------------------------------- -// For innate melee attack -//----------------------------------------------------------------------------- -int CNPC_Hunter::MeleeAttack2Conditions ( float flDot, float flDist ) -{ - return COND_NONE; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Hunter::IsCorporealEnemy( CBaseEntity *pEnemy ) -{ - if( !pEnemy ) - return false; - - // Generally speaking, don't melee attack anything the player can't see. - if( pEnemy->IsEffectActive( EF_NODRAW ) ) - return false; - - // Don't flank, melee attack striderbusters. - if ( IsStriderBuster( pEnemy ) ) - return false; - - return true; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Hunter::RangeAttack1Conditions( float flDot, float flDist ) -{ - return COND_NONE; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Hunter::RangeAttack2Conditions( float flDot, float flDist ) -{ - bool bIsBuster = IsStriderBuster( GetEnemy() ); - bool bIsPerfectBullseye = ( GetEnemy() && dynamic_cast(GetEnemy()) && ((CNPC_Bullseye *)GetEnemy())->UsePerfectAccuracy() ); - - if ( !bIsPerfectBullseye && !bIsBuster && !hunter_flechette_test.GetBool() && ( gpGlobals->curtime < m_flNextRangeAttack2Time ) ) - { - return COND_NONE; - } - - if ( m_bDisableShooting ) - { - return COND_NONE; - } - - if ( !HasCondition( COND_SEE_ENEMY ) ) - { - return COND_NONE; - } - - float flMaxFlechetteRange = hunter_flechette_max_range.GetFloat(); - - if ( IsUsingSiegeTargets() ) - { - flMaxFlechetteRange *= HUNTER_SIEGE_MAX_DIST_MODIFIER; - } - - if ( !bIsBuster && ( flDist > flMaxFlechetteRange ) ) - { - return COND_TOO_FAR_TO_ATTACK; - } - else if ( !bIsBuster && ( !GetEnemy() || !GetEnemy()->ClassMatches( "npc_bullseye" ) ) && flDist < hunter_flechette_min_range.GetFloat() ) - { - return COND_TOO_CLOSE_TO_ATTACK; - } - else if ( flDot < HUNTER_FACING_DOT ) - { - return COND_NOT_FACING_ATTACK; - } - - if ( !bIsBuster && !m_bEnableUnplantedShooting && !hunter_flechette_test.GetBool() && !CanPlantHere( GetAbsOrigin() ) ) - { - return COND_HUNTER_CANT_PLANT; - } - - return COND_CAN_RANGE_ATTACK2; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Hunter::WeaponLOSCondition(const Vector &ownerPos, const Vector &targetPos, bool bSetConditions) -{ - CBaseEntity *pTargetEnt; - - pTargetEnt = GetEnemy(); - - trace_t tr; - Vector vFrom = ownerPos + GetViewOffset(); - AI_TraceLine( vFrom, targetPos, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - if ( ( pTargetEnt && tr.m_pEnt == pTargetEnt) || tr.fraction == 1.0 || CanShootThrough( tr, targetPos ) ) - { - static Vector vMins( -2.0, -2.0, -2.0 ); - static Vector vMaxs( -vMins); - // Hit the enemy, or hit nothing (traced all the way to a nonsolid enemy like a bullseye) - AI_TraceHull( vFrom - Vector( 0, 0, 18 ), targetPos, vMins, vMaxs, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); - - if ( ( pTargetEnt && tr.m_pEnt == pTargetEnt) || tr.fraction == 1.0 || CanShootThrough( tr, targetPos ) ) - { - if ( hunter_show_weapon_los_condition.GetBool() ) - { - NDebugOverlay::Line( vFrom, targetPos, 255, 0, 255, false, 0.1 ); - NDebugOverlay::Line( vFrom - Vector( 0, 0, 18 ), targetPos, 0, 0, 255, false, 0.1 ); - } - return true; - } - } - else if ( bSetConditions ) - { - SetCondition( COND_WEAPON_SIGHT_OCCLUDED ); - SetEnemyOccluder( tr.m_pEnt ); - } - - return false; -} - -//----------------------------------------------------------------------------- -// Look in front and see if the claw hit anything. -// -// Input : flDist distance to trace -// iDamage damage to do if attack hits -// vecViewPunch camera punch (if attack hits player) -// vecVelocityPunch velocity punch (if attack hits player) -// -// Output : The entity hit by claws. NULL if nothing. -//----------------------------------------------------------------------------- -CBaseEntity *CNPC_Hunter::MeleeAttack( float flDist, int iDamage, QAngle &qaViewPunch, Vector &vecVelocityPunch, int BloodOrigin ) -{ - // Added test because claw attack anim sometimes used when for cases other than melee - if ( GetEnemy() ) - { - trace_t tr; - AI_TraceHull( WorldSpaceCenter(), GetEnemy()->WorldSpaceCenter(), -Vector(8,8,8), Vector(8,8,8), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction < 1.0f ) - return NULL; - } - - // - // Trace out a cubic section of our hull and see what we hit. - // - Vector vecMins = GetHullMins(); - Vector vecMaxs = GetHullMaxs(); - vecMins.z = vecMins.x; - vecMaxs.z = vecMaxs.x; - - CBaseEntity *pHurt = CheckTraceHullAttack( flDist, vecMins, vecMaxs, iDamage, DMG_SLASH ); - - if ( pHurt ) - { - EmitSound( "NPC_Hunter.MeleeHit" ); - EmitSound( "NPC_Hunter.TackleHit" ); - - CBasePlayer *pPlayer = ToBasePlayer( pHurt ); - - if ( pPlayer != NULL && !(pPlayer->GetFlags() & FL_GODMODE ) ) - { - pPlayer->ViewPunch( qaViewPunch ); - pPlayer->VelocityPunch( vecVelocityPunch ); - - // Shake the screen - UTIL_ScreenShake( pPlayer->GetAbsOrigin(), 100.0, 1.5, 1.0, 2, SHAKE_START ); - - // Red damage indicator - color32 red = { 128, 0, 0, 128 }; - UTIL_ScreenFade( pPlayer, red, 1.0f, 0.1f, FFADE_IN ); - - /*if ( UTIL_ShouldShowBlood( pPlayer->BloodColor() ) ) - { - // Spray some of the player's blood on the hunter. - trace_t tr; - - Vector vecHunterEyePos; // = EyePosition(); - QAngle angDiscard; - GetBonePosition( LookupBone( "MiniStrider.top_eye_bone" ), vecHunterEyePos, angDiscard ); - - Vector vecPlayerEyePos = pPlayer->EyePosition(); - - Vector vecDir = vecHunterEyePos - vecPlayerEyePos; - float flLen = VectorNormalize( vecDir ); - - Vector vecStart = vecPlayerEyePos - ( vecDir * 64 ); - Vector vecEnd = vecPlayerEyePos + ( vecDir * ( flLen + 64 ) ); - - NDebugOverlay::HorzArrow( vecStart, vecEnd, 16, 255, 255, 0, 255, false, 10 ); - - UTIL_TraceLine( vecStart, vecEnd, MASK_SHOT, pPlayer, COLLISION_GROUP_NONE, &tr ); - - if ( tr.m_pEnt ) - { - Msg( "Hit %s!!!\n", tr.m_pEnt->GetDebugName() ); - UTIL_DecalTrace( &tr, "Blood" ); - } - }*/ - } - else if ( !pPlayer ) - { - if ( IsMovablePhysicsObject( pHurt ) ) - { - // If it's a vphysics object that's too heavy, crash into it too. - IPhysicsObject *pPhysics = pHurt->VPhysicsGetObject(); - if ( pPhysics ) - { - // If the object is being held by the player, break it or make them drop it. - if ( pPhysics->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - { - // If it's breakable, break it. - if ( pHurt->m_takedamage == DAMAGE_YES ) - { - CBreakableProp *pBreak = dynamic_cast(pHurt); - if ( pBreak ) - { - CTakeDamageInfo info( this, this, 20, DMG_SLASH ); - pBreak->Break( this, info ); - } - } - } - } - } - - if ( UTIL_ShouldShowBlood(pHurt->BloodColor()) ) - { - // Hit an NPC. Bleed them! - Vector vecBloodPos; - - switch ( BloodOrigin ) - { - case HUNTER_BLOOD_LEFT_FOOT: - { - if ( GetAttachment( "blood_left", vecBloodPos ) ) - { - SpawnBlood( vecBloodPos, g_vecAttackDir, pHurt->BloodColor(), MIN( iDamage, 30 ) ); - } - - break; - } - } - } - } - } - else - { - // TODO: - //AttackMissSound(); - } - - m_flNextMeleeTime = gpGlobals->curtime + hunter_melee_delay.GetFloat(); - - return pHurt; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Hunter::TestShootPosition(const Vector &vecShootPos, const Vector &targetPos ) -{ - if ( !CanPlantHere(vecShootPos ) ) - { - return false; - } - - return BaseClass::TestShootPosition( vecShootPos, targetPos ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Vector CNPC_Hunter::Weapon_ShootPosition( ) -{ - matrix3x4_t gunMatrix; - GetAttachment( gm_nTopGunAttachment, gunMatrix ); - - Vector vecShootPos; - MatrixGetColumn( gunMatrix, 3, vecShootPos ); - - return vecShootPos; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ) -{ - float flTracerDist; - Vector vecDir; - Vector vecEndPos; - - vecDir = tr.endpos - vecTracerSrc; - - flTracerDist = VectorNormalize( vecDir ); - - int nAttachment = LookupAttachment( "MiniGun" ); - - UTIL_Tracer( vecTracerSrc, tr.endpos, nAttachment, TRACER_FLAG_USEATTACHMENT, 5000, true, "HunterTracer" ); -} - - -//----------------------------------------------------------------------------- -// Trace didn't hit the intended target, but should the hunter -// shoot anyway? We use this to get the hunter to destroy -// breakables that are between him and his target. -//----------------------------------------------------------------------------- -bool CNPC_Hunter::CanShootThrough( const trace_t &tr, const Vector &vecTarget ) -{ - if ( !tr.m_pEnt ) - { - return false; - } - - if ( !tr.m_pEnt->GetHealth() ) - { - return false; - } - - // Don't try to shoot through allies. - CAI_BaseNPC *pNPC = tr.m_pEnt->MyNPCPointer(); - if ( pNPC && ( IRelationType( pNPC ) == D_LI ) ) - { - return false; - } - - // Would a trace ignoring this entity continue to the target? - trace_t continuedTrace; - AI_TraceLine( tr.endpos, vecTarget, MASK_SHOT, tr.m_pEnt, COLLISION_GROUP_NONE, &continuedTrace ); - - if ( continuedTrace.fraction != 1.0 ) - { - if ( continuedTrace.m_pEnt != GetEnemy() ) - { - return false; - } - } - - return true; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Hunter::GetSoundInterests() -{ - return SOUND_WORLD | SOUND_COMBAT | SOUND_PLAYER | SOUND_DANGER | SOUND_PHYSICS_DANGER | SOUND_PLAYER_VEHICLE | SOUND_BULLET_IMPACT | SOUND_MOVE_AWAY; -} - -//----------------------------------------------------------------------------- -// Tells us whether the Hunter is acting in a large, outdoor map, -// currently only ep2_outland_12. This allows us to create logic -// branches here in the AI code so that we can make choices that -// tailor behavior to larger and smaller maps. -//----------------------------------------------------------------------------- -bool CNPC_Hunter::IsInLargeOutdoorMap() -{ - return m_bInLargeOutdoorMap; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::AlertSound() -{ - EmitSound( "NPC_Hunter.Alert" ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::PainSound( const CTakeDamageInfo &info ) -{ - if ( gpGlobals->curtime > m_flNextDamageTime ) - { - EmitSound( "NPC_Hunter.Pain" ); - m_flNextDamageTime = gpGlobals->curtime + random->RandomFloat( 0.5, 1.2 ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::DeathSound( const CTakeDamageInfo &info ) -{ - EmitSound( "NPC_Hunter.Death" ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::TraceAttack( const CTakeDamageInfo &inputInfo, const Vector &vecDir, trace_t *ptr ) -{ - CTakeDamageInfo info = inputInfo; - - // Even though the damage might not hurt us, we want to react to it - // if it's from the player. - if ( info.GetAttacker()->IsPlayer() ) - { - if ( !HasMemory( bits_MEMORY_PROVOKED ) ) - { - GetEnemies()->ClearMemory( info.GetAttacker() ); - Remember( bits_MEMORY_PROVOKED ); - SetCondition( COND_LIGHT_DAMAGE ); - } - } - - // HUnters have special resisitance to some types of damage. - if ( ( info.GetDamageType() & DMG_BULLET ) || - ( info.GetDamageType() & DMG_BUCKSHOT ) || - ( info.GetDamageType() & DMG_CLUB ) || - ( info.GetDamageType() & DMG_NEVERGIB ) ) - { - float flScale = 1.0; - - if ( info.GetDamageType() & DMG_BUCKSHOT ) - { - flScale = sk_hunter_buckshot_damage_scale.GetFloat(); - } - else if ( ( info.GetDamageType() & DMG_BULLET ) || ( info.GetDamageType() & DMG_NEVERGIB ) ) - { - // Hunters resist most bullet damage, but they are actually vulnerable to .357 rounds, - // since players regard that weapon as one of the game's truly powerful weapons. - if( info.GetAmmoType() == GetAmmoDef()->Index("357") ) - { - flScale = 1.16f; - } - else - { - flScale = sk_hunter_bullet_damage_scale.GetFloat(); - } - } - - if ( GetActivity() == ACT_HUNTER_CHARGE_RUN ) - { - flScale *= sk_hunter_charge_damage_scale.GetFloat(); - } - - if ( flScale != 0 ) - { - float flDamage = info.GetDamage() * flScale; - info.SetDamage( flDamage ); - } - - QAngle vecAngles; - VectorAngles( ptr->plane.normal, vecAngles ); - DispatchParticleEffect( "blood_impact_synth_01", ptr->endpos, vecAngles ); - DispatchParticleEffect( "blood_impact_synth_01_arc_parent", PATTACH_POINT_FOLLOW, this, gm_nHeadCenterAttachment ); - } - - BaseClass::TraceAttack( info, vecDir, ptr ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -const impactdamagetable_t &CNPC_Hunter::GetPhysicsImpactDamageTable() -{ - return s_HunterImpactDamageTable; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::PhysicsDamageEffect( const Vector &vecPos, const Vector &vecDir ) -{ - CEffectData data; - data.m_vOrigin = vecPos; - data.m_vNormal = vecDir; - DispatchEffect( "HunterDamage", data ); - - if ( random->RandomInt( 0, 1 ) == 0 ) - { - CBaseEntity *pTrail = CreateEntityByName( "sparktrail" ); - pTrail->SetOwnerEntity( this ); - pTrail->Spawn(); - } -} - - -//----------------------------------------------------------------------------- -// We were hit by a strider buster. Do the tesla effect on our hitboxes. -//----------------------------------------------------------------------------- -void CNPC_Hunter::TeslaThink() -{ - CEffectData data; - data.m_nEntIndex = entindex(); - data.m_flMagnitude = 3; - data.m_flScale = 0.5f; - DispatchEffect( "TeslaHitboxes", data ); - EmitSound( "RagdollBoogie.Zap" ); - - if ( gpGlobals->curtime < m_flTeslaStopTime ) - { - SetContextThink( &CNPC_Hunter::TeslaThink, gpGlobals->curtime + random->RandomFloat( 0.1f, 0.3f ), HUNTER_ZAP_THINK ); - } -} - - -//----------------------------------------------------------------------------- -// Our health is low. Show damage effects. -//----------------------------------------------------------------------------- -void CNPC_Hunter::BleedThink() -{ - // Spurt blood from random points on the hunter's head. - Vector vecOrigin; - QAngle angDir; - GetAttachment( gm_nHeadCenterAttachment, vecOrigin, angDir ); - - Vector vecDir = RandomVector( -1, 1 ); - VectorNormalize( vecDir ); - VectorAngles( vecDir, Vector( 0, 0, 1 ), angDir ); - - vecDir *= gm_flHeadRadius; - DispatchParticleEffect( "blood_spurt_synth_01", vecOrigin + vecDir, angDir ); - - SetNextThink( gpGlobals->curtime + random->RandomFloat( 0.6, 1.5 ), HUNTER_BLEED_THINK ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Hunter::IsHeavyDamage( const CTakeDamageInfo &info ) -{ - if ( info.GetDamage() < 45 ) - { - return false; - } - - if ( info.GetDamage() < 180 ) - { - if ( !m_HeavyDamageDelay.Expired() || !BaseClass::IsHeavyDamage( info ) ) - { - return false; - } - } - - m_HeavyDamageDelay.Set( 15, 25 ); - return true; - -} - - -//----------------------------------------------------------------------------- -// We've taken some damage. Maybe we should flinch because of it. -//----------------------------------------------------------------------------- -void CNPC_Hunter::ConsiderFlinching( const CTakeDamageInfo &info ) -{ - if ( !m_FlinchTimer.Expired() ) - { - // Someone is whaling on us. Push out the timer so we don't keep flinching. - m_FlinchTimer.Set( random->RandomFloat( 0.3 ) ); - return; - } - - if ( GetState() == NPC_STATE_SCRIPT ) - { - return; - } - - Activity eGesture = ACT_HUNTER_FLINCH_N; - - Vector forward; - GetVectors( &forward, NULL, NULL ); - - Vector vecForceDir = info.GetDamageForce(); - VectorNormalize( vecForceDir ); - - float flDot = DotProduct( forward, vecForceDir ); - - if ( flDot > 0.707 ) - { - // flinch forward - eGesture = ACT_HUNTER_FLINCH_N; - } - else if ( flDot < -0.707 ) - { - // flinch back - eGesture = ACT_HUNTER_FLINCH_S; - } - else - { - // flinch left or right - Vector cross = CrossProduct( forward, vecForceDir ); - - if ( cross.z > 0 ) - { - eGesture = ACT_HUNTER_FLINCH_W; - } - else - { - eGesture = ACT_HUNTER_FLINCH_E; - } - } - - if ( !IsPlayingGesture( eGesture ) ) - { - RestartGesture( eGesture ); - m_FlinchTimer.Set( random->RandomFloat( 0.3, 1.0 ) ); - } -} - - -//----------------------------------------------------------------------------- -// This is done from a think function because when the hunter is killed, -// the physics code puts the vehicle's pre-collision velocity back so the jostle -// is basically discared. -//----------------------------------------------------------------------------- -void CNPC_Hunter::JostleVehicleThink() -{ - CBaseEntity *pInflictor = m_hHitByVehicle; - if ( !pInflictor ) - return; - - Vector vecVelDir = pInflictor->GetSmoothedVelocity(); - float flSpeed = VectorNormalize( vecVelDir ); - Vector vecForce = CrossProduct( vecVelDir, Vector( 0, 0, 1 ) ); - if ( DotProduct( vecForce, GetAbsOrigin() ) < DotProduct( vecForce, pInflictor->GetAbsOrigin() ) ) - { - // We're to the left of the vehicle that's hitting us. - vecForce *= -1; - } - - VectorNormalize( vecForce ); - vecForce.z = 1.0; - - float flForceScale = RemapValClamped( flSpeed, hunter_jostle_car_min_speed.GetFloat(), hunter_jostle_car_max_speed.GetFloat(), 50.0f, 150.0f ); - - vecForce *= ( flForceScale * pInflictor->VPhysicsGetObject()->GetMass() ); - - pInflictor->VPhysicsGetObject()->ApplyForceOffset( vecForce, WorldSpaceCenter() ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Hunter::OnTakeDamage( const CTakeDamageInfo &info ) -{ - CTakeDamageInfo myInfo = info; - - if ( ( info.GetDamageType() & DMG_CRUSH ) && !( info.GetDamageType() & DMG_VEHICLE ) ) - { - // Don't take damage from physics objects that weren't thrown by the player. - CBaseEntity *pInflictor = info.GetInflictor(); - - IPhysicsObject *pObj = pInflictor->VPhysicsGetObject(); - //Assert( pObj ); - - if ( !pObj || !pInflictor->HasPhysicsAttacker( 4.0 ) ) - { - myInfo.SetDamage( 0 ); - } - else - { - // Physics objects that have flechettes stuck in them spoof - // a flechette hitting us so we dissolve when killed and award - // the achievement of killing a hunter with its flechettes. - CUtlVector children; - GetAllChildren( pInflictor, children ); - for (int i = 0; i < children.Count(); i++ ) - { - CBaseEntity *pent = children.Element( i ); - if ( dynamic_cast( pent ) ) - { - myInfo.SetInflictor( pent ); - myInfo.SetDamageType( myInfo.GetDamageType() | DMG_DISSOLVE ); - } - } - } - } - - return BaseClass::OnTakeDamage( myInfo ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Hunter::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - CTakeDamageInfo myInfo = info; - - // don't take damage from my own weapons!!! - // Exception: I "own" a magnade if it's glued to me. - CBaseEntity *pInflictor = info.GetInflictor(); - CBaseEntity *pAttacker = info.GetAttacker(); - if ( pInflictor ) - { - if ( IsStriderBuster( pInflictor ) ) - { - // Get a tesla effect on our hitboxes for a little while. - SetContextThink( &CNPC_Hunter::TeslaThink, gpGlobals->curtime, HUNTER_ZAP_THINK ); - m_flTeslaStopTime = gpGlobals->curtime + 2.0f; - - myInfo.SetDamage( sk_hunter_dmg_from_striderbuster.GetFloat() ) ; - - SetCondition( COND_HUNTER_STAGGERED ); - } - else if ( pInflictor->ClassMatches( GetClassname() ) && !( info.GetDamageType() == DMG_GENERIC ) ) - { - return 0; - } - else if ( pInflictor->ClassMatches( "hunter_flechette" ) ) - { - if ( !( ( CHunterFlechette *)pInflictor )->WasThrownBack() ) - { - // Flechettes only hurt us if they were thrown back at us by the player. This prevents - // hunters from hurting themselves when they walk into their own flechette clusters. - return 0; - } - } - } - - if ( m_EscortBehavior.GetFollowTarget() && m_EscortBehavior.GetFollowTarget() == pAttacker ) - { - return 0; - } - - bool bHitByUnoccupiedCar = false; - if ( ( ( info.GetDamageType() & DMG_CRUSH ) && ( pAttacker && pAttacker->IsPlayer() ) ) || - ( info.GetDamageType() & DMG_VEHICLE ) ) - { - // myInfo, not info! it may have been modified above. - float flDamage = myInfo.GetDamage(); - if ( flDamage < HUNTER_MIN_PHYSICS_DAMAGE ) - { - //DevMsg( "hunter: <<<< ZERO PHYSICS DAMAGE: %f\n", flDamage ); - myInfo.SetDamage( 0 ); - } - else - { - CBaseEntity *pInflictor = info.GetInflictor(); - if ( ( info.GetDamageType() & DMG_VEHICLE ) || - ( pInflictor && pInflictor->GetServerVehicle() && - ( ( bHitByUnoccupiedCar = ( dynamic_cast(pInflictor) && static_cast(pInflictor)->GetDriver() == NULL ) ) == false ) ) ) - { - // Adjust the damage from vehicles. - flDamage *= sk_hunter_vehicle_damage_scale.GetFloat(); - myInfo.SetDamage( flDamage ); - - // Apply a force to jostle the vehicle that hit us. - // Pick a force direction based on which side we're on relative to the vehicle's motion. - Vector vecVelDir = pInflictor->GetSmoothedVelocity(); - if ( vecVelDir.Length() >= hunter_jostle_car_min_speed.GetFloat() ) - { - EmitSound( "NPC_Hunter.HitByVehicle" ); - m_hHitByVehicle = pInflictor; - SetContextThink( &CNPC_Hunter::JostleVehicleThink, gpGlobals->curtime, HUNTER_JOSTLE_VEHICLE_THINK ); - } - } - - if ( !bHitByUnoccupiedCar ) - { - SetCondition( COND_HUNTER_STAGGERED ); - } - } - - //DevMsg( "hunter: >>>> PHYSICS DAMAGE: %f (was %f)\n", flDamage, info.GetDamage() ); - } - - // Show damage effects if we actually took damage. - if ( ( myInfo.GetDamageType() & ( DMG_CRUSH | DMG_BLAST ) ) && ( myInfo.GetDamage() > 0 ) ) - { - if ( !bHitByUnoccupiedCar ) - SetCondition( COND_HUNTER_STAGGERED ); - } - - if ( HasCondition( COND_HUNTER_STAGGERED ) ) - { - // Throw a bunch of gibs out - Vector vecForceDir = -myInfo.GetDamageForce(); - VectorNormalize( vecForceDir ); - PhysicsDamageEffect( myInfo.GetDamagePosition(), vecForceDir ); - - // Stagger away from the direction the damage came from. - m_vecStaggerDir = myInfo.GetDamageForce(); - VectorNormalize( m_vecStaggerDir ); - } - - // Take less damage from citizens and Alyx, otherwise hunters go down too easily. - float flScale = 1.0; - - if ( pAttacker && - ( ( pAttacker->Classify() == CLASS_CITIZEN_REBEL ) || - ( pAttacker->Classify() == CLASS_PLAYER_ALLY ) || - ( pAttacker->Classify() == CLASS_PLAYER_ALLY_VITAL ) ) ) - { - flScale *= sk_hunter_citizen_damage_scale.GetFloat(); - } - - if ( flScale != 0 ) - { - // We're taking a nonzero amount of damage. - - // If we're not staggering, consider flinching! - if ( !HasCondition( COND_HUNTER_STAGGERED ) ) - { - ConsiderFlinching( info ); - } - - if( pAttacker && pAttacker->IsPlayer() ) - { - // This block of code will distract the Hunter back to the player if the - // player does harm to the Hunter but is not the Hunter's current enemy. - // This is achieved by updating the Hunter's enemy memory of the player and - // making the Hunter's current enemy invalid for a short time. - if( !GetEnemy() || !GetEnemy()->IsPlayer() ) - { - UpdateEnemyMemory( pAttacker, pAttacker->GetAbsOrigin(), this ); - - if( GetEnemy() ) - { - // Gotta forget about this person for a little bit. - GetEnemies()->SetTimeValidEnemy( GetEnemy(), gpGlobals->curtime + HUNTER_IGNORE_ENEMY_TIME ); - } - } - } - - float flDamage = myInfo.GetDamage() * flScale; - myInfo.SetDamage( flDamage ); - } - - int nRet = BaseClass::OnTakeDamage_Alive( myInfo ); - - m_EscortBehavior.OnDamage( myInfo ); - - // Spark at 30% health. - if ( !IsBleeding() && ( GetHealth() <= sk_hunter_health.GetInt() * 0.3 ) ) - { - StartBleeding(); - } - - if ( IsUsingSiegeTargets() && info.GetAttacker() != NULL && info.GetAttacker()->IsPlayer() ) - { - // Defend myself. Try to siege attack immediately. - m_flTimeNextSiegeTargetAttack = gpGlobals->curtime; - } - - return nRet; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::Event_Killed( const CTakeDamageInfo &info ) -{ - // Remember the killing blow to make decisions about ragdolling. - m_nKillingDamageType = info.GetDamageType(); - - if ( m_EscortBehavior.GetFollowTarget() ) - { - if ( AIGetNumFollowers( m_EscortBehavior.GetFollowTarget(), m_iClassname ) == 1 ) - { - m_EscortBehavior.GetEscortTarget()->AlertSound(); - if ( info.GetAttacker() && info.GetAttacker()->IsPlayer() ) - { - m_EscortBehavior.GetEscortTarget()->UpdateEnemyMemory( UTIL_GetLocalPlayer(), UTIL_GetLocalPlayer()->GetAbsOrigin(), this ); - } - } - } - - if ( info.GetDamageType() & DMG_VEHICLE ) - { - bool bWasRunDown = false; - int iRundownCounter = 0; - if ( GetSquad() ) - { - if ( !m_IgnoreVehicleTimer.Expired() ) - { - GetSquad()->GetSquadData( HUNTER_RUNDOWN_SQUADDATA, &iRundownCounter ); - GetSquad()->SetSquadData( HUNTER_RUNDOWN_SQUADDATA, iRundownCounter + 1 ); - bWasRunDown = true; - } - } - - if ( hunter_dodge_debug.GetBool() ) - Msg( "Hunter %d was%s run down\n", entindex(), ( bWasRunDown ) ? "" : " not" ); - - // Death by vehicle! Decrement the hunters to run over counter. - // When the counter reaches zero hunters will start dodging. - if ( GlobalEntity_GetCounter( s_iszHuntersToRunOver ) > 0 ) - { - GlobalEntity_AddToCounter( s_iszHuntersToRunOver, -1 ); - } - } - - // Stop all our thinks - SetContextThink( NULL, 0, HUNTER_BLEED_THINK ); - - StopParticleEffects( this ); - - BaseClass::Event_Killed( info ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::StartBleeding() -{ - // Do this even if we're already bleeding (see OnRestore). - m_bIsBleeding = true; - - // Start gushing blood from our... anus or something. - DispatchParticleEffect( "blood_drip_synth_01", PATTACH_POINT_FOLLOW, this, gm_nHeadBottomAttachment ); - - // Emit spurts of our blood - SetContextThink( &CNPC_Hunter::BleedThink, gpGlobals->curtime + 0.1, HUNTER_BLEED_THINK ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -float CNPC_Hunter::MaxYawSpeed() -{ - if ( IsStriderBuster( GetEnemy() ) ) - { - return 60; - } - - if ( GetActivity() == ACT_HUNTER_ANGRY ) - return 0; - - if ( GetActivity() == ACT_HUNTER_CHARGE_RUN ) - return 5; - - if ( GetActivity() == ACT_HUNTER_IDLE_PLANTED ) - return 0; - - if ( GetActivity() == ACT_HUNTER_RANGE_ATTACK2_UNPLANTED ) - return 180; - - switch ( GetActivity() ) - { - case ACT_RANGE_ATTACK2: - { - return 0; - } - - case ACT_90_LEFT: - case ACT_90_RIGHT: - { - return 45; - } - - case ACT_TURN_LEFT: - case ACT_TURN_RIGHT: - { - return 45; - } - - case ACT_WALK: - { - return 25; - } - - default: - { - return 35; - } - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Hunter::IsJumpLegal(const Vector &startPos, const Vector &apex, const Vector &endPos) const -{ - float MAX_JUMP_RISE = 220.0f; - float MAX_JUMP_DISTANCE = 512.0f; - float MAX_JUMP_DROP = 384.0f; - - trace_t tr; - UTIL_TraceHull( startPos, startPos, GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - if ( tr.startsolid ) - { - // Trying to start a jump in solid! Consider checking for this in CAI_MoveProbe::JumpMoveLimit. - Assert( 0 ); - return false; - } - - if ( BaseClass::IsJumpLegal( startPos, apex, endPos, MAX_JUMP_RISE, MAX_JUMP_DROP, MAX_JUMP_DISTANCE ) ) - { - return true; - } - return false; -} - - -//----------------------------------------------------------------------------- -// Let the probe know I can run through small debris -// Stolen shamelessly from the Antlion Guard -//----------------------------------------------------------------------------- -bool CNPC_Hunter::ShouldProbeCollideAgainstEntity( CBaseEntity *pEntity ) -{ - if ( s_iszPhysPropClassname != pEntity->m_iClassname ) - return BaseClass::ShouldProbeCollideAgainstEntity( pEntity ); - - if ( pEntity->GetMoveType() == MOVETYPE_VPHYSICS ) - { - IPhysicsObject *pPhysObj = pEntity->VPhysicsGetObject(); - - if( pPhysObj && pPhysObj->GetMass() <= 500.0f ) - { - return false; - } - } - - return BaseClass::ShouldProbeCollideAgainstEntity( pEntity ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::DoMuzzleFlash( int nAttachment ) -{ - BaseClass::DoMuzzleFlash(); - - DispatchParticleEffect( "hunter_muzzle_flash", PATTACH_POINT_FOLLOW, this, nAttachment ); - - // Dispatch the elight - CEffectData data; - data.m_nAttachmentIndex = nAttachment; - data.m_nEntIndex = entindex(); - DispatchEffect( "HunterMuzzleFlash", data ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Hunter::CountRangedAttackers() -{ - CBaseEntity *pEnemy = GetEnemy(); - if ( !pEnemy ) - { - return 0; - } - - int nAttackers = 0; - for ( int i = 0; i < g_Hunters.Count(); i++ ) - { - CNPC_Hunter *pOtherHunter = g_Hunters[i]; - if ( pOtherHunter->GetEnemy() == pEnemy ) - { - if ( pOtherHunter->IsCurSchedule( SCHED_HUNTER_RANGE_ATTACK2 ) ) - { - nAttackers++; - } - } - } - return nAttackers; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::DelayRangedAttackers( float minDelay, float maxDelay, bool bForced ) -{ - float delayMultiplier = ( g_pGameRules->IsSkillLevel( SKILL_EASY ) ) ? 1.25 : 1.0; - if ( !m_bEnableSquadShootDelay && !bForced ) - { - m_flNextRangeAttack2Time = gpGlobals->curtime + random->RandomFloat( minDelay, maxDelay ) * delayMultiplier; - return; - } - - CBaseEntity *pEnemy = GetEnemy(); - for ( int i = 0; i < g_Hunters.Count(); i++ ) - { - CNPC_Hunter *pOtherHunter = g_Hunters[i]; - if ( pOtherHunter->GetEnemy() == pEnemy ) - { - float nextTime = gpGlobals->curtime + random->RandomFloat( minDelay, maxDelay ) * delayMultiplier; - if ( nextTime > pOtherHunter->m_flNextRangeAttack2Time ) - pOtherHunter->m_flNextRangeAttack2Time = nextTime; - } - } -} - - -//----------------------------------------------------------------------------- -// Given a target to shoot at, decide where to aim. -//----------------------------------------------------------------------------- -void CNPC_Hunter::GetShootDir( Vector &vecDir, const Vector &vecSrc, CBaseEntity *pTargetEntity, bool bStriderBuster, int nShotNum, bool bSingleShot ) -{ - //RestartGesture( ACT_HUNTER_GESTURE_SHOOT ); - - EmitSound( "NPC_Hunter.FlechetteShoot" ); - - Vector vecBodyTarget; - - if( pTargetEntity->Classify() == CLASS_PLAYER_ALLY_VITAL ) - { - // Shooting at Alyx, most likely (in EP2). The attack is designed to displace - // her, not necessarily actually harm her. So shoot at the area around her feet. - vecBodyTarget = pTargetEntity->GetAbsOrigin(); - } - else - { - vecBodyTarget = pTargetEntity->BodyTarget( vecSrc ); - } - - Vector vecTarget = vecBodyTarget; - - Vector vecDelta = pTargetEntity->GetAbsOrigin() - GetAbsOrigin(); - float flDist = vecDelta.Length(); - - if ( !bStriderBuster ) - { - // If we're not firing at a strider buster, miss in an entertaining way for the - // first three shots of each volley. - if ( ( nShotNum < 3 ) && ( flDist > 200 ) ) - { - Vector vecTargetForward; - Vector vecTargetRight; - pTargetEntity->GetVectors( &vecTargetForward, &vecTargetRight, NULL ); - - Vector vecForward; - GetVectors( &vecForward, NULL, NULL ); - - float flDot = DotProduct( vecTargetForward, vecForward ); - - if ( flDot < -0.8f ) - { - // Our target is facing us, shoot the ground between us. - float flPerc = 0.7 + ( 0.1 * nShotNum ); - vecTarget = GetAbsOrigin() + ( flPerc * ( pTargetEntity->GetAbsOrigin() - GetAbsOrigin() ) ); - } - else if ( flDot > 0.8f ) - { - // Our target is facing away from us, shoot to the left or right. - Vector vecMissDir = vecTargetRight; - if ( m_bMissLeft ) - { - vecMissDir *= -1.0f; - } - - vecTarget = pTargetEntity->EyePosition() + ( 36.0f * ( 3 - nShotNum ) ) * vecMissDir; - } - else - { - // Our target is facing vaguely perpendicular to us, shoot across their view. - vecTarget = pTargetEntity->EyePosition() + ( 36.0f * ( 3 - nShotNum ) ) * vecTargetForward; - } - } - // If we can't see them, shoot where we last saw them. - else if ( !HasCondition( COND_SEE_ENEMY ) ) - { - Vector vecDelta = vecTarget - pTargetEntity->GetAbsOrigin(); - vecTarget = m_vecEnemyLastSeen + vecDelta; - } - } - else - { - // If we're firing at a striderbuster, lead it. - float flSpeed = hunter_flechette_speed.GetFloat(); - if ( !flSpeed ) - { - flSpeed = 2500.0f; - } - - flSpeed *= 1.5; - - float flDeltaTime = flDist / flSpeed; - vecTarget = vecTarget + flDeltaTime * pTargetEntity->GetSmoothedVelocity(); - } - - vecDir = vecTarget - vecSrc; - VectorNormalize( vecDir ); -} - - -//----------------------------------------------------------------------------- -// Ensures that we don't exceed our pitch/yaw limits when shooting flechettes. -// Returns true if we had to clamp, false if not. -//----------------------------------------------------------------------------- -bool CNPC_Hunter::ClampShootDir( Vector &vecDir ) -{ - Vector vecDir2D = vecDir; - vecDir2D.z = 0; - - Vector vecForward; - GetVectors( &vecForward, NULL, NULL ); - - Vector vecForward2D = vecForward; - vecForward2D.z = 0; - - float flDot = DotProduct( vecForward2D, vecDir2D ); - if ( flDot >= HUNTER_SHOOT_MAX_YAW_COS ) - { - // No need to clamp. - return false; - } - - Vector vecAxis; - CrossProduct( vecDir, vecForward, vecAxis ); - VectorNormalize( vecAxis ); - - Quaternion q; - AxisAngleQuaternion( vecAxis, -HUNTER_SHOOT_MAX_YAW_DEG, q ); - - matrix3x4_t rot; - QuaternionMatrix( q, rot ); - VectorRotate( vecForward, rot, vecDir ); - VectorNormalize( vecDir ); - - return true; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Hunter::ShouldSeekTarget( CBaseEntity *pTargetEntity, bool bStriderBuster ) -{ - bool bSeek = false; - - if ( bStriderBuster ) - { - bool bSeek = false; - - if ( pTargetEntity->VPhysicsGetObject() && ( pTargetEntity->VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) ) - { - bSeek = true; - } - else if ( StriderBuster_NumFlechettesAttached( pTargetEntity ) == 0 ) - { - if ( StriderBuster_IsAttachedStriderBuster(pTargetEntity) ) - { - bSeek = true; - } - else if ( hunter_seek_thrown_striderbusters_tolerance.GetFloat() > 0.0 ) - { - CNPC_Strider *pEscortTarget = m_EscortBehavior.GetEscortTarget(); - if ( pEscortTarget && ( pEscortTarget->GetAbsOrigin() - pTargetEntity->GetAbsOrigin() ).LengthSqr() < Square( hunter_seek_thrown_striderbusters_tolerance.GetFloat() ) ) - { - bSeek = true; - } - } - } - } - - return bSeek; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::BeginVolley( int nNum, float flStartTime ) -{ - m_nFlechettesQueued = nNum; - m_nClampedShots = 0; - m_flNextFlechetteTime = flStartTime; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Hunter::ShootFlechette( CBaseEntity *pTargetEntity, bool bSingleShot ) -{ - if ( !pTargetEntity ) - { - Assert( false ); - return false; - } - - int nShotNum = hunter_flechette_volley_size.GetInt() - m_nFlechettesQueued; - - bool bStriderBuster = IsStriderBuster( pTargetEntity ); - - // Choose the next muzzle to shoot from. - Vector vecSrc; - QAngle angMuzzle; - - if ( m_bTopMuzzle ) - { - GetAttachment( gm_nTopGunAttachment, vecSrc, angMuzzle ); - DoMuzzleFlash( gm_nTopGunAttachment ); - } - else - { - GetAttachment( gm_nBottomGunAttachment, vecSrc, angMuzzle ); - DoMuzzleFlash( gm_nBottomGunAttachment ); - } - - m_bTopMuzzle = !m_bTopMuzzle; - - Vector vecDir; - GetShootDir( vecDir, vecSrc, pTargetEntity, bStriderBuster, nShotNum, bSingleShot ); - - bool bClamped = false; - if ( hunter_clamp_shots.GetBool() ) - { - bClamped = ClampShootDir( vecDir ); - } - - CShotManipulator manipulator( vecDir ); - Vector vecShoot; - - if( IsUsingSiegeTargets() && nShotNum >= 2 && (nShotNum % 2) == 0 ) - { - // Near perfect accuracy for these three shots, so they are likely to fly right into the windows. - // NOTE! In siege behavior in the map that this behavior was designed for (ep2_outland_10), the - // Hunters will only ever shoot at siege targets in siege mode. If you allow Hunters in siege mode - // to attack players or other NPCs, this accuracy bonus will apply unless we apply a bit more logic to it. - vecShoot = manipulator.ApplySpread( VECTOR_CONE_1DEGREES * 0.5, 1.0f ); - } - else - { - vecShoot = manipulator.ApplySpread( VECTOR_CONE_4DEGREES, 1.0f ); - } - - QAngle angShoot; - VectorAngles( vecShoot, angShoot ); - - CHunterFlechette *pFlechette = CHunterFlechette::FlechetteCreate( vecSrc, angShoot, this ); - - pFlechette->AddEffects( EF_NOSHADOW ); - - vecShoot *= hunter_flechette_speed.GetFloat(); - - pFlechette->Shoot( vecShoot, bStriderBuster ); - - if ( ShouldSeekTarget( pTargetEntity, bStriderBuster ) ) - { - pFlechette->SetSeekTarget( pTargetEntity ); - } - - if( nShotNum == 1 && pTargetEntity->Classify() == CLASS_PLAYER_ALLY_VITAL ) - { - // Make this person afraid and react to ME, not to the flechettes. - // Otherwise they could be scared into running towards the hunter. - CSoundEnt::InsertSound( SOUND_DANGER|SOUND_CONTEXT_REACT_TO_SOURCE|SOUND_CONTEXT_EXCLUDE_COMBINE, pTargetEntity->EyePosition(), 180, 2.0f, this ); - } - - return bClamped; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Vector CNPC_Hunter::LeftFootHit( float eventtime ) -{ - Vector footPosition; - - GetAttachment( "left foot", footPosition ); - CPASAttenuationFilter filter( this ); - EmitSound( filter, entindex(), "NPC_Hunter.Footstep", &footPosition, eventtime ); - - FootFX( footPosition ); - - return footPosition; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Vector CNPC_Hunter::RightFootHit( float eventtime ) -{ - Vector footPosition; - - GetAttachment( "right foot", footPosition ); - CPASAttenuationFilter filter( this ); - EmitSound( filter, entindex(), "NPC_Hunter.Footstep", &footPosition, eventtime ); - FootFX( footPosition ); - - return footPosition; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Vector CNPC_Hunter::BackFootHit( float eventtime ) -{ - Vector footPosition; - - GetAttachment( "back foot", footPosition ); - CPASAttenuationFilter filter( this ); - EmitSound( filter, entindex(), "NPC_Hunter.BackFootstep", &footPosition, eventtime ); - FootFX( footPosition ); - - return footPosition; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::FootFX( const Vector &origin ) -{ - return; - - // dvs TODO: foot dust? probably too expensive for these guys - /*trace_t tr; - AI_TraceLine( origin, origin - Vector(0,0,100), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - float yaw = random->RandomInt(0,120); - for ( int i = 0; i < 3; i++ ) - { - Vector dir = UTIL_YawToVector( yaw + i*120 ) * 10; - VectorNormalize( dir ); - dir.z = 0.25; - VectorNormalize( dir ); - g_pEffects->Dust( tr.endpos, dir, 12, 50 ); - }*/ -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CBaseEntity *CNPC_Hunter::GetEnemyVehicle() -{ - if ( GetEnemy() == NULL ) - return false; - - CBaseCombatCharacter *pCCEnemy = GetEnemy()->MyCombatCharacterPointer(); - if ( pCCEnemy != NULL ) - return pCCEnemy->GetVehicleEntity(); - - return false; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::DrawDebugGeometryOverlays() -{ - if (m_debugOverlays & OVERLAY_BBOX_BIT) - { - float flViewRange = acos(0.8); - Vector vEyeDir = EyeDirection2D( ); - Vector vLeftDir, vRightDir; - float fSin, fCos; - SinCos( flViewRange, &fSin, &fCos ); - - vLeftDir.x = vEyeDir.x * fCos - vEyeDir.y * fSin; - vLeftDir.y = vEyeDir.x * fSin + vEyeDir.y * fCos; - vLeftDir.z = vEyeDir.z; - fSin = sin(-flViewRange); - fCos = cos(-flViewRange); - vRightDir.x = vEyeDir.x * fCos - vEyeDir.y * fSin; - vRightDir.y = vEyeDir.x * fSin + vEyeDir.y * fCos; - vRightDir.z = vEyeDir.z; - - int nSeq = GetSequence(); - if ( ( GetEntryNode( nSeq ) == gm_nPlantedNode ) && ( GetExitNode( nSeq ) == gm_nPlantedNode ) ) - { - // planted - green - NDebugOverlay::Box( GetAbsOrigin(), GetHullMins(), GetHullMaxs(), 0, 255, 0, 128, 0 ); - } - else if ( ( GetEntryNode( nSeq ) == gm_nUnplantedNode ) && ( GetExitNode( nSeq ) == gm_nUnplantedNode ) ) - { - // unplanted - blue - NDebugOverlay::Box( GetAbsOrigin(), GetHullMins(), GetHullMaxs(), 0, 0, 255, 128, 0 ); - } - else if ( ( GetEntryNode( nSeq ) == gm_nUnplantedNode ) && ( GetExitNode( nSeq ) == gm_nPlantedNode ) ) - { - // planting transition - cyan - NDebugOverlay::Box( GetAbsOrigin(), GetHullMins(), GetHullMaxs(), 0, 255, 255, 128, 0 ); - } - else if ( ( GetEntryNode( nSeq ) == gm_nPlantedNode ) && ( GetExitNode( nSeq ) == gm_nUnplantedNode ) ) - { - // unplanting transition - purple - NDebugOverlay::Box( GetAbsOrigin(), GetHullMins(), GetHullMaxs(), 255, 0, 255, 128, 0 ); - } - else - { - // unknown / other node - red - Msg( "UNKNOWN: %s\n", GetSequenceName( GetSequence() ) ); - NDebugOverlay::Box( GetAbsOrigin(), GetHullMins(), GetHullMaxs(), 255, 0, 0, 128, 0 ); - } - - NDebugOverlay::BoxDirection(EyePosition(), Vector(0,0,-1), Vector(200,0,1), vLeftDir, 255, 0, 0, 50, 0 ); - NDebugOverlay::BoxDirection(EyePosition(), Vector(0,0,-1), Vector(200,0,1), vRightDir, 255, 0, 0, 50, 0 ); - NDebugOverlay::BoxDirection(EyePosition(), Vector(0,0,-1), Vector(200,0,1), vEyeDir, 0, 255, 0, 50, 0 ); - NDebugOverlay::Box(EyePosition(), -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, 128, 0 ); - } - - m_EscortBehavior.DrawDebugGeometryOverlays(); - - BaseClass::DrawDebugGeometryOverlays(); -} - - -//----------------------------------------------------------------------------- -// Player has illuminated this NPC with the flashlight -//----------------------------------------------------------------------------- -void CNPC_Hunter::PlayerHasIlluminatedNPC( CBasePlayer *pPlayer, float flDot ) -{ - if ( m_bFlashlightInEyes ) - return; - - // Ignore the flashlight if it's not shining at my eyes - if ( PlayerFlashlightOnMyEyes( pPlayer ) ) - { - //Msg( ">>>> SHINING FLASHLIGHT ON ME\n" ); - m_bFlashlightInEyes = true; - SetExpression( "scenes/npc/hunter/hunter_eyeclose.vcd" ); - m_flPupilDilateTime = gpGlobals->curtime + 0.2f; - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Hunter::PlayerFlashlightOnMyEyes( CBasePlayer *pPlayer ) -{ - Vector vecEyes, vecEyeForward, vecPlayerForward; - GetAttachment( gm_nTopGunAttachment, vecEyes, &vecEyeForward ); - pPlayer->EyeVectors( &vecPlayerForward ); - - Vector vecToEyes = (vecEyes - pPlayer->EyePosition()); - //float flDist = VectorNormalize( vecToEyes ); - - float flDot = DotProduct( vecPlayerForward, vecToEyes ); - if ( flDot < 0.98 ) - return false; - - // Check facing to ensure we're in front of her - Vector los = ( pPlayer->EyePosition() - EyePosition() ); - los.z = 0; - VectorNormalize( los ); - Vector facingDir = EyeDirection2D(); - flDot = DotProduct( los, facingDir ); - return ( flDot > 0.3 ); -} - - -//----------------------------------------------------------------------------- -// Return a random expression for the specified state to play over -// the state's expression loop. -//----------------------------------------------------------------------------- -const char *CNPC_Hunter::SelectRandomExpressionForState( NPC_STATE state ) -{ - if ( m_bFlashlightInEyes ) - return NULL; - - if ( !hunter_random_expressions.GetBool() ) - return NULL; - - const char *szExpressions[4] = - { - "scenes/npc/hunter/hunter_scan.vcd", - "scenes/npc/hunter/hunter_eyeclose.vcd", - "scenes/npc/hunter/hunter_roar.vcd", - "scenes/npc/hunter/hunter_pain.vcd" - }; - - int nIndex = random->RandomInt( 0, 3 ); - //Msg( "RANDOM Expression: %s\n", szExpressions[nIndex] ); - return szExpressions[nIndex]; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::PlayExpressionForState( NPC_STATE state ) -{ - if ( m_bFlashlightInEyes ) - { - return; - } - - BaseClass::PlayExpressionForState( state ); -} - - -//----------------------------------------------------------------------------- -// TODO: remove if we're not doing striderbuster stuff -//----------------------------------------------------------------------------- -void CNPC_Hunter::StriderBusterAttached( CBaseEntity *pAttached ) -{ - // Add another to the list - m_hAttachedBusters.AddToTail( pAttached ); - - SetCondition( COND_HUNTER_HIT_BY_STICKYBOMB ); - if (m_hAttachedBusters.Count() == 1) - { - EmitSound( "NPC_Hunter.Alert" ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::StriderBusterDetached( CBaseEntity *pAttached ) -{ - int elem = m_hAttachedBusters.Find(pAttached); - if (elem >= 0) - { - m_hAttachedBusters.FastRemove(elem); - } -} - - -//----------------------------------------------------------------------------- -// Set direction that the hunter aims his body and eyes (guns). -//----------------------------------------------------------------------------- -void CNPC_Hunter::SetAim( const Vector &aimDir, float flInterval ) -{ - QAngle angDir; - VectorAngles( aimDir, angDir ); - float curPitch = GetPoseParameter( gm_nBodyPitchPoseParam ); - float curYaw = GetPoseParameter( gm_nBodyYawPoseParam ); - - float newPitch; - float newYaw; - - if ( GetEnemy() ) - { - // clamp and dampen movement - newPitch = curPitch + 0.8 * UTIL_AngleDiff( UTIL_ApproachAngle( angDir.x, curPitch, 20 ), curPitch ); - - float flRelativeYaw = UTIL_AngleDiff( angDir.y, GetAbsAngles().y ); - newYaw = curYaw + UTIL_AngleDiff( flRelativeYaw, curYaw ); - } - else - { - // Sweep your weapon more slowly if you're not fighting someone - newPitch = curPitch + 0.6 * UTIL_AngleDiff( UTIL_ApproachAngle( angDir.x, curPitch, 20 ), curPitch ); - - float flRelativeYaw = UTIL_AngleDiff( angDir.y, GetAbsAngles().y ); - newYaw = curYaw + 0.6 * UTIL_AngleDiff( flRelativeYaw, curYaw ); - } - - newPitch = AngleNormalize( newPitch ); - newYaw = AngleNormalize( newYaw ); - - //Msg( "pitch=%f, yaw=%f\n", newPitch, newYaw ); - - SetPoseParameter( gm_nAimPitchPoseParam, 0 ); - SetPoseParameter( gm_nAimYawPoseParam, 0 ); - - SetPoseParameter( gm_nBodyPitchPoseParam, clamp( newPitch, -45, 45 ) ); - SetPoseParameter( gm_nBodyYawPoseParam, clamp( newYaw, -45, 45 ) ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::RelaxAim( float flInterval ) -{ - float curPitch = GetPoseParameter( gm_nBodyPitchPoseParam ); - float curYaw = GetPoseParameter( gm_nBodyYawPoseParam ); - - // dampen existing aim - float newPitch = AngleNormalize( UTIL_ApproachAngle( 0, curPitch, 3 ) ); - float newYaw = AngleNormalize( UTIL_ApproachAngle( 0, curYaw, 2 ) ); - - SetPoseParameter( gm_nAimPitchPoseParam, 0 ); - SetPoseParameter( gm_nAimYawPoseParam, 0 ); - - SetPoseParameter( gm_nBodyPitchPoseParam, clamp( newPitch, -45, 45 ) ); - SetPoseParameter( gm_nBodyYawPoseParam, clamp( newYaw, -45, 45 ) ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Hunter::UpdateAim() -{ - if ( !GetModelPtr() || !GetModelPtr()->SequencesAvailable() ) - return; - - float flInterval = GetAnimTimeInterval(); - - // Some activities look bad if we're giving our enemy the stinkeye. - int eActivity = GetActivity(); - - if ( GetEnemy() && - GetState() != NPC_STATE_SCRIPT && - ( eActivity != ACT_HUNTER_CHARGE_CRASH ) && - ( eActivity != ACT_HUNTER_CHARGE_HIT ) ) - { - Vector vecShootOrigin; - - vecShootOrigin = Weapon_ShootPosition(); - Vector vecShootDir = GetShootEnemyDir( vecShootOrigin, false ); - - SetAim( vecShootDir, flInterval ); - } - else - { - RelaxAim( flInterval ); - } -} - - -//----------------------------------------------------------------------------- -// Don't become a ragdoll until we've finished our death anim -//----------------------------------------------------------------------------- -bool CNPC_Hunter::CanBecomeRagdoll() -{ - return ( m_nKillingDamageType & DMG_CRUSH ) || - IsCurSchedule( SCHED_DIE, false ) || // Finished playing death anim, time to ragdoll - IsCurSchedule( SCHED_HUNTER_CHARGE_ENEMY, false ) || // While moving, it looks better to ragdoll instantly - IsCurSchedule( SCHED_SCRIPTED_RUN, false ) || - ( GetActivity() == ACT_WALK ) || ( GetActivity() == ACT_RUN ) || - GetCurSchedule() == NULL; // Failsafe -} - - -//----------------------------------------------------------------------------- -// Determines the best type of death anim to play based on how we died. -//----------------------------------------------------------------------------- -Activity CNPC_Hunter::GetDeathActivity() -{ - return ACT_DIESIMPLE; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_HunterEscortBehavior::OnDamage( const CTakeDamageInfo &info ) -{ - if ( info.GetDamage() > 0 && info.GetAttacker()->IsPlayer() && - GetFollowTarget() && ( AIGetNumFollowers( GetFollowTarget() ) > 1 ) && - ( GetOuter()->GetSquad()->GetSquadSoundWaitTime() <= gpGlobals->curtime ) ) // && !FarFromFollowTarget() - { - // Start the clock ticking. We'll return the the strider when the timer elapses. - m_flTimeEscortReturn = gpGlobals->curtime + random->RandomFloat( 15.0f, 25.0f ); - GetOuter()->GetSquad()->SetSquadSoundWaitTime( m_flTimeEscortReturn + 1.0 ); // prevent others from breaking escort - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_HunterEscortBehavior::BuildScheduleTestBits() -{ - BaseClass::BuildScheduleTestBits(); - - if ( ( m_flTimeEscortReturn != 0 ) && ( gpGlobals->curtime > m_flTimeEscortReturn ) ) - { - // We're delinquent! Return to strider! - GetOuter()->ClearCustomInterruptCondition( COND_NEW_ENEMY ); - GetOuter()->ClearCustomInterruptCondition( COND_SEE_ENEMY ); - GetOuter()->ClearCustomInterruptCondition( COND_SEE_HATE ); - GetOuter()->ClearCustomInterruptCondition( COND_CAN_RANGE_ATTACK1 ); - GetOuter()->ClearCustomInterruptCondition( COND_CAN_RANGE_ATTACK2 ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_HunterEscortBehavior::CheckBreakEscort() -{ - if ( m_flTimeEscortReturn != 0 && ( FarFromFollowTarget() || gpGlobals->curtime >= m_flTimeEscortReturn ) ) - { - if ( FarFromFollowTarget() ) - { - m_flTimeEscortReturn = gpGlobals->curtime; - } - else - { - m_flTimeEscortReturn = 0; - } - if ( GetOuter()->GetSquad() ) - { - GetOuter()->GetSquad()->SetSquadSoundWaitTime( gpGlobals->curtime + random->RandomFloat( 5.0f, 12.0f ) ); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_HunterEscortBehavior::GatherConditionsNotActive( void ) -{ - if ( m_bEnabled ) - { - DistributeFreeHunters(); - } - - BaseClass::GatherConditionsNotActive(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_HunterEscortBehavior::GatherConditions( void ) -{ - m_bEnabled = true; - - DistributeFreeHunters(); - - BaseClass::GatherConditions(); - - if ( GetEnemy() && GetEnemy()->IsPlayer() && HasCondition( COND_SEE_ENEMY ) ) - { - if ( GetOuter()->GetSquad()->GetSquadSoundWaitTime() <= gpGlobals->curtime && ((CBasePlayer *)GetEnemy())->IsInAVehicle() ) - { - m_flTimeEscortReturn = gpGlobals->curtime + random->RandomFloat( 15.0f, 25.0f ); - GetOuter()->GetSquad()->SetSquadSoundWaitTime( m_flTimeEscortReturn + 1.0 ); // prevent others from breaking escort - } - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CAI_HunterEscortBehavior::ShouldFollow() -{ - if ( IsStriderBuster( GetEnemy() ) ) - return false; - - if ( HasCondition( COND_HEAR_PHYSICS_DANGER ) ) - return false; - - if ( m_flTimeEscortReturn <= gpGlobals->curtime ) - { - return CAI_FollowBehavior::ShouldFollow(); - } - - return false; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_HunterEscortBehavior::BeginScheduleSelection() -{ - BaseClass::BeginScheduleSelection(); - Assert( m_SavedDistTooFar == GetOuter()->m_flDistTooFar ); - GetOuter()->m_flDistTooFar *= 2; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CAI_HunterEscortBehavior::SelectSchedule() -{ - if( m_FollowDelay.IsRunning() && !m_FollowDelay.Expired() ) - { - return FollowCallBaseSelectSchedule(); - } - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CAI_HunterEscortBehavior::FollowCallBaseSelectSchedule() -{ - if ( GetOuter()->GetState() == NPC_STATE_COMBAT ) - { - return GetOuter()->SelectCombatSchedule(); - } - - return BaseClass::FollowCallBaseSelectSchedule(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_HunterEscortBehavior::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_MOVE_TO_FOLLOW_POSITION: - { - if ( GetEnemy() ) - { - if ( GetOuter()->OccupyStrategySlot( SQUAD_SLOT_RUN_SHOOT ) ) - { - if ( GetOuter()->GetSquad()->GetSquadMemberNearestTo( GetEnemy()->GetAbsOrigin() ) == GetOuter() ) - { - GetOuter()->BeginVolley( NUM_FLECHETTE_VOLLEY_ON_FOLLOW, gpGlobals->curtime + 1.0 + random->RandomFloat( 0, .25 ) + random->RandomFloat( 0, .25 ) ); - } - else - { - GetOuter()->VacateStrategySlot(); - } - } - } - BaseClass::StartTask( pTask ); - break; - } - - default: - BaseClass::StartTask( pTask ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_HunterEscortBehavior::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_MOVE_TO_FOLLOW_POSITION: - { - if ( !GetFollowTarget() ) - { - TaskFail( FAIL_NO_TARGET ); - } - else - { - if ( GetEnemy() ) - { - CNPC_Hunter *pHunter = GetOuter(); - Vector vecEnemyLKP = pHunter->GetEnemyLKP(); - pHunter->AddFacingTarget( pHunter->GetEnemy(), vecEnemyLKP, 1.0, 0.8 ); - bool bVacate = false; - - bool bHasSlot = pHunter->HasStrategySlot( SQUAD_SLOT_RUN_SHOOT ); - if ( HasCondition( COND_SEE_ENEMY ) ) - { - float maxDist = hunter_flechette_max_range.GetFloat() * 3; - float distSq = ( pHunter->GetAbsOrigin() - pHunter->GetEnemy()->GetAbsOrigin() ).Length2DSqr(); - - if ( distSq < Square( maxDist ) ) - { - if ( gpGlobals->curtime >= pHunter->m_flNextFlechetteTime ) - { - if ( !bHasSlot ) - { - if ( GetOuter()->OccupyStrategySlot( SQUAD_SLOT_RUN_SHOOT ) ) - { - if ( GetOuter()->GetSquad()->GetSquadMemberNearestTo( GetEnemy()->GetAbsOrigin() ) == GetOuter() ) - { - bHasSlot = true; - } - else - { - GetOuter()->VacateStrategySlot(); - } - } - } - - if ( bHasSlot ) - { - // Start the firing sound. - //CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - //if ( controller.SoundGetVolume( pHunter->m_pGunFiringSound ) == 0.0f ) - //{ - // controller.SoundChangeVolume( pHunter->m_pGunFiringSound, 1.0f, 0.0f ); - //} - - pHunter->ShootFlechette( GetEnemy(), true ); - - if ( --pHunter->m_nFlechettesQueued > 0 ) - { - pHunter->m_flNextFlechetteTime = gpGlobals->curtime + hunter_flechette_delay.GetFloat(); - } - else - { - // Stop the firing sound. - //CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - //controller.SoundChangeVolume( pHunter->m_pGunFiringSound, 0, 0.01f ); - - bVacate = true; - pHunter->BeginVolley( NUM_FLECHETTE_VOLLEY_ON_FOLLOW, gpGlobals->curtime + 1.0 + random->RandomFloat( 0, .25 ) + random->RandomFloat( 0, .25 ) ); - } - } - } - } - else if ( bHasSlot ) - { - bVacate = true; - } - } - else if ( bHasSlot ) - { - bVacate = true; - } - - if ( bVacate ) - { - pHunter->VacateStrategySlot(); - } - } - - if ( m_FollowAttackTimer.Expired() && IsFollowTargetInRange( .8 )) - { - m_FollowAttackTimer.Set( 8, 24 ); - TaskComplete(); - } - else - { - BaseClass::RunTask( pTask ); - } - } - break; - } - - default: - BaseClass::RunTask( pTask ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_HunterEscortBehavior::FindFreeHunters( CUtlVector *pFreeHunters ) -{ - pFreeHunters->EnsureCapacity( g_Hunters.Count() ); - int i; - - for ( i = 0; i < g_Hunters.Count(); i++ ) - { - CNPC_Hunter *pHunter = g_Hunters[i]; - if ( pHunter->IsAlive() && pHunter->m_EscortBehavior.m_bEnabled ) - { - if ( pHunter->m_EscortBehavior.GetFollowTarget() == NULL || !pHunter->m_EscortBehavior.GetFollowTarget()->IsAlive() ) - { - pFreeHunters->AddToTail( pHunter); - } - } - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_HunterEscortBehavior::DistributeFreeHunters() -{ - if ( g_TimeLastDistributeFreeHunters != -1 && gpGlobals->curtime - g_TimeLastDistributeFreeHunters < FREE_HUNTER_DISTRIBUTE_INTERVAL ) - { - return; - } - - g_TimeLastDistributeFreeHunters = gpGlobals->curtime; - - CUtlVector freeHunters; - int i; - FindFreeHunters( &freeHunters ); - - CAI_BaseNPC **ppNPCs = g_AI_Manager.AccessAIs(); - for ( i = 0; i < g_AI_Manager.NumAIs() && freeHunters.Count(); i++ ) - { - int nToAdd; - CNPC_Strider *pStrider = ( ppNPCs[i]->IsAlive() ) ? dynamic_cast( ppNPCs[i] ) : NULL; - if ( pStrider && !pStrider->CarriedByDropship() ) - { - if ( ( nToAdd = 3 - AIGetNumFollowers( pStrider ) ) > 0 ) - { - for ( int j = freeHunters.Count() - 1; j >= 0 && nToAdd > 0; --j ) - { - DevMsg( "npc_hunter %d assigned to npc_strider %d\n", freeHunters[j]->entindex(), pStrider->entindex() ); - freeHunters[j]->FollowStrider( pStrider ); - freeHunters.FastRemove( j ); - nToAdd--; - } - } - } - } - - for ( i = 0; i < freeHunters.Count(); i++ ) - { - //DevMsg( "npc_hunter %d assigned to free_hunters_squad\n", freeHunters[i]->entindex() ); - freeHunters[i]->m_EscortBehavior.SetFollowTarget( NULL ); - freeHunters[i]->AddToSquad( AllocPooledString( "free_hunters_squad" ) ); - } - -#if 0 - CBaseEntity *pHunterMaker = gEntList.FindEntityByClassname( NULL, "npc_hunter_maker" ); // TODO: this picks the same one every time! - if ( pHunterMaker ) - { - for ( i = 0; i < freeHunters.Count(); i++ ) - { - freeHunters[i]->m_EscortBehavior.SetFollowTarget( pHunterMaker ); - } - } -#endif -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_HunterEscortBehavior::DrawDebugGeometryOverlays() -{ - if ( !GetFollowTarget() ) - return; - - Vector vecFollowPos = GetGoalPosition(); - if ( FarFromFollowTarget() ) - { - if ( gpGlobals->curtime >= m_flTimeEscortReturn ) - { - NDebugOverlay::HorzArrow( GetOuter()->GetAbsOrigin(), vecFollowPos, 16.0f, 255, 0, 0, 0, true, 0 ); - } - else - { - NDebugOverlay::HorzArrow( GetOuter()->GetAbsOrigin(), vecFollowPos, 16.0f, 255, 255, 0, 0, true, 0 ); - } - } - else - { - NDebugOverlay::HorzArrow( GetOuter()->GetAbsOrigin(), vecFollowPos, 16.0f, 0, 255, 0, 0, true, 0 ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool Hunter_IsHunter(CBaseEntity *pEnt) -{ - return dynamic_cast(pEnt) != NULL; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void Hunter_StriderBusterLaunched( CBaseEntity *pBuster ) -{ - CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); - int nAIs = g_AI_Manager.NumAIs(); - - for ( int i = 0; i < nAIs; i++ ) - { - CAI_BaseNPC *pNPC = ppAIs[ i ]; - if ( pNPC && ( pNPC->Classify() == CLASS_COMBINE_HUNTER ) && pNPC->m_lifeState == LIFE_ALIVE ) - { - if ( !pNPC->GetEnemy() || !IsStriderBuster( pNPC->GetEnemy() ) ) - { - Vector vecDelta = pNPC->GetAbsOrigin() - pBuster->GetAbsOrigin(); - if ( vecDelta.Length2DSqr() < 9437184.0f ) // 3072 * 3072 - { - pNPC->SetEnemy( pBuster ); - pNPC->SetState( NPC_STATE_COMBAT ); - pNPC->UpdateEnemyMemory( pBuster, pBuster->GetAbsOrigin() ); - - // Stop whatever we're doing. - pNPC->SetCondition( COND_SCHEDULE_DONE ); - } - } - } - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void Hunter_StriderBusterAttached( CBaseEntity *pHunter, CBaseEntity *pAttached ) -{ - Assert(dynamic_cast(pHunter)); - - static_cast(pHunter)->StriderBusterAttached(pAttached); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void Hunter_StriderBusterDetached( CBaseEntity *pHunter, CBaseEntity *pAttached ) -{ - Assert(dynamic_cast(pHunter)); - - static_cast(pHunter)->StriderBusterDetached(pAttached); -} - -//------------------------------------------------------------------------------------------------- -// -// ep2_outland_12 custom npc makers -// -//------------------------------------------------------------------------------------------------- - -class CHunterMaker : public CTemplateNPCMaker -{ - typedef CTemplateNPCMaker BaseClass; -public: - void MakeMultipleNPCS( int nNPCs ) - { - const float MIN_HEALTH_PCT = 0.2; - - CUtlVector candidates; - CUtlVectorFixed freeHunters; - CAI_HunterEscortBehavior::FindFreeHunters( &candidates ); - - freeHunters.EnsureCapacity( 3 ); - int i; - - for ( i = 0; i < candidates.Count() && freeHunters.Count() < 3; i++ ) - { - if ( candidates[i]->GetHealth() > candidates[i]->GetMaxHealth() * MIN_HEALTH_PCT ) - { - freeHunters.AddToTail( candidates[i] ); - } - } - - int nRequested = nNPCs; - if ( nNPCs < 3 ) - { - nNPCs = MIN( 3, nNPCs + freeHunters.Count() ); - } - - int nSummoned = 0; - for ( i = 0; i < freeHunters.Count() && nNPCs; i++ ) - { - freeHunters[i]->m_EscortBehavior.SetFollowTarget( this ); // this will make them not "free" - freeHunters[i]->SetName( m_iszTemplateName ); // this will force the hunter to get the FollowStrider input - nNPCs--; - nSummoned++; - } - - DevMsg( "Requested %d to spawn, Summoning %d free hunters, spawning %d new hunters\n", nRequested, nSummoned, nNPCs ); - if ( nNPCs ) - { - BaseClass::MakeMultipleNPCS( nNPCs ); - } - } -}; - -LINK_ENTITY_TO_CLASS( npc_hunter_maker, CHunterMaker ); - - -//------------------------------------------------------------------------------------------------- -// -// Schedules -// -//------------------------------------------------------------------------------------------------- -AI_BEGIN_CUSTOM_NPC( npc_hunter, CNPC_Hunter ) - - DECLARE_TASK( TASK_HUNTER_AIM ) - DECLARE_TASK( TASK_HUNTER_FIND_DODGE_POSITION ) - DECLARE_TASK( TASK_HUNTER_DODGE ) - DECLARE_TASK( TASK_HUNTER_PRE_RANGE_ATTACK2 ) - DECLARE_TASK( TASK_HUNTER_SHOOT_COMMIT ) - DECLARE_TASK( TASK_HUNTER_ANNOUNCE_FLANK ) - DECLARE_TASK( TASK_HUNTER_BEGIN_FLANK ) - DECLARE_TASK( TASK_HUNTER_STAGGER ) - DECLARE_TASK( TASK_HUNTER_CORNERED_TIMER ) - DECLARE_TASK( TASK_HUNTER_FIND_SIDESTEP_POSITION ) - DECLARE_TASK( TASK_HUNTER_CHARGE ) - DECLARE_TASK( TASK_HUNTER_FINISH_RANGE_ATTACK ) - DECLARE_TASK( TASK_HUNTER_WAIT_FOR_MOVEMENT_FACING_ENEMY ) - DECLARE_TASK( TASK_HUNTER_CHARGE_DELAY ) - - DECLARE_ACTIVITY( ACT_HUNTER_DEPLOYRA2 ) - DECLARE_ACTIVITY( ACT_HUNTER_DODGER ) - DECLARE_ACTIVITY( ACT_HUNTER_DODGEL ) - DECLARE_ACTIVITY( ACT_HUNTER_GESTURE_SHOOT ) - DECLARE_ACTIVITY( ACT_HUNTER_FLINCH_STICKYBOMB ) - DECLARE_ACTIVITY( ACT_HUNTER_STAGGER ) - DECLARE_ACTIVITY( ACT_DI_HUNTER_MELEE ) - DECLARE_ACTIVITY( ACT_DI_HUNTER_THROW ) - DECLARE_ACTIVITY( ACT_HUNTER_MELEE_ATTACK1_VS_PLAYER ) - DECLARE_ACTIVITY( ACT_HUNTER_ANGRY ) - DECLARE_ACTIVITY( ACT_HUNTER_WALK_ANGRY ) - DECLARE_ACTIVITY( ACT_HUNTER_FOUND_ENEMY ) - DECLARE_ACTIVITY( ACT_HUNTER_FOUND_ENEMY_ACK ) - DECLARE_ACTIVITY( ACT_HUNTER_CHARGE_START ) - DECLARE_ACTIVITY( ACT_HUNTER_CHARGE_RUN ) - DECLARE_ACTIVITY( ACT_HUNTER_CHARGE_STOP ) - DECLARE_ACTIVITY( ACT_HUNTER_CHARGE_CRASH ) - DECLARE_ACTIVITY( ACT_HUNTER_CHARGE_HIT ) - DECLARE_ACTIVITY( ACT_HUNTER_RANGE_ATTACK2_UNPLANTED ) - DECLARE_ACTIVITY( ACT_HUNTER_IDLE_PLANTED ) - DECLARE_ACTIVITY( ACT_HUNTER_FLINCH_N ) - DECLARE_ACTIVITY( ACT_HUNTER_FLINCH_S ) - DECLARE_ACTIVITY( ACT_HUNTER_FLINCH_E ) - DECLARE_ACTIVITY( ACT_HUNTER_FLINCH_W ) - - DECLARE_INTERACTION( g_interactionHunterFoundEnemy ); - - DECLARE_SQUADSLOT( SQUAD_SLOT_HUNTER_CHARGE ) - DECLARE_SQUADSLOT( SQUAD_SLOT_HUNTER_FLANK_FIRST ) - DECLARE_SQUADSLOT( SQUAD_SLOT_RUN_SHOOT ) - - DECLARE_CONDITION( COND_HUNTER_SHOULD_PATROL ) - DECLARE_CONDITION( COND_HUNTER_FORCED_FLANK_ENEMY ) - DECLARE_CONDITION( COND_HUNTER_CAN_CHARGE_ENEMY ) - DECLARE_CONDITION( COND_HUNTER_STAGGERED ) - DECLARE_CONDITION( COND_HUNTER_IS_INDOORS ) - DECLARE_CONDITION( COND_HUNTER_HIT_BY_STICKYBOMB ) - DECLARE_CONDITION( COND_HUNTER_SEE_STRIDERBUSTER ) - DECLARE_CONDITION( COND_HUNTER_FORCED_DODGE ) - DECLARE_CONDITION( COND_HUNTER_INCOMING_VEHICLE ) - DECLARE_CONDITION( COND_HUNTER_NEW_HINTGROUP ) - DECLARE_CONDITION( COND_HUNTER_CANT_PLANT ) - DECLARE_CONDITION( COND_HUNTER_SQUADMATE_FOUND_ENEMY ) - - DECLARE_ANIMEVENT( AE_HUNTER_FOOTSTEP_LEFT ) - DECLARE_ANIMEVENT( AE_HUNTER_FOOTSTEP_RIGHT ) - DECLARE_ANIMEVENT( AE_HUNTER_FOOTSTEP_BACK ) - DECLARE_ANIMEVENT( AE_HUNTER_MELEE_ANNOUNCE ) - DECLARE_ANIMEVENT( AE_HUNTER_MELEE_ATTACK_LEFT ) - DECLARE_ANIMEVENT( AE_HUNTER_MELEE_ATTACK_RIGHT ) - DECLARE_ANIMEVENT( AE_HUNTER_DIE ) - DECLARE_ANIMEVENT( AE_HUNTER_SPRAY_BLOOD ) - DECLARE_ANIMEVENT( AE_HUNTER_START_EXPRESSION ) - DECLARE_ANIMEVENT( AE_HUNTER_END_EXPRESSION ) - - //========================================================= - // Attack (Deploy/shoot/finish) - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HUNTER_RANGE_ATTACK1, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_HUNTER_SHOOT_COMMIT 0" - " TASK_RANGE_ATTACK1 0" - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_LOST_ENEMY" - " COND_ENEMY_OCCLUDED" - " COND_WEAPON_SIGHT_OCCLUDED" - " COND_TOO_CLOSE_TO_ATTACK" - " COND_TOO_FAR_TO_ATTACK" - " COND_NOT_FACING_ATTACK" - ) - - //========================================================= - // Attack (Deploy/shoot/finish) - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HUNTER_RANGE_ATTACK2, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_HUNTER_PRE_RANGE_ATTACK2 0" - " TASK_HUNTER_SHOOT_COMMIT 0" - " TASK_RANGE_ATTACK2 0" - " TASK_HUNTER_FINISH_RANGE_ATTACK 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT 0.4" - " TASK_WAIT_RANDOM 0.2" - " " - " Interrupts" - " COND_NEW_ENEMY" - ) - - //========================================================= - // Shoot at striderbuster. Distinct from generic range attack - // because of BuildScheduleTestBits. - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HUNTER_RANGE_ATTACK2_VS_STRIDERBUSTER, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_HUNTER_SHOOT_COMMIT 0" - " TASK_RANGE_ATTACK2 0" - " " - " Interrupts" - ) - - //========================================================= - // Shoot at striderbuster with a little latency beforehand - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HUNTER_RANGE_ATTACK2_VS_STRIDERBUSTER_LATENT, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_HUNTER_SHOOT_COMMIT 0" - " TASK_WAIT 0.2" - " TASK_PLAY_SEQUENCE_FACE_ENEMY ACTIVITY:ACT_RANGE_ATTACK2" - " TASK_RANGE_ATTACK2 0" - " " - " Interrupts" - ) - - //========================================================= - // Dodge Incoming vehicle - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HUNTER_DODGE, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_HUNTER_FAIL_DODGE" - " TASK_HUNTER_FIND_DODGE_POSITION 0" - " TASK_HUNTER_DODGE 0" - "" - " Interrupts" - ) - - //========================================================= - // Dodge Incoming vehicle - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HUNTER_FAIL_DODGE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - ) - - //================================================== - // > SCHED_HUNTER_CHARGE_ENEMY - // Rush at my enemy and head-butt them. - //================================================== - DEFINE_SCHEDULE - ( - SCHED_HUNTER_CHARGE_ENEMY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_HUNTER_FAIL_CHARGE_ENEMY" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_HUNTER_CHARGE 0" - "" - " Interrupts" - " COND_TASK_FAILED" - " COND_ENEMY_DEAD" - ) - - DEFINE_SCHEDULE - ( - SCHED_HUNTER_FAIL_CHARGE_ENEMY, - - " Tasks" - " TASK_HUNTER_CHARGE_DELAY 10" - ) - - //========================================================= - // Chase the enemy with intent to claw - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HUNTER_CHASE_ENEMY_MELEE, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ESTABLISH_LINE_OF_FIRE" - " TASK_STOP_MOVING 0" - " TASK_GET_CHASE_PATH_TO_ENEMY 300" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_ENEMY_UNREACHABLE" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - //" COND_TOO_CLOSE_TO_ATTACK" - " COND_LOST_ENEMY" - ) - - //========================================================= - // Chase my enemy, shoot or claw when possible to do so. - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HUNTER_CHASE_ENEMY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ESTABLISH_LINE_OF_FIRE" - " TASK_STOP_MOVING 0" - " TASK_GET_CHASE_PATH_TO_ENEMY 300" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_ENEMY_UNREACHABLE" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - " COND_TOO_CLOSE_TO_ATTACK" - " COND_LOST_ENEMY" - ) - - //========================================================= - // Move to a flanking position, then shoot if possible. - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HUNTER_FLANK_ENEMY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ESTABLISH_LINE_OF_FIRE" - " TASK_STOP_MOVING 0" - " TASK_HUNTER_BEGIN_FLANK 0" - " TASK_GET_FLANK_ARC_PATH_TO_ENEMY_LOS 30" - " TASK_HUNTER_ANNOUNCE_FLANK 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_FACE_ENEMY 0" - //" TASK_HUNTER_END_FLANK 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - //" COND_CAN_RANGE_ATTACK1" - //" COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - " COND_ENEMY_DEAD" - " COND_ENEMY_UNREACHABLE" - " COND_TOO_CLOSE_TO_ATTACK" - " COND_LOST_ENEMY" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HUNTER_COMBAT_FACE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT_FACE_ENEMY 1" - "" - " Interrupts" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - ) - - //========================================================= - // Like the base class, only don't stop in the middle of - // swinging if the enemy is killed, hides, or new enemy. - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HUNTER_MELEE_ATTACK1, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_MELEE_ATTACK1 0" - //" TASK_SET_SCHEDULE SCHEDULE:SCHED_HUNTER_POST_MELEE_WAIT" - "" - " Interrupts" - ) - - //========================================================= - // In a fight with nothing to do. Make busy! - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HUNTER_CHANGE_POSITION, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_WANDER 720432" // 6 feet to 36 feet - " TASK_RUN_PATH 0" - " TASK_HUNTER_WAIT_FOR_MOVEMENT_FACING_ENEMY 0" - " TASK_STOP_MOVING 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_HUNTER_CHANGE_POSITION_FINISH" - "" - " Interrupts" - " COND_ENEMY_DEAD" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - " COND_HEAR_DANGER" - " COND_HEAR_MOVE_AWAY" - " COND_NEW_ENEMY" - ) - - //========================================================= - // In a fight with nothing to do. Make busy! - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HUNTER_CHANGE_POSITION_FINISH, - - " Tasks" - " TASK_FACE_ENEMY 0" - " TASK_WAIT_FACE_ENEMY_RANDOM 5" - "" - " Interrupts" - " COND_ENEMY_DEAD" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - " COND_HEAR_DANGER" - " COND_HEAR_MOVE_AWAY" - " COND_NEW_ENEMY" - ) - - //========================================================= - // In a fight with nothing to do. Make busy! - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HUNTER_SIDESTEP, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_HUNTER_FAIL_IMMEDIATE" // used because sched_fail includes a one second pause. ick! - " TASK_STOP_MOVING 0" - " TASK_HUNTER_FIND_SIDESTEP_POSITION 0" - " TASK_GET_PATH_TO_SAVEPOSITION 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HUNTER_PATROL, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_WANDER 720432" // 6 feet to 36 feet - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_FACE_REASONABLE 0" - " TASK_WAIT_RANDOM 3" - "" - " Interrupts" - " COND_ENEMY_DEAD" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_HEAR_COMBAT" - " COND_HEAR_PLAYER" - " COND_HEAR_BULLET_IMPACT" - " COND_HEAR_MOVE_AWAY" - " COND_NEW_ENEMY" - " COND_SEE_ENEMY" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - ) - - //========================================================= - // Stagger because I got hit by something heavy - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HUNTER_STAGGER, - - " Tasks" - " TASK_HUNTER_STAGGER 0" - "" - " Interrupts" - ) - - //========================================================= - // Run around randomly until we detect an enemy - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HUNTER_PATROL_RUN, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_COMBAT_FACE" - " TASK_SET_ROUTE_SEARCH_TIME 5" // Spend 5 seconds trying to build a path if stuck - " TASK_GET_PATH_TO_RANDOM_NODE 200" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_CAN_RANGE_ATTACK1 " - " COND_CAN_RANGE_ATTACK2 " - " COND_CAN_MELEE_ATTACK1 " - " COND_CAN_MELEE_ATTACK2" - " COND_GIVE_WAY" - " COND_NEW_ENEMY" - " COND_HEAR_COMBAT" - " COND_HEAR_DANGER" - " COND_HEAR_PLAYER" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HUNTER_TAKE_COVER_FROM_ENEMY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_HUNTER_CHASE_ENEMY_MELEE" - " TASK_HUNTER_CORNERED_TIMER 10.0" - " TASK_WAIT 0.0" - // " TASK_SET_TOLERANCE_DISTANCE 24" - // " TASK_FIND_COVER_FROM_ENEMY 0" - " TASK_FIND_FAR_NODE_COVER_FROM_ENEMY 200.0" - " TASK_RUN_PATH 0" - " TASK_HUNTER_CORNERED_TIMER 0.0" - // " TASK_CLEAR_FAIL_SCHEDULE 0" // not used because sched_fail includes a one second pause. ick! - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_HUNTER_FAIL_IMMEDIATE" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_REMEMBER MEMORY:INCOVER" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_HUNTER_HIDE_UNDER_COVER" - /* - " TASK_FACE_ENEMY 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" // Translated to cover - " TASK_WAIT 1" - */ - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_HEAR_DANGER" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HUNTER_HIDE_UNDER_COVER, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_HUNTER_FAIL_IMMEDIATE" // used because sched_fail includes a one second pause. ick! - " TASK_FACE_ENEMY 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" // Translated to cover - " TASK_WAIT 1" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_HEAR_DANGER" - " COND_HAVE_ENEMY_LOS" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HUNTER_FOUND_ENEMY, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_PLAY_SEQUENCE_FACE_ENEMY ACTIVITY:ACT_HUNTER_FOUND_ENEMY" - "" - " Interrupts" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HUNTER_FOUND_ENEMY_ACK, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_WAIT_RANDOM 0.75" - " TASK_FACE_ENEMY 0" - " TASK_PLAY_SEQUENCE_FACE_ENEMY ACTIVITY:ACT_HUNTER_FOUND_ENEMY_ACK" - "" - " Interrupts" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - ) - - //========================================================= - // An empty schedule that immediately bails out, faster than - // SCHED_FAIL which stops moving and waits for one second. - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HUNTER_FAIL_IMMEDIATE, - - " Tasks" - " TASK_WAIT 0" - - ) - - DEFINE_SCHEDULE - ( - SCHED_HUNTER_GOTO_HINT, - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_HUNTER_CLEAR_HINTNODE" // used because sched_fail includes a one second pause. ick! - " TASK_GET_PATH_TO_HINTNODE 1" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_CLEAR_HINTNODE 0" - "" - "" - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_HUNTER_CLEAR_HINTNODE, - " Tasks" - " TASK_CLEAR_HINTNODE 0" - "" - "" - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_HUNTER_SIEGE_STAND, - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_FACE_PLAYER 0" - " TASK_WAIT 10" - " TASK_WAIT_RANDOM 2" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_HUNTER_CHANGE_POSITION_SIEGE" - "" - "" - " Interrupts" - " COND_SEE_PLAYER" - " COND_NEW_ENEMY" - ) - - DEFINE_SCHEDULE - ( - SCHED_HUNTER_CHANGE_POSITION_SIEGE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_WANDER 2400480" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_FACE_PLAYER 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - ) - - // formula is MIN_DIST * 10000 + MAX_DIST - -AI_END_CUSTOM_NPC() diff --git a/game/server/episodic/npc_hunter.h b/game/server/episodic/npc_hunter.h deleted file mode 100644 index 5406b3657..000000000 --- a/game/server/episodic/npc_hunter.h +++ /dev/null @@ -1,25 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Expose an IsAHunter function -// -//=============================================================================// - -#ifndef NPC_HUNTER_H -#define NPC_HUNTER_H - -#if defined( _WIN32 ) -#pragma once -#endif - -class CBaseEntity; - -/// true if given entity pointer is a hunter. -bool Hunter_IsHunter(CBaseEntity *pEnt); - -// call throughs for member functions - -void Hunter_StriderBusterAttached( CBaseEntity *pHunter, CBaseEntity *pAttached ); -void Hunter_StriderBusterDetached( CBaseEntity *pHunter, CBaseEntity *pAttached ); -void Hunter_StriderBusterLaunched( CBaseEntity *pBuster ); - -#endif diff --git a/game/server/episodic/npc_magnusson.cpp b/game/server/episodic/npc_magnusson.cpp deleted file mode 100644 index 7d501afeb..000000000 --- a/game/server/episodic/npc_magnusson.cpp +++ /dev/null @@ -1,127 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ==== -// -// Purpose: Dr. Magnusson, a grumpy bastard who builds satellites and rockets -// at the White Forest missile silo. Instantly unlikeable, he is also -// the inventor of the Magnusson Device aka "strider buster", which -// is purported to resemble his cantelope-like head. -// -//============================================================================= - - -//----------------------------------------------------------------------------- -// Generic NPC - purely for scripted sequence work. -//----------------------------------------------------------------------------- -#include "cbase.h" -#include "npcevent.h" -#include "ai_basenpc.h" -#include "ai_hull.h" -#include "ai_baseactor.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// NPC's Anim Events Go Here -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CNPC_Magnusson : public CAI_BaseActor -{ -public: - DECLARE_CLASS( CNPC_Magnusson, CAI_BaseActor ); - - void Spawn( void ); - void Precache( void ); - Class_T Classify ( void ); - void HandleAnimEvent( animevent_t *pEvent ); - int GetSoundInterests ( void ); -}; - -LINK_ENTITY_TO_CLASS( npc_magnusson, CNPC_Magnusson ); - - -//----------------------------------------------------------------------------- -// Classify - indicates this NPC's place in the -// relationship table. -//----------------------------------------------------------------------------- -Class_T CNPC_Magnusson::Classify ( void ) -{ - return CLASS_PLAYER_ALLY_VITAL; -} - - -//----------------------------------------------------------------------------- -// HandleAnimEvent - catches the NPC-specific messages -// that occur when tagged animation frames are played. -//----------------------------------------------------------------------------- -void CNPC_Magnusson::HandleAnimEvent( animevent_t *pEvent ) -{ - switch( pEvent->event ) - { - case 1: - default: - BaseClass::HandleAnimEvent( pEvent ); - break; - } -} - -//----------------------------------------------------------------------------- -// GetSoundInterests - generic NPC can't hear. -//----------------------------------------------------------------------------- -int CNPC_Magnusson::GetSoundInterests ( void ) -{ - return 0; -} - -//----------------------------------------------------------------------------- -// Spawn -//----------------------------------------------------------------------------- -void CNPC_Magnusson::Spawn() -{ - // Allow custom model usage (mostly for monitors) - const char *szModel = (char *)STRING( GetModelName() ); - if (!szModel || !*szModel) - { - szModel = "models/magnusson.mdl"; - SetModelName( AllocPooledString(szModel) ); - } - - Precache(); - SetModel( szModel ); - - BaseClass::Spawn(); - - SetHullType(HULL_HUMAN); - SetHullSizeNormal(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - SetBloodColor( BLOOD_COLOR_RED ); - m_iHealth = 8; - m_flFieldOfView = 0.5;// indicates the width of this NPC's forward view cone ( as a dotproduct result ) - m_NPCState = NPC_STATE_NONE; - - CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_OPEN_DOORS | bits_CAP_ANIMATEDFACE | bits_CAP_TURN_HEAD ); - CapabilitiesAdd( bits_CAP_FRIENDLY_DMG_IMMUNE ); - - AddEFlags( EFL_NO_DISSOLVE | EFL_NO_MEGAPHYSCANNON_RAGDOLL | EFL_NO_PHYSCANNON_INTERACTION ); - - NPCInit(); -} - -//----------------------------------------------------------------------------- -// Precache - precaches all resources this NPC needs -//----------------------------------------------------------------------------- -void CNPC_Magnusson::Precache() -{ - PrecacheModel( STRING( GetModelName() ) ); - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// AI Schedules Specific to this NPC -//----------------------------------------------------------------------------- diff --git a/game/server/episodic/npc_puppet.cpp b/game/server/episodic/npc_puppet.cpp deleted file mode 100644 index 2dae9668d..000000000 --- a/game/server/episodic/npc_puppet.cpp +++ /dev/null @@ -1,121 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: NPC Puppet -// -//============================================================================= - -#include "cbase.h" -#include "ai_basenpc.h" - -// Must be the last file included -#include "memdbgon.h" - -class CNPC_Puppet : public CAI_BaseNPC -{ - DECLARE_CLASS( CNPC_Puppet, CAI_BaseNPC ); -public: - - virtual void Spawn( void ); - virtual void Precache( void ); - - void InputSetAnimationTarget( inputdata_t &inputdata ); - -private: - - string_t m_sAnimTargetname; - string_t m_sAnimAttachmentName; - - CNetworkVar( EHANDLE, m_hAnimationTarget ); // NPC that will drive what animation we're playing - CNetworkVar( int, m_nTargetAttachment ); // Attachment point to match to on the target - - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); -}; - -LINK_ENTITY_TO_CLASS( npc_puppet, CNPC_Puppet ); - -BEGIN_DATADESC( CNPC_Puppet ) - DEFINE_KEYFIELD( m_sAnimTargetname, FIELD_STRING, "animationtarget" ), - DEFINE_KEYFIELD( m_sAnimAttachmentName, FIELD_STRING, "attachmentname" ), - - DEFINE_FIELD( m_nTargetAttachment, FIELD_INTEGER ), - DEFINE_FIELD( m_hAnimationTarget, FIELD_EHANDLE ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetAnimationTarget", InputSetAnimationTarget ), -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CNPC_Puppet, DT_NPC_Puppet ) - SendPropEHandle( SENDINFO( m_hAnimationTarget ) ), - SendPropInt( SENDINFO( m_nTargetAttachment) ), -END_SEND_TABLE() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Puppet::Precache( void ) -{ - BaseClass::Precache(); - PrecacheModel( STRING( GetModelName() ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Puppet::Spawn( void ) -{ - BaseClass::Spawn(); - - Precache(); - - SetModel( STRING( GetModelName() ) ); - - NPCInit(); - - SetHealth( 100 ); - - // Find our animation target - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, m_sAnimTargetname ); - m_hAnimationTarget = pTarget; - if ( pTarget ) - { - CBaseAnimating *pAnimating = pTarget->GetBaseAnimating(); - if ( pAnimating ) - { - m_nTargetAttachment = pAnimating->LookupAttachment( STRING( m_sAnimAttachmentName ) ); - } - } - - // Always be scripted - SetInAScript( true ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_Puppet::InputSetAnimationTarget( inputdata_t &inputdata ) -{ - // Take the new name - m_sAnimTargetname = MAKE_STRING( inputdata.value.String() ); - - // Find our animation target - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, m_sAnimTargetname ); - if ( pTarget == NULL ) - { - Warning("Failed to find animation target %s for npc_puppet (%s)\n", STRING( m_sAnimTargetname ), STRING( GetEntityName() ) ); - return; - } - - m_hAnimationTarget = pTarget; - - CBaseAnimating *pAnimating = pTarget->GetBaseAnimating(); - if ( pAnimating ) - { - // Cache off our target attachment - m_nTargetAttachment = pAnimating->LookupAttachment( STRING( m_sAnimAttachmentName ) ); - } - - // Stuff us at the owner's core for visibility reasons - SetParent( pTarget ); - SetLocalOrigin( vec3_origin ); - SetLocalAngles( vec3_angle ); -} diff --git a/game/server/episodic/prop_scalable.cpp b/game/server/episodic/prop_scalable.cpp deleted file mode 100644 index 1133187e6..000000000 --- a/game/server/episodic/prop_scalable.cpp +++ /dev/null @@ -1,150 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Big pulsating ball inside the core of the citadel -// -//=============================================================================// - -#include "cbase.h" -#include "baseentity.h" - -#define COREBALL_MODEL "models/props_combine/coreball.mdl" - -class CPropScalable : public CBaseAnimating -{ -public: - DECLARE_CLASS( CPropScalable, CBaseAnimating ); - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - CPropScalable(); - - virtual void Spawn( void ); - virtual void Precache( void ); - - CNetworkVar( float, m_flScaleX ); - CNetworkVar( float, m_flScaleY ); - CNetworkVar( float, m_flScaleZ ); - - CNetworkVar( float, m_flLerpTimeX ); - CNetworkVar( float, m_flLerpTimeY ); - CNetworkVar( float, m_flLerpTimeZ ); - - CNetworkVar( float, m_flGoalTimeX ); - CNetworkVar( float, m_flGoalTimeY ); - CNetworkVar( float, m_flGoalTimeZ ); - - void InputSetScaleX( inputdata_t &inputdata ); - void InputSetScaleY( inputdata_t &inputdata ); - void InputSetScaleZ( inputdata_t &inputdata ); -}; - -LINK_ENTITY_TO_CLASS( prop_coreball, CPropScalable ); -LINK_ENTITY_TO_CLASS( prop_scalable, CPropScalable ); - -BEGIN_DATADESC( CPropScalable ) - DEFINE_INPUTFUNC( FIELD_VECTOR, "SetScaleX", InputSetScaleX ), - DEFINE_INPUTFUNC( FIELD_VECTOR, "SetScaleY", InputSetScaleY ), - DEFINE_INPUTFUNC( FIELD_VECTOR, "SetScaleZ", InputSetScaleZ ), - - DEFINE_FIELD( m_flScaleX, FIELD_FLOAT ), - DEFINE_FIELD( m_flScaleY, FIELD_FLOAT ), - DEFINE_FIELD( m_flScaleZ, FIELD_FLOAT ), - - DEFINE_FIELD( m_flLerpTimeX, FIELD_FLOAT ), - DEFINE_FIELD( m_flLerpTimeY, FIELD_FLOAT ), - DEFINE_FIELD( m_flLerpTimeZ, FIELD_FLOAT ), - - DEFINE_FIELD( m_flGoalTimeX, FIELD_FLOAT ), - DEFINE_FIELD( m_flGoalTimeY, FIELD_FLOAT ), - DEFINE_FIELD( m_flGoalTimeZ, FIELD_FLOAT ), -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CPropScalable, DT_PropScalable ) - SendPropFloat( SENDINFO(m_flScaleX), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO(m_flScaleY), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO(m_flScaleZ), 0, SPROP_NOSCALE ), - - SendPropFloat( SENDINFO(m_flLerpTimeX), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO(m_flLerpTimeY), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO(m_flLerpTimeZ), 0, SPROP_NOSCALE ), - - SendPropFloat( SENDINFO(m_flGoalTimeX), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO(m_flGoalTimeY), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO(m_flGoalTimeZ), 0, SPROP_NOSCALE ), -END_SEND_TABLE() - -CPropScalable::CPropScalable( void ) -{ - m_flScaleX = 1.0f; - m_flScaleY = 1.0f; - m_flScaleZ = 1.0f; - - UseClientSideAnimation(); -} - -void CPropScalable::Spawn( void ) -{ - // Stomp our model name if we're the coreball (legacy) - if ( FClassnameIs( this, "prop_coreball" ) ) - { - PrecacheModel( COREBALL_MODEL ); - SetModel( COREBALL_MODEL ); - } - else - { - char *szModel = (char *)STRING( GetModelName() ); - if (!szModel || !*szModel) - { - Warning( "prop_scalable at %.0f %.0f %0.f missing modelname\n", GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z ); - UTIL_Remove( this ); - return; - } - - PrecacheModel( szModel ); - SetModel( szModel ); - } - - SetMoveType( MOVETYPE_NONE ); - - BaseClass::Spawn(); - - AddEffects( EF_NOSHADOW ); - - SetSequence( 0 ); - SetPlaybackRate( 1.0f ); -} - -void CPropScalable::Precache( void ) -{ - BaseClass::Precache(); -} - -void CPropScalable::InputSetScaleX( inputdata_t &inputdata ) -{ - Vector vecScale; - inputdata.value.Vector3D( vecScale ); - - m_flScaleX = vecScale.x; - m_flLerpTimeX = vecScale.y; - m_flGoalTimeX = gpGlobals->curtime; -} - -void CPropScalable::InputSetScaleY( inputdata_t &inputdata ) -{ - Vector vecScale; - inputdata.value.Vector3D( vecScale ); - - m_flScaleY = vecScale.x; - m_flLerpTimeY = vecScale.y; - m_flGoalTimeY = gpGlobals->curtime; -} - -void CPropScalable::InputSetScaleZ( inputdata_t &inputdata ) -{ - Vector vecScale; - inputdata.value.Vector3D( vecScale ); - - m_flScaleZ = vecScale.x; - m_flLerpTimeZ = vecScale.y; - m_flGoalTimeZ = gpGlobals->curtime; -} diff --git a/game/server/episodic/vehicle_jeep_episodic.cpp b/game/server/episodic/vehicle_jeep_episodic.cpp deleted file mode 100644 index 217aa51a1..000000000 --- a/game/server/episodic/vehicle_jeep_episodic.cpp +++ /dev/null @@ -1,1763 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// -// -//============================================================================= - -#include "cbase.h" -#include "vehicle_jeep_episodic.h" -#include "collisionutils.h" -#include "npc_alyx_episodic.h" -#include "particle_parse.h" -#include "particle_system.h" -#include "hl2_player.h" -#include "in_buttons.h" -#include "vphysics/friction.h" -#include "vphysicsupdateai.h" -#include "physics_npc_solver.h" -#include "Sprite.h" -#include "weapon_striderbuster.h" -#include "npc_strider.h" -#include "vguiscreen.h" -#include "hl2_vehicle_radar.h" -#include "props.h" -#include "ai_dynamiclink.h" - -extern ConVar phys_upimpactforcescale; - -ConVar jalopy_blocked_exit_max_speed( "jalopy_blocked_exit_max_speed", "50" ); - -#define JEEP_AMMOCRATE_HITGROUP 5 -#define JEEP_AMMO_CRATE_CLOSE_DELAY 2.0f - -// Bodygroups -#define JEEP_RADAR_BODYGROUP 1 -#define JEEP_HOPPER_BODYGROUP 2 -#define JEEP_CARBAR_BODYGROUP 3 - -#define RADAR_PANEL_MATERIAL "vgui/screens/radar" -#define RADAR_PANEL_WRITEZ "engine/writez" - -static const char *s_szHazardSprite = "sprites/light_glow01.vmt"; - -enum -{ - RADAR_MODE_NORMAL = 0, - RADAR_MODE_STICKY, -}; - -//========================================================= -//========================================================= -class CRadarTarget : public CPointEntity -{ - DECLARE_CLASS( CRadarTarget, CPointEntity ); - -public: - void Spawn(); - - bool IsDisabled() { return m_bDisabled; } - int GetType() { return m_iType; } - int GetMode() { return m_iMode; } - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - int ObjectCaps(); - -private: - bool m_bDisabled; - int m_iType; - int m_iMode; - -public: - float m_flRadius; - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( info_radar_target, CRadarTarget ); - -BEGIN_DATADESC( CRadarTarget ) - DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ), - DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "radius" ), - DEFINE_KEYFIELD( m_iType, FIELD_INTEGER, "type" ), - DEFINE_KEYFIELD( m_iMode, FIELD_INTEGER, "mode" ), - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable",InputDisable ), -END_DATADESC(); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CRadarTarget::Spawn() -{ - BaseClass::Spawn(); - - AddEffects( EF_NODRAW ); - SetMoveType( MOVETYPE_NONE ); - SetSolid( SOLID_NONE ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CRadarTarget::InputEnable( inputdata_t &inputdata ) -{ - m_bDisabled = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CRadarTarget::InputDisable( inputdata_t &inputdata ) -{ - m_bDisabled = true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CRadarTarget::ObjectCaps() -{ - return BaseClass::ObjectCaps() | FCAP_ACROSS_TRANSITION; -} - - - - -// -// Trigger which detects entities placed in the cargo hold of the jalopy -// - -class CVehicleCargoTrigger : public CBaseEntity -{ - DECLARE_CLASS( CVehicleCargoTrigger, CBaseEntity ); - -public: - - // - // Creates a trigger with the specified bounds - - static CVehicleCargoTrigger *Create( const Vector &vecOrigin, const Vector &vecMins, const Vector &vecMaxs, CBaseEntity *pOwner ) - { - CVehicleCargoTrigger *pTrigger = (CVehicleCargoTrigger *) CreateEntityByName( "trigger_vehicle_cargo" ); - if ( pTrigger == NULL ) - return NULL; - - UTIL_SetOrigin( pTrigger, vecOrigin ); - UTIL_SetSize( pTrigger, vecMins, vecMaxs ); - pTrigger->SetOwnerEntity( pOwner ); - pTrigger->SetParent( pOwner ); - - pTrigger->Spawn(); - - return pTrigger; - } - - // - // Handles the trigger touching its intended quarry - - void CargoTouch( CBaseEntity *pOther ) - { - // Cannot be ignoring touches - if ( ( m_hIgnoreEntity == pOther ) || ( m_flIgnoreDuration >= gpGlobals->curtime ) ) - return; - - // Make sure this object is being held by the player - if ( pOther->VPhysicsGetObject() == NULL || (pOther->VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD) == false ) - return; - - if ( StriderBuster_NumFlechettesAttached( pOther ) > 0 ) - return; - - AddCargo( pOther ); - } - - bool AddCargo( CBaseEntity *pOther ) - { - // For now, only bother with strider busters - if ( (FClassnameIs( pOther, "weapon_striderbuster" ) == false) && - (FClassnameIs( pOther, "npc_grenade_magna" ) == false) - ) - return false; - - // Must be a physics prop - CPhysicsProp *pProp = dynamic_cast(pOther); - if ( pOther == NULL ) - return false; - - CPropJeepEpisodic *pJeep = dynamic_cast< CPropJeepEpisodic * >( GetOwnerEntity() ); - if ( pJeep == NULL ) - return false; - - // Make the player release the item - Pickup_ForcePlayerToDropThisObject( pOther ); - - // Stop colliding with things - pOther->VPhysicsDestroyObject(); - pOther->SetSolidFlags( FSOLID_NOT_SOLID ); - pOther->SetMoveType( MOVETYPE_NONE ); - - // Parent the object to our owner - pOther->SetParent( GetOwnerEntity() ); - - // The car now owns the entity - pJeep->AddPropToCargoHold( pProp ); - - // Notify the buster that it's been added to the cargo hold. - StriderBuster_OnAddToCargoHold( pProp ); - - // Stop touching this item - Disable(); - - return true; - } - - // - // Setup the entity - - void Spawn( void ) - { - BaseClass::Spawn(); - - SetSolid( SOLID_BBOX ); - SetSolidFlags( FSOLID_TRIGGER | FSOLID_NOT_SOLID ); - - SetTouch( &CVehicleCargoTrigger::CargoTouch ); - } - - void Activate() - { - BaseClass::Activate(); - SetSolidFlags( FSOLID_TRIGGER | FSOLID_NOT_SOLID ); // Fixes up old savegames - } - - // - // When we've stopped touching this entity, we ignore it - - void EndTouch( CBaseEntity *pOther ) - { - if ( pOther == m_hIgnoreEntity ) - { - m_hIgnoreEntity = NULL; - } - - BaseClass::EndTouch( pOther ); - } - - // - // Disables the trigger for a set duration - - void IgnoreTouches( CBaseEntity *pIgnoreEntity ) - { - m_hIgnoreEntity = pIgnoreEntity; - m_flIgnoreDuration = gpGlobals->curtime + 0.5f; - } - - void Disable( void ) - { - SetTouch( NULL ); - } - - void Enable( void ) - { - SetTouch( &CVehicleCargoTrigger::CargoTouch ); - } - -protected: - - float m_flIgnoreDuration; - CHandle m_hIgnoreEntity; - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( trigger_vehicle_cargo, CVehicleCargoTrigger ); - -BEGIN_DATADESC( CVehicleCargoTrigger ) - DEFINE_FIELD( m_flIgnoreDuration, FIELD_TIME ), - DEFINE_FIELD( m_hIgnoreEntity, FIELD_EHANDLE ), - DEFINE_ENTITYFUNC( CargoTouch ), -END_DATADESC(); - -// -// Transition reference point for the vehicle -// - -class CInfoTargetVehicleTransition : public CPointEntity -{ -public: - DECLARE_CLASS( CInfoTargetVehicleTransition, CPointEntity ); - - void Enable( void ) { m_bDisabled = false; } - void Disable( void ) { m_bDisabled = true; } - - bool IsDisabled( void ) const { return m_bDisabled; } - -private: - - void InputEnable( inputdata_t &data ) { Enable(); } - void InputDisable( inputdata_t &data ) { Disable(); } - - bool m_bDisabled; - - DECLARE_DATADESC(); -}; - -BEGIN_DATADESC( CInfoTargetVehicleTransition ) - DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable",InputDisable ), -END_DATADESC(); - -LINK_ENTITY_TO_CLASS( info_target_vehicle_transition, CInfoTargetVehicleTransition ); - -// -// CPropJeepEpisodic -// - -LINK_ENTITY_TO_CLASS( prop_vehicle_jeep, CPropJeepEpisodic ); - -BEGIN_DATADESC( CPropJeepEpisodic ) - - DEFINE_FIELD( m_bEntranceLocked, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bExitLocked, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hCargoProp, FIELD_EHANDLE ), - DEFINE_FIELD( m_hCargoTrigger, FIELD_EHANDLE ), - DEFINE_FIELD( m_bAddingCargo, FIELD_BOOLEAN ), - DEFINE_ARRAY( m_hWheelDust, FIELD_EHANDLE, NUM_WHEEL_EFFECTS ), - DEFINE_ARRAY( m_hWheelWater, FIELD_EHANDLE, NUM_WHEEL_EFFECTS ), - DEFINE_ARRAY( m_hHazardLights, FIELD_EHANDLE, NUM_HAZARD_LIGHTS ), - DEFINE_FIELD( m_flCargoStartTime, FIELD_TIME ), - DEFINE_FIELD( m_bBlink, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bRadarEnabled, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bRadarDetectsEnemies, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hRadarScreen, FIELD_EHANDLE ), - DEFINE_FIELD( m_hLinkControllerFront, FIELD_EHANDLE ), - DEFINE_FIELD( m_hLinkControllerRear, FIELD_EHANDLE ), - DEFINE_KEYFIELD( m_bBusterHopperVisible, FIELD_BOOLEAN, "CargoVisible" ), - // m_flNextAvoidBroadcastTime - DEFINE_FIELD( m_flNextWaterSound, FIELD_TIME ), - DEFINE_FIELD( m_flNextRadarUpdateTime, FIELD_TIME ), - DEFINE_FIELD( m_iNumRadarContacts, FIELD_INTEGER ), - DEFINE_ARRAY( m_vecRadarContactPos, FIELD_POSITION_VECTOR, RADAR_MAX_CONTACTS ), - DEFINE_ARRAY( m_iRadarContactType, FIELD_INTEGER, RADAR_MAX_CONTACTS ), - - DEFINE_THINKFUNC( HazardBlinkThink ), - - DEFINE_OUTPUT( m_OnCompanionEnteredVehicle, "OnCompanionEnteredVehicle" ), - DEFINE_OUTPUT( m_OnCompanionExitedVehicle, "OnCompanionExitedVehicle" ), - DEFINE_OUTPUT( m_OnHostileEnteredVehicle, "OnHostileEnteredVehicle" ), - DEFINE_OUTPUT( m_OnHostileExitedVehicle, "OnHostileExitedVehicle" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "LockEntrance", InputLockEntrance ), - DEFINE_INPUTFUNC( FIELD_VOID, "UnlockEntrance", InputUnlockEntrance ), - DEFINE_INPUTFUNC( FIELD_VOID, "LockExit", InputLockExit ), - DEFINE_INPUTFUNC( FIELD_VOID, "UnlockExit", InputUnlockExit ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableRadar", InputEnableRadar ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableRadar", InputDisableRadar ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableRadarDetectEnemies", InputEnableRadarDetectEnemies ), - DEFINE_INPUTFUNC( FIELD_VOID, "AddBusterToCargo", InputAddBusterToCargo ), - DEFINE_INPUTFUNC( FIELD_VOID, "OutsideTransition", InputOutsideTransition ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisablePhysGun", InputDisablePhysGun ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnablePhysGun", InputEnablePhysGun ), - DEFINE_INPUTFUNC( FIELD_VOID, "CreateLinkController", InputCreateLinkController ), - DEFINE_INPUTFUNC( FIELD_VOID, "DestroyLinkController", InputDestroyLinkController ), - - DEFINE_INPUTFUNC( FIELD_BOOLEAN, "SetCargoHopperVisibility", InputSetCargoVisibility ), - -END_DATADESC(); - -IMPLEMENT_SERVERCLASS_ST(CPropJeepEpisodic, DT_CPropJeepEpisodic) - //CNetworkVar( int, m_iNumRadarContacts ); - SendPropInt( SENDINFO(m_iNumRadarContacts), 8 ), - - //CNetworkArray( Vector, m_vecRadarContactPos, RADAR_MAX_CONTACTS ); - SendPropArray( SendPropVector( SENDINFO_ARRAY(m_vecRadarContactPos), -1, SPROP_COORD), m_vecRadarContactPos ), - - //CNetworkArray( int, m_iRadarContactType, RADAR_MAX_CONTACTS ); - SendPropArray( SendPropInt(SENDINFO_ARRAY(m_iRadarContactType), RADAR_CONTACT_TYPE_BITS ), m_iRadarContactType ), -END_SEND_TABLE() - - -//============================================================================= -// Episodic jeep - -CPropJeepEpisodic::CPropJeepEpisodic( void ) : -m_bEntranceLocked( false ), -m_bExitLocked( false ), -m_bAddingCargo( false ), -m_flNextAvoidBroadcastTime( 0.0f ) -{ - m_bHasGun = false; - m_bUnableToFire = true; - m_bRadarDetectsEnemies = false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::UpdateOnRemove( void ) -{ - BaseClass::UpdateOnRemove(); - - // Kill our wheel dust - for ( int i = 0; i < NUM_WHEEL_EFFECTS; i++ ) - { - if ( m_hWheelDust[i] != NULL ) - { - UTIL_Remove( m_hWheelDust[i] ); - } - - if ( m_hWheelWater[i] != NULL ) - { - UTIL_Remove( m_hWheelWater[i] ); - } - } - - DestroyHazardLights(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::Precache( void ) -{ - PrecacheMaterial( RADAR_PANEL_MATERIAL ); - PrecacheMaterial( RADAR_PANEL_WRITEZ ); - PrecacheModel( s_szHazardSprite ); - PrecacheScriptSound( "JNK_Radar_Ping_Friendly" ); - PrecacheScriptSound( "Physics.WaterSplash" ); - - PrecacheParticleSystem( "WheelDust" ); - PrecacheParticleSystem( "WheelSplash" ); - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::EnterVehicle( CBaseCombatCharacter *pPassenger ) -{ - BaseClass::EnterVehicle( pPassenger ); - - // Turn our hazards off! - DestroyHazardLights(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::Spawn( void ) -{ - BaseClass::Spawn(); - - SetBlocksLOS( false ); - - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - if ( pPlayer != NULL ) - { - pPlayer->m_Local.m_iHideHUD |= HIDEHUD_VEHICLE_CROSSHAIR; - } - - - SetBodygroup( JEEP_HOPPER_BODYGROUP, m_bBusterHopperVisible ? 1 : 0); - CreateCargoTrigger(); - - // carbar bodygroup is always on - SetBodygroup( JEEP_CARBAR_BODYGROUP, 1 ); - - m_bRadarDetectsEnemies = false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::Activate() -{ - m_iNumRadarContacts = 0; // Force first contact tone - BaseClass::Activate(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::NPC_FinishedEnterVehicle( CAI_BaseNPC *pPassenger, bool bCompanion ) -{ - // FIXME: This will be moved to the NPCs entering and exiting - // Fire our outputs - if ( bCompanion ) - { - m_OnCompanionEnteredVehicle.FireOutput( this, pPassenger ); - } - else - { - m_OnHostileEnteredVehicle.FireOutput( this, pPassenger ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::NPC_FinishedExitVehicle( CAI_BaseNPC *pPassenger, bool bCompanion ) -{ - // FIXME: This will be moved to the NPCs entering and exiting - // Fire our outputs - if ( bCompanion ) - { - m_OnCompanionExitedVehicle.FireOutput( this, pPassenger ); - } - else - { - m_OnHostileExitedVehicle.FireOutput( this, pPassenger ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPassenger - -// bCompanion - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CPropJeepEpisodic::NPC_CanEnterVehicle( CAI_BaseNPC *pPassenger, bool bCompanion ) -{ - // Must be unlocked - if ( bCompanion && m_bEntranceLocked ) - return false; - - return BaseClass::NPC_CanEnterVehicle( pPassenger, bCompanion ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPassenger - -// bCompanion - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CPropJeepEpisodic::NPC_CanExitVehicle( CAI_BaseNPC *pPassenger, bool bCompanion ) -{ - // Must be unlocked - if ( bCompanion && m_bExitLocked ) - return false; - - return BaseClass::NPC_CanExitVehicle( pPassenger, bCompanion ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::InputLockEntrance( inputdata_t &data ) -{ - m_bEntranceLocked = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::InputUnlockEntrance( inputdata_t &data ) -{ - m_bEntranceLocked = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::InputLockExit( inputdata_t &data ) -{ - m_bExitLocked = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::InputUnlockExit( inputdata_t &data ) -{ - m_bExitLocked = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Turn on the Jalopy radar device -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::InputEnableRadar( inputdata_t &data ) -{ - if( m_bRadarEnabled ) - return; // Already enabled - - SetBodygroup( JEEP_RADAR_BODYGROUP, 1 ); - - SpawnRadarPanel(); -} - -//----------------------------------------------------------------------------- -// Purpose: Turn off the Jalopy radar device -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::InputDisableRadar( inputdata_t &data ) -{ - if( !m_bRadarEnabled ) - return; // Already disabled - - SetBodygroup( JEEP_RADAR_BODYGROUP, 0 ); - - DestroyRadarPanel(); -} - -//----------------------------------------------------------------------------- -// Purpose: Allow the Jalopy radar to detect Hunters and Striders -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::InputEnableRadarDetectEnemies( inputdata_t &data ) -{ - m_bRadarDetectsEnemies = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::InputAddBusterToCargo( inputdata_t &data ) -{ - if ( m_hCargoProp != NULL) - { - ReleasePropFromCargoHold(); - m_hCargoProp = NULL; - } - - CBaseEntity *pNewBomb = CreateEntityByName( "weapon_striderbuster" ); - if ( pNewBomb ) - { - DispatchSpawn( pNewBomb ); - pNewBomb->Teleport( &m_hCargoTrigger->GetAbsOrigin(), NULL, NULL ); - m_hCargoTrigger->AddCargo( pNewBomb ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CPropJeepEpisodic::PassengerInTransition( void ) -{ - // FIXME: Big hack - we need a way to bridge this data better - // TODO: Get a list of passengers we can traverse instead - CNPC_Alyx *pAlyx = CNPC_Alyx::GetAlyx(); - if ( pAlyx ) - { - if ( pAlyx->GetPassengerState() == PASSENGER_STATE_ENTERING || - pAlyx->GetPassengerState() == PASSENGER_STATE_EXITING ) - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Override velocity if our passenger is transitioning or we're upside-down -//----------------------------------------------------------------------------- -Vector CPropJeepEpisodic::PhysGunLaunchVelocity( const Vector &forward, float flMass ) -{ - // Disallow - if ( PassengerInTransition() ) - return vec3_origin; - - Vector vecPuntDir = BaseClass::PhysGunLaunchVelocity( forward, flMass ); - vecPuntDir.z = 150.0f; - vecPuntDir *= 600.0f; - return vecPuntDir; -} - -//----------------------------------------------------------------------------- -// Purpose: Rolls the vehicle when its trying to upright itself from a punt -//----------------------------------------------------------------------------- -AngularImpulse CPropJeepEpisodic::PhysGunLaunchAngularImpulse( void ) -{ - if ( IsOverturned() ) - return AngularImpulse( 0, 300, 0 ); - - // Don't spin randomly, always spin reliably - return AngularImpulse( 0, 0, 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: Get the upright strength based on what state we're in -//----------------------------------------------------------------------------- -float CPropJeepEpisodic::GetUprightStrength( void ) -{ - // Lesser if overturned - if ( IsOverturned() ) - return 2.0f; - - return 0.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::CreateCargoTrigger( void ) -{ - if ( m_hCargoTrigger != NULL ) - return; - - int nAttachment = LookupAttachment( "cargo" ); - if ( nAttachment ) - { - Vector vecAttachOrigin; - Vector vecForward, vecRight, vecUp; - GetAttachment( nAttachment, vecAttachOrigin, &vecForward, &vecRight, &vecUp ); - - // Approx size of the hold - Vector vecMins( -8.0, -6.0, 0 ); - Vector vecMaxs( 8.0, 6.0, 4.0 ); - - // NDebugOverlay::BoxDirection( vecAttachOrigin, vecMins, vecMaxs, vecForward, 255, 0, 0, 64, 4.0f ); - - // Create a trigger that lives for a small amount of time - m_hCargoTrigger = CVehicleCargoTrigger::Create( vecAttachOrigin, vecMins, vecMaxs, this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: If the player uses the jeep while at the back, he gets ammo from the crate instead -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - // Fall back and get in the vehicle instead, skip giving ammo - BaseClass::BaseClass::Use( pActivator, pCaller, useType, value ); -} - -#define MIN_WHEEL_DUST_SPEED 5 - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::UpdateWheelDust( void ) -{ - // See if this wheel should emit dust - const vehicleparams_t *vehicleData = m_pServerVehicle->GetVehicleParams(); - const vehicle_operatingparams_t *carState = m_pServerVehicle->GetVehicleOperatingParams(); - bool bAllowDust = vehicleData->steering.dustCloud; - - // Car must be active - bool bCarOn = m_VehiclePhysics.IsOn(); - - // Must be moving quickly enough or skidding along the ground - bool bCreateDust = ( bCarOn && - bAllowDust && - ( m_VehiclePhysics.GetSpeed() >= MIN_WHEEL_DUST_SPEED || carState->skidSpeed > DEFAULT_SKID_THRESHOLD ) ); - - // Update our wheel dust - Vector vecPos; - for ( int i = 0; i < NUM_WHEEL_EFFECTS; i++ ) - { - m_pServerVehicle->GetWheelContactPoint( i, vecPos ); - - // Make sure the effect is created - if ( m_hWheelDust[i] == NULL ) - { - // Create the dust effect in place - m_hWheelDust[i] = (CParticleSystem *) CreateEntityByName( "info_particle_system" ); - if ( m_hWheelDust[i] == NULL ) - continue; - - // Setup our basic parameters - m_hWheelDust[i]->KeyValue( "start_active", "0" ); - m_hWheelDust[i]->KeyValue( "effect_name", "WheelDust" ); - m_hWheelDust[i]->SetParent( this ); - m_hWheelDust[i]->SetLocalOrigin( vec3_origin ); - DispatchSpawn( m_hWheelDust[i] ); - if ( gpGlobals->curtime > 0.5f ) - m_hWheelDust[i]->Activate(); - } - - // Make sure the effect is created - if ( m_hWheelWater[i] == NULL ) - { - // Create the dust effect in place - m_hWheelWater[i] = (CParticleSystem *) CreateEntityByName( "info_particle_system" ); - if ( m_hWheelWater[i] == NULL ) - continue; - - // Setup our basic parameters - m_hWheelWater[i]->KeyValue( "start_active", "0" ); - m_hWheelWater[i]->KeyValue( "effect_name", "WheelSplash" ); - m_hWheelWater[i]->SetParent( this ); - m_hWheelWater[i]->SetLocalOrigin( vec3_origin ); - DispatchSpawn( m_hWheelWater[i] ); - if ( gpGlobals->curtime > 0.5f ) - m_hWheelWater[i]->Activate(); - } - - // Turn the dust on or off - if ( bCreateDust ) - { - // Angle the dust out away from the wheels - Vector vecForward, vecRight, vecUp; - GetVectors( &vecForward, &vecRight, &vecUp ); - - const vehicle_controlparams_t *vehicleControls = m_pServerVehicle->GetVehicleControlParams(); - float flWheelDir = ( i & 1 ) ? 1.0f : -1.0f; - QAngle vecAngles; - vecForward += vecRight * flWheelDir; - vecForward += vecRight * (vehicleControls->steering*0.5f) * flWheelDir; - vecForward += vecUp; - VectorAngles( vecForward, vecAngles ); - - // NDebugOverlay::Axis( vecPos, vecAngles, 8.0f, true, 0.1f ); - - if ( m_WaterData.m_bWheelInWater[i] ) - { - m_hWheelDust[i]->StopParticleSystem(); - - // Set us up in the right position - m_hWheelWater[i]->StartParticleSystem(); - m_hWheelWater[i]->SetAbsAngles( vecAngles ); - m_hWheelWater[i]->SetAbsOrigin( vecPos + Vector( 0, 0, 8 ) ); - - if ( m_flNextWaterSound < gpGlobals->curtime ) - { - m_flNextWaterSound = gpGlobals->curtime + random->RandomFloat( 0.25f, 1.0f ); - EmitSound( "Physics.WaterSplash" ); - } - } - else - { - m_hWheelWater[i]->StopParticleSystem(); - - // Set us up in the right position - m_hWheelDust[i]->StartParticleSystem(); - m_hWheelDust[i]->SetAbsAngles( vecAngles ); - m_hWheelDust[i]->SetAbsOrigin( vecPos + Vector( 0, 0, 8 ) ); - } - } - else - { - // Stop emitting - m_hWheelDust[i]->StopParticleSystem(); - m_hWheelWater[i]->StopParticleSystem(); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -ConVar jalopy_radar_test_ent( "jalopy_radar_test_ent", "none" ); - -//----------------------------------------------------------------------------- -// Purpose: Search for things that the radar detects, and stick them in the -// UTILVector that gets sent to the client for radar display. -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::UpdateRadar( bool forceUpdate ) -{ - bool bDetectedDog = false; - - if( !m_bRadarEnabled ) - return; - - if( !forceUpdate && gpGlobals->curtime < m_flNextRadarUpdateTime ) - return; - - // Count the targets on radar. If any more targets come on the radar, we beep. - int m_iNumOldRadarContacts = m_iNumRadarContacts; - - m_flNextRadarUpdateTime = gpGlobals->curtime + RADAR_UPDATE_FREQUENCY; - m_iNumRadarContacts = 0; - - CBaseEntity *pEnt = gEntList.FirstEnt(); - string_t iszRadarTarget = FindPooledString( "info_radar_target" ); - string_t iszStriderName = FindPooledString( "npc_strider" ); - string_t iszHunterName = FindPooledString( "npc_hunter" ); - - string_t iszTestName = FindPooledString( jalopy_radar_test_ent.GetString() ); - - Vector vecJalopyOrigin = WorldSpaceCenter(); - - while( pEnt != NULL ) - { - int type = RADAR_CONTACT_NONE; - - if( pEnt->m_iClassname == iszRadarTarget ) - { - CRadarTarget *pTarget = dynamic_cast(pEnt); - - if( pTarget != NULL && !pTarget->IsDisabled() ) - { - if( pTarget->m_flRadius < 0 || vecJalopyOrigin.DistToSqr(pTarget->GetAbsOrigin()) <= Square(pTarget->m_flRadius) ) - { - // This item has been detected. - type = pTarget->GetType(); - - if( type == RADAR_CONTACT_DOG ) - bDetectedDog = true;// used to prevent Alyx talking about the radar (see below) - - if( pTarget->GetMode() == RADAR_MODE_STICKY ) - { - // This beacon was just detected. Now change the radius to infinite - // so that it will never go off the radar due to distance. - pTarget->m_flRadius = -1; - } - } - } - } - else if ( m_bRadarDetectsEnemies ) - { - if ( pEnt->m_iClassname == iszStriderName ) - { - CNPC_Strider *pStrider = dynamic_cast(pEnt); - - if( !pStrider || !pStrider->CarriedByDropship() ) - { - // Ignore striders which are carried by dropships. - type = RADAR_CONTACT_LARGE_ENEMY; - } - } - - if ( pEnt->m_iClassname == iszHunterName ) - { - type = RADAR_CONTACT_ENEMY; - } - } - - if( type != RADAR_CONTACT_NONE ) - { - Vector vecPos = pEnt->WorldSpaceCenter(); - - m_vecRadarContactPos.Set( m_iNumRadarContacts, vecPos ); - m_iRadarContactType.Set( m_iNumRadarContacts, type ); - m_iNumRadarContacts++; - - if( m_iNumRadarContacts == RADAR_MAX_CONTACTS ) - break; - } - - pEnt = gEntList.NextEnt(pEnt); - } - - if( m_iNumRadarContacts > m_iNumOldRadarContacts ) - { - // Play a bleepy sound - if( !bDetectedDog ) - { - EmitSound( "JNK_Radar_Ping_Friendly" ); - } - - //Notify Alyx so she can talk about the radar contact - CNPC_Alyx *pAlyx = CNPC_Alyx::GetAlyx(); - - if( !bDetectedDog && pAlyx != NULL && pAlyx->GetVehicle() ) - { - pAlyx->SpeakIfAllowed( TLK_PASSENGER_NEW_RADAR_CONTACT ); - } - } - - if( bDetectedDog ) - { - // Update the radar much more frequently when dog is around. - m_flNextRadarUpdateTime = gpGlobals->curtime + RADAR_UPDATE_FREQUENCY_FAST; - } - - //Msg("Server detected %d objects\n", m_iNumRadarContacts ); - - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - CSingleUserRecipientFilter filter(pPlayer); - UserMessageBegin( filter, "UpdateJalopyRadar" ); - WRITE_BYTE( 0 ); // end marker - MessageEnd(); // send message -} - -ConVar jalopy_cargo_anim_time( "jalopy_cargo_anim_time", "1.0" ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::UpdateCargoEntry( void ) -{ - // Don't bother if we have no prop to move - if ( m_hCargoProp == NULL ) - return; - - // If we're past our animation point, then we're already done - if ( m_flCargoStartTime + jalopy_cargo_anim_time.GetFloat() < gpGlobals->curtime ) - { - // Close the hold immediately if we're finished - if ( m_bAddingCargo ) - { - m_flAmmoCrateCloseTime = gpGlobals->curtime; - m_bAddingCargo = false; - } - - return; - } - - // Get our target point - int nAttachment = LookupAttachment( "cargo" ); - Vector vecTarget, vecOut; - QAngle vecAngles; - GetAttachmentLocal( nAttachment, vecTarget, vecAngles ); - - // Find where we are in the blend and bias it for a fast entry and slow ease-out - float flPerc = (jalopy_cargo_anim_time.GetFloat()) ? (( gpGlobals->curtime - m_flCargoStartTime ) / jalopy_cargo_anim_time.GetFloat()) : 1.0f; - flPerc = Bias( flPerc, 0.75f ); - VectorLerp( m_hCargoProp->GetLocalOrigin(), vecTarget, flPerc, vecOut ); - - // Get our target orientation - CPhysicsProp *pProp = dynamic_cast(m_hCargoProp.Get()); - if ( pProp == NULL ) - return; - - // Slerp our quaternions to find where we are this frame - Quaternion qtTarget; - QAngle ang = pProp->PreferredCarryAngles() + QAngle(0.0f, 90.0f, 0.0f); - AngleQuaternion( ang, qtTarget ); // FIXME: Find the real offset to make this sit properly - Quaternion qtCurrent; - AngleQuaternion( pProp->GetLocalAngles(), qtCurrent ); - - Quaternion qtOut; - QuaternionSlerp( qtCurrent, qtTarget, flPerc, qtOut ); - - // Put it back to angles - QuaternionAngles( qtOut, vecAngles ); - - // Finally, take these new position - m_hCargoProp->SetLocalOrigin( vecOut ); - m_hCargoProp->SetLocalAngles( vecAngles ); - - // Push the closing out into the future to make sure we don't try and close at the same time - m_flAmmoCrateCloseTime += gpGlobals->frametime; -} - -#define VEHICLE_AVOID_BROADCAST_RATE 0.5f - -//----------------------------------------------------------------------------- -// Purpose: This function isn't really what we want -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::CreateAvoidanceZone( void ) -{ - if ( m_flNextAvoidBroadcastTime > gpGlobals->curtime ) - return; - - // Only do this when we're stopped - if ( m_VehiclePhysics.GetSpeed() > 5.0f ) - return; - - float flHullRadius = CollisionProp()->BoundingRadius2D(); - - Vector vecPos; - CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.33f, 0.25f ), &vecPos ); - CSoundEnt::InsertSound( SOUND_MOVE_AWAY, vecPos, (int)(flHullRadius*0.4f), VEHICLE_AVOID_BROADCAST_RATE, this ); - // NDebugOverlay::Sphere( vecPos, vec3_angle, flHullRadius*0.4f, 255, 0, 0, 0, true, VEHICLE_AVOID_BROADCAST_RATE ); - - CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.66f, 0.25f ), &vecPos ); - CSoundEnt::InsertSound( SOUND_MOVE_AWAY, vecPos, (int)(flHullRadius*0.4f), VEHICLE_AVOID_BROADCAST_RATE, this ); - // NDebugOverlay::Sphere( vecPos, vec3_angle, flHullRadius*0.4f, 255, 0, 0, 0, true, VEHICLE_AVOID_BROADCAST_RATE ); - - // Don't broadcast again until these are done - m_flNextAvoidBroadcastTime = gpGlobals->curtime + VEHICLE_AVOID_BROADCAST_RATE; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::Think( void ) -{ - BaseClass::Think(); - - // If our passenger is transitioning, then don't let the player drive off - CNPC_Alyx *pAlyx = CNPC_Alyx::GetAlyx(); - if ( pAlyx && pAlyx->GetPassengerState() == PASSENGER_STATE_EXITING ) - { - m_throttleDisableTime = gpGlobals->curtime + 0.25f; - } - - // Update our cargo entering our hold - UpdateCargoEntry(); - - // See if the wheel dust should be on or off - UpdateWheelDust(); - - // Update the radar, of course. - UpdateRadar(); - - if ( m_hCargoTrigger && !m_hCargoProp && !m_hCargoTrigger->m_pfnTouch ) - { - m_hCargoTrigger->Enable(); - } - - CreateAvoidanceZone(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEntity - -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::AddPropToCargoHold( CPhysicsProp *pProp ) -{ - // The hold must be empty to add something to it - if ( m_hCargoProp != NULL ) - { - Assert( 0 ); - return; - } - - // Take the prop as our cargo - m_hCargoProp = pProp; - m_flCargoStartTime = gpGlobals->curtime; - m_bAddingCargo = true; -} - -//----------------------------------------------------------------------------- -// Purpose: Drops the cargo from the hold -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::ReleasePropFromCargoHold( void ) -{ - // Pull the object free! - m_hCargoProp->SetParent( NULL ); - m_hCargoProp->CreateVPhysics(); - - if ( m_hCargoTrigger ) - { - m_hCargoTrigger->Enable(); - m_hCargoTrigger->IgnoreTouches( m_hCargoProp ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: If the player is trying to pull the cargo out of the hold using the physcannon, let him -// Output : Returns the cargo to pick up, if all the conditions are met -//----------------------------------------------------------------------------- -CBaseEntity *CPropJeepEpisodic::OnFailedPhysGunPickup( Vector vPhysgunPos ) -{ - // Make sure we're available to open - if ( m_hCargoProp != NULL ) - { - // Player's forward direction - Vector vecPlayerForward; - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer == NULL ) - return NULL; - - pPlayer->EyeVectors( &vecPlayerForward ); - - // Origin and facing of the cargo hold - Vector vecCargoOrigin; - Vector vecCargoForward; - GetAttachment( "cargo", vecCargoOrigin, &vecCargoForward ); - - // Direction from the cargo to the player's position - Vector vecPickupDir = ( vecCargoOrigin - vPhysgunPos ); - float flDist = VectorNormalize( vecPickupDir ); - - // We need to make sure the player's position is within a cone near the opening and that they're also facing the right way - bool bInCargoRange = ( (flDist < (15.0f * 12.0f)) && DotProduct( vecCargoForward, vecPickupDir ) < 0.1f ); - bool bFacingCargo = DotProduct( vecPlayerForward, vecPickupDir ) > 0.975f; - - // If we're roughly pulling at the item, pick that up - if ( bInCargoRange && bFacingCargo ) - { - // Save this for later - CBaseEntity *pCargo = m_hCargoProp; - - // Drop the cargo - ReleasePropFromCargoHold(); - - // Forget the item but pass it back as the object to pick up - m_hCargoProp = NULL; - return pCargo; - } - } - - return BaseClass::OnFailedPhysGunPickup( vPhysgunPos ); -} - -// adds a collision solver for any small props that are stuck under the vehicle -static void SolveBlockingProps( CPropJeepEpisodic *pVehicleEntity, IPhysicsObject *pVehiclePhysics ) -{ - CUtlVector solveList; - float vehicleMass = pVehiclePhysics->GetMass(); - Vector vehicleUp; - pVehicleEntity->GetVectors( NULL, NULL, &vehicleUp ); - IPhysicsFrictionSnapshot *pSnapshot = pVehiclePhysics->CreateFrictionSnapshot(); - while ( pSnapshot->IsValid() ) - { - IPhysicsObject *pOther = pSnapshot->GetObject(1); - float otherMass = pOther->GetMass(); - CBaseEntity *pOtherEntity = static_cast(pOther->GetGameData()); - Assert(pOtherEntity); - if ( pOtherEntity && pOtherEntity->GetMoveType() == MOVETYPE_VPHYSICS && pOther->IsMoveable() && (otherMass*4.0f) < vehicleMass ) - { - Vector normal; - pSnapshot->GetSurfaceNormal(normal); - // this points down in the car's reference frame, then it's probably trapped under the car - if ( DotProduct(normal, vehicleUp) < -0.9f ) - { - Vector point, pointLocal; - pSnapshot->GetContactPoint(point); - VectorITransform( point, pVehicleEntity->EntityToWorldTransform(), pointLocal ); - Vector bottomPoint = physcollision->CollideGetExtent( pVehiclePhysics->GetCollide(), vec3_origin, vec3_angle, Vector(0,0,-1) ); - // make sure it's under the bottom of the car - float bottomPlane = DotProduct(bottomPoint,vehicleUp)+8; // 8 inches above bottom - if ( DotProduct( pointLocal, vehicleUp ) <= bottomPlane ) - { - //Msg("Solved %s\n", pOtherEntity->GetClassname()); - if ( solveList.Find(pOtherEntity) < 0 ) - { - solveList.AddToTail(pOtherEntity); - } - } - } - } - pSnapshot->NextFrictionData(); - } - pVehiclePhysics->DestroyFrictionSnapshot( pSnapshot ); - if ( solveList.Count() ) - { - for ( int i = 0; i < solveList.Count(); i++ ) - { - EntityPhysics_CreateSolver( pVehicleEntity, solveList[i], true, 4.0f ); - } - pVehiclePhysics->RecheckContactPoints(); - } -} - -static void SimpleCollisionResponse( Vector velocityIn, const Vector &normal, float coefficientOfRestitution, Vector *pVelocityOut ) -{ - Vector Vn = DotProduct(velocityIn,normal) * normal; - Vector Vt = velocityIn - Vn; - *pVelocityOut = Vt - coefficientOfRestitution * Vn; -} - -static void KillBlockingEnemyNPCs( CBasePlayer *pPlayer, CBaseEntity *pVehicleEntity, IPhysicsObject *pVehiclePhysics ) -{ - Vector velocity; - pVehiclePhysics->GetVelocity( &velocity, NULL ); - float vehicleMass = pVehiclePhysics->GetMass(); - - // loop through the contacts and look for enemy NPCs that we're pushing on - CUtlVector npcList; - CUtlVector forceList; - CUtlVector contactList; - IPhysicsFrictionSnapshot *pSnapshot = pVehiclePhysics->CreateFrictionSnapshot(); - while ( pSnapshot->IsValid() ) - { - IPhysicsObject *pOther = pSnapshot->GetObject(1); - float otherMass = pOther->GetMass(); - CBaseEntity *pOtherEntity = static_cast(pOther->GetGameData()); - CAI_BaseNPC *pNPC = pOtherEntity ? pOtherEntity->MyNPCPointer() : NULL; - // Is this an enemy NPC with a small enough mass? - if ( pNPC && pPlayer->IRelationType(pNPC) != D_LI && ((otherMass*2.0f) < vehicleMass) ) - { - // accumulate the stress force for this NPC in the lsit - float force = pSnapshot->GetNormalForce(); - Vector normal; - pSnapshot->GetSurfaceNormal(normal); - normal *= force; - int index = npcList.Find(pNPC); - if ( index < 0 ) - { - vphysicsupdateai_t *pUpdate = NULL; - if ( pNPC->VPhysicsGetObject() && pNPC->VPhysicsGetObject()->GetShadowController() && pNPC->GetMoveType() == MOVETYPE_STEP ) - { - if ( pNPC->HasDataObjectType(VPHYSICSUPDATEAI) ) - { - pUpdate = static_cast(pNPC->GetDataObject(VPHYSICSUPDATEAI)); - // kill this guy if I've been pushing him for more than half a second and I'm - // still pushing in his direction - if ( (gpGlobals->curtime - pUpdate->startUpdateTime) > 0.5f && DotProduct(velocity,normal) > 0) - { - index = npcList.AddToTail(pNPC); - forceList.AddToTail( normal ); - Vector pos; - pSnapshot->GetContactPoint(pos); - contactList.AddToTail(pos); - } - } - else - { - pUpdate = static_cast(pNPC->CreateDataObject( VPHYSICSUPDATEAI )); - pUpdate->startUpdateTime = gpGlobals->curtime; - } - // update based on vphysics for the next second - // this allows the car to push the NPC - pUpdate->stopUpdateTime = gpGlobals->curtime + 1.0f; - float maxAngular; - pNPC->VPhysicsGetObject()->GetShadowController()->GetMaxSpeed( &pUpdate->savedShadowControllerMaxSpeed, &maxAngular ); - pNPC->VPhysicsGetObject()->GetShadowController()->MaxSpeed( 1.0f, maxAngular ); - } - } - else - { - forceList[index] += normal; - } - } - pSnapshot->NextFrictionData(); - } - pVehiclePhysics->DestroyFrictionSnapshot( pSnapshot ); - // now iterate the list and check each cumulative force against the threshold - if ( npcList.Count() ) - { - for ( int i = npcList.Count(); --i >= 0; ) - { - Vector damageForce; - npcList[i]->VPhysicsGetObject()->GetVelocity( &damageForce, NULL ); - Vector vel; - pVehiclePhysics->GetVelocityAtPoint( contactList[i], &vel ); - damageForce -= vel; - Vector normal = forceList[i]; - VectorNormalize(normal); - SimpleCollisionResponse( damageForce, normal, 1.0, &damageForce ); - damageForce += (normal * 300.0f); - damageForce *= npcList[i]->VPhysicsGetObject()->GetMass(); - float len = damageForce.Length(); - damageForce.z += len*phys_upimpactforcescale.GetFloat(); - Vector vehicleForce = -damageForce; - - CTakeDamageInfo dmgInfo( pVehicleEntity, pVehicleEntity, damageForce, contactList[i], 200.0f, DMG_CRUSH|DMG_VEHICLE ); - npcList[i]->TakeDamage( dmgInfo ); - pVehiclePhysics->ApplyForceOffset( vehicleForce, contactList[i] ); - PhysCollisionSound( pVehicleEntity, npcList[i]->VPhysicsGetObject(), CHAN_BODY, pVehiclePhysics->GetMaterialIndex(), npcList[i]->VPhysicsGetObject()->GetMaterialIndex(), gpGlobals->frametime, 200.0f ); - } - } -} - -void CPropJeepEpisodic::DriveVehicle( float flFrameTime, CUserCmd *ucmd, int iButtonsDown, int iButtonsReleased ) -{ - /* The car headlight hurts perf, there's no timer to turn it off automatically, - and we haven't built any gameplay around it. - - Furthermore, I don't think I've ever seen a playtester turn it on. - - if ( ucmd->impulse == 100 ) - { - if (HeadlightIsOn()) - { - HeadlightTurnOff(); - } - else - { - HeadlightTurnOn(); - } - }*/ - - if ( ucmd->forwardmove != 0.0f ) - { - //Msg("Push V: %.2f, %.2f, %.2f\n", ucmd->forwardmove, carState->engineRPM, carState->speed ); - CBasePlayer *pPlayer = ToBasePlayer(GetDriver()); - - if ( pPlayer && VPhysicsGetObject() ) - { - KillBlockingEnemyNPCs( pPlayer, this, VPhysicsGetObject() ); - SolveBlockingProps( this, VPhysicsGetObject() ); - } - } - BaseClass::DriveVehicle(flFrameTime, ucmd, iButtonsDown, iButtonsReleased); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::CreateHazardLights( void ) -{ - static const char *s_szAttach[NUM_HAZARD_LIGHTS] = - { - "rearlight_r", - "rearlight_l", - "headlight_r", - "headlight_l", - }; - - // Turn on the hazards! - for ( int i = 0; i < NUM_HAZARD_LIGHTS; i++ ) - { - if ( m_hHazardLights[i] == NULL ) - { - m_hHazardLights[i] = CSprite::SpriteCreate( s_szHazardSprite, GetLocalOrigin(), false ); - if ( m_hHazardLights[i] ) - { - m_hHazardLights[i]->SetTransparency( kRenderWorldGlow, 255, 220, 40, 255, kRenderFxNoDissipation ); - m_hHazardLights[i]->SetAttachment( this, LookupAttachment( s_szAttach[i] ) ); - m_hHazardLights[i]->SetGlowProxySize( 2.0f ); - m_hHazardLights[i]->TurnOff(); - if ( i < 2 ) - { - // Rear lights are red - m_hHazardLights[i]->SetColor( 255, 0, 0 ); - m_hHazardLights[i]->SetScale( 1.0f ); - } - else - { - // Font lights are white - m_hHazardLights[i]->SetScale( 1.0f ); - } - } - } - } - - // We start off - m_bBlink = false; - - // Setup our blink - SetContextThink( &CPropJeepEpisodic::HazardBlinkThink, gpGlobals->curtime + 0.1f, "HazardBlink" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::DestroyHazardLights( void ) -{ - for ( int i = 0; i < NUM_HAZARD_LIGHTS; i++ ) - { - if ( m_hHazardLights[i] != NULL ) - { - UTIL_Remove( m_hHazardLights[i] ); - } - } - - SetContextThink( NULL, gpGlobals->curtime, "HazardBlink" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : nRole - -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::ExitVehicle( int nRole ) -{ - BaseClass::ExitVehicle( nRole ); - - CreateHazardLights(); -} - -void CPropJeepEpisodic::SetBusterHopperVisibility(bool visible) -{ - // if we're there already do nothing - if (visible == m_bBusterHopperVisible) - return; - - SetBodygroup( JEEP_HOPPER_BODYGROUP, visible ? 1 : 0); - m_bBusterHopperVisible = visible; -} - - -void CPropJeepEpisodic::InputSetCargoVisibility( inputdata_t &data ) -{ - bool visible = data.value.Bool(); - - SetBusterHopperVisibility( visible ); -} - -//----------------------------------------------------------------------------- -// THIS CODE LIFTED RIGHT OUT OF TF2, to defer the pain of making vgui-on-an-entity -// code available to all CBaseAnimating. -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::SpawnRadarPanel() -{ - // FIXME: Deal with dynamically resizing control panels? - - // If we're attached to an entity, spawn control panels on it instead of use - CBaseAnimating *pEntityToSpawnOn = this; - const char *pOrgLL = "controlpanel0_ll"; - const char *pOrgUR = "controlpanel0_ur"; - - Assert( pEntityToSpawnOn ); - - // Lookup the attachment point... - int nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(pOrgLL); - - if (nLLAttachmentIndex <= 0) - { - return; - } - - int nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(pOrgUR); - if (nURAttachmentIndex <= 0) - { - return; - } - - const char *pScreenName = "jalopy_radar_panel"; - const char *pScreenClassname = "vgui_screen"; - - // Compute the screen size from the attachment points... - matrix3x4_t panelToWorld; - pEntityToSpawnOn->GetAttachment( nLLAttachmentIndex, panelToWorld ); - - matrix3x4_t worldToPanel; - MatrixInvert( panelToWorld, worldToPanel ); - - // Now get the lower right position + transform into panel space - Vector lr, lrlocal; - pEntityToSpawnOn->GetAttachment( nURAttachmentIndex, panelToWorld ); - MatrixGetColumn( panelToWorld, 3, lr ); - VectorTransform( lr, worldToPanel, lrlocal ); - - float flWidth = lrlocal.x; - float flHeight = lrlocal.y; - - CVGuiScreen *pScreen = CreateVGuiScreen( pScreenClassname, pScreenName, pEntityToSpawnOn, this, nLLAttachmentIndex ); - pScreen->SetActualSize( flWidth, flHeight ); - pScreen->SetActive( true ); - pScreen->SetOverlayMaterial( RADAR_PANEL_WRITEZ ); - pScreen->SetTransparency( true ); - - m_hRadarScreen.Set( pScreen ); - - m_bRadarEnabled = true; - m_iNumRadarContacts = 0; - m_flNextRadarUpdateTime = gpGlobals->curtime - 1.0f; -} - -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::DestroyRadarPanel() -{ - Assert( m_hRadarScreen != NULL ); - m_hRadarScreen->SUB_Remove(); - m_bRadarEnabled = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::HazardBlinkThink( void ) -{ - if ( m_bBlink ) - { - for ( int i = 0; i < NUM_HAZARD_LIGHTS; i++ ) - { - if ( m_hHazardLights[i] ) - { - m_hHazardLights[i]->SetBrightness( 0, 0.1f ); - } - } - - SetContextThink( &CPropJeepEpisodic::HazardBlinkThink, gpGlobals->curtime + 0.25f, "HazardBlink" ); - } - else - { - for ( int i = 0; i < NUM_HAZARD_LIGHTS; i++ ) - { - if ( m_hHazardLights[i] ) - { - m_hHazardLights[i]->SetBrightness( 255, 0.1f ); - m_hHazardLights[i]->TurnOn(); - } - } - - SetContextThink( &CPropJeepEpisodic::HazardBlinkThink, gpGlobals->curtime + 0.5f, "HazardBlink" ); - } - - m_bBlink = !m_bBlink; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::HandleWater( void ) -{ - // Only check the wheels and engine in water if we have a driver (player). - if ( !GetDriver() ) - return; - - // Update our internal state - CheckWater(); - - // Save of data from last think. - for ( int iWheel = 0; iWheel < JEEP_WHEEL_COUNT; ++iWheel ) - { - m_WaterData.m_bWheelWasInWater[iWheel] = m_WaterData.m_bWheelInWater[iWheel]; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Report our lock state -//----------------------------------------------------------------------------- -int CPropJeepEpisodic::DrawDebugTextOverlays( void ) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if ( m_debugOverlays & OVERLAY_TEXT_BIT ) - { - EntityText( text_offset, CFmtStr("Entrance: %s", m_bEntranceLocked ? "Locked" : "Unlocked" ), 0 ); - text_offset++; - - EntityText( text_offset, CFmtStr("Exit: %s", m_bExitLocked ? "Locked" : "Unlocked" ), 0 ); - text_offset++; - } - - return text_offset; -} - -#define TRANSITION_SEARCH_RADIUS (100*12) - -//----------------------------------------------------------------------------- -// Purpose: Teleport the car to a destination that will cause it to transition if it's not going to otherwise -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::InputOutsideTransition( inputdata_t &inputdata ) -{ - // Teleport into the new map - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - Vector vecTeleportPos; - QAngle vecTeleportAngles; - - // Get our bounds - Vector vecSurroundMins, vecSurroundMaxs; - CollisionProp()->WorldSpaceSurroundingBounds( &vecSurroundMins, &vecSurroundMaxs ); - vecSurroundMins -= WorldSpaceCenter(); - vecSurroundMaxs -= WorldSpaceCenter(); - - Vector vecBestPos; - QAngle vecBestAngles; - - CInfoTargetVehicleTransition *pEntity = NULL; - bool bSucceeded = false; - - // Find all entities of the correct name and try and sit where they're at - while ( ( pEntity = (CInfoTargetVehicleTransition *) gEntList.FindEntityByClassname( pEntity, "info_target_vehicle_transition" ) ) != NULL ) - { - // Must be enabled - if ( pEntity->IsDisabled() ) - continue; - - // Must be within range - if ( ( pEntity->GetAbsOrigin() - pPlayer->GetAbsOrigin() ).LengthSqr() > Square( TRANSITION_SEARCH_RADIUS ) ) - continue; - - vecTeleportPos = pEntity->GetAbsOrigin(); - vecTeleportAngles = pEntity->GetAbsAngles() + QAngle( 0, -90, 0 ); // Vehicle is always off by 90 degrees - - // Rotate to face the destination angles - Vector vecMins; - Vector vecMaxs; - VectorRotate( vecSurroundMins, vecTeleportAngles, vecMins ); - VectorRotate( vecSurroundMaxs, vecTeleportAngles, vecMaxs ); - - if ( vecMaxs.x < vecMins.x ) - swap( vecMins.x, vecMaxs.x ); - - if ( vecMaxs.y < vecMins.y ) - swap( vecMins.y, vecMaxs.y ); - - if ( vecMaxs.z < vecMins.z ) - swap( vecMins.z, vecMaxs.z ); - - // Move up - vecTeleportPos.z += ( vecMaxs.z - vecMins.z ); - - trace_t tr; - UTIL_TraceHull( vecTeleportPos, vecTeleportPos - Vector( 0, 0, 128 ), vecMins, vecMaxs, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - if ( tr.startsolid == false && tr.allsolid == false && tr.fraction < 1.0f ) - { - // Store this off - vecBestPos = tr.endpos; - vecBestAngles = vecTeleportAngles; - bSucceeded = true; - - // If this point isn't visible, then stop looking and use it - if ( pPlayer->FInViewCone( tr.endpos ) == false ) - break; - } - } - - // See if we're finished - if ( bSucceeded ) - { - Teleport( &vecTeleportPos, &vecTeleportAngles, NULL ); - return; - } - - // TODO: We found no valid teleport points, so try to find them dynamically - Warning("No valid vehicle teleport points!\n"); -} - -//----------------------------------------------------------------------------- -// Purpose: Stop players punting the car around. -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::InputDisablePhysGun( inputdata_t &data ) -{ - AddEFlags( EFL_NO_PHYSCANNON_INTERACTION ); -} -//----------------------------------------------------------------------------- -// Purpose: Return to normal -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::InputEnablePhysGun( inputdata_t &data ) -{ - RemoveEFlags( EFL_NO_PHYSCANNON_INTERACTION ); -} - -//----------------------------------------------------------------------------- -// Create and parent two radial node link controllers. -//----------------------------------------------------------------------------- -void CPropJeepEpisodic::InputCreateLinkController( inputdata_t &data ) -{ - Vector vecFront, vecRear; - Vector vecWFL, vecWFR; // Front wheels - Vector vecWRL, vecWRR; // Back wheels - - GetAttachment( "wheel_fr", vecWFR ); - GetAttachment( "wheel_fl", vecWFL ); - - GetAttachment( "wheel_rr", vecWRR ); - GetAttachment( "wheel_rl", vecWRL ); - - vecFront = (vecWFL + vecWFR) * 0.5f; - vecRear = (vecWRL + vecWRR) * 0.5f; - - float flRadius = ( (vecFront - vecRear).Length() ) * 0.6f; - - CAI_RadialLinkController *pLinkController = (CAI_RadialLinkController *)CreateEntityByName( "info_radial_link_controller" ); - if( pLinkController != NULL && m_hLinkControllerFront.Get() == NULL ) - { - pLinkController->m_flRadius = flRadius; - pLinkController->Spawn(); - pLinkController->SetAbsOrigin( vecFront ); - pLinkController->SetOwnerEntity( this ); - pLinkController->SetParent( this ); - pLinkController->Activate(); - m_hLinkControllerFront.Set( pLinkController ); - - //NDebugOverlay::Circle( vecFront, Vector(0,1,0), Vector(1,0,0), flRadius, 255, 255, 255, 128, false, 100 ); - } - - pLinkController = (CAI_RadialLinkController *)CreateEntityByName( "info_radial_link_controller" ); - if( pLinkController != NULL && m_hLinkControllerRear.Get() == NULL ) - { - pLinkController->m_flRadius = flRadius; - pLinkController->Spawn(); - pLinkController->SetAbsOrigin( vecRear ); - pLinkController->SetOwnerEntity( this ); - pLinkController->SetParent( this ); - pLinkController->Activate(); - m_hLinkControllerRear.Set( pLinkController ); - - //NDebugOverlay::Circle( vecRear, Vector(0,1,0), Vector(1,0,0), flRadius, 255, 255, 255, 128, false, 100 ); - } -} - -void CPropJeepEpisodic::InputDestroyLinkController( inputdata_t &data ) -{ - if( m_hLinkControllerFront.Get() != NULL ) - { - CAI_RadialLinkController *pLinkController = dynamic_cast(m_hLinkControllerFront.Get()); - if( pLinkController != NULL ) - { - pLinkController->ModifyNodeLinks(false); - UTIL_Remove( pLinkController ); - m_hLinkControllerFront.Set(NULL); - } - } - - if( m_hLinkControllerRear.Get() != NULL ) - { - CAI_RadialLinkController *pLinkController = dynamic_cast(m_hLinkControllerRear.Get()); - if( pLinkController != NULL ) - { - pLinkController->ModifyNodeLinks(false); - UTIL_Remove( pLinkController ); - m_hLinkControllerRear.Set(NULL); - } - } -} - - -bool CPropJeepEpisodic::AllowBlockedExit( CBaseCombatCharacter *pPassenger, int nRole ) -{ - // Wait until we've settled down before we resort to blocked exits. - // This keeps us from doing blocked exits in mid-jump, which can cause mayhem like - // sticking the player through player clips or into geometry. - return GetSmoothedVelocity().IsLengthLessThan( jalopy_blocked_exit_max_speed.GetFloat() ); -} - diff --git a/game/server/episodic/vehicle_jeep_episodic.h b/game/server/episodic/vehicle_jeep_episodic.h deleted file mode 100644 index 76c41d7d9..000000000 --- a/game/server/episodic/vehicle_jeep_episodic.h +++ /dev/null @@ -1,150 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef VEHICLE_JEEP_EPISODIC_H -#define VEHICLE_JEEP_EPISODIC_H -#ifdef _WIN32 -#pragma once -#endif - -#include "vehicle_jeep.h" -#include "ai_basenpc.h" -#include "hl2_vehicle_radar.h" - -class CParticleSystem; -class CVehicleCargoTrigger; -class CSprite; - -#define NUM_WHEEL_EFFECTS 2 -#define NUM_HAZARD_LIGHTS 4 - -//============================================================================= -// Episodic jeep - -class CPropJeepEpisodic : public CPropJeep -{ - DECLARE_CLASS( CPropJeepEpisodic, CPropJeep ); - DECLARE_SERVERCLASS(); - -public: - CPropJeepEpisodic( void ); - - virtual void Spawn( void ); - virtual void Activate( void ); - virtual void Think( void ); - virtual void UpdateOnRemove( void ); - - virtual void NPC_FinishedEnterVehicle( CAI_BaseNPC *pPassenger, bool bCompanion ); - virtual void NPC_FinishedExitVehicle( CAI_BaseNPC *pPassenger, bool bCompanion ); - - virtual bool NPC_CanEnterVehicle( CAI_BaseNPC *pPassenger, bool bCompanion ); - virtual bool NPC_CanExitVehicle( CAI_BaseNPC *pPassenger, bool bCompanion ); - virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - virtual void Precache( void ); - virtual void EnterVehicle( CBaseCombatCharacter *pPassenger ); - virtual void ExitVehicle( int nRole ); - virtual bool AllowBlockedExit( CBaseCombatCharacter *pPassenger, int nRole ); - - // Passengers take no damage except what we pass them - virtual bool PassengerShouldReceiveDamage( CTakeDamageInfo &info ) - { - if ( GetServerVehicle() && GetServerVehicle()->IsPassengerExiting() ) - return false; - - return ( info.GetDamageType() & DMG_VEHICLE ) != 0; - } - - virtual int ObjectCaps( void ) { return (BaseClass::ObjectCaps() | FCAP_NOTIFY_ON_TRANSITION); } - - void SpawnRadarPanel(); - void DestroyRadarPanel(); - int NumRadarContacts() { return m_iNumRadarContacts; } - - void AddPropToCargoHold( CPhysicsProp *pProp ); - - virtual CBaseEntity *OnFailedPhysGunPickup( Vector vPhysgunPos ); - virtual void DriveVehicle( float flFrameTime, CUserCmd *ucmd, int iButtonsDown, int iButtonsReleased ); - virtual int DrawDebugTextOverlays( void ); - - DECLARE_DATADESC(); - -protected: - void HazardBlinkThink( void ); - void CreateHazardLights( void ); - void DestroyHazardLights( void ); - - void UpdateCargoEntry( void ); - void ReleasePropFromCargoHold( void ); - void CreateCargoTrigger( void ); - virtual float GetUprightTime( void ) { return 1.0f; } - virtual float GetUprightStrength( void ); - virtual bool ShouldPuntUseLaunchForces( PhysGunForce_t reason ) { return ( reason == PHYSGUN_FORCE_PUNTED ); } - virtual void HandleWater( void ); - - virtual AngularImpulse PhysGunLaunchAngularImpulse( void ); - virtual Vector PhysGunLaunchVelocity( const Vector &forward, float flMass ); - bool PassengerInTransition( void ); - - void SetBusterHopperVisibility(bool visible); - -private: - - void UpdateWheelDust( void ); - void UpdateRadar( bool forceUpdate = false ); - - void InputLockEntrance( inputdata_t &data ); - void InputUnlockEntrance( inputdata_t &data ); - void InputLockExit( inputdata_t &data ); - void InputUnlockExit( inputdata_t &data ); - void InputEnableRadar( inputdata_t &data ); - void InputDisableRadar( inputdata_t &data ); - void InputEnableRadarDetectEnemies( inputdata_t &data ); - void InputAddBusterToCargo( inputdata_t &data ); - void InputSetCargoVisibility( inputdata_t &data ); - void InputOutsideTransition( inputdata_t &data ); - void InputDisablePhysGun( inputdata_t &data ); - void InputEnablePhysGun( inputdata_t &data ); - void InputCreateLinkController( inputdata_t &data ); - void InputDestroyLinkController( inputdata_t &data ); - void CreateAvoidanceZone( void ); - - bool m_bEntranceLocked; - bool m_bExitLocked; - bool m_bAddingCargo; - bool m_bBlink; - - float m_flCargoStartTime; // Time when the cargo was first added to the vehicle (used for animating into hold) - float m_flNextAvoidBroadcastTime; // Next time we'll warn entity to move out of us - - COutputEvent m_OnCompanionEnteredVehicle; // Passenger has completed entering the vehicle - COutputEvent m_OnCompanionExitedVehicle; // Passenger has completed exited the vehicle - COutputEvent m_OnHostileEnteredVehicle; // Passenger has completed entering the vehicle - COutputEvent m_OnHostileExitedVehicle; // Passenger has completed exited the vehicle - - CHandle< CParticleSystem > m_hWheelDust[NUM_WHEEL_EFFECTS]; - CHandle< CParticleSystem > m_hWheelWater[NUM_WHEEL_EFFECTS]; - CHandle< CVehicleCargoTrigger > m_hCargoTrigger; - CHandle< CPhysicsProp > m_hCargoProp; - - CHandle< CSprite > m_hHazardLights[NUM_HAZARD_LIGHTS]; - float m_flNextWaterSound; - - bool m_bRadarEnabled; - bool m_bRadarDetectsEnemies; - float m_flNextRadarUpdateTime; - EHANDLE m_hRadarScreen; - - EHANDLE m_hLinkControllerFront; - EHANDLE m_hLinkControllerRear; - - bool m_bBusterHopperVisible; // is the hopper assembly visible on the vehicle? please do not set this directly - use the accessor funct. - - CNetworkVar( int, m_iNumRadarContacts ); - CNetworkArray( Vector, m_vecRadarContactPos, RADAR_MAX_CONTACTS ); - CNetworkArray( int, m_iRadarContactType, RADAR_MAX_CONTACTS ); -}; - -#endif // VEHICLE_JEEP_EPISODIC_H diff --git a/game/server/episodic/weapon_hopwire.cpp b/game/server/episodic/weapon_hopwire.cpp deleted file mode 100644 index d5d454555..000000000 --- a/game/server/episodic/weapon_hopwire.cpp +++ /dev/null @@ -1,508 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "basehlcombatweapon.h" -#include "player.h" -#include "gamerules.h" -#include "grenade_frag.h" -#include "npcevent.h" -#include "engine/IEngineSound.h" -#include "items.h" -#include "in_buttons.h" -#include "soundent.h" -#include "grenade_hopwire.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define GRENADE_TIMER 2.0f //Seconds - -#define GRENADE_PAUSED_NO 0 -#define GRENADE_PAUSED_PRIMARY 1 -#define GRENADE_PAUSED_SECONDARY 2 - -#define GRENADE_RADIUS 4.0f // inches - -//----------------------------------------------------------------------------- -// Fragmentation grenades -//----------------------------------------------------------------------------- -class CWeaponHopwire: public CBaseHLCombatWeapon -{ - DECLARE_CLASS( CWeaponHopwire, CBaseHLCombatWeapon ); -public: - DECLARE_SERVERCLASS(); - - void Precache( void ); - void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); - void PrimaryAttack( void ); - void SecondaryAttack( void ); - void DecrementAmmo( CBaseCombatCharacter *pOwner ); - void ItemPostFrame( void ); - - void HandleFireOnEmpty( void ); - bool HasAnyAmmo( void ); - bool Deploy( void ); - bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); - - int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } - - bool Reload( void ); - -private: - void ThrowGrenade( CBasePlayer *pPlayer ); - void RollGrenade( CBasePlayer *pPlayer ); - void LobGrenade( CBasePlayer *pPlayer ); - // check a throw from vecSrc. If not valid, move the position back along the line to vecEye - void CheckThrowPosition( CBasePlayer *pPlayer, const Vector &vecEye, Vector &vecSrc ); - - bool m_bRedraw; //Draw the weapon again after throwing a grenade - - int m_AttackPaused; - bool m_fDrawbackFinished; - - CHandle m_hActiveHopWire; - - DECLARE_ACTTABLE(); - - DECLARE_DATADESC(); -}; - - -BEGIN_DATADESC( CWeaponHopwire ) - DEFINE_FIELD( m_bRedraw, FIELD_BOOLEAN ), - DEFINE_FIELD( m_AttackPaused, FIELD_INTEGER ), - DEFINE_FIELD( m_fDrawbackFinished, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hActiveHopWire, FIELD_EHANDLE ), -END_DATADESC() - -acttable_t CWeaponHopwire::m_acttable[] = -{ - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SLAM, true }, -}; - -IMPLEMENT_ACTTABLE(CWeaponHopwire); - -IMPLEMENT_SERVERCLASS_ST(CWeaponHopwire, DT_WeaponHopwire) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_hopwire, CWeaponHopwire ); -PRECACHE_WEAPON_REGISTER(weapon_hopwire); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponHopwire::Precache( void ) -{ - BaseClass::Precache(); - - UTIL_PrecacheOther( "npc_grenade_hopwire" ); - - PrecacheScriptSound( "WeaponFrag.Throw" ); - PrecacheScriptSound( "WeaponFrag.Roll" ); - - m_bRedraw = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CWeaponHopwire::Deploy( void ) -{ - m_bRedraw = false; - m_fDrawbackFinished = false; - - return BaseClass::Deploy(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponHopwire::Holster( CBaseCombatWeapon *pSwitchingTo ) -{ - if ( m_hActiveHopWire != NULL ) - return false; - - m_bRedraw = false; - m_fDrawbackFinished = false; - - return BaseClass::Holster( pSwitchingTo ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEvent - -// *pOperator - -//----------------------------------------------------------------------------- -void CWeaponHopwire::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - bool fThrewGrenade = false; - - switch( pEvent->event ) - { - case EVENT_WEAPON_SEQUENCE_FINISHED: - m_fDrawbackFinished = true; - break; - - case EVENT_WEAPON_THROW: - ThrowGrenade( pOwner ); - DecrementAmmo( pOwner ); - fThrewGrenade = true; - break; - - case EVENT_WEAPON_THROW2: - RollGrenade( pOwner ); - DecrementAmmo( pOwner ); - fThrewGrenade = true; - break; - - case EVENT_WEAPON_THROW3: - LobGrenade( pOwner ); - DecrementAmmo( pOwner ); - fThrewGrenade = true; - break; - - default: - BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); - break; - } - -#define RETHROW_DELAY 0.5 - if( fThrewGrenade ) - { - m_flNextPrimaryAttack = gpGlobals->curtime + RETHROW_DELAY; - m_flNextSecondaryAttack = gpGlobals->curtime + RETHROW_DELAY; - m_flTimeWeaponIdle = FLT_MAX; //NOTE: This is set once the animation has finished up! - - // Make a sound designed to scare snipers back into their holes! - CBaseCombatCharacter *pOwner = GetOwner(); - - if( pOwner ) - { - Vector vecSrc = pOwner->Weapon_ShootPosition(); - Vector vecDir; - - AngleVectors( pOwner->EyeAngles(), &vecDir ); - - trace_t tr; - - UTIL_TraceLine( vecSrc, vecSrc + vecDir * 1024, MASK_SOLID_BRUSHONLY, pOwner, COLLISION_GROUP_NONE, &tr ); - - CSoundEnt::InsertSound( SOUND_DANGER_SNIPERONLY, tr.endpos, 384, 0.2, pOwner ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Override the ammo behavior so we never disallow pulling the weapon out -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponHopwire::HasAnyAmmo( void ) -{ - if ( m_hActiveHopWire != NULL ) - return true; - - return BaseClass::HasAnyAmmo(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponHopwire::Reload( void ) -{ - if ( !HasPrimaryAmmo() ) - return false; - - if ( ( m_bRedraw ) && ( m_flNextPrimaryAttack <= gpGlobals->curtime ) && ( m_flNextSecondaryAttack <= gpGlobals->curtime ) ) - { - //Redraw the weapon - SendWeaponAnim( ACT_VM_DRAW ); - - //Update our times - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration(); - m_flTimeWeaponIdle = gpGlobals->curtime + SequenceDuration(); - - //Mark this as done - m_bRedraw = false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponHopwire::SecondaryAttack( void ) -{ - /* - if ( m_bRedraw ) - return; - - if ( !HasPrimaryAmmo() ) - return; - - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( pOwner ); - - if ( pPlayer == NULL ) - return; - - // Note that this is a secondary attack and prepare the grenade attack to pause. - m_AttackPaused = GRENADE_PAUSED_SECONDARY; - SendWeaponAnim( ACT_VM_PULLBACK_LOW ); - - // Don't let weapon idle interfere in the middle of a throw! - m_flTimeWeaponIdle = FLT_MAX; - m_flNextSecondaryAttack = FLT_MAX; - - // If I'm now out of ammo, switch away - if ( !HasPrimaryAmmo() ) - { - pPlayer->SwitchToNextBestWeapon( this ); - } - */ -} - -//----------------------------------------------------------------------------- -// Purpose: Allow activation even if this is our last piece of ammo -//----------------------------------------------------------------------------- -void CWeaponHopwire::HandleFireOnEmpty( void ) -{ - if ( m_hActiveHopWire!= NULL ) - { - // FIXME: This toggle is hokey - m_bRedraw = false; - PrimaryAttack(); - m_bRedraw = true; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponHopwire::PrimaryAttack( void ) -{ - if ( m_bRedraw ) - return; - - CBaseCombatCharacter *pOwner = GetOwner(); - if ( pOwner == NULL ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );; - if ( !pPlayer ) - return; - - // See if we're in trap mode - if ( hopwire_trap.GetBool() && ( m_hActiveHopWire != NULL ) ) - { - // Spring the trap - m_hActiveHopWire->Detonate(); - m_hActiveHopWire = NULL; - - // Don't allow another throw for awhile - m_flTimeWeaponIdle = m_flNextPrimaryAttack = gpGlobals->curtime + 2.0f; - - return; - } - - // Note that this is a primary attack and prepare the grenade attack to pause. - /* - m_AttackPaused = GRENADE_PAUSED_PRIMARY; - SendWeaponAnim( ACT_VM_PULLBACK_HIGH ); - */ - m_AttackPaused = GRENADE_PAUSED_SECONDARY; - SendWeaponAnim( ACT_VM_PULLBACK_LOW ); - - // Put both of these off indefinitely. We do not know how long - // the player will hold the grenade. - m_flTimeWeaponIdle = FLT_MAX; - m_flNextPrimaryAttack = FLT_MAX; - - // If I'm now out of ammo, switch away - /* - if ( !HasPrimaryAmmo() ) - { - pPlayer->SwitchToNextBestWeapon( this ); - } - */ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOwner - -//----------------------------------------------------------------------------- -void CWeaponHopwire::DecrementAmmo( CBaseCombatCharacter *pOwner ) -{ - pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponHopwire::ItemPostFrame( void ) -{ - if( m_fDrawbackFinished ) - { - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if (pOwner) - { - switch( m_AttackPaused ) - { - case GRENADE_PAUSED_PRIMARY: - if( !(pOwner->m_nButtons & IN_ATTACK) ) - { - SendWeaponAnim( ACT_VM_THROW ); - m_fDrawbackFinished = false; - } - break; - - case GRENADE_PAUSED_SECONDARY: - if( !(pOwner->m_nButtons & (IN_ATTACK|IN_ATTACK2)) ) - { - //See if we're ducking - if ( pOwner->m_nButtons & IN_DUCK ) - { - //Send the weapon animation - SendWeaponAnim( ACT_VM_SECONDARYATTACK ); - } - else - { - //Send the weapon animation - SendWeaponAnim( ACT_VM_HAULBACK ); - } - - m_fDrawbackFinished = false; - } - break; - - default: - break; - } - } - } - - BaseClass::ItemPostFrame(); - - if ( m_bRedraw ) - { - if ( IsViewModelSequenceFinished() ) - { - Reload(); - } - } -} - - // check a throw from vecSrc. If not valid, move the position back along the line to vecEye -void CWeaponHopwire::CheckThrowPosition( CBasePlayer *pPlayer, const Vector &vecEye, Vector &vecSrc ) -{ - trace_t tr; - - UTIL_TraceHull( vecEye, vecSrc, -Vector(GRENADE_RADIUS+2,GRENADE_RADIUS+2,GRENADE_RADIUS+2), Vector(GRENADE_RADIUS+2,GRENADE_RADIUS+2,GRENADE_RADIUS+2), - pPlayer->PhysicsSolidMaskForEntity(), pPlayer, pPlayer->GetCollisionGroup(), &tr ); - - if ( tr.DidHit() ) - { - vecSrc = tr.endpos; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -//----------------------------------------------------------------------------- -void CWeaponHopwire::ThrowGrenade( CBasePlayer *pPlayer ) -{ - Vector vecEye = pPlayer->EyePosition(); - Vector vForward, vRight; - - pPlayer->EyeVectors( &vForward, &vRight, NULL ); - Vector vecSrc = vecEye + vForward * 18.0f + vRight * 8.0f; - CheckThrowPosition( pPlayer, vecEye, vecSrc ); - vForward[2] += 0.1f; - - Vector vecThrow; - pPlayer->GetVelocity( &vecThrow, NULL ); - vecThrow += vForward * 1200; - m_hActiveHopWire = static_cast (HopWire_Create( vecSrc, vec3_angle, vecThrow, AngularImpulse(600,random->RandomInt(-1200,1200),0), pPlayer, GRENADE_TIMER )); - - m_bRedraw = true; - - WeaponSound( SINGLE ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -//----------------------------------------------------------------------------- -void CWeaponHopwire::LobGrenade( CBasePlayer *pPlayer ) -{ - Vector vecEye = pPlayer->EyePosition(); - Vector vForward, vRight; - - pPlayer->EyeVectors( &vForward, &vRight, NULL ); - Vector vecSrc = vecEye + vForward * 18.0f + vRight * 8.0f + Vector( 0, 0, -8 ); - CheckThrowPosition( pPlayer, vecEye, vecSrc ); - - Vector vecThrow; - pPlayer->GetVelocity( &vecThrow, NULL ); - vecThrow += vForward * 350 + Vector( 0, 0, 50 ); - m_hActiveHopWire = static_cast (HopWire_Create( vecSrc, vec3_angle, vecThrow, AngularImpulse(200,random->RandomInt(-600,600),0), pPlayer, GRENADE_TIMER )); - - WeaponSound( WPN_DOUBLE ); - - m_bRedraw = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -//----------------------------------------------------------------------------- -void CWeaponHopwire::RollGrenade( CBasePlayer *pPlayer ) -{ - // BUGBUG: Hardcoded grenade width of 4 - better not change the model :) - Vector vecSrc; - pPlayer->CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 0.0f ), &vecSrc ); - vecSrc.z += GRENADE_RADIUS; - - Vector vecFacing = pPlayer->BodyDirection2D( ); - // no up/down direction - vecFacing.z = 0; - VectorNormalize( vecFacing ); - trace_t tr; - UTIL_TraceLine( vecSrc, vecSrc - Vector(0,0,16), MASK_PLAYERSOLID, pPlayer, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction != 1.0 ) - { - // compute forward vec parallel to floor plane and roll grenade along that - Vector tangent; - CrossProduct( vecFacing, tr.plane.normal, tangent ); - CrossProduct( tr.plane.normal, tangent, vecFacing ); - } - vecSrc += (vecFacing * 18.0); - CheckThrowPosition( pPlayer, pPlayer->WorldSpaceCenter(), vecSrc ); - - Vector vecThrow; - pPlayer->GetVelocity( &vecThrow, NULL ); - vecThrow += vecFacing * 700; - // put it on its side - QAngle orientation(0,pPlayer->GetLocalAngles().y,-90); - // roll it - AngularImpulse rotSpeed(0,0,720); - m_hActiveHopWire = static_cast (HopWire_Create( vecSrc, orientation, vecThrow, rotSpeed, pPlayer, GRENADE_TIMER )); - - WeaponSound( SPECIAL1 ); - - m_bRedraw = true; -} diff --git a/game/server/episodic/weapon_oldmanharpoon.cpp b/game/server/episodic/weapon_oldmanharpoon.cpp deleted file mode 100644 index 438b07f27..000000000 --- a/game/server/episodic/weapon_oldmanharpoon.cpp +++ /dev/null @@ -1,36 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#include "weapon_citizenpackage.h" - -//----------------------------------------------------------------------------- -// Purpose: Old Man Harpoon - Lost Coast. -//----------------------------------------------------------------------------- -class CWeaponOldManHarpoon : public CWeaponCitizenPackage -{ - DECLARE_CLASS( CWeaponOldManHarpoon, CWeaponCitizenPackage ); -public: - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - DECLARE_ACTTABLE(); -}; - -IMPLEMENT_SERVERCLASS_ST( CWeaponOldManHarpoon, DT_WeaponOldManHarpoon ) -END_SEND_TABLE() - -BEGIN_DATADESC( CWeaponOldManHarpoon ) -END_DATADESC() - -LINK_ENTITY_TO_CLASS( weapon_oldmanharpoon, CWeaponOldManHarpoon ); -PRECACHE_WEAPON_REGISTER( weapon_oldmanharpoon ); - -acttable_t CWeaponOldManHarpoon::m_acttable[] = -{ - { ACT_IDLE, ACT_IDLE_SUITCASE, false }, - { ACT_WALK, ACT_WALK_SUITCASE, false }, -}; -IMPLEMENT_ACTTABLE( CWeaponOldManHarpoon ); diff --git a/game/server/episodic/weapon_striderbuster.cpp b/game/server/episodic/weapon_striderbuster.cpp deleted file mode 100644 index f75e51ea8..000000000 --- a/game/server/episodic/weapon_striderbuster.cpp +++ /dev/null @@ -1,1175 +0,0 @@ -//====== Copyright 1996-2007, Valve Corporation, All rights reserved. ======= -// -// An ingenious device. We call it "The Magnusson Device". Not my chosen label, -// you understand, but it seemed to please the personnel. -// -// From your point of view you simply throw it at a strider and then blow it up. -// -//============================================================================= - -#include "cbase.h" -#include "props.h" -#include "vphysics/constraints.h" -#include "physics_saverestore.h" -#include "model_types.h" -#include "ai_utils.h" -#include "particle_system.h" -#include "Sprite.h" -#include "citadel_effects_shared.h" -#include "soundent.h" -#include "SpriteTrail.h" -#include "te_effect_dispatch.h" -#include "beam_shared.h" -#include "npc_strider.h" -#include "npc_hunter.h" -#include "particle_parse.h" -#include "gameweaponmanager.h" -#include "GameStats.h" - -extern ConVar hunter_hate_held_striderbusters; -extern ConVar hunter_hate_thrown_striderbusters; -extern ConVar hunter_hate_attached_striderbusters; - - -ConVar striderbuster_health( "striderbuster_health", "14" ); -ConVar striderbuster_autoaim_radius( "striderbuster_autoaim_radius", "64.0f" ); -ConVar striderbuster_shot_velocity( "striderbuster_shot_velocity", "2500.0", FCVAR_NONE, "Speed at which launch the bomb from the physcannon" ); -ConVar striderbuster_allow_all_damage( "striderbuster_allow_all_damage", "0", FCVAR_NONE, "If set to '1' the bomb will detonate on any damage taken. Otherwise only the player may trigger it." ); - -//ConVar striderbuster_magnetic_radius("striderbuster_magnetic_radius","400.0f", FCVAR_NONE,"Maximum distance at which magnade experiences attraction to a target. Set to 0 to disable magnetism."); -ConVar striderbuster_magnetic_force_strider("striderbuster_magnetic_force_strider", "750000.0f", FCVAR_NONE,"Intensity of magnade's attraction to a strider."); -ConVar striderbuster_magnetic_force_hunter("striderbuster_magnetic_force_hunter","1750000.0f",FCVAR_NONE,"Intensity of magnade's attraction to a hunter."); -ConVar striderbuster_falloff_power("striderbuster_falloff_power","4",FCVAR_NONE,"Order of the distance falloff. 1 = linear 2 = quadratic"); -ConVar striderbuster_leg_stick_dist( "striderbuster_leg_stick_dist", "80.0", FCVAR_NONE, "If the buster hits a strider's leg, the max distance from the head at which it sticks anyway." ); -ConVar striderbuster_debugseek( "striderbuster_debugseek", "0" ); - -ConVar sk_striderbuster_magnet_multiplier( "sk_striderbuster_magnet_multiplier", "2.25" ); - -ConVar striderbuster_die_detach( "striderbuster_die_detach", "1" ); // Drop off the strider if a hunter shoots me. (Instead of exploding) -ConVar striderbuster_dive_force( "striderbuster_dive_force", "-200" ); // How much force to apply to a nosediving (dead in the air) striderbuster - -ConVar striderbuster_use_particle_flare( "striderbuster_use_particle_flare", "1" ); - -#define STRIDERBUSTER_FLAG_KNOCKED_OFF_STRIDER 0x00000001 // We were knocked off of a strider after the player attached me. - -#define SF_DONT_WEAPON_MANAGE 0x800000 - -#define STRIDERBUSTER_SPRITE_TRAIL "sprites/bluelaser1.vmt" - -string_t g_iszVehicle; - -#define BUSTER_PING_SOUND_FREQ 3.0f // How often (seconds) to issue the ping sound to remind players we are attached - -static const char *s_pBusterPingThinkContext = "BusterPing"; - -class CWeaponStriderBuster : public CPhysicsProp -{ - DECLARE_CLASS( CWeaponStriderBuster, CPhysicsProp ); - DECLARE_DATADESC(); - -public: - CWeaponStriderBuster( void ); - - virtual void Precache( void ); - virtual void Spawn( void ); - virtual void Activate( void ); - - // Treat as a live target so hunters can attack us - virtual bool IsAlive() { return true; } - - virtual void OnRestore( void ); - virtual void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); - virtual void UpdateOnRemove( void ); - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - virtual bool ShouldPuntUseLaunchForces( PhysGunForce_t reason ) { return ( reason == PHYSGUN_FORCE_LAUNCHED ); } - virtual QAngle PreferredCarryAngles( void ) { return m_CarryAngles; } - virtual bool HasPreferredCarryAnglesForPlayer( CBasePlayer *pPlayer ) { return true; } - - virtual void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ); - virtual void OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ); - virtual Vector PhysGunLaunchVelocity( const Vector &forward, float flMass ); - virtual float GetAutoAimRadius( void ) { return striderbuster_autoaim_radius.GetFloat(); } - virtual void BusterTouch( CBaseEntity *pOther ); - - virtual bool ShouldAttractAutoAim( CBaseEntity *pAimingEnt ) { return IsAttachedToStrider(); } - - void InputConstraintBroken( inputdata_t &inputdata ); - void BusterFlyThink(); - void BusterDetachThink(); - void BusterPingThink(); - - void OnAddToCargoHold(); - void OnFlechetteAttach( Vector &vecForceDir ); - int NumFlechettesAttached() { return m_nAttachedFlechettes; } - - float GetPickupTime() { return m_PickupTime; } - - int GetStriderBusterFlags() { return m_iBusterFlags; } // I added a flags field so we don't have to keep added bools for all of these contingencies (sjb) - -private: - - void Launch( CBasePlayer *pPhysGunUser ); - void Detonate( void ); - void Shatter( CBaseEntity *pAttacker ); - bool StickToEntity( CBaseEntity *pOther ); - bool CreateConstraintToObject( CBaseEntity *pObject ); - void DestroyConstraint( void ); - bool ShouldStickToEntity( CBaseEntity *pEntity ); - void CreateDestroyedEffect( void ); - - inline bool IsAttachedToStrider( void ) const; - - bool m_bDud; - bool m_bLaunched; - bool m_bNoseDiving; // No magnetism, nosedive and break. Hunter flechettes set this. - int m_nAttachedFlechettes; - float m_flCollisionSpeedSqr; - int m_nAttachedBoneFollowerIndex; - float m_PickupTime; - - IPhysicsConstraint *m_pConstraint; - EHANDLE m_hConstrainedEntity; - - CHandle m_hGlowSprite; - CHandle m_hMainGlow; - - //CHandle m_hGlowTrail; - EHANDLE m_hParticleEffect; - - int m_nRingTexture; - - QAngle m_CarryAngles; - - int m_iBusterFlags; - - COutputEvent m_OnAttachToStrider; - COutputEvent m_OnDetonate; - COutputEvent m_OnShatter; - COutputEvent m_OnShotDown; - -friend bool StriderBuster_IsAttachedStriderBuster( CBaseEntity *pEntity, CBaseEntity * ); - -}; - -LINK_ENTITY_TO_CLASS( prop_stickybomb, CWeaponStriderBuster ); -LINK_ENTITY_TO_CLASS( weapon_striderbuster, CWeaponStriderBuster ); - -BEGIN_DATADESC( CWeaponStriderBuster ) - DEFINE_KEYFIELD( m_bDud, FIELD_BOOLEAN, "dud" ), - - DEFINE_FIELD( m_bLaunched, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bNoseDiving, FIELD_BOOLEAN ), - DEFINE_FIELD( m_nAttachedFlechettes, FIELD_INTEGER ), - DEFINE_FIELD( m_flCollisionSpeedSqr, FIELD_FLOAT ), - DEFINE_FIELD( m_hConstrainedEntity, FIELD_EHANDLE ), - DEFINE_FIELD( m_hGlowSprite, FIELD_EHANDLE ), - DEFINE_FIELD( m_hMainGlow, FIELD_EHANDLE ), - //DEFINE_FIELD( m_hGlowTrail, FIELD_EHANDLE ), - - DEFINE_FIELD( m_nRingTexture, FIELD_INTEGER ), - DEFINE_FIELD( m_nAttachedBoneFollowerIndex, FIELD_INTEGER ), - - DEFINE_FIELD( m_PickupTime, FIELD_TIME ), - - DEFINE_FIELD( m_hParticleEffect, FIELD_EHANDLE ), - - DEFINE_FIELD( m_CarryAngles, FIELD_VECTOR ), - - DEFINE_FIELD( m_iBusterFlags, FIELD_INTEGER ), - DEFINE_PHYSPTR( m_pConstraint ), - - DEFINE_INPUTFUNC( FIELD_VOID, "ConstraintBroken", InputConstraintBroken ), - - DEFINE_OUTPUT( m_OnAttachToStrider, "OnAttachToStrider" ), - DEFINE_OUTPUT( m_OnDetonate, "OnDetonate" ), - DEFINE_OUTPUT( m_OnShatter, "OnShatter" ), - DEFINE_OUTPUT( m_OnShotDown, "OnShotDown" ), - - DEFINE_ENTITYFUNC( BusterTouch ), - DEFINE_THINKFUNC( BusterFlyThink ), - DEFINE_THINKFUNC( BusterDetachThink ), - DEFINE_THINKFUNC( BusterPingThink ), -END_DATADESC() - -CWeaponStriderBuster::CWeaponStriderBuster( void ) : - m_flCollisionSpeedSqr( -1.0f ), - m_nAttachedBoneFollowerIndex( -1 ), - m_pConstraint( NULL ), - m_hConstrainedEntity( NULL ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponStriderBuster::Precache( void ) -{ - PrecacheScriptSound( "Weapon_StriderBuster.StickToEntity" ); - PrecacheScriptSound( "Weapon_StriderBuster.Detonate" ); - PrecacheScriptSound( "Weapon_StriderBuster.Dud_Detonate" ); - PrecacheScriptSound( "Weapon_StriderBuster.Ping" ); - - PrecacheModel("sprites/orangeflare1.vmt"); - - UTIL_PrecacheOther( "env_citadel_energy_core" ); - UTIL_PrecacheOther( "sparktrail" ); - - m_nRingTexture = PrecacheModel( "sprites/lgtning.vmt" ); - - PrecacheParticleSystem( "striderbuster_attach" ); - PrecacheParticleSystem( "striderbuster_attached_pulse" ); - PrecacheParticleSystem( "striderbuster_explode_core" ); - PrecacheParticleSystem( "striderbuster_explode_dummy_core" ); - PrecacheParticleSystem( "striderbuster_break_flechette" ); - PrecacheParticleSystem( "striderbuster_trail" ); - PrecacheParticleSystem( "striderbuster_shotdown_trail" ); - PrecacheParticleSystem( "striderbuster_break" ); - PrecacheParticleSystem( "striderbuster_flechette_attached" ); - - SetModelName( AllocPooledString("models/magnusson_device.mdl") ); - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponStriderBuster::Spawn( void ) -{ - SetModelName( AllocPooledString("models/magnusson_device.mdl") ); - BaseClass::Spawn(); - - // Setup for being shot by the player - m_takedamage = DAMAGE_EVENTS_ONLY; - - // Ignore touches until launched. - SetTouch ( NULL ); - - AddFlag( FL_AIMTARGET|FL_OBJECT ); - - m_hParticleEffect = CreateEntityByName( "info_particle_system" ); - if ( m_hParticleEffect ) - { - m_hParticleEffect->KeyValue( "start_active", "1" ); - m_hParticleEffect->KeyValue( "effect_name", "striderbuster_smoke" ); - DispatchSpawn( m_hParticleEffect ); - if ( gpGlobals->curtime > 0.2f ) - { - m_hParticleEffect->Activate(); - } - m_hParticleEffect->SetAbsOrigin( GetAbsOrigin() ); - m_hParticleEffect->SetParent( this ); - } - - SetHealth( striderbuster_health.GetInt() ); - - SetNextThink(gpGlobals->curtime + 0.01f); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponStriderBuster::Activate( void ) -{ - g_iszVehicle = AllocPooledString( "prop_vehicle_jeep" ); - BaseClass::Activate(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponStriderBuster::OnRestore( void ) -{ - BaseClass::OnRestore(); - - // If we have an entity we're attached to, attempt to reconstruct our bone follower setup - if ( m_hConstrainedEntity != NULL ) - { - CNPC_Strider *pStrider = dynamic_cast(m_hConstrainedEntity.Get()); - if ( pStrider != NULL ) - { - // Make sure we've done this step or we'll have no controller to attach to - pStrider->InitBoneFollowers(); - - // Attempt to make a connection to the same bone follower we attached to previously - CBoneFollower *pBoneFollower = pStrider->GetBoneFollowerByIndex( m_nAttachedBoneFollowerIndex ); - if ( CreateConstraintToObject( pBoneFollower ) == false ) - { - Msg( "Failed to reattach to bone follower %d\n", m_nAttachedBoneFollowerIndex ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponStriderBuster::DestroyConstraint( void ) -{ - // Destroy the constraint - if ( m_pConstraint != NULL ) - { - physenv->DestroyConstraint( m_pConstraint ); - m_pConstraint = NULL; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Create a constraint between this object and another -// Input : *pObject - Object to constrain ourselves to -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponStriderBuster::CreateConstraintToObject( CBaseEntity *pObject ) -{ - if ( m_pConstraint != NULL ) - { - // Should we destroy the constraint and make a new one at this point? - Assert( 0 ); - return false; - } - - if ( pObject == NULL ) - return false; - - IPhysicsObject *pPhysObject = pObject->VPhysicsGetObject(); - if ( pPhysObject == NULL ) - return false; - - IPhysicsObject *pMyPhysObject = VPhysicsGetObject(); - if ( pPhysObject == NULL ) - return false; - - // Create the fixed constraint - constraint_fixedparams_t fixedConstraint; - fixedConstraint.Defaults(); - fixedConstraint.InitWithCurrentObjectState( pPhysObject, pMyPhysObject ); - - IPhysicsConstraint *pConstraint = physenv->CreateFixedConstraint( pPhysObject, pMyPhysObject, NULL, fixedConstraint ); - if ( pConstraint == NULL ) - return false; - - // Hold on to us - m_pConstraint = pConstraint; - pConstraint->SetGameData( (void *)this ); - m_hConstrainedEntity = pObject->GetOwnerEntity();; - - // Disable collisions between the two ents - PhysDisableObjectCollisions( pPhysObject, pMyPhysObject ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Physics system has just told us our constraint has been broken -//----------------------------------------------------------------------------- -void CWeaponStriderBuster::InputConstraintBroken( inputdata_t &inputdata ) -{ - // Shatter with no real explosion effect - Shatter( NULL ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponStriderBuster::UpdateOnRemove( void ) -{ - DestroyConstraint(); - - if ( m_hGlowSprite != NULL ) - { - m_hGlowSprite->FadeAndDie( 0.5f ); - m_hGlowSprite = NULL; - } - - if ( m_hParticleEffect ) - { - UTIL_Remove( m_hParticleEffect ); - } - - BaseClass::UpdateOnRemove(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEntity - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponStriderBuster::ShouldStickToEntity( CBaseEntity *pEntity ) -{ - if ( pEntity == NULL ) - return false; - - // Must have a follow parent - CBaseEntity *pFollowParent = pEntity->GetOwnerEntity(); - if ( pFollowParent == NULL ) - return false; - - // Must be a strider - CNPC_Strider *pStrider = dynamic_cast(pFollowParent); - if ( pStrider == NULL ) - return false; - - if( m_bNoseDiving ) - return false; - - // Don't attach to legs - CBoneFollower *pFollower = static_cast(pEntity); - if ( pStrider->IsLegBoneFollower( pFollower ) ) - { - Vector vecDelta = pStrider->GetAdjustedOrigin() - GetAbsOrigin(); - if ( vecDelta.Length() > striderbuster_leg_stick_dist.GetFloat() ) - { - return false; - } - } - - // Ick, this is kind of ugly, but it's also ugly having to pass pointer into this to avoid multiple castings! - // Save this to patch up save/restore later - m_nAttachedBoneFollowerIndex = pStrider->GetBoneFollowerIndex( pFollower ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Stick to an entity (using hierarchy if we can) -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponStriderBuster::StickToEntity( CBaseEntity *pOther ) -{ - // Make sure the object is travelling fast enough to stick - if ( m_flCollisionSpeedSqr > 50 && !m_bNoseDiving ) - { - // See if this is a valid strider bit - if ( ShouldStickToEntity( pOther ) ) - { - // Attempt to constraint to it - if ( CreateConstraintToObject( pOther ) ) - { - // Only works for striders, at the moment - CBaseEntity *pFollowParent = pOther->GetOwnerEntity(); - if ( pFollowParent == NULL ) - return false; - - // Allows us to identify our constrained object later - SetOwnerEntity( pFollowParent ); - - // Make a sound - EmitSound( "Weapon_StriderBuster.StickToEntity" ); - - DispatchParticleEffect( "striderbuster_attach", GetAbsOrigin(), GetAbsAngles(), NULL ); - - if( striderbuster_use_particle_flare.GetBool() ) - { - // We don't have to save any pointers or handles to this because it's parented to the buster. - // So it will die when the buster dies. Yay. - CParticleSystem *pFlare = (CParticleSystem *) CreateEntityByName( "info_particle_system" ); - - if ( pFlare != NULL ) - { - pFlare->KeyValue( "start_active", "1" ); - pFlare->KeyValue( "effect_name", "striderbuster_attached_pulse" ); - pFlare->SetParent( this ); - pFlare->SetLocalOrigin( vec3_origin ); - DispatchSpawn( pFlare ); - pFlare->Activate(); - } - } - else - { - // Create a glow sprite - m_hGlowSprite = CSprite::SpriteCreate( "sprites/orangeflare1.vmt", GetLocalOrigin(), false ); - - Assert( m_hGlowSprite ); - if ( m_hGlowSprite != NULL ) - { - m_hGlowSprite->TurnOn(); - m_hGlowSprite->SetTransparency( kRenderWorldGlow, 255, 255, 255, 255, kRenderFxNoDissipation ); - m_hGlowSprite->SetAbsOrigin( GetAbsOrigin() ); - m_hGlowSprite->SetScale( 5.0f ); - m_hGlowSprite->m_nRenderFX = kRenderFxStrobeFaster; - m_hGlowSprite->SetGlowProxySize( 16.0f ); - m_hGlowSprite->SetParent( this ); - } - } - - // Stop touching things - SetTouch( NULL ); - - // Must be a strider - CNPC_Strider *pStrider = dynamic_cast(pFollowParent); - if ( pStrider == NULL ) - return false; - - // Notify the strider we're attaching to him - pStrider->StriderBusterAttached( this ); - - m_OnAttachToStrider.FireOutput( this, this ); - - // Start the ping sound. - SetContextThink( &CWeaponStriderBuster::BusterPingThink, gpGlobals->curtime + BUSTER_PING_SOUND_FREQ, s_pBusterPingThinkContext ); - - // Don't autodelete this one! - WeaponManager_RemoveManaged( this ); - - return true; - } - - return false; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Create the explosion effect for the final big boom -//----------------------------------------------------------------------------- -void CWeaponStriderBuster::CreateDestroyedEffect( void ) -{ - CBaseEntity *pTrail; - - StopParticleEffects( this ); - - for ( int i = 0; i < 3; i++ ) - { - pTrail = CreateEntityByName( "sparktrail" ); - pTrail->SetOwnerEntity( this ); - DispatchSpawn( pTrail ); - } - - DispatchParticleEffect( "striderbuster_explode_core", GetAbsOrigin(), GetAbsAngles() ); - - // Create liquid fountain gushtacular effect here! - CEffectData data; - - int nNumSteps = 6; - float flRadStep = (2*M_PI) / nNumSteps; - for ( int i = 0; i < nNumSteps; i++ ) - { - data.m_vOrigin = GetAbsOrigin() + RandomVector( -32.0f, 32.0f ); - data.m_vNormal.x = cos( flRadStep*i ); - data.m_vNormal.y = sin( flRadStep*i ); - data.m_vNormal.z = 0.0f; - data.m_flScale = ( random->RandomInt( 0, 5 ) == 0 ) ? 1 : 2; - - DispatchEffect( "StriderBlood", data ); - } - - // More effects - UTIL_ScreenShake( GetAbsOrigin(), 20.0f, 150.0, 1.0, 1250.0f, SHAKE_START ); - - data.m_vOrigin = GetAbsOrigin(); - DispatchEffect( "cball_explode", data ); -} - -//----------------------------------------------------------------------------- -// Purpose: Handle a collision using our special behavior -//----------------------------------------------------------------------------- -void CWeaponStriderBuster::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) -{ - // Find out what we hit. - // Don't do anything special if we're already attached to a strider. - CBaseEntity *pVictim = pEvent->pEntities[!index]; - if ( pVictim == NULL || m_pConstraint != NULL ) - { - BaseClass::VPhysicsCollision( index, pEvent ); - return; - } - - // Don't attach if we're being held by the player - if ( VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - { - BaseClass::VPhysicsCollision( index, pEvent ); - return; - } - - // Save off the speed of the object - m_flCollisionSpeedSqr = ( pEvent->preVelocity[ index ] ).LengthSqr(); - - // Break if we hit the world while going fast enough. - // Launched duds detonate if they hit the world at any speed. - if ( pVictim->IsWorld() && ( ( m_bDud && m_bLaunched ) || m_flCollisionSpeedSqr > Square( 500 ) ) ) - { - m_OnShatter.FireOutput( this, this ); - Shatter( pVictim ); - return; - } - - // We'll handle this later in our touch call - if ( ShouldStickToEntity( pVictim ) ) - return; - - // Determine if we should shatter - CBaseEntity *pOwnerEntity = pVictim->GetOwnerEntity(); - bool bVictimIsStrider = ( ( pOwnerEntity != NULL ) && FClassnameIs( pOwnerEntity, "npc_strider" ) ); - - // Break if we hit anything other than a strider while going fast enough. - // Launched duds detonate if they hit anything other than a strider any speed. - if ( ( bVictimIsStrider == false ) && ( ( m_bDud && m_bLaunched ) || m_flCollisionSpeedSqr > Square( 500 ) ) ) - { - m_OnShatter.FireOutput( this, this ); - Shatter( pVictim ); - return; - } - - // Just bounce - BaseClass::VPhysicsCollision( index, pEvent ); -} - -//----------------------------------------------------------------------------- -// Purpose: Called to see if we should attach to the victim -// Input : *pOther - the victim -//----------------------------------------------------------------------------- -void CWeaponStriderBuster::BusterTouch( CBaseEntity *pOther ) -{ - // Attempt to stick to the entity - StickToEntity( pOther ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline bool CWeaponStriderBuster::IsAttachedToStrider( void ) const -{ - CBaseEntity *pAttachedEnt = GetOwnerEntity(); - if ( pAttachedEnt && FClassnameIs( pAttachedEnt, "npc_strider" ) ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponStriderBuster::Detonate( void ) -{ - CBaseEntity *pVictim = GetOwnerEntity(); - if ( !m_bDud && pVictim ) - { - // Kill the strider (with magic effect) - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - CTakeDamageInfo info( pPlayer, this, RandomVector( -100.0f, 100.0f ), GetAbsOrigin(), pVictim->GetHealth(), DMG_GENERIC ); - pVictim->TakeDamage( info ); - - gamestats->Event_WeaponHit( ToBasePlayer( pPlayer ), true, GetClassname(), info ); - - // Tracker 62293: There's a bug where the inflictor/attacker are reversed when calling TakeDamage above so the player never gets - // credit for the strider buster kills. The code has a bunch of assumptions lower level, so it's safer to just fix it here by - // crediting a kill to the player directly. - gamestats->Event_PlayerKilledOther( pPlayer, pVictim, info ); - } - - m_OnDetonate.FireOutput( this, this ); - - // Explode - if ( !m_bDud ) - { - CreateDestroyedEffect(); - EmitSound( "Weapon_StriderBuster.Detonate" ); - } - else - { - DispatchParticleEffect( "striderbuster_explode_dummy_core", GetAbsOrigin(), GetAbsAngles() ); - EmitSound( "Weapon_StriderBuster.Dud_Detonate" ); - } - - // Go to bits! - Shatter( pVictim ); -} - -//----------------------------------------------------------------------------- -// Purpose: Intercept damage and decide whether or not we want to trigger -// Input : &info - -//----------------------------------------------------------------------------- -int CWeaponStriderBuster::OnTakeDamage( const CTakeDamageInfo &info ) -{ - // If we're attached, any damage from the player makes us trigger - CBaseEntity *pInflictor = info.GetInflictor(); - CBaseEntity *pAttacker = info.GetAttacker(); - bool bInflictorIsPlayer = ( pInflictor != NULL && pInflictor->IsPlayer() ); - bool bAttackerIsPlayer = ( pAttacker != NULL && pAttacker->IsPlayer() ); - - if ( GetParent() && GetParent()->ClassMatches( g_iszVehicle ) ) - { - return 0; - } - - // Only take damage from a player, for the moment - if ( striderbuster_allow_all_damage.GetBool() || ( IsAttachedToStrider() && ( bAttackerIsPlayer || bInflictorIsPlayer ) ) ) - { - Detonate(); - return 0; - } - - if ( pAttacker && ( pAttacker->Classify() == CLASS_COMBINE || pAttacker->Classify() == CLASS_COMBINE_HUNTER ) ) - { - if ( VPhysicsGetObject() && !VPhysicsGetObject()->IsMoveable() ) - { - return 0; - } - } - - // Hunters are able to destroy strider busters - if ( hunter_hate_held_striderbusters.GetBool() || hunter_hate_thrown_striderbusters.GetBool() || hunter_hate_attached_striderbusters.GetBool() ) - { - if ( ( GetHealth() > 0 ) && ( pInflictor != NULL ) && FClassnameIs( pInflictor, "hunter_flechette" ) ) - { - // - // Flechette impacts don't hurt the striderbuster unless it's attached to a strider, - // but the explosions always do. This is so that held or thrown striderbusters fly - // awry because of the flechette, but attached striderbusters break instantly to make - // the hunters more effective at defending the strider. - // - if ( IsAttachedToStrider() || !( info.GetDamageType() & DMG_NEVERGIB ) ) - { - if( striderbuster_die_detach.GetBool() && IsAttachedToStrider() ) - { - // Make the buster fall off and break. - m_takedamage = DAMAGE_NO; - - CNPC_Strider *pStrider = dynamic_cast(GetOwnerEntity()); - Assert( pStrider != NULL ); - pStrider->StriderBusterDetached( this ); - DestroyConstraint(); - - // Amplify some lateral force. - Vector vecForce = info.GetDamageForce(); - vecForce.z = 0.0f; - VPhysicsGetObject()->ApplyForceCenter( vecForce * 5.0f ); - - SetContextThink( NULL, gpGlobals->curtime, s_pBusterPingThinkContext ); - - SetThink( &CWeaponStriderBuster::BusterDetachThink ); - SetNextThink( gpGlobals->curtime ); - m_iBusterFlags |= STRIDERBUSTER_FLAG_KNOCKED_OFF_STRIDER; - - return 0; - } - else - { - // Destroy the buster in place - // Make sure they know it blew up prematurely. - EmitSound( "Weapon_StriderBuster.Dud_Detonate" ); - DispatchParticleEffect( "striderbuster_break_flechette", GetAbsOrigin(), GetAbsAngles() ); - SetHealth( 0 ); - - Shatter( info.GetAttacker() ); - return 0; - } - } - - if ( info.GetDamage() < 5 ) - { - bool bFirst = ( m_CarryAngles.x == 45 && m_CarryAngles.y == 0 && m_CarryAngles.z == 0); - float sinTime = sin( gpGlobals->curtime ); - bool bSubtractX = ( bFirst ) ? ( sinTime < 0 ) : ( m_CarryAngles.x < 45 ); - - m_CarryAngles.x += ( 10.0 + 10.0 * fabsf( sinTime ) + random->RandomFloat( -2.5, 2.5 ) + random->RandomFloat( -2.5, 2.5 ) ) * ( ( bSubtractX ) ? -1.0 : 1.0 ); - m_CarryAngles.y = 15 * ( sin( gpGlobals->curtime ) + cos( gpGlobals->curtime * 0.5 ) ) * .5 + random->RandomFloat( -15, 15 ); - m_CarryAngles.z = 7.5 * ( sin( gpGlobals->curtime ) + sin( gpGlobals->curtime * 2.0 ) ) * .5 + random->RandomFloat( -7.5, 7.5 ); - } - - return 1; - } - } - - // Allow crushing damage - if ( info.GetDamageType() & DMG_CRUSH ) - return BaseClass::OnTakeDamage( info ); - - return 0; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CWeaponStriderBuster::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) -{ - m_PickupTime = gpGlobals->curtime; - m_CarryAngles.Init( 45, 0, 0 ); - if ( ( reason == PICKED_UP_BY_CANNON ) && ( !HasSpawnFlags( SF_DONT_WEAPON_MANAGE ) ) ) - { - WeaponManager_RemoveManaged( this ); - } - else if ( reason == PUNTED_BY_CANNON ) - { - Launch( pPhysGunUser ); - } - - BaseClass::OnPhysGunPickup( pPhysGunUser, reason ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CWeaponStriderBuster::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ) -{ - if ( Reason == LAUNCHED_BY_CANNON ) - { - Launch( pPhysGunUser ); - } - else if ( ( Reason == DROPPED_BY_CANNON ) && ( !HasSpawnFlags( SF_DONT_WEAPON_MANAGE ) ) ) - { - // This striderbuster is now fair game for autodeletion. - WeaponManager_AddManaged( this ); - } - - BaseClass::OnPhysGunDrop( pPhysGunUser, Reason ); -} - - -//----------------------------------------------------------------------------- -// Fling the buster with the physcannon either via punt or launch. -//----------------------------------------------------------------------------- -void CWeaponStriderBuster::Launch( CBasePlayer *pPhysGunUser ) -{ - if ( !HasSpawnFlags( SF_DONT_WEAPON_MANAGE ) ) - { - WeaponManager_RemoveManaged( this ); - } - - m_bLaunched = true; - - // Notify all nearby hunters that we were launched. - Hunter_StriderBusterLaunched( this ); - - // Start up the eye glow - m_hMainGlow = CSprite::SpriteCreate( "sprites/blueglow1.vmt", GetLocalOrigin(), false ); - - if ( m_hMainGlow != NULL ) - { - m_hMainGlow->FollowEntity( this ); - m_hMainGlow->SetTransparency( kRenderGlow, 255, 255, 255, 140, kRenderFxNoDissipation ); - m_hMainGlow->SetScale( 2.0f ); - m_hMainGlow->SetGlowProxySize( 8.0f ); - } - - if ( !m_bNoseDiving ) - { - DispatchParticleEffect( "striderbuster_trail", PATTACH_ABSORIGIN_FOLLOW, this ); - } - else - { - DispatchParticleEffect( "striderbuster_shotdown_trail", PATTACH_ABSORIGIN_FOLLOW, this ); - } - - // We get our touch function from the physics system - SetTouch ( &CWeaponStriderBuster::BusterTouch ); - - SetThink( &CWeaponStriderBuster::BusterFlyThink ); - SetNextThink( gpGlobals->curtime ); - - gamestats->Event_WeaponFired( pPhysGunUser, true, GetClassname() ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &forward - -// flMass - -// Output : Vector -//----------------------------------------------------------------------------- -Vector CWeaponStriderBuster::PhysGunLaunchVelocity( const Vector &forward, float flMass ) -{ - return ( striderbuster_shot_velocity.GetFloat() * forward ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponStriderBuster::Shatter( CBaseEntity *pAttacker ) -{ - if( m_bNoseDiving ) - m_OnShotDown.FireOutput( this, this ); - - m_takedamage = DAMAGE_YES; - - if( !IsAttachedToStrider() ) - { - // Don't display this particular effect if we're attached to a strider. This effect just gets lost - // in the big strider explosion anyway, so let's recover some perf. - DispatchParticleEffect( "striderbuster_break", GetAbsOrigin(), GetAbsAngles() ); - } - - // Buster is useless now. Stop thinking, touching. - SetThink( NULL ); - SetTouch( NULL ); - SetContextThink( NULL, gpGlobals->curtime, s_pBusterPingThinkContext ); - - // Deal deadly damage to ourselves (DMG_CRUSH is allowed, others are blocked) - CTakeDamageInfo info( pAttacker, pAttacker, RandomVector( -100, 100 ), GetAbsOrigin(), 100.0f, DMG_CRUSH ); - TakeDamage( info ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Give the buster a slight attraction to striders. -// Ported back from the magnade. -//----------------------------------------------------------------------------- -void CWeaponStriderBuster::BusterFlyThink() -{ - if (IsAttachedToStrider()) - return; // early out. Think no more. - - // If we're nosediving, forget about magnetism. - if ( m_bNoseDiving ) - { - if ( VPhysicsGetObject() ) - VPhysicsGetObject()->ApplyForceCenter( Vector( 0, 0, striderbuster_dive_force.GetFloat() ) ); - SetNextThink(gpGlobals->curtime + 0.01f); - return; - } - - // seek? - const float magradius = 38.0 * sk_striderbuster_magnet_multiplier.GetFloat(); // radius of strider hull times multiplier - if (magradius > 0 && - GetMoveType() == MOVETYPE_VPHYSICS && - VPhysicsGetObject() - ) - { - // find the nearest enemy. - CBaseEntity *pList[16]; - Vector origin = GetAbsOrigin(); - - // do a find in box ( a little faster than sphere ) - int count; - { - Vector mins,maxs; - mins = origin; - mins -= magradius; - - maxs = origin; - maxs += magradius; - - count = UTIL_EntitiesInBox(pList, 16, mins, maxs, FL_NPC); - } - - float magradiusSq = Square( magradius ); - float nearestDistSq = magradiusSq + 1; - int bestFit = -1; - Vector toTarget(0.0f, 0.0f, 0.0f); // will be garbage unless something good is found - CNPC_Strider *pBestStrider = NULL; - - for ( int ii = 0 ; ii < count ; ++ii ) - { - CNPC_Strider *pStrider = dynamic_cast(pList[ii]); - if ( pStrider && !pStrider->CarriedByDropship() ) // ShouldStickToEntity() doesn't work because the strider NPC isn't what we glue to - { - // get distance squared - VectorSubtract( pStrider->GetAdjustedOrigin(), GetAbsOrigin(), toTarget ); - - //NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + toTarget, 128, 0, 128, false, 0.1 ); - - float dSq = toTarget.LengthSqr(); - if (dSq < nearestDistSq) - { - bestFit = ii; nearestDistSq = dSq; - pBestStrider = pStrider; - } - } - } - - if (bestFit >= 0) // we found something and should attract towards it. (hysterisis later?) - { - if ( striderbuster_debugseek.GetBool() ) - { - NDebugOverlay::Circle( GetAbsOrigin() + toTarget, magradius, 255, 255, 255, 255, true, .1 ); - NDebugOverlay::Cross3D( GetAbsOrigin() + toTarget, magradius, 255, 255, 255, true, .1 ); - } - - // force magnitude. - float magnitude = GetMass() * striderbuster_magnetic_force_strider.GetFloat(); - int falloff = striderbuster_falloff_power.GetInt(); - switch (falloff) - { - case 1: - VPhysicsGetObject()->ApplyForceCenter( toTarget * (magnitude / nearestDistSq) ); // dividing through by distance squared normalizes toTarget and gives a linear falloff - break; - case 2: - VPhysicsGetObject()->ApplyForceCenter( toTarget * (magnitude / (nearestDistSq * sqrtf(nearestDistSq))) ); // dividing through by distance cubed normalizes toTarget and gives a quadratic falloff - break; - case 3: - VPhysicsGetObject()->ApplyForceCenter( toTarget * (magnitude / (nearestDistSq * nearestDistSq)) ); // dividing through by distance fourth normalizes toTarget and gives a cubic falloff - break; - case 4: - { - Vector toTarget; - pBestStrider->GetAttachment( "buster_target", toTarget ); - - if ( striderbuster_debugseek.GetBool() ) - { - NDebugOverlay::Cross3D( toTarget, magradius, 255, 0, 255, true, .1 ); - NDebugOverlay::Cross3D( toTarget, magradius, 255, 0, 255, true, .1 ); - } - - toTarget -= GetAbsOrigin(); - toTarget.NormalizeInPlace(); - VPhysicsGetObject()->ApplyForceCenter( toTarget * magnitude ); - - } - break; - default: // arbitrary powers - VPhysicsGetObject()->ApplyForceCenter( toTarget * (magnitude * powf(nearestDistSq,(falloff+1.0f)/2)) ); // square root for distance instead of squared, add one to normalize toTarget - break; - } - } - - SetNextThink(gpGlobals->curtime + 0.01f); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CWeaponStriderBuster::BusterDetachThink() -{ - SetNextThink( gpGlobals->curtime + 0.1f ); - - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector( 0, 0, 1200), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - - if( fabs(tr.startpos.z - tr.endpos.z) < 240.0f ) - { - SetThink(NULL); - EmitSound( "Weapon_StriderBuster.Dud_Detonate" ); - DispatchParticleEffect( "striderbuster_break_flechette", GetAbsOrigin(), GetAbsAngles() ); - SetHealth( 0 ); - CTakeDamageInfo info; - info.SetDamage( 1.0f ); - info.SetAttacker( this ); - info.SetInflictor( this ); - Shatter(this); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CWeaponStriderBuster::BusterPingThink() -{ - EmitSound( "Weapon_StriderBuster.Ping" ); - - SetContextThink( &CWeaponStriderBuster::BusterPingThink, gpGlobals->curtime + BUSTER_PING_SOUND_FREQ, s_pBusterPingThinkContext ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CWeaponStriderBuster::OnAddToCargoHold() -{ - if ( !HasSpawnFlags( SF_DONT_WEAPON_MANAGE ) ) - { - WeaponManager_RemoveManaged( this ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CWeaponStriderBuster::OnFlechetteAttach( Vector &vecFlechetteVelocity ) -{ - if ( m_bLaunched ) - { - Vector vecForce = vecFlechetteVelocity; - VectorNormalize( vecForce ); - - vecForce *= 1000; - vecForce.z = -5000; - - VPhysicsGetObject()->ApplyForceCenter( vecForce ); - } - - if ( !GetParent() || !GetParent()->ClassMatches( g_iszVehicle ) ) - { - if ( !m_bNoseDiving ) - { - //m_hGlowTrail->StopParticleSystem(); - StopParticleEffects( this ); - - if( m_iBusterFlags & STRIDERBUSTER_FLAG_KNOCKED_OFF_STRIDER ) - { - DispatchParticleEffect( "striderbuster_shotdown_trail", PATTACH_ABSORIGIN_FOLLOW, this ); - } - else - { - DispatchParticleEffect( "striderbuster_flechette_attached", PATTACH_ABSORIGIN_FOLLOW, this ); - } - } - - m_bNoseDiving = true; - } - m_nAttachedFlechettes++; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool StriderBuster_IsAttachedStriderBuster( CBaseEntity *pEntity, CBaseEntity *pAttachedTo ) -{ - Assert(dynamic_cast(pEntity)); - if ( !pAttachedTo ) - return static_cast(pEntity)->m_hConstrainedEntity != NULL; - else - return static_cast(pEntity)->m_hConstrainedEntity == pAttachedTo; -} - - -//----------------------------------------------------------------------------- -// Called when the striderbuster is placed in the jalopy's cargo container. -//----------------------------------------------------------------------------- -void StriderBuster_OnAddToCargoHold( CBaseEntity *pEntity ) -{ - CWeaponStriderBuster *pBuster = dynamic_cast ( pEntity ); - if ( pBuster ) - { - pBuster->OnAddToCargoHold(); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool StriderBuster_OnFlechetteAttach( CBaseEntity *pEntity, Vector &vecFlechetteVelocity ) -{ - CWeaponStriderBuster *pBuster = dynamic_cast ( pEntity ); - if ( pBuster ) - { - pBuster->OnFlechetteAttach( vecFlechetteVelocity ); - return true; - } - return false; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int StriderBuster_NumFlechettesAttached( CBaseEntity *pEntity ) -{ - CWeaponStriderBuster *pBuster = dynamic_cast ( pEntity ); - if ( pBuster ) - { - return pBuster->NumFlechettesAttached(); - } - return 0; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -float StriderBuster_GetPickupTime( CBaseEntity *pEntity ) -{ - CWeaponStriderBuster *pBuster = dynamic_cast ( pEntity ); - if ( pBuster ) - { - return pBuster->GetPickupTime(); - } - return 0; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool StriderBuster_WasKnockedOffStrider( CBaseEntity *pEntity ) -{ - CWeaponStriderBuster *pBuster = dynamic_cast ( pEntity ); - if ( pBuster ) - { - return ((pBuster->GetStriderBusterFlags() & STRIDERBUSTER_FLAG_KNOCKED_OFF_STRIDER) != 0); - } - - return false; -} diff --git a/game/server/episodic/weapon_striderbuster.h b/game/server/episodic/weapon_striderbuster.h deleted file mode 100644 index 3bddf7d0f..000000000 --- a/game/server/episodic/weapon_striderbuster.h +++ /dev/null @@ -1,20 +0,0 @@ -//========= Copyright 1996-2007, Valve Corporation, All rights reserved. ==== -// -// Helper functions for the striderbuster weapon. -// -//============================================================================= - -#ifndef WEAPON_STRIDERBUSTER_H -#define WEAPON_STRIDERBUSTER_H -#ifdef _WIN32 -#pragma once -#endif - -bool StriderBuster_IsAttachedStriderBuster( CBaseEntity *pEntity, CBaseEntity *pAttachedTo = NULL ); -void StriderBuster_OnAddToCargoHold( CBaseEntity *pEntity ); -bool StriderBuster_OnFlechetteAttach( CBaseEntity *pEntity, Vector &vecForceDir ); -int StriderBuster_NumFlechettesAttached( CBaseEntity *pEntity ); -float StriderBuster_GetPickupTime( CBaseEntity *pEntity ); -bool StriderBuster_WasKnockedOffStrider( CBaseEntity *pEntity ); - -#endif // WEAPON_STRIDERBUSTER_H diff --git a/game/server/event_tempentity_tester.cpp b/game/server/event_tempentity_tester.cpp deleted file mode 100644 index 5044937ec..000000000 --- a/game/server/event_tempentity_tester.cpp +++ /dev/null @@ -1,125 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" -#include "event_tempentity_tester.h" -#include "tier1/strtools.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define TEMPENT_TEST_GAP 1.0f - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &vecOrigin - -// &vecAngles - -// *single_te - -// Output : CBaseEntity -//----------------------------------------------------------------------------- -CBaseEntity *CTempEntTester::Create( const Vector &vecOrigin, const QAngle &vecAngles, const char *lifetime, const char *single_te ) -{ - float life; - char classname[ 128 ]; - if ( lifetime && lifetime[0] ) - { - life = atoi( lifetime ); - life = MAX( 1.0, life ); - life = MIN( 1000.0, life ); - - life += gpGlobals->curtime; - } - else - { - Msg( "Usage: te \n" ); - return NULL; - } - - if ( single_te && single_te[0] ) - { - Q_strncpy( classname, single_te ,sizeof(classname)); - Q_strlower( classname ); - } - else - { - Msg( "Usage: te \n" ); - return NULL; - } - - CTempEntTester *p = ( CTempEntTester * )CBaseEntity::CreateNoSpawn( "te_tester", vecOrigin, vecAngles ); - if ( !p ) - { - return NULL; - } - - Q_strncpy( p->m_szClass, classname ,sizeof(p->m_szClass)); - p->m_fLifeTime = life; - - p->Spawn(); - - return p; -} - -LINK_ENTITY_TO_CLASS( te_tester, CTempEntTester ); - -//----------------------------------------------------------------------------- -// Purpose: Called when object is being created -//----------------------------------------------------------------------------- -void CTempEntTester::Spawn( void ) -{ - // Not a physical thing... - AddEffects( EF_NODRAW ); - - m_pCurrent = CBaseTempEntity::GetList(); - while ( m_pCurrent ) - { - char name[ 128 ]; - Q_strncpy( name, m_pCurrent->GetName() ,sizeof(name)); - Q_strlower( name ); - if ( strstr( name, m_szClass ) ) - { - break; - } - - m_pCurrent = m_pCurrent->GetNext(); - } - - if ( !m_pCurrent ) - { - DevMsg("Couldn't find temp entity '%s'\n", m_szClass ); - UTIL_Remove( this ); - return; - } - - // Think right away - SetNextThink( gpGlobals->curtime ); -} - -//----------------------------------------------------------------------------- -// Purpose: Called when object should fire itself and move on -//----------------------------------------------------------------------------- -void CTempEntTester::Think( void ) -{ - // Should never happen - if ( !m_pCurrent ) - { - UTIL_Remove( this ); - return; - } - - m_pCurrent->Test( GetLocalOrigin(), GetLocalAngles() ); - SetNextThink( gpGlobals->curtime + TEMPENT_TEST_GAP ); - - // Time to destroy? - if ( gpGlobals->curtime >= m_fLifeTime ) - { - UTIL_Remove( this ); - return; - } -} diff --git a/game/server/event_tempentity_tester.h b/game/server/event_tempentity_tester.h deleted file mode 100644 index 67af11cc9..000000000 --- a/game/server/event_tempentity_tester.h +++ /dev/null @@ -1,40 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// -#if !defined( EVENT_TEMPENTITY_TESTER_H ) -#define EVENT_TEMPENTITY_TESTER_H -#ifdef _WIN32 -#pragma once -#endif - -class CBaseTempEntity; - - -//----------------------------------------------------------------------------- -// Purpose: A server object that is used to test all registered temp entities -//----------------------------------------------------------------------------- -class CTempEntTester : public CPointEntity -{ -public: - DECLARE_CLASS( CTempEntTester, CPointEntity ); - - void Spawn( void ); - void Think( void ); - - static CBaseEntity *Create( const Vector &vecOrigin, const QAngle &vecAngles, const char *lifetime, const char *single_te ); -private: - // Current temp entity to test - CBaseTempEntity *m_pCurrent; - - // Lifetime - float m_fLifeTime; - - char m_szClass[ 64 ]; -}; - -#endif // EVENT_TEMPENTITY_TESTER_H diff --git a/game/server/eventqueue.h b/game/server/eventqueue.h deleted file mode 100644 index 9bf1ebd8d..000000000 --- a/game/server/eventqueue.h +++ /dev/null @@ -1,83 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: A global class that holds a prioritized queue of entity I/O events. -// Events can be posted with a nonzero delay, which determines how long -// they are held before being dispatched to their recipients. -// -// The queue is serviced once per server frame. -// -//=============================================================================// - -#ifndef EVENTQUEUE_H -#define EVENTQUEUE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "mempool.h" - -struct EventQueuePrioritizedEvent_t -{ - float m_flFireTime; - string_t m_iTarget; - string_t m_iTargetInput; - EHANDLE m_pActivator; - EHANDLE m_pCaller; - int m_iOutputID; - EHANDLE m_pEntTarget; // a pointer to the entity to target; overrides m_iTarget - - variant_t m_VariantValue; // variable-type parameter - - EventQueuePrioritizedEvent_t *m_pNext; - EventQueuePrioritizedEvent_t *m_pPrev; - - DECLARE_SIMPLE_DATADESC(); - - DECLARE_FIXEDSIZE_ALLOCATOR( PrioritizedEvent_t ); -}; - -class CEventQueue -{ -public: - // pushes an event into the queue, targeting a string name (m_iName), or directly by a pointer - void AddEvent( const char *target, const char *action, variant_t Value, float fireDelay, CBaseEntity *pActivator, CBaseEntity *pCaller, int outputID = 0 ); - void AddEvent( CBaseEntity *target, const char *action, float fireDelay, CBaseEntity *pActivator, CBaseEntity *pCaller, int outputID = 0 ); - void AddEvent( CBaseEntity *target, const char *action, variant_t Value, float fireDelay, CBaseEntity *pActivator, CBaseEntity *pCaller, int outputID = 0 ); - - void CancelEvents( CBaseEntity *pCaller ); - void CancelEventOn( CBaseEntity *pTarget, const char *sInputName ); - bool HasEventPending( CBaseEntity *pTarget, const char *sInputName ); - - // services the queue, firing off any events who's time hath come - void ServiceEvents( void ); - - // debugging - void ValidateQueue( void ); - - // serialization - int Save( ISave &save ); - int Restore( IRestore &restore ); - - CEventQueue(); - ~CEventQueue(); - - void Init( void ); - void Clear( void ); // resets the list - - void Dump( void ); - -private: - - void AddEvent( EventQueuePrioritizedEvent_t *event ); - void RemoveEvent( EventQueuePrioritizedEvent_t *pe ); - - DECLARE_SIMPLE_DATADESC(); - EventQueuePrioritizedEvent_t m_Events; - int m_iListCount; -}; - -extern CEventQueue g_EventQueue; - - -#endif // EVENTQUEUE_H - diff --git a/game/server/explode.cpp b/game/server/explode.cpp deleted file mode 100644 index 92bf9edb1..000000000 --- a/game/server/explode.cpp +++ /dev/null @@ -1,491 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements an explosion entity and a support spark shower entity. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "decals.h" -#include "explode.h" -#include "ai_basenpc.h" -#include "IEffects.h" -#include "vstdlib/random.h" -#include "tier1/strtools.h" -#include "shareddefs.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Spark shower, created by the explosion entity. -//----------------------------------------------------------------------------- -class CShower : public CPointEntity -{ -public: - DECLARE_CLASS( CShower, CPointEntity ); - - void Spawn( void ); - void Think( void ); - void Touch( CBaseEntity *pOther ); - int ObjectCaps( void ) { return FCAP_DONT_SAVE; } -}; - -LINK_ENTITY_TO_CLASS( spark_shower, CShower ); - - -void CShower::Spawn( void ) -{ - Vector vecForward; - AngleVectors( GetLocalAngles(), &vecForward ); - - Vector vecNewVelocity; - vecNewVelocity = random->RandomFloat( 200, 300 ) * vecForward; - vecNewVelocity.x += random->RandomFloat(-100.f,100.f); - vecNewVelocity.y += random->RandomFloat(-100.f,100.f); - if ( vecNewVelocity.z >= 0 ) - vecNewVelocity.z += 200; - else - vecNewVelocity.z -= 200; - SetAbsVelocity( vecNewVelocity ); - - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); - SetGravity( UTIL_ScaleForGravity( 400 ) ); // fall a bit more slowly than normal - SetNextThink( gpGlobals->curtime + 0.1f ); - SetSolid( SOLID_NONE ); - UTIL_SetSize(this, vec3_origin, vec3_origin ); - AddEffects( EF_NODRAW ); - m_flSpeed = random->RandomFloat( 0.5, 1.5 ); - - SetLocalAngles( vec3_angle ); -} - - -void CShower::Think( void ) -{ - g_pEffects->Sparks( GetAbsOrigin() ); - - m_flSpeed -= 0.1; - if ( m_flSpeed > 0 ) - SetNextThink( gpGlobals->curtime + 0.1f ); - else - UTIL_Remove( this ); - SetGroundEntity( NULL ); -} - - -void CShower::Touch( CBaseEntity *pOther ) -{ - Vector vecNewVelocity = GetAbsVelocity(); - - if ( GetFlags() & FL_ONGROUND ) - vecNewVelocity *= 0.1; - else - vecNewVelocity *= 0.6; - - if ( (vecNewVelocity.x*vecNewVelocity.x+vecNewVelocity.y*vecNewVelocity.y) < 10.0 ) - m_flSpeed = 0; - - SetAbsVelocity( vecNewVelocity ); -} - - -class CEnvExplosion : public CPointEntity -{ -public: - DECLARE_CLASS( CEnvExplosion, CPointEntity ); - - CEnvExplosion( void ) - { - // Default to invalid. - m_sFireballSprite = -1; - }; - - void Precache( void ); - void Spawn( ); - void Smoke ( void ); - void SetCustomDamageType( int iType ) { m_iCustomDamageType = iType; } - bool KeyValue( const char *szKeyName, const char *szValue ); - - int DrawDebugTextOverlays(void); - - // Input handlers - void InputExplode( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - - int m_iMagnitude;// how large is the fireball? how much damage? - int m_iRadiusOverride;// For use when m_iMagnitude results in larger radius than designer desires. - int m_spriteScale; // what's the exact fireball sprite scale? - float m_flDamageForce; // How much damage force should we use? - string_t m_iszFireballSprite; - short m_sFireballSprite; - EHANDLE m_hInflictor; - int m_iCustomDamageType; - - // passed along to the RadiusDamage call - int m_iClassIgnore; - EHANDLE m_hEntityIgnore; - -}; - -LINK_ENTITY_TO_CLASS( env_explosion, CEnvExplosion ); - -BEGIN_DATADESC( CEnvExplosion ) - - DEFINE_KEYFIELD( m_iMagnitude, FIELD_INTEGER, "iMagnitude" ), - DEFINE_KEYFIELD( m_iRadiusOverride, FIELD_INTEGER, "iRadiusOverride" ), - DEFINE_FIELD( m_spriteScale, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_flDamageForce, FIELD_FLOAT, "DamageForce" ), - DEFINE_FIELD( m_iszFireballSprite, FIELD_STRING ), - DEFINE_FIELD( m_sFireballSprite, FIELD_SHORT ), - DEFINE_FIELD( m_hInflictor, FIELD_EHANDLE ), - DEFINE_FIELD( m_iCustomDamageType, FIELD_INTEGER ), - - DEFINE_FIELD( m_iClassIgnore, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_hEntityIgnore, FIELD_EHANDLE, "ignoredEntity" ), - - // Function Pointers - DEFINE_THINKFUNC( Smoke ), - - // Inputs - DEFINE_INPUTFUNC(FIELD_VOID, "Explode", InputExplode), - -END_DATADESC() - - -bool CEnvExplosion::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "fireballsprite")) - { - m_iszFireballSprite = AllocPooledString( szValue ); - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } - - return true; -} - -void CEnvExplosion::Precache( void ) -{ - if ( m_iszFireballSprite != NULL_STRING ) - { - m_sFireballSprite = PrecacheModel( STRING( m_iszFireballSprite ) ); - } -} - -void CEnvExplosion::Spawn( void ) -{ - Precache(); - - SetSolid( SOLID_NONE ); - AddEffects( EF_NODRAW ); - - SetMoveType( MOVETYPE_NONE ); - /* - if ( m_iMagnitude > 250 ) - { - m_iMagnitude = 250; - } - */ - - float flSpriteScale; - flSpriteScale = ( m_iMagnitude - 50) * 0.6; - - // Control the clamping of the fireball sprite - if( m_spawnflags & SF_ENVEXPLOSION_NOCLAMPMIN ) - { - // Don't inhibit clamping altogether. Just relax it a bit. - if ( flSpriteScale < 1 ) - { - flSpriteScale = 1; - } - } - else - { - if ( flSpriteScale < 10 ) - { - flSpriteScale = 10; - } - } - - if( m_spawnflags & SF_ENVEXPLOSION_NOCLAMPMAX ) - { - // We may need to adjust this to suit designers' needs. - if ( flSpriteScale > 200 ) - { - flSpriteScale = 200; - } - } - else - { - if ( flSpriteScale > 50 ) - { - flSpriteScale = 50; - } - } - - m_spriteScale = (int)flSpriteScale; - m_iCustomDamageType = -1; -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for making the explosion explode. -//----------------------------------------------------------------------------- -void CEnvExplosion::InputExplode( inputdata_t &inputdata ) -{ - trace_t tr; - - SetModelName( NULL_STRING );//invisible - SetSolid( SOLID_NONE );// intangible - - Vector vecSpot = GetAbsOrigin() + Vector( 0 , 0 , 8 ); - UTIL_TraceLine( vecSpot, vecSpot + Vector( 0, 0, -40 ), (MASK_SOLID_BRUSHONLY | MASK_WATER), this, COLLISION_GROUP_NONE, &tr ); - - // Pull out of the wall a bit. We used to move the explosion origin itself, but that seems unnecessary, not to mention a - // little weird when you consider that it might be in hierarchy. Instead we just calculate a new virtual position at - // which to place the explosion. We don't use that new position to calculate radius damage because according to Steve's - // comment, that adversely affects the force vector imparted on explosion victims when they ragdoll. - Vector vecExplodeOrigin = GetAbsOrigin(); - if ( tr.fraction != 1.0 ) - { - vecExplodeOrigin = tr.endpos + (tr.plane.normal * 24 ); - } - - // draw decal - if (! ( m_spawnflags & SF_ENVEXPLOSION_NODECAL)) - { - UTIL_DecalTrace( &tr, "Scorch" ); - } - - // It's stupid that this entity's spawnflags and the flags for the - // explosion temp ent don't match up. But because they don't, we - // have to reinterpret some of the spawnflags to determine which - // flags to pass to the temp ent. - int nFlags = TE_EXPLFLAG_NONE; - - if( m_spawnflags & SF_ENVEXPLOSION_NOFIREBALL ) - { - nFlags |= TE_EXPLFLAG_NOFIREBALL; - } - - if( m_spawnflags & SF_ENVEXPLOSION_NOSOUND ) - { - nFlags |= TE_EXPLFLAG_NOSOUND; - } - - if ( m_spawnflags & SF_ENVEXPLOSION_RND_ORIENT ) - { - nFlags |= TE_EXPLFLAG_ROTATE; - } - - if ( m_nRenderMode == kRenderTransAlpha ) - { - nFlags |= TE_EXPLFLAG_DRAWALPHA; - } - else if ( m_nRenderMode != kRenderTransAdd ) - { - nFlags |= TE_EXPLFLAG_NOADDITIVE; - } - - if( m_spawnflags & SF_ENVEXPLOSION_NOPARTICLES ) - { - nFlags |= TE_EXPLFLAG_NOPARTICLES; - } - - if( m_spawnflags & SF_ENVEXPLOSION_NODLIGHTS ) - { - nFlags |= TE_EXPLFLAG_NODLIGHTS; - } - - if ( m_spawnflags & SF_ENVEXPLOSION_NOFIREBALLSMOKE ) - { - nFlags |= TE_EXPLFLAG_NOFIREBALLSMOKE; - } - - //Get the damage override if specified - int iRadius = ( m_iRadiusOverride > 0 ) ? m_iRadiusOverride : static_cast(m_iMagnitude * 2.5f); - - CPASFilter filter( vecExplodeOrigin ); - te->Explosion( filter, 0.0, - &vecExplodeOrigin, - ( m_sFireballSprite < 1 ) ? g_sModelIndexFireball : m_sFireballSprite, - !( m_spawnflags & SF_ENVEXPLOSION_NOFIREBALL ) ? ( m_spriteScale / 10.0 ) : 0.0, - 15, - nFlags, - iRadius, - m_iMagnitude ); - - // do damage - if ( !( m_spawnflags & SF_ENVEXPLOSION_NODAMAGE ) ) - { - CBaseEntity *pAttacker = GetOwnerEntity() ? GetOwnerEntity() : this; - - // Only calculate damage type if we didn't get a custom one passed in - int iDamageType = m_iCustomDamageType; - if ( iDamageType == -1 ) - { - iDamageType = HasSpawnFlags( SF_ENVEXPLOSION_GENERIC_DAMAGE ) ? DMG_GENERIC : DMG_BLAST; - } - - CTakeDamageInfo info( m_hInflictor ? m_hInflictor : this, pAttacker, m_iMagnitude, iDamageType ); - - if( HasSpawnFlags( SF_ENVEXPLOSION_SURFACEONLY ) ) - { - info.AddDamageType( DMG_BLAST_SURFACE ); - } - - if ( m_flDamageForce ) - { - // Not the right direction, but it'll be fixed up by RadiusDamage. - info.SetDamagePosition( GetAbsOrigin() ); - info.SetDamageForce( Vector( m_flDamageForce, 0, 0 ) ); - } - - RadiusDamage( info, GetAbsOrigin(), iRadius, m_iClassIgnore, m_hEntityIgnore.Get() ); - } - - SetThink( &CEnvExplosion::Smoke ); - SetNextThink( gpGlobals->curtime + 0.3 ); - - // Only do these effects if we're not submerged - if ( UTIL_PointContents( GetAbsOrigin() ) & CONTENTS_WATER ) - { - // draw sparks - if ( !( m_spawnflags & SF_ENVEXPLOSION_NOSPARKS ) ) - { - int sparkCount = random->RandomInt(0,3); - - for ( int i = 0; i < sparkCount; i++ ) - { - QAngle angles; - VectorAngles( tr.plane.normal, angles ); - Create( "spark_shower", vecExplodeOrigin, angles, NULL ); - } - } - } -} - - -void CEnvExplosion::Smoke( void ) -{ - if ( !(m_spawnflags & SF_ENVEXPLOSION_REPEATABLE) ) - { - UTIL_Remove( this ); - } -} - - -// HACKHACK -- create one of these and fake a keyvalue to get the right explosion setup -void ExplosionCreate( const Vector ¢er, const QAngle &angles, - CBaseEntity *pOwner, int magnitude, int radius, int nSpawnFlags, float flExplosionForce, CBaseEntity *pInflictor, int iCustomDamageType, - const EHANDLE *ignoredEntity , Class_T ignoredClass ) -{ - char buf[128]; - - CEnvExplosion *pExplosion = (CEnvExplosion*)CBaseEntity::Create( "env_explosion", center, angles, pOwner ); - Q_snprintf( buf,sizeof(buf), "%3d", magnitude ); - const char *szKeyName = "iMagnitude"; - char *szValue = buf; - pExplosion->KeyValue( szKeyName, szValue ); - - pExplosion->AddSpawnFlags( nSpawnFlags ); - - if ( radius ) - { - Q_snprintf( buf,sizeof(buf), "%d", radius ); - pExplosion->KeyValue( "iRadiusOverride", buf ); - } - - if ( flExplosionForce != 0.0f ) - { - Q_snprintf( buf,sizeof(buf), "%.3f", flExplosionForce ); - pExplosion->KeyValue( "DamageForce", buf ); - } - - variant_t emptyVariant; - pExplosion->m_nRenderMode = kRenderTransAdd; - pExplosion->SetOwnerEntity( pOwner ); - pExplosion->Spawn(); - pExplosion->m_hInflictor = pInflictor; - pExplosion->SetCustomDamageType( iCustomDamageType ); - if (ignoredEntity) - { - pExplosion->m_hEntityIgnore = *ignoredEntity; - } - pExplosion->m_iClassIgnore = ignoredClass; - - pExplosion->AcceptInput( "Explode", NULL, NULL, emptyVariant, 0 ); -} - - -void ExplosionCreate( const Vector ¢er, const QAngle &angles, - CBaseEntity *pOwner, int magnitude, int radius, bool doDamage, float flExplosionForce, bool bSurfaceOnly, bool bSilent, int iCustomDamageType ) -{ - // For E3, no sparks - int nFlags = SF_ENVEXPLOSION_NOSPARKS | SF_ENVEXPLOSION_NODLIGHTS | SF_ENVEXPLOSION_NOSMOKE; - if ( !doDamage ) - { - nFlags |= SF_ENVEXPLOSION_NODAMAGE; - } - - if( bSurfaceOnly ) - { - nFlags |= SF_ENVEXPLOSION_SURFACEONLY; - } - - if( bSilent ) - { - nFlags |= SF_ENVEXPLOSION_NOSOUND; - } - - ExplosionCreate( center, angles, pOwner, magnitude, radius, nFlags, flExplosionForce, NULL, iCustomDamageType ); -} - -// this version lets you specify classes or entities to be ignored -void ExplosionCreate( const Vector ¢er, const QAngle &angles, - CBaseEntity *pOwner, int magnitude, int radius, bool doDamage, - const EHANDLE *ignoredEntity, Class_T ignoredClass, - float flExplosionForce , bool bSurfaceOnly , bool bSilent , int iCustomDamageType ) -{ - // For E3, no sparks - int nFlags = SF_ENVEXPLOSION_NOSPARKS | SF_ENVEXPLOSION_NODLIGHTS | SF_ENVEXPLOSION_NOSMOKE; - if ( !doDamage ) - { - nFlags |= SF_ENVEXPLOSION_NODAMAGE; - } - - if( bSurfaceOnly ) - { - nFlags |= SF_ENVEXPLOSION_SURFACEONLY; - } - - if( bSilent ) - { - nFlags |= SF_ENVEXPLOSION_NOSOUND; - } - - ExplosionCreate( center, angles, pOwner, magnitude, radius, nFlags, flExplosionForce, NULL, iCustomDamageType, ignoredEntity, ignoredClass ); -} - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CEnvExplosion::DrawDebugTextOverlays( void ) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - - Q_snprintf(tempstr,sizeof(tempstr)," magnitude: %i", m_iMagnitude); - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} diff --git a/game/server/explode.h b/game/server/explode.h deleted file mode 100644 index e5ee9fed4..000000000 --- a/game/server/explode.h +++ /dev/null @@ -1,43 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef EXPLODE_H -#define EXPLODE_H - -#define SF_ENVEXPLOSION_NODAMAGE 0x00000001 // when set, ENV_EXPLOSION will not actually inflict damage -#define SF_ENVEXPLOSION_REPEATABLE 0x00000002 // can this entity be refired? -#define SF_ENVEXPLOSION_NOFIREBALL 0x00000004 // don't draw the fireball -#define SF_ENVEXPLOSION_NOSMOKE 0x00000008 // don't draw the smoke -#define SF_ENVEXPLOSION_NODECAL 0x00000010 // don't make a scorch mark -#define SF_ENVEXPLOSION_NOSPARKS 0x00000020 // don't make sparks -#define SF_ENVEXPLOSION_NOSOUND 0x00000040 // don't play explosion sound. -#define SF_ENVEXPLOSION_RND_ORIENT 0x00000080 // randomly oriented sprites -#define SF_ENVEXPLOSION_NOFIREBALLSMOKE 0x0100 -#define SF_ENVEXPLOSION_NOPARTICLES 0x00000200 -#define SF_ENVEXPLOSION_NODLIGHTS 0x00000400 -#define SF_ENVEXPLOSION_NOCLAMPMIN 0x00000800 // don't clamp the minimum size of the fireball sprite -#define SF_ENVEXPLOSION_NOCLAMPMAX 0x00001000 // don't clamp the maximum size of the fireball sprite -#define SF_ENVEXPLOSION_SURFACEONLY 0x00002000 // don't damage the player if he's underwater. -#define SF_ENVEXPLOSION_GENERIC_DAMAGE 0x00004000 // don't do BLAST damage - -extern short g_sModelIndexFireball; -extern short g_sModelIndexSmoke; - -void ExplosionCreate( const Vector ¢er, const QAngle &angles, - CBaseEntity *pOwner, int magnitude, int radius, bool doDamage, float flExplosionForce = 0.0f, bool bSurfaceOnly = false, bool bSilent = false, int iCustomDamageType = -1 ); - -void ExplosionCreate( const Vector ¢er, const QAngle &angles, - CBaseEntity *pOwner, int magnitude, int radius, int nSpawnFlags, - float flExplosionForce = 0.0f, CBaseEntity *pInflictor = NULL, int iCustomDamageType = -1, const EHANDLE *ignoredEntity = NULL, Class_T ignoredClass = CLASS_NONE); - -// this version lets you specify classes or entities to be ignored -void ExplosionCreate( const Vector ¢er, const QAngle &angles, - CBaseEntity *pOwner, int magnitude, int radius, bool doDamage, - const EHANDLE *ignoredEntity, Class_T ignoredClass, - float flExplosionForce = 0.0f, bool bSurfaceOnly = false, bool bSilent = false, int iCustomDamageType = -1 ); - -#endif //EXPLODE_H diff --git a/game/server/filters.cpp b/game/server/filters.cpp deleted file mode 100644 index f752b49fb..000000000 --- a/game/server/filters.cpp +++ /dev/null @@ -1,631 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "filters.h" -#include "entitylist.h" -#include "ai_squad.h" -#include "ai_basenpc.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// ################################################################### -// > BaseFilter -// ################################################################### -LINK_ENTITY_TO_CLASS(filter_base, CBaseFilter); - -BEGIN_DATADESC( CBaseFilter ) - - DEFINE_KEYFIELD(m_bNegated, FIELD_BOOLEAN, "Negated"), - - // Inputs - DEFINE_INPUTFUNC( FIELD_INPUT, "TestActivator", InputTestActivator ), - - // Outputs - DEFINE_OUTPUT( m_OnPass, "OnPass"), - DEFINE_OUTPUT( m_OnFail, "OnFail"), - -END_DATADESC() - -//----------------------------------------------------------------------------- - -bool CBaseFilter::PassesFilterImpl( CBaseEntity *pCaller, CBaseEntity *pEntity ) -{ - return true; -} - - -bool CBaseFilter::PassesFilter( CBaseEntity *pCaller, CBaseEntity *pEntity ) -{ - bool baseResult = PassesFilterImpl( pCaller, pEntity ); - return (m_bNegated) ? !baseResult : baseResult; -} - - -bool CBaseFilter::PassesDamageFilter(const CTakeDamageInfo &info) -{ - bool baseResult = PassesDamageFilterImpl(info); - return (m_bNegated) ? !baseResult : baseResult; -} - - -bool CBaseFilter::PassesDamageFilterImpl( const CTakeDamageInfo &info ) -{ - return PassesFilterImpl( NULL, info.GetAttacker() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for testing the activator. If the activator passes the -// filter test, the OnPass output is fired. If not, the OnFail output is fired. -//----------------------------------------------------------------------------- -void CBaseFilter::InputTestActivator( inputdata_t &inputdata ) -{ - if ( PassesFilter( inputdata.pCaller, inputdata.pActivator ) ) - { - m_OnPass.FireOutput( inputdata.pActivator, this ); - } - else - { - m_OnFail.FireOutput( inputdata.pActivator, this ); - } -} - - -// ################################################################### -// > FilterMultiple -// -// Allows one to filter through mutiple filters -// ################################################################### -#define MAX_FILTERS 5 -enum filter_t -{ - FILTER_AND, - FILTER_OR, -}; - -class CFilterMultiple : public CBaseFilter -{ - DECLARE_CLASS( CFilterMultiple, CBaseFilter ); - DECLARE_DATADESC(); - - filter_t m_nFilterType; - string_t m_iFilterName[MAX_FILTERS]; - EHANDLE m_hFilter[MAX_FILTERS]; - - bool PassesFilterImpl( CBaseEntity *pCaller, CBaseEntity *pEntity ); - bool PassesDamageFilterImpl(const CTakeDamageInfo &info); - void Activate(void); -}; - -LINK_ENTITY_TO_CLASS(filter_multi, CFilterMultiple); - -BEGIN_DATADESC( CFilterMultiple ) - - - // Keys - DEFINE_KEYFIELD(m_nFilterType, FIELD_INTEGER, "FilterType"), - - // Silence, Classcheck! -// DEFINE_ARRAY( m_iFilterName, FIELD_STRING, MAX_FILTERS ), - - DEFINE_KEYFIELD(m_iFilterName[0], FIELD_STRING, "Filter01"), - DEFINE_KEYFIELD(m_iFilterName[1], FIELD_STRING, "Filter02"), - DEFINE_KEYFIELD(m_iFilterName[2], FIELD_STRING, "Filter03"), - DEFINE_KEYFIELD(m_iFilterName[3], FIELD_STRING, "Filter04"), - DEFINE_KEYFIELD(m_iFilterName[4], FIELD_STRING, "Filter05"), - DEFINE_ARRAY( m_hFilter, FIELD_EHANDLE, MAX_FILTERS ), - -END_DATADESC() - - - -//------------------------------------------------------------------------------ -// Purpose : Called after all entities have been loaded -//------------------------------------------------------------------------------ -void CFilterMultiple::Activate( void ) -{ - BaseClass::Activate(); - - // We may reject an entity specified in the array of names, but we want the array of valid filters to be contiguous! - int nNextFilter = 0; - - // Get handles to my filter entities - for ( int i = 0; i < MAX_FILTERS; i++ ) - { - if ( m_iFilterName[i] != NULL_STRING ) - { - CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, m_iFilterName[i] ); - CBaseFilter *pFilter = dynamic_cast(pEntity); - if ( pFilter == NULL ) - { - Warning("filter_multi: Tried to add entity (%s) which is not a filter entity!\n", STRING( m_iFilterName[i] ) ); - continue; - } - - // Take this entity and increment out array pointer - m_hFilter[nNextFilter] = pFilter; - nNextFilter++; - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns true if the entity passes our filter, false if not. -// Input : pEntity - Entity to test. -//----------------------------------------------------------------------------- -bool CFilterMultiple::PassesFilterImpl( CBaseEntity *pCaller, CBaseEntity *pEntity ) -{ - // Test against each filter - if (m_nFilterType == FILTER_AND) - { - for (int i=0;iPassesFilter( pCaller, pEntity ) ) - { - return false; - } - } - } - return true; - } - else // m_nFilterType == FILTER_OR - { - for (int i=0;iPassesFilter( pCaller, pEntity ) ) - { - return true; - } - } - } - return false; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns true if the entity passes our filter, false if not. -// Input : pEntity - Entity to test. -//----------------------------------------------------------------------------- -bool CFilterMultiple::PassesDamageFilterImpl(const CTakeDamageInfo &info) -{ - // Test against each filter - if (m_nFilterType == FILTER_AND) - { - for (int i=0;iPassesDamageFilter(info)) - { - return false; - } - } - } - return true; - } - else // m_nFilterType == FILTER_OR - { - for (int i=0;iPassesDamageFilter(info)) - { - return true; - } - } - } - return false; - } -} - - -// ################################################################### -// > FilterName -// ################################################################### -class CFilterName : public CBaseFilter -{ - DECLARE_CLASS( CFilterName, CBaseFilter ); - DECLARE_DATADESC(); - -public: - string_t m_iFilterName; - - bool PassesFilterImpl( CBaseEntity *pCaller, CBaseEntity *pEntity ) - { - // special check for !player as GetEntityName for player won't return "!player" as a name - if (FStrEq(STRING(m_iFilterName), "!player")) - { - return pEntity->IsPlayer(); - } - else - { - return pEntity->NameMatches( STRING(m_iFilterName) ); - } - } -}; - -LINK_ENTITY_TO_CLASS( filter_activator_name, CFilterName ); - -BEGIN_DATADESC( CFilterName ) - - // Keyfields - DEFINE_KEYFIELD( m_iFilterName, FIELD_STRING, "filtername" ), - -END_DATADESC() - - - -// ################################################################### -// > FilterClass -// ################################################################### -class CFilterClass : public CBaseFilter -{ - DECLARE_CLASS( CFilterClass, CBaseFilter ); - DECLARE_DATADESC(); - -public: - string_t m_iFilterClass; - - bool PassesFilterImpl( CBaseEntity *pCaller, CBaseEntity *pEntity ) - { - return pEntity->ClassMatches( STRING(m_iFilterClass) ); - } -}; - -LINK_ENTITY_TO_CLASS( filter_activator_class, CFilterClass ); - -BEGIN_DATADESC( CFilterClass ) - - // Keyfields - DEFINE_KEYFIELD( m_iFilterClass, FIELD_STRING, "filterclass" ), - -END_DATADESC() - - -// ################################################################### -// > FilterTeam -// ################################################################### -class FilterTeam : public CBaseFilter -{ - DECLARE_CLASS( FilterTeam, CBaseFilter ); - DECLARE_DATADESC(); - -public: - int m_iFilterTeam; - - bool PassesFilterImpl( CBaseEntity *pCaller, CBaseEntity *pEntity ) - { - return ( pEntity->GetTeamNumber() == m_iFilterTeam ); - } -}; - -LINK_ENTITY_TO_CLASS( filter_activator_team, FilterTeam ); - -BEGIN_DATADESC( FilterTeam ) - - // Keyfields - DEFINE_KEYFIELD( m_iFilterTeam, FIELD_INTEGER, "filterteam" ), - -END_DATADESC() - - -// ################################################################### -// > FilterMassGreater -// ################################################################### -class CFilterMassGreater : public CBaseFilter -{ - DECLARE_CLASS( CFilterMassGreater, CBaseFilter ); - DECLARE_DATADESC(); - -public: - float m_fFilterMass; - - bool PassesFilterImpl( CBaseEntity *pCaller, CBaseEntity *pEntity ) - { - if ( pEntity->VPhysicsGetObject() == NULL ) - return false; - - return ( pEntity->VPhysicsGetObject()->GetMass() > m_fFilterMass ); - } -}; - -LINK_ENTITY_TO_CLASS( filter_activator_mass_greater, CFilterMassGreater ); - -BEGIN_DATADESC( CFilterMassGreater ) - -// Keyfields -DEFINE_KEYFIELD( m_fFilterMass, FIELD_FLOAT, "filtermass" ), - -END_DATADESC() - - -// ################################################################### -// > FilterDamageType -// ################################################################### -class FilterDamageType : public CBaseFilter -{ - DECLARE_CLASS( FilterDamageType, CBaseFilter ); - DECLARE_DATADESC(); - -protected: - - bool PassesFilterImpl(CBaseEntity *pCaller, CBaseEntity *pEntity ) - { - ASSERT( false ); - return true; - } - - bool PassesDamageFilterImpl(const CTakeDamageInfo &info) - { - return info.GetDamageType() == m_iDamageType; - } - - int m_iDamageType; -}; - -LINK_ENTITY_TO_CLASS( filter_damage_type, FilterDamageType ); - -BEGIN_DATADESC( FilterDamageType ) - - // Keyfields - DEFINE_KEYFIELD( m_iDamageType, FIELD_INTEGER, "damagetype" ), - -END_DATADESC() - -// ################################################################### -// > CFilterEnemy -// ################################################################### - -#define SF_FILTER_ENEMY_NO_LOSE_AQUIRED (1<<0) - -class CFilterEnemy : public CBaseFilter -{ - DECLARE_CLASS( CFilterEnemy, CBaseFilter ); - // NOT SAVED - // m_iszPlayerName - DECLARE_DATADESC(); - -public: - - virtual bool PassesFilterImpl( CBaseEntity *pCaller, CBaseEntity *pEntity ); - virtual bool PassesDamageFilterImpl( const CTakeDamageInfo &info ); - -private: - - bool PassesNameFilter( CBaseEntity *pCaller ); - bool PassesProximityFilter( CBaseEntity *pCaller, CBaseEntity *pEnemy ); - bool PassesMobbedFilter( CBaseEntity *pCaller, CBaseEntity *pEnemy ); - - string_t m_iszEnemyName; // Name or classname - float m_flRadius; // Radius (enemies are acquired at this range) - float m_flOuterRadius; // Outer radius (enemies are LOST at this range) - int m_nMaxSquadmatesPerEnemy; // Maximum number of squadmates who may share the same enemy - string_t m_iszPlayerName; // "!player" -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CFilterEnemy::PassesFilterImpl( CBaseEntity *pCaller, CBaseEntity *pEntity ) -{ - if ( pCaller == NULL || pEntity == NULL ) - return false; - - // If asked to, we'll never fail to pass an already acquired enemy - // This allows us to use test criteria to initially pick an enemy, then disregard the test until a new enemy comes along - if ( HasSpawnFlags( SF_FILTER_ENEMY_NO_LOSE_AQUIRED ) && ( pEntity == pCaller->GetEnemy() ) ) - return true; - - // This is a little weird, but it's saying that if we're not the entity we're excluding the filter to, then just pass it throughZ - if ( PassesNameFilter( pEntity ) == false ) - return true; - - if ( PassesProximityFilter( pCaller, pEntity ) == false ) - return false; - - // NOTE: This can result in some weird NPC behavior if used improperly - if ( PassesMobbedFilter( pCaller, pEntity ) == false ) - return false; - - // The filter has been passed, meaning: - // - If we wanted all criteria to fail, they have - // - If we wanted all criteria to succeed, they have - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CFilterEnemy::PassesDamageFilterImpl( const CTakeDamageInfo &info ) -{ - // NOTE: This function has no meaning to this implementation of the filter class! - Assert( 0 ); - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Tests the enemy's name or classname -// Input : *pEnemy - Entity being assessed -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CFilterEnemy::PassesNameFilter( CBaseEntity *pEnemy ) -{ - // If there is no name specified, we're not using it - if ( m_iszEnemyName == NULL_STRING ) - return true; - - // Cache off the special case player name - if ( m_iszPlayerName == NULL_STRING ) - { - m_iszPlayerName = FindPooledString( "!player" ); - } - - if ( m_iszEnemyName == m_iszPlayerName ) - { - if ( pEnemy->IsPlayer() ) - { - if ( m_bNegated ) - return false; - - return true; - } - } - - // May be either a targetname or classname - bool bNameOrClassnameMatches = ( m_iszEnemyName == pEnemy->GetEntityName() || m_iszEnemyName == pEnemy->m_iClassname ); - - // We only leave this code block in a state meaning we've "succeeded" in any context - if ( m_bNegated ) - { - // We wanted the names to not match, but they did - if ( bNameOrClassnameMatches ) - return false; - } - else - { - // We wanted them to be the same, but they weren't - if ( bNameOrClassnameMatches == false ) - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Tests the enemy's proximity to the caller's position -// Input : *pCaller - Entity assessing the target -// *pEnemy - Entity being assessed -// Output : Returns true if potential enemy passes this filter stage -//----------------------------------------------------------------------------- -bool CFilterEnemy::PassesProximityFilter( CBaseEntity *pCaller, CBaseEntity *pEnemy ) -{ - // If there is no radius specified, we're not testing it - if ( m_flRadius <= 0.0f ) - return true; - - // We test the proximity differently when we've already picked up this enemy before - bool bAlreadyEnemy = ( pCaller->GetEnemy() == pEnemy ); - - // Get our squared length to the enemy from the caller - float flDistToEnemySqr = ( pCaller->GetAbsOrigin() - pEnemy->GetAbsOrigin() ).LengthSqr(); - - // Two radii are used to control oscillation between true/false cases - // The larger radius is either specified or defaulted to be double or half the size of the inner radius - float flLargerRadius = m_flOuterRadius; - if ( flLargerRadius == 0 ) - { - flLargerRadius = ( m_bNegated ) ? (m_flRadius*0.5f) : (m_flRadius*2.0f); - } - - float flSmallerRadius = m_flRadius; - if ( flSmallerRadius > flLargerRadius ) - { - swap( flLargerRadius, flSmallerRadius ); - } - - float flDist; - if ( bAlreadyEnemy ) - { - flDist = ( m_bNegated ) ? flSmallerRadius : flLargerRadius; - } - else - { - flDist = ( m_bNegated ) ? flLargerRadius : flSmallerRadius; - } - - // Test for success - if ( flDistToEnemySqr <= (flDist*flDist) ) - { - // We wanted to fail but didn't - if ( m_bNegated ) - return false; - - return true; - } - - // We wanted to succeed but didn't - if ( m_bNegated == false ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Attempt to govern how many squad members can target any given entity -// Input : *pCaller - Entity assessing the target -// *pEnemy - Entity being assessed -// Output : Returns true if potential enemy passes this filter stage -//----------------------------------------------------------------------------- -bool CFilterEnemy::PassesMobbedFilter( CBaseEntity *pCaller, CBaseEntity *pEnemy ) -{ - // Must be a valid candidate - CAI_BaseNPC *pNPC = pCaller->MyNPCPointer(); - if ( pNPC == NULL || pNPC->GetSquad() == NULL ) - return true; - - // Make sure we're checking for this - if ( m_nMaxSquadmatesPerEnemy <= 0 ) - return true; - - AISquadIter_t iter; - int nNumMatchingSquadmates = 0; - - // Look through our squad members to see how many of them are already mobbing this entity - for ( CAI_BaseNPC *pSquadMember = pNPC->GetSquad()->GetFirstMember( &iter ); pSquadMember != NULL; pSquadMember = pNPC->GetSquad()->GetNextMember( &iter ) ) - { - // Disregard ourself - if ( pSquadMember == pNPC ) - continue; - - // If the enemies match, count it - if ( pSquadMember->GetEnemy() == pEnemy ) - { - nNumMatchingSquadmates++; - - // If we're at or passed the max we stop - if ( nNumMatchingSquadmates >= m_nMaxSquadmatesPerEnemy ) - { - // We wanted to find more than allowed and we did - if ( m_bNegated ) - return true; - - // We wanted to be less but we're not - return false; - } - } - } - - // We wanted to find more than the allowed amount but we didn't - if ( m_bNegated ) - return false; - - return true; -} - -LINK_ENTITY_TO_CLASS( filter_enemy, CFilterEnemy ); - -BEGIN_DATADESC( CFilterEnemy ) - - DEFINE_KEYFIELD( m_iszEnemyName, FIELD_STRING, "filtername" ), - DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "filter_radius" ), - DEFINE_KEYFIELD( m_flOuterRadius, FIELD_FLOAT, "filter_outer_radius" ), - DEFINE_KEYFIELD( m_nMaxSquadmatesPerEnemy, FIELD_INTEGER, "filter_max_per_enemy" ), - DEFINE_FIELD( m_iszPlayerName, FIELD_STRING ), - -END_DATADESC() diff --git a/game/server/filters.h b/game/server/filters.h deleted file mode 100644 index 0d31f6247..000000000 --- a/game/server/filters.h +++ /dev/null @@ -1,60 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Filters are outboard entities that hold a set of rules that other -// entities can use to determine behaviors. -// -// For example, triggers can use an activator filter to determine who -// activates them. NPCs and breakables can use a damage filter to -// determine what can damage them. -// -// Current filter criteria are: -// -// Activator name -// Activator class -// Activator team -// Damage type (for damage filters only) -// -// More than one filter can be combined to create a more complex boolean -// expression by using filter_multi. -// -//=============================================================================// - -#ifndef FILTERS_H -#define FILTERS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "baseentity.h" -#include "entityoutput.h" - -// ################################################################### -// > BaseFilter -// ################################################################### -class CBaseFilter : public CLogicalEntity -{ - DECLARE_CLASS( CBaseFilter, CLogicalEntity ); - -public: - - DECLARE_DATADESC(); - - bool PassesFilter( CBaseEntity *pCaller, CBaseEntity *pEntity ); - bool PassesDamageFilter( const CTakeDamageInfo &info ); - - bool m_bNegated; - - // Inputs - void InputTestActivator( inputdata_t &inputdata ); - - // Outputs - COutputEvent m_OnPass; // Fired when filter is passed - COutputEvent m_OnFail; // Fired when filter is failed - -protected: - - virtual bool PassesFilterImpl( CBaseEntity *pCaller, CBaseEntity *pEntity ); - virtual bool PassesDamageFilterImpl(const CTakeDamageInfo &info); -}; - -#endif // FILTERS_H diff --git a/game/server/fire.cpp b/game/server/fire.cpp deleted file mode 100644 index 0f0eb4594..000000000 --- a/game/server/fire.cpp +++ /dev/null @@ -1,1463 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -//--------------------------------------------------------- -//--------------------------------------------------------- -#include "cbase.h" -#include "decals.h" -#include "fire.h" -#include "entitylist.h" -#include "basecombatcharacter.h" -#include "ndebugoverlay.h" -#include "engine/IEngineSound.h" -#include "ispatialpartition.h" -#include "collisionutils.h" -#include "tier0/vprof.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -/******************************************************************** - NOTE: if you are looking at this file becase you would like flares - to be considered as fires (and thereby trigger gas traps), be aware - that the env_flare class is actually found in weapon_flaregun.cpp - and is really a repurposed piece of ammunition. (env_flare isn't the - rod-like safety flare prop, but rather the bit of flame on the end.) - - You will have some difficulty making it work here, because CFlare - does not inherit from CFire and will thus not be enumerated by - CFireSphere::EnumElement(). In order to have flares be detected and - used by this system, you will need to promote certain member functions - of CFire into an interface class from which both CFire and CFlare - inherit. You will also need to modify CFireSphere::EnumElement so that - it properly disambiguates between fires and flares. - - For some partial work towards this end, see changelist 192474. - - ********************************************************************/ - - - - -#define FIRE_HEIGHT 256.0f -#define FIRE_SCALE_FROM_SIZE(firesize) (firesize * (1/FIRE_HEIGHT)) - -#define FIRE_MAX_GROUND_OFFSET 24.0f //(2 feet) - -#define DEFAULT_ATTACK_TIME 4.0f -#define DEFAULT_DECAY_TIME 8.0f - -// UNDONE: This shouldn't be constant but depend on specific fire -#define FIRE_WIDTH 128 -#define FIRE_MINS Vector(-20,-20,0 ) // Sould be FIRE_WIDTH in size -#define FIRE_MAXS Vector( 20, 20,20) // Sould be FIRE_WIDTH in size -#define FIRE_SPREAD_DAMAGE_MULTIPLIER 2.0 - -#define FIRE_MAX_HEAT_LEVEL 64.0f -#define FIRE_NORMAL_ATTACK_TIME 20.0f -#define FIRE_THINK_INTERVAL 0.1 - -ConVar fire_maxabsorb( "fire_maxabsorb", "50" ); -ConVar fire_absorbrate( "fire_absorbrate", "3" ); -ConVar fire_extscale("fire_extscale", "12"); -ConVar fire_extabsorb("fire_extabsorb", "5"); -ConVar fire_heatscale( "fire_heatscale", "1.0" ); -ConVar fire_incomingheatscale( "fire_incomingheatscale", "0.1" ); -ConVar fire_dmgscale( "fire_dmgscale", "0.1" ); -ConVar fire_dmgbase( "fire_dmgbase", "1" ); -ConVar fire_growthrate( "fire_growthrate", "1.0" ); -ConVar fire_dmginterval( "fire_dmginterval", "1.0" ); - -#define VPROF_FIRE(s) VPROF( s ) - -class CFire : public CBaseEntity -{ -public: - DECLARE_CLASS( CFire, CBaseEntity ); - - int DrawDebugTextOverlays(void); - - CFire( void ); - - virtual void UpdateOnRemove( void ); - - void Precache( void ); - void Init( const Vector &position, float scale, float attackTime, float fuel, int flags, int fireType ); - bool GoOut(); - - void BurnThink(); - void GoOutThink(); - void GoOutInSeconds( float seconds ); - - void SetOwner( CBaseEntity *hOwner ) { m_hOwner = hOwner; } - - void Scale( float end, float time ); - void AddHeat( float heat, bool selfHeat = false ); - int OnTakeDamage( const CTakeDamageInfo &info ); - - bool IsBurning( void ) const; - - bool GetFireDimensions( Vector *pFireMins, Vector *pFireMaxs ); - - void Extinguish( float heat ); - void DestroyEffect(); - - virtual void Update( float simTime ); - - void Spawn( void ); - void Activate( void ); - void StartFire( void ); - void Start(); - void SetToOutSize() - { - UTIL_SetSize( this, Vector(-8,-8,0), Vector(8,8,8) ); - } - - float GetHeatLevel() { return m_flHeatLevel; } - - virtual int UpdateTransmitState(); - - void DrawDebugGeometryOverlays(void) - { - if (m_debugOverlays & OVERLAY_BBOX_BIT) - { - if ( m_lastDamage > gpGlobals->curtime && m_flHeatAbsorb > 0 ) - { - NDebugOverlay::EntityBounds(this, 88, 255, 128, 0 ,0); - char tempstr[512]; - Q_snprintf( tempstr, sizeof(tempstr), "Heat: %.1f", m_flHeatAbsorb ); - EntityText(1,tempstr, 0); - } - else if ( !IsBurning() ) - { - NDebugOverlay::EntityBounds(this, 88, 88, 128, 0 ,0); - } - - if ( IsBurning() ) - { - Vector mins, maxs; - if ( GetFireDimensions( &mins, &maxs ) ) - { - NDebugOverlay::Box(GetAbsOrigin(), mins, maxs, 128, 0, 0, 10, 0); - } - } - - - } - BaseClass::DrawDebugGeometryOverlays(); - } - - void Disable(); - - //Inputs - void InputStartFire( inputdata_t &inputdata ); - void InputExtinguish( inputdata_t &inputdata ); - void InputExtinguishTemporary( inputdata_t &inputdata ); - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - -protected: - - void Spread( void ); - void SpawnEffect( fireType_e type, float scale ); - - CHandle m_hEffect; - EHANDLE m_hOwner; - - int m_nFireType; - - float m_flFuel; - float m_flDamageTime; - float m_lastDamage; - float m_flFireSize; // size of the fire in world units - - float m_flHeatLevel; // Used as a "health" for the fire. > 0 means the fire is burning - float m_flHeatAbsorb; // This much heat must be "absorbed" before it gets transferred to the flame size - float m_flDamageScale; - - float m_flMaxHeat; - float m_flLastHeatLevel; - - //NOTENOTE: Lifetime is an expression of the sum total of these amounts plus the global time when started - float m_flAttackTime; //Amount of time to scale up - - bool m_bEnabled; - bool m_bStartDisabled; - bool m_bDidActivate; - - - COutputEvent m_OnIgnited; - COutputEvent m_OnExtinguished; - - DECLARE_DATADESC(); -}; - -class CFireSphere : public IPartitionEnumerator -{ -public: - CFireSphere( CFire **pList, int listMax, bool onlyActiveFires, const Vector &origin, float radius ); - // This gets called by the enumeration methods with each element - // that passes the test. - virtual IterationRetval_t EnumElement( IHandleEntity *pHandleEntity ); - - int GetCount() { return m_count; } - bool AddToList( CFire *pEntity ); - -private: - Vector m_origin; - float m_radiusSqr; - CFire **m_pList; - int m_listMax; - int m_count; - bool m_onlyActiveFires; -}; - -CFireSphere::CFireSphere( CFire **pList, int listMax, bool onlyActiveFires, const Vector &origin, float radius ) -{ - m_pList = pList; - m_listMax = listMax; - m_count = 0; - m_onlyActiveFires = onlyActiveFires; - m_origin = origin; - m_radiusSqr = radius * radius; -} - -bool CFireSphere::AddToList( CFire *pFire ) -{ - if ( m_count >= m_listMax ) - return false; - m_pList[m_count] = pFire; - m_count++; - return true; -} - -IterationRetval_t CFireSphere::EnumElement( IHandleEntity *pHandleEntity ) -{ - CBaseEntity *pEntity = gEntList.GetBaseEntity( pHandleEntity->GetRefEHandle() ); - if ( pEntity ) - { - // UNDONE: Measure which of these is faster -// CFire *pFire = dynamic_cast(pEntity); - if ( !FClassnameIs( pEntity, "env_fire" ) ) - return ITERATION_CONTINUE; - - CFire *pFire = static_cast(pEntity); - if ( pFire ) - { - if ( !m_onlyActiveFires || pFire->IsBurning() ) - { - if ( (m_origin - pFire->GetAbsOrigin()).LengthSqr() < m_radiusSqr ) - { - if ( !AddToList( pFire ) ) - return ITERATION_STOP; - } - } - } - } - - return ITERATION_CONTINUE; -} - - -int FireSystem_GetFiresInSphere( CFire **pList, int listMax, bool onlyActiveFires, const Vector &origin, float radius ) -{ - CFireSphere sphereEnum( pList, listMax, onlyActiveFires, origin, radius ); - partition->EnumerateElementsInSphere( PARTITION_ENGINE_NON_STATIC_EDICTS, origin, radius, false, &sphereEnum ); - - return sphereEnum.GetCount(); -} - - -bool FireSystem_IsValidFirePosition( const Vector &position, float testRadius ) -{ - CFire *pList[1]; - int count = FireSystem_GetFiresInSphere( pList, ARRAYSIZE(pList), true, position, testRadius ); - if ( count > 0 ) - return false; - return true; -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -bool FireSystem_IsFireInWall( Vector &position, fireType_e type ) -{ - // Don't check natural fire against walls - if (type == FIRE_NATURAL) - return false; - - trace_t tr; - UTIL_TraceHull( position, position+Vector(0,0,0.1), FIRE_MINS,FIRE_MAXS,MASK_SOLID, NULL, COLLISION_GROUP_NONE, &tr ); - if (tr.fraction != 1.0 || tr.startsolid) - { - //NDebugOverlay::Box(position,FIRE_MINS,FIRE_MAXS,255,0,0,50,10); - return true; - } - //NDebugOverlay::Box(position,FIRE_MINS,FIRE_MAXS,0,255,0,50,10); - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Determines whether or not a new fire may be placed at a given location -// Input : &position - where we are trying to put the new fire -// separationRadius - the maximum distance fires must be apart from one another -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool FireSystem_CanAddFire( Vector *position, float separationRadius, fireType_e type, int flags ) -{ - //See if we found a fire inside the sphere - if ( !FireSystem_IsValidFirePosition( *position, separationRadius ) ) - return false; - - // Unless our fire is floating, make sure were not too high - if (!(flags & SF_FIRE_DONT_DROP)) - { - trace_t tr; - Vector startpos = *position; - Vector endpos = *position; - - startpos[2] += 1; - endpos[2] -= FIRE_MAX_GROUND_OFFSET; - - UTIL_TraceLine( startpos, endpos, MASK_SOLID, NULL, COLLISION_GROUP_NONE, &tr ); - - //See if we're floating too high - if ( ( tr.allsolid ) || ( tr.startsolid) || ( tr.fraction == 1.0f ) ) - { - return false; - } - - //TODO: If we've hit an entity here, start it on fire - CBaseEntity *pEntity = tr.m_pEnt; - - if ( ENTINDEX( pEntity->edict() ) != 0 ) - { - return false; - } - } - - - - // Check if fire is in a wall, if so try shifting around a bit - if (FireSystem_IsFireInWall( *position, type )) - { - Vector vTestPos = *position; - vTestPos.x += 10; - if (FireSystem_IsValidFirePosition( vTestPos, separationRadius ) && !FireSystem_IsFireInWall( vTestPos, type )) - { - *position = vTestPos; - return true; - } - vTestPos.y += 10; - if (FireSystem_IsValidFirePosition( vTestPos, separationRadius ) && !FireSystem_IsFireInWall( vTestPos, type )) - { - *position = vTestPos; - return true; - } - vTestPos.y -= 20; - if (FireSystem_IsValidFirePosition( vTestPos, separationRadius ) && !FireSystem_IsFireInWall( vTestPos, type )) - { - *position = vTestPos; - return true; - } - vTestPos.x -= 20; - if (FireSystem_IsValidFirePosition( vTestPos, separationRadius ) && !FireSystem_IsFireInWall( vTestPos, type )) - { - *position = vTestPos; - return true; - } - return false; - } - - //Able to add here - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Starts a fire at a specified location -// Input : &position - position to start the fire at -// flags - any special modifiers -//----------------------------------------------------------------------------- -bool FireSystem_StartFire( const Vector &position, float fireHeight, float attack, float fuel, int flags, CBaseEntity *owner, fireType_e type ) -{ - VPROF_FIRE( "FireSystem_StartFire1" ); - - Vector testPos = position; - //Must be okay to add fire here - if ( FireSystem_CanAddFire( &testPos, 16.0f, type, flags ) == false ) - { - CFire *pFires[16]; - int fireCount = FireSystem_GetFiresInSphere( pFires, ARRAYSIZE(pFires), true, position, 16.0f ); - for ( int i = 0; i < fireCount; i++ ) - { - // add to this fire - pFires[i]->AddHeat( fireHeight, false ); - } - - return false; - } - - //Create a new fire entity - CFire *fire = (CFire *) CreateEntityByName( "env_fire" ); - - if ( fire == NULL ) - return false; - - //Spawn the fire - // Fires not placed by a designer should be cleaned up automatically (not catch fire again) - fire->AddSpawnFlags( SF_FIRE_DIE_PERMANENT ); - fire->Spawn(); - fire->Init( testPos, fireHeight, attack, fuel, flags, type ); - fire->Start(); - fire->SetOwner( owner ); - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Starts a fire on a specified model. -// Input : pEntity - The model entity to catch on fire. -// fireHeight - -// attack - -// fuel - -// flags - -// owner - -// type - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool FireSystem_StartFire( CBaseAnimating *pEntity, float fireHeight, float attack, float fuel, int flags, CBaseEntity *owner, fireType_e type ) -{ - VPROF_FIRE( "FireSystem_StartFire2" ); - - Vector position = pEntity->GetAbsOrigin(); - Vector testPos = position; - - // Make sure its a valid position for fire (not in a wall, etc) - if ( FireSystem_CanAddFire( &testPos, 16.0f, type, flags ) == false ) - { - // Contribute heat to all fires within 16 units of this fire. - CFire *pFires[16]; - int fireCount = FireSystem_GetFiresInSphere( pFires, ARRAYSIZE(pFires), true, position, 16.0f ); - for ( int i = 0; i < fireCount; i++ ) - { - pFires[i]->AddHeat( fireHeight, false ); - } - - return false; - } - - // Create a new fire entity - CFire *fire = (CFire *) CreateEntityByName( "env_fire" ); - if ( fire == NULL ) - { - return false; - } - - // Spawn the fire. - // Fires not placed by a designer should be cleaned up automatically (not catch fire again). - fire->AddSpawnFlags( SF_FIRE_DIE_PERMANENT ); - fire->Spawn(); - fire->Init( testPos, fireHeight, attack, fuel, flags, type ); - fire->Start(); - fire->SetOwner( owner ); - - return true; -} - - -void FireSystem_ExtinguishInRadius( const Vector &origin, float radius, float rate ) -{ - // UNDONE: pass this instead of percent - float heat = (1-rate) * fire_extscale.GetFloat(); - - CFire *pFires[32]; - int fireCount = FireSystem_GetFiresInSphere( pFires, ARRAYSIZE(pFires), false, origin, radius ); - for ( int i = 0; i < fireCount; i++ ) - { - pFires[i]->Extinguish( heat ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &origin - -// radius - -// heat - -//----------------------------------------------------------------------------- -void FireSystem_AddHeatInRadius( const Vector &origin, float radius, float heat ) -{ - VPROF_FIRE( "FireSystem_AddHeatInRadius" ); - - CFire *pFires[32]; - - int fireCount = FireSystem_GetFiresInSphere( pFires, ARRAYSIZE(pFires), false, origin, radius ); - for ( int i = 0; i < fireCount; i++ ) - { - pFires[i]->AddHeat( heat ); - } -} - -//----------------------------------------------------------------------------- - -bool FireSystem_GetFireDamageDimensions( CBaseEntity *pEntity, Vector *pFireMins, Vector *pFireMaxs ) -{ - CFire *pFire = dynamic_cast(pEntity); - - if ( pFire && pFire->GetFireDimensions( pFireMins, pFireMaxs ) ) - { - *pFireMins /= FIRE_SPREAD_DAMAGE_MULTIPLIER; - *pFireMaxs /= FIRE_SPREAD_DAMAGE_MULTIPLIER; - return true; - } - pFireMins->Init(); - pFireMaxs->Init(); - return false; -} - - -//================================================== -// CFire -//================================================== -BEGIN_DATADESC( CFire ) - - DEFINE_FIELD( m_hEffect, FIELD_EHANDLE ), - DEFINE_FIELD( m_hOwner, FIELD_EHANDLE ), - DEFINE_KEYFIELD( m_nFireType, FIELD_INTEGER, "firetype" ), - - DEFINE_FIELD( m_flFuel, FIELD_FLOAT ), - DEFINE_FIELD( m_flDamageTime, FIELD_TIME ), - DEFINE_FIELD( m_lastDamage, FIELD_TIME ), - DEFINE_KEYFIELD( m_flFireSize, FIELD_FLOAT, "firesize" ), - - DEFINE_KEYFIELD( m_flHeatLevel, FIELD_FLOAT, "ignitionpoint" ), - DEFINE_FIELD( m_flHeatAbsorb, FIELD_FLOAT ), - DEFINE_KEYFIELD( m_flDamageScale,FIELD_FLOAT, "damagescale" ), - - DEFINE_FIELD( m_flMaxHeat, FIELD_FLOAT ), - //DEFINE_FIELD( m_flLastHeatLevel, FIELD_FLOAT ), - - DEFINE_KEYFIELD( m_flAttackTime, FIELD_FLOAT, "fireattack" ), - DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_bStartDisabled, FIELD_BOOLEAN, "StartDisabled" ), - DEFINE_FIELD( m_bDidActivate, FIELD_BOOLEAN ), - - DEFINE_FUNCTION( BurnThink ), - DEFINE_FUNCTION( GoOutThink ), - - - - DEFINE_INPUTFUNC( FIELD_VOID, "StartFire", InputStartFire ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "Extinguish", InputExtinguish ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "ExtinguishTemporary", InputExtinguishTemporary ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - - DEFINE_OUTPUT( m_OnIgnited, "OnIgnited" ), - DEFINE_OUTPUT( m_OnExtinguished, "OnExtinguished" ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( env_fire, CFire ); - -//================================================== -// CFire -//================================================== - -CFire::CFire( void ) -{ - m_flFuel = 0.0f; - m_flAttackTime = 0.0f; - m_flDamageTime = 0.0f; - m_lastDamage = 0; - m_nFireType = FIRE_NATURAL; - - //Spreading - m_flHeatAbsorb = 8.0f; - m_flHeatLevel = 0; - - // Must be in the constructor! - AddEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID ); -} - -//----------------------------------------------------------------------------- -// UpdateOnRemove -//----------------------------------------------------------------------------- -void CFire::UpdateOnRemove( void ) -{ - //Stop any looping sounds that might be playing - StopSound( "Fire.Plasma" ); - - DestroyEffect(); - - // Chain at end to mimic destructor unwind order - BaseClass::UpdateOnRemove(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFire::Precache( void ) -{ - if ( m_nFireType == FIRE_NATURAL ) - { - UTIL_PrecacheOther("_firesmoke"); - - if ( m_spawnflags & SF_FIRE_SMOKELESS ) - { - PrecacheParticleSystem( "env_fire_tiny" ); - PrecacheParticleSystem( "env_fire_small" ); - PrecacheParticleSystem( "env_fire_medium" ); - PrecacheParticleSystem( "env_fire_large" ); - } - else - { - PrecacheParticleSystem( "env_fire_tiny_smoke" ); - PrecacheParticleSystem( "env_fire_small_smoke" ); - PrecacheParticleSystem( "env_fire_medium_smoke" ); - PrecacheParticleSystem( "env_fire_large_smoke" ); - } - } - - if ( m_nFireType == FIRE_PLASMA ) - { - UTIL_PrecacheOther("_plasma"); - } - - PrecacheScriptSound( "Fire.Plasma" ); -} - -//------------------------------------------------------------------------------ -// Purpose : Input handler for starting the fire. -//------------------------------------------------------------------------------ -void CFire::InputStartFire( inputdata_t &inputdata ) -{ - if ( !m_bEnabled ) - return; - - StartFire(); -} - -void CFire::InputEnable( inputdata_t &inputdata ) -{ - m_bEnabled = true; -} - -void CFire::InputDisable( inputdata_t &inputdata ) -{ - Disable(); -} - -void CFire::Disable() -{ - m_bEnabled = false; - if ( IsBurning() ) - { - GoOut(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CFire::InputExtinguish( inputdata_t &inputdata ) -{ - m_spawnflags &= ~SF_FIRE_INFINITE; - GoOutInSeconds( inputdata.value.Float() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CFire::InputExtinguishTemporary( inputdata_t &inputdata ) -{ - GoOutInSeconds( inputdata.value.Float() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Starts burning. -//----------------------------------------------------------------------------- -void CFire::StartFire( void ) -{ - if ( m_hEffect != NULL ) - return; - - // Trace down and start a fire there. Nothing fancy yet. - Vector vFirePos; - trace_t tr; - if ( m_spawnflags & SF_FIRE_DONT_DROP ) - { - vFirePos = GetAbsOrigin(); - } - else - { - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector( 0, 0, 1024 ), MASK_FIRE_SOLID, this, COLLISION_GROUP_NONE, &tr ); - vFirePos = tr.endpos; - } - - int spawnflags = m_spawnflags; - m_spawnflags |= SF_FIRE_START_ON; - Init( vFirePos, m_flFireSize, m_flAttackTime, GetHealth(), m_spawnflags, (fireType_e) m_nFireType ); - Start(); - m_spawnflags = spawnflags; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFire::Spawn( void ) -{ - BaseClass::Spawn(); - - Precache(); - - m_takedamage = DAMAGE_NO; - - SetSolid( SOLID_NONE ); - AddEffects( EF_NODRAW ); - SetToOutSize(); - - // set up the ignition point - m_flHeatAbsorb = m_flHeatLevel * 0.05; - m_flHeatLevel = 0; - Init( GetAbsOrigin(), m_flFireSize, m_flAttackTime, m_flFuel, m_spawnflags, m_nFireType ); - - if( m_bStartDisabled ) - { - Disable(); - } - else - { - m_bEnabled = true; - } -} - -int CFire::UpdateTransmitState() -{ - // Don't want to be FL_EDICT_DONTSEND because our fire entity may make us transmit. - return SetTransmitState( FL_EDICT_ALWAYS ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFire::Activate( void ) -{ - BaseClass::Activate(); - - //See if we should start active - if ( !m_bDidActivate && ( m_spawnflags & SF_FIRE_START_ON ) ) - { - m_flHeatLevel = m_flMaxHeat; - - StartFire(); - } - - m_bDidActivate = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFire::SpawnEffect( fireType_e type, float scale ) -{ - CBaseFire *pEffect = NULL; - switch ( type ) - { - default: - case FIRE_NATURAL: - { - CFireSmoke *fireSmoke = (CFireSmoke *) CreateEntityByName( "_firesmoke" ); - fireSmoke->EnableSmoke( ( m_spawnflags & SF_FIRE_SMOKELESS )==false ); - fireSmoke->EnableGlow( ( m_spawnflags & SF_FIRE_NO_GLOW )==false ); - fireSmoke->EnableVisibleFromAbove( ( m_spawnflags & SF_FIRE_VISIBLE_FROM_ABOVE )!=false ); - - pEffect = fireSmoke; - m_nFireType = FIRE_NATURAL; - m_takedamage = DAMAGE_YES; - } - break; - - case FIRE_PLASMA: - { - CPlasma *plasma = (CPlasma *) CreateEntityByName( "_plasma" ); - plasma->EnableSmoke( true ); - - pEffect = plasma; - m_nFireType = FIRE_PLASMA; - m_takedamage = DAMAGE_YES; - - // Start burn sound - EmitSound( "Fire.Plasma" ); - } - break; - } - - UTIL_SetOrigin( pEffect, GetAbsOrigin() ); - pEffect->Spawn(); - pEffect->SetParent( this ); - pEffect->Scale( m_flFireSize, m_flFireSize, 0 ); - //Start it going - pEffect->Enable( ( m_spawnflags & SF_FIRE_START_ON ) ); - m_hEffect = pEffect; -} - -//----------------------------------------------------------------------------- -// Purpose: Spawn and initialize the fire -// Input : &position - where the fire resides -// lifetime - -//----------------------------------------------------------------------------- -void CFire::Init( const Vector &position, float scale, float attackTime, float fuel, int flags, int fireType ) -{ - m_flAttackTime = attackTime; - - m_spawnflags = flags; - m_nFireType = fireType; - - if ( flags & SF_FIRE_INFINITE ) - { - fuel = 0; - } - m_flFuel = fuel; - if ( m_flFuel ) - { - m_spawnflags |= SF_FIRE_DIE_PERMANENT; - } - - Vector localOrigin = position; - if ( GetMoveParent() ) - { - EntityMatrix parentMatrix; - parentMatrix.InitFromEntity( GetMoveParent() ); - localOrigin = parentMatrix.WorldToLocal( position ); - } - UTIL_SetOrigin( this, localOrigin ); - - SetSolid( SOLID_NONE ); - m_flFireSize = scale; - m_flMaxHeat = FIRE_MAX_HEAT_LEVEL * FIRE_SCALE_FROM_SIZE(scale); - //See if we should start on - if ( m_spawnflags & SF_FIRE_START_FULL ) - { - m_flHeatLevel = m_flMaxHeat; - } - m_flLastHeatLevel = 0; - -} - -void CFire::Start() -{ - float boxWidth = (m_flFireSize * (FIRE_WIDTH/FIRE_HEIGHT))*0.5f; - UTIL_SetSize(this, Vector(-boxWidth,-boxWidth,0),Vector(boxWidth,boxWidth,m_flFireSize)); - - //Spawn the client-side effect - SpawnEffect( (fireType_e)m_nFireType, FIRE_SCALE_FROM_SIZE(m_flFireSize) ); - m_OnIgnited.FireOutput( this, this ); - SetThink( &CFire::BurnThink ); - m_flDamageTime = 0; - // think right now - BurnThink(); -} - -//----------------------------------------------------------------------------- -// Purpose: Determines whether or not the fire is still active -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CFire::IsBurning( void ) const -{ - if ( m_flHeatLevel > 0 ) - return true; - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Get the damage box of the fire -//----------------------------------------------------------------------------- -bool CFire::GetFireDimensions( Vector *pFireMins, Vector *pFireMaxs ) -{ - if ( m_flHeatLevel <= 0 ) - { - pFireMins->Init(); - pFireMaxs->Init(); - return false; - } - - float scale = m_flHeatLevel / m_flMaxHeat; - float damageRadius = scale * m_flFireSize * FIRE_WIDTH / FIRE_HEIGHT * 0.5; - - damageRadius *= FIRE_SPREAD_DAMAGE_MULTIPLIER; //FIXME: Trying slightly larger radius for burning - - if ( damageRadius < 16 ) - { - damageRadius = 16; - } - - pFireMins->Init(-damageRadius,-damageRadius,0); - pFireMaxs->Init(damageRadius,damageRadius,m_flFireSize*scale); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Update the fire and its children -//----------------------------------------------------------------------------- -void CFire::Update( float simTime ) -{ - VPROF_FIRE( "CFire::Update" ); - - if ( m_flFuel != 0 ) - { - m_flFuel -= simTime; - if ( m_flFuel <= 0 ) - { - GoOutInSeconds( 1 ); - return; - } - } - - float strength = m_flHeatLevel / FIRE_MAX_HEAT_LEVEL; - if ( m_flHeatLevel != m_flLastHeatLevel ) - { - m_flLastHeatLevel = m_flHeatLevel; - // Make the effect the appropriate size given the heat level - m_hEffect->Scale( strength, 0.5f ); - } - // add heat to myself (grow) - float addedHeat = (m_flAttackTime > 0) ? m_flMaxHeat / m_flAttackTime : m_flMaxHeat; - addedHeat *= simTime * fire_growthrate.GetFloat(); - AddHeat( addedHeat, true ); - - // add heat to nearby fires - float outputHeat = strength * m_flHeatLevel; - - Vector fireMins; - Vector fireMaxs; - Vector fireEntityDamageMins; - Vector fireEntityDamageMaxs; - - GetFireDimensions( &fireMins, &fireMaxs ); - - if ( FIRE_SPREAD_DAMAGE_MULTIPLIER != 1.0 ) // if set to 1.0, optimizer will remove this code - { - fireEntityDamageMins = fireMins / FIRE_SPREAD_DAMAGE_MULTIPLIER; - fireEntityDamageMaxs = fireMaxs / FIRE_SPREAD_DAMAGE_MULTIPLIER; - } - - //NDebugOverlay::Box( GetAbsOrigin(), fireMins, fireMaxs, 255, 255, 255, 0, fire_dmginterval.GetFloat() ); - fireMins += GetAbsOrigin(); - fireMaxs += GetAbsOrigin(); - - if ( FIRE_SPREAD_DAMAGE_MULTIPLIER != 1.0 ) - { - fireEntityDamageMins += GetAbsOrigin(); - fireEntityDamageMaxs += GetAbsOrigin(); - } - - CBaseEntity *pNearby[256]; - CFire *pFires[16]; - int nearbyCount = UTIL_EntitiesInBox( pNearby, ARRAYSIZE(pNearby), fireMins, fireMaxs, 0 ); - int fireCount = 0; - int i; - - // is it time to do damage? - bool damage = false; - int outputDamage = 0; - if ( m_flDamageTime <= gpGlobals->curtime ) - { - m_flDamageTime = gpGlobals->curtime + fire_dmginterval.GetFloat(); - outputDamage = (int)((fire_dmgbase.GetFloat() + outputHeat * fire_dmgscale.GetFloat() * m_flDamageScale) * fire_dmginterval.GetFloat()); - if ( outputDamage ) - { - damage = true; - } - } - int damageFlags = (m_nFireType == FIRE_NATURAL) ? DMG_BURN : DMG_PLASMA; - for ( i = 0; i < nearbyCount; i++ ) - { - CBaseEntity *pOther = pNearby[i]; - - if ( pOther == this ) - { - continue; - } - else if ( FClassnameIs( pOther, "env_fire" ) ) - { - if ( fireCount < (int)ARRAYSIZE(pFires) ) - { - pFires[fireCount] = (CFire *)pOther; - fireCount++; - } - continue; - } - else if ( pOther->m_takedamage == DAMAGE_NO ) - { - pNearby[i] = NULL; - } - else if ( damage ) - { - bool bDoDamage; - - if ( FIRE_SPREAD_DAMAGE_MULTIPLIER != 1.0 && !pOther->IsPlayer() ) // if set to 1.0, optimizer will remove this code - { - Vector otherMins, otherMaxs; - pOther->CollisionProp()->WorldSpaceAABB( &otherMins, &otherMaxs ); - bDoDamage = IsBoxIntersectingBox( otherMins, otherMaxs, - fireEntityDamageMins, fireEntityDamageMaxs ); - - } - else - bDoDamage = true; - - if ( bDoDamage ) - { - // Make sure can actually see entity (don't damage through walls) - trace_t tr; - UTIL_TraceLine( this->WorldSpaceCenter(), pOther->WorldSpaceCenter(), MASK_FIRE_SOLID, pOther, COLLISION_GROUP_NONE, &tr ); - - if (tr.fraction == 1.0 && !tr.startsolid) - { - pOther->TakeDamage( CTakeDamageInfo( this, this, outputDamage, damageFlags ) ); - } - } - } - } - - outputHeat *= fire_heatscale.GetFloat() * simTime; - - if ( fireCount > 0 ) - { - outputHeat /= fireCount; - for ( i = 0; i < fireCount; i++ ) - { - pFires[i]->AddHeat( outputHeat, false ); - } - } -} - -// Destroy any effect I have -void CFire::DestroyEffect() -{ - CBaseFire *pEffect = m_hEffect; - if ( pEffect != NULL ) - { - //disable the graphics and remove the entity - pEffect->Enable( false ); - UTIL_Remove( pEffect ); - } -} -//----------------------------------------------------------------------------- -// Purpose: Think -//----------------------------------------------------------------------------- -void CFire::BurnThink( void ) -{ - SetNextThink( gpGlobals->curtime + FIRE_THINK_INTERVAL ); - - Update( FIRE_THINK_INTERVAL ); -} - -void CFire::GoOutThink() -{ - GoOut(); -} - -void CFire::GoOutInSeconds( float seconds ) -{ - Scale( 0.0f, seconds ); - - SetThink( &CFire::GoOutThink ); - SetNextThink( gpGlobals->curtime + seconds ); -} - -//------------------------------------------------------------------------------ -// Purpose : Blasts of significant size blow out fires that take damage -// Input : -// Output : -//------------------------------------------------------------------------------ -int CFire::OnTakeDamage( const CTakeDamageInfo &info ) -{ - return 0; -} - -void CFire::AddHeat( float heat, bool selfHeat ) -{ - if ( m_bEnabled ) - { - if ( !selfHeat ) - { - if ( IsBurning() ) - { - // scale back the incoming heat from surrounding fires - // if I've already ignited - heat *= fire_incomingheatscale.GetFloat(); - } - } - m_lastDamage = gpGlobals->curtime + 0.5; - bool start = m_flHeatLevel <= 0 ? true : false; - if ( m_flHeatAbsorb > 0 ) - { - float absorbDamage = heat * fire_absorbrate.GetFloat(); - if ( absorbDamage > m_flHeatAbsorb ) - { - heat -= m_flHeatAbsorb / fire_absorbrate.GetFloat(); - m_flHeatAbsorb = 0; - } - else - { - m_flHeatAbsorb -= absorbDamage; - heat = 0; - } - } - - m_flHeatLevel += heat; - if ( start && m_flHeatLevel > 0 && m_hEffect == NULL ) - { - StartFire(); - } - if ( m_flHeatLevel > m_flMaxHeat ) - m_flHeatLevel = m_flMaxHeat; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : end - -// time - -//----------------------------------------------------------------------------- -void CFire::Scale( float end, float time ) -{ - CBaseFire *pEffect = m_hEffect; - if ( pEffect ) - { - pEffect->Scale( end, time ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : time - -//----------------------------------------------------------------------------- -void CFire::Extinguish( float heat ) -{ - if ( !m_bEnabled ) - return; - - m_lastDamage = gpGlobals->curtime + 0.5; - bool out = m_flHeatLevel > 0 ? true : false; - - m_flHeatLevel -= heat; - m_flHeatAbsorb += fire_extabsorb.GetFloat() * heat; - if ( m_flHeatAbsorb > fire_maxabsorb.GetFloat() ) - { - m_flHeatAbsorb = fire_maxabsorb.GetFloat(); - } - - // drift toward the average attack time after being sprayed - // some fires are heavily scripted so their attack looks weird - // once interacted with. Basically, this blends out the scripting - // as the fire is sprayed with the extinguisher. - float averageAttackTime = m_flMaxHeat * (FIRE_NORMAL_ATTACK_TIME/FIRE_MAX_HEAT_LEVEL); - m_flAttackTime = Approach( averageAttackTime, m_flAttackTime, 2 * gpGlobals->frametime ); - - if ( m_flHeatLevel <= 0 ) - { - m_flHeatLevel = 0; - if ( out ) - { - GoOut(); - } - } -} - -bool CFire::GoOut() -{ - //Signal death - m_OnExtinguished.FireOutput( this, this ); - - DestroyEffect(); - m_flHeatLevel -= 20; - if ( m_flHeatLevel > 0 ) - m_flHeatLevel = 0; - - m_flLastHeatLevel = m_flHeatLevel; - SetThink(NULL); - SetNextThink( TICK_NEVER_THINK ); - if ( m_spawnflags & SF_FIRE_DIE_PERMANENT ) - { - UTIL_Remove( this ); - return true; - } - SetToOutSize(); - - return false; -} - -//================================================== -// CEnvFireSource is a source of heat that the player -// cannot put out -//================================================== - -#define FIRESOURCE_THINK_TIME 0.25 // seconds to - -#define SF_FIRESOURCE_START_ON 0x0001 - -class CEnvFireSource : public CBaseEntity -{ - DECLARE_CLASS( CEnvFireSource, CBaseEntity ); -public: - void Spawn(); - void Think(); - void TurnOn(); - void TurnOff(); - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - -private: - bool m_bEnabled; - float m_radius; - float m_damage; -}; - -BEGIN_DATADESC( CEnvFireSource ) - - DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_radius, FIELD_FLOAT, "fireradius" ), - DEFINE_KEYFIELD( m_damage,FIELD_FLOAT, "firedamage" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( env_firesource, CEnvFireSource ); - -void CEnvFireSource::Spawn() -{ - if ( m_spawnflags & SF_FIRESOURCE_START_ON ) - { - TurnOn(); - } - else - { - TurnOff(); - } -} - -void CEnvFireSource::Think() -{ - if ( !m_bEnabled ) - return; - SetNextThink( gpGlobals->curtime + FIRESOURCE_THINK_TIME ); - - CFire *pFires[128]; - int fireCount = FireSystem_GetFiresInSphere( pFires, ARRAYSIZE(pFires), false, GetAbsOrigin(), m_radius ); - - for ( int i = 0; i < fireCount; i++ ) - { - pFires[i]->AddHeat( m_damage * FIRESOURCE_THINK_TIME ); - } -} - -void CEnvFireSource::TurnOn() -{ - if ( m_bEnabled ) - return; - - m_bEnabled = true; - SetNextThink( gpGlobals->curtime ); -} - -void CEnvFireSource::TurnOff() -{ - if ( !m_bEnabled ) - return; - - m_bEnabled = false; - SetNextThink( TICK_NEVER_THINK ); -} -void CEnvFireSource::InputEnable( inputdata_t &inputdata ) -{ - TurnOn(); -} -void CEnvFireSource::InputDisable( inputdata_t &inputdata ) -{ - TurnOff(); -} - -//================================================== -// CEnvFireSensor detects changes in heat -//================================================== -#define SF_FIRESENSOR_START_ON 1 - -class CEnvFireSensor : public CBaseEntity -{ - DECLARE_CLASS( CEnvFireSensor, CBaseEntity ); -public: - void Spawn(); - void Think(); - void TurnOn(); - void TurnOff(); - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - -private: - bool m_bEnabled; - bool m_bHeatAtLevel; - float m_radius; - float m_targetLevel; - float m_targetTime; - float m_levelTime; - - COutputEvent m_OnHeatLevelStart; - COutputEvent m_OnHeatLevelEnd; -}; - -BEGIN_DATADESC( CEnvFireSensor ) - - DEFINE_KEYFIELD( m_radius, FIELD_FLOAT, "fireradius" ), - DEFINE_KEYFIELD( m_targetLevel, FIELD_FLOAT, "heatlevel" ), - DEFINE_KEYFIELD( m_targetTime, FIELD_FLOAT, "heattime" ), - - DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bHeatAtLevel, FIELD_BOOLEAN ), - DEFINE_FIELD( m_levelTime, FIELD_FLOAT ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - - DEFINE_OUTPUT( m_OnHeatLevelStart, "OnHeatLevelStart"), - DEFINE_OUTPUT( m_OnHeatLevelEnd, "OnHeatLevelEnd"), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( env_firesensor, CEnvFireSensor ); - -void CEnvFireSensor::Spawn() -{ - if ( m_spawnflags & SF_FIRESENSOR_START_ON ) - { - TurnOn(); - } - else - { - TurnOff(); - } -} - -void CEnvFireSensor::Think() -{ - if ( !m_bEnabled ) - return; - - float time = m_targetTime * 0.25; - if ( time < 0.1 ) - { - time = 0.1; - } - SetNextThink( gpGlobals->curtime + time ); - - float heat = 0; - CFire *pFires[128]; - int fireCount = FireSystem_GetFiresInSphere( pFires, ARRAYSIZE(pFires), true, GetAbsOrigin(), m_radius ); - for ( int i = 0; i < fireCount; i++ ) - { - heat += pFires[i]->GetHeatLevel(); - } - - if ( heat >= m_targetLevel ) - { - m_levelTime += time; - if ( m_levelTime >= m_targetTime ) - { - if ( !m_bHeatAtLevel ) - { - m_bHeatAtLevel = true; - m_OnHeatLevelStart.FireOutput( this, this ); - } - } - } - else - { - m_levelTime = 0; - if ( m_bHeatAtLevel ) - { - m_bHeatAtLevel = false; - m_OnHeatLevelEnd.FireOutput( this, this ); - } - } -} - -void CEnvFireSensor::TurnOn() -{ - if ( m_bEnabled ) - return; - - m_bEnabled = true; - SetNextThink( gpGlobals->curtime ); - m_bHeatAtLevel = false; - m_levelTime = 0; -} - -void CEnvFireSensor::TurnOff() -{ - if ( !m_bEnabled ) - return; - - m_bEnabled = false; - SetNextThink( TICK_NEVER_THINK ); - if ( m_bHeatAtLevel ) - { - m_bHeatAtLevel = false; - m_OnHeatLevelEnd.FireOutput( this, this ); - } - -} -void CEnvFireSensor::InputEnable( inputdata_t &inputdata ) -{ - TurnOn(); -} -void CEnvFireSensor::InputDisable( inputdata_t &inputdata ) -{ - TurnOff(); -} - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CFire::DrawDebugTextOverlays( void ) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - - // print flame size - Q_snprintf(tempstr,sizeof(tempstr)," size: %f", m_flFireSize); - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} diff --git a/game/server/fire.h b/game/server/fire.h deleted file mode 100644 index 02edbab2d..000000000 --- a/game/server/fire.h +++ /dev/null @@ -1,52 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef FIRE_H -#define FIRE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "entityoutput.h" -#include "fire_smoke.h" -#include "plasma.h" - -//Spawnflags -#define SF_FIRE_INFINITE 0x00000001 -#define SF_FIRE_SMOKELESS 0x00000002 -#define SF_FIRE_START_ON 0x00000004 -#define SF_FIRE_START_FULL 0x00000008 -#define SF_FIRE_DONT_DROP 0x00000010 -#define SF_FIRE_NO_GLOW 0x00000020 -#define SF_FIRE_DIE_PERMANENT 0x00000080 -#define SF_FIRE_VISIBLE_FROM_ABOVE 0x00000100 - -//================================================== -// CFire -//================================================== - -enum fireType_e -{ - FIRE_NATURAL = 0, - FIRE_PLASMA, -}; - -//================================================== - -// NPCs and grates do not prevent fire from travelling -#define MASK_FIRE_SOLID ( MASK_SOLID & (~(CONTENTS_MONSTER|CONTENTS_GRATE)) ) - -//================================================== -// FireSystem -//================================================== -bool FireSystem_StartFire( const Vector &position, float fireHeight, float attack, float fuel, int flags, CBaseEntity *owner, fireType_e type = FIRE_NATURAL); -void FireSystem_ExtinguishInRadius( const Vector &origin, float radius, float rate ); -void FireSystem_AddHeatInRadius( const Vector &origin, float radius, float heat ); - -bool FireSystem_GetFireDamageDimensions( CBaseEntity *pFire, Vector *pFireMins, Vector *pFireMaxs ); - -#endif // FIRE_H diff --git a/game/server/fire_smoke.cpp b/game/server/fire_smoke.cpp deleted file mode 100644 index 6266118aa..000000000 --- a/game/server/fire_smoke.cpp +++ /dev/null @@ -1,191 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "fire_smoke.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CBaseFire ) - - DEFINE_FIELD( m_flStartScale, FIELD_FLOAT ), - DEFINE_FIELD( m_flScale, FIELD_FLOAT ), - DEFINE_FIELD( m_flScaleTime, FIELD_TIME ), - DEFINE_FIELD( m_nFlags, FIELD_INTEGER ), - -END_DATADESC() - - -//================================================== -// CBaseFire -//================================================== - -CBaseFire::CBaseFire( void ) -{ - m_flStartScale = 0.0f; - m_flScale = 0.0f; - m_flScaleTime = 0.0f; - m_nFlags = bitsFIRE_NONE; -} - -CBaseFire::~CBaseFire( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: Take the current scale of the flame and move it towards a destination -// Input : size - destination size -// time - time to scale across -//----------------------------------------------------------------------------- -void CBaseFire::Scale( float size, float time ) -{ - //Send to the client - m_flScale = size; - m_flScaleTime = time; -} - -//----------------------------------------------------------------------------- -// Purpose: Overloaded Scale() function to set size -// Input : start - beginning sizek -// size - destination size -// time - time to scale across -//----------------------------------------------------------------------------- -void CBaseFire::Scale( float start, float size, float time ) -{ - //Send to the client - m_flStartScale = start; - m_flScale = size; - m_flScaleTime = time; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : state - -//----------------------------------------------------------------------------- -void CBaseFire::Enable( int state ) -{ - if ( state ) - { - m_nFlags |= bitsFIRE_ACTIVE; - } - else - { - m_nFlags &= ~bitsFIRE_ACTIVE; - } -} - -//================================================== -// CFireSmoke -//================================================== - -//Link the entity -LINK_ENTITY_TO_CLASS( _firesmoke, CFireSmoke ); - -//Send datatable -IMPLEMENT_SERVERCLASS_ST( CFireSmoke, DT_FireSmoke ) - SendPropFloat( SENDINFO( m_flStartScale ), 0, SPROP_NOSCALE), - SendPropFloat( SENDINFO( m_flScale ), 0, SPROP_NOSCALE), - SendPropFloat( SENDINFO( m_flScaleTime ), 0, SPROP_NOSCALE), - SendPropInt( SENDINFO( m_nFlags ), 8, SPROP_UNSIGNED ), - SendPropModelIndex( SENDINFO( m_nFlameModelIndex ) ), - SendPropModelIndex( SENDINFO( m_nFlameFromAboveModelIndex ) ), -END_SEND_TABLE() - -//Data description -BEGIN_DATADESC( CFireSmoke ) - - DEFINE_FIELD( m_flStartScale, FIELD_FLOAT ), - DEFINE_FIELD( m_flScale, FIELD_FLOAT ), - DEFINE_FIELD( m_flScaleTime, FIELD_FLOAT ), - DEFINE_FIELD( m_nFlags, FIELD_INTEGER ), - DEFINE_FIELD( m_nFlameModelIndex, FIELD_MODELINDEX ), - DEFINE_FIELD( m_nFlameFromAboveModelIndex, FIELD_MODELINDEX ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CFireSmoke::CFireSmoke( void ) -{ - //Client-side - m_flScale = 0.0f; - m_flScaleTime = 0.0f; - m_nFlags = bitsFIRE_NONE; - - //Server-side - AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CFireSmoke::~CFireSmoke( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFireSmoke::Precache() -{ - BaseClass::Precache(); -} - -void CFireSmoke::Spawn() -{ - Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : state - -//----------------------------------------------------------------------------- -void CFireSmoke::EnableSmoke( int state ) -{ - if ( state ) - { - m_nFlags |= bitsFIRESMOKE_SMOKE; - } - else - { - m_nFlags &= ~bitsFIRESMOKE_SMOKE; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : state - -//----------------------------------------------------------------------------- -void CFireSmoke::EnableGlow( int state ) -{ - if ( state ) - { - m_nFlags |= bitsFIRESMOKE_GLOW; - } - else - { - m_nFlags &= ~bitsFIRESMOKE_GLOW; - } -} - -void CFireSmoke::EnableVisibleFromAbove( int state ) -{ - if ( state ) - { - m_nFlags |= bitsFIRESMOKE_VISIBLE_FROM_ABOVE; - } - else - { - m_nFlags &= ~bitsFIRESMOKE_VISIBLE_FROM_ABOVE; - } -} diff --git a/game/server/fire_smoke.h b/game/server/fire_smoke.h deleted file mode 100644 index 4b3cb70f9..000000000 --- a/game/server/fire_smoke.h +++ /dev/null @@ -1,78 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef FIRE_SMOKE_H -#define FIRE_SMOKE_H -#pragma once - -#include "baseparticleentity.h" - -//================================================== -// CBaseFire -//================================================== - -//NOTENOTE: Reserved for all descendants -#define bitsFIRE_NONE 0x00000000 -#define bitsFIRE_ACTIVE 0x00000001 - -class CBaseFire : public CBaseEntity -{ -public: - DECLARE_DATADESC(); - DECLARE_CLASS( CBaseFire, CBaseEntity ); - - CBaseFire( void ); - virtual ~CBaseFire( void ); - - virtual void Scale( float size, float time ); - virtual void Scale( float start, float size, float time ); - virtual void Enable( int state = true ); - - //Client-side - CNetworkVar( float, m_flStartScale ); - CNetworkVar( float, m_flScale ); - CNetworkVar( float, m_flScaleTime ); - CNetworkVar( int, m_nFlags ); -}; - -//================================================== -// CFireSmoke -//================================================== - -//NOTENOTE: Mirrored in cl_dll/c_fire_smoke.cpp -#define bitsFIRESMOKE_SMOKE 0x00000002 -#define bitsFIRESMOKE_SMOKE_COLLISION 0x00000004 -#define bitsFIRESMOKE_GLOW 0x00000008 -#define bitsFIRESMOKE_VISIBLE_FROM_ABOVE 0x00000010 - -class CFireSmoke : public CBaseFire -{ -public: - DECLARE_CLASS( CFireSmoke, CBaseFire ); - - CFireSmoke( void ); - virtual ~CFireSmoke( void ); - - void Spawn(); - void Precache(); - void EnableSmoke( int state = true ); - void EnableGlow( int state = true ); - void EnableVisibleFromAbove( int state = true ); - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - -public: - - //Client-side - CNetworkVar( int, m_nFlameModelIndex ); - CNetworkVar( int, m_nFlameFromAboveModelIndex ); - - //Server-side -}; - -#endif //FIRE_SMOKE_H diff --git a/game/server/fish.cpp b/game/server/fish.cpp deleted file mode 100644 index 783554b5e..000000000 --- a/game/server/fish.cpp +++ /dev/null @@ -1,733 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// -// fish.cpp -// Simple fish behavior -// Author: Michael S. Booth, April 2005 - -#include "cbase.h" -#include "fish.h" -#include "saverestore_utlvector.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar fish_dormant( "fish_dormant", "0", FCVAR_REPLICATED | FCVAR_CHEAT, "Turns off interactive fish behavior. Fish become immobile and unresponsive." ); - - -//----------------------------------------------------------------------------------------------------- -LINK_ENTITY_TO_CLASS( fish, CFish ); - - -//----------------------------------------------------------------------------------------------------- -BEGIN_DATADESC( CFish ) - DEFINE_FIELD( m_pool, FIELD_EHANDLE ), - DEFINE_FIELD( m_id, FIELD_INTEGER ), - DEFINE_FIELD( m_angle, FIELD_FLOAT ), - DEFINE_FIELD( m_angleChange, FIELD_FLOAT ), - DEFINE_FIELD( m_forward, FIELD_VECTOR ), - DEFINE_FIELD( m_perp, FIELD_VECTOR ), - DEFINE_FIELD( m_poolOrigin, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_waterLevel, FIELD_FLOAT ), - DEFINE_FIELD( m_speed, FIELD_FLOAT ), - DEFINE_FIELD( m_desiredSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_calmSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_panicSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_avoidRange, FIELD_FLOAT ), - DEFINE_FIELD( m_turnClockwise, FIELD_BOOLEAN ), -END_DATADESC() - - -//----------------------------------------------------------------------------------------------------- -/** - * Send fish position relative to pool origin - */ -void SendProxy_FishOriginX( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ) -{ - CFish *fish = (CFish *)pStruct; - Assert( fish ); - - const Vector &v = fish->GetAbsOrigin(); - Vector origin = fish->m_poolOrigin; - - pOut->m_Float = v.x - origin.x; -} - -void SendProxy_FishOriginY( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ) -{ - CFish *fish = (CFish *)pStruct; - Assert( fish ); - - const Vector &v = fish->GetAbsOrigin(); - Vector origin = fish->m_poolOrigin; - - pOut->m_Float = v.y - origin.y; -} - -// keep angle in normalized range when sending it -void SendProxy_FishAngle( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ) -{ - float value = *((float *)pData); - - while( value > 360.0f ) - value -= 360.0f; - - while (value < 0.0f) - value += 360.0f; - - pOut->m_Float = value; -} - - -/** - * NOTE: Do NOT use SPROP_CHANGES_OFTEN, as it will reorder this list. - * The pool origin must arrive befoore m_x and m_y or the fish will - * respawn at the origin and zip back to their proper places. - */ -IMPLEMENT_SERVERCLASS_ST_NOBASE( CFish, DT_CFish ) - - SendPropVector( SENDINFO(m_poolOrigin), -1, SPROP_COORD, 0.0f, HIGH_DEFAULT ), // only sent once - - SendPropFloat( SENDINFO(m_angle), 7, 0 /*SPROP_CHANGES_OFTEN*/, 0.0f, 360.0f, SendProxy_FishAngle ), - - SendPropFloat( SENDINFO(m_x), 7, 0 /*SPROP_CHANGES_OFTEN*/, -255.0f, 255.0f ), - SendPropFloat( SENDINFO(m_y), 7, 0 /*SPROP_CHANGES_OFTEN*/, -255.0f, 255.0f ), - SendPropFloat( SENDINFO(m_z), -1, SPROP_COORD ), // only sent once - - SendPropModelIndex( SENDINFO(m_nModelIndex) ), - SendPropInt( SENDINFO(m_lifeState) ), - - SendPropFloat( SENDINFO(m_waterLevel) ), // only sent once - -END_SEND_TABLE() - - - -//------------------------------------------------------------------------------------------------------------- -CFish::CFish( void ) -{ -} - - -//------------------------------------------------------------------------------------------------------------- -CFish::~CFish() -{ -} - - -//------------------------------------------------------------------------------------------------------------- -void CFish::Initialize( CFishPool *pool, unsigned int id ) -{ - m_pool = pool; - m_id = id; - - m_poolOrigin = pool->GetAbsOrigin(); - m_waterLevel = pool->GetWaterLevel(); - - // pass relative position to the client - Vector deltaPos = GetAbsOrigin() - m_poolOrigin; - m_x = deltaPos.x; - m_y = deltaPos.y; - m_z = m_poolOrigin->z; - - SetModel( pool->GetModelName().ToCStr() ); -} - - -//------------------------------------------------------------------------------------------------------------- -void CFish::Spawn( void ) -{ - Precache(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE | FSOLID_NOT_SOLID | FSOLID_TRIGGER ); - SetMoveType( MOVETYPE_FLY ); - - m_angle = RandomFloat( 0.0f, 360.0f ); - m_angleChange = 0.0f; - - m_forward = Vector( 1.0f, 0.0, 0.0f ); - m_perp.x = -m_forward.y; - m_perp.y = m_forward.x; - m_perp.z = 0.0f; - - m_speed = 0.0f; - m_calmSpeed = RandomFloat( 10.0f, 20.0f ); - m_panicSpeed = m_calmSpeed * RandomFloat( 4.0f, 5.0f ); - m_desiredSpeed = m_calmSpeed; - - m_turnClockwise = (RandomInt( 0, 100 ) < 50); - - m_avoidRange = RandomFloat( 40.0f, 75.0f ); - - m_iHealth = 1; - m_iMaxHealth = 1; - m_takedamage = DAMAGE_YES; - - // spread out a bit - m_disperseTimer.Start( RandomFloat( 0.0f, 10.0f ) ); - m_goTimer.Start( RandomFloat( 10.0f, 60.0f ) ); - m_moveTimer.Start( RandomFloat( 2.0f, 10.0 ) ); - m_desiredSpeed = m_calmSpeed; -} - - -//------------------------------------------------------------------------------------------------------------- -void CFish::Event_Killed( const CTakeDamageInfo &info ) -{ - m_takedamage = DAMAGE_NO; - m_lifeState = LIFE_DEAD; -} - - -//------------------------------------------------------------------------------------------------------------- -/** - * In contact with "other" - */ -void CFish::Touch( CBaseEntity *other ) -{ - if (other && other->IsPlayer()) - { - // touched a Player - panic! - Panic(); - } -} - - -//------------------------------------------------------------------------------------------------------------- -/** - * Influence my motion to flock with other nearby fish - * 'amount' ranges from zero to one, representing the amount of flocking influence allowed - * If 'other' is NULL, flock to the center of the pool. - */ -void CFish::FlockTo( CFish *other, float amount ) -{ - // allow fish to disperse a bit at round start - if (!m_disperseTimer.IsElapsed()) - return; - - const float maxRange = (other) ? 100.0f : 300.0f; - - Vector to = (other) ? (other->GetAbsOrigin() - GetAbsOrigin()) : (m_pool->GetAbsOrigin() - GetAbsOrigin()); - float range = to.NormalizeInPlace(); - - if (range > maxRange) - return; - - // if they are close and we are moving together, avoid them - const float avoidRange = 25.0f; - if (other && range < avoidRange) - { - // compute their relative velocity to us - Vector relVel = other->GetAbsVelocity() - GetAbsVelocity(); - - if (DotProduct( to, relVel ) < 0.0f) - { - const float avoidPower = 5.0f; - - // their comin' right at us! - avoid - if (DotProduct( m_perp, to ) > 0.0f) - { - m_angleChange -= avoidPower * (1.0f - range/avoidRange); - } - else - { - m_angleChange += avoidPower * (1.0f - range/avoidRange); - } - return; - } - } - - // turn is 2 if 'other' is behind us, 1 perpendicular, and 0 straight ahead - float turn = 1.0f + DotProduct( -m_forward, to ); - - Vector perp( -m_forward.y, m_forward.x, 0.0f ); - float side = (DotProduct( perp, to ) > 1.0f) ? 1.0f : -1.0f; - - if (turn > 1.0f) - { - // always turn one way to avoid dithering if many fish are behind us - side = (m_turnClockwise) ? 1.0f : -1.0f; - } - - float power = 1.0f - (range / maxRange); - - const float flockInfluence = 0.7f; // 0.3f; // 0.3 - m_angleChange += amount * flockInfluence * power * side * turn; -} - - -//------------------------------------------------------------------------------------------------------------- -/** - * Returns a value between zero (no danger of hitting an obstacle) - * and one (extreme danger of hitting an obstacle). - * This is used to modulate later flocking behaviors. - */ -float CFish::Avoid( void ) -{ - const float avoidPower = 100.0f; // 50.0f; // 25.0f; - - // - // Stay within pool bounds. - // This may cause problems with pools with oddly concave portions - // right at the max range. - // - Vector toCenter = m_pool->GetAbsOrigin() - GetAbsOrigin(); - const float avoidZone = 20.0f; - if (toCenter.IsLengthGreaterThan( m_pool->GetMaxRange() - avoidZone )) - { - // turn away from edge - if (DotProduct( toCenter, m_forward ) < 0.0f) - { - m_angleChange += (m_turnClockwise) ? -avoidPower : avoidPower; - } - - // take total precedence over flocking - return 1.0f; - } - - trace_t result; - const float sideOffset = 0.2f; - - float rightDanger = 0.0f; - float leftDanger = 0.0f; - - // slightly right of forward - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + m_avoidRange * (m_forward + sideOffset * m_perp), MASK_PLAYERSOLID, this, COLLISION_GROUP_NONE, &result ); - if (result.fraction < 1.0f) - { - rightDanger = 1.0f - result.fraction; - } - - // slightly left of forward - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + m_avoidRange * (m_forward - sideOffset * m_perp), MASK_PLAYERSOLID, this, COLLISION_GROUP_NONE, &result ); - if (result.fraction < 1.0f) - { - // steer away - leftDanger = 1.0f - result.fraction; - } - - // steer away - prefer one side to avoid cul-de-sacs - if (m_turnClockwise) - { - if (rightDanger > 0.0f) - { - m_angleChange -= avoidPower * rightDanger; - } - else - { - m_angleChange += avoidPower * leftDanger; - } - } - else - { - if (leftDanger > 0.0f) - { - m_angleChange += avoidPower * leftDanger; - } - else - { - m_angleChange -= avoidPower * rightDanger; - } - } - - - return (leftDanger > rightDanger) ? leftDanger : rightDanger; -} - - -//------------------------------------------------------------------------------------------------------------- -void CFish::Panic( void ) -{ - // start to panic - m_panicTimer.Start( RandomFloat( 5.0f, 15.0f ) ); - m_moveTimer.Start( RandomFloat( 10.0f, 20.0f ) ); - m_desiredSpeed = m_panicSpeed; -} - - -//------------------------------------------------------------------------------------------------------------- -/** - * Invoked each server tick - */ -void CFish::Update( float deltaT ) -{ - Vector deltaPos = GetAbsOrigin() - m_poolOrigin; - const float safetyMargin = 5.0f; - - // pass relative position to the client - // clamp them here to cover the rare cases where a fish's high velocity skirts the range limit - m_x = clamp( deltaPos.x, -255.0f, 255.0f ); - m_y = clamp( deltaPos.y, -255.0f, 255.0f ); - m_z = m_poolOrigin->z; - - - // - // Dead fish just coast to a stop. All floating to the - // surface and bobbing motion is handled client-side. - // - if (m_lifeState == LIFE_DEAD) - { - // don't allow fish to leave maximum range of pool - if (deltaPos.IsLengthGreaterThan( m_pool->GetMaxRange() - safetyMargin )) - { - SetAbsVelocity( Vector( 0, 0, 0 ) ); - } - else - { - // decay movement speed to zero - Vector vel = GetAbsVelocity(); - - const float drag = 1.0f; - vel -= drag * vel * deltaT; - - SetAbsVelocity( vel ); - } - - return; - } - - - // - // Living fish behavior - // - - // periodically change our turning preference - if (m_turnTimer.IsElapsed()) - { - m_turnTimer.Start( RandomFloat( 10.0f, 30.0f ) ); - m_turnClockwise = !m_turnClockwise; - } - - if (m_panicTimer.GetRemainingTime() > 0.0f) - { - // panicking - m_desiredSpeed = m_panicSpeed; - } - else if (m_moveTimer.GetRemainingTime() > 0.0f) - { - // normal movement - m_desiredSpeed = m_calmSpeed; - } - else if (m_goTimer.IsElapsed()) - { - // move every so often - m_goTimer.Start( RandomFloat( 10.0f, 60.0f ) ); - m_moveTimer.Start( RandomFloat( 2.0f, 10.0 ) ); - m_desiredSpeed = m_calmSpeed; - } - - // avoid obstacles - float danger = Avoid(); - - // flock towards visible fish - for( int i=0; i maxAngleChange) - { - m_angleChange = maxAngleChange; - } - else if (m_angleChange < -maxAngleChange) - { - m_angleChange = -maxAngleChange; - } - - m_angle += m_angleChange; - m_angleChange = 0.0f; - - m_forward.x = cos( m_angle * M_PI/180.0f ); - m_forward.y = sin( m_angle * M_PI/180.0f ); - m_forward.z = 0.0f; - - m_perp.x = -m_forward.y; - m_perp.y = m_forward.x; - m_perp.z = 0.0f; - - // - // Update speed - // - const float rate = 2.0f; - m_speed += rate * (m_desiredSpeed - m_speed) * deltaT; - - // decay desired speed if done moving - if (m_moveTimer.IsElapsed()) - { - const float decayRate = 1.0f; - m_desiredSpeed -= decayRate * deltaT; - if (m_desiredSpeed < 0.0f) - { - m_desiredSpeed = 0.0f; - } - } - - Vector vel = m_speed * m_forward; - - // don't allow fish to leave maximum range of pool - if (deltaPos.IsLengthGreaterThan( m_pool->GetMaxRange() - safetyMargin )) - { - Vector toCenter = -deltaPos; - - float radial = DotProduct( toCenter, vel ); - if (radial < 0.0f) - { - // heading out of range, zero the radial velocity component - toCenter.NormalizeInPlace(); - Vector perp( -toCenter.y, toCenter.x, 0.0f ); - - float side = DotProduct( perp, vel ); - - vel = side * perp; - } - } - - SetAbsVelocity( vel ); - - m_flSpeed = m_speed; -} - - -//------------------------------------------------------------------------------------------------------------- -/** - * Zero the visible vector - */ -void CFish::ResetVisible( void ) -{ - m_visible.RemoveAll(); -} - - -//------------------------------------------------------------------------------------------------------------- -/** - * Add this fish to our visible vector - */ -void CFish::AddVisible( CFish *fish ) -{ - m_visible.AddToTail( fish ); -} - - -//------------------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------------------- -/** - * A CFishPool manages a collection of CFish, and defines where the "pool" is in the world. - */ - -LINK_ENTITY_TO_CLASS( func_fish_pool, CFishPool ); - -BEGIN_DATADESC( CFishPool ) - - DEFINE_FIELD( m_fishCount, FIELD_INTEGER ), - DEFINE_FIELD( m_maxRange, FIELD_FLOAT ), - DEFINE_FIELD( m_swimDepth, FIELD_FLOAT ), - DEFINE_FIELD( m_waterLevel, FIELD_FLOAT ), - DEFINE_FIELD( m_isDormant, FIELD_BOOLEAN ), - DEFINE_UTLVECTOR( m_fishes, FIELD_EHANDLE ), - - DEFINE_THINKFUNC( Update ), - -END_DATADESC() - - -//------------------------------------------------------------------------------------------------------------- -CFishPool::CFishPool( void ) -{ - m_fishCount = 0; - m_maxRange = 255.0f; - m_swimDepth = 0.0f; - m_isDormant = false; - - m_visTimer.Start( 0.5f ); - - ListenForGameEvent( "player_shoot" ); - ListenForGameEvent( "player_footstep" ); - ListenForGameEvent( "weapon_fire" ); - ListenForGameEvent( "hegrenade_detonate" ); - ListenForGameEvent( "flashbang_detonate" ); - ListenForGameEvent( "smokegrenade_detonate" ); - ListenForGameEvent( "bomb_exploded" ); -} - -//------------------------------------------------------------------------------------------------------------- -/** - * Initialize the fish pool - */ -void CFishPool::Spawn() -{ - SetThink( &CFishPool::Update ); - SetNextThink( gpGlobals->curtime ); - - m_waterLevel = UTIL_WaterLevel( GetAbsOrigin(), GetAbsOrigin().z, GetAbsOrigin().z + 1000.0f ); - - trace_t result; - for( int i=0; iInitialize( this, i ); - - if (fish) - { - CHandle hFish; - hFish.Set( fish ); - m_fishes.AddToTail( hFish ); - } - } -} - - -//------------------------------------------------------------------------------------------------------------- -/** - * Parse KeyValue pairs - */ -bool CFishPool::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq( szKeyName, "fish_count" )) - { - m_fishCount = atoi(szValue); - return true; - } - else if (FStrEq( szKeyName, "max_range" )) - { - m_maxRange = atof(szValue); - if (m_maxRange <= 1.0f) - { - m_maxRange = 1.0f; - } - else if (m_maxRange > 255.0f) - { - // stay within 8 bits range - m_maxRange = 255.0f; - } - - return true; - } - else if (FStrEq( szKeyName, "model" )) - { - PrecacheModel( szValue ); - SetModelName( AllocPooledString( szValue ) ); - } - - return BaseClass::KeyValue( szKeyName, szValue ); -} - - -//------------------------------------------------------------------------------------------------------------- -/** - * Game event processing - */ -void CFishPool::FireGameEvent( IGameEvent *event ) -{ - CBasePlayer *player = UTIL_PlayerByUserId( event->GetInt( "userid" ) ); - - // the fish panic - const float loudRange = 500.0f; - const float quietRange = 75.0f; - - float range = (Q_strcmp( "player_footstep", event->GetName() )) ? loudRange : quietRange; - - for( int i=0; iGetAbsOrigin() - m_fishes[i]->GetAbsOrigin()).IsLengthGreaterThan( range )) - { - // event too far away to care - continue; - } - - m_fishes[i]->Panic(); - } -} - - -//------------------------------------------------------------------------------------------------------------- -/** - * Invoked each server tick - */ -void CFishPool::Update( void ) -{ - float deltaT = 0.1f; - SetNextThink( gpGlobals->curtime + deltaT ); - - /// @todo Go dormant when no players are around to see us - - if (fish_dormant.GetBool()) - { - if (!m_isDormant) - { - // stop all the fish - for( int i=0; iSetAbsVelocity( Vector( 0, 0, 0 ) ); - } - - m_isDormant = true; - } - - return; - } - else - { - m_isDormant = false; - } - - // update fish to fish visibility - if (m_visTimer.IsElapsed()) - { - m_visTimer.Reset(); - - int i, j; - trace_t result; - - // reset each fishes vis list - for( i=0; iResetVisible(); - } - - // build new vis lists - line of sight is symmetric - for( i=0; iIsAlive()) - continue; - - for( j=i+1; jIsAlive()) - continue; - - UTIL_TraceLine( m_fishes[i]->GetAbsOrigin(), m_fishes[j]->GetAbsOrigin(), MASK_PLAYERSOLID, m_fishes[i], COLLISION_GROUP_NONE, &result ); - if (result.fraction >= 1.0f) - { - // the fish can see each other - m_fishes[i]->AddVisible( m_fishes[j] ); - m_fishes[j]->AddVisible( m_fishes[i] ); - } - } - } - } - - // simulate the fishes behavior - for( int i=0; iUpdate( deltaT ); - } -} - diff --git a/game/server/fish.h b/game/server/fish.h deleted file mode 100644 index 98be0689c..000000000 --- a/game/server/fish.h +++ /dev/null @@ -1,140 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -// fish.h -// Simple fish behavior -// Author: Michael S. Booth, April 2005 - -#ifndef _FISH_H_ -#define _FISH_H_ - -#include "baseanimating.h" -#include "GameEventListener.h" - -class CFishPool; - -//---------------------------------------------------------------------------------------------- -/** - * Simple ambient fish - */ -class CFish : public CBaseAnimating -{ -public: - DECLARE_CLASS( CFish, CBaseAnimating ); - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - CFish( void ); - virtual ~CFish(); - - void Initialize( CFishPool *pool, unsigned int id ); - - virtual void Spawn( void ); - - virtual void Event_Killed( const CTakeDamageInfo &info ); - virtual void Touch( CBaseEntity *other ); ///< in contact with "other" - - void Update( float deltaT ); ///< invoked each server tick - - void FlockTo( CFish *other, float amount ); ///< influence my motion to flock with other nearby fish - float Avoid( void ); - void Panic( void ); ///< panic for awhile - - void ResetVisible( void ); ///< zero the visible vector - void AddVisible( CFish *fish ); ///< add this fish to our visible vector - -private: - friend void SendProxy_FishOriginX( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); - friend void SendProxy_FishOriginY( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); - - CHandle m_pool; ///< the pool we are in - unsigned int m_id; ///< our unique ID - - CNetworkVar( float, m_x ); ///< have to send position coordinates separately since Z is unused - CNetworkVar( float, m_y ); ///< have to send position coordinates separately since Z is unused - CNetworkVar( float, m_z ); ///< only sent once since fish always swim at the same depth - - CNetworkVar( float, m_angle ); ///< only yaw changes - float m_angleChange; - Vector m_forward; - Vector m_perp; - - CNetworkVar( Vector, m_poolOrigin ); ///< used to efficiently network our relative position - CNetworkVar( float, m_waterLevel ); - - float m_speed; - float m_desiredSpeed; - - float m_calmSpeed; ///< speed the fish moves when calm - float m_panicSpeed; ///< speed the fish moves when panicked - - float m_avoidRange; ///< range to avoid obstacles - - CountdownTimer m_turnTimer; ///< every so often our turn preference changes - bool m_turnClockwise; ///< if true this fish prefers to turn clockwise, else CCW - - CountdownTimer m_goTimer; ///< start the fish moving when timer elapses - CountdownTimer m_moveTimer; ///< dont decay speed while we are moving - CountdownTimer m_panicTimer; ///< if active, fish is panicked - CountdownTimer m_disperseTimer; ///< initial non-flocking time - - CUtlVector< CFish * > m_visible; ///< vector of fish that we can see -}; - - -//---------------------------------------------------------------------------------------------- -/** - * This class defines a volume of water where a number of CFish swim - */ -class CFishPool : public CBaseEntity, public CGameEventListener -{ -public: - DECLARE_CLASS( CFishPool, CBaseEntity ); - DECLARE_DATADESC(); - - CFishPool( void ); - - virtual void Spawn(); - - virtual bool KeyValue( const char *szKeyName, const char *szValue ); - - virtual void FireGameEvent( IGameEvent *event ); - - void Update( void ); ///< invoked each server tick - - float GetWaterLevel( void ) const; ///< return Z coordinate of water in world coords - float GetMaxRange( void ) const; ///< return how far a fish is allowed to wander - -private: - int m_fishCount; ///< number of fish in the pool - float m_maxRange; ///< how far a fish is allowed to wander - float m_swimDepth; ///< the depth the fish swim below the water surface - - float m_waterLevel; ///< Z of water surface - - bool m_isDormant; - - CUtlVector< CHandle > m_fishes; ///< vector of all fish in this pool - - CountdownTimer m_visTimer; ///< for throttling line of sight checks between all fish -}; - - -inline float CFishPool::GetMaxRange( void ) const -{ - return m_maxRange; -} - - -inline float CFishPool::GetWaterLevel( void ) const -{ - return m_waterLevel; -} - - -#endif // _FISH_H_ - diff --git a/game/server/fogcontroller.cpp b/game/server/fogcontroller.cpp deleted file mode 100644 index 8b8a32b5f..000000000 --- a/game/server/fogcontroller.cpp +++ /dev/null @@ -1,391 +0,0 @@ -//========= Copyright 1996-2007, Valve Corporation, All rights reserved. ==== -// -// An entity that allows level designer control over the fog parameters. -// -//============================================================================= - -#include "cbase.h" -#include "fogcontroller.h" -#include "entityinput.h" -#include "entityoutput.h" -#include "eventqueue.h" -#include "player.h" -#include "world.h" -#include "ndebugoverlay.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -CFogSystem s_FogSystem( "FogSystem" ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CFogSystem *FogSystem( void ) -{ - return &s_FogSystem; -} - -LINK_ENTITY_TO_CLASS( env_fog_controller, CFogController ); - -BEGIN_DATADESC( CFogController ) - - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetStartDist", InputSetStartDist ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetEndDist", InputSetEndDist ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetMaxDensity", InputSetMaxDensity ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - DEFINE_INPUTFUNC( FIELD_COLOR32, "SetColor", InputSetColor ), - DEFINE_INPUTFUNC( FIELD_COLOR32, "SetColorSecondary", InputSetColorSecondary ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetFarZ", InputSetFarZ ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetAngles", InputSetAngles ), - - DEFINE_INPUTFUNC( FIELD_COLOR32, "SetColorLerpTo", InputSetColorLerpTo ), - DEFINE_INPUTFUNC( FIELD_COLOR32, "SetColorSecondaryLerpTo", InputSetColorSecondaryLerpTo ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetStartDistLerpTo", InputSetStartDistLerpTo ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetEndDistLerpTo", InputSetEndDistLerpTo ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartFogTransition", InputStartFogTransition ), - - // Quiet classcheck - //DEFINE_EMBEDDED( m_fog ), - - DEFINE_KEYFIELD( m_bUseAngles, FIELD_BOOLEAN, "use_angles" ), - DEFINE_KEYFIELD( m_fog.colorPrimary, FIELD_COLOR32, "fogcolor" ), - DEFINE_KEYFIELD( m_fog.colorSecondary, FIELD_COLOR32, "fogcolor2" ), - DEFINE_KEYFIELD( m_fog.dirPrimary, FIELD_VECTOR, "fogdir" ), - DEFINE_KEYFIELD( m_fog.enable, FIELD_BOOLEAN, "fogenable" ), - DEFINE_KEYFIELD( m_fog.blend, FIELD_BOOLEAN, "fogblend" ), - DEFINE_KEYFIELD( m_fog.start, FIELD_FLOAT, "fogstart" ), - DEFINE_KEYFIELD( m_fog.end, FIELD_FLOAT, "fogend" ), - DEFINE_KEYFIELD( m_fog.maxdensity, FIELD_FLOAT, "fogmaxdensity" ), - DEFINE_KEYFIELD( m_fog.farz, FIELD_FLOAT, "farz" ), - DEFINE_KEYFIELD( m_fog.duration, FIELD_FLOAT, "foglerptime" ), - - DEFINE_THINKFUNC( SetLerpValues ), - - DEFINE_FIELD( m_iChangedVariables, FIELD_INTEGER ), - - DEFINE_FIELD( m_fog.lerptime, FIELD_TIME ), - DEFINE_FIELD( m_fog.colorPrimaryLerpTo, FIELD_COLOR32 ), - DEFINE_FIELD( m_fog.colorSecondaryLerpTo, FIELD_COLOR32 ), - DEFINE_FIELD( m_fog.startLerpTo, FIELD_FLOAT ), - DEFINE_FIELD( m_fog.endLerpTo, FIELD_FLOAT ), - -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST_NOBASE( CFogController, DT_FogController ) -// fog data - SendPropInt( SENDINFO_STRUCTELEM( m_fog.enable ), 1, SPROP_UNSIGNED ), - SendPropInt( SENDINFO_STRUCTELEM( m_fog.blend ), 1, SPROP_UNSIGNED ), - SendPropVector( SENDINFO_STRUCTELEM(m_fog.dirPrimary), -1, SPROP_COORD), - SendPropInt( SENDINFO_STRUCTELEM( m_fog.colorPrimary ), 32, SPROP_UNSIGNED ), - SendPropInt( SENDINFO_STRUCTELEM( m_fog.colorSecondary ), 32, SPROP_UNSIGNED ), - SendPropFloat( SENDINFO_STRUCTELEM( m_fog.start ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO_STRUCTELEM( m_fog.end ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO_STRUCTELEM( m_fog.maxdensity ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO_STRUCTELEM( m_fog.farz ), 0, SPROP_NOSCALE ), - - SendPropInt( SENDINFO_STRUCTELEM( m_fog.colorPrimaryLerpTo ), 32, SPROP_UNSIGNED ), - SendPropInt( SENDINFO_STRUCTELEM( m_fog.colorSecondaryLerpTo ), 32, SPROP_UNSIGNED ), - SendPropFloat( SENDINFO_STRUCTELEM( m_fog.startLerpTo ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO_STRUCTELEM( m_fog.endLerpTo ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO_STRUCTELEM( m_fog.lerptime ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO_STRUCTELEM( m_fog.duration ), 0, SPROP_NOSCALE ), -END_SEND_TABLE() - -CFogController::CFogController() -{ - // Make sure that old maps without fog fields don't get wacked out fog values. - m_fog.enable = false; - m_fog.maxdensity = 1.0f; -} - - -CFogController::~CFogController() -{ -} - -void CFogController::Spawn( void ) -{ - BaseClass::Spawn(); - - m_fog.colorPrimaryLerpTo = m_fog.colorPrimary; - m_fog.colorSecondaryLerpTo = m_fog.colorSecondary; -} - -//----------------------------------------------------------------------------- -// Activate! -//----------------------------------------------------------------------------- -void CFogController::Activate( ) -{ - BaseClass::Activate(); - - if ( m_bUseAngles ) - { - AngleVectors( GetAbsAngles(), &m_fog.dirPrimary.GetForModify() ); - m_fog.dirPrimary.GetForModify() *= -1.0f; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CFogController::UpdateTransmitState() -{ - return SetTransmitState( FL_EDICT_ALWAYS ); -} - -//------------------------------------------------------------------------------ -// Purpose: Input handler for setting the fog start distance. -//------------------------------------------------------------------------------ -void CFogController::InputSetStartDist(inputdata_t &inputdata) -{ - // Get the world entity. - m_fog.start = inputdata.value.Float(); -} - -//------------------------------------------------------------------------------ -// Purpose: Input handler for setting the fog end distance. -//------------------------------------------------------------------------------ -void CFogController::InputSetEndDist(inputdata_t &inputdata) -{ - // Get the world entity. - m_fog.end = inputdata.value.Float(); -} - -//------------------------------------------------------------------------------ -// Input handler for setting the maximum density of the fog. This lets us bring -// the start distance in without the scene fogging too much. -//------------------------------------------------------------------------------ -void CFogController::InputSetMaxDensity( inputdata_t &inputdata ) -{ - m_fog.maxdensity = inputdata.value.Float(); -} - -//------------------------------------------------------------------------------ -// Purpose: Input handler for turning on the fog. -//------------------------------------------------------------------------------ -void CFogController::InputTurnOn(inputdata_t &inputdata) -{ - // Get the world entity. - m_fog.enable = true; -} - -//------------------------------------------------------------------------------ -// Purpose: Input handler for turning off the fog. -//------------------------------------------------------------------------------ -void CFogController::InputTurnOff(inputdata_t &inputdata) -{ - // Get the world entity. - m_fog.enable = false; -} - -//------------------------------------------------------------------------------ -// Purpose: Input handler for setting the primary fog color. -//------------------------------------------------------------------------------ -void CFogController::InputSetColor(inputdata_t &inputdata) -{ - // Get the world entity. - m_fog.colorPrimary = inputdata.value.Color32(); -} - - -//------------------------------------------------------------------------------ -// Purpose: Input handler for setting the secondary fog color. -//------------------------------------------------------------------------------ -void CFogController::InputSetColorSecondary(inputdata_t &inputdata) -{ - // Get the world entity. - m_fog.colorSecondary = inputdata.value.Color32(); -} - -void CFogController::InputSetFarZ(inputdata_t &inputdata) -{ - m_fog.farz = inputdata.value.Int(); -} - - -//------------------------------------------------------------------------------ -// Purpose: Sets the angles to use for the secondary fog direction. -//------------------------------------------------------------------------------ -void CFogController::InputSetAngles( inputdata_t &inputdata ) -{ - const char *pAngles = inputdata.value.String(); - - QAngle angles; - UTIL_StringToVector( angles.Base(), pAngles ); - - Vector vTemp; - AngleVectors( angles, &vTemp ); - SetAbsAngles( angles ); - - AngleVectors( GetAbsAngles(), &m_fog.dirPrimary.GetForModify() ); - m_fog.dirPrimary.GetForModify() *= -1.0f; -} - - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CFogController::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - - Q_snprintf(tempstr,sizeof(tempstr),"State: %s",(m_fog.enable)?"On":"Off"); - EntityText(text_offset,tempstr,0); - text_offset++; - - Q_snprintf(tempstr,sizeof(tempstr),"Start: %3.0f",m_fog.start); - EntityText(text_offset,tempstr,0); - text_offset++; - - Q_snprintf(tempstr,sizeof(tempstr),"End : %3.0f",m_fog.end); - EntityText(text_offset,tempstr,0); - text_offset++; - - color32 color = m_fog.colorPrimary; - Q_snprintf(tempstr,sizeof(tempstr),"1) Red : %i",color.r); - EntityText(text_offset,tempstr,0); - text_offset++; - - Q_snprintf(tempstr,sizeof(tempstr),"1) Green: %i",color.g); - EntityText(text_offset,tempstr,0); - text_offset++; - - Q_snprintf(tempstr,sizeof(tempstr),"1) Blue : %i",color.b); - EntityText(text_offset,tempstr,0); - text_offset++; - - color = m_fog.colorSecondary; - Q_snprintf(tempstr,sizeof(tempstr),"2) Red : %i",color.r); - EntityText(text_offset,tempstr,0); - text_offset++; - - Q_snprintf(tempstr,sizeof(tempstr),"2) Green: %i",color.g); - EntityText(text_offset,tempstr,0); - text_offset++; - - Q_snprintf(tempstr,sizeof(tempstr),"2) Blue : %i",color.b); - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} - -#define FOG_CONTROLLER_COLORPRIMARY_LERP 1 -#define FOG_CONTROLLER_COLORSECONDARY_LERP 2 -#define FOG_CONTROLLER_START_LERP 4 -#define FOG_CONTROLLER_END_LERP 8 - -void CFogController::InputSetColorLerpTo(inputdata_t &data) -{ - m_iChangedVariables |= FOG_CONTROLLER_COLORPRIMARY_LERP; - m_fog.colorPrimaryLerpTo = data.value.Color32(); -} - -void CFogController::InputSetColorSecondaryLerpTo(inputdata_t &data) -{ - m_iChangedVariables |= FOG_CONTROLLER_COLORSECONDARY_LERP; - m_fog.colorSecondaryLerpTo = data.value.Color32(); -} - -void CFogController::InputSetStartDistLerpTo(inputdata_t &data) -{ - m_iChangedVariables |= FOG_CONTROLLER_START_LERP; - m_fog.startLerpTo = data.value.Float(); -} - -void CFogController::InputSetEndDistLerpTo(inputdata_t &data) -{ - m_iChangedVariables |= FOG_CONTROLLER_END_LERP; - m_fog.endLerpTo = data.value.Float(); -} - -void CFogController::InputStartFogTransition(inputdata_t &data) -{ - SetThink( &CFogController::SetLerpValues ); - - m_fog.lerptime = gpGlobals->curtime + m_fog.duration + 0.1; - SetNextThink( gpGlobals->curtime + m_fog.duration ); -} - -void CFogController::SetLerpValues( void ) -{ - if ( m_iChangedVariables & FOG_CONTROLLER_COLORPRIMARY_LERP ) - { - m_fog.colorPrimary = m_fog.colorPrimaryLerpTo; - } - - if ( m_iChangedVariables & FOG_CONTROLLER_COLORSECONDARY_LERP ) - { - m_fog.colorSecondary = m_fog.colorSecondaryLerpTo; - } - - if ( m_iChangedVariables & FOG_CONTROLLER_START_LERP ) - { - m_fog.start = m_fog.startLerpTo; - } - - if ( m_iChangedVariables & FOG_CONTROLLER_END_LERP ) - { - m_fog.end = m_fog.endLerpTo; - } - - m_iChangedVariables = 0; - m_fog.lerptime = gpGlobals->curtime; -} - - -//----------------------------------------------------------------------------- -// Purpose: Clear out the fog controller. -//----------------------------------------------------------------------------- -void CFogSystem::LevelInitPreEntity( void ) -{ - m_pMasterController = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: On level load find the master fog controller. If no controller is -// set as Master, use the first fog controller found. -//----------------------------------------------------------------------------- -void CFogSystem::LevelInitPostEntity( void ) -{ - CFogController *pFogController = NULL; - do - { - pFogController = static_cast( gEntList.FindEntityByClassname( pFogController, "env_fog_controller" ) ); - if ( pFogController ) - { - if ( m_pMasterController == NULL ) - { - m_pMasterController = pFogController; - } - else - { - if ( pFogController->IsMaster() ) - { - m_pMasterController = pFogController; - } - } - } - } while ( pFogController ); - - // HACK: Singleplayer games don't get a call to CBasePlayer::Spawn on level transitions. - // CBasePlayer::Activate is called before this is called so that's too soon to set up the fog controller. - // We don't have a hook similar to Activate that happens after LevelInitPostEntity - // is called, or we could just do this in the player itself. - if ( gpGlobals->maxClients == 1 ) - { - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - if ( pPlayer && ( pPlayer->m_Local.m_PlayerFog.m_hCtrl.Get() == NULL ) ) - { - pPlayer->InitFogController(); - } - } -} - diff --git a/game/server/fogcontroller.h b/game/server/fogcontroller.h deleted file mode 100644 index 3fdb7099f..000000000 --- a/game/server/fogcontroller.h +++ /dev/null @@ -1,101 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef FOGCONTROLLER_H -#define FOGCONTROLLER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "playernet_vars.h" -#include "igamesystem.h" - -// Spawn Flags -#define SF_FOG_MASTER 0x0001 - -//============================================================================= -// -// Class Fog Controller: -// Compares a set of integer inputs to the one main input -// Outputs true if they are all equivalant, false otherwise -// -class CFogController : public CBaseEntity -{ -public: - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - DECLARE_CLASS( CFogController, CBaseEntity ); - - CFogController(); - ~CFogController(); - - // Parse data from a map file - virtual void Activate(); - virtual int UpdateTransmitState(); - - // Input handlers - void InputSetStartDist(inputdata_t &data); - void InputSetEndDist(inputdata_t &data); - void InputTurnOn(inputdata_t &data); - void InputTurnOff(inputdata_t &data); - void InputSetColor(inputdata_t &data); - void InputSetColorSecondary(inputdata_t &data); - void InputSetFarZ( inputdata_t &data ); - void InputSetAngles( inputdata_t &inputdata ); - void InputSetMaxDensity( inputdata_t &inputdata ); - - void InputSetColorLerpTo(inputdata_t &data); - void InputSetColorSecondaryLerpTo(inputdata_t &data); - void InputSetStartDistLerpTo(inputdata_t &data); - void InputSetEndDistLerpTo(inputdata_t &data); - - void InputStartFogTransition(inputdata_t &data); - - int DrawDebugTextOverlays(void); - - void SetLerpValues( void ); - void Spawn( void ); - - bool IsMaster( void ) { return HasSpawnFlags( SF_FOG_MASTER ); } - -public: - - CNetworkVarEmbedded( fogparams_t, m_fog ); - bool m_bUseAngles; - int m_iChangedVariables; -}; - -//============================================================================= -// -// Fog Controller System. -// -class CFogSystem : public CAutoGameSystem -{ -public: - - // Creation/Init. - CFogSystem( char const *name ) : CAutoGameSystem( name ) - { - m_pMasterController = NULL; - } - - ~CFogSystem() - { - m_pMasterController = NULL; - } - - virtual void LevelInitPreEntity(); - virtual void LevelInitPostEntity(); - CFogController *GetMasterFogController( void ) { return m_pMasterController; } - -private: - - CFogController *m_pMasterController; -}; - -CFogSystem *FogSystem( void ); - -#endif // FOGCONTROLLER_H diff --git a/game/server/forcefeedback.cpp b/game/server/forcefeedback.cpp deleted file mode 100644 index 50a40aec3..000000000 --- a/game/server/forcefeedback.cpp +++ /dev/null @@ -1,155 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#include "forcefeedback.h" -#include "igamesystem.h" - -class CForceFeedback : public IForceFeedback, public CAutoGameSystem -{ -public: - virtual bool Init(); - virtual void Shutdown(); - - // API - virtual void StopAllEffects( CBasePlayer *player ); - virtual void StopEffect( CBasePlayer *player, FORCEFEEDBACK_t effect ); - virtual void StartEffect( CBasePlayer *player, FORCEFEEDBACK_t effect, const FFBaseParams_t& params ); - - virtual void PauseAll( CBasePlayer *player ); - virtual void ResumeAll( CBasePlayer *player ); -}; - -static CForceFeedback g_ForceFeedbackSingleton; -IForceFeedback *forcefeedback = &g_ForceFeedbackSingleton; - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CForceFeedback::Init() -{ - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CForceFeedback::Shutdown() -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *player - -//----------------------------------------------------------------------------- -void CForceFeedback::StopAllEffects( CBasePlayer *player ) -{ - if ( !player ) - return; - - CSingleUserRecipientFilter user( player ); - - UserMessageBegin( user, "ForceFeedback" ); - - WRITE_BYTE( FFMSG_STOPALL ); // Reset effects - - MessageEnd(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *player - -// effect - -//----------------------------------------------------------------------------- -void CForceFeedback::StopEffect( CBasePlayer *player, FORCEFEEDBACK_t effect ) -{ - if ( !player ) - return; - - CSingleUserRecipientFilter user( player ); - - UserMessageBegin( user, "ForceFeedback" ); - - WRITE_BYTE( FFMSG_STOP ); // Reset effect - WRITE_BYTE( effect ); - - MessageEnd(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *player - -// effect - -// params - -//----------------------------------------------------------------------------- -void CForceFeedback::StartEffect( CBasePlayer *player, FORCEFEEDBACK_t effect, const FFBaseParams_t& params ) -{ - if ( !player ) - { - return; - } - - CSingleUserRecipientFilter user( player ); - - UserMessageBegin( user, "ForceFeedback" ); - - WRITE_BYTE( FFMSG_START ); // Reset effects - WRITE_BYTE( effect ); - - // encode direction as a byte - int dir = (int)( ( params.m_flDirection / 360.0f ) * 255.0f ); - WRITE_BYTE( dir ); - - // encode duration as a signed int - int duration = (int)(params.m_flDuration * 1000.0f); - WRITE_LONG( duration ); - - // encode gain as a byte - byte gain = (byte)clamp( params.m_flGain * 255.0f, 0.0f, 255.0f ); - - WRITE_BYTE( gain ); - WRITE_BYTE( params.m_nPriority ); - WRITE_BYTE( params.m_bSolo ? 1 : 0 ); - - MessageEnd(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *player - -//----------------------------------------------------------------------------- -void CForceFeedback::PauseAll( CBasePlayer *player ) -{ - if ( !player ) - return; - - CSingleUserRecipientFilter user( player ); - - UserMessageBegin( user, "ForceFeedback" ); - - WRITE_BYTE( FFMSG_PAUSE ); // Pause effects - - MessageEnd(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *player - -//----------------------------------------------------------------------------- -void CForceFeedback::ResumeAll( CBasePlayer *player ) -{ - if ( !player ) - return; - - CSingleUserRecipientFilter user( player ); - - UserMessageBegin( user, "ForceFeedback" ); - - WRITE_BYTE( FFMSG_RESUME ); // Resume effects - - MessageEnd(); -} diff --git a/game/server/fourwheelvehiclephysics.cpp b/game/server/fourwheelvehiclephysics.cpp deleted file mode 100644 index 6b324a961..000000000 --- a/game/server/fourwheelvehiclephysics.cpp +++ /dev/null @@ -1,1452 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: A moving vehicle that is used as a battering ram -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "fourwheelvehiclephysics.h" -#include "engine/IEngineSound.h" -#include "soundenvelope.h" -#include "in_buttons.h" -#include "player.h" -#include "IEffects.h" -#include "physics_saverestore.h" -#include "vehicle_base.h" -#include "isaverestore.h" -#include "movevars_shared.h" -#include "te_effect_dispatch.h" -#include "particle_parse.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define STICK_EXTENTS 400.0f - - -#define DUST_SPEED 5 // speed at which dust starts -#define REAR_AXLE 1 // indexes of axlex -#define FRONT_AXLE 0 -#define MAX_GUAGE_SPEED 100.0 // 100 mph is max speed shown on guage - -#define BRAKE_MAX_VALUE 1.0f -#define BRAKE_BACK_FORWARD_SCALAR 2.0f - -ConVar r_vehicleBrakeRate( "r_vehicleBrakeRate", "1.5", FCVAR_CHEAT ); - -ConVar xbox_throttlebias("xbox_throttlebias", "100", FCVAR_ARCHIVE ); -ConVar xbox_throttlespoof("xbox_throttlespoof", "200", FCVAR_ARCHIVE ); -ConVar xbox_autothrottle("xbox_autothrottle", "1", FCVAR_ARCHIVE ); -ConVar xbox_steering_deadzone( "xbox_steering_deadzone", "0.0" ); - -// remaps an angular variable to a 3 band function: -// 0 <= t < start : f(t) = 0 -// start <= t <= end : f(t) = end * spline(( t-start) / (end-start) ) // s curve between clamped and linear -// end < t : f(t) = t -float RemapAngleRange( float startInterval, float endInterval, float value ) -{ - // Fixup the roll - value = AngleNormalize( value ); - float absAngle = fabs(value); - - // beneath cutoff? - if ( absAngle < startInterval ) - { - value = 0; - } - // in spline range? - else if ( absAngle <= endInterval ) - { - float newAngle = SimpleSpline( (absAngle - startInterval) / (endInterval-startInterval) ) * endInterval; - // grab the sign from the initial value - if ( value < 0 ) - { - newAngle *= -1; - } - value = newAngle; - } - // else leave it alone, in linear range - - return value; -} - -enum vehicle_pose_params -{ - VEH_FL_WHEEL_HEIGHT=0, - VEH_FR_WHEEL_HEIGHT, - VEH_RL_WHEEL_HEIGHT, - VEH_RR_WHEEL_HEIGHT, - VEH_FL_WHEEL_SPIN, - VEH_FR_WHEEL_SPIN, - VEH_RL_WHEEL_SPIN, - VEH_RR_WHEEL_SPIN, - VEH_STEER, - VEH_ACTION, - VEH_SPEEDO, - -}; - - -BEGIN_DATADESC_NO_BASE( CFourWheelVehiclePhysics ) - -// These two are reset every time -// DEFINE_FIELD( m_pOuter, FIELD_EHANDLE ), -// m_pOuterServerVehicle; - - // Quiet down classcheck - // DEFINE_FIELD( m_controls, vehicle_controlparams_t ), - - // Controls - DEFINE_FIELD( m_controls.throttle, FIELD_FLOAT ), - DEFINE_FIELD( m_controls.steering, FIELD_FLOAT ), - DEFINE_FIELD( m_controls.brake, FIELD_FLOAT ), - DEFINE_FIELD( m_controls.boost, FIELD_FLOAT ), - DEFINE_FIELD( m_controls.handbrake, FIELD_BOOLEAN ), - DEFINE_FIELD( m_controls.handbrakeLeft, FIELD_BOOLEAN ), - DEFINE_FIELD( m_controls.handbrakeRight, FIELD_BOOLEAN ), - DEFINE_FIELD( m_controls.brakepedal, FIELD_BOOLEAN ), - DEFINE_FIELD( m_controls.bHasBrakePedal, FIELD_BOOLEAN ), - - // This has to be handled by the containing class owing to 'owner' issues -// DEFINE_PHYSPTR( m_pVehicle ), - - DEFINE_FIELD( m_nSpeed, FIELD_INTEGER ), - DEFINE_FIELD( m_nLastSpeed, FIELD_INTEGER ), - DEFINE_FIELD( m_nRPM, FIELD_INTEGER ), - DEFINE_FIELD( m_fLastBoost, FIELD_FLOAT ), - DEFINE_FIELD( m_nBoostTimeLeft, FIELD_INTEGER ), - DEFINE_FIELD( m_nHasBoost, FIELD_INTEGER ), - - DEFINE_FIELD( m_maxThrottle, FIELD_FLOAT ), - DEFINE_FIELD( m_flMaxRevThrottle, FIELD_FLOAT ), - DEFINE_FIELD( m_flMaxSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_actionSpeed, FIELD_FLOAT ), - - // This has to be handled by the containing class owing to 'owner' issues -// DEFINE_PHYSPTR_ARRAY( m_pWheels ), - - DEFINE_FIELD( m_wheelCount, FIELD_INTEGER ), - - DEFINE_ARRAY( m_wheelPosition, FIELD_VECTOR, 4 ), - DEFINE_ARRAY( m_wheelRotation, FIELD_VECTOR, 4 ), - DEFINE_ARRAY( m_wheelBaseHeight, FIELD_FLOAT, 4 ), - DEFINE_ARRAY( m_wheelTotalHeight, FIELD_FLOAT, 4 ), - DEFINE_ARRAY( m_poseParameters, FIELD_INTEGER, 12 ), - DEFINE_FIELD( m_actionValue, FIELD_FLOAT ), - DEFINE_KEYFIELD( m_actionScale, FIELD_FLOAT, "actionScale" ), - DEFINE_FIELD( m_debugRadius, FIELD_FLOAT ), - DEFINE_FIELD( m_throttleRate, FIELD_FLOAT ), - DEFINE_FIELD( m_throttleStartTime, FIELD_FLOAT ), - DEFINE_FIELD( m_throttleActiveTime, FIELD_FLOAT ), - DEFINE_FIELD( m_turboTimer, FIELD_FLOAT ), - - DEFINE_FIELD( m_flVehicleVolume, FIELD_FLOAT ), - DEFINE_FIELD( m_bIsOn, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bLastThrottle, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bLastBoost, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bLastSkid, FIELD_BOOLEAN ), -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CFourWheelVehiclePhysics::CFourWheelVehiclePhysics( CBaseAnimating *pOuter ) -{ - m_flVehicleVolume = 0.5; - m_pOuter = NULL; - m_pOuterServerVehicle = NULL; - m_flMaxSpeed = 30; -} - -//----------------------------------------------------------------------------- -// Destructor -//----------------------------------------------------------------------------- -CFourWheelVehiclePhysics::~CFourWheelVehiclePhysics () -{ - physenv->DestroyVehicleController( m_pVehicle ); -} - -//----------------------------------------------------------------------------- -// A couple wrapper methods to perform common operations -//----------------------------------------------------------------------------- -inline int CFourWheelVehiclePhysics::LookupPoseParameter( const char *szName ) -{ - return m_pOuter->LookupPoseParameter( szName ); -} - -inline float CFourWheelVehiclePhysics::GetPoseParameter( int iParameter ) -{ - return m_pOuter->GetPoseParameter( iParameter ); -} - -inline float CFourWheelVehiclePhysics::SetPoseParameter( int iParameter, float flValue ) -{ - Assert(IsFinite(flValue)); - return m_pOuter->SetPoseParameter( iParameter, flValue ); -} - -inline bool CFourWheelVehiclePhysics::GetAttachment( const char *szName, Vector &origin, QAngle &angles ) -{ - return m_pOuter->GetAttachment( szName, origin, angles ); -} - -//----------------------------------------------------------------------------- -// Methods related to spawn -//----------------------------------------------------------------------------- -void CFourWheelVehiclePhysics::InitializePoseParameters() -{ - m_poseParameters[VEH_FL_WHEEL_HEIGHT] = LookupPoseParameter( "vehicle_wheel_fl_height" ); - m_poseParameters[VEH_FR_WHEEL_HEIGHT] = LookupPoseParameter( "vehicle_wheel_fr_height" ); - m_poseParameters[VEH_RL_WHEEL_HEIGHT] = LookupPoseParameter( "vehicle_wheel_rl_height" ); - m_poseParameters[VEH_RR_WHEEL_HEIGHT] = LookupPoseParameter( "vehicle_wheel_rr_height" ); - m_poseParameters[VEH_FL_WHEEL_SPIN] = LookupPoseParameter( "vehicle_wheel_fl_spin" ); - m_poseParameters[VEH_FR_WHEEL_SPIN] = LookupPoseParameter( "vehicle_wheel_fr_spin" ); - m_poseParameters[VEH_RL_WHEEL_SPIN] = LookupPoseParameter( "vehicle_wheel_rl_spin" ); - m_poseParameters[VEH_RR_WHEEL_SPIN] = LookupPoseParameter( "vehicle_wheel_rr_spin" ); - m_poseParameters[VEH_STEER] = LookupPoseParameter( "vehicle_steer" ); - m_poseParameters[VEH_ACTION] = LookupPoseParameter( "vehicle_action" ); - m_poseParameters[VEH_SPEEDO] = LookupPoseParameter( "vehicle_guage" ); - - - // move the wheels to a neutral position - SetPoseParameter( m_poseParameters[VEH_SPEEDO], 0 ); - SetPoseParameter( m_poseParameters[VEH_STEER], 0 ); - SetPoseParameter( m_poseParameters[VEH_FL_WHEEL_HEIGHT], 0 ); - SetPoseParameter( m_poseParameters[VEH_FR_WHEEL_HEIGHT], 0 ); - SetPoseParameter( m_poseParameters[VEH_RL_WHEEL_HEIGHT], 0 ); - SetPoseParameter( m_poseParameters[VEH_RR_WHEEL_HEIGHT], 0 ); - m_pOuter->InvalidateBoneCache(); -} - -//----------------------------------------------------------------------------- -// Purpose: Parses the vehicle's script -//----------------------------------------------------------------------------- -bool CFourWheelVehiclePhysics::ParseVehicleScript( const char *pScriptName, solid_t &solid, vehicleparams_t &vehicle) -{ - // Physics keeps a cache of these to share among spawns of vehicles or flush for debugging - PhysFindOrAddVehicleScript( pScriptName, &vehicle, NULL ); - - m_debugRadius = vehicle.axles[0].wheels.radius; - CalcWheelData( vehicle ); - - PhysModelParseSolid( solid, m_pOuter, m_pOuter->GetModelIndex() ); - - // Allow the script to shift the center of mass - if ( vehicle.body.massCenterOverride != vec3_origin ) - { - solid.massCenterOverride = vehicle.body.massCenterOverride; - solid.params.massCenterOverride = &solid.massCenterOverride; - } - - // allow script to change the mass of the vehicle body - if ( vehicle.body.massOverride > 0 ) - { - solid.params.mass = vehicle.body.massOverride; - } - - return true; -} - -void CFourWheelVehiclePhysics::CalcWheelData( vehicleparams_t &vehicle ) -{ - const char *pWheelAttachments[4] = { "wheel_fl", "wheel_fr", "wheel_rl", "wheel_rr" }; - Vector left, right; - QAngle dummy; - SetPoseParameter( m_poseParameters[VEH_FL_WHEEL_HEIGHT], 0 ); - SetPoseParameter( m_poseParameters[VEH_FR_WHEEL_HEIGHT], 0 ); - SetPoseParameter( m_poseParameters[VEH_RL_WHEEL_HEIGHT], 0 ); - SetPoseParameter( m_poseParameters[VEH_RR_WHEEL_HEIGHT], 0 ); - m_pOuter->InvalidateBoneCache(); - if ( GetAttachment( "wheel_fl", left, dummy ) && GetAttachment( "wheel_fr", right, dummy ) ) - { - VectorITransform( left, m_pOuter->EntityToWorldTransform(), left ); - VectorITransform( right, m_pOuter->EntityToWorldTransform(), right ); - Vector center = (left + right) * 0.5; - vehicle.axles[0].offset = center; - vehicle.axles[0].wheelOffset = right - center; - // Cache the base height of the wheels in body space - m_wheelBaseHeight[0] = left.z; - m_wheelBaseHeight[1] = right.z; - } - - if ( GetAttachment( "wheel_rl", left, dummy ) && GetAttachment( "wheel_rr", right, dummy ) ) - { - VectorITransform( left, m_pOuter->EntityToWorldTransform(), left ); - VectorITransform( right, m_pOuter->EntityToWorldTransform(), right ); - Vector center = (left + right) * 0.5; - vehicle.axles[1].offset = center; - vehicle.axles[1].wheelOffset = right - center; - // Cache the base height of the wheels in body space - m_wheelBaseHeight[2] = left.z; - m_wheelBaseHeight[3] = right.z; - } - SetPoseParameter( m_poseParameters[VEH_FL_WHEEL_HEIGHT], 1 ); - SetPoseParameter( m_poseParameters[VEH_FR_WHEEL_HEIGHT], 1 ); - SetPoseParameter( m_poseParameters[VEH_RL_WHEEL_HEIGHT], 1 ); - SetPoseParameter( m_poseParameters[VEH_RR_WHEEL_HEIGHT], 1 ); - m_pOuter->InvalidateBoneCache(); - if ( GetAttachment( "wheel_fl", left, dummy ) && GetAttachment( "wheel_fr", right, dummy ) ) - { - VectorITransform( left, m_pOuter->EntityToWorldTransform(), left ); - VectorITransform( right, m_pOuter->EntityToWorldTransform(), right ); - // Cache the height range of the wheels in body space - m_wheelTotalHeight[0] = m_wheelBaseHeight[0] - left.z; - m_wheelTotalHeight[1] = m_wheelBaseHeight[1] - right.z; - vehicle.axles[0].wheels.springAdditionalLength = m_wheelTotalHeight[0]; - } - - if ( GetAttachment( "wheel_rl", left, dummy ) && GetAttachment( "wheel_rr", right, dummy ) ) - { - VectorITransform( left, m_pOuter->EntityToWorldTransform(), left ); - VectorITransform( right, m_pOuter->EntityToWorldTransform(), right ); - // Cache the height range of the wheels in body space - m_wheelTotalHeight[2] = m_wheelBaseHeight[0] - left.z; - m_wheelTotalHeight[3] = m_wheelBaseHeight[1] - right.z; - vehicle.axles[1].wheels.springAdditionalLength = m_wheelTotalHeight[2]; - } - for ( int i = 0; i < 4; i++ ) - { - if ( m_wheelTotalHeight[i] == 0.0f ) - { - DevWarning("Vehicle %s has invalid wheel attachment for %s - no movement\n", STRING(m_pOuter->GetModelName()), pWheelAttachments[i]); - m_wheelTotalHeight[i] = 1.0f; - } - } - - SetPoseParameter( m_poseParameters[VEH_FL_WHEEL_HEIGHT], 0 ); - SetPoseParameter( m_poseParameters[VEH_FR_WHEEL_HEIGHT], 0 ); - SetPoseParameter( m_poseParameters[VEH_RL_WHEEL_HEIGHT], 0 ); - SetPoseParameter( m_poseParameters[VEH_RR_WHEEL_HEIGHT], 0 ); - m_pOuter->InvalidateBoneCache(); - - // Get raytrace offsets if they exist. - if ( GetAttachment( "raytrace_fl", left, dummy ) && GetAttachment( "raytrace_fr", right, dummy ) ) - { - VectorITransform( left, m_pOuter->EntityToWorldTransform(), left ); - VectorITransform( right, m_pOuter->EntityToWorldTransform(), right ); - Vector center = ( left + right ) * 0.5; - vehicle.axles[0].raytraceCenterOffset = center; - vehicle.axles[0].raytraceOffset = right - center; - } - - if ( GetAttachment( "raytrace_rl", left, dummy ) && GetAttachment( "raytrace_rr", right, dummy ) ) - { - VectorITransform( left, m_pOuter->EntityToWorldTransform(), left ); - VectorITransform( right, m_pOuter->EntityToWorldTransform(), right ); - Vector center = ( left + right ) * 0.5; - vehicle.axles[1].raytraceCenterOffset = center; - vehicle.axles[1].raytraceOffset = right - center; - } -} - - -//----------------------------------------------------------------------------- -// Spawns the vehicle -//----------------------------------------------------------------------------- -void CFourWheelVehiclePhysics::Spawn( ) -{ - Assert( m_pOuter ); - - m_actionValue = 0; - m_actionSpeed = 0; - - m_bIsOn = false; - m_controls.handbrake = false; - m_controls.handbrakeLeft = false; - m_controls.handbrakeRight = false; - m_controls.bHasBrakePedal = true; - m_controls.bAnalogSteering = false; - - SetMaxThrottle( 1.0 ); - SetMaxReverseThrottle( -1.0f ); - - InitializePoseParameters(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Initializes the vehicle physics -// Called by our outer vehicle in it's Spawn() -//----------------------------------------------------------------------------- -bool CFourWheelVehiclePhysics::Initialize( const char *pVehicleScript, unsigned int nVehicleType ) -{ - // Ok, turn on the simulation now - // FIXME: Disabling collisions here is necessary because we seem to be - // getting a one-frame collision between the old + new collision models - if ( m_pOuter->VPhysicsGetObject() ) - { - m_pOuter->VPhysicsGetObject()->EnableCollisions(false); - } - m_pOuter->VPhysicsDestroyObject(); - - // Create the vphysics model + teleport it into position - solid_t solid; - vehicleparams_t vehicle; - if (!ParseVehicleScript( pVehicleScript, solid, vehicle )) - { - UTIL_Remove(m_pOuter); - return false; - } - - // NOTE: this needs to be greater than your max framerate (so zero is still instant) - m_throttleRate = 10000.0; - if ( vehicle.engine.throttleTime > 0 ) - { - m_throttleRate = 1.0 / vehicle.engine.throttleTime; - } - - m_flMaxSpeed = vehicle.engine.maxSpeed; - - IPhysicsObject *pBody = m_pOuter->VPhysicsInitNormal( SOLID_VPHYSICS, 0, false, &solid ); - PhysSetGameFlags( pBody, FVPHYSICS_NO_SELF_COLLISIONS | FVPHYSICS_MULTIOBJECT_ENTITY ); - m_pVehicle = physenv->CreateVehicleController( pBody, vehicle, nVehicleType, physgametrace ); - m_wheelCount = m_pVehicle->GetWheelCount(); - for ( int i = 0; i < m_wheelCount; i++ ) - { - m_pWheels[i] = m_pVehicle->GetWheel( i ); - } - return true; -} - - -//----------------------------------------------------------------------------- -// Various steering parameters -//----------------------------------------------------------------------------- -void CFourWheelVehiclePhysics::SetThrottle( float flThrottle ) -{ - m_controls.throttle = flThrottle; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFourWheelVehiclePhysics::SetMaxThrottle( float flMaxThrottle ) -{ - m_maxThrottle = flMaxThrottle; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFourWheelVehiclePhysics::SetMaxReverseThrottle( float flMaxThrottle ) -{ - m_flMaxRevThrottle = flMaxThrottle; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFourWheelVehiclePhysics::SetSteering( float flSteering, float flSteeringRate ) -{ - if ( !flSteeringRate ) - { - m_controls.steering = flSteering; - } - else - { - m_controls.steering = Approach( flSteering, m_controls.steering, flSteeringRate ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFourWheelVehiclePhysics::SetSteeringDegrees( float flDegrees ) -{ - vehicleparams_t &vehicleParams = m_pVehicle->GetVehicleParamsForChange(); - vehicleParams.steering.degreesSlow = flDegrees; - vehicleParams.steering.degreesFast = flDegrees; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFourWheelVehiclePhysics::SetAction( float flAction ) -{ - m_actionSpeed = flAction; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFourWheelVehiclePhysics::TurnOn( ) -{ - if ( IsEngineDisabled() ) - return; - - if ( !m_bIsOn ) - { - m_pOuterServerVehicle->SoundStart(); - m_bIsOn = true; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFourWheelVehiclePhysics::TurnOff( ) -{ - ResetControls(); - - if ( m_bIsOn ) - { - m_pOuterServerVehicle->SoundShutdown(); - m_bIsOn = false; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFourWheelVehiclePhysics::SetBoost( float flBoost ) -{ - if ( !IsEngineDisabled() ) - { - m_controls.boost = flBoost; - } -} - -//------------------------------------------------------ -// UpdateBooster - Calls UpdateBooster() in the vphysics -// code to allow the timer to be updated -// -// Returns: false if timer has expired (can use again and -// can stop think -// true if timer still running -//------------------------------------------------------ -bool CFourWheelVehiclePhysics::UpdateBooster( void ) -{ - float retval = m_pVehicle->UpdateBooster(gpGlobals->frametime ); - return ( retval > 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFourWheelVehiclePhysics::SetHasBrakePedal( bool bHasBrakePedal ) -{ - m_controls.bHasBrakePedal = bHasBrakePedal; -} - -//----------------------------------------------------------------------------- -// Teleport -//----------------------------------------------------------------------------- -void CFourWheelVehiclePhysics::Teleport( matrix3x4_t& relativeTransform ) -{ - // We basically just have to make sure the wheels are in the right place - // after teleportation occurs - - for ( int i = 0; i < m_wheelCount; i++ ) - { - matrix3x4_t matrix, newMatrix; - m_pWheels[i]->GetPositionMatrix( &matrix ); - ConcatTransforms( relativeTransform, matrix, newMatrix ); - m_pWheels[i]->SetPositionMatrix( newMatrix, true ); - } - - // Wake the vehicle back up after a teleport - if ( m_pOuterServerVehicle && m_pOuterServerVehicle->GetFourWheelVehicle() ) - { - IPhysicsObject *pObj = m_pOuterServerVehicle->GetFourWheelVehicle()->VPhysicsGetObject(); - if ( pObj ) - { - pObj->Wake(); - } - } -} - -#if 1 -// For the #if 0 debug code below! -#define HL2IVP_FACTOR METERS_PER_INCH -#define IVP2HL(x) (float)(x * (1.0f/HL2IVP_FACTOR)) -#define HL2IVP(x) (double)(x * HL2IVP_FACTOR) -#endif - -//----------------------------------------------------------------------------- -// Debugging methods -//----------------------------------------------------------------------------- -void CFourWheelVehiclePhysics::DrawDebugGeometryOverlays() -{ - for ( int iWheel = 0; iWheel < m_wheelCount; iWheel++ ) - { - IPhysicsObject *pWheel = m_pVehicle->GetWheel( iWheel ); - float radius = pWheel->GetSphereRadius(); - - Vector vecPos; - QAngle vecRot; - pWheel->GetPosition( &vecPos, &vecRot ); - // draw the physics object position/orientation - NDebugOverlay::Sphere( vecPos, vecRot, radius, 0, 255, 0, 0, false, 0 ); - // draw the animation position/orientation - NDebugOverlay::Sphere(m_wheelPosition[iWheel], m_wheelRotation[iWheel], radius, 255, 255, 0, 0, false, 0); - } - - // Render vehicle data. - IPhysicsObject *pBody = m_pOuter->VPhysicsGetObject(); - if ( pBody ) - { - const vehicleparams_t vehicleParams = m_pVehicle->GetVehicleParams(); - - // Draw a red cube as the "center" of the vehicle. - Vector vecBodyPosition; - QAngle angBodyDirection; - pBody->GetPosition( &vecBodyPosition, &angBodyDirection ); - NDebugOverlay::BoxAngles( vecBodyPosition, Vector( -5, -5, -5 ), Vector( 5, 5, 5 ), angBodyDirection, 255, 0, 0, 0 ,0 ); - - matrix3x4_t matrix; - AngleMatrix( angBodyDirection, vecBodyPosition, matrix ); - - // Draw green cubes at axle centers. - Vector vecAxlePositions[2], vecAxlePositionsHL[2]; - vecAxlePositions[0] = vehicleParams.axles[0].offset; - vecAxlePositions[1] = vehicleParams.axles[1].offset; - - VectorTransform( vecAxlePositions[0], matrix, vecAxlePositionsHL[0] ); - VectorTransform( vecAxlePositions[1], matrix, vecAxlePositionsHL[1] ); - - NDebugOverlay::BoxAngles( vecAxlePositionsHL[0], Vector( -3, -3, -3 ), Vector( 3, 3, 3 ), angBodyDirection, 0, 255, 0, 0 ,0 ); - NDebugOverlay::BoxAngles( vecAxlePositionsHL[1], Vector( -3, -3, -3 ), Vector( 3, 3, 3 ), angBodyDirection, 0, 255, 0, 0 ,0 ); - - // Draw wheel raycasts in yellow - vehicle_debugcarsystem_t debugCarSystem; - m_pVehicle->GetCarSystemDebugData( debugCarSystem ); - for ( int iWheel = 0; iWheel < 4; ++iWheel ) - { - Vector vecStart, vecEnd, vecImpact; - - // Hack for now. - float tmpY = IVP2HL( debugCarSystem.vecWheelRaycasts[iWheel][0].z ); - vecStart.z = -IVP2HL( debugCarSystem.vecWheelRaycasts[iWheel][0].y ); - vecStart.y = tmpY; - vecStart.x = IVP2HL( debugCarSystem.vecWheelRaycasts[iWheel][0].x ); - - tmpY = IVP2HL( debugCarSystem.vecWheelRaycasts[iWheel][1].z ); - vecEnd.z = -IVP2HL( debugCarSystem.vecWheelRaycasts[iWheel][1].y ); - vecEnd.y = tmpY; - vecEnd.x = IVP2HL( debugCarSystem.vecWheelRaycasts[iWheel][1].x ); - - tmpY = IVP2HL( debugCarSystem.vecWheelRaycastImpacts[iWheel].z ); - vecImpact.z = -IVP2HL( debugCarSystem.vecWheelRaycastImpacts[iWheel].y ); - vecImpact.y = tmpY; - vecImpact.x = IVP2HL( debugCarSystem.vecWheelRaycastImpacts[iWheel].x ); - - NDebugOverlay::BoxAngles( vecStart, Vector( -1 , -1, -1 ), Vector( 1, 1, 1 ), angBodyDirection, 0, 255, 0, 0, 0 ); - NDebugOverlay::Line( vecStart, vecEnd, 255, 255, 0, true, 0 ); - NDebugOverlay::BoxAngles( vecEnd, Vector( -1, -1, -1 ), Vector( 1, 1, 1 ), angBodyDirection, 255, 0, 0, 0, 0 ); - - NDebugOverlay::BoxAngles( vecImpact, Vector( -0.5f , -0.5f, -0.5f ), Vector( 0.5f, 0.5f, 0.5f ), angBodyDirection, 0, 0, 255, 0, 0 ); - DebugDrawContactPoints( m_pVehicle->GetWheel(iWheel) ); - } - } -} - -int CFourWheelVehiclePhysics::DrawDebugTextOverlays( int nOffset ) -{ - const vehicle_operatingparams_t ¶ms = m_pVehicle->GetOperatingParams(); - char tempstr[512]; - Q_snprintf( tempstr,sizeof(tempstr), "Speed %.1f T/S/B (%.0f/%.0f/%.1f)", params.speed, m_controls.throttle, m_controls.steering, m_controls.brake ); - m_pOuter->EntityText( nOffset, tempstr, 0 ); - nOffset++; - Msg( "%s", tempstr ); - - Q_snprintf( tempstr,sizeof(tempstr), "Gear: %d, RPM %4d", params.gear, (int)params.engineRPM ); - m_pOuter->EntityText( nOffset, tempstr, 0 ); - nOffset++; - Msg( " %s\n", tempstr ); - - return nOffset; -} - -//---------------------------------------------------- -// Place dust at vector passed in -//---------------------------------------------------- -void CFourWheelVehiclePhysics::PlaceWheelDust( int wheelIndex, bool ignoreSpeed ) -{ - // New vehicles handle this deeper into the base class - if ( hl2_episodic.GetBool() ) - return; - - // Old dust - Vector vecPos, vecVel; - m_pVehicle->GetWheelContactPoint( wheelIndex, &vecPos, NULL ); - - vecVel.Random( -1.0f, 1.0f ); - vecVel.z = random->RandomFloat( 0.3f, 1.0f ); - - VectorNormalize( vecVel ); - - // Higher speeds make larger dust clouds - float flSize; - if ( ignoreSpeed ) - { - flSize = 1.0f; - } - else - { - flSize = RemapValClamped( m_nSpeed, DUST_SPEED, m_flMaxSpeed, 0.0f, 1.0f ); - } - - if ( flSize ) - { - CEffectData data; - - data.m_vOrigin = vecPos; - data.m_vNormal = vecVel; - data.m_flScale = flSize; - - DispatchEffect( "WheelDust", data ); - } -} - -//----------------------------------------------------------------------------- -// Frame-based updating -//----------------------------------------------------------------------------- -bool CFourWheelVehiclePhysics::Think() -{ - if (!m_pVehicle) - return false; - - // Update sound + physics state - const vehicle_operatingparams_t &carState = m_pVehicle->GetOperatingParams(); - const vehicleparams_t &vehicleData = m_pVehicle->GetVehicleParams(); - - // Set save data. - float carSpeed = fabs( INS2MPH( carState.speed ) ); - m_nLastSpeed = m_nSpeed; - m_nSpeed = ( int )carSpeed; - m_nRPM = ( int )carState.engineRPM; - m_nHasBoost = (int)vehicleData.engine.boostDelay; // if we have any boost delay, vehicle has boost ability - - m_pVehicle->Update( gpGlobals->frametime, m_controls); - - // boost sounds - if( IsBoosting() && !m_bLastBoost ) - { - m_bLastBoost = true; - m_turboTimer = gpGlobals->curtime + 2.75f; // min duration for turbo sound - } - else if( !IsBoosting() && m_bLastBoost ) - { - if ( gpGlobals->curtime >= m_turboTimer ) - { - m_bLastBoost = false; - } - } - - m_fLastBoost = carState.boostDelay; - m_nBoostTimeLeft = carState.boostTimeLeft; - - // UNDONE: Use skid info from the physics system? - // Only check wheels if we're not being carried by a dropship - if ( m_pOuter->VPhysicsGetObject() && !m_pOuter->VPhysicsGetObject()->GetShadowController() ) - { - const float skidFactor = 0.15f; - const float minSpeed = DEFAULT_SKID_THRESHOLD / skidFactor; - // we have to slide at least 15% of our speed at higher speeds to make the skid sound (otherwise it can be too frequent) - float skidThreshold = m_bLastSkid ? DEFAULT_SKID_THRESHOLD : (carState.speed * 0.15f); - if ( skidThreshold < DEFAULT_SKID_THRESHOLD ) - { - // otherwise, ramp in the skid threshold to avoid the sound at really low speeds unless really skidding - skidThreshold = RemapValClamped( fabs(carState.speed), 0, minSpeed, DEFAULT_SKID_THRESHOLD*8, DEFAULT_SKID_THRESHOLD ); - } - // check for skidding, if we're skidding, need to play the sound - if ( carState.skidSpeed > skidThreshold && m_bIsOn ) - { - if ( !m_bLastSkid ) // only play sound once - { - m_bLastSkid = true; - CPASAttenuationFilter filter( m_pOuter ); - m_pOuterServerVehicle->PlaySound( VS_SKID_FRICTION_NORMAL ); - } - - // kick up dust from the wheels while skidding - for ( int i = 0; i < 4; i++ ) - { - PlaceWheelDust( i, true ); - } - } - else if ( m_bLastSkid == true ) - { - m_bLastSkid = false; - m_pOuterServerVehicle->StopSound( VS_SKID_FRICTION_NORMAL ); - } - - // toss dust up from the wheels of the vehicle if we're moving fast enough - if ( m_nSpeed >= DUST_SPEED && vehicleData.steering.dustCloud && m_bIsOn ) - { - for ( int i = 0; i < 4; i++ ) - { - PlaceWheelDust( i ); - } - } - } - - // Make the steering wheel match the input, with a little dampening. - #define STEER_DAMPING 0.8 - float flSteer = GetPoseParameter( m_poseParameters[VEH_STEER] ); - float flPhysicsSteer = carState.steeringAngle / vehicleData.steering.degreesSlow; - float value = (STEER_DAMPING * flSteer) + ((1 - STEER_DAMPING) * flPhysicsSteer); - if (!IsFinite(value)) - value = 0; - SetPoseParameter( m_poseParameters[VEH_STEER], value ); - - m_actionValue += m_actionSpeed * m_actionScale * gpGlobals->frametime; - SetPoseParameter( m_poseParameters[VEH_ACTION], m_actionValue ); - - // setup speedometer - if ( m_bIsOn == true ) - { - float displaySpeed = m_nSpeed / MAX_GUAGE_SPEED; - SetPoseParameter( m_poseParameters[VEH_SPEEDO], displaySpeed ); - } - - return m_bIsOn; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CFourWheelVehiclePhysics::VPhysicsUpdate( IPhysicsObject *pPhysics ) -{ - // must be a wheel - if ( pPhysics == m_pOuter->VPhysicsGetObject() ) - return true; - - // This is here so we can make the pose parameters of the wheels - // reflect their current physics state - for ( int i = 0; i < m_wheelCount; i++ ) - { - if ( pPhysics == m_pWheels[i] ) - { - Vector tmp; - pPhysics->GetPosition( &m_wheelPosition[i], &m_wheelRotation[i] ); - - // transform the wheel into body space - VectorITransform( m_wheelPosition[i], m_pOuter->EntityToWorldTransform(), tmp ); - SetPoseParameter( m_poseParameters[VEH_FL_WHEEL_HEIGHT + i], (m_wheelBaseHeight[i] - tmp.z) / m_wheelTotalHeight[i] ); - SetPoseParameter( m_poseParameters[VEH_FL_WHEEL_SPIN + i], -m_wheelRotation[i].z ); - return false; - } - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Shared code to compute the vehicle view position -//----------------------------------------------------------------------------- -void CFourWheelVehiclePhysics::GetVehicleViewPosition( const char *pViewAttachment, float flPitchFactor, Vector *pAbsOrigin, QAngle *pAbsAngles ) -{ - matrix3x4_t vehicleEyePosToWorld; - Vector vehicleEyeOrigin; - QAngle vehicleEyeAngles; - GetAttachment( pViewAttachment, vehicleEyeOrigin, vehicleEyeAngles ); - AngleMatrix( vehicleEyeAngles, vehicleEyePosToWorld ); - -#ifdef HL2_DLL - // View dampening. - if ( r_VehicleViewDampen.GetInt() ) - { - m_pOuterServerVehicle->GetFourWheelVehicle()->DampenEyePosition( vehicleEyeOrigin, vehicleEyeAngles ); - } -#endif - - // Compute the relative rotation between the unperterbed eye attachment + the eye angles - matrix3x4_t cameraToWorld; - AngleMatrix( *pAbsAngles, cameraToWorld ); - - matrix3x4_t worldToEyePos; - MatrixInvert( vehicleEyePosToWorld, worldToEyePos ); - - matrix3x4_t vehicleCameraToEyePos; - ConcatTransforms( worldToEyePos, cameraToWorld, vehicleCameraToEyePos ); - - // Now perterb the attachment point - vehicleEyeAngles.x = RemapAngleRange( PITCH_CURVE_ZERO * flPitchFactor, PITCH_CURVE_LINEAR, vehicleEyeAngles.x ); - vehicleEyeAngles.z = RemapAngleRange( ROLL_CURVE_ZERO * flPitchFactor, ROLL_CURVE_LINEAR, vehicleEyeAngles.z ); - AngleMatrix( vehicleEyeAngles, vehicleEyeOrigin, vehicleEyePosToWorld ); - - // Now treat the relative eye angles as being relative to this new, perterbed view position... - matrix3x4_t newCameraToWorld; - ConcatTransforms( vehicleEyePosToWorld, vehicleCameraToEyePos, newCameraToWorld ); - - // output new view abs angles - MatrixAngles( newCameraToWorld, *pAbsAngles ); - - // UNDONE: *pOrigin would already be correct in single player if the HandleView() on the server ran after vphysics - MatrixGetColumn( newCameraToWorld, 3, *pAbsOrigin ); -} - - -//----------------------------------------------------------------------------- -// Control initialization -//----------------------------------------------------------------------------- -void CFourWheelVehiclePhysics::ResetControls() -{ - m_controls.handbrake = true; - m_controls.handbrakeLeft = false; - m_controls.handbrakeRight = false; - m_controls.boost = 0; - m_controls.brake = 0.0f; - m_controls.throttle = 0; - m_controls.steering = 0; -} - -void CFourWheelVehiclePhysics::ReleaseHandbrake() -{ - m_controls.handbrake = false; -} - -void CFourWheelVehiclePhysics::SetHandbrake( bool bBrake ) -{ - m_controls.handbrake = bBrake; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFourWheelVehiclePhysics::EnableMotion( void ) -{ - for( int iWheel = 0; iWheel < m_wheelCount; ++iWheel ) - { - m_pWheels[iWheel]->EnableMotion( true ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFourWheelVehiclePhysics::DisableMotion( void ) -{ - Vector vecZero( 0.0f, 0.0f, 0.0f ); - AngularImpulse angNone( 0.0f, 0.0f, 0.0f ); - - for( int iWheel = 0; iWheel < m_wheelCount; ++iWheel ) - { - m_pWheels[iWheel]->SetVelocity( &vecZero, &angNone ); - m_pWheels[iWheel]->EnableMotion( false ); - } -} - -float CFourWheelVehiclePhysics::GetHLSpeed() const -{ - const vehicle_operatingparams_t &carState = m_pVehicle->GetOperatingParams(); - return carState.speed; -} - -float CFourWheelVehiclePhysics::GetSteering() const -{ - return m_controls.steering; -} - -float CFourWheelVehiclePhysics::GetSteeringDegrees() const -{ - const vehicleparams_t vehicleParams = m_pVehicle->GetVehicleParams(); - return vehicleParams.steering.degreesSlow; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFourWheelVehiclePhysics::SteeringRest( float carSpeed, const vehicleparams_t &vehicleData ) -{ - float flSteeringRate = RemapValClamped( carSpeed, vehicleData.steering.speedSlow, vehicleData.steering.speedFast, - vehicleData.steering.steeringRestRateSlow, vehicleData.steering.steeringRestRateFast ); - m_controls.steering = Approach(0, m_controls.steering, flSteeringRate * gpGlobals->frametime ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFourWheelVehiclePhysics::SteeringTurn( float carSpeed, const vehicleparams_t &vehicleData, bool bTurnLeft, bool bBrake, bool bThrottle ) -{ - float flTargetSteering = bTurnLeft ? -1.0f : 1.0f; - // steering speeds are stored in MPH - float flSteeringRestRate = RemapValClamped( carSpeed, vehicleData.steering.speedSlow, vehicleData.steering.speedFast, - vehicleData.steering.steeringRestRateSlow, vehicleData.steering.steeringRestRateFast ); - - float carSpeedIns = MPH2INS(carSpeed); - // engine speeds are stored in in/s - if ( carSpeedIns > vehicleData.engine.maxSpeed ) - { - flSteeringRestRate = RemapValClamped( carSpeedIns, vehicleData.engine.maxSpeed, vehicleData.engine.boostMaxSpeed, vehicleData.steering.steeringRestRateFast, vehicleData.steering.steeringRestRateFast*0.5f ); - } - - const vehicle_operatingparams_t &carState = m_pVehicle->GetOperatingParams(); - bool bIsBoosting = carState.isTorqueBoosting; - - // if you're recovering from a boost and still going faster than max, use the boost steering values - bool bIsBoostRecover = (carState.boostTimeLeft == 100 || carState.boostTimeLeft == 0) ? false : true; - float boostMinSpeed = vehicleData.engine.maxSpeed * vehicleData.engine.autobrakeSpeedGain; - if ( !bIsBoosting && bIsBoostRecover && carSpeedIns > boostMinSpeed ) - { - bIsBoosting = true; - } - - if ( bIsBoosting ) - { - flSteeringRestRate *= vehicleData.steering.boostSteeringRestRateFactor; - } - else if ( bThrottle ) - { - flSteeringRestRate *= vehicleData.steering.throttleSteeringRestRateFactor; - } - - float flSteeringRate = RemapValClamped( carSpeed, vehicleData.steering.speedSlow, vehicleData.steering.speedFast, - vehicleData.steering.steeringRateSlow, vehicleData.steering.steeringRateFast ); - - if ( fabs(flSteeringRate) < flSteeringRestRate ) - { - if ( Sign(flTargetSteering) != Sign(m_controls.steering) ) - { - flSteeringRate = flSteeringRestRate; - } - } - if ( bIsBoosting ) - { - flSteeringRate *= vehicleData.steering.boostSteeringRateFactor; - } - else if ( bBrake ) - { - flSteeringRate *= vehicleData.steering.brakeSteeringRateFactor; - } - flSteeringRate *= gpGlobals->frametime; - m_controls.steering = Approach( flTargetSteering, m_controls.steering, flSteeringRate ); - m_controls.bAnalogSteering = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFourWheelVehiclePhysics::SteeringTurnAnalog( float carSpeed, const vehicleparams_t &vehicleData, float sidemove ) -{ - - // OLD Code -#if 0 - float flSteeringRate = STEERING_BASE_RATE; - - float factor = clamp( fabs( sidemove ) / STICK_EXTENTS, 0.0f, 1.0f ); - - factor *= 30; - flSteeringRate *= log( factor ); - flSteeringRate *= gpGlobals->frametime; - - SetSteering( sidemove < 0.0f ? -1 : 1, flSteeringRate ); -#else - // This is tested with gamepads with analog sticks. It gives full analog control allowing the player to hold shallow turns. - float steering = ( sidemove / STICK_EXTENTS ); - - float flSign = ( steering > 0 ) ? 1.0f : -1.0f; - float flSteerAdj = RemapValClamped( fabs( steering ), xbox_steering_deadzone.GetFloat(), 1.0f, 0.0f, 1.0f ); - - float flSteeringRate = RemapValClamped( carSpeed, vehicleData.steering.speedSlow, vehicleData.steering.speedFast, - vehicleData.steering.steeringRateSlow, vehicleData.steering.steeringRateFast ); - flSteeringRate *= vehicleData.steering.throttleSteeringRestRateFactor; - - m_controls.bAnalogSteering = true; - SetSteering( flSign * flSteerAdj, flSteeringRate * gpGlobals->frametime ); -#endif -} - -//----------------------------------------------------------------------------- -// Methods related to actually driving the vehicle -//----------------------------------------------------------------------------- -void CFourWheelVehiclePhysics::UpdateDriverControls( CUserCmd *cmd, float flFrameTime ) -{ - const float SPEED_THROTTLE_AS_BRAKE = 2.0f; - int nButtons = cmd->buttons; - - // Get vehicle data. - const vehicle_operatingparams_t &carState = m_pVehicle->GetOperatingParams(); - const vehicleparams_t &vehicleData = m_pVehicle->GetVehicleParams(); - - // Get current speed in miles/hour. - float flCarSign = 0.0f; - if (carState.speed >= SPEED_THROTTLE_AS_BRAKE) - { - flCarSign = 1.0f; - } - else if ( carState.speed <= -SPEED_THROTTLE_AS_BRAKE ) - { - flCarSign = -1.0f; - } - float carSpeed = fabs(INS2MPH(carState.speed)); - - // If going forward and turning hard, keep the throttle applied. - if( xbox_autothrottle.GetBool() && cmd->forwardmove > 0.0f ) - { - if( carSpeed > GetMaxSpeed() * 0.75 ) - { - if( fabs(cmd->sidemove) > cmd->forwardmove ) - { - cmd->forwardmove = STICK_EXTENTS; - } - } - } - - //Msg("F: %4.1f \tS: %4.1f!\tSTEER: %3.1f\n", cmd->forwardmove, cmd->sidemove, carState.steeringAngle); - // If changing direction, use default "return to zero" speed to more quickly transition. - if ( ( nButtons & IN_MOVELEFT ) || ( nButtons & IN_MOVERIGHT ) ) - { - bool bTurnLeft = ( (nButtons & IN_MOVELEFT) != 0 ); - bool bBrake = ((nButtons & IN_BACK) != 0); - bool bThrottleDown = ( (nButtons & IN_FORWARD) != 0 ) && !bBrake; - SteeringTurn( carSpeed, vehicleData, bTurnLeft, bBrake, bThrottleDown ); - } - else if ( cmd->sidemove != 0.0f ) - { - SteeringTurnAnalog( carSpeed, vehicleData, cmd->sidemove ); - } - else - { - SteeringRest( carSpeed, vehicleData ); - } - - // Set vehicle control inputs. - m_controls.boost = 0; - m_controls.handbrake = false; - m_controls.handbrakeLeft = false; - m_controls.handbrakeRight = false; - m_controls.brakepedal = false; - bool bThrottle; - - //------------------------------------------------------------------------- - // Analog throttle biasing - This code gives the player a bit of control stick - // 'slop' in the opposite direction that they are driving. If a player is - // driving forward and makes a hard turn in which the stick actually goes - // below neutral (toward reverse), this code continues to propel the car - // forward unless the player makes a significant motion towards reverse. - // (The inverse is true when driving in reverse and the stick is moved slightly forward) - //------------------------------------------------------------------------- - CBaseEntity *pDriver = m_pOuterServerVehicle->GetDriver(); - CBasePlayer *pPlayerDriver; - float flBiasThreshold = xbox_throttlebias.GetFloat(); - - if( pDriver && pDriver->IsPlayer() ) - { - pPlayerDriver = dynamic_cast(pDriver); - - if( cmd->forwardmove == 0.0f && (fabs(cmd->sidemove) < 200.0f) ) - { - // If the stick goes neutral, clear out the bias. When the bias is neutral, it will begin biasing - // in whichever direction the user next presses the analog stick. - pPlayerDriver->SetVehicleAnalogControlBias( VEHICLE_ANALOG_BIAS_NONE ); - } - else if( cmd->forwardmove > 0.0f) - { - if( pPlayerDriver->GetVehicleAnalogControlBias() == VEHICLE_ANALOG_BIAS_REVERSE ) - { - // Player is pushing forward, but the controller is currently biased for reverse driving. - // Must pass a threshold to be accepted as forward input. Otherwise we just spoof a reduced reverse input - // to keep the car moving in the direction the player probably expects. - if( cmd->forwardmove < flBiasThreshold ) - { - cmd->forwardmove = -xbox_throttlespoof.GetFloat(); - } - else - { - // Passed the threshold. Allow the direction change to occur. - pPlayerDriver->SetVehicleAnalogControlBias( VEHICLE_ANALOG_BIAS_FORWARD ); - } - } - else if( pPlayerDriver->GetVehicleAnalogControlBias() == VEHICLE_ANALOG_BIAS_NONE ) - { - pPlayerDriver->SetVehicleAnalogControlBias( VEHICLE_ANALOG_BIAS_FORWARD ); - } - } - else if( cmd->forwardmove < 0.0f ) - { - if( pPlayerDriver->GetVehicleAnalogControlBias() == VEHICLE_ANALOG_BIAS_FORWARD ) - { - // Inverse of above logic - if( cmd->forwardmove > -flBiasThreshold ) - { - cmd->forwardmove = xbox_throttlespoof.GetFloat(); - } - else - { - pPlayerDriver->SetVehicleAnalogControlBias( VEHICLE_ANALOG_BIAS_REVERSE ); - } - } - else if( pPlayerDriver->GetVehicleAnalogControlBias() == VEHICLE_ANALOG_BIAS_NONE ) - { - pPlayerDriver->SetVehicleAnalogControlBias( VEHICLE_ANALOG_BIAS_REVERSE ); - } - } - } - - //========================= - // analog control - //========================= - if( cmd->forwardmove > 0.0f ) - { - float flAnalogThrottle = cmd->forwardmove / STICK_EXTENTS; - - flAnalogThrottle = clamp( flAnalogThrottle, 0.25f, 1.0f ); - - bThrottle = true; - if ( m_controls.throttle < 0 ) - { - m_controls.throttle = 0; - } - - float flMaxThrottle = MAX( 0.1, m_maxThrottle ); - if ( m_controls.steering != 0 ) - { - float flThrottleReduce = 0; - - // ramp this in, don't just start at the slow speed reduction (helps accelerate from a stop) - if ( carSpeed < vehicleData.steering.speedSlow ) - { - flThrottleReduce = RemapValClamped( carSpeed, 0, vehicleData.steering.speedSlow, - 0, vehicleData.steering.turnThrottleReduceSlow ); - } - else - { - flThrottleReduce = RemapValClamped( carSpeed, vehicleData.steering.speedSlow, vehicleData.steering.speedFast, - vehicleData.steering.turnThrottleReduceSlow, vehicleData.steering.turnThrottleReduceFast ); - } - - float limit = 1.0f - (flThrottleReduce * fabs(m_controls.steering)); - if ( limit < 0 ) - limit = 0; - flMaxThrottle = MIN( flMaxThrottle, limit ); - } - - m_controls.throttle = Approach( flMaxThrottle * flAnalogThrottle, m_controls.throttle, flFrameTime * m_throttleRate ); - - // Apply the brake. - if ( ( flCarSign < 0.0f ) && m_controls.bHasBrakePedal ) - { - m_controls.brake = Approach( BRAKE_MAX_VALUE, m_controls.brake, flFrameTime * r_vehicleBrakeRate.GetFloat() * BRAKE_BACK_FORWARD_SCALAR ); - m_controls.brakepedal = true; - m_controls.throttle = 0.0f; - bThrottle = false; - } - else - { - m_controls.brake = 0.0f; - } - } - else if( cmd->forwardmove < 0.0f ) - { - float flAnalogBrake = fabs(cmd->forwardmove / STICK_EXTENTS); - - flAnalogBrake = clamp( flAnalogBrake, 0.25f, 1.0f ); - - bThrottle = true; - if ( m_controls.throttle > 0 ) - { - m_controls.throttle = 0; - } - - float flMaxThrottle = MIN( -0.1, m_flMaxRevThrottle ); - m_controls.throttle = Approach( flMaxThrottle * flAnalogBrake, m_controls.throttle, flFrameTime * m_throttleRate ); - - // Apply the brake. - if ( ( flCarSign > 0.0f ) && m_controls.bHasBrakePedal ) - { - m_controls.brake = Approach( BRAKE_MAX_VALUE, m_controls.brake, flFrameTime * r_vehicleBrakeRate.GetFloat() ); - m_controls.brakepedal = true; - m_controls.throttle = 0.0f; - bThrottle = false; - } - else - { - m_controls.brake = 0.0f; - } - } - // digital control - else if ( nButtons & IN_FORWARD ) - { - bThrottle = true; - if ( m_controls.throttle < 0 ) - { - m_controls.throttle = 0; - } - - float flMaxThrottle = MAX( 0.1, m_maxThrottle ); - - if ( m_controls.steering != 0 ) - { - float flThrottleReduce = 0; - - // ramp this in, don't just start at the slow speed reduction (helps accelerate from a stop) - if ( carSpeed < vehicleData.steering.speedSlow ) - { - flThrottleReduce = RemapValClamped( carSpeed, 0, vehicleData.steering.speedSlow, - 0, vehicleData.steering.turnThrottleReduceSlow ); - } - else - { - flThrottleReduce = RemapValClamped( carSpeed, vehicleData.steering.speedSlow, vehicleData.steering.speedFast, - vehicleData.steering.turnThrottleReduceSlow, vehicleData.steering.turnThrottleReduceFast ); - } - - float limit = 1.0f - (flThrottleReduce * fabs(m_controls.steering)); - if ( limit < 0 ) - limit = 0; - flMaxThrottle = MIN( flMaxThrottle, limit ); - } - - m_controls.throttle = Approach( flMaxThrottle, m_controls.throttle, flFrameTime * m_throttleRate ); - - // Apply the brake. - if ( ( flCarSign < 0.0f ) && m_controls.bHasBrakePedal ) - { - m_controls.brake = Approach( BRAKE_MAX_VALUE, m_controls.brake, flFrameTime * r_vehicleBrakeRate.GetFloat() * BRAKE_BACK_FORWARD_SCALAR ); - m_controls.brakepedal = true; - m_controls.throttle = 0.0f; - bThrottle = false; - } - else - { - m_controls.brake = 0.0f; - } - } - else if ( nButtons & IN_BACK ) - { - bThrottle = true; - if ( m_controls.throttle > 0 ) - { - m_controls.throttle = 0; - } - - float flMaxThrottle = MIN( -0.1, m_flMaxRevThrottle ); - m_controls.throttle = Approach( flMaxThrottle, m_controls.throttle, flFrameTime * m_throttleRate ); - - // Apply the brake. - if ( ( flCarSign > 0.0f ) && m_controls.bHasBrakePedal ) - { - m_controls.brake = Approach( BRAKE_MAX_VALUE, m_controls.brake, flFrameTime * r_vehicleBrakeRate.GetFloat() ); - m_controls.brakepedal = true; - m_controls.throttle = 0.0f; - bThrottle = false; - } - else - { - m_controls.brake = 0.0f; - } - } - else - { - bThrottle = false; - m_controls.throttle = 0; - m_controls.brake = 0.0f; - } - - if ( ( nButtons & IN_SPEED ) && !IsEngineDisabled() && bThrottle ) - { - m_controls.boost = 1.0f; - } - - // Using has brakepedal for handbrake as well. - if ( ( nButtons & IN_JUMP ) && m_controls.bHasBrakePedal ) - { - m_controls.handbrake = true; - - if ( cmd->sidemove < -100 ) - { - m_controls.handbrakeLeft = true; - } - else if ( cmd->sidemove > 100 ) - { - m_controls.handbrakeRight = true; - } - - // Prevent playing of the engine revup when we're braking - bThrottle = false; - } - - if ( IsEngineDisabled() ) - { - m_controls.throttle = 0.0f; - m_controls.handbrake = true; - bThrottle = false; - } - - // throttle sounds - // If we dropped a bunch of speed, restart the throttle - if ( bThrottle && (m_nLastSpeed > m_nSpeed && (m_nLastSpeed - m_nSpeed > 10)) ) - { - m_bLastThrottle = false; - } - - // throttle down now but not before??? (or we're braking) - if ( !m_controls.handbrake && !m_controls.brakepedal && bThrottle && !m_bLastThrottle ) - { - m_throttleStartTime = gpGlobals->curtime; // need to track how long throttle is down - m_bLastThrottle = true; - } - // throttle up now but not before?? - else if ( !bThrottle && m_bLastThrottle && IsEngineDisabled() == false ) - { - m_throttleActiveTime = gpGlobals->curtime - m_throttleStartTime; - m_bLastThrottle = false; - } - - float flSpeedPercentage = clamp( m_nSpeed / m_flMaxSpeed, 0, 1 ); - vbs_sound_update_t params; - params.Defaults(); - params.bReverse = (m_controls.throttle < 0); - params.bThrottleDown = bThrottle; - params.bTurbo = IsBoosting(); - params.bVehicleInWater = m_pOuterServerVehicle->IsVehicleBodyInWater(); - params.flCurrentSpeedFraction = flSpeedPercentage; - params.flFrameTime = flFrameTime; - params.flWorldSpaceSpeed = carState.speed; - m_pOuterServerVehicle->SoundUpdate( params ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CFourWheelVehiclePhysics::IsBoosting( void ) -{ - const vehicleparams_t *pVehicleParams = &m_pVehicle->GetVehicleParams(); - const vehicle_operatingparams_t *pVehicleOperating = &m_pVehicle->GetOperatingParams(); - if ( pVehicleParams && pVehicleOperating ) - { - if ( ( pVehicleOperating->boostDelay - pVehicleParams->engine.boostDelay ) > 0.0f ) - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFourWheelVehiclePhysics::SetDisableEngine( bool bDisable ) -{ - // Set the engine state. - m_pVehicle->SetEngineDisabled( bDisable ); -} - -static int AddPhysToList( IPhysicsObject **pList, int listMax, int count, IPhysicsObject *pPhys ) -{ - if ( pPhys ) - { - if ( count < listMax ) - { - pList[count] = pPhys; - count++; - } - } - return count; -} - -int CFourWheelVehiclePhysics::VPhysicsGetObjectList( IPhysicsObject **pList, int listMax ) -{ - int count = 0; - // add the body - count = AddPhysToList( pList, listMax, count, m_pOuter->VPhysicsGetObject() ); - for ( int i = 0; i < 4; i++ ) - { - count = AddPhysToList( pList, listMax, count, m_pWheels[i] ); - } - return count; -} diff --git a/game/server/fourwheelvehiclephysics.h b/game/server/fourwheelvehiclephysics.h deleted file mode 100644 index 6bdca3f1a..000000000 --- a/game/server/fourwheelvehiclephysics.h +++ /dev/null @@ -1,218 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: A base class that deals with four-wheel vehicles -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef FOUR_WHEEL_VEHICLE_PHYSICS_H -#define FOUR_WHEEL_VEHICLE_PHYSICS_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "vphysics/vehicles.h" -#include "vcollide_parse.h" -#include "datamap.h" -#include "vehicle_sounds.h" - -// in/sec to miles/hour -#define INS2MPH_SCALE ( 3600 * (1/5280.0f) * (1/12.0f) ) -#define INS2MPH(x) ( (x) * INS2MPH_SCALE ) -#define MPH2INS(x) ( (x) * (1/INS2MPH_SCALE) ) - -class CBaseAnimating; -class CFourWheelServerVehicle; - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CFourWheelVehiclePhysics -{ -public: - DECLARE_DATADESC(); - - CFourWheelVehiclePhysics( CBaseAnimating *pOuter ); - ~CFourWheelVehiclePhysics (); - - // Call Precache + Spawn from the containing entity's Precache + Spawn methods - void Spawn(); - void SetOuter( CBaseAnimating *pOuter, CFourWheelServerVehicle *pServerVehicle ); - - // Initializes the vehicle physics so we can drive it - bool Initialize( const char *pScriptName, unsigned int nVehicleType ); - - void Teleport( matrix3x4_t& relativeTransform ); - bool VPhysicsUpdate( IPhysicsObject *pPhysics ); - bool Think(); - void PlaceWheelDust( int wheelIndex, bool ignoreSpeed = false ); - - void DrawDebugGeometryOverlays(); - int DrawDebugTextOverlays( int nOffset ); - - // Updates the controls based on user input - void UpdateDriverControls( CUserCmd *cmd, float flFrameTime ); - - // Various steering parameters - void SetThrottle( float flThrottle ); - void SetMaxThrottle( float flMaxThrottle ); - void SetMaxReverseThrottle( float flMaxThrottle ); - void SetSteering( float flSteering, float flSteeringRate ); - void SetSteeringDegrees( float flDegrees ); - void SetAction( float flAction ); - void TurnOn( ); - void TurnOff(); - void ReleaseHandbrake(); - void SetHandbrake( bool bBrake ); - bool IsOn() const { return m_bIsOn; } - void ResetControls(); - void SetBoost( float flBoost ); - bool UpdateBooster( void ); - void SetHasBrakePedal( bool bHasBrakePedal ); - - // Engine - void SetDisableEngine( bool bDisable ); - bool IsEngineDisabled( void ) { return m_pVehicle->IsEngineDisabled(); } - - // Enable/Disable Motion - void EnableMotion( void ); - void DisableMotion( void ); - - // Shared code to compute the vehicle view position - void GetVehicleViewPosition( const char *pViewAttachment, float flPitchFactor, Vector *pAbsPosition, QAngle *pAbsAngles ); - - IPhysicsObject *GetWheel( int iWheel ) { return m_pWheels[iWheel]; } - - int GetSpeed() const; - int GetMaxSpeed() const; - int GetRPM() const; - float GetThrottle() const; - bool HasBoost() const; - int BoostTimeLeft() const; - bool IsBoosting( void ); - float GetHLSpeed() const; - float GetSteering() const; - float GetSteeringDegrees() const; - IPhysicsVehicleController* GetVehicle(void) { return m_pVehicle; } - float GetWheelBaseHeight(int wheelIndex) { return m_wheelBaseHeight[wheelIndex]; } - float GetWheelTotalHeight(int wheelIndex) { return m_wheelTotalHeight[wheelIndex]; } - - IPhysicsVehicleController *GetVehicleController() { return m_pVehicle; } - const vehicleparams_t &GetVehicleParams( void ) { return m_pVehicle->GetVehicleParams(); } - const vehicle_controlparams_t &GetVehicleControls( void ) { return m_controls; } - const vehicle_operatingparams_t &GetVehicleOperatingParams( void ) { return m_pVehicle->GetOperatingParams(); } - - int VPhysicsGetObjectList( IPhysicsObject **pList, int listMax ); - -private: - // engine sounds - void CalcWheelData( vehicleparams_t &vehicle ); - - void SteeringRest( float carSpeed, const vehicleparams_t &vehicleData ); - void SteeringTurn( float carSpeed, const vehicleparams_t &vehicleData, bool bTurnLeft, bool bBrake, bool bThrottle ); - void SteeringTurnAnalog( float carSpeed, const vehicleparams_t &vehicleData, float sidemove ); - - // A couple wrapper methods to perform common operations - int LookupPoseParameter( const char *szName ); - float GetPoseParameter( int iParameter ); - float SetPoseParameter( int iParameter, float flValue ); - bool GetAttachment ( const char *szName, Vector &origin, QAngle &angles ); - - void InitializePoseParameters(); - bool ParseVehicleScript( const char *pScriptName, solid_t &solid, vehicleparams_t &vehicle ); - -private: - // This is the entity that contains this class - CHandle m_pOuter; - CFourWheelServerVehicle *m_pOuterServerVehicle; - - vehicle_controlparams_t m_controls; - IPhysicsVehicleController *m_pVehicle; - - // Vehicle state info - int m_nSpeed; - int m_nLastSpeed; - int m_nRPM; - float m_fLastBoost; - int m_nBoostTimeLeft; - int m_nHasBoost; - - float m_maxThrottle; - float m_flMaxRevThrottle; - float m_flMaxSpeed; - float m_actionSpeed; - IPhysicsObject *m_pWheels[4]; - - int m_wheelCount; - - Vector m_wheelPosition[4]; - QAngle m_wheelRotation[4]; - float m_wheelBaseHeight[4]; - float m_wheelTotalHeight[4]; - int m_poseParameters[12]; - float m_actionValue; - float m_actionScale; - float m_debugRadius; - float m_throttleRate; - float m_throttleStartTime; - float m_throttleActiveTime; - float m_turboTimer; - - float m_flVehicleVolume; // NPC driven vehicles used louder sounds - bool m_bIsOn; - bool m_bLastThrottle; - bool m_bLastBoost; - bool m_bLastSkid; -}; - - -//----------------------------------------------------------------------------- -// Physics state.. -//----------------------------------------------------------------------------- -inline int CFourWheelVehiclePhysics::GetSpeed() const -{ - return m_nSpeed; -} - -inline int CFourWheelVehiclePhysics::GetMaxSpeed() const -{ - return (int)INS2MPH(m_pVehicle->GetVehicleParams().engine.maxSpeed); -} - -inline int CFourWheelVehiclePhysics::GetRPM() const -{ - return m_nRPM; -} - -inline float CFourWheelVehiclePhysics::GetThrottle() const -{ - return m_controls.throttle; -} - -inline bool CFourWheelVehiclePhysics::HasBoost() const -{ - return m_nHasBoost != 0; -} - -inline int CFourWheelVehiclePhysics::BoostTimeLeft() const -{ - return m_nBoostTimeLeft; -} - -inline void CFourWheelVehiclePhysics::SetOuter( CBaseAnimating *pOuter, CFourWheelServerVehicle *pServerVehicle ) -{ - m_pOuter = pOuter; - m_pOuterServerVehicle = pServerVehicle; -} - -float RemapAngleRange( float startInterval, float endInterval, float value ); - -#define ROLL_CURVE_ZERO 5 // roll less than this is clamped to zero -#define ROLL_CURVE_LINEAR 45 // roll greater than this is copied out - -#define PITCH_CURVE_ZERO 10 // pitch less than this is clamped to zero -#define PITCH_CURVE_LINEAR 45 // pitch greater than this is copied out - -#endif // FOUR_WHEEL_VEHICLE_PHYSICS_H diff --git a/game/server/func_areaportal.cpp b/game/server/func_areaportal.cpp deleted file mode 100644 index 3bd653e8c..000000000 --- a/game/server/func_areaportal.cpp +++ /dev/null @@ -1,191 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: area portal entity: toggles visibility areas on/off -// -// NOTE: These are not really brush entities. They are brush entities from a -// designer/worldcraft perspective, but by the time they reach the game, the -// brush model is gone and this is, in effect, a point entity. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "func_areaportalbase.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -enum areaportal_state -{ - AREAPORTAL_CLOSED = 0, - AREAPORTAL_OPEN = 1, -}; - - -class CAreaPortal : public CFuncAreaPortalBase -{ -public: - DECLARE_CLASS( CAreaPortal, CFuncAreaPortalBase ); - - CAreaPortal(); - - virtual void Spawn( void ); - virtual void Precache( void ); - virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - virtual bool KeyValue( const char *szKeyName, const char *szValue ); - virtual int UpdateTransmitState(); - - // Input handlers - void InputOpen( inputdata_t &inputdata ); - void InputClose( inputdata_t &inputdata ); - void InputToggle( inputdata_t &inputdata ); - - virtual bool UpdateVisibility( const Vector &vOrigin, float fovDistanceAdjustFactor, bool &bIsOpenOnClient ); - - DECLARE_DATADESC(); - -private: - bool UpdateState( void ); - - int m_state; -}; - -LINK_ENTITY_TO_CLASS( func_areaportal, CAreaPortal ); - -BEGIN_DATADESC( CAreaPortal ) - - DEFINE_KEYFIELD( m_portalNumber, FIELD_INTEGER, "portalnumber" ), - DEFINE_FIELD( m_state, FIELD_INTEGER ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Open", InputOpen ), - DEFINE_INPUTFUNC( FIELD_VOID, "Close", InputClose ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - - // TODO: obsolete! remove - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputClose ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputOpen ), - -END_DATADESC() - - - -CAreaPortal::CAreaPortal() -{ - m_state = AREAPORTAL_OPEN; -} - - -void CAreaPortal::Spawn( void ) -{ - AddEffects( EF_NORECEIVESHADOW | EF_NOSHADOW ); - Precache(); -} - - -//----------------------------------------------------------------------------- -// Purpose: notify the engine of the state at startup/restore -//----------------------------------------------------------------------------- -void CAreaPortal::Precache( void ) -{ - UpdateState(); -} - - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CAreaPortal::InputClose( inputdata_t &inputdata ) -{ - m_state = AREAPORTAL_CLOSED; - UpdateState(); -} - - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CAreaPortal::InputOpen( inputdata_t &inputdata ) -{ - m_state = AREAPORTAL_OPEN; - UpdateState(); -} - - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CAreaPortal::InputToggle( inputdata_t &inputdata ) -{ - m_state = ((m_state == AREAPORTAL_OPEN) ? AREAPORTAL_CLOSED : AREAPORTAL_OPEN); - UpdateState(); -} - - -bool CAreaPortal::UpdateVisibility( const Vector &vOrigin, float fovDistanceAdjustFactor, bool &bIsOpenOnClient ) -{ - if ( m_state ) - { - // We're not closed, so give the base class a chance to close it. - return BaseClass::UpdateVisibility( vOrigin, fovDistanceAdjustFactor, bIsOpenOnClient ); - } - else - { - bIsOpenOnClient = false; - return false; - } -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CAreaPortal::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - if ( useType == USE_ON ) - { - m_state = AREAPORTAL_OPEN; - } - else if ( useType == USE_OFF ) - { - m_state = AREAPORTAL_CLOSED; - } - else - { - return; - } - - UpdateState(); -} - - -bool CAreaPortal::KeyValue( const char *szKeyName, const char *szValue ) -{ - if( FStrEq( szKeyName, "StartOpen" ) ) - { - m_state = (atoi(szValue) != 0) ? AREAPORTAL_OPEN : AREAPORTAL_CLOSED; - - return true; - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } -} - - -bool CAreaPortal::UpdateState() -{ - engine->SetAreaPortalState( m_portalNumber, m_state ); - return !!m_state; -} - - -int CAreaPortal::UpdateTransmitState() -{ - // Our brushes are kept around so don't transmit anything since we don't want to draw them. - return SetTransmitState( FL_EDICT_DONTSEND ); -} - diff --git a/game/server/func_areaportalbase.cpp b/game/server/func_areaportalbase.cpp deleted file mode 100644 index 4b8649b44..000000000 --- a/game/server/func_areaportalbase.cpp +++ /dev/null @@ -1,71 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#include "cbase.h" -#include "func_areaportalbase.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// A sphere around the player used for backface culling of areaportals. -#define VIEWER_PADDING 80 - - -CUtlLinkedList g_AreaPortals; - - - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CFuncAreaPortalBase ) - - DEFINE_FIELD( m_portalNumber, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_iPortalVersion, FIELD_INTEGER, "PortalVersion" ) -// DEFINE_FIELD( m_AreaPortalsElement, FIELD_SHORT ), - -END_DATADESC() - - - - -CFuncAreaPortalBase::CFuncAreaPortalBase() -{ - m_portalNumber = -1; - m_AreaPortalsElement = g_AreaPortals.AddToTail( this ); - m_iPortalVersion = 0; -} - - -CFuncAreaPortalBase::~CFuncAreaPortalBase() -{ - g_AreaPortals.Remove( m_AreaPortalsElement ); -} - - -bool CFuncAreaPortalBase::UpdateVisibility( const Vector &vOrigin, float fovDistanceAdjustFactor, bool &bIsOpenOnClient ) -{ - // NOTE: We leave bIsOpenOnClient alone on purpose here. See the header for a description of why. - - if( m_portalNumber == -1 ) - return false; - - // See if the viewer is on the backside. - VPlane plane; - if( !engine->GetAreaPortalPlane( vOrigin, m_portalNumber, &plane ) ) - return true; // leave it open if there's an error here for some reason - - bool bOpen = false; - if( plane.DistTo( vOrigin ) + VIEWER_PADDING > 0 ) - bOpen = true; - - return bOpen; -} - - - - diff --git a/game/server/func_areaportalbase.h b/game/server/func_areaportalbase.h deleted file mode 100644 index e30365222..000000000 --- a/game/server/func_areaportalbase.h +++ /dev/null @@ -1,116 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef FUNC_AREAPORTALBASE_H -#define FUNC_AREAPORTALBASE_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "baseentity.h" -#include "utllinkedlist.h" - - -// Shared stuff between door portals and window portals. -class CFuncAreaPortalBase : public CBaseEntity -{ - DECLARE_CLASS( CFuncAreaPortalBase, CBaseEntity ); -public: - DECLARE_DATADESC(); - - CFuncAreaPortalBase(); - virtual ~CFuncAreaPortalBase(); - - // Areaportals must be placed in each map for preprocess, they can't use transitions - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } - - // This is called each frame for each client to all portals to close - // when the viewer is far enough away, or on the backside. - // - // The default implementation closes the portal if the viewer (plus some padding) - // is on the backside of the portal. Return false if you close the portal. - // - // Returns whether or not the (server part of) the engine was told to shut the - // portal off for purposes of flowing through portals to determine which areas to - // send to the client. - // - // - // bIsOpenOnClient is usually the same as the return value but NOT always. Here's why (explained - // here in depth because this case was discovered in a lengthy debugging session): - // - // - Each CFuncAreaPortalBase represents two dareaportal_t's (matched by CFuncAreaPortalBase::m_portalNumber - // and dareaportal_t::m_PortalKey). Each dareaportal_t leads into one of the connected areas - // and the dareaportal_t's have opposite-facing planes. - // - // - The engine's SetAreaPortalState function takes a portal key and closes BOTH dareaportal_t's associated with it. - // - // - UpdateVisibility may decide a portal leading out of the _area you're sitting in_ can be closed - // for purposes of flowing through areas because you're on the backside of the dareaportal_t that - // you would flow out of. - // - // - At the same time, you might be able to look through the other dareaportal_t attached to - // that portal key (right back into the area you're standing in). - // - // - An illustration: - // - // -------------------- - // | | - // | |--------|aaaaaa| - // | | |bbbbbb| <---- aaaa and bbbb area both for PortalKey1 - // |**| | | - // | | | area | - // |**| | 2 | - // | | |------| - // | | | | - // | ---------- area | - // | 1 | - // |------------------| - // - // "aaaa" and "bbbb" each represent a different dareaportal_t, (aaa leads into area 2 and - // bbb leads into area 1). They both represent the same portal key though (call it PortalKey1). - // - // When standing in area 1 (where the "area 1" text is), the engine will check aaaa and it'll notice - // that you're on the wrong side of aaaa to be looking through it, so it'll say that PortalKey1 is closed - // for purposes of flowing through areas on the server (it turns out you can get to area 2 through - // the portal right above the "area 1" text). - // - // If you told the client that PortalKey1 was closed, then you'd get a pop when moving from area 1 - // to area 2 because the client would think you couldn't see through PortalKey1 into area 1 UNTIL - // the server transmitted the new updated PortalKey bits, which can be lagged. - // - // That's why we have bIsOpenOnClient which doesn't include this backfacing test. - // - // .. and they all lived happily ever after. - // The End - // - // - // - // Note: when you're standing in the space between the **'s, then the server would stop transmitting - // the contents of area 2 because there would be no portal you were on the correct side of to - // see into area 2. - virtual bool UpdateVisibility( const Vector &vOrigin, float fovDistanceAdjustFactor, bool &bIsOpenOnClient ); - - -public: - - // This matches two dareaportal_t::m_PortalKeys. - int m_portalNumber; - - int m_iPortalVersion; - -private: - - unsigned short m_AreaPortalsElement; // link into g_AreaPortals. -}; - - -extern CUtlLinkedList g_AreaPortals; - - - -#endif // FUNC_AREAPORTALBASE_H diff --git a/game/server/func_areaportalwindow.cpp b/game/server/func_areaportalwindow.cpp deleted file mode 100644 index 945272d71..000000000 --- a/game/server/func_areaportalwindow.cpp +++ /dev/null @@ -1,128 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "func_areaportalwindow.h" -#include "entitylist.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// The server will still send entities through a window even after it opaque -// to allow for net lag. -#define FADE_DIST_BUFFER 10 - - -LINK_ENTITY_TO_CLASS( func_areaportalwindow, CFuncAreaPortalWindow ); - - -IMPLEMENT_SERVERCLASS_ST( CFuncAreaPortalWindow, DT_FuncAreaPortalWindow ) - SendPropFloat( SENDINFO(m_flFadeDist), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO(m_flFadeStartDist), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO(m_flTranslucencyLimit), 0, SPROP_NOSCALE ), - - SendPropModelIndex(SENDINFO(m_iBackgroundModelIndex) ), -END_SEND_TABLE() - - -BEGIN_DATADESC( CFuncAreaPortalWindow ) - - DEFINE_KEYFIELD( m_portalNumber, FIELD_INTEGER, "portalnumber" ), - DEFINE_KEYFIELD( m_flFadeStartDist, FIELD_FLOAT, "FadeStartDist" ), - DEFINE_KEYFIELD( m_flFadeDist, FIELD_FLOAT, "FadeDist" ), - DEFINE_KEYFIELD( m_flTranslucencyLimit, FIELD_FLOAT, "TranslucencyLimit" ), - DEFINE_KEYFIELD( m_iBackgroundBModelName,FIELD_STRING, "BackgroundBModel" ), -// DEFINE_KEYFIELD( m_iBackgroundModelIndex,FIELD_INTEGER ), - - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFadeStartDistance", InputSetFadeStartDistance ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFadeEndDistance", InputSetFadeEndDistance ), - -END_DATADESC() - - - - -CFuncAreaPortalWindow::CFuncAreaPortalWindow() -{ - m_iBackgroundModelIndex = -1; -} - - -CFuncAreaPortalWindow::~CFuncAreaPortalWindow() -{ -} - - -void CFuncAreaPortalWindow::Spawn() -{ - Precache(); - - engine->SetAreaPortalState( m_portalNumber, 1 ); -} - - -void CFuncAreaPortalWindow::Activate() -{ - BaseClass::Activate(); - - // Find our background model. - CBaseEntity *pBackground = gEntList.FindEntityByName( NULL, m_iBackgroundBModelName ); - if( pBackground ) - { - m_iBackgroundModelIndex = modelinfo->GetModelIndex( STRING( pBackground->GetModelName() ) ); - pBackground->AddEffects( EF_NODRAW ); // we will draw for it. - } - - // Find our target and steal its bmodel. - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, m_target ); - if( pTarget ) - { - SetModel( STRING(pTarget->GetModelName()) ); - SetAbsOrigin( pTarget->GetAbsOrigin() ); - pTarget->AddEffects( EF_NODRAW ); // we will draw for it. - } -} - - -bool CFuncAreaPortalWindow::IsWindowOpen( const Vector &vOrigin, float fovDistanceAdjustFactor ) -{ - float flDist = CollisionProp()->CalcDistanceFromPoint( vOrigin ); - flDist *= fovDistanceAdjustFactor; - return ( flDist <= (m_flFadeDist + FADE_DIST_BUFFER) ); -} - - -bool CFuncAreaPortalWindow::UpdateVisibility( const Vector &vOrigin, float fovDistanceAdjustFactor, bool &bIsOpenOnClient ) -{ - if ( IsWindowOpen( vOrigin, fovDistanceAdjustFactor ) ) - { - return BaseClass::UpdateVisibility( vOrigin, fovDistanceAdjustFactor, bIsOpenOnClient ); - } - else - { - bIsOpenOnClient = false; - return false; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Changes the fade start distance -// Input: float distance in inches -//----------------------------------------------------------------------------- -void CFuncAreaPortalWindow::InputSetFadeStartDistance( inputdata_t &inputdata ) -{ - m_flFadeStartDist = inputdata.value.Float(); -} - -//----------------------------------------------------------------------------- -// Purpose: Changes the fade end distance -// Input: float distance in inches -//----------------------------------------------------------------------------- -void CFuncAreaPortalWindow::InputSetFadeEndDistance( inputdata_t &inputdata ) -{ - m_flFadeDist = inputdata.value.Float(); -} diff --git a/game/server/func_areaportalwindow.h b/game/server/func_areaportalwindow.h deleted file mode 100644 index a25597568..000000000 --- a/game/server/func_areaportalwindow.h +++ /dev/null @@ -1,67 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef FUNC_AREAPORTALWINDOW_H -#define FUNC_AREAPORTALWINDOW_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "baseentity.h" -#include "utllinkedlist.h" -#include "func_areaportalbase.h" - - -class CFuncAreaPortalWindow : public CFuncAreaPortalBase -{ -public: - DECLARE_CLASS( CFuncAreaPortalWindow, CFuncAreaPortalBase ); - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - CFuncAreaPortalWindow(); - ~CFuncAreaPortalWindow(); - - -// Overrides. -public: - - virtual void Spawn(); - virtual void Activate(); - - -// CFuncAreaPortalBase stuff. -public: - - virtual bool UpdateVisibility( const Vector &vOrigin, float fovDistanceAdjustFactor, bool &bIsOpenOnClient ); - - -public: - // Returns false if the viewer is past the fadeout distance. - bool IsWindowOpen( const Vector &vOrigin, float fovDistanceAdjustFactor ); - -public: - - CNetworkVar( float, m_flFadeStartDist ); // Distance at which it starts fading (when <= this, alpha=m_flTranslucencyLimit). - CNetworkVar( float, m_flFadeDist ); // Distance at which it becomes solid. - - // 0-1 value - minimum translucency it's allowed to get to. - CNetworkVar( float, m_flTranslucencyLimit ); - - string_t m_iBackgroundBModelName; // string name of background bmodel - CNetworkVar( int, m_iBackgroundModelIndex ); - - //Input handlers - void InputSetFadeStartDistance( inputdata_t &inputdata ); - void InputSetFadeEndDistance( inputdata_t &inputdata ); -}; - - - -#endif // FUNC_AREAPORTALWINDOW_H diff --git a/game/server/func_break.cpp b/game/server/func_break.cpp deleted file mode 100644 index bebdb38ef..000000000 --- a/game/server/func_break.cpp +++ /dev/null @@ -1,1324 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements breakables and pushables. func_breakable is a bmodel -// that breaks into pieces after taking damage. -// -//=============================================================================// - -#include "cbase.h" -#include "player.h" -#include "filters.h" -#include "func_break.h" -#include "decals.h" -#include "explode.h" -#include "in_buttons.h" -#include "physics.h" -#include "IEffects.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" -#include "globals.h" -#include "util.h" -#include "physics_impact_damage.h" -#include "tier0/icommandline.h" - -#ifdef PORTAL - #include "portal_shareddefs.h" - #include "portal_util_shared.h" - #include "prop_portal_shared.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar func_break_max_pieces( "func_break_max_pieces", "15", FCVAR_ARCHIVE | FCVAR_REPLICATED ); -ConVar func_break_reduction_factor( "func_break_reduction_factor", ".5" ); - -#ifdef HL1_DLL -extern void PlayerPickupObject( CBasePlayer *pPlayer, CBaseEntity *pObject ); -#endif - -extern Vector g_vecAttackDir; - -// Just add more items to the bottom of this array and they will automagically be supported -// This is done instead of just a classname in the FGD so we can control which entities can -// be spawned, and still remain fairly flexible - -#ifndef HL1_DLL - const char *CBreakable::pSpawnObjects[] = - { - NULL, // 0 - "item_battery", // 1 - "item_healthkit", // 2 - "item_ammo_pistol", // 3 - "item_ammo_pistol_large", // 4 - "item_ammo_smg1", // 5 - "item_ammo_smg1_large", // 6 - "item_ammo_ar2", // 7 - "item_ammo_ar2_large", // 8 - "item_box_buckshot", // 9 - "item_flare_round", // 10 - "item_box_flare_rounds", // 11 - "item_rpg_round", // 12 - "unused (item_smg1_grenade) 13",// 13 - "item_box_sniper_rounds", // 14 - "unused (?) 15", // 15 - "weapon_stunstick", // 16 - "unused (weapon_ar1) 17", // 17 - "weapon_ar2", // 18 - "unused (?) 19", // 19 - "weapon_rpg", // 20 - "weapon_smg1", // 21 - "unused (weapon_smg2) 22", // 22 - "unused (weapon_slam) 23", // 23 - "weapon_shotgun", // 24 - "unused (weapon_molotov) 25",// 25 - "item_dynamic_resupply", // 26 - }; -#else - // Half-Life 1 spawn objects! - const char *CBreakable::pSpawnObjects[] = - { - NULL, // 0 - "item_battery", // 1 - "item_healthkit", // 2 - "weapon_glock", // 3 - "ammo_9mmclip", // 4 - "weapon_mp5", // 5 - "ammo_9mmAR", // 6 - "ammo_ARgrenades", // 7 - "weapon_shotgun", // 8 - "ammo_buckshot", // 9 - "weapon_crossbow", // 10 - "ammo_crossbow", // 11 - "weapon_357", // 12 - "ammo_357", // 13 - "weapon_rpg", // 14 - "ammo_rpgclip", // 15 - "ammo_gaussclip", // 16 - "weapon_handgrenade",// 17 - "weapon_tripmine", // 18 - "weapon_satchel", // 19 - "weapon_snark", // 20 - "weapon_hornetgun", // 21 - }; -#endif - -const char *pFGDPropData[] = -{ - NULL, - "Wooden.Tiny", - "Wooden.Small", - "Wooden.Medium", - "Wooden.Large", - "Wooden.Huge", - "Metal.Small", - "Metal.Medium", - "Metal.Large", - "Cardboard.Small", - "Cardboard.Medium", - "Cardboard.Large", - "Stone.Small", - "Stone.Medium", - "Stone.Large", - "Stone.Huge", - "Glass.Small", - "Plastic.Small", - "Plastic.Medium", - "Plastic.Large", - "Pottery.Small", - "Pottery.Medium", - "Pottery.Large", - "Pottery.Huge", - "Glass.Window", -}; - -LINK_ENTITY_TO_CLASS( func_breakable, CBreakable ); -BEGIN_DATADESC( CBreakable ) - - DEFINE_FIELD( m_Material, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_Explosion, FIELD_INTEGER, "explosion" ), - DEFINE_KEYFIELD( m_GibDir, FIELD_VECTOR, "gibdir" ), - DEFINE_FIELD( m_hBreaker, FIELD_EHANDLE ), - - // Don't need to save/restore these because we precache after restore - //DEFINE_FIELD( m_idShard, FIELD_INTEGER ), - DEFINE_FIELD( m_angle, FIELD_FLOAT ), - DEFINE_FIELD( m_iszGibModel, FIELD_STRING ), - DEFINE_FIELD( m_iszSpawnObject, FIELD_STRING ), - DEFINE_KEYFIELD( m_ExplosionMagnitude, FIELD_INTEGER, "explodemagnitude" ), - DEFINE_KEYFIELD( m_flPressureDelay, FIELD_FLOAT, "PressureDelay" ), - DEFINE_KEYFIELD( m_iMinHealthDmg, FIELD_INTEGER, "minhealthdmg" ), - DEFINE_FIELD( m_bTookPhysicsDamage, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iszPropData, FIELD_STRING ), - DEFINE_INPUT( m_impactEnergyScale, FIELD_FLOAT, "physdamagescale" ), - DEFINE_KEYFIELD( m_PerformanceMode, FIELD_INTEGER, "PerformanceMode" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Break", InputBreak ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetHealth", InputSetHealth ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "AddHealth", InputAddHealth ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "RemoveHealth", InputRemoveHealth ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetMass", InputSetMass ), - - // Function Pointers - DEFINE_ENTITYFUNC( BreakTouch ), - DEFINE_THINKFUNC( Die ), - - // Outputs - DEFINE_OUTPUT(m_OnBreak, "OnBreak"), - DEFINE_OUTPUT(m_OnHealthChanged, "OnHealthChanged"), - - DEFINE_FIELD( m_flDmgModBullet, FIELD_FLOAT ), - DEFINE_FIELD( m_flDmgModClub, FIELD_FLOAT ), - DEFINE_FIELD( m_flDmgModExplosive, FIELD_FLOAT ), - DEFINE_FIELD( m_iszPhysicsDamageTableName, FIELD_STRING ), - DEFINE_FIELD( m_iszBreakableModel, FIELD_STRING ), - DEFINE_FIELD( m_iBreakableSkin, FIELD_INTEGER ), - DEFINE_FIELD( m_iBreakableCount, FIELD_INTEGER ), - DEFINE_FIELD( m_iMaxBreakableSize, FIELD_INTEGER ), - DEFINE_FIELD( m_iszBasePropData, FIELD_STRING ), - DEFINE_FIELD( m_iInteractions, FIELD_INTEGER ), - DEFINE_FIELD( m_explodeRadius, FIELD_FLOAT ), - DEFINE_FIELD( m_iszModelName, FIELD_STRING ), - - // Physics Influence - DEFINE_FIELD( m_hPhysicsAttacker, FIELD_EHANDLE ), - DEFINE_FIELD( m_flLastPhysicsInfluenceTime, FIELD_TIME ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBreakable::KeyValue( const char *szKeyName, const char *szValue ) -{ - // UNDONE_WC: explicitly ignoring these fields, but they shouldn't be in the map file! - if (FStrEq(szKeyName, "material")) - { - int i = atoi( szValue); - - // 0:glass, 1:metal, 2:flesh, 3:wood - - if ((i < 0) || (i >= matLastMaterial)) - m_Material = matWood; - else - m_Material = (Materials)i; - } - else if (FStrEq(szKeyName, "deadmodel")) - { - } - else if (FStrEq(szKeyName, "shards")) - { -// m_iShards = atof(szValue); - } - else if (FStrEq(szKeyName, "gibmodel") ) - { - m_iszGibModel = AllocPooledString(szValue); - } - else if (FStrEq(szKeyName, "spawnobject") ) - { - int object = atoi( szValue ); - if ( object > 0 && object < (int)ARRAYSIZE(pSpawnObjects) ) - m_iszSpawnObject = MAKE_STRING( pSpawnObjects[object] ); - } - else if (FStrEq(szKeyName, "propdata") ) - { - int pdata = atoi( szValue ); - if ( pdata > 0 && pdata < (int)ARRAYSIZE(pFGDPropData) ) - { - m_iszPropData = MAKE_STRING( pFGDPropData[pdata] ); - } - else if ( pdata ) - { - // If you've hit this warning, it's probably because someone's added a new - // propdata field to func_breakables in the .fgd, and not added it to the - // pFGDPropData list. - Warning("func_breakable with invalid propdata %d.\n", pdata ); - } - } - else if (FStrEq(szKeyName, "lip") ) - { - } - else - return BaseClass::KeyValue( szKeyName, szValue ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBreakable::Spawn( void ) -{ - // Initialize damage modifiers. Must be done before baseclass spawn. - m_flDmgModBullet = func_breakdmg_bullet.GetFloat(); - m_flDmgModClub = func_breakdmg_club.GetFloat(); - m_flDmgModExplosive = func_breakdmg_explosive.GetFloat(); - - ParsePropData(); - - Precache( ); - - if ( !m_iHealth || FBitSet( m_spawnflags, SF_BREAK_TRIGGER_ONLY ) ) - { - // This allows people to shoot at the glass (since it's penetrable) - if ( m_Material == matGlass ) - { - m_iHealth = 1; - } - - m_takedamage = DAMAGE_NO; - } - else - { - m_takedamage = DAMAGE_YES; - } - - m_iMaxHealth = ( m_iHealth > 0 ) ? m_iHealth : 1; - - SetSolid( SOLID_BSP ); - SetMoveType( MOVETYPE_PUSH ); - - // this is a hack to shoot the gibs in a specific yaw/direction - m_angle = GetLocalAngles().y; - SetLocalAngles( vec3_angle ); - - SetModel( STRING( GetModelName() ) );//set size and link into world. - - SetTouch( &CBreakable::BreakTouch ); - if ( FBitSet( m_spawnflags, SF_BREAK_TRIGGER_ONLY ) ) // Only break on trigger - { - SetTouch( NULL ); - } - - // Flag unbreakable glass as "worldbrush" so it will block ALL tracelines - if ( !IsBreakable() && m_nRenderMode != kRenderNormal ) - AddFlag( FL_WORLDBRUSH ); - - if ( m_impactEnergyScale == 0 ) - { - m_impactEnergyScale = 1.0; - } - - CreateVPhysics(); -} - -//----------------------------------------------------------------------------- -// Purpose: Parse this prop's data, if it has a keyvalues section. -// Returns true only if this prop is using a model that has a prop_data section that's invalid. -//----------------------------------------------------------------------------- -void CBreakable::ParsePropData( void ) -{ - if ( m_iszPropData == NULL_STRING ) - return; - - if ( !Q_strncmp( STRING(m_iszPropData), "None", 4 ) ) - return; - - g_PropDataSystem.ParsePropFromBase( this, STRING(m_iszPropData) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBreakable::CreateVPhysics( void ) -{ - VPhysicsInitStatic(); - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const char *CBreakable::MaterialSound( Materials precacheMaterial ) -{ - switch ( precacheMaterial ) - { - case matWood: - return "Breakable.MatWood"; - case matFlesh: - case matWeb: - return "Breakable.MatFlesh"; - case matComputer: - return "Breakable.Computer"; - case matUnbreakableGlass: - case matGlass: - return "Breakable.MatGlass"; - case matMetal: - return "Breakable.MatMetal"; - case matCinderBlock: - case matRocks: - return "Breakable.MatConcrete"; - case matCeilingTile: - case matNone: - default: - break; - } - - return NULL; -} - - -void CBreakable::MaterialSoundRandom( int entindex, Materials soundMaterial, float volume ) -{ - const char *soundname; - soundname = MaterialSound( soundMaterial ); - if ( !soundname ) - return; - - CSoundParameters params; - if ( !GetParametersForSound( soundname, params, NULL ) ) - return; - - CPASAttenuationFilter filter( CBaseEntity::Instance( entindex ), params.soundlevel ); - - - EmitSound_t ep; - ep.m_nChannel = params.channel; - ep.m_pSoundName = params.soundname; - ep.m_flVolume = volume; - ep.m_SoundLevel = params.soundlevel; - - EmitSound( filter, entindex, ep ); -} - - -void CBreakable::Precache( void ) -{ - const char *pGibName = "WoodChunks"; - - switch (m_Material) - { - case matWood: - pGibName = "WoodChunks"; - break; - - case matUnbreakableGlass: - case matGlass: - pGibName = "GlassChunks"; - break; - - case matMetal: - pGibName = "MetalChunks"; - break; - - case matRocks: - pGibName = "ConcreteChunks"; - break; - -#ifdef HL1_DLL - case matComputer: - pGibName = "ComputerGibs"; - break; - - case matCeilingTile: - pGibName = "CeilingTile"; - break; - - case matFlesh: - pGibName = "FleshGibs"; - break; - - case matCinderBlock: - pGibName = "CinderBlocks"; - break; - - case matWeb: - pGibName = "WebGibs"; - break; -#else - - case matCinderBlock: - pGibName = "ConcreteChunks"; - break; -#endif - -#if HL2_EPISODIC - case matNone: - pGibName = ""; - break; -#endif - - default: - Warning("%s (%s) at (%.3f %.3f %.3f) using obsolete or unknown material type.\n", GetClassname(), GetDebugName(), GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z ); - pGibName = "WoodChunks"; - break; - } - - if ( m_iszGibModel != NULL_STRING ) - { - pGibName = STRING(m_iszGibModel); - -#ifdef HL1_DLL - PrecacheModel( pGibName ); -#endif - } - - m_iszModelName = MAKE_STRING( pGibName ); - - // Precache the spawn item's data - if ( !CommandLine()->CheckParm("-makereslists")) - { - if ( m_iszSpawnObject != NULL_STRING ) - { - UTIL_PrecacheOther( STRING( m_iszSpawnObject ) ); - } - } - else - { - // Actually, precache all possible objects... - for ( int i = 0; i < (int)ARRAYSIZE(pSpawnObjects) ; ++i ) - { - if ( !pSpawnObjects[ i ] ) - continue; - - if ( !Q_strnicmp( pSpawnObjects[ i ], "unused", Q_strlen( "unused" ) ) ) - continue; - - UTIL_PrecacheOther( pSpawnObjects[ i ] ); - } - } - - PrecacheScriptSound( "Breakable.MatGlass" ); - PrecacheScriptSound( "Breakable.MatWood" ); - PrecacheScriptSound( "Breakable.MatMetal" ); - PrecacheScriptSound( "Breakable.MatFlesh" ); - PrecacheScriptSound( "Breakable.MatConcrete" ); - PrecacheScriptSound( "Breakable.Computer" ); - PrecacheScriptSound( "Breakable.Crate" ); - PrecacheScriptSound( "Breakable.Glass" ); - PrecacheScriptSound( "Breakable.Metal" ); - PrecacheScriptSound( "Breakable.Flesh" ); - PrecacheScriptSound( "Breakable.Concrete" ); - PrecacheScriptSound( "Breakable.Ceiling" ); -} - -// play shard sound when func_breakable takes damage. -// the more damage, the louder the shard sound. - - -void CBreakable::DamageSound( void ) -{ - int pitch; - float fvol; - const char *soundname = NULL; - int material = m_Material; - - if (random->RandomInt(0,2)) - { - pitch = PITCH_NORM; - } - else - { - pitch = 95 + random->RandomInt(0,34); - } - - fvol = random->RandomFloat(0.75, 1.0); - - if (material == matComputer && random->RandomInt(0,1)) - { - material = matMetal; - } - - switch (material) - { - case matGlass: - case matUnbreakableGlass: - soundname = "Breakable.MatGlass"; - break; - - case matWood: - soundname = "Breakable.MatWood"; - break; - - case matMetal: - soundname = "Breakable.MatMetal"; - break; - - case matRocks: - case matCinderBlock: - soundname = "Breakable.MatConcrete"; - break; - - case matComputer: - soundname = "Breakable.Computer"; - break; - - default: - break; - } - - if ( soundname ) - { - CSoundParameters params; - if ( GetParametersForSound( soundname, params, NULL ) ) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = params.channel; - ep.m_pSoundName = params.soundname; - ep.m_flVolume = fvol; - ep.m_SoundLevel = params.soundlevel; - ep.m_nPitch = pitch; - - EmitSound( filter, entindex(), ep ); - } - } -} - -void CBreakable::BreakTouch( CBaseEntity *pOther ) -{ - float flDamage; - - // only players can break these right now - if ( !pOther->IsPlayer() || !IsBreakable() ) - { - return; - } - - // can I be broken when run into? - if ( HasSpawnFlags( SF_BREAK_TOUCH ) ) - { - flDamage = pOther->GetSmoothedVelocity().Length() * 0.01; - - if (flDamage >= m_iHealth) - { - m_takedamage = DAMAGE_YES; - - SetTouch( NULL ); - OnTakeDamage( CTakeDamageInfo( pOther, pOther, flDamage, DMG_CRUSH ) ); - - // do a little damage to player if we broke glass or computer - CTakeDamageInfo info( pOther, pOther, flDamage/4, DMG_SLASH ); - CalculateMeleeDamageForce( &info, (pOther->GetAbsOrigin() - GetAbsOrigin()), GetAbsOrigin() ); - pOther->TakeDamage( info ); - } - } - - // can I be broken when stood upon? - if ( HasSpawnFlags( SF_BREAK_PRESSURE ) && pOther->GetGroundEntity() == this ) - { - // play creaking sound here. - DamageSound(); - - m_hBreaker = pOther; - - SetThink ( &CBreakable::Die ); - SetTouch( NULL ); - - // Add optional delay - SetNextThink( gpGlobals->curtime + m_flPressureDelay ); - - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for adding to the breakable's health. -// Input : Integer health points to add. -//----------------------------------------------------------------------------- -void CBreakable::InputAddHealth( inputdata_t &inputdata ) -{ - UpdateHealth( m_iHealth + inputdata.value.Int(), inputdata.pActivator ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for breaking the breakable immediately. -//----------------------------------------------------------------------------- -void CBreakable::InputBreak( inputdata_t &inputdata ) -{ - Break( inputdata.pActivator ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for removing health from the breakable. -// Input : Integer health points to remove. -//----------------------------------------------------------------------------- -void CBreakable::InputRemoveHealth( inputdata_t &inputdata ) -{ - UpdateHealth( m_iHealth - inputdata.value.Int(), inputdata.pActivator ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for setting the breakable's health. -//----------------------------------------------------------------------------- -void CBreakable::InputSetHealth( inputdata_t &inputdata ) -{ - UpdateHealth( inputdata.value.Int(), inputdata.pActivator ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for setting the breakable's mass. -//----------------------------------------------------------------------------- -void CBreakable::InputSetMass( inputdata_t &inputdata ) -{ - IPhysicsObject * vPhys = VPhysicsGetObject(); - if ( vPhys ) - { - float toMass = inputdata.value.Float(); - Assert(toMass > 0); - vPhys->SetMass( toMass ); - } - else - { - Warning( "Tried to call SetMass() on %s but it has no physics.\n", GetEntityName().ToCStr() ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Choke point for changes to breakable health. Ensures outputs are fired. -// Input : iNewHealth - -// pActivator - -// Output : Returns true if the breakable survived, false if it died (broke). -//----------------------------------------------------------------------------- -bool CBreakable::UpdateHealth( int iNewHealth, CBaseEntity *pActivator ) -{ - if ( iNewHealth != m_iHealth ) - { - m_iHealth = iNewHealth; - - if ( m_iMaxHealth == 0 ) - { - Assert( false ); - m_iMaxHealth = 1; - } - - // Output the new health as a percentage of max health [0..1] - float flRatio = clamp( (float)m_iHealth / (float)m_iMaxHealth, 0, 1 ); - m_OnHealthChanged.Set( flRatio, pActivator, this ); - - if ( m_iHealth <= 0 ) - { - Break( pActivator ); - return false; - } - else - { - if ( FBitSet( m_spawnflags, SF_BREAK_TRIGGER_ONLY ) ) - { - m_takedamage = DAMAGE_NO; - } - else - { - m_takedamage = DAMAGE_YES; - } - } - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Breaks the breakable if it can be broken. -// Input : pBreaker - The entity that caused us to break, either via an input, -// by shooting us, or by touching us. -//----------------------------------------------------------------------------- -void CBreakable::Break( CBaseEntity *pBreaker ) -{ - if ( IsBreakable() ) - { - QAngle angles = GetLocalAngles(); - angles.y = m_angle; - SetLocalAngles( angles ); - m_hBreaker = pBreaker; - Die(); - } -} - - -void CBreakable::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - // random spark if this is a 'computer' object - if (random->RandomInt(0,1) ) - { - switch( m_Material ) - { - case matComputer: - { - g_pEffects->Sparks( ptr->endpos ); - - EmitSound( "Breakable.Computer" ); - } - break; - - case matUnbreakableGlass: - g_pEffects->Ricochet( ptr->endpos, (vecDir*-1.0f) ); - break; - - default: - break; - } - } - - BaseClass::TraceAttack( info, vecDir, ptr ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Allows us to take damage from physics objects -//----------------------------------------------------------------------------- -void CBreakable::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) -{ - BaseClass::VPhysicsCollision( index, pEvent ); - - Vector damagePos; - pEvent->pInternalData->GetContactPoint( damagePos ); - Vector damageForce = pEvent->postVelocity[index] * pEvent->pObjects[index]->GetMass(); - if ( damageForce == vec3_origin ) - { - // This can happen if this entity is a func_breakable, and can't move. - // Use the velocity of the entity that hit us instead. - damageForce = pEvent->postVelocity[!index] * pEvent->pObjects[!index]->GetMass(); - } - - // If we're supposed to explode on collision, do so - if ( HasSpawnFlags( SF_BREAK_PHYSICS_BREAK_IMMEDIATELY ) ) - { - // We're toast - m_bTookPhysicsDamage = true; - CBaseEntity *pHitEntity = pEvent->pEntities[!index]; - - // HACKHACK: Reset mass to get correct collision response for the object breaking this glass - if ( m_Material == matGlass ) - { - pEvent->pObjects[index]->SetMass( 2.0f ); - } - CTakeDamageInfo dmgInfo( pHitEntity, pHitEntity, damageForce, damagePos, (m_iHealth + 1), DMG_CRUSH ); - PhysCallbackDamage( this, dmgInfo, *pEvent, index ); - } - else if ( !HasSpawnFlags( SF_BREAK_DONT_TAKE_PHYSICS_DAMAGE ) ) - { - int otherIndex = !index; - CBaseEntity *pOther = pEvent->pEntities[otherIndex]; - - // We're to take normal damage from this - int damageType; - IBreakableWithPropData *pBreakableInterface = assert_cast(this); - float damage = CalculateDefaultPhysicsDamage( index, pEvent, m_impactEnergyScale, true, damageType, pBreakableInterface->GetPhysicsDamageTable() ); - if ( damage > 0 ) - { - // HACKHACK: Reset mass to get correct collision response for the object breaking this glass - if ( m_Material == matGlass ) - { - pEvent->pObjects[index]->SetMass( 2.0f ); - } - CTakeDamageInfo dmgInfo( pOther, pOther, damageForce, damagePos, damage, damageType ); - PhysCallbackDamage( this, dmgInfo, *pEvent, index ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Allows us to make damage exceptions that are breakable-specific. -//----------------------------------------------------------------------------- -int CBreakable::OnTakeDamage( const CTakeDamageInfo &info ) -{ - Vector vecTemp; - - CTakeDamageInfo subInfo = info; - - // If attacker can't do at least the min required damage to us, don't take any damage from them - if ( m_takedamage == DAMAGE_NO || info.GetDamage() < m_iMinHealthDmg ) - return 0; - - // Check our damage filter - if ( !PassesDamageFilter(subInfo) ) - { - m_bTookPhysicsDamage = false; - return 1; - } - - vecTemp = subInfo.GetInflictor()->GetAbsOrigin() - WorldSpaceCenter(); - - if (!IsBreakable()) - return 0; - - float flPropDamage = GetBreakableDamage( subInfo, assert_cast(this) ); - subInfo.SetDamage( flPropDamage ); - - int iPrevHealth = m_iHealth; - BaseClass::OnTakeDamage( subInfo ); - - // HACK: slam health back to what it was so UpdateHealth can do its thing - int iNewHealth = m_iHealth; - m_iHealth = iPrevHealth; - if ( !UpdateHealth( iNewHealth, info.GetAttacker() ) ) - return 1; - - // Make a shard noise each time func breakable is hit, if it's capable of taking damage - if ( m_takedamage == DAMAGE_YES ) - { - // Don't play shard noise if being burned. - // Don't play shard noise if cbreakable actually died. - if ( ( subInfo.GetDamageType() & DMG_BURN ) == false ) - { - DamageSound(); - } - } - - return 1; -} - -//------------------------------------------------------------------------------ -// Purpose : Reset the OnGround flags for any entities that may have been -// resting on me -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBreakable::ResetOnGroundFlags(void) -{ - // !!! HACK This should work! - // Build a box above the entity that looks like an 9 inch high sheet - Vector mins, maxs; - CollisionProp()->WorldSpaceAABB( &mins, &maxs ); - mins.z -= 1; - maxs.z += 8; - - // BUGBUG -- can only find 256 entities on a breakable -- should be enough - CBaseEntity *pList[256]; - int count = UTIL_EntitiesInBox( pList, 256, mins, maxs, FL_ONGROUND ); - if ( count ) - { - for ( int i = 0; i < count; i++ ) - { - pList[i]->SetGroundEntity( (CBaseEntity *)NULL ); - } - } - -#ifdef PORTAL - // !!! HACK This should work! - // Tell touching portals to fizzle - int iPortalCount = CProp_Portal_Shared::AllPortals.Count(); - if( iPortalCount != 0 ) - { - Vector vMin, vMax; - CollisionProp()->WorldSpaceAABB( &vMin, &vMax ); - - Vector vBoxCenter = ( vMin + vMax ) * 0.5f; - Vector vBoxExtents = ( vMax - vMin ) * 0.5f; - - CProp_Portal **pPortals = CProp_Portal_Shared::AllPortals.Base(); - for( int i = 0; i != iPortalCount; ++i ) - { - CProp_Portal *pTempPortal = pPortals[i]; - if( UTIL_IsBoxIntersectingPortal( vBoxCenter, vBoxExtents, pTempPortal ) ) - { - pTempPortal->DoFizzleEffect( PORTAL_FIZZLE_KILLED, false ); - pTempPortal->Fizzle(); - } - } - } -#endif -} - - -//----------------------------------------------------------------------------- -// Purpose: Breaks the breakable. m_hBreaker is the entity that caused us to break. -//----------------------------------------------------------------------------- -void CBreakable::Die( void ) -{ - Vector vecVelocity;// shard velocity - char cFlag = 0; - int pitch; - float fvol; - - pitch = 95 + random->RandomInt(0,29); - - if (pitch > 97 && pitch < 103) - { - pitch = 100; - } - - // The more negative m_iHealth, the louder - // the sound should be. - - fvol = random->RandomFloat(0.85, 1.0) + (abs(m_iHealth) / 100.0); - if (fvol > 1.0) - { - fvol = 1.0; - } - - const char *soundname = NULL; - - switch (m_Material) - { - default: - break; - - case matGlass: - soundname = "Breakable.Glass"; - cFlag = BREAK_GLASS; - break; - - case matWood: - soundname = "Breakable.Crate"; - cFlag = BREAK_WOOD; - break; - - case matComputer: - soundname = "Breakable.Computer"; - cFlag = BREAK_METAL; - break; - - case matMetal: - soundname = "Breakable.Metal"; - cFlag = BREAK_METAL; - break; - - case matFlesh: - case matWeb: - soundname = "Breakable.Flesh"; - cFlag = BREAK_FLESH; - break; - - case matRocks: - case matCinderBlock: - soundname = "Breakable.Concrete"; - cFlag = BREAK_CONCRETE; - break; - - case matCeilingTile: - soundname = "Breakable.Ceiling"; - break; - } - - if ( soundname ) - { - if ( m_hBreaker && m_hBreaker->IsPlayer() ) - { - IGameEvent * event = gameeventmanager->CreateEvent( "break_breakable" ); - if ( event ) - { - event->SetInt( "userid", ToBasePlayer( m_hBreaker )->GetUserID() ); - event->SetInt( "entindex", entindex() ); - event->SetInt( "material", cFlag ); - gameeventmanager->FireEvent( event ); - } - } - - CSoundParameters params; - if ( GetParametersForSound( soundname, params, NULL ) ) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = params.channel; - ep.m_pSoundName = params.soundname; - ep.m_flVolume = fvol; - ep.m_SoundLevel = params.soundlevel; - ep.m_nPitch = pitch; - - EmitSound( filter, entindex(), ep ); - } - } - - switch( m_Explosion ) - { - case expDirected: - vecVelocity = g_vecAttackDir * -200; - break; - - case expUsePrecise: - { - AngleVectors( m_GibDir, &vecVelocity, NULL, NULL ); - vecVelocity *= 200; - } - break; - - case expRandom: - vecVelocity.x = 0; - vecVelocity.y = 0; - vecVelocity.z = 0; - break; - - default: - DevMsg("**ERROR - Unspecified gib dir method in func_breakable!\n"); - break; - } - - Vector vecSpot = WorldSpaceCenter(); - CPVSFilter filter2( vecSpot ); - - int iModelIndex = 0; - CCollisionProperty *pCollisionProp = CollisionProp(); - - Vector vSize = pCollisionProp->OBBSize(); - int iCount = (int)(( vSize[0] * vSize[1] + vSize[1] * vSize[2] + vSize[2] * vSize[0] ) / ( 3 * 12 * 12 )); - - if ( iCount > func_break_max_pieces.GetInt() ) - { - iCount = func_break_max_pieces.GetInt(); - } - - ConVarRef breakable_disable_gib_limit( "breakable_disable_gib_limit" ); - if ( !breakable_disable_gib_limit.GetBool() && iCount ) - { - if ( m_PerformanceMode == PM_NO_GIBS ) - { - iCount = 0; - } - else if ( m_PerformanceMode == PM_REDUCED_GIBS ) - { - int iNewCount = (int)(iCount * func_break_reduction_factor.GetFloat()); - iCount = MAX( iNewCount, 1 ); - } - } - - if ( m_iszModelName != NULL_STRING ) - { - for ( int i = 0; i < iCount; i++ ) - { - - #ifdef HL1_DLL - // Use the passed model instead of the propdata type - const char *modelName = STRING( m_iszModelName ); - - // if the map specifies a model by name - if( strstr( modelName, ".mdl" ) != NULL ) - { - iModelIndex = modelinfo->GetModelIndex( modelName ); - } - else // do the hl2 / normal way - #endif - - iModelIndex = modelinfo->GetModelIndex( g_PropDataSystem.GetRandomChunkModel( STRING( m_iszModelName ) ) ); - - // All objects except the first one in this run are marked as slaves... - int slaveFlag = 0; - if ( i != 0 ) - { - slaveFlag = BREAK_SLAVE; - } - - te->BreakModel( filter2, 0.0, - vecSpot, pCollisionProp->GetCollisionAngles(), vSize, - vecVelocity, iModelIndex, 100, 1, 2.5, cFlag | slaveFlag ); - } - } - - ResetOnGroundFlags(); - - // Don't fire something that could fire myself - SetName( NULL_STRING ); - - AddSolidFlags( FSOLID_NOT_SOLID ); - - // Fire targets on break - m_OnBreak.FireOutput( m_hBreaker, this ); - - VPhysicsDestroyObject(); - SetThink( &CBreakable::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 0.1f ); - if ( m_iszSpawnObject != NULL_STRING ) - { - CBaseEntity::Create( STRING(m_iszSpawnObject), vecSpot, pCollisionProp->GetCollisionAngles(), this ); - } - - if ( Explodable() ) - { - ExplosionCreate( vecSpot, pCollisionProp->GetCollisionAngles(), this, (int)GetExplosiveDamage(), (int)GetExplosiveRadius(), true ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns whether this object can be broken. -//----------------------------------------------------------------------------- -bool CBreakable::IsBreakable( void ) -{ - return m_Material != matUnbreakableGlass; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -char const *CBreakable::DamageDecal( int bitsDamageType, int gameMaterial ) -{ - if ( m_Material == matGlass ) - return "GlassBreak"; - - if ( m_Material == matUnbreakableGlass ) - return "BulletProof"; - - return BaseClass::DamageDecal( bitsDamageType, gameMaterial ); -} - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CBreakable::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - if ( GetMaxHealth() ) - { - char tempstr[512]; - Q_snprintf(tempstr,sizeof(tempstr),"Health: %i",GetHealth()); - EntityText(text_offset,tempstr,0); - text_offset++; - } - - if ( m_iszBasePropData != NULL_STRING ) - { - char tempstr[512]; - Q_snprintf(tempstr, sizeof(tempstr),"Base PropData: %s", STRING(m_iszBasePropData) ); - EntityText( text_offset, tempstr, 0); - text_offset++; - } - } - - return text_offset; -} - - -//----------------------------------------------------------------------------- -// Purpose: Keep track of physgun influence -//----------------------------------------------------------------------------- - -void CBreakable::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) -{ - m_hPhysicsAttacker = pPhysGunUser; - m_flLastPhysicsInfluenceTime = gpGlobals->curtime; -} - -void CBreakable::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t reason ) -{ - m_hPhysicsAttacker = pPhysGunUser; - m_flLastPhysicsInfluenceTime = gpGlobals->curtime; -} - -CBasePlayer *CBreakable::HasPhysicsAttacker( float dt ) -{ - if (gpGlobals->curtime - dt <= m_flLastPhysicsInfluenceTime) - { - return m_hPhysicsAttacker; - } - return NULL; -} - - -//============================================================================================================================= -// PUSHABLE -//============================================================================================================================= - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CPushable : public CBreakable -{ -public: - DECLARE_CLASS( CPushable, CBreakable ); - - void Spawn ( void ); - bool CreateVPhysics( void ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() | FCAP_ONOFF_USE; } - - // breakables use an overridden takedamage - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - virtual void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); - unsigned int PhysicsSolidMaskForEntity( void ) const { return MASK_PLAYERSOLID; } -}; - - -LINK_ENTITY_TO_CLASS( func_pushable, CPushable ); - - -void CPushable::Spawn( void ) -{ - if ( HasSpawnFlags( SF_PUSH_BREAKABLE ) ) - { - BaseClass::Spawn(); - } - else - { - Precache(); - - SetSolid( SOLID_VPHYSICS ); - - SetMoveType( MOVETYPE_PUSH ); - SetModel( STRING( GetModelName() ) ); - - CreateVPhysics(); - } - -#ifdef HL1_DLL - // Force HL1 Pushables to stay axially aligned. - VPhysicsGetObject()->SetInertia( Vector( 1e30, 1e30, 1e30 ) ); -#endif//HL1_DLL -} - - -bool CPushable::CreateVPhysics( void ) -{ - VPhysicsInitNormal( SOLID_VPHYSICS, 0, false ); - IPhysicsObject *pPhysObj = VPhysicsGetObject(); - if ( pPhysObj ) - { - pPhysObj->SetMass( 30 ); -// Vector vecInertia = Vector(800, 800, 800); -// pPhysObj->SetInertia( vecInertia ); - } - - return true; -} - -// Pull the func_pushable -void CPushable::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ -#ifdef HL1_DLL - if( m_spawnflags & SF_PUSH_NO_USE ) - return; - - // Allow pushables to be dragged by player - CBasePlayer *pPlayer = ToBasePlayer( pActivator ); - if ( pPlayer ) - { - if ( useType == USE_ON ) - { - PlayerPickupObject( pPlayer, this ); - } - } -#else - BaseClass::Use( pActivator, pCaller, useType, value ); -#endif -} - - -int CPushable::OnTakeDamage( const CTakeDamageInfo &info ) -{ - if ( m_spawnflags & SF_PUSH_BREAKABLE ) - return BaseClass::OnTakeDamage( info ); - - return 1; -} - -//----------------------------------------------------------------------------- -// Purpose: Allows us to take damage from physics objects -//----------------------------------------------------------------------------- -void CPushable::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) -{ - int otherIndex = !index; - CBaseEntity *pOther = pEvent->pEntities[otherIndex]; - if ( pOther->IsPlayer() ) - { - // Pushables don't take damage from impacts with the player - // We call all the way back to the baseclass to get the physics effects. - CBaseEntity::VPhysicsCollision( index, pEvent ); - return; - } - - BaseClass::VPhysicsCollision( index, pEvent ); -} - diff --git a/game/server/func_break.h b/game/server/func_break.h deleted file mode 100644 index 724b6ed9c..000000000 --- a/game/server/func_break.h +++ /dev/null @@ -1,174 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Defines a class for objects that break after taking a certain amount -// of damage. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef FUNC_BREAK_H -#define FUNC_BREAK_H -#pragma once - -#include "entityoutput.h" -#include "props.h" - -typedef enum { expRandom = 0, expDirected, expUsePrecise} Explosions; -typedef enum { matGlass = 0, matWood, matMetal, matFlesh, matCinderBlock, matCeilingTile, matComputer, matUnbreakableGlass, matRocks, matWeb, matNone, matLastMaterial } Materials; - - -#define NUM_SHARDS 6 // this many shards spawned when breakable objects break; - -// Spawnflags for func breakable -#define SF_BREAK_TRIGGER_ONLY 0x0001 // may only be broken by trigger -#define SF_BREAK_TOUCH 0x0002 // can be 'crashed through' by running player (plate glass) -#define SF_BREAK_PRESSURE 0x0004 // can be broken by a player standing on it -#define SF_BREAK_PHYSICS_BREAK_IMMEDIATELY 0x0200 // the first physics collision this breakable has will immediately break it -#define SF_BREAK_DONT_TAKE_PHYSICS_DAMAGE 0x0400 // this breakable doesn't take damage from physics collisions -#define SF_BREAK_NO_BULLET_PENETRATION 0x0800 // don't allow bullets to penetrate - -// Spawnflags for func_pushable (it's also func_breakable, so don't collide with those flags) -#define SF_PUSH_BREAKABLE 0x0080 -#define SF_PUSH_NO_USE 0x0100 // player cannot +use pickup this ent - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CBreakable : public CBaseEntity, public IBreakableWithPropData, public CDefaultPlayerPickupVPhysics -{ -public: - DECLARE_CLASS( CBreakable, CBaseEntity ); - - // basic functions - virtual void Spawn( void ); - void ParsePropData( void ); - bool CreateVPhysics( void ); - virtual void Precache( void ); - virtual bool KeyValue( const char *szKeyName, const char *szValue ); - virtual void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); - - void BreakTouch( CBaseEntity *pOther ); - void DamageSound( void ); - void Break( CBaseEntity *pBreaker ); - - // Input handlers - void InputAddHealth( inputdata_t &inputdata ); - void InputBreak( inputdata_t &inputdata ); - void InputRemoveHealth( inputdata_t &inputdata ); - void InputSetHealth( inputdata_t &inputdata ); - void InputSetMass( inputdata_t &inputdata ); - - - // breakables use an overridden takedamage - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - - // To spark when hit - void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - - bool IsBreakable( void ); - bool SparkWhenHit( void ); - - char const *DamageDecal( int bitsDamageType, int gameMaterial ); - - virtual void Die( void ); - void ResetOnGroundFlags(void); - - inline bool Explodable( void ) { return GetExplosiveRadius() > 0; } - - Materials GetMaterialType( void ) { return m_Material; } - static void MaterialSoundRandom( int entindex, Materials soundMaterial, float volume ); - static const char *MaterialSound( Materials precacheMaterial ); - - static const char *pSpawnObjects[]; - - int DrawDebugTextOverlays(void); - - DECLARE_DATADESC(); - -public: -// IBreakableWithPropData - void SetDmgModBullet( float flDmgMod ) { m_flDmgModBullet = flDmgMod; } - void SetDmgModClub( float flDmgMod ) { m_flDmgModClub = flDmgMod; } - void SetDmgModExplosive( float flDmgMod ) { m_flDmgModExplosive = flDmgMod; } - float GetDmgModBullet( void ) { return m_flDmgModBullet; } - float GetDmgModClub( void ) { return m_flDmgModClub; } - float GetDmgModExplosive( void ) { return m_flDmgModExplosive; } - void SetExplosiveRadius( float flRadius ) { m_explodeRadius = flRadius; } - void SetExplosiveDamage( float flDamage ) { m_ExplosionMagnitude = (int)flDamage; } - float GetExplosiveRadius( void ) { return m_explodeRadius; } - float GetExplosiveDamage( void ) { return m_ExplosionMagnitude; } - void SetPhysicsDamageTable( string_t iszTableName ) { m_iszPhysicsDamageTableName = iszTableName; } - string_t GetPhysicsDamageTable( void ) { return m_iszPhysicsDamageTableName; } - void SetBreakableModel( string_t iszModel ) { m_iszBreakableModel = iszModel; } - string_t GetBreakableModel( void ) { return m_iszBreakableModel; } - void SetBreakableSkin( int iSkin ) { m_iBreakableSkin = iSkin; } - int GetBreakableSkin( void ) { return m_iBreakableSkin; } - void SetBreakableCount( int iCount ) { m_iBreakableCount = iCount; } - int GetBreakableCount( void ) { return m_iBreakableCount; } - void SetMaxBreakableSize( int iSize ) { m_iMaxBreakableSize = iSize; } - int GetMaxBreakableSize( void ) { return m_iMaxBreakableSize; } - void SetPropDataBlocksLOS( bool bBlocksLOS ) { SetBlocksLOS( bBlocksLOS ); } - void SetPropDataIsAIWalkable( bool bBlocksLOS ) { SetAIWalkable( bBlocksLOS ); } - void SetBasePropData( string_t iszBase ) { m_iszBasePropData = iszBase; } - string_t GetBasePropData( void ) { return m_iszBasePropData; } - void SetInteraction( propdata_interactions_t Interaction ) { m_iInteractions |= (1 << Interaction); } - bool HasInteraction( propdata_interactions_t Interaction ) { return ( m_iInteractions & (1 << Interaction) ) != 0; } - void SetPhysicsMode(int iMode){} - int GetPhysicsMode() { return PHYSICS_MULTIPLAYER_SOLID; } - void SetMultiplayerBreakMode( mp_break_t mode ) {} - mp_break_t GetMultiplayerBreakMode( void ) const { return MULTIPLAYER_BREAK_DEFAULT; } - -protected: - float m_angle; - Materials m_Material; - EHANDLE m_hBreaker; // The entity that broke us. Held as a data member because sometimes breaking is delayed. - -private: - - Explosions m_Explosion; - QAngle m_GibDir; - string_t m_iszGibModel; - string_t m_iszSpawnObject; - int m_ExplosionMagnitude; - float m_flPressureDelay; // Delay before breaking when destoyed by pressure - int m_iMinHealthDmg; // minimum damage attacker must have to cause damage - bool m_bTookPhysicsDamage; - - string_t m_iszPropData; - string_t m_iszModelName; - -protected: - - bool UpdateHealth( int iNewHealth, CBaseEntity *pActivator ); - - float m_impactEnergyScale; - - COutputEvent m_OnBreak; - COutputFloat m_OnHealthChanged; - - // Prop data storage - float m_flDmgModBullet; - float m_flDmgModClub; - float m_flDmgModExplosive; - string_t m_iszPhysicsDamageTableName; - string_t m_iszBreakableModel; - int m_iBreakableSkin; - int m_iBreakableCount; - int m_iMaxBreakableSize; - string_t m_iszBasePropData; - int m_iInteractions; - PerformanceMode_t m_PerformanceMode; - - float m_explodeRadius; - -public: - // IPlayerPickupVPhysics - virtual void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ); - virtual void OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ); - virtual CBasePlayer *HasPhysicsAttacker( float dt ); -private: - CHandle m_hPhysicsAttacker; - float m_flLastPhysicsInfluenceTime; -}; - -#endif // FUNC_BREAK_H diff --git a/game/server/func_breakablesurf.cpp b/game/server/func_breakablesurf.cpp deleted file mode 100644 index 57ef622c7..000000000 --- a/game/server/func_breakablesurf.cpp +++ /dev/null @@ -1,1246 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: A planar textured surface that breaks into increasingly smaller fragments -// as it takes damage. Undamaged pieces remain attached to the world -// until they are damaged. Used for window panes. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ndebugoverlay.h" -#include "filters.h" -#include "player.h" -#include "func_breakablesurf.h" -#include "shattersurfacetypes.h" -#include "materialsystem/imaterialsystem.h" -#include "materialsystem/imaterial.h" -#include "materialsystem/imaterialvar.h" -#include "globals.h" -#include "physics_impact_damage.h" -#include "te_effect_dispatch.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// Spawn flags -#define SF_BREAKABLESURF_CRACK_DECALS 0x00000001 -#define SF_BREAKABLESURF_DAMAGE_FROM_HELD_OBJECTS 0x00000002 - -//############################################################################# -// > CWindowPane -//############################################################################# -#define WINDOW_PANEL_SIZE 12 -#define WINDOW_SMALL_SHARD_SIZE 4 -#define WINDOW_LARGE_SHARD_SIZE 7 -#define WINDOW_MAX_SUPPORT 6.75 -#define WINDOW_BREAK_SUPPORT 0.20 - -#define WINDOW_PANE_BROKEN -1 -#define WINDOW_PANE_HEALTHY 1 - -// Also defined in WC -#define QUAD_ERR_NONE 0 -#define QUAD_ERR_MULT_FACES 1 -#define QUAD_ERR_NOT_QUAD 2 - -// -// func_breakable - bmodel that breaks into pieces after taking damage -// -LINK_ENTITY_TO_CLASS( window_pane, CWindowPane ); -BEGIN_DATADESC( CWindowPane ) - - // Function Pointers - DEFINE_FUNCTION( Die ), - DEFINE_FUNCTION( PaneTouch ), - -END_DATADESC() - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CWindowPane::Spawn( void ) -{ - Precache( ); - - SetSolid( SOLID_BBOX ); - SetMoveType( MOVETYPE_FLYGRAVITY ); - m_takedamage = DAMAGE_YES; - - SetCollisionGroup( COLLISION_GROUP_BREAKABLE_GLASS ); - - SetModel( "models/brokenglass_piece.mdl" );//set size and link into world. -} - -void CWindowPane::Precache( void ) -{ - PrecacheModel( "models/brokenglass_piece.mdl" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pOther - -//----------------------------------------------------------------------------- -void CWindowPane::PaneTouch( CBaseEntity *pOther ) -{ - if (pOther && - pOther->GetCollisionGroup() != COLLISION_GROUP_BREAKABLE_GLASS) - { - Die(); - } -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CWindowPane::Die( void ) -{ - Vector flForce = -1 * GetAbsVelocity(); - - CPASFilter filter( GetAbsOrigin() ); - te->ShatterSurface( filter, 0.0, - &GetAbsOrigin(), &GetAbsAngles(), - &GetAbsVelocity(), &GetAbsOrigin(), - WINDOW_PANEL_SIZE, WINDOW_PANEL_SIZE,WINDOW_SMALL_SHARD_SIZE,SHATTERSURFACE_GLASS, - 255,255,255,255,255,255); - - UTIL_Remove(this); -} - -///------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -CWindowPane* CWindowPane::CreateWindowPane( const Vector &vecOrigin, const QAngle &vecAngles ) -{ - CWindowPane *pGlass = (CWindowPane*)CreateEntityByName( "window_pane" ); - if ( !pGlass ) - { - Msg( "NULL Ent in CreateWindowPane!\n" ); - return NULL; - } - - if ( pGlass->edict() ) - { - pGlass->SetLocalOrigin( vecOrigin ); - pGlass->SetLocalAngles( vecAngles ); - pGlass->Spawn(); - pGlass->SetTouch(&CWindowPane::PaneTouch); - pGlass->SetLocalAngularVelocity( RandomAngle(-50,50) ); - pGlass->m_nBody = random->RandomInt(0,2); - } - return pGlass; -} - - -//#################################################################################### -// > CBreakableSurface -//#################################################################################### -LINK_ENTITY_TO_CLASS( func_breakable_surf, CBreakableSurface ); - -BEGIN_DATADESC( CBreakableSurface ) - - DEFINE_KEYFIELD( m_nSurfaceType, FIELD_INTEGER, "surfacetype"), - DEFINE_KEYFIELD( m_nFragility, FIELD_INTEGER, "fragility"), - DEFINE_KEYFIELD( m_vLLVertex, FIELD_VECTOR, "lowerleft" ), - DEFINE_KEYFIELD( m_vULVertex, FIELD_VECTOR, "upperleft" ), - DEFINE_KEYFIELD( m_vLRVertex, FIELD_VECTOR, "lowerright" ), - DEFINE_KEYFIELD( m_vURVertex, FIELD_VECTOR, "upperright" ), - DEFINE_KEYFIELD( m_nQuadError, FIELD_INTEGER, "error" ), - - DEFINE_FIELD( m_nNumWide, FIELD_INTEGER), - DEFINE_FIELD( m_nNumHigh, FIELD_INTEGER), - DEFINE_FIELD( m_flPanelWidth, FIELD_FLOAT), - DEFINE_FIELD( m_flPanelHeight, FIELD_FLOAT), - DEFINE_FIELD( m_vNormal, FIELD_VECTOR), - DEFINE_FIELD( m_vCorner, FIELD_POSITION_VECTOR), - DEFINE_FIELD( m_bIsBroken, FIELD_BOOLEAN), - DEFINE_FIELD( m_nNumBrokenPanes, FIELD_INTEGER), - - // UNDONE: How to load save this? Need a way to update - // the client about the state of the window upon load... - // We should use client-side save/load to fix this problem. - DEFINE_AUTO_ARRAY2D( m_flSupport, FIELD_FLOAT), - DEFINE_ARRAY( m_RawPanelBitVec, FIELD_BOOLEAN, MAX_NUM_PANELS*MAX_NUM_PANELS ), - - // Function Pointers - DEFINE_THINKFUNC( BreakThink ), - DEFINE_ENTITYFUNC( SurfaceTouch ), - - DEFINE_INPUTFUNC( FIELD_VECTOR, "Shatter", InputShatter ), - - // DEFINE_FIELD( m_ForceUpdateClientData, CBitVec < MAX_PLAYERS > ), // No need to save/restore this, it's just a temporary flag field -END_DATADESC() - - -IMPLEMENT_SERVERCLASS_ST(CBreakableSurface, DT_BreakableSurface) - SendPropInt(SENDINFO(m_nNumWide), 8, SPROP_UNSIGNED), - SendPropInt(SENDINFO(m_nNumHigh), 8, SPROP_UNSIGNED), - SendPropFloat(SENDINFO(m_flPanelWidth), 0, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_flPanelHeight), 0, SPROP_NOSCALE), - SendPropVector(SENDINFO(m_vNormal), -1, SPROP_COORD), - SendPropVector(SENDINFO(m_vCorner), -1, SPROP_COORD), - SendPropInt(SENDINFO(m_bIsBroken), 1, SPROP_UNSIGNED), - SendPropInt(SENDINFO(m_nSurfaceType), 2, SPROP_UNSIGNED), - SendPropArray3(SENDINFO_ARRAY3(m_RawPanelBitVec), SendPropInt( SENDINFO_ARRAY( m_RawPanelBitVec ), 1, SPROP_UNSIGNED ) ), -END_SEND_TABLE() - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBreakableSurface::Precache(void) -{ - UTIL_PrecacheOther( "window_pane" ); - - // Load the edge types and styles for the specific surface type - if (m_nSurfaceType == SHATTERSURFACE_TILE) - { - PrecacheMaterial( "models/brokentile/tilebroken_03a" ); - PrecacheMaterial( "models/brokentile/tilebroken_03b" ); - PrecacheMaterial( "models/brokentile/tilebroken_03c" ); - PrecacheMaterial( "models/brokentile/tilebroken_03d" ); - - PrecacheMaterial( "models/brokentile/tilebroken_02a" ); - PrecacheMaterial( "models/brokentile/tilebroken_02b" ); - PrecacheMaterial( "models/brokentile/tilebroken_02c" ); - PrecacheMaterial( "models/brokentile/tilebroken_02d" ); - - PrecacheMaterial( "models/brokentile/tilebroken_01a" ); - PrecacheMaterial( "models/brokentile/tilebroken_01b" ); - PrecacheMaterial( "models/brokentile/tilebroken_01c" ); - PrecacheMaterial( "models/brokentile/tilebroken_01d" ); - } - else - { - PrecacheMaterial( "models/brokenglass/glassbroken_solid" ); - PrecacheMaterial( "models/brokenglass/glassbroken_01a" ); - PrecacheMaterial( "models/brokenglass/glassbroken_01b" ); - PrecacheMaterial( "models/brokenglass/glassbroken_01c" ); - PrecacheMaterial( "models/brokenglass/glassbroken_01d" ); - PrecacheMaterial( "models/brokenglass/glassbroken_02a" ); - PrecacheMaterial( "models/brokenglass/glassbroken_02b" ); - PrecacheMaterial( "models/brokenglass/glassbroken_02c" ); - PrecacheMaterial( "models/brokenglass/glassbroken_02d" ); - PrecacheMaterial( "models/brokenglass/glassbroken_03a" ); - PrecacheMaterial( "models/brokenglass/glassbroken_03b" ); - PrecacheMaterial( "models/brokenglass/glassbroken_03c" ); - PrecacheMaterial( "models/brokenglass/glassbroken_03d" ); - } - - BaseClass::Precache(); -} - - -//------------------------------------------------------------------------------ -// Purpose : Window has been touched. Break out pieces based on touching -// entity's bounding box -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBreakableSurface::SurfaceTouch( CBaseEntity *pOther ) -{ - // If tile only break if object is moving fast - if (m_nSurfaceType == SHATTERSURFACE_TILE) - { - Vector vVel; - pOther->GetVelocity( &vVel, NULL ); - if (vVel.Length() < 500) - { - return; - } - } - - // Find nearest point on plane for max - Vector vecAbsMins, vecAbsMaxs; - pOther->CollisionProp()->WorldSpaceAABB( &vecAbsMins, &vecAbsMaxs ); - Vector vToPlane = (vecAbsMaxs - m_vCorner); - float vDistToPlane = DotProduct(m_vNormal,vToPlane); - Vector vTouchPos = vecAbsMaxs + vDistToPlane*m_vNormal; - - float flMinsWidth,flMinsHeight; - PanePos(vTouchPos, &flMinsWidth, &flMinsHeight); - - // Find nearest point on plane for mins - vToPlane = (vecAbsMins - m_vCorner); - vDistToPlane = DotProduct(m_vNormal,vToPlane); - vTouchPos = vecAbsMins + vDistToPlane*m_vNormal; - - float flMaxsWidth,flMaxsHeight; - PanePos(vTouchPos, &flMaxsWidth, &flMaxsHeight); - - int nMinWidth = Floor2Int(MAX(0, MIN(flMinsWidth,flMaxsWidth))); - int nMaxWidth = Ceil2Int(fpmin(m_nNumWide,MAX(flMinsWidth,flMaxsWidth))); - - int nMinHeight = Floor2Int(MAX(0, MIN(flMinsHeight,flMaxsHeight))); - int nMaxHeight = Ceil2Int(fpmin(m_nNumHigh,MAX(flMinsHeight,flMaxsHeight))); - - Vector vHitVel; - pOther->GetVelocity( &vHitVel, NULL ); - - // Move faster then penetrating object so can see shards - vHitVel *= 5; - - // If I'm not broken yet, break me - if ( !m_bIsBroken ) - { - Die( pOther, vHitVel ); - } - - for (int height=nMinHeight;heightRandomInt(0,1)) - { - ShatterPane(nMinWidth-1, height,vHitVel,pOther->GetLocalOrigin()); - } - for (int width=nMinWidth;widthGetLocalOrigin()); - } - // Randomly break the one after so it doesn't look square - if (random->RandomInt(0,1)) - { - ShatterPane(nMaxWidth+1, height,vHitVel,pOther->GetLocalOrigin()); - } - } -} - -//------------------------------------------------------------------------------ -// Purpose : Only take damage in trace attack -// Input : -// Output : -//------------------------------------------------------------------------------ -int CBreakableSurface::OnTakeDamage( const CTakeDamageInfo &info ) -{ - if ( !m_bIsBroken && info.GetDamageType() == DMG_CRUSH ) - { - // physics will kill me now - Die( info.GetAttacker(), info.GetDamageForce() ); - return 0; - } - - if ( m_nSurfaceType == SHATTERSURFACE_GLASS && info.GetDamageType() & DMG_BLAST ) - { - Vector vecDir = info.GetInflictor()->GetAbsOrigin() - WorldSpaceCenter(); - VectorNormalize( vecDir ); - Die( info.GetAttacker(), vecDir ); - return 0; - } - - // Accept slash damage, too. Manhacks and such. - if ( m_nSurfaceType == SHATTERSURFACE_GLASS && (info.GetDamageType() & DMG_SLASH) ) - { - Die( info.GetAttacker(), info.GetDamageForce() ); - return 0; - } - - - return 0; -} - - -//------------------------------------------------------------------------------ -// Purpose: Accepts damage and breaks if health drops below zero. -//------------------------------------------------------------------------------ -void CBreakableSurface::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - // Decrease health - m_iHealth -= info.GetDamage(); - m_OnHealthChanged.Set( m_iHealth, info.GetAttacker(), this ); - - // If I'm not broken yet, break me - if (!m_bIsBroken ) - { - Vector vSurfDir = ptr->endpos - ptr->startpos; - Die( info.GetAttacker(), vSurfDir ); - } - - if (info.GetDamageType() & (DMG_BULLET | DMG_CLUB)) - { - // Figure out which panel has taken the damage and break it - float flWidth,flHeight; - PanePos(ptr->endpos,&flWidth,&flHeight); - int nWidth = (int)flWidth; - int nHeight = (int)flHeight; - - if ( ShatterPane(nWidth, nHeight,vecDir*500,ptr->endpos) ) - { - // Do an impact hit - CEffectData data; - - data.m_vNormal = ptr->plane.normal; - data.m_vOrigin = ptr->endpos; - - CPASFilter filter( data.m_vOrigin ); - - // client cannot trace against triggers - filter.SetIgnorePredictionCull( true ); - - te->DispatchEffect( filter, 0.0, data.m_vOrigin, "GlassImpact", data ); - } - - if (m_nSurfaceType == SHATTERSURFACE_GLASS) - { - // Break nearby panes if damages was near pane edge - float flWRem = flWidth - nWidth; - float flHRem = flHeight - nHeight; - - if (flWRem > 0.8 && nWidth != m_nNumWide-1) - { - ShatterPane(nWidth+1, nHeight,vecDir*500,ptr->endpos); - } - else if (flWRem < 0.2 && nWidth != 0) - { - ShatterPane(nWidth-1, nHeight,vecDir*500,ptr->endpos); - } - if (flHRem > 0.8 && nHeight != m_nNumHigh-1) - { - ShatterPane(nWidth, nHeight+1,vecDir*500,ptr->endpos); - } - else if (flHRem < 0.2 && nHeight != 0) - { - ShatterPane(nWidth, nHeight-1,vecDir*500,ptr->endpos); - } - - // Occasionally break the pane above me - if (random->RandomInt(0,1)==0) - { - ShatterPane(nWidth, nHeight+1,vecDir*1000,ptr->endpos); - // Occasionally break the pane above that - if (random->RandomInt(0,1)==0) - { - ShatterPane(nWidth, nHeight+2,vecDir*1000,ptr->endpos); - } - } - } - } - else if (info.GetDamageType() & (DMG_SONIC | DMG_BLAST)) - { - // ---------------------------------------- - // If it's tile blow out nearby tiles - // ---------------------------------------- - if (m_nSurfaceType == SHATTERSURFACE_TILE) - { - // Figure out which panel has taken the damage and break it - float flWidth,flHeight; - if (info.GetAttacker()) - { - PanePos(info.GetAttacker()->GetAbsOrigin(),&flWidth,&flHeight); - } - else - { - PanePos(ptr->endpos,&flWidth,&flHeight); - } - int nWidth = (int)flWidth; - int nHeight = (int)flHeight; - - // Blow out a roughly circular patch of tile with some randomness - for (int width =nWidth-4;widthRandomInt(2,5)) - { - ShatterPane(width, height,vecDir*500,ptr->endpos); - } - } - } - } - // ---------------------------------------- - // If it's glass blow out the whole window - // ---------------------------------------- - else - { - float flDot = DotProduct(m_vNormal,vecDir); - -#ifdef CSTRIKE_DLL - float damageMultiplier = info.GetDamage(); -#else - float damageMultiplier = 1.0f; -#endif - - Vector vBlastDir; - if (flDot > 0) - { - vBlastDir = damageMultiplier * 3000 * m_vNormal; - } - else - { - vBlastDir = damageMultiplier * -3000 * m_vNormal; - } - - // Has the window already been destroyed? - if (m_nNumBrokenPanes >= m_nNumWide*m_nNumHigh) - { - return; - } - // --------------------------------------------------------------- - // If less than 10% of my panels have been broken, blow me - // up in one large glass shatter - // --------------------------------------------------------------- - else if ( m_nNumBrokenPanes < 0.1*(m_nNumWide*m_nNumHigh)) - { - QAngle vAngles; - VectorAngles(-1*m_vNormal,vAngles); - - CreateShards(m_vCorner, vAngles,vBlastDir, ptr->endpos, - m_nNumWide*m_flPanelWidth, m_nNumHigh*m_flPanelHeight, WINDOW_LARGE_SHARD_SIZE); - } - // --------------------------------------------------------------- - // Otherwise break in the longest vertical strips possible - // (to cut down on the network bandwidth) - // --------------------------------------------------------------- - else - { - QAngle vAngles; - VectorAngles(-1*m_vNormal,vAngles); - Vector vWidthDir,vHeightDir; - AngleVectors(vAngles,NULL,&vWidthDir,&vHeightDir); - - for (int width=0;width 0) - { - Vector vBreakPos = m_vCorner + - (width*vWidthDir*m_flPanelWidth) + - ((height-nHCount)*vHeightDir*m_flPanelHeight); - - CreateShards(vBreakPos, vAngles, - vBlastDir, ptr->endpos, - m_flPanelWidth, nHCount*m_flPanelHeight, - WINDOW_LARGE_SHARD_SIZE); - - nHCount = 0; - } - } - if (nHCount) - { - Vector vBreakPos = m_vCorner + - (width*vWidthDir*m_flPanelWidth) + - ((height-nHCount)*vHeightDir*m_flPanelHeight); - - CreateShards(vBreakPos, vAngles, - vBlastDir, ptr->endpos, - m_flPanelWidth,nHCount*m_flPanelHeight, - WINDOW_LARGE_SHARD_SIZE); - } - } - } - - BreakAllPanes(); - } - } -} - -//------------------------------------------------------------------------------ -// Purpose: Break into panels -// Input : pBreaker - -// vDir - -//----------------------------------------------------------------------------- -void CBreakableSurface::Die( CBaseEntity *pBreaker, const Vector &vAttackDir ) -{ - if ( m_bIsBroken ) - return; - - // Play a break sound - PhysBreakSound( this, VPhysicsGetObject(), GetAbsOrigin() ); - - m_bIsBroken = true; - m_iHealth = 0.0f; - - if (pBreaker) - { - m_OnBreak.FireOutput( pBreaker, this ); - } - else - { - m_OnBreak.FireOutput( this, this ); - } - - float flDir = -1; - - if ( vAttackDir.LengthSqr() > 0.001 ) - { - float flDot = DotProduct( m_vNormal, vAttackDir ); - if (flDot < 0) - { - m_vLLVertex += m_vNormal; - m_vLRVertex += m_vNormal; - m_vULVertex += m_vNormal; - m_vURVertex += m_vNormal; - m_vNormal *= -1; - flDir = 1; - } - } - - // ------------------------------------------------------- - // The surface has two sides, when we are killed pick - // the side that the damage came from - // ------------------------------------------------------- - Vector vWidth = m_vLLVertex - m_vLRVertex; - Vector vHeight = m_vLLVertex - m_vULVertex; - CrossProduct( vWidth, vHeight, m_vNormal.GetForModify() ); - VectorNormalize(m_vNormal.GetForModify()); - - // --------------------------------------------------- - // Make sure width and height are oriented correctly - // --------------------------------------------------- - QAngle vAngles; - VectorAngles(-1*m_vNormal,vAngles); - Vector vWidthDir,vHeightDir; - AngleVectors(vAngles,NULL,&vWidthDir,&vHeightDir); - - float flWDist = DotProduct(vWidthDir,vWidth); - if (fabs(flWDist)<0.5) - { - Vector vSaveHeight = vHeight; - vHeight = vWidth * flDir; - vWidth = vSaveHeight * flDir; - } - - // ------------------------------------------------- - // Find which corner to use - // ------------------------------------------------- - bool bLeft = (DotProduct(vWidthDir,vWidth) < 0); - bool bLower = (DotProduct(vHeightDir,vHeight) < 0); - if (bLeft) - { - m_vCorner = bLower ? m_vLLVertex : m_vULVertex; - } - else - { - m_vCorner = bLower ? m_vLRVertex : m_vURVertex; - } - - // ------------------------------------------------- - // Calculate the number of panels - // ------------------------------------------------- - float flWidth = vWidth.Length(); - float flHeight = vHeight.Length(); - m_nNumWide = flWidth / WINDOW_PANEL_SIZE; - m_nNumHigh = flHeight / WINDOW_PANEL_SIZE; - - // If to many panels make panel size bigger - if (m_nNumWide > MAX_NUM_PANELS) m_nNumWide = MAX_NUM_PANELS; - if (m_nNumHigh > MAX_NUM_PANELS) m_nNumHigh = MAX_NUM_PANELS; - - m_flPanelWidth = flWidth / m_nNumWide; - m_flPanelHeight = flHeight / m_nNumHigh; - - // Initialize panels - for (int w=0;w m_nNumWide) - nMaxX = m_nNumWide; - - int nMinY = (int)(flCenterY - vecShatterInfo.z / m_flPanelHeight); - int nMaxY = (int)(flCenterY + vecShatterInfo.z / m_flPanelHeight) + 1; - - if (nMinY < 0) - nMinY = 0; - if (nMaxY > m_nNumHigh) - nMaxY = m_nNumHigh; - - QAngle vAngles; - VectorAngles(-1*m_vNormal,vAngles); - Vector vWidthDir,vHeightDir; - AngleVectors(vAngles,NULL,&vWidthDir,&vHeightDir); - - // Blow out a roughly circular of tile with some randomness - Vector2D vecActualCenter( flCenterX * m_flPanelWidth, flCenterY * m_flPanelHeight ); - for (int width = nMinX; width < nMaxX; width++) - { - for (int height = nMinY; height < nMaxY; height++) - { - Vector2D pt( (width + 0.5f) * m_flPanelWidth, (height + 0.5f) * m_flPanelWidth ); - if ( pt.DistToSqr(vecActualCenter) <= vecShatterInfo.z * vecShatterInfo.z ) - { - Vector vBreakPos = m_vCorner + - (width*vWidthDir*m_flPanelWidth) + - (height*vHeightDir*m_flPanelHeight); - - ShatterPane( width, height, m_vNormal * 500, vBreakPos ); - } - } - } -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBreakableSurface::Event_Killed( CBaseEntity *pInflictor, CBaseEntity *pAttacker, float flDamage, int bitsDamageType ) -{ - return; -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -bool CBreakableSurface::IsBroken(int nWidth, int nHeight) -{ - if (nWidth < 0 || nWidth >= m_nNumWide) return true; - if (nHeight < 0 || nHeight >= m_nNumHigh) return true; - - return (m_flSupport[nWidth][nHeight]==WINDOW_PANE_BROKEN); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : w - -// h - -// support - -//----------------------------------------------------------------------------- -void CBreakableSurface::SetSupport( int w, int h, float support ) -{ - m_flSupport[ w ][ h ] = support; - - int offset = w + h * m_nNumWide; - - bool prevval = m_RawPanelBitVec.Get( offset ); - bool curval = prevval; - - if ( support < 0.0f ) - { - curval = false; - } - else - { - curval = true; - } - if ( curval != prevval ) - { - m_RawPanelBitVec.Set( offset, curval ); - m_RawPanelBitVec.GetForModify( offset ); - } -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -float CBreakableSurface::GetSupport(int nWidth, int nHeight) -{ - return MAX(0,m_flSupport[nWidth][nHeight]); -} - -//------------------------------------------------------------------------------ -// Purpose : Return the structural support for this pane. Assumes window -// is upright. Still works for windows parallel to the ground -// but simulation isn't quite as good -// Input : -// Output : -//------------------------------------------------------------------------------ -float CBreakableSurface::RecalcSupport(int nWidth, int nHeight) -{ - // Always has some support. Zero signifies that it has been broken - float flSupport = 0.01; - - // ------------ - // Top support - // ------------ - if (nHeight == m_nNumHigh-1) - { - flSupport += 1.0; - } - else - { - flSupport += GetSupport(nWidth,nHeight+1); - } - - // ------------ - // Bottom Support - // ------------ - if (nHeight == 0) - { - flSupport += 1.25; - } - else - { - flSupport += 1.25 * GetSupport(nWidth,nHeight-1); - } - - // ------------ - // Left Support - // ------------ - if (nWidth == 0) - { - flSupport += 1.0; - } - else - { - flSupport += GetSupport(nWidth-1,nHeight); - } - - // -------------- - // Right Support - // -------------- - if (nWidth == m_nNumWide-1) - { - flSupport += 1.0; - } - else - { - flSupport += GetSupport(nWidth+1,nHeight); - } - - // -------------------- - // Bottom Left Support - // -------------------- - if (nHeight == 0 || nWidth == 0) - { - flSupport += 1.0; - } - else - { - flSupport += GetSupport(nWidth-1,nHeight-1); - } - - // --------------------- - // Bottom Right Support - // --------------------- - if (nHeight == 0 || nWidth == m_nNumWide-1) - { - flSupport += 1.0; - } - else - { - flSupport += GetSupport(nWidth+1,nHeight-1); - } - - // ----------------- - // Top Right Support - // ----------------- - if (nHeight == m_nNumHigh-1 || nWidth == m_nNumWide-1) - { - flSupport += 0.25; - } - else - { - flSupport += 0.25 * GetSupport(nWidth+1,nHeight+1); - } - - // ----------------- - // Top Left Support - // ----------------- - if (nHeight == m_nNumHigh-1 || nWidth == 0) - { - flSupport += 0.25; - } - else - { - flSupport += 0.25 * GetSupport(nWidth-1,nHeight+1); - } - - return flSupport; -} - - -//------------------------------------------------------------------------------ -// Purpose : Itterate through the panels and make sure none have become -// unstable -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBreakableSurface::BreakThink(void) -{ - // Don't calculate support if I'm tile - if (m_nSurfaceType == SHATTERSURFACE_TILE) - { - return; - } - - // ----------------------- - // Recalculate all support - // ----------------------- - int w; - float flSupport[MAX_NUM_PANELS][MAX_NUM_PANELS]; - for (w=0;wRandomInt(0,1)) - { - DropPane(w,h); - } - // Otherwise just shatter the glass - else - { - ShatterPane(w,h,vec3_origin,vec3_origin); - } - SetNextThink( gpGlobals->curtime ); - } - } - } - } -} - -//------------------------------------------------------------------------------ -// Purpose : Given a 3D position on the window in space return the height and -// width of the position from the window's corner -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBreakableSurface::PanePos(const Vector &vPos, float *flWidth, float *flHeight) -{ - Vector vAttackVec = vPos - m_vCorner; - QAngle vAngles; - VectorAngles(-1*m_vNormal,vAngles); - Vector vWidthDir,vHeightDir; - AngleVectors(vAngles,NULL,&vWidthDir,&vHeightDir); - float flWDist = DotProduct(vWidthDir,vAttackVec); - float flHDist = DotProduct(vHeightDir,vAttackVec); - - // Figure out which quadrent I'm in - *flWidth = flWDist/m_flPanelWidth; - *flHeight = flHDist/m_flPanelHeight; -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBreakableSurface::BreakAllPanes(void) -{ - // Now tell the client all the panes have been broken - for (int width=0;width= m_nNumWide) return; - if (nHeight < 0 || nHeight >= m_nNumHigh) return; - - // Count how many panes have been broken or dropped - m_nNumBrokenPanes++; - SetSupport( nWidth, nHeight, WINDOW_PANE_BROKEN ); - - SetThink(&CBreakableSurface::BreakThink); - SetNextThink( gpGlobals->curtime ); -} - -//------------------------------------------------------------------------------ -// Purpose : Drop a window pane entity -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBreakableSurface::DropPane(int nWidth, int nHeight) -{ - // Check parameter range - if (nWidth < 0 || nWidth >= m_nNumWide) return; - if (nHeight < 0 || nHeight >= m_nNumHigh) return; - - if (!IsBroken(nWidth,nHeight)) - { - BreakPane(nWidth,nHeight); - - QAngle vAngles; - VectorAngles(-1*m_vNormal,vAngles); - - Vector vWidthDir,vHeightDir; - AngleVectors(vAngles,NULL,&vWidthDir,&vHeightDir); - Vector vBreakPos = m_vCorner + - (nWidth*vWidthDir*m_flPanelWidth) + - (nHeight*vHeightDir*m_flPanelHeight); - - CreateShards(vBreakPos, vAngles, vec3_origin, vec3_origin, - WINDOW_PANEL_SIZE, WINDOW_PANEL_SIZE, - WINDOW_SMALL_SHARD_SIZE); - - DamageSound(); - - CWindowPane *pPane = CWindowPane::CreateWindowPane(vBreakPos, vAngles); - if (pPane) - { - pPane->SetLocalAngularVelocity( RandomAngle(-120,120) ); - } - } -} - -void CBreakableSurface::CreateShards(const Vector &vBreakPos, const QAngle &vAngles, - const Vector &vForce, const Vector &vForcePos, - float flWidth, float flHeight, - int nShardSize) -{ - Vector vAdjustedBreakPos = vBreakPos; - Vector vAdjustedForce = vForce; - int front_r,front_g,front_b; - int back_r,back_g,back_b; - - - // UNDONE: For now hardcode these colors. Later when used by more textures - // we'll automate this process or expose the colors in WC - if (m_nSurfaceType == SHATTERSURFACE_TILE) - { - // If tile shoot shards back from the shattered surface and offset slightly - // from the surface. - vAdjustedBreakPos -= 8*m_vNormal; - vAdjustedForce = -0.75*vForce; - front_r = 89; - front_g = 120; - front_b = 83; - back_r = 99; - back_g = 76; - back_b = 21; - } - else - { - front_r = 255; - front_g = 255; - front_b = 255; - back_r = 255; - back_g = 255; - back_b = 255; - } - - CPASFilter filter( vAdjustedBreakPos ); - te->ShatterSurface(filter, 0.0, - &vAdjustedBreakPos, &vAngles, - &vAdjustedForce, &vForcePos, - flWidth, flHeight,WINDOW_SMALL_SHARD_SIZE,m_nSurfaceType, - front_r,front_g,front_b,back_r,back_g,back_b);//4); -} - -//------------------------------------------------------------------------------ -// Purpose : Break a panel -// Input : -// Output : -//------------------------------------------------------------------------------ -bool CBreakableSurface::ShatterPane(int nWidth, int nHeight, const Vector &vForce, const Vector &vForcePos) -{ - // Check parameter range - if (nWidth < 0 || nWidth >= m_nNumWide) return false; - if (nHeight < 0 || nHeight >= m_nNumHigh) return false; - - if ( IsBroken(nWidth,nHeight) ) - return false; - - BreakPane(nWidth,nHeight); - - QAngle vAngles; - VectorAngles(-1*m_vNormal,vAngles); - Vector vWidthDir,vHeightDir; - AngleVectors(vAngles,NULL,&vWidthDir,&vHeightDir); - Vector vBreakPos = m_vCorner + - (nWidth*vWidthDir*m_flPanelWidth) + - (nHeight*vHeightDir*m_flPanelHeight); - - CreateShards(vBreakPos, vAngles,vForce, vForcePos, m_flPanelWidth, m_flPanelHeight, WINDOW_SMALL_SHARD_SIZE); - - DamageSound(); - return true; -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBreakableSurface::Spawn(void) -{ - BaseClass::Spawn(); - SetCollisionGroup( COLLISION_GROUP_BREAKABLE_GLASS ); - m_bIsBroken = false; - - if (m_nQuadError == QUAD_ERR_MULT_FACES) - { - Warning("Rejecting func_breakablesurf. Has multiple faces that aren't NODRAW.\n"); - UTIL_Remove(this); - } - else if (m_nQuadError == QUAD_ERR_NOT_QUAD) - { - Warning("Rejecting func_breakablesurf. Drawn face isn't a quad.\n"); - UTIL_Remove(this); - } - - int materialCount = modelinfo->GetModelMaterialCount( const_cast(GetModel()) ); - if( materialCount != 1 ) - { - Warning( "Encountered func_breakablesurf that has a material applied to more than one surface!\n" ); - UTIL_Remove(this); - } - - // Get at the first material; even if there are more than one. - IMaterial* pMaterial; - modelinfo->GetModelMaterials( const_cast(GetModel()), 1, &pMaterial ); - - // The material should point to a cracked version of itself - bool foundVar; - IMaterialVar* pCrackName = pMaterial->FindVar( "$crackmaterial", &foundVar, false ); - if (foundVar) - { - PrecacheMaterial( pCrackName->GetStringValue() ); - } - - // Init the Panel bit vector to all true. ( no panes are broken ) - int bitVecLength = MAX_NUM_PANELS * MAX_NUM_PANELS; - - for( int i=0;i 10 ) - { - // HACKHACK: Reset mass to get correct collision response for the object breaking this - pEvent->pObjects[index]->SetMass( 2.0f ); - - Vector normal, damagePos; - pEvent->pInternalData->GetSurfaceNormal( normal ); - if ( index == 0 ) - { - normal *= -1.0f; - } - pEvent->pInternalData->GetContactPoint( damagePos ); - int otherIndex = !index; - CBaseEntity *pInflictor = pEvent->pEntities[otherIndex]; - CTakeDamageInfo info( pInflictor, pInflictor, normal, damagePos, damage, damageType ); - PhysCallbackDamage( this, info, *pEvent, index ); - } - else if ( damage > 0 ) - { - if ( m_spawnflags & SF_BREAKABLESURF_CRACK_DECALS ) - { - - Vector normal, damagePos; - pEvent->pInternalData->GetSurfaceNormal( normal ); - if ( index == 0 ) - { - normal *= -1.0f; - } - pEvent->pInternalData->GetContactPoint( damagePos ); - - trace_t tr; - UTIL_TraceLine ( damagePos - normal, damagePos + normal, MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr ); - - // Only place decals and draw effects if we hit something valid - if ( tr.m_pEnt && tr.m_pEnt == this ) - { - // Build the impact data - CEffectData data; - data.m_vOrigin = tr.endpos; - data.m_vStart = tr.startpos; - data.m_nSurfaceProp = tr.surface.surfaceProps; - data.m_nDamageType = DMG_CLUB; - data.m_nHitBox = tr.hitbox; - data.m_nEntIndex = entindex(); - - // Send it on its way - DispatchEffect( "Impact", data ); - } - } - } - } - BaseClass::VPhysicsCollision( index, pEvent ); -} - diff --git a/game/server/func_breakablesurf.h b/game/server/func_breakablesurf.h deleted file mode 100644 index 7dc399b64..000000000 --- a/game/server/func_breakablesurf.h +++ /dev/null @@ -1,102 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef FUNC_BREAKABLESURF_H -#define FUNC_BREAKABLESURF_H -#ifdef _WIN32 -#pragma once -#endif - - -#define MAX_NUM_PANELS 16 //Must match client - -#include "func_break.h" - -//############################################################################# -// > CWindowPane -// -// A piece that falls out of the window -//############################################################################# -class CWindowPane : public CBaseAnimating -{ -public: - DECLARE_CLASS( CWindowPane, CBaseAnimating ); - - static CWindowPane* CreateWindowPane( const Vector &vecOrigin, const QAngle &vecAngles ); - - void Spawn( void ); - void Precache( void ); - void PaneTouch( CBaseEntity *pOther ); - void Die( void ); - DECLARE_DATADESC(); -}; - -//############################################################################# -// > CBreakableSurface -// -// A breakable surface -//############################################################################# -class CBreakableSurface : public CBreakable -{ - DECLARE_CLASS( CBreakableSurface, CBreakable ); - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - -public: - CNetworkVar( int, m_nNumWide ); - CNetworkVar( int, m_nNumHigh ); - CNetworkVar( float, m_flPanelWidth ); - CNetworkVar( float, m_flPanelHeight ); - CNetworkVector( m_vNormal ); - CNetworkVector( m_vCorner ); - CNetworkVar( bool, m_bIsBroken ); - CNetworkVar( ShatterSurface_t, m_nSurfaceType ); - int m_nNumBrokenPanes; - float m_flSupport[MAX_NUM_PANELS][MAX_NUM_PANELS]; //UNDONE: allocate dynamically? - - int m_nFragility; - Vector m_vLLVertex; - Vector m_vULVertex; - Vector m_vLRVertex; - Vector m_vURVertex; - int m_nQuadError; - - void SurfaceTouch( CBaseEntity *pOther ); - void PanePos(const Vector &vPos, float *flWidth, float *flHeight); - - bool IsBroken(int nWidth, int nHeight); - void SetSupport(int w, int h, float support); - - float GetSupport(int nWidth, int nHeight); - float RecalcSupport(int nWidth, int nHeight); - - void BreakPane(int nWidth, int nHeight); - void DropPane(int nWidth, int nHeight); - bool ShatterPane(int nWidth, int nHeight, const Vector &force, const Vector &vForcePos); - void BreakAllPanes(void); - - void CreateShards(const Vector &vBreakPos, const QAngle &vAngles, - const Vector &vForce, const Vector &vForcePos, - float flWidth, float flHeight, - int nShardSize); - - void Spawn(void); - void Precache(void); - void Die( CBaseEntity *pBreaker, const Vector &vAttackDir ); - void BreakThink(void); - void Event_Killed( CBaseEntity *pInflictor, CBaseEntity *pAttacker, float flDamage, int bitsDamageType ); - void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - int OnTakeDamage( const CTakeDamageInfo &info ); - void InputShatter( inputdata_t &inputdata ); - void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); -private: - // One bit per pane - CNetworkArray( bool, m_RawPanelBitVec, MAX_NUM_PANELS * MAX_NUM_PANELS ); -}; - -#endif // FUNC_BREAKABLESURF_H - diff --git a/game/server/func_dust.cpp b/game/server/func_dust.cpp deleted file mode 100644 index 5cb544db3..000000000 --- a/game/server/func_dust.cpp +++ /dev/null @@ -1,332 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Volumetric dust motes. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "func_dust_shared.h" -#include "te_particlesystem.h" -#include "IEffects.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CFunc_Dust : public CBaseEntity -{ -public: - DECLARE_CLASS( CFunc_Dust, CBaseEntity ); - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - CFunc_Dust(); - virtual ~CFunc_Dust(); - - -// CBaseEntity overrides. -public: - - virtual void Spawn(); - virtual void Activate(); - virtual void Precache(); - virtual bool KeyValue( const char *szKeyName, const char *szValue ); - - -// Input handles. -public: - - void InputTurnOn( inputdata_t &inputdata ); - void InputTurnOff( inputdata_t &inputdata ); - - -// FGD properties. -public: - - CNetworkVar( color32, m_Color ); - CNetworkVar( int, m_SpawnRate ); - - CNetworkVar( float, m_flSizeMin ); - CNetworkVar( float, m_flSizeMax ); - - CNetworkVar( int, m_SpeedMax ); - - CNetworkVar( int, m_LifetimeMin ); - CNetworkVar( int, m_LifetimeMax ); - - CNetworkVar( int, m_DistMax ); - - CNetworkVar( float, m_FallSpeed ); - -public: - - CNetworkVar( int, m_DustFlags ); // Combination of DUSTFLAGS_ - -private: - int m_iAlpha; - -}; - - -class CFunc_DustMotes : public CFunc_Dust -{ - DECLARE_CLASS( CFunc_DustMotes, CFunc_Dust ); -public: - CFunc_DustMotes(); -}; - - -class CFunc_DustCloud : public CFunc_Dust -{ - DECLARE_CLASS( CFunc_DustCloud, CFunc_Dust ); -public: -}; - -IMPLEMENT_SERVERCLASS_ST_NOBASE( CFunc_Dust, DT_Func_Dust ) - SendPropInt( SENDINFO(m_Color), 32, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_SpawnRate), 12, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_SpeedMax), 12, SPROP_UNSIGNED ), - SendPropFloat( SENDINFO(m_flSizeMin), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO(m_flSizeMax), 0, SPROP_NOSCALE ), - SendPropInt( SENDINFO(m_DistMax), 16, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_LifetimeMin), 4, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_LifetimeMax), 4, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_DustFlags), DUST_NUMFLAGS, SPROP_UNSIGNED ), - - SendPropModelIndex( SENDINFO(m_nModelIndex) ), - SendPropFloat( SENDINFO(m_FallSpeed), 0, SPROP_NOSCALE ), - SendPropDataTable( SENDINFO_DT( m_Collision ), &REFERENCE_SEND_TABLE(DT_CollisionProperty) ), -END_SEND_TABLE() - - -BEGIN_DATADESC( CFunc_Dust ) - - DEFINE_FIELD( m_DustFlags,FIELD_INTEGER ), - - DEFINE_KEYFIELD( m_Color, FIELD_COLOR32, "Color" ), - DEFINE_KEYFIELD( m_SpawnRate, FIELD_INTEGER, "SpawnRate" ), - DEFINE_KEYFIELD( m_flSizeMin, FIELD_FLOAT, "SizeMin" ), - DEFINE_KEYFIELD( m_flSizeMax, FIELD_FLOAT, "SizeMax" ), - DEFINE_KEYFIELD( m_SpeedMax, FIELD_INTEGER, "SpeedMax" ), - DEFINE_KEYFIELD( m_LifetimeMin, FIELD_INTEGER, "LifetimeMin" ), - DEFINE_KEYFIELD( m_LifetimeMax, FIELD_INTEGER, "LifetimeMax" ), - DEFINE_KEYFIELD( m_DistMax, FIELD_INTEGER, "DistMax" ), - DEFINE_FIELD( m_iAlpha, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_FallSpeed, FIELD_FLOAT, "FallSpeed" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ) - - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( func_dustmotes, CFunc_DustMotes ); -LINK_ENTITY_TO_CLASS( func_dustcloud, CFunc_DustCloud ); - - -// ------------------------------------------------------------------------------------- // -// CFunc_DustMotes implementation. -// ------------------------------------------------------------------------------------- // - -CFunc_DustMotes::CFunc_DustMotes() -{ - m_DustFlags |= DUSTFLAGS_SCALEMOTES; -} - - - -// ------------------------------------------------------------------------------------- // -// CFunc_Dust implementation. -// ------------------------------------------------------------------------------------- // - -CFunc_Dust::CFunc_Dust() -{ - m_DustFlags = DUSTFLAGS_ON; - m_FallSpeed = 0.0f; -} - - -CFunc_Dust::~CFunc_Dust() -{ -} - - -void CFunc_Dust::Spawn() -{ - Precache(); - - // Bind to our bmodel. - SetModel( STRING( GetModelName() ) ); - //AddSolidFlags( FSOLID_NOT_SOLID ); - AddSolidFlags( FSOLID_VOLUME_CONTENTS ); - - //Since keyvalues can arrive in any order, and UTIL_StringToColor32 stomps alpha, - //install the alpha value here. - color32 clr = { m_Color.m_Value.r, m_Color.m_Value.g, m_Color.m_Value.b, m_iAlpha }; - m_Color.Set( clr ); - - BaseClass::Spawn(); -} - - -void CFunc_Dust::Precache() -{ - PrecacheMaterial( "particle/sparkles" ); -} - -void CFunc_Dust::Activate() -{ - BaseClass::Activate(); -} - - -bool CFunc_Dust::KeyValue( const char *szKeyName, const char *szValue ) -{ - if( stricmp( szKeyName, "StartDisabled" ) == 0 ) - { - if( szValue[0] == '1' ) - m_DustFlags &= ~DUSTFLAGS_ON; - else - m_DustFlags |= DUSTFLAGS_ON; - - return true; - } - else if( stricmp( szKeyName, "Alpha" ) == 0 ) - { - m_iAlpha = atoi( szValue ); - return true; - } - else if( stricmp( szKeyName, "Frozen" ) == 0 ) - { - if( szValue[0] == '1' ) - m_DustFlags |= DUSTFLAGS_FROZEN; - else - m_DustFlags &= ~DUSTFLAGS_FROZEN; - - return true; - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } -} - - -void CFunc_Dust::InputTurnOn( inputdata_t &inputdata ) -{ - if( !(m_DustFlags & DUSTFLAGS_ON) ) - { - m_DustFlags |= DUSTFLAGS_ON; - } -} - - -void CFunc_Dust::InputTurnOff( inputdata_t &inputdata ) -{ - if( m_DustFlags & DUSTFLAGS_ON ) - { - m_DustFlags &= ~DUSTFLAGS_ON; - } -} - -// -// Dust -// - -class CTEDust : public CTEParticleSystem -{ -public: - DECLARE_CLASS( CTEDust, CTEParticleSystem ); - DECLARE_SERVERCLASS(); - - CTEDust( const char *name ); - virtual ~CTEDust( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ) { }; - - CNetworkVar( float, m_flSize ); - CNetworkVar( float, m_flSpeed ); - CNetworkVector( m_vecDirection ); -}; - -CTEDust::CTEDust( const char *name ) : BaseClass( name ) -{ - m_flSize = 1.0f; - m_flSpeed = 1.0f; - m_vecDirection.Init(); -} - -CTEDust::~CTEDust( void ) -{ -} - -IMPLEMENT_SERVERCLASS_ST( CTEDust, DT_TEDust ) - SendPropFloat( SENDINFO(m_flSize), -1, SPROP_COORD ), - SendPropFloat( SENDINFO(m_flSpeed), -1, SPROP_COORD ), - SendPropVector( SENDINFO(m_vecDirection), 4, 0, -1.0f, 1.0f ), // cheap normal -END_SEND_TABLE() - -static CTEDust g_TEDust( "Dust" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &pos - -// &angles - -//----------------------------------------------------------------------------- -void TE_Dust( IRecipientFilter& filter, float delay, - const Vector &pos, const Vector &dir, float size, float speed ) -{ - g_TEDust.m_vecOrigin = pos; - g_TEDust.m_vecDirection = dir; - g_TEDust.m_flSize = size; - g_TEDust.m_flSpeed = speed; - - Assert( dir.Length() < 1.01 ); // make sure it's a normal - - //Send it - g_TEDust.Create( filter, delay ); -} - -class CEnvDustPuff : public CPointEntity -{ - DECLARE_CLASS( CEnvDustPuff, CPointEntity ); - -public: - - DECLARE_DATADESC(); - -protected: - - // Input handlers - void InputSpawnDust( inputdata_t &inputdata ); - - float m_flScale; - color32 m_rgbaColor; -}; - -LINK_ENTITY_TO_CLASS( env_dustpuff, CEnvDustPuff ); - -BEGIN_DATADESC( CEnvDustPuff ) - - DEFINE_KEYFIELD( m_flScale, FIELD_FLOAT, "scale" ), - DEFINE_KEYFIELD( m_rgbaColor, FIELD_COLOR32, "color" ), - - // Function Pointers - DEFINE_INPUTFUNC( FIELD_VOID, "SpawnDust", InputSpawnDust ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CEnvDustPuff::InputSpawnDust( inputdata_t &inputdata ) -{ - Vector dir; - AngleVectors( GetAbsAngles(), &dir ); - - VectorNormalize( dir ); - - g_pEffects->Dust( GetAbsOrigin(), dir, m_flScale, m_flSpeed ); -} diff --git a/game/server/func_ladder_endpoint.cpp b/game/server/func_ladder_endpoint.cpp deleted file mode 100644 index f1f144f00..000000000 --- a/game/server/func_ladder_endpoint.cpp +++ /dev/null @@ -1,68 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// -#include "cbase.h" -#include "func_ladder.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: A transient entity used to construct a true CFuncLadder -// FIXME: THIS ENTITY IS OBSOLETE NOW, SHOULD BE REMOVED FROM HERE AND .FGD AT SOME POINT!!! -//----------------------------------------------------------------------------- -class CFuncLadderEndPoint : public CBaseEntity -{ -public: - DECLARE_CLASS( CFuncLadderEndPoint, CBaseEntity ); - - virtual void Activate(); - -private: - bool Validate(); -}; - -LINK_ENTITY_TO_CLASS( func_ladderendpoint, CFuncLadderEndPoint ); - -void CFuncLadderEndPoint::Activate() -{ - BaseClass::Activate(); - - if ( IsMarkedForDeletion() ) - return; - - Validate(); -} - -bool CFuncLadderEndPoint::Validate() -{ - // Find the the other end - Vector startPos = GetAbsOrigin(); - - CFuncLadderEndPoint *other = dynamic_cast< CFuncLadderEndPoint * >( GetNextTarget() ); - if ( !other ) - { - DevMsg( 1, "func_ladderendpoint(%s) without matching target\n", GetEntityName().ToCStr() ); - return false; - } - - Vector endPos = other->GetAbsOrigin(); - - CFuncLadder *ladder = ( CFuncLadder * )CreateEntityByName( "func_useableladder" ); - if ( ladder ) - { - ladder->SetEndPoints( startPos, endPos ); - ladder->SetAbsOrigin( GetAbsOrigin() ); - ladder->SetParent( GetParent() ); - ladder->SetName( GetEntityName() ); - ladder->Spawn(); - } - - // Delete both endpoints - UTIL_Remove( other ); - UTIL_Remove( this ); - - return true; -} diff --git a/game/server/func_lod.cpp b/game/server/func_lod.cpp deleted file mode 100644 index e5a02749e..000000000 --- a/game/server/func_lod.cpp +++ /dev/null @@ -1,115 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include "cbase.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CFunc_LOD : public CBaseEntity -{ - DECLARE_DATADESC(); - DECLARE_CLASS( CFunc_LOD, CBaseEntity ); -public: - DECLARE_SERVERCLASS(); - - CFunc_LOD(); - virtual ~CFunc_LOD(); - - - // When the viewer is between: - // (0 and m_fNonintrusiveDist): the bmodel is forced to be visible - // (m_fNonintrusiveDist and m_fDisappearDist): the bmodel is trying to appear or disappear nonintrusively - // (waits until it's out of the view frustrum or until there's a lot of motion) - // (m_fDisappearDist+): the bmodel is forced to be invisible - CNetworkVar( float, m_fDisappearDist ); - -// CBaseEntity overrides. -public: - - virtual void Spawn(); - bool CreateVPhysics(); - virtual void Activate(); - virtual bool KeyValue( const char *szKeyName, const char *szValue ); -}; - - -IMPLEMENT_SERVERCLASS_ST(CFunc_LOD, DT_Func_LOD) - SendPropFloat(SENDINFO(m_fDisappearDist), 0, SPROP_NOSCALE), -END_SEND_TABLE() - - -LINK_ENTITY_TO_CLASS(func_lod, CFunc_LOD); - - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CFunc_LOD ) - - DEFINE_FIELD( m_fDisappearDist, FIELD_FLOAT ), - -END_DATADESC() - - -// ------------------------------------------------------------------------------------- // -// CFunc_LOD implementation. -// ------------------------------------------------------------------------------------- // -CFunc_LOD::CFunc_LOD() -{ -} - - -CFunc_LOD::~CFunc_LOD() -{ -} - - -void CFunc_LOD::Spawn() -{ - // Bind to our bmodel. - SetModel( STRING( GetModelName() ) ); - SetSolid( SOLID_BSP ); - BaseClass::Spawn(); - - CreateVPhysics(); -} - -bool CFunc_LOD::CreateVPhysics() -{ - VPhysicsInitStatic(); - return true; -} - -void CFunc_LOD::Activate() -{ - BaseClass::Activate(); -} - - -bool CFunc_LOD::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "DisappearDist")) - { - m_fDisappearDist = (float)atof(szValue); - } - else if (FStrEq(szKeyName, "Solid")) - { - if (atoi(szValue) != 0) - { - AddSolidFlags( FSOLID_NOT_SOLID ); - } - } - else - { - return BaseClass::KeyValue(szKeyName, szValue); - } - - return true; -} - diff --git a/game/server/func_movelinear.cpp b/game/server/func_movelinear.cpp deleted file mode 100644 index d067f54b2..000000000 --- a/game/server/func_movelinear.cpp +++ /dev/null @@ -1,390 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements a brush model entity that moves along a linear path. -// Water whose level can be changed is implemented using the same entity. -// -//=============================================================================// - -#include "cbase.h" -#include "func_movelinear.h" -#include "entitylist.h" -#include "locksounds.h" -#include "ndebugoverlay.h" -#include "engine/IEngineSound.h" -#include "physics_saverestore.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// ------------------------------- -// SPAWN_FLAGS -// ------------------------------- -#define SF_MOVELINEAR_NOTSOLID 8 - -LINK_ENTITY_TO_CLASS( func_movelinear, CFuncMoveLinear ); -LINK_ENTITY_TO_CLASS( momentary_door, CFuncMoveLinear ); // For backward compatibility - -// -// func_water_analog is implemented as a linear mover so we can raise/lower the water level. -// -LINK_ENTITY_TO_CLASS( func_water_analog, CFuncMoveLinear ); - - -BEGIN_DATADESC( CFuncMoveLinear ) - - DEFINE_KEYFIELD( m_vecMoveDir, FIELD_VECTOR, "movedir" ), - DEFINE_KEYFIELD( m_soundStart, FIELD_SOUNDNAME, "StartSound" ), - DEFINE_KEYFIELD( m_soundStop, FIELD_SOUNDNAME, "StopSound" ), - DEFINE_FIELD( m_currentSound, FIELD_SOUNDNAME ), - DEFINE_KEYFIELD( m_flBlockDamage, FIELD_FLOAT, "BlockDamage"), - DEFINE_KEYFIELD( m_flStartPosition, FIELD_FLOAT, "StartPosition"), - DEFINE_KEYFIELD( m_flMoveDistance, FIELD_FLOAT, "MoveDistance"), -// DEFINE_PHYSPTR( m_pFluidController ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Open", InputOpen ), - DEFINE_INPUTFUNC( FIELD_VOID, "Close", InputClose ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetPosition", InputSetPosition ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetSpeed", InputSetSpeed ), - - // Outputs - DEFINE_OUTPUT( m_OnFullyOpen, "OnFullyOpen" ), - DEFINE_OUTPUT( m_OnFullyClosed, "OnFullyClosed" ), - - // Functions - DEFINE_FUNCTION( StopMoveSound ), - -END_DATADESC() - - -//------------------------------------------------------------------------------ -// Purpose: Called before spawning, after keyvalues have been parsed. -//------------------------------------------------------------------------------ -void CFuncMoveLinear::Spawn( void ) -{ - // Convert movedir from angles to a vector - QAngle angMoveDir = QAngle( m_vecMoveDir.x, m_vecMoveDir.y, m_vecMoveDir.z ); - AngleVectors( angMoveDir, &m_vecMoveDir ); - - SetMoveType( MOVETYPE_PUSH ); - SetModel( STRING( GetModelName() ) ); - - // Don't allow zero or negative speeds - if (m_flSpeed <= 0) - { - m_flSpeed = 100; - } - - // If move distance is set to zero, use with width of the - // brush to determine the size of the move distance - if (m_flMoveDistance <= 0) - { - Vector vecOBB = CollisionProp()->OBBSize(); - vecOBB -= Vector( 2, 2, 2 ); - m_flMoveDistance = DotProductAbs( m_vecMoveDir, vecOBB ) - m_flLip; - } - - m_vecPosition1 = GetAbsOrigin() - (m_vecMoveDir * m_flMoveDistance * m_flStartPosition); - m_vecPosition2 = m_vecPosition1 + (m_vecMoveDir * m_flMoveDistance); - m_vecFinalDest = GetAbsOrigin(); - - SetTouch( NULL ); - - Precache(); - - // It is solid? - SetSolid( SOLID_VPHYSICS ); - - if ( FClassnameIs( this, "func_water_analog" ) ) - { - AddSolidFlags( FSOLID_VOLUME_CONTENTS ); - } - - if ( !FClassnameIs( this, "func_water_analog" ) && FBitSet (m_spawnflags, SF_MOVELINEAR_NOTSOLID) ) - { - AddSolidFlags( FSOLID_NOT_SOLID ); - } - - CreateVPhysics(); -} - - -bool CFuncMoveLinear::ShouldSavePhysics( void ) -{ - // don't save physics for func_water_analog, regen - return !FClassnameIs( this, "func_water_analog" ); - -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CFuncMoveLinear::CreateVPhysics( void ) -{ - if ( !FClassnameIs( this, "func_water_analog" ) ) - { - //normal door - if ( !IsSolidFlagSet( FSOLID_NOT_SOLID ) ) - { - VPhysicsInitShadow( false, false ); - } - } - else - { - // special contents - AddSolidFlags( FSOLID_VOLUME_CONTENTS ); - //SETBITS( m_spawnflags, SF_DOOR_SILENT ); // water is silent for now - - IPhysicsObject *pPhysics = VPhysicsInitShadow( false, false ); - fluidparams_t fluid; - - Assert( CollisionProp()->GetCollisionAngles() == vec3_angle ); - fluid.damping = 0.01f; - fluid.surfacePlane[0] = 0; - fluid.surfacePlane[1] = 0; - fluid.surfacePlane[2] = 1; - fluid.surfacePlane[3] = CollisionProp()->GetCollisionOrigin().z + CollisionProp()->OBBMaxs().z - 1; - fluid.currentVelocity.Init(0,0,0); - fluid.torqueFactor = 0.1f; - fluid.viscosityFactor = 0.01f; - fluid.pGameData = static_cast(this); - - //FIXME: Currently there's no way to specify that you want slime - fluid.contents = CONTENTS_WATER; - - m_pFluidController = physenv->CreateFluidController( pPhysics, &fluid ); - } - - return true; -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CFuncMoveLinear::Precache( void ) -{ - if (m_soundStart != NULL_STRING) - { - PrecacheScriptSound( (char *) STRING(m_soundStart) ); - } - if (m_soundStop != NULL_STRING) - { - PrecacheScriptSound( (char *) STRING(m_soundStop) ); - } - m_currentSound = NULL_STRING; -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CFuncMoveLinear::MoveTo(Vector vPosition, float flSpeed) -{ - if ( flSpeed != 0 ) - { - if ( m_soundStart != NULL_STRING ) - { - if (m_currentSound == m_soundStart) - { - StopSound(entindex(), CHAN_BODY, (char*)STRING(m_soundStop)); - } - else - { - m_currentSound = m_soundStart; - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_BODY; - ep.m_pSoundName = (char*)STRING(m_soundStart); - ep.m_flVolume = 1; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - } - } - - LinearMove( vPosition, flSpeed ); - - if ( m_pFluidController ) - { - m_pFluidController->WakeAllSleepingObjects(); - } - - // Clear think (that stops sounds) - SetThink(NULL); - } -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CFuncMoveLinear::StopMoveSound( void ) -{ - if ( m_soundStart != NULL_STRING && ( m_currentSound == m_soundStart ) ) - { - StopSound(entindex(), CHAN_BODY, (char*)STRING(m_soundStart) ); - } - - if ( m_soundStop != NULL_STRING && ( m_currentSound != m_soundStop ) ) - { - m_currentSound = m_soundStop; - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_BODY; - ep.m_pSoundName = (char*)STRING(m_soundStop); - ep.m_flVolume = 1; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - } - - SetThink(NULL); -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CFuncMoveLinear::MoveDone( void ) -{ - // Stop sounds at the next think, rather than here as another - // SetPosition call might immediately follow the end of this move - SetThink(&CFuncMoveLinear::StopMoveSound); - SetNextThink( gpGlobals->curtime + 0.1f ); - BaseClass::MoveDone(); - - if ( GetAbsOrigin() == m_vecPosition2 ) - { - m_OnFullyOpen.FireOutput( this, this ); - } - else if ( GetAbsOrigin() == m_vecPosition1 ) - { - m_OnFullyClosed.FireOutput( this, this ); - } -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CFuncMoveLinear::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - if ( useType != USE_SET ) // Momentary buttons will pass down a float in here - return; - - if ( value > 1.0 ) - value = 1.0; - Vector move = m_vecPosition1 + (value * (m_vecPosition2 - m_vecPosition1)); - - Vector delta = move - GetLocalOrigin(); - float speed = delta.Length() * 10; - - MoveTo(move, speed); -} - - -//----------------------------------------------------------------------------- -// Purpose: Sets the position as a value from [0..1]. -//----------------------------------------------------------------------------- -void CFuncMoveLinear::SetPosition( float flPosition ) -{ - Vector vTargetPos = m_vecPosition1 + ( flPosition * (m_vecPosition2 - m_vecPosition1)); - if ((vTargetPos - GetLocalOrigin()).Length() > 0.001) - { - MoveTo(vTargetPos, m_flSpeed); - } -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CFuncMoveLinear::InputOpen( inputdata_t &inputdata ) -{ - if (GetLocalOrigin() != m_vecPosition2) - { - MoveTo(m_vecPosition2, m_flSpeed); - } -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CFuncMoveLinear::InputClose( inputdata_t &inputdata ) -{ - if (GetLocalOrigin() != m_vecPosition1) - { - MoveTo(m_vecPosition1, m_flSpeed); - } -} - - -//------------------------------------------------------------------------------ -// Purpose: Input handler for setting the position from [0..1]. -// Input : Float position. -//----------------------------------------------------------------------------- -void CFuncMoveLinear::InputSetPosition( inputdata_t &inputdata ) -{ - SetPosition( inputdata.value.Float() ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Called every frame when the bruch is blocked while moving -// Input : pOther - The blocking entity. -//----------------------------------------------------------------------------- -void CFuncMoveLinear::Blocked( CBaseEntity *pOther ) -{ - // Hurt the blocker - if ( m_flBlockDamage ) - { - pOther->TakeDamage( CTakeDamageInfo( this, this, m_flBlockDamage, DMG_CRUSH ) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CFuncMoveLinear::InputSetSpeed( inputdata_t &inputdata ) -{ - // Set the new speed - m_flSpeed = inputdata.value.Float(); - - // FIXME: This is a little questionable. Do we want to fix the speed, or let it continue on at the old speed? - float flDistToGoalSqr = ( m_vecFinalDest - GetAbsOrigin() ).LengthSqr(); - if ( flDistToGoalSqr > Square( FLT_EPSILON ) ) - { - // NOTE: We do NOT want to call sound functions here, just vanilla position changes - LinearMove( m_vecFinalDest, m_flSpeed ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CFuncMoveLinear::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - float flTravelDist = (m_vecPosition1 - m_vecPosition2).Length(); - float flCurDist = (m_vecPosition1 - GetLocalOrigin()).Length(); - Q_snprintf(tempstr,sizeof(tempstr),"Current Pos: %3.3f",flCurDist/flTravelDist); - EntityText(text_offset,tempstr,0); - text_offset++; - - float flTargetDist = (m_vecPosition1 - m_vecFinalDest).Length(); - Q_snprintf(tempstr,sizeof(tempstr),"Target Pos: %3.3f",flTargetDist/flTravelDist); - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} diff --git a/game/server/func_movelinear.h b/game/server/func_movelinear.h deleted file mode 100644 index 4bbee63ff..000000000 --- a/game/server/func_movelinear.h +++ /dev/null @@ -1,63 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef FUNC_MOVELINEAR_H -#define FUNC_MOVELINEAR_H - -#pragma once - -#include "basetoggle.h" -#include "entityoutput.h" - - -class IPhysicsFluidController; - - -class CFuncMoveLinear : public CBaseToggle -{ -public: - DECLARE_CLASS( CFuncMoveLinear, CBaseToggle ); - - void Spawn( void ); - void Precache( void ); - bool CreateVPhysics( void ); - bool ShouldSavePhysics( void ); - - void MoveTo(Vector vPosition, float flSpeed); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - void MoveDone( void ); - void StopMoveSound( void ); - void Blocked( CBaseEntity *pOther ); - void SetPosition( float flPosition ); - - int DrawDebugTextOverlays(void); - - // Input handlers - void InputOpen( inputdata_t &inputdata ); - void InputClose( inputdata_t &inputdata ); - void InputSetPosition( inputdata_t &inputdata ); - void InputSetSpeed( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - - Vector m_vecMoveDir; // Move direction. - - string_t m_soundStart; // start and looping sound - string_t m_soundStop; // stop sound - string_t m_currentSound; // sound I'm playing - - float m_flBlockDamage; // Damage inflicted when blocked. - float m_flStartPosition; // Position of brush when spawned - float m_flMoveDistance; // Total distance the brush can move - - IPhysicsFluidController *m_pFluidController; - - // Outputs - COutputEvent m_OnFullyOpen; - COutputEvent m_OnFullyClosed; -}; -#endif // FUNC_MOVELINEAR_H diff --git a/game/server/func_occluder.cpp b/game/server/func_occluder.cpp deleted file mode 100644 index 391ed06db..000000000 --- a/game/server/func_occluder.cpp +++ /dev/null @@ -1,123 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: area portal entity: toggles visibility areas on/off -// -// NOTE: These are not really brush entities. They are brush entities from a -// designer/worldcraft perspective, but by the time they reach the game, the -// brush model is gone and this is, in effect, a point entity. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CFuncOccluder : public CBaseEntity -{ -public: - DECLARE_CLASS( CFuncOccluder, CBaseEntity ); - - CFuncOccluder(); - - virtual void Spawn( void ); - virtual int UpdateTransmitState( void ); - - // Input handlers - void InputActivate( inputdata_t &inputdata ); - void InputDeactivate( inputdata_t &inputdata ); - void InputToggle( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - -private: - CNetworkVar( bool, m_bActive ); - CNetworkVar( int, m_nOccluderIndex ); -}; - -LINK_ENTITY_TO_CLASS( func_occluder, CFuncOccluder ); - -IMPLEMENT_SERVERCLASS_ST_NOBASE(CFuncOccluder, DT_FuncOccluder) - SendPropBool( SENDINFO(m_bActive) ), - SendPropInt(SENDINFO(m_nOccluderIndex), 10, SPROP_UNSIGNED ), -END_SEND_TABLE() - - -BEGIN_DATADESC( CFuncOccluder ) - - DEFINE_KEYFIELD( m_bActive, FIELD_BOOLEAN, "StartActive" ), - - // NOTE: This keyfield is computed + inserted by VBSP - DEFINE_KEYFIELD( m_nOccluderIndex, FIELD_INTEGER, "occludernumber" ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Deactivate", InputDeactivate ), - DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - -END_DATADESC() - - -//------------------------------------------------------------------------------ -// Occluder : -//------------------------------------------------------------------------------ -CFuncOccluder::CFuncOccluder() -{ - m_bActive = true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncOccluder::Spawn( void ) -{ - Precache( ); - - m_takedamage = DAMAGE_NO; - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NONE ); - - // set size and link into world. - SetModel( STRING( GetModelName() ) ); -} - - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CFuncOccluder::InputDeactivate( inputdata_t &inputdata ) -{ - m_bActive = false; -} - - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CFuncOccluder::InputActivate( inputdata_t &inputdata ) -{ - m_bActive = true; -} - - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CFuncOccluder::InputToggle( inputdata_t &inputdata ) -{ - m_bActive = !m_bActive; -} - - -//------------------------------------------------------------------------------ -// We always want to transmit these bad boys -//------------------------------------------------------------------------------ -int CFuncOccluder::UpdateTransmitState() -{ - // ALWAYS transmit to all clients. - return SetTransmitState( FL_EDICT_ALWAYS ); -} - diff --git a/game/server/func_reflective_glass.cpp b/game/server/func_reflective_glass.cpp deleted file mode 100644 index f8bcb9f35..000000000 --- a/game/server/func_reflective_glass.cpp +++ /dev/null @@ -1,27 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#include "cbase.h" -#include "modelentities.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CFuncReflectiveGlass : public CFuncBrush -{ - DECLARE_DATADESC(); - DECLARE_CLASS( CFuncReflectiveGlass, CFuncBrush ); - DECLARE_SERVERCLASS(); -}; - -// automatically hooks in the system's callbacks -BEGIN_DATADESC( CFuncReflectiveGlass ) -END_DATADESC() - -LINK_ENTITY_TO_CLASS( func_reflective_glass, CFuncReflectiveGlass ); - -IMPLEMENT_SERVERCLASS_ST( CFuncReflectiveGlass, DT_FuncReflectiveGlass ) -END_SEND_TABLE() diff --git a/game/server/func_smokevolume.cpp b/game/server/func_smokevolume.cpp deleted file mode 100644 index fd46260f6..000000000 --- a/game/server/func_smokevolume.cpp +++ /dev/null @@ -1,105 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "baseparticleentity.h" -#include "sendproxy.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CFuncSmokeVolume : public CBaseParticleEntity -{ -public: - DECLARE_CLASS( CFuncSmokeVolume, CBaseParticleEntity ); - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - CFuncSmokeVolume(); - void Spawn(); - void Activate( void ); - - // Set the times it fades out at. - void SetDensity( float density ); - -private: - CNetworkVar( color32, m_Color1 ); - CNetworkVar( color32, m_Color2 ); - CNetworkString( m_MaterialName, 255 ); - string_t m_String_tMaterialName; - CNetworkVar( float, m_ParticleDrawWidth ); - CNetworkVar( float, m_ParticleSpacingDistance ); - CNetworkVar( float, m_DensityRampSpeed ); - CNetworkVar( float, m_RotationSpeed ); - CNetworkVar( float, m_MovementSpeed ); - CNetworkVar( float, m_Density ); -}; - -BEGIN_DATADESC( CFuncSmokeVolume ) - - // Save/restore Keyvalue fields - DEFINE_KEYFIELD( m_Color1, FIELD_COLOR32, "Color1" ), - DEFINE_KEYFIELD( m_Color2, FIELD_COLOR32, "Color2" ), -// DEFINE_ARRAY( m_MaterialName, FIELD_STRING, 255 ), - DEFINE_KEYFIELD( m_String_tMaterialName, FIELD_STRING, "Material" ), - DEFINE_KEYFIELD( m_ParticleDrawWidth, FIELD_FLOAT, "ParticleDrawWidth" ), - DEFINE_KEYFIELD( m_ParticleSpacingDistance, FIELD_FLOAT, "ParticleSpacingDistance" ), - DEFINE_KEYFIELD( m_DensityRampSpeed, FIELD_FLOAT, "DensityRampSpeed" ), - DEFINE_KEYFIELD( m_RotationSpeed, FIELD_FLOAT, "RotationSpeed" ), - DEFINE_KEYFIELD( m_MovementSpeed, FIELD_FLOAT, "MovementSpeed" ), - DEFINE_KEYFIELD( m_Density, FIELD_FLOAT, "Density" ), - // inputs - DEFINE_INPUT( m_RotationSpeed, FIELD_FLOAT, "SetRotationSpeed"), - DEFINE_INPUT( m_MovementSpeed, FIELD_FLOAT, "SetMovementSpeed"), - DEFINE_INPUT( m_Density, FIELD_FLOAT, "SetDensity"), - -END_DATADESC() - - - - -IMPLEMENT_SERVERCLASS_ST( CFuncSmokeVolume, DT_FuncSmokeVolume ) - SendPropInt( SENDINFO( m_Color1 ), 32, SPROP_UNSIGNED, SendProxy_Color32ToInt ), - SendPropInt( SENDINFO( m_Color2 ), 32, SPROP_UNSIGNED, SendProxy_Color32ToInt ), - SendPropString( SENDINFO( m_MaterialName ) ), - SendPropFloat( SENDINFO( m_ParticleDrawWidth ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO( m_ParticleSpacingDistance ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO( m_DensityRampSpeed ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO( m_RotationSpeed ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO( m_MovementSpeed ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO( m_Density ), 0, SPROP_NOSCALE ), - SendPropInt( SENDINFO(m_spawnflags), 8, SPROP_UNSIGNED ) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( func_smokevolume, CFuncSmokeVolume ); - -CFuncSmokeVolume::CFuncSmokeVolume() -{ - m_Density = 1.0f; -} - -void CFuncSmokeVolume::SetDensity( float density ) -{ - m_Density = density; -} - -void CFuncSmokeVolume::Spawn() -{ - memset( m_MaterialName.GetForModify(), 0, sizeof( m_MaterialName ) ); - - // Bind to our bmodel. - SetModel( STRING( GetModelName() ) ); - - BaseClass::Spawn(); -} - -void CFuncSmokeVolume::Activate( void ) -{ - BaseClass::Activate(); - Q_strncpy( m_MaterialName.GetForModify(), STRING( m_String_tMaterialName ), 255 ); -} - diff --git a/game/server/game.cpp b/game/server/game.cpp deleted file mode 100644 index 8075d0397..000000000 --- a/game/server/game.cpp +++ /dev/null @@ -1,108 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "game.h" -#include "physics.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -void MapCycleFileChangedCallback( IConVar *var, const char *pOldString, float flOldValue ) -{ - if ( Q_stricmp( pOldString, mapcyclefile.GetString() ) != 0 ) - { - if ( GameRules() ) - { - // For multiplayer games, forces the mapcyclefile to be reloaded - GameRules()->ResetMapCycleTimeStamp(); - } - } -} - -ConVar displaysoundlist( "displaysoundlist","0" ); -ConVar mapcyclefile( "mapcyclefile", "mapcycle.txt", FCVAR_NONE, "Name of the .txt file used to cycle the maps on multiplayer servers ", MapCycleFileChangedCallback ); -ConVar servercfgfile( "servercfgfile","server.cfg" ); -ConVar lservercfgfile( "lservercfgfile","listenserver.cfg" ); - -// multiplayer server rules -ConVar teamplay( "mp_teamplay","0", FCVAR_NOTIFY ); -ConVar fraglimit( "mp_fraglimit","0", FCVAR_NOTIFY ); -ConVar falldamage( "mp_falldamage","0", FCVAR_NOTIFY ); -ConVar weaponstay( "mp_weaponstay","0", FCVAR_NOTIFY ); -ConVar forcerespawn( "mp_forcerespawn","1", FCVAR_NOTIFY ); -ConVar footsteps( "mp_footsteps","1", FCVAR_NOTIFY ); -ConVar flashlight( "mp_flashlight","0", FCVAR_NOTIFY ); -ConVar aimcrosshair( "mp_autocrosshair","1", FCVAR_NOTIFY ); -ConVar decalfrequency( "decalfrequency","10", FCVAR_NOTIFY ); -ConVar teamlist( "mp_teamlist","hgrunt;scientist", FCVAR_NOTIFY ); -ConVar teamoverride( "mp_teamoverride","1" ); -ConVar defaultteam( "mp_defaultteam","0" ); -ConVar allowNPCs( "mp_allowNPCs","1", FCVAR_NOTIFY ); - -// Engine Cvars -const ConVar *g_pDeveloper = NULL; - - -ConVar suitvolume( "suitvolume", "0.25", FCVAR_ARCHIVE ); - -class CGameDLL_ConVarAccessor : public IConCommandBaseAccessor -{ -public: - virtual bool RegisterConCommandBase( ConCommandBase *pCommand ) - { - // Remember "unlinked" default value for replicated cvars - bool replicated = pCommand->IsFlagSet( FCVAR_REPLICATED ); - const char *defvalue = NULL; - if ( replicated && !pCommand->IsCommand() ) - { - defvalue = ( ( ConVar * )pCommand)->GetDefault(); - } - - // Link to engine's list instead - cvar->RegisterConCommand( pCommand ); - - // Apply any command-line values. - const char *pValue = cvar->GetCommandLineValue( pCommand->GetName() ); - if( pValue ) - { - if ( !pCommand->IsCommand() ) - { - ( ( ConVar * )pCommand )->SetValue( pValue ); - } - } - else - { - // NOTE: If not overridden at the command line, then if it's a replicated cvar, make sure that it's - // value is the server's value. This solves a problem where think_limit is defined in shared - // code but the value is inside and #if defined( _DEBUG ) block and if you have a debug game .dll - // and a release client, then the limiit was coming from the client even though the server value - // was the one that was important during debugging. Now the server trumps the client value for - // replicated ConVars by setting the value here after the ConVar has been linked. - if ( replicated && defvalue && !pCommand->IsCommand() ) - { - ConVar *var = ( ConVar * )pCommand; - var->SetValue( defvalue ); - } - } - - return true; - } -}; - -static CGameDLL_ConVarAccessor g_ConVarAccessor; - -// Register your console variables here -// This gets called one time when the game is initialied -void InitializeCvars( void ) -{ - // Register cvars here: - ConVar_Register( FCVAR_GAMEDLL, &g_ConVarAccessor ); - - g_pDeveloper = cvar->FindVar( "developer" ); -} - diff --git a/game/server/game.h b/game/server/game.h deleted file mode 100644 index 531fce8f1..000000000 --- a/game/server/game.h +++ /dev/null @@ -1,41 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef GAME_H -#define GAME_H - - -#include "globals.h" - -extern void GameDLLInit( void ); - -extern ConVar displaysoundlist; -extern ConVar mapcyclefile; -extern ConVar servercfgfile; -extern ConVar lservercfgfile; - -// multiplayer server rules -extern ConVar teamplay; -extern ConVar fraglimit; -extern ConVar falldamage; -extern ConVar weaponstay; -extern ConVar forcerespawn; -extern ConVar footsteps; -extern ConVar flashlight; -extern ConVar aimcrosshair; -extern ConVar decalfrequency; -extern ConVar teamlist; -extern ConVar teamoverride; -extern ConVar defaultteam; -extern ConVar allowNPCs; - -extern ConVar suitvolume; - -// Engine Cvars -extern const ConVar *g_pDeveloper; -#endif // GAME_H diff --git a/game/server/game_ui.cpp b/game/server/game_ui.cpp deleted file mode 100644 index c0c9fba56..000000000 --- a/game/server/game_ui.cpp +++ /dev/null @@ -1,439 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Entities that capture the player's UI and move it into game design -// as outputs. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "entitylist.h" -#include "util.h" -#include "physics.h" -#include "entityoutput.h" -#include "player.h" -#include "in_buttons.h" -#include "basecombatweapon.h" -#include "baseviewmodel.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//---------------------------------------------------------------- -// Spawn flags -//---------------------------------------------------------------- -#define SF_GAMEUI_FREEZE_PLAYER 32 -#define SF_GAMEUI_HIDE_WEAPON 64 -#define SF_GAMEUI_USE_DEACTIVATES 128 -#define SF_GAMEUI_JUMP_DEACTIVATES 256 - - -class CGameUI : public CBaseEntity -{ -public: - DECLARE_CLASS( CGameUI, CBaseEntity ); - - DECLARE_DATADESC(); - - // Input handlers - void InputDeactivate( inputdata_t &inputdata ); - void InputActivate( inputdata_t &inputdata ); - - void Think( void ); - void Deactivate( CBaseEntity *pActivator ); - - float m_flFieldOfView; - CHandle m_hSaveWeapon; - - COutputEvent m_playerOn; - COutputEvent m_playerOff; - - COutputEvent m_pressedMoveLeft; - COutputEvent m_pressedMoveRight; - COutputEvent m_pressedForward; - COutputEvent m_pressedBack; - COutputEvent m_pressedAttack; - COutputEvent m_pressedAttack2; - - COutputEvent m_unpressedMoveLeft; - COutputEvent m_unpressedMoveRight; - COutputEvent m_unpressedForward; - COutputEvent m_unpressedBack; - COutputEvent m_unpressedAttack; - COutputEvent m_unpressedAttack2; - - COutputFloat m_xaxis; - COutputFloat m_yaxis; - COutputFloat m_attackaxis; - COutputFloat m_attack2axis; - - bool m_bForceUpdate; - int m_nLastButtonState; - - CHandle m_player; -}; - - -BEGIN_DATADESC( CGameUI ) - - DEFINE_KEYFIELD( m_flFieldOfView, FIELD_FLOAT, "FieldOfView" ), - DEFINE_FIELD( m_hSaveWeapon, FIELD_EHANDLE ), - DEFINE_FIELD( m_bForceUpdate, FIELD_BOOLEAN ), - DEFINE_FIELD( m_player, FIELD_EHANDLE ), - DEFINE_FIELD( m_nLastButtonState, FIELD_INTEGER ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Deactivate", InputDeactivate ), - DEFINE_INPUTFUNC( FIELD_STRING, "Activate", InputActivate ), - - DEFINE_OUTPUT( m_playerOn, "PlayerOn" ), - DEFINE_OUTPUT( m_playerOff, "PlayerOff" ), - - DEFINE_OUTPUT( m_pressedMoveLeft, "PressedMoveLeft" ), - DEFINE_OUTPUT( m_pressedMoveRight, "PressedMoveRight" ), - DEFINE_OUTPUT( m_pressedForward, "PressedForward" ), - DEFINE_OUTPUT( m_pressedBack, "PressedBack" ), - DEFINE_OUTPUT( m_pressedAttack, "PressedAttack" ), - DEFINE_OUTPUT( m_pressedAttack2, "PressedAttack2" ), - - DEFINE_OUTPUT( m_unpressedMoveLeft, "UnpressedMoveLeft" ), - DEFINE_OUTPUT( m_unpressedMoveRight, "UnpressedMoveRight" ), - DEFINE_OUTPUT( m_unpressedForward, "UnpressedForward" ), - DEFINE_OUTPUT( m_unpressedBack, "UnpressedBack" ), - DEFINE_OUTPUT( m_unpressedAttack, "UnpressedAttack" ), - DEFINE_OUTPUT( m_unpressedAttack2, "UnpressedAttack2" ), - - DEFINE_OUTPUT( m_xaxis, "XAxis" ), - DEFINE_OUTPUT( m_yaxis, "YAxis" ), - DEFINE_OUTPUT( m_attackaxis, "AttackAxis" ), - DEFINE_OUTPUT( m_attack2axis, "Attack2Axis" ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( game_ui, CGameUI ); - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGameUI::InputDeactivate( inputdata_t &inputdata ) -{ - Deactivate( inputdata.pActivator ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGameUI::Deactivate( CBaseEntity *pActivator ) -{ - CBasePlayer *pPlayer = m_player; - - AssertMsg(pPlayer, "CGameUI deactivated without a player!"); - - if (pPlayer) - { - // Re-enable player motion - if ( FBitSet( m_spawnflags, SF_GAMEUI_FREEZE_PLAYER ) ) - { - m_player->RemoveFlag( FL_ATCONTROLS ); - } - - // Restore weapons - if ( FBitSet( m_spawnflags, SF_GAMEUI_HIDE_WEAPON ) ) - { - // Turn the hud back on - pPlayer->m_Local.m_iHideHUD &= ~HIDEHUD_WEAPONSELECTION; - - if ( m_hSaveWeapon.Get() ) - { - m_player->Weapon_Switch( m_hSaveWeapon.Get() ); - m_hSaveWeapon = NULL; - } - - if ( pPlayer->GetActiveWeapon() ) - { - pPlayer->GetActiveWeapon()->Deploy(); - } - } - - // Announce that the player is no longer controlling through us - m_playerOff.FireOutput( pPlayer, this, 0 ); - - // Clear out the axis controls - m_xaxis.Set( 0, pPlayer, this ); - m_yaxis.Set( 0, pPlayer, this ); - m_attackaxis.Set( 0, pPlayer, this ); - m_attack2axis.Set( 0, pPlayer, this ); - m_nLastButtonState = 0; - m_player = NULL; - } - else - { - Warning("%s Deactivate(): I have no player when called by %s!\n", GetEntityName().ToCStr(), pActivator->GetEntityName().ToCStr()); - } - - // Stop thinking - SetNextThink( TICK_NEVER_THINK ); -} - - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CGameUI::InputActivate( inputdata_t &inputdata ) -{ - CBasePlayer *pPlayer; - - // Determine if we're specifying this as an override parameter - if ( inputdata.value.StringID() != NULL_STRING ) - { - CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, inputdata.value.String(), this, inputdata.pActivator, inputdata.pCaller ); - if ( pEntity == NULL || pEntity->IsPlayer() == false ) - { - Warning( "%s InputActivate: entity %s not found or is not a player!\n", GetEntityName().ToCStr(), inputdata.value.String() ); - return; - } - - pPlayer = ToBasePlayer( pEntity ); - } - else - { - // Otherwise try to use the activator - if ( inputdata.pActivator == NULL || inputdata.pActivator->IsPlayer() == false ) - { - Warning( "%s InputActivate: invalid or missing !activator!\n", GetEntityName().ToCStr(), inputdata.value.String() ); - return; - } - - pPlayer = ToBasePlayer( inputdata.pActivator ); - } - - // If another player is already using these controls3, ignore this activation - if ( m_player.Get() != NULL && pPlayer != m_player.Get() ) - { - // TODO: We could allow this by calling Deactivate() at this point and continuing on -- jdw - return; - } - - // Setup our internal data - m_player = pPlayer; - m_playerOn.FireOutput( pPlayer, this, 0 ); - - // Turn the hud off - SetNextThink( gpGlobals->curtime ); - - // Disable player's motion - if ( FBitSet( m_spawnflags, SF_GAMEUI_FREEZE_PLAYER ) ) - { - m_player->AddFlag( FL_ATCONTROLS ); - } - - // Store off and hide the currently held weapon - if ( FBitSet( m_spawnflags, SF_GAMEUI_HIDE_WEAPON ) ) - { - m_player->m_Local.m_iHideHUD |= HIDEHUD_WEAPONSELECTION; - - if ( m_player->GetActiveWeapon() ) - { - m_hSaveWeapon = m_player->GetActiveWeapon(); - - m_player->GetActiveWeapon()->Holster(); - m_player->ClearActiveWeapon(); - m_player->HideViewModels(); - } - } - - // We must update our state - m_bForceUpdate = true; -} - - -//------------------------------------------------------------------------------ -// Purpose: Samples the player's inputs and fires outputs based on what buttons -// are currently held down. -//------------------------------------------------------------------------------ -void CGameUI::Think( void ) -{ - CBasePlayer *pPlayer = m_player; - - // If player is gone, stop thinking - if (pPlayer == NULL) - { - SetNextThink( TICK_NEVER_THINK ); - return; - } - - // If we're forcing an update, state with a clean button state - if ( m_bForceUpdate ) - { - m_nLastButtonState = pPlayer->m_nButtons; - } - - // ------------------------------------------------ - // Check that toucher is facing the UI within - // the field of view tolerance. If not disconnect - // ------------------------------------------------ - if (m_flFieldOfView > -1) - { - Vector vPlayerFacing; - pPlayer->EyeVectors( &vPlayerFacing ); - Vector vPlayerToUI = GetAbsOrigin() - pPlayer->WorldSpaceCenter(); - VectorNormalize(vPlayerToUI); - - float flDotPr = DotProduct(vPlayerFacing,vPlayerToUI); - if (flDotPr < m_flFieldOfView) - { - Deactivate( pPlayer ); - return; - } - } - - pPlayer->AddFlag( FL_ONTRAIN ); - SetNextThink( gpGlobals->curtime ); - - // Deactivate if they jump or press +use. - // FIXME: prevent the use from going through in player.cpp - if ((( pPlayer->m_afButtonPressed & IN_USE ) && ( m_spawnflags & SF_GAMEUI_USE_DEACTIVATES )) || - (( pPlayer->m_afButtonPressed & IN_JUMP ) && ( m_spawnflags & SF_GAMEUI_JUMP_DEACTIVATES ))) - { - Deactivate( pPlayer ); - return; - } - - // Determine what's different - int nButtonsChanged = ( pPlayer->m_nButtons ^ m_nLastButtonState ); - - // - // Handle all our possible input triggers - // - - if ( nButtonsChanged & IN_MOVERIGHT ) - { - if ( m_nLastButtonState & IN_MOVERIGHT ) - { - m_unpressedMoveRight.FireOutput( pPlayer, this, 0 ); - } - else - { - m_pressedMoveRight.FireOutput( pPlayer, this, 0 ); - } - } - - if ( nButtonsChanged & IN_MOVELEFT ) - { - if ( m_nLastButtonState & IN_MOVELEFT ) - { - m_unpressedMoveLeft.FireOutput( pPlayer, this, 0 ); - } - else - { - m_pressedMoveLeft.FireOutput( pPlayer, this, 0 ); - } - } - - if ( nButtonsChanged & IN_FORWARD ) - { - if ( m_nLastButtonState & IN_FORWARD ) - { - m_unpressedForward.FireOutput( pPlayer, this, 0 ); - } - else - { - m_pressedForward.FireOutput( pPlayer, this, 0 ); - } - } - - if ( nButtonsChanged & IN_BACK ) - { - if ( m_nLastButtonState & IN_BACK ) - { - m_unpressedBack.FireOutput( pPlayer, this, 0 ); - } - else - { - m_pressedBack.FireOutput( pPlayer, this, 0 ); - } - } - - if ( nButtonsChanged & IN_ATTACK ) - { - if ( m_nLastButtonState & IN_ATTACK ) - { - m_unpressedAttack.FireOutput( pPlayer, this, 0 ); - } - else - { - m_pressedAttack.FireOutput( pPlayer, this, 0 ); - } - } - - if ( nButtonsChanged & IN_ATTACK2 ) - { - if ( m_nLastButtonState & IN_ATTACK2 ) - { - m_unpressedAttack2.FireOutput( pPlayer, this, 0 ); - } - else - { - m_pressedAttack2.FireOutput( pPlayer, this, 0 ); - } - } - - // Setup for the next frame - m_nLastButtonState = pPlayer->m_nButtons; - - float x = 0, y = 0, attack = 0, attack2 = 0; - if ( pPlayer->m_nButtons & IN_MOVERIGHT ) - { - x = 1; - } - else if ( pPlayer->m_nButtons & IN_MOVELEFT ) - { - x = -1; - } - - if ( pPlayer->m_nButtons & IN_FORWARD ) - { - y = 1; - } - else if ( pPlayer->m_nButtons & IN_BACK ) - { - y = -1; - } - - if ( pPlayer->m_nButtons & IN_ATTACK ) - { - attack = 1; - } - - if ( pPlayer->m_nButtons & IN_ATTACK2 ) - { - attack2 = 1; - } - - // - // Fire the analog outputs if they changed. - // - if ( m_bForceUpdate || ( m_xaxis.Get() != x ) ) - { - m_xaxis.Set( x, pPlayer, this ); - } - - if ( m_bForceUpdate || ( m_yaxis.Get() != y ) ) - { - m_yaxis.Set( y, pPlayer, this ); - } - - if ( m_bForceUpdate || ( m_attackaxis.Get() != attack ) ) - { - m_attackaxis.Set( attack, pPlayer, this ); - } - - if ( m_bForceUpdate || ( m_attack2axis.Get() != attack2 ) ) - { - m_attack2axis.Set( attack2, pPlayer, this ); - } - - m_bForceUpdate = false; -} diff --git a/game/server/gamehandle.cpp b/game/server/gamehandle.cpp deleted file mode 100644 index cd597f9cd..000000000 --- a/game/server/gamehandle.cpp +++ /dev/null @@ -1,30 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: returns the module handle of the game dll -// this is in its own file to protect it from tier0 PROTECTED_THINGS -//=============================================================================// - - -#if defined(_WIN32) -#include "winlite.h" -extern HMODULE win32DLLHandle; -#elif defined(_LINUX) -#include -#include "tier0/dbg.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -void *GetGameModuleHandle() -{ -#if defined(_WIN32) - return (void *)win32DLLHandle; -#elif defined(_LINUX) - Assert(0); - return NULL; // NOT implemented -#else -#error "GetGameModuleHandle() needs to be implemented" -#endif -} - diff --git a/game/server/gameinterface.cpp b/game/server/gameinterface.cpp deleted file mode 100644 index 6546ca27a..000000000 --- a/game/server/gameinterface.cpp +++ /dev/null @@ -1,3046 +0,0 @@ -//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: encapsulates and implements all the accessing of the game dll from external -// sources (only the engine at the time of writing) -// This files ONLY contains functions and data necessary to build an interface -// to external modules -//===========================================================================// - -#include "cbase.h" -#include "gamestringpool.h" -#include "mapentities_shared.h" -#include "game.h" -#include "entityapi.h" -#include "client.h" -#include "saverestore.h" -#include "entitylist.h" -#include "gamerules.h" -#include "soundent.h" -#include "player.h" -#include "server_class.h" -#include "ai_node.h" -#include "ai_link.h" -#include "ai_saverestore.h" -#include "ai_networkmanager.h" -#include "ndebugoverlay.h" -#include "ivoiceserver.h" -#include -#include "movehelper_server.h" -#include "networkstringtable_gamedll.h" -#include "filesystem.h" -#include "func_areaportalwindow.h" -#include "igamesystem.h" -#include "init_factory.h" -#include "vstdlib/random.h" -#include "env_wind_shared.h" -#include "engine/IEngineSound.h" -#include "ispatialpartition.h" -#include "textstatsmgr.h" -#include "bitbuf.h" -#include "saverestoretypes.h" -#include "physics_saverestore.h" -#include "achievement_saverestore.h" -#include "tier0/vprof.h" -#include "effect_dispatch_data.h" -#include "engine/IStaticPropMgr.h" -#include "TemplateEntities.h" -#include "ai_speech.h" -#include "soundenvelope.h" -#include "usermessages.h" -#include "physics.h" -#include "igameevents.h" -#include "EventLog.h" -#include "datacache/idatacache.h" -#include "engine/ivdebugoverlay.h" -#include "shareddefs.h" -#include "props.h" -#include "timedeventmgr.h" -#include "gameinterface.h" -#include "eventqueue.h" -#include "hltvdirector.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" -#include "nav_mesh.h" -#include "AI_ResponseSystem.h" -#include "saverestore_stringtable.h" -#include "util.h" -#include "tier0/icommandline.h" -#include "datacache/imdlcache.h" -#include "engine/iserverplugin.h" -#ifdef _WIN32 -#include "ienginevgui.h" -#endif -#include "ragdoll_shared.h" -#include "toolframework/iserverenginetools.h" -#include "sceneentity.h" -#include "appframework/IAppSystemGroup.h" -#include "scenefilecache/ISceneFileCache.h" -#include "tier2/tier2.h" -#include "particles/particles.h" -#include "GameStats.h" -#include "ixboxsystem.h" -#include "engine/imatchmaking.h" -#include "hl2orange.spa.h" -#include "particle_parse.h" -#include "steam/steam_api.h" -#include "tier3/tier3.h" -#include "serverbenchmark_base.h" - -#ifdef CSTRIKE_DLL // BOTPORT: TODO: move these ifdefs out -#include "bot/bot.h" -#endif - -#ifdef PORTAL -#include "prop_portal_shared.h" -#include "portal_player.h" -#endif - -extern IToolFrameworkServer *g_pToolFrameworkServer; -extern IParticleSystemQuery *g_pParticleSystemQuery; - -extern ConVar commentary; - -static CSteamAPIContext g_SteamAPIContext; -CSteamAPIContext *steamapicontext = &g_SteamAPIContext; - -IUploadGameStats *gamestatsuploader = NULL; - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -CTimedEventMgr g_NetworkPropertyEventMgr; - -ISaveRestoreBlockHandler *GetEventQueueSaveRestoreBlockHandler(); -ISaveRestoreBlockHandler *GetCommentarySaveRestoreBlockHandler(); - -CUtlLinkedList g_MapEntityRefs; - -// Engine interfaces. -IVEngineServer *engine = NULL; -IVoiceServer *g_pVoiceServer = NULL; -#if !defined(_STATIC_LINKED) -IFileSystem *filesystem = NULL; -#else -extern IFileSystem *filesystem; -#endif -INetworkStringTableContainer *networkstringtable = NULL; -IStaticPropMgrServer *staticpropmgr = NULL; -IUniformRandomStream *random = NULL; -IEngineSound *enginesound = NULL; -ISpatialPartition *partition = NULL; -IVModelInfo *modelinfo = NULL; -IEngineTrace *enginetrace = NULL; -IGameEventManager2 *gameeventmanager = NULL; -IDataCache *datacache = NULL; -IVDebugOverlay * debugoverlay = NULL; -ISoundEmitterSystemBase *soundemitterbase = NULL; -IServerPluginHelpers *serverpluginhelpers = NULL; -IServerEngineTools *serverenginetools = NULL; -ISceneFileCache *scenefilecache = NULL; -IXboxSystem *xboxsystem = NULL; // Xbox 360 only -IMatchmaking *matchmaking = NULL; // Xbox 360 only - -IGameSystem *SoundEmitterSystem(); - -bool ModelSoundsCacheInit(); -void ModelSoundsCacheShutdown(); - -void SceneManager_ClientActive( CBasePlayer *player ); - -class IMaterialSystem; -class IStudioRender; - -#ifdef _DEBUG -static ConVar s_UseNetworkVars( "UseNetworkVars", "1", FCVAR_CHEAT, "For profiling, toggle network vars." ); -#endif - -extern ConVar sv_noclipduringpause; -ConVar sv_massreport( "sv_massreport", "0" ); -ConVar sv_force_transmit_ents( "sv_force_transmit_ents", "0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "Will transmit all entities to client, regardless of PVS conditions (will still skip based on transmit flags, however)." ); - -ConVar sv_autosave( "sv_autosave", "1", 0, "Set to 1 to autosave game on level transition. Does not affect autosave triggers." ); -ConVar *sv_maxreplay = NULL; -static ConVar *g_pcv_commentary = NULL; -static ConVar *g_pcv_ThreadMode = NULL; - -// String tables -INetworkStringTable *g_pStringTableParticleEffectNames = NULL; -INetworkStringTable *g_pStringTableEffectDispatch = NULL; -INetworkStringTable *g_pStringTableVguiScreen = NULL; -INetworkStringTable *g_pStringTableMaterials = NULL; -INetworkStringTable *g_pStringTableInfoPanel = NULL; -INetworkStringTable *g_pStringTableClientSideChoreoScenes = NULL; - -CStringTableSaveRestoreOps g_VguiScreenStringOps; - -// Holds global variables shared between engine and game. -CGlobalVars *gpGlobals; -edict_t *g_pDebugEdictBase = 0; -static int g_nCommandClientIndex = 0; - -// The chapter number of the current -static int g_nCurrentChapterIndex = -1; - -static ConVar sv_showhitboxes( "sv_showhitboxes", "-1", FCVAR_CHEAT, "Send server-side hitboxes for specified entity to client (NOTE: this uses lots of bandwidth, use on listen server only)." ); - -void PrecachePointTemplates(); - -static ClientPutInServerOverrideFn g_pClientPutInServerOverride = NULL; -static void UpdateChapterRestrictions( const char *mapname ); - -static void UpdateRichPresence ( void ); - - -#if !defined( _XBOX ) // Don't doubly define this symbol. -CSharedEdictChangeInfo *g_pSharedChangeInfo = NULL; - -#endif - -IChangeInfoAccessor *CBaseEdict::GetChangeAccessor() -{ - return engine->GetChangeAccessor( (const edict_t *)this ); -} - -const IChangeInfoAccessor *CBaseEdict::GetChangeAccessor() const -{ - return engine->GetChangeAccessor( (const edict_t *)this ); -} - -const char *GetHintTypeDescription( CAI_Hint *pHint ); - -void ClientPutInServerOverride( ClientPutInServerOverrideFn fn ) -{ - g_pClientPutInServerOverride = fn; -} - -ConVar ai_post_frame_navigation( "ai_post_frame_navigation", "0" ); -class CPostFrameNavigationHook; -extern CPostFrameNavigationHook *PostFrameNavigationSystem( void ); - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int UTIL_GetCommandClientIndex( void ) -{ - // -1 == unknown,dedicated server console - // 0 == player 1 - - // Convert to 1 based offset - return (g_nCommandClientIndex+1); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CBasePlayer -//----------------------------------------------------------------------------- -CBasePlayer *UTIL_GetCommandClient( void ) -{ - int idx = UTIL_GetCommandClientIndex(); - if ( idx > 0 ) - { - return UTIL_PlayerByIndex( idx ); - } - - // HLDS console issued command - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Retrieves the MOD directory for the active game (ie. "hl2") -//----------------------------------------------------------------------------- - -bool UTIL_GetModDir( char *lpszTextOut, unsigned int nSize ) -{ - // Must pass in a buffer at least large enough to hold the desired string - const char *pGameDir = CommandLine()->ParmValue( "-game", "hl2" ); - Assert( strlen(pGameDir) <= nSize ); - if ( strlen(pGameDir) > nSize ) - return false; - - Q_strncpy( lpszTextOut, pGameDir, nSize ); - if ( Q_strnchr( lpszTextOut, '/', nSize ) || Q_strnchr( lpszTextOut, '\\', nSize ) ) - { - // Strip the last directory off (which will be our game dir) - Q_StripLastDir( lpszTextOut, nSize ); - - // Find the difference in string lengths and take that difference from the original string as the mod dir - int dirlen = Q_strlen( lpszTextOut ); - Q_strncpy( lpszTextOut, pGameDir + dirlen, Q_strlen( pGameDir ) - dirlen + 1 ); - } - - return true; -} - -extern void InitializeCvars( void ); - -CBaseEntity* FindPickerEntity( CBasePlayer* pPlayer ); -CAI_Node* FindPickerAINode( CBasePlayer* pPlayer, NodeType_e nNodeType ); -CAI_Link* FindPickerAILink( CBasePlayer* pPlayer ); -float GetFloorZ(const Vector &origin); -void UpdateAllClientData( void ); -void DrawMessageEntities(); - -#include "ai_network.h" - -// For now just using one big AI network -extern ConVar think_limit; - - -#if 0 -//----------------------------------------------------------------------------- -// Purpose: Draw output overlays for any measure sections -// Input : -//----------------------------------------------------------------------------- -void DrawMeasuredSections(void) -{ - int row = 1; - float rowheight = 0.025; - - CMeasureSection *p = CMeasureSection::GetList(); - while ( p ) - { - char str[256]; - Q_snprintf(str,sizeof(str),"%s",p->GetName()); - NDebugOverlay::ScreenText( 0.01,0.51+(row*rowheight),str, 255,255,255,255, 0.0 ); - - Q_snprintf(str,sizeof(str),"%5.2f\n",p->GetTime().GetMillisecondsF()); - //Q_snprintf(str,sizeof(str),"%3.3f\n",p->GetTime().GetSeconds() * 100.0 / engine->Time()); - NDebugOverlay::ScreenText( 0.28,0.51+(row*rowheight),str, 255,255,255,255, 0.0 ); - - Q_snprintf(str,sizeof(str),"%5.2f\n",p->GetMaxTime().GetMillisecondsF()); - //Q_snprintf(str,sizeof(str),"%3.3f\n",p->GetTime().GetSeconds() * 100.0 / engine->Time()); - NDebugOverlay::ScreenText( 0.34,0.51+(row*rowheight),str, 255,255,255,255, 0.0 ); - - - row++; - - p = p->GetNext(); - } - - bool sort_reset = false; - - // Time to redo sort? - if ( measure_resort.GetFloat() > 0.0 && - engine->Time() >= CMeasureSection::m_dNextResort ) - { - // Redo it - CMeasureSection::SortSections(); - // Set next time - CMeasureSection::m_dNextResort = engine->Time() + measure_resort.GetFloat(); - // Flag to reset sort accumulator, too - sort_reset = true; - } - - // Iterate through the sections now - p = CMeasureSection::GetList(); - while ( p ) - { - // Update max - p->UpdateMax(); - - // Reset regular accum. - p->Reset(); - // Reset sort accum less often - if ( sort_reset ) - { - p->SortReset(); - } - p = p->GetNext(); - } - -} -#endif - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void DrawAllDebugOverlays( void ) -{ - // If in debug select mode print the selection entities name or classname - if (CBaseEntity::m_bInDebugSelect) - { - CBasePlayer* pPlayer = UTIL_PlayerByIndex( CBaseEntity::m_nDebugPlayer ); - - if (pPlayer) - { - // First try to trace a hull to an entity - CBaseEntity *pEntity = FindPickerEntity( pPlayer ); - - if ( pEntity ) - { - pEntity->DrawDebugTextOverlays(); - pEntity->DrawBBoxOverlay(); - pEntity->SendDebugPivotOverlay(); - } - } - } - - // -------------------------------------------------------- - // Draw debug overlay lines - // -------------------------------------------------------- - UTIL_DrawOverlayLines(); - - // ------------------------------------------------------------------------ - // If in wc_edit mode draw a box to highlight which node I'm looking at - // ------------------------------------------------------------------------ - if (engine->IsInEditMode()) - { - CBasePlayer* pPlayer = UTIL_PlayerByIndex( CBaseEntity::m_nDebugPlayer ); - if (pPlayer) - { - if (g_pAINetworkManager->GetEditOps()->m_bLinkEditMode) - { - CAI_Link* pAILink = FindPickerAILink(pPlayer); - if (pAILink) - { - // For now just using one big AI network - Vector startPos = g_pBigAINet->GetNode(pAILink->m_iSrcID)->GetPosition(g_pAINetworkManager->GetEditOps()->m_iHullDrawNum); - Vector endPos = g_pBigAINet->GetNode(pAILink->m_iDestID)->GetPosition(g_pAINetworkManager->GetEditOps()->m_iHullDrawNum); - Vector linkDir = startPos-endPos; - float linkLen = VectorNormalize( linkDir ); - - // Draw in green if link that's been turned off - if (pAILink->m_LinkInfo & bits_LINK_OFF) - { - NDebugOverlay::BoxDirection(startPos, Vector(-4,-4,-4), Vector(-linkLen,4,4), linkDir, 0,255,0,40,0); - } - else - { - NDebugOverlay::BoxDirection(startPos, Vector(-4,-4,-4), Vector(-linkLen,4,4), linkDir, 255,0,0,40,0); - } - } - } - else - { - CAI_Node* pAINode; - if (g_pAINetworkManager->GetEditOps()->m_bAirEditMode) - { - pAINode = FindPickerAINode(pPlayer,NODE_AIR); - } - else - { - pAINode = FindPickerAINode(pPlayer,NODE_GROUND); - } - - if (pAINode) - { - Vector vecPos = pAINode->GetPosition(g_pAINetworkManager->GetEditOps()->m_iHullDrawNum); - NDebugOverlay::Box( vecPos, Vector(-8,-8,-8), Vector(8,8,8), 255,0,0,40,0); - - if ( pAINode->GetHint() ) - { - CBaseEntity *pEnt = (CBaseEntity *)pAINode->GetHint(); - if ( pEnt->GetEntityName() != NULL_STRING ) - { - NDebugOverlay::Text( vecPos + Vector(0,0,6), STRING(pEnt->GetEntityName()), false, 0 ); - } - NDebugOverlay::Text( vecPos, GetHintTypeDescription( pAINode->GetHint() ), false, 0 ); - } - } - } - // ------------------------------------ - // If in air edit mode draw guide line - // ------------------------------------ - if (g_pAINetworkManager->GetEditOps()->m_bAirEditMode) - { - UTIL_DrawPositioningOverlay(g_pAINetworkManager->GetEditOps()->m_flAirEditDistance); - } - else - { - NDebugOverlay::DrawGroundCrossHairOverlay(); - } - } - } - - // For not just using one big AI Network - if ( g_pAINetworkManager ) - { - g_pAINetworkManager->GetEditOps()->DrawAINetworkOverlay(); - } - - // PERFORMANCE: only do this in developer mode - if ( g_pDeveloper->GetInt() ) - { - // iterate through all objects for debug overlays - const CEntInfo *pInfo = gEntList.FirstEntInfo(); - - for ( ;pInfo; pInfo = pInfo->m_pNext ) - { - CBaseEntity *ent = (CBaseEntity *)pInfo->m_pEntity; - // HACKHACK: to flag off these calls - if ( ent->m_debugOverlays || ent->m_pTimedOverlay ) - { - MDLCACHE_CRITICAL_SECTION(); - ent->DrawDebugGeometryOverlays(); - } - } - } - - if ( sv_massreport.GetInt() ) - { - // iterate through all objects for debug overlays - const CEntInfo *pInfo = gEntList.FirstEntInfo(); - - for ( ;pInfo; pInfo = pInfo->m_pNext ) - { - CBaseEntity *ent = (CBaseEntity *)pInfo->m_pEntity; - if (!ent->VPhysicsGetObject()) - continue; - - char tempstr[512]; - Q_snprintf(tempstr, sizeof(tempstr),"%s: Mass: %.2f kg / %.2f lb (%s)", - STRING(ent->GetModelName()), ent->VPhysicsGetObject()->GetMass(), - kg2lbs(ent->VPhysicsGetObject()->GetMass()), - GetMassEquivalent(ent->VPhysicsGetObject()->GetMass())); - ent->EntityText(0, tempstr, 0); - } - } - - // A hack to draw point_message entities w/o developer required - DrawMessageEntities(); -} - -CServerGameDLL g_ServerGameDLL; -EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CServerGameDLL, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL, g_ServerGameDLL); - -bool CServerGameDLL::DLLInit( CreateInterfaceFn appSystemFactory, - CreateInterfaceFn physicsFactory, CreateInterfaceFn fileSystemFactory, - CGlobalVars *pGlobals) -{ - ConnectTier1Libraries( &appSystemFactory, 1 ); - ConnectTier2Libraries( &appSystemFactory, 1 ); - ConnectTier3Libraries( &appSystemFactory, 1 ); - - // Connected in ConnectTier1Libraries - if ( cvar == NULL ) - return false; - -#ifndef _X360 - g_SteamAPIContext.Init(); -#endif - - // init each (seperated for ease of debugging) - if ( (engine = (IVEngineServer*)appSystemFactory(INTERFACEVERSION_VENGINESERVER, NULL)) == NULL ) - return false; - if ( (g_pVoiceServer = (IVoiceServer*)appSystemFactory(INTERFACEVERSION_VOICESERVER, NULL)) == NULL ) - return false; - if ( (networkstringtable = (INetworkStringTableContainer *)appSystemFactory(INTERFACENAME_NETWORKSTRINGTABLESERVER,NULL)) == NULL ) - return false; - if ( (staticpropmgr = (IStaticPropMgrServer *)appSystemFactory(INTERFACEVERSION_STATICPROPMGR_SERVER,NULL)) == NULL ) - return false; - if ( (random = (IUniformRandomStream *)appSystemFactory(VENGINE_SERVER_RANDOM_INTERFACE_VERSION, NULL)) == NULL ) - return false; - if ( (enginesound = (IEngineSound *)appSystemFactory(IENGINESOUND_SERVER_INTERFACE_VERSION, NULL)) == NULL ) - return false; - if ( (partition = (ISpatialPartition *)appSystemFactory(INTERFACEVERSION_SPATIALPARTITION, NULL)) == NULL ) - return false; - if ( (modelinfo = (IVModelInfo *)appSystemFactory(VMODELINFO_SERVER_INTERFACE_VERSION, NULL)) == NULL ) - return false; - if ( (enginetrace = (IEngineTrace *)appSystemFactory(INTERFACEVERSION_ENGINETRACE_SERVER,NULL)) == NULL ) - return false; - if ( (filesystem = (IFileSystem *)fileSystemFactory(FILESYSTEM_INTERFACE_VERSION,NULL)) == NULL ) - return false; - if ( (gameeventmanager = (IGameEventManager2 *)appSystemFactory(INTERFACEVERSION_GAMEEVENTSMANAGER2,NULL)) == NULL ) - return false; - if ( (datacache = (IDataCache*)appSystemFactory(DATACACHE_INTERFACE_VERSION, NULL )) == NULL ) - return false; - if ( (soundemitterbase = (ISoundEmitterSystemBase *)appSystemFactory(SOUNDEMITTERSYSTEM_INTERFACE_VERSION, NULL)) == NULL ) - return false; -#ifndef _XBOX - if ( (gamestatsuploader = (IUploadGameStats *)appSystemFactory( INTERFACEVERSION_UPLOADGAMESTATS, NULL )) == NULL ) - return false; -#endif - if ( !mdlcache ) - return false; - if ( (serverpluginhelpers = (IServerPluginHelpers *)appSystemFactory(INTERFACEVERSION_ISERVERPLUGINHELPERS, NULL)) == NULL ) - return false; - if ( (scenefilecache = (ISceneFileCache *)appSystemFactory( SCENE_FILE_CACHE_INTERFACE_VERSION, NULL )) == NULL ) - return false; - if ( IsX360() && (xboxsystem = (IXboxSystem *)appSystemFactory( XBOXSYSTEM_INTERFACE_VERSION, NULL )) == NULL ) - return false; - if ( IsX360() && (matchmaking = (IMatchmaking *)appSystemFactory( VENGINE_MATCHMAKING_VERSION, NULL )) == NULL ) - return false; - - // If not running dedicated, grab the engine vgui interface - if ( !engine->IsDedicatedServer() ) - { -#ifdef _WIN32 - // This interface is optional, and is only valid when running with -tools - serverenginetools = ( IServerEngineTools * )appSystemFactory( VSERVERENGINETOOLS_INTERFACE_VERSION, NULL ); -#endif - } - - // Yes, both the client and game .dlls will try to Connect, the soundemittersystem.dll will handle this gracefully - if ( !soundemitterbase->Connect( appSystemFactory ) ) - return false; - - // cache the globals - gpGlobals = pGlobals; - - g_pSharedChangeInfo = engine->GetSharedEdictChangeInfo(); - - MathLib_Init( 2.2f, 2.2f, 0.0f, 2 ); - - // save these in case other system inits need them - factorylist_t factories; - factories.engineFactory = appSystemFactory; - factories.fileSystemFactory = fileSystemFactory; - factories.physicsFactory = physicsFactory; - FactoryList_Store( factories ); - - // load used game events - gameeventmanager->LoadEventsFromFile("resource/gameevents.res"); - - // init the cvar list first in case inits want to reference them - InitializeCvars(); - - // Initialize the particle system - if ( !g_pParticleSystemMgr->Init( g_pParticleSystemQuery ) ) - { - return false; - } - - sv_cheats = g_pCVar->FindVar( "sv_cheats" ); - if ( !sv_cheats ) - return false; - - g_pcv_commentary = g_pCVar->FindVar( "commentary" ); - g_pcv_ThreadMode = g_pCVar->FindVar( "host_thread_mode" ); - - sv_maxreplay = g_pCVar->FindVar( "sv_maxreplay" ); - - g_pGameSaveRestoreBlockSet->AddBlockHandler( GetEntitySaveRestoreBlockHandler() ); - g_pGameSaveRestoreBlockSet->AddBlockHandler( GetPhysSaveRestoreBlockHandler() ); - g_pGameSaveRestoreBlockSet->AddBlockHandler( GetAISaveRestoreBlockHandler() ); - g_pGameSaveRestoreBlockSet->AddBlockHandler( GetTemplateSaveRestoreBlockHandler() ); - g_pGameSaveRestoreBlockSet->AddBlockHandler( GetDefaultResponseSystemSaveRestoreBlockHandler() ); - g_pGameSaveRestoreBlockSet->AddBlockHandler( GetCommentarySaveRestoreBlockHandler() ); - g_pGameSaveRestoreBlockSet->AddBlockHandler( GetEventQueueSaveRestoreBlockHandler() ); - g_pGameSaveRestoreBlockSet->AddBlockHandler( GetAchievementSaveRestoreBlockHandler() ); - - // The string system must init first + shutdown last - IGameSystem::Add( GameStringSystem() ); - - // Physics must occur before the sound envelope manager - IGameSystem::Add( PhysicsGameSystem() ); - - // Used to service deferred navigation queries for NPCs - IGameSystem::Add( (IGameSystem *) PostFrameNavigationSystem() ); - - // Add game log system - IGameSystem::Add( GameLogSystem() ); -#ifndef _XBOX - // Add HLTV director - IGameSystem::Add( HLTVDirectorSystem() ); -#endif - // Add sound emitter - IGameSystem::Add( SoundEmitterSystem() ); - - // load Mod specific game events ( MUST be before InitAllSystems() so it can pickup the mod specific events) - gameeventmanager->LoadEventsFromFile("resource/ModEvents.res"); - -#ifdef CSTRIKE_DLL // BOTPORT: TODO: move these ifdefs out - InstallBotControl(); -#endif - - if ( !IGameSystem::InitAllSystems() ) - return false; - - // Due to dependencies, these are not autogamesystems - if ( !ModelSoundsCacheInit() ) - { - return false; - } - - // Parse the particle manifest file & register the effects within it - ParseParticleEffects( false ); - - // try to get debug overlay, may be NULL if on HLDS - debugoverlay = (IVDebugOverlay *)appSystemFactory( VDEBUG_OVERLAY_INTERFACE_VERSION, NULL ); - -#ifndef _XBOX - // create the Navigation Mesh interface - TheNavMesh = new CNavMesh; - - // init the gamestatsupload connection - gamestatsuploader->InitConnection(); -#endif - - return true; -} - -void CServerGameDLL::PostInit() -{ - IGameSystem::PostInitAllSystems(); -} - -void CServerGameDLL::DLLShutdown( void ) -{ - - // Due to dependencies, these are not autogamesystems - ModelSoundsCacheShutdown(); - - g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetAchievementSaveRestoreBlockHandler() ); - g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetCommentarySaveRestoreBlockHandler() ); - g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetEventQueueSaveRestoreBlockHandler() ); - g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetDefaultResponseSystemSaveRestoreBlockHandler() ); - g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetTemplateSaveRestoreBlockHandler() ); - g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetAISaveRestoreBlockHandler() ); - g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetPhysSaveRestoreBlockHandler() ); - g_pGameSaveRestoreBlockSet->RemoveBlockHandler( GetEntitySaveRestoreBlockHandler() ); - - char *pFilename = g_TextStatsMgr.GetStatsFilename(); - if ( !pFilename || !pFilename[0] ) - { - g_TextStatsMgr.SetStatsFilename( "stats.txt" ); - } - g_TextStatsMgr.WriteFile( filesystem ); - - IGameSystem::ShutdownAllSystems(); - -#ifdef CSTRIKE_DLL // BOTPORT: TODO: move these ifdefs out - RemoveBotControl(); -#endif - -#ifndef _XBOX - // destroy the Navigation Mesh interface - if (TheNavMesh) - { - delete TheNavMesh; - TheNavMesh = NULL; - } -#endif - - DisconnectTier3Libraries(); - DisconnectTier2Libraries(); - ConVar_Unregister(); - DisconnectTier1Libraries(); -} - - -//----------------------------------------------------------------------------- -// Purpose: See shareddefs.h for redefining this. Don't even think about it, though, for HL2. Or you will pay. ywb 9/22/03 -// Output : float -//----------------------------------------------------------------------------- -float CServerGameDLL::GetTickInterval( void ) const -{ - float tickinterval = DEFAULT_TICK_INTERVAL; - -#if defined( CSTRIKE_DLL ) - // in CS reduce tickrate/sec by defualt - tickinterval *= 2; -#endif - -// Ignoring this for now, server ops are abusing it -#if !defined( TF_DLL ) - // override if tick rate specified in command line - if ( CommandLine()->CheckParm( "-tickrate" ) ) - { - float tickrate = CommandLine()->ParmValue( "-tickrate", 0 ); - if ( tickrate > 10 ) - tickinterval = 1.0f / tickrate; - } -#endif - - return tickinterval; -} - -// This is called when a new game is started. (restart, map) -bool CServerGameDLL::GameInit( void ) -{ - ResetGlobalState(); - engine->ServerCommand( "exec game.cfg\n" ); - engine->ServerExecute( ); - CBaseEntity::sm_bAccurateTriggerBboxChecks = true; - - IGameEvent *event = gameeventmanager->CreateEvent( "game_init" ); - if ( event ) - { - gameeventmanager->FireEvent( event ); - } - - return true; -} - -// This is called when a game ends (server disconnect, death, restart, load) -// NOT on level transitions within a game -void CServerGameDLL::GameShutdown( void ) -{ - ResetGlobalState(); -} - -static bool g_OneWayTransition = false; -void Game_SetOneWayTransition( void ) -{ - g_OneWayTransition = true; -} - -static CUtlVector g_RestoredEntities; -// just for debugging, assert that this is the only time this function is called -static bool g_InRestore = false; - -void AddRestoredEntity( CBaseEntity *pEntity ) -{ - Assert(g_InRestore); - if ( !pEntity ) - return; - - g_RestoredEntities.AddToTail( EHANDLE(pEntity) ); -} - -void EndRestoreEntities() -{ - if ( !g_InRestore ) - return; - - // The entire hierarchy is restored, so we can call GetAbsOrigin again. - //CBaseEntity::SetAbsQueriesValid( true ); - - // Call all entities' OnRestore handlers - for ( int i = g_RestoredEntities.Count()-1; i >=0; --i ) - { - CBaseEntity *pEntity = g_RestoredEntities[i].Get(); - if ( pEntity && !pEntity->IsDormant() ) - { - MDLCACHE_CRITICAL_SECTION(); - pEntity->OnRestore(); - } - } - - g_RestoredEntities.Purge(); - - IGameSystem::OnRestoreAllSystems(); - - g_InRestore = false; - gEntList.CleanupDeleteList(); - - // HACKHACK: UNDONE: We need to redesign the main loop with respect to save/load/server activate - g_ServerGameDLL.ServerActivate( NULL, 0, 0 ); - CBaseEntity::SetAllowPrecache( false ); -} - -void BeginRestoreEntities() -{ - if ( g_InRestore ) - { - DevMsg( "BeginRestoreEntities without previous EndRestoreEntities.\n" ); - gEntList.CleanupDeleteList(); - } - g_RestoredEntities.Purge(); - g_InRestore = true; - - CBaseEntity::SetAllowPrecache( true ); - - // No calls to GetAbsOrigin until the entire hierarchy is restored! - //CBaseEntity::SetAbsQueriesValid( false ); -} - -//----------------------------------------------------------------------------- -// Purpose: This prevents sv.tickcount/gpGlobals->tickcount from advancing during restore which -// would cause a lot of the NPCs to fast forward their think times to the same -// tick due to some ticks being elapsed during restore where there was no simulation going on -//----------------------------------------------------------------------------- -bool CServerGameDLL::IsRestoring() -{ - return g_InRestore; -} - -// Called any time a new level is started (after GameInit() also on level transitions within a game) -bool CServerGameDLL::LevelInit( const char *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background ) -{ - VPROF("CServerGameDLL::LevelInit"); - ResetWindspeed(); - UpdateChapterRestrictions( pMapName ); - - if ( IsX360() && !background && (gpGlobals->maxClients == 1) && (g_nCurrentChapterIndex >= 0) ) - { - // Single player games tell xbox live what game & chapter the user is playing - UpdateRichPresence(); - } - - // IGameSystem::LevelInitPreEntityAllSystems() is called when the world is precached - // That happens either in LoadGameState() or in MapEntity_ParseAllEntities() - if ( loadGame ) - { - if ( pOldLevel ) - { - gpGlobals->eLoadType = MapLoad_Transition; - } - else - { - gpGlobals->eLoadType = MapLoad_LoadGame; - } - - BeginRestoreEntities(); - if ( !engine->LoadGameState( pMapName, 1 ) ) - { - if ( pOldLevel ) - { - MapEntity_ParseAllEntities( pMapEntities ); - } - else - { - // Regular save load case - return false; - } - } - - if ( pOldLevel ) - { - engine->LoadAdjacentEnts( pOldLevel, pLandmarkName ); - } - - if ( g_OneWayTransition ) - { - engine->ClearSaveDirAfterClientLoad(); - } - - if ( pOldLevel && sv_autosave.GetBool() == true ) - { - // This is a single-player style level transition. - // Queue up an autosave one second into the level - CBaseEntity *pAutosave = CBaseEntity::Create( "logic_autosave", vec3_origin, vec3_angle, NULL ); - if ( pAutosave ) - { - g_EventQueue.AddEvent( pAutosave, "Save", 1.0, NULL, NULL ); - g_EventQueue.AddEvent( pAutosave, "Kill", 1.1, NULL, NULL ); - } - } - } - else - { - if ( background ) - { - gpGlobals->eLoadType = MapLoad_Background; - } - else - { - gpGlobals->eLoadType = MapLoad_NewGame; - } - - // Clear out entity references, and parse the entities into it. - g_MapEntityRefs.Purge(); - CMapLoadEntityFilter filter; - MapEntity_ParseAllEntities( pMapEntities, &filter ); - - g_pServerBenchmark->StartBenchmark(); - - // Now call the mod specific parse - LevelInit_ParseAllEntities( pMapEntities ); - } - - // Check low violence settings for this map - g_RagdollLVManager.SetLowViolence( pMapName ); - - // Now that all of the active entities have been loaded in, precache any entities who need point_template parameters - // to be parsed (the above code has loaded all point_template entities) - PrecachePointTemplates(); - - // load MOTD from file into stringtable - LoadMessageOfTheDay(); - - // Sometimes an ent will Remove() itself during its precache, so RemoveImmediate won't happen. - // This makes sure those ents get cleaned up. - gEntList.CleanupDeleteList(); - - g_AIFriendliesTalkSemaphore.Release(); - g_AIFoesTalkSemaphore.Release(); - g_OneWayTransition = false; - - // clear any pending autosavedangerous - m_fAutoSaveDangerousTime = 0.0f; - m_fAutoSaveDangerousMinHealthToCommit = 0.0f; - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: called after every level change and load game, iterates through all the -// active entities and gives them a chance to fix up their state -//----------------------------------------------------------------------------- -#ifdef DEBUG -bool g_bReceivedChainedActivate; -bool g_bCheckForChainedActivate; -#define BeginCheckChainedActivate() if (0) ; else { g_bCheckForChainedActivate = true; g_bReceivedChainedActivate = false; } -#define EndCheckChainedActivate( bCheck ) \ - if (0) ; else \ - { \ - if ( bCheck ) \ - { \ - char msg[ 1024 ]; \ - Q_snprintf( msg, sizeof( msg ), "Entity (%i/%s/%s) failed to call base class Activate()\n", pClass->entindex(), pClass->GetClassname(), STRING( pClass->GetEntityName() ) ); \ - AssertMsg( g_bReceivedChainedActivate == true, msg ); \ - } \ - g_bCheckForChainedActivate = false; \ - } -#else -#define BeginCheckChainedActivate() ((void)0) -#define EndCheckChainedActivate( bCheck ) ((void)0) -#endif - -void CServerGameDLL::ServerActivate( edict_t *pEdictList, int edictCount, int clientMax ) -{ - // HACKHACK: UNDONE: We need to redesign the main loop with respect to save/load/server activate - if ( g_InRestore ) - return; - - if ( gEntList.ResetDeleteList() != 0 ) - { - Msg( "ERROR: Entity delete queue not empty on level start!\n" ); - } - - for ( CBaseEntity *pClass = gEntList.FirstEnt(); pClass != NULL; pClass = gEntList.NextEnt(pClass) ) - { - if ( pClass && !pClass->IsDormant() ) - { - MDLCACHE_CRITICAL_SECTION(); - - BeginCheckChainedActivate(); - pClass->Activate(); - - // We don't care if it finished activating if it decided to remove itself. - EndCheckChainedActivate( !( pClass->GetEFlags() & EFL_KILLME ) ); - } - } - - IGameSystem::LevelInitPostEntityAllSystems(); - // No more precaching after PostEntityAllSystems!!! - CBaseEntity::SetAllowPrecache( false ); - - // only display the think limit when the game is run with "developer" mode set - if ( !g_pDeveloper->GetInt() ) - { - think_limit.SetValue( 0 ); - } - -#ifndef _XBOX - // load the Navigation Mesh for this map - TheNavMesh->Load(); -#endif - -#ifdef CSTRIKE_DLL // BOTPORT: TODO: move these ifdefs out - TheBots->ServerActivate(); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Called at the start of every game frame -//----------------------------------------------------------------------------- -ConVar trace_report( "trace_report", "0" ); - -void CServerGameDLL::GameFrame( bool simulating ) -{ - VPROF( "CServerGameDLL::GameFrame" ); - - // Don't run frames until fully restored - if ( g_InRestore ) - return; - - if ( CBaseEntity::IsSimulatingOnAlternateTicks() ) - { - // only run simulation on even numbered ticks - if ( gpGlobals->tickcount & 1 ) - { - UpdateAllClientData(); - return; - } - // If we're skipping frames, then the frametime is 2x the normal tick - gpGlobals->frametime *= 2.0f; - } - - float oldframetime = gpGlobals->frametime; - -#ifdef _DEBUG - // For profiling.. let them enable/disable the networkvar manual mode stuff. - g_bUseNetworkVars = s_UseNetworkVars.GetBool(); -#endif - - extern void GameStartFrame( void ); - extern void ServiceEventQueue( void ); - extern void Physics_RunThinkFunctions( bool simulating ); - - // Delete anything that was marked for deletion - // outside of server frameloop (e.g., in response to concommand) - gEntList.CleanupDeleteList(); - - IGameSystem::FrameUpdatePreEntityThinkAllSystems(); - GameStartFrame(); - -#ifndef _XBOX - TheNavMesh->Update(); - - gamestatsuploader->UpdateConnection(); -#endif - - g_pServerBenchmark->UpdateBenchmark(); - - Physics_RunThinkFunctions( simulating ); - - IGameSystem::FrameUpdatePostEntityThinkAllSystems(); - - // UNDONE: Make these systems IGameSystems and move these calls into FrameUpdatePostEntityThink() - // service event queue, firing off any actions whos time has come - ServiceEventQueue(); - - // free all ents marked in think functions - gEntList.CleanupDeleteList(); - - // FIXME: Should this only occur on the final tick? - UpdateAllClientData(); - - if ( g_pGameRules ) - { - g_pGameRules->EndGameFrame(); - } - - if ( trace_report.GetBool() ) - { - int total = 0, totals[3]; - for ( int i = 0; i < 3; i++ ) - { - totals[i] = enginetrace->GetStatByIndex( i, true ); - if ( totals[i] > 0 ) - { - total += totals[i]; - } - } - - if ( total ) - { - Msg("Trace: %d, contents %d, enumerate %d\n", totals[0], totals[1], totals[2] ); - } - } - - // Any entities that detect network state changes on a timer do it here. - g_NetworkPropertyEventMgr.FireEvents(); - - gpGlobals->frametime = oldframetime; -} - -//----------------------------------------------------------------------------- -// Purpose: Called every frame even if not ticking -// Input : simulating - -//----------------------------------------------------------------------------- -void CServerGameDLL::PreClientUpdate( bool simulating ) -{ - if ( !simulating ) - return; - - /* - if (game_speeds.GetInt()) - { - DrawMeasuredSections(); - } - */ - -//#ifdef _DEBUG - allow this in release for now - DrawAllDebugOverlays(); -//#endif - - IGameSystem::PreClientUpdateAllSystems(); - - if ( sv_showhitboxes.GetInt() == -1 ) - return; - - if ( sv_showhitboxes.GetInt() == 0 ) - { - // assume it's text - CBaseEntity *pEntity = NULL; - - while (1) - { - pEntity = gEntList.FindEntityByName( pEntity, sv_showhitboxes.GetString() ); - if ( !pEntity ) - break; - - CBaseAnimating *anim = dynamic_cast< CBaseAnimating * >( pEntity ); - - if (anim) - { - anim->DrawServerHitboxes(); - } - } - return; - } - - CBaseAnimating *anim = dynamic_cast< CBaseAnimating * >( CBaseEntity::Instance( engine->PEntityOfEntIndex( sv_showhitboxes.GetInt() ) ) ); - if ( !anim ) - return; - - anim->DrawServerHitboxes(); -} - -void CServerGameDLL::Think( bool finalTick ) -{ - if ( m_fAutoSaveDangerousTime != 0.0f && m_fAutoSaveDangerousTime < gpGlobals->curtime ) - { - // The safety timer for a dangerous auto save has expired - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); - - if ( pPlayer && ( pPlayer->GetDeathTime() == 0.0f || pPlayer->GetDeathTime() > gpGlobals->curtime ) - && !pPlayer->IsSinglePlayerGameEnding() - ) - { - if( pPlayer->GetHealth() >= m_fAutoSaveDangerousMinHealthToCommit ) - { - // The player isn't dead, so make the dangerous auto save safe - engine->ServerCommand( "autosavedangerousissafe\n" ); - } - } - - m_fAutoSaveDangerousTime = 0.0f; - m_fAutoSaveDangerousMinHealthToCommit = 0.0f; - } -} - -void CServerGameDLL::OnQueryCvarValueFinished( QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue ) -{ -} - - -// Called when a level is shutdown (including changing levels) -void CServerGameDLL::LevelShutdown( void ) -{ - MDLCACHE_CRITICAL_SECTION(); - IGameSystem::LevelShutdownPreEntityAllSystems(); - - // YWB: - // This entity pointer is going away now and is corrupting memory on level transitions/restarts - CSoundEnt::ShutdownSoundEnt(); - - gEntList.Clear(); - - IGameSystem::LevelShutdownPostEntityAllSystems(); - - // In case we quit out during initial load - CBaseEntity::SetAllowPrecache( false ); - - g_nCurrentChapterIndex = -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : ServerClass* -//----------------------------------------------------------------------------- -ServerClass* CServerGameDLL::GetAllServerClasses() -{ - return g_pServerClassHead; -} - - -const char *CServerGameDLL::GetGameDescription( void ) -{ - return ::GetGameDescription(); -} - -void CServerGameDLL::CreateNetworkStringTables( void ) -{ - // Create any shared string tables here (and only here!) - // E.g.: xxx = networkstringtable->CreateStringTable( "SceneStrings", 512 ); - g_pStringTableParticleEffectNames = networkstringtable->CreateStringTable( "ParticleEffectNames", MAX_PARTICLESYSTEMS_STRINGS ); - g_pStringTableEffectDispatch = networkstringtable->CreateStringTable( "EffectDispatch", MAX_EFFECT_DISPATCH_STRINGS ); - g_pStringTableVguiScreen = networkstringtable->CreateStringTable( "VguiScreen", MAX_VGUI_SCREEN_STRINGS ); - g_pStringTableMaterials = networkstringtable->CreateStringTable( "Materials", MAX_MATERIAL_STRINGS ); - g_pStringTableInfoPanel = networkstringtable->CreateStringTable( "InfoPanel", MAX_INFOPANEL_STRINGS ); - g_pStringTableClientSideChoreoScenes = networkstringtable->CreateStringTable( "Scenes", MAX_CHOREO_SCENES_STRINGS ); - - Assert( g_pStringTableParticleEffectNames && - g_pStringTableEffectDispatch && - g_pStringTableVguiScreen && - g_pStringTableMaterials && - g_pStringTableInfoPanel && - g_pStringTableClientSideChoreoScenes ); - - // Need this so we have the error material always handy - PrecacheMaterial( "debug/debugempty" ); - Assert( GetMaterialIndex( "debug/debugempty" ) == 0 ); - - PrecacheParticleSystem( "error" ); // ensure error particle system is handy - Assert( GetParticleSystemIndex( "error" ) == 0 ); - - CreateNetworkStringTables_GameRules(); - - // Set up save/load utilities for string tables - g_VguiScreenStringOps.Init( g_pStringTableVguiScreen ); -} - -CSaveRestoreData *CServerGameDLL::SaveInit( int size ) -{ - return ::SaveInit(size); -} - -//----------------------------------------------------------------------------- -// Purpose: Saves data from a struct into a saverestore object, to be saved to disk -// Input : *pSaveData - the saverestore object -// char *pname - the name of the data to write -// *pBaseData - the struct into which the data is to be read -// *pFields - pointer to an array of data field descriptions -// fieldCount - the size of the array (number of field descriptions) -//----------------------------------------------------------------------------- -void CServerGameDLL::SaveWriteFields( CSaveRestoreData *pSaveData, const char *pname, void *pBaseData, datamap_t *pMap, typedescription_t *pFields, int fieldCount ) -{ - CSave saveHelper( pSaveData ); - saveHelper.WriteFields( pname, pBaseData, pMap, pFields, fieldCount ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Reads data from a save/restore block into a structure -// Input : *pSaveData - the saverestore object -// char *pname - the name of the data to extract from -// *pBaseData - the struct into which the data is to be restored -// *pFields - pointer to an array of data field descriptions -// fieldCount - the size of the array (number of field descriptions) -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- - -void CServerGameDLL::SaveReadFields( CSaveRestoreData *pSaveData, const char *pname, void *pBaseData, datamap_t *pMap, typedescription_t *pFields, int fieldCount ) -{ - CRestore restoreHelper( pSaveData ); - restoreHelper.ReadFields( pname, pBaseData, pMap, pFields, fieldCount ); -} - -//----------------------------------------------------------------------------- - -void CServerGameDLL::SaveGlobalState( CSaveRestoreData *s ) -{ - ::SaveGlobalState(s); -} - -void CServerGameDLL::RestoreGlobalState(CSaveRestoreData *s) -{ - ::RestoreGlobalState(s); -} - -void CServerGameDLL::Save( CSaveRestoreData *s ) -{ - CSave saveHelper( s ); - g_pGameSaveRestoreBlockSet->Save( &saveHelper ); -} - -void CServerGameDLL::Restore( CSaveRestoreData *s, bool b) -{ - CRestore restore(s); - g_pGameSaveRestoreBlockSet->Restore( &restore, b ); - g_pGameSaveRestoreBlockSet->PostRestore(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_type - -// *name - -// size - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- - -bool CServerGameDLL::GetUserMessageInfo( int msg_type, char *name, int maxnamelength, int& size ) -{ - if ( !usermessages->IsValidIndex( msg_type ) ) - return false; - - Q_strncpy( name, usermessages->GetUserMessageName( msg_type ), maxnamelength ); - size = usermessages->GetUserMessageSize( msg_type ); - return true; -} - -CStandardSendProxies* CServerGameDLL::GetStandardSendProxies() -{ - return &g_StandardSendProxies; -} - -int CServerGameDLL::CreateEntityTransitionList( CSaveRestoreData *s, int a) -{ - CRestore restoreHelper( s ); - // save off file base - int base = restoreHelper.GetReadPos(); - - int movedCount = ::CreateEntityTransitionList(s, a); - if ( movedCount ) - { - g_pGameSaveRestoreBlockSet->CallBlockHandlerRestore( GetPhysSaveRestoreBlockHandler(), base, &restoreHelper, false ); - g_pGameSaveRestoreBlockSet->CallBlockHandlerRestore( GetAISaveRestoreBlockHandler(), base, &restoreHelper, false ); - } - - GetPhysSaveRestoreBlockHandler()->PostRestore(); - GetAISaveRestoreBlockHandler()->PostRestore(); - - return movedCount; -} - -void CServerGameDLL::PreSave( CSaveRestoreData *s ) -{ - g_pGameSaveRestoreBlockSet->PreSave( s ); -} - -#include "client_textmessage.h" - -// This little hack lets me marry BSP names to messages in titles.txt -typedef struct -{ - const char *pBSPName; - const char *pTitleName; -} TITLECOMMENT; - -// this list gets searched for the first partial match, so some are out of order -static TITLECOMMENT gTitleComments[] = -{ -#ifdef HL1_DLL - { "t0a0", "#T0A0TITLE" }, - { "c0a0", "#HL1_Chapter1_Title" }, - { "c1a0", "#HL1_Chapter2_Title" }, - { "c1a1", "#HL1_Chapter3_Title" }, - { "c1a2", "#HL1_Chapter4_Title" }, - { "c1a3", "#HL1_Chapter5_Title" }, - { "c1a4", "#HL1_Chapter6_Title" }, - { "c2a1", "#HL1_Chapter7_Title" }, - { "c2a2", "#HL1_Chapter8_Title" }, - { "c2a3", "#HL1_Chapter9_Title" }, - { "c2a4d", "#HL1_Chapter11_Title" }, // These must appear before "C2A4" so all other map names starting with C2A4 get that title - { "c2a4e", "#HL1_Chapter11_Title" }, - { "c2a4f", "#HL1_Chapter11_Title" }, - { "c2a4g", "#HL1_Chapter11_Title" }, - { "c2a4", "#HL1_Chapter10_Title" }, - { "c2a5", "#HL1_Chapter12_Title" }, - { "c3a1", "#HL1_Chapter13_Title" }, - { "c3a2", "#HL1_Chapter14_Title" }, - { "c4a1a", "#HL1_Chapter17_Title" }, // Order is important, see above - { "c4a1b", "#HL1_Chapter17_Title" }, - { "c4a1c", "#HL1_Chapter17_Title" }, - { "c4a1d", "#HL1_Chapter17_Title" }, - { "c4a1e", "#HL1_Chapter17_Title" }, - { "c4a1", "#HL1_Chapter15_Title" }, - { "c4a2", "#HL1_Chapter16_Title" }, - { "c4a3", "#HL1_Chapter18_Title" }, - { "c5a1", "#HL1_Chapter19_Title" }, -#elif defined PORTAL - { "testchmb_a_00", "#Portal_Chapter1_Title" }, - { "testchmb_a_01", "#Portal_Chapter1_Title" }, - { "testchmb_a_02", "#Portal_Chapter2_Title" }, - { "testchmb_a_03", "#Portal_Chapter2_Title" }, - { "testchmb_a_04", "#Portal_Chapter3_Title" }, - { "testchmb_a_05", "#Portal_Chapter3_Title" }, - { "testchmb_a_06", "#Portal_Chapter4_Title" }, - { "testchmb_a_07", "#Portal_Chapter4_Title" }, - { "testchmb_a_08_advanced", "#Portal_Chapter5_Title" }, - { "testchmb_a_08", "#Portal_Chapter5_Title" }, - { "testchmb_a_09_advanced", "#Portal_Chapter6_Title" }, - { "testchmb_a_09", "#Portal_Chapter6_Title" }, - { "testchmb_a_10_advanced", "#Portal_Chapter7_Title" }, - { "testchmb_a_10", "#Portal_Chapter7_Title" }, - { "testchmb_a_11_advanced", "#Portal_Chapter8_Title" }, - { "testchmb_a_11", "#Portal_Chapter8_Title" }, - { "testchmb_a_13_advanced", "#Portal_Chapter9_Title" }, - { "testchmb_a_13", "#Portal_Chapter9_Title" }, - { "testchmb_a_14_advanced", "#Portal_Chapter10_Title" }, - { "testchmb_a_14", "#Portal_Chapter10_Title" }, - { "testchmb_a_15", "#Portal_Chapter11_Title" }, - { "escape_", "#Portal_Chapter11_Title" }, - { "background2", "#Portal_Chapter12_Title" }, -#else - { "intro", "#HL2_Chapter1_Title" }, - - { "d1_trainstation_05", "#HL2_Chapter2_Title" }, - { "d1_trainstation_06", "#HL2_Chapter2_Title" }, - - { "d1_trainstation_", "#HL2_Chapter1_Title" }, - - { "d1_canals_06", "#HL2_Chapter4_Title" }, - { "d1_canals_07", "#HL2_Chapter4_Title" }, - { "d1_canals_08", "#HL2_Chapter4_Title" }, - { "d1_canals_09", "#HL2_Chapter4_Title" }, - { "d1_canals_1", "#HL2_Chapter4_Title" }, - - { "d1_canals_0", "#HL2_Chapter3_Title" }, - - { "d1_eli_", "#HL2_Chapter5_Title" }, - - { "d1_town_", "#HL2_Chapter6_Title" }, - - { "d2_coast_09", "#HL2_Chapter8_Title" }, - { "d2_coast_1", "#HL2_Chapter8_Title" }, - { "d2_prison_01", "#HL2_Chapter8_Title" }, - - { "d2_coast_", "#HL2_Chapter7_Title" }, - - { "d2_prison_06", "#HL2_Chapter9a_Title" }, - { "d2_prison_07", "#HL2_Chapter9a_Title" }, - { "d2_prison_08", "#HL2_Chapter9a_Title" }, - - { "d2_prison_", "#HL2_Chapter9_Title" }, - - { "d3_c17_01", "#HL2_Chapter9a_Title" }, - { "d3_c17_09", "#HL2_Chapter11_Title" }, - { "d3_c17_1", "#HL2_Chapter11_Title" }, - - { "d3_c17_", "#HL2_Chapter10_Title" }, - - { "d3_citadel_", "#HL2_Chapter12_Title" }, - - { "d3_breen_", "#HL2_Chapter13_Title" }, - { "credits", "#HL2_Chapter14_Title" }, - - { "ep1_citadel_00", "#episodic_Chapter1_Title" }, - { "ep1_citadel_01", "#episodic_Chapter1_Title" }, - { "ep1_citadel_02b", "#episodic_Chapter1_Title" }, - { "ep1_citadel_02", "#episodic_Chapter1_Title" }, - { "ep1_citadel_03", "#episodic_Chapter2_Title" }, - { "ep1_citadel_04", "#episodic_Chapter2_Title" }, - { "ep1_c17_00a", "#episodic_Chapter3_Title" }, - { "ep1_c17_00", "#episodic_Chapter3_Title" }, - { "ep1_c17_01", "#episodic_Chapter4_Title" }, - { "ep1_c17_02b", "#episodic_Chapter4_Title" }, - { "ep1_c17_02", "#episodic_Chapter4_Title" }, - { "ep1_c17_05", "#episodic_Chapter5_Title" }, - { "ep1_c17_06", "#episodic_Chapter5_Title" }, - - { "ep2_outland_01a", "#ep2_Chapter1_Title" }, - { "ep2_outland_01", "#ep2_Chapter1_Title" }, - { "ep2_outland_02", "#ep2_Chapter2_Title" }, - { "ep2_outland_03", "#ep2_Chapter2_Title" }, - { "ep2_outland_04", "#ep2_Chapter2_Title" }, - { "ep2_outland_05", "#ep2_Chapter3_Title" }, - - { "ep2_outland_06a", "#ep2_Chapter4_Title" }, - { "ep2_outland_06", "#ep2_Chapter3_Title" }, - - { "ep2_outland_07", "#ep2_Chapter4_Title" }, - { "ep2_outland_08", "#ep2_Chapter4_Title" }, - { "ep2_outland_09", "#ep2_Chapter5_Title" }, - - { "ep2_outland_10a", "#ep2_Chapter5_Title" }, - { "ep2_outland_10", "#ep2_Chapter5_Title" }, - - { "ep2_outland_11a", "#ep2_Chapter6_Title" }, - { "ep2_outland_11", "#ep2_Chapter6_Title" }, - - { "ep2_outland_12a", "#ep2_Chapter7_Title" }, - { "ep2_outland_12", "#ep2_Chapter6_Title" }, -#endif -}; - -#ifdef _XBOX -void CServerGameDLL::GetTitleName( const char *pMapName, char* pTitleBuff, int titleBuffSize ) -{ - // Try to find a matching title comment for this mapname - for ( int i = 0; i < ARRAYSIZE(gTitleComments); i++ ) - { - if ( !Q_strnicmp( pMapName, gTitleComments[i].pBSPName, strlen(gTitleComments[i].pBSPName) ) ) - { - Q_strncpy( pTitleBuff, gTitleComments[i].pTitleName, titleBuffSize ); - return; - } - } - Q_strncpy( pTitleBuff, pMapName, titleBuffSize ); -} -#endif - -void CServerGameDLL::GetSaveComment( char *text, int maxlength, float flMinutes, float flSeconds, bool bNoTime ) -{ - char comment[64]; - const char *pName; - size_t i; - - char const *mapname = STRING( gpGlobals->mapname ); - - pName = NULL; - - // Try to find a matching title comment for this mapname - for ( i = 0; i < ARRAYSIZE(gTitleComments) && !pName; i++ ) - { - if ( !Q_strnicmp( mapname, gTitleComments[i].pBSPName, strlen(gTitleComments[i].pBSPName) ) ) - { - // found one - size_t j; - - // Got a message, post-process it to be save name friendly - Q_strncpy( comment, gTitleComments[i].pTitleName, sizeof( comment ) ); - pName = comment; - j = 0; - // Strip out CRs - while ( j < 64 && comment[j] ) - { - if ( comment[j] == '\n' || comment[j] == '\r' ) - comment[j] = 0; - else - j++; - } - break; - } - } - - // If we didn't get one, use the designer's map name, or the BSP name itself - if ( !pName ) - { - pName = mapname; - } - - if ( bNoTime ) - { - Q_snprintf( text, maxlength, "%-64.64s", pName ); - } - else - { - int minutes = (int)flMinutes; - int seconds = (int)flSeconds; - - // Wow, this guy/gal must suck...! - if ( minutes >= 1000 ) - { - minutes = 999; - seconds = 59; - } - - int minutesAdd = ( seconds / 60 ); - seconds %= 60; - - // add the elapsed time at the end of the comment, for the ui to parse out - Q_snprintf( text, maxlength, "%-64.64s %03d:%02d", pName, (minutes + minutesAdd), seconds ); - } -} - -void CServerGameDLL::WriteSaveHeaders( CSaveRestoreData *s ) -{ - CSave saveHelper( s ); - g_pGameSaveRestoreBlockSet->WriteSaveHeaders( &saveHelper ); - g_pGameSaveRestoreBlockSet->PostSave(); -} - -void CServerGameDLL::ReadRestoreHeaders( CSaveRestoreData *s ) -{ - CRestore restoreHelper( s ); - g_pGameSaveRestoreBlockSet->PreRestore(); - g_pGameSaveRestoreBlockSet->ReadRestoreHeaders( &restoreHelper ); -} - -void CServerGameDLL::PreSaveGameLoaded( char const *pSaveName, bool bInGame ) -{ - gamestats->Event_PreSaveGameLoaded( pSaveName, bInGame ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true if the game DLL wants the server not to be made public. -// Used by commentary system to hide multiplayer commentary servers from the master. -//----------------------------------------------------------------------------- -bool CServerGameDLL::ShouldHideServer( void ) -{ - if ( g_pcv_commentary && g_pcv_commentary->GetBool() ) - return true; - - if ( gpGlobals->eLoadType == MapLoad_Background ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -void CServerGameDLL::InvalidateMdlCache() -{ - CBaseAnimating *pAnimating; - for ( CBaseEntity *pEntity = gEntList.FirstEnt(); pEntity != NULL; pEntity = gEntList.NextEnt(pEntity) ) - { - pAnimating = dynamic_cast(pEntity); - if ( pAnimating ) - { - pAnimating->InvalidateMdlCache(); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Called during a transition, to build a map adjacency list -//----------------------------------------------------------------------------- -void CServerGameDLL::BuildAdjacentMapList( void ) -{ - // retrieve the pointer to the save data - CSaveRestoreData *pSaveData = gpGlobals->pSaveData; - - if ( pSaveData ) - pSaveData->levelInfo.connectionCount = BuildChangeList( pSaveData->levelInfo.levelList, MAX_LEVEL_CONNECTIONS ); -} - -//----------------------------------------------------------------------------- -// Purpose: Sanity-check to verify that a path is a relative path inside the game dir -// Taken From: engine/cmd.cpp -//----------------------------------------------------------------------------- -static bool IsValidPath( const char *pszFilename ) -{ - if ( !pszFilename ) - { - return false; - } - - if ( Q_strlen( pszFilename ) <= 0 || - Q_IsAbsolutePath( pszFilename ) || // to protect absolute paths - Q_strstr( pszFilename, ".." ) ) // to protect relative paths - { - return false; - } - - return true; -} - -static void ValidateMOTDFilename( IConVar *pConVar, const char *oldValue, float flOldValue ) -{ - ConVarRef var( pConVar ); - if ( !IsValidPath( var.GetString() ) ) - { - var.SetValue( var.GetDefault() ); - } -} - -static ConVar motdfile( "motdfile", "motd.txt", 0, "The MOTD file to load.", ValidateMOTDFilename ); -void CServerGameDLL::LoadMessageOfTheDay() -{ -#ifndef _XBOX - char data[2048]; - - int length = filesystem->Size( motdfile.GetString(), "GAME" ); - - if ( length <= 0 || length >= (int)(sizeof(data)-1) ) - { - DevMsg("Invalid file size for %s\n", motdfile.GetString() ); - return; - } - - FileHandle_t hFile = filesystem->Open( motdfile.GetString(), "rb", "GAME" ); - - if ( hFile == FILESYSTEM_INVALID_HANDLE ) - return; - - filesystem->Read( data, length, hFile ); - filesystem->Close( hFile ); - - data[length] = 0; - - g_pStringTableInfoPanel->AddString( CBaseEntity::IsServer(), "motd", length+1, data ); -#endif -} - -// keeps track of which chapters the user has unlocked -ConVar sv_unlockedchapters( "sv_unlockedchapters", "1", FCVAR_ARCHIVE | FCVAR_ARCHIVE_XBOX ); - -//----------------------------------------------------------------------------- -// Purpose: Updates which chapters are unlocked -//----------------------------------------------------------------------------- -void UpdateChapterRestrictions( const char *mapname ) -{ - // look at the chapter for this map - char chapterTitle[64]; - chapterTitle[0] = 0; - for ( size_t i = 0; i < ARRAYSIZE(gTitleComments); i++ ) - { - if ( !Q_strnicmp( mapname, gTitleComments[i].pBSPName, strlen(gTitleComments[i].pBSPName) ) ) - { - // found - Q_strncpy( chapterTitle, gTitleComments[i].pTitleName, sizeof( chapterTitle ) ); - size_t j = 0; - while ( j < 64 && chapterTitle[j] ) - { - if ( chapterTitle[j] == '\n' || chapterTitle[j] == '\r' ) - chapterTitle[j] = 0; - else - j++; - } - - break; - } - } - - if ( !chapterTitle[0] ) - return; - - // make sure the specified chapter title is unlocked - Q_strlower( chapterTitle ); - - // Get our active mod directory name - char modDir[MAX_PATH]; - if ( UTIL_GetModDir( modDir, sizeof(modDir) ) == false ) - return; - - char chapterNumberPrefix[64]; - Q_snprintf(chapterNumberPrefix, sizeof(chapterNumberPrefix), "#%s_chapter", modDir); - - const char *newChapterNumber = strstr( chapterTitle, chapterNumberPrefix ); - if ( newChapterNumber ) - { - // cut off the front - newChapterNumber += strlen( chapterNumberPrefix ); - char newChapter[32]; - Q_strncpy( newChapter, newChapterNumber, sizeof(newChapter) ); - - // cut off the end - char *end = strstr( newChapter, "_title" ); - if ( end ) - { - *end = 0; - } - - int nNewChapter = atoi( newChapter ); - - // HACK: HL2 added a zany chapter "9a" which wreaks - // havoc in this stupid atoi-based chapter code. - if ( !Q_stricmp( modDir, "hl2" ) ) - { - if ( !Q_stricmp( newChapter, "9a" ) ) - { - nNewChapter = 10; - } - else if ( nNewChapter > 9 ) - { - nNewChapter++; - } - } - - // ok we have the string, see if it's newer - const char *unlockedChapter = sv_unlockedchapters.GetString(); - int nUnlockedChapter = atoi( unlockedChapter ); - - if ( nUnlockedChapter < nNewChapter ) - { - // ok we're at a higher chapter, unlock - sv_unlockedchapters.SetValue( nNewChapter ); - - // HACK: Call up through a better function than this? 7/23/07 - jdw - if ( IsX360() ) - { - engine->ServerCommand( "host_writeconfig\n" ); - } - } - - g_nCurrentChapterIndex = nNewChapter; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Update xbox live data for the user's presence -//----------------------------------------------------------------------------- -void UpdateRichPresence ( void ) -{ - // This assumes we're playing a single player game - Assert ( gpGlobals->maxClients == 1 ); - - // Shouldn't get here unless we're playing a map and we've updated sv_unlockedchapters - Assert ( g_nCurrentChapterIndex >= 0 ); - - // Get our active mod directory name - char modDir[MAX_PATH]; - if ( UTIL_GetModDir( modDir, sizeof(modDir) ) == false ) - return; - - // Get presence data based on the game we're playing - uint iGameID, iChapterIndex, iChapterID, iGamePresenceID; - iGameID = iChapterIndex = iChapterID = iGamePresenceID = 0; - if ( Q_stristr( modDir, "hl2" ) ) - { - iGameID = CONTEXT_GAME_GAME_HALF_LIFE_2; - iChapterID = CONTEXT_CHAPTER_HL2; - iChapterIndex = g_nCurrentChapterIndex - 1; - iGamePresenceID = CONTEXT_PRESENCE_HL2_INGAME; - } - else if ( Q_stristr( modDir, "episodic" ) ) - { - iGameID = CONTEXT_GAME_GAME_EPISODE_ONE; - iChapterID = CONTEXT_CHAPTER_EP1; - iChapterIndex = g_nCurrentChapterIndex - 1; - iGamePresenceID = CONTEXT_PRESENCE_EP1_INGAME; - } - else if ( Q_stristr( modDir, "ep2" ) ) - { - iGameID = CONTEXT_GAME_GAME_EPISODE_TWO; - iChapterID = CONTEXT_CHAPTER_EP2; - iChapterIndex = g_nCurrentChapterIndex - 1; - iGamePresenceID = CONTEXT_PRESENCE_EP2_INGAME; - } - else if ( Q_stristr( modDir, "portal" ) ) - { - iGameID = CONTEXT_GAME_GAME_PORTAL; - iChapterID = CONTEXT_CHAPTER_PORTAL; - iChapterIndex = g_nCurrentChapterIndex - 1; - iGamePresenceID = CONTEXT_PRESENCE_PORTAL_INGAME; - } - else - { - Warning( "UpdateRichPresence failed in GameInterface. Didn't recognize -game parameter." ); - } - - if ( iChapterID < 0 ) - iChapterID = 0; - -#if defined( _X360 ) - - // Set chapter context based on mapname - if ( !xboxsystem->UserSetContext( XBX_GetPrimaryUserId(), iChapterID, iChapterIndex, true ) ) - { - Warning( "GameInterface: UserSetContext failed.\n" ); - } - - if ( commentary.GetBool() ) - { - // Set presence to show the user is playing developer commentary - if ( !xboxsystem->UserSetContext( XBX_GetPrimaryUserId(), X_CONTEXT_PRESENCE, CONTEXT_PRESENCE_COMMENTARY, true ) ) - { - Warning( "GameInterface: UserSetContext failed.\n" ); - } - } - else - { - // Set presence to show the user is in-game - if ( !xboxsystem->UserSetContext( XBX_GetPrimaryUserId(), X_CONTEXT_PRESENCE, iGamePresenceID, true ) ) - { - Warning( "GameInterface: UserSetContext failed.\n" ); - } - } - - // Set which game the user is playing - if ( !xboxsystem->UserSetContext( XBX_GetPrimaryUserId(), CONTEXT_GAME, iGameID, true ) ) - { - Warning( "GameInterface: UserSetContext failed.\n" ); - } - - if ( !xboxsystem->UserSetContext( XBX_GetPrimaryUserId(), X_CONTEXT_GAME_TYPE, X_CONTEXT_GAME_TYPE_STANDARD, true ) ) - { - Warning( "GameInterface: UserSetContext failed.\n" ); - } - - if ( !xboxsystem->UserSetContext( XBX_GetPrimaryUserId(), X_CONTEXT_GAME_MODE, CONTEXT_GAME_MODE_SINGLEPLAYER, true ) ) - { - Warning( "GameInterface: UserSetContext failed.\n" ); - } -#endif -} - -//----------------------------------------------------------------------------- -// Precaches a vgui screen overlay material -//----------------------------------------------------------------------------- -void PrecacheMaterial( const char *pMaterialName ) -{ - Assert( pMaterialName && pMaterialName[0] ); - g_pStringTableMaterials->AddString( CBaseEntity::IsServer(), pMaterialName ); -} - - -//----------------------------------------------------------------------------- -// Converts a previously precached material into an index -//----------------------------------------------------------------------------- -int GetMaterialIndex( const char *pMaterialName ) -{ - if (pMaterialName) - { - int nIndex = g_pStringTableMaterials->FindStringIndex( pMaterialName ); - - if (nIndex != INVALID_STRING_INDEX ) - { - return nIndex; - } - else - { - DevMsg("Warning! GetMaterialIndex: couldn't find material %s\n ", pMaterialName ); - return 0; - } - } - - // This is the invalid string index - return 0; -} - -//----------------------------------------------------------------------------- -// Converts a previously precached material index into a string -//----------------------------------------------------------------------------- -const char *GetMaterialNameFromIndex( int nMaterialIndex ) -{ - return g_pStringTableMaterials->GetString( nMaterialIndex ); -} - - -//----------------------------------------------------------------------------- -// Precaches a vgui screen overlay material -//----------------------------------------------------------------------------- -void PrecacheParticleSystem( const char *pParticleSystemName ) -{ - Assert( pParticleSystemName && pParticleSystemName[0] ); - g_pStringTableParticleEffectNames->AddString( CBaseEntity::IsServer(), pParticleSystemName ); -} - - -//----------------------------------------------------------------------------- -// Converts a previously precached material into an index -//----------------------------------------------------------------------------- -int GetParticleSystemIndex( const char *pParticleSystemName ) -{ - if ( pParticleSystemName ) - { - int nIndex = g_pStringTableParticleEffectNames->FindStringIndex( pParticleSystemName ); - if (nIndex != INVALID_STRING_INDEX ) - return nIndex; - - DevWarning("Server: Missing precache for particle system \"%s\"!\n", pParticleSystemName ); - } - - // This is the invalid string index - return 0; -} - -//----------------------------------------------------------------------------- -// Converts a previously precached material index into a string -//----------------------------------------------------------------------------- -const char *GetParticleSystemNameFromIndex( int nMaterialIndex ) -{ - if ( nMaterialIndex < g_pStringTableParticleEffectNames->GetMaxStrings() ) - return g_pStringTableParticleEffectNames->GetString( nMaterialIndex ); - return "error"; -} - -//----------------------------------------------------------------------------- -// Returns true if host_thread_mode is set to non-zero (and engine is running in threaded mode) -//----------------------------------------------------------------------------- -bool IsEngineThreaded() -{ - if ( g_pcv_ThreadMode ) - { - return g_pcv_ThreadMode->GetBool(); - } - return false; -} - -class CServerGameEnts : public IServerGameEnts -{ -public: - virtual void SetDebugEdictBase(edict_t *base); - virtual void MarkEntitiesAsTouching( edict_t *e1, edict_t *e2 ); - virtual void FreeContainingEntity( edict_t * ); - virtual edict_t* BaseEntityToEdict( CBaseEntity *pEnt ); - virtual CBaseEntity* EdictToBaseEntity( edict_t *pEdict ); - virtual void CheckTransmit( CCheckTransmitInfo *pInfo, const unsigned short *pEdictIndices, int nEdicts ); -}; -EXPOSE_SINGLE_INTERFACE(CServerGameEnts, IServerGameEnts, INTERFACEVERSION_SERVERGAMEENTS); - -void CServerGameEnts::SetDebugEdictBase(edict_t *base) -{ - g_pDebugEdictBase = base; -} - -//----------------------------------------------------------------------------- -// Purpose: Marks entities as touching -// Input : *e1 - -// *e2 - -//----------------------------------------------------------------------------- -void CServerGameEnts::MarkEntitiesAsTouching( edict_t *e1, edict_t *e2 ) -{ - CBaseEntity *entity = GetContainingEntity( e1 ); - CBaseEntity *entityTouched = GetContainingEntity( e2 ); - if ( entity && entityTouched ) - { - // HACKHACK: UNDONE: Pass in the trace here??!?!? - trace_t tr; - UTIL_ClearTrace( tr ); - tr.endpos = (entity->GetAbsOrigin() + entityTouched->GetAbsOrigin()) * 0.5; - entity->PhysicsMarkEntitiesAsTouching( entityTouched, tr ); - } -} - -void CServerGameEnts::FreeContainingEntity( edict_t *e ) -{ - ::FreeContainingEntity(e); -} - -edict_t* CServerGameEnts::BaseEntityToEdict( CBaseEntity *pEnt ) -{ - if ( pEnt ) - return pEnt->edict(); - else - return NULL; -} - -CBaseEntity* CServerGameEnts::EdictToBaseEntity( edict_t *pEdict ) -{ - if ( pEdict ) - return CBaseEntity::Instance( pEdict ); - else - return NULL; -} - - -/* Yuck.. ideally this would be in CServerNetworkProperty's header, but it requires CBaseEntity and -// inlining it gives a nice speedup. -inline void CServerNetworkProperty::CheckTransmit( CCheckTransmitInfo *pInfo ) -{ - // If we have a transmit proxy, let it hook our ShouldTransmit return value. - if ( m_pTransmitProxy ) - { - nShouldTransmit = m_pTransmitProxy->ShouldTransmit( pInfo, nShouldTransmit ); - } - - if ( m_pOuter->ShouldTransmit( pInfo ) ) - { - m_pOuter->SetTransmit( pInfo ); - } -} */ - -void CServerGameEnts::CheckTransmit( CCheckTransmitInfo *pInfo, const unsigned short *pEdictIndices, int nEdicts ) -{ - // NOTE: for speed's sake, this assumes that all networkables are CBaseEntities and that the edict list - // is consecutive in memory. If either of these things change, then this routine needs to change, but - // ideally we won't be calling any virtual from this routine. This speedy routine was added as an - // optimization which would be nice to keep. - edict_t *pBaseEdict = engine->PEntityOfEntIndex( 0 ); - - // get recipient player's skybox: - CBaseEntity *pRecipientEntity = CBaseEntity::Instance( pInfo->m_pClientEnt ); - - Assert( pRecipientEntity && pRecipientEntity->IsPlayer() ); - if ( !pRecipientEntity ) - return; - - MDLCACHE_CRITICAL_SECTION(); - CBasePlayer *pRecipientPlayer = static_cast( pRecipientEntity ); - const int skyBoxArea = pRecipientPlayer->m_Local.m_skybox3d.area; - -#ifndef _X360 - const bool bIsHLTV = pRecipientPlayer->IsHLTV(); - - // m_pTransmitAlways must be set if HLTV client - Assert( bIsHLTV == ( pInfo->m_pTransmitAlways != NULL) ); -#endif - - for ( int i=0; i < nEdicts; i++ ) - { - int iEdict = pEdictIndices[i]; - - edict_t *pEdict = &pBaseEdict[iEdict]; - Assert( pEdict == engine->PEntityOfEntIndex( iEdict ) ); - int nFlags = pEdict->m_fStateFlags & (FL_EDICT_DONTSEND|FL_EDICT_ALWAYS|FL_EDICT_PVSCHECK|FL_EDICT_FULLCHECK); - - // entity needs no transmit - if ( nFlags & FL_EDICT_DONTSEND ) - continue; - - // entity is already marked for sending - if ( pInfo->m_pTransmitEdict->Get( iEdict ) ) - continue; - - if ( nFlags & FL_EDICT_ALWAYS ) - { - // FIXME: Hey! Shouldn't this be using SetTransmit so as - // to also force network down dependent entities? - while ( true ) - { - // mark entity for sending - pInfo->m_pTransmitEdict->Set( iEdict ); - -#ifndef _X360 - if ( bIsHLTV ) - { - pInfo->m_pTransmitAlways->Set( iEdict ); - } -#endif - CServerNetworkProperty *pEnt = static_cast( pEdict->GetNetworkable() ); - if ( !pEnt ) - break; - - CServerNetworkProperty *pParent = pEnt->GetNetworkParent(); - if ( !pParent ) - break; - - pEdict = pParent->edict(); - iEdict = pParent->entindex(); - } - continue; - } - - // FIXME: Would like to remove all dependencies - CBaseEntity *pEnt = ( CBaseEntity * )pEdict->GetUnknown(); - Assert( dynamic_cast< CBaseEntity* >( pEdict->GetUnknown() ) == pEnt ); - - if ( nFlags == FL_EDICT_FULLCHECK ) - { - // do a full ShouldTransmit() check, may return FL_EDICT_CHECKPVS - nFlags = pEnt->ShouldTransmit( pInfo ); - - Assert( !(nFlags & FL_EDICT_FULLCHECK) ); - - if ( nFlags & FL_EDICT_ALWAYS ) - { - pEnt->SetTransmit( pInfo, true ); - continue; - } - } - - // don't send this entity - if ( !( nFlags & FL_EDICT_PVSCHECK ) ) - continue; - - CServerNetworkProperty *netProp = static_cast( pEdict->GetNetworkable() ); - -#ifndef _X360 - if ( bIsHLTV ) - { - // for the HLTV we don't cull against PVS - if ( netProp->AreaNum() == skyBoxArea ) - { - pEnt->SetTransmit( pInfo, true ); - } - else - { - pEnt->SetTransmit( pInfo, false ); - } - continue; - } -#endif - - // Always send entities in the player's 3d skybox. - // Sidenote: call of AreaNum() ensures that PVS data is up to date for this entity - bool bSameAreaAsSky = netProp->AreaNum() == skyBoxArea; - if ( bSameAreaAsSky ) - { - pEnt->SetTransmit( pInfo, true ); - continue; - } - - bool bInPVS = netProp->IsInPVS( pInfo ); - if ( bInPVS || sv_force_transmit_ents.GetBool() ) - { - // only send if entity is in PVS - pEnt->SetTransmit( pInfo, false ); - continue; - } - - // If the entity is marked "check PVS" but it's in hierarchy, walk up the hierarchy looking for the - // for any parent which is also in the PVS. If none are found, then we don't need to worry about sending ourself - CBaseEntity *orig = pEnt; - CServerNetworkProperty *check = netProp->GetNetworkParent(); - - // BUG BUG: I think it might be better to build up a list of edict indices which "depend" on other answers and then - // resolve them in a second pass. Not sure what happens if an entity has two parents who both request PVS check? - while ( check ) - { - int checkIndex = check->entindex(); - - // Parent already being sent - if ( pInfo->m_pTransmitEdict->Get( checkIndex ) ) - { - orig->SetTransmit( pInfo, true ); - break; - } - - edict_t *checkEdict = check->edict(); - int checkFlags = checkEdict->m_fStateFlags & (FL_EDICT_DONTSEND|FL_EDICT_ALWAYS|FL_EDICT_PVSCHECK|FL_EDICT_FULLCHECK); - if ( checkFlags & FL_EDICT_DONTSEND ) - break; - - if ( checkFlags & FL_EDICT_ALWAYS ) - { - orig->SetTransmit( pInfo, true ); - break; - } - - if ( checkFlags == FL_EDICT_FULLCHECK ) - { - // do a full ShouldTransmit() check, may return FL_EDICT_CHECKPVS - CBaseEntity *pCheckEntity = check->GetBaseEntity(); - nFlags = pCheckEntity->ShouldTransmit( pInfo ); - Assert( !(nFlags & FL_EDICT_FULLCHECK) ); - if ( nFlags & FL_EDICT_ALWAYS ) - { - pCheckEntity->SetTransmit( pInfo, true ); - orig->SetTransmit( pInfo, true ); - } - break; - } - - if ( checkFlags & FL_EDICT_PVSCHECK ) - { - // Check pvs - check->RecomputePVSInformation(); - bool bMoveParentInPVS = check->IsInPVS( pInfo ); - if ( bMoveParentInPVS ) - { - orig->SetTransmit( pInfo, true ); - break; - } - } - - // Continue up chain just in case the parent itself has a parent that's in the PVS... - check = check->GetNetworkParent(); - } - } - -// Msg("A:%i, N:%i, F: %i, P: %i\n", always, dontSend, fullCheck, PVS ); -} - - -CServerGameClients g_ServerGameClients; -EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CServerGameClients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS, g_ServerGameClients ); - - -//----------------------------------------------------------------------------- -// Purpose: called when a player tries to connect to the server -// Input : *pEdict - the new player -// char *pszName - the players name -// char *pszAddress - the IP address of the player -// reject - output - fill in with the reason why -// maxrejectlen -- sizeof output buffer -// the player was not allowed to connect. -// Output : Returns TRUE if player is allowed to join, FALSE if connection is denied. -//----------------------------------------------------------------------------- -bool CServerGameClients::ClientConnect( edict_t *pEdict, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen ) -{ - return g_pGameRules->ClientConnected( pEdict, pszName, pszAddress, reject, maxrejectlen ); -} - -//----------------------------------------------------------------------------- -// Purpose: Called when a player is fully active (i.e. ready to receive messages) -// Input : *pEntity - the player -//----------------------------------------------------------------------------- -void CServerGameClients::ClientActive( edict_t *pEdict, bool bLoadGame ) -{ - MDLCACHE_CRITICAL_SECTION(); - - ::ClientActive( pEdict, bLoadGame ); - - // If we just loaded from a save file, call OnRestore on valid entities - EndRestoreEntities(); - - if ( gpGlobals->eLoadType != MapLoad_LoadGame ) - { - // notify all entities that the player is now in the game - for ( CBaseEntity *pEntity = gEntList.FirstEnt(); pEntity != NULL; pEntity = gEntList.NextEnt(pEntity) ) - { - pEntity->PostClientActive(); - } - } - - // Tell the sound controller to check looping sounds - CBasePlayer *pPlayer = ( CBasePlayer * )CBaseEntity::Instance( pEdict ); - CSoundEnvelopeController::GetController().CheckLoopingSoundsForPlayer( pPlayer ); - SceneManager_ClientActive( pPlayer ); -} - -//----------------------------------------------------------------------------- -// Purpose: called when a player disconnects from a server -// Input : *pEdict - the player -//----------------------------------------------------------------------------- -void CServerGameClients::ClientDisconnect( edict_t *pEdict ) -{ - extern bool g_fGameOver; - - CBasePlayer *player = ( CBasePlayer * )CBaseEntity::Instance( pEdict ); - if ( player ) - { - if ( !g_fGameOver ) - { - player->SetMaxSpeed( 0.0f ); - - CSound *pSound; - pSound = CSoundEnt::SoundPointerForIndex( CSoundEnt::ClientSoundIndex( pEdict ) ); - { - // since this client isn't around to think anymore, reset their sound. - if ( pSound ) - { - pSound->Reset(); - } - } - - // since the edict doesn't get deleted, fix it so it doesn't interfere. - player->RemoveFlag( FL_AIMTARGET ); // don't attract autoaim - player->AddFlag( FL_DONTTOUCH ); // stop it touching anything - player->AddFlag( FL_NOTARGET ); // stop NPCs noticing it - player->AddSolidFlags( FSOLID_NOT_SOLID ); // nonsolid - - if ( g_pGameRules ) - { - g_pGameRules->ClientDisconnected( pEdict ); - gamestats->Event_PlayerDisconnected( player ); - } - } - - // Make sure all Untouch()'s are called for this client leaving - CBaseEntity::PhysicsRemoveTouchedList( player ); - CBaseEntity::PhysicsRemoveGroundList( player ); - -#if !defined( NO_ENTITY_PREDICTION ) - // Make sure anything we "own" is simulated by the server from now on - player->ClearPlayerSimulationList(); -#endif - } -} - -void CServerGameClients::ClientPutInServer( edict_t *pEntity, const char *playername ) -{ - if ( g_pClientPutInServerOverride ) - g_pClientPutInServerOverride( pEntity, playername ); - else - ::ClientPutInServer( pEntity, playername ); -} - -void CServerGameClients::ClientCommand( edict_t *pEntity, const CCommand &args ) -{ - CBasePlayer *pPlayer = ToBasePlayer( GetContainingEntity( pEntity ) ); - ::ClientCommand( pPlayer, args ); -} - -//----------------------------------------------------------------------------- -// Purpose: called after the player changes userinfo - gives dll a chance to modify -// it before it gets sent into the rest of the engine-> -// Input : *pEdict - the player -// *infobuffer - their infobuffer -//----------------------------------------------------------------------------- -void CServerGameClients::ClientSettingsChanged( edict_t *pEdict ) -{ - // Is the client spawned yet? - if ( !pEdict->GetUnknown() ) - return; - - CBasePlayer *player = ( CBasePlayer * )CBaseEntity::Instance( pEdict ); - - if ( !player ) - return; - -#define QUICKGETCVARVALUE(v) (engine->GetClientConVarValue( player->entindex(), v )) - - // get network setting for prediction & lag compensation - - // Unfortunately, we have to duplicate the code in cdll_bounded_cvars.cpp here because the client - // doesn't send the virtualized value up (because it has no way to know when the virtualized value - // changes). Possible todo: put the responsibility on the bounded cvar to notify the engine when - // its virtualized value has changed. - - player->m_nUpdateRate = Q_atoi( QUICKGETCVARVALUE("cl_updaterate") ); - static const ConVar *pMinUpdateRate = g_pCVar->FindVar( "sv_minupdaterate" ); - static const ConVar *pMaxUpdateRate = g_pCVar->FindVar( "sv_maxupdaterate" ); - if ( pMinUpdateRate && pMaxUpdateRate ) - player->m_nUpdateRate = (int)clamp( player->m_nUpdateRate, pMinUpdateRate->GetFloat(), pMaxUpdateRate->GetFloat() ); - - bool useInterpolation = Q_atoi( QUICKGETCVARVALUE("cl_interpolate") ) != 0; - if ( useInterpolation ) - { - float flLerpRatio = Q_atof( QUICKGETCVARVALUE("cl_interp_ratio") ); - if ( flLerpRatio == 0 ) - flLerpRatio = 1.0f; - float flLerpAmount = Q_atof( QUICKGETCVARVALUE("cl_interp") ); - - static const ConVar *pMin = g_pCVar->FindVar( "sv_client_min_interp_ratio" ); - static const ConVar *pMax = g_pCVar->FindVar( "sv_client_max_interp_ratio" ); - if ( pMin && pMax && pMin->GetFloat() != -1 ) - { - flLerpRatio = clamp( flLerpRatio, pMin->GetFloat(), pMax->GetFloat() ); - } - else - { - if ( flLerpRatio == 0 ) - flLerpRatio = 1.0f; - } - // #define FIXME_INTERP_RATIO - player->m_fLerpTime = MAX( flLerpAmount, flLerpRatio / player->m_nUpdateRate ); - } - else - { - player->m_fLerpTime = 0.0f; - } - -#if !defined( NO_ENTITY_PREDICTION ) - bool usePrediction = Q_atoi( QUICKGETCVARVALUE("cl_predict")) != 0; - - if ( usePrediction ) - { - player->m_bPredictWeapons = Q_atoi( QUICKGETCVARVALUE("cl_predictweapons")) != 0; - player->m_bLagCompensation = Q_atoi( QUICKGETCVARVALUE("cl_lagcompensation")) != 0; - } - else -#endif - { - player->m_bPredictWeapons = false; - player->m_bLagCompensation = false; - } - - -#undef QUICKGETCVARVALUE - - g_pGameRules->ClientSettingsChanged( player ); -} - - -#ifdef PORTAL -//----------------------------------------------------------------------------- -// Purpose: Runs CFuncAreaPortalBase::UpdateVisibility on each portal -// Input : pAreaPortal - The Area portal to test for visibility from portals -// Output : int - 1 if any portal needs this area portal open, 0 otherwise. -//----------------------------------------------------------------------------- -int TestAreaPortalVisibilityThroughPortals ( CFuncAreaPortalBase* pAreaPortal, edict_t *pViewEntity, unsigned char *pvs, int pvssize ) -{ - int iPortalCount = CProp_Portal_Shared::AllPortals.Count(); - if( iPortalCount == 0 ) - return 0; - - CProp_Portal **pPortals = CProp_Portal_Shared::AllPortals.Base(); - - for ( int i = 0; i != iPortalCount; ++i ) - { - CProp_Portal* pLocalPortal = pPortals[ i ]; - if ( pLocalPortal && pLocalPortal->m_bActivated ) - { - CProp_Portal* pRemotePortal = pLocalPortal->m_hLinkedPortal.Get(); - - // Make sure this portal's linked portal is in the PVS before we add what it can see - if ( pRemotePortal && pRemotePortal->m_bActivated && pRemotePortal->NetworkProp() && - pRemotePortal->NetworkProp()->IsInPVS( pViewEntity, pvs, pvssize ) ) - { - bool bIsOpenOnClient = true; - float fovDistanceAdjustFactor = 1.0f; - Vector portalOrg = pLocalPortal->GetAbsOrigin(); - int iPortalNeedsThisPortalOpen = pAreaPortal->UpdateVisibility( portalOrg, fovDistanceAdjustFactor, bIsOpenOnClient ); - - // Stop checking on success, this portal needs to be open - if ( iPortalNeedsThisPortalOpen ) - { - return iPortalNeedsThisPortalOpen; - } - } - } - } - - return 0; -} -#endif - -//----------------------------------------------------------------------------- -// Purpose: A client can have a separate "view entity" indicating that his/her view should depend on the origin of that -// view entity. If that's the case, then pViewEntity will be non-NULL and will be used. Otherwise, the current -// entity's origin is used. Either is offset by the m_vecViewOffset to get the eye position. -// From the eye position, we set up the PAS and PVS to use for filtering network messages to the client. At this point, we could -// override the actual PAS or PVS values, or use a different origin. -// NOTE: Do not cache the values of pas and pvs, as they depend on reusable memory in the engine, they are only good for this one frame -// Input : *pViewEntity - -// *pClient - -// **pvs - -// **pas - -//----------------------------------------------------------------------------- -void CServerGameClients::ClientSetupVisibility( edict_t *pViewEntity, edict_t *pClient, unsigned char *pvs, int pvssize ) -{ - Vector org; - - // Reset the PVS!!! - engine->ResetPVS( pvs, pvssize ); - - g_pToolFrameworkServer->PreSetupVisibility(); - - // Find the client's PVS - CBaseEntity *pVE = NULL; - if ( pViewEntity ) - { - pVE = GetContainingEntity( pViewEntity ); - // If we have a viewentity, it overrides the player's origin - if ( pVE ) - { - org = pVE->EyePosition(); - engine->AddOriginToPVS( org ); - } - } - - float fovDistanceAdjustFactor = 1; - - CBasePlayer *pPlayer = ( CBasePlayer * )GetContainingEntity( pClient ); - if ( pPlayer ) - { - org = pPlayer->EyePosition(); - pPlayer->SetupVisibility( pVE, pvs, pvssize ); - UTIL_SetClientVisibilityPVS( pClient, pvs, pvssize ); - fovDistanceAdjustFactor = pPlayer->GetFOVDistanceAdjustFactorForNetworking(); - } - - unsigned char portalBits[MAX_AREA_PORTAL_STATE_BYTES]; - memset( portalBits, 0, sizeof( portalBits ) ); - - int portalNums[512]; - int isOpen[512]; - int iOutPortal = 0; - - for( unsigned short i = g_AreaPortals.Head(); i != g_AreaPortals.InvalidIndex(); i = g_AreaPortals.Next(i) ) - { - CFuncAreaPortalBase *pCur = g_AreaPortals[i]; - - bool bIsOpenOnClient = true; - - // Update our array of which portals are open and flush it if necessary. - portalNums[iOutPortal] = pCur->m_portalNumber; - isOpen[iOutPortal] = pCur->UpdateVisibility( org, fovDistanceAdjustFactor, bIsOpenOnClient ); - -#ifdef PORTAL - // If the client doesn't need this open, test if portals might need this area portal open - if ( isOpen[iOutPortal] == 0 ) - { - isOpen[iOutPortal] = TestAreaPortalVisibilityThroughPortals( pCur, pViewEntity, pvs, pvssize ); - } -#endif - - ++iOutPortal; - if ( iOutPortal >= (int)ARRAYSIZE( portalNums ) ) - { - engine->SetAreaPortalStates( portalNums, isOpen, iOutPortal ); - iOutPortal = 0; - } - - // Version 0 portals (ie: shipping Half-Life 2 era) are always treated as open - // for purposes of the m_chAreaPortalBits array on the client. - if ( pCur->m_iPortalVersion == 0 ) - bIsOpenOnClient = true; - - if ( bIsOpenOnClient ) - { - if ( pCur->m_portalNumber < 0 ) - continue; - else if ( pCur->m_portalNumber >= (int)sizeof( portalBits ) * 8 ) - Error( "ClientSetupVisibility: portal number (%d) too large", pCur->m_portalNumber ); - else - portalBits[pCur->m_portalNumber >> 3] |= (1 << (pCur->m_portalNumber & 7)); - } - } - - // Flush the remaining areaportal states. - engine->SetAreaPortalStates( portalNums, isOpen, iOutPortal ); - - // Update the area bits that get sent to the client. - pPlayer->m_Local.UpdateAreaBits( pPlayer, portalBits ); - -#ifdef PORTAL - // *After* the player's view has updated its area bits, add on any other areas seen by portals - CPortal_Player* pPortalPlayer = dynamic_cast( pPlayer ); - if ( pPortalPlayer ) - { - pPortalPlayer->UpdatePortalViewAreaBits( pvs, pvssize ); - } -#endif //PORTAL -} - - - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *player - -// *buf - -// numcmds - -// totalcmds - -// dropped_packets - -// ignore - -// paused - -// Output : float -//----------------------------------------------------------------------------- -#define CMD_MAXBACKUP 64 - -float CServerGameClients::ProcessUsercmds( edict_t *player, bf_read *buf, int numcmds, int totalcmds, - int dropped_packets, bool ignore, bool paused ) -{ - int i; - CUserCmd *from, *to; - - // We track last three command in case we drop some - // packets but get them back. - CUserCmd cmds[ CMD_MAXBACKUP ]; - - CUserCmd cmdNull; // For delta compression - - Assert( numcmds >= 0 ); - Assert( ( totalcmds - numcmds ) >= 0 ); - - CBasePlayer *pPlayer = NULL; - CBaseEntity *pEnt = CBaseEntity::Instance(player); - if ( pEnt && pEnt->IsPlayer() ) - { - pPlayer = static_cast< CBasePlayer * >( pEnt ); - } - // Too many commands? - if ( totalcmds < 0 || totalcmds >= ( CMD_MAXBACKUP - 1 ) ) - { - const char *name = "unknown"; - if ( pPlayer ) - { - name = pPlayer->GetPlayerName(); - } - - Msg("CBasePlayer::ProcessUsercmds: too many cmds %i sent for player %s\n", totalcmds, name ); - // FIXME: Need a way to drop the client from here - //SV_DropClient ( host_client, false, "CMD_MAXBACKUP hit" ); - buf->SetOverflowFlag(); - return 0.0f; - } - - // Initialize for reading delta compressed usercmds - cmdNull.Reset(); - from = &cmdNull; - for ( i = totalcmds - 1; i >= 0; i-- ) - { - to = &cmds[ i ]; - ReadUsercmd( buf, to, from ); - from = to; - } - - // Client not fully connected or server has gone inactive or is paused, just ignore - if ( ignore || !pPlayer ) - { - return 0.0f; - } - - MDLCACHE_CRITICAL_SECTION(); - pPlayer->ProcessUsercmds( cmds, numcmds, totalcmds, dropped_packets, paused ); - - return TICK_INTERVAL; -} - - -void CServerGameClients::PostClientMessagesSent( void ) -{ - VPROF("CServerGameClients::PostClient"); - gEntList.PostClientMessagesSent(); -} - -// Sets the client index for the client who typed the command into his/her console -void CServerGameClients::SetCommandClient( int index ) -{ - g_nCommandClientIndex = index; -} - -int CServerGameClients::GetReplayDelay( edict_t *pEdict, int &entity ) -{ - CBasePlayer *pPlayer = ( CBasePlayer * )CBaseEntity::Instance( pEdict ); - - if ( !pPlayer ) - return 0; - - entity = pPlayer->GetReplayEntity(); - - return pPlayer->GetDelayTicks(); -} - - -//----------------------------------------------------------------------------- -// The client's userinfo data lump has changed -//----------------------------------------------------------------------------- -void CServerGameClients::ClientEarPosition( edict_t *pEdict, Vector *pEarOrigin ) -{ - CBasePlayer *pPlayer = ( CBasePlayer * )CBaseEntity::Instance( pEdict ); - if (pPlayer) - { - *pEarOrigin = pPlayer->EarPosition(); - } - else - { - // Shouldn't happen - Assert(0); - *pEarOrigin = vec3_origin; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *player - -// Output : CPlayerState -//----------------------------------------------------------------------------- -CPlayerState *CServerGameClients::GetPlayerState( edict_t *player ) -{ - // Is the client spawned yet? - if ( !player || !player->GetUnknown() ) - return NULL; - - CBasePlayer *pBasePlayer = ( CBasePlayer * )CBaseEntity::Instance( player ); - if ( !pBasePlayer ) - return NULL; - - return &pBasePlayer->pl; -} - -//----------------------------------------------------------------------------- -// Purpose: Anything this game .dll wants to add to the bug reporter text (e.g., the entity/model under the picker crosshair) -// can be added here -// Input : *buf - -// buflen - -//----------------------------------------------------------------------------- -void CServerGameClients::GetBugReportInfo( char *buf, int buflen ) -{ - recentNPCSpeech_t speech[ SPEECH_LIST_MAX_SOUNDS ]; - int num; - int i; - - buf[ 0 ] = 0; - - if ( gpGlobals->maxClients == 1 ) - { - CBaseEntity *ent = FindPickerEntity( UTIL_PlayerByIndex(1) ); - if ( ent ) - { - Q_snprintf( buf, buflen, "Picker %i/%s - ent %s model %s\n", - ent->entindex(), - ent->GetClassname(), - STRING( ent->GetEntityName() ), - STRING(ent->GetModelName()) ); - } - - // get any sounds that were spoken by NPCs recently - num = GetRecentNPCSpeech( speech ); - if ( num > 0 ) - { - Q_snprintf( buf, buflen, "%sRecent NPC speech:\n", buf ); - for( i = 0; i < num; i++ ) - { - Q_snprintf( buf, buflen, "%s time: %6.3f sound name: %s scene: %s\n", buf, speech[ i ].time, speech[ i ].name, speech[ i ].sceneName ); - } - Q_snprintf( buf, buflen, "%sCurrent time: %6.3f\n", buf, gpGlobals->curtime ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: A user has had their network id setup and validated -//----------------------------------------------------------------------------- -void CServerGameClients::NetworkIDValidated( const char *pszUserName, const char *pszNetworkID ) -{ -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -static bf_write *g_pMsgBuffer = NULL; - -void EntityMessageBegin( CBaseEntity * entity, bool reliable /*= false*/ ) -{ - Assert( !g_pMsgBuffer ); - - Assert ( entity ); - - g_pMsgBuffer = engine->EntityMessageBegin( entity->entindex(), entity->GetServerClass(), reliable ); -} - -void UserMessageBegin( IRecipientFilter& filter, const char *messagename ) -{ - Assert( !g_pMsgBuffer ); - - Assert( messagename ); - - int msg_type = usermessages->LookupUserMessage( messagename ); - - if ( msg_type == -1 ) - { - Error( "UserMessageBegin: Unregistered message '%s'\n", messagename ); - } - - g_pMsgBuffer = engine->UserMessageBegin( &filter, msg_type ); -} - -void MessageEnd( void ) -{ - Assert( g_pMsgBuffer ); - - engine->MessageEnd(); - - g_pMsgBuffer = NULL; -} - -void MessageWriteByte( int iValue) -{ - if (!g_pMsgBuffer) - Error( "WRITE_BYTE called with no active message\n" ); - - g_pMsgBuffer->WriteByte( iValue ); -} - -void MessageWriteChar( int iValue) -{ - if (!g_pMsgBuffer) - Error( "WRITE_CHAR called with no active message\n" ); - - g_pMsgBuffer->WriteChar( iValue ); -} - -void MessageWriteShort( int iValue) -{ - if (!g_pMsgBuffer) - Error( "WRITE_SHORT called with no active message\n" ); - - g_pMsgBuffer->WriteShort( iValue ); -} - -void MessageWriteWord( int iValue ) -{ - if (!g_pMsgBuffer) - Error( "WRITE_WORD called with no active message\n" ); - - g_pMsgBuffer->WriteWord( iValue ); -} - -void MessageWriteLong( int iValue) -{ - if (!g_pMsgBuffer) - Error( "WriteLong called with no active message\n" ); - - g_pMsgBuffer->WriteLong( iValue ); -} - -void MessageWriteFloat( float flValue) -{ - if (!g_pMsgBuffer) - Error( "WriteFloat called with no active message\n" ); - - g_pMsgBuffer->WriteFloat( flValue ); -} - -void MessageWriteAngle( float flValue) -{ - if (!g_pMsgBuffer) - Error( "WriteAngle called with no active message\n" ); - - g_pMsgBuffer->WriteBitAngle( flValue, 8 ); -} - -void MessageWriteCoord( float flValue) -{ - if (!g_pMsgBuffer) - Error( "WriteCoord called with no active message\n" ); - - g_pMsgBuffer->WriteBitCoord( flValue ); -} - -void MessageWriteVec3Coord( const Vector& rgflValue) -{ - if (!g_pMsgBuffer) - Error( "WriteVec3Coord called with no active message\n" ); - - g_pMsgBuffer->WriteBitVec3Coord( rgflValue ); -} - -void MessageWriteVec3Normal( const Vector& rgflValue) -{ - if (!g_pMsgBuffer) - Error( "WriteVec3Normal called with no active message\n" ); - - g_pMsgBuffer->WriteBitVec3Normal( rgflValue ); -} - -void MessageWriteAngles( const QAngle& rgflValue) -{ - if (!g_pMsgBuffer) - Error( "WriteVec3Normal called with no active message\n" ); - - g_pMsgBuffer->WriteBitAngles( rgflValue ); -} - -void MessageWriteString( const char *sz ) -{ - if (!g_pMsgBuffer) - Error( "WriteString called with no active message\n" ); - - g_pMsgBuffer->WriteString( sz ); -} - -void MessageWriteEntity( int iValue) -{ - if (!g_pMsgBuffer) - Error( "WriteEntity called with no active message\n" ); - - g_pMsgBuffer->WriteShort( iValue ); -} - -void MessageWriteEHandle( CBaseEntity *pEntity ) -{ - if (!g_pMsgBuffer) - Error( "WriteEHandle called with no active message\n" ); - - long iEncodedEHandle; - - if( pEntity ) - { - EHANDLE hEnt = pEntity; - - int iSerialNum = hEnt.GetSerialNumber() & (1 << NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS) - 1; - iEncodedEHandle = hEnt.GetEntryIndex() | (iSerialNum << MAX_EDICT_BITS); - } - else - { - iEncodedEHandle = INVALID_NETWORKED_EHANDLE_VALUE; - } - - g_pMsgBuffer->WriteLong( iEncodedEHandle ); -} - -// bitwise -void MessageWriteBool( bool bValue ) -{ - if (!g_pMsgBuffer) - Error( "WriteBool called with no active message\n" ); - - g_pMsgBuffer->WriteOneBit( bValue ? 1 : 0 ); -} - -void MessageWriteUBitLong( unsigned int data, int numbits ) -{ - if (!g_pMsgBuffer) - Error( "WriteUBitLong called with no active message\n" ); - - g_pMsgBuffer->WriteUBitLong( data, numbits ); -} - -void MessageWriteSBitLong( int data, int numbits ) -{ - if (!g_pMsgBuffer) - Error( "WriteSBitLong called with no active message\n" ); - - g_pMsgBuffer->WriteSBitLong( data, numbits ); -} - -void MessageWriteBits( const void *pIn, int nBits ) -{ - if (!g_pMsgBuffer) - Error( "WriteBits called with no active message\n" ); - - g_pMsgBuffer->WriteBits( pIn, nBits ); -} - -class CServerDLLSharedAppSystems : public IServerDLLSharedAppSystems -{ -public: - CServerDLLSharedAppSystems() - { - AddAppSystem( "soundemittersystem", SOUNDEMITTERSYSTEM_INTERFACE_VERSION ); - AddAppSystem( "scenefilecache", SCENE_FILE_CACHE_INTERFACE_VERSION ); - } - - virtual int Count() - { - return m_Systems.Count(); - } - virtual char const *GetDllName( int idx ) - { - return m_Systems[ idx ].m_pModuleName; - } - virtual char const *GetInterfaceName( int idx ) - { - return m_Systems[ idx ].m_pInterfaceName; - } -private: - void AddAppSystem( char const *moduleName, char const *interfaceName ) - { - AppSystemInfo_t sys; - sys.m_pModuleName = moduleName; - sys.m_pInterfaceName = interfaceName; - m_Systems.AddToTail( sys ); - } - - CUtlVector< AppSystemInfo_t > m_Systems; -}; - -EXPOSE_SINGLE_INTERFACE( CServerDLLSharedAppSystems, IServerDLLSharedAppSystems, SERVER_DLL_SHARED_APPSYSTEMS ); - - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -void CServerGameTags::GetTaggedConVarList( KeyValues *pCvarTagList ) -{ - if ( pCvarTagList ) - { - g_pGameRules->GetTaggedConVarList( pCvarTagList ); - } -} diff --git a/game/server/gameinterface.h b/game/server/gameinterface.h deleted file mode 100644 index 265b70064..000000000 --- a/game/server/gameinterface.h +++ /dev/null @@ -1,183 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Expose things from GameInterface.cpp. Mostly the engine interfaces. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef GAMEINTERFACE_H -#define GAMEINTERFACE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "mapentities.h" - -extern INetworkStringTable *g_pStringTableInfoPanel; - -// Player / Client related functions -// Most of this is implemented in gameinterface.cpp, but some of it is per-mod in files like cs_gameinterface.cpp, etc. -class CServerGameClients : public IServerGameClients -{ -public: - virtual bool ClientConnect( edict_t *pEntity, char const* pszName, char const* pszAddress, char *reject, int maxrejectlen ); - virtual void ClientActive( edict_t *pEntity, bool bLoadGame ); - virtual void ClientDisconnect( edict_t *pEntity ); - virtual void ClientPutInServer( edict_t *pEntity, const char *playername ); - virtual void ClientCommand( edict_t *pEntity, const CCommand &args ); - virtual void ClientSettingsChanged( edict_t *pEntity ); - virtual void ClientSetupVisibility( edict_t *pViewEntity, edict_t *pClient, unsigned char *pvs, int pvssize ); - virtual float ProcessUsercmds( edict_t *player, bf_read *buf, int numcmds, int totalcmds, - int dropped_packets, bool ignore, bool paused ); - // Player is running a command - virtual void PostClientMessagesSent( void ); - virtual void SetCommandClient( int index ); - virtual CPlayerState *GetPlayerState( edict_t *player ); - virtual void ClientEarPosition( edict_t *pEntity, Vector *pEarOrigin ); - - virtual void GetPlayerLimits( int& minplayers, int& maxplayers, int &defaultMaxPlayers ) const; - - // returns number of delay ticks if player is in Replay mode (0 = no delay) - virtual int GetReplayDelay( edict_t *player, int& entity ); - // Anything this game .dll wants to add to the bug reporter text (e.g., the entity/model under the picker crosshair) - // can be added here - virtual void GetBugReportInfo( char *buf, int buflen ); - virtual void NetworkIDValidated( const char *pszUserName, const char *pszNetworkID ); -}; - - -class CServerGameDLL : public IServerGameDLL -{ -public: - virtual bool DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory, - CreateInterfaceFn fileSystemFactory, CGlobalVars *pGlobals); - virtual void DLLShutdown( void ); - // Get the simulation interval (must be compiled with identical values into both client and game .dll for MOD!!!) - virtual float GetTickInterval( void ) const; - virtual bool GameInit( void ); - virtual void GameShutdown( void ); - virtual bool LevelInit( const char *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background ); - virtual void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax ); - virtual void LevelShutdown( void ); - virtual void GameFrame( bool simulating ); // could be called multiple times before sending data to clients - virtual void PreClientUpdate( bool simulating ); // called after all GameFrame() calls, before sending data to clients - - virtual ServerClass* GetAllServerClasses( void ); - virtual const char *GetGameDescription( void ); - virtual void CreateNetworkStringTables( void ); - - // Save/restore system hooks - virtual CSaveRestoreData *SaveInit( int size ); - virtual void SaveWriteFields( CSaveRestoreData *, char const* , void *, datamap_t *, typedescription_t *, int ); - virtual void SaveReadFields( CSaveRestoreData *, char const* , void *, datamap_t *, typedescription_t *, int ); - virtual void SaveGlobalState( CSaveRestoreData * ); - virtual void RestoreGlobalState( CSaveRestoreData * ); - virtual int CreateEntityTransitionList( CSaveRestoreData *, int ); - virtual void BuildAdjacentMapList( void ); - - virtual void PreSave( CSaveRestoreData * ); - virtual void Save( CSaveRestoreData * ); - virtual void GetSaveComment( char *comment, int maxlength, float flMinutes, float flSeconds, bool bNoTime = false ); -#ifdef _XBOX - virtual void GetTitleName( const char *pMapName, char* pTitleBuff, int titleBuffSize ); -#endif - virtual void WriteSaveHeaders( CSaveRestoreData * ); - - virtual void ReadRestoreHeaders( CSaveRestoreData * ); - virtual void Restore( CSaveRestoreData *, bool ); - virtual bool IsRestoring(); - - // Retrieve info needed for parsing the specified user message - virtual bool GetUserMessageInfo( int msg_type, char *name, int maxnamelength, int& size ); - - virtual CStandardSendProxies* GetStandardSendProxies(); - - virtual void PostInit(); - virtual void Think( bool finalTick ); - - virtual void OnQueryCvarValueFinished( QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue ); - - virtual void PreSaveGameLoaded( char const *pSaveName, bool bInGame ); - - // Returns true if the game DLL wants the server not to be made public. - // Used by commentary system to hide multiplayer commentary servers from the master. - virtual bool ShouldHideServer( void ); - - virtual void InvalidateMdlCache(); - - float m_fAutoSaveDangerousTime; - float m_fAutoSaveDangerousMinHealthToCommit; - -private: - - // This can just be a wrapper on MapEntity_ParseAllEntities, but CS does some tricks in here - // with the entity list. - void LevelInit_ParseAllEntities( const char *pMapEntities ); - void LoadMessageOfTheDay(); -}; - - -// Normally, when the engine calls ClientPutInServer, it calls a global function in the game DLL -// by the same name. Use this to override the function that it calls. This is used for bots. -typedef CBasePlayer* (*ClientPutInServerOverrideFn)( edict_t *pEdict, const char *playername ); - -void ClientPutInServerOverride( ClientPutInServerOverrideFn fn ); - -// -------------------------------------------------------------------------------------------- // -// Entity list management stuff. -// -------------------------------------------------------------------------------------------- // -// These are created for map entities in order as the map entities are spawned. -class CMapEntityRef -{ -public: - int m_iEdict; // Which edict slot this entity got. -1 if CreateEntityByName failed. - int m_iSerialNumber; // The edict serial number. TODO used anywhere ? -}; - -extern CUtlLinkedList g_MapEntityRefs; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CMapLoadEntityFilter : public IMapEntityFilter -{ -public: - virtual bool ShouldCreateEntity( const char *pClassname ) - { - // During map load, create all the entities. - return true; - } - - virtual CBaseEntity* CreateNextEntity( const char *pClassname ) - { - CBaseEntity *pRet = CreateEntityByName( pClassname ); - - CMapEntityRef ref; - ref.m_iEdict = -1; - ref.m_iSerialNumber = -1; - - if ( pRet ) - { - ref.m_iEdict = pRet->entindex(); - if ( pRet->edict() ) - ref.m_iSerialNumber = pRet->edict()->m_NetworkSerialNumber; - } - - g_MapEntityRefs.AddToTail( ref ); - return pRet; - } -}; - -bool IsEngineThreaded(); - -class CServerGameTags : public IServerGameTags -{ -public: - virtual void GetTaggedConVarList( KeyValues *pCvarTagList ); - -}; -EXPOSE_SINGLE_INTERFACE( CServerGameTags, IServerGameTags, INTERFACEVERSION_SERVERGAMETAGS ); - -#endif // GAMEINTERFACE_H - diff --git a/game/server/gametrace_dll.cpp b/game/server/gametrace_dll.cpp deleted file mode 100644 index 48f761e2f..000000000 --- a/game/server/gametrace_dll.cpp +++ /dev/null @@ -1,33 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "gametrace.h" -#include "world.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -bool CGameTrace::DidHitWorld() const -{ - return m_pEnt == GetWorldEntity(); -} - - -bool CGameTrace::DidHitNonWorldEntity() const -{ - return m_pEnt != NULL && !DidHitWorld(); -} - - -int CGameTrace::GetEntityIndex() const -{ - if ( m_pEnt ) - return m_pEnt->entindex(); - else - return -1; -} - diff --git a/game/server/gameweaponmanager.cpp b/game/server/gameweaponmanager.cpp deleted file mode 100644 index db74c5ebb..000000000 --- a/game/server/gameweaponmanager.cpp +++ /dev/null @@ -1,290 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" - -#include "gameweaponmanager.h" -#include "saverestore_utlvector.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//========================================================= -//========================================================= -class CGameWeaponManager; -static CUtlVector g_Managers; - - -//========================================================= -//========================================================= -class CGameWeaponManager : public CBaseEntity -{ - DECLARE_CLASS( CGameWeaponManager, CBaseEntity ); - DECLARE_DATADESC(); - -public: - void Spawn(); - CGameWeaponManager() - { - m_flAmmoMod = 1.0f; - m_bExpectingWeapon = false; - g_Managers.AddToTail( this ); - } - - ~CGameWeaponManager() - { - g_Managers.FindAndRemove( this ); - } - - void Think(); - void InputSetMaxPieces( inputdata_t &inputdata ); - void InputSetAmmoModifier( inputdata_t &inputdata ); - - string_t m_iszWeaponName; - int m_iMaxPieces; - float m_flAmmoMod; - bool m_bExpectingWeapon; - - CUtlVector m_ManagedNonWeapons; - -}; - -BEGIN_DATADESC( CGameWeaponManager ) - -//fields - DEFINE_KEYFIELD( m_iszWeaponName, FIELD_STRING, "weaponname" ), - DEFINE_KEYFIELD( m_iMaxPieces, FIELD_INTEGER, "maxpieces" ), - DEFINE_KEYFIELD( m_flAmmoMod, FIELD_FLOAT, "ammomod" ), - DEFINE_FIELD( m_bExpectingWeapon, FIELD_BOOLEAN ), -// funcs - DEFINE_FUNCTION( Think ), -// inputs - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetMaxPieces", InputSetMaxPieces ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetAmmoModifier", InputSetAmmoModifier ), - - DEFINE_UTLVECTOR( m_ManagedNonWeapons, FIELD_EHANDLE ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( game_weapon_manager, CGameWeaponManager ); - -void CreateWeaponManager( const char *pWeaponName, int iMaxPieces ) -{ - CGameWeaponManager *pManager = (CGameWeaponManager *)CreateEntityByName( "game_weapon_manager"); - - if( pManager ) - { - pManager->m_iszWeaponName = MAKE_STRING( pWeaponName ); - pManager->m_iMaxPieces = iMaxPieces; - DispatchSpawn( pManager ); - } -} - -void WeaponManager_AmmoMod( CBaseCombatWeapon *pWeapon ) -{ - for ( int i = 0; i < g_Managers.Count(); i++ ) - { - if ( g_Managers[i]->m_iszWeaponName == pWeapon->m_iClassname ) - { - int iNewClip = (int)(pWeapon->m_iClip1 * g_Managers[i]->m_flAmmoMod); - int iNewRandomClip = iNewClip + RandomInt( -2, 2 ); - - if ( iNewRandomClip > pWeapon->GetMaxClip1() ) - { - iNewRandomClip = pWeapon->GetMaxClip1(); - } - else if ( iNewRandomClip <= 0 ) - { - //Drop at least one bullet. - iNewRandomClip = 1; - } - - pWeapon->m_iClip1 = iNewRandomClip; - } - } -} - -void WeaponManager_AddManaged( CBaseEntity *pWeapon ) -{ - for ( int i = 0; i < g_Managers.Count(); i++ ) - { - if ( g_Managers[i]->m_iszWeaponName == pWeapon->m_iClassname ) - { - Assert( g_Managers[i]->m_ManagedNonWeapons.Find( pWeapon ) == g_Managers[i]->m_ManagedNonWeapons.InvalidIndex() ); - g_Managers[i]->m_ManagedNonWeapons.AddToTail( pWeapon ); - break; - } - } -} - -void WeaponManager_RemoveManaged( CBaseEntity *pWeapon ) -{ - for ( int i = 0; i < g_Managers.Count(); i++ ) - { - if ( g_Managers[i]->m_iszWeaponName == pWeapon->m_iClassname ) - { - int j = g_Managers[i]->m_ManagedNonWeapons.Find( pWeapon ); - if ( j != g_Managers[i]->m_ManagedNonWeapons.InvalidIndex() ) - { - g_Managers[i]->m_ManagedNonWeapons.FastRemove( j ); - } - } - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CGameWeaponManager::Spawn() -{ - SetThink( &CGameWeaponManager::Think ); - SetNextThink( gpGlobals->curtime ); - CBaseEntity *pEntity = CreateEntityByName( STRING(m_iszWeaponName) ); - if ( !pEntity ) - { - DevMsg("%s removed itself!\n", GetDebugName() ); - UTIL_Remove(this); - } - else - { - m_bExpectingWeapon = ( dynamic_cast(pEntity) != NULL ); - UTIL_Remove(pEntity); - } -} - -//--------------------------------------------------------- -// Count of all the weapons in the world of my type and -// see if we have a surplus. If there is a surplus, try -// to find suitable candidates for removal. -// -// Right now we just remove the first weapons we find that -// are behind the player, or are out of the player's PVS. -// Later, we may want to score the results so that we -// removed the farthest gun that's not in the player's -// viewcone, etc. -// -// Some notes and thoughts: -// -// This code is designed NOT to remove weapons that are -// hand-placed by level designers. It should only clean -// up weapons dropped by dead NPCs, which is useful in -// situations where enemies are spawned in for a sustained -// period of time. -// -// Right now we PREFER to remove weapons that are not in the -// player's PVS, but this could be opposite of what we -// really want. We may only want to conduct the cleanup on -// weapons that are IN the player's PVS. -//--------------------------------------------------------- -void CGameWeaponManager::Think() -{ - int i; - - // Don't have to think all that often. - SetNextThink( gpGlobals->curtime + 2.0 ); - - const char *pszWeaponName = STRING( m_iszWeaponName ); - - CUtlVector candidates( 0, 64 ); - - if ( m_bExpectingWeapon ) - { - CBaseCombatWeapon *pWeapon = NULL; - // Firstly, count the total number of weapons of this type in the world. - // Also count how many of those can potentially be removed. - pWeapon = assert_cast(gEntList.FindEntityByClassname( pWeapon, pszWeaponName )); - - while( pWeapon ) - { - if( !pWeapon->IsEffectActive( EF_NODRAW ) && pWeapon->IsRemoveable() ) - { - candidates.AddToTail( pWeapon ); - } - - pWeapon = assert_cast(gEntList.FindEntityByClassname( pWeapon, pszWeaponName )); - } - } - else - { - for ( i = 0; i < m_ManagedNonWeapons.Count(); i++) - { - CBaseEntity *pEntity = m_ManagedNonWeapons[i]; - if ( pEntity ) - { - Assert( pEntity->m_iClassname == m_iszWeaponName ); - if ( !pEntity->IsEffectActive( EF_NODRAW ) ) - { - candidates.AddToTail( pEntity ); - } - } - else - { - m_ManagedNonWeapons.FastRemove( i-- ); - } - } - } - - // Calculate the surplus. - int surplus = candidates.Count() - m_iMaxPieces; - - // Based on what the player can see, try to clean up the world by removing weapons that - // the player cannot see right at the moment. - CBaseEntity *pCandidate; - for ( i = 0; i < candidates.Count() && surplus > 0; i++ ) - { - bool fRemovedOne = false; - - pCandidate = candidates[i]; - Assert( !pCandidate->IsEffectActive( EF_NODRAW ) ); - - if ( gpGlobals->maxClients == 1 ) - { - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - // Nodraw serves as a flag that this weapon is already being removed since - // all we're really doing inside this loop is marking them for removal by - // the entity system. We don't want to count the same weapon as removed - // more than once. - if( !UTIL_FindClientInPVS( pCandidate->edict() ) ) - { - fRemovedOne = true; - } - else if( !pPlayer->FInViewCone( pCandidate ) ) - { - fRemovedOne = true; - } - else if ( UTIL_DistApprox( pPlayer->GetAbsOrigin(), pCandidate->GetAbsOrigin() ) > (30*12) ) - { - fRemovedOne = true; - } - } - else - { - fRemovedOne = true; - } - - if( fRemovedOne ) - { - pCandidate->AddEffects( EF_NODRAW ); - UTIL_Remove( pCandidate ); - - DevMsg( 2, "Surplus %s removed\n", pszWeaponName); - surplus--; - } - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CGameWeaponManager::InputSetMaxPieces( inputdata_t &inputdata ) -{ - m_iMaxPieces = inputdata.value.Int(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CGameWeaponManager::InputSetAmmoModifier( inputdata_t &inputdata ) -{ - m_flAmmoMod = inputdata.value.Float(); -} diff --git a/game/server/gameweaponmanager.h b/game/server/gameweaponmanager.h deleted file mode 100644 index 8a955e7ea..000000000 --- a/game/server/gameweaponmanager.h +++ /dev/null @@ -1,23 +0,0 @@ -//========== Copyright 2005, Valve Corporation, All rights reserved. ======== -// -// Purpose: -// -//============================================================================= - -#ifndef GAMEWEAPONMANAGER_H -#define GAMEWEAPONMANAGER_H - -#if defined( _WIN32 ) -#pragma once -#endif - -void CreateWeaponManager( const char *pWeaponName, int iMaxPieces ); - -class CBaseCombatWeapon; - -void WeaponManager_AmmoMod( CBaseCombatWeapon *pWeapon ); - -void WeaponManager_AddManaged( CBaseEntity *pWeapon ); -void WeaponManager_RemoveManaged( CBaseEntity *pWeapon ); - -#endif // GAMEWEAPONMANAGER_H diff --git a/game/server/genericactor.cpp b/game/server/genericactor.cpp deleted file mode 100644 index 6c3c89119..000000000 --- a/game/server/genericactor.cpp +++ /dev/null @@ -1,459 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -//========================================================= -// Generic NPC - purely for scripted sequence work. -//========================================================= -#include "cbase.h" -#include "shareddefs.h" -#include "npcevent.h" -#include "ai_basenpc.h" -#include "ai_hull.h" -#include "ai_baseactor.h" -#include "tier1/strtools.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar flex_looktime( "flex_looktime", "5" ); - -//--------------------------------------------------------- -// Sounds -//--------------------------------------------------------- - - -//========================================================= -// NPC's Anim Events Go Here -//========================================================= - -class CGenericActor : public CAI_BaseActor -{ -public: - DECLARE_CLASS( CGenericActor, CAI_BaseActor ); - - void Spawn( void ); - void Precache( void ); - float MaxYawSpeed( void ); - Class_T Classify ( void ); - void HandleAnimEvent( animevent_t *pEvent ); - int GetSoundInterests ( void ); - - - void TempGunEffect( void ); - - string_t m_strHullName; - - DECLARE_DATADESC(); -}; -LINK_ENTITY_TO_CLASS( generic_actor, CGenericActor ); - -BEGIN_DATADESC( CGenericActor ) - - DEFINE_KEYFIELD(m_strHullName, FIELD_STRING, "hull_name" ), - -END_DATADESC() - - -//========================================================= -// Classify - indicates this NPC's place in the -// relationship table. -//========================================================= -Class_T CGenericActor::Classify ( void ) -{ - return CLASS_NONE; -} - -//========================================================= -// MaxYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -float CGenericActor::MaxYawSpeed ( void ) -{ - return 90; -} - -//========================================================= -// HandleAnimEvent - catches the NPC-specific messages -// that occur when tagged animation frames are played. -//========================================================= -void CGenericActor::HandleAnimEvent( animevent_t *pEvent ) -{ - BaseClass::HandleAnimEvent( pEvent ); -} - -//========================================================= -// GetSoundInterests - generic NPC can't hear. -//========================================================= -int CGenericActor::GetSoundInterests ( void ) -{ - return 0; -} - -//========================================================= -// Spawn -//========================================================= -void CGenericActor::Spawn() -{ - Precache(); - - SetModel( STRING( GetModelName() ) ); - -/* - if ( FStrEq( STRING( GetModelName() ), "models/player.mdl" ) ) - UTIL_SetSize(this, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX); - else - UTIL_SetSize(this, VEC_HULL_MIN, VEC_HULL_MAX); -*/ - - if ( FStrEq( STRING( GetModelName() ), "models/player.mdl" ) || - FStrEq( STRING( GetModelName() ), "models/holo.mdl" ) || - FStrEq( STRING( GetModelName() ), "models/blackout.mdl" ) ) - { - UTIL_SetSize(this, VEC_HULL_MIN, VEC_HULL_MAX); - } - else - { - UTIL_SetSize(this, NAI_Hull::Mins(HULL_HUMAN), NAI_Hull::Maxs(HULL_HUMAN)); - } - - if ( !FStrEq( STRING( GetModelName() ), "models/blackout.mdl" ) ) - { - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - } - else - { - SetSolid( SOLID_NONE ); - } - - SetMoveType( MOVETYPE_STEP ); - SetBloodColor( BLOOD_COLOR_RED ); - m_iHealth = 8; - m_flFieldOfView = 0.5;// indicates the width of this NPC's forward view cone ( as a dotproduct result ) - m_NPCState = NPC_STATE_NONE; - - CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_OPEN_DOORS ); - - // remove head turn if no eyes or forward attachment - if (LookupAttachment( "eyes" ) > 0 && LookupAttachment( "forward" ) > 0) - { - CapabilitiesAdd( bits_CAP_TURN_HEAD | bits_CAP_ANIMATEDFACE ); - } - - if (m_strHullName != NULL_STRING) - { - SetHullType( NAI_Hull::LookupId( STRING( m_strHullName ) ) ); - } - else - { - SetHullType( HULL_HUMAN ); - } - SetHullSizeNormal( ); - - NPCInit(); -} - -//========================================================= -// Precache - precaches all resources this NPC needs -//========================================================= -void CGenericActor::Precache() -{ - PrecacheModel( STRING( GetModelName() ) ); -} - -//========================================================= -// AI Schedules Specific to this NPC -//========================================================= - - - - - - -// ----------------------------------------------------------------------- - - -// FIXME: delete this code - -class CFlextalkActor : public CGenericActor -{ -private: - DECLARE_CLASS( CFlextalkActor, CGenericActor ); -public: - DECLARE_DATADESC(); - - CFlextalkActor() { m_iszSentence = NULL_STRING; m_sentence = 0; } - //void GenericCyclerSpawn(char *szModel, Vector vecMin, Vector vecMax); - //virtual int ObjectCaps( void ) { return (BaseClass::ObjectCaps() | FCAP_IMPULSE_USE); } - //int OnTakeDamage( CBaseEntity *pInflictor, CBaseEntity *pAttacker, float flDamage, int bitsDamageType ); - //void Spawn( void ); - //void Precache( void ); - //void Think( void ); - - virtual void ProcessSceneEvents( void ); - - // Don't treat as a live target - //virtual bool IsAlive( void ) { return FALSE; } - - float m_flextime; - LocalFlexController_t m_flexnum; - float m_flextarget[64]; - float m_blinktime; - float m_looktime; - Vector m_lookTarget; - float m_speaktime; - int m_istalking; - int m_phoneme; - - string_t m_iszSentence; - int m_sentence; - - void SetFlexTarget( LocalFlexController_t flexnum, float value ); - LocalFlexController_t LookupFlex( const char *szTarget ); -}; - -BEGIN_DATADESC( CFlextalkActor ) - - DEFINE_FIELD( m_flextime, FIELD_TIME ), - DEFINE_FIELD( m_flexnum, FIELD_INTEGER ), - DEFINE_ARRAY( m_flextarget, FIELD_FLOAT, 64 ), - DEFINE_FIELD( m_blinktime, FIELD_TIME ), - DEFINE_FIELD( m_looktime, FIELD_TIME ), - DEFINE_FIELD( m_lookTarget, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_speaktime, FIELD_TIME ), - DEFINE_FIELD( m_istalking, FIELD_INTEGER ), - DEFINE_FIELD( m_phoneme, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_iszSentence, FIELD_STRING, "Sentence" ), - DEFINE_FIELD( m_sentence, FIELD_INTEGER ), - -END_DATADESC() - - - -LINK_ENTITY_TO_CLASS( cycler_actor, CFlextalkActor ); - -extern ConVar flex_expression; -extern ConVar flex_talk; - -// Cycler member functions - - -extern const char *predef_flexcontroller_names[]; -extern float predef_flexcontroller_values[7][30]; - -void CFlextalkActor::SetFlexTarget( LocalFlexController_t flexnum, float value ) -{ - m_flextarget[flexnum] = value; - - const char *pszType = GetFlexControllerType( flexnum ); - - for (LocalFlexController_t i = LocalFlexController_t(0); i < GetNumFlexControllers(); i++) - { - if (i != flexnum) - { - const char *pszOtherType = GetFlexControllerType( i ); - if (stricmp( pszType, pszOtherType ) == 0) - { - m_flextarget[i] = 0; - } - } - } - - float value2 = value; - if (1 || random->RandomFloat( 0.0, 1.0 ) < 0.2) - { - value2 = random->RandomFloat( value - 0.2, value + 0.2 ); - value2 = clamp( value2, 0.0, 1.0 ); - } - - - // HACK, for now, consider then linked is named "right_" or "left_" - if (strncmp( "right_", GetFlexControllerName( flexnum ), 6 ) == 0) - { - m_flextarget[flexnum+1] = value2; - } - else if (strncmp( "left_", GetFlexControllerName( flexnum ), 5 ) == 0) - { - m_flextarget[flexnum-1] = value2; - } -} - - -LocalFlexController_t CFlextalkActor::LookupFlex( const char *szTarget ) -{ - for (LocalFlexController_t i = LocalFlexController_t(0); i < GetNumFlexControllers(); i++) - { - const char *pszFlex = GetFlexControllerName( i ); - if (stricmp( szTarget, pszFlex ) == 0) - { - return i; - } - } - return LocalFlexController_t(-1); -} - - -void CFlextalkActor::ProcessSceneEvents( void ) -{ - if ( HasSceneEvents() ) - { - BaseClass::ProcessSceneEvents( ); - return; - } - - // only do this if they have more than eyelid movement - if (GetNumFlexControllers() > 2) - { - const char *pszExpression = flex_expression.GetString(); - - if (pszExpression && pszExpression[0] == '+' && pszExpression[1] != '\0') - { - int i; - int j = atoi( &pszExpression[1] ); - for (i = 0; i < GetNumFlexControllers(); i++) - { - m_flextarget[m_flexnum] = 0; - } - - for (i = 0; i < 35 && predef_flexcontroller_names[i]; i++) - { - m_flexnum = LookupFlex( predef_flexcontroller_names[i] ); - m_flextarget[m_flexnum] = predef_flexcontroller_values[j][i]; - // Msg( "%s %.3f\n", predef_flexcontroller_names[i], predef_flexcontroller_values[j][i] ); - } - } - else if (pszExpression && pszExpression[0] != '\0' && strcmp(pszExpression, "+") != 0) - { - char szExpression[128]; - char szTemp[32]; - - Q_strncpy( szExpression, pszExpression ,sizeof(szExpression)); - char *pszExpression = szExpression; - - while (*pszExpression != '\0') - { - if (*pszExpression == '+') - *pszExpression = ' '; - - pszExpression++; - } - - pszExpression = szExpression; - - while (*pszExpression) - { - if (*pszExpression != ' ') - { - if (*pszExpression == '-') - { - for (LocalFlexController_t i = LocalFlexController_t(0); i < GetNumFlexControllers(); i++) - { - m_flextarget[i] = 0; - } - } - else if (*pszExpression == '?') - { - for (LocalFlexController_t i = LocalFlexController_t(0); i < GetNumFlexControllers(); i++) - { - Msg( "\"%s\" ", GetFlexControllerName( i ) ); - } - Msg( "\n" ); - flex_expression.SetValue( "" ); - } - else - { - if (sscanf( pszExpression, "%31s", szTemp ) == 1) - { - m_flexnum = LookupFlex( szTemp ); - - if (m_flexnum != -1 && m_flextarget[m_flexnum] != 1) - { - m_flextarget[m_flexnum] = 1.0; - // SetFlexTarget( m_flexnum ); - } - pszExpression += strlen( szTemp ) - 1; - } - } - } - pszExpression++; - } - } - else if (m_flextime < gpGlobals->curtime) - { - m_flextime = gpGlobals->curtime + random->RandomFloat( 0.3, 0.5 ) * (30.0 / GetNumFlexControllers()); - m_flexnum = (LocalFlexController_t)random->RandomInt( 0, GetNumFlexControllers() - 1 ); - - if (m_flextarget[m_flexnum] == 1) - { - m_flextarget[m_flexnum] = 0; - } - else if (stricmp( GetFlexControllerType( m_flexnum ), "phoneme" ) != 0) - { - if (strstr( GetFlexControllerName( m_flexnum ), "upper_raiser" ) == NULL) - { - Msg( "%s:%s\n", GetFlexControllerType( m_flexnum ), GetFlexControllerName( m_flexnum ) ); - SetFlexTarget( m_flexnum, random->RandomFloat( 0.5, 1.0 ) ); - } - } - } - - // slide it up. - for (LocalFlexController_t i = LocalFlexController_t(0); i < GetNumFlexControllers(); i++) - { - float weight = GetFlexWeight( i ); - - if (weight != m_flextarget[i]) - { - weight = weight + (m_flextarget[i] - weight) / random->RandomFloat( 2.0, 4.0 ); - } - weight = clamp( weight, 0.0f, 1.0f ); - SetFlexWeight( i, weight ); - } - - if (flex_talk.GetInt() == -1) - { - m_istalking = 1; - - char pszSentence[256]; - Q_snprintf( pszSentence,sizeof(pszSentence), "%s%d", STRING(m_iszSentence), m_sentence++ ); - int sentenceIndex = engine->SentenceIndexFromName( pszSentence ); - if (sentenceIndex >= 0) - { - Msg( "%d : %s\n", sentenceIndex, pszSentence ); - CPASAttenuationFilter filter( this ); - CBaseEntity::EmitSentenceByIndex( filter, entindex(), CHAN_VOICE, sentenceIndex, 1, SNDLVL_TALKING, 0, PITCH_NORM ); - } - else - { - m_sentence = 0; - } - - flex_talk.SetValue( "0" ); - } - else if (flex_talk.GetInt() == -2) - { - m_flNextEyeLookTime = gpGlobals->curtime + 1000.0; - } - else if (flex_talk.GetInt() == -3) - { - m_flNextEyeLookTime = gpGlobals->curtime; - flex_talk.SetValue( "0" ); - } - else if (flex_talk.GetInt() == -4) - { - AddLookTarget( UTIL_PlayerByIndex( 1 ), 0.5, flex_looktime.GetFloat() ); - flex_talk.SetValue( "0" ); - } - else if (flex_talk.GetInt() == -5) - { - PickLookTarget( true ); - flex_talk.SetValue( "0" ); - } - } -} diff --git a/game/server/genericmonster.cpp b/game/server/genericmonster.cpp deleted file mode 100644 index 405ecdc0b..000000000 --- a/game/server/genericmonster.cpp +++ /dev/null @@ -1,472 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -//========================================================= -// Generic NPC - purely for scripted sequence work. -//========================================================= -#include "cbase.h" -#include "npcevent.h" -#include "ai_basenpc.h" -#include "ai_hull.h" -#include "KeyValues.h" -#include "engine/IEngineSound.h" -#include "physics_bone_follower.h" -#include "ai_baseactor.h" -#include "ai_senses.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// For holograms, make them not solid so the player can walk through them -#define SF_GENERICNPC_NOTSOLID (1 << 16) - -//========================================================= -// NPC's Anim Events Go Here -//========================================================= - -class CGenericNPC : public CAI_BaseNPC -{ -public: - DECLARE_CLASS( CGenericNPC, CAI_BaseNPC ); - - void Spawn( void ); - void Precache( void ); - float MaxYawSpeed( void ); - Class_T Classify ( void ); - void HandleAnimEvent( animevent_t *pEvent ); - int GetSoundInterests ( void ); - - void TempGunEffect( void ); -}; - -LINK_ENTITY_TO_CLASS( monster_generic, CGenericNPC ); - -//========================================================= -// Classify - indicates this NPC's place in the -// relationship table. -//========================================================= -Class_T CGenericNPC::Classify ( void ) -{ - return CLASS_NONE; -} - - -//========================================================= -// MaxYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -float CGenericNPC::MaxYawSpeed ( void ) -{ - return 90; -} - -//--------------------------------------------------------- -// !!!TEMP -// !!!TEMP -// !!!TEMP -// !!!TEMP -// -// (sjb) -//--------------------------------------------------------- -void CGenericNPC::TempGunEffect( void ) -{ - QAngle vecAngle; - Vector vecDir, vecShot; - Vector vecMuzzle, vecButt; - - GetAttachment( 2, vecMuzzle, vecAngle ); - GetAttachment( 3, vecButt, vecAngle ); - - vecDir = vecMuzzle - vecButt; - VectorNormalize( vecDir ); - - // CPVSFilter filter( GetAbsOrigin() ); - //te->ShowLine( filter, 0.0, vecSpot, vecSpot + vecForward ); - //UTIL_Sparks( vecMuzzle ); - - bool fSound = false; - - if( random->RandomInt( 0, 3 ) == 0 ) - { - fSound = true; - } - - Vector start = vecMuzzle + vecDir * 64; - Vector end = vecMuzzle + vecDir * 4096; - UTIL_Tracer( start, end, 0, TRACER_DONT_USE_ATTACHMENT, 5500, fSound ); - CPASAttenuationFilter filter2( this, "GenericNPC.GunSound" ); - EmitSound( filter2, entindex(), "GenericNPC.GunSound" ); -} - - -//========================================================= -// HandleAnimEvent - catches the NPC-specific messages -// that occur when tagged animation frames are played. -//========================================================= -void CGenericNPC::HandleAnimEvent( animevent_t *pEvent ) -{ - switch( pEvent->event ) - { - case 1: - // TEMPORARLY. Makes the May 2001 sniper demo work (sjb) - TempGunEffect(); - break; - - default: - BaseClass::HandleAnimEvent( pEvent ); - break; - } -} - -//========================================================= -// GetSoundInterests - generic NPC can't hear. -//========================================================= -int CGenericNPC::GetSoundInterests ( void ) -{ - return 0; -} - -//========================================================= -// Spawn -//========================================================= -void CGenericNPC::Spawn() -{ - Precache(); - - SetModel( STRING( GetModelName() ) ); - -/* - if ( FStrEq( STRING( GetModelName() ), "models/player.mdl" ) ) - UTIL_SetSize(this, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX); - else - UTIL_SetSize(this, VEC_HULL_MIN, VEC_HULL_MAX); -*/ - - if ( FStrEq( STRING( GetModelName() ), "models/player.mdl" ) || FStrEq( STRING( GetModelName() ), "models/holo.mdl" ) ) - UTIL_SetSize(this, VEC_HULL_MIN, VEC_HULL_MAX); - else - UTIL_SetSize(this, NAI_Hull::Mins(HULL_HUMAN), NAI_Hull::Maxs(HULL_HUMAN)); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - m_bloodColor = BLOOD_COLOR_RED; - m_iHealth = 8; - m_flFieldOfView = 0.5;// indicates the width of this NPC's forward view cone ( as a dotproduct result ) - m_NPCState = NPC_STATE_NONE; - - CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_OPEN_DOORS ); - - NPCInit(); - if ( !HasSpawnFlags(SF_GENERICNPC_NOTSOLID) ) - { - trace_t tr; - UTIL_TraceEntity( this, GetAbsOrigin(), GetAbsOrigin(), MASK_SOLID, &tr ); - if ( tr.startsolid ) - { - Msg("Placed npc_generic in solid!!! (%s)\n", STRING(GetModelName()) ); - m_spawnflags |= SF_GENERICNPC_NOTSOLID; - } - } - - if ( HasSpawnFlags(SF_GENERICNPC_NOTSOLID) ) - { - AddSolidFlags( FSOLID_NOT_SOLID ); - m_takedamage = DAMAGE_NO; - VPhysicsDestroyObject(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: precaches all resources this NPC needs -//----------------------------------------------------------------------------- -void CGenericNPC::Precache() -{ - BaseClass::Precache(); - - PrecacheModel( STRING( GetModelName() ) ); - - PrecacheScriptSound( "GenericNPC.GunSound" ); -} - -// a really large health is set to make sure these never die. -const int TOO_MUCH_HEALTH_TO_DIE = 1000; -//======================================================================================= -// Furniture: A dumb "NPC" that is uses in scripted sequences -// where an NPC needs to be frame locked with a prop. -//======================================================================================= -class CNPC_Furniture : public CAI_BaseActor -{ - DECLARE_CLASS( CNPC_Furniture, CAI_BaseActor ); - DECLARE_DATADESC(); -public: - void Spawn( void ); - void Precache( void ); - void Die( void ); - void UpdateEfficiency( bool bInPVS ) { SetEfficiency( ( GetSleepState() != AISS_AWAKE ) ? AIE_DORMANT : AIE_NORMAL ); SetMoveEfficiency( AIME_NORMAL ); } - Class_T Classify ( void ); - float MaxYawSpeed( void ){ return 0; } - virtual int ObjectCaps( void ); - bool CreateVPhysics( void ); - void NPCThink( void ); - void UpdateOnRemove( void ); - int SelectSchedule( void ); - void OnRestore( void ); - int OnTakeDamage( const CTakeDamageInfo &info ) - { - if ( m_iHealth <= info.GetDamage() ) - m_iHealth = info.GetDamage() + TOO_MUCH_HEALTH_TO_DIE; - return BaseClass::OnTakeDamage(info); - } - - void DrawDebugGeometryOverlays(void); - - void SetPlayerAvoidState( void ); - void InputDisablePlayerCollision( inputdata_t &inputdata ); - void InputEnablePlayerCollision( inputdata_t &inputdata ); - void UpdateBoneFollowerState( void ); - -private: - // Contained Bone Follower manager - CBoneFollowerManager m_BoneFollowerManager; -}; - -LINK_ENTITY_TO_CLASS( monster_furniture, CNPC_Furniture ); -LINK_ENTITY_TO_CLASS( npc_furniture, CNPC_Furniture ); - -//----------------------------------------------------------------------------- -// Save/load -//----------------------------------------------------------------------------- - -BEGIN_DATADESC( CNPC_Furniture ) - DEFINE_EMBEDDED( m_BoneFollowerManager ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisablePlayerCollision", InputDisablePlayerCollision ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnablePlayerCollision", InputEnablePlayerCollision ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: This used to have something to do with bees flying, but -// now it only initializes moving furniture in scripted sequences -//----------------------------------------------------------------------------- -void CNPC_Furniture::Spawn( ) -{ - Precache(); - - SetModel( STRING(GetModelName()) ); - - SetMoveType( MOVETYPE_STEP ); - SetSolid( SOLID_BBOX ); - - // Our collision, if needed, will be done through bone followers - AddSolidFlags( FSOLID_NOT_SOLID ); - - SetBloodColor( DONT_BLEED ); - m_iHealth = TOO_MUCH_HEALTH_TO_DIE; //wow - m_takedamage = DAMAGE_AIM; - SetSequence( 0 ); - SetCycle( 0 ); - SetNavType( NAV_FLY ); - AddFlag( FL_FLY ); - - CapabilitiesAdd( bits_CAP_MOVE_FLY | bits_CAP_TURN_HEAD | bits_CAP_ANIMATEDFACE ); - - AddEFlags( EFL_NO_MEGAPHYSCANNON_RAGDOLL ); - -// pev->nextthink += 1.0; -// SetThink (WalkMonsterDelay); - - ResetSequenceInfo( ); - SetCycle( 0 ); - NPCInit(); - - // Furniture needs to block LOS - SetBlocksLOS( true ); - - // Furniture just wastes CPU doing sensing code, since all they do is idle and play scripts - GetSenses()->AddSensingFlags( SENSING_FLAGS_DONT_LOOK | SENSING_FLAGS_DONT_LISTEN ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Furniture::Precache( void ) -{ - PrecacheModel( STRING( GetModelName() ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_Furniture::ObjectCaps( void ) -{ - // HL2 furniture transitions -#ifdef HL2_DLL - return CAI_BaseNPC::ObjectCaps(); -#else - return (CAI_BaseNPC::ObjectCaps() & ~FCAP_ACROSS_TRANSITION); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Furniture is killed -//----------------------------------------------------------------------------- -void CNPC_Furniture::Die( void ) -{ - SetThink ( &CNPC_Furniture::SUB_Remove ); - SetNextThink( gpGlobals->curtime ); -} - -//----------------------------------------------------------------------------- -// Purpose: ID's Furniture as neutral (noone will attack it) -//----------------------------------------------------------------------------- -Class_T CNPC_Furniture::Classify ( void ) -{ - return CLASS_NONE; -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -bool CNPC_Furniture::CreateVPhysics( void ) -{ -#ifndef HL2_DLL - return false; -#endif - - if ( !m_BoneFollowerManager.GetNumBoneFollowers() ) - { - KeyValues *modelKeyValues = new KeyValues(""); - if ( modelKeyValues->LoadFromBuffer( modelinfo->GetModelName( GetModel() ), modelinfo->GetModelKeyValueText( GetModel() ) ) ) - { - // Do we have a bone follower section? - KeyValues *pkvBoneFollowers = modelKeyValues->FindKey("bone_followers"); - if ( pkvBoneFollowers ) - { - // Loop through the list and create the bone followers - KeyValues *pBone = pkvBoneFollowers->GetFirstSubKey(); - while ( pBone ) - { - // Add it to the list - const char *pBoneName = pBone->GetString(); - m_BoneFollowerManager.AddBoneFollower( this, pBoneName ); - - pBone = pBone->GetNextKey(); - } - } - } - modelKeyValues->deleteThis(); - } - - return true; -} - -void CNPC_Furniture::InputDisablePlayerCollision( inputdata_t &inputdata ) -{ - SetCollisionGroup( COLLISION_GROUP_NPC_ACTOR ); - UpdateBoneFollowerState(); -} - -void CNPC_Furniture::InputEnablePlayerCollision( inputdata_t &inputdata ) -{ - SetCollisionGroup( COLLISION_GROUP_NPC ); - UpdateBoneFollowerState(); -} - -void CNPC_Furniture::UpdateBoneFollowerState( void ) -{ - if ( m_BoneFollowerManager.GetNumBoneFollowers() ) - { - physfollower_t* pBone = m_BoneFollowerManager.GetBoneFollower( 0 ); - - if ( pBone && pBone->hFollower && pBone->hFollower->GetCollisionGroup() != GetCollisionGroup() ) - { - for ( int i = 0; i < m_BoneFollowerManager.GetNumBoneFollowers(); i++ ) - { - pBone = m_BoneFollowerManager.GetBoneFollower( i ); - - if ( pBone && pBone->hFollower ) - { - pBone->hFollower->SetCollisionGroup( GetCollisionGroup() ); - } - } - } - } -} - -void CNPC_Furniture::SetPlayerAvoidState( void ) -{ - -} -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Furniture::NPCThink( void ) -{ - BaseClass::NPCThink(); - - // Update follower bones - m_BoneFollowerManager.UpdateBoneFollowers(this); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Furniture::UpdateOnRemove( void ) -{ - m_BoneFollowerManager.DestroyBoneFollowers(); - - BaseClass::UpdateOnRemove(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CNPC_Furniture::SelectSchedule( void ) -{ - switch( m_NPCState ) - { - case NPC_STATE_NONE: - case NPC_STATE_PRONE: - case NPC_STATE_IDLE: - case NPC_STATE_ALERT: - case NPC_STATE_COMBAT: - case NPC_STATE_DEAD: - return SCHED_WAIT_FOR_SCRIPT; - - case NPC_STATE_SCRIPT: - return BaseClass::SelectSchedule(); - - default: - DevWarning( 2, "Invalid State for SelectSchedule!\n" ); - break; - } - - return SCHED_FAIL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Furniture::OnRestore( void ) -{ - // Recreate any bone followers we have - CreateVPhysics(); - - BaseClass::OnRestore(); -} -void CNPC_Furniture::DrawDebugGeometryOverlays( void ) -{ - //ugh - if ( m_debugOverlays & OVERLAY_NPC_ZAP_BIT ) - { - m_debugOverlays &= ~OVERLAY_NPC_ZAP_BIT; - } - - BaseClass::DrawDebugGeometryOverlays(); -} diff --git a/game/server/gib.cpp b/game/server/gib.cpp deleted file mode 100644 index 3d15df6f0..000000000 --- a/game/server/gib.cpp +++ /dev/null @@ -1,679 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: A gib is a chunk of a body, or a piece of wood/metal/rocks/etc. -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//===========================================================================// - -#include "cbase.h" -#include "gib.h" -#include "soundent.h" -#include "func_break.h" // For materials -#include "player.h" -#include "vstdlib/random.h" -#include "ai_utils.h" -#include "EntityFlame.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern Vector g_vecAttackDir; // In globals.cpp - -BEGIN_DATADESC( CGib ) - - // gibs are not saved/restored -// DEFINE_FIELD( m_bloodColor, FIELD_INTEGER ), -// DEFINE_FIELD( m_hSprite, FIELD_EHANDLE ), -// DEFINE_FIELD( m_cBloodDecals, FIELD_INTEGER ), -// DEFINE_FIELD( m_material, FIELD_INTEGER ), -// DEFINE_FIELD( m_lifeTime, FIELD_TIME ), -// DEFINE_FIELD( m_pSprite, CSprite ), -// DEFINE_FIELD( m_hFlame, FIELD_EHANDLE ), - -// DEFINE_FIELD( m_hPhysicsAttacker, FIELD_EHANDLE ), -// DEFINE_FIELD( m_flLastPhysicsInfluenceTime, FIELD_TIME ), - -// DEFINE_FIELD( m_bForceRemove, FIELD_BOOLEAN ), - - // Function pointers - DEFINE_ENTITYFUNC( BounceGibTouch ), - DEFINE_ENTITYFUNC( StickyGibTouch ), - DEFINE_THINKFUNC( WaitTillLand ), - DEFINE_THINKFUNC( DieThink ), - -END_DATADESC() - - -// HACKHACK -- The gib velocity equations don't work -void CGib::LimitVelocity( void ) -{ - Vector vecNewVelocity = GetAbsVelocity(); - float length = VectorNormalize( vecNewVelocity ); - - // ceiling at 1500. The gib velocity equation is not bounded properly. Rather than tune it - // in 3 separate places again, I'll just limit it here. - if ( length > 1500.0 ) - { - vecNewVelocity *= 1500; // This should really be sv_maxvelocity * 0.75 or something - SetAbsVelocity( vecNewVelocity ); - } -} - - -void CGib::SpawnStickyGibs( CBaseEntity *pVictim, Vector vecOrigin, int cGibs ) -{ - int i; - - if ( g_Language.GetInt() == LANGUAGE_GERMAN ) - { - // no sticky gibs in germany right now! - return; - } - - for ( i = 0 ; i < cGibs ; i++ ) - { - CGib *pGib = (CGib *)CreateEntityByName( "gib" ); - - pGib->Spawn( "models/stickygib.mdl" ); - pGib->m_nBody = random->RandomInt(0,2); - - if ( pVictim ) - { - pGib->SetLocalOrigin( - Vector( vecOrigin.x + random->RandomFloat( -3, 3 ), - vecOrigin.y + random->RandomFloat( -3, 3 ), - vecOrigin.z + random->RandomFloat( -3, 3 ) ) ); - - // make the gib fly away from the attack vector - Vector vecNewVelocity = g_vecAttackDir * -1; - - // mix in some noise - vecNewVelocity.x += random->RandomFloat ( -0.15, 0.15 ); - vecNewVelocity.y += random->RandomFloat ( -0.15, 0.15 ); - vecNewVelocity.z += random->RandomFloat ( -0.15, 0.15 ); - - vecNewVelocity *= 900; - - QAngle vecAngVelocity( random->RandomFloat ( 250, 400 ), random->RandomFloat ( 250, 400 ), 0 ); - pGib->SetLocalAngularVelocity( vecAngVelocity ); - - // copy owner's blood color - pGib->SetBloodColor( pVictim->BloodColor() ); - - pGib->AdjustVelocityBasedOnHealth( pVictim->m_iHealth, vecNewVelocity ); - pGib->SetAbsVelocity( vecNewVelocity ); - - pGib->SetMoveType( MOVETYPE_FLYGRAVITY ); - pGib->RemoveSolidFlags( FSOLID_NOT_SOLID ); - pGib->SetCollisionBounds( vec3_origin, vec3_origin ); - pGib->SetTouch ( &CGib::StickyGibTouch ); - pGib->SetThink (NULL); - } - pGib->LimitVelocity(); - } -} - -void CGib::SpawnHeadGib( CBaseEntity *pVictim ) -{ - CGib *pGib = CREATE_ENTITY( CGib, "gib" ); - - if ( g_Language.GetInt() == LANGUAGE_GERMAN ) - { - pGib->Spawn( "models/germangibs.mdl" );// throw one head - pGib->m_nBody = 0; - } - else - { - pGib->Spawn( "models/gibs/hgibs.mdl" );// throw one head - pGib->m_nBody = 0; - } - - if ( pVictim ) - { - Vector vecNewVelocity = pGib->GetAbsVelocity(); - - pGib->SetLocalOrigin( pVictim->EyePosition() ); - - edict_t *pentPlayer = UTIL_FindClientInPVS( pGib->edict() ); - - if ( random->RandomInt ( 0, 100 ) <= 5 && pentPlayer ) - { - // 5% chance head will be thrown at player's face. - CBasePlayer *player = (CBasePlayer *)CBaseEntity::Instance( pentPlayer ); - if ( player ) - { - vecNewVelocity = ( player->EyePosition() ) - pGib->GetAbsOrigin(); - VectorNormalize(vecNewVelocity); - vecNewVelocity *= 300; - vecNewVelocity.z += 100; - } - } - else - { - vecNewVelocity = Vector (random->RandomFloat(-100,100), random->RandomFloat(-100,100), random->RandomFloat(200,300)); - } - - QAngle vecNewAngularVelocity = pGib->GetLocalAngularVelocity(); - vecNewAngularVelocity.x = random->RandomFloat ( 100, 200 ); - vecNewAngularVelocity.y = random->RandomFloat ( 100, 300 ); - pGib->SetLocalAngularVelocity( vecNewAngularVelocity ); - - // copy owner's blood color - pGib->SetBloodColor( pVictim->BloodColor() ); - pGib->AdjustVelocityBasedOnHealth( pVictim->m_iHealth, vecNewVelocity ); - pGib->SetAbsVelocity( vecNewVelocity ); - } - pGib->LimitVelocity(); -} - - -//----------------------------------------------------------------------------- -// Blood color (see BLOOD_COLOR_* macros in baseentity.h) -//----------------------------------------------------------------------------- -void CGib::SetBloodColor( int nBloodColor ) -{ - m_bloodColor = nBloodColor; -} - - -//------------------------------------------------------------------------------ -// A little piece of duplicated code -//------------------------------------------------------------------------------ -void CGib::AdjustVelocityBasedOnHealth( int nHealth, Vector &vecVelocity ) -{ - if ( nHealth > -50) - { - vecVelocity *= 0.7; - } - else if ( nHealth > -200) - { - vecVelocity *= 2; - } - else - { - vecVelocity *= 4; - } -} - - -//------------------------------------------------------------------------------ -// Purpose : Initialize a gibs position and velocity -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGib::InitGib( CBaseEntity *pVictim, float fMinVelocity, float fMaxVelocity ) -{ - // ------------------------------------------------------------------------ - // If have a pVictim spawn the gib somewhere in the pVictim's bounding volume - // ------------------------------------------------------------------------ - if ( pVictim ) - { - // Find a random position within the bounding box (add 1 to Z to get it out of the ground) - Vector vecOrigin; - pVictim->CollisionProp()->RandomPointInBounds( vec3_origin, Vector( 1, 1, 1 ), &vecOrigin ); - vecOrigin.z += 1.0f; - SetAbsOrigin( vecOrigin ); - - // make the gib fly away from the attack vector - Vector vecNewVelocity = g_vecAttackDir * -1; - - // mix in some noise - vecNewVelocity.x += random->RandomFloat ( -0.25, 0.25 ); - vecNewVelocity.y += random->RandomFloat ( -0.25, 0.25 ); - vecNewVelocity.z += random->RandomFloat ( -0.25, 0.25 ); - - vecNewVelocity *= random->RandomFloat ( fMaxVelocity, fMinVelocity ); - - QAngle vecNewAngularVelocity = GetLocalAngularVelocity(); - vecNewAngularVelocity.x = random->RandomFloat ( 100, 200 ); - vecNewAngularVelocity.y = random->RandomFloat ( 100, 300 ); - SetLocalAngularVelocity( vecNewAngularVelocity ); - - // copy owner's blood color - SetBloodColor( pVictim->BloodColor() ); - - AdjustVelocityBasedOnHealth( pVictim->m_iHealth, vecNewVelocity ); - - // Attempt to be physical if we can - if ( VPhysicsInitNormal( SOLID_BBOX, 0, false ) ) - { - IPhysicsObject *pObj = VPhysicsGetObject(); - - if ( pObj != NULL ) - { - AngularImpulse angImpulse = RandomAngularImpulse( -500, 500 ); - pObj->AddVelocity( &vecNewVelocity, &angImpulse ); - } - } - else - { - SetSolid( SOLID_BBOX ); - SetCollisionBounds( vec3_origin, vec3_origin ); - SetAbsVelocity( vecNewVelocity ); - } - - SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - } - - LimitVelocity(); -} - -//------------------------------------------------------------------------------ -// Purpose : Given an .mdl file with gibs and the number of gibs in the file -// spawns them in pVictim's bounding box -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGib::SpawnSpecificGibs( CBaseEntity* pVictim, - int nNumGibs, - float vMinVelocity, - float vMaxVelocity, - const char* cModelName, - float flLifetime) -{ - for (int i=0;iSpawn( cModelName ); - pGib->m_nBody = i; - pGib->InitGib( pVictim, vMinVelocity, vMaxVelocity ); - pGib->m_lifeTime = flLifetime; - - if ( pVictim != NULL ) - { - pGib->SetOwnerEntity( pVictim ); - } - } -} - -//------------------------------------------------------------------------------ -// Purpose : Spawn random gibs of the given gib type -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGib::SpawnRandomGibs( CBaseEntity *pVictim, int cGibs, GibType_e eGibType ) -{ - int cSplat; - - for ( cSplat = 0 ; cSplat < cGibs ; cSplat++ ) - { - CGib *pGib = CREATE_ENTITY( CGib, "gib" ); - - if ( g_Language.GetInt() == LANGUAGE_GERMAN ) - { - pGib->Spawn( "models/germangibs.mdl" ); - pGib->m_nBody = random->RandomInt(0,GERMAN_GIB_COUNT-1); - } - else - { - switch (eGibType) - { - case GIB_HUMAN: - // human pieces - pGib->Spawn( "models/gibs/hgibs.mdl" ); - pGib->m_nBody = random->RandomInt(1,HUMAN_GIB_COUNT-1);// start at one to avoid throwing random amounts of skulls (0th gib) - break; - case GIB_ALIEN: - // alien pieces - pGib->Spawn( "models/gibs/agibs.mdl" ); - pGib->m_nBody = random->RandomInt(0,ALIEN_GIB_COUNT-1); - break; - } - } - pGib->InitGib( pVictim, 300, 400); - } -} - -//========================================================= -// WaitTillLand - in order to emit their meaty scent from -// the proper location, gibs should wait until they stop -// bouncing to emit their scent. That's what this function -// does. -//========================================================= -void CGib::WaitTillLand ( void ) -{ - if (!IsInWorld()) - { - UTIL_Remove( this ); - return; - } - - if ( GetAbsVelocity() == vec3_origin ) - { - SetRenderColorA( 255 ); - m_nRenderMode = kRenderTransTexture; - if ( GetMoveType() != MOVETYPE_VPHYSICS ) - { - AddSolidFlags( FSOLID_NOT_SOLID ); - } - SetLocalAngularVelocity( vec3_angle ); - - SetNextThink( gpGlobals->curtime + m_lifeTime ); - SetThink ( &CGib::SUB_FadeOut ); - - if ( GetSprite() ) - { - CSprite *pSprite = dynamic_cast( GetSprite() ); - - if ( pSprite ) - { - //Adrian - Why am I doing this? Check InitPointGib for the answer! - if ( m_lifeTime == 0 ) - m_lifeTime = random->RandomFloat( 1, 3 ); - - pSprite->FadeAndDie( m_lifeTime ); - } - } - - if ( GetFlame() ) - { - CEntityFlame *pFlame = dynamic_cast< CEntityFlame*>( GetFlame() ); - - if ( pFlame ) - { - pFlame->SetLifetime( 1.0f ); - } - } - - // If you bleed, you stink! - if ( m_bloodColor != DONT_BLEED ) - { - // ok, start stinkin! - // FIXME: It's too easy to fill up the sound queue with all these meat sounds - // CSoundEnt::InsertSound ( SOUND_MEAT, GetAbsOrigin(), 384, 25 ); - } - } - else - { - // wait and check again in another half second. - SetNextThink( gpGlobals->curtime + 0.5f ); - } -} - -bool CGib::SUB_AllowedToFade( void ) -{ - if( VPhysicsGetObject() ) - { - if( VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD || GetEFlags() & EFL_IS_BEING_LIFTED_BY_BARNACLE ) - return false; - } - - CBasePlayer *pPlayer = ( AI_IsSinglePlayer() ) ? UTIL_GetLocalPlayer() : NULL; - - if ( pPlayer && pPlayer->FInViewCone( this ) && m_bForceRemove == false ) - { - return false; - } - - return true; -} - - -void CGib::DieThink ( void ) -{ - if ( GetSprite() ) - { - CSprite *pSprite = dynamic_cast( GetSprite() ); - - if ( pSprite ) - { - pSprite->FadeAndDie( 0.0 ); - } - } - - if ( GetFlame() ) - { - CEntityFlame *pFlame = dynamic_cast< CEntityFlame*>( GetFlame() ); - - if ( pFlame ) - { - pFlame->SetLifetime( 1.0f ); - } - } - - if ( g_pGameRules->IsMultiplayer() ) - { - UTIL_Remove( this ); - } - else - { - SetThink ( &CGib::SUB_FadeOut ); - SetNextThink( gpGlobals->curtime ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGib::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - CBasePlayer *pPlayer = ToBasePlayer( pActivator ); - - if ( pPlayer ) - { - pPlayer->PickupObject( this ); - } -} - -//----------------------------------------------------------------------------- -// Physics Attacker -//----------------------------------------------------------------------------- -void CGib::SetPhysicsAttacker( CBasePlayer *pEntity, float flTime ) -{ - m_hPhysicsAttacker = pEntity; - m_flLastPhysicsInfluenceTime = flTime; -} - - -//----------------------------------------------------------------------------- -// Purpose: Keep track of physgun influence -//----------------------------------------------------------------------------- -void CGib::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) -{ - SetPhysicsAttacker( pPhysGunUser, gpGlobals->curtime ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGib::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ) -{ - SetPhysicsAttacker( pPhysGunUser, gpGlobals->curtime ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CBasePlayer *CGib::HasPhysicsAttacker( float dt ) -{ - if (gpGlobals->curtime - dt <= m_flLastPhysicsInfluenceTime) - { - return m_hPhysicsAttacker; - } - return NULL; -} - - -// -// Gib bounces on the ground or wall, sponges some blood down, too! -// -void CGib::BounceGibTouch ( CBaseEntity *pOther ) -{ - Vector vecSpot; - trace_t tr; - - IPhysicsObject *pPhysics = VPhysicsGetObject(); - - if ( pPhysics ) - return; - - //if ( random->RandomInt(0,1) ) - // return;// don't bleed everytime - if (GetFlags() & FL_ONGROUND) - { - SetAbsVelocity( GetAbsVelocity() * 0.9 ); - QAngle angles = GetLocalAngles(); - angles.x = 0; - angles.z = 0; - SetLocalAngles( angles ); - - QAngle angVel = GetLocalAngularVelocity(); - angVel.x = 0; - angVel.z = 0; - SetLocalAngularVelocity( vec3_angle ); - } - else - { - if ( g_Language.GetInt() != LANGUAGE_GERMAN && m_cBloodDecals > 0 && m_bloodColor != DONT_BLEED ) - { - vecSpot = GetAbsOrigin() + Vector ( 0 , 0 , 8 );//move up a bit, and trace down. - UTIL_TraceLine ( vecSpot, vecSpot + Vector ( 0, 0, -24 ), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr); - - UTIL_BloodDecalTrace( &tr, m_bloodColor ); - - m_cBloodDecals--; - } - - if ( m_material != matNone && random->RandomInt(0,2) == 0 ) - { - float volume; - float zvel = fabs(GetAbsVelocity().z); - - volume = 0.8f * MIN(1.0, ((float)zvel) / 450.0f); - - CBreakable::MaterialSoundRandom( entindex(), (Materials)m_material, volume ); - } - } -} - -// -// Sticky gib puts blood on the wall and stays put. -// -void CGib::StickyGibTouch ( CBaseEntity *pOther ) -{ - Vector vecSpot; - trace_t tr; - - SetThink ( &CGib::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 10 ); - - if ( !FClassnameIs( pOther, "worldspawn" ) ) - { - SetNextThink( gpGlobals->curtime ); - return; - } - - UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + GetAbsVelocity() * 32, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr); - - UTIL_BloodDecalTrace( &tr, m_bloodColor ); - - Vector vecForward = tr.plane.normal * -1; - QAngle angles; - VectorAngles( vecForward, angles ); - SetLocalAngles( angles ); - SetAbsVelocity( vec3_origin ); - SetLocalAngularVelocity( vec3_angle ); - SetMoveType( MOVETYPE_NONE ); -} - -// -// Throw a chunk -// -void CGib::Spawn( const char *szGibModel ) -{ - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); - SetFriction(0.55); // deading the bounce a bit - - // sometimes an entity inherits the edict from a former piece of glass, - // and will spawn using the same render FX or m_nRenderMode! bad! - SetRenderColorA( 255 ); - m_nRenderMode = kRenderNormal; - m_nRenderFX = kRenderFxNone; - - // hopefully this will fix the VELOCITY TOO LOW crap - m_takedamage = DAMAGE_EVENTS_ONLY; - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - - SetModel( szGibModel ); - -#ifdef HL1_DLL - SetElasticity( 1.0 ); - UTIL_SetSize( this, vec3_origin, vec3_origin ); -#endif//HL1_DLL - - SetNextThink( gpGlobals->curtime + 4 ); - m_lifeTime = 25; - SetTouch ( &CGib::BounceGibTouch ); - - m_bForceRemove = false; - - m_material = matNone; - m_cBloodDecals = 5;// how many blood decals this gib can place (1 per bounce until none remain). - -} - - -//----------------------------------------------------------------------------- -// Spawn a gib with a finite lifetime, after which it will fade out. -//----------------------------------------------------------------------------- -void CGib::Spawn( const char *szGibModel, float flLifetime ) -{ - Spawn( szGibModel ); - m_lifeTime = flLifetime; - SetThink ( &CGib::SUB_FadeOut ); - SetNextThink( gpGlobals->curtime + m_lifeTime ); -} - - -LINK_ENTITY_TO_CLASS( gib, CGib ); - -CBaseEntity *CreateRagGib( const char *szModel, const Vector &vecOrigin, const QAngle &vecAngles, const Vector &vecForce, float flFadeTime, bool bShouldIgnite ) -{ - CRagGib *pGib; - - pGib = (CRagGib*)CreateEntityByName( "raggib" ); - - pGib->SetLocalAngles( vecAngles ); - - if ( !pGib ) - { - Msg( "**Can't create ragdoll gib!\n" ); - return NULL; - } - - if ( bShouldIgnite ) - { - CBaseAnimating *pAnimating = pGib->GetBaseAnimating(); - if (pAnimating != NULL ) - { - pAnimating->Ignite( random->RandomFloat( 8.0, 12.0 ), false ); - } - } - - pGib->Spawn( szModel, vecOrigin, vecForce, flFadeTime ); - - return pGib; -} - -void CRagGib::Spawn( const char *szModel, const Vector &vecOrigin, const Vector &vecForce, float flFadeTime = 0.0 ) -{ - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_SOLID ); - SetModel( szModel ); - UTIL_SetSize(this, vec3_origin, vec3_origin); - UTIL_SetOrigin( this, vecOrigin ); - if ( !BecomeRagdollOnClient( vecForce ) ) - { - AddSolidFlags( FSOLID_NOT_STANDABLE ); - RemoveSolidFlags( FSOLID_NOT_SOLID ); - if( flFadeTime > 0.0 ) - { - SUB_StartFadeOut( flFadeTime ); - } - } -} - -LINK_ENTITY_TO_CLASS( raggib, CRagGib ); diff --git a/game/server/gib.h b/game/server/gib.h deleted file mode 100644 index f355e002f..000000000 --- a/game/server/gib.h +++ /dev/null @@ -1,115 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: A gib is a chunk of a body, or a piece of wood/metal/rocks/etc. -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef GIB_H -#define GIB_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "baseanimating.h" -#include "player_pickup.h" -#include "Sprite.h" - -extern CBaseEntity *CreateRagGib( const char *szModel, const Vector &vecOrigin, const QAngle &vecAngles, const Vector &vecForce, float flFadeTime = 0.0, bool bShouldIgnite = false ); - -#define GERMAN_GIB_COUNT 4 -#define HUMAN_GIB_COUNT 6 -#define ALIEN_GIB_COUNT 4 - -enum GibType_e -{ - GIB_HUMAN, - GIB_ALIEN, -}; - -class CGib : public CBaseAnimating, - public CDefaultPlayerPickupVPhysics -{ -public: - DECLARE_CLASS( CGib, CBaseAnimating ); - - void Spawn( const char *szGibModel ); - void Spawn( const char *szGibModel, float flLifetime ); - - void InitGib( CBaseEntity *pVictim, float fMaxVelocity, float fMinVelocity ); - void BounceGibTouch ( CBaseEntity *pOther ); - void StickyGibTouch ( CBaseEntity *pOther ); - void WaitTillLand( void ); - void DieThink( void ); - void LimitVelocity( void ); - virtual bool SUB_AllowedToFade( void ); - - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - virtual int ObjectCaps( void ) { return (BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | FCAP_DONT_SAVE | FCAP_IMPULSE_USE; } - static void SpawnHeadGib( CBaseEntity *pVictim ); - static void SpawnRandomGibs( CBaseEntity *pVictim, int cGibs, GibType_e eGibType ); - static void SpawnStickyGibs( CBaseEntity *pVictim, Vector vecOrigin, int cGibs ); - static void SpawnSpecificGibs( CBaseEntity *pVictim, int nNumGibs, float fMaxVelocity, float fMinVelocity, const char* cModelName, float flLifetime = 25); - - void SetPhysicsAttacker( CBasePlayer *pEntity, float flTime ); - virtual void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ); - virtual void OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t reason ); - virtual CBasePlayer *HasPhysicsAttacker( float dt ); - - void SetSprite( CBaseEntity *pSprite ) - { - m_hSprite = pSprite; - } - - CBaseEntity *GetSprite( void ) - { - return m_hSprite.Get(); - } - - void SetFlame( CBaseEntity *pFlame ) - { - m_hFlame = pFlame; - } - - CBaseEntity *GetFlame( void ) - { - return m_hFlame.Get(); - } - - DECLARE_DATADESC(); - - -public: - void SetBloodColor( int nBloodColor ); - - int m_cBloodDecals; - int m_material; - float m_lifeTime; - bool m_bForceRemove; - - CHandle m_hPhysicsAttacker; - float m_flLastPhysicsInfluenceTime; - -private: - // A little piece of duplicated code - void AdjustVelocityBasedOnHealth( int nHealth, Vector &vecVelocity ); - int m_bloodColor; - - EHANDLE m_hSprite; - EHANDLE m_hFlame; -}; - -class CRagGib : public CBaseAnimating -{ -public: - DECLARE_CLASS( CRagGib, CBaseAnimating ); - - void Spawn( const char *szModel, const Vector &vecOrigin, const Vector &vecForce, float flFadeTime ); -}; - - -#endif //GIB_H diff --git a/game/server/globals.cpp b/game/server/globals.cpp deleted file mode 100644 index a90cd49db..000000000 --- a/game/server/globals.cpp +++ /dev/null @@ -1,27 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -/* - -===== globals.cpp ======================================================== - - DLL-wide global variable definitions. - They're all defined here, for convenient centralization. - Source files that need them should "extern ..." declare each - variable, to better document what globals they care about. - -*/ - -#include "cbase.h" -#include "soundent.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -Vector g_vecAttackDir; -int g_iSkillLevel; -bool g_fGameOver; diff --git a/game/server/globals.h b/game/server/globals.h deleted file mode 100644 index 1ba742048..000000000 --- a/game/server/globals.h +++ /dev/null @@ -1,20 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef GLOBALS_H -#define GLOBALS_H -#ifdef _WIN32 -#pragma once -#endif - - -extern Vector g_vecAttackDir; -extern int g_iSkillLevel; -extern bool g_fGameOver; -extern ConVar g_Language; - - -#endif // GLOBALS_H diff --git a/game/server/globalstate.cpp b/game/server/globalstate.cpp deleted file mode 100644 index 2c06932bf..000000000 --- a/game/server/globalstate.cpp +++ /dev/null @@ -1,320 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "basetypes.h" -#include "saverestore.h" -#include "saverestore_utlvector.h" -#include "saverestore_utlsymbol.h" -#include "globalstate.h" -#include "igamesystem.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -struct globalentity_t -{ - DECLARE_SIMPLE_DATADESC(); - - CUtlSymbol name; - CUtlSymbol levelName; - GLOBALESTATE state; - int counter; -}; - - -class CGlobalState : public CAutoGameSystem -{ -public: - CGlobalState( char const *name ) : CAutoGameSystem( name ), m_disableStateUpdates(false) - { - } - - // IGameSystem - virtual void LevelShutdownPreEntity() - { - // don't allow state updates during shutdowns - Assert( !m_disableStateUpdates ); - m_disableStateUpdates = true; - } - - virtual void LevelShutdownPostEntity() - { - Assert( m_disableStateUpdates ); - m_disableStateUpdates = false; - } - - void EnableStateUpdates( bool bEnable ) - { - m_disableStateUpdates = !bEnable; - } - - void SetState( int globalIndex, GLOBALESTATE state ) - { - if ( m_disableStateUpdates || !m_list.IsValidIndex(globalIndex) ) - return; - m_list[globalIndex].state = state; - } - - GLOBALESTATE GetState( int globalIndex ) - { - if ( !m_list.IsValidIndex(globalIndex) ) - return GLOBAL_OFF; - return m_list[globalIndex].state; - } - - void SetCounter( int globalIndex, int counter ) - { - if ( m_disableStateUpdates || !m_list.IsValidIndex(globalIndex) ) - return; - m_list[globalIndex].counter = counter; - } - - int AddToCounter( int globalIndex, int delta ) - { - if ( m_disableStateUpdates || !m_list.IsValidIndex(globalIndex) ) - return 0; - return ( m_list[globalIndex].counter += delta ); - } - - int GetCounter( int globalIndex ) - { - if ( !m_list.IsValidIndex(globalIndex) ) - return 0; - return m_list[globalIndex].counter; - } - - void SetMap( int globalIndex, string_t mapname ) - { - if ( !m_list.IsValidIndex(globalIndex) ) - return; - m_list[globalIndex].levelName = m_nameList.AddString( STRING(mapname) ); - } - - const char *GetMap( int globalIndex ) - { - if ( !m_list.IsValidIndex(globalIndex) ) - return NULL; - return m_nameList.String( m_list[globalIndex].levelName ); - } - - const char *GetName( int globalIndex ) - { - if ( !m_list.IsValidIndex(globalIndex) ) - return NULL; - return m_nameList.String( m_list[globalIndex].name ); - } - - int GetIndex( const char *pGlobalname ) - { - CUtlSymbol symName = m_nameList.Find( pGlobalname ); - - if ( symName.IsValid() ) - { - for ( int i = m_list.Count() - 1; i >= 0; --i ) - { - if ( m_list[i].name == symName ) - return i; - } - } - - return -1; - } - - int AddEntity( const char *pGlobalname, const char *pMapName, GLOBALESTATE state ) - { - globalentity_t entity; - entity.name = m_nameList.AddString( pGlobalname ); - entity.levelName = m_nameList.AddString( pMapName ); - entity.state = state; - entity.counter = 0; - - int index = GetIndex( m_nameList.String( entity.name ) ); - if ( index >= 0 ) - return index; - return m_list.AddToTail( entity ); - } - - int GetNumGlobals( void ) - { - return m_list.Count(); - } - - void Reset( void ); - int Save( ISave &save ); - int Restore( IRestore &restore ); - DECLARE_SIMPLE_DATADESC(); - -//#ifdef _DEBUG - void DumpGlobals( void ); -//#endif - -public: - CUtlSymbolTable m_nameList; -private: - bool m_disableStateUpdates; - CUtlVector m_list; -}; - -static CGlobalState gGlobalState( "CGlobalState" ); - -static CUtlSymbolDataOps g_GlobalSymbolDataOps( gGlobalState.m_nameList ); - - -void GlobalEntity_SetState( int globalIndex, GLOBALESTATE state ) -{ - gGlobalState.SetState( globalIndex, state ); -} - -void GlobalEntity_SetCounter( int globalIndex, int counter ) -{ - gGlobalState.SetCounter( globalIndex, counter ); -} - -int GlobalEntity_AddToCounter( int globalIndex, int delta ) -{ - return gGlobalState.AddToCounter( globalIndex, delta ); -} - -void GlobalEntity_EnableStateUpdates( bool bEnable ) -{ - gGlobalState.EnableStateUpdates( bEnable ); -} - - -void GlobalEntity_SetMap( int globalIndex, string_t mapname ) -{ - gGlobalState.SetMap( globalIndex, mapname ); -} - -int GlobalEntity_Add( const char *pGlobalname, const char *pMapName, GLOBALESTATE state ) -{ - return gGlobalState.AddEntity( pGlobalname, pMapName, state ); -} - -int GlobalEntity_GetIndex( const char *pGlobalname ) -{ - return gGlobalState.GetIndex( pGlobalname ); -} - -GLOBALESTATE GlobalEntity_GetState( int globalIndex ) -{ - return gGlobalState.GetState( globalIndex ); -} - -int GlobalEntity_GetCounter( int globalIndex ) -{ - return gGlobalState.GetCounter( globalIndex ); -} - -const char *GlobalEntity_GetMap( int globalIndex ) -{ - return gGlobalState.GetMap( globalIndex ); -} - -const char *GlobalEntity_GetName( int globalIndex ) -{ - return gGlobalState.GetName( globalIndex ); -} - -int GlobalEntity_GetNumGlobals( void ) -{ - return gGlobalState.GetNumGlobals(); -} - -CON_COMMAND(dump_globals, "Dump all global entities/states") -{ - gGlobalState.DumpGlobals(); -} - -// This is available all the time now on impulse 104, remove later -//#ifdef _DEBUG -void CGlobalState::DumpGlobals( void ) -{ - static const char *estates[] = { "Off", "On", "Dead" }; - - Msg( "-- Globals --\n" ); - for ( int i = 0; i < m_list.Count(); i++ ) - { - Msg( "%s: %s (%s) = %d\n", m_nameList.String( m_list[i].name ), m_nameList.String( m_list[i].levelName ), estates[m_list[i].state], m_list[i].counter ); - } -} -//#endif - - -// Global state Savedata -BEGIN_SIMPLE_DATADESC( CGlobalState ) - DEFINE_UTLVECTOR( m_list, FIELD_EMBEDDED ), - // DEFINE_FIELD( m_nameList, CUtlSymbolTable ), - // DEFINE_FIELD( m_disableStateUpdates, FIELD_BOOLEAN ), -END_DATADESC() - -BEGIN_SIMPLE_DATADESC( globalentity_t ) - DEFINE_CUSTOM_FIELD( name, &g_GlobalSymbolDataOps ), - DEFINE_CUSTOM_FIELD( levelName, &g_GlobalSymbolDataOps ), - DEFINE_FIELD( state, FIELD_INTEGER ), - DEFINE_FIELD( counter, FIELD_INTEGER ), -END_DATADESC() - - -int CGlobalState::Save( ISave &save ) -{ - if ( !save.WriteFields( "GLOBAL", this, NULL, m_DataMap.dataDesc, m_DataMap.dataNumFields ) ) - return 0; - - return 1; -} - -int CGlobalState::Restore( IRestore &restore ) -{ - Reset(); - if ( !restore.ReadFields( "GLOBAL", this, NULL, m_DataMap.dataDesc, m_DataMap.dataNumFields ) ) - return 0; - - return 1; -} - -void CGlobalState::Reset( void ) -{ - m_list.Purge(); - m_nameList.RemoveAll(); -} - - -void SaveGlobalState( CSaveRestoreData *pSaveData ) -{ - CSave saveHelper( pSaveData ); - gGlobalState.Save( saveHelper ); -} - - -void RestoreGlobalState( CSaveRestoreData *pSaveData ) -{ - CRestore restoreHelper( pSaveData ); - gGlobalState.Restore( restoreHelper ); -} - - -//----------------------------------------------------------------------------- -// Purpose: This gets called when a level is shut down -//----------------------------------------------------------------------------- - -void ResetGlobalState( void ) -{ - gGlobalState.Reset(); -} - - -void ShowServerGameTime() -{ - Msg( "Server game time: %f\n", gpGlobals->curtime ); -} - -CON_COMMAND(server_game_time, "Gives the game time in seconds (server's curtime)") -{ - ShowServerGameTime(); -} diff --git a/game/server/globalstate.h b/game/server/globalstate.h deleted file mode 100644 index f244cd05d..000000000 --- a/game/server/globalstate.h +++ /dev/null @@ -1,109 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef GLOBALSTATE_H -#define GLOBALSTATE_H -#ifdef _WIN32 -#pragma once -#endif - -typedef enum { GLOBAL_OFF = 0, GLOBAL_ON = 1, GLOBAL_DEAD = 2 } GLOBALESTATE; - -void GlobalEntity_SetState( int globalIndex, GLOBALESTATE state ); -void GlobalEntity_SetMap( int globalIndex, string_t mapname ); -int GlobalEntity_Add( const char *pGlobalname, const char *pMapName, GLOBALESTATE state ); - -int GlobalEntity_GetIndex( const char *pGlobalname ); -GLOBALESTATE GlobalEntity_GetState( int globalIndex ); -const char *GlobalEntity_GetMap( int globalIndex ); -const char *GlobalEntity_GetName( int globalIndex ); - -int GlobalEntity_GetCounter( int globalIndex ); -void GlobalEntity_SetCounter( int globalIndex, int counter ); -int GlobalEntity_AddToCounter( int globalIndex, int delta ); - -int GlobalEntity_GetNumGlobals( void ); -void GlobalEntity_EnableStateUpdates( bool bEnable ); - -inline int GlobalEntity_Add( string_t globalname, string_t mapName, GLOBALESTATE state ) -{ - return GlobalEntity_Add( STRING(globalname), STRING(mapName), state ); -} - -inline int GlobalEntity_GetIndex( string_t globalname ) -{ - return GlobalEntity_GetIndex( STRING(globalname) ); -} - -inline int GlobalEntity_IsInTable( string_t globalname ) -{ - return GlobalEntity_GetIndex( STRING(globalname) ) >= 0 ? true : false; -} - -inline int GlobalEntity_IsInTable( const char *pGlobalname ) -{ - return GlobalEntity_GetIndex( pGlobalname ) >= 0 ? true : false; -} - -inline void GlobalEntity_SetState( string_t globalname, GLOBALESTATE state ) -{ - GlobalEntity_SetState( GlobalEntity_GetIndex( globalname ), state ); -} - -inline void GlobalEntity_SetMap( string_t globalname, string_t mapname ) -{ - GlobalEntity_SetMap( GlobalEntity_GetIndex( globalname ), mapname ); -} - -inline GLOBALESTATE GlobalEntity_GetState( string_t globalname ) -{ - return GlobalEntity_GetState( GlobalEntity_GetIndex( globalname ) ); -} - -inline GLOBALESTATE GlobalEntity_GetState( const char *pGlobalName ) -{ - return GlobalEntity_GetState( GlobalEntity_GetIndex( pGlobalName ) ); -} - -inline int GlobalEntity_GetCounter( string_t globalname ) -{ - return GlobalEntity_GetCounter( GlobalEntity_GetIndex( globalname ) ); -} - -inline int GlobalEntity_GetCounter( const char *pGlobalName ) -{ - return GlobalEntity_GetCounter( GlobalEntity_GetIndex( pGlobalName ) ); -} - -inline void GlobalEntity_SetCounter( string_t globalname, int counter ) -{ - GlobalEntity_SetCounter( GlobalEntity_GetIndex( globalname ), counter ); -} - -inline void GlobalEntity_SetCounter( const char *pGlobalName, int counter ) -{ - GlobalEntity_SetCounter( GlobalEntity_GetIndex( pGlobalName ), counter ); -} - -inline int GlobalEntity_AddToCounter( string_t globalname, int delta ) -{ - return GlobalEntity_AddToCounter( GlobalEntity_GetIndex( globalname ), delta ); -} - -inline int GlobalEntity_AddToCounter( const char *pGlobalName, int delta ) -{ - return GlobalEntity_AddToCounter( GlobalEntity_GetIndex( pGlobalName ), delta ); -} - -inline GLOBALESTATE GlobalEntity_GetStateByIndex( int iIndex ) -{ - return GlobalEntity_GetState( iIndex ); -} - -void ResetGlobalState( void ); - -#endif // GLOBALSTATE_H diff --git a/game/server/globalstate_private.h b/game/server/globalstate_private.h deleted file mode 100644 index 347081cdc..000000000 --- a/game/server/globalstate_private.h +++ /dev/null @@ -1,15 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef GLOBALSTATE_PRIVATE_H -#define GLOBALSTATE_PRIVATE_H -#ifdef _WIN32 -#pragma once -#endif - - -#endif // GLOBALSTATE_PRIVATE_H diff --git a/game/server/grenadethrown.cpp b/game/server/grenadethrown.cpp deleted file mode 100644 index 0507a3688..000000000 --- a/game/server/grenadethrown.cpp +++ /dev/null @@ -1,81 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -/* - -===== grenade_base.cpp ======================================================== - - Base Handling for all the player's grenades - -*/ -#include "cbase.h" -#include "grenadethrown.h" -#include "ammodef.h" -#include "vstdlib/random.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// Precaches a grenade and ensures clients know of it's "ammo" -void UTIL_PrecacheOtherGrenade( const char *szClassname ) -{ - CBaseEntity *pEntity = CreateEntityByName( szClassname ); - if ( !pEntity ) - { - Msg( "NULL Ent in UTIL_PrecacheOtherGrenade\n" ); - return; - } - - CThrownGrenade *pGrenade = dynamic_cast( pEntity ); - - if (pGrenade) - { - pGrenade->Precache( ); - } - - UTIL_Remove( pEntity ); -} - -//----------------------------------------------------------------------------- -// Purpose: Setup basic values for Thrown grens -//----------------------------------------------------------------------------- -void CThrownGrenade::Spawn( void ) -{ - // point sized, solid, bouncing - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); - SetSolid( SOLID_BBOX ); - UTIL_SetSize(this, vec3_origin, vec3_origin); - - // Movement - SetGravity( UTIL_ScaleForGravity( 648 ) ); - SetFriction(0.6); - QAngle angles; - VectorAngles( GetAbsVelocity(), angles ); - SetLocalAngles( angles ); - QAngle vecAngVel( random->RandomFloat ( -100, -500 ), 0, 0 ); - SetLocalAngularVelocity( vecAngVel ); - - SetTouch( &CThrownGrenade::BounceTouch ); -} - -//----------------------------------------------------------------------------- -// Purpose: Throw the grenade. -// Input : vecOrigin - Starting position -// vecVelocity - Starting velocity -// flExplodeTime - Time at which to detonate -//----------------------------------------------------------------------------- -void CThrownGrenade::Thrown( Vector vecOrigin, Vector vecVelocity, float flExplodeTime ) -{ - // Throw - SetLocalOrigin( vecOrigin ); - SetAbsVelocity( vecVelocity ); - - // Explode in 3 seconds - SetThink( &CThrownGrenade::Detonate ); - SetNextThink( gpGlobals->curtime + flExplodeTime ); -} - diff --git a/game/server/grenadethrown.h b/game/server/grenadethrown.h deleted file mode 100644 index 577c3ccae..000000000 --- a/game/server/grenadethrown.h +++ /dev/null @@ -1,38 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Header file for player-thrown grenades. -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef GRENADE_BASE_H -#define GRENADE_BASE_H -#pragma once - -#include "basegrenade_shared.h" - -class CSprite; - -#define GRENADE_TIMER 5 // Try 5 seconds instead of 3? - -//----------------------------------------------------------------------------- -// Purpose: Base Thrown-Grenade class -//----------------------------------------------------------------------------- -class CThrownGrenade : public CBaseGrenade -{ -public: - DECLARE_CLASS( CThrownGrenade, CBaseGrenade ); - - void Spawn( void ); - void Thrown( Vector vecOrigin, Vector vecVelocity, float flExplodeTime ); -}; - - - -#endif // GRENADE_BASE_H diff --git a/game/server/guntarget.cpp b/game/server/guntarget.cpp deleted file mode 100644 index d5057e071..000000000 --- a/game/server/guntarget.cpp +++ /dev/null @@ -1,255 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements a moving target that moves along a path of path_tracks -// and can be shot and killed. When the target it killed it fires an -// OnDeath output. -// -// m_flSpeed is the travel speed -// m_iHealth is current health -// m_iMaxHealth is the amount to reset to each time it starts -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "entityoutput.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define FGUNTARGET_START_ON 0x0001 - - -class CGunTarget : public CBaseToggle -{ - DECLARE_CLASS( CGunTarget, CBaseToggle ); - -public: - - virtual void Spawn( void ); - virtual void Activate( void ); - bool CreateVPhysics( void ); - - virtual int BloodColor( void ) { return DONT_BLEED; } - -#if defined( HL2_DLL ) - virtual Class_T Classify( void ) { return CLASS_MILITARY; } -#elif defined( HL1_DLL ) - virtual Class_T Classify( void ) { return CLASS_MACHINE; } -#else - virtual Class_T Classify( void ) { return CLASS_NONE; } -#endif - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true ) { return GetAbsOrigin(); } - - // Input handlers - void InputStart( inputdata_t &inputdata ); - void InputStop( inputdata_t &inputdata ); - void InputToggle( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - -protected: - - void Next( void ); - void Start( void ); - void Wait( void ); - void Stop( void ); - -private: - - bool m_on; - EHANDLE m_hTargetEnt; - - // Outputs - COutputEvent m_OnDeath; -}; - - -LINK_ENTITY_TO_CLASS( func_guntarget, CGunTarget ); - -BEGIN_DATADESC( CGunTarget ) - - DEFINE_FIELD( m_on, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hTargetEnt, FIELD_EHANDLE ), - - // Function Pointers - DEFINE_FUNCTION( Next ), - DEFINE_FUNCTION( Start ), - DEFINE_FUNCTION( Wait ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Start", InputStart ), - DEFINE_INPUTFUNC( FIELD_VOID, "Stop", InputStop ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - - // Outputs - DEFINE_OUTPUT(m_OnDeath, "OnDeath"), - -END_DATADESC() - - - -void CGunTarget::Spawn( void ) -{ - SetSolid( SOLID_BSP ); - SetMoveType( MOVETYPE_PUSH ); - - SetModel( STRING( GetModelName() ) ); - - if ( m_flSpeed == 0 ) - m_flSpeed = 100; - - // Don't take damage until "on" - m_takedamage = DAMAGE_NO; - AddFlag( FL_NPC ); - - m_on = false; - m_iMaxHealth = m_iHealth; - - if ( HasSpawnFlags(FGUNTARGET_START_ON) ) - { - SetMoveDone( &CGunTarget::Start ); - SetMoveDoneTime( 0.3 ); - } - CreateVPhysics(); -} - - -bool CGunTarget::CreateVPhysics( void ) -{ - VPhysicsInitShadow( false, false ); - return true; -} - -void CGunTarget::Activate( void ) -{ - BaseClass::Activate(); - - CBaseEntity *pTarg; - // now find our next target - pTarg = GetNextTarget(); - if ( pTarg ) - { - m_hTargetEnt = pTarg; - Vector nextPos = pTarg->GetAbsOrigin(); - Teleport( &nextPos, NULL, NULL ); - } -} - - -void CGunTarget::Start( void ) -{ - m_takedamage = DAMAGE_YES; - AddFlag( FL_AIMTARGET ); - m_hTargetEnt = GetNextTarget(); - if ( m_hTargetEnt == NULL ) - return; - m_iHealth = m_iMaxHealth; - Next(); -} - - -void CGunTarget::Next( void ) -{ - SetThink( NULL ); - - m_hTargetEnt = GetNextTarget(); - CBaseEntity *pTarget = m_hTargetEnt; - - if ( !pTarget ) - { - Stop(); - return; - } - - SetMoveDone( &CGunTarget::Wait ); - LinearMove( pTarget->GetLocalOrigin(), m_flSpeed ); -} - - -void CGunTarget::Wait( void ) -{ - CBaseEntity *pTarget = m_hTargetEnt; - - if ( !pTarget ) - { - Stop(); - return; - } - - variant_t emptyVariant; - pTarget->AcceptInput( "InPass", this, this, emptyVariant, 0 ); - - m_flWait = pTarget->GetDelay(); - - m_target = pTarget->m_target; - SetMoveDone( &CGunTarget::Next ); - if (m_flWait != 0) - {// -1 wait will wait forever! - SetMoveDoneTime( m_flWait ); - } - else - { - Next();// do it RIGHT now! - } -} - - -void CGunTarget::Stop( void ) -{ - SetAbsVelocity( vec3_origin ); - SetMoveDoneTime( -1 ); - m_takedamage = DAMAGE_NO; -} - - -int CGunTarget::OnTakeDamage( const CTakeDamageInfo &info ) -{ - if ( m_iHealth > 0 ) - { - m_iHealth -= info.GetDamage(); - if ( m_iHealth <= 0 ) - { - m_iHealth = 0; - Stop(); - - m_OnDeath.FireOutput( info.GetInflictor(), this ); - } - } - return 0; -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that starts the target moving. -//----------------------------------------------------------------------------- -void CGunTarget::InputStart( inputdata_t &inputdata ) -{ - Start(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that stops the target from moving. -//----------------------------------------------------------------------------- -void CGunTarget::InputStop( inputdata_t &inputdata ) -{ - Stop(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that toggles the start/stop state of the target. -//----------------------------------------------------------------------------- -void CGunTarget::InputToggle( inputdata_t &inputdata ) -{ - if ( m_on ) - { - Stop(); - } - else - { - Start(); - } -} diff --git a/game/server/h_ai.cpp b/game/server/h_ai.cpp deleted file mode 100644 index 7c1211be7..000000000 --- a/game/server/h_ai.cpp +++ /dev/null @@ -1,266 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Utility functions used by AI code. -// -//=============================================================================// - -#include "cbase.h" -#include "game.h" -#include "vstdlib/random.h" -#include "movevars_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define NUM_LATERAL_CHECKS 13 // how many checks are made on each side of a NPC looking for lateral cover -#define NUM_LATERAL_LOS_CHECKS 6 // how many checks are made on each side of a NPC looking for lateral cover - -#define TOSS_HEIGHT_MAX 300 // altitude of initial trace done to see how high something can be tossed - -//float flRandom = random->RandomFloat(0,1); - -bool g_fDrawLines = FALSE; - - -//========================================================= -// FBoxVisible - a more accurate ( and slower ) version -// of FVisible. -// -// !!!UNDONE - make this CAI_BaseNPC? -//========================================================= -bool FBoxVisible( CBaseEntity *pLooker, CBaseEntity *pTarget, Vector &vecTargetOrigin, float flSize ) -{ - // don't look through water - if ((pLooker->GetWaterLevel() != 3 && pTarget->GetWaterLevel() == 3) - || (pLooker->GetWaterLevel() == 3 && pTarget->GetWaterLevel() == 0)) - return FALSE; - - trace_t tr; - Vector vecLookerOrigin = pLooker->EyePosition();//look through the NPC's 'eyes' - for (int i = 0; i < 5; i++) - { - Vector vecTarget = pTarget->GetAbsOrigin(); - vecTarget.x += random->RandomFloat( pTarget->WorldAlignMins().x + flSize, pTarget->WorldAlignMaxs().x - flSize); - vecTarget.y += random->RandomFloat( pTarget->WorldAlignMins().y + flSize, pTarget->WorldAlignMaxs().y - flSize); - vecTarget.z += random->RandomFloat( pTarget->WorldAlignMins().z + flSize, pTarget->WorldAlignMaxs().z - flSize); - - UTIL_TraceLine(vecLookerOrigin, vecTarget, MASK_BLOCKLOS, pLooker, COLLISION_GROUP_NONE, &tr); - - if (tr.fraction == 1.0) - { - vecTargetOrigin = vecTarget; - return TRUE;// line of sight is valid. - } - } - return FALSE;// Line of sight is not established -} - - - -//----------------------------------------------------------------------------- -// Purpose: Returns the correct toss velocity to throw a given object at a point. -// Like the other version of VecCheckToss, but allows you to filter for any -// number of entities to ignore. -// Input : pEntity - The object doing the throwing. Is *NOT* automatically included in the -// filter below. -// pFilter - A trace filter of entities to ignore in the object's collision sweeps. -// It is recommended to include at least the thrower. -// vecSpot1 - The point from which the object is being thrown. -// vecSpot2 - The point TO which the object is being thrown. -// flHeightMaxRatio - A scale factor indicating the maximum ratio of height -// to total throw distance, measured from the higher of the two endpoints to -// the apex. -1 indicates that there is no maximum. -// flGravityAdj - Scale factor for gravity - should match the gravity scale -// that the object will use in midair. -// bRandomize - when true, introduces a little fudge to the throw -// Output : Velocity to throw the object with. -//----------------------------------------------------------------------------- -Vector VecCheckToss( CBaseEntity *pEntity, ITraceFilter *pFilter, Vector vecSpot1, Vector vecSpot2, float flHeightMaxRatio, float flGravityAdj, bool bRandomize, Vector *vecMins, Vector *vecMaxs ) -{ - trace_t tr; - Vector vecMidPoint;// halfway point between Spot1 and Spot2 - Vector vecApex;// highest point - Vector vecScale; - Vector vecTossVel; - Vector vecTemp; - float flGravity = sv_gravity.GetFloat() * flGravityAdj; - - if (vecSpot2.z - vecSpot1.z > 500) - { - // to high, fail - return vec3_origin; - } - - Vector forward, right; - AngleVectors( pEntity->GetLocalAngles(), &forward, &right, NULL ); - - if (bRandomize) - { - // toss a little bit to the left or right, not right down on the enemy's bean (head). - vecSpot2 += right * ( random->RandomFloat(-8,8) + random->RandomFloat(-16,16) ); - vecSpot2 += forward * ( random->RandomFloat(-8,8) + random->RandomFloat(-16,16) ); - } - - // calculate the midpoint and apex of the 'triangle' - // UNDONE: normalize any Z position differences between spot1 and spot2 so that triangle is always RIGHT - // get a rough idea of how high it can be thrown - vecMidPoint = vecSpot1 + (vecSpot2 - vecSpot1) * 0.5; - UTIL_TraceLine(vecMidPoint, vecMidPoint + Vector(0,0,TOSS_HEIGHT_MAX), MASK_SOLID_BRUSHONLY, pFilter, &tr); - vecMidPoint = tr.endpos; - - if( tr.fraction != 1.0 ) - { - // (subtract 15 so the object doesn't hit the ceiling) - vecMidPoint.z -= 15; - } - - if (flHeightMaxRatio != -1) - { - // But don't throw so high that it looks silly. Maximize the height of the - // throw above the highest of the two endpoints to a ratio of the throw length. - float flHeightMax = flHeightMaxRatio * (vecSpot2 - vecSpot1).Length(); - float flHighestEndZ = MAX(vecSpot1.z, vecSpot2.z); - if ((vecMidPoint.z - flHighestEndZ) > flHeightMax) - { - vecMidPoint.z = flHighestEndZ + flHeightMax; - } - } - - if (vecMidPoint.z < vecSpot1.z || vecMidPoint.z < vecSpot2.z) - { - // Not enough space, fail - return vec3_origin; - } - - // How high should the object travel to reach the apex - float distance1 = (vecMidPoint.z - vecSpot1.z); - float distance2 = (vecMidPoint.z - vecSpot2.z); - - // How long will it take for the object to travel this distance - float time1 = sqrt( distance1 / (0.5 * flGravity) ); - float time2 = sqrt( distance2 / (0.5 * flGravity) ); - - if (time1 < 0.1) - { - // too close - return vec3_origin; - } - - // how hard to throw sideways to get there in time. - vecTossVel = (vecSpot2 - vecSpot1) / (time1 + time2); - - // how hard upwards to reach the apex at the right time. - vecTossVel.z = flGravity * time1; - - // find the apex - vecApex = vecSpot1 + vecTossVel * time1; - vecApex.z = vecMidPoint.z; - - // JAY: Repro behavior from HL1 -- toss check went through gratings - UTIL_TraceLine(vecSpot1, vecApex, (MASK_SOLID&(~CONTENTS_GRATE)), pFilter, &tr); - if (tr.fraction != 1.0) - { - // fail! - return vec3_origin; - } - - // UNDONE: either ignore NPCs or change it to not care if we hit our enemy - UTIL_TraceLine(vecSpot2, vecApex, (MASK_SOLID_BRUSHONLY&(~CONTENTS_GRATE)), pFilter, &tr); - if (tr.fraction != 1.0) - { - // fail! - return vec3_origin; - } - - if ( vecMins && vecMaxs ) - { - // Check to ensure the entity's hull can travel the first half of the grenade throw - UTIL_TraceHull( vecSpot1, vecApex, *vecMins, *vecMaxs, (MASK_SOLID&(~CONTENTS_GRATE)), pFilter, &tr); - if ( tr.fraction < 1.0 ) - return vec3_origin; - } - - return vecTossVel; -} - - - -//----------------------------------------------------------------------------- -// Purpose: Returns the correct toss velocity to throw a given object at a point. -// Input : pEntity - The entity that is throwing the object. -// vecSpot1 - The point from which the object is being thrown. -// vecSpot2 - The point TO which the object is being thrown. -// flHeightMaxRatio - A scale factor indicating the maximum ratio of height -// to total throw distance, measured from the higher of the two endpoints to -// the apex. -1 indicates that there is no maximum. -// flGravityAdj - Scale factor for gravity - should match the gravity scale -// that the object will use in midair. -// bRandomize - when true, introduces a little fudge to the throw -// Output : Velocity to throw the object with. -//----------------------------------------------------------------------------- -Vector VecCheckToss( CBaseEntity *pEntity, Vector vecSpot1, Vector vecSpot2, float flHeightMaxRatio, float flGravityAdj, bool bRandomize, Vector *vecMins, Vector *vecMaxs ) -{ - // construct a filter and call through to the other version of this function. - CTraceFilterSimple traceFilter( pEntity, COLLISION_GROUP_NONE ); - return VecCheckToss( pEntity, &traceFilter, vecSpot1, vecSpot2, - flHeightMaxRatio, flGravityAdj, bRandomize, - vecMins, vecMaxs ); -} - -// -// VecCheckThrow - returns the velocity vector at which an object should be thrown from vecspot1 to hit vecspot2. -// returns vec3_origin if throw is not feasible. -// -Vector VecCheckThrow ( CBaseEntity *pEdict, const Vector &vecSpot1, Vector vecSpot2, float flSpeed, float flGravityAdj, Vector *vecMins, Vector *vecMaxs ) -{ - float flGravity = sv_gravity.GetFloat() * flGravityAdj; - - Vector vecGrenadeVel = (vecSpot2 - vecSpot1); - - // throw at a constant time - float time = vecGrenadeVel.Length( ) / flSpeed; - vecGrenadeVel = vecGrenadeVel * (1.0 / time); - - // adjust upward toss to compensate for gravity loss - vecGrenadeVel.z += flGravity * time * 0.5; - - Vector vecApex = vecSpot1 + (vecSpot2 - vecSpot1) * 0.5; - vecApex.z += 0.5 * flGravity * (time * 0.5) * (time * 0.5); - - - trace_t tr; - UTIL_TraceLine(vecSpot1, vecApex, MASK_SOLID, pEdict, COLLISION_GROUP_NONE, &tr); - if (tr.fraction != 1.0) - { - // fail! - //NDebugOverlay::Line( vecSpot1, vecApex, 255, 0, 0, true, 5.0 ); - return vec3_origin; - } - - //NDebugOverlay::Line( vecSpot1, vecApex, 0, 255, 0, true, 5.0 ); - - UTIL_TraceLine(vecSpot2, vecApex, MASK_SOLID_BRUSHONLY, pEdict, COLLISION_GROUP_NONE, &tr); - if (tr.fraction != 1.0) - { - // fail! - //NDebugOverlay::Line( vecApex, vecSpot2, 255, 0, 0, true, 5.0 ); - return vec3_origin; - } - - //NDebugOverlay::Line( vecApex, vecSpot2, 0, 255, 0, true, 5.0 ); - - if ( vecMins && vecMaxs ) - { - // Check to ensure the entity's hull can travel the first half of the grenade throw - UTIL_TraceHull( vecSpot1, vecApex, *vecMins, *vecMaxs, MASK_SOLID, pEdict, COLLISION_GROUP_NONE, &tr); - if ( tr.fraction < 1.0 ) - { - //NDebugOverlay::SweptBox( vecSpot1, tr.endpos, *vecMins, *vecMaxs, vec3_angle, 255, 0, 0, 64, 5.0 ); - return vec3_origin; - } - } - - //NDebugOverlay::SweptBox( vecSpot1, vecApex, *vecMins, *vecMaxs, vec3_angle, 0, 255, 0, 64, 5.0 ); - - return vecGrenadeVel; -} diff --git a/game/server/h_cycler.cpp b/game/server/h_cycler.cpp deleted file mode 100644 index 519371016..000000000 --- a/game/server/h_cycler.cpp +++ /dev/null @@ -1,518 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: The Halflife Cycler NPCs -// -//=============================================================================// - -#include "cbase.h" -#include "ai_basenpc.h" -#include "ai_motor.h" -#include "basecombatweapon.h" -#include "animation.h" -#include "vstdlib/random.h" -#include "h_cycler.h" -#include "Sprite.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define FCYCLER_NOTSOLID 0x0001 - -extern short g_sModelIndexSmoke; // (in combatweapon.cpp) holds the index for the smoke cloud - -BEGIN_DATADESC( CCycler ) - - // Fields - DEFINE_FIELD( m_animate, FIELD_INTEGER ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_STRING, "SetSequence", InputSetSequence ), - -END_DATADESC() - -// -// we should get rid of all the other cyclers and replace them with this. -// -class CGenericCycler : public CCycler -{ -public: - DECLARE_CLASS( CGenericCycler, CCycler ); - - void Spawn() - { - GenericCyclerSpawn( (char *)STRING( GetModelName() ), Vector(-16, -16, 0), Vector(16, 16, 72) ); - } -}; -LINK_ENTITY_TO_CLASS( cycler, CGenericCycler ); -LINK_ENTITY_TO_CLASS( model_studio, CGenericCycler ); // For now model_studios build as cyclers. - - -// Cycler member functions - -void CCycler::GenericCyclerSpawn(char *szModel, Vector vecMin, Vector vecMax) -{ - if (!szModel || !*szModel) - { - Warning( "cycler at %.0f %.0f %0.f missing modelname\n", GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z ); - UTIL_Remove( this ); - return; - } - - Precache(); - - SetModel( szModel ); - - m_bloodColor = DONT_BLEED; - - CCycler::Spawn( ); - - UTIL_SetSize(this, vecMin, vecMax); -} - - -void CCycler::Precache() -{ - PrecacheModel( (const char *)STRING( GetModelName() ) ); -} - - -void CCycler::Spawn( ) -{ - InitBoneControllers(); - - SetSolid( SOLID_BBOX ); - if ( m_spawnflags & FCYCLER_NOTSOLID ) - { - AddSolidFlags( FSOLID_NOT_SOLID ); - } - else - { - AddSolidFlags( FSOLID_NOT_STANDABLE ); - } - - SetMoveType( MOVETYPE_NONE ); - m_takedamage = DAMAGE_YES; - m_iHealth = 80000;// no cycler should die - GetMotor()->SetIdealYaw( GetLocalAngles().y ); - GetMotor()->SnapYaw(); - - m_flPlaybackRate = 1.0; - m_flGroundSpeed = 0; - - SetNextThink( gpGlobals->curtime + 1.0f ); - - ResetSequenceInfo( ); - - if (GetSequence() != 0 || m_flCycle != 0) - { -#ifdef TF2_DLL - m_animate = 1; -#else - m_animate = 0; - m_flPlaybackRate = 0; -#endif - } - else - { - m_animate = 1; - } -} - - - - -// -// cycler think -// -void CCycler::Think( void ) -{ - SetNextThink( gpGlobals->curtime + 0.1f ); - - if (m_animate) - { - StudioFrameAdvance ( ); - DispatchAnimEvents( this ); - } - if (IsSequenceFinished() && !SequenceLoops()) - { - // ResetSequenceInfo(); - // hack to avoid reloading model every frame - m_flAnimTime = gpGlobals->curtime; - m_flPlaybackRate = 1.0; - m_bSequenceFinished = false; - m_flLastEventCheck = 0; - m_flCycle = 0; - if (!m_animate) - m_flPlaybackRate = 0.0; // FIX: don't reset framerate - } -} - -// -// CyclerUse - starts a rotation trend -// -void CCycler::Use ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - m_animate = !m_animate; - if (m_animate) - m_flPlaybackRate = 1.0; - else - m_flPlaybackRate = 0.0; -} - -//----------------------------------------------------------------------------- -// Purpose: Changes sequences when hurt. -//----------------------------------------------------------------------------- -int CCycler::OnTakeDamage( const CTakeDamageInfo &info ) -{ - if (m_animate) - { - int nSequence = GetSequence() + 1; - if ( !IsValidSequence(nSequence) ) - { - nSequence = 0; - } - - ResetSequence( nSequence ); - m_flCycle = 0; - } - else - { - m_flPlaybackRate = 1.0; - StudioFrameAdvance (); - m_flPlaybackRate = 0; - Msg( "sequence: %d, frame %.0f\n", GetSequence(), m_flCycle ); - } - - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: Input that sets the sequence of the cycler -//----------------------------------------------------------------------------- -void CCycler::InputSetSequence( inputdata_t &inputdata ) -{ - if (m_animate) - { - // Legacy support: Try it as a number, and support '0' - const char *sChar = inputdata.value.String(); - int iSeqNum = atoi( sChar ); - if ( !iSeqNum && sChar[0] != '0' ) - { - // Treat it as a sequence name - ResetSequence( LookupSequence( sChar ) ); - } - else - { - ResetSequence( iSeqNum ); - } - - if (m_flPlaybackRate == 0.0) - { - ResetSequence( 0 ); - } - - m_flCycle = 0; - } -} - -// FIXME: this doesn't work anymore, and hasn't for a while now. - -class CWeaponCycler : public CBaseCombatWeapon -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( CWeaponCycler, CBaseCombatWeapon ); - - DECLARE_SERVERCLASS(); - - void Spawn( void ); - - void PrimaryAttack( void ); - void SecondaryAttack( void ); - bool Deploy( void ); - bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); - string_t m_iszModel; - int m_iModel; -}; - -IMPLEMENT_SERVERCLASS_ST(CWeaponCycler, DT_WeaponCycler) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( cycler_weapon, CWeaponCycler ); - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CWeaponCycler ) - - DEFINE_FIELD( m_iszModel, FIELD_STRING ), - DEFINE_FIELD( m_iModel, FIELD_INTEGER ), - -END_DATADESC() - -void CWeaponCycler::Spawn( ) -{ - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_NONE ); - - PrecacheModel( STRING( GetModelName() ) ); - SetModel( STRING( GetModelName() ) ); - m_iszModel = GetModelName(); - m_iModel = GetModelIndex(); - - UTIL_SetSize(this, Vector(-16, -16, 0), Vector(16, 16, 16)); - SetTouch( &CWeaponCycler::DefaultTouch ); -} - - - -bool CWeaponCycler::Deploy( ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - - if (pOwner) - { - pOwner->m_flNextAttack = gpGlobals->curtime + 1.0; - SendWeaponAnim( 0 ); - m_iClip1 = 0; - m_iClip2 = 0; - return true; - } - return false; -} - - -bool CWeaponCycler::Holster( CBaseCombatWeapon *pSwitchingTo ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - if (pOwner) - { - pOwner->m_flNextAttack = gpGlobals->curtime + 0.5; - } - - return true; -} - - -void CWeaponCycler::PrimaryAttack() -{ - SendWeaponAnim( GetSequence() ); - m_flNextPrimaryAttack = gpGlobals->curtime + 0.3; -} - - -void CWeaponCycler::SecondaryAttack( void ) -{ - float flFrameRate; - - int nSequence = (GetSequence() + 1) % 8; - - // BUG: Why do we set this here and then set to zero right after? - SetModelIndex( m_iModel ); - flFrameRate = 0.0; - - SetModelIndex( 0 ); - - if (flFrameRate == 0.0) - { - nSequence = 0; - } - - SetSequence( nSequence ); - SendWeaponAnim( nSequence ); - - m_flNextSecondaryAttack = gpGlobals->curtime + 0.3; -} - - - -// Flaming Wreakage -class CWreckage : public CAI_BaseNPC -{ -public: - DECLARE_CLASS( CWreckage, CAI_BaseNPC ); - - DECLARE_DATADESC(); - - void Spawn( void ); - void Precache( void ); - void Think( void ); - - float m_flStartTime; - float m_flDieTime; -}; - -BEGIN_DATADESC( CWreckage ) - - DEFINE_FIELD( m_flStartTime, FIELD_TIME ), - DEFINE_FIELD( m_flDieTime, FIELD_TIME ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( cycler_wreckage, CWreckage ); - -void CWreckage::Spawn( void ) -{ - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NONE ); - m_takedamage = 0; - - SetCycle( 0 ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - if (GetModelName() != NULL_STRING) - { - PrecacheModel( STRING( GetModelName() ) ); - SetModel( STRING( GetModelName() ) ); - } - - m_flStartTime = gpGlobals->curtime; -} - -void CWreckage::Precache( ) -{ - if ( GetModelName() != NULL_STRING ) - PrecacheModel( STRING( GetModelName() ) ); -} - -void CWreckage::Think( void ) -{ - StudioFrameAdvance( ); - SetNextThink( gpGlobals->curtime + 0.2 ); - - if (m_flDieTime) - { - if (m_flDieTime < gpGlobals->curtime) - { - UTIL_Remove( this ); - return; - } - else if (random->RandomFloat( 0, m_flDieTime - m_flStartTime ) > m_flDieTime - gpGlobals->curtime) - { - return; - } - } - - Vector vecSrc; - CollisionProp()->RandomPointInBounds( vec3_origin, Vector(1, 1, 1), &vecSrc ); - CPVSFilter filter( vecSrc ); - te->Smoke( filter, 0.0, - &vecSrc, g_sModelIndexSmoke, - random->RandomFloat(0,4.9) + 5.0, - random->RandomInt(0, 3) + 8 ); -} - -// BlendingCycler -// Used to demonstrate animation blending -class CBlendingCycler : public CCycler -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( CBlendingCycler, CCycler ); - - void Spawn( void ); - bool KeyValue( const char *szKeyName, const char *szValue ); - void Think( void ); - virtual int ObjectCaps( void ) { return (BaseClass::ObjectCaps() | FCAP_DONT_SAVE | FCAP_IMPULSE_USE); } - - int m_iLowerBound; - int m_iUpperBound; - int m_iCurrent; - int m_iBlendspeed; - string_t m_iszSequence; -}; -LINK_ENTITY_TO_CLASS( cycler_blender, CBlendingCycler ); - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CBlendingCycler ) - - DEFINE_FIELD( m_iLowerBound, FIELD_INTEGER ), - DEFINE_FIELD( m_iUpperBound, FIELD_INTEGER ), - DEFINE_FIELD( m_iCurrent, FIELD_INTEGER ), - DEFINE_FIELD( m_iBlendspeed, FIELD_INTEGER ), - DEFINE_FIELD( m_iszSequence, FIELD_STRING ), - -END_DATADESC() - -void CBlendingCycler::Spawn( void ) -{ - // Remove if it's not blending - if (m_iLowerBound == 0 && m_iUpperBound == 0) - { - UTIL_Remove( this ); - return; - } - - GenericCyclerSpawn( (char *)STRING( GetModelName() ), Vector(-16,-16,-16), Vector(16,16,16)); - if (!m_iBlendspeed) - m_iBlendspeed = 5; - - // Initialise Sequence - if (m_iszSequence != NULL_STRING) - { - SetSequence( LookupSequence( STRING(m_iszSequence) ) ); - } - - m_iCurrent = m_iLowerBound; -} - -bool CBlendingCycler::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "lowboundary")) - { - m_iLowerBound = atoi(szValue); - } - else if (FStrEq(szKeyName, "highboundary")) - { - m_iUpperBound = atoi(szValue); - } - else if (FStrEq(szKeyName, "blendspeed")) - { - m_iBlendspeed = atoi(szValue); - } - else if (FStrEq(szKeyName, "blendsequence")) - { - m_iszSequence = AllocPooledString(szValue); - } - else - return BaseClass::KeyValue( szKeyName, szValue ); - - return true; -} - -// Blending Cycler think -void CBlendingCycler::Think( void ) -{ - SetNextThink( gpGlobals->curtime + 0.1f ); - - // Move - m_iCurrent += m_iBlendspeed; - if ( (m_iCurrent > m_iUpperBound) || (m_iCurrent < m_iLowerBound) ) - m_iBlendspeed = m_iBlendspeed * -1; - - // Set blend - SetPoseParameter( 0, m_iCurrent ); - - Msg( "Current Blend: %d\n", m_iCurrent ); - - if (IsSequenceFinished() && !SequenceLoops()) - { - // ResetSequenceInfo(); - // hack to avoid reloading model every frame - m_flAnimTime = gpGlobals->curtime; - m_flPlaybackRate = 1.0; - m_bSequenceFinished = false; - m_flLastEventCheck = 0; - m_flCycle = 0; - if (!m_animate) - { - m_flPlaybackRate = 0.0; // FIX: don't reset framerate - } - } -} - - diff --git a/game/server/h_cycler.h b/game/server/h_cycler.h deleted file mode 100644 index d089646e8..000000000 --- a/game/server/h_cycler.h +++ /dev/null @@ -1,41 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef H_CYCLER_H -#define H_CYCLER_H -#ifdef _WIN32 -#pragma once -#endif - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CCycler : public CAI_BaseNPC -{ -public: - DECLARE_CLASS( CCycler, CAI_BaseNPC ); - - void GenericCyclerSpawn(char *szModel, Vector vecMin, Vector vecMax); - virtual int ObjectCaps( void ) { return (BaseClass::ObjectCaps() | FCAP_IMPULSE_USE); } - int OnTakeDamage( const CTakeDamageInfo &info ); - void Spawn( void ); - void Precache( void ); - void Think( void ); - //void Pain( float flDamage ); - void Use ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - // Don't treat as a live target - virtual bool IsAlive( void ) { return false; } - - // Inputs - void InputSetSequence( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - - int m_animate; -}; - -#endif // H_CYCLER_H diff --git a/game/server/h_export.cpp b/game/server/h_export.cpp deleted file mode 100644 index 9fe0bceae..000000000 --- a/game/server/h_export.cpp +++ /dev/null @@ -1,48 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -/* - -===== h_export.cpp ======================================================== - - Entity classes exported by Halflife. - -*/ - -#if defined(_WIN32) && !defined(_XBOX) - -#include "winlite.h" -#include "datamap.h" -#include "tier0/dbg.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -HMODULE win32DLLHandle; - -// Required DLL entry point -BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) -{ - // ensure data sizes are stable - if ( sizeof(inputfunc_t) != sizeof(int) ) - { - Assert( sizeof(inputfunc_t) == sizeof(int) ); - return FALSE; - } - - if ( fdwReason == DLL_PROCESS_ATTACH ) - { - win32DLLHandle = hinstDLL; - } - else if ( fdwReason == DLL_PROCESS_DETACH ) - { - } - return TRUE; -} - -#endif - diff --git a/game/server/hierarchy.cpp b/game/server/hierarchy.cpp deleted file mode 100644 index 50a98490c..000000000 --- a/game/server/hierarchy.cpp +++ /dev/null @@ -1,169 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Contains the set of functions for manipulating entity hierarchies. -// -// $NoKeywords: $ -//=============================================================================// - -// UNDONE: Reconcile this with SetParent() - -#include "cbase.h" -#include "hierarchy.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Does the linked list work of removing a child object from the hierarchy. -// Input : pParent - -// pChild - -//----------------------------------------------------------------------------- -void UnlinkChild( CBaseEntity *pParent, CBaseEntity *pChild ) -{ - CBaseEntity *pList; - EHANDLE *pPrev; - - pList = pParent->m_hMoveChild; - pPrev = &pParent->m_hMoveChild; - while ( pList ) - { - CBaseEntity *pNext = pList->m_hMovePeer; - if ( pList == pChild ) - { - // patch up the list - pPrev->Set( pNext ); - - // Clear hierarchy bits for this guy - pList->m_hMoveParent.Set( NULL ); - pList->m_hMovePeer.Set( NULL ); - pList->NetworkProp()->SetNetworkParent( CBaseHandle() ); - pList->DispatchUpdateTransmitState(); - pList->OnEntityEvent( ENTITY_EVENT_PARENT_CHANGED, NULL ); - - pParent->RecalcHasPlayerChildBit(); - return; - } - else - { - pPrev = &pList->m_hMovePeer; - pList = pNext; - } - } - - // This only happens if the child wasn't found in the parent's child list - Assert(0); -} - -void LinkChild( CBaseEntity *pParent, CBaseEntity *pChild ) -{ - EHANDLE hParent; - hParent.Set( pParent ); - pChild->m_hMovePeer.Set( pParent->FirstMoveChild() ); - pParent->m_hMoveChild.Set( pChild ); - pChild->m_hMoveParent = hParent; - pChild->NetworkProp()->SetNetworkParent( hParent ); - pChild->DispatchUpdateTransmitState(); - pChild->OnEntityEvent( ENTITY_EVENT_PARENT_CHANGED, NULL ); - pParent->RecalcHasPlayerChildBit(); -} - -void TransferChildren( CBaseEntity *pOldParent, CBaseEntity *pNewParent ) -{ - CBaseEntity *pChild = pOldParent->FirstMoveChild(); - while ( pChild ) - { - // NOTE: Have to do this before the unlink to ensure local coords are valid - Vector vecAbsOrigin = pChild->GetAbsOrigin(); - QAngle angAbsRotation = pChild->GetAbsAngles(); - Vector vecAbsVelocity = pChild->GetAbsVelocity(); -// QAngle vecAbsAngVelocity = pChild->GetAbsAngularVelocity(); - - UnlinkChild( pOldParent, pChild ); - LinkChild( pNewParent, pChild ); - - // FIXME: This is a hack to guarantee update of the local origin, angles, etc. - pChild->m_vecAbsOrigin.Init( FLT_MAX, FLT_MAX, FLT_MAX ); - pChild->m_angAbsRotation.Init( FLT_MAX, FLT_MAX, FLT_MAX ); - pChild->m_vecAbsVelocity.Init( FLT_MAX, FLT_MAX, FLT_MAX ); - - pChild->SetAbsOrigin(vecAbsOrigin); - pChild->SetAbsAngles(angAbsRotation); - pChild->SetAbsVelocity(vecAbsVelocity); -// pChild->SetAbsAngularVelocity(vecAbsAngVelocity); - - pChild = pOldParent->FirstMoveChild(); - } -} - -void UnlinkFromParent( CBaseEntity *pRemove ) -{ - if ( pRemove->GetMoveParent() ) - { - // NOTE: Have to do this before the unlink to ensure local coords are valid - Vector vecAbsOrigin = pRemove->GetAbsOrigin(); - QAngle angAbsRotation = pRemove->GetAbsAngles(); - Vector vecAbsVelocity = pRemove->GetAbsVelocity(); -// QAngle vecAbsAngVelocity = pRemove->GetAbsAngularVelocity(); - - UnlinkChild( pRemove->GetMoveParent(), pRemove ); - - pRemove->SetLocalOrigin(vecAbsOrigin); - pRemove->SetLocalAngles(angAbsRotation); - pRemove->SetLocalVelocity(vecAbsVelocity); -// pRemove->SetLocalAngularVelocity(vecAbsAngVelocity); - pRemove->UpdateWaterState(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Clears the parent of all the children of the given object. -//----------------------------------------------------------------------------- -void UnlinkAllChildren( CBaseEntity *pParent ) -{ - CBaseEntity *pChild = pParent->FirstMoveChild(); - while ( pChild ) - { - CBaseEntity *pNext = pChild->NextMovePeer(); - UnlinkFromParent( pChild ); - pChild = pNext; - } -} - -bool EntityIsParentOf( CBaseEntity *pParent, CBaseEntity *pEntity ) -{ - while ( pEntity->GetMoveParent() ) - { - pEntity = pEntity->GetMoveParent(); - if ( pParent == pEntity ) - return true; - } - - return false; -} - -static void GetAllChildren_r( CBaseEntity *pEntity, CUtlVector &list ) -{ - for ( ; pEntity != NULL; pEntity = pEntity->NextMovePeer() ) - { - list.AddToTail( pEntity ); - GetAllChildren_r( pEntity->FirstMoveChild(), list ); - } -} - -int GetAllChildren( CBaseEntity *pParent, CUtlVector &list ) -{ - if ( !pParent ) - return 0; - - GetAllChildren_r( pParent->FirstMoveChild(), list ); - return list.Count(); -} - -int GetAllInHierarchy( CBaseEntity *pParent, CUtlVector &list ) -{ - if (!pParent) - return 0; - list.AddToTail( pParent ); - return GetAllChildren( pParent, list ) + 1; -} diff --git a/game/server/hierarchy.h b/game/server/hierarchy.h deleted file mode 100644 index 449a60dff..000000000 --- a/game/server/hierarchy.h +++ /dev/null @@ -1,26 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Contains the set of functions for manipulating entity hierarchies. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef HIERARCHY_H -#define HIERARCHY_H -#ifdef _WIN32 -#pragma once -#endif - -#include "utlvector.h" - -class CBaseEntity; - -void UnlinkFromParent( CBaseEntity *pRemove ); -void TransferChildren( CBaseEntity *pOldParent, CBaseEntity *pNewParent ); -void LinkChild( CBaseEntity *pParent, CBaseEntity *pChild ); -void UnlinkAllChildren( CBaseEntity *pParent ); -int GetAllChildren( CBaseEntity *pParent, CUtlVector &list ); -bool EntityIsParentOf( CBaseEntity *pParent, CBaseEntity *pEntity ); -int GetAllInHierarchy( CBaseEntity *pParent, CUtlVector &list ); - -#endif // HIERARCHY_H diff --git a/game/server/hl1_CBaseHelicopter.h b/game/server/hl1_CBaseHelicopter.h deleted file mode 100644 index 39b292e05..000000000 --- a/game/server/hl1_CBaseHelicopter.h +++ /dev/null @@ -1,136 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -//--------------------------------------------------------- -// Helicopter flags -//--------------------------------------------------------- -enum HelicopterFlags_t -{ - BITS_HELICOPTER_GUN_ON = 0x00000001, // Gun is on and aiming - BITS_HELICOPTER_MISSILE_ON = 0x00000002, // Missile turrets are on and aiming -}; - - -//--------------------------------------------------------- -//--------------------------------------------------------- - -#define SF_NOWRECKAGE 0x08 -#define SF_NOROTORWASH 0x20 -#define SF_AWAITINPUT 0x40 - - -//--------------------------------------------------------- -//--------------------------------------------------------- -#define BASECHOPPER_MAX_SPEED 400.0f -#define BASECHOPPER_MAX_FIRING_SPEED 250.0f -#define BASECHOPPER_MIN_ROCKET_DIST 1000.0f -#define BASECHOPPER_MAX_GUN_DIST 2000.0f - - -//========================================================= -//========================================================= -class CBaseHelicopter : public CAI_BaseNPC -{ -public: - DECLARE_CLASS( CBaseHelicopter, CAI_BaseNPC ); - - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - void Spawn( void ); - void Precache( void ); - - void Event_Killed( const CTakeDamageInfo &info ); - void StopLoopingSounds(); - - int BloodColor( void ) { return DONT_BLEED; } - void GibMonster( void ); - - Class_T Classify ( void ) { return CLASS_HUMAN_MILITARY; } - - void CallDyingThink( void ) { DyingThink(); } - - bool HasEnemy( void ) { return GetEnemy() != NULL; } - void CheckEnemy( CBaseEntity *pEnemy ); - virtual bool ChooseEnemy( void ); - virtual void HelicopterThink( void ); - virtual void HelicopterPostThink( void ) { }; - virtual void FlyTouch( CBaseEntity *pOther ); - virtual void CrashTouch( CBaseEntity *pOther ); - virtual void DyingThink( void ); - virtual void Startup( void ); - virtual void NullThink( void ); - - virtual void Flight( void ); - - virtual void ShowDamage( void ) {}; - - virtual void FlyPathCorners( void ); - void UpdatePlayerDopplerShift( void ); - - virtual void Hunt( void ); - - virtual bool IsCrashing( void ) { return m_lifeState != LIFE_ALIVE; } - virtual float GetAcceleration( void ) { return 5; } - virtual bool HasReachedTarget( void ); - virtual void OnReachedTarget( CBaseEntity *pTarget ) {}; - - virtual void ApplySidewaysDrag( const Vector &vecRight ); - virtual void ApplyGeneralDrag( void ); - - - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - - virtual bool FireGun( void ); - - virtual float GetRotorVolume( void ) { return 1.0; } - virtual void InitializeRotorSound( void ); - virtual void UpdateRotorSoundPitch( int iPitch ); - - virtual void AimRocketGun(void) {}; - virtual void FireRocket( Vector vLaunchPos, Vector vLaunchDir ) {}; - - void DrawDebugGeometryOverlays(void); - - CSoundPatch *m_pRotorSound; - - float m_flForce; - int m_fHelicopterFlags; - - Vector m_vecDesiredFaceDir; - Vector m_vecDesiredPosition; - - Vector m_vecGoalOrientation; // orientation of the goal entity. - - float m_flLastSeen; - float m_flPrevSeen; - - int m_iSoundState; // don't save this - - Vector m_vecTarget; - Vector m_vecTargetPosition; - - float m_flMaxSpeed; // Maximum speed of the helicopter. - float m_flMaxSpeedFiring; // Maximum speed of the helicopter whilst firing guns. - - float m_flGoalSpeed; // Goal speed - float m_flInitialSpeed; - float m_angleVelocity; - - void ChangePathCorner( const char *pszName ); - - // Inputs - void InputChangePathCorner( inputdata_t &inputdata ); - void InputActivate( inputdata_t &inputdata ); - - // Outputs - COutputEvent m_AtTarget; // Fired when pathcorner has been reached - COutputEvent m_LeaveTarget; // Fired when pathcorner is left - - float m_flNextCrashExplosion; -}; diff --git a/game/server/hl2/Func_Monitor.cpp b/game/server/hl2/Func_Monitor.cpp deleted file mode 100644 index cbc186419..000000000 --- a/game/server/hl2/Func_Monitor.cpp +++ /dev/null @@ -1,109 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "point_camera.h" -#include "modelentities.h" -#include "info_camera_link.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CFuncMonitor : public CFuncBrush -{ - DECLARE_DATADESC(); - DECLARE_CLASS( CFuncMonitor, CFuncBrush ); - DECLARE_SERVERCLASS(); - -public: - virtual void Activate(); - virtual void UpdateOnRemove(); - -private: - void InputSetCamera(inputdata_t &inputdata); - void SetCameraByName(const char *szName); - void ReleaseCameraLink(); - - EHANDLE m_hInfoCameraLink; -}; - -// automatically hooks in the system's callbacks -BEGIN_DATADESC( CFuncMonitor ) - - DEFINE_FIELD( m_hInfoCameraLink, FIELD_EHANDLE ), - - // Outputs - DEFINE_INPUTFUNC( FIELD_STRING, "SetCamera", InputSetCamera ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( func_monitor, CFuncMonitor ); - - -IMPLEMENT_SERVERCLASS_ST( CFuncMonitor, DT_FuncMonitor ) -END_SEND_TABLE() - - -//----------------------------------------------------------------------------- -// Purpose: Called after all entities have spawned and after a load game. -//----------------------------------------------------------------------------- -void CFuncMonitor::Activate() -{ - BaseClass::Activate(); - SetCameraByName(STRING(m_target)); -} - -void CFuncMonitor::UpdateOnRemove() -{ - ReleaseCameraLink(); - BaseClass::UpdateOnRemove(); -} - - -//----------------------------------------------------------------------------- -// Frees the camera. -//----------------------------------------------------------------------------- -void CFuncMonitor::ReleaseCameraLink() -{ - if ( m_hInfoCameraLink ) - { - UTIL_Remove( m_hInfoCameraLink ); - m_hInfoCameraLink = NULL; - - // Keep the target up-to-date for save/load - m_target = NULL_STRING; - } -} - - -//----------------------------------------------------------------------------- -// Sets camera -//----------------------------------------------------------------------------- -void CFuncMonitor::SetCameraByName(const char *szName) -{ - ReleaseCameraLink(); - CBaseEntity *pBaseEnt = gEntList.FindEntityByName( NULL, szName ); - if( pBaseEnt ) - { - CPointCamera *pCamera = dynamic_cast( pBaseEnt ); - if( pCamera ) - { - // Keep the target up-to-date for save/load - m_target = MAKE_STRING( szName ); - m_hInfoCameraLink = CreateInfoCameraLink( this, pCamera ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncMonitor::InputSetCamera(inputdata_t &inputdata) -{ - SetCameraByName( inputdata.value.String() ); -} diff --git a/game/server/hl2/ai_allymanager.cpp b/game/server/hl2/ai_allymanager.cpp deleted file mode 100644 index 45cef870d..000000000 --- a/game/server/hl2/ai_allymanager.cpp +++ /dev/null @@ -1,263 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "entitylist.h" -#include "ai_basenpc.h" -#include "npc_citizen17.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define MAX_ALLIES 10 - -class CAI_AllyManager : public CBaseEntity -{ - DECLARE_CLASS( CAI_AllyManager, CBaseEntity ); - -public: - void Spawn(); - - void CountAllies( int *pTotal, int *pMedics ); - -private: - int m_iMaxAllies; - int m_iMaxMedics; - - int m_iAlliesLast; - int m_iMedicsLast; -public: - void WatchCounts(); - - // Input functions - void InputSetMaxAllies( inputdata_t &inputdata ); - void InputSetMaxMedics( inputdata_t &inputdata ); - void InputReplenish( inputdata_t &inputdata ); - - // Outputs - COutputEvent m_SpawnAlly[ MAX_ALLIES ]; - COutputEvent m_SpawnMedicAlly; - COutputEvent m_OnZeroAllies; - COutputEvent m_OnZeroMedicAllies; - - - DECLARE_DATADESC(); -}; - -ConVar ai_ally_manager_debug("ai_ally_manager_debug", "0" ); - - -LINK_ENTITY_TO_CLASS( ai_ally_manager, CAI_AllyManager ); - -BEGIN_DATADESC( CAI_AllyManager ) - DEFINE_KEYFIELD( m_iMaxAllies, FIELD_INTEGER, "maxallies" ), - DEFINE_KEYFIELD( m_iMaxMedics, FIELD_INTEGER, "maxmedics" ), - DEFINE_FIELD( m_iAlliesLast, FIELD_INTEGER ), - DEFINE_FIELD( m_iMedicsLast, FIELD_INTEGER ), - - DEFINE_THINKFUNC( WatchCounts ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetMaxAllies", InputSetMaxAllies ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetMaxMedics", InputSetMaxMedics ), - DEFINE_INPUTFUNC( FIELD_VOID, "Replenish", InputReplenish ), - - // Outputs - DEFINE_OUTPUT( m_SpawnAlly[ 0 ], "SpawnAlly0" ), - DEFINE_OUTPUT( m_SpawnAlly[ 1 ], "SpawnAlly1" ), - DEFINE_OUTPUT( m_SpawnAlly[ 2 ], "SpawnAlly2" ), - DEFINE_OUTPUT( m_SpawnAlly[ 3 ], "SpawnAlly3" ), - DEFINE_OUTPUT( m_SpawnAlly[ 4 ], "SpawnAlly4" ), - DEFINE_OUTPUT( m_SpawnAlly[ 5 ], "SpawnAlly5" ), - DEFINE_OUTPUT( m_SpawnAlly[ 6 ], "SpawnAlly6" ), - DEFINE_OUTPUT( m_SpawnAlly[ 7 ], "SpawnAlly7" ), - DEFINE_OUTPUT( m_SpawnAlly[ 8 ], "SpawnAlly8" ), - DEFINE_OUTPUT( m_SpawnAlly[ 9 ], "SpawnAlly9" ), - - DEFINE_OUTPUT( m_SpawnMedicAlly, "SpawnMedicAlly" ), - - DEFINE_OUTPUT( m_OnZeroAllies, "OnZeroAllies" ), - DEFINE_OUTPUT( m_OnZeroMedicAllies, "OnZeroMedicAllies" ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_AllyManager::Spawn() -{ - SetThink( &CAI_AllyManager::WatchCounts ); - SetNextThink( gpGlobals->curtime + 1.0 ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_AllyManager::WatchCounts() -{ - // Count the number of allies with the player right now. - int iCurrentAllies; - int iCurrentMedics; - - CountAllies( &iCurrentAllies, &iCurrentMedics ); - - if ( !iCurrentAllies && m_iAlliesLast ) - m_OnZeroAllies.FireOutput( this, this, 0 ); - - if ( !iCurrentMedics && m_iMedicsLast ) - m_OnZeroMedicAllies.FireOutput( this, this, 0 ); - - m_iAlliesLast = iCurrentAllies; - m_iMedicsLast = iCurrentMedics; - - SetNextThink( gpGlobals->curtime + 1.0 ); - - if ( ai_ally_manager_debug.GetBool() ) - DevMsg( "Ally manager counts %d allies, %d of which are medics\n", iCurrentAllies, iCurrentMedics ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_AllyManager::CountAllies( int *pTotal, int *pMedics ) -{ - (*pTotal) = (*pMedics) = 0; - - if ( !AI_IsSinglePlayer() ) - { - // @TODO (toml 10-22-04): no MP support right now - return; - } - - const Vector & vPlayerPos = UTIL_GetLocalPlayer()->GetAbsOrigin(); - CAI_BaseNPC ** ppAIs = g_AI_Manager.AccessAIs(); - int nAIs = g_AI_Manager.NumAIs(); - - for ( int i = 0; i < nAIs; i++ ) - { - if ( ppAIs[i]->IsAlive() && ppAIs[i]->IsPlayerAlly() ) - { - // Vital allies do not count. - if( ppAIs[i]->Classify() == CLASS_PLAYER_ALLY_VITAL ) - continue; - - // They only count if I can use them. - if( ppAIs[i]->HasSpawnFlags(SF_CITIZEN_NOT_COMMANDABLE) ) - continue; - - // They only count if I can use them. - if( ppAIs[i]->IRelationType( UTIL_GetLocalPlayer() ) != D_LI ) - continue; - - // Skip distant NPCs - if ( !ppAIs[i]->IsInPlayerSquad() && - !UTIL_FindClientInPVS( ppAIs[i]->edict() ) && - ( ( ppAIs[i]->GetAbsOrigin() - vPlayerPos ).LengthSqr() > 150*12 || - fabsf( ppAIs[i]->GetAbsOrigin().z - vPlayerPos.z ) > 192 ) ) - continue; - - if( FClassnameIs( ppAIs[i], "npc_citizen" ) ) - { - CNPC_Citizen *pCitizen = assert_cast(ppAIs[i]); - if ( !pCitizen->CanJoinPlayerSquad() ) - continue; - - if ( pCitizen->WasInPlayerSquad() && !pCitizen->IsInPlayerSquad() ) - continue; - - if ( ppAIs[i]->HasSpawnFlags( SF_CITIZEN_MEDIC ) ) - (*pMedics)++; - } - - (*pTotal)++; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAI_AllyManager::InputSetMaxAllies( inputdata_t &inputdata ) -{ - m_iMaxAllies = inputdata.value.Int(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_AllyManager::InputSetMaxMedics( inputdata_t &inputdata ) -{ - m_iMaxMedics = inputdata.value.Int(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAI_AllyManager::InputReplenish( inputdata_t &inputdata ) -{ - // Count the number of allies with the player right now. - int iCurrentAllies; - int iCurrentMedics; - - CountAllies( &iCurrentAllies, &iCurrentMedics ); - - // TOTAL number of allies to be replaced. - int iReplaceAllies = m_iMaxAllies - iCurrentAllies; - - // The number of total allies that should be medics. - int iReplaceMedics = m_iMaxMedics - iCurrentMedics; - - if( iReplaceMedics > iReplaceAllies ) - { - // Clamp medics. - iReplaceMedics = iReplaceAllies; - } - -// Medics. - if( m_iMaxMedics > 0 ) - { - - if( iReplaceMedics > MAX_ALLIES ) - { - // This error is fatal now. (sjb) - Msg("**ERROR! ai_allymanager - ReplaceMedics > MAX_ALLIES\n" ); - return; - } - - if ( ai_ally_manager_debug.GetBool() ) - DevMsg( "Ally manager spawning %d medics\n", iReplaceMedics ); - - int i; - for( i = 0 ; i < iReplaceMedics ; i++ ) - { - m_SpawnMedicAlly.FireOutput( this, this, 0 ); - - // Don't forget to count this guy against the number of - // allies to be replenished. - iReplaceAllies--; - } - } - -// Allies - if( iReplaceAllies < 1 ) - { - return; - } - - if( iReplaceAllies > MAX_ALLIES ) - { - Msg("**ERROR! ai_allymanager - ReplaceAllies > MAX_ALLIES\n" ); - iReplaceAllies = MAX_ALLIES; - } - - if ( ai_ally_manager_debug.GetBool() ) - DevMsg( "Ally manager spawning %d regulars\n", iReplaceAllies ); - - int i; - for( i = 0 ; i < iReplaceAllies ; i++ ) - { - m_SpawnAlly[ i ].FireOutput( this, this, 0 ); - } -} diff --git a/game/server/hl2/ai_behavior_actbusy.cpp b/game/server/hl2/ai_behavior_actbusy.cpp deleted file mode 100644 index 857d0679e..000000000 --- a/game/server/hl2/ai_behavior_actbusy.cpp +++ /dev/null @@ -1,3151 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" - -#include "ai_behavior_actbusy.h" - -#include "ai_navigator.h" -#include "ai_hint.h" -#include "ai_behavior_follow.h" -#include "KeyValues.h" -#include "filesystem.h" -#include "eventqueue.h" -#include "ai_playerally.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" -#include "entityblocker.h" -#include "npcevent.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define ACTBUSY_SEE_ENTITY_TIMEOUT 1.0f - -#define ACTBUSY_COMBAT_PLAYER_MAX_DIST 720.0f // NPCs in combat actbusy should try to stay within this distance of the player. - -ConVar ai_actbusy_search_time( "ai_actbusy_search_time","10.0" ); -ConVar ai_debug_actbusy( "ai_debug_actbusy", "0", FCVAR_CHEAT, "Used to debug actbusy behavior. Usage:\n\ -1: Constantly draw lines from NPCs to the actbusy nodes they've chosen to actbusy at.\n\ -2: Whenever an NPC makes a decision to use an actbusy, show which actbusy they've chosen.\n\ -3: Selected NPCs (with npc_select) will report why they're not choosing actbusy nodes.\n\ -4: Display debug output of actbusy logic.\n\ -5: Display safe zone volumes and info.\n\ -"); - -// Anim events -static int AE_ACTBUSY_WEAPON_FIRE_ON; -static int AE_ACTBUSY_WEAPON_FIRE_OFF; - -BEGIN_DATADESC( CAI_ActBusyBehavior ) - DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bForceActBusy, FIELD_BOOLEAN ), - DEFINE_CUSTOM_FIELD( m_ForcedActivity, ActivityDataOps() ), - DEFINE_FIELD( m_bTeleportToBusy, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bUseNearestBusy, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bLeaving, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bVisibleOnly, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bUseRenderBoundsForCollision, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flForcedMaxTime, FIELD_FLOAT ), - DEFINE_FIELD( m_bBusy, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bMovingToBusy, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bNeedsToPlayExitAnim, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flNextBusySearchTime, FIELD_TIME ), - DEFINE_FIELD( m_flEndBusyAt, FIELD_TIME ), - DEFINE_FIELD( m_flBusySearchRange, FIELD_FLOAT ), - DEFINE_FIELD( m_bInQueue, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iCurrentBusyAnim, FIELD_INTEGER ), - DEFINE_FIELD( m_hActBusyGoal, FIELD_EHANDLE ), - DEFINE_FIELD( m_bNeedToSetBounds, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hSeeEntity, FIELD_EHANDLE ), - DEFINE_FIELD( m_fTimeLastSawSeeEntity, FIELD_TIME ), - DEFINE_FIELD( m_bExitedBusyToDueLostSeeEntity, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bExitedBusyToDueSeeEnemy, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iNumConsecutivePathFailures, FIELD_INTEGER ), - DEFINE_FIELD( m_bAutoFireWeapon, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flDeferUntil, FIELD_TIME ), - DEFINE_FIELD( m_iNumEnemiesInSafeZone, FIELD_INTEGER ), -END_DATADESC(); - -enum -{ - ACTBUSY_SIGHT_METHOD_FULL = 0, // LOS and Viewcone - ACTBUSY_SIGHT_METHOD_LOS_ONLY, -}; - -//============================================================================= -//----------------------------------------------------------------------------- -// Purpose: Gamesystem that parses the act busy anim file -//----------------------------------------------------------------------------- -class CActBusyAnimData : public CAutoGameSystem -{ -public: - CActBusyAnimData( void ) : CAutoGameSystem( "CActBusyAnimData" ) - { - } - - // Inherited from IAutoServerSystem - virtual void LevelInitPostEntity( void ); - virtual void LevelShutdownPostEntity( void ); - - // Read in the data from the anim data file - void ParseAnimDataFile( void ); - - // Parse a keyvalues section into an act busy anim - bool ParseActBusyFromKV( busyanim_t *pAnim, KeyValues *pSection ); - - // Purpose: Returns the index of the busyanim data for the specified activity or sequence - int FindBusyAnim( Activity iActivity, const char *pSequence ); - - busyanim_t *GetBusyAnim( int iIndex ) { return &m_ActBusyAnims[iIndex]; } - -protected: - CUtlVector m_ActBusyAnims; -}; - -CActBusyAnimData g_ActBusyAnimDataSystem; - -//----------------------------------------------------------------------------- -// Inherited from IAutoServerSystem -//----------------------------------------------------------------------------- -void CActBusyAnimData::LevelInitPostEntity( void ) -{ - ParseAnimDataFile(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CActBusyAnimData::LevelShutdownPostEntity( void ) -{ - m_ActBusyAnims.Purge(); -} - -//----------------------------------------------------------------------------- -// Clear out the stats + their history -//----------------------------------------------------------------------------- -void CActBusyAnimData::ParseAnimDataFile( void ) -{ - KeyValues *pKVAnimData = new KeyValues( "ActBusyAnimDatafile" ); - if ( pKVAnimData->LoadFromFile( filesystem, "scripts/actbusy.txt" ) ) - { - // Now try and parse out each act busy anim - KeyValues *pKVAnim = pKVAnimData->GetFirstSubKey(); - while ( pKVAnim ) - { - // Create a new anim and add it to our list - int index = m_ActBusyAnims.AddToTail(); - busyanim_t *pAnim = &m_ActBusyAnims[index]; - if ( !ParseActBusyFromKV( pAnim, pKVAnim ) ) - { - m_ActBusyAnims.Remove( index ); - } - - pKVAnim = pKVAnim->GetNextKey(); - } - } - pKVAnimData->deleteThis(); -} - -//----------------------------------------------------------------------------- -// Purpose: Parse a keyvalues section into the prop -//----------------------------------------------------------------------------- -bool CActBusyAnimData::ParseActBusyFromKV( busyanim_t *pAnim, KeyValues *pSection ) -{ - pAnim->iszName = AllocPooledString( pSection->GetName() ); - - // Activities - pAnim->iActivities[BA_BUSY] = (Activity)CAI_BaseNPC::GetActivityID( pSection->GetString( "busy_anim", "ACT_INVALID" ) ); - pAnim->iActivities[BA_ENTRY] = (Activity)CAI_BaseNPC::GetActivityID( pSection->GetString( "entry_anim", "ACT_INVALID" ) ); - pAnim->iActivities[BA_EXIT] = (Activity)CAI_BaseNPC::GetActivityID( pSection->GetString( "exit_anim", "ACT_INVALID" ) ); - - // Sequences - pAnim->iszSequences[BA_BUSY] = AllocPooledString( pSection->GetString( "busy_sequence", NULL ) ); - pAnim->iszSequences[BA_ENTRY] = AllocPooledString( pSection->GetString( "entry_sequence", NULL ) ); - pAnim->iszSequences[BA_EXIT] = AllocPooledString( pSection->GetString( "exit_sequence", NULL ) ); - - // Sounds - pAnim->iszSounds[BA_BUSY] = AllocPooledString( pSection->GetString( "busy_sound", NULL ) ); - pAnim->iszSounds[BA_ENTRY] = AllocPooledString( pSection->GetString( "entry_sound", NULL ) ); - pAnim->iszSounds[BA_EXIT] = AllocPooledString( pSection->GetString( "exit_sound", NULL ) ); - - // Times - pAnim->flMinTime = pSection->GetFloat( "min_time", 10.0 ); - pAnim->flMaxTime = pSection->GetFloat( "max_time", 20.0 ); - - pAnim->bUseAutomovement = pSection->GetInt( "use_automovement", 0 ) != 0; - - const char *sInterrupt = pSection->GetString( "interrupts", "BA_INT_DANGER" ); - if ( !strcmp( sInterrupt, "BA_INT_PLAYER" ) ) - { - pAnim->iBusyInterruptType = BA_INT_PLAYER; - } - else if ( !strcmp( sInterrupt, "BA_INT_DANGER" ) ) - { - pAnim->iBusyInterruptType = BA_INT_DANGER; - } - else if ( !strcmp( sInterrupt, "BA_INT_AMBUSH" ) ) - { - pAnim->iBusyInterruptType = BA_INT_AMBUSH; - } - else if ( !strcmp( sInterrupt, "BA_INT_COMBAT" ) ) - { - pAnim->iBusyInterruptType = BA_INT_COMBAT; - } - else if ( !strcmp( sInterrupt, "BA_INT_ZOMBIESLUMP" )) - { - pAnim->iBusyInterruptType = BA_INT_ZOMBIESLUMP; - } - else if ( !strcmp( sInterrupt, "BA_INT_SIEGE_DEFENSE" )) - { - pAnim->iBusyInterruptType = BA_INT_SIEGE_DEFENSE; - } - else - { - pAnim->iBusyInterruptType = BA_INT_NONE; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the busyanim data for the specified activity -//----------------------------------------------------------------------------- -int CActBusyAnimData::FindBusyAnim( Activity iActivity, const char *pSequence ) -{ - int iCount = m_ActBusyAnims.Count(); - for ( int i = 0; i < iCount; i++ ) - { - busyanim_t *pBusyAnim = &m_ActBusyAnims[i]; - Assert( pBusyAnim ); - - if ( pSequence && pBusyAnim->iszName != NULL_STRING && !Q_stricmp( STRING(pBusyAnim->iszName), pSequence ) ) - return i; - - if ( iActivity != ACT_INVALID && pBusyAnim->iActivities[BA_BUSY] == iActivity ) - return i; - } - - if ( pSequence ) - { - Warning("Specified '%s' as a busy anim name, and it's not in the act busy anim list.\n", pSequence ); - } - else if ( iActivity != ACT_INVALID ) - { - Warning("Tried to use Activity %d as a busy anim, and it's not in the act busy anim list.\n", iActivity ); - } - - return -1; -} - -//============================================================================================================= -//============================================================================================================= - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CAI_ActBusyBehavior::CAI_ActBusyBehavior() -{ - // Disabled by default. Enabled by map entity. - m_bEnabled = false; - m_bUseRenderBoundsForCollision = false; - m_flDeferUntil = 0; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ActBusyBehavior::Enable( CAI_ActBusyGoal *pGoal, float flRange, bool bVisibleOnly ) -{ - NotifyBusyEnding(); - - if ( pGoal ) - { - m_hActBusyGoal = pGoal; - } - m_bEnabled = true; - m_bBusy = false; - m_bMovingToBusy = false; - m_bNeedsToPlayExitAnim = false; - m_bLeaving = false; - m_flNextBusySearchTime = gpGlobals->curtime + ai_actbusy_search_time.GetFloat(); - m_flEndBusyAt = 0; - m_bVisibleOnly = bVisibleOnly; - m_bInQueue = dynamic_cast(m_hActBusyGoal.Get()) != NULL; - m_ForcedActivity = ACT_INVALID; - m_hSeeEntity = NULL; - m_bExitedBusyToDueLostSeeEntity = false; - m_bExitedBusyToDueSeeEnemy = false; - m_iNumConsecutivePathFailures = 0; - - SetBusySearchRange( flRange ); - - if ( ai_debug_actbusy.GetInt() == 4 ) - { - Msg("ACTBUSY: behavior enabled on NPC %s (%s)\n", GetOuter()->GetClassname(), GetOuter()->GetDebugName() ); - } - - if( IsCombatActBusy() ) - { - CollectSafeZoneVolumes( pGoal ); - } - - // Robin: Due to ai goal entities delaying their EnableGoal call on each - // of their target Actors, NPCs that are spawned with active actbusies - // will have their SelectSchedule() called before their behavior has been - // enabled. To fix this, if we're enabled while in a schedule that can be - // overridden, immediately act busy. - if ( IsCurScheduleOverridable() ) - { - // Force search time to be now. - m_flNextBusySearchTime = gpGlobals->curtime; - GetOuter()->ClearSchedule( "Enabling act busy" ); - } - - ClearCondition( COND_ACTBUSY_AWARE_OF_ENEMY_IN_SAFE_ZONE ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_ActBusyBehavior::OnRestore() -{ - if ( m_bEnabled && m_hActBusyGoal != NULL && IsCombatActBusy() ) - { - CollectSafeZoneVolumes( m_hActBusyGoal ); - } - - BaseClass::OnRestore(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ActBusyBehavior::SetBusySearchRange( float flRange ) -{ - m_flBusySearchRange = flRange; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ActBusyBehavior::Disable( void ) -{ - if ( ai_debug_actbusy.GetInt() == 4 ) - { - Msg("ACTBUSY: behavior disabled on NPC %s (%s)\n", GetOuter()->GetClassname(), GetOuter()->GetDebugName() ); - } - - if ( m_bEnabled ) - { - SetCondition( COND_PROVOKED ); - } - - StopBusying(); - m_bEnabled = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ActBusyBehavior::ForceActBusy( CAI_ActBusyGoal *pGoal, CAI_Hint *pHintNode, float flMaxTime, bool bVisibleOnly, bool bTeleportToBusy, bool bUseNearestBusy, CBaseEntity *pSeeEntity, Activity activity ) -{ - Assert( !m_bLeaving ); - - if ( m_bNeedsToPlayExitAnim ) - { - // If we hit this, the mapmaker's told this NPC to actbusy somewhere while it's still in an actbusy. - // Right now, we don't support this. We could support it with a bit of work. - if ( HasAnimForActBusy( m_iCurrentBusyAnim, BA_EXIT ) ) - { - Warning("ACTBUSY: %s(%s) was told to actbusy while inside an actbusy that needs to exit first. IGNORING.\n", GetOuter()->GetDebugName(), GetOuter()->GetClassname() ); - return; - } - } - - if ( ai_debug_actbusy.GetInt() == 4 ) - { - Msg("ACTBUSY: ForceActBusy on NPC %s (%s): ", GetOuter()->GetClassname(), GetOuter()->GetDebugName() ); - if ( pHintNode ) - { - Msg("Hintnode %s", pHintNode->GetDebugName()); - } - else - { - Msg("No Hintnode specified"); - } - Msg("\n"); - } - - Enable( pGoal, m_flBusySearchRange, bVisibleOnly ); - m_bForceActBusy = true; - m_flForcedMaxTime = flMaxTime; - m_bTeleportToBusy = bTeleportToBusy; - m_bUseNearestBusy = bUseNearestBusy; - m_ForcedActivity = activity; - m_hSeeEntity = pSeeEntity; - - if ( pHintNode ) - { - if ( GetHintNode() && GetHintNode() != pHintNode ) - { - GetHintNode()->Unlock(); - } - - if ( pHintNode->Lock( GetOuter() ) ) - { - SetHintNode( pHintNode ); - } - } - - SetCondition( COND_PROVOKED ); -} - -//----------------------------------------------------------------------------- -// Purpose: Force the NPC to find an exit node and leave -//----------------------------------------------------------------------------- -void CAI_ActBusyBehavior::ForceActBusyLeave( bool bVisibleOnly ) -{ - if ( ai_debug_actbusy.GetInt() == 4 ) - { - Msg("ACTBUSY: ForceActBusyLeave on NPC %s (%s)\n", GetOuter()->GetClassname(), GetOuter()->GetDebugName() ); - } - - Enable( NULL, m_flBusySearchRange, bVisibleOnly ); - m_bForceActBusy = true; - m_bLeaving = true; - m_ForcedActivity = ACT_INVALID; - m_hSeeEntity = NULL; - - SetCondition( COND_PROVOKED ); -} - -//----------------------------------------------------------------------------- -// Purpose: Break the NPC out of the current busy state, but don't disable busying -//----------------------------------------------------------------------------- -void CAI_ActBusyBehavior::StopBusying( void ) -{ - if ( !GetOuter() ) - return; - - // Make sure we turn this off unconditionally! - m_bAutoFireWeapon = false; - - if ( ai_debug_actbusy.GetInt() == 4 ) - { - Msg("ACTBUSY: StopBusying on NPC %s (%s)\n", GetOuter()->GetClassname(), GetOuter()->GetDebugName() ); - } - - if ( m_bBusy || m_bMovingToBusy ) - { - SetCondition( COND_PROVOKED ); - } - - m_flEndBusyAt = gpGlobals->curtime; - m_bForceActBusy = false; - m_bTeleportToBusy = false; - m_bUseNearestBusy = false; - m_bLeaving = false; - m_bMovingToBusy = false; - m_ForcedActivity = ACT_INVALID; - m_hSeeEntity = NULL; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CAI_ActBusyBehavior::IsStopBusying() -{ - return IsCurSchedule(SCHED_ACTBUSY_STOP_BUSYING); -} - -//----------------------------------------------------------------------------- -// Purpose: Find a general purpose, suitable Hint Node for me to Act Busy. -//----------------------------------------------------------------------------- -CAI_Hint *CAI_ActBusyBehavior::FindActBusyHintNode() -{ - Assert( !IsCombatActBusy() ); - - int iBits = bits_HINT_NODE_USE_GROUP; - if ( m_bVisibleOnly ) - { - iBits |= bits_HINT_NODE_VISIBLE; - } - - if ( ai_debug_actbusy.GetInt() == 3 && GetOuter()->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT ) - { - iBits |= bits_HINT_NODE_REPORT_FAILURES; - } - - if ( m_bUseNearestBusy ) - { - iBits |= bits_HINT_NODE_NEAREST; - } - else - { - iBits |= bits_HINT_NODE_RANDOM; - } - - CAI_Hint *pNode = CAI_HintManager::FindHint( GetOuter(), HINT_WORLD_WORK_POSITION, iBits, m_flBusySearchRange ); - - return pNode; -} - -//----------------------------------------------------------------------------- -// Purpose: Find a node for me to combat act busy. -// -// Right now, all of this work assumes the actbusier is a player ally and -// wants to fight near the player a'la Alyx in ep2_outland_10. -//----------------------------------------------------------------------------- -CAI_Hint *CAI_ActBusyBehavior::FindCombatActBusyHintNode() -{ - Assert( IsCombatActBusy() ); - - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - - if( !pPlayer ) - return NULL; - - CHintCriteria criteria; - - // Ok, find a hint node THAT: - // -Is in my hint group - // -Is Visible (if specified by designer) - // -Is Closest to me (if specified by designer) - // -The player can see - // -Is within the accepted max dist from player - int iBits = bits_HINT_NODE_USE_GROUP; - - if ( m_bVisibleOnly ) - iBits |= bits_HINT_NODE_VISIBLE; - - if ( ai_debug_actbusy.GetInt() == 3 && GetOuter()->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT ) - iBits |= bits_HINT_NODE_REPORT_FAILURES; - - if ( m_bUseNearestBusy ) - iBits |= bits_HINT_NODE_NEAREST; - else - iBits |= bits_HINT_NODE_RANDOM; - - iBits |= bits_HAS_EYEPOSITION_LOS_TO_PLAYER; - - criteria.AddHintType( HINT_WORLD_WORK_POSITION ); - criteria.SetFlag( iBits ); - criteria.AddIncludePosition( pPlayer->GetAbsOrigin(), ACTBUSY_COMBAT_PLAYER_MAX_DIST ); - - CAI_Hint *pNode = CAI_HintManager::FindHint( GetOuter(), criteria ); - - return pNode; -} - -//----------------------------------------------------------------------------- -// Purpose: Find a suitable combat actbusy node to teleport to. That is, find -// one that the player is not going to see me appear at. -//----------------------------------------------------------------------------- -CAI_Hint *CAI_ActBusyBehavior::FindCombatActBusyTeleportHintNode() -{ - Assert( IsCombatActBusy() ); - - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - - if( !pPlayer ) - return NULL; - - CHintCriteria criteria; - - // Ok, find a hint node THAT: - // -Is in my hint group - // -The player CAN NOT see so that they don't see me teleport - int iBits = bits_HINT_NODE_USE_GROUP; - - if ( ai_debug_actbusy.GetInt() == 3 && GetOuter()->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT ) - iBits |= bits_HINT_NODE_REPORT_FAILURES; - - iBits |= bits_HINT_NODE_RANDOM; - iBits |= bits_HINT_NODE_NOT_VISIBLE_TO_PLAYER; - - criteria.AddHintType( HINT_WORLD_WORK_POSITION ); - criteria.SetFlag( iBits ); - criteria.AddIncludePosition( pPlayer->GetAbsOrigin(), ACTBUSY_COMBAT_PLAYER_MAX_DIST * 1.1f ); - - CAI_Hint *pNode = CAI_HintManager::FindHint( GetOuter(), criteria ); - - return pNode; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_ActBusyBehavior::FValidateHintType( CAI_Hint *pHint ) -{ - if ( pHint->HintType() != HINT_WORLD_WORK_POSITION && pHint->HintType() != HINT_NPC_EXIT_POINT ) - return false; - - // If the node doesn't want to be teleported to, we need to check for clear - const char *pSequenceOrActivity = STRING(pHint->HintActivityName()); - const char *cSpace = strchr( pSequenceOrActivity, ' ' ); - if ( cSpace ) - { - if ( !Q_strncmp( cSpace+1, "teleport", 8 ) ) - { - // Node is a teleport node, so it's good - return true; - } - } - - // Check for clearance - trace_t tr; - AI_TraceHull( pHint->GetAbsOrigin(), pHint->GetAbsOrigin(), GetOuter()->WorldAlignMins(), GetOuter()->WorldAlignMaxs(), MASK_SOLID, GetOuter(), COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction == 1.0 ) - return true; - - // Report failures - if ( ai_debug_actbusy.GetInt() == 3 && GetOuter()->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT ) - { - NDebugOverlay::Text( pHint->GetAbsOrigin(), "Node isn't clear.", false, 60 ); - NDebugOverlay::Box( pHint->GetAbsOrigin(), GetOuter()->WorldAlignMins(), GetOuter()->WorldAlignMaxs(), 255,0,0, 8, 2.0 ); - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_ActBusyBehavior::CanSelectSchedule( void ) -{ - // Always active when we're busy - if ( m_bBusy || m_bForceActBusy || m_bNeedsToPlayExitAnim ) - return true; - - if ( !m_bEnabled ) - return false; - - if ( m_flDeferUntil > gpGlobals->curtime ) - return false; - - if ( CountEnemiesInSafeZone() > 0 ) - { - // I have enemies left in the safe zone. Actbusy isn't appropriate. - // I should be off fighting them. - return false; - } - - if ( !IsCurScheduleOverridable() ) - return false; - - // Don't select actbusy if we're not going to search for a node anyway - return (m_flNextBusySearchTime < gpGlobals->curtime); -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if the current schedule is one that ActBusy is allowed to override -//----------------------------------------------------------------------------- -bool CAI_ActBusyBehavior::IsCurScheduleOverridable( void ) -{ - if( IsCombatActBusy() ) - { - // The whole point of a combat actbusy is that it can run in any state (including combat) - // the only exception is SCRIPT (sjb) - return (GetOuter()->GetState() != NPC_STATE_SCRIPT); - } - - // Act busies are not valid inside of a vehicle - if ( GetOuter()->IsInAVehicle() ) - return false; - - // Only if we're about to idle (or SCHED_NONE to catch newly spawned guys) - return ( IsCurSchedule( SCHED_IDLE_STAND ) || IsCurSchedule( SCHED_NONE ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pSound - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_ActBusyBehavior::ShouldIgnoreSound( CSound *pSound ) -{ - // If we're busy in an actbusy anim that's an ambush, stay mum as long as we can - if ( m_bBusy ) - { - busyanim_t *pBusyAnim = g_ActBusyAnimDataSystem.GetBusyAnim( m_iCurrentBusyAnim ); - - if( pBusyAnim && pBusyAnim->iBusyInterruptType == BA_INT_ZOMBIESLUMP ) - { - // Slumped zombies are deaf. - return true; - } - - if ( pBusyAnim && ( pBusyAnim->iBusyInterruptType == BA_INT_AMBUSH ) || ( pBusyAnim->iBusyInterruptType == BA_INT_COMBAT ) ) - { - /* - // Robin: First version ignored sounds in front of the NPC. - Vector vecToSound = (pSound->GetSoundReactOrigin() - GetAbsOrigin()); - vecToSound.z = 0; - VectorNormalize( vecToSound ); - Vector facingDir = GetOuter()->EyeDirection2D(); - if ( DotProduct( vecToSound, facingDir ) > 0 ) - return true; - */ - - // Ignore sounds that aren't visible - if ( !GetOuter()->FVisible( pSound->GetSoundReactOrigin() ) ) - return true; - } - } - - return BaseClass::ShouldIgnoreSound( pSound ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ActBusyBehavior::OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker ) -{ - if( IsCombatActBusy() && pSquadmate->IsPlayer() && IsInSafeZone( pAttacker ) ) - { - SetCondition( COND_ACTBUSY_AWARE_OF_ENEMY_IN_SAFE_ZONE ); // Break the actbusy, if we're running it. - m_flDeferUntil = gpGlobals->curtime + 4.0f; // Stop actbusying and go deal with that enemy!! - } - - BaseClass::OnFriendDamaged( pSquadmate, pAttacker ); -} - -//----------------------------------------------------------------------------- -// Purpose: Count the number of enemies of mine that are inside my safe zone -// volume. -// -// NOTE: We keep this count to prevent the NPC re-entering combat -// actbusy whilst too many enemies are present in the safe zone. -// This count does not automatically alert the NPC that there are -// enemies in the safe zone. -// You must set COND_ACTBUSY_AWARE_OF_ENEMY_IN_SAFE_ZONE to let -// the NPC know. -//----------------------------------------------------------------------------- -int CAI_ActBusyBehavior::CountEnemiesInSafeZone() -{ - if( !IsCombatActBusy() ) - { - return 0; - } - - // Grovel the AI list and count the enemies in the zone. By enemies, I mean - // anyone that I would fight if I saw. - CAI_BaseNPC ** ppAIs = g_AI_Manager.AccessAIs(); - int nAIs = g_AI_Manager.NumAIs(); - int count = 0; - - for ( int i = 0; i < nAIs; i++ ) - { - if( GetOuter()->IRelationType(ppAIs[i]) < D_LI ) - { - if( IsInSafeZone(ppAIs[i]) ) - { - count++; - } - } - } - - return count; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CAI_ActBusyBehavior::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - if( IsCombatActBusy() && info.GetAttacker() && IsInSafeZone( info.GetAttacker() ) ) - { - SetCondition( COND_ACTBUSY_AWARE_OF_ENEMY_IN_SAFE_ZONE ); // Break the actbusy, if we're running it. - m_flDeferUntil = gpGlobals->curtime + 4.0f; // Stop actbusying and go deal with that enemy!! - } - - return BaseClass::OnTakeDamage_Alive( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ActBusyBehavior::GatherConditions( void ) -{ - // Clear this condition before we call up, since the look sensing code will run and - // set this condition if it is relevant. - if( !IsCurSchedule(SCHED_ACTBUSY_BUSY, false) ) - { - // Only clear this condition when we aren't busying. We want it to be sticky - // during that time so that schedule selection works properly (sjb) - ClearCondition( COND_ACTBUSY_ENEMY_TOO_CLOSE ); - } - - BaseClass::GatherConditions(); - - bool bCheckLOS = true; - bool bCheckFOV = true; - - if( m_hActBusyGoal && m_hActBusyGoal->m_iSightMethod == ACTBUSY_SIGHT_METHOD_LOS_ONLY ) - { - bCheckFOV = false; - } - - // If we have a see entity, make sure we can still see it - if ( m_hSeeEntity && m_bBusy ) - { - if ( (!bCheckFOV||GetOuter()->FInViewCone(m_hSeeEntity)) && GetOuter()->QuerySeeEntity(m_hSeeEntity) && (!bCheckLOS||GetOuter()->FVisible(m_hSeeEntity)) ) - { - m_fTimeLastSawSeeEntity = gpGlobals->curtime; - ClearCondition( COND_ACTBUSY_LOST_SEE_ENTITY ); - } - else if( m_hActBusyGoal ) - { - float fDelta = gpGlobals->curtime - m_fTimeLastSawSeeEntity; - if( fDelta >= m_hActBusyGoal->m_flSeeEntityTimeout ) - { - SetCondition( COND_ACTBUSY_LOST_SEE_ENTITY ); - m_hActBusyGoal->NPCLostSeeEntity( GetOuter() ); - - if( IsCombatActBusy() && (GetOuter()->Classify() == CLASS_PLAYER_ALLY_VITAL && m_hSeeEntity->IsPlayer()) ) - { - // Defer any actbusying for several seconds. This serves as a heuristic for waiting - // for the player to settle after moving out of the room. This helps Alyx pick a more - // pertinent Actbusy near the player's new location. - m_flDeferUntil = gpGlobals->curtime + 4.0f; - } - } - } - } - else - { - ClearCondition( COND_ACTBUSY_LOST_SEE_ENTITY ); - } - - // If we're busy, ignore sounds depending on our actbusy break rules - if ( m_bBusy ) - { - busyanim_t *pBusyAnim = g_ActBusyAnimDataSystem.GetBusyAnim( m_iCurrentBusyAnim ); - if ( pBusyAnim ) - { - switch( pBusyAnim->iBusyInterruptType ) - { - case BA_INT_DANGER: - break; - - case BA_INT_AMBUSH: - break; - - case BA_INT_ZOMBIESLUMP: - { - ClearCondition( COND_HEAR_PLAYER ); - ClearCondition( COND_SEE_ENEMY ); - ClearCondition( COND_NEW_ENEMY ); - - CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); - - if( pPlayer ) - { - float flDist = pPlayer->GetAbsOrigin().DistTo( GetAbsOrigin() ); - - if( flDist <= 60 ) - { - StopBusying(); - } - } - } - break; - - case BA_INT_COMBAT: - // Ignore the player unless he shoots at us - ClearCondition( COND_HEAR_PLAYER ); - ClearCondition( COND_SEE_ENEMY ); - ClearCondition( COND_NEW_ENEMY ); - break; - - case BA_INT_PLAYER: - // Clear all but player. - ClearCondition( COND_HEAR_DANGER ); - ClearCondition( COND_HEAR_COMBAT ); - ClearCondition( COND_HEAR_WORLD ); - ClearCondition( COND_HEAR_BULLET_IMPACT ); - break; - - case BA_INT_SIEGE_DEFENSE: - ClearCondition( COND_HEAR_PLAYER ); - ClearCondition( COND_SEE_ENEMY ); - ClearCondition( COND_NEW_ENEMY ); - ClearCondition( COND_HEAR_COMBAT ); - ClearCondition( COND_HEAR_WORLD ); - ClearCondition( COND_HEAR_BULLET_IMPACT ); - break; - - case BA_INT_NONE: - // Clear all - ClearCondition( COND_HEAR_DANGER ); - ClearCondition( COND_HEAR_COMBAT ); - ClearCondition( COND_HEAR_WORLD ); - ClearCondition( COND_HEAR_BULLET_IMPACT ); - ClearCondition( COND_HEAR_PLAYER ); - break; - - default: - break; - } - } - } - - if( m_bAutoFireWeapon && random->RandomInt(0, 5) <= 3 ) - { - CBaseCombatWeapon *pWeapon = GetOuter()->GetActiveWeapon(); - - if( pWeapon ) - { - pWeapon->Operator_ForceNPCFire( GetOuter(), false ); - } - } - - if( ai_debug_actbusy.GetInt() == 5 ) - { - // Visualize them there Actbusy safe volumes - for( int i = 0 ; i < m_SafeZones.Count() ; i++ ) - { - busysafezone_t *pSafeZone = &m_SafeZones[i]; - - Vector vecBoxOrigin = (pSafeZone->vecMins + pSafeZone->vecMaxs) * 0.5f; - Vector vecBoxMins = vecBoxOrigin - pSafeZone->vecMins; - Vector vecBoxMaxs = vecBoxOrigin - pSafeZone->vecMaxs; - NDebugOverlay::Box( vecBoxOrigin, vecBoxMins, vecBoxMaxs, 255, 0, 255, 64, 0.2f ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ActBusyBehavior::EndScheduleSelection( void ) -{ - NotifyBusyEnding(); - - CheckAndCleanupOnExit(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : nActivity - -//----------------------------------------------------------------------------- -Activity CAI_ActBusyBehavior::NPC_TranslateActivity( Activity nActivity ) -{ - // Find out what the base class wants to do with the activity - Activity nNewActivity = BaseClass::NPC_TranslateActivity( nActivity ); - - if( nActivity == ACT_RUN ) - { - // FIXME: Forcing STIMULATED here is illegal if the entity doesn't support it as an activity - CAI_PlayerAlly *pAlly = dynamic_cast(GetOuter()); - if ( pAlly ) - return ACT_RUN_STIMULATED; - } - - // Else stay with the base class' decision. - return nNewActivity; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_ActBusyBehavior::HandleAnimEvent( animevent_t *pEvent ) -{ - if( pEvent->event == AE_ACTBUSY_WEAPON_FIRE_ON ) - { - m_bAutoFireWeapon = true; - return; - } - else if( pEvent->event == AE_ACTBUSY_WEAPON_FIRE_OFF ) - { - m_bAutoFireWeapon = false; - return; - } - - - return BaseClass::HandleAnimEvent( pEvent ); -} - -//----------------------------------------------------------------------------- -// Purpose: Actbusy's ending, ensure we haven't left NPC in broken state. -//----------------------------------------------------------------------------- -void CAI_ActBusyBehavior::CheckAndCleanupOnExit( void ) -{ - if ( m_bNeedsToPlayExitAnim && !GetOuter()->IsMarkedForDeletion() && GetOuter()->IsAlive() ) - { - Warning("NPC %s(%s) left actbusy without playing exit anim.\n", GetOuter()->GetDebugName(), GetOuter()->GetClassname() ); - m_bNeedsToPlayExitAnim = false; - } - - GetOuter()->RemoveFlag( FL_FLY ); - - // If we're supposed to use render bounds while inside the busy anim, restore normal now - if ( m_bUseRenderBoundsForCollision ) - { - GetOuter()->SetHullSizeNormal( true ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ActBusyBehavior::BuildScheduleTestBits( void ) -{ - BaseClass::BuildScheduleTestBits(); - - // When going to an actbusy, we can't be interrupted during the entry anim - if ( IsCurSchedule(SCHED_ACTBUSY_START_BUSYING) ) - { - if ( GetOuter()->GetTask()->iTask == TASK_ACTBUSY_PLAY_ENTRY ) - return; - - GetOuter()->SetCustomInterruptCondition( COND_PROVOKED ); - - if( IsCombatActBusy() ) - { - GetOuter()->SetCustomInterruptCondition( GetClassScheduleIdSpace()->ConditionLocalToGlobal(COND_ACTBUSY_ENEMY_TOO_CLOSE) ); - } - } - - // If we're in a queue, or leaving, we have no extra conditions - if ( m_bInQueue || IsCurSchedule( SCHED_ACTBUSY_LEAVE ) ) - return; - - // If we're not busy, or we're exiting a busy, we have no extra conditions - if ( !m_bBusy || IsCurSchedule( SCHED_ACTBUSY_STOP_BUSYING ) ) - return; - - busyanim_t *pBusyAnim = g_ActBusyAnimDataSystem.GetBusyAnim( m_iCurrentBusyAnim ); - if ( pBusyAnim ) - { - switch( pBusyAnim->iBusyInterruptType ) - { - case BA_INT_ZOMBIESLUMP: - { - GetOuter()->SetCustomInterruptCondition( COND_LIGHT_DAMAGE ); - GetOuter()->SetCustomInterruptCondition( COND_HEAVY_DAMAGE ); - } - break; - - case BA_INT_SIEGE_DEFENSE: - { - GetOuter()->SetCustomInterruptCondition( COND_HEAR_DANGER ); - GetOuter()->SetCustomInterruptCondition( GetClassScheduleIdSpace()->ConditionLocalToGlobal(COND_ACTBUSY_AWARE_OF_ENEMY_IN_SAFE_ZONE) ); - GetOuter()->SetCustomInterruptCondition( GetClassScheduleIdSpace()->ConditionLocalToGlobal(COND_ACTBUSY_ENEMY_TOO_CLOSE) ); - } - break; - - case BA_INT_AMBUSH: - case BA_INT_DANGER: - { - GetOuter()->SetCustomInterruptCondition( COND_LIGHT_DAMAGE ); - GetOuter()->SetCustomInterruptCondition( COND_HEAVY_DAMAGE ); - GetOuter()->SetCustomInterruptCondition( COND_HEAR_DANGER ); - GetOuter()->SetCustomInterruptCondition( COND_HEAR_COMBAT ); - GetOuter()->SetCustomInterruptCondition( COND_HEAR_BULLET_IMPACT ); - GetOuter()->SetCustomInterruptCondition( COND_NEW_ENEMY ); - GetOuter()->SetCustomInterruptCondition( COND_SEE_ENEMY ); - GetOuter()->SetCustomInterruptCondition( COND_PLAYER_ADDED_TO_SQUAD ); - GetOuter()->SetCustomInterruptCondition( COND_RECEIVED_ORDERS ); - break; - } - - case BA_INT_PLAYER: - { - GetOuter()->SetCustomInterruptCondition( COND_LIGHT_DAMAGE ); - GetOuter()->SetCustomInterruptCondition( COND_HEAVY_DAMAGE ); - GetOuter()->SetCustomInterruptCondition( COND_HEAR_DANGER ); - GetOuter()->SetCustomInterruptCondition( COND_HEAR_COMBAT ); - GetOuter()->SetCustomInterruptCondition( COND_HEAR_BULLET_IMPACT ); - GetOuter()->SetCustomInterruptCondition( COND_NEW_ENEMY ); - GetOuter()->SetCustomInterruptCondition( COND_PLAYER_ADDED_TO_SQUAD ); - GetOuter()->SetCustomInterruptCondition( COND_RECEIVED_ORDERS ); - - // The player can interrupt us - GetOuter()->SetCustomInterruptCondition( COND_SEE_PLAYER ); - break; - } - - case BA_INT_COMBAT: - { - GetOuter()->SetCustomInterruptCondition( COND_LIGHT_DAMAGE ); - GetOuter()->SetCustomInterruptCondition( COND_HEAVY_DAMAGE ); - GetOuter()->SetCustomInterruptCondition( COND_HEAR_DANGER ); - break; - } - - case BA_INT_NONE: - break; - - default: - break; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CAI_ActBusyBehavior::SelectScheduleForLeaving( void ) -{ - // Are we already near an exit node? - if ( GetHintNode() ) - { - if ( GetHintNode()->HintType() == HINT_NPC_EXIT_POINT ) - { - // Are we near it? If so, we're done. If not, move to it. - if ( UTIL_DistApprox( GetHintNode()->GetAbsOrigin(), GetAbsOrigin() ) < 64 ) - { - if ( !GetOuter()->IsMarkedForDeletion() ) - { - CBaseEntity *pOwner = GetOuter()->GetOwnerEntity(); - if ( pOwner ) - { - pOwner->DeathNotice( GetOuter() ); - GetOuter()->SetOwnerEntity( NULL ); - } - GetOuter()->SetThink( &CBaseEntity::SUB_Remove); //SUB_Remove) ; //GetOuter()->SUB_Remove ); - GetOuter()->SetNextThink( gpGlobals->curtime + 0.1 ); - - if ( m_hActBusyGoal ) - { - m_hActBusyGoal->NPCLeft( GetOuter() ); - } - } - - return SCHED_IDLE_STAND; - } - - return SCHED_ACTBUSY_LEAVE; - } - else - { - // Clear the node, it's no use to us - GetHintNode()->NPCStoppedUsing( GetOuter() ); - GetHintNode()->Unlock(); - SetHintNode( NULL ); - } - } - - // Find an exit node - CHintCriteria hintCriteria; - hintCriteria.SetHintType( HINT_NPC_EXIT_POINT ); - hintCriteria.SetFlag( bits_HINT_NODE_RANDOM | bits_HINT_NODE_CLEAR | bits_HINT_NODE_USE_GROUP ); - CAI_Hint *pNode = CAI_HintManager::FindHintRandom( GetOuter(), GetOuter()->GetAbsOrigin(), hintCriteria ); - if ( pNode ) - { - SetHintNode( pNode ); - return SCHED_ACTBUSY_LEAVE; - } - - // We've been told to leave, but we can't find an exit node. What to do? - return SCHED_IDLE_STAND; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CAI_ActBusyBehavior::SelectScheduleWhileNotBusy( int iBase ) -{ - // Randomly act busy (unless we're being forced, in which case we should search immediately) - if ( m_bForceActBusy || m_flNextBusySearchTime < gpGlobals->curtime ) - { - // If we're being forced, think again quickly - if ( m_bForceActBusy || IsCombatActBusy() ) - { - m_flNextBusySearchTime = gpGlobals->curtime + 2.0; - } - else - { - m_flNextBusySearchTime = gpGlobals->curtime + RandomFloat(ai_actbusy_search_time.GetFloat(), ai_actbusy_search_time.GetFloat()*2); - } - - // We may already have a node - bool bForceTeleport = false; - CAI_Hint *pNode = GetHintNode(); - if ( !pNode ) - { - if( IsCombatActBusy() ) - { - if ( m_hActBusyGoal->IsCombatActBusyTeleportAllowed() && m_iNumConsecutivePathFailures >= 2 && !AI_GetSinglePlayer()->FInViewCone(GetOuter()) ) - { - // Looks like I've tried several times to find a path to a valid hint node and - // haven't been able to. This means I'm on a patch of node graph that simply - // does not connect to any hint nodes that match my criteria. So try to find - // a node that's safe to teleport to. (sjb) ep2_outland_10 (Alyx) - // (Also, I must not be in the player's viewcone) - pNode = FindCombatActBusyTeleportHintNode(); - bForceTeleport = true; - } - else - { - pNode = FindCombatActBusyHintNode(); - } - } - else - { - pNode = FindActBusyHintNode(); - } - } - if ( pNode ) - { - // Ensure we've got a sequence for the node - const char *pSequenceOrActivity = STRING(pNode->HintActivityName()); - Activity iNodeActivity; - int iBusyAnim; - - // See if the node specifies that we should teleport to it - const char *cSpace = strchr( pSequenceOrActivity, ' ' ); - if ( cSpace ) - { - if ( !Q_strncmp( cSpace+1, "teleport", 8 ) ) - { - m_bTeleportToBusy = true; - } - - char sActOrSeqName[512]; - Q_strncpy( sActOrSeqName, pSequenceOrActivity, (cSpace-pSequenceOrActivity)+1 ); - iNodeActivity = (Activity)CAI_BaseNPC::GetActivityID( sActOrSeqName ); - iBusyAnim = g_ActBusyAnimDataSystem.FindBusyAnim( iNodeActivity, sActOrSeqName ); - } - else - { - iNodeActivity = (Activity)CAI_BaseNPC::GetActivityID( pSequenceOrActivity ); - iBusyAnim = g_ActBusyAnimDataSystem.FindBusyAnim( iNodeActivity, pSequenceOrActivity ); - } - - // Does this NPC have the activity or sequence for this node? - if ( HasAnimForActBusy( iBusyAnim, BA_BUSY ) ) - { - if ( HasCondition(COND_ACTBUSY_LOST_SEE_ENTITY) ) - { - // We've lost our see entity, which means we can't continue. - if ( m_bForceActBusy ) - { - // We were being told to act busy, which we can't do now that we've lost the see entity. - // Abort, and assume that the mapmaker will make us retry. - StopBusying(); - } - return iBase; - } - - m_iCurrentBusyAnim = iBusyAnim; - if ( m_iCurrentBusyAnim == -1 ) - return iBase; - - if ( ai_debug_actbusy.GetInt() == 4 ) - { - Msg("ACTBUSY: NPC %s (%s) found Actbusy node %s \n", GetOuter()->GetClassname(), GetOuter()->GetDebugName(), pNode->GetDebugName() ); - } - - if ( GetHintNode() ) - { - GetHintNode()->Unlock(); - } - - SetHintNode( pNode ); - if ( GetHintNode() && GetHintNode()->Lock( GetOuter() ) ) - { - if ( ai_debug_actbusy.GetInt() == 2 ) - { - // Show which actbusy we're moving towards - NDebugOverlay::Line( GetOuter()->WorldSpaceCenter(), pNode->GetAbsOrigin(), 0, 255, 0, true, 5.0 ); - NDebugOverlay::Box( pNode->GetAbsOrigin(), GetOuter()->WorldAlignMins(), GetOuter()->WorldAlignMaxs(), 0, 255, 0, 64, 5.0 ); - } - - // Let our act busy know we're moving to a node - if ( m_hActBusyGoal ) - { - m_hActBusyGoal->NPCMovingToBusy( GetOuter() ); - } - - m_bMovingToBusy = true; - - if( m_hActBusyGoal && m_hActBusyGoal->m_iszSeeEntityName != NULL_STRING ) - { - // Set the see entity Handle if we have one. - m_hSeeEntity.Set( gEntList.FindEntityByName(NULL, m_hActBusyGoal->m_iszSeeEntityName) ); - } - - // At this point we know we're starting. - ClearCondition( COND_ACTBUSY_AWARE_OF_ENEMY_IN_SAFE_ZONE ); - - // If we're supposed to teleport, do that instead - if ( m_bTeleportToBusy ) - { - return SCHED_ACTBUSY_TELEPORT_TO_BUSY; - } - else if( bForceTeleport ) - { - // We found a place to go, so teleport there and forget that we ever had trouble. - m_iNumConsecutivePathFailures = 0; - return SCHED_ACTBUSY_TELEPORT_TO_BUSY; - } - - return SCHED_ACTBUSY_START_BUSYING; - } - } - } - else - { - // WE DIDN'T FIND A NODE! - if( IsCombatActBusy() ) - { - // Don't try again right away, not enough state will have changed. - // Just go do something useful for a few seconds. - m_flNextBusySearchTime = gpGlobals->curtime + 10.0; - } - } - } - - return SCHED_NONE; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CAI_ActBusyBehavior::SelectScheduleWhileBusy( void ) -{ - // Are we supposed to stop on our current actbusy, but stay in the actbusy state? - if ( !ActBusyNodeStillActive() || (m_flEndBusyAt && gpGlobals->curtime >= m_flEndBusyAt) ) - { - if ( ai_debug_actbusy.GetInt() == 4 ) - { - Msg("ACTBUSY: NPC %s (%s) ending actbusy.\n", GetOuter()->GetClassname(), GetOuter()->GetDebugName() ); - } - - StopBusying(); - return SCHED_ACTBUSY_STOP_BUSYING; - } - - if( IsCombatActBusy() && (HasCondition(COND_ACTBUSY_AWARE_OF_ENEMY_IN_SAFE_ZONE) || HasCondition(COND_ACTBUSY_ENEMY_TOO_CLOSE)) ) - { - return SCHED_ACTBUSY_STOP_BUSYING; - } - - return SCHED_ACTBUSY_BUSY; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CAI_ActBusyBehavior::SelectSchedule() -{ - int iBase = BaseClass::SelectSchedule(); - - // Only do something if the base ai doesn't want to do anything - if ( !IsCombatActBusy() && !m_bForceActBusy && iBase != SCHED_IDLE_STAND ) - { - // If we're busy, we need to get out of it first - if ( m_bBusy ) - return SCHED_ACTBUSY_STOP_BUSYING; - - CheckAndCleanupOnExit(); - return iBase; - } - - // If we're supposed to be leaving, find a leave node and exit - if ( m_bLeaving ) - return SelectScheduleForLeaving(); - - // NPCs should not be busy if the actbusy behaviour has been disabled, or if they've received player squad commands - bool bShouldNotBeBusy = (!m_bEnabled || HasCondition( COND_PLAYER_ADDED_TO_SQUAD ) || HasCondition( COND_RECEIVED_ORDERS ) ); - if ( bShouldNotBeBusy ) - { - if ( !GetOuter()->IsMarkedForDeletion() && GetOuter()->IsAlive() ) - return SCHED_ACTBUSY_STOP_BUSYING; - } - else - { - if ( m_bBusy ) - return SelectScheduleWhileBusy(); - - // I'm not busy, and I'm supposed to be - int schedule = SelectScheduleWhileNotBusy( iBase ); - if ( schedule != SCHED_NONE ) - return schedule; - } - - CheckAndCleanupOnExit(); - return iBase; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_ActBusyBehavior::ActBusyNodeStillActive( void ) -{ - if ( !GetHintNode() ) - return false; - - return ( GetHintNode()->IsDisabled() == false ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_ActBusyBehavior::IsInterruptable( void ) -{ - if ( IsActive() ) - return false; - - return BaseClass::IsInterruptable(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_ActBusyBehavior::CanFlinch( void ) -{ - if ( m_bNeedsToPlayExitAnim ) - return false; - - return BaseClass::CanFlinch(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_ActBusyBehavior::CanRunAScriptedNPCInteraction( bool bForced ) -{ - // Prevent interactions during actbusy modes - if ( IsActive() ) - return false; - - return BaseClass::CanRunAScriptedNPCInteraction( bForced ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ActBusyBehavior::OnScheduleChange() -{ - if( IsCurSchedule(SCHED_ACTBUSY_BUSY, false) ) - { - if( HasCondition(COND_SEE_ENEMY) ) - { - m_bExitedBusyToDueSeeEnemy = true; - } - - if( HasCondition(COND_ACTBUSY_LOST_SEE_ENTITY) ) - { - m_bExitedBusyToDueLostSeeEntity = true; - } - } - - BaseClass::OnScheduleChange(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_ActBusyBehavior::QueryHearSound( CSound *pSound ) -{ - // Ignore friendly created combat sounds while in an actbusy. - // Fixes friendly NPCs going in & out of actbusies when the - // player fires shots at their feet. - if ( pSound->IsSoundType( SOUND_COMBAT ) || pSound->IsSoundType( SOUND_BULLET_IMPACT ) ) - { - if ( GetOuter()->IRelationType( pSound->m_hOwner ) == D_LI ) - return false; - } - - return BaseClass::QueryHearSound( pSound ); -} - -//----------------------------------------------------------------------------- -// Purpose: Because none of the startbusy schedules break on COND_NEW_ENEMY -// we have to do this distance check against all enemy NPCs we -// see as we're traveling to an ACTBUSY node -//----------------------------------------------------------------------------- -#define ACTBUSY_ENEMY_TOO_CLOSE_DIST_SQR Square(240) // 20 feet -void CAI_ActBusyBehavior::OnSeeEntity( CBaseEntity *pEntity ) -{ - BaseClass::OnSeeEntity( pEntity ); - - if( IsCombatActBusy() && GetOuter()->IRelationType(pEntity) < D_LI ) - { - if( pEntity->GetAbsOrigin().DistToSqr( GetAbsOrigin() ) <= ACTBUSY_ENEMY_TOO_CLOSE_DIST_SQR ) - { - SetCondition( COND_ACTBUSY_ENEMY_TOO_CLOSE ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_ActBusyBehavior::ShouldPlayerAvoid( void ) -{ - if( IsCombatActBusy() ) - { - // Alyx is only allowed to push if she's getting into or out of an actbusy - // animation. She isn't allowed to shove you around while she's running around - if ( IsCurSchedule(SCHED_ACTBUSY_START_BUSYING) ) - { - if ( GetCurTask() && GetCurTask()->iTask == TASK_ACTBUSY_PLAY_ENTRY ) - return true; - } - else if ( IsCurSchedule(SCHED_ACTBUSY_STOP_BUSYING) ) - { - if ( GetCurTask() && GetCurTask()->iTask == TASK_ACTBUSY_PLAY_EXIT ) - return true; - } - } - else - { - if ( IsCurSchedule ( SCHED_ACTBUSY_START_BUSYING ) ) - { - if ( GetCurTask() && GetCurTask()->iTask == TASK_WAIT_FOR_MOVEMENT || GetOuter()->GetTask()->iTask == TASK_ACTBUSY_PLAY_ENTRY ) - return true; - } - else if ( IsCurSchedule(SCHED_ACTBUSY_STOP_BUSYING) ) - { - if ( GetCurTask() && GetCurTask()->iTask == TASK_ACTBUSY_PLAY_EXIT ) - return true; - } - } - - return BaseClass::ShouldPlayerAvoid(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_ActBusyBehavior::ComputeAndSetRenderBounds() -{ - Vector mins, maxs; - if ( GetOuter()->ComputeHitboxSurroundingBox( &mins, &maxs ) ) - { - UTIL_SetSize( GetOuter(), mins - GetAbsOrigin(), maxs - GetAbsOrigin()); - if ( GetOuter()->VPhysicsGetObject() ) - { - GetOuter()->SetupVPhysicsHull(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true if the current NPC is acting busy, or moving to an actbusy -//----------------------------------------------------------------------------- -bool CAI_ActBusyBehavior::IsActive( void ) -{ - return ( m_bBusy || m_bForceActBusy || m_bNeedsToPlayExitAnim || m_bLeaving ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CAI_ActBusyBehavior::IsCombatActBusy() -{ - if( m_hActBusyGoal != NULL ) - return (m_hActBusyGoal->GetType() == ACTBUSY_TYPE_COMBAT); - - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_ActBusyBehavior::CollectSafeZoneVolumes( CAI_ActBusyGoal *pActBusyGoal ) -{ - // Reset these, so we don't use a volume from a previous actbusy goal. - m_SafeZones.RemoveAll(); - - if( pActBusyGoal->m_iszSafeZoneVolume != NULL_STRING ) - { - CBaseEntity *pVolume = gEntList.FindEntityByName( NULL, pActBusyGoal->m_iszSafeZoneVolume ); - - while( pVolume != NULL ) - { - busysafezone_t newSafeZone; - pVolume->CollisionProp()->WorldSpaceAABB( &newSafeZone.vecMins, &newSafeZone.vecMaxs ); - m_SafeZones.AddToTail( newSafeZone ); - pVolume = gEntList.FindEntityByName( pVolume, pActBusyGoal->m_iszSafeZoneVolume ); - } - } - - if( ai_debug_actbusy.GetInt() == 5 ) - { - Msg( "Actbusy collected %d safe zones\n", m_SafeZones.Count() ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CAI_ActBusyBehavior::IsInSafeZone( CBaseEntity *pEntity ) -{ - Vector vecLocation = pEntity->WorldSpaceCenter(); - - for( int i = 0 ; i < m_SafeZones.Count() ; i++ ) - { - busysafezone_t *pSafeZone = &m_SafeZones[i]; - - if( vecLocation.x > pSafeZone->vecMins.x && - vecLocation.y > pSafeZone->vecMins.y && - vecLocation.z > pSafeZone->vecMins.z && - - vecLocation.x < pSafeZone->vecMaxs.x && - vecLocation.y < pSafeZone->vecMaxs.y && - vecLocation.z < pSafeZone->vecMaxs.z ) - { - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if this NPC has the anims required to use the specified actbusy hint -//----------------------------------------------------------------------------- -bool CAI_ActBusyBehavior::HasAnimForActBusy( int iActBusy, busyanimparts_t AnimPart ) -{ - if ( iActBusy == -1 ) - return false; - - busyanim_t *pBusyAnim = g_ActBusyAnimDataSystem.GetBusyAnim( iActBusy ); - if ( !pBusyAnim ) - return false; - - // Try and play the sequence first - if ( pBusyAnim->iszSequences[AnimPart] != NULL_STRING ) - return (GetOuter()->LookupSequence( (char*)STRING(pBusyAnim->iszSequences[AnimPart]) ) != ACTIVITY_NOT_AVAILABLE); - - // Try and play the activity second - if ( pBusyAnim->iActivities[AnimPart] != ACT_INVALID ) - return GetOuter()->HaveSequenceForActivity( pBusyAnim->iActivities[AnimPart] ); - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Play the sound associated with the specified part of the current actbusy, if any -//----------------------------------------------------------------------------- -void CAI_ActBusyBehavior::PlaySoundForActBusy( busyanimparts_t AnimPart ) -{ - busyanim_t *pBusyAnim = g_ActBusyAnimDataSystem.GetBusyAnim( m_iCurrentBusyAnim ); - if ( !pBusyAnim ) - return; - - // Play the sound - if ( pBusyAnim->iszSounds[AnimPart] != NULL_STRING ) - { - // See if we can treat it as a game sound name - CSoundParameters params; - if ( GetOuter()->GetParametersForSound( STRING(pBusyAnim->iszSounds[AnimPart]), params, STRING(GetOuter()->GetModelName()) ) ) - { - CPASAttenuationFilter filter( GetOuter() ); - GetOuter()->EmitSound( filter, GetOuter()->entindex(), params ); - } - else - { - // Assume it's a response concept, and try to speak it - CAI_Expresser *pExpresser = GetOuter()->GetExpresser(); - if ( pExpresser ) - { - const char *concept = STRING(pBusyAnim->iszSounds[AnimPart]); - - // Must be able to speak the concept - if ( !pExpresser->IsSpeaking() && pExpresser->CanSpeakConcept( concept ) ) - { - pExpresser->Speak( concept ); - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Play a sequence or activity for the current actbusy -//----------------------------------------------------------------------------- -bool CAI_ActBusyBehavior::PlayAnimForActBusy( busyanimparts_t AnimPart ) -{ - busyanim_t *pBusyAnim = g_ActBusyAnimDataSystem.GetBusyAnim( m_iCurrentBusyAnim ); - if ( !pBusyAnim ) - return false; - - // Try and play the sequence first - if ( pBusyAnim->iszSequences[AnimPart] != NULL_STRING ) - { - GetOuter()->SetSequenceByName( (char*)STRING(pBusyAnim->iszSequences[AnimPart]) ); - GetOuter()->SetIdealActivity( ACT_DO_NOT_DISTURB ); - return true; - } - - // Try and play the activity second - if ( pBusyAnim->iActivities[AnimPart] != ACT_INVALID ) - { - GetOuter()->SetIdealActivity( pBusyAnim->iActivities[AnimPart] ); - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ActBusyBehavior::StartTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_ACTBUSY_PLAY_BUSY_ANIM: - { - // If we're not enabled here, it's due to the actbusy being deactivated during - // the NPC's entry animation. We can't abort in the middle of the entry, so we - // arrive here with a disabled actbusy behaviour. Exit gracefully. - if ( !m_bEnabled ) - { - TaskComplete(); - return; - } - - // Set the flag to remind the code to recompute the NPC's box from render bounds. - // This is used to delay the process so that we don't get a box built from render bounds - // when a character is still interpolating to their busy pose. - m_bNeedToSetBounds = true; - - // Get the busyanim for the specified activity - busyanim_t *pBusyAnim = g_ActBusyAnimDataSystem.GetBusyAnim( m_iCurrentBusyAnim ); - - // We start "flying" so we don't collide with the world, in case the level - // designer has us sitting on a chair, etc. - if( !pBusyAnim || !pBusyAnim->bUseAutomovement ) - { - GetOuter()->AddFlag( FL_FLY ); - } - - GetOuter()->SetGroundEntity( NULL ); - - // Fail if we're not on the node & facing the correct way - // We only do this check if we're still moving to the busy. This will only - // be true if there was no entry animation for this busy. We do it this way - // because the entry code contains this same check, and so we assume we're - // valid even if we're off now, because some entry animations move the - // character off the node. - if ( m_bMovingToBusy ) - { - if ( UTIL_DistApprox( GetHintNode()->GetAbsOrigin(), GetAbsOrigin() ) > 16 || !GetOuter()->FacingIdeal() ) - { - TaskFail( "Not correctly on hintnode" ); - m_flEndBusyAt = gpGlobals->curtime; - return; - } - } - - m_bMovingToBusy = false; - - if ( !ActBusyNodeStillActive() ) - { - TaskFail( FAIL_NO_HINT_NODE ); - return; - } - - // Have we just started using this node? - if ( !m_bBusy ) - { - m_bBusy = true; - - GetHintNode()->NPCStartedUsing( GetOuter() ); - if ( m_hActBusyGoal ) - { - m_hActBusyGoal->NPCStartedBusy( GetOuter() ); - } - - if ( pBusyAnim ) - { - float flMaxTime = pBusyAnim->flMaxTime; - float flMinTime = pBusyAnim->flMinTime; - - // Mapmaker input may have specified it's own max time - if ( m_bForceActBusy && m_flForcedMaxTime != NO_MAX_TIME ) - { - flMaxTime = m_flForcedMaxTime; - - // Don't let non-unlimited time amounts be less than the mintime - if ( flMaxTime && flMaxTime < flMinTime ) - { - flMinTime = flMaxTime; - } - } - - // If we have no max time, or we're in a queue, we loop forever. - if ( !flMaxTime || m_bInQueue ) - { - m_flEndBusyAt = 0; - GetOuter()->SetWait( 99999 ); - } - else - { - float flTime = RandomFloat(flMinTime, flMaxTime); - m_flEndBusyAt = gpGlobals->curtime + flTime; - GetOuter()->SetWait( flTime ); - } - } - } - - // Start playing the act busy - PlayAnimForActBusy( BA_BUSY ); - PlaySoundForActBusy( BA_BUSY ); - - // Now that we're busy, we don't need to be forced anymore - m_bForceActBusy = false; - m_bTeleportToBusy = false; - m_bUseNearestBusy = false; - m_ForcedActivity = ACT_INVALID; - - // If we're supposed to use render bounds while inside the busy anim, do so - if ( m_bUseRenderBoundsForCollision ) - { - ComputeAndSetRenderBounds(); - } - } - break; - - case TASK_ACTBUSY_PLAY_ENTRY: - { - // We start "flying" so we don't collide with the world, in case the level - // designer has us sitting on a chair, etc. - - // Get the busyanim for the specified activity - busyanim_t *pBusyAnim = g_ActBusyAnimDataSystem.GetBusyAnim( m_iCurrentBusyAnim ); - - // We start "flying" so we don't collide with the world, in case the level - // designer has us sitting on a chair, etc. - if( !pBusyAnim || !pBusyAnim->bUseAutomovement ) - { - GetOuter()->AddFlag( FL_FLY ); - } - - GetOuter()->SetGroundEntity( NULL ); - - m_bMovingToBusy = false; - m_bNeedsToPlayExitAnim = HasAnimForActBusy( m_iCurrentBusyAnim, BA_EXIT ); - - if ( !ActBusyNodeStillActive() ) - { - TaskFail( FAIL_NO_HINT_NODE ); - return; - } - - // Fail if we're not on the node & facing the correct way - if ( UTIL_DistApprox( GetHintNode()->GetAbsOrigin(), GetAbsOrigin() ) > 16 || !GetOuter()->FacingIdeal() ) - { - m_bBusy = false; - TaskFail( "Not correctly on hintnode" ); - return; - } - - PlaySoundForActBusy( BA_ENTRY ); - - // Play the entry animation. If it fails, we don't have an entry anim, so complete immediately. - if ( !PlayAnimForActBusy( BA_ENTRY ) ) - { - TaskComplete(); - } - } - break; - - case TASK_ACTBUSY_VERIFY_EXIT: - { - // NPC's that changed their bounding box must ensure that they can restore their regular box - // before they exit their actbusy. This task is designed to delay until that time if necessary. - if( !m_bUseRenderBoundsForCollision ) - { - // Don't bother if we didn't alter our BBox. - TaskComplete(); - break; - } - - // Set up a timer to check immediately. - GetOuter()->SetWait( 0 ); - } - break; - - case TASK_ACTBUSY_PLAY_EXIT: - { - // If we're supposed to use render bounds while inside the busy anim, restore normal now - if ( m_bUseRenderBoundsForCollision ) - { - GetOuter()->SetHullSizeNormal( true ); - } - - if ( m_hActBusyGoal ) - { - m_hActBusyGoal->NPCStartedLeavingBusy( GetOuter() ); - } - - PlaySoundForActBusy( BA_EXIT ); - - // Play the exit animation. If it fails, we don't have an entry anim, so complete immediately. - if ( !PlayAnimForActBusy( BA_EXIT ) ) - { - m_bNeedsToPlayExitAnim = false; - GetOuter()->RemoveFlag( FL_FLY ); - NotifyBusyEnding(); - TaskComplete(); - } - } - break; - - case TASK_ACTBUSY_TELEPORT_TO_BUSY: - { - if ( !ActBusyNodeStillActive() ) - { - TaskFail( FAIL_NO_HINT_NODE ); - return; - } - - Vector vecAbsOrigin = GetHintNode()->GetAbsOrigin(); - QAngle vecAbsAngles = GetHintNode()->GetAbsAngles(); - GetOuter()->Teleport( &vecAbsOrigin, &vecAbsAngles, NULL ); - GetOuter()->GetMotor()->SetIdealYaw( vecAbsAngles.y ); - - TaskComplete(); - } - break; - - case TASK_ACTBUSY_WALK_PATH_TO_BUSY: - { - // If we have a forced activity, use that. Otherwise, walk. - if ( m_ForcedActivity != ACT_INVALID && m_ForcedActivity != ACT_RESET ) - { - GetNavigator()->SetMovementActivity( m_ForcedActivity ); - - // Cover is void once I move - Forget( bits_MEMORY_INCOVER ); - - TaskComplete(); - } - else - { - if( IsCombatActBusy() ) - { - ChainStartTask( TASK_RUN_PATH ); - } - else - { - ChainStartTask( TASK_WALK_PATH ); - } - } - break; - } - - case TASK_ACTBUSY_GET_PATH_TO_ACTBUSY: - { - ChainStartTask( TASK_GET_PATH_TO_HINTNODE ); - - if ( !HasCondition(COND_TASK_FAILED) ) - { - // We successfully built a path, so stop counting consecutive failures. - m_iNumConsecutivePathFailures = 0; - - // Set the arrival sequence for the actbusy to be the busy sequence, if we don't have an entry animation - busyanim_t *pBusyAnim = g_ActBusyAnimDataSystem.GetBusyAnim( m_iCurrentBusyAnim ); - if ( pBusyAnim && pBusyAnim->iszSequences[BA_ENTRY] == NULL_STRING && pBusyAnim->iActivities[BA_ENTRY] == ACT_INVALID ) - { - // Try and play the sequence first - if ( pBusyAnim->iszSequences[BA_BUSY] != NULL_STRING ) - { - GetNavigator()->SetArrivalSequence( GetOuter()->LookupSequence( STRING(pBusyAnim->iszSequences[BA_BUSY]) ) ); - } - else if ( pBusyAnim->iActivities[BA_BUSY] != ACT_INVALID ) - { - // Try and play the activity second - GetNavigator()->SetArrivalActivity( pBusyAnim->iActivities[BA_BUSY] ); - } - } - else - { - // Robin: Set the arrival sequence / activity to be the entry animation. - if ( pBusyAnim->iszSequences[BA_ENTRY] != NULL_STRING ) - { - GetNavigator()->SetArrivalSequence( GetOuter()->LookupSequence( STRING(pBusyAnim->iszSequences[BA_ENTRY]) ) ); - } - else if ( pBusyAnim->iActivities[BA_ENTRY] != ACT_INVALID ) - { - // Try and play the activity second - GetNavigator()->SetArrivalActivity( pBusyAnim->iActivities[BA_ENTRY] ); - } - } - } - else - { - m_iNumConsecutivePathFailures++; - - if ( ai_debug_actbusy.GetInt() == 1 ) - { - if ( GetHintNode() ) - { - // Show which actbusy we're moving towards - NDebugOverlay::Line( GetOuter()->WorldSpaceCenter(), GetHintNode()->GetAbsOrigin(), 255, 0, 0, true, 1.0 ); - } - } - } - - break; - } - - default: - BaseClass::StartTask( pTask); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ActBusyBehavior::RunTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_WAIT_FOR_MOVEMENT: - { - // Ensure the hint node hasn't been disabled - if ( IsCurSchedule( SCHED_ACTBUSY_START_BUSYING ) ) - { - if ( !ActBusyNodeStillActive() ) - { - TaskFail(FAIL_NO_HINT_NODE); - return; - } - } - - if ( ai_debug_actbusy.GetInt() == 1 ) - { - if ( GetHintNode() ) - { - // Show which actbusy we're moving towards - NDebugOverlay::Line( GetOuter()->WorldSpaceCenter(), GetHintNode()->GetAbsOrigin(), 0, 255, 0, true, 0.2 ); - } - } - - BaseClass::RunTask( pTask ); - break; - } - - case TASK_ACTBUSY_PLAY_BUSY_ANIM: - { - if( m_bUseRenderBoundsForCollision ) - { - if( GetOuter()->IsSequenceFinished() && m_bNeedToSetBounds ) - { - ComputeAndSetRenderBounds(); - m_bNeedToSetBounds = false; - } - } - - if( IsCombatActBusy() ) - { - if( GetEnemy() != NULL && !HasCondition(COND_ENEMY_OCCLUDED) ) - { - // Break a combat actbusy if an enemy gets very close. - // I'll probably go to hell for not doing this with conditions like I should. (sjb) - float flDistSqr = GetAbsOrigin().DistToSqr( GetEnemy()->GetAbsOrigin() ); - - if( flDistSqr < Square(12.0f * 15.0f) ) - { - // End now. - m_flEndBusyAt = gpGlobals->curtime; - TaskComplete(); - return; - } - } - } - - GetOuter()->AutoMovement(); - // Stop if the node's been disabled - if ( !ActBusyNodeStillActive() || GetOuter()->IsWaitFinished() ) - { - TaskComplete(); - } - else - { - CAI_PlayerAlly *pAlly = dynamic_cast(GetOuter()); - if ( pAlly ) - { - pAlly->SelectInterjection(); - } - - if( HasCondition(COND_ACTBUSY_LOST_SEE_ENTITY) ) - { - StopBusying(); - TaskComplete(); - } - } - break; - } - - case TASK_ACTBUSY_PLAY_ENTRY: - { - GetOuter()->AutoMovement(); - if ( !ActBusyNodeStillActive() || GetOuter()->IsSequenceFinished() ) - { - TaskComplete(); - } - } - break; - - case TASK_ACTBUSY_VERIFY_EXIT: - { - if( GetOuter()->IsWaitFinished() ) - { - // Trace my normal hull over this spot to see if I'm able to stand up right now. - trace_t tr; - CTraceFilterOnlyNPCsAndPlayer filter( GetOuter(), COLLISION_GROUP_NONE ); - UTIL_TraceHull( GetOuter()->GetAbsOrigin(), GetOuter()->GetAbsOrigin(), NAI_Hull::Mins( HULL_HUMAN ), NAI_Hull::Maxs( HULL_HUMAN ), MASK_NPCSOLID, &filter, &tr ); - - if( tr.startsolid ) - { - // Blocked. Try again later. - GetOuter()->SetWait( 1.0f ); - } - else - { - // Put an entity blocker here for a moment until I get into my bounding box. - CBaseEntity *pBlocker = CEntityBlocker::Create( GetOuter()->GetAbsOrigin(), NAI_Hull::Mins( HULL_HUMAN ), NAI_Hull::Maxs( HULL_HUMAN ), GetOuter(), true ); - g_EventQueue.AddEvent( pBlocker, "Kill", 1.0, GetOuter(), GetOuter() ); - TaskComplete(); - } - } - } - break; - - case TASK_ACTBUSY_PLAY_EXIT: - { - GetOuter()->AutoMovement(); - if ( GetOuter()->IsSequenceFinished() ) - { - m_bNeedsToPlayExitAnim = false; - GetOuter()->RemoveFlag( FL_FLY ); - NotifyBusyEnding(); - TaskComplete(); - } - } - break; - - default: - BaseClass::RunTask( pTask); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ActBusyBehavior::NotifyBusyEnding( void ) -{ - // Be sure to disable autofire - m_bAutoFireWeapon = false; - - // Clear the hintnode if we're done with it - if ( GetHintNode() ) - { - if ( m_bBusy || m_bMovingToBusy ) - { - GetHintNode()->NPCStoppedUsing( GetOuter() ); - } - - GetHintNode()->Unlock(); - - if( IsCombatActBusy() ) - { - // Don't allow anyone to use this node for a bit. This is so the tactical position - // doesn't get re-occupied the moment I leave it. - GetHintNode()->DisableForSeconds( random->RandomFloat( 10, 15) ); - } - - SetHintNode( NULL ); - } - - // Then, if we were busy, stop being busy - if ( m_bBusy ) - { - m_bBusy = false; - - if ( m_hActBusyGoal ) - { - m_hActBusyGoal->NPCFinishedBusy( GetOuter() ); - - if ( m_bExitedBusyToDueLostSeeEntity ) - { - m_hActBusyGoal->NPCLostSeeEntity( GetOuter() ); - m_bExitedBusyToDueLostSeeEntity = false; - } - - if ( m_bExitedBusyToDueSeeEnemy ) - { - m_hActBusyGoal->NPCSeeEnemy( GetOuter() ); - m_bExitedBusyToDueSeeEnemy = false; - } - } - } - else if ( m_bMovingToBusy && m_hActBusyGoal ) - { - // Or if we were just on our way to be busy, let the goal know - m_hActBusyGoal->NPCAbortedMoveTo( GetOuter() ); - } - - // Don't busy again for a while - m_flEndBusyAt = 0; - - if( IsCombatActBusy() ) - { - // Actbusy again soon. Real soon. - m_flNextBusySearchTime = gpGlobals->curtime; - } - else - { - m_flNextBusySearchTime = gpGlobals->curtime + (RandomFloat(ai_actbusy_search_time.GetFloat(), ai_actbusy_search_time.GetFloat()*2)); - } -} - -//------------------------------------- - -AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( CAI_ActBusyBehavior ) - - DECLARE_CONDITION( COND_ACTBUSY_LOST_SEE_ENTITY ) - DECLARE_CONDITION( COND_ACTBUSY_AWARE_OF_ENEMY_IN_SAFE_ZONE ) - DECLARE_CONDITION( COND_ACTBUSY_ENEMY_TOO_CLOSE ) - - DECLARE_TASK( TASK_ACTBUSY_PLAY_BUSY_ANIM ) - DECLARE_TASK( TASK_ACTBUSY_PLAY_ENTRY ) - DECLARE_TASK( TASK_ACTBUSY_PLAY_EXIT ) - DECLARE_TASK( TASK_ACTBUSY_TELEPORT_TO_BUSY ) - DECLARE_TASK( TASK_ACTBUSY_WALK_PATH_TO_BUSY ) - DECLARE_TASK( TASK_ACTBUSY_GET_PATH_TO_ACTBUSY ) - DECLARE_TASK( TASK_ACTBUSY_VERIFY_EXIT ) - - DECLARE_ANIMEVENT( AE_ACTBUSY_WEAPON_FIRE_ON ) - DECLARE_ANIMEVENT( AE_ACTBUSY_WEAPON_FIRE_OFF ) - - //--------------------------------- - - DEFINE_SCHEDULE - ( - SCHED_ACTBUSY_START_BUSYING, - - " Tasks" - " TASK_SET_TOLERANCE_DISTANCE 4" - " TASK_ACTBUSY_GET_PATH_TO_ACTBUSY 0" - " TASK_ACTBUSY_WALK_PATH_TO_BUSY 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_FACE_HINTNODE 0" - " TASK_ACTBUSY_PLAY_ENTRY 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_ACTBUSY_BUSY" - "" - " Interrupts" - " COND_ACTBUSY_LOST_SEE_ENTITY" - ) - - DEFINE_SCHEDULE - ( - SCHED_ACTBUSY_BUSY, - - " Tasks" - " TASK_ACTBUSY_PLAY_BUSY_ANIM 0" - "" - " Interrupts" - " COND_PROVOKED" - ) - - DEFINE_SCHEDULE - ( - SCHED_ACTBUSY_STOP_BUSYING, - - " Tasks" - " TASK_ACTBUSY_VERIFY_EXIT 0" - " TASK_ACTBUSY_PLAY_EXIT 0" - " TASK_WAIT 0.1" - "" - " Interrupts" - " COND_NO_CUSTOM_INTERRUPTS" - ) - - DEFINE_SCHEDULE - ( - SCHED_ACTBUSY_LEAVE, - - " Tasks" - " TASK_SET_TOLERANCE_DISTANCE 4" - " TASK_ACTBUSY_GET_PATH_TO_ACTBUSY 0" - " TASK_ACTBUSY_WALK_PATH_TO_BUSY 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_PROVOKED" - ) - - DEFINE_SCHEDULE - ( - SCHED_ACTBUSY_TELEPORT_TO_BUSY, - - " Tasks" - " TASK_ACTBUSY_TELEPORT_TO_BUSY 0" - " TASK_ACTBUSY_PLAY_ENTRY 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_ACTBUSY_BUSY" - "" - " Interrupts" - " COND_PROVOKED" - ) - -AI_END_CUSTOM_SCHEDULE_PROVIDER() - - -//========================================================================================================== -// ACT BUSY GOALS -//========================================================================================================== -//----------------------------------------------------------------------------- -// Purpose: A level tool to control the actbusy behavior. -//----------------------------------------------------------------------------- -LINK_ENTITY_TO_CLASS( ai_goal_actbusy, CAI_ActBusyGoal ); - -BEGIN_DATADESC( CAI_ActBusyGoal ) - DEFINE_KEYFIELD( m_flBusySearchRange, FIELD_FLOAT, "busysearchrange" ), - DEFINE_KEYFIELD( m_bVisibleOnly, FIELD_BOOLEAN, "visibleonly" ), - DEFINE_KEYFIELD( m_iType, FIELD_INTEGER, "type" ), - DEFINE_KEYFIELD( m_bAllowCombatActBusyTeleport, FIELD_BOOLEAN, "allowteleport" ), - DEFINE_KEYFIELD( m_iszSeeEntityName, FIELD_STRING, "SeeEntity" ), - DEFINE_KEYFIELD( m_flSeeEntityTimeout, FIELD_FLOAT, "SeeEntityTimeout" ), - DEFINE_KEYFIELD( m_iszSafeZoneVolume, FIELD_STRING, "SafeZone" ), - DEFINE_KEYFIELD( m_iSightMethod, FIELD_INTEGER, "sightmethod" ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetBusySearchRange", InputSetBusySearchRange ), - DEFINE_INPUTFUNC( FIELD_STRING, "ForceNPCToActBusy", InputForceNPCToActBusy ), - DEFINE_INPUTFUNC( FIELD_EHANDLE, "ForceThisNPCToActBusy", InputForceThisNPCToActBusy ), - DEFINE_INPUTFUNC( FIELD_EHANDLE, "ForceThisNPCToLeave", InputForceThisNPCToLeave ), - - // Outputs - DEFINE_OUTPUT( m_OnNPCStartedBusy, "OnNPCStartedBusy" ), - DEFINE_OUTPUT( m_OnNPCFinishedBusy, "OnNPCFinishedBusy" ), - DEFINE_OUTPUT( m_OnNPCLeft, "OnNPCLeft" ), - DEFINE_OUTPUT( m_OnNPCLostSeeEntity, "OnNPCLostSeeEntity" ), - DEFINE_OUTPUT( m_OnNPCSeeEnemy, "OnNPCSeeEnemy" ), -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CAI_ActBusyBehavior *CAI_ActBusyGoal::GetBusyBehaviorForNPC( CBaseEntity *pEntity, const char *sInputName ) -{ - CAI_BaseNPC *pActor = dynamic_cast(pEntity); - if ( !pActor ) - { - Msg("ai_goal_actbusy input %s fired targeting an entity that isn't an NPC.\n", sInputName); - return NULL; - } - - // Get the NPC's behavior - CAI_ActBusyBehavior *pBehavior; - if ( !pActor->GetBehavior( &pBehavior ) ) - { - Msg("ai_goal_actbusy input %s fired on an NPC that doesn't support ActBusy behavior.\n", sInputName ); - return NULL; - } - - return pBehavior; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CAI_ActBusyBehavior *CAI_ActBusyGoal::GetBusyBehaviorForNPC( const char *pszActorName, CBaseEntity *pActivator, CBaseEntity *pCaller, const char *sInputName ) -{ - CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, MAKE_STRING(pszActorName), NULL, pActivator, pCaller ); - if ( !pEntity ) - { - Msg("ai_goal_actbusy input %s fired targeting a non-existant entity (%s).\n", sInputName, pszActorName ); - return NULL; - } - - return GetBusyBehaviorForNPC( pEntity, sInputName ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAI_ActBusyGoal::EnableGoal( CAI_BaseNPC *pAI ) -{ - BaseClass::EnableGoal( pAI ); - - // Now use this actor to lookup the Behavior - CAI_ActBusyBehavior *pBehavior; - if ( pAI->GetBehavior( &pBehavior ) ) - { - // Some NPCs may already be active due to a ForceActBusy input. - if ( !pBehavior->IsEnabled() ) - { - pBehavior->Enable( this, m_flBusySearchRange, m_bVisibleOnly ); - } - } - else - { - DevMsg( "ActBusy goal entity activated for an NPC (%s) that doesn't have the ActBusy behavior\n", pAI->GetDebugName() ); - return; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAI_ActBusyGoal::InputActivate( inputdata_t &inputdata ) -{ - if ( ai_debug_actbusy.GetInt() == 4 ) - { - Msg("ACTBUSY: Actbusy goal %s (%s) activated.\n", GetClassname(), GetDebugName() ); - } - - BaseClass::InputActivate( inputdata ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAI_ActBusyGoal::InputDeactivate( inputdata_t &inputdata ) -{ - if ( ai_debug_actbusy.GetInt() == 4 ) - { - Msg("ACTBUSY: Actbusy goal %s (%s) disabled.\n", GetClassname(), GetDebugName() ); - } - - BaseClass::InputDeactivate( inputdata ); - - for( int i = 0 ; i < NumActors() ; i++ ) - { - CAI_BaseNPC *pActor = GetActor( i ); - - if ( pActor ) - { - // Now use this actor to lookup the Behavior - CAI_ActBusyBehavior *pBehavior; - if ( pActor->GetBehavior( &pBehavior ) ) - { - pBehavior->Disable(); - } - else - { - DevMsg( "ActBusy goal entity deactivated for an NPC that doesn't have the ActBusy behavior\n" ); - return; - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ActBusyGoal::InputSetBusySearchRange( inputdata_t &inputdata ) -{ - m_flBusySearchRange = inputdata.value.Float(); - - for( int i = 0 ; i < NumActors() ; i++ ) - { - CAI_BaseNPC *pActor = GetActor( i ); - - if ( pActor ) - { - // Now use this actor to lookup the Behavior - CAI_ActBusyBehavior *pBehavior; - if ( pActor->GetBehavior( &pBehavior ) ) - { - pBehavior->SetBusySearchRange( m_flBusySearchRange ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ActBusyGoal::InputForceNPCToActBusy( inputdata_t &inputdata ) -{ - char parseString[255]; - Q_strncpy(parseString, inputdata.value.String(), sizeof(parseString)); - - CAI_Hint *pHintNode = NULL; - float flMaxTime = NO_MAX_TIME; - bool bTeleport = false; - bool bUseNearestBusy = false; - CBaseEntity *pSeeEntity = NULL; - - // Get NPC name - char *pszParam = strtok(parseString," "); - CAI_ActBusyBehavior *pBehavior = GetBusyBehaviorForNPC( pszParam, inputdata.pActivator, inputdata.pCaller, "InputForceNPCToActBusy" ); - if ( !pBehavior ) - return; - - // Wrapped this bugfix so that it doesn't break HL2. - bool bEpisodicBugFix = hl2_episodic.GetBool(); - - // Do we have a specified node too? - pszParam = strtok(NULL," "); - if ( pszParam ) - { - // Find the specified hintnode - CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, pszParam, NULL, inputdata.pActivator, inputdata.pCaller ); - if ( pEntity ) - { - pHintNode = dynamic_cast(pEntity); - if ( !pHintNode ) - { - Msg("ai_goal_actbusy input ForceNPCToActBusy fired targeting an entity that isn't a hintnode.\n", pszParam); - return; - } - - if ( bEpisodicBugFix ) - { - pszParam = strtok(NULL," "); - } - } - } - - Activity activity = ACT_INVALID; - - if ( !bEpisodicBugFix ) - { - pszParam = strtok(NULL," "); - } - - while ( pszParam ) - { - // Teleport? - if ( !Q_strncmp( pszParam, "teleport", 8 ) ) - { - bTeleport = true; - } - else if ( !Q_strncmp( pszParam, "nearest", 8 ) ) - { - bUseNearestBusy = true; - } - else if ( !Q_strncmp( pszParam, "see:", 4 ) ) - { - pSeeEntity = gEntList.FindEntityByName( NULL, pszParam+4 ); - } - else if ( pszParam[0] == '$' ) - { - // $ signs prepend custom movement sequences / activities - const char *pAnimName = pszParam+1; - // Try and resolve it as an activity name - activity = (Activity)ActivityList_IndexForName( pAnimName ); - if ( activity == ACT_INVALID ) - { - // Try it as sequence name - pBehavior->GetOuter()->m_iszSceneCustomMoveSeq = AllocPooledString( pAnimName ); - activity = ACT_SCRIPT_CUSTOM_MOVE; - } - } - else - { - // Do we have a specified time? - flMaxTime = atof( pszParam ); - } - - pszParam = strtok(NULL," "); - } - - if ( ai_debug_actbusy.GetInt() == 4 ) - { - Msg("ACTBUSY: Actbusy goal %s (%s) ForceNPCToActBusy input with data: %s.\n", GetClassname(), GetDebugName(), parseString ); - } - - // Tell the NPC to immediately act busy - pBehavior->SetBusySearchRange( m_flBusySearchRange ); - pBehavior->ForceActBusy( this, pHintNode, flMaxTime, m_bVisibleOnly, bTeleport, bUseNearestBusy, pSeeEntity, activity ); -} - -//----------------------------------------------------------------------------- -// Purpose: Force the passed in NPC to actbusy -//----------------------------------------------------------------------------- -void CAI_ActBusyGoal::InputForceThisNPCToActBusy( inputdata_t &inputdata ) -{ - CAI_ActBusyBehavior *pBehavior = GetBusyBehaviorForNPC( inputdata.value.Entity(), "InputForceThisNPCToActBusy" ); - if ( !pBehavior ) - return; - - // Tell the NPC to immediately act busy - pBehavior->SetBusySearchRange( m_flBusySearchRange ); - pBehavior->ForceActBusy( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: Force the passed in NPC to walk to a point and vanish -//----------------------------------------------------------------------------- -void CAI_ActBusyGoal::InputForceThisNPCToLeave( inputdata_t &inputdata ) -{ - CAI_ActBusyBehavior *pBehavior = GetBusyBehaviorForNPC( inputdata.value.Entity(), "InputForceThisNPCToLeave" ); - if ( !pBehavior ) - return; - - // Tell the NPC to find a leave point and move to it - pBehavior->SetBusySearchRange( m_flBusySearchRange ); - pBehavior->ForceActBusyLeave(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pNPC - -//----------------------------------------------------------------------------- -void CAI_ActBusyGoal::NPCMovingToBusy( CAI_BaseNPC *pNPC ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pNPC - -//----------------------------------------------------------------------------- -void CAI_ActBusyGoal::NPCStartedBusy( CAI_BaseNPC *pNPC ) -{ - m_OnNPCStartedBusy.Set( pNPC, pNPC, this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ActBusyGoal::NPCStartedLeavingBusy( CAI_BaseNPC *pNPC ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pNPC - -//----------------------------------------------------------------------------- -void CAI_ActBusyGoal::NPCAbortedMoveTo( CAI_BaseNPC *pNPC ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pNPC - -//----------------------------------------------------------------------------- -void CAI_ActBusyGoal::NPCFinishedBusy( CAI_BaseNPC *pNPC ) -{ - m_OnNPCFinishedBusy.Set( pNPC, pNPC, this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pNPC - -//----------------------------------------------------------------------------- -void CAI_ActBusyGoal::NPCLeft( CAI_BaseNPC *pNPC ) -{ - m_OnNPCLeft.Set( pNPC, pNPC, this ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_ActBusyGoal::NPCLostSeeEntity( CAI_BaseNPC *pNPC ) -{ - m_OnNPCLostSeeEntity.Set( pNPC, pNPC, this ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_ActBusyGoal::NPCSeeEnemy( CAI_BaseNPC *pNPC ) -{ - m_OnNPCSeeEnemy.Set( pNPC, pNPC, this ); -} - -//========================================================================================================== -// ACT BUSY QUEUE -//========================================================================================================== -//----------------------------------------------------------------------------- -// Purpose: A level tool to control the actbusy behavior to create NPC queues -//----------------------------------------------------------------------------- -LINK_ENTITY_TO_CLASS( ai_goal_actbusy_queue, CAI_ActBusyQueueGoal ); - -BEGIN_DATADESC( CAI_ActBusyQueueGoal ) - // Keys - DEFINE_FIELD( m_iCurrentQueueCount, FIELD_INTEGER ), - DEFINE_ARRAY( m_hNodes, FIELD_EHANDLE, MAX_QUEUE_NODES ), - DEFINE_ARRAY( m_bPlayerBlockedNodes, FIELD_BOOLEAN, MAX_QUEUE_NODES ), - DEFINE_FIELD( m_hExitNode, FIELD_EHANDLE ), - DEFINE_FIELD( m_hExitingNPC, FIELD_EHANDLE ), - DEFINE_KEYFIELD( m_bForceReachFront, FIELD_BOOLEAN, "mustreachfront" ), - // DEFINE_ARRAY( m_iszNodes, FIELD_STRING, MAX_QUEUE_NODES ), // Silence Classcheck! - DEFINE_KEYFIELD( m_iszNodes[0], FIELD_STRING, "node01"), - DEFINE_KEYFIELD( m_iszNodes[1], FIELD_STRING, "node02"), - DEFINE_KEYFIELD( m_iszNodes[2], FIELD_STRING, "node03"), - DEFINE_KEYFIELD( m_iszNodes[3], FIELD_STRING, "node04"), - DEFINE_KEYFIELD( m_iszNodes[4], FIELD_STRING, "node05"), - DEFINE_KEYFIELD( m_iszNodes[5], FIELD_STRING, "node06"), - DEFINE_KEYFIELD( m_iszNodes[6], FIELD_STRING, "node07"), - DEFINE_KEYFIELD( m_iszNodes[7], FIELD_STRING, "node08"), - DEFINE_KEYFIELD( m_iszNodes[8], FIELD_STRING, "node09"), - DEFINE_KEYFIELD( m_iszNodes[9], FIELD_STRING, "node10"), - DEFINE_KEYFIELD( m_iszNodes[10], FIELD_STRING, "node11"), - DEFINE_KEYFIELD( m_iszNodes[11], FIELD_STRING, "node12"), - DEFINE_KEYFIELD( m_iszNodes[12], FIELD_STRING, "node13"), - DEFINE_KEYFIELD( m_iszNodes[13], FIELD_STRING, "node14"), - DEFINE_KEYFIELD( m_iszNodes[14], FIELD_STRING, "node15"), - DEFINE_KEYFIELD( m_iszNodes[15], FIELD_STRING, "node16"), - DEFINE_KEYFIELD( m_iszNodes[16], FIELD_STRING, "node17"), - DEFINE_KEYFIELD( m_iszNodes[17], FIELD_STRING, "node18"), - DEFINE_KEYFIELD( m_iszNodes[18], FIELD_STRING, "node19"), - DEFINE_KEYFIELD( m_iszNodes[19], FIELD_STRING, "node20"), - DEFINE_KEYFIELD( m_iszExitNode, FIELD_STRING, "node_exit"), - - // Inputs - DEFINE_INPUTFUNC( FIELD_INTEGER, "PlayerStartedBlocking", InputPlayerStartedBlocking ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "PlayerStoppedBlocking", InputPlayerStoppedBlocking ), - DEFINE_INPUTFUNC( FIELD_VOID, "MoveQueueUp", InputMoveQueueUp ), - - // Outputs - DEFINE_OUTPUT( m_OnQueueMoved, "OnQueueMoved" ), - DEFINE_OUTPUT( m_OnNPCLeftQueue, "OnNPCLeftQueue" ), - DEFINE_OUTPUT( m_OnNPCStartedLeavingQueue, "OnNPCStartedLeavingQueue" ), - - DEFINE_THINKFUNC( QueueThink ), - DEFINE_THINKFUNC( MoveQueueUpThink ), - -END_DATADESC() - -#define QUEUE_THINK_CONTEXT "ActBusyQueueThinkContext" -#define QUEUE_MOVEUP_THINK_CONTEXT "ActBusyQueueMoveUpThinkContext" - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ActBusyQueueGoal::Spawn( void ) -{ - BaseClass::Spawn(); - - RegisterThinkContext( QUEUE_MOVEUP_THINK_CONTEXT ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ActBusyQueueGoal::DrawDebugGeometryOverlays( void ) -{ - BaseClass::DrawDebugGeometryOverlays(); - - // Debug for reservers - for ( int i = 0; i < MAX_QUEUE_NODES; i++ ) - { - if ( !m_hNodes[i] ) - continue; - if ( m_bPlayerBlockedNodes[i] ) - { - NDebugOverlay::Box( m_hNodes[i]->GetAbsOrigin(), -Vector(5,5,5), Vector(5,5,5), 255, 0, 0, 0, 0.1 ); - } - else - { - NDebugOverlay::Box( m_hNodes[i]->GetAbsOrigin(), -Vector(5,5,5), Vector(5,5,5), 255, 255, 255, 0, 0.1 ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ActBusyQueueGoal::InputActivate( inputdata_t &inputdata ) -{ - if ( !IsActive() ) - { - // Find all our nodes - for ( int i = 0; i < MAX_QUEUE_NODES; i++ ) - { - if ( m_iszNodes[i] == NULL_STRING ) - { - m_hNodes[i] = NULL; - continue; - } - - CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, m_iszNodes[i] ); - if ( !pEntity ) - { - Warning( "Unable to find ai_goal_actbusy_queue %s's node %d: %s\n", STRING(GetEntityName()), i, STRING(m_iszNodes[i]) ); - UTIL_Remove( this ); - return; - } - m_hNodes[i] = dynamic_cast(pEntity); - if ( !m_hNodes[i] ) - { - Warning( "ai_goal_actbusy_queue %s's node %d: '%s' is not an ai_hint.\n", STRING(GetEntityName()), i, STRING(m_iszNodes[i]) ); - UTIL_Remove( this ); - return; - } - - // Disable all but the first node - if ( i == 0 ) - { - m_hNodes[i]->SetDisabled( false ); - } - else - { - m_hNodes[i]->SetDisabled( true ); - } - } - - // Find the exit node - m_hExitNode = gEntList.FindEntityByName( NULL, m_iszExitNode ); - if ( !m_hExitNode ) - { - Warning( "Unable to find ai_goal_actbusy_queue %s's exit node: %s\n", STRING(GetEntityName()), STRING(m_iszExitNode) ); - UTIL_Remove( this ); - return; - } - - RecalculateQueueCount(); - - SetContextThink( &CAI_ActBusyQueueGoal::QueueThink, gpGlobals->curtime + 5, QUEUE_THINK_CONTEXT ); - } - - BaseClass::InputActivate( inputdata ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iCount - -//----------------------------------------------------------------------------- -void CAI_ActBusyQueueGoal::RecalculateQueueCount( void ) -{ - // First, find the highest unused node in the queue - int iCount = 0; - for ( int i = 0; i < MAX_QUEUE_NODES; i++ ) - { - if ( NodeIsOccupied(i) || m_bPlayerBlockedNodes[i] ) - { - iCount = i+1; - } - } - - //Msg("Count: %d (OLD %d)\n", iCount, m_iCurrentQueueCount ); - - // Queue hasn't changed? - if ( iCount == m_iCurrentQueueCount ) - return; - - for ( int i = 0; i < MAX_QUEUE_NODES; i++ ) - { - if ( m_hNodes[i] ) - { - // Disable nodes beyond 1 past the end of the queue - if ( i > iCount ) - { - m_hNodes[i]->SetDisabled( true ); - } - else - { - m_hNodes[i]->SetDisabled( false ); - - // To prevent NPCs outside the queue moving directly to nodes within the queue, only - // have the entry node be a valid actbusy node. - if ( i == iCount ) - { - m_hNodes[i]->SetHintType( HINT_WORLD_WORK_POSITION ); - } - else - { - m_hNodes[i]->SetHintType( HINT_NONE ); - } - } - } - } - - m_iCurrentQueueCount = iCount; - m_OnQueueMoved.Set( m_iCurrentQueueCount, this, this); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAI_ActBusyQueueGoal::InputPlayerStartedBlocking( inputdata_t &inputdata ) -{ - int iNode = inputdata.value.Int() - 1; - Assert( iNode >= 0 && iNode < MAX_QUEUE_NODES ); - - m_bPlayerBlockedNodes[iNode] = true; - - /* - // First, find all NPCs heading to points in front of the player's blocked spot - for ( int i = 0; i < iNode; i++ ) - { - CAI_BaseNPC *pNPC = GetNPCOnNode(i); - if ( !pNPC ) - continue; - - CAI_ActBusyBehavior *pBehavior = GetQueueBehaviorForNPC( pNPC ); - if ( pBehavior->IsMovingToBusy() ) - { - // We may be ahead of the player in the queue, which means we can safely - // be left alone to reach the node. Make sure we're not closer to it than the player is - float flPlayerDistToNode = (inputdata.pActivator->GetAbsOrigin() - m_hNodes[i]->GetAbsOrigin()).LengthSqr(); - if ( (pNPC->GetAbsOrigin() - m_hNodes[i]->GetAbsOrigin()).LengthSqr() < flPlayerDistToNode ) - continue; - - // We're an NPC heading to a node past the player, and yet the player's in our way. - pBehavior->StopBusying(); - } - } - */ - - // If an NPC was heading towards this node, tell him to go elsewhere - CAI_BaseNPC *pNPC = GetNPCOnNode(iNode); - PushNPCBackInQueue( pNPC, iNode ); - - RecalculateQueueCount(); -} - -//----------------------------------------------------------------------------- -// Purpose: Find a node back in the queue to move to, and push all NPCs beyond that backwards -//----------------------------------------------------------------------------- -void CAI_ActBusyQueueGoal::PushNPCBackInQueue( CAI_BaseNPC *pNPC, int iStartingNode ) -{ - // Push this guy back, and tell everyone behind him to move back too, until we find a gap - while ( pNPC ) - { - CAI_ActBusyBehavior *pBehavior = GetQueueBehaviorForNPC( pNPC ); - pBehavior->StopBusying(); - - // Find any node farther back in the queue that isn't player blocked - for ( int iNext = iStartingNode+1; iNext < MAX_QUEUE_NODES; iNext++ ) - { - if ( !m_bPlayerBlockedNodes[iNext] ) - { - // Kick off any NPCs on the node we're about to steal - CAI_BaseNPC *pTargetNPC = GetNPCOnNode(iNext); - if ( pTargetNPC ) - { - CAI_ActBusyBehavior *pTargetBehavior = GetQueueBehaviorForNPC( pTargetNPC ); - pTargetBehavior->StopBusying(); - } - - // Force the NPC to move up to the empty slot - pBehavior->ForceActBusy( this, m_hNodes[iNext] ); - - // Now look for a spot for the npc who's spot we've just stolen - pNPC = pTargetNPC; - iStartingNode = iNext; - break; - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAI_ActBusyQueueGoal::InputPlayerStoppedBlocking( inputdata_t &inputdata ) -{ - int iNode = inputdata.value.Int() - 1; - Assert( iNode >= 0 && iNode < MAX_QUEUE_NODES ); - - m_bPlayerBlockedNodes[iNode] = false; - - RecalculateQueueCount(); - MoveQueueUp(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAI_ActBusyQueueGoal::InputMoveQueueUp( inputdata_t &inputdata ) -{ - // Find the first NPC in the queue - CAI_BaseNPC *pNPC = NULL; - for ( int i = 0; i < MAX_QUEUE_NODES; i++ ) - { - pNPC = GetNPCOnNode(i); - if ( pNPC ) - { - CAI_ActBusyBehavior *pBehavior = GetQueueBehaviorForNPC( pNPC ); - // If we're still en-route, we're only allowed to leave if the queue - // is allowed to send NPCs away that haven't reached the front. - if ( !pBehavior->IsMovingToBusy() || !m_bForceReachFront ) - break; - - pNPC = NULL; - } - - // If queue members have to reach the front of the queue, - // break after trying the first node. - if ( m_bForceReachFront ) - break; - } - - // Did we find an NPC? - if ( pNPC ) - { - // Make them leave the actbusy - CAI_ActBusyBehavior *pBehavior = GetQueueBehaviorForNPC( pNPC ); - pBehavior->Disable(); - m_hExitingNPC = pNPC; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pNPC - -//----------------------------------------------------------------------------- -void CAI_ActBusyQueueGoal::NPCMovingToBusy( CAI_BaseNPC *pNPC ) -{ - BaseClass::NPCMovingToBusy( pNPC ); - RecalculateQueueCount(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pNPC - -//----------------------------------------------------------------------------- -void CAI_ActBusyQueueGoal::NPCStartedBusy( CAI_BaseNPC *pNPC ) -{ - BaseClass::NPCStartedBusy( pNPC ); - MoveQueueUp(); -} - -//----------------------------------------------------------------------------- -// Purpose: Start a short timer that'll clean up holes in the queue -//----------------------------------------------------------------------------- -void CAI_ActBusyQueueGoal::MoveQueueUp( void ) -{ - // Find the node the NPC has arrived at, and tell the guy behind him to move forward - if ( GetNextThink( QUEUE_MOVEUP_THINK_CONTEXT ) < gpGlobals->curtime ) - { - float flTime = gpGlobals->curtime + RandomFloat( 0.3, 0.5 ); - SetContextThink( &CAI_ActBusyQueueGoal::MoveQueueUpThink, flTime, QUEUE_MOVEUP_THINK_CONTEXT ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ActBusyQueueGoal::MoveQueueUpThink( void ) -{ - // Find empty holes in the queue, and move NPCs past them forward - for ( int iEmptyNode = 0; iEmptyNode < (MAX_QUEUE_NODES-1); iEmptyNode++ ) - { - if ( !NodeIsOccupied(iEmptyNode) && !m_bPlayerBlockedNodes[iEmptyNode] ) - { - // Look for NPCs farther down the queue, but not on the other side of a player - for ( int iNext = iEmptyNode+1; iNext < MAX_QUEUE_NODES; iNext++ ) - { - // Is the player blocking this node? If so, we're done - if ( m_bPlayerBlockedNodes[iNext] ) - break; - - CAI_BaseNPC *pNPC = GetNPCOnNode(iNext); - if ( pNPC ) - { - CAI_ActBusyBehavior *pBehavior = GetQueueBehaviorForNPC( pNPC ); - - // Force the NPC to move up to the empty slot - pBehavior->ForceActBusy( this, m_hNodes[iEmptyNode] ); - break; - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pNPC - -//----------------------------------------------------------------------------- -void CAI_ActBusyQueueGoal::NPCAbortedMoveTo( CAI_BaseNPC *pNPC ) -{ - BaseClass::NPCAbortedMoveTo( pNPC ); - - RemoveNPCFromQueue( pNPC ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pNPC - -//----------------------------------------------------------------------------- -void CAI_ActBusyQueueGoal::NPCFinishedBusy( CAI_BaseNPC *pNPC ) -{ - BaseClass::NPCFinishedBusy( pNPC ); - - // If this NPC was at the head of the line, move him to the exit node - if ( m_hExitingNPC == pNPC ) - { - pNPC->ScheduledMoveToGoalEntity( SCHED_IDLE_WALK, m_hExitNode, ACT_WALK ); - m_OnNPCLeftQueue.Set( pNPC, pNPC, this ); - m_hExitingNPC = NULL; - } - - RemoveNPCFromQueue( pNPC ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pNPC - -//----------------------------------------------------------------------------- -void CAI_ActBusyQueueGoal::NPCStartedLeavingBusy( CAI_BaseNPC *pNPC ) -{ - BaseClass::NPCStartedLeavingBusy( pNPC ); - - // If this NPC it at the head of the line, fire the output - if ( m_hExitingNPC == pNPC ) - { - m_OnNPCStartedLeavingQueue.Set( pNPC, pNPC, this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ActBusyQueueGoal::RemoveNPCFromQueue( CAI_BaseNPC *pNPC ) -{ - RecalculateQueueCount(); - - // Find the node the NPC was heading to, and tell the guy behind him to move forward - MoveQueueUp(); -} - -//----------------------------------------------------------------------------- -// Purpose: Move the first NPC out of the queue -//----------------------------------------------------------------------------- -void CAI_ActBusyQueueGoal::QueueThink( void ) -{ - if ( !GetNPCOnNode(0) ) - { - MoveQueueUp(); - } - - SetContextThink( &CAI_ActBusyQueueGoal::QueueThink, gpGlobals->curtime + 5, QUEUE_THINK_CONTEXT ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline bool CAI_ActBusyQueueGoal::NodeIsOccupied( int i ) -{ - return ( m_hNodes[i] && !m_hNodes[i]->IsDisabled() && m_hNodes[i]->IsLocked() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iNode - -// Output : CAI_BaseNPC -//----------------------------------------------------------------------------- -CAI_BaseNPC *CAI_ActBusyQueueGoal::GetNPCOnNode( int iNode ) -{ - if ( !m_hNodes[iNode] ) - return NULL; - - return dynamic_cast(m_hNodes[iNode]->User()); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iNode - -// Output : CAI_ActBusyBehavior -//----------------------------------------------------------------------------- -CAI_ActBusyBehavior *CAI_ActBusyQueueGoal::GetQueueBehaviorForNPC( CAI_BaseNPC *pNPC ) -{ - CAI_ActBusyBehavior *pBehavior; - pNPC->GetBehavior( &pBehavior ); - Assert( pBehavior ); - return pBehavior; -} - diff --git a/game/server/hl2/ai_behavior_actbusy.h b/game/server/hl2/ai_behavior_actbusy.h deleted file mode 100644 index 32aaf96c8..000000000 --- a/game/server/hl2/ai_behavior_actbusy.h +++ /dev/null @@ -1,318 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef AI_BEHAVIOR_ACTBUSY_H -#define AI_BEHAVIOR_ACTBUSY_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_behavior.h" -#include "ai_goalentity.h" - -//----------------------------------------------------------------------------- -enum -{ - ACTBUSY_TYPE_DEFAULT = 0, - ACTBUSY_TYPE_COMBAT, -}; - -enum busyinterrupt_t -{ - BA_INT_NONE, // Nothing breaks us out of this - BA_INT_DANGER, // Only danger signals interrupts this busy anim. The player will be ignored. - BA_INT_PLAYER, // The Player's presence interrupts this busy anim - BA_INT_AMBUSH, // We're waiting to ambush enemies. Don't break on danger sounds in front of us. - BA_INT_COMBAT, // Only break out if we're shot at. - BA_INT_ZOMBIESLUMP, // Zombies who are slumped on the ground. - BA_INT_SIEGE_DEFENSE, -}; - -enum busyanimparts_t -{ - BA_BUSY, - BA_ENTRY, - BA_EXIT, - - BA_MAX_ANIMS, -}; - -struct busyanim_t -{ - string_t iszName; - Activity iActivities[BA_MAX_ANIMS]; - string_t iszSequences[BA_MAX_ANIMS]; - string_t iszSounds[BA_MAX_ANIMS]; - float flMinTime; // Min time spent in this busy animation - float flMaxTime; // Max time spent in this busy animation. 0 means continue until interrupted. - busyinterrupt_t iBusyInterruptType; - bool bUseAutomovement; -}; - -struct busysafezone_t -{ - Vector vecMins; - Vector vecMaxs; -}; - -#define NO_MAX_TIME -1 - -class CAI_ActBusyGoal; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CAI_ActBusyBehavior : public CAI_SimpleBehavior -{ - DECLARE_CLASS( CAI_ActBusyBehavior, CAI_SimpleBehavior ); -public: - DECLARE_DATADESC(); - CAI_ActBusyBehavior(); - - enum - { - // Schedules - SCHED_ACTBUSY_START_BUSYING = BaseClass::NEXT_SCHEDULE, - SCHED_ACTBUSY_BUSY, - SCHED_ACTBUSY_STOP_BUSYING, - SCHED_ACTBUSY_LEAVE, - SCHED_ACTBUSY_TELEPORT_TO_BUSY, - NEXT_SCHEDULE, - - // Tasks - TASK_ACTBUSY_PLAY_BUSY_ANIM = BaseClass::NEXT_TASK, - TASK_ACTBUSY_PLAY_ENTRY, - TASK_ACTBUSY_PLAY_EXIT, - TASK_ACTBUSY_TELEPORT_TO_BUSY, - TASK_ACTBUSY_WALK_PATH_TO_BUSY, - TASK_ACTBUSY_GET_PATH_TO_ACTBUSY, - TASK_ACTBUSY_VERIFY_EXIT, - NEXT_TASK, - - // Conditions - COND_ACTBUSY_LOST_SEE_ENTITY = BaseClass::NEXT_CONDITION, - COND_ACTBUSY_AWARE_OF_ENEMY_IN_SAFE_ZONE, - COND_ACTBUSY_ENEMY_TOO_CLOSE, - NEXT_CONDITION, - }; - - virtual const char *GetName() { return "ActBusy"; } - - void Enable( CAI_ActBusyGoal *pGoal, float flRange, bool bVisibleOnly ); - void OnRestore(); - void SetBusySearchRange( float flRange ); - void Disable( void ); - void ForceActBusy( CAI_ActBusyGoal *pGoal, CAI_Hint *pHintNode = NULL, float flMaxTime = NO_MAX_TIME, bool bVisibleOnly = false, bool bTeleportToBusy = false, bool bUseNearestBusy = false, CBaseEntity *pSeeEntity = NULL, Activity activity = ACT_INVALID ); - void ForceActBusyLeave( bool bVisibleOnly = false ); - void StopBusying( void ); - bool IsStopBusying(); - CAI_Hint *FindActBusyHintNode( void ); - CAI_Hint *FindCombatActBusyHintNode( void ); - CAI_Hint *FindCombatActBusyTeleportHintNode( void ); - bool CanSelectSchedule( void ); - bool IsCurScheduleOverridable( void ); - bool ShouldIgnoreSound( CSound *pSound ); - void OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker ); - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - void GatherConditions( void ); - void BuildScheduleTestBits( void ); - void EndScheduleSelection( void ); - Activity NPC_TranslateActivity( Activity nActivity ); - void HandleAnimEvent( animevent_t *pEvent ); - void CheckAndCleanupOnExit( void ); - bool FValidateHintType( CAI_Hint *pHint ); - bool ActBusyNodeStillActive( void ); - bool IsMovingToBusy( void ) { return m_bMovingToBusy; } - bool IsEnabled( void ) { return m_bEnabled; } - float GetReasonableFacingDist( void ) { return 0; } // Actbusy ignores reasonable facing - bool IsInterruptable( void ); - bool ShouldPlayerAvoid( void ); - void SetUseRenderBounds( bool bUseBounds ) { m_bUseRenderBoundsForCollision = bUseBounds; } - void ComputeAndSetRenderBounds(); - bool CanFlinch( void ); - bool CanRunAScriptedNPCInteraction( bool bForced ); - void OnScheduleChange(); - bool QueryHearSound( CSound *pSound ); - void OnSeeEntity( CBaseEntity *pEntity ); - bool NeedsToPlayExitAnim() { return m_bNeedsToPlayExitAnim; } - - // Returns true if the current NPC is acting busy, or moving to an actbusy - bool IsActive( void ); - // Returns true if the current NPC is actually acting busy (i.e. inside an act busy anim) - bool IsInsideActBusy( void ) { return m_bBusy; } - - // Combat act busy stuff - bool IsCombatActBusy(); - void CollectSafeZoneVolumes( CAI_ActBusyGoal *pActBusyGoal ); - bool IsInSafeZone( CBaseEntity *pEntity ); - int CountEnemiesInSafeZone(); - -private: - virtual int SelectSchedule( void ); - int SelectScheduleForLeaving( void ); - int SelectScheduleWhileNotBusy( int iBase ); - int SelectScheduleWhileBusy( void ); - virtual void StartTask( const Task_t *pTask ); - virtual void RunTask( const Task_t *pTask ); - void NotifyBusyEnding( void ); - bool HasAnimForActBusy( int iActBusy, busyanimparts_t AnimPart ); - bool PlayAnimForActBusy( busyanimparts_t AnimPart ); - void PlaySoundForActBusy( busyanimparts_t AnimPart ); - -private: - bool m_bEnabled; - bool m_bForceActBusy; - Activity m_ForcedActivity; - bool m_bTeleportToBusy; - bool m_bUseNearestBusy; - bool m_bLeaving; - bool m_bVisibleOnly; - bool m_bUseRenderBoundsForCollision; - float m_flForcedMaxTime; - bool m_bBusy; - bool m_bMovingToBusy; - bool m_bNeedsToPlayExitAnim; - float m_flNextBusySearchTime; - float m_flEndBusyAt; - float m_flBusySearchRange; - bool m_bInQueue; - int m_iCurrentBusyAnim; - CHandle m_hActBusyGoal; - bool m_bNeedToSetBounds; - EHANDLE m_hSeeEntity; - float m_fTimeLastSawSeeEntity; - bool m_bExitedBusyToDueLostSeeEntity; - bool m_bExitedBusyToDueSeeEnemy; - - int m_iNumConsecutivePathFailures; // Count how many times we failed to find a path to a node, so we can consider teleporting. - bool m_bAutoFireWeapon; - float m_flDeferUntil; - int m_iNumEnemiesInSafeZone; - - CUtlVectorm_SafeZones; - - DEFINE_CUSTOM_SCHEDULE_PROVIDER; -}; - - -//----------------------------------------------------------------------------- -// Purpose: A level tool to control the actbusy behavior. -//----------------------------------------------------------------------------- -class CAI_ActBusyGoal : public CAI_GoalEntity -{ - DECLARE_CLASS( CAI_ActBusyGoal, CAI_GoalEntity ); -public: - CAI_ActBusyGoal() - { - // Support legacy maps, where this value used to be set from a constant (with a value of 1). - // Now designers can specify whatever they want in Hammer. Take care of old maps by setting - // this in the constructor. (sjb) - m_flSeeEntityTimeout = 1; - } - - virtual void NPCMovingToBusy( CAI_BaseNPC *pNPC ); - virtual void NPCAbortedMoveTo( CAI_BaseNPC *pNPC ); - virtual void NPCStartedBusy( CAI_BaseNPC *pNPC ); - virtual void NPCStartedLeavingBusy( CAI_BaseNPC *pNPC ); - virtual void NPCFinishedBusy( CAI_BaseNPC *pNPC ); - virtual void NPCLeft( CAI_BaseNPC *pNPC ); - virtual void NPCLostSeeEntity( CAI_BaseNPC *pNPC ); - virtual void NPCSeeEnemy( CAI_BaseNPC *pNPC ); - - int GetType() { return m_iType; } - bool IsCombatActBusyTeleportAllowed() { return m_bAllowCombatActBusyTeleport; } - -protected: - CAI_ActBusyBehavior *GetBusyBehaviorForNPC( const char *pszActorName, CBaseEntity *pActivator, CBaseEntity *pCaller, const char *sInputName ); - CAI_ActBusyBehavior *GetBusyBehaviorForNPC( CBaseEntity *pEntity, const char *sInputName ); - - void EnableGoal( CAI_BaseNPC *pAI ); - - // Inputs - virtual void InputActivate( inputdata_t &inputdata ); - virtual void InputDeactivate( inputdata_t &inputdata ); - void InputSetBusySearchRange( inputdata_t &inputdata ); - void InputForceNPCToActBusy( inputdata_t &inputdata ); - void InputForceThisNPCToActBusy( inputdata_t &inputdata ); - void InputForceThisNPCToLeave( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - -protected: - float m_flBusySearchRange; - bool m_bVisibleOnly; - int m_iType; - bool m_bAllowCombatActBusyTeleport; - -public: - // Let the actbusy behavior query these so we don't have to duplicate the data. - string_t m_iszSeeEntityName; - float m_flSeeEntityTimeout; - string_t m_iszSafeZoneVolume; - int m_iSightMethod; - -protected: - COutputEHANDLE m_OnNPCStartedBusy; - COutputEHANDLE m_OnNPCFinishedBusy; - COutputEHANDLE m_OnNPCLeft; - COutputEHANDLE m_OnNPCLostSeeEntity; - COutputEHANDLE m_OnNPCSeeEnemy; -}; - -// Maximum number of nodes allowed in an actbusy queue -#define MAX_QUEUE_NODES 20 - -//----------------------------------------------------------------------------- -// Purpose: A level tool to control the actbusy behavior to create NPC queues -//----------------------------------------------------------------------------- -class CAI_ActBusyQueueGoal : public CAI_ActBusyGoal -{ - DECLARE_CLASS( CAI_ActBusyQueueGoal, CAI_ActBusyGoal ); -public: - virtual void Spawn( void ); - virtual void DrawDebugGeometryOverlays( void ); - virtual void NPCMovingToBusy( CAI_BaseNPC *pNPC ); - virtual void NPCStartedBusy( CAI_BaseNPC *pNPC ); - virtual void NPCAbortedMoveTo( CAI_BaseNPC *pNPC ); - virtual void NPCFinishedBusy( CAI_BaseNPC *pNPC ); - virtual void NPCStartedLeavingBusy( CAI_BaseNPC *pNPC ); - - virtual void InputActivate( inputdata_t &inputdata ); - void InputPlayerStartedBlocking( inputdata_t &inputdata ); - void InputPlayerStoppedBlocking( inputdata_t &inputdata ); - void InputMoveQueueUp( inputdata_t &inputdata ); - - void PushNPCBackInQueue( CAI_BaseNPC *pNPC, int iStartingNode ); - void RemoveNPCFromQueue( CAI_BaseNPC *pNPC ); - void RecalculateQueueCount( void ); - void QueueThink( void ); - void MoveQueueUp( void ); - void MoveQueueUpThink( void ); - bool NodeIsOccupied( int i ); - CAI_BaseNPC *GetNPCOnNode( int iNode ); - CAI_ActBusyBehavior *GetQueueBehaviorForNPC( CAI_BaseNPC *pNPC ); - - DECLARE_DATADESC(); - -private: - int m_iCurrentQueueCount; - CHandle m_hNodes[ MAX_QUEUE_NODES ]; - bool m_bPlayerBlockedNodes[ MAX_QUEUE_NODES ]; - EHANDLE m_hExitNode; - EHANDLE m_hExitingNPC; - bool m_bForceReachFront; - - // Read from mapdata - string_t m_iszNodes[ MAX_QUEUE_NODES ]; - string_t m_iszExitNode; - - // Outputs - COutputInt m_OnQueueMoved; - COutputEHANDLE m_OnNPCLeftQueue; - COutputEHANDLE m_OnNPCStartedLeavingQueue; -}; - -#endif // AI_BEHAVIOR_ACTBUSY_H diff --git a/game/server/hl2/ai_behavior_functank.cpp b/game/server/hl2/ai_behavior_functank.cpp deleted file mode 100644 index 7af4349ac..000000000 --- a/game/server/hl2/ai_behavior_functank.cpp +++ /dev/null @@ -1,776 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "ai_behavior_functank.h" -#include "ai_navigator.h" -#include "ai_memory.h" -#include "ai_senses.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// How long to fire a func tank before running schedule selection again. -#define FUNCTANK_FIRE_TIME 5.0f - -BEGIN_DATADESC( CAI_FuncTankBehavior ) - DEFINE_FIELD( m_hFuncTank, FIELD_EHANDLE ), - DEFINE_FIELD( m_bMounted, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flBusyTime, FIELD_TIME ), - DEFINE_FIELD( m_bSpottedPlayerOutOfCover, FIELD_BOOLEAN ), -END_DATADESC(); - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//--k--------------------------------------------------------------------------- -CAI_FuncTankBehavior::CAI_FuncTankBehavior() -{ - m_hFuncTank = NULL; - m_bMounted = false; - m_flBusyTime = 0.0f; - m_bSpottedPlayerOutOfCover = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Deconstructor -//----------------------------------------------------------------------------- -CAI_FuncTankBehavior::~CAI_FuncTankBehavior() -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_FuncTankBehavior::CanSelectSchedule() -{ - // If we don't have a func_tank do not bother with conditions, schedules, etc. - if ( !m_hFuncTank ) - return false; - - // Are you alive, in a script? - if ( !GetOuter()->IsInterruptable() ) - return false; - - // Commander is giving you orders? - if ( GetOuter()->HasCondition( COND_RECEIVED_ORDERS ) ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_FuncTankBehavior::BeginScheduleSelection() -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_FuncTankBehavior::EndScheduleSelection() -{ - if ( m_bMounted ) - { - Dismount(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_FuncTankBehavior::PrescheduleThink() -{ - BaseClass::PrescheduleThink(); - - if ( !HasCondition(COND_SEE_PLAYER) ) - { - m_bSpottedPlayerOutOfCover = false; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CAI_FuncTankBehavior::SelectSchedule() -{ - // This shouldn't get called with an m_hFuncTank, see CanSelectSchedule. - Assert( m_hFuncTank ); - - // If we've been told to dismount, or we are out of ammo - dismount. - if ( HasCondition( COND_FUNCTANK_DISMOUNT ) || m_hFuncTank->GetAmmoCount() == 0 ) - { - if ( m_bMounted ) - { - Dismount(); - } - - return BaseClass::SelectSchedule(); - } - - // If we are not mounted to a func_tank look for one. - if ( !IsMounted() ) - { - return SCHED_MOVE_TO_FUNCTANK; - } - - // If we have an enemy, it's in the viewcone & we have LOS to it - if ( GetEnemy() ) - { - // Tell the func tank whenever we see the player for the first time since not seeing him for a while - if ( HasCondition( COND_NEW_ENEMY ) && GetEnemy()->IsPlayer() && !m_bSpottedPlayerOutOfCover ) - { - m_bSpottedPlayerOutOfCover = true; - m_hFuncTank->NPC_JustSawPlayer( GetEnemy() ); - } - - // Fire at the enemy. - return SCHED_FIRE_FUNCTANK; - } - else - { - // Scan for enemies. - return SCHED_SCAN_WITH_FUNCTANK; - } - - return SCHED_IDLE_STAND; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : activity - -// Output : Activity -//----------------------------------------------------------------------------- -Activity CAI_FuncTankBehavior::NPC_TranslateActivity( Activity activity ) -{ - // If I'm on the gun, I play the idle manned gun animation - if ( m_bMounted ) - return ACT_IDLE_MANNEDGUN; - - return BaseClass::NPC_TranslateActivity( activity ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_FuncTankBehavior::Dismount( void ) -{ - SetBusy( gpGlobals->curtime + AI_FUNCTANK_BEHAVIOR_BUSYTIME ); - - Assert( m_hFuncTank ); - - if ( m_hFuncTank ) - { - GetOuter()->SpeakSentence( FUNCTANK_SENTENCE_DISMOUNTING ); - - Assert( m_hFuncTank->IsMarkedForDeletion() || m_hFuncTank->GetController() == GetOuter() ); - - m_hFuncTank->NPC_SetInRoute( false ); - if ( m_hFuncTank->GetController() == GetOuter() ) - m_hFuncTank->StopControl(); - SetFuncTank( NULL ); - } - - GetOuter()->SetDesiredWeaponState( DESIREDWEAPONSTATE_UNHOLSTERED ); - - m_bMounted = false; - - // Set this condition to force breakout of any func_tank behavior schedules - SetCondition( COND_FUNCTANK_DISMOUNT ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int CAI_FuncTankBehavior::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - int iResult = BaseClass::OnTakeDamage_Alive( info ); - if ( !iResult ) - return 0; - - // If we've been hit by the player, and the player's not targetable - // by our func_tank, get off the tank. - CBaseEntity *pAttacker = info.GetAttacker(); - bool bValidDismountAttacker = (pAttacker && pAttacker->IsPlayer()); - -#ifdef HL2_EPISODIC - bValidDismountAttacker = true; -#endif - - if ( m_hFuncTank && bValidDismountAttacker == true ) - { - if ( !m_hFuncTank->IsEntityInViewCone( pAttacker ) ) - { - SetCondition( COND_FUNCTANK_DISMOUNT ); - } - } - - return iResult; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_FuncTankBehavior::StartTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_FUNCTANK_ANNOUNCE_SCAN: - { - if ( random->RandomInt( 0, 3 ) == 0 ) - { - GetOuter()->SpeakSentence( FUNCTANK_SENTENCE_SCAN_FOR_ENEMIES ); - } - TaskComplete(); - } - break; - - case TASK_GET_PATH_TO_FUNCTANK: - { - if ( !m_hFuncTank ) - { - TaskFail( FAIL_NO_TARGET ); - return; - } - - Vector vecManPos; - m_hFuncTank->NPC_FindManPoint( vecManPos ); - AI_NavGoal_t goal( vecManPos ); - goal.pTarget = m_hFuncTank; - if ( GetNavigator()->SetGoal( goal ) ) - { - GetNavigator()->SetArrivalDirection( m_hFuncTank->GetAbsAngles() ); - TaskComplete(); - } - else - { - TaskFail("NO PATH"); - - // Don't try and use me again for a while - SetBusy( gpGlobals->curtime + AI_FUNCTANK_BEHAVIOR_BUSYTIME ); - } - break; - } - case TASK_FACE_FUNCTANK: - { - if ( !m_hFuncTank ) - { - TaskFail( FAIL_NO_TARGET ); - return; - } - - // Ensure we've reached the func_tank - Vector vecManPos; - m_hFuncTank->NPC_FindManPoint( vecManPos ); - - // More leniency in Z. - Vector vecDelta = (vecManPos - GetAbsOrigin()); - if ( fabs(vecDelta.x) > 16 || fabs(vecDelta.y) > 16 || fabs(vecDelta.z) > 48 ) - { - TaskFail( "Not correctly on func_tank man point" ); - m_hFuncTank->NPC_InterruptRoute(); - return; - } - - GetMotor()->SetIdealYawToTarget( m_hFuncTank->GetAbsOrigin() ); - GetOuter()->SetTurnActivity(); - break; - } - - case TASK_HOLSTER_WEAPON: - { - if ( !m_hFuncTank ) - { - TaskFail( FAIL_NO_TARGET ); - return; - } - - if ( GetOuter()->IsWeaponHolstered() || !GetOuter()->CanHolsterWeapon() ) - { - GetOuter()->SpeakSentence( FUNCTANK_SENTENCE_JUST_MOUNTED ); - - // We are at the correct position and facing for the func_tank, mount it. - m_hFuncTank->StartControl( GetOuter() ); - GetOuter()->ClearEnemyMemory(); - m_bMounted = true; - TaskComplete(); - - GetOuter()->SetIdealActivity( ACT_IDLE_MANNEDGUN ); - } - else - { - GetOuter()->SetDesiredWeaponState( DESIREDWEAPONSTATE_HOLSTERED ); - } - break; - } - - case TASK_FIRE_FUNCTANK: - { - if ( !m_hFuncTank ) - { - TaskFail( FAIL_NO_TARGET ); - return; - } - GetOuter()->m_flWaitFinished = gpGlobals->curtime + FUNCTANK_FIRE_TIME; - break; - } - case TASK_SCAN_LEFT_FUNCTANK: - { - if ( !m_hFuncTank ) - { - TaskFail( FAIL_NO_TARGET ); - return; - } - - GetMotor()->SetIdealYawToTarget( m_hFuncTank->GetAbsOrigin() ); - - float flCenterYaw = m_hFuncTank->YawCenterWorld(); - float flYawRange = m_hFuncTank->YawRange(); - float flScanAmount = random->RandomFloat( 0, flYawRange ); - QAngle vecTargetAngles( 0, UTIL_AngleMod( flCenterYaw + flScanAmount ), 0 ); - - /* - float flCenterPitch = m_hFuncTank->YawCenterWorld(); - float flPitchRange = m_hFuncTank->PitchRange(); - float flPitch = random->RandomFloat( -flPitchRange, flPitchRange ); - QAngle vecTargetAngles( flCenterPitch + flPitch, UTIL_AngleMod( flCenterYaw + flScanAmount ), 0 ); - */ - - Vector vecTargetForward; - AngleVectors( vecTargetAngles, &vecTargetForward ); - Vector vecTarget = GetOuter()->EyePosition() + (vecTargetForward * 256); - GetOuter()->AddLookTarget( vecTarget, 1.0, 2.0, 0.2 ); - - m_hFuncTank->NPC_SetIdleAngle( vecTarget ); - - break; - } - case TASK_SCAN_RIGHT_FUNCTANK: - { - if ( !m_hFuncTank ) - { - TaskFail( FAIL_NO_TARGET ); - return; - } - - GetMotor()->SetIdealYawToTarget( m_hFuncTank->GetAbsOrigin() ); - - float flCenterYaw = m_hFuncTank->YawCenterWorld(); - float flYawRange = m_hFuncTank->YawRange(); - float flScanAmount = random->RandomFloat( 0, flYawRange ); - QAngle vecTargetAngles( 0, UTIL_AngleMod( flCenterYaw - flScanAmount ), 0 ); - - /* - float flCenterPitch = m_hFuncTank->YawCenterWorld(); - float flPitchRange = m_hFuncTank->PitchRange(); - float flPitch = random->RandomFloat( -flPitchRange, flPitchRange ); - QAngle vecTargetAngles( flCenterPitch + flPitch, UTIL_AngleMod( flCenterYaw - flScanAmount ), 0 ); - */ - - Vector vecTargetForward; - AngleVectors( vecTargetAngles, &vecTargetForward ); - Vector vecTarget = GetOuter()->EyePosition() + (vecTargetForward * 256); - GetOuter()->AddLookTarget( vecTarget, 1.0, 2.0, 0.2 ); - - m_hFuncTank->NPC_SetIdleAngle( vecTarget ); - - break; - } - case TASK_FORGET_ABOUT_FUNCTANK: - { - if ( !m_hFuncTank ) - { - TaskFail( FAIL_NO_TARGET ); - return; - } - break; - } - default: - { - BaseClass::StartTask( pTask ); - break; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_FuncTankBehavior::RunTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_FACE_FUNCTANK: - { - Assert( m_hFuncTank ); - - GetMotor()->UpdateYaw(); - - if ( GetOuter()->FacingIdeal() ) - { - TaskComplete(); - } - break; - } - case TASK_HOLSTER_WEAPON: - { - Assert( m_hFuncTank ); - - if ( GetOuter()->IsWeaponHolstered() ) - { - GetOuter()->SpeakSentence( FUNCTANK_SENTENCE_JUST_MOUNTED ); - - // We are at the correct position and facing for the func_tank, mount it. - m_hFuncTank->StartControl( GetOuter() ); - GetOuter()->ClearEnemyMemory(); - m_bMounted = true; - TaskComplete(); - - GetOuter()->SetIdealActivity( ACT_IDLE_MANNEDGUN ); - } - - break; - } - case TASK_FIRE_FUNCTANK: - { - Assert( m_hFuncTank ); - - if( GetOuter()->m_flWaitFinished < gpGlobals->curtime ) - { - TaskComplete(); - } - - if ( m_hFuncTank->NPC_HasEnemy() ) - { - GetOuter()->SetLastAttackTime( gpGlobals->curtime ); - m_hFuncTank->NPC_Fire(); - - // The NPC may have decided to stop using the func_tank, because it's out of ammo. - if ( !m_hFuncTank ) - { - TaskComplete(); - break; - } - } - else - { - TaskComplete(); - } - - Assert( m_hFuncTank ); - - if ( m_hFuncTank->GetAmmoCount() == 0 ) - { - TaskComplete(); - } - break; - } - case TASK_SCAN_LEFT_FUNCTANK: - case TASK_SCAN_RIGHT_FUNCTANK: - { - GetMotor()->UpdateYaw(); - if ( GetOuter()->FacingIdeal() ) - { - TaskComplete(); - } - break; - } - case TASK_FORGET_ABOUT_FUNCTANK: - { - m_hFuncTank->NPC_InterruptRoute(); - SetBusy( gpGlobals->curtime + AI_FUNCTANK_BEHAVIOR_BUSYTIME ); - TaskComplete(); - break; - } - default: - { - BaseClass::RunTask( pTask ); - break; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_FuncTankBehavior::Event_Killed( const CTakeDamageInfo &info ) -{ - if ( m_hFuncTank ) - { - Dismount(); - } - Assert( !m_hFuncTank ); - - BaseClass::Event_Killed( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_FuncTankBehavior::UpdateOnRemove( void ) -{ - if ( m_hFuncTank ) - { - Dismount(); - } - - BaseClass::UpdateOnRemove(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_FuncTankBehavior::SetFuncTank( CHandle hFuncTank ) -{ - if ( m_hFuncTank && !hFuncTank ) - { - SetBusy( gpGlobals->curtime + AI_FUNCTANK_BEHAVIOR_BUSYTIME ); - SetCondition( COND_FUNCTANK_DISMOUNT ); - } - - m_hFuncTank = hFuncTank; - GetOuter()->ClearSchedule( "Setting a new func_tank" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_FuncTankBehavior::AimGun( void ) -{ - if ( m_bMounted && m_hFuncTank) - { - Vector vecForward; - AngleVectors( m_hFuncTank->GetAbsAngles(), &vecForward ); - GetOuter()->SetAim( vecForward ); - return; - } - - BaseClass::AimGun(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_FuncTankBehavior::GatherConditions() -{ - BaseClass::GatherConditions(); - - // Since we can't pathfind, if we can't see the enemy, he's eluded us - // So we deliberately ignore unreachability - if ( GetEnemy() && !HasCondition(COND_SEE_ENEMY) ) - { - if ( gpGlobals->curtime - GetOuter()->GetEnemyLastTimeSeen() >= 3.0f ) - { - GetOuter()->MarkEnemyAsEluded(); - } - } - - if ( !m_hFuncTank ) - { - m_bMounted = false; - GetOuter()->SetDesiredWeaponState( DESIREDWEAPONSTATE_UNHOLSTERED ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseEntity *CAI_FuncTankBehavior::BestEnemy( void ) -{ - // Only use this BestEnemy call when we are on the manned gun. - if ( !m_hFuncTank ||!IsMounted() ) - return BaseClass::BestEnemy(); - - CBaseEntity *pBestEnemy = NULL; - int iBestDistSq = MAX_COORD_RANGE * MAX_COORD_RANGE; // so first visible entity will become the closest. - int iBestPriority = -1000; - bool bBestUnreachable = false; // Forces initial check - bool bBestSeen = false; - bool bUnreachable = false; - int iDistSq; - - AIEnemiesIter_t iter; - - // Get the current npc for checking from. - CAI_BaseNPC *pNPC = GetOuter(); - if ( !pNPC ) - return NULL; - - for( AI_EnemyInfo_t *pEMemory = GetEnemies()->GetFirst( &iter ); pEMemory != NULL; pEMemory = GetEnemies()->GetNext( &iter ) ) - { - CBaseEntity *pEnemy = pEMemory->hEnemy; - if ( !pEnemy || !pEnemy->IsAlive() ) - continue; - - // UNDONE: Move relationship checks into IsValidEnemy? - if ( ( pEnemy->GetFlags() & FL_NOTARGET ) || - ( pNPC->IRelationType( pEnemy ) != D_HT && pNPC->IRelationType( pEnemy ) != D_FR ) || - !IsValidEnemy( pEnemy ) ) - continue; - - if ( pEMemory->timeLastSeen < pNPC->GetAcceptableTimeSeenEnemy() ) - continue; - - if ( pEMemory->timeValidEnemy > gpGlobals->curtime ) - continue; - - // Skip enemies that have eluded me to prevent infinite loops - if ( GetEnemies()->HasEludedMe( pEnemy ) ) - continue; - - // Establish the reachability of this enemy - bUnreachable = pNPC->IsUnreachable( pEnemy ); - - // Check view cone of the view tank here. - bUnreachable = !m_hFuncTank->IsEntityInViewCone( pEnemy ); - if ( !bUnreachable ) - { - // It's in the viewcone. Now make sure we have LOS to it. - bUnreachable = !m_hFuncTank->HasLOSTo( pEnemy ); - } - - // If best is reachable and current is unreachable, skip the unreachable enemy regardless of priority - if ( !bBestUnreachable && bUnreachable ) - continue; - - // If best is unreachable and current is reachable, always pick the current regardless of priority - if ( bBestUnreachable && !bUnreachable ) - { - bBestSeen = ( pNPC->GetSenses()->DidSeeEntity( pEnemy ) || pNPC->FVisible( pEnemy ) ); // @TODO (toml 04-02-03): Need to optimize CanSeeEntity() so multiple calls in frame do not recalculate, rather cache - iBestPriority = pNPC->IRelationPriority( pEnemy ); - iBestDistSq = (int)(pEnemy->GetAbsOrigin() - GetAbsOrigin()).LengthSqr(); - pBestEnemy = pEnemy; - bBestUnreachable = bUnreachable; - } - // If both are unreachable or both are reachable, chose enemy based on priority and distance - else if ( pNPC->IRelationPriority( pEnemy ) > iBestPriority ) - { - // this entity is disliked MORE than the entity that we - // currently think is the best visible enemy. No need to do - // a distance check, just get mad at this one for now. - iBestPriority = pNPC->IRelationPriority ( pEnemy ); - iBestDistSq = (int)(pEnemy->GetAbsOrigin() - GetAbsOrigin()).LengthSqr(); - pBestEnemy = pEnemy; - bBestUnreachable = bUnreachable; - } - else if ( pNPC->IRelationPriority( pEnemy ) == iBestPriority ) - { - // this entity is disliked just as much as the entity that - // we currently think is the best visible enemy, so we only - // get mad at it if it is closer. - iDistSq = (int)(pEnemy->GetAbsOrigin() - GetAbsOrigin()).LengthSqr(); - - bool bCloser = ( iDistSq < iBestDistSq ) ; - - if ( bCloser || !bBestSeen ) - { - // @TODO (toml 04-02-03): Need to optimize FVisible() so multiple calls in frame do not recalculate, rather cache - bool fSeen = ( pNPC->GetSenses()->DidSeeEntity( pEnemy ) || pNPC->FVisible( pEnemy ) ); - if ( ( bCloser && ( fSeen || !bBestSeen ) ) || ( !bCloser && !bBestSeen && fSeen ) ) - { - bBestSeen = fSeen; - iBestDistSq = iDistSq; - iBestPriority = pNPC->IRelationPriority( pEnemy ); - pBestEnemy = pEnemy; - bBestUnreachable = bUnreachable; - } - } - } - } - return pBestEnemy; -} - -//============================================================================= -// -// Custom AI schedule data -// - -AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( CAI_FuncTankBehavior ) - - DECLARE_TASK( TASK_GET_PATH_TO_FUNCTANK ) - DECLARE_TASK( TASK_FACE_FUNCTANK ) - DECLARE_TASK( TASK_HOLSTER_WEAPON ) - DECLARE_TASK( TASK_FIRE_FUNCTANK ) - DECLARE_TASK( TASK_SCAN_LEFT_FUNCTANK ) - DECLARE_TASK( TASK_SCAN_RIGHT_FUNCTANK ) - DECLARE_TASK( TASK_FORGET_ABOUT_FUNCTANK ) - DECLARE_TASK( TASK_FUNCTANK_ANNOUNCE_SCAN ) - - DECLARE_CONDITION( COND_FUNCTANK_DISMOUNT ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_MOVE_TO_FUNCTANK, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE: SCHED_FAIL_MOVE_TO_FUNCTANK" - " TASK_GET_PATH_TO_FUNCTANK 0" - " TASK_SPEAK_SENTENCE 1000" // FUNCTANK_SENTENCE_MOVE_TO_MOUNT - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_FACE_FUNCTANK 0" - " TASK_HOLSTER_WEAPON 0" - " " - " Interrupts" - " COND_FUNCTANK_DISMOUNT" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_FIRE_FUNCTANK, - - " Tasks" - " TASK_ANNOUNCE_ATTACK 1" // 1 = primary attack - " TASK_FIRE_FUNCTANK 0" - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_LOST_ENEMY" - " COND_ENEMY_OCCLUDED" - " COND_WEAPON_BLOCKED_BY_FRIEND" - " COND_WEAPON_SIGHT_OCCLUDED" - " COND_FUNCTANK_DISMOUNT" - ) - - DEFINE_SCHEDULE - ( - SCHED_SCAN_WITH_FUNCTANK, - - " Tasks" - " TASK_FUNCTANK_ANNOUNCE_SCAN 0" - " TASK_STOP_MOVING 0" - " TASK_WAIT 4" - " TASK_SCAN_LEFT_FUNCTANK 0" - " TASK_WAIT 4" - " TASK_SCAN_RIGHT_FUNCTANK 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_PROVOKED" - " COND_FUNCTANK_DISMOUNT" - ) - - DEFINE_SCHEDULE - ( - SCHED_FAIL_MOVE_TO_FUNCTANK, - - " Tasks" - " TASK_FORGET_ABOUT_FUNCTANK 0" - "" - " Interrupts" - ) - -AI_END_CUSTOM_SCHEDULE_PROVIDER() diff --git a/game/server/hl2/ai_behavior_functank.h b/game/server/hl2/ai_behavior_functank.h deleted file mode 100644 index 002ae52d7..000000000 --- a/game/server/hl2/ai_behavior_functank.h +++ /dev/null @@ -1,120 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef AI_BEHAVIOR_FUNCTANK_H -#define AI_BEHAVIOR_FUNCTANK_H -#ifdef _WIN32 -#pragma once -#endif - -#include "simtimer.h" -#include "ai_behavior.h" -#include "func_tank.h" - -#define AI_FUNCTANK_BEHAVIOR_BUSYTIME 10.0f - -enum -{ - FUNCTANK_SENTENCE_MOVE_TO_MOUNT = SENTENCE_BASE_BEHAVIOR_INDEX, - FUNCTANK_SENTENCE_JUST_MOUNTED, - FUNCTANK_SENTENCE_SCAN_FOR_ENEMIES, - FUNCTANK_SENTENCE_DISMOUNTING, -}; - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CAI_FuncTankBehavior : public CAI_SimpleBehavior -{ - DECLARE_CLASS( CAI_FuncTankBehavior, CAI_SimpleBehavior ); - DEFINE_CUSTOM_SCHEDULE_PROVIDER; - DECLARE_DATADESC(); - -public: - // Contructor/Deconstructor - CAI_FuncTankBehavior(); - ~CAI_FuncTankBehavior(); - - void UpdateOnRemove(); - - // Identifier - const char *GetName() { return "FuncTank"; } - - // Schedule - bool CanSelectSchedule(); - void BeginScheduleSelection(); - void EndScheduleSelection(); - void PrescheduleThink(); - - Activity NPC_TranslateActivity( Activity activity ); - - // Conditions: - virtual void GatherConditions(); - - enum - { - SCHED_MOVE_TO_FUNCTANK = BaseClass::NEXT_SCHEDULE, - SCHED_FIRE_FUNCTANK, - SCHED_SCAN_WITH_FUNCTANK, - SCHED_FAIL_MOVE_TO_FUNCTANK, - }; - - // Tasks - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - - enum - { - TASK_GET_PATH_TO_FUNCTANK = BaseClass::NEXT_TASK, - TASK_FACE_FUNCTANK, - TASK_HOLSTER_WEAPON, - TASK_FIRE_FUNCTANK, - TASK_SCAN_LEFT_FUNCTANK, - TASK_SCAN_RIGHT_FUNCTANK, - TASK_FORGET_ABOUT_FUNCTANK, - TASK_FUNCTANK_ANNOUNCE_SCAN, - }; - - enum - { - COND_FUNCTANK_DISMOUNT = BaseClass::NEXT_CONDITION, - NEXT_CONDITION, - }; - - // Combat. - CBaseEntity *BestEnemy( void ); - void Event_Killed( const CTakeDamageInfo &info ); - - bool HasFuncTank( void ) { return ( m_hFuncTank != NULL ); } - void SetFuncTank( CHandle hFuncTank ); - CFuncTank *GetFuncTank() { return m_hFuncTank; } - void AimGun( void ); - - void Dismount( void ); - - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - - // Time. - void SetBusy( float flTime ) { m_flBusyTime = flTime; } - bool IsBusy( void ) { return ( gpGlobals->curtime < m_flBusyTime ); } - - bool IsMounted( void ) { return m_bMounted; } - -private: - - // Schedule - int SelectSchedule(); - -private: - - CHandle m_hFuncTank; - bool m_bMounted; - float m_flBusyTime; - bool m_bSpottedPlayerOutOfCover; -}; - -#endif // AI_BEHAVIOR_FUNCTANK_H diff --git a/game/server/hl2/ai_behavior_holster.cpp b/game/server/hl2/ai_behavior_holster.cpp deleted file mode 100644 index 44d07da42..000000000 --- a/game/server/hl2/ai_behavior_holster.cpp +++ /dev/null @@ -1,132 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "ai_behavior_holster.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -BEGIN_DATADESC( CAI_HolsterBehavior ) - DEFINE_FIELD( m_bWeaponOut, FIELD_BOOLEAN ), -END_DATADESC(); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CAI_HolsterBehavior::CAI_HolsterBehavior() -{ - // m_AssaultCue = CUE_NO_ASSAULT; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTask - -//----------------------------------------------------------------------------- -void CAI_HolsterBehavior::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_RANGE_ATTACK1: - BaseClass::StartTask( pTask ); - break; - default: - BaseClass::StartTask( pTask ); - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTask - -//----------------------------------------------------------------------------- -void CAI_HolsterBehavior::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_RANGE_ATTACK1: - BaseClass::RunTask( pTask ); - break; - default: - BaseClass::RunTask( pTask ); - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_HolsterBehavior::CanSelectSchedule() -{ - if ( !GetOuter()->IsInterruptable() ) - return false; - - if ( GetOuter()->HasCondition( COND_RECEIVED_ORDERS ) ) - return false; - - if ( GetEnemy() ) - { - // make sure weapon is out - if (!m_bWeaponOut) - { - return true; - } - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CAI_HolsterBehavior::SelectSchedule() -{ - return BaseClass::SelectSchedule(); -} - - - - - - -AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( CAI_HolsterBehavior ) - - DECLARE_TASK( TASK_HOLSTER_WEAPON ) - DECLARE_TASK( TASK_DRAW_WEAPON ) - - // DECLARE_CONDITION( COND_ ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HOLSTER_WEAPON, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_HOLSTER_WEAPON 0" - " " - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_DRAW_WEAPON, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_DRAW_WEAPON 0" - " " - " Interrupts" - ) - -AI_END_CUSTOM_SCHEDULE_PROVIDER() diff --git a/game/server/hl2/ai_behavior_holster.h b/game/server/hl2/ai_behavior_holster.h deleted file mode 100644 index 7348bada5..000000000 --- a/game/server/hl2/ai_behavior_holster.h +++ /dev/null @@ -1,76 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Deal with weapon being out -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - - -#ifndef AI_BEHAVIOR_HOLSTER_H -#define AI_BEHAVIOR_HOLSTER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_behavior.h" - -class CAI_HolsterBehavior : public CAI_SimpleBehavior -{ - DECLARE_CLASS( CAI_HolsterBehavior, CAI_SimpleBehavior ); - -public: - CAI_HolsterBehavior(); - - virtual const char *GetName() { return "Holster"; } - - virtual bool CanSelectSchedule(); - //virtual void BeginScheduleSelection(); - //virtual void EndScheduleSelection(); - - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - //void BuildScheduleTestBits(); - //int TranslateSchedule( int scheduleType ); - //void OnStartSchedule( int scheduleType ); - - //void InitializeBehavior(); - - enum - { - SCHED_HOLSTER_WEAPON = BaseClass::NEXT_SCHEDULE, // Try to get out of the player's way - SCHED_DRAW_WEAPON, - NEXT_SCHEDULE, - - TASK_HOLSTER_WEAPON = BaseClass::NEXT_TASK, - TASK_DRAW_WEAPON, - NEXT_TASK, - -/* - COND_PUT_CONDITIONS_HERE = BaseClass::NEXT_CONDITION, - NEXT_CONDITION, -*/ - }; - - DEFINE_CUSTOM_SCHEDULE_PROVIDER; - -public: - -private: - virtual int SelectSchedule(); - - bool m_bWeaponOut; - - //--------------------------------- - - DECLARE_DATADESC(); -}; - -#endif // AI_BEHAVIOR_HOLSTER_H - - diff --git a/game/server/hl2/ai_behavior_operator.cpp b/game/server/hl2/ai_behavior_operator.cpp deleted file mode 100644 index d1bcca419..000000000 --- a/game/server/hl2/ai_behavior_operator.cpp +++ /dev/null @@ -1,478 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "entitylist.h" -#include "ai_navigator.h" -#include "ai_behavior_operator.h" - - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//============================================================================= -//============================================================================= -// >OPERATOR BEHAVIOR -//============================================================================= -//============================================================================= -BEGIN_DATADESC( CAI_OperatorBehavior ) - DEFINE_FIELD( m_hGoalEntity, FIELD_EHANDLE ), - DEFINE_FIELD( m_hPositionEnt, FIELD_EHANDLE ), - DEFINE_FIELD( m_hContextTarget, FIELD_EHANDLE ), - DEFINE_EMBEDDED( m_WatchSeeEntity ), -END_DATADESC(); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CAI_OperatorBehavior::CAI_OperatorBehavior() -{ - m_hPositionEnt.Set(NULL); - m_hGoalEntity.Set(NULL); - m_hContextTarget.Set(NULL); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -#define POSITION_ENT_ALWAYS_SEE_DIST Square(120) -bool CAI_OperatorBehavior::CanSeePositionEntity() -{ - CAI_BaseNPC *pOuter = GetOuter(); - - Assert( m_hPositionEnt.Get() != NULL ); - - // early out here. - if( !pOuter->QuerySeeEntity(m_hPositionEnt) ) - { - m_WatchSeeEntity.Stop(); - return false; - } - - bool bSpotted = (pOuter->EyePosition().DistToSqr(m_hPositionEnt->GetAbsOrigin()) <= POSITION_ENT_ALWAYS_SEE_DIST); - if ( !bSpotted ) - { - bSpotted = ( pOuter->FInViewCone(m_hPositionEnt) && pOuter->FVisible(m_hPositionEnt) ); - } - - if (bSpotted ) - { - // If we haven't seen it up until now, start a timer. If we have seen it, wait for the - // timer to finish. This prevents edge cases where turning on the flashlight makes - // NPC spot the position entity a frame before she spots an enemy. - if ( !m_WatchSeeEntity.IsRunning() ) - { - m_WatchSeeEntity.Start( 0.3,0.31 ); - return false; - } - - if ( !m_WatchSeeEntity.Expired() ) - return false; - - return true; - } - - m_WatchSeeEntity.Stop(); - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CAI_OperatorBehavior::IsAtPositionEntity() -{ - Vector myPos = GetAbsOrigin(); - Vector objectPos = m_hPositionEnt->GetAbsOrigin(); - - Vector vecDir = objectPos - myPos; - - return (vecDir.Length2D() <= 12.0f); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_OperatorBehavior::GatherConditionsNotActive() -{ - if( m_hPositionEnt ) - { - // If we're not currently the active behavior, we have a position ent, and the - // NPC can see it, coax the AI out of IDLE/ALERT schedules with this condition. - if( CanSeePositionEntity() ) - { - SetCondition( COND_IDLE_INTERRUPT ); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_OperatorBehavior::GatherConditions( void ) -{ - if( GetGoalEntity() ) - { - if( GetGoalEntity()->GetState() == OPERATOR_STATE_FINISHED ) - { - if( IsCurSchedule(SCHED_OPERATOR_OPERATE) ) - { - // Break us out of the operator schedule if the operation completes. - SetCondition(COND_PROVOKED); - } - - m_hGoalEntity.Set(NULL); - m_hPositionEnt.Set(NULL); - } - else - { - if( CanSeePositionEntity() ) - { - ClearCondition( COND_OPERATOR_LOST_SIGHT_OF_POSITION ); - } - else - { - SetCondition( COND_OPERATOR_LOST_SIGHT_OF_POSITION ); - } - } - } - - BaseClass::GatherConditions(); - - // Ignore player pushing. - ClearCondition( COND_PLAYER_PUSHING ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTask - -//----------------------------------------------------------------------------- -void CAI_OperatorBehavior::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_OPERATOR_OPERATE: - { - // Fire the appropriate output! - switch( GetGoalEntity()->GetState() ) - { - case OPERATOR_STATE_NOT_READY: - GetGoalEntity()->m_OnMakeReady.FireOutput(NULL, NULL, 0); - break; - - case OPERATOR_STATE_READY: - GetGoalEntity()->m_OnBeginOperating.FireOutput(NULL, NULL, 0); - break; - - default: - //!!!HACKHACK - Assert(0); - break; - } - } - TaskComplete(); - break; - - case TASK_OPERATOR_START_PATH: - { - ChainStartTask(TASK_WALK_PATH); - } - break; - - case TASK_OPERATOR_GET_PATH_TO_POSITION: - { - CBaseEntity *pGoal = m_hPositionEnt; - - if( !pGoal ) - { - TaskFail("ai_goal_operator has no location entity\n"); - break; - } - - AI_NavGoal_t goal( pGoal->GetAbsOrigin() ); - goal.pTarget = pGoal; - - if ( GetNavigator()->SetGoal( goal ) == false ) - { - TaskFail( "Can't build path\n" ); - /* - // Try and get as close as possible otherwise - AI_NavGoal_t nearGoal( GOALTYPE_LOCATION_NEAREST_NODE, m_hTargetObject->GetAbsOrigin(), AIN_DEF_ACTIVITY, 256 ); - if ( GetNavigator()->SetGoal( nearGoal, AIN_CLEAR_PREVIOUS_STATE ) ) - { - //FIXME: HACK! The internal pathfinding is setting this without our consent, so override it! - ClearCondition( COND_TASK_FAILED ); - GetNavigator()->SetArrivalDirection( m_hTargetObject->GetAbsAngles() ); - TaskComplete(); - return; - } - */ - } - - GetNavigator()->SetArrivalDirection( pGoal->GetAbsAngles() ); - } - break; - - default: - BaseClass::StartTask( pTask ); - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTask - -//----------------------------------------------------------------------------- -void CAI_OperatorBehavior::RunTask( const Task_t *pTask ) -{ -/* - switch( pTask->iTask ) - { - default: - BaseClass::RunTask( pTask ); - break; - } -*/ - BaseClass::RunTask( pTask ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CAI_OperatorGoal *CAI_OperatorBehavior::GetGoalEntity() -{ - CAI_OperatorGoal *pGoal = dynamic_cast(m_hGoalEntity.Get()); - - // NULL is OK. - return pGoal; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CAI_OperatorBehavior::IsGoalReady() -{ - if( GetGoalEntity()->GetState() == OPERATOR_STATE_READY ) - { - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_OperatorBehavior::SetParameters( CAI_OperatorGoal *pGoal, CBaseEntity *pPositionEnt, CBaseEntity *pContextTarget ) -{ - m_hGoalEntity.Set( pGoal ); - m_hPositionEnt.Set( pPositionEnt ); - m_hContextTarget.Set( pContextTarget ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_OperatorBehavior::CanSelectSchedule() -{ - if ( m_hGoalEntity.Get() == NULL ) - return false; - - if ( m_hPositionEnt.Get() == NULL ) - return false; - - if( GetGoalEntity()->GetState() == OPERATOR_STATE_FINISHED ) - { - m_hGoalEntity.Set(NULL); - m_hPositionEnt.Set(NULL); - return false; - } - - if ( !GetOuter()->IsInterruptable() ) - return false; - - if ( GetOuter()->m_NPCState == NPC_STATE_COMBAT || GetOuter()->m_NPCState == NPC_STATE_SCRIPT ) - return false; - - // Don't grab NPCs who have been in combat recently - if ( GetOuter()->GetLastEnemyTime() && (gpGlobals->curtime - GetOuter()->GetLastEnemyTime()) < 3.0 ) - return false; - - if( !CanSeePositionEntity() ) - return false; - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CAI_OperatorBehavior::SelectSchedule() -{ - if( !IsAtPositionEntity() ) - { - GetGoalEntity()->m_OnBeginApproach.FireOutput( GetOuter(), GetOuter(), 0 ); - return SCHED_OPERATOR_APPROACH_POSITION; - } - - if( GetGoalEntity() && GetGoalEntity()->GetState() != OPERATOR_STATE_FINISHED) - { - if( GetOuter()->GetActiveWeapon() && !GetOuter()->IsWeaponHolstered() ) - { - GetOuter()->SetDesiredWeaponState( DESIREDWEAPONSTATE_HOLSTERED ); - return SCHED_OPERATOR_WAIT_FOR_HOLSTER; - } - - return SCHED_OPERATOR_OPERATE; - } - - return BaseClass::SelectSchedule(); -} - - -//============================================================================= -//============================================================================= -// >AI_GOAL_OPERATOR -//============================================================================= -//============================================================================= -LINK_ENTITY_TO_CLASS( ai_goal_operator, CAI_OperatorGoal ); - -BEGIN_DATADESC( CAI_OperatorGoal ) - DEFINE_KEYFIELD( m_iState, FIELD_INTEGER, "state" ), - DEFINE_KEYFIELD( m_iMoveTo, FIELD_INTEGER, "moveto" ), - DEFINE_KEYFIELD( m_iszContextTarget, FIELD_STRING, "contexttarget" ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "SetStateReady", InputSetStateReady ), - DEFINE_INPUTFUNC( FIELD_VOID, "SetStateFinished", InputSetStateFinished ), - DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ), - - // Outputs - DEFINE_OUTPUT( m_OnBeginApproach, "OnBeginApproach" ), - DEFINE_OUTPUT( m_OnMakeReady, "OnMakeReady" ), - DEFINE_OUTPUT( m_OnBeginOperating, "OnBeginOperating" ), - DEFINE_OUTPUT( m_OnFinished, "OnFinished" ), -END_DATADESC() - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_OperatorGoal::EnableGoal( CAI_BaseNPC *pAI ) -{ - CAI_OperatorBehavior *pBehavior; - - if ( !pAI->GetBehavior( &pBehavior ) ) - { - return; - } - - CBaseEntity *pPosition = gEntList.FindEntityByName(NULL, m_target); - - if( !pPosition ) - { - DevMsg("ai_goal_operator called %s with invalid position ent!\n", GetDebugName() ); - return; - } - - - CBaseEntity *pContextTarget = NULL; - - if( m_iszContextTarget != NULL_STRING ) - { - pContextTarget = gEntList.FindEntityByName( NULL, m_iszContextTarget ); - } - - pBehavior->SetParameters(this, pPosition, pContextTarget); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAI_OperatorGoal::InputActivate( inputdata_t &inputdata ) -{ - BaseClass::InputActivate( inputdata ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAI_OperatorGoal::InputDeactivate( inputdata_t &inputdata ) -{ - BaseClass::InputDeactivate( inputdata ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_OperatorGoal::InputSetStateReady( inputdata_t &inputdata ) -{ - m_iState = OPERATOR_STATE_READY; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_OperatorGoal::InputSetStateFinished( inputdata_t &inputdata ) -{ - m_iState = OPERATOR_STATE_FINISHED; - m_OnFinished.FireOutput( NULL, NULL, 0 ); -} - -//============================================================================= -//============================================================================= -// >SCHEDULES -//============================================================================= -//============================================================================= -AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( CAI_OperatorBehavior ) - -DECLARE_TASK( TASK_OPERATOR_GET_PATH_TO_POSITION ) -DECLARE_TASK( TASK_OPERATOR_START_PATH ) -DECLARE_TASK( TASK_OPERATOR_OPERATE ) - -DECLARE_CONDITION( COND_OPERATOR_LOST_SIGHT_OF_POSITION ) - -//========================================================= -//========================================================= -DEFINE_SCHEDULE -( - SCHED_OPERATOR_APPROACH_POSITION, - " Tasks" - " TASK_OPERATOR_GET_PATH_TO_POSITION 0" - " TASK_OPERATOR_START_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_HEAR_DANGER" - " COND_OPERATOR_LOST_SIGHT_OF_POSITION" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_OPERATOR_OPERATE, - " Tasks" - " TASK_WAIT 0.2" // Allow pending entity I/O to settle - " TASK_OPERATOR_OPERATE 0" - " TASK_WAIT_INDEFINITE 0" - " " - " Interrupts" - " COND_PROVOKED" - ) - -//========================================================= -//========================================================= -DEFINE_SCHEDULE -( - SCHED_OPERATOR_WAIT_FOR_HOLSTER, - " Tasks" - " TASK_WAIT 1.0" - " " - " Interrupts" - " " - ) - - AI_END_CUSTOM_SCHEDULE_PROVIDER() diff --git a/game/server/hl2/ai_behavior_operator.h b/game/server/hl2/ai_behavior_operator.h deleted file mode 100644 index 0f24df241..000000000 --- a/game/server/hl2/ai_behavior_operator.h +++ /dev/null @@ -1,144 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Operate consoles/machinery in the world. -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - - -#ifndef AI_BEHAVIOR_OPERATOR_H -#define AI_BEHAVIOR_OPERATOR_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_behavior.h" -#include "ai_goalentity.h" - -enum -{ - OPERATOR_STATE_NOT_READY = 0, - OPERATOR_STATE_READY, - OPERATOR_STATE_FINISHED, -}; - -enum -{ - OPERATOR_MOVETO_RESERVED = 0, - OPERATOR_MOVETO_WALK, - OPERATOR_MOVETO_RUN, -}; - -//========================================================= -//========================================================= -class CAI_OperatorGoal : public CAI_GoalEntity -{ - DECLARE_CLASS( CAI_OperatorGoal, CAI_GoalEntity ); -public: - CAI_OperatorGoal() - { - } - - void EnableGoal( CAI_BaseNPC *pAI ); - - int GetState() { return m_iState; } - int GetMoveTo() { return m_iMoveTo; } - - // Inputs - virtual void InputActivate( inputdata_t &inputdata ); - virtual void InputDeactivate( inputdata_t &inputdata ); - - void InputSetStateReady( inputdata_t &inputdata ); - void InputSetStateFinished( inputdata_t &inputdata ); - - COutputEvent m_OnBeginApproach; - COutputEvent m_OnMakeReady; - COutputEvent m_OnBeginOperating; - COutputEvent m_OnFinished; - - DECLARE_DATADESC(); - -protected: - int m_iState; - int m_iMoveTo; - string_t m_iszContextTarget; -}; - -//========================================================= -//========================================================= -class CAI_OperatorBehavior : public CAI_SimpleBehavior -{ - DECLARE_CLASS( CAI_OperatorBehavior, CAI_SimpleBehavior ); - -public: - CAI_OperatorBehavior(); - - virtual const char *GetName() { return "Operator"; } - - virtual void SetParameters( CAI_OperatorGoal *pGoal, CBaseEntity *pPositionEnt, CBaseEntity *pContextTarget ); - - virtual bool CanSelectSchedule(); - //virtual void BeginScheduleSelection(); - //virtual void EndScheduleSelection(); - - bool CanSeePositionEntity(); - bool IsAtPositionEntity(); - - void GatherConditionsNotActive(); - void GatherConditions( void ); - - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - - CAI_OperatorGoal *GetGoalEntity(); - - bool IsGoalReady(); - - //void BuildScheduleTestBits(); - //int TranslateSchedule( int scheduleType ); - //void OnStartSchedule( int scheduleType ); - - //void InitializeBehavior(); - - enum - { - SCHED_OPERATOR_APPROACH_POSITION = BaseClass::NEXT_SCHEDULE, - SCHED_OPERATOR_MAKE_READY, - SCHED_OPERATOR_OPERATE, - SCHED_OPERATOR_WAIT_FOR_HOLSTER, - NEXT_SCHEDULE, - - TASK_OPERATOR_GET_PATH_TO_POSITION = BaseClass::NEXT_TASK, - TASK_OPERATOR_START_PATH, - TASK_OPERATOR_OPERATE, - NEXT_TASK, - - COND_OPERATOR_LOST_SIGHT_OF_POSITION = BaseClass::NEXT_CONDITION, - NEXT_CONDITION, - }; - - DEFINE_CUSTOM_SCHEDULE_PROVIDER; - -public: - EHANDLE m_hGoalEntity; - EHANDLE m_hPositionEnt; - EHANDLE m_hContextTarget; - CRandStopwatch m_WatchSeeEntity; - -private: - virtual int SelectSchedule(); - - //--------------------------------- - - DECLARE_DATADESC(); -}; - -#endif // AI_BEHAVIOR_OPERATOR_H - - diff --git a/game/server/hl2/ai_behavior_police.cpp b/game/server/hl2/ai_behavior_police.cpp deleted file mode 100644 index 7122c8ad2..000000000 --- a/game/server/hl2/ai_behavior_police.cpp +++ /dev/null @@ -1,783 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" - -#include "ai_behavior_police.h" -#include "ai_navigator.h" -#include "ai_memory.h" -#include "collisionutils.h" -#include "npc_metropolice.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -BEGIN_DATADESC( CAI_PolicingBehavior ) - - DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bStartPolicing, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hPoliceGoal, FIELD_EHANDLE ), - DEFINE_FIELD( m_flNextHarassTime, FIELD_TIME ), - DEFINE_FIELD( m_flAggressiveTime, FIELD_TIME ), - DEFINE_FIELD( m_nNumWarnings, FIELD_INTEGER ), - DEFINE_FIELD( m_bTargetIsHostile, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flTargetHostileTime,FIELD_TIME ), - -END_DATADESC(); - -CAI_PolicingBehavior::CAI_PolicingBehavior( void ) -{ - m_bEnabled = false; - m_nNumWarnings = 0; - m_bTargetIsHostile = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PolicingBehavior::TargetIsHostile( void ) -{ - if ( ( m_flTargetHostileTime < gpGlobals->curtime ) && ( !m_bTargetIsHostile ) ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pGoal - -//----------------------------------------------------------------------------- -void CAI_PolicingBehavior::Enable( CAI_PoliceGoal *pGoal ) -{ - m_hPoliceGoal = pGoal; - m_bEnabled = true; - - m_bStartPolicing = true; - - // Update ourselves immediately - GetOuter()->ClearSchedule( "Enable police behavior" ); - //NotifyChangeBehaviorStatus( GetOuter()->IsInAScript() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PolicingBehavior::Disable( void ) -{ - m_hPoliceGoal = NULL; - m_bEnabled = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PolicingBehavior::CanSelectSchedule( void ) -{ - // Must be activated and valid - if ( IsEnabled() == false || !m_hPoliceGoal || !m_hPoliceGoal->GetTarget() ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : false - -//----------------------------------------------------------------------------- -void CAI_PolicingBehavior::HostSetBatonState( bool state ) -{ - // If we're a cop, turn the baton on - CNPC_MetroPolice *pCop = dynamic_cast(GetOuter()); - - if ( pCop != NULL ) - { - pCop->SetBatonState( state ); - pCop->SetTarget( m_hPoliceGoal->GetTarget() ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : false - -//----------------------------------------------------------------------------- -bool CAI_PolicingBehavior::HostBatonIsOn( void ) -{ - // If we're a cop, turn the baton on - CNPC_MetroPolice *pCop = dynamic_cast(GetOuter()); - if ( pCop ) - return pCop->BatonActive(); - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PolicingBehavior::HostSpeakSentence( const char *pSentence, SentencePriority_t nSoundPriority, SentenceCriteria_t nCriteria ) -{ - // If we're a cop, turn the baton on - CNPC_MetroPolice *pCop = dynamic_cast(GetOuter()); - - if ( pCop != NULL ) - { - CAI_Sentence< CNPC_MetroPolice > *pSentences = pCop->GetSentences(); - - pSentences->Speak( pSentence, nSoundPriority, nCriteria ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PolicingBehavior::BuildScheduleTestBits( void ) -{ - if ( IsCurSchedule( SCHED_IDLE_STAND ) || IsCurSchedule( SCHED_ALERT_STAND ) ) - { - if ( m_flNextHarassTime < gpGlobals->curtime ) - { - GetOuter()->SetCustomInterruptCondition( GetClassScheduleIdSpace()->ConditionLocalToGlobal( COND_POLICE_TARGET_TOO_CLOSE_HARASS ) ); - } - - GetOuter()->SetCustomInterruptCondition( GetClassScheduleIdSpace()->ConditionLocalToGlobal( COND_POLICE_TARGET_TOO_CLOSE_SUPPRESS ) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PolicingBehavior::GatherConditions( void ) -{ - BaseClass::GatherConditions(); - - // Mapmaker may have removed our goal while we're running our schedule - if ( !m_hPoliceGoal ) - { - Disable(); - return; - } - - ClearCondition( COND_POLICE_TARGET_TOO_CLOSE_HARASS ); - ClearCondition( COND_POLICE_TARGET_TOO_CLOSE_SUPPRESS ); - - CBaseEntity *pTarget = m_hPoliceGoal->GetTarget(); - - if ( pTarget == NULL ) - { - DevMsg( "ai_goal_police with NULL target entity!\n" ); - return; - } - - // See if we need to knock out our target immediately - if ( ShouldKnockOutTarget( pTarget ) ) - { - SetCondition( COND_POLICE_TARGET_TOO_CLOSE_SUPPRESS ); - } - - float flDistSqr = ( m_hPoliceGoal->WorldSpaceCenter() - pTarget->WorldSpaceCenter() ).Length2DSqr(); - float radius = ( m_hPoliceGoal->GetRadius() * PATROL_RADIUS_RATIO ); - float zDiff = fabs( m_hPoliceGoal->WorldSpaceCenter().z - pTarget->WorldSpaceCenter().z ); - - // If we're too far away, don't bother - if ( flDistSqr < (radius*radius) && zDiff < 32.0f ) - { - SetCondition( COND_POLICE_TARGET_TOO_CLOSE_HARASS ); - - if ( flDistSqr < (m_hPoliceGoal->GetRadius()*m_hPoliceGoal->GetRadius()) ) - { - SetCondition( COND_POLICE_TARGET_TOO_CLOSE_SUPPRESS ); - } - } - - // If we're supposed to stop chasing (aggression over), return - if ( m_bTargetIsHostile && m_flAggressiveTime < gpGlobals->curtime && IsCurSchedule(SCHED_CHASE_ENEMY) ) - { - // Force me to re-evaluate my schedule - GetOuter()->ClearSchedule( "Stopped chasing, aggression over" ); - } -} - -//----------------------------------------------------------------------------- -// We're taking cover from danger -//----------------------------------------------------------------------------- -void CAI_PolicingBehavior::AnnouncePolicing( void ) -{ - // We're policing - static const char *pWarnings[3] = - { - "METROPOLICE_MOVE_ALONG_A", - "METROPOLICE_MOVE_ALONG_B", - "METROPOLICE_MOVE_ALONG_C", - }; - - if ( m_nNumWarnings <= 3 ) - { - HostSpeakSentence( pWarnings[ m_nNumWarnings - 1 ], SENTENCE_PRIORITY_MEDIUM, SENTENCE_CRITERIA_NORMAL ); - } - else - { - // We loop at m_nNumWarnings == 4 for players who aren't moving - // but still pissing us off, and we're not allowed to do anything about it. (i.e. can't leave post) - // First two sentences sound pretty good, so randomly pick one of them. - int iSentence = RandomInt( 0, 1 ); - HostSpeakSentence( pWarnings[ iSentence ], SENTENCE_PRIORITY_MEDIUM, SENTENCE_CRITERIA_NORMAL ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : scheduleType - -// Output : int -//----------------------------------------------------------------------------- -int CAI_PolicingBehavior::TranslateSchedule( int scheduleType ) -{ - if ( scheduleType == SCHED_CHASE_ENEMY ) - { - if ( m_hPoliceGoal->ShouldRemainAtPost() && !MaintainGoalPosition() ) - return BaseClass::TranslateSchedule( SCHED_COMBAT_FACE ); - } - - return BaseClass::TranslateSchedule( scheduleType ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : newActivity - -// Output : Activity -//----------------------------------------------------------------------------- -Activity CAI_PolicingBehavior::NPC_TranslateActivity( Activity newActivity ) -{ - // See which harassment to play - if ( newActivity == ACT_POLICE_HARASS1 ) - { - switch( m_nNumWarnings ) - { - case 1: - return (Activity) ACT_POLICE_HARASS1; - break; - - default: - case 2: - return (Activity) ACT_POLICE_HARASS2; - break; - } - } - - return BaseClass::NPC_TranslateActivity( newActivity ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CBaseEntity -//----------------------------------------------------------------------------- -CBaseEntity *CAI_PolicingBehavior::GetGoalTarget( void ) -{ - if ( m_hPoliceGoal == NULL ) - { - //NOTENOTE: This has been called before the behavior is actually active, or the goal has gone invalid - Assert(0); - return NULL; - } - - return m_hPoliceGoal->GetTarget(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : time - -//----------------------------------------------------------------------------- -void CAI_PolicingBehavior::SetTargetHostileDuration( float time ) -{ - m_flTargetHostileTime = gpGlobals->curtime + time; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTask - -//----------------------------------------------------------------------------- -void CAI_PolicingBehavior::StartTask( const Task_t *pTask ) -{ - switch (pTask->iTask) - { - case TASK_POLICE_GET_PATH_TO_HARASS_GOAL: - { - Vector harassDir = ( m_hPoliceGoal->GetTarget()->WorldSpaceCenter() - WorldSpaceCenter() ); - float flDist = VectorNormalize( harassDir ); - - // See if we're already close enough - if ( flDist < pTask->flTaskData ) - { - TaskComplete(); - break; - } - - float flInter1, flInter2; - Vector harassPos = GetAbsOrigin() + ( harassDir * ( flDist - pTask->flTaskData ) ); - - // Find a point on our policing radius to stand on - if ( IntersectInfiniteRayWithSphere( GetAbsOrigin(), harassDir, m_hPoliceGoal->GetAbsOrigin(), m_hPoliceGoal->GetRadius(), &flInter1, &flInter2 ) ) - { - Vector vPos = m_hPoliceGoal->GetAbsOrigin() + harassDir * ( MAX( flInter1, flInter2 ) ); - - // See how far away the default one is - float testDist = UTIL_DistApprox2D( m_hPoliceGoal->GetAbsOrigin(), harassPos ); - - // If our other goal is closer, choose it - if ( testDist > UTIL_DistApprox2D( m_hPoliceGoal->GetAbsOrigin(), vPos ) ) - { - harassPos = vPos; - } - } - - if ( GetNavigator()->SetGoal( harassPos, (int)pTask->flTaskData ) ) - { - GetNavigator()->SetMovementActivity( (Activity) ACT_WALK_ANGRY ); - GetNavigator()->SetArrivalDirection( m_hPoliceGoal->GetTarget() ); - TaskComplete(); - } - else - { - TaskFail( FAIL_NO_ROUTE ); - } - } - break; - - case TASK_POLICE_GET_PATH_TO_POLICE_GOAL: - { - if ( GetNavigator()->SetGoal( m_hPoliceGoal->GetAbsOrigin(), (int)pTask->flTaskData ) ) - { - GetNavigator()->SetArrivalDirection( m_hPoliceGoal->GetAbsAngles() ); - TaskComplete(); - } - else - { - TaskFail( FAIL_NO_ROUTE ); - } - } - break; - - case TASK_POLICE_ANNOUNCE_HARASS: - { - AnnouncePolicing(); - - // Randomly say this again in the future - m_flNextHarassTime = gpGlobals->curtime + random->RandomInt( 4, 6 ); - - // Scatter rubber-neckers - CSoundEnt::InsertSound( SOUND_MOVE_AWAY, GetAbsOrigin(), 256, 2.0f, GetOuter() ); - } - TaskComplete(); - break; - - case TASK_POLICE_FACE_ALONG_GOAL: - { - // We may have lost our police goal in the 2 seconds we wait before this task - if ( m_hPoliceGoal ) - { - GetMotor()->SetIdealYaw( m_hPoliceGoal->GetAbsAngles().y ); - GetOuter()->SetTurnActivity(); - } - } - break; - - default: - BaseClass::StartTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_PolicingBehavior::RunTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_POLICE_FACE_ALONG_GOAL: - { - GetMotor()->UpdateYaw(); - - if ( GetOuter()->FacingIdeal() ) - { - TaskComplete(); - } - break; - } - - default: - BaseClass::RunTask( pTask); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PolicingBehavior::MaintainGoalPosition( void ) -{ - Vector vecOrg = GetAbsOrigin(); - Vector vecTarget = m_hPoliceGoal->GetAbsOrigin(); - - // Allow some slop on Z - if ( fabs(vecOrg.z - vecTarget.z) > 64 ) - return true; - - // Need to be very close on X/Y - if ( (vecOrg - vecTarget).Length2D() > 16 ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PolicingBehavior::ShouldKnockOutTarget( CBaseEntity *pTarget ) -{ - if ( m_hPoliceGoal == NULL ) - { - //NOTENOTE: This has been called before the behavior is actually active, or the goal has gone invalid - Assert(0); - return false; - } - - bool bVisible = GetOuter()->FVisible( pTarget ); - return m_hPoliceGoal->ShouldKnockOutTarget( pTarget->WorldSpaceCenter(), bVisible ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTarget - -//----------------------------------------------------------------------------- -void CAI_PolicingBehavior::KnockOutTarget( CBaseEntity *pTarget ) -{ - if ( m_hPoliceGoal == NULL ) - { - //NOTENOTE: This has been called before the behavior is actually active, or the goal has gone invalid - Assert(0); - return; - } - - m_hPoliceGoal->KnockOutTarget( pTarget ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CAI_PolicingBehavior::SelectSuppressSchedule( void ) -{ - CBaseEntity *pTarget = m_hPoliceGoal->GetTarget(); - - m_flAggressiveTime = gpGlobals->curtime + 4.0f; - - if ( m_bTargetIsHostile == false ) - { - // Mark this as a valid target - m_bTargetIsHostile = true; - - // Attack the target - GetOuter()->SetEnemy( pTarget ); - GetOuter()->SetState( NPC_STATE_COMBAT ); - GetOuter()->UpdateEnemyMemory( pTarget, pTarget->GetAbsOrigin() ); - - HostSetBatonState( true ); - - // Remember that we're angry with the target - m_nNumWarnings = POLICE_MAX_WARNINGS; - - // We need to let the system pickup the new enemy and deal with it on the next frame - return SCHED_COMBAT_FACE; - } - - // If we're supposed to stand still, then we need to show aggression - if ( m_hPoliceGoal->ShouldRemainAtPost() ) - { - // If we're off our mark, fight to it - if ( MaintainGoalPosition() ) - { - return SCHED_CHASE_ENEMY; - } - - //FIXME: This needs to be a more aggressive warning to the player - if ( m_flNextHarassTime < gpGlobals->curtime ) - { - return SCHED_POLICE_WARN_TARGET; - } - else - { - return SCHED_COMBAT_FACE; - } - } - - return SCHED_CHASE_ENEMY; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CAI_PolicingBehavior::SelectHarassSchedule( void ) -{ - CBaseEntity *pTarget = m_hPoliceGoal->GetTarget(); - - m_flAggressiveTime = gpGlobals->curtime + 4.0f; - - // If we just started to police, make sure we're on our mark - if ( MaintainGoalPosition() ) - return SCHED_POLICE_RETURN_FROM_HARASS; - - // Look at the target if they're too close - GetOuter()->AddLookTarget( pTarget, 0.5f, 5.0f ); - - // Say something if it's been long enough - if ( m_flNextHarassTime < gpGlobals->curtime ) - { - // Gesture the player away - GetOuter()->SetTarget( pTarget ); - - // Send outputs for each level of warning - if ( m_nNumWarnings == 0 ) - { - m_hPoliceGoal->FireWarningLevelOutput( 1 ); - } - else if ( m_nNumWarnings == 1 ) - { - m_hPoliceGoal->FireWarningLevelOutput( 2 ); - } - - if ( m_nNumWarnings < POLICE_MAX_WARNINGS ) - { - m_nNumWarnings++; - } - - // If we're over our limit, just suppress the offender - if ( m_nNumWarnings >= POLICE_MAX_WARNINGS ) - { - if ( m_bTargetIsHostile == false ) - { - // Mark the target as a valid target - m_bTargetIsHostile = true; - - GetOuter()->SetEnemy( pTarget ); - GetOuter()->SetState( NPC_STATE_COMBAT ); - GetOuter()->UpdateEnemyMemory( pTarget, pTarget->GetAbsOrigin() ); - HostSetBatonState( true ); - - m_hPoliceGoal->FireWarningLevelOutput( 4 ); - - return SCHED_COMBAT_FACE; - } - - if ( m_hPoliceGoal->ShouldRemainAtPost() == false ) - return SCHED_CHASE_ENEMY; - } - - // On our last warning, approach the target - if ( m_nNumWarnings == (POLICE_MAX_WARNINGS-1) ) - { - m_hPoliceGoal->FireWarningLevelOutput( 3 ); - - GetOuter()->SetTarget( pTarget ); - - HostSetBatonState( true ); - - if ( m_hPoliceGoal->ShouldRemainAtPost() == false ) - return SCHED_POLICE_HARASS_TARGET; - } - - // Otherwise just verbally warn him - return SCHED_POLICE_WARN_TARGET; - } - - return SCHED_NONE; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CAI_PolicingBehavior::SelectSchedule( void ) -{ - CBaseEntity *pTarget = m_hPoliceGoal->GetTarget(); - - // Validate our target - if ( pTarget == NULL ) - { - DevMsg( "ai_goal_police with NULL target entity!\n" ); - - // Turn us off - Disable(); - return SCHED_NONE; - } - - // Attack if we're supposed to - if ( ( m_flAggressiveTime >= gpGlobals->curtime ) && HasCondition( COND_CAN_MELEE_ATTACK1 ) ) - { - return SCHED_MELEE_ATTACK1; - } - - // See if we should immediately begin to attack our target - if ( HasCondition( COND_POLICE_TARGET_TOO_CLOSE_SUPPRESS ) ) - { - return SelectSuppressSchedule(); - } - - int newSchedule = SCHED_NONE; - - // See if we're harassing - if ( HasCondition( COND_POLICE_TARGET_TOO_CLOSE_HARASS ) ) - { - newSchedule = SelectHarassSchedule(); - } - - // Return that schedule if it was found - if ( newSchedule != SCHED_NONE ) - return newSchedule; - - // If our enemy is set, fogeda'bout it! - if ( m_flAggressiveTime < gpGlobals->curtime ) - { - // Return to your initial spot - if ( GetEnemy() ) - { - GetOuter()->SetEnemy( NULL ); - GetOuter()->SetState( NPC_STATE_ALERT ); - GetOuter()->GetEnemies()->RefreshMemories(); - } - - HostSetBatonState( false ); - m_bTargetIsHostile = false; - } - - // If we just started to police, make sure we're on our mark - if ( MaintainGoalPosition() ) - return SCHED_POLICE_RETURN_FROM_HARASS; - - // If I've got my baton on, keep looking at the target - if ( HostBatonIsOn() ) - return SCHED_POLICE_TRACK_TARGET; - - // Re-align myself to the goal angles if I've strayed - if ( fabs(UTIL_AngleDiff( GetAbsAngles().y, m_hPoliceGoal->GetAbsAngles().y )) > 15 ) - return SCHED_POLICE_FACE_ALONG_GOAL; - - return SCHED_IDLE_STAND; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CAI_PolicingBehavior::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ) -{ - if ( failedSchedule == SCHED_CHASE_ENEMY ) - { - // We've failed to chase our enemy, return to where we were came from - if ( MaintainGoalPosition() ) - return SCHED_POLICE_RETURN_FROM_HARASS; - - return SCHED_POLICE_WARN_TARGET; - } - - return BaseClass::SelectFailSchedule( failedSchedule, failedTask, taskFailCode ); -} - -//------------------------------------- - -AI_BEGIN_CUSTOM_SCHEDULE_PROVIDER( CAI_PolicingBehavior ) - - DECLARE_CONDITION( COND_POLICE_TARGET_TOO_CLOSE_HARASS ); - DECLARE_CONDITION( COND_POLICE_TARGET_TOO_CLOSE_SUPPRESS ); - - DECLARE_TASK( TASK_POLICE_GET_PATH_TO_HARASS_GOAL ); - DECLARE_TASK( TASK_POLICE_GET_PATH_TO_POLICE_GOAL ); - DECLARE_TASK( TASK_POLICE_ANNOUNCE_HARASS ); - DECLARE_TASK( TASK_POLICE_FACE_ALONG_GOAL ); - - DEFINE_SCHEDULE - ( - SCHED_POLICE_WARN_TARGET, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_TARGET 0" - " TASK_POLICE_ANNOUNCE_HARASS 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_POLICE_HARASS1" - "" - " Interrupts" - " COND_POLICE_TARGET_TOO_CLOSE_SUPPRESS" - ); - - DEFINE_SCHEDULE - ( - SCHED_POLICE_HARASS_TARGET, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_TARGET 0" - " TASK_POLICE_GET_PATH_TO_HARASS_GOAL 64" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_POLICE_ANNOUNCE_HARASS 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_POLICE_HARASS1" - "" - " Interrupts" - " COND_POLICE_TARGET_TOO_CLOSE_SUPPRESS" - ); - - DEFINE_SCHEDULE - ( - SCHED_POLICE_SUPPRESS_TARGET, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_TARGET 0" - " TASK_POLICE_ANNOUNCE_HARASS 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_POLICE_HARASS1" - "" - " Interrupts" - ); - - DEFINE_SCHEDULE - ( - SCHED_POLICE_RETURN_FROM_HARASS, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_POLICE_GET_PATH_TO_POLICE_GOAL 16" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - "" - " Interrupts" - " COND_POLICE_TARGET_TOO_CLOSE_SUPPRESS" - ); - - DEFINE_SCHEDULE - ( - SCHED_POLICE_TRACK_TARGET, - - " Tasks" - " TASK_FACE_TARGET 0" - "" - " Interrupts" - " COND_POLICE_TARGET_TOO_CLOSE_SUPPRESS" - ); - - DEFINE_SCHEDULE - ( - SCHED_POLICE_FACE_ALONG_GOAL, - - " Tasks" - " TASK_WAIT_RANDOM 2" - " TASK_POLICE_FACE_ALONG_GOAL 0" - "" - " Interrupts" - " COND_POLICE_TARGET_TOO_CLOSE_SUPPRESS" - ); - -AI_END_CUSTOM_SCHEDULE_PROVIDER() diff --git a/game/server/hl2/ai_behavior_police.h b/game/server/hl2/ai_behavior_police.h deleted file mode 100644 index 04bc20934..000000000 --- a/game/server/hl2/ai_behavior_police.h +++ /dev/null @@ -1,106 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef AI_BEHAVIOR_POLICE_H -#define AI_BEHAVIOR_POLICE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_behavior.h" -#include "ai_goal_police.h" -#include "ai_sentence.h" - -#define PATROL_RADIUS_RATIO 2.0f -#define POLICE_MAX_WARNINGS 4 - -class CAI_PolicingBehavior : public CAI_SimpleBehavior -{ - DECLARE_CLASS( CAI_PolicingBehavior, CAI_SimpleBehavior ); -public: - DECLARE_DATADESC(); - CAI_PolicingBehavior(); - - enum - { - // Schedules - SCHED_POLICE_RETURN_FROM_HARASS = BaseClass::NEXT_SCHEDULE, - SCHED_POLICE_WARN_TARGET, - SCHED_POLICE_HARASS_TARGET, - SCHED_POLICE_SUPPRESS_TARGET, - SCHED_POLICE_FACE_ALONG_GOAL, - SCHED_POLICE_TRACK_TARGET, - NEXT_SCHEDULE, - - // Tasks - TASK_POLICE_GET_PATH_TO_HARASS_GOAL = BaseClass::NEXT_TASK, - TASK_POLICE_GET_PATH_TO_POLICE_GOAL, - TASK_POLICE_FACE_ALONG_GOAL, - TASK_POLICE_ANNOUNCE_HARASS, - NEXT_TASK, - - // Conditions - COND_POLICE_TARGET_TOO_CLOSE_HARASS = BaseClass::NEXT_CONDITION, - COND_POLICE_TARGET_TOO_CLOSE_SUPPRESS, - NEXT_CONDITION, - }; - - virtual const char *GetName() { return "Policing"; } - - void Enable( CAI_PoliceGoal *pGoal ); - void Disable( void ); - bool CanSelectSchedule( void ); - void BuildScheduleTestBits( void ); - - bool IsEnabled( void ) { return m_bEnabled; } - bool TargetIsHostile( void ); - - bool ShouldKnockOutTarget( CBaseEntity *pTarget ); - void KnockOutTarget( CBaseEntity *pTarget ); - - int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ); - - CBaseEntity *GetGoalTarget( void ); - -private: - - void HostSpeakSentence( const char *pSentence, SentencePriority_t nSoundPriority, SentenceCriteria_t nCriteria ); - - int TranslateSchedule( int scheduleType ); - - int SelectSchedule( void ); - int SelectSuppressSchedule( void ); - int SelectHarassSchedule( void ); - - Activity NPC_TranslateActivity( Activity newActivity ); - void GatherConditions( void ); - bool OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval ); - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - - void AnnouncePolicing( void ); - void HostSetBatonState( bool state ); - bool HostBatonIsOn( void ); - - void SetTargetHostileDuration( float time ); - bool MaintainGoalPosition( void ); - -protected: - - bool m_bEnabled; - bool m_bStartPolicing; - float m_flNextHarassTime; - float m_flAggressiveTime; - int m_nNumWarnings; - bool m_bTargetIsHostile; - float m_flTargetHostileTime; - - CHandle m_hPoliceGoal; - - DEFINE_CUSTOM_SCHEDULE_PROVIDER; -}; - -#endif // AI_BEHAVIOR_POLICE_H diff --git a/game/server/hl2/ai_goal_police.cpp b/game/server/hl2/ai_goal_police.cpp deleted file mode 100644 index fc99f8c81..000000000 --- a/game/server/hl2/ai_goal_police.cpp +++ /dev/null @@ -1,170 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "ai_goal_police.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// ai_goal_police - -// Used by police to define a region they should keep a target outside of - -LINK_ENTITY_TO_CLASS( ai_goal_police, CAI_PoliceGoal ); - -BEGIN_DATADESC( CAI_PoliceGoal ) - - DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "PoliceRadius" ), - DEFINE_KEYFIELD( m_iszTarget, FIELD_STRING, "PoliceTarget" ), - - DEFINE_FIELD( m_bOverrideKnockOut, FIELD_BOOLEAN ), - // m_hTarget - - DEFINE_INPUTFUNC( FIELD_VOID, "EnableKnockOut", InputEnableKnockOut ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableKnockOut", InputDisableKnockOut ), - - DEFINE_OUTPUT( m_OnKnockOut, "OnKnockOut" ), - DEFINE_OUTPUT( m_OnFirstWarning, "OnFirstWarning" ), - DEFINE_OUTPUT( m_OnSecondWarning, "OnSecondWarning" ), - DEFINE_OUTPUT( m_OnLastWarning, "OnLastWarning" ), - DEFINE_OUTPUT( m_OnSupressingTarget,"OnSupressingTarget" ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CAI_PoliceGoal::CAI_PoliceGoal( void ) -{ - m_hTarget = NULL; - m_bOverrideKnockOut = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CAI_PoliceGoal::GetRadius( void ) -{ - return m_flRadius; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CBaseEntity -//----------------------------------------------------------------------------- -CBaseEntity *CAI_PoliceGoal::GetTarget( void ) -{ - if ( m_hTarget == NULL ) - { - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, m_iszTarget ); - - if ( pTarget == NULL ) - { - DevMsg( "Unable to find ai_goal_police target: %s\n", STRING(m_iszTarget) ); - return NULL; - } - - m_hTarget = pTarget; - } - - return m_hTarget; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &targetPos - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PoliceGoal::ShouldKnockOutTarget( const Vector &targetPos, bool bTargetVisible ) -{ - if ( m_bOverrideKnockOut ) - return true; - - // Must be flagged to do it - if ( HasSpawnFlags( SF_POLICE_GOAL_KNOCKOUT_BEHIND ) == false ) - return false; - - // If the target's not visible, we don't care about him - if ( !bTargetVisible ) - return false; - - Vector targetDir = targetPos - GetAbsOrigin(); - VectorNormalize( targetDir ); - - Vector facingDir; - AngleVectors( GetAbsAngles(), &facingDir ); - - // See if it's behind us - if ( DotProduct( facingDir, targetDir ) < 0 ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTarget - -//----------------------------------------------------------------------------- -void CAI_PoliceGoal::KnockOutTarget( CBaseEntity *pTarget ) -{ - m_OnKnockOut.FireOutput( pTarget, this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_PoliceGoal::ShouldRemainAtPost( void ) -{ - return HasSpawnFlags( SF_POLICE_GOAL_DO_NOT_LEAVE_POST ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : level - -//----------------------------------------------------------------------------- -void CAI_PoliceGoal::FireWarningLevelOutput( int level ) -{ - switch( level ) - { - case 1: - m_OnFirstWarning.FireOutput( this, this ); - break; - - case 2: - m_OnSecondWarning.FireOutput( this, this ); - break; - - case 3: - m_OnLastWarning.FireOutput( this, this ); - break; - - default: - m_OnSupressingTarget.FireOutput( this, this ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &data - -//----------------------------------------------------------------------------- -void CAI_PoliceGoal::InputEnableKnockOut( inputdata_t &data ) -{ - m_bOverrideKnockOut = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &data - -//----------------------------------------------------------------------------- -void CAI_PoliceGoal::InputDisableKnockOut( inputdata_t &data ) -{ - m_bOverrideKnockOut = false; -} - diff --git a/game/server/hl2/ai_goal_police.h b/game/server/hl2/ai_goal_police.h deleted file mode 100644 index 43d6ae959..000000000 --- a/game/server/hl2/ai_goal_police.h +++ /dev/null @@ -1,50 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef AI_GOAL_POLICE_H -#define AI_GOAL_POLICE_H -#ifdef _WIN32 -#pragma once -#endif - -class CAI_PoliceGoal : public CBaseEntity -{ -public: - - DECLARE_CLASS( CAI_PoliceGoal, CBaseEntity ); - - CAI_PoliceGoal( void ); - - float GetRadius( void ); - CBaseEntity *GetTarget( void ); - - bool ShouldKnockOutTarget( const Vector &targetPos, bool bTargetVisible ); // If the target should be knocked out - void KnockOutTarget( CBaseEntity *pTarget ); // Send an output that we've knocked out this target - bool ShouldRemainAtPost( void ); - - void InputEnableKnockOut( inputdata_t &data ); - void InputDisableKnockOut( inputdata_t &data ); - - void FireWarningLevelOutput( int level ); - - float m_flRadius; - EHANDLE m_hTarget; - string_t m_iszTarget; - bool m_bOverrideKnockOut; - - COutputEvent m_OnKnockOut; - COutputEvent m_OnFirstWarning; - COutputEvent m_OnSecondWarning; - COutputEvent m_OnLastWarning; - COutputEvent m_OnSupressingTarget; - - DECLARE_DATADESC(); -}; - -#define SF_POLICE_GOAL_KNOCKOUT_BEHIND (1<<1) // Knockout a target that's behind the plane that cuts perpendicularly through us -#define SF_POLICE_GOAL_DO_NOT_LEAVE_POST (1<<2) // Cop will not come off his policing goal, even when angered - -#endif // AI_GOAL_POLICE_H diff --git a/game/server/hl2/ai_interactions.h b/game/server/hl2/ai_interactions.h deleted file mode 100644 index 0c4cbe780..000000000 --- a/game/server/hl2/ai_interactions.h +++ /dev/null @@ -1,80 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -//================================================== -// Definition for all AI interactions -//================================================== - -#ifndef AI_INTERACTIONS_H -#define AI_INTERACTIONS_H - -#ifdef _WIN32 -#pragma once -#endif - -//Antlion -extern int g_interactionAntlionKilled; - -//Barnacle -extern int g_interactionBarnacleVictimDangle; -extern int g_interactionBarnacleVictimReleased; -extern int g_interactionBarnacleVictimGrab; - -//Bullsquid -//extern int g_interactionBullsquidPlay; -//extern int g_interactionBullsquidThrow; - -//Combine -extern int g_interactionCombineBash; -extern int g_interactionCombineRequestCover; - -//Houndeye -//extern int g_interactionHoundeyeGroupAttack; -//extern int g_interactionHoundeyeGroupRetreat; -//extern int g_interactionHoundeyeGroupRalley; - -//Scanner -extern int g_interactionScannerInspect; -extern int g_interactionScannerInspectBegin; -extern int g_interactionScannerInspectDone; -extern int g_interactionScannerInspectHandsUp; -extern int g_interactionScannerInspectShowArmband; -extern int g_interactionScannerSupportEntity; -extern int g_interactionScannerSupportPosition; - -//Metrocop -extern int g_interactionMetrocopPointed; -extern int g_interactionMetrocopStartedStitch; - -//ScriptedTarget -extern int g_interactionScriptedTarget; - -//Stalker -extern int g_interactionStalkerBurn; - -//Vortigaunt -extern int g_interactionVortigauntStomp; -extern int g_interactionVortigauntStompFail; -extern int g_interactionVortigauntStompHit; -extern int g_interactionVortigauntKick; -extern int g_interactionVortigauntClaw; - -//Floor turret -extern int g_interactionTurretStillStanding; - -// AI Interaction for being hit by a physics object -extern int g_interactionHitByPlayerThrownPhysObj; - -// Alerts vital allies when the player punts a large object (car) -extern int g_interactionPlayerPuntedHeavyObject; - -// Zombie -// Melee attack will land in one second or so. -extern int g_interactionZombieMeleeWarning; - -#endif //AI_INTERACTIONS_H diff --git a/game/server/hl2/ai_spotlight.cpp b/game/server/hl2/ai_spotlight.cpp deleted file mode 100644 index a96174fb9..000000000 --- a/game/server/hl2/ai_spotlight.cpp +++ /dev/null @@ -1,411 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "ai_spotlight.h" -#include "ai_basenpc.h" -#include "spotlightend.h" -#include "beam_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Parameters for how the scanner relates to citizens. -//----------------------------------------------------------------------------- -#define SPOTLIGHT_WIDTH 96 - - -//----------------------------------------------------------------------------- -// Save/load -//----------------------------------------------------------------------------- -BEGIN_SIMPLE_DATADESC( CAI_Spotlight ) - - // Robin: Don't save, recreated after restore/transition. - //DEFINE_FIELD( m_hSpotlight, FIELD_EHANDLE ), - //DEFINE_FIELD( m_hSpotlightTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_vSpotlightTargetPos, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vSpotlightDir, FIELD_VECTOR ), - DEFINE_FIELD( m_flSpotlightCurLength, FIELD_FLOAT ), - DEFINE_FIELD( m_flSpotlightMaxLength, FIELD_FLOAT ), - DEFINE_FIELD( m_flConstraintAngle, FIELD_FLOAT ), - DEFINE_FIELD( m_nHaloSprite, FIELD_MODELINDEX ), - DEFINE_FIELD( m_nSpotlightAttachment, FIELD_INTEGER ), - DEFINE_FIELD( m_nFlags, FIELD_INTEGER ), - DEFINE_FIELD( m_vAngularVelocity, FIELD_QUATERNION ), - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CAI_Spotlight::CAI_Spotlight() -{ -#ifdef _DEBUG - m_vSpotlightTargetPos.Init(); - m_vSpotlightDir.Init(); -#endif -} - - -CAI_Spotlight::~CAI_Spotlight() -{ - SpotlightDestroy(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_Spotlight::Precache(void) -{ - // Sprites - m_nHaloSprite = GetOuter()->PrecacheModel("sprites/light_glow03.vmt"); - - GetOuter()->PrecacheModel( "sprites/glow_test02.vmt" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_Spotlight::Init( CAI_BaseNPC *pOuter, int nFlags, float flConstraintAngle, float flMaxLength ) -{ - SetOuter( pOuter ); - m_nFlags = nFlags; - m_flConstraintAngle = flConstraintAngle; - m_flSpotlightMaxLength = flMaxLength; - - // Check for user error - if (m_flSpotlightMaxLength <= 0) - { - DevMsg("ERROR: Invalid spotlight length <= 0, setting to 500\n"); - m_flSpotlightMaxLength = 500; - } - - Precache(); - - m_vSpotlightTargetPos = vec3_origin; - m_hSpotlight = NULL; - m_hSpotlightTarget = NULL; - - AngleVectors( GetAbsAngles(), &m_vSpotlightDir ); - m_vAngularVelocity.Init( 0, 0, 0, 1 ); - m_flSpotlightCurLength = m_flSpotlightMaxLength; -} - - -//------------------------------------------------------------------------------ -// Computes the spotlight endpoint -//------------------------------------------------------------------------------ -void CAI_Spotlight::ComputeEndpoint( const Vector &vecStartPoint, Vector *pEndPoint ) -{ - // Create the endpoint - trace_t tr; - AI_TraceLine( vecStartPoint, vecStartPoint + m_vSpotlightDir * 2 * m_flSpotlightMaxLength, MASK_OPAQUE, GetOuter(), COLLISION_GROUP_NONE, &tr ); - *pEndPoint = tr.endpos; -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CAI_Spotlight::SpotlightCreate( int nAttachment, const Vector &vecInitialDir ) -{ - // Make sure we don't already have one - if ( m_hSpotlight != NULL ) - return; - - m_vSpotlightDir = vecInitialDir; - VectorNormalize( m_vSpotlightDir ); - m_nSpotlightAttachment = nAttachment; - - CreateSpotlightEntities(); -} - -//----------------------------------------------------------------------------- -// Purpose: Create the beam & spotlight end for this spotlight. -// Will be re-called after restore/transition -//----------------------------------------------------------------------------- -void CAI_Spotlight::CreateSpotlightEntities( void ) -{ - m_vAngularVelocity.Init( 0, 0, 0, 1 ); - - // Create the endpoint - // Get the initial position... - Vector vecStartPoint; - if ( m_nSpotlightAttachment == 0 ) - { - vecStartPoint = GetOuter()->GetAbsOrigin(); - } - else - { - GetOuter()->GetAttachment( m_nSpotlightAttachment, vecStartPoint ); - } - - Vector vecEndPoint; - ComputeEndpoint( vecStartPoint, &vecEndPoint ); - - m_hSpotlightTarget = (CSpotlightEnd*)CreateEntityByName( "spotlight_end" ); - m_hSpotlightTarget->Spawn(); - m_hSpotlightTarget->SetAbsOrigin( vecEndPoint ); - m_hSpotlightTarget->SetOwnerEntity( GetOuter() ); - m_hSpotlightTarget->SetRenderColor( 255, 255, 255 ); - m_hSpotlightTarget->m_Radius = m_flSpotlightMaxLength; - if ( FBitSet (m_nFlags, AI_SPOTLIGHT_NO_DLIGHTS) ) - { - m_hSpotlightTarget->m_flLightScale = 0.0; - } - else - { - m_hSpotlightTarget->m_flLightScale = SPOTLIGHT_WIDTH; - } - - // Create the beam - m_hSpotlight = CBeam::BeamCreate( "sprites/glow_test02.vmt", SPOTLIGHT_WIDTH ); - // Set the temporary spawnflag on the beam so it doesn't save (we'll recreate it on restore) - m_hSpotlight->AddSpawnFlags( SF_BEAM_TEMPORARY ); - m_hSpotlight->SetColor( 255, 255, 255 ); - m_hSpotlight->SetHaloTexture( m_nHaloSprite ); - m_hSpotlight->SetHaloScale( 32 ); - m_hSpotlight->SetEndWidth( m_hSpotlight->GetWidth() ); - m_hSpotlight->SetBeamFlags( (FBEAM_SHADEOUT|FBEAM_NOTILE) ); - m_hSpotlight->SetBrightness( 32 ); - m_hSpotlight->SetNoise( 0 ); - m_hSpotlight->EntsInit( GetOuter(), m_hSpotlightTarget ); - m_hSpotlight->SetStartAttachment( m_nSpotlightAttachment ); -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CAI_Spotlight::SpotlightDestroy(void) -{ - if ( m_hSpotlight ) - { - UTIL_Remove(m_hSpotlight); - m_hSpotlight = NULL; - - UTIL_Remove(m_hSpotlightTarget); - m_hSpotlightTarget = NULL; - } -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CAI_Spotlight::SetSpotlightTargetPos( const Vector &vSpotlightTargetPos ) -{ - m_vSpotlightTargetPos = vSpotlightTargetPos; -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CAI_Spotlight::SetSpotlightTargetDirection( const Vector &vSpotlightTargetDir ) -{ - if ( !m_hSpotlight ) - { - CreateSpotlightEntities(); - } - - VectorMA( m_hSpotlight->GetAbsStartPos(), 1000.0f, vSpotlightTargetDir, m_vSpotlightTargetPos ); -} - - -//------------------------------------------------------------------------------ -// Constrain to cone -//------------------------------------------------------------------------------ -bool CAI_Spotlight::ConstrainToCone( Vector *pDirection ) -{ - Vector vecOrigin, vecForward; - if ( m_nSpotlightAttachment == 0 ) - { - QAngle vecAngles; - vecAngles = GetOuter()->GetAbsAngles(); - AngleVectors( vecAngles, &vecForward ); - } - else - { - GetOuter()->GetAttachment( m_nSpotlightAttachment, vecOrigin, &vecForward ); - } - - - if ( m_flConstraintAngle == 0.0f ) - { - *pDirection = vecForward; - return true; - } - - float flDot = DotProduct( vecForward, *pDirection ); - if ( flDot >= cos( DEG2RAD( m_flConstraintAngle ) ) ) - return false; - - Vector vecAxis; - CrossProduct( *pDirection, vecForward, vecAxis ); - VectorNormalize( vecAxis ); - - Quaternion q; - AxisAngleQuaternion( vecAxis, -m_flConstraintAngle, q ); - - Vector vecResult; - matrix3x4_t rot; - QuaternionMatrix( q, rot ); - VectorRotate( vecForward, rot, vecResult ); - VectorNormalize( vecResult ); - - *pDirection = vecResult; - - return true; -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -#define QUAT_BLEND_FACTOR 0.4f - -void CAI_Spotlight::UpdateSpotlightDirection( void ) -{ - if ( !m_hSpotlight ) - { - CreateSpotlightEntities(); - } - - // Compute the current beam direction - Vector vTargetDir; - VectorSubtract( m_vSpotlightTargetPos, m_hSpotlight->GetAbsStartPos(), vTargetDir ); - VectorNormalize(vTargetDir); - ConstrainToCone( &vTargetDir ); - - // Compute the amount to rotate - float flDot = DotProduct( vTargetDir, m_vSpotlightDir ); - flDot = clamp( flDot, -1.0f, 1.0f ); - float flAngle = AngleNormalize( RAD2DEG( acos( flDot ) ) ); - float flClampedAngle = clamp( flAngle, 0.0f, 45.0f ); - float flBeamTurnRate = SimpleSplineRemapVal( flClampedAngle, 0.0f, 45.0f, 10.0f, 45.0f ); - if ( fabs(flAngle) > flBeamTurnRate * gpGlobals->frametime ) - { - flAngle = flBeamTurnRate * gpGlobals->frametime; - } - - // Compute the rotation axis - Vector vecRotationAxis; - CrossProduct( m_vSpotlightDir, vTargetDir, vecRotationAxis ); - if ( VectorNormalize( vecRotationAxis ) < 1e-3 ) - { - vecRotationAxis.Init( 0, 0, 1 ); - } - - // Compute the actual rotation amount, using quat slerp blending - Quaternion desiredQuat, resultQuat; - AxisAngleQuaternion( vecRotationAxis, flAngle, desiredQuat ); - QuaternionSlerp( m_vAngularVelocity, desiredQuat, QUAT_BLEND_FACTOR, resultQuat ); - m_vAngularVelocity = resultQuat; - - // If we're really close, and we're not moving very quickly, slam. - float flActualRotation = AngleNormalize( RAD2DEG(2 * acos(m_vAngularVelocity.w)) ); - if (( flActualRotation < 1e-3 ) && (flAngle < 1e-3 )) - { - m_vSpotlightDir = vTargetDir; - m_vAngularVelocity.Init( 0, 0, 0, 1 ); - return; - } - - // Update the desired direction - matrix3x4_t rot; - Vector vecNewDir; - QuaternionMatrix( m_vAngularVelocity, rot ); - VectorRotate( m_vSpotlightDir, rot, vecNewDir ); - m_vSpotlightDir = vecNewDir; - VectorNormalize(m_vSpotlightDir); -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CAI_Spotlight::UpdateSpotlightEndpoint( void ) -{ - if ( !m_hSpotlight ) - { - CreateSpotlightEntities(); - } - - Vector vecStartPoint, vecEndPoint; - vecStartPoint = m_hSpotlight->GetAbsStartPos(); - ComputeEndpoint( vecStartPoint, &vecEndPoint ); - - // If I'm not facing the spotlight turn it off - Vector vecSpotDir; - VectorSubtract( vecEndPoint, vecStartPoint, vecSpotDir ); - float flBeamLength = VectorNormalize(vecSpotDir); - - m_hSpotlightTarget->SetAbsOrigin( vecEndPoint ); - m_hSpotlightTarget->SetAbsVelocity( vec3_origin ); - m_hSpotlightTarget->m_vSpotlightOrg = vecStartPoint; - m_hSpotlightTarget->m_vSpotlightDir = vecSpotDir; - - // Avoid sudden change in where beam fades out when cross disconinuities - m_flSpotlightCurLength = Lerp( 0.20f, m_flSpotlightCurLength, flBeamLength ); - - // Fade out spotlight end if past max length. - if (m_flSpotlightCurLength > 2*m_flSpotlightMaxLength) - { - m_hSpotlightTarget->SetRenderColorA( 0 ); - m_hSpotlight->SetFadeLength(m_flSpotlightMaxLength); - } - else if (m_flSpotlightCurLength > m_flSpotlightMaxLength) - { - m_hSpotlightTarget->SetRenderColorA( (byte)((1-((m_flSpotlightCurLength-m_flSpotlightMaxLength)/m_flSpotlightMaxLength)))); - m_hSpotlight->SetFadeLength(m_flSpotlightMaxLength); - } - else - { - m_hSpotlightTarget->SetRenderColorA( 1 ); - m_hSpotlight->SetFadeLength(m_flSpotlightCurLength); - } - - // Adjust end width to keep beam width constant - float flNewWidth = SPOTLIGHT_WIDTH * ( flBeamLength / m_flSpotlightMaxLength ); - - flNewWidth = MIN( 100, flNewWidth ); - - m_hSpotlight->SetWidth(flNewWidth); - m_hSpotlight->SetEndWidth(flNewWidth); - - // Adjust width of light on the end. - if ( FBitSet (m_nFlags, AI_SPOTLIGHT_NO_DLIGHTS) ) - { - m_hSpotlightTarget->m_flLightScale = 0.0; - } - else - { - m_hSpotlightTarget->m_flLightScale = flNewWidth; - } -} - - -//------------------------------------------------------------------------------ -// Purpose: Update the direction and position of my spotlight (if it's active) -//------------------------------------------------------------------------------ -void CAI_Spotlight::Update(void) -{ - if ( !m_hSpotlight ) - { - CreateSpotlightEntities(); - } - - // Update the beam direction - UpdateSpotlightDirection(); - UpdateSpotlightEndpoint(); -} - diff --git a/game/server/hl2/ai_spotlight.h b/game/server/hl2/ai_spotlight.h deleted file mode 100644 index 38dd4fece..000000000 --- a/game/server/hl2/ai_spotlight.h +++ /dev/null @@ -1,83 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef AI_SPOTLIGHT_H -#define AI_SPOTLIGHT_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_component.h" - -class CBeam; -class CSprite; -class SmokeTrail; -class CSpotlightEnd; - - -//----------------------------------------------------------------------------- -// Parameters for how the scanner relates to citizens. -//----------------------------------------------------------------------------- -enum -{ - AI_SPOTLIGHT_NO_DLIGHTS = 0x1, -}; - - -class CAI_Spotlight : public CAI_Component -{ - DECLARE_SIMPLE_DATADESC(); - DECLARE_CLASS_NOBASE( CAI_Spotlight ); - -public: - CAI_Spotlight(); - ~CAI_Spotlight(); - - void Init( CAI_BaseNPC *pOuter, int nFlags, float flConstraintAngle, float flMaxLength ); - - // Create, destroy the spotlight - void SpotlightCreate( int nAttachment, const Vector &vecInitialDir ); - void SpotlightDestroy(void); - - // Controls the spotlight target position + direction - void SetSpotlightTargetPos( const Vector &vSpotlightTargetPos ); - void SetSpotlightTargetDirection( const Vector &vSpotlightTargetDir ); - - // Updates the spotlight. Call every frame! - void Update(void); - -private: - void Precache(void); - void CreateSpotlightEntities( void ); - void UpdateSpotlightDirection( void ); - void UpdateSpotlightEndpoint( void ); - - // Constrain to cone, returns true if it was constrained - bool ConstrainToCone( Vector *pDirection ); - - // Computes the spotlight endpoint - void ComputeEndpoint( const Vector &vecStartPoint, Vector *pEndPoint ); - -private: - CHandle m_hSpotlight; - CHandle m_hSpotlightTarget; - - Vector m_vSpotlightTargetPos; - Vector m_vSpotlightDir; - float m_flSpotlightCurLength; - float m_flSpotlightMaxLength; - float m_flConstraintAngle; - int m_nHaloSprite; - int m_nSpotlightAttachment; - int m_nFlags; - Quaternion m_vAngularVelocity; -}; - - -#endif // AI_SPOTLIGHT_H - - diff --git a/game/server/hl2/antlion_dust.cpp b/game/server/hl2/antlion_dust.cpp deleted file mode 100644 index 44a5d63bf..000000000 --- a/game/server/hl2/antlion_dust.cpp +++ /dev/null @@ -1,44 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "antlion_dust.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -IMPLEMENT_SERVERCLASS_ST( CTEAntlionDust, DT_TEAntlionDust ) - SendPropVector( SENDINFO( m_vecOrigin ) ), - SendPropVector( SENDINFO( m_vecAngles ) ), - SendPropBool( SENDINFO( m_bBlockedSpawner ) ), -END_SEND_TABLE() - -CTEAntlionDust::CTEAntlionDust( const char *name ) : BaseClass( name ) -{ -} - -CTEAntlionDust::~CTEAntlionDust( void ) -{ -} - -static CTEAntlionDust g_TEAntlionDust( "AntlionDust" ); - -//----------------------------------------------------------------------------- -// Purpose: Creates antlion dust effect -// Input : &origin - position -// &angles - angles -//----------------------------------------------------------------------------- -void UTIL_CreateAntlionDust( const Vector &origin, const QAngle &angles, bool bBlockedSpawner ) -{ - g_TEAntlionDust.m_vecOrigin = origin; - g_TEAntlionDust.m_vecAngles = angles; - g_TEAntlionDust.m_bBlockedSpawner = bBlockedSpawner; - - //Send it - CPVSFilter filter( origin ); - g_TEAntlionDust.Create( filter, 0.0f ); -} diff --git a/game/server/hl2/antlion_dust.h b/game/server/hl2/antlion_dust.h deleted file mode 100644 index a79ba0fcb..000000000 --- a/game/server/hl2/antlion_dust.h +++ /dev/null @@ -1,32 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef ANTLION_DUST_H -#define ANTLION_DUST_H - -#include "te_particlesystem.h" - -class CTEAntlionDust : public CTEParticleSystem -{ -public: - - DECLARE_CLASS( CTEAntlionDust, CTEParticleSystem ); - DECLARE_SERVERCLASS(); - - CTEAntlionDust( const char *name ); - virtual ~CTEAntlionDust( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ) { }; - - CNetworkVector( m_vecOrigin ); - CNetworkVar( QAngle, m_vecAngles ); - CNetworkVar( bool, m_bBlockedSpawner ); -}; - -void UTIL_CreateAntlionDust( const Vector &origin, const QAngle &angles, bool bBlockedSpawner = false ); - -#endif //ANTLION_DUST_H diff --git a/game/server/hl2/antlion_maker.cpp b/game/server/hl2/antlion_maker.cpp deleted file mode 100644 index ae7ba33a2..000000000 --- a/game/server/hl2/antlion_maker.cpp +++ /dev/null @@ -1,1753 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "npc_antlion.h" -#include "antlion_maker.h" -#include "saverestore_utlvector.h" -#include "mapentities.h" -#include "decals.h" -#include "iservervehicle.h" -#include "antlion_dust.h" -#include "smoke_trail.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -CAntlionMakerManager g_AntlionMakerManager( "CAntlionMakerManager" ); - -static const char *s_pPoolThinkContext = "PoolThinkContext"; -static const char *s_pBlockedEffectsThinkContext = "BlockedEffectsThinkContext"; -static const char *s_pBlockedCheckContext = "BlockedCheckContext"; - -ConVar g_debug_antlionmaker( "g_debug_antlionmaker", "0", FCVAR_CHEAT ); - - -#define ANTLION_MAKER_PLAYER_DETECT_RADIUS 512 -#define ANTLION_MAKER_BLOCKED_MASS 250.0f // half the weight of a car -#define ANTLION_MAKE_SPORE_SPAWNRATE 25.0f - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &vFightGoal - -//----------------------------------------------------------------------------- -void CAntlionMakerManager::BroadcastFightGoal( const Vector &vFightGoal ) -{ - CAntlionTemplateMaker *pMaker; - - for ( int i=0; i < m_Makers.Count(); i++ ) - { - pMaker = m_Makers[i]; - - if ( pMaker && pMaker->ShouldHearBugbait() ) - { - pMaker->SetFightTarget( vFightGoal ); - pMaker->SetChildMoveState( ANTLION_MOVE_FIGHT_TO_GOAL ); - pMaker->UpdateChildren(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pFightGoal - -//----------------------------------------------------------------------------- -void CAntlionMakerManager::BroadcastFightGoal( CBaseEntity *pFightGoal ) -{ - CAntlionTemplateMaker *pMaker; - - for ( int i=0; i < m_Makers.Count(); i++ ) - { - pMaker = m_Makers[i]; - - if ( pMaker && pMaker->ShouldHearBugbait() ) - { - pMaker->SetFightTarget( pFightGoal ); - pMaker->SetChildMoveState( ANTLION_MOVE_FIGHT_TO_GOAL ); - pMaker->UpdateChildren(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pFightGoal - -//----------------------------------------------------------------------------- -void CAntlionMakerManager::BroadcastFollowGoal( CBaseEntity *pFollowGoal ) -{ - CAntlionTemplateMaker *pMaker; - - for ( int i=0; i < m_Makers.Count(); i++ ) - { - pMaker = m_Makers[i]; - - if ( pMaker && pMaker->ShouldHearBugbait() ) - { - //pMaker->SetFightTarget( NULL ); - pMaker->SetFollowTarget( pFollowGoal ); - pMaker->SetChildMoveState( ANTLION_MOVE_FOLLOW ); - pMaker->UpdateChildren(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAntlionMakerManager::GatherMakers( void ) -{ - CBaseEntity *pSearch = NULL; - CAntlionTemplateMaker *pMaker; - - m_Makers.Purge(); - - // Find these all once - while ( ( pSearch = gEntList.FindEntityByClassname( pSearch, "npc_antlion_template_maker" ) ) != NULL ) - { - pMaker = static_cast(pSearch); - - m_Makers.AddToTail( pMaker ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAntlionMakerManager::LevelInitPostEntity( void ) -{ - //Find all antlion makers - GatherMakers(); -} - -//----------------------------------------------------------------------------- -// Antlion template maker -//----------------------------------------------------------------------------- - -LINK_ENTITY_TO_CLASS( npc_antlion_template_maker, CAntlionTemplateMaker ); - -//DT Definition -BEGIN_DATADESC( CAntlionTemplateMaker ) - - DEFINE_KEYFIELD( m_strSpawnGroup, FIELD_STRING, "spawngroup" ), - DEFINE_KEYFIELD( m_strSpawnTarget, FIELD_STRING, "spawntarget" ), - DEFINE_KEYFIELD( m_flSpawnRadius, FIELD_FLOAT, "spawnradius" ), - DEFINE_KEYFIELD( m_strFightTarget, FIELD_STRING, "fighttarget" ), - DEFINE_KEYFIELD( m_strFollowTarget, FIELD_STRING, "followtarget" ), - DEFINE_KEYFIELD( m_bIgnoreBugbait, FIELD_BOOLEAN, "ignorebugbait" ), - DEFINE_KEYFIELD( m_flVehicleSpawnDistance, FIELD_FLOAT, "vehicledistance" ), - DEFINE_KEYFIELD( m_flWorkerSpawnRate, FIELD_FLOAT, "workerspawnrate" ), - - DEFINE_FIELD( m_nChildMoveState, FIELD_INTEGER ), - DEFINE_FIELD( m_hFightTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_hProxyTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_hFollowTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_iSkinCount, FIELD_INTEGER ), - DEFINE_FIELD( m_flBlockedBumpTime, FIELD_TIME ), - DEFINE_FIELD( m_bBlocked, FIELD_BOOLEAN ), - - DEFINE_UTLVECTOR( m_Children, FIELD_EHANDLE ), - - DEFINE_KEYFIELD( m_iPool, FIELD_INTEGER, "pool_start" ), - DEFINE_KEYFIELD( m_iMaxPool, FIELD_INTEGER, "pool_max" ), - DEFINE_KEYFIELD( m_iPoolRegenAmount,FIELD_INTEGER, "pool_regen_amount" ), - DEFINE_KEYFIELD( m_flPoolRegenTime, FIELD_FLOAT, "pool_regen_time" ), - - DEFINE_INPUTFUNC( FIELD_STRING, "SetFightTarget", InputSetFightTarget ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetFollowTarget", InputSetFollowTarget ), - DEFINE_INPUTFUNC( FIELD_VOID, "ClearFollowTarget", InputClearFollowTarget ), - DEFINE_INPUTFUNC( FIELD_VOID, "ClearFightTarget", InputClearFightTarget ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetSpawnRadius", InputSetSpawnRadius ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "AddToPool", InputAddToPool ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetMaxPool", InputSetMaxPool ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetPoolRegenAmount", InputSetPoolRegenAmount ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetPoolRegenTime", InputSetPoolRegenTime ), - DEFINE_INPUTFUNC( FIELD_STRING, "ChangeDestinationGroup", InputChangeDestinationGroup ), - DEFINE_OUTPUT( m_OnAllBlocked, "OnAllBlocked" ), - - DEFINE_KEYFIELD( m_bCreateSpores, FIELD_BOOLEAN, "createspores" ), - - DEFINE_THINKFUNC( PoolRegenThink ), - DEFINE_THINKFUNC( FindNodesCloseToPlayer ), - DEFINE_THINKFUNC( BlockedCheckFunc ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CAntlionTemplateMaker::CAntlionTemplateMaker( void ) -{ - m_hFightTarget = NULL; - m_hProxyTarget = NULL; - m_hFollowTarget = NULL; - m_nChildMoveState = ANTLION_MOVE_FREE; - m_iSkinCount = 0; - m_flBlockedBumpTime = 0.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CAntlionTemplateMaker::~CAntlionTemplateMaker( void ) -{ - DestroyProxyTarget(); - m_Children.Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pAnt - -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::AddChild( CNPC_Antlion *pAnt ) -{ - m_Children.AddToTail( pAnt ); - m_nLiveChildren = m_Children.Count(); - - pAnt->SetOwnerEntity( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pAnt - -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::RemoveChild( CNPC_Antlion *pAnt ) -{ - m_Children.FindAndRemove( pAnt ); - m_nLiveChildren = m_Children.Count(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::FixupOrphans( void ) -{ - CBaseEntity *pSearch = NULL; - CNPC_Antlion *pAntlion = NULL; - - // Iterate through all antlions and see if there are any orphans - while ( ( pSearch = gEntList.FindEntityByClassname( pSearch, "npc_antlion" ) ) != NULL ) - { - pAntlion = dynamic_cast(pSearch); - - // See if it's a live orphan - if ( pAntlion && pAntlion->GetOwnerEntity() == NULL && pAntlion->IsAlive() ) - { - // See if its parent was named the same as we are - if ( stricmp( pAntlion->GetParentSpawnerName(), STRING( GetEntityName() ) ) == 0 ) - { - // Relink us to this antlion, he's come through a transition and was orphaned - AddChild( pAntlion ); - } - } - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::PrecacheTemplateEntity( CBaseEntity *pEntity ) -{ - BaseClass::PrecacheTemplateEntity( pEntity ); - - // If we can spawn workers, precache the worker as well. - if ( m_flWorkerSpawnRate != 0 ) - { - pEntity->AddSpawnFlags( SF_ANTLION_WORKER ); - pEntity->Precache(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::Activate( void ) -{ - FixupOrphans(); - - BaseClass::Activate(); - - // Are we using the pool behavior for coast? - if ( m_iMaxPool ) - { - if ( !m_flPoolRegenTime ) - { - Msg("%s using pool behavior without a specified pool regen time.\n", GetClassname() ); - m_flPoolRegenTime = 0.1; - } - - // Start up our think cycle unless we're reloading this map (which would reset it) - if ( m_bDisabled == false && gpGlobals->eLoadType != MapLoad_LoadGame ) - { - // Start our pool regeneration cycle - SetContextThink( &CAntlionTemplateMaker::PoolRegenThink, gpGlobals->curtime + m_flPoolRegenTime, s_pPoolThinkContext ); - - // Start our blocked effects cycle - if ( hl2_episodic.GetBool() == true && HasSpawnFlags( SF_ANTLIONMAKER_DO_BLOCKEDEFFECTS ) ) - { - SetContextThink( &CAntlionTemplateMaker::FindNodesCloseToPlayer, gpGlobals->curtime + 1.0f, s_pBlockedEffectsThinkContext ); - } - } - } - - ActivateAllSpores(); -} - -void CAntlionTemplateMaker::ActivateSpore( const char* sporename, Vector vOrigin ) -{ - if ( m_bCreateSpores == false ) - return; - - char szName[64]; - Q_snprintf( szName, sizeof( szName ), "%s_spore", sporename ); - - SporeExplosion *pSpore = (SporeExplosion*)gEntList.FindEntityByName( NULL, szName ); - - //One already exists... - if ( pSpore ) - { - if ( pSpore->m_bDisabled == true ) - { - inputdata_t inputdata; - pSpore->InputEnable( inputdata ); - } - - return; - } - - CBaseEntity *pEnt = CreateEntityByName( "env_sporeexplosion" ); - - if ( pEnt ) - { - pSpore = dynamic_cast(pEnt); - - if ( pSpore ) - { - pSpore->SetAbsOrigin( vOrigin ); - pSpore->SetName( AllocPooledString( szName ) ); - pSpore->m_flSpawnRate = ANTLION_MAKE_SPORE_SPAWNRATE; - } - } -} - -void CAntlionTemplateMaker::DisableSpore( const char* sporename ) -{ - if ( m_bCreateSpores == false ) - return; - - char szName[64]; - Q_snprintf( szName, sizeof( szName ), "%s_spore", sporename ); - - SporeExplosion *pSpore = (SporeExplosion*)gEntList.FindEntityByName( NULL, szName ); - - if ( pSpore && pSpore->m_bDisabled == false ) - { - inputdata_t inputdata; - pSpore->InputDisable( inputdata ); - return; - } -} - -void CAntlionTemplateMaker::ActivateAllSpores( void ) -{ - if ( m_bDisabled == true ) - return; - - if ( m_bCreateSpores == false ) - return; - - CHintCriteria hintCriteria; - - hintCriteria.SetGroup( m_strSpawnGroup ); - hintCriteria.SetHintType( HINT_ANTLION_BURROW_POINT ); - - CUtlVector hintList; - CAI_HintManager::FindAllHints( vec3_origin, hintCriteria, &hintList ); - - for ( int i = 0; i < hintList.Count(); i++ ) - { - CAI_Hint *pTestHint = hintList[i]; - - if ( pTestHint ) - { - bool bBlank; - if ( !AllHintsFromClusterBlocked( pTestHint, bBlank ) ) - { - ActivateSpore( STRING( pTestHint->GetEntityName() ), pTestHint->GetAbsOrigin() ); - } - } - } -} - -void CAntlionTemplateMaker::DisableAllSpores( void ) -{ - CHintCriteria hintCriteria; - - hintCriteria.SetGroup( m_strSpawnGroup ); - hintCriteria.SetHintType( HINT_ANTLION_BURROW_POINT ); - - CUtlVector hintList; - CAI_HintManager::FindAllHints( vec3_origin, hintCriteria, &hintList ); - - for ( int i = 0; i < hintList.Count(); i++ ) - { - CAI_Hint *pTestHint = hintList[i]; - - if ( pTestHint ) - { - DisableSpore( STRING( pTestHint->GetEntityName() ) ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CBaseEntity -//----------------------------------------------------------------------------- -CBaseEntity *CAntlionTemplateMaker::GetFightTarget( void ) -{ - if ( m_hFightTarget != NULL ) - return m_hFightTarget; - - return m_hProxyTarget; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CBaseEntity -//----------------------------------------------------------------------------- -CBaseEntity *CAntlionTemplateMaker::GetFollowTarget( void ) -{ - return m_hFollowTarget; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::UpdateChildren( void ) -{ - //Update all children - CNPC_Antlion *pAntlion = NULL; - - // Move through our child list - int i=0; - for ( ; i < m_Children.Count(); i++ ) - { - pAntlion = m_Children[i]; - - //HACKHACK - //Let's just fix this up. - //This guy might have been killed in another level and we just came back. - if ( pAntlion == NULL ) - { - m_Children.Remove( i ); - i--; - continue; - } - - if ( pAntlion->m_lifeState != LIFE_ALIVE ) - continue; - - pAntlion->SetFightTarget( GetFightTarget() ); - pAntlion->SetFollowTarget( GetFollowTarget() ); - pAntlion->SetMoveState( m_nChildMoveState ); - } - - m_nLiveChildren = i; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : strTarget - -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::SetFightTarget( string_t strTarget, CBaseEntity *pActivator, CBaseEntity *pCaller ) -{ - if ( HasSpawnFlags( SF_ANTLIONMAKER_RANDOM_FIGHT_TARGET ) ) - { - CBaseEntity *pSearch = m_hFightTarget; - - for ( int i = random->RandomInt(1,5); i > 0; i-- ) - pSearch = gEntList.FindEntityByName( pSearch, strTarget, this, pActivator, pCaller ); - - if ( pSearch != NULL ) - { - SetFightTarget( pSearch ); - } - else - { - SetFightTarget( gEntList.FindEntityByName( NULL, strTarget, this, pActivator, pCaller ) ); - } - } - else - { - SetFightTarget( gEntList.FindEntityByName( NULL, strTarget, this, pActivator, pCaller ) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEntity - -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::SetFightTarget( CBaseEntity *pEntity ) -{ - m_hFightTarget = pEntity; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &position - -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::SetFightTarget( const Vector &position ) -{ - CreateProxyTarget( position ); - - m_hFightTarget = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTarget - -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::SetFollowTarget( CBaseEntity *pTarget ) -{ - m_hFollowTarget = pTarget; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTarget - -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::SetFollowTarget( string_t strTarget, CBaseEntity *pActivator, CBaseEntity *pCaller ) -{ - CBaseEntity *pSearch = gEntList.FindEntityByName( NULL, strTarget, NULL, pActivator, pCaller ); - - if ( pSearch != NULL ) - { - SetFollowTarget( pSearch ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : state - -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::SetChildMoveState( AntlionMoveState_e state ) -{ - m_nChildMoveState = state; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &position - -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::CreateProxyTarget( const Vector &position ) -{ - // Create if we don't have one - if ( m_hProxyTarget == NULL ) - { - m_hProxyTarget = CreateEntityByName( "info_target" ); - } - - // Update if we do - if ( m_hProxyTarget != NULL ) - { - m_hProxyTarget->SetAbsOrigin( position ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::DestroyProxyTarget( void ) -{ - if ( m_hProxyTarget ) - { - UTIL_Remove( m_hProxyTarget ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : bIgnoreSolidEntities - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAntlionTemplateMaker::CanMakeNPC( bool bIgnoreSolidEntities ) -{ - if ( m_nMaxLiveChildren == 0 ) - return false; - - if ( !HasSpawnFlags( SF_ANTLIONMAKER_SPAWN_CLOSE_TO_TARGET ) ) - { - if ( m_strSpawnGroup == NULL_STRING ) - return BaseClass::CanMakeNPC( bIgnoreSolidEntities ); - } - - if ( m_nMaxLiveChildren > 0 && m_nLiveChildren >= m_nMaxLiveChildren ) - return false; - - // If we're spawning from a pool, ensure the pool has an antlion in it - if ( m_iMaxPool && !m_iPool ) - return false; - - if ( (CAI_BaseNPC::m_nDebugBits & bits_debugDisableAI) == bits_debugDisableAI ) - return false; - - return true; -} - -void CAntlionTemplateMaker::Enable( void ) -{ - BaseClass::Enable(); - - if ( m_iMaxPool ) - { - SetContextThink( &CAntlionTemplateMaker::PoolRegenThink, gpGlobals->curtime + m_flPoolRegenTime, s_pPoolThinkContext ); - } - - if ( hl2_episodic.GetBool() == true && HasSpawnFlags( SF_ANTLIONMAKER_DO_BLOCKEDEFFECTS ) ) - { - SetContextThink( &CAntlionTemplateMaker::FindNodesCloseToPlayer, gpGlobals->curtime + 1.0f, s_pBlockedEffectsThinkContext ); - } - - ActivateAllSpores(); -} - -void CAntlionTemplateMaker::Disable( void ) -{ - BaseClass::Disable(); - - SetContextThink( NULL, gpGlobals->curtime, s_pPoolThinkContext ); - SetContextThink( NULL, gpGlobals->curtime, s_pBlockedEffectsThinkContext ); - - DisableAllSpores(); -} - - -//----------------------------------------------------------------------------- -// Randomly turn it into an antlion worker if that is enabled for this maker. -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::ChildPreSpawn( CAI_BaseNPC *pChild ) -{ - BaseClass::ChildPreSpawn( pChild ); - - if ( ( m_flWorkerSpawnRate > 0 ) && ( random->RandomFloat( 0, 1 ) < m_flWorkerSpawnRate ) ) - { - pChild->AddSpawnFlags( SF_ANTLION_WORKER ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::MakeNPC( void ) -{ - // If we're not restricting to hint groups, spawn as normal - if ( !HasSpawnFlags( SF_ANTLIONMAKER_SPAWN_CLOSE_TO_TARGET ) ) - { - if ( m_strSpawnGroup == NULL_STRING ) - { - BaseClass::MakeNPC(); - return; - } - } - - if ( CanMakeNPC( true ) == false ) - return; - - // Set our defaults - Vector targetOrigin = GetAbsOrigin(); - QAngle targetAngles = GetAbsAngles(); - - // Look for our target entity - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, m_strSpawnTarget, this ); - - // Take its position if it exists - if ( pTarget != NULL ) - { - UTIL_PredictedPosition( pTarget, 1.5f, &targetOrigin ); - } - - Vector spawnOrigin = vec3_origin; - - CAI_Hint *pNode = NULL; - - bool bRandom = HasSpawnFlags( SF_ANTLIONMAKER_RANDOM_SPAWN_NODE ); - - if ( HasSpawnFlags( SF_ANTLIONMAKER_SPAWN_CLOSE_TO_TARGET ) ) - { - if ( FindNearTargetSpawnPosition( spawnOrigin, m_flSpawnRadius, pTarget ) == false ) - return; - } - else - { - // If we can't find a spawn position, then we can't spawn this time - if ( FindHintSpawnPosition( targetOrigin, m_flSpawnRadius, m_strSpawnGroup, &pNode, bRandom ) == false ) - return; - - pNode->GetPosition( HULL_MEDIUM, &spawnOrigin ); - } - - // Point at the current position of the enemy - if ( pTarget != NULL ) - { - targetOrigin = pTarget->GetAbsOrigin(); - } - - // Create the entity via a template - CAI_BaseNPC *pent = NULL; - CBaseEntity *pEntity = NULL; - MapEntity_ParseEntity( pEntity, STRING(m_iszTemplateData), NULL ); - - if ( pEntity != NULL ) - { - pent = (CAI_BaseNPC *) pEntity; - } - - if ( pent == NULL ) - { - Warning("NULL Ent in NPCMaker!\n" ); - return; - } - - if ( !HasSpawnFlags( SF_ANTLIONMAKER_SPAWN_CLOSE_TO_TARGET ) ) - { - // Lock this hint node - pNode->Lock( pEntity ); - - // Unlock it in two seconds, this forces subsequent antlions to - // reject this point as a spawn point to spread them out a bit - pNode->Unlock( 2.0f ); - } - - m_OnSpawnNPC.Set( pEntity, pEntity, this ); - - pent->AddSpawnFlags( SF_NPC_FALL_TO_GROUND ); - - ChildPreSpawn( pent ); - - // Put us at the desired location - pent->SetLocalOrigin( spawnOrigin ); - - QAngle spawnAngles; - - if ( pTarget ) - { - // Face our spawning direction - Vector spawnDir = ( targetOrigin - spawnOrigin ); - VectorNormalize( spawnDir ); - - VectorAngles( spawnDir, spawnAngles ); - spawnAngles[PITCH] = 0.0f; - spawnAngles[ROLL] = 0.0f; - } - else if ( pNode ) - { - spawnAngles = QAngle( 0, pNode->Yaw(), 0 ); - } - - pent->SetLocalAngles( spawnAngles ); - DispatchSpawn( pent ); - - pent->Activate(); - - m_iSkinCount = ( m_iSkinCount + 1 ) % ANTLION_SKIN_COUNT; - pent->m_nSkin = m_iSkinCount; - - ChildPostSpawn( pent ); - - // Hold onto the child - CNPC_Antlion *pAntlion = dynamic_cast(pent); - - AddChild( pAntlion ); - - m_bBlocked = false; - SetContextThink( NULL, -1, s_pBlockedCheckContext ); - - pAntlion->ClearBurrowPoint( spawnOrigin ); - - if (!(m_spawnflags & SF_NPCMAKER_INF_CHILD)) - { - if ( m_iMaxPool ) - { - m_iPool--; - - if ( g_debug_antlionmaker.GetInt() == 2 ) - { - Msg("SPAWNED: Pool: %d (max %d) (Regenerating %d every %f)\n", m_iPool, m_iMaxPool, m_iPoolRegenAmount, m_flPoolRegenTime ); - } - } - else - { - m_nMaxNumNPCs--; - } - - if ( IsDepleted() ) - { - m_OnAllSpawned.FireOutput( this, this ); - - // Disable this forever. Don't kill it because it still gets death notices - SetThink( NULL ); - SetUse( NULL ); - } - } -} - -bool CAntlionTemplateMaker::FindPositionOnFoot( Vector &origin, float radius, CBaseEntity *pTarget ) -{ - int iMaxTries = 10; - Vector vSpawnOrigin = pTarget->GetAbsOrigin(); - - while ( iMaxTries > 0 ) - { - vSpawnOrigin.x += random->RandomFloat( -radius, radius ); - vSpawnOrigin.y += random->RandomFloat( -radius, radius ); - vSpawnOrigin.z += 96; - - if ( ValidateSpawnPosition( vSpawnOrigin, pTarget ) == false ) - { - iMaxTries--; - continue; - } - - origin = vSpawnOrigin; - return true; - } - - return false; -} - -bool CAntlionTemplateMaker::FindPositionOnVehicle( Vector &origin, float radius, CBaseEntity *pTarget ) -{ - int iMaxTries = 10; - Vector vSpawnOrigin = pTarget->GetAbsOrigin(); - vSpawnOrigin.z += 96; - - if ( pTarget == NULL ) - return false; - - while ( iMaxTries > 0 ) - { - Vector vForward, vRight; - - pTarget->GetVectors( &vForward, &vRight, NULL ); - - float flSpeed = (pTarget->GetSmoothedVelocity().Length() * m_flVehicleSpawnDistance) * random->RandomFloat( 1.0f, 1.5f ); - - vSpawnOrigin = vSpawnOrigin + (vForward * flSpeed) + vRight * random->RandomFloat( -radius, radius ); - - if ( ValidateSpawnPosition( vSpawnOrigin, pTarget ) == false ) - { - iMaxTries--; - continue; - } - - origin = vSpawnOrigin; - return true; - } - - return false; -} - -bool CAntlionTemplateMaker::ValidateSpawnPosition( Vector &vOrigin, CBaseEntity *pTarget ) -{ - trace_t tr; - UTIL_TraceLine( vOrigin, vOrigin - Vector( 0, 0, 1024 ), MASK_BLOCKLOS | CONTENTS_WATER, NULL, COLLISION_GROUP_NONE, &tr ); - - if ( g_debug_antlionmaker.GetInt() == 1 ) - NDebugOverlay::Line( vOrigin, tr.endpos, 0, 255, 0, false, 5 ); - - // Make sure this point is clear - if ( tr.fraction != 1.0 ) - { - if ( tr.contents & ( CONTENTS_WATER ) ) - return false; - - const surfacedata_t *psurf = physprops->GetSurfaceData( tr.surface.surfaceProps ); - - if ( psurf ) - { - if ( g_debug_antlionmaker.GetInt() == 1 ) - { - char szText[16]; - - Q_snprintf( szText, 16, "Material %c", psurf->game.material ); - NDebugOverlay::Text( vOrigin, szText, true, 5 ); - } - - if ( psurf->game.material != CHAR_TEX_SAND ) - return false; - } - - if ( CAntlionRepellant::IsPositionRepellantFree( tr.endpos ) == false ) - return false; - - trace_t trCheck; - UTIL_TraceHull( tr.endpos, tr.endpos + Vector(0,0,5), NAI_Hull::Mins( HULL_MEDIUM ), NAI_Hull::Maxs( HULL_MEDIUM ), MASK_NPCSOLID, NULL, COLLISION_GROUP_NONE, &trCheck ); - - if ( trCheck.DidHit() == false ) - { - if ( g_debug_antlionmaker.GetInt() == 1 ) - NDebugOverlay::Box( tr.endpos + Vector(0,0,5), NAI_Hull::Mins( HULL_MEDIUM ), NAI_Hull::Maxs( HULL_MEDIUM ), 0, 255, 0, 128, 5 ); - - if ( pTarget ) - { - if ( pTarget->IsPlayer() ) - { - CBaseEntity *pVehicle = NULL; - CBasePlayer *pPlayer = dynamic_cast < CBasePlayer *> ( pTarget ); - - if ( pPlayer && pPlayer->GetVehicle() ) - pVehicle = ((CBasePlayer *)pTarget)->GetVehicle()->GetVehicleEnt(); - - CTraceFilterSkipTwoEntities traceFilter( pPlayer, pVehicle, COLLISION_GROUP_NONE ); - - trace_t trVerify; - - Vector vVerifyOrigin = pPlayer->GetAbsOrigin() + pPlayer->GetViewOffset(); - float flZOffset = NAI_Hull::Maxs( HULL_MEDIUM ).z; - UTIL_TraceLine( vVerifyOrigin, tr.endpos + Vector( 0, 0, flZOffset ), MASK_BLOCKLOS | CONTENTS_WATER, &traceFilter, &trVerify ); - - if ( trVerify.fraction != 1.0f ) - { - const surfacedata_t *psurf = physprops->GetSurfaceData( trVerify.surface.surfaceProps ); - - if ( psurf ) - { - if ( psurf->game.material == CHAR_TEX_DIRT ) - { - if ( g_debug_antlionmaker.GetInt() == 1 ) - { - NDebugOverlay::Line( vVerifyOrigin, trVerify.endpos, 255, 0, 0, false, 5 ); - } - - return false; - } - } - } - - if ( g_debug_antlionmaker.GetInt() == 1 ) - { - NDebugOverlay::Line( vVerifyOrigin, trVerify.endpos, 0, 255, 0, false, 5 ); - } - } - } - - - vOrigin = trCheck.endpos + Vector(0,0,5); - return true; - } - else - { - if ( g_debug_antlionmaker.GetInt() == 1 ) - NDebugOverlay::Box( tr.endpos + Vector(0,0,5), NAI_Hull::Mins( HULL_MEDIUM ), NAI_Hull::Maxs( HULL_MEDIUM ), 255, 0, 0, 128, 5 ); - - return false; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Find a position near the player to spawn the new antlion at -// Input : &origin - search origin -// radius - search radius -// *retOrigin - found origin (if any) -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAntlionTemplateMaker::FindNearTargetSpawnPosition( Vector &origin, float radius, CBaseEntity *pTarget ) -{ - if ( pTarget ) - { - CBaseEntity *pVehicle = NULL; - - if ( pTarget->IsPlayer() ) - { - CBasePlayer *pPlayer = ((CBasePlayer *)pTarget); - - if ( pPlayer->GetVehicle() ) - pVehicle = ((CBasePlayer *)pTarget)->GetVehicle()->GetVehicleEnt(); - } - - if ( pVehicle ) - return FindPositionOnVehicle( origin, radius, pVehicle ); - else - return FindPositionOnFoot( origin, radius, pTarget ); - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Find a hint position to spawn the new antlion at -// Input : &origin - search origin -// radius - search radius -// hintGroupName - search hint group name -// *retOrigin - found origin (if any) -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAntlionTemplateMaker::FindHintSpawnPosition( const Vector &origin, float radius, string_t hintGroupName, CAI_Hint **pHint, bool bRandom ) -{ - CAI_Hint *pChosenHint = NULL; - - CHintCriteria hintCriteria; - - hintCriteria.SetGroup( hintGroupName ); - hintCriteria.SetHintType( HINT_ANTLION_BURROW_POINT ); - - if ( bRandom ) - { - hintCriteria.SetFlag( bits_HINT_NODE_RANDOM ); - } - else - { - hintCriteria.SetFlag( bits_HINT_NODE_NEAREST ); - } - - // If requested, deny nodes that can be seen by the player - if ( m_spawnflags & SF_NPCMAKER_HIDEFROMPLAYER ) - { - hintCriteria.SetFlag( bits_HINT_NODE_NOT_VISIBLE_TO_PLAYER ); - } - - hintCriteria.AddIncludePosition( origin, radius ); - - if ( bRandom == true ) - { - pChosenHint = CAI_HintManager::FindHintRandom( NULL, origin, hintCriteria ); - } - else - { - pChosenHint = CAI_HintManager::FindHint( origin, hintCriteria ); - } - - if ( pChosenHint != NULL ) - { - bool bChosenHintBlocked = false; - - if ( AllHintsFromClusterBlocked( pChosenHint, bChosenHintBlocked ) ) - { - if ( ( GetIndexForThinkContext( s_pBlockedCheckContext ) == NO_THINK_CONTEXT ) || - ( GetNextThinkTick( s_pBlockedCheckContext ) == TICK_NEVER_THINK ) ) - { - SetContextThink( &CAntlionTemplateMaker::BlockedCheckFunc, gpGlobals->curtime + 2.0f, s_pBlockedCheckContext ); - } - - return false; - } - - if ( bChosenHintBlocked == true ) - { - return false; - } - - *pHint = pChosenHint; - return true; - } - - return false; -} - -void CAntlionTemplateMaker::DoBlockedEffects( CBaseEntity *pBlocker, Vector vOrigin ) -{ - // If the object blocking the hole is a physics object, wobble it a bit. - if( pBlocker ) - { - IPhysicsObject *pPhysObj = pBlocker->VPhysicsGetObject(); - - if( pPhysObj && pPhysObj->IsAsleep() ) - { - // Don't bonk the object unless it is at rest. - float x = RandomFloat( -5000, 5000 ); - float y = RandomFloat( -5000, 5000 ); - - Vector vecForce = Vector( x, y, RandomFloat(10000, 15000) ); - pPhysObj->ApplyForceCenter( vecForce ); - - UTIL_CreateAntlionDust( vOrigin, vec3_angle, true ); - pBlocker->EmitSound( "NPC_Antlion.MeleeAttackSingle_Muffled" ); - pBlocker->EmitSound( "NPC_Antlion.TrappedMetal" ); - - - m_flBlockedBumpTime = gpGlobals->curtime + random->RandomFloat( 1.75, 2.75 ); - } - } -} - -CBaseEntity *CAntlionTemplateMaker::AllHintsFromClusterBlocked( CAI_Hint *pNode, bool &bChosenHintBlocked ) -{ - // Only do this for episodic content! - if ( hl2_episodic.GetBool() == false ) - return NULL; - - CBaseEntity *pBlocker = NULL; - - if ( pNode != NULL ) - { - int iNumBlocked = 0; - int iNumNodes = 0; - - CHintCriteria hintCriteria; - - hintCriteria.SetGroup( m_strSpawnGroup ); - hintCriteria.SetHintType( HINT_ANTLION_BURROW_POINT ); - - CUtlVector hintList; - CAI_HintManager::FindAllHints( vec3_origin, hintCriteria, &hintList ); - - for ( int i = 0; i < hintList.Count(); i++ ) - { - CAI_Hint *pTestHint = hintList[i]; - - if ( pTestHint ) - { - if ( pTestHint->NameMatches( pNode->GetEntityName() ) ) - { - bool bBlocked; - - iNumNodes++; - - Vector spawnOrigin; - pTestHint->GetPosition( HULL_MEDIUM, &spawnOrigin ); - - bBlocked = false; - - CBaseEntity* pList[20]; - - int count = UTIL_EntitiesInBox( pList, 20, spawnOrigin + NAI_Hull::Mins( HULL_MEDIUM ), spawnOrigin + NAI_Hull::Maxs( HULL_MEDIUM ), 0 ); - - //Iterate over all the possible targets - for ( int i = 0; i < count; i++ ) - { - if ( pList[i]->GetMoveType() != MOVETYPE_VPHYSICS ) - continue; - - if ( PhysGetEntityMass( pList[i] ) > ANTLION_MAKER_BLOCKED_MASS ) - { - bBlocked = true; - iNumBlocked++; - pBlocker = pList[i]; - - if ( pTestHint == pNode ) - { - bChosenHintBlocked = true; - } - - break; - } - } - - if ( g_debug_antlionmaker.GetInt() == 1 ) - { - if ( bBlocked ) - { - NDebugOverlay::Box( spawnOrigin + Vector(0,0,5), NAI_Hull::Mins( HULL_MEDIUM ), NAI_Hull::Maxs( HULL_MEDIUM ), 255, 0, 0, 128, 0.25f ); - } - else - { - NDebugOverlay::Box( spawnOrigin + Vector(0,0,5), NAI_Hull::Mins( HULL_MEDIUM ), NAI_Hull::Maxs( HULL_MEDIUM ), 0, 255, 0, 128, 0.25f ); - } - } - } - } - } - - //All the nodes from this cluster are blocked so start playing the effects. - if ( iNumNodes > 0 && iNumBlocked == iNumNodes ) - { - return pBlocker; - } - } - - return NULL; -} - -void CAntlionTemplateMaker::FindNodesCloseToPlayer( void ) -{ - SetContextThink( &CAntlionTemplateMaker::FindNodesCloseToPlayer, gpGlobals->curtime + random->RandomFloat( 0.75, 1.75 ), s_pBlockedEffectsThinkContext ); - - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - - if ( pPlayer == NULL ) - return; - - CHintCriteria hintCriteria; - - float flRadius = ANTLION_MAKER_PLAYER_DETECT_RADIUS; - - hintCriteria.SetGroup( m_strSpawnGroup ); - hintCriteria.SetHintType( HINT_ANTLION_BURROW_POINT ); - hintCriteria.AddIncludePosition( pPlayer->GetAbsOrigin(), ANTLION_MAKER_PLAYER_DETECT_RADIUS ); - - CUtlVector hintList; - - if ( CAI_HintManager::FindAllHints( vec3_origin, hintCriteria, &hintList ) <= 0 ) - return; - - CUtlVector m_BlockedNames; - - //---- - //What we do here is find all hints of the same name (cluster name) and figure out if all of them are blocked. - //If they are then we only need to play the blocked effects once - //--- - for ( int i = 0; i < hintList.Count(); i++ ) - { - CAI_Hint *pNode = hintList[i]; - - if ( pNode && pNode->HintMatchesCriteria( NULL, hintCriteria, pPlayer->GetAbsOrigin(), &flRadius ) ) - { - bool bClusterAlreadyBlocked = false; - - //Have one of the nodes from this cluster been checked for blockage? If so then there's no need to do block checks again for this cluster. - for ( int iStringCount = 0; iStringCount < m_BlockedNames.Count(); iStringCount++ ) - { - if ( pNode->NameMatches( m_BlockedNames[iStringCount] ) ) - { - bClusterAlreadyBlocked = true; - break; - } - } - - if ( bClusterAlreadyBlocked == true ) - continue; - - Vector vHintPos; - pNode->GetPosition( HULL_MEDIUM, &vHintPos ); - - bool bBlank; - if ( CBaseEntity *pBlocker = AllHintsFromClusterBlocked( pNode, bBlank ) ) - { - DisableSpore( STRING( pNode->GetEntityName() ) ); - DoBlockedEffects( pBlocker, vHintPos ); - m_BlockedNames.AddToTail( pNode->GetEntityName() ); - } - else - { - ActivateSpore( STRING( pNode->GetEntityName() ), pNode->GetAbsOrigin() ); - } - } - } -} - -void CAntlionTemplateMaker::BlockedCheckFunc( void ) -{ - SetContextThink( &CAntlionTemplateMaker::BlockedCheckFunc, -1, s_pBlockedCheckContext ); - - if ( m_bBlocked == true ) - return; - - CUtlVector hintList; - int iBlocked = 0; - - CHintCriteria hintCriteria; - - hintCriteria.SetGroup( m_strSpawnGroup ); - hintCriteria.SetHintType( HINT_ANTLION_BURROW_POINT ); - - if ( CAI_HintManager::FindAllHints( vec3_origin, hintCriteria, &hintList ) > 0 ) - { - for ( int i = 0; i < hintList.Count(); i++ ) - { - CAI_Hint *pNode = hintList[i]; - - if ( pNode ) - { - Vector vHintPos; - pNode->GetPosition( AI_GetSinglePlayer(), &vHintPos ); - - CBaseEntity* pList[20]; - int count = UTIL_EntitiesInBox( pList, 20, vHintPos + NAI_Hull::Mins( HULL_MEDIUM ), vHintPos + NAI_Hull::Maxs( HULL_MEDIUM ), 0 ); - - //Iterate over all the possible targets - for ( int i = 0; i < count; i++ ) - { - if ( pList[i]->GetMoveType() != MOVETYPE_VPHYSICS ) - continue; - - if ( PhysGetEntityMass( pList[i] ) > ANTLION_MAKER_BLOCKED_MASS ) - { - iBlocked++; - break; - } - } - } - } - } - - if ( iBlocked > 0 && hintList.Count() == iBlocked ) - { - m_bBlocked = true; - m_OnAllBlocked.FireOutput( this, this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Makes the antlion immediatley unburrow if it started burrowed -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::ChildPostSpawn( CAI_BaseNPC *pChild ) -{ - CNPC_Antlion *pAntlion = static_cast(pChild); - - if ( pAntlion == NULL ) - return; - - // Unburrow the spawned antlion immediately - if ( pAntlion->m_bStartBurrowed ) - { - pAntlion->BurrowUse( this, this, USE_ON, 0.0f ); - } - - // Set us to a follow target, if we have one - if ( GetFollowTarget() ) - { - pAntlion->SetFollowTarget( GetFollowTarget() ); - } - else if ( ( m_strFollowTarget != NULL_STRING ) ) - { - // If we don't already have a fight target, set it up - SetFollowTarget( m_strFollowTarget ); - - if ( GetFightTarget() == NULL ) - { - SetChildMoveState( ANTLION_MOVE_FOLLOW ); - - // If it's valid, fight there - if ( GetFollowTarget() != NULL ) - { - pAntlion->SetFollowTarget( GetFollowTarget() ); - } - } - } - // See if we need to send them on their way to a fight goal - if ( GetFightTarget() && !HasSpawnFlags( SF_ANTLIONMAKER_RANDOM_FIGHT_TARGET ) ) - { - pAntlion->SetFightTarget( GetFightTarget() ); - } - else if ( m_strFightTarget != NULL_STRING ) - { - // If we don't already have a fight target, set it up - SetFightTarget( m_strFightTarget ); - SetChildMoveState( ANTLION_MOVE_FIGHT_TO_GOAL ); - - // If it's valid, fight there - if ( GetFightTarget() != NULL ) - { - pAntlion->SetFightTarget( GetFightTarget() ); - } - } - - // Set us to the desired movement state - pAntlion->SetMoveState( m_nChildMoveState ); - - // Save our name for level transitions - pAntlion->SetParentSpawnerName( STRING( GetEntityName() ) ); - - if ( m_hIgnoreEntity != NULL ) - { - pChild->SetOwnerEntity( m_hIgnoreEntity ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::InputSetFightTarget( inputdata_t &inputdata ) -{ - // Set our new goal - m_strFightTarget = MAKE_STRING( inputdata.value.String() ); - - SetFightTarget( m_strFightTarget, inputdata.pActivator, inputdata.pCaller ); - SetChildMoveState( ANTLION_MOVE_FIGHT_TO_GOAL ); - - UpdateChildren(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::InputSetFollowTarget( inputdata_t &inputdata ) -{ - // Set our new goal - m_strFollowTarget = MAKE_STRING( inputdata.value.String() ); - - SetFollowTarget( m_strFollowTarget, inputdata.pActivator, inputdata.pCaller ); - SetChildMoveState( ANTLION_MOVE_FOLLOW ); - - UpdateChildren(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::InputClearFightTarget( inputdata_t &inputdata ) -{ - SetFightTarget( NULL ); - SetChildMoveState( ANTLION_MOVE_FOLLOW ); - - UpdateChildren(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::InputClearFollowTarget( inputdata_t &inputdata ) -{ - SetFollowTarget( NULL ); - SetChildMoveState( ANTLION_MOVE_FIGHT_TO_GOAL ); - - UpdateChildren(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::InputSetSpawnRadius( inputdata_t &inputdata ) -{ - m_flSpawnRadius = inputdata.value.Float(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::InputAddToPool( inputdata_t &inputdata ) -{ - PoolAdd( inputdata.value.Int() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::InputSetMaxPool( inputdata_t &inputdata ) -{ - m_iMaxPool = inputdata.value.Int(); - if ( m_iPool > m_iMaxPool ) - { - m_iPool = m_iMaxPool; - } - - // Stop regenerating if we're supposed to stop using the pool - if ( !m_iMaxPool ) - { - SetContextThink( NULL, gpGlobals->curtime, s_pPoolThinkContext ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::InputSetPoolRegenAmount( inputdata_t &inputdata ) -{ - m_iPoolRegenAmount = inputdata.value.Int(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::InputSetPoolRegenTime( inputdata_t &inputdata ) -{ - m_flPoolRegenTime = inputdata.value.Float(); - - if ( m_flPoolRegenTime != 0.0f ) - { - SetContextThink( &CAntlionTemplateMaker::PoolRegenThink, gpGlobals->curtime + m_flPoolRegenTime, s_pPoolThinkContext ); - } - else - { - SetContextThink( NULL, gpGlobals->curtime, s_pPoolThinkContext ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Pool behavior for coast -// Input : iNumToAdd - -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::PoolAdd( int iNumToAdd ) -{ - m_iPool = clamp( m_iPool + iNumToAdd, 0, m_iMaxPool ); -} - -//----------------------------------------------------------------------------- -// Purpose: Regenerate the pool -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::PoolRegenThink( void ) -{ - if ( m_iPool < m_iMaxPool ) - { - m_iPool = clamp( m_iPool + m_iPoolRegenAmount, 0, m_iMaxPool ); - - if ( g_debug_antlionmaker.GetInt() == 2 ) - { - Msg("REGENERATED: Pool: %d (max %d) (Regenerating %d every %f)\n", m_iPool, m_iMaxPool, m_iPoolRegenAmount, m_flPoolRegenTime ); - } - } - - SetContextThink( &CAntlionTemplateMaker::PoolRegenThink, gpGlobals->curtime + m_flPoolRegenTime, s_pPoolThinkContext ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pVictim - -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::DeathNotice( CBaseEntity *pVictim ) -{ - CNPC_Antlion *pAnt = dynamic_cast(pVictim); - if ( pAnt == NULL ) - return; - - // Take it out of our list - RemoveChild( pAnt ); - - // Check if all live children are now dead - if ( m_nLiveChildren <= 0 ) - { - // Fire the output for this case - m_OnAllLiveChildrenDead.FireOutput( this, this ); - - bool bPoolDepleted = ( m_iMaxPool != 0 && m_iPool == 0 ); - if ( bPoolDepleted || IsDepleted() ) - { - // Signal that all our children have been spawned and are now dead - m_OnAllSpawnedDead.FireOutput( this, this ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: If this had a finite number of children, return true if they've all -// been created. -//----------------------------------------------------------------------------- -bool CAntlionTemplateMaker::IsDepleted( void ) -{ - // If we're running pool behavior, we're never depleted - if ( m_iMaxPool ) - return false; - - return BaseClass::IsDepleted(); -} - -//----------------------------------------------------------------------------- -// Purpose: Change the spawn group the maker is using -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::InputChangeDestinationGroup( inputdata_t &inputdata ) -{ - // FIXME: This function is redundant to the base class version, remove the m_strSpawnGroup - m_strSpawnGroup = inputdata.value.StringID(); -} - -//----------------------------------------------------------------------------- -// Purpose: Draw debugging text for the spawner -//----------------------------------------------------------------------------- -int CAntlionTemplateMaker::DrawDebugTextOverlays( void ) -{ - // We don't want the base class info, it's not useful to us - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if ( m_debugOverlays & OVERLAY_TEXT_BIT ) - { - char tempstr[255]; - - // Print the state of the spawner - if ( m_bDisabled ) - { - Q_strncpy( tempstr, "State: Disabled\n", sizeof(tempstr) ); - } - else - { - Q_strncpy( tempstr, "State: Enabled\n", sizeof(tempstr) ); - } - - EntityText( text_offset, tempstr, 0 ); - text_offset++; - - // Print follow information - if ( m_strFollowTarget != NULL_STRING ) - { - Q_snprintf( tempstr, sizeof(tempstr), "Follow Target: %s\n", STRING( m_strFollowTarget ) ); - } - else - { - Q_strncpy( tempstr, "Follow Target : NONE\n", sizeof(tempstr) ); - } - - EntityText( text_offset, tempstr, 0 ); - text_offset++; - - // Print fight information - if ( m_strFightTarget != NULL_STRING ) - { - Q_snprintf( tempstr, sizeof(tempstr), "Fight Target: %s\n", STRING( m_strFightTarget ) ); - } - else - { - Q_strncpy( tempstr, "Fight Target : NONE\n", sizeof(tempstr) ); - } - - EntityText( text_offset, tempstr, 0 ); - text_offset++; - - // Print spawning criteria information - if ( m_strSpawnTarget != NULL_STRING ) - { - Q_snprintf( tempstr, sizeof(tempstr), "Spawn Target: %s\n", STRING( m_strSpawnTarget ) ); - } - else - { - Q_strncpy( tempstr, "Spawn Target : NONE\n", sizeof(tempstr) ); - } - - EntityText( text_offset, tempstr, 0 ); - text_offset++; - - // Print the chilrens' state - Q_snprintf( tempstr, sizeof(tempstr), "Spawn Frequency: %f\n", m_flSpawnFrequency ); - EntityText( text_offset, tempstr, 0 ); - text_offset++; - - // Print the spawn radius - Q_snprintf( tempstr, sizeof(tempstr), "Spawn Radius: %.02f units\n", m_flSpawnRadius ); - EntityText( text_offset, tempstr, 0 ); - text_offset++; - - // Print the spawn group we're using - if ( m_strSpawnGroup != NULL_STRING ) - { - Q_snprintf( tempstr, sizeof(tempstr), "Spawn Group: %s\n", STRING( m_strSpawnGroup ) ); - EntityText( text_offset, tempstr, 0 ); - text_offset++; - } - - // Print the chilrens' state - Q_snprintf( tempstr, sizeof(tempstr), "Live Children: (%d/%d)\n", m_nLiveChildren, m_nMaxLiveChildren ); - EntityText( text_offset, tempstr, 0 ); - text_offset++; - - // Print pool information - if ( m_iMaxPool ) - { - // Print the pool's state - Q_snprintf( tempstr, sizeof(tempstr), "Pool: (%d/%d) (%d per regen)\n", m_iPool, m_iMaxPool, m_iPoolRegenAmount ); - EntityText( text_offset, tempstr, 0 ); - text_offset++; - - float flTimeRemaining = GetNextThink( s_pPoolThinkContext ) - gpGlobals->curtime; - - if ( flTimeRemaining < 0.0f ) - { - flTimeRemaining = 0.0f; - } - - // Print the pool's regeneration state - Q_snprintf( tempstr, sizeof(tempstr), "Pool Regen Time: %.02f sec. (%.02f remaining)\n", m_flPoolRegenTime, flTimeRemaining ); - EntityText( text_offset, tempstr, 0 ); - text_offset++; - } - } - - return text_offset; -} - -//----------------------------------------------------------------------------- -// Purpose: Draw debugging overlays for the spawner -//----------------------------------------------------------------------------- -void CAntlionTemplateMaker::DrawDebugGeometryOverlays( void ) -{ - BaseClass::DrawDebugGeometryOverlays(); - - if ( m_debugOverlays & OVERLAY_TEXT_BIT ) - { - int r, g, b; - - // Color by active state - if ( m_bDisabled ) - { - r = 255; - g = 0; - b = 0; - } - else - { - r = 0; - g = 255; - b = 0; - } - - // Draw ourself - NDebugOverlay::Box( GetAbsOrigin(), -Vector(8,8,8), Vector(8,8,8), r, g, b, true, 0.05f ); - - // Draw lines to our spawngroup hints - if ( m_strSpawnGroup != NULL_STRING ) - { - // Draw lines to our active hint groups - AIHintIter_t iter; - CAI_Hint *pHint = CAI_HintManager::GetFirstHint( &iter ); - while ( pHint != NULL ) - { - // Must be of the hint group we care about - if ( pHint->GetGroup() != m_strSpawnGroup ) - { - pHint = CAI_HintManager::GetNextHint( &iter ); - continue; - } - - // Draw an arrow to the spot - NDebugOverlay::VertArrow( GetAbsOrigin(), pHint->GetAbsOrigin() + Vector( 0, 0, 32 ), 8.0f, r, g, b, 0, true, 0.05f ); - - // Draw a box to represent where it's sitting - Vector vecForward; - AngleVectors( pHint->GetAbsAngles(), &vecForward ); - NDebugOverlay::BoxDirection( pHint->GetAbsOrigin(), -Vector(32,32,0), Vector(32,32,16), vecForward, r, g, b, true, 0.05f ); - - // Move to the next - pHint = CAI_HintManager::GetNextHint( &iter ); - } - } - - // Draw a line to the spawn target (if it exists) - if ( m_strSpawnTarget != NULL_STRING ) - { - // Find all the possible targets - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, m_strSpawnTarget ); - if ( pTarget != NULL ) - { - NDebugOverlay::VertArrow( GetAbsOrigin(), pTarget->WorldSpaceCenter(), 4.0f, 255, 255, 255, 0, true, 0.05f ); - } - } - - // Draw a line to the follow target (if it exists) - if ( m_strFollowTarget != NULL_STRING ) - { - // Find all the possible targets - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, m_strFollowTarget ); - if ( pTarget != NULL ) - { - NDebugOverlay::VertArrow( GetAbsOrigin(), pTarget->WorldSpaceCenter(), 4.0f, 255, 255, 0, 0, true, 0.05f ); - } - } - - // Draw a line to the fight target (if it exists) - if ( m_strFightTarget != NULL_STRING ) - { - // Find all the possible targets - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, m_strFightTarget ); - if ( pTarget != NULL ) - { - NDebugOverlay::VertArrow( GetAbsOrigin(), pTarget->WorldSpaceCenter(), 4.0f, 255, 0, 0, 0, true, 0.05f ); - } - } - } -} diff --git a/game/server/hl2/antlion_maker.h b/game/server/hl2/antlion_maker.h deleted file mode 100644 index ae7d99eb1..000000000 --- a/game/server/hl2/antlion_maker.h +++ /dev/null @@ -1,186 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ANTLION_MAKER_H -#define ANTLION_MAKER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "npc_antlion.h" -#include "monstermaker.h" -#include "igamesystem.h" -#include "ai_hint.h" - -// -// Antlion maker class -// - -#define SF_ANTLIONMAKER_RANDOM_SPAWN_NODE 0x00000400 -#define SF_ANTLIONMAKER_SPAWN_CLOSE_TO_TARGET 0x00000800 -#define SF_ANTLIONMAKER_RANDOM_FIGHT_TARGET 0x00001000 -#define SF_ANTLIONMAKER_DO_BLOCKEDEFFECTS 0x00002000 - -class CAntlionTemplateMaker : public CTemplateNPCMaker -{ - public: - - DECLARE_CLASS( CAntlionTemplateMaker, CTemplateNPCMaker ); - - CAntlionTemplateMaker( void ); - ~CAntlionTemplateMaker( void ); - - virtual int DrawDebugTextOverlays( void ); - virtual void DrawDebugGeometryOverlays( void ); - - void MakeNPC( void ); - void ChildPreSpawn( CAI_BaseNPC *pChild ); - void ChildPostSpawn( CAI_BaseNPC *pChild ); - - void InputSetFightTarget( inputdata_t &inputdata ); - void InputSetFollowTarget( inputdata_t &inputdata ); - void InputClearFightTarget( inputdata_t &inputdata ); - void InputClearFollowTarget( inputdata_t &inputdata ); - void InputSetSpawnRadius( inputdata_t &inputdata ); - void InputAddToPool( inputdata_t &inputdata ); - void InputSetMaxPool( inputdata_t &inputdata ); - void InputSetPoolRegenAmount( inputdata_t &inputdata ); - void InputSetPoolRegenTime( inputdata_t &inputdata ); - void InputChangeDestinationGroup( inputdata_t &inputdata ); - - void Activate( void ); - - // Do not transition - int ObjectCaps( void ) { return (BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION); } - - bool CanMakeNPC( bool bIgnoreSolidEntities = false ); - bool ShouldAlwaysThink( void ) { return true; } - - void AddChild( CNPC_Antlion *pAnt ); - void RemoveChild( CNPC_Antlion *pAnt ); - - void FixupOrphans( void ); - void UpdateChildren( void ); - - void CreateProxyTarget( const Vector &position ); - void DestroyProxyTarget( void ); - - void SetFightTarget( string_t strTarget, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); - void SetFightTarget( CBaseEntity *pEntity ); - void SetFightTarget( const Vector &position ); - - void SetFollowTarget( string_t strTarget, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); - void SetFollowTarget( CBaseEntity *pEntity ); - - void SetChildMoveState( AntlionMoveState_e state ); - - void DeathNotice( CBaseEntity *pVictim ); - bool IsDepleted( void ); - - bool ShouldHearBugbait( void ) { return (m_bIgnoreBugbait==false); } - - CBaseEntity *GetFightTarget( void ); - CBaseEntity *GetFollowTarget( void ); - - virtual void Enable( void ); - virtual void Disable( void ); - - - void BlockedCheckFunc( void ); - void FindNodesCloseToPlayer( void ); - void DoBlockedEffects( CBaseEntity *pBlocker, Vector vOrigin ); - - CBaseEntity *AllHintsFromClusterBlocked( CAI_Hint *pNode, bool &bChosenHintBlocked ); - - void ActivateAllSpores( void ); - void ActivateSpore( const char* sporename, Vector vOrigin ); - void DisableSpore( const char* sporename ); - void DisableAllSpores( void ); - -protected: - - void PrecacheTemplateEntity( CBaseEntity *pEntity ); - - bool FindHintSpawnPosition( const Vector &origin, float radius, string_t hintGroupName, CAI_Hint **pHint, bool bRandom = false ); - bool FindNearTargetSpawnPosition( Vector &origin, float radius, CBaseEntity *pTarget ); - - //These are used by FindNearTargetSpawnPosition - bool FindPositionOnFoot( Vector &origin, float radius, CBaseEntity *pTarget ); - bool FindPositionOnVehicle( Vector &origin, float radius, CBaseEntity *pTarget ); - bool ValidateSpawnPosition( Vector &vOrigin, CBaseEntity *pTarget = NULL ); - - // Pool behavior for coast - void PoolAdd( int iNumToAdd ); - void PoolRegenThink( void ); - -protected: - // FIXME: The m_strSpawnGroup is redundant to the m_iszDestinationGroup in the base class NPC template maker - string_t m_strSpawnGroup; // if present, spawn children on the nearest node of this group (to the player) - string_t m_strSpawnTarget; // name of target to spawn near - float m_flSpawnRadius; // radius around target to attempt to spawn in - float m_flWorkerSpawnRate; // Percentage chance of spawning a worker when we spawn an antlion [0..1]. - - string_t m_strFightTarget; // target entity name that all children will be told to fight to - string_t m_strFollowTarget; // entity name that all children will follow - - bool m_bIgnoreBugbait; // Whether or not to ignore bugbait - - AntlionMoveState_e m_nChildMoveState; - - EHANDLE m_hFightTarget; // A normal entity pointer for fight position - EHANDLE m_hProxyTarget; // This is a self-held target that is created and used when a vector is passed in as a fight - // goal, instead of an entity - EHANDLE m_hFollowTarget; // Target to follow - - CUtlVector< CHandle< CNPC_Antlion > > m_Children; - - // Pool behavior for coast - int m_iPool; - int m_iMaxPool; - int m_iPoolRegenAmount; - float m_flPoolRegenTime; - - float m_flVehicleSpawnDistance; - - int m_iSkinCount; - - float m_flBlockedBumpTime; - - bool m_bBlocked; - COutputEvent m_OnAllBlocked; - - bool m_bCreateSpores; - - DECLARE_DATADESC(); -}; - -// ======================================================== -// Antlion maker manager -// ======================================================== - -class CAntlionMakerManager : public CAutoGameSystem -{ -public: - CAntlionMakerManager( char const *name ) : CAutoGameSystem( name ) - { - } - - void LevelInitPostEntity( void ); - - void BroadcastFightGoal( const Vector &vFightGoal ); - void BroadcastFightGoal( CBaseEntity *pFightGoal ); - void BroadcastFollowGoal( CBaseEntity *pFollowGoal ); - -protected: - - void GatherMakers( void ); - - CUtlVector< CHandle< CAntlionTemplateMaker > > m_Makers; -}; - -extern CAntlionMakerManager g_AntlionMakerManager; - -#endif // ANTLION_MAKER_H diff --git a/game/server/hl2/ar2_explosion.cpp b/game/server/hl2/ar2_explosion.cpp deleted file mode 100644 index 153459368..000000000 --- a/game/server/hl2/ar2_explosion.cpp +++ /dev/null @@ -1,112 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "ar2_explosion.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define AR2EXPLOSION_ENTITYNAME "ar2explosion" - - -IMPLEMENT_SERVERCLASS_ST(AR2Explosion, DT_AR2Explosion) - SendPropString( SENDINFO( m_szMaterialName ) ), -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS(ar2explosion, AR2Explosion); - - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( AR2Explosion ) - - DEFINE_AUTO_ARRAY( m_szMaterialName, FIELD_CHARACTER ), - -END_DATADESC() - - -AR2Explosion* AR2Explosion::CreateAR2Explosion(const Vector &pos) -{ - CBaseEntity *pEnt = CreateEntityByName(AR2EXPLOSION_ENTITYNAME); - if(pEnt) - { - AR2Explosion *pEffect = dynamic_cast(pEnt); - if(pEffect && pEffect->edict()) - { - pEffect->SetLocalOrigin( pos ); - pEffect->Activate(); - return pEffect; - } - else - { - UTIL_Remove(pEnt); - } - } - - return NULL; -} - - -//----------------------------------------------------------------------------- -// A lightweight entity for level-designer placed AR2 explosions. -//----------------------------------------------------------------------------- -class CEnvAR2Explosion : public CPointEntity -{ -public: - DECLARE_CLASS( CEnvAR2Explosion, CPointEntity ); - - void Spawn( void ); - - // Input handlers - void InputExplode( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - -private: - - string_t m_iszMaterialName; -}; - - -BEGIN_DATADESC( CEnvAR2Explosion ) - DEFINE_INPUTFUNC(FIELD_VOID, "Explode", InputExplode), - DEFINE_KEYFIELD(m_iszMaterialName, FIELD_STRING, "material"), -END_DATADESC() - -LINK_ENTITY_TO_CLASS( env_ar2explosion, CEnvAR2Explosion ); - - -//----------------------------------------------------------------------------- -// Purpose: So you can see where this function begins and the last one ends. -//----------------------------------------------------------------------------- -void CEnvAR2Explosion::Spawn( void ) -{ - Precache(); - - SetSolid( SOLID_NONE ); - AddEffects( EF_NODRAW ); - - SetMoveType( MOVETYPE_NONE ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Creates the explosion effect. -//----------------------------------------------------------------------------- -void CEnvAR2Explosion::InputExplode( inputdata_t &inputdata ) -{ - AR2Explosion *pExplosion = AR2Explosion::CreateAR2Explosion(GetAbsOrigin()); - if (pExplosion) - { - pExplosion->SetLifetime( 10 ); - if (m_iszMaterialName != NULL_STRING) - { - pExplosion->SetMaterialName(STRING(m_iszMaterialName)); - } - } -} diff --git a/game/server/hl2/ar2_explosion.h b/game/server/hl2/ar2_explosion.h deleted file mode 100644 index f5a767353..000000000 --- a/game/server/hl2/ar2_explosion.h +++ /dev/null @@ -1,43 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef AR2_EXPLOSION_H -#define AR2_EXPLOSION_H - - -#include "baseparticleentity.h" - - -class AR2Explosion : public CBaseParticleEntity -{ - DECLARE_DATADESC(); - -public: - DECLARE_CLASS( AR2Explosion, CBaseParticleEntity ); - DECLARE_SERVERCLASS(); - - static AR2Explosion* CreateAR2Explosion(const Vector &pos); - - inline void SetMaterialName(const char *szMaterialName); - -private: - - CNetworkString( m_szMaterialName, 255 ); -}; - - -void AR2Explosion::SetMaterialName(const char *szMaterialName) -{ - if (szMaterialName) - { - Q_strncpy(m_szMaterialName.GetForModify(), szMaterialName, sizeof(m_szMaterialName)); - } -} - - -#endif diff --git a/game/server/hl2/assassin_smoke.cpp b/game/server/hl2/assassin_smoke.cpp deleted file mode 100644 index d86a4f748..000000000 --- a/game/server/hl2/assassin_smoke.cpp +++ /dev/null @@ -1,44 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "assassin_smoke.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define ASSASSINSMOKE_ENTITYNAME "env_assassinsmoke" - - -IMPLEMENT_SERVERCLASS_ST(CAssassinSmoke, DT_AssassinSmoke) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS(env_assassinsmoke, CAssassinSmoke); - - -CAssassinSmoke* CAssassinSmoke::CreateAssassinSmoke(const Vector &pos) -{ - CBaseEntity *pEnt = CreateEntityByName(ASSASSINSMOKE_ENTITYNAME); - if(pEnt) - { - CAssassinSmoke *pEffect = dynamic_cast(pEnt); - if (pEffect && pEffect->edict()) - { - pEffect->SetLocalOrigin( pos ); - pEffect->Activate(); - return pEffect; - } - else - { - UTIL_Remove(pEnt); - } - } - - return NULL; -} - - diff --git a/game/server/hl2/assassin_smoke.h b/game/server/hl2/assassin_smoke.h deleted file mode 100644 index c8e897535..000000000 --- a/game/server/hl2/assassin_smoke.h +++ /dev/null @@ -1,28 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef ASSASSIN_SMOKE_H -#define ASSASSIN_SMOKE_H - - -#include "baseparticleentity.h" - - -class CAssassinSmoke : public CBaseParticleEntity -{ -public: - DECLARE_CLASS( CAssassinSmoke, CBaseParticleEntity ); - DECLARE_SERVERCLASS(); - - static CAssassinSmoke* CreateAssassinSmoke (const Vector &pos); -}; - - -#endif//ASSASSIN_SMOKE_H - - diff --git a/game/server/hl2/basehlcombatweapon.cpp b/game/server/hl2/basehlcombatweapon.cpp deleted file mode 100644 index fedbb407c..000000000 --- a/game/server/hl2/basehlcombatweapon.cpp +++ /dev/null @@ -1,522 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "basehlcombatweapon.h" -#include "soundent.h" -#include "ai_basenpc.h" -#include "game.h" -#include "in_buttons.h" -#include "GameStats.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -IMPLEMENT_SERVERCLASS_ST( CHLMachineGun, DT_HLMachineGun ) -END_SEND_TABLE() - -//========================================================= -// >> CHLSelectFireMachineGun -//========================================================= -BEGIN_DATADESC( CHLMachineGun ) - - DEFINE_FIELD( m_nShotsFired, FIELD_INTEGER ), - DEFINE_FIELD( m_flNextSoundTime, FIELD_TIME ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CHLMachineGun::CHLMachineGun( void ) -{ -} - -const Vector &CHLMachineGun::GetBulletSpread( void ) -{ - static Vector cone = VECTOR_CONE_3DEGREES; - return cone; -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CHLMachineGun::PrimaryAttack( void ) -{ - // Only the player fires this way so we can cast - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - if (!pPlayer) - return; - - // Abort here to handle burst and auto fire modes - if ( (UsesClipsForAmmo1() && m_iClip1 == 0) || ( !UsesClipsForAmmo1() && !pPlayer->GetAmmoCount(m_iPrimaryAmmoType) ) ) - return; - - m_nShotsFired++; - - pPlayer->DoMuzzleFlash(); - - // To make the firing framerate independent, we may have to fire more than one bullet here on low-framerate systems, - // especially if the weapon we're firing has a really fast rate of fire. - int iBulletsToFire = 0; - float fireRate = GetFireRate(); - - // MUST call sound before removing a round from the clip of a CHLMachineGun - while ( m_flNextPrimaryAttack <= gpGlobals->curtime ) - { - WeaponSound(SINGLE, m_flNextPrimaryAttack); - m_flNextPrimaryAttack = m_flNextPrimaryAttack + fireRate; - iBulletsToFire++; - } - - // Make sure we don't fire more than the amount in the clip, if this weapon uses clips - if ( UsesClipsForAmmo1() ) - { - if ( iBulletsToFire > m_iClip1 ) - iBulletsToFire = m_iClip1; - m_iClip1 -= iBulletsToFire; - } - - m_iPrimaryAttacks++; - gamestats->Event_WeaponFired( pPlayer, true, GetClassname() ); - - // Fire the bullets - FireBulletsInfo_t info; - info.m_iShots = iBulletsToFire; - info.m_vecSrc = pPlayer->Weapon_ShootPosition( ); - info.m_vecDirShooting = pPlayer->GetAutoaimVector( AUTOAIM_SCALE_DEFAULT ); - info.m_vecSpread = pPlayer->GetAttackSpread( this ); - info.m_flDistance = MAX_TRACE_LENGTH; - info.m_iAmmoType = m_iPrimaryAmmoType; - info.m_iTracerFreq = 2; - FireBullets( info ); - - //Factor in the view kick - AddViewKick(); - - CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), SOUNDENT_VOLUME_MACHINEGUN, 0.2, pPlayer ); - - if (!m_iClip1 && pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0) - { - // HEV suit - indicate out of ammo condition - pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); - } - - SendWeaponAnim( GetPrimaryAttackActivity() ); - pPlayer->SetAnimation( PLAYER_ATTACK1 ); - - // Register a muzzleflash for the AI - pPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -//----------------------------------------------------------------------------- -void CHLMachineGun::FireBullets( const FireBulletsInfo_t &info ) -{ - if(CBasePlayer *pPlayer = ToBasePlayer ( GetOwner() ) ) - { - pPlayer->FireBullets(info); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Weapon firing conditions -//----------------------------------------------------------------------------- -int CHLMachineGun::WeaponRangeAttack1Condition( float flDot, float flDist ) -{ - if ( m_iClip1 <=0 ) - { - return COND_NO_PRIMARY_AMMO; - } - else if ( flDist < m_fMinRange1 ) - { - return COND_TOO_CLOSE_TO_ATTACK; - } - else if ( flDist > m_fMaxRange1 ) - { - return COND_TOO_FAR_TO_ATTACK; - } - else if ( flDot < 0.5f ) // UNDONE: Why check this here? Isn't the AI checking this already? - { - return COND_NOT_FACING_ATTACK; - } - - return COND_CAN_RANGE_ATTACK1; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHLMachineGun::DoMachineGunKick( CBasePlayer *pPlayer, float dampEasy, float maxVerticleKickAngle, float fireDurationTime, float slideLimitTime ) -{ - #define KICK_MIN_X 0.2f //Degrees - #define KICK_MIN_Y 0.2f //Degrees - #define KICK_MIN_Z 0.1f //Degrees - - QAngle vecScratch; - - //Find how far into our accuracy degradation we are - float duration = ( fireDurationTime > slideLimitTime ) ? slideLimitTime : fireDurationTime; - float kickPerc = duration / slideLimitTime; - - // do this to get a hard discontinuity, clear out anything under 10 degrees punch - pPlayer->ViewPunchReset( 10 ); - - //Apply this to the view angles as well - vecScratch.x = -( KICK_MIN_X + ( maxVerticleKickAngle * kickPerc ) ); - vecScratch.y = -( KICK_MIN_Y + ( maxVerticleKickAngle * kickPerc ) ) / 3; - vecScratch.z = KICK_MIN_Z + ( maxVerticleKickAngle * kickPerc ) / 8; - - //Wibble left and right - if ( random->RandomInt( -1, 1 ) >= 0 ) - vecScratch.y *= -1; - - //Wobble up and down - if ( random->RandomInt( -1, 1 ) >= 0 ) - vecScratch.z *= -1; - - //If we're in easy, dampen the effect a bit - if ( g_pGameRules->IsSkillLevel( SKILL_EASY ) ) - { - for ( int i = 0; i < 3; i++ ) - { - vecScratch[i] *= dampEasy; - } - } - - //Clip this to our desired min/max - UTIL_ClipPunchAngleOffset( vecScratch, pPlayer->m_Local.m_vecPunchAngle, QAngle( 24.0f, 3.0f, 1.0f ) ); - - //Add it to the view punch - // NOTE: 0.5 is just tuned to match the old effect before the punch became simulated - pPlayer->ViewPunch( vecScratch * 0.5 ); -} - -//----------------------------------------------------------------------------- -// Purpose: Reset our shots fired -//----------------------------------------------------------------------------- -bool CHLMachineGun::Deploy( void ) -{ - m_nShotsFired = 0; - - return BaseClass::Deploy(); -} - - - -//----------------------------------------------------------------------------- -// Purpose: Make enough sound events to fill the estimated think interval -// returns: number of shots needed -//----------------------------------------------------------------------------- -int CHLMachineGun::WeaponSoundRealtime( WeaponSound_t shoot_type ) -{ - int numBullets = 0; - - // ran out of time, clamp to current - if (m_flNextSoundTime < gpGlobals->curtime) - { - m_flNextSoundTime = gpGlobals->curtime; - } - - // make enough sound events to fill up the next estimated think interval - float dt = clamp( m_flAnimTime - m_flPrevAnimTime, 0, 0.2 ); - if (m_flNextSoundTime < gpGlobals->curtime + dt) - { - WeaponSound( SINGLE_NPC, m_flNextSoundTime ); - m_flNextSoundTime += GetFireRate(); - numBullets++; - } - if (m_flNextSoundTime < gpGlobals->curtime + dt) - { - WeaponSound( SINGLE_NPC, m_flNextSoundTime ); - m_flNextSoundTime += GetFireRate(); - numBullets++; - } - - return numBullets; -} - - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHLMachineGun::ItemPostFrame( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - // Debounce the recoiling counter - if ( ( pOwner->m_nButtons & IN_ATTACK ) == false ) - { - m_nShotsFired = 0; - } - - BaseClass::ItemPostFrame(); -} - -IMPLEMENT_SERVERCLASS_ST( CHLSelectFireMachineGun, DT_HLSelectFireMachineGun ) -END_SEND_TABLE() - -//========================================================= -// >> CHLSelectFireMachineGun -//========================================================= -BEGIN_DATADESC( CHLSelectFireMachineGun ) - - DEFINE_FIELD( m_iBurstSize, FIELD_INTEGER ), - DEFINE_FIELD( m_iFireMode, FIELD_INTEGER ), - - // Function pinters - DEFINE_FUNCTION( BurstThink ), - -END_DATADESC() - - - -float CHLSelectFireMachineGun::GetBurstCycleRate( void ) -{ - // this is the time it takes to fire an entire - // burst, plus whatever amount of delay we want - // to have between bursts. - return 0.5f; -} - -float CHLSelectFireMachineGun::GetFireRate( void ) -{ - switch( m_iFireMode ) - { - case FIREMODE_FULLAUTO: - // the time between rounds fired on full auto - return 0.1f; // 600 rounds per minute = 0.1 seconds per bullet - break; - - case FIREMODE_3RNDBURST: - // the time between rounds fired within a single burst - return 0.1f; // 600 rounds per minute = 0.1 seconds per bullet - break; - - default: - return 0.1f; - break; - } -} - -bool CHLSelectFireMachineGun::Deploy( void ) -{ - // Forget about any bursts this weapon was firing when holstered - m_iBurstSize = 0; - return BaseClass::Deploy(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CHLSelectFireMachineGun::PrimaryAttack( void ) -{ - if (m_bFireOnEmpty) - { - return; - } - switch( m_iFireMode ) - { - case FIREMODE_FULLAUTO: - BaseClass::PrimaryAttack(); - // Msg("%.3f\n", m_flNextPrimaryAttack.Get() ); - SetWeaponIdleTime( gpGlobals->curtime + 3.0f ); - break; - - case FIREMODE_3RNDBURST: - m_iBurstSize = GetBurstSize(); - - // Call the think function directly so that the first round gets fired immediately. - BurstThink(); - SetThink( &CHLSelectFireMachineGun::BurstThink ); - m_flNextPrimaryAttack = gpGlobals->curtime + GetBurstCycleRate(); - m_flNextSecondaryAttack = gpGlobals->curtime + GetBurstCycleRate(); - - // Pick up the rest of the burst through the think function. - SetNextThink( gpGlobals->curtime + GetFireRate() ); - break; - } - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( pOwner ) - { - m_iPrimaryAttacks++; - gamestats->Event_WeaponFired( pOwner, true, GetClassname() ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CHLSelectFireMachineGun::SecondaryAttack( void ) -{ - // change fire modes. - - switch( m_iFireMode ) - { - case FIREMODE_FULLAUTO: - //Msg( "Burst\n" ); - m_iFireMode = FIREMODE_3RNDBURST; - WeaponSound(SPECIAL2); - break; - - case FIREMODE_3RNDBURST: - //Msg( "Auto\n" ); - m_iFireMode = FIREMODE_FULLAUTO; - WeaponSound(SPECIAL1); - break; - } - - SendWeaponAnim( GetSecondaryAttackActivity() ); - - m_flNextSecondaryAttack = gpGlobals->curtime + 0.3; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( pOwner ) - { - m_iSecondaryAttacks++; - gamestats->Event_WeaponFired( pOwner, false, GetClassname() ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CHLSelectFireMachineGun::BurstThink( void ) -{ - CHLMachineGun::PrimaryAttack(); - - m_iBurstSize--; - - if( m_iBurstSize == 0 ) - { - // The burst is over! - SetThink(NULL); - - // idle immediately to stop the firing animation - SetWeaponIdleTime( gpGlobals->curtime ); - return; - } - - SetNextThink( gpGlobals->curtime + GetFireRate() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CHLSelectFireMachineGun::WeaponSound( WeaponSound_t shoot_type, float soundtime /*= 0.0f*/ ) -{ - if (shoot_type == SINGLE) - { - switch( m_iFireMode ) - { - case FIREMODE_FULLAUTO: - BaseClass::WeaponSound( SINGLE, soundtime ); - break; - - case FIREMODE_3RNDBURST: - if( m_iBurstSize == GetBurstSize() && m_iClip1 >= m_iBurstSize ) - { - // First round of a burst, and enough bullets remaining in the clip to fire the whole burst - BaseClass::WeaponSound( BURST, soundtime ); - } - else if( m_iClip1 < m_iBurstSize ) - { - // Not enough rounds remaining in the magazine to fire a burst, so play the gunshot - // sounds individually as each round is fired. - BaseClass::WeaponSound( SINGLE, soundtime ); - } - - break; - } - return; - } - - BaseClass::WeaponSound( shoot_type, soundtime ); -} - -// BUGBUG: These need to be rethought -//----------------------------------------------------------------------------- -int CHLSelectFireMachineGun::WeaponRangeAttack1Condition( float flDot, float flDist ) -{ - if (m_iClip1 <=0) - { - return COND_NO_PRIMARY_AMMO; - } - else if ( flDist < m_fMinRange1) - { - return COND_TOO_CLOSE_TO_ATTACK; - } - else if (flDist > m_fMaxRange1) - { - return COND_TOO_FAR_TO_ATTACK; - } - else if (flDot < 0.5) // UNDONE: Why check this here? Isn't the AI checking this already? - { - return COND_NOT_FACING_ATTACK; - } - - return COND_CAN_RANGE_ATTACK1; -} - -//----------------------------------------------------------------------------- -int CHLSelectFireMachineGun::WeaponRangeAttack2Condition( float flDot, float flDist ) -{ - return COND_NONE; // FIXME: disabled for now - - // m_iClip2 == -1 when no secondary clip is used - if ( m_iClip2 == 0 && UsesSecondaryAmmo() ) - { - return COND_NO_SECONDARY_AMMO; - } - else if ( flDist < m_fMinRange2 ) - { - // Don't return COND_TOO_CLOSE_TO_ATTACK only for primary attack - return COND_NONE; - } - else if (flDist > m_fMaxRange2 ) - { - // Don't return COND_TOO_FAR_TO_ATTACK only for primary attack - return COND_NONE; - } - else if ( flDot < 0.5 ) // UNDONE: Why check this here? Isn't the AI checking this already? - { - return COND_NOT_FACING_ATTACK; - } - - return COND_CAN_RANGE_ATTACK2; -} - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -CHLSelectFireMachineGun::CHLSelectFireMachineGun( void ) -{ - m_fMinRange1 = 65; - m_fMinRange2 = 65; - m_fMaxRange1 = 1024; - m_fMaxRange2 = 1024; - m_iFireMode = FIREMODE_FULLAUTO; -} diff --git a/game/server/hl2/basehlcombatweapon.h b/game/server/hl2/basehlcombatweapon.h deleted file mode 100644 index f558bab94..000000000 --- a/game/server/hl2/basehlcombatweapon.h +++ /dev/null @@ -1,97 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "basehlcombatweapon_shared.h" - -#ifndef BASEHLCOMBATWEAPON_H -#define BASEHLCOMBATWEAPON_H -#ifdef _WIN32 -#pragma once -#endif - -//========================================================= -// Machine gun base class -//========================================================= -abstract_class CHLMachineGun : public CBaseHLCombatWeapon -{ -public: - DECLARE_CLASS( CHLMachineGun, CBaseHLCombatWeapon ); - DECLARE_DATADESC(); - - CHLMachineGun(); - - DECLARE_SERVERCLASS(); - - void PrimaryAttack( void ); - - // Default calls through to m_hOwner, but plasma weapons can override and shoot projectiles here. - virtual void ItemPostFrame( void ); - virtual void FireBullets( const FireBulletsInfo_t &info ); - virtual float GetFireRate( void ) = 0; - virtual int WeaponRangeAttack1Condition( float flDot, float flDist ); - virtual bool Deploy( void ); - - virtual const Vector &GetBulletSpread( void ); - - int WeaponSoundRealtime( WeaponSound_t shoot_type ); - - // utility function - static void DoMachineGunKick( CBasePlayer *pPlayer, float dampEasy, float maxVerticleKickAngle, float fireDurationTime, float slideLimitTime ); - -protected: - - int m_nShotsFired; // Number of consecutive shots fired - - float m_flNextSoundTime; // real-time clock of when to make next sound -}; - -//========================================================= -// Machine guns capable of switching between full auto and -// burst fire modes. -//========================================================= -// Mode settings for select fire weapons -enum -{ - FIREMODE_FULLAUTO = 1, - FIREMODE_SEMI, - FIREMODE_3RNDBURST, -}; - -//========================================================= -// >> CHLSelectFireMachineGun -//========================================================= -class CHLSelectFireMachineGun : public CHLMachineGun -{ - DECLARE_CLASS( CHLSelectFireMachineGun, CHLMachineGun ); -public: - - CHLSelectFireMachineGun( void ); - - DECLARE_SERVERCLASS(); - - virtual float GetBurstCycleRate( void ); - virtual float GetFireRate( void ); - - virtual bool Deploy( void ); - virtual void WeaponSound( WeaponSound_t shoot_type, float soundtime = 0.0f ); - - DECLARE_DATADESC(); - - virtual int GetBurstSize( void ) { return 3; }; - - void BurstThink( void ); - - virtual void PrimaryAttack( void ); - virtual void SecondaryAttack( void ); - - virtual int WeaponRangeAttack1Condition( float flDot, float flDist ); - virtual int WeaponRangeAttack2Condition( float flDot, float flDist ); - -protected: - int m_iBurstSize; - int m_iFireMode; -}; -#endif // BASEHLCOMBATWEAPON_H diff --git a/game/server/hl2/cbasehelicopter.cpp b/game/server/hl2/cbasehelicopter.cpp deleted file mode 100644 index 43a7c54b2..000000000 --- a/game/server/hl2/cbasehelicopter.cpp +++ /dev/null @@ -1,1597 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Base class for helicopters & helicopter-type vehicles -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "ai_network.h" -#include "ai_default.h" -#include "ai_schedule.h" -#include "ai_hull.h" -#include "ai_node.h" -#include "ai_task.h" -#include "ai_senses.h" -#include "ai_memory.h" -#include "entitylist.h" -#include "soundenvelope.h" -#include "gamerules.h" -#include "grenade_homer.h" -#include "ndebugoverlay.h" -#include "cbasehelicopter.h" -#include "soundflags.h" -#include "rope.h" -#include "saverestore_utlvector.h" -#include "collisionutils.h" -#include "coordsize.h" -#include "effects.h" -#include "rotorwash.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -void ExpandBBox(Vector &vecMins, Vector &vecMaxs); - -#if 0 -virtual void NullThink( void ); -#endif //0 - -#define HELICOPTER_THINK_INTERVAL 0.1 -#define HELICOPTER_ROTORWASH_THINK_INTERVAL 0.01 -#define BASECHOPPER_DEBUG_WASH 1 - -ConVar g_debug_basehelicopter( "g_debug_basehelicopter", "0", FCVAR_CHEAT ); - -//--------------------------------------------------------- -//--------------------------------------------------------- -// TODOs -// -// -Member function: CHANGE MOVE GOAL -// -// -Member function: GET GRAVITY (or GetMaxThrust) -// -//--------------------------------------------------------- -//--------------------------------------------------------- - -static const char *s_pRotorWashThinkContext = "RotorWashThink"; -static const char *s_pDelayedKillThinkContext = "DelayedKillThink"; - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ - -BEGIN_DATADESC_NO_BASE( washentity_t ) - DEFINE_FIELD( hEntity, FIELD_EHANDLE ), - DEFINE_FIELD( flWashStartTime, FIELD_TIME ), -END_DATADESC() - - -BEGIN_DATADESC( CBaseHelicopter ) - - DEFINE_THINKFUNC( HelicopterThink ), - DEFINE_THINKFUNC( RotorWashThink ), - DEFINE_THINKFUNC( CallDyingThink ), - DEFINE_THINKFUNC( DelayedKillThink ), - DEFINE_ENTITYFUNC( CrashTouch ), - DEFINE_ENTITYFUNC( FlyTouch ), - - DEFINE_SOUNDPATCH( m_pRotorSound ), - DEFINE_SOUNDPATCH( m_pRotorBlast ), - DEFINE_FIELD( m_flForce, FIELD_FLOAT ), - DEFINE_FIELD( m_fHelicopterFlags, FIELD_INTEGER), - DEFINE_FIELD( m_vecDesiredFaceDir, FIELD_VECTOR ), - DEFINE_FIELD( m_flLastSeen, FIELD_TIME ), - DEFINE_FIELD( m_flPrevSeen, FIELD_TIME ), -// DEFINE_FIELD( m_iSoundState, FIELD_INTEGER ), // Don't save, precached - DEFINE_FIELD( m_vecTargetPosition, FIELD_POSITION_VECTOR ), - - DEFINE_FIELD( m_hRotorWash, FIELD_EHANDLE ), - - DEFINE_FIELD( m_flMaxSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_flMaxSpeedFiring, FIELD_FLOAT ), - DEFINE_FIELD( m_flGoalSpeed, FIELD_FLOAT ), - DEFINE_KEYFIELD( m_flInitialSpeed, FIELD_FLOAT, "InitialSpeed" ), - - DEFINE_FIELD( m_flRandomOffsetTime, FIELD_TIME ), - DEFINE_FIELD( m_vecRandomOffset, FIELD_VECTOR ), - DEFINE_FIELD( m_flRotorWashEntitySearchTime, FIELD_TIME ), - DEFINE_FIELD( m_bSuppressSound, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flStartupTime, FIELD_TIME ), - - DEFINE_FIELD( m_cullBoxMins, FIELD_VECTOR ), - DEFINE_FIELD( m_cullBoxMaxs, FIELD_VECTOR ), - - DEFINE_UTLVECTOR( m_hEntitiesPushedByWash, FIELD_EMBEDDED ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate), - DEFINE_INPUTFUNC( FIELD_VOID, "GunOn", InputGunOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "GunOff", InputGunOff ), - DEFINE_INPUTFUNC( FIELD_VOID, "MissileOn", InputMissileOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "MissileOff", InputMissileOff ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableRotorWash", InputEnableRotorWash ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableRotorWash", InputDisableRotorWash ), - DEFINE_INPUTFUNC( FIELD_VOID, "MoveTopSpeed", InputMoveTopSpeed ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "MoveSpecifiedSpeed", InputMoveSpecifiedSpeed ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetAngles", InputSetAngles ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableRotorSound", InputEnableRotorSound ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableRotorSound", InputDisableRotorSound ), - DEFINE_INPUTFUNC( FIELD_VOID, "Kill", InputKill ), - -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CBaseHelicopter, DT_BaseHelicopter ) - SendPropTime( SENDINFO( m_flStartupTime ) ), -END_SEND_TABLE() - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseHelicopter::CBaseHelicopter( void ) -{ - m_cullBoxMins = vec3_origin; - m_cullBoxMaxs = vec3_origin; - - m_hRotorWash = NULL; -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -// Notes : Have your derived Helicopter's Spawn() function call this one FIRST -//------------------------------------------------------------------------------ -void CBaseHelicopter::Precache( void ) -{ -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -// Notes : Have your derived Helicopter's Spawn() function call this one FIRST -//------------------------------------------------------------------------------ -void CBaseHelicopter::Spawn( void ) -{ - Precache( ); - - SetSolid( SOLID_BBOX ); - SetMoveType( MOVETYPE_STEP ); - AddFlag( FL_FLY ); - SetState( NPC_STATE_IDLE ); - - m_lifeState = LIFE_ALIVE; - - // motor - //****** - // All of this stuff is specific to the individual type of aircraft. Handle it yourself. - //****** - // m_iAmmoType = g_pGameRules->GetAmmoDef()->Index("AR2"); - // SetModel( "models/attack_helicopter.mdl" ); - // UTIL_SetSize( this, Vector( -32, -32, -64 ), Vector( 32, 32, 0 ) ); - // UTIL_SetOrigin( this, GetLocalOrigin() ); - // m_iHealth = 100; - // m_flFieldOfView = -0.707; // 270 degrees - // InitBoneControllers(); - // m_iRockets = 10; - // Get the rotor sound started up. - - // This base class assumes the helicopter has no guns or missiles. - // Set the appropriate flags in your derived class' Spawn() function. - m_fHelicopterFlags &= ~BITS_HELICOPTER_MISSILE_ON; - m_fHelicopterFlags &= ~BITS_HELICOPTER_GUN_ON; - - m_pRotorSound = NULL; - m_pRotorBlast = NULL; - - SetCycle( 0 ); - ResetSequenceInfo(); - - AddFlag( FL_NPC ); - - m_flMaxSpeed = BASECHOPPER_MAX_SPEED; - m_flMaxSpeedFiring = BASECHOPPER_MAX_FIRING_SPEED; - m_takedamage = DAMAGE_AIM; - - // Don't start up if the level designer has asked the - // helicopter to start disabled. - if ( !(m_spawnflags & SF_AWAITINPUT) ) - { - Startup(); - SetNextThink( gpGlobals->curtime + 1.0f ); - } - else - { - m_flStartupTime = FLT_MAX; - } - - InitPathingData( 0, BASECHOPPER_MIN_CHASE_DIST_DIFF, BASECHOPPER_AVOID_DIST ); - - // Setup collision hull - ExpandBBox( m_cullBoxMins, m_cullBoxMaxs ); - CollisionProp()->SetSurroundingBoundsType( USE_SPECIFIED_BOUNDS, &m_cullBoxMins, &m_cullBoxMaxs ); - AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST ); - m_flRandomOffsetTime = -1.0f; - m_vecRandomOffset.Init( 0, 0, 0 ); -} - - -//------------------------------------------------------------------------------ -// Cleanup -//------------------------------------------------------------------------------ -void CBaseHelicopter::UpdateOnRemove() -{ - StopRotorWash(); - BaseClass::UpdateOnRemove(); -} - - -//------------------------------------------------------------------------------ -// Gets the max speed of the helicopter -//------------------------------------------------------------------------------ -float CBaseHelicopter::GetMaxSpeed() -{ - // If our last path_track has specified a speed, use that instead of ours - if ( GetPathMaxSpeed() ) - return GetPathMaxSpeed(); - - return m_flMaxSpeed; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CBaseHelicopter::GetMaxSpeedFiring() -{ - // If our last path_track has specified a speed, use that instead of ours - if ( GetPathMaxSpeed() ) - return GetPathMaxSpeed(); - - return m_flMaxSpeedFiring; -} - - -//------------------------------------------------------------------------------ -// Enemy methods -//------------------------------------------------------------------------------ -bool CBaseHelicopter::GetTrackPatherTarget( Vector *pPos ) -{ - if ( GetEnemy() ) - { - *pPos = GetEnemy()->BodyTarget( GetAbsOrigin(), false ); - return true; - } - - return false; -} - -CBaseEntity *CBaseHelicopter::GetTrackPatherTargetEnt() -{ - return GetEnemy(); -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -bool CBaseHelicopter::FireGun( void ) -{ - return true; -} - - -//------------------------------------------------------------------------------ -// Purpose : The main think function for the helicopters -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBaseHelicopter::HelicopterThink( void ) -{ - CheckPVSCondition(); - - SetNextThink( gpGlobals->curtime + HELICOPTER_THINK_INTERVAL ); - - // Don't keep this around for more than one frame. - ClearCondition( COND_ENEMY_DEAD ); - - // Animate and dispatch animation events. - StudioFrameAdvance( ); - DispatchAnimEvents( this ); - - PrescheduleThink(); - - if ( IsMarkedForDeletion() ) - return; - - ShowDamage( ); - - // ----------------------------------------------- - // If AI is disabled, kill any motion and return - // ----------------------------------------------- - if (CAI_BaseNPC::m_nDebugBits & bits_debugDisableAI) - { - SetAbsVelocity( vec3_origin ); - SetLocalAngularVelocity( vec3_angle ); - SetNextThink( gpGlobals->curtime + HELICOPTER_THINK_INTERVAL ); - return; - } - - Hunt(); - - // Finally, forget dead enemies, or ones we've been told to ignore. - if( GetEnemy() != NULL && (!GetEnemy()->IsAlive() || GetEnemy()->GetFlags() & FL_NOTARGET || IRelationType( GetEnemy() ) == D_NU ) ) - { - SetEnemy( NULL ); - } - - HelicopterPostThink(); -} - -//----------------------------------------------------------------------------- -// Rotor wash think -//----------------------------------------------------------------------------- -void CBaseHelicopter::RotorWashThink( void ) -{ - if ( m_lifeState == LIFE_ALIVE || m_lifeState == LIFE_DYING ) - { - DrawRotorWash( BASECHOPPER_WASH_ALTITUDE, GetAbsOrigin() ); - SetContextThink( &CBaseHelicopter::RotorWashThink, gpGlobals->curtime + HELICOPTER_ROTORWASH_THINK_INTERVAL, s_pRotorWashThinkContext ); - } - else - { - SetContextThink( NULL, gpGlobals->curtime, s_pRotorWashThinkContext ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseHelicopter::DrawRotorWash( float flAltitude, const Vector &vecRotorOrigin ) -{ - // Shake any ropes nearby - if ( random->RandomInt( 0, 2 ) == 0 ) - { - CRopeKeyframe::ShakeRopes( GetAbsOrigin(), flAltitude, 128 ); - } - - if ( m_spawnflags & SF_NOROTORWASH ) - return; - - DoRotorPhysicsPush( vecRotorOrigin, flAltitude ); - - if ( m_flRotorWashEntitySearchTime > gpGlobals->curtime ) - return; - - // Only push every half second - m_flRotorWashEntitySearchTime = gpGlobals->curtime + 0.5f; -} - - -//----------------------------------------------------------------------------- -// Purpose: Push an airboat in our wash -//----------------------------------------------------------------------------- -#define MAX_AIRBOAT_ROLL_ANGLE 20.0f -#define MAX_AIRBOAT_ROLL_COSANGLE 0.866f -#define MAX_AIRBOAT_ROLL_COSANGLE_X2 0.5f - -void CBaseHelicopter::DoWashPushOnAirboat( CBaseEntity *pAirboat, - const Vector &vecWashToAirboat, float flWashAmount ) -{ - // For the airboat, simply produce a small roll and a push outwards. - // But don't produce a roll if we're too rolled in that direction already. - - // Get the actual up direction vector - Vector vecUp; - pAirboat->GetVectors( NULL, NULL, &vecUp ); - if ( vecUp.z < MAX_AIRBOAT_ROLL_COSANGLE ) - return; - - // Compute roll direction so that we get pushed down on the side where the rotor wash is. - Vector vecRollNormal; - CrossProduct( vecWashToAirboat, Vector( 0, 0, 1 ), vecRollNormal ); - - // Project it into the plane of the roll normal - VectorMA( vecUp, -DotProduct( vecUp, vecRollNormal ), vecRollNormal, vecUp ); - VectorNormalize( vecUp ); - - // Compute a vector which is the max direction we can roll given the roll constraint - Vector vecExtremeUp; - VMatrix rot; - MatrixBuildRotationAboutAxis( rot, vecRollNormal, MAX_AIRBOAT_ROLL_ANGLE ); - MatrixGetColumn( rot, 2, &vecExtremeUp ); - - // Find the angle between how vertical we are and how vertical we should be - float flCosDelta = DotProduct( vecExtremeUp, vecUp ); - float flDelta = acos(flCosDelta) * 180.0f / M_PI; - flDelta = clamp( flDelta, 0.0f, MAX_AIRBOAT_ROLL_ANGLE ); - flDelta = SimpleSplineRemapVal( flDelta, 0.0f, MAX_AIRBOAT_ROLL_ANGLE, 0.0f, 1.0f ); - - float flForce = 12.0f * flWashAmount * flDelta; - - Vector vecWashOrigin; - Vector vecForce; - VectorMultiply( Vector( 0, 0, -1 ), flForce, vecForce ); - VectorMA( pAirboat->GetAbsOrigin(), -200.0f, vecWashToAirboat, vecWashOrigin ); - - pAirboat->VPhysicsTakeDamage( CTakeDamageInfo( this, this, vecForce, vecWashOrigin, flWashAmount, DMG_BLAST ) ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Push a physics object in our wash. Return false if it's now out of our wash -//----------------------------------------------------------------------------- -bool CBaseHelicopter::DoWashPush( washentity_t *pWash, const Vector &vecWashOrigin ) -{ - if ( !pWash || !pWash->hEntity.Get() ) - return false; - - // Make sure the entity is still within our wash's radius - CBaseEntity *pEntity = pWash->hEntity; - - // This can happen because we can dynamically turn this flag on and off - if ( pEntity->IsEFlagSet( EFL_NO_ROTORWASH_PUSH )) - return false; - - Vector vecSpot = pEntity->BodyTarget( vecWashOrigin ); - Vector vecToSpot = ( vecSpot - vecWashOrigin ); - vecToSpot.z = 0; - float flDist = VectorNormalize( vecToSpot ); - if ( flDist > BASECHOPPER_WASH_RADIUS ) - return false; - - IRotorWashShooter *pShooter = GetRotorWashShooter( pEntity ); - IPhysicsObject *pPhysObject; - - - float flPushTime = (gpGlobals->curtime - pWash->flWashStartTime); - flPushTime = clamp( flPushTime, 0, BASECHOPPER_WASH_RAMP_TIME ); - float flWashAmount = RemapVal( flPushTime, 0, BASECHOPPER_WASH_RAMP_TIME, BASECHOPPER_WASH_PUSH_MIN, BASECHOPPER_WASH_PUSH_MAX ); - - if ( pShooter ) - { - Vector vecForce = (0.015f / 0.1f) * flWashAmount * vecToSpot * phys_pushscale.GetFloat(); - pEntity = pShooter->DoWashPush( pWash->flWashStartTime, vecForce ); - if ( !pEntity ) - return true; - - washentity_t Wash; - Wash.hEntity = pEntity; - Wash.flWashStartTime = pWash->flWashStartTime; - int i = m_hEntitiesPushedByWash.AddToTail( Wash ); - pWash = &m_hEntitiesPushedByWash[i]; - - pPhysObject = pEntity->VPhysicsGetObject(); - if ( !pPhysObject ) - return true; - } - else - { - // Airboat gets special treatment - if ( FClassnameIs( pEntity, "prop_vehicle_airboat" ) ) - { - DoWashPushOnAirboat( pEntity, vecToSpot, flWashAmount ); - return true; - } - - pPhysObject = pEntity->VPhysicsGetObject(); - if ( !pPhysObject ) - return false; - } - - // Push it away from the center of the wash - float flMass = pPhysObject->GetMass(); - - // This used to be mass independent, which is a bad idea because it blows 200kg engine blocks - // as much as it blows cardboard and soda cans. Make this force mass-independent, but clamp at - // 30kg. - flMass = MIN( flMass, 30.0f ); - - Vector vecForce = (0.015f / 0.1f) * flWashAmount * flMass * vecToSpot * phys_pushscale.GetFloat(); - pEntity->VPhysicsTakeDamage( CTakeDamageInfo( this, this, vecForce, vecWashOrigin, flWashAmount, DMG_BLAST ) ); - - // Debug - if ( g_debug_basehelicopter.GetInt() == BASECHOPPER_DEBUG_WASH ) - { - NDebugOverlay::Cross3D( pEntity->GetAbsOrigin(), -Vector(4,4,4), Vector(4,4,4), 255, 0, 0, true, 0.1f ); - NDebugOverlay::Line( pEntity->GetAbsOrigin(), pEntity->GetAbsOrigin() + vecForce, 255, 255, 0, true, 0.1f ); - - IPhysicsObject *pPhysObject = pEntity->VPhysicsGetObject(); - Msg("Pushed %s (index %d) (mass %f) with force %f (min %.2f max %.2f) at time %.2f\n", - pEntity->GetClassname(), pEntity->entindex(), pPhysObject->GetMass(), flWashAmount, - BASECHOPPER_WASH_PUSH_MIN * flMass, BASECHOPPER_WASH_PUSH_MAX * flMass, gpGlobals->curtime ); - } - - // If we've pushed this thing for some time, remove it to give us a chance to find lighter things nearby - if ( flPushTime > 2.0 ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseHelicopter::DoRotorPhysicsPush( const Vector &vecRotorOrigin, float flAltitude ) -{ - CBaseEntity *pEntity = NULL; - trace_t tr; - - // First, trace down and find out where the was is hitting the ground - UTIL_TraceLine( vecRotorOrigin, vecRotorOrigin+Vector(0,0,-flAltitude), (MASK_SOLID_BRUSHONLY|CONTENTS_WATER), NULL, COLLISION_GROUP_NONE, &tr ); - // Always raise the physics origin a bit - Vector vecPhysicsOrigin = tr.endpos + Vector(0,0,64); - - // Debug - if ( g_debug_basehelicopter.GetInt() == BASECHOPPER_DEBUG_WASH ) - { - NDebugOverlay::Cross3D( vecPhysicsOrigin, -Vector(16,16,16), Vector(16,16,16), 0, 255, 255, true, 0.1f ); - } - - // Push entities that we've pushed before, and are still within range - // Walk backwards because they may be removed if they're now out of range - int iCount = m_hEntitiesPushedByWash.Count(); - bool bWasPushingObjects = (iCount > 0); - for ( int i = (iCount-1); i >= 0; i-- ) - { - if ( !DoWashPush( &(m_hEntitiesPushedByWash[i]), vecPhysicsOrigin ) ) - { - // Out of range now, so remove - m_hEntitiesPushedByWash.Remove(i); - } - } - - if ( m_flRotorWashEntitySearchTime > gpGlobals->curtime ) - return; - - // Any spare slots? - iCount = m_hEntitiesPushedByWash.Count(); - if ( iCount >= BASECHOPPER_WASH_MAX_OBJECTS ) - return; - - // Find the lightest physics entity below us and add it to our list to push around - CBaseEntity *pLightestEntity = NULL; - float flLightestMass = 9999; - while ((pEntity = gEntList.FindEntityInSphere(pEntity, vecPhysicsOrigin, BASECHOPPER_WASH_RADIUS )) != NULL) - { - IRotorWashShooter *pShooter = GetRotorWashShooter( pEntity ); - - if ( pEntity->IsEFlagSet( EFL_NO_ROTORWASH_PUSH )) - continue; - - if ( pShooter || pEntity->GetMoveType() == MOVETYPE_VPHYSICS || (pEntity->VPhysicsGetObject() && !pEntity->IsPlayer()) ) - { - // Make sure it's not already in our wash - bool bAlreadyPushing = false; - for ( int i = 0; i < iCount; i++ ) - { - if ( m_hEntitiesPushedByWash[i].hEntity == pEntity ) - { - bAlreadyPushing = true; - break; - } - } - if ( bAlreadyPushing ) - continue; - - float flMass = FLT_MAX; - if ( pShooter ) - { - flMass = 1.0f; - } - else - { - // Don't try to push anything too big - IPhysicsObject *pPhysObject = pEntity->VPhysicsGetObject(); - if ( pPhysObject ) - { - flMass = pPhysObject->GetMass(); - if ( flMass > BASECHOPPER_WASH_MAX_MASS ) - continue; - } - } - - // Ignore anything bigger than the one we've already found - if ( flMass > flLightestMass ) - continue; - - Vector vecSpot = pEntity->BodyTarget( vecPhysicsOrigin ); - - // Don't push things too far below our starting point (helps reduce through-roof cases w/o doing a trace) - if ( fabs( vecSpot.z - vecPhysicsOrigin.z ) > 96 ) - continue; - - Vector vecToSpot = ( vecSpot - vecPhysicsOrigin ); - vecToSpot.z = 0; - float flDist = VectorNormalize( vecToSpot ); - if ( flDist > BASECHOPPER_WASH_RADIUS ) - continue; - - - // Try to cast to the helicopter; if we can't, then we can't be hit. - if ( pEntity->GetServerVehicle() ) - { - UTIL_TraceLine( vecSpot, vecPhysicsOrigin, MASK_SOLID_BRUSHONLY, pEntity, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction != 1.0f ) - continue; - } - - flLightestMass = flMass; - pLightestEntity = pEntity; - - washentity_t Wash; - Wash.hEntity = pLightestEntity; - Wash.flWashStartTime = gpGlobals->curtime; - m_hEntitiesPushedByWash.AddToTail( Wash ); - - // Can we fit more after adding this one? No? Then we are done. - iCount = m_hEntitiesPushedByWash.Count(); - if ( iCount >= BASECHOPPER_WASH_MAX_OBJECTS ) - break; - } - } - - // Handle sound. - // If we just started pushing objects, ramp the blast sound up. - if ( !bWasPushingObjects && m_hEntitiesPushedByWash.Count() ) - { - if ( m_pRotorBlast ) - { - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundChangeVolume( m_pRotorBlast, 1.0, 1.0 ); - } - } - else if ( bWasPushingObjects && m_hEntitiesPushedByWash.Count() == 0 ) - { - if ( m_pRotorBlast ) - { - // We just stopped pushing objects, so fade the blast sound out. - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundChangeVolume( m_pRotorBlast, 0, 1.0 ); - } - } -} - - -//------------------------------------------------------------------------------ -// Updates the enemy -//------------------------------------------------------------------------------ -float CBaseHelicopter::EnemySearchDistance( ) -{ - return 4092; -} - - -//------------------------------------------------------------------------------ -// Updates the enemy -//------------------------------------------------------------------------------ -void CBaseHelicopter::UpdateEnemy() -{ - if( HasCondition( COND_ENEMY_DEAD ) ) - { - SetEnemy( NULL ); - } - - // Look for my best enemy. If I change enemies, - // be sure and change my prevseen/lastseen timers. - if( m_lifeState == LIFE_ALIVE ) - { - GetSenses()->Look( (int)EnemySearchDistance() ); - - GetEnemies()->RefreshMemories(); - ChooseEnemy(); - - if( HasEnemy() ) - { - CBaseEntity *pEnemy = GetEnemy(); - GatherEnemyConditions( pEnemy ); - if ( FVisible( pEnemy ) ) - { - if (m_flLastSeen < gpGlobals->curtime - 2) - { - m_flPrevSeen = gpGlobals->curtime; - } - - m_flLastSeen = gpGlobals->curtime; - m_vecTargetPosition = pEnemy->WorldSpaceCenter(); - } - } - else - { - // look at where we're going instead - m_vecTargetPosition = GetDesiredPosition(); - } - } - else - { - // If we're dead or dying, forget our enemy and don't look for new ones(sjb) - SetEnemy( NULL ); - } - -} - -//------------------------------------------------------------------------------ -// Purpose : Override the desired position if your derived helicopter is doing something special -//------------------------------------------------------------------------------ -void CBaseHelicopter::UpdateDesiredPosition( void ) -{ -} - -//------------------------------------------------------------------------------ -// Updates the facing direction -//------------------------------------------------------------------------------ -void CBaseHelicopter::UpdateFacingDirection() -{ - if ( 1 ) - { - Vector targetDir = m_vecTargetPosition - GetAbsOrigin(); - Vector desiredDir = GetDesiredPosition() - GetAbsOrigin(); - - VectorNormalize( targetDir ); - VectorNormalize( desiredDir ); - - if ( !IsCrashing() && m_flLastSeen + 5 > gpGlobals->curtime ) //&& DotProduct( targetDir, desiredDir) > 0.25) - { - // If we've seen the target recently, face the target. - //Msg( "Facing Target \n" ); - m_vecDesiredFaceDir = targetDir; - } - else - { - // Face our desired position. - // Msg( "Facing Position\n" ); - m_vecDesiredFaceDir = desiredDir; - } - } - else - { - // Face the way the path corner tells us to. - //Msg( "Facing my path corner\n" ); - m_vecDesiredFaceDir = GetGoalOrientation(); - } - -} - - -//------------------------------------------------------------------------------ -// Fire weapons -//------------------------------------------------------------------------------ -void CBaseHelicopter::FireWeapons() -{ - // ALERT( at_console, "%.0f %.0f %.0f\n", gpGlobals->curtime, m_flLastSeen, m_flPrevSeen ); - if (m_fHelicopterFlags & BITS_HELICOPTER_GUN_ON) - { - //if ( (m_flLastSeen + 1 > gpGlobals->curtime) && (m_flPrevSeen + 2 < gpGlobals->curtime) ) - { - if (FireGun( )) - { - // slow down if we're firing - if (m_flGoalSpeed > GetMaxSpeedFiring() ) - { - m_flGoalSpeed = GetMaxSpeedFiring(); - } - } - } - } - - if (m_fHelicopterFlags & BITS_HELICOPTER_MISSILE_ON) - { - AimRocketGun(); - } -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBaseHelicopter::Hunt( void ) -{ - UpdateEnemy(); - - UpdateTrackNavigation( ); - - UpdateDesiredPosition(); - - UpdateFacingDirection(); - - Flight(); - - UpdatePlayerDopplerShift( ); - - FireWeapons(); -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBaseHelicopter::UpdatePlayerDopplerShift( ) -{ - // ----------------------------- - // make rotor, engine sounds - // ----------------------------- - if (m_iSoundState == 0) - { - // Sound startup. - InitializeRotorSound(); - } - else - { - CBaseEntity *pPlayer = NULL; - - // UNDONE: this needs to send different sounds to every player for multiplayer. - // FIXME: this isn't the correct way to find a player!!! - pPlayer = gEntList.FindEntityByName( NULL, "!player" ); - if (pPlayer) - { - Vector dir; - VectorSubtract( pPlayer->GetAbsOrigin(), GetAbsOrigin(), dir ); - VectorNormalize(dir); - -#if 1 - float velReceiver = DotProduct( pPlayer->GetAbsVelocity(), dir ); - float velTransmitter = -DotProduct( GetAbsVelocity(), dir ); - // speed of sound == 13049in/s - int iPitch = (int)(100 * ((1 - velReceiver / 13049) / (1 + velTransmitter / 13049))); -#else - // This is a bogus doppler shift, but I like it better - float relV = DotProduct( GetAbsVelocity() - pPlayer->GetAbsVelocity(), dir ); - int iPitch = (int)(100 + relV / 50.0); -#endif - - // clamp pitch shifts - if (iPitch > 250) - { - iPitch = 250; - } - if (iPitch < 50) - { - iPitch = 50; - } - - UpdateRotorSoundPitch( iPitch ); - // Msg( "Pitch:%d\n", iPitch ); - } - else - { - Msg( "Chopper didn't find a player!\n" ); - } - } -} - - -//----------------------------------------------------------------------------- -// Computes the actual position to fly to -//----------------------------------------------------------------------------- -void CBaseHelicopter::ComputeActualTargetPosition( float flSpeed, float flTime, float flPerpDist, Vector *pDest, bool bApplyNoise ) -{ - // This is used to make the helicopter drift around a bit. - if ( bApplyNoise && m_flRandomOffsetTime <= gpGlobals->curtime ) - { - m_vecRandomOffset.Random( -25.0f, 25.0f ); - m_flRandomOffsetTime = gpGlobals->curtime + 1.0f; - } - - if ( IsLeading() && GetEnemy() && IsOnPathTrack() ) - { - ComputePointAlongCurrentPath( flSpeed * flTime, flPerpDist, pDest ); - *pDest += m_vecRandomOffset; - return; - } - - *pDest = GetDesiredPosition() - GetAbsOrigin(); - float flDistToDesired = pDest->Length(); - if (flDistToDesired > flSpeed * flTime) - { - float scale = flSpeed * flTime / flDistToDesired; - *pDest *= scale; - } - else if ( IsOnPathTrack() ) - { - // Blend in a fake destination point based on the dest velocity - Vector vecDestVelocity; - ComputeNormalizedDestVelocity( &vecDestVelocity ); - vecDestVelocity *= flSpeed; - - float flBlendFactor = 1.0f - flDistToDesired / (flSpeed * flTime); - VectorMA( *pDest, flTime * flBlendFactor, vecDestVelocity, *pDest ); - } - - *pDest += GetAbsOrigin(); - - if ( bApplyNoise ) - { - // ComputePointAlongCurrentPath( flSpeed * flTime, flPerpDist, pDest ); - *pDest += m_vecRandomOffset; - } -} - - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CBaseHelicopter::Flight( void ) -{ - if( GetFlags() & FL_ONGROUND ) - { - //This would be really bad. - SetGroundEntity( NULL ); - } - - // Generic speed up - if (m_flGoalSpeed < GetMaxSpeed()) - { - m_flGoalSpeed += GetAcceleration(); - } - - //NDebugOverlay::Line(GetAbsOrigin(), m_vecDesiredPosition, 0,0,255, true, 0.1); - - // tilt model 5 degrees (why?! sjb) - QAngle vecAdj = QAngle( 5.0, 0, 0 ); - - // estimate where I'll be facing in one seconds - Vector forward, right, up; - AngleVectors( GetLocalAngles() + GetLocalAngularVelocity() * 2 + vecAdj, &forward, &right, &up ); - - // Vector vecEst1 = GetLocalOrigin() + GetAbsVelocity() + up * m_flForce - Vector( 0, 0, 384 ); - // float flSide = DotProduct( m_vecDesiredPosition - vecEst1, right ); - QAngle angVel = GetLocalAngularVelocity(); - float flSide = DotProduct( m_vecDesiredFaceDir, right ); - if (flSide < 0) - { - if (angVel.y < 60) - { - angVel.y += 8; - } - } - else - { - if (angVel.y > -60) - { - angVel.y -= 8; - } - } - - angVel.y *= ( 0.98 ); // why?! (sjb) - - // estimate where I'll be in two seconds - AngleVectors( GetLocalAngles() + angVel * 1 + vecAdj, NULL, NULL, &up ); - Vector vecEst = GetAbsOrigin() + GetAbsVelocity() * 2.0 + up * m_flForce * 20 - Vector( 0, 0, 384 * 2 ); - - // add immediate force - AngleVectors( GetLocalAngles() + vecAdj, &forward, &right, &up ); - - Vector vecImpulse( 0, 0, 0 ); - vecImpulse.x += up.x * m_flForce; - vecImpulse.y += up.y * m_flForce; - vecImpulse.z += up.z * m_flForce; - - // add gravity - vecImpulse.z -= 38.4; // 32ft/sec - ApplyAbsVelocityImpulse( vecImpulse ); - - float flSpeed = GetAbsVelocity().Length(); - float flDir = DotProduct( Vector( forward.x, forward.y, 0 ), Vector( GetAbsVelocity().x, GetAbsVelocity().y, 0 ) ); - if (flDir < 0) - { - flSpeed = -flSpeed; - } - - float flDist = DotProduct( GetDesiredPosition() - vecEst, forward ); - - // float flSlip = DotProduct( GetAbsVelocity(), right ); - float flSlip = -DotProduct( GetDesiredPosition() - vecEst, right ); - - // fly sideways - if (flSlip > 0) - { - if (GetLocalAngles().z > -30 && angVel.z > -15) - angVel.z -= 4; - else - angVel.z += 2; - } - else - { - if (GetLocalAngles().z < 30 && angVel.z < 15) - angVel.z += 4; - else - angVel.z -= 2; - } - - // These functions contain code Ken wrote that used to be right here as part of the flight model, - // but we want different helicopter vehicles to have different drag characteristics, so I made - // them virtual functions (sjb) - ApplySidewaysDrag( right ); - ApplyGeneralDrag(); - - // apply power to stay correct height - // FIXME: these need to be per class variables -#define MAX_FORCE 80 -#define FORCE_POSDELTA 12 -#define FORCE_NEGDELTA 8 - - if (m_flForce < MAX_FORCE && vecEst.z < GetDesiredPosition().z) - { - m_flForce += FORCE_POSDELTA; - } - else if (m_flForce > 30) - { - if (vecEst.z > GetDesiredPosition().z) - m_flForce -= FORCE_NEGDELTA; - } - - // pitch forward or back to get to target - //----------------------------------------- - // Pitch is reversed since Half-Life! (sjb) - //----------------------------------------- - if (flDist > 0 && flSpeed < m_flGoalSpeed /* && flSpeed < flDist */ && GetLocalAngles().x + angVel.x < 40) - { - // ALERT( at_console, "F " ); - // lean forward - angVel.x += 12.0; - } - else if (flDist < 0 && flSpeed > -50 && GetLocalAngles().x + angVel.x > -20) - { - // ALERT( at_console, "B " ); - // lean backward - angVel.x -= 12.0; - } - else if (GetLocalAngles().x + angVel.x < 0) - { - // ALERT( at_console, "f " ); - angVel.x += 4.0; - } - else if (GetLocalAngles().x + angVel.x > 0) - { - // ALERT( at_console, "b " ); - angVel.x -= 4.0; - } - - SetLocalAngularVelocity( angVel ); - // ALERT( at_console, "%.0f %.0f : %.0f %.0f : %.0f %.0f : %.0f\n", GetAbsOrigin().x, GetAbsVelocity().x, flDist, flSpeed, GetLocalAngles().x, m_vecAngVelocity.x, m_flForce ); - // ALERT( at_console, "%.0f %.0f : %.0f %0.f : %.0f\n", GetAbsOrigin().z, GetAbsVelocity().z, vecEst.z, m_vecDesiredPosition.z, m_flForce ); -} - - -//------------------------------------------------------------------------------ -// Updates the rotor wash volume -//------------------------------------------------------------------------------ -void CBaseHelicopter::UpdateRotorWashVolume() -{ - if ( !m_pRotorSound ) - return; - - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - float flVolDelta = GetRotorVolume() - controller.SoundGetVolume( m_pRotorSound ); - if ( flVolDelta ) - { - // We can change from 0 to 1 in 3 seconds. - // Figure out how many seconds flVolDelta will take. - float flRampTime = fabs( flVolDelta ) * 3.0f; - controller.SoundChangeVolume( m_pRotorSound, GetRotorVolume(), flRampTime ); - } -} - - -//------------------------------------------------------------------------------ -// For scripted times where it *has* to shoot -//------------------------------------------------------------------------------ -float CBaseHelicopter::GetRotorVolume( void ) -{ - return m_bSuppressSound ? 0.0f : 1.0f; -} - - -//----------------------------------------------------------------------------- -// Rotor sound -//----------------------------------------------------------------------------- -void CBaseHelicopter::InputEnableRotorSound( inputdata_t &inputdata ) -{ - m_bSuppressSound = false; -} - -void CBaseHelicopter::InputDisableRotorSound( inputdata_t &inputdata ) -{ - m_bSuppressSound = true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Marks the entity for deletion -//----------------------------------------------------------------------------- -void CBaseHelicopter::InputKill( inputdata_t &inputdata ) -{ - StopRotorWash(); - - m_bSuppressSound = true; - SetContextThink( &CBaseHelicopter::DelayedKillThink, gpGlobals->curtime + 3.0f, s_pDelayedKillThinkContext ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseHelicopter::StopRotorWash( void ) -{ - if ( m_hRotorWash ) - { - UTIL_Remove( m_hRotorWash ); - m_hRotorWash = NULL; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Marks the entity for deletion -//----------------------------------------------------------------------------- -void CBaseHelicopter::DelayedKillThink( ) -{ - // tell owner ( if any ) that we're dead.This is mostly for NPCMaker functionality. - CBaseEntity *pOwner = GetOwnerEntity(); - if ( pOwner ) - { - pOwner->DeathNotice( this ); - SetOwnerEntity( NULL ); - } - - UTIL_Remove( this ); -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBaseHelicopter::InitializeRotorSound( void ) -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - - if ( m_pRotorSound ) - { - // Get the rotor sound started up. - controller.Play( m_pRotorSound, 0.0, 100 ); - UpdateRotorWashVolume(); - } - - if ( m_pRotorBlast ) - { - // Start the blast sound and then immediately drop it to 0 (starting it at 0 wouldn't start it) - controller.Play( m_pRotorBlast, 1.0, 100 ); - controller.SoundChangeVolume(m_pRotorBlast, 0, 0.0); - } - - m_iSoundState = SND_CHANGE_PITCH; // hack for going through level transitions -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBaseHelicopter::UpdateRotorSoundPitch( int iPitch ) -{ - if (m_pRotorSound) - { - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundChangePitch( m_pRotorSound, iPitch, 0.1 ); - UpdateRotorWashVolume(); - } -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBaseHelicopter::FlyTouch( CBaseEntity *pOther ) -{ - // bounce if we hit something solid - if ( pOther->GetSolid() == SOLID_BSP) - { -// trace_t tr; -// tr = CBaseEntity::GetTouchTrace(); - - // UNDONE, do a real bounce - // FIXME: This causes bad problems, so we just ignore it right now - //ApplyAbsVelocityImpulse( tr.plane.normal * (GetAbsVelocity().Length() + 200) ); - } -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBaseHelicopter::CrashTouch( CBaseEntity *pOther ) -{ - // only crash if we hit something solid - if ( pOther->GetSolid() == SOLID_BSP) - { - SetTouch( NULL ); - SetNextThink( gpGlobals->curtime ); - } -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBaseHelicopter::DyingThink( void ) -{ - StudioFrameAdvance( ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - SetLocalAngularVelocity( GetLocalAngularVelocity() * 1.02 ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Override base class to add display of fly direction -// Input : -// Output : -//----------------------------------------------------------------------------- -void CBaseHelicopter::DrawDebugGeometryOverlays(void) -{ - if (m_pfnThink!= NULL) - { - // ------------------------------ - // Draw route if requested - // ------------------------------ - if (m_debugOverlays & OVERLAY_NPC_ROUTE_BIT) - { - NDebugOverlay::Line(GetAbsOrigin(), GetDesiredPosition(), 0,0,255, true, 0); - } - } - BaseClass::DrawDebugGeometryOverlays(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CBaseHelicopter::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - // Take no damage from trace attacks unless it's blast damage. RadiusDamage() sometimes calls - // TraceAttack() as a means for delivering blast damage. Usually when the explosive penetrates - // the target. (RPG missiles do this sometimes). - if( info.GetDamageType() & (DMG_BLAST|DMG_AIRBOAT) ) - { - BaseClass::TraceAttack( info, vecDir, ptr ); - } -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBaseHelicopter::NullThink( void ) -{ - StudioFrameAdvance( ); - SetNextThink( gpGlobals->curtime + 0.5f ); -} - - -void CBaseHelicopter::Startup( void ) -{ - StopRotorWash(); - - if ( !( m_spawnflags & SF_NOROTORWASH ) ) - { - m_hRotorWash = CreateRotorWashEmitter( GetAbsOrigin(), GetAbsAngles(), this, BASECHOPPER_WASH_ALTITUDE ); - } - - // Fade in the blades - m_flStartupTime = gpGlobals->curtime; - - m_flGoalSpeed = m_flInitialSpeed; - SetThink( &CBaseHelicopter::HelicopterThink ); - SetTouch( &CBaseHelicopter::FlyTouch ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - m_flRotorWashEntitySearchTime = gpGlobals->curtime; - SetContextThink( &CBaseHelicopter::RotorWashThink, gpGlobals->curtime, s_pRotorWashThinkContext ); -} - -void CBaseHelicopter::StopLoopingSounds() -{ - // Kill the rotor sounds - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundDestroy( m_pRotorSound ); - controller.SoundDestroy( m_pRotorBlast ); - m_pRotorSound = NULL; - m_pRotorBlast = NULL; - - BaseClass::StopLoopingSounds(); -} - -void CBaseHelicopter::Event_Killed( const CTakeDamageInfo &info ) -{ - m_lifeState = LIFE_DYING; - - SetMoveType( MOVETYPE_FLYGRAVITY ); - SetGravity( UTIL_ScaleForGravity( 240 ) ); // use a lower gravity - - StopLoopingSounds(); - - UTIL_SetSize( this, Vector( -32, -32, -64), Vector( 32, 32, 0) ); - SetThink( &CBaseHelicopter::CallDyingThink ); - SetTouch( &CBaseHelicopter::CrashTouch ); - - SetNextThink( gpGlobals->curtime + 0.1f ); - m_iHealth = 0; - m_takedamage = DAMAGE_NO; - -/* - if (m_spawnflags & SF_NOWRECKAGE) - { - m_flNextRocket = gpGlobals->curtime + 4.0; - } - else - { - m_flNextRocket = gpGlobals->curtime + 15.0; - } -*/ - StopRotorWash(); - - m_OnDeath.FireOutput( info.GetAttacker(), this ); -} - - -void CBaseHelicopter::GibMonster( void ) -{ -} - - -//----------------------------------------------------------------------------- -// Purpose: Call Startup for a helicopter that's been flagged to start disabled -//----------------------------------------------------------------------------- -void CBaseHelicopter::InputActivate( inputdata_t &inputdata ) -{ - if( m_spawnflags & SF_AWAITINPUT ) - { - Startup(); - - // Now clear the spawnflag to protect from - // subsequent calls. - m_spawnflags &= ~SF_AWAITINPUT; - } -} - -//------------------------------------------------------------------------------ -// Purpose : Turn the gun on -//------------------------------------------------------------------------------ -void CBaseHelicopter::InputGunOn( inputdata_t &inputdata ) -{ - m_fHelicopterFlags |= BITS_HELICOPTER_GUN_ON; -} - -//----------------------------------------------------------------------------- -// Purpose: Turn the gun off -//----------------------------------------------------------------------------- -void CBaseHelicopter::InputGunOff( inputdata_t &inputdata ) -{ - m_fHelicopterFlags &= ~BITS_HELICOPTER_GUN_ON; -} - -//------------------------------------------------------------------------------ -// Purpose : Turn the missile on -//------------------------------------------------------------------------------ -void CBaseHelicopter::InputMissileOn( inputdata_t &inputdata ) -{ - m_fHelicopterFlags |= BITS_HELICOPTER_MISSILE_ON; -} - -//----------------------------------------------------------------------------- -// Purpose: Turn the missile off -//----------------------------------------------------------------------------- -void CBaseHelicopter::InputMissileOff( inputdata_t &inputdata ) -{ - m_fHelicopterFlags &= ~BITS_HELICOPTER_MISSILE_ON; -} - - -//----------------------------------------------------------------------------- -// Enable, disable rotor wash -//----------------------------------------------------------------------------- -void CBaseHelicopter::InputEnableRotorWash( inputdata_t &inputdata ) -{ - m_spawnflags &= ~SF_NOROTORWASH; -} - -void CBaseHelicopter::InputDisableRotorWash( inputdata_t &inputdata ) -{ - m_spawnflags |= SF_NOROTORWASH; -} - - -//----------------------------------------------------------------------------- -// Causes the helicopter to immediately accelerate to its desired velocity -//----------------------------------------------------------------------------- -void CBaseHelicopter::InputMoveTopSpeed( inputdata_t &inputdata ) -{ - Vector vecVelocity; - ComputeActualTargetPosition( GetMaxSpeed(), 1.0f, 0.0f, &vecVelocity, false ); - vecVelocity -= GetAbsOrigin(); - - float flLength = VectorNormalize( vecVelocity ); - if (flLength < 1e-3) - { - GetVectors( &vecVelocity, NULL, NULL ); - } - - vecVelocity *= GetMaxSpeed(); - SetAbsVelocity( vecVelocity ); -} - -//----------------------------------------------------------------------------- -// Cause helicopter to immediately accelerate to specified velocity -//----------------------------------------------------------------------------- -void CBaseHelicopter::InputMoveSpecifiedSpeed( inputdata_t &inputdata ) -{ - Vector vecVelocity; - ComputeActualTargetPosition( GetMaxSpeed(), 1.0f, 0.0f, &vecVelocity, false ); - vecVelocity -= GetAbsOrigin(); - - float flLength = VectorNormalize( vecVelocity ); - if (flLength < 1e-3) - { - GetVectors( &vecVelocity, NULL, NULL ); - } - - float flSpeed = inputdata.value.Float(); - - vecVelocity *= flSpeed; - SetAbsVelocity( vecVelocity ); -} - -//------------------------------------------------------------------------------ -// Input values -//------------------------------------------------------------------------------ -void CBaseHelicopter::InputSetAngles( inputdata_t &inputdata ) -{ - const char *pAngles = inputdata.value.String(); - - QAngle angles; - UTIL_StringToVector( angles.Base(), pAngles ); - SetAbsAngles( angles ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CBaseHelicopter::ApplySidewaysDrag( const Vector &vecRight ) -{ - Vector vecNewVelocity = GetAbsVelocity(); - vecNewVelocity.x *= 1.0 - fabs( vecRight.x ) * 0.05; - vecNewVelocity.y *= 1.0 - fabs( vecRight.y ) * 0.05; - vecNewVelocity.z *= 1.0 - fabs( vecRight.z ) * 0.05; - SetAbsVelocity( vecNewVelocity ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CBaseHelicopter::ApplyGeneralDrag( void ) -{ - Vector vecNewVelocity = GetAbsVelocity(); - vecNewVelocity *= 0.995; - SetAbsVelocity( vecNewVelocity ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CBaseHelicopter::ChooseEnemy( void ) -{ - // See if there's a new enemy. - CBaseEntity *pNewEnemy; - - pNewEnemy = BestEnemy(); - - if ( pNewEnemy != GetEnemy() ) - { - if ( pNewEnemy != NULL ) - { - // New enemy! Clear the timers and set conditions. - SetEnemy( pNewEnemy ); - m_flLastSeen = m_flPrevSeen = gpGlobals->curtime; - } - else - { - SetEnemy( NULL ); - SetState( NPC_STATE_ALERT ); - } - return true; - } - else - { - ClearCondition( COND_NEW_ENEMY ); - return false; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CBaseHelicopter::GatherEnemyConditions( CBaseEntity *pEnemy ) -{ - // ------------------- - // If enemy is dead - // ------------------- - if ( !pEnemy->IsAlive() ) - { - SetCondition( COND_ENEMY_DEAD ); - ClearCondition( COND_SEE_ENEMY ); - ClearCondition( COND_ENEMY_OCCLUDED ); - return; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pInfo - -// bAlways - -//----------------------------------------------------------------------------- -void CBaseHelicopter::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ) -{ - // Are we already marked for transmission? - if ( pInfo->m_pTransmitEdict->Get( entindex() ) ) - return; - - BaseClass::SetTransmit( pInfo, bAlways ); - - // Make our smoke trail always come with us - if ( m_hRotorWash ) - { - m_hRotorWash->SetTransmit( pInfo, bAlways ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void ExpandBBox(Vector &vecMins, Vector &vecMaxs) -{ - // expand for *any* rotation - float maxval = 0; - for (int i = 0; i < 3; i++) - { - float v = fabs( vecMins[i]); - if (v > maxval) - maxval = v; - - v = fabs( vecMaxs[i]); - if (v > maxval) - maxval = v; - } - - vecMins.Init(-maxval, -maxval, -maxval); - vecMaxs.Init(maxval, maxval, maxval); -} diff --git a/game/server/hl2/cbasehelicopter.h b/game/server/hl2/cbasehelicopter.h deleted file mode 100644 index 846b4a6f0..000000000 --- a/game/server/hl2/cbasehelicopter.h +++ /dev/null @@ -1,294 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Base class for helicopters & helicopter-type vehicles -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef CBASEHELICOPTER_H -#define CBASEHELICOPTER_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_basenpc.h" -#include "ai_trackpather.h" - - -//--------------------------------------------------------- -// Helicopter flags -//--------------------------------------------------------- -enum HelicopterFlags_t -{ - BITS_HELICOPTER_GUN_ON = 0x00000001, // Gun is on and aiming - BITS_HELICOPTER_MISSILE_ON = 0x00000002, // Missile turrets are on and aiming -}; - - -//--------------------------------------------------------- -//--------------------------------------------------------- -#define SF_NOWRECKAGE 0x08 -#define SF_NOROTORWASH 0x20 -#define SF_AWAITINPUT 0x40 - -//--------------------------------------------------------- -//--------------------------------------------------------- -// Pathing data -#define BASECHOPPER_LEAD_DISTANCE 800.0f -#define BASECHOPPER_MIN_CHASE_DIST_DIFF 128.0f // Distance threshold used to determine when a target has moved enough to update our navigation to it -#define BASECHOPPER_AVOID_DIST 256.0f - -#define BASECHOPPER_MAX_SPEED 400.0f -#define BASECHOPPER_MAX_FIRING_SPEED 250.0f -#define BASECHOPPER_MIN_ROCKET_DIST 1000.0f -#define BASECHOPPER_MAX_GUN_DIST 2000.0f - -//--------------------------------------------------------- -// Physics rotor pushing -#define BASECHOPPER_WASH_RADIUS 256 -#define BASECHOPPER_WASH_PUSH_MIN 30 // Initial force * their mass applied to objects in the wash -#define BASECHOPPER_WASH_PUSH_MAX 40 // Maximum force * their mass applied to objects in the wash -#define BASECHOPPER_WASH_RAMP_TIME 1.0 // Time it takes to ramp from the initial to the max force on an object in the wash (at the center of the wash) -#define BASECHOPPER_WASH_MAX_MASS 300 // Don't attempt to push anything over this mass -#define BASECHOPPER_WASH_MAX_OBJECTS 6 // Maximum number of objects the wash will push at once - -// Wash physics pushing -struct washentity_t -{ - DECLARE_DATADESC(); - - EHANDLE hEntity; - float flWashStartTime; -}; - -#define BASECHOPPER_WASH_ALTITUDE 1024.0f - -//========================================================= -//========================================================= - -class CBaseHelicopter : public CAI_TrackPather -{ -public: - DECLARE_CLASS( CBaseHelicopter, CAI_TrackPather ); - - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - CBaseHelicopter( void ); - - void Spawn( void ); - void Precache( void ); - virtual void UpdateOnRemove(); - - void Event_Killed( const CTakeDamageInfo &info ); - void StopLoopingSounds(); - - int BloodColor( void ) { return DONT_BLEED; } - void GibMonster( void ); - - Class_T Classify ( void ) { return CLASS_COMBINE; } - - void CallDyingThink( void ) { DyingThink(); } - - bool HasEnemy( void ) { return GetEnemy() != NULL; } - virtual void GatherEnemyConditions( CBaseEntity *pEnemy ); - virtual bool ChooseEnemy( void ); - virtual void HelicopterPostThink( void ) { }; - virtual void FlyTouch( CBaseEntity *pOther ); - virtual void CrashTouch( CBaseEntity *pOther ); - virtual void HelicopterThink( void ); - virtual void DyingThink( void ); - virtual void NullThink( void ); - virtual void Startup ( void ); - - virtual void Flight( void ); - - virtual void ShowDamage( void ) {}; - - void UpdatePlayerDopplerShift( void ); - - virtual void Hunt( void ); - - virtual bool IsCrashing( void ) { return m_lifeState != LIFE_ALIVE; } - virtual float GetAcceleration( void ) { return 5; } - - virtual void ApplySidewaysDrag( const Vector &vecRight ); - virtual void ApplyGeneralDrag( void ); - - void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - - virtual bool FireGun( void ); - - virtual float GetRotorVolume( void ); - virtual void InitializeRotorSound( void ); - virtual void UpdateRotorSoundPitch( int iPitch ); - - virtual void AimRocketGun(void) {}; - virtual void FireRocket( Vector vLaunchPos, Vector vLaunchDir ) {}; - - virtual bool GetTrackPatherTarget( Vector *pPos ); - virtual CBaseEntity *GetTrackPatherTargetEnt(); - - void DrawDebugGeometryOverlays(void); - - // Rotor washes - virtual void DrawRotorWash( float flAltitude, const Vector &vecRotorOrigin ); - void DoRotorPhysicsPush( const Vector &vecRotorOrigin, float flAltitude ); - bool DoWashPush( washentity_t *pWash, const Vector &vecWashOrigin ); - void StopRotorWash( void ); - - // Purpose: Marks the entity for deletion - void InputKill( inputdata_t &inputdata ); - void DelayedKillThink( ); - - virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ); - - // Helicopters never burn - virtual void Ignite( float flFlameLifetime, bool bNPCOnly, float flSize, bool bCalledByLevelDesigner ) { return; } - - -protected: - void HelicopterMove( ); - - // Updates the enemy - void UpdateEnemy(); - - // Override the desired position if your derived helicopter is doing something special - virtual void UpdateDesiredPosition( void ); - - // Updates the facing direction - virtual void UpdateFacingDirection(); - - // Fire weapons - void FireWeapons(); - - // Computes the actual position to fly to - void ComputeActualTargetPosition( float flSpeed, float flTime, float flPerpDist, Vector *pDest, bool bApplyNoise = true ); - - // Gets the max speed of the helicopter - virtual float GetMaxSpeed(); - virtual float GetMaxSpeedFiring(); - - // Updates the enemy - virtual float EnemySearchDistance( ); - - // Rotor wash think - void RotorWashThink( void ); - - // Purpose: Push an airboat in our wash - void DoWashPushOnAirboat( CBaseEntity *pAirboat, const Vector &vecWashToAirboat, float flWashAmount ); - - // Updates the rotor wash volume - virtual void UpdateRotorWashVolume(); - - // Rotor sound - void InputEnableRotorSound( inputdata_t &inputdata ); - void InputDisableRotorSound( inputdata_t &inputdata ); - -protected: - CSoundPatch *m_pRotorSound; // Rotor loop played when the player can see the helicopter - CSoundPatch *m_pRotorBlast; // Sound played when the helicopter's pushing around physics objects - - float m_flForce; - int m_fHelicopterFlags; - - Vector m_vecDesiredFaceDir; - - float m_flLastSeen; - float m_flPrevSeen; - - int m_iSoundState; // don't save this - - Vector m_vecTargetPosition; - - float m_flMaxSpeed; // Maximum speed of the helicopter. - float m_flMaxSpeedFiring; // Maximum speed of the helicopter whilst firing guns. - - float m_flGoalSpeed; // Goal speed - float m_flInitialSpeed; - - float m_flRandomOffsetTime; - Vector m_vecRandomOffset; - float m_flRotorWashEntitySearchTime; - bool m_bSuppressSound; - - EHANDLE m_hRotorWash; // Attached rotorwash entity - - // Inputs - void InputActivate( inputdata_t &inputdata ); - - // Inputs - void InputGunOn( inputdata_t &inputdata ); - void InputGunOff( inputdata_t &inputdata ); - void InputMissileOn( inputdata_t &inputdata ); - void InputMissileOff( inputdata_t &inputdata ); - void InputEnableRotorWash( inputdata_t &inputdata ); - void InputDisableRotorWash( inputdata_t &inputdata ); - void InputMoveTopSpeed( inputdata_t &inputdata ); // Causes the helicopter to immediately accelerate to its desired velocity - void InputMoveSpecifiedSpeed( inputdata_t &inputdata ); - void InputSetAngles( inputdata_t &inputdata ); // Sets the angles of the helicopter - -protected: - // Custom conservative collision volumes - Vector m_cullBoxMins; - Vector m_cullBoxMaxs; - - // Wash physics pushing - CUtlVector< washentity_t > m_hEntitiesPushedByWash; - - void SetStartupTime( float time ) { m_flStartupTime = time; } -private: - CNetworkVar( float, m_flStartupTime ); -}; - -//----------------------------------------------------------------------------- -// This entity is used to create little force spheres that the helicopter -// should avoid. -//----------------------------------------------------------------------------- -class CAvoidSphere : public CBaseEntity -{ - DECLARE_DATADESC(); - -public: - DECLARE_CLASS( CAvoidSphere, CBaseEntity ); - - void Init( float flRadius ); - virtual void Activate(); - virtual void UpdateOnRemove(); - - static void ComputeAvoidanceForces( CBaseEntity *pEntity, float flEntityRadius, float flAvoidTime, Vector *pVecAvoidForce ); - -private: - typedef CHandle AvoidSphereHandle_t; - - float m_flRadius; - - static CUtlVector< AvoidSphereHandle_t > s_AvoidSpheres; -}; - - -//----------------------------------------------------------------------------- -// This entity is used to create little force boxes that the helicopter -// should avoid. -//----------------------------------------------------------------------------- -class CAvoidBox : public CBaseEntity -{ - DECLARE_DATADESC(); - -public: - DECLARE_CLASS( CAvoidBox, CBaseEntity ); - - virtual void Spawn( ); - virtual void Activate(); - virtual void UpdateOnRemove(); - - static void ComputeAvoidanceForces( CBaseEntity *pEntity, float flEntityRadius, float flAvoidTime, Vector *pVecAvoidForce ); - -private: - typedef CHandle AvoidBoxHandle_t; - static CUtlVector< AvoidBoxHandle_t > s_AvoidBoxes; -}; - - -#endif // CBASEHELICOPTER_H diff --git a/game/server/hl2/cbasespriteprojectile.cpp b/game/server/hl2/cbasespriteprojectile.cpp deleted file mode 100644 index 9e712045c..000000000 --- a/game/server/hl2/cbasespriteprojectile.cpp +++ /dev/null @@ -1,106 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Base class for simple projectiles -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "cbasespriteprojectile.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -LINK_ENTITY_TO_CLASS( baseprojectile, CBaseSpriteProjectile ); - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CBaseSpriteProjectile ) - - DEFINE_FIELD( m_iDmg, FIELD_INTEGER ), - DEFINE_FIELD( m_iDmgType, FIELD_INTEGER ), - DEFINE_FIELD( m_hIntendedTarget, FIELD_EHANDLE ), - -END_DATADESC() - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBaseSpriteProjectile::Spawn( char *pszModel, - const Vector &vecOrigin, - const Vector &vecVelocity, - edict_t *pOwner, - MoveType_t iMovetype, - MoveCollide_t nMoveCollide, - int iDamage, - int iDamageType, - CBaseEntity *pIntendedTarget ) -{ - Precache(); - - SetSolid( SOLID_BBOX ); - SetModel( pszModel ); - - UTIL_SetSize( this, vec3_origin, vec3_origin ); - - m_iDmg = iDamage; - m_iDmgType = iDamageType; - - SetMoveType( iMovetype, nMoveCollide ); - - UTIL_SetOrigin( this, vecOrigin ); - SetAbsVelocity( vecVelocity ); - - SetOwnerEntity( Instance( pOwner ) ); - - m_hIntendedTarget.Set( pIntendedTarget ); - - // Call think for free the first time. It's up to derived classes to rethink. - SetNextThink( gpGlobals->curtime ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBaseSpriteProjectile::Touch( CBaseEntity *pOther ) -{ - HandleTouch( pOther ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBaseSpriteProjectile::HandleTouch( CBaseEntity *pOther ) -{ - CBaseEntity *pOwner; - - pOwner = GetOwnerEntity(); - - if( !pOwner ) - { - pOwner = this; - } - - trace_t tr; - tr = BaseClass::GetTouchTrace( ); - - CTakeDamageInfo info( this, pOwner, m_iDmg, m_iDmgType ); - GuessDamageForce( &info, (tr.endpos - tr.startpos), tr.endpos ); - pOther->TakeDamage( info ); - - UTIL_Remove( this ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBaseSpriteProjectile::Think() -{ - HandleThink(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBaseSpriteProjectile::HandleThink() -{ -} - diff --git a/game/server/hl2/cbasespriteprojectile.h b/game/server/hl2/cbasespriteprojectile.h deleted file mode 100644 index 84ea50a3c..000000000 --- a/game/server/hl2/cbasespriteprojectile.h +++ /dev/null @@ -1,51 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Base class for simple projectiles -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef CBASESPRITEPROJECTILE_H -#define CBASESPRITEPROJECTILE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "Sprite.h" - -enum MoveType_t; -enum MoveCollide_t; - - -//============================================================================= -//============================================================================= -class CBaseSpriteProjectile : public CSprite -{ - DECLARE_DATADESC(); - DECLARE_CLASS( CBaseSpriteProjectile, CSprite ); - -public: - void Touch( CBaseEntity *pOther ); - virtual void HandleTouch( CBaseEntity *pOther ); - - void Think(); - virtual void HandleThink(); - - void Spawn( char *pszModel, - const Vector &vecOrigin, - const Vector &vecVelocity, - edict_t *pOwner, - MoveType_t iMovetype, - MoveCollide_t nMoveCollide, - int iDamage, - int iDamageType, - CBaseEntity *pIntendedTarget = NULL ); - - virtual void Precache( void ) {}; - - int m_iDmg; - int m_iDmgType; - EHANDLE m_hIntendedTarget; -}; - -#endif // CBASESPRITEPROJECTILE_H diff --git a/game/server/hl2/citadel_effects.cpp b/game/server/hl2/citadel_effects.cpp deleted file mode 100644 index 7c72971ff..000000000 --- a/game/server/hl2/citadel_effects.cpp +++ /dev/null @@ -1,158 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "citadel_effects_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -LINK_ENTITY_TO_CLASS( env_citadel_energy_core, CCitadelEnergyCore ); - -BEGIN_DATADESC( CCitadelEnergyCore ) - DEFINE_KEYFIELD( m_flScale, FIELD_FLOAT, "scale" ), - DEFINE_FIELD( m_nState, FIELD_INTEGER ), - DEFINE_FIELD( m_flDuration, FIELD_FLOAT ), - DEFINE_FIELD( m_flStartTime, FIELD_TIME ), - - DEFINE_INPUTFUNC( FIELD_FLOAT, "StartCharge", InputStartCharge ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartDischarge", InputStartDischarge ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "Stop", InputStop ), -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CCitadelEnergyCore, DT_CitadelEnergyCore ) - SendPropFloat( SENDINFO(m_flScale), 0, SPROP_NOSCALE), - SendPropInt( SENDINFO(m_nState), 8, SPROP_UNSIGNED), - SendPropFloat( SENDINFO(m_flDuration), 0, SPROP_NOSCALE), - SendPropFloat( SENDINFO(m_flStartTime), 0, SPROP_NOSCALE), - SendPropInt( SENDINFO(m_spawnflags), 0, SPROP_UNSIGNED), -END_SEND_TABLE() - - -//----------------------------------------------------------------------------- -// Precache: -//----------------------------------------------------------------------------- -void CCitadelEnergyCore::Precache() -{ - BaseClass::Precache(); - PrecacheMaterial( "effects/combinemuzzle2_dark" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCitadelEnergyCore::Spawn( void ) -{ - Precache(); - - UTIL_SetSize( this, Vector( -8, -8, -8 ), Vector( 8, 8, 8 ) ); - - // See if we start active - if ( HasSpawnFlags( SF_ENERGYCORE_START_ON ) ) - { - m_nState = (int)ENERGYCORE_STATE_DISCHARGING; - m_flStartTime = gpGlobals->curtime; - } - - // No model but we still need to force this! - AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flWarmUpTime - -//----------------------------------------------------------------------------- -void CCitadelEnergyCore::StartCharge( float flWarmUpTime ) -{ - m_nState = (int)ENERGYCORE_STATE_CHARGING; - m_flDuration = flWarmUpTime; - m_flStartTime = gpGlobals->curtime; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCitadelEnergyCore::StartDischarge( void ) -{ - m_nState = (int)ENERGYCORE_STATE_DISCHARGING; - m_flStartTime = gpGlobals->curtime; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flCoolDownTime - -//----------------------------------------------------------------------------- -void CCitadelEnergyCore::StopDischarge( float flCoolDownTime ) -{ - m_nState = (int)ENERGYCORE_STATE_OFF; - m_flDuration = flCoolDownTime; - m_flStartTime = gpGlobals->curtime; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CCitadelEnergyCore::InputStartCharge( inputdata_t &inputdata ) -{ - StartCharge( inputdata.value.Float() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CCitadelEnergyCore::InputStartDischarge( inputdata_t &inputdata ) -{ - StartDischarge(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CCitadelEnergyCore::InputStop( inputdata_t &inputdata ) -{ - StopDischarge( inputdata.value.Float() ); -} - -CBaseViewModel *IsViewModelMoveParent( CBaseEntity *pEffect ) -{ - if ( pEffect->GetMoveParent() ) - { - CBaseViewModel *pViewModel = dynamic_cast( pEffect->GetMoveParent() ); - - if ( pViewModel ) - { - return pViewModel; - } - } - - return NULL; -} - -int CCitadelEnergyCore::UpdateTransmitState( void ) -{ - if ( IsViewModelMoveParent( this ) ) - { - return SetTransmitState( FL_EDICT_FULLCHECK ); - } - - return BaseClass::UpdateTransmitState(); -} - -int CCitadelEnergyCore::ShouldTransmit( const CCheckTransmitInfo *pInfo ) -{ - CBaseViewModel *pViewModel = IsViewModelMoveParent( this ); - - if ( pViewModel ) - { - return pViewModel->ShouldTransmit( pInfo ); - } - - return BaseClass::ShouldTransmit( pInfo ); -} diff --git a/game/server/hl2/combine_mine.cpp b/game/server/hl2/combine_mine.cpp deleted file mode 100644 index 16a1b0f9e..000000000 --- a/game/server/hl2/combine_mine.cpp +++ /dev/null @@ -1,1284 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "soundenvelope.h" -#include "Sprite.h" -#include "entitylist.h" -#include "ai_basenpc.h" -#include "soundent.h" -#include "explode.h" -#include "physics.h" -#include "physics_saverestore.h" -#include "combine_mine.h" -#include "movevars_shared.h" -#include "vphysics/constraints.h" -#include "ai_hint.h" - -enum -{ - MINE_STATE_DORMANT = 0, - MINE_STATE_DEPLOY, // Try to lock down and arm - MINE_STATE_CAPTIVE, // Held in the physgun - MINE_STATE_ARMED, // Locked down and looking for targets - MINE_STATE_TRIGGERED, // No turning back. I'm going to explode when I touch something. - MINE_STATE_LAUNCHED, // Similar. Thrown from physgun. -}; - -// for the Modification keyfield -enum -{ - MINE_MODIFICATION_NORMAL = 0, - MINE_MODIFICATION_CAVERN, -}; - -// the citizen modified skins for the mine (inclusive): -#define MINE_CITIZEN_SKIN_MIN 1 -#define MINE_CITIZEN_SKIN_MAX 2 - -const char *pszMineStateNames[] = -{ - "Dormant", - "Deploy", - "Captive", - "Armed", - "Triggered", - "Launched", -}; - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// After this many flips, seriously cut the frequency with which you try. -#define BOUNCEBOMB_MAX_FLIPS 5 - -// Approximate radius of the bomb's model -#define BOUNCEBOMB_RADIUS 24 - -BEGIN_DATADESC( CBounceBomb ) - DEFINE_THINKFUNC( ExplodeThink ), - DEFINE_ENTITYFUNC( ExplodeTouch ), - DEFINE_THINKFUNC( SearchThink ), - DEFINE_THINKFUNC( BounceThink ), - DEFINE_THINKFUNC( SettleThink ), - DEFINE_THINKFUNC( CaptiveThink ), - DEFINE_THINKFUNC( CavernBounceThink ), - - DEFINE_SOUNDPATCH( m_pWarnSound ), - - DEFINE_KEYFIELD( m_flExplosionDelay, FIELD_FLOAT, "ExplosionDelay" ), - DEFINE_KEYFIELD( m_bBounce, FIELD_BOOLEAN, "Bounce" ), - - DEFINE_FIELD( m_bAwake, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hNearestNPC, FIELD_EHANDLE ), - DEFINE_FIELD( m_hSprite, FIELD_EHANDLE ), - DEFINE_FIELD( m_LastSpriteColor, FIELD_COLOR32 ), - - DEFINE_FIELD( m_flHookPositions, FIELD_FLOAT ), - DEFINE_FIELD( m_iHookN, FIELD_INTEGER ), - DEFINE_FIELD( m_iHookE, FIELD_INTEGER ), - DEFINE_FIELD( m_iHookS, FIELD_INTEGER ), - DEFINE_FIELD( m_iAllHooks, FIELD_INTEGER ), - - DEFINE_KEYFIELD( m_bLockSilently, FIELD_BOOLEAN, "LockSilently" ), - DEFINE_FIELD( m_bFoeNearest, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flIgnoreWorldTime, FIELD_TIME ), - DEFINE_KEYFIELD( m_bDisarmed, FIELD_BOOLEAN, "StartDisarmed" ), - DEFINE_KEYFIELD( m_iModification, FIELD_INTEGER, "Modification" ), - - DEFINE_FIELD( m_bPlacedByPlayer, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bHeldByPhysgun, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_iFlipAttempts, FIELD_INTEGER ), - - DEFINE_FIELD( m_flTimeGrabbed, FIELD_TIME ), - DEFINE_FIELD( m_iMineState, FIELD_INTEGER ), - - // Physics Influence - DEFINE_FIELD( m_hPhysicsAttacker, FIELD_EHANDLE ), - DEFINE_FIELD( m_flLastPhysicsInfluenceTime, FIELD_TIME ), - - DEFINE_PHYSPTR( m_pConstraint ), - - DEFINE_OUTPUT( m_OnPulledUp, "OnPulledUp" ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disarm", InputDisarm ), - -END_DATADESC() - -string_t CBounceBomb::gm_iszFloorTurretClassname; -string_t CBounceBomb::gm_iszGroundTurretClassname; - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBounceBomb::Precache() -{ - PrecacheModel("models/props_combine/combine_mine01.mdl"); - - PrecacheScriptSound( "NPC_CombineMine.Hop" ); - PrecacheScriptSound( "NPC_CombineMine.FlipOver" ); - PrecacheScriptSound( "NPC_CombineMine.TurnOn" ); - PrecacheScriptSound( "NPC_CombineMine.TurnOff" ); - PrecacheScriptSound( "NPC_CombineMine.OpenHooks" ); - PrecacheScriptSound( "NPC_CombineMine.CloseHooks" ); - - PrecacheScriptSound( "NPC_CombineMine.ActiveLoop" ); - - PrecacheModel( "sprites/glow01.vmt" ); - - gm_iszFloorTurretClassname = AllocPooledString( "npc_turret_floor" ); - gm_iszGroundTurretClassname = AllocPooledString( "npc_turret_ground" ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBounceBomb::Spawn() -{ - Precache(); - - Wake( false ); - - SetModel("models/props_combine/combine_mine01.mdl"); - - SetSolid( SOLID_VPHYSICS ); - - m_hSprite.Set( NULL ); - m_takedamage = DAMAGE_EVENTS_ONLY; - - // Find my feet! - m_iHookN = LookupPoseParameter( "blendnorth" ); - m_iHookE = LookupPoseParameter( "blendeast" ); - m_iHookS = LookupPoseParameter( "blendsouth" ); - m_iAllHooks = LookupPoseParameter( "blendstates" ); - m_flHookPositions = 0; - - SetHealth( 100 ); - - m_bBounce = true; - - SetSequence( SelectWeightedSequence( ACT_IDLE ) ); - - OpenHooks( true ); - - m_bHeldByPhysgun = false; - - m_iFlipAttempts = 0; - - if( !GetParent() ) - { - // Create vphysics now if I'm not being carried. - CreateVPhysics(); - } - - m_flTimeGrabbed = FLT_MAX; - - if( m_bDisarmed ) - { - SetMineState( MINE_STATE_DORMANT ); - } - else - { - SetMineState( MINE_STATE_DEPLOY ); - } - - // default to a different skin for cavern turrets (unless explicitly overridden) - if ( m_iModification == MINE_MODIFICATION_CAVERN ) - { - // look for this value in the first datamap - // loop through the data description list, restoring each data desc block - datamap_t *dmap = GetDataDescMap(); - - bool bFoundSkin = false; - // search through all the readable fields in the data description, looking for a match - for ( int i = 0; i < dmap->dataNumFields; ++i ) - { - if ( dmap->dataDesc[i].flags & (FTYPEDESC_OUTPUT | FTYPEDESC_KEY) ) - { - if ( !Q_stricmp(dmap->dataDesc[i].externalName, "Skin") ) - { - bFoundSkin = true; - break; - } - } - } - - if (!bFoundSkin) - { - // select a random skin for the mine. Actually, we'll cycle through the available skins - // using a static variable to provide better distribution. The static isn't saved but - // really it's only cosmetic. - static unsigned int nextSkin = MINE_CITIZEN_SKIN_MIN; - m_nSkin = nextSkin; - // increment the skin for next time - nextSkin = (nextSkin >= MINE_CITIZEN_SKIN_MAX) ? MINE_CITIZEN_SKIN_MIN : nextSkin + 1; - } - - // pretend like the player set me down. - m_bPlacedByPlayer = true; - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBounceBomb::OnRestore() -{ - BaseClass::OnRestore(); - if ( gpGlobals->eLoadType == MapLoad_Transition && !m_hSprite && m_LastSpriteColor.GetRawColor() != 0 ) - { - UpdateLight( true, m_LastSpriteColor.r(), m_LastSpriteColor.g(), m_LastSpriteColor.b(), m_LastSpriteColor.a() ); - } - - if( VPhysicsGetObject() ) - { - VPhysicsGetObject()->Wake(); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CBounceBomb::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - Q_snprintf(tempstr,sizeof(tempstr), pszMineStateNames[m_iMineState] ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBounceBomb::SetMineState( int iState ) -{ - m_iMineState = iState; - - switch( iState ) - { - case MINE_STATE_DORMANT: - { - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundChangeVolume( m_pWarnSound, 0.0, 0.1 ); - UpdateLight( false, 0, 0, 0, 0 ); - SetThink( NULL ); - } - break; - - case MINE_STATE_CAPTIVE: - { - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundChangeVolume( m_pWarnSound, 0.0, 0.2 ); - - // Unhook - unsigned int flags = VPhysicsGetObject()->GetCallbackFlags(); - VPhysicsGetObject()->SetCallbackFlags( flags | CALLBACK_GLOBAL_TOUCH_STATIC ); - OpenHooks(); - physenv->DestroyConstraint( m_pConstraint ); - m_pConstraint = NULL; - - UpdateLight( true, 0, 0, 255, 190 ); - SetThink( &CBounceBomb::CaptiveThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); - SetTouch( NULL ); - } - break; - - case MINE_STATE_DEPLOY: - OpenHooks( true ); - UpdateLight( true, 0, 0, 255, 190 ); - SetThink( &CBounceBomb::SettleThink ); - SetTouch( NULL ); - SetNextThink( gpGlobals->curtime + 0.1f ); - break; - - case MINE_STATE_ARMED: - UpdateLight( false, 0, 0, 0, 0 ); - SetThink( &CBounceBomb::SearchThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); - break; - - case MINE_STATE_TRIGGERED: - { - OpenHooks(); - - if( m_pConstraint ) - { - physenv->DestroyConstraint( m_pConstraint ); - m_pConstraint = NULL; - } - - // Scare NPC's - CSoundEnt::InsertSound( SOUND_DANGER, GetAbsOrigin(), 300, 1.0f, this ); - - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundChangeVolume( m_pWarnSound, 0.0, 0.2 ); - - SetTouch( &CBounceBomb::ExplodeTouch ); - unsigned int flags = VPhysicsGetObject()->GetCallbackFlags(); - VPhysicsGetObject()->SetCallbackFlags( flags | CALLBACK_GLOBAL_TOUCH_STATIC ); - - Vector vecNudge; - - vecNudge.x = random->RandomFloat( -1, 1 ); - vecNudge.y = random->RandomFloat( -1, 1 ); - vecNudge.z = 1.5; - vecNudge *= 350; - - VPhysicsGetObject()->Wake(); - VPhysicsGetObject()->ApplyForceCenter( vecNudge ); - - float x, y; - x = 10 + random->RandomFloat( 0, 20 ); - y = 10 + random->RandomFloat( 0, 20 ); - - VPhysicsGetObject()->ApplyTorqueCenter( AngularImpulse( x, y, 0 ) ); - - // Since we just nudged the mine, ignore collisions with the world until - // the mine is in the air. We only want to explode if the player tries to - // run over the mine before it jumps up. - m_flIgnoreWorldTime = gpGlobals->curtime + 1.0; - UpdateLight( true, 255, 0, 0, 190 ); - - // use the correct bounce behavior - if (m_iModification == MINE_MODIFICATION_CAVERN) - { - SetThink ( &CBounceBomb::CavernBounceThink ); - SetNextThink( gpGlobals->curtime + 0.15 ); - } - else - { - SetThink( &CBounceBomb::BounceThink ); - SetNextThink( gpGlobals->curtime + 0.5 ); - } - } - break; - - case MINE_STATE_LAUNCHED: - { - UpdateLight( true, 255, 0, 0, 190 ); - SetThink( NULL ); - SetNextThink( gpGlobals->curtime + 0.5 ); - - SetTouch( &CBounceBomb::ExplodeTouch ); - unsigned int flags = VPhysicsGetObject()->GetCallbackFlags(); - VPhysicsGetObject()->SetCallbackFlags( flags | CALLBACK_GLOBAL_TOUCH_STATIC ); - } - break; - - default: - DevMsg("**Unknown Mine State: %d\n", iState ); - break; - } -} - -//--------------------------------------------------------- -// Bouncbomb flips to try to right itself, try to get off -// of and object that it's not allowed to clamp to, or -// to get away from a hint node that inhibits placement -// of mines. -//--------------------------------------------------------- -void CBounceBomb::Flip( const Vector &vecForce, const AngularImpulse &torque ) -{ - if( m_iFlipAttempts > BOUNCEBOMB_MAX_FLIPS ) - { - // Not allowed to try anymore. - SetThink(NULL); - return; - } - - EmitSound( "NPC_CombineMine.FlipOver" ); - VPhysicsGetObject()->ApplyForceCenter( vecForce ); - VPhysicsGetObject()->ApplyTorqueCenter( torque ); - m_iFlipAttempts++; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -#define MINE_MIN_PROXIMITY_SQR 676 // 27 inches -bool CBounceBomb::IsValidLocation() -{ - CBaseEntity *pAvoidObject = NULL; - float flAvoidForce = 0.0f; - CAI_Hint *pHint; - CHintCriteria criteria; - criteria.SetHintType( HINT_WORLD_INHIBIT_COMBINE_MINES ); - criteria.SetFlag( bits_HINT_NODE_NEAREST ); - criteria.AddIncludePosition( GetAbsOrigin(), 12.0f * 15.0f ); - pHint = CAI_HintManager::FindHint( GetAbsOrigin(), criteria ); - - if( pHint ) - { - pAvoidObject = pHint; - flAvoidForce = 120.0f; - } - else - { - // Look for other mines that are too close to me. - CBaseEntity *pEntity = gEntList.FirstEnt(); - Vector vecMyPosition = GetAbsOrigin(); - while( pEntity ) - { - if( pEntity->m_iClassname == m_iClassname && pEntity != this ) - { - // Don't lock down if I'm near a mine that's already locked down. - if( vecMyPosition.DistToSqr(pEntity->GetAbsOrigin()) < MINE_MIN_PROXIMITY_SQR ) - { - pAvoidObject = pEntity; - flAvoidForce = 60.0f; - break; - } - } - - pEntity = gEntList.NextEnt( pEntity ); - } - } - - if( pAvoidObject ) - { - // Build a force vector to push us away from the inhibitor. - // Start by pushing upwards. - Vector vecForce = Vector( 0, 0, VPhysicsGetObject()->GetMass() * 200.0f ); - - // Now add some force in the direction that takes us away from the inhibitor. - Vector vecDir = GetAbsOrigin() - pAvoidObject->GetAbsOrigin(); - vecDir.z = 0.0f; - VectorNormalize( vecDir ); - vecForce += vecDir * VPhysicsGetObject()->GetMass() * flAvoidForce; - - Flip( vecForce, AngularImpulse( 100, 0, 0 ) ); - - // Tell the code that asked that this position isn't valid. - return false; - } - - return true; -} - -//--------------------------------------------------------- -// Release the spikes -//--------------------------------------------------------- -void CBounceBomb::BounceThink() -{ - SetNextThink( gpGlobals->curtime + 0.1 ); - StudioFrameAdvance(); - - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - - if ( pPhysicsObject != NULL ) - { - const float MINE_MAX_JUMP_HEIGHT = 200; - - // Figure out how much headroom the mine has, and hop to within a few inches of that. - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, MINE_MAX_JUMP_HEIGHT ), MASK_SHOT, this, COLLISION_GROUP_INTERACTIVE, &tr ); - - float height; - - if( tr.m_pEnt && tr.m_pEnt->VPhysicsGetObject() ) - { - // Physics object resting on me. Jump as hard as allowed to try to knock it away. - height = MINE_MAX_JUMP_HEIGHT; - } - else - { - height = tr.endpos.z - GetAbsOrigin().z; - height -= BOUNCEBOMB_RADIUS; - if ( height < 0.1 ) - height = 0.1; - } - - float time = sqrt( height / (0.5 * sv_gravity.GetFloat()) ); - float velocity = sv_gravity.GetFloat() * time; - - // or you can just AddVelocity to the object instead of ApplyForce - float force = velocity * pPhysicsObject->GetMass(); - - Vector up; - - GetVectors( NULL, NULL, &up ); - pPhysicsObject->Wake(); - pPhysicsObject->ApplyForceCenter( up * force ); - - pPhysicsObject->ApplyTorqueCenter( AngularImpulse( random->RandomFloat( 5, 25 ), random->RandomFloat( 5, 25 ), 0 ) ); - - - if( m_hNearestNPC ) - { - Vector vecPredict = m_hNearestNPC->GetSmoothedVelocity(); - - pPhysicsObject->ApplyForceCenter( vecPredict * 10 ); - } - - EmitSound( "NPC_CombineMine.Hop" ); - SetThink( NULL ); - } -} - - -//--------------------------------------------------------- -// A different bounce behavior for the citizen-modified mine. Detonates at the top of its apex, -// and does not attempt to track enemies. -//--------------------------------------------------------- -void CBounceBomb::CavernBounceThink() -{ - SetNextThink( gpGlobals->curtime + 0.1 ); - StudioFrameAdvance(); - - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - - if ( pPhysicsObject != NULL ) - { - const float MINE_MAX_JUMP_HEIGHT = 78; - - // Figure out how much headroom the mine has, and hop to within a few inches of that. - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, MINE_MAX_JUMP_HEIGHT ), MASK_SHOT, this, COLLISION_GROUP_INTERACTIVE, &tr ); - - float height; - - if( tr.m_pEnt && tr.m_pEnt->VPhysicsGetObject() ) - { - // Physics object resting on me. Jump as hard as allowed to try to knock it away. - height = MINE_MAX_JUMP_HEIGHT; - } - else - { - height = tr.endpos.z - GetAbsOrigin().z; - height -= BOUNCEBOMB_RADIUS; - if ( height < 0.1 ) - height = 0.1; - } - - float time = sqrt( height / (0.5 * sv_gravity.GetFloat()) ); - float velocity = sv_gravity.GetFloat() * time; - - // or you can just AddVelocity to the object instead of ApplyForce - float force = velocity * pPhysicsObject->GetMass(); - - Vector up; - - GetVectors( NULL, NULL, &up ); - - pPhysicsObject->Wake(); - pPhysicsObject->ApplyForceCenter( up * force ); - if( m_hNearestNPC ) - { - Vector vecPredict = m_hNearestNPC->GetSmoothedVelocity(); - - pPhysicsObject->ApplyForceCenter( vecPredict * (pPhysicsObject->GetMass() * 0.65f) ); - } - - pPhysicsObject->ApplyTorqueCenter( AngularImpulse( random->RandomFloat( 15, 40 ), random->RandomFloat( 15, 40 ), random->RandomFloat( 30, 60 ) ) ); - - EmitSound( "NPC_CombineMine.Hop" ); - - SetThink( &CBounceBomb::ExplodeThink ); - SetNextThink( gpGlobals->curtime + 0.33f ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBounceBomb::CaptiveThink() -{ - SetNextThink( gpGlobals->curtime + 0.05 ); - StudioFrameAdvance(); - - float phase = fabs( sin( gpGlobals->curtime * 4.0f ) ); - phase *= BOUNCEBOMB_HOOK_RANGE; - SetPoseParameter( m_iAllHooks, phase ); - return; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBounceBomb::SettleThink() -{ - SetNextThink( gpGlobals->curtime + 0.05 ); - StudioFrameAdvance(); - - if( GetParent() ) - { - // A scanner or something is carrying me. Just keep checking back. - return; - } - - // Not being carried. - if( !VPhysicsGetObject() ) - { - // Probably was just dropped. Get physics going. - CreateVPhysics(); - - if( !VPhysicsGetObject() ) - { - Msg("**** Can't create vphysics for combine_mine!\n" ); - UTIL_Remove( this ); - return; - } - - VPhysicsGetObject()->Wake(); - return; - } - - if( !m_bDisarmed ) - { - if( VPhysicsGetObject()->IsAsleep() && !(VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD) ) - { - // If i'm not resting on the world, jump randomly. - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector( 0, 0, 1024 ), MASK_SHOT|CONTENTS_GRATE, this, COLLISION_GROUP_NONE, &tr ); - - bool bHop = false; - if( tr.m_pEnt ) - { - IPhysicsObject *pPhysics = tr.m_pEnt->VPhysicsGetObject(); - - if( pPhysics && pPhysics->GetMass() <= 1000 ) - { - // Light physics objects can be moved out from under the mine. - bHop = true; - } - else if( tr.m_pEnt->m_takedamage != DAMAGE_NO ) - { - // Things that can be harmed can likely be broken. - bHop = true; - } - - if( bHop ) - { - Vector vecForce; - vecForce.x = random->RandomFloat( -1000, 1000 ); - vecForce.y = random->RandomFloat( -1000, 1000 ); - vecForce.z = 2500; - - AngularImpulse torque( 160, 0, 160 ); - - Flip( vecForce, torque ); - return; - } - - // Check for upside-down - Vector vecUp; - GetVectors( NULL, NULL, &vecUp ); - if( vecUp.z <= 0.8 ) - { - // Landed upside down. Right self - Vector vecForce( 0, 0, 2500 ); - Flip( vecForce, AngularImpulse( 60, 0, 0 ) ); - return; - } - } - - // Check to make sure I'm not in a forbidden location - if( !IsValidLocation() ) - { - return; - } - - // Lock to what I'm resting on - constraint_ballsocketparams_t ballsocket; - ballsocket.Defaults(); - ballsocket.constraint.Defaults(); - ballsocket.constraint.forceLimit = lbs2kg(1000); - ballsocket.constraint.torqueLimit = lbs2kg(1000); - ballsocket.InitWithCurrentObjectState( g_PhysWorldObject, VPhysicsGetObject(), GetAbsOrigin() ); - m_pConstraint = physenv->CreateBallsocketConstraint( g_PhysWorldObject, VPhysicsGetObject(), NULL, ballsocket ); - CloseHooks(); - - SetMineState( MINE_STATE_ARMED ); - } - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CBounceBomb::OnTakeDamage( const CTakeDamageInfo &info ) -{ - if( m_pConstraint || !VPhysicsGetObject()) - { - return false; - } - - VPhysicsTakeDamage( info ); - return true; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBounceBomb::UpdateLight( bool bTurnOn, unsigned int r, unsigned int g, unsigned int b, unsigned int a ) -{ - if( bTurnOn ) - { - Assert( a > 0 ); - - // Throw the old sprite away - if( m_hSprite ) - { - UTIL_Remove( m_hSprite ); - m_hSprite.Set( NULL ); - } - - if( !m_hSprite.Get() ) - { - Vector up; - GetVectors( NULL, NULL, &up ); - - // Light isn't on. - m_hSprite = CSprite::SpriteCreate( "sprites/glow01.vmt", GetAbsOrigin() + up * 10.0f, false ); - CSprite *pSprite = (CSprite *)m_hSprite.Get(); - - if( m_hSprite ) - { - pSprite->SetParent( this ); - pSprite->SetTransparency( kRenderTransAdd, r, g, b, a, kRenderFxNone ); - pSprite->SetScale( 0.35, 0.0 ); - } - } - else - { - // Update color - CSprite *pSprite = (CSprite *)m_hSprite.Get(); - pSprite->SetTransparency( kRenderTransAdd, r, g, b, a, kRenderFxNone ); - } - } - - if( !bTurnOn ) - { - if( m_hSprite ) - { - UTIL_Remove( m_hSprite ); - m_hSprite.Set( NULL ); - } - } - - if ( !m_hSprite ) - { - m_LastSpriteColor.SetRawColor( 0 ); - } - else - { - m_LastSpriteColor.SetColor( r, g, b, a ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBounceBomb::Wake( bool bAwake ) -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - - CReliableBroadcastRecipientFilter filter; - - if( !m_pWarnSound ) - { - m_pWarnSound = controller.SoundCreate( filter, entindex(), "NPC_CombineMine.ActiveLoop" ); - controller.Play( m_pWarnSound, 1.0, PITCH_NORM ); - } - - if( bAwake ) - { - // Turning on - if( m_bFoeNearest ) - { - EmitSound( "NPC_CombineMine.TurnOn" ); - controller.SoundChangeVolume( m_pWarnSound, 1.0, 0.1 ); - } - - unsigned char r, g, b; - r = g = b = 0; - - if( m_bFoeNearest ) - { - r = 255; - } - else - { - g = 255; - } - - UpdateLight( true, r, g, b, 190 ); - } - else - { - // Turning off - if( m_bFoeNearest ) - { - EmitSound( "NPC_CombineMine.TurnOff" ); - } - - SetNearestNPC( NULL ); - controller.SoundChangeVolume( m_pWarnSound, 0.0, 0.1 ); - UpdateLight( false, 0, 0, 0, 0 ); - } - - m_bAwake = bAwake; -} - -//--------------------------------------------------------- -// Returns distance to the nearest BaseCombatCharacter. -//--------------------------------------------------------- -float CBounceBomb::FindNearestNPC() -{ - float flNearest = (BOUNCEBOMB_WARN_RADIUS * BOUNCEBOMB_WARN_RADIUS) + 1.0; - - // Assume this search won't find anyone. - SetNearestNPC( NULL ); - - CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); - int nAIs = g_AI_Manager.NumAIs(); - - for ( int i = 0; i < nAIs; i++ ) - { - CAI_BaseNPC *pNPC = ppAIs[ i ]; - - if( pNPC->IsAlive() ) - { - // ignore hidden objects - if ( pNPC->IsEffectActive( EF_NODRAW ) ) - continue; - - // Don't bother with NPC's that are below me. - if( pNPC->EyePosition().z < GetAbsOrigin().z ) - continue; - - // Disregard things that want to be disregarded - if( pNPC->Classify() == CLASS_NONE ) - continue; - - // Disregard bullseyes - if( pNPC->Classify() == CLASS_BULLSEYE ) - continue; - - // Disregard turrets - if( pNPC->m_iClassname == gm_iszFloorTurretClassname || pNPC->m_iClassname == gm_iszGroundTurretClassname ) - continue; - - - float flDist = (GetAbsOrigin() - pNPC->GetAbsOrigin()).LengthSqr(); - - if( flDist < flNearest ) - { - // Now do a visibility test. - if( FVisible( pNPC, MASK_SOLID_BRUSHONLY ) ) - { - flNearest = flDist; - SetNearestNPC( pNPC ); - } - } - } - } - - // finally, check the player. - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - - if( pPlayer && !(pPlayer->GetFlags() & FL_NOTARGET) ) - { - float flDist = (pPlayer->GetAbsOrigin() - GetAbsOrigin() ).LengthSqr(); - - if( flDist < flNearest && FVisible( pPlayer, MASK_SOLID_BRUSHONLY ) ) - { - flNearest = flDist; - SetNearestNPC( pPlayer ); - } - } - - if( m_hNearestNPC.Get() ) - { - // If sprite is active, update its color to reflect who is nearest. - if( IsFriend( m_hNearestNPC ) ) - { - if( m_bFoeNearest ) - { - // Changing state to where a friend is nearest. - - if( IsFriend( m_hNearestNPC ) ) - { - // Friend - UpdateLight( true, 0, 255, 0, 190 ); - m_bFoeNearest = false; - } - } - } - else // it's a foe - { - if( !m_bFoeNearest ) - { - // Changing state to where a foe is nearest. - UpdateLight( true, 255, 0, 0, 190 ); - m_bFoeNearest = true; - } - } - } - - return sqrt( flNearest ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CBounceBomb::IsFriend( CBaseEntity *pEntity ) -{ - int classify = pEntity->Classify(); - bool bIsCombine = false; - - // Unconditional enemies to combine and Player. - if( classify == CLASS_ZOMBIE || classify == CLASS_HEADCRAB || classify == CLASS_ANTLION ) - { - return false; - } - - if( classify == CLASS_METROPOLICE || - classify == CLASS_COMBINE || - classify == CLASS_MILITARY || - classify == CLASS_COMBINE_HUNTER || - classify == CLASS_SCANNER ) - { - bIsCombine = true; - } - - if( m_bPlacedByPlayer ) - { - return !bIsCombine; - } - else - { - return bIsCombine; - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBounceBomb::SearchThink() -{ - if( !UTIL_FindClientInPVS(edict()) ) - { - // Sleep! - SetNextThink( gpGlobals->curtime + 0.5 ); - return; - } - - if( (CAI_BaseNPC::m_nDebugBits & bits_debugDisableAI) ) - { - if( IsAwake() ) - { - Wake(false); - } - - SetNextThink( gpGlobals->curtime + 0.5 ); - return; - } - - SetNextThink( gpGlobals->curtime + 0.1 ); - StudioFrameAdvance(); - - if( m_pConstraint && gpGlobals->curtime - m_flTimeGrabbed >= 1.0f ) - { - m_OnPulledUp.FireOutput( this, this ); - SetMineState( MINE_STATE_CAPTIVE ); - return; - } - - float flNearestNPCDist = FindNearestNPC(); - - if( flNearestNPCDist <= BOUNCEBOMB_WARN_RADIUS ) - { - if( !IsAwake() ) - { - Wake( true ); - } - } - else - { - if( IsAwake() ) - { - Wake( false ); - } - - return; - } - - if( flNearestNPCDist <= BOUNCEBOMB_DETONATE_RADIUS && !IsFriend( m_hNearestNPC ) ) - { - if( m_bBounce ) - { - SetMineState( MINE_STATE_TRIGGERED ); - } - else - { - // Don't pop up in the air, just explode if the NPC gets closer than explode radius. - SetThink( &CBounceBomb::ExplodeThink ); - SetNextThink( gpGlobals->curtime + m_flExplosionDelay ); - } - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBounceBomb::ExplodeTouch( CBaseEntity *pOther ) -{ - // Don't touch anything if held by physgun. - if( m_bHeldByPhysgun ) - return; - - // Don't touch triggers. - if( pOther->IsSolidFlagSet(FSOLID_TRIGGER) ) - return; - - // Don't touch gibs and other debris - if( pOther->GetCollisionGroup() == COLLISION_GROUP_DEBRIS ) - { - if( hl2_episodic.GetBool() ) - { - Vector vecVelocity; - - VPhysicsGetObject()->GetVelocity( &vecVelocity, NULL ); - - if( vecVelocity == vec3_origin ) - { - ExplodeThink(); - } - } - - return; - } - - // Don't detonate against the world if not allowed. Actually, don't - // detonate against anything that's probably not an NPC (such as physics props) - if( m_flIgnoreWorldTime > gpGlobals->curtime && !pOther->MyCombatCharacterPointer() ) - { - return; - } - - ExplodeThink(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBounceBomb::ExplodeThink() -{ - SetSolid( SOLID_NONE ); - - // Don't catch self in own explosion! - m_takedamage = DAMAGE_NO; - - if( m_hSprite ) - { - UpdateLight( false, 0, 0, 0, 0 ); - } - - if( m_pWarnSound ) - { - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundDestroy( m_pWarnSound ); - } - - - CBaseEntity *pThrower = HasPhysicsAttacker( 0.5 ); - - if (m_iModification == MINE_MODIFICATION_CAVERN) - { - ExplosionCreate( GetAbsOrigin(), GetAbsAngles(), (pThrower) ? pThrower : this, BOUNCEBOMB_EXPLODE_DAMAGE, BOUNCEBOMB_EXPLODE_RADIUS, true, - NULL, CLASS_PLAYER_ALLY ); - } - else - { - ExplosionCreate( GetAbsOrigin(), GetAbsAngles(), (pThrower) ? pThrower : this, BOUNCEBOMB_EXPLODE_DAMAGE, BOUNCEBOMB_EXPLODE_RADIUS, true); - } - UTIL_Remove( this ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBounceBomb::OpenHooks( bool bSilent ) -{ - if( !bSilent ) - { - EmitSound( "NPC_CombineMine.OpenHooks" ); - } - - if( VPhysicsGetObject() ) - { - // It's possible to not have a valid physics object here, since this function doubles as an initialization function. - PhysClearGameFlags( VPhysicsGetObject(), FVPHYSICS_CONSTRAINT_STATIC ); - - VPhysicsGetObject()->EnableMotion( true ); - } - - SetPoseParameter( m_iAllHooks, BOUNCEBOMB_HOOK_RANGE ); - -#ifdef _XBOX - RemoveEffects( EF_NOSHADOW ); -#endif - -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBounceBomb::CloseHooks() -{ - if( !m_bLockSilently ) - { - EmitSound( "NPC_CombineMine.CloseHooks" ); - } - - if( VPhysicsGetObject() ) - { - // It's possible to not have a valid physics object here, since this function doubles as an initialization function. - PhysSetGameFlags( VPhysicsGetObject(), FVPHYSICS_CONSTRAINT_STATIC ); - } - - // Only lock silently the first time we call this. - m_bLockSilently = false; - - SetPoseParameter( m_iAllHooks, 0 ); - - VPhysicsGetObject()->EnableMotion( false ); - - // Once I lock down, forget how many tries it took. - m_iFlipAttempts = 0; - -#ifdef _XBOX - AddEffects( EF_NOSHADOW ); -#endif -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBounceBomb::InputDisarm( inputdata_t &inputdata ) -{ - // Only affect a mine that's armed and not placed by player. - if( !m_bPlacedByPlayer && m_iMineState == MINE_STATE_ARMED ) - { - if( m_pConstraint ) - { - physenv->DestroyConstraint( m_pConstraint ); - m_pConstraint = NULL; - } - - m_bDisarmed = true; - OpenHooks(false); - - SetMineState(MINE_STATE_DORMANT); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBounceBomb::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ) -{ - m_hPhysicsAttacker = pPhysGunUser; - m_flLastPhysicsInfluenceTime = gpGlobals->curtime; - - m_flTimeGrabbed = FLT_MAX; - - m_bHeldByPhysgun = false; - - if( m_iMineState == MINE_STATE_ARMED ) - { - // Put the mine back to searching. - Wake( false ); - return; - } - - if( Reason == DROPPED_BY_CANNON ) - { - // Set to lock down to ground again. - m_bPlacedByPlayer = true; - OpenHooks( true ); - SetMineState( MINE_STATE_DEPLOY ); - } - else if ( Reason == LAUNCHED_BY_CANNON ) - { - SetMineState( MINE_STATE_LAUNCHED ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -CBasePlayer *CBounceBomb::HasPhysicsAttacker( float dt ) -{ - if (gpGlobals->curtime - dt <= m_flLastPhysicsInfluenceTime) - { - return m_hPhysicsAttacker; - } - return NULL; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBounceBomb::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) -{ - m_hPhysicsAttacker = pPhysGunUser; - m_flLastPhysicsInfluenceTime = gpGlobals->curtime; - - m_iFlipAttempts = 0; - - if( reason != PUNTED_BY_CANNON ) - { - if( m_iMineState == MINE_STATE_ARMED ) - { - // Yanking on a mine that is locked down, trying to rip it loose. - UpdateLight( true, 255, 255, 0, 190 ); - m_flTimeGrabbed = gpGlobals->curtime; - m_bHeldByPhysgun = true; - - VPhysicsGetObject()->EnableMotion( true ); - - // Try to scatter NPCs without panicking them. Make a move away sound up around their - // ear level. - CSoundEnt::InsertSound( SOUND_MOVE_AWAY, GetAbsOrigin() + Vector( 0, 0, 60), 32, 0.2f ); - return; - } - else - { - // Picked up a mine that was not locked down. - m_bHeldByPhysgun = true; - - if( m_iMineState == MINE_STATE_TRIGGERED ) - { - // This mine's already set to blow. Player can't place it. - return; - } - else - { - m_bDisarmed = false; - SetMineState( MINE_STATE_DEPLOY ); - } - } - } - else - { - m_bHeldByPhysgun = false; - } - - if( reason == PUNTED_BY_CANNON ) - { - if( m_iMineState == MINE_STATE_TRIGGERED || m_iMineState == MINE_STATE_ARMED ) - { - // Already set to blow - return; - } - - m_bDisarmed = false; - m_bPlacedByPlayer = true; - SetTouch( NULL ); - SetThink( &CBounceBomb::SettleThink ); - SetNextThink( gpGlobals->curtime + 0.1); - - // Since being punted causes the mine to flip, sometimes it 'catches an edge' - // and ends up touching the ground from whence it came, exploding instantly. - // This little stunt prevents that by ignoring world collisions for a very short time. - m_flIgnoreWorldTime = gpGlobals->curtime + 0.1; - } -} - - -LINK_ENTITY_TO_CLASS( bounce_bomb, CBounceBomb ); -LINK_ENTITY_TO_CLASS( combine_bouncemine, CBounceBomb ); -LINK_ENTITY_TO_CLASS( combine_mine, CBounceBomb ); - -/* -*/ diff --git a/game/server/hl2/combine_mine.h b/game/server/hl2/combine_mine.h deleted file mode 100644 index 25bdec622..000000000 --- a/game/server/hl2/combine_mine.h +++ /dev/null @@ -1,128 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "Color.h" - -#ifndef COMBINE_MINE_H -#define COMBINE_MINE_H - -#ifdef _WIN32 -#pragma once -#endif - -class CSoundPatch; - -//--------------------------------------------------------- -//--------------------------------------------------------- -#define BOUNCEBOMB_HOOK_RANGE 64 -#define BOUNCEBOMB_WARN_RADIUS 245.0 // Must be slightly less than physcannon! -#define BOUNCEBOMB_DETONATE_RADIUS 100.0 - -#define BOUNCEBOMB_EXPLODE_RADIUS 125 -#define BOUNCEBOMB_EXPLODE_DAMAGE 150 -#include "player_pickup.h" - -class CBounceBomb : public CBaseAnimating, public CDefaultPlayerPickupVPhysics -{ - DECLARE_CLASS( CBounceBomb, CBaseAnimating ); - -public: - CBounceBomb() { m_pWarnSound = NULL; m_bPlacedByPlayer = false; } - void Precache(); - void Spawn(); - void OnRestore(); - int DrawDebugTextOverlays(void); - void SetMineState( int iState ); - int GetMineState() { return m_iMineState; } - bool IsValidLocation(); - void Flip( const Vector &vecForce, const AngularImpulse &torque ); - void SearchThink(); - void BounceThink(); - void SettleThink(); - void CaptiveThink(); - void ExplodeThink(); - void ExplodeTouch( CBaseEntity *pOther ); - void CavernBounceThink(); ///< an alternative style of bouncing used for the citizen modded bouncers - bool IsAwake() { return m_bAwake; } - void Wake( bool bWake ); - float FindNearestNPC(); - void SetNearestNPC( CBaseEntity *pNearest ) { m_hNearestNPC.Set( pNearest ); } - int OnTakeDamage( const CTakeDamageInfo &info ); - bool IsFriend( CBaseEntity *pEntity ); - - void UpdateLight( bool bTurnOn, unsigned int r, unsigned int g, unsigned int b, unsigned int a ); - bool IsLightOn() { return m_hSprite.Get() != NULL; } - - void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason = PICKED_UP_BY_CANNON ); - void OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t reason ); - bool ForcePhysgunOpen( CBasePlayer *pPlayer ) { return true; } - bool HasPreferredCarryAnglesForPlayer( CBasePlayer *pPlayer ) { return true; } - virtual QAngle PreferredCarryAngles( void ) { return vec3_angle; } - CBasePlayer *HasPhysicsAttacker( float dt ); - - bool IsPlayerPlaced() { return m_bPlacedByPlayer; } - - bool CreateVPhysics() - { - VPhysicsInitNormal( SOLID_VPHYSICS, 0, false ); - return true; - } - - void Pickup(); - - void OpenHooks( bool bSilent = false ); - void CloseHooks(); - - DECLARE_DATADESC(); - - static string_t gm_iszFloorTurretClassname; - static string_t gm_iszGroundTurretClassname; - -private: - float m_flExplosionDelay; - - bool m_bAwake; - bool m_bBounce; - EHANDLE m_hNearestNPC; - EHANDLE m_hSprite; - Color m_LastSpriteColor; - - float m_flHookPositions; - int m_iHookN; - int m_iHookE; - int m_iHookS; - int m_iAllHooks; - - CSoundPatch *m_pWarnSound; - - bool m_bLockSilently; - bool m_bFoeNearest; - - float m_flIgnoreWorldTime; - - bool m_bDisarmed; - - bool m_bPlacedByPlayer; - - bool m_bHeldByPhysgun; - - int m_iFlipAttempts; - int m_iModification; - - CHandle m_hPhysicsAttacker; - float m_flLastPhysicsInfluenceTime; - - float m_flTimeGrabbed; - IPhysicsConstraint *m_pConstraint; - int m_iMineState; - - COutputEvent m_OnPulledUp; - void InputDisarm( inputdata_t &inputdata ); -}; - - - -#endif // COMBINE_MINE_H diff --git a/game/server/hl2/energy_wave.h b/game/server/hl2/energy_wave.h deleted file mode 100644 index fa7d92f7d..000000000 --- a/game/server/hl2/energy_wave.h +++ /dev/null @@ -1,37 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ENERGYWAVE_H -#define ENERGYWAVE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "basecombatweapon.h" -#include "energy_wave.h" - - -//----------------------------------------------------------------------------- -// Purpose: Shield -//----------------------------------------------------------------------------- -class CEnergyWave : public CBaseEntity -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( CEnergyWave, CBaseEntity ); - DECLARE_SERVERCLASS(); - -public: - void Spawn( void ); - void Precache( void ); - -public: - static CEnergyWave* Create( CBaseEntity *pentOwner ); -}; - - -#endif //ENERGYWAVE_H diff --git a/game/server/hl2/env_alyxemp.cpp b/game/server/hl2/env_alyxemp.cpp deleted file mode 100644 index 9a14a7230..000000000 --- a/game/server/hl2/env_alyxemp.cpp +++ /dev/null @@ -1,272 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Alyx's EMP effect -// -//=============================================================================// - -#include "cbase.h" -#include "env_alyxemp_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define EMP_BEAM_SPRITE "effects/laser1.vmt" - - -LINK_ENTITY_TO_CLASS( env_alyxemp, CAlyxEmpEffect ); - -BEGIN_DATADESC( CAlyxEmpEffect ) - - DEFINE_KEYFIELD( m_nType, FIELD_INTEGER, "Type" ), - DEFINE_KEYFIELD( m_strTargetName, FIELD_STRING, "EndTargetName" ), - - DEFINE_FIELD( m_nState, FIELD_INTEGER ), - DEFINE_FIELD( m_flDuration, FIELD_FLOAT ), - DEFINE_FIELD( m_flStartTime, FIELD_TIME ), - DEFINE_FIELD( m_hTargetEnt, FIELD_EHANDLE ), - DEFINE_FIELD( m_hBeam, FIELD_EHANDLE ), - - DEFINE_FIELD( m_iState, FIELD_INTEGER ), - DEFINE_FIELD( m_bAutomated, FIELD_BOOLEAN ), - - DEFINE_THINKFUNC( AutomaticThink ), - - DEFINE_INPUTFUNC( FIELD_FLOAT, "StartCharge", InputStartCharge ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartDischarge", InputStartDischarge ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "Stop", InputStop ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetTargetEnt", InputSetTargetEnt ), - -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CAlyxEmpEffect, DT_AlyxEmpEffect ) - SendPropInt( SENDINFO(m_nState), 8, SPROP_UNSIGNED), - SendPropFloat( SENDINFO(m_flDuration), 0, SPROP_NOSCALE), - SendPropFloat( SENDINFO(m_flStartTime), 0, SPROP_NOSCALE), -END_SEND_TABLE() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAlyxEmpEffect::Spawn( void ) -{ - Precache(); - - // No model but we still need to force this! - AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); - - // No shadows - AddEffects( EF_NOSHADOW | EF_NORECEIVESHADOW ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAlyxEmpEffect::Activate( void ) -{ - // Start out with a target entity - SetTargetEntity( STRING(m_strTargetName) ); - - BaseClass::Activate(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *szEntityName - -//----------------------------------------------------------------------------- -void CAlyxEmpEffect::SetTargetEntity( const char *szEntityName ) -{ - // Find and store off our target entity - CBaseEntity *pTargetEnt = NULL; - if ( szEntityName && szEntityName[0] ) - { - pTargetEnt = gEntList.FindEntityByName( NULL, szEntityName ); - - if ( pTargetEnt == NULL ) - { - Assert(0); - DevMsg( "Unable to find env_alyxemp (%s) target %s!\n", GetEntityName().ToCStr(), szEntityName ); - } - } - - SetTargetEntity( pTargetEnt ); -} - -//----------------------------------------------------------------------------- -// Passing NULL is ok! -//----------------------------------------------------------------------------- -void CAlyxEmpEffect::SetTargetEntity( CBaseEntity *pTarget ) -{ - m_hTargetEnt.Set( pTarget ); -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -void CAlyxEmpEffect::ActivateAutomatic( CBaseEntity *pAlyx, CBaseEntity *pTarget ) -{ - Assert( pAlyx->GetBaseAnimating() != NULL ); - - SetParent( pAlyx, pAlyx->GetBaseAnimating()->LookupAttachment("LeftHand") ); - SetLocalOrigin( vec3_origin ); - - m_iState = ALYXEMP_STATE_OFF; - SetTargetEntity( pTarget ); - SetThink( &CAlyxEmpEffect::AutomaticThink ); - SetNextThink( gpGlobals->curtime ); - - m_bAutomated = true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAlyxEmpEffect::AutomaticThink() -{ - bool bSetNextThink = true; - - switch( m_iState ) - { - case ALYXEMP_STATE_OFF: - StartCharge( 0.05f ); - break; - - case ALYXEMP_STATE_CHARGING: - StartDischarge(); - break; - - case ALYXEMP_STATE_DISCHARGING: - Stop( 1.0f ); - bSetNextThink = false; - break; - } - - m_iState++; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAlyxEmpEffect::Precache( void ) -{ - PrecacheModel( EMP_BEAM_SPRITE ); - - PrecacheScriptSound( "AlyxEmp.Charge" ); - PrecacheScriptSound( "AlyxEmp.Discharge" ); - PrecacheScriptSound( "AlyxEmp.Stop" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAlyxEmpEffect::InputStartCharge( inputdata_t &inputdata ) -{ - StartCharge( inputdata.value.Float() ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAlyxEmpEffect::StartCharge( float flDuration ) -{ - EmitSound( "AlyxEmp.Charge" ); - - m_nState = (int)ALYXEMP_STATE_CHARGING; - m_flDuration = flDuration; - m_flStartTime = gpGlobals->curtime; - - if( m_bAutomated ) - { - SetNextThink( gpGlobals->curtime + m_flDuration ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAlyxEmpEffect::InputStartDischarge( inputdata_t &inputdata ) -{ - StartDischarge(); -} - -void CAlyxEmpEffect::StartDischarge() -{ - EmitSound( "AlyxEmp.Discharge" ); - - m_nState = (int)ALYXEMP_STATE_DISCHARGING; - m_flStartTime = gpGlobals->curtime; - - // Beam effects on the target entity! - if ( !m_hBeam && m_hTargetEnt ) - { - // Check to store off our view model index - m_hBeam = CBeam::BeamCreate( EMP_BEAM_SPRITE, 8 ); - - if ( m_hBeam != NULL ) - { - m_hBeam->PointEntInit( m_hTargetEnt->GetAbsOrigin(), this ); - m_hBeam->SetStartEntity( m_hTargetEnt ); - m_hBeam->SetWidth( 4 ); - m_hBeam->SetEndWidth( 8 ); - m_hBeam->SetBrightness( 255 ); - m_hBeam->SetColor( 255, 255, 255 ); - m_hBeam->LiveForTime( 999.0f ); - m_hBeam->RelinkBeam(); - m_hBeam->SetNoise( 16 ); - } - - // End hit - Vector shotDir = ( GetAbsOrigin() - m_hTargetEnt->GetAbsOrigin() ); - VectorNormalize( shotDir ); - - CPVSFilter filter( m_hTargetEnt->GetAbsOrigin() ); - te->GaussExplosion( filter, 0.0f, m_hTargetEnt->GetAbsOrigin() - ( shotDir * 4.0f ), RandomVector(-1.0f, 1.0f), 0 ); - } - - if( m_bAutomated ) - { - SetNextThink( gpGlobals->curtime + 0.5f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAlyxEmpEffect::InputStop( inputdata_t &inputdata ) -{ - float flDuration = inputdata.value.Float(); - - Stop( flDuration ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAlyxEmpEffect::Stop( float flDuration ) -{ - EmitSound( "AlyxEmp.Stop" ); - - m_nState = (int)ALYXEMP_STATE_OFF; - m_flDuration = flDuration; - m_flStartTime = gpGlobals->curtime; - - if ( m_hBeam != NULL ) - { - UTIL_Remove( m_hBeam ); - m_hBeam = NULL; - } - - if( m_bAutomated ) - { - SetThink( &CAlyxEmpEffect::SUB_Remove ); - SetNextThink( gpGlobals->curtime + flDuration + 1.0f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CAlyxEmpEffect::InputSetTargetEnt( inputdata_t &inputdata ) -{ - SetTargetEntity( inputdata.value.String() ); -} diff --git a/game/server/hl2/env_headcrabcanister.cpp b/game/server/hl2/env_headcrabcanister.cpp deleted file mode 100644 index 9f9572a91..000000000 --- a/game/server/hl2/env_headcrabcanister.cpp +++ /dev/null @@ -1,1114 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "ai_hint.h" -#include "env_headcrabcanister_shared.h" -#include "explode.h" -#include "beam_shared.h" -#include "SpriteTrail.h" -#include "ar2_explosion.h" -#include "SkyCamera.h" -#include "smoke_trail.h" -#include "ai_basenpc.h" -#include "npc_headcrab.h" -#include "ai_motor.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Models! -//----------------------------------------------------------------------------- -#define ENV_HEADCRABCANISTER_MODEL "models/props_combine/headcrabcannister01a.mdl" -#define ENV_HEADCRABCANISTER_BROKEN_MODEL "models/props_combine/headcrabcannister01b.mdl" -#define ENV_HEADCRABCANISTER_SKYBOX_MODEL "models/props_combine/headcrabcannister01a_skybox.mdl" -#define ENV_HEADCRABCANISTER_INCOMING_SOUND_TIME 1.0f - -ConVar sk_env_headcrabcanister_shake_amplitude( "sk_env_headcrabcanister_shake_amplitude", "50" ); -ConVar sk_env_headcrabcanister_shake_radius( "sk_env_headcrabcanister_shake_radius", "1024" ); -ConVar sk_env_headcrabcanister_shake_radius_vehicle( "sk_env_headcrabcanister_shake_radius_vehicle", "2500" ); - -#define ENV_HEADCRABCANISTER_TRAIL_TIME 3.0f - -//----------------------------------------------------------------------------- -// Spawn flags -//----------------------------------------------------------------------------- -enum -{ - SF_NO_IMPACT_SOUND = 0x1, - SF_NO_LAUNCH_SOUND = 0x2, - SF_START_IMPACTED = 0x1000, - SF_LAND_AT_INITIAL_POSITION = 0x2000, - SF_WAIT_FOR_INPUT_TO_OPEN = 0x4000, - SF_WAIT_FOR_INPUT_TO_SPAWN_HEADCRABS = 0x8000, - SF_NO_SMOKE = 0x10000, - SF_NO_SHAKE = 0x20000, - SF_REMOVE_ON_IMPACT = 0x40000, - SF_NO_IMPACT_EFFECTS = 0x80000, -}; - - -//----------------------------------------------------------------------------- -// Headcrab types -//----------------------------------------------------------------------------- -static const char *s_pHeadcrabClass[] = -{ - "npc_headcrab", - "npc_headcrab_fast", - "npc_headcrab_poison", -}; - - -//----------------------------------------------------------------------------- -// Context think -//----------------------------------------------------------------------------- -static const char *s_pOpenThinkContext = "OpenThink"; -static const char *s_pHeadcrabThinkContext = "HeadcrabThink"; - - -//----------------------------------------------------------------------------- -// HeadcrabCanister Class -//----------------------------------------------------------------------------- -class CEnvHeadcrabCanister : public CBaseAnimating -{ - DECLARE_CLASS( CEnvHeadcrabCanister, CBaseAnimating ); - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - -public: - - // Initialization - CEnvHeadcrabCanister(); - - virtual void Precache( void ); - virtual void Spawn( void ); - virtual void UpdateOnRemove(); - - virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ); - -private: - void InputFireCanister( inputdata_t &inputdata ); - void InputOpenCanister( inputdata_t &inputdata ); - void InputSpawnHeadcrabs( inputdata_t &inputdata ); - void InputStopSmoke( inputdata_t &inputdata ); - - // Think(s) - void HeadcrabCanisterSkyboxThink( void ); - void HeadcrabCanisterWorldThink( void ); - void HeadcrabCanisterSpawnHeadcrabThink(); - void HeadcrabCanisterSkyboxOnlyThink( void ); - void HeadcrabCanisterSkyboxRestartThink( void ); - void WaitForOpenSequenceThink(); - - // Place the canister in the world - CSkyCamera* PlaceCanisterInWorld(); - - // Check for impacts - void TestForCollisionsAgainstEntities( const Vector &vecEndPosition ); - void TestForCollisionsAgainstWorld( const Vector &vecEndPosition ); - - // Figure out where we enter the world - void ComputeWorldEntryPoint( Vector *pStartPosition, QAngle *pStartAngles, Vector *pStartDirection ); - - // Blows up! - void Detonate( void ); - - // Landed! - void SetLanded( void ); - void Landed( void ); - - // Open! - void OpenCanister( void ); - void CanisterFinishedOpening(); - - // Set up the world model - void SetupWorldModel(); - - // Start spawning headcrabs - void StartSpawningHeadcrabs( float flDelay ); - -private: - CNetworkVar( bool, m_bLanded ); - - CNetworkVarEmbedded( CEnvHeadcrabCanisterShared, m_Shared ); - CHandle m_hTrail; - CHandle m_hSmokeTrail; - int m_nHeadcrabType; - int m_nHeadcrabCount; - Vector m_vecImpactPosition; - float m_flDamageRadius; - float m_flDamage; - bool m_bIncomingSoundStarted; - bool m_bHasDetonated; - bool m_bLaunched; - bool m_bOpened; - float m_flSmokeLifetime; - string_t m_iszLaunchPositionName; - - COutputEHANDLE m_OnLaunched; - COutputEvent m_OnImpacted; - COutputEvent m_OnOpened; - - // Only for skybox only cannisters. - float m_flMinRefireTime; - float m_flMaxRefireTime; - int m_nSkyboxCannisterCount; -}; - - -//============================================================================= -// -// HeadcrabCanister Functions -// - -LINK_ENTITY_TO_CLASS( env_headcrabcanister, CEnvHeadcrabCanister ); - -BEGIN_DATADESC( CEnvHeadcrabCanister ) - - DEFINE_FIELD( m_bLanded, FIELD_BOOLEAN ), - DEFINE_EMBEDDED( m_Shared ), - DEFINE_FIELD( m_hTrail, FIELD_EHANDLE ), - DEFINE_FIELD( m_hSmokeTrail, FIELD_EHANDLE ), - DEFINE_KEYFIELD( m_nHeadcrabType, FIELD_INTEGER, "HeadcrabType" ), - DEFINE_KEYFIELD( m_nHeadcrabCount, FIELD_INTEGER, "HeadcrabCount" ), - DEFINE_KEYFIELD( m_flSmokeLifetime, FIELD_FLOAT, "SmokeLifetime" ), - DEFINE_KEYFIELD( m_iszLaunchPositionName, FIELD_STRING, "LaunchPositionName" ), - DEFINE_FIELD( m_vecImpactPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_bIncomingSoundStarted, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bHasDetonated, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bLaunched, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bOpened, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_flMinRefireTime, FIELD_FLOAT, "MinSkyboxRefireTime" ), - DEFINE_KEYFIELD( m_flMaxRefireTime, FIELD_FLOAT, "MaxSkyboxRefireTime" ), - DEFINE_KEYFIELD( m_nSkyboxCannisterCount, FIELD_INTEGER, "SkyboxCannisterCount" ), - DEFINE_KEYFIELD( m_flDamageRadius, FIELD_FLOAT, "DamageRadius" ), - DEFINE_KEYFIELD( m_flDamage, FIELD_FLOAT, "Damage" ), - - // Function Pointers. - DEFINE_FUNCTION( HeadcrabCanisterSkyboxThink ), - DEFINE_FUNCTION( HeadcrabCanisterWorldThink ), - DEFINE_FUNCTION( HeadcrabCanisterSpawnHeadcrabThink ), - DEFINE_FUNCTION( WaitForOpenSequenceThink ), - DEFINE_FUNCTION( HeadcrabCanisterSkyboxOnlyThink ), - DEFINE_FUNCTION( HeadcrabCanisterSkyboxRestartThink ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "FireCanister", InputFireCanister ), - DEFINE_INPUTFUNC( FIELD_VOID, "OpenCanister", InputOpenCanister ), - DEFINE_INPUTFUNC( FIELD_VOID, "SpawnHeadcrabs", InputSpawnHeadcrabs ), - DEFINE_INPUTFUNC( FIELD_VOID, "StopSmoke", InputStopSmoke ), - - // Outputs - DEFINE_OUTPUT( m_OnLaunched, "OnLaunched" ), - DEFINE_OUTPUT( m_OnImpacted, "OnImpacted" ), - DEFINE_OUTPUT( m_OnOpened, "OnOpened" ), - -END_DATADESC() - - -EXTERN_SEND_TABLE(DT_EnvHeadcrabCanisterShared); - -IMPLEMENT_SERVERCLASS_ST( CEnvHeadcrabCanister, DT_EnvHeadcrabCanister ) - SendPropDataTable( SENDINFO_DT( m_Shared ), &REFERENCE_SEND_TABLE(DT_EnvHeadcrabCanisterShared) ), - SendPropBool( SENDINFO( m_bLanded ) ), -END_SEND_TABLE() - - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CEnvHeadcrabCanister::CEnvHeadcrabCanister() -{ - m_flMinRefireTime = -1.0f; - m_flMaxRefireTime = -1.0f; -} - - -//----------------------------------------------------------------------------- -// Precache! -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanister::Precache( void ) -{ - BaseClass::Precache(); - PrecacheModel( ENV_HEADCRABCANISTER_MODEL ); - PrecacheModel( ENV_HEADCRABCANISTER_BROKEN_MODEL ); - PrecacheModel( ENV_HEADCRABCANISTER_SKYBOX_MODEL ); - PrecacheModel("sprites/smoke.vmt"); - - PrecacheScriptSound( "HeadcrabCanister.LaunchSound" ); - PrecacheScriptSound( "HeadcrabCanister.AfterLanding" ); - PrecacheScriptSound( "HeadcrabCanister.Explosion" ); - PrecacheScriptSound( "HeadcrabCanister.IncomingSound" ); - PrecacheScriptSound( "HeadcrabCanister.SkyboxExplosion" ); - PrecacheScriptSound( "HeadcrabCanister.Open" ); - - UTIL_PrecacheOther( s_pHeadcrabClass[m_nHeadcrabType] ); -} - - -//----------------------------------------------------------------------------- -// Spawn! -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanister::Spawn( void ) -{ - Precache(); - BaseClass::Spawn(); - - // Do we have a position to launch from? - if ( m_iszLaunchPositionName != NULL_STRING ) - { - // It doesn't have any real presence at first. - SetSolid( SOLID_NONE ); - - m_vecImpactPosition = GetAbsOrigin(); - m_bIncomingSoundStarted = false; - m_bLanded = false; - m_bHasDetonated = false; - m_bOpened = false; - } - else if ( !HasSpawnFlags( SF_START_IMPACTED ) ) - { - // It doesn't have any real presence at first. - SetSolid( SOLID_NONE ); - - if ( !HasSpawnFlags( SF_LAND_AT_INITIAL_POSITION ) ) - { - Vector vecForward; - GetVectors( &vecForward, NULL, NULL ); - vecForward *= -1.0f; - - trace_t trace; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + vecForward * 10000, MASK_NPCWORLDSTATIC, - this, COLLISION_GROUP_NONE, &trace ); - - m_vecImpactPosition = trace.endpos; - } - else - { - m_vecImpactPosition = GetAbsOrigin(); - } - - m_bIncomingSoundStarted = false; - m_bLanded = false; - m_bHasDetonated = false; - m_bOpened = false; - } - else - { - m_bHasDetonated = true; - m_bIncomingSoundStarted = true; - m_bOpened = false; - m_vecImpactPosition = GetAbsOrigin(); - Landed(); - } -} - - -//----------------------------------------------------------------------------- -// On remove! -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanister::UpdateOnRemove() -{ - BaseClass::UpdateOnRemove(); - StopSound( "HeadcrabCanister.AfterLanding" ); - if ( m_hTrail ) - { - UTIL_Remove( m_hTrail ); - m_hTrail = NULL; - } - if ( m_hSmokeTrail ) - { - UTIL_Remove( m_hSmokeTrail ); - m_hSmokeTrail = NULL; - } -} - - -//----------------------------------------------------------------------------- -// Set up the world model -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanister::SetupWorldModel() -{ - SetModel( ENV_HEADCRABCANISTER_MODEL ); - SetSolid( SOLID_BBOX ); - - float flRadius = CollisionProp()->BoundingRadius(); - Vector vecMins( -flRadius, -flRadius, -flRadius ); - Vector vecMaxs( flRadius, flRadius, flRadius ); - SetSize( vecMins, vecMaxs ); - -} - - -//----------------------------------------------------------------------------- -// Figure out where we enter the world -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanister::ComputeWorldEntryPoint( Vector *pStartPosition, QAngle *pStartAngles, Vector *pStartDirection ) -{ - SetupWorldModel(); - - Vector vecForward; - GetVectors( &vecForward, NULL, NULL ); - - // Raycast up to the place where we should start from (start raycast slightly off the ground, - // since it'll be buried in the ground oftentimes) - trace_t tr; - CTraceFilterWorldOnly filter; - UTIL_TraceLine( GetAbsOrigin() + vecForward * 100, GetAbsOrigin() + vecForward * 10000, - CONTENTS_SOLID, &filter, &tr ); - - *pStartPosition = tr.endpos; - *pStartAngles = GetAbsAngles(); - VectorMultiply( vecForward, -1.0f, *pStartDirection ); -} - - -//----------------------------------------------------------------------------- -// Place the canister in the world -//----------------------------------------------------------------------------- -CSkyCamera *CEnvHeadcrabCanister::PlaceCanisterInWorld() -{ - CSkyCamera *pCamera = NULL; - - // Are we launching from a point? If so, use that point. - if ( m_iszLaunchPositionName != NULL_STRING ) - { - // Get the launch position entity - CBaseEntity *pLaunchPos = gEntList.FindEntityByName( NULL, m_iszLaunchPositionName ); - if ( !pLaunchPos ) - { - Warning("%s (%s) could not find an entity matching LaunchPositionName of '%s'\n", GetEntityName().ToCStr(), GetDebugName(), STRING(m_iszLaunchPositionName) ); - SUB_Remove(); - } - else - { - SetupWorldModel(); - - Vector vecForward, vecImpactDirection; - GetVectors( &vecForward, NULL, NULL ); - VectorMultiply( vecForward, -1.0f, vecImpactDirection ); - - m_Shared.InitInWorld( gpGlobals->curtime, pLaunchPos->GetAbsOrigin(), GetAbsAngles(), - vecImpactDirection, m_vecImpactPosition, true ); - SetThink( &CEnvHeadcrabCanister::HeadcrabCanisterWorldThink ); - SetNextThink( gpGlobals->curtime ); - } - } - else if ( DetectInSkybox() ) - { - pCamera = GetEntitySkybox(); - - SetModel( ENV_HEADCRABCANISTER_SKYBOX_MODEL ); - SetSolid( SOLID_NONE ); - - Vector vecForward; - GetVectors( &vecForward, NULL, NULL ); - vecForward *= -1.0f; - - m_Shared.InitInSkybox( gpGlobals->curtime, m_vecImpactPosition, GetAbsAngles(), vecForward, - m_vecImpactPosition, pCamera->m_skyboxData.origin, pCamera->m_skyboxData.scale ); - AddEFlags( EFL_IN_SKYBOX ); - SetThink( &CEnvHeadcrabCanister::HeadcrabCanisterSkyboxOnlyThink ); - SetNextThink( gpGlobals->curtime + m_Shared.GetEnterWorldTime() + TICK_INTERVAL ); - } - else - { - Vector vecStartPosition, vecDirection; - QAngle vecStartAngles; - ComputeWorldEntryPoint( &vecStartPosition, &vecStartAngles, &vecDirection ); - - // Figure out which skybox to place the entity in. - pCamera = GetCurrentSkyCamera(); - if ( pCamera ) - { - m_Shared.InitInSkybox( gpGlobals->curtime, vecStartPosition, vecStartAngles, vecDirection, - m_vecImpactPosition, pCamera->m_skyboxData.origin, pCamera->m_skyboxData.scale ); - - if ( m_Shared.IsInSkybox() ) - { - SetModel( ENV_HEADCRABCANISTER_SKYBOX_MODEL ); - SetSolid( SOLID_NONE ); - AddEFlags( EFL_IN_SKYBOX ); - SetThink( &CEnvHeadcrabCanister::HeadcrabCanisterSkyboxThink ); - SetNextThink( gpGlobals->curtime + m_Shared.GetEnterWorldTime() ); - } - else - { - SetThink( &CEnvHeadcrabCanister::HeadcrabCanisterWorldThink ); - SetNextThink( gpGlobals->curtime ); - } - } - else - { - m_Shared.InitInWorld( gpGlobals->curtime, vecStartPosition, vecStartAngles, - vecDirection, m_vecImpactPosition ); - SetThink( &CEnvHeadcrabCanister::HeadcrabCanisterWorldThink ); - SetNextThink( gpGlobals->curtime ); - } - } - - Vector vecEndPosition; - QAngle vecEndAngles; - m_Shared.GetPositionAtTime( gpGlobals->curtime, vecEndPosition, vecEndAngles ); - SetAbsOrigin( vecEndPosition ); - SetAbsAngles( vecEndAngles ); - - return pCamera; -} - - -//----------------------------------------------------------------------------- -// Fires the canister! -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanister::InputFireCanister( inputdata_t &inputdata ) -{ - if (m_bLaunched) - return; - - m_bLaunched = true; - - if ( HasSpawnFlags( SF_START_IMPACTED ) ) - { - StartSpawningHeadcrabs( 0.01f ); - return; - } - - // Play a firing sound - CPASAttenuationFilter filter( this, ATTN_NONE ); - - if ( !HasSpawnFlags( SF_NO_LAUNCH_SOUND ) ) - { - EmitSound( filter, entindex(), "HeadcrabCanister.LaunchSound" ); - } - - // Place the canister - CSkyCamera *pCamera = PlaceCanisterInWorld(); - - // Hook up a smoke trail - m_hTrail = CSpriteTrail::SpriteTrailCreate( "sprites/smoke.vmt", GetAbsOrigin(), true ); - m_hTrail->SetTransparency( kRenderTransAdd, 224, 224, 255, 255, kRenderFxNone ); - m_hTrail->SetAttachment( this, 0 ); - m_hTrail->SetStartWidth( 32.0 ); - m_hTrail->SetEndWidth( 200.0 ); - m_hTrail->SetStartWidthVariance( 15.0f ); - m_hTrail->SetTextureResolution( 0.002 ); - m_hTrail->SetLifeTime( ENV_HEADCRABCANISTER_TRAIL_TIME ); - m_hTrail->SetMinFadeLength( 1000.0f ); - - if ( pCamera && m_Shared.IsInSkybox() ) - { - m_hTrail->SetSkybox( pCamera->m_skyboxData.origin, pCamera->m_skyboxData.scale ); - } - - // Fire that output! - m_OnLaunched.Set( this, this, this ); -} - - -//----------------------------------------------------------------------------- -// Opens the canister! -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanister::InputOpenCanister( inputdata_t &inputdata ) -{ - if ( m_bLanded && !m_bOpened && HasSpawnFlags( SF_WAIT_FOR_INPUT_TO_OPEN ) ) - { - OpenCanister(); - } -} - - -//----------------------------------------------------------------------------- -// Spawns headcrabs -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanister::InputSpawnHeadcrabs( inputdata_t &inputdata ) -{ - if ( m_bLanded && m_bOpened && HasSpawnFlags( SF_WAIT_FOR_INPUT_TO_SPAWN_HEADCRABS ) ) - { - StartSpawningHeadcrabs( 0.01f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanister::InputStopSmoke( inputdata_t &inputdata ) -{ - if ( m_hSmokeTrail != NULL ) - { - UTIL_Remove( m_hSmokeTrail ); - m_hSmokeTrail = NULL; - } -} - -//============================================================================= -// -// Enumerator for swept bbox collision. -// -class CCollideList : public IEntityEnumerator -{ -public: - CCollideList( Ray_t *pRay, CBaseEntity* pIgnoreEntity, int nContentsMask ) : - m_Entities( 0, 32 ), m_pIgnoreEntity( pIgnoreEntity ), - m_nContentsMask( nContentsMask ), m_pRay(pRay) {} - - virtual bool EnumEntity( IHandleEntity *pHandleEntity ) - { - // Don't bother with the ignore entity. - if ( pHandleEntity == m_pIgnoreEntity ) - return true; - - Assert( pHandleEntity ); - - trace_t tr; - enginetrace->ClipRayToEntity( *m_pRay, m_nContentsMask, pHandleEntity, &tr ); - if (( tr.fraction < 1.0f ) || (tr.startsolid) || (tr.allsolid)) - { - CBaseEntity *pEntity = gEntList.GetBaseEntity( pHandleEntity->GetRefEHandle() ); - m_Entities.AddToTail( pEntity ); - } - - return true; - } - - CUtlVector m_Entities; - -private: - CBaseEntity *m_pIgnoreEntity; - int m_nContentsMask; - Ray_t *m_pRay; -}; - - -//----------------------------------------------------------------------------- -// Test for impact! -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanister::TestForCollisionsAgainstEntities( const Vector &vecEndPosition ) -{ - // Debugging!! -// NDebugOverlay::Box( GetAbsOrigin(), m_vecMin * 0.5f, m_vecMax * 0.5f, 255, 255, 0, 0, 5 ); -// NDebugOverlay::Box( vecEndPosition, m_vecMin, m_vecMax, 255, 0, 0, 0, 5 ); - - float flRadius = CollisionProp()->BoundingRadius(); - Vector vecMins( -flRadius, -flRadius, -flRadius ); - Vector vecMaxs( flRadius, flRadius, flRadius ); - - Ray_t ray; - ray.Init( GetAbsOrigin(), vecEndPosition, vecMins, vecMaxs ); - - CCollideList collideList( &ray, this, MASK_SOLID ); - enginetrace->EnumerateEntities( ray, false, &collideList ); - - float flDamage = m_flDamage; - - // Now get each entity and react accordinly! - for( int iEntity = collideList.m_Entities.Count(); --iEntity >= 0; ) - { - CBaseEntity *pEntity = collideList.m_Entities[iEntity]; - Vector vecForceDir = m_Shared.m_vecDirection; - - // Check for a physics object and apply force! - IPhysicsObject *pPhysObject = pEntity->VPhysicsGetObject(); - if ( pPhysObject ) - { - float flMass = PhysGetEntityMass( pEntity ); - vecForceDir *= flMass * 750; - pPhysObject->ApplyForceCenter( vecForceDir ); - } - - if ( pEntity->m_takedamage && ( m_flDamage != 0.0f ) ) - { - CTakeDamageInfo info( this, this, flDamage, DMG_BLAST ); - CalculateExplosiveDamageForce( &info, vecForceDir, pEntity->GetAbsOrigin() ); - pEntity->TakeDamage( info ); - } - } -} - - -//----------------------------------------------------------------------------- -// Test for impact! -//----------------------------------------------------------------------------- -#define INNER_RADIUS_FRACTION 0.25f - -void CEnvHeadcrabCanister::TestForCollisionsAgainstWorld( const Vector &vecEndPosition ) -{ - // Splash damage! - // Iterate on all entities in the vicinity. - float flDamageRadius = m_flDamageRadius; - float flDamage = m_flDamage; - - CBaseEntity *pEntity; - for ( CEntitySphereQuery sphere( vecEndPosition, flDamageRadius ); ( pEntity = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() ) - { - if ( pEntity == this ) - continue; - - if ( !pEntity->IsSolid() ) - continue; - - // Get distance to object and use it as a scale value. - Vector vecSegment; - VectorSubtract( pEntity->GetAbsOrigin(), vecEndPosition, vecSegment ); - float flDistance = VectorNormalize( vecSegment ); - - float flFactor = 1.0f / ( flDamageRadius * (INNER_RADIUS_FRACTION - 1) ); - flFactor *= flFactor; - float flScale = flDistance - flDamageRadius; - flScale *= flScale * flFactor; - if ( flScale > 1.0f ) - { - flScale = 1.0f; - } - - // Check for a physics object and apply force! - Vector vecForceDir = vecSegment; - IPhysicsObject *pPhysObject = pEntity->VPhysicsGetObject(); - if ( pPhysObject ) - { - // Send it flying!!! - float flMass = PhysGetEntityMass( pEntity ); - vecForceDir *= flMass * 750 * flScale; - pPhysObject->ApplyForceCenter( vecForceDir ); - } - - if ( pEntity->m_takedamage && ( m_flDamage != 0.0f ) ) - { - CTakeDamageInfo info( this, this, flDamage * flScale, DMG_BLAST ); - CalculateExplosiveDamageForce( &info, vecSegment, pEntity->GetAbsOrigin() ); - pEntity->TakeDamage( info ); - } - - if ( pEntity->IsPlayer() && !(static_cast(pEntity)->IsInAVehicle()) ) - { - if (vecSegment.z < 0.1f) - { - vecSegment.z = 0.1f; - VectorNormalize( vecSegment ); - } - float flAmount = SimpleSplineRemapVal( flScale, 0.0f, 1.0f, 250.0f, 1000.0f ); - pEntity->ApplyAbsVelocityImpulse( vecSegment * flAmount ); - } - } -} - - -//----------------------------------------------------------------------------- -// Headcrab creation -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanister::HeadcrabCanisterSpawnHeadcrabThink() -{ - Vector vecSpawnPosition; - QAngle vecSpawnAngles; - - --m_nHeadcrabCount; - - int nHeadCrabAttachment = LookupAttachment( "headcrab" ); - if ( GetAttachment( nHeadCrabAttachment, vecSpawnPosition, vecSpawnAngles ) ) - { - CBaseEntity *pEnt = CreateEntityByName( s_pHeadcrabClass[m_nHeadcrabType] ); - CBaseHeadcrab *pHeadCrab = assert_cast(pEnt); - - // Necessary to get it to eject properly (don't allow the NPC - // to override the spawn position specified). - pHeadCrab->AddSpawnFlags( SF_NPC_FALL_TO_GROUND ); - - // So we don't collide with the canister - // NOTE: Hierarchical attachment is necessary here to get the animations to work - pHeadCrab->SetOwnerEntity( this ); - DispatchSpawn( pHeadCrab ); - pHeadCrab->SetParent( this, nHeadCrabAttachment ); - pHeadCrab->SetLocalOrigin( vec3_origin ); - pHeadCrab->SetLocalAngles( vec3_angle ); - pHeadCrab->CrawlFromCanister(); - } - - if ( m_nHeadcrabCount != 0 ) - { - float flWaitTime = random->RandomFloat( 1.0f, 2.0f ); - SetContextThink( &CEnvHeadcrabCanister::HeadcrabCanisterSpawnHeadcrabThink, gpGlobals->curtime + flWaitTime, s_pHeadcrabThinkContext ); - } - else - { - SetContextThink( NULL, gpGlobals->curtime, s_pHeadcrabThinkContext ); - } -} - - -//----------------------------------------------------------------------------- -// Start spawning headcrabs -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanister::StartSpawningHeadcrabs( float flDelay ) -{ - if ( !m_bLanded || !m_bOpened || m_nHeadcrabCount == 0 ) - return; - - if ( m_nHeadcrabCount != 0 ) - { - SetContextThink( &CEnvHeadcrabCanister::HeadcrabCanisterSpawnHeadcrabThink, gpGlobals->curtime + flDelay, s_pHeadcrabThinkContext ); - } -} - - -//----------------------------------------------------------------------------- -// Canister finished opening -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanister::CanisterFinishedOpening( void ) -{ - ResetSequence( LookupSequence( "idle_open" ) ); - m_OnOpened.FireOutput( this, this, 0 ); - m_bOpened = true; - SetContextThink( NULL, gpGlobals->curtime, s_pOpenThinkContext ); - - if ( !HasSpawnFlags( SF_START_IMPACTED ) ) - { - if ( !HasSpawnFlags( SF_WAIT_FOR_INPUT_TO_SPAWN_HEADCRABS ) ) - { - StartSpawningHeadcrabs( 3.0f ); - } - } -} - - -//----------------------------------------------------------------------------- -// Finish the opening sequence -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanister::WaitForOpenSequenceThink() -{ - StudioFrameAdvance(); - if ( ( GetSequence() == LookupSequence( "open" ) ) && IsSequenceFinished() ) - { - CanisterFinishedOpening(); - } - else - { - SetContextThink( &CEnvHeadcrabCanister::WaitForOpenSequenceThink, gpGlobals->curtime + 0.01f, s_pOpenThinkContext ); - } -} - - -//----------------------------------------------------------------------------- -// Open the canister! -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanister::OpenCanister( void ) -{ - if ( m_bOpened ) - return; - - int nOpenSequence = LookupSequence( "open" ); - if ( nOpenSequence != ACT_INVALID ) - { - EmitSound( "HeadcrabCanister.Open" ); - - ResetSequence( nOpenSequence ); - SetContextThink( &CEnvHeadcrabCanister::WaitForOpenSequenceThink, gpGlobals->curtime + 0.01f, s_pOpenThinkContext ); - } - else - { - CanisterFinishedOpening(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanister::SetLanded( void ) -{ - SetAbsOrigin( m_vecImpactPosition ); - SetModel( ENV_HEADCRABCANISTER_BROKEN_MODEL ); - SetMoveType( MOVETYPE_NONE ); - SetSolid( SOLID_VPHYSICS ); - VPhysicsInitStatic(); - - AddEffects( EF_NOINTERP ); - m_bLanded = true; -} - -//----------------------------------------------------------------------------- -// Landed! -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanister::Landed( void ) -{ - EmitSound( "HeadcrabCanister.AfterLanding" ); - - // Lock us now that we've stopped - SetLanded(); - - // Hook the follow trail to the lead of the canister (which should be buried) - // to hide problems with the edge of the follow trail - if (m_hTrail) - { - m_hTrail->SetAttachment( this, LookupAttachment("trail") ); - } - - // Start smoke, unless we don't want it - if ( !HasSpawnFlags( SF_NO_SMOKE ) ) - { - // Create the smoke trail to obscure the headcrabs - m_hSmokeTrail = SmokeTrail::CreateSmokeTrail(); - m_hSmokeTrail->FollowEntity( this, "smoke" ); - - m_hSmokeTrail->m_SpawnRate = 8; - m_hSmokeTrail->m_ParticleLifetime = 2.0f; - - m_hSmokeTrail->m_StartColor.Init( 0.7f, 0.7f, 0.7f ); - m_hSmokeTrail->m_EndColor.Init( 0.6, 0.6, 0.6 ); - - m_hSmokeTrail->m_StartSize = 32; - m_hSmokeTrail->m_EndSize = 64; - m_hSmokeTrail->m_SpawnRadius= 8; - m_hSmokeTrail->m_MinSpeed = 0; - m_hSmokeTrail->m_MaxSpeed = 8; - m_hSmokeTrail->m_MinDirectedSpeed = 32; - m_hSmokeTrail->m_MaxDirectedSpeed = 64; - m_hSmokeTrail->m_Opacity = 0.35f; - - m_hSmokeTrail->SetLifetime( m_flSmokeLifetime ); - } - - SetThink( NULL ); - - if ( !HasSpawnFlags( SF_WAIT_FOR_INPUT_TO_OPEN ) ) - { - if ( HasSpawnFlags( SF_START_IMPACTED ) ) - { - CanisterFinishedOpening( ); - } - else - { - OpenCanister(); - } - } -} - - -//----------------------------------------------------------------------------- -// Creates the explosion effect -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanister::Detonate( ) -{ - // Send the impact output - m_OnImpacted.FireOutput( this, this, 0 ); - - if ( !HasSpawnFlags( SF_NO_IMPACT_SOUND ) ) - { - StopSound( "HeadcrabCanister.IncomingSound" ); - EmitSound( "HeadcrabCanister.Explosion" ); - } - - // If we're supposed to be removed, do that now - if ( HasSpawnFlags( SF_REMOVE_ON_IMPACT ) ) - { - SetAbsOrigin( m_vecImpactPosition ); - SetModel( ENV_HEADCRABCANISTER_BROKEN_MODEL ); - SetMoveType( MOVETYPE_NONE ); - AddEffects( EF_NOINTERP ); - m_bLanded = true; - - // Become invisible so our trail can finish up - AddEffects( EF_NODRAW ); - SetSolidFlags( FSOLID_NOT_SOLID ); - - SetThink( &CEnvHeadcrabCanister::SUB_Remove ); - SetNextThink( gpGlobals->curtime + ENV_HEADCRABCANISTER_TRAIL_TIME ); - - return; - } - - // Test for damaging things - TestForCollisionsAgainstWorld( m_vecImpactPosition ); - - // Shake the screen unless flagged otherwise - if ( !HasSpawnFlags( SF_NO_SHAKE ) ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); - - // If the player is on foot, then do a more limited shake - float shakeRadius = ( pPlayer && pPlayer->IsInAVehicle() ) ? sk_env_headcrabcanister_shake_radius_vehicle.GetFloat() : sk_env_headcrabcanister_shake_radius.GetFloat(); - - UTIL_ScreenShake( m_vecImpactPosition, sk_env_headcrabcanister_shake_amplitude.GetFloat(), 150.0, 1.0, shakeRadius, SHAKE_START ); - } - - // Do explosion effects - if ( !HasSpawnFlags( SF_NO_IMPACT_EFFECTS ) ) - { - // Normal explosion - ExplosionCreate( m_vecImpactPosition, GetAbsAngles(), this, 50, 500, - SF_ENVEXPLOSION_NODLIGHTS | SF_ENVEXPLOSION_NOSPARKS | SF_ENVEXPLOSION_NODAMAGE | SF_ENVEXPLOSION_NOSOUND, 1300.0f ); - - // Dust explosion - AR2Explosion *pExplosion = AR2Explosion::CreateAR2Explosion( m_vecImpactPosition ); - - if( pExplosion ) - { - pExplosion->SetLifetime(10); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: This think function simulates (moves/collides) the HeadcrabCanister while in -// the world. -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanister::HeadcrabCanisterWorldThink( void ) -{ - // Get the current time. - float flTime = gpGlobals->curtime; - - Vector vecStartPosition = GetAbsOrigin(); - - // Update HeadcrabCanister position for swept collision test. - Vector vecEndPosition; - QAngle vecEndAngles; - m_Shared.GetPositionAtTime( flTime, vecEndPosition, vecEndAngles ); - - if ( !m_bIncomingSoundStarted && !HasSpawnFlags( SF_NO_IMPACT_SOUND ) ) - { - float flDistSq = ENV_HEADCRABCANISTER_INCOMING_SOUND_TIME * m_Shared.m_flFlightSpeed; - flDistSq *= flDistSq; - if ( vecEndPosition.DistToSqr(m_vecImpactPosition) <= flDistSq ) - { - // Figure out if we're close enough to play the incoming sound - EmitSound( "HeadcrabCanister.IncomingSound" ); - m_bIncomingSoundStarted = true; - } - } - - TestForCollisionsAgainstEntities( vecEndPosition ); - if ( m_Shared.DidImpact( flTime ) ) - { - if ( !m_bHasDetonated ) - { - Detonate(); - m_bHasDetonated = true; - } - - if ( !HasSpawnFlags( SF_REMOVE_ON_IMPACT ) ) - { - Landed(); - } - - return; - } - - // Always move full movement. - SetAbsOrigin( vecEndPosition ); - - // Touch triggers along the way - PhysicsTouchTriggers( &vecStartPosition ); - - SetNextThink( gpGlobals->curtime + 0.2f ); - SetAbsAngles( vecEndAngles ); - - if ( !m_bHasDetonated ) - { - if ( vecEndPosition.DistToSqr( m_vecImpactPosition ) < BoundingRadius() * BoundingRadius() ) - { - Detonate(); - m_bHasDetonated = true; - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: This think function should be called at the time when the HeadcrabCanister -// will be leaving the skybox and entering the world. -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanister::HeadcrabCanisterSkyboxThink( void ) -{ - // Use different position computation - m_Shared.ConvertFromSkyboxToWorld(); - - Vector vecEndPosition; - QAngle vecEndAngles; - m_Shared.GetPositionAtTime( gpGlobals->curtime, vecEndPosition, vecEndAngles ); - UTIL_SetOrigin( this, vecEndPosition ); - SetAbsAngles( vecEndAngles ); - RemoveEFlags( EFL_IN_SKYBOX ); - - // Switch to the actual-scale model - SetupWorldModel(); - - // Futz with the smoke trail to get it working across the boundary - m_hTrail->SetSkybox( vec3_origin, 1.0f ); - - // Now we start looking for collisions - SetThink( &CEnvHeadcrabCanister::HeadcrabCanisterWorldThink ); - SetNextThink( gpGlobals->curtime + 0.01f ); -} - - -//----------------------------------------------------------------------------- -// Purpose: This stops its motion in the skybox -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanister::HeadcrabCanisterSkyboxOnlyThink( void ) -{ - Vector vecEndPosition; - QAngle vecEndAngles; - m_Shared.GetPositionAtTime( gpGlobals->curtime, vecEndPosition, vecEndAngles ); - UTIL_SetOrigin( this, vecEndPosition ); - SetAbsAngles( vecEndAngles ); - - if ( !HasSpawnFlags( SF_NO_IMPACT_SOUND ) ) - { - CPASAttenuationFilter filter( this, ATTN_NONE ); - EmitSound( filter, entindex(), "HeadcrabCanister.SkyboxExplosion" ); - } - - if ( m_nSkyboxCannisterCount != 0 ) - { - if ( --m_nSkyboxCannisterCount <= 0 ) - { - SetThink( NULL ); - return; - } - } - - float flRefireTime = random->RandomFloat( m_flMinRefireTime, m_flMaxRefireTime ) + ENV_HEADCRABCANISTER_TRAIL_TIME; - SetThink( &CEnvHeadcrabCanister::HeadcrabCanisterSkyboxRestartThink ); - SetNextThink( gpGlobals->curtime + flRefireTime ); -} - - -//----------------------------------------------------------------------------- -// This will re-fire the headcrab cannister -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanister::HeadcrabCanisterSkyboxRestartThink( void ) -{ - if ( m_hTrail ) - { - UTIL_Remove( m_hTrail ); - m_hTrail = NULL; - } - - m_bLaunched = false; - - inputdata_t data; - InputFireCanister( data ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pInfo - -// bAlways - -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanister::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ) -{ - // Are we already marked for transmission? - if ( pInfo->m_pTransmitEdict->Get( entindex() ) ) - return; - - BaseClass::SetTransmit( pInfo, bAlways ); - - // Make our smoke trail always come with us - if ( m_hSmokeTrail ) - { - m_hSmokeTrail->SetTransmit( pInfo, bAlways ); - } -} diff --git a/game/server/hl2/env_speaker.cpp b/game/server/hl2/env_speaker.cpp deleted file mode 100644 index 822d9edea..000000000 --- a/game/server/hl2/env_speaker.cpp +++ /dev/null @@ -1,217 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include "cbase.h" -#include "player.h" -#include "mathlib/mathlib.h" -#include "env_speaker.h" -#include "ai_speech.h" -#include "stringregistry.h" -#include "gamerules.h" -#include "game.h" -#include -#include "entitylist.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "ndebugoverlay.h" -#include "soundscape.h" -#include "AI_ResponseSystem.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SF_SPEAKER_START_SILENT 1 -#define SF_SPEAKER_EVERYWHERE 2 - -extern ISaveRestoreOps *responseSystemSaveRestoreOps; -#include "saverestore.h" - -LINK_ENTITY_TO_CLASS( env_speaker, CSpeaker ); - -BEGIN_DATADESC( CSpeaker ) - - DEFINE_KEYFIELD( m_delayMin, FIELD_FLOAT, "delaymin" ), - DEFINE_KEYFIELD( m_delayMax, FIELD_FLOAT, "delaymax" ), - DEFINE_KEYFIELD( m_iszRuleScriptFile, FIELD_STRING, "rulescript" ), - DEFINE_KEYFIELD( m_iszConcept, FIELD_STRING, "concept" ), - - // Needs to be set up in the Activate methods of derived classes - //DEFINE_CUSTOM_FIELD( m_pInstancedResponseSystem, responseSystemSaveRestoreOps ), - - // Function Pointers - DEFINE_FUNCTION( SpeakerThink ), - - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - -END_DATADESC() - - -void CSpeaker::Spawn( void ) -{ - const char *soundfile = (const char *)STRING( m_iszRuleScriptFile ); - - if ( Q_strlen( soundfile ) < 1 ) - { - Warning( "'speaker' entity with no Level/Sentence! at: %f, %f, %f\n", GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z ); - SetNextThink( gpGlobals->curtime + 0.1f ); - SetThink( &CSpeaker::SUB_Remove ); - return; - } - -// const char *concept = (const char *)STRING( m_iszConcept ); -// if ( Q_strlen( concept ) < 1 ) -// { -// Warning( "'speaker' entity using rule set %s with empty concept string\n", soundfile ); -// } - - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NONE ); - - SetThink(&CSpeaker::SpeakerThink); - SetNextThink( TICK_NEVER_THINK ); - - // allow on/off switching via 'use' function. - - Precache( ); -} - - -void CSpeaker::Precache( void ) -{ - if ( !FBitSet (m_spawnflags, SF_SPEAKER_START_SILENT ) ) - { - // set first announcement time for random n second - SetNextThink( gpGlobals->curtime + random->RandomFloat(5.0, 15.0) ); - } - - if ( !m_pInstancedResponseSystem ) - { - m_pInstancedResponseSystem = PrecacheCustomResponseSystem( STRING( m_iszRuleScriptFile ) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Need a custom save restore so we can restore the instanced response system by name -// after we've loaded the filename from disk... -// Input : &save - -//----------------------------------------------------------------------------- -int CSpeaker::Save( ISave &save ) -{ - int iret = BaseClass::Save( save ); - if ( iret ) - { - bool doSave = ( m_pInstancedResponseSystem && ( m_iszRuleScriptFile != NULL_STRING ) ) ? true : false; - save.WriteBool( &doSave ); - if ( doSave ) - { - save.StartBlock( "InstancedResponseSystem" ); - { - SaveRestoreFieldInfo_t fieldInfo = { &m_pInstancedResponseSystem, 0, NULL }; - responseSystemSaveRestoreOps->Save( fieldInfo, &save ); - } - save.EndBlock(); - } - } - return iret; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &restore - -//----------------------------------------------------------------------------- -int CSpeaker::Restore( IRestore &restore ) -{ - int iret = BaseClass::Restore( restore ); - if ( iret ) - { - bool doRead = false; - restore.ReadBool( &doRead ); - if ( doRead ) - { - char szResponseSystemBlockName[SIZE_BLOCK_NAME_BUF]; - restore.StartBlock( szResponseSystemBlockName ); - if ( !Q_stricmp( szResponseSystemBlockName, "InstancedResponseSystem" ) ) - { - if ( !m_pInstancedResponseSystem ) - { - m_pInstancedResponseSystem = PrecacheCustomResponseSystem( STRING( m_iszRuleScriptFile ) ); - if ( m_pInstancedResponseSystem ) - { - SaveRestoreFieldInfo_t fieldInfo = - { - &m_pInstancedResponseSystem, - 0, - NULL - }; - responseSystemSaveRestoreOps->Restore( fieldInfo, &restore ); - } - } - } - restore.EndBlock(); - } - } - return iret; -} - -void CSpeaker::SpeakerThink( void ) -{ - // Wait for the talking characters to finish first. - if ( !g_AIFriendliesTalkSemaphore.IsAvailable( this ) || !g_AIFoesTalkSemaphore.IsAvailable( this ) ) - { - float releaseTime = MAX( g_AIFriendliesTalkSemaphore.GetReleaseTime(), g_AIFoesTalkSemaphore.GetReleaseTime() ); - // Add some slop (only up to one second) - releaseTime += random->RandomFloat( 0, 1 ); - SetNextThink( releaseTime ); - return; - } - - DispatchResponse( m_iszConcept.ToCStr() ); - - SetNextThink( gpGlobals->curtime + random->RandomFloat(m_delayMin, m_delayMax) ); - - // time delay until it's ok to speak: used so that two NPCs don't talk at once - g_AIFriendliesTalkSemaphore.Acquire( 5, this ); - g_AIFoesTalkSemaphore.Acquire( 5, this ); -} - - -void CSpeaker::InputTurnOn( inputdata_t &inputdata ) -{ - // turn on announcements - SetNextThink( gpGlobals->curtime + 0.1 ); -} - - -void CSpeaker::InputTurnOff( inputdata_t &inputdata ) -{ - // turn off announcements - SetNextThink( TICK_NEVER_THINK ); -} - - -// -// If an announcement is pending, cancel it. If no announcement is pending, start one. -// -void CSpeaker::InputToggle( inputdata_t &inputdata ) -{ - int fActive = (GetNextThink() > 0.0 ); - - // fActive is true only if an announcement is pending - if ( fActive ) - { - // turn off announcements - SetNextThink( TICK_NEVER_THINK ); - } - else - { - // turn on announcements - SetNextThink( gpGlobals->curtime + 0.1f ); - } -} diff --git a/game/server/hl2/env_speaker.h b/game/server/hl2/env_speaker.h deleted file mode 100644 index e1a41bab3..000000000 --- a/game/server/hl2/env_speaker.h +++ /dev/null @@ -1,54 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ENV_SPEAKER_H -#define ENV_SPEAKER_H -#ifdef _WIN32 -#pragma once -#endif - -// =================================================================================== -// -// Speaker class. Used for announcements per level, for door lock/unlock spoken voice. -// - -class CSpeaker : public CPointEntity -{ -public: - DECLARE_CLASS( CSpeaker, CPointEntity ); - - void Spawn( void ); - void Precache( void ); - - DECLARE_DATADESC(); - - virtual int ObjectCaps( void ) { return (BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION); } - - virtual IResponseSystem *GetResponseSystem() { return m_pInstancedResponseSystem; } - - virtual int Save( ISave &save ); - virtual int Restore( IRestore &restore ); - -protected: - - void SpeakerThink( void ); - - void InputToggle( inputdata_t &inputdata ); - - float m_delayMin; - float m_delayMax; - - string_t m_iszRuleScriptFile; - string_t m_iszConcept; - IResponseSystem *m_pInstancedResponseSystem; - -public: - - void InputTurnOff( inputdata_t &inputdata ); - void InputTurnOn( inputdata_t &inputdata ); -}; - -#endif // ENV_SPEAKER_H diff --git a/game/server/hl2/env_starfield.cpp b/game/server/hl2/env_starfield.cpp deleted file mode 100644 index 249bd60d4..000000000 --- a/game/server/hl2/env_starfield.cpp +++ /dev/null @@ -1,107 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "baseparticleentity.h" -#include "sendproxy.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CEnvStarfield : public CBaseEntity -{ - DECLARE_CLASS( CEnvStarfield, CBaseEntity ); -public: - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - virtual void Precache(); - virtual void Spawn( void ); - virtual int UpdateTransmitState(void); - - // Inputs - void InputTurnOn( inputdata_t &inputdata ); - void InputTurnOff( inputdata_t &inputdata ); - void InputSetDensity( inputdata_t &inputdata ); - -private: - CNetworkVar( bool, m_bOn ); - CNetworkVar( float, m_flDensity ); -}; - -BEGIN_DATADESC( CEnvStarfield ) - DEFINE_FIELD( m_bOn, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flDensity, FIELD_FLOAT ), - - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetDensity", InputSetDensity ), -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CEnvStarfield, DT_EnvStarfield ) - SendPropInt( SENDINFO(m_bOn), 1, SPROP_UNSIGNED ), - SendPropFloat( SENDINFO(m_flDensity), 0, SPROP_NOSCALE), -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( env_starfield, CEnvStarfield ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvStarfield::Spawn() -{ - BaseClass::Spawn(); - - m_flDensity = 1.0; - m_bOn = false; - - Precache(); -} - -void CEnvStarfield::Precache() -{ - BaseClass::Precache(); - - PrecacheMaterial( "effects/spark_noz" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CEnvStarfield::UpdateTransmitState() -{ - return SetTransmitState( FL_EDICT_ALWAYS ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvStarfield::InputTurnOn( inputdata_t &inputdata ) -{ - m_bOn = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CEnvStarfield::InputTurnOff( inputdata_t &inputdata ) -{ - m_bOn = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CEnvStarfield::InputSetDensity( inputdata_t &inputdata ) -{ - m_flDensity = inputdata.value.Float(); -} diff --git a/game/server/hl2/extinguisherjet.cpp b/game/server/hl2/extinguisherjet.cpp deleted file mode 100644 index 01a150309..000000000 --- a/game/server/hl2/extinguisherjet.cpp +++ /dev/null @@ -1,202 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "extinguisherjet.h" -#include "engine/IEngineSound.h" -#include "fire.h" -#include "ndebugoverlay.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern ConVar fire_extinguisher_debug; - -//Networking -IMPLEMENT_SERVERCLASS_ST( CExtinguisherJet, DT_ExtinguisherJet ) - SendPropInt(SENDINFO(m_bEmit), 1, SPROP_UNSIGNED), - SendPropInt(SENDINFO(m_bUseMuzzlePoint), 1, SPROP_UNSIGNED), - SendPropInt(SENDINFO(m_nLength), 32, SPROP_UNSIGNED), - SendPropInt(SENDINFO(m_nSize), 32, SPROP_UNSIGNED), -END_SEND_TABLE() - -//Save/restore -BEGIN_DATADESC( CExtinguisherJet ) - - //Regular fields - DEFINE_FIELD( m_bEmit, FIELD_BOOLEAN ), - - DEFINE_KEYFIELD( m_bEnabled, FIELD_BOOLEAN, "enabled" ), - DEFINE_KEYFIELD( m_nLength, FIELD_INTEGER, "length" ), - DEFINE_KEYFIELD( m_nSize, FIELD_INTEGER, "size" ), - DEFINE_KEYFIELD( m_nRadius, FIELD_INTEGER, "radius" ), - DEFINE_KEYFIELD( m_flStrength,FIELD_FLOAT, "strength" ), - - DEFINE_FIELD( m_bAutoExtinguish, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bUseMuzzlePoint, FIELD_BOOLEAN ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - - DEFINE_FUNCTION( ExtinguishThink ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( env_extinguisherjet, CExtinguisherJet ); - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -CExtinguisherJet::CExtinguisherJet( void ) -{ - m_bEmit = false; - m_bEnabled = false; - m_bAutoExtinguish = true; - - m_nLength = 128; - m_nSize = 8; - m_flStrength = 0.97f; //FIXME: Stub numbers - m_nRadius = 32; - - // Send to the client even though we don't have a model - AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CExtinguisherJet::Spawn( void ) -{ - Precache(); - - if ( m_bEnabled ) - { - TurnOn(); - } -} - -void CExtinguisherJet::Precache() -{ - BaseClass::Precache(); - - PrecacheScriptSound( "ExtinguisherJet.TurnOn" ); - PrecacheScriptSound( "ExtinguisherJet.TurnOff" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CExtinguisherJet::TurnOn( void ) -{ - //Turn on sound - if ( m_bEmit == false ) - { - EmitSound( "ExtinguisherJet.TurnOn" ); - m_bEnabled = m_bEmit = true; - } - - SetThink( &CExtinguisherJet::ExtinguishThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CExtinguisherJet::TurnOff( void ) -{ - //Turn off sound - if ( m_bEmit ) - { - EmitSound( "ExtinguisherJet.TurnOff" ); - m_bEnabled = m_bEmit = false; - } - - SetThink( NULL ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CExtinguisherJet::InputEnable( inputdata_t &inputdata ) -{ - TurnOn(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CExtinguisherJet::InputDisable( inputdata_t &inputdata ) -{ - TurnOff(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CExtinguisherJet::InputToggle( inputdata_t &inputdata ) -{ - if ( m_bEnabled ) - { - TurnOff(); - } - else - { - TurnOn(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CExtinguisherJet::Think( void ) -{ - CBaseEntity::Think(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CExtinguisherJet::ExtinguishThink( void ) -{ - SetNextThink( gpGlobals->curtime + 0.1f ); - - if ( m_bEnabled == false ) - return; - - if ( m_bAutoExtinguish == false ) - return; - - Vector vTestPos; - Vector vForward, vRight, vUp; - - AngleVectors( GetAbsAngles(), &vForward ); - - vTestPos = GetAbsOrigin() + ( vForward * m_nLength ); - - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), vTestPos, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - //Extinguish the fire where we hit - FireSystem_ExtinguishInRadius( tr.endpos, m_nRadius, m_flStrength ); - - //Debug visualization - if ( fire_extinguisher_debug.GetInt() ) - { - int radius = m_nRadius; - - NDebugOverlay::Line( GetAbsOrigin(), tr.endpos, 0, 0, 128, false, 0.1f ); - - NDebugOverlay::Box( GetAbsOrigin(), Vector(-1, -1, -1), Vector(1, 1, 1), 0, 0, 128, false, 0.1f ); - NDebugOverlay::Box( tr.endpos, Vector(-2, -2, -2), Vector(2, 2, 2), 0, 0, 128, false, 0.1f ); - NDebugOverlay::Box( tr.endpos, Vector(-radius, -radius, -radius), Vector(radius, radius, radius), 0, 0, 255, false, 0.1f ); - } -} diff --git a/game/server/hl2/extinguisherjet.h b/game/server/hl2/extinguisherjet.h deleted file mode 100644 index 1918ef5b7..000000000 --- a/game/server/hl2/extinguisherjet.h +++ /dev/null @@ -1,55 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef EXTINGUISHERJET_H -#define EXTINGUISHERJET_H -#ifdef _WIN32 -#pragma once -#endif - -#include "baseparticleentity.h" - -class CExtinguisherJet : public CBaseEntity -{ -public: - DECLARE_CLASS( CExtinguisherJet, CBaseEntity ); - - CExtinguisherJet( void ); - - virtual void Spawn( void ); - virtual void Precache(); - - void TurnOn( void ); - void TurnOff( void ); - - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - void InputToggle( inputdata_t &inputdata ); - - virtual void Think( void ); - - void ExtinguishThink( void ); - - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - -// Stuff from the datatable. -public: - CNetworkVar( bool, m_bEmit ); // Emit particles? - CNetworkVar( int, m_nLength ); // Length of jet - CNetworkVar( int, m_nSize ); // Size of jet (as in width and noise of particle movement) - int m_nRadius; // Radius area to extinguish where jet hits - float m_flStrength; // Strength of the extinguisher - - bool m_bEnabled; - - //Used for viewmodel - CNetworkVar( bool, m_bUseMuzzlePoint ); - bool m_bAutoExtinguish; //Whether extinguisher should put out fires in its think, or let owner do it -}; - -#endif // EXTINGUISHERJET_H diff --git a/game/server/hl2/func_bulletshield.cpp b/game/server/hl2/func_bulletshield.cpp deleted file mode 100644 index 441ddd472..000000000 --- a/game/server/hl2/func_bulletshield.cpp +++ /dev/null @@ -1,101 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "entityoutput.h" -#include "ndebugoverlay.h" -#include "func_bulletshield.h" -#include "collisionutils.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern ConVar ent_debugkeys; -extern ConVar showtriggers; - - - -LINK_ENTITY_TO_CLASS( func_bulletshield, CFuncBulletShield ); - -BEGIN_DATADESC( CFuncBulletShield ) - -/* - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputTurnOff ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - DEFINE_KEYFIELD( m_iDisabled, FIELD_INTEGER, "StartDisabled" ), - DEFINE_KEYFIELD( m_iSolidity, FIELD_INTEGER, "Solidity" ), - DEFINE_KEYFIELD( m_bSolidBsp, FIELD_BOOLEAN, "solidbsp" ), - DEFINE_KEYFIELD( m_iszExcludedClass, FIELD_STRING, "excludednpc" ), - DEFINE_KEYFIELD( m_bInvertExclusion, FIELD_BOOLEAN, "invert_exclusion" ), -*/ - -END_DATADESC() - - - -void CFuncBulletShield::Spawn( void ) -{ - BaseClass::Spawn(); - - AddSolidFlags( FSOLID_CUSTOMRAYTEST ); - AddSolidFlags( FSOLID_CUSTOMBOXTEST ); - // SetSolid(SOLID_CUSTOM); - - VPhysicsDestroyObject(); -} - -/* -bool IntersectRayWithOBB( const Vector &vecRayStart, const Vector &vecRayDelta, - const matrix3x4_t &matOBBToWorld, const Vector &vecOBBMins, const Vector &vecOBBMaxs, - float flTolerance, CBaseTrace *pTrace ); - -bool IntersectRayWithOBB( const Vector &vecRayOrigin, const Vector &vecRayDelta, - const Vector &vecBoxOrigin, const QAngle &angBoxRotation, - const Vector &vecOBBMins, const Vector &vecOBBMaxs, float flTolerance, CBaseTrace *pTrace ); - -bool IntersectRayWithOBB( const Ray_t &ray, const Vector &vecBoxOrigin, const QAngle &angBoxRotation, - const Vector &vecOBBMins, const Vector &vecOBBMaxs, float flTolerance, CBaseTrace *pTrace ); - -bool IntersectRayWithOBB( const Ray_t &ray, const matrix3x4_t &matOBBToWorld, - const Vector &vecOBBMins, const Vector &vecOBBMaxs, float flTolerance, CBaseTrace *pTrace ); - -bool IntersectRayWithOBB( const Vector &vecRayStart, const Vector &vecRayDelta, - const matrix3x4_t &matOBBToWorld, const Vector &vecOBBMins, const Vector &vecOBBMaxs, - float flTolerance, BoxTraceInfo_t *pTrace ); - */ - -bool CFuncBulletShield::TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ) -{ - // ignore unless a shot - if ((mask & MASK_SHOT) == MASK_SHOT) - { - // use obb collision - ICollideable *pCol = GetCollideable(); - Assert(pCol); - - return IntersectRayWithOBB(ray,pCol->GetCollisionOrigin(),pCol->GetCollisionAngles(), - pCol->OBBMins(),pCol->OBBMaxs(),1.0f,&trace); - - /* - const model_t *pModel = this->GetCollisionModel(); - if ( pModel && pModel->type == mod_brush ) - { - int nModelIndex = this->GetCollisionModelIndex(); - cmodel_t *pCModel = CM_InlineModelNumber( nModelIndex - 1 ); - int nHeadNode = pCModel->headnode; - - CM_TransformedBoxTrace( ray, nHeadNode, fMask, this->GetCollisionOrigin(), this->GetCollisionAngles(), *pTrace ); - return true; - } - return false; - */ - - // return BaseClass::TestCollision( ray, mask, trace ); - } - else - return false; -} diff --git a/game/server/hl2/func_bulletshield.h b/game/server/hl2/func_bulletshield.h deleted file mode 100644 index 86635ce43..000000000 --- a/game/server/hl2/func_bulletshield.h +++ /dev/null @@ -1,68 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef FUNC_BULLETSHIELD_H -#define FUNC_BULLETSHIELD_H -#ifdef _WIN32 -#pragma once -#endif - -//!! replace this with generic start enabled/disabled -#define SF_WALL_START_OFF 0x0001 -#define SF_IGNORE_PLAYERUSE 0x0002 - -#include "modelentities.h" - -//----------------------------------------------------------------------------- -// Purpose: shield that stops bullets, but not other objects -// enabled state: brush is visible -// disabled staute: brush not visible -//----------------------------------------------------------------------------- -class CFuncBulletShield : public CFuncBrush -{ -public: - DECLARE_CLASS( CFuncBulletShield, CFuncBrush ); - DECLARE_DATADESC(); - - virtual void Spawn( void ); - - bool TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ); - /* - bool CreateVPhysics( void ); - - virtual int ObjectCaps( void ) { return HasSpawnFlags(SF_IGNORE_PLAYERUSE) ? BaseClass::ObjectCaps() : BaseClass::ObjectCaps() | FCAP_IMPULSE_USE; } - - virtual int DrawDebugTextOverlays( void ); - - void TurnOff( void ); - void TurnOn( void ); - - // Input handlers - void InputTurnOff( inputdata_t &inputdata ); - void InputTurnOn( inputdata_t &inputdata ); - void InputToggle( inputdata_t &inputdata ); - - enum BrushSolidities_e { - BRUSHSOLID_TOGGLE = 0, - BRUSHSOLID_NEVER = 1, - BRUSHSOLID_ALWAYS = 2, - }; - - BrushSolidities_e m_iSolidity; - int m_iDisabled; - bool m_bSolidBsp; - string_t m_iszExcludedClass; - bool m_bInvertExclusion; - - DECLARE_DATADESC(); - - virtual bool IsOn( void ); - */ -}; - - -#endif // MODELENTITIES_H diff --git a/game/server/hl2/func_recharge.cpp b/game/server/hl2/func_recharge.cpp deleted file mode 100644 index 7f73685cf..000000000 --- a/game/server/hl2/func_recharge.cpp +++ /dev/null @@ -1,777 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -/* - -===== h_battery.cpp ======================================================== - - battery-related code - -*/ - -#include "cbase.h" -#include "gamerules.h" -#include "player.h" -#include "engine/IEngineSound.h" -#include "in_buttons.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -static ConVar sk_suitcharger( "sk_suitcharger","0" ); -static ConVar sk_suitcharger_citadel( "sk_suitcharger_citadel","0" ); -static ConVar sk_suitcharger_citadel_maxarmor( "sk_suitcharger_citadel_maxarmor","0" ); - -#define SF_CITADEL_RECHARGER 0x2000 -#define SF_KLEINER_RECHARGER 0x4000 // Gives only 25 health - -class CRecharge : public CBaseToggle -{ -public: - DECLARE_CLASS( CRecharge, CBaseToggle ); - - void Spawn( ); - bool CreateVPhysics(); - int DrawDebugTextOverlays(void); - void Off(void); - void Recharge(void); - bool KeyValue( const char *szKeyName, const char *szValue ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - virtual int ObjectCaps( void ) { return (BaseClass::ObjectCaps() | FCAP_CONTINUOUS_USE); } - -private: - void InputRecharge( inputdata_t &inputdata ); - - float MaxJuice() const; - void UpdateJuice( int newJuice ); - - DECLARE_DATADESC(); - - float m_flNextCharge; - int m_iReactivate ; // DeathMatch Delay until reactvated - int m_iJuice; - int m_iOn; // 0 = off, 1 = startup, 2 = going - float m_flSoundTime; - - int m_nState; - - COutputFloat m_OutRemainingCharge; - COutputEvent m_OnHalfEmpty; - COutputEvent m_OnEmpty; - COutputEvent m_OnFull; - COutputEvent m_OnPlayerUse; -}; - -BEGIN_DATADESC( CRecharge ) - - DEFINE_FIELD( m_flNextCharge, FIELD_TIME ), - DEFINE_FIELD( m_iReactivate, FIELD_INTEGER), - DEFINE_FIELD( m_iJuice, FIELD_INTEGER), - DEFINE_FIELD( m_iOn, FIELD_INTEGER), - DEFINE_FIELD( m_flSoundTime, FIELD_TIME ), - DEFINE_FIELD( m_nState, FIELD_INTEGER ), - - // Function Pointers - DEFINE_FUNCTION( Off ), - DEFINE_FUNCTION( Recharge ), - - DEFINE_OUTPUT(m_OutRemainingCharge, "OutRemainingCharge"), - DEFINE_OUTPUT(m_OnHalfEmpty, "OnHalfEmpty" ), - DEFINE_OUTPUT(m_OnEmpty, "OnEmpty" ), - DEFINE_OUTPUT(m_OnFull, "OnFull" ), - DEFINE_OUTPUT(m_OnPlayerUse, "OnPlayerUse" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Recharge", InputRecharge ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS(func_recharge, CRecharge); - - -bool CRecharge::KeyValue( const char *szKeyName, const char *szValue ) -{ - if ( FStrEq(szKeyName, "style") || - FStrEq(szKeyName, "height") || - FStrEq(szKeyName, "value1") || - FStrEq(szKeyName, "value2") || - FStrEq(szKeyName, "value3")) - { - } - else if (FStrEq(szKeyName, "dmdelay")) - { - m_iReactivate = atoi(szValue); - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } - - return true; -} - -void CRecharge::Spawn() -{ - Precache( ); - - SetSolid( SOLID_BSP ); - SetMoveType( MOVETYPE_PUSH ); - - SetModel( STRING( GetModelName() ) ); - - UpdateJuice( (int)MaxJuice() ); - - m_nState = 0; - - CreateVPhysics(); -} - -bool CRecharge::CreateVPhysics() -{ - VPhysicsInitStatic(); - return true; -} - -int CRecharge::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - Q_snprintf(tempstr,sizeof(tempstr),"Charge left: %i", m_iJuice ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} - - -//----------------------------------------------------------------------------- -// Max juice for recharger -//----------------------------------------------------------------------------- -float CRecharge::MaxJuice() const -{ - if ( HasSpawnFlags( SF_CITADEL_RECHARGER ) ) - { - return sk_suitcharger_citadel.GetFloat(); - } - - return sk_suitcharger.GetFloat(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : newJuice - -//----------------------------------------------------------------------------- -void CRecharge::UpdateJuice( int newJuice ) -{ - bool reduced = newJuice < m_iJuice; - if ( reduced ) - { - // Fire 1/2 way output and/or empyt output - int oneHalfJuice = (int)(MaxJuice() * 0.5f); - if ( newJuice <= oneHalfJuice && m_iJuice > oneHalfJuice ) - { - m_OnHalfEmpty.FireOutput( this, this ); - } - - if ( newJuice <= 0 ) - { - m_OnEmpty.FireOutput( this, this ); - } - } - else if ( newJuice != m_iJuice && - newJuice == (int)MaxJuice() ) - { - m_OnFull.FireOutput( this, this ); - } - m_iJuice = newJuice; -} - -void CRecharge::InputRecharge( inputdata_t &inputdata ) -{ - Recharge(); -} - -void CRecharge::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - // if it's not a player, ignore - if ( !pActivator || !pActivator->IsPlayer() ) - return; - - // Only usable if you have the HEV suit on - if ( !((CBasePlayer *)pActivator)->IsSuitEquipped() ) - { - if (m_flSoundTime <= gpGlobals->curtime) - { - m_flSoundTime = gpGlobals->curtime + 0.62; - EmitSound( "SuitRecharge.Deny" ); - } - return; - } - - // if there is no juice left, turn it off - if (m_iJuice <= 0) - { - m_nState = 1; - Off(); - } - - // if the player doesn't have the suit, or there is no juice left, make the deny noise - if ( m_iJuice <= 0 ) - { - if (m_flSoundTime <= gpGlobals->curtime) - { - m_flSoundTime = gpGlobals->curtime + 0.62; - EmitSound( "SuitRecharge.Deny" ); - } - return; - } - - SetNextThink( gpGlobals->curtime + 0.25 ); - SetThink(&CRecharge::Off); - - // Time to recharge yet? - if (m_flNextCharge >= gpGlobals->curtime) - return; - - // Make sure that we have a caller - if (!pActivator) - return; - - m_hActivator = pActivator; - - //only recharge the player - - if (!m_hActivator->IsPlayer() ) - return; - - // Play the on sound or the looping charging sound - if (!m_iOn) - { - m_iOn++; - EmitSound( "SuitRecharge.Start" ); - m_flSoundTime = 0.56 + gpGlobals->curtime; - - m_OnPlayerUse.FireOutput( pActivator, this ); - } - - if ((m_iOn == 1) && (m_flSoundTime <= gpGlobals->curtime)) - { - m_iOn++; - CPASAttenuationFilter filter( this, "SuitRecharge.ChargingLoop" ); - filter.MakeReliable(); - EmitSound( filter, entindex(), "SuitRecharge.ChargingLoop" ); - } - - CBasePlayer *pl = (CBasePlayer *) m_hActivator.Get(); - - // charge the player - int nMaxArmor = 100; - int nIncrementArmor = 1; - if ( HasSpawnFlags( SF_CITADEL_RECHARGER ) ) - { - nMaxArmor = sk_suitcharger_citadel_maxarmor.GetInt(); - nIncrementArmor = 10; - - // Also give health for the citadel version. - if( pActivator->GetHealth() < pActivator->GetMaxHealth() ) - { - pActivator->TakeHealth( 5, DMG_GENERIC ); - } - } - - if (pl->ArmorValue() < nMaxArmor) - { - UpdateJuice( m_iJuice - nIncrementArmor ); - pl->IncrementArmorValue( nIncrementArmor, nMaxArmor ); - } - - // Send the output. - float flRemaining = m_iJuice / MaxJuice(); - m_OutRemainingCharge.Set(flRemaining, pActivator, this); - - // govern the rate of charge - m_flNextCharge = gpGlobals->curtime + 0.1; -} - -void CRecharge::Recharge(void) -{ - UpdateJuice( (int)MaxJuice() ); - m_nState = 0; - SetThink( &CRecharge::SUB_DoNothing ); -} - -void CRecharge::Off(void) -{ - // Stop looping sound. - if (m_iOn > 1) - { - StopSound( "SuitRecharge.ChargingLoop" ); - } - - m_iOn = 0; - - if ((!m_iJuice) && ( ( m_iReactivate = (int)g_pGameRules->FlHEVChargerRechargeTime() ) > 0) ) - { - SetNextThink( gpGlobals->curtime + m_iReactivate ); - SetThink(&CRecharge::Recharge); - } - else - { - SetThink( NULL ); - } -} - - -//NEW -class CNewRecharge : public CBaseAnimating -{ -public: - DECLARE_CLASS( CNewRecharge, CBaseAnimating ); - - void Spawn( ); - bool CreateVPhysics(); - int DrawDebugTextOverlays(void); - void Off(void); - void Recharge(void); - bool KeyValue( const char *szKeyName, const char *szValue ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - virtual int ObjectCaps( void ) { return (BaseClass::ObjectCaps() | m_iCaps ); } - - void SetInitialCharge( void ); - -private: - void InputRecharge( inputdata_t &inputdata ); - void InputSetCharge( inputdata_t &inputdata ); - float MaxJuice() const; - void UpdateJuice( int newJuice ); - void Precache( void ); - - DECLARE_DATADESC(); - - float m_flNextCharge; - int m_iReactivate ; // DeathMatch Delay until reactvated - int m_iJuice; - int m_iOn; // 0 = off, 1 = startup, 2 = going - float m_flSoundTime; - - int m_nState; - int m_iCaps; - int m_iMaxJuice; - - COutputFloat m_OutRemainingCharge; - COutputEvent m_OnHalfEmpty; - COutputEvent m_OnEmpty; - COutputEvent m_OnFull; - COutputEvent m_OnPlayerUse; - - virtual void StudioFrameAdvance ( void ); - float m_flJuice; -}; - -BEGIN_DATADESC( CNewRecharge ) - - DEFINE_FIELD( m_flNextCharge, FIELD_TIME ), - DEFINE_FIELD( m_iReactivate, FIELD_INTEGER), - DEFINE_FIELD( m_iJuice, FIELD_INTEGER), - DEFINE_FIELD( m_iOn, FIELD_INTEGER), - DEFINE_FIELD( m_flSoundTime, FIELD_TIME ), - DEFINE_FIELD( m_nState, FIELD_INTEGER ), - DEFINE_FIELD( m_iCaps, FIELD_INTEGER ), - DEFINE_FIELD( m_iMaxJuice, FIELD_INTEGER ), - - // Function Pointers - DEFINE_FUNCTION( Off ), - DEFINE_FUNCTION( Recharge ), - - DEFINE_OUTPUT(m_OutRemainingCharge, "OutRemainingCharge"), - DEFINE_OUTPUT(m_OnHalfEmpty, "OnHalfEmpty" ), - DEFINE_OUTPUT(m_OnEmpty, "OnEmpty" ), - DEFINE_OUTPUT(m_OnFull, "OnFull" ), - DEFINE_OUTPUT(m_OnPlayerUse, "OnPlayerUse" ), - DEFINE_FIELD( m_flJuice, FIELD_FLOAT ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Recharge", InputRecharge ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetCharge", InputSetCharge ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( item_suitcharger, CNewRecharge); - -#define HEALTH_CHARGER_MODEL_NAME "models/props_combine/suit_charger001.mdl" -#define CHARGE_RATE 0.25f -#define CHARGES_PER_SECOND 1 / CHARGE_RATE -#define CITADEL_CHARGES_PER_SECOND 10 / CHARGE_RATE -#define CALLS_PER_SECOND 7.0f * CHARGES_PER_SECOND - - -bool CNewRecharge::KeyValue( const char *szKeyName, const char *szValue ) -{ - if ( FStrEq(szKeyName, "style") || - FStrEq(szKeyName, "height") || - FStrEq(szKeyName, "value1") || - FStrEq(szKeyName, "value2") || - FStrEq(szKeyName, "value3")) - { - } - else if (FStrEq(szKeyName, "dmdelay")) - { - m_iReactivate = atoi(szValue); - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } - - return true; -} - -void CNewRecharge::Precache( void ) -{ - PrecacheModel( HEALTH_CHARGER_MODEL_NAME ); - - PrecacheScriptSound( "SuitRecharge.Deny" ); - PrecacheScriptSound( "SuitRecharge.Start" ); - PrecacheScriptSound( "SuitRecharge.ChargingLoop" ); - -} - -void CNewRecharge::SetInitialCharge( void ) -{ - if ( HasSpawnFlags( SF_KLEINER_RECHARGER ) ) - { - // The charger in Kleiner's lab. - m_iMaxJuice = 25; - return; - } - - if ( HasSpawnFlags( SF_CITADEL_RECHARGER ) ) - { - m_iMaxJuice = sk_suitcharger_citadel.GetInt(); - return; - } - - m_iMaxJuice = sk_suitcharger.GetInt(); -} - -void CNewRecharge::Spawn() -{ - Precache( ); - - SetMoveType( MOVETYPE_NONE ); - SetSolid( SOLID_VPHYSICS ); - CreateVPhysics(); - - SetModel( HEALTH_CHARGER_MODEL_NAME ); - AddEffects( EF_NOSHADOW ); - - ResetSequence( LookupSequence( "idle" ) ); - - SetInitialCharge(); - - UpdateJuice( (int)MaxJuice() ); - - m_nState = 0; - m_iCaps = FCAP_CONTINUOUS_USE; - - CreateVPhysics(); - - m_flJuice = m_iJuice; - - m_iReactivate = 0; - - SetCycle( 1.0f - ( m_flJuice / MaxJuice() ) ); -} - -bool CNewRecharge::CreateVPhysics() -{ - VPhysicsInitStatic(); - return true; -} - -int CNewRecharge::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - Q_snprintf(tempstr,sizeof(tempstr),"Charge left: %i", m_iJuice ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} - -void CNewRecharge::StudioFrameAdvance( void ) -{ - m_flPlaybackRate = 0; - - float flMaxJuice = MaxJuice() + 0.1f; - float flNewJuice = 1.0f - (float)( m_flJuice / flMaxJuice ); - - SetCycle( flNewJuice ); -// Msg( "Cycle: %f - Juice: %d - m_flJuice :%f - Interval: %f\n", (float)GetCycle(), (int)m_iJuice, (float)m_flJuice, GetAnimTimeInterval() ); - - if ( !m_flPrevAnimTime ) - { - m_flPrevAnimTime = gpGlobals->curtime; - } - - // Latch prev - m_flPrevAnimTime = m_flAnimTime; - // Set current - m_flAnimTime = gpGlobals->curtime; -} - - - -//----------------------------------------------------------------------------- -// Max juice for recharger -//----------------------------------------------------------------------------- -float CNewRecharge::MaxJuice() const -{ - return m_iMaxJuice; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : newJuice - -//----------------------------------------------------------------------------- -void CNewRecharge::UpdateJuice( int newJuice ) -{ - bool reduced = newJuice < m_iJuice; - if ( reduced ) - { - // Fire 1/2 way output and/or empyt output - int oneHalfJuice = (int)(MaxJuice() * 0.5f); - if ( newJuice <= oneHalfJuice && m_iJuice > oneHalfJuice ) - { - m_OnHalfEmpty.FireOutput( this, this ); - } - - if ( newJuice <= 0 ) - { - m_OnEmpty.FireOutput( this, this ); - } - } - else if ( newJuice != m_iJuice && - newJuice == (int)MaxJuice() ) - { - m_OnFull.FireOutput( this, this ); - } - m_iJuice = newJuice; -} - -void CNewRecharge::InputRecharge( inputdata_t &inputdata ) -{ - Recharge(); -} - -void CNewRecharge::InputSetCharge( inputdata_t &inputdata ) -{ - ResetSequence( LookupSequence( "idle" ) ); - - int iJuice = inputdata.value.Int(); - - m_flJuice = m_iMaxJuice = m_iJuice = iJuice; - StudioFrameAdvance(); -} - -void CNewRecharge::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - // if it's not a player, ignore - if ( !pActivator || !pActivator->IsPlayer() ) - return; - - CBasePlayer *pPlayer = static_cast(pActivator); - - // Reset to a state of continuous use. - m_iCaps = FCAP_CONTINUOUS_USE; - - if ( m_iOn ) - { - float flCharges = CHARGES_PER_SECOND; - float flCalls = CALLS_PER_SECOND; - - if ( HasSpawnFlags( SF_CITADEL_RECHARGER ) ) - flCharges = CITADEL_CHARGES_PER_SECOND; - - m_flJuice -= flCharges / flCalls; - StudioFrameAdvance(); - } - - // Only usable if you have the HEV suit on - if ( !pPlayer->IsSuitEquipped() ) - { - if (m_flSoundTime <= gpGlobals->curtime) - { - m_flSoundTime = gpGlobals->curtime + 0.62; - EmitSound( "SuitRecharge.Deny" ); - } - return; - } - - // if there is no juice left, turn it off - if ( m_iJuice <= 0 ) - { - // Start our deny animation over again - ResetSequence( LookupSequence( "emptyclick" ) ); - - m_nState = 1; - - // Shut off - Off(); - - // Play a deny sound - if ( m_flSoundTime <= gpGlobals->curtime ) - { - m_flSoundTime = gpGlobals->curtime + 0.62; - EmitSound( "SuitRecharge.Deny" ); - } - - return; - } - - // Get our maximum armor value - int nMaxArmor = 100; - if ( HasSpawnFlags( SF_CITADEL_RECHARGER ) ) - { - nMaxArmor = sk_suitcharger_citadel_maxarmor.GetInt(); - } - - int nIncrementArmor = 1; - - // The citadel charger gives more per charge and also gives health - if ( HasSpawnFlags( SF_CITADEL_RECHARGER ) ) - { - nIncrementArmor = 10; - -#ifdef HL2MP - nIncrementArmor = 2; -#endif - - // Also give health for the citadel version. - if ( pActivator->GetHealth() < pActivator->GetMaxHealth() && m_flNextCharge < gpGlobals->curtime ) - { - pActivator->TakeHealth( 5, DMG_GENERIC ); - } - } - - // If we're over our limit, debounce our keys - if ( pPlayer->ArmorValue() >= nMaxArmor) - { - // Citadel charger must also be at max health - if ( !HasSpawnFlags(SF_CITADEL_RECHARGER) || ( HasSpawnFlags( SF_CITADEL_RECHARGER ) && pActivator->GetHealth() >= pActivator->GetMaxHealth() ) ) - { - // Make the user re-use me to get started drawing health. - pPlayer->m_afButtonPressed &= ~IN_USE; - m_iCaps = FCAP_IMPULSE_USE; - - EmitSound( "SuitRecharge.Deny" ); - return; - } - } - - // This is bumped out if used within the time period - SetNextThink( gpGlobals->curtime + CHARGE_RATE ); - SetThink( &CNewRecharge::Off ); - - // Time to recharge yet? - if ( m_flNextCharge >= gpGlobals->curtime ) - return; - - // Play the on sound or the looping charging sound - if ( !m_iOn ) - { - m_iOn++; - EmitSound( "SuitRecharge.Start" ); - m_flSoundTime = 0.56 + gpGlobals->curtime; - - m_OnPlayerUse.FireOutput( pActivator, this ); - } - - if ((m_iOn == 1) && (m_flSoundTime <= gpGlobals->curtime)) - { - m_iOn++; - CPASAttenuationFilter filter( this, "SuitRecharge.ChargingLoop" ); - filter.MakeReliable(); - EmitSound( filter, entindex(), "SuitRecharge.ChargingLoop" ); - } - - // Give armor if we need it - if ( pPlayer->ArmorValue() < nMaxArmor ) - { - UpdateJuice( m_iJuice - nIncrementArmor ); - pPlayer->IncrementArmorValue( nIncrementArmor, nMaxArmor ); - } - - // Send the output. - float flRemaining = m_iJuice / MaxJuice(); - m_OutRemainingCharge.Set(flRemaining, pActivator, this); - - // govern the rate of charge - m_flNextCharge = gpGlobals->curtime + 0.1; -} - -void CNewRecharge::Recharge(void) -{ - EmitSound( "SuitRecharge.Start" ); - ResetSequence( LookupSequence( "idle" ) ); - - UpdateJuice( (int)MaxJuice() ); - - m_nState = 0; - m_flJuice = m_iJuice; - m_iReactivate = 0; - StudioFrameAdvance(); - - SetThink( &CNewRecharge::SUB_DoNothing ); -} - -void CNewRecharge::Off(void) -{ - // Stop looping sound. - if (m_iOn > 1) - { - StopSound( "SuitRecharge.ChargingLoop" ); - } - - if ( m_nState == 1 ) - { - SetCycle( 1.0f ); - } - - m_iOn = 0; - m_flJuice = m_iJuice; - - if ( m_iReactivate == 0 ) - { - if ((!m_iJuice) && g_pGameRules->FlHEVChargerRechargeTime() > 0 ) - { - if ( HasSpawnFlags( SF_CITADEL_RECHARGER ) ) - { - m_iReactivate = (int)(g_pGameRules->FlHEVChargerRechargeTime() * 2); - } - else - { - m_iReactivate = (int)g_pGameRules->FlHEVChargerRechargeTime(); - } - SetNextThink( gpGlobals->curtime + m_iReactivate ); - SetThink(&CNewRecharge::Recharge); - } - else - { - SetThink( NULL ); - } - } -} diff --git a/game/server/hl2/func_tank.cpp b/game/server/hl2/func_tank.cpp deleted file mode 100644 index c2de249a6..000000000 --- a/game/server/hl2/func_tank.cpp +++ /dev/null @@ -1,4421 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ==== -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#include "func_tank.h" -#include "Sprite.h" -#include "EnvLaser.h" -#include "basecombatweapon.h" -#include "explode.h" -#include "eventqueue.h" -#include "gamerules.h" -#include "ammodef.h" -#include "in_buttons.h" -#include "soundent.h" -#include "ndebugoverlay.h" -#include "grenade_beam.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "physics_cannister.h" -#include "decals.h" -#include "shake.h" -#include "particle_smokegrenade.h" -#include "player.h" -#include "entitylist.h" -#include "IEffects.h" -#include "ai_basenpc.h" -#include "ai_behavior_functank.h" -#include "weapon_rpg.h" -#include "effects.h" -#include "iservervehicle.h" -#include "soundenvelope.h" -#include "effect_dispatch_data.h" -#include "te_effect_dispatch.h" -#include "props.h" -#include "rumble_shared.h" -#include "particle_parse.h" - -#ifdef HL2_DLL -#include "hl2_player.h" -#endif //HL2_DLL - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern Vector PointOnLineNearestPoint(const Vector& vStartPos, const Vector& vEndPos, const Vector& vPoint); - -ConVar mortar_visualize("mortar_visualize", "0" ); - -BEGIN_DATADESC( CFuncTank ) - DEFINE_KEYFIELD( m_yawRate, FIELD_FLOAT, "yawrate" ), - DEFINE_KEYFIELD( m_yawRange, FIELD_FLOAT, "yawrange" ), - DEFINE_KEYFIELD( m_yawTolerance, FIELD_FLOAT, "yawtolerance" ), - DEFINE_KEYFIELD( m_pitchRate, FIELD_FLOAT, "pitchrate" ), - DEFINE_KEYFIELD( m_pitchRange, FIELD_FLOAT, "pitchrange" ), - DEFINE_KEYFIELD( m_pitchTolerance, FIELD_FLOAT, "pitchtolerance" ), - DEFINE_KEYFIELD( m_fireRate, FIELD_FLOAT, "firerate" ), - DEFINE_FIELD( m_fireTime, FIELD_TIME ), - DEFINE_KEYFIELD( m_persist, FIELD_FLOAT, "persistence" ), - DEFINE_KEYFIELD( m_persist2, FIELD_FLOAT, "persistence2" ), - DEFINE_KEYFIELD( m_minRange, FIELD_FLOAT, "minRange" ), - DEFINE_KEYFIELD( m_maxRange, FIELD_FLOAT, "maxRange" ), - DEFINE_FIELD( m_flMinRange2, FIELD_FLOAT ), - DEFINE_FIELD( m_flMaxRange2, FIELD_FLOAT ), - DEFINE_KEYFIELD( m_iAmmoCount, FIELD_INTEGER, "ammo_count" ), - DEFINE_KEYFIELD( m_spriteScale, FIELD_FLOAT, "spritescale" ), - DEFINE_KEYFIELD( m_iszSpriteSmoke, FIELD_STRING, "spritesmoke" ), - DEFINE_KEYFIELD( m_iszSpriteFlash, FIELD_STRING, "spriteflash" ), - DEFINE_KEYFIELD( m_bulletType, FIELD_INTEGER, "bullet" ), - DEFINE_FIELD( m_nBulletCount, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_spread, FIELD_INTEGER, "firespread" ), - DEFINE_KEYFIELD( m_iBulletDamage, FIELD_INTEGER, "bullet_damage" ), - DEFINE_KEYFIELD( m_iBulletDamageVsPlayer, FIELD_INTEGER, "bullet_damage_vs_player" ), - DEFINE_KEYFIELD( m_iszMaster, FIELD_STRING, "master" ), - -#ifdef HL2_EPISODIC - DEFINE_KEYFIELD( m_iszAmmoType, FIELD_STRING, "ammotype" ), - DEFINE_FIELD( m_iAmmoType, FIELD_INTEGER ), -#else - DEFINE_FIELD( m_iSmallAmmoType, FIELD_INTEGER ), - DEFINE_FIELD( m_iMediumAmmoType, FIELD_INTEGER ), - DEFINE_FIELD( m_iLargeAmmoType, FIELD_INTEGER ), -#endif // HL2_EPISODIC - - DEFINE_KEYFIELD( m_soundStartRotate, FIELD_SOUNDNAME, "rotatestartsound" ), - DEFINE_KEYFIELD( m_soundStopRotate, FIELD_SOUNDNAME, "rotatestopsound" ), - DEFINE_KEYFIELD( m_soundLoopRotate, FIELD_SOUNDNAME, "rotatesound" ), - DEFINE_KEYFIELD( m_flPlayerGracePeriod, FIELD_FLOAT, "playergraceperiod" ), - DEFINE_KEYFIELD( m_flIgnoreGraceUpto, FIELD_FLOAT, "ignoregraceupto" ), - DEFINE_KEYFIELD( m_flPlayerLockTimeBeforeFire, FIELD_FLOAT, "playerlocktimebeforefire" ), - DEFINE_FIELD( m_flLastSawNonPlayer, FIELD_TIME ), - - DEFINE_FIELD( m_yawCenter, FIELD_FLOAT ), - DEFINE_FIELD( m_yawCenterWorld, FIELD_FLOAT ), - DEFINE_FIELD( m_pitchCenter, FIELD_FLOAT ), - DEFINE_FIELD( m_pitchCenterWorld, FIELD_FLOAT ), - DEFINE_FIELD( m_fireLast, FIELD_TIME ), - DEFINE_FIELD( m_lastSightTime, FIELD_TIME ), - DEFINE_FIELD( m_barrelPos, FIELD_VECTOR ), - DEFINE_FIELD( m_sightOrigin, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_hFuncTankTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_hController, FIELD_EHANDLE ), - DEFINE_FIELD( m_vecControllerUsePos, FIELD_VECTOR ), - DEFINE_FIELD( m_flNextAttack, FIELD_TIME ), - DEFINE_FIELD( m_targetEntityName, FIELD_STRING ), - DEFINE_FIELD( m_hTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_vTargetPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecNPCIdleTarget, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_persist2burst, FIELD_FLOAT), - //DEFINE_FIELD( m_parentMatrix, FIELD_MATRIX ), // DON'T SAVE - DEFINE_FIELD( m_hControlVolume, FIELD_EHANDLE ), - DEFINE_KEYFIELD( m_iszControlVolume, FIELD_STRING, "control_volume" ), - DEFINE_FIELD( m_flNextControllerSearch, FIELD_TIME ), - DEFINE_FIELD( m_bShouldFindNPCs, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bNPCInRoute, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_iszNPCManPoint, FIELD_STRING, "npc_man_point" ), - DEFINE_FIELD( m_bReadyToFire, FIELD_BOOLEAN ), - - DEFINE_KEYFIELD( m_bPerformLeading, FIELD_BOOLEAN, "LeadTarget" ), - DEFINE_FIELD( m_flStartLeadFactor, FIELD_FLOAT ), - DEFINE_FIELD( m_flStartLeadFactorTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextLeadFactor, FIELD_FLOAT ), - DEFINE_FIELD( m_flNextLeadFactorTime, FIELD_TIME ), - - // Used for when the gun is attached to another entity - DEFINE_KEYFIELD( m_iszBaseAttachment, FIELD_STRING, "gun_base_attach" ), - DEFINE_KEYFIELD( m_iszBarrelAttachment, FIELD_STRING, "gun_barrel_attach" ), -// DEFINE_FIELD( m_nBarrelAttachment, FIELD_INTEGER ), - - // Used when the gun is actually a part of the parent entity, and pose params aim it - DEFINE_KEYFIELD( m_iszYawPoseParam, FIELD_STRING, "gun_yaw_pose_param" ), - DEFINE_KEYFIELD( m_iszPitchPoseParam, FIELD_STRING, "gun_pitch_pose_param" ), - DEFINE_KEYFIELD( m_flYawPoseCenter, FIELD_FLOAT, "gun_yaw_pose_center" ), - DEFINE_KEYFIELD( m_flPitchPoseCenter, FIELD_FLOAT, "gun_pitch_pose_center" ), - DEFINE_FIELD( m_bUsePoseParameters, FIELD_BOOLEAN ), - - DEFINE_KEYFIELD( m_iEffectHandling, FIELD_INTEGER, "effecthandling" ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ), - DEFINE_INPUTFUNC( FIELD_VOID, "Deactivate", InputDeactivate ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFireRate", InputSetFireRate ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetDamage", InputSetDamage ), - DEFINE_INPUTFUNC( FIELD_VECTOR, "SetTargetPosition", InputSetTargetPosition ), - DEFINE_INPUTFUNC( FIELD_VECTOR, "SetTargetDir", InputSetTargetDir ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetTargetEntityName", InputSetTargetEntityName ), - DEFINE_INPUTFUNC( FIELD_EHANDLE, "SetTargetEntity", InputSetTargetEntity ), - DEFINE_INPUTFUNC( FIELD_VOID, "ClearTargetEntity", InputClearTargetEntity ), - DEFINE_INPUTFUNC( FIELD_STRING, "FindNPCToManTank", InputFindNPCToManTank ), - DEFINE_INPUTFUNC( FIELD_VOID, "StopFindingNPCs", InputStopFindingNPCs ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartFindingNPCs", InputStartFindingNPCs ), - DEFINE_INPUTFUNC( FIELD_VOID, "ForceNPCOff", InputForceNPCOff ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetMaxRange", InputSetMaxRange ), - - // Outputs - DEFINE_OUTPUT(m_OnFire, "OnFire"), - DEFINE_OUTPUT(m_OnLoseTarget, "OnLoseTarget"), - DEFINE_OUTPUT(m_OnAquireTarget, "OnAquireTarget"), - DEFINE_OUTPUT(m_OnAmmoDepleted, "OnAmmoDepleted"), - DEFINE_OUTPUT(m_OnGotController, "OnGotController"), - DEFINE_OUTPUT(m_OnLostController, "OnLostController"), - DEFINE_OUTPUT(m_OnGotPlayerController, "OnGotPlayerController"), - DEFINE_OUTPUT(m_OnLostPlayerController, "OnLostPlayerController"), - DEFINE_OUTPUT(m_OnReadyToFire, "OnReadyToFire"), -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CFuncTank::CFuncTank() -{ - m_nBulletCount = 0; - - m_bNPCInRoute = false; - m_flNextControllerSearch = 0; - m_bShouldFindNPCs = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CFuncTank::~CFuncTank( void ) -{ - if ( m_soundLoopRotate != NULL_STRING && ( m_spawnflags & SF_TANK_SOUNDON ) ) - { - StopSound( entindex(), CHAN_STATIC, STRING(m_soundLoopRotate) ); - } -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -inline bool CFuncTank::CanFire( void ) -{ - float flTimeDelay = gpGlobals->curtime - m_lastSightTime; - - // Fire when can't see enemy if time is less that persistence time - if ( flTimeDelay <= m_persist ) - return true; - - // Fire when I'm in a persistence2 burst - if ( flTimeDelay <= m_persist2burst ) - return true; - - // If less than persistence2, occasionally do another burst - if ( flTimeDelay <= m_persist2 ) - { - if ( random->RandomInt( 0, 30 ) == 0 ) - { - m_persist2burst = flTimeDelay + 0.5f; - return true; - } - } - - return false; -} - -//------------------------------------------------------------------------------ -// Purpose: Input handler for activating the tank. -//------------------------------------------------------------------------------ -void CFuncTank::InputActivate( inputdata_t &inputdata ) -{ - TankActivate(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncTank::TankActivate( void ) -{ - m_spawnflags |= SF_TANK_ACTIVE; - SetNextThink( gpGlobals->curtime + 0.1f ); - m_fireLast = gpGlobals->curtime; -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for deactivating the tank. -//----------------------------------------------------------------------------- -void CFuncTank::InputDeactivate( inputdata_t &inputdata ) -{ - TankDeactivate(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncTank::TankDeactivate( void ) -{ - m_spawnflags &= ~SF_TANK_ACTIVE; - m_fireLast = 0; - StopRotSound(); -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for changing the name of the tank's target entity. -//----------------------------------------------------------------------------- -void CFuncTank::InputSetTargetEntityName( inputdata_t &inputdata ) -{ - m_targetEntityName = inputdata.value.StringID(); - m_hTarget = FindTarget( m_targetEntityName, inputdata.pActivator ); - - // No longer aim at target position if have one - m_spawnflags &= ~SF_TANK_AIM_AT_POS; -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for setting a new target entity by ehandle. -//----------------------------------------------------------------------------- -void CFuncTank::InputSetTargetEntity( inputdata_t &inputdata ) -{ - if ( inputdata.value.Entity() != NULL ) - { - m_targetEntityName = inputdata.value.Entity()->GetEntityName(); - } - else - { - m_targetEntityName = NULL_STRING; - } - m_hTarget = inputdata.value.Entity(); - - // No longer aim at target position if have one - m_spawnflags &= ~SF_TANK_AIM_AT_POS; -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for clearing the tank's target entity -//----------------------------------------------------------------------------- -void CFuncTank::InputClearTargetEntity( inputdata_t &inputdata ) -{ - m_targetEntityName = NULL_STRING; - m_hTarget = NULL; - - // No longer aim at target position if have one - m_spawnflags &= ~SF_TANK_AIM_AT_POS; -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for setting the rate of fire in shots per second. -//----------------------------------------------------------------------------- -void CFuncTank::InputSetFireRate( inputdata_t &inputdata ) -{ - m_fireRate = inputdata.value.Float(); -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for setting the damage -//----------------------------------------------------------------------------- -void CFuncTank::InputSetDamage( inputdata_t &inputdata ) -{ - m_iBulletDamage = inputdata.value.Int(); -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for setting the target as a position. -//----------------------------------------------------------------------------- -void CFuncTank::InputSetTargetPosition( inputdata_t &inputdata ) -{ - m_spawnflags |= SF_TANK_AIM_AT_POS; - m_hTarget = NULL; - - inputdata.value.Vector3D( m_vTargetPosition ); -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for setting the target as a position. -//----------------------------------------------------------------------------- -void CFuncTank::InputSetTargetDir( inputdata_t &inputdata ) -{ - m_spawnflags |= SF_TANK_AIM_AT_POS; - m_hTarget = NULL; - - Vector vecTargetDir; - inputdata.value.Vector3D( vecTargetDir ); - m_vTargetPosition = GetAbsOrigin() + m_barrelPos.LengthSqr() * vecTargetDir; -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for telling the func_tank to find an NPC to man it. -//----------------------------------------------------------------------------- -void CFuncTank::InputFindNPCToManTank( inputdata_t &inputdata ) -{ - // Verify the func_tank is controllable and available. - if ( !IsNPCControllable() && !IsNPCSetController() ) - return; - - // If we have a controller already - don't look for one. - if ( HasController() ) - return; - - // NPC assigned to man the func_tank? - CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, inputdata.value.StringID() ); - if ( pEntity ) - { - CAI_BaseNPC *pNPC = pEntity->MyNPCPointer(); - if ( pNPC ) - { - // Verify the npc has the func_tank controller behavior. - CAI_FuncTankBehavior *pBehavior; - if ( pNPC->GetBehavior( &pBehavior ) ) - { - m_hController = pNPC; - pBehavior->SetFuncTank( this ); - NPC_SetInRoute( true ); - return; - } - } - } - - // No controller? Find a nearby NPC who can man this func_tank. - NPC_FindController(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CFuncTank::InputStopFindingNPCs( inputdata_t &inputdata ) -{ - m_bShouldFindNPCs = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CFuncTank::InputStartFindingNPCs( inputdata_t &inputdata ) -{ - m_bShouldFindNPCs = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CFuncTank::InputForceNPCOff( inputdata_t &inputdata ) -{ - // Interrupt any npc in route (ally or not). - if ( NPC_InRoute() ) - { - // Interrupt the npc's route. - NPC_InterruptRoute(); - } - - // If we don't have a controller - then the gun should be free. - if ( !m_hController ) - return; - - CAI_BaseNPC *pNPC = m_hController->MyNPCPointer(); - if ( !pNPC ) - return; - - CAI_FuncTankBehavior *pBehavior; - if ( pNPC->GetBehavior( &pBehavior ) ) - { - pBehavior->Dismount(); - } - - m_hController = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CFuncTank::InputSetMaxRange( inputdata_t &inputdata ) -{ - m_maxRange = inputdata.value.Float(); - m_flMaxRange2 = m_maxRange * m_maxRange; -} - -//----------------------------------------------------------------------------- -// Purpose: Find the closest NPC with the func_tank behavior. -//----------------------------------------------------------------------------- -void CFuncTank::NPC_FindController( void ) -{ - // Not NPC controllable or controllable on by specified npc's return. - if ( !IsNPCControllable() || IsNPCSetController() ) - return; - - // Initialize for finding closest NPC. - CAI_BaseNPC *pClosestNPC = NULL; - float flClosestDist2 = ( FUNCTANK_DISTANCE_MAX * FUNCTANK_DISTANCE_MAX ); - float flMinDistToEnemy2 = ( FUNCTANK_DISTANCE_MIN_TO_ENEMY * FUNCTANK_DISTANCE_MIN_TO_ENEMY ); - CAI_FuncTankBehavior *pClosestBehavior = NULL; - - // Get the mount position. - Vector vecMountPos; - NPC_FindManPoint( vecMountPos ); - - // Search through the AI list for the closest NPC with the func_tank behavior. - CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); - int nAICount = g_AI_Manager.NumAIs(); - for ( int iAI = 0; iAI < nAICount; ++iAI ) - { - CAI_BaseNPC *pNPC = ppAIs[iAI]; - if ( !pNPC ) - continue; - - if ( !pNPC->IsAlive() ) - continue; - - if ( pNPC->IsInAScript() ) - continue; - - CAI_FuncTankBehavior *pBehavior; - if ( pNPC->GetBehavior( &pBehavior ) ) - { - // Don't mount the func_tank if your "enemy" is within X feet or it or the npc. - CBaseEntity *pEnemy = pNPC->GetEnemy(); - - if ( pEnemy ) - { - if ( !IsEntityInViewCone(pEnemy) ) - { - // Don't mount the tank if the tank can't be aimed at the enemy. - continue; - } - - float flDist2 = ( pEnemy->GetAbsOrigin() - pNPC->GetAbsOrigin() ).LengthSqr(); - if ( flDist2 < flMinDistToEnemy2 ) - continue; - - flDist2 = ( vecMountPos - pEnemy->GetAbsOrigin() ).LengthSqr(); - if ( flDist2 < flMinDistToEnemy2 ) - continue; - - if ( !pNPC->FVisible( vecMountPos + pNPC->GetViewOffset() ) ) - continue; - } - - trace_t tr; - UTIL_TraceEntity( pNPC, vecMountPos, vecMountPos, MASK_NPCSOLID, this, pNPC->GetCollisionGroup(), &tr ); - if( tr.startsolid || tr.fraction < 1.0 ) - { - // Don't mount the tank if someone/something is located on the control point. - continue; - } - - if ( !pBehavior->HasFuncTank() && !pBehavior->IsBusy() ) - { - float flDist2 = ( vecMountPos - pNPC->GetAbsOrigin() ).LengthSqr(); - if ( flDist2 < flClosestDist2 ) - { - pClosestNPC = pNPC; - pClosestBehavior = pBehavior; - flClosestDist2 = flDist2; - } - } - } - } - - // Set the closest NPC as controller. - if ( pClosestNPC ) - { - m_hController = pClosestNPC; - pClosestBehavior->SetFuncTank( this ); - NPC_SetInRoute( true ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CFuncTank::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - // -------------- - // State - // -------------- - char tempstr[255]; - if (IsActive()) - { - Q_strncpy(tempstr,"State: Active",sizeof(tempstr)); - } - else - { - Q_strncpy(tempstr,"State: Inactive",sizeof(tempstr)); - } - EntityText(text_offset,tempstr,0); - text_offset++; - - // ------------------- - // Print Firing Speed - // -------------------- - Q_snprintf(tempstr,sizeof(tempstr),"Fire Rate: %f",m_fireRate); - - EntityText(text_offset,tempstr,0); - text_offset++; - - // -------------- - // Print Target - // -------------- - if (m_hTarget!=NULL) - { - Q_snprintf(tempstr,sizeof(tempstr),"Target: %s",m_hTarget->GetDebugName()); - } - else - { - Q_snprintf(tempstr,sizeof(tempstr),"Target: - "); - } - EntityText(text_offset,tempstr,0); - text_offset++; - - // -------------- - // Target Pos - // -------------- - if (m_spawnflags & SF_TANK_AIM_AT_POS) - { - Q_snprintf(tempstr,sizeof(tempstr),"Aim Pos: %3.0f %3.0f %3.0f",m_vTargetPosition.x,m_vTargetPosition.y,m_vTargetPosition.z); - } - else - { - Q_snprintf(tempstr,sizeof(tempstr),"Aim Pos: - "); - } - EntityText(text_offset,tempstr,0); - text_offset++; - - } - return text_offset; -} - -//----------------------------------------------------------------------------- -// Purpose: Override base class to add display of fly direction -// Input : -// Output : -//----------------------------------------------------------------------------- -void CFuncTank::DrawDebugGeometryOverlays(void) -{ - // Center - QAngle angCenter; - Vector vecForward; - angCenter = QAngle( 0, YawCenterWorld(), 0 ); - AngleVectors( angCenter, &vecForward ); - NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + (vecForward * 64), 255,255,255, true, 0.1); - - // Draw the yaw ranges - angCenter = QAngle( 0, YawCenterWorld() + m_yawRange, 0 ); - AngleVectors( angCenter, &vecForward ); - NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + (vecForward * 128), 0,255,0, true, 0.1); - angCenter = QAngle( 0, YawCenterWorld() - m_yawRange, 0 ); - AngleVectors( angCenter, &vecForward ); - NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + (vecForward * 128), 0,255,0, true, 0.1); - - // Draw the pitch ranges - angCenter = QAngle( PitchCenterWorld() + m_pitchRange, 0, 0 ); - AngleVectors( angCenter, &vecForward ); - NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + (vecForward * 128), 255,0,0, true, 0.1); - angCenter = QAngle( PitchCenterWorld() - m_pitchRange, 0, 0 ); - AngleVectors( angCenter, &vecForward ); - NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + (vecForward * 128), 255,0,0, true, 0.1); - - BaseClass::DrawDebugGeometryOverlays(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pAttacker - -// flDamage - -// vecDir - -// ptr - -// bitsDamageType - -//----------------------------------------------------------------------------- -void CFuncTank::TraceAttack( CBaseEntity *pAttacker, float flDamage, const Vector &vecDir, trace_t *ptr, int bitsDamageType) -{ - if (m_spawnflags & SF_TANK_DAMAGE_KICK) - { - // Deflect the func_tank - // Only adjust yaw for now - if (pAttacker) - { - Vector vFromAttacker = (pAttacker->EyePosition()-GetAbsOrigin()); - vFromAttacker.z = 0; - VectorNormalize(vFromAttacker); - - Vector vFromAttacker2 = (ptr->endpos-GetAbsOrigin()); - vFromAttacker2.z = 0; - VectorNormalize(vFromAttacker2); - - - Vector vCrossProduct; - CrossProduct(vFromAttacker,vFromAttacker2, vCrossProduct); - - QAngle angles; - angles = GetLocalAngles(); - if (vCrossProduct.z > 0) - { - angles.y += 10; - } - else - { - angles.y -= 10; - } - - // Limit against range in y - if ( angles.y > m_yawCenter + m_yawRange ) - { - angles.y = m_yawCenter + m_yawRange; - } - else if ( angles.y < (m_yawCenter - m_yawRange) ) - { - angles.y = (m_yawCenter - m_yawRange); - } - - SetLocalAngles( angles ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : targetName - -// pActivator - -//----------------------------------------------------------------------------- -CBaseEntity *CFuncTank::FindTarget( string_t targetName, CBaseEntity *pActivator ) -{ - return gEntList.FindEntityGenericNearest( STRING( targetName ), GetAbsOrigin(), 0, this, pActivator ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Caches entity key values until spawn is called. -// Input : szKeyName - -// szValue - -// Output : -//----------------------------------------------------------------------------- -bool CFuncTank::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "barrel")) - { - m_barrelPos.x = atof(szValue); - return true; - } - - if (FStrEq(szKeyName, "barrely")) - { - m_barrelPos.y = atof(szValue); - return true; - } - - if (FStrEq(szKeyName, "barrelz")) - { - m_barrelPos.z = atof(szValue); - return true; - } - - return BaseClass::KeyValue( szKeyName, szValue ); -} - - -static Vector gTankSpread[] = -{ - Vector( 0, 0, 0 ), // perfect - Vector( 0.025, 0.025, 0.025 ), // small cone - Vector( 0.05, 0.05, 0.05 ), // medium cone - Vector( 0.1, 0.1, 0.1 ), // large cone - Vector( 0.25, 0.25, 0.25 ), // extra-large cone -}; -#define MAX_FIRING_SPREADS ARRAYSIZE(gTankSpread) - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncTank::Spawn( void ) -{ - Precache(); - -#ifdef HL2_EPISODIC - m_iAmmoType = GetAmmoDef()->Index( STRING( m_iszAmmoType ) ); -#else - m_iSmallAmmoType = GetAmmoDef()->Index("Pistol"); - m_iMediumAmmoType = GetAmmoDef()->Index("SMG1"); - m_iLargeAmmoType = GetAmmoDef()->Index("AR2"); -#endif // HL2_EPISODIC - - SetMoveType( MOVETYPE_PUSH ); // so it doesn't get pushed by anything - SetSolid( SOLID_VPHYSICS ); - SetModel( STRING( GetModelName() ) ); - AddEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID ); - - if ( HasSpawnFlags(SF_TANK_NOTSOLID) ) - { - AddSolidFlags( FSOLID_NOT_SOLID ); - } - - m_hControlVolume = NULL; - - if ( GetParent() && GetParent()->GetBaseAnimating() ) - { - CBaseAnimating *pAnim = GetParent()->GetBaseAnimating(); - if ( m_iszBaseAttachment != NULL_STRING ) - { - int nAttachment = pAnim->LookupAttachment( STRING( m_iszBaseAttachment ) ); - if ( nAttachment != 0 ) - { - SetParent( pAnim, nAttachment ); - SetLocalOrigin( vec3_origin ); - SetLocalAngles( vec3_angle ); - } - } - - m_bUsePoseParameters = (m_iszYawPoseParam != NULL_STRING) && (m_iszPitchPoseParam != NULL_STRING); - - if ( m_iszBarrelAttachment != NULL_STRING ) - { - if ( m_bUsePoseParameters ) - { - pAnim->SetPoseParameter( STRING( m_iszYawPoseParam ), 0 ); - pAnim->SetPoseParameter( STRING( m_iszPitchPoseParam ), 0 ); - pAnim->InvalidateBoneCache(); - } - - m_nBarrelAttachment = pAnim->LookupAttachment( STRING(m_iszBarrelAttachment) ); - - Vector vecWorldBarrelPos; - QAngle worldBarrelAngle; - pAnim->GetAttachment( m_nBarrelAttachment, vecWorldBarrelPos, worldBarrelAngle ); - VectorITransform( vecWorldBarrelPos, EntityToWorldTransform( ), m_barrelPos ); - } - - if ( m_bUsePoseParameters ) - { - // In this case, we're relying on the parent to have the gun model - AddEffects( EF_NODRAW ); - QAngle localAngles( m_flPitchPoseCenter, m_flYawPoseCenter, 0 ); - SetLocalAngles( localAngles ); - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NOCLIP ); - - // If our parent is a prop_dynamic, make it use hitboxes for renderbox - CDynamicProp *pProp = dynamic_cast(GetParent()); - if ( pProp ) - { - pProp->m_bUseHitboxesForRenderBox = true; - } - } - } - - // For smoothing out leading - m_flStartLeadFactor = 1.0f; - m_flNextLeadFactor = 1.0f; - m_flStartLeadFactorTime = gpGlobals->curtime; - m_flNextLeadFactorTime = gpGlobals->curtime + 1.0f; - - m_yawCenter = GetLocalAngles().y; - m_yawCenterWorld = GetAbsAngles().y; - m_pitchCenter = GetLocalAngles().x; - m_pitchCenterWorld = GetAbsAngles().y; - m_vTargetPosition = vec3_origin; - - if ( IsActive() || (IsControllable() && !HasController()) ) - { - // Think to find controllers. - SetNextThink( gpGlobals->curtime + 1.0f ); - m_flNextControllerSearch = gpGlobals->curtime + 1.0f; - } - - UpdateMatrix(); - - m_sightOrigin = WorldBarrelPosition(); // Point at the end of the barrel - - if ( m_spread > (int)MAX_FIRING_SPREADS ) - { - m_spread = 0; - } - - // No longer aim at target position if have one - m_spawnflags &= ~SF_TANK_AIM_AT_POS; - - if (m_spawnflags & SF_TANK_DAMAGE_KICK) - { - m_takedamage = DAMAGE_YES; - } - - // UNDONE: Do this? - //m_targetEntityName = m_target; - if ( GetSolid() != SOLID_NONE ) - { - CreateVPhysics(); - } - - // Setup squared min/max range. - m_flMinRange2 = m_minRange * m_minRange; - m_flMaxRange2 = m_maxRange * m_maxRange; - m_flIgnoreGraceUpto *= m_flIgnoreGraceUpto; - - m_flLastSawNonPlayer = 0; - - if( IsActive() ) - { - m_OnReadyToFire.FireOutput( this, this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncTank::Activate( void ) -{ - BaseClass::Activate(); - - // Necessary for save/load - if ( (m_iszBarrelAttachment != NULL_STRING) && (m_nBarrelAttachment == 0) ) - { - if ( GetParent() && GetParent()->GetBaseAnimating() ) - { - CBaseAnimating *pAnim = GetParent()->GetBaseAnimating(); - m_nBarrelAttachment = pAnim->LookupAttachment( STRING(m_iszBarrelAttachment) ); - } - } -} - -bool CFuncTank::CreateVPhysics() -{ - VPhysicsInitShadow( false, false ); - return true; -} - - -void CFuncTank::Precache( void ) -{ - if ( m_iszSpriteSmoke != NULL_STRING ) - PrecacheModel( STRING(m_iszSpriteSmoke) ); - if ( m_iszSpriteFlash != NULL_STRING ) - PrecacheModel( STRING(m_iszSpriteFlash) ); - - if ( m_soundStartRotate != NULL_STRING ) - PrecacheScriptSound( STRING(m_soundStartRotate) ); - if ( m_soundStopRotate != NULL_STRING ) - PrecacheScriptSound( STRING(m_soundStopRotate) ); - if ( m_soundLoopRotate != NULL_STRING ) - PrecacheScriptSound( STRING(m_soundLoopRotate) ); - - PrecacheScriptSound( "Func_Tank.BeginUse" ); - - // Precache the combine cannon - if ( m_iEffectHandling == EH_COMBINE_CANNON ) - { - PrecacheScriptSound( "NPC_Combine_Cannon.FireBullet" ); - } -} - -void CFuncTank::UpdateOnRemove( void ) -{ - if ( HasController() ) - { - StopControl(); - } - BaseClass::UpdateOnRemove(); -} - - -//----------------------------------------------------------------------------- -// Barrel position -//----------------------------------------------------------------------------- -void CFuncTank::UpdateMatrix( void ) -{ - m_parentMatrix.InitFromEntity( GetParent(), GetParentAttachment() ); -} - - -//----------------------------------------------------------------------------- -// Barrel position -//----------------------------------------------------------------------------- -Vector CFuncTank::WorldBarrelPosition( void ) -{ - if ( (m_nBarrelAttachment == 0) || !GetParent() ) - { - EntityMatrix tmp; - tmp.InitFromEntity( this ); - return tmp.LocalToWorld( m_barrelPos ); - } - - Vector vecOrigin; - QAngle vecAngles; - CBaseAnimating *pAnim = GetParent()->GetBaseAnimating(); - pAnim->GetAttachment( m_nBarrelAttachment, vecOrigin, vecAngles ); - return vecOrigin; -} - - -//----------------------------------------------------------------------------- -// Make the parent's pose parameters match the func_tank -//----------------------------------------------------------------------------- -void CFuncTank::PhysicsSimulate( void ) -{ - BaseClass::PhysicsSimulate(); - - if ( m_bUsePoseParameters && GetParent() ) - { - const QAngle &angles = GetLocalAngles(); - CBaseAnimating *pAnim = GetParent()->GetBaseAnimating(); - pAnim->SetPoseParameter( STRING( m_iszYawPoseParam ), angles.y ); - pAnim->SetPoseParameter( STRING( m_iszPitchPoseParam ), angles.x ); - pAnim->StudioFrameAdvance(); - } -} - -//============================================================================= -// -// TANK CONTROLLING -// - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CFuncTank::OnControls( CBaseEntity *pTest ) -{ - // Is the tank controllable. - if ( !IsControllable() ) - return false; - - if ( !m_hControlVolume ) - { - // Find our control volume - if ( m_iszControlVolume != NULL_STRING ) - { - m_hControlVolume = dynamic_cast( gEntList.FindEntityByName( NULL, m_iszControlVolume ) ); - } - - if (( !m_hControlVolume ) && IsControllable() ) - { - Msg( "ERROR: Couldn't find control volume for player-controllable func_tank %s.\n", STRING(GetEntityName()) ); - return false; - } - } - - if ( m_hControlVolume->IsTouching( pTest ) ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CFuncTank::StartControl( CBaseCombatCharacter *pController ) -{ - // Check to see if we have a controller. - if ( HasController() && GetController() != pController ) - return false; - - // Team only or disabled? - if ( m_iszMaster != NULL_STRING ) - { - if ( !UTIL_IsMasterTriggered( m_iszMaster, pController ) ) - return false; - } - - // Set func_tank as manned by player/npc. - m_hController = pController; - if ( pController->IsPlayer() ) - { - m_spawnflags |= SF_TANK_PLAYER; - - CBasePlayer *pPlayer = static_cast( m_hController.Get() ); - pPlayer->m_Local.m_iHideHUD |= HIDEHUD_WEAPONSELECTION; - } - else - { - m_spawnflags |= SF_TANK_NPC; - NPC_SetInRoute( false ); - } - - // Holster player/npc weapon - if ( m_hController->GetActiveWeapon() ) - { - m_hController->GetActiveWeapon()->Holster(); - } - - // Set the controller's position to be the use position. - m_vecControllerUsePos = m_hController->GetLocalOrigin(); - - EmitSound( "Func_Tank.BeginUse" ); - - SetNextThink( gpGlobals->curtime + 0.1f ); - - // Let the map maker know a controller has been found - if ( m_hController->IsPlayer() ) - { - m_OnGotPlayerController.FireOutput( this, this ); - } - else - { - m_OnGotController.FireOutput( this, this ); - } - - OnStartControlled(); - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// TODO: bring back the controllers current weapon -//----------------------------------------------------------------------------- -void CFuncTank::StopControl() -{ - // Do we have a controller? - if ( !m_hController ) - return; - - OnStopControlled(); - - // Arm player/npc weapon. - if ( m_hController->GetActiveWeapon() ) - { - m_hController->GetActiveWeapon()->Deploy(); - } - - if ( m_hController->IsPlayer() ) - { - CBasePlayer *pPlayer = static_cast( m_hController.Get() ); - pPlayer->m_Local.m_iHideHUD &= ~HIDEHUD_WEAPONSELECTION; - } - - // Stop thinking. - SetNextThink( TICK_NEVER_THINK ); - - // Let the map maker know a controller has been lost. - if ( m_hController->IsPlayer() ) - { - m_OnLostPlayerController.FireOutput( this, this ); - } - else - { - m_OnLostController.FireOutput( this, this ); - } - - // Reset the func_tank as unmanned (player/npc). - if ( m_hController->IsPlayer() ) - { - m_spawnflags &= ~SF_TANK_PLAYER; - } - else - { - m_spawnflags &= ~SF_TANK_NPC; - } - - m_hController = NULL; - - // Set think, if the func_tank can think on its own. - if ( IsActive() || (IsControllable() && !HasController()) ) - { - // Delay the think to find controllers a bit -#ifdef FUNCTANK_AUTOUSE - m_flNextControllerSearch = gpGlobals->curtime + 1.0f; -#else - m_flNextControllerSearch = gpGlobals->curtime + 5.0f; -#endif//FUNCTANK_AUTOUSE - - SetNextThink( m_flNextControllerSearch ); - } - - SetLocalAngularVelocity( vec3_angle ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Called each frame by the player's ItemPostFrame -//----------------------------------------------------------------------------- -void CFuncTank::ControllerPostFrame( void ) -{ - // Make sure we have a contoller. - Assert( m_hController != NULL ); - - // Control the firing rate. - if ( gpGlobals->curtime < m_flNextAttack ) - return; - - if ( !IsPlayerManned() ) - return; - - CBasePlayer *pPlayer = static_cast( m_hController.Get() ); - if ( ( pPlayer->m_nButtons & IN_ATTACK ) == 0 ) - return; - - Vector forward; - AngleVectors( GetAbsAngles(), &forward ); - m_fireLast = gpGlobals->curtime - (1/m_fireRate) - 0.01; // to make sure the gun doesn't fire too many bullets - - int bulletCount = (int)((gpGlobals->curtime - m_fireLast) * m_fireRate); - - if( HasSpawnFlags( SF_TANK_AIM_ASSISTANCE ) ) - { - // Trace out a hull and if it hits something, adjust the shot to hit that thing. - trace_t tr; - Vector start = WorldBarrelPosition(); - Vector dir = forward; - - UTIL_TraceHull( start, start + forward * 8192, -Vector(8,8,8), Vector(8,8,8), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - if( tr.m_pEnt && tr.m_pEnt->m_takedamage != DAMAGE_NO && (tr.m_pEnt->GetFlags() & FL_AIMTARGET) ) - { - forward = tr.m_pEnt->WorldSpaceCenter() - start; - VectorNormalize( forward ); - } - } - - Fire( bulletCount, WorldBarrelPosition(), forward, pPlayer, false ); - - // HACKHACK -- make some noise (that the AI can hear) - CSoundEnt::InsertSound( SOUND_COMBAT, WorldSpaceCenter(), FUNCTANK_FIREVOLUME, 0.2 ); - - if( m_iAmmoCount > -1 ) - { - if( !(m_iAmmoCount % 10) ) - { - Msg("Ammo Remaining: %d\n", m_iAmmoCount ); - } - - if( --m_iAmmoCount == 0 ) - { - // Kick the player off the gun, and make myself not usable. - m_spawnflags &= ~SF_TANK_CANCONTROL; - StopControl(); - return; - } - } - - SetNextAttack( gpGlobals->curtime + (1/m_fireRate) ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CFuncTank::HasController( void ) -{ - return (m_hController != NULL); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CBaseCombatCharacter -//----------------------------------------------------------------------------- -CBaseCombatCharacter *CFuncTank::GetController( void ) -{ - return m_hController; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CFuncTank::NPC_FindManPoint( Vector &vecPos ) -{ - if ( m_iszNPCManPoint != NULL_STRING ) - { - CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, m_iszNPCManPoint ); - if ( pEntity ) - { - vecPos = pEntity->GetAbsOrigin(); - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: The NPC manning this gun just saw a player for the first time since he left cover -//----------------------------------------------------------------------------- -void CFuncTank::NPC_JustSawPlayer( CBaseEntity *pTarget ) -{ - SetNextAttack( gpGlobals->curtime + m_flPlayerLockTimeBeforeFire ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncTank::NPC_Fire( void ) -{ - // Control the firing rate. - if ( gpGlobals->curtime < m_flNextAttack ) - return; - - // Check for a valid npc controller. - if ( !m_hController ) - return; - - CAI_BaseNPC *pNPC = m_hController->MyNPCPointer(); - if ( !pNPC ) - return; - - // Setup for next round of firing. - if ( m_nBulletCount == 0 ) - { - m_nBulletCount = GetRandomBurst(); - m_fireTime = 1.0f; - } - - // m_fireLast looks like it is only needed for Active non-controlled func_tank. -// m_fireLast = gpGlobals->curtime - (1/m_fireRate) - 0.01; // to make sure the gun doesn't fire too many bullets - - Vector vecBarrelEnd = WorldBarrelPosition(); - Vector vecForward; - AngleVectors( GetAbsAngles(), &vecForward ); - - if ( (pNPC->CapabilitiesGet() & bits_CAP_NO_HIT_SQUADMATES) && pNPC->IsInSquad() ) - { - // Avoid shooting squadmates. - if ( pNPC->IsSquadmateInSpread( vecBarrelEnd, vecBarrelEnd + vecForward * 2048, gTankSpread[m_spread].x, 8*12 ) ) - { - return; - } - } - - if ( !HasSpawnFlags( SF_TANK_ALLOW_PLAYER_HITS ) && (pNPC->CapabilitiesGet() & bits_CAP_NO_HIT_PLAYER) ) - { - // Avoid shooting player. - if ( pNPC->PlayerInSpread( vecBarrelEnd, vecBarrelEnd + vecForward * 2048, gTankSpread[m_spread].x, 8*12 ) ) - { - return; - } - } - - bool bIgnoreSpread = false; - - CBaseEntity *pEnemy = pNPC->GetEnemy(); - if ( HasSpawnFlags( SF_TANK_HACKPLAYERHIT ) && pEnemy && pEnemy->IsPlayer() ) - { - // Every third shot should be fired directly at the player - if ( m_nBulletCount%2 == 0 ) - { - Vector vecBodyTarget = pEnemy->BodyTarget( vecBarrelEnd, false ); - vecForward = (vecBodyTarget - vecBarrelEnd); - VectorNormalize( vecForward ); - bIgnoreSpread = true; - } - } - - // Fire the bullet(s). - Fire( 1, vecBarrelEnd, vecForward, m_hController, bIgnoreSpread ); - --m_nBulletCount; - - // Check ammo counts and dismount when empty. - if( m_iAmmoCount > -1 ) - { - if( --m_iAmmoCount == 0 ) - { - // Disable the func_tank. - m_spawnflags &= ~SF_TANK_CANCONTROL; - - // Remove the npc. - StopControl(); - return; - } - } - - float flFireTime = GetRandomFireTime(); - if ( m_nBulletCount != 0 ) - { - m_fireTime -= flFireTime; - SetNextAttack( gpGlobals->curtime + flFireTime ); - } - else - { - SetNextAttack( gpGlobals->curtime + m_fireTime ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CFuncTank::NPC_HasEnemy( void ) -{ - if ( !IsNPCManned() ) - return false; - - CAI_BaseNPC *pNPC = m_hController->MyNPCPointer(); - Assert( pNPC ); - - return ( pNPC->GetEnemy() != NULL ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncTank::NPC_InterruptRoute( void ) -{ - if ( !m_hController ) - return; - - CAI_BaseNPC *pNPC = m_hController->MyNPCPointer(); - if ( !pNPC ) - return; - - CAI_FuncTankBehavior *pBehavior; - if ( pNPC->GetBehavior( &pBehavior ) ) - { - pBehavior->SetFuncTank( NULL ); - } - - // Reset the npc controller. - m_hController = NULL; - - // No NPC's in route. - NPC_SetInRoute( false ); - - // Delay the think to find controllers a bit - m_flNextControllerSearch = gpGlobals->curtime + 5.0f; - - if ( !HasController() ) - { - // Start thinking to find controllers again - SetNextThink( m_flNextControllerSearch ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CFuncTank::NPC_InterruptController( void ) -{ - // If we don't have a controller - then the gun should be free. - if ( !m_hController ) - return true; - - CAI_BaseNPC *pNPC = m_hController->MyNPCPointer(); - if ( !pNPC || !pNPC->IsPlayerAlly() ) - return false; - - CAI_FuncTankBehavior *pBehavior; - if ( pNPC->GetBehavior( &pBehavior ) ) - { - pBehavior->Dismount(); - } - - m_hController = NULL; - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CFuncTank::GetRandomFireTime( void ) -{ - Assert( m_fireRate != 0 ); - float flOOFireRate = 1.0f / m_fireRate; - float flOOFireRateBy2 = flOOFireRate * 0.5f; - float flOOFireRateBy4 = flOOFireRate * 0.25f; - return random->RandomFloat( flOOFireRateBy4, flOOFireRateBy2 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CFuncTank::GetRandomBurst( void ) -{ - return random->RandomInt( (int)m_fireRate-2, (int)m_fireRate+2 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pActivator - -// *pCaller - -// useType - -// value - -//----------------------------------------------------------------------------- -void CFuncTank::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - if ( !IsControllable() ) - return; - - // player controlled turret - CBasePlayer *pPlayer = ToBasePlayer( pActivator ); - if ( !pPlayer ) - return; - - if ( value == 2 && useType == USE_SET ) - { - ControllerPostFrame(); - } - else if ( m_hController != pPlayer && useType != USE_OFF ) - { - // The player must be within the func_tank controls - if ( !m_hControlVolume ) - { - // Find our control volume - if ( m_iszControlVolume != NULL_STRING ) - { - m_hControlVolume = dynamic_cast( gEntList.FindEntityByName( NULL, m_iszControlVolume ) ); - } - - if (( !m_hControlVolume ) && IsControllable() ) - { - Msg( "ERROR: Couldn't find control volume for player-controllable func_tank %s.\n", STRING(GetEntityName()) ); - return; - } - } - - if ( !m_hControlVolume->IsTouching( pPlayer ) ) - return; - - // Interrupt any npc in route (ally or not). - if ( NPC_InRoute() ) - { - // Interrupt the npc's route. - NPC_InterruptRoute(); - } - - // Interrupt NPC - if possible (they must be allies). - if ( IsNPCControllable() && HasController() ) - { - if ( !NPC_InterruptController() ) - return; - } - - pPlayer->SetUseEntity( this ); - StartControl( pPlayer ); - } - else - { - StopControl(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : range - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CFuncTank::InRange( float range ) -{ - if ( range < m_minRange ) - return FALSE; - if ( (m_maxRange > 0) && (range > m_maxRange) ) - return FALSE; - - return TRUE; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CFuncTank::InRange2( float flRange2 ) -{ - if ( flRange2 < m_flMinRange2 ) - return false; - - if ( ( m_flMaxRange2 > 0.0f ) && ( flRange2 > m_flMaxRange2 ) ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncTank::Think( void ) -{ - FuncTankPreThink(); - - m_hFuncTankTarget = NULL; - - // Look for a new controller? - if ( IsControllable() && !HasController() && (m_flNextControllerSearch <= gpGlobals->curtime) ) - { - if ( m_bShouldFindNPCs && gpGlobals->curtime > 5.0f ) - { - // Check for in route and timer. - if ( !NPC_InRoute() ) - { - NPC_FindController(); - } - } - -#ifdef FUNCTANK_AUTOUSE - CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); - bool bThinkFast = false; - - if( pPlayer ) - { - if ( !m_hControlVolume ) - { - // Find our control volume - if ( m_iszControlVolume != NULL_STRING ) - { - m_hControlVolume = dynamic_cast( gEntList.FindEntityByName( NULL, m_iszControlVolume ) ); - } - - if (( !m_hControlVolume ) && IsControllable() ) - { - Msg( "ERROR: Couldn't find control volume for player-controllable func_tank %s.\n", STRING(GetEntityName()) ); - return; - } - } - - if ( m_hControlVolume ) - { - if( m_hControlVolume->IsTouching( pPlayer ) && pPlayer->FInViewCone(WorldSpaceCenter()) ) - { - // If my control volume is touching a player that's facing the mounted gun, automatically use the gun. - // !!!BUGBUG - this only works in cases where the player can see the gun whilst standing in the control - // volume. (This works just fine for all func_tanks mounted on combine walls and small barriers) - variant_t emptyVariant; - AcceptInput( "Use", pPlayer, pPlayer, emptyVariant, USE_TOGGLE ); - } - else - { - // If the player is nearby, think faster for snappier response to XBox auto mounting - float flDistSqr = GetAbsOrigin().DistToSqr( pPlayer->GetAbsOrigin() ); - - if( flDistSqr <= Square(360) ) - { - bThinkFast = true; - } - } - } - } - - // Keep thinking, in case they turn NPC finding back on - if ( !HasController() ) - { - if( bThinkFast ) - { - SetNextThink( gpGlobals->curtime + 0.1f ); - } - else - { - SetNextThink( gpGlobals->curtime + 2.0f ); - } - } - - if( bThinkFast ) - { - m_flNextControllerSearch = gpGlobals->curtime + 0.1f; - } - else - { - m_flNextControllerSearch = gpGlobals->curtime + 2.0f; - } -#else - // Keep thinking, in case they turn NPC finding back on - if ( !HasController() ) - { - SetNextThink( gpGlobals->curtime + 2.0f ); - } - - m_flNextControllerSearch = gpGlobals->curtime + 2.0f; -#endif//FUNCTANK_AUTOUSE - } - - // refresh the matrix - UpdateMatrix(); - - SetLocalAngularVelocity( vec3_angle ); - TrackTarget(); - - if ( fabs(GetLocalAngularVelocity().x) > 1 || fabs(GetLocalAngularVelocity().y) > 1 ) - { - StartRotSound(); - } - else - { - StopRotSound(); - } - - FuncTankPostThink(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Aim the offset barrel at a position in parent space -// Input : parentTarget - the position of the target in parent space -// Output : Vector - angles in local space -//----------------------------------------------------------------------------- -QAngle CFuncTank::AimBarrelAt( const Vector &parentTarget ) -{ - Vector target = parentTarget - GetLocalOrigin(); - float quadTarget = target.LengthSqr(); - float quadTargetXY = target.x*target.x + target.y*target.y; - - // Target is too close! Can't aim at it - if ( quadTarget <= m_barrelPos.LengthSqr() ) - { - return GetLocalAngles(); - } - else - { - // We're trying to aim the offset barrel at an arbitrary point. - // To calculate this, I think of the target as being on a sphere with - // it's center at the origin of the gun. - // The rotation we need is the opposite of the rotation that moves the target - // along the surface of that sphere to intersect with the gun's shooting direction - // To calculate that rotation, we simply calculate the intersection of the ray - // coming out of the barrel with the target sphere (that's the new target position) - // and use atan2() to get angles - - // angles from target pos to center - float targetToCenterYaw = atan2( target.y, target.x ); - float centerToGunYaw = atan2( m_barrelPos.y, sqrt( quadTarget - (m_barrelPos.y*m_barrelPos.y) ) ); - - float targetToCenterPitch = atan2( target.z, sqrt( quadTargetXY ) ); - float centerToGunPitch = atan2( -m_barrelPos.z, sqrt( quadTarget - (m_barrelPos.z*m_barrelPos.z) ) ); - return QAngle( -RAD2DEG(targetToCenterPitch+centerToGunPitch), RAD2DEG( targetToCenterYaw + centerToGunYaw ), 0 ); - } -} - - -//----------------------------------------------------------------------------- -// Aim the tank at the player crosshair -//----------------------------------------------------------------------------- -void CFuncTank::CalcPlayerCrosshairTarget( Vector *pVecTarget ) -{ - // Get the player. - CBasePlayer *pPlayer = static_cast( m_hController.Get() ); - - // Tank aims at player's crosshair. - Vector vecStart, vecDir; - trace_t tr; - - vecStart = pPlayer->EyePosition(); - - if ( !IsX360() ) - { - vecDir = pPlayer->EyeDirection3D(); - } - else - { - // Use autoaim as the eye dir. - vecDir = pPlayer->GetAutoaimVector( AUTOAIM_SCALE_DEFAULT ); - } - - // Make sure to start the trace outside of the player's bbox! - UTIL_TraceLine( vecStart + vecDir * 24, vecStart + vecDir * 8192, MASK_BLOCKLOS_AND_NPCS, this, COLLISION_GROUP_NONE, &tr ); - - *pVecTarget = tr.endpos; -} - -//----------------------------------------------------------------------------- -// Aim the tank at the player crosshair -//----------------------------------------------------------------------------- -void CFuncTank::AimBarrelAtPlayerCrosshair( QAngle *pAngles ) -{ - Vector vecTarget; - CalcPlayerCrosshairTarget( &vecTarget ); - *pAngles = AimBarrelAt( m_parentMatrix.WorldToLocal( vecTarget ) ); -} - - -//----------------------------------------------------------------------------- -// Aim the tank at the NPC's enemy -//----------------------------------------------------------------------------- -void CFuncTank::CalcNPCEnemyTarget( Vector *pVecTarget ) -{ - Vector vecTarget; - CAI_BaseNPC *pNPC = m_hController->MyNPCPointer(); - - // Aim the barrel at the npc's enemy, or where the npc is looking. - CBaseEntity *pEnemy = pNPC->GetEnemy(); - if ( pEnemy ) - { - // Clear the idle target - *pVecTarget = pEnemy->BodyTarget( GetAbsOrigin(), false ); - m_vecNPCIdleTarget = *pVecTarget; - } - else - { - if ( m_vecNPCIdleTarget != vec3_origin ) - { - *pVecTarget = m_vecNPCIdleTarget; - } - else - { - Vector vecForward; - QAngle angCenter( 0, m_yawCenterWorld, 0 ); - AngleVectors( angCenter, &vecForward ); - trace_t tr; - Vector vecBarrel = GetAbsOrigin() + m_barrelPos; - UTIL_TraceLine( vecBarrel, vecBarrel + vecForward * 8192, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - *pVecTarget = tr.endpos; - } - } -} - - -//----------------------------------------------------------------------------- -// Aim the tank at the NPC's enemy -//----------------------------------------------------------------------------- -void CFuncTank::AimBarrelAtNPCEnemy( QAngle *pAngles ) -{ - Vector vecTarget; - CalcNPCEnemyTarget( &vecTarget ); - *pAngles = AimBarrelAt( m_parentMatrix.WorldToLocal( vecTarget ) ); -} - -//----------------------------------------------------------------------------- -// Returns true if the desired angles are out of range -//----------------------------------------------------------------------------- -bool CFuncTank::RotateTankToAngles( const QAngle &angles, float *pDistX, float *pDistY ) -{ - bool bClamped = false; - - // Force the angles to be relative to the center position - float offsetY = UTIL_AngleDistance( angles.y, m_yawCenter ); - float offsetX = UTIL_AngleDistance( angles.x, m_pitchCenter ); - - float flActualYaw = m_yawCenter + offsetY; - float flActualPitch = m_pitchCenter + offsetX; - - if ( ( fabs( offsetY ) > m_yawRange + m_yawTolerance ) || - ( fabs( offsetX ) > m_pitchRange + m_pitchTolerance ) ) - { - // Limit against range in x - flActualYaw = clamp( flActualYaw, m_yawCenter - m_yawRange, m_yawCenter + m_yawRange ); - flActualPitch = clamp( flActualPitch, m_pitchCenter - m_pitchRange, m_pitchCenter + m_pitchRange ); - - bClamped = true; - } - - // Get at the angular vel - QAngle vecAngVel = GetLocalAngularVelocity(); - - // Move toward target at rate or less - float distY = UTIL_AngleDistance( flActualYaw, GetLocalAngles().y ); - vecAngVel.y = distY * 10; - vecAngVel.y = clamp( vecAngVel.y, -m_yawRate, m_yawRate ); - - // Move toward target at rate or less - float distX = UTIL_AngleDistance( flActualPitch, GetLocalAngles().x ); - vecAngVel.x = distX * 10; - vecAngVel.x = clamp( vecAngVel.x, -m_pitchRate, m_pitchRate ); - - // How exciting! We're done - SetLocalAngularVelocity( vecAngVel ); - - if ( pDistX && pDistY ) - { - *pDistX = distX; - *pDistY = distY; - } - - return bClamped; -} - - -//----------------------------------------------------------------------------- -// We lost our target! -//----------------------------------------------------------------------------- -void CFuncTank::LostTarget( void ) -{ - if (m_fireLast != 0) - { - m_OnLoseTarget.FireOutput(this, this); - m_fireLast = 0; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncTank::ComputeLeadingPosition( const Vector &vecShootPosition, CBaseEntity *pTarget, Vector *pLeadPosition ) -{ - Vector vecTarget = pTarget->BodyTarget( vecShootPosition, false ); - float flShotSpeed = GetShotSpeed(); - if ( flShotSpeed == 0 ) - { - *pLeadPosition = vecTarget; - return; - } - - Vector vecVelocity = pTarget->GetSmoothedVelocity(); - vecVelocity.z = 0.0f; - float flTargetSpeed = VectorNormalize( vecVelocity ); - - // Guesstimate... - if ( m_flNextLeadFactorTime < gpGlobals->curtime ) - { - m_flStartLeadFactor = m_flNextLeadFactor; - m_flStartLeadFactorTime = gpGlobals->curtime; - m_flNextLeadFactor = random->RandomFloat( 0.8f, 1.3f ); - m_flNextLeadFactorTime = gpGlobals->curtime + random->RandomFloat( 2.0f, 4.0f ); - } - - float flFactor = (gpGlobals->curtime - m_flStartLeadFactorTime) / (m_flNextLeadFactorTime - m_flStartLeadFactorTime); - float flLeadFactor = SimpleSplineRemapVal( flFactor, 0.0f, 1.0f, m_flStartLeadFactor, m_flNextLeadFactor ); - flTargetSpeed *= flLeadFactor; - - Vector vecDelta; - VectorSubtract( vecShootPosition, vecTarget, vecDelta ); - float flTargetToShooter = VectorNormalize( vecDelta ); - float flCosTheta = DotProduct( vecDelta, vecVelocity ); - - // Law of cosines... z^2 = x^2 + y^2 - 2xy cos Theta - // where z = flShooterToPredictedTargetPosition = flShotSpeed * predicted time - // x = flTargetSpeed * predicted time - // y = flTargetToShooter - // solve for predicted time using at^2 + bt + c = 0, t = (-b +/- sqrt( b^2 - 4ac )) / 2a - float a = flTargetSpeed * flTargetSpeed - flShotSpeed * flShotSpeed; - float b = -2.0f * flTargetToShooter * flCosTheta * flTargetSpeed; - float c = flTargetToShooter * flTargetToShooter; - - float flDiscrim = b*b - 4*a*c; - if (flDiscrim < 0) - { - *pLeadPosition = vecTarget; - return; - } - - flDiscrim = sqrt(flDiscrim); - float t = (-b + flDiscrim) / (2.0f * a); - float t2 = (-b - flDiscrim) / (2.0f * a); - if ( t < t2 ) - { - t = t2; - } - - if ( t <= 0.0f ) - { - *pLeadPosition = vecTarget; - return; - } - - VectorMA( vecTarget, flTargetSpeed * t, vecVelocity, *pLeadPosition ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncTank::AimFuncTankAtTarget( void ) -{ - // Get world target position - CBaseEntity *pTarget = NULL; - trace_t tr; - QAngle angles; - bool bUpdateTime = false; - - CBaseEntity *pTargetVehicle = NULL; - Vector barrelEnd = WorldBarrelPosition(); - Vector worldTargetPosition; - if (m_spawnflags & SF_TANK_AIM_AT_POS) - { - worldTargetPosition = m_vTargetPosition; - } - else - { - CBaseEntity *pEntity = (CBaseEntity *)m_hTarget; - if ( !pEntity || ( pEntity->GetFlags() & FL_NOTARGET ) ) - { - if( m_targetEntityName != NULL_STRING ) - { - m_hTarget = FindTarget( m_targetEntityName, NULL ); - } - - LostTarget(); - return; - } - - pTarget = pEntity; - - // Calculate angle needed to aim at target - worldTargetPosition = pEntity->EyePosition(); - if ( pEntity->IsPlayer() ) - { - CBasePlayer *pPlayer = assert_cast(pEntity); - pTargetVehicle = pPlayer->GetVehicleEntity(); - if ( pTargetVehicle ) - { - worldTargetPosition = pTargetVehicle->BodyTarget( GetAbsOrigin(), false ); - } - } - } - - float range2 = worldTargetPosition.DistToSqr( barrelEnd ); - if ( !InRange2( range2 ) ) - { - if ( m_hTarget ) - { - m_hTarget = NULL; - LostTarget(); - } - return; - } - - Vector vecAimOrigin = m_sightOrigin; - if (m_spawnflags & SF_TANK_AIM_AT_POS) - { - bUpdateTime = true; - m_sightOrigin = m_vTargetPosition; - vecAimOrigin = m_sightOrigin; - } - else - { - if ( m_spawnflags & SF_TANK_LINEOFSIGHT ) - { - AI_TraceLOS( barrelEnd, worldTargetPosition, this, &tr ); - } - else - { - tr.fraction = 1.0f; - tr.m_pEnt = pTarget; - } - - // No line of sight, don't track - if ( tr.fraction == 1.0 || tr.m_pEnt == pTarget || (pTargetVehicle && (tr.m_pEnt == pTargetVehicle)) ) - { - if ( InRange2( range2 ) && pTarget && pTarget->IsAlive() ) - { - bUpdateTime = true; - - // Sight position is BodyTarget with no noise (so gun doesn't bob up and down) - CBaseEntity *pInstance = pTargetVehicle ? pTargetVehicle : pTarget; - m_hFuncTankTarget = pInstance; - - m_sightOrigin = pInstance->BodyTarget( GetAbsOrigin(), false ); - if ( m_bPerformLeading ) - { - ComputeLeadingPosition( barrelEnd, pInstance, &vecAimOrigin ); - } - else - { - vecAimOrigin = m_sightOrigin; - } - } - } - } - - // Convert targetPosition to parent - Vector vecLocalOrigin = m_parentMatrix.WorldToLocal( vecAimOrigin ); - angles = AimBarrelAt( vecLocalOrigin ); - - // FIXME: These need to be the clamped angles - float distX, distY; - bool bClamped = RotateTankToAngles( angles, &distX, &distY ); - if ( bClamped ) - { - bUpdateTime = false; - } - - if ( bUpdateTime ) - { - if( (gpGlobals->curtime - m_lastSightTime >= 1.0) && (gpGlobals->curtime > m_flNextAttack) ) - { - // Enemy was hidden for a while, and I COULD fire right now. Instead, tack a delay on. - m_flNextAttack = gpGlobals->curtime + 0.5; - } - - m_lastSightTime = gpGlobals->curtime; - m_persist2burst = 0; - } - - SetMoveDoneTime( 0.1 ); - - if ( CanFire() && ( (fabs(distX) <= m_pitchTolerance) && (fabs(distY) <= m_yawTolerance) || (m_spawnflags & SF_TANK_LINEOFSIGHT) ) ) - { - bool fire = false; - Vector forward; - AngleVectors( GetLocalAngles(), &forward ); - forward = m_parentMatrix.ApplyRotation( forward ); - - if ( m_spawnflags & SF_TANK_LINEOFSIGHT ) - { - AI_TraceLine( barrelEnd, pTarget->WorldSpaceCenter(), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction == 1.0f || (tr.m_pEnt && tr.m_pEnt == pTarget) ) - { - fire = true; - } - } - else - { - fire = true; - } - - if ( fire ) - { - if (m_fireLast == 0) - { - m_OnAquireTarget.FireOutput(this, this); - } - FiringSequence( barrelEnd, forward, this ); - } - else - { - LostTarget(); - } - } - else - { - LostTarget(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncTank::TrackTarget( void ) -{ - QAngle angles; - - if( !m_bReadyToFire && m_flNextAttack <= gpGlobals->curtime ) - { - m_OnReadyToFire.FireOutput( this, this ); - m_bReadyToFire = true; - } - - if ( IsPlayerManned() ) - { - AimBarrelAtPlayerCrosshair( &angles ); - RotateTankToAngles( angles ); - SetNextThink( gpGlobals->curtime + 0.05f ); - SetMoveDoneTime( 0.1 ); - return; - } - - if ( IsNPCManned() ) - { - AimBarrelAtNPCEnemy( &angles ); - RotateTankToAngles( angles ); - SetNextThink( gpGlobals->curtime + 0.05f ); - SetMoveDoneTime( 0.1 ); - return; - } - - if ( !IsActive() ) - { - // If we're not active, but we're controllable, we need to keep thinking - if ( IsControllable() && !HasController() ) - { - // Think to find controllers. - SetNextThink( m_flNextControllerSearch ); - } - return; - } - - // Clean room for unnecessarily complicated old code - SetNextThink( gpGlobals->curtime + 0.1f ); - AimFuncTankAtTarget(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Start of firing sequence. By default, just fire now. -// Input : &barrelEnd - -// &forward - -// *pAttacker - -//----------------------------------------------------------------------------- -void CFuncTank::FiringSequence( const Vector &barrelEnd, const Vector &forward, CBaseEntity *pAttacker ) -{ - if ( m_fireLast != 0 ) - { - int bulletCount = (int)((gpGlobals->curtime - m_fireLast) * m_fireRate); - - if ( bulletCount > 0 ) - { - // NOTE: Set m_fireLast first so that Fire can adjust it - m_fireLast = gpGlobals->curtime; - Fire( bulletCount, barrelEnd, forward, pAttacker, false ); - } - } - else - { - m_fireLast = gpGlobals->curtime; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncTank::DoMuzzleFlash( void ) -{ - // If we're parented to something, make it play the muzzleflash - if ( m_bUsePoseParameters && GetParent() ) - { - CBaseAnimating *pAnim = GetParent()->GetBaseAnimating(); - pAnim->DoMuzzleFlash(); - - // Do the AR2 muzzle flash - if ( m_iEffectHandling == EH_COMBINE_CANNON ) - { - CEffectData data; - data.m_nAttachmentIndex = m_nBarrelAttachment; - data.m_nEntIndex = pAnim->entindex(); - - // FIXME: Create a custom entry here! - DispatchEffect( "ChopperMuzzleFlash", data ); - } - else - { - CEffectData data; - data.m_nEntIndex = pAnim->entindex(); - data.m_nAttachmentIndex = m_nBarrelAttachment; - data.m_flScale = 1.0f; - data.m_fFlags = MUZZLEFLASH_COMBINE; - - DispatchEffect( "MuzzleFlash", data ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CFuncTank::GetTracerType( void ) -{ - switch( m_iEffectHandling ) - { - case EH_AR2: - return "AR2Tracer"; - - case EH_COMBINE_CANNON: - return "HelicopterTracer"; - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Fire targets and spawn sprites. -// Input : bulletCount - -// barrelEnd - -// forward - -// pAttacker - -//----------------------------------------------------------------------------- -void CFuncTank::Fire( int bulletCount, const Vector &barrelEnd, const Vector &forward, CBaseEntity *pAttacker, bool bIgnoreSpread ) -{ - // If we have a specific effect handler, apply it's effects - if ( m_iEffectHandling == EH_AR2 ) - { - DoMuzzleFlash(); - - // Play the AR2 sound - EmitSound( "Weapon_functank.Single" ); - } - else if ( m_iEffectHandling == EH_COMBINE_CANNON ) - { - DoMuzzleFlash(); - - // Play the cannon sound - EmitSound( "NPC_Combine_Cannon.FireBullet" ); - } - else - { - if ( m_iszSpriteSmoke != NULL_STRING ) - { - CSprite *pSprite = CSprite::SpriteCreate( STRING(m_iszSpriteSmoke), barrelEnd, TRUE ); - pSprite->AnimateAndDie( random->RandomFloat( 15.0, 20.0 ) ); - pSprite->SetTransparency( kRenderTransAlpha, m_clrRender->r, m_clrRender->g, m_clrRender->b, 255, kRenderFxNone ); - - Vector vecVelocity( 0, 0, random->RandomFloat(40, 80) ); - pSprite->SetAbsVelocity( vecVelocity ); - pSprite->SetScale( m_spriteScale ); - } - if ( m_iszSpriteFlash != NULL_STRING ) - { - CSprite *pSprite = CSprite::SpriteCreate( STRING(m_iszSpriteFlash), barrelEnd, TRUE ); - pSprite->AnimateAndDie( 5 ); - pSprite->SetTransparency( kRenderTransAdd, 255, 255, 255, 255, kRenderFxNoDissipation ); - pSprite->SetScale( m_spriteScale ); - } - } - - if( pAttacker && pAttacker->IsPlayer() ) - { - if ( IsX360() ) - { - UTIL_PlayerByIndex(1)->RumbleEffect( RUMBLE_AR2, 0, RUMBLE_FLAG_RESTART | RUMBLE_FLAG_RANDOM_AMPLITUDE ); - } - else - { - CSoundEnt::InsertSound( SOUND_MOVE_AWAY, barrelEnd + forward * 32.0f, 32, 0.2f, pAttacker, SOUNDENT_CHANNEL_WEAPON ); - } - } - - - m_OnFire.FireOutput(this, this); - m_bReadyToFire = false; -} - - -void CFuncTank::TankTrace( const Vector &vecStart, const Vector &vecForward, const Vector &vecSpread, trace_t &tr ) -{ - Vector forward, right, up; - - AngleVectors( GetAbsAngles(), &forward, &right, &up ); - // get circular gaussian spread - float x, y, z; - do { - x = random->RandomFloat(-0.5,0.5) + random->RandomFloat(-0.5,0.5); - y = random->RandomFloat(-0.5,0.5) + random->RandomFloat(-0.5,0.5); - z = x*x+y*y; - } while (z > 1); - Vector vecDir = vecForward + - x * vecSpread.x * right + - y * vecSpread.y * up; - Vector vecEnd; - - vecEnd = vecStart + vecDir * MAX_TRACE_LENGTH; - UTIL_TraceLine( vecStart, vecEnd, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); -} - - -void CFuncTank::StartRotSound( void ) -{ - if ( m_spawnflags & SF_TANK_SOUNDON ) - return; - m_spawnflags |= SF_TANK_SOUNDON; - - if ( m_soundLoopRotate != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - filter.MakeReliable(); - - EmitSound_t ep; - ep.m_nChannel = CHAN_STATIC; - ep.m_pSoundName = (char*)STRING(m_soundLoopRotate); - ep.m_flVolume = 0.85; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - } - - if ( m_soundStartRotate != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_BODY; - ep.m_pSoundName = (char*)STRING(m_soundStartRotate); - ep.m_flVolume = 1.0f; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - } -} - - -void CFuncTank::StopRotSound( void ) -{ - if ( m_spawnflags & SF_TANK_SOUNDON ) - { - if ( m_soundLoopRotate != NULL_STRING ) - { - StopSound( entindex(), CHAN_STATIC, (char*)STRING(m_soundLoopRotate) ); - } - if ( m_soundStopRotate != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_BODY; - ep.m_pSoundName = (char*)STRING(m_soundStopRotate); - ep.m_flVolume = 1.0f; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - } - } - m_spawnflags &= ~SF_TANK_SOUNDON; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CFuncTank::IsEntityInViewCone( CBaseEntity *pEntity ) -{ - // First check to see if the enemy is in range. - Vector vecBarrelEnd = WorldBarrelPosition(); - float flRange2 = ( pEntity->GetAbsOrigin() - vecBarrelEnd ).LengthSqr(); - - if( !(GetSpawnFlags() & SF_TANK_IGNORE_RANGE_IN_VIEWCONE) ) - { - if ( !InRange2( flRange2 ) ) - return false; - } - - // If we're trying to shoot at a player, and we've seen a non-player recently, check the grace period - if ( m_flPlayerGracePeriod && pEntity->IsPlayer() && (gpGlobals->curtime - m_flLastSawNonPlayer) < m_flPlayerGracePeriod ) - { - // Grace period is ignored under a certain distance - if ( flRange2 > m_flIgnoreGraceUpto ) - return false; - } - - // Check to see if the entity center lies within the yaw and pitch constraints. - // This isn't horribly accurate, but should do for now. - QAngle angGun; - angGun = AimBarrelAt( m_parentMatrix.WorldToLocal( pEntity->GetAbsOrigin() ) ); - - // Force the angles to be relative to the center position - float flOffsetY = UTIL_AngleDistance( angGun.y, m_yawCenter ); - float flOffsetX = UTIL_AngleDistance( angGun.x, m_pitchCenter ); - angGun.y = m_yawCenter + flOffsetY; - angGun.x = m_pitchCenter + flOffsetX; - - if ( ( fabs( flOffsetY ) > m_yawRange + m_yawTolerance ) || ( fabs( flOffsetX ) > m_pitchRange + m_pitchTolerance ) ) - return false; - - // Remember the last time we saw a non-player - if ( !pEntity->IsPlayer() ) - { - m_flLastSawNonPlayer = gpGlobals->curtime; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if this func tank can see the enemy -//----------------------------------------------------------------------------- -bool CFuncTank::HasLOSTo( CBaseEntity *pEntity ) -{ - if ( !pEntity ) - return false; - - // Get the barrel position - Vector vecBarrelEnd = WorldBarrelPosition(); - Vector vecTarget = pEntity->BodyTarget( GetAbsOrigin(), false ); - trace_t tr; - - // Ignore the func_tank and any prop it's parented to - CTraceFilterSkipTwoEntities traceFilter( this, GetParent(), COLLISION_GROUP_NONE ); - - // UNDONE: Should this hit BLOCKLOS brushes? - AI_TraceLine( vecBarrelEnd, vecTarget, MASK_BLOCKLOS_AND_NPCS, &traceFilter, &tr ); - - CBaseEntity *pHitEntity = tr.m_pEnt; - - // Is entity in a vehicle? if so, verify vehicle is target and return if so (so npc shoots at vehicle) - CBaseCombatCharacter *pCCEntity = pEntity->MyCombatCharacterPointer(); - if ( pCCEntity != NULL && pCCEntity->IsInAVehicle() ) - { - // Ok, player in vehicle, check if vehicle is target we're looking at, fire if it is - // Also, check to see if the owner of the entity is the vehicle, in which case it's valid too. - // This catches vehicles that use bone followers. - CBaseEntity *pVehicle = pCCEntity->GetVehicle()->GetVehicleEnt(); - if ( pHitEntity == pVehicle || ( pHitEntity != NULL && pHitEntity->GetOwnerEntity() == pVehicle ) ) - return true; - } - - return ( tr.fraction == 1.0 || tr.m_pEnt == pEntity ); -} - -// ############################################################################# -// CFuncTankGun -// ############################################################################# -class CFuncTankGun : public CFuncTank -{ -public: - DECLARE_CLASS( CFuncTankGun, CFuncTank ); - - void Fire( int bulletCount, const Vector &barrelEnd, const Vector &forward, CBaseEntity *pAttacker, bool bIgnoreSpread ); -}; -LINK_ENTITY_TO_CLASS( func_tank, CFuncTankGun ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncTankGun::Fire( int bulletCount, const Vector &barrelEnd, const Vector &forward, CBaseEntity *pAttacker, bool bIgnoreSpread ) -{ - int i; - - FireBulletsInfo_t info; - info.m_iShots = 1; - info.m_vecSrc = barrelEnd; - info.m_vecDirShooting = forward; - if ( bIgnoreSpread ) - { - info.m_vecSpread = gTankSpread[0]; - } - else - { - info.m_vecSpread = gTankSpread[m_spread]; - } - - info.m_flDistance = MAX_TRACE_LENGTH; - info.m_iTracerFreq = 1; - info.m_iDamage = m_iBulletDamage; - info.m_iPlayerDamage = m_iBulletDamageVsPlayer; - info.m_pAttacker = pAttacker; - info.m_pAdditionalIgnoreEnt = GetParent(); - -#ifdef HL2_EPISODIC - if ( m_iAmmoType != -1 ) - { - for ( i = 0; i < bulletCount; i++ ) - { - info.m_iAmmoType = m_iAmmoType; - FireBullets( info ); - } - } -#else - for ( i = 0; i < bulletCount; i++ ) - { - switch( m_bulletType ) - { - case TANK_BULLET_SMALL: - info.m_iAmmoType = m_iSmallAmmoType; - FireBullets( info ); - break; - - case TANK_BULLET_MEDIUM: - info.m_iAmmoType = m_iMediumAmmoType; - FireBullets( info ); - break; - - case TANK_BULLET_LARGE: - info.m_iAmmoType = m_iLargeAmmoType; - FireBullets( info ); - break; - - default: - case TANK_BULLET_NONE: - break; - } - } -#endif // HL2_EPISODIC - - CFuncTank::Fire( bulletCount, barrelEnd, forward, pAttacker, bIgnoreSpread ); -} - -// ############################################################################# -// CFuncTankPulseLaser -// ############################################################################# -class CFuncTankPulseLaser : public CFuncTankGun -{ -public: - DECLARE_CLASS( CFuncTankPulseLaser, CFuncTankGun ); - DECLARE_DATADESC(); - - void Precache(); - void Fire( int bulletCount, const Vector &barrelEnd, const Vector &forward, CBaseEntity *pAttacker, bool bIgnoreSpread ); - - float m_flPulseSpeed; - float m_flPulseWidth; - color32 m_flPulseColor; - float m_flPulseLife; - float m_flPulseLag; - string_t m_sPulseFireSound; -}; -LINK_ENTITY_TO_CLASS( func_tankpulselaser, CFuncTankPulseLaser ); - -BEGIN_DATADESC( CFuncTankPulseLaser ) - - DEFINE_KEYFIELD( m_flPulseSpeed, FIELD_FLOAT, "PulseSpeed" ), - DEFINE_KEYFIELD( m_flPulseWidth, FIELD_FLOAT, "PulseWidth" ), - DEFINE_KEYFIELD( m_flPulseColor, FIELD_COLOR32, "PulseColor" ), - DEFINE_KEYFIELD( m_flPulseLife, FIELD_FLOAT, "PulseLife" ), - DEFINE_KEYFIELD( m_flPulseLag, FIELD_FLOAT, "PulseLag" ), - DEFINE_KEYFIELD( m_sPulseFireSound, FIELD_SOUNDNAME, "PulseFireSound" ), - -END_DATADESC() - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CFuncTankPulseLaser::Precache(void) -{ - UTIL_PrecacheOther( "grenade_beam" ); - - if ( m_sPulseFireSound != NULL_STRING ) - { - PrecacheScriptSound( STRING(m_sPulseFireSound) ); - } - BaseClass::Precache(); -} -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CFuncTankPulseLaser::Fire( int bulletCount, const Vector &barrelEnd, const Vector &vecForward, CBaseEntity *pAttacker, bool bIgnoreSpread ) -{ - // -------------------------------------------------- - // Get direction vectors for spread - // -------------------------------------------------- - Vector vecUp = Vector(0,0,1); - Vector vecRight; - CrossProduct ( vecForward, vecUp, vecRight ); - CrossProduct ( vecForward, -vecRight, vecUp ); - - for ( int i = 0; i < bulletCount; i++ ) - { - // get circular gaussian spread - float x, y, z; - do { - x = random->RandomFloat(-0.5,0.5) + random->RandomFloat(-0.5,0.5); - y = random->RandomFloat(-0.5,0.5) + random->RandomFloat(-0.5,0.5); - z = x*x+y*y; - } while (z > 1); - - Vector vecDir = vecForward + x * gTankSpread[m_spread].x * vecRight + y * gTankSpread[m_spread].y * vecUp; - - CGrenadeBeam *pPulse = CGrenadeBeam::Create( pAttacker, barrelEnd); - pPulse->Format(m_flPulseColor, m_flPulseWidth); - pPulse->Shoot(vecDir,m_flPulseSpeed,m_flPulseLife,m_flPulseLag,m_iBulletDamage); - - if ( m_sPulseFireSound != NULL_STRING ) - { - CPASAttenuationFilter filter( this, 0.6f ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_WEAPON; - ep.m_pSoundName = (char*)STRING(m_sPulseFireSound); - ep.m_flVolume = 1.0f; - ep.m_SoundLevel = SNDLVL_85dB; - - EmitSound( filter, entindex(), ep ); - } - - } - CFuncTank::Fire( bulletCount, barrelEnd, vecForward, pAttacker, bIgnoreSpread ); -} - -// ############################################################################# -// CFuncTankLaser -// ############################################################################# -class CFuncTankLaser : public CFuncTank -{ - DECLARE_CLASS( CFuncTankLaser, CFuncTank ); -public: - void Activate( void ); - void Fire( int bulletCount, const Vector &barrelEnd, const Vector &forward, CBaseEntity *pAttacker, bool bIgnoreSpread ); - void Think( void ); - CEnvLaser *GetLaser( void ); - - DECLARE_DATADESC(); - -private: - CEnvLaser *m_pLaser; - float m_laserTime; - string_t m_iszLaserName; -}; -LINK_ENTITY_TO_CLASS( func_tanklaser, CFuncTankLaser ); - -BEGIN_DATADESC( CFuncTankLaser ) - - DEFINE_KEYFIELD( m_iszLaserName, FIELD_STRING, "laserentity" ), - - DEFINE_FIELD( m_pLaser, FIELD_CLASSPTR ), - DEFINE_FIELD( m_laserTime, FIELD_TIME ), - -END_DATADESC() - - -void CFuncTankLaser::Activate( void ) -{ - BaseClass::Activate(); - - if ( !GetLaser() ) - { - UTIL_Remove(this); - Warning( "Laser tank with no env_laser!\n" ); - } - else - { - m_pLaser->TurnOff(); - } -} - - -CEnvLaser *CFuncTankLaser::GetLaser( void ) -{ - if ( m_pLaser ) - return m_pLaser; - - CBaseEntity *pLaser = gEntList.FindEntityByName( NULL, m_iszLaserName ); - while ( pLaser ) - { - // Found the landmark - if ( FClassnameIs( pLaser, "env_laser" ) ) - { - m_pLaser = (CEnvLaser *)pLaser; - break; - } - else - { - pLaser = gEntList.FindEntityByName( pLaser, m_iszLaserName ); - } - } - - return m_pLaser; -} - - -void CFuncTankLaser::Think( void ) -{ - if ( m_pLaser && (gpGlobals->curtime > m_laserTime) ) - m_pLaser->TurnOff(); - - CFuncTank::Think(); -} - - -void CFuncTankLaser::Fire( int bulletCount, const Vector &barrelEnd, const Vector &forward, CBaseEntity *pAttacker, bool bIgnoreSpread ) -{ - int i; - trace_t tr; - - if ( GetLaser() ) - { - for ( i = 0; i < bulletCount; i++ ) - { - m_pLaser->SetLocalOrigin( barrelEnd ); - TankTrace( barrelEnd, forward, gTankSpread[m_spread], tr ); - - m_laserTime = gpGlobals->curtime; - m_pLaser->TurnOn(); - m_pLaser->SetFireTime( gpGlobals->curtime - 1.0 ); - m_pLaser->FireAtPoint( tr ); - m_pLaser->SetNextThink( TICK_NEVER_THINK ); - } - CFuncTank::Fire( bulletCount, barrelEnd, forward, this, bIgnoreSpread ); - } -} - -class CFuncTankRocket : public CFuncTank -{ -public: - DECLARE_CLASS( CFuncTankRocket, CFuncTank ); - - void Precache( void ); - void Fire( int bulletCount, const Vector &barrelEnd, const Vector &forward, CBaseEntity *pAttacker, bool bIgnoreSpread ); - virtual float GetShotSpeed() { return m_flRocketSpeed; } - -protected: - float m_flRocketSpeed; - - DECLARE_DATADESC(); -}; - -BEGIN_DATADESC( CFuncTankRocket ) - - DEFINE_KEYFIELD( m_flRocketSpeed, FIELD_FLOAT, "rocketspeed" ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( func_tankrocket, CFuncTankRocket ); - -void CFuncTankRocket::Precache( void ) -{ - UTIL_PrecacheOther( "rpg_missile" ); - CFuncTank::Precache(); -} - -void CFuncTankRocket::Fire( int bulletCount, const Vector &barrelEnd, const Vector &forward, CBaseEntity *pAttacker, bool bIgnoreSpread ) -{ - CMissile *pRocket = (CMissile *) CBaseEntity::Create( "rpg_missile", barrelEnd, GetAbsAngles(), this ); - - pRocket->DumbFire(); - pRocket->SetNextThink( gpGlobals->curtime + 0.1f ); - pRocket->SetAbsVelocity( forward * m_flRocketSpeed ); - if ( GetController() && GetController()->IsPlayer() ) - { - pRocket->SetDamage( m_iBulletDamage ); - } - else - { - pRocket->SetDamage( m_iBulletDamageVsPlayer ); - } - - CFuncTank::Fire( bulletCount, barrelEnd, forward, this, bIgnoreSpread ); -} - - -//----------------------------------------------------------------------------- -// Airboat gun -//----------------------------------------------------------------------------- -class CFuncTankAirboatGun : public CFuncTank -{ -public: - DECLARE_CLASS( CFuncTankAirboatGun, CFuncTank ); - DECLARE_DATADESC(); - - void Precache( void ); - virtual void Spawn(); - virtual void Activate(); - virtual void Fire( int bulletCount, const Vector &barrelEnd, const Vector &forward, CBaseEntity *pAttacker, bool bIgnoreSpread ); - virtual void ControllerPostFrame(); - virtual void OnStopControlled(); - virtual const char *GetTracerType( void ); - virtual Vector WorldBarrelPosition( void ); - virtual void DoImpactEffect( trace_t &tr, int nDamageType ); - -private: - void CreateSounds(); - void DestroySounds(); - void DoMuzzleFlash( ); - void StartFiring(); - void StopFiring(); - - CSoundPatch *m_pGunFiringSound; - float m_flNextHeavyShotTime; - bool m_bIsFiring; - - string_t m_iszAirboatGunModel; - CHandle m_hAirboatGunModel; - int m_nGunBarrelAttachment; - float m_flLastImpactEffectTime; -}; - - -//----------------------------------------------------------------------------- -// Save/load: -//----------------------------------------------------------------------------- -BEGIN_DATADESC( CFuncTankAirboatGun ) - - DEFINE_SOUNDPATCH( m_pGunFiringSound ), - DEFINE_FIELD( m_flNextHeavyShotTime, FIELD_TIME ), - DEFINE_FIELD( m_bIsFiring, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_iszAirboatGunModel, FIELD_STRING, "airboat_gun_model" ), -// DEFINE_FIELD( m_hAirboatGunModel, FIELD_EHANDLE ), -// DEFINE_FIELD( m_nGunBarrelAttachment, FIELD_INTEGER ), - DEFINE_FIELD( m_flLastImpactEffectTime, FIELD_TIME ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( func_tankairboatgun, CFuncTankAirboatGun ); - - -//----------------------------------------------------------------------------- -// Precache: -//----------------------------------------------------------------------------- -void CFuncTankAirboatGun::Precache( void ) -{ - BaseClass::Precache(); - PrecacheScriptSound( "Airboat.FireGunLoop" ); - PrecacheScriptSound( "Airboat.FireGunRevDown"); - CreateSounds(); -} - - -//----------------------------------------------------------------------------- -// Precache: -//----------------------------------------------------------------------------- -void CFuncTankAirboatGun::Spawn( void ) -{ - BaseClass::Spawn(); - m_flNextHeavyShotTime = 0.0f; - m_bIsFiring = false; - m_flLastImpactEffectTime = -1; -} - - -//----------------------------------------------------------------------------- -// Attachment indices -//----------------------------------------------------------------------------- -void CFuncTankAirboatGun::Activate() -{ - BaseClass::Activate(); - - if ( m_iszAirboatGunModel != NULL_STRING ) - { - m_hAirboatGunModel = dynamic_cast( gEntList.FindEntityByName( NULL, m_iszAirboatGunModel ) ); - if ( m_hAirboatGunModel ) - { - m_nGunBarrelAttachment = m_hAirboatGunModel->LookupAttachment( "muzzle" ); - } - } -} - - -//----------------------------------------------------------------------------- -// Create/destroy looping sounds -//----------------------------------------------------------------------------- -void CFuncTankAirboatGun::CreateSounds() -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - - CPASAttenuationFilter filter( this ); - if (!m_pGunFiringSound) - { - m_pGunFiringSound = controller.SoundCreate( filter, entindex(), "Airboat.FireGunLoop" ); - controller.Play( m_pGunFiringSound, 0, 100 ); - } -} - -void CFuncTankAirboatGun::DestroySounds() -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - - controller.SoundDestroy( m_pGunFiringSound ); - m_pGunFiringSound = NULL; -} - - -//----------------------------------------------------------------------------- -// Stop Firing -//----------------------------------------------------------------------------- -void CFuncTankAirboatGun::StartFiring() -{ - if ( !m_bIsFiring ) - { - CSoundEnvelopeController *pController = &CSoundEnvelopeController::GetController(); - float flVolume = pController->SoundGetVolume( m_pGunFiringSound ); - pController->SoundChangeVolume( m_pGunFiringSound, 1.0f, 0.1f * (1.0f - flVolume) ); - m_bIsFiring = true; - } -} - -void CFuncTankAirboatGun::StopFiring() -{ - if ( m_bIsFiring ) - { - CSoundEnvelopeController *pController = &CSoundEnvelopeController::GetController(); - float flVolume = pController->SoundGetVolume( m_pGunFiringSound ); - pController->SoundChangeVolume( m_pGunFiringSound, 0.0f, 0.1f * flVolume ); - EmitSound( "Airboat.FireGunRevDown" ); - m_bIsFiring = false; - } -} - - -//----------------------------------------------------------------------------- -// Maintains airboat gun sounds -//----------------------------------------------------------------------------- -void CFuncTankAirboatGun::ControllerPostFrame( void ) -{ - if ( IsPlayerManned() ) - { - CBasePlayer *pPlayer = static_cast( GetController() ); - if ( pPlayer->m_nButtons & IN_ATTACK ) - { - StartFiring(); - } - else - { - StopFiring(); - } - } - - BaseClass::ControllerPostFrame(); -} - - -//----------------------------------------------------------------------------- -// Stop controlled -//----------------------------------------------------------------------------- -void CFuncTankAirboatGun::OnStopControlled() -{ - StopFiring(); - BaseClass::OnStopControlled(); -} - - -//----------------------------------------------------------------------------- -// Barrel position -//----------------------------------------------------------------------------- -Vector CFuncTankAirboatGun::WorldBarrelPosition( void ) -{ - if ( !m_hAirboatGunModel || (m_nGunBarrelAttachment == 0) ) - { - return BaseClass::WorldBarrelPosition(); - } - - Vector vecOrigin; - m_hAirboatGunModel->GetAttachment( m_nGunBarrelAttachment, vecOrigin ); - return vecOrigin; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const char *CFuncTankAirboatGun::GetTracerType( void ) -{ - if ( gpGlobals->curtime >= m_flNextHeavyShotTime ) - return "AirboatGunHeavyTracer"; - - return "AirboatGunTracer"; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncTankAirboatGun::DoMuzzleFlash( void ) -{ - if ( m_hAirboatGunModel && (m_nGunBarrelAttachment != 0) ) - { - CEffectData data; - data.m_nEntIndex = m_hAirboatGunModel->entindex(); - data.m_nAttachmentIndex = m_nGunBarrelAttachment; - data.m_flScale = 1.0f; - DispatchEffect( "AirboatMuzzleFlash", data ); - } -} - - -//----------------------------------------------------------------------------- -// Allows the shooter to change the impact effect of his bullets -//----------------------------------------------------------------------------- -void CFuncTankAirboatGun::DoImpactEffect( trace_t &tr, int nDamageType ) -{ - // The airboat spits out so much crap that we need to do cheaper versions - // of the impact effects. Also, we need to do less of them. - if ( m_flLastImpactEffectTime == gpGlobals->curtime ) - return; - - m_flLastImpactEffectTime = gpGlobals->curtime; - UTIL_ImpactTrace( &tr, nDamageType, "AirboatGunImpact" ); -} - - -//----------------------------------------------------------------------------- -// Fires bullets -//----------------------------------------------------------------------------- -#define AIRBOAT_GUN_HEAVY_SHOT_INTERVAL 0.2f - -void CFuncTankAirboatGun::Fire( int bulletCount, const Vector &barrelEnd, const Vector &forward, CBaseEntity *pAttacker, bool bIgnoreSpread ) -{ - CAmmoDef *pAmmoDef = GetAmmoDef(); - int ammoType = pAmmoDef->Index( "AirboatGun" ); - - FireBulletsInfo_t info; - info.m_vecSrc = barrelEnd; - info.m_vecDirShooting = forward; - info.m_flDistance = 4096; - info.m_iAmmoType = ammoType; - - if ( gpGlobals->curtime >= m_flNextHeavyShotTime ) - { - info.m_iShots = 1; - info.m_vecSpread = VECTOR_CONE_PRECALCULATED; - info.m_flDamageForceScale = 1000.0f; - } - else - { - info.m_iShots = 2; - info.m_vecSpread = VECTOR_CONE_5DEGREES; - } - - FireBullets( info ); - - DoMuzzleFlash(); - - // NOTE: This must occur after FireBullets - if ( gpGlobals->curtime >= m_flNextHeavyShotTime ) - { - m_flNextHeavyShotTime = gpGlobals->curtime + AIRBOAT_GUN_HEAVY_SHOT_INTERVAL; - } -} - - -//----------------------------------------------------------------------------- -// APC Rocket -//----------------------------------------------------------------------------- -#define DEATH_VOLLEY_MISSILE_COUNT 10 -#define DEATH_VOLLEY_MIN_FIRE_RATE 3 -#define DEATH_VOLLEY_MAX_FIRE_RATE 6 - -class CFuncTankAPCRocket : public CFuncTank -{ -public: - DECLARE_CLASS( CFuncTankAPCRocket, CFuncTank ); - - void Precache( void ); - virtual void Spawn(); - virtual void UpdateOnRemove(); - void Fire( int bulletCount, const Vector &barrelEnd, const Vector &forward, CBaseEntity *pAttacker, bool bIgnoreSpread ); - virtual void Think(); - virtual float GetShotSpeed() { return m_flRocketSpeed; } - -protected: - void InputDeathVolley( inputdata_t &inputdata ); - void FireDying( const Vector &barrelEnd ); - - EHANDLE m_hLaserDot; - float m_flRocketSpeed; - int m_nSide; - int m_nBurstCount; - bool m_bDying; - - DECLARE_DATADESC(); -}; - - -BEGIN_DATADESC( CFuncTankAPCRocket ) - - DEFINE_KEYFIELD( m_flRocketSpeed, FIELD_FLOAT, "rocketspeed" ), - DEFINE_FIELD( m_hLaserDot, FIELD_EHANDLE ), - DEFINE_FIELD( m_nSide, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_nBurstCount, FIELD_INTEGER, "burstcount" ), - DEFINE_FIELD( m_bDying, FIELD_BOOLEAN ), - - DEFINE_INPUTFUNC( FIELD_VOID, "DeathVolley", InputDeathVolley ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( func_tankapcrocket, CFuncTankAPCRocket ); - -void CFuncTankAPCRocket::Precache( void ) -{ - UTIL_PrecacheOther( "apc_missile" ); - - PrecacheScriptSound( "PropAPC.FireCannon" ); - - CFuncTank::Precache(); -} - -void CFuncTankAPCRocket::Spawn( void ) -{ - BaseClass::Spawn(); - AddEffects( EF_NODRAW ); - m_nSide = 0; - m_bDying = false; - m_hLaserDot = CreateLaserDot( GetAbsOrigin(), this, false ); - m_nBulletCount = m_nBurstCount; - SetSolid( SOLID_NONE ); - SetLocalVelocity( vec3_origin ); -} - -void CFuncTankAPCRocket::UpdateOnRemove( void ) -{ - if ( m_hLaserDot ) - { - UTIL_Remove( m_hLaserDot ); - m_hLaserDot = NULL; - } - BaseClass::UpdateOnRemove(); -} - -void CFuncTankAPCRocket::FireDying( const Vector &barrelEnd ) -{ - Vector vecDir; - vecDir.Random( -1.0f, 1.0f ); - if ( vecDir.z < 0.0f ) - { - vecDir.z *= -1.0f; - } - - VectorNormalize( vecDir ); - - Vector vecVelocity; - VectorMultiply( vecDir, m_flRocketSpeed * random->RandomFloat( 0.75f, 1.25f ), vecVelocity ); - - QAngle angles; - VectorAngles( vecDir, angles ); - - CAPCMissile *pRocket = (CAPCMissile *) CAPCMissile::Create( barrelEnd, angles, vecVelocity, this ); - float flDeathTime = random->RandomFloat( 0.3f, 0.5f ); - if ( random->RandomFloat( 0.0f, 1.0f ) < 0.3f ) - { - pRocket->ExplodeDelay( flDeathTime ); - } - else - { - pRocket->AugerDelay( flDeathTime ); - } - - // Make erratic firing - m_fireRate = random->RandomFloat( DEATH_VOLLEY_MIN_FIRE_RATE, DEATH_VOLLEY_MAX_FIRE_RATE ); - if ( --m_nBulletCount <= 0 ) - { - UTIL_Remove( this ); - } -} - -void CFuncTankAPCRocket::Fire( int bulletCount, const Vector &barrelEnd, const Vector &forward, CBaseEntity *pAttacker, bool bIgnoreSpread ) -{ - static float s_pSide[] = { 0.966, 0.866, 0.5, -0.5, -0.866, -0.966 }; - - Vector vecDir; - CrossProduct( Vector( 0, 0, 1 ), forward, vecDir ); - vecDir.z = 1.0f; - vecDir.x *= s_pSide[m_nSide]; - vecDir.y *= s_pSide[m_nSide]; - if ( ++m_nSide >= 6 ) - { - m_nSide = 0; - } - - VectorNormalize( vecDir ); - - Vector vecVelocity; - VectorMultiply( vecDir, m_flRocketSpeed, vecVelocity ); - - QAngle angles; - VectorAngles( vecDir, angles ); - - CAPCMissile *pRocket = (CAPCMissile *) CAPCMissile::Create( barrelEnd, angles, vecVelocity, this ); - pRocket->IgniteDelay(); - - CFuncTank::Fire( bulletCount, barrelEnd, forward, this, bIgnoreSpread ); - - if ( --m_nBulletCount <= 0 ) - { - m_nBulletCount = m_nBurstCount; - - // This will cause it to wait for a little while before shooting - m_fireLast += random->RandomFloat( 2.0f, 3.0f ); - } - EmitSound( "PropAPC.FireCannon" ); -} - -void CFuncTankAPCRocket::Think() -{ - // Inert if we're carried... - if ( GetMoveParent() && GetMoveParent()->GetMoveParent() ) - { - SetNextThink( gpGlobals->curtime + 0.5f ); - return; - } - - BaseClass::Think(); - m_hLaserDot->SetAbsOrigin( m_sightOrigin ); - SetLaserDotTarget( m_hLaserDot, m_hFuncTankTarget ); - EnableLaserDot( m_hLaserDot, m_hFuncTankTarget != NULL ); - - if ( m_bDying ) - { - FireDying( WorldBarrelPosition() ); - return; - } -} - - -void CFuncTankAPCRocket::InputDeathVolley( inputdata_t &inputdata ) -{ - if ( !m_bDying ) - { - m_fireRate = random->RandomFloat( DEATH_VOLLEY_MIN_FIRE_RATE, DEATH_VOLLEY_MAX_FIRE_RATE ); - SetNextAttack( gpGlobals->curtime + (1.0f / m_fireRate ) ); - m_nBulletCount = DEATH_VOLLEY_MISSILE_COUNT; - m_bDying = true; - } -} - - -//----------------------------------------------------------------------------- -// Mortar shell -//----------------------------------------------------------------------------- -class CMortarShell : public CBaseEntity -{ -public: - DECLARE_CLASS( CMortarShell, CBaseEntity ); - - static CMortarShell *Create( const Vector &vecStart, const Vector &vecTarget, const Vector &vecShotDir, float flImpactDelay, float flWarnDelay, string_t warnSound ); - - void Spawn( void ); - void Precache( void ); - void Impact( void ); - void Warn( void ); - void FlyThink( void ); - void FadeThink( void ); - int UpdateTransmitState( void ); - -private: - - void FixUpImpactPoint( const Vector &initialPos, const Vector &initialNormal, Vector *endPos, Vector *endNormal ); - - float m_flFadeTime; - float m_flImpactTime; - float m_flWarnTime; - float m_flNPCWarnTime; - string_t m_warnSound; - int m_iSpriteTexture; - bool m_bHasWarned; - Vector m_vecFiredFrom; - Vector m_vecFlyDir; - float m_flSpawnedTime; - - CHandle m_pBeamEffect[4]; - - CNetworkVar( float, m_flLifespan ); - CNetworkVar( float, m_flRadius ); - CNetworkVar( Vector, m_vecSurfaceNormal ); - - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); -}; - -LINK_ENTITY_TO_CLASS( mortarshell, CMortarShell ); - -BEGIN_DATADESC( CMortarShell ) - DEFINE_FIELD( m_flImpactTime, FIELD_TIME ), - DEFINE_FIELD( m_flFadeTime, FIELD_TIME ), - DEFINE_FIELD( m_flWarnTime, FIELD_TIME ), - DEFINE_FIELD( m_flNPCWarnTime, FIELD_TIME ), - DEFINE_FIELD( m_warnSound, FIELD_STRING ), - DEFINE_FIELD( m_iSpriteTexture, FIELD_INTEGER ), - DEFINE_FIELD( m_bHasWarned, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flLifespan, FIELD_FLOAT ), - DEFINE_FIELD( m_vecFiredFrom, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecFlyDir, FIELD_VECTOR ), - DEFINE_FIELD( m_flSpawnedTime, FIELD_TIME ), - DEFINE_AUTO_ARRAY( m_pBeamEffect, FIELD_EHANDLE), - DEFINE_FIELD( m_flRadius, FIELD_FLOAT ), - DEFINE_FIELD( m_vecSurfaceNormal, FIELD_VECTOR ), - - DEFINE_FUNCTION( FlyThink ), - DEFINE_FUNCTION( FadeThink ), -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CMortarShell, DT_MortarShell ) - SendPropFloat( SENDINFO( m_flLifespan ), -1, SPROP_NOSCALE ), - SendPropFloat( SENDINFO( m_flRadius ), -1, SPROP_NOSCALE ), - SendPropVector( SENDINFO( m_vecSurfaceNormal ), 0, SPROP_NORMAL ), -END_SEND_TABLE() - -#define MORTAR_TEST_RADIUS 16.0f - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &initialPos - -// *endPos - -// *endNormal - -//----------------------------------------------------------------------------- -void CMortarShell::FixUpImpactPoint( const Vector &initialPos, const Vector &initialNormal, Vector *endPos, Vector *endNormal ) -{ - Vector vecStartOffset; - - vecStartOffset = initialPos + ( initialNormal * 1.0f ); - - trace_t tr; - UTIL_TraceLine( vecStartOffset, vecStartOffset - Vector( 0, 0, 256 ), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction < 1.0f ) - { - if ( endPos ) - { - *endPos = tr.endpos + ( initialNormal * 16.0f ); - } - - if ( endNormal ) - { - *endNormal = tr.plane.normal; - } - } - else - { - if ( endPos ) - { - *endPos = initialPos; - } - - if ( endNormal ) - { - *endNormal = initialNormal; - } - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -#define MORTAR_BLAST_DAMAGE 50 -#define MORTAR_BLAST_HEIGHT 7500 - -CMortarShell *CMortarShell::Create( const Vector &vecStart, const Vector &vecTarget, const Vector &vecShotDir, float flImpactDelay, float flWarnDelay, string_t warnSound ) -{ - CMortarShell *pShell = (CMortarShell *)CreateEntityByName("mortarshell" ); - - // Place the mortar shell at the target location so that it can make the sound and explode. - trace_t tr; - UTIL_TraceLine( vecTarget, vecTarget + ( vecShotDir * 128.0f ), MASK_SOLID_BRUSHONLY, pShell, COLLISION_GROUP_NONE, &tr ); - - Vector targetPos, targetNormal; - pShell->FixUpImpactPoint( tr.endpos, tr.plane.normal, &targetPos, &targetNormal ); - - UTIL_SetOrigin( pShell, targetPos ); - - Vector vecStartSkew, vecEndSkew; - - vecStartSkew = targetPos - vecStart; - vecStartSkew[2] = 0.0f; - float skewLength = VectorNormalize( vecStartSkew ); - - vecEndSkew = -vecStartSkew * ( skewLength * 0.25f ); - vecStartSkew *= skewLength * 0.1f; - - // Muzzleflash beam - pShell->m_pBeamEffect[0] = CBeam::BeamCreate( "sprites/laserbeam.vmt", 1 ); - pShell->m_pBeamEffect[0]->PointsInit( vecStart, vecStart + Vector( vecStartSkew[0], vecStartSkew[1], MORTAR_BLAST_HEIGHT ) ); - pShell->m_pBeamEffect[0]->SetColor( 16, 16, 8 ); - pShell->m_pBeamEffect[0]->SetBrightness( 0 ); - pShell->m_pBeamEffect[0]->SetNoise( 0 ); - pShell->m_pBeamEffect[0]->SetBeamFlag( FBEAM_SHADEOUT ); - pShell->m_pBeamEffect[0]->SetWidth( 64.0f ); - pShell->m_pBeamEffect[0]->SetEndWidth( 64.0f ); - - pShell->m_pBeamEffect[1] = CBeam::BeamCreate( "sprites/laserbeam.vmt", 1 ); - pShell->m_pBeamEffect[1]->PointsInit( vecStart, vecStart + Vector( vecStartSkew[0], vecStartSkew[1], MORTAR_BLAST_HEIGHT ) ); - pShell->m_pBeamEffect[1]->SetColor( 255, 255, 255 ); - pShell->m_pBeamEffect[1]->SetBrightness( 0 ); - pShell->m_pBeamEffect[1]->SetNoise( 0 ); - pShell->m_pBeamEffect[1]->SetBeamFlag( FBEAM_SHADEOUT ); - pShell->m_pBeamEffect[1]->SetWidth( 8.0f ); - pShell->m_pBeamEffect[1]->SetEndWidth( 8.0f ); - - trace_t skyTrace; - UTIL_TraceLine( targetPos, targetPos + Vector( vecEndSkew[0], vecEndSkew[1], MORTAR_BLAST_HEIGHT ), MASK_SOLID_BRUSHONLY, pShell, COLLISION_GROUP_NONE, &skyTrace ); - - // We must touch the sky to make this beam - if ( skyTrace.fraction <= 1.0f && skyTrace.surface.flags & SURF_SKY ) - { - // Impact point beam - pShell->m_pBeamEffect[2] = CBeam::BeamCreate( "sprites/laserbeam.vmt", 1 ); - pShell->m_pBeamEffect[2]->PointsInit( targetPos, targetPos + Vector( vecEndSkew[0], vecEndSkew[1], MORTAR_BLAST_HEIGHT ) ); - pShell->m_pBeamEffect[2]->SetColor( 16, 16, 8 ); - pShell->m_pBeamEffect[2]->SetBrightness( 0 ); - pShell->m_pBeamEffect[2]->SetNoise( 0 ); - pShell->m_pBeamEffect[2]->SetBeamFlag( FBEAM_SHADEOUT ); - pShell->m_pBeamEffect[2]->SetWidth( 32.0f ); - pShell->m_pBeamEffect[2]->SetEndWidth( 32.0f ); - - pShell->m_pBeamEffect[3] = CBeam::BeamCreate( "sprites/laserbeam.vmt", 1 ); - pShell->m_pBeamEffect[3]->PointsInit( targetPos, targetPos + Vector( vecEndSkew[0], vecEndSkew[1], MORTAR_BLAST_HEIGHT ) ); - pShell->m_pBeamEffect[3]->SetColor( 255, 255, 255 ); - pShell->m_pBeamEffect[3]->SetBrightness( 0 ); - pShell->m_pBeamEffect[3]->SetNoise( 0 ); - pShell->m_pBeamEffect[3]->SetBeamFlag( FBEAM_SHADEOUT ); - pShell->m_pBeamEffect[3]->SetWidth( 4.0f ); - pShell->m_pBeamEffect[3]->SetEndWidth( 4.0f ); - } - else - { - // Mark these as not being used - pShell->m_pBeamEffect[2] = NULL; - pShell->m_pBeamEffect[3] = NULL; - } - - pShell->m_vecFiredFrom = vecStart; - pShell->m_flLifespan = flImpactDelay; - pShell->m_flImpactTime = gpGlobals->curtime + flImpactDelay; - pShell->m_flWarnTime = pShell->m_flImpactTime - flWarnDelay; - pShell->m_flNPCWarnTime = pShell->m_flWarnTime - 0.5; - pShell->m_warnSound = warnSound; - pShell->Spawn(); - - // Save off the impact normal - pShell->m_vecSurfaceNormal = targetNormal; - pShell->m_flRadius = MORTAR_BLAST_RADIUS; - - return pShell; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CMortarShell::Precache() -{ - m_iSpriteTexture = PrecacheModel( "sprites/physbeam.vmt" ); - - PrecacheScriptSound( "Weapon_Mortar.Impact" ); - PrecacheMaterial( "effects/ar2ground2" ); - - if ( NULL_STRING != m_warnSound ) - { - PrecacheScriptSound( STRING( m_warnSound ) ); - } -} - -//------------------------------------------------------------------------------ -// Purpose : Send even though we don't have a model -//------------------------------------------------------------------------------ -int CMortarShell::UpdateTransmitState( void ) -{ - return SetTransmitState( FL_EDICT_PVSCHECK ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CMortarShell::Spawn() -{ - Precache(); - - AddEffects( EF_NODRAW ); - AddSolidFlags( FSOLID_NOT_SOLID ); - - Vector mins( -MORTAR_BLAST_RADIUS, -MORTAR_BLAST_RADIUS, -MORTAR_BLAST_RADIUS ); - Vector maxs( MORTAR_BLAST_RADIUS, MORTAR_BLAST_RADIUS, MORTAR_BLAST_RADIUS ); - - UTIL_SetSize( this, mins, maxs ); - - m_vecFlyDir = GetAbsOrigin() - m_vecFiredFrom; - VectorNormalize( m_vecFlyDir ); - - m_flSpawnedTime = gpGlobals->curtime; - - SetThink( &CMortarShell::FlyThink ); - SetNextThink( gpGlobals->curtime ); - - // No model but we still need to force this! - AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// steps - -// bias - -//----------------------------------------------------------------------------- -ConVar curve_bias( "curve_bias", "0.5" ); - -enum -{ - CURVE_BIAS, - CURVE_GAIN, - CURVE_SMOOTH, - CURVE_SMOOTH_TWEAK, -}; - -void UTIL_VisualizeCurve( int type, int steps, float bias ) -{ - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); - Vector vForward, vRight, vUp; - - pPlayer->EyeVectors( &vForward, &vRight, &vUp ); - - Vector renderOrigin = pPlayer->EyePosition() + ( vForward * 512.0f ); - - float renderScale = 8.0f; - float lastPerc, perc; - - Vector renderOffs, lastRenderOffs = vec3_origin; - - for ( int i = 0; i < steps; i++ ) - { - perc = RemapValClamped( i, 0, steps-1, 0.0f, 1.0f ); - - switch( type ) - { - case CURVE_BIAS: - perc = Bias( perc, bias ); - break; - - case CURVE_GAIN: - perc = Gain( perc, bias ); - break; - - case CURVE_SMOOTH: - perc = SmoothCurve( perc ); - break; - - case CURVE_SMOOTH_TWEAK: - perc = SmoothCurve_Tweak( perc, bias, 0.9f ); - break; - } - - renderOffs = ( vRight * (-steps*0.5f) * renderScale ) + ( vUp * (renderScale*-(steps*0.5f)) )+ ( vRight * i * renderScale ) + ( vUp * perc * (renderScale*steps) ); - - NDebugOverlay::Cross3D( renderOrigin + renderOffs, -Vector(2,2,2), Vector(2,2,2), 255, 0, 0, true, 0.05f ); - - if ( i > 0 ) - { - NDebugOverlay::Line( renderOrigin + renderOffs, renderOrigin + lastRenderOffs, 255, 0, 0, true, 0.05f ); - } - - lastRenderOffs = renderOffs; - lastPerc = perc; - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CMortarShell::FlyThink() -{ - SetNextThink( gpGlobals->curtime + 0.05 ); - - if ( gpGlobals->curtime > m_flNPCWarnTime ) - { - // Warn the AI. Make this radius a little larger than the explosion will be, and make the sound last a little longer. - CSoundEnt::InsertSound ( SOUND_DANGER | SOUND_CONTEXT_MORTAR, GetAbsOrigin(), (int)(MORTAR_BLAST_RADIUS * 1.25), (m_flImpactTime - m_flNPCWarnTime) + 0.15 ); - m_flNPCWarnTime = FLT_MAX; - } - - //UTIL_VisualizeCurve( CURVE_GAIN, 64, curve_bias.GetFloat() ); - - float lifePerc = 1.0f - ( ( m_flImpactTime - gpGlobals->curtime ) / ( m_flImpactTime - m_flSpawnedTime ) ); - - lifePerc = clamp( lifePerc, 0.0f, 1.0f ); - - float curve1 = Bias( lifePerc, 0.75f ); - - // Beam updates START - - m_pBeamEffect[0]->SetBrightness( (int)(255 * curve1) ); - m_pBeamEffect[0]->SetWidth( 64.0f * curve1 ); - m_pBeamEffect[0]->SetEndWidth( 64.0f * curve1 ); - - m_pBeamEffect[1]->SetBrightness( (int)(255 * curve1) ); - m_pBeamEffect[1]->SetWidth( 8.0f * curve1 ); - m_pBeamEffect[1]->SetEndWidth( 8.0f * curve1 ); - - float curve2 = Bias( lifePerc, 0.1f ); - - if ( m_pBeamEffect[2] ) - { - m_pBeamEffect[2]->SetBrightness( (int)(255 * curve2) ); - m_pBeamEffect[2]->SetWidth( 32.0f * curve2 ); - m_pBeamEffect[2]->SetEndWidth( 32.0f * curve2 ); - } - - if ( m_pBeamEffect[3] ) - { - m_pBeamEffect[3]->SetBrightness( (int)(255 * curve2) ); - m_pBeamEffect[3]->SetWidth( 8.0f * curve2 ); - m_pBeamEffect[3]->SetEndWidth( 8.0f * curve2 ); - } - - // Beam updates END - - if( !m_bHasWarned && gpGlobals->curtime > m_flWarnTime ) - { - Warn(); - } - - if( gpGlobals->curtime > m_flImpactTime ) - { - Impact(); - } - -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CMortarShell::Warn( void ) -{ - if ( m_warnSound != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_WEAPON; - ep.m_pSoundName = (char*)STRING(m_warnSound); - ep.m_flVolume = 1.0f; - ep.m_SoundLevel = SNDLVL_NONE; - - EmitSound( filter, entindex(), ep ); - } - - m_bHasWarned = true; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CMortarShell::Impact( void ) -{ - // Fire the bullets - Vector vecSrc, vecShootDir; - - float flRadius = MORTAR_BLAST_RADIUS; - - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector( 0, 0, 128 ), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - - UTIL_DecalTrace( &tr, "Scorch" ); - - // Send the effect over - CEffectData data; - - // Do an extra effect if we struck the world - if ( tr.m_pEnt && tr.m_pEnt->IsWorld() ) - { - data.m_flRadius = flRadius * 0.5f; - data.m_vNormal = tr.plane.normal; - data.m_vOrigin = tr.endpos; - - DispatchEffect( "AR2Explosion", data ); - } - - //Shockring - CBroadcastRecipientFilter filter2; - te->BeamRingPoint( filter2, 0, GetAbsOrigin(), //origin - 8.0f, //start radius - flRadius * 2, //end radius - m_iSpriteTexture, //texture - 0, //halo index - 0, //start frame - 2, //framerate - 0.2f, //life - 32, //width - 0, //spread - 0, //amplitude - 255, //r - 255, //g - 225, //b - 32, //a - 0, //speed - FBEAM_FADEOUT - ); - - //Shockring - te->BeamRingPoint( filter2, 0, GetAbsOrigin(), //origin - 8.0f, //start radius - flRadius, //end radius - m_iSpriteTexture, //texture - 0, //halo index - 0, //start frame - 2, //framerate - 0.2f, //life - 64, //width - 0, //spread - 0, //amplitude - 255, //r - 255, //g - 225, //b - 64, //a - 0, //speed - FBEAM_FADEOUT - ); - - RadiusDamage( CTakeDamageInfo( this, GetOwnerEntity(), MORTAR_BLAST_DAMAGE, (DMG_BLAST|DMG_DISSOLVE) ), GetAbsOrigin(), MORTAR_BLAST_RADIUS, CLASS_NONE, NULL ); - - EmitSound( "Weapon_Mortar.Impact" ); - - UTIL_ScreenShake( GetAbsOrigin(), 10, 60, 1.0, 550, SHAKE_START, false ); - - //Fade the beams over time! - m_flFadeTime = gpGlobals->curtime; - - SetThink( &CMortarShell::FadeThink ); - SetNextThink( gpGlobals->curtime + 0.05f ); -} - -#define MORTAR_FADE_LENGTH 1.0f - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMortarShell::FadeThink( void ) -{ - SetNextThink( gpGlobals->curtime + 0.05f ); - - float lifePerc = 1.0f - ( ( gpGlobals->curtime - m_flFadeTime ) / MORTAR_FADE_LENGTH ); - - lifePerc = clamp( lifePerc, 0.0f, 1.0f ); - - float curve1 = Bias( lifePerc, 0.1f ); - - // Beam updates START - - m_pBeamEffect[0]->SetBrightness( (int)(255 * curve1) ); - m_pBeamEffect[0]->SetWidth( 64.0f * curve1 ); - m_pBeamEffect[0]->SetEndWidth( 64.0f * curve1 ); - - m_pBeamEffect[1]->SetBrightness( (int)(255 * curve1) ); - m_pBeamEffect[1]->SetWidth( 8.0f * curve1 ); - m_pBeamEffect[1]->SetEndWidth( 8.0f * curve1 ); - - float curve2 = Bias( lifePerc, 0.25f ); - - if ( m_pBeamEffect[2] ) - { - m_pBeamEffect[2]->SetBrightness( (int)(255 * curve2) ); - m_pBeamEffect[2]->SetWidth( 32.0f * curve2 ); - m_pBeamEffect[2]->SetEndWidth( 32.0f * curve2 ); - } - - if ( m_pBeamEffect[3] ) - { - m_pBeamEffect[3]->SetBrightness( (int)(255 * curve2) ); - m_pBeamEffect[3]->SetWidth( 8.0f * curve2 ); - m_pBeamEffect[3]->SetEndWidth( 8.0f * curve2 ); - } - - // Beam updates END - - if ( gpGlobals->curtime > ( m_flFadeTime + MORTAR_FADE_LENGTH ) ) - { - UTIL_Remove( m_pBeamEffect[0] ); - UTIL_Remove( m_pBeamEffect[1] ); - UTIL_Remove( m_pBeamEffect[2] ); - UTIL_Remove( m_pBeamEffect[3] ); - - SetThink(NULL); - UTIL_Remove( this ); - } -} - -//========================================================= -//========================================================= -class CFuncTankMortar : public CFuncTank -{ -public: - DECLARE_CLASS( CFuncTankMortar, CFuncTank ); - - CFuncTankMortar() { m_fLastShotMissed = false; } - - void Precache( void ); - void FiringSequence( const Vector &barrelEnd, const Vector &forward, CBaseEntity *pAttacker ); - void Fire( int bulletCount, const Vector &barrelEnd, const Vector &vecForward, CBaseEntity *pAttacker, bool bIgnoreSpread ); - void ShootGun(void); - void Spawn(); - void SetNextAttack( float flWait ); - - // Input handlers. - void InputShootGun( inputdata_t &inputdata ); - void InputFireAtWill( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - - int m_Magnitude; - float m_fireDelay; - string_t m_fireStartSound; - //string_t m_fireEndSound; - - string_t m_incomingSound; - float m_flWarningTime; - float m_flFireVariance; - - bool m_fLastShotMissed; - - // store future firing event - CBaseEntity *m_pAttacker; -}; - -LINK_ENTITY_TO_CLASS( func_tankmortar, CFuncTankMortar ); - -BEGIN_DATADESC( CFuncTankMortar ) - - DEFINE_KEYFIELD( m_Magnitude, FIELD_INTEGER, "iMagnitude" ), - DEFINE_KEYFIELD( m_fireDelay, FIELD_FLOAT, "firedelay" ), - DEFINE_KEYFIELD( m_fireStartSound, FIELD_STRING, "firestartsound" ), - //DEFINE_KEYFIELD( m_fireEndSound, FIELD_STRING, "fireendsound" ), - DEFINE_KEYFIELD( m_incomingSound, FIELD_STRING, "incomingsound" ), - DEFINE_KEYFIELD( m_flWarningTime, FIELD_TIME, "warningtime" ), - DEFINE_KEYFIELD( m_flFireVariance, FIELD_TIME, "firevariance" ), - - DEFINE_FIELD( m_fLastShotMissed, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_pAttacker, FIELD_CLASSPTR ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "ShootGun", InputShootGun ), - DEFINE_INPUTFUNC( FIELD_VOID, "FireAtWill", InputFireAtWill ), -END_DATADESC() - - -void CFuncTankMortar::Spawn() -{ - BaseClass::Spawn(); - - m_takedamage = DAMAGE_NO; -} - -void CFuncTankMortar::Precache( void ) -{ - if ( m_fireStartSound != NULL_STRING ) - PrecacheScriptSound( STRING(m_fireStartSound) ); - //if ( m_fireEndSound != NULL_STRING ) - // PrecacheScriptSound( STRING(m_fireEndSound) ); - if ( m_incomingSound != NULL_STRING ) - PrecacheScriptSound( STRING(m_incomingSound) ); - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CFuncTankMortar::SetNextAttack( float flWait ) -{ - if ( m_flFireVariance > 0.09 ) - flWait += random->RandomFloat( -m_flFireVariance, m_flFireVariance ); - BaseClass::SetNextAttack( flWait ); -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler to make the tank shoot. -//----------------------------------------------------------------------------- -void CFuncTankMortar::InputShootGun( inputdata_t &inputdata ) -{ - ShootGun(); -} - -//----------------------------------------------------------------------------- -// This mortar can fire the next round as soon as it is ready. This is not a -// 'sticky' state, it just allows us to get the next shot off as soon as the -// tank is on target. great for scripted applications where you need a shot as -// soon as you can get it. -//----------------------------------------------------------------------------- -void CFuncTankMortar::InputFireAtWill( inputdata_t &inputdata ) -{ - SetNextAttack( gpGlobals->curtime ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncTankMortar::ShootGun( void ) -{ - Vector forward; - AngleVectors( GetLocalAngles(), &forward ); - UpdateMatrix(); - forward = m_parentMatrix.ApplyRotation( forward ); - - Fire( 1, WorldBarrelPosition(), forward, m_pAttacker, false ); -} - - -void CFuncTankMortar::FiringSequence( const Vector &barrelEnd, const Vector &forward, CBaseEntity *pAttacker ) -{ - if ( gpGlobals->curtime > GetNextAttack() ) - { - ShootGun(); - m_fireLast = gpGlobals->curtime; - SetNextAttack( gpGlobals->curtime + (1.0 / m_fireRate ) ); - } - else - { - m_fireLast = gpGlobals->curtime; - } -} - -void CFuncTankMortar::Fire( int bulletCount, const Vector &barrelEnd, const Vector &vecForward, CBaseEntity *pAttacker, bool bIgnoreSpread ) -{ - Vector vecProjectedPosition = vec3_invalid; - trace_t tr; - - if ( m_hTarget ) - { - float leadTime = (m_fireDelay * 1.1); - - if ( m_hTarget->IsNPC() ) // Give NPCs a little extra grace - leadTime = 1.25; - - Vector vLead = m_hTarget->GetSmoothedVelocity() * leadTime; - Vector vNoise; - - vecProjectedPosition = m_hTarget->WorldSpaceCenter() + vLead; - vNoise.AsVector2D().Random( -6*12, 6*12); - vNoise.z = 0; - - if( m_hTarget->Classify() != CLASS_BULLSEYE ) - { - // Don't apply noise when attacking a bullseye. - vecProjectedPosition += vNoise; - } - } - else if ( IsPlayerManned() ) - { - CalcPlayerCrosshairTarget( &vecProjectedPosition ); - } - else if ( IsNPCManned() ) - { - CalcNPCEnemyTarget( &vecProjectedPosition ); - //vecProjectedPosition += GetEnemy()->GetSmoothedVelocity() * (m_fireDelay * 1.1); - } - else - return; - - #define TARGET_SEARCH_DEPTH 100 - - // find something interesting to shoot at near the projected position. - Vector delta; - - // Make a really rough approximation of the last half of the mortar trajectory and trace it. - // Do this so that mortars fired into windows land on rooftops, and that targets projected - // inside buildings (or out of the world) clip to the world. (usually a building facade) - - // Find halfway between the mortar and the target. - Vector vecSpot = ( vecProjectedPosition + GetAbsOrigin() ) * 0.5; - vecSpot.z = GetAbsOrigin().z; - - // Trace up to find the fake 'apex' of the shell. The skybox or 1024 units, whichever comes first. - UTIL_TraceLine( vecSpot, vecSpot + Vector(0, 0, 1024), MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr ); - vecSpot = tr.endpos; - - //NDebugOverlay::Line( tr.startpos, tr.endpos, 0,255,0, false, 5 ); - - // Now trace from apex to target - UTIL_TraceLine( vecSpot, vecProjectedPosition, MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr ); - - if( mortar_visualize.GetBool() ) - { - NDebugOverlay::Line( tr.startpos, tr.endpos, 255,0,0, false, 5 ); - } - - if ( m_fireStartSound != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_WEAPON; - ep.m_pSoundName = (char*)STRING(m_fireStartSound); - ep.m_flVolume = 1.0f; - ep.m_SoundLevel = SNDLVL_NONE; - - EmitSound( filter, entindex(), ep ); - } - - Vector vecFinalDir = tr.endpos - tr.startpos; - VectorNormalize( vecFinalDir ); - - CMortarShell::Create( barrelEnd, tr.endpos, vecFinalDir, m_fireDelay, m_flWarningTime, m_incomingSound ); - BaseClass::Fire( bulletCount, barrelEnd, vecForward, this, bIgnoreSpread ); -} - -//----------------------------------------------------------------------------- -// Purpose: Func tank that fires physics cannisters placed on it -//----------------------------------------------------------------------------- -class CFuncTankPhysCannister : public CFuncTank -{ -public: - DECLARE_CLASS( CFuncTankPhysCannister, CFuncTank ); - DECLARE_DATADESC(); - - void Fire( int bulletCount, const Vector &barrelEnd, const Vector &forward, CBaseEntity *pAttacker, bool bIgnoreSpread ); - -protected: - string_t m_iszBarrelVolume; - CHandle m_hBarrelVolume; -}; - -LINK_ENTITY_TO_CLASS( func_tankphyscannister, CFuncTankPhysCannister ); - -BEGIN_DATADESC( CFuncTankPhysCannister ) - - DEFINE_KEYFIELD( m_iszBarrelVolume, FIELD_STRING, "barrel_volume" ), - DEFINE_FIELD( m_hBarrelVolume, FIELD_EHANDLE ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncTankPhysCannister::Fire( int bulletCount, const Vector &barrelEnd, const Vector &forward, CBaseEntity *pAttacker, bool bIgnoreSpread ) -{ - // Find our barrel volume - if ( !m_hBarrelVolume ) - { - if ( m_iszBarrelVolume != NULL_STRING ) - { - m_hBarrelVolume = dynamic_cast( gEntList.FindEntityByName( NULL, m_iszBarrelVolume ) ); - } - - if ( !m_hBarrelVolume ) - { - Msg("ERROR: Couldn't find barrel volume for func_tankphyscannister %s.\n", STRING(GetEntityName()) ); - return; - } - } - - // Do we have a cannister in our barrel volume? - CPhysicsCannister *pCannister = (CPhysicsCannister *)m_hBarrelVolume->GetTouchedEntityOfType( "physics_cannister" ); - if ( !pCannister ) - { - // Play a no-ammo sound - return; - } - - // Fire the cannister! - pCannister->CannisterFire( pAttacker ); -} - -//========================================================= -//========================================================= -static const char *s_pUpdateBeamThinkContext = "UpdateBeamThinkContext"; -#define COMBINE_CANNON_BEAM "effects/blueblacklargebeam.vmt" -//#define COMBINE_CANNON_BEAM "sprites/strider_bluebeam.vmt" - -class CFuncTankCombineCannon : public CFuncTankGun -{ - DECLARE_CLASS( CFuncTankCombineCannon, CFuncTankGun ); - - void Precache(); - void Spawn(); - void CreateBeam(); - void DestroyBeam(); - void FuncTankPostThink(); - void AdjustRateOfFire(); - void UpdateBeamThink( void ); - void Fire( int bulletCount, const Vector &barrelEnd, const Vector &forward, CBaseEntity *pAttacker, bool bIgnoreSpread ); - void MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ); - void TankDeactivate(); - - void InputSetTargetEntity( inputdata_t &inputdata ); - void InputClearTargetEntity( inputdata_t &inputdata ); - - void InputEnableHarrass( inputdata_t &inputdata ); - void InputDisableHarrass( inputdata_t &inputdata ); - - COutputEvent m_OnShotAtPlayer; - - CHandle m_hBeam; - - DECLARE_DATADESC(); - -private: - float m_originalFireRate; - float m_flTimeNextSweep; - float m_flTimeBeamOn; - Vector m_vecTrueForward; - bool m_bShouldHarrass; - bool m_bLastTargetWasNPC; // Tells whether the last entity we fired a shot at was an NPC (otherwise it was the player) -}; - -BEGIN_DATADESC( CFuncTankCombineCannon ) - DEFINE_FIELD( m_originalFireRate, FIELD_FLOAT ), - DEFINE_THINKFUNC( UpdateBeamThink ), - DEFINE_FIELD( m_flTimeNextSweep, FIELD_TIME ), - DEFINE_FIELD( m_flTimeBeamOn, FIELD_TIME ), - DEFINE_FIELD( m_hBeam, FIELD_EHANDLE ), - DEFINE_FIELD( m_vecTrueForward, FIELD_VECTOR ), - DEFINE_FIELD( m_bShouldHarrass, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bLastTargetWasNPC, FIELD_BOOLEAN ), - - DEFINE_INPUTFUNC( FIELD_VOID, "EnableHarrass", InputEnableHarrass ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableHarrass", InputDisableHarrass ), - - DEFINE_OUTPUT( m_OnShotAtPlayer, "OnShotAtPlayer" ), - -END_DATADESC() - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CFuncTankCombineCannon::Precache() -{ - m_originalFireRate = m_fireRate; - - PrecacheModel(COMBINE_CANNON_BEAM); - PrecacheParticleSystem( "Weapon_Combine_Ion_Cannon" ); - - BaseClass::Precache(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CFuncTankCombineCannon::Spawn() -{ - BaseClass::Spawn(); - m_flTimeBeamOn = gpGlobals->curtime; - CreateBeam(); - - m_bShouldHarrass = true; - - GetVectors( &m_vecTrueForward, NULL, NULL ); - m_bLastTargetWasNPC = false; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CFuncTankCombineCannon::CreateBeam() -{ - if (!m_hBeam && gpGlobals->curtime >= m_flTimeBeamOn ) - { - m_hBeam = CBeam::BeamCreate( COMBINE_CANNON_BEAM, 1.0f ); - m_hBeam->SetColor( 255, 255, 255 ); - SetContextThink( &CFuncTankCombineCannon::UpdateBeamThink, gpGlobals->curtime, s_pUpdateBeamThinkContext ); - } - else - { - // Beam seems to be on, or I'm not supposed to have it on at the moment. - return; - } - - Vector vecInitialAim; - - AngleVectors( GetAbsAngles(), &vecInitialAim, NULL, NULL ); - - m_hBeam->PointsInit( WorldBarrelPosition(), WorldBarrelPosition() + vecInitialAim ); - m_hBeam->SetBrightness( 255 ); - m_hBeam->SetNoise( 0 ); - m_hBeam->SetWidth( 3.0f ); - m_hBeam->SetEndWidth( 0 ); - m_hBeam->SetScrollRate( 0 ); - m_hBeam->SetFadeLength( 60 ); // five feet to fade out - //m_hBeam->SetHaloTexture( sHaloSprite ); - m_hBeam->SetHaloScale( 4.0f ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CFuncTankCombineCannon::DestroyBeam() -{ - if( m_hBeam ) - { - UTIL_Remove( m_hBeam ); - m_hBeam.Set(NULL); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CFuncTankCombineCannon::AdjustRateOfFire() -{ - // Maintain 1.5 rounds per second rate of fire. - m_fireRate = 1.5; -/* - if( m_hTarget.Get() != NULL && m_hTarget->IsPlayer() ) - { - if( m_bLastTargetWasNPC ) - { - // Cheat, and be able to fire RIGHT NOW if the target is a player and the - // last target I fired at was an NPC. This prevents the player from running - // for it while the gun is busy dealing with NPCs - SetNextAttack( gpGlobals->curtime ); - } - } -*/ -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -#define COMBINE_CANNON_BEAM_MAX_DIST 1900.0f -void CFuncTankCombineCannon::UpdateBeamThink() -{ - SetContextThink( &CFuncTankCombineCannon::UpdateBeamThink, gpGlobals->curtime + 0.025, s_pUpdateBeamThinkContext ); - - // Always try to create the beam. - CreateBeam(); - - if( !m_hBeam ) - return; - - trace_t trBeam; - trace_t trShot; - trace_t trBlockLOS; - - Vector vecBarrel = WorldBarrelPosition(); - Vector vecAim; - AngleVectors( GetAbsAngles(), &vecAim, NULL, NULL ); - - AI_TraceLine( vecBarrel, vecBarrel + vecAim * COMBINE_CANNON_BEAM_MAX_DIST, MASK_SHOT, this, COLLISION_GROUP_NONE, &trBeam ); - - m_hBeam->SetStartPos( trBeam.startpos ); - m_hBeam->SetEndPos( trBeam.endpos ); - - if( !(m_spawnflags & SF_TANK_AIM_AT_POS) ) - { - SetTargetPosition( trBeam.endpos ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CFuncTankCombineCannon::FuncTankPostThink() -{ - AdjustRateOfFire(); - - if( m_hTarget.Get() == NULL ) - { - if( gpGlobals->curtime > m_flTimeNextSweep ) - { - AddSpawnFlags( SF_TANK_AIM_AT_POS ); - - Vector vecTargetPosition = GetTargetPosition(); - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - Vector vecToPlayer = pPlayer->WorldSpaceCenter() - GetAbsOrigin(); - vecToPlayer.NormalizeInPlace(); - - bool bHarass = false; - float flDot = DotProduct( m_vecTrueForward, vecToPlayer ); - - if( flDot >= 0.9f && m_bShouldHarrass ) - { - //Msg("%s Harrassing player\n", GetDebugName() ); - vecTargetPosition = pPlayer->EyePosition(); - bHarass = true; - } - else - { - //Msg( "%s Bored\n", GetDebugName() ); - // Just point off in the distance, more or less directly ahead of me. - vecTargetPosition = GetAbsOrigin() + m_vecTrueForward * 1900.0f; - } - - int i; - Vector vecTest; - bool bFoundPoint = false; - for( i = 0 ; i < 5 ; i++ ) - { - vecTest = vecTargetPosition; - - if( bHarass ) - { - vecTest.x += random->RandomFloat( -48, 48 ); - vecTest.y += random->RandomFloat( -48, 48 ); - vecTest.z += random->RandomFloat( 16, 48 ); - } - else - { - vecTest.x += random->RandomFloat( -48, 48 ); - vecTest.y += random->RandomFloat( -48, 48 ); - vecTest.z += random->RandomFloat( -48, 48 ); - } - - // Get the barrel position - Vector vecBarrelEnd = WorldBarrelPosition(); - trace_t trLOS; - trace_t trShoot; - - // Ignore the func_tank and any prop it's parented to, and check line of sight to the point - // Trace to the point. If an opaque trace doesn't reach the point, that means the beam hit - // something closer, (including a blockLOS), so try again. - CTraceFilterSkipTwoEntities traceFilter( this, GetParent(), COLLISION_GROUP_NONE ); - AI_TraceLine( vecBarrelEnd, vecTest, MASK_BLOCKLOS_AND_NPCS, &traceFilter, &trLOS ); - AI_TraceLine( vecBarrelEnd, vecTest, MASK_SHOT, &traceFilter, &trShoot ); - - if( trLOS.fraction < trShoot.fraction ) - { - // Damn block LOS brushes. - continue; - } - - //Msg("Point is visible in %d tries\n", i); - bFoundPoint = true; - break; - } - - if( bFoundPoint ) - { - vecTargetPosition = vecTest; - SetTargetPosition( vecTargetPosition ); - //Msg("New place\n"); - } - - if( bHarass ) - { - m_flTimeNextSweep = gpGlobals->curtime + random->RandomFloat( 0.25f, 0.75f ); - } - else - { - m_flTimeNextSweep = gpGlobals->curtime + random->RandomFloat( 1, 3 ); - } - } - } - else - { - //Msg("%d engaging: %s\n", entindex(), m_hTarget->GetClassname() ); - RemoveSpawnFlags( SF_TANK_AIM_AT_POS ); - } -} - -//--------------------------------------------------------- -// A normal func_tank uses a method of aiming the gun that will -// always follow a fast-moving player. This is because the func_tank -// turns the weapon by applying angular velocities in the early -// phase of the func_tank's Think(). Because the bullet is fired -// later in the same think, it is fired before the game physics have -// updated the func_tank's angles using the newly-computed angular -// velocity, so the bullet always trails the target slightly. -// This is unacceptable for the Combine Cannon, as the cannon MUST -// strike a moving player with absolute certainty. As a quick -// remedy, this code allows the combine cannon to fire a bullet -// at a slightly different angle than the gun is aiming, to -// ensure a hit. Large discrepancies are ignored and we accept -// the miss instead of presenting a bullet fired at an obviously -// adjusted angle. -//--------------------------------------------------------- -void CFuncTankCombineCannon::Fire( int bulletCount, const Vector &barrelEnd, const Vector &forward, CBaseEntity *pAttacker, bool bIgnoreSpread ) -{ - // Specifically do NOT fire in aim at pos mode. This is just for show. - if( HasSpawnFlags(SF_TANK_AIM_AT_POS) ) - return; - - Vector vecAdjustedForward = forward; - - if( m_hTarget != NULL ) - { - Vector vecToTarget = m_hTarget->BodyTarget( barrelEnd, false ) - barrelEnd; - VectorNormalize( vecToTarget ); - - float flDot = DotProduct( vecToTarget, forward ); - - if( flDot >= 0.97 ) - { - vecAdjustedForward = vecToTarget; - } - - if( m_hTarget->IsNPC() ) - m_bLastTargetWasNPC = true; - else - m_bLastTargetWasNPC = false; - - if( m_hTarget->IsPlayer() ) - m_OnShotAtPlayer.FireOutput( this, this ); - } - - BaseClass::Fire( bulletCount, barrelEnd, vecAdjustedForward, pAttacker, bIgnoreSpread ); - - // Turn off the beam and tell it to stay off for a bit. We want it to look like the beam became the - // ion cannon 'rail gun' effect. - DestroyBeam(); - m_flTimeBeamOn = gpGlobals->curtime + 0.2f; - - m_flTimeNextSweep = gpGlobals->curtime + random->RandomInt( 1, 2 ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CFuncTankCombineCannon::MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ) -{ - // If the shot passed near the player, shake the screen. - if( AI_IsSinglePlayer() ) - { - Vector vecPlayer = AI_GetSinglePlayer()->EyePosition(); - - Vector vecNearestPoint = PointOnLineNearestPoint( vecTracerSrc, tr.endpos, vecPlayer ); - - float flDist = vecPlayer.DistTo( vecNearestPoint ); - - if( flDist >= 10.0f && flDist <= 120.0f ) - { - // Don't shake the screen if we're hit (within 10 inches), but do shake if a shot otherwise comes within 10 feet. - UTIL_ScreenShake( vecNearestPoint, 10, 60, 0.3, 120.0f, SHAKE_START, false ); - } - } - - // Send the railgun effect - DispatchParticleEffect( "Weapon_Combine_Ion_Cannon", vecTracerSrc, tr.endpos, vec3_angle, NULL ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CFuncTankCombineCannon::TankDeactivate() -{ - DestroyBeam(); - m_flTimeBeamOn = gpGlobals->curtime + 1.0f; - SetContextThink( NULL, 0, s_pUpdateBeamThinkContext ); - - BaseClass::TankDeactivate(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CFuncTankCombineCannon::InputSetTargetEntity( inputdata_t &inputdata ) -{ - BaseClass::InputSetTargetEntity( inputdata ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CFuncTankCombineCannon::InputClearTargetEntity( inputdata_t &inputdata ) -{ -/* - m_targetEntityName = NULL_STRING; - m_hTarget = NULL; - - // No longer aim at target position if have one - m_spawnflags &= ~SF_TANK_AIM_AT_POS; -*/ - BaseClass::InputClearTargetEntity( inputdata ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CFuncTankCombineCannon::InputEnableHarrass( inputdata_t &inputdata ) -{ - m_bShouldHarrass = true; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CFuncTankCombineCannon::InputDisableHarrass( inputdata_t &inputdata ) -{ - m_bShouldHarrass = false; -} - - -LINK_ENTITY_TO_CLASS( func_tank_combine_cannon, CFuncTankCombineCannon ); diff --git a/game/server/hl2/func_tank.h b/game/server/hl2/func_tank.h deleted file mode 100644 index dca73099b..000000000 --- a/game/server/hl2/func_tank.h +++ /dev/null @@ -1,353 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef FUNC_TANK_H -#define FUNC_TANK_H -#ifdef _WIN32 -#pragma once -#endif - -#include "triggers.h" - -#define SF_TANK_ACTIVE 0x0001 -#define SF_TANK_PLAYER 0x0002 -#define SF_TANK_HUMANS 0x0004 -#define SF_TANK_ALIENS 0x0008 -#define SF_TANK_LINEOFSIGHT 0x0010 -#define SF_TANK_CANCONTROL 0x0020 -#define SF_TANK_DAMAGE_KICK 0x0040 // Kick when take damage -#define SF_TANK_AIM_AT_POS 0x0080 // Aim at a particular position -#define SF_TANK_AIM_ASSISTANCE 0x0100 -#define SF_TANK_NPC 0x0200 -#define SF_TANK_NPC_CONTROLLABLE 0x0400 // 1024 -#define SF_TANK_NPC_SET_CONTROLLER 0x0800 // 2048 -#define SF_TANK_ALLOW_PLAYER_HITS 0x1000 // 4096 Allow friendly NPCs to fire upon enemies near the player -#define SF_TANK_IGNORE_RANGE_IN_VIEWCONE 0x2000 // 8192 Don't use range as a factor in determining if something is in view cone -#define SF_TANK_NOTSOLID 0x8000 // 32768 -#define SF_TANK_SOUNDON 0x10000 // FIXME: This is not really a spawnflag! It holds transient state!!! -#define SF_TANK_HACKPLAYERHIT 0x20000 // 131072 Make this func_tank cheat and hit the player regularly - -#define FUNCTANK_DISTANCE_MAX 1200 // 100 ft. -#define FUNCTANK_DISTANCE_MIN_TO_ENEMY 180 -#define FUNCTANK_FIREVOLUME 1000 -#define FUNCTANK_NPC_ROUTE_TIME 5.0f - -// Effect handling -// If the func_tank has a chosen method of handling effects, use that -// instead of the individual effect settings. (muzzleflash, sound, tracer, etc) -enum FUNCTANK_EFFECT_HANDLING -{ - EH_NONE, // Use the effect settings - EH_AR2, // Use AR2 effects - EH_COMBINE_CANNON // Large Combine cannon -}; - -enum TANKBULLET -{ - TANK_BULLET_NONE = 0, - TANK_BULLET_SMALL = 1, - TANK_BULLET_MEDIUM = 2, - TANK_BULLET_LARGE = 3, -}; - -#define MORTAR_BLAST_RADIUS 350 - - -// Custom damage -// env_laser (duration is 0.5 rate of fire) -// rockets -// explosion? - -class CFuncTank : public CBaseEntity -{ - - DECLARE_CLASS( CFuncTank, CBaseEntity ); - -public: - - CFuncTank(); - ~CFuncTank(); - void Spawn( void ); - void Activate( void ); - void Precache( void ); - bool CreateVPhysics( void ); - bool KeyValue( const char *szKeyName, const char *szValue ); - void UpdateOnRemove(); - - void SetYawRate( float flYawRate ) { m_yawRate = flYawRate; } - void SetPitchRate( float flPitchRate ) { m_pitchRate = flPitchRate; } - - int ObjectCaps( void ) - { - return ( BaseClass::ObjectCaps() | FCAP_IMPULSE_USE | FCAP_USE_IN_RADIUS ); - } - - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - virtual void FuncTankPreThink() { return; } - void Think( void ); - virtual void FuncTankPostThink() { return; } - - int GetAmmoCount( void ) { return m_iAmmoCount; } - - // NPC - bool NPC_FindManPoint( Vector &vecPos ); - bool NPC_HasEnemy( void ); - void NPC_Fire( void ); - void NPC_InterruptRoute( void ); - void NPC_JustSawPlayer( CBaseEntity *pTarget ); - void NPC_SetInRoute( bool bInRoute ) { m_bNPCInRoute = bInRoute; } - void NPC_SetIdleAngle( Vector vecIdle ) { m_vecNPCIdleTarget = vecIdle; } - - // LOS - bool IsEntityInViewCone( CBaseEntity *pEntity ); - bool HasLOSTo( CBaseEntity *pEntity ); - - // Controller - CBaseCombatCharacter *GetController( void ); - bool StartControl( CBaseCombatCharacter *pController ); - void StopControl( void ); - Vector GetTargetPosition() { return m_vTargetPosition; } - void SetTargetPosition( const Vector &vecPos ) { m_vTargetPosition = vecPos; } - - const float YawCenter() const { return m_yawCenter; } - const float YawCenterWorld() const { return m_yawCenterWorld; } - const float YawRange() const { return m_yawRange; } - const float PitchCenter() const { return m_pitchCenter; } - const float PitchCenterWorld() const { return m_pitchCenterWorld; } - const float PitchRange() const { return m_pitchRange; } - - virtual void PhysicsSimulate( void ); - - virtual void OnStartControlled() {} - virtual void OnStopControlled() {} - - // SF Tests. - inline bool IsControllable( void ) { return ( m_spawnflags & SF_TANK_CANCONTROL ) ? true : false; } - inline bool IsActive( void ) { return ( m_spawnflags & SF_TANK_ACTIVE ) ? true : false; } - inline bool IsNPCControllable( void ) { return ( m_spawnflags & SF_TANK_NPC_CONTROLLABLE ) ? true : false; } - inline bool IsNPCSetController( void ) { return ( m_spawnflags & SF_TANK_NPC_SET_CONTROLLER ) ? true : false; } - - virtual void DoMuzzleFlash( void ); - virtual const char *GetTracerType( void ); - -protected: - virtual float GetShotSpeed() { return 0; } - - virtual Vector WorldBarrelPosition( void ); - void UpdateMatrix( void ); - - float GetNextAttack() const { return m_flNextAttack; } - virtual void SetNextAttack( float flWait ) { m_flNextAttack = flWait; } - - virtual void Fire( int bulletCount, const Vector &barrelEnd, const Vector &forward, CBaseEntity *pAttacker, bool bIgnoreSpread ); - void TankTrace( const Vector &vecStart, const Vector &vecForward, const Vector &vecSpread, trace_t &tr ); - int GetRandomBurst( void ); - float GetRandomFireTime( void ); - - void CalcPlayerCrosshairTarget( Vector *pVecTarget ); - void CalcNPCEnemyTarget( Vector *pVecTarget ); - - inline bool IsPlayerManned( void ) { return m_hController && m_hController->IsPlayer() && ( m_spawnflags & SF_TANK_PLAYER ); } - inline bool IsNPCManned( void ) { return m_hController && m_hController->MyNPCPointer() && ( m_spawnflags & SF_TANK_NPC ); } - -private: - void TrackTarget( void ); - int DrawDebugTextOverlays(void); - void DrawDebugGeometryOverlays(void); - - virtual void FiringSequence( const Vector &barrelEnd, const Vector &forward, CBaseEntity *pAttacker ); - - void StartRotSound( void ); - void StopRotSound( void ); - - // Input handlers. - void InputActivate( inputdata_t &inputdata ); - void InputDeactivate( inputdata_t &inputdata ); - void InputSetFireRate( inputdata_t &inputdata ); - void InputSetDamage( inputdata_t &inputdata ); - void InputSetTargetDir( inputdata_t &inputdata ); - void InputSetTargetPosition( inputdata_t &inputdata ); - void InputSetTargetEntityName( inputdata_t &inputdata ); - -protected: - virtual void InputSetTargetEntity( inputdata_t &inputdata ); - virtual void InputClearTargetEntity( inputdata_t &inputdata ); - -private: - void InputFindNPCToManTank( inputdata_t &inputdata ); - void InputStopFindingNPCs( inputdata_t &inputdata ); - void InputStartFindingNPCs( inputdata_t &inputdata ); - void InputForceNPCOff( inputdata_t &inputdata ); - void InputSetMaxRange( inputdata_t &inputdata ); - - inline bool CanFire( void ); - bool InRange( float range ); - bool InRange2( float flRange2 ); - - void TraceAttack( CBaseEntity *pAttacker, float flDamage, const Vector &vecDir, trace_t *ptr, int bitsDamageType); - - QAngle AimBarrelAt( const Vector &parentTarget ); - - DECLARE_DATADESC(); - - bool OnControls( CBaseEntity *pTest ); - bool HasController( void ); - - CBaseEntity *FindTarget( string_t targetName, CBaseEntity *pActivator ); - - // NPC - void NPC_FindController( void ); - bool NPC_InRoute( void ) { return m_bNPCInRoute; } - bool NPC_InterruptController( void ); - - // Aim the tank at the player crosshair - void AimBarrelAtPlayerCrosshair( QAngle *pAngles ); - - // Aim the tank at the NPC's enemy - void AimBarrelAtNPCEnemy( QAngle *pAngles ); - - // Aim the tank at the func_tank's enemy - void AimFuncTankAtTarget( void ); - - // Returns true if the desired angles are out of range - bool RotateTankToAngles( const QAngle &angles, float *pDistX = NULL, float *pDistY = NULL ); - - // We lost our target! - void LostTarget( void ); - - // Purpose: - void ComputeLeadingPosition( const Vector &vecShootPosition, CBaseEntity *pTarget, Vector *pLeadPosition ); - -protected: - virtual void ControllerPostFrame( void ); - - virtual void TankActivate(void); - virtual void TankDeactivate(void); - - float m_fireLast; // Last time I fired - float m_fireRate; // How many rounds/second - - EHANDLE m_hTarget; - - TANKBULLET m_bulletType; // Bullet type - int m_iBulletDamage; // 0 means use Bullet type's default damage - int m_iBulletDamageVsPlayer; // Damage vs player. 0 means use m_iBulletDamage - -#ifdef HL2_EPISODIC - string_t m_iszAmmoType; // The name of the ammodef that we use when we fire. Bullet damage still comes from keyvalues. - int m_iAmmoType; // The cached index of the ammodef that we use when we fire. -#else - int m_iSmallAmmoType; - int m_iMediumAmmoType; - int m_iLargeAmmoType; -#endif // HL2_EPISODIC - - int m_spread; // firing spread - - EntityMatrix m_parentMatrix; - - Vector m_sightOrigin; // Last sight of target - EHANDLE m_hFuncTankTarget; - - int m_nBulletCount; - -private: - - // This is either the player manning the func_tank, or an NPC. The NPC is either manning the tank, or running - // to the man point. If he's en-route, m_bNPCInRoute will be true. - CHandle m_hController; - - float m_flNextAttack; - Vector m_vecControllerUsePos; - - float m_yawCenter; // "Center" yaw - float m_yawCenterWorld; // "Center" yaw in world space - float m_yawRate; // Max turn rate to track targets - float m_yawRange; // Range of turning motion (one-sided: 30 is +/- 30 degress from center) - // Zero is full rotation - float m_yawTolerance; // Tolerance angle - - float m_pitchCenter; // "Center" pitch - float m_pitchCenterWorld; // "Center" pitch in world space - float m_pitchRate; // Max turn rate on pitch - float m_pitchRange; // Range of pitch motion as above - float m_pitchTolerance; // Tolerance angle - - float m_fireTime; // How much time has been used to fire the weapon so far. - float m_lastSightTime;// Last time I saw target - float m_persist; // Persistence of firing (how long do I shoot when I can't see) - float m_persist2; // Secondary persistence of firing (randomly shooting when I can't see) - float m_persist2burst;// How long secondary persistence burst lasts - float m_minRange; // Minimum range to aim/track - float m_maxRange; // Max range to aim/track - float m_flMinRange2; - float m_flMaxRange2; - int m_iAmmoCount; // ammo - - Vector m_barrelPos; // Length of the freakin barrel - float m_spriteScale; // Scale of any sprites we shoot - string_t m_iszSpriteSmoke; - string_t m_iszSpriteFlash; - - string_t m_iszMaster; // Master entity (game_team_master or multisource) - - string_t m_soundStartRotate; - string_t m_soundStopRotate; - string_t m_soundLoopRotate; - - float m_flPlayerGracePeriod; - float m_flIgnoreGraceUpto; - float m_flPlayerLockTimeBeforeFire; - float m_flLastSawNonPlayer; - - string_t m_targetEntityName; - Vector m_vTargetPosition; - Vector m_vecNPCIdleTarget; - - // Used for when the gun is attached to another entity - string_t m_iszBarrelAttachment; - int m_nBarrelAttachment; - string_t m_iszBaseAttachment; - - // Used when the gun is actually a part of the parent entity, and pose params aim it - string_t m_iszYawPoseParam; - string_t m_iszPitchPoseParam; - float m_flYawPoseCenter; - float m_flPitchPoseCenter; - bool m_bUsePoseParameters; - - // Lead the target? - bool m_bPerformLeading; - float m_flStartLeadFactor; - float m_flStartLeadFactorTime; - float m_flNextLeadFactor; - float m_flNextLeadFactorTime; - - COutputEvent m_OnFire; - COutputEvent m_OnLoseTarget; - COutputEvent m_OnAquireTarget; - COutputEvent m_OnAmmoDepleted; - COutputEvent m_OnGotController; - COutputEvent m_OnLostController; - COutputEvent m_OnGotPlayerController; - COutputEvent m_OnLostPlayerController; - COutputEvent m_OnReadyToFire; - - CHandle m_hControlVolume; - string_t m_iszControlVolume; - - float m_flNextControllerSearch; - bool m_bShouldFindNPCs; - bool m_bNPCInRoute; - string_t m_iszNPCManPoint; - - bool m_bReadyToFire; - - int m_iEffectHandling; -}; - -#endif // FUNC_TANK_H diff --git a/game/server/hl2/grenade_ar2.cpp b/game/server/hl2/grenade_ar2.cpp deleted file mode 100644 index 8b0979f93..000000000 --- a/game/server/hl2/grenade_ar2.cpp +++ /dev/null @@ -1,253 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "grenade_ar2.h" -#include "weapon_ar2.h" -#include "soundent.h" -#include "decals.h" -#include "shake.h" -#include "smoke_trail.h" -#include "ar2_explosion.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "world.h" - -#ifdef PORTAL - #include "portal_util_shared.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define AR2_GRENADE_MAX_DANGER_RADIUS 300 - -extern short g_sModelIndexFireball; // (in combatweapon.cpp) holds the index for the smoke cloud - -// Moved to HL2_SharedGameRules because these are referenced by shared AmmoDef functions -extern ConVar sk_plr_dmg_smg1_grenade; -extern ConVar sk_npc_dmg_smg1_grenade; -extern ConVar sk_max_smg1_grenade; - -ConVar sk_smg1_grenade_radius ( "sk_smg1_grenade_radius","0"); - -ConVar g_CV_SmokeTrail("smoke_trail", "1", 0); // temporary dust explosion switch - -BEGIN_DATADESC( CGrenadeAR2 ) - - DEFINE_FIELD( m_hSmokeTrail, FIELD_EHANDLE ), - DEFINE_FIELD( m_fSpawnTime, FIELD_TIME ), - DEFINE_FIELD( m_fDangerRadius, FIELD_FLOAT ), - - // Function pointers - DEFINE_ENTITYFUNC( GrenadeAR2Touch ), - DEFINE_THINKFUNC( GrenadeAR2Think ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( grenade_ar2, CGrenadeAR2 ); - -void CGrenadeAR2::Spawn( void ) -{ - Precache( ); - SetSolid( SOLID_BBOX ); - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); - - // Hits everything but debris - SetCollisionGroup( COLLISION_GROUP_PROJECTILE ); - - SetModel( "models/Weapons/ar2_grenade.mdl"); - UTIL_SetSize(this, Vector(-3, -3, -3), Vector(3, 3, 3)); -// UTIL_SetSize(this, Vector(0, 0, 0), Vector(0, 0, 0)); - - SetUse( &CGrenadeAR2::DetonateUse ); - SetTouch( &CGrenadeAR2::GrenadeAR2Touch ); - SetThink( &CGrenadeAR2::GrenadeAR2Think ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - if( GetOwnerEntity() && GetOwnerEntity()->IsPlayer() ) - { - m_flDamage = sk_plr_dmg_smg1_grenade.GetFloat(); - } - else - { - m_flDamage = sk_npc_dmg_smg1_grenade.GetFloat(); - } - - m_DmgRadius = sk_smg1_grenade_radius.GetFloat(); - m_takedamage = DAMAGE_YES; - m_bIsLive = true; - m_iHealth = 1; - - SetGravity( UTIL_ScaleForGravity( 400 ) ); // use a lower gravity for grenades to make them easier to see - SetFriction( 0.8 ); - SetSequence( 0 ); - - m_fDangerRadius = 100; - - m_fSpawnTime = gpGlobals->curtime; - - // ------------- - // Smoke trail. - // ------------- - if( g_CV_SmokeTrail.GetInt() && !IsXbox() ) - { - m_hSmokeTrail = SmokeTrail::CreateSmokeTrail(); - - if( m_hSmokeTrail ) - { - m_hSmokeTrail->m_SpawnRate = 48; - m_hSmokeTrail->m_ParticleLifetime = 1; - m_hSmokeTrail->m_StartColor.Init(0.1f, 0.1f, 0.1f); - m_hSmokeTrail->m_EndColor.Init(0,0,0); - m_hSmokeTrail->m_StartSize = 12; - m_hSmokeTrail->m_EndSize = m_hSmokeTrail->m_StartSize * 4; - m_hSmokeTrail->m_SpawnRadius = 4; - m_hSmokeTrail->m_MinSpeed = 4; - m_hSmokeTrail->m_MaxSpeed = 24; - m_hSmokeTrail->m_Opacity = 0.2f; - - m_hSmokeTrail->SetLifetime(10.0f); - m_hSmokeTrail->FollowEntity(this); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: The grenade has a slight delay before it goes live. That way the -// person firing it can bounce it off a nearby wall. However if it -// hits another character it blows up immediately -// Input : -// Output : -//----------------------------------------------------------------------------- -void CGrenadeAR2::GrenadeAR2Think( void ) -{ - SetNextThink( gpGlobals->curtime + 0.05f ); - - if (!m_bIsLive) - { - // Go live after a short delay - if (m_fSpawnTime + MAX_AR2_NO_COLLIDE_TIME < gpGlobals->curtime) - { - m_bIsLive = true; - } - } - - // If I just went solid and my velocity is zero, it means I'm resting on - // the floor already when I went solid so blow up - if (m_bIsLive) - { - if (GetAbsVelocity().Length() == 0.0 || - GetGroundEntity() != NULL ) - { - Detonate(); - } - } - - // The old way of making danger sounds would scare the crap out of EVERYONE between you and where the grenade - // was going to hit. The radius of the danger sound now 'blossoms' over the grenade's lifetime, making it seem - // dangerous to a larger area downrange than it does from where it was fired. - if( m_fDangerRadius <= AR2_GRENADE_MAX_DANGER_RADIUS ) - { - m_fDangerRadius += ( AR2_GRENADE_MAX_DANGER_RADIUS * 0.05 ); - } - - CSoundEnt::InsertSound( SOUND_DANGER, GetAbsOrigin() + GetAbsVelocity() * 0.5, (int)m_fDangerRadius, 0.2, this, SOUNDENT_CHANNEL_REPEATED_DANGER ); -} - -void CGrenadeAR2::Event_Killed( const CTakeDamageInfo &info ) -{ - Detonate( ); -} - -void CGrenadeAR2::GrenadeAR2Touch( CBaseEntity *pOther ) -{ - Assert( pOther ); - if ( !pOther->IsSolid() ) - return; - - // If I'm live go ahead and blow up - if (m_bIsLive) - { - Detonate(); - } - else - { - // If I'm not live, only blow up if I'm hitting an chacter that - // is not the owner of the weapon - CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pOther ); - if (pBCC && GetThrower() != pBCC) - { - m_bIsLive = true; - Detonate(); - } - } -} - -void CGrenadeAR2::Detonate(void) -{ - if (!m_bIsLive) - { - return; - } - m_bIsLive = false; - m_takedamage = DAMAGE_NO; - - if(m_hSmokeTrail) - { - UTIL_Remove(m_hSmokeTrail); - m_hSmokeTrail = NULL; - } - - CPASFilter filter( GetAbsOrigin() ); - - te->Explosion( filter, 0.0, - &GetAbsOrigin(), - g_sModelIndexFireball, - 2.0, - 15, - TE_EXPLFLAG_NONE, - m_DmgRadius, - m_flDamage ); - - Vector vecForward = GetAbsVelocity(); - VectorNormalize(vecForward); - trace_t tr; - UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + 60*vecForward, MASK_SHOT, - this, COLLISION_GROUP_NONE, &tr); - - - if ((tr.m_pEnt != GetWorldEntity()) || (tr.hitbox != 0)) - { - // non-world needs smaller decals - if( tr.m_pEnt && !tr.m_pEnt->IsNPC() ) - { - UTIL_DecalTrace( &tr, "SmallScorch" ); - } - } - else - { - UTIL_DecalTrace( &tr, "Scorch" ); - } - - UTIL_ScreenShake( GetAbsOrigin(), 25.0, 150.0, 1.0, 750, SHAKE_START ); - - RadiusDamage ( CTakeDamageInfo( this, GetThrower(), m_flDamage, DMG_BLAST ), GetAbsOrigin(), m_DmgRadius, CLASS_NONE, NULL ); - - UTIL_Remove( this ); -} - -void CGrenadeAR2::Precache( void ) -{ - PrecacheModel("models/Weapons/ar2_grenade.mdl"); -} - - -CGrenadeAR2::CGrenadeAR2(void) -{ - m_hSmokeTrail = NULL; -} diff --git a/game/server/hl2/grenade_ar2.h b/game/server/hl2/grenade_ar2.h deleted file mode 100644 index 1560dca21..000000000 --- a/game/server/hl2/grenade_ar2.h +++ /dev/null @@ -1,47 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Projectile shot from the AR2 -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef GRENADEAR2_H -#define GRENADEAR2_H - -#include "basegrenade_shared.h" - -#define MAX_AR2_NO_COLLIDE_TIME 0.2 - -class SmokeTrail; -class CWeaponAR2; - -class CGrenadeAR2 : public CBaseGrenade -{ -public: - DECLARE_CLASS( CGrenadeAR2, CBaseGrenade ); - - CHandle< SmokeTrail > m_hSmokeTrail; - float m_fSpawnTime; - float m_fDangerRadius; - - - void Spawn( void ); - void Precache( void ); - void GrenadeAR2Touch( CBaseEntity *pOther ); - void GrenadeAR2Think( void ); - void Event_Killed( const CTakeDamageInfo &info ); - -public: - void EXPORT Detonate(void); - CGrenadeAR2(void); - - DECLARE_DATADESC(); -}; - -#endif //GRENADEAR2_H diff --git a/game/server/hl2/grenade_beam.cpp b/game/server/hl2/grenade_beam.cpp deleted file mode 100644 index 284cc77e9..000000000 --- a/game/server/hl2/grenade_beam.cpp +++ /dev/null @@ -1,443 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Projectile shot by mortar synth. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "grenade_beam.h" -#include "beam_shared.h" -#include "ndebugoverlay.h" -#include "decals.h" -#include "engine/IEngineSound.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define GRENADEBEAM_DEFAULTWIDTH 2.0 - -// ============================================================================== -// > CGrenadeBeamChaser -// ============================================================================== -BEGIN_DATADESC( CGrenadeBeamChaser ) - - DEFINE_FIELD( m_pTarget, FIELD_CLASSPTR ), - - // Function pointers - DEFINE_FUNCTION( ChaserThink ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( grenade_beam_chaser, CGrenadeBeamChaser ); - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenadeBeamChaser::Spawn( void ) -{ - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_FLY ); - SetThink(&CGrenadeBeamChaser::ChaserThink); - SetNextThink( gpGlobals->curtime ); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenadeBeamChaser::ChaserThink( void ) -{ - Vector vTargetPos; - m_pTarget->GetChaserTargetPos(&vTargetPos); - Vector vTargetDir = (vTargetPos - GetLocalOrigin()); - - // ------------------------------------------------- - // Check to see if we'll pass our target this frame - // If so get the next target - // ------------------------------------------------- - float flTargetDist = vTargetDir.Length(); - if ((gpGlobals->frametime * m_pTarget->m_flBeamSpeed) > flTargetDist) - { - m_pTarget->GetNextTargetPos(&vTargetPos); - vTargetDir = (vTargetPos - GetLocalOrigin()); - flTargetDist = vTargetDir.Length(); - } - - if (flTargetDist != 0) - { - //-------------------------------------- - // Set our velocity to chase the target - //-------------------------------------- - VectorNormalize(vTargetDir); - SetAbsVelocity( vTargetDir * m_pTarget->m_flBeamSpeed ); - } - SetNextThink( gpGlobals->curtime ); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -CGrenadeBeamChaser* CGrenadeBeamChaser::ChaserCreate( CGrenadeBeam *pTarget ) -{ - CGrenadeBeamChaser *pChaser = (CGrenadeBeamChaser *)CreateEntityByName( "grenade_beam_chaser" ); - pChaser->SetLocalOrigin( pTarget->GetLocalOrigin() ); - pChaser->m_pTarget = pTarget; - pChaser->Spawn(); - return pChaser; -} - -// ============================================================================== -// > CGrenadeBeam -// ============================================================================== -BEGIN_DATADESC( CGrenadeBeam ) - - DEFINE_FIELD( m_vLaunchPos, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_flBeamWidth, FIELD_FLOAT ), - DEFINE_FIELD( m_flBeamSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_flBeamLag, FIELD_FLOAT ), - DEFINE_FIELD( m_flLaunchTime, FIELD_TIME ), - DEFINE_FIELD( m_flLastTouchTime, FIELD_TIME ), - DEFINE_FIELD( m_hBeamChaser, FIELD_EHANDLE ), - DEFINE_FIELD( m_nNumHits, FIELD_INTEGER ), - - DEFINE_ARRAY( m_pHitLocation, FIELD_VECTOR, GRENADEBEAM_MAXHITS ), - DEFINE_ARRAY( m_pBeam, FIELD_CLASSPTR, GRENADEBEAM_MAXBEAMS ), - - // Function pointers - DEFINE_ENTITYFUNC( GrenadeBeamTouch ), - DEFINE_THINKFUNC( KillBeam ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( grenade_beam, CGrenadeBeam ); - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenadeBeam::Spawn( void ) -{ - Precache( ); - SetSolid( SOLID_BBOX ); - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); - - //UNDONE/HACK: this model is never used but one is needed - SetModel( "Models/weapons/flare.mdl" ); - AddEffects( EF_NODRAW ); - - SetTouch( &CGrenadeBeam::GrenadeBeamTouch ); - SetNextThink( gpGlobals->curtime ); - - m_takedamage = DAMAGE_NO; - m_iHealth = 1; - SetGravity( 0.0001 ); - m_nNumHits = 0; - UTIL_SetSize( this, vec3_origin, vec3_origin ); -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -CGrenadeBeam* CGrenadeBeam::Create( CBaseEntity* pOwner, const Vector &vStart) -{ - CGrenadeBeam *pEnergy = (CGrenadeBeam *)CreateEntityByName( "grenade_beam" ); - pEnergy->Spawn(); - pEnergy->SetOwnerEntity( pOwner ); - pEnergy->SetRenderColor( 255, 0, 0, 0 ); - pEnergy->m_flBeamWidth = GRENADEBEAM_DEFAULTWIDTH; - UTIL_SetOrigin( pEnergy, vStart ); - - return pEnergy; -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenadeBeam::Format(color32 clrColor, float flWidth) -{ - m_clrRender = clrColor; - m_flBeamWidth = flWidth; -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenadeBeam::Shoot(Vector vDirection, float flSpeed, float flLifetime, float flLag, float flDamage ) -{ - SetThink ( &CGrenadeBeam::KillBeam ); - SetNextThink( gpGlobals->curtime + flLifetime ); - m_hBeamChaser = CGrenadeBeamChaser::ChaserCreate(this); - m_flBeamSpeed = flSpeed; - SetAbsVelocity( vDirection * flSpeed ); - m_flBeamLag = flLag; - m_flDamage = flDamage; - m_flLaunchTime = gpGlobals->curtime; - m_vLaunchPos = GetAbsOrigin(); - m_flLastTouchTime = 0; - CreateBeams(); - UpdateBeams(); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenadeBeam::KillBeam(void) -{ - SetThink(NULL); - SetTouch(NULL); - m_hBeamChaser->SetThink(NULL); - UTIL_Remove(m_hBeamChaser); - UTIL_Remove(this); - - for (int i=0;icurtime - m_flLastTouchTime < 0.01) - { - KillBeam(); - return; - } - m_flLastTouchTime = gpGlobals->curtime; - - // --------------------------------------- - // If I have room for another hit, add it - // --------------------------------------- - if (m_nNumHits < GRENADEBEAM_MAXHITS) - { - m_pHitLocation[m_nNumHits] = GetLocalOrigin(); - m_nNumHits++; - } - // Otherwise copy over old hit, and force chaser into last hit position - else - { - m_hBeamChaser->SetLocalOrigin( m_pHitLocation[0] ); - for (int i=0;iRandomInt(5, 10), 10); - } - - // -------------------------------------------- - // Play burn sounds - // -------------------------------------------- - if (pOther->m_takedamage) - { - pOther->TakeDamage( CTakeDamageInfo( this, this, m_flDamage, DMG_BURN ) ); - KillBeam(); - return; - } - - EmitSound( "GrenadeBeam.HitSound" ); - - trace_t tr; - Vector vDirection = GetAbsVelocity(); - VectorNormalize(vDirection); - UTIL_TraceLine( GetAbsOrigin()-vDirection, GetAbsOrigin()+vDirection, MASK_SOLID, NULL, COLLISION_GROUP_NONE, &tr ); - UTIL_DecalTrace( &tr, "RedGlowFade" ); - UTIL_ImpactTrace( &tr, DMG_ENERGYBEAM ); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenadeBeam::GetNextTargetPos(Vector *vPosition) -{ - // Only advance if tail launch time has passed - if (gpGlobals->curtime - m_flLaunchTime > m_flBeamLag) - { - if (m_nNumHits > 0) - { - for (int i=0;icurtime - m_flLaunchTime < m_flBeamLag) - { - *vPosition = m_vLaunchPos; - } - else if (m_nNumHits > 0) - { - *vPosition = m_pHitLocation[0]; - } - else - { - *vPosition = GetLocalOrigin(); - } -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenadeBeam::CreateBeams(void) -{ - for ( int i=0; i < GRENADEBEAM_MAXBEAMS; ++i ) - { - m_pBeam[i] = CBeam::BeamCreate( "sprites/laser.vmt", m_flBeamWidth ); - m_pBeam[i]->SetColor( m_clrRender->r, m_clrRender->g, m_clrRender->b ); - m_pBeam[i]->EntsInit( this, m_hBeamChaser ); - m_pBeam[i]->SetBrightness( 255 ); - m_pBeam[i]->SetNoise( 1 ); - m_pBeam[i]->SetBeamFlag( FBEAM_SHADEIN ); - m_pBeam[i]->SetBeamFlag( FBEAM_SHADEOUT ); - } -} -/* -void CGrenadeBeam::DebugBeams(void) -{ - if (m_nNumHits > 0) - { - NDebugOverlay::Line(GetLocalOrigin(), m_pHitLocation[m_nNumHits-1], 255,255,25, true, 0.1); - NDebugOverlay::Line(m_hBeamChaser->GetLocalOrigin(), m_pHitLocation[0], 255,255,25, true, 0.1); - - for (int i=0;iGetLocalOrigin(), 255,255,25, true, 0.1); - } - - for (int i=0;iEntsInit( this, m_hBeamChaser ); - for (int i=1;iSetBrightness(0); - } - } - // ------------------------------------------------------------------ - // Otherwise draw beams between hits - // ------------------------------------------------------------------ - else - { - m_pBeam[0]->PointEntInit( m_pHitLocation[0], m_hBeamChaser ); - - for (int i=1;iPointsInit(m_pHitLocation[i-1],m_pHitLocation[i]); - m_pBeam[i]->SetBrightness(255); - } - else - { - m_pBeam[i]->SetBrightness(0); - } - } - - m_pBeam[GRENADEBEAM_MAXBEAMS-1]->PointEntInit( m_pHitLocation[m_nNumHits-1], this ); - m_pBeam[GRENADEBEAM_MAXBEAMS-1]->SetBrightness(255); - } -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenadeBeam::Precache( void ) -{ - PrecacheModel("sprites/laser.vmt"); - - //UNDONE/HACK: this model is never used but one is needed - PrecacheModel("Models/weapons/flare.mdl"); - - PrecacheScriptSound( "GrenadeBeam.HitSound" ); -} - -//------------------------------------------------------------------------------ -// Purpose : Send even though we don't have a model -// Input : -// Output : -//------------------------------------------------------------------------------ -int CGrenadeBeam::UpdateTransmitState(void) -{ - return SetTransmitState( FL_EDICT_PVSCHECK ); -} - diff --git a/game/server/hl2/grenade_beam.h b/game/server/hl2/grenade_beam.h deleted file mode 100644 index 430dae2fb..000000000 --- a/game/server/hl2/grenade_beam.h +++ /dev/null @@ -1,74 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Projectile shot by mortar synth -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef GRENADEBEAM_H -#define GRENADEBEAM_H - -#include "basegrenade_shared.h" - -#define GRENADEBEAM_MAXBEAMS 2 -#define GRENADEBEAM_MAXHITS GRENADEBEAM_MAXBEAMS-1 - -class CGrenadeBeam; -class CBeam; - -// End of the grenade beam -class CGrenadeBeamChaser : public CBaseAnimating -{ -public: - DECLARE_CLASS( CGrenadeBeamChaser, CBaseAnimating ); - DECLARE_DATADESC(); - - static CGrenadeBeamChaser* ChaserCreate( CGrenadeBeam *pTarget ); - - void Spawn( void ); - void ChaserThink(); - - CGrenadeBeam* m_pTarget; -}; - -class CGrenadeBeam : public CBaseGrenade -{ -public: - DECLARE_CLASS( CGrenadeBeam, CBaseGrenade ); - DECLARE_DATADESC(); - - static CGrenadeBeam* Create( CBaseEntity* pOwner, const Vector &vStart); - -public: - void Spawn( void ); - void Precache( void ); - void Format( color32 clrColor, float flWidth); - void GrenadeBeamTouch( CBaseEntity *pOther ); - void KillBeam(); - void CreateBeams(void); - void UpdateBeams(void); - //void DebugBeams(void); - void GetChaserTargetPos(Vector *vPosition); - void GetNextTargetPos(Vector *vPosition); - int UpdateTransmitState(void); - void Shoot(Vector vDirection, float flSpeed, float flLifetime, float flLag, float flDamage ); - - Vector m_vLaunchPos; - float m_flBeamWidth; - float m_flBeamSpeed; - float m_flBeamLag; - float m_flLaunchTime; - float m_flLastTouchTime; - EHANDLE m_hBeamChaser; - int m_nNumHits; - Vector m_pHitLocation[GRENADEBEAM_MAXHITS]; - CBeam* m_pBeam[GRENADEBEAM_MAXBEAMS]; -}; - -#endif //GRENADEBEAM_H diff --git a/game/server/hl2/grenade_brickbat.cpp b/game/server/hl2/grenade_brickbat.cpp deleted file mode 100644 index a42400cdb..000000000 --- a/game/server/hl2/grenade_brickbat.cpp +++ /dev/null @@ -1,274 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Things thrown from the hand -// -//=============================================================================// - -#include "cbase.h" -#include "player.h" -#include "ammodef.h" -#include "gamerules.h" -#include "grenade_brickbat.h" -#include "soundent.h" -#include "decals.h" -#include "IEffects.h" -#include "engine/IEngineSound.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// Global Savedata for changelevel trigger -BEGIN_DATADESC( CGrenade_Brickbat ) - - DEFINE_FIELD( m_nType, FIELD_INTEGER ), - DEFINE_FIELD( m_bExplodes, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bBounceToFlat, FIELD_BOOLEAN ), - - // Function Pointers - DEFINE_ENTITYFUNC( BrickbatTouch ), - DEFINE_THINKFUNC( BrickbatThink ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( brickbat, CGrenade_Brickbat ); - -void CGrenade_Brickbat::Spawn( void ) -{ - RemoveEffects( EF_NOINTERP ); - SetCollisionGroup( COLLISION_GROUP_PROJECTILE ); - SetTouch( &CGrenade_Brickbat::BrickbatTouch ); - SetThink( &CGrenade_Brickbat::BrickbatThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - m_takedamage = DAMAGE_YES; - m_iHealth = 1; - - SetGravity( 1.0 ); - SetSequence( 1 ); - - CreateVPhysics(); -} - -bool CGrenade_Brickbat::CreateVPhysics() -{ - VPhysicsInitNormal( SOLID_VPHYSICS, 0, false ); - IPhysicsObject *pPhysics = VPhysicsGetObject(); - if ( pPhysics ) - { - // we want world touches - unsigned int flags = pPhysics->GetCallbackFlags(); - pPhysics->SetCallbackFlags( flags | CALLBACK_GLOBAL_TOUCH_STATIC ); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CGrenade_Brickbat::BrickbatTouch( CBaseEntity *pOther ) -{ - // ----------------------------------------------------------- - // Might be physically simulated so get my velocity manually - // ----------------------------------------------------------- - Vector vVelocity; - GetVelocity(&vVelocity,NULL); - - // ----------------------------------- - // Do damage if we moving fairly fast - // ----------------------------------- - if (vVelocity.Length() > 100) - { - if (GetThrower()) - { - trace_t tr; - tr = CBaseEntity::GetTouchTrace( ); - ClearMultiDamage( ); - Vector forward; - AngleVectors( GetLocalAngles(), &forward ); - - CTakeDamageInfo info( this, GetThrower(), m_flDamage, DMG_CRUSH ); - CalculateMeleeDamageForce( &info, forward, tr.endpos ); - pOther->DispatchTraceAttack( info, forward, &tr ); - ApplyMultiDamage(); - } - // If this thrown item explodes, blow it up - if (m_bExplodes) - { - Detonate(); - return; - } - } - else if (pOther->GetFlags() & FL_CLIENT) - { - SpawnBrickbatWeapon(); - return; - } -} - -//------------------------------------------------------------------------------ -// Purpose : Brickbat grenade turns back into a brickbat weapon -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenade_Brickbat::SpawnBrickbatWeapon( void ) -{ - CWeaponBrickbat *pBrickbat = (CWeaponBrickbat*)CBaseEntity::CreateNoSpawn( - "weapon_brickbat", GetLocalOrigin(), GetLocalAngles(), NULL ); - // Spawn after we set the ammo type so the correct model is used - if (pBrickbat) - { - pBrickbat->m_iCurrentAmmoType = m_nType; - pBrickbat->Spawn(); - VPhysicsDestroyObject(); - SetThink(NULL); - UTIL_Remove(this); - } -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenade_Brickbat::BrickbatThink( void ) -{ - // ----------------------------------------------------------- - // Might be physically simulated so get my velocity manually - // ----------------------------------------------------------- - Vector vVelocity; - AngularImpulse vAngVel; - GetVelocity(&vVelocity,&vAngVel); - - // See if I can lose my owner (has dropper moved out of way?) - // Want do this so owner can throw the brickbat - if (GetOwnerEntity()) - { - trace_t tr; - Vector vUpABit = GetAbsOrigin(); - vUpABit.z += 5.0; - - CBaseEntity* saveOwner = GetOwnerEntity(); - SetOwnerEntity( NULL ); - UTIL_TraceEntity( this, GetAbsOrigin(), vUpABit, MASK_SOLID, &tr ); - if ( tr.startsolid || tr.fraction != 1.0 ) - { - SetOwnerEntity( saveOwner ); - } - } - - // --------------------------------------------------------------- - // Make sure we're not resting on a living thing's bounding box - // --------------------------------------------------------------- - if (vVelocity.Length() < 0.01) - { - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector(0,0,10), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction < 1.0 && tr.m_pEnt) - { - CBaseEntity *pEntity = tr.m_pEnt; - if (pEntity->GetFlags() & (FL_CLIENT | FL_NPC)) - { - // -------------------- - // Bounce me off - // -------------------- - Vector vNewVel; - vNewVel.y = 100; - vNewVel.x = random->RandomInt(-100,100); - vNewVel.z = random->RandomInt(-100,100); - - // If physically simulated - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - if ( pPhysicsObject ) - { - pPhysicsObject->AddVelocity( &vNewVel, &vAngVel ); - } - // Otherwise - else - { - SetAbsVelocity( vNewVel ); - } - } - } - } - - if (vVelocity.Length() < 0.01) - { - SpawnBrickbatWeapon(); - } - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -//===================================================================== -// > Rock -//===================================================================== -class CGrenadeRockBB : public CGrenade_Brickbat -{ -public: - DECLARE_CLASS( CGrenadeRockBB, CGrenade_Brickbat ); - - void Spawn(void) - { - m_nType = BRICKBAT_ROCK; - SetModel( "models/props_junk/Rock001a.mdl" ); - BaseClass::Spawn(); - } - void Precache( void ) - { - PrecacheModel("models/props_junk/Rock001a.mdl"); - BaseClass::Precache(); - } -}; -LINK_ENTITY_TO_CLASS( grenade_rockbb, CGrenadeRockBB ); -PRECACHE_REGISTER(grenade_rockbb); - - -//===================================================================== -// > BeerBottle -//===================================================================== -class CGrenadeBottle : public CGrenade_Brickbat -{ -public: - DECLARE_CLASS( CGrenadeBottle, CGrenade_Brickbat ); - - void Spawn(void) - { - m_nType = BRICKBAT_BOTTLE; - m_bExplodes = true; - SetModel( "models/weapons/w_bb_bottle.mdl" ); - BaseClass::Spawn(); - } - void Precache( void ); - void Detonate( void ); -}; - -void CGrenadeBottle::Precache( void ) -{ - PrecacheModel("models/weapons/w_bb_bottle.mdl"); - - PrecacheScriptSound( "GrenadeBottle.Detonate" ); - - BaseClass::Precache(); -} - -void CGrenadeBottle::Detonate( void ) -{ - trace_t trace; - - UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + GetAbsVelocity(), MASK_SOLID, this, COLLISION_GROUP_NONE, &trace); - UTIL_DecalTrace( &trace, "BeerSplash" ); - - EmitSound( "GrenadeBottle.Detonate" ); - - CSoundEnt::InsertSound(SOUND_COMBAT, GetAbsOrigin(), 400, 0.5); - - UTIL_Remove( this ); -} - -LINK_ENTITY_TO_CLASS( grenade_beerbottle, CGrenadeBottle ); -PRECACHE_REGISTER(grenade_beerbottle); - - diff --git a/game/server/hl2/grenade_brickbat.h b/game/server/hl2/grenade_brickbat.h deleted file mode 100644 index ebba2b433..000000000 --- a/game/server/hl2/grenade_brickbat.h +++ /dev/null @@ -1,40 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Things thrown from the hand -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef GRENADEBRICKBAT_H -#define GRENADEBRICKBAT_H - -#include "basegrenade_shared.h" -#include "weapon_brickbat.h" - -class CGrenade_Brickbat : public CBaseGrenade -{ -public: - DECLARE_CLASS( CGrenade_Brickbat, CBaseGrenade ); - - virtual void Spawn( void ); - virtual void SpawnBrickbatWeapon( void ); - virtual void Detonate( void ) { return;}; - virtual bool CreateVPhysics(); - void BrickbatTouch( CBaseEntity *pOther ); - void BrickbatThink( void ); - - BrickbatAmmo_t m_nType; - bool m_bExplodes; - bool m_bBounceToFlat; // Bouncing to flatten - -public: - DECLARE_DATADESC(); -}; - -#endif //GRENADEBRICKBAT_H diff --git a/game/server/hl2/grenade_bugbait.cpp b/game/server/hl2/grenade_bugbait.cpp deleted file mode 100644 index 0788aaa65..000000000 --- a/game/server/hl2/grenade_bugbait.cpp +++ /dev/null @@ -1,326 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Bugbait weapon to summon and direct antlions -// -//=============================================================================// - -#include "cbase.h" -#include "grenade_bugbait.h" -#include "decals.h" -#include "smoke_trail.h" -#include "soundent.h" -#include "engine/IEngineSound.h" -#include "npc_bullseye.h" -#include "entitylist.h" -#include "antlion_maker.h" -#include "eventqueue.h" - -#ifdef PORTAL - #include "portal_util_shared.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// Setup the sensor list template - -CEntityClassList g_BugBaitSensorList; -template <> CBugBaitSensor *CEntityClassList::m_pClassList = NULL; - -CBugBaitSensor* GetBugBaitSensorList() -{ - return g_BugBaitSensorList.m_pClassList; -} - -CBugBaitSensor::CBugBaitSensor( void ) -{ - g_BugBaitSensorList.Insert( this ); -} - -CBugBaitSensor::~CBugBaitSensor( void ) -{ - g_BugBaitSensorList.Remove( this ); -} - -BEGIN_DATADESC( CBugBaitSensor ) - - // This is re-set up in the constructor - //DEFINE_FIELD( m_pNext, FIELD_CLASSPTR ), - - DEFINE_KEYFIELD( m_bEnabled, FIELD_BOOLEAN, "Enabled" ), - DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "radius" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - - // Function Pointers - DEFINE_OUTPUT( m_OnBaited, "OnBaited" ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( point_bugbait, CBugBaitSensor ); - -//============================================================================= -// Bugbait grenade -//============================================================================= - -#define GRENADE_MODEL "models/weapons/w_bugbait.mdl" - -BEGIN_DATADESC( CGrenadeBugBait ) - - DEFINE_FIELD( m_flGracePeriodEndsAt, FIELD_TIME ), - DEFINE_FIELD( m_pSporeTrail, FIELD_CLASSPTR ), - - // Function Pointers - DEFINE_ENTITYFUNC( BugBaitTouch ), - DEFINE_THINKFUNC( ThinkBecomeSolid ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( npc_grenade_bugbait, CGrenadeBugBait ); - -//Radius of the bugbait's effect on other creatures -ConVar bugbait_radius( "bugbait_radius", "512" ); -ConVar bugbait_hear_radius( "bugbait_hear_radius", "2500" ); -ConVar bugbait_distract_time( "bugbait_distract_time", "5" ); -ConVar bugbait_grenade_radius( "bugbait_grenade_radius", "150" ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGrenadeBugBait::Spawn( void ) -{ - Precache(); - - SetModel( GRENADE_MODEL ); - SetCollisionGroup( COLLISION_GROUP_PROJECTILE ); - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_DEFAULT ); - SetSolid( SOLID_BBOX ); - - UTIL_SetSize( this, Vector( -2, -2, -2), Vector( 2, 2, 2 ) ); - - SetTouch( &CGrenadeBugBait::BugBaitTouch ); - - m_takedamage = DAMAGE_NO; - - m_pSporeTrail = NULL; - - /* - m_pSporeTrail = SporeTrail::CreateSporeTrail(); - - m_pSporeTrail->m_bEmit = true; - m_pSporeTrail->m_flSpawnRate = 100.0f; - m_pSporeTrail->m_flParticleLifetime = 1.0f; - m_pSporeTrail->m_flStartSize = 1.0f; - m_pSporeTrail->m_flEndSize = 1.0f; - m_pSporeTrail->m_flSpawnRadius = 8.0f; - - m_pSporeTrail->m_vecEndColor = Vector( 0, 0, 0 ); - */ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGrenadeBugBait::Precache( void ) -{ - PrecacheModel( GRENADE_MODEL ); - - PrecacheScriptSound( "GrenadeBugBait.Splat" ); - - BaseClass::Precache(); -} - -#define NUM_SPLASHES 6 - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGrenadeBugBait::BugBaitTouch( CBaseEntity *pOther ) -{ - // Don't hit triggers or water - Assert( pOther ); - if ( pOther->IsSolidFlagSet(FSOLID_TRIGGER|FSOLID_VOLUME_CONTENTS) ) - return; - - if ( m_pSporeTrail != NULL ) - { - m_pSporeTrail->m_bEmit = false; - } - - //Do effect for the hit - SporeExplosion *pSporeExplosion = SporeExplosion::CreateSporeExplosion(); - - if ( pSporeExplosion ) - { - Vector dir = -GetAbsVelocity(); - VectorNormalize( dir ); - - QAngle angles; - VectorAngles( dir, angles ); - - pSporeExplosion->SetLocalAngles( angles ); - pSporeExplosion->SetLocalOrigin( GetAbsOrigin() ); - pSporeExplosion->m_flSpawnRate = 8.0f; - pSporeExplosion->m_flParticleLifetime = 2.0f; - pSporeExplosion->SetRenderColor( 0, (int)0.5f, (int)0.25f, (int)0.15f ); - - pSporeExplosion->m_flStartSize = 32.0f; - pSporeExplosion->m_flEndSize = 64.0f; - pSporeExplosion->m_flSpawnRadius = 32.0f; - - pSporeExplosion->SetLifetime( bugbait_distract_time.GetFloat() ); - } - - trace_t tr; - Vector traceDir = GetAbsVelocity(); - - VectorNormalize( traceDir ); - - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + traceDir * 64, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction < 1.0f ) - { - UTIL_DecalTrace( &tr, "BeerSplash" ); //TODO: Use real decal - } - - //Make a splat sound - CPASAttenuationFilter filter( this ); - EmitSound( filter, entindex(), "GrenadeBugBait.Splat" ); - - //Make sure we want to call antlions - if ( ActivateBugbaitTargets( GetThrower(), GetAbsOrigin(), false ) == false ) - { - //Alert any antlions around - CSoundEnt::InsertSound( SOUND_BUGBAIT, GetAbsOrigin(), bugbait_hear_radius.GetInt(), bugbait_distract_time.GetFloat(), GetThrower() ); - } - - // Tell all spawners to now fight to this position - g_AntlionMakerManager.BroadcastFightGoal( GetAbsOrigin() ); - - //Go away - UTIL_Remove( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: Activate any nearby bugbait targets -// Returns true if the bugbait target wants to suppress the call. -//----------------------------------------------------------------------------- -bool CGrenadeBugBait::ActivateBugbaitTargets( CBaseEntity *pOwner, Vector vecOrigin, bool bSqueezed ) -{ - //Attempt to activate any spawners in a radius around the bugbait - CBaseEntity* pList[100]; - Vector delta( bugbait_grenade_radius.GetFloat(), bugbait_grenade_radius.GetFloat(), bugbait_grenade_radius.GetFloat() ); - bool suppressCall = false; - - int count = UTIL_EntitiesInBox( pList, 100, vecOrigin - delta, vecOrigin + delta, 0 ); - - // If the bugbait's been thrown, look for nearby targets to affect - if ( !bSqueezed ) - { - for ( int i = 0; i < count; i++ ) - { - // If close enough, make combine soldiers freak out when hit - if ( UTIL_DistApprox( pList[i]->WorldSpaceCenter(), vecOrigin ) < bugbait_grenade_radius.GetFloat() ) - { - // Must be a soldier - if ( FClassnameIs( pList[i], "npc_combine_s") ) - { - CAI_BaseNPC *pCombine = pList[i]->MyNPCPointer(); - - if ( pCombine != NULL ) - { - trace_t tr; - UTIL_TraceLine( vecOrigin, pCombine->EyePosition(), MASK_ALL, pOwner, COLLISION_GROUP_NONE, &tr); - - if ( tr.fraction == 1.0 || tr.m_pEnt == pCombine ) - { - // Randomize the start time a little so multiple combine hit by - // the same bugbait don't all dance in synch. - g_EventQueue.AddEvent( pCombine, "HitByBugbait", RandomFloat(0, 0.5), pOwner, pOwner ); - } - } - } - } - } - } - // Iterate over all sensors to see if they detected this impact - for ( CBugBaitSensor *pSensor = GetBugBaitSensorList(); pSensor != NULL; pSensor = pSensor->m_pNext ) - { - if ( pSensor == NULL ) - continue; - - if ( pSensor->IsDisabled() ) - continue; - - if ( bSqueezed && pSensor->DetectsSqueeze() == false ) - continue; - - if ( !bSqueezed && pSensor->DetectsThrown() == false ) - continue; - - //Make sure we're within range of the sensor - if ( pSensor->GetRadius() > ( pSensor->GetAbsOrigin() - vecOrigin ).Length() ) - { - //Tell the sensor it's been hit - if ( pSensor->Baited( pOwner ) ) - { - //If we're suppressing the call to antlions, then don't make a bugbait sound - if ( pSensor->SuppressCall() ) - { - suppressCall = true; - } - } - } - } - - return suppressCall; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGrenadeBugBait::ThinkBecomeSolid( void ) -{ - SetThink( NULL ); - RemoveSolidFlags( FSOLID_NOT_SOLID ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : duration - -//----------------------------------------------------------------------------- -void CGrenadeBugBait::SetGracePeriod( float duration ) -{ - SetThink( &CGrenadeBugBait::ThinkBecomeSolid ); - SetNextThink( gpGlobals->curtime + duration ); - - // Become unsolid - AddSolidFlags( FSOLID_NOT_SOLID ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &position - -// &angles - -// &velocity - -// &angVelocity - -// *owner - -// Output : CBaseGrenade -//----------------------------------------------------------------------------- -CGrenadeBugBait *BugBaitGrenade_Create( const Vector &position, const QAngle &angles, const Vector &velocity, const QAngle &angVelocity, CBaseEntity *owner ) -{ - CGrenadeBugBait *pGrenade = (CGrenadeBugBait *) CBaseEntity::Create( "npc_grenade_bugbait", position, angles, owner ); - - if ( pGrenade != NULL ) - { - pGrenade->SetLocalAngularVelocity( angVelocity ); - pGrenade->SetAbsVelocity( velocity ); - pGrenade->SetThrower( ToBaseCombatCharacter( owner ) ); - } - - return pGrenade; -} - diff --git a/game/server/hl2/grenade_bugbait.h b/game/server/hl2/grenade_bugbait.h deleted file mode 100644 index 6bfb59f7b..000000000 --- a/game/server/hl2/grenade_bugbait.h +++ /dev/null @@ -1,135 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef GRENADE_BUGBAIT_H -#define GRENADE_BUGBAIT_H -#ifdef _WIN32 -#pragma once -#endif - -#include "smoke_trail.h" -#include "basegrenade_shared.h" - -//Radius of the bugbait's effect on other creatures -extern ConVar bugbait_radius; -extern ConVar bugbait_hear_radius; -extern ConVar bugbait_distract_time; -extern ConVar bugbait_grenade_radius; - -#define SF_BUGBAIT_SUPPRESS_CALL 0x00000001 -#define SF_BUGBAIT_NOT_THROWN 0x00000002 // Don't detect player throwing the bugbait near this point -#define SF_BUGBAIT_NOT_SQUEEZE 0x00000004 // Don't detect player squeezing the bugbait - -//============================================================================= -// Bugbait sensor -//============================================================================= - -class CBugBaitSensor : public CPointEntity -{ -public: - - DECLARE_CLASS( CBugBaitSensor, CPointEntity ); - - DECLARE_DATADESC(); - - CBugBaitSensor( void ); - ~CBugBaitSensor( void ); - - bool Baited( CBaseEntity *pOther ) - { - if ( !m_bEnabled ) - return false; - - m_OnBaited.FireOutput( pOther, this ); - return true; - } - - void InputEnable( inputdata_t &data ) - { - m_bEnabled = true; - } - - void InputDisable( inputdata_t &data ) - { - m_bEnabled = false; - } - - void InputToggle( inputdata_t &data ) - { - m_bEnabled = !m_bEnabled; - } - - bool SuppressCall( void ) - { - return ( HasSpawnFlags( SF_BUGBAIT_SUPPRESS_CALL ) ); - } - - bool DetectsSqueeze( void ) - { - return ( !HasSpawnFlags( SF_BUGBAIT_NOT_SQUEEZE ) ); - } - - bool DetectsThrown( void ) - { - return ( !HasSpawnFlags( SF_BUGBAIT_NOT_THROWN ) ); - } - - float GetRadius( void ) const - { - if ( m_flRadius == 0 ) - return bugbait_radius.GetFloat(); - - return m_flRadius; - } - - bool IsDisabled( void ) const - { - return !m_bEnabled; - } - -protected: - - float m_flRadius; - bool m_bEnabled; - COutputEvent m_OnBaited; - -public: - CBugBaitSensor *m_pNext; -}; - -// -// Bug Bait Grenade -// - -class CGrenadeBugBait : public CBaseGrenade -{ - DECLARE_CLASS( CGrenadeBugBait, CBaseGrenade ); -public: - void Spawn( void ); - void Precache( void ); - - void ThinkBecomeSolid( void ); - void SetGracePeriod( float duration ); - - void BugBaitTouch( CBaseEntity *pOther ); - - // Activate nearby bugbait targets - static bool ActivateBugbaitTargets( CBaseEntity *pOwner, Vector vecOrigin, bool bSqueezed ); - - DECLARE_DATADESC(); - -protected: - void CreateTarget( const Vector &position, CBaseEntity *pOther ); - - float m_flGracePeriodEndsAt; - - SporeTrail *m_pSporeTrail; -}; - -extern CGrenadeBugBait *BugBaitGrenade_Create( const Vector &position, const QAngle &angles, const Vector &velocity, const QAngle &angVelocity, CBaseEntity *owner ); - -#endif // GRENADE_BUGBAIT_H diff --git a/game/server/hl2/grenade_energy.cpp b/game/server/hl2/grenade_energy.cpp deleted file mode 100644 index 533f3eaee..000000000 --- a/game/server/hl2/grenade_energy.cpp +++ /dev/null @@ -1,158 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Projectile shot by mortar synth. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "grenade_energy.h" -#include "soundent.h" -#include "player.h" -#include "hl2_shareddefs.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define ENERGY_GRENADE_LIFETIME 1 - -ConVar sk_dmg_energy_grenade ( "sk_dmg_energy_grenade","0"); -ConVar sk_energy_grenade_radius ( "sk_energy_grenade_radius","0"); - -BEGIN_DATADESC( CGrenadeEnergy ) - - DEFINE_FIELD( m_flMaxFrame, FIELD_INTEGER ), - DEFINE_FIELD( m_nEnergySprite, FIELD_INTEGER ), - DEFINE_FIELD( m_flLaunchTime, FIELD_TIME ), - - // Function pointers - DEFINE_THINKFUNC( Animate ), - DEFINE_ENTITYFUNC( GrenadeEnergyTouch ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( grenade_energy, CGrenadeEnergy ); - -void CGrenadeEnergy::Spawn( void ) -{ - Precache( ); - SetSolid( SOLID_BBOX ); - SetMoveType( MOVETYPE_FLY ); - - SetModel( "Models/weapons/w_energy_grenade.mdl" ); - - SetUse( &CBaseGrenade::DetonateUse ); - SetTouch( &CGrenadeEnergy::GrenadeEnergyTouch ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - m_flDamage = sk_dmg_energy_grenade.GetFloat(); - m_DmgRadius = sk_energy_grenade_radius.GetFloat(); - m_takedamage = DAMAGE_YES; - m_iHealth = 1; - - SetCycle(0); - - m_flLaunchTime = gpGlobals->curtime; - - SetCollisionGroup( HL2COLLISION_GROUP_HOUNDEYE ); - - UTIL_SetSize( this, vec3_origin, vec3_origin ); - - m_flMaxFrame = modelinfo->GetModelFrameCount( GetModel() ) - 1; - -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenadeEnergy::Shoot( CBaseEntity* pOwner, const Vector &vStart, Vector vVelocity ) -{ - CGrenadeEnergy *pEnergy = (CGrenadeEnergy *)CreateEntityByName( "grenade_energy" ); - pEnergy->Spawn(); - - UTIL_SetOrigin( pEnergy, vStart ); - pEnergy->SetAbsVelocity( vVelocity ); - pEnergy->SetOwnerEntity( pOwner ); - - pEnergy->SetThink ( &CGrenadeEnergy::Animate ); - pEnergy->SetNextThink( gpGlobals->curtime + 0.1f ); - - pEnergy->m_nRenderMode = kRenderTransAdd; - pEnergy->SetRenderColor( 160, 160, 160, 255 ); - pEnergy->m_nRenderFX = kRenderFxNone; -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenadeEnergy::Animate( void ) -{ - float flLifeLeft = 1-(gpGlobals->curtime - m_flLaunchTime)/ENERGY_GRENADE_LIFETIME; - - if (flLifeLeft < 0) - { - SetRenderColorA( 0 ); - SetThink(NULL); - UTIL_Remove(this); - } - - SetNextThink( gpGlobals->curtime + 0.01f ); - - QAngle angles; - VectorAngles( GetAbsVelocity(), angles ); - SetLocalAngles( angles ); - - SetNextThink( gpGlobals->curtime + 0.1f ); - - StudioFrameAdvance( ); - - SetRenderColorA( (byte)flLifeLeft ); -} - -void CGrenadeEnergy::Event_Killed( const CTakeDamageInfo &info ) -{ - Detonate( ); -} - -void CGrenadeEnergy::GrenadeEnergyTouch( CBaseEntity *pOther ) -{ - if ( pOther->m_takedamage ) - { - float flLifeLeft = 1-(gpGlobals->curtime - m_flLaunchTime)/ENERGY_GRENADE_LIFETIME; - - if ( pOther->GetFlags() & (FL_CLIENT) ) - { - CBasePlayer *pPlayer = ( CBasePlayer * )pOther; - float flKick = 120 * flLifeLeft; - pPlayer->m_Local.m_vecPunchAngle.SetX( flKick * (random->RandomInt(0,1) == 1) ? -1 : 1 ); - pPlayer->m_Local.m_vecPunchAngle.SetY( flKick * (random->RandomInt(0,1) == 1) ? -1 : 1 ); - } - float flDamage = m_flDamage * flLifeLeft; - if (flDamage < 1) - { - flDamage = 1; - } - - trace_t tr; - tr = GetTouchTrace(); - CTakeDamageInfo info( this, GetThrower(), m_flDamage * flLifeLeft, DMG_SONIC ); - CalculateMeleeDamageForce( &info, (tr.endpos - tr.startpos), tr.endpos ); - pOther->TakeDamage( info ); - } - Detonate(); -} - -void CGrenadeEnergy::Detonate(void) -{ - m_takedamage = DAMAGE_NO; - UTIL_Remove( this ); -} - -void CGrenadeEnergy::Precache( void ) -{ - PrecacheModel("Models/weapons/w_energy_grenade.mdl"); -} diff --git a/game/server/hl2/grenade_energy.h b/game/server/hl2/grenade_energy.h deleted file mode 100644 index 721a1e4eb..000000000 --- a/game/server/hl2/grenade_energy.h +++ /dev/null @@ -1,42 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Projectile shot by mortar synth -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef GRENADEENERGY_H -#define GRENADEENERGY_H - -#include "basegrenade_shared.h" - -class CGrenadeEnergy : public CBaseGrenade -{ -public: - DECLARE_CLASS( CGrenadeEnergy, CBaseGrenade ); - - static void Shoot( CBaseEntity* pOwner, const Vector &vStart, Vector vVelocity ); - -public: - void Spawn( void ); - void Precache( void ); - void Animate( void ); - void GrenadeEnergyTouch( CBaseEntity *pOther ); - void Event_Killed( const CTakeDamageInfo &info ); - - int m_flMaxFrame; - int m_nEnergySprite; - float m_flLaunchTime; // When was this thing launched - - void EXPORT Detonate(void); - - DECLARE_DATADESC(); -}; - -#endif //GRENADEENERGY_H diff --git a/game/server/hl2/grenade_frag.cpp b/game/server/hl2/grenade_frag.cpp deleted file mode 100644 index 05f5250b7..000000000 --- a/game/server/hl2/grenade_frag.cpp +++ /dev/null @@ -1,453 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "basegrenade_shared.h" -#include "grenade_frag.h" -#include "Sprite.h" -#include "SpriteTrail.h" -#include "soundent.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define FRAG_GRENADE_BLIP_FREQUENCY 1.0f -#define FRAG_GRENADE_BLIP_FAST_FREQUENCY 0.3f - -#define FRAG_GRENADE_GRACE_TIME_AFTER_PICKUP 1.5f -#define FRAG_GRENADE_WARN_TIME 1.5f - -const float GRENADE_COEFFICIENT_OF_RESTITUTION = 0.2f; - -ConVar sk_plr_dmg_fraggrenade ( "sk_plr_dmg_fraggrenade","0"); -ConVar sk_npc_dmg_fraggrenade ( "sk_npc_dmg_fraggrenade","0"); -ConVar sk_fraggrenade_radius ( "sk_fraggrenade_radius", "0"); - -#define GRENADE_MODEL "models/Weapons/w_grenade.mdl" - -class CGrenadeFrag : public CBaseGrenade -{ - DECLARE_CLASS( CGrenadeFrag, CBaseGrenade ); - -#if !defined( CLIENT_DLL ) - DECLARE_DATADESC(); -#endif - - ~CGrenadeFrag( void ); - -public: - void Spawn( void ); - void OnRestore( void ); - void Precache( void ); - bool CreateVPhysics( void ); - void CreateEffects( void ); - void SetTimer( float detonateDelay, float warnDelay ); - void SetVelocity( const Vector &velocity, const AngularImpulse &angVelocity ); - int OnTakeDamage( const CTakeDamageInfo &inputInfo ); - void BlipSound() { EmitSound( "Grenade.Blip" ); } - void DelayThink(); - void VPhysicsUpdate( IPhysicsObject *pPhysics ); - void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ); - void SetCombineSpawned( bool combineSpawned ) { m_combineSpawned = combineSpawned; } - bool IsCombineSpawned( void ) const { return m_combineSpawned; } - void SetPunted( bool punt ) { m_punted = punt; } - bool WasPunted( void ) const { return m_punted; } - - // this function only used in episodic. -#ifdef HL2_EPISODIC - bool HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt); -#endif - - void InputSetTimer( inputdata_t &inputdata ); - -protected: - CHandle m_pMainGlow; - CHandle m_pGlowTrail; - - float m_flNextBlipTime; - bool m_inSolid; - bool m_combineSpawned; - bool m_punted; -}; - -LINK_ENTITY_TO_CLASS( npc_grenade_frag, CGrenadeFrag ); - -BEGIN_DATADESC( CGrenadeFrag ) - - // Fields - DEFINE_FIELD( m_pMainGlow, FIELD_EHANDLE ), - DEFINE_FIELD( m_pGlowTrail, FIELD_EHANDLE ), - DEFINE_FIELD( m_flNextBlipTime, FIELD_TIME ), - DEFINE_FIELD( m_inSolid, FIELD_BOOLEAN ), - DEFINE_FIELD( m_combineSpawned, FIELD_BOOLEAN ), - DEFINE_FIELD( m_punted, FIELD_BOOLEAN ), - - // Function Pointers - DEFINE_THINKFUNC( DelayThink ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetTimer", InputSetTimer ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CGrenadeFrag::~CGrenadeFrag( void ) -{ -} - -void CGrenadeFrag::Spawn( void ) -{ - Precache( ); - - SetModel( GRENADE_MODEL ); - - if( GetOwnerEntity() && GetOwnerEntity()->IsPlayer() ) - { - m_flDamage = sk_plr_dmg_fraggrenade.GetFloat(); - m_DmgRadius = sk_fraggrenade_radius.GetFloat(); - } - else - { - m_flDamage = sk_npc_dmg_fraggrenade.GetFloat(); - m_DmgRadius = sk_fraggrenade_radius.GetFloat(); - } - - m_takedamage = DAMAGE_YES; - m_iHealth = 1; - - SetSize( -Vector(4,4,4), Vector(4,4,4) ); - SetCollisionGroup( COLLISION_GROUP_WEAPON ); - CreateVPhysics(); - - BlipSound(); - m_flNextBlipTime = gpGlobals->curtime + FRAG_GRENADE_BLIP_FREQUENCY; - - AddSolidFlags( FSOLID_NOT_STANDABLE ); - - m_combineSpawned = false; - m_punted = false; - - BaseClass::Spawn(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGrenadeFrag::OnRestore( void ) -{ - // If we were primed and ready to detonate, put FX on us. - if (m_flDetonateTime > 0) - CreateEffects(); - - BaseClass::OnRestore(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGrenadeFrag::CreateEffects( void ) -{ - // Start up the eye glow - m_pMainGlow = CSprite::SpriteCreate( "sprites/redglow1.vmt", GetLocalOrigin(), false ); - - int nAttachment = LookupAttachment( "fuse" ); - - if ( m_pMainGlow != NULL ) - { - m_pMainGlow->FollowEntity( this ); - m_pMainGlow->SetAttachment( this, nAttachment ); - m_pMainGlow->SetTransparency( kRenderGlow, 255, 255, 255, 200, kRenderFxNoDissipation ); - m_pMainGlow->SetScale( 0.2f ); - m_pMainGlow->SetGlowProxySize( 4.0f ); - } - - // Start up the eye trail - m_pGlowTrail = CSpriteTrail::SpriteTrailCreate( "sprites/bluelaser1.vmt", GetLocalOrigin(), false ); - - if ( m_pGlowTrail != NULL ) - { - m_pGlowTrail->FollowEntity( this ); - m_pGlowTrail->SetAttachment( this, nAttachment ); - m_pGlowTrail->SetTransparency( kRenderTransAdd, 255, 0, 0, 255, kRenderFxNone ); - m_pGlowTrail->SetStartWidth( 8.0f ); - m_pGlowTrail->SetEndWidth( 1.0f ); - m_pGlowTrail->SetLifeTime( 0.5f ); - } -} - -bool CGrenadeFrag::CreateVPhysics() -{ - // Create the object in the physics system - VPhysicsInitNormal( SOLID_BBOX, 0, false ); - return true; -} - -// this will hit only things that are in newCollisionGroup, but NOT in collisionGroupAlreadyChecked -class CTraceFilterCollisionGroupDelta : public CTraceFilterEntitiesOnly -{ -public: - // It does have a base, but we'll never network anything below here.. - DECLARE_CLASS_NOBASE( CTraceFilterCollisionGroupDelta ); - - CTraceFilterCollisionGroupDelta( const IHandleEntity *passentity, int collisionGroupAlreadyChecked, int newCollisionGroup ) - : m_pPassEnt(passentity), m_collisionGroupAlreadyChecked( collisionGroupAlreadyChecked ), m_newCollisionGroup( newCollisionGroup ) - { - } - - virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) - { - if ( !PassServerEntityFilter( pHandleEntity, m_pPassEnt ) ) - return false; - CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); - - if ( pEntity ) - { - if ( g_pGameRules->ShouldCollide( m_collisionGroupAlreadyChecked, pEntity->GetCollisionGroup() ) ) - return false; - if ( g_pGameRules->ShouldCollide( m_newCollisionGroup, pEntity->GetCollisionGroup() ) ) - return true; - } - - return false; - } - -protected: - const IHandleEntity *m_pPassEnt; - int m_collisionGroupAlreadyChecked; - int m_newCollisionGroup; -}; - -void CGrenadeFrag::VPhysicsUpdate( IPhysicsObject *pPhysics ) -{ - BaseClass::VPhysicsUpdate( pPhysics ); - Vector vel; - AngularImpulse angVel; - pPhysics->GetVelocity( &vel, &angVel ); - - Vector start = GetAbsOrigin(); - // find all entities that my collision group wouldn't hit, but COLLISION_GROUP_NONE would and bounce off of them as a ray cast - CTraceFilterCollisionGroupDelta filter( this, GetCollisionGroup(), COLLISION_GROUP_NONE ); - trace_t tr; - - // UNDONE: Hull won't work with hitboxes - hits outer hull. But the whole point of this test is to hit hitboxes. -#if 0 - UTIL_TraceHull( start, start + vel * gpGlobals->frametime, CollisionProp()->OBBMins(), CollisionProp()->OBBMaxs(), CONTENTS_HITBOX|CONTENTS_MONSTER|CONTENTS_SOLID, &filter, &tr ); -#else - UTIL_TraceLine( start, start + vel * gpGlobals->frametime, CONTENTS_HITBOX|CONTENTS_MONSTER|CONTENTS_SOLID, &filter, &tr ); -#endif - if ( tr.startsolid ) - { - if ( !m_inSolid ) - { - // UNDONE: Do a better contact solution that uses relative velocity? - vel *= -GRENADE_COEFFICIENT_OF_RESTITUTION; // bounce backwards - pPhysics->SetVelocity( &vel, NULL ); - } - m_inSolid = true; - return; - } - m_inSolid = false; - if ( tr.DidHit() ) - { - Vector dir = vel; - VectorNormalize(dir); - // send a tiny amount of damage so the character will react to getting bonked - CTakeDamageInfo info( this, GetThrower(), pPhysics->GetMass() * vel, GetAbsOrigin(), 0.1f, DMG_CRUSH ); - tr.m_pEnt->TakeDamage( info ); - - // reflect velocity around normal - vel = -2.0f * tr.plane.normal * DotProduct(vel,tr.plane.normal) + vel; - - // absorb 80% in impact - vel *= GRENADE_COEFFICIENT_OF_RESTITUTION; - angVel *= -0.5f; - pPhysics->SetVelocity( &vel, &angVel ); - } -} - - -void CGrenadeFrag::Precache( void ) -{ - PrecacheModel( GRENADE_MODEL ); - - PrecacheScriptSound( "Grenade.Blip" ); - - PrecacheModel( "sprites/redglow1.vmt" ); - PrecacheModel( "sprites/bluelaser1.vmt" ); - - BaseClass::Precache(); -} - -void CGrenadeFrag::SetTimer( float detonateDelay, float warnDelay ) -{ - m_flDetonateTime = gpGlobals->curtime + detonateDelay; - m_flWarnAITime = gpGlobals->curtime + warnDelay; - SetThink( &CGrenadeFrag::DelayThink ); - SetNextThink( gpGlobals->curtime ); - - CreateEffects(); -} - -void CGrenadeFrag::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) -{ - SetThrower( pPhysGunUser ); - -#ifdef HL2MP - SetTimer( FRAG_GRENADE_GRACE_TIME_AFTER_PICKUP, FRAG_GRENADE_GRACE_TIME_AFTER_PICKUP / 2); - - BlipSound(); - m_flNextBlipTime = gpGlobals->curtime + FRAG_GRENADE_BLIP_FAST_FREQUENCY; - m_bHasWarnedAI = true; -#else - if( IsX360() ) - { - // Give 'em a couple of seconds to aim and throw. - SetTimer( 2.0f, 1.0f); - BlipSound(); - m_flNextBlipTime = gpGlobals->curtime + FRAG_GRENADE_BLIP_FAST_FREQUENCY; - } -#endif - -#ifdef HL2_EPISODIC - SetPunted( true ); -#endif - - BaseClass::OnPhysGunPickup( pPhysGunUser, reason ); -} - -void CGrenadeFrag::DelayThink() -{ - if( gpGlobals->curtime > m_flDetonateTime ) - { - Detonate(); - return; - } - - if( !m_bHasWarnedAI && gpGlobals->curtime >= m_flWarnAITime ) - { -#if !defined( CLIENT_DLL ) - CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin(), 400, 1.5, this ); -#endif - m_bHasWarnedAI = true; - } - - if( gpGlobals->curtime > m_flNextBlipTime ) - { - BlipSound(); - - if( m_bHasWarnedAI ) - { - m_flNextBlipTime = gpGlobals->curtime + FRAG_GRENADE_BLIP_FAST_FREQUENCY; - } - else - { - m_flNextBlipTime = gpGlobals->curtime + FRAG_GRENADE_BLIP_FREQUENCY; - } - } - - SetNextThink( gpGlobals->curtime + 0.1 ); -} - -void CGrenadeFrag::SetVelocity( const Vector &velocity, const AngularImpulse &angVelocity ) -{ - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - if ( pPhysicsObject ) - { - pPhysicsObject->AddVelocity( &velocity, &angVelocity ); - } -} - -int CGrenadeFrag::OnTakeDamage( const CTakeDamageInfo &inputInfo ) -{ - // Manually apply vphysics because BaseCombatCharacter takedamage doesn't call back to CBaseEntity OnTakeDamage - VPhysicsTakeDamage( inputInfo ); - - // Grenades only suffer blast damage and burn damage. - if( !(inputInfo.GetDamageType() & (DMG_BLAST|DMG_BURN) ) ) - return 0; - - return BaseClass::OnTakeDamage( inputInfo ); -} - -#ifdef HL2_EPISODIC -extern int g_interactionBarnacleVictimGrab; ///< usually declared in ai_interactions.h but no reason to haul all of that in here. -extern int g_interactionBarnacleVictimBite; -extern int g_interactionBarnacleVictimReleased; -bool CGrenadeFrag::HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt) -{ - // allow fragnades to be grabbed by barnacles. - if ( interactionType == g_interactionBarnacleVictimGrab ) - { - // give the grenade another five seconds seconds so the player can have the satisfaction of blowing up the barnacle with it - float timer = m_flDetonateTime - gpGlobals->curtime + 5.0f; - SetTimer( timer, timer - FRAG_GRENADE_WARN_TIME ); - - return true; - } - else if ( interactionType == g_interactionBarnacleVictimBite ) - { - // detonate the grenade immediately - SetTimer( 0, 0 ); - return true; - } - else if ( interactionType == g_interactionBarnacleVictimReleased ) - { - // take the five seconds back off the timer. - float timer = MAX(m_flDetonateTime - gpGlobals->curtime - 5.0f,0.0f); - SetTimer( timer, timer - FRAG_GRENADE_WARN_TIME ); - return true; - } - else - { - return BaseClass::HandleInteraction( interactionType, data, sourceEnt ); - } -} -#endif - -void CGrenadeFrag::InputSetTimer( inputdata_t &inputdata ) -{ - SetTimer( inputdata.value.Float(), inputdata.value.Float() - FRAG_GRENADE_WARN_TIME ); -} - -CBaseGrenade *Fraggrenade_Create( const Vector &position, const QAngle &angles, const Vector &velocity, const AngularImpulse &angVelocity, CBaseEntity *pOwner, float timer, bool combineSpawned ) -{ - // Don't set the owner here, or the player can't interact with grenades he's thrown - CGrenadeFrag *pGrenade = (CGrenadeFrag *)CBaseEntity::Create( "npc_grenade_frag", position, angles, pOwner ); - - pGrenade->SetTimer( timer, timer - FRAG_GRENADE_WARN_TIME ); - pGrenade->SetVelocity( velocity, angVelocity ); - pGrenade->SetThrower( ToBaseCombatCharacter( pOwner ) ); - pGrenade->m_takedamage = DAMAGE_EVENTS_ONLY; - pGrenade->SetCombineSpawned( combineSpawned ); - - return pGrenade; -} - -bool Fraggrenade_WasPunted( const CBaseEntity *pEntity ) -{ - const CGrenadeFrag *pFrag = dynamic_cast( pEntity ); - if ( pFrag ) - { - return pFrag->WasPunted(); - } - - return false; -} - -bool Fraggrenade_WasCreatedByCombine( const CBaseEntity *pEntity ) -{ - const CGrenadeFrag *pFrag = dynamic_cast( pEntity ); - if ( pFrag ) - { - return pFrag->IsCombineSpawned(); - } - - return false; -} diff --git a/game/server/hl2/grenade_frag.h b/game/server/hl2/grenade_frag.h deleted file mode 100644 index 05f70a2e0..000000000 --- a/game/server/hl2/grenade_frag.h +++ /dev/null @@ -1,19 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef GRENADE_FRAG_H -#define GRENADE_FRAG_H -#pragma once - -class CBaseGrenade; -struct edict_t; - -CBaseGrenade *Fraggrenade_Create( const Vector &position, const QAngle &angles, const Vector &velocity, const AngularImpulse &angVelocity, CBaseEntity *pOwner, float timer, bool combineSpawned ); -bool Fraggrenade_WasPunted( const CBaseEntity *pEntity ); -bool Fraggrenade_WasCreatedByCombine( const CBaseEntity *pEntity ); - -#endif // GRENADE_FRAG_H diff --git a/game/server/hl2/grenade_homer.cpp b/game/server/hl2/grenade_homer.cpp deleted file mode 100644 index 0f5927565..000000000 --- a/game/server/hl2/grenade_homer.cpp +++ /dev/null @@ -1,696 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Grenade used by the city scanner -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "grenade_homer.h" -#include "weapon_ar2.h" -#include "soundent.h" -#include "decals.h" -#include "shake.h" -#include "smoke_trail.h" -#include "ar2_explosion.h" -#include "mathlib/mathlib.h" -#include "game.h" -#include "ndebugoverlay.h" -#include "hl2_shareddefs.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "movevars_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define HOMER_TRAIL0_LIFE 0.1 -#define HOMER_TRAIL1_LIFE 0.2 -#define HOMER_TRAIL2_LIFE 3.0// 1.0 - -extern short g_sModelIndexFireball; // (in combatweapon.cpp) holds the index for the smoke cloud - -ConVar sk_dmg_homer_grenade( "sk_dmg_homer_grenade","0" ); -ConVar sk_homer_grenade_radius( "sk_homer_grenade_radius","0" ); - -BEGIN_DATADESC( CGrenadeHomer ) - - DEFINE_ARRAY( m_hRocketTrail, FIELD_EHANDLE, 3 ), - DEFINE_FIELD( m_sFlySound, FIELD_STRING), - DEFINE_FIELD( m_flNextFlySoundTime, FIELD_TIME), - - DEFINE_FIELD( m_flHomingStrength, FIELD_FLOAT), - DEFINE_FIELD( m_flHomingDelay, FIELD_FLOAT), - DEFINE_FIELD( m_flHomingRampUp, FIELD_FLOAT), - DEFINE_FIELD( m_flHomingDuration, FIELD_FLOAT), - DEFINE_FIELD( m_flHomingRampDown, FIELD_FLOAT), - DEFINE_FIELD( m_flHomingSpeed, FIELD_FLOAT), - DEFINE_FIELD( m_flSpinMagnitude, FIELD_FLOAT), - DEFINE_FIELD( m_flSpinSpeed, FIELD_FLOAT), - DEFINE_FIELD( m_nRocketTrailType, FIELD_INTEGER), - -// DEFINE_FIELD( m_spriteTexture, FIELD_INTEGER), - - DEFINE_FIELD( m_flHomingLaunchTime, FIELD_TIME), - DEFINE_FIELD( m_flHomingStartTime, FIELD_TIME ), - DEFINE_FIELD( m_flHomingEndTime, FIELD_TIME ), - DEFINE_FIELD( m_flSpinOffset, FIELD_FLOAT), - - DEFINE_FIELD( m_hTarget, FIELD_EHANDLE), - - // Function pointers - DEFINE_THINKFUNC( AimThink ), - DEFINE_ENTITYFUNC( GrenadeHomerTouch ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( grenade_homer, CGrenadeHomer ); - - -///------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -CGrenadeHomer* CGrenadeHomer::CreateGrenadeHomer( string_t sModelName, string_t sFlySound, const Vector &vecOrigin, const QAngle &vecAngles, edict_t *pentOwner ) -{ - CGrenadeHomer *pGrenade = (CGrenadeHomer*)CreateEntityByName( "grenade_homer" ); - if ( !pGrenade ) - { - Warning( "NULL Ent in Create!\n" ); - return NULL; - } - - if ( pGrenade->edict() ) - { - pGrenade->m_sFlySound = sFlySound; - pGrenade->SetOwnerEntity( Instance( pentOwner ) ); - pGrenade->SetLocalOrigin( vecOrigin ); - pGrenade->SetLocalAngles( vecAngles ); - pGrenade->SetModel( STRING(sModelName) ); - } - return pGrenade; -} - - -void CGrenadeHomer::Precache( void ) -{ - m_spriteTexture = PrecacheModel( "sprites/lgtning.vmt" ); - - PrecacheScriptSound( "GrenadeHomer.StopSounds" ); - if ( NULL_STRING != m_sFlySound ) - { - PrecacheScriptSound( STRING(m_sFlySound) ); - } - -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenadeHomer::Spawn( void ) -{ - Precache( ); - - SetSolid( SOLID_BBOX ); - SetMoveType( MOVETYPE_FLY ); - - UTIL_SetSize(this, Vector(0, 0, 0), Vector(0, 0, 0)); - - m_flDamage = sk_dmg_homer_grenade.GetFloat(); - m_DmgRadius = sk_homer_grenade_radius.GetFloat(); - m_takedamage = DAMAGE_YES; - m_iHealth = 1; - - SetGravity( 1.0 ); - SetFriction( 0.8 ); - SetSequence( 1 ); - - m_flHomingStrength = 0; - m_flHomingDelay = 0; - m_flHomingDuration = 0; - - SetCollisionGroup( HL2COLLISION_GROUP_HOMING_MISSILE ); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenadeHomer::SetSpin(float flSpinMagnitude, float flSpinSpeed) -{ - m_flSpinMagnitude = flSpinMagnitude; - m_flSpinSpeed = flSpinSpeed; - m_flSpinOffset = random->RandomInt((int)-m_flSpinSpeed, (int)m_flSpinSpeed); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenadeHomer::SetHoming(float flStrength, float flDelay, float flRampUp, float flDuration, float flRampDown) -{ - m_flHomingStrength = flStrength; - m_flHomingDelay = flDelay; - m_flHomingRampUp = flRampUp; - m_flHomingDuration = flDuration; - m_flHomingRampDown = flRampDown; -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenadeHomer::StartRocketTrail(void) -{ - RocketTrail *pRocketTrail = RocketTrail::CreateRocketTrail(); - if(pRocketTrail) - { - pRocketTrail->m_SpawnRate = 80; - pRocketTrail->m_ParticleLifetime = 2; - if ( m_nRocketTrailType == HOMER_SMOKE_TRAIL_ALIEN ) - { - pRocketTrail->m_StartColor.Init(0.5, 0.0, 0.5); - } - else - { - pRocketTrail->m_StartColor.Init(0.75, 0.75, 0.75); - } - pRocketTrail->m_Opacity = 0.35f; - pRocketTrail->m_EndColor.Init(0.4,0.4,0.4); - pRocketTrail->m_StartSize = 8; - pRocketTrail->m_EndSize = 16; - pRocketTrail->m_SpawnRadius = 3; - pRocketTrail->m_MinSpeed = 2; - pRocketTrail->m_MaxSpeed = 10; - pRocketTrail->SetLifetime(120); - pRocketTrail->FollowEntity(this); - - m_hRocketTrail[0] = pRocketTrail; - } - /* - pRocketTrail = RocketTrail::CreateRocketTrail(); - if(pRocketTrail) - { - pRocketTrail->m_SpawnRate = 100; - pRocketTrail->m_ParticleLifetime = HOMER_TRAIL1_LIFE; - if ( m_nRocketTrailType == HOMER_SMOKE_TRAIL_ALIEN ) - { - pRocketTrail->m_StartColor.Init(0.0, 0.0, 0.5); - } - else - { - pRocketTrail->m_StartColor.Init(0.5, 0.5, 0.0); - } - pRocketTrail->m_EndColor.Init(0.5,0.5,0.5); - pRocketTrail->m_StartSize = 3; - pRocketTrail->m_EndSize = 6; - pRocketTrail->m_SpawnRadius = 1; - pRocketTrail->m_MinSpeed = 15; - pRocketTrail->m_MaxSpeed = 25; - pRocketTrail->SetLifetime(120); - pRocketTrail->FollowEntity(this); - - m_hRocketTrail[1] = pRocketTrail; - } - pRocketTrail = RocketTrail::CreateRocketTrail(); - if(pRocketTrail) - { - pRocketTrail->m_SpawnRate = 50; - pRocketTrail->m_ParticleLifetime = HOMER_TRAIL2_LIFE; - if ( m_nRocketTrailType == HOMER_SMOKE_TRAIL_ALIEN ) - { - pRocketTrail->m_StartColor.Init(0.1, 0.0, 0.1); - } - else - { - pRocketTrail->m_StartColor.Init(0.1, 0.1, 0.1); - } - pRocketTrail->m_EndColor.Init(0.5,0.5,0.5); - pRocketTrail->m_StartSize = 8; - pRocketTrail->m_EndSize = 20; - pRocketTrail->m_SpawnRadius = 1; - pRocketTrail->m_MinSpeed = 15; - pRocketTrail->m_MaxSpeed = 25; - pRocketTrail->SetLifetime(120); - pRocketTrail->FollowEntity(this); - - m_hRocketTrail[2] = pRocketTrail; - } - */ -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenadeHomer::UpdateRocketTrail(float fScale) -{ - if (m_hRocketTrail[0] == NULL) - { - StartRocketTrail(); - } - - if (m_hRocketTrail[0]) - { - m_hRocketTrail[0]->m_ParticleLifetime = fScale*HOMER_TRAIL0_LIFE; - } - if (m_hRocketTrail[1]) - { - m_hRocketTrail[1]->m_ParticleLifetime = fScale*HOMER_TRAIL1_LIFE; - } - - if (m_hRocketTrail[2]) - { - m_hRocketTrail[2]->m_ParticleLifetime = fScale*HOMER_TRAIL2_LIFE; - } -} - -void CGrenadeHomer::StopRocketTrail() -{ - // Stop emitting smoke - for (int i=0;i<3;i++) - { - if(m_hRocketTrail[i]) - { - m_hRocketTrail[i]->SetEmit(false); - UTIL_Remove( m_hRocketTrail[i] ); - m_hRocketTrail[i] = NULL; - } - } -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenadeHomer::Launch( CBaseEntity* pOwner, - CBaseEntity* pTarget, - const Vector& vInitVelocity, - float flHomingSpeed, - float flGravity, - int nRocketTrailType) -{ - SetOwnerEntity( pOwner ); - m_hTarget = pTarget; - SetAbsVelocity( vInitVelocity ); - m_flHomingSpeed = flHomingSpeed; - SetGravity( flGravity ); - m_nRocketTrailType = nRocketTrailType; - - // ---------------------------- - // Initialize homing parameters - // ---------------------------- - m_flHomingLaunchTime = gpGlobals->curtime; - - // ------------- - // Smoke trail. - // ------------- - if ( (m_nRocketTrailType == HOMER_SMOKE_TRAIL_ON) || (m_nRocketTrailType == HOMER_SMOKE_TRAIL_ALIEN) ) - { - StartRocketTrail(); - } - - SetUse( &CGrenadeHomer::DetonateUse ); - SetTouch( &CGrenadeHomer::GrenadeHomerTouch ); - SetThink( &CGrenadeHomer::AimThink ); - AimThink(); - SetNextThink( gpGlobals->curtime ); - - // Issue danger! - if ( pTarget ) - { - // Figure out how long it'll take for me to reach the target. - float flDist = ( pTarget->WorldSpaceCenter() - WorldSpaceCenter() ).Length(); - float flTime = MAX( 0.5, flDist / GetAbsVelocity().Length() ); - - CSoundEnt::InsertSound ( SOUND_DANGER, m_hTarget->GetAbsOrigin(), 300, flTime, pOwner ); - } -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenadeHomer::Event_Killed( const CTakeDamageInfo &info ) -{ - Detonate( ); -} - -void CGrenadeHomer::GrenadeHomerTouch( CBaseEntity *pOther ) -{ - Assert( pOther ); - - // Don't take damage from other homing grenades so can shoot in vollies - if (FClassnameIs( pOther, "grenade_homer") || !pOther->IsSolid() ) - { - return; - } - - // ---------------------------------- - // If I hit the sky, don't explode - // ---------------------------------- - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + GetAbsVelocity(), MASK_SOLID_BRUSHONLY, - this, COLLISION_GROUP_NONE, &tr); - - if (tr.surface.flags & SURF_SKY) - { - StopRocketTrail(); - UTIL_Remove( this ); - } - else - { - Detonate(); - } -} - -void CGrenadeHomer::Detonate(void) -{ - StopRocketTrail(); - - StopSound(entindex(), CHAN_BODY, STRING(m_sFlySound)); - - m_takedamage = DAMAGE_NO; - - CPASFilter filter( GetAbsOrigin() ); - - te->Explosion( filter, 0.0, - &GetAbsOrigin(), - g_sModelIndexFireball, - 2.0, - 15, - TE_EXPLFLAG_NONE, - m_DmgRadius, - m_flDamage ); - -// int magnitude = 1.0; -// int colorRamp = random->RandomInt( 128, 255 ); - - - if ( m_nRocketTrailType == HOMER_SMOKE_TRAIL_ALIEN ) - { - // Add a shockring - CBroadcastRecipientFilter filter3; - te->BeamRingPoint( filter3, 0, - GetAbsOrigin(), //origin - 16, //start radius - 1000, //end radius - m_spriteTexture, //texture - 0, //halo index - 0, //start frame - 2, //framerate - 0.3f, //life - 128, //width - 16, //spread - 0, //amplitude - 100, //r - 0, //g - 200, //b - 50, //a - 128 //speed - ); - - - // Add a shockring - CBroadcastRecipientFilter filter4; - te->BeamRingPoint( filter4, 0, - GetAbsOrigin(), //origin - 16, //start radius - 500, //end radius - m_spriteTexture, //texture - 0, //halo index - 0, //start frame - 2, //framerate - 0.3f, //life - 128, //width - 16, //spread - 0, //amplitude - 200, //r - 0, //g - 100, //b - 50, //a - 128 //speed - ); - - - - } - - - Vector vecForward = GetAbsVelocity(); - VectorNormalize(vecForward); - trace_t tr; - UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + 60*vecForward, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, & tr); - - UTIL_DecalTrace( &tr, "Scorch" ); - - UTIL_ScreenShake( GetAbsOrigin(), 25.0, 150.0, 1.0, 750, SHAKE_START ); - - RadiusDamage ( CTakeDamageInfo( this, GetOwnerEntity(), m_flDamage, DMG_BLAST ), GetAbsOrigin(), m_DmgRadius, CLASS_NONE, NULL ); - CPASAttenuationFilter filter2( this, "GrenadeHomer.StopSounds" ); - EmitSound( filter2, entindex(), "GrenadeHomer.StopSounds" ); - UTIL_Remove( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CGrenadeHomer::PlayFlySound(void) -{ - if (gpGlobals->curtime > m_flNextFlySoundTime) - { - CPASAttenuationFilter filter( this, 0.8 ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_BODY; - ep.m_pSoundName = STRING(m_sFlySound); - ep.m_flVolume = 1.0f; - ep.m_SoundLevel = SNDLVL_NORM; - ep.m_nPitch = 100; - - EmitSound( filter, entindex(), ep ); - - m_flNextFlySoundTime = gpGlobals->curtime + 1.0; - } -} - -//------------------------------------------------------------------------------ -// Purpose : Move toward targetmap -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenadeHomer::AimThink( void ) -{ - // Blow up the missile if we have an explicit detonate time that - // has been reached - if (m_flDetonateTime != 0 && - gpGlobals->curtime > m_flDetonateTime) - { - Detonate(); - return; - } - - PlayFlySound(); - - Vector vTargetPos = vec3_origin; - Vector vTargetDir; - float flCurHomingStrength = 0; - - // ------------------------------------------------ - // If I'm homing - // ------------------------------------------------ - if (m_hTarget != NULL) - { - vTargetPos = m_hTarget->EyePosition(); - vTargetDir = vTargetPos - GetAbsOrigin(); - VectorNormalize(vTargetDir); - - // -------------------------------------------------- - // If my target is far away do some primitive - // obstacle avoidance - // -------------------------------------------------- - if ((vTargetPos - GetAbsOrigin()).Length() > 200) - { - Vector vTravelDir = GetAbsVelocity(); - VectorNormalize(vTravelDir); - vTravelDir *= 50; - - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + vTravelDir, MASK_SHOT, m_hTarget, COLLISION_GROUP_NONE, &tr ); - if (tr.fraction != 1.0) - { - // Head off in normal - float dotPr = DotProduct(vTravelDir,tr.plane.normal); - Vector vBounce = -dotPr * tr.plane.normal; - vBounce.z = 0; - VectorNormalize(vBounce); - vTargetDir += vBounce; - VectorNormalize(vTargetDir); - // DEBUG TOOL - //NDebugOverlay::Line(GetOrigin(), GetOrigin()+vTravelDir, 255,0,0, true, 20); - //NDebugOverlay::Line(GetOrigin(), GetOrigin()+(12*tr.plane.normal), 0,0,255, true, 20); - //NDebugOverlay::Line(GetOrigin(), GetOrigin()+(vTargetDir), 0,255,0, true, 20); - } - } - - float flTargetSpeed = GetAbsVelocity().Length(); - float flHomingRampUpStartTime = m_flHomingLaunchTime + m_flHomingDelay; - float flHomingSustainStartTime = flHomingRampUpStartTime + m_flHomingRampUp; - float flHomingRampDownStartTime = flHomingSustainStartTime + m_flHomingDuration; - float flHomingEndHomingTime = flHomingRampDownStartTime + m_flHomingRampDown; - // --------- - // Delay - // --------- - if (gpGlobals->curtime < flHomingRampUpStartTime) - { - flCurHomingStrength = 0; - flTargetSpeed = 0; - } - // ---------- - // Ramp Up - // ---------- - else if (gpGlobals->curtime < flHomingSustainStartTime) - { - float flAge = gpGlobals->curtime - flHomingRampUpStartTime; - flCurHomingStrength = m_flHomingStrength * (flAge/m_flHomingRampUp); - flTargetSpeed = flCurHomingStrength * m_flHomingSpeed; - } - // ---------- - // Sustain - // ---------- - else if (gpGlobals->curtime < flHomingRampDownStartTime) - { - flCurHomingStrength = m_flHomingStrength; - flTargetSpeed = m_flHomingSpeed; - } - // ----------- - // Ramp Down - // ----------- - else if (gpGlobals->curtime < flHomingEndHomingTime) - { - float flAge = gpGlobals->curtime - flHomingRampDownStartTime; - flCurHomingStrength = m_flHomingStrength * (1-(flAge/m_flHomingRampDown)); - flTargetSpeed = m_flHomingSpeed; - } - // --------------- - // Set Homing - // --------------- - if (flCurHomingStrength > 0) - { - // ------------- - // Smoke trail. - // ------------- - if (m_nRocketTrailType == HOMER_SMOKE_TRAIL_ON_HOMING) - { - UpdateRocketTrail(flCurHomingStrength); - } - - // Extract speed and direction - Vector vCurDir = GetAbsVelocity(); - float flCurSpeed = VectorNormalize(vCurDir); - flTargetSpeed = MAX(flTargetSpeed, flCurSpeed); - - // Add in homing direction - Vector vecNewVelocity = GetAbsVelocity(); - float flTimeToUse = gpGlobals->frametime; - while (flTimeToUse > 0) - { - vecNewVelocity = (flCurHomingStrength * vTargetDir) + ((1 - flCurHomingStrength) * vCurDir); - flTimeToUse =- 0.1; - } - VectorNormalize(vecNewVelocity); - vecNewVelocity *= flTargetSpeed; - SetAbsVelocity( vecNewVelocity ); - } - } - - // ---------------------------------------------------------------------------------------- - // Add time-coherent noise to the current velocity - // ---------------------------------------------------------------------------------------- - Vector vecImpulse( 0, 0, 0 ); - if (m_flSpinMagnitude > 0) - { - vecImpulse.x += m_flSpinMagnitude*sin(m_flSpinSpeed * gpGlobals->curtime + m_flSpinOffset); - vecImpulse.y += m_flSpinMagnitude*cos(m_flSpinSpeed * gpGlobals->curtime + m_flSpinOffset); - vecImpulse.z -= m_flSpinMagnitude*cos(m_flSpinSpeed * gpGlobals->curtime + m_flSpinOffset); - } - - // Add in gravity - vecImpulse.z -= GetGravity() * sv_gravity.GetFloat() * gpGlobals->frametime; - ApplyAbsVelocityImpulse( vecImpulse ); - - QAngle angles; - VectorAngles( GetAbsVelocity(), angles ); - SetLocalAngles( angles ); - -#if 0 // BUBBLE - if( gpGlobals->curtime > m_flNextWarnTime ) - { - // Make a bubble of warning sound in front of me. - const float WARN_INTERVAL = 0.25f; - float flSpeed = GetAbsVelocity().Length(); - Vector vecWarnLocation; - - // warn a little bit ahead of us, please. - vecWarnLocation = GetAbsOrigin() + GetAbsVelocity() * 0.75; - - // Make a bubble of warning ahead of the missile. - CSoundEnt::InsertSound ( SOUND_DANGER, vecWarnLocation, flSpeed * WARN_INTERVAL, 0.5 ); - -#if 0 - Vector vecRight, vecForward; - - AngleVectors( GetAbsAngles(), &vecForward, &vecRight, NULL ); - - NDebugOverlay::Line( vecWarnLocation, vecWarnLocation + vecForward * flSpeed * WARN_INTERVAL * 0.5, 255,255,0, true, 10); - NDebugOverlay::Line( vecWarnLocation, vecWarnLocation - vecForward * flSpeed * WARN_INTERVAL * 0.5, 255,255,0, true, 10); - - NDebugOverlay::Line( vecWarnLocation, vecWarnLocation + vecRight * flSpeed * WARN_INTERVAL * 0.5, 255,255,0, true, 10); - NDebugOverlay::Line( vecWarnLocation, vecWarnLocation - vecRight * flSpeed * WARN_INTERVAL * 0.5, 255,255,0, true, 10); -#endif - m_flNextWarnTime = gpGlobals->curtime + WARN_INTERVAL; - } -#endif // BUBBLE - - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -int CGrenadeHomer::OnTakeDamage( const CTakeDamageInfo &info ) -{ - // Don't take damage from other homing grenades so can shoot in vollies - if (FClassnameIs( info.GetInflictor(), "grenade_homer")) - { - return 0; - } - return BaseClass::OnTakeDamage( info ); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -CGrenadeHomer::CGrenadeHomer(void) -{ - for (int i=0;i<3;i++) - { - m_hRocketTrail[i] = NULL; - } -} diff --git a/game/server/hl2/grenade_homer.h b/game/server/hl2/grenade_homer.h deleted file mode 100644 index 3b38f3546..000000000 --- a/game/server/hl2/grenade_homer.h +++ /dev/null @@ -1,83 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Projectile shot by city scanner -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef GRENADEHOMER_H -#define GRENADEHOMER_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "basegrenade_shared.h" -#include "weapon_rpg.h" - -enum HomerRocketTrail_t -{ - HOMER_SMOKE_TRAIL_OFF, // No smoke trail - HOMER_SMOKE_TRAIL_ON, // Smoke trail always on - HOMER_SMOKE_TRAIL_ON_HOMING, // Smoke trail on when homing turned on - HOMER_SMOKE_TRAIL_ALIEN, // Alien colors on smoke trail -}; - -class CGrenadeHomer : public CBaseGrenade -{ -public: - DECLARE_CLASS( CGrenadeHomer, CBaseGrenade ); - - static CGrenadeHomer* CreateGrenadeHomer( string_t nModelName, string_t sFlySound, const Vector &vecOrigin, const QAngle &vecAngles, edict_t *pentOwner ); - - virtual void Precache( void ); - void Spawn( void ); - void Launch( CBaseEntity *pOwner, CBaseEntity *pTarget, const Vector &vInitVelocity, float m_flHomingSpeed, float fFallSpeed, int nRocketTrailType); - void SetSpin(float flSpinMagnitude, float flSpinSpeed); - void SetHoming(float flStrength, float flDelay, float flRampUp, float flDuration, float flRampDown); - - CHandle m_hRocketTrail[3]; - -private: - string_t m_sFlySound; - float m_flNextFlySoundTime; - - // Input Parameters - float m_flHomingStrength; - float m_flHomingDelay; // How long before homing starts - float m_flHomingRampUp; // How long it take to reach full strength - float m_flHomingDuration; // How long does homing last - float m_flHomingRampDown; // How long to reach no homing again - float m_flHomingSpeed; - float m_flSpinMagnitude; - float m_flSpinSpeed; - int m_nRocketTrailType; - int m_spriteTexture; - - // In flight data - float m_flHomingLaunchTime; - float m_flHomingStartTime; - float m_flHomingEndTime; - float m_flSpinOffset; // For randomization - - EHANDLE m_hTarget; - - void AimThink( void ); - void StartRocketTrail(void); - void UpdateRocketTrail(float fScale); - void StopRocketTrail(void); - void PlayFlySound( void ); - void GrenadeHomerTouch( CBaseEntity *pOther ); - void Event_Killed( const CTakeDamageInfo &info ); - int OnTakeDamage( const CTakeDamageInfo &info ); - -public: - void EXPORT Detonate(void); - CGrenadeHomer(void); - - DECLARE_DATADESC(); -}; - -#endif //GRENADEHOMER_H diff --git a/game/server/hl2/grenade_molotov.cpp b/game/server/hl2/grenade_molotov.cpp deleted file mode 100644 index b003a8efd..000000000 --- a/game/server/hl2/grenade_molotov.cpp +++ /dev/null @@ -1,245 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Flaming bottle thrown from the hand -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "player.h" -#include "ammodef.h" -#include "gamerules.h" -#include "grenade_molotov.h" -#include "weapon_brickbat.h" -#include "soundent.h" -#include "decals.h" -#include "fire.h" -#include "shake.h" -#include "ndebugoverlay.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern short g_sModelIndexFireball; - -extern ConVar sk_plr_dmg_molotov; -extern ConVar sk_npc_dmg_molotov; -ConVar sk_molotov_radius ( "sk_molotov_radius","0"); - -#define MOLOTOV_EXPLOSION_VOLUME 1024 - -BEGIN_DATADESC( CGrenade_Molotov ) - - DEFINE_FIELD( m_pFireTrail, FIELD_CLASSPTR ), - - // Function Pointers - DEFINE_ENTITYFUNC( MolotovTouch ), - DEFINE_THINKFUNC( MolotovThink ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( grenade_molotov, CGrenade_Molotov ); - -void CGrenade_Molotov::Spawn( void ) -{ - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); - SetSolid( SOLID_BBOX ); - SetCollisionGroup( COLLISION_GROUP_PROJECTILE ); - RemoveEffects( EF_NOINTERP ); - - SetModel( "models/weapons/w_molotov.mdl"); - - UTIL_SetSize(this, Vector( -6, -6, -2), Vector(6, 6, 2)); - - SetTouch( &CGrenade_Molotov::MolotovTouch ); - SetThink( &CGrenade_Molotov::MolotovThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - m_flDamage = sk_plr_dmg_molotov.GetFloat(); - m_DmgRadius = sk_molotov_radius.GetFloat(); - - m_takedamage = DAMAGE_YES; - m_iHealth = 1; - - SetGravity( 1.0 ); - SetFriction( 0.8 ); // Give a little bounce so can flatten - SetSequence( 1 ); - - m_pFireTrail = SmokeTrail::CreateSmokeTrail(); - - if( m_pFireTrail ) - { - m_pFireTrail->m_SpawnRate = 48; - m_pFireTrail->m_ParticleLifetime = 1.0f; - - m_pFireTrail->m_StartColor.Init( 0.2f, 0.2f, 0.2f ); - m_pFireTrail->m_EndColor.Init( 0.0, 0.0, 0.0 ); - - m_pFireTrail->m_StartSize = 8; - m_pFireTrail->m_EndSize = 32; - m_pFireTrail->m_SpawnRadius = 4; - m_pFireTrail->m_MinSpeed = 8; - m_pFireTrail->m_MaxSpeed = 16; - m_pFireTrail->m_Opacity = 0.25f; - - m_pFireTrail->SetLifetime( 20.0f ); - m_pFireTrail->FollowEntity( this, "0" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CGrenade_Molotov::MolotovTouch( CBaseEntity *pOther ) -{ - Detonate(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CGrenade_Molotov::Detonate( void ) -{ - SetModelName( NULL_STRING ); //invisible - AddSolidFlags( FSOLID_NOT_SOLID ); // intangible - - m_takedamage = DAMAGE_NO; - - trace_t trace; - UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + Vector ( 0, 0, -128 ), MASK_SOLID_BRUSHONLY, - this, COLLISION_GROUP_NONE, &trace); - - // Pull out of the wall a bit - if ( trace.fraction != 1.0 ) - { - SetLocalOrigin( trace.endpos + (trace.plane.normal * (m_flDamage - 24) * 0.6) ); - } - - int contents = UTIL_PointContents ( GetAbsOrigin() ); - - if ( (contents & MASK_WATER) ) - { - UTIL_Remove( this ); - return; - } - - EmitSound( "Grenade_Molotov.Detonate"); - -// Start some fires - int i; - QAngle vecTraceAngles; - Vector vecTraceDir; - trace_t firetrace; - - for( i = 0 ; i < 16 ; i++ ) - { - // build a little ray - vecTraceAngles[PITCH] = random->RandomFloat(45, 135); - vecTraceAngles[YAW] = random->RandomFloat(0, 360); - vecTraceAngles[ROLL] = 0.0f; - - AngleVectors( vecTraceAngles, &vecTraceDir ); - - Vector vecStart, vecEnd; - - vecStart = GetAbsOrigin() + ( trace.plane.normal * 128 ); - vecEnd = vecStart + vecTraceDir * 512; - - UTIL_TraceLine( vecStart, vecEnd, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &firetrace ); - - Vector ofsDir = ( firetrace.endpos - GetAbsOrigin() ); - float offset = VectorNormalize( ofsDir ); - - if ( offset > 128 ) - offset = 128; - - //Get our scale based on distance - float scale = 0.1f + ( 0.75f * ( 1.0f - ( offset / 128.0f ) ) ); - float growth = 0.1f + ( 0.75f * ( offset / 128.0f ) ); - - if( firetrace.fraction != 1.0 ) - { - FireSystem_StartFire( firetrace.endpos, scale, growth, 30.0f, (SF_FIRE_START_ON|SF_FIRE_SMOKELESS|SF_FIRE_NO_GLOW), (CBaseEntity*) this, FIRE_NATURAL ); - } - } -// End Start some fires - - CPASFilter filter2( trace.endpos ); - - te->Explosion( filter2, 0.0, - &trace.endpos, - g_sModelIndexFireball, - 2.0, - 15, - TE_EXPLFLAG_NOPARTICLES, - m_DmgRadius, - m_flDamage ); - - CBaseEntity *pOwner; - pOwner = GetOwnerEntity(); - SetOwnerEntity( NULL ); // can't traceline attack owner if this is set - - UTIL_DecalTrace( &trace, "Scorch" ); - - UTIL_ScreenShake( GetAbsOrigin(), 25.0, 150.0, 1.0, 750, SHAKE_START ); - CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin(), BASEGRENADE_EXPLOSION_VOLUME, 3.0 ); - - RadiusDamage( CTakeDamageInfo( this, pOwner, m_flDamage, DMG_BLAST ), GetAbsOrigin(), m_DmgRadius, CLASS_NONE, NULL ); - - AddEffects( EF_NODRAW ); - SetAbsVelocity( vec3_origin ); - SetNextThink( gpGlobals->curtime + 0.2 ); - - if ( m_pFireTrail ) - { - UTIL_Remove( m_pFireTrail ); - } - - UTIL_Remove(this); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenade_Molotov::MolotovThink( void ) -{ - // See if I can lose my owner (has dropper moved out of way?) - // Want do this so owner can throw the brickbat - if (GetOwnerEntity()) - { - trace_t tr; - Vector vUpABit = GetAbsOrigin(); - vUpABit.z += 5.0; - - CBaseEntity* saveOwner = GetOwnerEntity(); - SetOwnerEntity( NULL ); - UTIL_TraceEntity( this, GetAbsOrigin(), vUpABit, MASK_SOLID, &tr ); - if ( tr.startsolid || tr.fraction != 1.0 ) - { - SetOwnerEntity( saveOwner ); - } - } - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -void CGrenade_Molotov::Precache( void ) -{ - BaseClass::Precache(); - - PrecacheModel("models/weapons/w_bb_bottle.mdl"); - - UTIL_PrecacheOther("_firesmoke"); - - PrecacheScriptSound( "Grenade_Molotov.Detonate" ); -} - diff --git a/game/server/hl2/grenade_molotov.h b/game/server/hl2/grenade_molotov.h deleted file mode 100644 index 743160d67..000000000 --- a/game/server/hl2/grenade_molotov.h +++ /dev/null @@ -1,38 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Molotov grenades -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef GRENADEMOLOTOV_H -#define GRENADEMOLOTOV_H - -#include "basegrenade_shared.h" -#include "smoke_trail.h" - -class CGrenade_Molotov : public CBaseGrenade -{ -public: - DECLARE_CLASS( CGrenade_Molotov, CBaseGrenade ); - - virtual void Spawn( void ); - virtual void Precache( void ); - virtual void Detonate( void ); - void MolotovTouch( CBaseEntity *pOther ); - void MolotovThink( void ); - -protected: - - SmokeTrail *m_pFireTrail; - - DECLARE_DATADESC(); -}; - -#endif //GRENADEMOLOTOV_H diff --git a/game/server/hl2/grenade_pathfollower.cpp b/game/server/hl2/grenade_pathfollower.cpp deleted file mode 100644 index bc4eeccf4..000000000 --- a/game/server/hl2/grenade_pathfollower.cpp +++ /dev/null @@ -1,330 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: This is the brickbat weapon -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "grenade_pathfollower.h" -#include "soundent.h" -#include "decals.h" -#include "shake.h" -#include "smoke_trail.h" -#include "entitylist.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define GRENADE_PF_TURN_RATE 30 -#define GRENADE_PF_TOLERANCE 300 -#define GRENADE_PF_MODEL "models/Weapons/w_missile.mdl" - -extern short g_sModelIndexFireball; // (in combatweapon.cpp) holds the index for the smoke cloud - -ConVar sk_dmg_pathfollower_grenade ( "sk_dmg_pathfollower_grenade","0"); -ConVar sk_pathfollower_grenade_radius ( "sk_pathfollower_grenade_radius","0"); - -BEGIN_DATADESC( CGrenadePathfollower ) - - DEFINE_FIELD( m_pPathTarget, FIELD_CLASSPTR ), - DEFINE_FIELD( m_flFlySpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_sFlySound, FIELD_SOUNDNAME ), - DEFINE_FIELD( m_flNextFlySoundTime, FIELD_TIME), - DEFINE_FIELD( m_hRocketTrail, FIELD_EHANDLE), - - DEFINE_THINKFUNC( AimThink ), - - // Function pointers - DEFINE_ENTITYFUNC( GrenadeTouch ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( grenade_pathfollower, CGrenadePathfollower ); - -void CGrenadePathfollower::Precache() -{ - BaseClass::Precache(); - - PrecacheScriptSound( "GrenadePathfollower.StopSounds" ); -} - -void CGrenadePathfollower::Spawn( void ) -{ - Precache( ); - - // ------------------------- - // Inert when first spawned - // ------------------------- - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_SOLID ); - - SetMoveType( MOVETYPE_NONE ); - AddFlag( FL_OBJECT ); // So can be shot down - AddEffects( EF_NODRAW ); - - UTIL_SetSize(this, Vector(0, 0, 0), Vector(0, 0, 0)); - - m_flDamage = sk_dmg_pathfollower_grenade.GetFloat(); - m_DmgRadius = sk_pathfollower_grenade_radius.GetFloat(); - m_takedamage = DAMAGE_YES; - m_iHealth = 200; - - SetGravity( 0.00001 ); - SetFriction( 0.8 ); - SetSequence( 1 ); -} - -void CGrenadePathfollower::Event_Killed( const CTakeDamageInfo &info ) -{ - Detonate( ); -} - -void CGrenadePathfollower::GrenadeTouch( CBaseEntity *pOther ) -{ - // ---------------------------------- - // If I hit the sky, don't explode - // ---------------------------------- - trace_t tr; - UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + GetAbsVelocity(), MASK_SOLID_BRUSHONLY, - this, COLLISION_GROUP_NONE, &tr); - - if (tr.surface.flags & SURF_SKY) - { - if(m_hRocketTrail) - { - UTIL_Remove(m_hRocketTrail); - m_hRocketTrail = NULL; - } - UTIL_Remove( this ); - } - Detonate(); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenadePathfollower::Detonate(void) -{ - StopSound(entindex(), CHAN_BODY, STRING(m_sFlySound)); - - m_takedamage = DAMAGE_NO; - - if(m_hRocketTrail) - { - UTIL_Remove(m_hRocketTrail); - m_hRocketTrail = NULL; - } - - CPASFilter filter( GetAbsOrigin() ); - - te->Explosion( filter, 0.0, - &GetAbsOrigin(), - g_sModelIndexFireball, - 0.5, - 15, - TE_EXPLFLAG_NONE, - m_DmgRadius, - m_flDamage ); - - Vector vecForward = GetAbsVelocity(); - VectorNormalize(vecForward); - trace_t tr; - UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + 60*vecForward, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, & tr); - - UTIL_DecalTrace( &tr, "Scorch" ); - - UTIL_ScreenShake( GetAbsOrigin(), 25.0, 150.0, 1.0, 750, SHAKE_START ); - CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin(), 400, 0.2 ); - - RadiusDamage ( CTakeDamageInfo( this, GetThrower(), m_flDamage, DMG_BLAST ), GetAbsOrigin(), m_DmgRadius, CLASS_NONE, NULL ); - CPASAttenuationFilter filter2( this, "GrenadePathfollower.StopSounds" ); - EmitSound( filter2, entindex(), "GrenadePathfollower.StopSounds" ); - UTIL_Remove( this ); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenadePathfollower::Launch( float flLaunchSpeed, string_t sPathCornerName) -{ - m_pPathTarget = gEntList.FindEntityByName( NULL, sPathCornerName ); - if (m_pPathTarget) - { - m_flFlySpeed = flLaunchSpeed; - Vector vTargetDir = (m_pPathTarget->GetAbsOrigin() - GetAbsOrigin()); - VectorNormalize(vTargetDir); - SetAbsVelocity( m_flFlySpeed * vTargetDir ); - QAngle angles; - VectorAngles( GetAbsVelocity(), angles ); - SetLocalAngles( angles ); - } - else - { - Warning( "ERROR: Grenade_Pathfollower (%s) with no pathcorner!\n",GetDebugName()); - return; - } - - // Make this thing come to life - RemoveSolidFlags( FSOLID_NOT_SOLID ); - SetMoveType( MOVETYPE_FLYGRAVITY ); - RemoveEffects( EF_NODRAW ); - - SetUse( &CGrenadePathfollower::DetonateUse ); - SetTouch( &CGrenadePathfollower::GrenadeTouch ); - SetThink( &CGrenadePathfollower::AimThink ); - - SetNextThink( gpGlobals->curtime + 0.1f ); - - // Make the trail - m_hRocketTrail = RocketTrail::CreateRocketTrail(); - - if ( m_hRocketTrail ) - { - m_hRocketTrail->m_Opacity = 0.2f; - m_hRocketTrail->m_SpawnRate = 100; - m_hRocketTrail->m_ParticleLifetime = 0.5f; - m_hRocketTrail->m_StartColor.Init( 0.65f, 0.65f , 0.65f ); - m_hRocketTrail->m_EndColor.Init( 0.0, 0.0, 0.0 ); - m_hRocketTrail->m_StartSize = 8; - m_hRocketTrail->m_EndSize = 16; - m_hRocketTrail->m_SpawnRadius = 4; - m_hRocketTrail->m_MinSpeed = 2; - m_hRocketTrail->m_MaxSpeed = 16; - - m_hRocketTrail->SetLifetime( 999 ); - m_hRocketTrail->FollowEntity( this, "0" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CGrenadePathfollower::PlayFlySound(void) -{ - if (gpGlobals->curtime > m_flNextFlySoundTime) - { - CPASAttenuationFilter filter( this, 0.8 ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_BODY; - ep.m_pSoundName = STRING(m_sFlySound); - ep.m_flVolume = 1.0f; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - m_flNextFlySoundTime = gpGlobals->curtime + 1.0; - } -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CGrenadePathfollower::AimThink( void ) -{ - PlayFlySound(); - - // --------------------------------------------------- - // Check if it's time to skip to the next path corner - // --------------------------------------------------- - if (m_pPathTarget) - { - float flLength = (GetAbsOrigin() - m_pPathTarget->GetAbsOrigin()).Length(); - if (flLength < GRENADE_PF_TOLERANCE) - { - m_pPathTarget = gEntList.FindEntityByName( NULL, m_pPathTarget->m_target ); - if (!m_pPathTarget) - { - SetGravity( 1.0 ); - } - } - } - - // -------------------------------------------------- - // If I have a pathcorner, aim towards it - // -------------------------------------------------- - if (m_pPathTarget) - { - Vector vTargetDir = (m_pPathTarget->GetAbsOrigin() - GetAbsOrigin()); - VectorNormalize(vTargetDir); - - Vector vecNewVelocity = GetAbsVelocity(); - VectorNormalize(vecNewVelocity); - - float flTimeToUse = gpGlobals->frametime; - while (flTimeToUse > 0) - { - vecNewVelocity += vTargetDir; - flTimeToUse =- 0.1; - } - vecNewVelocity *= m_flFlySpeed; - SetAbsVelocity( vecNewVelocity ); - } - - QAngle angles; - VectorAngles( GetAbsVelocity(), angles ); - SetLocalAngles( angles ); - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -Class_T CGrenadePathfollower::Classify( void) -{ - return CLASS_MISSILE; -}; - -CGrenadePathfollower::CGrenadePathfollower(void) -{ - m_hRocketTrail = NULL; -} - -//------------------------------------------------------------------------------ -// Purpose : In case somehow we get removed w/o detonating, make sure -// we stop making sounds -// Input : -// Output : -//------------------------------------------------------------------------------ -CGrenadePathfollower::~CGrenadePathfollower(void) -{ - StopSound(entindex(), CHAN_BODY, STRING(m_sFlySound)); -} - -///------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -CGrenadePathfollower* CGrenadePathfollower::CreateGrenadePathfollower( string_t sModelName, string_t sFlySound, const Vector &vecOrigin, const QAngle &vecAngles, edict_t *pentOwner ) -{ - CGrenadePathfollower *pGrenade = (CGrenadePathfollower*)CreateEntityByName( "grenade_pathfollower" ); - if ( !pGrenade ) - { - Warning( "NULL Ent in CGrenadePathfollower!\n" ); - return NULL; - } - - if ( pGrenade->edict() ) - { - pGrenade->m_sFlySound = sFlySound; - pGrenade->SetOwnerEntity( Instance( pentOwner ) ); - pGrenade->SetLocalOrigin( vecOrigin ); - pGrenade->SetLocalAngles( vecAngles ); - pGrenade->SetModel( STRING(sModelName) ); - pGrenade->Spawn(); - } - return pGrenade; -} diff --git a/game/server/hl2/grenade_pathfollower.h b/game/server/hl2/grenade_pathfollower.h deleted file mode 100644 index 0cce277d1..000000000 --- a/game/server/hl2/grenade_pathfollower.h +++ /dev/null @@ -1,52 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Projectile shot by wasteland scanner -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef GRENADEPATHFOLLOWER_H -#define GRENADEPATHFOLLOWER_H - -#include "basegrenade_shared.h" - -class RocketTrail; - -class CGrenadePathfollower : public CBaseGrenade -{ -public: - DECLARE_CLASS( CGrenadePathfollower, CBaseGrenade ); - - static CGrenadePathfollower* CreateGrenadePathfollower( string_t sModelName, string_t sFlySound, const Vector &vecOrigin, const QAngle &vecAngles, edict_t *pentOwner ); - - CHandle m_hRocketTrail; - CBaseEntity* m_pPathTarget; // path corner we are heading towards - float m_flFlySpeed; - string_t m_sFlySound; - float m_flNextFlySoundTime; - - Class_T Classify( void); - void Spawn( void ); - void AimThink( void ); - void GrenadeTouch( CBaseEntity *pOther ); - void Event_Killed( const CTakeDamageInfo &info ); - void Launch( float flLaunchSpeed, string_t sPathCornerName); - void PlayFlySound(void); - - void EXPORT Detonate(void); - - CGrenadePathfollower(void); - ~CGrenadePathfollower(void); - - virtual void Precache(); - - DECLARE_DATADESC(); -}; - -#endif //GRENADEPATHFOLLOWER_H diff --git a/game/server/hl2/grenade_satchel.cpp b/game/server/hl2/grenade_satchel.cpp deleted file mode 100644 index 140d1cacc..000000000 --- a/game/server/hl2/grenade_satchel.cpp +++ /dev/null @@ -1,365 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include "cbase.h" -#include "grenade_satchel.h" -#include "player.h" -#include "soundenvelope.h" -#include "engine/IEngineSound.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar sk_plr_dmg_satchel ( "sk_plr_dmg_satchel","0"); -ConVar sk_npc_dmg_satchel ( "sk_npc_dmg_satchel","0"); -ConVar sk_satchel_radius ( "sk_satchel_radius","0"); - -BEGIN_DATADESC( CSatchelCharge ) - - DEFINE_SOUNDPATCH( m_soundSlide ), - - DEFINE_FIELD( m_flSlideVolume, FIELD_FLOAT ), - DEFINE_FIELD( m_flNextBounceSoundTime, FIELD_TIME ), - DEFINE_FIELD( m_bInAir, FIELD_BOOLEAN ), - DEFINE_FIELD( m_vLastPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_pMyWeaponSLAM, FIELD_CLASSPTR ), - DEFINE_FIELD( m_bIsAttached, FIELD_BOOLEAN ), - - // Function Pointers - DEFINE_ENTITYFUNC( SatchelTouch ), - DEFINE_THINKFUNC( SatchelThink ), - DEFINE_USEFUNC( SatchelUse ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( npc_satchel, CSatchelCharge ); - -//========================================================= -// Deactivate - do whatever it is we do to an orphaned -// satchel when we don't want it in the world anymore. -//========================================================= -void CSatchelCharge::Deactivate( void ) -{ - AddSolidFlags( FSOLID_NOT_SOLID ); - UTIL_Remove( this ); -} - - -void CSatchelCharge::Spawn( void ) -{ - Precache( ); - // motor - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); - SetSolid( SOLID_BBOX ); - SetCollisionGroup( COLLISION_GROUP_PROJECTILE ); - SetModel( "models/Weapons/w_slam.mdl" ); - - UTIL_SetSize(this, Vector( -6, -6, -2), Vector(6, 6, 2)); - - SetTouch( &CSatchelCharge::SatchelTouch ); - SetUse( &CSatchelCharge::SatchelUse ); - SetThink( &CSatchelCharge::SatchelThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - m_flDamage = sk_plr_dmg_satchel.GetFloat(); - m_DmgRadius = sk_satchel_radius.GetFloat(); - m_takedamage = DAMAGE_YES; - m_iHealth = 1; - - SetGravity( UTIL_ScaleForGravity( 560 ) ); // slightly lower gravity - SetFriction( 1.0 ); - SetSequence( 1 ); - - m_bIsAttached = false; - m_bInAir = true; - m_flSlideVolume = -1.0; - m_flNextBounceSoundTime = 0; - - m_vLastPosition = vec3_origin; - - InitSlideSound(); -} - -//----------------------------------------------------------------------------- - -void CSatchelCharge::InitSlideSound(void) -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - CPASAttenuationFilter filter( this ); - m_soundSlide = controller.SoundCreate( filter, entindex(), CHAN_STATIC, "SatchelCharge.Slide", ATTN_NORM ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CSatchelCharge::KillSlideSound(void) -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.CommandClear( m_soundSlide ); - controller.SoundFadeOut( m_soundSlide, 0.0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CSatchelCharge::SatchelUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - KillSlideSound(); - SetThink( &CBaseGrenade::Detonate ); - SetNextThink( gpGlobals->curtime ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CSatchelCharge::SatchelTouch( CBaseEntity *pOther ) -{ - Assert( pOther ); - if ( !pOther->IsSolid() ) - return; - - // If successfully thrown and touching the - // NPC that released this grenade, pick it up - if ( pOther == GetThrower() && GetOwnerEntity() == NULL ) - { - CBasePlayer *pPlayer = ToBasePlayer( m_pMyWeaponSLAM->GetOwner() ); - if (pPlayer) - { - // Give the player ammo - pPlayer->GiveAmmo(1, m_pMyWeaponSLAM->m_iSecondaryAmmoType); - - CPASAttenuationFilter filter( pPlayer, "SatchelCharge.Pickup" ); - EmitSound( filter, pPlayer->entindex(), "SatchelCharge.Pickup" ); - - m_bIsLive = false; - - // Take weapon out of detonate mode if necessary - if (!m_pMyWeaponSLAM->AnyUndetonatedCharges()) - { - m_pMyWeaponSLAM->m_bDetonatorArmed = false; - m_pMyWeaponSLAM->m_bNeedDetonatorHolster = true; - - // Put detonator away right away - m_pMyWeaponSLAM->SetWeaponIdleTime( gpGlobals->curtime ); - } - - // Kill any sliding sound - KillSlideSound(); - - // Remove satchel charge from world - UTIL_Remove( this ); - return; - } - - } - - StudioFrameAdvance( ); - - // Is it attached to a wall? - if (m_bIsAttached) - { - return; - } - - SetGravity( 1 );// normal gravity now - - // HACKHACK - On ground isn't always set, so look for ground underneath - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector(0,0,10), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction < 1.0 ) - { - // add a bit of static friction - SetAbsVelocity( GetAbsVelocity() * 0.85 ); - SetLocalAngularVelocity( GetLocalAngularVelocity() * 0.8 ); - } - - UpdateSlideSound(); - - if (m_bInAir) - { - BounceSound(); - m_bInAir = false; - } - -} - -void CSatchelCharge::UpdateSlideSound( void ) -{ - if (!m_soundSlide) - { - return; - } - - float volume = GetAbsVelocity().Length2D()/1000; - if (volume < 0.01 && m_soundSlide) - { - KillSlideSound(); - return; - } - // HACKHACK - On ground isn't always set, so look for ground underneath - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector(0,0,10), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - - - if ( tr.fraction < 1.0 ) - { - if (m_flSlideVolume == -1.0) - { - controller.CommandClear( m_soundSlide ); - controller.Play( m_soundSlide, 1.0, 100 ); - m_flSlideVolume = 1.0; - } - else - { - float volume = GetAbsVelocity().Length()/1000; - if ( volume < m_flSlideVolume ) - { - m_flSlideVolume = volume; - controller.CommandClear( m_soundSlide ); - controller.SoundChangeVolume( m_soundSlide, volume, 0.1 ); - } - } - } - else - { - controller.CommandClear( m_soundSlide ); - controller.SoundChangeVolume( m_soundSlide, 0.0, 0.01 ); - m_flSlideVolume = -1.0; - m_bInAir = true; - return; - } -} - -void CSatchelCharge::SatchelThink( void ) -{ - // If attached resize so player can pick up off wall - if (m_bIsAttached) - { - UTIL_SetSize(this, Vector( -2, -2, -6), Vector(2, 2, 6)); - } - - UpdateSlideSound(); - - // See if I can lose my owner (has dropper moved out of way?) - // Want do this so owner can shoot the satchel charge - if (GetOwnerEntity()) - { - trace_t tr; - Vector vUpABit = GetAbsOrigin(); - vUpABit.z += 5.0; - - CBaseEntity* saveOwner = GetOwnerEntity(); - SetOwnerEntity( NULL ); - UTIL_TraceEntity( this, GetAbsOrigin(), vUpABit, MASK_SOLID, &tr ); - if ( tr.startsolid || tr.fraction != 1.0 ) - { - SetOwnerEntity( saveOwner ); - } - } - - // Bounce movement code gets this think stuck occasionally so check if I've - // succeeded in moving, otherwise kill my motions. - else if ((GetAbsOrigin() - m_vLastPosition).LengthSqr()<1) - { - SetAbsVelocity( vec3_origin ); - - QAngle angVel = GetLocalAngularVelocity(); - angVel.y = 0; - SetLocalAngularVelocity( angVel ); - - // Kill any remaining sound - KillSlideSound(); - - // Clear think function - SetThink(NULL); - return; - } - m_vLastPosition= GetAbsOrigin(); - - StudioFrameAdvance( ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - if (!IsInWorld()) - { - // Kill any remaining sound - KillSlideSound(); - - UTIL_Remove( this ); - return; - } - - // Is it attached to a wall? - if (m_bIsAttached) - { - return; - } - - Vector vecNewVel = GetAbsVelocity(); - if (GetWaterLevel() == 3) - { - SetMoveType( MOVETYPE_FLY ); - vecNewVel *= 0.8; - vecNewVel.z += 8; - SetLocalAngularVelocity( GetLocalAngularVelocity() * 0.9 ); - } - else if (GetWaterLevel() == 0) - { - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); - } - else - { - vecNewVel.z -= 8; - } - SetAbsVelocity( vecNewVel ); -} - -void CSatchelCharge::Precache( void ) -{ - PrecacheModel("models/Weapons/w_slam.mdl"); - - PrecacheScriptSound( "SatchelCharge.Pickup" ); - PrecacheScriptSound( "SatchelCharge.Bounce" ); - - PrecacheScriptSound( "SatchelCharge.Slide" ); -} - -void CSatchelCharge::BounceSound( void ) -{ - if (gpGlobals->curtime > m_flNextBounceSoundTime) - { - EmitSound( "SatchelCharge.Bounce" ); - - m_flNextBounceSoundTime = gpGlobals->curtime + 0.1; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Constructor -// Input : -// Output : -//----------------------------------------------------------------------------- -CSatchelCharge::CSatchelCharge(void) -{ - m_vLastPosition.Init(); - m_pMyWeaponSLAM = NULL; -} - -CSatchelCharge::~CSatchelCharge(void) -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundDestroy( m_soundSlide ); -} diff --git a/game/server/hl2/grenade_satchel.h b/game/server/hl2/grenade_satchel.h deleted file mode 100644 index 57f530806..000000000 --- a/game/server/hl2/grenade_satchel.h +++ /dev/null @@ -1,57 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Satchel Charge -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef SATCHEL_H -#define SATCHEL_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "basegrenade_shared.h" -#include "hl2mp/weapon_slam.h" - -class CSoundPatch; - -class CSatchelCharge : public CBaseGrenade -{ -public: - DECLARE_CLASS( CSatchelCharge, CBaseGrenade ); - - void Spawn( void ); - void Precache( void ); - void BounceSound( void ); - void UpdateSlideSound( void ); - void KillSlideSound(void); - void SatchelTouch( CBaseEntity *pOther ); - void SatchelThink( void ); - void SatchelUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - CSoundPatch* m_soundSlide; - float m_flSlideVolume; - float m_flNextBounceSoundTime; - bool m_bInAir; - Vector m_vLastPosition; - -public: - CWeapon_SLAM* m_pMyWeaponSLAM; // Who shot me.. - bool m_bIsAttached; - void Deactivate( void ); - - CSatchelCharge(); - ~CSatchelCharge(); - - DECLARE_DATADESC(); - -private: - void InitSlideSound(void); -}; - -#endif //SATCHEL_H diff --git a/game/server/hl2/grenade_spit.cpp b/game/server/hl2/grenade_spit.cpp deleted file mode 100644 index c292d1cdc..000000000 --- a/game/server/hl2/grenade_spit.cpp +++ /dev/null @@ -1,284 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "grenade_spit.h" -#include "soundent.h" -#include "decals.h" -#include "smoke_trail.h" -#include "hl2_shareddefs.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "particle_parse.h" -#include "particle_system.h" -#include "soundenvelope.h" -#include "ai_utils.h" -#include "te_effect_dispatch.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar sk_antlion_worker_spit_grenade_dmg ( "sk_antlion_worker_spit_grenade_dmg", "20", FCVAR_NONE, "Total damage done by an individual antlion worker loogie."); -ConVar sk_antlion_worker_spit_grenade_radius ( "sk_antlion_worker_spit_grenade_radius","40", FCVAR_NONE, "Radius of effect for an antlion worker spit grenade."); -ConVar sk_antlion_worker_spit_grenade_poison_ratio ( "sk_antlion_worker_spit_grenade_poison_ratio","0.3", FCVAR_NONE, "Percentage of an antlion worker's spit damage done as poison (which regenerates)"); - -LINK_ENTITY_TO_CLASS( grenade_spit, CGrenadeSpit ); - -BEGIN_DATADESC( CGrenadeSpit ) - - DEFINE_FIELD( m_bPlaySound, FIELD_BOOLEAN ), - - // Function pointers - DEFINE_ENTITYFUNC( GrenadeSpitTouch ), - -END_DATADESC() - -CGrenadeSpit::CGrenadeSpit( void ) : m_pHissSound( NULL ), m_bPlaySound( true ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGrenadeSpit::Spawn( void ) -{ - Precache( ); - SetSolid( SOLID_BBOX ); - SetMoveType( MOVETYPE_FLYGRAVITY ); - SetSolidFlags( FSOLID_NOT_STANDABLE ); - - SetModel( "models/spitball_large.mdl" ); - UTIL_SetSize( this, vec3_origin, vec3_origin ); - - SetUse( &CBaseGrenade::DetonateUse ); - SetTouch( &CGrenadeSpit::GrenadeSpitTouch ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - m_flDamage = sk_antlion_worker_spit_grenade_dmg.GetFloat(); - m_DmgRadius = sk_antlion_worker_spit_grenade_radius.GetFloat(); - m_takedamage = DAMAGE_NO; - m_iHealth = 1; - - SetGravity( UTIL_ScaleForGravity( SPIT_GRAVITY ) ); - SetFriction( 0.8f ); - - SetCollisionGroup( HL2COLLISION_GROUP_SPIT ); - - AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); - - // We're self-illuminating, so we don't take or give shadows - AddEffects( EF_NOSHADOW|EF_NORECEIVESHADOW ); - - // Create the dust effect in place - m_hSpitEffect = (CParticleSystem *) CreateEntityByName( "info_particle_system" ); - if ( m_hSpitEffect != NULL ) - { - // Setup our basic parameters - m_hSpitEffect->KeyValue( "start_active", "1" ); - m_hSpitEffect->KeyValue( "effect_name", "antlion_spit_trail" ); - m_hSpitEffect->SetParent( this ); - m_hSpitEffect->SetLocalOrigin( vec3_origin ); - DispatchSpawn( m_hSpitEffect ); - if ( gpGlobals->curtime > 0.5f ) - m_hSpitEffect->Activate(); - } -} - - -void CGrenadeSpit::SetSpitSize( int nSize ) -{ - switch (nSize) - { - case SPIT_LARGE: - { - m_bPlaySound = true; - SetModel( "models/spitball_large.mdl" ); - break; - } - case SPIT_MEDIUM: - { - m_bPlaySound = true; - m_flDamage *= 0.5f; - SetModel( "models/spitball_medium.mdl" ); - break; - } - case SPIT_SMALL: - { - m_bPlaySound = false; - m_flDamage *= 0.25f; - SetModel( "models/spitball_small.mdl" ); - break; - } - } -} - -void CGrenadeSpit::Event_Killed( const CTakeDamageInfo &info ) -{ - Detonate( ); -} - -//----------------------------------------------------------------------------- -// Purpose: Handle spitting -//----------------------------------------------------------------------------- -void CGrenadeSpit::GrenadeSpitTouch( CBaseEntity *pOther ) -{ - if ( pOther->IsSolidFlagSet(FSOLID_VOLUME_CONTENTS | FSOLID_TRIGGER) ) - { - // Some NPCs are triggers that can take damage (like antlion grubs). We should hit them. - if ( ( pOther->m_takedamage == DAMAGE_NO ) || ( pOther->m_takedamage == DAMAGE_EVENTS_ONLY ) ) - return; - } - - // Don't hit other spit - if ( pOther->GetCollisionGroup() == HL2COLLISION_GROUP_SPIT ) - return; - - // We want to collide with water - const trace_t *pTrace = &CBaseEntity::GetTouchTrace(); - - // copy out some important things about this trace, because the first TakeDamage - // call below may cause another trace that overwrites the one global pTrace points - // at. - bool bHitWater = ( ( pTrace->contents & CONTENTS_WATER ) != 0 ); - CBaseEntity *const pTraceEnt = pTrace->m_pEnt; - const Vector tracePlaneNormal = pTrace->plane.normal; - - if ( bHitWater ) - { - // Splash! - CEffectData data; - data.m_fFlags = 0; - data.m_vOrigin = pTrace->endpos; - data.m_vNormal = Vector( 0, 0, 1 ); - data.m_flScale = 8.0f; - - DispatchEffect( "watersplash", data ); - } - else - { - // Make a splat decal - trace_t *pNewTrace = const_cast( pTrace ); - UTIL_DecalTrace( pNewTrace, "BeerSplash" ); - } - - // Part normal damage, part poison damage - float poisonratio = sk_antlion_worker_spit_grenade_poison_ratio.GetFloat(); - - // Take direct damage if hit - // NOTE: assume that pTrace is invalidated from this line forward! - if ( pTraceEnt ) - { - pTraceEnt->TakeDamage( CTakeDamageInfo( this, GetThrower(), m_flDamage * (1.0f-poisonratio), DMG_ACID ) ); - pTraceEnt->TakeDamage( CTakeDamageInfo( this, GetThrower(), m_flDamage * poisonratio, DMG_POISON ) ); - } - - CSoundEnt::InsertSound( SOUND_DANGER, GetAbsOrigin(), (int)(m_DmgRadius * 2.0f), 0.5f, GetThrower() ); - - QAngle vecAngles; - VectorAngles( tracePlaneNormal, vecAngles ); - - if ( pOther->IsPlayer() || bHitWater ) - { - // Do a lighter-weight effect if we just hit a player - DispatchParticleEffect( "antlion_spit_player", GetAbsOrigin(), vecAngles ); - } - else - { - DispatchParticleEffect( "antlion_spit", GetAbsOrigin(), vecAngles ); - } - - Detonate(); -} - -void CGrenadeSpit::Detonate(void) -{ - m_takedamage = DAMAGE_NO; - - EmitSound( "GrenadeSpit.Hit" ); - - // Stop our hissing sound - if ( m_pHissSound != NULL ) - { - CSoundEnvelopeController::GetController().SoundDestroy( m_pHissSound ); - m_pHissSound = NULL; - } - - if ( m_hSpitEffect ) - { - UTIL_Remove( m_hSpitEffect ); - } - - UTIL_Remove( this ); -} - -void CGrenadeSpit::InitHissSound( void ) -{ - if ( m_bPlaySound == false ) - return; - - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - if ( m_pHissSound == NULL ) - { - CPASAttenuationFilter filter( this ); - m_pHissSound = controller.SoundCreate( filter, entindex(), "NPC_Antlion.PoisonBall" ); - controller.Play( m_pHissSound, 1.0f, 100 ); - } -} - -void CGrenadeSpit::Think( void ) -{ - InitHissSound(); - if ( m_pHissSound == NULL ) - return; - - // Add a doppler effect to the balls as they travel - CBaseEntity *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer != NULL ) - { - Vector dir; - VectorSubtract( pPlayer->GetAbsOrigin(), GetAbsOrigin(), dir ); - VectorNormalize(dir); - - float velReceiver = DotProduct( pPlayer->GetAbsVelocity(), dir ); - float velTransmitter = -DotProduct( GetAbsVelocity(), dir ); - - // speed of sound == 13049in/s - int iPitch = (int)(100 * ((1 - velReceiver / 13049) / (1 + velTransmitter / 13049))); - - // clamp pitch shifts - if ( iPitch > 250 ) - { - iPitch = 250; - } - if ( iPitch < 50 ) - { - iPitch = 50; - } - - // Set the pitch we've calculated - CSoundEnvelopeController::GetController().SoundChangePitch( m_pHissSound, iPitch, 0.1f ); - } - - // Set us up to think again shortly - SetNextThink( gpGlobals->curtime + 0.05f ); -} - -void CGrenadeSpit::Precache( void ) -{ - // m_nSquidSpitSprite = PrecacheModel("sprites/greenglow1.vmt");// client side spittle. - - PrecacheModel( "models/spitball_large.mdl" ); - PrecacheModel("models/spitball_medium.mdl"); - PrecacheModel("models/spitball_small.mdl"); - - PrecacheScriptSound( "GrenadeSpit.Hit" ); - - PrecacheParticleSystem( "antlion_spit_player" ); - PrecacheParticleSystem( "antlion_spit" ); -} diff --git a/game/server/hl2/grenade_spit.h b/game/server/hl2/grenade_spit.h deleted file mode 100644 index 52357cc80..000000000 --- a/game/server/hl2/grenade_spit.h +++ /dev/null @@ -1,58 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Projectile shot by bullsquid -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef GRENADESPIT_H -#define GRENADESPIT_H - -#include "basegrenade_shared.h" - -class CParticleSystem; - -enum SpitSize_e -{ - SPIT_SMALL, - SPIT_MEDIUM, - SPIT_LARGE, -}; - -#define SPIT_GRAVITY 600 - -class CGrenadeSpit : public CBaseGrenade -{ - DECLARE_CLASS( CGrenadeSpit, CBaseGrenade ); - -public: - CGrenadeSpit( void ); - - virtual void Spawn( void ); - virtual void Precache( void ); - virtual void Event_Killed( const CTakeDamageInfo &info ); - - virtual unsigned int PhysicsSolidMaskForEntity( void ) const { return ( BaseClass::PhysicsSolidMaskForEntity() | CONTENTS_WATER ); } - - void GrenadeSpitTouch( CBaseEntity *pOther ); - void SetSpitSize( int nSize ); - void Detonate( void ); - void Think( void ); - -private: - DECLARE_DATADESC(); - - void InitHissSound( void ); - - CHandle< CParticleSystem > m_hSpitEffect; - CSoundPatch *m_pHissSound; - bool m_bPlaySound; -}; - -#endif //GRENADESPIT_H diff --git a/game/server/hl2/grenade_tripmine.cpp b/game/server/hl2/grenade_tripmine.cpp deleted file mode 100644 index 06cfdb928..000000000 --- a/game/server/hl2/grenade_tripmine.cpp +++ /dev/null @@ -1,265 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements the tripmine grenade. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "beam_shared.h" -#include "shake.h" -#include "grenade_tripmine.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern const char* g_pModelNameLaser; - -ConVar sk_plr_dmg_tripmine ( "sk_plr_dmg_tripmine","0"); -ConVar sk_npc_dmg_tripmine ( "sk_npc_dmg_tripmine","0"); -ConVar sk_tripmine_radius ( "sk_tripmine_radius","0"); - -LINK_ENTITY_TO_CLASS( npc_tripmine, CTripmineGrenade ); - -BEGIN_DATADESC( CTripmineGrenade ) - - DEFINE_FIELD( m_hOwner, FIELD_EHANDLE ), - DEFINE_FIELD( m_flPowerUp, FIELD_TIME ), - DEFINE_FIELD( m_vecDir, FIELD_VECTOR ), - DEFINE_FIELD( m_vecEnd, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_flBeamLength, FIELD_FLOAT ), - DEFINE_FIELD( m_pBeam, FIELD_CLASSPTR ), - DEFINE_FIELD( m_posOwner, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_angleOwner, FIELD_VECTOR ), - - // Function Pointers - DEFINE_THINKFUNC( WarningThink ), - DEFINE_THINKFUNC( PowerupThink ), - DEFINE_THINKFUNC( BeamBreakThink ), - DEFINE_THINKFUNC( DelayDeathThink ), - -END_DATADESC() - -CTripmineGrenade::CTripmineGrenade() -{ - m_vecDir.Init(); - m_vecEnd.Init(); - m_posOwner.Init(); - m_angleOwner.Init(); -} - -void CTripmineGrenade::Spawn( void ) -{ - Precache( ); - // motor - SetMoveType( MOVETYPE_FLY ); - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_SOLID ); - SetModel( "models/Weapons/w_slam.mdl" ); - SetCycle(0); - - m_nBody = 3; - m_flDamage = sk_plr_dmg_tripmine.GetFloat(); - m_DmgRadius = sk_tripmine_radius.GetFloat(); - - ResetSequenceInfo( ); - m_flPlaybackRate = 0; - - UTIL_SetSize(this, Vector( -4, -4, -2), Vector(4, 4, 2)); - - m_flPowerUp = gpGlobals->curtime + 2.0; - - SetThink( &CTripmineGrenade::PowerupThink ); - SetNextThink( gpGlobals->curtime + 0.2 ); - - m_takedamage = DAMAGE_YES; - - m_iHealth = 1; - - EmitSound( "TripmineGrenade.Charge" ); - - // Tripmine sits at 90 on wall so rotate back to get m_vecDir - QAngle angles = GetLocalAngles(); - angles.x -= 90; - - AngleVectors( angles, &m_vecDir ); - m_vecEnd = GetLocalOrigin() + m_vecDir * 2048; -} - - -void CTripmineGrenade::Precache( void ) -{ - PrecacheModel("models/Weapons/w_slam.mdl"); - - PrecacheScriptSound( "TripmineGrenade.Charge" ); - PrecacheScriptSound( "TripmineGrenade.PowerUp" ); - PrecacheScriptSound( "TripmineGrenade.StopSound" ); - PrecacheScriptSound( "TripmineGrenade.Activate" ); - PrecacheScriptSound( "TripmineGrenade.ShootRope" ); - PrecacheScriptSound( "TripmineGrenade.Hook" ); -} - - -void CTripmineGrenade::WarningThink( void ) -{ - // set to power up - SetThink( &CTripmineGrenade::PowerupThink ); - SetNextThink( gpGlobals->curtime + 1.0f ); -} - - -void CTripmineGrenade::PowerupThink( void ) -{ - if (gpGlobals->curtime > m_flPowerUp) - { - MakeBeam( ); - RemoveSolidFlags( FSOLID_NOT_SOLID ); - m_bIsLive = true; - - // play enabled sound - EmitSound( "TripmineGrenade.PowerUp" );; - } - SetNextThink( gpGlobals->curtime + 0.1f ); -} - - -void CTripmineGrenade::KillBeam( void ) -{ - if ( m_pBeam ) - { - UTIL_Remove( m_pBeam ); - m_pBeam = NULL; - } -} - - -void CTripmineGrenade::MakeBeam( void ) -{ - trace_t tr; - - UTIL_TraceLine( GetAbsOrigin(), m_vecEnd, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - m_flBeamLength = tr.fraction; - - - - // If I hit a living thing, send the beam through me so it turns on briefly - // and then blows the living thing up - CBaseEntity *pEntity = tr.m_pEnt; - CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pEntity ); - - // Draw length is not the beam length if entity is in the way - float drawLength = tr.fraction; - if (pBCC) - { - SetOwnerEntity( pBCC ); - UTIL_TraceLine( GetAbsOrigin(), m_vecEnd, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - m_flBeamLength = tr.fraction; - SetOwnerEntity( NULL ); - - } - - // set to follow laser spot - SetThink( &CTripmineGrenade::BeamBreakThink ); - - // Delay first think slightly so beam has time - // to appear if person right in front of it - SetNextThink( gpGlobals->curtime + 1.0f ); - - Vector vecTmpEnd = GetLocalOrigin() + m_vecDir * 2048 * drawLength; - - m_pBeam = CBeam::BeamCreate( g_pModelNameLaser, 1.0 ); - m_pBeam->PointEntInit( vecTmpEnd, this ); - m_pBeam->SetColor( 0, 214, 198 ); - m_pBeam->SetScrollRate( (int)25.6 ); - m_pBeam->SetBrightness( 64 ); -} - - -void CTripmineGrenade::BeamBreakThink( void ) -{ - // See if I can go solid yet (has dropper moved out of way?) - if (IsSolidFlagSet( FSOLID_NOT_SOLID )) - { - trace_t tr; - Vector vUpBit = GetAbsOrigin(); - vUpBit.z += 5.0; - - UTIL_TraceEntity( this, GetAbsOrigin(), vUpBit, MASK_SHOT, &tr ); - if ( !tr.startsolid && (tr.fraction == 1.0) ) - { - RemoveSolidFlags( FSOLID_NOT_SOLID ); - } - } - - trace_t tr; - - // NOT MASK_SHOT because we want only simple hit boxes - UTIL_TraceLine( GetAbsOrigin(), m_vecEnd, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - - // ALERT( at_console, "%f : %f\n", tr.flFraction, m_flBeamLength ); - - // respawn detect. - if ( !m_pBeam ) - { - MakeBeam( ); - if ( tr.m_pEnt ) - m_hOwner = tr.m_pEnt; // reset owner too - } - - - CBaseEntity *pEntity = tr.m_pEnt; - CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pEntity ); - - if (pBCC || fabs( m_flBeamLength - tr.fraction ) > 0.001) - { - m_iHealth = 0; - Event_Killed( CTakeDamageInfo( (CBaseEntity*)m_hOwner, this, 100, GIB_NORMAL ) ); - return; - } - - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -int CTripmineGrenade::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - if (gpGlobals->curtime < m_flPowerUp && info.GetDamage() < m_iHealth) - { - // disable - // Create( "weapon_tripmine", GetLocalOrigin() + m_vecDir * 24, GetAngles() ); - SetThink( &CBaseEntity::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 0.1f ); - KillBeam(); - return FALSE; - } - return BaseClass::OnTakeDamage_Alive( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CTripmineGrenade::Event_Killed( const CTakeDamageInfo &info ) -{ - m_takedamage = DAMAGE_NO; - - SetThink( &CTripmineGrenade::DelayDeathThink ); - SetNextThink( gpGlobals->curtime + 0.5 ); - - EmitSound( "TripmineGrenade.StopSound" ); -} - - -void CTripmineGrenade::DelayDeathThink( void ) -{ - KillBeam(); - trace_t tr; - UTIL_TraceLine ( GetAbsOrigin() + m_vecDir * 8, GetAbsOrigin() - m_vecDir * 64, MASK_SOLID, this, COLLISION_GROUP_NONE, & tr); - UTIL_ScreenShake( GetAbsOrigin(), 25.0, 150.0, 1.0, 750, SHAKE_START ); - - Explode( &tr, DMG_BLAST ); -} - diff --git a/game/server/hl2/grenade_tripmine.h b/game/server/hl2/grenade_tripmine.h deleted file mode 100644 index 1e51cec8b..000000000 --- a/game/server/hl2/grenade_tripmine.h +++ /dev/null @@ -1,55 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef GRENADE_TRIPMINE_H -#define GRENADE_TRIPMINE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "basegrenade_shared.h" - -class CBeam; - - -class CTripmineGrenade : public CBaseGrenade -{ -public: - DECLARE_CLASS( CTripmineGrenade, CBaseGrenade ); - - CTripmineGrenade(); - void Spawn( void ); - void Precache( void ); - - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - - void WarningThink( void ); - void PowerupThink( void ); - void BeamBreakThink( void ); - void DelayDeathThink( void ); - void Event_Killed( const CTakeDamageInfo &info ); - - void MakeBeam( void ); - void KillBeam( void ); - -public: - EHANDLE m_hOwner; - -private: - float m_flPowerUp; - Vector m_vecDir; - Vector m_vecEnd; - float m_flBeamLength; - - CBeam *m_pBeam; - Vector m_posOwner; - Vector m_angleOwner; - - DECLARE_DATADESC(); -}; - -#endif // GRENADE_TRIPMINE_H diff --git a/game/server/hl2/grenade_tripwire.cpp b/game/server/hl2/grenade_tripwire.cpp deleted file mode 100644 index dee2fb32b..000000000 --- a/game/server/hl2/grenade_tripwire.cpp +++ /dev/null @@ -1,397 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements the tripmine grenade. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "util.h" -#include "shake.h" -#include "grenade_tripwire.h" -#include "grenade_homer.h" -#include "rope.h" -#include "rope_shared.h" -#include "engine/IEngineSound.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar sk_dmg_tripwire ( "sk_dmg_tripwire","0"); -ConVar sk_tripwire_radius ( "sk_tripwire_radius","0"); - -#define GRENADETRIPWIRE_MISSILEMDL "models/Weapons/ar2_grenade.mdl" - -#define TGRENADE_LAUNCH_VEL 1200 -#define TGRENADE_SPIN_MAG 50 -#define TGRENADE_SPIN_SPEED 100 -#define TGRENADE_MISSILE_OFFSET 50 -#define TGRENADE_MAX_ROPE_LEN 1500 - -LINK_ENTITY_TO_CLASS( npc_tripwire, CTripwireGrenade ); - -BEGIN_DATADESC( CTripwireGrenade ) - - DEFINE_FIELD( m_flPowerUp, FIELD_TIME ), - DEFINE_FIELD( m_nMissileCount, FIELD_INTEGER ), - DEFINE_FIELD( m_vecDir, FIELD_VECTOR ), - DEFINE_FIELD( m_vTargetPos, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vTargetOffset, FIELD_VECTOR ), - DEFINE_FIELD( m_pRope, FIELD_CLASSPTR ), - DEFINE_FIELD( m_pHook, FIELD_CLASSPTR ), - - // Function Pointers - DEFINE_THINKFUNC( WarningThink ), - DEFINE_THINKFUNC( PowerupThink ), - DEFINE_THINKFUNC( RopeBreakThink ), - DEFINE_THINKFUNC( FireThink ), - -END_DATADESC() - -CTripwireGrenade::CTripwireGrenade() -{ - m_vecDir.Init(); -} - -void CTripwireGrenade::Spawn( void ) -{ - Precache( ); - - SetMoveType( MOVETYPE_FLY ); - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_SOLID ); - - SetModel( "models/Weapons/w_slam.mdl" ); - - m_nMissileCount = 0; - - UTIL_SetSize(this, Vector( -4, -4, -2), Vector(4, 4, 2)); - - m_flPowerUp = gpGlobals->curtime + 1.2;//<>get rid of this - - SetThink( &CTripwireGrenade::WarningThink ); - SetNextThink( gpGlobals->curtime + 1.0f ); - - m_takedamage = DAMAGE_YES; - - m_iHealth = 1; - - m_pRope = NULL; - m_pHook = NULL; - - // Tripwire grenade sits at 90 on wall so rotate back to get m_vecDir - QAngle angles = GetLocalAngles(); - angles.x -= 90; - - AngleVectors( angles, &m_vecDir ); -} - - -void CTripwireGrenade::Precache( void ) -{ - PrecacheModel("models/Weapons/w_slam.mdl"); - - PrecacheModel(GRENADETRIPWIRE_MISSILEMDL); -} - - -void CTripwireGrenade::WarningThink( void ) -{ - // play activate sound - EmitSound( "TripwireGrenade.Activate" ); - - // set to power up - SetThink( &CTripwireGrenade::PowerupThink ); - SetNextThink( gpGlobals->curtime + 1.0f ); -} - - -void CTripwireGrenade::PowerupThink( void ) -{ - if (gpGlobals->curtime > m_flPowerUp) - { - MakeRope( ); - RemoveSolidFlags( FSOLID_NOT_SOLID ); - m_bIsLive = true; - } - SetNextThink( gpGlobals->curtime + 0.1f ); -} - - -void CTripwireGrenade::BreakRope( void ) -{ - if (m_pRope) - { - m_pRope->m_RopeFlags |= ROPE_COLLIDE; - m_pRope->DetachPoint(0); - - Vector vVelocity; - m_pHook->GetVelocity( &vVelocity, NULL ); - if (vVelocity.Length() > 1) - { - m_pRope->DetachPoint(1); - } - } -} - - -void CTripwireGrenade::MakeRope( void ) -{ - SetThink( &CTripwireGrenade::RopeBreakThink ); - - // Delay first think slightly so rope has time - // to appear if person right in front of it - SetNextThink( gpGlobals->curtime + 1.0f ); - - // Create hook for end of tripwire - m_pHook = (CTripwireHook*)CBaseEntity::Create( "tripwire_hook", GetLocalOrigin(), GetLocalAngles() ); - if (m_pHook) - { - Vector vShootVel = 800*(m_vecDir + Vector(0,0,0.3)+RandomVector(-0.01,0.01)); - m_pHook->SetVelocity( vShootVel, vec3_origin); - m_pHook->SetOwnerEntity( this ); - m_pHook->m_hGrenade = this; - - m_pRope = CRopeKeyframe::Create(this,m_pHook,0,0); - if (m_pRope) - { - m_pRope->m_Width = 1; - m_pRope->m_RopeLength = 3; - m_pRope->m_Slack = 100; - - CPASAttenuationFilter filter( this,"TripwireGrenade.ShootRope" ); - EmitSound( filter, entindex(),"TripwireGrenade.ShootRope" ); - } - } -} - -void CTripwireGrenade::Attach( void ) -{ - StopSound( "TripwireGrenade.ShootRope" ); -} - -void CTripwireGrenade::RopeBreakThink( void ) -{ - // See if I can go solid yet (has dropper moved out of way?) - if (IsSolidFlagSet(FSOLID_NOT_SOLID)) - { - trace_t tr; - Vector vUpBit = GetAbsOrigin(); - vUpBit.z += 5.0; - - UTIL_TraceEntity( this, GetAbsOrigin(), vUpBit, MASK_SHOT, &tr ); - if ( !tr.startsolid && (tr.fraction == 1.0) ) - { - RemoveSolidFlags( FSOLID_NOT_SOLID ); - } - } - - // Check if rope had gotten beyond it's max length - float flRopeLength = (GetAbsOrigin()-m_pHook->GetAbsOrigin()).Length(); - if (flRopeLength > TGRENADE_MAX_ROPE_LEN) - { - // Shoot missiles at hook - m_iHealth = 0; - BreakRope(); - m_vTargetPos = m_pHook->GetAbsOrigin(); - CrossProduct ( m_vecDir, Vector(0,0,1), m_vTargetOffset ); - m_vTargetOffset *=TGRENADE_MISSILE_OFFSET; - SetThink(&CTripwireGrenade::FireThink); - FireThink(); - } - - // Check to see if can see hook - // NOT MASK_SHOT because we want only simple hit boxes - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), m_pHook->GetAbsOrigin(), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - - // If can't see hook - CBaseEntity *pEntity = tr.m_pEnt; - if (tr.fraction != 1.0 && pEntity != m_pHook) - { - // Shoot missiles at place where rope was intersected - m_iHealth = 0; - BreakRope(); - m_vTargetPos = tr.endpos; - CrossProduct ( m_vecDir, Vector(0,0,1), m_vTargetOffset ); - m_vTargetOffset *=TGRENADE_MISSILE_OFFSET; - SetThink(&CTripwireGrenade::FireThink); - FireThink(); - return; - } - - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -//------------------------------------------------------------------------------ -// Purpose : Die if I take any damage -// Input : -// Output : -//------------------------------------------------------------------------------ -int CTripwireGrenade::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - // Killed upon any damage - Event_Killed( info ); - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: If someone damaged, me shoot of my missiles and die -// Input : -// Output : -//----------------------------------------------------------------------------- -void CTripwireGrenade::Event_Killed( const CTakeDamageInfo &info ) -{ - if (m_iHealth > 0) - { - // Fire missiles and blow up - for (int i=0;i<6;i++) - { - Vector vTargetPos = GetAbsOrigin() + RandomVector(-600,600); - FireMissile(vTargetPos); - } - BreakRope(); - UTIL_Remove(this); - } -} - -//------------------------------------------------------------------------------ -// Purpose : Fire a missile at the target position -// Input : -// Output : -//------------------------------------------------------------------------------ -void CTripwireGrenade::FireMissile(const Vector &vTargetPos) -{ - Vector vTargetDir = (vTargetPos - GetAbsOrigin()); - VectorNormalize(vTargetDir); - - float flGravity = 0.0001; // No gravity on the missiles - bool bSmokeTrail = true; - float flHomingSpeed = 0; - Vector vLaunchVelocity = TGRENADE_LAUNCH_VEL*vTargetDir; - float flSpinMagnitude = TGRENADE_SPIN_MAG; - float flSpinSpeed = TGRENADE_SPIN_SPEED; - - //<> hold in string_t - CGrenadeHomer *pGrenade = CGrenadeHomer::CreateGrenadeHomer( MAKE_STRING(GRENADETRIPWIRE_MISSILEMDL), MAKE_STRING("TripwireGrenade.FlySound"), GetAbsOrigin(), vec3_angle, edict() ); - - pGrenade->Spawn( ); - pGrenade->SetSpin(flSpinMagnitude,flSpinSpeed); - pGrenade->SetHoming(0,0,0,0,0); - pGrenade->SetDamage(sk_dmg_tripwire.GetFloat()); - pGrenade->SetDamageRadius(sk_tripwire_radius.GetFloat()); - pGrenade->Launch(this,NULL,vLaunchVelocity,flHomingSpeed,flGravity,bSmokeTrail); - - // Calculate travel time - float flTargetDist = (GetAbsOrigin() - vTargetPos).Length(); - - pGrenade->m_flDetonateTime = gpGlobals->curtime + flTargetDist/TGRENADE_LAUNCH_VEL; - -} - -//------------------------------------------------------------------------------ -// Purpose : Shoot off a series of missiles over time, then go intert -// Input : -// Output : -//------------------------------------------------------------------------------ -void CTripwireGrenade::FireThink() -{ - SetNextThink( gpGlobals->curtime + 0.16f ); - - Vector vTargetPos = m_vTargetPos + (m_vTargetOffset * m_nMissileCount); - FireMissile(vTargetPos); - - vTargetPos = m_vTargetPos - (m_vTargetOffset * m_nMissileCount); - FireMissile(vTargetPos); - - - m_nMissileCount++; - if (m_nMissileCount > 4) - { - m_iHealth = -1; - SetThink( NULL ); - } -} - -// #################################################################### -// CTripwireHook -// -// This is what the tripwire shoots out at the end of the rope -// #################################################################### -LINK_ENTITY_TO_CLASS( tripwire_hook, CTripwireHook ); - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CTripwireHook ) - - DEFINE_FIELD( m_hGrenade, FIELD_EHANDLE ), - DEFINE_FIELD( m_bAttached, FIELD_BOOLEAN ), - -END_DATADESC() - - -void CTripwireHook::Spawn( void ) -{ - - Precache( ); - SetModel( "models/Weapons/w_grenade.mdl" );//<> - - UTIL_SetSize(this, Vector( -1, -1, -1), Vector(1,1, 1)); - - m_takedamage = DAMAGE_NO; - m_bAttached = false; - - CreateVPhysics(); -} - -bool CTripwireHook::CreateVPhysics() -{ - // Create the object in the physics system - IPhysicsObject *pPhysicsObject = VPhysicsInitNormal( SOLID_BBOX, 0, false ); - - // Make sure I get touch called for static geometry - if ( pPhysicsObject ) - { - int flags = pPhysicsObject->GetCallbackFlags(); - flags |= CALLBACK_GLOBAL_TOUCH_STATIC; - pPhysicsObject->SetCallbackFlags(flags); - } - return true; -} - - -void CTripwireHook::Precache( void ) -{ - PrecacheModel("models/Weapons/w_grenade.mdl"); //<> -} - -void CTripwireHook::EndTouch( CBaseEntity *pOther ) -{ - //<>do instead by clearing touch function - if (!m_bAttached) - { - m_bAttached = true; - - SetVelocity(vec3_origin, vec3_origin); - SetMoveType( MOVETYPE_NONE ); - - EmitSound( "TripwireGrenade.Hook" ); - - // Let the tripwire grenade know that I've attached - CTripwireGrenade* pGrenade = dynamic_cast((CBaseEntity*)m_hGrenade); - if (pGrenade) - { - pGrenade->Attach(); - } - } -} - -void CTripwireHook::SetVelocity( const Vector &velocity, const AngularImpulse &angVelocity ) -{ - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - if ( pPhysicsObject ) - { - pPhysicsObject->AddVelocity( &velocity, &angVelocity ); - } -} diff --git a/game/server/hl2/grenade_tripwire.h b/game/server/hl2/grenade_tripwire.h deleted file mode 100644 index cf58122e4..000000000 --- a/game/server/hl2/grenade_tripwire.h +++ /dev/null @@ -1,80 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Tripmine -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef TRIPWIRE_H -#define TRIPWIRE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "basegrenade_shared.h" - -class CRopeKeyframe; - -// #################################################################### -// CTripwireHook -// -// This is what the tripwire shoots out at the end of the rope -// #################################################################### -class CTripwireHook : public CBaseAnimating -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( CTripwireHook, CBaseAnimating ); - - EHANDLE m_hGrenade; - bool m_bAttached; - - void Spawn( void ); - void Precache( void ); - bool CreateVPhysics( void ); - void EndTouch( CBaseEntity *pOther ); - void SetVelocity( const Vector &velocity, const AngularImpulse &angVelocity ); -}; - -class CTripwireGrenade : public CBaseGrenade -{ -public: - DECLARE_CLASS( CTripwireGrenade, CBaseGrenade ); - - CTripwireGrenade(); - void Spawn( void ); - void Precache( void ); - - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - - void WarningThink( void ); - void PowerupThink( void ); - void RopeBreakThink( void ); - void FireThink( void ); - void Event_Killed( const CTakeDamageInfo &info ); - void Attach( void ); - - void MakeRope( void ); - void BreakRope( void ); - void ShakeRope( void ); - void FireMissile(const Vector &vTargetPos); - -private: - float m_flPowerUp; - Vector m_vecDir; - - int m_nMissileCount; - - Vector m_vTargetPos; - Vector m_vTargetOffset; - - CRopeKeyframe* m_pRope; - CTripwireHook* m_pHook; - - DECLARE_DATADESC(); -}; - -#endif //TRIPWIRE_H diff --git a/game/server/hl2/hl2_ai_network.cpp b/game/server/hl2/hl2_ai_network.cpp deleted file mode 100644 index 96510e01c..000000000 --- a/game/server/hl2/hl2_ai_network.cpp +++ /dev/null @@ -1,26 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - - -#include "cbase.h" - -#include "ai_networkmanager.h" -#include "npc_strider.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CHL2NetworkBuildHelper : public CAI_NetworkBuildHelper -{ - DECLARE_CLASS( CHL2NetworkBuildHelper, CAI_NetworkBuildHelper ); - - void PostInitNodePosition( CAI_Network *pNetwork, CAI_Node *pNode ) - { - AdjustStriderNodePosition( pNetwork, pNode ); - } -}; - -LINK_ENTITY_TO_CLASS(ai_network_build_helper,CHL2NetworkBuildHelper); diff --git a/game/server/hl2/hl2_client.cpp b/game/server/hl2/hl2_client.cpp deleted file mode 100644 index be9f212c1..000000000 --- a/game/server/hl2/hl2_client.cpp +++ /dev/null @@ -1,177 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -/* - -===== tf_client.cpp ======================================================== - - HL2 client/server game specific stuff - -*/ - -#include "cbase.h" -#include "hl2_player.h" -#include "hl2_gamerules.h" -#include "gamerules.h" -#include "teamplay_gamerules.h" -#include "entitylist.h" -#include "physics.h" -#include "game.h" -#include "player_resource.h" -#include "engine/IEngineSound.h" - -#include "tier0/vprof.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -void Host_Say( edict_t *pEdict, bool teamonly ); - -extern CBaseEntity* FindPickerEntityClass( CBasePlayer *pPlayer, char *classname ); -extern bool g_fGameOver; - -/* -=========== -ClientPutInServer - -called each time a player is spawned into the game -============ -*/ -void ClientPutInServer( edict_t *pEdict, const char *playername ) -{ - // Allocate a CBasePlayer for pev, and call spawn - CHL2_Player *pPlayer = CHL2_Player::CreatePlayer( "player", pEdict ); - pPlayer->SetPlayerName( playername ); -} - - -void ClientActive( edict_t *pEdict, bool bLoadGame ) -{ - CHL2_Player *pPlayer = dynamic_cast< CHL2_Player* >( CBaseEntity::Instance( pEdict ) ); - Assert( pPlayer ); - - if ( !pPlayer ) - { - return; - } - - pPlayer->InitialSpawn(); - - if ( !bLoadGame ) - { - pPlayer->Spawn(); - } -} - - -/* -=============== -const char *GetGameDescription() - -Returns the descriptive name of this .dll. E.g., Half-Life, or Team Fortress 2 -=============== -*/ -const char *GetGameDescription() -{ - if ( g_pGameRules ) // this function may be called before the world has spawned, and the game rules initialized - return g_pGameRules->GetGameDescription(); - else - return "Half-Life 2"; -} - -//----------------------------------------------------------------------------- -// Purpose: Given a player and optional name returns the entity of that -// classname that the player is nearest facing -// -// Input : -// Output : -//----------------------------------------------------------------------------- -CBaseEntity* FindEntity( edict_t *pEdict, char *classname) -{ - // If no name was given set bits based on the picked - if (FStrEq(classname,"")) - { - return (FindPickerEntityClass( static_cast(GetContainingEntity(pEdict)), classname )); - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Precache game-specific models & sounds -//----------------------------------------------------------------------------- -void ClientGamePrecache( void ) -{ - CBaseEntity::PrecacheModel("models/player.mdl"); - CBaseEntity::PrecacheModel( "models/gibs/agibs.mdl" ); - CBaseEntity::PrecacheModel ("models/weapons/v_hands.mdl"); - - CBaseEntity::PrecacheScriptSound( "HUDQuickInfo.LowAmmo" ); - CBaseEntity::PrecacheScriptSound( "HUDQuickInfo.LowHealth" ); - - CBaseEntity::PrecacheScriptSound( "FX_AntlionImpact.ShellImpact" ); - CBaseEntity::PrecacheScriptSound( "Missile.ShotDown" ); - CBaseEntity::PrecacheScriptSound( "Bullets.DefaultNearmiss" ); - CBaseEntity::PrecacheScriptSound( "Bullets.GunshipNearmiss" ); - CBaseEntity::PrecacheScriptSound( "Bullets.StriderNearmiss" ); - - CBaseEntity::PrecacheScriptSound( "Geiger.BeepHigh" ); - CBaseEntity::PrecacheScriptSound( "Geiger.BeepLow" ); -} - - -// called by ClientKill and DeadThink -void respawn( CBaseEntity *pEdict, bool fCopyCorpse ) -{ - if (gpGlobals->coop || gpGlobals->deathmatch) - { - if ( fCopyCorpse ) - { - // make a copy of the dead body for appearances sake - ((CHL2_Player *)pEdict)->CreateCorpse(); - } - - // respawn player - pEdict->Spawn(); - } - else - { // restart the entire server - engine->ServerCommand("reload\n"); - } -} - -void GameStartFrame( void ) -{ - VPROF("GameStartFrame()"); - if ( g_fGameOver ) - return; - - gpGlobals->teamplay = (teamplay.GetInt() != 0); -} - -#ifdef HL2_EPISODIC -extern ConVar gamerules_survival; -#endif - -//========================================================= -// instantiate the proper game rules object -//========================================================= -void InstallGameRules() -{ -#ifdef HL2_EPISODIC - if ( gamerules_survival.GetBool() ) - { - // Survival mode - CreateGameRulesObject( "CHalfLife2Survival" ); - } - else -#endif - { - // generic half-life - CreateGameRulesObject( "CHalfLife2" ); - } -} - diff --git a/game/server/hl2/hl2_eventlog.cpp b/game/server/hl2/hl2_eventlog.cpp deleted file mode 100644 index ea1342d3f..000000000 --- a/game/server/hl2/hl2_eventlog.cpp +++ /dev/null @@ -1,61 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "../EventLog.h" -#include "KeyValues.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CHL2EventLog : public CEventLog -{ -private: - typedef CEventLog BaseClass; - -public: - virtual char const *Name() { return "CHL2EventLog"; } - - virtual ~CHL2EventLog() {}; - -public: - bool PrintEvent( IGameEvent * event ) // override virtual function - { - if ( BaseClass::PrintEvent( event ) ) - { - return true; - } - - if ( Q_strcmp(event->GetName(), "hl2_") == 0 ) - { - return PrintHL2Event( event ); - } - - return false; - } - -protected: - - bool PrintHL2Event( IGameEvent * event ) // print Mod specific logs - { - // const char * name = event->GetName() + Q_strlen("hl2_"); // remove prefix - - return false; - } - -}; - -static CHL2EventLog s_HL2EventLog; - -//----------------------------------------------------------------------------- -// Singleton access -//----------------------------------------------------------------------------- -IGameSystem* GameLogSystem() -{ - return &s_HL2EventLog; -} - diff --git a/game/server/hl2/hl2_gamestats.cpp b/game/server/hl2/hl2_gamestats.cpp deleted file mode 100644 index 8ecd706d5..000000000 --- a/game/server/hl2/hl2_gamestats.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#include "hl2_gamestats.h" -#include "achievementmgr.h" - -static CHL2GameStats s_HL2GameStats; - -CHL2GameStats::CHL2GameStats( void ) -{ - gamestats = &s_HL2GameStats; -} diff --git a/game/server/hl2/hl2_gamestats.h b/game/server/hl2/hl2_gamestats.h deleted file mode 100644 index 69f79b625..000000000 --- a/game/server/hl2/hl2_gamestats.h +++ /dev/null @@ -1,23 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef HL2_GAMESTATS_H -#define HL2_GAMESTATS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "GameStats.h" - -class CHL2GameStats : public CBaseGameStats -{ - typedef CBaseGameStats BaseClass; - -public: - CHL2GameStats( void ); -}; - -#endif // EP1_GAMESTATS_H diff --git a/game/server/hl2/hl2_player.cpp b/game/server/hl2/hl2_player.cpp deleted file mode 100644 index 68624b8d9..000000000 --- a/game/server/hl2/hl2_player.cpp +++ /dev/null @@ -1,3913 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Player for HL2. -// -//=============================================================================// - -#include "cbase.h" -#include "hl2_player.h" -#include "globalstate.h" -#include "game.h" -#include "gamerules.h" -#include "trains.h" -#include "basehlcombatweapon_shared.h" -#include "vcollide_parse.h" -#include "in_buttons.h" -#include "ai_interactions.h" -#include "ai_squad.h" -#include "igamemovement.h" -#include "ai_hull.h" -#include "hl2_shareddefs.h" -#include "info_camera_link.h" -#include "point_camera.h" -#include "engine/IEngineSound.h" -#include "ndebugoverlay.h" -#include "iservervehicle.h" -#include "IVehicle.h" -#include "globals.h" -#include "collisionutils.h" -#include "coordsize.h" -#include "effect_color_tables.h" -#include "vphysics/player_controller.h" -#include "player_pickup.h" -#include "weapon_physcannon.h" -#include "script_intro.h" -#include "effect_dispatch_data.h" -#include "te_effect_dispatch.h" -#include "ai_basenpc.h" -#include "AI_Criteria.h" -#include "npc_barnacle.h" -#include "entitylist.h" -#include "env_zoom.h" -#include "hl2_gamerules.h" -#include "prop_combine_ball.h" -#include "datacache/imdlcache.h" -#include "eventqueue.h" -#include "GameStats.h" -#include "filters.h" -#include "tier0/icommandline.h" - -#ifdef HL2_EPISODIC -#include "npc_alyx_episodic.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern ConVar weapon_showproficiency; -extern ConVar autoaim_max_dist; - -// Do not touch with without seeing me, please! (sjb) -// For consistency's sake, enemy gunfire is traced against a scaled down -// version of the player's hull, not the hitboxes for the player's model -// because the player isn't aware of his model, and can't do anything about -// preventing headshots and other such things. Also, game difficulty will -// not change if the model changes. This is the value by which to scale -// the X/Y of the player's hull to get the volume to trace bullets against. -#define PLAYER_HULL_REDUCTION 0.70 - -// This switches between the single primary weapon, and multiple weapons with buckets approach (jdw) -#define HL2_SINGLE_PRIMARY_WEAPON_MODE 0 - -#define TIME_IGNORE_FALL_DAMAGE 10.0 - -extern int gEvilImpulse101; - -ConVar sv_autojump( "sv_autojump", "0" ); - -ConVar hl2_walkspeed( "hl2_walkspeed", "150" ); -ConVar hl2_normspeed( "hl2_normspeed", "190" ); -ConVar hl2_sprintspeed( "hl2_sprintspeed", "320" ); - -ConVar hl2_darkness_flashlight_factor ( "hl2_darkness_flashlight_factor", "1" ); - -#ifdef HL2MP - #define HL2_WALK_SPEED 150 - #define HL2_NORM_SPEED 190 - #define HL2_SPRINT_SPEED 320 -#else - #define HL2_WALK_SPEED hl2_walkspeed.GetFloat() - #define HL2_NORM_SPEED hl2_normspeed.GetFloat() - #define HL2_SPRINT_SPEED hl2_sprintspeed.GetFloat() -#endif - -ConVar player_showpredictedposition( "player_showpredictedposition", "0" ); -ConVar player_showpredictedposition_timestep( "player_showpredictedposition_timestep", "1.0" ); - -ConVar player_squad_transient_commands( "player_squad_transient_commands", "1", FCVAR_REPLICATED ); -ConVar player_squad_double_tap_time( "player_squad_double_tap_time", "0.25" ); - -ConVar sv_infinite_aux_power( "sv_infinite_aux_power", "0", FCVAR_CHEAT ); - -ConVar autoaim_unlock_target( "autoaim_unlock_target", "0.8666" ); - -ConVar sv_stickysprint("sv_stickysprint", "0", FCVAR_ARCHIVE | FCVAR_ARCHIVE_XBOX); - -#define FLASH_DRAIN_TIME 1.1111 // 100 units / 90 secs -#define FLASH_CHARGE_TIME 50.0f // 100 units / 2 secs - - -//============================================================================================== -// CAPPED PLAYER PHYSICS DAMAGE TABLE -//============================================================================================== -static impactentry_t cappedPlayerLinearTable[] = -{ - { 150*150, 5 }, - { 250*250, 10 }, - { 450*450, 20 }, - { 550*550, 30 }, - //{ 700*700, 100 }, - //{ 1000*1000, 500 }, -}; - -static impactentry_t cappedPlayerAngularTable[] = -{ - { 100*100, 10 }, - { 150*150, 20 }, - { 200*200, 30 }, - //{ 300*300, 500 }, -}; - -static impactdamagetable_t gCappedPlayerImpactDamageTable = -{ - cappedPlayerLinearTable, - cappedPlayerAngularTable, - - ARRAYSIZE(cappedPlayerLinearTable), - ARRAYSIZE(cappedPlayerAngularTable), - - 24*24.0f, // minimum linear speed - 360*360.0f, // minimum angular speed - 2.0f, // can't take damage from anything under 2kg - - 5.0f, // anything less than 5kg is "small" - 5.0f, // never take more than 5 pts of damage from anything under 5kg - 36*36.0f, // <5kg objects must go faster than 36 in/s to do damage - - 0.0f, // large mass in kg (no large mass effects) - 1.0f, // large mass scale - 2.0f, // large mass falling scale - 320.0f, // min velocity for player speed to cause damage - -}; - -// Flashlight utility -bool g_bCacheLegacyFlashlightStatus = true; -bool g_bUseLegacyFlashlight; -bool Flashlight_UseLegacyVersion( void ) -{ - // If this is the first run through, cache off what the answer should be (cannot change during a session) - if ( g_bCacheLegacyFlashlightStatus ) - { - char modDir[MAX_PATH]; - if ( UTIL_GetModDir( modDir, sizeof(modDir) ) == false ) - return false; - - g_bUseLegacyFlashlight = ( !Q_strcmp( modDir, "hl2" ) || !Q_strcmp( modDir, "episodic" ) ); - - g_bCacheLegacyFlashlightStatus = false; - } - - // Return the results - return g_bUseLegacyFlashlight; -} - -//----------------------------------------------------------------------------- -// Purpose: Used to relay outputs/inputs from the player to the world and viceversa -//----------------------------------------------------------------------------- -class CLogicPlayerProxy : public CLogicalEntity -{ - DECLARE_CLASS( CLogicPlayerProxy, CLogicalEntity ); - -private: - - DECLARE_DATADESC(); - -public: - - COutputEvent m_OnFlashlightOn; - COutputEvent m_OnFlashlightOff; - COutputEvent m_PlayerHasAmmo; - COutputEvent m_PlayerHasNoAmmo; - COutputEvent m_PlayerDied; - COutputEvent m_PlayerMissedAR2AltFire; // Player fired a combine ball which did not dissolve any enemies. - - COutputInt m_RequestedPlayerHealth; - - void InputRequestPlayerHealth( inputdata_t &inputdata ); - void InputSetFlashlightSlowDrain( inputdata_t &inputdata ); - void InputSetFlashlightNormalDrain( inputdata_t &inputdata ); - void InputSetPlayerHealth( inputdata_t &inputdata ); - void InputRequestAmmoState( inputdata_t &inputdata ); - void InputLowerWeapon( inputdata_t &inputdata ); - void InputEnableCappedPhysicsDamage( inputdata_t &inputdata ); - void InputDisableCappedPhysicsDamage( inputdata_t &inputdata ); - void InputSetLocatorTargetEntity( inputdata_t &inputdata ); - - void Activate ( void ); - - bool PassesDamageFilter( const CTakeDamageInfo &info ); - - EHANDLE m_hPlayer; -}; - - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CC_ToggleZoom( void ) -{ - CBasePlayer* pPlayer = UTIL_GetCommandClient(); - - if( pPlayer ) - { - CHL2_Player *pHL2Player = dynamic_cast(pPlayer); - - if( pHL2Player && pHL2Player->IsSuitEquipped() ) - { - pHL2Player->ToggleZoom(); - } - } -} - -static ConCommand toggle_zoom("toggle_zoom", CC_ToggleZoom, "Toggles zoom display" ); - -// ConVar cl_forwardspeed( "cl_forwardspeed", "400", FCVAR_CHEAT ); // Links us to the client's version -ConVar xc_crouch_range( "xc_crouch_range", "0.85", FCVAR_ARCHIVE, "Percentarge [1..0] of joystick range to allow ducking within" ); // Only 1/2 of the range is used -ConVar xc_use_crouch_limiter( "xc_use_crouch_limiter", "0", FCVAR_ARCHIVE, "Use the crouch limiting logic on the controller" ); - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CC_ToggleDuck( void ) -{ - CBasePlayer* pPlayer = UTIL_GetCommandClient(); - if ( pPlayer == NULL ) - return; - - // Cannot be frozen - if ( pPlayer->GetFlags() & FL_FROZEN ) - return; - - static bool bChecked = false; - static ConVar *pCVcl_forwardspeed = NULL; - if ( !bChecked ) - { - bChecked = true; - pCVcl_forwardspeed = ( ConVar * )cvar->FindVar( "cl_forwardspeed" ); - } - - - // If we're not ducked, do extra checking - if ( xc_use_crouch_limiter.GetBool() ) - { - if ( pPlayer->GetToggledDuckState() == false ) - { - float flForwardSpeed = 400.0f; - if ( pCVcl_forwardspeed ) - { - flForwardSpeed = pCVcl_forwardspeed->GetFloat(); - } - - flForwardSpeed = MAX( 1.0f, flForwardSpeed ); - - // Make sure we're not in the blindspot on the crouch detection - float flStickDistPerc = ( pPlayer->GetStickDist() / flForwardSpeed ); // Speed is the magnitude - if ( flStickDistPerc > xc_crouch_range.GetFloat() ) - return; - } - } - - // Toggle the duck - pPlayer->ToggleDuck(); -} - -static ConCommand toggle_duck("toggle_duck", CC_ToggleDuck, "Toggles duck" ); - -#ifndef HL2MP -#ifndef PORTAL -LINK_ENTITY_TO_CLASS( player, CHL2_Player ); -#endif -#endif - -PRECACHE_REGISTER(player); - -CBaseEntity *FindEntityForward( CBasePlayer *pMe, bool fHull ); - -BEGIN_SIMPLE_DATADESC( LadderMove_t ) - DEFINE_FIELD( m_bForceLadderMove, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bForceMount, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flStartTime, FIELD_TIME ), - DEFINE_FIELD( m_flArrivalTime, FIELD_TIME ), - DEFINE_FIELD( m_vecGoalPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecStartPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_hForceLadder, FIELD_EHANDLE ), - DEFINE_FIELD( m_hReservedSpot, FIELD_EHANDLE ), -END_DATADESC() - -// Global Savedata for HL2 player -BEGIN_DATADESC( CHL2_Player ) - - DEFINE_FIELD( m_nControlClass, FIELD_INTEGER ), - DEFINE_EMBEDDED( m_HL2Local ), - - DEFINE_FIELD( m_bSprintEnabled, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flTimeAllSuitDevicesOff, FIELD_TIME ), - DEFINE_FIELD( m_fIsSprinting, FIELD_BOOLEAN ), - DEFINE_FIELD( m_fIsWalking, FIELD_BOOLEAN ), - - /* - // These are initialized every time the player calls Activate() - DEFINE_FIELD( m_bIsAutoSprinting, FIELD_BOOLEAN ), - DEFINE_FIELD( m_fAutoSprintMinTime, FIELD_TIME ), - */ - - // Field is used within a single tick, no need to save restore - // DEFINE_FIELD( m_bPlayUseDenySound, FIELD_BOOLEAN ), - // m_pPlayerAISquad reacquired on load - - DEFINE_AUTO_ARRAY( m_vecMissPositions, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_nNumMissPositions, FIELD_INTEGER ), - - // m_pPlayerAISquad - DEFINE_EMBEDDED( m_CommanderUpdateTimer ), - // m_RealTimeLastSquadCommand - DEFINE_FIELD( m_QueuedCommand, FIELD_INTEGER ), - - DEFINE_FIELD( m_flTimeIgnoreFallDamage, FIELD_TIME ), - DEFINE_FIELD( m_bIgnoreFallDamageResetAfterImpact, FIELD_BOOLEAN ), - - // Suit power fields - DEFINE_FIELD( m_flSuitPowerLoad, FIELD_FLOAT ), - - DEFINE_FIELD( m_flIdleTime, FIELD_TIME ), - DEFINE_FIELD( m_flMoveTime, FIELD_TIME ), - DEFINE_FIELD( m_flLastDamageTime, FIELD_TIME ), - DEFINE_FIELD( m_flTargetFindTime, FIELD_TIME ), - - DEFINE_FIELD( m_flAdmireGlovesAnimTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextFlashlightCheckTime, FIELD_TIME ), - DEFINE_FIELD( m_flFlashlightPowerDrainScale, FIELD_FLOAT ), - DEFINE_FIELD( m_bFlashlightDisabled, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_bUseCappedPhysicsDamageTable, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_hLockedAutoAimEntity, FIELD_EHANDLE ), - - DEFINE_EMBEDDED( m_LowerWeaponTimer ), - DEFINE_EMBEDDED( m_AutoaimTimer ), - - DEFINE_INPUTFUNC( FIELD_FLOAT, "IgnoreFallDamage", InputIgnoreFallDamage ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "IgnoreFallDamageWithoutReset", InputIgnoreFallDamageWithoutReset ), - DEFINE_INPUTFUNC( FIELD_VOID, "OnSquadMemberKilled", OnSquadMemberKilled ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableFlashlight", InputDisableFlashlight ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableFlashlight", InputEnableFlashlight ), - DEFINE_INPUTFUNC( FIELD_VOID, "ForceDropPhysObjects", InputForceDropPhysObjects ), - - DEFINE_SOUNDPATCH( m_sndLeeches ), - DEFINE_SOUNDPATCH( m_sndWaterSplashes ), - - DEFINE_FIELD( m_flArmorReductionTime, FIELD_TIME ), - DEFINE_FIELD( m_iArmorReductionFrom, FIELD_INTEGER ), - - DEFINE_FIELD( m_flTimeUseSuspended, FIELD_TIME ), - - DEFINE_FIELD( m_hLocatorTargetEntity, FIELD_EHANDLE ), - - DEFINE_FIELD( m_flTimeNextLadderHint, FIELD_TIME ), - - //DEFINE_FIELD( m_hPlayerProxy, FIELD_EHANDLE ), //Shut up class check! - -END_DATADESC() - -CHL2_Player::CHL2_Player() -{ - m_nNumMissPositions = 0; - m_pPlayerAISquad = 0; - m_bSprintEnabled = true; - - m_flArmorReductionTime = 0.0f; - m_iArmorReductionFrom = 0; -} - -// -// SUIT POWER DEVICES -// -#define SUITPOWER_CHARGE_RATE 12.5 // 100 units in 8 seconds - -#ifdef HL2MP - CSuitPowerDevice SuitDeviceSprint( bits_SUIT_DEVICE_SPRINT, 25.0f ); // 100 units in 4 seconds -#else - CSuitPowerDevice SuitDeviceSprint( bits_SUIT_DEVICE_SPRINT, 12.5f ); // 100 units in 8 seconds -#endif - -#ifdef HL2_EPISODIC - CSuitPowerDevice SuitDeviceFlashlight( bits_SUIT_DEVICE_FLASHLIGHT, 1.111 ); // 100 units in 90 second -#else - CSuitPowerDevice SuitDeviceFlashlight( bits_SUIT_DEVICE_FLASHLIGHT, 2.222 ); // 100 units in 45 second -#endif -CSuitPowerDevice SuitDeviceBreather( bits_SUIT_DEVICE_BREATHER, 6.7f ); // 100 units in 15 seconds (plus three padded seconds) - - -IMPLEMENT_SERVERCLASS_ST(CHL2_Player, DT_HL2_Player) - SendPropDataTable(SENDINFO_DT(m_HL2Local), &REFERENCE_SEND_TABLE(DT_HL2Local), SendProxy_SendLocalDataTable), - SendPropBool( SENDINFO(m_fIsSprinting) ), -END_SEND_TABLE() - - -void CHL2_Player::Precache( void ) -{ - BaseClass::Precache(); - - PrecacheScriptSound( "HL2Player.SprintNoPower" ); - PrecacheScriptSound( "HL2Player.SprintStart" ); - PrecacheScriptSound( "HL2Player.UseDeny" ); - PrecacheScriptSound( "HL2Player.FlashLightOn" ); - PrecacheScriptSound( "HL2Player.FlashLightOff" ); - PrecacheScriptSound( "HL2Player.PickupWeapon" ); - PrecacheScriptSound( "HL2Player.TrainUse" ); - PrecacheScriptSound( "HL2Player.Use" ); - PrecacheScriptSound( "HL2Player.BurnPain" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHL2_Player::CheckSuitZoom( void ) -{ -//#ifndef _XBOX - //Adrian - No zooming without a suit! - if ( IsSuitEquipped() ) - { - if ( m_afButtonReleased & IN_ZOOM ) - { - StopZooming(); - } - else if ( m_afButtonPressed & IN_ZOOM ) - { - StartZooming(); - } - } -//#endif//_XBOX -} - -void CHL2_Player::EquipSuit( bool bPlayEffects ) -{ - MDLCACHE_CRITICAL_SECTION(); - BaseClass::EquipSuit(); - - m_HL2Local.m_bDisplayReticle = true; - - if ( bPlayEffects == true ) - { - StartAdmireGlovesAnimation(); - } -} - -void CHL2_Player::RemoveSuit( void ) -{ - BaseClass::RemoveSuit(); - - m_HL2Local.m_bDisplayReticle = false; -} - -void CHL2_Player::HandleSpeedChanges( void ) -{ - int buttonsChanged = m_afButtonPressed | m_afButtonReleased; - - bool bCanSprint = CanSprint(); - bool bIsSprinting = IsSprinting(); - bool bWantSprint = ( bCanSprint && IsSuitEquipped() && (m_nButtons & IN_SPEED) ); - if ( bIsSprinting != bWantSprint && (buttonsChanged & IN_SPEED) ) - { - // If someone wants to sprint, make sure they've pressed the button to do so. We want to prevent the - // case where a player can hold down the sprint key and burn tiny bursts of sprint as the suit recharges - // We want a full debounce of the key to resume sprinting after the suit is completely drained - if ( bWantSprint ) - { - if ( sv_stickysprint.GetBool() ) - { - StartAutoSprint(); - } - else - { - StartSprinting(); - } - } - else - { - if ( !sv_stickysprint.GetBool() ) - { - StopSprinting(); - } - // Reset key, so it will be activated post whatever is suppressing it. - m_nButtons &= ~IN_SPEED; - } - } - - bool bIsWalking = IsWalking(); - // have suit, pressing button, not sprinting or ducking - bool bWantWalking; - - if( IsSuitEquipped() ) - { - bWantWalking = (m_nButtons & IN_WALK) && !IsSprinting() && !(m_nButtons & IN_DUCK); - } - else - { - bWantWalking = true; - } - - if( bIsWalking != bWantWalking ) - { - if ( bWantWalking ) - { - StartWalking(); - } - else - { - StopWalking(); - } - } -} - -//----------------------------------------------------------------------------- -// This happens when we powerdown from the mega physcannon to the regular one -//----------------------------------------------------------------------------- -void CHL2_Player::HandleArmorReduction( void ) -{ - if ( m_flArmorReductionTime < gpGlobals->curtime ) - return; - - if ( ArmorValue() <= 0 ) - return; - - float flPercent = 1.0f - (( m_flArmorReductionTime - gpGlobals->curtime ) / ARMOR_DECAY_TIME ); - - int iArmor = Lerp( flPercent, m_iArmorReductionFrom, 0 ); - - SetArmorValue( iArmor ); -} - -//----------------------------------------------------------------------------- -// Purpose: Allow pre-frame adjustments on the player -//----------------------------------------------------------------------------- -void CHL2_Player::PreThink(void) -{ - if ( player_showpredictedposition.GetBool() ) - { - Vector predPos; - - UTIL_PredictedPosition( this, player_showpredictedposition_timestep.GetFloat(), &predPos ); - - NDebugOverlay::Box( predPos, NAI_Hull::Mins( GetHullType() ), NAI_Hull::Maxs( GetHullType() ), 0, 255, 0, 0, 0.01f ); - NDebugOverlay::Line( GetAbsOrigin(), predPos, 0, 255, 0, 0, 0.01f ); - } - -#ifdef HL2_EPISODIC - if( m_hLocatorTargetEntity != NULL ) - { - // Keep track of the entity here, the client will pick up the rest of the work - m_HL2Local.m_vecLocatorOrigin = m_hLocatorTargetEntity->WorldSpaceCenter(); - } - else - { - m_HL2Local.m_vecLocatorOrigin = vec3_invalid; // This tells the client we have no locator target. - } -#endif//HL2_EPISODIC - - // Riding a vehicle? - if ( IsInAVehicle() ) - { - VPROF( "CHL2_Player::PreThink-Vehicle" ); - // make sure we update the client, check for timed damage and update suit even if we are in a vehicle - UpdateClientData(); - CheckTimeBasedDamage(); - - // Allow the suit to recharge when in the vehicle. - SuitPower_Update(); - CheckSuitUpdate(); - CheckSuitZoom(); - - WaterMove(); - return; - } - - // This is an experiment of mine- autojumping! - // only affects you if sv_autojump is nonzero. - if( (GetFlags() & FL_ONGROUND) && sv_autojump.GetFloat() != 0 ) - { - VPROF( "CHL2_Player::PreThink-Autojump" ); - // check autojump - Vector vecCheckDir; - - vecCheckDir = GetAbsVelocity(); - - float flVelocity = VectorNormalize( vecCheckDir ); - - if( flVelocity > 200 ) - { - // Going fast enough to autojump - vecCheckDir = WorldSpaceCenter() + vecCheckDir * 34 - Vector( 0, 0, 16 ); - - trace_t tr; - - UTIL_TraceHull( WorldSpaceCenter() - Vector( 0, 0, 16 ), vecCheckDir, NAI_Hull::Mins(HULL_TINY_CENTERED),NAI_Hull::Maxs(HULL_TINY_CENTERED), MASK_PLAYERSOLID, this, COLLISION_GROUP_PLAYER, &tr ); - - //NDebugOverlay::Line( tr.startpos, tr.endpos, 0,255,0, true, 10 ); - - if( tr.fraction == 1.0 && !tr.startsolid ) - { - // Now trace down! - UTIL_TraceLine( vecCheckDir, vecCheckDir - Vector( 0, 0, 64 ), MASK_PLAYERSOLID, this, COLLISION_GROUP_NONE, &tr ); - - //NDebugOverlay::Line( tr.startpos, tr.endpos, 0,255,0, true, 10 ); - - if( tr.fraction == 1.0 && !tr.startsolid ) - { - // !!!HACKHACK - // I KNOW, I KNOW, this is definitely not the right way to do this, - // but I'm prototyping! (sjb) - Vector vecNewVelocity = GetAbsVelocity(); - vecNewVelocity.z += 250; - SetAbsVelocity( vecNewVelocity ); - } - } - } - } - - VPROF_SCOPE_BEGIN( "CHL2_Player::PreThink-Speed" ); - HandleSpeedChanges(); -#ifdef HL2_EPISODIC - HandleArmorReduction(); -#endif - - if( sv_stickysprint.GetBool() && m_bIsAutoSprinting ) - { - // If we're ducked and not in the air - if( IsDucked() && GetGroundEntity() != NULL ) - { - StopSprinting(); - } - // Stop sprinting if the player lets off the stick for a moment. - else if( GetStickDist() == 0.0f ) - { - if( gpGlobals->curtime > m_fAutoSprintMinTime ) - { - StopSprinting(); - } - } - else - { - // Stop sprinting one half second after the player stops inputting with the move stick. - m_fAutoSprintMinTime = gpGlobals->curtime + 0.5f; - } - } - else if ( IsSprinting() ) - { - // Disable sprint while ducked unless we're in the air (jumping) - if ( IsDucked() && ( GetGroundEntity() != NULL ) ) - { - StopSprinting(); - } - } - - VPROF_SCOPE_END(); - - if ( g_fGameOver || IsPlayerLockedInPlace() ) - return; // finale - - VPROF_SCOPE_BEGIN( "CHL2_Player::PreThink-ItemPreFrame" ); - ItemPreFrame( ); - VPROF_SCOPE_END(); - - VPROF_SCOPE_BEGIN( "CHL2_Player::PreThink-WaterMove" ); - WaterMove(); - VPROF_SCOPE_END(); - - if ( g_pGameRules && g_pGameRules->FAllowFlashlight() ) - m_Local.m_iHideHUD &= ~HIDEHUD_FLASHLIGHT; - else - m_Local.m_iHideHUD |= HIDEHUD_FLASHLIGHT; - - - VPROF_SCOPE_BEGIN( "CHL2_Player::PreThink-CommanderUpdate" ); - CommanderUpdate(); - VPROF_SCOPE_END(); - - // Operate suit accessories and manage power consumption/charge - VPROF_SCOPE_BEGIN( "CHL2_Player::PreThink-SuitPower_Update" ); - SuitPower_Update(); - VPROF_SCOPE_END(); - - // checks if new client data (for HUD and view control) needs to be sent to the client - VPROF_SCOPE_BEGIN( "CHL2_Player::PreThink-UpdateClientData" ); - UpdateClientData(); - VPROF_SCOPE_END(); - - VPROF_SCOPE_BEGIN( "CHL2_Player::PreThink-CheckTimeBasedDamage" ); - CheckTimeBasedDamage(); - VPROF_SCOPE_END(); - - VPROF_SCOPE_BEGIN( "CHL2_Player::PreThink-CheckSuitUpdate" ); - CheckSuitUpdate(); - VPROF_SCOPE_END(); - - VPROF_SCOPE_BEGIN( "CHL2_Player::PreThink-CheckSuitZoom" ); - CheckSuitZoom(); - VPROF_SCOPE_END(); - - if (m_lifeState >= LIFE_DYING) - { - PlayerDeathThink(); - return; - } - -#ifdef HL2_EPISODIC - CheckFlashlight(); -#endif // HL2_EPISODIC - - // So the correct flags get sent to client asap. - // - if ( m_afPhysicsFlags & PFLAG_DIROVERRIDE ) - AddFlag( FL_ONTRAIN ); - else - RemoveFlag( FL_ONTRAIN ); - - // Train speed control - if ( m_afPhysicsFlags & PFLAG_DIROVERRIDE ) - { - CBaseEntity *pTrain = GetGroundEntity(); - float vel; - - if ( pTrain ) - { - if ( !(pTrain->ObjectCaps() & FCAP_DIRECTIONAL_USE) ) - pTrain = NULL; - } - - if ( !pTrain ) - { - if ( GetActiveWeapon() && (GetActiveWeapon()->ObjectCaps() & FCAP_DIRECTIONAL_USE) ) - { - m_iTrain = TRAIN_ACTIVE | TRAIN_NEW; - - if ( m_nButtons & IN_FORWARD ) - { - m_iTrain |= TRAIN_FAST; - } - else if ( m_nButtons & IN_BACK ) - { - m_iTrain |= TRAIN_BACK; - } - else - { - m_iTrain |= TRAIN_NEUTRAL; - } - return; - } - else - { - trace_t trainTrace; - // Maybe this is on the other side of a level transition - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + Vector(0,0,-38), - MASK_PLAYERSOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trainTrace ); - - if ( trainTrace.fraction != 1.0 && trainTrace.m_pEnt ) - pTrain = trainTrace.m_pEnt; - - - if ( !pTrain || !(pTrain->ObjectCaps() & FCAP_DIRECTIONAL_USE) || !pTrain->OnControls(this) ) - { -// Warning( "In train mode with no train!\n" ); - m_afPhysicsFlags &= ~PFLAG_DIROVERRIDE; - m_iTrain = TRAIN_NEW|TRAIN_OFF; - return; - } - } - } - else if ( !( GetFlags() & FL_ONGROUND ) || pTrain->HasSpawnFlags( SF_TRACKTRAIN_NOCONTROL ) || (m_nButtons & (IN_MOVELEFT|IN_MOVERIGHT) ) ) - { - // Turn off the train if you jump, strafe, or the train controls go dead - m_afPhysicsFlags &= ~PFLAG_DIROVERRIDE; - m_iTrain = TRAIN_NEW|TRAIN_OFF; - return; - } - - SetAbsVelocity( vec3_origin ); - vel = 0; - if ( m_afButtonPressed & IN_FORWARD ) - { - vel = 1; - pTrain->Use( this, this, USE_SET, (float)vel ); - } - else if ( m_afButtonPressed & IN_BACK ) - { - vel = -1; - pTrain->Use( this, this, USE_SET, (float)vel ); - } - - if (vel) - { - m_iTrain = TrainSpeed((int)pTrain->m_flSpeed, (int)((CFuncTrackTrain*)pTrain)->GetMaxSpeed()); - m_iTrain |= TRAIN_ACTIVE|TRAIN_NEW; - } - } - else if (m_iTrain & TRAIN_ACTIVE) - { - m_iTrain = TRAIN_NEW; // turn off train - } - - - // - // If we're not on the ground, we're falling. Update our falling velocity. - // - if ( !( GetFlags() & FL_ONGROUND ) ) - { - m_Local.m_flFallVelocity = -GetAbsVelocity().z; - } - - if ( m_afPhysicsFlags & PFLAG_ONBARNACLE ) - { - bool bOnBarnacle = false; - CNPC_Barnacle *pBarnacle = NULL; - do - { - // FIXME: Not a good or fast solution, but maybe it will catch the bug! - pBarnacle = (CNPC_Barnacle*)gEntList.FindEntityByClassname( pBarnacle, "npc_barnacle" ); - if ( pBarnacle ) - { - if ( pBarnacle->GetEnemy() == this ) - { - bOnBarnacle = true; - } - } - } while ( pBarnacle ); - - if ( !bOnBarnacle ) - { - Warning( "Attached to barnacle?\n" ); - Assert( 0 ); - m_afPhysicsFlags &= ~PFLAG_ONBARNACLE; - } - else - { - SetAbsVelocity( vec3_origin ); - } - } - // StudioFrameAdvance( );//!!!HACKHACK!!! Can't be hit by traceline when not animating? - - // Update weapon's ready status - UpdateWeaponPosture(); - - // Disallow shooting while zooming - if ( IsX360() ) - { - if ( IsZooming() ) - { - if( GetActiveWeapon() && !GetActiveWeapon()->IsWeaponZoomed() ) - { - // If not zoomed because of the weapon itself, do not attack. - m_nButtons &= ~(IN_ATTACK|IN_ATTACK2); - } - } - } - else - { - if ( m_nButtons & IN_ZOOM ) - { - //FIXME: Held weapons like the grenade get sad when this happens - #ifdef HL2_EPISODIC - // Episodic allows players to zoom while using a func_tank - CBaseCombatWeapon* pWep = GetActiveWeapon(); - if ( !m_hUseEntity || ( pWep && pWep->IsWeaponVisible() ) ) - #endif - m_nButtons &= ~(IN_ATTACK|IN_ATTACK2); - } - } -} - -void CHL2_Player::PostThink( void ) -{ - BaseClass::PostThink(); - - if ( !g_fGameOver && !IsPlayerLockedInPlace() && IsAlive() ) - { - HandleAdmireGlovesAnimation(); - } -} - -void CHL2_Player::StartAdmireGlovesAnimation( void ) -{ - MDLCACHE_CRITICAL_SECTION(); - CBaseViewModel *vm = GetViewModel( 0 ); - - if ( vm && !GetActiveWeapon() ) - { - vm->SetWeaponModel( "models/weapons/v_hands.mdl", NULL ); - ShowViewModel( true ); - - int idealSequence = vm->SelectWeightedSequence( ACT_VM_IDLE ); - - if ( idealSequence >= 0 ) - { - vm->SendViewModelMatchingSequence( idealSequence ); - m_flAdmireGlovesAnimTime = gpGlobals->curtime + vm->SequenceDuration( idealSequence ); - } - } -} - -void CHL2_Player::HandleAdmireGlovesAnimation( void ) -{ - CBaseViewModel *pVM = GetViewModel(); - - if ( pVM && pVM->GetOwningWeapon() == NULL ) - { - if ( m_flAdmireGlovesAnimTime != 0.0 ) - { - if ( m_flAdmireGlovesAnimTime > gpGlobals->curtime ) - { - pVM->m_flPlaybackRate = 1.0f; - pVM->StudioFrameAdvance( ); - } - else if ( m_flAdmireGlovesAnimTime < gpGlobals->curtime ) - { - m_flAdmireGlovesAnimTime = 0.0f; - pVM->SetWeaponModel( NULL, NULL ); - } - } - } - else - m_flAdmireGlovesAnimTime = 0.0f; -} - -#define HL2PLAYER_RELOADGAME_ATTACK_DELAY 1.0f - -void CHL2_Player::Activate( void ) -{ - BaseClass::Activate(); - InitSprinting(); - -#ifdef HL2_EPISODIC - - // Delay attacks by 1 second after loading a game. - if ( GetActiveWeapon() ) - { - float flRemaining = GetActiveWeapon()->m_flNextPrimaryAttack - gpGlobals->curtime; - - if ( flRemaining < HL2PLAYER_RELOADGAME_ATTACK_DELAY ) - { - GetActiveWeapon()->m_flNextPrimaryAttack = gpGlobals->curtime + HL2PLAYER_RELOADGAME_ATTACK_DELAY; - } - - flRemaining = GetActiveWeapon()->m_flNextSecondaryAttack - gpGlobals->curtime; - - if ( flRemaining < HL2PLAYER_RELOADGAME_ATTACK_DELAY ) - { - GetActiveWeapon()->m_flNextSecondaryAttack = gpGlobals->curtime + HL2PLAYER_RELOADGAME_ATTACK_DELAY; - } - } - -#endif - - GetPlayerProxy(); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -Class_T CHL2_Player::Classify ( void ) -{ - // If player controlling another entity? If so, return this class - if (m_nControlClass != CLASS_NONE) - { - return m_nControlClass; - } - else - { - if(IsInAVehicle()) - { - IServerVehicle *pVehicle = GetVehicle(); - return pVehicle->ClassifyPassenger( this, CLASS_PLAYER ); - } - else - { - return CLASS_PLAYER; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: This is a generic function (to be implemented by sub-classes) to -// handle specific interactions between different types of characters -// (For example the barnacle grabbing an NPC) -// Input : Constant for the type of interaction -// Output : true - if sub-class has a response for the interaction -// false - if sub-class has no response -//----------------------------------------------------------------------------- -bool CHL2_Player::HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt) -{ - if ( interactionType == g_interactionBarnacleVictimDangle ) - return false; - - if (interactionType == g_interactionBarnacleVictimReleased) - { - m_afPhysicsFlags &= ~PFLAG_ONBARNACLE; - SetMoveType( MOVETYPE_WALK ); - return true; - } - else if (interactionType == g_interactionBarnacleVictimGrab) - { -#ifdef HL2_EPISODIC - CNPC_Alyx *pAlyx = CNPC_Alyx::GetAlyx(); - if ( pAlyx ) - { - // Make Alyx totally hate this barnacle so that she saves the player. - int priority; - - priority = pAlyx->IRelationPriority(sourceEnt); - pAlyx->AddEntityRelationship( sourceEnt, D_HT, priority + 5 ); - } -#endif//HL2_EPISODIC - - m_afPhysicsFlags |= PFLAG_ONBARNACLE; - ClearUseEntity(); - return true; - } - return false; -} - - -void CHL2_Player::PlayerRunCommand(CUserCmd *ucmd, IMoveHelper *moveHelper) -{ - // Handle FL_FROZEN. - if ( m_afPhysicsFlags & PFLAG_ONBARNACLE ) - { - ucmd->forwardmove = 0; - ucmd->sidemove = 0; - ucmd->upmove = 0; - ucmd->buttons &= ~IN_USE; - } - - // Can't use stuff while dead - if ( IsDead() ) - { - ucmd->buttons &= ~IN_USE; - } - - //Update our movement information - if ( ( ucmd->forwardmove != 0 ) || ( ucmd->sidemove != 0 ) || ( ucmd->upmove != 0 ) ) - { - m_flIdleTime -= TICK_INTERVAL * 2.0f; - - if ( m_flIdleTime < 0.0f ) - { - m_flIdleTime = 0.0f; - } - - m_flMoveTime += TICK_INTERVAL; - - if ( m_flMoveTime > 4.0f ) - { - m_flMoveTime = 4.0f; - } - } - else - { - m_flIdleTime += TICK_INTERVAL; - - if ( m_flIdleTime > 4.0f ) - { - m_flIdleTime = 4.0f; - } - - m_flMoveTime -= TICK_INTERVAL * 2.0f; - - if ( m_flMoveTime < 0.0f ) - { - m_flMoveTime = 0.0f; - } - } - - //Msg("Player time: [ACTIVE: %f]\t[IDLE: %f]\n", m_flMoveTime, m_flIdleTime ); - - BaseClass::PlayerRunCommand( ucmd, moveHelper ); -} - -//----------------------------------------------------------------------------- -// Purpose: Sets HL2 specific defaults. -//----------------------------------------------------------------------------- -void CHL2_Player::Spawn(void) -{ - -#ifndef HL2MP -#ifndef PORTAL - SetModel( "models/player.mdl" ); -#endif -#endif - - BaseClass::Spawn(); - - // - // Our player movement speed is set once here. This will override the cl_xxxx - // cvars unless they are set to be lower than this. - // - //m_flMaxspeed = 320; - - if ( !IsSuitEquipped() ) - StartWalking(); - - SuitPower_SetCharge( 100 ); - - m_Local.m_iHideHUD |= HIDEHUD_CHAT; - - m_pPlayerAISquad = g_AI_SquadManager.FindCreateSquad(AllocPooledString(PLAYER_SQUADNAME)); - - InitSprinting(); - - // Setup our flashlight values -#ifdef HL2_EPISODIC - m_HL2Local.m_flFlashBattery = 100.0f; -#endif - - GetPlayerProxy(); - - SetFlashlightPowerDrainScale( 1.0f ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHL2_Player::UpdateLocatorPosition( const Vector &vecPosition ) -{ -#ifdef HL2_EPISODIC - m_HL2Local.m_vecLocatorOrigin = vecPosition; -#endif//HL2_EPISODIC -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHL2_Player::InitSprinting( void ) -{ - StopSprinting(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns whether or not we are allowed to sprint now. -//----------------------------------------------------------------------------- -bool CHL2_Player::CanSprint() -{ - return ( m_bSprintEnabled && // Only if sprint is enabled - !IsWalking() && // Not if we're walking - !( m_Local.m_bDucked && !m_Local.m_bDucking ) && // Nor if we're ducking - (GetWaterLevel() != 3) && // Certainly not underwater - (GlobalEntity_GetState("suit_no_sprint") != GLOBAL_ON) ); // Out of the question without the sprint module -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHL2_Player::StartAutoSprint() -{ - if( IsSprinting() ) - { - StopSprinting(); - } - else - { - StartSprinting(); - m_bIsAutoSprinting = true; - m_fAutoSprintMinTime = gpGlobals->curtime + 1.5f; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHL2_Player::StartSprinting( void ) -{ - if( m_HL2Local.m_flSuitPower < 10 ) - { - // Don't sprint unless there's a reasonable - // amount of suit power. - - // debounce the button for sound playing - if ( m_afButtonPressed & IN_SPEED ) - { - CPASAttenuationFilter filter( this ); - filter.UsePredictionRules(); - EmitSound( filter, entindex(), "HL2Player.SprintNoPower" ); - } - return; - } - - if( !SuitPower_AddDevice( SuitDeviceSprint ) ) - return; - - CPASAttenuationFilter filter( this ); - filter.UsePredictionRules(); - EmitSound( filter, entindex(), "HL2Player.SprintStart" ); - - SetMaxSpeed( HL2_SPRINT_SPEED ); - m_fIsSprinting = true; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHL2_Player::StopSprinting( void ) -{ - if ( m_HL2Local.m_bitsActiveDevices & SuitDeviceSprint.GetDeviceID() ) - { - SuitPower_RemoveDevice( SuitDeviceSprint ); - } - - if( IsSuitEquipped() ) - { - SetMaxSpeed( HL2_NORM_SPEED ); - } - else - { - SetMaxSpeed( HL2_WALK_SPEED ); - } - - m_fIsSprinting = false; - - if ( sv_stickysprint.GetBool() ) - { - m_bIsAutoSprinting = false; - m_fAutoSprintMinTime = 0.0f; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Called to disable and enable sprint due to temporary circumstances: -// - Carrying a heavy object with the physcannon -//----------------------------------------------------------------------------- -void CHL2_Player::EnableSprint( bool bEnable ) -{ - if ( !bEnable && IsSprinting() ) - { - StopSprinting(); - } - - m_bSprintEnabled = bEnable; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHL2_Player::StartWalking( void ) -{ - SetMaxSpeed( HL2_WALK_SPEED ); - m_fIsWalking = true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHL2_Player::StopWalking( void ) -{ - SetMaxSpeed( HL2_NORM_SPEED ); - m_fIsWalking = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CHL2_Player::CanZoom( CBaseEntity *pRequester ) -{ - if ( IsZooming() ) - return false; - - //Check our weapon - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHL2_Player::ToggleZoom(void) -{ - if( IsZooming() ) - { - StopZooming(); - } - else - { - StartZooming(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: +zoom suit zoom -//----------------------------------------------------------------------------- -void CHL2_Player::StartZooming( void ) -{ - int iFOV = 25; - if ( SetFOV( this, iFOV, 0.4f ) ) - { - m_HL2Local.m_bZooming = true; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHL2_Player::StopZooming( void ) -{ - int iFOV = (int)GetZoomOwnerDesiredFOV( m_hZoomOwner ); - - if ( SetFOV( this, iFOV, 0.2f ) ) - { - m_HL2Local.m_bZooming = false; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CHL2_Player::IsZooming( void ) -{ - if ( m_hZoomOwner != NULL ) - return true; - - return false; -} - -class CPhysicsPlayerCallback : public IPhysicsPlayerControllerEvent -{ -public: - int ShouldMoveTo( IPhysicsObject *pObject, const Vector &position ) - { - CHL2_Player *pPlayer = (CHL2_Player *)pObject->GetGameData(); - if ( pPlayer ) - { - if ( pPlayer->TouchedPhysics() ) - { - return 0; - } - } - return 1; - } -}; - -static CPhysicsPlayerCallback playerCallback; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHL2_Player::InitVCollision( const Vector &vecAbsOrigin, const Vector &vecAbsVelocity ) -{ - BaseClass::InitVCollision( vecAbsOrigin, vecAbsVelocity ); - - // Setup the HL2 specific callback. - IPhysicsPlayerController *pPlayerController = GetPhysicsController(); - if ( pPlayerController ) - { - pPlayerController->SetEventHandler( &playerCallback ); - } -} - - -CHL2_Player::~CHL2_Player( void ) -{ -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -bool CHL2_Player::CommanderFindGoal( commandgoal_t *pGoal ) -{ - CAI_BaseNPC *pAllyNpc; - trace_t tr; - Vector vecTarget; - Vector forward; - - EyeVectors( &forward ); - - //--------------------------------- - // MASK_SHOT on purpose! So that you don't hit the invisible hulls of the NPCs. - CTraceFilterSkipTwoEntities filter( this, PhysCannonGetHeldEntity( GetActiveWeapon() ), COLLISION_GROUP_INTERACTIVE_DEBRIS ); - - UTIL_TraceLine( EyePosition(), EyePosition() + forward * MAX_COORD_RANGE, MASK_SHOT, &filter, &tr ); - - if( !tr.DidHitWorld() ) - { - CUtlVector Allies; - AISquadIter_t iter; - for ( pAllyNpc = m_pPlayerAISquad->GetFirstMember(&iter); pAllyNpc; pAllyNpc = m_pPlayerAISquad->GetNextMember(&iter) ) - { - if ( pAllyNpc->IsCommandable() ) - Allies.AddToTail( pAllyNpc ); - } - - for( int i = 0 ; i < Allies.Count() ; i++ ) - { - if( Allies[ i ]->IsValidCommandTarget( tr.m_pEnt ) ) - { - pGoal->m_pGoalEntity = tr.m_pEnt; - return true; - } - } - } - - if( tr.fraction == 1.0 || (tr.surface.flags & SURF_SKY) ) - { - // Move commands invalid against skybox. - pGoal->m_vecGoalLocation = tr.endpos; - return false; - } - - if ( tr.m_pEnt->IsNPC() && ((CAI_BaseNPC *)(tr.m_pEnt))->IsCommandable() ) - { - pGoal->m_vecGoalLocation = tr.m_pEnt->GetAbsOrigin(); - } - else - { - vecTarget = tr.endpos; - - Vector mins( -16, -16, 0 ); - Vector maxs( 16, 16, 0 ); - - // Back up from whatever we hit so that there's enough space at the - // target location for a bounding box. - // Now trace down. - //UTIL_TraceLine( vecTarget, vecTarget - Vector( 0, 0, 8192 ), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - UTIL_TraceHull( vecTarget + tr.plane.normal * 24, - vecTarget - Vector( 0, 0, 8192 ), - mins, - maxs, - MASK_SOLID_BRUSHONLY, - this, - COLLISION_GROUP_NONE, - &tr ); - - - if ( !tr.startsolid ) - pGoal->m_vecGoalLocation = tr.endpos; - else - pGoal->m_vecGoalLocation = vecTarget; - } - - pAllyNpc = GetSquadCommandRepresentative(); - if ( !pAllyNpc ) - return false; - - vecTarget = pGoal->m_vecGoalLocation; - if ( !pAllyNpc->FindNearestValidGoalPos( vecTarget, &pGoal->m_vecGoalLocation ) ) - return false; - - return ( ( vecTarget - pGoal->m_vecGoalLocation ).LengthSqr() < Square( 15*12 ) ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CAI_BaseNPC *CHL2_Player::GetSquadCommandRepresentative() -{ - if ( m_pPlayerAISquad != NULL ) - { - CAI_BaseNPC *pAllyNpc = m_pPlayerAISquad->GetFirstMember(); - - if ( pAllyNpc ) - { - return pAllyNpc->GetSquadCommandRepresentative(); - } - } - - return NULL; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CHL2_Player::GetNumSquadCommandables() -{ - AISquadIter_t iter; - int c = 0; - for ( CAI_BaseNPC *pAllyNpc = m_pPlayerAISquad->GetFirstMember(&iter); pAllyNpc; pAllyNpc = m_pPlayerAISquad->GetNextMember(&iter) ) - { - if ( pAllyNpc->IsCommandable() ) - c++; - } - return c; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CHL2_Player::GetNumSquadCommandableMedics() -{ - AISquadIter_t iter; - int c = 0; - for ( CAI_BaseNPC *pAllyNpc = m_pPlayerAISquad->GetFirstMember(&iter); pAllyNpc; pAllyNpc = m_pPlayerAISquad->GetNextMember(&iter) ) - { - if ( pAllyNpc->IsCommandable() && pAllyNpc->IsMedic() ) - c++; - } - return c; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHL2_Player::CommanderUpdate() -{ - CAI_BaseNPC *pCommandRepresentative = GetSquadCommandRepresentative(); - bool bFollowMode = false; - if ( pCommandRepresentative ) - { - bFollowMode = ( pCommandRepresentative->GetCommandGoal() == vec3_invalid ); - - // set the variables for network transmission (to show on the hud) - m_HL2Local.m_iSquadMemberCount = GetNumSquadCommandables(); - m_HL2Local.m_iSquadMedicCount = GetNumSquadCommandableMedics(); - m_HL2Local.m_fSquadInFollowMode = bFollowMode; - - // debugging code for displaying extra squad indicators - /* - char *pszMoving = ""; - AISquadIter_t iter; - for ( CAI_BaseNPC *pAllyNpc = m_pPlayerAISquad->GetFirstMember(&iter); pAllyNpc; pAllyNpc = m_pPlayerAISquad->GetNextMember(&iter) ) - { - if ( pAllyNpc->IsCommandMoving() ) - { - pszMoving = "<-"; - break; - } - } - - NDebugOverlay::ScreenText( - 0.932, 0.919, - CFmtStr( "%d|%c%s", GetNumSquadCommandables(), ( bFollowMode ) ? 'F' : 'S', pszMoving ), - 255, 128, 0, 128, - 0 ); - */ - - } - else - { - m_HL2Local.m_iSquadMemberCount = 0; - m_HL2Local.m_iSquadMedicCount = 0; - m_HL2Local.m_fSquadInFollowMode = true; - } - - if ( m_QueuedCommand != CC_NONE && ( m_QueuedCommand == CC_FOLLOW || gpGlobals->realtime - m_RealTimeLastSquadCommand >= player_squad_double_tap_time.GetFloat() ) ) - { - CommanderExecute( m_QueuedCommand ); - m_QueuedCommand = CC_NONE; - } - else if ( !bFollowMode && pCommandRepresentative && m_CommanderUpdateTimer.Expired() && player_squad_transient_commands.GetBool() ) - { - m_CommanderUpdateTimer.Set(2.5); - - if ( pCommandRepresentative->ShouldAutoSummon() ) - CommanderExecute( CC_FOLLOW ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// bHandled - indicates whether to continue delivering this order to -// all allies. Allows us to stop delivering certain types of orders once we find -// a suitable candidate. (like picking up a single weapon. We don't wish for -// all allies to respond and try to pick up one weapon). -//----------------------------------------------------------------------------- -bool CHL2_Player::CommanderExecuteOne( CAI_BaseNPC *pNpc, const commandgoal_t &goal, CAI_BaseNPC **Allies, int numAllies ) -{ - if ( goal.m_pGoalEntity ) - { - return pNpc->TargetOrder( goal.m_pGoalEntity, Allies, numAllies ); - } - else if ( pNpc->IsInPlayerSquad() ) - { - pNpc->MoveOrder( goal.m_vecGoalLocation, Allies, numAllies ); - } - - return true; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CHL2_Player::CommanderExecute( CommanderCommand_t command ) -{ - CAI_BaseNPC *pPlayerSquadLeader = GetSquadCommandRepresentative(); - - if ( !pPlayerSquadLeader ) - { - EmitSound( "HL2Player.UseDeny" ); - return; - } - - int i; - CUtlVector Allies; - commandgoal_t goal; - - if ( command == CC_TOGGLE ) - { - if ( pPlayerSquadLeader->GetCommandGoal() != vec3_invalid ) - command = CC_FOLLOW; - else - command = CC_SEND; - } - else - { - if ( command == CC_FOLLOW && pPlayerSquadLeader->GetCommandGoal() == vec3_invalid ) - return; - } - - if ( command == CC_FOLLOW ) - { - goal.m_pGoalEntity = this; - goal.m_vecGoalLocation = vec3_invalid; - } - else - { - goal.m_pGoalEntity = NULL; - goal.m_vecGoalLocation = vec3_invalid; - - // Find a goal for ourselves. - if( !CommanderFindGoal( &goal ) ) - { - EmitSound( "HL2Player.UseDeny" ); - return; // just keep following - } - } - -#ifdef _DEBUG - if( goal.m_pGoalEntity == NULL && goal.m_vecGoalLocation == vec3_invalid ) - { - DevMsg( 1, "**ERROR: Someone sent an invalid goal to CommanderExecute!\n" ); - } -#endif // _DEBUG - - AISquadIter_t iter; - for ( CAI_BaseNPC *pAllyNpc = m_pPlayerAISquad->GetFirstMember(&iter); pAllyNpc; pAllyNpc = m_pPlayerAISquad->GetNextMember(&iter) ) - { - if ( pAllyNpc->IsCommandable() ) - Allies.AddToTail( pAllyNpc ); - } - - //--------------------------------- - // If the trace hits an NPC, send all ally NPCs a "target" order. Always - // goes to targeted one first -#ifdef DEBUG - int nAIs = g_AI_Manager.NumAIs(); -#endif - CAI_BaseNPC * pTargetNpc = (goal.m_pGoalEntity) ? goal.m_pGoalEntity->MyNPCPointer() : NULL; - - bool bHandled = false; - if( pTargetNpc ) - { - bHandled = !CommanderExecuteOne( pTargetNpc, goal, Allies.Base(), Allies.Count() ); - } - - for ( i = 0; !bHandled && i < Allies.Count(); i++ ) - { - if ( Allies[i] != pTargetNpc && Allies[i]->IsPlayerAlly() ) - { - bHandled = !CommanderExecuteOne( Allies[i], goal, Allies.Base(), Allies.Count() ); - } - Assert( nAIs == g_AI_Manager.NumAIs() ); // not coded to support mutating set of NPCs - } -} - -//----------------------------------------------------------------------------- -// Enter/exit commander mode, manage ally selection. -//----------------------------------------------------------------------------- -void CHL2_Player::CommanderMode() -{ - float commandInterval = gpGlobals->realtime - m_RealTimeLastSquadCommand; - m_RealTimeLastSquadCommand = gpGlobals->realtime; - if ( commandInterval < player_squad_double_tap_time.GetFloat() ) - { - m_QueuedCommand = CC_FOLLOW; - } - else - { - m_QueuedCommand = (player_squad_transient_commands.GetBool()) ? CC_SEND : CC_TOGGLE; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iImpulse - -//----------------------------------------------------------------------------- -void CHL2_Player::CheatImpulseCommands( int iImpulse ) -{ - switch( iImpulse ) - { - case 50: - { - CommanderMode(); - break; - } - - case 51: - { - // Cheat to create a dynamic resupply item - Vector vecForward; - AngleVectors( EyeAngles(), &vecForward ); - CBaseEntity *pItem = (CBaseEntity *)CreateEntityByName( "item_dynamic_resupply" ); - if ( pItem ) - { - Vector vecOrigin = GetAbsOrigin() + vecForward * 256 + Vector(0,0,64); - QAngle vecAngles( 0, GetAbsAngles().y - 90, 0 ); - pItem->SetAbsOrigin( vecOrigin ); - pItem->SetAbsAngles( vecAngles ); - pItem->KeyValue( "targetname", "resupply" ); - pItem->Spawn(); - pItem->Activate(); - } - break; - } - - case 52: - { - // Rangefinder - trace_t tr; - UTIL_TraceLine( EyePosition(), EyePosition() + EyeDirection3D() * MAX_COORD_RANGE, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - if( tr.fraction != 1.0 ) - { - float flDist = (tr.startpos - tr.endpos).Length(); - float flDist2D = (tr.startpos - tr.endpos).Length2D(); - DevMsg( 1,"\nStartPos: %.4f %.4f %.4f --- EndPos: %.4f %.4f %.4f\n", tr.startpos.x,tr.startpos.y,tr.startpos.z,tr.endpos.x,tr.endpos.y,tr.endpos.z ); - DevMsg( 1,"3D Distance: %.4f units (%.2f feet) --- 2D Distance: %.4f units (%.2f feet)\n", flDist, flDist / 12.0, flDist2D, flDist2D / 12.0 ); - } - - break; - } - - default: - BaseClass::CheatImpulseCommands( iImpulse ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHL2_Player::SetupVisibility( CBaseEntity *pViewEntity, unsigned char *pvs, int pvssize ) -{ - BaseClass::SetupVisibility( pViewEntity, pvs, pvssize ); - - int area = pViewEntity ? pViewEntity->NetworkProp()->AreaNum() : NetworkProp()->AreaNum(); - PointCameraSetupVisibility( this, area, pvs, pvssize ); - - // If the intro script is playing, we want to get it's visibility points - if ( g_hIntroScript ) - { - Vector vecOrigin; - CBaseEntity *pCamera; - if ( g_hIntroScript->GetIncludedPVSOrigin( &vecOrigin, &pCamera ) ) - { - // If it's a point camera, turn it on - CPointCamera *pPointCamera = dynamic_cast< CPointCamera* >(pCamera); - if ( pPointCamera ) - { - pPointCamera->SetActive( true ); - } - engine->AddOriginToPVS( vecOrigin ); - } - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHL2_Player::SuitPower_Update( void ) -{ - if( SuitPower_ShouldRecharge() ) - { - SuitPower_Charge( SUITPOWER_CHARGE_RATE * gpGlobals->frametime ); - } - else if( m_HL2Local.m_bitsActiveDevices ) - { - float flPowerLoad = m_flSuitPowerLoad; - - //Since stickysprint quickly shuts off sprint if it isn't being used, this isn't an issue. - if ( !sv_stickysprint.GetBool() ) - { - if( SuitPower_IsDeviceActive(SuitDeviceSprint) ) - { - if( !fabs(GetAbsVelocity().x) && !fabs(GetAbsVelocity().y) ) - { - // If player's not moving, don't drain sprint juice. - flPowerLoad -= SuitDeviceSprint.GetDeviceDrainRate(); - } - } - } - - if( SuitPower_IsDeviceActive(SuitDeviceFlashlight) ) - { - float factor; - - factor = 1.0f / m_flFlashlightPowerDrainScale; - - flPowerLoad -= ( SuitDeviceFlashlight.GetDeviceDrainRate() * (1.0f - factor) ); - } - - if( !SuitPower_Drain( flPowerLoad * gpGlobals->frametime ) ) - { - // TURN OFF ALL DEVICES!! - if( IsSprinting() ) - { - StopSprinting(); - } - - if ( Flashlight_UseLegacyVersion() ) - { - if( FlashlightIsOn() ) - { -#ifndef HL2MP - FlashlightTurnOff(); -#endif - } - } - } - - if ( Flashlight_UseLegacyVersion() ) - { - // turn off flashlight a little bit after it hits below one aux power notch (5%) - if( m_HL2Local.m_flSuitPower < 4.8f && FlashlightIsOn() ) - { -#ifndef HL2MP - FlashlightTurnOff(); -#endif - } - } - } -} - - -//----------------------------------------------------------------------------- -// Charge battery fully, turn off all devices. -//----------------------------------------------------------------------------- -void CHL2_Player::SuitPower_Initialize( void ) -{ - m_HL2Local.m_bitsActiveDevices = 0x00000000; - m_HL2Local.m_flSuitPower = 100.0; - m_flSuitPowerLoad = 0.0; -} - - -//----------------------------------------------------------------------------- -// Purpose: Interface to drain power from the suit's power supply. -// Input: Amount of charge to remove (expressed as percentage of full charge) -// Output: Returns TRUE if successful, FALSE if not enough power available. -//----------------------------------------------------------------------------- -bool CHL2_Player::SuitPower_Drain( float flPower ) -{ - // Suitpower cheat on? - if ( sv_infinite_aux_power.GetBool() ) - return true; - - m_HL2Local.m_flSuitPower -= flPower; - - if( m_HL2Local.m_flSuitPower < 0.0 ) - { - // Power is depleted! - // Clamp and fail - m_HL2Local.m_flSuitPower = 0.0; - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Interface to add power to the suit's power supply -// Input: Amount of charge to add -//----------------------------------------------------------------------------- -void CHL2_Player::SuitPower_Charge( float flPower ) -{ - m_HL2Local.m_flSuitPower += flPower; - - if( m_HL2Local.m_flSuitPower > 100.0 ) - { - // Full charge, clamp. - m_HL2Local.m_flSuitPower = 100.0; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CHL2_Player::SuitPower_IsDeviceActive( const CSuitPowerDevice &device ) -{ - return (m_HL2Local.m_bitsActiveDevices & device.GetDeviceID()) != 0; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CHL2_Player::SuitPower_AddDevice( const CSuitPowerDevice &device ) -{ - // Make sure this device is NOT active!! - if( m_HL2Local.m_bitsActiveDevices & device.GetDeviceID() ) - return false; - - if( !IsSuitEquipped() ) - return false; - - m_HL2Local.m_bitsActiveDevices |= device.GetDeviceID(); - m_flSuitPowerLoad += device.GetDeviceDrainRate(); - return true; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CHL2_Player::SuitPower_RemoveDevice( const CSuitPowerDevice &device ) -{ - // Make sure this device is active!! - if( ! (m_HL2Local.m_bitsActiveDevices & device.GetDeviceID()) ) - return false; - - if( !IsSuitEquipped() ) - return false; - - // Take a little bit of suit power when you disable a device. If the device is shutting off - // because the battery is drained, no harm done, the battery charge cannot go below 0. - // This code in combination with the delay before the suit can start recharging are a defense - // against exploits where the player could rapidly tap sprint and never run out of power. - SuitPower_Drain( device.GetDeviceDrainRate() * 0.1f ); - - m_HL2Local.m_bitsActiveDevices &= ~device.GetDeviceID(); - m_flSuitPowerLoad -= device.GetDeviceDrainRate(); - - if( m_HL2Local.m_bitsActiveDevices == 0x00000000 ) - { - // With this device turned off, we can set this timer which tells us when the - // suit power system entered a no-load state. - m_flTimeAllSuitDevicesOff = gpGlobals->curtime; - } - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -#define SUITPOWER_BEGIN_RECHARGE_DELAY 0.5f -bool CHL2_Player::SuitPower_ShouldRecharge( void ) -{ - // Make sure all devices are off. - if( m_HL2Local.m_bitsActiveDevices != 0x00000000 ) - return false; - - // Is the system fully charged? - if( m_HL2Local.m_flSuitPower >= 100.0f ) - return false; - - // Has the system been in a no-load state for long enough - // to begin recharging? - if( gpGlobals->curtime < m_flTimeAllSuitDevicesOff + SUITPOWER_BEGIN_RECHARGE_DELAY ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -ConVar sk_battery( "sk_battery","0" ); - -bool CHL2_Player::ApplyBattery( float powerMultiplier ) -{ - const float MAX_NORMAL_BATTERY = 100; - if ((ArmorValue() < MAX_NORMAL_BATTERY) && IsSuitEquipped()) - { - int pct; - char szcharge[64]; - - IncrementArmorValue( (int)(sk_battery.GetFloat() * powerMultiplier), (int)MAX_NORMAL_BATTERY ); - - CPASAttenuationFilter filter( this, "ItemBattery.Touch" ); - EmitSound( filter, entindex(), "ItemBattery.Touch" ); - - CSingleUserRecipientFilter user( this ); - user.MakeReliable(); - - UserMessageBegin( user, "ItemPickup" ); - WRITE_STRING( "item_battery" ); - MessageEnd(); - - - // Suit reports new power level - // For some reason this wasn't working in release build -- round it. - pct = (int)( (float)(ArmorValue() * 100.0) * (1.0/MAX_NORMAL_BATTERY) + 0.5); - pct = (pct / 5); - if (pct > 0) - pct--; - - Q_snprintf( szcharge,sizeof(szcharge),"!HEV_%1dP", pct ); - - //UTIL_EmitSoundSuit(edict(), szcharge); - //SetSuitUpdate(szcharge, FALSE, SUIT_NEXT_IN_30SEC); - return true; - } - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CHL2_Player::FlashlightIsOn( void ) -{ - return IsEffectActive( EF_DIMLIGHT ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHL2_Player::FlashlightTurnOn( void ) -{ - if( m_bFlashlightDisabled ) - return; - - if ( Flashlight_UseLegacyVersion() ) - { - if( !SuitPower_AddDevice( SuitDeviceFlashlight ) ) - return; - } -#ifdef HL2_DLL - if( !IsSuitEquipped() ) - return; -#endif - - AddEffects( EF_DIMLIGHT ); - EmitSound( "HL2Player.FlashLightOn" ); - - variant_t flashlighton; - flashlighton.SetFloat( m_HL2Local.m_flSuitPower / 100.0f ); - FirePlayerProxyOutput( "OnFlashlightOn", flashlighton, this, this ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHL2_Player::FlashlightTurnOff( void ) -{ - if ( Flashlight_UseLegacyVersion() ) - { - if( !SuitPower_RemoveDevice( SuitDeviceFlashlight ) ) - return; - } - - RemoveEffects( EF_DIMLIGHT ); - EmitSound( "HL2Player.FlashLightOff" ); - - variant_t flashlightoff; - flashlightoff.SetFloat( m_HL2Local.m_flSuitPower / 100.0f ); - FirePlayerProxyOutput( "OnFlashlightOff", flashlightoff, this, this ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -#define FLASHLIGHT_RANGE Square(600) -bool CHL2_Player::IsIlluminatedByFlashlight( CBaseEntity *pEntity, float *flReturnDot ) -{ - if( !FlashlightIsOn() ) - return false; - - if( pEntity->Classify() == CLASS_BARNACLE && pEntity->GetEnemy() == this ) - { - // As long as my flashlight is on, the barnacle that's pulling me in is considered illuminated. - // This is because players often shine their flashlights at Alyx when they are in a barnacle's - // grasp, and wonder why Alyx isn't helping. Alyx isn't helping because the light isn't pointed - // at the barnacle. This will allow Alyx to see the barnacle no matter which way the light is pointed. - return true; - } - - // Within 50 feet? - float flDistSqr = GetAbsOrigin().DistToSqr(pEntity->GetAbsOrigin()); - if( flDistSqr > FLASHLIGHT_RANGE ) - return false; - - // Within 45 degrees? - Vector vecSpot = pEntity->WorldSpaceCenter(); - Vector los; - - // If the eyeposition is too close, move it back. Solves problems - // caused by the player being too close the target. - if ( flDistSqr < (128 * 128) ) - { - Vector vecForward; - EyeVectors( &vecForward ); - Vector vecMovedEyePos = EyePosition() - (vecForward * 128); - los = ( vecSpot - vecMovedEyePos ); - } - else - { - los = ( vecSpot - EyePosition() ); - } - - VectorNormalize( los ); - Vector facingDir = EyeDirection3D( ); - float flDot = DotProduct( los, facingDir ); - - if ( flReturnDot ) - { - *flReturnDot = flDot; - } - - if ( flDot < 0.92387f ) - return false; - - if( !FVisible(pEntity) ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Let NPCs know when the flashlight is trained on them -//----------------------------------------------------------------------------- -void CHL2_Player::CheckFlashlight( void ) -{ - if ( !FlashlightIsOn() ) - return; - - if ( m_flNextFlashlightCheckTime > gpGlobals->curtime ) - return; - m_flNextFlashlightCheckTime = gpGlobals->curtime + FLASHLIGHT_NPC_CHECK_INTERVAL; - - // Loop through NPCs looking for illuminated ones - for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - CAI_BaseNPC *pNPC = g_AI_Manager.AccessAIs()[i]; - - float flDot; - - if ( IsIlluminatedByFlashlight( pNPC, &flDot ) ) - { - pNPC->PlayerHasIlluminatedNPC( this, flDot ); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHL2_Player::SetPlayerUnderwater( bool state ) -{ - if ( state ) - { - SuitPower_AddDevice( SuitDeviceBreather ); - } - else - { - SuitPower_RemoveDevice( SuitDeviceBreather ); - } - - BaseClass::SetPlayerUnderwater( state ); -} - -//----------------------------------------------------------------------------- -bool CHL2_Player::PassesDamageFilter( const CTakeDamageInfo &info ) -{ - CBaseEntity *pAttacker = info.GetAttacker(); - if( pAttacker && pAttacker->MyNPCPointer() && pAttacker->MyNPCPointer()->IsPlayerAlly() ) - { - return false; - } - - if( m_hPlayerProxy && !m_hPlayerProxy->PassesDamageFilter( info ) ) - { - return false; - } - - return BaseClass::PassesDamageFilter( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHL2_Player::SetFlashlightEnabled( bool bState ) -{ - m_bFlashlightDisabled = !bState; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHL2_Player::InputDisableFlashlight( inputdata_t &inputdata ) -{ - if( FlashlightIsOn() ) - FlashlightTurnOff(); - - SetFlashlightEnabled( false ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHL2_Player::InputEnableFlashlight( inputdata_t &inputdata ) -{ - SetFlashlightEnabled( true ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Prevent the player from taking fall damage for [n] seconds, but -// reset back to taking fall damage after the first impact (so players will be -// hurt if they bounce off what they hit). This is the original behavior. -//----------------------------------------------------------------------------- -void CHL2_Player::InputIgnoreFallDamage( inputdata_t &inputdata ) -{ - float timeToIgnore = inputdata.value.Float(); - - if ( timeToIgnore <= 0.0 ) - timeToIgnore = TIME_IGNORE_FALL_DAMAGE; - - m_flTimeIgnoreFallDamage = gpGlobals->curtime + timeToIgnore; - m_bIgnoreFallDamageResetAfterImpact = true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Absolutely prevent the player from taking fall damage for [n] seconds. -//----------------------------------------------------------------------------- -void CHL2_Player::InputIgnoreFallDamageWithoutReset( inputdata_t &inputdata ) -{ - float timeToIgnore = inputdata.value.Float(); - - if ( timeToIgnore <= 0.0 ) - timeToIgnore = TIME_IGNORE_FALL_DAMAGE; - - m_flTimeIgnoreFallDamage = gpGlobals->curtime + timeToIgnore; - m_bIgnoreFallDamageResetAfterImpact = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Notification of a player's npc ally in the players squad being killed -//----------------------------------------------------------------------------- -void CHL2_Player::OnSquadMemberKilled( inputdata_t &data ) -{ - // send a message to the client, to notify the hud of the loss - CSingleUserRecipientFilter user( this ); - user.MakeReliable(); - UserMessageBegin( user, "SquadMemberDied" ); - MessageEnd(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHL2_Player::NotifyFriendsOfDamage( CBaseEntity *pAttackerEntity ) -{ - CAI_BaseNPC *pAttacker = pAttackerEntity->MyNPCPointer(); - if ( pAttacker ) - { - const Vector &origin = GetAbsOrigin(); - for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - const float NEAR_Z = 12*12; - const float NEAR_XY_SQ = Square( 50*12 ); - CAI_BaseNPC *pNpc = g_AI_Manager.AccessAIs()[i]; - if ( pNpc->IsPlayerAlly() ) - { - const Vector &originNpc = pNpc->GetAbsOrigin(); - if ( fabsf( originNpc.z - origin.z ) < NEAR_Z ) - { - if ( (originNpc.AsVector2D() - origin.AsVector2D()).LengthSqr() < NEAR_XY_SQ ) - { - pNpc->OnFriendDamaged( this, pAttacker ); - } - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -ConVar test_massive_dmg("test_massive_dmg", "30" ); -ConVar test_massive_dmg_clip("test_massive_dmg_clip", "0.5" ); -int CHL2_Player::OnTakeDamage( const CTakeDamageInfo &info ) -{ - if ( GlobalEntity_GetState( "gordon_invulnerable" ) == GLOBAL_ON ) - return 0; - - // ignore fall damage if instructed to do so by input - if ( ( info.GetDamageType() & DMG_FALL ) && m_flTimeIgnoreFallDamage > gpGlobals->curtime ) - { - // usually, we will reset the input flag after the first impact. However there is another input that - // prevents this behavior. - if ( m_bIgnoreFallDamageResetAfterImpact ) - { - m_flTimeIgnoreFallDamage = 0; - } - return 0; - } - - if( info.GetDamageType() & DMG_BLAST_SURFACE ) - { - if( GetWaterLevel() > 2 ) - { - // Don't take blast damage from anything above the surface. - if( info.GetInflictor()->GetWaterLevel() == 0 ) - { - return 0; - } - } - } - - if ( info.GetDamage() > 0.0f ) - { - m_flLastDamageTime = gpGlobals->curtime; - - if ( info.GetAttacker() ) - NotifyFriendsOfDamage( info.GetAttacker() ); - } - - // Modify the amount of damage the player takes, based on skill. - CTakeDamageInfo playerDamage = info; - - // Should we run this damage through the skill level adjustment? - bool bAdjustForSkillLevel = true; - - if( info.GetDamageType() == DMG_GENERIC && info.GetAttacker() == this && info.GetInflictor() == this ) - { - // Only do a skill level adjustment if the player isn't his own attacker AND inflictor. - // This prevents damage from SetHealth() inputs from being adjusted for skill level. - bAdjustForSkillLevel = false; - } - - if ( GetVehicleEntity() != NULL && GlobalEntity_GetState("gordon_protect_driver") == GLOBAL_ON ) - { - if( playerDamage.GetDamage() > test_massive_dmg.GetFloat() && playerDamage.GetInflictor() == GetVehicleEntity() && (playerDamage.GetDamageType() & DMG_CRUSH) ) - { - playerDamage.ScaleDamage( test_massive_dmg_clip.GetFloat() / playerDamage.GetDamage() ); - } - } - - if( bAdjustForSkillLevel ) - { - playerDamage.AdjustPlayerDamageTakenForSkillLevel(); - } - - gamestats->Event_PlayerDamage( this, info ); - - return BaseClass::OnTakeDamage( playerDamage ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -//----------------------------------------------------------------------------- -int CHL2_Player::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - // Drown - if( info.GetDamageType() & DMG_DROWN ) - { - if( m_idrowndmg == m_idrownrestored ) - { - EmitSound( "Player.DrownStart" ); - } - else - { - EmitSound( "Player.DrownContinue" ); - } - } - - // Burnt - if ( info.GetDamageType() & DMG_BURN ) - { - EmitSound( "HL2Player.BurnPain" ); - } - - - if( (info.GetDamageType() & DMG_SLASH) && hl2_episodic.GetBool() ) - { - if( m_afPhysicsFlags & PFLAG_USING ) - { - // Stop the player using a rotating button for a short time if hit by a creature's melee attack. - // This is for the antlion burrow-corking training in EP1 (sjb). - SuspendUse( 0.5f ); - } - } - - - // Call the base class implementation - return BaseClass::OnTakeDamage_Alive( info ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHL2_Player::OnDamagedByExplosion( const CTakeDamageInfo &info ) -{ - if ( info.GetInflictor() && info.GetInflictor()->ClassMatches( "mortarshell" ) ) - { - // No ear ringing for mortar - UTIL_ScreenShake( info.GetInflictor()->GetAbsOrigin(), 4.0, 1.0, 0.5, 1000, SHAKE_START, false ); - return; - } - BaseClass::OnDamagedByExplosion( info ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CHL2_Player::ShouldShootMissTarget( CBaseCombatCharacter *pAttacker ) -{ - if( gpGlobals->curtime > m_flTargetFindTime ) - { - // Put this off into the future again. - m_flTargetFindTime = gpGlobals->curtime + random->RandomFloat( 3, 5 ); - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Notifies Alyx that player has put a combine ball into a socket so she can comment on it. -// Input : pCombineBall - ball the was socketed -//----------------------------------------------------------------------------- -void CHL2_Player::CombineBallSocketed( CPropCombineBall *pCombineBall ) -{ -#ifdef HL2_EPISODIC - CNPC_Alyx *pAlyx = CNPC_Alyx::GetAlyx(); - if ( pAlyx ) - { - pAlyx->CombineBallSocketed( pCombineBall->NumBounces() ); - } -#endif -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHL2_Player::Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info ) -{ - BaseClass::Event_KilledOther( pVictim, info ); - -#ifdef HL2_EPISODIC - - CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); - - for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - if ( ppAIs[i] && ppAIs[i]->IRelationType(this) == D_LI ) - { - ppAIs[i]->OnPlayerKilledOther( pVictim, info ); - } - } - -#endif -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHL2_Player::Event_Killed( const CTakeDamageInfo &info ) -{ - BaseClass::Event_Killed( info ); - - FirePlayerProxyOutput( "PlayerDied", variant_t(), this, this ); - NotifyScriptsOfDeath(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHL2_Player::NotifyScriptsOfDeath( void ) -{ - CBaseEntity *pEnt = gEntList.FindEntityByClassname( NULL, "scripted_sequence" ); - - while( pEnt ) - { - variant_t emptyVariant; - pEnt->AcceptInput( "ScriptPlayerDeath", NULL, NULL, emptyVariant, 0 ); - - pEnt = gEntList.FindEntityByClassname( pEnt, "scripted_sequence" ); - } - - pEnt = gEntList.FindEntityByClassname( NULL, "logic_choreographed_scene" ); - - while( pEnt ) - { - variant_t emptyVariant; - pEnt->AcceptInput( "ScriptPlayerDeath", NULL, NULL, emptyVariant, 0 ); - - pEnt = gEntList.FindEntityByClassname( pEnt, "logic_choreographed_scene" ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHL2_Player::GetAutoaimVector( autoaim_params_t ¶ms ) -{ - BaseClass::GetAutoaimVector( params ); - - if ( IsX360() ) - { - if( IsInAVehicle() ) - { - if( m_hLockedAutoAimEntity && m_hLockedAutoAimEntity->IsAlive() && ShouldKeepLockedAutoaimTarget(m_hLockedAutoAimEntity) ) - { - if( params.m_hAutoAimEntity && params.m_hAutoAimEntity != m_hLockedAutoAimEntity ) - { - // Autoaim has picked a new target. Switch. - m_hLockedAutoAimEntity = params.m_hAutoAimEntity; - } - - // Ignore autoaim and just keep aiming at this target. - params.m_hAutoAimEntity = m_hLockedAutoAimEntity; - Vector vecTarget = m_hLockedAutoAimEntity->BodyTarget( EyePosition(), false ); - Vector vecDir = vecTarget - EyePosition(); - VectorNormalize( vecDir ); - - params.m_vecAutoAimDir = vecDir; - params.m_vecAutoAimPoint = vecTarget; - return; - } - else - { - m_hLockedAutoAimEntity = NULL; - } - } - - // If the player manually gets his crosshair onto a target, make that target sticky - if( params.m_fScale != AUTOAIM_SCALE_DIRECT_ONLY ) - { - // Only affect this for 'real' queries - //if( params.m_hAutoAimEntity && params.m_bOnTargetNatural ) - if( params.m_hAutoAimEntity ) - { - // Turn on sticky. - m_HL2Local.m_bStickyAutoAim = true; - - if( IsInAVehicle() ) - { - m_hLockedAutoAimEntity = params.m_hAutoAimEntity; - } - } - else if( !params.m_hAutoAimEntity ) - { - // Turn off sticky only if there's no target at all. - m_HL2Local.m_bStickyAutoAim = false; - - m_hLockedAutoAimEntity = NULL; - } - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CHL2_Player::ShouldKeepLockedAutoaimTarget( EHANDLE hLockedTarget ) -{ - Vector vecLooking; - Vector vecToTarget; - - vecToTarget = hLockedTarget->WorldSpaceCenter() - EyePosition(); - float flDist = vecToTarget.Length2D(); - VectorNormalize( vecToTarget ); - - if( flDist > autoaim_max_dist.GetFloat() ) - return false; - - float flDot; - - vecLooking = EyeDirection3D(); - flDot = DotProduct( vecLooking, vecToTarget ); - - if( flDot < autoaim_unlock_target.GetFloat() ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iCount - -// iAmmoIndex - -// bSuppressSound - -// Output : int -//----------------------------------------------------------------------------- -int CHL2_Player::GiveAmmo( int nCount, int nAmmoIndex, bool bSuppressSound) -{ - // Don't try to give the player invalid ammo indices. - if (nAmmoIndex < 0) - return 0; - - bool bCheckAutoSwitch = false; - if (!HasAnyAmmoOfType(nAmmoIndex)) - { - bCheckAutoSwitch = true; - } - - int nAdd = BaseClass::GiveAmmo(nCount, nAmmoIndex, bSuppressSound); - - if ( nCount > 0 && nAdd == 0 ) - { - // we've been denied the pickup, display a hud icon to show that - CSingleUserRecipientFilter user( this ); - user.MakeReliable(); - UserMessageBegin( user, "AmmoDenied" ); - WRITE_SHORT( nAmmoIndex ); - MessageEnd(); - } - - // - // If I was dry on ammo for my best weapon and justed picked up ammo for it, - // autoswitch to my best weapon now. - // - if (bCheckAutoSwitch) - { - CBaseCombatWeapon *pWeapon = g_pGameRules->GetNextBestWeapon(this, GetActiveWeapon()); - - if ( pWeapon && pWeapon->GetPrimaryAmmoType() == nAmmoIndex ) - { - SwitchToNextBestWeapon(GetActiveWeapon()); - } - } - - return nAdd; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CHL2_Player::Weapon_CanUse( CBaseCombatWeapon *pWeapon ) -{ -#ifndef HL2MP - if ( pWeapon->ClassMatches( "weapon_stunstick" ) ) - { - if ( ApplyBattery( 0.5 ) ) - UTIL_Remove( pWeapon ); - return false; - } -#endif - - return BaseClass::Weapon_CanUse( pWeapon ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pWeapon - -//----------------------------------------------------------------------------- -void CHL2_Player::Weapon_Equip( CBaseCombatWeapon *pWeapon ) -{ -#if HL2_SINGLE_PRIMARY_WEAPON_MODE - - if ( pWeapon->GetSlot() == WEAPON_PRIMARY_SLOT ) - { - Weapon_DropSlot( WEAPON_PRIMARY_SLOT ); - } - -#endif - - if( GetActiveWeapon() == NULL ) - { - m_HL2Local.m_bWeaponLowered = false; - } - - BaseClass::Weapon_Equip( pWeapon ); -} - -//----------------------------------------------------------------------------- -// Purpose: Player reacts to bumping a weapon. -// Input : pWeapon - the weapon that the player bumped into. -// Output : Returns true if player picked up the weapon -//----------------------------------------------------------------------------- -bool CHL2_Player::BumpWeapon( CBaseCombatWeapon *pWeapon ) -{ - -#if HL2_SINGLE_PRIMARY_WEAPON_MODE - - CBaseCombatCharacter *pOwner = pWeapon->GetOwner(); - - // Can I have this weapon type? - if ( pOwner || !Weapon_CanUse( pWeapon ) || !g_pGameRules->CanHavePlayerItem( this, pWeapon ) ) - { - if ( gEvilImpulse101 ) - { - UTIL_Remove( pWeapon ); - } - return false; - } - - // ---------------------------------------- - // If I already have it just take the ammo - // ---------------------------------------- - if (Weapon_OwnsThisType( pWeapon->GetClassname(), pWeapon->GetSubType())) - { - //Only remove the weapon if we attained ammo from it - if ( Weapon_EquipAmmoOnly( pWeapon ) == false ) - return false; - - // Only remove me if I have no ammo left - // Can't just check HasAnyAmmo because if I don't use clips, I want to be removed, - if ( pWeapon->UsesClipsForAmmo1() && pWeapon->HasPrimaryAmmo() ) - return false; - - UTIL_Remove( pWeapon ); - return false; - } - // ------------------------- - // Otherwise take the weapon - // ------------------------- - else - { - //Make sure we're not trying to take a new weapon type we already have - if ( Weapon_SlotOccupied( pWeapon ) ) - { - CBaseCombatWeapon *pActiveWeapon = Weapon_GetSlot( WEAPON_PRIMARY_SLOT ); - - if ( pActiveWeapon != NULL && pActiveWeapon->HasAnyAmmo() == false && Weapon_CanSwitchTo( pWeapon ) ) - { - Weapon_Equip( pWeapon ); - return true; - } - - //Attempt to take ammo if this is the gun we're holding already - if ( Weapon_OwnsThisType( pWeapon->GetClassname(), pWeapon->GetSubType() ) ) - { - Weapon_EquipAmmoOnly( pWeapon ); - } - - return false; - } - - pWeapon->CheckRespawn(); - - pWeapon->AddSolidFlags( FSOLID_NOT_SOLID ); - pWeapon->AddEffects( EF_NODRAW ); - - Weapon_Equip( pWeapon ); - - EmitSound( "HL2Player.PickupWeapon" ); - - return true; - } -#else - - return BaseClass::BumpWeapon( pWeapon ); - -#endif - -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *cmd - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CHL2_Player::ClientCommand( const CCommand &args ) -{ -#if HL2_SINGLE_PRIMARY_WEAPON_MODE - - //Drop primary weapon - if ( !Q_stricmp( args[0], "DropPrimary" ) ) - { - Weapon_DropSlot( WEAPON_PRIMARY_SLOT ); - return true; - } - -#endif - - if ( !Q_stricmp( args[0], "emit" ) ) - { - CSingleUserRecipientFilter filter( this ); - if ( args.ArgC() > 1 ) - { - EmitSound( filter, entindex(), args[ 1 ] ); - } - else - { - EmitSound( filter, entindex(), "Test.Sound" ); - } - return true; - } - - return BaseClass::ClientCommand( args ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : void CBasePlayer::PlayerUse -//----------------------------------------------------------------------------- -void CHL2_Player::PlayerUse ( void ) -{ - // Was use pressed or released? - if ( ! ((m_nButtons | m_afButtonPressed | m_afButtonReleased) & IN_USE) ) - return; - - if ( m_afButtonPressed & IN_USE ) - { - // Currently using a latched entity? - if ( ClearUseEntity() ) - { - return; - } - else - { - if ( m_afPhysicsFlags & PFLAG_DIROVERRIDE ) - { - m_afPhysicsFlags &= ~PFLAG_DIROVERRIDE; - m_iTrain = TRAIN_NEW|TRAIN_OFF; - return; - } - else - { // Start controlling the train! - CBaseEntity *pTrain = GetGroundEntity(); - if ( pTrain && !(m_nButtons & IN_JUMP) && (GetFlags() & FL_ONGROUND) && (pTrain->ObjectCaps() & FCAP_DIRECTIONAL_USE) && pTrain->OnControls(this) ) - { - m_afPhysicsFlags |= PFLAG_DIROVERRIDE; - m_iTrain = TrainSpeed((int)pTrain->m_flSpeed, (int)((CFuncTrackTrain*)pTrain)->GetMaxSpeed()); - m_iTrain |= TRAIN_NEW; - EmitSound( "HL2Player.TrainUse" ); - return; - } - } - } - - // Tracker 3926: We can't +USE something if we're climbing a ladder - if ( GetMoveType() == MOVETYPE_LADDER ) - { - return; - } - } - - if( m_flTimeUseSuspended > gpGlobals->curtime ) - { - // Something has temporarily stopped us being able to USE things. - // Obviously, this should be used very carefully.(sjb) - return; - } - - CBaseEntity *pUseEntity = FindUseEntity(); - - bool usedSomething = false; - - // Found an object - if ( pUseEntity ) - { - //!!!UNDONE: traceline here to prevent +USEing buttons through walls - int caps = pUseEntity->ObjectCaps(); - variant_t emptyVariant; - - if ( m_afButtonPressed & IN_USE ) - { - // Robin: Don't play sounds for NPCs, because NPCs will allow respond with speech. - if ( !pUseEntity->MyNPCPointer() ) - { - EmitSound( "HL2Player.Use" ); - } - } - - if ( ( (m_nButtons & IN_USE) && (caps & FCAP_CONTINUOUS_USE) ) || - ( (m_afButtonPressed & IN_USE) && (caps & (FCAP_IMPULSE_USE|FCAP_ONOFF_USE)) ) ) - { - if ( caps & FCAP_CONTINUOUS_USE ) - m_afPhysicsFlags |= PFLAG_USING; - - pUseEntity->AcceptInput( "Use", this, this, emptyVariant, USE_TOGGLE ); - - usedSomething = true; - } - // UNDONE: Send different USE codes for ON/OFF. Cache last ONOFF_USE object to send 'off' if you turn away - else if ( (m_afButtonReleased & IN_USE) && (pUseEntity->ObjectCaps() & FCAP_ONOFF_USE) ) // BUGBUG This is an "off" use - { - pUseEntity->AcceptInput( "Use", this, this, emptyVariant, USE_TOGGLE ); - - usedSomething = true; - } - -#if HL2_SINGLE_PRIMARY_WEAPON_MODE - - //Check for weapon pick-up - if ( m_afButtonPressed & IN_USE ) - { - CBaseCombatWeapon *pWeapon = dynamic_cast(pUseEntity); - - if ( ( pWeapon != NULL ) && ( Weapon_CanSwitchTo( pWeapon ) ) ) - { - //Try to take ammo or swap the weapon - if ( Weapon_OwnsThisType( pWeapon->GetClassname(), pWeapon->GetSubType() ) ) - { - Weapon_EquipAmmoOnly( pWeapon ); - } - else - { - Weapon_DropSlot( pWeapon->GetSlot() ); - Weapon_Equip( pWeapon ); - } - - usedSomething = true; - } - } -#endif - } - else if ( m_afButtonPressed & IN_USE ) - { - // Signal that we want to play the deny sound, unless the user is +USEing on a ladder! - // The sound is emitted in ItemPostFrame, since that occurs after GameMovement::ProcessMove which - // lets the ladder code unset this flag. - m_bPlayUseDenySound = true; - } - - // Debounce the use key - if ( usedSomething && pUseEntity ) - { - m_Local.m_nOldButtons |= IN_USE; - m_afButtonPressed &= ~IN_USE; - } -} - -ConVar sv_show_crosshair_target( "sv_show_crosshair_target", "0" ); - -//----------------------------------------------------------------------------- -// Purpose: Updates the posture of the weapon from lowered to ready -//----------------------------------------------------------------------------- -void CHL2_Player::UpdateWeaponPosture( void ) -{ - CBaseCombatWeapon *pWeapon = dynamic_cast(GetActiveWeapon()); - - if ( pWeapon && m_LowerWeaponTimer.Expired() && pWeapon->CanLower() ) - { - m_LowerWeaponTimer.Set( .3 ); - VPROF( "CHL2_Player::UpdateWeaponPosture-CheckLower" ); - Vector vecAim = BaseClass::GetAutoaimVector( AUTOAIM_SCALE_DIRECT_ONLY ); - - const float CHECK_FRIENDLY_RANGE = 50 * 12; - trace_t tr; - UTIL_TraceLine( EyePosition(), EyePosition() + vecAim * CHECK_FRIENDLY_RANGE, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - CBaseEntity *aimTarget = tr.m_pEnt; - - //If we're over something - if ( aimTarget && !tr.DidHitWorld() ) - { - if ( !aimTarget->IsNPC() || aimTarget->MyNPCPointer()->GetState() != NPC_STATE_COMBAT ) - { - Disposition_t dis = IRelationType( aimTarget ); - - //Debug info for seeing what an object "cons" as - if ( sv_show_crosshair_target.GetBool() ) - { - int text_offset = BaseClass::DrawDebugTextOverlays(); - - char tempstr[255]; - - switch ( dis ) - { - case D_LI: - Q_snprintf( tempstr, sizeof(tempstr), "Disposition: Like" ); - break; - - case D_HT: - Q_snprintf( tempstr, sizeof(tempstr), "Disposition: Hate" ); - break; - - case D_FR: - Q_snprintf( tempstr, sizeof(tempstr), "Disposition: Fear" ); - break; - - case D_NU: - Q_snprintf( tempstr, sizeof(tempstr), "Disposition: Neutral" ); - break; - - default: - case D_ER: - Q_snprintf( tempstr, sizeof(tempstr), "Disposition: !!!ERROR!!!" ); - break; - } - - //Draw the text - NDebugOverlay::EntityText( aimTarget->entindex(), text_offset, tempstr, 0 ); - } - - //See if we hates it - if ( dis == D_LI ) - { - //We're over a friendly, drop our weapon - if ( Weapon_Lower() == false ) - { - //FIXME: We couldn't lower our weapon! - } - - return; - } - } - } - - if ( Weapon_Ready() == false ) - { - //FIXME: We couldn't raise our weapon! - } - } - - if( g_pGameRules->GetAutoAimMode() != AUTOAIM_NONE ) - { - if( !pWeapon ) - { - // This tells the client to draw no crosshair - m_HL2Local.m_bWeaponLowered = true; - return; - } - else - { - if( !pWeapon->CanLower() && m_HL2Local.m_bWeaponLowered ) - m_HL2Local.m_bWeaponLowered = false; - } - - if( !m_AutoaimTimer.Expired() ) - return; - - m_AutoaimTimer.Set( .1 ); - - VPROF( "hl2_x360_aiming" ); - - // Call the autoaim code to update the local player data, which allows the client to update. - autoaim_params_t params; - params.m_vecAutoAimPoint.Init(); - params.m_vecAutoAimDir.Init(); - params.m_fScale = AUTOAIM_SCALE_DEFAULT; - params.m_fMaxDist = autoaim_max_dist.GetFloat(); - GetAutoaimVector( params ); - m_HL2Local.m_hAutoAimTarget.Set( params.m_hAutoAimEntity ); - m_HL2Local.m_vecAutoAimPoint.Set( params.m_vecAutoAimPoint ); - m_HL2Local.m_bAutoAimTarget = ( params.m_bAutoAimAssisting || params.m_bOnTargetNatural ); - return; - } - else - { - // Make sure there's no residual autoaim target if the user changes the xbox_aiming convar on the fly. - m_HL2Local.m_hAutoAimTarget.Set(NULL); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Lowers the weapon posture (for hovering over friendlies) -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CHL2_Player::Weapon_Lower( void ) -{ - VPROF( "CHL2_Player::Weapon_Lower" ); - // Already lowered? - if ( m_HL2Local.m_bWeaponLowered ) - return true; - - m_HL2Local.m_bWeaponLowered = true; - - CBaseCombatWeapon *pWeapon = dynamic_cast(GetActiveWeapon()); - - if ( pWeapon == NULL ) - return false; - - return pWeapon->Lower(); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the weapon posture to normal -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CHL2_Player::Weapon_Ready( void ) -{ - VPROF( "CHL2_Player::Weapon_Ready" ); - - // Already ready? - if ( m_HL2Local.m_bWeaponLowered == false ) - return true; - - m_HL2Local.m_bWeaponLowered = false; - - CBaseCombatWeapon *pWeapon = dynamic_cast(GetActiveWeapon()); - - if ( pWeapon == NULL ) - return false; - - return pWeapon->Ready(); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns whether or not we can switch to the given weapon. -// Input : pWeapon - -//----------------------------------------------------------------------------- -bool CHL2_Player::Weapon_CanSwitchTo( CBaseCombatWeapon *pWeapon ) -{ - CBasePlayer *pPlayer = (CBasePlayer *)this; -#if !defined( CLIENT_DLL ) - IServerVehicle *pVehicle = pPlayer->GetVehicle(); -#else - IClientVehicle *pVehicle = pPlayer->GetVehicle(); -#endif - if (pVehicle && !pPlayer->UsingStandardWeaponsInVehicle()) - return false; - - if ( !pWeapon->HasAnyAmmo() && !GetAmmoCount( pWeapon->m_iPrimaryAmmoType ) ) - return false; - - if ( !pWeapon->CanDeploy() ) - return false; - - if ( GetActiveWeapon() ) - { - if ( PhysCannonGetHeldEntity( GetActiveWeapon() ) == pWeapon && - Weapon_OwnsThisType( pWeapon->GetClassname(), pWeapon->GetSubType()) ) - { - return true; - } - - if ( !GetActiveWeapon()->CanHolster() ) - return false; - } - - return true; -} - -void CHL2_Player::PickupObject( CBaseEntity *pObject, bool bLimitMassAndSize ) -{ - // can't pick up what you're standing on - if ( GetGroundEntity() == pObject ) - return; - - if ( bLimitMassAndSize == true ) - { - if ( CBasePlayer::CanPickupObject( pObject, 35, 128 ) == false ) - return; - } - - // Can't be picked up if NPCs are on me - if ( pObject->HasNPCsOnIt() ) - return; - - PlayerPickupObject( this, pObject ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CBaseEntity -//----------------------------------------------------------------------------- -bool CHL2_Player::IsHoldingEntity( CBaseEntity *pEnt ) -{ - return PlayerPickupControllerIsHoldingEntity( m_hUseEntity, pEnt ); -} - -float CHL2_Player::GetHeldObjectMass( IPhysicsObject *pHeldObject ) -{ - float mass = PlayerPickupGetHeldObjectMass( m_hUseEntity, pHeldObject ); - if ( mass == 0.0f ) - { - mass = PhysCannonGetHeldObjectMass( GetActiveWeapon(), pHeldObject ); - } - return mass; -} - -CBaseEntity *CHL2_Player::GetHeldObject( void ) -{ - return PhysCannonGetHeldEntity( GetActiveWeapon() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Force the player to drop any physics objects he's carrying -//----------------------------------------------------------------------------- -void CHL2_Player::ForceDropOfCarriedPhysObjects( CBaseEntity *pOnlyIfHoldingThis ) -{ - if ( PhysIsInCallback() ) - { - variant_t value; - g_EventQueue.AddEvent( this, "ForceDropPhysObjects", value, 0.01f, pOnlyIfHoldingThis, this ); - return; - } - -#ifdef HL2_EPISODIC - if ( hl2_episodic.GetBool() ) - { - CBaseEntity *pHeldEntity = PhysCannonGetHeldEntity( GetActiveWeapon() ); - if( pHeldEntity && pHeldEntity->ClassMatches( "grenade_helicopter" ) ) - { - return; - } - } -#endif - - // Drop any objects being handheld. - ClearUseEntity(); - - // Then force the physcannon to drop anything it's holding, if it's our active weapon - PhysCannonForceDrop( GetActiveWeapon(), NULL ); -} - -void CHL2_Player::InputForceDropPhysObjects( inputdata_t &data ) -{ - ForceDropOfCarriedPhysObjects( data.pActivator ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHL2_Player::UpdateClientData( void ) -{ - if (m_DmgTake || m_DmgSave || m_bitsHUDDamage != m_bitsDamageType) - { - // Comes from inside me if not set - Vector damageOrigin = GetLocalOrigin(); - // send "damage" message - // causes screen to flash, and pain compass to show direction of damage - damageOrigin = m_DmgOrigin; - - // only send down damage type that have hud art - int iShowHudDamage = g_pGameRules->Damage_GetShowOnHud(); - int visibleDamageBits = m_bitsDamageType & iShowHudDamage; - - m_DmgTake = clamp( m_DmgTake, 0, 255 ); - m_DmgSave = clamp( m_DmgSave, 0, 255 ); - - // If we're poisoned, but it wasn't this frame, don't send the indicator - // Without this check, any damage that occured to the player while they were - // recovering from a poison bite would register as poisonous as well and flash - // the whole screen! -- jdw - if ( visibleDamageBits & DMG_POISON ) - { - float flLastPoisonedDelta = gpGlobals->curtime - m_tbdPrev; - if ( flLastPoisonedDelta > 0.1f ) - { - visibleDamageBits &= ~DMG_POISON; - } - } - - CSingleUserRecipientFilter user( this ); - user.MakeReliable(); - UserMessageBegin( user, "Damage" ); - WRITE_BYTE( (int)m_DmgSave ); - WRITE_BYTE( (int)m_DmgTake ); - WRITE_LONG( visibleDamageBits ); - WRITE_FLOAT( damageOrigin.x ); //BUG: Should be fixed point (to hud) not floats - WRITE_FLOAT( damageOrigin.y ); //BUG: However, the HUD does _not_ implement bitfield messages (yet) - WRITE_FLOAT( damageOrigin.z ); //BUG: We use WRITE_VEC3COORD for everything else - MessageEnd(); - - m_DmgTake = 0; - m_DmgSave = 0; - m_bitsHUDDamage = m_bitsDamageType; - - // Clear off non-time-based damage indicators - int iTimeBasedDamage = g_pGameRules->Damage_GetTimeBased(); - m_bitsDamageType &= iTimeBasedDamage; - } - - // Update Flashlight -#ifdef HL2_EPISODIC - if ( Flashlight_UseLegacyVersion() == false ) - { - if ( FlashlightIsOn() && sv_infinite_aux_power.GetBool() == false ) - { - m_HL2Local.m_flFlashBattery -= FLASH_DRAIN_TIME * gpGlobals->frametime; - if ( m_HL2Local.m_flFlashBattery < 0.0f ) - { - FlashlightTurnOff(); - m_HL2Local.m_flFlashBattery = 0.0f; - } - } - else - { - m_HL2Local.m_flFlashBattery += FLASH_CHARGE_TIME * gpGlobals->frametime; - if ( m_HL2Local.m_flFlashBattery > 100.0f ) - { - m_HL2Local.m_flFlashBattery = 100.0f; - } - } - } - else - { - m_HL2Local.m_flFlashBattery = -1.0f; - } -#endif // HL2_EPISODIC - - BaseClass::UpdateClientData(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CHL2_Player::OnRestore() -{ - BaseClass::OnRestore(); - m_pPlayerAISquad = g_AI_SquadManager.FindCreateSquad(AllocPooledString(PLAYER_SQUADNAME)); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -Vector CHL2_Player::EyeDirection2D( void ) -{ - Vector vecReturn = EyeDirection3D(); - vecReturn.z = 0; - vecReturn.AsVector2D().NormalizeInPlace(); - - return vecReturn; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -Vector CHL2_Player::EyeDirection3D( void ) -{ - Vector vecForward; - - // Return the vehicle angles if we request them - if ( GetVehicle() != NULL ) - { - CacheVehicleView(); - EyeVectors( &vecForward ); - return vecForward; - } - - AngleVectors( EyeAngles(), &vecForward ); - return vecForward; -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CHL2_Player::Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmodelindex ) -{ - MDLCACHE_CRITICAL_SECTION(); - - // Recalculate proficiency! - SetCurrentWeaponProficiency( CalcWeaponProficiency( pWeapon ) ); - - // Come out of suit zoom mode - if ( IsZooming() ) - { - StopZooming(); - } - - return BaseClass::Weapon_Switch( pWeapon, viewmodelindex ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -WeaponProficiency_t CHL2_Player::CalcWeaponProficiency( CBaseCombatWeapon *pWeapon ) -{ - WeaponProficiency_t proficiency; - - proficiency = WEAPON_PROFICIENCY_PERFECT; - - if( weapon_showproficiency.GetBool() != 0 ) - { - Msg("Player switched to %s, proficiency is %s\n", pWeapon->GetClassname(), GetWeaponProficiencyName( proficiency ) ); - } - - return proficiency; -} - -//----------------------------------------------------------------------------- -// Purpose: override how single player rays hit the player -//----------------------------------------------------------------------------- - -bool LineCircleIntersection( - const Vector2D ¢er, - const float radius, - const Vector2D &vLinePt, - const Vector2D &vLineDir, - float *fIntersection1, - float *fIntersection2) -{ - // Line = P + Vt - // Sphere = r (assume we've translated to origin) - // (P + Vt)^2 = r^2 - // VVt^2 + 2PVt + (PP - r^2) - // Solve as quadratic: (-b +/- sqrt(b^2 - 4ac)) / 2a - // If (b^2 - 4ac) is < 0 there is no solution. - // If (b^2 - 4ac) is = 0 there is one solution (a case this function doesn't support). - // If (b^2 - 4ac) is > 0 there are two solutions. - Vector2D P; - float a, b, c, sqr, insideSqr; - - - // Translate circle to origin. - P[0] = vLinePt[0] - center[0]; - P[1] = vLinePt[1] - center[1]; - - a = vLineDir.Dot(vLineDir); - b = 2.0f * P.Dot(vLineDir); - c = P.Dot(P) - (radius * radius); - - insideSqr = b*b - 4*a*c; - if(insideSqr <= 0.000001f) - return false; - - // Ok, two solutions. - sqr = (float)FastSqrt(insideSqr); - - float denom = 1.0 / (2.0f * a); - - *fIntersection1 = (-b - sqr) * denom; - *fIntersection2 = (-b + sqr) * denom; - - return true; -} - -static void Collision_ClearTrace( const Vector &vecRayStart, const Vector &vecRayDelta, CBaseTrace *pTrace ) -{ - pTrace->startpos = vecRayStart; - pTrace->endpos = vecRayStart; - pTrace->endpos += vecRayDelta; - pTrace->startsolid = false; - pTrace->allsolid = false; - pTrace->fraction = 1.0f; - pTrace->contents = 0; -} - - -bool IntersectRayWithAACylinder( const Ray_t &ray, - const Vector ¢er, float radius, float height, CBaseTrace *pTrace ) -{ - Assert( ray.m_IsRay ); - Collision_ClearTrace( ray.m_Start, ray.m_Delta, pTrace ); - - // First intersect the ray with the top + bottom planes - float halfHeight = height * 0.5; - - // Handle parallel case - Vector vStart = ray.m_Start - center; - Vector vEnd = vStart + ray.m_Delta; - - float flEnterFrac, flLeaveFrac; - if (FloatMakePositive(ray.m_Delta.z) < 1e-8) - { - if ( (vStart.z < -halfHeight) || (vStart.z > halfHeight) ) - { - return false; // no hit - } - flEnterFrac = 0.0f; flLeaveFrac = 1.0f; - } - else - { - // Clip the ray to the top and bottom of box - flEnterFrac = IntersectRayWithAAPlane( vStart, vEnd, 2, 1, halfHeight); - flLeaveFrac = IntersectRayWithAAPlane( vStart, vEnd, 2, 1, -halfHeight); - - if ( flLeaveFrac < flEnterFrac ) - { - float temp = flLeaveFrac; - flLeaveFrac = flEnterFrac; - flEnterFrac = temp; - } - - if ( flLeaveFrac < 0 || flEnterFrac > 1) - { - return false; - } - } - - // Intersect with circle - float flCircleEnterFrac, flCircleLeaveFrac; - if ( !LineCircleIntersection( vec3_origin.AsVector2D(), radius, - vStart.AsVector2D(), ray.m_Delta.AsVector2D(), &flCircleEnterFrac, &flCircleLeaveFrac ) ) - { - return false; // no hit - } - - Assert( flCircleEnterFrac <= flCircleLeaveFrac ); - if ( flCircleLeaveFrac < 0 || flCircleEnterFrac > 1) - { - return false; - } - - if ( flEnterFrac < flCircleEnterFrac ) - flEnterFrac = flCircleEnterFrac; - if ( flLeaveFrac > flCircleLeaveFrac ) - flLeaveFrac = flCircleLeaveFrac; - - if ( flLeaveFrac < flEnterFrac ) - return false; - - VectorMA( ray.m_Start, flEnterFrac , ray.m_Delta, pTrace->endpos ); - pTrace->fraction = flEnterFrac; - pTrace->contents = CONTENTS_SOLID; - - // Calculate the point on our center line where we're nearest the intersection point - Vector collisionCenter; - CalcClosestPointOnLineSegment( pTrace->endpos, center + Vector( 0, 0, halfHeight ), center - Vector( 0, 0, halfHeight ), collisionCenter ); - - // Our normal is the direction from that center point to the intersection point - pTrace->plane.normal = pTrace->endpos - collisionCenter; - VectorNormalize( pTrace->plane.normal ); - - return true; -} - - -bool CHL2_Player::TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ) -{ - if( g_pGameRules->IsMultiplayer() ) - { - return BaseClass::TestHitboxes( ray, fContentsMask, tr ); - } - else - { - Assert( ray.m_IsRay ); - - Vector mins, maxs; - - mins = WorldAlignMins(); - maxs = WorldAlignMaxs(); - - if ( IntersectRayWithAACylinder( ray, WorldSpaceCenter(), maxs.x * PLAYER_HULL_REDUCTION, maxs.z - mins.z, &tr ) ) - { - tr.hitbox = 0; - CStudioHdr *pStudioHdr = GetModelPtr( ); - if (!pStudioHdr) - return false; - - mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( m_nHitboxSet ); - if ( !set || !set->numhitboxes ) - return false; - - mstudiobbox_t *pbox = set->pHitbox( tr.hitbox ); - mstudiobone_t *pBone = pStudioHdr->pBone(pbox->bone); - tr.surface.name = "**studio**"; - tr.surface.flags = SURF_HITBOX; - tr.surface.surfaceProps = physprops->GetSurfaceIndex( pBone->pszSurfaceProp() ); - } - - return true; - } -} - -//--------------------------------------------------------- -// Show the player's scaled down bbox that we use for -// bullet impacts. -//--------------------------------------------------------- -void CHL2_Player::DrawDebugGeometryOverlays(void) -{ - BaseClass::DrawDebugGeometryOverlays(); - - if (m_debugOverlays & OVERLAY_BBOX_BIT) - { - Vector mins, maxs; - - mins = WorldAlignMins(); - maxs = WorldAlignMaxs(); - - mins.x *= PLAYER_HULL_REDUCTION; - mins.y *= PLAYER_HULL_REDUCTION; - - maxs.x *= PLAYER_HULL_REDUCTION; - maxs.y *= PLAYER_HULL_REDUCTION; - - NDebugOverlay::Box( GetAbsOrigin(), mins, maxs, 255, 0, 0, 100, 0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Helper to remove from ladder -//----------------------------------------------------------------------------- -void CHL2_Player::ExitLadder() -{ - if ( MOVETYPE_LADDER != GetMoveType() ) - return; - - SetMoveType( MOVETYPE_WALK ); - SetMoveCollide( MOVECOLLIDE_DEFAULT ); - // Remove from ladder - m_HL2Local.m_hLadder.Set( NULL ); -} - - -surfacedata_t *CHL2_Player::GetLadderSurface( const Vector &origin ) -{ - extern const char *FuncLadder_GetSurfaceprops(CBaseEntity *pLadderEntity); - - CBaseEntity *pLadder = m_HL2Local.m_hLadder.Get(); - if ( pLadder ) - { - const char *pSurfaceprops = FuncLadder_GetSurfaceprops(pLadder); - // get ladder material from func_ladder - return physprops->GetSurfaceData( physprops->GetSurfaceIndex( pSurfaceprops ) ); - - } - return BaseClass::GetLadderSurface(origin); -} - -//----------------------------------------------------------------------------- -// Purpose: Queues up a use deny sound, played in ItemPostFrame. -//----------------------------------------------------------------------------- -void CHL2_Player::PlayUseDenySound() -{ - m_bPlayUseDenySound = true; -} - - -void CHL2_Player::ItemPostFrame() -{ - BaseClass::ItemPostFrame(); - - if ( m_bPlayUseDenySound ) - { - m_bPlayUseDenySound = false; - EmitSound( "HL2Player.UseDeny" ); - } -} - - -void CHL2_Player::StartWaterDeathSounds( void ) -{ - CPASAttenuationFilter filter( this ); - - if ( m_sndLeeches == NULL ) - { - m_sndLeeches = (CSoundEnvelopeController::GetController()).SoundCreate( filter, entindex(), CHAN_STATIC, "coast.leech_bites_loop" , ATTN_NORM ); - } - - if ( m_sndLeeches ) - { - (CSoundEnvelopeController::GetController()).Play( m_sndLeeches, 1.0f, 100 ); - } - - if ( m_sndWaterSplashes == NULL ) - { - m_sndWaterSplashes = (CSoundEnvelopeController::GetController()).SoundCreate( filter, entindex(), CHAN_STATIC, "coast.leech_water_churn_loop" , ATTN_NORM ); - } - - if ( m_sndWaterSplashes ) - { - (CSoundEnvelopeController::GetController()).Play( m_sndWaterSplashes, 1.0f, 100 ); - } -} - -void CHL2_Player::StopWaterDeathSounds( void ) -{ - if ( m_sndLeeches ) - { - (CSoundEnvelopeController::GetController()).SoundFadeOut( m_sndLeeches, 0.5f, true ); - m_sndLeeches = NULL; - } - - if ( m_sndWaterSplashes ) - { - (CSoundEnvelopeController::GetController()).SoundFadeOut( m_sndWaterSplashes, 0.5f, true ); - m_sndWaterSplashes = NULL; - } -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -void CHL2_Player::MissedAR2AltFire() -{ - if( GetPlayerProxy() != NULL ) - { - GetPlayerProxy()->m_PlayerMissedAR2AltFire.FireOutput( this, this ); - } -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -void CHL2_Player::DisplayLadderHudHint() -{ -#if !defined( CLIENT_DLL ) - if( gpGlobals->curtime > m_flTimeNextLadderHint ) - { - m_flTimeNextLadderHint = gpGlobals->curtime + 60.0f; - - CFmtStr hint; - hint.sprintf( "#Valve_Hint_Ladder" ); - UTIL_HudHintText( this, hint.Access() ); - } -#endif//CLIENT_DLL -} - -//----------------------------------------------------------------------------- -// Shuts down sounds -//----------------------------------------------------------------------------- -void CHL2_Player::StopLoopingSounds( void ) -{ - if ( m_sndLeeches != NULL ) - { - (CSoundEnvelopeController::GetController()).SoundDestroy( m_sndLeeches ); - m_sndLeeches = NULL; - } - - if ( m_sndWaterSplashes != NULL ) - { - (CSoundEnvelopeController::GetController()).SoundDestroy( m_sndWaterSplashes ); - m_sndWaterSplashes = NULL; - } - - BaseClass::StopLoopingSounds(); -} - -//----------------------------------------------------------------------------- -void CHL2_Player::ModifyOrAppendPlayerCriteria( AI_CriteriaSet& set ) -{ - BaseClass::ModifyOrAppendPlayerCriteria( set ); - - if ( GlobalEntity_GetIndex( "gordon_precriminal" ) == -1 ) - { - set.AppendCriteria( "gordon_precriminal", "0" ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -const impactdamagetable_t &CHL2_Player::GetPhysicsImpactDamageTable() -{ - if ( m_bUseCappedPhysicsDamageTable ) - return gCappedPlayerImpactDamageTable; - - return BaseClass::GetPhysicsImpactDamageTable(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Makes a splash when the player transitions between water states -//----------------------------------------------------------------------------- -void CHL2_Player::Splash( void ) -{ - CEffectData data; - data.m_fFlags = 0; - data.m_vOrigin = GetAbsOrigin(); - data.m_vNormal = Vector(0,0,1); - data.m_vAngles = QAngle( 0, 0, 0 ); - - if ( GetWaterType() & CONTENTS_SLIME ) - { - data.m_fFlags |= FX_WATER_IN_SLIME; - } - - float flSpeed = GetAbsVelocity().Length(); - if ( flSpeed < 300 ) - { - data.m_flScale = random->RandomFloat( 10, 12 ); - DispatchEffect( "waterripple", data ); - } - else - { - data.m_flScale = random->RandomFloat( 6, 8 ); - DispatchEffect( "watersplash", data ); - } -} - -CLogicPlayerProxy *CHL2_Player::GetPlayerProxy( void ) -{ - CLogicPlayerProxy *pProxy = dynamic_cast< CLogicPlayerProxy* > ( m_hPlayerProxy.Get() ); - - if ( pProxy == NULL ) - { - pProxy = (CLogicPlayerProxy*)gEntList.FindEntityByClassname(NULL, "logic_playerproxy" ); - - if ( pProxy == NULL ) - return NULL; - - pProxy->m_hPlayer = this; - m_hPlayerProxy = pProxy; - } - - return pProxy; -} - -void CHL2_Player::FirePlayerProxyOutput( const char *pszOutputName, variant_t variant, CBaseEntity *pActivator, CBaseEntity *pCaller ) -{ - if ( GetPlayerProxy() == NULL ) - return; - - GetPlayerProxy()->FireNamedOutput( pszOutputName, variant, pActivator, pCaller ); -} - -LINK_ENTITY_TO_CLASS( logic_playerproxy, CLogicPlayerProxy); - -BEGIN_DATADESC( CLogicPlayerProxy ) - DEFINE_OUTPUT( m_OnFlashlightOn, "OnFlashlightOn" ), - DEFINE_OUTPUT( m_OnFlashlightOff, "OnFlashlightOff" ), - DEFINE_OUTPUT( m_RequestedPlayerHealth, "PlayerHealth" ), - DEFINE_OUTPUT( m_PlayerHasAmmo, "PlayerHasAmmo" ), - DEFINE_OUTPUT( m_PlayerHasNoAmmo, "PlayerHasNoAmmo" ), - DEFINE_OUTPUT( m_PlayerDied, "PlayerDied" ), - DEFINE_OUTPUT( m_PlayerMissedAR2AltFire, "PlayerMissedAR2AltFire" ), - DEFINE_INPUTFUNC( FIELD_VOID, "RequestPlayerHealth", InputRequestPlayerHealth ), - DEFINE_INPUTFUNC( FIELD_VOID, "SetFlashlightSlowDrain", InputSetFlashlightSlowDrain ), - DEFINE_INPUTFUNC( FIELD_VOID, "SetFlashlightNormalDrain", InputSetFlashlightNormalDrain ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetPlayerHealth", InputSetPlayerHealth ), - DEFINE_INPUTFUNC( FIELD_VOID, "RequestAmmoState", InputRequestAmmoState ), - DEFINE_INPUTFUNC( FIELD_VOID, "LowerWeapon", InputLowerWeapon ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableCappedPhysicsDamage", InputEnableCappedPhysicsDamage ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableCappedPhysicsDamage", InputDisableCappedPhysicsDamage ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetLocatorTargetEntity", InputSetLocatorTargetEntity ), - DEFINE_FIELD( m_hPlayer, FIELD_EHANDLE ), -END_DATADESC() - -void CLogicPlayerProxy::Activate( void ) -{ - BaseClass::Activate(); - - if ( m_hPlayer == NULL ) - { - m_hPlayer = AI_GetSinglePlayer(); - } -} - -bool CLogicPlayerProxy::PassesDamageFilter( const CTakeDamageInfo &info ) -{ - if (m_hDamageFilter) - { - CBaseFilter *pFilter = (CBaseFilter *)(m_hDamageFilter.Get()); - return pFilter->PassesDamageFilter(info); - } - - return true; -} - -void CLogicPlayerProxy::InputSetPlayerHealth( inputdata_t &inputdata ) -{ - if ( m_hPlayer == NULL ) - return; - - m_hPlayer->SetHealth( inputdata.value.Int() ); - -} - -void CLogicPlayerProxy::InputRequestPlayerHealth( inputdata_t &inputdata ) -{ - if ( m_hPlayer == NULL ) - return; - - m_RequestedPlayerHealth.Set( m_hPlayer->GetHealth(), inputdata.pActivator, inputdata.pCaller ); -} - -void CLogicPlayerProxy::InputSetFlashlightSlowDrain( inputdata_t &inputdata ) -{ - if( m_hPlayer == NULL ) - return; - - CHL2_Player *pPlayer = dynamic_cast(m_hPlayer.Get()); - - if( pPlayer ) - pPlayer->SetFlashlightPowerDrainScale( hl2_darkness_flashlight_factor.GetFloat() ); -} - -void CLogicPlayerProxy::InputSetFlashlightNormalDrain( inputdata_t &inputdata ) -{ - if( m_hPlayer == NULL ) - return; - - CHL2_Player *pPlayer = dynamic_cast(m_hPlayer.Get()); - - if( pPlayer ) - pPlayer->SetFlashlightPowerDrainScale( 1.0f ); -} - -void CLogicPlayerProxy::InputRequestAmmoState( inputdata_t &inputdata ) -{ - if( m_hPlayer == NULL ) - return; - - CHL2_Player *pPlayer = dynamic_cast(m_hPlayer.Get()); - - for ( int i = 0 ; i < pPlayer->WeaponCount(); ++i ) - { - CBaseCombatWeapon* pCheck = pPlayer->GetWeapon( i ); - - if ( pCheck ) - { - if ( pCheck->HasAnyAmmo() && (pCheck->UsesPrimaryAmmo() || pCheck->UsesSecondaryAmmo())) - { - m_PlayerHasAmmo.FireOutput( this, this, 0 ); - return; - } - } - } - - m_PlayerHasNoAmmo.FireOutput( this, this, 0 ); -} - -void CLogicPlayerProxy::InputLowerWeapon( inputdata_t &inputdata ) -{ - if( m_hPlayer == NULL ) - return; - - CHL2_Player *pPlayer = dynamic_cast(m_hPlayer.Get()); - - pPlayer->Weapon_Lower(); -} - -void CLogicPlayerProxy::InputEnableCappedPhysicsDamage( inputdata_t &inputdata ) -{ - if( m_hPlayer == NULL ) - return; - - CHL2_Player *pPlayer = dynamic_cast(m_hPlayer.Get()); - pPlayer->EnableCappedPhysicsDamage(); -} - -void CLogicPlayerProxy::InputDisableCappedPhysicsDamage( inputdata_t &inputdata ) -{ - if( m_hPlayer == NULL ) - return; - - CHL2_Player *pPlayer = dynamic_cast(m_hPlayer.Get()); - pPlayer->DisableCappedPhysicsDamage(); -} - -void CLogicPlayerProxy::InputSetLocatorTargetEntity( inputdata_t &inputdata ) -{ - if( m_hPlayer == NULL ) - return; - - CBaseEntity *pTarget = NULL; // assume no target - string_t iszTarget = MAKE_STRING( inputdata.value.String() ); - - if( iszTarget != NULL_STRING ) - { - pTarget = gEntList.FindEntityByName( NULL, iszTarget ); - } - - CHL2_Player *pPlayer = dynamic_cast(m_hPlayer.Get()); - pPlayer->SetLocatorTargetEntity(pTarget); -} - diff --git a/game/server/hl2/hl2_player.h b/game/server/hl2/hl2_player.h deleted file mode 100644 index 2e2a8f10a..000000000 --- a/game/server/hl2/hl2_player.h +++ /dev/null @@ -1,385 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Player for HL2. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef HL2_PLAYER_H -#define HL2_PLAYER_H -#pragma once - - -#include "player.h" -#include "hl2_playerlocaldata.h" -#include "simtimer.h" -#include "soundenvelope.h" - -class CAI_Squad; -class CPropCombineBall; - -extern int TrainSpeed(int iSpeed, int iMax); -extern void CopyToBodyQue( CBaseAnimating *pCorpse ); - -#define ARMOR_DECAY_TIME 3.5f - -enum HL2PlayerPhysFlag_e -{ - // 1 -- 5 are used by enum PlayerPhysFlag_e in player.h - - PFLAG_ONBARNACLE = ( 1<<6 ) // player is hangning from the barnalce -}; - -class IPhysicsPlayerController; -class CLogicPlayerProxy; - -struct commandgoal_t -{ - Vector m_vecGoalLocation; - CBaseEntity *m_pGoalEntity; -}; - -// Time between checks to determine whether NPCs are illuminated by the flashlight -#define FLASHLIGHT_NPC_CHECK_INTERVAL 0.4 - -//---------------------------------------------------- -// Definitions for weapon slots -//---------------------------------------------------- -#define WEAPON_MELEE_SLOT 0 -#define WEAPON_SECONDARY_SLOT 1 -#define WEAPON_PRIMARY_SLOT 2 -#define WEAPON_EXPLOSIVE_SLOT 3 -#define WEAPON_TOOL_SLOT 4 - -//============================================================================= -//============================================================================= -class CSuitPowerDevice -{ -public: - CSuitPowerDevice( int bitsID, float flDrainRate ) { m_bitsDeviceID = bitsID; m_flDrainRate = flDrainRate; } -private: - int m_bitsDeviceID; // tells what the device is. DEVICE_SPRINT, DEVICE_FLASHLIGHT, etc. BITMASK!!!!! - float m_flDrainRate; // how quickly does this device deplete suit power? ( percent per second ) - -public: - int GetDeviceID( void ) const { return m_bitsDeviceID; } - float GetDeviceDrainRate( void ) const - { - if( g_pGameRules->GetSkillLevel() == SKILL_EASY && hl2_episodic.GetBool() && !(GetDeviceID()&bits_SUIT_DEVICE_SPRINT) ) - return m_flDrainRate * 0.5f; - else - return m_flDrainRate; - } -}; - -//============================================================================= -// >> HL2_PLAYER -//============================================================================= -class CHL2_Player : public CBasePlayer -{ -public: - DECLARE_CLASS( CHL2_Player, CBasePlayer ); - - CHL2_Player(); - ~CHL2_Player( void ); - - static CHL2_Player *CreatePlayer( const char *className, edict_t *ed ) - { - CHL2_Player::s_PlayerEdict = ed; - return (CHL2_Player*)CreateEntityByName( className ); - } - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - virtual void CreateCorpse( void ) { CopyToBodyQue( this ); }; - - virtual void Precache( void ); - virtual void Spawn(void); - virtual void Activate( void ); - virtual void CheatImpulseCommands( int iImpulse ); - virtual void PlayerRunCommand( CUserCmd *ucmd, IMoveHelper *moveHelper); - virtual void PlayerUse ( void ); - virtual void SuspendUse( float flDuration ) { m_flTimeUseSuspended = gpGlobals->curtime + flDuration; } - virtual void UpdateClientData( void ); - virtual void OnRestore(); - virtual void StopLoopingSounds( void ); - virtual void Splash( void ); - virtual void ModifyOrAppendPlayerCriteria( AI_CriteriaSet& set ); - - void DrawDebugGeometryOverlays(void); - - virtual Vector EyeDirection2D( void ); - virtual Vector EyeDirection3D( void ); - - virtual void CommanderMode(); - - virtual bool ClientCommand( const CCommand &args ); - - // from cbasecombatcharacter - void InitVCollision( const Vector &vecAbsOrigin, const Vector &vecAbsVelocity ); - WeaponProficiency_t CalcWeaponProficiency( CBaseCombatWeapon *pWeapon ); - - Class_T Classify ( void ); - - // from CBasePlayer - virtual void SetupVisibility( CBaseEntity *pViewEntity, unsigned char *pvs, int pvssize ); - - // Suit Power Interface - void SuitPower_Update( void ); - bool SuitPower_Drain( float flPower ); // consume some of the suit's power. - void SuitPower_Charge( float flPower ); // add suit power. - void SuitPower_SetCharge( float flPower ) { m_HL2Local.m_flSuitPower = flPower; } - void SuitPower_Initialize( void ); - bool SuitPower_IsDeviceActive( const CSuitPowerDevice &device ); - bool SuitPower_AddDevice( const CSuitPowerDevice &device ); - bool SuitPower_RemoveDevice( const CSuitPowerDevice &device ); - bool SuitPower_ShouldRecharge( void ); - float SuitPower_GetCurrentPercentage( void ) { return m_HL2Local.m_flSuitPower; } - - void SetFlashlightEnabled( bool bState ); - - // Apply a battery - bool ApplyBattery( float powerMultiplier = 1.0 ); - - // Commander Mode for controller NPCs - enum CommanderCommand_t - { - CC_NONE, - CC_TOGGLE, - CC_FOLLOW, - CC_SEND, - }; - - void CommanderUpdate(); - void CommanderExecute( CommanderCommand_t command = CC_TOGGLE ); - bool CommanderFindGoal( commandgoal_t *pGoal ); - void NotifyFriendsOfDamage( CBaseEntity *pAttackerEntity ); - CAI_BaseNPC *GetSquadCommandRepresentative(); - int GetNumSquadCommandables(); - int GetNumSquadCommandableMedics(); - - // Locator - void UpdateLocatorPosition( const Vector &vecPosition ); - - // Sprint Device - void StartAutoSprint( void ); - void StartSprinting( void ); - void StopSprinting( void ); - void InitSprinting( void ); - bool IsSprinting( void ) { return m_fIsSprinting; } - bool CanSprint( void ); - void EnableSprint( bool bEnable); - - bool CanZoom( CBaseEntity *pRequester ); - void ToggleZoom(void); - void StartZooming( void ); - void StopZooming( void ); - bool IsZooming( void ); - void CheckSuitZoom( void ); - - // Walking - void StartWalking( void ); - void StopWalking( void ); - bool IsWalking( void ) { return m_fIsWalking; } - - // Aiming heuristics accessors - virtual float GetIdleTime( void ) const { return ( m_flIdleTime - m_flMoveTime ); } - virtual float GetMoveTime( void ) const { return ( m_flMoveTime - m_flIdleTime ); } - virtual float GetLastDamageTime( void ) const { return m_flLastDamageTime; } - virtual bool IsDucking( void ) const { return !!( GetFlags() & FL_DUCKING ); } - - virtual bool PassesDamageFilter( const CTakeDamageInfo &info ); - void InputIgnoreFallDamage( inputdata_t &inputdata ); - void InputIgnoreFallDamageWithoutReset( inputdata_t &inputdata ); - void InputEnableFlashlight( inputdata_t &inputdata ); - void InputDisableFlashlight( inputdata_t &inputdata ); - - const impactdamagetable_t &GetPhysicsImpactDamageTable(); - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - virtual void OnDamagedByExplosion( const CTakeDamageInfo &info ); - bool ShouldShootMissTarget( CBaseCombatCharacter *pAttacker ); - - void CombineBallSocketed( CPropCombineBall *pCombineBall ); - - virtual void Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info ); - - virtual void GetAutoaimVector( autoaim_params_t ¶ms ); - bool ShouldKeepLockedAutoaimTarget( EHANDLE hLockedTarget ); - - void SetLocatorTargetEntity( CBaseEntity *pEntity ) { m_hLocatorTargetEntity.Set( pEntity ); } - - virtual int GiveAmmo( int nCount, int nAmmoIndex, bool bSuppressSound); - virtual bool BumpWeapon( CBaseCombatWeapon *pWeapon ); - - virtual bool Weapon_CanUse( CBaseCombatWeapon *pWeapon ); - virtual void Weapon_Equip( CBaseCombatWeapon *pWeapon ); - virtual bool Weapon_Lower( void ); - virtual bool Weapon_Ready( void ); - virtual bool Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmodelindex = 0 ); - virtual bool Weapon_CanSwitchTo( CBaseCombatWeapon *pWeapon ); - - void FirePlayerProxyOutput( const char *pszOutputName, variant_t variant, CBaseEntity *pActivator, CBaseEntity *pCaller ); - - CLogicPlayerProxy *GetPlayerProxy( void ); - - // Flashlight Device - void CheckFlashlight( void ); - int FlashlightIsOn( void ); - void FlashlightTurnOn( void ); - void FlashlightTurnOff( void ); - bool IsIlluminatedByFlashlight( CBaseEntity *pEntity, float *flReturnDot ); - void SetFlashlightPowerDrainScale( float flScale ) { m_flFlashlightPowerDrainScale = flScale; } - - // Underwater breather device - virtual void SetPlayerUnderwater( bool state ); - virtual bool CanBreatheUnderwater() const { return m_HL2Local.m_flSuitPower > 0.0f; } - - // physics interactions - virtual void PickupObject( CBaseEntity *pObject, bool bLimitMassAndSize ); - virtual bool IsHoldingEntity( CBaseEntity *pEnt ); - virtual void ForceDropOfCarriedPhysObjects( CBaseEntity *pOnlyIfHoldindThis ); - virtual float GetHeldObjectMass( IPhysicsObject *pHeldObject ); - virtual CBaseEntity *GetHeldObject( void ); - - virtual bool IsFollowingPhysics( void ) { return (m_afPhysicsFlags & PFLAG_ONBARNACLE) > 0; } - void InputForceDropPhysObjects( inputdata_t &data ); - - virtual void Event_Killed( const CTakeDamageInfo &info ); - void NotifyScriptsOfDeath( void ); - - // override the test for getting hit - virtual bool TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ); - - LadderMove_t *GetLadderMove() { return &m_HL2Local.m_LadderMove; } - virtual void ExitLadder(); - virtual surfacedata_t *GetLadderSurface( const Vector &origin ); - - virtual void EquipSuit( bool bPlayEffects = true ); - virtual void RemoveSuit( void ); - void HandleAdmireGlovesAnimation( void ); - void StartAdmireGlovesAnimation( void ); - - void HandleSpeedChanges( void ); - - void SetControlClass( Class_T controlClass ) { m_nControlClass = controlClass; } - - void StartWaterDeathSounds( void ); - void StopWaterDeathSounds( void ); - - bool IsWeaponLowered( void ) { return m_HL2Local.m_bWeaponLowered; } - void HandleArmorReduction( void ); - void StartArmorReduction( void ) { m_flArmorReductionTime = gpGlobals->curtime + ARMOR_DECAY_TIME; - m_iArmorReductionFrom = ArmorValue(); - } - - void MissedAR2AltFire(); - - inline void EnableCappedPhysicsDamage(); - inline void DisableCappedPhysicsDamage(); - - // HUD HINTS - void DisplayLadderHudHint(); - - CSoundPatch *m_sndLeeches; - CSoundPatch *m_sndWaterSplashes; - -protected: - virtual void PreThink( void ); - virtual void PostThink( void ); - virtual bool HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt); - - virtual void UpdateWeaponPosture( void ); - - virtual void ItemPostFrame(); - virtual void PlayUseDenySound(); - -private: - bool CommanderExecuteOne( CAI_BaseNPC *pNpc, const commandgoal_t &goal, CAI_BaseNPC **Allies, int numAllies ); - - void OnSquadMemberKilled( inputdata_t &data ); - - Class_T m_nControlClass; // Class when player is controlling another entity - // This player's HL2 specific data that should only be replicated to - // the player and not to other players. - CNetworkVarEmbedded( CHL2PlayerLocalData, m_HL2Local ); - - float m_flTimeAllSuitDevicesOff; - - bool m_bSprintEnabled; // Used to disable sprint temporarily - bool m_bIsAutoSprinting; // A proxy for holding down the sprint key. - float m_fAutoSprintMinTime; // Minimum time to maintain autosprint regardless of player speed. - - CNetworkVar( bool, m_fIsSprinting ); - CNetworkVarForDerived( bool, m_fIsWalking ); - -protected: // Jeep: Portal_Player needs access to this variable to overload PlayerUse for picking up objects through portals - bool m_bPlayUseDenySound; // Signaled by PlayerUse, but can be unset by HL2 ladder code... - -private: - - CAI_Squad * m_pPlayerAISquad; - CSimpleSimTimer m_CommanderUpdateTimer; - float m_RealTimeLastSquadCommand; - CommanderCommand_t m_QueuedCommand; - - Vector m_vecMissPositions[16]; - int m_nNumMissPositions; - - float m_flTimeIgnoreFallDamage; - bool m_bIgnoreFallDamageResetAfterImpact; - - // Suit power fields - float m_flSuitPowerLoad; // net suit power drain (total of all device's drainrates) - float m_flAdmireGlovesAnimTime; - - float m_flNextFlashlightCheckTime; - float m_flFlashlightPowerDrainScale; - - // Aiming heuristics code - float m_flIdleTime; //Amount of time we've been motionless - float m_flMoveTime; //Amount of time we've been in motion - float m_flLastDamageTime; //Last time we took damage - float m_flTargetFindTime; - - EHANDLE m_hPlayerProxy; - - bool m_bFlashlightDisabled; - bool m_bUseCappedPhysicsDamageTable; - - float m_flArmorReductionTime; - int m_iArmorReductionFrom; - - float m_flTimeUseSuspended; - - CSimpleSimTimer m_LowerWeaponTimer; - CSimpleSimTimer m_AutoaimTimer; - - EHANDLE m_hLockedAutoAimEntity; - - EHANDLE m_hLocatorTargetEntity; // The entity that's being tracked by the suit locator. - - float m_flTimeNextLadderHint; // Next time we're eligible to display a HUD hint about a ladder. - - friend class CHL2GameMovement; -}; - - -//----------------------------------------------------------------------------- -// FIXME: find a better way to do this -// Switches us to a physics damage table that caps the max damage. -//----------------------------------------------------------------------------- -void CHL2_Player::EnableCappedPhysicsDamage() -{ - m_bUseCappedPhysicsDamageTable = true; -} - - -void CHL2_Player::DisableCappedPhysicsDamage() -{ - m_bUseCappedPhysicsDamageTable = false; -} - - -#endif //HL2_PLAYER_H diff --git a/game/server/hl2/hl2_playerlocaldata.cpp b/game/server/hl2/hl2_playerlocaldata.cpp deleted file mode 100644 index c3916a6a6..000000000 --- a/game/server/hl2/hl2_playerlocaldata.cpp +++ /dev/null @@ -1,69 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "hl2_playerlocaldata.h" -#include "hl2_player.h" -#include "mathlib/mathlib.h" -#include "entitylist.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -BEGIN_SEND_TABLE_NOBASE( CHL2PlayerLocalData, DT_HL2Local ) - SendPropFloat( SENDINFO(m_flSuitPower), 10, SPROP_UNSIGNED | SPROP_ROUNDUP, 0.0, 100.0 ), - SendPropInt( SENDINFO(m_bZooming), 1, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_bitsActiveDevices), MAX_SUIT_DEVICES, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_iSquadMemberCount) ), - SendPropInt( SENDINFO(m_iSquadMedicCount) ), - SendPropBool( SENDINFO(m_fSquadInFollowMode) ), - SendPropBool( SENDINFO(m_bWeaponLowered) ), - SendPropEHandle( SENDINFO(m_hAutoAimTarget) ), - SendPropVector( SENDINFO(m_vecAutoAimPoint) ), - SendPropEHandle( SENDINFO(m_hLadder) ), - SendPropBool( SENDINFO(m_bDisplayReticle) ), - SendPropBool( SENDINFO(m_bStickyAutoAim) ), - SendPropBool( SENDINFO(m_bAutoAimTarget) ), -#ifdef HL2_EPISODIC - SendPropFloat( SENDINFO(m_flFlashBattery) ), - SendPropVector( SENDINFO(m_vecLocatorOrigin) ), -#endif -END_SEND_TABLE() - -BEGIN_SIMPLE_DATADESC( CHL2PlayerLocalData ) - DEFINE_FIELD( m_flSuitPower, FIELD_FLOAT ), - DEFINE_FIELD( m_bZooming, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bitsActiveDevices, FIELD_INTEGER ), - DEFINE_FIELD( m_iSquadMemberCount, FIELD_INTEGER ), - DEFINE_FIELD( m_iSquadMedicCount, FIELD_INTEGER ), - DEFINE_FIELD( m_fSquadInFollowMode, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bWeaponLowered, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bDisplayReticle, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bStickyAutoAim, FIELD_BOOLEAN ), -#ifdef HL2_EPISODIC - DEFINE_FIELD( m_flFlashBattery, FIELD_FLOAT ), - DEFINE_FIELD( m_vecLocatorOrigin, FIELD_POSITION_VECTOR ), -#endif - // Ladder related stuff - DEFINE_FIELD( m_hLadder, FIELD_EHANDLE ), - DEFINE_EMBEDDED( m_LadderMove ), -END_DATADESC() - -CHL2PlayerLocalData::CHL2PlayerLocalData() -{ - m_flSuitPower = 0.0; - m_bZooming = false; - m_bWeaponLowered = false; - m_hAutoAimTarget.Set(NULL); - m_hLadder.Set(NULL); - m_vecAutoAimPoint.GetForModify().Init(); - m_bDisplayReticle = false; -#ifdef HL2_EPISODIC - m_flFlashBattery = 0.0f; -#endif -} - diff --git a/game/server/hl2/hl2_playerlocaldata.h b/game/server/hl2/hl2_playerlocaldata.h deleted file mode 100644 index 1ecf64b07..000000000 --- a/game/server/hl2/hl2_playerlocaldata.h +++ /dev/null @@ -1,56 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef HL2_PLAYERLOCALDATA_H -#define HL2_PLAYERLOCALDATA_H -#ifdef _WIN32 -#pragma once -#endif - -#include "networkvar.h" - -#include "hl_movedata.h" - -//----------------------------------------------------------------------------- -// Purpose: Player specific data for HL2 ( sent only to local player, too ) -//----------------------------------------------------------------------------- -class CHL2PlayerLocalData -{ -public: - // Save/restore - DECLARE_SIMPLE_DATADESC(); - DECLARE_CLASS_NOBASE( CHL2PlayerLocalData ); - DECLARE_EMBEDDED_NETWORKVAR(); - - CHL2PlayerLocalData(); - - CNetworkVar( float, m_flSuitPower ); - CNetworkVar( bool, m_bZooming ); - CNetworkVar( int, m_bitsActiveDevices ); - CNetworkVar( int, m_iSquadMemberCount ); - CNetworkVar( int, m_iSquadMedicCount ); - CNetworkVar( bool, m_fSquadInFollowMode ); - CNetworkVar( bool, m_bWeaponLowered ); - CNetworkVar( EHANDLE, m_hAutoAimTarget ); - CNetworkVar( Vector, m_vecAutoAimPoint ); - CNetworkVar( bool, m_bDisplayReticle ); - CNetworkVar( bool, m_bStickyAutoAim ); - CNetworkVar( bool, m_bAutoAimTarget ); -#ifdef HL2_EPISODIC - CNetworkVar( float, m_flFlashBattery ); - CNetworkVar( Vector, m_vecLocatorOrigin ); -#endif - - // Ladder related data - CNetworkVar( EHANDLE, m_hLadder ); - LadderMove_t m_LadderMove; -}; - -EXTERN_SEND_TABLE(DT_HL2Local); - - -#endif // HL2_PLAYERLOCALDATA_H diff --git a/game/server/hl2/hl2_triggers.cpp b/game/server/hl2/hl2_triggers.cpp deleted file mode 100644 index e441faa49..000000000 --- a/game/server/hl2/hl2_triggers.cpp +++ /dev/null @@ -1,875 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "weapon_physcannon.h" -#include "hl2_player.h" -#include "saverestore_utlvector.h" -#include "triggers.h" - -//----------------------------------------------------------------------------- -// Weapon-dissolve trigger; all weapons in this field (sans the physcannon) are destroyed! -//----------------------------------------------------------------------------- -class CTriggerWeaponDissolve : public CTriggerMultiple -{ - DECLARE_CLASS( CTriggerWeaponDissolve, CTriggerMultiple ); - DECLARE_DATADESC(); - -public: - ~CTriggerWeaponDissolve( void ); - - virtual void Spawn( void ); - virtual void Precache( void ); - virtual void Activate( void ); - virtual void StartTouch( CBaseEntity *pOther ); - - inline bool HasWeapon( CBaseCombatWeapon *pWeapon ); - - Vector GetConduitPoint( CBaseEntity *pTarget ); - - void InputStopSound( inputdata_t &inputdata ); - - void AddWeapon( CBaseCombatWeapon *pWeapon ); - void CreateBeam( const Vector &vecSource, CBaseEntity *pDest, float flLifetime ); - void DissolveThink( void ); - -private: - - COutputEvent m_OnDissolveWeapon; - COutputEvent m_OnChargingPhyscannon; - - CUtlVector< CHandle > m_pWeapons; - CUtlVector< CHandle > m_pConduitPoints; - string_t m_strEmitterName; - int m_spriteTexture; -}; - -LINK_ENTITY_TO_CLASS( trigger_weapon_dissolve, CTriggerWeaponDissolve ); - -BEGIN_DATADESC( CTriggerWeaponDissolve ) - - DEFINE_KEYFIELD( m_strEmitterName, FIELD_STRING, "emittername" ), - DEFINE_UTLVECTOR( m_pWeapons, FIELD_EHANDLE ), - DEFINE_UTLVECTOR( m_pConduitPoints, FIELD_EHANDLE ), - DEFINE_FIELD( m_spriteTexture, FIELD_MODELINDEX ), - - DEFINE_OUTPUT( m_OnDissolveWeapon, "OnDissolveWeapon" ), - DEFINE_OUTPUT( m_OnChargingPhyscannon, "OnChargingPhyscannon" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "StopSound", InputStopSound ), - - DEFINE_THINKFUNC( DissolveThink ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Destructor -//----------------------------------------------------------------------------- -CTriggerWeaponDissolve::~CTriggerWeaponDissolve( void ) -{ - m_pWeapons.Purge(); - m_pConduitPoints.Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: Call precache for our sprite texture -//----------------------------------------------------------------------------- -void CTriggerWeaponDissolve::Spawn( void ) -{ - BaseClass::Spawn(); - Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: Precache our sprite texture -//----------------------------------------------------------------------------- -void CTriggerWeaponDissolve::Precache( void ) -{ - BaseClass::Precache(); - - m_spriteTexture = PrecacheModel( "sprites/lgtning.vmt" ); - - PrecacheScriptSound( "WeaponDissolve.Dissolve" ); - PrecacheScriptSound( "WeaponDissolve.Charge" ); - PrecacheScriptSound( "WeaponDissolve.Beam" ); -} - -static const char *s_pDissolveThinkContext = "DissolveThinkContext"; - -//----------------------------------------------------------------------------- -// Purpose: Collect all our known conduit points -//----------------------------------------------------------------------------- -void CTriggerWeaponDissolve::Activate( void ) -{ - BaseClass::Activate(); - - CBaseEntity *pEntity = NULL; - - while ( ( pEntity = gEntList.FindEntityByName( pEntity, m_strEmitterName ) ) != NULL ) - { - m_pConduitPoints.AddToTail( pEntity ); - } - - SetContextThink( &CTriggerWeaponDissolve::DissolveThink, gpGlobals->curtime + 0.1f, s_pDissolveThinkContext ); -} - -//----------------------------------------------------------------------------- -// Purpose: Checks to see if a weapon is already known -// Input : *pWeapon - weapon to check for -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CTriggerWeaponDissolve::HasWeapon( CBaseCombatWeapon *pWeapon ) -{ - if ( m_pWeapons.Find( pWeapon ) == m_pWeapons.InvalidIndex() ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Adds a weapon to the known weapon list -// Input : *pWeapon - weapon to add -//----------------------------------------------------------------------------- -void CTriggerWeaponDissolve::AddWeapon( CBaseCombatWeapon *pWeapon ) -{ - if ( HasWeapon( pWeapon ) ) - return; - - m_pWeapons.AddToTail( pWeapon ); -} - -//----------------------------------------------------------------------------- -// Purpose: Collect any weapons inside our volume -// Input : *pOther - -//----------------------------------------------------------------------------- -void CTriggerWeaponDissolve::StartTouch( CBaseEntity *pOther ) -{ - BaseClass::StartTouch( pOther ); - - if ( PassesTriggerFilters( pOther ) == false ) - return; - - CBaseCombatWeapon *pWeapon = dynamic_cast(pOther); - - if ( pWeapon == NULL ) - return; - - AddWeapon( pWeapon ); -} - -//----------------------------------------------------------------------------- -// Purpose: Creates a beam between a conduit point and a weapon -// Input : &vecSource - conduit point -// *pDest - weapon -// flLifetime - amount of time -//----------------------------------------------------------------------------- -void CTriggerWeaponDissolve::CreateBeam( const Vector &vecSource, CBaseEntity *pDest, float flLifetime ) -{ - CBroadcastRecipientFilter filter; - - te->BeamEntPoint( filter, 0.0, - 0, - &vecSource, - pDest->entindex(), - &(pDest->WorldSpaceCenter()), - m_spriteTexture, - 0, // No halo - 1, // Frame - 30, - flLifetime, - 16.0f, // Start width - 4.0f, // End width - 0, // No fade - 8, // Amplitude - 255, - 255, - 255, - 255, - 16 ); // Speed -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the closest conduit point to a weapon -// Input : *pTarget - weapon to check for -// Output : Vector - position of the conduit -//----------------------------------------------------------------------------- -Vector CTriggerWeaponDissolve::GetConduitPoint( CBaseEntity *pTarget ) -{ - float nearDist = 9999999.0f; - Vector bestPoint = vec3_origin; - float testDist; - - // Find the nearest conduit to the target - for ( int i = 0; i < m_pConduitPoints.Count(); i++ ) - { - testDist = ( m_pConduitPoints[i]->GetAbsOrigin() - pTarget->GetAbsOrigin() ).LengthSqr(); - - if ( testDist < nearDist ) - { - bestPoint = m_pConduitPoints[i]->GetAbsOrigin(); - nearDist = testDist; - } - } - - return bestPoint; -} - -//----------------------------------------------------------------------------- -// Purpose: Dissolve all weapons within our volume -//----------------------------------------------------------------------------- -void CTriggerWeaponDissolve::DissolveThink( void ) -{ - int numWeapons = m_pWeapons.Count(); - - // Dissolve all the items within the volume - for ( int i = 0; i < numWeapons; i++ ) - { - CBaseCombatWeapon *pWeapon = m_pWeapons[i]; - Vector vecConduit = GetConduitPoint( pWeapon ); - - // The physcannon upgrades when this happens - if ( FClassnameIs( pWeapon, "weapon_physcannon" ) ) - { - // This must be the last weapon for us to care - if ( numWeapons > 1 ) - continue; - - //FIXME: Make them do this on a stagger! - - // All conduits send power to the weapon - for ( int i = 0; i < m_pConduitPoints.Count(); i++ ) - { - CreateBeam( m_pConduitPoints[i]->GetAbsOrigin(), pWeapon, 4.0f ); - } - - PhysCannonBeginUpgrade( pWeapon ); - m_OnChargingPhyscannon.FireOutput( this, this ); - - EmitSound( "WeaponDissolve.Beam" ); - - // We're done - m_pWeapons.Purge(); - m_pConduitPoints.Purge(); - SetContextThink( NULL, 0, s_pDissolveThinkContext ); - return; - } - - // Randomly dissolve them all - float flLifetime = random->RandomFloat( 2.5f, 4.0f ); - CreateBeam( vecConduit, pWeapon, flLifetime ); - pWeapon->Dissolve( NULL, gpGlobals->curtime + ( 3.0f - flLifetime ), false ); - - m_OnDissolveWeapon.FireOutput( this, this ); - - CPASAttenuationFilter filter( pWeapon ); - EmitSound( filter, pWeapon->entindex(), "WeaponDissolve.Dissolve" ); - - // Beam looping sound - EmitSound( "WeaponDissolve.Beam" ); - - m_pWeapons.Remove( i ); - SetContextThink( &CTriggerWeaponDissolve::DissolveThink, gpGlobals->curtime + random->RandomFloat( 0.5f, 1.5f ), s_pDissolveThinkContext ); - return; - } - - SetContextThink( &CTriggerWeaponDissolve::DissolveThink, gpGlobals->curtime + 0.1f, s_pDissolveThinkContext ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CTriggerWeaponDissolve::InputStopSound( inputdata_t &inputdata ) -{ - StopSound( "WeaponDissolve.Beam" ); - StopSound( "WeaponDissolve.Charge" ); -} - -//----------------------------------------------------------------------------- -// Weapon-strip trigger; can't pick up weapons while in the field -//----------------------------------------------------------------------------- -class CTriggerWeaponStrip : public CTriggerMultiple -{ - DECLARE_CLASS( CTriggerWeaponStrip, CTriggerMultiple ); - DECLARE_DATADESC(); - -public: - void StartTouch(CBaseEntity *pOther); - void EndTouch(CBaseEntity *pOther); - -private: - bool m_bKillWeapons; -}; - - -//----------------------------------------------------------------------------- -// Save/load -//----------------------------------------------------------------------------- -LINK_ENTITY_TO_CLASS( trigger_weapon_strip, CTriggerWeaponStrip ); - -BEGIN_DATADESC( CTriggerWeaponStrip ) - DEFINE_KEYFIELD( m_bKillWeapons, FIELD_BOOLEAN, "KillWeapons" ), -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Drops all weapons, marks the character as not being able to pick up weapons -//----------------------------------------------------------------------------- -void CTriggerWeaponStrip::StartTouch(CBaseEntity *pOther) -{ - BaseClass::StartTouch( pOther ); - - if ( PassesTriggerFilters(pOther) == false ) - return; - - CBaseCombatCharacter *pCharacter = pOther->MyCombatCharacterPointer(); - - if ( m_bKillWeapons ) - { - for ( int i = 0 ; i < pCharacter->WeaponCount(); ++i ) - { - CBaseCombatWeapon *pWeapon = pCharacter->GetWeapon( i ); - if ( !pWeapon ) - continue; - - pCharacter->Weapon_Drop( pWeapon ); - UTIL_Remove( pWeapon ); - } - return; - } - - // Strip the player of his weapons - if ( pCharacter && pCharacter->IsAllowedToPickupWeapons() ) - { - CBaseCombatWeapon *pBugbait = pCharacter->Weapon_OwnsThisType( "weapon_bugbait" ); - if ( pBugbait ) - { - pCharacter->Weapon_Drop( pBugbait ); - UTIL_Remove( pBugbait ); - } - - pCharacter->Weapon_DropAll( true ); - pCharacter->SetPreventWeaponPickup( true ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Called when an entity stops touching us. -// Input : pOther - The entity that was touching us. -//----------------------------------------------------------------------------- -void CTriggerWeaponStrip::EndTouch(CBaseEntity *pOther) -{ - if ( IsTouching( pOther ) ) - { - CBaseCombatCharacter *pCharacter = pOther->MyCombatCharacterPointer(); - if ( pCharacter ) - { - pCharacter->SetPreventWeaponPickup( false ); - } - } - - BaseClass::EndTouch( pOther ); -} - - - -//----------------------------------------------------------------------------- -// Teleport trigger -//----------------------------------------------------------------------------- -class CTriggerPhysicsTrap : public CTriggerMultiple -{ - DECLARE_CLASS( CTriggerPhysicsTrap, CTriggerMultiple ); - DECLARE_DATADESC(); - -public: - void Touch( CBaseEntity *pOther ); - -private: - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - void InputToggle( inputdata_t &inputdata ); - - int m_nDissolveType; -}; - - -//----------------------------------------------------------------------------- -// Save/load -//----------------------------------------------------------------------------- -LINK_ENTITY_TO_CLASS( trigger_physics_trap, CTriggerPhysicsTrap ); - -BEGIN_DATADESC( CTriggerPhysicsTrap ) - - DEFINE_KEYFIELD( m_nDissolveType, FIELD_INTEGER, "dissolvetype" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - -END_DATADESC() - -//------------------------------------------------------------------------------ -// Inputs -//------------------------------------------------------------------------------ -void CTriggerPhysicsTrap::InputToggle( inputdata_t &inputdata ) -{ - if ( m_bDisabled ) - { - InputEnable( inputdata ); - } - else - { - InputDisable( inputdata ); - } -} - -void CTriggerPhysicsTrap::InputEnable( inputdata_t &inputdata ) -{ - if ( m_bDisabled ) - { - Enable(); - } -} - -void CTriggerPhysicsTrap::InputDisable( inputdata_t &inputdata ) -{ - if ( !m_bDisabled ) - { - Disable(); - } -} - -//----------------------------------------------------------------------------- -// Traps the entities -//----------------------------------------------------------------------------- -#define JOINTS_TO_CONSTRAIN 1 - -void CTriggerPhysicsTrap::Touch( CBaseEntity *pOther ) -{ - if ( !PassesTriggerFilters(pOther) ) - return; - - CBaseAnimating *pAnim = pOther->GetBaseAnimating(); - if ( !pAnim ) - return; - -#ifdef HL2_DLL - // HACK: Upgrade the physcannon - if ( FClassnameIs( pAnim, "weapon_physcannon" ) ) - { - PhysCannonBeginUpgrade( pAnim ); - return; - } -#endif - - pAnim->Dissolve( NULL, gpGlobals->curtime, false, m_nDissolveType ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -class CWateryDeathLeech : public CBaseAnimating -{ - DECLARE_CLASS( CWateryDeathLeech, CBaseAnimating ); -public: - DECLARE_DATADESC(); - - void Spawn( void ); - void Precache( void ); - void LeechThink( void ); - - int m_iFadeState; -}; - -LINK_ENTITY_TO_CLASS( ent_watery_leech, CWateryDeathLeech ); - -BEGIN_DATADESC( CWateryDeathLeech ) - DEFINE_THINKFUNC( LeechThink ), - DEFINE_FIELD( m_iFadeState, FIELD_INTEGER ), -END_DATADESC() - -void CWateryDeathLeech::Precache( void ) -{ - //Ugh this is temporary until Jakob finishes the animations and doesn't need the command anymore. - bool allowPrecache = CBaseEntity::IsPrecacheAllowed(); - CBaseEntity::SetAllowPrecache( true ); - - BaseClass::Precache(); - - PrecacheModel( "models/leech.mdl" ); - CBaseEntity::SetAllowPrecache( allowPrecache ); -} - -void CWateryDeathLeech::Spawn( void ) -{ - Precache(); - BaseClass::Spawn(); - - SetSolid ( SOLID_NONE ); - - SetMoveType( MOVETYPE_NONE ); - AddEffects( EF_NOSHADOW ); - - SetModel( "models/leech.mdl" ); - - SetThink( &CWateryDeathLeech::LeechThink ); - SetNextThink( gpGlobals->curtime + 0.1 ); - - m_flPlaybackRate = random->RandomFloat( 0.5, 1.5 ); - SetCycle( random->RandomFloat( 0.0f, 0.9f ) ); - - QAngle vAngle; - vAngle[YAW] = random->RandomFloat( 0, 360 ); - SetAbsAngles( vAngle ); - - m_iFadeState = 1; - SetRenderColorA( 1 ); -} - -void CWateryDeathLeech::LeechThink( void ) -{ - if ( IsMarkedForDeletion() ) - return; - - StudioFrameAdvance(); - SetNextThink( gpGlobals->curtime + 0.1 ); - - if ( m_iFadeState != 0 ) - { - float dt = gpGlobals->frametime; - if ( dt > 0.1f ) - { - dt = 0.1f; - } - m_nRenderMode = kRenderTransTexture; - int speed = (int)MAX(1,256*dt); // fade out over 1 second - - if ( m_iFadeState == -1 ) - SetRenderColorA( (byte)UTIL_Approach( 0, m_clrRender->a, speed ) ); - else - SetRenderColorA( (byte)UTIL_Approach( 255, m_clrRender->a, speed ) ); - - if ( m_clrRender->a == 0 ) - { - UTIL_Remove(this); - } - else if ( m_clrRender->a == 255 ) - { - m_iFadeState = 0; - } - else - { - SetNextThink( gpGlobals->curtime ); - } - } - - - if ( GetOwnerEntity() ) - { - if ( GetOwnerEntity()->GetWaterLevel() < 3 ) - { - AddEffects( EF_NODRAW ); - } - else - { - RemoveEffects( EF_NODRAW ); - } - - SetAbsOrigin( GetOwnerEntity()->GetAbsOrigin() + GetOwnerEntity()->GetViewOffset() ); - } -} - -class CTriggerWateryDeath : public CBaseTrigger -{ - DECLARE_CLASS( CTriggerWateryDeath, CBaseTrigger ); -public: - DECLARE_DATADESC(); - - void Spawn( void ); - void Precache( void ); - void Touch( CBaseEntity *pOther ); - void SpawnLeeches( CBaseEntity *pOther ); - - // Ignore non-living entities - virtual bool PassesTriggerFilters(CBaseEntity *pOther) - { - if ( !BaseClass::PassesTriggerFilters(pOther) ) - return false; - - return (pOther->m_takedamage == DAMAGE_YES); - } - - virtual void StartTouch(CBaseEntity *pOther); - virtual void EndTouch(CBaseEntity *pOther); - -private: - - CUtlVector< EHANDLE > m_hLeeches; - - // Kill times for entities I'm touching - CUtlVector< float > m_flEntityKillTimes; - float m_flNextPullSound; - float m_flPainValue; -}; - -BEGIN_DATADESC( CTriggerWateryDeath ) - DEFINE_UTLVECTOR( m_flEntityKillTimes, FIELD_TIME ), - DEFINE_UTLVECTOR( m_hLeeches, FIELD_EHANDLE ), - DEFINE_FIELD( m_flNextPullSound, FIELD_TIME ), - DEFINE_FIELD( m_flPainValue, FIELD_FLOAT ), -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( trigger_waterydeath, CTriggerWateryDeath ); - -// Stages of the waterydeath trigger, in time offsets from the initial touch -#define WD_KILLTIME_NEXT_BITE 0.3 -#define WD_PAINVALUE_STEP 2.0 -#define WD_MAX_DAMAGE 15.0f - -//----------------------------------------------------------------------------- -// Purpose: Called when spawning, after keyvalues have been handled. -//----------------------------------------------------------------------------- -void CTriggerWateryDeath::Spawn( void ) -{ - BaseClass::Spawn(); - Precache(); - - m_flNextPullSound = 0; - m_flPainValue = 0; - InitTrigger(); -} - -void CTriggerWateryDeath::Precache( void ) -{ - //Ugh this is temporary until Jakob finishes the animations and doesn't need the command anymore. - BaseClass::Precache(); - PrecacheModel( "models/leech.mdl" ); - - PrecacheScriptSound( "coast.leech_bites_loop" ); - PrecacheScriptSound( "coast.leech_water_churn_loop" ); -} - -void CTriggerWateryDeath::SpawnLeeches( CBaseEntity *pOther ) -{ - if ( pOther == NULL ) - return; - - if ( m_hLeeches.Count() > 0 ) - return; - - int iMaxLeeches = 12; - - for ( int i = 0; i < iMaxLeeches; i++ ) - { - CWateryDeathLeech *pLeech = (CWateryDeathLeech*)CreateEntityByName( "ent_watery_leech" ); - - if ( pLeech ) - { - m_hLeeches.AddToTail( pLeech ); - - pLeech->Spawn(); - pLeech->SetAbsOrigin( pOther->GetAbsOrigin() ); - pLeech->SetOwnerEntity( pOther ); - - if ( i <= 8 ) - pLeech->SetSequence( i % 4 ); - else - pLeech->SetSequence( ( i % 4 ) + 4 ) ; - pLeech->ResetSequenceInfo(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerWateryDeath::Touch( CBaseEntity *pOther ) -{ - if (!PassesTriggerFilters(pOther)) - return; - - // Find our index - EHANDLE hOther; - hOther = pOther; - int iIndex = m_hTouchingEntities.Find( hOther ); - if ( iIndex == m_hTouchingEntities.InvalidIndex() ) - return; - - float flKillTime = m_flEntityKillTimes[iIndex]; - - // Time to kill it? - if ( gpGlobals->curtime > flKillTime ) - { - //EmitSound( filter, entindex(), "WateryDeath.Bite", &pOther->GetAbsOrigin() ); - // Kill it - if ( pOther->IsPlayer() ) - { - m_flPainValue = MIN( m_flPainValue + WD_PAINVALUE_STEP, WD_MAX_DAMAGE ); - } - else - { - m_flPainValue = WD_MAX_DAMAGE; - } - - // Use DMG_GENERIC & make the target inflict the damage on himself. - // This ensures that if the target is the player, the damage isn't modified by skill - CTakeDamageInfo info = CTakeDamageInfo( pOther, pOther, m_flPainValue, DMG_GENERIC ); - - GuessDamageForce( &info, (pOther->GetAbsOrigin() - GetAbsOrigin()), pOther->GetAbsOrigin() ); - pOther->TakeDamage( info ); - - m_flEntityKillTimes[iIndex] = gpGlobals->curtime + WD_KILLTIME_NEXT_BITE; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Called when an entity starts touching us. -// Input : pOther - The entity that is touching us. -//----------------------------------------------------------------------------- -void CTriggerWateryDeath::StartTouch(CBaseEntity *pOther) -{ - BaseClass::StartTouch( pOther ); - - m_flPainValue = 0.0f; - - // If we added him to our list, store the start time - EHANDLE hOther; - hOther = pOther; - if ( m_hTouchingEntities.Find( hOther ) != m_hTouchingEntities.InvalidIndex() ) - { - // Always added to the end - // Players get warned, everything else gets et quick. - if ( pOther->IsPlayer() ) - { - m_flEntityKillTimes.AddToTail( gpGlobals->curtime + WD_KILLTIME_NEXT_BITE ); - } - else - { - m_flEntityKillTimes.AddToTail( gpGlobals->curtime + WD_KILLTIME_NEXT_BITE ); - } - } - -#ifdef HL2_DLL - if ( pOther->IsPlayer() ) - { - SpawnLeeches( pOther ); - - CHL2_Player *pHL2Player = dynamic_cast( pOther ); - - if ( pHL2Player ) - { - pHL2Player->StartWaterDeathSounds(); - } - } -#endif - -} - - -//----------------------------------------------------------------------------- -// Purpose: Called when an entity stops touching us. -// Input : pOther - The entity that was touching us. -//----------------------------------------------------------------------------- -void CTriggerWateryDeath::EndTouch( CBaseEntity *pOther ) -{ - if ( IsTouching( pOther ) ) - { - EHANDLE hOther; - hOther = pOther; - - // Remove the time from our list - int iIndex = m_hTouchingEntities.Find( hOther ); - if ( iIndex != m_hTouchingEntities.InvalidIndex() ) - { - m_flEntityKillTimes.Remove( iIndex ); - } - } - -#ifdef HL2_DLL - if ( pOther->IsPlayer() ) - { - for (int i = 0; i < m_hLeeches.Count(); i++ ) - { - CWateryDeathLeech *pLeech = dynamic_cast( m_hLeeches[i].Get() ); - - if ( pLeech ) - { - pLeech->m_iFadeState = -1; - } - } - - if ( m_hLeeches.Count() > 0 ) - m_hLeeches.Purge(); - - CHL2_Player *pHL2Player = dynamic_cast( pOther ); - - if ( pHL2Player ) - { - //Adrian: Hi, you might be wondering why I'm doing this, yes? - // Well, EndTouch is called not only when the player leaves - // the trigger, but also on level shutdown. We can't let the - // soundpatch fade the sound out since we'll hit a nasty assert - // cause it'll try to fade out a sound using an entity that might - // be gone since we're shutting down the server. - if ( !(pHL2Player->GetFlags() & FL_DONTTOUCH ) ) - pHL2Player->StopWaterDeathSounds(); - } - } -#endif - - BaseClass::EndTouch( pOther ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Triggers whenever an RPG is fired within it -//----------------------------------------------------------------------------- -class CTriggerRPGFire : public CTriggerMultiple -{ - DECLARE_CLASS( CTriggerRPGFire, CTriggerMultiple ); -public: - ~CTriggerRPGFire(); - - void Spawn( void ); - void OnRestore( void ); -}; - -LINK_ENTITY_TO_CLASS( trigger_rpgfire, CTriggerRPGFire ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTriggerRPGFire::~CTriggerRPGFire( void ) -{ - g_hWeaponFireTriggers.FindAndRemove( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: Called when spawning, after keyvalues have been handled. -//----------------------------------------------------------------------------- -void CTriggerRPGFire::Spawn( void ) -{ - BaseClass::Spawn(); - - InitTrigger(); - - g_hWeaponFireTriggers.AddToTail( this ); - - // Stomp the touch function, because we don't want to respond to touch - SetTouch( NULL ); -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CTriggerRPGFire::OnRestore() -{ - BaseClass::OnRestore(); - - g_hWeaponFireTriggers.AddToTail( this ); -} diff --git a/game/server/hl2/hl_playermove.cpp b/game/server/hl2/hl_playermove.cpp deleted file mode 100644 index b0bd53006..000000000 --- a/game/server/hl2/hl_playermove.cpp +++ /dev/null @@ -1,178 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "player_command.h" -#include "player.h" -#include "igamemovement.h" -#include "hl_movedata.h" -#include "ipredictionsystem.h" -#include "iservervehicle.h" -#include "hl2_player.h" -#include "vehicle_base.h" -#include "GameStats.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CHLPlayerMove : public CPlayerMove -{ - DECLARE_CLASS( CHLPlayerMove, CPlayerMove ); -public: - CHLPlayerMove() : - m_bWasInVehicle( false ), - m_bVehicleFlipped( false ), - m_bInGodMode( false ), - m_bInNoClip( false ) - { - m_vecSaveOrigin.Init(); - } - - void SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ); - void FinishMove( CBasePlayer *player, CUserCmd *ucmd, CMoveData *move ); - -private: - Vector m_vecSaveOrigin; - bool m_bWasInVehicle; - bool m_bVehicleFlipped; - bool m_bInGodMode; - bool m_bInNoClip; -}; - -// -// -// PlayerMove Interface -static CHLPlayerMove g_PlayerMove; - -//----------------------------------------------------------------------------- -// Singleton accessor -//----------------------------------------------------------------------------- -CPlayerMove *PlayerMove() -{ - return &g_PlayerMove; -} - -// - -static CHLMoveData g_HLMoveData; -CMoveData *g_pMoveData = &g_HLMoveData; - -IPredictionSystem *IPredictionSystem::g_pPredictionSystems = NULL; - -void CHLPlayerMove::SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) -{ - // Call the default SetupMove code. - BaseClass::SetupMove( player, ucmd, pHelper, move ); - - // Convert to HL2 data. - CHL2_Player *pHLPlayer = static_cast( player ); - Assert( pHLPlayer ); - - CHLMoveData *pHLMove = static_cast( move ); - Assert( pHLMove ); - - player->m_flForwardMove = ucmd->forwardmove; - player->m_flSideMove = ucmd->sidemove; - - pHLMove->m_bIsSprinting = pHLPlayer->IsSprinting(); - - if ( gpGlobals->frametime != 0 ) - { - IServerVehicle *pVehicle = player->GetVehicle(); - - if ( pVehicle ) - { - pVehicle->SetupMove( player, ucmd, pHelper, move ); - - if ( !m_bWasInVehicle ) - { - m_bWasInVehicle = true; - m_vecSaveOrigin.Init(); - } - } - else - { - m_vecSaveOrigin = player->GetAbsOrigin(); - if ( m_bWasInVehicle ) - { - m_bWasInVehicle = false; - } - } - } -} - - -void CHLPlayerMove::FinishMove( CBasePlayer *player, CUserCmd *ucmd, CMoveData *move ) -{ - // Call the default FinishMove code. - BaseClass::FinishMove( player, ucmd, move ); - if ( gpGlobals->frametime != 0 ) - { - float distance = 0.0f; - IServerVehicle *pVehicle = player->GetVehicle(); - if ( pVehicle ) - { - pVehicle->FinishMove( player, ucmd, move ); - IPhysicsObject *obj = player->GetVehicleEntity()->VPhysicsGetObject(); - if ( obj ) - { - Vector newPos; - obj->GetPosition( &newPos, NULL ); - distance = VectorLength( newPos - m_vecSaveOrigin ); - if ( m_vecSaveOrigin == vec3_origin || distance > 100.0f ) - distance = 0.0f; - m_vecSaveOrigin = newPos; - } - - CPropVehicleDriveable *driveable = dynamic_cast< CPropVehicleDriveable * >( player->GetVehicleEntity() ); - if ( driveable ) - { - // Overturned and at rest (if still moving it can fix itself) - bool bFlipped = driveable->IsOverturned() && ( distance < 0.5f ); - if ( m_bVehicleFlipped != bFlipped ) - { - if ( bFlipped ) - { - gamestats->Event_FlippedVehicle( player, driveable ); - } - m_bVehicleFlipped = bFlipped; - } - } - else - { - m_bVehicleFlipped = false; - } - } - else - { - m_bVehicleFlipped = false; - distance = VectorLength( player->GetAbsOrigin() - m_vecSaveOrigin ); - } - if ( distance > 0 ) - { - gamestats->Event_PlayerTraveled( player, distance, pVehicle ? true : false, !pVehicle && static_cast< CHL2_Player * >( player )->IsSprinting() ); - } - } - - bool bGodMode = ( player->GetFlags() & FL_GODMODE ) ? true : false; - if ( m_bInGodMode != bGodMode ) - { - m_bInGodMode = bGodMode; - if ( bGodMode ) - { - gamestats->Event_PlayerEnteredGodMode( player ); - } - } - bool bNoClip = ( player->GetMoveType() == MOVETYPE_NOCLIP ); - if ( m_bInNoClip != bNoClip ) - { - m_bInNoClip = bNoClip; - if ( bNoClip ) - { - gamestats->Event_PlayerEnteredNoClip( player ); - } - } -} diff --git a/game/server/hl2/info_darknessmode_lightsource.cpp b/game/server/hl2/info_darknessmode_lightsource.cpp deleted file mode 100644 index 01d19a611..000000000 --- a/game/server/hl2/info_darknessmode_lightsource.cpp +++ /dev/null @@ -1,454 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#include "info_darknessmode_lightsource.h" -#include "ai_debug_shared.h" - -void CV_Debug_Darkness( IConVar *var, const char *pOldString, float flOldValue ); -ConVar g_debug_darkness( "g_debug_darkness", "0", FCVAR_NONE, "Show darkness mode lightsources.", CV_Debug_Darkness ); -ConVar darkness_ignore_LOS_to_sources( "darkness_ignore_LOS_to_sources", "1", FCVAR_NONE ); - -class CInfoDarknessLightSource; - -//----------------------------------------------------------------------------- -// Purpose: Manages entities that provide light while in darkness mode -//----------------------------------------------------------------------------- -class CDarknessLightSourcesSystem : public CAutoGameSystem -{ -public: - CDarknessLightSourcesSystem() : CAutoGameSystem( "CDarknessLightSourcesSystem" ) - { - } - - void LevelInitPreEntity(); - - void AddLightSource( CInfoDarknessLightSource *pEntity, float flRadius ); - void RemoveLightSource( CInfoDarknessLightSource *pEntity ); - bool IsEntityVisibleToTarget( CBaseEntity *pLooker, CBaseEntity *pTarget ); - bool AreThereLightSourcesWithinRadius( CBaseEntity *pLooker, float flRadius ); - void SetDebug( bool bDebug ); - -private: - struct lightsource_t - { - float flLightRadiusSqr; - CHandle hEntity; - }; - - CUtlVector m_LightSources; -}; - -CDarknessLightSourcesSystem *DarknessLightSourcesSystem(); - -//----------------------------------------------------------------------------- -// Darkness mode light source entity -//----------------------------------------------------------------------------- -class CInfoDarknessLightSource : public CBaseEntity -{ - DECLARE_CLASS( CInfoDarknessLightSource, CBaseEntity ); -public: - DECLARE_DATADESC(); - - virtual void Activate() - { - if ( m_bDisabled == false ) - { - DarknessLightSourcesSystem()->AddLightSource( this, m_flLightRadius ); - - if ( g_debug_darkness.GetBool() ) - { - SetThink( &CInfoDarknessLightSource::DebugThink ); - SetNextThink( gpGlobals->curtime ); - } - } - - BaseClass::Activate(); - } - virtual void UpdateOnRemove() - { - DarknessLightSourcesSystem()->RemoveLightSource( this ); - BaseClass::UpdateOnRemove(); - } - void SetLightRadius( float flRadius ) - { - m_flLightRadius = flRadius; - } - - void InputEnable( inputdata_t &inputdata ) - { - DarknessLightSourcesSystem()->AddLightSource( this, m_flLightRadius ); - m_bDisabled = false; - } - - void InputDisable( inputdata_t &inputdata ) - { - DarknessLightSourcesSystem()->RemoveLightSource( this ); - m_bDisabled = true; - } - - void DebugThink( void ) - { - Vector vecRadius( m_flLightRadius, m_flLightRadius, m_flLightRadius ); - NDebugOverlay::Box( GetAbsOrigin(), -vecRadius, vecRadius, 255,255,255, 8, 0.1 ); - NDebugOverlay::Box( GetAbsOrigin(), -Vector(5,5,5), Vector(5,5,5), 255,0,0, 8, 0.1 ); - SetNextThink( gpGlobals->curtime + 0.1 ); - - int textoffset = 0; - EntityText( textoffset, UTIL_VarArgs("Org: %.2f %.2f %.2f", GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z ), 0.1 ); - textoffset++; - EntityText( textoffset, UTIL_VarArgs("Radius %.2f", m_flLightRadius), 0.1 ); - textoffset++; - if ( m_bIgnoreLOS ) - { - EntityText( textoffset, "Ignoring LOS", 0.1 ); - textoffset++; - } - if ( m_bDisabled ) - { - EntityText( textoffset, "DISABLED", 0.1 ); - textoffset++; - } - } - - void IgnoreLOS( void ) - { - m_bIgnoreLOS = true; - } - - bool ShouldIgnoreLOS( void ) - { - return m_bIgnoreLOS; - } - -private: - float m_flLightRadius; - bool m_bDisabled; - bool m_bIgnoreLOS; -}; - -LINK_ENTITY_TO_CLASS( info_darknessmode_lightsource, CInfoDarknessLightSource ); - -BEGIN_DATADESC( CInfoDarknessLightSource ) - DEFINE_KEYFIELD( m_flLightRadius, FIELD_FLOAT, "LightRadius" ), - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ), - DEFINE_FIELD( m_bIgnoreLOS, FIELD_BOOLEAN ), - - DEFINE_THINKFUNC( DebugThink ), -END_DATADESC() - -CDarknessLightSourcesSystem g_DarknessLightSourcesSystem; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CDarknessLightSourcesSystem *DarknessLightSourcesSystem() -{ - return &g_DarknessLightSourcesSystem; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDarknessLightSourcesSystem::LevelInitPreEntity() -{ - m_LightSources.Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDarknessLightSourcesSystem::AddLightSource( CInfoDarknessLightSource *pEntity, float flRadius ) -{ - lightsource_t sNewSource; - sNewSource.hEntity = pEntity; - sNewSource.flLightRadiusSqr = flRadius * flRadius; - m_LightSources.AddToTail( sNewSource ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDarknessLightSourcesSystem::RemoveLightSource( CInfoDarknessLightSource *pEntity ) -{ - for ( int i = m_LightSources.Count() - 1; i >= 0; i-- ) - { - if ( m_LightSources[i].hEntity == pEntity ) - { - m_LightSources.Remove(i); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDarknessLightSourcesSystem::IsEntityVisibleToTarget( CBaseEntity *pLooker, CBaseEntity *pTarget ) -{ - if ( pTarget->IsEffectActive( EF_BRIGHTLIGHT ) || pTarget->IsEffectActive( EF_DIMLIGHT ) ) - return true; - - bool bDebug = g_debug_darkness.GetBool(); - if ( bDebug && pLooker ) - { - bDebug = (pLooker->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT) != 0; - } - - trace_t tr; - - // Loop through all the light sources. Do it backwards, so we can remove dead ones. - for ( int i = m_LightSources.Count() - 1; i >= 0; i-- ) - { - // Removed? - if ( m_LightSources[i].hEntity == NULL || m_LightSources[i].hEntity->IsMarkedForDeletion() ) - { - m_LightSources.FastRemove( i ); - continue; - } - - CInfoDarknessLightSource *pLightSource = m_LightSources[i].hEntity; - - // Close enough to a light source? - float flDistanceSqr = (pTarget->WorldSpaceCenter() - pLightSource->GetAbsOrigin()).LengthSqr(); - if ( flDistanceSqr < m_LightSources[i].flLightRadiusSqr ) - { - if ( pLightSource->ShouldIgnoreLOS() ) - { - if ( bDebug ) - { - NDebugOverlay::Line( pTarget->WorldSpaceCenter(), pLightSource->GetAbsOrigin(), 0,255,0,true, 0.1); - } - return true; - } - - // Check LOS from the light to the target - CTraceFilterSkipTwoEntities filter( pTarget, pLooker, COLLISION_GROUP_NONE ); - AI_TraceLine( pTarget->WorldSpaceCenter(), pLightSource->GetAbsOrigin(), MASK_BLOCKLOS, &filter, &tr ); - if ( tr.fraction == 1.0 ) - { - if ( bDebug ) - { - NDebugOverlay::Line( tr.startpos, tr.endpos, 0,255,0,true, 0.1); - } - return true; - } - - if ( bDebug ) - { - NDebugOverlay::Line( tr.startpos, tr.endpos, 255,0,0,true, 0.1); - NDebugOverlay::Line( tr.endpos, pLightSource->GetAbsOrigin(), 128,0,0,true, 0.1); - } - - // If the target is within the radius of the light, don't do sillhouette checks - continue; - } - - if ( !pLooker ) - continue; - - // Between a light source and the looker? - Vector vecLookerToLight = (pLightSource->GetAbsOrigin() - pLooker->WorldSpaceCenter()); - Vector vecLookerToTarget = (pTarget->WorldSpaceCenter() - pLooker->WorldSpaceCenter()); - float flDistToSource = VectorNormalize( vecLookerToLight ); - float flDistToTarget = VectorNormalize( vecLookerToTarget ); - float flDot = DotProduct( vecLookerToLight, vecLookerToTarget ); - if ( flDot > 0 ) - { - // Make sure the target is in front of the lightsource - if ( flDistToTarget < flDistToSource ) - { - if ( bDebug ) - { - NDebugOverlay::Line( pLooker->WorldSpaceCenter(), pLooker->WorldSpaceCenter() + (vecLookerToLight * 128), 255,255,255,true, 0.1); - NDebugOverlay::Line( pLooker->WorldSpaceCenter(), pLooker->WorldSpaceCenter() + (vecLookerToTarget * 128), 255,0,0,true, 0.1); - } - - // Now, we need to find out if the light source is obscured by anything. - // To do this, we want to calculate the point of intersection between the light source - // sphere and the line from the looker through the target. - float flASqr = (flDistToSource * flDistToSource); - float flB = -2 * flDistToSource * flDot; - float flCSqr = m_LightSources[i].flLightRadiusSqr; - float flDesc = (flB * flB) - (4 * (flASqr - flCSqr)); - if ( flDesc >= 0 ) - { - float flLength = (-flB - sqrt(flDesc)) / 2; - Vector vecSpherePoint = pLooker->WorldSpaceCenter() + (vecLookerToTarget * flLength); - - // We've got the point of intersection. See if we can see it. - CTraceFilterSkipTwoEntities filter( pTarget, pLooker, COLLISION_GROUP_NONE ); - AI_TraceLine( pLooker->EyePosition(), vecSpherePoint, MASK_SOLID_BRUSHONLY, &filter, &tr ); - - if ( bDebug ) - { - if (tr.fraction != 1.0) - { - NDebugOverlay::Line( pLooker->WorldSpaceCenter(), vecSpherePoint, 255,0,0,true, 0.1); - } - else - { - NDebugOverlay::Line( pLooker->WorldSpaceCenter(), vecSpherePoint, 0,255,0,true, 0.1); - NDebugOverlay::Line( pLightSource->GetAbsOrigin(), vecSpherePoint, 255,0,0,true, 0.1); - } - } - - if ( tr.fraction == 1.0 ) - return true; - } - } - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDarknessLightSourcesSystem::AreThereLightSourcesWithinRadius( CBaseEntity *pLooker, float flRadius ) -{ - float flRadiusSqr = (flRadius * flRadius); - for ( int i = m_LightSources.Count() - 1; i >= 0; i-- ) - { - // Removed? - if ( m_LightSources[i].hEntity == NULL || m_LightSources[i].hEntity->IsMarkedForDeletion() ) - { - m_LightSources.FastRemove( i ); - continue; - } - - CBaseEntity *pLightSource = m_LightSources[i].hEntity; - - // Close enough to a light source? - float flDistanceSqr = (pLooker->WorldSpaceCenter() - pLightSource->GetAbsOrigin()).LengthSqr(); - if ( flDistanceSqr < flRadiusSqr ) - { - trace_t tr; - AI_TraceLine( pLooker->EyePosition(), pLightSource->GetAbsOrigin(), MASK_SOLID_BRUSHONLY, pLooker, COLLISION_GROUP_NONE, &tr ); - - if ( g_debug_darkness.GetBool() ) - { - if (tr.fraction != 1.0) - { - NDebugOverlay::Line( pLooker->WorldSpaceCenter(), tr.endpos, 255,0,0,true, 0.1); - } - else - { - NDebugOverlay::Line( pLooker->WorldSpaceCenter(), tr.endpos, 0,255,0,true, 0.1); - NDebugOverlay::Line( pLightSource->GetAbsOrigin(), tr.endpos, 255,0,0,true, 0.1); - } - } - - if ( tr.fraction == 1.0 ) - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDarknessLightSourcesSystem::SetDebug( bool bDebug ) -{ - for ( int i = m_LightSources.Count() - 1; i >= 0; i-- ) - { - CInfoDarknessLightSource *pLightSource = dynamic_cast(m_LightSources[i].hEntity.Get()); - if ( pLightSource ) - { - if ( bDebug ) - { - pLightSource->SetThink( &CInfoDarknessLightSource::DebugThink ); - pLightSource->SetNextThink( gpGlobals->curtime ); - } - else - { - pLightSource->SetThink( NULL ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CV_Debug_Darkness( IConVar *pConVar, const char *pOldString, float flOldValue ) -{ - ConVarRef var( pConVar ); - DarknessLightSourcesSystem()->SetDebug( var.GetBool() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEntity - -//----------------------------------------------------------------------------- -void AddEntityToDarknessCheck( CBaseEntity *pEntity, float flLightRadius /*=DARKNESS_LIGHTSOURCE_SIZE*/ ) -{ - // Create a light source, and attach it to the entity - CInfoDarknessLightSource *pLightSource = (CInfoDarknessLightSource *) CreateEntityByName( "info_darknessmode_lightsource" ); - if ( pLightSource ) - { - pLightSource->SetLightRadius( flLightRadius ); - DispatchSpawn( pLightSource ); - pLightSource->SetAbsOrigin( pEntity->WorldSpaceCenter() ); - pLightSource->SetParent( pEntity ); - pLightSource->Activate(); - - // Dynamically created darkness sources can ignore LOS - // to match the (broken) visual representation of our dynamic lights. - if ( darkness_ignore_LOS_to_sources.GetBool() ) - { - pLightSource->IgnoreLOS(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEntity - -//----------------------------------------------------------------------------- -void RemoveEntityFromDarknessCheck( CBaseEntity *pEntity ) -{ - // Find any light sources parented to this entity, and remove them - CBaseEntity *pChild = pEntity->FirstMoveChild(); - while ( pChild ) - { - CBaseEntity *pPrevChild = pChild; - pChild = pChild->NextMovePeer(); - - if ( dynamic_cast(pPrevChild) ) - { - UTIL_Remove( pPrevChild ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEntity - -//----------------------------------------------------------------------------- -bool LookerCouldSeeTargetInDarkness( CBaseEntity *pLooker, CBaseEntity *pTarget ) -{ - if ( DarknessLightSourcesSystem()->IsEntityVisibleToTarget( pLooker, pTarget ) ) - { - //NDebugOverlay::Line( pTarget->WorldSpaceCenter(), pLooker->WorldSpaceCenter(), 0,255,0,true, 0.1); - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if there is at least 1 darkness light source within -// the specified radius of the looker. -//----------------------------------------------------------------------------- -bool DarknessLightSourceWithinRadius( CBaseEntity *pLooker, float flRadius ) -{ - return DarknessLightSourcesSystem()->AreThereLightSourcesWithinRadius( pLooker, flRadius ); -} diff --git a/game/server/hl2/info_darknessmode_lightsource.h b/game/server/hl2/info_darknessmode_lightsource.h deleted file mode 100644 index 7a329e69e..000000000 --- a/game/server/hl2/info_darknessmode_lightsource.h +++ /dev/null @@ -1,22 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef INFO_DARKNESSMODE_LIGHTSOURCE_H -#define INFO_DARKNESSMODE_LIGHTSOURCE_H -#ifdef _WIN32 -#pragma once -#endif - -// Default distance from lightsources that entities are considered visible -// NOTE!!! This is bigger by a factor of to deal with fixing a bug from HL2. See dlight_t.h -#define DARKNESS_LIGHTSOURCE_SIZE (256.0f*1.2f) - -void AddEntityToDarknessCheck( CBaseEntity *pEntity, float flLightRadius = DARKNESS_LIGHTSOURCE_SIZE ); -void RemoveEntityFromDarknessCheck( CBaseEntity *pEntity ); -bool LookerCouldSeeTargetInDarkness( CBaseEntity *pLooker, CBaseEntity *pTarget ); -bool DarknessLightSourceWithinRadius( CBaseEntity *pLooker, float flRadius ); - -#endif // INFO_DARKNESSMODE_LIGHTSOURCE_H diff --git a/game/server/hl2/info_teleporter_countdown.cpp b/game/server/hl2/info_teleporter_countdown.cpp deleted file mode 100644 index 7e5882671..000000000 --- a/game/server/hl2/info_teleporter_countdown.cpp +++ /dev/null @@ -1,125 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -//----------------------------------------------------------------------------- -// Amount of time before breen teleports away -//----------------------------------------------------------------------------- -class CInfoTeleporterCountdown : public CPointEntity -{ - DECLARE_CLASS( CInfoTeleporterCountdown, CPointEntity ); - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - -public: - virtual int UpdateTransmitState(); - -private: - void InputDisable(inputdata_t &inputdata); - void InputEnable(inputdata_t &inputdata); - void InputStartCountdown(inputdata_t &inputdata); - void InputStopCountdown(inputdata_t &inputdata); - - CNetworkVar( bool, m_bCountdownStarted ); - CNetworkVar( bool, m_bDisabled ); - CNetworkVar( float, m_flStartTime ); - CNetworkVar( float, m_flTimeRemaining ); -}; - - -//----------------------------------------------------------------------------- -// Save/load -//----------------------------------------------------------------------------- -BEGIN_DATADESC( CInfoTeleporterCountdown ) - - DEFINE_FIELD( m_bCountdownStarted, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bDisabled, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flStartTime, FIELD_TIME ), - DEFINE_FIELD( m_flTimeRemaining, FIELD_FLOAT ), - - // Outputs - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "StartCountdown", InputStartCountdown ), - DEFINE_INPUTFUNC( FIELD_VOID, "StopCountdown", InputStopCountdown ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( info_teleporter_countdown, CInfoTeleporterCountdown ); - - -//----------------------------------------------------------------------------- -// Networking -//----------------------------------------------------------------------------- -IMPLEMENT_SERVERCLASS_ST( CInfoTeleporterCountdown, DT_InfoTeleporterCountdown ) - SendPropInt( SENDINFO( m_bCountdownStarted ), 1, SPROP_UNSIGNED ), - SendPropInt( SENDINFO( m_bDisabled ), 1, SPROP_UNSIGNED ), - SendPropTime( SENDINFO( m_flStartTime ) ), - SendPropFloat( SENDINFO( m_flTimeRemaining ), 0, SPROP_NOSCALE ), -END_SEND_TABLE() - - -//----------------------------------------------------------------------------- -// Starts/stops countdown -//----------------------------------------------------------------------------- -void CInfoTeleporterCountdown::InputStartCountdown(inputdata_t &inputdata) -{ - if (!m_bCountdownStarted) - { - m_bCountdownStarted = true; - m_bDisabled = false; - m_flStartTime = gpGlobals->curtime; - m_flTimeRemaining = inputdata.value.Float(); - } -} - -void CInfoTeleporterCountdown::InputStopCountdown(inputdata_t &inputdata) -{ - m_bCountdownStarted = false; -} - - -//----------------------------------------------------------------------------- -// Disables/reenables an active countdown -//----------------------------------------------------------------------------- -void CInfoTeleporterCountdown::InputDisable(inputdata_t &inputdata) -{ - if ( !m_bDisabled ) - { - m_bDisabled = true; - if ( m_bCountdownStarted ) - { - m_flTimeRemaining -= gpGlobals->curtime - m_flStartTime; - } - } -} - -void CInfoTeleporterCountdown::InputEnable(inputdata_t &inputdata) -{ - if ( m_bDisabled ) - { - m_bDisabled = false; - if ( m_bCountdownStarted ) - { - m_flStartTime = gpGlobals->curtime; - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Always send the teleporter countdown -//----------------------------------------------------------------------------- -int CInfoTeleporterCountdown::UpdateTransmitState() -{ - return SetTransmitState( FL_EDICT_ALWAYS ); -} diff --git a/game/server/hl2/item_ammo.cpp b/game/server/hl2/item_ammo.cpp deleted file mode 100644 index 5bca1ff2d..000000000 --- a/game/server/hl2/item_ammo.cpp +++ /dev/null @@ -1,984 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: The various ammo types for HL2 -// -//=============================================================================// - -#include "cbase.h" -#include "player.h" -#include "gamerules.h" -#include "items.h" -#include "ammodef.h" -#include "eventlist.h" -#include "npcevent.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//--------------------------------------------------------- -// Applies ammo quantity scale. -//--------------------------------------------------------- -int ITEM_GiveAmmo( CBasePlayer *pPlayer, float flCount, const char *pszAmmoName, bool bSuppressSound = false ) -{ - int iAmmoType = GetAmmoDef()->Index(pszAmmoName); - if (iAmmoType == -1) - { - Msg("ERROR: Attempting to give unknown ammo type (%s)\n",pszAmmoName); - return 0; - } - - flCount *= g_pGameRules->GetAmmoQuantityScale(iAmmoType); - - // Don't give out less than 1 of anything. - flCount = MAX( 1.0f, flCount ); - - return pPlayer->GiveAmmo( (int)flCount, iAmmoType, bSuppressSound ); -} - -// ======================================================================== -// >> BoxSRounds -// ======================================================================== -class CItem_BoxSRounds : public CItem -{ -public: - DECLARE_CLASS( CItem_BoxSRounds, CItem ); - - void Spawn( void ) - { - Precache( ); - SetModel( "models/items/boxsrounds.mdl" ); - BaseClass::Spawn( ); - } - void Precache( void ) - { - PrecacheModel ("models/items/boxsrounds.mdl"); - } - bool MyTouch( CBasePlayer *pPlayer ) - { - if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_PISTOL, "Pistol")) - { - if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO ) - { - UTIL_Remove(this); - } - - return true; - } - return false; - } -}; -LINK_ENTITY_TO_CLASS(item_box_srounds, CItem_BoxSRounds); -LINK_ENTITY_TO_CLASS(item_ammo_pistol, CItem_BoxSRounds); - -// ======================================================================== -// >> LargeBoxSRounds -// ======================================================================== -class CItem_LargeBoxSRounds : public CItem -{ -public: - DECLARE_CLASS( CItem_LargeBoxSRounds, CItem ); - - void Spawn( void ) - { - Precache( ); - SetModel( "models/items/boxsrounds.mdl" ); - BaseClass::Spawn( ); - } - void Precache( void ) - { - PrecacheModel ("models/items/boxsrounds.mdl"); - } - bool MyTouch( CBasePlayer *pPlayer ) - { - if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_PISTOL_LARGE, "Pistol")) - { - if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO ) - { - UTIL_Remove(this); - } - return true; - } - return false; - } -}; -LINK_ENTITY_TO_CLASS(item_large_box_srounds, CItem_LargeBoxSRounds); -LINK_ENTITY_TO_CLASS(item_ammo_pistol_large, CItem_LargeBoxSRounds); - -// ======================================================================== -// >> BoxMRounds -// ======================================================================== -class CItem_BoxMRounds : public CItem -{ -public: - DECLARE_CLASS( CItem_BoxMRounds, CItem ); - - void Spawn( void ) - { - Precache( ); - SetModel( "models/items/boxmrounds.mdl"); - BaseClass::Spawn( ); - } - void Precache( void ) - { - PrecacheModel ("models/items/boxmrounds.mdl"); - } - bool MyTouch( CBasePlayer *pPlayer ) - { - if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_SMG1, "SMG1")) - { - if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO ) - { - UTIL_Remove(this); - } - return true; - } - return false; - } -}; -LINK_ENTITY_TO_CLASS(item_box_mrounds, CItem_BoxMRounds); -LINK_ENTITY_TO_CLASS(item_ammo_smg1, CItem_BoxMRounds); - -// ======================================================================== -// >> LargeBoxMRounds -// ======================================================================== -class CItem_LargeBoxMRounds : public CItem -{ -public: - DECLARE_CLASS( CItem_LargeBoxMRounds, CItem ); - - void Spawn( void ) - { - Precache( ); - SetModel( "models/items/boxmrounds.mdl"); - BaseClass::Spawn( ); - } - void Precache( void ) - { - PrecacheModel ("models/items/boxmrounds.mdl"); - } - bool MyTouch( CBasePlayer *pPlayer ) - { - if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_SMG1_LARGE, "SMG1")) - { - if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO ) - { - UTIL_Remove(this); - } - return true; - } - return false; - } -}; -LINK_ENTITY_TO_CLASS(item_large_box_mrounds, CItem_LargeBoxMRounds); -LINK_ENTITY_TO_CLASS(item_ammo_smg1_large, CItem_LargeBoxMRounds); - -// ======================================================================== -// >> BoxLRounds -// ======================================================================== -class CItem_BoxLRounds : public CItem -{ -public: - DECLARE_CLASS( CItem_BoxLRounds, CItem ); - - void Spawn( void ) - { - Precache( ); - SetModel( "models/items/combine_rifle_cartridge01.mdl"); - BaseClass::Spawn( ); - } - void Precache( void ) - { - PrecacheModel ("models/items/combine_rifle_cartridge01.mdl"); - } - bool MyTouch( CBasePlayer *pPlayer ) - { - if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_AR2, "AR2")) - { - if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO ) - { - UTIL_Remove(this); - } - return true; - } - return false; - } -}; -LINK_ENTITY_TO_CLASS(item_box_lrounds, CItem_BoxLRounds); -LINK_ENTITY_TO_CLASS(item_ammo_ar2, CItem_BoxLRounds); - -// ======================================================================== -// >> LargeBoxLRounds -// ======================================================================== -class CItem_LargeBoxLRounds : public CItem -{ -public: - DECLARE_CLASS( CItem_LargeBoxLRounds, CItem ); - - void Spawn( void ) - { - Precache( ); - SetModel( "models/items/combine_rifle_cartridge01.mdl"); - BaseClass::Spawn( ); - } - void Precache( void ) - { - PrecacheModel ("models/items/combine_rifle_cartridge01.mdl"); - } - bool MyTouch( CBasePlayer *pPlayer ) - { - if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_AR2_LARGE, "AR2")) - { - if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO ) - { - UTIL_Remove(this); - } - return true; - } - return false; - } -}; -LINK_ENTITY_TO_CLASS(item_large_box_lrounds, CItem_LargeBoxLRounds); -LINK_ENTITY_TO_CLASS(item_ammo_ar2_large, CItem_LargeBoxLRounds); - - -// ======================================================================== -// >> CItem_Box357Rounds -// ======================================================================== -class CItem_Box357Rounds : public CItem -{ -public: - DECLARE_CLASS( CItem_Box357Rounds, CItem ); - - void Precache( void ) - { - PrecacheModel ("models/items/357ammo.mdl"); - } - void Spawn( void ) - { - Precache( ); - SetModel( "models/items/357ammo.mdl"); - BaseClass::Spawn( ); - } - - bool MyTouch( CBasePlayer *pPlayer ) - { - if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_357, "357")) - { - if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO ) - { - UTIL_Remove(this); - } - return true; - } - return false; - } -}; -LINK_ENTITY_TO_CLASS(item_ammo_357, CItem_Box357Rounds); - - -// ======================================================================== -// >> CItem_LargeBox357Rounds -// ======================================================================== -class CItem_LargeBox357Rounds : public CItem -{ -public: - DECLARE_CLASS( CItem_LargeBox357Rounds, CItem ); - - void Precache( void ) - { - PrecacheModel ("models/items/357ammobox.mdl"); - } - void Spawn( void ) - { - Precache( ); - SetModel( "models/items/357ammobox.mdl"); - BaseClass::Spawn( ); - } - - bool MyTouch( CBasePlayer *pPlayer ) - { - if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_357_LARGE, "357")) - { - if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO ) - { - UTIL_Remove(this); - } - return true; - } - return false; - } -}; -LINK_ENTITY_TO_CLASS(item_ammo_357_large, CItem_LargeBox357Rounds); - - -// ======================================================================== -// >> CItem_BoxXBowRounds -// ======================================================================== -class CItem_BoxXBowRounds : public CItem -{ -public: - DECLARE_CLASS( CItem_BoxXBowRounds, CItem ); - - void Precache( void ) - { - PrecacheModel ("models/items/crossbowrounds.mdl"); - } - - void Spawn( void ) - { - Precache( ); - SetModel( "models/items/crossbowrounds.mdl"); - BaseClass::Spawn( ); - } - - bool MyTouch( CBasePlayer *pPlayer ) - { - if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_CROSSBOW, "XBowBolt" )) - { - if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO ) - { - UTIL_Remove(this); - } - return true; - } - return false; - } -}; -LINK_ENTITY_TO_CLASS(item_ammo_crossbow, CItem_BoxXBowRounds); - - -// ======================================================================== -// >> FlareRound -// ======================================================================== -class CItem_FlareRound : public CItem -{ -public: - DECLARE_CLASS( CItem_FlareRound, CItem ); - - void Spawn( void ) - { - Precache( ); - SetModel( "models/items/flare.mdl"); - BaseClass::Spawn( ); - } - void Precache( void ) - { - PrecacheModel ("models/items/flare.mdl"); - } - bool MyTouch( CBasePlayer *pPlayer ) - { - if (ITEM_GiveAmmo( pPlayer, 1, "FlareRound")) - { - if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO ) - { - UTIL_Remove(this); - } - return true; - } - return false; - } -}; -LINK_ENTITY_TO_CLASS(item_flare_round, CItem_FlareRound); - -// ======================================================================== -// >> BoxFlareRounds -// ======================================================================== -#define SIZE_BOX_FLARE_ROUNDS 5 - -class CItem_BoxFlareRounds : public CItem -{ -public: - DECLARE_CLASS( CItem_BoxFlareRounds, CItem ); - - void Spawn( void ) - { - Precache( ); - SetModel( "models/items/boxflares.mdl"); - BaseClass::Spawn( ); - } - void Precache( void ) - { - PrecacheModel ("models/items/boxflares.mdl"); - } - bool MyTouch( CBasePlayer *pPlayer ) - { - if (ITEM_GiveAmmo( pPlayer, SIZE_BOX_FLARE_ROUNDS, "FlareRound")) - { - if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO ) - { - UTIL_Remove(this); - } - return true; - } - return false; - } -}; -LINK_ENTITY_TO_CLASS(item_box_flare_rounds, CItem_BoxFlareRounds); - -// ======================================================================== -// RPG Round -// ======================================================================== -class CItem_RPG_Round : public CItem -{ -public: - DECLARE_CLASS( CItem_RPG_Round, CItem ); - - void Spawn( void ) - { - Precache( ); - SetModel( "models/weapons/w_missile_closed.mdl"); - BaseClass::Spawn( ); - } - void Precache( void ) - { - PrecacheModel ("models/weapons/w_missile_closed.mdl"); - } - bool MyTouch( CBasePlayer *pPlayer ) - { - if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_RPG_ROUND, "RPG_Round")) - { - if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO ) - { - UTIL_Remove(this); - } - return true; - } - return false; - } -}; -LINK_ENTITY_TO_CLASS( item_ml_grenade, CItem_RPG_Round ); -LINK_ENTITY_TO_CLASS( item_rpg_round, CItem_RPG_Round ); - -// ======================================================================== -// >> AR2_Grenade -// ======================================================================== -class CItem_AR2_Grenade : public CItem -{ -public: - DECLARE_CLASS( CItem_AR2_Grenade, CItem ); - - void Spawn( void ) - { - Precache( ); - SetModel( "models/items/ar2_grenade.mdl"); - BaseClass::Spawn( ); - } - void Precache( void ) - { - PrecacheModel ("models/items/ar2_grenade.mdl"); - } - bool MyTouch( CBasePlayer *pPlayer ) - { - if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_SMG1_GRENADE, "SMG1_Grenade")) - { - if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO ) - { - UTIL_Remove(this); - } - return true; - } - return false; - } -}; -LINK_ENTITY_TO_CLASS(item_ar2_grenade, CItem_AR2_Grenade); -LINK_ENTITY_TO_CLASS(item_ammo_smg1_grenade, CItem_AR2_Grenade); - -// ======================================================================== -// >> BoxSniperRounds -// ======================================================================== -#define SIZE_BOX_SNIPER_ROUNDS 10 - -class CItem_BoxSniperRounds : public CItem -{ -public: - DECLARE_CLASS( CItem_BoxSniperRounds, CItem ); - - void Spawn( void ) - { - Precache( ); - SetModel( "models/items/boxsniperrounds.mdl"); - BaseClass::Spawn( ); - } - void Precache( void ) - { - PrecacheModel ("models/items/boxsniperrounds.mdl"); - } - bool MyTouch( CBasePlayer *pPlayer ) - { - if (ITEM_GiveAmmo( pPlayer, SIZE_BOX_SNIPER_ROUNDS, "SniperRound")) - { - if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO ) - { - UTIL_Remove(this); - } - return true; - } - return false; - } -}; -LINK_ENTITY_TO_CLASS(item_box_sniper_rounds, CItem_BoxSniperRounds); - - -// ======================================================================== -// >> BoxBuckshot -// ======================================================================== -class CItem_BoxBuckshot : public CItem -{ -public: - DECLARE_CLASS( CItem_BoxBuckshot, CItem ); - - void Spawn( void ) - { - Precache( ); - SetModel( "models/items/boxbuckshot.mdl"); - BaseClass::Spawn( ); - } - void Precache( void ) - { - PrecacheModel ("models/items/boxbuckshot.mdl"); - } - bool MyTouch( CBasePlayer *pPlayer ) - { - if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_BUCKSHOT, "Buckshot")) - { - if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO ) - { - UTIL_Remove(this); - } - return true; - } - return false; - } -}; -LINK_ENTITY_TO_CLASS(item_box_buckshot, CItem_BoxBuckshot); - -// ======================================================================== -// >> CItem_AR2AltFireRound -// ======================================================================== -class CItem_AR2AltFireRound : public CItem -{ -public: - DECLARE_CLASS( CItem_AR2AltFireRound, CItem ); - - void Precache( void ) - { - PrecacheParticleSystem( "combineball" ); - PrecacheModel ("models/items/combine_rifle_ammo01.mdl"); - } - - void Spawn( void ) - { - Precache( ); - SetModel( "models/items/combine_rifle_ammo01.mdl"); - BaseClass::Spawn( ); - } - - bool MyTouch( CBasePlayer *pPlayer ) - { - if (ITEM_GiveAmmo( pPlayer, SIZE_AMMO_AR2_ALTFIRE, "AR2AltFire" ) ) - { - if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_NO ) - { - UTIL_Remove(this); - } - return true; - } - return false; - } -}; - -LINK_ENTITY_TO_CLASS( item_ammo_ar2_altfire, CItem_AR2AltFireRound ); - -// ================================================================== -// Ammo crate which will supply infinite ammo of the specified type -// ================================================================== - -// Ammo types -enum -{ - AMMOCRATE_SMALL_ROUNDS, - AMMOCRATE_MEDIUM_ROUNDS, - AMMOCRATE_LARGE_ROUNDS, - AMMOCRATE_RPG_ROUNDS, - AMMOCRATE_BUCKSHOT, - AMMOCRATE_GRENADES, - AMMOCRATE_357, - AMMOCRATE_CROSSBOW, - AMMOCRATE_AR2_ALTFIRE, - AMMOCRATE_SMG_ALTFIRE, - NUM_AMMO_CRATE_TYPES, -}; - -// Ammo crate - -class CItem_AmmoCrate : public CBaseAnimating -{ -public: - DECLARE_CLASS( CItem_AmmoCrate, CBaseAnimating ); - - void Spawn( void ); - void Precache( void ); - bool CreateVPhysics( void ); - - virtual void HandleAnimEvent( animevent_t *pEvent ); - - void SetupCrate( void ); - void OnRestore( void ); - - //FIXME: May not want to have this used in a radius - int ObjectCaps( void ) { return (BaseClass::ObjectCaps() | (FCAP_IMPULSE_USE|FCAP_USE_IN_RADIUS)); }; - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - void InputKill( inputdata_t &data ); - void CrateThink( void ); - - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - -protected: - - int m_nAmmoType; - int m_nAmmoIndex; - - static const char *m_lpzModelNames[NUM_AMMO_CRATE_TYPES]; - static const char *m_lpzAmmoNames[NUM_AMMO_CRATE_TYPES]; - static int m_nAmmoAmounts[NUM_AMMO_CRATE_TYPES]; - static const char *m_pGiveWeapon[NUM_AMMO_CRATE_TYPES]; - - float m_flCloseTime; - COutputEvent m_OnUsed; - CHandle< CBasePlayer > m_hActivator; - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( item_ammo_crate, CItem_AmmoCrate ); - -BEGIN_DATADESC( CItem_AmmoCrate ) - - DEFINE_KEYFIELD( m_nAmmoType, FIELD_INTEGER, "AmmoType" ), - - DEFINE_FIELD( m_flCloseTime, FIELD_FLOAT ), - DEFINE_FIELD( m_hActivator, FIELD_EHANDLE ), - - // These can be recreated - //DEFINE_FIELD( m_nAmmoIndex, FIELD_INTEGER ), - //DEFINE_FIELD( m_lpzModelNames, FIELD_ ), - //DEFINE_FIELD( m_lpzAmmoNames, FIELD_ ), - //DEFINE_FIELD( m_nAmmoAmounts, FIELD_INTEGER ), - - DEFINE_OUTPUT( m_OnUsed, "OnUsed" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Kill", InputKill ), - - DEFINE_THINKFUNC( CrateThink ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Animation events. -//----------------------------------------------------------------------------- - -// Models names -const char *CItem_AmmoCrate::m_lpzModelNames[NUM_AMMO_CRATE_TYPES] = -{ - "models/items/ammocrate_pistol.mdl", // Small rounds - "models/items/ammocrate_smg1.mdl", // Medium rounds - "models/items/ammocrate_ar2.mdl", // Large rounds - "models/items/ammocrate_rockets.mdl", // RPG rounds - "models/items/ammocrate_buckshot.mdl", // Buckshot - "models/items/ammocrate_grenade.mdl", // Grenades - "models/items/ammocrate_smg1.mdl", // 357 - "models/items/ammocrate_smg1.mdl", // Crossbow - - //FIXME: This model is incorrect! - "models/items/ammocrate_ar2.mdl", // Combine Ball - "models/items/ammocrate_smg2.mdl", // smg grenade -}; - -// Ammo type names -const char *CItem_AmmoCrate::m_lpzAmmoNames[NUM_AMMO_CRATE_TYPES] = -{ - "Pistol", - "SMG1", - "AR2", - "RPG_Round", - "Buckshot", - "Grenade", - "357", - "XBowBolt", - "AR2AltFire", - "SMG1_Grenade", -}; - -// Ammo amount given per +use -int CItem_AmmoCrate::m_nAmmoAmounts[NUM_AMMO_CRATE_TYPES] = -{ - 300, // Pistol - 300, // SMG1 - 300, // AR2 - 3, // RPG rounds - 120, // Buckshot - 5, // Grenades - 50, // 357 - 50, // Crossbow - 3, // AR2 alt-fire - 5, -}; - -const char *CItem_AmmoCrate::m_pGiveWeapon[NUM_AMMO_CRATE_TYPES] = -{ - NULL, // Pistol - NULL, // SMG1 - NULL, // AR2 - NULL, // RPG rounds - NULL, // Buckshot - "weapon_frag", // Grenades - NULL, // 357 - NULL, // Crossbow - NULL, // AR2 alt-fire - NULL, // SMG alt-fire -}; - -#define AMMO_CRATE_CLOSE_DELAY 1.5f - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CItem_AmmoCrate::Spawn( void ) -{ - Precache(); - - BaseClass::Spawn(); - - SetModel( STRING( GetModelName() ) ); - SetMoveType( MOVETYPE_NONE ); - SetSolid( SOLID_VPHYSICS ); - CreateVPhysics(); - - ResetSequence( LookupSequence( "Idle" ) ); - SetBodygroup( 1, true ); - - m_flCloseTime = gpGlobals->curtime; - m_flAnimTime = gpGlobals->curtime; - m_flPlaybackRate = 0.0; - SetCycle( 0 ); - - m_takedamage = DAMAGE_EVENTS_ONLY; - -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -bool CItem_AmmoCrate::CreateVPhysics( void ) -{ - return ( VPhysicsInitStatic() != NULL ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CItem_AmmoCrate::Precache( void ) -{ - SetupCrate(); - PrecacheModel( STRING( GetModelName() ) ); - - PrecacheScriptSound( "AmmoCrate.Open" ); - PrecacheScriptSound( "AmmoCrate.Close" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CItem_AmmoCrate::SetupCrate( void ) -{ - SetModelName( AllocPooledString( m_lpzModelNames[m_nAmmoType] ) ); - - m_nAmmoIndex = GetAmmoDef()->Index( m_lpzAmmoNames[m_nAmmoType] ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CItem_AmmoCrate::OnRestore( void ) -{ - BaseClass::OnRestore(); - - // Restore our internal state - SetupCrate(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pActivator - -// *pCaller - -// useType - -// value - -//----------------------------------------------------------------------------- -void CItem_AmmoCrate::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - CBasePlayer *pPlayer = ToBasePlayer( pActivator ); - - if ( pPlayer == NULL ) - return; - - m_OnUsed.FireOutput( pActivator, this ); - - int iSequence = LookupSequence( "Open" ); - - // See if we're not opening already - if ( GetSequence() != iSequence ) - { - Vector mins, maxs; - trace_t tr; - - CollisionProp()->WorldSpaceAABB( &mins, &maxs ); - - Vector vOrigin = GetAbsOrigin(); - vOrigin.z += ( maxs.z - mins.z ); - mins = (mins - GetAbsOrigin()) * 0.2f; - maxs = (maxs - GetAbsOrigin()) * 0.2f; - mins.z = ( GetAbsOrigin().z - vOrigin.z ); - - UTIL_TraceHull( vOrigin, vOrigin, mins, maxs, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.startsolid || tr.allsolid ) - return; - - m_hActivator = pPlayer; - - // Animate! - ResetSequence( iSequence ); - - // Make sound - CPASAttenuationFilter sndFilter( this, "AmmoCrate.Open" ); - EmitSound( sndFilter, entindex(), "AmmoCrate.Open" ); - - // Start thinking to make it return - SetThink( &CItem_AmmoCrate::CrateThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); - } - - // Don't close again for two seconds - m_flCloseTime = gpGlobals->curtime + AMMO_CRATE_CLOSE_DELAY; -} - -//----------------------------------------------------------------------------- -// Purpose: allows the crate to open up when hit by a crowbar -//----------------------------------------------------------------------------- -int CItem_AmmoCrate::OnTakeDamage( const CTakeDamageInfo &info ) -{ - // if it's the player hitting us with a crowbar, open up - CBasePlayer *player = ToBasePlayer(info.GetAttacker()); - if (player) - { - CBaseCombatWeapon *weapon = player->GetActiveWeapon(); - - if (weapon && !stricmp(weapon->GetName(), "weapon_crowbar")) - { - // play the normal use sound - player->EmitSound( "HL2Player.Use" ); - // open the crate - Use(info.GetAttacker(), info.GetAttacker(), USE_TOGGLE, 0.0f); - } - } - - // don't actually take any damage - return 0; -} - - -//----------------------------------------------------------------------------- -// Purpose: Catches the monster-specific messages that occur when tagged -// animation frames are played. -// Input : *pEvent - -//----------------------------------------------------------------------------- -void CItem_AmmoCrate::HandleAnimEvent( animevent_t *pEvent ) -{ - if ( pEvent->event == AE_AMMOCRATE_PICKUP_AMMO ) - { - if ( m_hActivator ) - { - if ( m_pGiveWeapon[m_nAmmoType] && !m_hActivator->Weapon_OwnsThisType( m_pGiveWeapon[m_nAmmoType] ) ) - { - CBaseEntity *pEntity = CreateEntityByName( m_pGiveWeapon[m_nAmmoType] ); - CBaseCombatWeapon *pWeapon = dynamic_cast(pEntity); - if ( pWeapon ) - { - pWeapon->SetAbsOrigin( m_hActivator->GetAbsOrigin() ); - pWeapon->m_iPrimaryAmmoType = 0; - pWeapon->m_iSecondaryAmmoType = 0; - pWeapon->Spawn(); - if ( !m_hActivator->BumpWeapon( pWeapon ) ) - { - UTIL_Remove( pEntity ); - } - else - { - SetBodygroup( 1, false ); - } - } - } - - if ( m_hActivator->GiveAmmo( m_nAmmoAmounts[m_nAmmoType], m_nAmmoIndex ) != 0 ) - { - SetBodygroup( 1, false ); - } - m_hActivator = NULL; - } - return; - } - - BaseClass::HandleAnimEvent( pEvent ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CItem_AmmoCrate::CrateThink( void ) -{ - StudioFrameAdvance(); - DispatchAnimEvents( this ); - - SetNextThink( gpGlobals->curtime + 0.1f ); - - // Start closing if we're not already - if ( GetSequence() != LookupSequence( "Close" ) ) - { - // Not ready to close? - if ( m_flCloseTime <= gpGlobals->curtime ) - { - m_hActivator = NULL; - - ResetSequence( LookupSequence( "Close" ) ); - } - } - else - { - // See if we're fully closed - if ( IsSequenceFinished() ) - { - // Stop thinking - SetThink( NULL ); - CPASAttenuationFilter sndFilter( this, "AmmoCrate.Close" ); - EmitSound( sndFilter, entindex(), "AmmoCrate.Close" ); - - // FIXME: We're resetting the sequence here - // but setting Think to NULL will cause this to never have - // StudioFrameAdvance called. What are the consequences of that? - ResetSequence( LookupSequence( "Idle" ) ); - SetBodygroup( 1, true ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &data - -//----------------------------------------------------------------------------- -void CItem_AmmoCrate::InputKill( inputdata_t &data ) -{ - UTIL_Remove( this ); -} - diff --git a/game/server/hl2/item_antidote.cpp b/game/server/hl2/item_antidote.cpp deleted file mode 100644 index 70324e290..000000000 --- a/game/server/hl2/item_antidote.cpp +++ /dev/null @@ -1,45 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -/* - -===== item_antidote.cpp ======================================================== - - handling for the antidote object -*/ - -#include "cbase.h" -#include "player.h" -#include "basecombatweapon.h" -#include "gamerules.h" -#include "items.h" - -class CItemAntidote : public CItem -{ -public: - DECLARE_CLASS( CItemAntidote, CItem ); - - void Spawn( void ) - { - Precache( ); - SetModel( "models/w_antidote.mdl" ); - BaseClass::Spawn( ); - } - void Precache( void ) - { - PrecacheModel ("models/w_antidote.mdl"); - } - bool MyTouch( CBasePlayer *pPlayer ) - { - pPlayer->SetSuitUpdate("!HEV_DET4", FALSE, SUIT_NEXT_IN_1MIN); - - pPlayer->m_rgItems[ITEM_ANTIDOTE] += 1; - return true; - } -}; - -LINK_ENTITY_TO_CLASS(item_antidote, CItemAntidote); diff --git a/game/server/hl2/item_battery.cpp b/game/server/hl2/item_battery.cpp deleted file mode 100644 index c0a221f69..000000000 --- a/game/server/hl2/item_battery.cpp +++ /dev/null @@ -1,45 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Handling for the suit batteries. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "hl2_player.h" -#include "basecombatweapon.h" -#include "gamerules.h" -#include "items.h" -#include "engine/IEngineSound.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CItemBattery : public CItem -{ -public: - DECLARE_CLASS( CItemBattery, CItem ); - - void Spawn( void ) - { - Precache( ); - SetModel( "models/items/battery.mdl" ); - BaseClass::Spawn( ); - } - void Precache( void ) - { - PrecacheModel ("models/items/battery.mdl"); - - PrecacheScriptSound( "ItemBattery.Touch" ); - - } - bool MyTouch( CBasePlayer *pPlayer ) - { - CHL2_Player *pHL2Player = dynamic_cast( pPlayer ); - return ( pHL2Player && pHL2Player->ApplyBattery() ); - } -}; - -LINK_ENTITY_TO_CLASS(item_battery, CItemBattery); -PRECACHE_REGISTER(item_battery); - diff --git a/game/server/hl2/item_dynamic_resupply.cpp b/game/server/hl2/item_dynamic_resupply.cpp deleted file mode 100644 index 6198bcfd7..000000000 --- a/game/server/hl2/item_dynamic_resupply.cpp +++ /dev/null @@ -1,657 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "item_dynamic_resupply.h" -#include "props.h" -#include "items.h" -#include "ammodef.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar sk_dynamic_resupply_modifier( "sk_dynamic_resupply_modifier","1.0" ); -extern ConVar sk_battery; -extern ConVar sk_healthkit; - -ConVar g_debug_dynamicresupplies( "g_debug_dynamicresupplies", "0", FCVAR_NONE, "Debug item_dynamic_resupply spawning. Set to 1 to see text printouts of the spawning. Set to 2 to see lines drawn to other items factored into the spawning." ); - -struct DynamicResupplyItems_t -{ - const char *sEntityName; - const char *sAmmoDef; - int iAmmoCount; - float flFullProbability; // Probability of spawning if the player meeds all goals -}; - -struct SpawnInfo_t -{ - float m_flDesiredRatio; - float m_flCurrentRatio; - float m_flDelta; - int m_iPotentialItems; -}; - - -// Health types -static DynamicResupplyItems_t g_DynamicResupplyHealthItems[] = -{ - { "item_healthkit", "Health", 0, 0.0f, }, - { "item_battery", "Armor", 0, 0.0f }, -}; - -// Ammo types -static DynamicResupplyItems_t g_DynamicResupplyAmmoItems[] = -{ - { "item_ammo_pistol", "Pistol", SIZE_AMMO_PISTOL, 0.5f }, - { "item_ammo_smg1", "SMG1", SIZE_AMMO_SMG1, 0.4f }, - { "item_ammo_smg1_grenade", "SMG1_Grenade", SIZE_AMMO_SMG1_GRENADE, 0.0f }, - { "item_ammo_ar2", "AR2", SIZE_AMMO_AR2, 0.0f }, - { "item_box_buckshot", "Buckshot", SIZE_AMMO_BUCKSHOT, 0.0f }, - { "item_rpg_round", "RPG_Round", SIZE_AMMO_RPG_ROUND, 0.0f }, - { "weapon_frag", "Grenade", 1, 0.1f }, - { "item_ammo_357", "357", SIZE_AMMO_357, 0.0f }, - { "item_ammo_crossbow", "XBowBolt", SIZE_AMMO_CROSSBOW, 0.0f }, - { "item_ammo_ar2_altfire", "AR2AltFire", SIZE_AMMO_AR2_ALTFIRE, 0.0f }, -}; - -#define DS_HEALTH_INDEX 0 -#define DS_ARMOR_INDEX 1 -#define DS_GRENADE_INDEX 6 - -#define NUM_HEALTH_ITEMS (ARRAYSIZE(g_DynamicResupplyHealthItems)) -#define NUM_AMMO_ITEMS (ARRAYSIZE(g_DynamicResupplyAmmoItems)) - -#define DYNAMIC_ITEM_THINK 1.0 - -#define POTENTIAL_ITEM_RADIUS 1024 - -//----------------------------------------------------------------------------- -// Purpose: An item that dynamically decides what the player needs most and spawns that. -//----------------------------------------------------------------------------- -class CItem_DynamicResupply : public CPointEntity -{ - DECLARE_CLASS( CItem_DynamicResupply, CPointEntity ); -public: - DECLARE_DATADESC(); - - CItem_DynamicResupply(); - - void Spawn( void ); - void Precache( void ); - void Activate( void ); - void CheckPVSThink( void ); - - // Inputs - void InputKill( inputdata_t &data ); - void InputCalculateType( inputdata_t &data ); - void InputBecomeMaster( inputdata_t &data ); - - float GetDesiredHealthPercentage( void ) const { return m_flDesiredHealth[0]; } - -private: - friend void DynamicResupply_InitFromAlternateMaster( CBaseEntity *pTargetEnt, string_t iszMaster ); - void FindPotentialItems( int nCount, DynamicResupplyItems_t *pItems, int iDebug, SpawnInfo_t *pSpawnInfo ); - void ComputeHealthRatios( CItem_DynamicResupply* pMaster, CBasePlayer *pPlayer, int iDebug, SpawnInfo_t *pSpawnInfo ); - void ComputeAmmoRatios( CItem_DynamicResupply* pMaster, CBasePlayer *pPlayer, int iDebug, SpawnInfo_t *pSpawnInfo ); - bool SpawnItemFromRatio( int nCount, DynamicResupplyItems_t *pItems, int iDebug, SpawnInfo_t *pSpawnInfo, Vector *pVecSpawnOrigin ); - - // Spawns an item when the player is full - void SpawnFullItem( CItem_DynamicResupply *pMaster, CBasePlayer *pPlayer, int iDebug ); - void SpawnDynamicItem( CBasePlayer *pPlayer ); - - enum Versions - { - VERSION_0, - VERSION_1_PERSISTENT_MASTER, - - VERSION_CURRENT = VERSION_1_PERSISTENT_MASTER, - }; - - int m_version; - float m_flDesiredHealth[ NUM_HEALTH_ITEMS ]; - float m_flDesiredAmmo[ NUM_AMMO_ITEMS ]; - - bool m_bIsMaster; -}; - -LINK_ENTITY_TO_CLASS(item_dynamic_resupply, CItem_DynamicResupply); - -// Master -typedef CHandle DynamicResupplyHandle_t; - -static DynamicResupplyHandle_t g_MasterResupply; - - -//----------------------------------------------------------------------------- -// Save/load: -//----------------------------------------------------------------------------- -BEGIN_DATADESC( CItem_DynamicResupply ) - - DEFINE_THINKFUNC( CheckPVSThink ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Kill", InputKill ), - DEFINE_INPUTFUNC( FIELD_VOID, "CalculateType", InputCalculateType ), - DEFINE_INPUTFUNC( FIELD_VOID, "BecomeMaster", InputBecomeMaster ), - - DEFINE_KEYFIELD( m_flDesiredHealth[0], FIELD_FLOAT, "DesiredHealth" ), - DEFINE_KEYFIELD( m_flDesiredHealth[1], FIELD_FLOAT, "DesiredArmor" ), - DEFINE_KEYFIELD( m_flDesiredAmmo[0], FIELD_FLOAT, "DesiredAmmoPistol" ), - DEFINE_KEYFIELD( m_flDesiredAmmo[1], FIELD_FLOAT, "DesiredAmmoSMG1" ), - DEFINE_KEYFIELD( m_flDesiredAmmo[2], FIELD_FLOAT, "DesiredAmmoSMG1_Grenade" ), - DEFINE_KEYFIELD( m_flDesiredAmmo[3], FIELD_FLOAT, "DesiredAmmoAR2" ), - DEFINE_KEYFIELD( m_flDesiredAmmo[4], FIELD_FLOAT, "DesiredAmmoBuckshot" ), - DEFINE_KEYFIELD( m_flDesiredAmmo[5], FIELD_FLOAT, "DesiredAmmoRPG_Round" ), - DEFINE_KEYFIELD( m_flDesiredAmmo[6], FIELD_FLOAT, "DesiredAmmoGrenade" ), - DEFINE_KEYFIELD( m_flDesiredAmmo[7], FIELD_FLOAT, "DesiredAmmo357" ), - DEFINE_KEYFIELD( m_flDesiredAmmo[8], FIELD_FLOAT, "DesiredAmmoCrossbow" ), - DEFINE_KEYFIELD( m_flDesiredAmmo[9], FIELD_FLOAT, "DesiredAmmoAR2_AltFire" ), - - DEFINE_FIELD( m_version, FIELD_INTEGER ), - DEFINE_FIELD( m_bIsMaster, FIELD_BOOLEAN ), - - // Silence, Classcheck! -// DEFINE_ARRAY( m_flDesiredHealth, FIELD_FLOAT, NUM_HEALTH_ITEMS ), -// DEFINE_ARRAY( m_flDesiredAmmo, FIELD_FLOAT, NUM_AMMO_ITEMS ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CItem_DynamicResupply::CItem_DynamicResupply( void ) -{ - AddSpawnFlags( SF_DYNAMICRESUPPLY_USE_MASTER ); - m_version = VERSION_CURRENT; - - // Setup default values - m_flDesiredHealth[0] = 1.0; // Health - m_flDesiredHealth[1] = 0.3; // Armor - m_flDesiredAmmo[0] = 0.5; // Pistol - m_flDesiredAmmo[1] = 0.5; // SMG1 - m_flDesiredAmmo[2] = 0.1; // SMG1 Grenade - m_flDesiredAmmo[3] = 0.4; // AR2 - m_flDesiredAmmo[4] = 0.5; // Shotgun - m_flDesiredAmmo[5] = 0.0; // RPG Round - m_flDesiredAmmo[6] = 0.1; // Grenade - m_flDesiredAmmo[7] = 0; // 357 - m_flDesiredAmmo[8] = 0; // Crossbow - m_flDesiredAmmo[9] = 0; // AR2 alt-fire -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CItem_DynamicResupply::Spawn( void ) -{ - if ( g_pGameRules->IsAllowedToSpawn( this ) == false ) - { - UTIL_Remove( this ); - return; - } - - // Don't callback to spawn - Precache(); - - m_bIsMaster = HasSpawnFlags( SF_DYNAMICRESUPPLY_IS_MASTER ); - - // Am I the master? - if ( !HasSpawnFlags( SF_DYNAMICRESUPPLY_IS_MASTER | SF_DYNAMICRESUPPLY_ALTERNATE_MASTER ) ) - { - // Stagger the thinks a bit so they don't all think at the same time - SetNextThink( gpGlobals->curtime + RandomFloat(0.2f, 0.4f) ); - SetThink( &CItem_DynamicResupply::CheckPVSThink ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CItem_DynamicResupply::Activate( void ) -{ - BaseClass::Activate(); - - if ( HasSpawnFlags( SF_DYNAMICRESUPPLY_IS_MASTER ) ) - { - if ( !g_MasterResupply && ( m_bIsMaster || m_version < VERSION_1_PERSISTENT_MASTER ) ) - { - g_MasterResupply = this; - } - else - { - m_bIsMaster = false; - } - } - if ( !HasSpawnFlags( SF_DYNAMICRESUPPLY_ALTERNATE_MASTER ) && HasSpawnFlags( SF_DYNAMICRESUPPLY_USE_MASTER ) && gpGlobals->curtime < 1.0 ) - { - if ( !g_MasterResupply ) - { - Warning( "item_dynamic_resupply set to 'Use Master', but no item_dynamic_resupply master exists.\n" ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CItem_DynamicResupply::Precache( void ) -{ - // Precache all the items potentially spawned - size_t i; - for ( i = 0; i < NUM_HEALTH_ITEMS; i++ ) - { - UTIL_PrecacheOther( g_DynamicResupplyHealthItems[i].sEntityName ); - } - - for ( i = 0; i < NUM_AMMO_ITEMS; i++ ) - { - UTIL_PrecacheOther( g_DynamicResupplyAmmoItems[i].sEntityName ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CItem_DynamicResupply::CheckPVSThink( void ) -{ - edict_t *pentPlayer = UTIL_FindClientInPVS( edict() ); - if ( pentPlayer ) - { - CBasePlayer *pPlayer = (CBasePlayer *)CBaseEntity::Instance( pentPlayer ); - if ( pPlayer ) - { - SpawnDynamicItem( pPlayer ); - return; - } - } - - SetNextThink( gpGlobals->curtime + DYNAMIC_ITEM_THINK ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &data - -//----------------------------------------------------------------------------- -void CItem_DynamicResupply::InputKill( inputdata_t &data ) -{ - UTIL_Remove( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &data - -//----------------------------------------------------------------------------- -void CItem_DynamicResupply::InputCalculateType( inputdata_t &data ) -{ - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - SpawnDynamicItem( pPlayer ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &data - -//----------------------------------------------------------------------------- -void CItem_DynamicResupply::InputBecomeMaster( inputdata_t &data ) -{ - if ( g_MasterResupply ) - g_MasterResupply->m_bIsMaster = false; - - g_MasterResupply = this; - m_bIsMaster = true; - - // Stop thinking now that I am the master. - SetThink( NULL ); -} - - -//----------------------------------------------------------------------------- -// Chooses an item when the player is full -//----------------------------------------------------------------------------- -void CItem_DynamicResupply::SpawnFullItem( CItem_DynamicResupply *pMaster, CBasePlayer *pPlayer, int iDebug ) -{ - // Can we not actually spawn the item? - if ( !HasSpawnFlags(SF_DYNAMICRESUPPLY_ALWAYS_SPAWN) ) - return; - - float flRatio[NUM_AMMO_ITEMS]; - size_t i; - float flTotalProb = 0.0f; - for ( i = 0; i < NUM_AMMO_ITEMS; ++i ) - { - int iAmmoType = GetAmmoDef()->Index( g_DynamicResupplyAmmoItems[i].sAmmoDef ); - bool bCanSpawn = pPlayer->Weapon_GetWpnForAmmo( iAmmoType ) != NULL; - - if ( bCanSpawn && ( g_DynamicResupplyAmmoItems[i].flFullProbability != 0 ) && ( pMaster->m_flDesiredAmmo[i] != 0.0f ) ) - { - flTotalProb += g_DynamicResupplyAmmoItems[i].flFullProbability; - flRatio[i] = flTotalProb; - } - else - { - flRatio[i] = -1.0f; - } - } - - if ( flTotalProb == 0.0f ) - { - // If we're supposed to fallback to just a health vial, do that and finish. - if ( pMaster->HasSpawnFlags(SF_DYNAMICRESUPPLY_FALLBACK_TO_VIAL) ) - { - CBaseEntity::Create( "item_healthvial", GetAbsOrigin(), GetAbsAngles(), this ); - - if ( iDebug ) - { - Msg("Player is full, spawning item_healthvial due to spawnflag.\n", g_DynamicResupplyAmmoItems[i].sEntityName ); - } - return; - } - - // Otherwise, spawn the first ammo item in the list - flRatio[0] = 1.0f; - flTotalProb = 1.0f; - } - - float flChoice = random->RandomFloat( 0.0f, flTotalProb ); - for ( i = 0; i < NUM_AMMO_ITEMS; ++i ) - { - if ( flChoice <= flRatio[i] ) - { - CBaseEntity::Create( g_DynamicResupplyAmmoItems[i].sEntityName, GetAbsOrigin(), GetAbsAngles(), this ); - - if ( iDebug ) - { - Msg("Player is full, spawning %s \n", g_DynamicResupplyAmmoItems[i].sEntityName ); - } - return; - } - } - - if ( iDebug ) - { - Msg("Player is full on all health + ammo, is not spawning.\n" ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CItem_DynamicResupply::FindPotentialItems( int nCount, DynamicResupplyItems_t *pItems, int iDebug, SpawnInfo_t *pSpawnInfo ) -{ - int i; - for ( i = 0; i < nCount; ++i ) - { - pSpawnInfo[i].m_iPotentialItems = 0; - } - - // Count the potential addition of items in the PVS - CBaseEntity *pEntity = NULL; - while ( (pEntity = UTIL_EntitiesInPVS( this, pEntity )) != NULL ) - { - if ( pEntity->WorldSpaceCenter().DistToSqr( WorldSpaceCenter() ) > (POTENTIAL_ITEM_RADIUS * POTENTIAL_ITEM_RADIUS) ) - continue; - - for ( i = 0; i < nCount; ++i ) - { - if ( !FClassnameIs( pEntity, pItems[i].sEntityName ) ) - continue; - - if ( iDebug == 2 ) - { - NDebugOverlay::Line( WorldSpaceCenter(), pEntity->WorldSpaceCenter(), 0,255,0, true, 20.0 ); - } - - ++pSpawnInfo[i].m_iPotentialItems; - break; - } - } - - if ( iDebug ) - { - Msg("Searching the PVS:\n"); - for ( int i = 0; i < nCount; i++ ) - { - Msg(" Found %d '%s' in the PVS.\n", pSpawnInfo[i].m_iPotentialItems, pItems[i].sEntityName ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CItem_DynamicResupply::ComputeHealthRatios( CItem_DynamicResupply* pMaster, CBasePlayer *pPlayer, int iDebug, SpawnInfo_t *pSpawnInfo ) -{ - for ( size_t i = 0; i < NUM_HEALTH_ITEMS; i++ ) - { - // Figure out the current level of this resupply type - float flMax; - if ( i == DS_HEALTH_INDEX ) - { - // Health - flMax = pPlayer->GetMaxHealth(); - - float flCurrentHealth = pPlayer->GetHealth() + (pSpawnInfo[i].m_iPotentialItems * sk_healthkit.GetFloat()); - pSpawnInfo[i].m_flCurrentRatio = (flCurrentHealth / flMax); - } - else if ( i == DS_ARMOR_INDEX ) - { - // Armor - // Ignore armor if we don't have the suit - if ( !pPlayer->IsSuitEquipped() ) - { - pSpawnInfo[i].m_flCurrentRatio = 1.0; - } - else - { - flMax = MAX_NORMAL_BATTERY; - float flCurrentArmor = pPlayer->ArmorValue() + (pSpawnInfo[i].m_iPotentialItems * sk_battery.GetFloat()); - pSpawnInfo[i].m_flCurrentRatio = (flCurrentArmor / flMax); - } - } - - pSpawnInfo[i].m_flDesiredRatio = pMaster->m_flDesiredHealth[i] * sk_dynamic_resupply_modifier.GetFloat(); - pSpawnInfo[i].m_flDelta = pSpawnInfo[i].m_flDesiredRatio - pSpawnInfo[i].m_flCurrentRatio; - pSpawnInfo[i].m_flDelta = clamp( pSpawnInfo[i].m_flDelta, 0, 1 ); - } - - if ( iDebug ) - { - Msg("Calculating desired health ratios & deltas:\n"); - for ( size_t i = 0; i < NUM_HEALTH_ITEMS; i++ ) - { - Msg(" %s Desired Ratio: %.2f, Current Ratio: %.2f = Delta of %.2f\n", - g_DynamicResupplyHealthItems[i].sEntityName, pSpawnInfo[i].m_flDesiredRatio, pSpawnInfo[i].m_flCurrentRatio, pSpawnInfo[i].m_flDelta ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CItem_DynamicResupply::ComputeAmmoRatios( CItem_DynamicResupply* pMaster, CBasePlayer *pPlayer, int iDebug, SpawnInfo_t *pSpawnInfo ) -{ - for ( size_t i = 0; i < NUM_AMMO_ITEMS; i++ ) - { - // Get the ammodef's - int iAmmoType = GetAmmoDef()->Index( g_DynamicResupplyAmmoItems[i].sAmmoDef ); - Assert( iAmmoType != -1 ); - - // Ignore ammo types if we don't have a weapon that uses it (except for the grenade) - if ( (i != DS_GRENADE_INDEX) && !pPlayer->Weapon_GetWpnForAmmo( iAmmoType ) ) - { - pSpawnInfo[i].m_flCurrentRatio = 1.0; - } - else - { - float flMax = GetAmmoDef()->MaxCarry( iAmmoType ); - float flCurrentAmmo = pPlayer->GetAmmoCount( iAmmoType ); - flCurrentAmmo += (pSpawnInfo[i].m_iPotentialItems * g_DynamicResupplyAmmoItems[i].iAmmoCount); - pSpawnInfo[i].m_flCurrentRatio = (flCurrentAmmo / flMax); - } - - // Use the master if we're supposed to - pSpawnInfo[i].m_flDesiredRatio = pMaster->m_flDesiredAmmo[i] * sk_dynamic_resupply_modifier.GetFloat(); - pSpawnInfo[i].m_flDelta = pSpawnInfo[i].m_flDesiredRatio - pSpawnInfo[i].m_flCurrentRatio; - pSpawnInfo[i].m_flDelta = clamp( pSpawnInfo[i].m_flDelta, 0, 1 ); - } - - if ( iDebug ) - { - Msg("Calculating desired ammo ratios & deltas:\n"); - for ( size_t i = 0; i < NUM_AMMO_ITEMS; i++ ) - { - Msg(" %s Desired Ratio: %.2f, Current Ratio: %.2f = Delta of %.2f\n", - g_DynamicResupplyAmmoItems[i].sEntityName, pSpawnInfo[i].m_flDesiredRatio, pSpawnInfo[i].m_flCurrentRatio, pSpawnInfo[i].m_flDelta ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CItem_DynamicResupply::SpawnItemFromRatio( int nCount, DynamicResupplyItems_t *pItems, int iDebug, SpawnInfo_t *pSpawnInfo, Vector *pVecSpawnOrigin ) -{ - // Now find the one we're farthest from - float flFarthest = 0; - int iSelectedIndex = -1; - for ( int i = 0; i < nCount; ++i ) - { - if ( pSpawnInfo[i].m_flDelta > flFarthest ) - { - flFarthest = pSpawnInfo[i].m_flDelta; - iSelectedIndex = i; - } - } - - if ( iSelectedIndex < 0 ) - return false; - - if ( iDebug ) - { - Msg("Chosen item: %s (had farthest delta, %.2f)\n", pItems[iSelectedIndex].sEntityName, pSpawnInfo[iSelectedIndex].m_flDelta ); - } - - CBaseEntity *pEnt = CBaseEntity::Create( pItems[iSelectedIndex].sEntityName, *pVecSpawnOrigin, GetAbsAngles(), this ); - pEnt->SetAbsVelocity( GetAbsVelocity() ); - pEnt->SetLocalAngularVelocity( GetLocalAngularVelocity() ); - - // Move the entity up so that it doesn't go below the spawn origin - Vector vecWorldMins, vecWorldMaxs; - pEnt->CollisionProp()->WorldSpaceAABB( &vecWorldMins, &vecWorldMaxs ); - if ( vecWorldMins.z < pVecSpawnOrigin->z ) - { - float dz = pVecSpawnOrigin->z - vecWorldMins.z; - pVecSpawnOrigin->z += dz; - vecWorldMaxs.z += dz; - pEnt->SetAbsOrigin( *pVecSpawnOrigin ); - } - - // Update the spawn position to spawn them on top of each other - pVecSpawnOrigin->z = vecWorldMaxs.z + 6.0f; - - pVecSpawnOrigin->x += random->RandomFloat( -6, 6 ); - pVecSpawnOrigin->y += random->RandomFloat( -6, 6 ); - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CItem_DynamicResupply::SpawnDynamicItem( CBasePlayer *pPlayer ) -{ - Assert( pPlayer ); - - // If we're the master, we never want to spawn - if ( g_MasterResupply == this ) - return; - - int iDebug = g_debug_dynamicresupplies.GetInt(); - if ( iDebug ) - { - Msg("Spawning item_dynamic_resupply:\n"); - } - - SpawnInfo_t pAmmoInfo[ NUM_AMMO_ITEMS ]; - SpawnInfo_t pHealthInfo[ NUM_HEALTH_ITEMS ]; - - // Count the potential addition of items in the PVS - FindPotentialItems( NUM_HEALTH_ITEMS, g_DynamicResupplyHealthItems, iDebug, pHealthInfo ); - FindPotentialItems( NUM_AMMO_ITEMS, g_DynamicResupplyAmmoItems, iDebug, pAmmoInfo ); - - // Use the master if we're supposed to - CItem_DynamicResupply *pMaster = this; - if ( HasSpawnFlags( SF_DYNAMICRESUPPLY_USE_MASTER ) && g_MasterResupply ) - { - pMaster = g_MasterResupply; - } - - // Compute desired ratios for health and ammo - ComputeHealthRatios( pMaster, pPlayer, iDebug, pHealthInfo ); - ComputeAmmoRatios( pMaster, pPlayer, iDebug, pAmmoInfo ); - - Vector vecSpawnOrigin = GetAbsOrigin(); - bool bHealthSpawned = SpawnItemFromRatio( NUM_HEALTH_ITEMS, g_DynamicResupplyHealthItems, iDebug, pHealthInfo, &vecSpawnOrigin ); - bool bAmmoSpawned = SpawnItemFromRatio( NUM_AMMO_ITEMS, g_DynamicResupplyAmmoItems, iDebug, pAmmoInfo, &vecSpawnOrigin ); - if ( !bHealthSpawned && !bAmmoSpawned ) - { - SpawnFullItem( pMaster, pPlayer, iDebug ); - } - - SetThink( NULL ); - UTIL_Remove( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float DynamicResupply_GetDesiredHealthPercentage( void ) -{ - // Return what the master supply dictates - if ( g_MasterResupply != NULL ) - return g_MasterResupply->GetDesiredHealthPercentage(); - - // Full health if they haven't specified otherwise - return 1.0f; -} - - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -void DynamicResupply_InitFromAlternateMaster( CBaseEntity *pTargetEnt, string_t iszMaster ) -{ - if ( iszMaster== NULL_STRING ) - { - return; - } - - CItem_DynamicResupply *pTargetResupply = assert_cast( pTargetEnt ); - CBaseEntity *pMasterEnt = gEntList.FindEntityByName( NULL, iszMaster ); - - if ( !pMasterEnt || !pMasterEnt->ClassMatches( pTargetResupply->GetClassname() ) ) - { - DevWarning( "Invalid item_dynamic_resupply name %s\n", STRING( iszMaster ) ); - return; - } - - CItem_DynamicResupply *pMasterResupply = assert_cast( pMasterEnt ); - - pTargetResupply->RemoveSpawnFlags( SF_DYNAMICRESUPPLY_USE_MASTER ); - memcpy( pTargetResupply->m_flDesiredHealth, pMasterResupply->m_flDesiredHealth, sizeof( pMasterResupply->m_flDesiredHealth ) ); - memcpy( pTargetResupply->m_flDesiredAmmo, pMasterResupply->m_flDesiredAmmo, sizeof( pMasterResupply->m_flDesiredAmmo ) ); - -} diff --git a/game/server/hl2/item_dynamic_resupply.h b/game/server/hl2/item_dynamic_resupply.h deleted file mode 100644 index b0c191f34..000000000 --- a/game/server/hl2/item_dynamic_resupply.h +++ /dev/null @@ -1,25 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ITEM_DYNAMIC_RESUPPLY_H -#define ITEM_DYNAMIC_RESUPPLY_H - -#ifdef _WIN32 -#pragma once -#endif - - -// Spawnflags -#define SF_DYNAMICRESUPPLY_USE_MASTER 1 -#define SF_DYNAMICRESUPPLY_IS_MASTER 2 -#define SF_DYNAMICRESUPPLY_ALWAYS_SPAWN 4 // even if the player has met his target -#define SF_DYNAMICRESUPPLY_FALLBACK_TO_VIAL 8 // If we fail to spawn anything, spawn a health vial -#define SF_DYNAMICRESUPPLY_ALTERNATE_MASTER 16 // Don't assume role as master on activate, but don't think either - -float DynamicResupply_GetDesiredHealthPercentage( void ); -void DynamicResupply_InitFromAlternateMaster( CBaseEntity *pResupply, string_t iszMaster ); - -#endif // ITEM_DYNAMIC_RESUPPLY_H diff --git a/game/server/hl2/item_healthkit.cpp b/game/server/hl2/item_healthkit.cpp deleted file mode 100644 index a2729268f..000000000 --- a/game/server/hl2/item_healthkit.cpp +++ /dev/null @@ -1,743 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements health kits and wall mounted health chargers. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "gamerules.h" -#include "player.h" -#include "items.h" -#include "in_buttons.h" -#include "engine/IEngineSound.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar sk_healthkit( "sk_healthkit","0" ); -ConVar sk_healthvial( "sk_healthvial","0" ); -ConVar sk_healthcharger( "sk_healthcharger","0" ); - -//----------------------------------------------------------------------------- -// Small health kit. Heals the player when picked up. -//----------------------------------------------------------------------------- -class CHealthKit : public CItem -{ -public: - DECLARE_CLASS( CHealthKit, CItem ); - - void Spawn( void ); - void Precache( void ); - bool MyTouch( CBasePlayer *pPlayer ); -}; - -LINK_ENTITY_TO_CLASS( item_healthkit, CHealthKit ); -PRECACHE_REGISTER(item_healthkit); - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHealthKit::Spawn( void ) -{ - Precache(); - SetModel( "models/items/healthkit.mdl" ); - - BaseClass::Spawn(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHealthKit::Precache( void ) -{ - PrecacheModel("models/items/healthkit.mdl"); - - PrecacheScriptSound( "HealthKit.Touch" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -// Output : -//----------------------------------------------------------------------------- -bool CHealthKit::MyTouch( CBasePlayer *pPlayer ) -{ - if ( pPlayer->TakeHealth( sk_healthkit.GetFloat(), DMG_GENERIC ) ) - { - CSingleUserRecipientFilter user( pPlayer ); - user.MakeReliable(); - - UserMessageBegin( user, "ItemPickup" ); - WRITE_STRING( GetClassname() ); - MessageEnd(); - - CPASAttenuationFilter filter( pPlayer, "HealthKit.Touch" ); - EmitSound( filter, pPlayer->entindex(), "HealthKit.Touch" ); - - if ( g_pGameRules->ItemShouldRespawn( this ) ) - { - Respawn(); - } - else - { - UTIL_Remove(this); - } - - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Small dynamically dropped health kit -//----------------------------------------------------------------------------- - -class CHealthVial : public CItem -{ -public: - DECLARE_CLASS( CHealthVial, CItem ); - - void Spawn( void ) - { - Precache(); - SetModel( "models/healthvial.mdl" ); - - BaseClass::Spawn(); - } - - void Precache( void ) - { - PrecacheModel("models/healthvial.mdl"); - - PrecacheScriptSound( "HealthVial.Touch" ); - } - - bool MyTouch( CBasePlayer *pPlayer ) - { - if ( pPlayer->TakeHealth( sk_healthvial.GetFloat(), DMG_GENERIC ) ) - { - CSingleUserRecipientFilter user( pPlayer ); - user.MakeReliable(); - - UserMessageBegin( user, "ItemPickup" ); - WRITE_STRING( GetClassname() ); - MessageEnd(); - - CPASAttenuationFilter filter( pPlayer, "HealthVial.Touch" ); - EmitSound( filter, pPlayer->entindex(), "HealthVial.Touch" ); - - if ( g_pGameRules->ItemShouldRespawn( this ) ) - { - Respawn(); - } - else - { - UTIL_Remove(this); - } - - return true; - } - - return false; - } -}; - -LINK_ENTITY_TO_CLASS( item_healthvial, CHealthVial ); -PRECACHE_REGISTER( item_healthvial ); - -//----------------------------------------------------------------------------- -// Wall mounted health kit. Heals the player when used. -//----------------------------------------------------------------------------- -class CWallHealth : public CBaseToggle -{ -public: - DECLARE_CLASS( CWallHealth, CBaseToggle ); - - void Spawn( ); - void Precache( void ); - int DrawDebugTextOverlays(void); - bool CreateVPhysics(void); - void Off(void); - void Recharge(void); - bool KeyValue( const char *szKeyName, const char *szValue ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() | m_iCaps; } - - float m_flNextCharge; - int m_iReactivate ; // DeathMatch Delay until reactvated - int m_iJuice; - int m_iOn; // 0 = off, 1 = startup, 2 = going - float m_flSoundTime; - - int m_nState; - int m_iCaps; - - COutputFloat m_OutRemainingHealth; - COutputEvent m_OnPlayerUse; - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS(func_healthcharger, CWallHealth); - - -BEGIN_DATADESC( CWallHealth ) - - DEFINE_FIELD( m_flNextCharge, FIELD_TIME), - DEFINE_FIELD( m_iReactivate, FIELD_INTEGER), - DEFINE_FIELD( m_iJuice, FIELD_INTEGER), - DEFINE_FIELD( m_iOn, FIELD_INTEGER), - DEFINE_FIELD( m_flSoundTime, FIELD_TIME), - DEFINE_FIELD( m_nState, FIELD_INTEGER ), - DEFINE_FIELD( m_iCaps, FIELD_INTEGER ), - - // Function Pointers - DEFINE_FUNCTION( Off ), - DEFINE_FUNCTION( Recharge ), - - DEFINE_OUTPUT( m_OnPlayerUse, "OnPlayerUse" ), - DEFINE_OUTPUT( m_OutRemainingHealth, "OutRemainingHealth"), - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pkvd - -//----------------------------------------------------------------------------- -bool CWallHealth::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "style") || - FStrEq(szKeyName, "height") || - FStrEq(szKeyName, "value1") || - FStrEq(szKeyName, "value2") || - FStrEq(szKeyName, "value3")) - { - return(true); - } - else if (FStrEq(szKeyName, "dmdelay")) - { - m_iReactivate = atoi(szValue); - return(true); - } - - return(BaseClass::KeyValue( szKeyName, szValue )); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWallHealth::Spawn(void) -{ - Precache( ); - - SetSolid( SOLID_BSP ); - SetMoveType( MOVETYPE_PUSH ); - - SetModel( STRING( GetModelName() ) ); - - m_iJuice = sk_healthcharger.GetInt(); - - m_nState = 0; - - m_iCaps = FCAP_CONTINUOUS_USE; - - CreateVPhysics(); -} - -int CWallHealth::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - Q_snprintf(tempstr,sizeof(tempstr),"Charge left: %i", m_iJuice ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} - -//----------------------------------------------------------------------------- - -bool CWallHealth::CreateVPhysics(void) -{ - VPhysicsInitStatic(); - return true; - -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWallHealth::Precache(void) -{ - PrecacheScriptSound( "WallHealth.Deny" ); - PrecacheScriptSound( "WallHealth.Start" ); - PrecacheScriptSound( "WallHealth.LoopingContinueCharge" ); - PrecacheScriptSound( "WallHealth.Recharge" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pActivator - -// *pCaller - -// useType - -// value - -//----------------------------------------------------------------------------- -void CWallHealth::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - // Make sure that we have a caller - if (!pActivator) - return; - - // if it's not a player, ignore - if ( !pActivator->IsPlayer() ) - return; - - CBasePlayer *pPlayer = dynamic_cast(pActivator); - - // Reset to a state of continuous use. - m_iCaps = FCAP_CONTINUOUS_USE; - - // if there is no juice left, turn it off - if (m_iJuice <= 0) - { - m_nState = 1; - Off(); - } - - // if the player doesn't have the suit, or there is no juice left, make the deny noise. - // disabled HEV suit dependency for now. - //if ((m_iJuice <= 0) || (!(pActivator->m_bWearingSuit))) - if (m_iJuice <= 0) - { - if (m_flSoundTime <= gpGlobals->curtime) - { - m_flSoundTime = gpGlobals->curtime + 0.62; - EmitSound( "WallHealth.Deny" ); - } - return; - } - - if( pActivator->GetHealth() >= pActivator->GetMaxHealth() ) - { - if( pPlayer ) - { - pPlayer->m_afButtonPressed &= ~IN_USE; - } - - // Make the user re-use me to get started drawing health. - m_iCaps = FCAP_IMPULSE_USE; - - return; - } - - SetNextThink( gpGlobals->curtime + 0.25f ); - SetThink(&CWallHealth::Off); - - // Time to recharge yet? - - if (m_flNextCharge >= gpGlobals->curtime) - return; - - // Play the on sound or the looping charging sound - if (!m_iOn) - { - m_iOn++; - EmitSound( "WallHealth.Start" ); - m_flSoundTime = 0.56 + gpGlobals->curtime; - - m_OnPlayerUse.FireOutput( pActivator, this ); - } - if ((m_iOn == 1) && (m_flSoundTime <= gpGlobals->curtime)) - { - m_iOn++; - CPASAttenuationFilter filter( this, "WallHealth.LoopingContinueCharge" ); - filter.MakeReliable(); - EmitSound( filter, entindex(), "WallHealth.LoopingContinueCharge" ); - } - - // charge the player - if ( pActivator->TakeHealth( 1, DMG_GENERIC ) ) - { - m_iJuice--; - } - - // Send the output. - float flRemaining = m_iJuice / sk_healthcharger.GetFloat(); - m_OutRemainingHealth.Set(flRemaining, pActivator, this); - - // govern the rate of charge - m_flNextCharge = gpGlobals->curtime + 0.1; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWallHealth::Recharge(void) -{ - EmitSound( "WallHealth.Recharge" ); - m_iJuice = sk_healthcharger.GetInt(); - m_nState = 0; - SetThink( NULL ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWallHealth::Off(void) -{ - // Stop looping sound. - if (m_iOn > 1) - StopSound( "WallHealth.LoopingContinueCharge" ); - - m_iOn = 0; - - if ((!m_iJuice) && ( ( m_iReactivate = (int)g_pGameRules->FlHealthChargerRechargeTime() ) > 0) ) - { - SetNextThink( gpGlobals->curtime + m_iReactivate ); - SetThink(&CWallHealth::Recharge); - } - else - SetThink( NULL ); -} - -//----------------------------------------------------------------------------- -// Wall mounted health kit. Heals the player when used. -//----------------------------------------------------------------------------- -class CNewWallHealth : public CBaseAnimating -{ -public: - DECLARE_CLASS( CNewWallHealth, CBaseAnimating ); - - void Spawn( ); - void Precache( void ); - int DrawDebugTextOverlays(void); - bool CreateVPhysics(void); - void Off(void); - void Recharge(void); - bool KeyValue( const char *szKeyName, const char *szValue ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() | m_iCaps; } - - float m_flNextCharge; - int m_iReactivate ; // DeathMatch Delay until reactvated - int m_iJuice; - int m_iOn; // 0 = off, 1 = startup, 2 = going - float m_flSoundTime; - - int m_nState; - int m_iCaps; - - COutputFloat m_OutRemainingHealth; - COutputEvent m_OnPlayerUse; - - void StudioFrameAdvance ( void ); - - float m_flJuice; - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( item_healthcharger, CNewWallHealth); - - -BEGIN_DATADESC( CNewWallHealth ) - - DEFINE_FIELD( m_flNextCharge, FIELD_TIME), - DEFINE_FIELD( m_iReactivate, FIELD_INTEGER), - DEFINE_FIELD( m_iJuice, FIELD_INTEGER), - DEFINE_FIELD( m_iOn, FIELD_INTEGER), - DEFINE_FIELD( m_flSoundTime, FIELD_TIME), - DEFINE_FIELD( m_nState, FIELD_INTEGER ), - DEFINE_FIELD( m_iCaps, FIELD_INTEGER ), - DEFINE_FIELD( m_flJuice, FIELD_FLOAT ), - - // Function Pointers - DEFINE_FUNCTION( Off ), - DEFINE_FUNCTION( Recharge ), - - DEFINE_OUTPUT( m_OnPlayerUse, "OnPlayerUse" ), - DEFINE_OUTPUT( m_OutRemainingHealth, "OutRemainingHealth"), - -END_DATADESC() - -#define HEALTH_CHARGER_MODEL_NAME "models/props_combine/health_charger001.mdl" -#define CHARGE_RATE 0.25f -#define CHARGES_PER_SECOND 1.0f / CHARGE_RATE -#define CALLS_PER_SECOND 7.0f * CHARGES_PER_SECOND - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pkvd - -//----------------------------------------------------------------------------- -bool CNewWallHealth::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "style") || - FStrEq(szKeyName, "height") || - FStrEq(szKeyName, "value1") || - FStrEq(szKeyName, "value2") || - FStrEq(szKeyName, "value3")) - { - return(true); - } - else if (FStrEq(szKeyName, "dmdelay")) - { - m_iReactivate = atoi(szValue); - return(true); - } - - return(BaseClass::KeyValue( szKeyName, szValue )); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNewWallHealth::Spawn(void) -{ - Precache( ); - - SetMoveType( MOVETYPE_NONE ); - SetSolid( SOLID_VPHYSICS ); - CreateVPhysics(); - - SetModel( HEALTH_CHARGER_MODEL_NAME ); - AddEffects( EF_NOSHADOW ); - - ResetSequence( LookupSequence( "idle" ) ); - - m_iJuice = sk_healthcharger.GetInt(); - - m_nState = 0; - - m_iReactivate = 0; - m_iCaps = FCAP_CONTINUOUS_USE; - - CreateVPhysics(); - - m_flJuice = m_iJuice; - SetCycle( 1.0f - ( m_flJuice / sk_healthcharger.GetFloat() ) ); -} - -int CNewWallHealth::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - Q_snprintf(tempstr,sizeof(tempstr),"Charge left: %i", m_iJuice ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} - -//----------------------------------------------------------------------------- - -bool CNewWallHealth::CreateVPhysics(void) -{ - VPhysicsInitStatic(); - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNewWallHealth::Precache(void) -{ - PrecacheModel( HEALTH_CHARGER_MODEL_NAME ); - - PrecacheScriptSound( "WallHealth.Deny" ); - PrecacheScriptSound( "WallHealth.Start" ); - PrecacheScriptSound( "WallHealth.LoopingContinueCharge" ); - PrecacheScriptSound( "WallHealth.Recharge" ); -} - -void CNewWallHealth::StudioFrameAdvance( void ) -{ - m_flPlaybackRate = 0; - - float flMaxJuice = sk_healthcharger.GetFloat(); - - SetCycle( 1.0f - (float)( m_flJuice / flMaxJuice ) ); -// Msg( "Cycle: %f - Juice: %d - m_flJuice :%f - Interval: %f\n", (float)GetCycle(), (int)m_iJuice, (float)m_flJuice, GetAnimTimeInterval() ); - - if ( !m_flPrevAnimTime ) - { - m_flPrevAnimTime = gpGlobals->curtime; - } - - // Latch prev - m_flPrevAnimTime = m_flAnimTime; - // Set current - m_flAnimTime = gpGlobals->curtime; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pActivator - -// *pCaller - -// useType - -// value - -//----------------------------------------------------------------------------- -void CNewWallHealth::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - // Make sure that we have a caller - if (!pActivator) - return; - - // if it's not a player, ignore - if ( !pActivator->IsPlayer() ) - return; - CBasePlayer *pPlayer = dynamic_cast(pActivator); - - // Reset to a state of continuous use. - m_iCaps = FCAP_CONTINUOUS_USE; - - if ( m_iOn ) - { - float flCharges = CHARGES_PER_SECOND; - float flCalls = CALLS_PER_SECOND; - - m_flJuice -= flCharges / flCalls; - StudioFrameAdvance(); - } - - // if there is no juice left, turn it off - if (m_iJuice <= 0) - { - ResetSequence( LookupSequence( "emptyclick" ) ); - m_nState = 1; - Off(); - } - - // if the player doesn't have the suit, or there is no juice left, make the deny noise. - // disabled HEV suit dependency for now. - //if ((m_iJuice <= 0) || (!(pActivator->m_bWearingSuit))) - if (m_iJuice <= 0) - { - if (m_flSoundTime <= gpGlobals->curtime) - { - m_flSoundTime = gpGlobals->curtime + 0.62; - EmitSound( "WallHealth.Deny" ); - } - return; - } - - if( pActivator->GetHealth() >= pActivator->GetMaxHealth() ) - { - if( pPlayer ) - { - pPlayer->m_afButtonPressed &= ~IN_USE; - } - - // Make the user re-use me to get started drawing health. - m_iCaps = FCAP_IMPULSE_USE; - - EmitSound( "WallHealth.Deny" ); - return; - } - - SetNextThink( gpGlobals->curtime + CHARGE_RATE ); - SetThink( &CNewWallHealth::Off ); - - // Time to recharge yet? - - if (m_flNextCharge >= gpGlobals->curtime) - return; - - // Play the on sound or the looping charging sound - if (!m_iOn) - { - m_iOn++; - EmitSound( "WallHealth.Start" ); - m_flSoundTime = 0.56 + gpGlobals->curtime; - - m_OnPlayerUse.FireOutput( pActivator, this ); - } - if ((m_iOn == 1) && (m_flSoundTime <= gpGlobals->curtime)) - { - m_iOn++; - CPASAttenuationFilter filter( this, "WallHealth.LoopingContinueCharge" ); - filter.MakeReliable(); - EmitSound( filter, entindex(), "WallHealth.LoopingContinueCharge" ); - } - - // charge the player - if ( pActivator->TakeHealth( 1, DMG_GENERIC ) ) - { - m_iJuice--; - } - - // Send the output. - float flRemaining = m_iJuice / sk_healthcharger.GetFloat(); - m_OutRemainingHealth.Set(flRemaining, pActivator, this); - - // govern the rate of charge - m_flNextCharge = gpGlobals->curtime + 0.1; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNewWallHealth::Recharge(void) -{ - EmitSound( "WallHealth.Recharge" ); - m_flJuice = m_iJuice = sk_healthcharger.GetInt(); - m_nState = 0; - - ResetSequence( LookupSequence( "idle" ) ); - StudioFrameAdvance(); - - m_iReactivate = 0; - - SetThink( NULL ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNewWallHealth::Off(void) -{ - // Stop looping sound. - if (m_iOn > 1) - StopSound( "WallHealth.LoopingContinueCharge" ); - - if ( m_nState == 1 ) - { - SetCycle( 1.0f ); - } - - m_iOn = 0; - m_flJuice = m_iJuice; - - if ( m_iReactivate == 0 ) - { - if ((!m_iJuice) && g_pGameRules->FlHealthChargerRechargeTime() > 0 ) - { - m_iReactivate = (int)g_pGameRules->FlHealthChargerRechargeTime(); - SetNextThink( gpGlobals->curtime + m_iReactivate ); - SetThink(&CNewWallHealth::Recharge); - } - else - SetThink( NULL ); - } -} - diff --git a/game/server/hl2/item_itemcrate.cpp b/game/server/hl2/item_itemcrate.cpp deleted file mode 100644 index 1899360a9..000000000 --- a/game/server/hl2/item_itemcrate.cpp +++ /dev/null @@ -1,276 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: The various ammo types for HL2 -// -//=============================================================================// - -#include "cbase.h" -#include "props.h" -#include "items.h" -#include "item_dynamic_resupply.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -const char *pszItemCrateModelName[] = -{ - "models/items/item_item_crate.mdl", - "models/items/item_beacon_crate.mdl", -}; - -//----------------------------------------------------------------------------- -// A breakable crate that drops items -//----------------------------------------------------------------------------- -class CItem_ItemCrate : public CPhysicsProp -{ -public: - DECLARE_CLASS( CItem_ItemCrate, CPhysicsProp ); - DECLARE_DATADESC(); - - void Precache( void ); - void Spawn( void ); - - virtual int ObjectCaps() { return BaseClass::ObjectCaps() | FCAP_WCEDIT_POSITION; }; - - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - - void InputKill( inputdata_t &data ); - - virtual void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); - virtual void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ); - -protected: - virtual void OnBreak( const Vector &vecVelocity, const AngularImpulse &angVel, CBaseEntity *pBreaker ); - -private: - // Crate types. Add more! - enum CrateType_t - { - CRATE_SPECIFIC_ITEM = 0, - CRATE_TYPE_COUNT, - }; - - enum CrateAppearance_t - { - CRATE_APPEARANCE_DEFAULT = 0, - CRATE_APPEARANCE_RADAR_BEACON, - }; - -private: - CrateType_t m_CrateType; - string_t m_strItemClass; - int m_nItemCount; - string_t m_strAlternateMaster; - CrateAppearance_t m_CrateAppearance; - - COutputEvent m_OnCacheInteraction; -}; - - -LINK_ENTITY_TO_CLASS(item_item_crate, CItem_ItemCrate); - - -//----------------------------------------------------------------------------- -// Save/load: -//----------------------------------------------------------------------------- -BEGIN_DATADESC( CItem_ItemCrate ) - - DEFINE_KEYFIELD( m_CrateType, FIELD_INTEGER, "CrateType" ), - DEFINE_KEYFIELD( m_strItemClass, FIELD_STRING, "ItemClass" ), - DEFINE_KEYFIELD( m_nItemCount, FIELD_INTEGER, "ItemCount" ), - DEFINE_KEYFIELD( m_strAlternateMaster, FIELD_STRING, "SpecificResupply" ), - DEFINE_KEYFIELD( m_CrateAppearance, FIELD_INTEGER, "CrateAppearance" ), - DEFINE_INPUTFUNC( FIELD_VOID, "Kill", InputKill ), - DEFINE_OUTPUT( m_OnCacheInteraction, "OnCacheInteraction" ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CItem_ItemCrate::Precache( void ) -{ - // Set this here to quiet base prop warnings - PrecacheModel( pszItemCrateModelName[m_CrateAppearance] ); - SetModel( pszItemCrateModelName[m_CrateAppearance] ); - - BaseClass::Precache(); - if ( m_CrateType == CRATE_SPECIFIC_ITEM ) - { - if ( NULL_STRING != m_strItemClass ) - { - // Don't precache if this is a null string. - UTIL_PrecacheOther( STRING(m_strItemClass) ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CItem_ItemCrate::Spawn( void ) -{ - if ( g_pGameRules->IsAllowedToSpawn( this ) == false ) - { - UTIL_Remove( this ); - return; - } - - DisableAutoFade(); - SetModelName( AllocPooledString( pszItemCrateModelName[m_CrateAppearance] ) ); - - if ( NULL_STRING == m_strItemClass ) - { - Warning( "CItem_ItemCrate(%i): CRATE_SPECIFIC_ITEM with NULL ItemClass string (deleted)!!!\n", entindex() ); - UTIL_Remove( this ); - return; - } - - Precache( ); - SetModel( pszItemCrateModelName[m_CrateAppearance] ); - AddEFlags( EFL_NO_ROTORWASH_PUSH ); - BaseClass::Spawn( ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &data - -//----------------------------------------------------------------------------- -void CItem_ItemCrate::InputKill( inputdata_t &data ) -{ - UTIL_Remove( this ); -} - - -//----------------------------------------------------------------------------- -// Item crates blow up immediately -//----------------------------------------------------------------------------- -int CItem_ItemCrate::OnTakeDamage( const CTakeDamageInfo &info ) -{ - if ( info.GetDamageType() & DMG_AIRBOAT ) - { - CTakeDamageInfo dmgInfo = info; - dmgInfo.ScaleDamage( 10.0 ); - return BaseClass::OnTakeDamage( dmgInfo ); - } - - return BaseClass::OnTakeDamage( info ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CItem_ItemCrate::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) -{ - float flDamageScale = 1.0f; - if ( FClassnameIs( pEvent->pEntities[!index], "prop_vehicle_airboat" ) || - FClassnameIs( pEvent->pEntities[!index], "prop_vehicle_jeep" ) ) - { - flDamageScale = 100.0f; - } - - m_impactEnergyScale *= flDamageScale; - BaseClass::VPhysicsCollision( index, pEvent ); - m_impactEnergyScale /= flDamageScale; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CItem_ItemCrate::OnBreak( const Vector &vecVelocity, const AngularImpulse &angImpulse, CBaseEntity *pBreaker ) -{ - // FIXME: We could simply store the name of an entity to put into the crate - // as a string entered in by worldcraft. Should we? I'd do it for sure - // if it was easy to get a dropdown with all entity types in it. - - m_OnCacheInteraction.FireOutput(pBreaker,this); - - for ( int i = 0; i < m_nItemCount; ++i ) - { - CBaseEntity *pSpawn = NULL; - switch( m_CrateType ) - { - case CRATE_SPECIFIC_ITEM: - pSpawn = CreateEntityByName( STRING(m_strItemClass) ); - break; - - default: - break; - } - - if ( !pSpawn ) - return; - - // Give a little randomness... - Vector vecOrigin; - CollisionProp()->RandomPointInBounds( Vector(0.25, 0.25, 0.25), Vector( 0.75, 0.75, 0.75 ), &vecOrigin ); - pSpawn->SetAbsOrigin( vecOrigin ); - - QAngle vecAngles; - vecAngles.x = random->RandomFloat( -20.0f, 20.0f ); - vecAngles.y = random->RandomFloat( 0.0f, 360.0f ); - vecAngles.z = random->RandomFloat( -20.0f, 20.0f ); - pSpawn->SetAbsAngles( vecAngles ); - - Vector vecActualVelocity; - vecActualVelocity.Random( -10.0f, 10.0f ); -// vecActualVelocity += vecVelocity; - pSpawn->SetAbsVelocity( vecActualVelocity ); - - QAngle angVel; - AngularImpulseToQAngle( angImpulse, angVel ); - pSpawn->SetLocalAngularVelocity( angVel ); - - // If we're creating an item, it can't be picked up until it comes to rest - // But only if it wasn't broken by a vehicle - CItem *pItem = dynamic_cast(pSpawn); - if ( pItem && !pBreaker->GetServerVehicle()) - { - pItem->ActivateWhenAtRest(); - } - - pSpawn->Spawn(); - - // Avoid missing items drops by a dynamic resupply because they don't think immediately - if ( FClassnameIs( pSpawn, "item_dynamic_resupply" ) ) - { - if ( m_strAlternateMaster != NULL_STRING ) - { - DynamicResupply_InitFromAlternateMaster( pSpawn, m_strAlternateMaster ); - } - if ( i == 0 ) - { - pSpawn->AddSpawnFlags( SF_DYNAMICRESUPPLY_ALWAYS_SPAWN ); - } - pSpawn->SetNextThink( gpGlobals->curtime ); - } - } -} - -void CItem_ItemCrate::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) -{ - BaseClass::OnPhysGunPickup( pPhysGunUser, reason ); - - m_OnCacheInteraction.FireOutput( pPhysGunUser, this ); - - if ( reason == PUNTED_BY_CANNON && m_CrateAppearance != CRATE_APPEARANCE_RADAR_BEACON ) - { - Vector vForward; - AngleVectors( pPhysGunUser->EyeAngles(), &vForward, NULL, NULL ); - Vector vForce = Pickup_PhysGunLaunchVelocity( this, vForward, PHYSGUN_FORCE_PUNTED ); - AngularImpulse angular = AngularImpulse( 0, 0, 0 ); - - IPhysicsObject *pPhysics = VPhysicsGetObject(); - - if ( pPhysics ) - { - pPhysics->AddVelocity( &vForce, &angular ); - } - - TakeDamage( CTakeDamageInfo( pPhysGunUser, pPhysGunUser, GetHealth(), DMG_GENERIC ) ); - } -} diff --git a/game/server/hl2/item_longjump.cpp b/game/server/hl2/item_longjump.cpp deleted file mode 100644 index d0ab4fd5d..000000000 --- a/game/server/hl2/item_longjump.cpp +++ /dev/null @@ -1,61 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -/* - -===== item_longjump.cpp ======================================================== - - handling for the longjump module -*/ - -#include "cbase.h" -#include "player.h" -//#include "weapons.h" -#include "gamerules.h" -#include "items.h" - -class CItemLongJump : public CItem -{ -public: - DECLARE_CLASS( CItemLongJump, CItem ); - - void Spawn( void ) - { - Precache( ); - SetModel( "models/w_longjump.mdl" ); - BaseClass::Spawn( ); - } - void Precache( void ) - { - PrecacheModel ("models/w_longjump.mdl"); - } - bool MyTouch( CBasePlayer *pPlayer ) - { - if ( pPlayer->m_fLongJump ) - { - return FALSE; - } - - if ( pPlayer->IsSuitEquipped() ) - { - pPlayer->m_fLongJump = TRUE;// player now has longjump module - - CSingleUserRecipientFilter user( pPlayer ); - user.MakeReliable(); - - UserMessageBegin( user, "ItemPickup" ); - WRITE_STRING( STRING(pev->classname) ); - MessageEnd(); - - UTIL_EmitSoundSuit( pPlayer->edict(), "!HEV_A1" ); // Play the longjump sound UNDONE: Kelly? correct sound? - return true; - } - return false; - } -}; - -LINK_ENTITY_TO_CLASS( item_longjump, CItemLongJump ); diff --git a/game/server/hl2/item_security.cpp b/game/server/hl2/item_security.cpp deleted file mode 100644 index f39cb230d..000000000 --- a/game/server/hl2/item_security.cpp +++ /dev/null @@ -1,44 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -/* - -===== item_security.cpp ======================================================== - - handling for the security item -*/ - -#include "cbase.h" -#include "player.h" -//#include "weapons.h" -#include "gamerules.h" -#include "items.h" - -class CItemSecurity : public CItem -{ -public: - DECLARE_CLASS( CItemSecurity, CItem ); - - void Spawn( void ) - { - Precache( ); - SetModel( "models/w_security.mdl" ); - BaseClass::Spawn( ); - } - void Precache( void ) - { - PrecacheModel ("models/w_security.mdl"); - } - bool MyTouch( CBasePlayer *pPlayer ) - { - pPlayer->m_rgItems[ITEM_SECURITY] += 1; - return true; - } -}; - -LINK_ENTITY_TO_CLASS(item_security, CItemSecurity); - diff --git a/game/server/hl2/item_suit.cpp b/game/server/hl2/item_suit.cpp deleted file mode 100644 index 73aa66ed6..000000000 --- a/game/server/hl2/item_suit.cpp +++ /dev/null @@ -1,58 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -/* - -===== item_suit.cpp ======================================================== - - handling for the player's suit. -*/ - -#include "cbase.h" -#include "player.h" -#include "gamerules.h" -#include "items.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SF_SUIT_SHORTLOGON 0x0001 - -class CItemSuit : public CItem -{ -public: - DECLARE_CLASS( CItemSuit, CItem ); - - void Spawn( void ) - { - Precache( ); - SetModel( "models/items/hevsuit.mdl" ); - BaseClass::Spawn( ); - - CollisionProp()->UseTriggerBounds( false, 0 ); - } - void Precache( void ) - { - PrecacheModel ("models/items/hevsuit.mdl"); - } - bool MyTouch( CBasePlayer *pPlayer ) - { - if ( pPlayer->IsSuitEquipped() ) - return FALSE; - - if ( m_spawnflags & SF_SUIT_SHORTLOGON ) - UTIL_EmitSoundSuit(pPlayer->edict(), "!HEV_A0"); // short version of suit logon, - else - UTIL_EmitSoundSuit(pPlayer->edict(), "!HEV_AAx"); // long version of suit logon - - pPlayer->EquipSuit(); - - return true; - } -}; - -LINK_ENTITY_TO_CLASS(item_suit, CItemSuit); diff --git a/game/server/hl2/look_door.cpp b/game/server/hl2/look_door.cpp deleted file mode 100644 index 1ccbd1877..000000000 --- a/game/server/hl2/look_door.cpp +++ /dev/null @@ -1,237 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements doors that move when you look at them. -// -// $NoKeywords: $ -//=============================================================================// - - -#include "cbase.h" -#include "basecombatcharacter.h" -#include "entitylist.h" -#include "func_movelinear.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SF_LDOOR_THRESHOLD 8192 -#define SF_LDOOR_INVERT 16384 -#define SF_LDOOR_FROM_OPEN 32768 - - -class CLookDoor : public CFuncMoveLinear -{ -public: - DECLARE_CLASS( CLookDoor, CFuncMoveLinear ); - - void Spawn( void ); - void MoveThink( void ); - - // Inputs - void InputInvertOn( inputdata_t &inputdata ); - void InputInvertOff( inputdata_t &inputdata ); - - float m_flProximityDistance; // How far before I start reacting - float m_flProximityOffset; - float m_flFieldOfView; - - EHANDLE m_hLooker; // Who is looking - - DECLARE_DATADESC(); -}; - - -class CLookDoorThinker : public CLogicalEntity -{ -public: - DECLARE_CLASS( CLookDoorThinker, CLogicalEntity ); - - void LookThink( void ); - EHANDLE m_hLookDoor; // Who owns me - - DECLARE_DATADESC(); -}; - - -BEGIN_DATADESC( CLookDoorThinker ) - - DEFINE_FIELD( m_hLookDoor, FIELD_EHANDLE ), - - // Function Pointers - DEFINE_FUNCTION(LookThink), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( lookdoorthinker, CLookDoorThinker ); - - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CLookDoorThinker::LookThink(void) -{ - if (m_hLookDoor) - { - ((CLookDoor*)(CBaseEntity*)m_hLookDoor)->MoveThink(); - SetNextThink( gpGlobals->curtime + 0.01f ); - } - else - { - UTIL_Remove(this); - } -} - - -BEGIN_DATADESC( CLookDoor ) - - DEFINE_KEYFIELD( m_flProximityDistance, FIELD_FLOAT, "ProximityDistance"), - DEFINE_KEYFIELD( m_flProximityOffset, FIELD_FLOAT, "ProximityOffset"), - DEFINE_KEYFIELD( m_flFieldOfView, FIELD_FLOAT, "FieldOfView" ), - DEFINE_FIELD(m_hLooker, FIELD_EHANDLE), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "InvertOn", InputInvertOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "InvertOff", InputInvertOff ), - - // Function Pointers - DEFINE_FUNCTION(MoveThink), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( func_lookdoor, CLookDoor ); - - -//------------------------------------------------------------------------------ -// Purpose : Input handlers. -//------------------------------------------------------------------------------ -void CLookDoor::InputInvertOn( inputdata_t &inputdata ) -{ - m_spawnflags |= SF_LDOOR_INVERT; -} - -void CLookDoor::InputInvertOff( inputdata_t &inputdata ) -{ - m_spawnflags &= ~SF_LDOOR_INVERT; -} - - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CLookDoor::Spawn(void) -{ - BaseClass::Spawn(); - - if (m_target == NULL_STRING) - { - Warning( "ERROR: DoorLook (%s) given no target. Rejecting spawn.\n",GetDebugName()); - return; - } - CLookDoorThinker* pLookThinker = (CLookDoorThinker*)CreateEntityByName("lookdoorthinker"); - if (pLookThinker) - { - pLookThinker->SetThink(&CLookDoorThinker::LookThink); - pLookThinker->m_hLookDoor = this; - pLookThinker->SetNextThink( gpGlobals->curtime + 0.1f ); - } -} - - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CLookDoor::MoveThink(void) -{ - // -------------------------------- - // Make sure we have a looker - // -------------------------------- - if (m_hLooker == NULL) - { - m_hLooker = (CBaseEntity*)gEntList.FindEntityByName( NULL, m_target ); - - if (m_hLooker == NULL) - { - return; - } - } - - //-------------------------------------- - // Calculate an orgin for the door - //-------------------------------------- - Vector vOrigin = WorldSpaceCenter() - GetAbsOrigin(); - - // If FROM_OPEN flag is set, door proximity is measured - // from the open and not the closed position - if (FBitSet (m_spawnflags, SF_LDOOR_FROM_OPEN)) - { - vOrigin += m_vecPosition2; - } - - // ------------------------------------------------------ - // First add movement based on proximity - // ------------------------------------------------------ - float flProxMove = 0; - if (m_flProximityDistance > 0) - { - float flDist = (m_hLooker->GetAbsOrigin() - vOrigin).Length()-m_flProximityOffset; - if (flDist < 0) flDist = 0; - - if (flDist < m_flProximityDistance) - { - if (FBitSet (m_spawnflags, SF_LDOOR_THRESHOLD)) - { - flProxMove = 1.0; - } - else - { - flProxMove = 1-flDist/m_flProximityDistance; - } - } - } - - // ------------------------------------------------------ - // Then add movement based on view angle - // ------------------------------------------------------ - float flViewMove = 0; - if (m_flFieldOfView > 0) - { - // ---------------------------------------- - // Check that toucher is facing the target - // ---------------------------------------- - Assert( dynamic_cast< CBaseCombatCharacter* >( m_hLooker.Get() ) ); - CBaseCombatCharacter* pBCC = (CBaseCombatCharacter*)m_hLooker.Get(); - Vector vTouchDir = pBCC->EyeDirection3D( ); - Vector vTargetDir = vOrigin - pBCC->EyePosition(); - VectorNormalize(vTargetDir); - - float flDotPr = DotProduct(vTouchDir,vTargetDir); - if (flDotPr < m_flFieldOfView) - { - flViewMove = 0.0; - } - else - { - flViewMove = (flDotPr-m_flFieldOfView)/(1.0 - m_flFieldOfView); - } - } - - //--------------------------------------- - // Summate the two moves - //--------------------------------------- - float flMove = flProxMove + flViewMove; - if (flMove > 1.0) - { - flMove = 1.0; - } - - // If behavior is inverted do the reverse - if (FBitSet (m_spawnflags, SF_LDOOR_INVERT)) - { - flMove = 1-flMove; - } - - // Move the door - SetPosition( flMove ); -} - diff --git a/game/server/hl2/monster_dummy.cpp b/game/server/hl2/monster_dummy.cpp deleted file mode 100644 index 8af8c604d..000000000 --- a/game/server/hl2/monster_dummy.cpp +++ /dev/null @@ -1,176 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// This is a skeleton file for use when creating a new -// NPC. Copy and rename this file for the new -// NPC and add the copy to the build. -// -// Leave this file in the build until we ship! Allowing -// this file to be rebuilt with the rest of the game ensures -// that it stays up to date with the rest of the NPC code. -// -// Replace occurances of CNewNPC with the new NPC's -// classname. Don't forget the lower-case occurance in -// LINK_ENTITY_TO_CLASS() -// -// -// ASSUMPTIONS MADE: -// -// You're making a character based on CAI_BaseNPC. If this -// is not true, make sure you replace all occurances -// of 'CAI_BaseNPC' in this file with the appropriate -// parent class. -// -// You're making a human-sized NPC that walks. -// -//=============================================================================// -#include "cbase.h" -#include "ai_default.h" -#include "ai_task.h" -#include "ai_schedule.h" -#include "ai_hull.h" -#include "soundent.h" -#include "game.h" -#include "npcevent.h" -#include "entitylist.h" -#include "activitylist.h" -#include "ai_basenpc.h" -#include "engine/IEngineSound.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//========================================================= -// Private activities -//========================================================= -int ACT_MYCUSTOMACTIVITY = -1; - -//========================================================= -// Custom schedules -//========================================================= -enum -{ - SCHED_MYCUSTOMSCHEDULE = LAST_SHARED_SCHEDULE, -}; - -//========================================================= -// Custom tasks -//========================================================= -enum -{ - TASK_MYCUSTOMTASK = LAST_SHARED_TASK, -}; - - -//========================================================= -// Custom Conditions -//========================================================= -enum -{ - COND_MYCUSTOMCONDITION = LAST_SHARED_CONDITION, -}; - - -//========================================================= -//========================================================= -class CNewNPC : public CAI_BaseNPC -{ - DECLARE_CLASS( CNewNPC, CAI_BaseNPC ); - -public: - void Precache( void ); - void Spawn( void ); - Class_T Classify( void ); - - DECLARE_DATADESC(); - - // This is a dummy field. In order to provide save/restore - // code in this file, we must have at least one field - // for the code to operate on. Delete this field when - // you are ready to do your own save/restore for this - // character. - int m_iDeleteThisField; - - DEFINE_CUSTOM_AI; -}; - -LINK_ENTITY_TO_CLASS( npc_newnpc, CNewNPC ); -IMPLEMENT_CUSTOM_AI( npc_citizen,CNewNPC ); - - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CNewNPC ) - - DEFINE_FIELD( m_iDeleteThisField, FIELD_INTEGER ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: Initialize the custom schedules -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNewNPC::InitCustomSchedules(void) -{ - INIT_CUSTOM_AI(CNewNPC); - - ADD_CUSTOM_TASK(CNewNPC, TASK_MYCUSTOMTASK); - - ADD_CUSTOM_SCHEDULE(CNewNPC, SCHED_MYCUSTOMSCHEDULE); - - ADD_CUSTOM_ACTIVITY(CNewNPC, ACT_MYCUSTOMACTIVITY); - - ADD_CUSTOM_CONDITION(CNewNPC, COND_MYCUSTOMCONDITION); -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CNewNPC::Precache( void ) -{ - PrecacheModel( "models/mymodel.mdl" ); - - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CNewNPC::Spawn( void ) -{ - Precache(); - - SetModel( "models/mymodel.mdl" ); - SetHullType(HULL_HUMAN); - SetHullSizeNormal(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - SetBloodColor( BLOOD_COLOR_RED ); - m_iHealth = 20; - m_flFieldOfView = 0.5; - m_NPCState = NPC_STATE_NONE; - - CapabilitiesClear(); - //CapabilitiesAdd( bits_CAP_NONE ); - - NPCInit(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -// -// Output : -//----------------------------------------------------------------------------- -Class_T CNewNPC::Classify( void ) -{ - return CLASS_NONE; -} diff --git a/game/server/hl2/npc_BaseZombie.cpp b/game/server/hl2/npc_BaseZombie.cpp deleted file mode 100644 index 7e916ff75..000000000 --- a/game/server/hl2/npc_BaseZombie.cpp +++ /dev/null @@ -1,3030 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements the zombie, a horrific once-human headcrab victim. -// -// The zombie has two main states: Full and Torso. -// -// In Full state, the zombie is whole and walks upright as he did in Half-Life. -// He will try to claw the player and swat physics items at him. -// -// In Torso state, the zombie has been blasted or cut in half, and the Torso will -// drag itself along the ground with its arms. It will try to claw the player. -// -// In either state, a severely injured Zombie will release its headcrab, which -// will immediately go after the player. The Zombie will then die (ragdoll). -// -//=============================================================================// - -#include "cbase.h" -#include "npc_BaseZombie.h" -#include "player.h" -#include "game.h" -#include "ai_network.h" -#include "ai_navigator.h" -#include "ai_motor.h" -#include "ai_default.h" -#include "ai_schedule.h" -#include "ai_hull.h" -#include "ai_node.h" -#include "ai_memory.h" -#include "ai_senses.h" -#include "bitstring.h" -#include "EntityFlame.h" -#include "hl2_shareddefs.h" -#include "npcevent.h" -#include "activitylist.h" -#include "entitylist.h" -#include "gib.h" -#include "soundenvelope.h" -#include "ndebugoverlay.h" -#include "rope.h" -#include "rope_shared.h" -#include "igamesystem.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "props.h" -#include "hl2_gamerules.h" -#include "weapon_physcannon.h" -#include "ammodef.h" -#include "vehicle_base.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern ConVar sk_npc_head; - -#define ZOMBIE_BULLET_DAMAGE_SCALE 0.5f - -int g_interactionZombieMeleeWarning; - -envelopePoint_t envDefaultZombieMoanVolumeFast[] = -{ - { 1.0f, 1.0f, - 0.1f, 0.1f, - }, - { 0.0f, 0.0f, - 0.2f, 0.3f, - }, -}; - -envelopePoint_t envDefaultZombieMoanVolume[] = -{ - { 1.0f, 0.1f, - 0.1f, 0.1f, - }, - { 1.0f, 1.0f, - 0.2f, 0.2f, - }, - { 0.0f, 0.0f, - 0.3f, 0.4f, - }, -}; - - -// if the zombie doesn't find anything closer than this, it doesn't swat. -#define ZOMBIE_FARTHEST_PHYSICS_OBJECT 40.0*12.0 -#define ZOMBIE_PHYSICS_SEARCH_DEPTH 100 - -// Don't swat objects unless player is closer than this. -#define ZOMBIE_PLAYER_MAX_SWAT_DIST 1000 - -// -// How much health a Zombie torso gets when a whole zombie is broken -// It's whole zombie's MAX Health * this value -#define ZOMBIE_TORSO_HEALTH_FACTOR 0.5 - -// -// When the zombie has health < m_iMaxHealth * this value, it will -// try to release its headcrab. -#define ZOMBIE_RELEASE_HEALTH_FACTOR 0.5 - -// -// The heaviest physics object that a zombie should try to swat. (kg) -#define ZOMBIE_MAX_PHYSOBJ_MASS 60 - -// -// Zombie tries to get this close to a physics object's origin to swat it -#define ZOMBIE_PHYSOBJ_SWATDIST 80 - -// -// Because movement code sometimes doesn't get us QUITE where we -// want to go, the zombie tries to get this close to a physics object -// Zombie will end up somewhere between PHYSOBJ_MOVE_TO_DIST & PHYSOBJ_SWATDIST -#define ZOMBIE_PHYSOBJ_MOVE_TO_DIST 48 - -// -// How long between physics swat attacks (in seconds). -#define ZOMBIE_SWAT_DELAY 5 - - -// -// After taking damage, ignore further damage for n seconds. This keeps the zombie -// from being interrupted while. -// -#define ZOMBIE_FLINCH_DELAY 3 - - -#define ZOMBIE_BURN_TIME 10 // If ignited, burn for this many seconds -#define ZOMBIE_BURN_TIME_NOISE 2 // Give or take this many seconds. - - -//========================================================= -// private activities -//========================================================= -int CNPC_BaseZombie::ACT_ZOM_SWATLEFTMID; -int CNPC_BaseZombie::ACT_ZOM_SWATRIGHTMID; -int CNPC_BaseZombie::ACT_ZOM_SWATLEFTLOW; -int CNPC_BaseZombie::ACT_ZOM_SWATRIGHTLOW; -int CNPC_BaseZombie::ACT_ZOM_RELEASECRAB; -int CNPC_BaseZombie::ACT_ZOM_FALL; - -ConVar sk_zombie_dmg_one_slash( "sk_zombie_dmg_one_slash","0"); -ConVar sk_zombie_dmg_both_slash( "sk_zombie_dmg_both_slash","0"); - - -// When a zombie spawns, he will select a 'base' pitch value -// that's somewhere between basepitchmin & basepitchmax -ConVar zombie_basemin( "zombie_basemin", "100" ); -ConVar zombie_basemax( "zombie_basemax", "100" ); - -ConVar zombie_changemin( "zombie_changemin", "0" ); -ConVar zombie_changemax( "zombie_changemax", "0" ); - -// play a sound once in every zombie_stepfreq steps -ConVar zombie_stepfreq( "zombie_stepfreq", "4" ); -ConVar zombie_moanfreq( "zombie_moanfreq", "1" ); - -ConVar zombie_decaymin( "zombie_decaymin", "0.1" ); -ConVar zombie_decaymax( "zombie_decaymax", "0.4" ); - -ConVar zombie_ambushdist( "zombie_ambushdist", "16000" ); - -//========================================================= -// For a couple of reasons, we keep a running count of how -// many zombies in the world are angry at any given time. -//========================================================= -static int s_iAngryZombies = 0; - -//========================================================= -//========================================================= -class CAngryZombieCounter : public CAutoGameSystem -{ -public: - CAngryZombieCounter( char const *name ) : CAutoGameSystem( name ) - { - } - // Level init, shutdown - virtual void LevelInitPreEntity() - { - s_iAngryZombies = 0; - } -}; - -CAngryZombieCounter AngryZombieCounter( "CAngryZombieCounter" ); - - -int AE_ZOMBIE_ATTACK_RIGHT; -int AE_ZOMBIE_ATTACK_LEFT; -int AE_ZOMBIE_ATTACK_BOTH; -int AE_ZOMBIE_SWATITEM; -int AE_ZOMBIE_STARTSWAT; -int AE_ZOMBIE_STEP_LEFT; -int AE_ZOMBIE_STEP_RIGHT; -int AE_ZOMBIE_SCUFF_LEFT; -int AE_ZOMBIE_SCUFF_RIGHT; -int AE_ZOMBIE_ATTACK_SCREAM; -int AE_ZOMBIE_GET_UP; -int AE_ZOMBIE_POUND; -int AE_ZOMBIE_ALERTSOUND; -int AE_ZOMBIE_POPHEADCRAB; - - -//========================================================= -//========================================================= -BEGIN_DATADESC( CNPC_BaseZombie ) - - DEFINE_SOUNDPATCH( m_pMoanSound ), - DEFINE_FIELD( m_fIsTorso, FIELD_BOOLEAN ), - DEFINE_FIELD( m_fIsHeadless, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flNextFlinch, FIELD_TIME ), - DEFINE_FIELD( m_bHeadShot, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flBurnDamage, FIELD_FLOAT ), - DEFINE_FIELD( m_flBurnDamageResetTime, FIELD_TIME ), - DEFINE_FIELD( m_hPhysicsEnt, FIELD_EHANDLE ), - DEFINE_FIELD( m_flNextMoanSound, FIELD_TIME ), - DEFINE_FIELD( m_flNextSwat, FIELD_TIME ), - DEFINE_FIELD( m_flNextSwatScan, FIELD_TIME ), - DEFINE_FIELD( m_crabHealth, FIELD_FLOAT ), - DEFINE_FIELD( m_flMoanPitch, FIELD_FLOAT ), - DEFINE_FIELD( m_iMoanSound, FIELD_INTEGER ), - DEFINE_FIELD( m_hObstructor, FIELD_EHANDLE ), - DEFINE_FIELD( m_bIsSlumped, FIELD_BOOLEAN ), - -END_DATADESC() - - -//LINK_ENTITY_TO_CLASS( base_zombie, CNPC_BaseZombie ); - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CNPC_BaseZombie::g_numZombies = 0; - - -//--------------------------------------------------------- -//--------------------------------------------------------- -CNPC_BaseZombie::CNPC_BaseZombie() -{ - // Gotta select which sound we're going to play, right here! - // Because everyone's constructed before they spawn. - // - // Assign moan sounds in order, over and over. - // This means if 3 or so zombies spawn near each - // other, they will definitely not pick the same - // moan loop. - m_iMoanSound = g_numZombies; - - g_numZombies++; -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -CNPC_BaseZombie::~CNPC_BaseZombie() -{ - g_numZombies--; -} - - -//--------------------------------------------------------- -// The closest physics object is chosen that is: -// <= MaxMass in Mass -// Between the zombie and the enemy -// not too far from a direct line to the enemy. -//--------------------------------------------------------- -bool CNPC_BaseZombie::FindNearestPhysicsObject( int iMaxMass ) -{ - CBaseEntity *pList[ ZOMBIE_PHYSICS_SEARCH_DEPTH ]; - CBaseEntity *pNearest = NULL; - float flDist; - IPhysicsObject *pPhysObj; - int i; - Vector vecDirToEnemy; - Vector vecDirToObject; - - if ( !CanSwatPhysicsObjects() || !GetEnemy() ) - { - // Can't swat, or no enemy, so no swat. - m_hPhysicsEnt = NULL; - return false; - } - - vecDirToEnemy = GetEnemy()->GetAbsOrigin() - GetAbsOrigin(); - float dist = VectorNormalize(vecDirToEnemy); - vecDirToEnemy.z = 0; - - if( dist > ZOMBIE_PLAYER_MAX_SWAT_DIST ) - { - // Player is too far away. Don't bother - // trying to swat anything at them until - // they are closer. - return false; - } - - float flNearestDist = MIN( dist, ZOMBIE_FARTHEST_PHYSICS_OBJECT * 0.5 ); - Vector vecDelta( flNearestDist, flNearestDist, GetHullHeight() * 2.0 ); - - class CZombieSwatEntitiesEnum : public CFlaggedEntitiesEnum - { - public: - CZombieSwatEntitiesEnum( CBaseEntity **pList, int listMax, int iMaxMass ) - : CFlaggedEntitiesEnum( pList, listMax, 0 ), - m_iMaxMass( iMaxMass ) - { - } - - virtual IterationRetval_t EnumElement( IHandleEntity *pHandleEntity ) - { - CBaseEntity *pEntity = gEntList.GetBaseEntity( pHandleEntity->GetRefEHandle() ); - if ( pEntity && - pEntity->VPhysicsGetObject() && - pEntity->VPhysicsGetObject()->GetMass() <= m_iMaxMass && - pEntity->VPhysicsGetObject()->IsAsleep() && - pEntity->VPhysicsGetObject()->IsMoveable() ) - { - return CFlaggedEntitiesEnum::EnumElement( pHandleEntity ); - } - return ITERATION_CONTINUE; - } - - int m_iMaxMass; - }; - - CZombieSwatEntitiesEnum swatEnum( pList, ZOMBIE_PHYSICS_SEARCH_DEPTH, iMaxMass ); - - int count = UTIL_EntitiesInBox( GetAbsOrigin() - vecDelta, GetAbsOrigin() + vecDelta, &swatEnum ); - - // magically know where they are - Vector vecZombieKnees; - CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 0.25f ), &vecZombieKnees ); - - for( i = 0 ; i < count ; i++ ) - { - pPhysObj = pList[ i ]->VPhysicsGetObject(); - - Assert( !( !pPhysObj || pPhysObj->GetMass() > iMaxMass || !pPhysObj->IsAsleep() ) ); - - Vector center = pList[ i ]->WorldSpaceCenter(); - flDist = UTIL_DistApprox2D( GetAbsOrigin(), center ); - - if( flDist >= flNearestDist ) - continue; - - // This object is closer... but is it between the player and the zombie? - vecDirToObject = pList[ i ]->WorldSpaceCenter() - GetAbsOrigin(); - VectorNormalize(vecDirToObject); - vecDirToObject.z = 0; - - if( DotProduct( vecDirToEnemy, vecDirToObject ) < 0.8 ) - continue; - - if( flDist >= UTIL_DistApprox2D( center, GetEnemy()->GetAbsOrigin() ) ) - continue; - - // don't swat things where the highest point is under my knees - // NOTE: This is a rough test; a more exact test is going to occur below - if ( (center.z + pList[i]->BoundingRadius()) < vecZombieKnees.z ) - continue; - - // don't swat things that are over my head. - if( center.z > EyePosition().z ) - continue; - - vcollide_t *pCollide = modelinfo->GetVCollide( pList[i]->GetModelIndex() ); - - Vector objMins, objMaxs; - physcollision->CollideGetAABB( &objMins, &objMaxs, pCollide->solids[0], pList[i]->GetAbsOrigin(), pList[i]->GetAbsAngles() ); - - if ( objMaxs.z < vecZombieKnees.z ) - continue; - - if ( !FVisible( pList[i] ) ) - continue; - - if ( hl2_episodic.GetBool() ) - { - // Skip things that the enemy can't see. Do we want this as a general thing? - // The case for this feature is that zombies who are pursuing the player will - // stop along the way to swat objects at the player who is around the corner or - // otherwise not in a place that the object has a hope of hitting. This diversion - // makes the zombies very late (in a random fashion) getting where they are going. (sjb 1/2/06) - if( !GetEnemy()->FVisible( pList[i] ) ) - continue; - } - - // Make this the last check, since it makes a string. - // Don't swat server ragdolls! - if ( FClassnameIs( pList[ i ], "physics_prop_ragdoll" ) ) - continue; - - if ( FClassnameIs( pList[ i ], "prop_ragdoll" ) ) - continue; - - // The object must also be closer to the zombie than it is to the enemy - pNearest = pList[ i ]; - flNearestDist = flDist; - } - - m_hPhysicsEnt = pNearest; - - if( m_hPhysicsEnt == NULL ) - { - return false; - } - else - { - return true; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Returns this monster's place in the relationship table. -//----------------------------------------------------------------------------- -Class_T CNPC_BaseZombie::Classify( void ) -{ - if ( IsSlumped() ) - return CLASS_NONE; - - return( CLASS_ZOMBIE ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Disposition_t CNPC_BaseZombie::IRelationType( CBaseEntity *pTarget ) -{ - // Slumping should not affect Zombie's opinion of others - if ( IsSlumped() ) - { - m_bIsSlumped = false; - Disposition_t result = BaseClass::IRelationType( pTarget ); - m_bIsSlumped = true; - return result; - } - - return BaseClass::IRelationType( pTarget ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the maximum yaw speed based on the monster's current activity. -//----------------------------------------------------------------------------- -float CNPC_BaseZombie::MaxYawSpeed( void ) -{ - if( m_fIsTorso ) - { - return( 60 ); - } - else if (IsMoving() && HasPoseParameter( GetSequence(), m_poseMove_Yaw )) - { - return( 15 ); - } - else - { - switch( GetActivity() ) - { - case ACT_TURN_LEFT: - case ACT_TURN_RIGHT: - return 100; - break; - case ACT_RUN: - return 15; - break; - case ACT_WALK: - case ACT_IDLE: - return 25; - break; - case ACT_RANGE_ATTACK1: - case ACT_RANGE_ATTACK2: - case ACT_MELEE_ATTACK1: - case ACT_MELEE_ATTACK2: - return 120; - default: - return 90; - break; - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: turn in the direction of movement -// Output : -//----------------------------------------------------------------------------- -bool CNPC_BaseZombie::OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval ) -{ - if (!HasPoseParameter( GetSequence(), m_poseMove_Yaw )) - { - return BaseClass::OverrideMoveFacing( move, flInterval ); - } - - // required movement direction - float flMoveYaw = UTIL_VecToYaw( move.dir ); - float idealYaw = UTIL_AngleMod( flMoveYaw ); - - if (GetEnemy()) - { - float flEDist = UTIL_DistApprox2D( WorldSpaceCenter(), GetEnemy()->WorldSpaceCenter() ); - - if (flEDist < 256.0) - { - float flEYaw = UTIL_VecToYaw( GetEnemy()->WorldSpaceCenter() - WorldSpaceCenter() ); - - if (flEDist < 128.0) - { - idealYaw = flEYaw; - } - else - { - idealYaw = flMoveYaw + UTIL_AngleDiff( flEYaw, flMoveYaw ) * (2 - flEDist / 128.0); - } - - //DevMsg("was %.0f now %.0f\n", flMoveYaw, idealYaw ); - } - } - - GetMotor()->SetIdealYawAndUpdate( idealYaw ); - - // find movement direction to compensate for not being turned far enough - float fSequenceMoveYaw = GetSequenceMoveYaw( GetSequence() ); - float flDiff = UTIL_AngleDiff( flMoveYaw, GetLocalAngles().y + fSequenceMoveYaw ); - SetPoseParameter( m_poseMove_Yaw, GetPoseParameter( m_poseMove_Yaw ) + flDiff ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: For innate melee attack -// Input : -// Output : -//----------------------------------------------------------------------------- -int CNPC_BaseZombie::MeleeAttack1Conditions ( float flDot, float flDist ) -{ - float range = GetClawAttackRange(); - - if (flDist > range ) - { - // Translate a hit vehicle into its passenger if found - if ( GetEnemy() != NULL ) - { -#if defined(HL2_DLL) && !defined(HL2MP) - // If the player is holding an object, knock it down. - if( GetEnemy()->IsPlayer() ) - { - CBasePlayer *pPlayer = ToBasePlayer( GetEnemy() ); - - Assert( pPlayer != NULL ); - - // Is the player carrying something? - CBaseEntity *pObject = GetPlayerHeldEntity(pPlayer); - - if( !pObject ) - { - pObject = PhysCannonGetHeldEntity( pPlayer->GetActiveWeapon() ); - } - - if( pObject ) - { - float flDist = pObject->WorldSpaceCenter().DistTo( WorldSpaceCenter() ); - - if( flDist <= GetClawAttackRange() ) - return COND_CAN_MELEE_ATTACK1; - } - } -#endif - } - return COND_TOO_FAR_TO_ATTACK; - } - - if (flDot < 0.7) - { - return COND_NOT_FACING_ATTACK; - } - - // Build a cube-shaped hull, the same hull that ClawAttack() is going to use. - Vector vecMins = GetHullMins(); - Vector vecMaxs = GetHullMaxs(); - vecMins.z = vecMins.x; - vecMaxs.z = vecMaxs.x; - - Vector forward; - GetVectors( &forward, NULL, NULL ); - - trace_t tr; - CTraceFilterNav traceFilter( this, false, this, COLLISION_GROUP_NONE ); - AI_TraceHull( WorldSpaceCenter(), WorldSpaceCenter() + forward * GetClawAttackRange(), vecMins, vecMaxs, MASK_NPCSOLID, &traceFilter, &tr ); - - if( tr.fraction == 1.0 || !tr.m_pEnt ) - { - -#ifdef HL2_EPISODIC - - // If our trace was unobstructed but we were shooting - if ( GetEnemy() && GetEnemy()->Classify() == CLASS_BULLSEYE ) - return COND_CAN_MELEE_ATTACK1; - -#endif // HL2_EPISODIC - - // This attack would miss completely. Trick the zombie into moving around some more. - return COND_TOO_FAR_TO_ATTACK; - } - - if( tr.m_pEnt == GetEnemy() || - tr.m_pEnt->IsNPC() || - ( tr.m_pEnt->m_takedamage == DAMAGE_YES && (dynamic_cast(tr.m_pEnt) ) ) ) - { - // -Let the zombie swipe at his enemy if he's going to hit them. - // -Also let him swipe at NPC's that happen to be between the zombie and the enemy. - // This makes mobs of zombies seem more rowdy since it doesn't leave guys in the back row standing around. - // -Also let him swipe at things that takedamage, under the assumptions that they can be broken. - return COND_CAN_MELEE_ATTACK1; - } - - Vector vecTrace = tr.endpos - tr.startpos; - float lenTraceSq = vecTrace.Length2DSqr(); - - if ( GetEnemy() && GetEnemy()->MyCombatCharacterPointer() && tr.m_pEnt == static_cast(GetEnemy())->GetVehicleEntity() ) - { - if ( lenTraceSq < Square( GetClawAttackRange() * 0.75f ) ) - { - return COND_CAN_MELEE_ATTACK1; - } - } - - if( tr.m_pEnt->IsBSPModel() ) - { - // The trace hit something solid, but it's not the enemy. If this item is closer to the zombie than - // the enemy is, treat this as an obstruction. - Vector vecToEnemy = GetEnemy()->WorldSpaceCenter() - WorldSpaceCenter(); - - if( lenTraceSq < vecToEnemy.Length2DSqr() ) - { - return COND_ZOMBIE_LOCAL_MELEE_OBSTRUCTION; - } - } - -#ifdef HL2_EPISODIC - - if ( !tr.m_pEnt->IsWorld() && GetEnemy() && GetEnemy()->GetGroundEntity() == tr.m_pEnt ) - { - //Try to swat whatever the player is standing on instead of acting like a dill. - return COND_CAN_MELEE_ATTACK1; - } - - // Bullseyes are given some grace on if they can be hit - if ( GetEnemy() && GetEnemy()->Classify() == CLASS_BULLSEYE ) - return COND_CAN_MELEE_ATTACK1; - -#endif // HL2_EPISODIC - - // Move around some more - return COND_TOO_FAR_TO_ATTACK; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -#define ZOMBIE_BUCKSHOT_TRIPLE_DAMAGE_DIST 96.0f // Triple damage from buckshot at 8 feet (headshot only) -float CNPC_BaseZombie::GetHitgroupDamageMultiplier( int iHitGroup, const CTakeDamageInfo &info ) -{ - switch( iHitGroup ) - { - case HITGROUP_HEAD: - { - if( info.GetDamageType() & DMG_BUCKSHOT ) - { - float flDist = FLT_MAX; - - if( info.GetAttacker() ) - { - flDist = ( GetAbsOrigin() - info.GetAttacker()->GetAbsOrigin() ).Length(); - } - - if( flDist <= ZOMBIE_BUCKSHOT_TRIPLE_DAMAGE_DIST ) - { - return 3.0f; - } - } - else - { - return 2.0f; - } - } - } - - return BaseClass::GetHitgroupDamageMultiplier( iHitGroup, info ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_BaseZombie::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - CTakeDamageInfo infoCopy = info; - - // Keep track of headshots so we can determine whether to pop off our headcrab. - if (ptr->hitgroup == HITGROUP_HEAD) - { - m_bHeadShot = true; - } - - if( infoCopy.GetDamageType() & DMG_BUCKSHOT ) - { - // Zombie gets across-the-board damage reduction for buckshot. This compensates for the recent changes which - // make the shotgun much more powerful, and returns the zombies to a level that has been playtested extensively.(sjb) - // This normalizes the buckshot damage to what it used to be on normal (5 dmg per pellet. Now it's 8 dmg per pellet). - infoCopy.ScaleDamage( 0.625 ); - } - - BaseClass::TraceAttack( infoCopy, vecDir, ptr ); -} - - -//----------------------------------------------------------------------------- -// Purpose: A zombie has taken damage. Determine whether he should split in half -// Input : -// Output : bool, true if yes. -//----------------------------------------------------------------------------- -bool CNPC_BaseZombie::ShouldBecomeTorso( const CTakeDamageInfo &info, float flDamageThreshold ) -{ - if ( info.GetDamageType() & DMG_REMOVENORAGDOLL ) - return false; - - if ( m_fIsTorso ) - { - // Already split. - return false; - } - - // Not if we're in a dss - if ( IsRunningDynamicInteraction() ) - return false; - - // Break in half IF: - // - // Take half or more of max health in DMG_BLAST - if( (info.GetDamageType() & DMG_BLAST) && flDamageThreshold >= 0.5 ) - { - return true; - } - - if ( hl2_episodic.GetBool() ) - { - // Always split after a cannon hit - if ( info.GetAmmoType() == GetAmmoDef()->Index("CombineHeavyCannon") ) - return true; - } - -#if 0 - if( info.GetDamageType() & DMG_BUCKSHOT ) - { - if( m_iHealth <= 0 || flDamageThreshold >= 0.5 ) - { - return true; - } - } -#endif - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: A zombie has taken damage. Determine whether he release his headcrab. -// Output : YES, IMMEDIATE, or SCHEDULED (see HeadcrabRelease_t) -//----------------------------------------------------------------------------- -HeadcrabRelease_t CNPC_BaseZombie::ShouldReleaseHeadcrab( const CTakeDamageInfo &info, float flDamageThreshold ) -{ - if ( m_iHealth <= 0 ) - { - if ( info.GetDamageType() & DMG_REMOVENORAGDOLL ) - return RELEASE_NO; - - if ( info.GetDamageType() & DMG_SNIPER ) - return RELEASE_RAGDOLL; - - // If I was killed by a bullet... - if ( info.GetDamageType() & DMG_BULLET ) - { - if( m_bHeadShot ) - { - if( flDamageThreshold > 0.25 ) - { - // Enough force to kill the crab. - return RELEASE_RAGDOLL; - } - } - else - { - // Killed by a shot to body or something. Crab is ok! - return RELEASE_IMMEDIATE; - } - } - - // If I was killed by an explosion, release the crab. - if ( info.GetDamageType() & DMG_BLAST ) - { - return RELEASE_RAGDOLL; - } - - if ( m_fIsTorso && IsChopped( info ) ) - { - return RELEASE_RAGDOLL_SLICED_OFF; - } - } - - return RELEASE_NO; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pInflictor - -// pAttacker - -// flDamage - -// bitsDamageType - -// Output : int -//----------------------------------------------------------------------------- -#define ZOMBIE_SCORCH_RATE 8 -#define ZOMBIE_MIN_RENDERCOLOR 50 -int CNPC_BaseZombie::OnTakeDamage_Alive( const CTakeDamageInfo &inputInfo ) -{ - CTakeDamageInfo info = inputInfo; - - if( inputInfo.GetDamageType() & DMG_BURN ) - { - // If a zombie is on fire it only takes damage from the fire that's attached to it. (DMG_DIRECT) - // This is to stop zombies from burning to death 10x faster when they're standing around - // 10 fire entities. - if( IsOnFire() && !(inputInfo.GetDamageType() & DMG_DIRECT) ) - { - return 0; - } - - Scorch( ZOMBIE_SCORCH_RATE, ZOMBIE_MIN_RENDERCOLOR ); - } - - // Take some percentage of damage from bullets (unless hit in the crab). Always take full buckshot & sniper damage - if ( !m_bHeadShot && (info.GetDamageType() & DMG_BULLET) && !(info.GetDamageType() & (DMG_BUCKSHOT|DMG_SNIPER)) ) - { - info.ScaleDamage( ZOMBIE_BULLET_DAMAGE_SCALE ); - } - - if ( ShouldIgnite( info ) ) - { - Ignite( 100.0f ); - } - - int tookDamage = BaseClass::OnTakeDamage_Alive( info ); - - // flDamageThreshold is what percentage of the creature's max health - // this amount of damage represents. (clips at 1.0) - float flDamageThreshold = MIN( 1, info.GetDamage() / m_iMaxHealth ); - - // Being chopped up by a sharp physics object is a pretty special case - // so we handle it with some special code. Mainly for - // Ravenholm's helicopter traps right now (sjb). - bool bChopped = IsChopped(info); - bool bSquashed = IsSquashed(info); - bool bKilledByVehicle = ( ( info.GetDamageType() & DMG_VEHICLE ) != 0 ); - - if( !m_fIsTorso && (bChopped || bSquashed) && !bKilledByVehicle && !(info.GetDamageType() & DMG_REMOVENORAGDOLL) ) - { - if( bChopped ) - { - EmitSound( "E3_Phystown.Slicer" ); - } - - DieChopped( info ); - } - else - { - HeadcrabRelease_t release = ShouldReleaseHeadcrab( info, flDamageThreshold ); - - switch( release ) - { - case RELEASE_IMMEDIATE: - ReleaseHeadcrab( EyePosition(), vec3_origin, true, true ); - break; - - case RELEASE_RAGDOLL: - // Go a little easy on headcrab ragdoll force. They're light! - ReleaseHeadcrab( EyePosition(), inputInfo.GetDamageForce() * 0.25, true, false, true ); - break; - - case RELEASE_RAGDOLL_SLICED_OFF: - { - EmitSound( "E3_Phystown.Slicer" ); - Vector vecForce = inputInfo.GetDamageForce() * 0.1; - vecForce += Vector( 0, 0, 2000.0 ); - ReleaseHeadcrab( EyePosition(), vecForce, true, false, true ); - } - break; - - case RELEASE_VAPORIZE: - RemoveHead(); - break; - - case RELEASE_SCHEDULED: - SetCondition( COND_ZOMBIE_RELEASECRAB ); - break; - - default: - break; - } - - if( ShouldBecomeTorso( info, flDamageThreshold ) ) - { - bool bHitByCombineCannon = (inputInfo.GetAmmoType() == GetAmmoDef()->Index("CombineHeavyCannon")); - - if ( CanBecomeLiveTorso() ) - { - BecomeTorso( vec3_origin, inputInfo.GetDamageForce() * 0.50 ); - - if ( ( info.GetDamageType() & DMG_BLAST) && random->RandomInt( 0, 1 ) == 0 ) - { - Ignite( 5.0 + random->RandomFloat( 0.0, 5.0 ) ); - } - - // For Combine cannon impacts - if ( hl2_episodic.GetBool() ) - { - if ( bHitByCombineCannon ) - { - // Catch on fire. - Ignite( 5.0f + random->RandomFloat( 0.0f, 5.0f ) ); - } - } - - if (flDamageThreshold >= 1.0) - { - m_iHealth = 0; - BecomeRagdollOnClient( info.GetDamageForce() ); - } - } - else if ( random->RandomInt(1, 3) == 1 ) - DieChopped( info ); - } - } - - if( tookDamage > 0 && (info.GetDamageType() & (DMG_BURN|DMG_DIRECT)) && m_ActBusyBehavior.IsActive() ) - { - //!!!HACKHACK- Stuff a light_damage condition if an actbusying zombie takes direct burn damage. This will cause an - // ignited zombie to 'wake up' and rise out of its actbusy slump. (sjb) - SetCondition( COND_LIGHT_DAMAGE ); - } - - // IMPORTANT: always clear the headshot flag after applying damage. No early outs! - m_bHeadShot = false; - - return tookDamage; -} - -//----------------------------------------------------------------------------- -// Purpose: make a sound Alyx can hear when in darkness mode -// Input : volume (radius) of the sound. -// Output : -//----------------------------------------------------------------------------- -void CNPC_BaseZombie::MakeAISpookySound( float volume, float duration ) -{ - if ( HL2GameRules()->IsAlyxInDarknessMode() ) - { - CSoundEnt::InsertSound( SOUND_COMBAT, EyePosition(), (int)volume, duration, this, SOUNDENT_CHANNEL_SPOOKY_NOISE ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_BaseZombie::CanPlayMoanSound() -{ - if( HasSpawnFlags( SF_NPC_GAG ) ) - return false; - - // Burning zombies play their moan loop at full volume for as long as they're - // burning. Don't let a moan envelope play cause it will turn the volume down when done. - if( IsOnFire() ) - return false; - - // Members of a small group of zombies can vocalize whenever they want - if( s_iAngryZombies <= 4 ) - return true; - - // This serves to limit the number of zombies that can moan at one time when there are a lot. - if( random->RandomInt( 1, zombie_moanfreq.GetInt() * (s_iAngryZombies/2) ) == 1 ) - { - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Open a window and let a little bit of the looping moan sound -// come through. -//----------------------------------------------------------------------------- -void CNPC_BaseZombie::MoanSound( envelopePoint_t *pEnvelope, int iEnvelopeSize ) -{ - if( HasSpawnFlags( SF_NPC_GAG ) ) - { - // Not yet! - return; - } - - if( !m_pMoanSound ) - { - // Don't set this up until the code calls for it. - const char *pszSound = GetMoanSound( m_iMoanSound ); - m_flMoanPitch = random->RandomInt( zombie_basemin.GetInt(), zombie_basemax.GetInt() ); - - //m_pMoanSound = ENVELOPE_CONTROLLER.SoundCreate( entindex(), CHAN_STATIC, pszSound, ATTN_NORM ); - CPASAttenuationFilter filter( this ); - m_pMoanSound = ENVELOPE_CONTROLLER.SoundCreate( filter, entindex(), CHAN_STATIC, pszSound, ATTN_NORM ); - - ENVELOPE_CONTROLLER.Play( m_pMoanSound, 1.0, m_flMoanPitch ); - } - - //HACKHACK get these from chia chin's console vars. - envDefaultZombieMoanVolumeFast[ 1 ].durationMin = zombie_decaymin.GetFloat(); - envDefaultZombieMoanVolumeFast[ 1 ].durationMax = zombie_decaymax.GetFloat(); - - if( random->RandomInt( 1, 2 ) == 1 ) - { - IdleSound(); - } - - float duration = ENVELOPE_CONTROLLER.SoundPlayEnvelope( m_pMoanSound, SOUNDCTRL_CHANGE_VOLUME, pEnvelope, iEnvelopeSize ); - - float flPitch = random->RandomInt( (int)m_flMoanPitch + zombie_changemin.GetInt(), (int)m_flMoanPitch + zombie_changemax.GetInt() ); - ENVELOPE_CONTROLLER.SoundChangePitch( m_pMoanSound, flPitch, 0.3 ); - - m_flNextMoanSound = gpGlobals->curtime + duration + 9999; -} - -//----------------------------------------------------------------------------- -// Purpose: Determine whether the zombie is chopped up by some physics item -//----------------------------------------------------------------------------- -bool CNPC_BaseZombie::IsChopped( const CTakeDamageInfo &info ) -{ - float flDamageThreshold = MIN( 1, info.GetDamage() / m_iMaxHealth ); - - if ( m_iHealth > 0 || flDamageThreshold <= 0.5 ) - return false; - - if ( !( info.GetDamageType() & DMG_SLASH) ) - return false; - - if ( !( info.GetDamageType() & DMG_CRUSH) ) - return false; - - if ( info.GetDamageType() & DMG_REMOVENORAGDOLL ) - return false; - - // If you take crush and slash damage, you're hit by a sharp physics item. - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Return true if this gibbing zombie should ignite its gibs -//----------------------------------------------------------------------------- -bool CNPC_BaseZombie::ShouldIgniteZombieGib( void ) -{ -#ifdef HL2_EPISODIC - // If we're in darkness mode, don't ignite giblets, because we don't want to - // pay the perf cost of multiple dynamic lights per giblet. - return ( IsOnFire() && !HL2GameRules()->IsAlyxInDarknessMode() ); -#else - return IsOnFire(); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Handle the special case of a zombie killed by a physics chopper. -//----------------------------------------------------------------------------- -void CNPC_BaseZombie::DieChopped( const CTakeDamageInfo &info ) -{ - bool bSquashed = IsSquashed(info); - - Vector forceVector( vec3_origin ); - - forceVector += CalcDamageForceVector( info ); - - if( !m_fIsHeadless && !bSquashed ) - { - if( random->RandomInt( 0, 1 ) == 0 ) - { - // Drop a live crab half of the time. - ReleaseHeadcrab( EyePosition(), forceVector * 0.005, true, false, false ); - } - } - - float flFadeTime = 0.0; - - if( HasSpawnFlags( SF_NPC_FADE_CORPSE ) ) - { - flFadeTime = 5.0; - } - - SetSolid( SOLID_NONE ); - AddEffects( EF_NODRAW ); - - Vector vecLegsForce; - vecLegsForce.x = random->RandomFloat( -400, 400 ); - vecLegsForce.y = random->RandomFloat( -400, 400 ); - vecLegsForce.z = random->RandomFloat( 0, 250 ); - - if( bSquashed && vecLegsForce.z > 0 ) - { - // Force the broken legs down. (Give some additional force, too) - vecLegsForce.z *= -10; - } - - CBaseEntity *pLegGib = CreateRagGib( GetLegsModel(), GetAbsOrigin(), GetAbsAngles(), vecLegsForce, flFadeTime, ShouldIgniteZombieGib() ); - if ( pLegGib ) - { - CopyRenderColorTo( pLegGib ); - } - - forceVector *= random->RandomFloat( 0.04, 0.06 ); - forceVector.z = ( 100 * 12 * 5 ) * random->RandomFloat( 0.8, 1.2 ); - - if( bSquashed && forceVector.z > 0 ) - { - // Force the broken torso down. - forceVector.z *= -1.0; - } - - // Why do I have to fix this up?! (sjb) - QAngle TorsoAngles; - TorsoAngles = GetAbsAngles(); - TorsoAngles.x -= 90.0f; - CBaseEntity *pTorsoGib = CreateRagGib( GetTorsoModel(), GetAbsOrigin() + Vector( 0, 0, 64 ), TorsoAngles, forceVector, flFadeTime, ShouldIgniteZombieGib() ); - if ( pTorsoGib ) - { - CBaseAnimating *pAnimating = dynamic_cast(pTorsoGib); - if( pAnimating ) - { - pAnimating->SetBodygroup( ZOMBIE_BODYGROUP_HEADCRAB, !m_fIsHeadless ); - } - - pTorsoGib->SetOwnerEntity( this ); - CopyRenderColorTo( pTorsoGib ); - - } - - if ( UTIL_ShouldShowBlood( BLOOD_COLOR_YELLOW ) ) - { - int i; - Vector vecSpot; - Vector vecDir; - - for ( i = 0 ; i < 4; i++ ) - { - vecSpot = WorldSpaceCenter(); - - vecSpot.x += random->RandomFloat( -12, 12 ); - vecSpot.y += random->RandomFloat( -12, 12 ); - vecSpot.z += random->RandomFloat( -4, 16 ); - - UTIL_BloodDrips( vecSpot, vec3_origin, BLOOD_COLOR_YELLOW, 50 ); - } - - for ( int i = 0 ; i < 4 ; i++ ) - { - Vector vecSpot = WorldSpaceCenter(); - - vecSpot.x += random->RandomFloat( -12, 12 ); - vecSpot.y += random->RandomFloat( -12, 12 ); - vecSpot.z += random->RandomFloat( -4, 16 ); - - vecDir.x = random->RandomFloat(-1, 1); - vecDir.y = random->RandomFloat(-1, 1); - vecDir.z = 0; - VectorNormalize( vecDir ); - - UTIL_BloodImpact( vecSpot, vecDir, BloodColor(), 1 ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: damage has been done. Should the zombie ignite? -//----------------------------------------------------------------------------- -bool CNPC_BaseZombie::ShouldIgnite( const CTakeDamageInfo &info ) -{ - if ( IsOnFire() ) - { - // Already burning! - return false; - } - - if ( info.GetDamageType() & DMG_BURN ) - { - // - // If we take more than ten percent of our health in burn damage within a five - // second interval, we should catch on fire. - // - m_flBurnDamage += info.GetDamage(); - m_flBurnDamageResetTime = gpGlobals->curtime + 5; - - if ( m_flBurnDamage >= m_iMaxHealth * 0.1 ) - { - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Sufficient fire damage has been done. Zombie ignites! -//----------------------------------------------------------------------------- -void CNPC_BaseZombie::Ignite( float flFlameLifetime, bool bNPCOnly, float flSize, bool bCalledByLevelDesigner ) -{ - BaseClass::Ignite( flFlameLifetime, bNPCOnly, flSize, bCalledByLevelDesigner ); - -#ifdef HL2_EPISODIC - if ( HL2GameRules()->IsAlyxInDarknessMode() == true && GetEffectEntity() != NULL ) - { - GetEffectEntity()->AddEffects( EF_DIMLIGHT ); - } -#endif // HL2_EPISODIC - - // Set the zombie up to burn to death in about ten seconds. - SetHealth( (int)MIN( m_iHealth, FLAME_DIRECT_DAMAGE_PER_SEC * (ZOMBIE_BURN_TIME + random->RandomFloat( -ZOMBIE_BURN_TIME_NOISE, ZOMBIE_BURN_TIME_NOISE)) ) ); - - // FIXME: use overlays when they come online - //AddOverlay( ACT_ZOM_WALK_ON_FIRE, false ); - if( !m_ActBusyBehavior.IsActive() ) - { - Activity activity = GetActivity(); - Activity burningActivity = activity; - - if ( activity == ACT_WALK ) - { - burningActivity = ACT_WALK_ON_FIRE; - } - else if ( activity == ACT_RUN ) - { - burningActivity = ACT_RUN_ON_FIRE; - } - else if ( activity == ACT_IDLE ) - { - burningActivity = ACT_IDLE_ON_FIRE; - } - - if( HaveSequenceForActivity(burningActivity) ) - { - // Make sure we have a sequence for this activity (torsos don't have any, for instance) - // to prevent the baseNPC & baseAnimating code from throwing red level errors. - SetActivity( burningActivity ); - } - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_BaseZombie::CopyRenderColorTo( CBaseEntity *pOther ) -{ - color32 color = GetRenderColor(); - pOther->SetRenderColor( color.r, color.g, color.b, color.a ); -} - -//----------------------------------------------------------------------------- -// Purpose: Look in front and see if the claw hit anything. -// -// Input : flDist distance to trace -// iDamage damage to do if attack hits -// vecViewPunch camera punch (if attack hits player) -// vecVelocityPunch velocity punch (if attack hits player) -// -// Output : The entity hit by claws. NULL if nothing. -//----------------------------------------------------------------------------- -CBaseEntity *CNPC_BaseZombie::ClawAttack( float flDist, int iDamage, QAngle &qaViewPunch, Vector &vecVelocityPunch, int BloodOrigin ) -{ - // Added test because claw attack anim sometimes used when for cases other than melee - int iDriverInitialHealth = -1; - CBaseEntity *pDriver = NULL; - if ( GetEnemy() ) - { - trace_t tr; - AI_TraceHull( WorldSpaceCenter(), GetEnemy()->WorldSpaceCenter(), -Vector(8,8,8), Vector(8,8,8), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction < 1.0f ) - return NULL; - - // CheckTraceHullAttack() can damage player in vehicle as side effect of melee attack damaging physics objects, which the car forwards to the player - // need to detect this to get correct damage effects - CBaseCombatCharacter *pCCEnemy = ( GetEnemy() != NULL ) ? GetEnemy()->MyCombatCharacterPointer() : NULL; - CBaseEntity *pVehicleEntity; - if ( pCCEnemy != NULL && ( pVehicleEntity = pCCEnemy->GetVehicleEntity() ) != NULL ) - { - if ( pVehicleEntity->GetServerVehicle() && dynamic_cast(pVehicleEntity) ) - { - pDriver = static_cast(pVehicleEntity)->GetDriver(); - if ( pDriver && pDriver->IsPlayer() ) - { - iDriverInitialHealth = pDriver->GetHealth(); - } - else - { - pDriver = NULL; - } - } - } - } - - // - // Trace out a cubic section of our hull and see what we hit. - // - Vector vecMins = GetHullMins(); - Vector vecMaxs = GetHullMaxs(); - vecMins.z = vecMins.x; - vecMaxs.z = vecMaxs.x; - - CBaseEntity *pHurt = NULL; - if ( GetEnemy() && GetEnemy()->Classify() == CLASS_BULLSEYE ) - { - // We always hit bullseyes we're targeting - pHurt = GetEnemy(); - CTakeDamageInfo info( this, this, vec3_origin, GetAbsOrigin(), iDamage, DMG_SLASH ); - pHurt->TakeDamage( info ); - } - else - { - // Try to hit them with a trace - pHurt = CheckTraceHullAttack( flDist, vecMins, vecMaxs, iDamage, DMG_SLASH ); - } - - if ( pDriver && iDriverInitialHealth != pDriver->GetHealth() ) - { - pHurt = pDriver; - } - - if ( !pHurt && m_hPhysicsEnt != NULL && IsCurSchedule(SCHED_ZOMBIE_ATTACKITEM) ) - { - pHurt = m_hPhysicsEnt; - - Vector vForce = pHurt->WorldSpaceCenter() - WorldSpaceCenter(); - VectorNormalize( vForce ); - - vForce *= 5 * 24; - - CTakeDamageInfo info( this, this, vForce, GetAbsOrigin(), iDamage, DMG_SLASH ); - pHurt->TakeDamage( info ); - - pHurt = m_hPhysicsEnt; - } - - if ( pHurt ) - { - AttackHitSound(); - - CBasePlayer *pPlayer = ToBasePlayer( pHurt ); - - if ( pPlayer != NULL && !(pPlayer->GetFlags() & FL_GODMODE ) ) - { - pPlayer->ViewPunch( qaViewPunch ); - - pPlayer->VelocityPunch( vecVelocityPunch ); - } - else if( !pPlayer && UTIL_ShouldShowBlood(pHurt->BloodColor()) ) - { - // Hit an NPC. Bleed them! - Vector vecBloodPos; - - switch( BloodOrigin ) - { - case ZOMBIE_BLOOD_LEFT_HAND: - if( GetAttachment( "blood_left", vecBloodPos ) ) - SpawnBlood( vecBloodPos, g_vecAttackDir, pHurt->BloodColor(), MIN( iDamage, 30 ) ); - break; - - case ZOMBIE_BLOOD_RIGHT_HAND: - if( GetAttachment( "blood_right", vecBloodPos ) ) - SpawnBlood( vecBloodPos, g_vecAttackDir, pHurt->BloodColor(), MIN( iDamage, 30 ) ); - break; - - case ZOMBIE_BLOOD_BOTH_HANDS: - if( GetAttachment( "blood_left", vecBloodPos ) ) - SpawnBlood( vecBloodPos, g_vecAttackDir, pHurt->BloodColor(), MIN( iDamage, 30 ) ); - - if( GetAttachment( "blood_right", vecBloodPos ) ) - SpawnBlood( vecBloodPos, g_vecAttackDir, pHurt->BloodColor(), MIN( iDamage, 30 ) ); - break; - - case ZOMBIE_BLOOD_BITE: - // No blood for these. - break; - } - } - } - else - { - AttackMissSound(); - } - - if ( pHurt == m_hPhysicsEnt && IsCurSchedule(SCHED_ZOMBIE_ATTACKITEM) ) - { - m_hPhysicsEnt = NULL; - m_flNextSwat = gpGlobals->curtime + random->RandomFloat( 2, 4 ); - } - - return pHurt; -} - -//----------------------------------------------------------------------------- -// Purpose: The zombie is frustrated and pounding walls/doors. Make an appropriate noise -// Input : -//----------------------------------------------------------------------------- -void CNPC_BaseZombie::PoundSound() -{ - trace_t tr; - Vector forward; - - GetVectors( &forward, NULL, NULL ); - - AI_TraceLine( EyePosition(), EyePosition() + forward * 128, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - - if( tr.fraction == 1.0 ) - { - // Didn't hit anything! - return; - } - - if( tr.fraction < 1.0 && tr.m_pEnt ) - { - const surfacedata_t *psurf = physprops->GetSurfaceData( tr.surface.surfaceProps ); - if( psurf ) - { - EmitSound( physprops->GetString(psurf->sounds.impactHard) ); - return; - } - } - - // Otherwise fall through to the default sound. - CPASAttenuationFilter filter( this,"NPC_BaseZombie.PoundDoor" ); - EmitSound( filter, entindex(),"NPC_BaseZombie.PoundDoor" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Catches the monster-specific events that occur when tagged animation -// frames are played. -// Input : pEvent - -//----------------------------------------------------------------------------- -void CNPC_BaseZombie::HandleAnimEvent( animevent_t *pEvent ) -{ - if ( pEvent->event == AE_NPC_ATTACK_BROADCAST ) - { - if( GetEnemy() && GetEnemy()->IsNPC() ) - { - if( HasCondition(COND_CAN_MELEE_ATTACK1) ) - { - // This animation is sometimes played by code that doesn't intend to attack the enemy - // (For instance, code that makes a zombie take a frustrated swipe at an obstacle). - // Try not to trigger a reaction from our enemy unless we're really attacking. - GetEnemy()->MyNPCPointer()->DispatchInteraction( g_interactionZombieMeleeWarning, NULL, this ); - } - } - return; - } - - if ( pEvent->event == AE_ZOMBIE_POUND ) - { - PoundSound(); - return; - } - - if ( pEvent->event == AE_ZOMBIE_ALERTSOUND ) - { - AlertSound(); - return; - } - - if ( pEvent->event == AE_ZOMBIE_STEP_LEFT ) - { - MakeAIFootstepSound( 180.0f ); - FootstepSound( false ); - return; - } - - if ( pEvent->event == AE_ZOMBIE_STEP_RIGHT ) - { - MakeAIFootstepSound( 180.0f ); - FootstepSound( true ); - return; - } - - if ( pEvent->event == AE_ZOMBIE_GET_UP ) - { - MakeAIFootstepSound( 180.0f, 3.0f ); - if( !IsOnFire() ) - { - // If you let this code run while a zombie is burning, it will stop wailing. - m_flNextMoanSound = gpGlobals->curtime; - MoanSound( envDefaultZombieMoanVolumeFast, ARRAYSIZE( envDefaultZombieMoanVolumeFast ) ); - } - return; - } - - if ( pEvent->event == AE_ZOMBIE_SCUFF_LEFT ) - { - MakeAIFootstepSound( 180.0f ); - FootscuffSound( false ); - return; - } - - if ( pEvent->event == AE_ZOMBIE_SCUFF_RIGHT ) - { - MakeAIFootstepSound( 180.0f ); - FootscuffSound( true ); - return; - } - - // all swat animations are handled as a single case. - if ( pEvent->event == AE_ZOMBIE_STARTSWAT ) - { - MakeAIFootstepSound( 180.0f ); - AttackSound(); - return; - } - - if ( pEvent->event == AE_ZOMBIE_ATTACK_SCREAM ) - { - AttackSound(); - return; - } - - if ( pEvent->event == AE_ZOMBIE_SWATITEM ) - { - CBaseEntity *pEnemy = GetEnemy(); - if ( pEnemy ) - { - Vector v; - CBaseEntity *pPhysicsEntity = m_hPhysicsEnt; - if( !pPhysicsEntity ) - { - DevMsg( "**Zombie: Missing my physics ent!!" ); - return; - } - - IPhysicsObject *pPhysObj = pPhysicsEntity->VPhysicsGetObject(); - - if( !pPhysObj ) - { - DevMsg( "**Zombie: No Physics Object for physics Ent!" ); - return; - } - - EmitSound( "NPC_BaseZombie.Swat" ); - PhysicsImpactSound( pEnemy, pPhysObj, CHAN_BODY, pPhysObj->GetMaterialIndex(), physprops->GetSurfaceIndex("flesh"), 0.5, 800 ); - - Vector physicsCenter = pPhysicsEntity->WorldSpaceCenter(); - v = pEnemy->WorldSpaceCenter() - physicsCenter; - VectorNormalize(v); - - // Send the object at 800 in/sec toward the enemy. Add 200 in/sec up velocity to keep it - // in the air for a second or so. - v = v * 800; - v.z += 200; - - // add some spin so the object doesn't appear to just fly in a straight line - // Also this spin will move the object slightly as it will press on whatever the object - // is resting on. - AngularImpulse angVelocity( random->RandomFloat(-180, 180), 20, random->RandomFloat(-360, 360) ); - - pPhysObj->AddVelocity( &v, &angVelocity ); - - // If we don't put the object scan time well into the future, the zombie - // will re-select the object he just hit as it is flying away from him. - // It will likely always be the nearest object because the zombie moved - // close enough to it to hit it. - m_hPhysicsEnt = NULL; - - m_flNextSwatScan = gpGlobals->curtime + ZOMBIE_SWAT_DELAY; - - return; - } - } - - if ( pEvent->event == AE_ZOMBIE_ATTACK_RIGHT ) - { - QAngle viewPunch = QAngle(-15.0f, -20.0f, -10.0f); - Vector right, forward, velocityPunch; - AngleVectors( GetLocalAngles(), &forward, &right, NULL ); - - right = right * 100; - forward = forward * 200; - velocityPunch = right + forward; - - ClawAttack( GetClawAttackRange(), sk_zombie_dmg_one_slash.GetInt(), viewPunch, velocityPunch, ZOMBIE_BLOOD_RIGHT_HAND ); - return; - } - - if ( pEvent->event == AE_ZOMBIE_ATTACK_LEFT ) - { - QAngle viewPunch = QAngle(-15.0f, -20.0f, -10.0f); - Vector right, forward, velocityPunch; - AngleVectors( GetLocalAngles(), &forward, &right, NULL ); - - right = right * -100; - forward = forward * 200; - velocityPunch = right + forward; - - ClawAttack( GetClawAttackRange(), sk_zombie_dmg_one_slash.GetInt(), viewPunch, velocityPunch, ZOMBIE_BLOOD_LEFT_HAND ); - return; - } - - if ( pEvent->event == AE_ZOMBIE_ATTACK_BOTH ) - { - Vector forward; - QAngle qaPunch( 45, random->RandomInt(-5,5), random->RandomInt(-5,5) ); - AngleVectors( GetLocalAngles(), &forward ); - forward = forward * 200; - ClawAttack( GetClawAttackRange(), sk_zombie_dmg_one_slash.GetInt(), qaPunch, forward, ZOMBIE_BLOOD_BOTH_HANDS ); - return; - } - - if ( pEvent->event == AE_ZOMBIE_POPHEADCRAB ) - { - if ( GetInteractionPartner() == NULL ) - return; - - const char *pString = pEvent->options; - char token[128]; - pString = nexttoken( token, pString, ' ' ); - - int boneIndex = GetInteractionPartner()->LookupBone( token ); - - if ( boneIndex == -1 ) - { - Warning( "AE_ZOMBIE_POPHEADCRAB event using invalid bone name! Usage: event AE_ZOMBIE_POPHEADCRAB \" \" \n" ); - return; - } - - pString = nexttoken( token, pString, ' ' ); - - if ( token == '\0' ) - { - Warning( "AE_ZOMBIE_POPHEADCRAB event format missing velocity parameter! Usage: event AE_ZOMBIE_POPHEADCRAB \" \" \n" ); - return; - } - - Vector vecBonePosition; - QAngle angles; - Vector vecHeadCrabPosition; - - int iCrabAttachment = LookupAttachment( "headcrab" ); - int iSpeed = atoi( token ); - - GetInteractionPartner()->GetBonePosition( boneIndex, vecBonePosition, angles ); - GetAttachment( iCrabAttachment, vecHeadCrabPosition ); - - Vector vVelocity = vecHeadCrabPosition - vecBonePosition; - VectorNormalize( vVelocity ); - - CTakeDamageInfo dmgInfo( this, GetInteractionPartner(), m_iHealth, DMG_DIRECT ); - - dmgInfo.SetDamagePosition( vecHeadCrabPosition ); - - ReleaseHeadcrab( EyePosition(), vVelocity * iSpeed, true, false, true ); - - GuessDamageForce( &dmgInfo, vVelocity, vecHeadCrabPosition, 0.5f ); - TakeDamage( dmgInfo ); - return; - } - - BaseClass::HandleAnimEvent( pEvent ); -} - -//----------------------------------------------------------------------------- -// Purpose: Spawn function for the base zombie. -// -// !!!IMPORTANT!!! YOUR DERIVED CLASS'S SPAWN() RESPONSIBILITIES: -// -// Call Precache(); -// Set status for m_fIsTorso & m_fIsHeadless -// Set blood color -// Set health -// Set field of view -// Call CapabilitiesClear() & then set relevant capabilities -// THEN Call BaseClass::Spawn() -//----------------------------------------------------------------------------- -void CNPC_BaseZombie::Spawn( void ) -{ - SetSolid( SOLID_BBOX ); - SetMoveType( MOVETYPE_STEP ); - -#ifdef _XBOX - // Always fade the corpse - AddSpawnFlags( SF_NPC_FADE_CORPSE ); -#endif // _XBOX - - m_NPCState = NPC_STATE_NONE; - - CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_INNATE_MELEE_ATTACK1 ); - CapabilitiesAdd( bits_CAP_SQUAD ); - - m_flNextSwat = gpGlobals->curtime; - m_flNextSwatScan = gpGlobals->curtime; - m_pMoanSound = NULL; - - m_flNextMoanSound = gpGlobals->curtime + 9999; - - SetZombieModel(); - - NPCInit(); - - m_bIsSlumped = false; - - // Zombies get to cheat for 6 seconds (sjb) - GetEnemies()->SetFreeKnowledgeDuration( 6.0 ); - - m_ActBusyBehavior.SetUseRenderBounds(true); -} - - -//----------------------------------------------------------------------------- -// Purpose: Pecaches all resources this NPC needs. -//----------------------------------------------------------------------------- -void CNPC_BaseZombie::Precache( void ) -{ - UTIL_PrecacheOther( GetHeadcrabClassname() ); - - PrecacheScriptSound( "E3_Phystown.Slicer" ); - PrecacheScriptSound( "NPC_BaseZombie.PoundDoor" ); - PrecacheScriptSound( "NPC_BaseZombie.Swat" ); - - PrecacheModel( GetLegsModel() ); - PrecacheModel( GetTorsoModel() ); - - PrecacheParticleSystem( "blood_impact_zombie_01" ); - - BaseClass::Precache(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_BaseZombie::StartTouch( CBaseEntity *pOther ) -{ - BaseClass::StartTouch( pOther ); - - if( IsSlumped() && hl2_episodic.GetBool() ) - { - if( FClassnameIs( pOther, "prop_physics" ) ) - { - // Get up! - m_ActBusyBehavior.StopBusying(); - } - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_BaseZombie::CreateBehaviors() -{ - AddBehavior( &m_ActBusyBehavior ); - - return BaseClass::CreateBehaviors(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CNPC_BaseZombie::TranslateSchedule( int scheduleType ) -{ - switch( scheduleType ) - { - case SCHED_CHASE_ENEMY: - if ( HasCondition( COND_ZOMBIE_LOCAL_MELEE_OBSTRUCTION ) && !HasCondition(COND_TASK_FAILED) && IsCurSchedule( SCHED_ZOMBIE_CHASE_ENEMY, false ) ) - { - return SCHED_COMBAT_PATROL; - } - return SCHED_ZOMBIE_CHASE_ENEMY; - break; - - case SCHED_ZOMBIE_SWATITEM: - // If the object is far away, move and swat it. If it's close, just swat it. - if( DistToPhysicsEnt() > ZOMBIE_PHYSOBJ_SWATDIST ) - { - return SCHED_ZOMBIE_MOVE_SWATITEM; - } - else - { - return SCHED_ZOMBIE_SWATITEM; - } - break; - - case SCHED_STANDOFF: - return SCHED_ZOMBIE_WANDER_STANDOFF; - - case SCHED_MELEE_ATTACK1: - return SCHED_ZOMBIE_MELEE_ATTACK1; - } - - return BaseClass::TranslateSchedule( scheduleType ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Allows for modification of the interrupt mask for the current schedule. -// In the most cases the base implementation should be called first. -//----------------------------------------------------------------------------- -void CNPC_BaseZombie::BuildScheduleTestBits( void ) -{ - // Ignore damage if we were recently damaged or we're attacking. - if ( GetActivity() == ACT_MELEE_ATTACK1 ) - { - ClearCustomInterruptCondition( COND_LIGHT_DAMAGE ); - ClearCustomInterruptCondition( COND_HEAVY_DAMAGE ); - } -#ifndef HL2_EPISODIC - else if ( m_flNextFlinch >= gpGlobals->curtime ) - { - ClearCustomInterruptCondition( COND_LIGHT_DAMAGE ); - ClearCustomInterruptCondition( COND_HEAVY_DAMAGE ); - } -#endif // !HL2_EPISODIC - - // Everything should be interrupted if we get killed. - SetCustomInterruptCondition( COND_ZOMBIE_RELEASECRAB ); - - BaseClass::BuildScheduleTestBits(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Called when we change schedules. -//----------------------------------------------------------------------------- -void CNPC_BaseZombie::OnScheduleChange( void ) -{ - // - // If we took damage and changed schedules, ignore further damage for a few seconds. - // - if ( HasCondition( COND_LIGHT_DAMAGE ) || HasCondition( COND_HEAVY_DAMAGE )) - { - m_flNextFlinch = gpGlobals->curtime + ZOMBIE_FLINCH_DELAY; - } - - BaseClass::OnScheduleChange(); -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CNPC_BaseZombie::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ) -{ - if( failedSchedule == SCHED_ZOMBIE_WANDER_MEDIUM ) - { - return SCHED_ZOMBIE_WANDER_FAIL; - } - - // If we can swat physics objects, see if we can swat our obstructor - if ( CanSwatPhysicsObjects() ) - { - if ( !m_fIsTorso && IsPathTaskFailure( taskFailCode ) && - m_hObstructor != NULL && m_hObstructor->VPhysicsGetObject() && - m_hObstructor->VPhysicsGetObject()->GetMass() < 100 ) - { - m_hPhysicsEnt = m_hObstructor; - m_hObstructor = NULL; - return SCHED_ZOMBIE_ATTACKITEM; - } - } - - m_hObstructor = NULL; - - return BaseClass::SelectFailSchedule( failedSchedule, failedTask, taskFailCode ); -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CNPC_BaseZombie::SelectSchedule ( void ) -{ - if ( HasCondition( COND_ZOMBIE_RELEASECRAB ) ) - { - // Death waits for no man. Or zombie. Or something. - return SCHED_ZOMBIE_RELEASECRAB; - } - - if ( BehaviorSelectSchedule() ) - { - return BaseClass::SelectSchedule(); - } - - switch ( m_NPCState ) - { - case NPC_STATE_COMBAT: - if ( HasCondition( COND_NEW_ENEMY ) && GetEnemy() ) - { - float flDist; - - flDist = ( GetLocalOrigin() - GetEnemy()->GetLocalOrigin() ).Length(); - - // If this is a new enemy that's far away, ambush!! - if (flDist >= zombie_ambushdist.GetFloat() && MustCloseToAttack() ) - { - return SCHED_ZOMBIE_MOVE_TO_AMBUSH; - } - } - - if ( HasCondition( COND_LOST_ENEMY ) || ( HasCondition( COND_ENEMY_UNREACHABLE ) && MustCloseToAttack() ) ) - { - return SCHED_ZOMBIE_WANDER_MEDIUM; - } - - if( HasCondition( COND_ZOMBIE_CAN_SWAT_ATTACK ) ) - { - return SCHED_ZOMBIE_SWATITEM; - } - break; - - case NPC_STATE_ALERT: - if ( HasCondition( COND_LOST_ENEMY ) || HasCondition( COND_ENEMY_DEAD ) || ( HasCondition( COND_ENEMY_UNREACHABLE ) && MustCloseToAttack() ) ) - { - ClearCondition( COND_LOST_ENEMY ); - ClearCondition( COND_ENEMY_UNREACHABLE ); - -#ifdef DEBUG_ZOMBIES - DevMsg("Wandering\n"); -#endif - - // Just lost track of our enemy. - // Wander around a bit so we don't look like a dingus. - return SCHED_ZOMBIE_WANDER_MEDIUM; - } - break; - - default: - break; - } - - return BaseClass::SelectSchedule(); -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_BaseZombie::IsSlumped( void ) -{ - if( hl2_episodic.GetBool() ) - { - if( m_ActBusyBehavior.IsInsideActBusy() && !m_ActBusyBehavior.IsStopBusying() ) - { - return true; - } - } - else - { - int sequence = GetSequence(); - if ( sequence != -1 ) - { - return ( strncmp( GetSequenceName( sequence ), "slump", 5 ) == 0 ); - } - } - - return false; -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_BaseZombie::IsGettingUp( void ) -{ - if( m_ActBusyBehavior.IsActive() && m_ActBusyBehavior.IsStopBusying() ) - { - return true; - } - return false; -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CNPC_BaseZombie::GetSwatActivity( void ) -{ - // Hafta figure out whether to swat with left or right arm. - // Also hafta figure out whether to swat high or low. (later) - float flDot; - Vector vecRight, vecDirToObj; - - AngleVectors( GetLocalAngles(), NULL, &vecRight, NULL ); - - vecDirToObj = m_hPhysicsEnt->GetLocalOrigin() - GetLocalOrigin(); - VectorNormalize(vecDirToObj); - - // compare in 2D. - vecRight.z = 0.0; - vecDirToObj.z = 0.0; - - flDot = DotProduct( vecRight, vecDirToObj ); - - Vector vecMyCenter; - Vector vecObjCenter; - - vecMyCenter = WorldSpaceCenter(); - vecObjCenter = m_hPhysicsEnt->WorldSpaceCenter(); - float flZDiff; - - flZDiff = vecMyCenter.z - vecObjCenter.z; - - if( flDot >= 0 ) - { - // Right - if( flZDiff < 0 ) - { - return ACT_ZOM_SWATRIGHTMID; - } - - return ACT_ZOM_SWATRIGHTLOW; - } - else - { - // Left - if( flZDiff < 0 ) - { - return ACT_ZOM_SWATLEFTMID; - } - - return ACT_ZOM_SWATLEFTLOW; - } -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_BaseZombie::GatherConditions( void ) -{ - ClearCondition( COND_ZOMBIE_LOCAL_MELEE_OBSTRUCTION ); - - BaseClass::GatherConditions(); - - if( m_NPCState == NPC_STATE_COMBAT && !m_fIsTorso ) - { - // This check for !m_pPhysicsEnt prevents a crashing bug, but also - // eliminates the zombie picking a better physics object if one happens to fall - // between him and the object he's heading for already. - if( gpGlobals->curtime >= m_flNextSwatScan && (m_hPhysicsEnt == NULL) ) - { - FindNearestPhysicsObject( ZOMBIE_MAX_PHYSOBJ_MASS ); - m_flNextSwatScan = gpGlobals->curtime + 2.0; - } - } - - if( (m_hPhysicsEnt != NULL) && gpGlobals->curtime >= m_flNextSwat && HasCondition( COND_SEE_ENEMY ) && !HasCondition( COND_ZOMBIE_RELEASECRAB ) ) - { - SetCondition( COND_ZOMBIE_CAN_SWAT_ATTACK ); - } - else - { - ClearCondition( COND_ZOMBIE_CAN_SWAT_ATTACK ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_BaseZombie::PrescheduleThink( void ) -{ - BaseClass::PrescheduleThink(); - -#if 0 - DevMsg(" ** %d Angry Zombies **\n", s_iAngryZombies ); -#endif - -#if 0 - if( m_NPCState == NPC_STATE_COMBAT ) - { - // Zombies should make idle sounds in combat - if( random->RandomInt( 0, 30 ) == 0 ) - { - IdleSound(); - } - } -#endif - - // - // Cool off if we aren't burned for five seconds or so. - // - if ( ( m_flBurnDamageResetTime ) && ( gpGlobals->curtime >= m_flBurnDamageResetTime ) ) - { - m_flBurnDamage = 0; - } -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_BaseZombie::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_ZOMBIE_DIE: - // Go to ragdoll - KillMe(); - TaskComplete(); - break; - - case TASK_ZOMBIE_GET_PATH_TO_PHYSOBJ: - { - Vector vecGoalPos; - Vector vecDir; - - vecDir = GetLocalOrigin() - m_hPhysicsEnt->GetLocalOrigin(); - VectorNormalize(vecDir); - vecDir.z = 0; - - AI_NavGoal_t goal( m_hPhysicsEnt->WorldSpaceCenter() ); - goal.pTarget = m_hPhysicsEnt; - GetNavigator()->SetGoal( goal ); - - TaskComplete(); - } - break; - - case TASK_ZOMBIE_SWAT_ITEM: - { - if( m_hPhysicsEnt == NULL ) - { - // Physics Object is gone! Probably was an explosive - // or something else broke it. - TaskFail("Physics ent NULL"); - } - else if ( DistToPhysicsEnt() > ZOMBIE_PHYSOBJ_SWATDIST ) - { - // Physics ent is no longer in range! Probably another zombie swatted it or it moved - // for some other reason. - TaskFail( "Physics swat item has moved" ); - } - else - { - SetIdealActivity( (Activity)GetSwatActivity() ); - } - break; - } - break; - - case TASK_ZOMBIE_DELAY_SWAT: - m_flNextSwat = gpGlobals->curtime + pTask->flTaskData; - TaskComplete(); - break; - - case TASK_ZOMBIE_RELEASE_HEADCRAB: - { - // make the crab look like it's pushing off the body - Vector vecForward; - Vector vecVelocity; - - AngleVectors( GetAbsAngles(), &vecForward ); - - vecVelocity = vecForward * 30; - vecVelocity.z += 100; - - ReleaseHeadcrab( EyePosition(), vecVelocity, true, true ); - TaskComplete(); - } - break; - - case TASK_ZOMBIE_WAIT_POST_MELEE: - { -#ifndef HL2_EPISODIC - TaskComplete(); - return; -#endif - - // Don't wait when attacking the player - if ( GetEnemy() && GetEnemy()->IsPlayer() ) - { - TaskComplete(); - return; - } - - // Wait a single think - SetWait( 0.1 ); - } - break; - - default: - BaseClass::StartTask( pTask ); - } -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_BaseZombie::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_ZOMBIE_SWAT_ITEM: - if( IsActivityFinished() ) - { - TaskComplete(); - } - break; - - case TASK_ZOMBIE_WAIT_POST_MELEE: - { - if ( IsWaitFinished() ) - { - TaskComplete(); - } - } - break; - default: - BaseClass::RunTask( pTask ); - break; - } -} - - -//--------------------------------------------------------- -// Make the necessary changes to a zombie to make him a -// torso! -//--------------------------------------------------------- -void CNPC_BaseZombie::BecomeTorso( const Vector &vecTorsoForce, const Vector &vecLegsForce ) -{ - if( m_fIsTorso ) - { - DevMsg( "*** Zombie is already a torso!\n" ); - return; - } - - if( IsOnFire() ) - { - Extinguish(); - Ignite( 30 ); - } - - if ( !m_fIsHeadless ) - { - m_iMaxHealth = ZOMBIE_TORSO_HEALTH_FACTOR * m_iMaxHealth; - m_iHealth = m_iMaxHealth; - - // No more opening doors! - CapabilitiesRemove( bits_CAP_DOORS_GROUP ); - - ClearSchedule( "Becoming torso" ); - GetNavigator()->ClearGoal(); - m_hPhysicsEnt = NULL; - - // Put the zombie in a TOSS / fall schedule - // Otherwise he fails and sits on the ground for a sec. - SetSchedule( SCHED_FALL_TO_GROUND ); - - m_fIsTorso = true; - - // Put the torso up where the torso was when the zombie - // was whole. - Vector origin = GetAbsOrigin(); - origin.z += 40; - SetAbsOrigin( origin ); - - SetGroundEntity( NULL ); - // assume zombie mass ~ 100 kg - ApplyAbsVelocityImpulse( vecTorsoForce * (1.0 / 100.0) ); - } - - float flFadeTime = 0.0; - - if( HasSpawnFlags( SF_NPC_FADE_CORPSE ) ) - { - flFadeTime = 5.0; - } - - if ( m_fIsTorso == true ) - { - // -40 on Z to make up for the +40 on Z that we did above. This stops legs spawning above the head. - CBaseEntity *pGib = CreateRagGib( GetLegsModel(), GetAbsOrigin() - Vector(0, 0, 40), GetAbsAngles(), vecLegsForce, flFadeTime ); - - // don't collide with this thing ever - if ( pGib ) - { - pGib->SetOwnerEntity( this ); - } - } - - - SetZombieModel(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_BaseZombie::Event_Killed( const CTakeDamageInfo &info ) -{ - if ( info.GetDamageType() & DMG_VEHICLE ) - { - Vector vecDamageDir = info.GetDamageForce(); - VectorNormalize( vecDamageDir ); - - // Big blood splat - UTIL_BloodSpray( WorldSpaceCenter(), vecDamageDir, BLOOD_COLOR_YELLOW, 8, FX_BLOODSPRAY_CLOUD ); - } - - BaseClass::Event_Killed( info ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_BaseZombie::BecomeRagdoll( const CTakeDamageInfo &info, const Vector &forceVector ) -{ - bool bKilledByVehicle = ( ( info.GetDamageType() & DMG_VEHICLE ) != 0 ); - if( m_fIsTorso || (!IsChopped(info) && !IsSquashed(info)) || bKilledByVehicle ) - { - return BaseClass::BecomeRagdoll( info, forceVector ); - } - - if( !(GetFlags()&FL_TRANSRAGDOLL) ) - { - RemoveDeferred(); - } - - return true; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_BaseZombie::StopLoopingSounds() -{ - ENVELOPE_CONTROLLER.SoundDestroy( m_pMoanSound ); - m_pMoanSound = NULL; - - BaseClass::StopLoopingSounds(); -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_BaseZombie::RemoveHead( void ) -{ - m_fIsHeadless = true; - SetZombieModel(); -} - - -bool CNPC_BaseZombie::ShouldPlayFootstepMoan( void ) -{ - if( random->RandomInt( 1, zombie_stepfreq.GetInt() * s_iAngryZombies ) == 1 ) - { - return true; - } - - return false; -} - - -#define ZOMBIE_CRAB_INHERITED_SPAWNFLAGS (SF_NPC_GAG|SF_NPC_LONG_RANGE|SF_NPC_FADE_CORPSE|SF_NPC_ALWAYSTHINK) -#define CRAB_HULL_EXPAND 1.1f -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_BaseZombie::HeadcrabFits( CBaseAnimating *pCrab ) -{ - Vector vecSpawnLoc = pCrab->GetAbsOrigin(); - - CTraceFilterSimpleList traceFilter( COLLISION_GROUP_NONE ); - traceFilter.AddEntityToIgnore( pCrab ); - traceFilter.AddEntityToIgnore( this ); - if ( GetInteractionPartner() ) - { - traceFilter.AddEntityToIgnore( GetInteractionPartner() ); - } - - trace_t tr; - AI_TraceHull( vecSpawnLoc, - vecSpawnLoc - Vector( 0, 0, 1 ), - NAI_Hull::Mins(HULL_TINY) * CRAB_HULL_EXPAND, - NAI_Hull::Maxs(HULL_TINY) * CRAB_HULL_EXPAND, - MASK_NPCSOLID, - &traceFilter, - &tr ); - - if( tr.fraction != 1.0 ) - { - //NDebugOverlay::Box( vecSpawnLoc, NAI_Hull::Mins(HULL_TINY) * CRAB_HULL_EXPAND, NAI_Hull::Maxs(HULL_TINY) * CRAB_HULL_EXPAND, 255, 0, 0, 100, 10.0 ); - return false; - } - - //NDebugOverlay::Box( vecSpawnLoc, NAI_Hull::Mins(HULL_TINY) * CRAB_HULL_EXPAND, NAI_Hull::Maxs(HULL_TINY) * CRAB_HULL_EXPAND, 0, 255, 0, 100, 10.0 ); - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &vecOrigin - -// &vecVelocity - -// fRemoveHead - -// fRagdollBody - -//----------------------------------------------------------------------------- -void CNPC_BaseZombie::ReleaseHeadcrab( const Vector &vecOrigin, const Vector &vecVelocity, bool fRemoveHead, bool fRagdollBody, bool fRagdollCrab ) -{ - CAI_BaseNPC *pCrab; - Vector vecSpot = vecOrigin; - - // Until the headcrab is a bodygroup, we have to approximate the - // location of the head with magic numbers. - if( !m_fIsTorso ) - { - vecSpot.z -= 16; - } - - if( fRagdollCrab ) - { - //Vector vecForce = Vector( 0, 0, random->RandomFloat( 700, 1100 ) ); - CBaseEntity *pGib = CreateRagGib( GetHeadcrabModel(), vecOrigin, GetLocalAngles(), vecVelocity, 15, ShouldIgniteZombieGib() ); - - if ( pGib ) - { - CBaseAnimating *pAnimatingGib = dynamic_cast(pGib); - - // don't collide with this thing ever - int iCrabAttachment = LookupAttachment( "headcrab" ); - if (iCrabAttachment > 0 && pAnimatingGib ) - { - SetHeadcrabSpawnLocation( iCrabAttachment, pAnimatingGib ); - } - - if( !HeadcrabFits(pAnimatingGib) ) - { - UTIL_Remove(pGib); - return; - } - - pGib->SetOwnerEntity( this ); - CopyRenderColorTo( pGib ); - - - if( UTIL_ShouldShowBlood(BLOOD_COLOR_YELLOW) ) - { - UTIL_BloodImpact( pGib->WorldSpaceCenter(), Vector(0,0,1), BLOOD_COLOR_YELLOW, 1 ); - - for ( int i = 0 ; i < 3 ; i++ ) - { - Vector vecSpot = pGib->WorldSpaceCenter(); - - vecSpot.x += random->RandomFloat( -8, 8 ); - vecSpot.y += random->RandomFloat( -8, 8 ); - vecSpot.z += random->RandomFloat( -8, 8 ); - - UTIL_BloodDrips( vecSpot, vec3_origin, BLOOD_COLOR_YELLOW, 50 ); - } - } - } - } - else - { - pCrab = (CAI_BaseNPC*)CreateEntityByName( GetHeadcrabClassname() ); - - if ( !pCrab ) - { - Warning( "**%s: Can't make %s!\n", GetClassname(), GetHeadcrabClassname() ); - return; - } - - // Stick the crab in whatever squad the zombie was in. - pCrab->SetSquadName( m_SquadName ); - - // don't pop to floor, fall - pCrab->AddSpawnFlags( SF_NPC_FALL_TO_GROUND ); - - // add on the parent flags - pCrab->AddSpawnFlags( m_spawnflags & ZOMBIE_CRAB_INHERITED_SPAWNFLAGS ); - - // make me the crab's owner to avoid collision issues - pCrab->SetOwnerEntity( this ); - - pCrab->SetAbsOrigin( vecSpot ); - pCrab->SetAbsAngles( GetAbsAngles() ); - DispatchSpawn( pCrab ); - - pCrab->GetMotor()->SetIdealYaw( GetAbsAngles().y ); - - // FIXME: npc's with multiple headcrabs will need some way to query different attachments. - // NOTE: this has till after spawn is called so that the model is set up - int iCrabAttachment = LookupAttachment( "headcrab" ); - if (iCrabAttachment > 0) - { - SetHeadcrabSpawnLocation( iCrabAttachment, pCrab ); - pCrab->GetMotor()->SetIdealYaw( pCrab->GetAbsAngles().y ); - - // Take out any pitch - QAngle angles = pCrab->GetAbsAngles(); - angles.x = 0.0; - pCrab->SetAbsAngles( angles ); - } - - if( !HeadcrabFits(pCrab) ) - { - UTIL_Remove(pCrab); - return; - } - - pCrab->SetActivity( ACT_IDLE ); - pCrab->SetNextThink( gpGlobals->curtime ); - pCrab->PhysicsSimulate(); - pCrab->SetAbsVelocity( vecVelocity ); - - // if I have an enemy, stuff that to the headcrab. - CBaseEntity *pEnemy; - pEnemy = GetEnemy(); - - pCrab->m_flNextAttack = gpGlobals->curtime + 1.0f; - - if( pEnemy ) - { - pCrab->SetEnemy( pEnemy ); - } - if( ShouldIgniteZombieGib() ) - { - pCrab->Ignite( 30 ); - } - - CopyRenderColorTo( pCrab ); - - pCrab->Activate(); - } - - if( fRemoveHead ) - { - RemoveHead(); - } - - if( fRagdollBody ) - { - BecomeRagdollOnClient( vec3_origin ); - } -} - - - -void CNPC_BaseZombie::SetHeadcrabSpawnLocation( int iCrabAttachment, CBaseAnimating *pCrab ) -{ - Assert( iCrabAttachment > 0 ); - - // get world location of intended headcrab root bone - matrix3x4_t attachmentToWorld; - GetAttachment( iCrabAttachment, attachmentToWorld ); - - // find offset of root bone from origin - pCrab->SetAbsOrigin( Vector( 0, 0, 0 ) ); - pCrab->SetAbsAngles( QAngle( 0, 0, 0 ) ); - pCrab->InvalidateBoneCache(); - matrix3x4_t rootLocal; - pCrab->GetBoneTransform( 0, rootLocal ); - - // invert it - matrix3x4_t rootInvLocal; - MatrixInvert( rootLocal, rootInvLocal ); - - // find spawn location needed for rootLocal transform to match attachmentToWorld - matrix3x4_t spawnOrigin; - ConcatTransforms( attachmentToWorld, rootInvLocal, spawnOrigin ); - - // reset location of headcrab - Vector vecOrigin; - QAngle vecAngles; - MatrixAngles( spawnOrigin, vecAngles, vecOrigin ); - pCrab->SetAbsOrigin( vecOrigin ); - - // FIXME: head crabs don't like pitch or roll! - vecAngles.z = 0; - - pCrab->SetAbsAngles( vecAngles ); - pCrab->InvalidateBoneCache(); -} - - - -//--------------------------------------------------------- -// Provides a standard way for the zombie to get the -// distance to a physics ent. Since the code to find physics -// objects uses a fast dis approx, we have to use that here -// as well. -//--------------------------------------------------------- -float CNPC_BaseZombie::DistToPhysicsEnt( void ) -{ - //return ( GetLocalOrigin() - m_hPhysicsEnt->GetLocalOrigin() ).Length(); - if ( m_hPhysicsEnt != NULL ) - return UTIL_DistApprox2D( GetAbsOrigin(), m_hPhysicsEnt->WorldSpaceCenter() ); - return ZOMBIE_PHYSOBJ_SWATDIST + 1; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_BaseZombie::OnStateChange( NPC_STATE OldState, NPC_STATE NewState ) -{ - switch( NewState ) - { - case NPC_STATE_COMBAT: - { - RemoveSpawnFlags( SF_NPC_GAG ); - s_iAngryZombies++; - } - break; - - default: - if( OldState == NPC_STATE_COMBAT ) - { - // Only decrement if coming OUT of combat state. - s_iAngryZombies--; - } - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Refines a base activity into something more specific to our internal state. -//----------------------------------------------------------------------------- -Activity CNPC_BaseZombie::NPC_TranslateActivity( Activity baseAct ) -{ - if ( baseAct == ACT_WALK && IsCurSchedule( SCHED_COMBAT_PATROL, false) ) - baseAct = ACT_RUN; - - if ( IsOnFire() ) - { - switch ( baseAct ) - { - case ACT_RUN_ON_FIRE: - { - return ( Activity )ACT_WALK_ON_FIRE; - } - - case ACT_WALK: - { - // I'm on fire. Put ME out. - return ( Activity )ACT_WALK_ON_FIRE; - } - - case ACT_IDLE: - { - // I'm on fire. Put ME out. - return ( Activity )ACT_IDLE_ON_FIRE; - } - - default: - break; - } - } - - return BaseClass::NPC_TranslateActivity( baseAct ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Vector CNPC_BaseZombie::BodyTarget( const Vector &posSrc, bool bNoisy ) -{ - - if( IsCurSchedule(SCHED_BIG_FLINCH) || m_ActBusyBehavior.IsActive() ) - { - // This zombie is assumed to be standing up. - // Return a position that's centered over the absorigin, - // halfway between the origin and the head. - Vector vecTarget = GetAbsOrigin(); - Vector vecHead = HeadTarget( posSrc ); - vecTarget.z = ((vecTarget.z + vecHead.z) * 0.5f); - return vecTarget; - } - - return BaseClass::BodyTarget( posSrc, bNoisy ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Vector CNPC_BaseZombie::HeadTarget( const Vector &posSrc ) -{ - int iCrabAttachment = LookupAttachment( "headcrab" ); - Assert( iCrabAttachment > 0 ); - - Vector vecPosition; - - GetAttachment( iCrabAttachment, vecPosition ); - - return vecPosition; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -float CNPC_BaseZombie::GetAutoAimRadius() -{ - if( m_fIsTorso ) - { - return 12.0f; - } - - return BaseClass::GetAutoAimRadius(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_BaseZombie::OnInsufficientStopDist( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) -{ - if ( pMoveGoal->directTrace.fStatus == AIMR_BLOCKED_ENTITY && gpGlobals->curtime >= m_flNextSwat ) - { - m_hObstructor = pMoveGoal->directTrace.pObstruction; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEnemy - -// &chasePosition - -//----------------------------------------------------------------------------- -void CNPC_BaseZombie::TranslateNavGoal( CBaseEntity *pEnemy, Vector &chasePosition ) -{ - // If our enemy is in a vehicle, we need them to tell us where to navigate to them - if ( pEnemy == NULL ) - return; - - CBaseCombatCharacter *pBCC = pEnemy->MyCombatCharacterPointer(); - if ( pBCC && pBCC->IsInAVehicle() ) - { - Vector vecForward, vecRight; - pBCC->GetVectors( &vecForward, &vecRight, NULL ); - - chasePosition = pBCC->WorldSpaceCenter() + ( vecForward * 24.0f ) + ( vecRight * 48.0f ); - return; - } - - BaseClass::TranslateNavGoal( pEnemy, chasePosition ); -} - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC( base_zombie, CNPC_BaseZombie ) - - DECLARE_TASK( TASK_ZOMBIE_DELAY_SWAT ) - DECLARE_TASK( TASK_ZOMBIE_SWAT_ITEM ) - DECLARE_TASK( TASK_ZOMBIE_GET_PATH_TO_PHYSOBJ ) - DECLARE_TASK( TASK_ZOMBIE_DIE ) - DECLARE_TASK( TASK_ZOMBIE_RELEASE_HEADCRAB ) - DECLARE_TASK( TASK_ZOMBIE_WAIT_POST_MELEE ) - - DECLARE_ACTIVITY( ACT_ZOM_SWATLEFTMID ) - DECLARE_ACTIVITY( ACT_ZOM_SWATRIGHTMID ) - DECLARE_ACTIVITY( ACT_ZOM_SWATLEFTLOW ) - DECLARE_ACTIVITY( ACT_ZOM_SWATRIGHTLOW ) - DECLARE_ACTIVITY( ACT_ZOM_RELEASECRAB ) - DECLARE_ACTIVITY( ACT_ZOM_FALL ) - - DECLARE_CONDITION( COND_ZOMBIE_CAN_SWAT_ATTACK ) - DECLARE_CONDITION( COND_ZOMBIE_RELEASECRAB ) - DECLARE_CONDITION( COND_ZOMBIE_LOCAL_MELEE_OBSTRUCTION ) - - //Adrian: events go here - DECLARE_ANIMEVENT( AE_ZOMBIE_ATTACK_RIGHT ) - DECLARE_ANIMEVENT( AE_ZOMBIE_ATTACK_LEFT ) - DECLARE_ANIMEVENT( AE_ZOMBIE_ATTACK_BOTH ) - DECLARE_ANIMEVENT( AE_ZOMBIE_SWATITEM ) - DECLARE_ANIMEVENT( AE_ZOMBIE_STARTSWAT ) - DECLARE_ANIMEVENT( AE_ZOMBIE_STEP_LEFT ) - DECLARE_ANIMEVENT( AE_ZOMBIE_STEP_RIGHT ) - DECLARE_ANIMEVENT( AE_ZOMBIE_SCUFF_LEFT ) - DECLARE_ANIMEVENT( AE_ZOMBIE_SCUFF_RIGHT ) - DECLARE_ANIMEVENT( AE_ZOMBIE_ATTACK_SCREAM ) - DECLARE_ANIMEVENT( AE_ZOMBIE_GET_UP ) - DECLARE_ANIMEVENT( AE_ZOMBIE_POUND ) - DECLARE_ANIMEVENT( AE_ZOMBIE_ALERTSOUND ) - DECLARE_ANIMEVENT( AE_ZOMBIE_POPHEADCRAB ) - - DECLARE_INTERACTION( g_interactionZombieMeleeWarning ) - - DEFINE_SCHEDULE - ( - SCHED_ZOMBIE_MOVE_SWATITEM, - - " Tasks" - " TASK_ZOMBIE_DELAY_SWAT 3" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY" - " TASK_ZOMBIE_GET_PATH_TO_PHYSOBJ 0" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_FACE_ENEMY 0" - " TASK_ZOMBIE_SWAT_ITEM 0" - " " - " Interrupts" - " COND_ZOMBIE_RELEASECRAB" - " COND_ENEMY_DEAD" - " COND_NEW_ENEMY" - ) - - //========================================================= - // SwatItem - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_ZOMBIE_SWATITEM, - - " Tasks" - " TASK_ZOMBIE_DELAY_SWAT 3" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY" - " TASK_FACE_ENEMY 0" - " TASK_ZOMBIE_SWAT_ITEM 0" - " " - " Interrupts" - " COND_ZOMBIE_RELEASECRAB" - " COND_ENEMY_DEAD" - " COND_NEW_ENEMY" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_ZOMBIE_ATTACKITEM, - - " Tasks" - " TASK_FACE_ENEMY 0" - " TASK_MELEE_ATTACK1 0" - " " - " Interrupts" - " COND_ZOMBIE_RELEASECRAB" - " COND_ENEMY_DEAD" - " COND_NEW_ENEMY" - ) - - //========================================================= - // ChaseEnemy - //========================================================= -#ifdef HL2_EPISODIC - DEFINE_SCHEDULE - ( - SCHED_ZOMBIE_CHASE_ENEMY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY_FAILED" - " TASK_SET_TOLERANCE_DISTANCE 24" - " TASK_GET_CHASE_PATH_TO_ENEMY 600" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_FACE_ENEMY 0" - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_ENEMY_UNREACHABLE" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK2" - " COND_TOO_CLOSE_TO_ATTACK" - " COND_TASK_FAILED" - " COND_ZOMBIE_CAN_SWAT_ATTACK" - " COND_ZOMBIE_RELEASECRAB" - " COND_HEAVY_DAMAGE" - ) -#else - DEFINE_SCHEDULE - ( - SCHED_ZOMBIE_CHASE_ENEMY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY_FAILED" - " TASK_SET_TOLERANCE_DISTANCE 24" - " TASK_GET_CHASE_PATH_TO_ENEMY 600" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_FACE_ENEMY 0" - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_ENEMY_UNREACHABLE" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK2" - " COND_TOO_CLOSE_TO_ATTACK" - " COND_TASK_FAILED" - " COND_ZOMBIE_CAN_SWAT_ATTACK" - " COND_ZOMBIE_RELEASECRAB" - ) -#endif // HL2_EPISODIC - - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_ZOMBIE_RELEASECRAB, - - " Tasks" - " TASK_PLAY_PRIVATE_SEQUENCE_FACE_ENEMY ACTIVITY:ACT_ZOM_RELEASECRAB" - " TASK_ZOMBIE_RELEASE_HEADCRAB 0" - " TASK_ZOMBIE_DIE 0" - " " - " Interrupts" - " COND_TASK_FAILED" - ) - - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_ZOMBIE_MOVE_TO_AMBUSH, - - " Tasks" - " TASK_WAIT 1.0" // don't react as soon as you see the player. - " TASK_FIND_COVER_FROM_ENEMY 0" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_TURN_LEFT 180" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_ZOMBIE_WAIT_AMBUSH" - " " - " Interrupts" - " COND_TASK_FAILED" - " COND_NEW_ENEMY" - ) - - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_ZOMBIE_WAIT_AMBUSH, - - " Tasks" - " TASK_WAIT_FACE_ENEMY 99999" - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_ENEMY" - ) - - //========================================================= - // Wander around for a while so we don't look stupid. - // this is done if we ever lose track of our enemy. - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_ZOMBIE_WANDER_MEDIUM, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_WANDER 480384" // 4 feet to 32 feet - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_WAIT_PVS 0" // if the player left my PVS, just wait. - " TASK_SET_SCHEDULE SCHEDULE:SCHED_ZOMBIE_WANDER_MEDIUM" // keep doing it - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - ) - - DEFINE_SCHEDULE - ( - SCHED_ZOMBIE_WANDER_STANDOFF, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_WANDER 480384" // 4 feet to 32 feet - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_WAIT_PVS 0" // if the player left my PVS, just wait. - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_ENEMY_DEAD" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK2" - " COND_ZOMBIE_RELEASECRAB" - ) - - //========================================================= - // If you fail to wander, wait just a bit and try again. - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_ZOMBIE_WANDER_FAIL, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_WAIT 1" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_ZOMBIE_WANDER_MEDIUM" - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_ENEMY_DEAD" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK2" - " COND_ZOMBIE_RELEASECRAB" - ) - - //========================================================= - // Like the base class, only don't stop in the middle of - // swinging if the enemy is killed, hides, or new enemy. - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_ZOMBIE_MELEE_ATTACK1, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_ANNOUNCE_ATTACK 1" // 1 = primary attack - " TASK_MELEE_ATTACK1 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_ZOMBIE_POST_MELEE_WAIT" - "" - " Interrupts" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - ) - - //========================================================= - // Make the zombie wait a frame after a melee attack, to - // allow itself & it's enemy to test for dynamic scripted sequences. - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_ZOMBIE_POST_MELEE_WAIT, - - " Tasks" - " TASK_ZOMBIE_WAIT_POST_MELEE 0" - ) - -AI_END_CUSTOM_NPC() diff --git a/game/server/hl2/npc_BaseZombie.h b/game/server/hl2/npc_BaseZombie.h deleted file mode 100644 index 1d20f1da9..000000000 --- a/game/server/hl2/npc_BaseZombie.h +++ /dev/null @@ -1,291 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef NPC_BASEZOMBIE_H -#define NPC_BASEZOMBIE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_basenpc.h" -#include "ai_blended_movement.h" -#include "soundenvelope.h" -#include "ai_behavior_actbusy.h" - -#define ZOM_ATTN_FOOTSTEP ATTN_IDLE - -#define ENVELOPE_CONTROLLER (CSoundEnvelopeController::GetController()) - -#define ZOMBIE_MELEE_REACH 55 - -extern int AE_ZOMBIE_ATTACK_RIGHT; -extern int AE_ZOMBIE_ATTACK_LEFT; -extern int AE_ZOMBIE_ATTACK_BOTH; -extern int AE_ZOMBIE_SWATITEM; -extern int AE_ZOMBIE_STARTSWAT; -extern int AE_ZOMBIE_STEP_LEFT; -extern int AE_ZOMBIE_STEP_RIGHT; -extern int AE_ZOMBIE_SCUFF_LEFT; -extern int AE_ZOMBIE_SCUFF_RIGHT; -extern int AE_ZOMBIE_ATTACK_SCREAM; -extern int AE_ZOMBIE_GET_UP; -extern int AE_ZOMBIE_POUND; - -#define ZOMBIE_BODYGROUP_HEADCRAB 1 // The crab on our head - -// Pass these to claw attack so we know where to draw the blood. -#define ZOMBIE_BLOOD_LEFT_HAND 0 -#define ZOMBIE_BLOOD_RIGHT_HAND 1 -#define ZOMBIE_BLOOD_BOTH_HANDS 2 -#define ZOMBIE_BLOOD_BITE 3 - - -enum HeadcrabRelease_t -{ - RELEASE_NO, - RELEASE_IMMEDIATE, // release the headcrab right now! - RELEASE_SCHEDULED, // release the headcrab through the AI schedule. - RELEASE_VAPORIZE, // just destroy the crab. - RELEASE_RAGDOLL, // release a dead crab - RELEASE_RAGDOLL_SLICED_OFF // toss the crab up a bit -}; - - -//========================================================= -// schedules -//========================================================= -enum -{ - SCHED_ZOMBIE_CHASE_ENEMY = LAST_SHARED_SCHEDULE, - SCHED_ZOMBIE_MOVE_SWATITEM, - SCHED_ZOMBIE_SWATITEM, - SCHED_ZOMBIE_ATTACKITEM, - SCHED_ZOMBIE_RELEASECRAB, - SCHED_ZOMBIE_MOVE_TO_AMBUSH, - SCHED_ZOMBIE_WAIT_AMBUSH, - SCHED_ZOMBIE_WANDER_MEDIUM, // medium range wandering behavior. - SCHED_ZOMBIE_WANDER_FAIL, - SCHED_ZOMBIE_WANDER_STANDOFF, - SCHED_ZOMBIE_MELEE_ATTACK1, - SCHED_ZOMBIE_POST_MELEE_WAIT, - - LAST_BASE_ZOMBIE_SCHEDULE, -}; - -//========================================================= -// tasks -//========================================================= -enum -{ - TASK_ZOMBIE_DELAY_SWAT = LAST_SHARED_TASK, - TASK_ZOMBIE_GET_PATH_TO_PHYSOBJ, - TASK_ZOMBIE_SWAT_ITEM, - TASK_ZOMBIE_DIE, - TASK_ZOMBIE_RELEASE_HEADCRAB, - TASK_ZOMBIE_WAIT_POST_MELEE, - - LAST_BASE_ZOMBIE_TASK, -}; - - -//========================================================= -// Zombie conditions -//========================================================= -enum Zombie_Conds -{ - COND_ZOMBIE_CAN_SWAT_ATTACK = LAST_SHARED_CONDITION, - COND_ZOMBIE_RELEASECRAB, - COND_ZOMBIE_LOCAL_MELEE_OBSTRUCTION, - - LAST_BASE_ZOMBIE_CONDITION, -}; - - - -typedef CAI_BlendingHost< CAI_BehaviorHost > CAI_BaseZombieBase; - -//========================================================= -//========================================================= -abstract_class CNPC_BaseZombie : public CAI_BaseZombieBase -{ - DECLARE_CLASS( CNPC_BaseZombie, CAI_BaseZombieBase ); - -public: - CNPC_BaseZombie( void ); - ~CNPC_BaseZombie( void ); - - void Spawn( void ); - void Precache( void ); - void StartTouch( CBaseEntity *pOther ); - bool CreateBehaviors(); - float MaxYawSpeed( void ); - bool OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval ); - Class_T Classify( void ); - Disposition_t IRelationType( CBaseEntity *pTarget ); - void HandleAnimEvent( animevent_t *pEvent ); - - void OnStateChange( NPC_STATE OldState, NPC_STATE NewState ); - - void KillMe( void ) - { - m_iHealth = 5; - OnTakeDamage( CTakeDamageInfo( this, this, m_iHealth * 2, DMG_GENERIC ) ); - } - - int MeleeAttack1Conditions ( float flDot, float flDist ); - virtual float GetClawAttackRange() const { return ZOMBIE_MELEE_REACH; } - - // No range attacks - int RangeAttack1Conditions ( float flDot, float flDist ) { return( 0 ); } - - virtual float GetHitgroupDamageMultiplier( int iHitGroup, const CTakeDamageInfo &info ); - void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - virtual float GetReactionDelay( CBaseEntity *pEnemy ) { return 0.0; } - - virtual int SelectSchedule ( void ); - virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ); - virtual void BuildScheduleTestBits( void ); - - virtual int TranslateSchedule( int scheduleType ); - virtual Activity NPC_TranslateActivity( Activity baseAct ); - - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - - void GatherConditions( void ); - void PrescheduleThink( void ); - - virtual void Event_Killed( const CTakeDamageInfo &info ); - virtual bool BecomeRagdoll( const CTakeDamageInfo &info, const Vector &forceVector ); - void StopLoopingSounds(); - virtual void OnScheduleChange( void ); - - virtual void PoundSound(); - - // Custom damage/death - bool ShouldIgnite( const CTakeDamageInfo &info ); - bool ShouldIgniteZombieGib( void ); - virtual bool IsChopped( const CTakeDamageInfo &info ); - virtual bool IsSquashed( const CTakeDamageInfo &info ) { return false; } - virtual void DieChopped( const CTakeDamageInfo &info ); - virtual void Ignite( float flFlameLifetime, bool bNPCOnly = true, float flSize = 0.0f, bool bCalledByLevelDesigner = false ); - void CopyRenderColorTo( CBaseEntity *pOther ); - - virtual bool ShouldBecomeTorso( const CTakeDamageInfo &info, float flDamageThreshold ); - virtual HeadcrabRelease_t ShouldReleaseHeadcrab( const CTakeDamageInfo &info, float flDamageThreshold ); - - // Headcrab releasing/breaking apart - void RemoveHead( void ); - virtual void SetZombieModel( void ) { }; - virtual void BecomeTorso( const Vector &vecTorsoForce, const Vector &vecLegsForce ); - virtual bool CanBecomeLiveTorso() { return false; } - virtual bool HeadcrabFits( CBaseAnimating *pCrab ); - void ReleaseHeadcrab( const Vector &vecOrigin, const Vector &vecVelocity, bool fRemoveHead, bool fRagdollBody, bool fRagdollCrab = false ); - void SetHeadcrabSpawnLocation( int iCrabAttachment, CBaseAnimating *pCrab ); - - // Slumping/sleeping - bool IsSlumped( void ); - bool IsGettingUp( void ); - - // Swatting physics objects - int GetSwatActivity( void ); - bool FindNearestPhysicsObject( int iMaxMass ); - float DistToPhysicsEnt( void ); - virtual bool CanSwatPhysicsObjects( void ) { return true; } - - // Returns whether we must be very near our enemy to attack them. - virtual bool MustCloseToAttack(void) { return true; } - - virtual CBaseEntity *ClawAttack( float flDist, int iDamage, QAngle &qaViewPunch, Vector &vecVelocityPunch, int BloodOrigin ); - - // Sounds & sound envelope - virtual bool ShouldPlayFootstepMoan( void ); - virtual void PainSound( const CTakeDamageInfo &info ) = 0; - virtual void AlertSound( void ) = 0; - virtual void IdleSound( void ) = 0; - virtual void AttackSound( void ) = 0; - virtual void AttackHitSound( void ) = 0; - virtual void AttackMissSound( void ) = 0; - virtual void FootstepSound( bool fRightFoot ) = 0; - virtual void FootscuffSound( bool fRightFoot ) = 0; - - // make a sound Alyx can hear when in darkness mode - void MakeAISpookySound( float volume, float duration = 0.5 ); - - virtual bool CanPlayMoanSound(); - virtual void MoanSound( envelopePoint_t *pEnvelope, int iEnvelopeSize ); - bool ShouldPlayIdleSound( void ) { return false; } - - virtual const char *GetMoanSound( int nSound ) = 0; - virtual const char *GetHeadcrabClassname( void ) = 0; - virtual const char *GetLegsModel( void ) = 0; - virtual const char *GetTorsoModel( void ) = 0; - virtual const char *GetHeadcrabModel( void ) = 0; - - virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy ); - virtual Vector HeadTarget( const Vector &posSrc ); - virtual float GetAutoAimRadius(); - virtual void TranslateNavGoal( CBaseEntity *pEnemy, Vector &chasePosition ); - - bool OnInsufficientStopDist( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ); - - virtual bool AllowedToIgnite( void ) { return true; } - -public: - CAI_ActBusyBehavior m_ActBusyBehavior; - - - -protected: - - CSoundPatch *m_pMoanSound; - - bool m_fIsTorso; // is this is a half-zombie? - bool m_fIsHeadless; // is this zombie headless - - float m_flNextFlinch; - - bool m_bHeadShot; // Used to determine the survival of our crab beyond our death. - - // - // Zombies catch on fire if they take too much burn damage in a given time period. - // - float m_flBurnDamage; // Keeps track of how much burn damage we've incurred in the last few seconds. - float m_flBurnDamageResetTime; // Time at which we reset the burn damage. - - EHANDLE m_hPhysicsEnt; - - float m_flNextMoanSound; - float m_flNextSwat; - float m_flNextSwatScan; - float m_crabHealth; - float m_flMoanPitch; - - EHANDLE m_hObstructor; - - static int g_numZombies; // counts total number of existing zombies. - - int m_iMoanSound; // each zombie picks one of the 4 and keeps it. - - static int ACT_ZOM_SWATLEFTMID; - static int ACT_ZOM_SWATRIGHTMID; - static int ACT_ZOM_SWATLEFTLOW; - static int ACT_ZOM_SWATRIGHTLOW; - static int ACT_ZOM_RELEASECRAB; - static int ACT_ZOM_FALL; - - DECLARE_DATADESC(); - - DEFINE_CUSTOM_AI; - -private: - bool m_bIsSlumped; - -}; - -#endif // NPC_BASEZOMBIE_H diff --git a/game/server/hl2/npc_PoisonZombie.cpp b/game/server/hl2/npc_PoisonZombie.cpp deleted file mode 100644 index 0a737945d..000000000 --- a/game/server/hl2/npc_PoisonZombie.cpp +++ /dev/null @@ -1,1145 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: A hideous, putrescent, pus-filled undead carcass atop which a vile -// nest of filthy poisonous headcrabs lurks. -// -// Anyway, this guy has two range attacks: at short range, headcrabs -// will leap from the nest to attack. At long range he will wrench a -// headcrab from his back to throw it at his enemy. -// -//=============================================================================// - -#include "cbase.h" -#include "ai_basenpc.h" -#include "ai_default.h" -#include "ai_schedule.h" -#include "ai_hull.h" -#include "ai_motor.h" -#include "game.h" -#include "npc_headcrab.h" -#include "npcevent.h" -#include "entitylist.h" -#include "ai_task.h" -#include "activitylist.h" -#include "engine/IEngineSound.h" -#include "npc_BaseZombie.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define BREATH_VOL_MAX 0.6 - -// -// Controls how soon he throws the first headcrab after seeing his enemy (also when the first headcrab leaps off) -// -#define ZOMBIE_THROW_FIRST_MIN_DELAY 1 // min seconds before first crab throw -#define ZOMBIE_THROW_FIRST_MAX_DELAY 2 // max seconds before first crab throw - -// -// Controls how often he throws headcrabs (also how often headcrabs leap off) -// -#define ZOMBIE_THROW_MIN_DELAY 4 // min seconds between crab throws -#define ZOMBIE_THROW_MAX_DELAY 10 // max seconds between crab throws - -// -// Ranges for throwing headcrabs. -// -#define ZOMBIE_THROW_RANGE_MIN 250 -#define ZOMBIE_THROW_RANGE_MAX 800 -#define ZOMBIE_THROW_CONE 0.6 - -// -// Ranges for headcrabs leaping off. -// -#define ZOMBIE_HC_LEAP_RANGE_MIN 12 -#define ZOMBIE_HC_LEAP_RANGE_MAX 256 -#define ZOMBIE_HC_LEAP_CONE 0.6 - - -#define ZOMBIE_BODYGROUP_NEST_BASE 2 // First nest crab, +2 more -#define ZOMBIE_BODYGROUP_THROW 5 // The crab in our hand for throwing - -#define ZOMBIE_ENEMY_BREATHE_DIST 300 // How close we must be to our enemy before we start breathing hard. - - -envelopePoint_t envPoisonZombieMoanVolumeFast[] = -{ - { 1.0f, 1.0f, - 0.1f, 0.1f, - }, - { 0.0f, 0.0f, - 0.2f, 0.3f, - }, -}; - - -// -// Turns the breathing off for a second, then back on. -// -envelopePoint_t envPoisonZombieBreatheVolumeOffShort[] = -{ - { 0.0f, 0.0f, - 0.1f, 0.1f, - }, - { 0.0f, 0.0f, - 2.0f, 2.0f, - }, - { BREATH_VOL_MAX, BREATH_VOL_MAX, - 1.0f, 1.0f, - }, -}; - - -// -// Custom schedules. -// -enum -{ - SCHED_ZOMBIE_POISON_RANGE_ATTACK2 = LAST_BASE_ZOMBIE_SCHEDULE, - SCHED_ZOMBIE_POISON_RANGE_ATTACK1, -}; - - -//----------------------------------------------------------------------------- -// The maximum number of headcrabs we can have riding on our back. -// NOTE: If you change this value you must also change the lookup table in Spawn! -//----------------------------------------------------------------------------- -#define MAX_CRABS 3 - -int AE_ZOMBIE_POISON_THROW_WARN_SOUND; -int AE_ZOMBIE_POISON_PICKUP_CRAB; -int AE_ZOMBIE_POISON_THROW_SOUND; -int AE_ZOMBIE_POISON_THROW_CRAB; -int AE_ZOMBIE_POISON_SPIT; - -//----------------------------------------------------------------------------- -// The model we use for our legs when we get blowed up. -//----------------------------------------------------------------------------- -static const char *s_szLegsModel = "models/zombie/classic_legs.mdl"; - - -//----------------------------------------------------------------------------- -// The classname of the headcrab that jumps off of this kind of zombie. -//----------------------------------------------------------------------------- -static const char *s_szHeadcrabClassname = "npc_headcrab_poison"; -static const char *s_szHeadcrabModel = "models/headcrabblack.mdl"; - -static const char *pMoanSounds[] = -{ - "NPC_PoisonZombie.Moan1", -}; - -//----------------------------------------------------------------------------- -// Skill settings. -//----------------------------------------------------------------------------- -ConVar sk_zombie_poison_health( "sk_zombie_poison_health", "0"); -ConVar sk_zombie_poison_dmg_spit( "sk_zombie_poison_dmg_spit","0"); - -class CNPC_PoisonZombie : public CAI_BlendingHost -{ - DECLARE_CLASS( CNPC_PoisonZombie, CAI_BlendingHost ); - -public: - - // - // CBaseZombie implemenation. - // - virtual Vector HeadTarget( const Vector &posSrc ); - bool ShouldBecomeTorso( const CTakeDamageInfo &info, float flDamageThreshold ); - virtual bool IsChopped( const CTakeDamageInfo &info ) { return false; } - - // - // CAI_BaseNPC implementation. - // - virtual float MaxYawSpeed( void ); - - virtual int RangeAttack1Conditions( float flDot, float flDist ); - virtual int RangeAttack2Conditions( float flDot, float flDist ); - - virtual float GetClawAttackRange() const { return 70; } - - virtual void PrescheduleThink( void ); - virtual void BuildScheduleTestBits( void ); - virtual int SelectSchedule( void ); - virtual int SelectFailSchedule( int nFailedSchedule, int nFailedTask, AI_TaskFailureCode_t eTaskFailCode ); - virtual int TranslateSchedule( int scheduleType ); - - virtual bool ShouldPlayIdleSound( void ); - - // - // CBaseAnimating implementation. - // - virtual void HandleAnimEvent( animevent_t *pEvent ); - - // - // CBaseEntity implementation. - // - virtual void Spawn( void ); - virtual void Precache( void ); - virtual void SetZombieModel( void ); - - virtual Class_T Classify( void ); - virtual void Event_Killed( const CTakeDamageInfo &info ); - virtual int OnTakeDamage_Alive( const CTakeDamageInfo &inputInfo ); - - DECLARE_DATADESC(); - DEFINE_CUSTOM_AI; - - void PainSound( const CTakeDamageInfo &info ); - void AlertSound( void ); - void IdleSound( void ); - void AttackSound( void ); - void AttackHitSound( void ); - void AttackMissSound( void ); - void FootstepSound( bool fRightFoot ); - void FootscuffSound( bool fRightFoot ) {}; - - virtual void StopLoopingSounds( void ); - -protected: - - virtual void MoanSound( envelopePoint_t *pEnvelope, int iEnvelopeSize ); - virtual bool MustCloseToAttack( void ); - - virtual const char *GetMoanSound( int nSoundIndex ); - virtual const char *GetLegsModel( void ); - virtual const char *GetTorsoModel( void ); - virtual const char *GetHeadcrabClassname( void ); - virtual const char *GetHeadcrabModel( void ); - -private: - - void BreatheOffShort( void ); - - void EnableCrab( int nCrab, bool bEnable ); - int RandomThrowCrab( void ); - void EvacuateNest( bool bExplosion, float flDamage, CBaseEntity *pAttacker ); - - CSoundPatch *m_pFastBreathSound; - CSoundPatch *m_pSlowBreathSound; - - int m_nCrabCount; // How many headcrabs we have on our back. - bool m_bCrabs[MAX_CRABS]; // Which crabs in particular are on our back. - float m_flNextCrabThrowTime; // The next time we are allowed to throw a headcrab. - - float m_flNextPainSoundTime; - - bool m_bNearEnemy; - - // NOT serialized: - int m_nThrowCrab; // The crab we are about to throw. -}; - -LINK_ENTITY_TO_CLASS( npc_poisonzombie, CNPC_PoisonZombie ); - - -BEGIN_DATADESC( CNPC_PoisonZombie ) - - DEFINE_SOUNDPATCH( m_pFastBreathSound ), - DEFINE_SOUNDPATCH( m_pSlowBreathSound ), - DEFINE_KEYFIELD( m_nCrabCount, FIELD_INTEGER, "crabcount" ), - DEFINE_ARRAY( m_bCrabs, FIELD_BOOLEAN, MAX_CRABS ), - DEFINE_FIELD( m_flNextCrabThrowTime, FIELD_TIME ), - - DEFINE_FIELD( m_flNextPainSoundTime, FIELD_TIME ), - - DEFINE_FIELD( m_bNearEnemy, FIELD_BOOLEAN ), - - // NOT serialized: - //DEFINE_FIELD( m_nThrowCrab, FIELD_INTEGER ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_PoisonZombie::Precache( void ) -{ - PrecacheModel("models/zombie/poison.mdl"); - - PrecacheScriptSound( "NPC_PoisonZombie.Die" ); - PrecacheScriptSound( "NPC_PoisonZombie.ThrowWarn" ); - PrecacheScriptSound( "NPC_PoisonZombie.Throw" ); - PrecacheScriptSound( "NPC_PoisonZombie.Idle" ); - PrecacheScriptSound( "NPC_PoisonZombie.Pain" ); - PrecacheScriptSound( "NPC_PoisonZombie.Alert" ); - PrecacheScriptSound( "NPC_PoisonZombie.FootstepRight" ); - PrecacheScriptSound( "NPC_PoisonZombie.FootstepLeft" ); - PrecacheScriptSound( "NPC_PoisonZombie.Attack" ); - - PrecacheScriptSound( "NPC_PoisonZombie.FastBreath" ); - PrecacheScriptSound( "NPC_PoisonZombie.Moan1" ); - - PrecacheScriptSound( "Zombie.AttackHit" ); - PrecacheScriptSound( "Zombie.AttackMiss" ); - - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_PoisonZombie::Spawn( void ) -{ - Precache(); - - m_fIsTorso = m_fIsHeadless = false; - -#ifdef HL2_EPISODIC - SetBloodColor( BLOOD_COLOR_ZOMBIE ); -#else - SetBloodColor( BLOOD_COLOR_YELLOW ); -#endif // HL2_EPISODIC - - m_iHealth = sk_zombie_poison_health.GetFloat(); - m_flFieldOfView = 0.2; - - CapabilitiesClear(); - CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_INNATE_MELEE_ATTACK1 | bits_CAP_INNATE_RANGE_ATTACK1 | bits_CAP_INNATE_RANGE_ATTACK2 ); - - BaseClass::Spawn(); - - CPASAttenuationFilter filter( this, ATTN_IDLE ); - m_pFastBreathSound = ENVELOPE_CONTROLLER.SoundCreate( filter, entindex(), CHAN_ITEM, "NPC_PoisonZombie.FastBreath", ATTN_IDLE ); - ENVELOPE_CONTROLLER.Play( m_pFastBreathSound, 0.0f, 100 ); - - CPASAttenuationFilter filter2( this ); - m_pSlowBreathSound = ENVELOPE_CONTROLLER.SoundCreate( filter2, entindex(), CHAN_ITEM, "NPC_PoisonZombie.Moan1", ATTN_NORM ); - ENVELOPE_CONTROLLER.Play( m_pSlowBreathSound, BREATH_VOL_MAX, 100 ); - - int nCrabs = m_nCrabCount; - if ( !nCrabs ) - { - nCrabs = MAX_CRABS; - } - m_nCrabCount = 0; - - // - // Generate a random set of crabs based on the crab count - // specified by the level designer. - // - int nBits[] = - { - // One bit - 0x01, - 0x02, - 0x04, - - // Two bits - 0x03, - 0x05, - 0x06, - }; - - int nBitMask = 7; - if (nCrabs == 1) - { - nBitMask = nBits[random->RandomInt( 0, 2 )]; - } - else if (nCrabs == 2) - { - nBitMask = nBits[random->RandomInt( 3, 5 )]; - } - - for ( int i = 0; i < MAX_CRABS; i++ ) - { - EnableCrab( i, ( nBitMask & ( 1 << i ) ) != 0 ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns a moan sound for this class of zombie. -//----------------------------------------------------------------------------- -const char *CNPC_PoisonZombie::GetMoanSound( int nSound ) -{ - return pMoanSounds[nSound % ARRAYSIZE( pMoanSounds )]; -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns the model to use for our legs ragdoll when we are blown in twain. -//----------------------------------------------------------------------------- -const char *CNPC_PoisonZombie::GetLegsModel( void ) -{ - return s_szLegsModel; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -const char *CNPC_PoisonZombie::GetTorsoModel( void ) -{ - return "models/zombie/classic_torso.mdl"; -} - - - -//----------------------------------------------------------------------------- -// Purpose: Returns the classname (ie "npc_headcrab") to spawn when our headcrab bails. -//----------------------------------------------------------------------------- -const char *CNPC_PoisonZombie::GetHeadcrabClassname( void ) -{ - return s_szHeadcrabClassname; -} - -const char *CNPC_PoisonZombie::GetHeadcrabModel( void ) -{ - return s_szHeadcrabModel; -} - - -//----------------------------------------------------------------------------- -// Purpose: Turns the given crab on or off. -//----------------------------------------------------------------------------- -void CNPC_PoisonZombie::EnableCrab( int nCrab, bool bEnable ) -{ - ASSERT( ( nCrab >= 0 ) && ( nCrab < MAX_CRABS ) ); - - if ( ( nCrab >= 0 ) && ( nCrab < MAX_CRABS ) ) - { - if (m_bCrabs[nCrab] != bEnable) - { - m_nCrabCount += bEnable ? 1 : -1; - } - - m_bCrabs[nCrab] = bEnable; - SetBodygroup( ZOMBIE_BODYGROUP_NEST_BASE + nCrab, bEnable ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_PoisonZombie::StopLoopingSounds( void ) -{ - ENVELOPE_CONTROLLER.SoundDestroy( m_pFastBreathSound ); - m_pFastBreathSound = NULL; - - ENVELOPE_CONTROLLER.SoundDestroy( m_pSlowBreathSound ); - m_pSlowBreathSound = NULL; - - BaseClass::StopLoopingSounds(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : info - -//----------------------------------------------------------------------------- -void CNPC_PoisonZombie::Event_Killed( const CTakeDamageInfo &info ) -{ - if ( !( info.GetDamageType() & ( DMG_BLAST | DMG_ALWAYSGIB) ) ) - { - EmitSound( "NPC_PoisonZombie.Die" ); - } - - if ( !m_fIsTorso ) - { - EvacuateNest(info.GetDamageType() == DMG_BLAST, info.GetDamage(), info.GetAttacker() ); - } - - BaseClass::Event_Killed( info ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputInfo - -// Output : int -//----------------------------------------------------------------------------- -int CNPC_PoisonZombie::OnTakeDamage_Alive( const CTakeDamageInfo &inputInfo ) -{ - // - // Calculate what percentage of the creature's max health - // this amount of damage represents (clips at 1.0). - // - float flDamagePercent = MIN( 1, inputInfo.GetDamage() / m_iMaxHealth ); - - // - // Throw one crab for every 20% damage we take. - // - if ( flDamagePercent >= 0.2 ) - { - m_flNextCrabThrowTime = gpGlobals->curtime; - } - - return BaseClass::OnTakeDamage_Alive( inputInfo ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CNPC_PoisonZombie::MaxYawSpeed( void ) -{ - return BaseClass::MaxYawSpeed(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Class_T CNPC_PoisonZombie::Classify( void ) -{ - return CLASS_ZOMBIE; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -// NOTE: This function is still heavy with common code (found at the bottom). -// we should consider moving some into the base class! (sjb) -//----------------------------------------------------------------------------- -void CNPC_PoisonZombie::SetZombieModel( void ) -{ - Hull_t lastHull = GetHullType(); - - if ( m_fIsTorso ) - { - SetModel( "models/zombie/classic_torso.mdl" ); - SetHullType(HULL_TINY); - } - else - { - SetModel( "models/zombie/poison.mdl" ); - SetHullType(HULL_HUMAN); - } - - SetBodygroup( ZOMBIE_BODYGROUP_HEADCRAB, !m_fIsHeadless ); - - SetHullSizeNormal( true ); - SetDefaultEyeOffset(); - SetActivity( ACT_IDLE ); - - // hull changed size, notify vphysics - // UNDONE: Solve this generally, systematically so other - // NPCs can change size - if ( lastHull != GetHullType() ) - { - if ( VPhysicsGetObject() ) - { - SetupVPhysicsHull(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Checks conditions for letting a headcrab leap off our back at our enemy. -//----------------------------------------------------------------------------- -int CNPC_PoisonZombie::RangeAttack1Conditions( float flDot, float flDist ) -{ - if ( !m_nCrabCount ) - { - //DevMsg("Range1: No crabs\n"); - return 0; - } - - if ( m_flNextCrabThrowTime > gpGlobals->curtime ) - { - //DevMsg("Range1: Too soon\n"); - return 0; - } - - if ( flDist < ZOMBIE_HC_LEAP_RANGE_MIN ) - { - //DevMsg("Range1: Too close to attack\n"); - return COND_TOO_CLOSE_TO_ATTACK; - } - - if ( flDist > ZOMBIE_HC_LEAP_RANGE_MAX ) - { - //DevMsg("Range1: Too far to attack\n"); - return COND_TOO_FAR_TO_ATTACK; - } - - if ( flDot < ZOMBIE_HC_LEAP_CONE ) - { - //DevMsg("Range1: Not facing\n"); - return COND_NOT_FACING_ATTACK; - } - - m_nThrowCrab = RandomThrowCrab(); - - //DevMsg("*** Range1: Can range attack\n"); - return COND_CAN_RANGE_ATTACK1; -} - - -//----------------------------------------------------------------------------- -// Purpose: Checks conditions for throwing a headcrab leap at our enemy. -//----------------------------------------------------------------------------- -int CNPC_PoisonZombie::RangeAttack2Conditions( float flDot, float flDist ) -{ - if ( !m_nCrabCount ) - { - //DevMsg("Range2: No crabs\n"); - return 0; - } - - if ( m_flNextCrabThrowTime > gpGlobals->curtime ) - { - //DevMsg("Range2: Too soon\n"); - return 0; - } - - if ( flDist < ZOMBIE_THROW_RANGE_MIN ) - { - //DevMsg("Range2: Too close to attack\n"); - return COND_TOO_CLOSE_TO_ATTACK; - } - - if ( flDist > ZOMBIE_THROW_RANGE_MAX ) - { - //DevMsg("Range2: Too far to attack\n"); - return COND_TOO_FAR_TO_ATTACK; - } - - if ( flDot < ZOMBIE_THROW_CONE ) - { - //DevMsg("Range2: Not facing\n"); - return COND_NOT_FACING_ATTACK; - } - - m_nThrowCrab = RandomThrowCrab(); - - //DevMsg("*** Range2: Can range attack\n"); - return COND_CAN_RANGE_ATTACK2; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Vector CNPC_PoisonZombie::HeadTarget( const Vector &posSrc ) -{ - int iCrabAttachment = LookupAttachment( "headcrab1" ); - Assert( iCrabAttachment > 0 ); - - Vector vecPosition; - - GetAttachment( iCrabAttachment, vecPosition ); - - return vecPosition; -} - -//----------------------------------------------------------------------------- -// Purpose: Turns off our breath so we can play another vocal sound. -// TODO: pass in duration -//----------------------------------------------------------------------------- -void CNPC_PoisonZombie::BreatheOffShort( void ) -{ - if ( m_bNearEnemy ) - { - ENVELOPE_CONTROLLER.SoundPlayEnvelope( m_pFastBreathSound, SOUNDCTRL_CHANGE_VOLUME, envPoisonZombieBreatheVolumeOffShort, ARRAYSIZE(envPoisonZombieBreatheVolumeOffShort) ); - } - else - { - ENVELOPE_CONTROLLER.SoundPlayEnvelope( m_pSlowBreathSound, SOUNDCTRL_CHANGE_VOLUME, envPoisonZombieBreatheVolumeOffShort, ARRAYSIZE(envPoisonZombieBreatheVolumeOffShort) ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Catches the monster-specific events that occur when tagged animation -// frames are played. -// Input : pEvent - -//----------------------------------------------------------------------------- -void CNPC_PoisonZombie::HandleAnimEvent( animevent_t *pEvent ) -{ - - if ( pEvent->event == AE_ZOMBIE_POISON_PICKUP_CRAB ) - { - EnableCrab( m_nThrowCrab, false ); - SetBodygroup( ZOMBIE_BODYGROUP_THROW, 1 ); - return; - } - - if ( pEvent->event == AE_ZOMBIE_POISON_THROW_WARN_SOUND ) - { - BreatheOffShort(); - EmitSound( "NPC_PoisonZombie.ThrowWarn" ); - return; - } - - if ( pEvent->event == AE_ZOMBIE_POISON_THROW_SOUND ) - { - BreatheOffShort(); - EmitSound( "NPC_PoisonZombie.Throw" ); - return; - } - - if ( pEvent->event == AE_ZOMBIE_POISON_THROW_CRAB ) - { - SetBodygroup( ZOMBIE_BODYGROUP_THROW, 0 ); - - CBlackHeadcrab *pCrab = (CBlackHeadcrab *)CreateNoSpawn( GetHeadcrabClassname(), EyePosition(), vec3_angle, this ); - pCrab->AddSpawnFlags( SF_NPC_FALL_TO_GROUND ); - - // Fade if our parent is supposed to - if ( HasSpawnFlags( SF_NPC_FADE_CORPSE ) ) - { - pCrab->AddSpawnFlags( SF_NPC_FADE_CORPSE ); - } - - // make me the crab's owner to avoid collision issues - pCrab->SetOwnerEntity( this ); - - pCrab->Spawn(); - - pCrab->SetLocalAngles( GetLocalAngles() ); - pCrab->SetActivity( ACT_RANGE_ATTACK1 ); - pCrab->SetNextThink( gpGlobals->curtime ); - pCrab->PhysicsSimulate(); - - pCrab->GetMotor()->SetIdealYaw( GetAbsAngles().y ); - - if ( IsOnFire() ) - { - pCrab->Ignite( 100.0 ); - } - - CBaseEntity *pEnemy = GetEnemy(); - if ( pEnemy ) - { - Vector vecEnemyEyePos = pEnemy->EyePosition(); - pCrab->ThrowAt( vecEnemyEyePos ); - } - - if (m_nCrabCount == 0) - { - CapabilitiesRemove( bits_CAP_INNATE_RANGE_ATTACK1 | bits_CAP_INNATE_RANGE_ATTACK2 ); - } - - m_flNextCrabThrowTime = gpGlobals->curtime + random->RandomInt( ZOMBIE_THROW_MIN_DELAY, ZOMBIE_THROW_MAX_DELAY ); - return; - } - - if ( pEvent->event == AE_ZOMBIE_POISON_SPIT ) - { - Vector forward; - QAngle qaPunch( 45, random->RandomInt(-5, 5), random->RandomInt(-5, 5) ); - AngleVectors( GetLocalAngles(), &forward ); - forward = forward * 200; - ClawAttack( GetClawAttackRange(), sk_zombie_poison_dmg_spit.GetInt(), qaPunch, forward, ZOMBIE_BLOOD_BITE ); - return; - } - - BaseClass::HandleAnimEvent( pEvent ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns the index of a randomly chosen crab to throw. -//----------------------------------------------------------------------------- -int CNPC_PoisonZombie::RandomThrowCrab( void ) -{ - // FIXME: this could take a long time, theoretically - int nCrab = -1; - do - { - int nTest = random->RandomInt( 0, 2 ); - if ( m_bCrabs[nTest] ) - { - nCrab = nTest; - } - } while ( nCrab == -1 ); - - return nCrab; -} - - -//----------------------------------------------------------------------------- -// Purpose: The nest is dead! Evacuate the nest! -// Input : bExplosion - We were evicted by an explosion so we should go a-flying. -// flDamage - The damage that was done to cause the evacuation. -//----------------------------------------------------------------------------- -void CNPC_PoisonZombie::EvacuateNest( bool bExplosion, float flDamage, CBaseEntity *pAttacker ) -{ - // HACK: if we were in mid-throw, drop the throwing crab also. - if ( GetBodygroup( ZOMBIE_BODYGROUP_THROW ) ) - { - SetBodygroup( ZOMBIE_BODYGROUP_THROW, 0 ); - m_nCrabCount++; - } - - for( int i = 0; i < MAX_CRABS ; i++ ) - { - if( m_bCrabs[i] ) - { - Vector vecPosition; - QAngle vecAngles; - - char szAttachment[64]; - - switch( i ) - { - case 0: - strcpy( szAttachment, "headcrab2" ); - break; - case 1: - strcpy( szAttachment, "headcrab3" ); - break; - case 2: - strcpy( szAttachment, "headcrab4" ); - break; - } - - GetAttachment( szAttachment, vecPosition, vecAngles ); - - // Now slam the angles because the attachment point will have pitch and roll, which we can't use. - vecAngles = QAngle( 0, random->RandomFloat( 0, 360 ), 0 ); - - CBlackHeadcrab *pCrab = (CBlackHeadcrab *)CreateNoSpawn( GetHeadcrabClassname(), vecPosition, vecAngles, this ); - pCrab->Spawn(); - - if( !HeadcrabFits(pCrab) ) - { - UTIL_Remove(pCrab); - continue; - } - - float flVelocityScale = 2.0f; - if ( bExplosion && ( flDamage > 10 ) ) - { - flVelocityScale = 0.1 * flDamage; - } - - if (IsOnFire()) - { - pCrab->Ignite( 100.0 ); - } - - pCrab->Eject( vecAngles, flVelocityScale, pAttacker ); - EnableCrab( i, false ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_PoisonZombie::PrescheduleThink( void ) -{ - if ( HasCondition( COND_NEW_ENEMY ) ) - { - m_flNextCrabThrowTime = gpGlobals->curtime + random->RandomInt( ZOMBIE_THROW_FIRST_MIN_DELAY, ZOMBIE_THROW_FIRST_MAX_DELAY ); - } - - bool bNearEnemy = false; - if ( GetEnemy() != NULL ) - { - float flDist = (GetEnemy()->GetAbsOrigin() - GetAbsOrigin()).Length(); - if ( flDist < ZOMBIE_ENEMY_BREATHE_DIST ) - { - bNearEnemy = true; - } - } - - if ( bNearEnemy ) - { - if ( !m_bNearEnemy ) - { - // Our enemy is nearby. Breathe faster. - float duration = random->RandomFloat( 1.0f, 2.0f ); - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pFastBreathSound, BREATH_VOL_MAX, duration ); - ENVELOPE_CONTROLLER.SoundChangePitch( m_pFastBreathSound, random->RandomInt( 100, 120 ), random->RandomFloat( 1.0f, 2.0f ) ); - - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pSlowBreathSound, 0.0f, duration ); - - m_bNearEnemy = true; - } - } - else if ( m_bNearEnemy ) - { - // Our enemy is far away. Slow our breathing down. - float duration = random->RandomFloat( 2.0f, 4.0f ); - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pFastBreathSound, BREATH_VOL_MAX, duration ); - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pSlowBreathSound, 0.0f, duration ); -// ENVELOPE_CONTROLLER.SoundChangePitch( m_pBreathSound, random->RandomInt( 80, 100 ), duration ); - - m_bNearEnemy = false; - } - - BaseClass::PrescheduleThink(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Allows for modification of the interrupt mask for the current schedule. -// In the most cases the base implementation should be called first. -//----------------------------------------------------------------------------- -void CNPC_PoisonZombie::BuildScheduleTestBits( void ) -{ - BaseClass::BuildScheduleTestBits(); - - if ( IsCurSchedule( SCHED_CHASE_ENEMY ) ) - { - SetCustomInterruptCondition( COND_LIGHT_DAMAGE ); - SetCustomInterruptCondition( COND_HEAVY_DAMAGE ); - } - else if ( IsCurSchedule( SCHED_RANGE_ATTACK1 ) || IsCurSchedule( SCHED_RANGE_ATTACK2 ) ) - { - ClearCustomInterruptCondition( COND_LIGHT_DAMAGE ); - ClearCustomInterruptCondition( COND_HEAVY_DAMAGE ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_PoisonZombie::SelectFailSchedule( int nFailedSchedule, int nFailedTask, AI_TaskFailureCode_t eTaskFailCode ) -{ - int nSchedule = BaseClass::SelectFailSchedule( nFailedSchedule, nFailedTask, eTaskFailCode ); - - if ( nSchedule == SCHED_CHASE_ENEMY_FAILED && m_nCrabCount > 0 ) - { - return SCHED_ESTABLISH_LINE_OF_FIRE; - } - - return nSchedule; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CNPC_PoisonZombie::SelectSchedule( void ) -{ - int nSchedule = BaseClass::SelectSchedule(); - - if ( nSchedule == SCHED_SMALL_FLINCH ) - { - m_flNextFlinchTime = gpGlobals->curtime + random->RandomFloat( 1, 3 ); - } - - return nSchedule; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : scheduleType - -// Output : int -//----------------------------------------------------------------------------- -int CNPC_PoisonZombie::TranslateSchedule( int scheduleType ) -{ - if ( scheduleType == SCHED_RANGE_ATTACK2 ) - { - return SCHED_ZOMBIE_POISON_RANGE_ATTACK2; - } - - if ( scheduleType == SCHED_RANGE_ATTACK1 ) - { - return SCHED_ZOMBIE_POISON_RANGE_ATTACK1; - } - - if ( scheduleType == SCHED_COMBAT_FACE && IsUnreachable( GetEnemy() ) ) - return SCHED_TAKE_COVER_FROM_ENEMY; - - // We'd simply like to shamble towards our enemy - if ( scheduleType == SCHED_MOVE_TO_WEAPON_RANGE ) - return SCHED_CHASE_ENEMY; - - return BaseClass::TranslateSchedule( scheduleType ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_PoisonZombie::ShouldPlayIdleSound( void ) -{ - return CAI_BaseNPC::ShouldPlayIdleSound(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Play a random attack hit sound -//----------------------------------------------------------------------------- -void CNPC_PoisonZombie::AttackHitSound( void ) -{ - EmitSound( "Zombie.AttackHit" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Play a random attack miss sound -//----------------------------------------------------------------------------- -void CNPC_PoisonZombie::AttackMissSound( void ) -{ - EmitSound( "Zombie.AttackMiss" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Play a random attack sound. -//----------------------------------------------------------------------------- -void CNPC_PoisonZombie::AttackSound( void ) -{ - EmitSound( "NPC_PoisonZombie.Attack" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Play a random idle sound. -//----------------------------------------------------------------------------- -void CNPC_PoisonZombie::IdleSound( void ) -{ - // HACK: base zombie code calls IdleSound even when not idle! - if ( m_NPCState != NPC_STATE_COMBAT ) - { - BreatheOffShort(); - EmitSound( "NPC_PoisonZombie.Idle" ); - MakeAISpookySound( 360.0f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Play a random pain sound. -//----------------------------------------------------------------------------- -void CNPC_PoisonZombie::PainSound( const CTakeDamageInfo &info ) -{ - // Don't make pain sounds too often. - if ( m_flNextPainSoundTime <= gpGlobals->curtime ) - { - BreatheOffShort(); - EmitSound( "NPC_PoisonZombie.Pain" ); - m_flNextPainSoundTime = gpGlobals->curtime + random->RandomFloat( 4.0, 7.0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Play a random alert sound. -//----------------------------------------------------------------------------- -void CNPC_PoisonZombie::AlertSound( void ) -{ - BreatheOffShort(); - - EmitSound( "NPC_PoisonZombie.Alert" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Sound of a footstep -//----------------------------------------------------------------------------- -void CNPC_PoisonZombie::FootstepSound( bool fRightFoot ) -{ - if( fRightFoot ) - { - EmitSound( "NPC_PoisonZombie.FootstepRight" ); - } - else - { - EmitSound( "NPC_PoisonZombie.FootstepLeft" ); - } - - if( ShouldPlayFootstepMoan() ) - { - m_flNextMoanSound = gpGlobals->curtime; - MoanSound( envPoisonZombieMoanVolumeFast, ARRAYSIZE( envPoisonZombieMoanVolumeFast ) ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: If we don't have any headcrabs to throw, we must close to attack our enemy. -//----------------------------------------------------------------------------- -bool CNPC_PoisonZombie::MustCloseToAttack(void) -{ - return (m_nCrabCount == 0); -} - - -//----------------------------------------------------------------------------- -// Purpose: Open a window and let a little bit of the looping moan sound -// come through. -//----------------------------------------------------------------------------- -void CNPC_PoisonZombie::MoanSound( envelopePoint_t *pEnvelope, int iEnvelopeSize ) -{ - if( !m_pMoanSound ) - { - // Don't set this up until the code calls for it. - const char *pszSound = GetMoanSound( m_iMoanSound ); - m_flMoanPitch = random->RandomInt( 98, 110 ); - - CPASAttenuationFilter filter( this, 1.5 ); - //m_pMoanSound = ENVELOPE_CONTROLLER.SoundCreate( entindex(), CHAN_STATIC, pszSound, ATTN_NORM ); - m_pMoanSound = ENVELOPE_CONTROLLER.SoundCreate( filter, entindex(), CHAN_STATIC, pszSound, 1.5 ); - - ENVELOPE_CONTROLLER.Play( m_pMoanSound, 0.5, m_flMoanPitch ); - } - - envPoisonZombieMoanVolumeFast[ 1 ].durationMin = 0.1; - envPoisonZombieMoanVolumeFast[ 1 ].durationMax = 0.4; - - if ( random->RandomInt( 1, 2 ) == 1 ) - { - IdleSound(); - } - - float duration = ENVELOPE_CONTROLLER.SoundPlayEnvelope( m_pMoanSound, SOUNDCTRL_CHANGE_VOLUME, pEnvelope, iEnvelopeSize ); - - float flPitchShift = random->RandomInt( -4, 4 ); - ENVELOPE_CONTROLLER.SoundChangePitch( m_pMoanSound, m_flMoanPitch + flPitchShift, 0.3 ); - - m_flNextMoanSound = gpGlobals->curtime + duration + 9999; -} - - -//----------------------------------------------------------------------------- -// Purpose: Overloaded so that explosions don't split the poison zombie in twain. -//----------------------------------------------------------------------------- -bool CNPC_PoisonZombie::ShouldBecomeTorso( const CTakeDamageInfo &info, float flDamageThreshold ) -{ - return false; -} - - -int ACT_ZOMBIE_POISON_THREAT; - - -AI_BEGIN_CUSTOM_NPC( npc_poisonzombie, CNPC_PoisonZombie ) - - DECLARE_ACTIVITY( ACT_ZOMBIE_POISON_THREAT ) - - //Adrian: events go here - DECLARE_ANIMEVENT( AE_ZOMBIE_POISON_THROW_WARN_SOUND ) - DECLARE_ANIMEVENT( AE_ZOMBIE_POISON_PICKUP_CRAB ) - DECLARE_ANIMEVENT( AE_ZOMBIE_POISON_THROW_SOUND ) - DECLARE_ANIMEVENT( AE_ZOMBIE_POISON_THROW_CRAB ) - DECLARE_ANIMEVENT( AE_ZOMBIE_POISON_SPIT ) - - DEFINE_SCHEDULE - ( - SCHED_ZOMBIE_POISON_RANGE_ATTACK2, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_IDEAL 0" - " TASK_PLAY_PRIVATE_SEQUENCE_FACE_ENEMY ACTIVITY:ACT_ZOMBIE_POISON_THREAT" - " TASK_FACE_IDEAL 0" - " TASK_RANGE_ATTACK2 0" - - " Interrupts" - " COND_NO_PRIMARY_AMMO" - ) - - DEFINE_SCHEDULE - ( - SCHED_ZOMBIE_POISON_RANGE_ATTACK1, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_ANNOUNCE_ATTACK 1" // 1 = primary attack - " TASK_RANGE_ATTACK1 0" - "" - " Interrupts" - " COND_NO_PRIMARY_AMMO" - ) - -AI_END_CUSTOM_NPC() - - diff --git a/game/server/hl2/npc_alyx.cpp b/game/server/hl2/npc_alyx.cpp deleted file mode 100644 index bdd3bcfb2..000000000 --- a/game/server/hl2/npc_alyx.cpp +++ /dev/null @@ -1,272 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Alyx, the female sidekick and love interest that's taking the world by storm! -// -// Try the new Alyx Brite toothpaste! -// Alyx lederhosen! -// -// FIXME: need a better comment block -// -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" -#include "ai_basenpc.h" -#include "ai_hull.h" -#include "ai_basehumanoid.h" -#include "npc_alyx.h" -#include "ai_senses.h" -#include "soundent.h" -#include "props.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -LINK_ENTITY_TO_CLASS( npc_alyx, CNPC_Alyx ); - -BEGIN_DATADESC( CNPC_Alyx ) - - DEFINE_FIELD( m_hEmpTool, FIELD_EHANDLE ), - -END_DATADESC() - -int AE_ALYX_EMPTOOL_ATTACHMENT; -int AE_ALYX_EMPTOOL_SEQUENCE; - -//========================================================= -// Classify - indicates this NPC's place in the -// relationship table. -//========================================================= -Class_T CNPC_Alyx::Classify ( void ) -{ - return CLASS_PLAYER_ALLY_VITAL; -} - - -//========================================================= -// HandleAnimEvent - catches the NPC-specific messages -// that occur when tagged animation frames are played. -//========================================================= -void CNPC_Alyx::HandleAnimEvent( animevent_t *pEvent ) -{ - if (pEvent->event == AE_ALYX_EMPTOOL_ATTACHMENT) - { - if (!m_hEmpTool) - { - // Old savegame? - CreateEmpTool(); - if (!m_hEmpTool) - return; - } - - int iAttachment = LookupAttachment( pEvent->options ); - m_hEmpTool->SetParent(this, iAttachment); - m_hEmpTool->SetLocalOrigin( Vector( 0, 0, 0 ) ); - m_hEmpTool->SetLocalAngles( QAngle( 0, 0, 0 ) ); - - return; - } - else if (pEvent->event == AE_ALYX_EMPTOOL_SEQUENCE) - { - if (!m_hEmpTool) - return; - - CDynamicProp *pEmpTool = dynamic_cast(m_hEmpTool.Get()); - - if (!pEmpTool) - return; - - int iSequence = pEmpTool->LookupSequence( pEvent->options ); - if (iSequence != ACT_INVALID) - { - pEmpTool->PropSetSequence( iSequence ); - } - - return; - } - - switch( pEvent->event ) - { - case 1: - default: - BaseClass::HandleAnimEvent( pEvent ); - break; - } -} - -//========================================================= -// -//========================================================= -bool CNPC_Alyx::CreateBehaviors() -{ - return BaseClass::CreateBehaviors(); -} - - -//========================================================= -// Spawn -//========================================================= -void CNPC_Alyx::Spawn() -{ - BaseClass::Spawn(); - - // If Alyx has a parent, she's currently inside a pod. Prevent her from moving. - if ( GetMoveParent() ) - { - SetMoveType( MOVETYPE_NONE ); - CapabilitiesClear(); - - CapabilitiesAdd( bits_CAP_ANIMATEDFACE | bits_CAP_TURN_HEAD ); - CapabilitiesAdd( bits_CAP_FRIENDLY_DMG_IMMUNE ); - } - else - { - SetupAlyxWithoutParent(); - CreateEmpTool( ); - } - - AddEFlags( EFL_NO_DISSOLVE | EFL_NO_MEGAPHYSCANNON_RAGDOLL | EFL_NO_PHYSCANNON_INTERACTION ); - - m_iHealth = 80; - - NPCInit(); -} - -//========================================================= -// Precache - precaches all resources this NPC needs -//========================================================= -void CNPC_Alyx::Precache() -{ - BaseClass::Precache(); - PrecacheScriptSound( "npc_alyx.die" ); - PrecacheModel( STRING( GetModelName() ) ); - PrecacheModel( "models/alyx_emptool_prop.mdl" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Alyx::SelectModel() -{ - // Alyx is allowed to use multiple models, because she appears in the pod. - // She defaults to her normal model. - const char *szModel = STRING( GetModelName() ); - if (!szModel || !*szModel) - { - SetModelName( AllocPooledString("models/alyx.mdl") ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Alyx::SetupAlyxWithoutParent( void ) -{ - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - - CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_DOORS_GROUP | bits_CAP_TURN_HEAD | bits_CAP_DUCK | bits_CAP_SQUAD ); - CapabilitiesAdd( bits_CAP_USE_WEAPONS ); - CapabilitiesAdd( bits_CAP_ANIMATEDFACE ); - CapabilitiesAdd( bits_CAP_FRIENDLY_DMG_IMMUNE ); - CapabilitiesAdd( bits_CAP_AIM_GUN ); - CapabilitiesAdd( bits_CAP_MOVE_SHOOT ); - CapabilitiesAdd( bits_CAP_USE_SHOT_REGULATOR ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -void CNPC_Alyx::CreateEmpTool( void ) -{ - m_hEmpTool = (CBaseAnimating*)CreateEntityByName( "prop_dynamic" ); - if ( m_hEmpTool ) - { - m_hEmpTool->SetModel( "models/alyx_emptool_prop.mdl" ); - m_hEmpTool->SetName( AllocPooledString("Alyx_Emptool") ); - int iAttachment = LookupAttachment( "Emp_Holster" ); - m_hEmpTool->SetParent(this, iAttachment); - m_hEmpTool->SetOwnerEntity(this); - m_hEmpTool->SetSolid( SOLID_NONE ); - m_hEmpTool->SetLocalOrigin( Vector( 0, 0, 0 ) ); - m_hEmpTool->SetLocalAngles( QAngle( 0, 0, 0 ) ); - m_hEmpTool->Spawn(); - } -} - - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Alyx::PrescheduleThink( void ) -{ - BaseClass::PrescheduleThink(); - - // Figure out if Alyx has just been removed from her parent - if ( GetMoveType() == MOVETYPE_NONE && !GetMoveParent() ) - { - SetupAlyxWithoutParent(); - SetupVPhysicsHull(); - } - - if ( HasCondition( COND_TALKER_PLAYER_DEAD ) ) - { - SpeakIfAllowed( TLK_PLDEAD ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Activity CNPC_Alyx::NPC_TranslateActivity( Activity activity ) -{ - activity = BaseClass::NPC_TranslateActivity( activity ); - if ( activity == ACT_IDLE && (m_NPCState == NPC_STATE_COMBAT || m_NPCState == NPC_STATE_ALERT) ) - { - if (gpGlobals->curtime - m_flLastAttackTime < 3 || gpGlobals->curtime - GetEnemyLastTimeSeen() < 8) - { - activity = ACT_IDLE_ANGRY; - } - } - - return activity; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -void CNPC_Alyx::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - BaseClass::TraceAttack( info, vecDir, ptr ); - - // FIXME: hack until some way of removing decals after healing - m_fNoDamageDecal = true; -} - -//----------------------------------------------------------------------------- - -void CNPC_Alyx::DeathSound( const CTakeDamageInfo &info ) -{ - // Sentences don't play on dead NPCs - SentenceStop(); - - EmitSound( "npc_alyx.die" ); -} - -//========================================================= -// AI Schedules Specific to this NPC -//========================================================= - -AI_BEGIN_CUSTOM_NPC( npc_alyx, CNPC_Alyx ) - - DECLARE_ANIMEVENT( AE_ALYX_EMPTOOL_ATTACHMENT ) - DECLARE_ANIMEVENT( AE_ALYX_EMPTOOL_SEQUENCE ) - -AI_END_CUSTOM_NPC() - diff --git a/game/server/hl2/npc_alyx.h b/game/server/hl2/npc_alyx.h deleted file mode 100644 index fd2eed22a..000000000 --- a/game/server/hl2/npc_alyx.h +++ /dev/null @@ -1,38 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Base combat character with no AI -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#include "ai_baseactor.h" -#include "npc_playercompanion.h" -#include "ai_behavior_holster.h" - -class CNPC_Alyx : public CNPC_PlayerCompanion -{ -public: - DECLARE_CLASS( CNPC_Alyx, CNPC_PlayerCompanion ); - - bool CreateBehaviors(); - void Spawn( void ); - void SelectModel(); - void Precache( void ); - void SetupAlyxWithoutParent( void ); - void CreateEmpTool( void ); - void PrescheduleThink( void ); - Class_T Classify ( void ); - void HandleAnimEvent( animevent_t *pEvent ); - Activity NPC_TranslateActivity ( Activity activity ); - void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - bool ShouldLookForBetterWeapon() { return false; } - bool IsReadinessCapable() { return false; } - void DeathSound( const CTakeDamageInfo &info ); - - EHANDLE m_hEmpTool; - - DECLARE_DATADESC(); - DEFINE_CUSTOM_AI; -}; diff --git a/game/server/hl2/npc_alyx_episodic.cpp b/game/server/hl2/npc_alyx_episodic.cpp deleted file mode 100644 index 5e57f8dbd..000000000 --- a/game/server/hl2/npc_alyx_episodic.cpp +++ /dev/null @@ -1,3613 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Alyx, the female sidekick and love interest that's taking the world by storm! -// -// Try the new Alyx Brite toothpaste! -// Alyx lederhosen! -// -// FIXME: need a better comment block -// -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" -#include "ai_basenpc.h" -#include "ai_hull.h" -#include "ai_basehumanoid.h" -#include "ai_behavior_follow.h" -#include "npc_alyx_episodic.h" -#include "npc_headcrab.h" -#include "npc_BaseZombie.h" -#include "ai_senses.h" -#include "ai_memory.h" -#include "soundent.h" -#include "props.h" -#include "IEffects.h" -#include "globalstate.h" -#include "weapon_physcannon.h" -#include "info_darknessmode_lightsource.h" -#include "sceneentity.h" -#include "hl2_gamerules.h" -#include "scripted.h" -#include "hl2_player.h" -#include "env_alyxemp_shared.h" -#include "basehlcombatweapon.h" -#include "basegrenade_shared.h" -#include "ai_interactions.h" -#include "weapon_flaregun.h" -#include "env_debughistory.h" - -extern Vector PointOnLineNearestPoint(const Vector& vStartPos, const Vector& vEndPos, const Vector& vPoint); - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -bool g_HackOutland10DamageHack; - -int ACT_ALYX_DRAW_TOOL; -int ACT_ALYX_IDLE_TOOL; -int ACT_ALYX_ZAP_TOOL; -int ACT_ALYX_HOLSTER_TOOL; -int ACT_ALYX_PICKUP_RACK; - -string_t CLASSNAME_ALYXGUN; -string_t CLASSNAME_SMG1; -string_t CLASSNAME_SHOTGUN; -string_t CLASSNAME_AR2; - -bool IsInCommentaryMode( void ); - -#define ALYX_BREATHING_VOLUME_MAX 1.0 - -#define ALYX_DARKNESS_LOST_PLAYER_DIST ( 120 * 120 ) // 12 feet - -#define ALYX_MIN_MOB_DIST_SQR Square(120) // Any enemy closer than this adds to the 'mob' -#define ALYX_MIN_CONSIDER_DIST Square(1200) // Only enemies within this range are counted and considered to generate AI speech - -#define CONCEPT_ALYX_REQUEST_ITEM "TLK_ALYX_REQUEST_ITEM" -#define CONCEPT_ALYX_INTERACTION_DONE "TLK_ALYX_INTERACTION_DONE" -#define CONCEPT_ALYX_CANCEL_INTERACTION "TLK_ALYX_CANCEL_INTERACTION" - -#define ALYX_MIN_ENEMY_DIST_TO_CROUCH 360 // Minimum distance that our enemy must be for me to crouch -#define ALYX_MIN_ENEMY_HEALTH_TO_CROUCH 15 -#define ALYX_CROUCH_DELAY 5 // Time after crouching before Alyx will crouch again - -//----------------------------------------------------------------------------- -// Interactions -//----------------------------------------------------------------------------- -extern int g_interactionZombieMeleeWarning; - -LINK_ENTITY_TO_CLASS( npc_alyx, CNPC_Alyx ); - -BEGIN_DATADESC( CNPC_Alyx ) - - DEFINE_FIELD( m_hEmpTool, FIELD_EHANDLE ), - DEFINE_FIELD( m_hHackTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_hStealthLookTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_bInteractionAllowed, FIELD_BOOLEAN ), - DEFINE_FIELD( m_fTimeNextSearchForInteractTargets, FIELD_TIME ), - DEFINE_FIELD( m_bDarknessSpeechAllowed, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bIsEMPHolstered, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bIsFlashlightBlind, FIELD_BOOLEAN ), - DEFINE_FIELD( m_fStayBlindUntil, FIELD_TIME ), - DEFINE_FIELD( m_flDontBlindUntil, FIELD_TIME ), - DEFINE_FIELD( m_bSpokeLostPlayerInDarkness, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bPlayerFlashlightState, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bHadCondSeeEnemy, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iszCurrentBlindScene, FIELD_STRING ), - DEFINE_FIELD( m_fTimeUntilNextDarknessFoundPlayer, FIELD_TIME ), - DEFINE_FIELD( m_fCombatStartTime, FIELD_TIME ), - DEFINE_FIELD( m_fCombatEndTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextCrouchTime, FIELD_TIME ), - DEFINE_FIELD( m_WeaponType, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_bShouldHaveEMP, FIELD_BOOLEAN, "ShouldHaveEMP" ), - - DEFINE_SOUNDPATCH( m_sndDarknessBreathing ), - - DEFINE_EMBEDDED( m_SpeechWatch_LostPlayer ), - DEFINE_EMBEDDED( m_SpeechTimer_HeardSound ), - DEFINE_EMBEDDED( m_SpeechWatch_SoundDelay ), - DEFINE_EMBEDDED( m_SpeechWatch_BreathingRamp ), - DEFINE_EMBEDDED( m_SpeechWatch_FoundPlayer ), - - DEFINE_EMBEDDED( m_MoveMonitor ), - - DEFINE_INPUTFUNC( FIELD_VOID, "DisallowInteraction", InputDisallowInteraction ), - DEFINE_INPUTFUNC( FIELD_VOID, "AllowInteraction", InputAllowInteraction ), - DEFINE_INPUTFUNC( FIELD_STRING, "GiveWeapon", InputGiveWeapon ), - DEFINE_INPUTFUNC( FIELD_BOOLEAN, "AllowDarknessSpeech", InputAllowDarknessSpeech ), - DEFINE_INPUTFUNC( FIELD_BOOLEAN, "GiveEMP", InputGiveEMP ), - DEFINE_INPUTFUNC( FIELD_VOID, "VehiclePunted", InputVehiclePunted ), - DEFINE_INPUTFUNC( FIELD_VOID, "OutsideTransition", InputOutsideTransition ), - - DEFINE_OUTPUT( m_OnFinishInteractWithObject, "OnFinishInteractWithObject" ), - DEFINE_OUTPUT( m_OnPlayerUse, "OnPlayerUse" ), - - DEFINE_USEFUNC( Use ), - -END_DATADESC() - -#define ALYX_FEAR_ZOMBIE_DIST_SQR Square(60) -#define ALYX_FEAR_ANTLION_DIST_SQR Square(360) - -//----------------------------------------------------------------------------- -// Anim events -//----------------------------------------------------------------------------- -static int AE_ALYX_EMPTOOL_ATTACHMENT; -static int AE_ALYX_EMPTOOL_SEQUENCE; -static int AE_ALYX_EMPTOOL_USE; -static int COMBINE_AE_BEGIN_ALTFIRE; -static int COMBINE_AE_ALTFIRE; - -ConVar npc_alyx_readiness( "npc_alyx_readiness", "1" ); -ConVar npc_alyx_force_stop_moving( "npc_alyx_force_stop_moving", "1" ); -ConVar npc_alyx_readiness_transitions( "npc_alyx_readiness_transitions", "1" ); -ConVar npc_alyx_crouch( "npc_alyx_crouch", "1" ); - -// global pointer to Alyx for fast lookups -CEntityClassList g_AlyxList; -template <> CNPC_Alyx *CEntityClassList::m_pClassList = NULL; - -//========================================================= -// initialize Alyx before keyvalues are processed -//========================================================= -CNPC_Alyx::CNPC_Alyx() -{ - g_AlyxList.Insert(this); - // defaults to having an EMP - m_bShouldHaveEMP = true; -} - -CNPC_Alyx::~CNPC_Alyx( ) -{ - g_AlyxList.Remove(this); -} - -//========================================================= -// Classify - indicates this NPC's place in the -// relationship table. -//========================================================= -Class_T CNPC_Alyx::Classify ( void ) -{ - return CLASS_PLAYER_ALLY_VITAL; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Alyx::FValidateHintType( CAI_Hint *pHint ) -{ - switch( pHint->HintType() ) - { - case HINT_WORLD_VISUALLY_INTERESTING: - return true; - break; - case HINT_WORLD_VISUALLY_INTERESTING_STEALTH: - return true; - break; - default: - break; - } - - return BaseClass::FValidateHintType( pHint ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Alyx::ObjectCaps() -{ - int caps = BaseClass::ObjectCaps(); - - if( m_FuncTankBehavior.IsMounted() ) - { - caps &= ~FCAP_IMPULSE_USE; - } - - return caps; -} - -//========================================================= -// HandleAnimEvent - catches the NPC-specific messages -// that occur when tagged animation frames are played. -//========================================================= -void CNPC_Alyx::HandleAnimEvent( animevent_t *pEvent ) -{ - if (pEvent->event == AE_ALYX_EMPTOOL_ATTACHMENT) - { - if (!m_hEmpTool) - { - // Old savegame? - CreateEmpTool(); - if (!m_hEmpTool) - return; - } - - int iAttachment = LookupAttachment( pEvent->options ); - m_hEmpTool->SetParent(this, iAttachment); - m_hEmpTool->SetLocalOrigin( Vector( 0, 0, 0 ) ); - m_hEmpTool->SetLocalAngles( QAngle( 0, 0, 0 ) ); - - if( !stricmp( pEvent->options, "Emp_Holster" ) ) - { - SetEMPHolstered(true); - } - else - { - SetEMPHolstered(false); - } - - return; - } - else if (pEvent->event == AE_ALYX_EMPTOOL_SEQUENCE) - { - if (!m_hEmpTool) - return; - - CDynamicProp *pEmpTool = dynamic_cast(m_hEmpTool.Get()); - - if (!pEmpTool) - return; - - int iSequence = pEmpTool->LookupSequence( pEvent->options ); - if (iSequence != ACT_INVALID) - { - pEmpTool->PropSetSequence( iSequence ); - } - - return; - } - else if (pEvent->event == AE_ALYX_EMPTOOL_USE) - { - if( m_OperatorBehavior.IsGoalReady() ) - { - if( m_OperatorBehavior.m_hContextTarget.Get() != NULL ) - { - EmpZapTarget( m_OperatorBehavior.m_hContextTarget ); - } - } - return; - } - else if ( pEvent->event == COMBINE_AE_BEGIN_ALTFIRE ) - { - EmitSound( "Weapon_CombineGuard.Special1" ); - return; - } - else if ( pEvent->event == COMBINE_AE_ALTFIRE ) - { - animevent_t fakeEvent; - - fakeEvent.pSource = this; - fakeEvent.event = EVENT_WEAPON_AR2_ALTFIRE; - GetActiveWeapon()->Operator_HandleAnimEvent( &fakeEvent, this ); - //m_iNumGrenades--; - - return; - } - - switch( pEvent->event ) - { - case 1: - default: - BaseClass::HandleAnimEvent( pEvent ); - break; - } -} - -//========================================================= -// Returns a pointer to Alyx's entity -//========================================================= -CNPC_Alyx *CNPC_Alyx::GetAlyx( void ) -{ - return g_AlyxList.m_pClassList; -} - -//========================================================= -// -//========================================================= -bool CNPC_Alyx::CreateBehaviors() -{ - AddBehavior( &m_FuncTankBehavior ); - bool result = BaseClass::CreateBehaviors(); - - return result; -} - - -//========================================================= -// Spawn -//========================================================= -void CNPC_Alyx::Spawn() -{ - BaseClass::Spawn(); - - // If Alyx has a parent, she's currently inside a pod. Prevent her from moving. - if ( GetMoveParent() ) - { - SetMoveType( MOVETYPE_NONE ); - CapabilitiesClear(); - - CapabilitiesAdd( bits_CAP_ANIMATEDFACE | bits_CAP_TURN_HEAD ); - CapabilitiesAdd( bits_CAP_FRIENDLY_DMG_IMMUNE ); - } - else - { - SetupAlyxWithoutParent(); - CreateEmpTool( ); - } - - AddEFlags( EFL_NO_DISSOLVE | EFL_NO_MEGAPHYSCANNON_RAGDOLL | EFL_NO_PHYSCANNON_INTERACTION ); - - m_iHealth = 80; - m_bloodColor = DONT_BLEED; - - NPCInit(); - - SetUse( &CNPC_Alyx::Use ); - - m_bInteractionAllowed = true; - - m_fTimeNextSearchForInteractTargets = gpGlobals->curtime; - - SetEMPHolstered(true); - - m_bDontPickupWeapons = true; - - m_bDarknessSpeechAllowed = true; - - m_fCombatStartTime = 0.0f; - m_fCombatEndTime = 0.0f; - - m_AnnounceAttackTimer.Set( 3, 5 ); -} - -//========================================================= -// Precache - precaches all resources this NPC needs -//========================================================= -void CNPC_Alyx::Precache() -{ - BaseClass::Precache(); - PrecacheScriptSound( "npc_alyx.die" ); - PrecacheModel( STRING( GetModelName() ) ); - PrecacheModel( "models/alyx_emptool_prop.mdl" ); - - // For hacking - PrecacheScriptSound( "DoSpark" ); - PrecacheScriptSound( "npc_alyx.starthacking" ); - PrecacheScriptSound( "npc_alyx.donehacking" ); - PrecacheScriptSound( "npc_alyx.readytohack" ); - PrecacheScriptSound( "npc_alyx.interruptedhacking" ); - PrecacheScriptSound( "ep_01.al_dark_breathing01" ); - PrecacheScriptSound( "Weapon_CombineGuard.Special1" ); - - UTIL_PrecacheOther( "env_alyxemp" ); - - CLASSNAME_ALYXGUN = AllocPooledString( "weapon_alyxgun" ); - CLASSNAME_SMG1 = AllocPooledString( "weapon_smg1" ); - CLASSNAME_SHOTGUN = AllocPooledString( "weapon_shotgun" ); - CLASSNAME_AR2 = AllocPooledString( "weapon_ar2" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Alyx::Activate( void ) -{ - // Alyx always kicks her health back up to full after loading a savegame. - // Avoids problems with players saving the game in places where she dies immediately afterwards. - m_iHealth = 80; - - BaseClass::Activate(); - - // Alyx always assumes she has said hello to Gordon! - SetSpokeConcept( TLK_HELLO, NULL, false ); - - // Add my personal concepts - CAI_AllySpeechManager *pSpeechManager = GetAllySpeechManager(); - - if( pSpeechManager ) - { - ConceptInfo_t conceptRequestItem = - { - CONCEPT_ALYX_REQUEST_ITEM, SPEECH_IMPORTANT, -1, -1, -1, -1, -1, -1, AICF_TARGET_PLAYER - }; - - pSpeechManager->AddCustomConcept( conceptRequestItem ); - } - - // cleanup savegames that may not have this set - if (m_hEmpTool) - { - m_hEmpTool->AddEffects( EF_PARENT_ANIMATES ); - } - - m_WeaponType = ComputeWeaponType(); - - // !!!HACKHACK for Overwatch, If we're in ep2_outland_10, do half damage to Combine - // Be advised, this will also happen in 10a, but this is not a problem. - g_HackOutland10DamageHack = false; - if( !Q_strnicmp( STRING(gpGlobals->mapname), "ep2_outland_10", 14) ) - { - g_HackOutland10DamageHack = true; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Alyx::StopLoopingSounds( void ) -{ - CSoundEnvelopeController::GetController().SoundDestroy( m_sndDarknessBreathing ); - m_sndDarknessBreathing = NULL; - - BaseClass::StopLoopingSounds(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Alyx::SelectModel() -{ - // Alyx is allowed to use multiple models, because she appears in the pod. - // She defaults to her normal model. - const char *szModel = STRING( GetModelName() ); - if (!szModel || !*szModel) - { - SetModelName( AllocPooledString("models/alyx.mdl") ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Alyx::SetupAlyxWithoutParent( void ) -{ - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - - CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_DOORS_GROUP | bits_CAP_TURN_HEAD | bits_CAP_DUCK | bits_CAP_SQUAD ); - CapabilitiesAdd( bits_CAP_USE_WEAPONS ); - CapabilitiesAdd( bits_CAP_ANIMATEDFACE ); - CapabilitiesAdd( bits_CAP_FRIENDLY_DMG_IMMUNE ); - CapabilitiesAdd( bits_CAP_AIM_GUN ); - CapabilitiesAdd( bits_CAP_MOVE_SHOOT ); - CapabilitiesAdd( bits_CAP_USE_SHOT_REGULATOR ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Create and initialized Alyx's EMP tool -//----------------------------------------------------------------------------- - -void CNPC_Alyx::CreateEmpTool( void ) -{ - if (!m_bShouldHaveEMP || m_hEmpTool) - return; - - m_hEmpTool = (CBaseAnimating*)CreateEntityByName( "prop_dynamic" ); - if ( m_hEmpTool ) - { - m_hEmpTool->SetModel( "models/alyx_emptool_prop.mdl" ); - m_hEmpTool->SetName( AllocPooledString("Alyx_Emptool") ); - int iAttachment = LookupAttachment( "Emp_Holster" ); - m_hEmpTool->SetParent(this, iAttachment); - m_hEmpTool->SetOwnerEntity(this); - m_hEmpTool->SetSolid( SOLID_NONE ); - m_hEmpTool->SetLocalOrigin( Vector( 0, 0, 0 ) ); - m_hEmpTool->SetLocalAngles( QAngle( 0, 0, 0 ) ); - m_hEmpTool->AddSpawnFlags(SF_DYNAMICPROP_NO_VPHYSICS); - m_hEmpTool->AddEffects( EF_PARENT_ANIMATES ); - m_hEmpTool->Spawn(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Map input to create or destroy alyx's EMP tool -//----------------------------------------------------------------------------- - -void CNPC_Alyx::InputGiveEMP( inputdata_t &inputdata ) -{ - m_bShouldHaveEMP = inputdata.value.Bool(); - if (m_bShouldHaveEMP) - { - if (!m_hEmpTool) - { - CreateEmpTool( ); - } - } - else - { - if (m_hEmpTool) - { - UTIL_Remove( m_hEmpTool ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -struct ReadinessTransition_t -{ - int iPreviousLevel; - int iCurrentLevel; - Activity requiredActivity; - Activity transitionActivity; -}; - - -void CNPC_Alyx::ReadinessLevelChanged( int iPriorLevel ) -{ - BaseClass::ReadinessLevelChanged( iPriorLevel ); - - // When we drop from agitated to stimulated, stand up if we were crouching. - if ( iPriorLevel == AIRL_AGITATED && GetReadinessLevel() == AIRL_STIMULATED ) - { - //Warning("CROUCH: Standing, dropping back to stimulated.\n" ); - Stand(); - } - - if ( GetActiveWeapon() == NULL ) - return; - - //If Alyx is going from Relaxed to Agitated or Stimulated, let her raise her weapon before she's able to fire. - if ( iPriorLevel == AIRL_RELAXED && GetReadinessLevel() > iPriorLevel ) - { - GetShotRegulator()->FireNoEarlierThan( gpGlobals->curtime + 0.5 ); - } - - // FIXME: Are there certain animations that we DO want to interrupt? - if ( HasActiveLayer() ) - return; - - if ( npc_alyx_readiness_transitions.GetBool() ) - { - // We don't have crouching readiness transitions yet - if ( IsCrouching() ) - return; - - static ReadinessTransition_t readinessTransitions[] = - { - //Previous Readiness level - Current Readiness Level - Activity NPC needs to be playing - Gesture to play - { AIRL_RELAXED, AIRL_STIMULATED, ACT_IDLE, ACT_READINESS_RELAXED_TO_STIMULATED, }, - { AIRL_RELAXED, AIRL_STIMULATED, ACT_WALK, ACT_READINESS_RELAXED_TO_STIMULATED_WALK, }, - { AIRL_AGITATED, AIRL_STIMULATED, ACT_IDLE, ACT_READINESS_AGITATED_TO_STIMULATED, }, - { AIRL_STIMULATED, AIRL_RELAXED, ACT_IDLE, ACT_READINESS_STIMULATED_TO_RELAXED, } - }; - - for ( size_t i = 0; i < ARRAYSIZE( readinessTransitions ); i++ ) - { - if ( GetIdealActivity() != readinessTransitions[i].requiredActivity ) - continue; - - Activity translatedTransitionActivity = Weapon_TranslateActivity( readinessTransitions[i].transitionActivity ); - - if ( translatedTransitionActivity == ACT_INVALID || translatedTransitionActivity == readinessTransitions[i].transitionActivity ) - continue; - - Activity finalActivity = TranslateActivityReadiness( translatedTransitionActivity ); - - if ( iPriorLevel == readinessTransitions[i].iPreviousLevel && GetReadinessLevel() == readinessTransitions[i].iCurrentLevel ) - { - RestartGesture( finalActivity ); - break; - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Alyx::PrescheduleThink( void ) -{ - BaseClass::PrescheduleThink(); - - // Figure out if Alyx has just been removed from her parent - if ( GetMoveType() == MOVETYPE_NONE && !GetMoveParent() ) - { - // Don't confuse the passenger behavior with just removing Alyx's parent! - if ( m_PassengerBehavior.IsEnabled() == false ) - { - SetupAlyxWithoutParent(); - SetupVPhysicsHull(); - } - } - - // If Alyx is in combat, and she doesn't have her gun out, fetch it - if ( GetState() == NPC_STATE_COMBAT && IsWeaponHolstered() && !m_FuncTankBehavior.IsRunning() ) - { - SetDesiredWeaponState( DESIREDWEAPONSTATE_UNHOLSTERED ); - } - - // If we're in stealth mode, and we can still see the stealth node, keep using it - if ( GetReadinessLevel() == AIRL_STEALTH ) - { - if ( m_hStealthLookTarget && !m_hStealthLookTarget->IsDisabled() ) - { - if ( m_hStealthLookTarget->IsInNodeFOV(this) && FVisible( m_hStealthLookTarget ) ) - return; - } - - // Break out of stealth mode - SetReadinessLevel( AIRL_STIMULATED, true, true ); - ClearLookTarget( m_hStealthLookTarget ); - m_hStealthLookTarget = NULL; - } - - // If we're being blinded by the flashlight, see if we should stop - if ( m_bIsFlashlightBlind ) - { - // we used to have a bug where if we tried to remove alyx from the blind scene before it got loaded asynchronously, - // she would get stuck in the animation with m_bIsFlashlightBlind set to false. that should be fixed, but just to - // be sure, we wait a bit to prevent this from happening. - if ( m_fStayBlindUntil < gpGlobals->curtime ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); - if ( pPlayer && (!CanBeBlindedByFlashlight( true ) || !pPlayer->IsIlluminatedByFlashlight(this, NULL ) || !PlayerFlashlightOnMyEyes( pPlayer )) && - !BlindedByFlare() ) - { - // Remove the actor from the flashlight scene - ADD_DEBUG_HISTORY( HISTORY_ALYX_BLIND, UTIL_VarArgs( "(%0.2f) Alyx: end blind scene '%s'\n", gpGlobals->curtime, STRING(m_iszCurrentBlindScene) ) ); - RemoveActorFromScriptedScenes( this, true, false, STRING(m_iszCurrentBlindScene) ); - - // Allow firing again, but prevent myself from firing until I'm done - GetShotRegulator()->EnableShooting(); - GetShotRegulator()->FireNoEarlierThan( gpGlobals->curtime + 1.0 ); - - m_bIsFlashlightBlind = false; - m_flDontBlindUntil = gpGlobals->curtime + RandomFloat( 1, 3 ); - } - } - } - else - { - CheckBlindedByFlare(); - } -} - -//----------------------------------------------------------------------------- -// Periodically look for opportunities to interact with objects in the world. -// Right now Alyx only interacts with things the player picks up with -// physcannon. -//----------------------------------------------------------------------------- -#define ALYX_INTERACT_SEARCH_FREQUENCY 1.0f // seconds -void CNPC_Alyx::SearchForInteractTargets() -{ - if( m_fTimeNextSearchForInteractTargets > gpGlobals->curtime ) - { - return; - } - - m_fTimeNextSearchForInteractTargets = gpGlobals->curtime + ALYX_INTERACT_SEARCH_FREQUENCY; - - // Ensure player can be seen. - if( !HasCondition( COND_SEE_PLAYER) ) - { - //Msg("ALYX Can't interact: can't see player\n"); - return; - } - - CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); - - if( !pPlayer ) - { - return; - } - - CBaseEntity *pProspect = PhysCannonGetHeldEntity(pPlayer->GetActiveWeapon()); - - if( !pProspect ) - { - //Msg("ALYX Can't interact: player not holding anything\n"); - return; - } - - if( !IsValidInteractTarget(pProspect) ) - { - //Msg("ALYX Can't interact: player holding an invalid object\n"); - return; - } - - SetInteractTarget(pProspect); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Alyx::GatherConditions() -{ - BaseClass::GatherConditions(); - - if( HasCondition( COND_HEAR_DANGER ) ) - { - // Don't let Alyx worry about combat sounds if she's panicking - // from danger sounds. This prevents her from running ALERT_FACE_BEST_SOUND - // as soon as a grenade explodes (which makes a loud combat sound). If Alyx - // is NOT panicking over a Danger sound, she'll hear the combat sounds as normal. - ClearCondition( COND_HEAR_COMBAT ); - } - - // Update flashlight state - ClearCondition( COND_ALYX_PLAYER_FLASHLIGHT_EXPIRED ); - ClearCondition( COND_ALYX_PLAYER_TURNED_ON_FLASHLIGHT ); - ClearCondition( COND_ALYX_PLAYER_TURNED_OFF_FLASHLIGHT ); - CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); - if ( pPlayer ) - { - bool bFlashlightState = pPlayer->FlashlightIsOn() != 0; - if ( bFlashlightState != m_bPlayerFlashlightState ) - { - if ( bFlashlightState ) - { - SetCondition( COND_ALYX_PLAYER_TURNED_ON_FLASHLIGHT ); - } - else - { - // If the power level is low, consider it expired, due - // to it running out or the player turning it off in anticipation. - CHL2_Player *pHLPlayer = assert_cast( pPlayer ); - if ( pHLPlayer->SuitPower_GetCurrentPercentage() < 15 ) - { - SetCondition( COND_ALYX_PLAYER_FLASHLIGHT_EXPIRED ); - } - else - { - SetCondition( COND_ALYX_PLAYER_TURNED_OFF_FLASHLIGHT ); - } - } - - m_bPlayerFlashlightState = bFlashlightState; - } - } - - - if ( m_NPCState == NPC_STATE_COMBAT ) - { - DoCustomCombatAI(); - } - - if( HasInteractTarget() ) - { - // Check that any current interact target is still valid. - if( !IsValidInteractTarget(GetInteractTarget()) ) - { - SetInteractTarget(NULL); - } - } - - // This is not an else...if because the code above could have started - // with an interact target and ended without one. - if( !HasInteractTarget() ) - { - SearchForInteractTargets(); - } - - // Set up our interact conditions. - if( HasInteractTarget() ) - { - if( CanInteractWithTarget(GetInteractTarget()) ) - { - SetCondition(COND_ALYX_CAN_INTERACT_WITH_TARGET); - ClearCondition(COND_ALYX_CAN_NOT_INTERACT_WITH_TARGET); - } - else - { - SetCondition(COND_ALYX_CAN_NOT_INTERACT_WITH_TARGET); - ClearCondition(COND_ALYX_CAN_INTERACT_WITH_TARGET); - } - - SetCondition( COND_ALYX_HAS_INTERACT_TARGET ); - ClearCondition( COND_ALYX_NO_INTERACT_TARGET ); - } - else - { - SetCondition( COND_ALYX_NO_INTERACT_TARGET ); - ClearCondition( COND_ALYX_HAS_INTERACT_TARGET ); - } - - // Check for explosions! - if( HasCondition(COND_HEAR_COMBAT) ) - { - CSound *pSound = GetBestSound(); - - if ( IsInAVehicle() == false ) // For now, don't do these animations while in the vehicle - { - if( (pSound->SoundTypeNoContext() & SOUND_COMBAT) && (pSound->SoundContext() & SOUND_CONTEXT_EXPLOSION) ) - { - if ( HasShotgun() ) - { - if ( !IsPlayingGesture(ACT_GESTURE_FLINCH_BLAST_SHOTGUN) && !IsPlayingGesture(ACT_GESTURE_FLINCH_BLAST_DAMAGED_SHOTGUN) ) - { - RestartGesture( ACT_GESTURE_FLINCH_BLAST_SHOTGUN ); - GetShotRegulator()->FireNoEarlierThan( gpGlobals->curtime + SequenceDuration( ACT_GESTURE_FLINCH_BLAST_SHOTGUN ) + 0.5f ); // Allow another second for Alyx to bring her weapon to bear after the flinch. - } - } - else - { - if ( !IsPlayingGesture(ACT_GESTURE_FLINCH_BLAST) && !IsPlayingGesture(ACT_GESTURE_FLINCH_BLAST_DAMAGED) ) - { - RestartGesture( ACT_GESTURE_FLINCH_BLAST ); - GetShotRegulator()->FireNoEarlierThan( gpGlobals->curtime + SequenceDuration( ACT_GESTURE_FLINCH_BLAST ) + 0.5f ); // Allow another second for Alyx to bring her weapon to bear after the flinch. - } - } - } - } - } - - // ROBIN: This was here to solve a problem in a playtest. We've since found what we think was the cause. - // It's a useful piece of debug to have lying there, so I've left it in. - if ( (GetFlags() & FL_FLY) && m_NPCState != NPC_STATE_SCRIPT && !m_ActBusyBehavior.IsActive() && !m_PassengerBehavior.IsEnabled() ) - { - Warning( "Removed FL_FLY from Alyx, who wasn't running a script or actbusy. Time %.2f, map %s.\n", gpGlobals->curtime, STRING(gpGlobals->mapname) ); - RemoveFlag( FL_FLY ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Alyx::ShouldPlayerAvoid( void ) -{ - if( IsCurSchedule(SCHED_ALYX_NEW_WEAPON, false) ) - return true; - -#if 1 - if( IsCurSchedule( SCHED_PC_GET_OFF_COMPANION, false) ) - { - CBaseEntity *pGroundEnt = GetGroundEntity(); - if( pGroundEnt != NULL && pGroundEnt->IsPlayer() ) - { - if( GetAbsOrigin().z < pGroundEnt->EyePosition().z ) - return true; - } - } -#endif - return BaseClass::ShouldPlayerAvoid(); -} - -//----------------------------------------------------------------------------- -// Just heard a gunfire sound. Try to figure out how much we should know -// about it. -//----------------------------------------------------------------------------- -void CNPC_Alyx::AnalyzeGunfireSound( CSound *pSound ) -{ - Assert( pSound != NULL ); - - if( GetState() != NPC_STATE_ALERT && GetState() != NPC_STATE_IDLE ) - { - // Only have code for IDLE and ALERT now. - return; - } - - // Have to verify a bunch of stuff about the sound. It must have a valid BaseCombatCharacter as the owner, - // must have a valid target, and we need a valid pointer to the player. - if( pSound->m_hOwner.Get() == NULL ) - return; - - if( pSound->m_hTarget.Get() == NULL ) - return; - - CBaseCombatCharacter *pSoundOriginBCC = pSound->m_hOwner->MyCombatCharacterPointer(); - if( pSoundOriginBCC == NULL ) - return; - - CBaseEntity *pSoundTarget = pSound->m_hTarget.Get(); - - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - - Assert( pPlayer != NULL ); - - if( pSoundTarget == this ) - { - // The shooter is firing at me. Assume if Alyx can hear the gunfire, she can deduce its origin. - UpdateEnemyMemory( pSoundOriginBCC, pSoundOriginBCC->GetAbsOrigin(), this ); - } - else if( pSoundTarget == pPlayer ) - { - // The shooter is firing at the player. Assume Alyx can deduce the origin if the player COULD see the origin, and Alyx COULD see the player. - if( pPlayer->FVisible(pSoundOriginBCC) && FVisible(pPlayer) ) - { - UpdateEnemyMemory( pSoundOriginBCC, pSoundOriginBCC->GetAbsOrigin(), this ); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Alyx::IsValidEnemy( CBaseEntity *pEnemy ) -{ - if ( HL2GameRules()->IsAlyxInDarknessMode() ) - { - if ( !CanSeeEntityInDarkness( pEnemy ) ) - return false; - } - - // Alyx can only take a stalker as her enemy which is angry at the player or her. - if ( pEnemy->Classify() == CLASS_STALKER ) - { - if( !pEnemy->GetEnemy() ) - { - return false; - } - - if( pEnemy->GetEnemy() != this && !pEnemy->GetEnemy()->IsPlayer() ) - { - return false; - } - } - - if ( m_AssaultBehavior.IsRunning() && IsTurret( pEnemy ) ) - { - CBaseCombatCharacter *pBCC = dynamic_cast(pEnemy); - - if ( pBCC != NULL && !pBCC->FInViewCone(this) ) - { - // Don't let turrets that can't shoot me distract me from my assault behavior. - // This fixes a very specific problem that appeared in Episode 2 map ep2_outland_09 - // Where Alyx wouldn't terminate an assault while standing on an assault point because - // she was afraid of a turret that was visible from the assault point, but facing the - // other direction and thus not a threat. - return false; - } - } - - return BaseClass::IsValidEnemy(pEnemy); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Alyx::Event_Killed( const CTakeDamageInfo &info ) -{ - // Destroy our EMP tool since it won't follow us onto the ragdoll anyway - if ( m_hEmpTool != NULL ) - { - UTIL_Remove( m_hEmpTool ); - } - - BaseClass::Event_Killed( info ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Alyx::Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info ) -{ - // comment on killing npc's - if ( pVictim->IsNPC() ) - { - SpeakIfAllowed( TLK_ALYX_ENEMY_DEAD ); - } - - // Alyx builds a proxy for the dead enemy so she has something to shoot at for a short time after - // the enemy ragdolls. - if( !(pVictim->GetFlags() & FL_ONGROUND) || pVictim->GetMoveType() != MOVETYPE_STEP ) - { - // Don't fire up in the air, since the dead enemy will have fallen. - return; - } - - if( pVictim->GetAbsOrigin().DistTo(GetAbsOrigin()) < 96.0f ) - { - // Don't shoot at an enemy corpse that dies very near to me. This will prevent Alyx attacking - // Other nearby enemies. - return; - } - - if( !HasShotgun() ) - { - CAI_BaseNPC *pTarget = CreateCustomTarget( pVictim->GetAbsOrigin(), 2.0f ); - - AddEntityRelationship( pTarget, IRelationType(pVictim), IRelationPriority(pVictim) ); - - // Update or Create a memory entry for this target and make Alyx think she's seen this target recently. - // This prevents the baseclass from not recognizing this target and forcing Alyx into - // SCHED_WAKE_ANGRY, which wastes time and causes her to change animation sequences rapidly. - GetEnemies()->UpdateMemory( GetNavigator()->GetNetwork(), pTarget, pTarget->GetAbsOrigin(), 0.0f, true ); - AI_EnemyInfo_t *pMemory = GetEnemies()->Find( pTarget ); - - if( pMemory ) - { - // Pretend we've known about this target longer than we really have. - pMemory->timeFirstSeen = gpGlobals->curtime - 10.0f; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Called by enemy NPC's when they are ignited -// Input : pVictim - entity that was ignited -//----------------------------------------------------------------------------- -void CNPC_Alyx::EnemyIgnited( CAI_BaseNPC *pVictim ) -{ - if ( FVisible( pVictim ) ) - { - SpeakIfAllowed( TLK_ENEMY_BURNING ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Called by combine balls when they're socketed -// Input : pVictim - entity killed by player -//----------------------------------------------------------------------------- -void CNPC_Alyx::CombineBallSocketed( int iNumBounces ) -{ - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - - if ( !pPlayer || !FVisible(pPlayer) ) - { - return; - } - - // set up the speech modifiers - CFmtStrN<128> modifiers( "num_bounces:%d", iNumBounces ); - - // fire off a ball socketed concept - SpeakIfAllowed( TLK_BALLSOCKETED, modifiers ); -} - -//----------------------------------------------------------------------------- -// Purpose: If we're a passenger in a vehicle -//----------------------------------------------------------------------------- -bool CNPC_Alyx::RunningPassengerBehavior( void ) -{ - // Must be active and not outside the vehicle - if ( m_PassengerBehavior.IsRunning() && m_PassengerBehavior.GetPassengerState() != PASSENGER_STATE_OUTSIDE ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Handle "mobbed" combat condition when Alyx is overwhelmed by force -//----------------------------------------------------------------------------- -void CNPC_Alyx::DoMobbedCombatAI( void ) -{ - AIEnemiesIter_t iter; - - float visibleEnemiesScore = 0.0f; - float closeEnemiesScore = 0.0f; - - for ( AI_EnemyInfo_t *pEMemory = GetEnemies()->GetFirst(&iter); pEMemory != NULL; pEMemory = GetEnemies()->GetNext(&iter) ) - { - if ( IRelationType( pEMemory->hEnemy ) != D_NU && IRelationType( pEMemory->hEnemy ) != D_LI && pEMemory->hEnemy->GetAbsOrigin().DistToSqr(GetAbsOrigin()) <= ALYX_MIN_CONSIDER_DIST ) - { - if( pEMemory->hEnemy && pEMemory->hEnemy->IsAlive() && gpGlobals->curtime - pEMemory->timeLastSeen <= 0.5f && pEMemory->hEnemy->Classify() != CLASS_BULLSEYE ) - { - if( pEMemory->hEnemy->GetAbsOrigin().DistToSqr(GetAbsOrigin()) <= ALYX_MIN_MOB_DIST_SQR ) - { - closeEnemiesScore += 1.0f; - } - else - { - visibleEnemiesScore += 1.0f; - } - } - } - } - - if( closeEnemiesScore > 2 ) - { - SetCondition( COND_MOBBED_BY_ENEMIES ); - - // mark anyone in the mob as having mobbed me - for ( AI_EnemyInfo_t *pEMemory = GetEnemies()->GetFirst(&iter); pEMemory != NULL; pEMemory = GetEnemies()->GetNext(&iter) ) - { - if ( pEMemory->bMobbedMe ) - continue; - - if ( IRelationType( pEMemory->hEnemy ) != D_NU && IRelationType( pEMemory->hEnemy ) != D_LI && pEMemory->hEnemy->GetAbsOrigin().DistToSqr(GetAbsOrigin()) <= ALYX_MIN_CONSIDER_DIST ) - { - if( pEMemory->hEnemy && pEMemory->hEnemy->IsAlive() && gpGlobals->curtime - pEMemory->timeLastSeen <= 0.5f && pEMemory->hEnemy->Classify() != CLASS_BULLSEYE ) - { - if( pEMemory->hEnemy->GetAbsOrigin().DistToSqr(GetAbsOrigin()) <= ALYX_MIN_MOB_DIST_SQR ) - { - pEMemory->bMobbedMe = true; - } - } - } - } - } - else - { - ClearCondition( COND_MOBBED_BY_ENEMIES ); - } - - // Alyx's gun can never run out of ammo. Allow Alyx to ignore LOW AMMO warnings - // if she's in a close quarters fight with several enemies. She'll attempt to reload - // as soon as her combat situation is less pressing. - if( HasCondition( COND_MOBBED_BY_ENEMIES ) ) - { - ClearCondition( COND_LOW_PRIMARY_AMMO ); - } - - // Say a combat thing - if( HasCondition( COND_MOBBED_BY_ENEMIES ) ) - { - SpeakIfAllowed( TLK_MOBBED ); - } - else if( visibleEnemiesScore > 4 ) - { - SpeakIfAllowed( TLK_MANY_ENEMIES ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Custom AI for Alyx while in combat -//----------------------------------------------------------------------------- -void CNPC_Alyx::DoCustomCombatAI( void ) -{ - // Only run the following code if we're not in a vehicle - if ( RunningPassengerBehavior() == false ) - { - // Do our mobbed by enemies logic - DoMobbedCombatAI(); - } - - CBaseEntity *pEnemy = GetEnemy(); - - if( HasCondition( COND_LOW_PRIMARY_AMMO ) ) - { - if( pEnemy ) - { - if( GetAbsOrigin().DistToSqr( pEnemy->GetAbsOrigin() ) < Square( 60.0f ) ) - { - // Don't reload if an enemy is right in my face. - ClearCondition( COND_LOW_PRIMARY_AMMO ); - } - } - } - - if ( HasCondition( COND_LIGHT_DAMAGE ) ) - { - if ( pEnemy && !IsCrouching() ) - { - // If my enemy is shooting at me from a distance, crouch for protection - if ( EnemyDistance( pEnemy ) > ALYX_MIN_ENEMY_DIST_TO_CROUCH ) - { - DesireCrouch(); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Alyx::DoCustomSpeechAI( void ) -{ - BaseClass::DoCustomSpeechAI(); - - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - - if ( HasCondition(COND_NEW_ENEMY) && GetEnemy() ) - { - if ( GetEnemy()->Classify() == CLASS_HEADCRAB ) - { - CBaseHeadcrab *pHC = assert_cast(GetEnemy()); - // If we see a headcrab for the first time as he's jumping at me, freak out! - if ( ( GetEnemy()->GetEnemy() == this ) && pHC->IsJumping() && gpGlobals->curtime - GetEnemies()->FirstTimeSeen(GetEnemy()) < 0.5 ) - { - SpeakIfAllowed( "TLK_SPOTTED_INCOMING_HEADCRAB" ); - } - // If we see a headcrab leaving a zombie that just died, mention it - else if ( pHC->GetOwnerEntity() && ( pHC->GetOwnerEntity()->Classify() == CLASS_ZOMBIE ) && !pHC->GetOwnerEntity()->IsAlive() ) - { - SpeakIfAllowed( "TLK_SPOTTED_HEADCRAB_LEAVING_ZOMBIE" ); - } - } - else if ( GetEnemy()->Classify() == CLASS_ZOMBIE ) - { - CNPC_BaseZombie *pZombie = assert_cast(GetEnemy()); - // If we see a zombie getting up, mention it - if ( pZombie->IsGettingUp() ) - { - SpeakIfAllowed( "TLK_SPOTTED_ZOMBIE_WAKEUP" ); - } - } - } - - // Darkness mode speech - ClearCondition( COND_ALYX_IN_DARK ); - if ( HL2GameRules()->IsAlyxInDarknessMode() ) - { - // Even though the darkness light system will take flares into account when Alyx - // says she's lost the player in the darkness, players still think she's silly - // when they're too far from the flare to be seen. - // So, check for lit flares or other dynamic lights, and don't do - // a bunch of the darkness speech if there's a lit flare nearby. - bool bNearbyFlare = DarknessLightSourceWithinRadius( this, 500 ); - if ( !bNearbyFlare ) - { - SetCondition( COND_ALYX_IN_DARK ); - if ( HasCondition( COND_ALYX_PLAYER_TURNED_OFF_FLASHLIGHT ) || HasCondition( COND_ALYX_PLAYER_FLASHLIGHT_EXPIRED ) ) - { - // Player just turned off the flashlight. Start ramping up Alyx's breathing. - if ( !m_sndDarknessBreathing ) - { - CPASAttenuationFilter filter( this ); - m_sndDarknessBreathing = CSoundEnvelopeController::GetController().SoundCreate( filter, entindex(), CHAN_STATIC, - "ep_01.al_dark_breathing01", SNDLVL_TALKING ); - CSoundEnvelopeController::GetController().Play( m_sndDarknessBreathing, 0.0f, PITCH_NORM ); - } - - if ( m_sndDarknessBreathing ) - { - CSoundEnvelopeController::GetController().SoundChangeVolume( m_sndDarknessBreathing, ALYX_BREATHING_VOLUME_MAX, RandomFloat(10,20) ); - m_SpeechWatch_BreathingRamp.Stop(); - } - } - } - - // If we lose an enemy due to the flashlight, comment about it - if ( !HasCondition( COND_SEE_ENEMY ) && m_bHadCondSeeEnemy && !HasCondition( COND_TALKER_PLAYER_DEAD ) ) - { - if ( m_bDarknessSpeechAllowed && HasCondition( COND_ALYX_PLAYER_TURNED_OFF_FLASHLIGHT ) && - GetEnemy() && ( GetEnemy()->Classify() != CLASS_BULLSEYE ) ) - { - SpeakIfAllowed( "TLK_DARKNESS_LOSTENEMY_BY_FLASHLIGHT" ); - } - else if ( m_bDarknessSpeechAllowed && HasCondition( COND_ALYX_PLAYER_FLASHLIGHT_EXPIRED ) && - GetEnemy() && ( GetEnemy()->Classify() != CLASS_BULLSEYE ) ) - { - SpeakIfAllowed( "TLK_DARKNESS_LOSTENEMY_BY_FLASHLIGHT_EXPIRED" ); - } - else if ( m_bDarknessSpeechAllowed && GetEnemy() && ( GetEnemy()->Classify() != CLASS_BULLSEYE ) && - pPlayer && pPlayer->FlashlightIsOn() && !pPlayer->IsIlluminatedByFlashlight(GetEnemy(), NULL ) && - FVisible( GetEnemy() ) ) - { - SpeakIfAllowed( TLK_DARKNESS_ENEMY_IN_DARKNESS ); - } - m_bHadCondSeeEnemy = false; - } - else if ( HasCondition( COND_SEE_ENEMY ) ) - { - m_bHadCondSeeEnemy = true; - } - else if ( ( !GetEnemy() || ( GetEnemy()->Classify() == CLASS_BULLSEYE ) ) && m_bDarknessSpeechAllowed ) - { - if ( HasCondition( COND_ALYX_PLAYER_FLASHLIGHT_EXPIRED ) ) - { - SpeakIfAllowed( TLK_DARKNESS_FLASHLIGHT_EXPIRED ); - } - else if ( HasCondition( COND_ALYX_PLAYER_TURNED_OFF_FLASHLIGHT ) ) - { - SpeakIfAllowed( TLK_FLASHLIGHT_OFF ); - } - else if ( HasCondition( COND_ALYX_PLAYER_TURNED_ON_FLASHLIGHT ) ) - { - SpeakIfAllowed( TLK_FLASHLIGHT_ON ); - } - } - - // If we've just seen a new enemy, and it's illuminated by the flashlight, - // tell the player to keep the flashlight on 'em. - if ( HasCondition(COND_NEW_ENEMY) && !HasCondition( COND_TALKER_PLAYER_DEAD ) ) - { - // First time we've seen this guy? - if ( gpGlobals->curtime - GetEnemies()->FirstTimeSeen(GetEnemy()) < 0.5 ) - { - if ( pPlayer && pPlayer->IsIlluminatedByFlashlight(GetEnemy(), NULL ) && m_bDarknessSpeechAllowed && - !LookerCouldSeeTargetInDarkness( this, GetEnemy() ) ) - { - SpeakIfAllowed( "TLK_DARKNESS_FOUNDENEMY_BY_FLASHLIGHT" ); - } - } - } - - // When we lose the player, start lost-player talker after some time - if ( !bNearbyFlare && m_bDarknessSpeechAllowed ) - { - if ( !HasCondition(COND_SEE_PLAYER) && !m_SpeechWatch_LostPlayer.IsRunning() ) - { - m_SpeechWatch_LostPlayer.Set( 5,8 ); - m_SpeechWatch_LostPlayer.Start(); - m_MoveMonitor.SetMark( AI_GetSinglePlayer(), 48 ); - } - else if ( m_SpeechWatch_LostPlayer.Expired() ) - { - // Can't see the player? - if ( !HasCondition(COND_SEE_PLAYER) && !HasCondition( COND_TALKER_PLAYER_DEAD ) && !HasCondition( COND_SEE_ENEMY ) && - ( !pPlayer || pPlayer->GetAbsOrigin().DistToSqr(GetAbsOrigin()) > ALYX_DARKNESS_LOST_PLAYER_DIST ) ) - { - // only speak if player hasn't moved. - if ( m_MoveMonitor.TargetMoved( AI_GetSinglePlayer() ) ) - { - SpeakIfAllowed( "TLK_DARKNESS_LOSTPLAYER" ); - m_SpeechWatch_LostPlayer.Set(10); - m_SpeechWatch_LostPlayer.Start(); - m_bSpokeLostPlayerInDarkness = true; - } - } - } - - // Speech concepts that only occur when the player's flashlight is off - if ( pPlayer && !HasCondition( COND_TALKER_PLAYER_DEAD ) && !pPlayer->FlashlightIsOn() ) - { - // When the player first turns off the light, don't talk about sounds for a bit - if ( HasCondition( COND_ALYX_PLAYER_TURNED_OFF_FLASHLIGHT ) || HasCondition( COND_ALYX_PLAYER_FLASHLIGHT_EXPIRED ) ) - { - m_SpeechTimer_HeardSound.Set(4); - } - else if ( m_SpeechWatch_SoundDelay.Expired() ) - { - // We've waited for a bit after the sound, now talk about it - SpeakIfAllowed( "TLK_DARKNESS_HEARDSOUND" ); - m_SpeechWatch_SoundDelay.Stop(); - } - else if ( HasCondition( COND_HEAR_SPOOKY ) ) - { - // If we hear anything while the player's flashlight is off, randomly mention it - if ( m_SpeechTimer_HeardSound.Expired() ) - { - m_SpeechTimer_HeardSound.Set(10); - - // Wait for the sound to play for a bit before speaking about it - m_SpeechWatch_SoundDelay.Set( 1.0,3.0 ); - m_SpeechWatch_SoundDelay.Start(); - } - } - } - } - - // Stop the heard sound response if the player turns the flashlight on - if ( bNearbyFlare || HasCondition( COND_ALYX_PLAYER_TURNED_ON_FLASHLIGHT ) ) - { - m_SpeechWatch_SoundDelay.Stop(); - - if ( m_sndDarknessBreathing ) - { - CSoundEnvelopeController::GetController().SoundChangeVolume( m_sndDarknessBreathing, 0.0f, 0.5 ); - m_SpeechWatch_BreathingRamp.Stop(); - } - } - } - else - { - if ( m_sndDarknessBreathing ) - { - CSoundEnvelopeController::GetController().SoundChangeVolume( m_sndDarknessBreathing, 0.0f, 0.5 ); - m_SpeechWatch_BreathingRamp.Stop(); - } - - if ( !HasCondition(COND_SEE_PLAYER) && !m_SpeechWatch_FoundPlayer.IsRunning() ) - { - // wait a minute before saying something when alyx sees him again - m_SpeechWatch_FoundPlayer.Set( 60, 75 ); - m_SpeechWatch_FoundPlayer.Start(); - } - else if ( HasCondition(COND_SEE_PLAYER) ) - { - if ( m_SpeechWatch_FoundPlayer.Expired() && m_bDarknessSpeechAllowed ) - { - SpeakIfAllowed( "TLK_FOUNDPLAYER" ); - } - m_SpeechWatch_FoundPlayer.Stop(); - } - } - - // If we spoke lost-player, and now we see him/her, say so - if ( m_bSpokeLostPlayerInDarkness ) - { - // If we've left darkness mode, or if the player has blinded me with - // the flashlight, don't bother speaking the found player line. - if ( !m_bIsFlashlightBlind && HL2GameRules()->IsAlyxInDarknessMode() && m_bDarknessSpeechAllowed ) - { - if ( HasCondition(COND_SEE_PLAYER) && !HasCondition( COND_TALKER_PLAYER_DEAD ) ) - { - if ( ( m_fTimeUntilNextDarknessFoundPlayer == AI_INVALID_TIME ) || ( gpGlobals->curtime < m_fTimeUntilNextDarknessFoundPlayer ) ) - { - SpeakIfAllowed( "TLK_DARKNESS_FOUNDPLAYER" ); - } - m_bSpokeLostPlayerInDarkness = false; - } - } - else - { - m_bSpokeLostPlayerInDarkness = false; - } - } - - - if ( ( !m_bDarknessSpeechAllowed || HasCondition(COND_SEE_PLAYER) ) && m_SpeechWatch_LostPlayer.IsRunning() ) - { - m_SpeechWatch_LostPlayer.Stop(); - m_MoveMonitor.ClearMark(); - } - - // Ramp the breathing back up after speaking - if ( m_SpeechWatch_BreathingRamp.IsRunning() ) - { - if ( m_SpeechWatch_BreathingRamp.Expired() ) - { - CSoundEnvelopeController::GetController().SoundChangeVolume( m_sndDarknessBreathing, ALYX_BREATHING_VOLUME_MAX, RandomFloat(5,10) ); - m_SpeechWatch_BreathingRamp.Stop(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_Alyx::SpeakIfAllowed( AIConcept_t concept, const char *modifiers /*= NULL*/, bool bRespondingToPlayer /*= false*/, char *pszOutResponseChosen /*= NULL*/, size_t bufsize /* = 0 */ ) -{ - if ( BaseClass::SpeakIfAllowed( concept, modifiers, bRespondingToPlayer, pszOutResponseChosen, bufsize ) ) - { - // If we're breathing in the darkness, drop the volume quickly - if ( m_sndDarknessBreathing && CSoundEnvelopeController::GetController().SoundGetVolume( m_sndDarknessBreathing ) > 0.0 ) - { - CSoundEnvelopeController::GetController().SoundChangeVolume( m_sndDarknessBreathing, 0.0f, 0.1 ); - - // Ramp up the sound again after the response is over - float flDelay = (GetTimeSpeechComplete() - gpGlobals->curtime); - m_SpeechWatch_BreathingRamp.Set( flDelay ); - m_SpeechWatch_BreathingRamp.Start(); - } - - return true; - } - - return false; -} - -extern int ACT_ANTLION_FLIP; -extern int ACT_ANTLION_ZAP_FLIP; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Disposition_t CNPC_Alyx::IRelationType( CBaseEntity *pTarget ) -{ - Disposition_t disposition = BaseClass::IRelationType( pTarget ); - - if ( pTarget == NULL ) - return disposition; - - if( pTarget->Classify() == CLASS_ANTLION ) - { - if( disposition == D_HT ) - { - // If Alyx hates this antlion (default relationship), make her fear it, if it is very close. - if( GetAbsOrigin().DistToSqr(pTarget->GetAbsOrigin()) < ALYX_FEAR_ANTLION_DIST_SQR ) - { - disposition = D_FR; - } - - // Fall through... - } - } - else if( pTarget->Classify() == CLASS_ZOMBIE && disposition == D_HT && GetActiveWeapon() ) - { - if( GetAbsOrigin().DistToSqr(pTarget->GetAbsOrigin()) < ALYX_FEAR_ZOMBIE_DIST_SQR ) - { - // Be afraid of a zombie that's near if I'm not allowed to dodge. This will make Alyx back away. - return D_FR; - } - } - else if ( pTarget->Classify() == CLASS_MISSILE ) - { - // Fire at missiles while in the vehicle - if ( IsInAVehicle() ) - return D_HT; - } - - return disposition; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Alyx::IRelationPriority( CBaseEntity *pTarget ) -{ - int priority = BaseClass::IRelationPriority( pTarget ); - - if( pTarget->Classify() == CLASS_ANTLION ) - { - // Make Alyx prefer Antlions that are flipped onto their backs. - // UNLESS she has a different enemy that could melee attack her while her back is turned. - CAI_BaseNPC *pNPC = pTarget->MyNPCPointer(); - if ( pNPC && ( pNPC->GetActivity() == ACT_ANTLION_FLIP || pNPC->GetActivity() == ACT_ANTLION_ZAP_FLIP ) ) - { - if( GetEnemy() && GetEnemy() != pTarget ) - { - // I have an enemy that is not this thing. If that enemy is near, I shouldn't - // become distracted. - if( GetAbsOrigin().DistToSqr(GetEnemy()->GetAbsOrigin()) < Square(180) ) - { - return priority; - } - } - - priority += 1; - } - } - - return priority; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -#define ALYX_360_VIEW_DIST_SQR 129600 // 30 feet -bool CNPC_Alyx::FInViewCone( CBaseEntity *pEntity ) -{ - // Alyx can see 360 degrees but only at limited distance. This allows her to be aware of a - // large mob of enemies (usually antlions or zombies) closing in. This situation is so obvious to the - // player that it doesn't make sense for Alyx to be unaware of the entire group simply because she - // hasn't seen all of the enemies with her own eyes. - if( ( pEntity->IsNPC() || pEntity->IsPlayer() ) && pEntity->GetAbsOrigin().DistToSqr(GetAbsOrigin()) <= ALYX_360_VIEW_DIST_SQR ) - { - // Only see players and NPC's with 360 cone - // For instance, DON'T tell the eyeball/head tracking code that you can see an object that is behind you! - return true; - } - - // Else, fall through... - if ( HL2GameRules()->IsAlyxInDarknessMode() ) - { - if ( CanSeeEntityInDarkness( pEntity ) ) - return true; - } - - return BaseClass::FInViewCone( pEntity ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEntity - -//----------------------------------------------------------------------------- -bool CNPC_Alyx::CanSeeEntityInDarkness( CBaseEntity *pEntity ) -{ - /* - // Alyx can see enemies that are right next to her - // Robin: Disabled, made her too effective, you could safely leave her alone. - if ( pEntity->IsNPC() ) - { - if ( (pEntity->WorldSpaceCenter() - EyePosition()).LengthSqr() < (80*80) ) - return true; - } - */ - - CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); - if ( pPlayer && pEntity != pPlayer ) - { - if ( pPlayer->IsIlluminatedByFlashlight(pEntity, NULL ) ) - return true; - } - - return LookerCouldSeeTargetInDarkness( this, pEntity ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Alyx::QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC) -{ - if ( HL2GameRules()->IsAlyxInDarknessMode() ) - { - if ( !CanSeeEntityInDarkness( pEntity ) ) - return false; - } - - return BaseClass::QuerySeeEntity(pEntity, bOnlyHateOrFearIfNPC); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Alyx::IsCoverPosition( const Vector &vecThreat, const Vector &vecPosition ) -{ - return BaseClass::IsCoverPosition( vecThreat, vecPosition ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Activity CNPC_Alyx::NPC_TranslateActivity( Activity activity ) -{ - activity = BaseClass::NPC_TranslateActivity( activity ); - - if ( activity == ACT_RUN && GetEnemy() && GetEnemy()->Classify() == CLASS_COMBINE_GUNSHIP ) - { - // Always cower from gunship! - if ( HaveSequenceForActivity( ACT_RUN_PROTECTED ) ) - activity = ACT_RUN_PROTECTED; - } - - switch ( activity ) - { - // !!!HACK - Alyx doesn't have the required animations for shotguns, - // so trick her into using the rifle counterparts for now (sjb) - case ACT_RUN_AIM_SHOTGUN: return ACT_RUN_AIM_RIFLE; - case ACT_WALK_AIM_SHOTGUN: return ACT_WALK_AIM_RIFLE; - case ACT_IDLE_ANGRY_SHOTGUN: return ACT_IDLE_ANGRY_SMG1; - case ACT_RANGE_ATTACK_SHOTGUN_LOW: return ACT_RANGE_ATTACK_SMG1_LOW; - - case ACT_PICKUP_RACK: return (Activity)ACT_ALYX_PICKUP_RACK; - case ACT_DROP_WEAPON: if ( HasShotgun() ) return (Activity)ACT_DROP_WEAPON_SHOTGUN; - - default: break; - } - - return activity; -} - -bool CNPC_Alyx::ShouldDeferToFollowBehavior() -{ - return BaseClass::ShouldDeferToFollowBehavior(); -} - -void CNPC_Alyx::BuildScheduleTestBits() -{ - bool bIsInteracting = false; - - bIsInteracting = ( IsCurSchedule(SCHED_ALYX_PREPARE_TO_INTERACT_WITH_TARGET, false) || - IsCurSchedule(SCHED_ALYX_WAIT_TO_INTERACT_WITH_TARGET, false) || - IsCurSchedule(SCHED_ALYX_INTERACT_WITH_TARGET, false) || - IsCurSchedule(SCHED_ALYX_INTERACTION_INTERRUPTED, false) || - IsCurSchedule(SCHED_ALYX_FINISH_INTERACTING_WITH_TARGET, false) ); - - if( !bIsInteracting && IsAllowedToInteract() ) - { - switch( m_NPCState ) - { - case NPC_STATE_COMBAT: - SetCustomInterruptCondition( COND_ALYX_HAS_INTERACT_TARGET ); - SetCustomInterruptCondition( COND_ALYX_CAN_INTERACT_WITH_TARGET ); - break; - - case NPC_STATE_ALERT: - case NPC_STATE_IDLE: - SetCustomInterruptCondition( COND_ALYX_HAS_INTERACT_TARGET ); - SetCustomInterruptCondition( COND_ALYX_CAN_INTERACT_WITH_TARGET ); - break; - - default: - break; - } - } - - // This nugget fixes a bug where Alyx will continue to attack an enemy she no longer hates in the - // case where her relationship with the enemy changes while she's running a SCHED_SCENE_GENERIC. - // Since we don't run ChooseEnemy() when we're running a schedule that doesn't interrupt on COND_NEW_ENEMY, - // we also do not re-evaluate and flush enemies we don't hate anymore. (sjb 6/9/2005) - if( IsCurSchedule(SCHED_SCENE_GENERIC) && GetEnemy() && GetEnemy()->VPhysicsGetObject() ) - { - if( GetEnemy()->VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - { - SetCustomInterruptCondition( COND_NEW_ENEMY ); - } - } - - if( GetCurSchedule()->HasInterrupt( COND_IDLE_INTERRUPT ) ) - { - SetCustomInterruptCondition( COND_BETTER_WEAPON_AVAILABLE ); - } - - // If we're not in a script, keep an eye out for falling - if ( m_NPCState != NPC_STATE_SCRIPT && !IsInAVehicle() && !IsCurSchedule(SCHED_ALYX_FALL_TO_GROUND,false) ) - { - SetCustomInterruptCondition( COND_FLOATING_OFF_GROUND ); - } - - BaseClass::BuildScheduleTestBits(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Alyx::ShouldBehaviorSelectSchedule( CAI_BehaviorBase *pBehavior ) -{ - if( pBehavior == &m_AssaultBehavior ) - { - if( HasCondition( COND_MOBBED_BY_ENEMIES )) - return false; - } - - return BaseClass::ShouldBehaviorSelectSchedule( pBehavior ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Alyx::SelectSchedule( void ) -{ - // If we're in darkness mode, and the player has the flashlight off, and we hear a zombie footstep, - // and the player isn't nearby, deliberately turn away from the zombie to let the zombie grab me. - if ( HL2GameRules()->IsAlyxInDarknessMode() && m_NPCState == NPC_STATE_ALERT ) - { - if ( HasCondition ( COND_HEAR_COMBAT ) && !HasCondition(COND_SEE_PLAYER) ) - { - CSound *pBestSound = GetBestSound(); - if ( pBestSound && pBestSound->m_hOwner ) - { - if ( pBestSound->m_hOwner->Classify() == CLASS_ZOMBIE && pBestSound->SoundChannel() == SOUNDENT_CHANNEL_NPC_FOOTSTEP ) - return SCHED_ALYX_ALERT_FACE_AWAYFROM_BESTSOUND; - } - } - } - - if( HasCondition(COND_ALYX_CAN_INTERACT_WITH_TARGET) ) - return SCHED_ALYX_INTERACT_WITH_TARGET; - - if( HasCondition(COND_ALYX_HAS_INTERACT_TARGET) && HasCondition(COND_SEE_PLAYER) && IsAllowedToInteract() ) - { - ExpireCurrentRandomLookTarget(); - if( IsEMPHolstered() ) - { - return SCHED_ALYX_PREPARE_TO_INTERACT_WITH_TARGET; - } - - return SCHED_ALYX_WAIT_TO_INTERACT_WITH_TARGET; - } - - if( !IsEMPHolstered() && !HasInteractTarget() && !m_ActBusyBehavior.IsActive() ) - return SCHED_ALYX_HOLSTER_EMP; - - if ( HasCondition(COND_BETTER_WEAPON_AVAILABLE) ) - { - if( m_iszPendingWeapon != NULL_STRING ) - { - return SCHED_SWITCH_TO_PENDING_WEAPON; - } - else - { - CBaseHLCombatWeapon *pWeapon = dynamic_cast(Weapon_FindUsable( WEAPON_SEARCH_DELTA )); - if ( pWeapon ) - { - m_flNextWeaponSearchTime = gpGlobals->curtime + 10.0; - // Now lock the weapon for several seconds while we go to pick it up. - pWeapon->Lock( 10.0, this ); - SetTarget( pWeapon ); - return SCHED_ALYX_NEW_WEAPON; - } - } - } - - if ( HasCondition(COND_ENEMY_OCCLUDED) ) - { - //Warning("CROUCH: Standing, enemy is occluded.\n" ); - Stand(); - } - - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Alyx::SelectScheduleDanger( void ) -{ - if( HasCondition( COND_HEAR_DANGER ) ) - { - CSound *pSound; - pSound = GetBestSound( SOUND_DANGER ); - - ASSERT( pSound != NULL ); - - if ( pSound && (pSound->m_iType & SOUND_DANGER) && ( pSound->SoundChannel() == SOUNDENT_CHANNEL_ZOMBINE_GRENADE ) ) - { - SpeakIfAllowed( TLK_DANGER_ZOMBINE_GRENADE ); - } - } - - return BaseClass::SelectScheduleDanger(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Alyx::TranslateSchedule( int scheduleType ) -{ - switch( scheduleType ) - { - case SCHED_ALERT_FACE_BESTSOUND: - return SCHED_ALYX_ALERT_FACE_BESTSOUND; - break; - - case SCHED_COMBAT_FACE: - if ( !HasCondition(COND_TASK_FAILED) && !IsCrouching() ) - return SCHED_ALYX_COMBAT_FACE; - break; - - case SCHED_WAKE_ANGRY: - return SCHED_ALYX_WAKE_ANGRY; - break; - - case SCHED_FALL_TO_GROUND: - return SCHED_ALYX_FALL_TO_GROUND; - break; - - case SCHED_ALERT_REACT_TO_COMBAT_SOUND: - return SCHED_ALYX_ALERT_REACT_TO_COMBAT_SOUND; - break; - - case SCHED_COWER: - case SCHED_PC_COWER: - // Alyx doesn't have cower animations. - return SCHED_FAIL; - - case SCHED_RANGE_ATTACK1: - { - if ( GetEnemy() ) - { - CBaseEntity *pEnemy = GetEnemy(); - if ( !IsCrouching() ) - { - // Does my enemy have enough health to warrant crouching? - if ( pEnemy->GetHealth() > ALYX_MIN_ENEMY_HEALTH_TO_CROUCH ) - { - // And are they far enough away? Expand the min dist so we don't crouch & stand immediately. - if ( EnemyDistance( pEnemy ) > (ALYX_MIN_ENEMY_DIST_TO_CROUCH * 1.5) && (pEnemy->GetFlags() & FL_ONGROUND) ) - { - //Warning("CROUCH: Desiring due to enemy far away.\n" ); - DesireCrouch(); - } - } - } - - // Are we supposed to be crouching? - if ( IsCrouching() || ( CrouchIsDesired() && !HasCondition( COND_HEAVY_DAMAGE ) ) ) - { - // See if they're a valid crouch target - if ( EnemyIsValidCrouchTarget( pEnemy ) ) - { - Crouch(); - } - else - { - //Warning("CROUCH: Standing, enemy not valid crouch target.\n" ); - Stand(); - } - } - else - { - //Warning("CROUCH: Standing, no enemy.\n" ); - Stand(); - } - } - - return SCHED_ALYX_RANGE_ATTACK1; - } - break; - - case SCHED_HIDE_AND_RELOAD: - { - if ( HL2GameRules()->IsAlyxInDarknessMode() ) - return SCHED_RELOAD; - - // If I don't have a ranged attacker as an enemy, don't try to hide - AIEnemiesIter_t iter; - for ( AI_EnemyInfo_t *pEMemory = GetEnemies()->GetFirst(&iter); pEMemory != NULL; pEMemory = GetEnemies()->GetNext(&iter) ) - { - CAI_BaseNPC *pEnemy = pEMemory->hEnemy.Get()->MyNPCPointer(); - if ( !pEnemy ) - continue; - - // Ignore enemies that don't hate me - if ( pEnemy->IRelationType( this ) != D_HT ) - continue; - - // Look for enemies with ranged capabilities - if ( pEnemy->CapabilitiesGet() & ( bits_CAP_WEAPON_RANGE_ATTACK1 | bits_CAP_WEAPON_RANGE_ATTACK2 | bits_CAP_INNATE_RANGE_ATTACK1 | bits_CAP_INNATE_RANGE_ATTACK2 ) ) - return SCHED_HIDE_AND_RELOAD; - } - - return SCHED_RELOAD; - } - break; - - case SCHED_RUN_FROM_ENEMY: - if ( HasCondition( COND_MOBBED_BY_ENEMIES ) ) - { - return SCHED_RUN_FROM_ENEMY_MOB; - } - break; - - case SCHED_IDLE_STAND: - return SCHED_ALYX_IDLE_STAND; - -#ifdef HL2_EPISODIC - case SCHED_RUN_RANDOM: - if( GetEnemy() && HasCondition(COND_SEE_ENEMY) && GetActiveWeapon() ) - { - // SCHED_RUN_RANDOM is a last ditch effort, it's the bottom of a chain of - // sequential schedule failures. Since this can cause Alyx to freeze up, - // just let her fight if she can. (sjb). - return SCHED_RANGE_ATTACK1; - } - break; -#endif// HL2_EPISODIC - } - - return BaseClass::TranslateSchedule( scheduleType ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Alyx::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_SOUND_WAKE: - LocateEnemySound(); - // Don't do the half second wait here that the PlayerCompanion class does. (sbj) 1/4/2006 - TaskComplete(); - break; - - case TASK_ANNOUNCE_ATTACK: - { - SpeakAttacking(); - BaseClass::StartTask( pTask ); - break; - } - - case TASK_ALYX_BUILD_COMBAT_FACE_PATH: - { - if ( GetEnemy() && !FInAimCone( GetEnemyLKP() ) && FVisible( GetEnemyLKP() ) ) - { - Vector vecToEnemy = GetEnemyLKP() - GetAbsOrigin(); - VectorNormalize( vecToEnemy ); - - Vector vecMoveGoal = GetAbsOrigin() - (vecToEnemy * 24.0f); - - if ( !GetNavigator()->SetGoal( vecMoveGoal ) ) - { - TaskFail(FAIL_NO_ROUTE); - } - else - { - GetMotor()->SetIdealYawToTarget( GetEnemy()->WorldSpaceCenter() ); - GetNavigator()->SetArrivalDirection( GetEnemy() ); - TaskComplete(); - } - } - else - { - TaskFail("Defaulting To BaseClass::CombatFace"); - } - } - break; - - case TASK_ALYX_HOLSTER_AND_DESTROY_PISTOL: - { - // If we don't have the alyx gun, throw away our current, - // since the alyx gun is the only one we can tuck away. - if ( HasAlyxgun() ) - { - SetDesiredWeaponState( DESIREDWEAPONSTATE_HOLSTERED_DESTROYED ); - } - else - { - Weapon_Drop( GetActiveWeapon() ); - } - - SetWait( 1 ); // Wait while she does it. - } - break; - - case TASK_STOP_MOVING: - if ( npc_alyx_force_stop_moving.GetBool() ) - { - if ( ( GetNavigator()->IsGoalSet() && GetNavigator()->IsGoalActive() ) || GetNavType() == NAV_JUMP ) - { - DbgNavMsg( this, "Start TASK_STOP_MOVING\n" ); - DbgNavMsg( this, "Initiating stopping path\n" ); - GetNavigator()->StopMoving( false ); - - // E3 Hack - if ( HasPoseMoveYaw() ) - { - SetPoseParameter( m_poseMove_Yaw, 0 ); - } - } - else - { - if ( GetNavigator()->SetGoalFromStoppingPath() ) - { - DbgNavMsg( this, "Start TASK_STOP_MOVING\n" ); - DbgNavMsg( this, "Initiating stopping path\n" ); - } - else - { - GetNavigator()->ClearGoal(); - - if ( IsMoving() ) - { - SetIdealActivity( GetStoppedActivity() ); - } - TaskComplete(); - } - } - } - else - { - BaseClass::StartTask( pTask ); - } - break; - - case TASK_REACT_TO_COMBAT_SOUND: - { - CSound *pSound = GetBestSound(); - - if( pSound && pSound->IsSoundType(SOUND_COMBAT) && pSound->IsSoundType(SOUND_CONTEXT_GUNFIRE) ) - { - AnalyzeGunfireSound(pSound); - } - - TaskComplete(); - } - break; - - case TASK_ALYX_HOLSTER_PISTOL: - HolsterPistol(); - TaskComplete(); - break; - - case TASK_ALYX_DRAW_PISTOL: - DrawPistol(); - TaskComplete(); - break; - - case TASK_ALYX_WAIT_HACKING: - SetWait( pTask->flTaskData ); - break; - - case TASK_ALYX_GET_PATH_TO_INTERACT_TARGET: - { - if( !HasInteractTarget() ) - { - TaskFail("No interact target"); - return; - } - - AI_NavGoal_t goal; - - goal.type = GOALTYPE_LOCATION; - goal.dest = GetInteractTarget()->WorldSpaceCenter(); - goal.pTarget = GetInteractTarget(); - - GetNavigator()->SetGoal( goal ); - } - break; - - case TASK_ALYX_ANNOUNCE_HACK: - SpeakIfAllowed( CONCEPT_ALYX_REQUEST_ITEM ); - TaskComplete(); - break; - - case TASK_ALYX_BEGIN_INTERACTION: - { - INPCInteractive *pInteractive = dynamic_cast(GetInteractTarget()); - if ( pInteractive ) - { - EmpZapTarget( GetInteractTarget() ); - - pInteractive->AlyxStartedInteraction(); - pInteractive->NotifyInteraction(this); - pInteractive->AlyxFinishedInteraction(); - m_OnFinishInteractWithObject.FireOutput( GetInteractTarget(), this ); - } - - TaskComplete(); - } - break; - - case TASK_ALYX_COMPLETE_INTERACTION: - { - INPCInteractive *pInteractive = dynamic_cast(GetInteractTarget()); - - if( pInteractive ) - { - for( int i = 0 ; i < 3 ; i++ ) - { - g_pEffects->Sparks( GetInteractTarget()->WorldSpaceCenter() ); - } - - GetInteractTarget()->EmitSound("DoSpark"); - Speak( CONCEPT_ALYX_INTERACTION_DONE ); - - SetInteractTarget(NULL); - } - - TaskComplete(); - } - break; - - case TASK_ALYX_SET_IDLE_ACTIVITY: - { - Activity goalActivity = (Activity)((int)pTask->flTaskData); - if ( IsActivityFinished() ) - { - SetIdealActivity( goalActivity ); - } - } - break; - - case TASK_ALYX_FALL_TO_GROUND: - // If we wait this long without landing, we'll fall to our death - SetWait(2); - break; - - default: - BaseClass::StartTask(pTask); - break; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Alyx::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_ALYX_HOLSTER_AND_DESTROY_PISTOL: - if( IsWaitFinished() ) - TaskComplete(); - break; - - case TASK_STOP_MOVING: - { - if ( npc_alyx_force_stop_moving.GetBool() ) - { - ChainRunTask( TASK_WAIT_FOR_MOVEMENT ); - if ( !TaskIsRunning() ) - { - DbgNavMsg( this, "TASK_STOP_MOVING Complete\n" ); - } - } - else - { - BaseClass::RunTask( pTask ); - } - break; - } - - case TASK_ALYX_WAIT_HACKING: - if( GetInteractTarget() && random->RandomInt(0, 3) == 0 ) - { - g_pEffects->Sparks( GetInteractTarget()->WorldSpaceCenter() ); - GetInteractTarget()->EmitSound("DoSpark"); - } - - if ( IsWaitFinished() ) - { - TaskComplete(); - } - break; - - case TASK_ALYX_SET_IDLE_ACTIVITY: - { - if ( IsActivityStarted() ) - { - TaskComplete(); - } - } - break; - - case TASK_ALYX_FALL_TO_GROUND: - if ( GetFlags() & FL_ONGROUND ) - { - TaskComplete(); - } - else if( IsWaitFinished() ) - { - // Call back to the base class & see if it can find a ground for us - // If it can't, we'll fall to our death - ChainRunTask( TASK_FALL_TO_GROUND ); - if ( TaskIsRunning() ) - { - CTakeDamageInfo info; - info.SetDamage( m_iHealth ); - info.SetAttacker( this ); - info.SetInflictor( this ); - info.SetDamageType( DMG_GENERIC ); - TakeDamage( info ); - } - } - break; - - default: - BaseClass::RunTask(pTask); - break; - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Alyx::OnStateChange( NPC_STATE OldState, NPC_STATE NewState ) -{ - switch( NewState ) - { - case NPC_STATE_COMBAT: - { - m_fCombatStartTime = gpGlobals->curtime; - } - break; - - default: - if( OldState == NPC_STATE_COMBAT ) - { - // coming out of combat state. - m_fCombatEndTime = gpGlobals->curtime + 2.0f; - } - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Alyx::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - BaseClass::TraceAttack( info, vecDir, ptr ); - - // FIXME: hack until some way of removing decals after healing - m_fNoDamageDecal = true; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Alyx::CanBeHitByMeleeAttack( CBaseEntity *pAttacker ) -{ - if( IsCurSchedule(SCHED_DUCK_DODGE) ) - { - return false; - } - - return BaseClass::CanBeHitByMeleeAttack( pAttacker ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Alyx::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - //!!!HACKHACK - EP1 - Stop alyx taking all physics damage to prevent her dying - // in freak accidents resembling spontaneous stress damage death (which are now impossible) - // Also stop her taking damage from flames: Fixes her being burnt to death from entity flames - // attached to random debris chunks while inside scripted sequences. - if( info.GetDamageType() & (DMG_CRUSH | DMG_BURN) ) - return 0; - - // If we're in commentary mode, prevent her taking damage from other NPCs - if ( IsInCommentaryMode() && info.GetAttacker() && info.GetAttacker()->IsNPC() ) - return 0; - - int taken = BaseClass::OnTakeDamage_Alive(info); - - if ( taken && HL2GameRules()->IsAlyxInDarknessMode() && !HasCondition( COND_TALKER_PLAYER_DEAD ) ) - { - if ( !HasCondition(COND_SEE_ENEMY) && (info.GetDamageType() & (DMG_SLASH | DMG_CLUB) ) ) - { - // I've taken melee damage. If I haven't seen the enemy for a few seconds, make some noise. - float flLastTimeSeen = GetEnemies()->LastTimeSeen( info.GetAttacker(), false ); - if ( flLastTimeSeen == AI_INVALID_TIME || gpGlobals->curtime - flLastTimeSeen > 3.0 ) - { - SpeakIfAllowed( "TLK_DARKNESS_UNKNOWN_WOUND" ); - m_fTimeUntilNextDarknessFoundPlayer = gpGlobals->curtime + RandomFloat( 3, 5 ); - } - } - } - - if( taken && (info.GetDamageType() & DMG_BLAST) ) - { - if ( HasShotgun() ) - { - if ( !IsPlayingGesture(ACT_GESTURE_FLINCH_BLAST) && !IsPlayingGesture(ACT_GESTURE_FLINCH_BLAST_DAMAGED_SHOTGUN) ) - { - RestartGesture( ACT_GESTURE_FLINCH_BLAST_DAMAGED_SHOTGUN ); - GetShotRegulator()->FireNoEarlierThan( gpGlobals->curtime + SequenceDuration( ACT_GESTURE_FLINCH_BLAST_DAMAGED_SHOTGUN ) + 0.5f ); - } - } - else - { - if ( !IsPlayingGesture(ACT_GESTURE_FLINCH_BLAST) && !IsPlayingGesture(ACT_GESTURE_FLINCH_BLAST_DAMAGED) ) - { - RestartGesture( ACT_GESTURE_FLINCH_BLAST_DAMAGED ); - GetShotRegulator()->FireNoEarlierThan( gpGlobals->curtime + SequenceDuration( ACT_GESTURE_FLINCH_BLAST_DAMAGED ) + 0.5f ); - } - } - } - - return taken; -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -bool CNPC_Alyx::FCanCheckAttacks() -{ - if( GetEnemy() && IsGunship( GetEnemy() ) ) - { - // Don't attack gunships - return false; - } - - return BaseClass::FCanCheckAttacks(); -} - -//----------------------------------------------------------------------------- -// Purpose: Half damage against Combine Soldiers in outland_10 -//----------------------------------------------------------------------------- -float CNPC_Alyx::GetAttackDamageScale( CBaseEntity *pVictim ) -{ - if( g_HackOutland10DamageHack && pVictim->Classify() == CLASS_COMBINE ) - { - return 0.75f; - } - - return BaseClass::GetAttackDamageScale( pVictim ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Alyx::HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt) -{ - if( interactionType == g_interactionZombieMeleeWarning && IsAllowedToDodge() ) - { - // If a zombie is attacking, ditch my current schedule and duck if I'm running a schedule that will - // be interrupted if I'm hit. - if( ConditionInterruptsCurSchedule(COND_LIGHT_DAMAGE) || ConditionInterruptsCurSchedule( COND_HEAVY_DAMAGE) ) - { - //Only dodge an NPC you can see attacking. - if( sourceEnt && FInViewCone(sourceEnt) ) - { - SetSchedule(SCHED_DUCK_DODGE); - } - } - - return true; - } - - if( interactionType == g_interactionPlayerPuntedHeavyObject ) - { - // Try to get Alyx out of the way when player is punting cars around. - CBaseEntity *pProp = (CBaseEntity*)(data); - - if( pProp ) - { - float distToProp = pProp->WorldSpaceCenter().DistTo( GetAbsOrigin() ); - float distToPlayer = sourceEnt->WorldSpaceCenter().DistTo( GetAbsOrigin() ); - - // Do this if the prop is within 60 feet, and is closer to me than the player is. - if( distToProp < (60.0f * 12.0f) && (distToProp < distToPlayer) ) - { - if( fabs(pProp->WorldSpaceCenter().z - WorldSpaceCenter().z) <= 120.0f ) - { - if( sourceEnt->FInViewCone(this) ) - { - CSoundEnt::InsertSound( SOUND_MOVE_AWAY, EarPosition(), 16, 1.0f, pProp ); - } - } - } - } - return true; - } - - return BaseClass::HandleInteraction( interactionType, data, sourceEnt ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Alyx::HolsterPistol() -{ - if( GetActiveWeapon() ) - { - GetActiveWeapon()->AddEffects(EF_NODRAW); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Alyx::DrawPistol() -{ - if( GetActiveWeapon() ) - { - GetActiveWeapon()->RemoveEffects(EF_NODRAW); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Alyx::Weapon_Drop( CBaseCombatWeapon *pWeapon, const Vector *pvecTarget, const Vector *pVelocity ) -{ - BaseClass::Weapon_Drop( pWeapon, pvecTarget, pVelocity ); - - if( pWeapon && pWeapon->ClassMatches( CLASSNAME_ALYXGUN ) ) - { - pWeapon->SUB_Remove(); - } - - m_WeaponType = WT_NONE; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Alyx::IsAllowedToAim() -{ - // Alyx can aim only if fully agitated - if( GetReadinessLevel() != AIRL_AGITATED ) - return false; - - return BaseClass::IsAllowedToAim(); -} - - -//----------------------------------------------------------------------------- -void CNPC_Alyx::PainSound( const CTakeDamageInfo &info ) -{ - // Alex has specific sounds for when attacked in the dark - if ( !HasCondition( COND_ALYX_IN_DARK ) ) - { - // set up the speech modifiers - CFmtStrN<128> modifiers( "damageammo:%s", info.GetAmmoName() ); - - SpeakIfAllowed( TLK_WOUND, modifiers ); - } -} - -//----------------------------------------------------------------------------- - -void CNPC_Alyx::DeathSound( const CTakeDamageInfo &info ) -{ - // Sentences don't play on dead NPCs - SentenceStop(); - - if ( !SpokeConcept( TLK_SELF_IN_BARNACLE ) ) - { - EmitSound( "npc_alyx.die" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Alyx::OnSeeEntity( CBaseEntity *pEntity ) -{ - BaseClass::OnSeeEntity(pEntity); - - if( pEntity->IsPlayer() && pEntity->IsEFlagSet(EFL_IS_BEING_LIFTED_BY_BARNACLE) ) - { - SpeakIfAllowed( TLK_ALLY_IN_BARNACLE ); - } -} - - -//--------------------------------------------------------- -// A sort of trivial rejection, this function tells us whether -// this object is something Alyx can interact with at all. -// (Alyx's state and the object's state are not considered -// at this stage) -//--------------------------------------------------------- -bool CNPC_Alyx::IsValidInteractTarget( CBaseEntity *pTarget ) -{ - INPCInteractive *pInteractive = dynamic_cast(pTarget); - - if( !pInteractive ) - { - // Not an INPCInteractive entity. - return false; - } - - if( !pInteractive->CanInteractWith(this) ) - { - return false; - } - - if( pInteractive->HasBeenInteractedWith() ) - { - // Already been interacted with. - return false; - } - - IPhysicsObject *pPhysics; - - pPhysics = pTarget->VPhysicsGetObject(); - if( pPhysics ) - { - if( !(pPhysics->GetGameFlags() & FVPHYSICS_PLAYER_HELD) ) - { - // Player isn't holding this physics object - return false; - } - } - - if( GetAbsOrigin().DistToSqr(pTarget->WorldSpaceCenter()) > (360.0f * 360.0f) ) - { - // Too far away! - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Alyx::SetInteractTarget( CBaseEntity *pTarget ) -{ - if( !pTarget ) - { - ClearCondition( COND_ALYX_HAS_INTERACT_TARGET ); - ClearCondition( COND_ALYX_CAN_INTERACT_WITH_TARGET ); - - SetCondition( COND_ALYX_NO_INTERACT_TARGET ); - SetCondition( COND_ALYX_CAN_NOT_INTERACT_WITH_TARGET ); - } - - m_hHackTarget.Set(pTarget); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Alyx::EmpZapTarget( CBaseEntity *pTarget ) -{ - g_pEffects->Sparks( pTarget->WorldSpaceCenter() ); - - CAlyxEmpEffect *pEmpEffect = (CAlyxEmpEffect*)CreateEntityByName( "env_alyxemp" ); - - if( pEmpEffect ) - { - pEmpEffect->Spawn(); - pEmpEffect->ActivateAutomatic( this, pTarget ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_Alyx::CanInteractWithTarget( CBaseEntity *pTarget ) -{ - if( !IsValidInteractTarget(pTarget) ) - return false; - - float flDist; - - flDist = (WorldSpaceCenter() - pTarget->WorldSpaceCenter()).Length(); - - if( flDist > 80.0f ) - { - return false; - } - - if( !IsAllowedToInteract() ) - { - SpeakIfAllowed( TLK_CANT_INTERACT_NOW ); - return false; - } - - if( IsEMPHolstered() ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Player has illuminated this NPC with the flashlight -//----------------------------------------------------------------------------- -void CNPC_Alyx::PlayerHasIlluminatedNPC( CBasePlayer *pPlayer, float flDot ) -{ - if ( m_bIsFlashlightBlind ) - return; - - if ( !CanBeBlindedByFlashlight( true ) ) - return; - - // Ignore the flashlight if it's not shining at my eyes - if ( PlayerFlashlightOnMyEyes( pPlayer ) ) - { - char szResponse[AI_Response::MAX_RESPONSE_NAME]; - - // Only say the blinding speech if it's time to - if ( SpeakIfAllowed( "TLK_FLASHLIGHT_ILLUM", NULL, false, szResponse, AI_Response::MAX_RESPONSE_NAME ) ) - { - m_iszCurrentBlindScene = AllocPooledString( szResponse ); - ADD_DEBUG_HISTORY( HISTORY_ALYX_BLIND, UTIL_VarArgs( "(%0.2f) Alyx: start flashlight blind scene '%s'\n", gpGlobals->curtime, STRING(m_iszCurrentBlindScene) ) ); - GetShotRegulator()->DisableShooting(); - m_bIsFlashlightBlind = true; - m_fStayBlindUntil = gpGlobals->curtime + 0.1f; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Check if player has illuminated this NPC with a flare -//----------------------------------------------------------------------------- -void CNPC_Alyx::CheckBlindedByFlare( void ) -{ - if ( m_bIsFlashlightBlind ) - return; - - if ( !CanBeBlindedByFlashlight( false ) ) - return; - - // Ignore the flare if it's not too close - if ( BlindedByFlare() ) - { - char szResponse[AI_Response::MAX_RESPONSE_NAME]; - - // Only say the blinding speech if it's time to - if ( SpeakIfAllowed( "TLK_FLASHLIGHT_ILLUM", NULL, false, szResponse, AI_Response::MAX_RESPONSE_NAME ) ) - { - m_iszCurrentBlindScene = AllocPooledString( szResponse ); - ADD_DEBUG_HISTORY( HISTORY_ALYX_BLIND, UTIL_VarArgs( "(%0.2f) Alyx: start flare blind scene '%s'\n", gpGlobals->curtime, - STRING(m_iszCurrentBlindScene) ) ); - GetShotRegulator()->DisableShooting(); - m_bIsFlashlightBlind = true; - m_fStayBlindUntil = gpGlobals->curtime + 0.1f; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input: bCheckLightSources - if true, checks if any light darkness lightsources are near -//----------------------------------------------------------------------------- -bool CNPC_Alyx::CanBeBlindedByFlashlight( bool bCheckLightSources ) -{ - // Can't be blinded if we're not in alyx darkness mode - /* - if ( !HL2GameRules()->IsAlyxInDarknessMode() ) - return false; - */ - - // Can't be blinded if I'm in a script, or in combat - if ( IsInAScript() || GetState() == NPC_STATE_COMBAT || GetState() == NPC_STATE_SCRIPT ) - return false; - if ( IsSpeaking() ) - return false; - - // can't be blinded if Alyx is near a light source - if ( bCheckLightSources && DarknessLightSourceWithinRadius( this, 500 ) ) - return false; - - // Not during an actbusy - if ( m_ActBusyBehavior.IsActive() ) - return false; - if ( m_OperatorBehavior.IsRunning() ) - return false; - - // Can't be blinded if I've been in combat recently, to fix anim snaps - if ( GetLastEnemyTime() != 0.0 ) - { - if ( (gpGlobals->curtime - GetLastEnemyTime()) < 2 ) - return false; - } - - // Can't be blinded if I'm reloading - if ( IsCurSchedule(SCHED_RELOAD, false) ) - return false; - - // Can't be blinded right after being blind, to prevent oscillation - if ( gpGlobals->curtime < m_flDontBlindUntil ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Alyx::PlayerFlashlightOnMyEyes( CBasePlayer *pPlayer ) -{ - Vector vecEyes, vecPlayerForward; - vecEyes = EyePosition(); - pPlayer->EyeVectors( &vecPlayerForward ); - - Vector vecToEyes = (vecEyes - pPlayer->EyePosition()); - float flDist = VectorNormalize( vecToEyes ); - - // We can be blinded in daylight, but only at close range - if ( HL2GameRules()->IsAlyxInDarknessMode() == false ) - { - if ( flDist > (8*12.0f) ) - return false; - } - - float flDot = DotProduct( vecPlayerForward, vecToEyes ); - if ( flDot < 0.98 ) - return false; - - // Check facing to ensure we're in front of her - Vector los = ( pPlayer->EyePosition() - vecEyes ); - los.z = 0; - VectorNormalize( los ); - Vector facingDir = EyeDirection2D(); - flDot = DotProduct( los, facingDir ); - return ( flDot > 0.3 ); -} - -//----------------------------------------------------------------------------- -// Purpose: Checks if Alyx is blinded by a flare -// Input : -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Alyx::BlindedByFlare( void ) -{ - Vector vecEyes = EyePosition(); - - Vector los; - Vector vecToEyes; - Vector facingDir = EyeDirection2D(); - - // use a wider radius when she's already blind to help with edge cases - // where she flickers back and forth due to animation - float fBlindDist = ( m_bIsFlashlightBlind ) ? 35.0f : 30.0f; - - CFlare *pFlare = CFlare::GetActiveFlares(); - while( pFlare != NULL ) - { - vecToEyes = (vecEyes - pFlare->GetAbsOrigin()); - float fDist = VectorNormalize( vecToEyes ); - if ( fDist < fBlindDist ) - { - // Check facing to ensure we're in front of her - los = ( pFlare->GetAbsOrigin() - vecEyes ); - los.z = 0; - VectorNormalize( los ); - float flDot = DotProduct( los, facingDir ); - if ( ( flDot > 0.3 ) && FVisible( pFlare ) ) - { - return true; - } - } - - pFlare = pFlare->GetNextFlare(); - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Alyx::CanReload( void ) -{ - if ( m_bIsFlashlightBlind ) - return false; - - return BaseClass::CanReload(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Alyx::PickTacticalLookTarget( AILookTargetArgs_t *pArgs ) -{ - if( HasInteractTarget() ) - { - pArgs->hTarget = GetInteractTarget(); - pArgs->flInfluence = 0.8f; - pArgs->flDuration = 3.0f; - return true; - } - - if( m_ActBusyBehavior.IsActive() && m_ActBusyBehavior.IsCombatActBusy() ) - { - return false; - } - - return BaseClass::PickTacticalLookTarget( pArgs ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Alyx::OnSelectedLookTarget( AILookTargetArgs_t *pArgs ) -{ - if ( pArgs && pArgs->hTarget ) - { - // If it's a stealth target, we want to go into stealth mode - CAI_Hint *pHint = dynamic_cast(pArgs->hTarget.Get()); - if ( pHint && pHint->HintType() == HINT_WORLD_VISUALLY_INTERESTING_STEALTH ) - { - SetReadinessLevel( AIRL_STEALTH, true, true ); - pArgs->flDuration = 9999999; - m_hStealthLookTarget = pHint; - return; - } - } - - // If we're in stealth mode, break out now - if ( GetReadinessLevel() == AIRL_STEALTH ) - { - SetReadinessLevel( AIRL_STIMULATED, true, true ); - if ( m_hStealthLookTarget ) - { - ClearLookTarget( m_hStealthLookTarget ); - m_hStealthLookTarget = NULL; - } - } -} - -//----------------------------------------------------------------------------- -// Output : Behavior to use -//----------------------------------------------------------------------------- -CAI_FollowBehavior &CNPC_Alyx::GetFollowBehavior( void ) -{ - // Use the base class - return m_FollowBehavior; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Alyx::AimGun( void ) -{ - if (m_FuncTankBehavior.IsMounted()) - { - m_FuncTankBehavior.AimGun(); - return; - } - - // Always allow the passenger behavior to handle this - if ( m_PassengerBehavior.IsEnabled() ) - { - m_PassengerBehavior.AimGun(); - return; - } - - if( !GetEnemy() ) - { - if ( GetReadinessLevel() == AIRL_STEALTH && m_hStealthLookTarget != NULL ) - { - // Only aim if we're not far from the node - Vector vecAimDir = m_hStealthLookTarget->GetAbsOrigin() - Weapon_ShootPosition(); - if ( VectorNormalize( vecAimDir ) > 80 ) - { - // Ignore nodes that are behind her - Vector vecForward; - GetVectors( &vecForward, NULL, NULL ); - float flDot = DotProduct( vecAimDir, vecForward ); - if ( flDot > 0 ) - { - SetAim( vecAimDir); - return; - } - } - } - } - - BaseClass::AimGun(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Vector CNPC_Alyx::GetActualShootPosition( const Vector &shootOrigin ) -{ - if( HasShotgun() && GetEnemy() && GetEnemy()->Classify() == CLASS_ZOMBIE && random->RandomInt( 0, 1 ) == 1 ) - { - // 50-50 zombie headshots with shotgun! - return GetEnemy()->HeadTarget( shootOrigin ); - } - - return BaseClass::GetActualShootPosition( shootOrigin ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_Alyx::EnemyIsValidCrouchTarget( CBaseEntity *pEnemy ) -{ - // Don't crouch to shoot flying enemies (or jumping antlions) - if ( !(pEnemy->GetFlags() & FL_ONGROUND) ) - return false; - - // Don't crouch to shoot if we couldn't see them while crouching - if ( !CouldShootIfCrouching( pEnemy ) ) - { - //Warning("CROUCH: Not valid due to crouch-no-LOS.\n" ); - return false; - } - - // Don't crouch to shoot enemies that are close to me - if ( EnemyDistance( pEnemy ) <= ALYX_MIN_ENEMY_DIST_TO_CROUCH ) - { - //Warning("CROUCH: Not valid due to enemy-too-close.\n" ); - return false; - } - - // Don't crouch to shoot enemies that are too far off my vertical plane - if ( fabs( pEnemy->GetAbsOrigin().z - GetAbsOrigin().z ) > 64 ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: degrees to turn in 0.1 seconds -//----------------------------------------------------------------------------- -float CNPC_Alyx::MaxYawSpeed( void ) -{ - if ( IsCrouching() ) - return 10; - - return BaseClass::MaxYawSpeed(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_Alyx::Stand( void ) -{ - bool bWasCrouching = IsCrouching(); - if ( !BaseClass::Stand() ) - return false; - - if ( bWasCrouching ) - { - m_flNextCrouchTime = gpGlobals->curtime + ALYX_CROUCH_DELAY; - OnUpdateShotRegulator(); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_Alyx::Crouch( void ) -{ - if ( !npc_alyx_crouch.GetBool() ) - return false; - - // Alyx will ignore crouch requests while she has the shotgun - if ( HasShotgun() ) - return false; - - bool bWasStanding = !IsCrouching(); - if ( !BaseClass::Crouch() ) - return false; - - if ( bWasStanding ) - { - OnUpdateShotRegulator(); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Alyx::DesireCrouch( void ) -{ - // Ignore crouch desire if we've been crouching recently to reduce oscillation - if ( m_flNextCrouchTime > gpGlobals->curtime ) - return; - - BaseClass::DesireCrouch(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Tack on extra criteria for responses -//----------------------------------------------------------------------------- -void CNPC_Alyx::ModifyOrAppendCriteria( AI_CriteriaSet &set ) -{ - AIEnemiesIter_t iter; - float fLengthOfLastCombat; - int iNumEnemies; - - if ( GetState() == NPC_STATE_COMBAT ) - { - fLengthOfLastCombat = gpGlobals->curtime - m_fCombatStartTime; - } - else - { - fLengthOfLastCombat = m_fCombatEndTime - m_fCombatStartTime; - } - - set.AppendCriteria( "combat_length", UTIL_VarArgs( "%.3f", fLengthOfLastCombat ) ); - - iNumEnemies = 0; - for ( AI_EnemyInfo_t *pEMemory = GetEnemies()->GetFirst(&iter); pEMemory != NULL; pEMemory = GetEnemies()->GetNext(&iter) ) - { - if ( pEMemory->hEnemy->IsAlive() && ( pEMemory->hEnemy->Classify() != CLASS_BULLSEYE ) ) - { - iNumEnemies++; - } - } - set.AppendCriteria( "num_enemies", UTIL_VarArgs( "%d", iNumEnemies ) ); - set.AppendCriteria( "darkness_mode", UTIL_VarArgs( "%d", HasCondition( COND_ALYX_IN_DARK ) ) ); - set.AppendCriteria( "water_level", UTIL_VarArgs( "%d", GetWaterLevel() ) ); - - CHL2_Player *pPlayer = assert_cast( UTIL_PlayerByIndex( 1 ) ); - set.AppendCriteria( "num_companions", UTIL_VarArgs( "%d", pPlayer ? pPlayer->GetNumSquadCommandables() : 0 ) ); - set.AppendCriteria( "flashlight_on", UTIL_VarArgs( "%d", pPlayer ? pPlayer->FlashlightIsOn() : 0 ) ); - - BaseClass::ModifyOrAppendCriteria( set ); -} - -//----------------------------------------------------------------------------- -// Purpose: Turn off Alyx's readiness when she's around a vehicle -//----------------------------------------------------------------------------- -bool CNPC_Alyx::IsReadinessCapable( void ) -{ - // Let the convar decide - return npc_alyx_readiness.GetBool();; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Alyx::IsAllowedToInteract() -{ - if ( RunningPassengerBehavior() ) - return false; - - if( IsInAScript() ) - return false; - - if( IsCurSchedule(SCHED_SCENE_GENERIC) ) - return false; - - if( GetEnemy() ) - { - if( GetEnemy()->GetAbsOrigin().DistTo( GetAbsOrigin() ) <= 240.0f ) - { - // Enemy is nearby! - return false; - } - } - - return m_bInteractionAllowed; -} - -//----------------------------------------------------------------------------- -// Purpose: Allows the NPC to react to being given a weapon -// Input : *pNewWeapon - Weapon given -//----------------------------------------------------------------------------- -void CNPC_Alyx::OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ) -{ - m_WeaponType = ComputeWeaponType(); - BaseClass::OnChangeActiveWeapon( pOldWeapon, pNewWeapon ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Allows the NPC to react to being given a weapon -// Input : *pNewWeapon - Weapon given -//----------------------------------------------------------------------------- -void CNPC_Alyx::OnGivenWeapon( CBaseCombatWeapon *pNewWeapon ) -{ - // HACK: This causes Alyx to pull her gun from a holstered position - if ( pNewWeapon->ClassMatches( CLASSNAME_ALYXGUN ) ) - { - // Put it away so we can pull it out properly - GetActiveWeapon()->Holster(); - SetActiveWeapon( NULL ); - - // Draw the weapon when we're next able to - SetDesiredWeaponState( DESIREDWEAPONSTATE_UNHOLSTERED ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Alyx::Weapon_Equip( CBaseCombatWeapon *pWeapon ) -{ - m_WeaponType = ComputeWeaponType( pWeapon ); - BaseClass::Weapon_Equip( pWeapon ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Alyx::Weapon_CanUse( CBaseCombatWeapon *pWeapon ) -{ - if( !pWeapon->ClassMatches( CLASSNAME_SHOTGUN ) ) - return false; - - return BaseClass::Weapon_CanUse( pWeapon ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -//----------------------------------------------------------------------------- -void CNPC_Alyx::OnUpdateShotRegulator( ) -{ - BaseClass::OnUpdateShotRegulator(); - - if ( !HasShotgun() && IsCrouching() ) - { - // While crouching, Alyx fires longer bursts - int iMinBurst, iMaxBurst; - GetShotRegulator()->GetBurstShotCountRange( &iMinBurst, &iMaxBurst ); - GetShotRegulator()->SetBurstShotCountRange( iMinBurst * 2, iMaxBurst * 2 ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Alyx::BarnacleDeathSound( void ) -{ - Speak( TLK_SELF_IN_BARNACLE ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : PassengerState_e -//----------------------------------------------------------------------------- -PassengerState_e CNPC_Alyx::GetPassengerState( void ) -{ - return m_PassengerBehavior.GetPassengerState(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Alyx::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - // if I'm in the vehicle, the player is probably trying to use the vehicle - if ( GetPassengerState() == PASSENGER_STATE_INSIDE && pActivator->IsPlayer() && GetParent() ) - { - GetParent()->Use( pActivator, pCaller, useType, value ); - return; - } - m_bDontUseSemaphore = true; - SpeakIfAllowed( TLK_USE ); - m_bDontUseSemaphore = false; - - m_OnPlayerUse.FireOutput( pActivator, pCaller ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_Alyx::PlayerInSpread( const Vector &sourcePos, const Vector &targetPos, float flSpread, float maxDistOffCenter, bool ignoreHatedPlayers ) -{ - // loop through all players - for (int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - - if ( pPlayer && ( !ignoreHatedPlayers || IRelationType( pPlayer ) != D_HT ) ) - { - //If the player is being lifted by a barnacle then go ahead and ignore the player and shoot. -#ifdef HL2_EPISODIC - if ( pPlayer->IsEFlagSet( EFL_IS_BEING_LIFTED_BY_BARNACLE ) ) - return false; -#endif - - if ( PointInSpread( pPlayer, sourcePos, targetPos, pPlayer->WorldSpaceCenter(), flSpread, maxDistOffCenter ) ) - return true; - } - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_Alyx::IsCrouchedActivity( Activity activity ) -{ - Activity realActivity = TranslateActivity(activity); - - switch ( realActivity ) - { - case ACT_RELOAD_LOW: - case ACT_COVER_LOW: - case ACT_COVER_PISTOL_LOW: - case ACT_COVER_SMG1_LOW: - case ACT_RELOAD_SMG1_LOW: - - // Aren't these supposed to be a little higher than the above? - case ACT_RANGE_ATTACK1_LOW: - case ACT_RANGE_ATTACK2_LOW: - case ACT_RANGE_ATTACK_AR2_LOW: - case ACT_RANGE_ATTACK_SMG1_LOW: - case ACT_RANGE_ATTACK_SHOTGUN_LOW: - case ACT_RANGE_ATTACK_PISTOL_LOW: - case ACT_RANGE_AIM_LOW: - case ACT_RANGE_AIM_SMG1_LOW: - case ACT_RANGE_AIM_PISTOL_LOW: - case ACT_RANGE_AIM_AR2_LOW: - return true; - - default: - break; - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_Alyx::OnBeginMoveAndShoot() -{ - if ( BaseClass::OnBeginMoveAndShoot() ) - { - SpeakAttacking(); - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Alyx::SpeakAttacking( void ) -{ - if ( GetActiveWeapon() && m_AnnounceAttackTimer.Expired() ) - { - SpeakIfAllowed( TLK_ATTACKING, UTIL_VarArgs("attacking_with_weapon:%s", GetActiveWeapon()->GetClassname()) ); - m_AnnounceAttackTimer.Set( 3, 5 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *lpszInteractionName - -// *pOther - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Alyx::ForceVehicleInteraction( const char *lpszInteractionName, CBaseCombatCharacter *pOther ) -{ - return m_PassengerBehavior.ForceVehicleInteraction( lpszInteractionName, pOther ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CNPC_Alyx::WeaponType_t CNPC_Alyx::ComputeWeaponType( CBaseEntity *pWeapon ) -{ - if ( !pWeapon ) - { - pWeapon = GetActiveWeapon(); - } - - if ( !pWeapon ) - { - return WT_NONE; - } - - if ( pWeapon->ClassMatches( CLASSNAME_ALYXGUN ) ) - { - return WT_ALYXGUN; - } - - if ( pWeapon->ClassMatches( CLASSNAME_SMG1 ) ) - { - return WT_SMG1; - } - - if ( pWeapon->ClassMatches( CLASSNAME_SHOTGUN ) ) - { - return WT_SHOTGUN; - } - - if ( pWeapon->ClassMatches( CLASSNAME_AR2 ) ) - { - return WT_AR2; - } - - return WT_OTHER; -} - -//----------------------------------------------------------------------------- -// Purpose: Complain about being punted -//----------------------------------------------------------------------------- -void CNPC_Alyx::InputVehiclePunted( inputdata_t &inputdata ) -{ - // If we're in a vehicle, complain about being punted - if ( IsInAVehicle() && GetVehicleEntity() == inputdata.pCaller ) - { - // FIXME: Pass this up into the behavior? - SpeakIfAllowed( TLK_PASSENGER_PUNTED ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_Alyx::InputOutsideTransition( inputdata_t &inputdata ) -{ - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer && pPlayer->IsInAVehicle() ) - { - if ( ShouldAlwaysTransition() == false ) - return; - - // Enter immediately - EnterVehicle( pPlayer->GetVehicleEntity(), true ); - return; - } - - // If the player is in the vehicle and we're not, then we need to enter the vehicle immediately - BaseClass::InputOutsideTransition( inputdata ); -} - -//========================================================= -// AI Schedules Specific to this NPC -//========================================================= - -AI_BEGIN_CUSTOM_NPC( npc_alyx, CNPC_Alyx ) - - DECLARE_TASK( TASK_ALYX_BEGIN_INTERACTION ) - DECLARE_TASK( TASK_ALYX_COMPLETE_INTERACTION ) - DECLARE_TASK( TASK_ALYX_ANNOUNCE_HACK ) - DECLARE_TASK( TASK_ALYX_GET_PATH_TO_INTERACT_TARGET ) - DECLARE_TASK( TASK_ALYX_WAIT_HACKING ) - DECLARE_TASK( TASK_ALYX_DRAW_PISTOL ) - DECLARE_TASK( TASK_ALYX_HOLSTER_PISTOL ) - DECLARE_TASK( TASK_ALYX_HOLSTER_AND_DESTROY_PISTOL ) - DECLARE_TASK( TASK_ALYX_BUILD_COMBAT_FACE_PATH ) - DECLARE_TASK( TASK_ALYX_SET_IDLE_ACTIVITY ) - DECLARE_TASK( TASK_ALYX_FALL_TO_GROUND ) - - DECLARE_ANIMEVENT( AE_ALYX_EMPTOOL_ATTACHMENT ) - DECLARE_ANIMEVENT( AE_ALYX_EMPTOOL_SEQUENCE ) - DECLARE_ANIMEVENT( AE_ALYX_EMPTOOL_USE ) - DECLARE_ANIMEVENT( COMBINE_AE_BEGIN_ALTFIRE ) - DECLARE_ANIMEVENT( COMBINE_AE_ALTFIRE ) - - DECLARE_CONDITION( COND_ALYX_HAS_INTERACT_TARGET ) - DECLARE_CONDITION( COND_ALYX_NO_INTERACT_TARGET ) - DECLARE_CONDITION( COND_ALYX_CAN_INTERACT_WITH_TARGET ) - DECLARE_CONDITION( COND_ALYX_CAN_NOT_INTERACT_WITH_TARGET ) - DECLARE_CONDITION( COND_ALYX_PLAYER_TURNED_ON_FLASHLIGHT ) - DECLARE_CONDITION( COND_ALYX_PLAYER_TURNED_OFF_FLASHLIGHT ) - DECLARE_CONDITION( COND_ALYX_PLAYER_FLASHLIGHT_EXPIRED ) - DECLARE_CONDITION( COND_ALYX_IN_DARK ) - - DECLARE_ACTIVITY( ACT_ALYX_DRAW_TOOL ) - DECLARE_ACTIVITY( ACT_ALYX_IDLE_TOOL ) - DECLARE_ACTIVITY( ACT_ALYX_ZAP_TOOL ) - DECLARE_ACTIVITY( ACT_ALYX_HOLSTER_TOOL ) - DECLARE_ACTIVITY( ACT_ALYX_PICKUP_RACK ) - - DEFINE_SCHEDULE - ( - SCHED_ALYX_PREPARE_TO_INTERACT_WITH_TARGET, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_ALYX_DRAW_TOOL" - " TASK_SET_ACTIVITY ACTIVITY:ACT_ALYX_IDLE_TOOL" - " TASK_FACE_PLAYER 0" - "" - " Interrupts" - "" - ) - - DEFINE_SCHEDULE - ( - SCHED_ALYX_WAIT_TO_INTERACT_WITH_TARGET, - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_ALYX_ANNOUNCE_HACK 0" - " TASK_FACE_PLAYER 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_ALYX_IDLE_TOOL" - " TASK_WAIT 2" - "" - " Interrupts" - " COND_ALYX_CAN_INTERACT_WITH_TARGET" - " COND_ALYX_NO_INTERACT_TARGET" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - ) - - DEFINE_SCHEDULE - ( - SCHED_ALYX_INTERACT_WITH_TARGET, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_PLAYER 0" - " TASK_ALYX_BEGIN_INTERACTION 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_ALYX_ZAP_TOOL" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_ALYX_FINISH_INTERACTING_WITH_TARGET" - "" - " Interrupts" - " COND_ALYX_NO_INTERACT_TARGET" - " COND_ALYX_CAN_NOT_INTERACT_WITH_TARGET" - ) - - DEFINE_SCHEDULE - ( - SCHED_ALYX_FINISH_INTERACTING_WITH_TARGET, - - " Tasks" - " TASK_ALYX_COMPLETE_INTERACTION 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_ALYX_HOLSTER_TOOL" - "" - " Interrupts" - "" - ) - - DEFINE_SCHEDULE - ( - SCHED_ALYX_HOLSTER_EMP, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_ALYX_HOLSTER_TOOL" - " TASK_ALYX_DRAW_PISTOL 0" - "" - " Interrupts" - "" - ) - - DEFINE_SCHEDULE - ( - SCHED_ALYX_INTERACTION_INTERRUPTED, - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_FACE_PLAYER 0" - " TASK_WAIT 2" - "" - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_ALYX_ALERT_FACE_AWAYFROM_BESTSOUND, - " Tasks" - " TASK_STORE_BESTSOUND_REACTORIGIN_IN_SAVEPOSITION 0" - " TASK_STOP_MOVING 0" - " TASK_FACE_AWAY_FROM_SAVEPOSITION 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT 10.0" - " TASK_FACE_REASONABLE 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_FEAR" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_PROVOKED" - ) - - //=============================================== - // > RangeAttack1 - //=============================================== - DEFINE_SCHEDULE - ( - SCHED_ALYX_RANGE_ATTACK1, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_ANNOUNCE_ATTACK 1" // 1 = primary attack - " TASK_RANGE_ATTACK1 0" - "" - " Interrupts" - " COND_ENEMY_WENT_NULL" - " COND_HEAVY_DAMAGE" - " COND_ENEMY_OCCLUDED" - " COND_NO_PRIMARY_AMMO" - " COND_HEAR_DANGER" - " COND_WEAPON_BLOCKED_BY_FRIEND" - " COND_WEAPON_SIGHT_OCCLUDED" - ) - - //=============================================== - // > SCHED_ALYX_ALERT_REACT_TO_COMBAT_SOUND - //=============================================== - DEFINE_SCHEDULE - ( - SCHED_ALYX_ALERT_REACT_TO_COMBAT_SOUND, - - " Tasks" - " TASK_REACT_TO_COMBAT_SOUND 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_ALERT_FACE_BESTSOUND" - "" - " Interrupts" - " COND_NEW_ENEMY" - ) - - //========================================================= - // > SCHED_ALYX_COMBAT_FACE - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_ALYX_COMBAT_FACE, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_COMBAT_FACE" - " TASK_STOP_MOVING 0" - " TASK_ALYX_BUILD_COMBAT_FACE_PATH 0" - " TASK_RUN_PATH 0" - " TASK_FACE_IDEAL 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - ) - - //========================================================= - // > SCHED_ALYX_WAKE_ANGRY - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_ALYX_WAKE_ANGRY, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SOUND_WAKE 0" - "" - " Interrupts" - ) - - //=============================================== - // > NewWeapon - //=============================================== - DEFINE_SCHEDULE - ( - SCHED_ALYX_NEW_WEAPON, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_TOLERANCE_DISTANCE 5" - " TASK_GET_PATH_TO_TARGET_WEAPON 0" - " TASK_WEAPON_RUN_PATH 0" - " TASK_STOP_MOVING 0" - " TASK_ALYX_HOLSTER_AND_DESTROY_PISTOL 0" - " TASK_FACE_TARGET 0" - " TASK_WEAPON_PICKUP 0" - " TASK_WAIT 1"// Don't move before done standing up - "" - " Interrupts" - ) - - //=============================================== - // > Alyx_Idle_Stand - //=============================================== - DEFINE_SCHEDULE - ( - SCHED_ALYX_IDLE_STAND, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_ALYX_SET_IDLE_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT 5" - " TASK_WAIT_PVS 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_FEAR" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_SMELL" - " COND_PROVOKED" - " COND_GIVE_WAY" - " COND_HEAR_PLAYER" - " COND_HEAR_DANGER" - " COND_HEAR_COMBAT" - " COND_HEAR_BULLET_IMPACT" - " COND_IDLE_INTERRUPT" - ) - - //=============================================== - // Makes Alyx die if she falls too long - //=============================================== - DEFINE_SCHEDULE - ( - SCHED_ALYX_FALL_TO_GROUND, - - " Tasks" - " TASK_ALYX_FALL_TO_GROUND 0" - "" - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_ALYX_ALERT_FACE_BESTSOUND, - - " Tasks" - " TASK_STORE_BESTSOUND_REACTORIGIN_IN_SAVEPOSITION 0" - " TASK_STOP_MOVING 0" - " TASK_FACE_SAVEPOSITION 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_FEAR" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_PROVOKED" - ); - -AI_END_CUSTOM_NPC() diff --git a/game/server/hl2/npc_alyx_episodic.h b/game/server/hl2/npc_alyx_episodic.h deleted file mode 100644 index 01e0c32d6..000000000 --- a/game/server/hl2/npc_alyx_episodic.h +++ /dev/null @@ -1,289 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Base combat character with no AI -// -//=====================================================================================// - -#include "ai_baseactor.h" -#include "npc_playercompanion.h" -#include "ai_behavior_holster.h" -#include "ai_behavior_functank.h" -#include "soundenvelope.h" - -extern ConVar npc_alyx_readiness; - -class CNPC_Alyx : public CNPC_PlayerCompanion -{ -public: - DECLARE_CLASS( CNPC_Alyx, CNPC_PlayerCompanion ); - - // fast class list - CNPC_Alyx *m_pNext; - - virtual void ModifyOrAppendCriteria( AI_CriteriaSet &set ); - - bool ForceVehicleInteraction( const char *lpszInteractionName, CBaseCombatCharacter *pOther ); - - CNPC_Alyx( ); - ~CNPC_Alyx( ); - - static CNPC_Alyx *GetAlyx( void ); - - bool CreateBehaviors(); - void Spawn( void ); - void Activate( void ); - void StopLoopingSounds( void ); - void SelectModel(); - void Precache( void ); - void SetupAlyxWithoutParent( void ); - void CreateEmpTool( void ); - void PrescheduleThink( void ); - void GatherConditions(); - bool ShouldPlayerAvoid( void ); - void AnalyzeGunfireSound( CSound *pSound ); - bool IsValidEnemy( CBaseEntity *pEnemy ); - void Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info ); - void Event_Killed( const CTakeDamageInfo &info ); - void EnemyIgnited( CAI_BaseNPC *pVictim ); - void CombineBallSocketed( int iNumBounces ); - void AimGun( void ); - Vector GetActualShootPosition( const Vector &shootOrigin ); - float MaxYawSpeed( void ); - void OnUpdateShotRegulator(); - bool IsCrouchedActivity( Activity activity ); - bool OnBeginMoveAndShoot(); - void SpeakAttacking( void ); - - virtual float GetJumpGravity() const { return 1.8f; } - - // Crouching - Vector GetCrouchEyeOffset( void ) { return Vector(0,0,50); } - Vector GetCrouchGunOffset( void ) { return Vector(0,0,40); } - bool EnemyIsValidCrouchTarget( CBaseEntity *pEnemy ); - bool Stand( void ); - bool Crouch( void ); - void DesireCrouch( void ); - - // Custom AI - void DoCustomCombatAI( void ); - void DoMobbedCombatAI( void ); - void DoCustomSpeechAI( void ); - - Disposition_t IRelationType( CBaseEntity *pTarget ); - int IRelationPriority( CBaseEntity *pTarget ); - - CAI_FollowBehavior &GetFollowBehavior( void ); - - Class_T Classify ( void ); - bool FValidateHintType( CAI_Hint *pHint ); - int ObjectCaps(); - void HandleAnimEvent( animevent_t *pEvent ); - bool FInViewCone( CBaseEntity *pEntity ); - bool QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC = false ); - bool CanSeeEntityInDarkness( CBaseEntity *pEntity ); - bool IsCoverPosition( const Vector &vecThreat, const Vector &vecPosition ); - Activity NPC_TranslateActivity ( Activity activity ); - bool ShouldDeferToFollowBehavior(); - void BuildScheduleTestBits(); - bool ShouldBehaviorSelectSchedule( CAI_BehaviorBase *pBehavior ); - int SelectSchedule( void ); - int SelectScheduleDanger( void ); - int TranslateSchedule( int scheduleType ); - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - void OnStateChange( NPC_STATE OldState, NPC_STATE NewState ); - float LengthOfLastCombat( void ) const; - // bool IsNavigationUrgent(); - - void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - bool CanBeHitByMeleeAttack( CBaseEntity *pAttacker ); - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - bool FCanCheckAttacks(); - float GetAttackDamageScale( CBaseEntity *pVictim ); - - - bool HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt); - virtual bool SpeakIfAllowed( AIConcept_t concept, const char *modifiers = NULL, bool bRespondingToPlayer = false, char *pszOutResponseChosen = NULL, size_t bufsize = 0 ); - - void HolsterPistol(); - void DrawPistol(); - void Weapon_Drop( CBaseCombatWeapon *pWeapon, const Vector *pvecTarget = NULL, const Vector *pVelocity = NULL ); - - void SetEMPHolstered( bool bHolstered ) { m_bIsEMPHolstered = bHolstered; } - bool IsEMPHolstered() { return (!m_hEmpTool || m_hEmpTool->GetParent() != this || m_bIsEMPHolstered); } - - float GetReadinessDecay() { return 60.0f; } - virtual bool IsAllowedToAim(); - - virtual void PainSound( const CTakeDamageInfo &info ); - virtual void DeathSound( const CTakeDamageInfo &info ); - - // Hacking and object interaction - void SearchForInteractTargets(); - bool IsValidInteractTarget( CBaseEntity *pTarget ); - bool CanInteractWithTarget( CBaseEntity *pTarget ); - void SetInteractTarget( CBaseEntity *pTarget ); - bool HasInteractTarget() { return m_hHackTarget != NULL; } - CBaseEntity *GetInteractTarget() { return m_hHackTarget; } - void EmpZapTarget( CBaseEntity *pTarget ); - - virtual void OnSeeEntity( CBaseEntity *pEntity ); - - void InputAllowInteraction( inputdata_t &inputdata ) - { - m_bInteractionAllowed = true; - } - void InputDisallowInteraction( inputdata_t &inputdata ) - { - m_bInteractionAllowed = false; - } - void InputAllowDarknessSpeech( inputdata_t &inputdata ) - { - m_bDarknessSpeechAllowed = inputdata.value.Bool(); - } - void InputGiveEMP( inputdata_t &inputdata ); - void InputVehiclePunted( inputdata_t &inputdata ); - void InputOutsideTransition( inputdata_t &inputdata ); - - virtual void OnGivenWeapon( CBaseCombatWeapon *pNewWeapon ); - virtual void OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ); - virtual void Weapon_Equip( CBaseCombatWeapon *pWeapon ); - virtual bool Weapon_CanUse( CBaseCombatWeapon *pWeapon ); - - // Blinding - virtual void PlayerHasIlluminatedNPC( CBasePlayer *pPlayer, float flDot ); - void CheckBlindedByFlare( void ); - bool CanBeBlindedByFlashlight( bool bCheckLightSources ); - bool PlayerFlashlightOnMyEyes( CBasePlayer *pPlayer ); - bool BlindedByFlare( void ); - bool CanReload( void ); - - virtual bool PickTacticalLookTarget( AILookTargetArgs_t *pArgs ); - virtual void OnSelectedLookTarget( AILookTargetArgs_t *pArgs ); - virtual bool IsReadinessCapable( void ); - - virtual void ReadinessLevelChanged( int iPriorLevel ); - - bool IsAllowedToInteract(); - virtual void BarnacleDeathSound( void ); - - virtual const char *GetDeathMessageText( void ) { return "GAMEOVER_ALYXDEAD"; } - - PassengerState_e GetPassengerState( void ); - - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - bool PlayerInSpread( const Vector &sourcePos, const Vector &targetPos, float flSpread, float maxDistOffCenter, bool ignoreHatedPlayers ); - -private: - EHANDLE m_hEmpTool; - EHANDLE m_hHackTarget; - CHandle m_hStealthLookTarget; - bool m_bInteractionAllowed; - float m_fTimeNextSearchForInteractTargets; - bool m_bDarknessSpeechAllowed; - bool m_bIsEMPHolstered; - bool m_bIsFlashlightBlind; - float m_fStayBlindUntil; - float m_flDontBlindUntil; - bool m_bSpokeLostPlayerInDarkness; - bool m_bPlayerFlashlightState; - bool m_bHadCondSeeEnemy; - string_t m_iszCurrentBlindScene; - float m_fTimeUntilNextDarknessFoundPlayer; - float m_fCombatStartTime; - float m_fCombatEndTime; - float m_flNextCrouchTime; - - CSoundPatch *m_sndDarknessBreathing; - - // Speech timers - // Theoretically, these shouldn't be needed. Instead, each response - // should prevent the concept being spoken for the desired time. But - // until the responses exists, Alyx will spam the response rules forever, - // so these timers stop that. - CRandStopwatch m_SpeechWatch_LostPlayer; - CSimpleSimTimer m_SpeechTimer_HeardSound; - CRandStopwatch m_SpeechWatch_SoundDelay; - CRandStopwatch m_SpeechWatch_BreathingRamp; - CRandStopwatch m_SpeechWatch_FoundPlayer; - - CAI_MoveMonitor m_MoveMonitor; - - enum WeaponType_t - { - WT_NONE, - WT_ALYXGUN, - WT_SMG1, - WT_SHOTGUN, - WT_AR2, - WT_OTHER, - }; - - int m_WeaponType; - - bool m_bShouldHaveEMP; - - CAI_FuncTankBehavior m_FuncTankBehavior; - - COutputEvent m_OnFinishInteractWithObject; - COutputEvent m_OnPlayerUse; - - bool RunningPassengerBehavior( void ); - - WeaponType_t ComputeWeaponType( CBaseEntity *pWeapon = NULL ); - WeaponType_t GetWeaponType() { return (WeaponType_t)m_WeaponType; } - bool HasShotgun() { Assert( m_WeaponType == ComputeWeaponType() ); return ( m_WeaponType == WT_SHOTGUN ); } - bool HasAlyxgun() { Assert( m_WeaponType == ComputeWeaponType() ); return ( m_WeaponType == WT_ALYXGUN ); } - bool HasAR2() { Assert( m_WeaponType == ComputeWeaponType() ); return ( m_WeaponType == WT_AR2 ); } - -private: - enum - { - COND_ALYX_HAS_INTERACT_TARGET = BaseClass::NEXT_CONDITION, - COND_ALYX_NO_INTERACT_TARGET, - COND_ALYX_CAN_INTERACT_WITH_TARGET, // Hack target is in a suitable state and location to hack - COND_ALYX_CAN_NOT_INTERACT_WITH_TARGET, - COND_ALYX_PLAYER_TURNED_ON_FLASHLIGHT, - COND_ALYX_PLAYER_TURNED_OFF_FLASHLIGHT, - COND_ALYX_PLAYER_FLASHLIGHT_EXPIRED, - COND_ALYX_IN_DARK, // lights are out and she can't see - }; - - enum - { - SCHED_ALYX_PREPARE_TO_INTERACT_WITH_TARGET = BaseClass::NEXT_SCHEDULE, - SCHED_ALYX_WAIT_TO_INTERACT_WITH_TARGET, - SCHED_ALYX_INTERACT_WITH_TARGET, - SCHED_ALYX_INTERACTION_INTERRUPTED, - SCHED_ALYX_FINISH_INTERACTING_WITH_TARGET, - SCHED_ALYX_HOLSTER_EMP, - SCHED_ALYX_ALERT_FACE_AWAYFROM_BESTSOUND, - SCHED_ALYX_RANGE_ATTACK1, - SCHED_ALYX_ALERT_REACT_TO_COMBAT_SOUND, - SCHED_ALYX_COMBAT_FACE, - SCHED_ALYX_WAKE_ANGRY, - SCHED_ALYX_NEW_WEAPON, - SCHED_ALYX_IDLE_STAND, - SCHED_ALYX_ALERT_FACE_BESTSOUND, - SCHED_ALYX_FALL_TO_GROUND, - }; - - enum - { - - TASK_ALYX_BEGIN_INTERACTION = BaseClass::NEXT_TASK, - TASK_ALYX_COMPLETE_INTERACTION, - TASK_ALYX_ANNOUNCE_HACK, - TASK_ALYX_GET_PATH_TO_INTERACT_TARGET, - TASK_ALYX_WAIT_HACKING, - TASK_ALYX_HOLSTER_PISTOL, - TASK_ALYX_DRAW_PISTOL, - TASK_ALYX_HOLSTER_AND_DESTROY_PISTOL, - TASK_ALYX_BUILD_COMBAT_FACE_PATH, - TASK_ALYX_SET_IDLE_ACTIVITY, - TASK_ALYX_FALL_TO_GROUND, - }; - - DECLARE_DATADESC(); - DEFINE_CUSTOM_AI; -}; diff --git a/game/server/hl2/npc_antlion.cpp b/game/server/hl2/npc_antlion.cpp deleted file mode 100644 index e0942b64c..000000000 --- a/game/server/hl2/npc_antlion.cpp +++ /dev/null @@ -1,5102 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Antlion - nasty bug -// -//=============================================================================// - -#include "cbase.h" -#include "ai_hint.h" -#include "ai_squad.h" -#include "ai_moveprobe.h" -#include "ai_route.h" -#include "npcevent.h" -#include "gib.h" -#include "entitylist.h" -#include "ndebugoverlay.h" -#include "antlion_dust.h" -#include "engine/IEngineSound.h" -#include "globalstate.h" -#include "movevars_shared.h" -#include "te_effect_dispatch.h" -#include "vehicle_base.h" -#include "mapentities.h" -#include "antlion_maker.h" -#include "npc_antlion.h" -#include "decals.h" -#include "hl2_shareddefs.h" -#include "explode.h" -#include "weapon_physcannon.h" -#include "baseparticleentity.h" -#include "props.h" -#include "particle_parse.h" -#include "ai_tacticalservices.h" - -#ifdef HL2_EPISODIC -#include "grenade_spit.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//Debug visualization -ConVar g_debug_antlion( "g_debug_antlion", "0" ); - -// base antlion stuff -ConVar sk_antlion_health( "sk_antlion_health", "0" ); -ConVar sk_antlion_swipe_damage( "sk_antlion_swipe_damage", "0" ); -ConVar sk_antlion_jump_damage( "sk_antlion_jump_damage", "0" ); -ConVar sk_antlion_air_attack_dmg( "sk_antlion_air_attack_dmg", "0" ); - - -#ifdef HL2_EPISODIC - -// workers -#define ANTLION_WORKERS_BURST() (true) -#define ANTLION_WORKER_BURST_IS_POISONOUS() (true) - -ConVar sk_antlion_worker_burst_damage( "sk_antlion_worker_burst_damage", "50", FCVAR_NONE, "How much damage is inflicted by an antlion worker's death explosion." ); -ConVar sk_antlion_worker_health( "sk_antlion_worker_health", "0", FCVAR_NONE, "Hitpoints of an antlion worker. If 0, will use base antlion hitpoints." ); -ConVar sk_antlion_worker_spit_speed( "sk_antlion_worker_spit_speed", "0", FCVAR_NONE, "Speed at which an antlion spit grenade travels." ); - -// This must agree with the AntlionWorkerBurstRadius() function! -ConVar sk_antlion_worker_burst_radius( "sk_antlion_worker_burst_radius", "160", FCVAR_NONE, "Effect radius of an antlion worker's death explosion." ); - -#endif - -ConVar g_test_new_antlion_jump( "g_test_new_antlion_jump", "1", FCVAR_ARCHIVE ); -ConVar antlion_easycrush( "antlion_easycrush", "1" ); -ConVar g_antlion_cascade_push( "g_antlion_cascade_push", "1", FCVAR_ARCHIVE ); - -ConVar g_debug_antlion_worker( "g_debug_antlion_worker", "0" ); - -extern ConVar bugbait_radius; - -int AE_ANTLION_WALK_FOOTSTEP; -int AE_ANTLION_MELEE_HIT1; -int AE_ANTLION_MELEE_HIT2; -int AE_ANTLION_MELEE_POUNCE; -int AE_ANTLION_FOOTSTEP_SOFT; -int AE_ANTLION_FOOTSTEP_HEAVY; -int AE_ANTLION_START_JUMP; -int AE_ANTLION_BURROW_IN; -int AE_ANTLION_BURROW_OUT; -int AE_ANTLION_VANISH; -int AE_ANTLION_OPEN_WINGS; -int AE_ANTLION_CLOSE_WINGS; -int AE_ANTLION_MELEE1_SOUND; -int AE_ANTLION_MELEE2_SOUND; -int AE_ANTLION_WORKER_EXPLODE_SCREAM; -int AE_ANTLION_WORKER_EXPLODE_WARN; -int AE_ANTLION_WORKER_EXPLODE; -int AE_ANTLION_WORKER_SPIT; -int AE_ANTLION_WORKER_DONT_EXPLODE; - - -//Attack range definitions -#define ANTLION_MELEE1_RANGE 100.0f -#define ANTLION_MELEE2_RANGE 64.0f -#define ANTLION_MELEE2_RANGE_MAX 175.0f -#define ANTLION_MELEE2_RANGE_MIN 64.0f -#define ANTLION_JUMP_MIN 128.0f - -#define ANTLION_JUMP_MAX_RISE 512.0f -#define ANTLION_JUMP_MAX 1024.0f - -#define ANTLION_MIN_BUGBAIT_GOAL_TARGET_RADIUS 512 - -//Interaction IDs -int g_interactionAntlionFoundTarget = 0; -int g_interactionAntlionFiredAtTarget = 0; - -#define ANTLION_MODEL "models/antlion.mdl" -#define ANTLION_WORKER_MODEL "models/antlion_worker.mdl" - -#define ANTLION_BURROW_IN 0 -#define ANTLION_BURROW_OUT 1 - -#define ANTLION_BUGBAIT_NAV_TOLERANCE 200 - -#define ANTLION_OBEY_FOLLOW_TIME 5.0f - - -//================================================== -// AntlionSquadSlots -//================================================== - -enum -{ - SQUAD_SLOT_ANTLION_JUMP = LAST_SHARED_SQUADSLOT, - SQUAD_SLOT_ANTLION_WORKER_FIRE, -}; - -//================================================== -// Antlion Activities -//================================================== - -int ACT_ANTLION_JUMP_START; -int ACT_ANTLION_DISTRACT; -int ACT_ANTLION_DISTRACT_ARRIVED; -int ACT_ANTLION_BURROW_IN; -int ACT_ANTLION_BURROW_OUT; -int ACT_ANTLION_BURROW_IDLE; -int ACT_ANTLION_RUN_AGITATED; -int ACT_ANTLION_FLIP; -int ACT_ANTLION_ZAP_FLIP; -int ACT_ANTLION_POUNCE; -int ACT_ANTLION_POUNCE_MOVING; -int ACT_ANTLION_DROWN; -int ACT_ANTLION_LAND; -int ACT_ANTLION_WORKER_EXPLODE; - - -//================================================== -// CNPC_Antlion -//================================================== - -CNPC_Antlion::CNPC_Antlion( void ) -{ - m_flIdleDelay = 0.0f; - m_flBurrowTime = 0.0f; - m_flJumpTime = 0.0f; - m_flPounceTime = 0.0f; - m_flObeyFollowTime = 0.0f; - m_iUnBurrowAttempts = 0; - - m_flAlertRadius = 256.0f; - m_flFieldOfView = -0.5f; - - m_bStartBurrowed = false; - m_bAgitatedSound = false; - m_bWingsOpen = false; - - m_flIgnoreSoundTime = 0.0f; - m_bHasHeardSound = false; - - m_flNextAcknowledgeTime = 0.0f; - m_flNextJumpPushTime = 0.0f; - - m_vecLastJumpAttempt.Init(); - m_vecSavedJump.Init(); - - m_hFightGoalTarget = NULL; - m_hFollowTarget = NULL; - m_bLoopingStarted = false; - - m_bForcedStuckJump = false; - m_nBodyBone = -1; - m_bSuppressUnburrowEffects = false; -} - -LINK_ENTITY_TO_CLASS( npc_antlion, CNPC_Antlion ); - -//================================================== -// CNPC_Antlion::m_DataDesc -//================================================== - -BEGIN_DATADESC( CNPC_Antlion ) - - DEFINE_KEYFIELD( m_bStartBurrowed, FIELD_BOOLEAN, "startburrowed" ), - DEFINE_KEYFIELD( m_bIgnoreBugbait, FIELD_BOOLEAN, "ignorebugbait" ), - DEFINE_KEYFIELD( m_flAlertRadius, FIELD_FLOAT, "radius" ), - DEFINE_KEYFIELD( m_flEludeDistance, FIELD_FLOAT, "eludedist" ), - DEFINE_KEYFIELD( m_bSuppressUnburrowEffects, FIELD_BOOLEAN, "unburroweffects" ), - - DEFINE_FIELD( m_vecSaveSpitVelocity, FIELD_VECTOR ), - DEFINE_FIELD( m_flIdleDelay, FIELD_TIME ), - DEFINE_FIELD( m_flBurrowTime, FIELD_TIME ), - DEFINE_FIELD( m_flJumpTime, FIELD_TIME ), - DEFINE_FIELD( m_flPounceTime, FIELD_TIME ), - DEFINE_FIELD( m_iUnBurrowAttempts, FIELD_INTEGER ), - DEFINE_FIELD( m_iContext, FIELD_INTEGER ), - DEFINE_FIELD( m_vecSavedJump, FIELD_VECTOR ), - DEFINE_FIELD( m_vecLastJumpAttempt, FIELD_VECTOR ), - DEFINE_FIELD( m_flIgnoreSoundTime, FIELD_TIME ), - DEFINE_FIELD( m_vecHeardSound, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_bHasHeardSound, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bAgitatedSound, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bWingsOpen, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flNextAcknowledgeTime, FIELD_TIME ), - DEFINE_FIELD( m_hFollowTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_hFightGoalTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_strParentSpawner, FIELD_STRING ), - DEFINE_FIELD( m_flSuppressFollowTime, FIELD_FLOAT ), - DEFINE_FIELD( m_MoveState, FIELD_INTEGER ), - DEFINE_FIELD( m_flObeyFollowTime, FIELD_TIME ), - DEFINE_FIELD( m_bLeapAttack, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bDisableJump, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flTimeDrown, FIELD_TIME ), - DEFINE_FIELD( m_flTimeDrownSplash, FIELD_TIME ), - DEFINE_FIELD( m_bDontExplode, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flNextJumpPushTime, FIELD_TIME ), - DEFINE_FIELD( m_bForcedStuckJump, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flZapDuration, FIELD_TIME ), -#if HL2_EPISODIC - DEFINE_FIELD( m_bHasDoneAirAttack, FIELD_BOOLEAN ), -#endif - // DEFINE_FIELD( m_bLoopingStarted, FIELD_BOOLEAN ), - // m_FollowBehavior - // m_AssaultBehavior - - DEFINE_INPUTFUNC( FIELD_VOID, "Unburrow", InputUnburrow ), - DEFINE_INPUTFUNC( FIELD_VOID, "Burrow", InputBurrow ), - DEFINE_INPUTFUNC( FIELD_VOID, "BurrowAway", InputBurrowAway ), - DEFINE_INPUTFUNC( FIELD_STRING, "FightToPosition", InputFightToPosition ), - DEFINE_INPUTFUNC( FIELD_STRING, "StopFightToPosition", InputStopFightToPosition ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableJump", InputEnableJump ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableJump", InputDisableJump ), - DEFINE_INPUTFUNC( FIELD_VOID, "IgnoreBugbait", InputIgnoreBugbait ), - DEFINE_INPUTFUNC( FIELD_VOID, "HearBugbait", InputHearBugbait ), - DEFINE_INPUTFUNC( FIELD_STRING, "JumpAtTarget", InputJumpAtTarget ), - - DEFINE_OUTPUT( m_OnReachFightGoal, "OnReachedFightGoal" ), - DEFINE_OUTPUT( m_OnUnBurrowed, "OnUnBurrowed" ), - - // Function Pointers - DEFINE_ENTITYFUNC( Touch ), - DEFINE_USEFUNC( BurrowUse ), - DEFINE_THINKFUNC( ZapThink ), - - // DEFINE_FIELD( FIELD_SHORT, m_hFootstep ), -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Antlion::Spawn( void ) -{ - Precache(); - -#ifdef _XBOX - // Always fade the corpse - AddSpawnFlags( SF_NPC_FADE_CORPSE ); -#endif // _XBOX - -#ifdef HL2_EPISODIC - if ( IsWorker() ) - { - SetModel( ANTLION_WORKER_MODEL ); - AddSpawnFlags( SF_NPC_LONG_RANGE ); - SetBloodColor( BLOOD_COLOR_ANTLION_WORKER ); - } - else - { - SetModel( ANTLION_MODEL ); - SetBloodColor( BLOOD_COLOR_ANTLION ); - } -#else - SetModel( ANTLION_MODEL ); - SetBloodColor( BLOOD_COLOR_YELLOW ); -#endif // HL2_EPISODIC - - SetHullType(HULL_MEDIUM); - SetHullSizeNormal(); - SetDefaultEyeOffset(); - - SetNavType( NAV_GROUND ); - - m_NPCState = NPC_STATE_NONE; - -#if HL2_EPISODIC - m_iHealth = ( IsWorker() ) ? sk_antlion_worker_health.GetFloat() : sk_antlion_health.GetFloat(); -#else - m_iHealth = sk_antlion_health.GetFloat(); -#endif // _DEBUG - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - - - SetMoveType( MOVETYPE_STEP ); - - //Only do this if a squadname appears in the entity - if ( m_SquadName != NULL_STRING ) - { - CapabilitiesAdd( bits_CAP_SQUAD ); - } - - SetCollisionGroup( HL2COLLISION_GROUP_ANTLION ); - - CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_MOVE_JUMP | bits_CAP_INNATE_MELEE_ATTACK1 | bits_CAP_INNATE_MELEE_ATTACK2 ); - - // Workers shoot projectiles - if ( IsWorker() ) - { - CapabilitiesAdd( bits_CAP_INNATE_RANGE_ATTACK1 ); - // CapabilitiesRemove( bits_CAP_INNATE_MELEE_ATTACK2 ); - } - - // JAY: Optimize these out for now - if ( HasSpawnFlags( SF_ANTLION_USE_GROUNDCHECKS ) == false ) - CapabilitiesAdd( bits_CAP_SKIP_NAV_GROUND_CHECK ); - - NPCInit(); - - if ( IsWorker() ) - { - // Bump up the worker's eye position a bit - SetViewOffset( Vector( 0, 0, 32 ) ); - } - - // Antlions will always pursue - m_flDistTooFar = FLT_MAX; - - m_bDisableJump = false; - - //See if we're supposed to start burrowed - if ( m_bStartBurrowed ) - { - AddEffects( EF_NODRAW ); - AddFlag( FL_NOTARGET ); - m_spawnflags |= SF_NPC_GAG; - AddSolidFlags( FSOLID_NOT_SOLID ); - m_takedamage = DAMAGE_NO; - - SetState( NPC_STATE_IDLE ); - SetActivity( (Activity) ACT_ANTLION_BURROW_IDLE ); - SetSchedule( SCHED_ANTLION_WAIT_FOR_UNBORROW_TRIGGER ); - - SetUse( &CNPC_Antlion::BurrowUse ); - } - - BaseClass::Spawn(); - - m_nSkin = random->RandomInt( 0, ANTLION_SKIN_COUNT-1 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Antlion::Activate( void ) -{ - // If we're friendly to the player, setup a relationship to reflect it - if ( IsAllied() ) - { - // Handle all clients - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - - if ( pPlayer != NULL ) - { - AddEntityRelationship( pPlayer, D_LI, 99 ); - } - } - } - - BaseClass::Activate(); -} - - -//----------------------------------------------------------------------------- -// Purpose: override this to simplify the physics shadow of the antlions -//----------------------------------------------------------------------------- -bool CNPC_Antlion::CreateVPhysics() -{ - bool bRet = BaseClass::CreateVPhysics(); - return bRet; -} - -// Use all the gibs -#define NUM_ANTLION_GIBS_UNIQUE 3 -const char *pszAntlionGibs_Unique[NUM_ANTLION_GIBS_UNIQUE] = { - "models/gibs/antlion_gib_large_1.mdl", - "models/gibs/antlion_gib_large_2.mdl", - "models/gibs/antlion_gib_large_3.mdl" -}; - -#define NUM_ANTLION_GIBS_MEDIUM 3 -const char *pszAntlionGibs_Medium[NUM_ANTLION_GIBS_MEDIUM] = { - "models/gibs/antlion_gib_medium_1.mdl", - "models/gibs/antlion_gib_medium_2.mdl", - "models/gibs/antlion_gib_medium_3.mdl" -}; - -// XBox doesn't use the smaller gibs, so don't cache them -#define NUM_ANTLION_GIBS_SMALL 3 -const char *pszAntlionGibs_Small[NUM_ANTLION_GIBS_SMALL] = { - "models/gibs/antlion_gib_small_1.mdl", - "models/gibs/antlion_gib_small_2.mdl", - "models/gibs/antlion_gib_small_3.mdl" -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Antlion::Precache( void ) -{ -#ifdef HL2_EPISODIC - if ( IsWorker() ) - { - PrecacheModel( ANTLION_WORKER_MODEL ); - PropBreakablePrecacheAll( MAKE_STRING( ANTLION_WORKER_MODEL ) ); - UTIL_PrecacheOther( "grenade_spit" ); - PrecacheParticleSystem( "blood_impact_antlion_worker_01" ); - PrecacheParticleSystem( "antlion_gib_02" ); - PrecacheParticleSystem( "blood_impact_yellow_01" ); - } - else -#endif // HL2_EPISODIC - { - PrecacheModel( ANTLION_MODEL ); - PropBreakablePrecacheAll( MAKE_STRING( ANTLION_MODEL ) ); - PrecacheParticleSystem( "blood_impact_antlion_01" ); - PrecacheParticleSystem( "AntlionGib" ); - } - - for ( int i = 0; i < NUM_ANTLION_GIBS_UNIQUE; ++i ) - { - PrecacheModel( pszAntlionGibs_Unique[ i ] ); - } - for ( int i = 0; i < NUM_ANTLION_GIBS_MEDIUM; ++i ) - { - PrecacheModel( pszAntlionGibs_Medium[ i ] ); - } - for ( int i = 0; i < NUM_ANTLION_GIBS_SMALL; ++i ) - { - PrecacheModel( pszAntlionGibs_Small[ i ] ); - } - - PrecacheScriptSound( "NPC_Antlion.RunOverByVehicle" ); - PrecacheScriptSound( "NPC_Antlion.MeleeAttack" ); - m_hFootstep = PrecacheScriptSound( "NPC_Antlion.Footstep" ); - PrecacheScriptSound( "NPC_Antlion.BurrowIn" ); - PrecacheScriptSound( "NPC_Antlion.BurrowOut" ); - PrecacheScriptSound( "NPC_Antlion.FootstepSoft" ); - PrecacheScriptSound( "NPC_Antlion.FootstepHeavy" ); - PrecacheScriptSound( "NPC_Antlion.MeleeAttackSingle" ); - PrecacheScriptSound( "NPC_Antlion.MeleeAttackDouble" ); - PrecacheScriptSound( "NPC_Antlion.Distracted" ); - PrecacheScriptSound( "NPC_Antlion.Idle" ); - PrecacheScriptSound( "NPC_Antlion.Pain" ); - PrecacheScriptSound( "NPC_Antlion.Land" ); - PrecacheScriptSound( "NPC_Antlion.WingsOpen" ); - PrecacheScriptSound( "NPC_Antlion.LoopingAgitated" ); - PrecacheScriptSound( "NPC_Antlion.Distracted" ); - -#ifdef HL2_EPISODIC - PrecacheScriptSound( "NPC_Antlion.PoisonBurstScream" ); - PrecacheScriptSound( "NPC_Antlion.PoisonBurstScreamSubmerged" ); - PrecacheScriptSound( "NPC_Antlion.PoisonBurstExplode" ); - PrecacheScriptSound( "NPC_Antlion.MeleeAttack_Muffled" ); - PrecacheScriptSound( "NPC_Antlion.TrappedMetal" ); - PrecacheScriptSound( "NPC_Antlion.ZappedFlip" ); - PrecacheScriptSound( "NPC_Antlion.PoisonShoot" ); - PrecacheScriptSound( "NPC_Antlion.PoisonBall" ); -#endif - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -inline CBaseEntity *CNPC_Antlion::EntityToWatch( void ) -{ - return ( m_hFollowTarget != NULL ) ? m_hFollowTarget.Get() : GetEnemy(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Cache whatever pose parameters we intend to use -//----------------------------------------------------------------------------- -void CNPC_Antlion::PopulatePoseParameters( void ) -{ - m_poseHead_Pitch = LookupPoseParameter("head_pitch"); - m_poseHead_Yaw = LookupPoseParameter("head_yaw" ); - - BaseClass::PopulatePoseParameters(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Antlion::UpdateHead( void ) -{ - float yaw = GetPoseParameter( m_poseHead_Yaw ); - float pitch = GetPoseParameter( m_poseHead_Pitch ); - - CBaseEntity *pTarget = EntityToWatch(); - - if ( pTarget != NULL ) - { - Vector enemyDir = pTarget->WorldSpaceCenter() - WorldSpaceCenter(); - VectorNormalize( enemyDir ); - - if ( DotProduct( enemyDir, BodyDirection3D() ) < 0.0f ) - { - SetPoseParameter( m_poseHead_Yaw, UTIL_Approach( 0, yaw, 10 ) ); - SetPoseParameter( m_poseHead_Pitch, UTIL_Approach( 0, pitch, 10 ) ); - - return; - } - - float facingYaw = VecToYaw( BodyDirection3D() ); - float yawDiff = VecToYaw( enemyDir ); - yawDiff = UTIL_AngleDiff( yawDiff, facingYaw + yaw ); - - float facingPitch = UTIL_VecToPitch( BodyDirection3D() ); - float pitchDiff = UTIL_VecToPitch( enemyDir ); - pitchDiff = UTIL_AngleDiff( pitchDiff, facingPitch + pitch ); - - SetPoseParameter( m_poseHead_Yaw, UTIL_Approach( yaw + yawDiff, yaw, 50 ) ); - SetPoseParameter( m_poseHead_Pitch, UTIL_Approach( pitch + pitchDiff, pitch, 50 ) ); - } - else - { - SetPoseParameter( m_poseHead_Yaw, UTIL_Approach( 0, yaw, 10 ) ); - SetPoseParameter( m_poseHead_Pitch, UTIL_Approach( 0, pitch, 10 ) ); - } -} - -#define ANTLION_VIEW_FIELD_NARROW 0.85f - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEntity - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Antlion::FInViewCone( CBaseEntity *pEntity ) -{ - m_flFieldOfView = ( GetEnemy() != NULL ) ? ANTLION_VIEW_FIELD_NARROW : VIEW_FIELD_WIDE; - - return BaseClass::FInViewCone( pEntity ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &vecSpot - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Antlion::FInViewCone( const Vector &vecSpot ) -{ - m_flFieldOfView = ( GetEnemy() != NULL ) ? ANTLION_VIEW_FIELD_NARROW : VIEW_FIELD_WIDE; - - return BaseClass::FInViewCone( vecSpot ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Antlion::CanBecomeRagdoll() -{ - // This prevents us from dying in the regular way. It forces a schedule selection - // that will select SCHED_DIE, where we can do our poison burst thing. -#ifdef HL2_EPISODIC - if ( IsWorker() && ANTLION_WORKERS_BURST() ) - { - // If we're in a script, we're allowed to ragdoll. This lets the vort's dynamic - // interaction ragdoll us. - return ( m_NPCState == NPC_STATE_SCRIPT || m_bDontExplode ); - } -#endif - return BaseClass::CanBecomeRagdoll(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pVictim - -//----------------------------------------------------------------------------- -void CNPC_Antlion::Event_Killed( const CTakeDamageInfo &info ) -{ - //Turn off wings - SetWings( false ); - VacateStrategySlot(); - - if ( IsCurSchedule(SCHED_ANTLION_BURROW_IN) || IsCurSchedule(SCHED_ANTLION_BURROW_OUT) ) - { - AddEFlags( EF_NOSHADOW ); - } - - if ( info.GetDamageType() & DMG_CRUSH ) - { - CSoundEnt::InsertSound( SOUND_PHYSICS_DANGER, GetAbsOrigin(), 256, 0.5f, this ); - } - - BaseClass::Event_Killed( info ); - - CBaseEntity *pAttacker = info.GetInflictor(); - - if ( pAttacker && pAttacker->GetServerVehicle() && ShouldGib( info ) == true ) - { - trace_t tr; - UTIL_TraceLine( GetAbsOrigin() + Vector( 0, 0, 64 ), pAttacker->GetAbsOrigin(), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - UTIL_DecalTrace( &tr, "Antlion.Splat" ); - - SpawnBlood( GetAbsOrigin(), g_vecAttackDir, BloodColor(), info.GetDamage() ); - - CPASAttenuationFilter filter( this ); - EmitSound( filter, entindex(), "NPC_Antlion.RunOverByVehicle" ); - } - - // Stop our zap effect! - SetContextThink( NULL, gpGlobals->curtime, "ZapThink" ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Antlion::MeleeAttack( float distance, float damage, QAngle& viewPunch, Vector& shove ) -{ - Vector vecForceDir; - - // Always hurt bullseyes for now - if ( ( GetEnemy() != NULL ) && ( GetEnemy()->Classify() == CLASS_BULLSEYE ) ) - { - vecForceDir = (GetEnemy()->GetAbsOrigin() - GetAbsOrigin()); - CTakeDamageInfo info( this, this, damage, DMG_SLASH ); - CalculateMeleeDamageForce( &info, vecForceDir, GetEnemy()->GetAbsOrigin() ); - GetEnemy()->TakeDamage( info ); - return; - } - - CBaseEntity *pHurt = CheckTraceHullAttack( distance, -Vector(16,16,32), Vector(16,16,32), (int)damage, DMG_SLASH, 5.0f ); - - if ( pHurt ) - { - vecForceDir = ( pHurt->WorldSpaceCenter() - WorldSpaceCenter() ); - - //FIXME: Until the interaction is setup, kill combine soldiers in one hit -- jdw - if ( FClassnameIs( pHurt, "npc_combine_s" ) ) - { - CTakeDamageInfo dmgInfo( this, this, pHurt->m_iHealth+25, DMG_SLASH ); - CalculateMeleeDamageForce( &dmgInfo, vecForceDir, pHurt->GetAbsOrigin() ); - pHurt->TakeDamage( dmgInfo ); - return; - } - - CBasePlayer *pPlayer = ToBasePlayer( pHurt ); - - if ( pPlayer != NULL ) - { - //Kick the player angles - if ( !(pPlayer->GetFlags() & FL_GODMODE ) && pPlayer->GetMoveType() != MOVETYPE_NOCLIP ) - { - pPlayer->ViewPunch( viewPunch ); - - Vector dir = pHurt->GetAbsOrigin() - GetAbsOrigin(); - VectorNormalize(dir); - - QAngle angles; - VectorAngles( dir, angles ); - Vector forward, right; - AngleVectors( angles, &forward, &right, NULL ); - - //Push the target back - pHurt->ApplyAbsVelocityImpulse( - right * shove[1] - forward * shove[0] ); - } - } - - // Play a random attack hit sound - EmitSound( "NPC_Antlion.MeleeAttack" ); - } -} - -// Number of times the antlions will attempt to generate a random chase position -#define NUM_CHASE_POSITION_ATTEMPTS 3 - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &targetPos - -// &result - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Antlion::FindChasePosition( const Vector &targetPos, Vector &result ) -{ - if ( HasSpawnFlags( SF_ANTLION_USE_GROUNDCHECKS ) == true ) - { - result = targetPos; - return true; - } - - Vector runDir = ( targetPos - GetAbsOrigin() ); - VectorNormalize( runDir ); - - Vector vRight, vUp; - VectorVectors( runDir, vRight, vUp ); - - for ( int i = 0; i < NUM_CHASE_POSITION_ATTEMPTS; i++ ) - { - result = targetPos; - result += -runDir * random->RandomInt( 64, 128 ); - result += vRight * random->RandomInt( -128, 128 ); - - //FIXME: We need to do a more robust search here - // Find a ground position and try to get there - if ( GetGroundPosition( result, result ) ) - return true; - } - - //TODO: If we're making multiple inquiries to this, make sure it's evenly spread - - if ( g_debug_antlion.GetInt() == 1 ) - { - NDebugOverlay::Cross3D( result, -Vector(32,32,32), Vector(32,32,32), 255, 255, 0, true, 2.0f ); - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &testPos - -//----------------------------------------------------------------------------- -bool CNPC_Antlion::GetGroundPosition( const Vector &testPos, Vector &result ) -{ - // Trace up to clear the ground - trace_t tr; - AI_TraceHull( testPos, testPos + Vector( 0, 0, 64 ), NAI_Hull::Mins( GetHullType() ), NAI_Hull::Maxs( GetHullType() ), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - - // If we're stuck in solid, this can't be valid - if ( tr.allsolid ) - { - if ( g_debug_antlion.GetInt() == 3 ) - { - NDebugOverlay::BoxDirection( testPos, NAI_Hull::Mins( GetHullType() ), NAI_Hull::Maxs( GetHullType() ) + Vector( 0, 0, 128 ), Vector( 0, 0, 1 ), 255, 0, 0, true, 2.0f ); - } - - return false; - } - - if ( g_debug_antlion.GetInt() == 3 ) - { - NDebugOverlay::BoxDirection( testPos, NAI_Hull::Mins( GetHullType() ), NAI_Hull::Maxs( GetHullType() ) + Vector( 0, 0, 128 ), Vector( 0, 0, 1 ), 0, 255, 0, true, 2.0f ); - } - - // Trace down to find the ground - AI_TraceHull( tr.endpos, tr.endpos - Vector( 0, 0, 128 ), NAI_Hull::Mins( GetHullType() ), NAI_Hull::Maxs( GetHullType() ), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - - if ( g_debug_antlion.GetInt() == 3 ) - { - NDebugOverlay::BoxDirection( tr.endpos, NAI_Hull::Mins( GetHullType() ) - Vector( 0, 0, 256 ), NAI_Hull::Maxs( GetHullType() ), Vector( 0, 0, 1 ), 255, 255, 0, true, 2.0f ); - } - - // We must end up on the floor with this trace - if ( tr.fraction < 1.0f ) - { - if ( g_debug_antlion.GetInt() == 3 ) - { - NDebugOverlay::Cross3D( tr.endpos, NAI_Hull::Mins( GetHullType() ), NAI_Hull::Maxs( GetHullType() ), 255, 0, 0, true, 2.0f ); - } - - result = tr.endpos; - return true; - } - - // Ended up in open space - return false; -} -void CNPC_Antlion::ManageFleeCapabilities( bool bEnable ) -{ - if ( bEnable == false ) - { - //Remove the jump capabilty when we build our route. - //We'll enable it back again after the route has been built. - CapabilitiesRemove( bits_CAP_MOVE_JUMP ); - - if ( HasSpawnFlags( SF_ANTLION_USE_GROUNDCHECKS ) == false ) - CapabilitiesRemove( bits_CAP_SKIP_NAV_GROUND_CHECK ); - } - else - { - if ( m_bDisableJump == false ) - CapabilitiesAdd( bits_CAP_MOVE_JUMP ); - - if ( HasSpawnFlags( SF_ANTLION_USE_GROUNDCHECKS ) == false ) - CapabilitiesAdd( bits_CAP_SKIP_NAV_GROUND_CHECK ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : soundType - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Antlion::GetPathToSoundFleePoint( int soundType ) -{ - CSound *pSound = GetLoudestSoundOfType( soundType ); - - if ( pSound == NULL ) - { - //NOTENOTE: If you're here, there's a disparity between Listen() and GetLoudestSoundOfType() - jdw - TaskFail( "Unable to find thumper sound!" ); - return false; - } - - ManageFleeCapabilities( false ); - - //Try and find a hint-node first - CHintCriteria hintCriteria; - - hintCriteria.SetHintType( HINT_ANTLION_THUMPER_FLEE_POINT ); - hintCriteria.SetFlag( bits_HINT_NODE_NEAREST ); - hintCriteria.AddIncludePosition( WorldSpaceCenter(), 2500 ); - - CAI_Hint *pHint = CAI_HintManager::FindHint( WorldSpaceCenter(), hintCriteria ); - - Vector vecFleeGoal; - Vector vecSoundPos = pSound->GetSoundOrigin(); - - // Put the sound location on the same plane as the antlion. - vecSoundPos.z = GetAbsOrigin().z; - - Vector vecFleeDir = GetAbsOrigin() - vecSoundPos; - VectorNormalize( vecFleeDir ); - - if ( pHint != NULL ) - { - // Get our goal position - pHint->GetPosition( this, &vecFleeGoal ); - - // Find a route to that position - AI_NavGoal_t goal( vecFleeGoal, (Activity) ACT_ANTLION_RUN_AGITATED, 128, AIN_DEF_FLAGS ); - - if ( GetNavigator()->SetGoal( goal ) ) - { - pHint->Lock( this ); - pHint->Unlock( 2.0f ); - - GetNavigator()->SetArrivalActivity( (Activity) ACT_ANTLION_DISTRACT_ARRIVED ); - GetNavigator()->SetArrivalDirection( -vecFleeDir ); - - ManageFleeCapabilities( true ); - return true; - } - } - - //Make us offset this a little at least - float flFleeYaw = VecToYaw( vecFleeDir ) + random->RandomInt( -20, 20 ); - - vecFleeDir = UTIL_YawToVector( flFleeYaw ); - - // Move us to the outer radius of the noise (with some randomness) - vecFleeGoal = vecSoundPos + vecFleeDir * ( pSound->Volume() + random->RandomInt( 32, 64 ) ); - - // Find a route to that position - AI_NavGoal_t goal( vecFleeGoal + Vector( 0, 0, 8 ), (Activity) ACT_ANTLION_RUN_AGITATED, 512, AIN_DEF_FLAGS ); - - if ( GetNavigator()->SetGoal( goal ) ) - { - GetNavigator()->SetArrivalActivity( (Activity) ACT_ANTLION_DISTRACT_ARRIVED ); - GetNavigator()->SetArrivalDirection( -vecFleeDir ); - - ManageFleeCapabilities( true ); - return true; - } - - ManageFleeCapabilities( true ); - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns whether the enemy has been seen within the time period supplied -// Input : flTime - Timespan we consider -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Antlion::SeenEnemyWithinTime( float flTime ) -{ - float flLastSeenTime = GetEnemies()->LastTimeSeen( GetEnemy() ); - return ( flLastSeenTime != 0.0f && ( gpGlobals->curtime - flLastSeenTime ) < flTime ); -} - -//----------------------------------------------------------------------------- -// Purpose: Test whether this antlion can hit the target -//----------------------------------------------------------------------------- -bool CNPC_Antlion::InnateWeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions ) -{ - if ( GetNextAttack() > gpGlobals->curtime ) - return false; - - // If we can see the enemy, or we've seen them in the last few seconds just try to lob in there - if ( SeenEnemyWithinTime( 3.0f ) ) - { - Vector vSpitPos; - GetAttachment( "mouth", vSpitPos ); - - return GetSpitVector( vSpitPos, targetPos, &m_vecSaveSpitVelocity ); - } - - return BaseClass::InnateWeaponLOSCondition( ownerPos, targetPos, bSetConditions ); -} - -// -// FIXME: Create this in a better fashion! -// - -Vector VecCheckThrowTolerance( CBaseEntity *pEdict, const Vector &vecSpot1, Vector vecSpot2, float flSpeed, float flTolerance ) -{ - flSpeed = MAX( 1.0f, flSpeed ); - - float flGravity = sv_gravity.GetFloat(); - - Vector vecGrenadeVel = (vecSpot2 - vecSpot1); - - // throw at a constant time - float time = vecGrenadeVel.Length( ) / flSpeed; - vecGrenadeVel = vecGrenadeVel * (1.0 / time); - - // adjust upward toss to compensate for gravity loss - vecGrenadeVel.z += flGravity * time * 0.5; - - Vector vecApex = vecSpot1 + (vecSpot2 - vecSpot1) * 0.5; - vecApex.z += 0.5 * flGravity * (time * 0.5) * (time * 0.5); - - - trace_t tr; - UTIL_TraceLine( vecSpot1, vecApex, MASK_SOLID, pEdict, COLLISION_GROUP_NONE, &tr ); - if (tr.fraction != 1.0) - { - // fail! - if ( g_debug_antlion_worker.GetBool() ) - { - NDebugOverlay::Line( vecSpot1, vecApex, 255, 0, 0, true, 5.0 ); - } - - return vec3_origin; - } - - if ( g_debug_antlion_worker.GetBool() ) - { - NDebugOverlay::Line( vecSpot1, vecApex, 0, 255, 0, true, 5.0 ); - } - - UTIL_TraceLine( vecApex, vecSpot2, MASK_SOLID_BRUSHONLY, pEdict, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction != 1.0 ) - { - bool bFail = true; - - // Didn't make it all the way there, but check if we're within our tolerance range - if ( flTolerance > 0.0f ) - { - float flNearness = ( tr.endpos - vecSpot2 ).LengthSqr(); - if ( flNearness < Square( flTolerance ) ) - { - if ( g_debug_antlion_worker.GetBool() ) - { - NDebugOverlay::Sphere( tr.endpos, vec3_angle, flTolerance, 0, 255, 0, 0, true, 5.0 ); - } - - bFail = false; - } - } - - if ( bFail ) - { - if ( g_debug_antlion_worker.GetBool() ) - { - NDebugOverlay::Line( vecApex, vecSpot2, 255, 0, 0, true, 5.0 ); - NDebugOverlay::Sphere( tr.endpos, vec3_angle, flTolerance, 255, 0, 0, 0, true, 5.0 ); - } - return vec3_origin; - } - } - - if ( g_debug_antlion_worker.GetBool() ) - { - NDebugOverlay::Line( vecApex, vecSpot2, 0, 255, 0, true, 5.0 ); - } - - return vecGrenadeVel; -} - -//----------------------------------------------------------------------------- -// Purpose: Get a toss direction that will properly lob spit to hit a target -// Input : &vecStartPos - Where the spit will start from -// &vecTarget - Where the spit is meant to land -// *vecOut - The resulting vector to lob the spit -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Antlion::GetSpitVector( const Vector &vecStartPos, const Vector &vecTarget, Vector *vecOut ) -{ - // antlion workers exist only in episodic. -#if HL2_EPISODIC - // Try the most direct route - Vector vecToss = VecCheckThrowTolerance( this, vecStartPos, vecTarget, sk_antlion_worker_spit_speed.GetFloat(), (10.0f*12.0f) ); - - // If this failed then try a little faster (flattens the arc) - if ( vecToss == vec3_origin ) - { - vecToss = VecCheckThrowTolerance( this, vecStartPos, vecTarget, sk_antlion_worker_spit_speed.GetFloat() * 1.5f, (10.0f*12.0f) ); - if ( vecToss == vec3_origin ) - return false; - } - - // Save out the result - if ( vecOut ) - { - *vecOut = vecToss; - } - - return true; -#else - return false; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flDuration - -//----------------------------------------------------------------------------- -void CNPC_Antlion::DelaySquadAttack( float flDuration ) -{ - if ( GetSquad() ) - { - // Reduce the duration by as much as 50% of the total time to make this less robotic - float flAdjDuration = flDuration - random->RandomFloat( 0.0f, (flDuration*0.5f) ); - GetSquad()->BroadcastInteraction( g_interactionAntlionFiredAtTarget, (void *)&flAdjDuration, this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEvent - -//----------------------------------------------------------------------------- -void CNPC_Antlion::HandleAnimEvent( animevent_t *pEvent ) -{ - QAngle viewPunch; - Vector shove; -#ifdef HL2_EPISODIC - // Handle the spit event - if ( pEvent->event == AE_ANTLION_WORKER_SPIT ) - { - if ( GetEnemy() ) - { - Vector vSpitPos; - GetAttachment( "mouth", vSpitPos ); - - Vector vTarget; - - // If our enemy is looking at us and far enough away, lead him - if ( HasCondition( COND_ENEMY_FACING_ME ) && UTIL_DistApprox( GetAbsOrigin(), GetEnemy()->GetAbsOrigin() ) > (40*12) ) - { - UTIL_PredictedPosition( GetEnemy(), 0.5f, &vTarget ); - vTarget.z = GetEnemy()->GetAbsOrigin().z; - } - else - { - // Otherwise he can't see us and he won't be able to dodge - vTarget = GetEnemy()->BodyTarget( vSpitPos, true ); - } - - vTarget[2] += random->RandomFloat( 0.0f, 32.0f ); - - // Try and spit at our target - Vector vecToss; - if ( GetSpitVector( vSpitPos, vTarget, &vecToss ) == false ) - { - // Now try where they were - if ( GetSpitVector( vSpitPos, m_vSavePosition, &vecToss ) == false ) - { - // Failing that, just shoot with the old velocity we calculated initially! - vecToss = m_vecSaveSpitVelocity; - } - } - - // Find what our vertical theta is to estimate the time we'll impact the ground - Vector vecToTarget = ( vTarget - vSpitPos ); - VectorNormalize( vecToTarget ); - float flVelocity = VectorNormalize( vecToss ); - float flCosTheta = DotProduct( vecToTarget, vecToss ); - float flTime = (vSpitPos-vTarget).Length2D() / ( flVelocity * flCosTheta ); - - // Emit a sound where this is going to hit so that targets get a chance to act correctly - CSoundEnt::InsertSound( SOUND_DANGER, vTarget, (15*12), flTime, this ); - - // Don't fire again until this volley would have hit the ground (with some lag behind it) - SetNextAttack( gpGlobals->curtime + flTime + random->RandomFloat( 0.5f, 2.0f ) ); - - // Tell any squadmates not to fire for some portion of the time this volley will be in the air (except on hard) - if ( g_pGameRules->IsSkillLevel( SKILL_HARD ) == false ) - DelaySquadAttack( flTime ); - - for ( int i = 0; i < 6; i++ ) - { - CGrenadeSpit *pGrenade = (CGrenadeSpit*) CreateEntityByName( "grenade_spit" ); - pGrenade->SetAbsOrigin( vSpitPos ); - pGrenade->SetAbsAngles( vec3_angle ); - DispatchSpawn( pGrenade ); - pGrenade->SetThrower( this ); - pGrenade->SetOwnerEntity( this ); - - if ( i == 0 ) - { - pGrenade->SetSpitSize( SPIT_LARGE ); - pGrenade->SetAbsVelocity( vecToss * flVelocity ); - } - else - { - pGrenade->SetAbsVelocity( ( vecToss + RandomVector( -0.035f, 0.035f ) ) * flVelocity ); - pGrenade->SetSpitSize( random->RandomInt( SPIT_SMALL, SPIT_MEDIUM ) ); - } - - // Tumble through the air - pGrenade->SetLocalAngularVelocity( - QAngle( random->RandomFloat( -250, -500 ), - random->RandomFloat( -250, -500 ), - random->RandomFloat( -250, -500 ) ) ); - } - - for ( int i = 0; i < 8; i++ ) - { - DispatchParticleEffect( "blood_impact_yellow_01", vSpitPos + RandomVector( -12.0f, 12.0f ), RandomAngle( 0, 360 ) ); - } - - EmitSound( "NPC_Antlion.PoisonShoot" ); - } - return; - } - - if ( pEvent->event == AE_ANTLION_WORKER_DONT_EXPLODE ) - { - m_bDontExplode = true; - return; - } - -#endif // HL2_EPISODIC - - if ( pEvent->event == AE_ANTLION_WALK_FOOTSTEP ) - { - MakeAIFootstepSound( 240.0f ); - EmitSound( "NPC_Antlion.Footstep", m_hFootstep, pEvent->eventtime ); - return; - } - - if ( pEvent->event == AE_ANTLION_MELEE_HIT1 ) - { - viewPunch = QAngle(20.0f, 0.0f, -12.0f); - shove = Vector(-250.0f, 1.0f, 1.0f); - MeleeAttack( ANTLION_MELEE1_RANGE, sk_antlion_swipe_damage.GetFloat(), viewPunch, shove ); - return; - } - - if ( pEvent->event == AE_ANTLION_MELEE_HIT2 ) - { - viewPunch = QAngle(20.0f, 0.0f, 0.0f); - shove = Vector(-350.0f, 1.0f, 1.0f); - MeleeAttack( ANTLION_MELEE1_RANGE, sk_antlion_swipe_damage.GetFloat(), viewPunch, shove ); - return; - } - - if ( pEvent->event == AE_ANTLION_MELEE_POUNCE ) - { - viewPunch = QAngle(4.0f, 0.0f, 0.0f); - shove = Vector(-250.0f, 1.0f, 1.0f); - MeleeAttack( ANTLION_MELEE2_RANGE, sk_antlion_swipe_damage.GetFloat(), viewPunch, shove ); - return; - } - - if ( pEvent->event == AE_ANTLION_OPEN_WINGS ) - { - SetWings( true ); - return; - } - - if ( pEvent->event == AE_ANTLION_CLOSE_WINGS ) - { - SetWings( false ); - return; - } - - if ( pEvent->event == AE_ANTLION_VANISH ) - { - AddSolidFlags( FSOLID_NOT_SOLID ); - m_takedamage = DAMAGE_NO; - AddEffects( EF_NODRAW ); - SetWings( false ); - - return; - } - - if ( pEvent->event == AE_ANTLION_BURROW_IN ) - { - //Burrowing sound - EmitSound( "NPC_Antlion.BurrowIn" ); - - //Shake the screen - UTIL_ScreenShake( GetAbsOrigin(), 0.5f, 80.0f, 1.0f, 256.0f, SHAKE_START ); - - //Throw dust up - CreateDust(); - - if ( GetHintNode() ) - { - GetHintNode()->Unlock( 2.0f ); - } - - return; - } - - if ( pEvent->event == AE_ANTLION_BURROW_OUT ) - { - EmitSound( "NPC_Antlion.BurrowOut" ); - - //Shake the screen - UTIL_ScreenShake( GetAbsOrigin(), 0.5f, 80.0f, 1.0f, 256.0f, SHAKE_START ); - - //Throw dust up - CreateDust(); - - RemoveEffects( EF_NODRAW ); - RemoveFlag( FL_NOTARGET ); - - return; - } - - if ( pEvent->event == AE_ANTLION_FOOTSTEP_SOFT ) - { - EmitSound( "NPC_Antlion.FootstepSoft", pEvent->eventtime ); - return; - } - - if ( pEvent->event == AE_ANTLION_FOOTSTEP_HEAVY ) - { - EmitSound( "NPC_Antlion.FootstepHeavy", pEvent->eventtime ); - return; - } - - - if ( pEvent->event == AE_ANTLION_MELEE1_SOUND ) - { - EmitSound( "NPC_Antlion.MeleeAttackSingle" ); - return; - } - - if ( pEvent->event == AE_ANTLION_MELEE2_SOUND ) - { - EmitSound( "NPC_Antlion.MeleeAttackDouble" ); - return; - } - - if ( pEvent->event == AE_ANTLION_START_JUMP ) - { - StartJump(); - return; - } - - // antlion worker events -#if HL2_EPISODIC - if ( pEvent->event == AE_ANTLION_WORKER_EXPLODE_SCREAM ) - { - if ( GetWaterLevel() < 2 ) - { - EmitSound( "NPC_Antlion.PoisonBurstScream" ); - } - else - { - EmitSound( "NPC_Antlion.PoisonBurstScreamSubmerged" ); - } - return; - } - - if ( pEvent->event == AE_ANTLION_WORKER_EXPLODE_WARN ) - { - CSoundEnt::InsertSound( SOUND_PHYSICS_DANGER, GetAbsOrigin(), sk_antlion_worker_burst_radius.GetInt(), 0.5f, this ); - return; - } - - if ( pEvent->event == AE_ANTLION_WORKER_EXPLODE ) - { - CTakeDamageInfo info( this, this, sk_antlion_worker_burst_damage.GetFloat(), DMG_BLAST_SURFACE | ( ANTLION_WORKER_BURST_IS_POISONOUS() ? DMG_POISON : DMG_ACID ) ); - Event_Gibbed( info ); - return; - } -#endif - - BaseClass::HandleAnimEvent( pEvent ); -} - -bool CNPC_Antlion::IsUnusableNode(int iNodeID, CAI_Hint *pHint) -{ - bool iBaseReturn = BaseClass::IsUnusableNode( iNodeID, pHint ); - - if ( g_test_new_antlion_jump.GetBool() == 0 ) - return iBaseReturn; - - CAI_Node *pNode = GetNavigator()->GetNetwork()->GetNode( iNodeID ); - - if ( pNode ) - { - if ( pNode->IsLocked() ) - return true; - } - - return iBaseReturn; -} - -void CNPC_Antlion::LockJumpNode( void ) -{ - if ( HasSpawnFlags( SF_ANTLION_USE_GROUNDCHECKS ) == false ) - return; - - if ( GetNavigator()->GetPath() == NULL ) - return; - - if ( g_test_new_antlion_jump.GetBool() == false ) - return; - - AI_Waypoint_t *pWaypoint = GetNavigator()->GetPath()->GetCurWaypoint(); - - while ( pWaypoint ) - { - AI_Waypoint_t *pNextWaypoint = pWaypoint->GetNext(); - if ( pNextWaypoint && pNextWaypoint->NavType() == NAV_JUMP && pWaypoint->iNodeID != NO_NODE ) - { - CAI_Node *pNode = GetNavigator()->GetNetwork()->GetNode( pWaypoint->iNodeID ); - - if ( pNode ) - { - //NDebugOverlay::Box( pNode->GetOrigin(), Vector( -16, -16, -16 ), Vector( 16, 16, 16 ), 255, 0, 0, 0, 2 ); - pNode->Lock( 0.5f ); - break; - } - } - else - { - pWaypoint = pWaypoint->GetNext(); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Antlion::OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) -{ - bool iBaseReturn = BaseClass::OnObstructionPreSteer( pMoveGoal, distClear, pResult ); - - if ( g_test_new_antlion_jump.GetBool() == false ) - return iBaseReturn; - - if ( HasSpawnFlags( SF_ANTLION_USE_GROUNDCHECKS ) == false ) - return iBaseReturn; - - CAI_BaseNPC *pBlocker = pMoveGoal->directTrace.pObstruction->MyNPCPointer(); - - if ( pBlocker && pBlocker->Classify() == CLASS_ANTLION ) - { - // HACKHACK - CNPC_Antlion *pAntlion = dynamic_cast< CNPC_Antlion * > ( pBlocker ); - - if ( pAntlion ) - { - if ( pAntlion->AllowedToBePushed() == true && GetEnemy() == NULL ) - { - //NDebugOverlay::Box( pAntlion->GetAbsOrigin(), GetHullMins(), GetHullMaxs(), 0, 255, 0, 0, 2 ); - pAntlion->GetMotor()->SetIdealYawToTarget( WorldSpaceCenter() ); - pAntlion->SetSchedule( SCHED_MOVE_AWAY ); - pAntlion->m_flNextJumpPushTime = gpGlobals->curtime + 2.0f; - } - } - } - - return iBaseReturn; -} - -bool NPC_Antlion_IsAntlion( CBaseEntity *pEntity ) -{ - CNPC_Antlion *pAntlion = dynamic_cast(pEntity); - - return pAntlion ? true : false; -} - -class CTraceFilterAntlion : public CTraceFilterEntitiesOnly -{ -public: - CTraceFilterAntlion( const CBaseEntity *pEntity ) { m_pIgnore = pEntity; } - - virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) - { - CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); - - if ( m_pIgnore == pEntity ) - return false; - - if ( pEntity->IsNPC() == false ) - return false; - - if ( NPC_Antlion_IsAntlion( pEntity ) ) - return true; - - return false; - } -private: - - const CBaseEntity *m_pIgnore; -}; - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Antlion::StartTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_ANTLION_FIND_COVER_FROM_SAVEPOSITION: - { - Vector coverPos; - - if ( GetTacticalServices()->FindCoverPos( m_vSavePosition, EyePosition(), 0, CoverRadius(), &coverPos ) ) - { - AI_NavGoal_t goal(coverPos, ACT_RUN, AIN_HULL_TOLERANCE); - GetNavigator()->SetGoal( goal ); - - m_flMoveWaitFinished = gpGlobals->curtime + pTask->flTaskData; - } - else - { - // no coverwhatsoever. - TaskFail(FAIL_NO_COVER); - } - } - break; - - case TASK_ANNOUNCE_ATTACK: - { - EmitSound( "NPC_Antlion.MeleeAttackSingle" ); - TaskComplete(); - break; - } - - case TASK_ANTLION_FACE_JUMP: - break; - - case TASK_ANTLION_DROWN: - { - // Set the gravity really low here! Sink slowly - SetGravity( 0 ); - SetAbsVelocity( vec3_origin ); - m_flTimeDrownSplash = gpGlobals->curtime + random->RandomFloat( 0, 0.5 ); - m_flTimeDrown = gpGlobals->curtime + 4; - break; - } - - case TASK_ANTLION_REACH_FIGHT_GOAL: - - m_OnReachFightGoal.FireOutput( this, this ); - TaskComplete(); - break; - - case TASK_ANTLION_DISMOUNT_NPC: - { - CBaseEntity *pGroundEnt = GetGroundEntity(); - - if( pGroundEnt != NULL ) - { - trace_t trace; - CTraceFilterAntlion traceFilter( this ); - AI_TraceHull( GetAbsOrigin(), GetAbsOrigin(), WorldAlignMins(), WorldAlignMaxs(), MASK_SOLID, &traceFilter, &trace ); - - if ( trace.m_pEnt ) - { - m_bDontExplode = true; - OnTakeDamage( CTakeDamageInfo( this, this, m_iHealth+1, DMG_GENERIC ) ); - return; - } - - // Jump behind the other NPC so I don't block their path. - Vector vecJumpDir; - - pGroundEnt->GetVectors( &vecJumpDir, NULL, NULL ); - - SetGroundEntity( NULL ); - - // Bump up - UTIL_SetOrigin( this, GetAbsOrigin() + Vector( 0, 0 , 1 ) ); - - SetAbsVelocity( vecJumpDir * -200 + Vector( 0, 0, 100 ) ); - - // Doing ACT_RESET first assures they play the animation, even when in transition - ResetActivity(); - SetActivity( (Activity) ACT_ANTLION_FLIP ); - } - else - { - // Dead or gone now - TaskComplete(); - } - } - - break; - - case TASK_ANTLION_FACE_BUGBAIT: - - //Must have a saved sound - //FIXME: This isn't assured to be still pointing to the right place, need to protect this - if ( !m_bHasHeardSound ) - { - TaskFail( "No remembered bug bait sound to run to!" ); - return; - } - - GetMotor()->SetIdealYawToTargetAndUpdate( m_vecHeardSound ); - SetTurnActivity(); - - break; - - case TASK_ANTLION_GET_PATH_TO_BUGBAIT: - { - //Must have a saved sound - //FIXME: This isn't assured to be still pointing to the right place, need to protect this - if ( !m_bHasHeardSound ) - { - TaskFail( "No remembered bug bait sound to run to!" ); - return; - } - - Vector goalPos; - - // Find the position to chase to - if ( FindChasePosition( m_vecHeardSound, goalPos ) ) - { - AI_NavGoal_t goal( goalPos, (Activity) ACT_ANTLION_RUN_AGITATED, ANTLION_BUGBAIT_NAV_TOLERANCE ); - - //Try to run directly there - if ( GetNavigator()->SetGoal( goal, AIN_DISCARD_IF_FAIL ) == false ) - { - //Try and get as close as possible otherwise - AI_NavGoal_t nearGoal( GOALTYPE_LOCATION_NEAREST_NODE, goalPos, (Activity) ACT_ANTLION_RUN_AGITATED, ANTLION_BUGBAIT_NAV_TOLERANCE ); - - if ( GetNavigator()->SetGoal( nearGoal, AIN_CLEAR_PREVIOUS_STATE ) ) - { - //FIXME: HACK! The internal pathfinding is setting this without our consent, so override it! - ClearCondition( COND_TASK_FAILED ); - - LockJumpNode(); - TaskComplete(); - return; - } - else - { - TaskFail( "Antlion failed to find path to bugbait position\n" ); - return; - } - } - else - { - LockJumpNode(); - TaskComplete(); - return; - } - } - - TaskFail( "Antlion failed to find path to bugbait position\n" ); - break; - } - - case TASK_ANTLION_WAIT_FOR_TRIGGER: - m_flIdleDelay = gpGlobals->curtime + 1.0f; - - break; - - case TASK_ANTLION_JUMP: - - if ( CheckLanding() ) - { - TaskComplete(); - } - - break; - - case TASK_ANTLION_CHECK_FOR_UNBORROW: - - m_iUnBurrowAttempts = 0; - - if ( ValidBurrowPoint( GetAbsOrigin() ) ) - { - m_spawnflags &= ~SF_NPC_GAG; - RemoveSolidFlags( FSOLID_NOT_SOLID ); - TaskComplete(); - } - - break; - - case TASK_ANTLION_BURROW_WAIT: - - if ( pTask->flTaskData == 1.0f ) - { - //Set our next burrow time - m_flBurrowTime = gpGlobals->curtime + random->RandomFloat( 1, 6 ); - } - - break; - - case TASK_ANTLION_FIND_BURROW_IN_POINT: - - if ( FindBurrow( GetAbsOrigin(), pTask->flTaskData, ANTLION_BURROW_IN ) == false ) - { - TaskFail( "TASK_ANTLION_FIND_BURROW_IN_POINT: Unable to find burrow in position\n" ); - } - else - { - TaskComplete(); - } - - break; - - case TASK_ANTLION_FIND_BURROW_OUT_POINT: - - if ( FindBurrow( GetAbsOrigin(), pTask->flTaskData, ANTLION_BURROW_OUT ) == false ) - { - TaskFail( "TASK_ANTLION_FIND_BURROW_OUT_POINT: Unable to find burrow out position\n" ); - } - else - { - TaskComplete(); - } - - break; - - case TASK_ANTLION_BURROW: - Burrow(); - TaskComplete(); - - break; - - case TASK_ANTLION_UNBURROW: - Unburrow(); - TaskComplete(); - - break; - - case TASK_ANTLION_VANISH: - AddEffects( EF_NODRAW ); - AddFlag( FL_NOTARGET ); - m_spawnflags |= SF_NPC_GAG; - - // If the task parameter is non-zero, remove us when we vanish - if ( pTask->flTaskData ) - { - CBaseEntity *pOwner = GetOwnerEntity(); - - if( pOwner != NULL ) - { - pOwner->DeathNotice( this ); - SetOwnerEntity( NULL ); - } - - // NOTE: We can't UTIL_Remove here, because we're in the middle of running our AI, and - // we'll crash later in the bowels of the AI. Remove ourselves next frame. - SetThink( &CNPC_Antlion::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 0.1 ); - } - - TaskComplete(); - - break; - - case TASK_ANTLION_GET_THUMPER_ESCAPE_PATH: - { - if ( GetPathToSoundFleePoint( SOUND_THUMPER ) ) - { - TaskComplete(); - } - else - { - TaskFail( FAIL_NO_REACHABLE_NODE ); - } - } - - break; - - case TASK_ANTLION_GET_PHYSICS_DANGER_ESCAPE_PATH: - { - if ( GetPathToSoundFleePoint( SOUND_PHYSICS_DANGER ) ) - { - TaskComplete(); - } - else - { - TaskFail( FAIL_NO_REACHABLE_NODE ); - } - } - - break; - - - default: - BaseClass::StartTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTask - -//----------------------------------------------------------------------------- -void CNPC_Antlion::RunTask( const Task_t *pTask ) -{ - // some state that needs be set each frame -#if HL2_EPISODIC - if ( GetFlags() & FL_ONGROUND ) - { - m_bHasDoneAirAttack = false; - } -#endif - - switch ( pTask->iTask ) - { - case TASK_ANTLION_FACE_JUMP: - { - Vector jumpDir = m_vecSavedJump; - VectorNormalize( jumpDir ); - - QAngle jumpAngles; - VectorAngles( jumpDir, jumpAngles ); - - GetMotor()->SetIdealYawAndUpdate( jumpAngles[YAW], AI_KEEP_YAW_SPEED ); - SetTurnActivity(); - - if ( GetMotor()->DeltaIdealYaw() < 2 ) - { - TaskComplete(); - } - } - - break; - - case TASK_ANTLION_DROWN: - { - if ( gpGlobals->curtime > m_flTimeDrownSplash ) - { - float flWaterZ = UTIL_FindWaterSurface( GetAbsOrigin(), GetAbsOrigin().z, GetAbsOrigin().z + NAI_Hull::Maxs( GetHullType() ).z ); - - CEffectData data; - data.m_fFlags = 0; - data.m_vOrigin = GetAbsOrigin(); - data.m_vOrigin.z = flWaterZ; - data.m_vNormal = Vector( 0, 0, 1 ); - data.m_flScale = random->RandomFloat( 12.0, 16.0 ); - - DispatchEffect( "watersplash", data ); - - m_flTimeDrownSplash = gpGlobals->curtime + random->RandomFloat( 0.5, 2.5 ); - } - - if ( gpGlobals->curtime > m_flTimeDrown ) - { - m_bDontExplode = true; - OnTakeDamage( CTakeDamageInfo( this, this, m_iHealth+1, DMG_DROWN ) ); - TaskComplete(); - } - break; - } - - case TASK_ANTLION_REACH_FIGHT_GOAL: - break; - - case TASK_ANTLION_DISMOUNT_NPC: - - if ( GetFlags() & FL_ONGROUND ) - { - CBaseEntity *pGroundEnt = GetGroundEntity(); - - if ( ( pGroundEnt != NULL ) && ( ( pGroundEnt->MyNPCPointer() != NULL ) || pGroundEnt->GetSolidFlags() & FSOLID_NOT_STANDABLE ) ) - { - // Jump behind the other NPC so I don't block their path. - Vector vecJumpDir; - - pGroundEnt->GetVectors( &vecJumpDir, NULL, NULL ); - - SetGroundEntity( NULL ); - - // Bump up - UTIL_SetOrigin( this, GetAbsOrigin() + Vector( 0, 0 , 1 ) ); - - Vector vecRandom = RandomVector( -250.0f, 250.0f ); - vecRandom[2] = random->RandomFloat( 100.0f, 200.0f ); - SetAbsVelocity( vecRandom ); - - // Doing ACT_RESET first assures they play the animation, even when in transition - ResetActivity(); - SetActivity( (Activity) ACT_ANTLION_FLIP ); - } - else if ( IsActivityFinished() ) - { - TaskComplete(); - } - } - - break; - - case TASK_ANTLION_FACE_BUGBAIT: - - //Must have a saved sound - //FIXME: This isn't assured to be still pointing to the right place, need to protect this - if ( !m_bHasHeardSound ) - { - TaskFail( "No remembered bug bait sound to run to!" ); - return; - } - - GetMotor()->SetIdealYawToTargetAndUpdate( m_vecHeardSound ); - - if ( FacingIdeal() ) - { - TaskComplete(); - } - - break; - - case TASK_ANTLION_WAIT_FOR_TRIGGER: - - if ( ( m_flIdleDelay > gpGlobals->curtime ) || GetEntityName() != NULL_STRING ) - return; - - TaskComplete(); - - break; - - case TASK_ANTLION_JUMP: - - if ( CheckLanding() ) - { - TaskComplete(); - } - - break; - - case TASK_ANTLION_CHECK_FOR_UNBORROW: - - //Must wait for our next check time - if ( m_flBurrowTime > gpGlobals->curtime ) - return; - - //See if we can pop up - if ( ValidBurrowPoint( GetAbsOrigin() ) ) - { - m_spawnflags &= ~SF_NPC_GAG; - RemoveSolidFlags( FSOLID_NOT_SOLID ); - - TaskComplete(); - return; - } - - //Try again in a couple of seconds - m_flBurrowTime = gpGlobals->curtime + random->RandomFloat( 0.5f, 1.0f ); - m_iUnBurrowAttempts++; - - // Robin: If we fail 10 times, kill ourself. - // This deals with issues where the game relies out antlion spawners - // firing their OnBlocked output, but the spawner isn't attempting to - // spawn because it has multiple live children lying around stuck under - // physics props unable to unburrow. - if ( m_iUnBurrowAttempts >= 10 ) - { - m_bDontExplode = true; - m_takedamage = DAMAGE_YES; - OnTakeDamage( CTakeDamageInfo( this, this, m_iHealth+1, DMG_GENERIC ) ); - } - - break; - - case TASK_ANTLION_BURROW_WAIT: - - //See if enough time has passed - if ( m_flBurrowTime < gpGlobals->curtime ) - { - TaskComplete(); - } - - break; - - default: - BaseClass::RunTask( pTask ); - break; - } -} - -bool CNPC_Antlion::AllowedToBePushed( void ) -{ - if ( IsCurSchedule( SCHED_ANTLION_BURROW_WAIT ) || - IsCurSchedule(SCHED_ANTLION_BURROW_IN) || - IsCurSchedule(SCHED_ANTLION_BURROW_OUT) || - IsCurSchedule(SCHED_ANTLION_BURROW_AWAY ) || - IsCurSchedule( SCHED_ANTLION_RUN_TO_FIGHT_GOAL ) ) - return false; - - if ( IsRunningDynamicInteraction() ) - return false; - - if ( IsMoving() == false && IsCurSchedule( SCHED_ANTLION_FLIP ) == false - && GetNavType() != NAV_JUMP && m_flNextJumpPushTime <= gpGlobals->curtime ) - { - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true if a reasonable jumping distance -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CNPC_Antlion::IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos ) const -{ - const float MAX_JUMP_RISE = 512; - const float MAX_JUMP_DROP = 512; - const float MAX_JUMP_DISTANCE = 1024; - const float MIN_JUMP_DISTANCE = 128; - - if ( CAntlionRepellant::IsPositionRepellantFree( endPos ) == false ) - return false; - - //Adrian: Don't try to jump if my destination is right next to me. - if ( ( endPos - GetAbsOrigin()).Length() < MIN_JUMP_DISTANCE ) - return false; - - if ( HasSpawnFlags( SF_ANTLION_USE_GROUNDCHECKS ) && g_test_new_antlion_jump.GetBool() == true ) - { - trace_t tr; - AI_TraceHull( endPos, endPos, GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.m_pEnt ) - { - CAI_BaseNPC *pBlocker = tr.m_pEnt->MyNPCPointer(); - - if ( pBlocker && pBlocker->Classify() == CLASS_ANTLION ) - { - // HACKHACK - CNPC_Antlion *pAntlion = dynamic_cast< CNPC_Antlion * > ( pBlocker ); - - if ( pAntlion ) - { - if ( pAntlion->AllowedToBePushed() == true ) - { - // NDebugOverlay::Line( GetAbsOrigin(), endPos, 255, 0, 0, 0, 2 ); - // NDebugOverlay::Box( pAntlion->GetAbsOrigin(), GetHullMins(), GetHullMaxs(), 0, 0, 255, 0, 2 ); - pAntlion->GetMotor()->SetIdealYawToTarget( endPos ); - pAntlion->SetSchedule( SCHED_MOVE_AWAY ); - pAntlion->m_flNextJumpPushTime = gpGlobals->curtime + 2.0f; - } - } - } - } - } - - return BaseClass::IsJumpLegal( startPos, apex, endPos, MAX_JUMP_RISE, MAX_JUMP_DROP, MAX_JUMP_DISTANCE ); -} - -bool CNPC_Antlion::IsFirmlyOnGround( void ) -{ - if( !( GetFlags()&FL_ONGROUND ) ) - return false; - - trace_t tr; - - float flHeight = fabs( GetHullMaxs().z - GetHullMins().z ); - - Vector vOrigin = GetAbsOrigin() + Vector( GetHullMins().x, GetHullMins().y, 0 ); -// NDebugOverlay::Line( vOrigin, vOrigin - Vector( 0, 0, flHeight * 0.5 ), 255, 0, 0, true, 5 ); - UTIL_TraceLine( vOrigin, vOrigin - Vector( 0, 0, flHeight * 0.5 ), MASK_NPCSOLID, this, GetCollisionGroup(), &tr ); - - if ( tr.fraction != 1.0f ) - return true; - - vOrigin = GetAbsOrigin() - Vector( GetHullMins().x, GetHullMins().y, 0 ); -// NDebugOverlay::Line( vOrigin, vOrigin - Vector( 0, 0, flHeight * 0.5 ), 255, 0, 0, true, 5 ); - UTIL_TraceLine( vOrigin, vOrigin - Vector( 0, 0, flHeight * 0.5 ), MASK_NPCSOLID, this, GetCollisionGroup(), &tr ); - - if ( tr.fraction != 1.0f ) - return true; - - vOrigin = GetAbsOrigin() + Vector( GetHullMins().x, -GetHullMins().y, 0 ); -// NDebugOverlay::Line( vOrigin, vOrigin - Vector( 0, 0, flHeight * 0.5 ), 255, 0, 0, true, 5 ); - UTIL_TraceLine( vOrigin, vOrigin - Vector( 0, 0, flHeight * 0.5 ), MASK_NPCSOLID, this, GetCollisionGroup(), &tr ); - - if ( tr.fraction != 1.0f ) - return true; - - vOrigin = GetAbsOrigin() + Vector( -GetHullMins().x, GetHullMins().y, 0 ); -// NDebugOverlay::Line( vOrigin, vOrigin - Vector( 0, 0, flHeight * 0.5 ), 255, 0, 0, true, 5 ); - UTIL_TraceLine( vOrigin, vOrigin - Vector( 0, 0, flHeight * 0.5 ), MASK_NPCSOLID, this, GetCollisionGroup(), &tr ); - - if ( tr.fraction != 1.0f ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_Antlion::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ) -{ - if ( m_FollowBehavior.GetNumFailedFollowAttempts() >= 2 ) - { - if( IsFirmlyOnGround() == false ) - { - Vector vecJumpDir; - - vecJumpDir.z = 0; - vecJumpDir.x = 0; - vecJumpDir.y = 0; - - while( vecJumpDir.x == 0 && vecJumpDir.y == 0 ) - { - vecJumpDir.x = random->RandomInt( -1, 1 ); - vecJumpDir.y = random->RandomInt( -1, 1 ); - } - - vecJumpDir.NormalizeInPlace(); - - SetGroundEntity( NULL ); - - m_vecSavedJump = vecJumpDir * 512 + Vector( 0, 0, 256 ); - m_bForcedStuckJump = true; - - return SCHED_ANTLION_JUMP; - } - } - - // Catch the LOF failure and choose another route to take - if ( failedSchedule == SCHED_ESTABLISH_LINE_OF_FIRE ) - return SCHED_ANTLION_WORKER_FLANK_RANDOM; - - return BaseClass::SelectFailSchedule( failedSchedule, failedTask, taskFailCode ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Antlion::ShouldJump( void ) -{ - if ( GetEnemy() == NULL ) - return false; - - //Too soon to try to jump - if ( m_flJumpTime > gpGlobals->curtime ) - return false; - - // only jump if you're on the ground - if (!(GetFlags() & FL_ONGROUND) || GetNavType() == NAV_JUMP ) - return false; - - // Don't jump if I'm not allowed - if ( ( CapabilitiesGet() & bits_CAP_MOVE_JUMP ) == false ) - return false; - - Vector vEnemyForward, vForward; - - GetEnemy()->GetVectors( &vEnemyForward, NULL, NULL ); - GetVectors( &vForward, NULL, NULL ); - - float flDot = DotProduct( vForward, vEnemyForward ); - - if ( flDot < 0.5f ) - flDot = 0.5f; - - Vector vecPredictedPos; - - //Get our likely position in two seconds - UTIL_PredictedPosition( GetEnemy(), flDot * 2.5f, &vecPredictedPos ); - - // Don't jump if we're already near the target - if ( ( GetAbsOrigin() - vecPredictedPos ).LengthSqr() < (512*512) ) - return false; - - //Don't retest if the target hasn't moved enough - //FIXME: Check your own distance from last attempt as well - if ( ( ( m_vecLastJumpAttempt - vecPredictedPos ).LengthSqr() ) < (128*128) ) - { - m_flJumpTime = gpGlobals->curtime + random->RandomFloat( 1.0f, 2.0f ); - return false; - } - - Vector targetDir = ( vecPredictedPos - GetAbsOrigin() ); - - float flDist = VectorNormalize( targetDir ); - - // don't jump at target it it's very close - if (flDist < ANTLION_JUMP_MIN) - return false; - - Vector targetPos = vecPredictedPos + ( targetDir * (GetHullWidth()*4.0f) ); - - if ( CAntlionRepellant::IsPositionRepellantFree( targetPos ) == false ) - return false; - - // Try the jump - AIMoveTrace_t moveTrace; - GetMoveProbe()->MoveLimit( NAV_JUMP, GetAbsOrigin(), targetPos, MASK_NPCSOLID, GetNavTargetEntity(), &moveTrace ); - - //See if it succeeded - if ( IsMoveBlocked( moveTrace.fStatus ) ) - { - if ( g_debug_antlion.GetInt() == 2 ) - { - NDebugOverlay::Box( targetPos, GetHullMins(), GetHullMaxs(), 255, 0, 0, 0, 5 ); - NDebugOverlay::Line( GetAbsOrigin(), targetPos, 255, 0, 0, 0, 5 ); - } - - m_flJumpTime = gpGlobals->curtime + random->RandomFloat( 1.0f, 2.0f ); - return false; - } - - if ( g_debug_antlion.GetInt() == 2 ) - { - NDebugOverlay::Box( targetPos, GetHullMins(), GetHullMaxs(), 0, 255, 0, 0, 5 ); - NDebugOverlay::Line( GetAbsOrigin(), targetPos, 0, 255, 0, 0, 5 ); - } - - //Save this jump in case the next time fails - m_vecSavedJump = moveTrace.vJumpVelocity; - m_vecLastJumpAttempt = targetPos; - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Antlion::TranslateSchedule( int scheduleType ) -{ - if ( ( m_hFollowTarget != NULL ) || IsAllied() ) - { - if ( ( scheduleType == SCHED_IDLE_STAND ) || ( scheduleType == SCHED_ALERT_STAND ) ) - return SCHED_ANTLION_BUGBAIT_IDLE_STAND; - } - - return BaseClass::TranslateSchedule( scheduleType ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Activity CNPC_Antlion::NPC_TranslateActivity( Activity baseAct ) -{ - // Workers explode as long as they didn't drown. - if ( IsWorker() && ( baseAct == ACT_DIESIMPLE ) && !m_bDontExplode ) - { - return ( Activity )ACT_ANTLION_WORKER_EXPLODE; - } - - return BaseClass::NPC_TranslateActivity( baseAct ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CNPC_Antlion::ChooseMoveSchedule( void ) -{ - // See if we need to invalidate our fight goal - if ( ShouldResumeFollow() ) - { - // Set us back to following - SetMoveState( ANTLION_MOVE_FOLLOW ); - - // Tell our parent that we've swapped modes - CAntlionTemplateMaker *pMaker = dynamic_cast(GetOwnerEntity()); - - if ( pMaker != NULL ) - { - pMaker->SetChildMoveState( ANTLION_MOVE_FOLLOW ); - } - } - - // Figure out our move state - switch( m_MoveState ) - { - case ANTLION_MOVE_FREE: - return SCHED_NONE; // Let the base class handle us - break; - - // Fighting to a position - case ANTLION_MOVE_FIGHT_TO_GOAL: - { - if ( m_hFightGoalTarget ) - { - float targetDist = UTIL_DistApprox( WorldSpaceCenter(), m_hFightGoalTarget->GetAbsOrigin() ); - - if ( targetDist > 256 ) - { - Vector testPos; - Vector targetPos = ( m_hFightGoalTarget ) ? m_hFightGoalTarget->GetAbsOrigin() : m_vSavePosition; - - // Find a suitable chase position - if ( FindChasePosition( targetPos, testPos ) ) - { - m_vSavePosition = testPos; - return SCHED_ANTLION_RUN_TO_FIGHT_GOAL; - } - } - } - } - break; - - // Following a goal - case ANTLION_MOVE_FOLLOW: - { - if ( m_FollowBehavior.CanSelectSchedule() ) - { - // See if we should burrow away if our target it too far off - if ( ShouldAbandonFollow() ) - return SCHED_ANTLION_BURROW_AWAY; - - DeferSchedulingToBehavior( &m_FollowBehavior ); - return BaseClass::SelectSchedule(); - } - } - break; - } - - return SCHED_NONE; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Antlion::ZapThink( void ) -{ - CEffectData data; - data.m_nEntIndex = entindex(); - data.m_flMagnitude = 4; - data.m_flScale = random->RandomFloat( 0.25f, 1.0f ); - - DispatchEffect( "TeslaHitboxes", data ); - - if ( m_flZapDuration > gpGlobals->curtime ) - { - SetContextThink( &CNPC_Antlion::ZapThink, gpGlobals->curtime + random->RandomFloat( 0.05f, 0.25f ), "ZapThink" ); - } - else - { - SetContextThink( NULL, gpGlobals->curtime, "ZapThink" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CNPC_Antlion::SelectSchedule( void ) -{ - // Workers explode when killed unless told otherwise by anim events etc. - m_bDontExplode = false; - - // Clear out this condition - ClearCondition( COND_ANTLION_RECEIVED_ORDERS ); - - // If we're supposed to be burrowed, stay there - if ( m_bStartBurrowed ) - return SCHED_ANTLION_WAIT_FOR_UNBORROW_TRIGGER; - - // See if a friendly player is pushing us away - if ( HasCondition( COND_PLAYER_PUSHING ) ) - return SCHED_MOVE_AWAY; - - //Flipped? - if ( HasCondition( COND_ANTLION_FLIPPED ) ) - { - ClearCondition( COND_ANTLION_FLIPPED ); - - // See if it's a forced, electrical flip - if ( m_flZapDuration > gpGlobals->curtime ) - { - SetContextThink( &CNPC_Antlion::ZapThink, gpGlobals->curtime, "ZapThink" ); - return SCHED_ANTLION_ZAP_FLIP; - } - - // Regular flip - return SCHED_ANTLION_FLIP; - } - - if( HasCondition( COND_ANTLION_IN_WATER ) ) - { - // No matter what, drown in water - return SCHED_ANTLION_DROWN; - } - - // If we're flagged to burrow away when eluded, do so - if ( ( m_spawnflags & SF_ANTLION_BURROW_ON_ELUDED ) && ( HasCondition( COND_ENEMY_UNREACHABLE ) || HasCondition( COND_ENEMY_TOO_FAR ) ) ) - return SCHED_ANTLION_BURROW_AWAY; - - //Hear a thumper? - if ( HasCondition( COND_HEAR_THUMPER ) ) - { - // Ignore thumpers that aren't visible - CSound *pSound = GetLoudestSoundOfType( SOUND_THUMPER ); - - if ( pSound ) - { - CTakeDamageInfo info; - PainSound( info ); - ClearCondition( COND_HEAR_THUMPER ); - - return SCHED_ANTLION_FLEE_THUMPER; - } - } - - //Hear a physics danger sound? - if( HasCondition( COND_HEAR_PHYSICS_DANGER ) ) - { - CTakeDamageInfo info; - PainSound( info ); - return SCHED_ANTLION_FLEE_PHYSICS_DANGER; - } - - //On another NPC's head? - if( HasCondition( COND_ANTLION_ON_NPC ) ) - { - // You're on an NPC's head. Get off. - return SCHED_ANTLION_DISMOUNT_NPC; - } - - // If we're scripted to jump at a target, do so - if ( HasCondition( COND_ANTLION_CAN_JUMP_AT_TARGET ) ) - { - // NDebugOverlay::Cross3D( m_vecSavedJump, 32.0f, 255, 0, 0, true, 2.0f ); - ClearCondition( COND_ANTLION_CAN_JUMP_AT_TARGET ); - return SCHED_ANTLION_JUMP; - } - - //Hear bug bait splattered? - if ( HasCondition( COND_HEAR_BUGBAIT ) && ( m_bIgnoreBugbait == false ) ) - { - //Play a special sound - if ( m_flNextAcknowledgeTime < gpGlobals->curtime ) - { - EmitSound( "NPC_Antlion.Distracted" ); - m_flNextAcknowledgeTime = gpGlobals->curtime + 1.0f; - } - - m_flIdleDelay = gpGlobals->curtime + 4.0f; - - //If the sound is valid, act upon it - if ( m_bHasHeardSound ) - { - //Mark anything in the area as more interesting - CBaseEntity *pTarget = NULL; - CBaseEntity *pNewEnemy = NULL; - Vector soundOrg = m_vecHeardSound; - - //Find all entities within that sphere - while ( ( pTarget = gEntList.FindEntityInSphere( pTarget, soundOrg, bugbait_radius.GetInt() ) ) != NULL ) - { - CAI_BaseNPC *pNPC = pTarget->MyNPCPointer(); - - if ( pNPC == NULL ) - continue; - - if ( pNPC->CanBeAnEnemyOf( this ) == false ) - continue; - - //Check to see if the default relationship is hatred, and if so intensify that - if ( ( IRelationType( pNPC ) == D_HT ) && ( pNPC->IsPlayer() == false ) ) - { - AddEntityRelationship( pNPC, D_HT, 99 ); - - //Try to spread out the enemy distribution - if ( ( pNewEnemy == NULL ) || ( random->RandomInt( 0, 1 ) ) ) - { - pNewEnemy = pNPC; - continue; - } - } - } - - // If we have a new enemy, take it - if ( pNewEnemy != NULL ) - { - //Setup our ignore info - SetEnemy( pNewEnemy ); - } - - ClearCondition( COND_HEAR_BUGBAIT ); - - return SCHED_ANTLION_CHASE_BUGBAIT; - } - } - - if( m_AssaultBehavior.CanSelectSchedule() ) - { - DeferSchedulingToBehavior( &m_AssaultBehavior ); - return BaseClass::SelectSchedule(); - } - - //Otherwise do basic state schedule selection - switch ( m_NPCState ) - { - case NPC_STATE_COMBAT: - { - // Worker-only AI - if ( hl2_episodic.GetBool() && IsWorker() ) - { - // Melee attack if we can - if ( HasCondition( COND_CAN_MELEE_ATTACK1 ) ) - return SCHED_MELEE_ATTACK1; - - // Pounce if they're too near us - if ( HasCondition( COND_CAN_MELEE_ATTACK2 ) ) - { - m_flPounceTime = gpGlobals->curtime + 1.5f; - - if ( m_bLeapAttack == true ) - return SCHED_ANTLION_POUNCE_MOVING; - - return SCHED_ANTLION_POUNCE; - } - - // A squadmate died, so run away! - if ( HasCondition( COND_ANTLION_SQUADMATE_KILLED ) ) - { - SetNextAttack( gpGlobals->curtime + random->RandomFloat( 2.0f, 4.0f ) ); - ClearCondition( COND_ANTLION_SQUADMATE_KILLED ); - return SCHED_ANTLION_TAKE_COVER_FROM_ENEMY; - } - - // Flee on heavy damage - if ( HasCondition( COND_HEAVY_DAMAGE ) ) - { - SetNextAttack( gpGlobals->curtime + random->RandomFloat( 2.0f, 4.0f ) ); - return SCHED_ANTLION_TAKE_COVER_FROM_ENEMY; - } - - // Range attack if we're able - if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - { - if ( OccupyStrategySlot( SQUAD_SLOT_ANTLION_WORKER_FIRE ) ) - { - EmitSound( "NPC_Antlion.PoisonBurstScream" ); - SetNextAttack( gpGlobals->curtime + random->RandomFloat( 0.5f, 2.5f ) ); - if ( GetEnemy() ) - { - m_vSavePosition = GetEnemy()->BodyTarget( GetAbsOrigin() ); - } - - return SCHED_ANTLION_WORKER_RANGE_ATTACK1; - } - } - - // Back up, we're too near an enemy or can't see them - if ( HasCondition( COND_TOO_CLOSE_TO_ATTACK ) || HasCondition( COND_ENEMY_OCCLUDED ) ) - return SCHED_ESTABLISH_LINE_OF_FIRE; - - // See if we need to destroy breakable cover - if ( HasCondition( COND_WEAPON_SIGHT_OCCLUDED ) ) - return SCHED_SHOOT_ENEMY_COVER; - - // Run around randomly if our target is looking in our direction - if ( HasCondition( COND_BEHIND_ENEMY ) == false ) - return SCHED_ANTLION_WORKER_FLANK_RANDOM; - - // Face our target and continue to fire - return SCHED_COMBAT_FACE; - } - else - { - // Lunge at the enemy - if ( HasCondition( COND_CAN_MELEE_ATTACK2 ) ) - { - m_flPounceTime = gpGlobals->curtime + 1.5f; - - if ( m_bLeapAttack == true ) - return SCHED_ANTLION_POUNCE_MOVING; - else - return SCHED_ANTLION_POUNCE; - } - - // Try to jump - if ( HasCondition( COND_ANTLION_CAN_JUMP ) ) - return SCHED_ANTLION_JUMP; - } - } - break; - - default: - { - int moveSched = ChooseMoveSchedule(); - - if ( moveSched != SCHED_NONE ) - return moveSched; - - if ( GetEnemy() == NULL && ( HasCondition( COND_LIGHT_DAMAGE ) || HasCondition( COND_HEAVY_DAMAGE ) ) ) - { - Vector vecEnemyLKP; - - // Retrieve a memory for the damage taken - // Fill in where we're trying to look - if ( GetEnemies()->Find( AI_UNKNOWN_ENEMY ) ) - { - vecEnemyLKP = GetEnemies()->LastKnownPosition( AI_UNKNOWN_ENEMY ); - } - else - { - // Don't have an enemy, so face the direction the last attack came from (don't face north) - vecEnemyLKP = WorldSpaceCenter() + ( g_vecAttackDir * 128 ); - } - - // If we're already facing the attack direction, then take cover from it - if ( FInViewCone( vecEnemyLKP ) ) - { - // Save this position for our cover search - m_vSavePosition = vecEnemyLKP; - return SCHED_ANTLION_TAKE_COVER_FROM_SAVEPOSITION; - } - - // By default, we'll turn to face the attack - } - } - break; - } - - return BaseClass::SelectSchedule(); -} - -void CNPC_Antlion::Ignite ( float flFlameLifetime, bool bNPCOnly, float flSize, bool bCalledByLevelDesigner ) -{ -#ifdef HL2_EPISODIC - float flDamage = m_iHealth + 1; - - CTakeDamageInfo dmgInfo( this, this, flDamage, DMG_GENERIC ); - GuessDamageForce( &dmgInfo, Vector( 0, 0, 8 ), GetAbsOrigin() ); - TakeDamage( dmgInfo ); -#else - BaseClass::Ignite( flFlameLifetime, bNPCOnly, flSize, bCalledByLevelDesigner ); -#endif - -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Antlion::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - CTakeDamageInfo newInfo = info; - - if( hl2_episodic.GetBool() && antlion_easycrush.GetBool() ) - { - if( newInfo.GetDamageType() & DMG_CRUSH ) - { - if( newInfo.GetInflictor() && newInfo.GetInflictor()->VPhysicsGetObject() ) - { - float flMass = newInfo.GetInflictor()->VPhysicsGetObject()->GetMass(); - - if( flMass > 250.0f && newInfo.GetDamage() < GetHealth() ) - { - newInfo.SetDamage( GetHealth() ); - } - } - } - } - - // If we're being hoisted by a barnacle, we only take damage from that barnacle (otherwise we can die too early!) - if ( IsEFlagSet( EFL_IS_BEING_LIFTED_BY_BARNACLE ) ) - { - if ( info.GetAttacker() && info.GetAttacker()->Classify() != CLASS_BARNACLE ) - return 0; - } - - // Find out how much damage we're about to take - int nDamageTaken = BaseClass::OnTakeDamage_Alive( newInfo ); - if ( gpGlobals->curtime - m_flLastDamageTime < 0.5f ) - { - // Accumulate it - m_nSustainedDamage += nDamageTaken; - } - else - { - // Reset, it's been too long - m_nSustainedDamage = nDamageTaken; - } - - m_flLastDamageTime = gpGlobals->curtime; - - return nDamageTaken; -} - -//----------------------------------------------------------------------------- -// Purpose: Antlion who are flipped will knock over other antlions behind them! -//----------------------------------------------------------------------------- -void CNPC_Antlion::CascadePush( const Vector &vecForce ) -{ - // Controlled via this convar until this is proven worthwhile - if ( hl2_episodic.GetBool() == false /*|| g_antlion_cascade_push.GetBool() == false*/ ) - return; - - Vector vecForceDir = vecForce; - float flMagnitude = VectorNormalize( vecForceDir ); - Vector vecPushBack = GetAbsOrigin() + ( vecForceDir * (flMagnitude*0.1f) ); - - // Make antlions flip all around us! - CBaseEntity *pEnemySearch[32]; - int nNumEnemies = UTIL_EntitiesInBox( pEnemySearch, ARRAYSIZE(pEnemySearch), vecPushBack-Vector(48,48,0), vecPushBack+Vector(48,48,64), FL_NPC ); - for ( int i = 0; i < nNumEnemies; i++ ) - { - // We only care about antlions - if ( pEnemySearch[i] == NULL || pEnemySearch[i]->Classify() != CLASS_ANTLION || pEnemySearch[i] == this ) - continue; - - CNPC_Antlion *pAntlion = dynamic_cast(pEnemySearch[i]); - if ( pAntlion != NULL ) - { - Vector vecDir = ( pAntlion->GetAbsOrigin() - GetAbsOrigin() ); - vecDir[2] = 0.0f; - float flDist = VectorNormalize( vecDir ); - float flFalloff = RemapValClamped( flDist, 0, 256, 1.0f, 0.1f ); - - vecDir *= ( flMagnitude * flFalloff ); - vecDir[2] += ( (flMagnitude*0.25f) * flFalloff ); - - pAntlion->ApplyAbsVelocityImpulse( vecDir ); - - // Turn them over - pAntlion->Flip(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -inline bool CNPC_Antlion::IsFlipped( void ) -{ - return ( GetActivity() == ACT_ANTLION_FLIP || GetActivity() == ACT_ANTLION_ZAP_FLIP ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Antlion::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - CTakeDamageInfo newInfo = info; - - Vector vecShoveDir = vecDir; - vecShoveDir.z = 0.0f; - - //Are we already flipped? - if ( IsFlipped() ) - { - //If we were hit by physics damage, move with it - if ( newInfo.GetDamageType() & (DMG_CRUSH|DMG_PHYSGUN) ) - { - PainSound( newInfo ); - Vector vecForce = ( vecShoveDir * random->RandomInt( 500, 1000 ) ) + Vector(0.0f, 0.0f, 64.0f); - CascadePush( vecForce ); - ApplyAbsVelocityImpulse( vecForce ); - SetGroundEntity( NULL ); - } - - //More vulnerable when flipped - newInfo.ScaleDamage( 4.0f ); - } - else if ( newInfo.GetDamageType() & (DMG_PHYSGUN) || - ( newInfo.GetDamageType() & (DMG_BLAST|DMG_CRUSH) && newInfo.GetDamage() >= 25.0f ) ) - { - // Don't do this if we're in an interaction - if ( !IsRunningDynamicInteraction() ) - { - //Grenades, physcannons, and physics impacts make us fuh-lip! - - if( hl2_episodic.GetBool() ) - { - PainSound( newInfo ); - - if( GetFlags() & FL_ONGROUND ) - { - // Only flip if on the ground. - SetCondition( COND_ANTLION_FLIPPED ); - } - - Vector vecForce = ( vecShoveDir * random->RandomInt( 500, 1000 ) ) + Vector(0.0f, 0.0f, 64.0f); - - CascadePush( vecForce ); - ApplyAbsVelocityImpulse( vecForce ); - SetGroundEntity( NULL ); - } - else - { - //Don't flip off the deck - if ( GetFlags() & FL_ONGROUND ) - { - PainSound( newInfo ); - - SetCondition( COND_ANTLION_FLIPPED ); - - //Get tossed! - ApplyAbsVelocityImpulse( ( vecShoveDir * random->RandomInt( 500, 1000 ) ) + Vector(0.0f, 0.0f, 64.0f) ); - SetGroundEntity( NULL ); - } - } - } - } - - BaseClass::TraceAttack( newInfo, vecDir, ptr ); -} - -void CNPC_Antlion::StopLoopingSounds( void ) -{ - if ( m_bLoopingStarted ) - { - StopSound( "NPC_Antlion.WingsOpen" ); - m_bLoopingStarted = false; - } - if ( m_bAgitatedSound ) - { - StopSound( "NPC_Antlion.LoopingAgitated" ); - m_bAgitatedSound = false; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Antlion::IdleSound( void ) -{ - EmitSound( "NPC_Antlion.Idle" ); - m_flIdleDelay = gpGlobals->curtime + 4.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Antlion::PainSound( const CTakeDamageInfo &info ) -{ - EmitSound( "NPC_Antlion.Pain" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : -//----------------------------------------------------------------------------- -float CNPC_Antlion::GetIdealAccel( void ) const -{ - return GetIdealSpeed() * 2.0; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CNPC_Antlion::MaxYawSpeed( void ) -{ - switch ( GetActivity() ) - { - case ACT_IDLE: - return 32.0f; - break; - - case ACT_WALK: - return 16.0f; - break; - - default: - case ACT_RUN: - return 32.0f; - break; - } - - return 32.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Antlion::ShouldPlayIdleSound( void ) -{ - //Only do idles in the right states - if ( ( m_NPCState != NPC_STATE_IDLE && m_NPCState != NPC_STATE_ALERT ) ) - return false; - - //Gagged monsters don't talk - if ( m_spawnflags & SF_NPC_GAG ) - return false; - - //Don't cut off another sound or play again too soon - if ( m_flIdleDelay > gpGlobals->curtime ) - return false; - - //Randomize it a bit - if ( random->RandomInt( 0, 20 ) ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pFriend - -//----------------------------------------------------------------------------- -void CNPC_Antlion::NotifyDeadFriend( CBaseEntity *pFriend ) -{ - SetCondition( COND_ANTLION_SQUADMATE_KILLED ); - BaseClass::NotifyDeadFriend( pFriend ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Determine whether or not to check our attack conditions -//----------------------------------------------------------------------------- -bool CNPC_Antlion::FCanCheckAttacks( void ) -{ - if ( IsWorker() ) - { - // Only do this if we've seen our target recently and our schedule can be interrupted - if ( SeenEnemyWithinTime( 3.0f ) && ConditionInterruptsCurSchedule( COND_CAN_RANGE_ATTACK1 ) ) - return FInViewCone( GetEnemy() ); - } - - return BaseClass::FCanCheckAttacks(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_Antlion::RangeAttack1Conditions( float flDot, float flDist ) -{ - if ( GetNextAttack() > gpGlobals->curtime ) - return COND_NOT_FACING_ATTACK; - - if ( flDot < DOT_10DEGREE ) - return COND_NOT_FACING_ATTACK; - - if ( flDist > (150*12) ) - return COND_TOO_FAR_TO_ATTACK; - - if ( flDist < (20*12) ) - return COND_TOO_CLOSE_TO_ATTACK; - - return COND_CAN_RANGE_ATTACK1; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_Antlion::MeleeAttack1Conditions( float flDot, float flDist ) -{ -#if 1 //NOTENOTE: Use predicted position melee attacks - - //Get our likely position in one half second - Vector vecPrPos; - UTIL_PredictedPosition( GetEnemy(), 0.5f, &vecPrPos ); - - //Get the predicted distance and direction - float flPrDist = ( vecPrPos - GetAbsOrigin() ).LengthSqr(); - if ( flPrDist > Square( ANTLION_MELEE1_RANGE ) ) - return COND_TOO_FAR_TO_ATTACK; - - // Compare our target direction to our body facing - Vector2D vec2DPrDir = ( vecPrPos - GetAbsOrigin() ).AsVector2D(); - Vector2D vec2DBodyDir = BodyDirection2D().AsVector2D(); - - float flPrDot = DotProduct2D ( vec2DPrDir, vec2DBodyDir ); - if ( flPrDot < 0.5f ) - return COND_NOT_FACING_ATTACK; - - trace_t tr; - AI_TraceHull( WorldSpaceCenter(), GetEnemy()->WorldSpaceCenter(), -Vector(8,8,8), Vector(8,8,8), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - - // If the hit entity isn't our target and we don't hate it, don't hit it - if ( tr.m_pEnt != GetEnemy() && tr.fraction < 1.0f && IRelationType( tr.m_pEnt ) != D_HT ) - return 0; - -#else - - if ( flDot < 0.5f ) - return COND_NOT_FACING_ATTACK; - - float flAdjustedDist = ANTLION_MELEE1_RANGE; - - if ( GetEnemy() ) - { - // Give us extra space if our enemy is in a vehicle - CBaseCombatCharacter *pCCEnemy = GetEnemy()->MyCombatCharacterPointer(); - if ( pCCEnemy != NULL && pCCEnemy->IsInAVehicle() ) - { - flAdjustedDist *= 2.0f; - } - } - - if ( flDist > flAdjustedDist ) - return COND_TOO_FAR_TO_ATTACK; - - trace_t tr; - AI_TraceHull( WorldSpaceCenter(), GetEnemy()->WorldSpaceCenter(), -Vector(8,8,8), Vector(8,8,8), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction < 1.0f ) - return 0; - -#endif - - return COND_CAN_MELEE_ATTACK1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flDot - -// flDist - -// Output : int -//----------------------------------------------------------------------------- -int CNPC_Antlion::MeleeAttack2Conditions( float flDot, float flDist ) -{ - // See if it's too soon to pounce again - if ( m_flPounceTime > gpGlobals->curtime ) - return 0; - - float flPrDist, flPrDot; - Vector vecPrPos; - Vector2D vec2DPrDir; - - //Get our likely position in one half second - UTIL_PredictedPosition( GetEnemy(), 0.25f, &vecPrPos ); - - //Get the predicted distance and direction - flPrDist = ( vecPrPos - GetAbsOrigin() ).Length(); - vec2DPrDir = ( vecPrPos - GetAbsOrigin() ).AsVector2D(); - - Vector vecBodyDir = BodyDirection2D(); - - Vector2D vec2DBodyDir = vecBodyDir.AsVector2D(); - - flPrDot = DotProduct2D ( vec2DPrDir, vec2DBodyDir ); - - if ( ( flPrDist > ANTLION_MELEE2_RANGE_MAX ) ) - { - m_flPounceTime = gpGlobals->curtime + 0.2f; - return COND_TOO_FAR_TO_ATTACK; - } - else if ( ( flPrDist < ANTLION_MELEE2_RANGE_MIN ) ) - { - m_flPounceTime = gpGlobals->curtime + 0.2f; - return COND_TOO_CLOSE_TO_ATTACK; - } - - trace_t tr; - AI_TraceHull( WorldSpaceCenter(), GetEnemy()->WorldSpaceCenter(), -Vector(8,8,8), Vector(8,8,8), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction < 1.0f ) - return 0; - - if ( IsMoving() ) - m_bLeapAttack = true; - else - m_bLeapAttack = false; - - return COND_CAN_MELEE_ATTACK2; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : interactionType - -// *data - -// *sender - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Antlion::HandleInteraction( int interactionType, void *data, CBaseCombatCharacter *sender ) -{ - //Check for a target found while burrowed - if ( interactionType == g_interactionAntlionFoundTarget ) - { - CBaseEntity *pOther = (CBaseEntity *) data; - - //Randomly delay - m_flBurrowTime = gpGlobals->curtime + random->RandomFloat( 0.5f, 1.0f ); - BurrowUse( pOther, pOther, USE_ON, 0.0f ); - - return true; - } - - // fixed for episodic: allow interactions to fall through in the base class. ifdefed away - // for mainline in case anything depends on this bug. -#ifdef HL2_EPISODIC - - if ( interactionType == g_interactionAntlionFiredAtTarget ) - { - // Bump out our attack time - if ( IsWorker() ) - { - float flDuration = *((float *)data); - SetNextAttack( gpGlobals->curtime + flDuration ); - } - } - - return BaseClass::HandleInteraction( interactionType, data, sender ); -#else - return false; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Antlion::Alone( void ) -{ - if ( m_pSquad == NULL ) - return true; - - if ( m_pSquad->NumMembers() <= 1 ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Antlion::StartJump( void ) -{ - if ( m_bForcedStuckJump == false ) - { - // FIXME: Why must this be true? - // Must be jumping at an enemy - // if ( GetEnemy() == NULL ) - // return; - - //Don't jump if we're not on the ground - if ( ( GetFlags() & FL_ONGROUND ) == false ) - return; - } - - //Take us off the ground - SetGroundEntity( NULL ); - SetAbsVelocity( m_vecSavedJump ); - - m_bForcedStuckJump = false; -#if HL2_EPISODIC - m_bHasDoneAirAttack = false; -#endif - - //Setup our jump time so that we don't try it again too soon - m_flJumpTime = gpGlobals->curtime + random->RandomInt( 2, 6 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : sHint - -// nNodeNum - -// Output : bool CAI_BaseNPC::FValidateHintType -//----------------------------------------------------------------------------- -bool CNPC_Antlion::FValidateHintType( CAI_Hint *pHint ) -{ - switch ( m_iContext ) - { - case ANTLION_BURROW_OUT: - { - //See if this is a valid point - Vector vHintPos; - pHint->GetPosition(this,&vHintPos); - - if ( ValidBurrowPoint( vHintPos ) == false ) - return false; - } - break; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &origin - -//----------------------------------------------------------------------------- -void CNPC_Antlion::ClearBurrowPoint( const Vector &origin ) -{ - CBaseEntity *pEntity = NULL; - float flDist; - Vector vecSpot, vecCenter, vecForce; - - bool bPlayerInSphere = false; - - //Iterate on all entities in the vicinity. - for ( CEntitySphereQuery sphere( origin, 128 ); ( pEntity = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() ) - { - if ( pEntity->Classify() == CLASS_PLAYER ) - { - bPlayerInSphere = true; - continue; - } - - if ( pEntity->m_takedamage != DAMAGE_NO && pEntity->Classify() != CLASS_PLAYER && pEntity->VPhysicsGetObject() ) - { - vecSpot = pEntity->BodyTarget( origin ); - vecForce = ( vecSpot - origin ) + Vector( 0, 0, 16 ); - - // decrease damage for an ent that's farther from the bomb. - flDist = VectorNormalize( vecForce ); - - //float mass = pEntity->VPhysicsGetObject()->GetMass(); - CollisionProp()->RandomPointInBounds( vec3_origin, Vector( 1.0f, 1.0f, 1.0f ), &vecCenter ); - - if ( flDist <= 128.0f ) - { - pEntity->VPhysicsGetObject()->Wake(); - pEntity->VPhysicsGetObject()->ApplyForceOffset( vecForce * 250.0f, vecCenter ); - } - } - } - - if ( bPlayerInSphere == false ) - { - //Cause a ruckus - UTIL_ScreenShake( origin, 1.0f, 80.0f, 1.0f, 256.0f, SHAKE_START ); - } -} - -bool NPC_CheckBrushExclude( CBaseEntity *pEntity, CBaseEntity *pBrush ); -//----------------------------------------------------------------------------- -// traceline methods -//----------------------------------------------------------------------------- -class CTraceFilterSimpleNPCExclude : public CTraceFilterSimple -{ -public: - DECLARE_CLASS( CTraceFilterSimpleNPCExclude, CTraceFilterSimple ); - - CTraceFilterSimpleNPCExclude( const IHandleEntity *passentity, int collisionGroup ) - : CTraceFilterSimple( passentity, collisionGroup ) - { - } - - bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) - { - Assert( dynamic_cast(pHandleEntity) ); - CBaseEntity *pTestEntity = static_cast(pHandleEntity); - - if ( GetPassEntity() ) - { - CBaseEntity *pEnt = gEntList.GetBaseEntity( GetPassEntity()->GetRefEHandle() ); - - if ( pEnt->IsNPC() ) - { - if ( NPC_CheckBrushExclude( pEnt, pTestEntity ) == true ) - return false; - } - } - return BaseClass::ShouldHitEntity( pHandleEntity, contentsMask ); - } -}; - -//----------------------------------------------------------------------------- -// Purpose: Determine whether a point is valid or not for burrowing up into -// Input : &point - point to test for validity -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Antlion::ValidBurrowPoint( const Vector &point ) -{ - trace_t tr; - - CTraceFilterSimpleNPCExclude filter( this, COLLISION_GROUP_NONE ); - AI_TraceHull( point, point+Vector(0,0,1), GetHullMins(), GetHullMaxs(), - MASK_NPCSOLID, &filter, &tr ); - - //See if we were able to get there - if ( ( tr.startsolid ) || ( tr.allsolid ) || ( tr.fraction < 1.0f ) ) - { - CBaseEntity *pEntity = tr.m_pEnt; - - //If it's a physics object, attempt to knock is away, unless it's a car - if ( ( pEntity ) && ( pEntity->VPhysicsGetObject() ) && ( pEntity->GetServerVehicle() == NULL ) ) - { - ClearBurrowPoint( point ); - } - - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Finds a burrow point for the antlion -// Input : distance - radius to search for burrow spot in -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Antlion::FindBurrow( const Vector &origin, float distance, int type, bool excludeNear ) -{ - //Burrowing in? - if ( type == ANTLION_BURROW_IN ) - { - //Attempt to find a burrowing point - CHintCriteria hintCriteria; - - hintCriteria.SetHintType( HINT_ANTLION_BURROW_POINT ); - hintCriteria.SetFlag( bits_HINT_NODE_NEAREST ); - - hintCriteria.AddIncludePosition( origin, distance ); - - if ( excludeNear ) - { - hintCriteria.AddExcludePosition( origin, 128 ); - } - - CAI_Hint *pHint = CAI_HintManager::FindHint( this, hintCriteria ); - - if ( pHint == NULL ) - return false; - - //Free up the node for use - if ( GetHintNode() ) - { - GetHintNode()->Unlock(0); - } - - SetHintNode( pHint ); - - //Lock the node - pHint->Lock(this); - - //Setup our path and attempt to run there - Vector vHintPos; - GetHintNode()->GetPosition( this, &vHintPos ); - - AI_NavGoal_t goal( vHintPos, ACT_RUN ); - - return GetNavigator()->SetGoal( goal ); - } - - //Burrow out - m_iContext = ANTLION_BURROW_OUT; - - CHintCriteria hintCriteria; - - hintCriteria.SetHintType( HINT_ANTLION_BURROW_POINT ); - hintCriteria.SetFlag( bits_HINT_NODE_NEAREST ); - - if ( GetEnemy() != NULL ) - { - hintCriteria.AddIncludePosition( GetEnemy()->GetAbsOrigin(), distance ); - } - - //Attempt to find an open burrow point - CAI_Hint *pHint = CAI_HintManager::FindHint( this, hintCriteria ); - - m_iContext = -1; - - if ( pHint == NULL ) - return false; - - //Free up the node for use - if (GetHintNode()) - { - GetHintNode()->Unlock(0); - } - - SetHintNode( pHint ); - pHint->Lock(this); - - Vector burrowPoint; - pHint->GetPosition(this,&burrowPoint); - - UTIL_SetOrigin( this, burrowPoint ); - - //Burrowing out - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Cause the antlion to unborrow -// Input : *pActivator - -// *pCaller - -// useType - -// value - -//----------------------------------------------------------------------------- - -void CNPC_Antlion::BurrowUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - //Don't allow us to do this again - SetUse( NULL ); - - //Allow idle sounds again - m_spawnflags &= ~SF_NPC_GAG; - - //If the player activated this, then take them as an enemy - if ( ( pCaller != NULL ) && ( pCaller->IsPlayer() ) ) - { - SetEnemy( pActivator ); - } - - //Start trying to surface - SetSchedule( SCHED_ANTLION_WAIT_UNBORROW ); -} - -//----------------------------------------------------------------------------- -// Purpose: Monitor the antlion's jump to play the proper landing sequence -//----------------------------------------------------------------------------- -bool CNPC_Antlion::CheckLanding( void ) -{ - trace_t tr; - Vector testPos, shove = Vector( -250.0f, 1.0f, 1.0f ); - QAngle viewPunch = QAngle( 4.0f, 0.0f, 0.0f ); - - //Amount of time to predict forward - const float timeStep = 0.1f; - - //Roughly looks one second into the future - testPos = GetAbsOrigin() + ( GetAbsVelocity() * timeStep ); - testPos[2] -= ( 0.5 * sv_gravity.GetFloat() * GetGravity() * timeStep * timeStep); - - if ( g_debug_antlion.GetInt() == 2 ) - { - NDebugOverlay::Line( GetAbsOrigin(), testPos, 255, 0, 0, 0, 0.5f ); - NDebugOverlay::Cross3D( m_vecSavedJump, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, true, 0.5f ); - } - - // Look below - AI_TraceHull( GetAbsOrigin(), testPos, NAI_Hull::Mins( GetHullType() ), NAI_Hull::Maxs( GetHullType() ), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - - //See if we're about to contact, or have already contacted the ground - if ( ( tr.fraction != 1.0f ) || ( GetFlags() & FL_ONGROUND ) ) - { - int sequence = SelectWeightedSequence( (Activity)ACT_ANTLION_LAND ); - - if ( GetSequence() != sequence ) - { - SetWings( false ); - VacateStrategySlot(); - SetIdealActivity( (Activity) ACT_ANTLION_LAND ); - - CreateDust( false ); - EmitSound( "NPC_Antlion.Land" ); - - if ( GetEnemy() && GetEnemy()->IsPlayer() ) - { - CBasePlayer *pPlayer = ToBasePlayer( GetEnemy() ); - - if ( pPlayer && pPlayer->IsInAVehicle() == false ) - MeleeAttack( ANTLION_MELEE1_RANGE, sk_antlion_swipe_damage.GetFloat(), viewPunch, shove ); - } - - SetAbsVelocity( GetAbsVelocity() * 0.33f ); - return false; - } - - return IsActivityFinished(); - } - - return false; -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEntity - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Antlion::QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC ) -{ - //If we're under the ground, don't look at enemies - if ( IsEffectActive( EF_NODRAW ) ) - return false; - - return BaseClass::QuerySeeEntity(pEntity, bOnlyHateOrFearIfNPC); -} - -//----------------------------------------------------------------------------- -// Purpose: Turns the antlion's wings on or off -// Input : state - on or off -//----------------------------------------------------------------------------- -void CNPC_Antlion::SetWings( bool state ) -{ - if ( m_bWingsOpen == state ) - return; - - m_bWingsOpen = state; - - if ( m_bWingsOpen ) - { - CPASAttenuationFilter filter( this, "NPC_Antlion.WingsOpen" ); - filter.MakeReliable(); - - EmitSound( filter, entindex(), "NPC_Antlion.WingsOpen" ); - SetBodygroup( 1, 1 ); - m_bLoopingStarted = true; - } - else - { - StopSound( "NPC_Antlion.WingsOpen" ); - SetBodygroup( 1, 0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Antlion::Burrow( void ) -{ - SetWings( false ); - - //Stop us from taking damage and being solid - m_spawnflags |= SF_NPC_GAG; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Antlion::Unburrow( void ) -{ - m_bStartBurrowed = false; - SetWings( false ); - - //Become solid again and visible - m_spawnflags &= ~SF_NPC_GAG; - RemoveSolidFlags( FSOLID_NOT_SOLID ); - m_takedamage = DAMAGE_YES; - - SetGroundEntity( NULL ); - - //If we have an enemy, come out facing them - if ( GetEnemy() ) - { - Vector dir = GetEnemy()->GetAbsOrigin() - GetAbsOrigin(); - VectorNormalize(dir); - - QAngle angles = GetAbsAngles(); - angles[ YAW ] = UTIL_VecToYaw( dir ); - SetLocalAngles( angles ); - } - - //fire output upon unburrowing - m_OnUnBurrowed.FireOutput( this, this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_Antlion::InputUnburrow( inputdata_t &inputdata ) -{ - if ( IsAlive() == false ) - return; - - SetSchedule( SCHED_ANTLION_WAIT_UNBORROW ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_Antlion::InputBurrow( inputdata_t &inputdata ) -{ - if ( IsAlive() == false ) - return; - - SetSchedule( SCHED_ANTLION_BURROW_IN ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_Antlion::InputBurrowAway( inputdata_t &inputdata ) -{ - if ( IsAlive() == false ) - return; - - SetSchedule( SCHED_ANTLION_BURROW_AWAY ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Antlion::CreateDust( bool placeDecal ) -{ - trace_t tr; - AI_TraceLine( GetAbsOrigin()+Vector(0,0,1), GetAbsOrigin()-Vector(0,0,64), MASK_SOLID_BRUSHONLY | CONTENTS_PLAYERCLIP | CONTENTS_MONSTERCLIP, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction < 1.0f ) - { - const surfacedata_t *pdata = physprops->GetSurfaceData( tr.surface.surfaceProps ); - - if ( hl2_episodic.GetBool() == true || ( pdata->game.material == CHAR_TEX_CONCRETE ) || - ( pdata->game.material == CHAR_TEX_DIRT ) || - ( pdata->game.material == CHAR_TEX_SAND ) ) - { - - if ( !m_bSuppressUnburrowEffects ) - { - UTIL_CreateAntlionDust( tr.endpos + Vector(0,0,24), GetAbsAngles() ); - - if ( placeDecal ) - { - UTIL_DecalTrace( &tr, "Antlion.Unburrow" ); - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pSound - -//----------------------------------------------------------------------------- -bool CNPC_Antlion::QueryHearSound( CSound *pSound ) -{ - if ( !BaseClass::QueryHearSound( pSound ) ) - return false; - - if ( pSound->m_iType == SOUND_BUGBAIT ) - { - //Must be more recent than the current - if ( pSound->SoundExpirationTime() <= m_flIgnoreSoundTime ) - return false; - - //If we can hear it, store it - m_bHasHeardSound = (pSound != NULL); - if ( m_bHasHeardSound ) - { - m_vecHeardSound = pSound->GetSoundOrigin(); - m_flIgnoreSoundTime = pSound->SoundExpirationTime(); - } - } - - //Do the normal behavior at this point - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Allows for modification of the interrupt mask for the current schedule. -// In the most cases the base implementation should be called first. -//----------------------------------------------------------------------------- -void CNPC_Antlion::BuildScheduleTestBits( void ) -{ - //Don't allow any modifications when scripted - if ( m_NPCState == NPC_STATE_SCRIPT ) - return; - - // If we're allied with the player, don't be startled by him - if ( IsAllied() ) - { - ClearCustomInterruptCondition( COND_HEAR_PLAYER ); - SetCustomInterruptCondition( COND_PLAYER_PUSHING ); - } - - //Make sure we interrupt a run schedule if we can jump - if ( IsCurSchedule(SCHED_CHASE_ENEMY) ) - { - SetCustomInterruptCondition( COND_ANTLION_CAN_JUMP ); - SetCustomInterruptCondition( COND_ENEMY_UNREACHABLE ); - } - - if ( !IsCurSchedule( SCHED_ANTLION_DROWN ) ) - { - // Interrupt any schedule unless already drowning. - SetCustomInterruptCondition( COND_ANTLION_IN_WATER ); - } - else - { - // Don't stop drowning just because you're in water! - ClearCustomInterruptCondition( COND_ANTLION_IN_WATER ); - } - - // Make sure we don't stop in midair - /* - if ( GetActivity() == ACT_JUMP || GetActivity() == ACT_GLIDE || GetActivity() == ACT_LAND ) - { - ClearCustomInterruptCondition( COND_NEW_ENEMY ); - } - */ - - //Interrupt any schedule unless already fleeing, burrowing, burrowed, or unburrowing. - if( !IsCurSchedule(SCHED_ANTLION_FLEE_THUMPER) && - !IsCurSchedule(SCHED_ANTLION_FLEE_PHYSICS_DANGER) && - !IsCurSchedule(SCHED_ANTLION_BURROW_IN) && - !IsCurSchedule(SCHED_ANTLION_WAIT_UNBORROW) && - !IsCurSchedule(SCHED_ANTLION_BURROW_OUT) && - !IsCurSchedule(SCHED_ANTLION_BURROW_WAIT) && - !IsCurSchedule(SCHED_ANTLION_WAIT_FOR_UNBORROW_TRIGGER)&& - !IsCurSchedule(SCHED_ANTLION_WAIT_FOR_CLEAR_UNBORROW)&& - !IsCurSchedule(SCHED_ANTLION_WAIT_UNBORROW) && - !IsCurSchedule(SCHED_ANTLION_JUMP) && - !IsCurSchedule(SCHED_ANTLION_FLIP) && - !IsCurSchedule(SCHED_ANTLION_DISMOUNT_NPC) && - ( GetFlags() & FL_ONGROUND ) ) - { - // Only do these if not jumping as well - if (!IsCurSchedule(SCHED_ANTLION_JUMP)) - { - if ( GetEnemy() == NULL ) - { - SetCustomInterruptCondition( COND_HEAR_PHYSICS_DANGER ); - } - - SetCustomInterruptCondition( COND_HEAR_THUMPER ); - SetCustomInterruptCondition( COND_HEAR_BUGBAIT ); - SetCustomInterruptCondition( COND_ANTLION_FLIPPED ); - SetCustomInterruptCondition( COND_ANTLION_CAN_JUMP_AT_TARGET ); - - if ( GetNavType() != NAV_JUMP ) - SetCustomInterruptCondition( COND_ANTLION_RECEIVED_ORDERS ); - } - - SetCustomInterruptCondition( COND_ANTLION_ON_NPC ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEnemy - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Antlion::IsValidEnemy( CBaseEntity *pEnemy ) -{ - //See if antlions are friendly to the player in this map - if ( IsAllied() && pEnemy->IsPlayer() ) - return false; - - if ( pEnemy->IsWorld() ) - return false; - - //If we're chasing bugbait, close to within a certain radius before picking up enemies - if ( IsCurSchedule( GetGlobalScheduleId( SCHED_ANTLION_CHASE_BUGBAIT ) ) && ( GetNavigator() != NULL ) ) - { - //If the enemy is without the target radius, then don't allow them - if ( ( GetNavigator()->IsGoalActive() ) && ( GetNavigator()->GetGoalPos() - pEnemy->GetAbsOrigin() ).Length() > bugbait_radius.GetFloat() ) - return false; - } - - // If we're following an entity we limit our attack distances - if ( m_FollowBehavior.GetFollowTarget() != NULL ) - { - float enemyDist = ( pEnemy->GetAbsOrigin() - GetAbsOrigin() ).LengthSqr(); - - if ( m_flObeyFollowTime > gpGlobals->curtime ) - { - // Unless we're right next to the enemy, follow our target - if ( enemyDist > (128*128) ) - return false; - } - else - { - // Otherwise don't follow if the target is far - if ( enemyDist > (2000*2000) ) - return false; - } - } - - return BaseClass::IsValidEnemy( pEnemy ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Antlion::GatherConditions( void ) -{ - BaseClass::GatherConditions(); - - // See if I've landed on an NPC! - CBaseEntity *pGroundEnt = GetGroundEntity(); - - if ( ( ( pGroundEnt != NULL ) && ( pGroundEnt->GetSolidFlags() & FSOLID_NOT_STANDABLE ) ) && ( GetFlags() & FL_ONGROUND ) && ( !IsEffectActive( EF_NODRAW ) && !pGroundEnt->IsEffectActive( EF_NODRAW ) ) ) - { - SetCondition( COND_ANTLION_ON_NPC ); - } - else - { - ClearCondition( COND_ANTLION_ON_NPC ); - } - - // See if our follow target is too far off -/* if ( m_hFollowTarget != NULL ) - { - float targetDist = UTIL_DistApprox( WorldSpaceCenter(), m_hFollowTarget->GetAbsOrigin() ); - - if ( targetDist > 400 ) - { - SetCondition( COND_ANTLION_FOLLOW_TARGET_TOO_FAR ); - } - else - { - ClearCondition( COND_ANTLION_FOLLOW_TARGET_TOO_FAR ); - } - }*/ - - if ( IsCurSchedule( SCHED_ANTLION_BURROW_WAIT ) == false && - IsCurSchedule(SCHED_ANTLION_BURROW_IN) == false && - IsCurSchedule(SCHED_ANTLION_BURROW_OUT) == false && - IsCurSchedule(SCHED_FALL_TO_GROUND ) == false && - IsEffectActive( EF_NODRAW ) == false ) - { - if( m_lifeState == LIFE_ALIVE && GetWaterLevel() > 1 ) - { - // Start Drowning! - SetCondition( COND_ANTLION_IN_WATER ); - } - } - - //Ignore the player pushing me if I'm flipped over! - if ( IsCurSchedule( SCHED_ANTLION_FLIP ) ) - ClearCondition( COND_PLAYER_PUSHING ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Antlion::PrescheduleThink( void ) -{ - UpdateHead(); - - Activity eActivity = GetActivity(); - - //See if we need to play their agitated sound - if ( ( eActivity == ACT_ANTLION_RUN_AGITATED ) && ( m_bAgitatedSound == false ) ) - { - //Start sound - CPASAttenuationFilter filter( this, "NPC_Antlion.LoopingAgitated" ); - filter.MakeReliable(); - - EmitSound( filter, entindex(), "NPC_Antlion.LoopingAgitated" ); - m_bAgitatedSound = true; - } - else if ( ( eActivity != ACT_ANTLION_RUN_AGITATED ) && ( m_bAgitatedSound == true ) ) - { - //Stop sound - StopSound( "NPC_Antlion.LoopingAgitated" ); - m_bAgitatedSound = false; - } - - //See if our wings got interrupted from being turned off - if ( ( m_bWingsOpen ) && - ( eActivity != ACT_ANTLION_JUMP_START ) && - ( eActivity != ACT_JUMP ) && - ( eActivity != ACT_GLIDE ) && - ( eActivity != ACT_ANTLION_LAND ) && - ( eActivity != ACT_ANTLION_DISTRACT )) - { - SetWings( false ); - } - - // Make sure we've turned off our burrow state if we're not in it - if ( IsEffectActive( EF_NODRAW ) && - ( eActivity != ACT_ANTLION_BURROW_IDLE ) && - ( eActivity != ACT_ANTLION_BURROW_OUT ) && - ( eActivity != ACT_ANTLION_BURROW_IN) ) - { - DevMsg( "Antlion failed to unburrow properly!\n" ); - Assert( 0 ); - RemoveEffects( EF_NODRAW ); - RemoveSolidFlags( FSOLID_NOT_SOLID ); - m_takedamage = DAMAGE_YES; - RemoveFlag( FL_NOTARGET ); - m_spawnflags &= ~SF_NPC_GAG; - } - - //New Enemy? Try to jump at him. - if ( HasCondition( COND_NEW_ENEMY ) ) - { - m_flJumpTime = 0.0f; - } - - // See if we should jump because of desirables conditions, or a scripted request - if ( ShouldJump() ) - { - SetCondition( COND_ANTLION_CAN_JUMP ); - } - else - { - ClearCondition( COND_ANTLION_CAN_JUMP ); - } - - BaseClass::PrescheduleThink(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flDamage - -// bitsDamageType - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Antlion::IsLightDamage( const CTakeDamageInfo &info ) -{ - if ( ( random->RandomInt( 0, 1 ) ) && ( info.GetDamage() > 3 ) ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Antlion::IsAllied( void ) -{ - return ( GlobalEntity_GetState( "antlion_allied" ) == GLOBAL_ON ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Antlion::ShouldResumeFollow( void ) -{ - if ( IsAllied() == false ) - return false; - - if ( m_MoveState == ANTLION_MOVE_FOLLOW || m_hFollowTarget == NULL ) - return false; - - if ( m_flSuppressFollowTime > gpGlobals->curtime ) - return false; - - if ( GetEnemy() != NULL ) - { - m_flSuppressFollowTime = gpGlobals->curtime + random->RandomInt( 5, 10 ); - return false; - } - - //TODO: See if the follow target has wandered off too far from where we last followed them to - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Antlion::ShouldAbandonFollow( void ) -{ - // Never give up if we can see the goal - if ( m_FollowBehavior.FollowTargetVisible() ) - return false; - - // Never give up if we're too close - float flDistance = UTIL_DistApprox2D( m_FollowBehavior.GetFollowTarget()->WorldSpaceCenter(), WorldSpaceCenter() ); - - if ( flDistance < 1500 ) - return false; - - if ( flDistance > 1500 * 2.0f ) - return true; - - // If we've failed too many times, give up - if ( m_FollowBehavior.GetNumFailedFollowAttempts() ) - return true; - - // If the target simply isn't reachable to us, give up - if ( m_FollowBehavior.TargetIsUnreachable() ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTarget - -//----------------------------------------------------------------------------- -void CNPC_Antlion::SetFightTarget( CBaseEntity *pTarget ) -{ - m_hFightGoalTarget = pTarget; - - SetCondition( COND_ANTLION_RECEIVED_ORDERS ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_Antlion::InputFightToPosition( inputdata_t &inputdata ) -{ - if ( IsAlive() == false ) - return; - - CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, inputdata.value.String(), NULL, inputdata.pActivator, inputdata.pCaller ); - - if ( pEntity != NULL ) - { - SetFightTarget( pEntity ); - SetFollowTarget( NULL ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_Antlion::InputStopFightToPosition( inputdata_t &inputdata ) -{ - SetFightTarget( NULL ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEnemy - -//----------------------------------------------------------------------------- -void CNPC_Antlion::GatherEnemyConditions( CBaseEntity *pEnemy ) -{ - // Do the base class - BaseClass::GatherEnemyConditions( pEnemy ); - - // Only continue if we burrow when eluded - if ( ( m_spawnflags & SF_ANTLION_BURROW_ON_ELUDED ) == false ) - return; - - // If we're not already too far away, check again - //TODO: Check to make sure we don't already have a condition set that removes the need for this - if ( HasCondition( COND_ENEMY_UNREACHABLE ) == false ) - { - Vector predPosition; - UTIL_PredictedPosition( GetEnemy(), 1.0f, &predPosition ); - - Vector predDir = ( predPosition - GetAbsOrigin() ); - float predLength = VectorNormalize( predDir ); - - // See if we'll be outside our effective target range - if ( predLength > m_flEludeDistance ) - { - Vector predVelDir = ( predPosition - GetEnemy()->GetAbsOrigin() ); - float predSpeed = VectorNormalize( predVelDir ); - - // See if the enemy is moving mostly away from us - if ( ( predSpeed > 512.0f ) && ( DotProduct( predVelDir, predDir ) > 0.0f ) ) - { - // Mark the enemy as eluded and burrow away - ClearEnemyMemory(); - SetEnemy( NULL ); - SetIdealState( NPC_STATE_ALERT ); - SetCondition( COND_ENEMY_UNREACHABLE ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Antlion::ShouldGib( const CTakeDamageInfo &info ) -{ - // If we're being hoisted, we only want to gib when the barnacle hurts us with his bite! - if ( IsEFlagSet( EFL_IS_BEING_LIFTED_BY_BARNACLE ) ) - { - if ( info.GetAttacker() && info.GetAttacker()->Classify() != CLASS_BARNACLE ) - return false; - - return true; - } - - if ( info.GetDamageType() & (DMG_NEVERGIB|DMG_DISSOLVE) ) - return false; - -#ifdef HL2_EPISODIC - if ( IsWorker() && ANTLION_WORKERS_BURST() ) - return !m_bDontExplode; -#endif - - if ( info.GetDamageType() & (DMG_ALWAYSGIB|DMG_BLAST) ) - return true; - - if ( m_iHealth < -20 ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Antlion::CorpseGib( const CTakeDamageInfo &info ) -{ -#ifdef HL2_EPISODIC - - if ( IsWorker() ) - { - DoPoisonBurst(); - } - else -#endif // HL2_EPISODIC - { - // Use the bone position to handle being moved by an animation (like a dynamic scripted sequence) - static int s_nBodyBone = -1; - if ( s_nBodyBone == -1 ) - { - s_nBodyBone = LookupBone( "Antlion.Body_Bone" ); - } - - Vector vecOrigin; - QAngle angBone; - GetBonePosition( s_nBodyBone, vecOrigin, angBone ); - - DispatchParticleEffect( "AntlionGib", vecOrigin, QAngle( 0, 0, 0 ) ); - } - - Vector velocity = vec3_origin; - AngularImpulse angVelocity = RandomAngularImpulse( -150, 150 ); - breakablepropparams_t params( EyePosition(), GetAbsAngles(), velocity, angVelocity ); - params.impactEnergyScale = 1.0f; - params.defBurstScale = 150.0f; - params.defCollisionGroup = COLLISION_GROUP_DEBRIS; - PropBreakableCreateAll( GetModelIndex(), NULL, params, this, -1, true, true ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOther - -//----------------------------------------------------------------------------- -void CNPC_Antlion::Touch( CBaseEntity *pOther ) -{ - //See if the touching entity is a vehicle - CBasePlayer *pPlayer = ToBasePlayer( AI_GetSinglePlayer() ); - - // FIXME: Technically we'll want to check to see if a vehicle has touched us with the player OR NPC driver - - if ( pPlayer && pPlayer->IsInAVehicle() ) - { - IServerVehicle *pVehicle = pPlayer->GetVehicle(); - CBaseEntity *pVehicleEnt = pVehicle->GetVehicleEnt(); - - if ( pVehicleEnt == pOther ) - { - CPropVehicleDriveable *pDrivableVehicle = dynamic_cast( pVehicleEnt ); - - if ( pDrivableVehicle != NULL ) - { - //Get tossed! - Vector vecShoveDir = pOther->GetAbsVelocity(); - Vector vecTargetDir = GetAbsOrigin() - pOther->GetAbsOrigin(); - - VectorNormalize( vecShoveDir ); - VectorNormalize( vecTargetDir ); - - bool bBurrowingOut = IsCurSchedule( SCHED_ANTLION_BURROW_OUT ); - - if ( ( ( pDrivableVehicle->m_nRPM > 75 ) && DotProduct( vecShoveDir, vecTargetDir ) <= 0 ) || bBurrowingOut == true ) - { - if ( IsFlipped() || bBurrowingOut == true ) - { - float flDamage = m_iHealth; - - if ( random->RandomInt( 0, 10 ) > 4 ) - flDamage += 25; - - CTakeDamageInfo dmgInfo( pVehicleEnt, pPlayer, flDamage, DMG_VEHICLE ); - - CalculateMeleeDamageForce( &dmgInfo, vecShoveDir, pOther->GetAbsOrigin() ); - TakeDamage( dmgInfo ); - } - else - { - // We're being shoved - CTakeDamageInfo dmgInfo( pVehicleEnt, pPlayer, 0, DMG_VEHICLE ); - PainSound( dmgInfo ); - - SetCondition( COND_ANTLION_FLIPPED ); - - vecTargetDir[2] = 0.0f; - - ApplyAbsVelocityImpulse( ( vecTargetDir * 250.0f ) + Vector(0,0,64.0f) ); - SetGroundEntity( NULL ); - - CSoundEnt::InsertSound( SOUND_PHYSICS_DANGER, GetAbsOrigin(), 256, 0.5f, this ); - } - } - } - } - } - - BaseClass::Touch( pOther ); - - // in episodic, an antlion colliding with the player in midair does him damage. - // pursuant bugs 58590, 56960, this happens only once per glide. -#ifdef HL2_EPISODIC - if ( GetActivity() == ACT_GLIDE && IsValidEnemy( pOther ) && !m_bHasDoneAirAttack ) - { - CTakeDamageInfo dmgInfo( this, this, sk_antlion_air_attack_dmg.GetInt(), DMG_SLASH ); - - CalculateMeleeDamageForce( &dmgInfo, Vector( 0, 0, 1 ), GetAbsOrigin() ); - pOther->TakeDamage( dmgInfo ); - - //Kick the player angles - bool bIsPlayer = pOther->IsPlayer(); - if ( bIsPlayer && !(pOther->GetFlags() & FL_GODMODE ) && pOther->GetMoveType() != MOVETYPE_NOCLIP ) - { - pOther->ViewPunch( QAngle( 4.0f, 0.0f, 0.0f ) ); - } - - // set my "I have already attacked someone" flag - if ( bIsPlayer || pOther->IsNPC()) - { - m_bHasDoneAirAttack = true; - } - } -#endif - - // Did the player touch me? - if ( pOther->IsPlayer() ) - { - // Don't test for this if the pusher isn't friendly - if ( IsValidEnemy( pOther ) ) - return; - - // Ignore if pissed at player - if ( m_afMemory & bits_MEMORY_PROVOKED ) - return; - - if ( !IsCurSchedule( SCHED_MOVE_AWAY ) && !IsCurSchedule( SCHED_ANTLION_BURROW_OUT ) ) - TestPlayerPushing( pOther ); - } - - //Adrian: Explode if hit by gunship! - //Maybe only do this if hit by the propellers? - if ( pOther->IsNPC() ) - { - if ( pOther->Classify() == CLASS_COMBINE_GUNSHIP ) - { - float flDamage = m_iHealth + 25; - - CTakeDamageInfo dmgInfo( pOther, pOther, flDamage, DMG_GENERIC ); - GuessDamageForce( &dmgInfo, (pOther->GetAbsOrigin() - GetAbsOrigin()), pOther->GetAbsOrigin() ); - TakeDamage( dmgInfo ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: turn in the direction of movement -// Output : -//----------------------------------------------------------------------------- -bool CNPC_Antlion::OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval ) -{ - if ( hl2_episodic.GetBool() ) - { - if ( IsWorker() && GetEnemy() ) - { - AddFacingTarget( GetEnemy(), GetEnemy()->WorldSpaceCenter(), 1.0f, 0.2f ); - return BaseClass::OverrideMoveFacing( move, flInterval ); - } - } - - //Adrian: Make antlions face the thumper while they flee away. - if ( IsCurSchedule( SCHED_ANTLION_FLEE_THUMPER ) ) - { - CSound *pSound = GetLoudestSoundOfType( SOUND_THUMPER ); - - if ( pSound ) - { - AddFacingTarget( pSound->GetSoundOrigin(), 1.0, 0.5f ); - } - } - else if ( GetEnemy() && GetNavigator()->GetMovementActivity() == ACT_RUN ) - { - // FIXME: this will break scripted sequences that walk when they have an enemy - Vector vecEnemyLKP = GetEnemyLKP(); - if ( UTIL_DistApprox( vecEnemyLKP, GetAbsOrigin() ) < 512 ) - { - // Only start facing when we're close enough - AddFacingTarget( GetEnemy(), vecEnemyLKP, 1.0, 0.2 ); - } - } - - return BaseClass::OverrideMoveFacing( move, flInterval ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Antlion::InputDisableJump( inputdata_t &inputdata ) -{ - m_bDisableJump = true; - CapabilitiesRemove( bits_CAP_MOVE_JUMP ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Antlion::InputEnableJump( inputdata_t &inputdata ) -{ - m_bDisableJump = false; - CapabilitiesAdd( bits_CAP_MOVE_JUMP ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTarget - -//----------------------------------------------------------------------------- -void CNPC_Antlion::SetFollowTarget( CBaseEntity *pTarget ) -{ - m_FollowBehavior.SetFollowTarget( pTarget ); - m_hFollowTarget = pTarget; - m_flObeyFollowTime = gpGlobals->curtime + ANTLION_OBEY_FOLLOW_TIME; - - SetCondition( COND_ANTLION_RECEIVED_ORDERS ); - - // Play an acknowledgement noise - if ( m_flNextAcknowledgeTime < gpGlobals->curtime ) - { - EmitSound( "NPC_Antlion.Distracted" ); - m_flNextAcknowledgeTime = gpGlobals->curtime + 1.0f; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Antlion::CreateBehaviors( void ) -{ - AddBehavior( &m_FollowBehavior ); - AddBehavior( &m_AssaultBehavior ); - - return BaseClass::CreateBehaviors(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_Antlion::InputIgnoreBugbait( inputdata_t &inputdata ) -{ - m_bIgnoreBugbait = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_Antlion::InputHearBugbait( inputdata_t &inputdata ) -{ - m_bIgnoreBugbait = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : state - -//----------------------------------------------------------------------------- -void CNPC_Antlion::SetMoveState( AntlionMoveState_e state ) -{ - m_MoveState = state; - - switch( m_MoveState ) - { - case ANTLION_MOVE_FOLLOW: - - m_FollowBehavior.SetFollowTarget( m_hFollowTarget ); - - // Clear any previous state - m_flSuppressFollowTime = 0; - - break; - - case ANTLION_MOVE_FIGHT_TO_GOAL: - - m_FollowBehavior.SetFollowTarget( NULL ); - - // Keep the time we started this - m_flSuppressFollowTime = gpGlobals->curtime + random->RandomInt( 10, 15 ); - break; - - default: - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Special version helps other NPCs hit overturned antlion -//----------------------------------------------------------------------------- -Vector CNPC_Antlion::BodyTarget( const Vector &posSrc, bool bNoisy /*= true*/ ) -{ - // Cache the bone away to avoid future lookups - if ( m_nBodyBone == -1 ) - { - CBaseAnimating *pAnimating = GetBaseAnimating(); - m_nBodyBone = pAnimating->LookupBone( "Antlion.Body_Bone" ); - } - - // Get the exact position in our center of mass (thorax) - Vector vecResult; - QAngle vecAngle; - GetBonePosition( m_nBodyBone, vecResult, vecAngle ); - - if ( bNoisy ) - return vecResult + RandomVector( -8, 8 ); - - return vecResult; -} - -//----------------------------------------------------------------------------- -// Purpose: Flip the antlion over -//----------------------------------------------------------------------------- -void CNPC_Antlion::Flip( bool bZapped /*= false*/ ) -{ - // We can't flip an already flipped antlion - if ( IsFlipped() ) - return; - - // Must be on the ground - if ( ( GetFlags() & FL_ONGROUND ) == false ) - return; - - // Can't be in a dynamic interation - if ( IsRunningDynamicInteraction() ) - return; - - SetCondition( COND_ANTLION_FLIPPED ); - - if ( bZapped ) - { - m_flZapDuration = gpGlobals->curtime + SequenceDuration( SelectWeightedSequence( (Activity) ACT_ANTLION_ZAP_FLIP) ) + 0.1f; - - EmitSound( "NPC_Antlion.ZappedFlip" ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_Antlion::InputJumpAtTarget( inputdata_t &inputdata ) -{ - CBaseEntity *pJumpTarget = gEntList.FindEntityByName( NULL, inputdata.value.String(), this, inputdata.pActivator, inputdata.pCaller ); - if ( pJumpTarget == NULL ) - { - Msg("Unable to find jump target named (%s)\n", inputdata.value.String() ); - return; - } - -#if HL2_EPISODIC - - // Try the jump - AIMoveTrace_t moveTrace; - Vector targetPos = pJumpTarget->GetAbsOrigin(); - - // initialize jump state - float minJumpHeight = 0.0; - float maxHorzVel = 800.0f; - - // initial jump, sets baseline for minJumpHeight - Vector vecApex; - Vector rawJumpVel = GetMoveProbe()->CalcJumpLaunchVelocity(GetAbsOrigin(), targetPos, sv_gravity.GetFloat() * GetJumpGravity(), &minJumpHeight, maxHorzVel, &vecApex ); - - if ( g_debug_antlion.GetInt() == 2 ) - { - NDebugOverlay::Box( targetPos, GetHullMins(), GetHullMaxs(), 0, 255, 0, 0, 5 ); - NDebugOverlay::Line( GetAbsOrigin(), targetPos, 0, 255, 0, 0, 5 ); - NDebugOverlay::Line( GetAbsOrigin(), rawJumpVel, 255, 255, 0, 0, 5 ); - } - - m_vecSavedJump = rawJumpVel; - -#else - - // Get the direction and speed to our target - Vector vecJumpDir = ( pJumpTarget->GetAbsOrigin() - GetAbsOrigin() ); - VectorNormalize( vecJumpDir ); - vecJumpDir *= 800.0f; // FIXME: We'd like to pass this in as a parameter, but comma delimited lists are bad - m_vecSavedJump = vecJumpDir; - -#endif - - SetCondition( COND_ANTLION_CAN_JUMP_AT_TARGET ); -} - -#if HL2_EPISODIC -//----------------------------------------------------------------------------- -// workers can explode. -//----------------------------------------------------------------------------- -void CNPC_Antlion::DoPoisonBurst() -{ - if ( GetWaterLevel() < 2 ) - { - CTakeDamageInfo info( this, this, sk_antlion_worker_burst_damage.GetFloat(), DMG_BLAST_SURFACE | ( ANTLION_WORKER_BURST_IS_POISONOUS() ? DMG_POISON : DMG_ACID ) ); - - RadiusDamage( info, GetAbsOrigin(), sk_antlion_worker_burst_radius.GetFloat(), CLASS_NONE, this ); - - DispatchParticleEffect( "antlion_gib_02", WorldSpaceCenter(), GetAbsAngles() ); - } - else - { - CEffectData data; - - data.m_vOrigin = WorldSpaceCenter(); - data.m_flMagnitude = 100; - data.m_flScale = 128; - data.m_fFlags = ( SF_ENVEXPLOSION_NODAMAGE | SF_ENVEXPLOSION_NOSPARKS | SF_ENVEXPLOSION_NODLIGHTS | SF_ENVEXPLOSION_NOSMOKE ); - - DispatchEffect( "WaterSurfaceExplosion", data ); - } - - EmitSound( "NPC_Antlion.PoisonBurstExplode" ); -} -#endif - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_Antlion::IsHeavyDamage( const CTakeDamageInfo &info ) -{ - if ( hl2_episodic.GetBool() && IsWorker() ) - { - if ( m_nSustainedDamage + info.GetDamage() > 6 ) - return true; - } - - return BaseClass::IsHeavyDamage( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : bForced - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Antlion::CanRunAScriptedNPCInteraction( bool bForced /*= false*/ ) -{ - // Workers shouldn't do DSS's because they explode - if ( IsWorker() ) - return false; - - return BaseClass::CanRunAScriptedNPCInteraction( bForced ); -} - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CAntlionRepellant ) - DEFINE_KEYFIELD( m_flRepelRadius, FIELD_FLOAT, "repelradius" ), - DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ), - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), -END_DATADESC() - -static CUtlVector< CHandle< CAntlionRepellant > >m_hRepellantList; - - -CAntlionRepellant::~CAntlionRepellant() -{ - m_hRepellantList.FindAndRemove( this ); -} - -void CAntlionRepellant::Spawn( void ) -{ - BaseClass::Spawn(); - m_bEnabled = true; - - m_hRepellantList.AddToTail( this ); -} - -void CAntlionRepellant::InputEnable( inputdata_t &inputdata ) -{ - m_bEnabled = true; - - if ( m_hRepellantList.HasElement( this ) == false ) - m_hRepellantList.AddToTail( this ); -} - -void CAntlionRepellant::InputDisable( inputdata_t &inputdata ) -{ - m_bEnabled = false; - m_hRepellantList.FindAndRemove( this ); -} - -float CAntlionRepellant::GetRadius( void ) -{ - if ( m_bEnabled == false ) - return 0.0f; - - return m_flRepelRadius; -} - -void CAntlionRepellant::OnRestore( void ) -{ - BaseClass::OnRestore(); - - if ( m_bEnabled == true ) - { - if ( m_hRepellantList.HasElement( this ) == false ) - m_hRepellantList.AddToTail( this ); - } -} - -bool CAntlionRepellant::IsPositionRepellantFree( Vector vDesiredPos ) -{ - for ( int i = 0; i < m_hRepellantList.Count(); i++ ) - { - if ( m_hRepellantList[i] ) - { - CAntlionRepellant *pRep = m_hRepellantList[i].Get(); - - if ( pRep ) - { - float flDist = (vDesiredPos - pRep->GetAbsOrigin()).Length(); - - if ( flDist <= pRep->GetRadius() ) - return false; - } - } - } - - return true; -} - -LINK_ENTITY_TO_CLASS( point_antlion_repellant, CAntlionRepellant); - - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC( npc_antlion, CNPC_Antlion ) - - //Register our interactions - DECLARE_INTERACTION( g_interactionAntlionFoundTarget ) - DECLARE_INTERACTION( g_interactionAntlionFiredAtTarget ) - - //Conditions - DECLARE_CONDITION( COND_ANTLION_FLIPPED ) - DECLARE_CONDITION( COND_ANTLION_ON_NPC ) - DECLARE_CONDITION( COND_ANTLION_CAN_JUMP ) - DECLARE_CONDITION( COND_ANTLION_FOLLOW_TARGET_TOO_FAR ) - DECLARE_CONDITION( COND_ANTLION_RECEIVED_ORDERS ) - DECLARE_CONDITION( COND_ANTLION_IN_WATER ) - DECLARE_CONDITION( COND_ANTLION_CAN_JUMP_AT_TARGET ) - DECLARE_CONDITION( COND_ANTLION_SQUADMATE_KILLED ) - - //Squad slots - DECLARE_SQUADSLOT( SQUAD_SLOT_ANTLION_JUMP ) - DECLARE_SQUADSLOT( SQUAD_SLOT_ANTLION_WORKER_FIRE ) - - //Tasks - DECLARE_TASK( TASK_ANTLION_SET_CHARGE_GOAL ) - DECLARE_TASK( TASK_ANTLION_BURROW ) - DECLARE_TASK( TASK_ANTLION_UNBURROW ) - DECLARE_TASK( TASK_ANTLION_VANISH ) - DECLARE_TASK( TASK_ANTLION_FIND_BURROW_IN_POINT ) - DECLARE_TASK( TASK_ANTLION_FIND_BURROW_OUT_POINT ) - DECLARE_TASK( TASK_ANTLION_BURROW_WAIT ) - DECLARE_TASK( TASK_ANTLION_CHECK_FOR_UNBORROW ) - DECLARE_TASK( TASK_ANTLION_JUMP ) - DECLARE_TASK( TASK_ANTLION_WAIT_FOR_TRIGGER ) - DECLARE_TASK( TASK_ANTLION_GET_THUMPER_ESCAPE_PATH ) - DECLARE_TASK( TASK_ANTLION_GET_PATH_TO_BUGBAIT ) - DECLARE_TASK( TASK_ANTLION_FACE_BUGBAIT ) - DECLARE_TASK( TASK_ANTLION_DISMOUNT_NPC ) - DECLARE_TASK( TASK_ANTLION_REACH_FIGHT_GOAL ) - DECLARE_TASK( TASK_ANTLION_GET_PHYSICS_DANGER_ESCAPE_PATH ) - DECLARE_TASK( TASK_ANTLION_FACE_JUMP ) - DECLARE_TASK( TASK_ANTLION_DROWN ) - DECLARE_TASK( TASK_ANTLION_GET_PATH_TO_RANDOM_NODE ) - DECLARE_TASK( TASK_ANTLION_FIND_COVER_FROM_SAVEPOSITION ) - - //Activities - DECLARE_ACTIVITY( ACT_ANTLION_DISTRACT ) - DECLARE_ACTIVITY( ACT_ANTLION_DISTRACT_ARRIVED ) - DECLARE_ACTIVITY( ACT_ANTLION_JUMP_START ) - DECLARE_ACTIVITY( ACT_ANTLION_BURROW_IN ) - DECLARE_ACTIVITY( ACT_ANTLION_BURROW_OUT ) - DECLARE_ACTIVITY( ACT_ANTLION_BURROW_IDLE ) - DECLARE_ACTIVITY( ACT_ANTLION_RUN_AGITATED ) - DECLARE_ACTIVITY( ACT_ANTLION_FLIP ) - DECLARE_ACTIVITY( ACT_ANTLION_POUNCE ) - DECLARE_ACTIVITY( ACT_ANTLION_POUNCE_MOVING ) - DECLARE_ACTIVITY( ACT_ANTLION_DROWN ) - DECLARE_ACTIVITY( ACT_ANTLION_LAND ) - DECLARE_ACTIVITY( ACT_ANTLION_WORKER_EXPLODE ) - DECLARE_ACTIVITY( ACT_ANTLION_ZAP_FLIP ) - - //Events - DECLARE_ANIMEVENT( AE_ANTLION_WALK_FOOTSTEP ) - DECLARE_ANIMEVENT( AE_ANTLION_MELEE_HIT1 ) - DECLARE_ANIMEVENT( AE_ANTLION_MELEE_HIT2 ) - DECLARE_ANIMEVENT( AE_ANTLION_MELEE_POUNCE ) - DECLARE_ANIMEVENT( AE_ANTLION_FOOTSTEP_SOFT ) - DECLARE_ANIMEVENT( AE_ANTLION_FOOTSTEP_HEAVY ) - DECLARE_ANIMEVENT( AE_ANTLION_START_JUMP ) - DECLARE_ANIMEVENT( AE_ANTLION_BURROW_IN ) - DECLARE_ANIMEVENT( AE_ANTLION_BURROW_OUT ) - DECLARE_ANIMEVENT( AE_ANTLION_VANISH ) - DECLARE_ANIMEVENT( AE_ANTLION_OPEN_WINGS ) - DECLARE_ANIMEVENT( AE_ANTLION_CLOSE_WINGS ) - DECLARE_ANIMEVENT( AE_ANTLION_MELEE1_SOUND ) - DECLARE_ANIMEVENT( AE_ANTLION_MELEE2_SOUND ) - DECLARE_ANIMEVENT( AE_ANTLION_WORKER_EXPLODE_SCREAM ) - DECLARE_ANIMEVENT( AE_ANTLION_WORKER_EXPLODE_WARN ) - DECLARE_ANIMEVENT( AE_ANTLION_WORKER_EXPLODE ) - DECLARE_ANIMEVENT( AE_ANTLION_WORKER_SPIT ) - DECLARE_ANIMEVENT( AE_ANTLION_WORKER_DONT_EXPLODE ) - - //Schedules - - //================================================== - // Jump - //================================================== - - DEFINE_SCHEDULE - ( - SCHED_ANTLION_JUMP, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_ANTLION_FACE_JUMP 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_ANTLION_JUMP_START" - " TASK_ANTLION_JUMP 0" - "" - " Interrupts" - " COND_TASK_FAILED" - ) - - //================================================== - // Wait for unborrow (once burrow has been triggered) - //================================================== - - DEFINE_SCHEDULE - ( - SCHED_ANTLION_WAIT_UNBORROW, - - " Tasks" - " TASK_ANTLION_BURROW_WAIT 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_ANTLION_WAIT_FOR_CLEAR_UNBORROW" - "" - " Interrupts" - " COND_TASK_FAILED" - ) - - //================================================== - // Burrow Wait - //================================================== - - DEFINE_SCHEDULE - ( - SCHED_ANTLION_BURROW_WAIT, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ANTLION_BURROW_WAIT" - " TASK_ANTLION_BURROW_WAIT 1" - " TASK_ANTLION_FIND_BURROW_OUT_POINT 1024" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_ANTLION_WAIT_FOR_CLEAR_UNBORROW" - "" - " Interrupts" - " COND_TASK_FAILED" - ) - - //================================================== - // Burrow In - //================================================== - - DEFINE_SCHEDULE - ( - SCHED_ANTLION_BURROW_IN, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY_FAILED" - " TASK_ANTLION_BURROW 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_ANTLION_BURROW_IN" - " TASK_ANTLION_VANISH 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_ANTLION_BURROW_WAIT" - "" - " Interrupts" - " COND_TASK_FAILED" - ) - - //================================================== - // Run to burrow in - //================================================== - - DEFINE_SCHEDULE - ( - SCHED_ANTLION_RUN_TO_BURROW_IN, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY_FAILED" - " TASK_SET_TOLERANCE_DISTANCE 8" - " TASK_ANTLION_FIND_BURROW_IN_POINT 512" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_ANTLION_BURROW_IN" - "" - " Interrupts" - " COND_TASK_FAILED" - " COND_GIVE_WAY" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - ) - - //================================================== - // Burrow Out - //================================================== - - DEFINE_SCHEDULE - ( - SCHED_ANTLION_BURROW_OUT, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ANTLION_BURROW_WAIT" - " TASK_ANTLION_UNBURROW 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_ANTLION_BURROW_OUT" - "" - " Interrupts" - " COND_TASK_FAILED" - ) - - //================================================== - // Wait for unborrow (triggered) - //================================================== - - DEFINE_SCHEDULE - ( - SCHED_ANTLION_WAIT_FOR_UNBORROW_TRIGGER, - - " Tasks" - " TASK_ANTLION_WAIT_FOR_TRIGGER 0" - "" - " Interrupts" - " COND_TASK_FAILED" - ) - - //================================================== - // Wait for clear burrow spot (triggered) - //================================================== - - DEFINE_SCHEDULE - ( - SCHED_ANTLION_WAIT_FOR_CLEAR_UNBORROW, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ANTLION_BURROW_WAIT" - " TASK_ANTLION_CHECK_FOR_UNBORROW 1" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_ANTLION_BURROW_OUT" - "" - " Interrupts" - " COND_TASK_FAILED" - ) - - //================================================== - // Run from the sound of a thumper! - //================================================== - DEFINE_SCHEDULE - ( - SCHED_ANTLION_FLEE_THUMPER, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_IDLE_STAND" - " TASK_ANTLION_GET_THUMPER_ESCAPE_PATH 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_ANTLION_DISTRACT_ARRIVED" - "" - " Interrupts" - " COND_TASK_FAILED" - " COND_ANTLION_FLIPPED" - ) - - //================================================== - // SCHED_ANTLION_CHASE_BUGBAIT - //================================================== - DEFINE_SCHEDULE - ( - SCHED_ANTLION_CHASE_BUGBAIT, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_ANTLION_GET_PATH_TO_BUGBAIT 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_ANTLION_FACE_BUGBAIT 0" - "" - " Interrupts" - " COND_CAN_MELEE_ATTACK1" - " COND_SEE_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - ) - - //================================================== - // SCHED_ANTLION_ZAP_FLIP - //================================================== - DEFINE_SCHEDULE - ( - SCHED_ANTLION_ZAP_FLIP, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_RESET_ACTIVITY 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_ANTLION_ZAP_FLIP" - - " Interrupts" - " COND_TASK_FAILED" - ) - - //================================================== - // SCHED_ANTLION_FLIP - //================================================== - DEFINE_SCHEDULE - ( - SCHED_ANTLION_FLIP, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_RESET_ACTIVITY 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_ANTLION_FLIP" - - " Interrupts" - " COND_TASK_FAILED" - ) - - //========================================================= - // Headcrab has landed atop another NPC. Get down! - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_ANTLION_DISMOUNT_NPC, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_ANTLION_DISMOUNT_NPC 0" - - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_ANTLION_RUN_TO_FIGHT_GOAL, - - " Tasks" - " TASK_SET_TOLERANCE_DISTANCE 128" - " TASK_GET_PATH_TO_SAVEPOSITION 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_ANTLION_REACH_FIGHT_GOAL 0" - - " Interrupts" - " COND_NEW_ENEMY" - " COND_HEAVY_DAMAGE" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_ANTLION_CAN_JUMP" - ) - - DEFINE_SCHEDULE - ( - SCHED_ANTLION_RUN_TO_FOLLOW_GOAL, - - " Tasks" - " TASK_SET_TOLERANCE_DISTANCE 128" - " TASK_GET_PATH_TO_SAVEPOSITION 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - - " Interrupts" - " COND_NEW_ENEMY" - " COND_HEAVY_DAMAGE" - " COND_ANTLION_CAN_JUMP" - " COND_ANTLION_FOLLOW_TARGET_TOO_FAR" - ) - - DEFINE_SCHEDULE - ( - SCHED_ANTLION_BUGBAIT_IDLE_STAND, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_PLAYER 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT 2" - - " Interrupts" - " COND_NEW_ENEMY" - " COND_HEAVY_DAMAGE" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_HEAR_COMBAT" - " COND_ANTLION_CAN_JUMP" - " COND_ANTLION_FOLLOW_TARGET_TOO_FAR" - " COND_GIVE_WAY" - ) - - DEFINE_SCHEDULE - ( - SCHED_ANTLION_BURROW_AWAY, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_ANTLION_BURROW 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_ANTLION_BURROW_IN" - " TASK_ANTLION_VANISH 1" - - " Interrupts" - ) - - //================================================== - // Run from the sound of a physics crash - //================================================== - DEFINE_SCHEDULE - ( - SCHED_ANTLION_FLEE_PHYSICS_DANGER, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY" - " TASK_ANTLION_GET_PHYSICS_DANGER_ESCAPE_PATH 1024" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - "" - " Interrupts" - " COND_TASK_FAILED" - ) - - // Pounce forward at our enemy - DEFINE_SCHEDULE - ( - SCHED_ANTLION_POUNCE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_ANNOUNCE_ATTACK 1" - " TASK_RESET_ACTIVITY 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_ANTLION_POUNCE" - - " Interrupts" - " COND_TASK_FAILED" - ) - // Pounce forward at our enemy - DEFINE_SCHEDULE - ( - SCHED_ANTLION_POUNCE_MOVING, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_ANNOUNCE_ATTACK 1" - " TASK_RESET_ACTIVITY 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_ANTLION_POUNCE_MOVING" - - " Interrupts" - " COND_TASK_FAILED" - ) - - //========================================================= - // The irreversible process of drowning - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_ANTLION_DROWN, - - " Tasks" - " TASK_SET_ACTIVITY ACTIVITY:ACT_ANTLION_DROWN" - " TASK_ANTLION_DROWN 0" - "" - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_ANTLION_WORKER_RANGE_ATTACK1, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_ANNOUNCE_ATTACK 1" // 1 = primary attack - " TASK_RANGE_ATTACK1 0" - "" - " Interrupts" - " COND_TASK_FAILED" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - ) - - DEFINE_SCHEDULE - ( - SCHED_ANTLION_WORKER_FLANK_RANDOM, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ANTLION_WORKER_RUN_RANDOM" - " TASK_SET_TOLERANCE_DISTANCE 48" - " TASK_SET_ROUTE_SEARCH_TIME 1" // Spend 1 second trying to build a path if stuck - " TASK_GET_FLANK_ARC_PATH_TO_ENEMY_LOS 30" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_TASK_FAILED" - " COND_HEAVY_DAMAGE" - " COND_ANTLION_SQUADMATE_KILLED" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_MELEE_ATTACK1" - ) - - DEFINE_SCHEDULE - ( - SCHED_ANTLION_WORKER_RUN_RANDOM, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ANTLION_TAKE_COVER_FROM_ENEMY" - " TASK_SET_TOLERANCE_DISTANCE 48" - " TASK_SET_ROUTE_SEARCH_TIME 1" // Spend 1 second trying to build a path if stuck - " TASK_GET_PATH_TO_RANDOM_NODE 128" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_TASK_FAILED" - " COND_CAN_RANGE_ATTACK1" - ) - - DEFINE_SCHEDULE - ( - SCHED_ANTLION_TAKE_COVER_FROM_ENEMY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_FAIL_TAKE_COVER" - " TASK_FIND_COVER_FROM_ENEMY 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - "" - " Interrupts" - " COND_TASK_FAILED" - " COND_NEW_ENEMY" - ) - - DEFINE_SCHEDULE - ( - SCHED_ANTLION_TAKE_COVER_FROM_SAVEPOSITION, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_FAIL_TAKE_COVER" - " TASK_ANTLION_FIND_COVER_FROM_SAVEPOSITION 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - "" - " Interrupts" - " COND_TASK_FAILED" - " COND_NEW_ENEMY" - ) - -AI_END_CUSTOM_NPC() - - -//----------------------------------------------------------------------------- -// Purpose: Whether or not the target is a worker class of antlion -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool IsAntlionWorker( CBaseEntity *pEntity ) -{ - // Must at least be valid and an antlion - return ( pEntity != NULL && - pEntity->Classify() == CLASS_ANTLION && - pEntity->HasSpawnFlags( SF_ANTLION_WORKER ) && - dynamic_cast(pEntity) != NULL ); // Save this as the last step -} - -//----------------------------------------------------------------------------- -// Purpose: Whether or not the entity is a common antlion -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool IsAntlion( CBaseEntity *pEntity ) -{ - // Must at least be valid and an antlion - return ( pEntity != NULL && - pEntity->Classify() == CLASS_ANTLION && - dynamic_cast(pEntity) != NULL ); // Save this as the last step -} - -#ifdef HL2_EPISODIC -//----------------------------------------------------------------------------- -// Purpose: Used by other entities to judge the antlion worker's radius of damage -//----------------------------------------------------------------------------- -float AntlionWorkerBurstRadius( void ) -{ - return sk_antlion_worker_burst_radius.GetFloat(); -} -#endif // HL2_EPISODIC diff --git a/game/server/hl2/npc_antlion.h b/game/server/hl2/npc_antlion.h deleted file mode 100644 index 7da91300d..000000000 --- a/game/server/hl2/npc_antlion.h +++ /dev/null @@ -1,418 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef NPC_ANTLION_H -#define NPC_ANTLION_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_blended_movement.h" -#include "soundent.h" -#include "ai_behavior_follow.h" -#include "ai_behavior_assault.h" - -class CAntlionTemplateMaker; - -#define ANTLION_FOLLOW_DISTANCE 350 -#define ANTLION_FOLLOW_DISTANCE_SQR (ANTLION_FOLLOW_DISTANCE*ANTLION_FOLLOW_DISTANCE) -#define ANTLION_SKIN_COUNT 4 - -class CNPC_Antlion; - -// Antlion follow behavior -class CAI_AntlionFollowBehavior : public CAI_FollowBehavior -{ - typedef CAI_FollowBehavior BaseClass; - -public: - - CAI_AntlionFollowBehavior() - : BaseClass( AIF_ANTLION ) - { - } - - bool FarFromFollowTarget( void ) - { - return ( GetFollowTarget() && (GetAbsOrigin() - GetFollowTarget()->GetAbsOrigin()).LengthSqr() > ANTLION_FOLLOW_DISTANCE_SQR ); - } - - bool ShouldFollow( void ) - { - if ( GetFollowTarget() == NULL ) - return false; - - if ( GetEnemy() != NULL ) - return false; - - return true; - } -}; - -// -// Antlion class -// - -enum AntlionMoveState_e -{ - ANTLION_MOVE_FREE, - ANTLION_MOVE_FOLLOW, - ANTLION_MOVE_FIGHT_TO_GOAL, -}; - -#define SF_ANTLION_BURROW_ON_ELUDED ( 1 << 16 ) -#define SF_ANTLION_USE_GROUNDCHECKS ( 1 << 17 ) -#define SF_ANTLION_WORKER ( 1 << 18 ) // Use the "worker" model - -typedef CAI_BlendingHost< CAI_BehaviorHost > CAI_BaseAntlionBase; - -class CNPC_Antlion : public CAI_BaseAntlionBase -{ -public: - - DECLARE_CLASS( CNPC_Antlion, CAI_BaseAntlionBase ); - - CNPC_Antlion( void ); - - virtual float InnateRange1MinRange( void ) { return 50*12; } - virtual float InnateRange1MaxRange( void ) { return 250*12; } - - bool IsWorker( void ) const { return HasSpawnFlags( SF_ANTLION_WORKER ); } // NOTE: IsAntlionWorker function must agree! - - float GetIdealAccel( void ) const; - float MaxYawSpeed( void ); - bool FInViewCone( CBaseEntity *pEntity ); - bool FInViewCone( const Vector &vecSpot ); - - void Activate( void ); - void HandleAnimEvent( animevent_t *pEvent ); - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - void IdleSound( void ); - void PainSound( const CTakeDamageInfo &info ); - void Precache( void ); - void Spawn( void ); - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - void BuildScheduleTestBits( void ); - void GatherConditions( void ); - void PrescheduleThink( void ); - void ZapThink( void ); - void BurrowUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - bool CreateVPhysics(); - - bool IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos ) const; - bool HandleInteraction( int interactionType, void *data, CBaseCombatCharacter *sender = NULL ); - bool QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC = false ); - bool ShouldPlayIdleSound( void ); - bool OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval ); - bool IsValidEnemy(CBaseEntity *pEnemy); - bool QueryHearSound( CSound *pSound ); - bool IsLightDamage( const CTakeDamageInfo &info ); - bool CreateBehaviors( void ); - bool ShouldHearBugbait( void ) { return ( m_bIgnoreBugbait == false ); } - int SelectSchedule( void ); - - void Touch( CBaseEntity *pOther ); - - virtual int RangeAttack1Conditions( float flDot, float flDist ); - virtual int MeleeAttack1Conditions( float flDot, float flDist ); - virtual int MeleeAttack2Conditions( float flDot, float flDist ); - virtual int GetSoundInterests( void ) { return (BaseClass::GetSoundInterests())|(SOUND_DANGER|SOUND_PHYSICS_DANGER|SOUND_THUMPER|SOUND_BUGBAIT); } - virtual bool IsHeavyDamage( const CTakeDamageInfo &info ); - - Class_T Classify( void ) { return CLASS_ANTLION; } - - void Event_Killed( const CTakeDamageInfo &info ); - bool FValidateHintType ( CAI_Hint *pHint ); - void GatherEnemyConditions( CBaseEntity *pEnemy ); - - bool IsAllied( void ); - bool ShouldGib( const CTakeDamageInfo &info ); - bool CorpseGib( const CTakeDamageInfo &info ); - - float GetMaxJumpSpeed() const { return 1024.0f; } - - void SetFightTarget( CBaseEntity *pTarget ); - void InputFightToPosition( inputdata_t &inputdata ); - void InputStopFightToPosition( inputdata_t &inputdata ); - void InputJumpAtTarget( inputdata_t &inputdata ); - - void SetFollowTarget( CBaseEntity *pTarget ); - int TranslateSchedule( int scheduleType ); - - virtual Activity NPC_TranslateActivity( Activity baseAct ); - - bool ShouldResumeFollow( void ); - bool ShouldAbandonFollow( void ); - - void SetMoveState( AntlionMoveState_e state ); - int ChooseMoveSchedule( void ); - - DECLARE_DATADESC(); - - bool m_bStartBurrowed; - float m_flNextJumpPushTime; - - void SetParentSpawnerName( const char *szName ) { m_strParentSpawner = MAKE_STRING( szName ); } - const char *GetParentSpawnerName( void ) { return STRING( m_strParentSpawner ); } - - virtual void StopLoopingSounds( void ); - bool AllowedToBePushed( void ); - - virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true ); - virtual float GetAutoAimRadius() { return 36.0f; } - - void ClearBurrowPoint( const Vector &origin ); - - void Flip( bool bZapped = false ); - - bool CanBecomeRagdoll(); - - virtual void NotifyDeadFriend( CBaseEntity *pFriend ); - -private: - - inline CBaseEntity *EntityToWatch( void ); - void UpdateHead( void ); - - bool FindChasePosition( const Vector &targetPos, Vector &result ); - bool GetGroundPosition( const Vector &testPos, Vector &result ); - bool GetPathToSoundFleePoint( int soundType ); - inline bool IsFlipped( void ); - - void Burrow( void ); - void Unburrow( void ); - - void InputUnburrow( inputdata_t &inputdata ); - void InputBurrow( inputdata_t &inputdata ); - void InputBurrowAway( inputdata_t &inputdata ); - void InputDisableJump( inputdata_t &inputdata ); - void InputEnableJump( inputdata_t &inputdata ); - void InputIgnoreBugbait( inputdata_t &inputdata ); - void InputHearBugbait( inputdata_t &inputdata ); - - bool FindBurrow( const Vector &origin, float distance, int type, bool excludeNear = true ); - void CreateDust( bool placeDecal = true ); - - bool ValidBurrowPoint( const Vector &point ); - bool CheckLanding( void ); - bool Alone( void ); - bool CheckAlertRadius( void ); - bool ShouldJump( void ); - - void MeleeAttack( float distance, float damage, QAngle& viewPunch, Vector& shove ); - void SetWings( bool state ); - void StartJump( void ); - void LockJumpNode( void ); - - bool IsUnusableNode(int iNodeID, CAI_Hint *pHint); - - bool OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ); - - void ManageFleeCapabilities( bool bEnable ); - - int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ); - bool IsFirmlyOnGround( void ); - void CascadePush( const Vector &vecForce ); - - virtual bool CanRunAScriptedNPCInteraction( bool bForced = false ); - - virtual void Ignite ( float flFlameLifetime, bool bNPCOnly, float flSize, bool bCalledByLevelDesigner ); - virtual bool GetSpitVector( const Vector &vecStartPos, const Vector &vecTarget, Vector *vecOut ); - virtual bool InnateWeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions ); - virtual bool FCanCheckAttacks( void ); - - bool SeenEnemyWithinTime( float flTime ); - void DelaySquadAttack( float flDuration ); - -#if HL2_EPISODIC - void DoPoisonBurst(); -#endif - - float m_flIdleDelay; - float m_flBurrowTime; - float m_flJumpTime; - float m_flAlertRadius; - - float m_flPounceTime; - int m_iUnBurrowAttempts; - int m_iContext; //for FValidateHintType context - - Vector m_vecSaveSpitVelocity; // Saved when we start to attack and used if we failed to get a clear shot once we release - - CAI_AntlionFollowBehavior m_FollowBehavior; - CAI_AssaultBehavior m_AssaultBehavior; - - AntlionMoveState_e m_MoveState; - - COutputEvent m_OnReachFightGoal; //Reached our scripted destination to fight to - COutputEvent m_OnUnBurrowed; //Unburrowed - - Vector m_vecSavedJump; - Vector m_vecLastJumpAttempt; - - float m_flIgnoreSoundTime; // Sound time to ignore if earlier than - float m_flNextAcknowledgeTime; // Next time an antlion can make an acknowledgement noise - float m_flSuppressFollowTime; // Amount of time to suppress our follow time - float m_flObeyFollowTime; // A range of time the antlions must be obedient - - Vector m_vecHeardSound; - bool m_bHasHeardSound; - bool m_bAgitatedSound; //Playing agitated sound? - bool m_bWingsOpen; //Are the wings open? - bool m_bIgnoreBugbait; //If the antlion should ignore bugbait sounds - string_t m_strParentSpawner; //Name of our spawner - - EHANDLE m_hFollowTarget; - EHANDLE m_hFightGoalTarget; - float m_flEludeDistance; //Distance until the antlion will consider himself "eluded" if so flagged - bool m_bLeapAttack; - bool m_bDisableJump; - float m_flTimeDrown; - float m_flTimeDrownSplash; - bool m_bDontExplode; // Suppresses worker poison burst when drowning, failing to unburrow, etc. - bool m_bLoopingStarted; - bool m_bSuppressUnburrowEffects; // Don't kick up dust when spawning -#if HL2_EPISODIC - bool m_bHasDoneAirAttack; ///< only allowed to apply this damage once per glide -#endif - - bool m_bForcedStuckJump; - int m_nBodyBone; - - // Used to trigger a heavy damage interrupt if sustained damage is taken - int m_nSustainedDamage; - float m_flLastDamageTime; - float m_flZapDuration; - -protected: - int m_poseHead_Yaw, m_poseHead_Pitch; - virtual void PopulatePoseParameters( void ); - -private: - - HSOUNDSCRIPTHANDLE m_hFootstep; - - DEFINE_CUSTOM_AI; - - //================================================== - // AntlionConditions - //================================================== - - enum - { - COND_ANTLION_FLIPPED = LAST_SHARED_CONDITION, - COND_ANTLION_ON_NPC, - COND_ANTLION_CAN_JUMP, - COND_ANTLION_FOLLOW_TARGET_TOO_FAR, - COND_ANTLION_RECEIVED_ORDERS, - COND_ANTLION_IN_WATER, - COND_ANTLION_CAN_JUMP_AT_TARGET, - COND_ANTLION_SQUADMATE_KILLED - }; - - //================================================== - // AntlionSchedules - //================================================== - - enum - { - SCHED_ANTLION_CHASE_ENEMY_BURROW = LAST_SHARED_SCHEDULE, - SCHED_ANTLION_JUMP, - SCHED_ANTLION_RUN_TO_BURROW_IN, - SCHED_ANTLION_BURROW_IN, - SCHED_ANTLION_BURROW_WAIT, - SCHED_ANTLION_BURROW_OUT, - SCHED_ANTLION_WAIT_FOR_UNBORROW_TRIGGER, - SCHED_ANTLION_WAIT_FOR_CLEAR_UNBORROW, - SCHED_ANTLION_WAIT_UNBORROW, - SCHED_ANTLION_FLEE_THUMPER, - SCHED_ANTLION_CHASE_BUGBAIT, - SCHED_ANTLION_FLIP, - SCHED_ANTLION_DISMOUNT_NPC, - SCHED_ANTLION_RUN_TO_FIGHT_GOAL, - SCHED_ANTLION_RUN_TO_FOLLOW_GOAL, - SCHED_ANTLION_BUGBAIT_IDLE_STAND, - SCHED_ANTLION_BURROW_AWAY, - SCHED_ANTLION_FLEE_PHYSICS_DANGER, - SCHED_ANTLION_POUNCE, - SCHED_ANTLION_POUNCE_MOVING, - SCHED_ANTLION_DROWN, - SCHED_ANTLION_WORKER_RANGE_ATTACK1, - SCHED_ANTLION_WORKER_RUN_RANDOM, - SCHED_ANTLION_TAKE_COVER_FROM_ENEMY, - SCHED_ANTLION_ZAP_FLIP, - SCHED_ANTLION_WORKER_FLANK_RANDOM, - SCHED_ANTLION_TAKE_COVER_FROM_SAVEPOSITION - }; - - //================================================== - // AntlionTasks - //================================================== - - enum - { - TASK_ANTLION_SET_CHARGE_GOAL = LAST_SHARED_TASK, - TASK_ANTLION_FIND_BURROW_IN_POINT, - TASK_ANTLION_FIND_BURROW_OUT_POINT, - TASK_ANTLION_BURROW, - TASK_ANTLION_UNBURROW, - TASK_ANTLION_VANISH, - TASK_ANTLION_BURROW_WAIT, - TASK_ANTLION_CHECK_FOR_UNBORROW, - TASK_ANTLION_JUMP, - TASK_ANTLION_WAIT_FOR_TRIGGER, - TASK_ANTLION_GET_THUMPER_ESCAPE_PATH, - TASK_ANTLION_GET_PATH_TO_BUGBAIT, - TASK_ANTLION_FACE_BUGBAIT, - TASK_ANTLION_DISMOUNT_NPC, - TASK_ANTLION_REACH_FIGHT_GOAL, - TASK_ANTLION_GET_PHYSICS_DANGER_ESCAPE_PATH, - TASK_ANTLION_FACE_JUMP, - TASK_ANTLION_DROWN, - TASK_ANTLION_GET_PATH_TO_RANDOM_NODE, - TASK_ANTLION_FIND_COVER_FROM_SAVEPOSITION, - }; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Shield -//----------------------------------------------------------------------------- -class CAntlionRepellant : public CPointEntity -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( CAntlionRepellant, CPointEntity ); - ~CAntlionRepellant(); - -public: - void Spawn( void ); - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - float GetRadius( void ); - void SetRadius( float flRadius ) { m_flRepelRadius = flRadius; } - - static bool IsPositionRepellantFree( Vector vDesiredPos ); - - void OnRestore( void ); - -private: - - float m_flRepelRadius; - bool m_bEnabled; -}; - -extern bool IsAntlion( CBaseEntity *pEntity ); -extern bool IsAntlionWorker( CBaseEntity *pEntity ); - -#ifdef HL2_EPISODIC -extern float AntlionWorkerBurstRadius( void ); -#endif // HL2_EPISODIC - -#endif // NPC_ANTLION_H diff --git a/game/server/hl2/npc_antliongrub.cpp b/game/server/hl2/npc_antliongrub.cpp deleted file mode 100644 index 50db89e07..000000000 --- a/game/server/hl2/npc_antliongrub.cpp +++ /dev/null @@ -1,979 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Antlion Grub - cannon fodder -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "gib.h" -#include "Sprite.h" -#include "te_effect_dispatch.h" -#include "npc_antliongrub.h" -#include "ai_utils.h" -#include "particle_parse.h" -#include "items.h" -#include "item_dynamic_resupply.h" -#include "npc_vortigaunt_episodic.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar sk_grubnugget_health_small( "sk_grubnugget_health_small", "1" ); -ConVar sk_grubnugget_health_medium( "sk_grubnugget_health_medium", "4" ); -ConVar sk_grubnugget_health_large( "sk_grubnugget_health_large", "6" ); -ConVar sk_grubnugget_enabled( "sk_grubnugget_enabled", "1" ); - -#define ANTLIONGRUB_MODEL "models/antlion_grub.mdl" -#define ANTLIONGRUB_SQUASHED_MODEL "models/antlion_grub_squashed.mdl" - -#define SF_ANTLIONGRUB_NO_AUTO_PLACEMENT (1<<0) - - -enum GrubState_e -{ - GRUB_STATE_IDLE, - GRUB_STATE_AGITATED, -}; - -enum -{ - NUGGET_NONE, - NUGGET_SMALL = 1, - NUGGET_MEDIUM, - NUGGET_LARGE -}; - -// -// Grub nugget -// - -class CGrubNugget : public CItem -{ -public: - DECLARE_CLASS( CGrubNugget, CItem ); - - virtual void Spawn( void ); - virtual void Precache( void ); - virtual void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); - virtual void Event_Killed( const CTakeDamageInfo &info ); - virtual bool VPhysicsIsFlesh( void ); - - bool MyTouch( CBasePlayer *pPlayer ); - void SetDenomination( int nSize ) { Assert( nSize <= NUGGET_LARGE && nSize >= NUGGET_SMALL ); m_nDenomination = nSize; } - - DECLARE_DATADESC(); - -private: - int m_nDenomination; // Denotes size and health amount given -}; - -BEGIN_DATADESC( CGrubNugget ) - DEFINE_FIELD( m_nDenomination, FIELD_INTEGER ), -END_DATADESC() - -LINK_ENTITY_TO_CLASS( item_grubnugget, CGrubNugget ); - -// -// Simple grub -// - -class CAntlionGrub : public CBaseAnimating -{ -public: - DECLARE_CLASS( CAntlionGrub, CBaseAnimating ); - - virtual void Activate( void ); - virtual void Spawn( void ); - virtual void Precache( void ); - virtual void UpdateOnRemove( void ); - virtual void Event_Killed( const CTakeDamageInfo &info ); - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - - void InputSquash( inputdata_t &data ); - - void IdleThink( void ); - void FlinchThink( void ); - void GrubTouch( CBaseEntity *pOther ); - - DECLARE_DATADESC(); - -protected: - - inline bool InPVS( void ); - void SetNextThinkByDistance( void ); - - int GetNuggetDenomination( void ); - void CreateNugget( void ); - void MakeIdleSounds( void ); - void MakeSquashDecals( const Vector &vecOrigin ); - void AttachToSurface( void ); - void CreateGlow( void ); - void FadeGlow( void ); - void Squash( CBaseEntity *pOther, bool bDealDamage, bool bSpawnBlood ); - void SpawnSquashedGrub( void ); - void InputAgitate( inputdata_t &inputdata ); - - inline bool ProbeSurface( const Vector &vecTestPos, const Vector &vecDir, Vector *vecResult, Vector *vecNormal ); - - CHandle m_hGlowSprite; - int m_nGlowSpriteHandle; - float m_flFlinchTime; - float m_flNextIdleSoundTime; - float m_flNextSquealSoundTime; - bool m_bOutsidePVS; - GrubState_e m_State; - - COutputEvent m_OnAgitated; - COutputEvent m_OnDeath; - COutputEvent m_OnDeathByPlayer; -}; - -BEGIN_DATADESC( CAntlionGrub ) - - DEFINE_FIELD( m_hGlowSprite, FIELD_EHANDLE ), - DEFINE_FIELD( m_flFlinchTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextIdleSoundTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextSquealSoundTime, FIELD_TIME ), - DEFINE_FIELD( m_State, FIELD_INTEGER ), - - DEFINE_INPUTFUNC( FIELD_FLOAT, "Agitate", InputAgitate ), - - DEFINE_OUTPUT( m_OnAgitated, "OnAgitated" ), - DEFINE_OUTPUT( m_OnDeath, "OnDeath" ), - DEFINE_OUTPUT( m_OnDeathByPlayer, "OnDeathByPlayer" ), - - // Functions - DEFINE_ENTITYFUNC( GrubTouch ), - DEFINE_ENTITYFUNC( IdleThink ), - DEFINE_ENTITYFUNC( FlinchThink ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Squash", InputSquash ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( npc_antlion_grub, CAntlionGrub ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAntlionGrub::CreateGlow( void ) -{ - // Create the glow sprite - m_hGlowSprite = CSprite::SpriteCreate( "sprites/grubflare1.vmt", GetLocalOrigin(), false ); - Assert( m_hGlowSprite ); - if ( m_hGlowSprite == NULL ) - return; - - m_hGlowSprite->TurnOn(); - m_hGlowSprite->SetTransparency( kRenderWorldGlow, 156, 169, 121, 164, kRenderFxNoDissipation ); - m_hGlowSprite->SetScale( 0.5f ); - m_hGlowSprite->SetGlowProxySize( 16.0f ); - int nAttachment = LookupAttachment( "glow" ); - m_hGlowSprite->SetParent( this, nAttachment ); - m_hGlowSprite->SetLocalOrigin( vec3_origin ); - - // Don't uselessly animate, we're a static sprite! - m_hGlowSprite->SetThink( NULL ); - m_hGlowSprite->SetNextThink( TICK_NEVER_THINK ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAntlionGrub::FadeGlow( void ) -{ - if ( m_hGlowSprite ) - { - m_hGlowSprite->FadeAndDie( 0.25f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAntlionGrub::UpdateOnRemove( void ) -{ - FadeGlow(); - - BaseClass::UpdateOnRemove(); -} - -//----------------------------------------------------------------------------- -// Purpose: Find what size of nugget to spawn -//----------------------------------------------------------------------------- -int CAntlionGrub::GetNuggetDenomination( void ) -{ - // Find the desired health perc we want to be at - float flDesiredHealthPerc = DynamicResupply_GetDesiredHealthPercentage(); - - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer == NULL ) - return -1; - - // Get the player's current health percentage - float flPlayerHealthPerc = (float) pPlayer->GetHealth() / (float) pPlayer->GetMaxHealth(); - - // If we're already maxed out, return the small nugget - if ( flPlayerHealthPerc >= flDesiredHealthPerc ) - { - return NUGGET_SMALL; - } - - // Find where we fall in the desired health's range - float flPercDelta = flPlayerHealthPerc / flDesiredHealthPerc; - - // The larger to discrepancy, the higher the chance to move quickly to close it - float flSeed = random->RandomFloat( 0.0f, 1.0f ); - float flRandomPerc = Bias( flSeed, (1.0f-flPercDelta) ); - - int nDenomination; - if ( flRandomPerc < 0.25f ) - { - nDenomination = NUGGET_SMALL; - } - else if ( flRandomPerc < 0.625f ) - { - nDenomination = NUGGET_MEDIUM; - } - else - { - nDenomination = NUGGET_LARGE; - } - - // Msg("Player: %.02f, Desired: %.02f, Seed: %.02f, Perc: %.02f, Result: %d\n", flPlayerHealthPerc, flDesiredHealthPerc, flSeed, flRandomPerc, nDenomination ); - - return nDenomination; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAntlionGrub::CreateNugget( void ) -{ - CGrubNugget *pNugget = (CGrubNugget *) CreateEntityByName( "item_grubnugget" ); - if ( pNugget == NULL ) - return; - - Vector vecOrigin; - Vector vecForward; - GetAttachment( LookupAttachment( "glow" ), vecOrigin, &vecForward ); - - // Find out what size to make this nugget! - int nDenomination = GetNuggetDenomination(); - pNugget->SetDenomination( nDenomination ); - - pNugget->SetAbsOrigin( vecOrigin ); - pNugget->SetAbsAngles( RandomAngle( 0, 360 ) ); - DispatchSpawn( pNugget ); - - IPhysicsObject *pPhys = pNugget->VPhysicsGetObject(); - if ( pPhys ) - { - Vector vecForward; - GetVectors( &vecForward, NULL, NULL ); - - Vector vecVelocity = RandomVector( -35.0f, 35.0f ) + ( vecForward * -RandomFloat( 50.0f, 75.0f ) ); - AngularImpulse vecAngImpulse = RandomAngularImpulse( -100.0f, 100.0f ); - - pPhys->AddVelocity( &vecVelocity, &vecAngImpulse ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -//----------------------------------------------------------------------------- -void CAntlionGrub::Event_Killed( const CTakeDamageInfo &info ) -{ - // Fire our output only if the player is the one that killed us - if ( info.GetAttacker() && info.GetAttacker()->IsPlayer() ) - { - m_OnDeathByPlayer.FireOutput( info.GetAttacker(), info.GetAttacker() ); - } - - m_OnDeath.FireOutput( info.GetAttacker(), info.GetAttacker() ); - SendOnKilledGameEvent( info ); - - // Crush and crowbar damage hurt us more than others - bool bSquashed = ( info.GetDamageType() & (DMG_CRUSH|DMG_CLUB)) ? true : false; - Squash( info.GetAttacker(), false, bSquashed ); - - m_takedamage = DAMAGE_NO; - - if ( sk_grubnugget_enabled.GetBool() ) - { - CreateNugget(); - } - - // Go away - SetThink( &CBaseEntity::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - // we deliberately do not call BaseClass::EventKilled -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -//----------------------------------------------------------------------------- -int CAntlionGrub::OnTakeDamage( const CTakeDamageInfo &info ) -{ - // Animate a flinch of pain if we're dying - bool bSquashed = ( ( GetEffects() & EF_NODRAW ) != 0 ); - if ( bSquashed == false ) - { - SetSequence( SelectWeightedSequence( ACT_SMALL_FLINCH ) ); - m_flFlinchTime = gpGlobals->curtime + random->RandomFloat( 0.5f, 1.0f ); - - SetThink( &CAntlionGrub::FlinchThink ); - SetNextThink( gpGlobals->curtime + 0.05f ); - } - - return BaseClass::OnTakeDamage( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: Whether or not we're in the PVS -//----------------------------------------------------------------------------- -inline bool CAntlionGrub::InPVS( void ) -{ - return ( UTIL_FindClientInPVS( edict() ) != NULL ) || (UTIL_ClientPVSIsExpanded() && UTIL_FindClientInVisibilityPVS( edict() )); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAntlionGrub::SetNextThinkByDistance( void ) -{ - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer == NULL ) - { - SetNextThink( gpGlobals->curtime + random->RandomFloat( 0.5f, 3.0f ) ); - return; - } - - float flDistToPlayerSqr = ( GetAbsOrigin() - pPlayer->GetAbsOrigin() ).LengthSqr(); - float scale = RemapValClamped( flDistToPlayerSqr, Square( 400 ), Square( 5000 ), 1.0f, 5.0f ); - float time = random->RandomFloat( 1.0f, 3.0f ); - SetNextThink( gpGlobals->curtime + ( time * scale ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAntlionGrub::Spawn( void ) -{ - Precache(); - BaseClass::Spawn(); - - SetModel( ANTLIONGRUB_MODEL ); - - // FIXME: This is a big perf hit with the number of grubs we're using! - jdw - CreateGlow(); - - SetSolid( SOLID_BBOX ); - SetSolidFlags( FSOLID_TRIGGER ); - SetMoveType( MOVETYPE_NONE ); - SetCollisionGroup( COLLISION_GROUP_NONE ); - AddEffects( EF_NOSHADOW ); - - CollisionProp()->UseTriggerBounds(true,1); - - SetTouch( &CAntlionGrub::GrubTouch ); - - SetHealth( 1 ); - m_takedamage = DAMAGE_YES; - - // Stick to the nearest surface - if ( HasSpawnFlags( SF_ANTLIONGRUB_NO_AUTO_PLACEMENT ) == false ) - { - AttachToSurface(); - } - - // At this point, alter our bounds to make sure we're within them - Vector vecMins, vecMaxs; - RotateAABB( EntityToWorldTransform(), CollisionProp()->OBBMins(), CollisionProp()->OBBMaxs(), vecMins, vecMaxs ); - - UTIL_SetSize( this, vecMins, vecMaxs ); - - // Start our idle activity - SetSequence( SelectWeightedSequence( ACT_IDLE ) ); - SetCycle( random->RandomFloat( 0.0f, 1.0f ) ); - ResetSequenceInfo(); - - m_State = GRUB_STATE_IDLE; - - // Reset - m_flFlinchTime = 0.0f; - m_flNextIdleSoundTime = gpGlobals->curtime + random->RandomFloat( 4.0f, 8.0f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAntlionGrub::Activate( void ) -{ - BaseClass::Activate(); - - // Idly think - SetThink( &CAntlionGrub::IdleThink ); - SetNextThinkByDistance(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &vecTestPos - -// *vecResult - -// *flDist - -// Output : inline bool -//----------------------------------------------------------------------------- -inline bool CAntlionGrub::ProbeSurface( const Vector &vecTestPos, const Vector &vecDir, Vector *vecResult, Vector *vecNormal ) -{ - // Trace down to find a surface - trace_t tr; - UTIL_TraceLine( vecTestPos, vecTestPos + (vecDir*256.0f), MASK_NPCSOLID&(~CONTENTS_MONSTER), this, COLLISION_GROUP_NONE, &tr ); - - if ( vecResult ) - { - *vecResult = tr.endpos; - } - - if ( vecNormal ) - { - *vecNormal = tr.plane.normal; - } - - return ( tr.fraction < 1.0f ); -} - -//----------------------------------------------------------------------------- -// Purpose: Attaches the grub to the surface underneath its abdomen -//----------------------------------------------------------------------------- -void CAntlionGrub::AttachToSurface( void ) -{ - // Get our downward direction - Vector vecForward, vecRight, vecDown; - GetVectors( &vecForward, &vecRight, &vecDown ); - vecDown.Negate(); - - Vector vecOffset = ( vecDown * -8.0f ); - - // Middle - Vector vecMid, vecMidNormal; - if ( ProbeSurface( WorldSpaceCenter() + vecOffset, vecDown, &vecMid, &vecMidNormal ) == false ) - { - // A grub was left hanging in the air, it must not be near any valid surfaces! - Warning("Antlion grub stranded in space at (%.02f, %.02f, %.02f) : REMOVED\n", GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z ); - UTIL_Remove( this ); - return; - } - - // Sit at the mid-point - UTIL_SetOrigin( this, vecMid ); - - Vector vecPivot; - Vector vecPivotNormal; - - bool bNegate = true; - - // First test our tail (more crucial that it doesn't interpenetrate with the world) - if ( ProbeSurface( WorldSpaceCenter() - ( vecForward * 12.0f ) + vecOffset, vecDown, &vecPivot, &vecPivotNormal ) == false ) - { - // If that didn't find a surface, try the head - if ( ProbeSurface( WorldSpaceCenter() + ( vecForward * 12.0f ) + vecOffset, vecDown, &vecPivot, &vecPivotNormal ) == false ) - { - // Worst case, just site at the middle - UTIL_SetOrigin( this, vecMid ); - - QAngle vecAngles; - VectorAngles( vecForward, vecMidNormal, vecAngles ); - SetAbsAngles( vecAngles ); - return; - } - - bNegate = false; - } - - // Find the line we'll lay on if these two points are connected by a line - Vector vecLieDir = ( vecPivot - vecMid ); - VectorNormalize( vecLieDir ); - if ( bNegate ) - { - // We need to try and maintain our facing - vecLieDir.Negate(); - } - - // Use the average of the surface normals to be our "up" direction - Vector vecPseudoUp = ( vecMidNormal + vecPivotNormal ) * 0.5f; - - QAngle vecAngles; - VectorAngles( vecLieDir, vecPseudoUp, vecAngles ); - - SetAbsAngles( vecAngles ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAntlionGrub::MakeIdleSounds( void ) -{ - if ( m_State == GRUB_STATE_AGITATED ) - { - if ( m_flNextSquealSoundTime < gpGlobals->curtime ) - { - EmitSound( "NPC_Antlion_Grub.Stimulated" ); - m_flNextSquealSoundTime = gpGlobals->curtime + random->RandomFloat( 1.5f, 3.0f ); - m_flNextIdleSoundTime = gpGlobals->curtime + random->RandomFloat( 4.0f, 8.0f ); - } - } - else - { - if ( m_flNextIdleSoundTime < gpGlobals->curtime ) - { - EmitSound( "NPC_Antlion_Grub.Idle" ); - m_flNextIdleSoundTime = gpGlobals->curtime + random->RandomFloat( 8.0f, 12.0f ); - } - } -} - -#define DEBUG_GRUB_THINK_TIMES 0 - -#if DEBUG_GRUB_THINK_TIMES - int nFrame = 0; - int nNumThinks = 0; -#endif // DEBUG_GRUB_THINK_TIMES - -//----------------------------------------------------------------------------- -// Purpose: Advance our thinks -//----------------------------------------------------------------------------- -void CAntlionGrub::IdleThink( void ) -{ -#if DEBUG_GRUB_THINK_TIMES - // Test for a new frame - if ( gpGlobals->framecount != nFrame ) - { - if ( nNumThinks > 10 ) - { - Msg("%d npc_antlion_grubs thinking per frame!\n", nNumThinks ); - } - - nFrame = gpGlobals->framecount; - nNumThinks = 0; - } - - nNumThinks++; -#endif // DEBUG_GRUB_THINK_TIMES - - // Check the PVS status - if ( InPVS() == false ) - { - // Push out into the future until they're in our PVS - SetNextThinkByDistance(); - m_bOutsidePVS = true; - return; - } - - // Stagger our sounds if we've just re-entered the PVS - if ( m_bOutsidePVS ) - { - m_flNextIdleSoundTime = gpGlobals->curtime + random->RandomFloat( 1.0f, 4.0f ); - m_bOutsidePVS = false; - } - - // See how close the player is - CBasePlayer *pPlayerEnt = AI_GetSinglePlayer(); - float flDistToPlayerSqr = ( GetAbsOrigin() - pPlayerEnt->GetAbsOrigin() ).LengthSqr(); - - bool bFlinching = ( m_flFlinchTime > gpGlobals->curtime ); - - // If they're far enough away, just wait to think again - if ( flDistToPlayerSqr > Square( 40*12 ) && bFlinching == false ) - { - SetNextThinkByDistance(); - return; - } - - // At this range, the player agitates us with his presence - bool bPlayerWithinAgitationRange = ( flDistToPlayerSqr <= Square( (6*12) ) ); - bool bAgitated = (bPlayerWithinAgitationRange || bFlinching ); - - // If we're idle and the player has come close enough, get agry - if ( ( m_State == GRUB_STATE_IDLE ) && bAgitated ) - { - SetSequence( SelectWeightedSequence( ACT_SMALL_FLINCH ) ); - m_State = GRUB_STATE_AGITATED; - } - else if ( IsSequenceFinished() ) - { - // See if it's time to choose a new sequence - ResetSequenceInfo(); - SetCycle( 0.0f ); - - // If we're near enough, we want to play an "alert" animation - if ( bAgitated ) - { - SetSequence( SelectWeightedSequence( ACT_SMALL_FLINCH ) ); - m_State = GRUB_STATE_AGITATED; - } - else - { - // Just idle - SetSequence( SelectWeightedSequence( ACT_IDLE ) ); - m_State = GRUB_STATE_IDLE; - } - - // Add some variation because we're often in large bunches - SetPlaybackRate( random->RandomFloat( 0.8f, 1.2f ) ); - } - - // Idle normally - StudioFrameAdvance(); - MakeIdleSounds(); - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAntlionGrub::FlinchThink( void ) -{ - StudioFrameAdvance(); - SetNextThink( gpGlobals->curtime + 0.1f ); - - // See if we're done - if ( m_flFlinchTime < gpGlobals->curtime ) - { - SetSequence( SelectWeightedSequence( ACT_IDLE ) ); - SetThink( &CAntlionGrub::IdleThink ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAntlionGrub::GrubTouch( CBaseEntity *pOther ) -{ - // We can be squished by the player, Vort, or flying heavy things. - IPhysicsObject *pPhysOther = pOther->VPhysicsGetObject(); // bool bThrown = ( pTarget->VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_WAS_THROWN ) != 0; - if ( pOther->IsPlayer() || FClassnameIs(pOther,"npc_vortigaunt") || ( pPhysOther && (pPhysOther->GetGameFlags() & FVPHYSICS_WAS_THROWN )) ) - { - m_OnAgitated.FireOutput( pOther, pOther ); - Squash( pOther, true, true ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAntlionGrub::Precache( void ) -{ - PrecacheModel( ANTLIONGRUB_MODEL ); - PrecacheModel( ANTLIONGRUB_SQUASHED_MODEL ); - - m_nGlowSpriteHandle = PrecacheModel("sprites/grubflare1.vmt"); - - PrecacheScriptSound( "NPC_Antlion_Grub.Idle" ); - PrecacheScriptSound( "NPC_Antlion_Grub.Alert" ); - PrecacheScriptSound( "NPC_Antlion_Grub.Stimulated" ); - PrecacheScriptSound( "NPC_Antlion_Grub.Die" ); - PrecacheScriptSound( "NPC_Antlion_Grub.Squish" ); - - PrecacheParticleSystem( "GrubSquashBlood" ); - PrecacheParticleSystem( "GrubBlood" ); - - UTIL_PrecacheOther( "item_grubnugget" ); - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: Squish the grub! -//----------------------------------------------------------------------------- -void CAntlionGrub::InputSquash( inputdata_t &data ) -{ - Squash( data.pActivator, true, true ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAntlionGrub::SpawnSquashedGrub( void ) -{ - // If we're already invisible, we're done - if ( GetEffects() & EF_NODRAW ) - return; - - Vector vecUp; - GetVectors( NULL, NULL, &vecUp ); - CBaseEntity *pGib = CreateRagGib( ANTLIONGRUB_SQUASHED_MODEL, GetAbsOrigin(), GetAbsAngles(), vecUp * 16.0f ); - if ( pGib ) - { - pGib->AddEffects( EF_NOSHADOW ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAntlionGrub::MakeSquashDecals( const Vector &vecOrigin ) -{ - trace_t tr; - Vector vecStart; - Vector vecTraceDir; - - GetVectors( NULL, NULL, &vecTraceDir ); - vecTraceDir.Negate(); - - for ( int i = 0 ; i < 8; i++ ) - { - vecStart.x = vecOrigin.x + random->RandomFloat( -16.0f, 16.0f ); - vecStart.y = vecOrigin.y + random->RandomFloat( -16.0f, 16.0f ); - vecStart.z = vecOrigin.z + 4; - - UTIL_TraceLine( vecStart, vecStart + ( vecTraceDir * (5*12) ), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction != 1.0 ) - { - UTIL_BloodDecalTrace( &tr, BLOOD_COLOR_YELLOW ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAntlionGrub::Squash( CBaseEntity *pOther, bool bDealDamage, bool bSpawnBlood ) -{ - // If we're already squashed, then don't bother doing it again! - if ( GetEffects() & EF_NODRAW ) - return; - - SpawnSquashedGrub(); - - AddEffects( EF_NODRAW ); - AddSolidFlags( FSOLID_NOT_SOLID ); - - // Stop being attached to us - if ( m_hGlowSprite ) - { - FadeGlow(); - m_hGlowSprite->SetParent( NULL ); - } - - EmitSound( "NPC_Antlion_Grub.Die" ); - EmitSound( "NPC_Antlion_Grub.Squish" ); - - // if vort stepped on me, maybe he wants to say something - if ( pOther && FClassnameIs( pOther, "npc_vortigaunt" ) ) - { - Assert(dynamic_cast(pOther)); - static_cast(pOther)->OnSquishedGrub(this); - } - - SetTouch( NULL ); - - //if ( bSpawnBlood ) - { - // Temp squash effect - Vector vecForward, vecUp; - AngleVectors( GetAbsAngles(), &vecForward, NULL, &vecUp ); - - // Start effects at either end of the grub - Vector vecSplortPos = GetAbsOrigin() + vecForward * 14.0f; - DispatchParticleEffect( "GrubSquashBlood", vecSplortPos, GetAbsAngles() ); - - vecSplortPos = GetAbsOrigin() - vecForward * 16.0f; - Vector vecDir = -vecForward; - QAngle vecAngles; - VectorAngles( vecDir, vecAngles ); - DispatchParticleEffect( "GrubSquashBlood", vecSplortPos, vecAngles ); - - MakeSquashDecals( GetAbsOrigin() + vecForward * 32.0f ); - MakeSquashDecals( GetAbsOrigin() - vecForward * 32.0f ); - } - - // Deal deadly damage to ourself - if ( bDealDamage ) - { - CTakeDamageInfo info( pOther, pOther, Vector( 0, 0, -1 ), GetAbsOrigin(), GetHealth()+1, DMG_CRUSH ); - TakeDamage( info ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -// &vecDir - -// *ptr - -//----------------------------------------------------------------------------- -void CAntlionGrub::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - QAngle vecAngles; - VectorAngles( -vecDir, vecAngles ); - DispatchParticleEffect( "GrubBlood", ptr->endpos, vecAngles ); - - BaseClass::TraceAttack( info, vecDir, ptr ); -} - -//----------------------------------------------------------------------------- -// Purpose: Make the grub angry! -//----------------------------------------------------------------------------- -void CAntlionGrub::InputAgitate( inputdata_t &inputdata ) -{ - SetSequence( SelectWeightedSequence( ACT_SMALL_FLINCH ) ); - m_State = GRUB_STATE_AGITATED; - m_flNextSquealSoundTime = gpGlobals->curtime; - - m_flFlinchTime = gpGlobals->curtime + inputdata.value.Float(); - - SetNextThink( gpGlobals->curtime ); -} - -// ===================================================================== -// -// Tasty grub nugget! -// -// ===================================================================== - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGrubNugget::Spawn( void ) -{ - Precache(); - - if ( m_nDenomination == NUGGET_LARGE ) - { - SetModel( "models/grub_nugget_large.mdl" ); - } - else if ( m_nDenomination == NUGGET_MEDIUM ) - { - SetModel( "models/grub_nugget_medium.mdl" ); - } - else - { - SetModel( "models/grub_nugget_small.mdl" ); - } - - // We're self-illuminating, so we don't take or give shadows - AddEffects( EF_NOSHADOW|EF_NORECEIVESHADOW ); - - m_iHealth = 1; - - BaseClass::Spawn(); - - m_takedamage = DAMAGE_YES; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGrubNugget::Precache( void ) -{ - PrecacheModel("models/grub_nugget_small.mdl"); - PrecacheModel("models/grub_nugget_medium.mdl"); - PrecacheModel("models/grub_nugget_large.mdl"); - - PrecacheScriptSound( "GrubNugget.Touch" ); - PrecacheScriptSound( "NPC_Antlion_Grub.Explode" ); - - PrecacheParticleSystem( "antlion_spit_player" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Let us be picked up by the gravity gun, regardless of our material -//----------------------------------------------------------------------------- -bool CGrubNugget::VPhysicsIsFlesh( void ) -{ - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CGrubNugget::MyTouch( CBasePlayer *pPlayer ) -{ - //int nHealthToGive = sk_grubnugget_health.GetFloat() * m_nDenomination; - int nHealthToGive; - switch (m_nDenomination) - { - case NUGGET_SMALL: - nHealthToGive = sk_grubnugget_health_small.GetInt(); - break; - case NUGGET_LARGE: - nHealthToGive = sk_grubnugget_health_large.GetInt(); - break; - default: - nHealthToGive = sk_grubnugget_health_medium.GetInt(); - } - - // Attempt to give the player health - if ( pPlayer->TakeHealth( nHealthToGive, DMG_GENERIC ) == 0 ) - return false; - - CSingleUserRecipientFilter user( pPlayer ); - user.MakeReliable(); - - UserMessageBegin( user, "ItemPickup" ); - WRITE_STRING( GetClassname() ); - MessageEnd(); - - CPASAttenuationFilter filter( pPlayer, "GrubNugget.Touch" ); - EmitSound( filter, pPlayer->entindex(), "GrubNugget.Touch" ); - - UTIL_Remove( this ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -// *pEvent - -//----------------------------------------------------------------------------- -void CGrubNugget::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) -{ - int damageType; - float damage = CalculateDefaultPhysicsDamage( index, pEvent, 1.0f, true, damageType ); - if ( damage > 5.0f ) - { - CBaseEntity *pHitEntity = pEvent->pEntities[!index]; - if ( pHitEntity == NULL ) - { - // hit world - pHitEntity = GetContainingEntity( INDEXENT(0) ); - } - - Vector damagePos; - pEvent->pInternalData->GetContactPoint( damagePos ); - Vector damageForce = pEvent->postVelocity[index] * pEvent->pObjects[index]->GetMass(); - if ( damageForce == vec3_origin ) - { - // This can happen if this entity is motion disabled, and can't move. - // Use the velocity of the entity that hit us instead. - damageForce = pEvent->postVelocity[!index] * pEvent->pObjects[!index]->GetMass(); - } - - // FIXME: this doesn't pass in who is responsible if some other entity "caused" this collision - PhysCallbackDamage( this, CTakeDamageInfo( pHitEntity, pHitEntity, damageForce, damagePos, damage, damageType ), *pEvent, index ); - } - - BaseClass::VPhysicsCollision( index, pEvent ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -//----------------------------------------------------------------------------- -void CGrubNugget::Event_Killed( const CTakeDamageInfo &info ) -{ - AddEffects( EF_NODRAW ); - DispatchParticleEffect( "antlion_spit_player", GetAbsOrigin(), QAngle( -90, 0, 0 ) ); - EmitSound( "NPC_Antlion_Grub.Explode" ); - - BaseClass::Event_Killed( info ); -} diff --git a/game/server/hl2/npc_antliongrub.h b/game/server/hl2/npc_antliongrub.h deleted file mode 100644 index f7c8727e9..000000000 --- a/game/server/hl2/npc_antliongrub.h +++ /dev/null @@ -1,13 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Antlion Grub - cannon fodder -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef NPC_ANTLIONGRUB_H -#define NPC_ANTLIONGRUB_H - -#endif //NPC_ANTLIONGRUB_H diff --git a/game/server/hl2/npc_antlionguard.cpp b/game/server/hl2/npc_antlionguard.cpp deleted file mode 100644 index fb9647b5f..000000000 --- a/game/server/hl2/npc_antlionguard.cpp +++ /dev/null @@ -1,5048 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Antlion Guard -// -//=============================================================================// - -#include "cbase.h" -#include "ai_hint.h" -#include "ai_localnavigator.h" -#include "ai_memory.h" -#include "ai_moveprobe.h" -#include "npcevent.h" -#include "IEffects.h" -#include "ndebugoverlay.h" -#include "soundent.h" -#include "soundenvelope.h" -#include "ai_squad.h" -#include "ai_network.h" -#include "ai_pathfinder.h" -#include "ai_navigator.h" -#include "ai_senses.h" -#include "npc_rollermine.h" -#include "ai_blended_movement.h" -#include "physics_prop_ragdoll.h" -#include "iservervehicle.h" -#include "player_pickup.h" -#include "props.h" -#include "antlion_dust.h" -#include "npc_antlion.h" -#include "decals.h" -#include "prop_combine_ball.h" -#include "eventqueue.h" -#include "te_effect_dispatch.h" -#include "Sprite.h" -#include "particle_parse.h" -#include "particle_system.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -inline void TraceHull_SkipPhysics( const Vector &vecAbsStart, const Vector &vecAbsEnd, const Vector &hullMin, - const Vector &hullMax, unsigned int mask, const CBaseEntity *ignore, - int collisionGroup, trace_t *ptr, float minMass ); - -ConVar g_debug_antlionguard( "g_debug_antlionguard", "0" ); -ConVar sk_antlionguard_dmg_charge( "sk_antlionguard_dmg_charge", "0" ); -ConVar sk_antlionguard_dmg_shove( "sk_antlionguard_dmg_shove", "0" ); - -#if HL2_EPISODIC -// When enabled, add code to have the antlion bleed profusely as it is badly injured. -#define ANTLIONGUARD_BLOOD_EFFECTS 2 -ConVar g_antlionguard_hemorrhage( "g_antlionguard_hemorrhage", "1", FCVAR_NONE, "If 1, guard will emit a bleeding particle effect when wounded." ); -#endif - -// Spawnflags -#define SF_ANTLIONGUARD_SERVERSIDE_RAGDOLL ( 1 << 16 ) -#define SF_ANTLIONGUARD_INSIDE_FOOTSTEPS ( 1 << 17 ) - -#define ENVELOPE_CONTROLLER (CSoundEnvelopeController::GetController()) -#define ANTLIONGUARD_MODEL "models/antlion_guard.mdl" -#define MIN_BLAST_DAMAGE 25.0f -#define MIN_CRUSH_DAMAGE 20.0f - -//================================================== -// -// Antlion Guard -// -//================================================== - -#define ANTLIONGUARD_MAX_OBJECTS 128 -#define ANTLIONGUARD_MIN_OBJECT_MASS 8 -#define ANTLIONGUARD_MAX_OBJECT_MASS 750 -#define ANTLIONGUARD_FARTHEST_PHYSICS_OBJECT 350 -#define ANTLIONGUARD_OBJECTFINDING_FOV DOT_45DEGREE // 1/sqrt(2) - -//Melee definitions -#define ANTLIONGUARD_MELEE1_RANGE 156.0f -#define ANTLIONGUARD_MELEE1_CONE 0.7f - -// Antlion summoning -#define ANTLIONGUARD_SUMMON_COUNT 3 - -// Sight -#define ANTLIONGUARD_FOV_NORMAL -0.4f - -// cavern guard's poisoning behavior -#if HL2_EPISODIC -#define ANTLIONGUARD_POISON_TO 12 // we only poison Gordon down to twelve to give him a chance to regen up to 20 by the next charge -#endif - -#define ANTLIONGUARD_CHARGE_MIN 256 -#define ANTLIONGUARD_CHARGE_MAX 2048 - -ConVar sk_antlionguard_health( "sk_antlionguard_health", "0" ); - -int g_interactionAntlionGuardFoundPhysicsObject = 0; // We're moving to a physics object to shove it, don't all choose the same object -int g_interactionAntlionGuardShovedPhysicsObject = 0; // We've punted an object, it is now clear to be chosen by others - -//================================================== -// AntlionGuardSchedules -//================================================== - -enum -{ - SCHED_ANTLIONGUARD_CHARGE = LAST_SHARED_SCHEDULE, - SCHED_ANTLIONGUARD_CHARGE_CRASH, - SCHED_ANTLIONGUARD_CHARGE_CANCEL, - SCHED_ANTLIONGUARD_PHYSICS_ATTACK, - SCHED_ANTLIONGUARD_PHYSICS_DAMAGE_HEAVY, - SCHED_ANTLIONGUARD_UNBURROW, - SCHED_ANTLIONGUARD_CHARGE_TARGET, - SCHED_ANTLIONGUARD_FIND_CHARGE_POSITION, - SCHED_ANTLIONGUARD_MELEE_ATTACK1, - SCHED_ANTLIONGUARD_SUMMON, - SCHED_ANTLIONGUARD_PATROL_RUN, - SCHED_ANTLIONGUARD_ROAR, - SCHED_ANTLIONGUARD_CHASE_ENEMY_TOLERANCE, - SCHED_FORCE_ANTLIONGUARD_PHYSICS_ATTACK, - SCHED_ANTLIONGUARD_CANT_ATTACK, - SCHED_ANTLIONGUARD_TAKE_COVER_FROM_ENEMY, - SCHED_ANTLIONGUARD_CHASE_ENEMY -}; - - -//================================================== -// AntlionGuardTasks -//================================================== - -enum -{ - TASK_ANTLIONGUARD_CHARGE = LAST_SHARED_TASK, - TASK_ANTLIONGUARD_GET_PATH_TO_PHYSOBJECT, - TASK_ANTLIONGUARD_SHOVE_PHYSOBJECT, - TASK_ANTLIONGUARD_SUMMON, - TASK_ANTLIONGUARD_SET_FLINCH_ACTIVITY, - TASK_ANTLIONGUARD_GET_PATH_TO_CHARGE_POSITION, - TASK_ANTLIONGUARD_GET_PATH_TO_NEAREST_NODE, - TASK_ANTLIONGUARD_GET_CHASE_PATH_ENEMY_TOLERANCE, - TASK_ANTLIONGUARD_OPPORTUNITY_THROW, - TASK_ANTLIONGUARD_FIND_PHYSOBJECT, -}; - -//================================================== -// AntlionGuardConditions -//================================================== - -enum -{ - COND_ANTLIONGUARD_PHYSICS_TARGET = LAST_SHARED_CONDITION, - COND_ANTLIONGUARD_PHYSICS_TARGET_INVALID, - COND_ANTLIONGUARD_HAS_CHARGE_TARGET, - COND_ANTLIONGUARD_CAN_SUMMON, - COND_ANTLIONGUARD_CAN_CHARGE -}; - -enum -{ - SQUAD_SLOT_ANTLIONGUARD_CHARGE = LAST_SHARED_SQUADSLOT, -}; - -//================================================== -// AntlionGuard Activities -//================================================== - -Activity ACT_ANTLIONGUARD_SEARCH; -Activity ACT_ANTLIONGUARD_PEEK_FLINCH; -Activity ACT_ANTLIONGUARD_PEEK_ENTER; -Activity ACT_ANTLIONGUARD_PEEK_EXIT; -Activity ACT_ANTLIONGUARD_PEEK1; -Activity ACT_ANTLIONGUARD_BARK; -Activity ACT_ANTLIONGUARD_PEEK_SIGHTED; -Activity ACT_ANTLIONGUARD_SHOVE_PHYSOBJECT; -Activity ACT_ANTLIONGUARD_FLINCH_LIGHT; -Activity ACT_ANTLIONGUARD_UNBURROW; -Activity ACT_ANTLIONGUARD_ROAR; -Activity ACT_ANTLIONGUARD_RUN_HURT; - -// Flinches -Activity ACT_ANTLIONGUARD_PHYSHIT_FR; -Activity ACT_ANTLIONGUARD_PHYSHIT_FL; -Activity ACT_ANTLIONGUARD_PHYSHIT_RR; -Activity ACT_ANTLIONGUARD_PHYSHIT_RL; - -// Charge -Activity ACT_ANTLIONGUARD_CHARGE_START; -Activity ACT_ANTLIONGUARD_CHARGE_CANCEL; -Activity ACT_ANTLIONGUARD_CHARGE_RUN; -Activity ACT_ANTLIONGUARD_CHARGE_CRASH; -Activity ACT_ANTLIONGUARD_CHARGE_STOP; -Activity ACT_ANTLIONGUARD_CHARGE_HIT; -Activity ACT_ANTLIONGUARD_CHARGE_ANTICIPATION; - -// Anim events -int AE_ANTLIONGUARD_CHARGE_HIT; -int AE_ANTLIONGUARD_SHOVE_PHYSOBJECT; -int AE_ANTLIONGUARD_SHOVE; -int AE_ANTLIONGUARD_FOOTSTEP_LIGHT; -int AE_ANTLIONGUARD_FOOTSTEP_HEAVY; -int AE_ANTLIONGUARD_CHARGE_EARLYOUT; -int AE_ANTLIONGUARD_VOICE_GROWL; -int AE_ANTLIONGUARD_VOICE_BARK; -int AE_ANTLIONGUARD_VOICE_PAIN; -int AE_ANTLIONGUARD_VOICE_SQUEEZE; -int AE_ANTLIONGUARD_VOICE_SCRATCH; -int AE_ANTLIONGUARD_VOICE_GRUNT; -int AE_ANTLIONGUARD_VOICE_ROAR; -int AE_ANTLIONGUARD_BURROW_OUT; - -struct PhysicsObjectCriteria_t -{ - CBaseEntity *pTarget; - Vector vecCenter; // Center point to look around - float flRadius; // Radius to search within - float flTargetCone; - bool bPreferObjectsAlongTargetVector; // Prefer objects that we can strike easily as we move towards our target - float flNearRadius; // If we won't hit the player with the object, but get this close, throw anyway -}; - -#define MAX_FAILED_PHYSOBJECTS 8 - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CNPC_AntlionGuard : public CAI_BlendedNPC -{ -public: - DECLARE_CLASS( CNPC_AntlionGuard, CAI_BlendedNPC ); - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - CNPC_AntlionGuard( void ); - - Class_T Classify( void ) { return CLASS_ANTLION; } - virtual int GetSoundInterests( void ) { return (SOUND_WORLD|SOUND_COMBAT|SOUND_PLAYER|SOUND_DANGER); } - virtual bool QueryHearSound( CSound *pSound ); - - const impactdamagetable_t &GetPhysicsImpactDamageTable( void ); - - virtual int MeleeAttack1Conditions( float flDot, float flDist ); - virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ); - - virtual int TranslateSchedule( int scheduleType ); - virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - virtual void DeathSound( const CTakeDamageInfo &info ); - virtual void Event_Killed( const CTakeDamageInfo &info ); - virtual int SelectSchedule( void ); - - virtual float GetAutoAimRadius() { return 36.0f; } - - virtual void Precache( void ); - virtual void Spawn( void ); - virtual void Activate( void ); - virtual void HandleAnimEvent( animevent_t *pEvent ); - virtual void UpdateEfficiency( bool bInPVS ) { SetEfficiency( ( GetSleepState() != AISS_AWAKE ) ? AIE_DORMANT : AIE_NORMAL ); SetMoveEfficiency( AIME_NORMAL ); } - virtual void PrescheduleThink( void ); - virtual void GatherConditions( void ); - virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - virtual void StartTask( const Task_t *pTask ); - virtual void RunTask( const Task_t *pTask ); - virtual void StopLoopingSounds(); - virtual bool HandleInteraction( int interactionType, void *data, CBaseCombatCharacter *sender ); - - // Input handlers. - void InputSetShoveTarget( inputdata_t &inputdata ); - void InputSetChargeTarget( inputdata_t &inputdata ); - void InputClearChargeTarget( inputdata_t &inputdata ); - void InputUnburrow( inputdata_t &inputdata ); - void InputRagdoll( inputdata_t &inputdata ); - void InputEnableBark( inputdata_t &inputdata ); - void InputDisableBark( inputdata_t &inputdata ); - void InputSummonedAntlionDied( inputdata_t &inputdata ); - void InputEnablePreferPhysicsAttack( inputdata_t &inputdata ); - void InputDisablePreferPhysicsAttack( inputdata_t &inputdata ); - - virtual bool IsLightDamage( const CTakeDamageInfo &info ); - virtual bool IsHeavyDamage( const CTakeDamageInfo &info ); - virtual bool OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval ); - virtual bool BecomeRagdollOnClient( const Vector &force ); - virtual void UpdateOnRemove( void ); - virtual bool IsUnreachable( CBaseEntity* pEntity ); // Is entity is unreachable? - - virtual float MaxYawSpeed( void ); - virtual bool OverrideMove( float flInterval ); - virtual bool CanBecomeRagdoll( void ); - - virtual bool ShouldProbeCollideAgainstEntity( CBaseEntity *pEntity ); - - virtual Activity NPC_TranslateActivity( Activity baseAct ); - -#if HL2_EPISODIC - //--------------------------------- - // Navigation & Movement -- prevent stopping paths for the guard - //--------------------------------- - class CNavigator : public CAI_ComponentWithOuter - { - typedef CAI_ComponentWithOuter BaseClass; - public: - CNavigator( CNPC_AntlionGuard *pOuter ) - : BaseClass( pOuter ) - { - } - - bool GetStoppingPath( CAI_WaypointList *pClippedWaypoints ); - }; - CAI_Navigator * CreateNavigator() { return new CNavigator( this ); } -#endif - - DEFINE_CUSTOM_AI; - -private: - - inline bool CanStandAtPoint( const Vector &vecPos, Vector *pOut ); - bool RememberFailedPhysicsTarget( CBaseEntity *pTarget ); - void GetPhysicsShoveDir( CBaseEntity *pObject, float flMass, Vector *pOut ); - void CreateGlow( CSprite **pSprite, const char *pAttachName ); - void DestroyGlows( void ); - void Footstep( bool bHeavy ); - int SelectCombatSchedule( void ); - int SelectUnreachableSchedule( void ); - bool CanSummon( bool bIgnoreTime ); - void SummonAntlions( void ); - - void ChargeLookAhead( void ); - bool EnemyIsRightInFrontOfMe( CBaseEntity **pEntity ); - bool HandleChargeImpact( Vector vecImpact, CBaseEntity *pEntity ); - bool ShouldCharge( const Vector &startPos, const Vector &endPos, bool useTime, bool bCheckForCancel ); - bool ShouldWatchEnemy( void ); - - void ImpactShock( const Vector &origin, float radius, float magnitude, CBaseEntity *pIgnored = NULL ); - void BuildScheduleTestBits( void ); - void Shove( void ); - void FoundEnemy( void ); - void LostEnemy( void ); - void UpdateHead( void ); - void UpdatePhysicsTarget( bool bPreferObjectsAlongTargetVector, float flRadius = ANTLIONGUARD_FARTHEST_PHYSICS_OBJECT ); - void MaintainPhysicsTarget( void ); - void ChargeDamage( CBaseEntity *pTarget ); - void StartSounds( void ); - void SetHeavyDamageAnim( const Vector &vecSource ); - float ChargeSteer( void ); - CBaseEntity *FindPhysicsObjectTarget( const PhysicsObjectCriteria_t &criteria ); - Vector GetPhysicsHitPosition( CBaseEntity *pObject, CBaseEntity *pTarget, Vector *vecTrajectory, float *flClearDistance ); - bool CanStandAtShoveTarget( CBaseEntity *pShoveObject, CBaseEntity *pTarget, Vector *pOut ); - CBaseEntity *GetNextShoveTarget( CBaseEntity *pLastEntity, AISightIter_t &iter ); - - int m_nFlinchActivity; - - bool m_bStopped; - bool m_bIsBurrowed; - bool m_bBarkEnabled; - float m_flNextSummonTime; - int m_iNumLiveAntlions; - - float m_flSearchNoiseTime; - float m_flAngerNoiseTime; - float m_flBreathTime; - float m_flChargeTime; - float m_flPhysicsCheckTime; - float m_flNextHeavyFlinchTime; - float m_flNextRoarTime; - int m_iChargeMisses; - bool m_bDecidedNotToStop; - bool m_bPreferPhysicsAttack; - - CNetworkVar( bool, m_bCavernBreed ); // If this guard is meant to be a cavern dweller (uses different assets) - CNetworkVar( bool, m_bInCavern ); // Behavioral hint telling the guard to change his behavior - - Vector m_vecPhysicsTargetStartPos; - Vector m_vecPhysicsHitPosition; - - EHANDLE m_hShoveTarget; - EHANDLE m_hChargeTarget; - EHANDLE m_hChargeTargetPosition; - EHANDLE m_hOldTarget; - EHANDLE m_hPhysicsTarget; - - CUtlVectorFixed m_FailedPhysicsTargets; - - COutputEvent m_OnSummon; - - CSoundPatch *m_pGrowlHighSound; - CSoundPatch *m_pGrowlLowSound; - CSoundPatch *m_pGrowlIdleSound; - CSoundPatch *m_pBreathSound; - CSoundPatch *m_pConfusedSound; - - string_t m_iszPhysicsPropClass; - string_t m_strShoveTargets; - - CSprite *m_hCaveGlow[2]; - -#if ANTLIONGUARD_BLOOD_EFFECTS - CNetworkVar( uint8, m_iBleedingLevel ); - - unsigned char GetBleedingLevel( void ) const; -#endif -protected: - - int m_poseThrow; - int m_poseHead_Yaw, m_poseHead_Pitch; - virtual void PopulatePoseParameters( void ); - - -// inline accessors -public: - inline bool IsCavernBreed( void ) const { return m_bCavernBreed; } - inline bool IsInCavern( void ) const { return m_bInCavern; } -}; - -//================================================== -// CNPC_AntlionGuard::m_DataDesc -//================================================== - -BEGIN_DATADESC( CNPC_AntlionGuard ) - - DEFINE_FIELD( m_nFlinchActivity, FIELD_INTEGER ), - DEFINE_FIELD( m_bStopped, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_bIsBurrowed, FIELD_BOOLEAN, "startburrowed" ), - DEFINE_KEYFIELD( m_bBarkEnabled, FIELD_BOOLEAN, "allowbark" ), - DEFINE_FIELD( m_flNextSummonTime, FIELD_TIME ), - DEFINE_FIELD( m_iNumLiveAntlions, FIELD_INTEGER ), - - DEFINE_FIELD( m_flSearchNoiseTime, FIELD_TIME ), - DEFINE_FIELD( m_flAngerNoiseTime, FIELD_TIME ), - DEFINE_FIELD( m_flBreathTime, FIELD_TIME ), - DEFINE_FIELD( m_flChargeTime, FIELD_TIME ), - - DEFINE_FIELD( m_hShoveTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_hChargeTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_hChargeTargetPosition, FIELD_EHANDLE ), - DEFINE_FIELD( m_hOldTarget, FIELD_EHANDLE ), - // m_FailedPhysicsTargets // We do not save/load these - - DEFINE_FIELD( m_hPhysicsTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_vecPhysicsTargetStartPos, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecPhysicsHitPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_flPhysicsCheckTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextHeavyFlinchTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextRoarTime, FIELD_TIME ), - DEFINE_FIELD( m_iChargeMisses, FIELD_INTEGER ), - DEFINE_FIELD( m_bDecidedNotToStop, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bPreferPhysicsAttack, FIELD_BOOLEAN ), - -#if ANTLIONGUARD_BLOOD_EFFECTS - DEFINE_FIELD( m_iBleedingLevel, FIELD_CHARACTER ), -#endif - - DEFINE_KEYFIELD( m_bCavernBreed,FIELD_BOOLEAN, "cavernbreed" ), - DEFINE_KEYFIELD( m_bInCavern, FIELD_BOOLEAN, "incavern" ), - DEFINE_KEYFIELD( m_strShoveTargets, FIELD_STRING, "shovetargets" ), - - DEFINE_AUTO_ARRAY( m_hCaveGlow, FIELD_CLASSPTR ), - - DEFINE_OUTPUT( m_OnSummon, "OnSummon" ), - - DEFINE_SOUNDPATCH( m_pGrowlHighSound ), - DEFINE_SOUNDPATCH( m_pGrowlLowSound ), - DEFINE_SOUNDPATCH( m_pGrowlIdleSound ), - DEFINE_SOUNDPATCH( m_pBreathSound ), - DEFINE_SOUNDPATCH( m_pConfusedSound ), - - DEFINE_INPUTFUNC( FIELD_STRING, "SetShoveTarget", InputSetShoveTarget ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetChargeTarget", InputSetChargeTarget ), - DEFINE_INPUTFUNC( FIELD_VOID, "ClearChargeTarget", InputClearChargeTarget ), - DEFINE_INPUTFUNC( FIELD_VOID, "Unburrow", InputUnburrow ), - DEFINE_INPUTFUNC( FIELD_VOID, "Ragdoll", InputRagdoll ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableBark", InputEnableBark ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableBark", InputDisableBark ), - DEFINE_INPUTFUNC( FIELD_VOID, "SummonedAntlionDied", InputSummonedAntlionDied ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnablePreferPhysicsAttack", InputEnablePreferPhysicsAttack ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisablePreferPhysicsAttack", InputDisablePreferPhysicsAttack ), - -END_DATADESC() - - -//Fast Growl (Growl High) -envelopePoint_t envAntlionGuardFastGrowl[] = -{ - { 1.0f, 1.0f, - 0.2f, 0.4f, - }, - { 0.1f, 0.1f, - 0.8f, 1.0f, - }, - { 0.0f, 0.0f, - 0.4f, 0.8f, - }, -}; - - -//Bark 1 (Growl High) -envelopePoint_t envAntlionGuardBark1[] = -{ - { 1.0f, 1.0f, - 0.1f, 0.2f, - }, - { 0.0f, 0.0f, - 0.4f, 0.6f, - }, -}; - -//Bark 2 (Confused) -envelopePoint_t envAntlionGuardBark2[] = -{ - { 1.0f, 1.0f, - 0.1f, 0.2f, - }, - { 0.2f, 0.3f, - 0.1f, 0.2f, - }, - { 0.0f, 0.0f, - 0.4f, 0.6f, - }, -}; - -//Pain -envelopePoint_t envAntlionGuardPain1[] = -{ - { 1.0f, 1.0f, - 0.1f, 0.2f, - }, - { -1.0f, -1.0f, - 0.5f, 0.8f, - }, - { 0.1f, 0.2f, - 0.1f, 0.2f, - }, - { 0.0f, 0.0f, - 0.5f, 0.75f, - }, -}; - -//Squeeze (High Growl) -envelopePoint_t envAntlionGuardSqueeze[] = -{ - { 1.0f, 1.0f, - 0.1f, 0.2f, - }, - { 0.0f, 0.0f, - 1.0f, 1.5f, - }, -}; - -//Scratch (Low Growl) -envelopePoint_t envAntlionGuardScratch[] = -{ - { 1.0f, 1.0f, - 0.4f, 0.6f, - }, - { 0.5f, 0.5f, - 0.4f, 0.6f, - }, - { 0.0f, 0.0f, - 1.0f, 1.5f, - }, -}; - -//Grunt -envelopePoint_t envAntlionGuardGrunt[] = -{ - { 0.6f, 1.0f, - 0.1f, 0.2f, - }, - { 0.0f, 0.0f, - 0.1f, 0.2f, - }, -}; - -envelopePoint_t envAntlionGuardGrunt2[] = -{ - { 0.2f, 0.4f, - 0.1f, 0.2f, - }, - { 0.0f, 0.0f, - 0.4f, 0.6f, - }, -}; - -//============================================================================================== -// ANTLION GUARD PHYSICS DAMAGE TABLE -//============================================================================================== -static impactentry_t antlionGuardLinearTable[] = -{ - { 100*100, 10 }, - { 250*250, 25 }, - { 350*350, 50 }, - { 500*500, 75 }, - { 1000*1000,100 }, -}; - -static impactentry_t antlionGuardAngularTable[] = -{ - { 50* 50, 10 }, - { 100*100, 25 }, - { 150*150, 50 }, - { 200*200, 75 }, -}; - -impactdamagetable_t gAntlionGuardImpactDamageTable = -{ - antlionGuardLinearTable, - antlionGuardAngularTable, - - ARRAYSIZE(antlionGuardLinearTable), - ARRAYSIZE(antlionGuardAngularTable), - - 200*200,// minimum linear speed squared - 180*180,// minimum angular speed squared (360 deg/s to cause spin/slice damage) - 15, // can't take damage from anything under 15kg - - 10, // anything less than 10kg is "small" - 5, // never take more than 1 pt of damage from anything under 15kg - 128*128,// <15kg objects must go faster than 36 in/s to do damage - - 45, // large mass in kg - 2, // large mass scale (anything over 500kg does 4X as much energy to read from damage table) - 1, // large mass falling scale - 0, // my min velocity -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const impactdamagetable_t -//----------------------------------------------------------------------------- -const impactdamagetable_t &CNPC_AntlionGuard::GetPhysicsImpactDamageTable( void ) -{ - return gAntlionGuardImpactDamageTable; -} - -//================================================== -// CNPC_AntlionGuard -//================================================== - -CNPC_AntlionGuard::CNPC_AntlionGuard( void ) -{ - m_bCavernBreed = false; - m_bInCavern = false; - - m_iszPhysicsPropClass = AllocPooledString( "prop_physics" ); -} - -LINK_ENTITY_TO_CLASS( npc_antlionguard, CNPC_AntlionGuard ); - -IMPLEMENT_SERVERCLASS_ST(CNPC_AntlionGuard, DT_NPC_AntlionGuard) - SendPropBool( SENDINFO( m_bCavernBreed ) ), - SendPropBool( SENDINFO( m_bInCavern ) ), - -#if ANTLIONGUARD_BLOOD_EFFECTS - SendPropInt( SENDINFO( m_iBleedingLevel ), 2, SPROP_UNSIGNED ), -#endif -END_SEND_TABLE() - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::UpdateOnRemove( void ) -{ - DestroyGlows(); - - // Chain to the base class - BaseClass::UpdateOnRemove(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::Precache( void ) -{ - PrecacheModel( ANTLIONGUARD_MODEL ); - - PrecacheScriptSound( "NPC_AntlionGuard.Shove" ); - PrecacheScriptSound( "NPC_AntlionGuard.HitHard" ); - - if ( HasSpawnFlags(SF_ANTLIONGUARD_INSIDE_FOOTSTEPS) ) - { - PrecacheScriptSound( "NPC_AntlionGuard.Inside.StepLight" ); - PrecacheScriptSound( "NPC_AntlionGuard.Inside.StepHeavy" ); - } - else - { - PrecacheScriptSound( "NPC_AntlionGuard.StepLight" ); - PrecacheScriptSound( "NPC_AntlionGuard.StepHeavy" ); - } - -#if HL2_EPISODIC - PrecacheScriptSound( "NPC_AntlionGuard.NearStepLight" ); - PrecacheScriptSound( "NPC_AntlionGuard.NearStepHeavy" ); - PrecacheScriptSound( "NPC_AntlionGuard.FarStepLight" ); - PrecacheScriptSound( "NPC_AntlionGuard.FarStepHeavy" ); - PrecacheScriptSound( "NPC_AntlionGuard.BreatheLoop" ); - PrecacheScriptSound( "NPC_AntlionGuard.ShellCrack" ); - PrecacheScriptSound( "NPC_AntlionGuard.Pain_Roar" ); - PrecacheModel( "sprites/grubflare1.vmt" ); -#endif // HL2_EPISODIC - - PrecacheScriptSound( "NPC_AntlionGuard.Anger" ); - PrecacheScriptSound( "NPC_AntlionGuard.Roar" ); - PrecacheScriptSound( "NPC_AntlionGuard.Die" ); - - PrecacheScriptSound( "NPC_AntlionGuard.GrowlHigh" ); - PrecacheScriptSound( "NPC_AntlionGuard.GrowlIdle" ); - PrecacheScriptSound( "NPC_AntlionGuard.BreathSound" ); - PrecacheScriptSound( "NPC_AntlionGuard.Confused" ); - PrecacheScriptSound( "NPC_AntlionGuard.Fallover" ); - - PrecacheScriptSound( "NPC_AntlionGuard.FrustratedRoar" ); - - PrecacheParticleSystem( "blood_antlionguard_injured_light" ); - PrecacheParticleSystem( "blood_antlionguard_injured_heavy" ); - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::DestroyGlows( void ) -{ - if ( m_hCaveGlow[0] ) - { - UTIL_Remove( m_hCaveGlow[0] ); - - // reset it to NULL in case there is a double death cleanup for some reason. - m_hCaveGlow[0] = NULL; - } - - if ( m_hCaveGlow[1] ) - { - UTIL_Remove( m_hCaveGlow[1] ); - - // reset it to NULL in case there is a double death cleanup for some reason. - m_hCaveGlow[1] = NULL; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::CreateGlow( CSprite **pSprite, const char *pAttachName ) -{ - if ( pSprite == NULL ) - return; - - // Create the glow sprite - *pSprite = CSprite::SpriteCreate( "sprites/grubflare1.vmt", GetLocalOrigin(), false ); - Assert( *pSprite ); - if ( *pSprite == NULL ) - return; - - (*pSprite)->TurnOn(); - (*pSprite)->SetTransparency( kRenderWorldGlow, 156, 169, 121, 164, kRenderFxNoDissipation ); - (*pSprite)->SetScale( 1.0f ); - (*pSprite)->SetGlowProxySize( 16.0f ); - int nAttachment = LookupAttachment( pAttachName ); - (*pSprite)->SetParent( this, nAttachment ); - (*pSprite)->SetLocalOrigin( vec3_origin ); - - // Don't uselessly animate, we're a static sprite! - (*pSprite)->SetThink( NULL ); - (*pSprite)->SetNextThink( TICK_NEVER_THINK ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::Spawn( void ) -{ - Precache(); - - SetModel( ANTLIONGUARD_MODEL ); - - // Switch our skin (for now), if we're the cavern guard - if ( m_bCavernBreed ) - { - m_nSkin = 1; - - // Add glows - CreateGlow( &(m_hCaveGlow[0]), "attach_glow1" ); - CreateGlow( &(m_hCaveGlow[1]), "attach_glow2" ); - } - else - { - m_hCaveGlow[0] = NULL; - m_hCaveGlow[1] = NULL; - } - - SetHullType( HULL_LARGE ); - SetHullSizeNormal(); - SetDefaultEyeOffset(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - - SetNavType( NAV_GROUND ); - SetBloodColor( BLOOD_COLOR_YELLOW ); - - m_iHealth = sk_antlionguard_health.GetFloat(); - m_iMaxHealth = m_iHealth; - m_flFieldOfView = ANTLIONGUARD_FOV_NORMAL; - - m_flPhysicsCheckTime = 0; - m_flChargeTime = 0; - m_flNextRoarTime = 0; - m_flNextSummonTime = 0; - m_iNumLiveAntlions = 0; - m_iChargeMisses = 0; - m_flNextHeavyFlinchTime = 0; - m_bDecidedNotToStop = false; - - ClearHintGroup(); - - m_bStopped = false; - - m_hShoveTarget = NULL; - m_hChargeTarget = NULL; - m_hChargeTargetPosition = NULL; - m_hPhysicsTarget = NULL; - - m_HackedGunPos.x = 10; - m_HackedGunPos.y = 0; - m_HackedGunPos.z = 30; - - CapabilitiesClear(); - CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_INNATE_MELEE_ATTACK1 | bits_CAP_SQUAD ); - CapabilitiesAdd( bits_CAP_SKIP_NAV_GROUND_CHECK ); - - NPCInit(); - - BaseClass::Spawn(); - - //See if we're supposed to start burrowed - if ( m_bIsBurrowed ) - { - AddEffects( EF_NODRAW ); - AddFlag( FL_NOTARGET ); - - m_spawnflags |= SF_NPC_GAG; - - AddSolidFlags( FSOLID_NOT_SOLID ); - - m_takedamage = DAMAGE_NO; - - if ( m_hCaveGlow[0] ) - m_hCaveGlow[0]->TurnOff(); - - if ( m_hCaveGlow[1] ) - m_hCaveGlow[1]->TurnOff(); - } - - // Do not dissolve - AddEFlags( EFL_NO_DISSOLVE ); - - // We get a minute of free knowledge about the target - GetEnemies()->SetEnemyDiscardTime( 120.0f ); - GetEnemies()->SetFreeKnowledgeDuration( 60.0f ); - - // We need to bloat the absbox to encompass all the hitboxes - Vector absMin = -Vector(100,100,0); - Vector absMax = Vector(100,100,128); - - CollisionProp()->SetSurroundingBoundsType( USE_SPECIFIED_BOUNDS, &absMin, &absMax ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::Activate( void ) -{ - BaseClass::Activate(); - - // Find all nearby physics objects and add them to the list of objects we will sense - CBaseEntity *pObject = NULL; - while ( ( pObject = gEntList.FindEntityInSphere( pObject, WorldSpaceCenter(), 2500 ) ) != NULL ) - { - // Can't throw around debris - if ( pObject->GetCollisionGroup() == COLLISION_GROUP_DEBRIS ) - continue; - - // We can only throw a few types of things - if ( !FClassnameIs( pObject, "prop_physics" ) && !FClassnameIs( pObject, "func_physbox" ) ) - continue; - - // Ensure it's mass is within range - IPhysicsObject *pPhysObj = pObject->VPhysicsGetObject(); - if( ( pPhysObj == NULL ) || ( pPhysObj->GetMass() > ANTLIONGUARD_MAX_OBJECT_MASS ) || ( pPhysObj->GetMass() < ANTLIONGUARD_MIN_OBJECT_MASS ) ) - continue; - - // Tell the AI sensing list that we want to consider this - g_AI_SensedObjectsManager.AddEntity( pObject ); - - if ( g_debug_antlionguard.GetInt() == 5 ) - { - Msg("Antlion Guard: Added prop with model '%s' to sense list.\n", STRING(pObject->GetModelName()) ); - pObject->m_debugOverlays |= OVERLAY_BBOX_BIT; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if the guard's allowed to summon antlions -//----------------------------------------------------------------------------- -bool CNPC_AntlionGuard::CanSummon( bool bIgnoreTime ) -{ - if ( !m_bBarkEnabled ) - return false; - - if ( !bIgnoreTime && m_flNextSummonTime > gpGlobals->curtime ) - return false; - - // Hit the max number of them allowed? Only summon when we're 2 down. - if ( m_iNumLiveAntlions >= MAX(1, ANTLIONGUARD_SUMMON_COUNT-1) ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Our enemy is unreachable. Select a schedule. -//----------------------------------------------------------------------------- -int CNPC_AntlionGuard::SelectUnreachableSchedule( void ) -{ - // If we're in the cavern setting, we opt out of this - if ( m_bInCavern ) - return SCHED_ANTLIONGUARD_CHASE_ENEMY_TOLERANCE; - // Summon antlions if we can - if ( HasCondition( COND_ANTLIONGUARD_CAN_SUMMON ) ) - return SCHED_ANTLIONGUARD_SUMMON; - - // First, look for objects near ourselves - PhysicsObjectCriteria_t criteria; - criteria.bPreferObjectsAlongTargetVector = false; - criteria.flNearRadius = (40*12); - criteria.flRadius = (250*12); - criteria.flTargetCone = -1.0f; - criteria.pTarget = GetEnemy(); - criteria.vecCenter = GetAbsOrigin(); - - CBaseEntity *pTarget = FindPhysicsObjectTarget( criteria ); - if ( pTarget == NULL && GetEnemy() ) - { - // Use the same criteria, but search near the target instead of us - criteria.vecCenter = GetEnemy()->GetAbsOrigin(); - pTarget = FindPhysicsObjectTarget( criteria ); - } - - // If we found one, we'll want to attack it - if ( pTarget ) - { - m_hPhysicsTarget = pTarget; - SetCondition( COND_ANTLIONGUARD_PHYSICS_TARGET ); - m_vecPhysicsTargetStartPos = m_hPhysicsTarget->WorldSpaceCenter(); - - // Tell any squadmates I'm going for this item so they don't as well - if ( GetSquad() != NULL ) - { - GetSquad()->BroadcastInteraction( g_interactionAntlionGuardFoundPhysicsObject, (void *)((CBaseEntity *)m_hPhysicsTarget), this ); - } - - return SCHED_ANTLIONGUARD_PHYSICS_ATTACK; - } - - // Deal with a visible player - if ( HasCondition( COND_SEE_ENEMY ) ) - { - // Roar at the player as show of frustration - if ( m_flNextRoarTime < gpGlobals->curtime ) - { - m_flNextRoarTime = gpGlobals->curtime + RandomFloat( 20,40 ); - return SCHED_ANTLIONGUARD_ROAR; - } - - // If we're under attack, then let's leave for a bit - if ( GetEnemy() && HasCondition( COND_HEAVY_DAMAGE ) ) - { - Vector dir = GetEnemy()->GetAbsOrigin() - GetAbsOrigin(); - VectorNormalize(dir); - - GetMotor()->SetIdealYaw( -dir ); - - return SCHED_ANTLIONGUARD_TAKE_COVER_FROM_ENEMY; - } - } - - // If we're too far away, try to close distance to our target first - float flDistToEnemySqr = ( GetEnemy()->GetAbsOrigin() - GetAbsOrigin() ).LengthSqr(); - if ( flDistToEnemySqr > Square( 100*12 ) ) - return SCHED_ANTLIONGUARD_CHASE_ENEMY_TOLERANCE; - - // Fire that we're unable to reach our target! - if ( GetEnemy() && GetEnemy()->IsPlayer() ) - { - m_OnLostPlayer.FireOutput( this, this ); - } - - m_OnLostEnemy.FireOutput( this, this ); - GetEnemies()->MarkAsEluded( GetEnemy() ); - - // Move randomly for the moment - return SCHED_ANTLIONGUARD_CANT_ATTACK; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_AntlionGuard::SelectCombatSchedule( void ) -{ - ClearHintGroup(); - - /* - bool bCanCharge = false; - if ( HasCondition( COND_SEE_ENEMY ) ) - { - bCanCharge = ShouldCharge( GetAbsOrigin(), GetEnemy()->GetAbsOrigin(), true, false ); - } - */ - - // Attack if we can - if ( HasCondition(COND_CAN_MELEE_ATTACK1) ) - return SCHED_MELEE_ATTACK1; - - // Otherwise, summon antlions - if ( HasCondition(COND_ANTLIONGUARD_CAN_SUMMON) ) - { - // If I can charge, and have antlions, charge instead - if ( HasCondition( COND_ANTLIONGUARD_CAN_CHARGE ) && m_iNumLiveAntlions ) - return SCHED_ANTLIONGUARD_CHARGE; - - return SCHED_ANTLIONGUARD_SUMMON; - } - - // See if we can bark - if ( HasCondition( COND_ENEMY_UNREACHABLE ) ) - return SelectUnreachableSchedule(); - - //Physics target - if ( HasCondition( COND_ANTLIONGUARD_PHYSICS_TARGET ) && !m_bInCavern ) - return SCHED_ANTLIONGUARD_PHYSICS_ATTACK; - - // If we've missed a couple of times, and we can summon, make it harder - if ( m_iChargeMisses >= 2 && CanSummon(true) ) - { - m_iChargeMisses--; - return SCHED_ANTLIONGUARD_SUMMON; - } - - // Charging - if ( HasCondition( COND_ANTLIONGUARD_CAN_CHARGE ) ) - { - // Don't let other squad members charge while we're doing it - OccupyStrategySlot( SQUAD_SLOT_ANTLIONGUARD_CHARGE ); - return SCHED_ANTLIONGUARD_CHARGE; - } - - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_AntlionGuard::ShouldCharge( const Vector &startPos, const Vector &endPos, bool useTime, bool bCheckForCancel ) -{ - // Don't charge in tight spaces unless forced to - if ( hl2_episodic.GetBool() && m_bInCavern && !(m_hChargeTarget.Get() && m_hChargeTarget->IsAlive()) ) - return false; - - // Must have a target - if ( !GetEnemy() ) - return false; - - // No one else in the squad can be charging already - if ( IsStrategySlotRangeOccupied( SQUAD_SLOT_ANTLIONGUARD_CHARGE, SQUAD_SLOT_ANTLIONGUARD_CHARGE ) ) - return false; - - // Don't check the distance once we start charging - if ( !bCheckForCancel ) - { - // Don't allow use to charge again if it's been too soon - if ( useTime && ( m_flChargeTime > gpGlobals->curtime ) ) - return false; - - float distance = UTIL_DistApprox2D( startPos, endPos ); - - // Must be within our tolerance range - if ( ( distance < ANTLIONGUARD_CHARGE_MIN ) || ( distance > ANTLIONGUARD_CHARGE_MAX ) ) - return false; - } - - if ( GetSquad() ) - { - // If someone in our squad is closer to the enemy, then don't charge (we end up hitting them more often than not!) - float flOurDistToEnemySqr = ( GetAbsOrigin() - GetEnemy()->GetAbsOrigin() ).LengthSqr(); - AISquadIter_t iter; - for ( CAI_BaseNPC *pSquadMember = GetSquad()->GetFirstMember( &iter ); pSquadMember; pSquadMember = GetSquad()->GetNextMember( &iter ) ) - { - if ( pSquadMember->IsAlive() == false || pSquadMember == this ) - continue; - - if ( ( pSquadMember->GetAbsOrigin() - GetEnemy()->GetAbsOrigin() ).LengthSqr() < flOurDistToEnemySqr ) - return false; - } - } - - //FIXME: We'd like to exclude small physics objects from this check! - - // We only need to hit the endpos with the edge of our bounding box - Vector vecDir = endPos - startPos; - VectorNormalize( vecDir ); - float flWidth = WorldAlignSize().x * 0.5; - Vector vecTargetPos = endPos - (vecDir * flWidth); - - // See if we can directly move there - AIMoveTrace_t moveTrace; - GetMoveProbe()->MoveLimit( NAV_GROUND, startPos, vecTargetPos, MASK_NPCSOLID_BRUSHONLY, GetEnemy(), &moveTrace ); - - // Draw the probe - if ( g_debug_antlionguard.GetInt() == 1 ) - { - Vector enemyDir = (vecTargetPos - startPos); - float enemyDist = VectorNormalize( enemyDir ); - - NDebugOverlay::BoxDirection( startPos, GetHullMins(), GetHullMaxs() + Vector(enemyDist,0,0), enemyDir, 0, 255, 0, 8, 1.0f ); - } - - // If we're not blocked, charge - if ( IsMoveBlocked( moveTrace ) ) - { - // Don't allow it if it's too close to us - if ( UTIL_DistApprox( WorldSpaceCenter(), moveTrace.vEndPosition ) < ANTLIONGUARD_CHARGE_MIN ) - return false; - - // Allow some special cases to not block us - if ( moveTrace.pObstruction != NULL ) - { - // If we've hit the world, see if it's a cliff - if ( moveTrace.pObstruction == GetContainingEntity( INDEXENT(0) ) ) - { - // Can't be too far above/below the target - if ( fabs( moveTrace.vEndPosition.z - vecTargetPos.z ) > StepHeight() ) - return false; - - // Allow it if we got pretty close - if ( UTIL_DistApprox( moveTrace.vEndPosition, vecTargetPos ) < 64 ) - return true; - } - - // Hit things that will take damage - if ( moveTrace.pObstruction->m_takedamage != DAMAGE_NO ) - return true; - - // Hit things that will move - if ( moveTrace.pObstruction->GetMoveType() == MOVETYPE_VPHYSICS ) - return true; - } - - return false; - } - - // Only update this if we've requested it - if ( useTime ) - { - m_flChargeTime = gpGlobals->curtime + 4.0f; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_AntlionGuard::SelectSchedule( void ) -{ - // Don't do anything if we're burrowed - if ( m_bIsBurrowed ) - return SCHED_IDLE_STAND; - -#if 0 - // Debug physics object finding - if ( 0 ) //g_debug_antlionguard.GetInt() == 3 ) - { - m_flPhysicsCheckTime = 0; - UpdatePhysicsTarget( false ); - return SCHED_IDLE_STAND; - } -#endif - - // Flinch on heavy damage, but not if we've flinched too recently. - // This is done to prevent stun-locks from grenades. - if ( !m_bInCavern && HasCondition( COND_HEAVY_DAMAGE ) && m_flNextHeavyFlinchTime < gpGlobals->curtime ) - { - m_flNextHeavyFlinchTime = gpGlobals->curtime + 8.0f; - return SCHED_ANTLIONGUARD_PHYSICS_DAMAGE_HEAVY; - } - - // Prefer to use physics, in this case - if ( m_bPreferPhysicsAttack ) - { - // If we have a target, try to go for it - if ( HasCondition( COND_ANTLIONGUARD_PHYSICS_TARGET ) ) - return SCHED_ANTLIONGUARD_PHYSICS_ATTACK; - } - - // Charge after a target if it's set - if ( m_hChargeTarget && m_hChargeTargetPosition ) - { - ClearCondition( COND_ANTLIONGUARD_HAS_CHARGE_TARGET ); - ClearHintGroup(); - - if ( m_hChargeTarget->IsAlive() == false ) - { - m_hChargeTarget = NULL; - m_hChargeTargetPosition = NULL; - SetEnemy( m_hOldTarget ); - - if ( m_hOldTarget == NULL ) - { - m_NPCState = NPC_STATE_ALERT; - } - } - else - { - m_hOldTarget = GetEnemy(); - SetEnemy( m_hChargeTarget ); - UpdateEnemyMemory( m_hChargeTarget, m_hChargeTarget->GetAbsOrigin() ); - - //If we can't see the target, run to somewhere we can - if ( ShouldCharge( GetAbsOrigin(), GetEnemy()->GetAbsOrigin(), false, false ) == false ) - return SCHED_ANTLIONGUARD_FIND_CHARGE_POSITION; - - return SCHED_ANTLIONGUARD_CHARGE_TARGET; - } - } - - // See if we need to clear a path to our enemy - if ( HasCondition( COND_ENEMY_OCCLUDED ) || HasCondition( COND_ENEMY_UNREACHABLE ) ) - { - CBaseEntity *pBlocker = GetEnemyOccluder(); - - if ( ( pBlocker != NULL ) && FClassnameIs( pBlocker, "prop_physics" ) && !m_bInCavern ) - { - m_hPhysicsTarget = pBlocker; - return SCHED_ANTLIONGUARD_PHYSICS_ATTACK; - } - } - - //Only do these in combat states - if ( m_NPCState == NPC_STATE_COMBAT && GetEnemy() ) - return SelectCombatSchedule(); - - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_AntlionGuard::MeleeAttack1Conditions( float flDot, float flDist ) -{ - // Don't attack again too soon - if ( GetNextAttack() > gpGlobals->curtime ) - return 0; - - // While charging, we can't melee attack - if ( IsCurSchedule( SCHED_ANTLIONGUARD_CHARGE ) ) - return 0; - - if ( hl2_episodic.GetBool() && m_bInCavern ) - { - // Predict where they'll be and see if THAT is within range - Vector vecPredPos; - UTIL_PredictedPosition( GetEnemy(), 0.25f, &vecPredPos ); - if ( ( GetAbsOrigin() - vecPredPos ).Length() > ANTLIONGUARD_MELEE1_RANGE ) - return COND_TOO_FAR_TO_ATTACK; - } - else - { - // Must be close enough - if ( flDist > ANTLIONGUARD_MELEE1_RANGE ) - return COND_TOO_FAR_TO_ATTACK; - } - - // Must be within a viable cone - if ( flDot < ANTLIONGUARD_MELEE1_CONE ) - return COND_NOT_FACING_ATTACK; - - // If the enemy is on top of me, I'm allowed to hit the sucker - if ( GetEnemy()->GetGroundEntity() == this ) - return COND_CAN_MELEE_ATTACK1; - - trace_t tr; - TraceHull_SkipPhysics( WorldSpaceCenter(), GetEnemy()->WorldSpaceCenter(), Vector(-10,-10,-10), Vector(10,10,10), MASK_SHOT_HULL, this, COLLISION_GROUP_NONE, &tr, VPhysicsGetObject()->GetMass() * 0.5 ); - - // If we hit anything, go for it - if ( tr.fraction < 1.0f ) - return COND_CAN_MELEE_ATTACK1; - - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CNPC_AntlionGuard::MaxYawSpeed( void ) -{ - Activity eActivity = GetActivity(); - - // Stay still - if (( eActivity == ACT_ANTLIONGUARD_SEARCH ) || - ( eActivity == ACT_ANTLIONGUARD_PEEK_ENTER ) || - ( eActivity == ACT_ANTLIONGUARD_PEEK_EXIT ) || - ( eActivity == ACT_ANTLIONGUARD_PEEK1 ) || - ( eActivity == ACT_ANTLIONGUARD_BARK ) || - ( eActivity == ACT_ANTLIONGUARD_PEEK_SIGHTED ) || - ( eActivity == ACT_MELEE_ATTACK1 ) ) - return 0.0f; - - CBaseEntity *pEnemy = GetEnemy(); - - if ( pEnemy != NULL && pEnemy->IsPlayer() == false ) - return 16.0f; - - // Turn slowly when you're charging - if ( eActivity == ACT_ANTLIONGUARD_CHARGE_START ) - return 4.0f; - - if ( hl2_episodic.GetBool() && m_bInCavern ) - { - // Allow a better turning rate when moving quickly but not charging the player - if ( ( eActivity == ACT_ANTLIONGUARD_CHARGE_RUN ) && IsCurSchedule( SCHED_ANTLIONGUARD_CHARGE ) == false ) - return 16.0f; - } - - // Turn more slowly as we close in on our target - if ( eActivity == ACT_ANTLIONGUARD_CHARGE_RUN ) - { - if ( pEnemy == NULL ) - return 2.0f; - - float dist = UTIL_DistApprox2D( GetEnemy()->WorldSpaceCenter(), WorldSpaceCenter() ); - - if ( dist > 512 ) - return 16.0f; - - //FIXME: Alter by skill level - float yawSpeed = RemapVal( dist, 0, 512, 1.0f, 2.0f ); - yawSpeed = clamp( yawSpeed, 1.0f, 2.0f ); - - return yawSpeed; - } - - if ( eActivity == ACT_ANTLIONGUARD_CHARGE_STOP ) - return 8.0f; - - switch( eActivity ) - { - case ACT_TURN_LEFT: - case ACT_TURN_RIGHT: - return 40.0f; - break; - - case ACT_RUN: - default: - return 20.0f; - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flInterval - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_AntlionGuard::OverrideMove( float flInterval ) -{ - // If the guard's charging, we're handling the movement - if ( IsCurSchedule( SCHED_ANTLIONGUARD_CHARGE ) ) - return true; - - // TODO: This code increases the guard's ability to successfully hit a target, but adds a new dimension of navigation - // trouble to do with him not being able to "close the distance" between himself and the object he wants to hit. - // Fixing this will require some thought on how he picks the correct distances to his targets and when he's "close enough". -- jdw - - /* - if ( m_hPhysicsTarget != NULL ) - { - float flWidth = m_hPhysicsTarget->CollisionProp()->BoundingRadius2D(); - GetLocalNavigator()->AddObstacle( m_hPhysicsTarget->WorldSpaceCenter(), flWidth * 0.75f, AIMST_AVOID_OBJECT ); - //NDebugOverlay::Sphere( m_hPhysicsTarget->WorldSpaceCenter(), vec3_angle, flWidth, 255, 255, 255, 0, true, 0.5f ); - } - */ - - return BaseClass::OverrideMove( flInterval ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::Shove( void ) -{ - if ( GetNextAttack() > gpGlobals->curtime ) - return; - - CBaseEntity *pHurt = NULL; - CBaseEntity *pTarget; - - pTarget = ( m_hShoveTarget == NULL ) ? GetEnemy() : m_hShoveTarget.Get(); - - if ( pTarget == NULL ) - { - m_hShoveTarget = NULL; - return; - } - - //Always damage bullseyes if we're scripted to hit them - if ( pTarget->Classify() == CLASS_BULLSEYE ) - { - pTarget->TakeDamage( CTakeDamageInfo( this, this, 1.0f, DMG_CRUSH ) ); - m_hShoveTarget = NULL; - return; - } - - float damage = ( pTarget->IsPlayer() ) ? sk_antlionguard_dmg_shove.GetFloat() : 250; - - // If the target's still inside the shove cone, ensure we hit him - Vector vecForward, vecEnd; - AngleVectors( GetAbsAngles(), &vecForward ); - float flDistSqr = ( pTarget->WorldSpaceCenter() - WorldSpaceCenter() ).LengthSqr(); - Vector2D v2LOS = ( pTarget->WorldSpaceCenter() - WorldSpaceCenter() ).AsVector2D(); - Vector2DNormalize(v2LOS); - float flDot = DotProduct2D (v2LOS, vecForward.AsVector2D() ); - if ( flDistSqr < (ANTLIONGUARD_MELEE1_RANGE*ANTLIONGUARD_MELEE1_RANGE) && flDot >= ANTLIONGUARD_MELEE1_CONE ) - { - vecEnd = pTarget->WorldSpaceCenter(); - } - else - { - vecEnd = WorldSpaceCenter() + ( BodyDirection3D() * ANTLIONGUARD_MELEE1_RANGE ); - } - - // Use the melee trace to ensure we hit everything there - trace_t tr; - CTakeDamageInfo dmgInfo( this, this, damage, DMG_SLASH ); - CTraceFilterMelee traceFilter( this, COLLISION_GROUP_NONE, &dmgInfo, 1.0, true ); - Ray_t ray; - ray.Init( WorldSpaceCenter(), vecEnd, Vector(-16,-16,-16), Vector(16,16,16) ); - enginetrace->TraceRay( ray, MASK_SHOT_HULL, &traceFilter, &tr ); - pHurt = tr.m_pEnt; - - // Knock things around - ImpactShock( tr.endpos, 100.0f, 250.0f ); - - if ( pHurt ) - { - Vector traceDir = ( tr.endpos - tr.startpos ); - VectorNormalize( traceDir ); - - // Generate enough force to make a 75kg guy move away at 600 in/sec - Vector vecForce = traceDir * ImpulseScale( 75, 600 ); - CTakeDamageInfo info( this, this, vecForce, tr.endpos, damage, DMG_CLUB ); - pHurt->TakeDamage( info ); - - m_hShoveTarget = NULL; - - EmitSound( "NPC_AntlionGuard.Shove" ); - - // If the player, throw him around - if ( pHurt->IsPlayer() ) - { - //Punch the view - pHurt->ViewPunch( QAngle(20,0,-20) ); - - //Shake the screen - UTIL_ScreenShake( pHurt->GetAbsOrigin(), 100.0, 1.5, 1.0, 2, SHAKE_START ); - - //Red damage indicator - color32 red = {128,0,0,128}; - UTIL_ScreenFade( pHurt, red, 1.0f, 0.1f, FFADE_IN ); - - Vector forward, up; - AngleVectors( GetLocalAngles(), &forward, NULL, &up ); - pHurt->ApplyAbsVelocityImpulse( forward * 400 + up * 150 ); - - // in the episodes, the cavern guard poisons the player -#if HL2_EPISODIC - // If I am a cavern guard attacking the player, and he still lives, then poison him too. - if ( m_bInCavern && pHurt->IsPlayer() && pHurt->IsAlive() && pHurt->m_iHealth > ANTLIONGUARD_POISON_TO) - { - // That didn't finish them. Take them down to one point with poison damage. It'll heal. - pHurt->TakeDamage( CTakeDamageInfo( this, this, pHurt->m_iHealth - ANTLIONGUARD_POISON_TO, DMG_POISON ) ); - } -#endif - - } - else - { - CBaseCombatCharacter *pVictim = ToBaseCombatCharacter( pHurt ); - - if ( pVictim ) - { - if ( NPC_Rollermine_IsRollermine( pVictim ) ) - { - Pickup_OnPhysGunDrop( pVictim, NULL, LAUNCHED_BY_CANNON ); - } - - // FIXME: This causes NPCs that are not physically motivated to hop into the air strangely -- jdw - // pVictim->ApplyAbsVelocityImpulse( BodyDirection2D() * 400 + Vector( 0, 0, 250 ) ); - } - - m_hShoveTarget = NULL; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CTraceFilterCharge : public CTraceFilterEntitiesOnly -{ -public: - // It does have a base, but we'll never network anything below here.. - DECLARE_CLASS_NOBASE( CTraceFilterCharge ); - - CTraceFilterCharge( const IHandleEntity *passentity, int collisionGroup, CNPC_AntlionGuard *pAttacker ) - : m_pPassEnt(passentity), m_collisionGroup(collisionGroup), m_pAttacker(pAttacker) - { - } - - virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) - { - if ( !StandardFilterRules( pHandleEntity, contentsMask ) ) - return false; - - if ( !PassServerEntityFilter( pHandleEntity, m_pPassEnt ) ) - return false; - - // Don't test if the game code tells us we should ignore this collision... - CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); - - if ( pEntity ) - { - if ( !pEntity->ShouldCollide( m_collisionGroup, contentsMask ) ) - return false; - - if ( !g_pGameRules->ShouldCollide( m_collisionGroup, pEntity->GetCollisionGroup() ) ) - return false; - - if ( pEntity->m_takedamage == DAMAGE_NO ) - return false; - - // Translate the vehicle into its driver for damage - if ( pEntity->GetServerVehicle() != NULL ) - { - CBaseEntity *pDriver = pEntity->GetServerVehicle()->GetPassenger(); - - if ( pDriver != NULL ) - { - pEntity = pDriver; - } - } - - Vector attackDir = pEntity->WorldSpaceCenter() - m_pAttacker->WorldSpaceCenter(); - VectorNormalize( attackDir ); - - float flDamage = ( pEntity->IsPlayer() ) ? sk_antlionguard_dmg_shove.GetFloat() : 250;; - - CTakeDamageInfo info( m_pAttacker, m_pAttacker, flDamage, DMG_CRUSH ); - CalculateMeleeDamageForce( &info, attackDir, info.GetAttacker()->WorldSpaceCenter(), 4.0f ); - - CBaseCombatCharacter *pVictimBCC = pEntity->MyCombatCharacterPointer(); - - // Only do these comparisons between NPCs - if ( pVictimBCC ) - { - // Can only damage other NPCs that we hate - if ( m_pAttacker->IRelationType( pEntity ) == D_HT ) - { - pEntity->TakeDamage( info ); - return true; - } - } - else - { - // Otherwise just damage passive objects in our way - pEntity->TakeDamage( info ); - Pickup_ForcePlayerToDropThisObject( pEntity ); - } - } - - return false; - } - -public: - const IHandleEntity *m_pPassEnt; - int m_collisionGroup; - CNPC_AntlionGuard *m_pAttacker; -}; - -#define MIN_FOOTSTEP_NEAR_DIST Square( 80*12.0f )// ft - -//----------------------------------------------------------------------------- -// Purpose: Plays a footstep sound with temporary distance fades -// Input : bHeavy - Larger back hoof is considered a "heavy" step -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::Footstep( bool bHeavy ) -{ - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - Assert( pPlayer != NULL ); - if ( pPlayer == NULL ) - return; - - float flDistanceToPlayerSqr = ( pPlayer->GetAbsOrigin() - GetAbsOrigin() ).LengthSqr(); - float flNearVolume = RemapValClamped( flDistanceToPlayerSqr, Square(10*12.0f), MIN_FOOTSTEP_NEAR_DIST, VOL_NORM, 0.0f ); - - EmitSound_t soundParams; - CPASAttenuationFilter filter( this ); - - if ( bHeavy ) - { - if ( flNearVolume > 0.0f ) - { - soundParams.m_pSoundName = "NPC_AntlionGuard.NearStepHeavy"; - soundParams.m_flVolume = flNearVolume; - soundParams.m_nFlags = SND_CHANGE_VOL; - EmitSound( filter, entindex(), soundParams ); - } - - EmitSound( "NPC_AntlionGuard.FarStepHeavy" ); - } - else - { - if ( flNearVolume > 0.0f ) - { - soundParams.m_pSoundName = "NPC_AntlionGuard.NearStepLight"; - soundParams.m_flVolume = flNearVolume; - soundParams.m_nFlags = SND_CHANGE_VOL; - EmitSound( filter, entindex(), soundParams ); - } - - EmitSound( "NPC_AntlionGuard.FarStepLight" ); - } -} - -extern ConVar sv_gravity; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pObject - -// *pOut - -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::GetPhysicsShoveDir( CBaseEntity *pObject, float flMass, Vector *pOut ) -{ - const Vector vecStart = pObject->WorldSpaceCenter(); - const Vector vecTarget = GetEnemy()->WorldSpaceCenter(); - - const float flBaseSpeed = 800.0f; - float flSpeed = RemapValClamped( flMass, 0.0f, 150.0f, flBaseSpeed * 2.0f, flBaseSpeed ); - - // Try the most direct route - Vector vecToss = VecCheckThrow( this, vecStart, vecTarget, flSpeed, 1.0f ); - - // If this failed then try a little faster (flattens the arc) - if ( vecToss == vec3_origin ) - { - vecToss = VecCheckThrow( this, vecStart, vecTarget, flSpeed * 1.25f, 1.0f ); - if ( vecToss == vec3_origin ) - { - const float flGravity = sv_gravity.GetFloat(); - - vecToss = (vecTarget - vecStart); - - // throw at a constant time - float time = vecToss.Length( ) / flSpeed; - vecToss = vecToss * (1.0f / time); - - // adjust upward toss to compensate for gravity loss - vecToss.z += flGravity * time * 0.5f; - } - } - - // Save out the result - if ( pOut ) - { - *pOut = vecToss; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEvent - -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::HandleAnimEvent( animevent_t *pEvent ) -{ - if ( pEvent->event == AE_ANTLIONGUARD_CHARGE_EARLYOUT ) - { - // Robin: Removed this because it usually made him look less intelligent, not more. - // This code left here so we don't get warnings in the console. - - /* - // Cancel the charge if it's no longer valid - if ( ShouldCharge( GetAbsOrigin(), GetEnemy()->GetAbsOrigin(), false, true ) == false ) - { - SetSchedule( SCHED_ANTLIONGUARD_CHARGE_CANCEL ); - } - */ - - return; - } - - // Don't handle anim events after death - if ( m_NPCState == NPC_STATE_DEAD ) - { - BaseClass::HandleAnimEvent( pEvent ); - return; - } - - if ( pEvent->event == AE_ANTLIONGUARD_SHOVE_PHYSOBJECT ) - { - if ( m_hPhysicsTarget == NULL ) - { - // Disrupt other objects near us anyway - ImpactShock( WorldSpaceCenter(), 150, 250.0f ); - return; - } - - // If we have no enemy, we don't really have a direction to throw the object - // in. But, we still want to clobber it so the animevent doesn't happen fruitlessly, - // and we want to clear the condition flags and other state regarding the m_hPhysicsTarget. - // So, skip the code relevant to computing a launch vector specific to the object I'm - // striking, but use the ImpactShock call further below to punch everything in the neighborhood. - CBaseEntity *pEnemy = GetEnemy(); - if ( pEnemy != NULL ) - { - //Setup the throw velocity - IPhysicsObject *physObj = m_hPhysicsTarget->VPhysicsGetObject(); - Vector vecShoveVel = ( pEnemy->GetAbsOrigin() - m_hPhysicsTarget->WorldSpaceCenter() ); - float flTargetDist = VectorNormalize( vecShoveVel ); - - // Must still be close enough to our target - Vector shoveDir = m_hPhysicsTarget->WorldSpaceCenter() - WorldSpaceCenter(); - float shoveDist = VectorNormalize( shoveDir ); - if ( shoveDist > 300.0f ) - { - // Pick a new target next time (this one foiled us!) - RememberFailedPhysicsTarget( m_hPhysicsTarget ); - m_hPhysicsTarget = NULL; - return; - } - - // Toss this if we're episodic - if ( hl2_episodic.GetBool() ) - { - Vector vecTargetDir = vecShoveVel; - - // Get our shove direction - GetPhysicsShoveDir( m_hPhysicsTarget, physObj->GetMass(), &vecShoveVel ); - - // If the player isn't looking at me, and isn't reachable, be more forgiving about hitting them - if ( HasCondition( COND_ENEMY_UNREACHABLE ) && HasCondition( COND_ENEMY_FACING_ME ) == false ) - { - // Build an arc around the top of the target that we'll offset our aim by - Vector vecOffset; - float flSin, flCos; - float flRad = random->RandomFloat( 0, M_PI / 6.0f ); // +/- 30 deg - if ( random->RandomInt( 0, 1 ) ) - flRad *= -1.0f; - - SinCos( flRad, &flSin, &flCos ); - - // Rotate the 2-d circle to be "facing" along our shot direction - Vector vecArc; - QAngle vecAngles; - VectorAngles( vecTargetDir, vecAngles ); - VectorRotate( Vector( 0.0f, flCos, flSin ), vecAngles, vecArc ); - - // Find the radius by which to avoid the player - float flOffsetRadius = ( m_hPhysicsTarget->CollisionProp()->BoundingRadius() + GetEnemy()->CollisionProp()->BoundingRadius() ) * 1.5f; - - // Add this to our velocity to offset it - vecShoveVel += ( vecArc * flOffsetRadius ); - } - - // Factor out mass - vecShoveVel *= physObj->GetMass(); - - // FIXME: We need to restore this on the object at some point if we do this! - float flDragCoef = 0.0f; - physObj->SetDragCoefficient( &flDragCoef, &flDragCoef ); - } - else - { - if ( flTargetDist < 512 ) - flTargetDist = 512; - - if ( flTargetDist > 1024 ) - flTargetDist = 1024; - - vecShoveVel *= flTargetDist * 3 * physObj->GetMass(); //FIXME: Scale by skill - vecShoveVel[2] += physObj->GetMass() * 350.0f; - } - - if ( NPC_Rollermine_IsRollermine( m_hPhysicsTarget ) ) - { - Pickup_OnPhysGunDrop( m_hPhysicsTarget, NULL, LAUNCHED_BY_CANNON ); - } - - //Send it flying - AngularImpulse angVel( random->RandomFloat(-180, 180), 100, random->RandomFloat(-360, 360) ); - physObj->ApplyForceCenter( vecShoveVel ); - physObj->AddVelocity( NULL, &angVel ); - } - - //Display dust - Vector vecRandom = RandomVector( -1, 1); - VectorNormalize( vecRandom ); - g_pEffects->Dust( m_hPhysicsTarget->WorldSpaceCenter(), vecRandom, 64.0f, 32 ); - - // If it's being held by the player, break that bond - Pickup_ForcePlayerToDropThisObject( m_hPhysicsTarget ); - - EmitSound( "NPC_AntlionGuard.HitHard" ); - - //Clear the state information, we're done - ClearCondition( COND_ANTLIONGUARD_PHYSICS_TARGET ); - ClearCondition( COND_ANTLIONGUARD_PHYSICS_TARGET_INVALID ); - - // Disrupt other objects near it, including the m_hPhysicsTarget if we had no valid enemy - ImpactShock( m_hPhysicsTarget->WorldSpaceCenter(), 150, 250.0f, pEnemy != NULL ? m_hPhysicsTarget : NULL ); - - // Notify any squad members that we're no longer monopolizing this object - if ( GetSquad() != NULL ) - { - GetSquad()->BroadcastInteraction( g_interactionAntlionGuardShovedPhysicsObject, (void *)((CBaseEntity *)m_hPhysicsTarget), this ); - } - - m_hPhysicsTarget = NULL; - m_FailedPhysicsTargets.RemoveAll(); - - return; - } - - if ( pEvent->event == AE_ANTLIONGUARD_CHARGE_HIT ) - { - UTIL_ScreenShake( GetAbsOrigin(), 32.0f, 4.0f, 1.0f, 512, SHAKE_START ); - EmitSound( "NPC_AntlionGuard.HitHard" ); - - Vector startPos = GetAbsOrigin(); - float checkSize = ( CollisionProp()->BoundingRadius() + 8.0f ); - Vector endPos = startPos + ( BodyDirection3D() * checkSize ); - - CTraceFilterCharge traceFilter( this, COLLISION_GROUP_NONE, this ); - - Ray_t ray; - ray.Init( startPos, endPos, GetHullMins(), GetHullMaxs() ); - - trace_t tr; - enginetrace->TraceRay( ray, MASK_SHOT, &traceFilter, &tr ); - - if ( g_debug_antlionguard.GetInt() == 1 ) - { - Vector hullMaxs = GetHullMaxs(); - hullMaxs.x += checkSize; - - NDebugOverlay::BoxDirection( startPos, GetHullMins(), hullMaxs, BodyDirection2D(), 100, 255, 255, 20, 1.0f ); - } - - //NDebugOverlay::Box3D( startPos, endPos, BodyDirection2D(), - if ( m_hChargeTarget && m_hChargeTarget->IsAlive() == false ) - { - m_hChargeTarget = NULL; - m_hChargeTargetPosition = NULL; - } - - // Cause a shock wave from this point which will distrupt nearby physics objects - ImpactShock( tr.endpos, 200, 500 ); - return; - } - - if ( pEvent->event == AE_ANTLIONGUARD_SHOVE ) - { - EmitSound("NPC_AntlionGuard.StepLight", pEvent->eventtime ); - Shove(); - return; - } - - if ( pEvent->event == AE_ANTLIONGUARD_FOOTSTEP_LIGHT ) - { - if ( HasSpawnFlags(SF_ANTLIONGUARD_INSIDE_FOOTSTEPS) ) - { -#if HL2_EPISODIC - Footstep( false ); -#else - EmitSound("NPC_AntlionGuard.Inside.StepLight", pEvent->eventtime ); -#endif // HL2_EPISODIC - } - else - { -#if HL2_EPISODIC - Footstep( false ); -#else - EmitSound("NPC_AntlionGuard.StepLight", pEvent->eventtime ); -#endif // HL2_EPISODIC - } - return; - } - - if ( pEvent->event == AE_ANTLIONGUARD_FOOTSTEP_HEAVY ) - { - if ( HasSpawnFlags(SF_ANTLIONGUARD_INSIDE_FOOTSTEPS) ) - { -#if HL2_EPISODIC - Footstep( true ); -#else - EmitSound( "NPC_AntlionGuard.Inside.StepHeavy", pEvent->eventtime ); -#endif // HL2_EPISODIC - } - else - { -#if HL2_EPISODIC - Footstep( true ); -#else - EmitSound( "NPC_AntlionGuard.StepHeavy", pEvent->eventtime ); -#endif // HL2_EPISODIC - } - return; - } - - if ( pEvent->event == AE_ANTLIONGUARD_VOICE_GROWL ) - { - StartSounds(); - - float duration = 0.0f; - - if ( random->RandomInt( 0, 10 ) < 6 ) - { - duration = ENVELOPE_CONTROLLER.SoundPlayEnvelope( m_pGrowlHighSound, SOUNDCTRL_CHANGE_VOLUME, envAntlionGuardFastGrowl, ARRAYSIZE(envAntlionGuardFastGrowl) ); - } - else - { - duration = 1.0f; - EmitSound( "NPC_AntlionGuard.FrustratedRoar" ); - ENVELOPE_CONTROLLER.SoundFadeOut( m_pGrowlHighSound, 0.5f, false ); - } - - m_flAngerNoiseTime = gpGlobals->curtime + duration + random->RandomFloat( 2.0f, 4.0f ); - - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pBreathSound, 0.0f, 0.1f ); - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pGrowlIdleSound, 0.0f, 0.1f ); - - m_flBreathTime = gpGlobals->curtime + duration - 0.2f; - - EmitSound( "NPC_AntlionGuard.Anger" ); - return; - } - - - if ( pEvent->event == AE_ANTLIONGUARD_VOICE_BARK ) - { - StartSounds(); - - float duration = ENVELOPE_CONTROLLER.SoundPlayEnvelope( m_pGrowlHighSound, SOUNDCTRL_CHANGE_VOLUME, envAntlionGuardBark1, ARRAYSIZE(envAntlionGuardBark1) ); - ENVELOPE_CONTROLLER.SoundPlayEnvelope( m_pConfusedSound, SOUNDCTRL_CHANGE_VOLUME, envAntlionGuardBark2, ARRAYSIZE(envAntlionGuardBark2) ); - - m_flAngerNoiseTime = gpGlobals->curtime + duration + random->RandomFloat( 2.0f, 4.0f ); - - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pBreathSound, 0.0f, 0.1f ); - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pGrowlIdleSound, 0.0f, 0.1f ); - - m_flBreathTime = gpGlobals->curtime + duration - 0.2f; - return; - } - - if ( pEvent->event == AE_ANTLIONGUARD_VOICE_ROAR ) - { - StartSounds(); - - float duration = ENVELOPE_CONTROLLER.SoundPlayEnvelope( m_pGrowlHighSound, SOUNDCTRL_CHANGE_VOLUME, envAntlionGuardFastGrowl, ARRAYSIZE(envAntlionGuardFastGrowl) ); - - m_flAngerNoiseTime = gpGlobals->curtime + duration + random->RandomFloat( 2.0f, 4.0f ); - - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pBreathSound, 0.0f, 0.1f ); - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pGrowlIdleSound, 0.0f, 0.1f ); - - m_flBreathTime = gpGlobals->curtime + duration - 0.2f; - - EmitSound( "NPC_AntlionGuard.Roar" ); - return; - } - - if ( pEvent->event == AE_ANTLIONGUARD_VOICE_PAIN ) - { - StartSounds(); - - float duration = ENVELOPE_CONTROLLER.SoundPlayEnvelope( m_pConfusedSound, SOUNDCTRL_CHANGE_VOLUME, envAntlionGuardPain1, ARRAYSIZE(envAntlionGuardPain1) ); - ENVELOPE_CONTROLLER.SoundPlayEnvelope( m_pGrowlHighSound, SOUNDCTRL_CHANGE_VOLUME, envAntlionGuardBark2, ARRAYSIZE(envAntlionGuardBark2) ); - - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pBreathSound, 0.0f, 0.1f ); - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pGrowlIdleSound, 0.0f, 0.1f ); - - m_flBreathTime = gpGlobals->curtime + duration - 0.2f; - return; - } - - if ( pEvent->event == AE_ANTLIONGUARD_VOICE_SQUEEZE ) - { - StartSounds(); - - float duration = ENVELOPE_CONTROLLER.SoundPlayEnvelope( m_pGrowlHighSound, SOUNDCTRL_CHANGE_VOLUME, envAntlionGuardSqueeze, ARRAYSIZE(envAntlionGuardSqueeze) ); - - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pBreathSound, 0.6f, random->RandomFloat( 2.0f, 4.0f ) ); - ENVELOPE_CONTROLLER.SoundChangePitch( m_pBreathSound, random->RandomInt( 60, 80 ), random->RandomFloat( 2.0f, 4.0f ) ); - - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pGrowlIdleSound, 0.0f, 0.1f ); - - m_flBreathTime = gpGlobals->curtime + ( duration * 0.5f ); - - EmitSound( "NPC_AntlionGuard.Anger" ); - return; - } - - if ( pEvent->event == AE_ANTLIONGUARD_VOICE_SCRATCH ) - { - StartSounds(); - - float duration = random->RandomFloat( 2.0f, 4.0f ); - - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pBreathSound, 0.6f, duration ); - ENVELOPE_CONTROLLER.SoundChangePitch( m_pBreathSound, random->RandomInt( 60, 80 ), duration ); - - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pGrowlIdleSound, 0.0f, 0.1f ); - - m_flBreathTime = gpGlobals->curtime + duration; - - EmitSound( "NPC_AntlionGuard.Anger" ); - return; - } - - if ( pEvent->event == AE_ANTLIONGUARD_VOICE_GRUNT ) - { - StartSounds(); - - float duration = ENVELOPE_CONTROLLER.SoundPlayEnvelope( m_pConfusedSound, SOUNDCTRL_CHANGE_VOLUME, envAntlionGuardGrunt, ARRAYSIZE(envAntlionGuardGrunt) ); - ENVELOPE_CONTROLLER.SoundPlayEnvelope( m_pGrowlHighSound, SOUNDCTRL_CHANGE_VOLUME, envAntlionGuardGrunt2, ARRAYSIZE(envAntlionGuardGrunt2) ); - - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pBreathSound, 0.0f, 0.1f ); - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pGrowlIdleSound, 0.0f, 0.1f ); - - m_flBreathTime = gpGlobals->curtime + duration; - return; - } - - if ( pEvent->event == AE_ANTLIONGUARD_BURROW_OUT ) - { - EmitSound( "NPC_Antlion.BurrowOut" ); - - //Shake the screen - UTIL_ScreenShake( GetAbsOrigin(), 0.5f, 80.0f, 1.0f, 256.0f, SHAKE_START ); - - //Throw dust up - UTIL_CreateAntlionDust( GetAbsOrigin() + Vector(0,0,24), GetLocalAngles() ); - - RemoveEffects( EF_NODRAW ); - RemoveFlag( FL_NOTARGET ); - - if ( m_bCavernBreed ) - { - if ( m_hCaveGlow[0] ) - m_hCaveGlow[0]->TurnOn(); - - if ( m_hCaveGlow[1] ) - m_hCaveGlow[1]->TurnOn(); - } - - return; - } - - BaseClass::HandleAnimEvent( pEvent ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::SetHeavyDamageAnim( const Vector &vecSource ) -{ - if ( !m_bInCavern ) - { - Vector vFacing = BodyDirection2D(); - Vector vDamageDir = ( vecSource - WorldSpaceCenter() ); - - vDamageDir.z = 0.0f; - - VectorNormalize( vDamageDir ); - - Vector vDamageRight, vDamageUp; - VectorVectors( vDamageDir, vDamageRight, vDamageUp ); - - float damageDot = DotProduct( vFacing, vDamageDir ); - float damageRightDot = DotProduct( vFacing, vDamageRight ); - - // See if it's in front - if ( damageDot > 0.0f ) - { - // See if it's right - if ( damageRightDot > 0.0f ) - { - m_nFlinchActivity = ACT_ANTLIONGUARD_PHYSHIT_FR; - } - else - { - m_nFlinchActivity = ACT_ANTLIONGUARD_PHYSHIT_FL; - } - } - else - { - // Otherwise it's from behind - if ( damageRightDot < 0.0f ) - { - m_nFlinchActivity = ACT_ANTLIONGUARD_PHYSHIT_RR; - } - else - { - m_nFlinchActivity = ACT_ANTLIONGUARD_PHYSHIT_RL; - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -//----------------------------------------------------------------------------- -int CNPC_AntlionGuard::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - CTakeDamageInfo dInfo = info; - - // Don't take damage from another antlion guard! - if ( dInfo.GetAttacker() && dInfo.GetAttacker() != this && FClassnameIs( dInfo.GetAttacker(), "npc_antlionguard" ) ) - return 0; - - if ( ( dInfo.GetDamageType() & DMG_CRUSH ) && !( dInfo.GetDamageType() & DMG_VEHICLE ) ) - { - // Don't take damage from physics objects that weren't thrown by the player. - CBaseEntity *pInflictor = dInfo.GetInflictor(); - - IPhysicsObject *pObj = pInflictor->VPhysicsGetObject(); - if ( !pObj || !( pObj->GetGameFlags() & FVPHYSICS_WAS_THROWN ) ) - { - return 0; - } - } - - // Hack to make antlion guard harder in HARD - if ( g_pGameRules->IsSkillLevel(SKILL_HARD) && !(info.GetDamageType() & DMG_CRUSH) ) - { - dInfo.SetDamage( dInfo.GetDamage() * 0.75 ); - } - - // Cap damage taken by crushing (otherwise we can get crushed oddly) - if ( ( dInfo.GetDamageType() & DMG_CRUSH ) && dInfo.GetDamage() > 100 ) - { - dInfo.SetDamage( 100 ); - } - - // Only take damage from what we classify as heavy damages (explosions, refrigerators, etc) - if ( IsHeavyDamage( dInfo ) ) - { - // Always take a set amount of damage from a combine ball - if ( info.GetInflictor() && UTIL_IsCombineBall( info.GetInflictor() ) ) - { - dInfo.SetDamage( 50 ); - } - - UTIL_ScreenShake( GetAbsOrigin(), 32.0f, 8.0f, 0.5f, 512, SHAKE_START ); - - // Set our response animation - SetHeavyDamageAnim( dInfo.GetDamagePosition() ); - - // Explosive barrels don't carry through their attacker, so this - // condition isn't set, and we still want to flinch. So we set it. - SetCondition( COND_HEAVY_DAMAGE ); - - // TODO: Make this its own effect! - CEffectData data; - data.m_vOrigin = dInfo.GetDamagePosition(); - data.m_vNormal = -dInfo.GetDamageForce(); - VectorNormalize( data.m_vNormal ); - DispatchEffect( "HunterDamage", data ); - - // Play a sound for a physics impact - if ( dInfo.GetDamageType() & DMG_CRUSH ) - { - EmitSound("NPC_AntlionGuard.ShellCrack"); - } - - // Roar in pain - EmitSound( "NPC_AntlionGuard.Pain_Roar" ); - - // TODO: This will require a more complete solution; for now let's shelve it! - /* - if ( dInfo.GetDamageType() & DMG_BLAST ) - { - // Create the dust effect in place - CParticleSystem *pParticle = (CParticleSystem *) CreateEntityByName( "info_particle_system" ); - if ( pParticle != NULL ) - { - // Setup our basic parameters - pParticle->KeyValue( "start_active", "1" ); - pParticle->KeyValue( "effect_name", "fire_medium_02_nosmoke" ); - pParticle->SetParent( this ); - pParticle->SetParentAttachment( "SetParentAttachment", "attach_glow2", true ); - pParticle->SetLocalOrigin( Vector( -16, 24, 0 ) ); - DispatchSpawn( pParticle ); - if ( gpGlobals->curtime > 0.5f ) - pParticle->Activate(); - - pParticle->SetThink( &CBaseEntity::SUB_Remove ); - pParticle->SetNextThink( gpGlobals->curtime + random->RandomFloat( 2.0f, 3.0f ) ); - } - } - */ - } - - int nPreHealth = GetHealth(); - int nDamageTaken = BaseClass::OnTakeDamage_Alive( dInfo ); - - // See if we've crossed a measured phase in our health and flinch from that to show we do take damage - if ( !m_bInCavern && HasCondition( COND_HEAVY_DAMAGE ) == false && ( info.GetDamageType() & DMG_BULLET ) ) - { - bool bTakeHeavyDamage = false; - - // Do an early flinch so that players understand the guard can be hurt by - if ( ( (float) GetHealth() / (float) GetMaxHealth() ) > 0.9f ) - { - float flPrePerc = (float) nPreHealth / (float) GetMaxHealth(); - float flPostPerc = (float) GetHealth() / (float) GetMaxHealth(); - if ( flPrePerc >= 0.95f && flPostPerc < 0.95f ) - { - bTakeHeavyDamage = true; - } - } - - // Otherwise see if we've passed a measured point in our health - if ( bTakeHeavyDamage == false ) - { - const float flNumDamagePhases = 5.0f; - - float flDenom = ( (float) GetMaxHealth() / flNumDamagePhases ); - int nPreDamagePhase = (int)ceil(nPreHealth / flDenom); - int nPostDamagePhase = (int)ceil(GetHealth() / flDenom); - if ( nPreDamagePhase != nPostDamagePhase ) - { - bTakeHeavyDamage = true; - } - } - - // Flinch if we should - if ( bTakeHeavyDamage ) - { - // Set our response animation - SetHeavyDamageAnim( dInfo.GetDamagePosition() ); - - // Roar in pain - EmitSound( "NPC_AntlionGuard.Pain_Roar" ); - - // Flinch! - SetCondition( COND_HEAVY_DAMAGE ); - } - } - - return nDamageTaken; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pAttacker - -// flDamage - -// &vecDir - -// *ptr - -// bitsDamageType - -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::TraceAttack( const CTakeDamageInfo &inputInfo, const Vector &vecDir, trace_t *ptr ) -{ - CTakeDamageInfo info = inputInfo; - - // Bullets are weak against us, buckshot less so - if ( info.GetDamageType() & DMG_BUCKSHOT ) - { - info.ScaleDamage( 0.5f ); - } - else if ( info.GetDamageType() & DMG_BULLET ) - { - info.ScaleDamage( 0.25f ); - } - - // Make sure we haven't rounded down to a minimal amount - if ( info.GetDamage() < 1.0f ) - { - info.SetDamage( 1.0f ); - } - - BaseClass::TraceAttack( info, vecDir, ptr ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTask - -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::StartTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_ANTLIONGUARD_SET_FLINCH_ACTIVITY: - SetIdealActivity( (Activity) m_nFlinchActivity ); - break; - - case TASK_ANTLIONGUARD_SUMMON: - SummonAntlions(); - m_OnSummon.FireOutput( this, this, 0 ); - TaskComplete(); - break; - - case TASK_ANTLIONGUARD_SHOVE_PHYSOBJECT: - { - if ( ( m_hPhysicsTarget == NULL ) || ( GetEnemy() == NULL ) ) - { - TaskFail( "Tried to shove a NULL physics target!\n" ); - break; - } - - //Get the direction and distance to our thrown object - Vector dirToTarget = ( m_hPhysicsTarget->WorldSpaceCenter() - WorldSpaceCenter() ); - float distToTarget = VectorNormalize( dirToTarget ); - dirToTarget.z = 0; - - //Validate it's still close enough to shove - //FIXME: Real numbers - if ( distToTarget > 256.0f ) - { - RememberFailedPhysicsTarget( m_hPhysicsTarget ); - m_hPhysicsTarget = NULL; - - TaskFail( "Shove target moved\n" ); - break; - } - - //Validate its offset from our facing - float targetYaw = UTIL_VecToYaw( dirToTarget ); - float offset = UTIL_AngleDiff( targetYaw, UTIL_AngleMod( GetLocalAngles().y ) ); - - if ( fabs( offset ) > 55 ) - { - RememberFailedPhysicsTarget( m_hPhysicsTarget ); - m_hPhysicsTarget = NULL; - - TaskFail( "Shove target off-center\n" ); - break; - } - - //Blend properly - SetPoseParameter( m_poseThrow, offset ); - - //Start playing the animation - SetActivity( ACT_ANTLIONGUARD_SHOVE_PHYSOBJECT ); - } - break; - - case TASK_ANTLIONGUARD_FIND_PHYSOBJECT: - { - if ( m_bInCavern && !m_bPreferPhysicsAttack ) - { - TaskFail( "Cavern guard is not allowed to use physics attacks." ); - } - - // Force the antlion guard to find a physobject - m_flPhysicsCheckTime = 0; - UpdatePhysicsTarget( false, (100*12) ); - if ( m_hPhysicsTarget ) - { - TaskComplete(); - } - else - { - TaskFail( "Failed to find a physobject.\n" ); - } - } - break; - - case TASK_ANTLIONGUARD_GET_PATH_TO_PHYSOBJECT: - { - if ( ( m_hPhysicsTarget == NULL ) || ( GetEnemy() == NULL ) ) - { - TaskFail( "Tried to find a path to NULL physics target!\n" ); - break; - } - - Vector vecGoalPos = m_vecPhysicsHitPosition; - AI_NavGoal_t goal( GOALTYPE_LOCATION, vecGoalPos, ACT_RUN ); - - if ( GetNavigator()->SetGoal( goal ) ) - { - if ( g_debug_antlionguard.GetInt() == 1 ) - { - NDebugOverlay::Cross3D( vecGoalPos, Vector(8,8,8), -Vector(8,8,8), 0, 255, 0, true, 2.0f ); - NDebugOverlay::Line( vecGoalPos, m_hPhysicsTarget->WorldSpaceCenter(), 0, 255, 0, true, 2.0f ); - NDebugOverlay::Line( m_hPhysicsTarget->WorldSpaceCenter(), GetEnemy()->WorldSpaceCenter(), 0, 255, 0, true, 2.0f ); - } - - // Face the enemy - GetNavigator()->SetArrivalDirection( GetEnemy() ); - TaskComplete(); - } - else - { - if ( g_debug_antlionguard.GetInt() == 1 ) - { - NDebugOverlay::Cross3D( vecGoalPos, Vector(8,8,8), -Vector(8,8,8), 255, 0, 0, true, 2.0f ); - NDebugOverlay::Line( vecGoalPos, m_hPhysicsTarget->WorldSpaceCenter(), 255, 0, 0, true, 2.0f ); - NDebugOverlay::Line( m_hPhysicsTarget->WorldSpaceCenter(), GetEnemy()->WorldSpaceCenter(), 255, 0, 0, true, 2.0f ); - } - - RememberFailedPhysicsTarget( m_hPhysicsTarget ); - m_hPhysicsTarget = NULL; - TaskFail( "Unable to navigate to physics attack target!\n" ); - break; - } - - //!!!HACKHACK - this is a hack that covers a bug in antlion guard physics target selection! (Tracker #77601) - // This piece of code (combined with some code in GatherConditions) COVERS THE BUG by escaping the schedule - // if 30 seconds have passed (it should never take this long for the guard to get to an object and hit it). - // It's too scary to figure out why this particular antlion guard can't get to its object, but we're shipping - // like, tomorrow. (sjb) 8/22/2007 - m_flWaitFinished = gpGlobals->curtime + 30.0f; - } - break; - - case TASK_ANTLIONGUARD_CHARGE: - { - // HACK: Because the guard stops running his normal blended movement - // here, he also needs to remove his blended movement layers! - GetMotor()->MoveStop(); - - SetActivity( ACT_ANTLIONGUARD_CHARGE_START ); - m_bDecidedNotToStop = false; - } - break; - - - case TASK_ANTLIONGUARD_GET_PATH_TO_CHARGE_POSITION: - { - if ( !m_hChargeTargetPosition ) - { - TaskFail( "Tried to find a charge position without one specified.\n" ); - break; - } - - // Move to the charge position - AI_NavGoal_t goal( GOALTYPE_LOCATION, m_hChargeTargetPosition->GetAbsOrigin(), ACT_RUN ); - if ( GetNavigator()->SetGoal( goal ) ) - { - // We want to face towards the charge target - Vector vecDir = m_hChargeTarget->GetAbsOrigin() - m_hChargeTargetPosition->GetAbsOrigin(); - VectorNormalize( vecDir ); - vecDir.z = 0; - GetNavigator()->SetArrivalDirection( vecDir ); - TaskComplete(); - } - else - { - m_hChargeTarget = NULL; - m_hChargeTargetPosition = NULL; - TaskFail( FAIL_NO_ROUTE ); - } - } - break; - - case TASK_ANTLIONGUARD_GET_PATH_TO_NEAREST_NODE: - { - if ( !GetEnemy() ) - { - TaskFail( FAIL_NO_ENEMY ); - break; - } - - // Find the nearest node to the enemy - int node = GetNavigator()->GetNetwork()->NearestNodeToPoint( this, GetEnemy()->GetAbsOrigin(), false ); - CAI_Node *pNode = GetNavigator()->GetNetwork()->GetNode( node ); - if( pNode == NULL ) - { - TaskFail( FAIL_NO_ROUTE ); - break; - } - - Vector vecNodePos = pNode->GetPosition( GetHullType() ); - AI_NavGoal_t goal( GOALTYPE_LOCATION, vecNodePos, ACT_RUN ); - if ( GetNavigator()->SetGoal( goal ) ) - { - GetNavigator()->SetArrivalDirection( GetEnemy() ); - TaskComplete(); - break; - } - - - TaskFail( FAIL_NO_ROUTE ); - break; - } - break; - - case TASK_ANTLIONGUARD_GET_CHASE_PATH_ENEMY_TOLERANCE: - { - // Chase the enemy, but allow local navigation to succeed if it gets within the goal tolerance - GetNavigator()->SetLocalSucceedOnWithinTolerance( true ); - - if ( GetNavigator()->SetGoal( GOALTYPE_ENEMY ) ) - { - TaskComplete(); - } - else - { - RememberUnreachable(GetEnemy()); - TaskFail(FAIL_NO_ROUTE); - } - - GetNavigator()->SetLocalSucceedOnWithinTolerance( false ); - } - break; - - case TASK_ANTLIONGUARD_OPPORTUNITY_THROW: - { - // If we've got some live antlions, look for a physics object to throw - if ( m_iNumLiveAntlions >= 2 && RandomFloat(0,1) > 0.5 ) - { - m_FailedPhysicsTargets.RemoveAll(); - UpdatePhysicsTarget( false, m_bPreferPhysicsAttack ? (100*12) : ANTLIONGUARD_FARTHEST_PHYSICS_OBJECT ); - if ( HasCondition( COND_ANTLIONGUARD_PHYSICS_TARGET ) && !m_bInCavern ) - { - SetSchedule( SCHED_ANTLIONGUARD_PHYSICS_ATTACK ); - } - } - - TaskComplete(); - } - break; - - default: - BaseClass::StartTask(pTask); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Calculate & apply damage & force for a charge to a target. -// Done outside of the guard because we need to do this inside a trace filter. -//----------------------------------------------------------------------------- -void ApplyChargeDamage( CBaseEntity *pAntlionGuard, CBaseEntity *pTarget, float flDamage ) -{ - Vector attackDir = ( pTarget->WorldSpaceCenter() - pAntlionGuard->WorldSpaceCenter() ); - VectorNormalize( attackDir ); - Vector offset = RandomVector( -32, 32 ) + pTarget->WorldSpaceCenter(); - - // Generate enough force to make a 75kg guy move away at 700 in/sec - Vector vecForce = attackDir * ImpulseScale( 75, 700 ); - - // Deal the damage - CTakeDamageInfo info( pAntlionGuard, pAntlionGuard, vecForce, offset, flDamage, DMG_CLUB ); - pTarget->TakeDamage( info ); - -#if HL2_EPISODIC - // If I am a cavern guard attacking the player, and he still lives, then poison him too. - Assert( dynamic_cast(pAntlionGuard) ); - - if ( static_cast(pAntlionGuard)->IsInCavern() && pTarget->IsPlayer() && pTarget->IsAlive() && pTarget->m_iHealth > ANTLIONGUARD_POISON_TO) - { - // That didn't finish them. Take them down to one point with poison damage. It'll heal. - pTarget->TakeDamage( CTakeDamageInfo( pAntlionGuard, pAntlionGuard, pTarget->m_iHealth - ANTLIONGUARD_POISON_TO, DMG_POISON ) ); - } -#endif - -} - -//----------------------------------------------------------------------------- -// Purpose: A simple trace filter class to skip small moveable physics objects -//----------------------------------------------------------------------------- -class CTraceFilterSkipPhysics : public CTraceFilter -{ -public: - // It does have a base, but we'll never network anything below here.. - DECLARE_CLASS_NOBASE( CTraceFilterSkipPhysics ); - - CTraceFilterSkipPhysics( const IHandleEntity *passentity, int collisionGroup, float minMass ) - : m_pPassEnt(passentity), m_collisionGroup(collisionGroup), m_minMass(minMass) - { - } - virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) - { - if ( !StandardFilterRules( pHandleEntity, contentsMask ) ) - return false; - - if ( !PassServerEntityFilter( pHandleEntity, m_pPassEnt ) ) - return false; - - // Don't test if the game code tells us we should ignore this collision... - CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); - if ( pEntity ) - { - if ( !pEntity->ShouldCollide( m_collisionGroup, contentsMask ) ) - return false; - - if ( !g_pGameRules->ShouldCollide( m_collisionGroup, pEntity->GetCollisionGroup() ) ) - return false; - - // don't test small moveable physics objects (unless it's an NPC) - if ( !pEntity->IsNPC() && pEntity->GetMoveType() == MOVETYPE_VPHYSICS ) - { - IPhysicsObject *pPhysics = pEntity->VPhysicsGetObject(); - Assert(pPhysics); - if ( pPhysics->IsMoveable() && pPhysics->GetMass() < m_minMass ) - return false; - } - - // If we hit an antlion, don't stop, but kill it - if ( pEntity->Classify() == CLASS_ANTLION ) - { - CBaseEntity *pGuard = (CBaseEntity*)EntityFromEntityHandle( m_pPassEnt ); - ApplyChargeDamage( pGuard, pEntity, pEntity->GetHealth() ); - return false; - } - } - - return true; - } - - - -private: - const IHandleEntity *m_pPassEnt; - int m_collisionGroup; - float m_minMass; -}; - -inline void TraceHull_SkipPhysics( const Vector &vecAbsStart, const Vector &vecAbsEnd, const Vector &hullMin, - const Vector &hullMax, unsigned int mask, const CBaseEntity *ignore, - int collisionGroup, trace_t *ptr, float minMass ) -{ - Ray_t ray; - ray.Init( vecAbsStart, vecAbsEnd, hullMin, hullMax ); - CTraceFilterSkipPhysics traceFilter( ignore, collisionGroup, minMass ); - enginetrace->TraceRay( ray, mask, &traceFilter, ptr ); -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if our charge target is right in front of the guard -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_AntlionGuard::EnemyIsRightInFrontOfMe( CBaseEntity **pEntity ) -{ - if ( !GetEnemy() ) - return false; - - if ( (GetEnemy()->WorldSpaceCenter() - WorldSpaceCenter()).LengthSqr() < (156*156) ) - { - Vector vecLOS = ( GetEnemy()->GetAbsOrigin() - GetAbsOrigin() ); - vecLOS.z = 0; - VectorNormalize( vecLOS ); - Vector vBodyDir = BodyDirection2D(); - if ( DotProduct( vecLOS, vBodyDir ) > 0.8 ) - { - // He's in front of me, and close. Make sure he's not behind a wall. - trace_t tr; - UTIL_TraceLine( WorldSpaceCenter(), GetEnemy()->EyePosition(), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - if ( tr.m_pEnt == GetEnemy() ) - { - *pEntity = tr.m_pEnt; - return true; - } - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: While charging, look ahead and see if we're going to run into anything. -// If we are, start the gesture so it looks like we're anticipating the hit. -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::ChargeLookAhead( void ) -{ - trace_t tr; - Vector vecForward; - GetVectors( &vecForward, NULL, NULL ); - Vector vecTestPos = GetAbsOrigin() + ( vecForward * m_flGroundSpeed * 0.75 ); - Vector testHullMins = GetHullMins(); - testHullMins.z += (StepHeight() * 2); - TraceHull_SkipPhysics( GetAbsOrigin(), vecTestPos, testHullMins, GetHullMaxs(), MASK_SHOT_HULL, this, COLLISION_GROUP_NONE, &tr, VPhysicsGetObject()->GetMass() * 0.5 ); - - //NDebugOverlay::Box( tr.startpos, testHullMins, GetHullMaxs(), 0, 255, 0, true, 0.1f ); - //NDebugOverlay::Box( vecTestPos, testHullMins, GetHullMaxs(), 255, 0, 0, true, 0.1f ); - - if ( tr.fraction != 1.0 ) - { - // Start playing the hit animation - AddGesture( ACT_ANTLIONGUARD_CHARGE_ANTICIPATION ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Handles the guard charging into something. Returns true if it hit the world. -//----------------------------------------------------------------------------- -bool CNPC_AntlionGuard::HandleChargeImpact( Vector vecImpact, CBaseEntity *pEntity ) -{ - // Cause a shock wave from this point which will disrupt nearby physics objects - ImpactShock( vecImpact, 128, 350 ); - - // Did we hit anything interesting? - if ( !pEntity || pEntity->IsWorld() ) - { - // Robin: Due to some of the finicky details in the motor, the guard will hit - // the world when it is blocked by our enemy when trying to step up - // during a moveprobe. To get around this, we see if the enemy's within - // a volume in front of the guard when we hit the world, and if he is, - // we hit him anyway. - EnemyIsRightInFrontOfMe( &pEntity ); - - // Did we manage to find him? If not, increment our charge miss count and abort. - if ( pEntity->IsWorld() ) - { - m_iChargeMisses++; - return true; - } - } - - // Hit anything we don't like - if ( IRelationType( pEntity ) == D_HT && ( GetNextAttack() < gpGlobals->curtime ) ) - { - EmitSound( "NPC_AntlionGuard.Shove" ); - - if ( !IsPlayingGesture( ACT_ANTLIONGUARD_CHARGE_HIT ) ) - { - RestartGesture( ACT_ANTLIONGUARD_CHARGE_HIT ); - } - - ChargeDamage( pEntity ); - - pEntity->ApplyAbsVelocityImpulse( ( BodyDirection2D() * 400 ) + Vector( 0, 0, 200 ) ); - - if ( !pEntity->IsAlive() && GetEnemy() == pEntity ) - { - SetEnemy( NULL ); - } - - SetNextAttack( gpGlobals->curtime + 2.0f ); - SetActivity( ACT_ANTLIONGUARD_CHARGE_STOP ); - - // We've hit something, so clear our miss count - m_iChargeMisses = 0; - return false; - } - - // Hit something we don't hate. If it's not moveable, crash into it. - if ( pEntity->GetMoveType() == MOVETYPE_NONE || pEntity->GetMoveType() == MOVETYPE_PUSH ) - return true; - - // If it's a vphysics object that's too heavy, crash into it too. - if ( pEntity->GetMoveType() == MOVETYPE_VPHYSICS ) - { - IPhysicsObject *pPhysics = pEntity->VPhysicsGetObject(); - if ( pPhysics ) - { - // If the object is being held by the player, knock it out of his hands - if ( pPhysics->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - { - Pickup_ForcePlayerToDropThisObject( pEntity ); - return false; - } - - if ( (!pPhysics->IsMoveable() || pPhysics->GetMass() > VPhysicsGetObject()->GetMass() * 0.5f ) ) - return true; - } - } - - return false; - - /* - - ROBIN: Wrote & then removed this. If we want to have large rocks that the guard - should smack around, then we should enable it. - - else - { - // If we hit a physics prop, smack the crap out of it. (large rocks) - // Factor the object mass into it, because we want to move it no matter how heavy it is. - if ( pEntity->GetMoveType() == MOVETYPE_VPHYSICS ) - { - CTakeDamageInfo info( this, this, 250, DMG_BLAST ); - info.SetDamagePosition( vecImpact ); - float flForce = ImpulseScale( pEntity->VPhysicsGetObject()->GetMass(), 250 ); - flForce *= random->RandomFloat( 0.85, 1.15 ); - - // Calculate the vector and stuff it into the takedamageinfo - Vector vecForce = BodyDirection3D(); - VectorNormalize( vecForce ); - vecForce *= flForce; - vecForce *= phys_pushscale.GetFloat(); - info.SetDamageForce( vecForce ); - - pEntity->VPhysicsTakeDamage( info ); - } - } - */ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CNPC_AntlionGuard::ChargeSteer( void ) -{ - trace_t tr; - Vector testPos, steer, forward, right; - QAngle angles; - const float testLength = m_flGroundSpeed * 0.15f; - - //Get our facing - GetVectors( &forward, &right, NULL ); - - steer = forward; - - const float faceYaw = UTIL_VecToYaw( forward ); - - //Offset right - VectorAngles( forward, angles ); - angles[YAW] += 45.0f; - AngleVectors( angles, &forward ); - - //Probe out - testPos = GetAbsOrigin() + ( forward * testLength ); - - //Offset by step height - Vector testHullMins = GetHullMins(); - testHullMins.z += (StepHeight() * 2); - - //Probe - TraceHull_SkipPhysics( GetAbsOrigin(), testPos, testHullMins, GetHullMaxs(), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr, VPhysicsGetObject()->GetMass() * 0.5f ); - - //Debug info - if ( g_debug_antlionguard.GetInt() == 1 ) - { - if ( tr.fraction == 1.0f ) - { - NDebugOverlay::BoxDirection( GetAbsOrigin(), testHullMins, GetHullMaxs() + Vector(testLength,0,0), forward, 0, 255, 0, 8, 0.1f ); - } - else - { - NDebugOverlay::BoxDirection( GetAbsOrigin(), testHullMins, GetHullMaxs() + Vector(testLength,0,0), forward, 255, 0, 0, 8, 0.1f ); - } - } - - //Add in this component - steer += ( right * 0.5f ) * ( 1.0f - tr.fraction ); - - //Offset left - angles[YAW] -= 90.0f; - AngleVectors( angles, &forward ); - - //Probe out - testPos = GetAbsOrigin() + ( forward * testLength ); - - // Probe - TraceHull_SkipPhysics( GetAbsOrigin(), testPos, testHullMins, GetHullMaxs(), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr, VPhysicsGetObject()->GetMass() * 0.5f ); - - //Debug - if ( g_debug_antlionguard.GetInt() == 1 ) - { - if ( tr.fraction == 1.0f ) - { - NDebugOverlay::BoxDirection( GetAbsOrigin(), testHullMins, GetHullMaxs() + Vector(testLength,0,0), forward, 0, 255, 0, 8, 0.1f ); - } - else - { - NDebugOverlay::BoxDirection( GetAbsOrigin(), testHullMins, GetHullMaxs() + Vector(testLength,0,0), forward, 255, 0, 0, 8, 0.1f ); - } - } - - //Add in this component - steer -= ( right * 0.5f ) * ( 1.0f - tr.fraction ); - - //Debug - if ( g_debug_antlionguard.GetInt() == 1 ) - { - NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + ( steer * 512.0f ), 255, 255, 0, true, 0.1f ); - NDebugOverlay::Cross3D( GetAbsOrigin() + ( steer * 512.0f ), Vector(2,2,2), -Vector(2,2,2), 255, 255, 0, true, 0.1f ); - - NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + ( BodyDirection3D() * 256.0f ), 255, 0, 255, true, 0.1f ); - NDebugOverlay::Cross3D( GetAbsOrigin() + ( BodyDirection3D() * 256.0f ), Vector(2,2,2), -Vector(2,2,2), 255, 0, 255, true, 0.1f ); - } - - return UTIL_AngleDiff( UTIL_VecToYaw( steer ), faceYaw ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTask - -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::RunTask( const Task_t *pTask ) -{ - switch (pTask->iTask) - { - case TASK_ANTLIONGUARD_SET_FLINCH_ACTIVITY: - - AutoMovement( ); - - if ( IsActivityFinished() ) - { - TaskComplete(); - } - break; - - case TASK_ANTLIONGUARD_SHOVE_PHYSOBJECT: - - if ( IsActivityFinished() ) - { - TaskComplete(); - } - - break; - - /* - case TASK_RUN_PATH: - { - - - } - break; - */ - - case TASK_ANTLIONGUARD_CHARGE: - { - Activity eActivity = GetActivity(); - - // See if we're trying to stop after hitting/missing our target - if ( eActivity == ACT_ANTLIONGUARD_CHARGE_STOP || eActivity == ACT_ANTLIONGUARD_CHARGE_CRASH ) - { - if ( IsActivityFinished() ) - { - TaskComplete(); - return; - } - - // Still in the process of slowing down. Run movement until it's done. - AutoMovement(); - return; - } - - // Check for manual transition - if ( ( eActivity == ACT_ANTLIONGUARD_CHARGE_START ) && ( IsActivityFinished() ) ) - { - SetActivity( ACT_ANTLIONGUARD_CHARGE_RUN ); - } - - // See if we're still running - if ( eActivity == ACT_ANTLIONGUARD_CHARGE_RUN || eActivity == ACT_ANTLIONGUARD_CHARGE_START ) - { - if ( HasCondition( COND_NEW_ENEMY ) || HasCondition( COND_LOST_ENEMY ) || HasCondition( COND_ENEMY_DEAD ) ) - { - SetActivity( ACT_ANTLIONGUARD_CHARGE_STOP ); - return; - } - else - { - if ( GetEnemy() != NULL ) - { - Vector goalDir = ( GetEnemy()->GetAbsOrigin() - GetAbsOrigin() ); - VectorNormalize( goalDir ); - - if ( DotProduct( BodyDirection2D(), goalDir ) < 0.25f ) - { - if ( !m_bDecidedNotToStop ) - { - // We've missed the target. Randomly decide not to stop, which will cause - // the guard to just try and swing around for another pass. - m_bDecidedNotToStop = true; - if ( RandomFloat(0,1) > 0.3 ) - { - m_iChargeMisses++; - SetActivity( ACT_ANTLIONGUARD_CHARGE_STOP ); - } - } - } - else - { - m_bDecidedNotToStop = false; - } - } - } - } - - // Steer towards our target - float idealYaw; - if ( GetEnemy() == NULL ) - { - idealYaw = GetMotor()->GetIdealYaw(); - } - else - { - idealYaw = CalcIdealYaw( GetEnemy()->GetAbsOrigin() ); - } - - // Add in our steering offset - idealYaw += ChargeSteer(); - - // Turn to face - GetMotor()->SetIdealYawAndUpdate( idealYaw ); - - // See if we're going to run into anything soon - ChargeLookAhead(); - - // Let our animations simply move us forward. Keep the result - // of the movement so we know whether we've hit our target. - AIMoveTrace_t moveTrace; - if ( AutoMovement( GetEnemy(), &moveTrace ) == false ) - { - // Only stop if we hit the world - if ( HandleChargeImpact( moveTrace.vEndPosition, moveTrace.pObstruction ) ) - { - // If we're starting up, this is an error - if ( eActivity == ACT_ANTLIONGUARD_CHARGE_START ) - { - TaskFail( "Unable to make initial movement of charge\n" ); - return; - } - - // Crash unless we're trying to stop already - if ( eActivity != ACT_ANTLIONGUARD_CHARGE_STOP ) - { - if ( moveTrace.fStatus == AIMR_BLOCKED_WORLD && moveTrace.vHitNormal == vec3_origin ) - { - SetActivity( ACT_ANTLIONGUARD_CHARGE_STOP ); - } - else - { - SetActivity( ACT_ANTLIONGUARD_CHARGE_CRASH ); - } - } - } - else if ( moveTrace.pObstruction ) - { - // If we hit an antlion, don't stop, but kill it - if ( moveTrace.pObstruction->Classify() == CLASS_ANTLION ) - { - if ( FClassnameIs( moveTrace.pObstruction, "npc_antlionguard" ) ) - { - // Crash unless we're trying to stop already - if ( eActivity != ACT_ANTLIONGUARD_CHARGE_STOP ) - { - SetActivity( ACT_ANTLIONGUARD_CHARGE_STOP ); - } - } - else - { - ApplyChargeDamage( this, moveTrace.pObstruction, moveTrace.pObstruction->GetHealth() ); - } - } - } - } - } - break; - - case TASK_WAIT_FOR_MOVEMENT: - { - // the cavern antlion can clothesline gordon - if ( m_bInCavern ) - { - - // See if we're going to run into anything soon - ChargeLookAhead(); - - if ( HasCondition(COND_CAN_MELEE_ATTACK1) ) - { - - - CBaseEntity *pEntity = GetEnemy(); - - if (pEntity && pEntity->IsPlayer()) - { - EmitSound( "NPC_AntlionGuard.Shove" ); - - if ( !IsPlayingGesture( ACT_ANTLIONGUARD_CHARGE_HIT ) ) - { - RestartGesture( ACT_ANTLIONGUARD_CHARGE_HIT ); - } - - ChargeDamage( pEntity ); - - pEntity->ApplyAbsVelocityImpulse( ( BodyDirection2D() * 400 ) + Vector( 0, 0, 200 ) ); - - if ( !pEntity->IsAlive() && GetEnemy() == pEntity ) - { - SetEnemy( NULL ); - } - - SetNextAttack( gpGlobals->curtime + 2.0f ); - SetActivity( ACT_ANTLIONGUARD_CHARGE_STOP ); - - // We've hit something, so clear our miss count - m_iChargeMisses = 0; - - AutoMovement(); - TaskComplete(); - return; - } - } - } - - BaseClass::RunTask( pTask ); - - } - break; - - default: - BaseClass::RunTask(pTask); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Summon antlions around the guard -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::SummonAntlions( void ) -{ - // We want to spawn them around the guard - Vector vecForward, vecRight; - AngleVectors( QAngle(0,GetAbsAngles().y,0), &vecForward, &vecRight, NULL ); - - // Spawn positions - struct spawnpos_t - { - float flForward; - float flRight; - }; - - spawnpos_t sAntlionSpawnPositions[] = - { - { 0, 200 }, - { 0, -200 }, - { 128, 128 }, - { 128, -128 }, - { -128, 128 }, - { -128, -128 }, - { 200, 0 }, - { -200, 0 }, - }; - - // Only spawn up to our max count - int iSpawnPoint = 0; - for ( int i = 0; (m_iNumLiveAntlions < ANTLIONGUARD_SUMMON_COUNT) && (iSpawnPoint < (int)ARRAYSIZE(sAntlionSpawnPositions)); i++ ) - { - // Determine spawn position for the antlion - Vector vecSpawn = GetAbsOrigin() + ( sAntlionSpawnPositions[iSpawnPoint].flForward * vecForward ) + ( sAntlionSpawnPositions[iSpawnPoint].flRight * vecRight ); - iSpawnPoint++; - // Randomise it a little - vecSpawn.x += RandomFloat( -64, 64 ); - vecSpawn.y += RandomFloat( -64, 64 ); - vecSpawn.z += 64; - - // Make sure it's clear, and make sure we hit something - trace_t tr; - UTIL_TraceHull( vecSpawn, vecSpawn - Vector(0,0,128), NAI_Hull::Mins( HULL_MEDIUM ), NAI_Hull::Maxs( HULL_MEDIUM ), MASK_NPCSOLID, NULL, COLLISION_GROUP_NONE, &tr ); - if ( tr.startsolid || tr.allsolid || tr.fraction == 1.0 ) - { - if ( g_debug_antlionguard.GetInt() == 2 ) - { - NDebugOverlay::Box( tr.endpos, NAI_Hull::Mins( HULL_MEDIUM ), NAI_Hull::Maxs( HULL_MEDIUM ), 255, 0, 0, true, 5.0f ); - } - continue; - } - - // Ensure it's dirt or sand - const surfacedata_t *pdata = physprops->GetSurfaceData( tr.surface.surfaceProps ); - if ( ( pdata->game.material != CHAR_TEX_DIRT ) && ( pdata->game.material != CHAR_TEX_SAND ) ) - { - if ( g_debug_antlionguard.GetInt() == 2 ) - { - NDebugOverlay::Box( tr.endpos, NAI_Hull::Mins( HULL_MEDIUM ), NAI_Hull::Maxs( HULL_MEDIUM ), 255, 128, 128, true, 5.0f ); - } - continue; - } - - // Make sure the guard can see it - trace_t tr_vis; - UTIL_TraceLine( WorldSpaceCenter(), tr.endpos, MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr_vis ); - if ( tr_vis.fraction != 1.0 ) - { - if ( g_debug_antlionguard.GetInt() == 2 ) - { - NDebugOverlay::Line( WorldSpaceCenter(), tr.endpos, 255, 0, 0, true, 5.0f ); - } - continue; - } - - CAI_BaseNPC *pent = (CAI_BaseNPC*)CreateEntityByName( "npc_antlion" ); - if ( !pent ) - break; - - CNPC_Antlion *pAntlion = assert_cast(pent); - - if ( g_debug_antlionguard.GetInt() == 2 ) - { - NDebugOverlay::Box( tr.endpos, NAI_Hull::Mins( HULL_MEDIUM ), NAI_Hull::Maxs( HULL_MEDIUM ), 0, 255, 0, true, 5.0f ); - NDebugOverlay::Line( WorldSpaceCenter(), tr.endpos, 0, 255, 0, true, 5.0f ); - } - - vecSpawn = tr.endpos; - pAntlion->SetAbsOrigin( vecSpawn ); - - // Start facing our enemy if we have one, otherwise just match the guard. - Vector vecFacing = vecForward; - if ( GetEnemy() ) - { - vecFacing = GetEnemy()->GetAbsOrigin() - GetAbsOrigin(); - VectorNormalize( vecFacing ); - } - QAngle vecAngles; - VectorAngles( vecFacing, vecAngles ); - pAntlion->SetAbsAngles( vecAngles ); - - pAntlion->AddSpawnFlags( SF_NPC_FALL_TO_GROUND ); - pAntlion->AddSpawnFlags( SF_NPC_FADE_CORPSE ); - - // Make the antlion fire my input when he dies - pAntlion->KeyValue( "OnDeath", UTIL_VarArgs("%s,SummonedAntlionDied,,0,-1", STRING(GetEntityName())) ); - - // Start the antlion burrowed, and tell him to come up - pAntlion->m_bStartBurrowed = true; - DispatchSpawn( pAntlion ); - pAntlion->Activate(); - g_EventQueue.AddEvent( pAntlion, "Unburrow", RandomFloat(0.1, 1.0), this, this ); - - // Add it to our squad - if ( GetSquad() != NULL ) - { - GetSquad()->AddToSquad( pAntlion ); - } - - // Set the antlion's enemy to our enemy - if ( GetEnemy() ) - { - pAntlion->SetEnemy( GetEnemy() ); - pAntlion->SetState( NPC_STATE_COMBAT ); - pAntlion->UpdateEnemyMemory( GetEnemy(), GetEnemy()->GetAbsOrigin() ); - } - - m_iNumLiveAntlions++; - } - - if ( g_debug_antlionguard.GetInt() == 2 ) - { - Msg("Guard summoned antlion count: %d\n", m_iNumLiveAntlions ); - } - - if ( m_iNumLiveAntlions > 2 ) - { - m_flNextSummonTime = gpGlobals->curtime + RandomFloat( 15,20 ); - } - else - { - m_flNextSummonTime = gpGlobals->curtime + RandomFloat( 10,15 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::FoundEnemy( void ) -{ - m_flAngerNoiseTime = gpGlobals->curtime + 2.0f; - SetState( NPC_STATE_COMBAT ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::LostEnemy( void ) -{ - m_flSearchNoiseTime = gpGlobals->curtime + 2.0f; - SetState( NPC_STATE_ALERT ); - - m_OnLostPlayer.FireOutput( this, this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::InputSetShoveTarget( inputdata_t &inputdata ) -{ - if ( IsAlive() == false ) - return; - - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, inputdata.value.String(), NULL, inputdata.pActivator, inputdata.pCaller ); - - if ( pTarget == NULL ) - { - Warning( "**Guard %s cannot find shove target %s\n", GetClassname(), inputdata.value.String() ); - m_hShoveTarget = NULL; - return; - } - - m_hShoveTarget = pTarget; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::InputSetChargeTarget( inputdata_t &inputdata ) -{ - if ( !IsAlive() ) - return; - - // Pull the target & position out of the string - char parseString[255]; - Q_strncpy(parseString, inputdata.value.String(), sizeof(parseString)); - - // Get charge target name - char *pszParam = strtok(parseString," "); - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, pszParam, NULL, inputdata.pActivator, inputdata.pCaller ); - if ( !pTarget ) - { - Warning( "ERROR: Guard %s cannot find charge target '%s'\n", STRING(GetEntityName()), pszParam ); - return; - } - - // Get the charge position name - pszParam = strtok(NULL," "); - CBaseEntity *pPosition = gEntList.FindEntityByName( NULL, pszParam, NULL, inputdata.pActivator, inputdata.pCaller ); - if ( !pPosition ) - { - Warning( "ERROR: Guard %s cannot find charge position '%s'\nMake sure you've specified the parameters as [target start]!\n", STRING(GetEntityName()), pszParam ); - return; - } - - // Make sure we don't stack charge targets - if ( m_hChargeTarget ) - { - if ( GetEnemy() == m_hChargeTarget ) - { - SetEnemy( NULL ); - } - } - - SetCondition( COND_ANTLIONGUARD_HAS_CHARGE_TARGET ); - m_hChargeTarget = pTarget; - m_hChargeTargetPosition = pPosition; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::InputClearChargeTarget( inputdata_t &inputdata ) -{ - m_hChargeTarget = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : baseAct - -// Output : Activity -//----------------------------------------------------------------------------- -Activity CNPC_AntlionGuard::NPC_TranslateActivity( Activity baseAct ) -{ - //See which run to use - if ( ( baseAct == ACT_RUN ) && IsCurSchedule( SCHED_ANTLIONGUARD_CHARGE ) ) - return (Activity) ACT_ANTLIONGUARD_CHARGE_RUN; - - // Do extra code if we're trying to close on an enemy in a confined space (unless scripted) - if ( hl2_episodic.GetBool() && m_bInCavern && baseAct == ACT_RUN && IsInAScript() == false ) - return (Activity) ACT_ANTLIONGUARD_CHARGE_RUN; - - if ( ( baseAct == ACT_RUN ) && ( m_iHealth <= (m_iMaxHealth/4) ) ) - return (Activity) ACT_ANTLIONGUARD_RUN_HURT; - - return baseAct; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_AntlionGuard::ShouldWatchEnemy( void ) -{ - Activity nActivity = GetActivity(); - - if ( ( nActivity == ACT_ANTLIONGUARD_SEARCH ) || - ( nActivity == ACT_ANTLIONGUARD_PEEK_ENTER ) || - ( nActivity == ACT_ANTLIONGUARD_PEEK_EXIT ) || - ( nActivity == ACT_ANTLIONGUARD_PEEK1 ) || - ( nActivity == ACT_ANTLIONGUARD_PEEK_SIGHTED ) || - ( nActivity == ACT_ANTLIONGUARD_SHOVE_PHYSOBJECT ) || - ( nActivity == ACT_ANTLIONGUARD_PHYSHIT_FR ) || - ( nActivity == ACT_ANTLIONGUARD_PHYSHIT_FL ) || - ( nActivity == ACT_ANTLIONGUARD_PHYSHIT_RR ) || - ( nActivity == ACT_ANTLIONGUARD_PHYSHIT_RL ) || - ( nActivity == ACT_ANTLIONGUARD_CHARGE_CRASH ) || - ( nActivity == ACT_ANTLIONGUARD_CHARGE_HIT ) || - ( nActivity == ACT_ANTLIONGUARD_CHARGE_ANTICIPATION ) ) - { - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::UpdateHead( void ) -{ - float yaw = GetPoseParameter( m_poseHead_Yaw ); - float pitch = GetPoseParameter( m_poseHead_Pitch ); - - // If we should be watching our enemy, turn our head - if ( ShouldWatchEnemy() && ( GetEnemy() != NULL ) ) - { - Vector enemyDir = GetEnemy()->WorldSpaceCenter() - WorldSpaceCenter(); - VectorNormalize( enemyDir ); - - float angle = VecToYaw( BodyDirection3D() ); - float angleDiff = VecToYaw( enemyDir ); - angleDiff = UTIL_AngleDiff( angleDiff, angle + yaw ); - - SetPoseParameter( m_poseHead_Yaw, UTIL_Approach( yaw + angleDiff, yaw, 50 ) ); - - angle = UTIL_VecToPitch( BodyDirection3D() ); - angleDiff = UTIL_VecToPitch( enemyDir ); - angleDiff = UTIL_AngleDiff( angleDiff, angle + pitch ); - - SetPoseParameter( m_poseHead_Pitch, UTIL_Approach( pitch + angleDiff, pitch, 50 ) ); - } - else - { - // Otherwise turn the head back to its normal position - SetPoseParameter( m_poseHead_Yaw, UTIL_Approach( 0, yaw, 10 ) ); - SetPoseParameter( m_poseHead_Pitch, UTIL_Approach( 0, pitch, 10 ) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::MaintainPhysicsTarget( void ) -{ - if ( m_hPhysicsTarget == NULL || GetEnemy() == NULL ) - return; - - // Update our current target to make sure it's still valid - float flTargetDistSqr = ( m_hPhysicsTarget->WorldSpaceCenter() - m_vecPhysicsTargetStartPos ).LengthSqr(); - bool bTargetMoved = ( flTargetDistSqr > Square(30*12.0f) ); - bool bEnemyCloser = ( ( GetEnemy()->GetAbsOrigin() - GetAbsOrigin() ).LengthSqr() <= flTargetDistSqr ); - - // Make sure this hasn't moved too far or that the player is now closer - if ( bTargetMoved || bEnemyCloser ) - { - ClearCondition( COND_ANTLIONGUARD_PHYSICS_TARGET ); - SetCondition( COND_ANTLIONGUARD_PHYSICS_TARGET_INVALID ); - m_hPhysicsTarget = NULL; - return; - } - else - { - SetCondition( COND_ANTLIONGUARD_PHYSICS_TARGET ); - ClearCondition( COND_ANTLIONGUARD_PHYSICS_TARGET_INVALID ); - } - - if ( g_debug_antlionguard.GetInt() == 3 ) - { - NDebugOverlay::Cross3D( m_hPhysicsTarget->WorldSpaceCenter(), -Vector(32,32,32), Vector(32,32,32), 255, 255, 255, true, 1.0f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::UpdatePhysicsTarget( bool bPreferObjectsAlongTargetVector, float flRadius ) -{ - if ( GetEnemy() == NULL ) - return; - - // Already have a target, don't bother looking - if ( m_hPhysicsTarget != NULL ) - return; - - // Too soon to check again - if ( m_flPhysicsCheckTime > gpGlobals->curtime ) - return; - - // Attempt to find a valid shove target - PhysicsObjectCriteria_t criteria; - criteria.pTarget = GetEnemy(); - criteria.vecCenter = GetEnemy()->GetAbsOrigin(); - criteria.flRadius = flRadius; - criteria.flTargetCone = ANTLIONGUARD_OBJECTFINDING_FOV; - criteria.bPreferObjectsAlongTargetVector = bPreferObjectsAlongTargetVector; - criteria.flNearRadius = (20*12); // TODO: It may preferable to disable this for legacy products as well -- jdw - - m_hPhysicsTarget = FindPhysicsObjectTarget( criteria ); - - // Found one, so interrupt us if we care - if ( m_hPhysicsTarget != NULL ) - { - SetCondition( COND_ANTLIONGUARD_PHYSICS_TARGET ); - m_vecPhysicsTargetStartPos = m_hPhysicsTarget->WorldSpaceCenter(); - } - - // Don't search again for another second - m_flPhysicsCheckTime = gpGlobals->curtime + 1.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: Let the probe know I can run through small debris -//----------------------------------------------------------------------------- -bool CNPC_AntlionGuard::ShouldProbeCollideAgainstEntity( CBaseEntity *pEntity ) -{ - if ( m_iszPhysicsPropClass != pEntity->m_iClassname ) - return BaseClass::ShouldProbeCollideAgainstEntity( pEntity ); - - if ( m_hPhysicsTarget == pEntity ) - return false; - - if ( pEntity->GetMoveType() == MOVETYPE_VPHYSICS ) - { - IPhysicsObject *pPhysObj = pEntity->VPhysicsGetObject(); - - if( pPhysObj && pPhysObj->GetMass() <= ANTLIONGUARD_MAX_OBJECT_MASS ) - { - return false; - } - } - - return BaseClass::ShouldProbeCollideAgainstEntity( pEntity ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::PrescheduleThink( void ) -{ - BaseClass::PrescheduleThink(); - - // Don't do anything after death - if ( m_NPCState == NPC_STATE_DEAD ) - return; - - // If we're burrowed, then don't do any of this - if ( m_bIsBurrowed ) - return; - - // Automatically update our physics target when chasing enemies - if ( IsCurSchedule( SCHED_ANTLIONGUARD_CHASE_ENEMY ) || - IsCurSchedule( SCHED_ANTLIONGUARD_PATROL_RUN ) || - IsCurSchedule( SCHED_ANTLIONGUARD_CANT_ATTACK ) || - IsCurSchedule( SCHED_ANTLIONGUARD_CHASE_ENEMY_TOLERANCE ) ) - { - bool bCheckAlongLine = ( IsCurSchedule( SCHED_ANTLIONGUARD_CHASE_ENEMY ) || IsCurSchedule( SCHED_ANTLIONGUARD_CHASE_ENEMY_TOLERANCE ) ); - UpdatePhysicsTarget( bCheckAlongLine ); - } - else if ( !IsCurSchedule( SCHED_ANTLIONGUARD_PHYSICS_ATTACK ) ) - { - ClearCondition( COND_ANTLIONGUARD_PHYSICS_TARGET ); - m_hPhysicsTarget = NULL; - } - - UpdateHead(); - - if ( ( m_flGroundSpeed <= 0.0f ) ) - { - if ( m_bStopped == false ) - { - StartSounds(); - - float duration = random->RandomFloat( 2.0f, 8.0f ); - - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pBreathSound, 0.0f, duration ); - ENVELOPE_CONTROLLER.SoundChangePitch( m_pBreathSound, random->RandomInt( 40, 60 ), duration ); - - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pGrowlIdleSound, 0.0f, duration ); - ENVELOPE_CONTROLLER.SoundChangePitch( m_pGrowlIdleSound, random->RandomInt( 120, 140 ), duration ); - - m_flBreathTime = gpGlobals->curtime + duration - (duration*0.75f); - } - - m_bStopped = true; - - if ( m_flBreathTime < gpGlobals->curtime ) - { - StartSounds(); - - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pGrowlIdleSound, random->RandomFloat( 0.2f, 0.3f ), random->RandomFloat( 0.5f, 1.0f ) ); - ENVELOPE_CONTROLLER.SoundChangePitch( m_pGrowlIdleSound, random->RandomInt( 80, 120 ), random->RandomFloat( 0.5f, 1.0f ) ); - - m_flBreathTime = gpGlobals->curtime + random->RandomFloat( 1.0f, 8.0f ); - } - } - else - { - if ( m_bStopped ) - { - StartSounds(); - - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pBreathSound, 0.6f, random->RandomFloat( 2.0f, 4.0f ) ); - ENVELOPE_CONTROLLER.SoundChangePitch( m_pBreathSound, random->RandomInt( 140, 160 ), random->RandomFloat( 2.0f, 4.0f ) ); - - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pGrowlIdleSound, 0.0f, 1.0f ); - ENVELOPE_CONTROLLER.SoundChangePitch( m_pGrowlIdleSound, random->RandomInt( 90, 110 ), 0.2f ); - } - - - m_bStopped = false; - } - - // Put danger sounds out in front of us - for ( int i = 0; i < 3; i++ ) - { - CSoundEnt::InsertSound( SOUND_DANGER, WorldSpaceCenter() + ( BodyDirection3D() * 128 * (i+1) ), 128, 0.1f, this ); - } - -#if ANTLIONGUARD_BLOOD_EFFECTS - // compute and if necessary transmit the bleeding level for the particle effect - m_iBleedingLevel = GetBleedingLevel(); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::GatherConditions( void ) -{ - BaseClass::GatherConditions(); - - if ( CanSummon(false) ) - { - SetCondition( COND_ANTLIONGUARD_CAN_SUMMON ); - } - else - { - ClearCondition( COND_ANTLIONGUARD_CAN_SUMMON ); - } - - // Make sure our physics target is still valid - MaintainPhysicsTarget(); - - if( IsCurSchedule(SCHED_ANTLIONGUARD_PHYSICS_ATTACK) ) - { - if( gpGlobals->curtime > m_flWaitFinished ) - { - ClearCondition( COND_ANTLIONGUARD_PHYSICS_TARGET ); - SetCondition( COND_ANTLIONGUARD_PHYSICS_TARGET_INVALID ); - m_hPhysicsTarget = NULL; - } - } - - // See if we can charge the target - if ( GetEnemy() ) - { - if ( ShouldCharge( GetAbsOrigin(), GetEnemy()->GetAbsOrigin(), true, false ) ) - { - SetCondition( COND_ANTLIONGUARD_CAN_CHARGE ); - } - else - { - ClearCondition( COND_ANTLIONGUARD_CAN_CHARGE ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::StopLoopingSounds() -{ - //Stop all sounds - ENVELOPE_CONTROLLER.SoundDestroy( m_pGrowlHighSound ); - ENVELOPE_CONTROLLER.SoundDestroy( m_pGrowlIdleSound ); - ENVELOPE_CONTROLLER.SoundDestroy( m_pBreathSound ); - ENVELOPE_CONTROLLER.SoundDestroy( m_pConfusedSound ); - - - m_pGrowlHighSound = NULL; - m_pGrowlIdleSound = NULL; - m_pBreathSound = NULL; - m_pConfusedSound = NULL; - - BaseClass::StopLoopingSounds(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::InputUnburrow( inputdata_t &inputdata ) -{ - if ( IsAlive() == false ) - return; - - if ( m_bIsBurrowed == false ) - return; - - m_spawnflags &= ~SF_NPC_GAG; - - RemoveSolidFlags( FSOLID_NOT_SOLID ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - - m_takedamage = DAMAGE_YES; - - SetSchedule( SCHED_ANTLIONGUARD_UNBURROW ); - - m_bIsBurrowed = false; -} - -//------------------------------------------------------------------------------ -// Purpose : Returns true is entity was remembered as unreachable. -// After a time delay reachability is checked -// Input : -// Output : -//------------------------------------------------------------------------------ -bool CNPC_AntlionGuard::IsUnreachable(CBaseEntity *pEntity) -{ - float UNREACHABLE_DIST_TOLERANCE_SQ = (240 * 240); - - // Note that it's ok to remove elements while I'm iterating - // as long as I iterate backwards and remove them using FastRemove - for (int i=m_UnreachableEnts.Size()-1;i>=0;i--) - { - // Remove any dead elements - if (m_UnreachableEnts[i].hUnreachableEnt == NULL) - { - m_UnreachableEnts.FastRemove(i); - } - else if (pEntity == m_UnreachableEnts[i].hUnreachableEnt) - { - // Test for reachability on any elements that have timed out - if ( gpGlobals->curtime > m_UnreachableEnts[i].fExpireTime || - pEntity->GetAbsOrigin().DistToSqr(m_UnreachableEnts[i].vLocationWhenUnreachable) > UNREACHABLE_DIST_TOLERANCE_SQ) - { - m_UnreachableEnts.FastRemove(i); - return false; - } - return true; - } - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Return the point at which the guard wants to stand on to knock the physics object at the target entity -// Input : *pObject - Object to be shoved. -// *pTarget - Target to be shoved at. -// *vecTrajectory - Trajectory to our target -// *flClearDistance - Distance behind the entity we're clear to use -// Output : Position at which to attempt to strike the object -//----------------------------------------------------------------------------- -Vector CNPC_AntlionGuard::GetPhysicsHitPosition( CBaseEntity *pObject, CBaseEntity *pTarget, Vector *vecTrajectory, float *flClearDistance ) -{ - // Get the trajectory we want to knock the object along - Vector vecToTarget = pTarget->WorldSpaceCenter() - pObject->WorldSpaceCenter(); - VectorNormalize( vecToTarget ); - vecToTarget.z = 0; - - // Get the distance we want to be from the object when we hit it - IPhysicsObject *pPhys = pObject->VPhysicsGetObject(); - Vector extent = physcollision->CollideGetExtent( pPhys->GetCollide(), pObject->GetAbsOrigin(), pObject->GetAbsAngles(), -vecToTarget ); - float flDist = ( extent - pObject->WorldSpaceCenter() ).Length() + CollisionProp()->BoundingRadius() + 32.0f; - - if ( vecTrajectory != NULL ) - { - *vecTrajectory = vecToTarget; - } - - if ( flClearDistance != NULL ) - { - *flClearDistance = flDist; - } - - // Position at which we'd like to be - return (pObject->WorldSpaceCenter() + ( vecToTarget * -flDist )); -} - -//----------------------------------------------------------------------------- -// Purpose: See if we're able to stand on the ground at this point -// Input : &vecPos - Position to try -// *pOut - Result position (only valid if we return true) -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -inline bool CNPC_AntlionGuard::CanStandAtPoint( const Vector &vecPos, Vector *pOut ) -{ - Vector vecStart = vecPos + Vector( 0, 0, (4*12) ); - Vector vecEnd = vecPos - Vector( 0, 0, (4*12) ); - trace_t tr; - bool bTraceCleared = false; - - // Start high and try to go lower, looking for the ground between here and there - // We do this first because it's more likely to succeed in the typical guard arenas (with open terrain) - UTIL_TraceHull( vecStart, vecEnd, GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - if ( tr.startsolid && !tr.allsolid ) - { - // We started in solid but didn't end up there, see if we can stand where we ended up - UTIL_TraceHull( tr.endpos, tr.endpos, GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - - // Must not be in solid - bTraceCleared = ( !tr.allsolid && !tr.startsolid ); - } - else - { - // Must not be in solid and must have found a floor (otherwise we're potentially hanging over a ledge) - bTraceCleared = ( tr.allsolid == false && tr.fraction < 1.0f ); - } - - // Either we're clear or we're still unlucky - if ( bTraceCleared == false ) - { - if ( g_debug_antlionguard.GetInt() == 3 ) - { - NDebugOverlay::Box( vecPos, GetHullMins(), GetHullMaxs(), 255, 0, 0, 0, 15.0f ); - } - return false; - } - - if ( pOut ) - { - *pOut = tr.endpos; - } - - if ( g_debug_antlionguard.GetInt() == 3 ) - { - NDebugOverlay::Box( (*pOut), GetHullMins(), GetHullMaxs(), 0, 255, 0, 0, 15.0f ); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Determines whether or not the guard can stand in a position to strike a specified object -// Input : *pShoveObject - Object being shoved -// *pTarget - Target we're shoving the object at -// *pOut - The position we decide to stand at -// Output : Returns true if the guard can stand and deliver. -//----------------------------------------------------------------------------- -bool CNPC_AntlionGuard::CanStandAtShoveTarget( CBaseEntity *pShoveObject, CBaseEntity *pTarget, Vector *pOut ) -{ - // Get the position we want to be at to swing at the object - float flClearDistance; - Vector vecTrajectory; - Vector vecHitPosition = GetPhysicsHitPosition( pShoveObject, pTarget, &vecTrajectory, &flClearDistance ); - Vector vecStandPosition; - - if ( g_debug_antlionguard.GetInt() == 3 ) - { - NDebugOverlay::HorzArrow( pShoveObject->WorldSpaceCenter(), pShoveObject->WorldSpaceCenter() + vecTrajectory * 64.0f, 16.0f, 255, 255, 0, 16, true, 15.0f ); - } - - // If we failed, try around the sides - if ( CanStandAtPoint( vecHitPosition, &vecStandPosition ) == false ) - { - // Get the angle (in reverse) to the target - float flRad = atan2( -vecTrajectory.y, -vecTrajectory.x ); - float flRadOffset = DEG2RAD( 45.0f ); - - // Build an offset vector, rotating around the base - Vector vecSkewTrajectory; - SinCos( flRad + flRadOffset, &vecSkewTrajectory.y, &vecSkewTrajectory.x ); - vecSkewTrajectory.z = 0.0f; - - // Try to the side - if ( CanStandAtPoint( ( pShoveObject->WorldSpaceCenter() + ( vecSkewTrajectory * flClearDistance ) ), &vecStandPosition ) == false ) - { - // Try the other side - SinCos( flRad - flRadOffset, &vecSkewTrajectory.y, &vecSkewTrajectory.x ); - vecSkewTrajectory.z = 0.0f; - if ( CanStandAtPoint( ( pShoveObject->WorldSpaceCenter() + ( vecSkewTrajectory * flClearDistance ) ), &vecStandPosition ) == false ) - return false; - } - } - - // Found it, report it - if ( pOut != NULL ) - { - *pOut = vecStandPosition; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Iterate through a number of lists depending on our criteria -//----------------------------------------------------------------------------- -CBaseEntity *CNPC_AntlionGuard::GetNextShoveTarget( CBaseEntity *pLastEntity, AISightIter_t &iter ) -{ - // Try to find scripted items first - if ( m_strShoveTargets != NULL_STRING ) - { - CBaseEntity *pFound = gEntList.FindEntityByName( pLastEntity, m_strShoveTargets ); - if ( pFound ) - return pFound; - } - - // Failing that, use our senses - if ( iter != (AISightIter_t)(-1) ) - return GetSenses()->GetNextSeenEntity( &iter ); - - return GetSenses()->GetFirstSeenEntity( &iter, SEEN_MISC ); -} - -//----------------------------------------------------------------------------- -// Purpose: Search for a physics item to swat at the player -// Output : Returns the object we're going to swat. -//----------------------------------------------------------------------------- -CBaseEntity *CNPC_AntlionGuard::FindPhysicsObjectTarget( const PhysicsObjectCriteria_t &criteria ) -{ - // Must have a valid target entity - if ( criteria.pTarget == NULL ) - return NULL; - - if ( g_debug_antlionguard.GetInt() == 3 ) - { - NDebugOverlay::Circle( GetAbsOrigin(), QAngle( -90, 0, 0 ), criteria.flRadius, 255, 0, 0, 8, true, 2.0f ); - } - - // Get the vector to our target, from ourself - Vector vecDirToTarget = criteria.pTarget->GetAbsOrigin() - GetAbsOrigin(); - VectorNormalize( vecDirToTarget ); - vecDirToTarget.z = 0; - - // Cost is determined by distance to the object, modified by how "in line" it is with our target direction of travel - // Use the distance to the player as the base cost for throwing an object (avoids pushing things too close to the player) - float flLeastCost = ( criteria.bPreferObjectsAlongTargetVector ) ? ( criteria.pTarget->GetAbsOrigin() - GetAbsOrigin() ).LengthSqr() : Square( criteria.flRadius ); - float flCost; - - AISightIter_t iter = (AISightIter_t)(-1); - CBaseEntity *pObject = NULL; - CBaseEntity *pNearest = NULL; - Vector vecBestHitPosition = vec3_origin; - - // Look through the list of sensed objects for possible targets - while( ( pObject = GetNextShoveTarget( pObject, iter ) ) != NULL ) - { - // If we couldn't shove this object last time, don't try again - if ( m_FailedPhysicsTargets.Find( pObject ) != m_FailedPhysicsTargets.InvalidIndex() ) - continue; - - // Ignore things less than half a foot in diameter - if ( pObject->CollisionProp()->BoundingRadius() < 6.0f ) - continue; - - IPhysicsObject *pPhysObj = pObject->VPhysicsGetObject(); - if ( pPhysObj == NULL ) - continue; - - // Ignore motion disabled props - if ( pPhysObj->IsMoveable() == false ) - continue; - - // Ignore things lighter than 5kg - if ( pPhysObj->GetMass() < 5.0f ) - continue; - - // Ignore objects moving too quickly (they'll be too hard to catch otherwise) - Vector velocity; - pPhysObj->GetVelocity( &velocity, NULL ); - if ( velocity.LengthSqr() > (16*16) ) - continue; - - // Get the direction from us to the physics object - Vector vecDirToObject = pObject->WorldSpaceCenter() - GetAbsOrigin(); - VectorNormalize( vecDirToObject ); - vecDirToObject.z = 0; - - Vector vecObjCenter = pObject->WorldSpaceCenter(); - float flDistSqr = 0.0f; - float flDot = 0.0f; - - // If we want to find things along the vector to the target, do so - if ( criteria.bPreferObjectsAlongTargetVector ) - { - // Object must be closer than our target - if ( ( GetAbsOrigin() - vecObjCenter ).LengthSqr() > ( GetAbsOrigin() - criteria.pTarget->GetAbsOrigin() ).LengthSqr() ) - continue; - - // Calculate a "cost" to this object - flDistSqr = ( GetAbsOrigin() - vecObjCenter ).LengthSqr(); - flDot = DotProduct( vecDirToTarget, vecDirToObject ); - - // Ignore things outside our allowed cone - if ( flDot < criteria.flTargetCone ) - continue; - - // The more perpendicular we are, the higher the cost - float flCostScale = RemapValClamped( flDot, 1.0f, criteria.flTargetCone, 1.0f, 4.0f ); - flCost = flDistSqr * flCostScale; - } - else - { - // Straight distance cost - flCost = ( criteria.vecCenter - vecObjCenter ).LengthSqr(); - } - - // This must be a less costly object to use - if ( flCost >= flLeastCost ) - { - if ( g_debug_antlionguard.GetInt() == 3 ) - { - NDebugOverlay::Box( vecObjCenter, -Vector(16,16,16), Vector(16,16,16), 255, 0, 0, 0, 2.0f ); - } - - continue; - } - - // Check for a (roughly) clear trajectory path from the object to target - trace_t tr; - UTIL_TraceLine( vecObjCenter, criteria.pTarget->BodyTarget( vecObjCenter ), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - - // See how close to our target we got (we still look good hurling things that won't necessarily hit) - if ( ( tr.endpos - criteria.pTarget->WorldSpaceCenter() ).LengthSqr() > Square(criteria.flNearRadius) ) - continue; - - // Must be able to stand at a position to hit the object - Vector vecHitPosition; - if ( CanStandAtShoveTarget( pObject, criteria.pTarget, &vecHitPosition ) == false ) - { - if ( g_debug_antlionguard.GetInt() == 3 ) - { - NDebugOverlay::HorzArrow( GetAbsOrigin(), pObject->WorldSpaceCenter(), 32.0f, 255, 0, 0, 64, true, 2.0f ); - } - continue; - } - - // Take this as the best object so far - pNearest = pObject; - flLeastCost = flCost; - vecBestHitPosition = vecHitPosition; - - if ( g_debug_antlionguard.GetInt() == 3 ) - { - NDebugOverlay::HorzArrow( GetAbsOrigin(), pObject->WorldSpaceCenter(), 16.0f, 255, 255, 0, 0, true, 2.0f ); - } - } - - // Set extra info if we've succeeded - if ( pNearest != NULL ) - { - m_vecPhysicsHitPosition = vecBestHitPosition; - - if ( g_debug_antlionguard.GetInt() == 3 ) - { - NDebugOverlay::HorzArrow( GetAbsOrigin(), pNearest->WorldSpaceCenter(), 32.0f, 0, 255, 0, 128, true, 2.0f ); - } - } - - return pNearest; -} - -//----------------------------------------------------------------------------- -// Purpose: Allows for modification of the interrupt mask for the current schedule. -// In the most cases the base implementation should be called first. -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::BuildScheduleTestBits( void ) -{ - BaseClass::BuildScheduleTestBits(); - - // Interrupt if we can shove something - if ( IsCurSchedule( SCHED_ANTLIONGUARD_CHASE_ENEMY ) ) - { - SetCustomInterruptCondition( COND_ANTLIONGUARD_PHYSICS_TARGET ); - SetCustomInterruptCondition( COND_ANTLIONGUARD_CAN_SUMMON ); - } - - // Interrupt if we've been given a charge target - if ( IsCurSchedule( SCHED_ANTLIONGUARD_CHARGE ) == false ) - { - SetCustomInterruptCondition( COND_ANTLIONGUARD_HAS_CHARGE_TARGET ); - } - - // Once we commit to doing this, just do it! - if ( IsCurSchedule( SCHED_MELEE_ATTACK1 ) ) - { - ClearCustomInterruptCondition( COND_ENEMY_OCCLUDED ); - } - - // Always take heavy damage - SetCustomInterruptCondition( COND_HEAVY_DAMAGE ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &origin - -// radius - -// magnitude - -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::ImpactShock( const Vector &origin, float radius, float magnitude, CBaseEntity *pIgnored ) -{ - // Also do a local physics explosion to push objects away - float adjustedDamage, flDist; - Vector vecSpot; - float falloff = 1.0f / 2.5f; - - CBaseEntity *pEntity = NULL; - - // Find anything within our radius - while ( ( pEntity = gEntList.FindEntityInSphere( pEntity, origin, radius ) ) != NULL ) - { - // Don't affect the ignored target - if ( pEntity == pIgnored ) - continue; - if ( pEntity == this ) - continue; - - // UNDONE: Ask the object if it should get force if it's not MOVETYPE_VPHYSICS? - if ( pEntity->GetMoveType() == MOVETYPE_VPHYSICS || ( pEntity->VPhysicsGetObject() && pEntity->IsPlayer() == false ) ) - { - vecSpot = pEntity->BodyTarget( GetAbsOrigin() ); - - // decrease damage for an ent that's farther from the bomb. - flDist = ( GetAbsOrigin() - vecSpot ).Length(); - - if ( radius == 0 || flDist <= radius ) - { - adjustedDamage = flDist * falloff; - adjustedDamage = magnitude - adjustedDamage; - - if ( adjustedDamage < 1 ) - { - adjustedDamage = 1; - } - - CTakeDamageInfo info( this, this, adjustedDamage, DMG_BLAST ); - CalculateExplosiveDamageForce( &info, (vecSpot - GetAbsOrigin()), GetAbsOrigin() ); - - pEntity->VPhysicsTakeDamage( info ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTarget - -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::ChargeDamage( CBaseEntity *pTarget ) -{ - if ( pTarget == NULL ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( pTarget ); - - if ( pPlayer != NULL ) - { - //Kick the player angles - pPlayer->ViewPunch( QAngle( 20, 20, -30 ) ); - - Vector dir = pPlayer->WorldSpaceCenter() - WorldSpaceCenter(); - VectorNormalize( dir ); - dir.z = 0.0f; - - Vector vecNewVelocity = dir * 250.0f; - vecNewVelocity[2] += 128.0f; - pPlayer->SetAbsVelocity( vecNewVelocity ); - - color32 red = {128,0,0,128}; - UTIL_ScreenFade( pPlayer, red, 1.0f, 0.1f, FFADE_IN ); - } - - // Player takes less damage - float flDamage = ( pPlayer == NULL ) ? 250 : sk_antlionguard_dmg_charge.GetFloat(); - - // If it's being held by the player, break that bond - Pickup_ForcePlayerToDropThisObject( pTarget ); - - // Calculate the physics force - ApplyChargeDamage( this, pTarget, flDamage ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::InputRagdoll( inputdata_t &inputdata ) -{ - if ( IsAlive() == false ) - return; - - //Set us to nearly dead so the velocity from death is minimal - SetHealth( 1 ); - - CTakeDamageInfo info( this, this, GetHealth(), DMG_CRUSH ); - BaseClass::TakeDamage( info ); -} - - - -//----------------------------------------------------------------------------- -// Purpose: make m_bPreferPhysicsAttack true -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::InputEnablePreferPhysicsAttack( inputdata_t &inputdata ) -{ - m_bPreferPhysicsAttack = true; -} - -//----------------------------------------------------------------------------- -// Purpose: make m_bPreferPhysicsAttack false -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::InputDisablePreferPhysicsAttack( inputdata_t &inputdata ) -{ - m_bPreferPhysicsAttack = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_AntlionGuard::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ) -{ - // Figure out what to do next - if ( failedSchedule == SCHED_ANTLIONGUARD_CHASE_ENEMY && HasCondition( COND_ENEMY_UNREACHABLE ) ) - return SelectUnreachableSchedule(); - - return BaseClass::SelectFailSchedule( failedSchedule,failedTask, taskFailCode ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : scheduleType - -// Output : int -//----------------------------------------------------------------------------- -int CNPC_AntlionGuard::TranslateSchedule( int scheduleType ) -{ - switch( scheduleType ) - { - case SCHED_CHASE_ENEMY: - return SCHED_ANTLIONGUARD_CHASE_ENEMY; - break; - } - - return BaseClass::TranslateSchedule( scheduleType ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::StartSounds( void ) -{ - //Initialize the additive sound channels - CPASAttenuationFilter filter( this ); - - if ( m_pGrowlHighSound == NULL ) - { - m_pGrowlHighSound = ENVELOPE_CONTROLLER.SoundCreate( filter, entindex(), CHAN_VOICE, "NPC_AntlionGuard.GrowlHigh", ATTN_NORM ); - - if ( m_pGrowlHighSound ) - { - ENVELOPE_CONTROLLER.Play( m_pGrowlHighSound,0.0f, 100 ); - } - } - - if ( m_pGrowlIdleSound == NULL ) - { - m_pGrowlIdleSound = ENVELOPE_CONTROLLER.SoundCreate( filter, entindex(), CHAN_STATIC, "NPC_AntlionGuard.GrowlIdle", ATTN_NORM ); - - if ( m_pGrowlIdleSound ) - { - ENVELOPE_CONTROLLER.Play( m_pGrowlIdleSound,0.0f, 100 ); - } - } - - if ( m_pBreathSound == NULL ) - { - m_pBreathSound = ENVELOPE_CONTROLLER.SoundCreate( filter, entindex(), CHAN_ITEM, "NPC_AntlionGuard.BreathSound", ATTN_NORM ); - - if ( m_pBreathSound ) - { - ENVELOPE_CONTROLLER.Play( m_pBreathSound, 0.0f, 100 ); - } - } - - if ( m_pConfusedSound == NULL ) - { - m_pConfusedSound = ENVELOPE_CONTROLLER.SoundCreate( filter, entindex(), CHAN_WEAPON,"NPC_AntlionGuard.Confused", ATTN_NORM ); - - if ( m_pConfusedSound ) - { - ENVELOPE_CONTROLLER.Play( m_pConfusedSound, 0.0f, 100 ); - } - } - -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::InputEnableBark( inputdata_t &inputdata ) -{ - m_bBarkEnabled = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::InputDisableBark( inputdata_t &inputdata ) -{ - m_bBarkEnabled = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::DeathSound( const CTakeDamageInfo &info ) -{ - EmitSound( "NPC_AntlionGuard.Die" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::Event_Killed( const CTakeDamageInfo &info ) -{ - BaseClass::Event_Killed( info ); - - // Tell all of my antlions to burrow away, 'cos they fear the Freeman - if ( m_iNumLiveAntlions ) - { - CBaseEntity *pSearch = NULL; - - // Iterate through all antlions and see if there are any orphans - while ( ( pSearch = gEntList.FindEntityByClassname( pSearch, "npc_antlion" ) ) != NULL ) - { - CNPC_Antlion *pAntlion = assert_cast(pSearch); - - // See if it's a live orphan - if ( pAntlion && pAntlion->GetOwnerEntity() == NULL && pAntlion->IsAlive() ) - { - g_EventQueue.AddEvent( pAntlion, "BurrowAway", RandomFloat(0.1, 2.0), this, this ); - } - } - } - - DestroyGlows(); - - // If I'm bleeding, stop due to decreased pressure of hemolymph after - // cessation of aortic contraction -#if ANTLIONGUARD_BLOOD_EFFECTS - m_iBleedingLevel = 0; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Don't become a ragdoll until we've finished our death anim -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_AntlionGuard::CanBecomeRagdoll( void ) -{ - if ( IsCurSchedule( SCHED_DIE ) ) - return true; - - return hl2_episodic.GetBool(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &force - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_AntlionGuard::BecomeRagdollOnClient( const Vector &force ) -{ - if ( !CanBecomeRagdoll() ) - return false; - - EmitSound( "NPC_AntlionGuard.Fallover" ); - - // Become server-side ragdoll if we're flagged to do it - if ( m_spawnflags & SF_ANTLIONGUARD_SERVERSIDE_RAGDOLL ) - { - CTakeDamageInfo info; - - // Fake the info - info.SetDamageType( DMG_GENERIC ); - info.SetDamageForce( force ); - info.SetDamagePosition( WorldSpaceCenter() ); - - CBaseEntity *pRagdoll = CreateServerRagdoll( this, 0, info, COLLISION_GROUP_NONE ); - - // Transfer our name to the new ragdoll - pRagdoll->SetName( GetEntityName() ); - pRagdoll->SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - - // Get rid of our old body - UTIL_Remove(this); - - return true; - } - - return BaseClass::BecomeRagdollOnClient( force ); -} - -//----------------------------------------------------------------------------- -// Purpose: Override how we face our target as we move -// Output : -//----------------------------------------------------------------------------- -bool CNPC_AntlionGuard::OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval ) -{ - Vector vecFacePosition = vec3_origin; - CBaseEntity *pFaceTarget = NULL; - bool bFaceTarget = false; - - // FIXME: this will break scripted sequences that walk when they have an enemy - if ( m_hChargeTarget ) - { - vecFacePosition = m_hChargeTarget->GetAbsOrigin(); - pFaceTarget = m_hChargeTarget; - bFaceTarget = true; - } -#ifdef HL2_EPISODIC - else if ( GetEnemy() && IsCurSchedule( SCHED_ANTLIONGUARD_CANT_ATTACK ) ) - { - // Always face our enemy when randomly patrolling around - vecFacePosition = GetEnemy()->EyePosition(); - pFaceTarget = GetEnemy(); - bFaceTarget = true; - } -#endif // HL2_EPISODIC - else if ( GetEnemy() && GetNavigator()->GetMovementActivity() == ACT_RUN ) - { - Vector vecEnemyLKP = GetEnemyLKP(); - - // Only start facing when we're close enough - if ( ( UTIL_DistApprox( vecEnemyLKP, GetAbsOrigin() ) < 512 ) || IsCurSchedule( SCHED_ANTLIONGUARD_PATROL_RUN ) ) - { - vecFacePosition = vecEnemyLKP; - pFaceTarget = GetEnemy(); - bFaceTarget = true; - } - } - - // Face - if ( bFaceTarget ) - { - AddFacingTarget( pFaceTarget, vecFacePosition, 1.0, 0.2 ); - } - - return BaseClass::OverrideMoveFacing( move, flInterval ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_AntlionGuard::IsHeavyDamage( const CTakeDamageInfo &info ) -{ - // Struck by blast - if ( info.GetDamageType() & DMG_BLAST ) - { - if ( info.GetDamage() > MIN_BLAST_DAMAGE ) - return true; - } - - // Struck by large object - if ( info.GetDamageType() & DMG_CRUSH ) - { - IPhysicsObject *pPhysObject = info.GetInflictor()->VPhysicsGetObject(); - - if ( ( pPhysObject != NULL ) && ( pPhysObject->GetGameFlags() & FVPHYSICS_WAS_THROWN ) ) - { - // Always take hits from a combine ball - if ( UTIL_IsAR2CombineBall( info.GetInflictor() ) ) - return true; - - // If we're under half health, stop being interrupted by heavy damage - if ( GetHealth() < (GetMaxHealth() * 0.25) ) - return false; - - // Ignore physics damages that don't do much damage - if ( info.GetDamage() < MIN_CRUSH_DAMAGE ) - return false; - - return true; - } - - return false; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_AntlionGuard::IsLightDamage( const CTakeDamageInfo &info ) -{ - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pChild - -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::InputSummonedAntlionDied( inputdata_t &inputdata ) -{ - m_iNumLiveAntlions--; - Assert( m_iNumLiveAntlions >= 0 ); - - if ( g_debug_antlionguard.GetInt() == 2 ) - { - Msg("Guard summoned antlion count: %d\n", m_iNumLiveAntlions ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Filter out sounds we don't care about -// Input : *pSound - sound to test against -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_AntlionGuard::QueryHearSound( CSound *pSound ) -{ - // Don't bother with danger sounds from antlions or other guards - if ( pSound->SoundType() == SOUND_DANGER && ( pSound->m_hOwner != NULL && pSound->m_hOwner->Classify() == CLASS_ANTLION ) ) - return false; - - return BaseClass::QueryHearSound( pSound ); -} - - -#if HL2_EPISODIC -//--------------------------------------------------------- -// Prevent the cavern guard from using stopping paths, as it occasionally forces him off the navmesh. -//--------------------------------------------------------- -bool CNPC_AntlionGuard::CNavigator::GetStoppingPath( CAI_WaypointList *pClippedWaypoints ) -{ - if (GetOuter()->m_bInCavern) - { - return false; - } - else - { - return BaseClass::GetStoppingPath( pClippedWaypoints ); - } -} -#endif - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTarget - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_AntlionGuard::RememberFailedPhysicsTarget( CBaseEntity *pTarget ) -{ - // Already in the list? - if ( m_FailedPhysicsTargets.Find( pTarget ) != m_FailedPhysicsTargets.InvalidIndex() ) - return true; - - // We're not holding on to any more - if ( ( m_FailedPhysicsTargets.Count() + 1 ) > MAX_FAILED_PHYSOBJECTS ) - return false; - - m_FailedPhysicsTargets.AddToTail( pTarget ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Handle squad or NPC interactions -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_AntlionGuard::HandleInteraction( int interactionType, void *data, CBaseCombatCharacter *sender ) -{ - // Don't chase targets that other guards in our squad may be going after! - if ( interactionType == g_interactionAntlionGuardFoundPhysicsObject ) - { - RememberFailedPhysicsTarget( (CBaseEntity *) data ); - return true; - } - - // Mark a shoved object as being free to pursue again - if ( interactionType == g_interactionAntlionGuardShovedPhysicsObject ) - { - CBaseEntity *pObject = (CBaseEntity *) data; - m_FailedPhysicsTargets.FindAndRemove( pObject ); - return true; - } - - return BaseClass::HandleInteraction( interactionType, data, sender ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Cache whatever pose parameters we intend to use -//----------------------------------------------------------------------------- -void CNPC_AntlionGuard::PopulatePoseParameters( void ) -{ - m_poseThrow = LookupPoseParameter("throw"); - m_poseHead_Pitch = LookupPoseParameter("head_pitch"); - m_poseHead_Yaw = LookupPoseParameter("head_yaw" ); - - BaseClass::PopulatePoseParameters(); -} - -#if ANTLIONGUARD_BLOOD_EFFECTS -//----------------------------------------------------------------------------- -// Purpose: Return desired level for the continuous bleeding effect (not the -// individual blood spurts you see per bullet hit) -// Return 0 for don't bleed, -// 1 for mild bleeding -// 2 for severe bleeding -//----------------------------------------------------------------------------- -unsigned char CNPC_AntlionGuard::GetBleedingLevel( void ) const -{ - if ( m_iHealth > ( m_iMaxHealth >> 1 ) ) - { // greater than 50% - return 0; - } - else if ( m_iHealth > ( m_iMaxHealth >> 2 ) ) - { // less than 50% but greater than 25% - return 1; - } - else - { - return 2; - } -} -#endif - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC( npc_antlionguard, CNPC_AntlionGuard ) - - // Interactions - DECLARE_INTERACTION( g_interactionAntlionGuardFoundPhysicsObject ) - DECLARE_INTERACTION( g_interactionAntlionGuardShovedPhysicsObject ) - - // Squadslots - DECLARE_SQUADSLOT( SQUAD_SLOT_ANTLIONGUARD_CHARGE ) - - //Tasks - DECLARE_TASK( TASK_ANTLIONGUARD_CHARGE ) - DECLARE_TASK( TASK_ANTLIONGUARD_GET_PATH_TO_PHYSOBJECT ) - DECLARE_TASK( TASK_ANTLIONGUARD_SHOVE_PHYSOBJECT ) - DECLARE_TASK( TASK_ANTLIONGUARD_SUMMON ) - DECLARE_TASK( TASK_ANTLIONGUARD_SET_FLINCH_ACTIVITY ) - DECLARE_TASK( TASK_ANTLIONGUARD_GET_PATH_TO_CHARGE_POSITION ) - DECLARE_TASK( TASK_ANTLIONGUARD_GET_PATH_TO_NEAREST_NODE ) - DECLARE_TASK( TASK_ANTLIONGUARD_GET_CHASE_PATH_ENEMY_TOLERANCE ) - DECLARE_TASK( TASK_ANTLIONGUARD_OPPORTUNITY_THROW ) - DECLARE_TASK( TASK_ANTLIONGUARD_FIND_PHYSOBJECT ) - - //Activities - DECLARE_ACTIVITY( ACT_ANTLIONGUARD_SEARCH ) - DECLARE_ACTIVITY( ACT_ANTLIONGUARD_PEEK_FLINCH ) - DECLARE_ACTIVITY( ACT_ANTLIONGUARD_PEEK_ENTER ) - DECLARE_ACTIVITY( ACT_ANTLIONGUARD_PEEK_EXIT ) - DECLARE_ACTIVITY( ACT_ANTLIONGUARD_PEEK1 ) - DECLARE_ACTIVITY( ACT_ANTLIONGUARD_BARK ) - DECLARE_ACTIVITY( ACT_ANTLIONGUARD_PEEK_SIGHTED ) - DECLARE_ACTIVITY( ACT_ANTLIONGUARD_CHARGE_START ) - DECLARE_ACTIVITY( ACT_ANTLIONGUARD_CHARGE_CANCEL ) - DECLARE_ACTIVITY( ACT_ANTLIONGUARD_CHARGE_RUN ) - DECLARE_ACTIVITY( ACT_ANTLIONGUARD_CHARGE_CRASH ) - DECLARE_ACTIVITY( ACT_ANTLIONGUARD_CHARGE_STOP ) - DECLARE_ACTIVITY( ACT_ANTLIONGUARD_CHARGE_HIT ) - DECLARE_ACTIVITY( ACT_ANTLIONGUARD_CHARGE_ANTICIPATION ) - DECLARE_ACTIVITY( ACT_ANTLIONGUARD_SHOVE_PHYSOBJECT ) - DECLARE_ACTIVITY( ACT_ANTLIONGUARD_FLINCH_LIGHT ) - DECLARE_ACTIVITY( ACT_ANTLIONGUARD_UNBURROW ) - DECLARE_ACTIVITY( ACT_ANTLIONGUARD_ROAR ) - DECLARE_ACTIVITY( ACT_ANTLIONGUARD_RUN_HURT ) - DECLARE_ACTIVITY( ACT_ANTLIONGUARD_PHYSHIT_FR ) - DECLARE_ACTIVITY( ACT_ANTLIONGUARD_PHYSHIT_FL ) - DECLARE_ACTIVITY( ACT_ANTLIONGUARD_PHYSHIT_RR ) - DECLARE_ACTIVITY( ACT_ANTLIONGUARD_PHYSHIT_RL ) - - //Adrian: events go here - DECLARE_ANIMEVENT( AE_ANTLIONGUARD_CHARGE_HIT ) - DECLARE_ANIMEVENT( AE_ANTLIONGUARD_SHOVE_PHYSOBJECT ) - DECLARE_ANIMEVENT( AE_ANTLIONGUARD_SHOVE ) - DECLARE_ANIMEVENT( AE_ANTLIONGUARD_FOOTSTEP_LIGHT ) - DECLARE_ANIMEVENT( AE_ANTLIONGUARD_FOOTSTEP_HEAVY ) - DECLARE_ANIMEVENT( AE_ANTLIONGUARD_CHARGE_EARLYOUT ) - DECLARE_ANIMEVENT( AE_ANTLIONGUARD_VOICE_GROWL ) - DECLARE_ANIMEVENT( AE_ANTLIONGUARD_VOICE_BARK ) - DECLARE_ANIMEVENT( AE_ANTLIONGUARD_VOICE_PAIN ) - DECLARE_ANIMEVENT( AE_ANTLIONGUARD_VOICE_SQUEEZE ) - DECLARE_ANIMEVENT( AE_ANTLIONGUARD_VOICE_SCRATCH ) - DECLARE_ANIMEVENT( AE_ANTLIONGUARD_VOICE_GRUNT ) - DECLARE_ANIMEVENT( AE_ANTLIONGUARD_BURROW_OUT ) - DECLARE_ANIMEVENT( AE_ANTLIONGUARD_VOICE_ROAR ) - - DECLARE_CONDITION( COND_ANTLIONGUARD_PHYSICS_TARGET ) - DECLARE_CONDITION( COND_ANTLIONGUARD_PHYSICS_TARGET_INVALID ) - DECLARE_CONDITION( COND_ANTLIONGUARD_HAS_CHARGE_TARGET ) - DECLARE_CONDITION( COND_ANTLIONGUARD_CAN_SUMMON ) - DECLARE_CONDITION( COND_ANTLIONGUARD_CAN_CHARGE ) - - //================================================== - // SCHED_ANTLIONGUARD_SUMMON - //================================================== - - DEFINE_SCHEDULE - ( - SCHED_ANTLIONGUARD_SUMMON, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_ANTLIONGUARD_BARK" - " TASK_ANTLIONGUARD_SUMMON 0" - " TASK_ANTLIONGUARD_OPPORTUNITY_THROW 0" - " " - " Interrupts" - " COND_HEAVY_DAMAGE" - ) - - //================================================== - // SCHED_ANTLIONGUARD_CHARGE - //================================================== - - DEFINE_SCHEDULE - ( - SCHED_ANTLIONGUARD_CHARGE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ANTLIONGUARD_CHASE_ENEMY" - " TASK_FACE_ENEMY 0" - " TASK_ANTLIONGUARD_CHARGE 0" - "" - " Interrupts" - " COND_TASK_FAILED" - " COND_HEAVY_DAMAGE" - - // These are deliberately left out so they can be detected during the - // charge Task and correctly play the charge stop animation. - //" COND_NEW_ENEMY" - //" COND_ENEMY_DEAD" - //" COND_LOST_ENEMY" - ) - - //================================================== - // SCHED_ANTLIONGUARD_CHARGE_TARGET - //================================================== - - DEFINE_SCHEDULE - ( - SCHED_ANTLIONGUARD_CHARGE_TARGET, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_ANTLIONGUARD_CHARGE 0" - "" - " Interrupts" - " COND_TASK_FAILED" - " COND_ENEMY_DEAD" - " COND_HEAVY_DAMAGE" - ) - - //================================================== - // SCHED_ANTLIONGUARD_CHARGE_SMASH - //================================================== - - DEFINE_SCHEDULE - ( - SCHED_ANTLIONGUARD_CHARGE_CRASH, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_ANTLIONGUARD_CHARGE_CRASH" - "" - " Interrupts" - " COND_TASK_FAILED" - " COND_HEAVY_DAMAGE" - ) - - //================================================== - // SCHED_ANTLIONGUARD_PHYSICS_ATTACK - //================================================== - - DEFINE_SCHEDULE - ( - SCHED_ANTLIONGUARD_PHYSICS_ATTACK, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ANTLIONGUARD_CHASE_ENEMY" - " TASK_ANTLIONGUARD_GET_PATH_TO_PHYSOBJECT 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_FACE_ENEMY 0" - " TASK_ANTLIONGUARD_SHOVE_PHYSOBJECT 0" - "" - " Interrupts" - " COND_TASK_FAILED" - " COND_ENEMY_DEAD" - " COND_LOST_ENEMY" - " COND_NEW_ENEMY" - " COND_ANTLIONGUARD_PHYSICS_TARGET_INVALID" - " COND_HEAVY_DAMAGE" - ) - - //================================================== - // SCHED_FORCE_ANTLIONGUARD_PHYSICS_ATTACK - //================================================== - - DEFINE_SCHEDULE - ( - SCHED_FORCE_ANTLIONGUARD_PHYSICS_ATTACK, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ANTLIONGUARD_CANT_ATTACK" - " TASK_ANTLIONGUARD_FIND_PHYSOBJECT 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_ANTLIONGUARD_PHYSICS_ATTACK" - "" - " Interrupts" - " COND_ANTLIONGUARD_PHYSICS_TARGET" - " COND_HEAVY_DAMAGE" - ) - - //================================================== - // SCHED_ANTLIONGUARD_CANT_ATTACK - // If we're here, the guard can't chase enemy, can't find a physobject to attack with, and can't summon - //================================================== - -#ifdef HL2_EPISODIC - - DEFINE_SCHEDULE - ( - SCHED_ANTLIONGUARD_CANT_ATTACK, - - " Tasks" - " TASK_SET_ROUTE_SEARCH_TIME 2" // Spend 5 seconds trying to build a path if stuck - " TASK_GET_PATH_TO_RANDOM_NODE 1024" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_WAIT_PVS 0" - "" - " Interrupts" - " COND_GIVE_WAY" - " COND_NEW_ENEMY" - " COND_ANTLIONGUARD_PHYSICS_TARGET" - " COND_HEAVY_DAMAGE" - ) - -#else - - DEFINE_SCHEDULE - ( - SCHED_ANTLIONGUARD_CANT_ATTACK, - - " Tasks" - " TASK_WAIT 5" - "" - " Interrupts" - ) - -#endif - - //================================================== - // SCHED_ANTLIONGUARD_PHYSICS_DAMAGE_HEAVY - //================================================== - - DEFINE_SCHEDULE - ( - SCHED_ANTLIONGUARD_PHYSICS_DAMAGE_HEAVY, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_RESET_ACTIVITY 0" - " TASK_ANTLIONGUARD_SET_FLINCH_ACTIVITY 0" - "" - " Interrupts" - ) - - //================================================== - // SCHED_ANTLIONGUARD_UNBURROW - //================================================== - - DEFINE_SCHEDULE - ( - SCHED_ANTLIONGUARD_UNBURROW, - - " Tasks" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_ANTLIONGUARD_UNBURROW" - "" - " Interrupts" - ) - - //================================================== - // SCHED_ANTLIONGUARD_CHARGE_CANCEL - //================================================== - - DEFINE_SCHEDULE - ( - SCHED_ANTLIONGUARD_CHARGE_CANCEL, - - " Tasks" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_ANTLIONGUARD_CHARGE_CANCEL" - "" - " Interrupts" - ) - - //================================================== - // SCHED_ANTLIONGUARD_FIND_CHARGE_POSITION - //================================================== - - DEFINE_SCHEDULE - ( - SCHED_ANTLIONGUARD_FIND_CHARGE_POSITION, - - " Tasks" - " TASK_ANTLIONGUARD_GET_PATH_TO_CHARGE_POSITION 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " " - " Interrupts" - " COND_ENEMY_DEAD" - " COND_GIVE_WAY" - " COND_TASK_FAILED" - " COND_HEAVY_DAMAGE" - ) - - //========================================================= - // > SCHED_ANTLIONGUARD_CHASE_ENEMY_TOLERANCE - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_ANTLIONGUARD_CHASE_ENEMY_TOLERANCE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ANTLIONGUARD_PATROL_RUN" - " TASK_ANTLIONGUARD_GET_PATH_TO_NEAREST_NODE 500" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - " COND_TASK_FAILED" - " COND_CAN_MELEE_ATTACK1" - " COND_GIVE_WAY" - " COND_NEW_ENEMY" - " COND_ANTLIONGUARD_CAN_SUMMON" - " COND_ANTLIONGUARD_PHYSICS_TARGET" - " COND_HEAVY_DAMAGE" - " COND_ANTLIONGUARD_CAN_CHARGE" - ); - - //========================================================= - // > PATROL_RUN - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_ANTLIONGUARD_PATROL_RUN, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ANTLIONGUARD_CANT_ATTACK" - " TASK_SET_ROUTE_SEARCH_TIME 3" // Spend 3 seconds trying to build a path if stuck - " TASK_ANTLIONGUARD_GET_PATH_TO_NEAREST_NODE 500" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_TASK_FAILED" - " COND_CAN_MELEE_ATTACK1" - " COND_GIVE_WAY" - " COND_NEW_ENEMY" - " COND_ANTLIONGUARD_PHYSICS_TARGET" - " COND_ANTLIONGUARD_CAN_SUMMON" - " COND_HEAVY_DAMAGE" - " COND_ANTLIONGUARD_CAN_CHARGE" - ); - - //================================================== - // SCHED_ANTLIONGUARD_ROAR - //================================================== - - DEFINE_SCHEDULE - ( - SCHED_ANTLIONGUARD_ROAR, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_ANTLIONGUARD_ROAR" - " " - " Interrupts" - " COND_HEAVY_DAMAGE" - ) - - //================================================== - // SCHED_ANTLIONGUARD_TAKE_COVER_FROM_ENEMY - //================================================== - DEFINE_SCHEDULE - ( - SCHED_ANTLIONGUARD_TAKE_COVER_FROM_ENEMY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ANTLIONGUARD_CANT_ATTACK" - " TASK_FIND_COVER_FROM_ENEMY 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - "" - " Interrupts" - " COND_TASK_FAILED" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_ANTLIONGUARD_PHYSICS_TARGET" - " COND_ANTLIONGUARD_CAN_SUMMON" - " COND_HEAVY_DAMAGE" - ) - - //========================================================= - // SCHED_ANTLIONGUARD_CHASE_ENEMY - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_ANTLIONGUARD_CHASE_ENEMY, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_GET_CHASE_PATH_TO_ENEMY 300" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_ENEMY_UNREACHABLE" - " COND_CAN_RANGE_ATTACK1" - // " COND_CAN_MELEE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK2" - " COND_TOO_CLOSE_TO_ATTACK" - " COND_TASK_FAILED" - " COND_LOST_ENEMY" - " COND_HEAVY_DAMAGE" - " COND_ANTLIONGUARD_CAN_CHARGE" - ) - -AI_END_CUSTOM_NPC() diff --git a/game/server/hl2/npc_apcdriver.cpp b/game/server/hl2/npc_apcdriver.cpp deleted file mode 100644 index c5aa18937..000000000 --- a/game/server/hl2/npc_apcdriver.cpp +++ /dev/null @@ -1,298 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "npc_vehicledriver.h" -#include "vehicle_apc.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SF_APCDRIVER_NO_ROCKET_ATTACK 0x10000 -#define SF_APCDRIVER_NO_GUN_ATTACK 0x20000 - -#define NPC_APCDRIVER_REMEMBER_TIME 4 - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CNPC_APCDriver : public CNPC_VehicleDriver -{ - DECLARE_CLASS( CNPC_APCDriver, CNPC_VehicleDriver ); -public: - DECLARE_DATADESC(); - DEFINE_CUSTOM_AI; - - virtual void Spawn( void ); - virtual void Activate( void ); - - virtual bool FVisible( CBaseEntity *pTarget, int traceMask, CBaseEntity **ppBlocker ); - virtual bool WeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions ); - virtual Class_T Classify ( void ) { return CLASS_COMBINE; } - virtual void PrescheduleThink( ); - virtual Disposition_t IRelationType(CBaseEntity *pTarget); - - // AI - virtual int RangeAttack1Conditions( float flDot, float flDist ); - virtual int RangeAttack2Conditions( float flDot, float flDist ); - -private: - // Are we being carried by a dropship? - bool IsBeingCarried(); - - // Enable, disable firing - void InputEnableFiring( inputdata_t &inputdata ); - void InputDisableFiring( inputdata_t &inputdata ); - - CHandle m_hAPC; - float m_flTimeLastSeenEnemy; - bool m_bFiringDisabled; -}; - - -BEGIN_DATADESC( CNPC_APCDriver ) - - //DEFINE_FIELD( m_hAPC, FIELD_EHANDLE ), - DEFINE_FIELD( m_bFiringDisabled, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flTimeLastSeenEnemy, FIELD_TIME ), - - DEFINE_INPUTFUNC( FIELD_VOID, "EnableFiring", InputEnableFiring ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableFiring", InputDisableFiring ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( npc_apcdriver, CNPC_APCDriver ); - - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CNPC_APCDriver::Spawn( void ) -{ - BaseClass::Spawn(); - - m_flTimeLastSeenEnemy = -NPC_APCDRIVER_REMEMBER_TIME; - CapabilitiesClear(); - CapabilitiesAdd( bits_CAP_INNATE_RANGE_ATTACK1 | bits_CAP_INNATE_RANGE_ATTACK2 ); - m_bFiringDisabled = false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_APCDriver::Activate( void ) -{ - BaseClass::Activate(); - - m_hAPC = dynamic_cast((CBaseEntity*)m_hVehicleEntity); - if ( !m_hAPC ) - { - Warning( "npc_apcdriver %s couldn't find his apc named %s.\n", STRING(GetEntityName()), STRING(m_iszVehicleName) ); - UTIL_Remove( this ); - return; - } - SetParent( m_hAPC ); - SetAbsOrigin( m_hAPC->WorldSpaceCenter() ); - SetLocalAngles( vec3_angle ); - - m_flDistTooFar = m_hAPC->MaxAttackRange(); - SetDistLook( m_hAPC->MaxAttackRange() ); -} - - -//----------------------------------------------------------------------------- -// Enable, disable firing -//----------------------------------------------------------------------------- -void CNPC_APCDriver::InputEnableFiring( inputdata_t &inputdata ) -{ - m_bFiringDisabled = false; -} - -void CNPC_APCDriver::InputDisableFiring( inputdata_t &inputdata ) -{ - m_bFiringDisabled = true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Let's not hate things the APC makes -//----------------------------------------------------------------------------- -Disposition_t CNPC_APCDriver::IRelationType(CBaseEntity *pTarget) -{ - if ( pTarget == m_hAPC || (pTarget->GetOwnerEntity() == m_hAPC) ) - return D_LI; - - return BaseClass::IRelationType(pTarget); -} - - -//------------------------------------------------------------------------------ -// Are we being carried by a dropship? -//------------------------------------------------------------------------------ -bool CNPC_APCDriver::IsBeingCarried() -{ - // Inert if we're carried... - Vector vecVelocity; - m_hAPC->GetVelocity( &vecVelocity, NULL ); - return ( m_hAPC->GetMoveParent() != NULL ) || (fabs(vecVelocity.z) >= 15); -} - - - -//------------------------------------------------------------------------------ -// Is the enemy visible? -//------------------------------------------------------------------------------ -bool CNPC_APCDriver::WeaponLOSCondition(const Vector &ownerPos, const Vector &targetPos, bool bSetConditions) -{ - if ( m_hAPC->m_lifeState != LIFE_ALIVE ) - return false; - - if ( IsBeingCarried() || m_bFiringDisabled ) - return false; - - float flTargetDist = ownerPos.DistTo( targetPos ); - if (flTargetDist > m_hAPC->MaxAttackRange()) - return false; - - return true; -} - - -//----------------------------------------------------------------------------- -// Is the enemy visible? -//----------------------------------------------------------------------------- -bool CNPC_APCDriver::FVisible( CBaseEntity *pTarget, int traceMask, CBaseEntity **ppBlocker ) -{ - if ( m_hAPC->m_lifeState != LIFE_ALIVE ) - return false; - - if ( IsBeingCarried() || m_bFiringDisabled ) - return false; - - float flTargetDist = GetAbsOrigin().DistTo( pTarget->GetAbsOrigin() ); - if (flTargetDist > m_hAPC->MaxAttackRange()) - return false; - - bool bVisible = m_hAPC->FVisible( pTarget, traceMask, ppBlocker ); - if ( bVisible && (pTarget == GetEnemy()) ) - { - m_flTimeLastSeenEnemy = gpGlobals->curtime; - } - - if ( pTarget->IsPlayer() || pTarget->Classify() == CLASS_BULLSEYE ) - { - if (!bVisible) - { - if ( ( gpGlobals->curtime - m_flTimeLastSeenEnemy ) <= NPC_APCDRIVER_REMEMBER_TIME ) - return true; - } - } - - return bVisible; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int CNPC_APCDriver::RangeAttack1Conditions( float flDot, float flDist ) -{ - if ( HasSpawnFlags(SF_APCDRIVER_NO_GUN_ATTACK) ) - return COND_NONE; - - if ( m_hAPC->m_lifeState != LIFE_ALIVE ) - return COND_NONE; - - if ( IsBeingCarried() || m_bFiringDisabled ) - return COND_NONE; - - if ( !HasCondition( COND_SEE_ENEMY ) ) - return COND_NONE; - - if ( !m_hAPC->IsInPrimaryFiringCone() ) - return COND_NONE; - - // Vehicle not ready to fire again yet? - if ( m_pVehicleInterface->Weapon_PrimaryCanFireAt() > gpGlobals->curtime + 0.1f ) - return COND_NONE; - - float flMinDist, flMaxDist; - m_pVehicleInterface->Weapon_PrimaryRanges( &flMinDist, &flMaxDist ); - - if (flDist < flMinDist) - return COND_NONE; - - if (flDist > flMaxDist) - return COND_NONE; - - return COND_CAN_RANGE_ATTACK1; -} - -int CNPC_APCDriver::RangeAttack2Conditions( float flDot, float flDist ) -{ - if ( HasSpawnFlags(SF_APCDRIVER_NO_ROCKET_ATTACK) ) - return COND_NONE; - - if ( m_hAPC->m_lifeState != LIFE_ALIVE ) - return COND_NONE; - - if ( IsBeingCarried() || m_bFiringDisabled ) - return COND_NONE; - - if ( !HasCondition( COND_SEE_ENEMY ) ) - return COND_NONE; - - // Vehicle not ready to fire again yet? - if ( m_pVehicleInterface->Weapon_SecondaryCanFireAt() > gpGlobals->curtime + 0.1f ) - return COND_NONE; - - float flMinDist, flMaxDist; - m_pVehicleInterface->Weapon_SecondaryRanges( &flMinDist, &flMaxDist ); - - if (flDist < flMinDist) - return COND_NONE; - - if (flDist > flMaxDist) - return COND_NONE; - - return COND_CAN_RANGE_ATTACK2; -} - - -//----------------------------------------------------------------------------- -// Aim the laser dot! -//----------------------------------------------------------------------------- -void CNPC_APCDriver::PrescheduleThink( ) -{ - BaseClass::PrescheduleThink(); - - if ( m_hAPC->m_lifeState == LIFE_ALIVE ) - { - if ( GetEnemy() ) - { - m_hAPC->AimPrimaryWeapon( GetEnemy()->BodyTarget( GetAbsOrigin(), false ) ); - } - m_hAPC->AimSecondaryWeaponAt( GetEnemy() ); - } - else if ( m_hAPC->m_lifeState == LIFE_DEAD ) - { - UTIL_Remove( this ); - } -} - - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- -AI_BEGIN_CUSTOM_NPC( npc_apcdriver, CNPC_APCDriver ) - -AI_END_CUSTOM_NPC() diff --git a/game/server/hl2/npc_assassin.cpp b/game/server/hl2/npc_assassin.cpp deleted file mode 100644 index 536f47878..000000000 --- a/game/server/hl2/npc_assassin.cpp +++ /dev/null @@ -1,1104 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "ammodef.h" -#include "ai_hint.h" -#include "ai_navigator.h" -#include "npc_assassin.h" -#include "game.h" -#include "npcevent.h" -#include "engine/IEngineSound.h" -#include "ai_squad.h" -#include "ai_squadslot.h" -#include "ai_moveprobe.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar sk_assassin_health( "sk_assassin_health","150"); -ConVar g_debug_assassin( "g_debug_assassin", "0" ); - -//========================================================= -// Anim Events -//========================================================= -#define ASSASSIN_AE_FIRE_PISTOL_RIGHT 1 -#define ASSASSIN_AE_FIRE_PISTOL_LEFT 2 -#define ASSASSIN_AE_KICK_HIT 3 - -int AE_ASSASIN_FIRE_PISTOL_RIGHT; -int AE_ASSASIN_FIRE_PISTOL_LEFT; -int AE_ASSASIN_KICK_HIT; - -//========================================================= -// Assassin activities -//========================================================= -int ACT_ASSASSIN_FLIP_LEFT; -int ACT_ASSASSIN_FLIP_RIGHT; -int ACT_ASSASSIN_FLIP_BACK; -int ACT_ASSASSIN_FLIP_FORWARD; -int ACT_ASSASSIN_PERCH; - -//========================================================= -// Flip types -//========================================================= -enum -{ - FLIP_LEFT, - FLIP_RIGHT, - FLIP_FORWARD, - FLIP_BACKWARD, - NUM_FLIP_TYPES, -}; - -//========================================================= -// Private conditions -//========================================================= -enum Assassin_Conds -{ - COND_ASSASSIN_ENEMY_TARGETTING_ME = LAST_SHARED_CONDITION, -}; - -//========================================================= -// Assassin schedules -//========================================================= -enum -{ - SCHED_ASSASSIN_FIND_VANTAGE_POINT = LAST_SHARED_SCHEDULE, - SCHED_ASSASSIN_EVADE, - SCHED_ASSASSIN_STALK_ENEMY, - SCHED_ASSASSIN_LUNGE, -}; - -//========================================================= -// Assassin tasks -//========================================================= -enum -{ - TASK_ASSASSIN_GET_PATH_TO_VANTAGE_POINT = LAST_SHARED_TASK, - TASK_ASSASSIN_EVADE, - TASK_ASSASSIN_SET_EYE_STATE, - TASK_ASSASSIN_LUNGE, -}; - - -//----------------------------------------------------------------------------- -// Purpose: Class Constructor -//----------------------------------------------------------------------------- -CNPC_Assassin::CNPC_Assassin( void ) -{ -} - -//----------------------------------------------------------------------------- - -LINK_ENTITY_TO_CLASS( npc_assassin, CNPC_Assassin ); - -#if 0 -//--------------------------------------------------------- -// Custom Client entity -//--------------------------------------------------------- -IMPLEMENT_SERVERCLASS_ST(CNPC_Assassin, DT_NPC_Assassin) -END_SEND_TABLE() - -#endif - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CNPC_Assassin ) - DEFINE_FIELD( m_nNumFlips, FIELD_INTEGER ), - DEFINE_FIELD( m_nLastFlipType, FIELD_INTEGER ), - DEFINE_FIELD( m_flNextFlipTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextLungeTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextShotTime, FIELD_TIME ), - DEFINE_FIELD( m_bEvade, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bAggressive, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bBlinkState, FIELD_BOOLEAN ), - DEFINE_FIELD( m_pEyeSprite, FIELD_CLASSPTR ), - DEFINE_FIELD( m_pEyeTrail, FIELD_CLASSPTR ), -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CNPC_Assassin::Precache( void ) -{ - PrecacheModel( "models/fassassin.mdl" ); - - PrecacheScriptSound( "NPC_Assassin.ShootPistol" ); - PrecacheScriptSound( "Zombie.AttackHit" ); - PrecacheScriptSound( "Assassin.AttackMiss" ); - PrecacheScriptSound( "NPC_Assassin.Footstep" ); - - PrecacheModel( "sprites/redglow1.vmt" ); - - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CNPC_Assassin::Spawn( void ) -{ - Precache(); - - SetModel( "models/fassassin.mdl" ); - - SetHullType(HULL_HUMAN); - SetHullSizeNormal(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - SetBloodColor( BLOOD_COLOR_RED ); - - m_iHealth = sk_assassin_health.GetFloat(); - m_flFieldOfView = 0.1; - m_NPCState = NPC_STATE_NONE; - - CapabilitiesClear(); - CapabilitiesAdd( bits_CAP_MOVE_CLIMB | bits_CAP_MOVE_GROUND | bits_CAP_MOVE_JUMP ); - CapabilitiesAdd( bits_CAP_SQUAD | bits_CAP_USE_WEAPONS | bits_CAP_AIM_GUN | bits_CAP_INNATE_RANGE_ATTACK1 | bits_CAP_INNATE_RANGE_ATTACK2 | bits_CAP_INNATE_MELEE_ATTACK1 ); - - //Turn on our guns - SetBodygroup( 1, 1 ); - - int attachment = LookupAttachment( "Eye" ); - - // Start up the eye glow - m_pEyeSprite = CSprite::SpriteCreate( "sprites/redglow1.vmt", GetLocalOrigin(), false ); - - if ( m_pEyeSprite != NULL ) - { - m_pEyeSprite->SetAttachment( this, attachment ); - m_pEyeSprite->SetTransparency( kRenderTransAdd, 255, 255, 255, 200, kRenderFxNone ); - m_pEyeSprite->SetScale( 0.25f ); - } - - // Start up the eye trail - m_pEyeTrail = CSpriteTrail::SpriteTrailCreate( "sprites/bluelaser1.vmt", GetLocalOrigin(), false ); - - if ( m_pEyeTrail != NULL ) - { - m_pEyeTrail->SetAttachment( this, attachment ); - m_pEyeTrail->SetTransparency( kRenderTransAdd, 255, 0, 0, 200, kRenderFxNone ); - m_pEyeTrail->SetStartWidth( 8.0f ); - m_pEyeTrail->SetLifeTime( 0.75f ); - } - - NPCInit(); - - m_bEvade = false; - m_bAggressive = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true if a reasonable jumping distance -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CNPC_Assassin::IsJumpLegal(const Vector &startPos, const Vector &apex, const Vector &endPos) const -{ - const float MAX_JUMP_RISE = 256.0f; - const float MAX_JUMP_DISTANCE = 256.0f; - const float MAX_JUMP_DROP = 512.0f; - - return BaseClass::IsJumpLegal( startPos, apex, endPos, MAX_JUMP_RISE, MAX_JUMP_DROP, MAX_JUMP_DISTANCE ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flDot - -// flDist - -// Output : int CNPC_Assassin::MeleeAttack1Conditions -//----------------------------------------------------------------------------- -int CNPC_Assassin::MeleeAttack1Conditions ( float flDot, float flDist ) -{ - if ( flDist > 84 ) - return COND_TOO_FAR_TO_ATTACK; - - if ( flDot < 0.7f ) - return 0; - - if ( GetEnemy() == NULL ) - return 0; - - return COND_CAN_MELEE_ATTACK1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flDot - -// flDist - -// Output : int CNPC_Assassin::RangeAttack1Conditions -//----------------------------------------------------------------------------- -int CNPC_Assassin::RangeAttack1Conditions ( float flDot, float flDist ) -{ - if ( flDist < 84 ) - return COND_TOO_CLOSE_TO_ATTACK; - - if ( flDist > 1024 ) - return COND_TOO_FAR_TO_ATTACK; - - if ( flDot < 0.5f ) - return COND_NOT_FACING_ATTACK; - - return COND_CAN_RANGE_ATTACK1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flDot - -// flDist - -// Output : int CNPC_Assassin::RangeAttack1Conditions -//----------------------------------------------------------------------------- -int CNPC_Assassin::RangeAttack2Conditions ( float flDot, float flDist ) -{ - if ( m_flNextLungeTime > gpGlobals->curtime ) - return 0; - - float lungeRange = GetSequenceMoveDist( SelectWeightedSequence( (Activity) ACT_ASSASSIN_FLIP_FORWARD ) ); - - if ( flDist < lungeRange * 0.25f ) - return COND_TOO_CLOSE_TO_ATTACK; - - if ( flDist > lungeRange * 1.5f ) - return COND_TOO_FAR_TO_ATTACK; - - if ( flDot < 0.75f ) - return COND_NOT_FACING_ATTACK; - - if ( GetEnemy() == NULL ) - return 0; - - // Check for a clear path - trace_t tr; - UTIL_TraceHull( GetAbsOrigin(), GetEnemy()->GetAbsOrigin(), GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction == 1.0f || tr.m_pEnt == GetEnemy() ) - return COND_CAN_RANGE_ATTACK2; - - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : hand - -//----------------------------------------------------------------------------- -void CNPC_Assassin::FirePistol( int hand ) -{ - if ( m_flNextShotTime > gpGlobals->curtime ) - return; - - m_flNextShotTime = gpGlobals->curtime + random->RandomFloat( 0.05f, 0.15f ); - - Vector muzzlePos; - QAngle muzzleAngle; - - const char *handName = ( hand ) ? "LeftMuzzle" : "RightMuzzle"; - - GetAttachment( handName, muzzlePos, muzzleAngle ); - - Vector muzzleDir; - - if ( GetEnemy() == NULL ) - { - AngleVectors( muzzleAngle, &muzzleDir ); - } - else - { - muzzleDir = GetEnemy()->BodyTarget( muzzlePos ) - muzzlePos; - VectorNormalize( muzzleDir ); - } - - int bulletType = GetAmmoDef()->Index( "Pistol" ); - - FireBullets( 1, muzzlePos, muzzleDir, VECTOR_CONE_5DEGREES, 1024, bulletType, 2 ); - - UTIL_MuzzleFlash( muzzlePos, muzzleAngle, (int)0.5f, 1 ); - - CPASAttenuationFilter filter( this ); - EmitSound( filter, entindex(), "NPC_Assassin.ShootPistol" ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Assassin::HandleAnimEvent( animevent_t *pEvent ) -{ - - if ( pEvent->event == AE_ASSASIN_FIRE_PISTOL_RIGHT ) - { - FirePistol( 0 ); - return; - } - - if ( pEvent->event == AE_ASSASIN_FIRE_PISTOL_LEFT ) - { - FirePistol( 1 ); - return; - } - - if ( pEvent->event == AE_ASSASIN_KICK_HIT ) - { - Vector attackDir = BodyDirection2D(); - Vector attackPos = WorldSpaceCenter() + ( attackDir * 64.0f ); - - trace_t tr; - UTIL_TraceHull( WorldSpaceCenter(), attackPos, -Vector(8,8,8), Vector(8,8,8), MASK_SHOT_HULL, this, COLLISION_GROUP_NONE, &tr ); - - if ( ( tr.m_pEnt != NULL ) && ( tr.DidHitWorld() == false ) ) - { - if ( tr.m_pEnt->m_takedamage != DAMAGE_NO ) - { - CTakeDamageInfo info( this, this, 5, DMG_CLUB ); - CalculateMeleeDamageForce( &info, (tr.endpos - tr.startpos), tr.endpos ); - tr.m_pEnt->TakeDamage( info ); - - CBasePlayer *pPlayer = ToBasePlayer( tr.m_pEnt ); - - if ( pPlayer != NULL ) - { - //Kick the player angles - pPlayer->ViewPunch( QAngle( -30, 40, 10 ) ); - } - - EmitSound( "Zombie.AttackHit" ); - //EmitSound( "Assassin.AttackHit" ); - } - } - else - { - EmitSound( "Assassin.AttackMiss" ); - //EmitSound( "Assassin.AttackMiss" ); - } - - return; - } - - BaseClass::HandleAnimEvent( pEvent ); -} - -//----------------------------------------------------------------------------- -// Purpose: Causes the assassin to prefer to run away, rather than towards her target -//----------------------------------------------------------------------------- -bool CNPC_Assassin::MovementCost( int moveType, const Vector &vecStart, const Vector &vecEnd, float *pCost ) -{ - if ( GetEnemy() == NULL ) - return true; - - float multiplier = 1.0f; - - Vector moveDir = ( vecEnd - vecStart ); - VectorNormalize( moveDir ); - - Vector enemyDir = ( GetEnemy()->GetAbsOrigin() - vecStart ); - VectorNormalize( enemyDir ); - - // If we're moving towards our enemy, then the cost is much higher than normal - if ( DotProduct( enemyDir, moveDir ) > 0.5f ) - { - multiplier = 16.0f; - } - - *pCost *= multiplier; - - return ( multiplier != 1 ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CNPC_Assassin::SelectSchedule ( void ) -{ - switch ( m_NPCState ) - { - case NPC_STATE_IDLE: - case NPC_STATE_ALERT: - { - if ( HasCondition ( COND_HEAR_DANGER ) ) - return SCHED_TAKE_COVER_FROM_BEST_SOUND; - - if ( HasCondition ( COND_HEAR_COMBAT ) ) - return SCHED_INVESTIGATE_SOUND; - } - break; - - case NPC_STATE_COMBAT: - { - // dead enemy - if ( HasCondition( COND_ENEMY_DEAD ) ) - { - // call base class, all code to handle dead enemies is centralized there. - return BaseClass::SelectSchedule(); - } - - // Need to move - if ( /*( HasCondition( COND_SEE_ENEMY ) && HasCondition( COND_ASSASSIN_ENEMY_TARGETTING_ME ) && random->RandomInt( 0, 32 ) == 0 && m_flNextFlipTime < gpGlobals->curtime ) )*/ - ( m_nNumFlips > 0 ) || - ( ( HasCondition ( COND_LIGHT_DAMAGE ) && random->RandomInt( 0, 2 ) == 0 ) ) || ( HasCondition ( COND_HEAVY_DAMAGE ) ) ) - { - if ( m_nNumFlips <= 0 ) - { - m_nNumFlips = random->RandomInt( 1, 2 ); - } - - return SCHED_ASSASSIN_EVADE; - } - - // Can kick - if ( HasCondition( COND_CAN_MELEE_ATTACK1 ) ) - return SCHED_MELEE_ATTACK1; - - // Can shoot - if ( HasCondition( COND_CAN_RANGE_ATTACK2 ) ) - { - m_flNextLungeTime = gpGlobals->curtime + 2.0f; - m_nLastFlipType = FLIP_FORWARD; - - return SCHED_ASSASSIN_LUNGE; - } - - // Can shoot - if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - return SCHED_RANGE_ATTACK1; - - // Face our enemy - if ( HasCondition( COND_SEE_ENEMY ) ) - return SCHED_COMBAT_FACE; - - // new enemy - if ( HasCondition( COND_NEW_ENEMY ) ) - return SCHED_TAKE_COVER_FROM_ENEMY; - - // ALERT( at_console, "stand\n"); - return SCHED_ASSASSIN_FIND_VANTAGE_POINT; - } - break; - - default: - break; - } - - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Assassin::PrescheduleThink( void ) -{ - if ( GetActivity() == ACT_RUN || GetActivity() == ACT_WALK) - { - CPASAttenuationFilter filter( this ); - - static int iStep = 0; - iStep = ! iStep; - if (iStep) - { - EmitSound( filter, entindex(), "NPC_Assassin.Footstep" ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : right - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Assassin::CanFlip( int flipType, Activity &activity, const Vector *avoidPosition ) -{ - Vector testDir; - Activity act = ACT_INVALID; - - switch( flipType ) - { - case FLIP_RIGHT: - GetVectors( NULL, &testDir, NULL ); - act = NPC_TranslateActivity( (Activity) ACT_ASSASSIN_FLIP_RIGHT ); - break; - - case FLIP_LEFT: - GetVectors( NULL, &testDir, NULL ); - testDir.Negate(); - act = NPC_TranslateActivity( (Activity) ACT_ASSASSIN_FLIP_LEFT ); - break; - - case FLIP_FORWARD: - GetVectors( &testDir, NULL, NULL ); - act = NPC_TranslateActivity( (Activity) ACT_ASSASSIN_FLIP_FORWARD ); - break; - - case FLIP_BACKWARD: - GetVectors( &testDir, NULL, NULL ); - testDir.Negate(); - act = NPC_TranslateActivity( (Activity) ACT_ASSASSIN_FLIP_BACK ); - break; - - default: - assert(0); //NOTENOTE: Invalid flip type - activity = ACT_INVALID; - return false; - break; - } - - // Make sure we don't flip towards our avoidance position/ - if ( avoidPosition != NULL ) - { - Vector avoidDir = (*avoidPosition) - GetAbsOrigin(); - VectorNormalize( avoidDir ); - - if ( DotProduct( avoidDir, testDir ) > 0.0f ) - return false; - } - - int seq = SelectWeightedSequence( act ); - - // Find out the length of this sequence - float testDist = GetSequenceMoveDist( seq ); - - // Find the resulting end position from the sequence's movement - Vector endPos = GetAbsOrigin() + ( testDir * testDist ); - - trace_t tr; - - if ( ( flipType != FLIP_BACKWARD ) && ( avoidPosition != NULL ) ) - { - UTIL_TraceLine( (*avoidPosition), endPos, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction == 1.0f ) - return false; - } - - /* - UTIL_TraceHull( GetAbsOrigin(), endPos, NAI_Hull::Mins(m_eHull) + Vector( 0, 0, StepHeight() ), NAI_Hull::Maxs(m_eHull), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - - // See if we're hit an obstruction in that direction - if ( tr.fraction < 1.0f ) - { - if ( g_debug_assassin.GetBool() ) - { - NDebugOverlay::BoxDirection( GetAbsOrigin(), NAI_Hull::Mins(m_eHull) + Vector( 0, 0, StepHeight() ), NAI_Hull::Maxs(m_eHull) + Vector( testDist, 0, StepHeight() ), testDir, 255, 0, 0, true, 2.0f ); - } - - return false; - } - -#define NUM_STEPS 2 - - float stepLength = testDist / NUM_STEPS; - - for ( int i = 1; i <= NUM_STEPS; i++ ) - { - endPos = GetAbsOrigin() + ( testDir * (stepLength*i) ); - - // Also check for a cliff edge - UTIL_TraceHull( endPos, endPos - Vector( 0, 0, StepHeight() * 4.0f ), NAI_Hull::Mins(m_eHull) + Vector( 0, 0, StepHeight() ), NAI_Hull::Maxs(m_eHull), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction == 1.0f ) - { - if ( g_debug_assassin.GetBool() ) - { - NDebugOverlay::BoxDirection( endPos, NAI_Hull::Mins(m_eHull) + Vector( 0, 0, StepHeight() ), NAI_Hull::Maxs(m_eHull) + Vector( StepHeight() * 4.0f, 0, StepHeight() ), Vector(0,0,-1), 255, 0, 0, true, 2.0f ); - } - - return false; - } - } - - if ( g_debug_assassin.GetBool() ) - { - NDebugOverlay::BoxDirection( GetAbsOrigin(), NAI_Hull::Mins(m_eHull) + Vector( 0, 0, StepHeight() ), NAI_Hull::Maxs(m_eHull) + Vector( testDist, 0, StepHeight() ), testDir, 0, 255, 0, true, 2.0f ); - } - */ - - AIMoveTrace_t moveTrace; - GetMoveProbe()->TestGroundMove( GetAbsOrigin(), endPos, MASK_NPCSOLID, AITGM_DEFAULT, &moveTrace ); - - if ( moveTrace.fStatus != AIMR_OK ) - return false; - - // Return the activity to use - activity = (Activity) act; - - return true; -} - -//--------------------------------------------------------- -// Purpose: -//--------------------------------------------------------- -void CNPC_Assassin::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_ASSASSIN_SET_EYE_STATE: - { - SetEyeState( (eyeState_t) ( (int) pTask->flTaskData ) ); - TaskComplete(); - } - break; - - case TASK_ASSASSIN_EVADE: - { - Activity flipAct = ACT_INVALID; - - const Vector *avoidPos = ( GetEnemy() != NULL ) ? &(GetEnemy()->GetAbsOrigin()) : NULL; - - for ( int i = FLIP_LEFT; i < NUM_FLIP_TYPES; i++ ) - { - if ( CanFlip( i, flipAct, avoidPos ) ) - { - // Don't flip back to where we just were - if ( ( ( i == FLIP_LEFT ) && ( m_nLastFlipType == FLIP_RIGHT ) ) || - ( ( i == FLIP_RIGHT ) && ( m_nLastFlipType == FLIP_LEFT ) ) || - ( ( i == FLIP_FORWARD ) && ( m_nLastFlipType == FLIP_BACKWARD ) ) || - ( ( i == FLIP_BACKWARD ) && ( m_nLastFlipType == FLIP_FORWARD ) ) ) - { - flipAct = ACT_INVALID; - continue; - } - - m_nNumFlips--; - ResetIdealActivity( flipAct ); - m_flNextFlipTime = gpGlobals->curtime + 2.0f; - m_nLastFlipType = i; - break; - } - } - - if ( flipAct == ACT_INVALID ) - { - m_nNumFlips = 0; - m_nLastFlipType = -1; - m_flNextFlipTime = gpGlobals->curtime + 2.0f; - TaskFail( "Unable to find flip evasion direction!\n" ); - } - } - break; - - case TASK_ASSASSIN_GET_PATH_TO_VANTAGE_POINT: - { - assert( GetEnemy() != NULL ); - if ( GetEnemy() == NULL ) - break; - - Vector goalPos; - - CHintCriteria hint; - - // Find a disadvantage node near the player, but away from ourselves - hint.SetHintType( HINT_TACTICAL_ENEMY_DISADVANTAGED ); - hint.AddExcludePosition( GetAbsOrigin(), 256 ); - hint.AddExcludePosition( GetEnemy()->GetAbsOrigin(), 256 ); - - if ( ( m_pSquad != NULL ) && ( m_pSquad->NumMembers() > 1 ) ) - { - AISquadIter_t iter; - for ( CAI_BaseNPC *pSquadMember = m_pSquad->GetFirstMember( &iter ); pSquadMember; pSquadMember = m_pSquad->GetNextMember( &iter ) ) - { - if ( pSquadMember == NULL ) - continue; - - hint.AddExcludePosition( pSquadMember->GetAbsOrigin(), 128 ); - } - } - - hint.SetFlag( bits_HINT_NODE_NEAREST ); - - CAI_Hint *pHint = CAI_HintManager::FindHint( this, GetEnemy()->GetAbsOrigin(), hint ); - - if ( pHint == NULL ) - { - TaskFail( "Unable to find vantage point!\n" ); - break; - } - - pHint->GetPosition( this, &goalPos ); - - AI_NavGoal_t goal( goalPos ); - - //Try to run directly there - if ( GetNavigator()->SetGoal( goal ) == false ) - { - TaskFail( "Unable to find path to vantage point!\n" ); - break; - } - - TaskComplete(); - } - break; - - default: - BaseClass::StartTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -float CNPC_Assassin::MaxYawSpeed( void ) -{ - switch( GetActivity() ) - { - case ACT_TURN_LEFT: - case ACT_TURN_RIGHT: - return 160; - break; - case ACT_RUN: - return 900; - break; - case ACT_RANGE_ATTACK1: - return 0; - break; - default: - return 60; - break; - } -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Assassin::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_ASSASSIN_EVADE: - - AutoMovement(); - - if ( IsActivityFinished() ) - { - TaskComplete(); - } - - break; - - default: - BaseClass::RunTask( pTask ); - break; - } -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Assassin::FValidateHintType ( CAI_Hint *pHint ) -{ - switch( pHint->HintType() ) - { - case HINT_TACTICAL_ENEMY_DISADVANTAGED: - { - Vector hintPos; - pHint->GetPosition( this, &hintPos ); - - // Verify that we can see the target from that position - hintPos += GetViewOffset(); - - trace_t tr; - UTIL_TraceLine( hintPos, GetEnemy()->BodyTarget( hintPos, true ), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - // Check for seeing our target at the new location - if ( ( tr.fraction == 1.0f ) || ( tr.m_pEnt == GetEnemy() ) ) - return false; - - return true; - break; - } - - default: - return false; - break; - } - - return FALSE; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const Vector -//----------------------------------------------------------------------------- -const Vector &CNPC_Assassin::GetViewOffset( void ) -{ - static Vector eyeOffset; - - //FIXME: Use eye attachment? - // If we're crouching, offset appropriately - if ( ( GetActivity() == ACT_ASSASSIN_PERCH ) || - ( GetActivity() == ACT_RANGE_ATTACK1 ) ) - { - eyeOffset = Vector( 0, 0, 24.0f ); - } - else - { - eyeOffset = BaseClass::GetViewOffset(); - } - - return eyeOffset; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Assassin::OnScheduleChange( void ) -{ - //TODO: Change eye state? - - BaseClass::OnScheduleChange(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : state - -//----------------------------------------------------------------------------- -void CNPC_Assassin::SetEyeState( eyeState_t state ) -{ - //Must have a valid eye to affect - if ( ( m_pEyeSprite == NULL ) || ( m_pEyeTrail == NULL ) ) - return; - - //Set the state - switch( state ) - { - default: - case ASSASSIN_EYE_SEE_TARGET: //Fade in and scale up - m_pEyeSprite->SetColor( 255, 0, 0 ); - m_pEyeSprite->SetBrightness( 164, 0.1f ); - m_pEyeSprite->SetScale( 0.4f, 0.1f ); - - m_pEyeTrail->SetColor( 255, 0, 0 ); - m_pEyeTrail->SetScale( 8.0f ); - m_pEyeTrail->SetBrightness( 164 ); - - break; - - case ASSASSIN_EYE_SEEKING_TARGET: //Ping-pongs - - //Toggle our state - m_bBlinkState = !m_bBlinkState; - m_pEyeSprite->SetColor( 255, 128, 0 ); - - if ( m_bBlinkState ) - { - //Fade up and scale up - m_pEyeSprite->SetScale( 0.25f, 0.1f ); - m_pEyeSprite->SetBrightness( 164, 0.1f ); - } - else - { - //Fade down and scale down - m_pEyeSprite->SetScale( 0.2f, 0.1f ); - m_pEyeSprite->SetBrightness( 64, 0.1f ); - } - - break; - - case ASSASSIN_EYE_DORMANT: //Fade out and scale down - m_pEyeSprite->SetScale( 0.5f, 0.5f ); - m_pEyeSprite->SetBrightness( 64, 0.5f ); - - m_pEyeTrail->SetScale( 2.0f ); - m_pEyeTrail->SetBrightness( 64 ); - break; - - case ASSASSIN_EYE_DEAD: //Fade out slowly - m_pEyeSprite->SetColor( 255, 0, 0 ); - m_pEyeSprite->SetScale( 0.1f, 5.0f ); - m_pEyeSprite->SetBrightness( 0, 5.0f ); - - m_pEyeTrail->SetColor( 255, 0, 0 ); - m_pEyeTrail->SetScale( 0.1f ); - m_pEyeTrail->SetBrightness( 0 ); - break; - - case ASSASSIN_EYE_ACTIVE: - m_pEyeSprite->SetColor( 255, 0, 0 ); - m_pEyeSprite->SetScale( 0.1f ); - m_pEyeSprite->SetBrightness( 0 ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Assassin::GatherEnemyConditions( CBaseEntity *pEnemy ) -{ - ClearCondition( COND_ASSASSIN_ENEMY_TARGETTING_ME ); - - BaseClass::GatherEnemyConditions( pEnemy ); - - // See if we're being targetted specifically - if ( HasCondition( COND_ENEMY_FACING_ME ) ) - { - Vector enemyDir = GetAbsOrigin() - pEnemy->GetAbsOrigin(); - VectorNormalize( enemyDir ); - - Vector enemyBodyDir; - CBasePlayer *pPlayer = ToBasePlayer( pEnemy ); - - if ( pPlayer != NULL ) - { - enemyBodyDir = pPlayer->BodyDirection3D(); - } - else - { - AngleVectors( pEnemy->GetAbsAngles(), &enemyBodyDir ); - } - - float enemyDot = DotProduct( enemyBodyDir, enemyDir ); - - //FIXME: Need to refine this a bit - if ( enemyDot > 0.97f ) - { - SetCondition( COND_ASSASSIN_ENEMY_TARGETTING_ME ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Assassin::BuildScheduleTestBits( void ) -{ - SetNextThink( gpGlobals->curtime + 0.05 ); - - //Don't allow any modifications when scripted - if ( m_NPCState == NPC_STATE_SCRIPT ) - return; - - //Become interrupted if we're targetted when shooting an enemy - if ( IsCurSchedule( SCHED_RANGE_ATTACK1 ) ) - { - SetCustomInterruptCondition( COND_ASSASSIN_ENEMY_TARGETTING_ME ); - } - -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -//----------------------------------------------------------------------------- -void CNPC_Assassin::Event_Killed( const CTakeDamageInfo &info ) -{ - BaseClass::Event_Killed( info ); - - // Turn off the eye - SetEyeState( ASSASSIN_EYE_DEAD ); - - // Turn off the pistols - SetBodygroup( 1, 0 ); - - // Spawn her guns -} - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC( npc_assassin, CNPC_Assassin ) - - DECLARE_ACTIVITY(ACT_ASSASSIN_FLIP_LEFT) - DECLARE_ACTIVITY(ACT_ASSASSIN_FLIP_RIGHT) - DECLARE_ACTIVITY(ACT_ASSASSIN_FLIP_BACK) - DECLARE_ACTIVITY(ACT_ASSASSIN_FLIP_FORWARD) - DECLARE_ACTIVITY(ACT_ASSASSIN_PERCH) - - //Adrian: events go here - DECLARE_ANIMEVENT( AE_ASSASIN_FIRE_PISTOL_RIGHT ) - DECLARE_ANIMEVENT( AE_ASSASIN_FIRE_PISTOL_LEFT ) - DECLARE_ANIMEVENT( AE_ASSASIN_KICK_HIT ) - - DECLARE_TASK(TASK_ASSASSIN_GET_PATH_TO_VANTAGE_POINT) - DECLARE_TASK(TASK_ASSASSIN_EVADE) - DECLARE_TASK(TASK_ASSASSIN_SET_EYE_STATE) - DECLARE_TASK(TASK_ASSASSIN_LUNGE) - - DECLARE_CONDITION(COND_ASSASSIN_ENEMY_TARGETTING_ME) - - //========================================================= - // ASSASSIN_STALK_ENEMY - //========================================================= - - DEFINE_SCHEDULE - ( - SCHED_ASSASSIN_STALK_ENEMY, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_PLAY_SEQUENCE_FACE_ENEMY ACTIVITY:ACT_ASSASSIN_PERCH" - " " - " Interrupts" - " COND_ASSASSIN_ENEMY_TARGETTING_ME" - " COND_SEE_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - ) - - //========================================================= - // > ASSASSIN_FIND_VANTAGE_POINT - //========================================================= - - DEFINE_SCHEDULE - ( - SCHED_ASSASSIN_FIND_VANTAGE_POINT, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_TAKE_COVER_FROM_ENEMY" - " TASK_STOP_MOVING 0" - " TASK_ASSASSIN_GET_PATH_TO_VANTAGE_POINT 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_ASSASSIN_STALK_ENEMY" - " " - " Interrupts" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_TASK_FAILED" - ) - - //========================================================= - // Assassin needs to avoid the player - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_ASSASSIN_EVADE, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ASSASSIN_FIND_VANTAGE_POINT" - " TASK_STOP_MOVING 0" - " TASK_ASSASSIN_EVADE 0" - " " - " Interrupts" - " COND_TASK_FAILED" - ) - - //========================================================= - // Assassin needs to avoid the player - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_ASSASSIN_LUNGE, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ASSASSIN_FIND_VANTAGE_POINT" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_ASSASSIN_FLIP_FORWARD" - " " - " Interrupts" - " COND_TASK_FAILED" - ) - -AI_END_CUSTOM_NPC() diff --git a/game/server/hl2/npc_assassin.h b/game/server/hl2/npc_assassin.h deleted file mode 100644 index 90572f848..000000000 --- a/game/server/hl2/npc_assassin.h +++ /dev/null @@ -1,90 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef NPC_ASSASSIN_H -#define NPC_ASSASSIN_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_basenpc.h" -#include "Sprite.h" -#include "SpriteTrail.h" -#include "soundent.h" - -//Eye states -enum eyeState_t -{ - ASSASSIN_EYE_SEE_TARGET = 0, //Sees the target, bright and big - ASSASSIN_EYE_SEEKING_TARGET, //Looking for a target, blinking (bright) - ASSASSIN_EYE_ACTIVE, //Actively looking - ASSASSIN_EYE_DORMANT, //Not active - ASSASSIN_EYE_DEAD, //Completely invisible -}; - -//========================================================= -//========================================================= -class CNPC_Assassin : public CAI_BaseNPC -{ -public: - DECLARE_CLASS( CNPC_Assassin, CAI_BaseNPC ); - // DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - CNPC_Assassin( void ); - - Class_T Classify( void ) { return CLASS_COMBINE; } - int GetSoundInterests ( void ) { return (SOUND_WORLD|SOUND_COMBAT|SOUND_PLAYER); } - - int SelectSchedule ( void ); - int MeleeAttack1Conditions ( float flDot, float flDist ); - int RangeAttack1Conditions ( float flDot, float flDist ); - int RangeAttack2Conditions ( float flDot, float flDist ); - - void Precache( void ); - void Spawn( void ); - void PrescheduleThink( void ); - void HandleAnimEvent( animevent_t *pEvent ); - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - void OnScheduleChange( void ); - void GatherEnemyConditions( CBaseEntity *pEnemy ); - void BuildScheduleTestBits( void ); - void Event_Killed( const CTakeDamageInfo &info ); - - bool FValidateHintType ( CAI_Hint *pHint ); - bool IsJumpLegal(const Vector &startPos, const Vector &apex, const Vector &endPos) const; - bool MovementCost( int moveType, const Vector &vecStart, const Vector &vecEnd, float *pCost ); - - float MaxYawSpeed( void ); - - const Vector &GetViewOffset( void ); - -private: - - void SetEyeState( eyeState_t state ); - void FirePistol( int hand ); - bool CanFlip( int flipType, Activity &activity, const Vector *avoidPosition ); - - int m_nNumFlips; - int m_nLastFlipType; - float m_flNextFlipTime; //Next earliest time the assassin can flip again - float m_flNextLungeTime; - float m_flNextShotTime; - - bool m_bEvade; - bool m_bAggressive; // Sets certain state, including whether or not her eye is visible - bool m_bBlinkState; - - CSprite *m_pEyeSprite; - CSpriteTrail *m_pEyeTrail; - - DEFINE_CUSTOM_AI; -}; - - -#endif // NPC_ASSASSIN_H diff --git a/game/server/hl2/npc_attackchopper.cpp b/game/server/hl2/npc_attackchopper.cpp deleted file mode 100644 index ba04e439c..000000000 --- a/game/server/hl2/npc_attackchopper.cpp +++ /dev/null @@ -1,6117 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#include "cbase.h" -#include "ai_network.h" -#include "ai_default.h" -#include "ai_schedule.h" -#include "ai_hull.h" -#include "ai_node.h" -#include "ai_task.h" -#include "entitylist.h" -#include "basecombatweapon.h" -#include "soundenvelope.h" -#include "gib.h" -#include "gamerules.h" -#include "ammodef.h" -#include "grenade_homer.h" -#include "cbasehelicopter.h" -#include "engine/IEngineSound.h" -#include "IEffects.h" -#include "globals.h" -#include "explode.h" -#include "movevars_shared.h" -#include "smoke_trail.h" -#include "ar2_explosion.h" -#include "collisionutils.h" -#include "props.h" -#include "EntityFlame.h" -#include "decals.h" -#include "effect_dispatch_data.h" -#include "te_effect_dispatch.h" -#include "ai_spotlight.h" -#include "vphysics/constraints.h" -#include "physics_saverestore.h" -#include "ai_memory.h" -#include "npc_attackchopper.h" - -#ifdef HL2_EPISODIC -#include "physics_bone_follower.h" -#endif // HL2_EPISODIC - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// ------------------------------------- -// Bone controllers -// ------------------------------------- -#define CHOPPER_DRONE_NAME "models/combine_helicopter/helicopter_bomb01.mdl" -#define CHOPPER_MODEL_NAME "models/combine_helicopter.mdl" -#define CHOPPER_MODEL_CORPSE_NAME "models/combine_helicopter_broken.mdl" -#define CHOPPER_RED_LIGHT_SPRITE "sprites/redglow1.vmt" - -#define CHOPPER_MAX_SMALL_CHUNKS 1 -#define CHOPPER_MAX_CHUNKS 3 -static const char *s_pChunkModelName[CHOPPER_MAX_CHUNKS] = -{ - "models/gibs/helicopter_brokenpiece_01.mdl", - "models/gibs/helicopter_brokenpiece_02.mdl", - "models/gibs/helicopter_brokenpiece_03.mdl", -}; - -#define BOMB_SKIN_LIGHT_ON 1 -#define BOMB_SKIN_LIGHT_OFF 0 - - -#define HELICOPTER_CHUNK_COCKPIT "models/gibs/helicopter_brokenpiece_04_cockpit.mdl" -#define HELICOPTER_CHUNK_TAIL "models/gibs/helicopter_brokenpiece_05_tailfan.mdl" -#define HELICOPTER_CHUNK_BODY "models/gibs/helicopter_brokenpiece_06_body.mdl" - - -#define CHOPPER_MAX_SPEED (60 * 17.6f) -#define CHOPPER_MAX_FIRING_SPEED 250.0f -#define CHOPPER_MAX_GUN_DIST 2000.0f - -#define CHOPPER_ACCEL_RATE 500 -#define CHOPPER_ACCEL_RATE_BOOST 1500 - -#define DEFAULT_FREE_KNOWLEDGE_DURATION 5.0f - -// ------------------------------------- -// Pathing data -#define CHOPPER_LEAD_DISTANCE 800.0f -#define CHOPPER_MIN_CHASE_DIST_DIFF 128.0f // Distance threshold used to determine when a target has moved enough to update our navigation to it -#define CHOPPER_MIN_AGGRESSIVE_CHASE_DIST_DIFF 64.0f -#define CHOPPER_AVOID_DIST 512.0f -#define CHOPPER_ARRIVE_DIST 128.0f - -#define CHOPPER_MAX_CIRCLE_OF_DEATH_FOLLOW_SPEED 450.0f -#define CHOPPER_MIN_CIRCLE_OF_DEATH_RADIUS 150.0f -#define CHOPPER_MAX_CIRCLE_OF_DEATH_RADIUS 350.0f - -#define CHOPPER_BOMB_DROP_COUNT 6 - -// Bullrush -#define CHOPPER_BULLRUSH_MODE_DISTANCE g_helicopter_bullrush_distance.GetFloat() -#define CHOPPER_BULLRUSH_ENEMY_BOMB_DISTANCE g_helicopter_bullrush_bomb_enemy_distance.GetFloat() -#define CHOPPER_BULLRUSH_ENEMY_BOMB_TIME g_helicopter_bullrush_bomb_time.GetFloat() -#define CHOPPER_BULLRUSH_ENEMY_BOMB_SPEED g_helicopter_bullrush_bomb_speed.GetFloat() -#define CHOPPER_BULLRUSH_SHOOTING_VERTICAL_OFFSET g_helicopter_bullrush_shoot_height.GetFloat() - -#define CHOPPER_GUN_CHARGE_TIME g_helicopter_chargetime.GetFloat() -#define CHOPPER_GUN_IDLE_TIME g_helicopter_idletime.GetFloat() -#define CHOPPER_GUN_MAX_FIRING_DIST g_helicopter_maxfiringdist.GetFloat() - -#define BULLRUSH_IDLE_PLAYER_FIRE_TIME 6.0f - -#define DRONE_SPEED sk_helicopter_drone_speed.GetFloat() - -#define SF_HELICOPTER_LOUD_ROTOR_SOUND 0x00010000 -#define SF_HELICOPTER_ELECTRICAL_DRONE 0x00020000 -#define SF_HELICOPTER_LIGHTS 0x00040000 -#define SF_HELICOPTER_IGNORE_AVOID_FORCES 0x00080000 -#define SF_HELICOPTER_AGGRESSIVE 0x00100000 -#define SF_HELICOPTER_LONG_SHADOW 0x00200000 - -#define CHOPPER_SLOW_BOMB_SPEED 250 - -#define CHOPPER_BULLRUSH_SLOW_SHOOT_SPEED 250 -#define CHOPPER_BULLRUSH_SLOW_SHOOT_SPEED_SQ (CHOPPER_BULLRUSH_SLOW_SHOOT_SPEED * CHOPPER_BULLRUSH_SLOW_SHOOT_SPEED) - -#define CHOPPER_BULLRUSH_SLOW_SHOOT_SPEED_2 450 -#define CHOPPER_BULLRUSH_SLOW_SHOOT_SPEED_2_SQ (CHOPPER_BULLRUSH_SLOW_SHOOT_SPEED_2 * CHOPPER_BULLRUSH_SLOW_SHOOT_SPEED_2) - -// CVars -ConVar sk_helicopter_health( "sk_helicopter_health","5600"); -ConVar sk_helicopter_firingcone( "sk_helicopter_firingcone","20.0", 0, "The angle in degrees of the cone in which the shots will be fired" ); -ConVar sk_helicopter_burstcount( "sk_helicopter_burstcount","12", 0, "How many shot bursts to fire after charging up. The bigger the number, the longer the firing is" ); -ConVar sk_helicopter_roundsperburst( "sk_helicopter_roundsperburst","5", 0, "How many shots to fire in a single burst" ); - -ConVar sk_helicopter_grenadedamage( "sk_helicopter_grenadedamage","25.0", 0, "The amount of damage the helicopter grenade deals." ); -ConVar sk_helicopter_grenaderadius( "sk_helicopter_grenaderadius","275.0", 0, "The damage radius of the helicopter grenade." ); -ConVar sk_helicopter_grenadeforce( "sk_helicopter_grenadeforce","55000.0", 0, "The physics force that the helicopter grenade exerts." ); -ConVar sk_helicopter_grenade_puntscale( "sk_helicopter_grenade_puntscale","1.5", 0, "When physpunting a chopper's grenade, scale its velocity by this much." ); - -// Number of bomb hits it takes to kill a chopper on each skill level. -ConVar sk_helicopter_num_bombs1("sk_helicopter_num_bombs1", "3"); -ConVar sk_helicopter_num_bombs2("sk_helicopter_num_bombs2", "5"); -ConVar sk_helicopter_num_bombs3("sk_helicopter_num_bombs3", "5"); - -ConVar sk_npc_dmg_helicopter_to_plr( "sk_npc_dmg_helicopter_to_plr","3", 0, "Damage helicopter shots deal to the player" ); -ConVar sk_npc_dmg_helicopter( "sk_npc_dmg_helicopter","6", 0, "Damage helicopter shots deal to everything but the player" ); - -ConVar sk_helicopter_drone_speed( "sk_helicopter_drone_speed","450.0", 0, "How fast does the zapper drone move?" ); - -ConVar g_helicopter_chargetime( "g_helicopter_chargetime","2.0", 0, "How much time we have to wait (on average) between the time we start hearing the charging sound + the chopper fires" ); -ConVar g_helicopter_bullrush_distance("g_helicopter_bullrush_distance", "5000"); -ConVar g_helicopter_bullrush_bomb_enemy_distance("g_helicopter_bullrush_bomb_enemy_distance", "0"); -ConVar g_helicopter_bullrush_bomb_time("g_helicopter_bullrush_bomb_time", "10"); -ConVar g_helicopter_idletime( "g_helicopter_idletime","3.0", 0, "How much time we have to wait (on average) after we fire before we can charge up again" ); -ConVar g_helicopter_maxfiringdist( "g_helicopter_maxfiringdist","2500.0", 0, "The maximum distance the player can be from the chopper before it stops firing" ); -ConVar g_helicopter_bullrush_bomb_speed( "g_helicopter_bullrush_bomb_speed","850.0", 0, "The maximum distance the player can be from the chopper before it stops firing" ); -ConVar g_helicopter_bullrush_shoot_height( "g_helicopter_bullrush_shoot_height","650.0", 0, "The maximum distance the player can be from the chopper before it stops firing" ); -ConVar g_helicopter_bullrush_mega_bomb_health( "g_helicopter_bullrush_mega_bomb_health","0.25", 0, "Fraction of the health of the chopper before it mega-bombs" ); - -ConVar g_helicopter_bomb_danger_radius( "g_helicopter_bomb_danger_radius", "120" ); - -Activity ACT_HELICOPTER_DROP_BOMB; -Activity ACT_HELICOPTER_CRASHING; - -static const char *s_pBlinkLightThinkContext = "BlinkLights"; -static const char *s_pSpotlightThinkContext = "SpotlightThink"; -static const char *s_pRampSoundContext = "RampSound"; -static const char *s_pWarningBlinkerContext = "WarningBlinker"; -static const char *s_pAnimateThinkContext = "Animate"; - -#define CHOPPER_LIGHT_BLINK_TIME 1.0f -#define CHOPPER_LIGHT_BLINK_TIME_SHORT 0.1f - -#define BOMB_LIFETIME 2.5f // Don't access this directly. Call GetBombLifetime(); -#define BOMB_RAMP_SOUND_TIME 1.0f - -enum -{ - MAX_HELICOPTER_LIGHTS = 3, -}; - -enum -{ - SF_GRENADE_HELICOPTER_MEGABOMB = 0x1, -}; - -#define GRENADE_HELICOPTER_MODEL "models/combine_helicopter/helicopter_bomb01.mdl" - -LINK_ENTITY_TO_CLASS( info_target_helicopter_crash, CPointEntity ); - - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -static inline float ClampSplineRemapVal( float flValue, float flMinValue, float flMaxValue, float flOutMin, float flOutMax ) -{ - Assert( flMinValue <= flMaxValue ); - float flClampedVal = clamp( flValue, flMinValue, flMaxValue ); - return SimpleSplineRemapVal( flClampedVal, flMinValue, flMaxValue, flOutMin, flOutMax ); -} - - -//----------------------------------------------------------------------------- -// The bombs the attack helicopter drops -//----------------------------------------------------------------------------- -enum -{ - SKIN_REGULAR, - SKIN_DUD, -}; - -class CGrenadeHelicopter : public CBaseGrenade -{ - DECLARE_DATADESC(); - -public: - DECLARE_CLASS( CGrenadeHelicopter, CBaseGrenade ); - - virtual void Precache( ); - virtual void Spawn( ); - virtual void UpdateOnRemove(); - virtual void OnEntityEvent( EntityEvent_t event, void *pEventData ); - virtual void PhysicsSimulate( void ); - virtual float GetShakeAmplitude( void ) { return 25.0; } - virtual float GetShakeRadius( void ) { return sk_helicopter_grenaderadius.GetFloat() * 2; } - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - virtual void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); - void SetExplodeOnContact( bool bExplode ) { m_bExplodeOnContact = bExplode; } - - virtual QAngle PreferredCarryAngles( void ) { return QAngle( -12, 98, 55 ); } - virtual bool HasPreferredCarryAnglesForPlayer( CBasePlayer *pPlayer ) { return true; } - - float GetBombLifetime(); - -#ifdef HL2_EPISODIC - virtual void OnPhysGunPickup(CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ); - virtual void OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t reason ); - virtual Class_T Classify( void ) { return CLASS_MISSILE; } - void SetCollisionObject( CBaseEntity *pEntity ) { m_hCollisionObject = pEntity; } - void SendMissEvent(); - bool IsThrownByPlayer(); - - virtual bool ShouldPuntUseLaunchForces( PhysGunForce_t reason ) { return ( reason == PHYSGUN_FORCE_LAUNCHED ); } - virtual Vector PhysGunLaunchVelocity( const Vector &forward, float flMass ); - - void InputExplodeIn( inputdata_t &inputdata ); -#endif // HL2_EPISODIC - -private: - // Pow! - void DoExplosion( const Vector &vecOrigin, const Vector &vecVelocity ); - void ExplodeThink(); - void RampSoundThink(); - void WarningBlinkerThink(); - void StopWarningBlinker(); - void AnimateThink(); - void ExplodeConcussion( CBaseEntity *pOther ); - void BecomeActive(); - void ResolveFlyCollisionCustom( trace_t &trace, Vector &vecVelocity ); - - bool m_bActivated; - bool m_bExplodeOnContact; - CSoundPatch *m_pWarnSound; - - EHANDLE m_hWarningSprite; - bool m_bBlinkerAtTop; - - -#ifdef HL2_EPISODIC - float m_flLifetime; - EHANDLE m_hCollisionObject; // Pointer to object we re-enable collisions with when picked up - bool m_bPickedUp; - float m_flBlinkFastTime; - COutputEvent m_OnPhysGunOnlyPickup; -#endif // HL2_EPISODIC -}; - - -//----------------------------------------------------------------------------- -// The bombs the attack helicopter drops -//----------------------------------------------------------------------------- -class CBombDropSensor : public CBaseEntity -{ - DECLARE_DATADESC(); - -public: - DECLARE_CLASS( CBombDropSensor, CBaseEntity ); - - void Spawn(); - - // Drop a bomb at a particular location - void InputDropBomb( inputdata_t &inputdata ); - void InputDropBombStraightDown( inputdata_t &inputdata ); - void InputDropBombAtTarget( inputdata_t &inputdata ); - void InputDropBombAtTargetAlways( inputdata_t &inputdata ); - void InputDropBombDelay( inputdata_t &inputdata ); -}; - -//----------------------------------------------------------------------------- -// This entity is used to create boxes that the helicopter can't bomb in -//----------------------------------------------------------------------------- -class CBombSuppressor : public CBaseEntity -{ - DECLARE_DATADESC(); - -public: - DECLARE_CLASS( CBombSuppressor, CBaseEntity ); - - virtual void Spawn( ); - virtual void Activate(); - virtual void UpdateOnRemove(); - - static bool CanBomb( const Vector &vecPosition ); - -private: - typedef CHandle BombSuppressorHandle_t; - static CUtlVector< BombSuppressorHandle_t > s_BombSuppressors; -}; - - enum - { - CHUNK_COCKPIT, - CHUNK_BODY, - CHUNK_TAIL - }; - -//----------------------------------------------------------------------------- -// This entity is used for helicopter gibs with specific properties -//----------------------------------------------------------------------------- -class CHelicopterChunk : public CBaseAnimating -{ - DECLARE_DATADESC(); - -public: - DECLARE_CLASS( CHelicopterChunk, CBaseAnimating ); - - virtual void Spawn( void ); - virtual void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); - - static CHelicopterChunk *CreateHelicopterChunk( const Vector &vecPos, const QAngle &vecAngles, const Vector &vecVelocity, const char *pszModelName, int chunkID ); - - int m_nChunkID; - - CHandle m_hMaster; - IPhysicsConstraint *m_pTailConstraint; - IPhysicsConstraint *m_pCockpitConstraint; - -protected: - - void CollisionCallback( CHelicopterChunk *pCaller ); - - void FallThink( void ); - - bool m_bLanded; -}; - -//----------------------------------------------------------------------------- -// The attack helicopter -//----------------------------------------------------------------------------- -class CNPC_AttackHelicopter : public CBaseHelicopter -{ -public: - DECLARE_CLASS( CNPC_AttackHelicopter, CBaseHelicopter ); - DECLARE_DATADESC(); - DEFINE_CUSTOM_AI; - - CNPC_AttackHelicopter(); - ~CNPC_AttackHelicopter(); - - virtual void Precache( void ); - virtual void Spawn( void ); - virtual void Activate( void ); - virtual bool CreateComponents(); - virtual int ObjectCaps(); - -#ifdef HL2_EPISODIC - virtual bool CreateVPhysics( void ); -#endif // HL2_EPISODIC - - virtual void UpdateOnRemove(); - virtual void StopLoopingSounds(); - - int BloodColor( void ) { return DONT_BLEED; } - Class_T Classify ( void ) { return CLASS_COMBINE_GUNSHIP; } - virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - - // Shot spread - virtual Vector GetAttackSpread( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget ); - - // More Enemy visibility check - virtual bool FVisible( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ); - - // Think! - virtual void PrescheduleThink( void ); - - // Purpose: Set the gunship's paddles flailing! - virtual void Event_Killed( const CTakeDamageInfo &info ); - - // Drop a bomb at a particular location - void InputDropBomb( inputdata_t &inputdata ); - void InputDropBombStraightDown( inputdata_t &inputdata ); - void InputDropBombAtTarget( inputdata_t &inputdata ); - void InputDropBombAtTargetAlways( inputdata_t &inputdata ); - void InputDropBombAtTargetInternal( inputdata_t &inputdata, bool bCheckFairness ); - void InputDropBombDelay( inputdata_t &inputdata ); - void InputStartCarpetBombing( inputdata_t &inputdata ); - void InputStopCarpetBombing( inputdata_t &inputdata ); - - virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ); - virtual const char *GetTracerType( void ); - - virtual void DoImpactEffect( trace_t &tr, int nDamageType ); - virtual void DoMuzzleFlash( void ); - - // FIXME: Work this back into the base class - virtual bool ShouldUseFixedPatrolLogic() { return true; } - -protected: - - int m_poseWeapon_Pitch, m_poseWeapon_Yaw, m_poseRudder; - virtual void PopulatePoseParameters( void ); - -private: - enum GunState_t - { - GUN_STATE_IDLE = 0, - GUN_STATE_CHARGING, - GUN_STATE_FIRING, - }; - - // Gets the max speed of the helicopter - virtual float GetMaxSpeed(); - virtual float GetMaxSpeedFiring(); - - // Startup the chopper - virtual void Startup(); - - void InitializeRotorSound( void ); - - // Weaponry - bool FireGun( void ); - - // Movement: - virtual void Flight( void ); - - // Changes the main thinking method of helicopters - virtual void Hunt( void ); - - // For scripted times where it *has* to shoot - void InputResetIdleTime( inputdata_t &inputdata ); - void InputSetHealthFraction( inputdata_t &inputdata ); - void InputStartBombExplodeOnContact( inputdata_t &inputdata ); - void InputStopBombExplodeOnContact( inputdata_t &inputdata ); - - void InputEnableAlwaysTransition( inputdata_t &inputdata ); - void InputDisableAlwaysTransition( inputdata_t &inputdata ); - void InputOutsideTransition( inputdata_t &inputdata ); - void InputSetOutsideTransitionTarget( inputdata_t &inputdata ); - - // Turns off the gun - void InputGunOff( inputdata_t &inputdata ); - - // Vehicle attack modes - void InputStartBombingVehicle( inputdata_t &inputdata ); - void InputStartTrailingVehicle( inputdata_t &inputdata ); - void InputStartDefaultBehavior( inputdata_t &inputdata ); - void InputStartAlwaysLeadingVehicle( inputdata_t &inputdata ); - - // Deadly shooting, tex! - void InputEnableDeadlyShooting( inputdata_t &inputdata ); - void InputDisableDeadlyShooting( inputdata_t &inputdata ); - void InputStartNormalShooting( inputdata_t &inputdata ); - void InputStartLongCycleShooting( inputdata_t &inputdata ); - void InputStartContinuousShooting( inputdata_t &inputdata ); - void InputStartFastShooting( inputdata_t &inputdata ); - - int GetShootingMode( ); - bool IsDeadlyShooting(); - - // Bombing suppression - void InputEnableBombing( inputdata_t &inputdata ); - void InputDisableBombing( inputdata_t &inputdata ); - - // Visibility tests - void InputDisablePathVisibilityTests( inputdata_t &inputdata ); - void InputEnablePathVisibilityTests( inputdata_t &inputdata ); - - // Death, etc. - void InputSelfDestruct( inputdata_t &inputdata ); - - // Enemy visibility check - CBaseEntity *FindTrackBlocker( const Vector &vecViewPoint, const Vector &vecTargetPos ); - - // Special path navigation when we explicitly want to follow a path - void UpdateFollowPathNavigation(); - - // Find interesting nearby things to shoot - int BuildMissTargetList( int nCount, CBaseEntity **ppMissCandidates ); - - // Shoot when the player's your enemy : - void ShootAtPlayer( const Vector &vBasePos, const Vector &vGunDir ); - - // Shoot when the player's your enemy + he's driving a vehicle - void ShootAtVehicle( const Vector &vBasePos, const Vector &vGunDir ); - - // Shoot where we're facing - void ShootAtFacingDirection( const Vector &vBasePos, const Vector &vGunDir, bool bFirstShotAccurate ); - - // Updates the facing direction - void UpdateFacingDirection( const Vector &vecActualDesiredPosition ); - - // Various states of the helicopter firing... - bool PoseGunTowardTargetDirection( const Vector &vTargetDir ); - - // Compute the position to fire at (vehicle + non-vehicle case) - void ComputeFireAtPosition( Vector *pVecActualTargetPosition ); - void ComputeVehicleFireAtPosition( Vector *pVecActualTargetPosition ); - - // Various states of the helicopter firing... - bool DoGunIdle( const Vector &vecGunDir, const Vector &vTargetDir ); - bool DoGunCharging( ); - bool DoGunFiring( const Vector &vBasePos, const Vector &vGunDir, const Vector &vecFireAtPosition ); - void FireElectricityGun( ); - - // Chooses a point within the circle of death to fire in - void PickDirectionToCircleOfDeath( const Vector &vBasePos, const Vector &vecFireAtPosition, Vector *pResult ); - - // Gets a vehicle the enemy is in (if any) - CBaseEntity *GetEnemyVehicle(); - - // Updates the perpendicular path distance for the chopper - float UpdatePerpPathDistance( float flMaxPathOffset ); - - // Purpose : - void UpdateEnemyLeading( void ); - - // Drop those bombs! - void DropBombs( ); - - // Should we drop those bombs? - bool ShouldDropBombs( void ); - - // Returns the max firing distance - float GetMaxFiringDistance(); - - // Make sure we don't hit too many times - void FireBullets( const FireBulletsInfo_t &info ); - - // Is it "fair" to drop this bomb? - bool IsBombDropFair( const Vector &vecBombStartPos, const Vector &vecVelocity ); - - // Actually drops the bomb - void CreateBomb( bool bCheckForFairness = true, Vector *pVecVelocity = NULL, bool bMegaBomb = false ); - CGrenadeHelicopter *SpawnBombEntity( const Vector &vecPos, const Vector &vecVelocity ); // Spawns the bomb entity and sets it up - - // Deliberately aims as close as possible w/o hitting - void AimCloseToTargetButMiss( CBaseEntity *pTarget, float flMinDist, float flMaxDist, const Vector &shootOrigin, Vector *pResult ); - - // Pops a shot inside the circle of death using the burst rules - void ShootInsideCircleOfDeath( const Vector &vBasePos, const Vector &vecFireAtPosition ); - - // How easy is the target to hit? - void UpdateTargetHittability(); - - // Add a smoke trail since we've taken more damage - void AddSmokeTrail( const Vector &vecPos ); - - // Destroy all smoke trails - void DestroySmokeTrails(); - - // Creates the breakable husk of an attack chopper - void CreateChopperHusk(); - - // Pow! - void ExplodeAndThrowChunk( const Vector &vecExplosionPos ); - - // Drop a corpse! - void DropCorpse( int nDamage ); - - // Should we trigger a damage effect? - bool ShouldTriggerDamageEffect( int nPrevHealth, int nEffectCount ) const; - - // Become indestructible - void InputBecomeIndestructible( inputdata_t &inputdata ); - - // Purpose : - float CreepTowardEnemy( float flSpeed, float flMinSpeed, float flMaxSpeed, float flMinDist, float flMaxDist ); - - // Start bullrush - void InputStartBullrushBehavior( inputdata_t &inputdata ); - - void GetMaxSpeedAndAccel( float *pMaxSpeed, float *pAccelRate ); - void ComputeAngularVelocity( const Vector &vecGoalUp, const Vector &vecFacingDirection ); - void ComputeVelocity( const Vector &deltaPos, float flAdditionalHeight, float flMinDistFromSegment, float flMaxDistFromSegment, Vector *pVecAccel ); - void FlightDirectlyOverhead( void ); - - // Methods related to computing leading distance - float ComputeBombingLeadingDistance( float flSpeed, float flSpeedAlongPath, bool bEnemyInVehicle ); - float ComputeBullrushLeadingDistance( float flSpeed, float flSpeedAlongPath, bool bEnemyInVehicle ); - - bool IsCarpetBombing() { return m_bIsCarpetBombing == true; } - - // Update the bullrush state - void UpdateBullrushState( void ); - - // Whether to shoot at or bomb an idle player - bool ShouldBombIdlePlayer( void ); - - // Different bomb-dropping behavior - void BullrushBombs( ); - - // Switch to idle - void SwitchToBullrushIdle( void ); - - // Secondary mode - void SetSecondaryMode( int nMode, bool bRetainTime = false ); - bool IsInSecondaryMode( int nMode ); - float SecondaryModeTime( ) const; - - // Should the chopper shoot the idle player? - bool ShouldShootIdlePlayerInBullrush(); - - // Shutdown shooting during bullrush - void ShutdownGunDuringBullrush( ); - - // Updates the enemy - virtual float EnemySearchDistance( ); - - // Prototype zapper - bool IsValidZapTarget( CBaseEntity *pTarget ); - void CreateZapBeam( const Vector &vecTargetPos ); - void CreateEntityZapEffect( CBaseEntity *pEnt ); - - // Blink lights - void BlinkLightsThink(); - - // Spotlights - void SpotlightThink(); - void SpotlightStartup(); - void SpotlightShutdown(); - - CBaseEntity *GetCrashPoint() { return m_hCrashPoint.Get(); } - -private: - enum - { - ATTACK_MODE_DEFAULT = 0, - ATTACK_MODE_BOMB_VEHICLE, - ATTACK_MODE_TRAIL_VEHICLE, - ATTACK_MODE_ALWAYS_LEAD_VEHICLE, - ATTACK_MODE_BULLRUSH_VEHICLE, - }; - - enum - { - MAX_SMOKE_TRAILS = 5, - MAX_EXPLOSIONS = 13, - MAX_CORPSES = 2, - }; - - enum - { - BULLRUSH_MODE_WAIT_FOR_ENEMY = 0, - BULLRUSH_MODE_GET_DISTANCE, - BULLRUSH_MODE_DROP_BOMBS_FIXED_SPEED, - BULLRUSH_MODE_DROP_BOMBS_FOLLOW_PLAYER, - BULLRUSH_MODE_SHOOT_GUN, - BULLRUSH_MODE_MEGA_BOMB, - BULLRUSH_MODE_SHOOT_IDLE_PLAYER, - }; - - enum - { - SHOOT_MODE_DEFAULT = 0, - SHOOT_MODE_LONG_CYCLE, - SHOOT_MODE_CONTINUOUS, - SHOOT_MODE_FAST, - }; - -#ifdef HL2_EPISODIC - void InitBoneFollowers( void ); - CBoneFollowerManager m_BoneFollowerManager; -#endif // HL2_EPISODIC - - CAI_Spotlight m_Spotlight; - Vector m_angGun; - QAngle m_vecAngAcceleration; - int m_iAmmoType; - float m_flLastCorpseFall; - GunState_t m_nGunState; - float m_flChargeTime; - float m_flIdleTimeDelay; - int m_nRemainingBursts; - int m_nGrenadeCount; - float m_flPathOffset; - float m_flAcrossTime; - float m_flCurrPathOffset; - int m_nBurstHits; - int m_nMaxBurstHits; - float m_flCircleOfDeathRadius; - int m_nAttackMode; - float m_flInputDropBombTime; - CHandle m_hSensor; - float m_flAvoidMetric; - AngularImpulse m_vecLastAngVelocity; - CHandle m_hSmokeTrail[MAX_SMOKE_TRAILS]; - int m_nSmokeTrailCount; - bool m_bIndestructible; - float m_flGracePeriod; - bool m_bBombsExplodeOnContact; - bool m_bNonCombat; - - int m_nNearShots; - int m_nMaxNearShots; - - // Bomb dropping attachments - int m_nGunTipAttachment; - int m_nGunBaseAttachment; - int m_nBombAttachment; - int m_nSpotlightAttachment; - float m_flLastFastTime; - - // Secondary modes - int m_nSecondaryMode; - float m_flSecondaryModeStartTime; - - // Bullrush behavior - bool m_bRushForward; - float m_flBullrushAdditionalHeight; - int m_nBullrushBombMode; - float m_flNextBullrushBombTime; - float m_flNextMegaBombHealth; - - // Shooting method - int m_nShootingMode; - bool m_bDeadlyShooting; - - // Bombing suppression - bool m_bBombingSuppressed; - - // Blinking lights - CHandle m_hLights[MAX_HELICOPTER_LIGHTS]; - bool m_bShortBlink; - - // Path behavior - bool m_bIgnorePathVisibilityTests; - - // Teleport - bool m_bAlwaysTransition; - string_t m_iszTransitionTarget; - - // Special attacks - bool m_bIsCarpetBombing; - - // Fun damage effects - float m_flGoalRollDmg; - float m_flGoalYawDmg; - - // Sounds - CSoundPatch *m_pGunFiringSound; - - // Outputs - COutputInt m_OnHealthChanged; - COutputEvent m_OnShotDown; - - // Crashing - EHANDLE m_hCrashPoint; -}; - -#ifdef HL2_EPISODIC -static const char *pFollowerBoneNames[] = -{ - "Chopper.Body" -}; -#endif // HL2_EPISODIC - -LINK_ENTITY_TO_CLASS( npc_helicopter, CNPC_AttackHelicopter ); - -BEGIN_DATADESC( CNPC_AttackHelicopter ) - - DEFINE_ENTITYFUNC( FlyTouch ), - - DEFINE_EMBEDDED( m_Spotlight ), -#ifdef HL2_EPISODIC - DEFINE_EMBEDDED( m_BoneFollowerManager ), -#endif - DEFINE_FIELD( m_angGun, FIELD_VECTOR ), - DEFINE_FIELD( m_vecAngAcceleration, FIELD_VECTOR ), - DEFINE_FIELD( m_iAmmoType, FIELD_INTEGER ), - DEFINE_FIELD( m_flLastCorpseFall, FIELD_TIME ), - DEFINE_FIELD( m_nGunState, FIELD_INTEGER ), - DEFINE_FIELD( m_flChargeTime, FIELD_TIME ), - DEFINE_FIELD( m_flIdleTimeDelay, FIELD_FLOAT ), - DEFINE_FIELD( m_nRemainingBursts, FIELD_INTEGER ), - DEFINE_FIELD( m_nGrenadeCount, FIELD_INTEGER ), - DEFINE_FIELD( m_flPathOffset, FIELD_FLOAT ), - DEFINE_FIELD( m_flAcrossTime, FIELD_TIME ), - DEFINE_FIELD( m_flCurrPathOffset, FIELD_FLOAT ), - DEFINE_FIELD( m_nBurstHits, FIELD_INTEGER ), - DEFINE_FIELD( m_nMaxBurstHits, FIELD_INTEGER ), - DEFINE_FIELD( m_flCircleOfDeathRadius, FIELD_FLOAT ), - DEFINE_FIELD( m_nAttackMode, FIELD_INTEGER ), - DEFINE_FIELD( m_flInputDropBombTime, FIELD_TIME ), - DEFINE_FIELD( m_hSensor, FIELD_EHANDLE ), - DEFINE_FIELD( m_flAvoidMetric, FIELD_FLOAT ), - DEFINE_FIELD( m_vecLastAngVelocity, FIELD_VECTOR ), - DEFINE_AUTO_ARRAY( m_hSmokeTrail, FIELD_EHANDLE ), - DEFINE_FIELD( m_nSmokeTrailCount, FIELD_INTEGER ), - DEFINE_FIELD( m_nNearShots, FIELD_INTEGER ), - DEFINE_FIELD( m_nMaxNearShots, FIELD_INTEGER ), -// DEFINE_FIELD( m_nGunTipAttachment, FIELD_INTEGER ), -// DEFINE_FIELD( m_nGunBaseAttachment, FIELD_INTEGER ), -// DEFINE_FIELD( m_nBombAttachment, FIELD_INTEGER ), -// DEFINE_FIELD( m_nSpotlightAttachment, FIELD_INTEGER ), - DEFINE_FIELD( m_flLastFastTime, FIELD_TIME ), - DEFINE_FIELD( m_nSecondaryMode, FIELD_INTEGER ), - DEFINE_FIELD( m_flSecondaryModeStartTime, FIELD_TIME ), - DEFINE_FIELD( m_bRushForward, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flBullrushAdditionalHeight, FIELD_FLOAT ), - DEFINE_FIELD( m_nBullrushBombMode, FIELD_INTEGER ), - DEFINE_FIELD( m_flNextBullrushBombTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextMegaBombHealth, FIELD_FLOAT ), - DEFINE_FIELD( m_nShootingMode, FIELD_INTEGER ), - DEFINE_FIELD( m_bDeadlyShooting, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bBombingSuppressed, FIELD_BOOLEAN ), - DEFINE_SOUNDPATCH( m_pGunFiringSound ), - DEFINE_AUTO_ARRAY( m_hLights, FIELD_EHANDLE ), - DEFINE_FIELD( m_bIgnorePathVisibilityTests, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bShortBlink, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bIndestructible, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bBombsExplodeOnContact, FIELD_BOOLEAN ), - - DEFINE_KEYFIELD( m_bAlwaysTransition, FIELD_BOOLEAN, "AlwaysTransition" ), - DEFINE_KEYFIELD( m_iszTransitionTarget, FIELD_STRING, "TransitionTarget" ), - DEFINE_FIELD( m_bIsCarpetBombing, FIELD_BOOLEAN ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableAlwaysTransition", InputEnableAlwaysTransition ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableAlwaysTransition", InputDisableAlwaysTransition ), - DEFINE_INPUTFUNC( FIELD_VOID, "OutsideTransition", InputOutsideTransition ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetTransitionTarget", InputSetOutsideTransitionTarget ), - - DEFINE_KEYFIELD( m_flGracePeriod, FIELD_FLOAT, "GracePeriod" ), - DEFINE_KEYFIELD( m_flMaxSpeed, FIELD_FLOAT, "PatrolSpeed" ), - DEFINE_KEYFIELD( m_bNonCombat, FIELD_BOOLEAN, "NonCombat" ), - - DEFINE_FIELD( m_hCrashPoint, FIELD_EHANDLE ), - - DEFINE_INPUTFUNC( FIELD_VOID, "ResetIdleTime", InputResetIdleTime ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartAlwaysLeadingVehicle", InputStartAlwaysLeadingVehicle ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartBombingVehicle", InputStartBombingVehicle ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartTrailingVehicle", InputStartTrailingVehicle ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartDefaultBehavior", InputStartDefaultBehavior ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartBullrushBehavior", InputStartBullrushBehavior ), - - DEFINE_INPUTFUNC( FIELD_VOID, "DropBomb", InputDropBomb ), - DEFINE_INPUTFUNC( FIELD_VOID, "DropBombStraightDown", InputDropBombStraightDown ), - DEFINE_INPUTFUNC( FIELD_STRING, "DropBombAtTargetAlways", InputDropBombAtTargetAlways ), - DEFINE_INPUTFUNC( FIELD_STRING, "DropBombAtTarget", InputDropBombAtTarget ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "DropBombDelay", InputDropBombDelay ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartCarpetBombing", InputStartCarpetBombing ), - DEFINE_INPUTFUNC( FIELD_VOID, "StopCarpetBombing", InputStopCarpetBombing ), - DEFINE_INPUTFUNC( FIELD_VOID, "BecomeIndestructible", InputBecomeIndestructible ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableDeadlyShooting", InputEnableDeadlyShooting ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableDeadlyShooting", InputDisableDeadlyShooting ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartNormalShooting", InputStartNormalShooting ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartLongCycleShooting", InputStartLongCycleShooting ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartContinuousShooting", InputStartContinuousShooting ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartFastShooting", InputStartFastShooting ), - DEFINE_INPUTFUNC( FIELD_VOID, "GunOff", InputGunOff ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetHealthFraction", InputSetHealthFraction ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartBombExplodeOnContact", InputStartBombExplodeOnContact ), - DEFINE_INPUTFUNC( FIELD_VOID, "StopBombExplodeOnContact", InputStopBombExplodeOnContact ), - - DEFINE_INPUTFUNC( FIELD_VOID, "DisablePathVisibilityTests", InputDisablePathVisibilityTests ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnablePathVisibilityTests", InputEnablePathVisibilityTests ), - - DEFINE_INPUTFUNC( FIELD_VOID, "SelfDestruct", InputSelfDestruct ), - - DEFINE_THINKFUNC( BlinkLightsThink ), - DEFINE_THINKFUNC( SpotlightThink ), - - DEFINE_OUTPUT( m_OnHealthChanged, "OnHealthChanged" ), - DEFINE_OUTPUT( m_OnShotDown, "OnShotDown" ), - -END_DATADESC() - - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -CNPC_AttackHelicopter::CNPC_AttackHelicopter() : - m_flGracePeriod( 2.0f ), - m_bBombsExplodeOnContact( false ), - m_bNonCombat( false ) -{ - m_flMaxSpeed = 0; -} - -CNPC_AttackHelicopter::~CNPC_AttackHelicopter(void) -{ -} - - -//----------------------------------------------------------------------------- -// Purpose: Shuts down looping sounds when we are killed in combat or deleted. -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::StopLoopingSounds() -{ - BaseClass::StopLoopingSounds(); - - if ( m_pGunFiringSound ) - { - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundDestroy( m_pGunFiringSound ); - m_pGunFiringSound = NULL; - } -} - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void Chopper_PrecacheChunks( CBaseEntity *pChopper ) -{ - for ( int i = 0; i < CHOPPER_MAX_CHUNKS; ++i ) - { - pChopper->PrecacheModel( s_pChunkModelName[i] ); - } - - pChopper->PrecacheModel( HELICOPTER_CHUNK_COCKPIT ); - pChopper->PrecacheModel( HELICOPTER_CHUNK_TAIL ); - pChopper->PrecacheModel( HELICOPTER_CHUNK_BODY ); -} - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::Precache( void ) -{ - BaseClass::Precache(); - - if ( !HasSpawnFlags(SF_HELICOPTER_ELECTRICAL_DRONE) ) - { - PrecacheModel( CHOPPER_MODEL_NAME ); - } - else - { - PrecacheModel( CHOPPER_DRONE_NAME ); - } - - PrecacheModel( CHOPPER_RED_LIGHT_SPRITE ); - //PrecacheModel( CHOPPER_MODEL_CORPSE_NAME ); - - // If we're never going to engage in combat, we don't need to load these assets! - if ( m_bNonCombat == false ) - { - UTIL_PrecacheOther( "grenade_helicopter" ); - UTIL_PrecacheOther( "env_fire_trail" ); - Chopper_PrecacheChunks( this ); - PrecacheModel("models/combine_soldier.mdl"); - } - - PrecacheScriptSound("NPC_AttackHelicopter.ChargeGun"); - if ( HasSpawnFlags( SF_HELICOPTER_LOUD_ROTOR_SOUND ) ) - { - PrecacheScriptSound("NPC_AttackHelicopter.RotorsLoud"); - } - else - { - PrecacheScriptSound("NPC_AttackHelicopter.Rotors"); - } - PrecacheScriptSound( "NPC_AttackHelicopter.DropMine" ); - PrecacheScriptSound( "NPC_AttackHelicopter.BadlyDamagedAlert" ); - PrecacheScriptSound( "NPC_AttackHelicopter.CrashingAlarm1" ); - PrecacheScriptSound( "NPC_AttackHelicopter.MegabombAlert" ); - - PrecacheScriptSound( "NPC_AttackHelicopter.RotorBlast" ); - PrecacheScriptSound( "NPC_AttackHelicopter.EngineFailure" ); - PrecacheScriptSound( "NPC_AttackHelicopter.FireGun" ); - PrecacheScriptSound( "NPC_AttackHelicopter.Crash" ); - PrecacheScriptSound( "HelicopterBomb.HardImpact" ); - - PrecacheScriptSound( "ReallyLoudSpark" ); - PrecacheScriptSound( "NPC_AttackHelicopterGrenade.Ping" ); -} - -int CNPC_AttackHelicopter::ObjectCaps() -{ - int caps = BaseClass::ObjectCaps(); - if ( m_bAlwaysTransition ) - caps |= FCAP_NOTIFY_ON_TRANSITION; - return caps; -} - -void CNPC_AttackHelicopter::InputOutsideTransition( inputdata_t &inputdata ) -{ - CBaseEntity *pEnt = gEntList.FindEntityByName( NULL, m_iszTransitionTarget ); - - if ( pEnt ) - { - Vector teleportLocation = pEnt->GetAbsOrigin(); - QAngle teleportAngles = pEnt->GetAbsAngles(); - Teleport( &teleportLocation, &teleportAngles, &vec3_origin ); - Teleported(); - } - else - { - DevMsg( 2, "NPC \"%s\" failed to find a suitable transition a point\n", STRING(GetEntityName()) ); - } -} - -void CNPC_AttackHelicopter::InputSetOutsideTransitionTarget( inputdata_t &inputdata ) -{ - m_iszTransitionTarget = MAKE_STRING( inputdata.value.String() ); -} - - -//----------------------------------------------------------------------------- -// Create components -//----------------------------------------------------------------------------- -bool CNPC_AttackHelicopter::CreateComponents() -{ - if ( !BaseClass::CreateComponents() ) - return false; - - m_Spotlight.Init( this, AI_SPOTLIGHT_NO_DLIGHTS, 45.0f, 500.0f ); - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose : -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::Spawn( void ) -{ - Precache( ); - - m_bIndestructible = false; - m_bDeadlyShooting = false; - m_bBombingSuppressed = false; - m_bIgnorePathVisibilityTests = false; - - if ( !HasSpawnFlags(SF_HELICOPTER_ELECTRICAL_DRONE) ) - { - SetModel( CHOPPER_MODEL_NAME ); - } - else - { - SetModel( CHOPPER_DRONE_NAME ); - } - - ExtractBbox( SelectHeaviestSequence( ACT_IDLE ), m_cullBoxMins, m_cullBoxMaxs ); - GetEnemies()->SetFreeKnowledgeDuration( DEFAULT_FREE_KNOWLEDGE_DURATION ); - - float flLoadedSpeed = m_flMaxSpeed; - BaseClass::Spawn(); - - float flChaseDist = HasSpawnFlags( SF_HELICOPTER_AGGRESSIVE ) ? - CHOPPER_MIN_AGGRESSIVE_CHASE_DIST_DIFF : CHOPPER_MIN_CHASE_DIST_DIFF; - InitPathingData( CHOPPER_ARRIVE_DIST, flChaseDist, CHOPPER_AVOID_DIST ); - SetFarthestPathDist( GetMaxFiringDistance() ); - - m_takedamage = DAMAGE_YES; - m_nGunState = GUN_STATE_IDLE; - SetHullType( HULL_LARGE_CENTERED ); - - SetHullSizeNormal(); - -#ifdef HL2_EPISODIC - CreateVPhysics(); -#endif // HL2_EPISODIC - - SetPauseState( PAUSE_NO_PAUSE ); - - m_iMaxHealth = m_iHealth = sk_helicopter_health.GetInt(); - - m_flMaxSpeed = flLoadedSpeed; - if ( m_flMaxSpeed <= 0 ) - { - m_flMaxSpeed = CHOPPER_MAX_SPEED; - } - m_flNextMegaBombHealth = m_iMaxHealth - m_iMaxHealth * g_helicopter_bullrush_mega_bomb_health.GetFloat(); - - m_nGrenadeCount = CHOPPER_BOMB_DROP_COUNT; - - m_flFieldOfView = -1.0; // 360 degrees - m_flIdleTimeDelay = 0.0f; - m_iAmmoType = GetAmmoDef()->Index("HelicopterGun"); - - InitBoneControllers(); - - m_fHelicopterFlags = BITS_HELICOPTER_GUN_ON; - m_bSuppressSound = false; - - m_flAcrossTime = -1.0f; - m_flPathOffset = 0.0f; - m_flCurrPathOffset = 0.0f; - m_nAttackMode = ATTACK_MODE_DEFAULT; - m_flInputDropBombTime = gpGlobals->curtime; - SetActivity( ACT_IDLE ); - - int nBombAttachment = LookupAttachment("bomb"); - m_hSensor = static_cast(CreateEntityByName( "npc_helicoptersensor" )); - m_hSensor->Spawn(); - m_hSensor->SetParent( this, nBombAttachment ); - m_hSensor->SetLocalOrigin( vec3_origin ); - m_hSensor->SetLocalAngles( vec3_angle ); - m_hSensor->SetOwnerEntity( this ); - - AddFlag( FL_AIMTARGET ); - - m_hCrashPoint.Set( NULL ); -} - -#ifdef HL2_EPISODIC -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_AttackHelicopter::CreateVPhysics( void ) -{ - InitBoneFollowers(); - return BaseClass::CreateVPhysics(); -} -#endif // HL2_EPISODIC - -//------------------------------------------------------------------------------ -// Startup the chopper -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::Startup() -{ - BaseClass::Startup(); - - if ( HasSpawnFlags( SF_HELICOPTER_LIGHTS ) ) - { - for ( int i = 0; i < MAX_HELICOPTER_LIGHTS; ++i ) - { - // See if there's an attachment for this smoke trail - char buf[32]; - Q_snprintf( buf, 32, "Light_Red%d", i ); - int nAttachment = LookupAttachment( buf ); - if ( nAttachment == 0 ) - { - m_hLights[i] = NULL; - continue; - } - - m_hLights[i] = CSprite::SpriteCreate( CHOPPER_RED_LIGHT_SPRITE, vec3_origin, false ); - if ( !m_hLights[i] ) - continue; - - m_hLights[i]->SetParent( this, nAttachment ); - m_hLights[i]->SetLocalOrigin( vec3_origin ); - m_hLights[i]->SetLocalVelocity( vec3_origin ); - m_hLights[i]->SetMoveType( MOVETYPE_NONE ); - m_hLights[i]->SetTransparency( kRenderTransAdd, 255, 255, 255, 200, kRenderFxNone ); - m_hLights[i]->SetScale( 1.0f ); - m_hLights[i]->TurnOn(); - } - - SetContextThink( &CNPC_AttackHelicopter::BlinkLightsThink, gpGlobals->curtime + CHOPPER_LIGHT_BLINK_TIME_SHORT, s_pBlinkLightThinkContext ); - } -} - - -//------------------------------------------------------------------------------ -// Startup the chopper -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::BlinkLightsThink() -{ - bool bIsOn = false; - for ( int i = 0; i < MAX_HELICOPTER_LIGHTS; ++i ) - { - if ( !m_hLights[i] ) - continue; - - if ( m_hLights[i]->GetScale() > 0.1f ) - { - m_hLights[i]->SetScale( 0.1f, CHOPPER_LIGHT_BLINK_TIME_SHORT ); - } - else - { - m_hLights[i]->SetScale( 0.5f, 0.0f ); - bIsOn = true; - } - } - - float flTime; - if ( bIsOn ) - { - flTime = CHOPPER_LIGHT_BLINK_TIME_SHORT; - } - else - { - flTime = m_bShortBlink ? CHOPPER_LIGHT_BLINK_TIME_SHORT : CHOPPER_LIGHT_BLINK_TIME; - m_bShortBlink = !m_bShortBlink; - } - - SetContextThink( &CNPC_AttackHelicopter::BlinkLightsThink, gpGlobals->curtime + flTime, s_pBlinkLightThinkContext ); -} - - -//------------------------------------------------------------------------------ -// Start up spotlights -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::SpotlightStartup() -{ - if ( !HasSpawnFlags( SF_HELICOPTER_LIGHTS ) ) - return; - - Vector vecForward; - Vector vecOrigin; - GetAttachment( m_nSpotlightAttachment, vecOrigin, &vecForward ); - m_Spotlight.SpotlightCreate( m_nSpotlightAttachment, vecForward ); - SpotlightThink(); -} - - -//------------------------------------------------------------------------------ -// Shutdown spotlights -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::SpotlightShutdown() -{ - m_Spotlight.SpotlightDestroy(); - SetContextThink( NULL, gpGlobals->curtime, s_pSpotlightThinkContext ); -} - - -//------------------------------------------------------------------------------ -// Spotlights -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::SpotlightThink() -{ - // NOTE: This function should deal with all deactivation cases - if ( m_lifeState != LIFE_ALIVE ) - { - SpotlightShutdown(); - return; - } - - switch( m_nAttackMode ) - { - case ATTACK_MODE_BULLRUSH_VEHICLE: - { - switch ( m_nSecondaryMode ) - { - case BULLRUSH_MODE_SHOOT_GUN: - { - Vector vecForward; - Vector vecOrigin; - GetAttachment( m_nSpotlightAttachment, vecOrigin, &vecForward ); - m_Spotlight.SetSpotlightTargetDirection( vecForward ); - } - break; - - case BULLRUSH_MODE_SHOOT_IDLE_PLAYER: - if ( GetEnemy() ) - { - m_Spotlight.SetSpotlightTargetPos( GetEnemy()->WorldSpaceCenter() ); - } - break; - - default: - SpotlightShutdown(); - return; - } - } - break; - - default: - SpotlightShutdown(); - return; - } - - m_Spotlight.Update(); - SetContextThink( &CNPC_AttackHelicopter::SpotlightThink, gpGlobals->curtime + TICK_INTERVAL, s_pSpotlightThinkContext ); -} - -//----------------------------------------------------------------------------- -// Purpose: Always transition along with the player -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::InputEnableAlwaysTransition( inputdata_t &inputdata ) -{ - m_bAlwaysTransition = true; -} - -//----------------------------------------------------------------------------- -// Purpose: Stop always transitioning along with the player -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::InputDisableAlwaysTransition( inputdata_t &inputdata ) -{ - m_bAlwaysTransition = false; -} - -//------------------------------------------------------------------------------ -// On Remove -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::UpdateOnRemove() -{ - BaseClass::UpdateOnRemove(); - StopLoopingSounds(); - UTIL_Remove(m_hSensor); - DestroySmokeTrails(); - for ( int i = 0; i < MAX_HELICOPTER_LIGHTS; ++i ) - { - if ( m_hLights[i] ) - { - UTIL_Remove( m_hLights[i] ); - m_hLights[i] = NULL; - } - } - -#ifdef HL2_EPISODIC - m_BoneFollowerManager.DestroyBoneFollowers(); -#endif // HL2_EPISODIC -} - - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::Activate( void ) -{ - BaseClass::Activate(); - m_nGunBaseAttachment = LookupAttachment("gun"); - m_nGunTipAttachment = LookupAttachment("muzzle"); - m_nBombAttachment = LookupAttachment("bomb"); - m_nSpotlightAttachment = LookupAttachment("spotlight"); - - if ( HasSpawnFlags( SF_HELICOPTER_LONG_SHADOW ) ) - { - SetShadowCastDistance( 2048 ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const char *CNPC_AttackHelicopter::GetTracerType( void ) -{ - return "HelicopterTracer"; -} - - -//----------------------------------------------------------------------------- -// Allows the shooter to change the impact effect of his bullets -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::DoImpactEffect( trace_t &tr, int nDamageType ) -{ - UTIL_ImpactTrace( &tr, nDamageType, "HelicopterImpact" ); -} - - -//------------------------------------------------------------------------------ -// Purpose : Create our rotor sound -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::InitializeRotorSound( void ) -{ - if ( !m_pRotorSound ) - { - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - CPASAttenuationFilter filter( this ); - - if ( HasSpawnFlags( SF_HELICOPTER_LOUD_ROTOR_SOUND ) ) - { - m_pRotorSound = controller.SoundCreate( filter, entindex(), "NPC_AttackHelicopter.RotorsLoud" ); - } - else - { - m_pRotorSound = controller.SoundCreate( filter, entindex(), "NPC_AttackHelicopter.Rotors" ); - } - - m_pRotorBlast = controller.SoundCreate( filter, entindex(), "NPC_AttackHelicopter.RotorBlast" ); - m_pGunFiringSound = controller.SoundCreate( filter, entindex(), "NPC_AttackHelicopter.FireGun" ); - controller.Play( m_pGunFiringSound, 0.0, 100 ); - } - else - { - Assert(m_pRotorSound); - Assert(m_pRotorBlast); - Assert(m_pGunFiringSound); - } - - - BaseClass::InitializeRotorSound(); -} - - -//------------------------------------------------------------------------------ -// Gets the max speed of the helicopter -//------------------------------------------------------------------------------ -float CNPC_AttackHelicopter::GetMaxSpeed() -{ - if ( HasSpawnFlags(SF_HELICOPTER_ELECTRICAL_DRONE) ) - return DRONE_SPEED; - - if ( ( m_nAttackMode == ATTACK_MODE_BULLRUSH_VEHICLE ) && IsInSecondaryMode( BULLRUSH_MODE_DROP_BOMBS_FIXED_SPEED ) ) - return CHOPPER_BULLRUSH_ENEMY_BOMB_SPEED; - - if ( !GetEnemyVehicle() ) - return BaseClass::GetMaxSpeed(); - - return 3000.0f; -} - -float CNPC_AttackHelicopter::GetMaxSpeedFiring() -{ - if ( HasSpawnFlags(SF_HELICOPTER_ELECTRICAL_DRONE) ) - return DRONE_SPEED; - - if ( ( m_nAttackMode == ATTACK_MODE_BULLRUSH_VEHICLE ) && IsInSecondaryMode( BULLRUSH_MODE_DROP_BOMBS_FIXED_SPEED ) ) - return CHOPPER_BULLRUSH_ENEMY_BOMB_SPEED; - - if ( !GetEnemyVehicle() ) - return BaseClass::GetMaxSpeedFiring(); - - return 3000.0f; -} - - -//------------------------------------------------------------------------------ -// Returns the max firing distance -//------------------------------------------------------------------------------ -float CNPC_AttackHelicopter::GetMaxFiringDistance() -{ - if ( !GetEnemyVehicle() ) - return CHOPPER_GUN_MAX_FIRING_DIST; - - return 8000.0f; -} - - -//------------------------------------------------------------------------------ -// Updates the enemy -//------------------------------------------------------------------------------ -float CNPC_AttackHelicopter::EnemySearchDistance( ) -{ - return 6000.0f; -} - - -//------------------------------------------------------------------------------ -// Leading behaviors -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::InputStartBombingVehicle( inputdata_t &inputdata ) -{ - m_nAttackMode = ATTACK_MODE_BOMB_VEHICLE; - SetLeadingDistance( 1500.0f ); -} - -void CNPC_AttackHelicopter::InputStartTrailingVehicle( inputdata_t &inputdata ) -{ - m_nAttackMode = ATTACK_MODE_TRAIL_VEHICLE; - SetLeadingDistance( -1500.0f ); -} - -void CNPC_AttackHelicopter::InputStartDefaultBehavior( inputdata_t &inputdata ) -{ - m_nAttackMode = ATTACK_MODE_DEFAULT; -} - -void CNPC_AttackHelicopter::InputStartAlwaysLeadingVehicle( inputdata_t &inputdata ) -{ - m_nAttackMode = ATTACK_MODE_ALWAYS_LEAD_VEHICLE; - SetLeadingDistance( 0.0f ); -} - -void CNPC_AttackHelicopter::InputStartBullrushBehavior( inputdata_t &inputdata ) -{ - if ( m_nAttackMode != ATTACK_MODE_BULLRUSH_VEHICLE ) - { - m_nAttackMode = ATTACK_MODE_BULLRUSH_VEHICLE; - SetSecondaryMode( BULLRUSH_MODE_WAIT_FOR_ENEMY ); - SetLeadingDistance( 0.0f ); - } -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::InputStartCarpetBombing( inputdata_t &inputdata ) -{ - m_bIsCarpetBombing = true; -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::InputStopCarpetBombing( inputdata_t &inputdata ) -{ - m_bIsCarpetBombing = false; -} - -//------------------------------------------------------------------------------ -// Become indestructible -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::InputBecomeIndestructible( inputdata_t &inputdata ) -{ - m_bIndestructible = true; -} - - -//------------------------------------------------------------------------------ -// Deadly shooting, tex! -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::InputEnableDeadlyShooting( inputdata_t &inputdata ) -{ - m_bDeadlyShooting = true; -} - -void CNPC_AttackHelicopter::InputDisableDeadlyShooting( inputdata_t &inputdata ) -{ - m_bDeadlyShooting = false; -} - -void CNPC_AttackHelicopter::InputStartNormalShooting( inputdata_t &inputdata ) -{ - m_nShootingMode = SHOOT_MODE_DEFAULT; -} - -void CNPC_AttackHelicopter::InputStartLongCycleShooting( inputdata_t &inputdata ) -{ - m_nShootingMode = SHOOT_MODE_LONG_CYCLE; -} - -void CNPC_AttackHelicopter::InputStartContinuousShooting( inputdata_t &inputdata ) -{ - m_nShootingMode = SHOOT_MODE_CONTINUOUS; -} - -void CNPC_AttackHelicopter::InputStartFastShooting( inputdata_t &inputdata ) -{ - m_nShootingMode = SHOOT_MODE_FAST; -} - -//------------------------------------------------------------------------------ -// Deadly shooting, tex! -//------------------------------------------------------------------------------ -bool CNPC_AttackHelicopter::IsDeadlyShooting() -{ - if ( m_bDeadlyShooting ) - return true; - - if (( m_nAttackMode == ATTACK_MODE_BULLRUSH_VEHICLE ) && IsInSecondaryMode( BULLRUSH_MODE_SHOOT_IDLE_PLAYER ) ) - { - return (!GetEnemyVehicle()) && GetEnemy() && GetEnemy()->IsPlayer(); - } - - return false; -} - -int CNPC_AttackHelicopter::GetShootingMode( ) -{ - if ( IsDeadlyShooting() ) - return SHOOT_MODE_LONG_CYCLE; - - if ( m_nAttackMode == ATTACK_MODE_BULLRUSH_VEHICLE ) - return SHOOT_MODE_CONTINUOUS; - - return m_nShootingMode; -} - - -//----------------------------------------------------------------------------- -// Bombing suppression -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::InputEnableBombing( inputdata_t &inputdata ) -{ - m_bBombingSuppressed = false; -} - -void CNPC_AttackHelicopter::InputDisableBombing( inputdata_t &inputdata ) -{ - m_bBombingSuppressed = true; -} - - -//----------------------------------------------------------------------------- -// Visibility tests -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::InputDisablePathVisibilityTests( inputdata_t &inputdata ) -{ - m_bIgnorePathVisibilityTests = true; - GetEnemies()->SetUnforgettable( GetEnemy(), true ); -} - -void CNPC_AttackHelicopter::InputEnablePathVisibilityTests( inputdata_t &inputdata ) -{ - m_bIgnorePathVisibilityTests = false; - GetEnemies()->SetUnforgettable( GetEnemy(), false ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::InputSelfDestruct( inputdata_t &inputdata ) -{ - m_lifeState = LIFE_ALIVE; // Force to die properly. - CTakeDamageInfo info( this, this, Vector(0, 0, 1), WorldSpaceCenter(), GetMaxHealth(), CLASS_MISSILE ); - TakeDamage( info ); -} - -//----------------------------------------------------------------------------- -// For scripted times where it *has* to shoot -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::InputSetHealthFraction( inputdata_t &inputdata ) -{ - // Sets the health fraction, no damage effects - if ( inputdata.value.Float() > 0 ) - { - SetHealth( (int)(GetMaxHealth() * inputdata.value.Float() * 0.01f) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::InputStartBombExplodeOnContact( inputdata_t &inputdata ) -{ - m_bBombsExplodeOnContact = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::InputStopBombExplodeOnContact( inputdata_t &inputdata ) -{ - m_bBombsExplodeOnContact = false; -} - -//------------------------------------------------------------------------------ -// For scripted times where it *has* to shoot -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::InputResetIdleTime( inputdata_t &inputdata ) -{ - if ( m_nGunState == GUN_STATE_IDLE ) - { - m_flNextAttack = gpGlobals->curtime; - } -} - - -//----------------------------------------------------------------------------- -// This trace filter ignores all breakables + physics props -//----------------------------------------------------------------------------- -class CTraceFilterChopper : public CTraceFilterSimple -{ - DECLARE_CLASS( CTraceFilterChopper, CTraceFilterSimple ); - -public: - CTraceFilterChopper( const IHandleEntity *passentity, int collisionGroup ); - virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ); - -private: - const IHandleEntity *m_pPassEnt; - int m_collisionGroup; -}; - -CTraceFilterChopper::CTraceFilterChopper( const IHandleEntity *passentity, int collisionGroup ) : - CTraceFilterSimple( passentity, collisionGroup ) -{ -} - -bool CTraceFilterChopper::ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ) -{ - CBaseEntity *pEnt = static_cast(pServerEntity)->GetBaseEntity(); - if ( pEnt ) - { - if ( FClassnameIs( pEnt, "func_breakable" ) || - FClassnameIs( pEnt, "func_physbox" ) || - FClassnameIs( pEnt, "prop_physics" ) || - FClassnameIs( pEnt, "physics_prop" ) ) - { - return false; - } - } - - return BaseClass::ShouldHitEntity( pServerEntity, contentsMask ); -} - - -//----------------------------------------------------------------------------- -// Enemy visibility check -//----------------------------------------------------------------------------- -CBaseEntity *CNPC_AttackHelicopter::FindTrackBlocker( const Vector &vecViewPoint, const Vector &vecTargetPos ) -{ - if ( m_bIgnorePathVisibilityTests ) - return NULL; - - CTraceFilterChopper chopperFilter( this, COLLISION_GROUP_NONE ); - - trace_t tr; - AI_TraceHull( vecViewPoint, vecTargetPos, -Vector(4,4,4), Vector(4,4,4), MASK_SHOT, &chopperFilter, &tr ); - - if ( tr.fraction != 1.0f ) - { - Assert( tr.m_pEnt ); - } - - return (tr.fraction != 1.0f) ? tr.m_pEnt : NULL; -} - - -//----------------------------------------------------------------------------- -// More Enemy visibility check -//----------------------------------------------------------------------------- -bool CNPC_AttackHelicopter::FVisible( CBaseEntity *pEntity, int traceMask, CBaseEntity **ppBlocker ) -{ - if ( pEntity->GetFlags() & FL_NOTARGET ) - return false; - -#if 0 - // FIXME: only block LOS through opaque water - // don't look through water - if ((m_nWaterLevel != 3 && pEntity->m_nWaterLevel == 3) - || (m_nWaterLevel == 3 && pEntity->m_nWaterLevel == 0)) - return false; -#endif - - Vector vecLookerOrigin = EyePosition();//look through the caller's 'eyes' - Vector vecTargetOrigin = pEntity->EyePosition(); - - CTraceFilterChopper chopperFilter( this, COLLISION_GROUP_NONE ); - - trace_t tr; - UTIL_TraceLine(vecLookerOrigin, vecTargetOrigin, traceMask, &chopperFilter, &tr); - - if (tr.fraction != 1.0) - { - // Got line of sight! - if ( tr.m_pEnt == pEntity ) - return true; - - // Got line of sight on the vehicle the player is driving! - if ( pEntity && pEntity->IsPlayer() ) - { - CBasePlayer *pPlayer = assert_cast( pEntity ); - if ( tr.m_pEnt == pPlayer->GetVehicleEntity() ) - return true; - } - - if (ppBlocker) - { - *ppBlocker = tr.m_pEnt; - } - return false;// Line of sight is not established - } - - return true;// line of sight is valid. -} - - -//------------------------------------------------------------------------------ -// Shot spread -//------------------------------------------------------------------------------ -#define PLAYER_TIGHTEN_FACTOR 0.75f -Vector CNPC_AttackHelicopter::GetAttackSpread( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget ) -{ - float flSinConeDegrees = sin( sk_helicopter_firingcone.GetFloat() * PLAYER_TIGHTEN_FACTOR * 0.5f * (3.14f / 180.0f) ); - Vector vecSpread( flSinConeDegrees, flSinConeDegrees, flSinConeDegrees ); - return vecSpread; -} - - -//------------------------------------------------------------------------------ -// Find interesting nearby things to shoot -//------------------------------------------------------------------------------ -int CNPC_AttackHelicopter::BuildMissTargetList( int nCount, CBaseEntity **ppMissCandidates ) -{ - int numMissCandidates = 0; - - CBaseEntity *pEnts[256]; - Vector radius( 150, 150, 150 ); - const Vector &vecSource = GetEnemy()->WorldSpaceCenter(); - - int numEnts = UTIL_EntitiesInBox( pEnts, 256, vecSource - radius, vecSource+radius, 0 ); - - for ( int i = 0; i < numEnts; i++ ) - { - if ( pEnts[i] == NULL ) - continue; - - if ( numMissCandidates >= nCount ) - break; - - // Miss candidates cannot include the player or his vehicle - if ( pEnts[i] == GetEnemyVehicle() || pEnts[i] == GetEnemy() ) - continue; - - // See if it's a good target candidate - if ( FClassnameIs( pEnts[i], "prop_dynamic" ) || - FClassnameIs( pEnts[i], "prop_physics" ) || - FClassnameIs( pEnts[i], "physics_prop" ) ) - { - ppMissCandidates[numMissCandidates++] = pEnts[i]; - } - } - - return numMissCandidates; -} - - -//------------------------------------------------------------------------------ -// Gets a vehicle the enemy is in (if any) -//------------------------------------------------------------------------------ -CBaseEntity *CNPC_AttackHelicopter::GetEnemyVehicle() -{ - if ( !GetEnemy() ) - return NULL; - - if ( !GetEnemy()->IsPlayer() ) - return NULL; - - return static_cast(GetEnemy())->GetVehicleEntity(); -} - - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::ShootAtPlayer( const Vector &vBasePos, const Vector &vGunDir ) -{ - // Fire one shots per round right at the player, using usual rules - FireBulletsInfo_t info; - info.m_vecSrc = vBasePos; - info.m_vecSpread = VECTOR_CONE_PRECALCULATED; - info.m_flDistance = MAX_COORD_RANGE; - info.m_iAmmoType = m_iAmmoType; - info.m_iTracerFreq = 1; - info.m_vecDirShooting = GetActualShootTrajectory( vBasePos ); - info.m_nFlags = FIRE_BULLETS_TEMPORARY_DANGER_SOUND; - - DoMuzzleFlash(); - - QAngle vGunAng; - VectorAngles( vGunDir, vGunAng ); - - FireBullets( info ); - - // Fire the rest of the bullets at objects around the player - CBaseEntity *ppNearbyTargets[16]; - int nActualTargets = BuildMissTargetList( 16, ppNearbyTargets ); - - // Randomly sort it... - int i; - for ( i = 0; i < nActualTargets; ++i ) - { - int nSwap = random->RandomInt( 0, nActualTargets - 1 ); - swap( ppNearbyTargets[i], ppNearbyTargets[nSwap] ); - } - - // Just shoot where we're facing - float flSinConeDegrees = sin( sk_helicopter_firingcone.GetFloat() * 0.5f * (3.14f / 180.0f) ); - Vector vecSpread( flSinConeDegrees, flSinConeDegrees, flSinConeDegrees ); - - // How many times should we hit the player this time? - int nDesiredHitCount = (int)(((float)( m_nMaxBurstHits - m_nBurstHits ) / (float)m_nRemainingBursts) + 0.5f); - int nNearbyTargetCount = 0; - int nPlayerShotCount = 0; - for ( i = sk_helicopter_roundsperburst.GetInt() - 1; --i >= 0; ) - { - // Find something interesting around the enemy to shoot instead of just missing. - if ( nActualTargets > nNearbyTargetCount ) - { - // FIXME: Constrain to the firing cone? - ppNearbyTargets[nNearbyTargetCount]->CollisionProp()->RandomPointInBounds( Vector(.25, .25, .25), Vector(.75, .75, .75), &info.m_vecDirShooting ); - info.m_vecDirShooting -= vBasePos; - VectorNormalize( info.m_vecDirShooting ); - info.m_vecSpread = VECTOR_CONE_PRECALCULATED; - info.m_flDistance = MAX_COORD_RANGE; - info.m_nFlags = FIRE_BULLETS_TEMPORARY_DANGER_SOUND; - - FireBullets( info ); - - ++nNearbyTargetCount; - continue; - } - - if ( GetEnemy() && ( nPlayerShotCount < nDesiredHitCount )) - { - GetEnemy()->CollisionProp()->RandomPointInBounds( Vector(0, 0, 0), Vector(1, 1, 1), &info.m_vecDirShooting ); - info.m_vecDirShooting -= vBasePos; - VectorNormalize( info.m_vecDirShooting ); - info.m_vecSpread = VECTOR_CONE_PRECALCULATED; - info.m_flDistance = MAX_COORD_RANGE; - info.m_nFlags = FIRE_BULLETS_TEMPORARY_DANGER_SOUND; - FireBullets( info ); - ++nPlayerShotCount; - continue; - } - - // Nothing nearby; just fire randomly... - info.m_vecDirShooting = vGunDir; - info.m_vecSpread = vecSpread; - info.m_flDistance = 8192; - info.m_nFlags = FIRE_BULLETS_TEMPORARY_DANGER_SOUND; - - FireBullets( info ); - } -} - - -//----------------------------------------------------------------------------- -// Chooses a point within the circle of death to fire in -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::PickDirectionToCircleOfDeath( const Vector &vBasePos, const Vector &vecFireAtPosition, Vector *pResult ) -{ - *pResult = vecFireAtPosition; - float x, y; - do - { - x = random->RandomFloat( -1.0f, 1.0f ); - y = random->RandomFloat( -1.0f, 1.0f ); - } while ( (x * x + y * y) > 1.0f ); - - pResult->x += x * m_flCircleOfDeathRadius; - pResult->y += y * m_flCircleOfDeathRadius; - - *pResult -= vBasePos; - VectorNormalize( *pResult ); -} - - -//----------------------------------------------------------------------------- -// Deliberately aims as close as possible w/o hitting -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::AimCloseToTargetButMiss( CBaseEntity *pTarget, float flMinDist, float flMaxDist, const Vector &shootOrigin, Vector *pResult ) -{ - Vector vecDirection; - VectorSubtract( pTarget->WorldSpaceCenter(), shootOrigin, vecDirection ); - float flDist = VectorNormalize( vecDirection ); - float flRadius = pTarget->BoundingRadius() + random->RandomFloat( flMinDist, flMaxDist ); - - float flMinRadius = flRadius; - if ( flDist > flRadius ) - { - flMinRadius = flDist * flRadius / sqrt( flDist * flDist - flRadius * flRadius ); - } - - // Choose random points in a plane perpendicular to the shoot origin. - Vector vecRandomDir; - vecRandomDir.Random( -1.0f, 1.0f ); - VectorMA( vecRandomDir, -DotProduct( vecDirection, vecRandomDir ), vecDirection, vecRandomDir ); - VectorNormalize( vecRandomDir ); - vecRandomDir *= flMinRadius; - vecRandomDir += pTarget->WorldSpaceCenter(); - - VectorSubtract( vecRandomDir, shootOrigin, *pResult ); - VectorNormalize( *pResult ); -} - - -//----------------------------------------------------------------------------- -// Make sure we don't hit too many times -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::FireBullets( const FireBulletsInfo_t &info ) -{ - // Use this to count the number of hits in a burst - bool bIsPlayer = GetEnemy() && GetEnemy()->IsPlayer(); - if ( !bIsPlayer ) - { - BaseClass::FireBullets( info ); - return; - } - - if ( !GetEnemyVehicle() && !IsDeadlyShooting() ) - { - if ( m_nBurstHits >= m_nMaxBurstHits ) - { - FireBulletsInfo_t actualInfo = info; - actualInfo.m_pAdditionalIgnoreEnt = GetEnemy(); - BaseClass::FireBullets( actualInfo ); - return; - } - } - - CBasePlayer *pPlayer = assert_cast(GetEnemy()); - - int nPrevHealth = pPlayer->GetHealth(); - int nPrevArmor = pPlayer->ArmorValue(); - - BaseClass::FireBullets( info ); - - if (( pPlayer->GetHealth() < nPrevHealth ) || ( pPlayer->ArmorValue() < nPrevArmor )) - { - ++m_nBurstHits; - } -} - - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::ShootInsideCircleOfDeath( const Vector &vBasePos, const Vector &vecFireAtPosition ) -{ - Vector vecFireDirection; - if ( m_nAttackMode == ATTACK_MODE_BULLRUSH_VEHICLE ) - { - PickDirectionToCircleOfDeath( vBasePos, vecFireAtPosition, &vecFireDirection ); - } - else if ( ( m_nNearShots < m_nMaxNearShots ) || !GetEnemyVehicle() ) - { - if ( ( m_nBurstHits < m_nMaxBurstHits ) || !GetEnemy() ) - { - ++m_nNearShots; - PickDirectionToCircleOfDeath( vBasePos, vecFireAtPosition, &vecFireDirection ); - } - else - { - m_nNearShots += 6; - AimCloseToTargetButMiss( GetEnemy(), 20.0f, 50.0f, vBasePos, &vecFireDirection ); - } - } - else - { - AimCloseToTargetButMiss( GetEnemyVehicle(), 10.0f, 80.0f, vBasePos, &vecFireDirection ); - } - - FireBulletsInfo_t info( 1, vBasePos, vecFireDirection, VECTOR_CONE_PRECALCULATED, MAX_COORD_RANGE, m_iAmmoType ); - info.m_iTracerFreq = 1; - info.m_nFlags = FIRE_BULLETS_TEMPORARY_DANGER_SOUND; - - FireBullets( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::DoMuzzleFlash( void ) -{ - BaseClass::DoMuzzleFlash(); - - CEffectData data; - - data.m_nAttachmentIndex = LookupAttachment( "muzzle" ); - data.m_nEntIndex = entindex(); - DispatchEffect( "ChopperMuzzleFlash", data ); -} - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -#define HIT_VEHICLE_SPEED_MIN 200.0f -#define HIT_VEHICLE_SPEED_MAX 500.0f - -void CNPC_AttackHelicopter::ShootAtVehicle( const Vector &vBasePos, const Vector &vecFireAtPosition ) -{ - int nShotsRemaining = sk_helicopter_roundsperburst.GetInt(); - - DoMuzzleFlash(); - - // Do special code against episodic drivers - if ( hl2_episodic.GetBool() ) - { - Vector vecVelocity; - GetEnemyVehicle()->GetVelocity( &vecVelocity, NULL ); - - float flSpeed = clamp( vecVelocity.Length(), 0.0f, 400.0f ); - float flRange = RemapVal( flSpeed, 0.0f, 400.0f, 0.05f, 1.0f ); - - // Alter each shot's trajectory based on our speed - for ( int i = 0; i < nShotsRemaining; i++ ) - { - Vector vecShotDir; - - // If they're at a dead stand-still, just hit them - if ( flRange <= 0.1f ) - { - VectorSubtract( GetEnemy()->EyePosition(), vBasePos, vecShotDir ); - - Vector vecOffset; - vecOffset.Random( -40.0f, 40.0f ); - vecShotDir += vecOffset; - VectorNormalize( vecShotDir ); - } - else - { - // Aim in a cone around them - AimCloseToTargetButMiss( GetEnemy(), (3*12) * flRange, (10*12) * flRange, vBasePos, &vecShotDir ); - } - - FireBulletsInfo_t info( 1, vBasePos, vecShotDir, VECTOR_CONE_PRECALCULATED, MAX_COORD_RANGE, m_iAmmoType ); - info.m_iTracerFreq = 1; - FireBullets( info ); - } - - // We opt out of the rest of the function - // FIXME: Should we emulate the below functionality and have half the bullets attempt to miss admirably? -- jdw - return; - } - - // Pop one at the player based on how fast he's going - if ( m_nBurstHits < m_nMaxBurstHits ) - { - Vector vecDir; - VectorSubtract( GetEnemy()->EyePosition(), vBasePos, vecDir ); - - Vector vecOffset; - vecOffset.Random( -5.0f, 5.0f ); - vecDir += vecOffset; - VectorNormalize( vecDir ); - - FireBulletsInfo_t info( 1, vBasePos, vecDir, VECTOR_CONE_PRECALCULATED, MAX_COORD_RANGE, m_iAmmoType ); - info.m_iTracerFreq = 1; - FireBullets( info ); - --nShotsRemaining; - } - - // Fire half of the bullets within the circle of death, the other half at interesting things - int i; - int nFireInCircle = nShotsRemaining >> 1; - nShotsRemaining -= nFireInCircle; - for ( i = 0; i < nFireInCircle; ++i ) - { - ShootInsideCircleOfDeath( vBasePos, vecFireAtPosition ); - } - - // Fire the rest of the bullets at objects around the enemy - CBaseEntity *ppNearbyTargets[16]; - int nActualTargets = BuildMissTargetList( 16, ppNearbyTargets ); - - // Randomly sort it... - for ( i = 0; i < nActualTargets; ++i ) - { - int nSwap = random->RandomInt( 0, nActualTargets - 1 ); - swap( ppNearbyTargets[i], ppNearbyTargets[nSwap] ); - } - - // Just shoot where we're facing - float flSinConeDegrees = sin( sk_helicopter_firingcone.GetFloat() * 0.5f * (3.14f / 180.0f) ); - Vector vecSpread( flSinConeDegrees, flSinConeDegrees, flSinConeDegrees ); - - for ( i = nShotsRemaining; --i >= 0; ) - { - // Find something interesting around the enemy to shoot instead of just missing. - if ( nActualTargets > i ) - { - Vector vecFireDirection; - ppNearbyTargets[i]->CollisionProp()->RandomPointInBounds( Vector(.25, .25, .25), Vector(.75, .75, .75), &vecFireDirection ); - vecFireDirection -= vBasePos; - VectorNormalize( vecFireDirection ); - - // FIXME: Constrain to the firing cone? - - // I put in all the default arguments simply so I could guarantee the first shot of one of the bursts always hits - FireBulletsInfo_t info( 1, vBasePos, vecFireDirection, VECTOR_CONE_PRECALCULATED, MAX_COORD_RANGE, m_iAmmoType ); - info.m_iTracerFreq = 1; - FireBullets( info ); - } - else - { - ShootInsideCircleOfDeath( vBasePos, vecFireAtPosition ); - } - } -} - - -//------------------------------------------------------------------------------ -// Various states of the helicopter firing... -//------------------------------------------------------------------------------ -bool CNPC_AttackHelicopter::PoseGunTowardTargetDirection( const Vector &vTargetDir ) -{ - Vector vecOut; - VectorIRotate( vTargetDir, EntityToWorldTransform(), vecOut ); - - QAngle angles; - VectorAngles(vecOut, angles); - - if (angles.y > 180) - { - angles.y = angles.y - 360; - } - else if (angles.y < -180) - { - angles.y = angles.y + 360; - } - if (angles.x > 180) - { - angles.x = angles.x - 360; - } - else if (angles.x < -180) - { - angles.x = angles.x + 360; - } - - if ( ( m_nAttackMode == ATTACK_MODE_BULLRUSH_VEHICLE ) && !IsInSecondaryMode(BULLRUSH_MODE_SHOOT_IDLE_PLAYER) && GetEnemy()) - { - if ( GetEnemyVehicle() ) - { - angles.x = clamp( angles.x, -12.0f, 0.0f ); - angles.y = clamp( angles.y, -10.0f, 10.0f ); - } - else - { - angles.x = clamp( angles.x, -10.0f, 10.0f ); - angles.y = clamp( angles.y, -10.0f, 10.0f ); - } - } - - if (angles.x > m_angGun.x) - { - m_angGun.x = MIN( angles.x, m_angGun.x + 12 ); - } - if (angles.x < m_angGun.x) - { - m_angGun.x = MAX( angles.x, m_angGun.x - 12 ); - } - if (angles.y > m_angGun.y) - { - m_angGun.y = MIN( angles.y, m_angGun.y + 12 ); - } - if (angles.y < m_angGun.y) - { - m_angGun.y = MAX( angles.y, m_angGun.y - 12 ); - } - - SetPoseParameter( m_poseWeapon_Pitch, -m_angGun.x ); - SetPoseParameter( m_poseWeapon_Yaw, m_angGun.y ); - - return true; -} - - -//------------------------------------------------------------------------------ -// Compute the enemy position (non-vehicle case) -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::ComputeFireAtPosition( Vector *pVecActualTargetPosition ) -{ - // Deal with various leading behaviors... - *pVecActualTargetPosition = m_vecTargetPosition; -} - - -//------------------------------------------------------------------------------ -// Compute the enemy position (non-vehicle case) -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::ComputeVehicleFireAtPosition( Vector *pVecActualTargetPosition ) -{ - CBaseEntity *pVehicle = GetEnemyVehicle(); - - // Make sure the circle of death doesn't move more than N units - // This will cause the target to have to maintain a large enough speed - *pVecActualTargetPosition = pVehicle->BodyTarget( GetAbsOrigin(), false ); - -// NDebugOverlay::Box( *pVecActualTargetPosition, -// Vector(-m_flCircleOfDeathRadius, -m_flCircleOfDeathRadius, 0), -// Vector(m_flCircleOfDeathRadius, m_flCircleOfDeathRadius, 0), -// 0, 0, 255, false, 0.1f ); -} - - -//------------------------------------------------------------------------------ -// Here's what we do when we're looking for a target -//------------------------------------------------------------------------------ -bool CNPC_AttackHelicopter::DoGunIdle( const Vector &vGunDir, const Vector &vTargetDir ) -{ - // When bullrushing, skip the idle - if ( ( m_nAttackMode == ATTACK_MODE_BULLRUSH_VEHICLE ) && - ( IsInSecondaryMode( BULLRUSH_MODE_SHOOT_GUN ) || IsInSecondaryMode(BULLRUSH_MODE_SHOOT_IDLE_PLAYER) ) ) - { - EmitSound( "NPC_AttackHelicopter.ChargeGun" ); - m_flChargeTime = gpGlobals->curtime + CHOPPER_GUN_CHARGE_TIME; - m_nGunState = GUN_STATE_CHARGING; - m_flCircleOfDeathRadius = CHOPPER_MAX_CIRCLE_OF_DEATH_RADIUS; - return true; - } - - // Can't continually fire.... - if (m_flNextAttack > gpGlobals->curtime) - return false; - - // Don't fire if we're too far away, or if the enemy isn't in front of us - if (!GetEnemy()) - return false; - - float flMaxDistSqr = GetMaxFiringDistance(); - flMaxDistSqr *= flMaxDistSqr; - - float flDistSqr = WorldSpaceCenter().DistToSqr( GetEnemy()->WorldSpaceCenter() ); - if (flDistSqr > flMaxDistSqr) - return false; - - // If he's mostly within the cone, shoot away! - float flChargeCone = sk_helicopter_firingcone.GetFloat() * 0.5f; - if ( flChargeCone < 15.0f ) - { - flChargeCone = 15.0f; - } - - float flCosConeDegrees = cos( flChargeCone * (3.14f / 180.0f) ); - float fDotPr = DotProduct( vGunDir, vTargetDir ); - if (fDotPr < flCosConeDegrees) - return false; - - // Fast shooting doesn't charge up - if( m_nShootingMode == SHOOT_MODE_FAST ) - { - m_flChargeTime = gpGlobals->curtime; - m_nGunState = GUN_STATE_CHARGING; - m_flAvoidMetric = 0.0f; - m_vecLastAngVelocity.Init( 0, 0, 0 ); - } - else - { - EmitSound( "NPC_AttackHelicopter.ChargeGun" ); - float flChargeTime = CHOPPER_GUN_CHARGE_TIME; - float flVariance = flChargeTime * 0.1f; - m_flChargeTime = gpGlobals->curtime + random->RandomFloat(flChargeTime - flVariance, flChargeTime + flVariance); - m_nGunState = GUN_STATE_CHARGING; - m_flAvoidMetric = 0.0f; - m_vecLastAngVelocity.Init( 0, 0, 0 ); - } - - return true; -} - - -//------------------------------------------------------------------------------ -// How easy is the target to hit? -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::UpdateTargetHittability() -{ - // This simply is a measure of how much juking is going on. - // Along with how much steering is happening. - if ( GetEnemyVehicle() ) - { - Vector vecVelocity; - AngularImpulse vecAngVelocity; - GetEnemyVehicle()->GetVelocity( &vecVelocity, &vecAngVelocity ); - - float flDist = fabs( vecAngVelocity.z - m_vecLastAngVelocity.z ); - m_flAvoidMetric += flDist; - m_vecLastAngVelocity = vecAngVelocity; - } -} - - -//------------------------------------------------------------------------------ -// Here's what we do when we're getting ready to fire -//------------------------------------------------------------------------------ -bool CNPC_AttackHelicopter::DoGunCharging( ) -{ - // Update the target hittability, which will indicate how many hits we'll accept. - UpdateTargetHittability(); - - if ( m_flChargeTime > gpGlobals->curtime ) - return false; - - m_nGunState = GUN_STATE_FIRING; - - if ( HasSpawnFlags( SF_HELICOPTER_AGGRESSIVE ) ) - { - SetPauseState( PAUSE_AT_NEXT_LOS_POSITION ); - } - - int nHitFactor = 1; - switch( GetShootingMode() ) - { - case SHOOT_MODE_DEFAULT: - case SHOOT_MODE_FAST: - { - int nBurstCount = sk_helicopter_burstcount.GetInt(); - m_nRemainingBursts = random->RandomInt( nBurstCount, 2 * nBurstCount ); - m_flIdleTimeDelay = 0.1f * ( m_nRemainingBursts - nBurstCount ); - } - break; - - case SHOOT_MODE_LONG_CYCLE: - { - m_nRemainingBursts = 60; - m_flIdleTimeDelay = 0.0f; - nHitFactor = 2; - } - break; - - case SHOOT_MODE_CONTINUOUS: - if ( m_nAttackMode == ATTACK_MODE_BULLRUSH_VEHICLE ) - { - // We're relying on the special aiming behavior for bullrushing to just randomly deal damage - m_nRemainingBursts = 1; - m_flIdleTimeDelay = 0.0f; - } - else - { - m_nRemainingBursts = 0; - m_flIdleTimeDelay = 0.0f; - nHitFactor = 1000; - } - break; - } - - if ( !GetEnemyVehicle() ) - { - m_nMaxBurstHits = !IsDeadlyShooting() ? random->RandomInt( 6, 9 ) : 200; - m_nMaxNearShots = 10000; - } - else - { - Vector vecVelocity; - GetEnemyVehicle()->GetVelocity( &vecVelocity, NULL ); - float flSpeed = vecVelocity.Length(); - flSpeed = clamp( flSpeed, 150.0f, 600.0f ); - flSpeed = RemapVal( flSpeed, 150.0f, 600.0f, 0.0f, 1.0f ); - float flAvoid = clamp( m_flAvoidMetric, 100.0f, 400.0f ); - flAvoid = RemapVal( flAvoid, 100.0f, 400.0f, 0.0f, 1.0f ); - - float flTotal = 0.5f * ( flSpeed + flAvoid ); - int nHitCount = (int)(RemapVal( flTotal, 0.0f, 1.0f, 7, -0.5 ) + 0.5f); - - int nMin = nHitCount >= 1 ? nHitCount - 1 : 0; - m_nMaxBurstHits = random->RandomInt( nMin, nHitCount + 1 ); - - int nNearShots = (int)(RemapVal( flTotal, 0.0f, 1.0f, 70, 5 ) + 0.5f); - int nMinNearShots = nNearShots >= 5 ? nNearShots - 5 : 0; - m_nMaxNearShots = random->RandomInt( nMinNearShots, nNearShots + 5 ); - - // Set up the circle of death parameters at this point - m_flCircleOfDeathRadius = SimpleSplineRemapVal( flTotal, 0.0f, 1.0f, - CHOPPER_MIN_CIRCLE_OF_DEATH_RADIUS, CHOPPER_MAX_CIRCLE_OF_DEATH_RADIUS ); - } - - m_nMaxBurstHits *= nHitFactor; - m_nMaxNearShots *= nHitFactor; - - m_nBurstHits = 0; - m_nNearShots = 0; - return true; -} - - -//------------------------------------------------------------------------------ -// Shoot where we're facing -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::ShootAtFacingDirection( const Vector &vBasePos, const Vector &vGunDir, bool bFirstShotAccurate ) -{ - // Just shoot where we're facing - float flSinConeDegrees = sin( sk_helicopter_firingcone.GetFloat() * 0.5f * (3.14f / 180.0f) ); - Vector vecSpread( flSinConeDegrees, flSinConeDegrees, flSinConeDegrees ); - - int nShotCount = sk_helicopter_roundsperburst.GetInt(); - if ( bFirstShotAccurate && GetEnemy() ) - { - // Check to see if the enemy is within his firing cone - if ( GetEnemy() ) - { - // Find the closest point to the gunDir - const Vector &vecCenter = GetEnemy()->WorldSpaceCenter(); - - float t; - Vector vNearPoint; - Vector vEndPoint; - VectorMA( vBasePos, 1024.0f, vGunDir, vEndPoint ); - CalcClosestPointOnLine( vecCenter, vBasePos, vEndPoint, vNearPoint, &t ); - if ( t > 0.0f ) - { - Vector vecDelta; - VectorSubtract( vecCenter, vBasePos, vecDelta ); - float flDist = VectorNormalize( vecDelta ); - float flPerpDist = vecCenter.DistTo( vNearPoint ); - float flSinAngle = flPerpDist / flDist; - if ( flSinAngle <= flSinConeDegrees ) - { - FireBulletsInfo_t info( 1, vBasePos, vecDelta, VECTOR_CONE_PRECALCULATED, 8192, m_iAmmoType ); - info.m_iTracerFreq = 1; - FireBullets( info ); - --nShotCount; - } - } - } - } - -#ifdef HL2_EPISODIC - if( GetEnemy() != NULL ) - { - CSoundEnt::InsertSound( SOUND_DANGER, GetEnemy()->WorldSpaceCenter(), 180, 0.5f, this, SOUNDENT_CHANNEL_REPEATED_DANGER ); - } -#endif//HL2_EPISODIC - - DoMuzzleFlash(); - - FireBulletsInfo_t info( nShotCount, vBasePos, vGunDir, vecSpread, 8192, m_iAmmoType ); - info.m_iTracerFreq = 1; - FireBullets( info ); -} - - -//----------------------------------------------------------------------------- -// Can we zap it? -//----------------------------------------------------------------------------- -bool CNPC_AttackHelicopter::IsValidZapTarget( CBaseEntity *pTarget ) -{ - // Don't use the player or vehicle as a zap target, we'll do that ourselves. - if ( pTarget->IsPlayer() || pTarget->GetServerVehicle() ) - return false; - - if ( pTarget == this ) - return false; - - if ( !pTarget->IsSolid() ) - return false; - - Assert( pTarget ); - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int count = pTarget->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - for ( int i = 0; i < count; i++ ) - { - int material = pList[i]->GetMaterialIndex(); - const surfacedata_t *pSurfaceData = physprops->GetSurfaceData( material ); - - // Is flesh or metal? Go for it! - if ( pSurfaceData->game.material == CHAR_TEX_METAL || - pSurfaceData->game.material == CHAR_TEX_FLESH || - pSurfaceData->game.material == CHAR_TEX_VENT || - pSurfaceData->game.material == CHAR_TEX_GRATE || - pSurfaceData->game.material == CHAR_TEX_COMPUTER || - pSurfaceData->game.material == CHAR_TEX_BLOODYFLESH || - pSurfaceData->game.material == CHAR_TEX_ALIENFLESH ) - { - return true; - } - } - return false; -} - - -//------------------------------------------------------------------------------ -// Effects -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::CreateZapBeam( const Vector &vecTargetPos ) -{ - CEffectData data; - data.m_nEntIndex = entindex(); - data.m_nAttachmentIndex = 0; // m_nGunTipAttachment; - data.m_vOrigin = vecTargetPos; - data.m_flScale = 5; - DispatchEffect( "TeslaZap", data ); -} - -void CNPC_AttackHelicopter::CreateEntityZapEffect( CBaseEntity *pEnt ) -{ - CEffectData data; - data.m_nEntIndex = pEnt->entindex(); - data.m_flMagnitude = 10; - data.m_flScale = 1.0f; - DispatchEffect( "TeslaHitboxes", data ); -} - - -//------------------------------------------------------------------------------ -// Here's what we do when we *are* firing -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::FireElectricityGun( ) -{ - if ( m_flNextAttack > gpGlobals->curtime ) - return; - - EmitSound( "ReallyLoudSpark" ); - - CBaseEntity *ppEnts[256]; - Vector vecCenter = WorldSpaceCenter(); - float flRadius = 500.0f; - vecCenter.z -= flRadius * 0.8f; - int nEntCount = UTIL_EntitiesInSphere( ppEnts, 256, vecCenter, flRadius, 0 ); - CBaseEntity *ppCandidates[256]; - int nCandidateCount = 0; - int i; - for ( i = 0; i < nEntCount; i++ ) - { - if ( ppEnts[i] == NULL ) - continue; - - // Zap metal or flesh things. - if ( !IsValidZapTarget( ppEnts[i] ) ) - continue; - - ppCandidates[ nCandidateCount++ ] = ppEnts[i]; - } - - // First, put a bolt in front of the player, at random - float flDist = 1024; - if ( GetEnemy() ) - { - Vector vecDelta; - Vector2DSubtract( GetEnemy()->WorldSpaceCenter().AsVector2D(), WorldSpaceCenter().AsVector2D(), vecDelta.AsVector2D() ); - vecDelta.z = 0.0f; - - flDist = VectorNormalize( vecDelta ); - Vector vecPerp( -vecDelta.y, vecDelta.x, 0.0f ); - int nBoltCount = (int)(ClampSplineRemapVal( flDist, 256.0f, 1024.0f, 8, 0 ) + 0.5f); - - for ( i = 0; i < nBoltCount; ++i ) - { - Vector vecTargetPt = GetEnemy()->WorldSpaceCenter(); - VectorMA( vecTargetPt, random->RandomFloat( flDist + 100, flDist + 500 ), vecDelta, vecTargetPt ); - VectorMA( vecTargetPt, random->RandomFloat( -500, 500 ), vecPerp, vecTargetPt ); - vecTargetPt.z += random->RandomFloat( -500, 500 ); - CreateZapBeam( vecTargetPt ); - } - } - - // Next, choose the number of bolts... - int nBoltCount = random->RandomInt( 8, 16 ); - for ( i = 0; i < nBoltCount; ++i ) - { - if ( (nCandidateCount > 0) && random->RandomFloat( 0.0f, 1.0f ) < 0.6f ) - { - --nCandidateCount; - - Vector vecTarget; - ppCandidates[nCandidateCount]->CollisionProp()->RandomPointInBounds( vec3_origin, Vector( 1, 1, 1 ), &vecTarget ); - CreateZapBeam( vecTarget ); - CreateEntityZapEffect( ppCandidates[nCandidateCount] ); - } - else - { - // Select random point *on* sphere - Vector vecTargetPt; - float flEffectRadius = random->RandomFloat( flRadius * 1.2, flRadius * 1.5f ); - float flTheta = random->RandomFloat( 0.0f, 2.0f * M_PI ); - float flPhi = random->RandomFloat( -0.5f * M_PI, 0.5f * M_PI ); - vecTargetPt.x = cos(flTheta) * cos(flPhi); - vecTargetPt.y = sin(flTheta) * cos(flPhi); - vecTargetPt.z = sin(flPhi); - vecTargetPt *= flEffectRadius; - vecTargetPt += vecCenter; - - CreateZapBeam( vecTargetPt ); - } - } - - // Finally, put a bolt right at the player, at random - float flHitRatio = ClampSplineRemapVal( flDist, 128.0f, 512.0f, 0.75f, 0.0f ); - if ( random->RandomFloat( 0.0f, 1.0f ) < flHitRatio ) - { - if ( GetEnemyVehicle() ) - { - Vector vecTarget; - GetEnemyVehicle()->CollisionProp()->RandomPointInBounds( vec3_origin, Vector( 1, 1, 1 ), &vecTarget ); - CreateZapBeam( vecTarget ); - CreateEntityZapEffect( GetEnemyVehicle() ); - - CTakeDamageInfo info( this, this, 5, DMG_SHOCK ); - GetEnemy()->TakeDamage( info ); - } - else if ( GetEnemy() ) - { - Vector vecTarget; - GetEnemy()->CollisionProp()->RandomPointInBounds( vec3_origin, Vector( 1, 1, 1 ), &vecTarget ); - CreateZapBeam( vecTarget ); - - CTakeDamageInfo info( this, this, 5, DMG_SHOCK ); - GetEnemy()->TakeDamage( info ); - } - } - - m_flNextAttack = gpGlobals->curtime + random->RandomFloat( 0.3f, 1.0f ); -} - - -//------------------------------------------------------------------------------ -// Here's what we do when we *are* firing -//------------------------------------------------------------------------------ -#define INTERVAL_BETWEEN_HITS 4 - -bool CNPC_AttackHelicopter::DoGunFiring( const Vector &vBasePos, const Vector &vGunDir, const Vector &vecFireAtPosition ) -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - float flVolume = controller.SoundGetVolume( m_pGunFiringSound ); - if ( flVolume != 1.0f ) - { - controller.SoundChangeVolume( m_pGunFiringSound, 1.0, 0.01f ); - } - - if ( ( m_nAttackMode == ATTACK_MODE_BULLRUSH_VEHICLE ) && ( IsInSecondaryMode( BULLRUSH_MODE_SHOOT_GUN ) ) ) - { - ShootAtFacingDirection( vBasePos, vGunDir, m_nRemainingBursts == 0 ); - } - else if ( GetEnemyVehicle() ) - { - ShootAtVehicle( vBasePos, vecFireAtPosition ); - } - else if ( GetEnemy() && GetEnemy()->IsPlayer() ) - { - if ( !IsDeadlyShooting() ) - { - ShootAtPlayer( vBasePos, vGunDir ); - } - else - { - ShootAtFacingDirection( vBasePos, vGunDir, true ); - } - } - else - { - ShootAtFacingDirection( vBasePos, vGunDir, false ); - } - - if ( m_nAttackMode == ATTACK_MODE_BULLRUSH_VEHICLE ) - { - if ( --m_nRemainingBursts < 0 ) - { - m_nRemainingBursts = INTERVAL_BETWEEN_HITS; - } - return true; - } - - --m_nRemainingBursts; - if ( m_nRemainingBursts > 0 ) - return true; - - controller.SoundChangeVolume( m_pGunFiringSound, 0.0, 0.01f ); - float flIdleTime = CHOPPER_GUN_IDLE_TIME; - float flVariance = flIdleTime * 0.1f; - m_flNextAttack = gpGlobals->curtime + m_flIdleTimeDelay + random->RandomFloat(flIdleTime - flVariance, flIdleTime + flVariance); - m_nGunState = GUN_STATE_IDLE; - SetPauseState( PAUSE_NO_PAUSE ); - return true; -} - - -//------------------------------------------------------------------------------ -// Is it "fair" to drop this bomb? -//------------------------------------------------------------------------------ -#define MIN_BOMB_DISTANCE_SQR ( 600.0f * 600.0f ) - -bool CNPC_AttackHelicopter::IsBombDropFair( const Vector &vecBombStartPos, const Vector &vecBombVelocity ) -{ - if ( (m_nAttackMode == ATTACK_MODE_BULLRUSH_VEHICLE) && IsInSecondaryMode( BULLRUSH_MODE_SHOOT_IDLE_PLAYER ) ) - return true; - - // Can happen if you're noclipping around - if ( !GetEnemy() ) - return false; - - // If the player is moving slowly, it's fair - if ( GetEnemy()->GetSmoothedVelocity().LengthSqr() < ( CHOPPER_SLOW_BOMB_SPEED * CHOPPER_SLOW_BOMB_SPEED ) ) - return true; - - // Skip out if we're right above or behind the player.. that's unfair - if ( GetEnemy() && GetEnemy()->IsPlayer() ) - { - // How much time will it take to fall? - // dx = 0.5 * a * t^2 - Vector vecTarget = GetEnemy()->BodyTarget( GetAbsOrigin(), false ); - float dz = vecBombStartPos.z - vecTarget.z; - float dt = (dz > 0.0f) ? sqrt( 2 * dz / sv_gravity.GetFloat() ) : 0.0f; - - // Where will the enemy be in that time? - Vector vecEnemyVel = GetEnemy()->GetSmoothedVelocity(); - VectorMA( vecTarget, dt, vecEnemyVel, vecTarget ); - - // Where will the bomb be in that time? - Vector vecBomb; - VectorMA( vecBombStartPos, dt, vecBombVelocity, vecBomb ); - - float flEnemySpeed = vecEnemyVel.LengthSqr(); - flEnemySpeed = clamp( flEnemySpeed, 200.0f, 500.0f ); - float flDistFactorSq = RemapVal( flEnemySpeed, 200.0f, 500.0f, 0.3f, 1.0f ); - flDistFactorSq *= flDistFactorSq; - - // If it's too close, then we're not doing it. - if ( vecBomb.AsVector2D().DistToSqr( vecTarget.AsVector2D() ) < (flDistFactorSq * MIN_BOMB_DISTANCE_SQR) ) - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Create the bomb entity and set it up -// Input : &vecPos - Position to spawn at -// &vecVelocity - velocity to spawn with -//----------------------------------------------------------------------------- -CGrenadeHelicopter *CNPC_AttackHelicopter::SpawnBombEntity( const Vector &vecPos, const Vector &vecVelocity ) -{ - // Create the grenade and set it up - CGrenadeHelicopter *pGrenade = static_cast(CreateEntityByName( "grenade_helicopter" )); - pGrenade->SetAbsOrigin( vecPos ); - pGrenade->SetOwnerEntity( this ); - pGrenade->SetThrower( this ); - pGrenade->SetAbsVelocity( vecVelocity ); - DispatchSpawn( pGrenade ); - pGrenade->SetExplodeOnContact( m_bBombsExplodeOnContact ); - -#ifdef HL2_EPISODIC - // Disable collisions with the owner's bone followers while we drop - physfollower_t *pFollower = m_BoneFollowerManager.GetBoneFollower( 0 ); - if ( pFollower ) - { - CBaseEntity *pBoneFollower = pFollower->hFollower; - PhysDisableEntityCollisions( pBoneFollower, pGrenade ); - pGrenade->SetCollisionObject( pBoneFollower ); - } -#endif // HL2_EPISODIC - - return pGrenade; -} - -//------------------------------------------------------------------------------ -// Actually drops the bomb -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::CreateBomb( bool bCheckForFairness, Vector *pVecVelocity, bool bMegaBomb ) -{ - if ( m_bBombingSuppressed ) - return; - - Vector vTipPos; - GetAttachment( m_nBombAttachment, vTipPos ); - - if ( !CBombSuppressor::CanBomb( vTipPos ) ) - return; - - // Compute velocity - Vector vecActualVelocity; - if ( !pVecVelocity ) - { - Vector vecAcross; - vecActualVelocity = GetAbsVelocity(); - CrossProduct( vecActualVelocity, Vector( 0, 0, 1 ), vecAcross ); - VectorNormalize( vecAcross ); - vecAcross *= random->RandomFloat( 10.0f, 30.0f ); - vecAcross *= random->RandomFloat( 0.0f, 1.0f ) < 0.5f ? 1.0f : -1.0f; - - // Blat out z component of velocity if it's moving upward.... - if ( vecActualVelocity.z > 0 ) - { - vecActualVelocity.z = 0.0f; - } - - vecActualVelocity += vecAcross; - } - else - { - vecActualVelocity = *pVecVelocity; - } - - if ( bCheckForFairness ) - { - if ( !IsBombDropFair( vTipPos, vecActualVelocity ) ) - return; - } - - AddGesture( (Activity)ACT_HELICOPTER_DROP_BOMB ); - EmitSound( "NPC_AttackHelicopter.DropMine" ); - - // Make the bomb and send it off - CGrenadeHelicopter *pGrenade = SpawnBombEntity( vTipPos, vecActualVelocity ); - if ( pGrenade && bMegaBomb ) - { - pGrenade->AddSpawnFlags( SF_GRENADE_HELICOPTER_MEGABOMB ); - } -} - - -//------------------------------------------------------------------------------ -// Drop a bomb at a particular location -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::InputDropBomb( inputdata_t &inputdata ) -{ - if ( m_flInputDropBombTime > gpGlobals->curtime ) - return; - - // Prevent two triggers from being hit the same frame - m_flInputDropBombTime = gpGlobals->curtime + 0.01f; - - CreateBomb( ); - - // If we're in the middle of a bomb dropping schedule, wait to drop another bomb. - if ( ShouldDropBombs() ) - { - m_flNextAttack = gpGlobals->curtime + 0.5f + random->RandomFloat( 0.3f, 0.6f ); - } -} - - -//------------------------------------------------------------------------------ -// Drops a bomb straight downwards -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::InputDropBombStraightDown( inputdata_t &inputdata ) -{ - if ( m_flInputDropBombTime > gpGlobals->curtime ) - return; - - // Prevent two triggers from being hit the same frame - m_flInputDropBombTime = gpGlobals->curtime + 0.01f; - - Vector vTipPos; - GetAttachment( m_nBombAttachment, vTipPos ); - - // Make the bomb drop straight down - SpawnBombEntity( vTipPos, vec3_origin ); - - // If we're in the middle of a bomb dropping schedule, wait to drop another bomb. - if ( ShouldDropBombs() ) - { - m_flNextAttack = gpGlobals->curtime + 0.5f + random->RandomFloat( 0.3f, 0.6f ); - } -} - - -//------------------------------------------------------------------------------ -// Drop a bomb at a particular location -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::InputDropBombAtTargetInternal( inputdata_t &inputdata, bool bCheckFairness ) -{ - if ( m_flInputDropBombTime > gpGlobals->curtime ) - return; - - // Prevent two triggers from being hit the same frame - m_flInputDropBombTime = gpGlobals->curtime + 0.01f; - - // Find our specified target - string_t strBombTarget = MAKE_STRING( inputdata.value.String() ); - CBaseEntity *pBombEnt = gEntList.FindEntityByName( NULL, strBombTarget ); - if ( pBombEnt == NULL ) - { - Warning( "%s: Could not find bomb drop target '%s'!\n", GetClassname(), STRING( strBombTarget ) ); - return; - } - - Vector vTipPos; - GetAttachment( m_nBombAttachment, vTipPos ); - - // Compute the time it would take to fall to the target - Vector vecTarget = pBombEnt->BodyTarget( GetAbsOrigin(), false ); - float dz = vTipPos.z - vecTarget.z; - if ( dz <= 0.0f ) - { - Warning("Bomb target %s is above the chopper!\n", STRING( strBombTarget ) ); - return; - } - float dt = sqrt( 2 * dz / sv_gravity.GetFloat() ); - - // Compute the velocity that would make it happen - Vector vecVelocity; - VectorSubtract( vecTarget, vTipPos, vecVelocity ); - vecVelocity /= dt; - vecVelocity.z = 0.0f; - - if ( bCheckFairness ) - { - if ( !IsBombDropFair( vTipPos, vecVelocity ) ) - return; - } - - // Make the bomb and send it off - SpawnBombEntity( vTipPos, vecVelocity ); - - // If we're in the middle of a bomb dropping schedule, wait to drop another bomb. - if ( ShouldDropBombs() ) - { - m_flNextAttack = gpGlobals->curtime + 1.5f + random->RandomFloat( 0.1f, 0.2f ); - } -} - - -//------------------------------------------------------------------------------ -// Drop a bomb at a particular location -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::InputDropBombAtTargetAlways( inputdata_t &inputdata ) -{ - InputDropBombAtTargetInternal( inputdata, false ); -} - - -//------------------------------------------------------------------------------ -// Drop a bomb at a particular location -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::InputDropBombAtTarget( inputdata_t &inputdata ) -{ - InputDropBombAtTargetInternal( inputdata, true ); -} - - -//------------------------------------------------------------------------------ -// Drop a bomb at a particular location -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::InputDropBombDelay( inputdata_t &inputdata ) -{ - m_flInputDropBombTime = gpGlobals->curtime + inputdata.value.Float(); - - if ( ShouldDropBombs() ) - { - m_flNextAttack = m_flInputDropBombTime; - } -} - - -//------------------------------------------------------------------------------ -// Drop those bombs! -//------------------------------------------------------------------------------ -#define MAX_BULLRUSH_BOMB_DISTANCE_SQR ( 3072.0f * 3072.0f ) - -void CNPC_AttackHelicopter::DropBombs( ) -{ - // Can't continually fire.... - if (m_flNextAttack > gpGlobals->curtime) - return; - - // Otherwise, behave as normal. - if ( m_nAttackMode != ATTACK_MODE_BULLRUSH_VEHICLE ) - { - if ( GetEnemy() && GetEnemy()->IsPlayer() ) - { - if ( GetEnemy()->GetSmoothedVelocity().LengthSqr() > ( CHOPPER_SLOW_BOMB_SPEED * CHOPPER_SLOW_BOMB_SPEED ) ) - { - // Don't drop bombs if you are behind the player, unless the player is moving slowly - float flLeadingDistSq = GetLeadingDistance() * 0.75f; - flLeadingDistSq *= flLeadingDistSq; - - Vector vecPoint; - ClosestPointToCurrentPath( &vecPoint ); - if ( vecPoint.AsVector2D().DistToSqr( GetDesiredPosition().AsVector2D() ) > flLeadingDistSq ) - return; - } - } - } - else - { - // Skip out if we're bullrushing but too far from the player - if ( GetEnemy() ) - { - if ( GetEnemy()->GetAbsOrigin().AsVector2D().DistToSqr( GetAbsOrigin().AsVector2D() ) > MAX_BULLRUSH_BOMB_DISTANCE_SQR ) - return; - } - } - - CreateBomb( ); - - m_flNextAttack = gpGlobals->curtime + 0.5f + random->RandomFloat( 0.3f, 0.6f ); - - if ( (m_nAttackMode != ATTACK_MODE_BULLRUSH_VEHICLE) ) - { - if ( --m_nGrenadeCount <= 0 ) - { - m_nGrenadeCount = CHOPPER_BOMB_DROP_COUNT; - m_flNextAttack += random->RandomFloat( 1.5f, 3.0f ); - } - } -} - - -//------------------------------------------------------------------------------ -// Should we drop those bombs? -//------------------------------------------------------------------------------ -#define BOMB_GRACE_PERIOD 1.5f -#define BOMB_MIN_SPEED 150.0 - -bool CNPC_AttackHelicopter::ShouldDropBombs( void ) -{ - if ( IsCarpetBombing() ) - return true; - - if ( m_nAttackMode == ATTACK_MODE_BULLRUSH_VEHICLE ) - { - // Distance determines whether or not we should do this - if ((m_nSecondaryMode == BULLRUSH_MODE_SHOOT_IDLE_PLAYER) && (SecondaryModeTime() >= BULLRUSH_IDLE_PLAYER_FIRE_TIME)) - return ShouldBombIdlePlayer(); - - return (( m_nSecondaryMode == BULLRUSH_MODE_DROP_BOMBS_FIXED_SPEED ) || ( m_nSecondaryMode == BULLRUSH_MODE_DROP_BOMBS_FOLLOW_PLAYER )); - } - - if (!IsLeading() || !GetEnemyVehicle()) - return false; - - if (( m_nAttackMode != ATTACK_MODE_BOMB_VEHICLE ) && ( m_nAttackMode != ATTACK_MODE_ALWAYS_LEAD_VEHICLE )) - return false; - - if ( m_nGunState != GUN_STATE_IDLE ) - return false; - - // This is for bombing. If you get hit, give a grace period to get back to speed - float flSpeedSqr = GetEnemy()->GetSmoothedVelocity().LengthSqr(); - if ( flSpeedSqr >= BOMB_MIN_SPEED * BOMB_MIN_SPEED ) - { - m_flLastFastTime = gpGlobals->curtime; - } - else - { - if ( ( gpGlobals->curtime - m_flLastFastTime ) < BOMB_GRACE_PERIOD ) - return false; - } - - float flSpeedAlongPath = TargetSpeedAlongPath(); - if ( m_nAttackMode == ATTACK_MODE_BOMB_VEHICLE ) - return ( flSpeedAlongPath > -BOMB_MIN_SPEED ); - - // This is for ALWAYS_LEAD - if ( fabs(flSpeedAlongPath) < 50.0f ) - return false; - - float flLeadingDist = ComputeDistanceToLeadingPosition( ); - flLeadingDist = GetLeadingDistance() - flLeadingDist; - if ( flSpeedAlongPath < 0.0f ) - { - return flLeadingDist < 300.0f; - } - else - { - return flLeadingDist > -300.0f; - } -} - - -//------------------------------------------------------------------------------ -// Different bomb-dropping behavior -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::BullrushBombs( ) -{ - if ( gpGlobals->curtime < m_flNextBullrushBombTime ) - return; - - if ( m_nBullrushBombMode & 0x1 ) - { - CreateBomb( false, NULL, true ); - } - else - { - Vector vecAcross; - Vector vecVelocity = GetAbsVelocity(); - CrossProduct( vecVelocity, Vector( 0, 0, 1 ), vecAcross ); - VectorNormalize( vecAcross ); - vecAcross *= random->RandomFloat( 300.0f, 500.0f ); - - // Blat out z component of velocity if it's moving upward.... - if ( vecVelocity.z > 0 ) - { - vecVelocity.z = 0.0f; - } - vecVelocity += vecAcross; - CreateBomb( false, &vecVelocity, true ); - - VectorMA( vecVelocity, -2.0f, vecAcross, vecVelocity ); - CreateBomb( false, &vecVelocity, true ); - } - - m_nBullrushBombMode = !m_nBullrushBombMode; - m_flNextBullrushBombTime = gpGlobals->curtime + 0.2f; -} - - -//----------------------------------------------------------------------------- -// Purpose: Turn the gun off -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::InputGunOff( inputdata_t &inputdata ) -{ - BaseClass::InputGunOff( inputdata ); - - if ( m_pGunFiringSound ) - { - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundChangeVolume( m_pGunFiringSound, 0.0, 0.01f ); - } -} - - -//------------------------------------------------------------------------------ -// Fire that gun baby! -//------------------------------------------------------------------------------ -bool CNPC_AttackHelicopter::FireGun( void ) -{ - // Do the test electricity gun - if ( HasSpawnFlags(SF_HELICOPTER_ELECTRICAL_DRONE) ) - { - FireElectricityGun( ); - return true; - } - - // HACK: CBaseHelicopter ignores this, and fire forever at the last place it saw the player. Why? - if (( m_nGunState == GUN_STATE_IDLE ) && ( m_nAttackMode != ATTACK_MODE_BULLRUSH_VEHICLE ) && !IsCarpetBombing() ) - { - if ( (m_flLastSeen + 1 <= gpGlobals->curtime) || (m_flPrevSeen + m_flGracePeriod > gpGlobals->curtime) ) - return false; - } - - if ( IsCarpetBombing() ) - { - BullrushBombs(); - return false; - } - - if ( ShouldDropBombs() ) - { - DropBombs( ); - return false; - } - - // Drop those bullrush bombs when shooting... - if ( m_nAttackMode == ATTACK_MODE_BULLRUSH_VEHICLE ) - { - if ( IsInSecondaryMode( BULLRUSH_MODE_MEGA_BOMB ) ) - { - BullrushBombs( ); - return false; - } - - // Don't fire if we're bullrushing and we're getting distance - if ( !IsInSecondaryMode( BULLRUSH_MODE_SHOOT_GUN ) && !IsInSecondaryMode(BULLRUSH_MODE_SHOOT_IDLE_PLAYER) ) - return false; - - // If we're in the grace period on this mode, then don't fire - if ( IsInSecondaryMode( BULLRUSH_MODE_SHOOT_IDLE_PLAYER ) && (SecondaryModeTime() < BULLRUSH_IDLE_PLAYER_FIRE_TIME) ) - { - // Stop our gun sound - if ( m_nGunState != GUN_STATE_IDLE ) - { - ShutdownGunDuringBullrush(); - } - - return false; - } - } - - // Get gun attachment points - Vector vBasePos; - GetAttachment( m_nGunBaseAttachment, vBasePos ); - - // Aim perfectly while idle, but after charging, the gun don't move so fast. - Vector vecFireAtPosition; - if ( !GetEnemyVehicle() || (m_nGunState == GUN_STATE_IDLE) ) - { - ComputeFireAtPosition( &vecFireAtPosition ); - } - else - { - ComputeVehicleFireAtPosition( &vecFireAtPosition ); - } - - Vector vTargetDir = vecFireAtPosition - vBasePos; - VectorNormalize( vTargetDir ); - - // Makes the model of the gun point to where we're aiming. - if ( !PoseGunTowardTargetDirection( vTargetDir ) ) - return false; - - // Are we charging? - if ( m_nGunState == GUN_STATE_CHARGING ) - { - if ( !DoGunCharging( ) ) - return false; - } - - Vector vTipPos; - GetAttachment( m_nGunTipAttachment, vTipPos ); - - Vector vGunDir = vTipPos - vBasePos; - VectorNormalize( vGunDir ); - - // Are we firing? - if ( m_nGunState == GUN_STATE_FIRING ) - { - return DoGunFiring( vTipPos, vGunDir, vecFireAtPosition ); - } - - return DoGunIdle( vGunDir, vTargetDir ); -} - - -//----------------------------------------------------------------------------- -// Should we trigger a damage effect? -//----------------------------------------------------------------------------- -inline bool CNPC_AttackHelicopter::ShouldTriggerDamageEffect( int nPrevHealth, int nEffectCount ) const -{ - int nPrevRange = (int)( ((float)nPrevHealth / (float)GetMaxHealth()) * nEffectCount ); - int nRange = (int)( ((float)GetHealth() / (float)GetMaxHealth()) * nEffectCount ); - return ( nRange != nPrevRange ); -} - - -//----------------------------------------------------------------------------- -// Add a smoke trail since we've taken more damage -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::AddSmokeTrail( const Vector &vecPos ) -{ - if ( m_nSmokeTrailCount == MAX_SMOKE_TRAILS ) - return; - - // See if there's an attachment for this smoke trail - int nAttachment = LookupAttachment( UTIL_VarArgs( "damage%d", m_nSmokeTrailCount ) ); - - if ( nAttachment == 0 ) - return; - - // The final smoke trail is a flaming engine - if ( m_nSmokeTrailCount == 0 || m_nSmokeTrailCount % 2 ) - { - CFireTrail *pFireTrail = CFireTrail::CreateFireTrail(); - - if ( pFireTrail == NULL ) - return; - - m_hSmokeTrail[m_nSmokeTrailCount] = pFireTrail; - - pFireTrail->FollowEntity( this, UTIL_VarArgs( "damage%d", m_nSmokeTrailCount ) ); - pFireTrail->SetParent( this, nAttachment ); - pFireTrail->SetLocalOrigin( vec3_origin ); - pFireTrail->SetMoveType( MOVETYPE_NONE ); - pFireTrail->SetLifetime( -1 ); - } - else - { - SmokeTrail *pSmokeTrail = SmokeTrail::CreateSmokeTrail(); - if( !pSmokeTrail ) - return; - - m_hSmokeTrail[m_nSmokeTrailCount] = pSmokeTrail; - - pSmokeTrail->m_SpawnRate = 48; - pSmokeTrail->m_ParticleLifetime = 0.5f; - pSmokeTrail->m_StartColor.Init(0.15, 0.15, 0.15); - pSmokeTrail->m_EndColor.Init(0.0, 0.0, 0.0); - pSmokeTrail->m_StartSize = 24; - pSmokeTrail->m_EndSize = 80; - pSmokeTrail->m_SpawnRadius = 8; - pSmokeTrail->m_Opacity = 0.2; - pSmokeTrail->m_MinSpeed = 16; - pSmokeTrail->m_MaxSpeed = 64; - pSmokeTrail->SetLifetime(-1); - pSmokeTrail->SetParent( this, nAttachment ); - pSmokeTrail->SetLocalOrigin( vec3_origin ); - pSmokeTrail->SetMoveType( MOVETYPE_NONE ); - } - - m_nSmokeTrailCount++; -} - - -//----------------------------------------------------------------------------- -// Destroy all smoke trails -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::DestroySmokeTrails() -{ - for ( int i = m_nSmokeTrailCount; --i >= 0; ) - { - UTIL_Remove( m_hSmokeTrail[i] ); - m_hSmokeTrail[i] = NULL; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &vecChunkPos - -//----------------------------------------------------------------------------- -void Chopper_CreateChunk( CBaseEntity *pChopper, const Vector &vecChunkPos, const QAngle &vecChunkAngles, const char *pszChunkName, bool bSmall ) -{ - // Drop a flaming, smoking chunk. - CGib *pChunk = CREATE_ENTITY( CGib, "gib" ); - pChunk->Spawn( pszChunkName ); - pChunk->SetBloodColor( DONT_BLEED ); - - pChunk->SetAbsOrigin( vecChunkPos ); - pChunk->SetAbsAngles( vecChunkAngles ); - - pChunk->SetOwnerEntity( pChopper ); - - if ( bSmall ) - { - pChunk->m_lifeTime = random->RandomFloat( 0.5f, 1.0f ); - pChunk->SetSolidFlags( FSOLID_NOT_SOLID ); - pChunk->SetSolid( SOLID_BBOX ); - pChunk->AddEffects( EF_NODRAW ); - pChunk->SetGravity( UTIL_ScaleForGravity( 400 ) ); - } - else - { - pChunk->m_lifeTime = 5.0f; - } - - pChunk->SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - - // Set the velocity - Vector vecVelocity; - AngularImpulse angImpulse; - - QAngle angles; - angles.x = random->RandomFloat( -70, 20 ); - angles.y = random->RandomFloat( 0, 360 ); - angles.z = 0.0f; - AngleVectors( angles, &vecVelocity ); - - vecVelocity *= random->RandomFloat( 550, 800 ); - vecVelocity += pChopper->GetAbsVelocity(); - - angImpulse = RandomAngularImpulse( -180, 180 ); - - pChunk->SetAbsVelocity( vecVelocity ); - - if ( bSmall == false ) - { - IPhysicsObject *pPhysicsObject = pChunk->VPhysicsInitNormal( SOLID_VPHYSICS, pChunk->GetSolidFlags(), false ); - - if ( pPhysicsObject ) - { - pPhysicsObject->EnableMotion( true ); - pPhysicsObject->SetVelocity(&vecVelocity, &angImpulse ); - } - } - - CFireTrail *pFireTrail = CFireTrail::CreateFireTrail(); - - if ( pFireTrail == NULL ) - return; - - pFireTrail->FollowEntity( pChunk, "" ); - pFireTrail->SetParent( pChunk, 0 ); - pFireTrail->SetLocalOrigin( vec3_origin ); - pFireTrail->SetMoveType( MOVETYPE_NONE ); - pFireTrail->SetLifetime( pChunk->m_lifeTime ); -} - -//------------------------------------------------------------------------------ -// Pow! -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::ExplodeAndThrowChunk( const Vector &vecExplosionPos ) -{ - CEffectData data; - data.m_vOrigin = vecExplosionPos; - DispatchEffect( "HelicopterMegaBomb", data ); - - EmitSound( "BaseExplosionEffect.Sound" ); - - UTIL_ScreenShake( vecExplosionPos, 25.0, 150.0, 1.0, 750.0f, SHAKE_START ); - - if(GetCrashPoint() != NULL) - { - // Make it clear that I'm done for. - ExplosionCreate( vecExplosionPos, QAngle(0,0,1), this, 100, 128, false ); - } - - if ( random->RandomInt( 0, 4 ) ) - { - for ( int i = 0; i < 2; i++ ) - { - Chopper_CreateChunk( this, vecExplosionPos, RandomAngle(0, 360), g_PropDataSystem.GetRandomChunkModel( "MetalChunks" ), true ); - } - } - else - { - Chopper_CreateChunk( this, vecExplosionPos, RandomAngle(0, 360), s_pChunkModelName[random->RandomInt( 0, CHOPPER_MAX_SMALL_CHUNKS - 1 )], false ); - } -} - - -//----------------------------------------------------------------------------- -// Drop a corpse! -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::DropCorpse( int nDamage ) -{ - // Don't drop another corpse if the next guy's not out on the gun yet - if ( m_flLastCorpseFall > gpGlobals->curtime ) - return; - - // Clamp damage to prevent ridiculous ragdoll velocity - if( nDamage > 250.0f ) - nDamage = 250; - - m_flLastCorpseFall = gpGlobals->curtime + 3.0; - - // Spawn a ragdoll combine guard - float forceScale = nDamage * 75 * 4; - Vector vecForceVector = RandomVector(-1,1); - vecForceVector.z = 0.5; - vecForceVector *= forceScale; - - CBaseEntity *pGib = CreateRagGib( "models/combine_soldier.mdl", GetAbsOrigin(), GetAbsAngles(), vecForceVector ); - if ( pGib ) - { - pGib->SetOwnerEntity( this ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - // Take no damage from trace attacks unless it's blast damage. RadiusDamage() sometimes calls - // TraceAttack() as a means for delivering blast damage. Usually when the explosive penetrates - // the target. (RPG missiles do this sometimes). - if ( ( info.GetDamageType() & DMG_AIRBOAT ) || - ( info.GetInflictor()->Classify() == CLASS_MISSILE ) || - ( info.GetAttacker()->Classify() == CLASS_MISSILE ) ) - { - BaseClass::BaseClass::TraceAttack( info, vecDir, ptr ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_AttackHelicopter::OnTakeDamage( const CTakeDamageInfo &info ) -{ - // We don't take blast damage from anything but the airboat or missiles (or myself!) - if( info.GetInflictor() != this ) - { - if ( ( ( info.GetDamageType() & DMG_AIRBOAT ) == 0 ) && - ( info.GetInflictor()->Classify() != CLASS_MISSILE ) && - ( info.GetAttacker()->Classify() != CLASS_MISSILE ) ) - return 0; - } - - if ( m_bIndestructible ) - { - if ( GetHealth() < info.GetDamage() ) - return 0; - } - - // helicopter takes extra damage from its own grenades - CGrenadeHelicopter *pGren = dynamic_cast(info.GetInflictor()); - if ( pGren && info.GetAttacker() && info.GetAttacker()->IsPlayer() ) - { - CTakeDamageInfo fudgedInfo = info; - - float damage; - if( g_pGameRules->IsSkillLevel(SKILL_EASY) ) - { - damage = GetMaxHealth() / sk_helicopter_num_bombs1.GetFloat(); - } - else if( g_pGameRules->IsSkillLevel(SKILL_HARD) ) - { - damage = GetMaxHealth() / sk_helicopter_num_bombs3.GetFloat(); - } - else // Medium, or unspecified - { - damage = GetMaxHealth() / sk_helicopter_num_bombs2.GetFloat(); - } - damage = ceilf( damage ); - fudgedInfo.SetDamage( damage ); - fudgedInfo.SetMaxDamage( damage ); - - return BaseClass::OnTakeDamage( fudgedInfo ); - } - - return BaseClass::OnTakeDamage( info ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Take damage from trace attacks if they hit the gunner -//----------------------------------------------------------------------------- -int CNPC_AttackHelicopter::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - int nPrevHealth = GetHealth(); - - if ( ( info.GetInflictor() != NULL ) && ( info.GetInflictor()->GetOwnerEntity() != NULL ) && ( info.GetInflictor()->GetOwnerEntity() == this ) ) - { - // Don't take damage from my own bombs. (Unless the player grabbed them and threw them back) - return 0; - } - - // Chain - int nRetVal = BaseClass::OnTakeDamage_Alive( info ); - - if( info.GetDamageType() & DMG_BLAST ) - { - // Apply a force push that makes us look like we're reacting to the damage - Vector damageDir = info.GetDamageForce(); - VectorNormalize( damageDir ); - ApplyAbsVelocityImpulse( damageDir * 500.0f ); - - // Knock the helicopter off of the level, too. - Vector vecRight, vecForce; - float flDot; - GetVectors( NULL, &vecRight, NULL ); - vecForce = info.GetDamageForce(); - VectorNormalize( vecForce ); - - flDot = DotProduct( vecForce, vecRight ); - - m_flGoalRollDmg = random->RandomFloat( 10, 30 ); - - if( flDot <= 0.0f ) - { - // Missile hit the right side. - m_flGoalRollDmg *= -1; - } - } - - // Spawn damage effects - if ( nPrevHealth != GetHealth() ) - { - // Give the badly damaged call to say we're going to mega bomb soon - if ( m_nAttackMode == ATTACK_MODE_BULLRUSH_VEHICLE ) - { - if (( nPrevHealth > m_flNextMegaBombHealth ) && (GetHealth() <= m_flNextMegaBombHealth) ) - { - EmitSound( "NPC_AttackHelicopter.BadlyDamagedAlert" ); - } - } - - if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_SMOKE_TRAILS ) ) - { - AddSmokeTrail( info.GetDamagePosition() ); - } - - if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_CORPSES ) ) - { - if ( nPrevHealth != GetMaxHealth() ) - { - DropCorpse( (int)info.GetDamage() ); - } - } - - if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_EXPLOSIONS ) ) - { - ExplodeAndThrowChunk( info.GetDamagePosition() ); - } - - int nPrevPercent = (int)(100.0f * nPrevHealth / GetMaxHealth()); - int nCurrPercent = (int)(100.0f * GetHealth() / GetMaxHealth()); - if (( (nPrevPercent + 9) / 10 ) != ( (nCurrPercent + 9) / 10 )) - { - m_OnHealthChanged.Set( nCurrPercent, this, this ); - } - } - - return nRetVal; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Chopper_BecomeChunks( CBaseEntity *pChopper ) -{ - QAngle vecChunkAngles = pChopper->GetAbsAngles(); - Vector vecForward, vecUp; - pChopper->GetVectors( &vecForward, NULL, &vecUp ); - -#ifdef HL2_EPISODIC - CNPC_AttackHelicopter *pAttackHelicopter; - pAttackHelicopter = dynamic_cast(pChopper); - if( pAttackHelicopter != NULL ) - { - // New for EP2, we may be tailspinning, (crashing) and playing an animation that is spinning - // our root bone, which means our model is not facing the way our entity is facing. So we have - // to do some attachment point math to get the proper angles to use for computing the relative - // positions of the gibs. The attachment points called DAMAGE0 is properly oriented and attached - // to the chopper body so we can use its angles. - int iAttach = pAttackHelicopter->LookupAttachment( "damage0" ); - Vector vecAttachPos; - - if( iAttach > -1 ) - { - pAttackHelicopter->GetAttachment(iAttach, vecAttachPos, vecChunkAngles ); - AngleVectors( vecChunkAngles, &vecForward, NULL, &vecUp ); - } - } -#endif//HL2_EPISODIC - - - Vector vecChunkPos = pChopper->GetAbsOrigin(); - - Vector vecRight(0,0,0); - - if( hl2_episodic.GetBool() ) - { - // We need to get a right hand vector to toss the cockpit and tail pieces - // so their motion looks like a continuation of the tailspin animation - // that the chopper plays before crashing. - pChopper->GetVectors( NULL, &vecRight, NULL ); - } - - // Body - CHelicopterChunk *pBodyChunk = CHelicopterChunk::CreateHelicopterChunk( vecChunkPos, vecChunkAngles, pChopper->GetAbsVelocity(), HELICOPTER_CHUNK_BODY, CHUNK_BODY ); - Chopper_CreateChunk( pChopper, vecChunkPos, RandomAngle( 0, 360 ), s_pChunkModelName[random->RandomInt( 0, CHOPPER_MAX_CHUNKS - 1 )], false ); - - vecChunkPos = pChopper->GetAbsOrigin() + ( vecForward * 100.0f ) + ( vecUp * -38.0f ); - - // Cockpit - CHelicopterChunk *pCockpitChunk = CHelicopterChunk::CreateHelicopterChunk( vecChunkPos, vecChunkAngles, pChopper->GetAbsVelocity() + vecRight * -800.0f, HELICOPTER_CHUNK_COCKPIT, CHUNK_COCKPIT ); - Chopper_CreateChunk( pChopper, vecChunkPos, RandomAngle( 0, 360 ), s_pChunkModelName[random->RandomInt( 0, CHOPPER_MAX_CHUNKS - 1 )], false ); - - pCockpitChunk->m_hMaster = pBodyChunk; - - vecChunkPos = pChopper->GetAbsOrigin() + ( vecForward * -175.0f ); - - // Tail - CHelicopterChunk *pTailChunk = CHelicopterChunk::CreateHelicopterChunk( vecChunkPos, vecChunkAngles, pChopper->GetAbsVelocity() + vecRight * 800.0f, HELICOPTER_CHUNK_TAIL, CHUNK_TAIL ); - Chopper_CreateChunk( pChopper, vecChunkPos, RandomAngle( 0, 360 ), s_pChunkModelName[random->RandomInt( 0, CHOPPER_MAX_CHUNKS - 1 )], false ); - - pTailChunk->m_hMaster = pBodyChunk; - - // Constrain all the pieces together loosely - IPhysicsObject *pBodyObject = pBodyChunk->VPhysicsGetObject(); - Assert( pBodyObject ); - - IPhysicsObject *pCockpitObject = pCockpitChunk->VPhysicsGetObject(); - Assert( pCockpitObject ); - - IPhysicsObject *pTailObject = pTailChunk->VPhysicsGetObject(); - Assert( pTailObject ); - - IPhysicsConstraintGroup *pGroup = NULL; - - // Create the constraint - constraint_fixedparams_t fixed; - fixed.Defaults(); - fixed.InitWithCurrentObjectState( pBodyObject, pTailObject ); - fixed.constraint.Defaults(); - - pBodyChunk->m_pTailConstraint = physenv->CreateFixedConstraint( pBodyObject, pTailObject, pGroup, fixed ); - - fixed.Defaults(); - fixed.InitWithCurrentObjectState( pBodyObject, pCockpitObject ); - fixed.constraint.Defaults(); - - pBodyChunk->m_pCockpitConstraint = physenv->CreateFixedConstraint( pBodyObject, pCockpitObject, pGroup, fixed ); -} - -//----------------------------------------------------------------------------- -// Purpose: Start us crashing -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::Event_Killed( const CTakeDamageInfo &info ) -{ - if( m_lifeState == LIFE_ALIVE ) - { - m_OnShotDown.FireOutput( this, this ); - } - - m_lifeState = LIFE_DYING; - - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundChangeVolume( m_pGunFiringSound, 0.0, 0.1f ); - - if( GetCrashPoint() == NULL ) - { - CBaseEntity *pCrashPoint = gEntList.FindEntityByClassname( NULL, "info_target_helicopter_crash" ); - if( pCrashPoint != NULL ) - { - m_hCrashPoint.Set( pCrashPoint ); - SetDesiredPosition( pCrashPoint->GetAbsOrigin() ); - - // Start the failing engine sound - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundDestroy( m_pRotorSound ); - - CPASAttenuationFilter filter( this ); - m_pRotorSound = controller.SoundCreate( filter, entindex(), "NPC_AttackHelicopter.EngineFailure" ); - controller.Play( m_pRotorSound, 1.0, 100 ); - - // Tailspin!! - SetActivity( ACT_HELICOPTER_CRASHING ); - - // Intentionally returning with m_lifeState set to LIFE_DYING - return; - } - } - - Chopper_BecomeChunks( this ); - StopLoopingSounds(); - - m_lifeState = LIFE_DEAD; - - EmitSound( "NPC_CombineGunship.Explode" ); - - SetThink( &CNPC_AttackHelicopter::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - AddEffects( EF_NODRAW ); - - // Makes the slower rotors fade back in - SetStartupTime( gpGlobals->curtime + 99.0f ); - - m_iHealth = 0; - m_takedamage = DAMAGE_NO; - - m_OnDeath.FireOutput( info.GetAttacker(), this ); -} - -//------------------------------------------------------------------------------ -// Creates the breakable husk of an attack chopper -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::CreateChopperHusk() -{ - // We're embedded into the ground - CBaseEntity *pCorpse = CreateEntityByName( "prop_physics" ); - pCorpse->SetAbsOrigin( GetAbsOrigin() ); - pCorpse->SetAbsAngles( GetAbsAngles() ); - pCorpse->SetModel( CHOPPER_MODEL_CORPSE_NAME ); - pCorpse->AddSpawnFlags( SF_PHYSPROP_MOTIONDISABLED ); - pCorpse->Spawn(); - pCorpse->SetMoveType( MOVETYPE_NONE ); -} - -//----------------------------------------------------------------------------- -// Think! -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::PrescheduleThink( void ) -{ - if ( m_flGoalRollDmg != 0.0f ) - { - m_flGoalRollDmg = UTIL_Approach( 0, m_flGoalRollDmg, 2.0f ); - } - - switch( m_lifeState ) - { - case LIFE_DYING: - { - if( GetCrashPoint() != NULL ) - { - // Stay on this, no matter what. - SetDesiredPosition( GetCrashPoint()->WorldSpaceCenter() ); - } - - if ( random->RandomInt( 0, 4 ) == 0 ) - { - Vector explodePoint; - CollisionProp()->RandomPointInBounds( Vector(0.25,0.25,0.25), Vector(0.75,0.75,0.75), &explodePoint ); - - ExplodeAndThrowChunk( explodePoint ); - } - } - break; - } - - BaseClass::PrescheduleThink(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CNPC_AttackHelicopter::UpdatePerpPathDistance( float flMaxPathOffset ) -{ - if ( !IsLeading() || !GetEnemy() ) - { - m_flCurrPathOffset = 0.0f; - return 0.0f; - } - - float flNewPathOffset = TargetDistanceToPath(); - - // Make bomb dropping more interesting - if ( ShouldDropBombs() ) - { - float flSpeedAlongPath = TargetSpeedAlongPath(); - - if ( flSpeedAlongPath > 10.0f ) - { - float flLeadTime = GetLeadingDistance() / flSpeedAlongPath; - flLeadTime = clamp( flLeadTime, 0.0f, 2.0f ); - flNewPathOffset += 0.25 * flLeadTime * TargetSpeedAcrossPath(); - } - - flSpeedAlongPath = clamp( flSpeedAlongPath, 100.0f, 500.0f ); - float flSinHeight = SimpleSplineRemapVal( flSpeedAlongPath, 100.0f, 500.0f, 0.0f, 200.0f ); - flNewPathOffset += flSinHeight * sin( 2.0f * M_PI * (gpGlobals->curtime / 6.0f) ); - } - - if ( (flMaxPathOffset != 0.0f) && (flNewPathOffset > flMaxPathOffset) ) - { - flNewPathOffset = flMaxPathOffset; - } - - float flMaxChange = 1000.0f * (gpGlobals->curtime - GetLastThink()); - if ( fabs( flNewPathOffset - m_flCurrPathOffset ) < flMaxChange ) - { - m_flCurrPathOffset = flNewPathOffset; - } - else - { - float flSign = (m_flCurrPathOffset < flNewPathOffset) ? 1.0f : -1.0f; - m_flCurrPathOffset += flSign * flMaxChange; - } - - return m_flCurrPathOffset; -} - - -//----------------------------------------------------------------------------- -// Computes the max speed + acceleration: -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::GetMaxSpeedAndAccel( float *pMaxSpeed, float *pAccelRate ) -{ - *pAccelRate = CHOPPER_ACCEL_RATE; - *pMaxSpeed = GetMaxSpeed(); - if ( GetEnemyVehicle() ) - { - *pAccelRate *= 9.0f; - } -} - - -//----------------------------------------------------------------------------- -// Computes the acceleration: -//----------------------------------------------------------------------------- -#define HELICOPTER_GRAVITY 384 -#define HELICOPTER_DT 0.1f -#define HELICOPTER_MIN_DZ_DAMP -500.0f -#define HELICOPTER_MAX_DZ_DAMP -1000.0f -#define HELICOPTER_FORCE_BLEND 0.8f -#define HELICOPTER_FORCE_BLEND_VEHICLE 0.2f - -void CNPC_AttackHelicopter::ComputeVelocity( const Vector &vecTargetPosition, - float flAdditionalHeight, float flMinDistFromSegment, float flMaxDistFromSegment, Vector *pVecAccel ) -{ - Vector deltaPos; - VectorSubtract( vecTargetPosition, GetAbsOrigin(), deltaPos ); - - // calc goal linear accel to hit deltaPos in dt time. - // This is solving the equation xf = 0.5 * a * dt^2 + vo * dt + xo - float dt = 1.0f; - pVecAccel->x = 2.0f * (deltaPos.x - GetAbsVelocity().x * dt) / (dt * dt); - pVecAccel->y = 2.0f * (deltaPos.y - GetAbsVelocity().y * dt) / (dt * dt); - pVecAccel->z = 2.0f * (deltaPos.z - GetAbsVelocity().z * dt) / (dt * dt) + HELICOPTER_GRAVITY; - - float flDistFromPath = 0.0f; - Vector vecPoint, vecDelta; - if ( flMaxDistFromSegment != 0.0f ) - { - // Also, add in a little force to get us closer to our current line segment if we can - ClosestPointToCurrentPath( &vecPoint ); - - if ( flAdditionalHeight != 0.0f ) - { - Vector vecEndPoint, vecClosest; - vecEndPoint = vecPoint; - vecEndPoint.z += flAdditionalHeight; - CalcClosestPointOnLineSegment( GetAbsOrigin(), vecPoint, vecEndPoint, vecClosest ); - vecPoint = vecClosest; - } - - VectorSubtract( vecPoint, GetAbsOrigin(), vecDelta ); - flDistFromPath = VectorNormalize( vecDelta ); - if ( flDistFromPath > flMaxDistFromSegment ) - { - // Strongly constrain to an n unit pipe around the current path - // by damping out all impulse forces that would push us further from the pipe - float flAmount = (flDistFromPath - flMaxDistFromSegment) / 200.0f; - flAmount = clamp( flAmount, 0, 1 ); - VectorMA( *pVecAccel, flAmount * 200.0f, vecDelta, *pVecAccel ); - } - } - - // Apply avoidance forces - if ( !HasSpawnFlags( SF_HELICOPTER_IGNORE_AVOID_FORCES ) ) - { - Vector vecAvoidForce; - CAvoidSphere::ComputeAvoidanceForces( this, 350.0f, 2.0f, &vecAvoidForce ); - *pVecAccel += vecAvoidForce; - CAvoidBox::ComputeAvoidanceForces( this, 350.0f, 2.0f, &vecAvoidForce ); - *pVecAccel += vecAvoidForce; - } - - // don't fall faster than 0.2G or climb faster than 2G - pVecAccel->z = clamp( pVecAccel->z, HELICOPTER_GRAVITY * 0.2f, HELICOPTER_GRAVITY * 2.0f ); - - // The lift factor owing to horizontal movement - float flHorizLiftFactor = fabs( pVecAccel->x ) * 0.10f + fabs( pVecAccel->y ) * 0.10f; - - // If we're way above the path, dampen horizontal lift factor - float flNewHorizLiftFactor = clamp( deltaPos.z, HELICOPTER_MAX_DZ_DAMP, HELICOPTER_MIN_DZ_DAMP ); - flNewHorizLiftFactor = SimpleSplineRemapVal( flNewHorizLiftFactor, HELICOPTER_MIN_DZ_DAMP, HELICOPTER_MAX_DZ_DAMP, flHorizLiftFactor, 2.5f * (HELICOPTER_GRAVITY * 0.2) ); - float flDampening = (flNewHorizLiftFactor != 0.0f) ? (flNewHorizLiftFactor / flHorizLiftFactor) : 1.0f; - if ( flDampening < 1.0f ) - { - pVecAccel->x *= flDampening; - pVecAccel->y *= flDampening; - flHorizLiftFactor = flNewHorizLiftFactor; - } - - Vector forward, right, up; - GetVectors( &forward, &right, &up ); - - // First, attenuate the current force - float flForceBlend = GetEnemyVehicle() ? HELICOPTER_FORCE_BLEND_VEHICLE : HELICOPTER_FORCE_BLEND; - m_flForce *= flForceBlend; - - // Now add force based on our acceleration factors - m_flForce += ( pVecAccel->z + flHorizLiftFactor ) * HELICOPTER_DT * (1.0f - flForceBlend); - - // The force is always *locally* upward based; we pitch + roll the chopper to get movement - Vector vecImpulse; - VectorMultiply( up, m_flForce, vecImpulse ); - - // NOTE: These have to be done *before* the additional path distance drag forces are applied below - ApplySidewaysDrag( right ); - ApplyGeneralDrag(); - - // If LIFE_DYING, maintain control as long as we're flying to a crash point. - if ( m_lifeState != LIFE_DYING || (m_lifeState == LIFE_DYING && GetCrashPoint() != NULL) ) - { - vecImpulse.z += -HELICOPTER_GRAVITY * HELICOPTER_DT; - - if ( flMinDistFromSegment != 0.0f && ( flDistFromPath > flMinDistFromSegment ) ) - { - Vector vecVelDir = GetAbsVelocity(); - - // Strongly constrain to an n unit pipe around the current path - // by damping out all impulse forces that would push us further from the pipe - float flDot = DotProduct( vecImpulse, vecDelta ); - if ( flDot < 0.0f ) - { - VectorMA( vecImpulse, -flDot * 0.1f, vecDelta, vecImpulse ); - } - - // Also apply an extra impulse to compensate for the current velocity - flDot = DotProduct( vecVelDir, vecDelta ); - if ( flDot < 0.0f ) - { - VectorMA( vecImpulse, -flDot * 0.1f, vecDelta, vecImpulse ); - } - } - } - else - { - // No more upward lift... - vecImpulse.z = -HELICOPTER_GRAVITY * HELICOPTER_DT; - - // Damp the horizontal impulses; we should pretty much be falling ballistically - vecImpulse.x *= 0.1f; - vecImpulse.y *= 0.1f; - } - - // Add in our velocity pulse for this frame - ApplyAbsVelocityImpulse( vecImpulse ); -} - - - -//----------------------------------------------------------------------------- -// Computes the max speed + acceleration: -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::ComputeAngularVelocity( const Vector &vecGoalUp, const Vector &vecFacingDirection ) -{ - QAngle goalAngAccel; - if ( m_lifeState != LIFE_DYING || (m_lifeState == LIFE_DYING && GetCrashPoint() != NULL) ) - { - Vector forward, right, up; - GetVectors( &forward, &right, &up ); - - Vector goalUp = vecGoalUp; - VectorNormalize( goalUp ); - - // calc goal orientation to hit linear accel forces - float goalPitch = RAD2DEG( asin( DotProduct( forward, goalUp ) ) ); - float goalYaw = UTIL_VecToYaw( vecFacingDirection ); - float goalRoll = RAD2DEG( asin( DotProduct( right, goalUp ) ) + m_flGoalRollDmg ); - goalPitch *= 0.75f; - - // clamp goal orientations - goalPitch = clamp( goalPitch, -30, 45 ); - goalRoll = clamp( goalRoll, -45, 45 ); - - // calc angular accel needed to hit goal pitch in dt time. - float dt = 0.6; - goalAngAccel.x = 2.0 * (AngleDiff( goalPitch, AngleNormalize( GetAbsAngles().x ) ) - GetLocalAngularVelocity().x * dt) / (dt * dt); - goalAngAccel.y = 2.0 * (AngleDiff( goalYaw, AngleNormalize( GetAbsAngles().y ) ) - GetLocalAngularVelocity().y * dt) / (dt * dt); - goalAngAccel.z = 2.0 * (AngleDiff( goalRoll, AngleNormalize( GetAbsAngles().z ) ) - GetLocalAngularVelocity().z * dt) / (dt * dt); - - goalAngAccel.x = clamp( goalAngAccel.x, -300, 300 ); - //goalAngAccel.y = clamp( goalAngAccel.y, -60, 60 ); - goalAngAccel.y = clamp( goalAngAccel.y, -120, 120 ); - goalAngAccel.z = clamp( goalAngAccel.z, -300, 300 ); - } - else - { - goalAngAccel.x = 0; - goalAngAccel.y = random->RandomFloat( 50, 120 ); - goalAngAccel.z = 0; - } - - // limit angular accel changes to similate mechanical response times - QAngle angAccelAccel; - float dt = 0.1; - angAccelAccel.x = (goalAngAccel.x - m_vecAngAcceleration.x) / dt; - angAccelAccel.y = (goalAngAccel.y - m_vecAngAcceleration.y) / dt; - angAccelAccel.z = (goalAngAccel.z - m_vecAngAcceleration.z) / dt; - - angAccelAccel.x = clamp( angAccelAccel.x, -1000, 1000 ); - angAccelAccel.y = clamp( angAccelAccel.y, -1000, 1000 ); - angAccelAccel.z = clamp( angAccelAccel.z, -1000, 1000 ); - - // DevMsg( "pitch %6.1f (%6.1f:%6.1f) ", goalPitch, GetLocalAngles().x, m_vecAngVelocity.x ); - // DevMsg( "roll %6.1f (%6.1f:%6.1f) : ", goalRoll, GetLocalAngles().z, m_vecAngVelocity.z ); - // DevMsg( "%6.1f %6.1f %6.1f : ", goalAngAccel.x, goalAngAccel.y, goalAngAccel.z ); - // DevMsg( "%6.0f %6.0f %6.0f\n", angAccelAccel.x, angAccelAccel.y, angAccelAccel.z ); - - m_vecAngAcceleration += angAccelAccel * 0.1; - - QAngle angVel = GetLocalAngularVelocity(); - angVel += m_vecAngAcceleration * 0.1; - angVel.y = clamp( angVel.y, -120, 120 ); - - // Fix up pitch and yaw to tend toward small values - if ( m_lifeState == LIFE_DYING && GetCrashPoint() == NULL ) - { - float flPitchDiff = random->RandomFloat( -5, 5 ) - GetAbsAngles().x; - angVel.x = flPitchDiff * 0.1f; - float flRollDiff = random->RandomFloat( -5, 5 ) - GetAbsAngles().z; - angVel.z = flRollDiff * 0.1f; - } - - SetLocalAngularVelocity( angVel ); - - float flAmt = clamp( angVel.y, -30, 30 ); - float flRudderPose = RemapVal( flAmt, -30, 30, 45, -45 ); - SetPoseParameter( "rudder", flRudderPose ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::FlightDirectlyOverhead( void ) -{ - Vector vecTargetPosition = m_vecTargetPosition; - CBaseEntity *pEnemy = GetEnemy(); - if ( HasEnemy() && FVisible( pEnemy ) ) - { - if ( GetEnemy()->IsPlayer() ) - { - CBaseEntity *pEnemyVehicle = assert_cast(GetEnemy())->GetVehicleEntity(); - if ( pEnemyVehicle ) - { - Vector vecEnemyVel = pEnemyVehicle->GetSmoothedVelocity(); - Vector vecRelativePosition; - VectorSubtract( GetAbsOrigin(), pEnemyVehicle->GetAbsOrigin(), vecRelativePosition ); - float flDist = VectorNormalize( vecRelativePosition ); - float flEnemySpeed = VectorNormalize( vecEnemyVel ); - float flDot = DotProduct( vecRelativePosition, vecEnemyVel ); - float flSpeed = GetMaxSpeed() * 0.3f; //GetAbsVelocity().Length(); - - float a = flSpeed * flSpeed - flEnemySpeed * flEnemySpeed; - float b = 2.0f * flEnemySpeed * flDist * flDot; - float c = - flDist * flDist; - - float flDiscrim = b * b - 4 * a * c; - if ( flDiscrim >= 0 ) - { - float t = ( -b + sqrt( flDiscrim ) ) / (2 * a); - t = clamp( t, 0.0f, 4.0f ); - VectorMA( pEnemyVehicle->GetAbsOrigin(), t * flEnemySpeed, vecEnemyVel, vecTargetPosition ); - } - } - } - } - -// if ( GetCurrentPathTargetPosition() ) -// { -// vecTargetPosition.z = GetCurrentPathTargetPosition()->z; -// } - - NDebugOverlay::Cross3D( vecTargetPosition, -Vector(32,32,32), Vector(32,32,32), 0, 0, 255, true, 0.1f ); - - UpdateFacingDirection( vecTargetPosition ); - - Vector accel; - ComputeVelocity( vecTargetPosition, 0.0f, 0.0f, 0.0f, &accel ); - ComputeAngularVelocity( accel, m_vecDesiredFaceDir ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::Flight( void ) -{ - if( GetFlags() & FL_ONGROUND ) - { - // This would be really bad. - SetGroundEntity( NULL ); - } - - // Determine the distances we must lie from the path - float flMaxPathOffset = MaxDistanceFromCurrentPath(); - float flPerpDist = UpdatePerpPathDistance( flMaxPathOffset ); - - float flMinDistFromSegment, flMaxDistFromSegment; - if ( !IsLeading() ) - { - flMinDistFromSegment = 0.0f; - flMaxDistFromSegment = 0.0f; - } - else - { - flMinDistFromSegment = fabs(flPerpDist) + 100.0f; - flMaxDistFromSegment = fabs(flPerpDist) + 200.0f; - if ( flMaxPathOffset != 0.0 ) - { - if ( flMaxDistFromSegment > flMaxPathOffset - 100.0f ) - { - flMaxDistFromSegment = flMaxPathOffset - 100.0f; - } - - if ( flMinDistFromSegment > flMaxPathOffset - 200.0f ) - { - flMinDistFromSegment = flMaxPathOffset - 200.0f; - } - } - } - - float maxSpeed, accelRate; - GetMaxSpeedAndAccel( &maxSpeed, &accelRate ); - - Vector vecTargetPosition; - float flCurrentSpeed = GetAbsVelocity().Length(); - float flDist = MIN( flCurrentSpeed + accelRate, maxSpeed ); - float dt = 1.0f; - ComputeActualTargetPosition( flDist, dt, flPerpDist, &vecTargetPosition ); - - // Raise high in the air when doing the shooting attack - float flAdditionalHeight = 0.0f; - if ( m_nAttackMode == ATTACK_MODE_BULLRUSH_VEHICLE ) - { - flAdditionalHeight = clamp( m_flBullrushAdditionalHeight, 0.0f, flMaxPathOffset ); - vecTargetPosition.z += flAdditionalHeight; - } - - Vector accel; - UpdateFacingDirection( vecTargetPosition ); - ComputeVelocity( vecTargetPosition, flAdditionalHeight, flMinDistFromSegment, flMaxDistFromSegment, &accel ); - ComputeAngularVelocity( accel, m_vecDesiredFaceDir ); -} - - -//------------------------------------------------------------------------------ -// Updates the facing direction -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::UpdateFacingDirection( const Vector &vecActualDesiredPosition ) -{ - bool bIsBullrushing = ( m_nAttackMode == ATTACK_MODE_BULLRUSH_VEHICLE ); - - bool bSeenTargetRecently = HasSpawnFlags( SF_HELICOPTER_AGGRESSIVE ) || ( m_flLastSeen + 5 > gpGlobals->curtime ); - if ( GetEnemy() && !bIsBullrushing ) - { - if ( !IsLeading() ) - { - if( IsCarpetBombing() && hl2_episodic.GetBool() ) - { - m_vecDesiredFaceDir = vecActualDesiredPosition - GetAbsOrigin(); - } - else if ( !IsCrashing() && bSeenTargetRecently ) - { - // If we've seen the target recently, face the target. - m_vecDesiredFaceDir = m_vecTargetPosition - GetAbsOrigin(); - } - else - { - // Remain facing the way you were facing... - } - } - else - { - if ( ShouldDropBombs() || IsCarpetBombing() ) - { - m_vecDesiredFaceDir = vecActualDesiredPosition - GetAbsOrigin(); - } - else - { - m_vecDesiredFaceDir = m_vecTargetPosition - GetAbsOrigin(); - } - } - } - else - { - // Face our desired position - float flDistSqr = vecActualDesiredPosition.AsVector2D().DistToSqr( GetAbsOrigin().AsVector2D() ); - if ( flDistSqr <= 50 * 50 ) - { - if (( flDistSqr > 1 * 1 ) && bSeenTargetRecently && IsInSecondaryMode( BULLRUSH_MODE_SHOOT_IDLE_PLAYER ) ) - { - m_vecDesiredFaceDir = m_vecTargetPosition - GetAbsOrigin(); - m_vecDesiredFaceDir.z = 0.0f; - } - else - { - GetVectors( &m_vecDesiredFaceDir, NULL, NULL ); - } - } - else - { - m_vecDesiredFaceDir = vecActualDesiredPosition - GetAbsOrigin(); - } - } - VectorNormalize( m_vecDesiredFaceDir ); -} - - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -#define ENEMY_CREEP_RATE 400 -float CNPC_AttackHelicopter::CreepTowardEnemy( float flSpeed, float flMinSpeed, float flMaxSpeed, float flMinDist, float flMaxDist ) -{ - float dt = gpGlobals->curtime - GetLastThink(); - float flEnemyCreepDist = ENEMY_CREEP_RATE * dt; - - // When the player is slow, creep toward him within a second or two - float flLeadingDist = ClampSplineRemapVal( flSpeed, flMinSpeed, flMaxSpeed, flMinDist, flMaxDist ); - float flCurrentDist = GetLeadingDistance( ); - if ( fabs(flLeadingDist - flCurrentDist) > flEnemyCreepDist ) - { - float flSign = ( flLeadingDist < flCurrentDist ) ? -1.0f : 1.0f; - flLeadingDist = flCurrentDist + flSign * flEnemyCreepDist; - } - - return flLeadingDist; -} - - -#define MIN_ENEMY_SPEED 300 - - -//------------------------------------------------------------------------------ -// Computes how far to lead the player when bombing -//------------------------------------------------------------------------------ -float CNPC_AttackHelicopter::ComputeBombingLeadingDistance( float flSpeed, float flSpeedAlongPath, bool bEnemyInVehicle ) -{ - if ( ( flSpeed <= MIN_ENEMY_SPEED ) && bEnemyInVehicle ) - { - return CreepTowardEnemy( flSpeed, 0.0f, MIN_ENEMY_SPEED, 0.0f, 1000.0f ); - } - - return ClampSplineRemapVal( flSpeedAlongPath, 200.0f, 600.0f, 1000.0f, 2000.0f ); -} - - -//------------------------------------------------------------------------------ -// Computes how far to lead the player when bullrushing -//------------------------------------------------------------------------------ -float CNPC_AttackHelicopter::ComputeBullrushLeadingDistance( float flSpeed, float flSpeedAlongPath, bool bEnemyInVehicle ) -{ - switch ( m_nSecondaryMode ) - { - case BULLRUSH_MODE_WAIT_FOR_ENEMY: - return 0.0f; - - case BULLRUSH_MODE_GET_DISTANCE: - return m_bRushForward ? -CHOPPER_BULLRUSH_MODE_DISTANCE : CHOPPER_BULLRUSH_MODE_DISTANCE; - - case BULLRUSH_MODE_DROP_BOMBS_FOLLOW_PLAYER: -// return m_bRushForward ? 1500.0f : -1500.0f; - return ComputeBombingLeadingDistance( flSpeed, flSpeedAlongPath, bEnemyInVehicle ); - - case BULLRUSH_MODE_SHOOT_IDLE_PLAYER: - return 0.0f; - - case BULLRUSH_MODE_DROP_BOMBS_FIXED_SPEED: - return m_bRushForward ? 7000 : -7000; - - case BULLRUSH_MODE_MEGA_BOMB: - return m_bRushForward ? CHOPPER_BULLRUSH_MODE_DISTANCE : -CHOPPER_BULLRUSH_MODE_DISTANCE; - - case BULLRUSH_MODE_SHOOT_GUN: - { - float flLeadDistance = 1000.f - CHOPPER_BULLRUSH_ENEMY_BOMB_DISTANCE; - return m_bRushForward ? flLeadDistance : -flLeadDistance; - } - } - - Assert(0); - return 0.0f; -} - - -//------------------------------------------------------------------------------ -// Secondary mode -//------------------------------------------------------------------------------ -inline void CNPC_AttackHelicopter::SetSecondaryMode( int nMode, bool bRetainTime ) -{ - m_nSecondaryMode = nMode; - if (!bRetainTime) - { - m_flSecondaryModeStartTime = gpGlobals->curtime; - } -} - -inline bool CNPC_AttackHelicopter::IsInSecondaryMode( int nMode ) -{ - return m_nSecondaryMode == nMode; -} - -inline float CNPC_AttackHelicopter::SecondaryModeTime( ) const -{ - return gpGlobals->curtime - m_flSecondaryModeStartTime; -} - - -//------------------------------------------------------------------------------ -// Switch to idle -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::SwitchToBullrushIdle( void ) -{ - // Put us directly into idle gun state (we're in firing state) - m_flNextAttack = gpGlobals->curtime; - m_nGunState = GUN_STATE_IDLE; - m_nRemainingBursts = 0; - m_flBullrushAdditionalHeight = 0.0f; - SetPauseState( PAUSE_NO_PAUSE ); - - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundChangeVolume( m_pGunFiringSound, 0.0, 0.1f ); -} - - -//------------------------------------------------------------------------------ -// Should the chopper shoot the idle player? -//------------------------------------------------------------------------------ -bool CNPC_AttackHelicopter::ShouldShootIdlePlayerInBullrush() -{ - // Once he starts shooting, then don't stop until the player is moving pretty fast - float flSpeedSqr = IsInSecondaryMode( BULLRUSH_MODE_SHOOT_IDLE_PLAYER ) ? CHOPPER_BULLRUSH_SLOW_SHOOT_SPEED_2_SQ : CHOPPER_BULLRUSH_SLOW_SHOOT_SPEED_SQ; - return ( GetEnemy() && GetEnemy()->GetSmoothedVelocity().LengthSqr() <= flSpeedSqr ); -} - - -//------------------------------------------------------------------------------ -// Shutdown shooting during bullrush -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::ShutdownGunDuringBullrush( ) -{ - // Put us directly into idle gun state (we're in firing state) - m_flNextAttack = gpGlobals->curtime; - m_nGunState = GUN_STATE_IDLE; - m_nRemainingBursts = 0; - SetPauseState( PAUSE_NO_PAUSE ); - - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundChangeVolume( m_pGunFiringSound, 0.0, 0.1f ); -} - -#define HELICOPTER_MIN_IDLE_BOMBING_DIST 350.0f -#define HELICOPTER_MIN_IDLE_BOMBING_SPEED 350.0f - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_AttackHelicopter::ShouldBombIdlePlayer( void ) -{ - // Must be settled over a position and not moving too quickly to do this - if ( GetAbsVelocity().LengthSqr() > Square(HELICOPTER_MIN_IDLE_BOMBING_SPEED) ) - return false; - - // Must be within a certain range of the target - float flDistToTargetSqr = (GetEnemy()->WorldSpaceCenter() - GetAbsOrigin()).Length2DSqr(); - - if ( flDistToTargetSqr < Square(HELICOPTER_MIN_IDLE_BOMBING_DIST) ) - return true; - - // Can't bomb this - return false; -} - -//------------------------------------------------------------------------------ -// Update the bullrush state -//------------------------------------------------------------------------------ -#define BULLRUSH_GOAL_TOLERANCE 200 -#define BULLRUSH_BOMB_MAX_DISTANCE 3500 - -void CNPC_AttackHelicopter::UpdateBullrushState( void ) -{ - if ( !GetEnemy() || IsInForcedMove() ) - { - if ( !IsInSecondaryMode( BULLRUSH_MODE_WAIT_FOR_ENEMY ) ) - { - SwitchToBullrushIdle(); - SetSecondaryMode( BULLRUSH_MODE_WAIT_FOR_ENEMY ); - } - } - - switch( m_nSecondaryMode ) - { - case BULLRUSH_MODE_WAIT_FOR_ENEMY: - { - m_flBullrushAdditionalHeight = CHOPPER_BULLRUSH_SHOOTING_VERTICAL_OFFSET; - if ( GetEnemy() && !IsInForcedMove() ) - { - // This forces us to not start trying checking positions - // until we have been on the path for a little while - if ( SecondaryModeTime() > 0.3f ) - { - float flDistanceToGoal = ComputeDistanceToTargetPosition(); - Vector vecPathDir; - CurrentPathDirection( &vecPathDir ); - bool bMovingForward = DotProduct2D( GetAbsVelocity().AsVector2D(), vecPathDir.AsVector2D() ) >= 0.0f; - if ( flDistanceToGoal * (bMovingForward ? 1.0f : -1.0f) > 1000 ) - { - m_bRushForward = bMovingForward; - SetSecondaryMode( BULLRUSH_MODE_SHOOT_GUN ); - SpotlightStartup(); - } - else - { - m_bRushForward = !bMovingForward; - SetSecondaryMode( BULLRUSH_MODE_GET_DISTANCE ); - } - } - } - else - { - m_flSecondaryModeStartTime = gpGlobals->curtime; - } - } - break; - - case BULLRUSH_MODE_GET_DISTANCE: - { - m_flBullrushAdditionalHeight = CHOPPER_BULLRUSH_SHOOTING_VERTICAL_OFFSET; - - float flDistanceToGoal = ComputeDistanceToTargetPosition(); - if ( m_bRushForward ) - { - if ( flDistanceToGoal < (CHOPPER_BULLRUSH_MODE_DISTANCE - 1000) ) - break; - } - else - { - if ( flDistanceToGoal > -(CHOPPER_BULLRUSH_MODE_DISTANCE - 1000) ) - break; - } - - if ( GetHealth() <= m_flNextMegaBombHealth ) - { - m_flNextMegaBombHealth -= GetMaxHealth() * g_helicopter_bullrush_mega_bomb_health.GetFloat(); - m_flNextBullrushBombTime = gpGlobals->curtime; - SetSecondaryMode( BULLRUSH_MODE_MEGA_BOMB ); - EmitSound( "NPC_AttackHelicopter.MegabombAlert" ); - } - else - { - SetSecondaryMode( BULLRUSH_MODE_SHOOT_GUN ); - SpotlightStartup(); - } - } - break; - - case BULLRUSH_MODE_MEGA_BOMB: - { - m_flBullrushAdditionalHeight = CHOPPER_BULLRUSH_SHOOTING_VERTICAL_OFFSET; - - float flDistanceToGoal = ComputeDistanceToTargetPosition(); - if ( m_bRushForward ) - { - if ( flDistanceToGoal > -(CHOPPER_BULLRUSH_MODE_DISTANCE - 1000) ) - break; - } - else - { - if ( flDistanceToGoal < (CHOPPER_BULLRUSH_MODE_DISTANCE - 1000) ) - break; - } - - m_bRushForward = !m_bRushForward; - SetSecondaryMode( BULLRUSH_MODE_GET_DISTANCE ); - } - break; - - case BULLRUSH_MODE_SHOOT_GUN: - { - // When shooting, stop when we cross the player's position - // Then start bombing. Use the fixed speed version if we're too far - // from the enemy or if he's travelling in the opposite direction. - // Otherwise, do the standard bombing behavior for a while. - float flDistanceToGoal = ComputeDistanceToTargetPosition(); - - float flShootingHeight = CHOPPER_BULLRUSH_SHOOTING_VERTICAL_OFFSET; - float flSwitchToBombDist = CHOPPER_BULLRUSH_ENEMY_BOMB_DISTANCE; - float flDropDownDist = 2000.0f; - if ( m_bRushForward ) - { - m_flBullrushAdditionalHeight = ClampSplineRemapVal( flDistanceToGoal, - flSwitchToBombDist, flSwitchToBombDist + flDropDownDist, 0.0f, flShootingHeight ); - if ( flDistanceToGoal > flSwitchToBombDist ) - break; - } - else - { - m_flBullrushAdditionalHeight = ClampSplineRemapVal( flDistanceToGoal, - -flSwitchToBombDist - flDropDownDist, -flSwitchToBombDist, flShootingHeight, 0.0f ); - if ( flDistanceToGoal < -flSwitchToBombDist ) - break; - } - - if ( ShouldShootIdlePlayerInBullrush() ) - { - SetSecondaryMode( BULLRUSH_MODE_SHOOT_IDLE_PLAYER ); - } - else - { - ShutdownGunDuringBullrush( ); - SetSecondaryMode( BULLRUSH_MODE_DROP_BOMBS_FIXED_SPEED ); - } - } - break; - - case BULLRUSH_MODE_SHOOT_IDLE_PLAYER: - { - // Shut down our gun if we're switching to bombing - if ( ShouldBombIdlePlayer() ) - { - // Must not already be shutdown - if (( m_nGunState != GUN_STATE_IDLE ) && (SecondaryModeTime() >= BULLRUSH_IDLE_PLAYER_FIRE_TIME)) - { - ShutdownGunDuringBullrush( ); - } - } - -// m_nBurstHits = 0; - m_flCircleOfDeathRadius = ClampSplineRemapVal( SecondaryModeTime(), BULLRUSH_IDLE_PLAYER_FIRE_TIME, BULLRUSH_IDLE_PLAYER_FIRE_TIME + 5.0f, 256.0f, 64.0f ); - m_flBullrushAdditionalHeight = CHOPPER_BULLRUSH_SHOOTING_VERTICAL_OFFSET; - if ( !ShouldShootIdlePlayerInBullrush() ) - { - ShutdownGunDuringBullrush( ); - SetSecondaryMode( BULLRUSH_MODE_DROP_BOMBS_FIXED_SPEED ); - } - } - break; - - case BULLRUSH_MODE_DROP_BOMBS_FOLLOW_PLAYER: - { - m_flBullrushAdditionalHeight = 0.0f; - float flDistanceToGoal = ComputeDistanceToTargetPosition(); - if ( fabs( flDistanceToGoal ) > 2000.0f ) - { - SetSecondaryMode( BULLRUSH_MODE_DROP_BOMBS_FIXED_SPEED, true ); - break; - } - } - // FALL THROUGH!! - - case BULLRUSH_MODE_DROP_BOMBS_FIXED_SPEED: - { - float flDistanceToGoal = ComputeDistanceToTargetPosition(); - - m_flBullrushAdditionalHeight = 0.0f; - if (( SecondaryModeTime() >= CHOPPER_BULLRUSH_ENEMY_BOMB_TIME ) || ( flDistanceToGoal > BULLRUSH_BOMB_MAX_DISTANCE )) - { - m_bRushForward = !m_bRushForward; - SetSecondaryMode( BULLRUSH_MODE_GET_DISTANCE ); - } - } - break; - } -} - - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::UpdateEnemyLeading( void ) -{ - bool bEnemyInVehicle = true; - CBaseEntity *pTarget = GetEnemyVehicle(); - if ( !pTarget ) - { - bEnemyInVehicle = false; - if ( (m_nAttackMode == ATTACK_MODE_DEFAULT) || !GetEnemy() ) - { - EnableLeading( false ); - return; - } - - pTarget = GetEnemy(); - } - - EnableLeading( true ); - - float flLeadingDist = 0.0f; - float flSpeedAlongPath = TargetSpeedAlongPath(); - float flSpeed = pTarget->GetSmoothedVelocity().Length(); - - // Do the test electricity gun - if ( HasSpawnFlags(SF_HELICOPTER_ELECTRICAL_DRONE) ) - { - if ( flSpeedAlongPath < 200.0f ) - { - flLeadingDist = ClampSplineRemapVal( flSpeedAlongPath, 0.0f, 200.0f, 100.0f, -200.0f ); - } - else - { - flLeadingDist = ClampSplineRemapVal( flSpeedAlongPath, 200.0f, 600.0f, -200.0f, -500.0f ); - } - SetLeadingDistance( flLeadingDist ); - return; - } - - switch( m_nAttackMode ) - { - case ATTACK_MODE_BULLRUSH_VEHICLE: - flLeadingDist = ComputeBullrushLeadingDistance( flSpeed, flSpeedAlongPath, bEnemyInVehicle ); - break; - - case ATTACK_MODE_ALWAYS_LEAD_VEHICLE: - if (( flSpeed <= MIN_ENEMY_SPEED ) && (bEnemyInVehicle) ) - { - flLeadingDist = CreepTowardEnemy( flSpeed, 0.0f, MIN_ENEMY_SPEED, 0.0f, 1000.0f ); - } - else - { - if ( flSpeedAlongPath > 0.0f ) - { - flLeadingDist = ClampSplineRemapVal( flSpeedAlongPath, 200.0f, 600.0f, 1000.0f, 2000.0f ); - } - else - { - flLeadingDist = ClampSplineRemapVal( flSpeedAlongPath, -600.0f, -200.0f, -2000.0f, -1000.0f ); - } - } - break; - - case ATTACK_MODE_BOMB_VEHICLE: - flLeadingDist = ComputeBombingLeadingDistance( flSpeed, flSpeedAlongPath, bEnemyInVehicle ); - break; - - case ATTACK_MODE_DEFAULT: - case ATTACK_MODE_TRAIL_VEHICLE: - if (( flSpeed <= MIN_ENEMY_SPEED ) && (bEnemyInVehicle)) - { - flLeadingDist = CreepTowardEnemy( flSpeed, 150.0f, MIN_ENEMY_SPEED, 500.0f, -1000.0f ); - } - else - { - flLeadingDist = ClampSplineRemapVal( flSpeedAlongPath, -600.0f, -200.0f, -2500.0f, -1000.0f ); - } - break; - } - - SetLeadingDistance( flLeadingDist ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pInfo - -// bAlways - -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ) -{ - // Are we already marked for transmission? - if ( pInfo->m_pTransmitEdict->Get( entindex() ) ) - return; - - BaseClass::SetTransmit( pInfo, bAlways ); - - // Make our smoke trails always come with us - for ( int i = 0; i < m_nSmokeTrailCount; i++ ) - { - m_hSmokeTrail[i]->SetTransmit( pInfo, bAlways ); - } -} - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CNPC_AttackHelicopter::Hunt( void ) -{ - if ( m_lifeState == LIFE_DEAD ) - { - return; - } - - if ( m_lifeState == LIFE_DYING ) - { - Flight(); - UpdatePlayerDopplerShift( ); - return; - } - - // FIXME: Hack to allow us to change the firing distance - SetFarthestPathDist( GetMaxFiringDistance() ); - - UpdateEnemy(); - - // Give free knowledge of the enemy position if the chopper is "aggressive" - if ( HasSpawnFlags( SF_HELICOPTER_AGGRESSIVE ) && GetEnemy() ) - { - m_vecTargetPosition = GetEnemy()->WorldSpaceCenter(); - } - - // Test for state transitions when in bullrush mode - if ( m_nAttackMode == ATTACK_MODE_BULLRUSH_VEHICLE ) - { - UpdateBullrushState(); - } - - UpdateEnemyLeading(); - - UpdateTrackNavigation( ); - - Flight(); - - UpdatePlayerDopplerShift( ); - - FireWeapons(); - - if ( !(m_fHelicopterFlags & BITS_HELICOPTER_GUN_ON) ) - { - // !!!HACKHACK This is a fairly unsavoury hack that allows the attack - // chopper to continue to carpet bomb even with the gun turned off - // (Normally the chopper will carpet bomb inside FireGun(), but FireGun() - // doesn't get called by the above call to FireWeapons() if the gun is turned off) - // Adding this little exception here lets me avoid going into the CBaseHelicopter and - // making some functions virtual that don't want to be virtual. - if ( IsCarpetBombing() ) - { - BullrushBombs(); - } - } - -#ifdef HL2_EPISODIC - // Update our bone followers - m_BoneFollowerManager.UpdateBoneFollowers(this); -#endif // HL2_EPISODIC -} - -//----------------------------------------------------------------------------- -// Purpose: Cache whatever pose parameters we intend to use -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::PopulatePoseParameters( void ) -{ - m_poseWeapon_Pitch = LookupPoseParameter("weapon_pitch"); - m_poseWeapon_Yaw = LookupPoseParameter("weapon_yaw"); - m_poseRudder = LookupPoseParameter("rudder"); - - BaseClass::PopulatePoseParameters(); -} - -#ifdef HL2_EPISODIC -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_AttackHelicopter::InitBoneFollowers( void ) -{ - // Don't do this if we're already loaded - if ( m_BoneFollowerManager.GetNumBoneFollowers() != 0 ) - return; - - // Init our followers - m_BoneFollowerManager.InitBoneFollowers( this, ARRAYSIZE(pFollowerBoneNames), pFollowerBoneNames ); -} -#endif // HL2_EPISODIC - -//----------------------------------------------------------------------------- -// Where are how should we avoid? -//----------------------------------------------------------------------------- -AI_BEGIN_CUSTOM_NPC( npc_helicopter, CNPC_AttackHelicopter ) - -// DECLARE_TASK( ) - - DECLARE_ACTIVITY( ACT_HELICOPTER_DROP_BOMB ); - DECLARE_ACTIVITY( ACT_HELICOPTER_CRASHING ); - -// DECLARE_CONDITION( COND_ ) - - //========================================================= -// DEFINE_SCHEDULE -// ( -// SCHED_DUMMY, -// -// " Tasks" -// " TASK_FACE_ENEMY 0" -// " " -// " Interrupts" -// ) - - -AI_END_CUSTOM_NPC() - - - -//------------------------------------------------------------------------------ -// -// A sensor used to drop bombs only in the correct points -// -//------------------------------------------------------------------------------ -LINK_ENTITY_TO_CLASS( npc_helicoptersensor, CBombDropSensor ); - -BEGIN_DATADESC( CBombDropSensor ) - - DEFINE_INPUTFUNC( FIELD_VOID, "DropBomb", InputDropBomb ), - DEFINE_INPUTFUNC( FIELD_VOID, "DropBombStraightDown", InputDropBombStraightDown ), - DEFINE_INPUTFUNC( FIELD_STRING, "DropBombAtTargetAlways", InputDropBombAtTargetAlways ), - DEFINE_INPUTFUNC( FIELD_STRING, "DropBombAtTarget", InputDropBombAtTarget ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "DropBombDelay", InputDropBombDelay ), - -END_DATADESC() - - -void CBombDropSensor::Spawn() -{ - BaseClass::Spawn(); - UTIL_SetSize(this, Vector(-30,-30,-30), Vector(30,30,30) ); - SetSolid(SOLID_BBOX); - - // Shots pass through - SetCollisionGroup( COLLISION_GROUP_PROJECTILE ); -} - -// Drop a bomb at a particular location -void CBombDropSensor::InputDropBomb( inputdata_t &inputdata ) -{ - inputdata_t myVersion = inputdata; - myVersion.pActivator = this; - assert_cast(GetOwnerEntity())->InputDropBomb( myVersion ); -} - -void CBombDropSensor::InputDropBombStraightDown( inputdata_t &inputdata ) -{ - inputdata_t myVersion = inputdata; - myVersion.pActivator = this; - assert_cast(GetOwnerEntity())->InputDropBombStraightDown( myVersion ); -} - -void CBombDropSensor::InputDropBombAtTarget( inputdata_t &inputdata ) -{ - inputdata_t myVersion = inputdata; - myVersion.pActivator = this; - assert_cast(GetOwnerEntity())->InputDropBombAtTarget( myVersion ); -} - -void CBombDropSensor::InputDropBombAtTargetAlways( inputdata_t &inputdata ) -{ - inputdata_t myVersion = inputdata; - myVersion.pActivator = this; - assert_cast(GetOwnerEntity())->InputDropBombAtTargetAlways( myVersion ); -} - -void CBombDropSensor::InputDropBombDelay( inputdata_t &inputdata ) -{ - inputdata_t myVersion = inputdata; - myVersion.pActivator = this; - assert_cast(GetOwnerEntity())->InputDropBombDelay( myVersion ); -} - -//------------------------------------------------------------------------------ -// -// The bombs the helicopter drops on the player -// -//------------------------------------------------------------------------------ - -//------------------------------------------------------------------------------ -// Save/load -//------------------------------------------------------------------------------ - -LINK_ENTITY_TO_CLASS( grenade_helicopter, CGrenadeHelicopter ); - -BEGIN_DATADESC( CGrenadeHelicopter ) - - DEFINE_FIELD( m_bActivated, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bExplodeOnContact, FIELD_BOOLEAN ), - DEFINE_SOUNDPATCH( m_pWarnSound ), - - DEFINE_FIELD( m_hWarningSprite, FIELD_EHANDLE ), - DEFINE_FIELD( m_bBlinkerAtTop, FIELD_BOOLEAN ), - -#ifdef HL2_EPISODIC - DEFINE_FIELD( m_flLifetime, FIELD_FLOAT ), - DEFINE_FIELD( m_hCollisionObject, FIELD_EHANDLE ), - DEFINE_FIELD( m_bPickedUp, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flBlinkFastTime, FIELD_TIME ), - - DEFINE_INPUTFUNC( FIELD_FLOAT, "ExplodeIn", InputExplodeIn ), - - DEFINE_OUTPUT( m_OnPhysGunOnlyPickup, "OnPhysGunOnlyPickup" ), -#endif // HL2_EPISODIC - - DEFINE_THINKFUNC( ExplodeThink ), - DEFINE_THINKFUNC( AnimateThink ), - DEFINE_THINKFUNC( RampSoundThink ), - DEFINE_THINKFUNC( WarningBlinkerThink ), - DEFINE_ENTITYFUNC( ExplodeConcussion ), - -END_DATADESC() - -#define SF_HELICOPTER_GRENADE_DUD (1<<16) // Will not become active on impact, only when launched via physcannon - -//------------------------------------------------------------------------------ -// Precache -//------------------------------------------------------------------------------ -void CGrenadeHelicopter::Precache( void ) -{ - BaseClass::Precache( ); - PrecacheModel( GRENADE_HELICOPTER_MODEL ); - - PrecacheScriptSound( "ReallyLoudSpark" ); - PrecacheScriptSound( "NPC_AttackHelicopterGrenade.Ping" ); - PrecacheScriptSound( "NPC_AttackHelicopterGrenade.PingCaptured" ); - PrecacheScriptSound( "NPC_AttackHelicopterGrenade.HardImpact" ); -} - - -//------------------------------------------------------------------------------ -// Spawn -//------------------------------------------------------------------------------ -void CGrenadeHelicopter::Spawn( void ) -{ - Precache(); - - // point sized, solid, bouncing - SetCollisionGroup( COLLISION_GROUP_PROJECTILE ); - SetModel( GRENADE_HELICOPTER_MODEL ); - - if ( HasSpawnFlags( SF_HELICOPTER_GRENADE_DUD ) ) - { - m_nSkin = (int)SKIN_DUD; - } - - if ( !HasSpawnFlags( SF_GRENADE_HELICOPTER_MEGABOMB ) ) - { - IPhysicsObject *pPhysicsObject = VPhysicsInitNormal( SOLID_VPHYSICS, GetSolidFlags(), false ); - SetMoveType( MOVETYPE_VPHYSICS ); - - Vector vecAbsVelocity = GetAbsVelocity(); - pPhysicsObject->AddVelocity( &vecAbsVelocity, NULL ); - } - else - { - SetSolid( SOLID_BBOX ); - SetCollisionBounds( Vector( -12.5, -12.5, -12.5 ), Vector( 12.5, 12.5, 12.5 ) ); - VPhysicsInitShadow( false, false ); - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_CUSTOM ); - SetElasticity( 0.5f ); - AddEffects( EF_NOSHADOW ); - } - - // We're always being dropped beneath the helicopter; need to not - // be affected by the rotor wash - AddEFlags( EFL_NO_ROTORWASH_PUSH ); - - // contact grenades arc lower - QAngle angles; - VectorAngles(GetAbsVelocity(), angles ); - SetLocalAngles( angles ); - - SetThink( NULL ); - - // Tumble in air - QAngle vecAngVel( random->RandomFloat ( -100, -500 ), 0, 0 ); - SetLocalAngularVelocity( vecAngVel ); - - // Explode on contact - SetTouch( &CGrenadeHelicopter::ExplodeConcussion ); - - // use a lower gravity for grenades to make them easier to see - SetGravity( UTIL_ScaleForGravity( 400 ) ); - -#ifdef HL2_EPISODIC - m_bPickedUp = false; - m_flLifetime = BOMB_LIFETIME * 2.0; -#endif // HL2_EPISODIC - - if ( hl2_episodic.GetBool() ) - { - // Disallow this, we'd rather deal with them as physobjects - m_takedamage = DAMAGE_NO; - } - else - { - // Allow player to blow this puppy up in the air - m_takedamage = DAMAGE_YES; - } - - m_bActivated = false; - m_pWarnSound = NULL; - m_bExplodeOnContact = false; - - m_flDamage = sk_helicopter_grenadedamage.GetFloat(); - - g_pNotify->AddEntity( this, this ); - - if( hl2_episodic.GetBool() ) - { - SetContextThink( &CGrenadeHelicopter::AnimateThink, gpGlobals->curtime, s_pAnimateThinkContext ); - } -} - - -//------------------------------------------------------------------------------ -// On Remve -//------------------------------------------------------------------------------ -void CGrenadeHelicopter::UpdateOnRemove() -{ - if( m_pWarnSound ) - { - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundDestroy( m_pWarnSound ); - } - g_pNotify->ClearEntity( this ); - BaseClass::UpdateOnRemove(); -} - - -#ifdef HL2_EPISODIC -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CGrenadeHelicopter::InputExplodeIn( inputdata_t &inputdata ) -{ - m_flLifetime = inputdata.value.Float(); - - if ( HasSpawnFlags( SF_HELICOPTER_GRENADE_DUD ) ) - { - // We are a dud no more! - RemoveSpawnFlags( SF_HELICOPTER_GRENADE_DUD ); - m_nSkin = (int)SKIN_REGULAR; - } - - m_bActivated = false; - BecomeActive(); -} -#endif - - -//------------------------------------------------------------------------------ -// Activate! -//------------------------------------------------------------------------------ -void CGrenadeHelicopter::BecomeActive() -{ - if ( m_bActivated ) - return; - - if ( IsMarkedForDeletion() ) - return; - - m_bActivated = true; - - bool bMegaBomb = HasSpawnFlags(SF_GRENADE_HELICOPTER_MEGABOMB); - - SetThink( &CGrenadeHelicopter::ExplodeThink ); - - if ( hl2_episodic.GetBool() ) - { - if ( HasSpawnFlags( SF_HELICOPTER_GRENADE_DUD ) == false ) - { - SetNextThink( gpGlobals->curtime + GetBombLifetime() ); - } - else - { - // NOTE: A dud will not explode after a set time, only when launched! - SetThink( NULL ); - return; - } - } - else - { - SetNextThink( gpGlobals->curtime + GetBombLifetime() ); - } - - if ( !bMegaBomb ) - { - SetContextThink( &CGrenadeHelicopter::RampSoundThink, gpGlobals->curtime + GetBombLifetime() - BOMB_RAMP_SOUND_TIME, s_pRampSoundContext ); - - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - CReliableBroadcastRecipientFilter filter; - m_pWarnSound = controller.SoundCreate( filter, entindex(), "NPC_AttackHelicopterGrenade.Ping" ); - controller.Play( m_pWarnSound, 1.0, PITCH_NORM ); - } - - SetContextThink( &CGrenadeHelicopter::WarningBlinkerThink, gpGlobals->curtime + (GetBombLifetime() - 2.0f), s_pWarningBlinkerContext ); - -#ifdef HL2_EPISODIC - m_flBlinkFastTime = gpGlobals->curtime + GetBombLifetime() - 1.0f; -#endif//HL2_EPISODIC -} - - -//------------------------------------------------------------------------------ -// Pow! -//------------------------------------------------------------------------------ -void CGrenadeHelicopter::RampSoundThink( ) -{ - if ( m_pWarnSound ) - { - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundChangePitch( m_pWarnSound, 140, BOMB_RAMP_SOUND_TIME ); - } - - SetContextThink( NULL, gpGlobals->curtime, s_pRampSoundContext ); -} - - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CGrenadeHelicopter::WarningBlinkerThink() -{ -#ifndef HL2_EPISODIC - return; -#endif - -/* - if( !m_hWarningSprite.Get() ) - { - Vector up; - GetVectors( NULL, NULL, &up ); - - // Light isn't on, so create the sprite. - m_hWarningSprite = CSprite::SpriteCreate( "sprites/redglow1.vmt", GetAbsOrigin() + up * 10.0f, false ); - CSprite *pSprite = (CSprite *)m_hWarningSprite.Get(); - - if( pSprite != NULL ) - { - pSprite->SetParent( this, LookupAttachment("top") ); - pSprite->SetTransparency( kRenderTransAdd, 255, 255, 255, 255, kRenderFxNone ); - pSprite->SetScale( 0.35, 0.0 ); - } - - m_bBlinkerAtTop = true; - - ResetSequence( LookupActivity( "ACT_ARM" ) ); - } - else -*/ - { - // Just flip it to the other attachment. - if( m_bBlinkerAtTop ) - { - //m_hWarningSprite->SetParentAttachment( "SetParentAttachment", "bottom", false ); - m_nSkin = (int)SKIN_REGULAR; - m_bBlinkerAtTop = false; - } - else - { - //m_hWarningSprite->SetParentAttachment( "SetParentAttachment", "top", false ); - m_nSkin = (int)SKIN_DUD; - m_bBlinkerAtTop = true; - } - } - - // Frighten people - CSoundEnt::InsertSound ( SOUND_DANGER, WorldSpaceCenter(), g_helicopter_bomb_danger_radius.GetInt(), 0.2f, this, SOUNDENT_CHANNEL_REPEATED_DANGER ); - -#ifdef HL2_EPISODIC - if( gpGlobals->curtime >= m_flBlinkFastTime ) - { - SetContextThink( &CGrenadeHelicopter::WarningBlinkerThink, gpGlobals->curtime + 0.1f, s_pWarningBlinkerContext ); - } - else - { - SetContextThink( &CGrenadeHelicopter::WarningBlinkerThink, gpGlobals->curtime + 0.2f, s_pWarningBlinkerContext ); - } -#endif//HL2_EPISODIC -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CGrenadeHelicopter::StopWarningBlinker() -{ - if( m_hWarningSprite.Get() ) - { - UTIL_Remove( m_hWarningSprite.Get() ); - m_hWarningSprite.Set( NULL ); - } -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CGrenadeHelicopter::AnimateThink() -{ - StudioFrameAdvance(); - SetContextThink( &CGrenadeHelicopter::AnimateThink, gpGlobals->curtime + 0.1f, s_pAnimateThinkContext ); -} - -//------------------------------------------------------------------------------ -// Entity events... these are events targetted to a particular entity -//------------------------------------------------------------------------------ -void CGrenadeHelicopter::OnEntityEvent( EntityEvent_t event, void *pEventData ) -{ - BaseClass::OnEntityEvent( event, pEventData ); - - if ( event == ENTITY_EVENT_WATER_TOUCH ) - { - BecomeActive(); - } -} - - -//------------------------------------------------------------------------------ -// If we hit water, then stop -//------------------------------------------------------------------------------ -void CGrenadeHelicopter::PhysicsSimulate( void ) -{ - Vector vecPrevPosition = GetAbsOrigin(); - - BaseClass::PhysicsSimulate(); - - if (!m_bActivated && (GetMoveType() != MOVETYPE_VPHYSICS)) - { - if ( GetWaterLevel() > 1 ) - { - SetAbsVelocity( vec3_origin ); - SetMoveType( MOVETYPE_NONE ); - BecomeActive(); - } - - // Stuck condition, can happen pretty often - if ( vecPrevPosition == GetAbsOrigin() ) - { - SetAbsVelocity( vec3_origin ); - SetMoveType( MOVETYPE_NONE ); - BecomeActive(); - } - } -} - - -//------------------------------------------------------------------------------ -// If we hit something, start the timer -//------------------------------------------------------------------------------ -void CGrenadeHelicopter::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) -{ - BaseClass::VPhysicsCollision( index, pEvent ); - BecomeActive(); - -#ifndef HL2_EPISODIC // in ep2, don't do this here, do it in Touch() - if ( m_bExplodeOnContact ) - { - Vector vecVelocity; - GetVelocity( &vecVelocity, NULL ); - DoExplosion( GetAbsOrigin(), vecVelocity ); - } -#endif - - - if( hl2_episodic.GetBool() ) - { - float flImpactSpeed = pEvent->preVelocity->Length(); - if( flImpactSpeed > 400.0f && pEvent->pEntities[ 1 ]->IsWorld() ) - { - EmitSound( "NPC_AttackHelicopterGrenade.HardImpact" ); - } - } -} - - -#if HL2_EPISODIC -//------------------------------------------------------------------------------ -// double launch velocity for ep2_outland_08 -//------------------------------------------------------------------------------ -Vector CGrenadeHelicopter::PhysGunLaunchVelocity( const Vector &forward, float flMass ) -{ - // return ( striderbuster_shot_velocity.GetFloat() * forward ); - - return BaseClass::PhysGunLaunchVelocity(forward,flMass) * sk_helicopter_grenaderadius.GetFloat(); -} -#endif - - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -float CGrenadeHelicopter::GetBombLifetime() -{ -#if HL2_EPISODIC - return m_flLifetime; -#else - return BOMB_LIFETIME; -#endif -} - - -//------------------------------------------------------------------------------ -// Pow! -//------------------------------------------------------------------------------ -int CGrenadeHelicopter::OnTakeDamage( const CTakeDamageInfo &info ) -{ - // We don't take blast damage - if ( info.GetDamageType() & DMG_BLAST ) - return 0; - - return BaseClass::OnTakeDamage( info ); -} - - -//------------------------------------------------------------------------------ -// Pow! -//------------------------------------------------------------------------------ -void CGrenadeHelicopter::DoExplosion( const Vector &vecOrigin, const Vector &vecVelocity ) -{ - ExplosionCreate( GetAbsOrigin(), GetAbsAngles(), GetOwnerEntity() ? GetOwnerEntity() : this, sk_helicopter_grenadedamage.GetInt(), - sk_helicopter_grenaderadius.GetInt(), (SF_ENVEXPLOSION_NOSPARKS|SF_ENVEXPLOSION_NODLIGHTS|SF_ENVEXPLOSION_NODECAL|SF_ENVEXPLOSION_NOFIREBALL|SF_ENVEXPLOSION_NOPARTICLES), - sk_helicopter_grenadeforce.GetFloat(), this ); - - if ( GetShakeAmplitude() ) - { - UTIL_ScreenShake( GetAbsOrigin(), GetShakeAmplitude(), 150.0, 1.0, GetShakeRadius(), SHAKE_START ); - } - - CEffectData data; - - // If we're under water do a water explosion - if ( GetWaterLevel() != 0 && (GetWaterType() & CONTENTS_WATER) ) - { - data.m_vOrigin = WorldSpaceCenter(); - data.m_flMagnitude = 128; - data.m_flScale = 128; - data.m_fFlags = 0; - DispatchEffect( "WaterSurfaceExplosion", data ); - } - else - { - // Otherwise do a normal explosion - data.m_vOrigin = GetAbsOrigin(); - DispatchEffect( "HelicopterMegaBomb", data ); - } - - UTIL_Remove( this ); -} - - -//------------------------------------------------------------------------------ -// I think I Pow! -//------------------------------------------------------------------------------ -void CGrenadeHelicopter::ExplodeThink(void) -{ -#ifdef HL2_EPISODIC - // remember if we were thrown by player, we can only determine this prior to explosion - bool bIsThrownByPlayer = IsThrownByPlayer(); - int iHealthBefore = 0; - // get the health of the helicopter we came from prior to our explosion - CNPC_AttackHelicopter *pOwner = dynamic_cast( GetOriginalThrower() ); - if ( pOwner ) - { - iHealthBefore = pOwner->GetHealth(); - } -#endif // HL2_EPISODIC - - Vector vecVelocity; - GetVelocity( &vecVelocity, NULL ); - DoExplosion( GetAbsOrigin(), vecVelocity ); - -#ifdef HL2_EPISODIC - // if we were thrown by player, look at health of helicopter after explosion and determine if we damaged it - if ( bIsThrownByPlayer && pOwner && ( iHealthBefore > 0 ) ) - { - int iHealthAfter = pOwner->GetHealth(); - if ( iHealthAfter == iHealthBefore ) - { - // The player threw us, we exploded due to timer, and we did not damage the helicopter that fired us. Send a miss event - SendMissEvent(); - } - } -#endif // HL2_EPISODIC - -} - - -//------------------------------------------------------------------------------ -// I think I Pow! -//------------------------------------------------------------------------------ -void CGrenadeHelicopter::ResolveFlyCollisionCustom( trace_t &trace, Vector &vecVelocity ) -{ - ResolveFlyCollisionBounce( trace, vecVelocity, 0.1f ); -} - - -//------------------------------------------------------------------------------ -// Contact grenade, explode when it touches something -//------------------------------------------------------------------------------ -void CGrenadeHelicopter::ExplodeConcussion( CBaseEntity *pOther ) -{ - if ( !pOther->IsSolid() ) - return; - - if ( !m_bExplodeOnContact ) - { - if ( pOther->IsWorld() ) - return; - - if ( hl2_episodic.GetBool() ) - { - // Don't hit anything other than vehicles - if ( pOther->GetCollisionGroup() != COLLISION_GROUP_VEHICLE ) - return; - } - } - -#ifdef HL2_EPISODIC - CBaseEntity *pEntityHit = pOther; - if ( pEntityHit->ClassMatches( "phys_bone_follower" ) && pEntityHit->GetOwnerEntity() ) - { - pEntityHit = pEntityHit->GetOwnerEntity(); - } - if ( ( CLASS_COMBINE_GUNSHIP != pEntityHit->Classify() ) || !pEntityHit->ClassMatches( "npc_helicopter" ) ) - { - // We hit something other than a helicopter. If the player threw us, send a miss event - if ( IsThrownByPlayer() ) - { - SendMissEvent(); - } - } -#endif // HL2_EPISODIC - - Vector vecVelocity; - GetVelocity( &vecVelocity, NULL ); - DoExplosion( GetAbsOrigin(), vecVelocity ); -} - - -#ifdef HL2_EPISODIC -//----------------------------------------------------------------------------- -// Purpose: The bomb will act differently when picked up by the player -//----------------------------------------------------------------------------- -void CGrenadeHelicopter::OnPhysGunPickup(CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) -{ - if ( reason == PICKED_UP_BY_CANNON ) - { - if ( !m_bPickedUp ) - { - if( m_hWarningSprite.Get() != NULL ) - { - UTIL_Remove( m_hWarningSprite ); - m_hWarningSprite.Set(NULL); - } - - // Turn on - BecomeActive(); - - // Change the warning sound to a captured sound. - SetContextThink( &CGrenadeHelicopter::RampSoundThink, gpGlobals->curtime + GetBombLifetime() - BOMB_RAMP_SOUND_TIME, s_pRampSoundContext ); - - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundDestroy( m_pWarnSound ); - - CReliableBroadcastRecipientFilter filter; - m_pWarnSound = controller.SoundCreate( filter, entindex(), "NPC_AttackHelicopterGrenade.PingCaptured" ); - controller.Play( m_pWarnSound, 1.0, PITCH_NORM ); - - // Reset our counter so the player has more time - SetThink( &CGrenadeHelicopter::ExplodeThink ); - SetNextThink( gpGlobals->curtime + GetBombLifetime() ); - - SetContextThink( &CGrenadeHelicopter::WarningBlinkerThink, gpGlobals->curtime + GetBombLifetime() - 2.0f, s_pWarningBlinkerContext ); - -#ifdef HL2_EPISODIC - m_nSkin = (int)SKIN_REGULAR; - m_flBlinkFastTime = gpGlobals->curtime + GetBombLifetime() - 1.0f; -#endif//HL2_EPISODIC - - // Stop us from sparing damage to the helicopter that dropped us - SetOwnerEntity( pPhysGunUser ); - PhysEnableEntityCollisions( this, m_hCollisionObject ); - - // Don't do this again! - m_bPickedUp = true; - - m_OnPhysGunOnlyPickup.FireOutput( pPhysGunUser, this ); - } - } - - BaseClass::OnPhysGunPickup( pPhysGunUser, reason ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGrenadeHelicopter::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t reason ) -{ - if ( reason == LAUNCHED_BY_CANNON ) - { - // Enable world touches. - unsigned int flags = VPhysicsGetObject()->GetCallbackFlags(); - VPhysicsGetObject()->SetCallbackFlags( flags | CALLBACK_GLOBAL_TOUCH_STATIC ); - - // Explode on contact - SetTouch( &CGrenadeHelicopter::ExplodeConcussion ); - m_bExplodeOnContact = true; - - } - - BaseClass::OnPhysGunDrop( pPhysGunUser, reason ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns if the player threw this grenade w/phys gun -//----------------------------------------------------------------------------- -bool CGrenadeHelicopter::IsThrownByPlayer() -{ - // if player is the owner and we're set to explode on contact, then the player threw this grenade. - return ( ( GetOwnerEntity() == UTIL_GetLocalPlayer() ) && m_bExplodeOnContact ); -} - -//----------------------------------------------------------------------------- -// Purpose: If player threw this grenade, sends a miss event -//----------------------------------------------------------------------------- -void CGrenadeHelicopter::SendMissEvent() -{ - // send a miss event - IGameEvent *event = gameeventmanager->CreateEvent( "helicopter_grenade_punt_miss" ); - if ( event ) - { - gameeventmanager->FireEvent( event ); - } -} - -#endif // HL2_EPISODIC - -//----------------------------------------------------------------------------- -// -// This entity is used to create little force spheres that the helicopters should avoid. -// -//----------------------------------------------------------------------------- -CUtlVector< CAvoidSphere::AvoidSphereHandle_t > CAvoidSphere::s_AvoidSpheres; - -#define SF_AVOIDSPHERE_AVOID_BELOW 0x00010000 - -LINK_ENTITY_TO_CLASS( npc_heli_avoidsphere, CAvoidSphere ); - -BEGIN_DATADESC( CAvoidSphere ) - - DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "radius" ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Creates an avoidance sphere -//----------------------------------------------------------------------------- -CBaseEntity *CreateHelicopterAvoidanceSphere( CBaseEntity *pParent, int nAttachment, float flRadius, bool bAvoidBelow ) -{ - CAvoidSphere *pSphere = static_cast(CreateEntityByName( "npc_heli_avoidsphere" )); - pSphere->Init( flRadius ); - if ( bAvoidBelow ) - { - pSphere->AddSpawnFlags( SF_AVOIDSPHERE_AVOID_BELOW ); - } - pSphere->Spawn(); - pSphere->SetParent( pParent, nAttachment ); - pSphere->SetLocalOrigin( vec3_origin ); - pSphere->SetLocalAngles( vec3_angle ); - pSphere->SetOwnerEntity( pParent ); - return pSphere; -} - - -//----------------------------------------------------------------------------- -// Init -//----------------------------------------------------------------------------- -void CAvoidSphere::Init( float flRadius ) -{ - m_flRadius = flRadius; -} - - -//----------------------------------------------------------------------------- -// Spawn, remove -//----------------------------------------------------------------------------- -void CAvoidSphere::Activate( ) -{ - BaseClass::Activate(); - s_AvoidSpheres.AddToTail( this ); -} - -void CAvoidSphere::UpdateOnRemove( ) -{ - s_AvoidSpheres.FindAndRemove( this ); - BaseClass::UpdateOnRemove(); -} - - -//----------------------------------------------------------------------------- -// Where are how should we avoid? -//----------------------------------------------------------------------------- -void CAvoidSphere::ComputeAvoidanceForces( CBaseEntity *pEntity, float flEntityRadius, - float flAvoidTime, Vector *pVecAvoidForce ) -{ - pVecAvoidForce->Init( ); - - Vector vecEntityDelta; - VectorMultiply( pEntity->GetAbsVelocity(), flAvoidTime, vecEntityDelta ); - Vector vecEntityCenter = pEntity->WorldSpaceCenter(); - - for ( int i = s_AvoidSpheres.Count(); --i >= 0; ) - { - CAvoidSphere *pSphere = s_AvoidSpheres[i].Get(); - const Vector &vecAvoidCenter = pSphere->WorldSpaceCenter(); - - // NOTE: This test can be thought of sweeping a sphere through space - // and seeing if it intersects the avoidance sphere - float flTotalRadius = flEntityRadius + pSphere->m_flRadius; - float t1, t2; - if ( !IntersectRayWithSphere( vecEntityCenter, vecEntityDelta, - vecAvoidCenter, flTotalRadius, &t1, &t2 ) ) - { - continue; - } - - // NOTE: The point of closest approach is at the average t value - Vector vecClosestApproach; - float flAverageT = (t1 + t2) * 0.5f; - VectorMA( vecEntityCenter, flAverageT, vecEntityDelta, vecClosestApproach ); - - // Add velocity to make it be pushed out away from the sphere center - // without totally counteracting its velocity. - Vector vecDir; - VectorSubtract( vecClosestApproach, vecAvoidCenter, vecDir ); - float flZDist = vecDir.z; - float flDist = VectorNormalize( vecDir ); - float flDistToTravel; - if ( flDist < 0.01f ) - { - flDist = 0.01f; - vecDir.Init( 0, 0, 1 ); - flDistToTravel = flTotalRadius; - } - else - { - // make the chopper always avoid *above* - // That means if a force would be applied to push the chopper down, - // figure out a new distance to travel that would push the chopper up. - if ( flZDist < 0.0f && !pSphere->HasSpawnFlags(SF_AVOIDSPHERE_AVOID_BELOW) ) - { - Vector vecExitPoint; - vecDir.z = -vecDir.z; - VectorMA( vecAvoidCenter, flTotalRadius, vecDir, vecExitPoint ); - VectorSubtract( vecExitPoint, vecClosestApproach, vecDir ); - flDistToTravel = VectorNormalize( vecDir ); - } - else - { - Assert( flDist <= flTotalRadius ); - flDistToTravel = flTotalRadius - flDist; - } - } - - // The actual force amount is easy to think about: - // We need to change the position by dx over a time dt, so dv = dx/dt - // But so it doesn't explode, lets clamp t1 to a not-unreasonable time - if ( t1 < 0.25f ) - { - t1 = 0.25f; - } - - float flForce = 1.25f * flDistToTravel / t1; - vecDir *= flForce; - - *pVecAvoidForce += vecDir; - } -} - - -//----------------------------------------------------------------------------- -// -// This entity is used to create little force boxes that the helicopters should avoid. -// -//----------------------------------------------------------------------------- -CUtlVector< CAvoidBox::AvoidBoxHandle_t > CAvoidBox::s_AvoidBoxes; - -#define SF_AVOIDBOX_AVOID_BELOW 0x00010000 - -LINK_ENTITY_TO_CLASS( npc_heli_avoidbox, CAvoidBox ); - -BEGIN_DATADESC( CAvoidBox ) -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Spawn, remove -//----------------------------------------------------------------------------- -void CAvoidBox::Spawn( ) -{ - SetModel( STRING( GetModelName() ) ); - SetSolid( SOLID_BSP ); - AddSolidFlags( FSOLID_NOT_SOLID ); - AddEffects( EF_NODRAW ); -} - -void CAvoidBox::Activate( ) -{ - BaseClass::Activate(); - s_AvoidBoxes.AddToTail( this ); -} - -void CAvoidBox::UpdateOnRemove( ) -{ - s_AvoidBoxes.FindAndRemove( this ); - BaseClass::UpdateOnRemove(); -} - - -//----------------------------------------------------------------------------- -// Where are how should we avoid? -//----------------------------------------------------------------------------- -void CAvoidBox::ComputeAvoidanceForces( CBaseEntity *pEntity, float flEntityRadius, float flAvoidTime, Vector *pVecAvoidForce ) -{ - pVecAvoidForce->Init( ); - - Vector vecEntityDelta, vecEntityEnd; - VectorMultiply( pEntity->GetAbsVelocity(), flAvoidTime, vecEntityDelta ); - Vector vecEntityCenter = pEntity->WorldSpaceCenter(); - VectorAdd( vecEntityCenter, vecEntityDelta, vecEntityEnd ); - - Vector vecVelDir = pEntity->GetAbsVelocity(); - VectorNormalize( vecVelDir ); - - for ( int i = s_AvoidBoxes.Count(); --i >= 0; ) - { - CAvoidBox *pBox = s_AvoidBoxes[i].Get(); - - const Vector &vecAvoidCenter = pBox->WorldSpaceCenter(); - - // NOTE: This test can be thought of sweeping a sphere through space - // and seeing if it intersects the avoidance box - float flTotalRadius = flEntityRadius + pBox->BoundingRadius(); - float t1, t2; - if ( !IntersectInfiniteRayWithSphere( vecEntityCenter, vecEntityDelta, - vecAvoidCenter, flTotalRadius, &t1, &t2 ) ) - { - continue; - } - - if (( t2 < 0.0f ) || ( t1 > 1.0f )) - continue; - - // Unlike the avoid spheres, we also need to make sure the ray intersects the box - Vector vecLocalCenter, vecLocalDelta; - pBox->CollisionProp()->WorldToCollisionSpace( vecEntityCenter, &vecLocalCenter ); - pBox->CollisionProp()->WorldDirectionToCollisionSpace( vecEntityDelta, &vecLocalDelta ); - - Vector vecBoxMin( -flEntityRadius, -flEntityRadius, -flEntityRadius ); - Vector vecBoxMax( flEntityRadius, flEntityRadius, flEntityRadius ); - vecBoxMin += pBox->CollisionProp()->OBBMins(); - vecBoxMax += pBox->CollisionProp()->OBBMaxs(); - - trace_t tr; - if ( !IntersectRayWithBox( vecLocalCenter, vecLocalDelta, vecBoxMin, vecBoxMax, 0.0f, &tr ) ) - continue; - - // NOTE: The point of closest approach is at the average t value - Vector vecClosestApproach; - float flAverageT = (t1 + t2) * 0.5f; - VectorMA( vecEntityCenter, flAverageT, vecEntityDelta, vecClosestApproach ); - - // Add velocity to make it be pushed out away from the sphere center - // without totally counteracting its velocity. - Vector vecDir; - VectorSubtract( vecClosestApproach, vecAvoidCenter, vecDir ); - - // Limit unnecessary sideways motion - if ( ( tr.plane.type != 3 ) || ( tr.plane.normal[2] > 0.0f ) ) - { - vecDir.x *= 0.1f; - vecDir.y *= 0.1f; - } - - float flZDist = vecDir.z; - float flDist = VectorNormalize( vecDir ); - float flDistToTravel; - if ( flDist < 10.0f ) - { - flDist = 10.0f; - vecDir.Init( 0, 0, 1 ); - flDistToTravel = flTotalRadius; - } - else - { - // make the chopper always avoid *above* - // That means if a force would be applied to push the chopper down, - // figure out a new distance to travel that would push the chopper up. - if ( flZDist < 0.0f && !pBox->HasSpawnFlags(SF_AVOIDSPHERE_AVOID_BELOW) ) - { - Vector vecExitPoint; - vecDir.z = -vecDir.z; - VectorMA( vecAvoidCenter, flTotalRadius, vecDir, vecExitPoint ); - VectorSubtract( vecExitPoint, vecClosestApproach, vecDir ); - flDistToTravel = VectorNormalize( vecDir ); - } - else - { - Assert( flDist <= flTotalRadius ); - flDistToTravel = flTotalRadius - flDist; - } - } - - // The actual force amount is easy to think about: - // We need to change the position by dx over a time dt, so dv = dx/dt - // But so it doesn't explode, lets clamp t1 to a not-unreasonable time - if ( t1 < 0.25f ) - { - t1 = 0.25f; - } - - float flForce = 1.5f * flDistToTravel / t1; - vecDir *= flForce; - - *pVecAvoidForce += vecDir; - } -} - - -//----------------------------------------------------------------------------- -// -// This entity is used to create little force boxes that the helicopters should avoid. -// -//----------------------------------------------------------------------------- -CUtlVector< CBombSuppressor::BombSuppressorHandle_t > CBombSuppressor::s_BombSuppressors; - -LINK_ENTITY_TO_CLASS( npc_heli_nobomb, CBombSuppressor ); - -BEGIN_DATADESC( CBombSuppressor ) -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Spawn, remove -//----------------------------------------------------------------------------- -void CBombSuppressor::Spawn( ) -{ - SetModel( STRING( GetModelName() ) ); - SetSolid( SOLID_BSP ); - AddSolidFlags( FSOLID_NOT_SOLID ); - AddEffects( EF_NODRAW ); -} - -void CBombSuppressor::Activate( ) -{ - BaseClass::Activate(); - s_BombSuppressors.AddToTail( this ); -} - -void CBombSuppressor::UpdateOnRemove( ) -{ - s_BombSuppressors.FindAndRemove( this ); - BaseClass::UpdateOnRemove(); -} - - -//----------------------------------------------------------------------------- -// Where are how should we avoid? -//----------------------------------------------------------------------------- -bool CBombSuppressor::CanBomb( const Vector &vecPosition ) -{ - for ( int i = s_BombSuppressors.Count(); --i >= 0; ) - { - CBombSuppressor *pBox = s_BombSuppressors[i].Get(); - if ( pBox->CollisionProp()->IsPointInBounds( vecPosition ) ) - return false; - } - - return true; -} - -LINK_ENTITY_TO_CLASS( helicopter_chunk, CHelicopterChunk ); - -BEGIN_DATADESC( CHelicopterChunk ) - - DEFINE_THINKFUNC( FallThink ), - - DEFINE_FIELD( m_bLanded, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hMaster, FIELD_EHANDLE ), - DEFINE_FIELD( m_nChunkID, FIELD_INTEGER ), - DEFINE_PHYSPTR( m_pTailConstraint ), - DEFINE_PHYSPTR( m_pCockpitConstraint ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHelicopterChunk::Spawn( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHelicopterChunk::FallThink( void ) -{ - if ( m_bLanded ) - { - SetThink( NULL ); - return; - } - - if ( random->RandomInt( 0, 8 ) == 0 ) - { - CEffectData data; - data.m_vOrigin = GetAbsOrigin() + RandomVector( -64, 64 ); - DispatchEffect( "HelicopterMegaBomb", data ); - - EmitSound( "BaseExplosionEffect.Sound" ); - } - - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -// *pEvent - -//----------------------------------------------------------------------------- -void CHelicopterChunk::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) -{ - BaseClass::VPhysicsCollision( index, pEvent ); - - if ( m_bLanded == false ) - { - int otherIndex = !index; - CBaseEntity *pOther = pEvent->pEntities[otherIndex]; - if ( !pOther ) - return; - - if ( pOther->IsWorld() ) - { - CollisionCallback( this ); - - m_bLanded = true; - SetThink( NULL ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pCaller - -//----------------------------------------------------------------------------- -void CHelicopterChunk::CollisionCallback( CHelicopterChunk *pCaller ) -{ - if ( m_bLanded ) - return; - - if ( m_hMaster != NULL ) - { - m_hMaster->CollisionCallback( this ); - } - else - { - // Break our other constraints - if ( m_pTailConstraint ) - { - physenv->DestroyConstraint( m_pTailConstraint ); - m_pTailConstraint = NULL; - } - - if ( m_pCockpitConstraint ) - { - physenv->DestroyConstraint( m_pCockpitConstraint ); - m_pCockpitConstraint = NULL; - } - - // Add a dust cloud - AR2Explosion *pExplosion = AR2Explosion::CreateAR2Explosion( GetAbsOrigin() ); - - if ( pExplosion != NULL ) - { - pExplosion->SetLifetime( 10 ); - } - - // Make a loud noise - EmitSound( "NPC_AttackHelicopter.Crash" ); - - m_bLanded = true; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &vecPos - -// &vecAngles - -// &vecVelocity - -// *pszModelName - -// Output : CHelicopterChunk -//----------------------------------------------------------------------------- -CHelicopterChunk *CHelicopterChunk::CreateHelicopterChunk( const Vector &vecPos, const QAngle &vecAngles, const Vector &vecVelocity, const char *pszModelName, int chunkID ) -{ - // Drop a flaming, smoking chunk. - CHelicopterChunk *pChunk = CREATE_ENTITY( CHelicopterChunk, "helicopter_chunk" ); - - if ( pChunk == NULL ) - return NULL; - - pChunk->Spawn(); - - pChunk->SetAbsOrigin( vecPos ); - pChunk->SetAbsAngles( vecAngles ); - - pChunk->SetModel( pszModelName ); - - pChunk->m_nChunkID = chunkID; - pChunk->SetCollisionGroup( COLLISION_GROUP_INTERACTIVE ); - - IPhysicsObject *pPhysicsObject = pChunk->VPhysicsInitNormal( SOLID_VPHYSICS, pChunk->GetSolidFlags(), false ); - - // Set the velocity - if ( pPhysicsObject ) - { - pPhysicsObject->EnableMotion( true ); - Vector vecChunkVelocity; - AngularImpulse angImpulse; - - vecChunkVelocity = vecVelocity; - angImpulse = vec3_origin; - - pPhysicsObject->SetVelocity(&vecChunkVelocity, &angImpulse ); - } - - pChunk->SetThink( &CHelicopterChunk::FallThink ); - pChunk->SetNextThink( gpGlobals->curtime + 0.1f ); - - pChunk->m_bLanded = false; - - SmokeTrail *pSmokeTrail = SmokeTrail::CreateSmokeTrail(); - pSmokeTrail->FollowEntity( pChunk, "damage" ); - - pSmokeTrail->m_SpawnRate = 4; - pSmokeTrail->m_ParticleLifetime = 2.0f; - - pSmokeTrail->m_StartColor.Init( 0.7f, 0.7f, 0.7f ); - pSmokeTrail->m_EndColor.Init( 0.6, 0.6, 0.6 ); - - pSmokeTrail->m_StartSize = 32; - pSmokeTrail->m_EndSize = 64; - pSmokeTrail->m_SpawnRadius= 8; - pSmokeTrail->m_MinSpeed = 0; - pSmokeTrail->m_MaxSpeed = 8; - pSmokeTrail->m_Opacity = 0.35f; - - CFireTrail *pFireTrail = CFireTrail::CreateFireTrail(); - - if ( pFireTrail == NULL ) - return pChunk; - - pFireTrail->FollowEntity( pChunk, "damage" ); - pFireTrail->SetParent( pChunk, 1 ); - pFireTrail->SetLocalOrigin( vec3_origin ); - pFireTrail->SetMoveType( MOVETYPE_NONE ); - pFireTrail->SetLifetime( 10.0f ); - - return pChunk; -} diff --git a/game/server/hl2/npc_attackchopper.h b/game/server/hl2/npc_attackchopper.h deleted file mode 100644 index b40afe0d0..000000000 --- a/game/server/hl2/npc_attackchopper.h +++ /dev/null @@ -1,30 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - - -#ifndef NPC_ATTACKCHOPPER_H -#define NPC_ATTACKCHOPPER_H - -#ifdef _WIN32 -#pragma once -#endif - - -//----------------------------------------------------------------------------- -// Creates an avoidance sphere -//----------------------------------------------------------------------------- -CBaseEntity *CreateHelicopterAvoidanceSphere( CBaseEntity *pParent, int nAttachment, float flRadius, bool bAvoidBelow = false ); - -// Chopper gibbage -void Chopper_BecomeChunks( CBaseEntity *pChopper ); -void Chopper_CreateChunk( CBaseEntity *pChopper, const Vector &vecChunkPos, const QAngle &vecChunkAngles, const char *pszChunkName, bool bSmall ); -void Chopper_PrecacheChunks( CBaseEntity *pChopper ); - -#endif // NPC_ATTACKCHOPPER_H - - diff --git a/game/server/hl2/npc_barnacle.cpp b/game/server/hl2/npc_barnacle.cpp deleted file mode 100644 index 11de86305..000000000 --- a/game/server/hl2/npc_barnacle.cpp +++ /dev/null @@ -1,2734 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: barnacle - stationary ceiling mounted 'fishing' monster -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "physics_prop_ragdoll.h" -#include "npc_barnacle.h" -#include "npcevent.h" -#include "gib.h" -#include "ai_default.h" -#include "activitylist.h" -#include "hl2_player.h" -#include "vstdlib/random.h" -#include "physics_saverestore.h" -#include "vcollide_parse.h" -#include "vphysics/constraints.h" -#include "studio.h" -#include "bone_setup.h" -#include "iservervehicle.h" -#include "collisionutils.h" -#include "combine_mine.h" -#include "explode.h" -#include "npc_BaseZombie.h" -#include "modelentities.h" - -#if HL2_EPISODIC -#include "npc_antlion.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern ConVar sv_gravity; -ConVar sk_barnacle_health( "sk_barnacle_health","0"); - -static ConVar npc_barnacle_swallow( "npc_barnacle_swallow", "0", 0, "Use prototype swallow code." ); - -const char *CNPC_Barnacle::m_szGibNames[NUM_BARNACLE_GIBS] = -{ - "models/gibs/hgibs.mdl", - "models/gibs/hgibs_scapula.mdl", - "models/gibs/hgibs_rib.mdl", - "models/gibs/hgibs_spine.mdl" -}; - -//----------------------------------------------------------------------------- -// Private activities. -//----------------------------------------------------------------------------- -int ACT_BARNACLE_SLURP; // Pulling the tongue up with prey on the end -int ACT_BARNACLE_BITE_HUMAN; // Biting the head of a humanoid -int ACT_BARNACLE_BITE_PLAYER; // Biting the head of the player -int ACT_BARNACLE_CHEW_HUMAN; // Slowly swallowing the humanoid -int ACT_BARNACLE_BARF_HUMAN; // Spitting out human legs & gibs -int ACT_BARNACLE_TONGUE_WRAP; // Wrapping the tongue around a target -int ACT_BARNACLE_TASTE_SPIT; // Yuck! Me no like that! -int ACT_BARNACLE_BITE_SMALL_THINGS; // Eats small things -int ACT_BARNACLE_CHEW_SMALL_THINGS; // Chews small things - - -//----------------------------------------------------------------------------- -// Interactions -//----------------------------------------------------------------------------- -int g_interactionBarnacleVictimDangle = 0; -int g_interactionBarnacleVictimReleased = 0; -int g_interactionBarnacleVictimGrab = 0; -int g_interactionBarnacleVictimBite = 0; - -LINK_ENTITY_TO_CLASS( npc_barnacle, CNPC_Barnacle ); - -// Tongue Spring constants -#define BARNACLE_TONGUE_SPRING_CONSTANT_HANGING 10000 -#define BARNACLE_TONGUE_SPRING_CONSTANT_LIFTING 10000 -#define BARNACLE_TONGUE_SPRING_CONSTANT_LOWERING 7000 -#define BARNACLE_TONGUE_SPRING_DAMPING 20 -#define BARNACLE_TONGUE_TIP_MASS 100 -#define BARNACLE_TONGUE_MAX_LIFT_MASS 70 - -#define BARNACLE_BITE_DAMAGE_TO_PLAYER 15 -#define BARNACLE_DEAD_TONGUE_ALTITUDE 164 -#define BARNACLE_MIN_DEAD_TONGUE_CLEARANCE 78 - - -//========================================================= -// Monster's Anim Events Go Here -//========================================================= -#define BARNACLE_AE_PUKEGIB 2 -#define BARNACLE_AE_BITE 3 -#define BARNACLE_AE_SPIT 4 - -int AE_BARNACLE_PUKEGIB; -int AE_BARNACLE_BITE; -int AE_BARNACLE_SPIT; - -#if BARNACLE_USE_TONGUE_OFFSET -// Static variable that holds the difference between the player's -// eyepos and the tongue when he is seized -- used for offsetting -// the drawing of the tongue so that it doesn't appear to clip into -// the camera when we recenter the player. -const Vector CNPC_Barnacle::m_svPlayerHeldTipOffset(24,0,-8); -#endif - -//----------------------------------------------------------------------------- -// Purpose: Constructor -// Input : -// Output : -//----------------------------------------------------------------------------- -CNPC_Barnacle::CNPC_Barnacle(void) -{ - m_flRestUnitsAboveGround = 16.0f; - m_flNextBloodTime = -1.0f; -#ifndef _XBOX - m_nBloodColor = BLOOD_COLOR_YELLOW; -#endif - m_bPlayerWasStanding = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CNPC_Barnacle::~CNPC_Barnacle( void ) -{ - // Destroy the ragdoll->tongue tip constraint - if ( m_pConstraint ) - { - physenv->DestroyConstraint( m_pConstraint ); - m_pConstraint = NULL; - } -} - -/* - - input LetGo(void) : "Let go of anything I am holding." - - output OnGrab(string) : "When I attach my tongue to something" - output OnRelease(string) : "When I let go of something" -*/ - -BEGIN_DATADESC( CNPC_Barnacle ) - - DEFINE_FIELD( m_flAltitude, FIELD_FLOAT ), - DEFINE_FIELD( m_cGibs, FIELD_INTEGER ),// barnacle loads up on gibs each time it kills something. - DEFINE_FIELD( m_bLiftingPrey, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bSwallowingPrey, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flDigestFinish, FIELD_TIME ), - DEFINE_FIELD( m_bPlayedPullSound, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bPlayerWasStanding, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flVictimHeight, FIELD_FLOAT ), - DEFINE_FIELD( m_iGrabbedBoneIndex, FIELD_INTEGER ), - - DEFINE_FIELD( m_vecRoot, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecTip, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_hTongueRoot, FIELD_EHANDLE ), - DEFINE_FIELD( m_hTongueTip, FIELD_EHANDLE ), - DEFINE_FIELD( m_hRagdoll, FIELD_EHANDLE ), - DEFINE_AUTO_ARRAY( m_pRagdollBones, FIELD_MATRIX3X4_WORLDSPACE ), - DEFINE_PHYSPTR( m_pConstraint ), - DEFINE_KEYFIELD( m_flRestUnitsAboveGround, FIELD_FLOAT, "RestDist" ), - DEFINE_FIELD( m_nSpitAttachment, FIELD_INTEGER ), - DEFINE_FIELD( m_hLastSpitEnemy, FIELD_EHANDLE ), - DEFINE_FIELD( m_nShakeCount, FIELD_INTEGER ), - DEFINE_FIELD( m_flNextBloodTime, FIELD_TIME ), -#ifndef _XBOX - DEFINE_FIELD( m_nBloodColor, FIELD_INTEGER ), -#endif - DEFINE_FIELD( m_vecBloodPos, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_flBarnaclePullSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_flLocalTimer, FIELD_TIME ), - DEFINE_FIELD( m_vLastEnemyPos, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_flLastPull, FIELD_FLOAT ), - DEFINE_EMBEDDED( m_StuckTimer ), - - DEFINE_INPUTFUNC( FIELD_VOID, "DropTongue", InputDropTongue ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetDropTongueSpeed", InputSetDropTongueSpeed ), - -#ifdef HL2_EPISODIC - DEFINE_INPUTFUNC( FIELD_VOID, "LetGo", InputLetGo ), - DEFINE_OUTPUT( m_OnGrab, "OnGrab" ), - DEFINE_OUTPUT( m_OnRelease, "OnRelease" ), -#endif - - // Function pointers - DEFINE_THINKFUNC( BarnacleThink ), - DEFINE_THINKFUNC( WaitTillDead ), - - DEFINE_FIELD( m_bSwallowingBomb, FIELD_BOOLEAN ), - -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CNPC_Barnacle, DT_Barnacle ) - SendPropFloat( SENDINFO( m_flAltitude ), 0, SPROP_NOSCALE), - SendPropVector( SENDINFO( m_vecRoot ), 0, SPROP_COORD ), - SendPropVector( SENDINFO( m_vecTip ), 0, SPROP_COORD ), - SendPropVector( SENDINFO( m_vecTipDrawOffset ), 0, SPROP_NOSCALE ), -END_SEND_TABLE() - - -//========================================================= -// Classify - indicates this monster's place in the -// relationship table. -//========================================================= -Class_T CNPC_Barnacle::Classify ( void ) -{ - return CLASS_BARNACLE; -} - -//----------------------------------------------------------------------------- -// Purpose: Initialize absmin & absmax to the appropriate box -//----------------------------------------------------------------------------- -void CNPC_Barnacle::ComputeWorldSpaceSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs ) -{ - // Extend our bounding box downwards the length of the tongue - CollisionProp()->WorldSpaceAABB( pVecWorldMins, pVecWorldMaxs ); - - // We really care about the tongue tip. The altitude is not really relevant. - VectorMin( *pVecWorldMins, m_vecTip, *pVecWorldMins ); - VectorMax( *pVecWorldMaxs, m_vecTip, *pVecWorldMaxs ); - -// pVecWorldMins->z -= m_flAltitude; -} - -//========================================================= -// HandleAnimEvent - catches the monster-specific messages -// that occur when tagged animation frames are played. -// -// Returns number of events handled, 0 if none. -//========================================================= -void CNPC_Barnacle::HandleAnimEvent( animevent_t *pEvent ) -{ - if ( pEvent->event== AE_BARNACLE_PUKEGIB ) - { - CGib::SpawnSpecificGibs( this, 1, 50, 1, "models/gibs/hgibs_rib.mdl"); - return; - } - if ( pEvent->event == AE_BARNACLE_BITE ) - { - BitePrey(); - return; - } - if ( pEvent->event == AE_BARNACLE_SPIT ) - { - SpitPrey(); - return; - } - - BaseClass::HandleAnimEvent( pEvent ); -} - -//========================================================= -// Spawn -//========================================================= -void CNPC_Barnacle::Spawn() -{ - Precache( ); - - SetModel( "models/barnacle.mdl" ); - UTIL_SetSize( this, Vector(-16, -16, -40), Vector(16, 16, 0) ); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - CollisionProp()->SetSurroundingBoundsType( USE_GAME_CODE ); -#if HL2_EPISODIC // the episodic barnacle is solid, so it can be sawbladed. - SetMoveType( MOVETYPE_PUSH ); -#else - SetMoveType( MOVETYPE_NONE ); -#endif - SetBloodColor( BLOOD_COLOR_GREEN ); - m_iHealth = sk_barnacle_health.GetFloat(); - m_flFieldOfView = 0.5;// indicates the width of this monster's forward view cone ( as a dotproduct result ) - m_NPCState = NPC_STATE_NONE; - m_cGibs = 0; - m_bLiftingPrey = false; - m_bSwallowingPrey = false; - m_bSwallowingBomb = false; - m_flDigestFinish = 0; - m_takedamage = DAMAGE_YES; - m_pConstraint = NULL; - m_nShakeCount = 0; -#if HL2_EPISODIC // the episodic barnacle is solid, so it can be sawbladed. - IPhysicsObject *pPhys = VPhysicsInitShadow( false, false ); - if (pPhys) - { - pPhys->SetMass(500); - } -#endif - InitBoneControllers(); - InitTonguePosition(); - - // set eye position - SetDefaultEyeOffset(); - - - // Add some variation because we're often in large bunches - SetActivity( ACT_IDLE ); - SetPlaybackRate( random->RandomFloat( 0.8f, 1.2f ) ); - - SetThink ( &CNPC_Barnacle::BarnacleThink ); - SetNextThink( gpGlobals->curtime + 0.5f ); - - m_flBarnaclePullSpeed = BARNACLE_PULL_SPEED; - - //Do not have a shadow - AddEffects( EF_NOSHADOW ); - - AddFlag( FL_AIMTARGET ); -} - - -//----------------------------------------------------------------------------- -// Sets the tongue's height -//----------------------------------------------------------------------------- -void CNPC_Barnacle::SetAltitude( float flAltitude ) -{ - if ( HasSpawnFlags( SF_BARNACLE_AMBUSH ) ) - return; - - m_flAltitude = flAltitude; -} - -void CNPC_Barnacle::DropTongue( void ) -{ - if ( m_hTongueRoot ) - return; - - m_hTongueRoot = CBarnacleTongueTip::CreateTongueRoot( m_vecRoot, QAngle(90,0,0) ); - m_hTongueTip = CBarnacleTongueTip::CreateTongueTip( this, m_hTongueRoot, m_vecTip, QAngle(0,0,0) ); - m_nSpitAttachment = LookupAttachment( "StrikeHeadAttach" ); - Assert( m_hTongueRoot && m_hTongueTip ); - - RemoveSpawnFlags( SF_BARNACLE_AMBUSH ); -} -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Barnacle::Activate( void ) -{ - BaseClass::Activate(); - - if ( HasSpawnFlags( SF_BARNACLE_AMBUSH ) ) - return; - - // Create our tongue tips - if ( !m_hTongueRoot ) - { - DropTongue(); - } - else if ( GetEnemy() && IsEnemyAPlayer() && !m_pConstraint ) - { - IPhysicsObject *pPlayerPhys = GetEnemy()->VPhysicsGetObject(); - IPhysicsObject *pTonguePhys = m_hTongueTip->VPhysicsGetObject(); - - constraint_fixedparams_t fixed; - fixed.Defaults(); - fixed.InitWithCurrentObjectState( pTonguePhys, pPlayerPhys ); - fixed.constraint.Defaults(); - m_pConstraint = physenv->CreateFixedConstraint( pTonguePhys, pPlayerPhys, NULL, fixed ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int CNPC_Barnacle::OnTakeDamage_Alive( const CTakeDamageInfo &inputInfo ) -{ - CTakeDamageInfo info = inputInfo; - if ( info.GetDamageType() & DMG_CLUB ) - { - info.SetDamage( m_iHealth ); - } - - if ( GetActivity() == ACT_IDLE ) - { - SetActivity( ACT_SMALL_FLINCH ); - } - - if( hl2_episodic.GetBool() && info.GetAttacker() && info.GetAttacker()->Classify() == CLASS_PLAYER_ALLY_VITAL ) - { - if( FClassnameIs( info.GetAttacker(), "npc_alyx" ) ) - { - // Alyx does double damage to barnacles, so that she can save the - // player's life in a more timely fashion. (sjb) - info.ScaleDamage( 2.0f ); - } - } - - DropTongue(); - - return BaseClass::OnTakeDamage_Alive( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: Player has illuminated this NPC with the flashlight -//----------------------------------------------------------------------------- -void CNPC_Barnacle::PlayerHasIlluminatedNPC( CBasePlayer *pPlayer, float flDot ) -{ - // Create a sound to scare friendly allies away from the base on the barnacle - if( IsAlive() ) - { - CSoundEnt::InsertSound( SOUND_MOVE_AWAY | SOUND_CONTEXT_ALLIES_ONLY, m_vecTip, 60, FLASHLIGHT_NPC_CHECK_INTERVAL ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Initialize tongue position when first spawned -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_Barnacle::InitTonguePosition( void ) -{ - CBaseEntity *pTouchEnt; - float flLength; - - pTouchEnt = TongueTouchEnt( &flLength ); - SetAltitude( flLength ); - - Vector origin; - - GetAttachment( "TongueEnd", origin ); - - float flTongueAdj = origin.z - GetAbsOrigin().z; - m_vecRoot = origin - Vector(0,0,flTongueAdj); - m_vecTip.Set( m_vecRoot.Get() - Vector(0,0,(float)m_flAltitude) ); - CollisionProp()->MarkSurroundingBoundsDirty(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// TODO: The LostPrey(true) at the top of if ( m_hRagdoll ) isnt' quite right: -// it will make the barnacle drop anything that's shot on the way up. This is a -// quick fix for the antlions which crashed otherwise (they have somewhat anomalous -// ragdoll behaivor) but should be revisted. -//----------------------------------------------------------------------------- -void CNPC_Barnacle::BarnacleThink ( void ) -{ - CBaseEntity *pTouchEnt; - float flLength; - - SetNextThink( gpGlobals->curtime + 0.1f ); - - UpdateTongue(); - - // AI Disabled, don't do anything? - if ( CAI_BaseNPC::m_nDebugBits & bits_debugDisableAI ) - return; - - // Do we have an enemy? - if ( m_hRagdoll ) - { - if ( m_bLiftingPrey ) - { - if ( GetEnemy() ) - { - LiftPrey(); - } - else - { - LostPrey(true); - } - } - else if ( m_bSwallowingPrey ) - { - // Slowly swallowing the ragdoll - SwallowPrey(); - } - // Stay bloated as we digest - else if ( m_flDigestFinish ) - { - // Still digesting him> - if ( m_flDigestFinish > gpGlobals->curtime ) - { - if ( IsActivityFinished() ) - { - SetActivity( ACT_IDLE ); - } - - // bite prey every once in a while - if ( random->RandomInt(0,25) == 0 ) - { - EmitSound( "NPC_Barnacle.Digest" ); - } - } - else - { - // Finished digesting -#if HL2_EPISODIC - // have to save this off because LostPrey() resets it (and if we take damage before hitting that, - // then the dead thing will go flying) - bool poisoned = m_bSwallowingPoison; - - LostPrey( true ); // Remove all evidence - m_flDigestFinish = 0; - - if ( poisoned ) - { // hurt me - TakeDamage( CTakeDamageInfo( this, this, m_iHealth, DMG_ACID ) ); - } -#else - LostPrey( true ); // Remove all evidence - m_flDigestFinish = 0; -#endif - } - } - } - else if ( GetEnemy() ) - { - if ( m_bLiftingPrey || m_bSwallowingBomb == true ) - { - LiftPrey(); - } - // Stay bloated as we digest - else if ( m_flDigestFinish ) - { - // Still digesting him - if ( m_flDigestFinish > gpGlobals->curtime ) - { - if ( IsActivityFinished() ) - { - SetActivity( ACT_IDLE ); - } - - // bite prey every once in a while - if ( random->RandomInt(0,25) == 0 ) - { - EmitSound( "NPC_Barnacle.Digest" ); - } - } - else - { - // Finished digesting -#if HL2_EPISODIC - // have to save this off because LostPrey() resets it (and if we take damage before hitting that, - // then the dead thing will go flying) - bool poisoned = m_bSwallowingPoison; - - LostPrey( true ); // Remove all evidence - m_flDigestFinish = 0; - - if ( poisoned ) - { // hurt me - TakeDamage( CTakeDamageInfo( this, this, m_iHealth, DMG_ACID ) ); - } -#else - LostPrey( true ); // Remove all evidence - m_flDigestFinish = 0; -#endif - } - } - } - else - { - // Were we lifting prey? - if ( m_bSwallowingPrey || m_bLiftingPrey ) - { - // Something removed our prey. - LostPrey( false ); - } - - // barnacle has no prey right now, so just idle and check to see if anything is touching the tongue. - - // If idle and no nearby client, don't think so often - // NOTE: Use the surrounding bounds so that we'll think often event if the tongue - // tip is in the PVS but the body isn't - Vector vecSurroundMins, vecSurroundMaxs; - CollisionProp()->WorldSpaceSurroundingBounds( &vecSurroundMins, &vecSurroundMaxs ); - if ( !UTIL_FindClientInPVS( vecSurroundMins, vecSurroundMaxs ) ) - { - SetNextThink( gpGlobals->curtime + random->RandomFloat(1,1.5) ); // Stagger a bit to keep barnacles from thinking on the same frame - } - - if ( IsActivityFinished() && GetActivity() != ACT_IDLE ) - { - // this is done so barnacle will fidget. - - // Add some variation because we're often in large bunches - SetActivity( ACT_IDLE ); - SetPlaybackRate( random->RandomFloat( 0.8f, 1.2f ) ); - } - - if ( m_cGibs && random->RandomInt(0,99) == 1 ) - { - // cough up a gib. - CGib::SpawnSpecificGibs( this, 1, 50, 1, "models/gibs/hgibs_rib.mdl"); - m_cGibs--; - - EmitSound( "NPC_Barnacle.Digest" ); - } - - pTouchEnt = TongueTouchEnt( &flLength ); - - // If there's something under us, lower the tongue down so we can grab it - if ( m_flAltitude < flLength ) - { - float dt = gpGlobals->curtime - GetLastThink(); - SetAltitude( m_flAltitude + m_flBarnaclePullSpeed * dt ); - } - - // NOTE: SetAltitude above will change m_flAltitude, hence the second check - if ( m_flAltitude >= flLength ) - { - // If we're already low enough, try to grab. - bool bGrabbedTarget = false; - if ( ( pTouchEnt != NULL ) && ( pTouchEnt != m_hLastSpitEnemy.Get() ) ) - { - // tongue is fully extended, and is touching someone. - CBaseCombatCharacter *pBCC = dynamic_cast(pTouchEnt); - - if( CanPickup( pBCC ) ) - { - Vector vecGrabPos = pTouchEnt->EyePosition(); - if( !pBCC || pBCC->DispatchInteraction( g_interactionBarnacleVictimGrab, &vecGrabPos, this ) ) - { - EmitSound( "NPC_Barnacle.BreakNeck" ); - AttachTongueToTarget( pTouchEnt, vecGrabPos ); - - // Set the local timer to 60 seconds, which starts the lifting phase on - // the upshot of the sine wave which right away makes it more obvious - // that the player is being lifted. - m_flLocalTimer = 60.0f; - m_vLastEnemyPos = pTouchEnt->GetAbsOrigin(); - m_flLastPull = 0; - m_StuckTimer.Set(3.0); - bGrabbedTarget = true; - - // Set our touch flag so no one else tries to grab us this frame - pTouchEnt->AddEFlags( EFL_IS_BEING_LIFTED_BY_BARNACLE ); - } - } - } - - if ( !bGrabbedTarget ) - { - // Restore the hanging spring constant - if ( m_hTongueTip ) - { - m_hTongueTip->m_pSpring->SetSpringConstant( BARNACLE_TONGUE_SPRING_CONSTANT_HANGING ); - } - SetAltitude( flLength ); - } - } - } - - // NDebugOverlay::Box( GetAbsOrigin() - Vector( 0, 0, m_flAltitude ), Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), 255,255,255, 0, 0.1 ); - - StudioFrameAdvance(); - DispatchAnimEvents( this ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Barnacle::CanPickup( CBaseCombatCharacter *pBCC ) -{ - // Barnacle can pick this item up because it has already passed the filters - // in TongueTouchEnt. It just isn't an NPC or player and doesn't need further inspection. - if( !pBCC ) - return true; - - // Don't pickup turrets - if( FClassnameIs( pBCC, "npc_turret_floor" ) ) - return false; - - // Don't pick up a dead player or NPC - if( !pBCC->IsAlive() ) - return false; - - if( pBCC->IsPlayer() ) - { - CBasePlayer *pPlayer = dynamic_cast(pBCC); - - Assert( pPlayer != NULL ); - - // Don't pick up a player held by another barnacle - if( pPlayer->HasPhysicsFlag(PFLAG_ONBARNACLE) ) - return false; - } - else if ( pBCC->IsInAVehicle() ) - { - // Don't pluck an NPC from a vehicle. - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Allows the ragdoll to settle before biting it -//----------------------------------------------------------------------------- -bool CNPC_Barnacle::WaitForRagdollToSettle( float flBiteZOffset ) -{ - Vector vecVictimPos = GetEnemy()->GetAbsOrigin(); - - Vector vecCheckPos; - QAngle vecBoneAngles; - m_hRagdoll->GetBonePosition( m_iGrabbedBoneIndex, vecCheckPos, vecBoneAngles ); - - // Stop sucking while we wait for the ragdoll to settle - SetActivity( ACT_IDLE ); - - Vector vecVelocity; - AngularImpulse angVel; - float flDelta = 4.0; - - // Only bite if the target bone is in the right position. - Vector vecBitePoint = GetAbsOrigin(); - vecBitePoint.z -= flBiteZOffset; - - //NDebugOverlay::Box( vecBitePoint, -Vector(10,10,10), Vector(10,10,10), 0,255,0, 0, 0.1 ); - //NDebugOverlay::Line( vecBitePoint, vecCheckPos, 0, 255, 0, true, 0.1 ); - - if ( (vecBitePoint.x - vecCheckPos.x) > flDelta || (vecBitePoint.y - vecCheckPos.y) > flDelta ) - { - // I can't bite this critter because it's not lined up with me on the X/Y plane. If it is - // as close to my mouth as I can get it, I should drop it. - if( vecBitePoint.z - vecVictimPos.z < 72.0f ) - { - // A man-sized target has been pulled up to my mouth, but - // is not aligned for biting. Drop it. - SpitPrey(); - } - - return false; - } - - // Right height? - if ( (vecBitePoint.z - vecCheckPos.z) > flDelta ) - { - // Slowly raise / lower the target into the right position - if ( vecBitePoint.z > vecCheckPos.z ) - { - // Pull the victim towards the mouth - SetAltitude( m_flAltitude - 1 ); - vecVictimPos.z += 1; - } - else - { - // We pulled 'em up too far, so lower them a little - SetAltitude( m_flAltitude + 1 ); - vecVictimPos.z -= 1; - } - UTIL_SetOrigin ( GetEnemy(), vecVictimPos ); - return false; - } - - // Get the velocity of the bone we've grabbed, and only bite when it's not moving much - CStudioHdr *pStudioHdr = m_hRagdoll->GetModelPtr(); - mstudiobone_t *pBone = pStudioHdr->pBone( m_iGrabbedBoneIndex ); - int iBoneIndex = pBone->physicsbone; - ragdoll_t *pRagdoll = m_hRagdoll->GetRagdoll(); - IPhysicsObject *pRagdollPhys = pRagdoll->list[iBoneIndex].pObject; - pRagdollPhys->GetVelocity( &vecVelocity, &angVel ); - return ( vecVelocity.LengthSqr() < 20 ); -} - - -//----------------------------------------------------------------------------- -// Allows the physics prop to settle before biting it -//----------------------------------------------------------------------------- -bool CNPC_Barnacle::WaitForPhysicsObjectToSettle( float flBiteZOffset ) -{ - --m_nShakeCount; - if ( m_nShakeCount & 0x1 ) - { - SetAltitude( flBiteZOffset + 15 ); - } - else - { - SetAltitude( flBiteZOffset ); - } - - return ( m_nShakeCount <= 0 ); - - - /* - IPhysicsObject *pPhysicsObject = GetEnemy()->VPhysicsGetObject(); - - Vector vecVelocity; - AngularImpulse angVel; - pPhysicsObject->GetVelocity( &vecVelocity, &angVel ); - - return ( vecVelocity.LengthSqr() < 25 ); - */ -} - - -//----------------------------------------------------------------------------- -// Purpose: Make a horrific noise before we pull the prey stuck to our tongue up towards our mouth -//----------------------------------------------------------------------------- -void CNPC_Barnacle::PlayLiftingScream( float flBiteZOffset ) -{ - if ( !m_bPlayedPullSound && m_flAltitude < (flBiteZOffset + 100) ) - { - EmitSound( "NPC_Barnacle.Scream" ); - m_bPlayedPullSound = true; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Lift the prey stuck to our tongue up towards our mouth -//----------------------------------------------------------------------------- -void CNPC_Barnacle::PullEnemyTorwardsMouth( bool bAdjustEnemyOrigin ) -{ - CBaseEntity *pEnemy = GetEnemy(); - if ( pEnemy->IsPlayer() && pEnemy->GetMoveType() == MOVETYPE_NOCLIP ) - { - LostPrey( false ); - return; - } - - // Pull the victim towards the mouth - float dt = gpGlobals->curtime - GetLastThink(); - - // Assumes constant frame rate :| - m_flLocalTimer += dt; - - float flPull = fabs(sin( m_flLocalTimer * 5 )); - - flPull *= m_flBarnaclePullSpeed * dt; - - SetAltitude( m_flAltitude - flPull ); - - - if ( bAdjustEnemyOrigin ) - { - if ( m_flLastPull > 1.0 ) - { - if ( (pEnemy->GetAbsOrigin() - m_vLastEnemyPos).LengthSqr() < Square( m_flLastPull - 1.0 ) ) - { - if ( m_StuckTimer.Expired() ) - { - LostPrey( false ); - return; - } - } - else - { - m_StuckTimer.Set(3.0); - } - } - else - m_StuckTimer.Delay(dt); - - m_vLastEnemyPos = pEnemy->GetAbsOrigin(); - m_flLastPull = flPull; - - Vector vecNewPos = m_vLastEnemyPos; - // vecNewPos.z += flPull; - -#if 0 - // this is an example of one somewhat crude attempt to realign objects so that they are directly underneath - // the barnacle. It introduces unacceptable oscillation. - const float MAX_CENTERING_VELOCITY = 24.0f; - float distToMove = MAX_CENTERING_VELOCITY * dt; - Vector2D vToCenter = GetAbsOrigin().AsVector2D() - GetEnemy()->GetAbsOrigin().AsVector2D(); - float distFromCenter = vToCenter.NormalizeInPlace(); - - Msg("<%.3f,%.3f>\n",vToCenter.x,vToCenter.y); - - - if ( distFromCenter < distToMove ) - { - vecNewPos.x = GetAbsOrigin().x; - vecNewPos.y = GetAbsOrigin().y; - } - else - { - vToCenter *= distToMove; - vecNewPos.x += vToCenter.x; - vecNewPos.y += vToCenter.y; - // GetEnemy()->Teleport( &vecNewPos, NULL, NULL ); - } - -#endif - // recentering the player under the barnacle was tried in the code - // below, but then disabled for Orange Box ship because the viewmodel - // jitter became unacceptably noisy after other changes to physics - // and client. -#if 0 - // this technique is a little noisy and needs to be readdressed. - if (pEnemy->IsPlayer()) - { - Vector playerOrigin = GetEnemy()->GetAbsOrigin(); - Vector2D vToCenter = GetAbsOrigin().AsVector2D() - playerOrigin.AsVector2D(); - float distFromCenter = vToCenter.NormalizeInPlace(); - - // if we're off by more than a few inches - if ( distFromCenter > 6.0f ) - { - // get us there in a second - Vector desiredVelocity; - float distToMove = MIN(distFromCenter, 24.0f * dt); - desiredVelocity.x = vToCenter.x * distToMove; - desiredVelocity.y = vToCenter.y * distToMove; - desiredVelocity.z = 0; -#if 0 // here is a physical force-based way (too noisy!): - IPhysicsObject *pTonguePhys = m_hTongueTip->VPhysicsGetObject(); - pTonguePhys->ApplyForceCenter(desiredVelocity); -#else - vecNewPos = playerOrigin + desiredVelocity; - - // find how far we can actually transport the player - trace_t tr; - UTIL_TraceEntity( pEnemy, playerOrigin, vecNewPos, MASK_PLAYERSOLID, m_hTongueTip.Get(), pEnemy->GetCollisionGroup(), &tr ); - pEnemy->Teleport(&tr.endpos, NULL, &desiredVelocity); -#endif - } - } - -#endif - - // GetEnemy()->Teleport( &vecNewPos, NULL, NULL ); - - if( pEnemy->GetFlags() & FL_ONGROUND ) - { - // Try to fight OnGround - pEnemy->SetGravity( 0 ); - pEnemy->RemoveFlag( FL_ONGROUND ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Barnacle::UpdatePlayerConstraint( void ) -{ - // Check to see if the player's standing/ducking state has changed. - CBasePlayer *pPlayer = static_cast( GetEnemy() ); - bool bStanding = ( ( pPlayer->GetFlags() & FL_DUCKING ) == 0 ); - if ( bStanding == m_bPlayerWasStanding ) - return; - - // if player is on the ladder, disengage him - if ( pPlayer->GetMoveType() == MOVETYPE_LADDER ) - { - pPlayer->ExitLadder(); - } - - // Destroy the current constraint. - physenv->DestroyConstraint( m_pConstraint ); - m_pConstraint = NULL; - - if ( m_hTongueTip ) - { - // Create the new constraint for the standing/ducking player physics object. - IPhysicsObject *pPlayerPhys = pPlayer->VPhysicsGetObject(); - IPhysicsObject *pTonguePhys = m_hTongueTip->VPhysicsGetObject(); - - constraint_fixedparams_t fixed; - fixed.Defaults(); - fixed.InitWithCurrentObjectState( pTonguePhys, pPlayerPhys ); - fixed.constraint.Defaults(); - - m_pConstraint = physenv->CreateFixedConstraint( pTonguePhys, pPlayerPhys, NULL, fixed ); - } - - // Save state for the next check. - m_bPlayerWasStanding = bStanding; -} - -//----------------------------------------------------------------------------- -// Purpose: Lift the prey stuck to our tongue up towards our mouth -//----------------------------------------------------------------------------- -void CNPC_Barnacle::LiftPlayer( float flBiteZOffset ) -{ - // Add an additional height for the player to avoid view clipping - flBiteZOffset += 25.0; - - // Play a scream when we're almost within bite range - PlayLiftingScream( flBiteZOffset ); - - // Update player constraint. - UpdatePlayerConstraint(); - - // Figure out when the prey has reached our bite range use eye position to avoid - // clipping into the barnacle body - if ( GetAbsOrigin().z - GetEnemy()->EyePosition().z < flBiteZOffset) - { - m_bLiftingPrey = false; - - // Start the bite animation. The anim event in it will finish the job. - SetActivity( (Activity)ACT_BARNACLE_BITE_PLAYER ); - } - else - { - PullEnemyTorwardsMouth( true ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Lift the prey stuck to our tongue up towards our mouth -//----------------------------------------------------------------------------- -void CNPC_Barnacle::LiftNPC( float flBiteZOffset ) -{ - // Necessary to make the NPCs not do things like talk - GetEnemy()->AddEFlags( EFL_IS_BEING_LIFTED_BY_BARNACLE ); - - // Play a scream when we're almost within bite range - PlayLiftingScream( flBiteZOffset ); - - // Figure out when the prey has reached our bite range - if ( GetAbsOrigin().z - m_vecTip.Get().z < flBiteZOffset ) - { - m_bLiftingPrey = false; - - const Vector &vecSize = GetEnemy()->CollisionProp()->OBBSize(); - if ( vecSize.z < 40 ) - { - // Start the bite animation. The anim event in it will finish the job. - SetActivity( (Activity)ACT_BARNACLE_BITE_SMALL_THINGS ); - } - else - { - // Start the bite animation. The anim event in it will finish the job. - SetActivity( (Activity)ACT_BARNACLE_BITE_HUMAN ); - } - } - else - { - PullEnemyTorwardsMouth( true ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Lift the prey stuck to our tongue up towards our mouth -//----------------------------------------------------------------------------- -void CNPC_Barnacle::LiftRagdoll( float flBiteZOffset ) -{ - // Necessary to make the NPCs not do things like talk - GetEnemy()->AddEFlags( EFL_IS_BEING_LIFTED_BY_BARNACLE ); - - // Play a scream when we're almost within bite range - PlayLiftingScream( flBiteZOffset ); - - // Figure out when the prey has reached our bite range - if ( GetAbsOrigin().z - m_vecTip.Get().z < flBiteZOffset ) - { - // If we've got a ragdoll, wait until the bone is down below the mouth. - if ( !WaitForRagdollToSettle( flBiteZOffset ) ) - return; - - if ( GetEnemy()->Classify() == CLASS_ZOMBIE ) - { - // lifted the prey high enough to see it's a zombie. Spit it out. - if ( hl2_episodic.GetBool() ) - { - m_bLiftingPrey = false; - SetActivity( (Activity)ACT_BARNACLE_BITE_SMALL_THINGS ); - } - else - { - SpitPrey(); - } - return; - } - - m_bLiftingPrey = false; - - const Vector &vecSize = GetEnemy()->CollisionProp()->OBBSize(); - if ( vecSize.z < 40 ) - { - // Start the bite animation. The anim event in it will finish the job. - SetActivity( (Activity)ACT_BARNACLE_BITE_SMALL_THINGS ); - } - else - { - // Start the bite animation. The anim event in it will finish the job. - SetActivity( (Activity)ACT_BARNACLE_BITE_HUMAN ); - } - } - else - { - // Pull the victim towards the mouth - PullEnemyTorwardsMouth( false ); - - // Apply forces to the attached ragdoll based upon the animations of the enemy, if the enemy is still alive. - if ( GetEnemy()->IsAlive() ) - { - CBaseAnimating *pAnimating = dynamic_cast( GetEnemy() ); - - // Get the current bone matrix - /* - Vector pos[MAXSTUDIOBONES]; - Quaternion q[MAXSTUDIOBONES]; - matrix3x4_t pBoneToWorld[MAXSTUDIOBONES]; - CalcPoseSingle( pStudioHdr, pos, q, pAnimating->GetSequence(), pAnimating->m_flCycle, pAnimating->GetPoseParameterArray(), BONE_USED_BY_ANYTHING ); - Studio_BuildMatrices( pStudioHdr, vec3_angle, vec3_origin, pos, q, -1, pBoneToWorld, BONE_USED_BY_ANYTHING ); - - - // Apply the forces to the ragdoll - RagdollApplyAnimationAsVelocity( *(m_hRagdoll->GetRagdoll()), pBoneToWorld ); - */ - - // Get the current bone matrix - matrix3x4_t pBoneToWorld[MAXSTUDIOBONES]; - pAnimating->SetupBones( pBoneToWorld, BONE_USED_BY_ANYTHING ); - - // Apply the forces to the ragdoll - RagdollApplyAnimationAsVelocity( *(m_hRagdoll->GetRagdoll()), m_pRagdollBones, pBoneToWorld, 0.2 ); - - // Store off the current bone matrix for next time - pAnimating->SetupBones( m_pRagdollBones, BONE_USED_BY_ANYTHING ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Lift the prey stuck to our tongue up towards our mouth -//----------------------------------------------------------------------------- -void CNPC_Barnacle::LiftPhysicsObject( float flBiteZOffset ) -{ - CBaseEntity *pVictim = GetEnemy(); - - // Bite a little higher up, since the bits point is the tip of the tongue - flBiteZOffset -= 5.0f; - - //NDebugOverlay::Box( vecCheckPos, -Vector(10,10,10), Vector(10,10,10), 255,255,255, 0, 0.1 ); - - // Play a scream when we're almost within bite range - PlayLiftingScream( flBiteZOffset ); - - // Figure out when the prey has reached our bite range - if ( GetAbsOrigin().z - m_vecTip.Get().z < flBiteZOffset ) // then yes, let's chomp - { - if ( m_hTongueTip ) - { - m_hTongueTip->m_pSpring->SetSpringConstant( BARNACLE_TONGUE_SPRING_CONSTANT_HANGING ); - } - - // Wait until the physics object stops flailing - if ( !WaitForPhysicsObjectToSettle( flBiteZOffset ) ) - return; - - // Necessary for good +use interactions - pVictim->RemoveEFlags( EFL_IS_BEING_LIFTED_BY_BARNACLE ); - - // If we got a physics prop, wait until the thing has settled down - m_bLiftingPrey = false; - - if ( hl2_episodic.GetBool() ) - { - CBounceBomb *pBounce = dynamic_cast( pVictim ); - - if ( pBounce ) - { - if ( m_bSwallowingBomb == true ) - { - pBounce->ExplodeThink(); - return; - } - - SetActivity( (Activity)ACT_BARNACLE_BITE_SMALL_THINGS ); - } - else - { - // Start the bite animation. The anim event in it will finish the job. - SetActivity( (Activity)ACT_BARNACLE_TASTE_SPIT ); - } - } - else - { - // Start the bite animation. The anim event in it will finish the job. - SetActivity( (Activity)ACT_BARNACLE_TASTE_SPIT ); - } - -#ifdef HL2_EPISODIC - // if the object is a combatclass, send it a chomp interaction in case it wants to respond to that - // in some nonstandard way. - CBaseCombatCharacter *pBCC = dynamic_cast(pVictim); - if( pBCC ) - { - Vector tipPos = m_vecTip.Get(); - - pBCC->DispatchInteraction( g_interactionBarnacleVictimBite, &tipPos, this ); - } -#endif - } - else - { - // Necessary for good +use interactions - pVictim->AddEFlags( EFL_IS_BEING_LIFTED_BY_BARNACLE ); - - // Pull the victim towards the mouth - PullEnemyTorwardsMouth( false ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Lift the prey stuck to our tongue up towards our mouth -//----------------------------------------------------------------------------- -void CNPC_Barnacle::LiftPrey( void ) -{ - CBaseEntity *pVictim = GetEnemy(); - Assert( pVictim ); - - // Drop the prey if it's been obscured by something - trace_t tr; - AI_TraceLine( WorldSpaceCenter(), pVictim->WorldSpaceCenter(), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - bool bEnemyIsNPC = IsEnemyAnNPC() && !IsEnemyARagdoll(); - if ( ( bEnemyIsNPC && !pVictim->IsAlive() ) || (tr.fraction < 1.0 && tr.m_pEnt != pVictim && tr.m_pEnt != m_hRagdoll) ) - { - if ( !GetEnemy()->IsPlayer() ) - { - // ignore the object so we don't get into a loop of trying to pick it up. - m_hLastSpitEnemy = GetEnemy(); - } - LostPrey( false ); - return; - } - - // Height from the barnacle's origin to the point at which it bites - float flBiteZOffset = 60.0; - - if ( IsEnemyAPlayer() ) - { - LiftPlayer(flBiteZOffset); - } - else if ( IsEnemyARagdoll() ) - { - LiftRagdoll(flBiteZOffset); - } - else if ( bEnemyIsNPC ) - { - LiftNPC(flBiteZOffset); - } - else - { - LiftPhysicsObject(flBiteZOffset); - } - - if ( m_hRagdoll ) - { - QAngle newAngles( 0, m_hRagdoll->GetAbsAngles()[YAW], 0 ); - - Vector centerDelta = m_hRagdoll->WorldSpaceCenter() - GetEnemy()->WorldSpaceCenter(); - Vector newOrigin = GetEnemy()->GetAbsOrigin() + centerDelta; - GetEnemy()->SetAbsOrigin( newOrigin ); - GetEnemy()->SetAbsAngles( newAngles ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Attach a serverside ragdoll prop for the specified entity to our tongue -//----------------------------------------------------------------------------- -CRagdollProp *CNPC_Barnacle::AttachRagdollToTongue( CBaseAnimating *pAnimating ) -{ - // Find his head bone - m_iGrabbedBoneIndex = -1; - Vector vecNeckOffset; - - if ( m_hTongueTip ) - { - vecNeckOffset = (pAnimating->EyePosition() - m_hTongueTip->GetAbsOrigin()); - } - - CStudioHdr *pHdr = pAnimating->GetModelPtr(); - if ( pHdr ) - { - int set = pAnimating->GetHitboxSet(); - for( int i = 0; i < pHdr->iHitboxCount(set); i++ ) - { - mstudiobbox_t *pBox = pHdr->pHitbox( i, set ); - if ( !pBox ) - continue; - - if ( pBox->group == HITGROUP_HEAD ) - { - m_iGrabbedBoneIndex = pBox->bone; - break; - } - } - } - - // HACK: Until we have correctly assigned hitgroups on our models, lookup the bones - // for the models that we know are in the barnacle maps. - //m_iGrabbedBoneIndex = pAnimating->LookupBone( "Bip01 L Foot" ); - if ( m_iGrabbedBoneIndex == -1 ) - { - // Citizens, Conscripts - m_iGrabbedBoneIndex = pAnimating->LookupBone( "Bip01 Head" ); - } - if ( m_iGrabbedBoneIndex == -1 ) - { - // Metrocops, Combine soldiers - m_iGrabbedBoneIndex = pAnimating->LookupBone( "ValveBiped.Bip01_Head1" ); - } - if ( m_iGrabbedBoneIndex == -1 ) - { - // Vortigaunts - m_iGrabbedBoneIndex = pAnimating->LookupBone( "ValveBiped.head" ); - } - if ( m_iGrabbedBoneIndex == -1 ) - { - // Bullsquids - m_iGrabbedBoneIndex = pAnimating->LookupBone( "Bullsquid.Head_Bone1" ); - } - - if ( m_iGrabbedBoneIndex == -1 ) - { - // Just use the first bone - m_iGrabbedBoneIndex = 0; - } - - // Move the tip to the bone - Vector vecBonePos; - QAngle vecBoneAngles; - pAnimating->GetBonePosition( m_iGrabbedBoneIndex, vecBonePos, vecBoneAngles ); - - if ( m_hTongueTip ) - { - m_hTongueTip->Teleport( &vecBonePos, NULL, NULL ); - } - - //NDebugOverlay::Box( vecBonePos, -Vector(5,5,5), Vector(5,5,5), 255,255,255, 0, 10.0 ); - - // Create the ragdoll attached to tongue - IPhysicsObject *pTonguePhysObject = m_hTongueTip->VPhysicsGetObject(); - CRagdollProp *pRagdoll = CreateServerRagdollAttached( pAnimating, vec3_origin, -1, COLLISION_GROUP_NONE, pTonguePhysObject, m_hTongueTip, 0, vecBonePos, m_iGrabbedBoneIndex, vec3_origin ); - if ( pRagdoll ) - { -#if HL2_EPISODIC - PhysEnableEntityCollisions( this, pAnimating ); - PhysDisableEntityCollisions( this, pRagdoll ); -#endif - - pRagdoll->DisableAutoFade(); - pRagdoll->SetThink( NULL ); - } - - return pRagdoll; -} - -void CNPC_Barnacle::InputSetDropTongueSpeed( inputdata_t &inputdata ) -{ - m_flBarnaclePullSpeed = inputdata.value.Int(); -} - -void CNPC_Barnacle::InputDropTongue( inputdata_t &inputdata ) -{ - DropTongue(); -} - -//----------------------------------------------------------------------------- -// Purpose: Grab the specified target with our tongue -//----------------------------------------------------------------------------- -void CNPC_Barnacle::AttachTongueToTarget( CBaseEntity *pTouchEnt, Vector vecGrabPos ) -{ - -#if HL2_EPISODIC - m_OnGrab.Set( pTouchEnt, this, this ); -#endif - - // Reset this valricue each time we attach prey. If it needs to be reduced, code below will do so. - m_flBarnaclePullSpeed = BARNACLE_PULL_SPEED; - - if ( RandomFloat(0,1) > 0.5 ) - { - EmitSound( "NPC_Barnacle.PullPant" ); - } - else - { - EmitSound( "NPC_Barnacle.TongueStretch" ); - } - - SetActivity( (Activity)ACT_BARNACLE_SLURP ); - - // Get the player out of the vehicle he's in. - if ( pTouchEnt->IsPlayer() ) - { - CBasePlayer *pPlayer = static_cast(pTouchEnt); - if ( pPlayer->IsInAVehicle() ) - { - pPlayer->LeaveVehicle( pPlayer->GetAbsOrigin(), pPlayer->GetAbsAngles() ); - - // The player could have warped through the tongue while on a high-speed vehicle. - // Move him back under the barnacle. - Vector vecDelta; - VectorSubtract( pPlayer->GetAbsOrigin(), GetAbsOrigin(), vecDelta ); - vecDelta.z = 0.0f; - float flDist = VectorNormalize( vecDelta ); - if ( flDist > 20 ) - { - Vector vecNewPos; - VectorMA( GetAbsOrigin(), 20, vecDelta, vecNewPos ); - vecNewPos.z = pPlayer->GetAbsOrigin().z; - pPlayer->SetAbsOrigin( vecNewPos ); - } - } - - m_bPlayerWasStanding = ( ( pPlayer->GetFlags() & FL_DUCKING ) == 0 ); - } - - SetEnemy( pTouchEnt ); -#if HL2_EPISODIC - // Disable collision between myself and the obejct I've seized. - PhysDisableEntityCollisions( this, pTouchEnt ); -#endif - - // teleporting the player in this way is illegitimate -- try it in third person to see the problem - if ( /* pTouchEnt->IsPlayer() || */ pTouchEnt->MyNPCPointer() ) - { - Vector origin = GetAbsOrigin(); - origin.z = pTouchEnt->GetAbsOrigin().z; - - CTraceFilterSkipTwoEntities traceFilter( this, pTouchEnt, COLLISION_GROUP_NONE ); - trace_t placementTrace; - UTIL_TraceHull( origin, origin, pTouchEnt->WorldAlignMins(), pTouchEnt->WorldAlignMaxs(), MASK_NPCSOLID, &traceFilter, &placementTrace ); - if ( placementTrace.startsolid ) - { - UTIL_TraceHull( origin + Vector(0, 0, 24), origin, pTouchEnt->WorldAlignMins(), pTouchEnt->WorldAlignMaxs(), MASK_NPCSOLID, &traceFilter, &placementTrace ); - if ( !placementTrace.startsolid ) - { - pTouchEnt->SetAbsOrigin( placementTrace.endpos ); - // pTouchEnt->Teleport( &placementTrace.endpos, NULL, NULL ); - } - } - else - { - pTouchEnt->SetAbsOrigin( origin ); - // pTouchEnt->Teleport( &origin, NULL, NULL ); - } - } - - m_nShakeCount = 6; - m_bLiftingPrey = true;// indicate that we should be lifting prey. - SetAltitude( (GetAbsOrigin().z - vecGrabPos.z) ); - m_bPlayedPullSound = false; - - CBaseAnimating *pAnimating = dynamic_cast(pTouchEnt); - - if ( IsEnemyAPlayer() || IsEnemyAPhysicsObject() ) - { - // The player (and phys objects) doesn't ragdoll, so just grab him and pull him up manually - IPhysicsObject *pPlayerPhys = pTouchEnt->VPhysicsGetObject(); - IPhysicsObject *pTonguePhys = m_hTongueTip->VPhysicsGetObject(); - - Vector vecGrabPos; - if ( pTouchEnt->IsPlayer() ) - { - vecGrabPos = pTouchEnt->EyePosition(); -#if BARNACLE_USE_TONGUE_OFFSET - VectorRotate( m_svPlayerHeldTipOffset, pTouchEnt->EntityToWorldTransform(), m_vecTipDrawOffset.GetForModify() ); - m_vecTipDrawOffset.GetForModify().z = m_svPlayerHeldTipOffset.z; -#endif - // pTonguePhys->GetPosition(&vecGrabPos,NULL); - } - else - { - VectorSubtract( m_vecTip, pTouchEnt->GetAbsOrigin(), vecGrabPos ); - VectorNormalize( vecGrabPos ); - vecGrabPos = physcollision->CollideGetExtent( pPlayerPhys->GetCollide(), pTouchEnt->GetAbsOrigin(), pTouchEnt->GetAbsAngles(), vecGrabPos ); -#if BARNACLE_USE_TONGUE_OFFSET - m_vecTipDrawOffset.GetForModify().Zero(); -#endif - } - - m_hTongueTip->Teleport( &vecGrabPos, NULL, NULL ); - - float flDist = (vecGrabPos - GetAbsOrigin() ).Length(); - float flTime = flDist / m_flBarnaclePullSpeed; - - // If this object would be pulled in too quickly, change the pull speed. - if( flTime < BARNACLE_MIN_PULL_TIME ) - { - m_flBarnaclePullSpeed = flDist / BARNACLE_MIN_PULL_TIME; - } - - constraint_fixedparams_t fixed; - fixed.Defaults(); - fixed.InitWithCurrentObjectState( pTonguePhys, pPlayerPhys ); - fixed.constraint.Defaults(); - - /* -You can use this stanza to try to counterplace the constraint on the player's head so he gets hauled sideways to the right place on the barnacle, but it is better to just move the tongue before attachment. - if ( IsEnemyAPlayer() ) - { - Vector2D vToCenter = GetAbsOrigin().AsVector2D() - pTouchEnt->EyePosition().AsVector2D(); - fixed.attachedRefXform[0][3] -= vToCenter.x ; - fixed.attachedRefXform[1][3] -= vToCenter.y ; - } - */ - - m_pConstraint = physenv->CreateFixedConstraint( pTonguePhys, pPlayerPhys, NULL, fixed ); - - // Increase the tongue's spring constant while lifting - m_hTongueTip->m_pSpring->SetSpringConstant( BARNACLE_TONGUE_SPRING_CONSTANT_LIFTING ); - UpdateTongue(); - - return; - } - - // NPC case... - pAnimating->InvalidateBoneCache(); - - // Make a ragdoll for the guy, and hide him. - pTouchEnt->AddSolidFlags( FSOLID_NOT_SOLID ); - - m_hRagdoll = AttachRagdollToTongue( pAnimating ); - m_hRagdoll->SetDamageEntity( pAnimating ); - - // Make it try to blend out of ragdoll on the client on deletion - // NOTE: This isn't fully implemented, so disable - //m_hRagdoll->SetUnragdoll( pAnimating ); - - // Apply the target's current velocity to each of the ragdoll's bones - Vector vecVelocity = pAnimating->GetGroundSpeedVelocity() * 0.5; - ragdoll_t *pRagdoll = m_hRagdoll->GetRagdoll(); - - // barnacle might let go if ragdoll is separated - so increase the separation checking a bit - constraint_groupparams_t params; - pRagdoll->pGroup->GetErrorParams( ¶ms ); - params.minErrorTicks = MIN( params.minErrorTicks, 5 ); - pRagdoll->pGroup->SetErrorParams( params ); - - for ( int i = 0; i < pRagdoll->listCount; i++ ) - { - pRagdoll->list[i].pObject->AddVelocity( &vecVelocity, NULL ); - } - - if ( npc_barnacle_swallow.GetBool() ) - { - m_hRagdoll->SetOverlaySequence( ACT_GESTURE_BARNACLE_STRANGLE ); - m_hRagdoll->SetBlendWeight( 1.0f ); - } - - // Now hide the actual enemy - pTouchEnt->AddEffects( EF_NODRAW ); - - // Increase the tongue's spring constant while lifting - m_hTongueTip->m_pSpring->SetSpringConstant( BARNACLE_TONGUE_SPRING_CONSTANT_LIFTING ); - UpdateTongue(); - - // Store off the current bone matrix so we have it next frame - pAnimating->SetupBones( m_pRagdollBones, BONE_USED_BY_ANYTHING ); -} - - -//----------------------------------------------------------------------------- -// Spit out the prey; add physics force! -//----------------------------------------------------------------------------- -void CNPC_Barnacle::SpitPrey() -{ - if ( GetEnemy() ) - { - IPhysicsObject *pObject = GetEnemy()->VPhysicsGetObject(); - if (pObject) - { - Vector vecPosition, force; - GetAttachment( m_nSpitAttachment, vecPosition, &force ); - - force *= pObject->GetMass() * 50.0f; - pObject->ApplyForceOffset( force, vec3_origin ); - } - - m_hLastSpitEnemy = GetEnemy(); - } - - LostPrey( false ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Prey is in position, bite them and start swallowing them -//----------------------------------------------------------------------------- -void CNPC_Barnacle::BitePrey( void ) -{ - Assert( GetEnemy() ); - - CBaseCombatCharacter *pVictim = GetEnemyCombatCharacterPointer(); - -#ifdef HL2_EPISODIC - if ( pVictim == NULL ) - { - if ( GetEnemy() ) - { - CBounceBomb *pBounce = dynamic_cast( GetEnemy() ); - - if ( pBounce ) - { - // Stop the ragdoll moving and start to pull the sucker up into our mouth - m_bSwallowingPrey = true; - m_bSwallowingBomb = true; - IPhysicsObject *pTonguePhys = m_hTongueTip->VPhysicsGetObject(); - - // Stop the tongue's spring getting in the way of swallowing - m_hTongueTip->m_pSpring->SetSpringConstant( 0 ); - - // Switch the tongue tip to shadow and drag it up - pTonguePhys->SetShadow( 1e4, 1e4, false, false ); - pTonguePhys->UpdateShadow( m_hTongueTip->GetAbsOrigin(), m_hTongueTip->GetAbsAngles(), false, 0 ); - m_hTongueTip->SetMoveType( MOVETYPE_NOCLIP ); - m_hTongueTip->SetAbsVelocity( Vector(0,0,32) ); - - - SetAltitude( (GetAbsOrigin().z - m_hTongueTip->GetAbsOrigin().z) ); - } - } - - return; - } -#endif - - Assert( pVictim ); - if ( !pVictim ) - { - return; - } - - EmitSound( "NPC_Barnacle.FinalBite" ); - - m_flVictimHeight = GetEnemy()->WorldAlignSize().z; - - // Kill the victim instantly - int iDamageType = DMG_SLASH | DMG_ALWAYSGIB; - int nDamage; - if ( !pVictim->IsPlayer() ) - { - iDamageType |= DMG_ALWAYSGIB; - nDamage = pVictim->m_iHealth; - } - else - { - nDamage = BARNACLE_BITE_DAMAGE_TO_PLAYER; - } - - if ( m_hRagdoll ) - { - // We've got a ragdoll, so prevent this creating another one - iDamageType |= DMG_REMOVENORAGDOLL; - m_hRagdoll->SetDamageEntity( NULL ); - } - - -#if HL2_EPISODIC - m_bSwallowingPoison = IsPoisonous(pVictim); - unsigned int enemyClass = GetEnemy()->Classify(); -#endif - // DMG_CRUSH because we don't wan't to impart physics forces - - pVictim->TakeDamage( CTakeDamageInfo( this, this, nDamage, iDamageType | DMG_CRUSH ) ); - - m_cGibs = 3; - - // In episodic, bite the zombie's headcrab off & drop the body -#ifdef HL2_EPISODIC - - if ( enemyClass == CLASS_ZOMBIE ) - { - if ( m_hRagdoll ) - { - m_hRagdoll->SetBodygroup( ZOMBIE_BODYGROUP_HEADCRAB, false ); - DetachAttachedRagdoll( m_hRagdoll ); - m_hLastSpitEnemy = m_hRagdoll.Get(); - m_hRagdoll->EmitSound( "NPC_HeadCrab.Die" ); - m_hRagdoll = NULL; - } - - // Create some blood to hide the vanishing headcrab - Vector vecBloodPos; - CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 0.0f ), &vecBloodPos ); - UTIL_BloodSpray( vecBloodPos, Vector(0,0,-1), GetEnemy()->BloodColor(), 8, FX_BLOODSPRAY_ALL ); - - m_flDigestFinish = gpGlobals->curtime + 10.0; - return; - } - - // in episodic, where barnacles can eat antlions, vanish the ragdoll because the gibs will spray everywhere - // and hide it. - if ( enemyClass == CLASS_ANTLION ) - { - -#ifndef _XBOX - m_nBloodColor = pVictim->BloodColor(); -#endif - m_flNextBloodTime = 0.0f; - SprayBlood(); - - m_flDigestFinish = gpGlobals->curtime + 10.0; - if (m_hRagdoll) - { - UTIL_Remove( m_hRagdoll ); - } - - - if ( m_bSwallowingPoison ) - { // hurt me - TakeDamage( CTakeDamageInfo( this, this, m_iHealth, DMG_ACID ) ); - } - - return; - } - -#endif - - // Players are never swallowed, nor is anything we don't have a ragdoll for - if ( !m_hRagdoll || pVictim->IsPlayer() ) - { - if ( !pVictim->IsPlayer() || pVictim->GetHealth() <= 0 ) - { - LostPrey( false ); - } - return; - } - - // Stop the ragdoll moving and start to pull the sucker up into our mouth - m_bSwallowingPrey = true; - IPhysicsObject *pTonguePhys = m_hTongueTip->VPhysicsGetObject(); - - // Make it nonsolid to the world so we can pull it through the roof - PhysDisableEntityCollisions( m_hRagdoll->VPhysicsGetObject(), g_PhysWorldObject ); - - // Stop the tongue's spring getting in the way of swallowing - m_hTongueTip->m_pSpring->SetSpringConstant( 0 ); - - // Switch the tongue tip to shadow and drag it up - pTonguePhys->SetShadow( 1e4, 1e4, false, false ); - pTonguePhys->UpdateShadow( m_hTongueTip->GetAbsOrigin(), m_hTongueTip->GetAbsAngles(), false, 0 ); - m_hTongueTip->SetMoveType( MOVETYPE_NOCLIP ); - m_hTongueTip->SetAbsVelocity( Vector(0,0,32) ); - - SetAltitude( (GetAbsOrigin().z - m_hTongueTip->GetAbsOrigin().z) ); - - if ( !npc_barnacle_swallow.GetBool() ) - return; - - // Because the victim is dead, remember the blood color - m_flNextBloodTime = 0.0f; - - // NOTE: This was too confusing to people with the more recognizable blood -- jdw -#ifndef _XBOX - m_nBloodColor = pVictim->BloodColor(); -#endif - CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 0.0f ), &m_vecBloodPos ); - - // m_hRagdoll->SetOverlaySequence( ACT_DIE_BARNACLE_SWALLOW ); - m_hRagdoll->SetBlendWeight( 0.0f ); - - SprayBlood(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Barnacle::SprayBlood() -{ - if ( gpGlobals->curtime < m_flNextBloodTime ) - return; - - m_flNextBloodTime = gpGlobals->curtime + 0.2f; - - Vector bloodDir = RandomVector( -1.0f, 1.0f ); - bloodDir.z = -fabs( bloodDir.z ); - - Vector jitterPos = RandomVector( -8, 8 ); - jitterPos.z = 0.0f; - -#ifndef _XBOX - UTIL_BloodSpray( m_vecBloodPos + jitterPos, Vector( 0,0,-1), - m_nBloodColor, RandomInt( 4, 8 ), RandomInt(0,2) == 0 ? FX_BLOODSPRAY_ALL : FX_BLOODSPRAY_CLOUD ); -#else - UTIL_BloodSpray( m_vecBloodPos + jitterPos, Vector( 0,0,-1), - BLOOD_COLOR_YELLOW, RandomInt( 4, 8 ), RandomInt(0,2) == 0 ? FX_BLOODSPRAY_ALL : FX_BLOODSPRAY_CLOUD ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Slowly swallow the prey whole. Only used on humanoids. -//----------------------------------------------------------------------------- -void CNPC_Barnacle::SwallowPrey( void ) -{ - if ( IsActivityFinished() ) - { - if (GetActivity() == ACT_BARNACLE_BITE_HUMAN ) - { - SetActivity( (Activity)ACT_BARNACLE_CHEW_HUMAN ); - } - else - { - SetActivity( (Activity)ACT_BARNACLE_CHEW_SMALL_THINGS ); - } - } - - // Move the body up slowly - Vector vecSwallowPos = m_hTongueTip->GetAbsOrigin(); - vecSwallowPos.z -= m_flVictimHeight; - //NDebugOverlay::Box( vecSwallowPos, -Vector(5,5,5), Vector(5,5,5), 255,255,255, 0, 0.1 ); - - // bite prey every once in a while - if ( random->RandomInt(0,25) == 0 ) - { - EmitSound( "NPC_Barnacle.Digest" ); - } - - // Fully swallowed it? - float flDistanceToGo = GetAbsOrigin().z - vecSwallowPos.z; - if ( flDistanceToGo <= 0 ) - { - // He's dead jim - m_bSwallowingPrey = false; - m_hTongueTip->SetAbsVelocity( vec3_origin ); - -#if HL2_EPISODIC - // digest poisonous things for just a moment before being killed by them (it looks wierd if it's instant) - m_flDigestFinish = gpGlobals->curtime + m_bSwallowingPoison ? 0.48f : 10.0f; -#else - m_flDigestFinish = gpGlobals->curtime + 10.0; -#endif - } - - if ( npc_barnacle_swallow.GetBool() ) - { - SprayBlood(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Remove the fake ragdoll and bring the actual enemy back in view -//----------------------------------------------------------------------------- -void CNPC_Barnacle::RemoveRagdoll( bool bDestroyRagdoll ) -{ - // Destroy the tongue tip constraint - if ( m_pConstraint ) - { - physenv->DestroyConstraint( m_pConstraint ); - m_pConstraint = NULL; - } - - // Remove the ragdoll - if ( m_hRagdoll ) - { - // Only destroy the ragdoll if told to. We might be just dropping - // the ragdoll because the target was killed on the way up. - m_hRagdoll->SetDamageEntity( NULL ); - if ( npc_barnacle_swallow.GetBool() ) - { - m_hRagdoll->SetThink( NULL ); - m_hRagdoll->SetBlendWeight( 1.0f ); - } - DetachAttachedRagdoll( m_hRagdoll ); - if ( bDestroyRagdoll ) - { - UTIL_Remove( m_hRagdoll ); - } - m_hRagdoll = NULL; - - // Reduce the spring constant while we lower - m_hTongueTip->m_pSpring->SetSpringConstant( BARNACLE_TONGUE_SPRING_CONSTANT_LOWERING ); - - // Unhide the enemy - if ( GetEnemy() ) - { - GetEnemy()->RemoveEffects( EF_NODRAW ); - GetEnemy()->RemoveSolidFlags( FSOLID_NOT_SOLID ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: For some reason (he was killed, etc) we lost the prey we were dragging towards our mouth. -//----------------------------------------------------------------------------- -void CNPC_Barnacle::LostPrey( bool bRemoveRagdoll ) -{ - -#if HL2_EPISODIC - m_OnRelease.Set( GetEnemy(), this, this ); -#endif - - CBaseEntity * const pEnemy = GetEnemy(); - - if ( pEnemy ) - { -#if HL2_EPISODIC - PhysEnableEntityCollisions( this, pEnemy ); -#endif - - //No one survives being snatched by a barnacle anymore, so leave - // this flag set so that their entity gets removed. - //GetEnemy()->RemoveEFlags( EFL_IS_BEING_LIFTED_BY_BARNACLE ); - CBaseCombatCharacter *pVictim = GetEnemyCombatCharacterPointer(); - if ( pVictim ) - { - pVictim->DispatchInteraction( g_interactionBarnacleVictimReleased, NULL, this ); - pVictim->RemoveEFlags( EFL_IS_BEING_LIFTED_BY_BARNACLE ); - - if ( m_hRagdoll ) - { - QAngle newAngles( 0, m_hRagdoll->GetAbsAngles()[ YAW ], 0 ); - - Vector centerDelta = m_hRagdoll->WorldSpaceCenter() - pEnemy->WorldSpaceCenter(); - Vector newOrigin = pEnemy->GetAbsOrigin() + centerDelta; - pEnemy->SetAbsOrigin( newOrigin ); - - pVictim->SetAbsAngles( newAngles ); - } - pVictim->SetGroundEntity( NULL ); - } - else if ( IsEnemyAPhysicsObject() ) - { - // If we're a physics object, then we need to clear this flag - pEnemy->RemoveEFlags( EFL_IS_BEING_LIFTED_BY_BARNACLE ); - } - } - - - RemoveRagdoll( bRemoveRagdoll ); - m_bLiftingPrey = false; - m_bSwallowingPrey = false; -#if HL2_EPISODIC - m_bSwallowingPoison = false; -#endif - SetEnemy( NULL ); - - - m_vecTipDrawOffset.GetForModify().Zero(); - - if ( m_hTongueTip ) - { - // Remove our tongue's shadow object, in case we just finished swallowing something - IPhysicsObject *pPhysicsObject = m_hTongueTip->VPhysicsGetObject(); - if ( pPhysicsObject && pPhysicsObject->GetShadowController() ) - { - Vector vecCenter = WorldSpaceCenter(); - m_hTongueTip->Teleport( &vecCenter, NULL, &vec3_origin ); - - // Reduce the spring constant while we lower - m_hTongueTip->m_pSpring->SetSpringConstant( BARNACLE_TONGUE_SPRING_CONSTANT_LOWERING ); - - // Start colliding with the world again - pPhysicsObject->RemoveShadowController(); - m_hTongueTip->SetMoveType( MOVETYPE_VPHYSICS ); - pPhysicsObject->EnableMotion( true ); - pPhysicsObject->EnableGravity( true ); - pPhysicsObject->RecheckCollisionFilter(); - } - } -} - - -//----------------------------------------------------------------------------- -// The tongue's vphysics updated -//----------------------------------------------------------------------------- -void CNPC_Barnacle::OnTongueTipUpdated() -{ - // Update the tip's position - const Vector &vecNewTip = m_hTongueTip->GetAbsOrigin(); - if ( vecNewTip != m_vecTip ) - { - m_vecTip = vecNewTip; - CollisionProp()->MarkSurroundingBoundsDirty(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Update the positions of the tongue points -//----------------------------------------------------------------------------- -void CNPC_Barnacle::UpdateTongue( void ) -{ - if ( m_hTongueTip == NULL ) - return; - - // Set the spring's length to that of the tongue's extension - - // Compute the rest length of the tongue based on the spring. - // This occurs when mg == kx or x = mg/k - float flRestStretch = (BARNACLE_TONGUE_TIP_MASS * sv_gravity.GetFloat()) / BARNACLE_TONGUE_SPRING_CONSTANT_HANGING; - - // FIXME: HACK!!!! The code above doesn't quite make the tip end up in the right place. - // but it should. So, we're gonna hack it the rest of the way. - flRestStretch += 4; - - m_hTongueTip->m_pSpring->SetSpringLength( m_flAltitude - flRestStretch ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Barnacle::SpawnDeathGibs( void ) -{ - bool bDroppedAny = false; - - // Drop a random number of gibs - for ( size_t i=0; i < ARRAYSIZE(m_szGibNames); i++ ) - { - if ( random->RandomInt( 0, 1 ) ) - { - CGib::SpawnSpecificGibs( this, 1, 32, 1, m_szGibNames[i] ); - bDroppedAny = true; - } - } - - // Make sure we at least drop something - if ( bDroppedAny == false ) - { - CGib::SpawnSpecificGibs( this, 1, 32, 1, m_szGibNames[0] ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Barnacle::Event_Killed( const CTakeDamageInfo &info ) -{ - m_OnDeath.FireOutput( info.GetAttacker(), this ); - SendOnKilledGameEvent( info ); - - AddSolidFlags( FSOLID_NOT_SOLID ); - m_takedamage = DAMAGE_NO; - m_lifeState = LIFE_DYING; - - // Are we lifting prey? - if ( GetEnemy() ) - { - // Cleanup - LostPrey( false ); - } - else if ( m_bSwallowingPrey && m_hRagdoll ) - { - // We're swallowing a body. Make it stick inside us. - m_hTongueTip->SetAbsVelocity( vec3_origin ); - - m_hRagdoll->StopFollowingEntity(); - m_hRagdoll->SetMoveType( MOVETYPE_VPHYSICS ); - m_hRagdoll->SetAbsOrigin( m_hTongueTip->GetAbsOrigin() ); - m_hRagdoll->RemoveSolidFlags( FSOLID_NOT_SOLID ); - m_hRagdoll->SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - m_hRagdoll->RecheckCollisionFilter(); - if ( npc_barnacle_swallow.GetBool() ) - { - m_hRagdoll->SetThink( NULL ); - m_hRagdoll->SetBlendWeight( 1.0f ); - } - } - else - { - // Destroy the ragdoll->tongue tip constraint - if ( m_pConstraint ) - { - physenv->DestroyConstraint( m_pConstraint ); - m_pConstraint = NULL; - } - LostPrey( true ); - } - - // Puke gibs unless we're told to be cheap - bool spawnGibs = ( !HasSpawnFlags( SF_BARNACLE_CHEAP_DEATH ) || random->RandomInt( 0, 1 ) ); - - if ( spawnGibs ) - { - SpawnDeathGibs(); - } - - // Puke blood -#ifdef _XBOX - UTIL_BloodSpray( GetAbsOrigin(), Vector(0,0,-1), BLOOD_COLOR_YELLOW, 8, FX_BLOODSPRAY_ALL ); -#else - UTIL_BloodSpray( GetAbsOrigin(), Vector(0,0,-1), BLOOD_COLOR_RED, 8, FX_BLOODSPRAY_ALL ); -#endif - - // Put blood on the ground if near enough - trace_t bloodTrace; - AI_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector( 0, 0, 256 ), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &bloodTrace); - - if ( bloodTrace.fraction < 1.0f ) - { -#ifdef _XBOX - UTIL_BloodDecalTrace( &bloodTrace, BLOOD_COLOR_YELLOW ); -#else - UTIL_BloodDecalTrace( &bloodTrace, BLOOD_COLOR_RED ); -#endif - } - - EmitSound( "NPC_Barnacle.Die" ); - - SetActivity( ACT_DIESIMPLE ); - - StudioFrameAdvance(); - - SetNextThink( gpGlobals->curtime + 0.1f ); - SetThink ( &CNPC_Barnacle::WaitTillDead ); - - // we deliberately do not call BaseClass::EventKilled -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Barnacle::WaitTillDead ( void ) -{ - SetNextThink( gpGlobals->curtime + 0.1f ); - - StudioFrameAdvance(); - DispatchAnimEvents ( this ); - - if ( IsActivityFinished() ) - { - // death anim finished. - StopAnimation(); - } - - float goalAltitude = BARNACLE_DEAD_TONGUE_ALTITUDE; - - trace_t tr; - AI_TraceLine( m_vecRoot.Get(), m_vecRoot.Get() - Vector( 0, 0, 256 ), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction < 1.0 ) - { - float distToFloor = ( m_vecRoot.Get() - tr.endpos ).Length(); - float clearance = distToFloor - goalAltitude; - - if ( clearance < BARNACLE_MIN_DEAD_TONGUE_CLEARANCE ) - { - if ( distToFloor - BARNACLE_MIN_DEAD_TONGUE_CLEARANCE > distToFloor * .5 ) - { - goalAltitude = distToFloor - BARNACLE_MIN_DEAD_TONGUE_CLEARANCE; - } - else - { - goalAltitude = distToFloor * .5; - } - } - } - - // Keep moving the tongue to its dead position - // FIXME: This stupid algorithm is necessary because - // I can't seem to get reproduceable behavior from springs - bool bTongueInPosition = false; - float flDist = m_vecRoot.Get().z - m_vecTip.Get().z; - if ( fabs(flDist - goalAltitude) > 20.0f ) - { - float flNewAltitude; - float dt = gpGlobals->curtime - GetLastThink(); - if ( m_flAltitude >= goalAltitude ) - { - flNewAltitude = MAX( goalAltitude, m_flAltitude - m_flBarnaclePullSpeed * dt ); - } - else - { - flNewAltitude = MIN( goalAltitude, m_flAltitude + m_flBarnaclePullSpeed * dt ); - } - SetAltitude( flNewAltitude ); - } - else - { - // Wait for settling... - IPhysicsObject *pTipObject = m_hTongueTip->VPhysicsGetObject(); - - Vector vecVelocity; - AngularImpulse angVel; - pTipObject->GetVelocity( &vecVelocity, &angVel ); - if ( vecVelocity.LengthSqr() < 1.0f ) - { - // We may need to have a heavier spring constant until we settle - // to avoid strange looking rest conditions (when the tongue is really bent from - // picking up a barrel, it looks strange to switch to the hanging constant) - m_hTongueTip->m_pSpring->SetSpringConstant( BARNACLE_TONGUE_SPRING_CONSTANT_HANGING ); - if ( fabs(flDist - goalAltitude) > 1.0f ) - { - float flSign = ( flDist > goalAltitude ) ? -1.0f : 1.0f; - SetAltitude( m_flAltitude + flSign ); - } - else if ( vecVelocity.LengthSqr() < 0.01f ) - { - bTongueInPosition = ( fabs(flDist - goalAltitude) <= 1.0f ); - } - } - } - - if ( IsActivityFinished() && bTongueInPosition ) - { - // Remove our tongue pieces - UTIL_Remove( m_hTongueTip ); - UTIL_Remove( m_hTongueRoot ); - m_hTongueTip = NULL; - m_hTongueRoot = NULL; - - SetThink ( NULL ); - m_lifeState = LIFE_DEAD; - } - else - { - UpdateTongue(); - } -} - -#if HL2_EPISODIC -//========================================================= -// Some creatures are poisonous to barnacles, and the barnacle -// will die after consuming them. This determines if a given -// entity is one of those things. -// todo: could be a bit faster -//========================================================= -bool CNPC_Barnacle::IsPoisonous( CBaseEntity *pVictim ) -{ - if (!pVictim) - return false; - - if ( FClassnameIs(pVictim,"npc_headcrab_poison") ) - return true; - - if ( FClassnameIs(pVictim,"npc_headcrab_black") ) - return true; - - if ( FClassnameIs(pVictim,"npc_antlion") && - static_cast(pVictim)->IsWorker() - ) - return true; - - return false; -} - - - - -//========================================================= -// script input to immediately abandon whatever I am lifting -//========================================================= -void CNPC_Barnacle::InputLetGo( inputdata_t &inputdata ) -{ - if ( GetEnemy() ) - { - if ( !GetEnemy()->IsPlayer() ) - { - // ignore the object so we don't get into a loop of trying to pick it up. - m_hLastSpitEnemy = GetEnemy(); - } - - LostPrey( false ); - } -} - - -// Barnacle has custom impact damage tables, so it can take grave damage from sawblades. -static impactentry_t barnacleLinearTable[] = -{ - { 150*150, 5 }, - { 250*250, 10 }, - { 350*350, 50 }, - { 500*500, 100 }, - { 1000*1000, 500 }, -}; - - -static impactentry_t barnacleAngularTable[] = -{ - { 100*100, 35 }, // Sawblade always kills. - { 200*200, 50 }, - { 250*250, 500 }, -}; - -static impactdamagetable_t gBarnacleImpactDamageTable = -{ - barnacleLinearTable, - barnacleAngularTable, - - ARRAYSIZE(barnacleLinearTable), - ARRAYSIZE(barnacleAngularTable), - - 24*24, // minimum linear speed squared - 360*360, // minimum angular speed squared (360 deg/s to cause spin/slice damage) - 2, // can't take damage from anything under 2kg - - 5, // anything less than 5kg is "small" - 5, // never take more than 5 pts of damage from anything under 5kg - 36*36, // <5kg objects must go faster than 36 in/s to do damage - - VPHYSICS_LARGE_OBJECT_MASS, // large mass in kg - 4, // large mass scale (anything over 500kg does 4X as much energy to read from damage table) - 5, // large mass falling scale (emphasize falling/crushing damage over sideways impacts since the stress will kill you anyway) - 0.0f, // min vel -}; - - -const impactdamagetable_t &CNPC_Barnacle::GetPhysicsImpactDamageTable( void ) -{ - return gBarnacleImpactDamageTable; -} - -#endif - - -//========================================================= -// Precache - precaches all resources this monster needs -//========================================================= -void CNPC_Barnacle::Precache() -{ - PrecacheModel("models/barnacle.mdl"); - - // Precache all gibs - for ( size_t i=0; i < ARRAYSIZE(m_szGibNames); i++ ) - { - PrecacheModel( m_szGibNames[i] ); - } - - PrecacheScriptSound( "NPC_Barnacle.Digest" ); - PrecacheScriptSound( "NPC_Barnacle.Scream" ); - PrecacheScriptSound( "NPC_Barnacle.PullPant" ); - PrecacheScriptSound( "NPC_Barnacle.TongueStretch" ); - PrecacheScriptSound( "NPC_Barnacle.FinalBite" ); - PrecacheScriptSound( "NPC_Barnacle.Die" ); - PrecacheScriptSound( "NPC_Barnacle.BreakNeck" ); - - PrecacheModel( "models/props_junk/rock001a.mdl" ); - - BaseClass::Precache(); -} - -//========================================================= -// TongueTouchEnt - does a trace along the barnacle's tongue -// to see if any entity is touching it. Also stores the length -// of the trace in the int pointer provided. -//========================================================= -// enumerate entities that match a set of edict flags into a static array -class CTongueEntitiesEnum : public IPartitionEnumerator -{ -public: - CTongueEntitiesEnum( CBaseEntity **pList, int listMax ); - // This gets called by the enumeration methods with each element - // that passes the test. - virtual IterationRetval_t EnumElement( IHandleEntity *pHandleEntity ); - - int GetCount() { return m_nCount; } - bool AddToList( CBaseEntity *pEntity ); - -private: - CBaseEntity **m_pList; - int m_nListMax; - int m_nCount; -}; - -CTongueEntitiesEnum::CTongueEntitiesEnum( CBaseEntity **pList, int listMax ) -{ - m_pList = pList; - m_nListMax = listMax; - m_nCount = 0; -} - -bool CTongueEntitiesEnum::AddToList( CBaseEntity *pEntity ) -{ - m_pList[m_nCount] = pEntity; - ++m_nCount; - return ( m_nCount < m_nListMax ); -} - -IterationRetval_t CTongueEntitiesEnum::EnumElement( IHandleEntity *pHandleEntity ) -{ - CBaseEntity *pEntity = gEntList.GetBaseEntity( pHandleEntity->GetRefEHandle() ); - if ( pEntity ) - { - if ( !AddToList( pEntity ) ) - return ITERATION_STOP; - } - return ITERATION_CONTINUE; -} - - -//----------------------------------------------------------------------------- -// Barnacle must trace against only brushes and its last enemy -//----------------------------------------------------------------------------- -class CBarnacleTongueFilter : public CTraceFilterSimple -{ - DECLARE_CLASS( CBarnacleTongueFilter, CTraceFilterSimple ); - -public: - CBarnacleTongueFilter( CBaseEntity *pLastEnemy, const IHandleEntity *passedict, int collisionGroup ) : - CTraceFilterSimple( passedict, collisionGroup ) - { - m_pLastEnemy = pLastEnemy; - m_pBarnacle = const_cast( EntityFromEntityHandle( passedict ) ); - } - - virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ) - { - if ( pServerEntity == m_pLastEnemy ) - return true; - -#ifdef HL2_EPISODIC - CBaseEntity *pEntity = EntityFromEntityHandle( pServerEntity ); - - if ( pEntity ) - { - if ( FStrEq( STRING( pEntity->m_iClassname ), "func_brush" ) ) - { - CFuncBrush *pFuncBrush = assert_cast(pEntity); - - if ( pFuncBrush->m_bInvertExclusion ) - { - if ( pFuncBrush->m_iszExcludedClass == m_pBarnacle->m_iClassname ) - return true; - else - return false; - } - else - { - if ( pFuncBrush->m_iszExcludedClass != m_pBarnacle->m_iClassname ) - return false; - - } - } - - if ( pEntity->IsBSPModel() == false && pEntity->IsWorld() == false ) - { - return false; - } - } -#endif - - return BaseClass::ShouldHitEntity( pServerEntity, contentsMask ); - } - -private: - CBaseEntity *m_pLastEnemy; - CBaseEntity *m_pBarnacle; -}; - - -#define BARNACLE_CHECK_SPACING 12 -CBaseEntity *CNPC_Barnacle::TongueTouchEnt ( float *pflLength ) -{ - trace_t tr; - float length; - - int iMask = MASK_SOLID_BRUSHONLY; - -#ifdef HL2_EPISODIC - iMask = MASK_NPCSOLID; -#endif - - // trace once to hit architecture and see if the tongue needs to change position. - CBarnacleTongueFilter tongueFilter( m_hLastSpitEnemy, this, COLLISION_GROUP_NONE ); - AI_TraceLine ( GetAbsOrigin(), GetAbsOrigin() - Vector ( 0 , 0 , 2048 ), - iMask, &tongueFilter, &tr ); - - length = fabs( GetAbsOrigin().z - tr.endpos.z ); - // Pull it up a tad - length = MAX(8, length - m_flRestUnitsAboveGround); - if ( pflLength ) - { - *pflLength = length; - } - - Vector delta = Vector( BARNACLE_CHECK_SPACING, BARNACLE_CHECK_SPACING, 0 ); - Vector mins = GetAbsOrigin() - delta; - Vector maxs = GetAbsOrigin() + delta; - maxs.z = GetAbsOrigin().z; - mins.z -= length; - - CBaseEntity *pList[10]; - CTongueEntitiesEnum tongueEnum( pList, 10 ); - partition->EnumerateElementsInBox( PARTITION_ENGINE_SOLID_EDICTS, mins, maxs, false, &tongueEnum ); - int nCount = tongueEnum.GetCount(); - if ( !nCount ) - return NULL; - - for ( int i = 0; i < nCount; i++ ) - { - CBaseEntity *pTest = pList[i]; - - // Can't lift something that's in the process of being lifted... - // Necessary for good +use interactions - if ( pTest->IsEFlagSet( EFL_IS_BEING_LIFTED_BY_BARNACLE ) ) - continue; - - // Vehicles can drive so fast that players can warp through the barnacle tongue. - // Therefore, we have to do a check to ensure that doesn't happen. - if ( pTest->GetServerVehicle() ) - { - CBaseEntity *pDriver = pTest->GetServerVehicle()->GetPassenger(); - if ( pDriver ) - { - Vector vecPrevDriverPos; - pTest->GetVelocity( &vecPrevDriverPos ); - VectorMA( pDriver->GetAbsOrigin(), -0.1f, vecPrevDriverPos, vecPrevDriverPos ); - - Ray_t sweptDriver; - sweptDriver.Init( vecPrevDriverPos, pDriver->GetAbsOrigin(), pDriver->WorldAlignMins(), pDriver->WorldAlignMaxs() ); - if ( IsBoxIntersectingRay( mins, maxs, sweptDriver ) ) - { - pTest = pDriver; - } - } - } - - // Deal with physics objects - if ( pTest->GetMoveType() == MOVETYPE_VPHYSICS ) - { - IPhysicsObject *pObject = pTest->VPhysicsGetObject(); - if ( pObject && pObject->GetMass() <= BARNACLE_TONGUE_MAX_LIFT_MASS ) - { - // If this is an item, make sure it's near the tongue before lifting it. - // Weapons and other items have very large bounding boxes. - if( pTest->GetSolidFlags() & FSOLID_TRIGGER ) - { - if( UTIL_DistApprox2D( WorldSpaceCenter(), pTest->WorldSpaceCenter() ) > 16 ) - { - continue; - } - } - - // Allow the barnacles to grab stuff while their tongue is lowering -#ifdef HL2_EPISODIC - length = fabs( GetAbsOrigin().z - pTest->WorldSpaceCenter().z ); - // Pull it up a tad - length = MAX(8, length - m_flRestUnitsAboveGround); - if ( pflLength ) - { - *pflLength = length; - } -#endif - - return pTest; - } - } - - // NPCs + players - CBaseCombatCharacter *pVictim = ToBaseCombatCharacter( pTest ); - if ( !pVictim ) - continue; - - // only clients and monsters - if ( pTest != this && - IRelationType( pTest ) == D_HT && - pVictim->m_lifeState != LIFE_DEAD && - pVictim->m_lifeState != LIFE_DYING && - !( pVictim->GetFlags() & FL_NOTARGET ) ) - { - - // Allow the barnacles to grab stuff while their tongue is lowering -#ifdef HL2_EPISODIC - length = fabs( GetAbsOrigin().z - pTest->WorldSpaceCenter().z ); - // Pull it up a tad - length = MAX(8, length - m_flRestUnitsAboveGround); - if ( pflLength ) - { - *pflLength = length; - } -#endif - - return pTest; - } - } - - return NULL; -} - -//=============================================================================================================================== -// BARNACLE TONGUE TIP -//=============================================================================================================================== -// Crane tip -LINK_ENTITY_TO_CLASS( npc_barnacle_tongue_tip, CBarnacleTongueTip ); - -BEGIN_DATADESC( CBarnacleTongueTip ) - - DEFINE_FIELD( m_hBarnacle, FIELD_EHANDLE ), - DEFINE_PHYSPTR( m_pSpring ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: To by usable by vphysics, this needs to have a phys model. -//----------------------------------------------------------------------------- -void CBarnacleTongueTip::Spawn( void ) -{ - Precache(); - SetModel( "models/props_junk/rock001a.mdl" ); - AddEffects( EF_NODRAW ); - - // We don't want this to be solid, because we don't want it to collide with the barnacle. - SetSolid( SOLID_VPHYSICS ); - AddSolidFlags( FSOLID_NOT_SOLID ); - BaseClass::Spawn(); - - m_pSpring = NULL; -} - -int CBarnacleTongueTip::UpdateTransmitState( void ) -{ - return SetTransmitState( FL_EDICT_PVSCHECK ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBarnacleTongueTip::Precache( void ) -{ - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBarnacleTongueTip::UpdateOnRemove( ) -{ - if ( m_pSpring ) - { - physenv->DestroySpring( m_pSpring ); - m_pSpring = NULL; - } - BaseClass::UpdateOnRemove(); -} - - -//----------------------------------------------------------------------------- -// If the tip changes, we gotta update the barnacle's notion of his tongue -//----------------------------------------------------------------------------- -void CBarnacleTongueTip::VPhysicsUpdate( IPhysicsObject *pPhysics ) -{ - BaseClass::VPhysicsUpdate( pPhysics ); - - if ( m_hBarnacle.Get() ) - { - m_hBarnacle->OnTongueTipUpdated(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Activate/create the spring -//----------------------------------------------------------------------------- -bool CBarnacleTongueTip::CreateSpring( CBaseAnimating *pTongueRoot ) -{ - IPhysicsObject *pPhysObject = VPhysicsGetObject(); - IPhysicsObject *pRootPhysObject = pTongueRoot->VPhysicsGetObject(); - Assert( pRootPhysObject ); - Assert( pPhysObject ); - - // Root has huge mass, tip has little - pRootPhysObject->SetMass( VPHYSICS_MAX_MASS ); - pPhysObject->SetMass( BARNACLE_TONGUE_TIP_MASS ); - float damping = 3; - pPhysObject->SetDamping( &damping, &damping ); - - springparams_t spring; - spring.constant = BARNACLE_TONGUE_SPRING_CONSTANT_HANGING; - spring.damping = BARNACLE_TONGUE_SPRING_DAMPING; - spring.naturalLength = (GetAbsOrigin() - pTongueRoot->GetAbsOrigin()).Length(); - spring.relativeDamping = 10; - spring.startPosition = GetAbsOrigin(); - spring.endPosition = pTongueRoot->GetAbsOrigin(); - spring.useLocalPositions = false; - m_pSpring = physenv->CreateSpring( pPhysObject, pRootPhysObject, &spring ); - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Create a barnacle tongue tip at the bottom of the tongue -//----------------------------------------------------------------------------- -CBarnacleTongueTip *CBarnacleTongueTip::CreateTongueTip( CNPC_Barnacle *pBarnacle, CBaseAnimating *pTongueRoot, const Vector &vecOrigin, const QAngle &vecAngles ) -{ - CBarnacleTongueTip *pTip = (CBarnacleTongueTip *)CBaseEntity::Create( "npc_barnacle_tongue_tip", vecOrigin, vecAngles ); - if ( !pTip ) - return NULL; - - pTip->VPhysicsInitNormal( pTip->GetSolid(), pTip->GetSolidFlags(), false ); - if ( !pTip->CreateSpring( pTongueRoot ) ) - return NULL; - - // Set the backpointer to the barnacle - pTip->m_hBarnacle = pBarnacle; - - // Don't collide with the world - IPhysicsObject *pTipPhys = pTip->VPhysicsGetObject(); - - // turn off all floating / fluid simulation - pTipPhys->SetCallbackFlags( pTipPhys->GetCallbackFlags() & (~CALLBACK_DO_FLUID_SIMULATION) ); - - return pTip; -} - -//----------------------------------------------------------------------------- -// Purpose: Create a barnacle tongue tip at the root (i.e. inside the barnacle) -//----------------------------------------------------------------------------- -CBarnacleTongueTip *CBarnacleTongueTip::CreateTongueRoot( const Vector &vecOrigin, const QAngle &vecAngles ) -{ - CBarnacleTongueTip *pTip = (CBarnacleTongueTip *)CBaseEntity::Create( "npc_barnacle_tongue_tip", vecOrigin, vecAngles ); - if ( !pTip ) - return NULL; - - pTip->AddSolidFlags( FSOLID_NOT_SOLID ); - - // Disable movement on the root, we'll move this thing manually. - pTip->VPhysicsInitShadow( false, false ); - pTip->SetMoveType( MOVETYPE_NONE ); - return pTip; -} - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC( npc_barnacle, CNPC_Barnacle ) - - // Register our interactions - DECLARE_INTERACTION( g_interactionBarnacleVictimDangle ) - DECLARE_INTERACTION( g_interactionBarnacleVictimReleased ) - DECLARE_INTERACTION( g_interactionBarnacleVictimGrab ) - DECLARE_INTERACTION( g_interactionBarnacleVictimBite ) - - // Conditions - - // Tasks - - // Activities - DECLARE_ACTIVITY( ACT_BARNACLE_SLURP ) // Pulling the tongue up with prey on the end - DECLARE_ACTIVITY( ACT_BARNACLE_BITE_HUMAN ) // Biting the head of a humanoid - DECLARE_ACTIVITY( ACT_BARNACLE_BITE_PLAYER ) // Biting the head of a humanoid - DECLARE_ACTIVITY( ACT_BARNACLE_CHEW_HUMAN ) // Slowly swallowing the humanoid - DECLARE_ACTIVITY( ACT_BARNACLE_BARF_HUMAN ) // Spitting out human legs & gibs - DECLARE_ACTIVITY( ACT_BARNACLE_TONGUE_WRAP ) // Wrapping the tongue around a target - DECLARE_ACTIVITY( ACT_BARNACLE_TASTE_SPIT ) // Yuck! Me no like that! - DECLARE_ACTIVITY( ACT_BARNACLE_BITE_SMALL_THINGS ) // Biting small things, like a headcrab - DECLARE_ACTIVITY( ACT_BARNACLE_CHEW_SMALL_THINGS ) // Chewing small things, like a headcrab - - //Adrian: events go here - DECLARE_ANIMEVENT( AE_BARNACLE_PUKEGIB ) - DECLARE_ANIMEVENT( AE_BARNACLE_BITE ) - DECLARE_ANIMEVENT( AE_BARNACLE_SPIT ) - // Schedules - -AI_END_CUSTOM_NPC() diff --git a/game/server/hl2/npc_barnacle.h b/game/server/hl2/npc_barnacle.h deleted file mode 100644 index 924f286dc..000000000 --- a/game/server/hl2/npc_barnacle.h +++ /dev/null @@ -1,239 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef NPC_BARNACLE_H -#define NPC_BARNACLE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_basenpc.h" -#include "studio.h" -#include "physics_prop_ragdoll.h" - -class CNPC_Barnacle; - - -#define BARNACLE_PULL_SPEED 80 -#define BARNACLE_KILL_VICTIM_DELAY 5 // how many seconds after pulling prey in to gib them. - -// Tongue -#define BARNACLE_TONGUE_POINTS 8 - -#define BARNACLE_MIN_PULL_TIME 3.0f - -#define NUM_BARNACLE_GIBS 4 - -#define SF_BARNACLE_CHEAP_DEATH (1<<16) // Don't spawn as many gibs -#define SF_BARNACLE_AMBUSH (1<<17) // Start with tongue retracted and wait for input. - -// when true, causes the barnacle's visible tongue to offset -// from the physical one when pulling the player. -#define BARNACLE_USE_TONGUE_OFFSET 1 - - -//----------------------------------------------------------------------------- -// Purpose: This is the entity we place at the top & bottom of the tongue, to create a vphysics spring -//----------------------------------------------------------------------------- -class CBarnacleTongueTip : public CBaseAnimating -{ - DECLARE_CLASS( CBarnacleTongueTip, CBaseAnimating ); - -public: - DECLARE_DATADESC(); - - virtual void Spawn( void ); - virtual void Precache( void ); - virtual void UpdateOnRemove( ); - virtual void VPhysicsUpdate( IPhysicsObject *pPhysics ); - - virtual int UpdateTransmitState( void ); - bool CreateSpring( CBaseAnimating *pTongueRoot ); - static CBarnacleTongueTip *CreateTongueTip( CNPC_Barnacle *pBarnacle, CBaseAnimating *pTongueRoot, const Vector &vecOrigin, const QAngle &vecAngles ); - static CBarnacleTongueTip *CreateTongueRoot( const Vector &vecOrigin, const QAngle &vecAngles ); - - IPhysicsSpring *m_pSpring; - -private: - CHandle m_hBarnacle; -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CNPC_Barnacle : public CAI_BaseNPC -{ - DECLARE_CLASS( CNPC_Barnacle, CAI_BaseNPC ); -public: - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - CNPC_Barnacle(); - ~CNPC_Barnacle(); - - void Spawn( void ); - virtual void Activate( void ); - void Precache( void ); - Class_T Classify ( void ); - virtual void ComputeWorldSpaceSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs ); - virtual void HandleAnimEvent( animevent_t *pEvent ); - void Event_Killed( const CTakeDamageInfo &info ); - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - void PlayerHasIlluminatedNPC( CBasePlayer *pPlayer, float flDot ); - - // The tongue's vphysics updated - void OnTongueTipUpdated(); - -private: - void SetAltitude( float flAltitude ); - void SpawnDeathGibs( void ); - - void InitTonguePosition( void ); - CBaseEntity* TongueTouchEnt ( float *pflLength ); - void BarnacleThink ( void ); - void SwallowPrey( void ); - void WaitTillDead ( void ); - void AttachTongueToTarget( CBaseEntity *pTouchEnt, Vector vecGrabPos ); - CRagdollProp *AttachRagdollToTongue( CBaseAnimating *pAnimating ); - void RemoveRagdoll( bool bDestroyRagdoll ); - void LostPrey( bool bRemoveRagdoll ); - void BitePrey( void ); - - // Updates the tongue length - void UpdateTongue( void ); - - // Spit out the prey; add physics force! - void SpitPrey(); - - void SprayBlood(); - - // What type of enemy do we have? - bool IsEnemyAPlayer(); - bool IsEnemyARagdoll(); - bool IsEnemyAPhysicsObject(); - bool IsEnemyAnNPC(); - - bool CanPickup( CBaseCombatCharacter *pBCC ); - - // Allows the ragdoll to settle before biting it - bool WaitForRagdollToSettle( float flBiteZOffset ); - - // Allows the physics prop to settle before biting it - bool WaitForPhysicsObjectToSettle( float flBiteZOffset ); - - // Play a scream right before biting - void PlayLiftingScream( float flBiteZOffset ); - - // Pulls the prey upward toward the mouth - void PullEnemyTorwardsMouth( bool bAdjustEnemyOrigin ); - - // Lift the prey stuck to our tongue up towards our mouth - void LiftPrey( void ); - void LiftPlayer( float flBiteZOffset ); - void LiftRagdoll( float flBiteZOffset ); - void LiftPhysicsObject( float flBiteZOffset ); - void LiftNPC( float flBiteZOffset ); - - void UpdatePlayerConstraint( void ); - - void InputDropTongue( inputdata_t &inputdata ); - void InputSetDropTongueSpeed( inputdata_t &inputdata ); - void DropTongue( void ); - - - -#if HL2_EPISODIC - /// Decides whether something should poison the barnacle upon eating - static bool IsPoisonous( CBaseEntity *pVictim ); - - void InputLetGo( inputdata_t &inputdata ); - COutputEHANDLE m_OnGrab, m_OnRelease; - - const impactdamagetable_t &GetPhysicsImpactDamageTable( void ); -#endif - - CNetworkVar( float, m_flAltitude ); - int m_cGibs; // barnacle loads up on gibs each time it kills something. - bool m_bLiftingPrey; // true when the prey's on the tongue and being lifted to the mouth - bool m_bSwallowingPrey; // if it's a human, true while the barnacle chews it and swallows it whole. - float m_flDigestFinish; // time at which we've finished digesting something we chewed - float m_flVictimHeight; - int m_iGrabbedBoneIndex; - bool m_bPlayedPullSound; - bool m_bPlayerWasStanding; - - static const char *m_szGibNames[NUM_BARNACLE_GIBS]; - - // Tongue spline points - CNetworkVar( Vector, m_vecRoot ); - CNetworkVar( Vector, m_vecTip ); - CNetworkVar( Vector, m_vecTipDrawOffset ); - - // Tongue tip & root - CHandle m_hTongueRoot; - CHandle m_hTongueTip; - CHandle m_hRagdoll; - matrix3x4_t m_pRagdollBones[MAXSTUDIOBONES]; - IPhysicsConstraint *m_pConstraint; - float m_flRestUnitsAboveGround; - int m_nSpitAttachment; - EHANDLE m_hLastSpitEnemy; - int m_nShakeCount; - - float m_flNextBloodTime; -#ifndef _XBOX - int m_nBloodColor; -#endif - Vector m_vecBloodPos; - - float m_flBarnaclePullSpeed; - float m_flLocalTimer; - - Vector m_vLastEnemyPos; - float m_flLastPull; - CSimpleSimTimer m_StuckTimer; - bool m_bSwallowingBomb; -#ifdef HL2_EPISODIC - bool m_bSwallowingPoison; -#endif - -#if BARNACLE_USE_TONGUE_OFFSET - // Static because only one barnacle can be holding the player - // at a time, and because it's not really a big deal if it - // resets to zero after reload. - const static Vector m_svPlayerHeldTipOffset; -#endif - - DEFINE_CUSTOM_AI; -}; - - -//----------------------------------------------------------------------------- -// What type of enemy do we have? -//----------------------------------------------------------------------------- -inline bool CNPC_Barnacle::IsEnemyAPlayer() -{ - return GetEnemy() && GetEnemy()->IsPlayer(); -} - -inline bool CNPC_Barnacle::IsEnemyARagdoll() -{ - return m_hRagdoll != NULL; -} - -inline bool CNPC_Barnacle::IsEnemyAPhysicsObject() -{ - return !m_hRagdoll && GetEnemy() && !GetEnemy()->IsPlayer() && - !GetEnemy()->MyNPCPointer() && (GetEnemy()->GetMoveType() == MOVETYPE_VPHYSICS); -} - -inline bool CNPC_Barnacle::IsEnemyAnNPC() -{ - return !IsEnemyARagdoll() && (GetEnemy()->MyNPCPointer() != NULL); -} - - -#endif // NPC_BARNACLE_H diff --git a/game/server/hl2/npc_barney.cpp b/game/server/hl2/npc_barney.cpp deleted file mode 100644 index 36f2ba1b1..000000000 --- a/game/server/hl2/npc_barney.cpp +++ /dev/null @@ -1,250 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "ai_default.h" -#include "ai_task.h" -#include "ai_schedule.h" -#include "ai_node.h" -#include "ai_hull.h" -#include "ai_hint.h" -#include "ai_squad.h" -#include "ai_senses.h" -#include "ai_navigator.h" -#include "ai_motor.h" -#include "ai_behavior.h" -#include "ai_baseactor.h" -#include "ai_behavior_lead.h" -#include "ai_behavior_follow.h" -#include "ai_behavior_standoff.h" -#include "ai_behavior_assault.h" -#include "npc_playercompanion.h" -#include "soundent.h" -#include "game.h" -#include "npcevent.h" -#include "activitylist.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "sceneentity.h" -#include "ai_behavior_functank.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define BARNEY_MODEL "models/barney.mdl" - -ConVar sk_barney_health( "sk_barney_health","0"); - -//========================================================= -// Barney activities -//========================================================= - -class CNPC_Barney : public CNPC_PlayerCompanion -{ -public: - DECLARE_CLASS( CNPC_Barney, CNPC_PlayerCompanion ); - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - virtual void Precache() - { - // Prevents a warning - SelectModel( ); - BaseClass::Precache(); - - PrecacheScriptSound( "NPC_Barney.FootstepLeft" ); - PrecacheScriptSound( "NPC_Barney.FootstepRight" ); - PrecacheScriptSound( "NPC_Barney.Die" ); - - PrecacheInstancedScene( "scenes/Expressions/BarneyIdle.vcd" ); - PrecacheInstancedScene( "scenes/Expressions/BarneyAlert.vcd" ); - PrecacheInstancedScene( "scenes/Expressions/BarneyCombat.vcd" ); - } - - void Spawn( void ); - void SelectModel(); - Class_T Classify( void ); - void Weapon_Equip( CBaseCombatWeapon *pWeapon ); - - bool CreateBehaviors( void ); - - void HandleAnimEvent( animevent_t *pEvent ); - - bool ShouldLookForBetterWeapon() { return false; } - - void OnChangeRunningBehavior( CAI_BehaviorBase *pOldBehavior, CAI_BehaviorBase *pNewBehavior ); - - void DeathSound( const CTakeDamageInfo &info ); - void GatherConditions(); - void UseFunc( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - CAI_FuncTankBehavior m_FuncTankBehavior; - COutputEvent m_OnPlayerUse; - - DEFINE_CUSTOM_AI; -}; - - -LINK_ENTITY_TO_CLASS( npc_barney, CNPC_Barney ); - -//--------------------------------------------------------- -// -//--------------------------------------------------------- -IMPLEMENT_SERVERCLASS_ST(CNPC_Barney, DT_NPC_Barney) -END_SEND_TABLE() - - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CNPC_Barney ) -// m_FuncTankBehavior - DEFINE_OUTPUT( m_OnPlayerUse, "OnPlayerUse" ), - DEFINE_USEFUNC( UseFunc ), -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Barney::SelectModel() -{ - SetModelName( AllocPooledString( BARNEY_MODEL ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Barney::Spawn( void ) -{ - Precache(); - - m_iHealth = 80; - - m_iszIdleExpression = MAKE_STRING("scenes/Expressions/BarneyIdle.vcd"); - m_iszAlertExpression = MAKE_STRING("scenes/Expressions/BarneyAlert.vcd"); - m_iszCombatExpression = MAKE_STRING("scenes/Expressions/BarneyCombat.vcd"); - - BaseClass::Spawn(); - - AddEFlags( EFL_NO_DISSOLVE | EFL_NO_MEGAPHYSCANNON_RAGDOLL | EFL_NO_PHYSCANNON_INTERACTION ); - - NPCInit(); - - SetUse( &CNPC_Barney::UseFunc ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : -//----------------------------------------------------------------------------- -Class_T CNPC_Barney::Classify( void ) -{ - return CLASS_PLAYER_ALLY_VITAL; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Barney::Weapon_Equip( CBaseCombatWeapon *pWeapon ) -{ - BaseClass::Weapon_Equip( pWeapon ); - - if( hl2_episodic.GetBool() && FClassnameIs( pWeapon, "weapon_ar2" ) ) - { - // Allow Barney to defend himself at point-blank range in c17_05. - pWeapon->m_fMinRange1 = 0.0f; - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Barney::HandleAnimEvent( animevent_t *pEvent ) -{ - switch( pEvent->event ) - { - case NPC_EVENT_LEFTFOOT: - { - EmitSound( "NPC_Barney.FootstepLeft", pEvent->eventtime ); - } - break; - case NPC_EVENT_RIGHTFOOT: - { - EmitSound( "NPC_Barney.FootstepRight", pEvent->eventtime ); - } - break; - - default: - BaseClass::HandleAnimEvent( pEvent ); - break; - } -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_Barney::DeathSound( const CTakeDamageInfo &info ) -{ - // Sentences don't play on dead NPCs - SentenceStop(); - - EmitSound( "npc_barney.die" ); - -} - -bool CNPC_Barney::CreateBehaviors( void ) -{ - BaseClass::CreateBehaviors(); - AddBehavior( &m_FuncTankBehavior ); - - return true; -} - -void CNPC_Barney::OnChangeRunningBehavior( CAI_BehaviorBase *pOldBehavior, CAI_BehaviorBase *pNewBehavior ) -{ - if ( pNewBehavior == &m_FuncTankBehavior ) - { - m_bReadinessCapable = false; - } - else if ( pOldBehavior == &m_FuncTankBehavior ) - { - m_bReadinessCapable = IsReadinessCapable(); - } - - BaseClass::OnChangeRunningBehavior( pOldBehavior, pNewBehavior ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Barney::GatherConditions() -{ - BaseClass::GatherConditions(); - - // Handle speech AI. Don't do AI speech if we're in scripts unless permitted by the EnableSpeakWhileScripting input. - if ( m_NPCState == NPC_STATE_IDLE || m_NPCState == NPC_STATE_ALERT || m_NPCState == NPC_STATE_COMBAT || - ( ( m_NPCState == NPC_STATE_SCRIPT ) && CanSpeakWhileScripting() ) ) - { - DoCustomSpeechAI(); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Barney::UseFunc( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - m_bDontUseSemaphore = true; - SpeakIfAllowed( TLK_USE ); - m_bDontUseSemaphore = false; - - m_OnPlayerUse.FireOutput( pActivator, pCaller ); -} - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC( npc_barney, CNPC_Barney ) - -AI_END_CUSTOM_NPC() diff --git a/game/server/hl2/npc_basescanner.cpp b/game/server/hl2/npc_basescanner.cpp deleted file mode 100644 index e419091ce..000000000 --- a/game/server/hl2/npc_basescanner.cpp +++ /dev/null @@ -1,1846 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#include "npcevent.h" -#include "ai_basenpc_physicsflyer.h" -#include "weapon_physcannon.h" -#include "hl2_player.h" -#include "npc_scanner.h" -#include "IEffects.h" -#include "explode.h" -#include "ai_route.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar g_debug_basescanner( "g_debug_basescanner", "0", FCVAR_CHEAT ); - -BEGIN_DATADESC( CNPC_BaseScanner ) - DEFINE_EMBEDDED( m_KilledInfo ), - DEFINE_SOUNDPATCH( m_pEngineSound ), - - DEFINE_FIELD( m_flFlyNoiseBase, FIELD_FLOAT ), - DEFINE_FIELD( m_flEngineStallTime, FIELD_TIME ), - DEFINE_FIELD( m_fNextFlySoundTime, FIELD_TIME ), - DEFINE_FIELD( m_nFlyMode, FIELD_INTEGER ), - - DEFINE_FIELD( m_vecDiveBombDirection, FIELD_VECTOR ), - DEFINE_FIELD( m_flDiveBombRollForce, FIELD_FLOAT ), - - // Physics Influence - DEFINE_FIELD( m_hPhysicsAttacker, FIELD_EHANDLE ), - DEFINE_FIELD( m_flLastPhysicsInfluenceTime, FIELD_TIME ), - - DEFINE_FIELD( m_flGoalOverrideDistance, FIELD_FLOAT ), - - DEFINE_FIELD( m_flAttackNearDist, FIELD_FLOAT ), - DEFINE_FIELD( m_flAttackFarDist, FIELD_FLOAT ), - DEFINE_FIELD( m_flAttackRange, FIELD_FLOAT ), - - DEFINE_FIELD( m_nPoseTail, FIELD_INTEGER ), - DEFINE_FIELD( m_nPoseDynamo, FIELD_INTEGER ), - DEFINE_FIELD( m_nPoseFlare, FIELD_INTEGER ), - DEFINE_FIELD( m_nPoseFaceVert, FIELD_INTEGER ), - DEFINE_FIELD( m_nPoseFaceHoriz, FIELD_INTEGER ), - - // DEFINE_FIELD( m_bHasSpoken, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_pSmokeTrail, FIELD_CLASSPTR ), - - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetDistanceOverride", InputSetDistanceOverride ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetFlightSpeed", InputSetFlightSpeed ), - - DEFINE_THINKFUNC( DiveBombSoundThink ), -END_DATADESC() - -ConVar sk_scanner_dmg_dive( "sk_scanner_dmg_dive","0"); - -//----------------------------------------------------------------------------- -// Think contexts -//----------------------------------------------------------------------------- -static const char *s_pDiveBombSoundThinkContext = "DiveBombSoundThinkContext"; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CNPC_BaseScanner::CNPC_BaseScanner() -{ -#ifdef _DEBUG - m_vCurrentBanking.Init(); -#endif - m_pEngineSound = NULL; - m_bHasSpoken = false; - - m_flAttackNearDist = SCANNER_ATTACK_NEAR_DIST; - m_flAttackFarDist = SCANNER_ATTACK_FAR_DIST; - m_flAttackRange = SCANNER_ATTACK_RANGE; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::Spawn(void) -{ -#ifdef _XBOX - // Always fade the corpse - AddSpawnFlags( SF_NPC_FADE_CORPSE ); - AddEffects( EF_NOSHADOW ); -#endif // _XBOX - - SetHullType( HULL_TINY_CENTERED ); - SetHullSizeNormal(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - - SetMoveType( MOVETYPE_VPHYSICS ); - - m_bloodColor = DONT_BLEED; - SetViewOffset( Vector(0, 0, 10) ); // Position of the eyes relative to NPC's origin. - m_flFieldOfView = 0.2; - m_NPCState = NPC_STATE_NONE; - - SetNavType( NAV_FLY ); - - AddFlag( FL_FLY ); - - // This entity cannot be dissolved by the combine balls, - // nor does it get killed by the mega physcannon. - AddEFlags( EFL_NO_DISSOLVE | EFL_NO_MEGAPHYSCANNON_RAGDOLL ); - - m_flGoalOverrideDistance = 0.0f; - - m_nFlyMode = SCANNER_FLY_PATROL; - AngleVectors( GetLocalAngles(), &m_vCurrentBanking ); - m_fHeadYaw = 0; - m_pSmokeTrail = NULL; - - SetCurrentVelocity( vec3_origin ); - - // Noise modifier - Vector bobAmount; - bobAmount.x = random->RandomFloat( -2.0f, 2.0f ); - bobAmount.y = random->RandomFloat( -2.0f, 2.0f ); - bobAmount.z = random->RandomFloat( 2.0f, 4.0f ); - if ( random->RandomInt( 0, 1 ) ) - { - bobAmount.z *= -1.0f; - } - SetNoiseMod( bobAmount ); - - // set flight speed - m_flSpeed = GetMaxSpeed(); - - // -------------------------------------------- - - CapabilitiesAdd( bits_CAP_MOVE_FLY | bits_CAP_SQUAD | bits_CAP_TURN_HEAD | bits_CAP_SKIP_NAV_GROUND_CHECK ); - - NPCInit(); - - m_flFlyNoiseBase = random->RandomFloat( 0, M_PI ); - - m_flNextAttack = gpGlobals->curtime; -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::UpdateEfficiency( bool bInPVS ) -{ - SetEfficiency( ( GetSleepState() != AISS_AWAKE ) ? AIE_DORMANT : AIE_NORMAL ); - SetMoveEfficiency( AIME_NORMAL ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -float CNPC_BaseScanner::GetAutoAimRadius() -{ - if( g_pGameRules->GetAutoAimMode() == AUTOAIM_ON_CONSOLE ) - { - return 24.0f; - } - - return 12.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: Called just before we are deleted. -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::UpdateOnRemove( void ) -{ - // Stop combat loops if I'm alive. If I'm dead, the die sound will already have stopped it. - if ( IsAlive() && m_bHasSpoken ) - { - SentenceStop(); - } - - BaseClass::UpdateOnRemove(); -} - -//----------------------------------------------------------------------------- -// Purpose: Gets the appropriate next schedule based on current condition -// bits. -//----------------------------------------------------------------------------- -int CNPC_BaseScanner::SelectSchedule(void) -{ - // ---------------------------------------------------- - // If I'm dead, go into a dive bomb - // ---------------------------------------------------- - if ( m_iHealth <= 0 ) - { - m_flSpeed = SCANNER_MAX_DIVE_BOMB_SPEED; - return SCHED_SCANNER_ATTACK_DIVEBOMB; - } - - // ------------------------------- - // If I'm in a script sequence - // ------------------------------- - if ( m_NPCState == NPC_STATE_SCRIPT ) - return(BaseClass::SelectSchedule()); - - // ------------------------------- - // Flinch - // ------------------------------- - if ( HasCondition(COND_LIGHT_DAMAGE) || HasCondition(COND_HEAVY_DAMAGE) ) - { - if ( IsHeldByPhyscannon( ) ) - return SCHED_SMALL_FLINCH; - - if ( m_NPCState == NPC_STATE_IDLE ) - return SCHED_SMALL_FLINCH; - - if ( m_NPCState == NPC_STATE_ALERT ) - { - if ( m_iHealth < ( 3 * m_iMaxHealth / 4 )) - return SCHED_TAKE_COVER_FROM_ORIGIN; - - if ( SelectWeightedSequence( ACT_SMALL_FLINCH ) != -1 ) - return SCHED_SMALL_FLINCH; - } - else - { - if ( random->RandomInt( 0, 10 ) < 4 ) - return SCHED_SMALL_FLINCH; - } - } - - // I'm being held by the physcannon... struggle! - if ( IsHeldByPhyscannon( ) ) - return SCHED_SCANNER_HELD_BY_PHYSCANNON; - - // ---------------------------------------------------------- - // If I have an enemy - // ---------------------------------------------------------- - if ( GetEnemy() != NULL && GetEnemy()->IsAlive() ) - { - // Patrol if the enemy has vanished - if ( HasCondition( COND_LOST_ENEMY ) ) - return SCHED_SCANNER_PATROL; - - // Chase via route if we're directly blocked - if ( HasCondition( COND_SCANNER_FLY_BLOCKED ) ) - return SCHED_SCANNER_CHASE_ENEMY; - - // Attack if it's time - if ( gpGlobals->curtime >= m_flNextAttack ) - { - if ( HasCondition( COND_CAN_MELEE_ATTACK1 ) ) - return SCHED_SCANNER_ATTACK; - } - - // Otherwise fly in low for attack - return SCHED_SCANNER_ATTACK_HOVER; - } - - // Default to patrolling around - return SCHED_SCANNER_PATROL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::OnScheduleChange( void ) -{ - m_flSpeed = GetMaxSpeed(); - - BaseClass::OnScheduleChange(); -} - -//----------------------------------------------------------------------------- -// Purpose: For innate melee attack -//----------------------------------------------------------------------------- -int CNPC_BaseScanner::MeleeAttack1Conditions( float flDot, float flDist ) -{ - if (GetEnemy() == NULL) - { - return COND_NONE; - } - - // Check too far to attack with 2D distance - float vEnemyDist2D = (GetEnemy()->GetLocalOrigin() - GetLocalOrigin()).Length2D(); - - if (m_flNextAttack > gpGlobals->curtime) - { - return COND_NONE; - } - else if (vEnemyDist2D > m_flAttackRange) - { - return COND_TOO_FAR_TO_ATTACK; - } - else if (flDot < 0.7) - { - return COND_NOT_FACING_ATTACK; - } - return COND_CAN_MELEE_ATTACK1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : eOldState - -// eNewState - -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::OnStateChange( NPC_STATE eOldState, NPC_STATE eNewState ) -{ - if (( eNewState == NPC_STATE_ALERT ) || ( eNewState == NPC_STATE_COMBAT )) - { - SetPoseParameter(m_nPoseFlare, 1.0f); - } - else - { - SetPoseParameter(m_nPoseFlare, 0); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pTask - -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::StartTask( const Task_t *pTask ) -{ - switch (pTask->iTask) - { - case TASK_SCANNER_SET_FLY_PATROL: - { - // Fly in patrol mode and clear any - // remaining target entity - m_nFlyMode = SCANNER_FLY_PATROL; - TaskComplete(); - break; - } - case TASK_SCANNER_SET_FLY_CHASE: - { - m_nFlyMode = SCANNER_FLY_CHASE; - TaskComplete(); - break; - } - case TASK_SCANNER_SET_FLY_ATTACK: - { - m_nFlyMode = SCANNER_FLY_ATTACK; - TaskComplete(); - break; - } - - case TASK_SCANNER_SET_FLY_DIVE: - { - // Pick a direction to divebomb. - if ( GetEnemy() != NULL ) - { - // Fly towards my enemy - Vector vEnemyPos = GetEnemyLKP(); - m_vecDiveBombDirection = vEnemyPos - GetLocalOrigin(); - } - else - { - // Pick a random forward and down direction. - Vector forward; - GetVectors( &forward, NULL, NULL ); - m_vecDiveBombDirection = forward + Vector( random->RandomFloat( -10, 10 ), random->RandomFloat( -10, 10 ), random->RandomFloat( -20, -10 ) ); - } - VectorNormalize( m_vecDiveBombDirection ); - - // Calculate a roll force. - m_flDiveBombRollForce = random->RandomFloat( 20.0, 420.0 ); - if ( random->RandomInt( 0, 1 ) ) - { - m_flDiveBombRollForce *= -1; - } - - DiveBombSoundThink(); - - m_nFlyMode = SCANNER_FLY_DIVE; - TaskComplete(); - break; - } - - default: - BaseClass::StartTask(pTask); - break; - } -} - -//------------------------------------------------------------------------------ -// Purpose: Override to split in two when attacked -//------------------------------------------------------------------------------ -int CNPC_BaseScanner::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - // Start smoking when we're nearly dead - if ( m_iHealth < ( m_iMaxHealth - ( m_iMaxHealth / 4 ) ) ) - { - StartSmokeTrail(); - } - - return (BaseClass::OnTakeDamage_Alive( info )); -} - -//------------------------------------------------------------------------------ -// Purpose: Override to split in two when attacked -//------------------------------------------------------------------------------ -int CNPC_BaseScanner::OnTakeDamage_Dying( const CTakeDamageInfo &info ) -{ - // do the damage - m_iHealth -= info.GetDamage(); - - if ( m_iHealth < -40 ) - { - Gib(); - return 1; - } - - return VPhysicsTakeDamage( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - if ( info.GetDamageType() & DMG_BULLET) - { - g_pEffects->Ricochet(ptr->endpos,ptr->plane.normal); - } - - BaseClass::TraceAttack( info, vecDir, ptr ); -} - -//----------------------------------------------------------------------------- -// Take damage from being thrown by a physcannon -//----------------------------------------------------------------------------- -#define SCANNER_SMASH_SPEED 250.0 // How fast a scanner must slam into something to take full damage -void CNPC_BaseScanner::TakeDamageFromPhyscannon( CBasePlayer *pPlayer ) -{ - CTakeDamageInfo info; - info.SetDamageType( DMG_GENERIC ); - info.SetInflictor( this ); - info.SetAttacker( pPlayer ); - info.SetDamagePosition( GetAbsOrigin() ); - info.SetDamageForce( Vector( 1.0, 1.0, 1.0 ) ); - - // Convert velocity into damage. - Vector vel; - VPhysicsGetObject()->GetVelocity( &vel, NULL ); - float flSpeed = vel.Length(); - - float flFactor = flSpeed / SCANNER_SMASH_SPEED; - - // Clamp. Don't inflict negative damage or massive damage! - flFactor = clamp( flFactor, 0.0f, 2.0f ); - float flDamage = m_iMaxHealth * flFactor; - -#if 0 - Msg("Doing %f damage for %f speed!\n", flDamage, flSpeed ); -#endif - - info.SetDamage( flDamage ); - TakeDamage( info ); -} - - -//----------------------------------------------------------------------------- -// Take damage from physics impacts -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::TakeDamageFromPhysicsImpact( int index, gamevcollisionevent_t *pEvent ) -{ - CBaseEntity *pHitEntity = pEvent->pEntities[!index]; - - // NOTE: Augment the normal impact energy scale here. - float flDamageScale = PlayerHasMegaPhysCannon() ? 10.0f : 5.0f; - - // Scale by the mapmaker's energyscale - flDamageScale *= m_impactEnergyScale; - - int damageType = 0; - float damage = CalculateDefaultPhysicsDamage( index, pEvent, flDamageScale, true, damageType ); - if ( damage == 0 ) - return; - - Vector damagePos; - pEvent->pInternalData->GetContactPoint( damagePos ); - Vector damageForce = pEvent->postVelocity[index] * pEvent->pObjects[index]->GetMass(); - if ( damageForce == vec3_origin ) - { - // This can happen if this entity is motion disabled, and can't move. - // Use the velocity of the entity that hit us instead. - damageForce = pEvent->postVelocity[!index] * pEvent->pObjects[!index]->GetMass(); - } - - // FIXME: this doesn't pass in who is responsible if some other entity "caused" this collision - PhysCallbackDamage( this, CTakeDamageInfo( pHitEntity, pHitEntity, damageForce, damagePos, damage, damageType ), *pEvent, index ); -} - -//----------------------------------------------------------------------------- -// Is the scanner being held? -//----------------------------------------------------------------------------- -bool CNPC_BaseScanner::IsHeldByPhyscannon( ) -{ - return VPhysicsGetObject() && (VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD); -} - -//------------------------------------------------------------------------------ -// Physics impact -//------------------------------------------------------------------------------ -#define SCANNER_SMASH_TIME 0.75 // How long after being thrown from a physcannon that a manhack is eligible to die from impact -void CNPC_BaseScanner::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) -{ - BaseClass::VPhysicsCollision( index, pEvent ); - - // Take no impact damage while being carried. - if ( IsHeldByPhyscannon( ) ) - return; - - CBasePlayer *pPlayer = HasPhysicsAttacker( SCANNER_SMASH_TIME ); - if( pPlayer ) - { - TakeDamageFromPhyscannon( pPlayer ); - return; - } - - // It also can take physics damage from things thrown by the player. - int otherIndex = !index; - CBaseEntity *pHitEntity = pEvent->pEntities[otherIndex]; - if ( pHitEntity ) - { - if ( pHitEntity->HasPhysicsAttacker( 0.5f ) ) - { - // It can take physics damage from things thrown by the player. - TakeDamageFromPhysicsImpact( index, pEvent ); - } - else if ( FClassnameIs( pHitEntity, "prop_combine_ball" ) ) - { - // It also can take physics damage from a combine ball. - TakeDamageFromPhysicsImpact( index, pEvent ); - } - } -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CNPC_BaseScanner::Gib( void ) -{ - if ( IsMarkedForDeletion() ) - return; - - // Sparks - for ( int i = 0; i < 4; i++ ) - { - Vector sparkPos = GetAbsOrigin(); - sparkPos.x += random->RandomFloat(-12,12); - sparkPos.y += random->RandomFloat(-12,12); - sparkPos.z += random->RandomFloat(-12,12); - g_pEffects->Sparks(sparkPos); - } - - // Light - CBroadcastRecipientFilter filter; - te->DynamicLight( filter, 0.0, &WorldSpaceCenter(), 255, 180, 100, 0, 100, 0.1, 0 ); - - // Cover the gib spawn - ExplosionCreate( WorldSpaceCenter(), GetAbsAngles(), this, 64, 64, false ); - - // Turn off any smoke trail - if ( m_pSmokeTrail ) - { - m_pSmokeTrail->m_ParticleLifetime = 0; - UTIL_Remove(m_pSmokeTrail); - m_pSmokeTrail = NULL; - } - - // FIXME: This is because we couldn't save/load the CTakeDamageInfo. - // because it's midnight before the teamwide playtest. Real solution - // is to add a datadesc to CTakeDamageInfo - if ( m_KilledInfo.GetInflictor() ) - { - BaseClass::Event_Killed( m_KilledInfo ); - } - - UTIL_Remove(this); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPhysGunUser - -// bPunting - -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) -{ - m_hPhysicsAttacker = pPhysGunUser; - m_flLastPhysicsInfluenceTime = gpGlobals->curtime; - - if ( reason == PUNTED_BY_CANNON ) - { - // There's about to be a massive change in velocity. - // Think immediately to handle changes in m_vCurrentVelocity; - SetNextThink( gpGlobals->curtime + 0.01f ); - - m_flEngineStallTime = gpGlobals->curtime + 2.0f; - ScannerEmitSound( "DiveBomb" ); - } - else - { - SetCondition( COND_SCANNER_GRABBED_BY_PHYSCANNON ); - ClearCondition( COND_SCANNER_RELEASED_FROM_PHYSCANNON ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPhysGunUser - -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ) -{ - m_hPhysicsAttacker = pPhysGunUser; - m_flLastPhysicsInfluenceTime = gpGlobals->curtime; - - ClearCondition( COND_SCANNER_GRABBED_BY_PHYSCANNON ); - SetCondition( COND_SCANNER_RELEASED_FROM_PHYSCANNON ); - - if ( Reason == LAUNCHED_BY_CANNON ) - { - m_flEngineStallTime = gpGlobals->curtime + 2.0f; - - // There's about to be a massive change in velocity. - // Think immediately to handle changes in m_vCurrentVelocity; - SetNextThink( gpGlobals->curtime + 0.01f ); - ScannerEmitSound( "DiveBomb" ); - } -} - - -//------------------------------------------------------------------------------ -// Do we have a physics attacker? -//------------------------------------------------------------------------------ -CBasePlayer *CNPC_BaseScanner::HasPhysicsAttacker( float dt ) -{ - // If the player is holding me now, or I've been recently thrown - // then return a pointer to that player - if ( IsHeldByPhyscannon( ) || (gpGlobals->curtime - dt <= m_flLastPhysicsInfluenceTime) ) - { - return m_hPhysicsAttacker; - } - return NULL; -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CNPC_BaseScanner::StopLoopingSounds(void) -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundDestroy( m_pEngineSound ); - m_pEngineSound = NULL; - - BaseClass::StopLoopingSounds(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pInflictor - -// pAttacker - -// flDamage - -// bitsDamageType - -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::Event_Killed( const CTakeDamageInfo &info ) -{ - // Copy off the takedamage info that killed me, since we're not going to call - // up into the base class's Event_Killed() until we gib. (gibbing is ultimate death) - m_KilledInfo = info; - - // Interrupt whatever schedule I'm on - SetCondition(COND_SCHEDULE_DONE); - - // If I have an enemy and I'm up high, do a dive bomb (unless dissolved) - if ( GetEnemy() != NULL && (info.GetDamageType() & DMG_DISSOLVE) == false ) - { - Vector vecDelta = GetLocalOrigin() - GetEnemy()->GetLocalOrigin(); - if ( ( vecDelta.z > 120 ) && ( vecDelta.Length() > 360 ) ) - { - // If I'm divebombing, don't take any more damage. It will make Event_Killed() be called again. - // This is especially bad if someone machineguns the divebombing scanner. - AttackDivebomb(); - return; - } - } - - Gib(); -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CNPC_BaseScanner::AttackDivebomb( void ) -{ - ScannerEmitSound( "DiveBomb" ); - - m_takedamage = DAMAGE_NO; - - StartSmokeTrail(); -} - -//------------------------------------------------------------------------------ -// Purpose: Checks to see if we hit anything while dive bombing. -//------------------------------------------------------------------------------ -void CNPC_BaseScanner::AttackDivebombCollide(float flInterval) -{ - // - // Trace forward to see if I hit anything - // - Vector checkPos = GetAbsOrigin() + (GetCurrentVelocity() * flInterval); - trace_t tr; - CBaseEntity* pHitEntity = NULL; - AI_TraceHull( GetAbsOrigin(), checkPos, GetHullMins(), GetHullMaxs(), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - - if (tr.m_pEnt) - { - pHitEntity = tr.m_pEnt; - - // Did I hit an entity that isn't another scanner? - if (pHitEntity && pHitEntity->Classify()!=CLASS_SCANNER) - { - if ( !pHitEntity->ClassMatches("item_battery") ) - { - if ( !pHitEntity->IsWorld() ) - { - CTakeDamageInfo info( this, this, sk_scanner_dmg_dive.GetFloat(), DMG_CLUB ); - CalculateMeleeDamageForce( &info, (tr.endpos - tr.startpos), tr.endpos ); - pHitEntity->TakeDamage( info ); - } - Gib(); - } - } - } - - if (tr.fraction != 1.0) - { - // We've hit something so deflect our velocity based on the surface - // norm of what we've hit - if (flInterval > 0) - { - float moveLen = (1.0 - tr.fraction)*(GetAbsOrigin() - checkPos).Length(); - Vector vBounceVel = moveLen*tr.plane.normal/flInterval; - - // If I'm right over the ground don't push down - if (vBounceVel.z < 0) - { - float floorZ = GetFloorZ(GetAbsOrigin()); - if (fabs(GetAbsOrigin().z - floorZ) < 36.0f) - { - vBounceVel.z = 0; - } - } - SetCurrentVelocity( GetCurrentVelocity() + vBounceVel ); - } - CBaseCombatCharacter* pBCC = ToBaseCombatCharacter( pHitEntity ); - - if (pBCC) - { - // Spawn some extra blood where we hit - SpawnBlood(tr.endpos, g_vecAttackDir, pBCC->BloodColor(), sk_scanner_dmg_dive.GetFloat()); - } - else - { - if (!(m_spawnflags & SF_NPC_GAG)) - { - // <> need better sound here... - ScannerEmitSound( "Shoot" ); - } - // For sparks we must trace a line in the direction of the surface norm - // that we hit. - checkPos = GetAbsOrigin() - (tr.plane.normal * 24); - - AI_TraceLine( GetAbsOrigin(), checkPos,MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - if (tr.fraction != 1.0) - { - g_pEffects->Sparks( tr.endpos ); - - CBroadcastRecipientFilter filter; - te->DynamicLight( filter, 0.0, - &GetAbsOrigin(), 255, 180, 100, 0, 50, 0.1, 0 ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::PlayFlySound(void) -{ - if ( IsMarkedForDeletion() ) - return; - - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - - //Setup the sound if we're not already - if ( m_pEngineSound == NULL ) - { - // Create the sound - CPASAttenuationFilter filter( this ); - - m_pEngineSound = controller.SoundCreate( filter, entindex(), CHAN_STATIC, GetEngineSound(), ATTN_NORM ); - - Assert(m_pEngineSound); - - // Start the engine sound - controller.Play( m_pEngineSound, 0.0f, 100.0f ); - controller.SoundChangeVolume( m_pEngineSound, 1.0f, 2.0f ); - } - - float speed = GetCurrentVelocity().Length(); - float flVolume = 0.25f + (0.75f*(speed/GetMaxSpeed())); - int iPitch = (int)MIN( 255, 80 + (20*(speed/GetMaxSpeed())) ); - - //Update our pitch and volume based on our speed - controller.SoundChangePitch( m_pEngineSound, iPitch, 0.1f ); - controller.SoundChangeVolume( m_pEngineSound, flVolume, 0.1f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::ScannerEmitSound( const char *pszSoundName ) -{ - CFmtStr snd; - snd.sprintf("%s.%s", GetScannerSoundPrefix(), pszSoundName ); - - m_bHasSpoken = true; - - EmitSound( snd.Access() ); -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CNPC_BaseScanner::SpeakSentence( int sentenceType ) -{ - if (sentenceType == SCANNER_SENTENCE_ATTENTION) - { - ScannerEmitSound( "Attention" ); - } - else if (sentenceType == SCANNER_SENTENCE_HANDSUP) - { - ScannerEmitSound( "Scan" ); - } - else if (sentenceType == SCANNER_SENTENCE_PROCEED) - { - ScannerEmitSound( "Proceed" ); - } - else if (sentenceType == SCANNER_SENTENCE_CURIOUS) - { - ScannerEmitSound( "Curious" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::InputSetFlightSpeed(inputdata_t &inputdata) -{ - //FIXME: Currently unsupported - - /* - m_flFlightSpeed = inputdata.value.Int(); - m_bFlightSpeedOverridden = (m_flFlightSpeed > 0); - */ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::StartSmokeTrail( void ) -{ - if ( m_pSmokeTrail != NULL ) - return; - - m_pSmokeTrail = SmokeTrail::CreateSmokeTrail(); - - if ( m_pSmokeTrail ) - { - m_pSmokeTrail->m_SpawnRate = 10; - m_pSmokeTrail->m_ParticleLifetime = 1; - m_pSmokeTrail->m_StartSize = 8; - m_pSmokeTrail->m_EndSize = 50; - m_pSmokeTrail->m_SpawnRadius = 10; - m_pSmokeTrail->m_MinSpeed = 15; - m_pSmokeTrail->m_MaxSpeed = 25; - - m_pSmokeTrail->m_StartColor.Init( 0.5f, 0.5f, 0.5f ); - m_pSmokeTrail->m_EndColor.Init( 0, 0, 0 ); - m_pSmokeTrail->SetLifetime( 500.0f ); - m_pSmokeTrail->FollowEntity( this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::BlendPhyscannonLaunchSpeed() -{ - // Blend out desired velocity when launched by the physcannon - if (!VPhysicsGetObject()) - return; - - if ( HasPhysicsAttacker( SCANNER_SMASH_TIME ) && !IsHeldByPhyscannon( ) ) - { - Vector vecCurrentVelocity; - VPhysicsGetObject()->GetVelocity( &vecCurrentVelocity, NULL ); - float flLerpFactor = (gpGlobals->curtime - m_flLastPhysicsInfluenceTime) / SCANNER_SMASH_TIME; - flLerpFactor = clamp( flLerpFactor, 0.0f, 1.0f ); - flLerpFactor = SimpleSplineRemapVal( flLerpFactor, 0.0f, 1.0f, 0.0f, 1.0f ); - flLerpFactor *= flLerpFactor; - VectorLerp( vecCurrentVelocity, m_vCurrentVelocity, flLerpFactor, m_vCurrentVelocity ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::MoveExecute_Alive(float flInterval) -{ - // Amount of noise to add to flying - float noiseScale = 3.0f; - - // ------------------------------------------- - // Avoid obstacles, unless I'm dive bombing - // ------------------------------------------- - if (m_nFlyMode != SCANNER_FLY_DIVE) - { - SetCurrentVelocity( GetCurrentVelocity() + VelocityToAvoidObstacles(flInterval) ); - } - // If I am dive bombing add more noise to my flying - else - { - AttackDivebombCollide(flInterval); - noiseScale *= 4; - } - - IPhysicsObject *pPhysics = VPhysicsGetObject(); - - if ( pPhysics && pPhysics->IsAsleep() ) - { - pPhysics->Wake(); - } - - // Add time-coherent noise to the current velocity so that it never looks bolted in place. - AddNoiseToVelocity( noiseScale ); - - AdjustScannerVelocity(); - - float maxSpeed = GetEnemy() ? ( GetMaxSpeed() * 2.0f ) : GetMaxSpeed(); - if ( m_nFlyMode == SCANNER_FLY_DIVE ) - { - maxSpeed = -1; - } - - // Limit fall speed - LimitSpeed( maxSpeed ); - - // Blend out desired velocity when launched by the physcannon - BlendPhyscannonLaunchSpeed(); - - // Update what we're looking at - UpdateHead( flInterval ); - - // Control the tail based on our vertical travel - float tailPerc = clamp( GetCurrentVelocity().z, -150, 250 ); - tailPerc = SimpleSplineRemapVal( tailPerc, -150, 250, -25, 80 ); - - SetPoseParameter( m_nPoseTail, tailPerc ); - - // Spin the dynamo based upon our speed - float flCurrentDynamo = GetPoseParameter( m_nPoseDynamo ); - float speed = GetCurrentVelocity().Length(); - float flDynamoSpeed = (maxSpeed > 0 ? speed / maxSpeed : 1.0) * 60; - flCurrentDynamo -= flDynamoSpeed; - if ( flCurrentDynamo < -180.0 ) - { - flCurrentDynamo += 360.0; - } - SetPoseParameter( m_nPoseDynamo, flCurrentDynamo ); - - PlayFlySound(); -} - -//----------------------------------------------------------------------------- -// Purpose: Handles movement towards the last move target. -// Input : flInterval - -//----------------------------------------------------------------------------- -bool CNPC_BaseScanner::OverridePathMove( CBaseEntity *pMoveTarget, float flInterval ) -{ - // Save our last patrolling direction - Vector lastPatrolDir = GetNavigator()->GetCurWaypointPos() - GetAbsOrigin(); - - // Continue on our path - if ( ProgressFlyPath( flInterval, pMoveTarget, (MASK_NPCSOLID|CONTENTS_WATER), false, 64 ) == AINPP_COMPLETE ) - { - if ( IsCurSchedule( SCHED_SCANNER_PATROL ) ) - { - m_vLastPatrolDir = lastPatrolDir; - VectorNormalize(m_vLastPatrolDir); - } - - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flInterval - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_BaseScanner::OverrideMove( float flInterval ) -{ - // ---------------------------------------------- - // If dive bombing - // ---------------------------------------------- - if (m_nFlyMode == SCANNER_FLY_DIVE) - { - MoveToDivebomb( flInterval ); - } - else - { - Vector vMoveTargetPos(0,0,0); - CBaseEntity *pMoveTarget = NULL; - - if ( !GetNavigator()->IsGoalActive() || ( GetNavigator()->GetCurWaypointFlags() | bits_WP_TO_PATHCORNER ) ) - { - // Select move target - if ( GetTarget() != NULL ) - { - pMoveTarget = GetTarget(); - } - else if ( GetEnemy() != NULL ) - { - pMoveTarget = GetEnemy(); - } - - // Select move target position - if ( GetEnemy() != NULL ) - { - vMoveTargetPos = GetEnemy()->GetAbsOrigin(); - } - } - else - { - vMoveTargetPos = GetNavigator()->GetCurWaypointPos(); - } - - ClearCondition( COND_SCANNER_FLY_CLEAR ); - ClearCondition( COND_SCANNER_FLY_BLOCKED ); - - // See if we can fly there directly - if ( pMoveTarget ) - { - trace_t tr; - AI_TraceHull( GetAbsOrigin(), vMoveTargetPos, GetHullMins(), GetHullMaxs(), MASK_NPCSOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - - float fTargetDist = (1.0f-tr.fraction)*(GetAbsOrigin() - vMoveTargetPos).Length(); - - if ( ( tr.m_pEnt == pMoveTarget ) || ( fTargetDist < 50 ) ) - { - if ( g_debug_basescanner.GetBool() ) - { - NDebugOverlay::Line(GetLocalOrigin(), vMoveTargetPos, 0,255,0, true, 0); - NDebugOverlay::Cross3D(tr.endpos,Vector(-5,-5,-5),Vector(5,5,5),0,255,0,true,0.1); - } - - SetCondition( COND_SCANNER_FLY_CLEAR ); - } - else - { - //HANDY DEBUG TOOL - if ( g_debug_basescanner.GetBool() ) - { - NDebugOverlay::Line(GetLocalOrigin(), vMoveTargetPos, 255,0,0, true, 0); - NDebugOverlay::Cross3D(tr.endpos,Vector(-5,-5,-5),Vector(5,5,5),255,0,0,true,0.1); - } - - SetCondition( COND_SCANNER_FLY_BLOCKED ); - } - } - - // If I have a route, keep it updated and move toward target - if ( GetNavigator()->IsGoalActive() ) - { - if ( OverridePathMove( pMoveTarget, flInterval ) ) - { - BlendPhyscannonLaunchSpeed(); - return true; - } - } - // ---------------------------------------------- - // If attacking - // ---------------------------------------------- - else if (m_nFlyMode == SCANNER_FLY_ATTACK) - { - MoveToAttack( flInterval ); - } - // ----------------------------------------------------------------- - // If I don't have a route, just decelerate - // ----------------------------------------------------------------- - else if (!GetNavigator()->IsGoalActive()) - { - float myDecay = 9.5; - Decelerate( flInterval, myDecay); - } - } - - MoveExecute_Alive( flInterval ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &goalPos - -// &startPos - -// idealRange - -// idealHeight - -// Output : Vector -//----------------------------------------------------------------------------- -Vector CNPC_BaseScanner::IdealGoalForMovement( const Vector &goalPos, const Vector &startPos, float idealRange, float idealHeightDiff ) -{ - Vector vMoveDir; - - if ( GetGoalDirection( &vMoveDir ) == false ) - { - vMoveDir = ( goalPos - startPos ); - vMoveDir.z = 0; - VectorNormalize( vMoveDir ); - } - - // Move up from the position by the desired amount - Vector vIdealPos = goalPos + Vector( 0, 0, idealHeightDiff ) + ( vMoveDir * -idealRange ); - - // Trace down and make sure we can fit here - trace_t tr; - AI_TraceHull( vIdealPos, vIdealPos - Vector( 0, 0, MinGroundDist() ), GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - - // Move up otherwise - if ( tr.fraction < 1.0f ) - { - vIdealPos.z += ( MinGroundDist() * ( 1.0f - tr.fraction ) ); - } - - //FIXME: We also need to make sure that we fit here at all, and if not, chose a new spot - - // Debug tools - if ( g_debug_basescanner.GetBool() ) - { - NDebugOverlay::Cross3D( goalPos, -Vector(8,8,8), Vector(8,8,8), 255, 255, 0, true, 0.1f ); - NDebugOverlay::Cross3D( startPos, -Vector(8,8,8), Vector(8,8,8), 255, 0, 255, true, 0.1f ); - NDebugOverlay::Cross3D( vIdealPos, -Vector(8,8,8), Vector(8,8,8), 255, 255, 255, true, 0.1f ); - NDebugOverlay::Line( startPos, goalPos, 0, 255, 0, true, 0.1f ); - - NDebugOverlay::Cross3D( goalPos + ( vMoveDir * -idealRange ), -Vector(8,8,8), Vector(8,8,8), 255, 255, 255, true, 0.1f ); - NDebugOverlay::Line( goalPos, goalPos + ( vMoveDir * -idealRange ), 255, 255, 0, true, 0.1f ); - NDebugOverlay::Line( goalPos + ( vMoveDir * -idealRange ), vIdealPos, 255, 255, 0, true, 0.1f ); - } - - return vIdealPos; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flInterval - -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::MoveToAttack(float flInterval) -{ - if (GetEnemy() == NULL) - return; - - if ( flInterval <= 0 ) - return; - - Vector vTargetPos = GetEnemyLKP(); - - //float flDesiredDist = m_flAttackNearDist + ( ( m_flAttackFarDist - m_flAttackNearDist ) / 2 ); - - Vector idealPos = IdealGoalForMovement( vTargetPos, GetAbsOrigin(), GetGoalDistance(), m_flAttackNearDist ); - - MoveToTarget( flInterval, idealPos ); - - //FIXME: Re-implement? - - /* - // --------------------------------------------------------- - // Add evasion if I have taken damage recently - // --------------------------------------------------------- - if ((m_flLastDamageTime + SCANNER_EVADE_TIME) > gpGlobals->curtime) - { - vFlyDirection = vFlyDirection + VelocityToEvade(GetEnemyCombatCharacterPointer()); - } - */ -} - -//----------------------------------------------------------------------------- -// Purpose: Accelerates toward a given position. -// Input : flInterval - Time interval over which to move. -// vecMoveTarget - Position to move toward. -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::MoveToTarget( float flInterval, const Vector &vecMoveTarget ) -{ - // Don't move if stalling - if ( m_flEngineStallTime > gpGlobals->curtime ) - return; - - // Look at our inspection target if we have one - if ( GetEnemy() != NULL ) - { - // Otherwise at our enemy - TurnHeadToTarget( flInterval, GetEnemy()->EyePosition() ); - } - else - { - // Otherwise face our motion direction - TurnHeadToTarget( flInterval, vecMoveTarget ); - } - - // ------------------------------------- - // Move towards our target - // ------------------------------------- - float myAccel; - float myZAccel = 400.0f; - float myDecay = 0.15f; - - Vector vecCurrentDir; - - // Get the relationship between my current velocity and the way I want to be going. - vecCurrentDir = GetCurrentVelocity(); - VectorNormalize( vecCurrentDir ); - - Vector targetDir = vecMoveTarget - GetAbsOrigin(); - float flDist = VectorNormalize(targetDir); - - float flDot; - flDot = DotProduct( targetDir, vecCurrentDir ); - - if( flDot > 0.25 ) - { - // If my target is in front of me, my flight model is a bit more accurate. - myAccel = 250; - } - else - { - // Have a harder time correcting my course if I'm currently flying away from my target. - myAccel = 128; - } - - if ( myAccel > flDist / flInterval ) - { - myAccel = flDist / flInterval; - } - - if ( myZAccel > flDist / flInterval ) - { - myZAccel = flDist / flInterval; - } - - MoveInDirection( flInterval, targetDir, myAccel, myZAccel, myDecay ); - - // calc relative banking targets - Vector forward, right, up; - GetVectors( &forward, &right, &up ); - - m_vCurrentBanking.x = targetDir.x; - m_vCurrentBanking.z = 120.0f * DotProduct( right, targetDir ); - m_vCurrentBanking.y = 0; - - float speedPerc = SimpleSplineRemapVal( GetCurrentVelocity().Length(), 0.0f, GetMaxSpeed(), 0.0f, 1.0f ); - - speedPerc = clamp( speedPerc, 0.0f, 1.0f ); - - m_vCurrentBanking *= speedPerc; -} - -//----------------------------------------------------------------------------- -// Danger sounds. -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::DiveBombSoundThink() -{ - Vector vecPosition, vecVelocity; - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - - if ( pPhysicsObject == NULL ) - return; - - pPhysicsObject->GetPosition( &vecPosition, NULL ); - pPhysicsObject->GetVelocity( &vecVelocity, NULL ); - - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer ) - { - Vector vecDelta; - VectorSubtract( pPlayer->GetAbsOrigin(), vecPosition, vecDelta ); - VectorNormalize( vecDelta ); - if ( DotProduct( vecDelta, vecVelocity ) > 0.5f ) - { - Vector vecEndPoint; - VectorMA( vecPosition, 2.0f * TICK_INTERVAL, vecVelocity, vecEndPoint ); - float flDist = CalcDistanceToLineSegment( pPlayer->GetAbsOrigin(), vecPosition, vecEndPoint ); - if ( flDist < 200.0f ) - { - ScannerEmitSound( "DiveBombFlyby" ); - SetContextThink( &CNPC_BaseScanner::DiveBombSoundThink, gpGlobals->curtime + 0.5f, s_pDiveBombSoundThinkContext ); - return; - } - } - } - - SetContextThink( &CNPC_BaseScanner::DiveBombSoundThink, gpGlobals->curtime + 2.0f * TICK_INTERVAL, s_pDiveBombSoundThinkContext ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flInterval - -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::MoveToDivebomb(float flInterval) -{ - float myAccel = 1600; - float myDecay = 0.05f; // decay current velocity to 10% in 1 second - - // Fly towards my enemy - Vector vEnemyPos = GetEnemyLKP(); - Vector vFlyDirection = vEnemyPos - GetLocalOrigin(); - VectorNormalize( vFlyDirection ); - - // Set net velocity - MoveInDirection( flInterval, m_vecDiveBombDirection, myAccel, myAccel, myDecay); - - // Spin out of control. - Vector forward; - VPhysicsGetObject()->LocalToWorldVector( &forward, Vector( 1.0, 0.0, 0.0 ) ); - AngularImpulse torque = forward * m_flDiveBombRollForce; - VPhysicsGetObject()->ApplyTorqueCenter( torque ); - - // BUGBUG: why Y axis and not Z? - Vector up; - VPhysicsGetObject()->LocalToWorldVector( &up, Vector( 0.0, 1.0, 0.0 ) ); - VPhysicsGetObject()->ApplyForceCenter( up * 2000 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_BaseScanner::IsEnemyPlayerInSuit() -{ - if( GetEnemy() && GetEnemy()->IsPlayer() ) - { - CHL2_Player *pPlayer = NULL; - pPlayer = (CHL2_Player *)GetEnemy(); - - if( pPlayer && pPlayer->IsSuitEquipped() ) - { - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CNPC_BaseScanner::GetGoalDistance( void ) -{ - if ( m_flGoalOverrideDistance != 0.0f ) - return m_flGoalOverrideDistance; - - switch ( m_nFlyMode ) - { - case SCANNER_FLY_ATTACK: - { - float goalDist = ( m_flAttackNearDist + ( ( m_flAttackFarDist - m_flAttackNearDist ) / 2 ) ); - if( IsEnemyPlayerInSuit() ) - { - goalDist *= 0.5; - } - return goalDist; - } - break; - default: - break; - } - - return 128.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &vOut - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_BaseScanner::GetGoalDirection( Vector *vOut ) -{ - CBaseEntity *pTarget = GetTarget(); - - if ( pTarget == NULL ) - return false; - - if ( FClassnameIs( pTarget, "info_hint_air" ) || FClassnameIs( pTarget, "info_target" ) ) - { - AngleVectors( pTarget->GetAbsAngles(), vOut ); - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Vector CNPC_BaseScanner::VelocityToEvade(CBaseCombatCharacter *pEnemy) -{ - if (pEnemy) - { - // ----------------------------------------- - // Keep out of enemy's shooting position - // ----------------------------------------- - Vector vEnemyFacing = pEnemy->BodyDirection2D( ); - Vector vEnemyDir = pEnemy->EyePosition() - GetLocalOrigin(); - VectorNormalize(vEnemyDir); - float fDotPr = DotProduct(vEnemyFacing,vEnemyDir); - - if (fDotPr < -0.9) - { - Vector vDirUp(0,0,1); - Vector vDir; - CrossProduct( vEnemyFacing, vDirUp, vDir); - - Vector crossProduct; - CrossProduct(vEnemyFacing, vEnemyDir, crossProduct); - if (crossProduct.y < 0) - { - vDir = vDir * -1; - } - return (vDir); - } - else if (fDotPr < -0.85) - { - Vector vDirUp(0,0,1); - Vector vDir; - CrossProduct( vEnemyFacing, vDirUp, vDir); - - Vector crossProduct; - CrossProduct(vEnemyFacing, vEnemyDir, crossProduct); - if (random->RandomInt(0,1)) - { - vDir = vDir * -1; - } - return (vDir); - } - } - return vec3_origin; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_BaseScanner::DrawDebugTextOverlays(void) -{ - int nOffset = BaseClass::DrawDebugTextOverlays(); - - if ( m_debugOverlays & OVERLAY_TEXT_BIT ) - { - Vector vel; - GetVelocity( &vel, NULL ); - - char tempstr[512]; - Q_snprintf( tempstr, sizeof(tempstr), "speed (max): %.2f (%.2f)", vel.Length(), m_flSpeed ); - EntityText( nOffset, tempstr, 0 ); - nOffset++; - } - - return nOffset; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CNPC_BaseScanner::GetHeadTurnRate( void ) -{ - if ( GetEnemy() ) - return 800.0f; - - return 350.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -inline CBaseEntity *CNPC_BaseScanner::EntityToWatch( void ) -{ - return ( GetTarget() != NULL ) ? GetTarget() : GetEnemy(); // Okay if NULL -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flInterval - -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::UpdateHead( float flInterval ) -{ - float yaw = GetPoseParameter( m_nPoseFaceHoriz ); - float pitch = GetPoseParameter( m_nPoseFaceVert ); - - CBaseEntity *pTarget = EntityToWatch(); - - Vector vLookPos; - - if ( !HasCondition( COND_IN_PVS ) || GetAttachment( "eyes", vLookPos ) == false ) - { - vLookPos = EyePosition(); - } - - if ( pTarget != NULL ) - { - Vector lookDir = pTarget->EyePosition() - vLookPos; - VectorNormalize( lookDir ); - - if ( DotProduct( lookDir, BodyDirection3D() ) < 0.0f ) - { - SetPoseParameter( m_nPoseFaceHoriz, UTIL_Approach( 0, yaw, 10 ) ); - SetPoseParameter( m_nPoseFaceVert, UTIL_Approach( 0, pitch, 10 ) ); - - return; - } - - float facingYaw = VecToYaw( BodyDirection3D() ); - float yawDiff = VecToYaw( lookDir ); - yawDiff = UTIL_AngleDiff( yawDiff, facingYaw + yaw ); - - float facingPitch = UTIL_VecToPitch( BodyDirection3D() ); - float pitchDiff = UTIL_VecToPitch( lookDir ); - pitchDiff = UTIL_AngleDiff( pitchDiff, facingPitch + pitch ); - - SetPoseParameter( m_nPoseFaceHoriz, UTIL_Approach( yaw + yawDiff, yaw, 50 ) ); - SetPoseParameter( m_nPoseFaceVert, UTIL_Approach( pitch + pitchDiff, pitch, 50 ) ); - } - else - { - SetPoseParameter( m_nPoseFaceHoriz, UTIL_Approach( 0, yaw, 10 ) ); - SetPoseParameter( m_nPoseFaceVert, UTIL_Approach( 0, pitch, 10 ) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &linear - -// &angular - -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::ClampMotorForces( Vector &linear, AngularImpulse &angular ) -{ - // limit reaction forces - if ( m_nFlyMode != SCANNER_FLY_DIVE ) - { - linear.x = clamp( linear.x, -500, 500 ); - linear.y = clamp( linear.y, -500, 500 ); - linear.z = clamp( linear.z, -500, 500 ); - } - - // If we're dive bombing, we need to drop faster than normal - if ( m_nFlyMode != SCANNER_FLY_DIVE ) - { - // Add in weightlessness - linear.z += 800; - } - - angular.z = clamp( angular.z, -GetHeadTurnRate(), GetHeadTurnRate() ); - if ( m_nFlyMode == SCANNER_FLY_DIVE ) - { - // Disable pitch and roll motors while crashing. - angular.x = 0; - angular.y = 0; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::InputSetDistanceOverride( inputdata_t &inputdata ) -{ - m_flGoalOverrideDistance = inputdata.value.Float(); -} - -//----------------------------------------------------------------------------- -// Purpose: Emit sounds specific to the NPC's state. -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::AlertSound(void) -{ - ScannerEmitSound( "Alert" ); -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CNPC_BaseScanner::DeathSound( const CTakeDamageInfo &info ) -{ - ScannerEmitSound( "Die" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Overridden so that scanners play battle sounds while fighting. -// Output : Returns TRUE on success, FALSE on failure. -//----------------------------------------------------------------------------- -bool CNPC_BaseScanner::ShouldPlayIdleSound( void ) -{ - if ( HasSpawnFlags( SF_NPC_GAG ) ) - return false; - - if ( random->RandomInt( 0, 25 ) != 0 ) - return false; - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Plays sounds while idle or in combat. -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::IdleSound(void) -{ - if ( m_NPCState == NPC_STATE_COMBAT ) - { - // dvs: the combat sounds should be related to what is happening, rather than random - ScannerEmitSound( "Combat" ); - } - else - { - ScannerEmitSound( "Idle" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Plays a sound when hurt. -//----------------------------------------------------------------------------- -void CNPC_BaseScanner::PainSound( const CTakeDamageInfo &info ) -{ - ScannerEmitSound( "Pain" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CNPC_BaseScanner::GetMaxSpeed() -{ - return SCANNER_MAX_SPEED; -} - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC( npc_basescanner, CNPC_BaseScanner ) - - DECLARE_TASK( TASK_SCANNER_SET_FLY_PATROL ) - DECLARE_TASK( TASK_SCANNER_SET_FLY_CHASE ) - DECLARE_TASK( TASK_SCANNER_SET_FLY_ATTACK ) - DECLARE_TASK( TASK_SCANNER_SET_FLY_DIVE ) - - DECLARE_CONDITION(COND_SCANNER_FLY_CLEAR) - DECLARE_CONDITION(COND_SCANNER_FLY_BLOCKED) - DECLARE_CONDITION(COND_SCANNER_RELEASED_FROM_PHYSCANNON) - DECLARE_CONDITION(COND_SCANNER_GRABBED_BY_PHYSCANNON) - - //========================================================= - // > SCHED_SCANNER_PATROL - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_SCANNER_PATROL, - - " Tasks" - " TASK_SCANNER_SET_FLY_PATROL 0" - " TASK_SET_TOLERANCE_DISTANCE 32" - " TASK_SET_ROUTE_SEARCH_TIME 5" // Spend 5 seconds trying to build a path if stuck - " TASK_GET_PATH_TO_RANDOM_NODE 2000" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_GIVE_WAY" - " COND_NEW_ENEMY" - " COND_SEE_ENEMY" - " COND_SEE_FEAR" - " COND_HEAR_COMBAT" - " COND_HEAR_DANGER" - " COND_HEAR_PLAYER" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_PROVOKED" - " COND_SCANNER_GRABBED_BY_PHYSCANNON" - ) - - //========================================================= - // > SCHED_SCANNER_ATTACK - // - // This task does nothing. Translate it in your derived - // class to perform your attack. - // - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_SCANNER_ATTACK, - - " Tasks" - " TASK_SCANNER_SET_FLY_ATTACK 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT 0.1" - "" - " Interrupts" - " COND_TOO_FAR_TO_ATTACK" - " COND_SCANNER_FLY_BLOCKED" - " COND_NEW_ENEMY" - " COND_SCANNER_GRABBED_BY_PHYSCANNON" - ) - - //========================================================= - // > SCHED_SCANNER_ATTACK_HOVER - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_SCANNER_ATTACK_HOVER, - - " Tasks" - " TASK_SCANNER_SET_FLY_ATTACK 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT 0.1" - "" - " Interrupts" - " COND_TOO_FAR_TO_ATTACK" - " COND_SCANNER_FLY_BLOCKED" - " COND_NEW_ENEMY" - " COND_SCANNER_GRABBED_BY_PHYSCANNON" - ) - - //========================================================= - // > SCHED_SCANNER_ATTACK_DIVEBOMB - // - // Only done when scanner is dead - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_SCANNER_ATTACK_DIVEBOMB, - - " Tasks" - " TASK_SCANNER_SET_FLY_DIVE 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT 10" - "" - " Interrupts" - " COND_SCANNER_GRABBED_BY_PHYSCANNON" - ) - - //========================================================= - // > SCHED_SCANNER_CHASE_ENEMY - // - // Different interrupts than normal chase enemy. - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_SCANNER_CHASE_ENEMY, - - " Tasks" - " TASK_SCANNER_SET_FLY_CHASE 0" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_SCANNER_PATROL" - " TASK_SET_TOLERANCE_DISTANCE 120" - " TASK_GET_PATH_TO_ENEMY 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - "" - " Interrupts" - " COND_SCANNER_FLY_CLEAR" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_LOST_ENEMY" - " COND_SCANNER_GRABBED_BY_PHYSCANNON" - ) - - //========================================================= - // > SCHED_SCANNER_CHASE_TARGET - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_SCANNER_CHASE_TARGET, - - " Tasks" - " TASK_SCANNER_SET_FLY_CHASE 0" - " TASK_SET_TOLERANCE_DISTANCE 64" - " TASK_GET_PATH_TO_TARGET 0" //FIXME: This is wrong! - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_SCANNER_FLY_CLEAR" - " COND_NEW_ENEMY" - " COND_SCANNER_GRABBED_BY_PHYSCANNON" - ) - - //========================================================= - // > SCHED_SCANNER_FOLLOW_HOVER - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_SCANNER_FOLLOW_HOVER, - - " Tasks" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT 0.1" - "" - " Interrupts" - " COND_SCANNER_FLY_BLOCKED" - " COND_SCANNER_GRABBED_BY_PHYSCANNON" - ) - - //========================================================= - // > SCHED_SCANNER_HELD_BY_PHYSCANNON - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_SCANNER_HELD_BY_PHYSCANNON, - - " Tasks" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT 5.0" - "" - " Interrupts" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_SCANNER_RELEASED_FROM_PHYSCANNON" - ) - -AI_END_CUSTOM_NPC() diff --git a/game/server/hl2/npc_basescanner.h b/game/server/hl2/npc_basescanner.h deleted file mode 100644 index 81908125c..000000000 --- a/game/server/hl2/npc_basescanner.h +++ /dev/null @@ -1,256 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef NPC_BASESCANNER_H -#define NPC_BASESCANNER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "cbase.h" -#include "player_pickup.h" -#include "weapon_physcannon.h" -#include "hl2_player.h" -#include "smoke_trail.h" -#include "ai_basenpc_physicsflyer.h" - -//----------------------------------------------------------------------------- -// States for the scanner's sound. -//----------------------------------------------------------------------------- -enum ScannerFlyMode_t -{ - SCANNER_FLY_PHOTO = 0, // Fly close to photograph entity - SCANNER_FLY_PATROL, // Fly slowly around the enviroment - SCANNER_FLY_FAST, // Fly quickly around the enviroment - SCANNER_FLY_CHASE, // Fly quickly around the enviroment - SCANNER_FLY_SPOT, // Fly above enity in spotlight position - SCANNER_FLY_ATTACK, // Get in my enemies face for spray or flash - SCANNER_FLY_DIVE, // Divebomb - only done when dead - SCANNER_FLY_FOLLOW, // Following a target -}; - -enum ScannerInspectAct_t -{ - SCANNER_INSACT_HANDS_UP, - SCANNER_INSACT_SHOWARMBAND, -}; - -// Sentences -#define SCANNER_SENTENCE_ATTENTION 0 -#define SCANNER_SENTENCE_HANDSUP 1 -#define SCANNER_SENTENCE_PROCEED 2 -#define SCANNER_SENTENCE_CURIOUS 3 - -// Scanner attack distances -#define SCANNER_ATTACK_NEAR_DIST 150 // Fly attack min distance -#define SCANNER_ATTACK_FAR_DIST 300 // Fly attack max distance -#define SCANNER_ATTACK_RANGE 350 // Attack max distance -#define SCANNER_ATTACK_MIN_DELAY 8 // Min time between attacks -#define SCANNER_ATTACK_MAX_DELAY 12 // Max time between attacks -#define SCANNER_EVADE_TIME 1 // How long to evade after take damage - -// Scanner movement vars -#define SCANNER_BANK_RATE 30 -#define SCANNER_MAX_SPEED 250 -#define SCANNER_MAX_DIVE_BOMB_SPEED 2500 -#define SCANNER_SQUAD_FLY_DIST 500 // How far to scanners stay apart -#define SCANNER_SQUAD_HELP_DIST 4000 // How far will I fly to help - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CNPC_BaseScanner : public CAI_BasePhysicsFlyingBot, public CDefaultPlayerPickupVPhysics -{ - DECLARE_CLASS( CNPC_BaseScanner, CAI_BasePhysicsFlyingBot ); - -public: - CNPC_BaseScanner(); - - void Spawn(void); - - virtual void UpdateEfficiency( bool bInPVS ); - - Class_T Classify( void ) { return(CLASS_SCANNER); } - virtual float GetAutoAimRadius(); - - void Event_Killed( const CTakeDamageInfo &info ); - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - int OnTakeDamage_Dying( const CTakeDamageInfo &info ); - void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - void Gib(void); - - void OnStateChange( NPC_STATE eOldState, NPC_STATE eNewState ); - void ClampMotorForces( Vector &linear, AngularImpulse &angular ); - - int DrawDebugTextOverlays(void); - - virtual float GetHeadTurnRate( void ); - - virtual void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); - - // CDefaultPlayerPickupVPhysics - void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ); - void OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ); - - bool ShouldPlayIdleSound( void ); - void IdleSound( void ); - void DeathSound( const CTakeDamageInfo &info ); - void AlertSound( void ); - void PainSound( const CTakeDamageInfo &info ); - virtual const char *GetScannerSoundPrefix( void ) { return ""; } - void ScannerEmitSound( const char *pszSoundName ); - - int MeleeAttack1Conditions ( float flDot, float flDist ); - - int SelectSchedule(void); - void StartTask( const Task_t *pTask ); - void OnScheduleChange( void ); - void UpdateOnRemove( void ); - virtual float GetMaxSpeed( void ); - - void PostRunStopMoving() {} // scanner can use "movement" activities but not be moving - - virtual bool CanBecomeServerRagdoll( void ) { return false; } - - void SpeakSentence( int sentenceType ); - - bool IsHeldByPhyscannon( void ); - - // Inputs - void InputSetFlightSpeed( inputdata_t &inputdata ); - void InputSetDistanceOverride( inputdata_t &inputdata ); - -protected: - virtual const char *GetEngineSound( void ) { return NULL; } - void PlayFlySound(void); - - void SetBanking( float flInterval ); - void UpdateHead( float flInterval ); - inline CBaseEntity *EntityToWatch( void ); - - bool IsEnemyPlayerInSuit( void ); - - // Movement - virtual bool OverridePathMove( CBaseEntity *pMoveTarget, float flInterval ); - virtual bool OverrideMove( float flInterval ); - Vector IdealGoalForMovement( const Vector &goalPos, const Vector &startPos, float idealRange, float idealHeight ); - virtual void AdjustScannerVelocity( void ) { return; } - virtual void MoveToAttack(float flInterval); - virtual void MoveToTarget( float flInterval, const Vector &vecMoveTarget ); - virtual void MoveExecute_Alive(float flInterval); - virtual float MinGroundDist(void) { return 64; } - Vector VelocityToEvade(CBaseCombatCharacter *pEnemy); - virtual float GetGoalDistance( void ); - - // Divebombing - virtual void AttackDivebomb( void ); - void DiveBombSoundThink(); - void AttackDivebombCollide(float flInterval); - void MoveToDivebomb(float flInterval); - void BlendPhyscannonLaunchSpeed(); - -private: - bool GetGoalDirection( Vector *vOut ); - - void StartSmokeTrail( void ); - - // Take damage from being thrown by a physcannon - void TakeDamageFromPhyscannon( CBasePlayer *pPlayer ); - - // Take damage from physics impacts - void TakeDamageFromPhysicsImpact( int index, gamevcollisionevent_t *pEvent ); - - // Do we have a physics attacker? - CBasePlayer *HasPhysicsAttacker( float dt ); - - virtual void StopLoopingSounds(void); - -public: - // ------------------------ - // Death Cleanup - // ------------------------ - CTakeDamageInfo m_KilledInfo; - -protected: - ScannerFlyMode_t m_nFlyMode; - - // Pose parameters - int m_nPoseTail; - int m_nPoseDynamo; - int m_nPoseFlare; - int m_nPoseFaceVert; - int m_nPoseFaceHoriz; - - bool m_bHasSpoken; - - // Movement - float m_flFlyNoiseBase; - float m_flEngineStallTime; - float m_fNextFlySoundTime; - Vector m_vecDiveBombDirection; // The direction we dive bomb. Calculated at the moment of death. - float m_flDiveBombRollForce; // Used for roll while dive bombing. - - float m_flGoalOverrideDistance; - - // Deriver scanner variables - float m_flAttackNearDist; - float m_flAttackFarDist; - float m_flAttackRange; - -private: - CSoundPatch *m_pEngineSound; - - // physics influence - CHandle m_hPhysicsAttacker; - float m_flLastPhysicsInfluenceTime; - - // Attacks - SmokeTrail *m_pSmokeTrail; - -protected: - DEFINE_CUSTOM_AI; - - // Custom interrupt conditions - enum - { - COND_SCANNER_FLY_CLEAR = BaseClass::NEXT_CONDITION, - COND_SCANNER_FLY_BLOCKED, - COND_SCANNER_GRABBED_BY_PHYSCANNON, - COND_SCANNER_RELEASED_FROM_PHYSCANNON, - - NEXT_CONDITION, - }; - - // Custom schedules - enum - { - SCHED_SCANNER_PATROL = BaseClass::NEXT_SCHEDULE, - SCHED_SCANNER_ATTACK, - SCHED_SCANNER_ATTACK_HOVER, - SCHED_SCANNER_ATTACK_DIVEBOMB, - SCHED_SCANNER_CHASE_ENEMY, - SCHED_SCANNER_CHASE_TARGET, - SCHED_SCANNER_FOLLOW_HOVER, - SCHED_SCANNER_HELD_BY_PHYSCANNON, - - NEXT_SCHEDULE, - }; - - // Custom tasks - enum - { - TASK_SCANNER_SET_FLY_PATROL = BaseClass::NEXT_TASK, - TASK_SCANNER_SET_FLY_CHASE, - TASK_SCANNER_SET_FLY_ATTACK, - TASK_SCANNER_SET_FLY_DIVE, - - NEXT_TASK, - }; - - DECLARE_DATADESC(); -}; - -#endif // NPC_BASESCANNER_H diff --git a/game/server/hl2/npc_blob.cpp b/game/server/hl2/npc_blob.cpp deleted file mode 100644 index c3de8ea6e..000000000 --- a/game/server/hl2/npc_blob.cpp +++ /dev/null @@ -1,1379 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// npc_blob - experimental, cpu-intensive monster made of lots of smaller elements -// -//=============================================================================// -#include "cbase.h" -#include "ai_default.h" -#include "ai_task.h" -#include "ai_schedule.h" -#include "ai_hull.h" -#include "soundent.h" -#include "game.h" -#include "npcevent.h" -#include "entitylist.h" -#include "activitylist.h" -#include "ai_basenpc.h" -#include "engine/IEngineSound.h" -#include "vstdlib/jobthread.h" -#include "saverestore_utlvector.h" -#include "eventqueue.h" -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern float MOVE_HEIGHT_EPSILON; - -#define BLOB_MAX_AVOID_ORIGINS 3 - -ConVar blob_mindist( "blob_mindist", "120.0" ); -ConVar blob_element_speed( "blob_element_speed", "187" ); -ConVar npc_blob_idle_speed_factor( "npc_blob_idle_speed_factor", "0.5" ); - -ConVar blob_numelements( "blob_numelements", "20" ); -ConVar blob_batchpercent( "blob_batchpercent", "100" ); - -ConVar blob_radius( "blob_radius", "160" ); - -//ConVar blob_min_element_speed( "blob_min_element_speed", "50" ); -//ConVar blob_max_element_speed( "blob_max_element_speed", "250" ); - -ConVar npc_blob_use_threading( "npc_blob_use_threading", "1" ); - -ConVar npc_blob_sin_amplitude( "npc_blob_sin_amplitude", "60.0f" ); - -ConVar npc_blob_show_centroid( "npc_blob_show_centroid", "0" ); - -ConVar npc_blob_straggler_dist( "npc_blob_straggler_dist", "240" ); - -ConVar npc_blob_use_orientation( "npc_blob_use_orientation", "1" ); -ConVar npc_blob_use_model( "npc_blob_use_model", "2" ); - -ConVar npc_blob_think_interval( "npc_blob_think_interval", "0.025" ); - - -#define NPC_BLOB_MODEL "models/headcrab.mdl" - -//========================================================= -// Blob movement rules -//========================================================= -enum -{ - BLOB_MOVE_SWARM = 0, // Just swarm with the rest of the group - BLOB_MOVE_TO_TARGET_LOCATION, // Move to a designated location - BLOB_MOVE_TO_TARGET_ENTITY, // Chase the designated entity - BLOB_MOVE_DONT_MOVE, // Sit still!!!! -}; - -//========================================================= -//========================================================= -class CBlobElement : public CBaseAnimating -{ -public: - void Precache(); - void Spawn(); - int DrawDebugTextOverlays(void); - - void SetElementVelocity( Vector vecVelocity, bool bPlanarOnly ); - void AddElementVelocity( Vector vecVelocityAdd, bool bPlanarOnly ); - void ModifyVelocityForSurface( float flInterval, float flSpeed ); - - void SetSinePhase( float flPhase ) { m_flSinePhase = flPhase; } - float GetSinePhase() { return m_flSinePhase; } - - float GetSineAmplitude() { return m_flSineAmplitude; } - float GetSineFrequency() { return m_flSineFrequency; } - - void SetActiveMovementRule( int moveRule ) { m_iMovementRule = moveRule; } - int GetActiveMovementRule() { return m_iMovementRule; } - - void MoveTowardsTargetEntity( float speed ); - void SetTargetEntity( CBaseEntity *pEntity ) { m_hTargetEntity = pEntity; } - CBaseEntity *GetTargetEntity() { return m_hTargetEntity.Get(); } - - void MoveTowardsTargetLocation( float speed ); - void SetTargetLocation( const Vector &vecLocation ) { m_vecTargetLocation = vecLocation; } - - void ReconfigureRandomParams(); - void EnforceSpeedLimits( float flMinSpeed, float flMaxSpeed ); - - DECLARE_DATADESC(); - -public: - Vector m_vecPrevOrigin; // Only exists for debugging (isolating stuck elements) - int m_iStuckCount; - bool m_bOnWall; - float m_flDistFromCentroidSqr; - int m_iElementNumber; - Vector m_vecTargetLocation; - float m_flRandomEightyPercent; - -private: - EHANDLE m_hTargetEntity; - float m_flSinePhase; - float m_flSineAmplitude; - float m_flSineFrequency; - int m_iMovementRule; -}; -LINK_ENTITY_TO_CLASS( blob_element, CBlobElement ); - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CBlobElement ) - -DEFINE_FIELD( m_vecPrevOrigin, FIELD_POSITION_VECTOR ), -DEFINE_FIELD( m_iStuckCount, FIELD_INTEGER ), -DEFINE_FIELD( m_bOnWall, FIELD_BOOLEAN ), -DEFINE_FIELD( m_flDistFromCentroidSqr, FIELD_FLOAT ), -DEFINE_FIELD( m_iElementNumber, FIELD_INTEGER ), -DEFINE_FIELD( m_vecTargetLocation, FIELD_POSITION_VECTOR ), -DEFINE_FIELD( m_hTargetEntity, FIELD_EHANDLE ), -DEFINE_FIELD( m_flSinePhase, FIELD_FLOAT ), -DEFINE_FIELD( m_flSineAmplitude, FIELD_FLOAT ), -DEFINE_FIELD( m_flSineFrequency, FIELD_FLOAT ), -DEFINE_FIELD( m_iMovementRule, FIELD_INTEGER ), - -END_DATADESC() - - -const char *pszBlobModels[] = -{ - "models/gibs/agibs.mdl", - "models/props_junk/watermelon01.mdl", - "models/w_squeak.mdl", - "models/baby_headcrab.mdl" -}; - -const char *GetBlobModelName() -{ - int index = npc_blob_use_model.GetInt(); - - return pszBlobModels[ index ]; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBlobElement::Precache() -{ - PrecacheModel( GetBlobModelName() ); - - m_flRandomEightyPercent = random->RandomFloat( 0.8f, 1.0f ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBlobElement::Spawn() -{ - Precache(); - - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_FLY ); - AddSolidFlags( FSOLID_NOT_STANDABLE | FSOLID_NOT_SOLID ); - - SetModel( GetBlobModelName() ); - UTIL_SetSize( this, vec3_origin, vec3_origin ); - - QAngle angles(0,0,0); - angles.y = random->RandomFloat( 0, 180 ); - SetAbsAngles( angles ); - - AddEffects( EF_NOSHADOW ); - - ReconfigureRandomParams(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CBlobElement::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - Q_snprintf(tempstr,sizeof(tempstr), "Element #:%d", m_iElementNumber ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} - - -//--------------------------------------------------------- -// This is the official way to set velocity for an element -// Do not call SetAbsVelocity() directly, since we also -// need to record the last velocity we intended to give the -// element, so that we can detect changes after game physics -// runs. -//--------------------------------------------------------- -void CBlobElement::SetElementVelocity( Vector vecVelocity, bool bPlanarOnly ) -{ - SetAbsVelocity( vecVelocity ); -} - -//--------------------------------------------------------- -// This is the official way to add velocity to an element. -// See SetElementVelocity() for explanation. -//--------------------------------------------------------- -void CBlobElement::AddElementVelocity( Vector vecVelocityAdd, bool bPlanarOnly ) -{ - Vector vecSum = GetAbsVelocity() + vecVelocityAdd; - SetAbsVelocity( vecSum ); -} - -//--------------------------------------------------------- -// This function seeks to keep the blob element moving along -// multiple different types of surfaces (climbing walls, etc) -//--------------------------------------------------------- -#define BLOB_TRACE_HEIGHT 8.0f -void CBlobElement::ModifyVelocityForSurface( float flInterval, float flSpeed ) -{ - trace_t tr; - Vector vecStart = GetAbsOrigin(); - Vector up = Vector( 0, 0, BLOB_TRACE_HEIGHT ); - - Vector vecWishedGoal = vecStart + (GetAbsVelocity() * flInterval); - - UTIL_TraceLine( vecStart + up, vecWishedGoal + up, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - //NDebugOverlay::Line( tr.startpos, tr.endpos, 255, 0, 0, false, 0.1f ); - - m_bOnWall = false; - - if( tr.fraction == 1.0f ) - { - UTIL_TraceLine( vecWishedGoal + up, vecWishedGoal - (up * 2.0f), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - //NDebugOverlay::Line( tr.startpos, tr.endpos, 255, 255, 0, false, 0.1f ); - tr.endpos.z += MOVE_HEIGHT_EPSILON; - } - else - { - //NDebugOverlay::Cross3D( GetAbsOrigin(), 16, 255, 255, 0, false, 0.025f ); - - m_bOnWall = true; - - if( tr.m_pEnt != NULL && !tr.m_pEnt->IsWorld() ) - { - IPhysicsObject *pPhysics = tr.m_pEnt->VPhysicsGetObject(); - - if( pPhysics != NULL ) - { - Vector vecMassCenter; - Vector vecMassCenterWorld; - - vecMassCenter = pPhysics->GetMassCenterLocalSpace(); - pPhysics->LocalToWorld( &vecMassCenterWorld, vecMassCenter ); - - if( tr.endpos.z > vecMassCenterWorld.z ) - { - pPhysics->ApplyForceOffset( (-150.0f * m_flRandomEightyPercent) * tr.plane.normal, tr.endpos ); - } - } - } - } - - Vector vecDir = tr.endpos - vecStart; - VectorNormalize( vecDir ); - SetElementVelocity( vecDir * flSpeed, false ); -} - -//--------------------------------------------------------- -// Set velocity that will carry me towards a specified entity -// Most often used to move along with the npc_blob that -// is directing me. -//--------------------------------------------------------- -void CBlobElement::MoveTowardsTargetEntity( float speed ) -{ - CBaseEntity *pTarget = m_hTargetEntity.Get(); - - if( pTarget != NULL ) - { - // Try to attack my target's enemy directly if I can. - CBaseEntity *pTargetEnemy = pTarget->GetEnemy(); - - if( pTargetEnemy != NULL ) - { - pTarget = pTargetEnemy; - } - - Vector vecDir = pTarget->WorldSpaceCenter() - GetAbsOrigin(); - vecDir.NormalizeInPlace(); - SetElementVelocity( vecDir * speed, true ); - } - else - { - SetElementVelocity( vec3_origin, true ); - } -} - -//--------------------------------------------------------- -// Set velocity that will take me towards a specified location. -// This is often used to send all blob elements to specific -// locations, causing the blob to appear as though it has -// formed a specific shape. -//--------------------------------------------------------- -void CBlobElement::MoveTowardsTargetLocation( float speed ) -{ - Vector vecDir = m_vecTargetLocation - GetAbsOrigin(); - float dist = VectorNormalize( vecDir ); - - //!!!HACKHACK - how about a real way to tell if we've reached our goal? - if( dist <= 8.0f ) - { - SetActiveMovementRule( BLOB_MOVE_DONT_MOVE ); - } - - speed = MIN( dist, speed ); - - SetElementVelocity( vecDir * speed, true ); -} - -//--------------------------------------------------------- -// Pick new random numbers for the parameters that create -// variations in movement. -//--------------------------------------------------------- -void CBlobElement::ReconfigureRandomParams() -{ - m_flSinePhase = random->RandomFloat( 0.01f, 0.9f ); - m_flSineFrequency = random->RandomFloat( 10.0f, 20.0f ); - m_flSineAmplitude = random->RandomFloat( 0.5f, 1.5f ); -} - -//--------------------------------------------------------- -// Adjust velocity if this element is moving faster than -// flMaxSpeed or slower than flMinSpeed -//--------------------------------------------------------- -void CBlobElement::EnforceSpeedLimits( float flMinSpeed, float flMaxSpeed ) -{ - Vector vecVelocity = GetAbsVelocity(); - float flSpeed = VectorNormalize( vecVelocity ); - - if( flSpeed > flMaxSpeed ) - { - SetElementVelocity( vecVelocity * flMaxSpeed, true ); - } - else if( flSpeed < flMinSpeed ) - { - SetElementVelocity( vecVelocity * flMinSpeed, true ); - } -} - -//========================================================= -// Custom schedules -//========================================================= -enum -{ - SCHED_MYCUSTOMSCHEDULE = LAST_SHARED_SCHEDULE, -}; - -//========================================================= -// Custom tasks -//========================================================= -enum -{ - TASK_MYCUSTOMTASK = LAST_SHARED_TASK, -}; - - -//========================================================= -// Custom Conditions -//========================================================= -enum -{ - COND_MYCUSTOMCONDITION = LAST_SHARED_CONDITION, -}; - - -//========================================================= -//========================================================= -class CNPC_Blob : public CAI_BaseNPC -{ - DECLARE_CLASS( CNPC_Blob, CAI_BaseNPC ); - -public: - CNPC_Blob(); - void Precache( void ); - void Spawn( void ); - Class_T Classify( void ); - void RunAI(); - void GatherConditions( void ); - int SelectSchedule( void ); - int GetSoundInterests( void ) { return (SOUND_BUGBAIT); } - - - void ComputeCentroid(); - - void DoBlobBatchedAI( int iStart, int iEnd ); - - int ComputeBatchSize(); - void AdvanceBatch(); - int GetBatchStart(); - int GetBatchEnd(); - - CBlobElement *CreateNewElement(); - void InitializeElements(); - void RecomputeIdealElementDist(); - - void RemoveAllElementsExcept( int iExempt ); - - void RemoveExcessElements( int iNumElements ); - void AddNewElements( int iNumElements ); - - void FormShapeFromPath( string_t iszPathName ); - void SetRadius( float flRadius ); - - DECLARE_DATADESC(); - - int m_iNumElements; - bool m_bInitialized; - int m_iBatchStart; - Vector m_vecCentroid; - float m_flMinElementDist; - - CUtlVector >m_Elements; - - DEFINE_CUSTOM_AI; - -public: - void InputFormPathShape( inputdata_t &inputdata ); - void InputSetRadius( inputdata_t &inputdata ); - void InputChaseEntity( inputdata_t &inputdata ); - void InputIsolateElement( inputdata_t &inputdata ); - void InputFormHemisphere( inputdata_t &inputdata ); - void InputFormTwoSpheres( inputdata_t &inputdata ); - -public: - Vector m_vecAvoidOrigin[ BLOB_MAX_AVOID_ORIGINS ]; - float m_flAvoidRadiusSqr; - -private: - int m_iReconfigureElement; - int m_iNumAvoidOrigins; - - bool m_bEatCombineHack; -}; - -LINK_ENTITY_TO_CLASS( npc_blob, CNPC_Blob ); -IMPLEMENT_CUSTOM_AI( npc_blob,CNPC_Blob ); - - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CNPC_Blob ) - -DEFINE_FIELD( m_iNumElements, FIELD_INTEGER ), -DEFINE_FIELD( m_bInitialized, FIELD_BOOLEAN ), -DEFINE_FIELD( m_iBatchStart, FIELD_INTEGER ), -DEFINE_FIELD( m_vecCentroid, FIELD_POSITION_VECTOR ), -DEFINE_FIELD( m_flMinElementDist, FIELD_FLOAT ), -DEFINE_FIELD( m_iReconfigureElement, FIELD_INTEGER ), -DEFINE_UTLVECTOR( m_Elements, FIELD_EHANDLE ), - -DEFINE_INPUTFUNC( FIELD_STRING, "FormPathShape", InputFormPathShape ), -DEFINE_INPUTFUNC( FIELD_FLOAT, "SetRadius", InputSetRadius ), -DEFINE_INPUTFUNC( FIELD_STRING, "ChaseEntity", InputChaseEntity ), -DEFINE_INPUTFUNC( FIELD_INTEGER, "IsolateElement", InputIsolateElement ), -DEFINE_INPUTFUNC( FIELD_VOID, "FormHemisphere", InputFormHemisphere ), -DEFINE_INPUTFUNC( FIELD_VOID, "FormTwoSpheres", InputFormTwoSpheres ), - -END_DATADESC() - -//--------------------------------------------------------- -//--------------------------------------------------------- -CNPC_Blob::CNPC_Blob() -{ - m_iNumElements = 0; - m_bInitialized = false; - m_iBatchStart = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: Initialize the custom schedules -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_Blob::InitCustomSchedules(void) -{ - INIT_CUSTOM_AI(CNPC_Blob); - - ADD_CUSTOM_TASK(CNPC_Blob, TASK_MYCUSTOMTASK); - - ADD_CUSTOM_SCHEDULE(CNPC_Blob, SCHED_MYCUSTOMSCHEDULE); - - ADD_CUSTOM_CONDITION(CNPC_Blob, COND_MYCUSTOMCONDITION); -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CNPC_Blob::Precache( void ) -{ - PrecacheModel( NPC_BLOB_MODEL ); - UTIL_PrecacheOther( "blob_element" ); - - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CNPC_Blob::Spawn( void ) -{ - Precache(); - - SetModel( NPC_BLOB_MODEL ); - - SetHullType(HULL_TINY); - SetHullSizeNormal(); - - SetSolid( SOLID_NONE ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - SetBloodColor( BLOOD_COLOR_RED ); - m_iHealth = INT_MAX; - m_flFieldOfView = -1.0f; - m_NPCState = NPC_STATE_NONE; - - CapabilitiesClear(); - CapabilitiesAdd( bits_CAP_MOVE_GROUND ); - - m_Elements.RemoveAll(); - - NPCInit(); - - AddEffects( EF_NODRAW ); - - m_flMinElementDist = blob_mindist.GetFloat(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -// -// Output : -//----------------------------------------------------------------------------- -Class_T CNPC_Blob::Classify( void ) -{ - return CLASS_PLAYER_ALLY; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Blob::RunAI() -{ - BaseClass::RunAI(); - - if( !m_bInitialized ) - { - // m_bInitialized is set to false in the constructor. So this bit of - // code runs one time, the first time I think. - Msg("I need to initialize\n"); - InitializeElements(); - m_bInitialized = true; - return; - } - - int iIdealNumElements = blob_numelements.GetInt(); - if( iIdealNumElements != m_iNumElements ) - { - int delta = iIdealNumElements - m_iNumElements; - - if( delta < 0 ) - { - delta = -delta; - delta = MIN(delta, 5 ); - RemoveExcessElements( delta ); - - if( m_iReconfigureElement > m_iNumElements ) - { - // Start this index over at zero, if it is past the new end of the utlvector. - m_iReconfigureElement = 0; - } - } - else - { - delta = MIN(delta, 5 ); - AddNewElements( delta ); - } - - RecomputeIdealElementDist(); - } - - ComputeCentroid(); - - if( npc_blob_show_centroid.GetBool() ) - { - NDebugOverlay::Cross3D( m_vecCentroid + Vector( 0, 0, 12 ), 32, 0, 255, 0, false, 0.025f ); - } - - if( npc_blob_use_threading.GetBool() ) - { - IterRangeParallel( this, &CNPC_Blob::DoBlobBatchedAI, 0, m_Elements.Count() ); - } - else - { - DoBlobBatchedAI( 0, m_Elements.Count() ); - } - - if( GetEnemy() != NULL ) - { - float flEnemyDistSqr = m_vecCentroid.DistToSqr( GetEnemy()->GetAbsOrigin() ); - - if( flEnemyDistSqr <= Square( 32.0f ) ) - { - if( GetEnemy()->Classify() == CLASS_COMBINE ) - { - if( !m_bEatCombineHack ) - { - variant_t var; - - var.SetFloat( 0 ); - g_EventQueue.AddEvent( GetEnemy(), "HitByBugBait", 0.0f, this, this ); - g_EventQueue.AddEvent( GetEnemy(), "SetHealth", var, 3.0f, this, this ); - m_bEatCombineHack = true; - - blob_radius.SetValue( 48.0f ); - RecomputeIdealElementDist(); - } - } - else - { - CTakeDamageInfo info; - - info.SetAttacker( this ); - info.SetInflictor( this ); - info.SetDamage( 5 ); - info.SetDamageType( DMG_SLASH ); - info.SetDamageForce( Vector( 0, 0, 1 ) ); - - GetEnemy()->TakeDamage( info ); - } - } - } - - SetNextThink( gpGlobals->curtime + npc_blob_think_interval.GetFloat() ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Blob::GatherConditions( void ) -{ - if( m_bEatCombineHack ) - { - // We just ate someone. - if( !GetEnemy() || !GetEnemy()->IsAlive() ) - { - m_bEatCombineHack = false; - blob_radius.SetValue( 160.0f ); - RecomputeIdealElementDist(); - } - } - - BaseClass::GatherConditions(); - -} - -//----------------------------------------------------------------------------- -// Either stand still or chase the enemy, for now. -//----------------------------------------------------------------------------- -int CNPC_Blob::SelectSchedule( void ) -{ - if( GetEnemy() == NULL ) - return SCHED_IDLE_STAND; - - return SCHED_CHASE_ENEMY; -} - -//----------------------------------------------------------------------------- -// Average the origin of all elements to get the centroid for the group -//----------------------------------------------------------------------------- -void CNPC_Blob::ComputeCentroid() -{ - m_vecCentroid = vec3_origin; - - for( int i = 0 ; i < m_Elements.Count() ; i++ ) - { - m_vecCentroid += m_Elements[ i ]->GetAbsOrigin(); - } - - m_vecCentroid /= m_Elements.Count(); -} - -//----------------------------------------------------------------------------- -// Run all of the AI for elements within the range iStart to iEnd -//----------------------------------------------------------------------------- -void CNPC_Blob::DoBlobBatchedAI( int iStart, int iEnd ) -{ - float flInterval = gpGlobals->curtime - GetLastThink(); - - // Local fields for sin-wave movement variance - float flMySine; - float flAmplitude = npc_blob_sin_amplitude.GetFloat(); - float flMyAmplitude; - Vector vecRight = Vector(0.0f, 0.0f, 0.0f); - Vector vecForward; - - // Local fields for attract/repel - float minDistSqr = Square( m_flMinElementDist ); - float flBlobSpeed = blob_element_speed.GetFloat(); - float flSpeed; - - // Local fields for speed limiting - float flMinSpeed = blob_element_speed.GetFloat() * 0.5f; - float flMaxSpeed = blob_element_speed.GetFloat() * 1.5f; - bool bEnforceSpeedLimit; - bool bEnforceRelativePositions; - bool bDoMovementVariation; - bool bDoOrientation = npc_blob_use_orientation.GetBool(); - float flIdleSpeedFactor = npc_blob_idle_speed_factor.GetFloat(); - - // Group cohesion - float flBlobRadiusSqr = Square( blob_radius.GetFloat() + 48.0f ); // Four feet of fudge - - // Build a right-hand vector along which we'll add some sine wave data to give each - // element a unique insect-like undulation along an axis perpendicular to their path, - // which makes the entire group look far less orderly - if( GetEnemy() != NULL ) - { - // If I have an enemy, the right-hand vector is perpendicular to a straight line - // from the group's centroid to the enemy's origin. - vecForward = GetEnemy()->GetAbsOrigin() - m_vecCentroid; - VectorNormalize( vecForward ); - vecRight.x = vecForward.y; - vecRight.y = -vecForward.x; - } - else - { - // If there is no enemy, wobble along the axis from the centroid to me. - vecForward = GetAbsOrigin() - m_vecCentroid; - VectorNormalize( vecForward ); - vecRight.x = vecForward.y; - vecRight.y = -vecForward.x; - } - - //-- - // MAIN LOOP - Run all of the elements in the set iStart to iEnd - //-- - for( int i = iStart ; i < iEnd ; i++ ) - { - CBlobElement *pThisElement = m_Elements[ i ]; - - //-- - // Initial movement - //-- - // Start out with bEnforceSpeedLimit set to false. This is because an element - // can't overspeed if it's moving undisturbed towards its target entity or - // target location. An element can only under or overspeed when it is repelled - // by multiple other elements in the group. See "Relative Positions" below. - // - // Initialize some 'defaults' that may be changed for each iteration of this loop - bEnforceSpeedLimit = false; - bEnforceRelativePositions = true; - bDoMovementVariation = true; - flSpeed = flBlobSpeed; - - switch( pThisElement->GetActiveMovementRule() ) - { - case BLOB_MOVE_DONT_MOVE: - { - pThisElement->SetElementVelocity( vec3_origin, true ); - - trace_t tr; - Vector vecOrigin = pThisElement->GetAbsOrigin(); - - UTIL_TraceLine( vecOrigin, vecOrigin - Vector( 0, 0, 16), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - if( tr.fraction < 1.0f ) - { - QAngle angles; - - VectorAngles( tr.plane.normal, angles ); - - float flSwap = angles.x; - - angles.x = -angles.y; - angles.y = flSwap; - - pThisElement->SetAbsAngles( angles ); - } - } - continue; - break; - - case BLOB_MOVE_TO_TARGET_LOCATION: - { - Vector vecDiff = pThisElement->GetAbsOrigin() - pThisElement->m_vecTargetLocation; - - if( vecDiff.Length2DSqr() <= Square(80.0f) ) - { - // Don't shove this guy around any more, let him get to his goal position. - flSpeed *= 0.5f; - bEnforceRelativePositions = false; - bDoMovementVariation = false; - } - - pThisElement->MoveTowardsTargetLocation( flSpeed ); - } - break; - - case BLOB_MOVE_TO_TARGET_ENTITY: - { - if( !IsMoving() && GetEnemy() == NULL ) - { - if( pThisElement->GetAbsOrigin().DistToSqr( GetAbsOrigin() ) <= flBlobRadiusSqr ) - { - flSpeed = (flSpeed * flIdleSpeedFactor) * pThisElement->m_flRandomEightyPercent; - } - } - pThisElement->MoveTowardsTargetEntity( flSpeed ); - } - break; - - default: - Msg("ERROR: Blob Element with unspecified Movement Rule\n"); - break; - } - - //--- - // Relative positions - //-- - // Check this element against ALL other elements. If the two elements are closer - // than the allowed minimum distance, repel this element away. (The other element - // will repel when its AI runs). A single element can be repelled by many other - // elements. This is why bEnforceSpeedLimit is set to true if any of the repelling - // code runs for this element. Multiple attempts to repel an element in the same - // direction will cause overspeed. Conflicting attempts to repel an element in opposite - // directions will cause underspeed. - Vector vecDir = Vector( 0, 0, 0 ); - Vector vecThisElementOrigin = pThisElement->GetAbsOrigin(); - - if( bEnforceRelativePositions ) - { - for( int j = 0 ; j < m_Elements.Count() ; j++ ) - { - // This is the innermost loop! We should optimize here, if anywhere. - - // If this element is on the wall, then don't be repelled by anyone. Repelling - // elements that are trying to climb a wall usually make them look like they - // fall off the wall a few times while climbing. - if( pThisElement->m_bOnWall ) - continue; - - CBlobElement *pThatElement = m_Elements[ j ]; - if( i != j ) - { - Vector vecThatElementOrigin = pThatElement->GetAbsOrigin(); - float distSqr = vecThisElementOrigin.DistToSqr( vecThatElementOrigin ); - - if( distSqr < minDistSqr ) - { - // Too close to the other element. Move away. - float flRepelSpeed; - Vector vecRepelDir = ( vecThisElementOrigin - vecThatElementOrigin ); - - vecRepelDir.NormalizeInPlace(); - flRepelSpeed = (flSpeed * ( 1.0f - ( distSqr / minDistSqr ) ) ) * pThatElement->GetSinePhase(); - pThisElement->AddElementVelocity( vecRepelDir * flRepelSpeed, true ); - - // Since we altered this element's velocity after it was initially set, there's a chance - // that the sums of multiple vectors will cause the element to over or underspeed, so - // mark it for speed limit enforcement - bEnforceSpeedLimit = true; - } - } - } - } - - //-- - // Movement variation - //-- - if( bDoMovementVariation ) - { - flMySine = sin( gpGlobals->curtime * pThisElement->GetSineFrequency() ); - flMyAmplitude = flAmplitude * pThisElement->GetSineAmplitude(); - pThisElement->AddElementVelocity( vecRight * (flMySine * flMyAmplitude), true ); - } - - // Avoidance - for( int a = 0 ; a < m_iNumAvoidOrigins ; a++ ) - { - Vector vecAvoidDir = pThisElement->GetAbsOrigin() - m_vecAvoidOrigin[ a ]; - - if( vecAvoidDir.LengthSqr() <= (m_flAvoidRadiusSqr * pThisElement->m_flRandomEightyPercent) ) - { - VectorNormalize( vecAvoidDir ); - pThisElement->AddElementVelocity( vecAvoidDir * (flSpeed * 2.0f), true ); - break; - } - } - - //-- - // Speed limits - //--- - if( bEnforceSpeedLimit == true ) - { - pThisElement->EnforceSpeedLimits( flMinSpeed, flMaxSpeed ); - } - - //-- - // Wall crawling - //-- - pThisElement->ModifyVelocityForSurface( flInterval, flSpeed ); - - // For identifying stuck elements. - pThisElement->m_vecPrevOrigin = pThisElement->GetAbsOrigin(); - - pThisElement->m_flDistFromCentroidSqr = pThisElement->m_vecPrevOrigin.DistToSqr( m_vecCentroid ); - - // Orientation - if( bDoOrientation ) - { - QAngle angles; - VectorAngles( pThisElement->GetAbsVelocity(), angles ); - pThisElement->SetAbsAngles( angles ); - } - -/* - //-- - // Stragglers/Group integrity - // - if( pThisElement->m_flDistFromCentroidSqr > flStragglerDistSqr ) - { - NDebugOverlay::Line( pThisElement->GetAbsOrigin(), m_vecCentroid, 255, 0, 0, false, 0.025f ); - } -*/ - } -} - -//----------------------------------------------------------------------------- -// Throw out all elements and their entities except for the the specified -// index into the UTILVector. This is useful for isolating elements that -// get into a bad state. -//----------------------------------------------------------------------------- -void CNPC_Blob::RemoveAllElementsExcept( int iExempt ) -{ - if( m_Elements.Count() == 1 ) - return; - - m_Elements[ 0 ].Set( m_Elements[ iExempt ].Get() ); - - for( int i = 1 ; i < m_Elements.Count() ; i++ ) - { - if( i != iExempt ) - { - m_Elements[ i ]->SUB_Remove(); - } - } - - m_Elements.RemoveMultiple( 1, m_Elements.Count() - 1 ); - - m_iNumElements = 1; -} - -//----------------------------------------------------------------------------- -// Purpose: The blob has too many elements. Locate good candidates and remove -// this many elements. -//----------------------------------------------------------------------------- -void CNPC_Blob::RemoveExcessElements( int iNumElements ) -{ - // For now we're not assessing candidates, just blindly removing. - int i; - for( i = 0 ; i < iNumElements ; i++ ) - { - int iLastElement = m_iNumElements - 1; - - // Nuke the associated entity - m_Elements[ iLastElement ]->SUB_Remove(); - - m_Elements.Remove( iLastElement ); - m_iNumElements--; - } -} - -//----------------------------------------------------------------------------- -// Purpose: This blob has too few elements. Add this many elements by stacking -// them on top of existing elements and allowing them to disperse themselves -// into the blob. -//----------------------------------------------------------------------------- -void CNPC_Blob::AddNewElements( int iNumElements ) -{ - int i; - - // Keep track of how many elements we had when we came into this function. - // Since the new elements copy their origins from existing elements, we only want - // to copy origins from elements that existed before we came into this function. - // Otherwise, the more elements we create while in this function, the more likely it - // becomes that several of them will stack on the same origin. - int iInitialElements = m_iNumElements; - - for( i = 0 ; i < iNumElements ; i++ ) - { - CBlobElement *pElement = CreateNewElement(); - - if( pElement != NULL ) - { - // Copy the origin of some element that is not me. This will make the expansion - // of the group easier on the eye, since this element will spawn inside of some - // other element, and then be pushed out by the blob's repel rules. - int iCopyElement = random->RandomInt( 0, iInitialElements - 1 ); - pElement->SetAbsOrigin( m_Elements[iCopyElement]->GetAbsOrigin() ); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -#define BLOB_MAX_VERTS 128 -void CNPC_Blob::FormShapeFromPath( string_t iszPathName ) -{ - Vector vertex[ BLOB_MAX_VERTS ]; - - int i; - int iNumVerts = 0; - - for ( i = 0 ; i < BLOB_MAX_VERTS ; i++ ) - { - if( iszPathName == NULL_STRING ) - { - //Msg("Terminal path\n"); - break; - } - - CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, iszPathName ); - - if( pEntity != NULL ) - { - bool bClosedPath = false; - - for( int j = 0 ; j < i ; j++ ) - { - // Stop if we reach a vertex that's already in the array (closed path) - if( vertex[ j ] == pEntity->GetAbsOrigin() ) - { - //Msg("Closed path!\n"); - bClosedPath = true; - break; - } - } - - vertex[ i ] = pEntity->GetAbsOrigin(); - iszPathName = pEntity->m_target; - iNumVerts++; - - if( bClosedPath ) - break; - } - } - - //Msg("%d verts found in path!\n", iNumVerts); - - float flPathLength = 0.0f; - float flDistribution; - - for( i = 0 ; i < iNumVerts - 1 ; i++ ) - { - Vector vecDiff = vertex[ i ] - vertex[ i + 1 ]; - - flPathLength += vecDiff.Length(); - } - - flDistribution = flPathLength / m_iNumElements; - Msg("Path length is %f, distribution is %f\n", flPathLength, flDistribution ); - - int element = 0; - for( i = 0 ; i < iNumVerts - 1 ; i++ ) - { - //NDebugOverlay::Line( vertex[ i ], vertex[ i + 1 ], 0, 255, 0, false, 10.0f ); - Vector vecDiff = vertex[ i + 1 ] - vertex[ i ]; - Vector vecStart = vertex[ i ]; - - float flSegmentLength = VectorNormalize( vecDiff ); - - float flStep; - - for( flStep = 0.0f ; flStep < flSegmentLength ; flStep += flDistribution ) - { - //NDebugOverlay::Cross3D( vecStart + vecDiff * flStep, 16, 255, 255, 255, false, 10.0f ); - m_Elements[ element ]->SetTargetLocation( vecStart + vecDiff * flStep ); - m_Elements[ element ]->SetActiveMovementRule( BLOB_MOVE_TO_TARGET_LOCATION ); - element++; - - if( element == m_iNumElements ) - return; - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Blob::SetRadius( float flRadius ) -{ - blob_radius.SetValue( flRadius ); - RecomputeIdealElementDist(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Blob::InputFormPathShape( inputdata_t &inputdata ) -{ - string_t shape = inputdata.value.StringID(); - - if( shape == NULL_STRING ) - return; - - //Msg("I'm supposed to form some shape called:%s\n", shape ); - - FormShapeFromPath( shape ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Blob::InputSetRadius( inputdata_t &inputdata ) -{ - float flNewRadius = inputdata.value.Float(); - - SetRadius( flNewRadius ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Blob::InputChaseEntity( inputdata_t &inputdata ) -{ - CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, inputdata.value.StringID(), NULL, inputdata.pActivator, inputdata.pCaller ); - - if ( pEntity ) - { - for( int i = 0 ; i < m_Elements.Count() ; i++ ) - { - CBlobElement *pElement = m_Elements[ i ]; - - pElement->SetTargetEntity( pEntity ); - pElement->SetActiveMovementRule( BLOB_MOVE_TO_TARGET_ENTITY ); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Blob::InputIsolateElement( inputdata_t &inputdata ) -{ - int iElement = inputdata.value.Int(); - - RemoveAllElementsExcept( iElement ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Blob::InputFormHemisphere( inputdata_t &inputdata ) -{ - Vector center = GetAbsOrigin(); - const float flRadius = 240.0f; - - Vector vecDir; - - for( int i = 0 ; i < m_Elements.Count() ; i++ ) - { - CBlobElement *pElement = m_Elements[ i ]; - - // Compute a point around my center - vecDir.x = random->RandomFloat( -1, 1 ); - vecDir.y = random->RandomFloat( -1, 1 ); - vecDir.z = random->RandomFloat( 0, 1 ); - - VectorNormalize( vecDir ); - - pElement->SetTargetLocation( center + vecDir * flRadius ); - pElement->SetActiveMovementRule( BLOB_MOVE_TO_TARGET_LOCATION ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Blob::InputFormTwoSpheres( inputdata_t &inputdata ) -{ - Vector center = GetAbsOrigin(); - Vector sphere1 = GetAbsOrigin() + Vector( 120.0f, 0, 120.0f ); - Vector sphere2 = GetAbsOrigin() + Vector( -120.0f, 0, 120.0f ); - const float flRadius = 100.0f; - - Vector vecDir; - - int batchSize = m_Elements.Count() / 2; - - for( int i = 0 ; i < batchSize ; i++ ) - { - CBlobElement *pElement = m_Elements[ i ]; - - // Compute a point around my center - vecDir.x = random->RandomFloat( -1, 1 ); - vecDir.y = random->RandomFloat( -1, 1 ); - vecDir.z = random->RandomFloat( -1, 1 ); - - VectorNormalize( vecDir ); - - pElement->SetTargetLocation( sphere1 + vecDir * flRadius ); - pElement->SetActiveMovementRule( BLOB_MOVE_TO_TARGET_LOCATION ); - } - - for( int i = batchSize ; i < m_Elements.Count() ; i++ ) - { - CBlobElement *pElement = m_Elements[ i ]; - - // Compute a point around my center - vecDir.x = random->RandomFloat( -1, 1 ); - vecDir.y = random->RandomFloat( -1, 1 ); - vecDir.z = random->RandomFloat( -1, 1 ); - - VectorNormalize( vecDir ); - - pElement->SetTargetLocation( sphere2 + vecDir * flRadius ); - pElement->SetActiveMovementRule( BLOB_MOVE_TO_TARGET_LOCATION ); - } - -} - -//----------------------------------------------------------------------------- -// Get the index of the element to start processing with for this batch. -//----------------------------------------------------------------------------- -int CNPC_Blob::GetBatchStart() -{ - return m_iBatchStart; -} - -//----------------------------------------------------------------------------- -// Get the index of the element to stop processing with for this batch. -//----------------------------------------------------------------------------- -int CNPC_Blob::GetBatchEnd() -{ - int batchDone = m_iBatchStart + ComputeBatchSize(); - batchDone = MIN( batchDone, m_Elements.Count() ); - - return batchDone; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Blob::ComputeBatchSize() -{ - int batchSize = m_Elements.Count() / ( 100 / blob_batchpercent.GetInt() ); - return batchSize; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -void CNPC_Blob::AdvanceBatch() -{ - m_iBatchStart += ComputeBatchSize(); - - if( m_iBatchStart >= m_Elements.Count() ) - m_iBatchStart = 0; -} - -//----------------------------------------------------------------------------- -// Creates a new blob element from scratch and adds it to the blob -//----------------------------------------------------------------------------- -CBlobElement *CNPC_Blob::CreateNewElement() -{ - CBlobElement *pElement = static_cast(CreateEntityByName( "blob_element" )); - - if( pElement != NULL ) - { - pElement->SetOwnerEntity( this ); - pElement->SetSinePhase( fabs( sin(((float)m_iNumElements)/10.0f) ) ); - pElement->SetActiveMovementRule( BLOB_MOVE_TO_TARGET_ENTITY ); - pElement->SetTargetEntity( this ); - - pElement->m_iElementNumber = m_iNumElements; - m_iNumElements++; - pElement->Spawn(); - m_Elements.AddToTail( pElement ); - return pElement; - } - - Warning("Blob could not spawn new element!\n"); - return NULL; -} - -//----------------------------------------------------------------------------- -// Create, initialize, and distribute all blob elements -//----------------------------------------------------------------------------- -void CNPC_Blob::InitializeElements() -{ - // Squirt all of the elements out into a circle - int i; - QAngle angDistributor( 0, 0, 0 ); - - int iNumElements = blob_numelements.GetInt(); - - float step = 360.0f / ((float)iNumElements); - for( i = 0 ; i < iNumElements ; i++ ) - { - Vector vecDir; - Vector vecDest; - AngleVectors( angDistributor, &vecDir, NULL, NULL ); - vecDest = WorldSpaceCenter() + vecDir * 64.0f; - - CBlobElement *pElement = CreateNewElement(); - - if( !pElement ) - { - Msg("Blob could not create all elements!!\n"); - return; - } - - trace_t tr; - UTIL_TraceLine( vecDest, vecDest + Vector (0, 0, MIN_COORD_FLOAT), MASK_SHOT, pElement, COLLISION_GROUP_NONE, &tr ); - - pElement->SetAbsOrigin( tr.endpos + Vector( 0, 0, 1 ) ); - - angDistributor.y += step; - } - - CBaseEntity *pEntity = gEntList.FindEntityByClassname( NULL, "info_target" ); - for( i = 0 ; i < BLOB_MAX_AVOID_ORIGINS ; i++ ) - { - if( pEntity ) - { - if( pEntity->NameMatches("avoid") ) - { - m_vecAvoidOrigin[ i ] = pEntity->GetAbsOrigin(); - m_flAvoidRadiusSqr = Square( 120.0f ); - m_iNumAvoidOrigins++; - } - - pEntity = gEntList.FindEntityByClassname( pEntity, "info_target" ); - } - else - { - break; - } - } - - Msg("%d avoid origins\n", m_iNumAvoidOrigins ); - - RecomputeIdealElementDist(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Blob::RecomputeIdealElementDist() -{ - float radius = blob_radius.GetFloat(); - float area = M_PI * Square(radius); - - //Msg("Area of blob is: %f\n", area ); - - //m_flMinElementDist = 2.75f * sqrt( area / m_iNumElements ); - m_flMinElementDist = M_PI * sqrt( area / m_iNumElements ); - - //Msg("New element dist: %f\n", m_flMinElementDist ); -} - diff --git a/game/server/hl2/npc_breen.cpp b/game/server/hl2/npc_breen.cpp deleted file mode 100644 index e800ac7f4..000000000 --- a/game/server/hl2/npc_breen.cpp +++ /dev/null @@ -1,132 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Dr. Breen, the oft maligned genius, heroically saving humanity from -// its own worst enemy, itself. -//=============================================================================// - - -//----------------------------------------------------------------------------- -// Generic NPC - purely for scripted sequence work. -//----------------------------------------------------------------------------- -#include "cbase.h" -#include "npcevent.h" -#include "ai_basenpc.h" -#include "ai_hull.h" -#include "ai_baseactor.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// Spawnflags -#define SF_BREEN_BACKGROUND_TALK ( 1 << 16 ) // 65536 - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CNPC_Breen : public CAI_BaseActor -{ -public: - DECLARE_CLASS( CNPC_Breen, CAI_BaseActor ); - - void Spawn( void ); - void Precache( void ); - Class_T Classify ( void ); - void HandleAnimEvent( animevent_t *pEvent ); - int GetSoundInterests ( void ); - bool UseSemaphore( void ); -}; - -LINK_ENTITY_TO_CLASS( npc_breen, CNPC_Breen ); - -//----------------------------------------------------------------------------- -// Classify - indicates this NPC's place in the -// relationship table. -//----------------------------------------------------------------------------- -Class_T CNPC_Breen::Classify ( void ) -{ - return CLASS_NONE; -} - - - -//----------------------------------------------------------------------------- -// HandleAnimEvent - catches the NPC-specific messages -// that occur when tagged animation frames are played. -//----------------------------------------------------------------------------- -void CNPC_Breen::HandleAnimEvent( animevent_t *pEvent ) -{ - switch( pEvent->event ) - { - case 1: - default: - BaseClass::HandleAnimEvent( pEvent ); - break; - } -} - -//----------------------------------------------------------------------------- -// GetSoundInterests - generic NPC can't hear. -//----------------------------------------------------------------------------- -int CNPC_Breen::GetSoundInterests ( void ) -{ - return 0; -} - -//----------------------------------------------------------------------------- -// Spawn -//----------------------------------------------------------------------------- -void CNPC_Breen::Spawn() -{ - // Breen is allowed to use multiple models, because he has a torso version for monitors. - // He defaults to his normal model. - const char *szModel = (char *)STRING( GetModelName() ); - if (!szModel || !*szModel) - { - szModel = "models/breen.mdl"; - SetModelName( AllocPooledString(szModel) ); - } - - Precache(); - SetModel( szModel ); - - BaseClass::Spawn(); - - SetHullType(HULL_HUMAN); - SetHullSizeNormal(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - SetBloodColor( BLOOD_COLOR_RED ); - m_iHealth = 8; - m_flFieldOfView = 0.5;// indicates the width of this NPC's forward view cone ( as a dotproduct result ) - m_NPCState = NPC_STATE_NONE; - - CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_OPEN_DOORS | bits_CAP_ANIMATEDFACE | bits_CAP_TURN_HEAD ); - CapabilitiesAdd( bits_CAP_FRIENDLY_DMG_IMMUNE ); - AddEFlags( EFL_NO_DISSOLVE | EFL_NO_MEGAPHYSCANNON_RAGDOLL | EFL_NO_PHYSCANNON_INTERACTION ); - - NPCInit(); -} - -//----------------------------------------------------------------------------- -// Precache - precaches all resources this NPC needs -//----------------------------------------------------------------------------- -void CNPC_Breen::Precache() -{ - PrecacheModel( STRING( GetModelName() ) ); - BaseClass::Precache(); -} - -bool CNPC_Breen::UseSemaphore( void ) -{ - if ( HasSpawnFlags( SF_BREEN_BACKGROUND_TALK ) ) - return false; - - return BaseClass::UseSemaphore(); -} - -//----------------------------------------------------------------------------- -// AI Schedules Specific to this NPC -//----------------------------------------------------------------------------- - diff --git a/game/server/hl2/npc_bullseye.cpp b/game/server/hl2/npc_bullseye.cpp deleted file mode 100644 index 7c6281e6b..000000000 --- a/game/server/hl2/npc_bullseye.cpp +++ /dev/null @@ -1,473 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Bullseyes act as targets for other NPC's to attack and to trigger -// events -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "basecombatcharacter.h" -#include "ai_basenpc.h" -#include "decals.h" -#include "filters.h" -#include "npc_bullseye.h" -#include "collisionutils.h" -#include "igamesystem.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CBullseyeList : public CAutoGameSystem -{ -public: - CBullseyeList( char const *name ) : CAutoGameSystem( name ) - { - } - - virtual void LevelShutdownPostEntity() - { - Clear(); - } - - void Clear() - { - m_list.Purge(); - } - - void AddToList( CNPC_Bullseye *pBullseye ); - void RemoveFromList( CNPC_Bullseye *pBullseye ); - - CUtlVector< CNPC_Bullseye * > m_list; -}; - -void CBullseyeList::AddToList( CNPC_Bullseye *pBullseye ) -{ - m_list.AddToTail( pBullseye ); -} - -void CBullseyeList::RemoveFromList( CNPC_Bullseye *pBullseye ) -{ - int index = m_list.Find( pBullseye ); - if ( index != m_list.InvalidIndex() ) - { - m_list.FastRemove( index ); - } -} - -CBullseyeList g_BullseyeList( "CBullseyeList" ); - -int FindBullseyesInCone( CBaseEntity **pList, int listMax, const Vector &coneOrigin, const Vector &coneAxis, float coneAngleCos, float coneLength ) -{ - if ( listMax <= 0 ) - return 0; - - int count = 0; - - for ( int i = g_BullseyeList.m_list.Count() - 1; i >= 0; --i ) - { - CNPC_Bullseye *pTest = g_BullseyeList.m_list[i]; - - if ( IsPointInCone( pTest->GetAbsOrigin(), coneOrigin, coneAxis, coneAngleCos, coneLength ) ) - { - pList[count] = pTest; - count++; - if ( count >= listMax ) - break; - } - } - - return count; -} - - -ConVar sk_bullseye_health( "sk_bullseye_health","0"); - -BEGIN_DATADESC( CNPC_Bullseye ) - - DEFINE_FIELD( m_hPainPartner, FIELD_EHANDLE ), - DEFINE_KEYFIELD( m_fAutoaimRadius, FIELD_FLOAT, "autoaimradius" ), - DEFINE_KEYFIELD( m_flFieldOfView, FIELD_FLOAT, "minangle" ), - DEFINE_KEYFIELD( m_flMinDistValidEnemy, FIELD_FLOAT, "mindist" ), - // DEFINE_FIELD( m_bPerfectAccuracy, FIELD_BOOLEAN ), // Don't save - - // Function Pointers - DEFINE_THINKFUNC( BullseyeThink ), - - DEFINE_INPUTFUNC( FIELD_VOID, "InputTargeted", InputTargeted ), - DEFINE_INPUTFUNC( FIELD_VOID, "InputReleased", InputReleased ), - // Outputs - DEFINE_OUTPUT( m_OnTargeted, "OnTargeted"), - DEFINE_OUTPUT( m_OnReleased, "OnReleased"), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( npc_bullseye, CNPC_Bullseye ); - - - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -CNPC_Bullseye::CNPC_Bullseye( void ) -{ - m_takedamage = DAMAGE_YES; - m_iHealth = sk_bullseye_health.GetFloat(); - m_hPainPartner = NULL; - g_BullseyeList.AddToList( this ); - m_flFieldOfView = 360; - m_flMinDistValidEnemy = 0; -} - -CNPC_Bullseye::~CNPC_Bullseye( void ) -{ - g_BullseyeList.RemoveFromList( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Bullseye::Precache( void ) -{ - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Bullseye::Spawn( void ) -{ - Precache(); - - // This is a dummy model that is never used! - UTIL_SetSize(this, Vector(-16,-16,-16), Vector(16,16,16)); - - SetMoveType( MOVETYPE_NONE ); - SetBloodColor( BLOOD_COLOR_RED ); - ClearEffects(); - SetGravity( 0.0 ); - - m_flFieldOfView = cos( DEG2RAD(m_flFieldOfView) / 2.0 ); - - //Got blood? - if ( m_spawnflags & SF_BULLSEYE_BLEED ) - { - SetBloodColor(BLOOD_COLOR_RED); - } - else - { - SetBloodColor(DONT_BLEED); - } - - AddFlag( FL_NPC ); - AddEFlags( EFL_NO_DISSOLVE ); - - SetThink( &CNPC_Bullseye::BullseyeThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - if( m_spawnflags & SF_BULLSEYE_NONSOLID ) - { - AddSolidFlags( FSOLID_NOT_SOLID ); - } - - if ( m_spawnflags & SF_BULLSEYE_VPHYSICSSHADOW ) - { - VPhysicsInitShadow( false, false ); - } - - if( m_spawnflags & SF_BULLSEYE_NODAMAGE ) - { - m_takedamage = DAMAGE_NO; - } - else - { - m_takedamage = DAMAGE_YES; - } - AddEffects( EF_NODRAW ); - - //Check our water level - PhysicsCheckWater(); - - CapabilitiesAdd( bits_CAP_SIMPLE_RADIUS_DAMAGE ); - - m_iMaxHealth = GetHealth(); - - if( m_fAutoaimRadius > 0.0f ) - { - // Make this an aimtarget, since it has some autoaim influence. - AddFlag(FL_AIMTARGET); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Bullseye::Activate( void ) -{ - BaseClass::Activate(); - - if ( m_spawnflags & SF_BULLSEYE_PERFECTACC ) - { - m_bPerfectAccuracy = true; - } - else - { - m_bPerfectAccuracy = false; - } -} - - -//------------------------------------------------------------------------------ -// Purpose : Override so doesn't fall to ground when killed -//------------------------------------------------------------------------------ -void CNPC_Bullseye::Event_Killed( const CTakeDamageInfo &info ) -{ - BaseClass::Event_Killed( info ); - - if( GetParent() ) - { - if( GetParent()->ClassMatches("prop_combine_ball") ) - { - // If this bullseye is parented to a combine ball, explode the combine ball - // and remove this bullseye. - variant_t emptyVariant; - GetParent()->AcceptInput( "explode", this, this, emptyVariant, 0 ); - - // Unhook. - SetParent(NULL); - - UTIL_Remove(this); - return; - } - } - - SetMoveType( MOVETYPE_NONE ); - AddSolidFlags( FSOLID_NOT_SOLID ); - UTIL_SetSize(this, vec3_origin, vec3_origin ); - - SetNextThink( gpGlobals->curtime + 0.1f ); - SetThink( &CBaseEntity::SUB_Remove ); -} - -//------------------------------------------------------------------------------ -// Purpose : Override base implimentation to let decals pass through -// me onto the surface beneath -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_Bullseye::DecalTrace( trace_t *pOldTrace, char const *decalName ) -{ - int index = decalsystem->GetDecalIndexForName( decalName ); - if ( index < 0 ) - return; - - // Get direction of original trace - Vector vTraceDir = pOldTrace->endpos - pOldTrace->startpos; - VectorNormalize(vTraceDir); - - // Create a new trace that passes through me - Vector vStartTrace = pOldTrace->endpos - (1.0 * vTraceDir); - Vector vEndTrace = pOldTrace->endpos + (MAX_TRACE_LENGTH * vTraceDir); - - trace_t pNewTrace; - AI_TraceLine(vStartTrace, vEndTrace, MASK_SHOT, this, COLLISION_GROUP_NONE, &pNewTrace); - - CBroadcastRecipientFilter filter; - te->Decal( filter, 0.0, &pNewTrace.endpos, &pNewTrace.startpos, - ENTINDEX( pNewTrace.m_pEnt ), pNewTrace.hitbox, index ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Bullseye::ImpactTrace( trace_t *pTrace, int iDamageType, const char *pCustomImpactName ) -{ - // Get direction of original trace - Vector vTraceDir = pTrace->endpos - pTrace->startpos; - VectorNormalize(vTraceDir); - - // Create a new trace that passes through me - Vector vStartTrace = pTrace->endpos - (1.0 * vTraceDir); - Vector vEndTrace = pTrace->endpos + (MAX_TRACE_LENGTH * vTraceDir); - - trace_t pNewTrace; - AI_TraceLine(vStartTrace, vEndTrace, MASK_SHOT, this, COLLISION_GROUP_NONE, &pNewTrace); - - CBaseEntity *pEntity = pNewTrace.m_pEnt; - - // Only do this for BSP model entities - if ( ( pEntity ) && ( pEntity->IsBSPModel() == false ) ) - return; - - BaseClass::ImpactTrace( pTrace, iDamageType, pCustomImpactName ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -// Output : -//----------------------------------------------------------------------------- -Class_T CNPC_Bullseye::Classify( void ) -{ - return CLASS_BULLSEYE; -} - -void CNPC_Bullseye::OnRestore( void ) -{ - if ( m_spawnflags & SF_BULLSEYE_VPHYSICSSHADOW ) - { - IPhysicsObject *pObject = VPhysicsGetObject(); - - if ( pObject == NULL ) - { - VPhysicsInitShadow( false, false ); - } - } - - BaseClass::OnRestore(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Bullseye::BullseyeThink( void ) -{ - ClearCondition( COND_LIGHT_DAMAGE ); - ClearCondition( COND_HEAVY_DAMAGE ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Bullseye::CanBecomeRagdoll() -{ - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Bullseye::CanBeAnEnemyOf( CBaseEntity *pEnemy ) -{ - static const float flFullFov = cos( DEG2RAD(360) / 2.0 ); - if ( fabsf( m_flFieldOfView - flFullFov ) > .01 ) - { - if ( !FInViewCone( pEnemy ) ) - { - return false; - } - } - - if ( m_flMinDistValidEnemy > 0 ) - { - float distSq = ( GetAbsOrigin().AsVector2D() - pEnemy->GetAbsOrigin().AsVector2D() ).LengthSqr(); - if ( distSq < Square( m_flMinDistValidEnemy ) ) - { - return false; - } - } - return BaseClass::CanBeAnEnemyOf( pEnemy ); -} - -//----------------------------------------------------------------------------- -// Purpose: Bullseyes should always report light damage if any amount of damage is taken -// Input : fDamage - amount of damage -// bitsDamageType - damage type -//----------------------------------------------------------------------------- -bool CNPC_Bullseye::IsLightDamage( const CTakeDamageInfo &info ) -{ - return ( info.GetDamage() > 0 ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pAttacker - -// flDamage - -// &vecDir - -// *ptr - -// bitsDamageType - -//----------------------------------------------------------------------------- -void CNPC_Bullseye::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - //If specified, we must be the enemy of the target - if ( m_spawnflags & SF_BULLSEYE_ENEMYDAMAGEONLY ) - { - CAI_BaseNPC *pInstigator = info.GetAttacker()->MyNPCPointer(); - - if ( pInstigator == NULL ) - return; - - if ( pInstigator->GetEnemy() != this ) - return; - } - - //We can bleed if we want to, we can leave decals behind... - if ( ( m_spawnflags & SF_BULLSEYE_BLEED ) && ( m_takedamage == DAMAGE_NO ) ) - { - TraceBleed( info.GetDamage(), vecDir, ptr, info.GetDamageType() ); - } - - BaseClass::TraceAttack( info, vecDir, ptr ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pInflictor - -// *pAttacker - -// flDamage - -// bitsDamageType - -// Output : int -//----------------------------------------------------------------------------- -int CNPC_Bullseye::OnTakeDamage( const CTakeDamageInfo &info ) -{ - SetNextThink( gpGlobals->curtime ); - - //If specified, we must be the enemy of the target - if ( m_spawnflags & SF_BULLSEYE_ENEMYDAMAGEONLY ) - { - CAI_BaseNPC *pInstigator = info.GetAttacker()->MyNPCPointer(); - - if ( pInstigator == NULL ) - return 0; - - if ( pInstigator->GetEnemy() != this ) - return 0; - } - - //If we're a pain proxy, send the damage through - if ( m_hPainPartner != NULL ) - { - m_hPainPartner->TakeDamage( info ); - - //Fire all pain indicators but take no real damage - CTakeDamageInfo subInfo = info; - subInfo.SetDamage( 0 ); - return BaseClass::OnTakeDamage( subInfo ); - } - - return BaseClass::OnTakeDamage( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOther - -//----------------------------------------------------------------------------- -void CNPC_Bullseye::SetPainPartner( CBaseEntity *pOther ) -{ - m_hPainPartner = pOther; -} - -void CNPC_Bullseye::InputTargeted( inputdata_t &inputdata ) -{ - m_OnTargeted.FireOutput( inputdata.pActivator, inputdata.pCaller, 0 ); -} - -void CNPC_Bullseye::InputReleased( inputdata_t &inputdata ) -{ - m_OnReleased.FireOutput( inputdata.pActivator, inputdata.pCaller, 0 ); -} diff --git a/game/server/hl2/npc_bullseye.h b/game/server/hl2/npc_bullseye.h deleted file mode 100644 index 3cae0af24..000000000 --- a/game/server/hl2/npc_bullseye.h +++ /dev/null @@ -1,79 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef NPC_BULLSEYE_H -#define NPC_BULLSEYE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_basenpc.h" - -//========================================================= -// >> CBullseye -//========================================================= -class CNPC_Bullseye : public CAI_BaseNPC -{ - DECLARE_CLASS( CNPC_Bullseye, CAI_BaseNPC ); - -public: - CNPC_Bullseye(void); - ~CNPC_Bullseye(); - - virtual void Precache( void ); - virtual void Spawn( void ); - virtual void Activate( void ); - virtual void OnRestore( void ); - - virtual float GetAutoAimRadius() { return m_fAutoaimRadius; } - - Class_T Classify( void ); - void Event_Killed( const CTakeDamageInfo &info ); - void DecalTrace( trace_t *pTrace, char const *decalName ); - void ImpactTrace( trace_t *pTrace, int iDamageType, const char *pCustomImpactName ); - bool IsLightDamage( const CTakeDamageInfo &info ); - void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - int OnTakeDamage( const CTakeDamageInfo &info ); - bool UsePerfectAccuracy( void ) { return m_bPerfectAccuracy; } - - bool TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ) { return false; } // force traces to test against hull - - void BullseyeThink( void ); - bool CanBecomeRagdoll( void ); - - void SetPainPartner( CBaseEntity *pOther ); - void InputTargeted( inputdata_t &inputdata ); - void InputReleased( inputdata_t &inputdata ); - bool CanBecomeServerRagdoll( void ) { return false; } - - bool CanBeAnEnemyOf( CBaseEntity *pEnemy ); - - -protected: - - EHANDLE m_hPainPartner; //Entity that the bullseye will pass any damage it take to - COutputEvent m_OnTargeted; - COutputEvent m_OnReleased; - bool m_bPerfectAccuracy; // Entities that shoot at me should be perfectly accurate - float m_fAutoaimRadius; // How much to influence player's autoaim. - float m_flMinDistValidEnemy; - - DECLARE_DATADESC(); -}; - -int FindBullseyesInCone( CBaseEntity **pList, int listMax, const Vector &coneOrigin, const Vector &coneAxis, float coneAngleCos, float coneLength ); - -#define SF_BULLSEYE_NONSOLID (1 << 16) -#define SF_BULLSEYE_NODAMAGE (1 << 17) -#define SF_BULLSEYE_ENEMYDAMAGEONLY (1 << 18) -#define SF_BULLSEYE_BLEED (1 << 19) -#define SF_BULLSEYE_PERFECTACC (1 << 20) -#define SF_BULLSEYE_VPHYSICSSHADOW (1 << 21) - - -#endif // NPC_BULLSEYE_H - diff --git a/game/server/hl2/npc_bullsquid.cpp b/game/server/hl2/npc_bullsquid.cpp deleted file mode 100644 index ca82675ff..000000000 --- a/game/server/hl2/npc_bullsquid.cpp +++ /dev/null @@ -1,1022 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements the bullsquid -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "game.h" -#include "AI_Default.h" -#include "AI_Schedule.h" -#include "AI_Hull.h" -#include "AI_Navigator.h" -#include "AI_Motor.h" -#include "AI_Squad.h" -#include "npc_bullsquid.h" -#include "NPCEvent.h" -#include "soundent.h" -#include "activitylist.h" -#include "weapon_brickbat.h" -#include "npc_headcrab.h" -#include "player.h" -#include "gamerules.h" // For g_pGameRules -#include "ammodef.h" -#include "grenade_spit.h" -#include "grenade_brickbat.h" -#include "entitylist.h" -#include "shake.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "movevars_shared.h" - -#include "AI_Hint.h" -#include "AI_Senses.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SQUID_SPRINT_DIST 256 // how close the squid has to get before starting to sprint and refusing to swerve - -ConVar sk_bullsquid_health( "sk_bullsquid_health", "0" ); -ConVar sk_bullsquid_dmg_bite( "sk_bullsquid_dmg_bite", "0" ); -ConVar sk_bullsquid_dmg_whip( "sk_bullsquid_dmg_whip", "0" ); - -//========================================================= -// monster-specific schedule types -//========================================================= -enum -{ - SCHED_SQUID_HURTHOP = LAST_SHARED_SCHEDULE + 1, - SCHED_SQUID_SEECRAB, - SCHED_SQUID_EAT, - SCHED_SQUID_SNIFF_AND_EAT, - SCHED_SQUID_WALLOW, -}; - -//========================================================= -// monster-specific tasks -//========================================================= -enum -{ - TASK_SQUID_HOPTURN = LAST_SHARED_TASK + 1, - TASK_SQUID_EAT, -}; - -//----------------------------------------------------------------------------- -// Squid Conditions -//----------------------------------------------------------------------------- -enum -{ - COND_SQUID_SMELL_FOOD = LAST_SHARED_CONDITION + 1, -}; - - -//========================================================= -// Interactions -//========================================================= -int g_interactionBullsquidThrow = 0; - -//========================================================= -// Monster's Anim Events Go Here -//========================================================= -#define BSQUID_AE_SPIT ( 1 ) -#define BSQUID_AE_BITE ( 2 ) -#define BSQUID_AE_BLINK ( 3 ) -#define BSQUID_AE_ROAR ( 4 ) -#define BSQUID_AE_HOP ( 5 ) -#define BSQUID_AE_THROW ( 6 ) -#define BSQUID_AE_WHIP_SND ( 7 ) - -LINK_ENTITY_TO_CLASS( npc_bullsquid, CNPC_Bullsquid ); - -int ACT_SQUID_EXCITED; -int ACT_SQUID_EAT; -int ACT_SQUID_DETECT_SCENT; -int ACT_SQUID_INSPECT_FLOOR; - - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CNPC_Bullsquid ) - - DEFINE_FIELD( m_fCanThreatDisplay, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flLastHurtTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextSpitTime, FIELD_TIME ), -// DEFINE_FIELD( m_nSquidSpitSprite, FIELD_INTEGER ), - DEFINE_FIELD( m_flHungryTime, FIELD_TIME ), - DEFINE_FIELD( m_nextSquidSoundTime, FIELD_TIME ), - -END_DATADESC() - - -//========================================================= -// Spawn -//========================================================= -void CNPC_Bullsquid::Spawn() -{ - Precache( ); - - SetModel( "models/bullsquid.mdl"); - SetHullType(HULL_WIDE_SHORT); - SetHullSizeNormal(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - m_bloodColor = BLOOD_COLOR_GREEN; - - SetRenderColor( 255, 255, 255, 255 ); - - m_iHealth = sk_bullsquid_health.GetFloat(); - m_flFieldOfView = 0.2;// indicates the width of this monster's forward view cone ( as a dotproduct result ) - m_NPCState = NPC_STATE_NONE; - - CapabilitiesClear(); - CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_INNATE_RANGE_ATTACK1 | bits_CAP_INNATE_MELEE_ATTACK1 | bits_CAP_INNATE_MELEE_ATTACK2 ); - - m_fCanThreatDisplay = TRUE; - m_flNextSpitTime = gpGlobals->curtime; - - NPCInit(); - - m_flDistTooFar = 784; -} - -//========================================================= -// Precache - precaches all resources this monster needs -//========================================================= -void CNPC_Bullsquid::Precache() -{ - PrecacheModel( "models/bullsquid.mdl" ); - m_nSquidSpitSprite = PrecacheModel("sprites/greenspit1.vmt");// client side spittle. - - UTIL_PrecacheOther( "grenade_spit" ); - - PrecacheScriptSound( "NPC_Bullsquid.Idle" ); - PrecacheScriptSound( "NPC_Bullsquid.Pain" ); - PrecacheScriptSound( "NPC_Bullsquid.Alert" ); - PrecacheScriptSound( "NPC_Bullsquid.Death" ); - PrecacheScriptSound( "NPC_Bullsquid.Attack1" ); - PrecacheScriptSound( "NPC_Bullsquid.Growl" ); - PrecacheScriptSound( "NPC_Bullsquid.TailWhip"); - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: Indicates this monster's place in the relationship table. -// Output : -//----------------------------------------------------------------------------- -Class_T CNPC_Bullsquid::Classify( void ) -{ - return CLASS_BULLSQUID; -} - -//========================================================= -// IdleSound -//========================================================= -#define SQUID_ATTN_IDLE (float)1.5 -void CNPC_Bullsquid::IdleSound( void ) -{ - EmitSound( "NPC_Bullsquid.Idle" ); -} - -//========================================================= -// PainSound -//========================================================= -void CNPC_Bullsquid::PainSound( const CTakeDamageInfo &info ) -{ - EmitSound( "NPC_Bullsquid.Pain" ); -} - -//========================================================= -// AlertSound -//========================================================= -void CNPC_Bullsquid::AlertSound( void ) -{ - EmitSound( "NPC_Bullsquid.Alert" ); -} - -//========================================================= -// DeathSound -//========================================================= -void CNPC_Bullsquid::DeathSound( const CTakeDamageInfo &info ) -{ - EmitSound( "NPC_Bullsquid.Death" ); -} - -//========================================================= -// AttackSound -//========================================================= -void CNPC_Bullsquid::AttackSound( void ) -{ - EmitSound( "NPC_Bullsquid.Attack1" ); -} - -//========================================================= -// GrowlSound -//========================================================= -void CNPC_Bullsquid::GrowlSound( void ) -{ - if (gpGlobals->curtime >= m_nextSquidSoundTime) - { - EmitSound( "NPC_Bullsquid.Growl" ); - m_nextSquidSoundTime = gpGlobals->curtime + random->RandomInt(1.5,3.0); - } -} - - -//========================================================= -// SetYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -float CNPC_Bullsquid::MaxYawSpeed( void ) -{ - float flYS = 0; - - switch ( GetActivity() ) - { - case ACT_WALK: flYS = 90; break; - case ACT_RUN: flYS = 90; break; - case ACT_IDLE: flYS = 90; break; - case ACT_RANGE_ATTACK1: flYS = 90; break; - default: - flYS = 90; - break; - } - - return flYS; -} - -//========================================================= -// HandleAnimEvent - catches the monster-specific messages -// that occur when tagged animation frames are played. -//========================================================= -void CNPC_Bullsquid::HandleAnimEvent( animevent_t *pEvent ) -{ - switch( pEvent->event ) - { - case BSQUID_AE_SPIT: - { - if ( GetEnemy() ) - { - Vector vSpitPos; - - GetAttachment( "Mouth", vSpitPos ); - - Vector vTarget = GetEnemy()->GetAbsOrigin(); - Vector vToss; - CBaseEntity* pBlocker; - float flGravity = SPIT_GRAVITY; - ThrowLimit(vSpitPos, vTarget, flGravity, 3, Vector(0,0,0), Vector(0,0,0), GetEnemy(), &vToss, &pBlocker); - - CGrenadeSpit *pGrenade = (CGrenadeSpit*)CreateNoSpawn( "grenade_spit", vSpitPos, vec3_angle, this ); - //pGrenade->KeyValue( "velocity", vToss ); - pGrenade->Spawn( ); - pGrenade->SetThrower( this ); - pGrenade->SetOwnerEntity( this ); - pGrenade->SetSpitSize( 2 ); - pGrenade->SetAbsVelocity( vToss ); - - // Tumble through the air - pGrenade->SetLocalAngularVelocity( - QAngle( - random->RandomFloat( -100, -500 ), - random->RandomFloat( -100, -500 ), - random->RandomFloat( -100, -500 ) - ) - ); - - AttackSound(); - - CPVSFilter filter( vSpitPos ); - te->SpriteSpray( filter, 0.0, - &vSpitPos, &vToss, m_nSquidSpitSprite, 5, 10, 15 ); - } - } - break; - - case BSQUID_AE_BITE: - { - // SOUND HERE! - CBaseEntity *pHurt = CheckTraceHullAttack( 70, Vector(-16,-16,-16), Vector(16,16,16), sk_bullsquid_dmg_bite.GetFloat(), DMG_SLASH ); - if ( pHurt ) - { - Vector forward, up; - AngleVectors( GetAbsAngles(), &forward, NULL, &up ); - pHurt->ApplyAbsVelocityImpulse( 100 * (up-forward) ); - pHurt->SetGroundEntity( NULL ); - } - } - break; - - case BSQUID_AE_WHIP_SND: - { - EmitSound( "NPC_Bullsquid.TailWhip" ); - break; - } - -/* - case BSQUID_AE_TAILWHIP: - { - CBaseEntity *pHurt = CheckTraceHullAttack( 70, Vector(-16,-16,-16), Vector(16,16,16), sk_bullsquid_dmg_whip.GetFloat(), DMG_SLASH | DMG_ALWAYSGIB ); - if ( pHurt ) - { - Vector right, up; - AngleVectors( GetAbsAngles(), NULL, &right, &up ); - - if ( pHurt->GetFlags() & ( FL_NPC | FL_CLIENT ) ) - pHurt->ViewPunch( QAngle( 20, 0, -20 ) ); - - pHurt->ApplyAbsVelocityImpulse( 100 * (up+2*right) ); - } - } - break; -*/ - - case BSQUID_AE_BLINK: - { - // close eye. - m_nSkin = 1; - } - break; - - case BSQUID_AE_HOP: - { - float flGravity = sv_gravity.GetFloat(); - - // throw the squid up into the air on this frame. - if ( GetFlags() & FL_ONGROUND ) - { - SetGroundEntity( NULL ); - } - - // jump 40 inches into the air - Vector vecVel = GetAbsVelocity(); - vecVel.z += sqrt( flGravity * 2.0 * 40 ); - SetAbsVelocity( vecVel ); - } - break; - - case BSQUID_AE_THROW: - { - // squid throws its prey IF the prey is a client. - CBaseEntity *pHurt = CheckTraceHullAttack( 70, Vector(-16,-16,-16), Vector(16,16,16), 0, 0 ); - - - if ( pHurt ) - { - pHurt->ViewPunch( QAngle(20,0,-20) ); - - // screeshake transforms the viewmodel as well as the viewangle. No problems with seeing the ends of the viewmodels. - UTIL_ScreenShake( pHurt->GetAbsOrigin(), 25.0, 1.5, 0.7, 2, SHAKE_START ); - - // If the player, throw him around - if ( pHurt->IsPlayer()) - { - Vector forward, up; - AngleVectors( GetLocalAngles(), &forward, NULL, &up ); - pHurt->ApplyAbsVelocityImpulse( forward * 300 + up * 300 ); - } - // If not the player see if has bullsquid throw interatcion - else - { - CBaseCombatCharacter *pVictim = ToBaseCombatCharacter( pHurt ); - if (pVictim) - { - if ( pVictim->DispatchInteraction( g_interactionBullsquidThrow, NULL, this ) ) - { - Vector forward, up; - AngleVectors( GetLocalAngles(), &forward, NULL, &up ); - pVictim->ApplyAbsVelocityImpulse( forward * 300 + up * 250 ); - } - } - } - } - } - break; - - default: - BaseClass::HandleAnimEvent( pEvent ); - } -} - -int CNPC_Bullsquid::RangeAttack1Conditions( float flDot, float flDist ) -{ - if ( IsMoving() && flDist >= 512 ) - { - // squid will far too far behind if he stops running to spit at this distance from the enemy. - return ( COND_NONE ); - } - - if ( flDist > 85 && flDist <= 784 && flDot >= 0.5 && gpGlobals->curtime >= m_flNextSpitTime ) - { - if ( GetEnemy() != NULL ) - { - if ( fabs( GetAbsOrigin().z - GetEnemy()->GetAbsOrigin().z ) > 256 ) - { - // don't try to spit at someone up really high or down really low. - return( COND_NONE ); - } - } - - if ( IsMoving() ) - { - // don't spit again for a long time, resume chasing enemy. - m_flNextSpitTime = gpGlobals->curtime + 5; - } - else - { - // not moving, so spit again pretty soon. - m_flNextSpitTime = gpGlobals->curtime + 0.5; - } - - return( COND_CAN_RANGE_ATTACK1 ); - } - - return( COND_NONE ); -} - -//========================================================= -// MeleeAttack2Conditions - bullsquid is a big guy, so has a longer -// melee range than most monsters. This is the tailwhip attack -//========================================================= -int CNPC_Bullsquid::MeleeAttack1Conditions( float flDot, float flDist ) -{ - if ( GetEnemy()->m_iHealth <= sk_bullsquid_dmg_whip.GetFloat() && flDist <= 85 && flDot >= 0.7 ) - { - return ( COND_CAN_MELEE_ATTACK1 ); - } - - return( COND_NONE ); -} - -//========================================================= -// MeleeAttack2Conditions - bullsquid is a big guy, so has a longer -// melee range than most monsters. This is the bite attack. -// this attack will not be performed if the tailwhip attack -// is valid. -//========================================================= -int CNPC_Bullsquid::MeleeAttack2Conditions( float flDot, float flDist ) -{ - if ( flDist <= 85 && flDot >= 0.7 && !HasCondition( COND_CAN_MELEE_ATTACK1 ) ) // The player & bullsquid can be as much as their bboxes - return ( COND_CAN_MELEE_ATTACK2 ); - - return( COND_NONE ); -} - -bool CNPC_Bullsquid::FValidateHintType( CAI_Hint *pHint ) -{ - if ( pHint->HintType() == HINT_HL1_WORLD_HUMAN_BLOOD ) - return true; - - DevMsg( "Couldn't validate hint type" ); - - return false; -} - -void CNPC_Bullsquid::RemoveIgnoredConditions( void ) -{ - if ( m_flHungryTime > gpGlobals->curtime ) - ClearCondition( COND_SQUID_SMELL_FOOD ); - - if ( gpGlobals->curtime - m_flLastHurtTime <= 20 ) - { - // haven't been hurt in 20 seconds, so let the squid care about stink. - ClearCondition( COND_SMELL ); - } - - if ( GetEnemy() != NULL ) - { - // ( Unless after a tasty headcrab, yumm ^_^ ) - if ( FClassnameIs( GetEnemy(), "monster_headcrab" ) ) - ClearCondition( COND_SMELL ); - } -} - -Disposition_t CNPC_Bullsquid::IRelationType( CBaseEntity *pTarget ) -{ - if ( gpGlobals->curtime - m_flLastHurtTime < 5 && FClassnameIs( pTarget, "monster_headcrab" ) ) - { - // if squid has been hurt in the last 5 seconds, and is getting relationship for a headcrab, - // tell squid to disregard crab. - return D_NU; - } - - return BaseClass::IRelationType( pTarget ); -} - -//========================================================= -// TakeDamage - overridden for bullsquid so we can keep track -// of how much time has passed since it was last injured -//========================================================= -int CNPC_Bullsquid::OnTakeDamage_Alive( const CTakeDamageInfo &inputInfo ) -{ - -#if 0 //Fix later. - - float flDist; - Vector vecApex, vOffset; - - // if the squid is running, has an enemy, was hurt by the enemy, hasn't been hurt in the last 3 seconds, and isn't too close to the enemy, - // it will swerve. (whew). - if ( GetEnemy() != NULL && IsMoving() && pevAttacker == GetEnemy() && gpGlobals->curtime - m_flLastHurtTime > 3 ) - { - flDist = ( GetAbsOrigin() - GetEnemy()->GetAbsOrigin() ).Length2D(); - - if ( flDist > SQUID_SPRINT_DIST ) - { - AI_Waypoint_t* pRoute = GetNavigator()->GetPath()->Route(); - - if ( pRoute ) - { - flDist = ( GetAbsOrigin() - pRoute[ pRoute->iNodeID ].vecLocation ).Length2D();// reusing flDist. - - if ( GetNavigator()->GetPath()->BuildTriangulationRoute( GetAbsOrigin(), pRoute[ pRoute->iNodeID ].vecLocation, flDist * 0.5, GetEnemy(), &vecApex, &vOffset, NAV_GROUND ) ) - { - GetNavigator()->PrependWaypoint( vecApex, bits_WP_TO_DETOUR | bits_WP_DONT_SIMPLIFY ); - } - } - } - } -#endif - - if ( !FClassnameIs( inputInfo.GetAttacker(), "monster_headcrab" ) ) - { - // don't forget about headcrabs if it was a headcrab that hurt the squid. - m_flLastHurtTime = gpGlobals->curtime; - } - - return BaseClass::OnTakeDamage_Alive( inputInfo ); -} - -//========================================================= -// GetSoundInterests - returns a bit mask indicating which types -// of sounds this monster regards. In the base class implementation, -// monsters care about all sounds, but no scents. -//========================================================= -int CNPC_Bullsquid::GetSoundInterests( void ) -{ - return SOUND_WORLD | - SOUND_COMBAT | - SOUND_CARCASS | - SOUND_MEAT | - SOUND_GARBAGE | - SOUND_PLAYER; -} - -//========================================================= -// OnListened - monsters dig through the active sound list for -// any sounds that may interest them. (smells, too!) -//========================================================= -void CNPC_Bullsquid::OnListened( void ) -{ - AISoundIter_t iter; - - CSound *pCurrentSound; - - static int conditionsToClear[] = - { - COND_SQUID_SMELL_FOOD, - }; - - ClearConditions( conditionsToClear, ARRAYSIZE( conditionsToClear ) ); - - pCurrentSound = GetSenses()->GetFirstHeardSound( &iter ); - - while ( pCurrentSound ) - { - // the npc cares about this sound, and it's close enough to hear. - int condition = COND_NONE; - - if ( !pCurrentSound->FIsSound() ) - { - // if not a sound, must be a smell - determine if it's just a scent, or if it's a food scent - if ( pCurrentSound->m_iType & ( SOUND_MEAT | SOUND_CARCASS ) ) - { - // the detected scent is a food item - condition = COND_SQUID_SMELL_FOOD; - } - } - - if ( condition != COND_NONE ) - SetCondition( condition ); - - pCurrentSound = GetSenses()->GetNextHeardSound( &iter ); - } - - BaseClass::OnListened(); -} - -//======================================================== -// RunAI - overridden for bullsquid because there are things -// that need to be checked every think. -//======================================================== -void CNPC_Bullsquid::RunAI( void ) -{ - // first, do base class stuff - BaseClass::RunAI(); - - if ( m_nSkin != 0 ) - { - // close eye if it was open. - m_nSkin = 0; - } - - if ( random->RandomInt( 0,39 ) == 0 ) - { - m_nSkin = 1; - } - - if ( GetEnemy() != NULL && GetActivity() == ACT_RUN ) - { - // chasing enemy. Sprint for last bit - if ( (GetAbsOrigin() - GetEnemy()->GetAbsOrigin()).Length2D() < SQUID_SPRINT_DIST ) - { - m_flPlaybackRate = 1.25; - } - } - -} - -//========================================================= -// GetSchedule -//========================================================= -int CNPC_Bullsquid::SelectSchedule( void ) -{ - switch ( m_NPCState ) - { - case NPC_STATE_ALERT: - { - if ( HasCondition( COND_LIGHT_DAMAGE ) || HasCondition( COND_HEAVY_DAMAGE ) ) - { - return SCHED_SQUID_HURTHOP; - } - - if ( HasCondition( COND_SQUID_SMELL_FOOD ) ) - { - CSound *pSound; - - pSound = GetBestScent(); - - if ( pSound && (!FInViewCone( pSound->GetSoundOrigin() ) || !FVisible( pSound->GetSoundOrigin() )) ) - { - // scent is behind or occluded - return SCHED_SQUID_SNIFF_AND_EAT; - } - - // food is right out in the open. Just go get it. - return SCHED_SQUID_EAT; - } - - if ( HasCondition( COND_SMELL ) ) - { - // there's something stinky. - CSound *pSound; - - pSound = GetBestScent(); - if ( pSound ) - return SCHED_SQUID_WALLOW; - } - - break; - } - case NPC_STATE_COMBAT: - { -// dead enemy - if ( HasCondition( COND_ENEMY_DEAD ) ) - { - // call base class, all code to handle dead enemies is centralized there. - return BaseClass::SelectSchedule(); - } - - if ( HasCondition( COND_NEW_ENEMY ) ) - { - if ( m_fCanThreatDisplay && IRelationType( GetEnemy() ) == D_HT && FClassnameIs( GetEnemy(), "monster_headcrab" ) ) - { - // this means squid sees a headcrab! - m_fCanThreatDisplay = FALSE;// only do the headcrab dance once per lifetime. - return SCHED_SQUID_SEECRAB; - } - else - { - return SCHED_WAKE_ANGRY; - } - } - - if ( HasCondition( COND_SQUID_SMELL_FOOD ) ) - { - CSound *pSound; - - pSound = GetBestScent(); - - if ( pSound && (!FInViewCone( pSound->GetSoundOrigin() ) || !FVisible( pSound->GetSoundOrigin() )) ) - { - // scent is behind or occluded - return SCHED_SQUID_SNIFF_AND_EAT; - } - - // food is right out in the open. Just go get it. - return SCHED_SQUID_EAT; - } - - if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - { - return SCHED_RANGE_ATTACK1; - } - - if ( HasCondition( COND_CAN_MELEE_ATTACK1 ) ) - { - return SCHED_MELEE_ATTACK1; - } - - if ( HasCondition( COND_CAN_MELEE_ATTACK2 ) ) - { - return SCHED_MELEE_ATTACK2; - } - - return SCHED_CHASE_ENEMY; - - break; - } - } - - return BaseClass::SelectSchedule(); -} - -//========================================================= -// FInViewCone - returns true is the passed vector is in -// the caller's forward view cone. The dot product is performed -// in 2d, making the view cone infinitely tall. -//========================================================= -bool CNPC_Bullsquid::FInViewCone( Vector pOrigin ) -{ - Vector los = ( pOrigin - GetAbsOrigin() ); - - // do this in 2D - los.z = 0; - VectorNormalize( los ); - - Vector facingDir = EyeDirection2D( ); - - float flDot = DotProduct( los, facingDir ); - - if ( flDot > m_flFieldOfView ) - return true; - - return false; -} - -//========================================================= -// Start task - selects the correct activity and performs -// any necessary calculations to start the next task on the -// schedule. OVERRIDDEN for bullsquid because it needs to -// know explicitly when the last attempt to chase the enemy -// failed, since that impacts its attack choices. -//========================================================= -void CNPC_Bullsquid::StartTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_MELEE_ATTACK2: - { - if (GetEnemy()) - { - GrowlSound(); - - m_flLastAttackTime = gpGlobals->curtime; - - BaseClass::StartTask( pTask ); - } - break; - } - case TASK_SQUID_HOPTURN: - { - SetActivity( ACT_HOP ); - - if ( GetEnemy() ) - { - Vector vecFacing = ( GetEnemy()->GetAbsOrigin() - GetAbsOrigin() ); - VectorNormalize( vecFacing ); - - GetMotor()->SetIdealYaw( vecFacing ); - } - - break; - } - case TASK_SQUID_EAT: - { - m_flHungryTime = gpGlobals->curtime + pTask->flTaskData; - TaskComplete(); - break; - } - default: - { - BaseClass::StartTask( pTask ); - break; - } - } -} - -//========================================================= -// RunTask -//========================================================= -void CNPC_Bullsquid::RunTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_SQUID_HOPTURN: - { - if ( GetEnemy() ) - { - Vector vecFacing = ( GetEnemy()->GetAbsOrigin() - GetAbsOrigin() ); - VectorNormalize( vecFacing ); - GetMotor()->SetIdealYaw( vecFacing ); - } - - if ( IsSequenceFinished() ) - { - TaskComplete(); - } - break; - } - default: - { - BaseClass::RunTask( pTask ); - break; - } - } -} - -//========================================================= -// GetIdealState - Overridden for Bullsquid to deal with -// the feature that makes it lose interest in headcrabs for -// a while if something injures it. -//========================================================= -NPC_STATE CNPC_Bullsquid::SelectIdealState( void ) -{ - // If no schedule conditions, the new ideal state is probably the reason we're in here. - switch ( m_NPCState ) - { - case NPC_STATE_COMBAT: - { - // COMBAT goes to ALERT upon death of enemy - if ( GetEnemy() != NULL && ( HasCondition( COND_LIGHT_DAMAGE ) || HasCondition( COND_HEAVY_DAMAGE ) ) && FClassnameIs( GetEnemy(), "monster_headcrab" ) ) - { - // if the squid has a headcrab enemy and something hurts it, it's going to forget about the crab for a while. - SetEnemy( NULL ); - return NPC_STATE_ALERT; - } - break; - } - } - - return BaseClass::SelectIdealState(); -} - - -//------------------------------------------------------------------------------ -// -// Schedules -// -//------------------------------------------------------------------------------ - -AI_BEGIN_CUSTOM_NPC( npc_bullsquid, CNPC_Bullsquid ) - - DECLARE_TASK( TASK_SQUID_HOPTURN ) - DECLARE_TASK( TASK_SQUID_EAT ) - - DECLARE_CONDITION( COND_SQUID_SMELL_FOOD ) - - DECLARE_ACTIVITY( ACT_SQUID_EXCITED ) - DECLARE_ACTIVITY( ACT_SQUID_EAT ) - DECLARE_ACTIVITY( ACT_SQUID_DETECT_SCENT ) - DECLARE_ACTIVITY( ACT_SQUID_INSPECT_FLOOR ) - - DECLARE_INTERACTION( g_interactionBullsquidThrow ) - - //========================================================= - // > SCHED_SQUID_HURTHOP - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_SQUID_HURTHOP, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SOUND_WAKE 0" - " TASK_SQUID_HOPTURN 0" - " TASK_FACE_ENEMY 0" - " " - " Interrupts" - ) - - //========================================================= - // > SCHED_SQUID_SEECRAB - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_SQUID_SEECRAB, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SOUND_WAKE 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_SQUID_EXCITED" - " TASK_FACE_ENEMY 0" - " " - " Interrupts" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - ) - - //========================================================= - // > SCHED_SQUID_EAT - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_SQUID_EAT, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SQUID_EAT 10" - " TASK_STORE_LASTPOSITION 0" - " TASK_GET_PATH_TO_BESTSCENT 0" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_SQUID_EAT" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_SQUID_EAT" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_SQUID_EAT" - " TASK_SQUID_EAT 50" - " TASK_GET_PATH_TO_LASTPOSITION 0" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_CLEAR_LASTPOSITION 0" - " " - " Interrupts" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_NEW_ENEMY" - " COND_SMELL" - ) - - //========================================================= - // > SCHED_SQUID_SNIFF_AND_EAT - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_SQUID_SNIFF_AND_EAT, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SQUID_EAT 10" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_SQUID_DETECT_SCENT" - " TASK_STORE_LASTPOSITION 0" - " TASK_GET_PATH_TO_BESTSCENT 0" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_SQUID_EAT" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_SQUID_EAT" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_SQUID_EAT" - " TASK_SQUID_EAT 50" - " TASK_GET_PATH_TO_LASTPOSITION 0" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_CLEAR_LASTPOSITION 0" - " " - " Interrupts" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_NEW_ENEMY" - " COND_SMELL" - ) - - //========================================================= - // > SCHED_SQUID_WALLOW - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_SQUID_WALLOW, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SQUID_EAT 10" - " TASK_STORE_LASTPOSITION 0" - " TASK_GET_PATH_TO_BESTSCENT 0" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_SQUID_INSPECT_FLOOR" - " TASK_SQUID_EAT 50" - " TASK_GET_PATH_TO_LASTPOSITION 0" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_CLEAR_LASTPOSITION 0" - " " - " Interrupts" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_NEW_ENEMY" - ) - -AI_END_CUSTOM_NPC() diff --git a/game/server/hl2/npc_bullsquid.h b/game/server/hl2/npc_bullsquid.h deleted file mode 100644 index cdff9c1fa..000000000 --- a/game/server/hl2/npc_bullsquid.h +++ /dev/null @@ -1,74 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Base combat character with no AI -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef NPC_BULLSQUID_H -#define NPC_BULLSQUID_H - -#include "AI_BaseNPC.h" - - -class CNPC_Bullsquid : public CAI_BaseNPC -{ - DECLARE_CLASS( CNPC_Bullsquid, CAI_BaseNPC ); - DECLARE_DATADESC(); - -public: - void Spawn( void ); - void Precache( void ); - Class_T Classify( void ); - - void IdleSound( void ); - void PainSound( const CTakeDamageInfo &info ); - void AlertSound( void ); - void DeathSound( const CTakeDamageInfo &info ); - void AttackSound( void ); - void GrowlSound( void ); - - float MaxYawSpeed ( void ); - - void HandleAnimEvent( animevent_t *pEvent ); - - int RangeAttack1Conditions( float flDot, float flDist ); - int MeleeAttack1Conditions( float flDot, float flDist ); - int MeleeAttack2Conditions( float flDot, float flDist ); - - bool FValidateHintType ( CAI_Hint *pHint ); - void RemoveIgnoredConditions( void ); - Disposition_t IRelationType( CBaseEntity *pTarget ); - int OnTakeDamage_Alive( const CTakeDamageInfo &inputInfo ); - - int GetSoundInterests ( void ); - void RunAI ( void ); - virtual void OnListened ( void ); - - int SelectSchedule( void ); - bool FInViewCone ( Vector pOrigin ); - - void StartTask ( const Task_t *pTask ); - void RunTask ( const Task_t *pTask ); - - NPC_STATE SelectIdealState ( void ); - - DEFINE_CUSTOM_AI; - -private: - - bool m_fCanThreatDisplay;// this is so the squid only does the "I see a headcrab!" dance one time. - float m_flLastHurtTime;// we keep track of this, because if something hurts a squid, it will forget about its love of headcrabs for a while. - float m_flNextSpitTime;// last time the bullsquid used the spit attack. - int m_nSquidSpitSprite; - float m_flHungryTime;// set this is a future time to stop the monster from eating for a while. - - float m_nextSquidSoundTime; -}; -#endif // NPC_BULLSQUID_H diff --git a/game/server/hl2/npc_citizen17.cpp b/game/server/hl2/npc_citizen17.cpp deleted file mode 100644 index 1eb02fa2e..000000000 --- a/game/server/hl2/npc_citizen17.cpp +++ /dev/null @@ -1,4265 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: The downtrodden citizens of City 17. -// -//=============================================================================// - -#include "cbase.h" - -#include "npc_citizen17.h" - -#include "ammodef.h" -#include "globalstate.h" -#include "soundent.h" -#include "BasePropDoor.h" -#include "weapon_rpg.h" -#include "hl2_player.h" -#include "items.h" - - -#ifdef HL2MP -#include "hl2mp/weapon_crowbar.h" -#else -#include "weapon_crowbar.h" -#endif - -#include "eventqueue.h" - -#include "ai_squad.h" -#include "ai_pathfinder.h" -#include "ai_route.h" -#include "ai_hint.h" -#include "ai_interactions.h" -#include "ai_looktarget.h" -#include "sceneentity.h" -#include "tier0/icommandline.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define INSIGNIA_MODEL "models/chefhat.mdl" - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -#define CIT_INSPECTED_DELAY_TIME 120 //How often I'm allowed to be inspected - -extern ConVar sk_healthkit; -extern ConVar sk_healthvial; - -const int MAX_PLAYER_SQUAD = 4; - -ConVar sk_citizen_health ( "sk_citizen_health", "0"); -ConVar sk_citizen_heal_player ( "sk_citizen_heal_player", "25"); -ConVar sk_citizen_heal_player_delay ( "sk_citizen_heal_player_delay", "25"); -ConVar sk_citizen_giveammo_player_delay( "sk_citizen_giveammo_player_delay", "10"); -ConVar sk_citizen_heal_player_min_pct ( "sk_citizen_heal_player_min_pct", "0.60"); -ConVar sk_citizen_heal_player_min_forced( "sk_citizen_heal_player_min_forced", "10.0"); -ConVar sk_citizen_heal_ally ( "sk_citizen_heal_ally", "30"); -ConVar sk_citizen_heal_ally_delay ( "sk_citizen_heal_ally_delay", "20"); -ConVar sk_citizen_heal_ally_min_pct ( "sk_citizen_heal_ally_min_pct", "0.90"); -ConVar sk_citizen_player_stare_time ( "sk_citizen_player_stare_time", "1.0" ); -ConVar sk_citizen_player_stare_dist ( "sk_citizen_player_stare_dist", "72" ); -ConVar sk_citizen_stare_heal_time ( "sk_citizen_stare_heal_time", "5" ); - -ConVar g_ai_citizen_show_enemy( "g_ai_citizen_show_enemy", "0" ); - -ConVar npc_citizen_insignia( "npc_citizen_insignia", "0" ); -ConVar npc_citizen_squad_marker( "npc_citizen_squad_marker", "0" ); -ConVar npc_citizen_explosive_resist( "npc_citizen_explosive_resist", "0" ); -ConVar npc_citizen_auto_player_squad( "npc_citizen_auto_player_squad", "1" ); -ConVar npc_citizen_auto_player_squad_allow_use( "npc_citizen_auto_player_squad_allow_use", "0" ); - - -ConVar npc_citizen_dont_precache_all( "npc_citizen_dont_precache_all", "0" ); - - -ConVar npc_citizen_medic_emit_sound("npc_citizen_medic_emit_sound", "1" ); -#ifdef HL2_EPISODIC -// todo: bake these into pound constants (for now they're not just for tuning purposes) -ConVar npc_citizen_heal_chuck_medkit("npc_citizen_heal_chuck_medkit" , "1" , FCVAR_ARCHIVE, "Set to 1 to use new experimental healthkit-throwing medic."); -ConVar npc_citizen_medic_throw_style( "npc_citizen_medic_throw_style", "1", FCVAR_ARCHIVE, "Set to 0 for a lobbier trajectory" ); -ConVar npc_citizen_medic_throw_speed( "npc_citizen_medic_throw_speed", "650" ); -ConVar sk_citizen_heal_toss_player_delay("sk_citizen_heal_toss_player_delay", "26", FCVAR_NONE, "how long between throwing healthkits" ); - - -#define MEDIC_THROW_SPEED npc_citizen_medic_throw_speed.GetFloat() -#define USE_EXPERIMENTAL_MEDIC_CODE() (npc_citizen_heal_chuck_medkit.GetBool() && NameMatches("griggs")) -#endif - -ConVar player_squad_autosummon_time( "player_squad_autosummon_time", "5" ); -ConVar player_squad_autosummon_move_tolerance( "player_squad_autosummon_move_tolerance", "20" ); -ConVar player_squad_autosummon_player_tolerance( "player_squad_autosummon_player_tolerance", "10" ); -ConVar player_squad_autosummon_time_after_combat( "player_squad_autosummon_time_after_combat", "8" ); -ConVar player_squad_autosummon_debug( "player_squad_autosummon_debug", "0" ); - -#define ShouldAutosquad() (npc_citizen_auto_player_squad.GetBool()) - -enum SquadSlot_T -{ - SQUAD_SLOT_CITIZEN_RPG1 = LAST_SHARED_SQUADSLOT, - SQUAD_SLOT_CITIZEN_RPG2, -}; - -const float HEAL_MOVE_RANGE = 30*12; -const float HEAL_TARGET_RANGE = 120; // 10 feet -#ifdef HL2_EPISODIC -const float HEAL_TOSS_TARGET_RANGE = 480; // 40 feet when we are throwing medkits -const float HEAL_TARGET_RANGE_Z = 72; // a second check that Gordon isn't too far above us -- 6 feet -#endif - -// player must be at least this distance away from an enemy before we fire an RPG at him -const float RPG_SAFE_DISTANCE = CMissile::EXPLOSION_RADIUS + 64.0; - -// Animation events -int AE_CITIZEN_GET_PACKAGE; -int AE_CITIZEN_HEAL; - -//------------------------------------- -//------------------------------------- - -ConVar ai_follow_move_commands( "ai_follow_move_commands", "1" ); -ConVar ai_citizen_debug_commander( "ai_citizen_debug_commander", "1" ); -#define DebuggingCommanderMode() (ai_citizen_debug_commander.GetBool() && (m_debugOverlays & OVERLAY_NPC_SELECTED_BIT)) - -//----------------------------------------------------------------------------- -// Citizen expressions for the citizen expression types -//----------------------------------------------------------------------------- -#define STATES_WITH_EXPRESSIONS 3 // Idle, Alert, Combat -#define EXPRESSIONS_PER_STATE 1 - -const char *szExpressionTypes[CIT_EXP_LAST_TYPE] = -{ - "Unassigned", - "Scared", - "Normal", - "Angry" -}; - -struct citizen_expression_list_t -{ - const char *szExpressions[EXPRESSIONS_PER_STATE]; -}; -// Scared -citizen_expression_list_t ScaredExpressions[STATES_WITH_EXPRESSIONS] = -{ - { {"scenes/Expressions/citizen_normal_idle_01.vcd"} }, - { {"scenes/Expressions/citizen_normal_alert_01.vcd"} }, - { {"scenes/Expressions/citizen_normal_combat_01.vcd"} }, -}; -// Normal -citizen_expression_list_t NormalExpressions[STATES_WITH_EXPRESSIONS] = -{ - { {"scenes/Expressions/citizen_normal_idle_01.vcd"} }, - { {"scenes/Expressions/citizen_normal_alert_01.vcd"} }, - { {"scenes/Expressions/citizen_normal_combat_01.vcd"} }, -}; -// Angry -citizen_expression_list_t AngryExpressions[STATES_WITH_EXPRESSIONS] = -{ - { {"scenes/Expressions/citizen_angry_idle_01.vcd"} }, - { {"scenes/Expressions/citizen_angry_alert_01.vcd"} }, - { {"scenes/Expressions/citizen_angry_combat_01.vcd"} }, -}; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -#define COMMAND_POINT_CLASSNAME "info_target_command_point" - -class CCommandPoint : public CPointEntity -{ - DECLARE_CLASS( CCommandPoint, CPointEntity ); -public: - CCommandPoint() - : m_bNotInTransition(false) - { - if ( ++gm_nCommandPoints > 1 ) - DevMsg( "WARNING: More than one citizen command point present\n" ); - } - - ~CCommandPoint() - { - --gm_nCommandPoints; - } - - int ObjectCaps() - { - int caps = ( BaseClass::ObjectCaps() | FCAP_NOTIFY_ON_TRANSITION ); - - if ( m_bNotInTransition ) - caps |= FCAP_DONT_SAVE; - - return caps; - } - - void InputOutsideTransition( inputdata_t &inputdata ) - { - if ( !AI_IsSinglePlayer() ) - return; - - m_bNotInTransition = true; - - CAI_Squad *pPlayerAISquad = g_AI_SquadManager.FindSquad(AllocPooledString(PLAYER_SQUADNAME)); - - if ( pPlayerAISquad ) - { - AISquadIter_t iter; - for ( CAI_BaseNPC *pAllyNpc = pPlayerAISquad->GetFirstMember(&iter); pAllyNpc; pAllyNpc = pPlayerAISquad->GetNextMember(&iter) ) - { - if ( pAllyNpc->GetCommandGoal() != vec3_invalid ) - { - bool bHadGag = pAllyNpc->HasSpawnFlags(SF_NPC_GAG); - - pAllyNpc->AddSpawnFlags(SF_NPC_GAG); - pAllyNpc->TargetOrder( UTIL_GetLocalPlayer(), &pAllyNpc, 1 ); - if ( !bHadGag ) - pAllyNpc->RemoveSpawnFlags(SF_NPC_GAG); - } - } - } - } - DECLARE_DATADESC(); - -private: - bool m_bNotInTransition; // does not need to be saved. If this is ever not default, the object is not being saved. - static int gm_nCommandPoints; -}; - -int CCommandPoint::gm_nCommandPoints; - -LINK_ENTITY_TO_CLASS( info_target_command_point, CCommandPoint ); -BEGIN_DATADESC( CCommandPoint ) - -// DEFINE_FIELD( m_bNotInTransition, FIELD_BOOLEAN ), - DEFINE_INPUTFUNC( FIELD_VOID, "OutsideTransition", InputOutsideTransition ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -class CMattsPipe : public CWeaponCrowbar -{ - DECLARE_CLASS( CMattsPipe, CWeaponCrowbar ); - - const char *GetWorldModel() const { return "models/props_canal/mattpipe.mdl"; } - void SetPickupTouch( void ) { /* do nothing */ } -}; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -//--------------------------------------------------------- -// Citizen models -//--------------------------------------------------------- - -static const char *g_ppszRandomHeads[] = -{ - "male_01.mdl", - "male_02.mdl", - "female_01.mdl", - "male_03.mdl", - "female_02.mdl", - "male_04.mdl", - "female_03.mdl", - "male_05.mdl", - "female_04.mdl", - "male_06.mdl", - "female_06.mdl", - "male_07.mdl", - "female_07.mdl", - "male_08.mdl", - "male_09.mdl", -}; - -static const char *g_ppszModelLocs[] = -{ - "Group01", - "Group01", - "Group02", - "Group03%s", -}; - -#define IsExcludedHead( type, bMedic, iHead) false // see XBox codeline for an implementation - - -//--------------------------------------------------------- -// Citizen activities -//--------------------------------------------------------- - -int ACT_CIT_HANDSUP; -int ACT_CIT_BLINDED; // Blinded by scanner photo -int ACT_CIT_SHOWARMBAND; -int ACT_CIT_HEAL; -int ACT_CIT_STARTLED; // Startled by sneaky scanner - -//--------------------------------------------------------- - -LINK_ENTITY_TO_CLASS( npc_citizen, CNPC_Citizen ); - -//--------------------------------------------------------- - -BEGIN_DATADESC( CNPC_Citizen ) - - DEFINE_CUSTOM_FIELD( m_nInspectActivity, ActivityDataOps() ), - DEFINE_FIELD( m_flNextFearSoundTime, FIELD_TIME ), - DEFINE_FIELD( m_flStopManhackFlinch, FIELD_TIME ), - DEFINE_FIELD( m_fNextInspectTime, FIELD_TIME ), - DEFINE_FIELD( m_flPlayerHealTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextHealthSearchTime, FIELD_TIME ), - DEFINE_FIELD( m_flAllyHealTime, FIELD_TIME ), -// gm_PlayerSquadEvaluateTimer -// m_AssaultBehavior -// m_FollowBehavior -// m_StandoffBehavior -// m_LeadBehavior -// m_FuncTankBehavior - DEFINE_FIELD( m_flPlayerGiveAmmoTime, FIELD_TIME ), - DEFINE_KEYFIELD( m_iszAmmoSupply, FIELD_STRING, "ammosupply" ), - DEFINE_KEYFIELD( m_iAmmoAmount, FIELD_INTEGER, "ammoamount" ), - DEFINE_FIELD( m_bRPGAvoidPlayer, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bShouldPatrol, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iszOriginalSquad, FIELD_STRING ), - DEFINE_FIELD( m_flTimeJoinedPlayerSquad, FIELD_TIME ), - DEFINE_FIELD( m_bWasInPlayerSquad, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flTimeLastCloseToPlayer, FIELD_TIME ), - DEFINE_EMBEDDED( m_AutoSummonTimer ), - DEFINE_FIELD( m_vAutoSummonAnchor, FIELD_POSITION_VECTOR ), - DEFINE_KEYFIELD( m_Type, FIELD_INTEGER, "citizentype" ), - DEFINE_KEYFIELD( m_ExpressionType, FIELD_INTEGER, "expressiontype" ), - DEFINE_FIELD( m_iHead, FIELD_INTEGER ), - DEFINE_FIELD( m_flTimePlayerStare, FIELD_TIME ), - DEFINE_FIELD( m_flTimeNextHealStare, FIELD_TIME ), - DEFINE_FIELD( m_hSavedFollowGoalEnt, FIELD_EHANDLE ), - DEFINE_KEYFIELD( m_bNotifyNavFailBlocked, FIELD_BOOLEAN, "notifynavfailblocked" ), - DEFINE_KEYFIELD( m_bNeverLeavePlayerSquad, FIELD_BOOLEAN, "neverleaveplayersquad" ), - DEFINE_KEYFIELD( m_iszDenyCommandConcept, FIELD_STRING, "denycommandconcept" ), - - DEFINE_OUTPUT( m_OnJoinedPlayerSquad, "OnJoinedPlayerSquad" ), - DEFINE_OUTPUT( m_OnLeftPlayerSquad, "OnLeftPlayerSquad" ), - DEFINE_OUTPUT( m_OnFollowOrder, "OnFollowOrder" ), - DEFINE_OUTPUT( m_OnStationOrder, "OnStationOrder" ), - DEFINE_OUTPUT( m_OnPlayerUse, "OnPlayerUse" ), - DEFINE_OUTPUT( m_OnNavFailBlocked, "OnNavFailBlocked" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "RemoveFromPlayerSquad", InputRemoveFromPlayerSquad ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartPatrolling", InputStartPatrolling ), - DEFINE_INPUTFUNC( FIELD_VOID, "StopPatrolling", InputStopPatrolling ), - DEFINE_INPUTFUNC( FIELD_VOID, "SetCommandable", InputSetCommandable ), - DEFINE_INPUTFUNC( FIELD_VOID, "SetMedicOn", InputSetMedicOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "SetMedicOff", InputSetMedicOff ), - DEFINE_INPUTFUNC( FIELD_VOID, "SetAmmoResupplierOn", InputSetAmmoResupplierOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "SetAmmoResupplierOff", InputSetAmmoResupplierOff ), - DEFINE_INPUTFUNC( FIELD_VOID, "SpeakIdleResponse", InputSpeakIdleResponse ), - -#if HL2_EPISODIC - DEFINE_INPUTFUNC( FIELD_VOID, "ThrowHealthKit", InputForceHealthKitToss ), -#endif - - DEFINE_USEFUNC( CommanderUse ), - DEFINE_USEFUNC( SimpleUse ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -CSimpleSimTimer CNPC_Citizen::gm_PlayerSquadEvaluateTimer; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -bool CNPC_Citizen::CreateBehaviors() -{ - BaseClass::CreateBehaviors(); - AddBehavior( &m_FuncTankBehavior ); - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::Precache() -{ - SelectModel(); - SelectExpressionType(); - - if ( !npc_citizen_dont_precache_all.GetBool() ) - PrecacheAllOfType( m_Type ); - else - PrecacheModel( STRING( GetModelName() ) ); - - if ( NameMatches( "matt" ) ) - PrecacheModel( "models/props_canal/mattpipe.mdl" ); - - PrecacheModel( INSIGNIA_MODEL ); - - PrecacheScriptSound( "NPC_Citizen.FootstepLeft" ); - PrecacheScriptSound( "NPC_Citizen.FootstepRight" ); - PrecacheScriptSound( "NPC_Citizen.Die" ); - - PrecacheInstancedScene( "scenes/Expressions/CitizenIdle.vcd" ); - PrecacheInstancedScene( "scenes/Expressions/CitizenAlert_loop.vcd" ); - PrecacheInstancedScene( "scenes/Expressions/CitizenCombat_loop.vcd" ); - - for ( int i = 0; i < STATES_WITH_EXPRESSIONS; i++ ) - { - for ( size_t j = 0; j < ARRAYSIZE(ScaredExpressions[i].szExpressions); j++ ) - { - PrecacheInstancedScene( ScaredExpressions[i].szExpressions[j] ); - } - for ( size_t j = 0; j < ARRAYSIZE(NormalExpressions[i].szExpressions); j++ ) - { - PrecacheInstancedScene( NormalExpressions[i].szExpressions[j] ); - } - for ( size_t j = 0; j < ARRAYSIZE(AngryExpressions[i].szExpressions); j++ ) - { - PrecacheInstancedScene( AngryExpressions[i].szExpressions[j] ); - } - } - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::PrecacheAllOfType( CitizenType_t type ) -{ - if ( m_Type == CT_UNIQUE ) - return; - - int nHeads = ARRAYSIZE( g_ppszRandomHeads ); - int i; - for ( i = 0; i < nHeads; ++i ) - { - if ( !IsExcludedHead( type, false, i ) ) - { - PrecacheModel( CFmtStr( "models/Humans/%s/%s", (const char *)(CFmtStr(g_ppszModelLocs[m_Type], "")), g_ppszRandomHeads[i] ) ); - } - } - - if ( m_Type == CT_REBEL ) - { - for ( i = 0; i < nHeads; ++i ) - { - if ( !IsExcludedHead( type, true, i ) ) - { - PrecacheModel( CFmtStr( "models/Humans/%s/%s", (const char *)(CFmtStr(g_ppszModelLocs[m_Type], "m")), g_ppszRandomHeads[i] ) ); - } - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::Spawn() -{ - BaseClass::Spawn(); - -#ifdef _XBOX - // Always fade the corpse - AddSpawnFlags( SF_NPC_FADE_CORPSE ); -#endif // _XBOX - - if ( ShouldAutosquad() ) - { - if ( m_SquadName == GetPlayerSquadName() ) - { - CAI_Squad *pPlayerSquad = g_AI_SquadManager.FindSquad( GetPlayerSquadName() ); - if ( pPlayerSquad && pPlayerSquad->NumMembers() >= MAX_PLAYER_SQUAD ) - m_SquadName = NULL_STRING; - } - gm_PlayerSquadEvaluateTimer.Force(); - } - - if ( IsAmmoResupplier() ) - m_nSkin = 2; - - m_bRPGAvoidPlayer = false; - - m_bShouldPatrol = false; - m_iHealth = sk_citizen_health.GetFloat(); - - // Are we on a train? Used in trainstation to have NPCs on trains. - if ( GetMoveParent() && FClassnameIs( GetMoveParent(), "func_tracktrain" ) ) - { - CapabilitiesRemove( bits_CAP_MOVE_GROUND ); - SetMoveType( MOVETYPE_NONE ); - if ( NameMatches("citizen_train_2") ) - { - SetSequenceByName( "d1_t01_TrainRide_Sit_Idle" ); - SetIdealActivity( ACT_DO_NOT_DISTURB ); - } - else - { - SetSequenceByName( "d1_t01_TrainRide_Stand" ); - SetIdealActivity( ACT_DO_NOT_DISTURB ); - } - } - - m_flStopManhackFlinch = -1; - - m_iszIdleExpression = MAKE_STRING("scenes/expressions/citizenidle.vcd"); - m_iszAlertExpression = MAKE_STRING("scenes/expressions/citizenalert_loop.vcd"); - m_iszCombatExpression = MAKE_STRING("scenes/expressions/citizencombat_loop.vcd"); - - m_iszOriginalSquad = m_SquadName; - - m_flNextHealthSearchTime = gpGlobals->curtime; - - CWeaponRPG *pRPG = dynamic_cast(GetActiveWeapon()); - if ( pRPG ) - { - CapabilitiesRemove( bits_CAP_USE_SHOT_REGULATOR ); - pRPG->StopGuiding(); - } - - m_flTimePlayerStare = FLT_MAX; - - AddEFlags( EFL_NO_DISSOLVE | EFL_NO_MEGAPHYSCANNON_RAGDOLL | EFL_NO_PHYSCANNON_INTERACTION ); - - NPCInit(); - - SetUse( &CNPC_Citizen::CommanderUse ); - Assert( !ShouldAutosquad() || !IsInPlayerSquad() ); - - m_bWasInPlayerSquad = IsInPlayerSquad(); - - // Use render bounds instead of human hull for guys sitting in chairs, etc. - m_ActBusyBehavior.SetUseRenderBounds( HasSpawnFlags( SF_CITIZEN_USE_RENDER_BOUNDS ) ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::PostNPCInit() -{ - if ( !gEntList.FindEntityByClassname( NULL, COMMAND_POINT_CLASSNAME ) ) - { - CreateEntityByName( COMMAND_POINT_CLASSNAME ); - } - - if ( IsInPlayerSquad() ) - { - if ( m_pSquad->NumMembers() > MAX_PLAYER_SQUAD ) - DevMsg( "Error: Spawning citizen in player squad but exceeds squad limit of %d members\n", MAX_PLAYER_SQUAD ); - - FixupPlayerSquad(); - } - else - { - if ( ( m_spawnflags & SF_CITIZEN_FOLLOW ) && AI_IsSinglePlayer() ) - { - m_FollowBehavior.SetFollowTarget( UTIL_GetLocalPlayer() ); - m_FollowBehavior.SetParameters( AIF_SIMPLE ); - } - } - - BaseClass::PostNPCInit(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -struct HeadCandidate_t -{ - int iHead; - int nHeads; - - static int __cdecl Sort( const HeadCandidate_t *pLeft, const HeadCandidate_t *pRight ) - { - return ( pLeft->nHeads - pRight->nHeads ); - } -}; - -void CNPC_Citizen::SelectModel() -{ - // If making reslists, precache everything!!! - static bool madereslists = false; - - if ( CommandLine()->CheckParm("-makereslists") && !madereslists ) - { - madereslists = true; - - PrecacheAllOfType( CT_DOWNTRODDEN ); - PrecacheAllOfType( CT_REFUGEE ); - PrecacheAllOfType( CT_REBEL ); - } - - const char *pszModelName = NULL; - - if ( m_Type == CT_DEFAULT ) - { - struct CitizenTypeMapping - { - const char *pszMapTag; - CitizenType_t type; - }; - - static CitizenTypeMapping CitizenTypeMappings[] = - { - { "trainstation", CT_DOWNTRODDEN }, - { "canals", CT_REFUGEE }, - { "town", CT_REFUGEE }, - { "coast", CT_REFUGEE }, - { "prison", CT_DOWNTRODDEN }, - { "c17", CT_REBEL }, - { "citadel", CT_DOWNTRODDEN }, - }; - - char szMapName[256]; - Q_strncpy(szMapName, STRING(gpGlobals->mapname), sizeof(szMapName) ); - Q_strlower(szMapName); - - for ( size_t i = 0; i < ARRAYSIZE(CitizenTypeMappings); i++ ) - { - if ( Q_stristr( szMapName, CitizenTypeMappings[i].pszMapTag ) ) - { - m_Type = CitizenTypeMappings[i].type; - break; - } - } - - if ( m_Type == CT_DEFAULT ) - m_Type = CT_DOWNTRODDEN; - } - - if( HasSpawnFlags( SF_CITIZEN_RANDOM_HEAD | SF_CITIZEN_RANDOM_HEAD_MALE | SF_CITIZEN_RANDOM_HEAD_FEMALE ) || GetModelName() == NULL_STRING ) - { - Assert( m_iHead == -1 ); - char gender = ( HasSpawnFlags( SF_CITIZEN_RANDOM_HEAD_MALE ) ) ? 'm' : - ( HasSpawnFlags( SF_CITIZEN_RANDOM_HEAD_FEMALE ) ) ? 'f' : 0; - - RemoveSpawnFlags( SF_CITIZEN_RANDOM_HEAD | SF_CITIZEN_RANDOM_HEAD_MALE | SF_CITIZEN_RANDOM_HEAD_FEMALE ); - if( HasSpawnFlags( SF_NPC_START_EFFICIENT ) ) - { - SetModelName( AllocPooledString("models/humans/male_cheaple.mdl" ) ); - return; - } - else - { - // Count the heads - int headCounts[ARRAYSIZE(g_ppszRandomHeads)] = { 0 }; - int i; - - for ( i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - CNPC_Citizen *pCitizen = dynamic_cast(g_AI_Manager.AccessAIs()[i]); - if ( pCitizen && pCitizen != this && pCitizen->m_iHead >= 0 && pCitizen->m_iHead < (int)ARRAYSIZE(g_ppszRandomHeads) ) - { - headCounts[pCitizen->m_iHead]++; - } - } - - // Find all candidates - CUtlVectorFixed candidates; - - for ( i = 0; i < (int)ARRAYSIZE(g_ppszRandomHeads); i++ ) - { - if ( !gender || g_ppszRandomHeads[i][0] == gender ) - { - if ( !IsExcludedHead( m_Type, IsMedic(), i ) ) - { - HeadCandidate_t candidate = { i, headCounts[i] }; - candidates.AddToTail( candidate ); - } - } - } - - Assert( candidates.Count() ); - candidates.Sort( &HeadCandidate_t::Sort ); - - int iSmallestCount = candidates[0].nHeads; - int iLimit; - - for ( iLimit = 0; iLimit < candidates.Count(); iLimit++ ) - { - if ( candidates[iLimit].nHeads > iSmallestCount ) - break; - } - - m_iHead = candidates[random->RandomInt( 0, iLimit - 1 )].iHead; - pszModelName = g_ppszRandomHeads[m_iHead]; - SetModelName(NULL_STRING); - } - } - - Assert( pszModelName || GetModelName() != NULL_STRING ); - - if ( !pszModelName ) - { - if ( GetModelName() == NULL_STRING ) - return; - pszModelName = strrchr(STRING(GetModelName()), '/' ); - if ( !pszModelName ) - pszModelName = STRING(GetModelName()); - else - { - pszModelName++; - if ( m_iHead == -1 ) - { - for ( int i = 0; i < (int)ARRAYSIZE(g_ppszRandomHeads); i++ ) - { - if ( Q_stricmp( g_ppszRandomHeads[i], pszModelName ) == 0 ) - { - m_iHead = i; - break; - } - } - } - } - if ( !*pszModelName ) - return; - } - - // Unique citizen models are left alone - if ( m_Type != CT_UNIQUE ) - { - SetModelName( AllocPooledString( CFmtStr( "models/Humans/%s/%s", (const char *)(CFmtStr(g_ppszModelLocs[ m_Type ], ( IsMedic() ) ? "m" : "" )), pszModelName ) ) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Citizen::SelectExpressionType() -{ - // If we've got a mapmaker assigned type, leave it alone - if ( m_ExpressionType != CIT_EXP_UNASSIGNED ) - return; - - switch ( m_Type ) - { - case CT_DOWNTRODDEN: - m_ExpressionType = (CitizenExpressionTypes_t)RandomInt( CIT_EXP_SCARED, CIT_EXP_NORMAL ); - break; - case CT_REFUGEE: - m_ExpressionType = (CitizenExpressionTypes_t)RandomInt( CIT_EXP_SCARED, CIT_EXP_NORMAL ); - break; - case CT_REBEL: - m_ExpressionType = (CitizenExpressionTypes_t)RandomInt( CIT_EXP_SCARED, CIT_EXP_ANGRY ); - break; - - case CT_DEFAULT: - case CT_UNIQUE: - default: - break; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::FixupMattWeapon() -{ - CBaseCombatWeapon *pWeapon = GetActiveWeapon(); - if ( pWeapon && pWeapon->ClassMatches( "weapon_crowbar" ) && NameMatches( "matt" ) ) - { - Weapon_Drop( pWeapon ); - UTIL_Remove( pWeapon ); - pWeapon = (CBaseCombatWeapon *)CREATE_UNSAVED_ENTITY( CMattsPipe, "weapon_crowbar" ); - pWeapon->SetName( AllocPooledString( "matt_weapon" ) ); - DispatchSpawn( pWeapon ); - -#ifdef DEBUG - extern bool g_bReceivedChainedActivate; - g_bReceivedChainedActivate = false; -#endif - pWeapon->Activate(); - Weapon_Equip( pWeapon ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -void CNPC_Citizen::Activate() -{ - BaseClass::Activate(); - FixupMattWeapon(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::OnRestore() -{ - gm_PlayerSquadEvaluateTimer.Force(); - - BaseClass::OnRestore(); - - if ( !gEntList.FindEntityByClassname( NULL, COMMAND_POINT_CLASSNAME ) ) - { - CreateEntityByName( COMMAND_POINT_CLASSNAME ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -string_t CNPC_Citizen::GetModelName() const -{ - string_t iszModelName = BaseClass::GetModelName(); - - // - // If the model refers to an obsolete model, pretend it was blank - // so that we pick the new default model. - // - if (!Q_strnicmp(STRING(iszModelName), "models/c17_", 11) || - !Q_strnicmp(STRING(iszModelName), "models/male", 11) || - !Q_strnicmp(STRING(iszModelName), "models/female", 13) || - !Q_strnicmp(STRING(iszModelName), "models/citizen", 14)) - { - return NULL_STRING; - } - - return iszModelName; -} - -//----------------------------------------------------------------------------- -// Purpose: Overridden to switch our behavior between passive and rebel. We -// become combative after Gordon becomes a criminal. -//----------------------------------------------------------------------------- -Class_T CNPC_Citizen::Classify() -{ - if (GlobalEntity_GetState("gordon_precriminal") == GLOBAL_ON) - return CLASS_CITIZEN_PASSIVE; - - if (GlobalEntity_GetState("citizens_passive") == GLOBAL_ON) - return CLASS_CITIZEN_PASSIVE; - - return CLASS_PLAYER_ALLY; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Citizen::ShouldAlwaysThink() -{ - return ( BaseClass::ShouldAlwaysThink() || IsInPlayerSquad() ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -#define CITIZEN_FOLLOWER_DESERT_FUNCTANK_DIST 45.0f*12.0f -bool CNPC_Citizen::ShouldBehaviorSelectSchedule( CAI_BehaviorBase *pBehavior ) -{ - if( pBehavior == &m_FollowBehavior ) - { - // Suppress follow behavior if I have a func_tank and the func tank is near - // what I'm supposed to be following. - if( m_FuncTankBehavior.CanSelectSchedule() ) - { - // Is the tank close to the follow target? - Vector vecTank = m_FuncTankBehavior.GetFuncTank()->WorldSpaceCenter(); - Vector vecFollowGoal = m_FollowBehavior.GetFollowGoalInfo().position; - - float flTankDistSqr = (vecTank - vecFollowGoal).LengthSqr(); - float flAllowDist = m_FollowBehavior.GetFollowGoalInfo().followPointTolerance * 2.0f; - float flAllowDistSqr = flAllowDist * flAllowDist; - if( flTankDistSqr < flAllowDistSqr ) - { - // Deny follow behavior so the tank can go. - return false; - } - } - } - else if( IsInPlayerSquad() && pBehavior == &m_FuncTankBehavior && m_FuncTankBehavior.IsMounted() ) - { - if( m_FollowBehavior.GetFollowTarget() ) - { - Vector vecFollowGoal = m_FollowBehavior.GetFollowTarget()->GetAbsOrigin(); - if( vecFollowGoal.DistToSqr( GetAbsOrigin() ) > Square(CITIZEN_FOLLOWER_DESERT_FUNCTANK_DIST) ) - { - return false; - } - } - } - - return BaseClass::ShouldBehaviorSelectSchedule( pBehavior ); -} - -void CNPC_Citizen::OnChangeRunningBehavior( CAI_BehaviorBase *pOldBehavior, CAI_BehaviorBase *pNewBehavior ) -{ - if ( pNewBehavior == &m_FuncTankBehavior ) - { - m_bReadinessCapable = false; - } - else if ( pOldBehavior == &m_FuncTankBehavior ) - { - m_bReadinessCapable = IsReadinessCapable(); - } - - BaseClass::OnChangeRunningBehavior( pOldBehavior, pNewBehavior ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::GatherConditions() -{ - BaseClass::GatherConditions(); - - if( IsInPlayerSquad() && hl2_episodic.GetBool() ) - { - // Leave the player squad if someone has made me neutral to player. - if( IRelationType(UTIL_GetLocalPlayer()) == D_NU ) - { - RemoveFromPlayerSquad(); - } - } - - if ( !SpokeConcept( TLK_JOINPLAYER ) && IsRunningScriptedSceneWithSpeech( this, true ) ) - { - SetSpokeConcept( TLK_JOINPLAYER, NULL ); - for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - CAI_BaseNPC *pNpc = g_AI_Manager.AccessAIs()[i]; - if ( pNpc != this && pNpc->GetClassname() == GetClassname() && pNpc->GetAbsOrigin().DistToSqr( GetAbsOrigin() ) < Square( 15*12 ) && FVisible( pNpc ) ) - { - (assert_cast(pNpc))->SetSpokeConcept( TLK_JOINPLAYER, NULL ); - } - } - } - - if( ShouldLookForHealthItem() ) - { - if( FindHealthItem( GetAbsOrigin(), Vector( 240, 240, 240 ) ) ) - SetCondition( COND_HEALTH_ITEM_AVAILABLE ); - else - ClearCondition( COND_HEALTH_ITEM_AVAILABLE ); - - m_flNextHealthSearchTime = gpGlobals->curtime + 4.0; - } - - // If the player is standing near a medic and can see the medic, - // assume the player is 'staring' and wants health. - if( CanHeal() ) - { - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - - if ( !pPlayer ) - { - m_flTimePlayerStare = FLT_MAX; - return; - } - - float flDistSqr = ( GetAbsOrigin() - pPlayer->GetAbsOrigin() ).Length2DSqr(); - float flStareDist = sk_citizen_player_stare_dist.GetFloat(); - float flPlayerDamage = pPlayer->GetMaxHealth() - pPlayer->GetHealth(); - - if( pPlayer->IsAlive() && flPlayerDamage > 0 && (flDistSqr <= flStareDist * flStareDist) && pPlayer->FInViewCone( this ) && pPlayer->FVisible( this ) ) - { - if( m_flTimePlayerStare == FLT_MAX ) - { - // Player wasn't looking at me at last think. He started staring now. - m_flTimePlayerStare = gpGlobals->curtime; - } - - // Heal if it's been long enough since last time I healed a staring player. - if( gpGlobals->curtime - m_flTimePlayerStare >= sk_citizen_player_stare_time.GetFloat() && gpGlobals->curtime > m_flTimeNextHealStare && !IsCurSchedule( SCHED_CITIZEN_HEAL ) ) - { - if ( ShouldHealTarget( pPlayer, true ) ) - { - SetCondition( COND_CIT_PLAYERHEALREQUEST ); - } - else - { - m_flTimeNextHealStare = gpGlobals->curtime + sk_citizen_stare_heal_time.GetFloat() * .5f; - ClearCondition( COND_CIT_PLAYERHEALREQUEST ); - } - } - -#ifdef HL2_EPISODIC - // Heal if I'm on an assault. The player hasn't had time to stare at me. - if( m_AssaultBehavior.IsRunning() && IsMoving() ) - { - SetCondition( COND_CIT_PLAYERHEALREQUEST ); - } -#endif - } - else - { - m_flTimePlayerStare = FLT_MAX; - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::PredictPlayerPush() -{ - if ( !AI_IsSinglePlayer() ) - return; - - if ( HasCondition( COND_CIT_PLAYERHEALREQUEST ) ) - return; - - bool bHadPlayerPush = HasCondition( COND_PLAYER_PUSHING ); - - BaseClass::PredictPlayerPush(); - - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - if ( !bHadPlayerPush && HasCondition( COND_PLAYER_PUSHING ) && - pPlayer->FInViewCone( this ) && CanHeal() ) - { - if ( ShouldHealTarget( pPlayer, true ) ) - { - ClearCondition( COND_PLAYER_PUSHING ); - SetCondition( COND_CIT_PLAYERHEALREQUEST ); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::PrescheduleThink() -{ - BaseClass::PrescheduleThink(); - - UpdatePlayerSquad(); - UpdateFollowCommandPoint(); - - if ( !npc_citizen_insignia.GetBool() && npc_citizen_squad_marker.GetBool() && IsInPlayerSquad() ) - { - Vector mins = WorldAlignMins() * .5 + GetAbsOrigin(); - Vector maxs = WorldAlignMaxs() * .5 + GetAbsOrigin(); - - float rMax = 255; - float gMax = 255; - float bMax = 255; - - float rMin = 255; - float gMin = 128; - float bMin = 0; - - const float TIME_FADE = 1.0; - float timeInSquad = gpGlobals->curtime - m_flTimeJoinedPlayerSquad; - timeInSquad = MIN( TIME_FADE, MAX( timeInSquad, 0 ) ); - - float fade = ( 1.0 - timeInSquad / TIME_FADE ); - - int r = (int)(rMin + ( rMax - rMin ) * fade); - int g = (int)(gMin + ( gMax - gMin ) * fade); - int b = (int)(bMin + ( bMax - bMin ) * fade); - - // THIS IS A PLACEHOLDER UNTIL WE HAVE A REAL DESIGN & ART -- DO NOT REMOVE - NDebugOverlay::Line( Vector( mins.x, GetAbsOrigin().y, GetAbsOrigin().z+1 ), Vector( maxs.x, GetAbsOrigin().y, GetAbsOrigin().z+1 ), r, g, b, false, .11 ); - NDebugOverlay::Line( Vector( GetAbsOrigin().x, mins.y, GetAbsOrigin().z+1 ), Vector( GetAbsOrigin().x, maxs.y, GetAbsOrigin().z+1 ), r, g, b, false, .11 ); - } - if( GetEnemy() && g_ai_citizen_show_enemy.GetBool() ) - { - NDebugOverlay::Line( EyePosition(), GetEnemy()->EyePosition(), 255, 0, 0, false, .1 ); - } - - if ( DebuggingCommanderMode() ) - { - if ( HaveCommandGoal() ) - { - CBaseEntity *pCommandPoint = gEntList.FindEntityByClassname( NULL, COMMAND_POINT_CLASSNAME ); - - if ( pCommandPoint ) - { - NDebugOverlay::Cross3D(pCommandPoint->GetAbsOrigin(), 16, 0, 255, 255, false, 0.1 ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Allows for modification of the interrupt mask for the current schedule. -// In the most cases the base implementation should be called first. -//----------------------------------------------------------------------------- -void CNPC_Citizen::BuildScheduleTestBits() -{ - BaseClass::BuildScheduleTestBits(); - - if ( IsCurSchedule( SCHED_IDLE_STAND ) || IsCurSchedule( SCHED_ALERT_STAND ) ) - { - SetCustomInterruptCondition( COND_CIT_START_INSPECTION ); - } - - if ( IsMedic() && IsCustomInterruptConditionSet( COND_HEAR_MOVE_AWAY ) ) - { - if( !IsCurSchedule(SCHED_RELOAD, false) ) - { - // Since schedule selection code prioritizes reloading over requests to heal - // the player, we must prevent this condition from breaking the reload schedule. - SetCustomInterruptCondition( COND_CIT_PLAYERHEALREQUEST ); - } - - SetCustomInterruptCondition( COND_CIT_COMMANDHEAL ); - } - - if( !IsCurSchedule( SCHED_NEW_WEAPON ) ) - { - SetCustomInterruptCondition( COND_RECEIVED_ORDERS ); - } - - if( GetCurSchedule()->HasInterrupt( COND_IDLE_INTERRUPT ) ) - { - SetCustomInterruptCondition( COND_BETTER_WEAPON_AVAILABLE ); - } - -#ifdef HL2_EPISODIC - if( IsMedic() && m_AssaultBehavior.IsRunning() ) - { - if( !IsCurSchedule(SCHED_RELOAD, false) ) - { - SetCustomInterruptCondition( COND_CIT_PLAYERHEALREQUEST ); - } - - SetCustomInterruptCondition( COND_CIT_COMMANDHEAL ); - } -#else - if( IsMedic() && m_AssaultBehavior.IsRunning() && !IsMoving() ) - { - if( !IsCurSchedule(SCHED_RELOAD, false) ) - { - SetCustomInterruptCondition( COND_CIT_PLAYERHEALREQUEST ); - } - - SetCustomInterruptCondition( COND_CIT_COMMANDHEAL ); - } -#endif -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Citizen::FInViewCone( CBaseEntity *pEntity ) -{ -#if 0 - if ( IsMortar( pEntity ) ) - { - // @TODO (toml 11-20-03): do this only if have heard mortar shell recently and it's active - return true; - } -#endif - return BaseClass::FInViewCone( pEntity ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Citizen::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ) -{ - switch( failedSchedule ) - { - case SCHED_NEW_WEAPON: - // If failed trying to pick up a weapon, try again in one second. This is because other AI code - // has put this off for 10 seconds under the assumption that the citizen would be able to - // pick up the weapon that they found. - m_flNextWeaponSearchTime = gpGlobals->curtime + 1.0f; - break; - - case SCHED_ESTABLISH_LINE_OF_FIRE_FALLBACK: - case SCHED_MOVE_TO_WEAPON_RANGE: - if( !IsMortar( GetEnemy() ) ) - { - if ( GetActiveWeapon() && ( GetActiveWeapon()->CapabilitiesGet() & bits_CAP_WEAPON_RANGE_ATTACK1 ) && random->RandomInt( 0, 1 ) && HasCondition(COND_SEE_ENEMY) && !HasCondition ( COND_NO_PRIMARY_AMMO ) ) - return TranslateSchedule( SCHED_RANGE_ATTACK1 ); - - return SCHED_STANDOFF; - } - break; - } - - return BaseClass::SelectFailSchedule( failedSchedule, failedTask, taskFailCode ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Citizen::SelectSchedule() -{ - // If we can't move, we're on a train, and should be sitting. - if ( GetMoveType() == MOVETYPE_NONE ) - { - // For now, we're only ever parented to trains. If you hit this assert, you've parented a citizen - // to something else, and now we need to figure out a better system. - Assert( GetMoveParent() && FClassnameIs( GetMoveParent(), "func_tracktrain" ) ); - return SCHED_CITIZEN_SIT_ON_TRAIN; - } - - CWeaponRPG *pRPG = dynamic_cast(GetActiveWeapon()); - if ( pRPG && pRPG->IsGuiding() ) - { - DevMsg( "Citizen in select schedule but RPG is guiding?\n"); - pRPG->StopGuiding(); - } - - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Citizen::SelectSchedulePriorityAction() -{ - int schedule = SelectScheduleHeal(); - if ( schedule != SCHED_NONE ) - return schedule; - - schedule = BaseClass::SelectSchedulePriorityAction(); - if ( schedule != SCHED_NONE ) - return schedule; - - schedule = SelectScheduleRetrieveItem(); - if ( schedule != SCHED_NONE ) - return schedule; - - return SCHED_NONE; -} - -//----------------------------------------------------------------------------- -// Determine if citizen should perform heal action. -//----------------------------------------------------------------------------- -int CNPC_Citizen::SelectScheduleHeal() -{ - // episodic medics may toss the healthkits rather than poke you with them -#if HL2_EPISODIC - - if ( CanHeal() ) - { - CBaseEntity *pEntity = PlayerInRange( GetLocalOrigin(), HEAL_TOSS_TARGET_RANGE ); - if ( pEntity ) - { - if ( USE_EXPERIMENTAL_MEDIC_CODE() && IsMedic() ) - { - // use the new heal toss algorithm - if ( ShouldHealTossTarget( pEntity, HasCondition( COND_CIT_PLAYERHEALREQUEST ) ) ) - { - SetTarget( pEntity ); - return SCHED_CITIZEN_HEAL_TOSS; - } - } - else if ( PlayerInRange( GetLocalOrigin(), HEAL_MOVE_RANGE ) ) - { - // use old mechanism for ammo - if ( ShouldHealTarget( pEntity, HasCondition( COND_CIT_PLAYERHEALREQUEST ) ) ) - { - SetTarget( pEntity ); - return SCHED_CITIZEN_HEAL; - } - } - - } - - if ( m_pSquad ) - { - pEntity = NULL; - float distClosestSq = HEAL_MOVE_RANGE*HEAL_MOVE_RANGE; - float distCurSq; - - AISquadIter_t iter; - CAI_BaseNPC *pSquadmate = m_pSquad->GetFirstMember( &iter ); - while ( pSquadmate ) - { - if ( pSquadmate != this ) - { - distCurSq = ( GetAbsOrigin() - pSquadmate->GetAbsOrigin() ).LengthSqr(); - if ( distCurSq < distClosestSq && ShouldHealTarget( pSquadmate ) ) - { - distClosestSq = distCurSq; - pEntity = pSquadmate; - } - } - - pSquadmate = m_pSquad->GetNextMember( &iter ); - } - - if ( pEntity ) - { - SetTarget( pEntity ); - return SCHED_CITIZEN_HEAL; - } - } - } - else - { - if ( HasCondition( COND_CIT_PLAYERHEALREQUEST ) ) - DevMsg( "Would say: sorry, need to recharge\n" ); - } - - return SCHED_NONE; - -#else - - if ( CanHeal() ) - { - CBaseEntity *pEntity = PlayerInRange( GetLocalOrigin(), HEAL_MOVE_RANGE ); - if ( pEntity && ShouldHealTarget( pEntity, HasCondition( COND_CIT_PLAYERHEALREQUEST ) ) ) - { - SetTarget( pEntity ); - return SCHED_CITIZEN_HEAL; - } - - if ( m_pSquad ) - { - pEntity = NULL; - float distClosestSq = HEAL_MOVE_RANGE*HEAL_MOVE_RANGE; - float distCurSq; - - AISquadIter_t iter; - CAI_BaseNPC *pSquadmate = m_pSquad->GetFirstMember( &iter ); - while ( pSquadmate ) - { - if ( pSquadmate != this ) - { - distCurSq = ( GetAbsOrigin() - pSquadmate->GetAbsOrigin() ).LengthSqr(); - if ( distCurSq < distClosestSq && ShouldHealTarget( pSquadmate ) ) - { - distClosestSq = distCurSq; - pEntity = pSquadmate; - } - } - - pSquadmate = m_pSquad->GetNextMember( &iter ); - } - - if ( pEntity ) - { - SetTarget( pEntity ); - return SCHED_CITIZEN_HEAL; - } - } - } - else - { - if ( HasCondition( COND_CIT_PLAYERHEALREQUEST ) ) - DevMsg( "Would say: sorry, need to recharge\n" ); - } - - return SCHED_NONE; - -#endif -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Citizen::SelectScheduleRetrieveItem() -{ - if ( HasCondition(COND_BETTER_WEAPON_AVAILABLE) ) - { - CBaseHLCombatWeapon *pWeapon = dynamic_cast(Weapon_FindUsable( WEAPON_SEARCH_DELTA )); - if ( pWeapon ) - { - m_flNextWeaponSearchTime = gpGlobals->curtime + 10.0; - // Now lock the weapon for several seconds while we go to pick it up. - pWeapon->Lock( 10.0, this ); - SetTarget( pWeapon ); - return SCHED_NEW_WEAPON; - } - } - - if( HasCondition(COND_HEALTH_ITEM_AVAILABLE) ) - { - if( !IsInPlayerSquad() ) - { - // Been kicked out of the player squad since the time I located the health. - ClearCondition( COND_HEALTH_ITEM_AVAILABLE ); - } - else - { - CBaseEntity *pBase = FindHealthItem(m_FollowBehavior.GetFollowTarget()->GetAbsOrigin(), Vector( 120, 120, 120 ) ); - CItem *pItem = dynamic_cast(pBase); - - if( pItem ) - { - SetTarget( pItem ); - return SCHED_GET_HEALTHKIT; - } - } - } - return SCHED_NONE; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Citizen::SelectScheduleNonCombat() -{ - if ( m_NPCState == NPC_STATE_IDLE ) - { - // Handle being inspected by the scanner - if ( HasCondition( COND_CIT_START_INSPECTION ) ) - { - ClearCondition( COND_CIT_START_INSPECTION ); - return SCHED_CITIZEN_PLAY_INSPECT_ACTIVITY; - } - } - - ClearCondition( COND_CIT_START_INSPECTION ); - - if ( m_bShouldPatrol ) - return SCHED_CITIZEN_PATROL; - - return SCHED_NONE; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Citizen::SelectScheduleManhackCombat() -{ - if ( m_NPCState == NPC_STATE_COMBAT && IsManhackMeleeCombatant() ) - { - if ( !HasCondition( COND_CAN_MELEE_ATTACK1 ) ) - { - float distSqEnemy = ( GetEnemy()->GetAbsOrigin() - EyePosition() ).LengthSqr(); - if ( distSqEnemy < 48.0*48.0 && - ( ( GetEnemy()->GetAbsOrigin() + GetEnemy()->GetSmoothedVelocity() * .1 ) - EyePosition() ).LengthSqr() < distSqEnemy ) - return SCHED_COWER; - - int iRoll = random->RandomInt( 1, 4 ); - if ( iRoll == 1 ) - return SCHED_BACK_AWAY_FROM_ENEMY; - else if ( iRoll == 2 ) - return SCHED_CHASE_ENEMY; - } - } - - return SCHED_NONE; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Citizen::SelectScheduleCombat() -{ - int schedule = SelectScheduleManhackCombat(); - if ( schedule != SCHED_NONE ) - return schedule; - - return BaseClass::SelectScheduleCombat(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Citizen::ShouldDeferToFollowBehavior() -{ -#if 0 - if ( HaveCommandGoal() ) - return false; -#endif - - return BaseClass::ShouldDeferToFollowBehavior(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Citizen::TranslateSchedule( int scheduleType ) -{ - CBasePlayer *pLocalPlayer = AI_GetSinglePlayer(); - - switch( scheduleType ) - { - case SCHED_IDLE_STAND: - case SCHED_ALERT_STAND: - if( m_NPCState != NPC_STATE_COMBAT && pLocalPlayer && !pLocalPlayer->IsAlive() && CanJoinPlayerSquad() ) - { - // Player is dead! - float flDist; - flDist = ( pLocalPlayer->GetAbsOrigin() - GetAbsOrigin() ).Length(); - - if( flDist < 50 * 12 ) - { - AddSpawnFlags( SF_CITIZEN_NOT_COMMANDABLE ); - return SCHED_CITIZEN_MOURN_PLAYER; - } - } - break; - - case SCHED_ESTABLISH_LINE_OF_FIRE: - case SCHED_MOVE_TO_WEAPON_RANGE: - if( !IsMortar( GetEnemy() ) && HaveCommandGoal() ) - { - if ( GetActiveWeapon() && ( GetActiveWeapon()->CapabilitiesGet() & bits_CAP_WEAPON_RANGE_ATTACK1 ) && random->RandomInt( 0, 1 ) && HasCondition(COND_SEE_ENEMY) && !HasCondition ( COND_NO_PRIMARY_AMMO ) ) - return TranslateSchedule( SCHED_RANGE_ATTACK1 ); - - return SCHED_STANDOFF; - } - break; - - case SCHED_CHASE_ENEMY: - if( !IsMortar( GetEnemy() ) && HaveCommandGoal() ) - { - return SCHED_STANDOFF; - } - break; - - case SCHED_RANGE_ATTACK1: - // If we have an RPG, we use a custom schedule for it - if ( !IsMortar( GetEnemy() ) && GetActiveWeapon() && FClassnameIs( GetActiveWeapon(), "weapon_rpg" ) ) - { - if ( GetEnemy() && GetEnemy()->ClassMatches( "npc_strider" ) ) - { - if (OccupyStrategySlotRange( SQUAD_SLOT_CITIZEN_RPG1, SQUAD_SLOT_CITIZEN_RPG2 ) ) - { - return SCHED_CITIZEN_STRIDER_RANGE_ATTACK1_RPG; - } - else - { - return SCHED_STANDOFF; - } - } - else - { - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer && GetEnemy() && ( ( GetEnemy()->GetAbsOrigin() - - pPlayer->GetAbsOrigin() ).LengthSqr() < RPG_SAFE_DISTANCE * RPG_SAFE_DISTANCE ) ) - { - // Don't fire our RPG at an enemy too close to the player - return SCHED_STANDOFF; - } - else - { - return SCHED_CITIZEN_RANGE_ATTACK1_RPG; - } - } - } - break; - } - - return BaseClass::TranslateSchedule( scheduleType ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Citizen::ShouldAcceptGoal( CAI_BehaviorBase *pBehavior, CAI_GoalEntity *pGoal ) -{ - if ( BaseClass::ShouldAcceptGoal( pBehavior, pGoal ) ) - { - CAI_FollowBehavior *pFollowBehavior = dynamic_cast(pBehavior ); - if ( pFollowBehavior ) - { - if ( IsInPlayerSquad() ) - { - m_hSavedFollowGoalEnt = (CAI_FollowGoal *)pGoal; - return false; - } - } - return true; - } - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::OnClearGoal( CAI_BehaviorBase *pBehavior, CAI_GoalEntity *pGoal ) -{ - if ( m_hSavedFollowGoalEnt == pGoal ) - m_hSavedFollowGoalEnt = NULL; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_CIT_PLAY_INSPECT_SEQUENCE: - SetIdealActivity( (Activity) m_nInspectActivity ); - break; - - case TASK_CIT_SIT_ON_TRAIN: - if ( NameMatches("citizen_train_2") ) - { - SetSequenceByName( "d1_t01_TrainRide_Sit_Idle" ); - SetIdealActivity( ACT_DO_NOT_DISTURB ); - } - else - { - SetSequenceByName( "d1_t01_TrainRide_Stand" ); - SetIdealActivity( ACT_DO_NOT_DISTURB ); - } - break; - - case TASK_CIT_LEAVE_TRAIN: - if ( NameMatches("citizen_train_2") ) - { - SetSequenceByName( "d1_t01_TrainRide_Sit_Exit" ); - SetIdealActivity( ACT_DO_NOT_DISTURB ); - } - else - { - SetSequenceByName( "d1_t01_TrainRide_Stand_Exit" ); - SetIdealActivity( ACT_DO_NOT_DISTURB ); - } - break; - - case TASK_CIT_HEAL: -#if HL2_EPISODIC - case TASK_CIT_HEAL_TOSS: -#endif - if ( IsMedic() ) - { - if ( GetTarget() && GetTarget()->IsPlayer() && GetTarget()->m_iMaxHealth == GetTarget()->m_iHealth ) - { - // Doesn't need us anymore - TaskComplete(); - break; - } - - Speak( TLK_HEAL ); - } - else if ( IsAmmoResupplier() ) - { - Speak( TLK_GIVEAMMO ); - } - SetIdealActivity( (Activity)ACT_CIT_HEAL ); - break; - - case TASK_CIT_RPG_AUGER: - m_bRPGAvoidPlayer = false; - SetWait( 15.0 ); // maximum time auger before giving up - break; - - case TASK_CIT_SPEAK_MOURNING: - if ( !IsSpeaking() && CanSpeakAfterMyself() ) - { - //CAI_AllySpeechManager *pSpeechManager = GetAllySpeechManager(); - - //if ( pSpeechManager-> ) - - Speak(TLK_PLDEAD); - } - TaskComplete(); - break; - - default: - BaseClass::StartTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_WAIT_FOR_MOVEMENT: - { - if ( IsManhackMeleeCombatant() ) - { - AddFacingTarget( GetEnemy(), 1.0, 0.5 ); - } - - BaseClass::RunTask( pTask ); - break; - } - - case TASK_MOVE_TO_TARGET_RANGE: - { - // If we're moving to heal a target, and the target dies, stop - if ( IsCurSchedule( SCHED_CITIZEN_HEAL ) && (!GetTarget() || !GetTarget()->IsAlive()) ) - { - TaskFail(FAIL_NO_TARGET); - return; - } - - BaseClass::RunTask( pTask ); - break; - } - - case TASK_CIT_PLAY_INSPECT_SEQUENCE: - { - AutoMovement(); - - if ( IsSequenceFinished() ) - { - TaskComplete(); - } - break; - } - case TASK_CIT_SIT_ON_TRAIN: - { - // If we were on a train, but we're not anymore, enable movement - if ( !GetMoveParent() ) - { - SetMoveType( MOVETYPE_STEP ); - CapabilitiesAdd( bits_CAP_MOVE_GROUND ); - TaskComplete(); - } - break; - } - - case TASK_CIT_LEAVE_TRAIN: - { - if ( IsSequenceFinished() ) - { - SetupVPhysicsHull(); - TaskComplete(); - } - break; - } - - case TASK_CIT_HEAL: - if ( IsSequenceFinished() ) - { - TaskComplete(); - } - else if (!GetTarget()) - { - // Our heal target was killed or deleted somehow. - TaskFail(FAIL_NO_TARGET); - } - else - { - if ( ( GetTarget()->GetAbsOrigin() - GetAbsOrigin() ).Length2D() > HEAL_MOVE_RANGE/2 ) - TaskComplete(); - - GetMotor()->SetIdealYawToTargetAndUpdate( GetTarget()->GetAbsOrigin() ); - } - break; - - -#if HL2_EPISODIC - case TASK_CIT_HEAL_TOSS: - if ( IsSequenceFinished() ) - { - TaskComplete(); - } - else if (!GetTarget()) - { - // Our heal target was killed or deleted somehow. - TaskFail(FAIL_NO_TARGET); - } - else - { - GetMotor()->SetIdealYawToTargetAndUpdate( GetTarget()->GetAbsOrigin() ); - } - break; - -#endif - - case TASK_CIT_RPG_AUGER: - { - // Keep augering until the RPG has been destroyed - CWeaponRPG *pRPG = dynamic_cast(GetActiveWeapon()); - if ( !pRPG ) - { - TaskFail( FAIL_ITEM_NO_FIND ); - return; - } - - // Has the RPG detonated? - if ( !pRPG->GetMissile() ) - { - pRPG->StopGuiding(); - TaskComplete(); - return; - } - - Vector vecLaserPos = pRPG->GetNPCLaserPosition(); - - if ( !m_bRPGAvoidPlayer ) - { - // Abort if we've lost our enemy - if ( !GetEnemy() ) - { - pRPG->StopGuiding(); - TaskFail( FAIL_NO_ENEMY ); - return; - } - - // Is our enemy occluded? - if ( HasCondition( COND_ENEMY_OCCLUDED ) ) - { - // Turn off the laserdot, but don't stop augering - pRPG->StopGuiding(); - return; - } - else if ( pRPG->IsGuiding() == false ) - { - pRPG->StartGuiding(); - } - - Vector vecEnemyPos = GetEnemy()->BodyTarget(GetAbsOrigin(), false); - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer && ( ( vecEnemyPos - pPlayer->GetAbsOrigin() ).LengthSqr() < RPG_SAFE_DISTANCE * RPG_SAFE_DISTANCE ) ) - { - m_bRPGAvoidPlayer = true; - Speak( TLK_WATCHOUT ); - } - else - { - // Pull the laserdot towards the target - Vector vecToTarget = (vecEnemyPos - vecLaserPos); - float distToMove = VectorNormalize( vecToTarget ); - if ( distToMove > 90 ) - distToMove = 90; - vecLaserPos += vecToTarget * distToMove; - } - } - - if ( m_bRPGAvoidPlayer ) - { - // Pull the laserdot up - vecLaserPos.z += 90; - } - - if ( IsWaitFinished() ) - { - pRPG->StopGuiding(); - TaskFail( FAIL_NO_SHOOT ); - return; - } - // Add imprecision to avoid obvious robotic perfection stationary targets - float imprecision = 18*sin(gpGlobals->curtime); - vecLaserPos.x += imprecision; - vecLaserPos.y += imprecision; - vecLaserPos.z += imprecision; - pRPG->UpdateNPCLaserPosition( vecLaserPos ); - } - break; - - default: - BaseClass::RunTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : code - -//----------------------------------------------------------------------------- -void CNPC_Citizen::TaskFail( AI_TaskFailureCode_t code ) -{ - // If our heal task has failed, push out the heal time - if ( IsCurSchedule( SCHED_CITIZEN_HEAL ) ) - { - m_flPlayerHealTime = gpGlobals->curtime + sk_citizen_heal_ally_delay.GetFloat(); - } - - if( code == FAIL_NO_ROUTE_BLOCKED && m_bNotifyNavFailBlocked ) - { - m_OnNavFailBlocked.FireOutput( this, this ); - } - - BaseClass::TaskFail( code ); -} - -//----------------------------------------------------------------------------- -// Purpose: Override base class activiites -//----------------------------------------------------------------------------- -Activity CNPC_Citizen::NPC_TranslateActivity( Activity activity ) -{ - if ( activity == ACT_MELEE_ATTACK1 ) - { - return ACT_MELEE_ATTACK_SWING; - } - - // !!!HACK - Citizens don't have the required animations for shotguns, - // so trick them into using the rifle counterparts for now (sjb) - if ( activity == ACT_RUN_AIM_SHOTGUN ) - return ACT_RUN_AIM_RIFLE; - if ( activity == ACT_WALK_AIM_SHOTGUN ) - return ACT_WALK_AIM_RIFLE; - if ( activity == ACT_IDLE_ANGRY_SHOTGUN ) - return ACT_IDLE_ANGRY_SMG1; - if ( activity == ACT_RANGE_ATTACK_SHOTGUN_LOW ) - return ACT_RANGE_ATTACK_SMG1_LOW; - - return BaseClass::NPC_TranslateActivity( activity ); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_Citizen::HandleAnimEvent( animevent_t *pEvent ) -{ - if ( pEvent->event == AE_CITIZEN_GET_PACKAGE ) - { - // Give the citizen a package - CBaseCombatWeapon *pWeapon = Weapon_Create( "weapon_citizenpackage" ); - if ( pWeapon ) - { - // If I have a name, make my weapon match it with "_weapon" appended - if ( GetEntityName() != NULL_STRING ) - { - pWeapon->SetName( AllocPooledString(UTIL_VarArgs("%s_weapon", STRING(GetEntityName()))) ); - } - Weapon_Equip( pWeapon ); - } - return; - } - else if ( pEvent->event == AE_CITIZEN_HEAL ) - { - // Heal my target (if within range) -#if HL2_EPISODIC - if ( USE_EXPERIMENTAL_MEDIC_CODE() && IsMedic() ) - { - CBaseCombatCharacter *pTarget = dynamic_cast( GetTarget() ); - Assert(pTarget); - if ( pTarget ) - { - m_flPlayerHealTime = gpGlobals->curtime + sk_citizen_heal_toss_player_delay.GetFloat();; - TossHealthKit( pTarget, Vector(48.0f, 0.0f, 0.0f) ); - } - } - else - { - Heal(); - } -#else - Heal(); -#endif - return; - } - - switch( pEvent->event ) - { - case NPC_EVENT_LEFTFOOT: - { - EmitSound( "NPC_Citizen.FootstepLeft", pEvent->eventtime ); - } - break; - - case NPC_EVENT_RIGHTFOOT: - { - EmitSound( "NPC_Citizen.FootstepRight", pEvent->eventtime ); - } - break; - - default: - BaseClass::HandleAnimEvent( pEvent ); - break; - } -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_Citizen::PickupItem( CBaseEntity *pItem ) -{ - Assert( pItem != NULL ); - if( FClassnameIs( pItem, "item_healthkit" ) ) - { - if ( TakeHealth( sk_healthkit.GetFloat(), DMG_GENERIC ) ) - { - RemoveAllDecals(); - UTIL_Remove( pItem ); - } - } - else if( FClassnameIs( pItem, "item_healthvial" ) ) - { - if ( TakeHealth( sk_healthvial.GetFloat(), DMG_GENERIC ) ) - { - RemoveAllDecals(); - UTIL_Remove( pItem ); - } - } - else - { - DevMsg("Citizen doesn't know how to pick up %s!\n", pItem->GetClassname() ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_Citizen::IgnorePlayerPushing( void ) -{ - // If the NPC's on a func_tank that the player cannot man, ignore player pushing - if ( m_FuncTankBehavior.IsMounted() ) - { - CFuncTank *pTank = m_FuncTankBehavior.GetFuncTank(); - if ( pTank && !pTank->IsControllable() ) - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Return a random expression for the specified state to play over -// the state's expression loop. -//----------------------------------------------------------------------------- -const char *CNPC_Citizen::SelectRandomExpressionForState( NPC_STATE state ) -{ - // Hacky remap of NPC states to expression states that we care about - int iExpressionState = 0; - switch ( state ) - { - case NPC_STATE_IDLE: - iExpressionState = 0; - break; - - case NPC_STATE_ALERT: - iExpressionState = 1; - break; - - case NPC_STATE_COMBAT: - iExpressionState = 2; - break; - - default: - // An NPC state we don't have expressions for - return NULL; - } - - // Now pick the right one for our expression type - switch ( m_ExpressionType ) - { - case CIT_EXP_SCARED: - { - int iRandom = RandomInt( 0, ARRAYSIZE(ScaredExpressions[iExpressionState].szExpressions)-1 ); - return ScaredExpressions[iExpressionState].szExpressions[iRandom]; - } - - case CIT_EXP_NORMAL: - { - int iRandom = RandomInt( 0, ARRAYSIZE(NormalExpressions[iExpressionState].szExpressions)-1 ); - return NormalExpressions[iExpressionState].szExpressions[iRandom]; - } - - case CIT_EXP_ANGRY: - { - int iRandom = RandomInt( 0, ARRAYSIZE(AngryExpressions[iExpressionState].szExpressions)-1 ); - return AngryExpressions[iExpressionState].szExpressions[iRandom]; - } - - default: - break; - } - - return NULL; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::SimpleUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - // Under these conditions, citizens will refuse to go with the player. - // Robin: NPCs should always respond to +USE even if someone else has the semaphore. - m_bDontUseSemaphore = true; - - // First, try to speak the +USE concept - if ( !SelectPlayerUseSpeech() ) - { - if ( HasSpawnFlags(SF_CITIZEN_NOT_COMMANDABLE) || IRelationType( pActivator ) == D_NU ) - { - // If I'm denying commander mode because a level designer has made that decision, - // then fire this output in case they've hooked it to an event. - m_OnDenyCommanderUse.FireOutput( this, this ); - } - } - - m_bDontUseSemaphore = false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Citizen::OnBeginMoveAndShoot() -{ - if ( BaseClass::OnBeginMoveAndShoot() ) - { - if( m_iMySquadSlot == SQUAD_SLOT_ATTACK1 || m_iMySquadSlot == SQUAD_SLOT_ATTACK2 ) - return true; // already have the slot I need - - if( m_iMySquadSlot == SQUAD_SLOT_NONE && OccupyStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::OnEndMoveAndShoot() -{ - VacateStrategySlot(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::LocateEnemySound() -{ -#if 0 - if ( !GetEnemy() ) - return; - - float flZDiff = GetLocalOrigin().z - GetEnemy()->GetLocalOrigin().z; - - if( flZDiff < -128 ) - { - EmitSound( "NPC_Citizen.UpThere" ); - } - else if( flZDiff > 128 ) - { - EmitSound( "NPC_Citizen.DownThere" ); - } - else - { - EmitSound( "NPC_Citizen.OverHere" ); - } -#endif -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Citizen::IsManhackMeleeCombatant() -{ - CBaseCombatWeapon *pWeapon = GetActiveWeapon(); - CBaseEntity *pEnemy = GetEnemy(); - return ( pEnemy && pWeapon && pEnemy->Classify() == CLASS_MANHACK && pWeapon->ClassMatches( "weapon_crowbar" ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: Return the actual position the NPC wants to fire at when it's trying -// to hit it's current enemy. -//----------------------------------------------------------------------------- -Vector CNPC_Citizen::GetActualShootPosition( const Vector &shootOrigin ) -{ - Vector vecTarget = BaseClass::GetActualShootPosition( shootOrigin ); - - CWeaponRPG *pRPG = dynamic_cast(GetActiveWeapon()); - // If we're firing an RPG at a gunship, aim off to it's side, because we'll auger towards it. - if ( pRPG && GetEnemy() ) - { - if ( FClassnameIs( GetEnemy(), "npc_combinegunship" ) ) - { - Vector vecRight; - GetVectors( NULL, &vecRight, NULL ); - // Random height - vecRight.z = 0; - - // Find a clear shot by checking for clear shots around it - float flShotOffsets[] = - { - 512, - -512, - 128, - -128 - }; - for ( size_t i = 0; i < ARRAYSIZE(flShotOffsets); i++ ) - { - Vector vecTest = vecTarget + (vecRight * flShotOffsets[i]); - // Add some random height to it - vecTest.z += RandomFloat( -512, 512 ); - trace_t tr; - AI_TraceLine( shootOrigin, vecTest, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); - - // If we can see the point, it's a clear shot - if ( tr.fraction == 1.0 && tr.m_pEnt != GetEnemy() ) - { - pRPG->SetNPCLaserPosition( vecTest ); - return vecTest; - } - } - } - else - { - pRPG->SetNPCLaserPosition( vecTarget ); - } - - } - - return vecTarget; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ) -{ - if ( pNewWeapon ) - { - GetShotRegulator()->SetParameters( pNewWeapon->GetMinBurst(), pNewWeapon->GetMaxBurst(), pNewWeapon->GetMinRestTime(), pNewWeapon->GetMaxRestTime() ); - } - BaseClass::OnChangeActiveWeapon( pOldWeapon, pNewWeapon ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -#define SHOTGUN_DEFER_SEARCH_TIME 20.0f -#define OTHER_DEFER_SEARCH_TIME FLT_MAX -bool CNPC_Citizen::ShouldLookForBetterWeapon() -{ - if ( BaseClass::ShouldLookForBetterWeapon() ) - { - if ( IsInPlayerSquad() && (GetActiveWeapon()&&IsMoving()) && ( m_FollowBehavior.GetFollowTarget() && m_FollowBehavior.GetFollowTarget()->IsPlayer() ) ) - { - // For citizens in the player squad, you must be unarmed, or standing still (if armed) in order to - // divert attention to looking for a new weapon. - return false; - } - - if ( GetActiveWeapon() && IsMoving() ) - return false; - - if ( GlobalEntity_GetState("gordon_precriminal") == GLOBAL_ON ) - { - // This stops the NPC looking altogether. - m_flNextWeaponSearchTime = FLT_MAX; - return false; - } - -#ifdef DEBUG - // Cached off to make sure you change this if you ask the code to defer. - float flOldWeaponSearchTime = m_flNextWeaponSearchTime; -#endif - - CBaseCombatWeapon *pWeapon = GetActiveWeapon(); - if( pWeapon ) - { - bool bDefer = false; - - if( FClassnameIs( pWeapon, "weapon_ar2" ) ) - { - // Content to keep this weapon forever - m_flNextWeaponSearchTime = OTHER_DEFER_SEARCH_TIME; - bDefer = true; - } - else if( FClassnameIs( pWeapon, "weapon_rpg" ) ) - { - // Content to keep this weapon forever - m_flNextWeaponSearchTime = OTHER_DEFER_SEARCH_TIME; - bDefer = true; - } - else if( FClassnameIs( pWeapon, "weapon_shotgun" ) ) - { - // Shotgunners do not defer their weapon search indefinitely. - // If more than one citizen in the squad has a shotgun, we force - // some of them to trade for another weapon. - if( NumWeaponsInSquad("weapon_shotgun") > 1 ) - { - // Check for another weapon now. If I don't find one, this code will - // retry in 2 seconds or so. - bDefer = false; - } - else - { - // I'm the only shotgunner in the group right now, so I'll check - // again in 3 0seconds or so. This code attempts to distribute - // the desire to reduce shotguns amongst squadmates so that all - // shotgunners do not discard their weapons when they suddenly realize - // the squad has too many. - if( random->RandomInt( 0, 1 ) == 0 ) - { - m_flNextWeaponSearchTime = gpGlobals->curtime + SHOTGUN_DEFER_SEARCH_TIME; - } - else - { - m_flNextWeaponSearchTime = gpGlobals->curtime + SHOTGUN_DEFER_SEARCH_TIME + 10.0f; - } - - bDefer = true; - } - } - - if( bDefer ) - { - // I'm happy with my current weapon. Don't search now. - // If you ask the code to defer, you must have set m_flNextWeaponSearchTime to when - // you next want to try to search. - Assert( m_flNextWeaponSearchTime != flOldWeaponSearchTime ); - return false; - } - } - - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Citizen::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - if( (info.GetDamageType() & DMG_BURN) && (info.GetDamageType() & DMG_DIRECT) ) - { -#define CITIZEN_SCORCH_RATE 6 -#define CITIZEN_SCORCH_FLOOR 75 - - Scorch( CITIZEN_SCORCH_RATE, CITIZEN_SCORCH_FLOOR ); - } - - CTakeDamageInfo newInfo = info; - - if( IsInSquad() && (info.GetDamageType() & DMG_BLAST) && info.GetInflictor() ) - { - if( npc_citizen_explosive_resist.GetBool() ) - { - // Blast damage. If this kills a squad member, give the - // remaining citizens a resistance bonus to this inflictor - // to try to avoid having the entire squad wiped out by a - // single explosion. - if( m_pSquad->IsSquadInflictor( info.GetInflictor() ) ) - { - newInfo.ScaleDamage( 0.5 ); - } - else - { - // If this blast is going to kill me, designate the inflictor - // so that the rest of the squad can enjoy a damage resist. - if( info.GetDamage() >= GetHealth() ) - { - m_pSquad->SetSquadInflictor( info.GetInflictor() ); - } - } - } - } - - return BaseClass::OnTakeDamage_Alive( newInfo ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Citizen::IsCommandable() -{ - return ( !HasSpawnFlags(SF_CITIZEN_NOT_COMMANDABLE) && IsInPlayerSquad() ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Citizen::IsPlayerAlly( CBasePlayer *pPlayer ) -{ - if ( Classify() == CLASS_CITIZEN_PASSIVE && GlobalEntity_GetState("gordon_precriminal") == GLOBAL_ON ) - { - // Robin: Citizens use friendly speech semaphore in trainstation - return true; - } - - return BaseClass::IsPlayerAlly( pPlayer ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Citizen::CanJoinPlayerSquad() -{ - if ( !AI_IsSinglePlayer() ) - return false; - - if ( m_NPCState == NPC_STATE_SCRIPT || m_NPCState == NPC_STATE_PRONE ) - return false; - - if ( HasSpawnFlags(SF_CITIZEN_NOT_COMMANDABLE) ) - return false; - - if ( IsInAScript() ) - return false; - - // Don't bother people who don't want to be bothered - if ( !CanBeUsedAsAFriend() ) - return false; - - if ( IRelationType( UTIL_GetLocalPlayer() ) != D_LI ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Citizen::WasInPlayerSquad() -{ - return m_bWasInPlayerSquad; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Citizen::HaveCommandGoal() const -{ - if (GetCommandGoal() != vec3_invalid) - return true; - return false; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Citizen::IsCommandMoving() -{ - if ( AI_IsSinglePlayer() && IsInPlayerSquad() ) - { - if ( m_FollowBehavior.GetFollowTarget() == UTIL_GetLocalPlayer() || - IsFollowingCommandPoint() ) - { - return ( m_FollowBehavior.IsMovingToFollowTarget() ); - } - } - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Citizen::ShouldAutoSummon() -{ - if ( !AI_IsSinglePlayer() || !IsFollowingCommandPoint() || !IsInPlayerSquad() ) - return false; - - CHL2_Player *pPlayer = (CHL2_Player *)UTIL_GetLocalPlayer(); - - float distMovedSq = ( pPlayer->GetAbsOrigin() - m_vAutoSummonAnchor ).LengthSqr(); - float moveTolerance = player_squad_autosummon_move_tolerance.GetFloat() * 12; - const Vector &vCommandGoal = GetCommandGoal(); - - if ( distMovedSq < Square(moveTolerance * 10) && (GetAbsOrigin() - vCommandGoal).LengthSqr() > Square(10*12) && IsCommandMoving() ) - { - m_AutoSummonTimer.Set( player_squad_autosummon_time.GetFloat() ); - if ( player_squad_autosummon_debug.GetBool() ) - DevMsg( "Waiting for arrival before initiating autosummon logic\n"); - } - else if ( m_AutoSummonTimer.Expired() ) - { - bool bSetFollow = false; - bool bTestEnemies = true; - - // Auto summon unconditionally if a significant amount of time has passed - if ( gpGlobals->curtime - m_AutoSummonTimer.GetNext() > player_squad_autosummon_time.GetFloat() * 2 ) - { - bSetFollow = true; - if ( player_squad_autosummon_debug.GetBool() ) - DevMsg( "Auto summoning squad: long time (%f)\n", ( gpGlobals->curtime - m_AutoSummonTimer.GetNext() ) + player_squad_autosummon_time.GetFloat() ); - } - - // Player must move for autosummon - if ( distMovedSq > Square(12) ) - { - bool bCommandPointIsVisible = pPlayer->FVisible( vCommandGoal + pPlayer->GetViewOffset() ); - - // Auto summon if the player is close by the command point - if ( !bSetFollow && bCommandPointIsVisible && distMovedSq > Square(24) ) - { - float closenessTolerance = player_squad_autosummon_player_tolerance.GetFloat() * 12; - if ( (pPlayer->GetAbsOrigin() - vCommandGoal).LengthSqr() < Square( closenessTolerance ) && - ((m_vAutoSummonAnchor - vCommandGoal).LengthSqr() > Square( closenessTolerance )) ) - { - bSetFollow = true; - if ( player_squad_autosummon_debug.GetBool() ) - DevMsg( "Auto summoning squad: player close to command point (%f)\n", (GetAbsOrigin() - vCommandGoal).Length() ); - } - } - - // Auto summon if moved a moderate distance and can't see command point, or moved a great distance - if ( !bSetFollow ) - { - if ( distMovedSq > Square( moveTolerance * 2 ) ) - { - bSetFollow = true; - bTestEnemies = ( distMovedSq < Square( moveTolerance * 10 ) ); - if ( player_squad_autosummon_debug.GetBool() ) - DevMsg( "Auto summoning squad: player very far from anchor (%f)\n", sqrt(distMovedSq) ); - } - else if ( distMovedSq > Square( moveTolerance ) ) - { - if ( !bCommandPointIsVisible ) - { - bSetFollow = true; - if ( player_squad_autosummon_debug.GetBool() ) - DevMsg( "Auto summoning squad: player far from anchor (%f)\n", sqrt(distMovedSq) ); - } - } - } - } - - // Auto summon only if there are no readily apparent enemies - if ( bSetFollow && bTestEnemies ) - { - for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - CAI_BaseNPC *pNpc = g_AI_Manager.AccessAIs()[i]; - float timeSinceCombatTolerance = player_squad_autosummon_time_after_combat.GetFloat(); - - if ( pNpc->IsInPlayerSquad() ) - { - if ( gpGlobals->curtime - pNpc->GetLastAttackTime() > timeSinceCombatTolerance || - gpGlobals->curtime - pNpc->GetLastDamageTime() > timeSinceCombatTolerance ) - continue; - } - else if ( pNpc->GetEnemy() ) - { - CBaseEntity *pNpcEnemy = pNpc->GetEnemy(); - if ( !IsSniper( pNpc ) && ( gpGlobals->curtime - pNpc->GetEnemyLastTimeSeen() ) > timeSinceCombatTolerance ) - continue; - - if ( pNpcEnemy == pPlayer ) - { - if ( pNpc->CanBeAnEnemyOf( pPlayer ) ) - { - bSetFollow = false; - break; - } - } - else if ( pNpcEnemy->IsNPC() && ( pNpcEnemy->MyNPCPointer()->GetSquad() == GetSquad() || pNpcEnemy->Classify() == CLASS_PLAYER_ALLY_VITAL ) ) - { - if ( pNpc->CanBeAnEnemyOf( this ) ) - { - bSetFollow = false; - break; - } - } - } - } - if ( !bSetFollow && player_squad_autosummon_debug.GetBool() ) - DevMsg( "Auto summon REVOKED: Combat recent \n"); - } - - return bSetFollow; - } - return false; -} - -//----------------------------------------------------------------------------- -// Is this entity something that the citizen should interact with (return true) -// or something that he should try to get close to (return false) -//----------------------------------------------------------------------------- -bool CNPC_Citizen::IsValidCommandTarget( CBaseEntity *pTarget ) -{ - return false; -} - -//----------------------------------------------------------------------------- -bool CNPC_Citizen::SpeakCommandResponse( AIConcept_t concept, const char *modifiers ) -{ - return SpeakIfAllowed( concept, - CFmtStr( "numselected:%d," - "useradio:%d%s", - ( GetSquad() ) ? GetSquad()->NumMembers() : 1, - ShouldSpeakRadio( AI_GetSinglePlayer() ), - ( modifiers ) ? CFmtStr(",%s", modifiers).operator const char *() : "" ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: return TRUE if the commander mode should try to give this order -// to more people. return FALSE otherwise. For instance, we don't -// try to send all 3 selectedcitizens to pick up the same gun. -//----------------------------------------------------------------------------- -bool CNPC_Citizen::TargetOrder( CBaseEntity *pTarget, CAI_BaseNPC **Allies, int numAllies ) -{ - if ( pTarget->IsPlayer() ) - { - // I'm the target! Toggle follow! - if( m_FollowBehavior.GetFollowTarget() != pTarget ) - { - ClearFollowTarget(); - SetCommandGoal( vec3_invalid ); - - // Turn follow on! - m_AssaultBehavior.Disable(); - m_FollowBehavior.SetFollowTarget( pTarget ); - m_FollowBehavior.SetParameters( AIF_SIMPLE ); - SpeakCommandResponse( TLK_STARTFOLLOW ); - - m_OnFollowOrder.FireOutput( this, this ); - } - else if ( m_FollowBehavior.GetFollowTarget() == pTarget ) - { - // Stop following. - m_FollowBehavior.SetFollowTarget( NULL ); - SpeakCommandResponse( TLK_STOPFOLLOW ); - } - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Turn off following before processing a move order. -//----------------------------------------------------------------------------- -void CNPC_Citizen::MoveOrder( const Vector &vecDest, CAI_BaseNPC **Allies, int numAllies ) -{ - if ( !AI_IsSinglePlayer() ) - return; - - if( hl2_episodic.GetBool() && m_iszDenyCommandConcept != NULL_STRING ) - { - SpeakCommandResponse( STRING(m_iszDenyCommandConcept) ); - return; - } - - CHL2_Player *pPlayer = (CHL2_Player *)UTIL_GetLocalPlayer(); - - m_AutoSummonTimer.Set( player_squad_autosummon_time.GetFloat() ); - m_vAutoSummonAnchor = pPlayer->GetAbsOrigin(); - - if( m_StandoffBehavior.IsRunning() ) - { - m_StandoffBehavior.SetStandoffGoalPosition( vecDest ); - } - - // If in assault, cancel and move. - if( m_AssaultBehavior.HasHitRallyPoint() && !m_AssaultBehavior.HasHitAssaultPoint() ) - { - m_AssaultBehavior.Disable(); - ClearSchedule( "Moving from rally point to assault point" ); - } - - bool spoke = false; - - CAI_BaseNPC *pClosest = NULL; - float closestDistSq = FLT_MAX; - - for( int i = 0 ; i < numAllies ; i++ ) - { - if( Allies[i]->IsInPlayerSquad() ) - { - Assert( Allies[i]->IsCommandable() ); - float distSq = ( pPlayer->GetAbsOrigin() - Allies[i]->GetAbsOrigin() ).LengthSqr(); - if( distSq < closestDistSq ) - { - pClosest = Allies[i]; - closestDistSq = distSq; - } - } - } - - if( m_FollowBehavior.GetFollowTarget() && !IsFollowingCommandPoint() ) - { - ClearFollowTarget(); -#if 0 - if ( ( pPlayer->GetAbsOrigin() - GetAbsOrigin() ).LengthSqr() < Square( 180 ) && - ( ( vecDest - pPlayer->GetAbsOrigin() ).LengthSqr() < Square( 120 ) || - ( vecDest - GetAbsOrigin() ).LengthSqr() < Square( 120 ) ) ) - { - if ( pClosest == this ) - SpeakIfAllowed( TLK_STOPFOLLOW ); - spoke = true; - } -#endif - } - - if ( !spoke && pClosest == this ) - { - float destDistToPlayer = ( vecDest - pPlayer->GetAbsOrigin() ).Length(); - float destDistToClosest = ( vecDest - GetAbsOrigin() ).Length(); - CFmtStr modifiers( "commandpoint_dist_to_player:%.0f," - "commandpoint_dist_to_npc:%.0f", - destDistToPlayer, - destDistToClosest ); - - SpeakCommandResponse( TLK_COMMANDED, modifiers ); - } - - m_OnStationOrder.FireOutput( this, this ); - - BaseClass::MoveOrder( vecDest, Allies, numAllies ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::OnMoveOrder() -{ - SetReadinessLevel( AIRL_STIMULATED, false, false ); - BaseClass::OnMoveOrder(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::CommanderUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - m_OnPlayerUse.FireOutput( pActivator, pCaller ); - - // Under these conditions, citizens will refuse to go with the player. - // Robin: NPCs should always respond to +USE even if someone else has the semaphore. - if ( !AI_IsSinglePlayer() || !CanJoinPlayerSquad() ) - { - SimpleUse( pActivator, pCaller, useType, value ); - return; - } - - if ( pActivator == UTIL_GetLocalPlayer() ) - { - // Don't say hi after you've been addressed by the player - SetSpokeConcept( TLK_HELLO, NULL ); - - if ( npc_citizen_auto_player_squad_allow_use.GetBool() ) - { - if ( !ShouldAutosquad() ) - TogglePlayerSquadState(); - else if ( !IsInPlayerSquad() && npc_citizen_auto_player_squad_allow_use.GetBool() ) - AddToPlayerSquad(); - } - else if ( GetCurSchedule() && ConditionInterruptsCurSchedule( COND_IDLE_INTERRUPT ) ) - { - if ( SpeakIfAllowed( TLK_QUESTION, NULL, true ) ) - { - if ( random->RandomInt( 1, 4 ) < 4 ) - { - CBaseEntity *pRespondant = FindSpeechTarget( AIST_NPCS ); - if ( pRespondant ) - { - g_EventQueue.AddEvent( pRespondant, "SpeakIdleResponse", ( GetTimeSpeechComplete() - gpGlobals->curtime ) + .2, this, this ); - } - } - } - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Citizen::ShouldSpeakRadio( CBaseEntity *pListener ) -{ - if ( !pListener ) - return false; - - const float radioRange = 384 * 384; - Vector vecDiff; - - vecDiff = WorldSpaceCenter() - pListener->WorldSpaceCenter(); - - if( vecDiff.LengthSqr() > radioRange ) - { - return true; - } - - return false; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::OnMoveToCommandGoalFailed() -{ - // Clear the goal. - SetCommandGoal( vec3_invalid ); - - // Announce failure. - SpeakCommandResponse( TLK_COMMAND_FAILED ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::AddToPlayerSquad() -{ - Assert( !IsInPlayerSquad() ); - - AddToSquad( AllocPooledString(PLAYER_SQUADNAME) ); - m_hSavedFollowGoalEnt = m_FollowBehavior.GetFollowGoal(); - m_FollowBehavior.SetFollowGoalDirect( NULL ); - - FixupPlayerSquad(); - - SetCondition( COND_PLAYER_ADDED_TO_SQUAD ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::RemoveFromPlayerSquad() -{ - Assert( IsInPlayerSquad() ); - - ClearFollowTarget(); - ClearCommandGoal(); - if ( m_iszOriginalSquad != NULL_STRING && strcmp( STRING( m_iszOriginalSquad ), PLAYER_SQUADNAME ) != 0 ) - AddToSquad( m_iszOriginalSquad ); - else - RemoveFromSquad(); - - if ( m_hSavedFollowGoalEnt ) - m_FollowBehavior.SetFollowGoal( m_hSavedFollowGoalEnt ); - - SetCondition( COND_PLAYER_REMOVED_FROM_SQUAD ); - - // Don't evaluate the player squad for 2 seconds. - gm_PlayerSquadEvaluateTimer.Set( 2.0 ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::TogglePlayerSquadState() -{ - if ( !AI_IsSinglePlayer() ) - return; - - if ( !IsInPlayerSquad() ) - { - AddToPlayerSquad(); - - if ( HaveCommandGoal() ) - { - SpeakCommandResponse( TLK_COMMANDED ); - } - else if ( m_FollowBehavior.GetFollowTarget() == UTIL_GetLocalPlayer() ) - { - SpeakCommandResponse( TLK_STARTFOLLOW ); - } - } - else - { - SpeakCommandResponse( TLK_STOPFOLLOW ); - RemoveFromPlayerSquad(); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -struct SquadCandidate_t -{ - CNPC_Citizen *pCitizen; - bool bIsInSquad; - float distSq; - int iSquadIndex; -}; - -void CNPC_Citizen::UpdatePlayerSquad() -{ - if ( !AI_IsSinglePlayer() ) - return; - - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - if ( ( pPlayer->GetAbsOrigin().AsVector2D() - GetAbsOrigin().AsVector2D() ).LengthSqr() < Square(20*12) ) - m_flTimeLastCloseToPlayer = gpGlobals->curtime; - - if ( !gm_PlayerSquadEvaluateTimer.Expired() ) - return; - - gm_PlayerSquadEvaluateTimer.Set( 2.0 ); - - // Remove stragglers - CAI_Squad *pPlayerSquad = g_AI_SquadManager.FindSquad( MAKE_STRING( PLAYER_SQUADNAME ) ); - if ( pPlayerSquad ) - { - CUtlVectorFixed squadMembersToRemove; - AISquadIter_t iter; - - for ( CAI_BaseNPC *pPlayerSquadMember = pPlayerSquad->GetFirstMember(&iter); pPlayerSquadMember; pPlayerSquadMember = pPlayerSquad->GetNextMember(&iter) ) - { - if ( pPlayerSquadMember->GetClassname() != GetClassname() ) - continue; - - CNPC_Citizen *pCitizen = assert_cast(pPlayerSquadMember); - - if ( !pCitizen->m_bNeverLeavePlayerSquad && - pCitizen->m_FollowBehavior.GetFollowTarget() && - !pCitizen->m_FollowBehavior.FollowTargetVisible() && - pCitizen->m_FollowBehavior.GetNumFailedFollowAttempts() > 0 && - gpGlobals->curtime - pCitizen->m_FollowBehavior.GetTimeFailFollowStarted() > 20 && - ( fabsf(( pCitizen->m_FollowBehavior.GetFollowTarget()->GetAbsOrigin().z - pCitizen->GetAbsOrigin().z )) > 196 || - ( pCitizen->m_FollowBehavior.GetFollowTarget()->GetAbsOrigin().AsVector2D() - pCitizen->GetAbsOrigin().AsVector2D() ).LengthSqr() > Square(50*12) ) ) - { - if ( DebuggingCommanderMode() ) - { - DevMsg( "Player follower is lost (%d, %f, %d)\n", - pCitizen->m_FollowBehavior.GetNumFailedFollowAttempts(), - gpGlobals->curtime - pCitizen->m_FollowBehavior.GetTimeFailFollowStarted(), - (int)((pCitizen->m_FollowBehavior.GetFollowTarget()->GetAbsOrigin().AsVector2D() - pCitizen->GetAbsOrigin().AsVector2D() ).Length()) ); - } - - squadMembersToRemove.AddToTail( pCitizen ); - } - } - - for ( int i = 0; i < squadMembersToRemove.Count(); i++ ) - { - squadMembersToRemove[i]->RemoveFromPlayerSquad(); - } - } - - // Autosquadding - const float JOIN_PLAYER_XY_TOLERANCE_SQ = Square(36*12); - const float UNCONDITIONAL_JOIN_PLAYER_XY_TOLERANCE_SQ = Square(12*12); - const float UNCONDITIONAL_JOIN_PLAYER_Z_TOLERANCE = 5*12; - const float SECOND_TIER_JOIN_DIST_SQ = Square(48*12); - if ( pPlayer && ShouldAutosquad() && !(pPlayer->GetFlags() & FL_NOTARGET ) && pPlayer->IsAlive() ) - { - CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); - CUtlVector candidates; - const Vector &vPlayerPos = pPlayer->GetAbsOrigin(); - bool bFoundNewGuy = false; - int i; - - for ( i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - if ( ppAIs[i]->GetState() == NPC_STATE_DEAD ) - continue; - - if ( ppAIs[i]->GetClassname() != GetClassname() ) - continue; - - CNPC_Citizen *pCitizen = assert_cast(ppAIs[i]); - int iNew; - - if ( pCitizen->IsInPlayerSquad() ) - { - iNew = candidates.AddToTail(); - candidates[iNew].pCitizen = pCitizen; - candidates[iNew].bIsInSquad = true; - candidates[iNew].distSq = 0; - candidates[iNew].iSquadIndex = pCitizen->GetSquad()->GetSquadIndex( pCitizen ); - } - else - { - float distSq = (vPlayerPos.AsVector2D() - pCitizen->GetAbsOrigin().AsVector2D()).LengthSqr(); - if ( distSq > JOIN_PLAYER_XY_TOLERANCE_SQ && - ( pCitizen->m_flTimeJoinedPlayerSquad == 0 || gpGlobals->curtime - pCitizen->m_flTimeJoinedPlayerSquad > 60.0 ) && - ( pCitizen->m_flTimeLastCloseToPlayer == 0 || gpGlobals->curtime - pCitizen->m_flTimeLastCloseToPlayer > 15.0 ) ) - continue; - - if ( !pCitizen->CanJoinPlayerSquad() ) - continue; - - bool bShouldAdd = false; - - if ( pCitizen->HasCondition( COND_SEE_PLAYER ) ) - bShouldAdd = true; - else - { - bool bPlayerVisible = pCitizen->FVisible( pPlayer ); - if ( bPlayerVisible ) - { - if ( pCitizen->HasCondition( COND_HEAR_PLAYER ) ) - bShouldAdd = true; - else if ( distSq < UNCONDITIONAL_JOIN_PLAYER_XY_TOLERANCE_SQ && fabsf(vPlayerPos.z - pCitizen->GetAbsOrigin().z) < UNCONDITIONAL_JOIN_PLAYER_Z_TOLERANCE ) - bShouldAdd = true; - } - } - - if ( bShouldAdd ) - { - // @TODO (toml 05-25-04): probably everyone in a squad should be a candidate if one of them sees the player - AI_Waypoint_t *pPathToPlayer = pCitizen->GetPathfinder()->BuildRoute( pCitizen->GetAbsOrigin(), vPlayerPos, pPlayer, 5*12, NAV_NONE, true ); - GetPathfinder()->UnlockRouteNodes( pPathToPlayer ); - - if ( !pPathToPlayer ) - continue; - - CAI_Path tempPath; - tempPath.SetWaypoints( pPathToPlayer ); // path object will delete waypoints - - iNew = candidates.AddToTail(); - candidates[iNew].pCitizen = pCitizen; - candidates[iNew].bIsInSquad = false; - candidates[iNew].distSq = distSq; - candidates[iNew].iSquadIndex = -1; - - bFoundNewGuy = true; - } - } - } - - if ( bFoundNewGuy ) - { - // Look for second order guys - int initialCount = candidates.Count(); - for ( i = 0; i < initialCount; i++ ) - candidates[i].pCitizen->AddSpawnFlags( SF_CITIZEN_NOT_COMMANDABLE ); // Prevents double-add - for ( i = 0; i < initialCount; i++ ) - { - if ( candidates[i].iSquadIndex == -1 ) - { - for ( int j = 0; j < g_AI_Manager.NumAIs(); j++ ) - { - if ( ppAIs[j]->GetState() == NPC_STATE_DEAD ) - continue; - - if ( ppAIs[j]->GetClassname() != GetClassname() ) - continue; - - if ( ppAIs[j]->HasSpawnFlags( SF_CITIZEN_NOT_COMMANDABLE ) ) - continue; - - CNPC_Citizen *pCitizen = assert_cast(ppAIs[j]); - - float distSq = (vPlayerPos - pCitizen->GetAbsOrigin()).Length2DSqr(); - if ( distSq > JOIN_PLAYER_XY_TOLERANCE_SQ ) - continue; - - distSq = (candidates[i].pCitizen->GetAbsOrigin() - pCitizen->GetAbsOrigin()).Length2DSqr(); - if ( distSq > SECOND_TIER_JOIN_DIST_SQ ) - continue; - - if ( !pCitizen->CanJoinPlayerSquad() ) - continue; - - if ( !pCitizen->FVisible( pPlayer ) ) - continue; - - int iNew = candidates.AddToTail(); - candidates[iNew].pCitizen = pCitizen; - candidates[iNew].bIsInSquad = false; - candidates[iNew].distSq = distSq; - candidates[iNew].iSquadIndex = -1; - pCitizen->AddSpawnFlags( SF_CITIZEN_NOT_COMMANDABLE ); // Prevents double-add - } - } - } - for ( i = 0; i < candidates.Count(); i++ ) - candidates[i].pCitizen->RemoveSpawnFlags( SF_CITIZEN_NOT_COMMANDABLE ); - - if ( candidates.Count() > MAX_PLAYER_SQUAD ) - { - candidates.Sort( PlayerSquadCandidateSortFunc ); - - for ( i = MAX_PLAYER_SQUAD; i < candidates.Count(); i++ ) - { - if ( candidates[i].pCitizen->IsInPlayerSquad() ) - { - candidates[i].pCitizen->RemoveFromPlayerSquad(); - } - } - } - - if ( candidates.Count() ) - { - CNPC_Citizen *pClosest = NULL; - float closestDistSq = FLT_MAX; - int nJoined = 0; - - for ( i = 0; i < candidates.Count() && i < MAX_PLAYER_SQUAD; i++ ) - { - if ( !candidates[i].pCitizen->IsInPlayerSquad() ) - { - candidates[i].pCitizen->AddToPlayerSquad(); - nJoined++; - - if ( candidates[i].distSq < closestDistSq ) - { - pClosest = candidates[i].pCitizen; - closestDistSq = candidates[i].distSq; - } - } - } - - if ( pClosest ) - { - if ( !pClosest->SpokeConcept( TLK_JOINPLAYER ) ) - { - pClosest->SpeakCommandResponse( TLK_JOINPLAYER, CFmtStr( "numjoining:%d", nJoined ) ); - } - else - { - pClosest->SpeakCommandResponse( TLK_STARTFOLLOW ); - } - - for ( i = 0; i < candidates.Count() && i < MAX_PLAYER_SQUAD; i++ ) - { - candidates[i].pCitizen->SetSpokeConcept( TLK_JOINPLAYER, NULL ); - } - } - } - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Citizen::PlayerSquadCandidateSortFunc( const SquadCandidate_t *pLeft, const SquadCandidate_t *pRight ) -{ - // "Bigger" means less approprate - CNPC_Citizen *pLeftCitizen = pLeft->pCitizen; - CNPC_Citizen *pRightCitizen = pRight->pCitizen; - - // Medics are better than anyone - if ( pLeftCitizen->IsMedic() && !pRightCitizen->IsMedic() ) - return -1; - - if ( !pLeftCitizen->IsMedic() && pRightCitizen->IsMedic() ) - return 1; - - CBaseCombatWeapon *pLeftWeapon = pLeftCitizen->GetActiveWeapon(); - CBaseCombatWeapon *pRightWeapon = pRightCitizen->GetActiveWeapon(); - - // People with weapons are better than those without - if ( pLeftWeapon && !pRightWeapon ) - return -1; - - if ( !pLeftWeapon && pRightWeapon ) - return 1; - - // Existing squad members are better than non-members - if ( pLeft->bIsInSquad && !pRight->bIsInSquad ) - return -1; - - if ( !pLeft->bIsInSquad && pRight->bIsInSquad ) - return 1; - - // New squad members are better than older ones - if ( pLeft->bIsInSquad && pRight->bIsInSquad ) - return pRight->iSquadIndex - pLeft->iSquadIndex; - - // Finally, just take the closer - return (int)(pRight->distSq - pLeft->distSq); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::FixupPlayerSquad() -{ - if ( !AI_IsSinglePlayer() ) - return; - - m_flTimeJoinedPlayerSquad = gpGlobals->curtime; - m_bWasInPlayerSquad = true; - if ( m_pSquad->NumMembers() > MAX_PLAYER_SQUAD ) - { - CAI_BaseNPC *pFirstMember = m_pSquad->GetFirstMember(NULL); - m_pSquad->RemoveFromSquad( pFirstMember ); - pFirstMember->ClearCommandGoal(); - - CNPC_Citizen *pFirstMemberCitizen = dynamic_cast< CNPC_Citizen * >( pFirstMember ); - if ( pFirstMemberCitizen ) - { - pFirstMemberCitizen->ClearFollowTarget(); - } - else - { - CAI_FollowBehavior *pOldMemberFollowBehavior; - if ( pFirstMember->GetBehavior( &pOldMemberFollowBehavior ) ) - { - pOldMemberFollowBehavior->SetFollowTarget( NULL ); - } - } - } - - ClearFollowTarget(); - - CAI_BaseNPC *pLeader = NULL; - AISquadIter_t iter; - for ( CAI_BaseNPC *pAllyNpc = m_pSquad->GetFirstMember(&iter); pAllyNpc; pAllyNpc = m_pSquad->GetNextMember(&iter) ) - { - if ( pAllyNpc->IsCommandable() ) - { - pLeader = pAllyNpc; - break; - } - } - - if ( pLeader && pLeader != this ) - { - const Vector &commandGoal = pLeader->GetCommandGoal(); - if ( commandGoal != vec3_invalid ) - { - SetCommandGoal( commandGoal ); - SetCondition( COND_RECEIVED_ORDERS ); - OnMoveOrder(); - } - else - { - CAI_FollowBehavior *pLeaderFollowBehavior; - if ( pLeader->GetBehavior( &pLeaderFollowBehavior ) ) - { - m_FollowBehavior.SetFollowTarget( pLeaderFollowBehavior->GetFollowTarget() ); - m_FollowBehavior.SetParameters( m_FollowBehavior.GetFormation() ); - } - - } - } - else - { - m_FollowBehavior.SetFollowTarget( UTIL_GetLocalPlayer() ); - m_FollowBehavior.SetParameters( AIF_SIMPLE ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::ClearFollowTarget() -{ - m_FollowBehavior.SetFollowTarget( NULL ); - m_FollowBehavior.SetParameters( AIF_SIMPLE ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::UpdateFollowCommandPoint() -{ - if ( !AI_IsSinglePlayer() ) - return; - - if ( IsInPlayerSquad() ) - { - if ( HaveCommandGoal() ) - { - CBaseEntity *pFollowTarget = m_FollowBehavior.GetFollowTarget(); - CBaseEntity *pCommandPoint = gEntList.FindEntityByClassname( NULL, COMMAND_POINT_CLASSNAME ); - - if( !pCommandPoint ) - { - DevMsg("**\nVERY BAD THING\nCommand point vanished! Creating a new one\n**\n"); - pCommandPoint = CreateEntityByName( COMMAND_POINT_CLASSNAME ); - } - - if ( pFollowTarget != pCommandPoint ) - { - pFollowTarget = pCommandPoint; - m_FollowBehavior.SetFollowTarget( pFollowTarget ); - m_FollowBehavior.SetParameters( AIF_COMMANDER ); - } - - if ( ( pCommandPoint->GetAbsOrigin() - GetCommandGoal() ).LengthSqr() > 0.01 ) - { - UTIL_SetOrigin( pCommandPoint, GetCommandGoal(), false ); - } - } - else - { - if ( IsFollowingCommandPoint() ) - ClearFollowTarget(); - if ( m_FollowBehavior.GetFollowTarget() != UTIL_GetLocalPlayer() ) - { - DevMsg( "Expected to be following player, but not\n" ); - m_FollowBehavior.SetFollowTarget( UTIL_GetLocalPlayer() ); - m_FollowBehavior.SetParameters( AIF_SIMPLE ); - } - } - } - else if ( IsFollowingCommandPoint() ) - ClearFollowTarget(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Citizen::IsFollowingCommandPoint() -{ - CBaseEntity *pFollowTarget = m_FollowBehavior.GetFollowTarget(); - if ( pFollowTarget ) - return FClassnameIs( pFollowTarget, COMMAND_POINT_CLASSNAME ); - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -struct SquadMemberInfo_t -{ - CNPC_Citizen * pMember; - bool bSeesPlayer; - float distSq; -}; - -int __cdecl SquadSortFunc( const SquadMemberInfo_t *pLeft, const SquadMemberInfo_t *pRight ) -{ - if ( pLeft->bSeesPlayer && !pRight->bSeesPlayer ) - { - return -1; - } - - if ( !pLeft->bSeesPlayer && pRight->bSeesPlayer ) - { - return 1; - } - - return (int)(pLeft->distSq - pRight->distSq); -} - -CAI_BaseNPC *CNPC_Citizen::GetSquadCommandRepresentative() -{ - if ( !AI_IsSinglePlayer() ) - return NULL; - - if ( IsInPlayerSquad() ) - { - static float lastTime; - static AIHANDLE hCurrent; - - if ( gpGlobals->curtime - lastTime > 2.0 || !hCurrent || !hCurrent->IsInPlayerSquad() ) // hCurrent will be NULL after level change - { - lastTime = gpGlobals->curtime; - hCurrent = NULL; - - CUtlVectorFixed candidates; - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - - if ( pPlayer ) - { - AISquadIter_t iter; - for ( CAI_BaseNPC *pAllyNpc = m_pSquad->GetFirstMember(&iter); pAllyNpc; pAllyNpc = m_pSquad->GetNextMember(&iter) ) - { - if ( pAllyNpc->IsCommandable() && dynamic_cast(pAllyNpc) ) - { - int i = candidates.AddToTail(); - candidates[i].pMember = (CNPC_Citizen *)(pAllyNpc); - candidates[i].bSeesPlayer = pAllyNpc->HasCondition( COND_SEE_PLAYER ); - candidates[i].distSq = ( pAllyNpc->GetAbsOrigin() - pPlayer->GetAbsOrigin() ).LengthSqr(); - } - } - - if ( candidates.Count() > 0 ) - { - candidates.Sort( SquadSortFunc ); - hCurrent = candidates[0].pMember; - } - } - } - - if ( hCurrent != NULL ) - { - Assert( dynamic_cast(hCurrent.Get()) && hCurrent->IsInPlayerSquad() ); - return hCurrent; - } - } - return NULL; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::SetSquad( CAI_Squad *pSquad ) -{ - bool bWasInPlayerSquad = IsInPlayerSquad(); - - BaseClass::SetSquad( pSquad ); - - if( IsInPlayerSquad() && !bWasInPlayerSquad ) - { - m_OnJoinedPlayerSquad.FireOutput(this, this); - if ( npc_citizen_insignia.GetBool() ) - AddInsignia(); - } - else if ( !IsInPlayerSquad() && bWasInPlayerSquad ) - { - if ( npc_citizen_insignia.GetBool() ) - RemoveInsignia(); - m_OnLeftPlayerSquad.FireOutput(this, this); - } -} - -//----------------------------------------------------------------------------- -// Purpose: This is a generic function (to be implemented by sub-classes) to -// handle specific interactions between different types of characters -// (For example the barnacle grabbing an NPC) -// Input : Constant for the type of interaction -// Output : true - if sub-class has a response for the interaction -// false - if sub-class has no response -//----------------------------------------------------------------------------- -bool CNPC_Citizen::HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt) -{ - // TODO: As citizen gets more complex, we will have to only allow - // these interruptions to happen from certain schedules - if (interactionType == g_interactionScannerInspect) - { - if ( gpGlobals->curtime > m_fNextInspectTime ) - { - //SetLookTarget(sourceEnt); - - // Don't let anyone else pick me for a couple seconds - SetNextScannerInspectTime( gpGlobals->curtime + 5.0 ); - return true; - } - return false; - } - else if (interactionType == g_interactionScannerInspectBegin) - { - // Don't inspect me again for a while - SetNextScannerInspectTime( gpGlobals->curtime + CIT_INSPECTED_DELAY_TIME ); - - Vector targetDir = ( sourceEnt->WorldSpaceCenter() - WorldSpaceCenter() ); - VectorNormalize( targetDir ); - - // If we're hit from behind, startle - if ( DotProduct( targetDir, BodyDirection3D() ) < 0 ) - { - m_nInspectActivity = ACT_CIT_STARTLED; - } - else - { - // Otherwise we're blinded by the flash - m_nInspectActivity = ACT_CIT_BLINDED; - } - - SetCondition( COND_CIT_START_INSPECTION ); - return true; - } - else if (interactionType == g_interactionScannerInspectHandsUp) - { - m_nInspectActivity = ACT_CIT_HANDSUP; - SetSchedule(SCHED_CITIZEN_PLAY_INSPECT_ACTIVITY); - return true; - } - else if (interactionType == g_interactionScannerInspectShowArmband) - { - m_nInspectActivity = ACT_CIT_SHOWARMBAND; - SetSchedule(SCHED_CITIZEN_PLAY_INSPECT_ACTIVITY); - return true; - } - else if (interactionType == g_interactionScannerInspectDone) - { - SetSchedule(SCHED_IDLE_WANDER); - return true; - } - else if (interactionType == g_interactionHitByPlayerThrownPhysObj ) - { - if ( IsOkToSpeakInResponseToPlayer() ) - { - Speak( TLK_PLYR_PHYSATK ); - } - return true; - } - - return BaseClass::HandleInteraction( interactionType, data, sourceEnt ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Citizen::FValidateHintType( CAI_Hint *pHint ) -{ - switch( pHint->HintType() ) - { - case HINT_WORLD_VISUALLY_INTERESTING: - return true; - break; - - default: - break; - } - - return BaseClass::FValidateHintType( pHint ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Citizen::CanHeal() -{ - if ( !IsMedic() && !IsAmmoResupplier() ) - return false; - - if( !hl2_episodic.GetBool() ) - { - // If I'm not armed, my priority should be to arm myself. - if ( IsMedic() && !GetActiveWeapon() ) - return false; - } - - if ( IsInAScript() || (m_NPCState == NPC_STATE_SCRIPT) ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Citizen::ShouldHealTarget( CBaseEntity *pTarget, bool bActiveUse ) -{ - Disposition_t disposition; - - if ( !pTarget && ( ( disposition = IRelationType( pTarget ) ) != D_LI && disposition != D_NU ) ) - return false; - - // Don't heal if I'm in the middle of talking - if ( IsSpeaking() ) - return false; - - bool bTargetIsPlayer = pTarget->IsPlayer(); - - // Don't heal or give ammo to targets in vehicles - CBaseCombatCharacter *pCCTarget = pTarget->MyCombatCharacterPointer(); - if ( pCCTarget != NULL && pCCTarget->IsInAVehicle() ) - return false; - - if ( IsMedic() ) - { - Vector toPlayer = ( pTarget->GetAbsOrigin() - GetAbsOrigin() ); - if (( bActiveUse || !HaveCommandGoal() || toPlayer.Length() < HEAL_TARGET_RANGE) -#ifdef HL2_EPISODIC - && fabs(toPlayer.z) < HEAL_TARGET_RANGE_Z -#endif - ) - { - if ( pTarget->m_iHealth > 0 ) - { - if ( bActiveUse ) - { - // Ignore heal requests if we're going to heal a tiny amount - float timeFullHeal = m_flPlayerHealTime; - float timeRecharge = sk_citizen_heal_player_delay.GetFloat(); - float maximumHealAmount = sk_citizen_heal_player.GetFloat(); - float healAmt = ( maximumHealAmount * ( 1.0 - ( timeFullHeal - gpGlobals->curtime ) / timeRecharge ) ); - if ( healAmt > pTarget->m_iMaxHealth - pTarget->m_iHealth ) - healAmt = pTarget->m_iMaxHealth - pTarget->m_iHealth; - if ( healAmt < sk_citizen_heal_player_min_forced.GetFloat() ) - return false; - - return ( pTarget->m_iMaxHealth > pTarget->m_iHealth ); - } - - // Are we ready to heal again? - bool bReadyToHeal = ( ( bTargetIsPlayer && m_flPlayerHealTime <= gpGlobals->curtime ) || - ( !bTargetIsPlayer && m_flAllyHealTime <= gpGlobals->curtime ) ); - - // Only heal if we're ready - if ( bReadyToHeal ) - { - int requiredHealth; - - if ( bTargetIsPlayer ) - requiredHealth = pTarget->GetMaxHealth() - sk_citizen_heal_player.GetInt(); - else - requiredHealth = pTarget->GetMaxHealth() * sk_citizen_heal_player_min_pct.GetInt(); - - if ( ( pTarget->m_iHealth <= requiredHealth ) && IRelationType( pTarget ) == D_LI ) - return true; - } - } - } - } - - // Only players need ammo - if ( IsAmmoResupplier() && bTargetIsPlayer ) - { - if ( m_flPlayerGiveAmmoTime <= gpGlobals->curtime ) - { - int iAmmoType = GetAmmoDef()->Index( STRING(m_iszAmmoSupply) ); - if ( iAmmoType == -1 ) - { - DevMsg("ERROR: Citizen attempting to give unknown ammo type (%s)\n", STRING(m_iszAmmoSupply) ); - } - else - { - // Does the player need the ammo we can give him? - int iMax = GetAmmoDef()->MaxCarry(iAmmoType); - int iCount = ((CBasePlayer*)pTarget)->GetAmmoCount(iAmmoType); - if ( !iCount || ((iMax - iCount) >= m_iAmmoAmount) ) - { - // Only give the player ammo if he has a weapon that uses it - if ( ((CBasePlayer*)pTarget)->Weapon_GetWpnForAmmo( iAmmoType ) ) - return true; - } - } - } - } - return false; -} - -#ifdef HL2_EPISODIC -//----------------------------------------------------------------------------- -// Determine if the citizen is in a position to be throwing medkits -//----------------------------------------------------------------------------- -bool CNPC_Citizen::ShouldHealTossTarget( CBaseEntity *pTarget, bool bActiveUse ) -{ - Disposition_t disposition; - - Assert( IsMedic() ); - if ( !IsMedic() ) - return false; - - if ( !pTarget && ( ( disposition = IRelationType( pTarget ) ) != D_LI && disposition != D_NU ) ) - return false; - - // Don't heal if I'm in the middle of talking - if ( IsSpeaking() ) - return false; - - bool bTargetIsPlayer = pTarget->IsPlayer(); - - // Don't heal or give ammo to targets in vehicles - CBaseCombatCharacter *pCCTarget = pTarget->MyCombatCharacterPointer(); - if ( pCCTarget != NULL && pCCTarget->IsInAVehicle() ) - return false; - - Vector toPlayer = ( pTarget->GetAbsOrigin() - GetAbsOrigin() ); - if ( bActiveUse || !HaveCommandGoal() || toPlayer.Length() < HEAL_TOSS_TARGET_RANGE ) - { - if ( pTarget->m_iHealth > 0 ) - { - if ( bActiveUse ) - { - // Ignore heal requests if we're going to heal a tiny amount - float timeFullHeal = m_flPlayerHealTime; - float timeRecharge = sk_citizen_heal_player_delay.GetFloat(); - float maximumHealAmount = sk_citizen_heal_player.GetFloat(); - float healAmt = ( maximumHealAmount * ( 1.0 - ( timeFullHeal - gpGlobals->curtime ) / timeRecharge ) ); - if ( healAmt > pTarget->m_iMaxHealth - pTarget->m_iHealth ) - healAmt = pTarget->m_iMaxHealth - pTarget->m_iHealth; - if ( healAmt < sk_citizen_heal_player_min_forced.GetFloat() ) - return false; - - return ( pTarget->m_iMaxHealth > pTarget->m_iHealth ); - } - - // Are we ready to heal again? - bool bReadyToHeal = ( ( bTargetIsPlayer && m_flPlayerHealTime <= gpGlobals->curtime ) || - ( !bTargetIsPlayer && m_flAllyHealTime <= gpGlobals->curtime ) ); - - // Only heal if we're ready - if ( bReadyToHeal ) - { - int requiredHealth; - - if ( bTargetIsPlayer ) - requiredHealth = pTarget->GetMaxHealth() - sk_citizen_heal_player.GetInt(); - else - requiredHealth = pTarget->GetMaxHealth() * sk_citizen_heal_player_min_pct.GetInt(); - - if ( ( pTarget->m_iHealth <= requiredHealth ) && IRelationType( pTarget ) == D_LI ) - return true; - } - } - } - - return false; -} -#endif - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::Heal() -{ - if ( !CanHeal() ) - return; - - CBaseEntity *pTarget = GetTarget(); - - Vector target = pTarget->GetAbsOrigin() - GetAbsOrigin(); - if ( target.Length() > HEAL_TARGET_RANGE * 2 ) - return; - - // Don't heal a player that's staring at you until a few seconds have passed. - m_flTimeNextHealStare = gpGlobals->curtime + sk_citizen_stare_heal_time.GetFloat(); - - if ( IsMedic() ) - { - float timeFullHeal; - float timeRecharge; - float maximumHealAmount; - if ( pTarget->IsPlayer() ) - { - timeFullHeal = m_flPlayerHealTime; - timeRecharge = sk_citizen_heal_player_delay.GetFloat(); - maximumHealAmount = sk_citizen_heal_player.GetFloat(); - m_flPlayerHealTime = gpGlobals->curtime + timeRecharge; - } - else - { - timeFullHeal = m_flAllyHealTime; - timeRecharge = sk_citizen_heal_ally_delay.GetFloat(); - maximumHealAmount = sk_citizen_heal_ally.GetFloat(); - m_flAllyHealTime = gpGlobals->curtime + timeRecharge; - } - - float healAmt = ( maximumHealAmount * ( 1.0 - ( timeFullHeal - gpGlobals->curtime ) / timeRecharge ) ); - - if ( healAmt > maximumHealAmount ) - healAmt = maximumHealAmount; - else - healAmt = RoundFloatToInt( healAmt ); - - if ( healAmt > 0 ) - { - if ( pTarget->IsPlayer() && npc_citizen_medic_emit_sound.GetBool() ) - { - CPASAttenuationFilter filter(pTarget, "HealthKit.Touch" ); - EmitSound( filter, pTarget->entindex(), "HealthKit.Touch" ); - } - - pTarget->TakeHealth( healAmt, DMG_GENERIC ); - pTarget->RemoveAllDecals(); - } - } - - if ( IsAmmoResupplier() ) - { - // Non-players don't use ammo - if ( pTarget->IsPlayer() ) - { - int iAmmoType = GetAmmoDef()->Index( STRING(m_iszAmmoSupply) ); - if ( iAmmoType == -1 ) - { - DevMsg("ERROR: Citizen attempting to give unknown ammo type (%s)\n", STRING(m_iszAmmoSupply) ); - } - else - { - ((CBasePlayer*)pTarget)->GiveAmmo( m_iAmmoAmount, iAmmoType, false ); - } - - m_flPlayerGiveAmmoTime = gpGlobals->curtime + sk_citizen_giveammo_player_delay.GetFloat(); - } - } -} - - - -#if HL2_EPISODIC -//----------------------------------------------------------------------------- -// Like Heal(), but tosses a healthkit in front of the player rather than just juicing him up. -//----------------------------------------------------------------------------- -void CNPC_Citizen::TossHealthKit(CBaseCombatCharacter *pThrowAt, const Vector &offset) -{ - Assert( pThrowAt ); - - Vector forward, right, up; - GetVectors( &forward, &right, &up ); - Vector medKitOriginPoint = WorldSpaceCenter() + ( forward * 20.0f ); - Vector destinationPoint; - // this doesn't work without a moveparent: pThrowAt->ComputeAbsPosition( offset, &destinationPoint ); - VectorTransform( offset, pThrowAt->EntityToWorldTransform(), destinationPoint ); - // flatten out any z change due to player looking up/down - destinationPoint.z = pThrowAt->EyePosition().z; - - Vector tossVelocity; - - if (npc_citizen_medic_throw_style.GetInt() == 0) - { - CTraceFilterSkipTwoEntities tracefilter( this, pThrowAt, COLLISION_GROUP_NONE ); - tossVelocity = VecCheckToss( this, &tracefilter, medKitOriginPoint, destinationPoint, 0.233f, 1.0f, false ); - } - else - { - tossVelocity = VecCheckThrow( this, medKitOriginPoint, destinationPoint, MEDIC_THROW_SPEED, 1.0f ); - - if (vec3_origin == tossVelocity) - { - // if out of range, just throw it as close as I can - tossVelocity = destinationPoint - medKitOriginPoint; - - // rotate upwards against gravity - float len = VectorLength(tossVelocity); - tossVelocity *= (MEDIC_THROW_SPEED / len); - tossVelocity.z += 0.57735026918962576450914878050196 * MEDIC_THROW_SPEED; - } - } - - // create a healthkit and toss it into the world - CBaseEntity *pHealthKit = CreateEntityByName( "item_healthkit" ); - Assert(pHealthKit); - if (pHealthKit) - { - pHealthKit->SetAbsOrigin( medKitOriginPoint ); - pHealthKit->SetOwnerEntity( this ); - // pHealthKit->SetAbsVelocity( tossVelocity ); - DispatchSpawn( pHealthKit ); - - { - IPhysicsObject *pPhysicsObject = pHealthKit->VPhysicsGetObject(); - Assert( pPhysicsObject ); - if ( pPhysicsObject ) - { - unsigned int cointoss = random->RandomInt(0,0xFF); // int bits used for bools - - // some random precession - Vector angDummy(random->RandomFloat(-200,200), random->RandomFloat(-200,200), - cointoss & 0x01 ? random->RandomFloat(200,600) : -1.0f * random->RandomFloat(200,600)); - pPhysicsObject->SetVelocity( &tossVelocity, &angDummy ); - } - } - } - else - { - Warning("Citizen tried to heal but could not spawn item_healthkit!\n"); - } - -} - -//----------------------------------------------------------------------------- -// cause an immediate call to TossHealthKit with some default numbers -//----------------------------------------------------------------------------- -void CNPC_Citizen::InputForceHealthKitToss( inputdata_t &inputdata ) -{ - TossHealthKit( UTIL_GetLocalPlayer(), Vector(48.0f, 0.0f, 0.0f) ); -} - -#endif - - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Citizen::ShouldLookForHealthItem() -{ - // Definitely do not take health if not in the player's squad. - if( !IsInPlayerSquad() ) - return false; - - if( gpGlobals->curtime < m_flNextHealthSearchTime ) - return false; - - // I'm fully healthy. - if( GetHealth() >= GetMaxHealth() ) - return false; - - // Player is hurt, don't steal his health. - if( AI_IsSinglePlayer() && UTIL_GetLocalPlayer()->GetHealth() <= UTIL_GetLocalPlayer()->GetHealth() * 0.75f ) - return false; - - // Wait till you're standing still. - if( IsMoving() ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::InputStartPatrolling( inputdata_t &inputdata ) -{ - m_bShouldPatrol = true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::InputStopPatrolling( inputdata_t &inputdata ) -{ - m_bShouldPatrol = false; -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_Citizen::OnGivenWeapon( CBaseCombatWeapon *pNewWeapon ) -{ - FixupMattWeapon(); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_Citizen::InputSetCommandable( inputdata_t &inputdata ) -{ - RemoveSpawnFlags( SF_CITIZEN_NOT_COMMANDABLE ); - gm_PlayerSquadEvaluateTimer.Force(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_Citizen::InputSetMedicOn( inputdata_t &inputdata ) -{ - AddSpawnFlags( SF_CITIZEN_MEDIC ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_Citizen::InputSetMedicOff( inputdata_t &inputdata ) -{ - RemoveSpawnFlags( SF_CITIZEN_MEDIC ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_Citizen::InputSetAmmoResupplierOn( inputdata_t &inputdata ) -{ - AddSpawnFlags( SF_CITIZEN_AMMORESUPPLIER ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_Citizen::InputSetAmmoResupplierOff( inputdata_t &inputdata ) -{ - RemoveSpawnFlags( SF_CITIZEN_AMMORESUPPLIER ); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_Citizen::InputSpeakIdleResponse( inputdata_t &inputdata ) -{ - SpeakIfAllowed( TLK_ANSWER, NULL, true ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Citizen::DeathSound( const CTakeDamageInfo &info ) -{ - // Sentences don't play on dead NPCs - SentenceStop(); - - EmitSound( "NPC_Citizen.Die" ); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_Citizen::FearSound( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Citizen::UseSemaphore( void ) -{ - // Ignore semaphore if we're told to work outside it - if ( HasSpawnFlags(SF_CITIZEN_IGNORE_SEMAPHORE) ) - return false; - - return BaseClass::UseSemaphore(); -} - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC( npc_citizen, CNPC_Citizen ) - - DECLARE_TASK( TASK_CIT_HEAL ) - DECLARE_TASK( TASK_CIT_RPG_AUGER ) - DECLARE_TASK( TASK_CIT_PLAY_INSPECT_SEQUENCE ) - DECLARE_TASK( TASK_CIT_SIT_ON_TRAIN ) - DECLARE_TASK( TASK_CIT_LEAVE_TRAIN ) - DECLARE_TASK( TASK_CIT_SPEAK_MOURNING ) -#if HL2_EPISODIC - DECLARE_TASK( TASK_CIT_HEAL_TOSS ) -#endif - - DECLARE_ACTIVITY( ACT_CIT_HANDSUP ) - DECLARE_ACTIVITY( ACT_CIT_BLINDED ) - DECLARE_ACTIVITY( ACT_CIT_SHOWARMBAND ) - DECLARE_ACTIVITY( ACT_CIT_HEAL ) - DECLARE_ACTIVITY( ACT_CIT_STARTLED ) - - DECLARE_CONDITION( COND_CIT_PLAYERHEALREQUEST ) - DECLARE_CONDITION( COND_CIT_COMMANDHEAL ) - DECLARE_CONDITION( COND_CIT_START_INSPECTION ) - - //Events - DECLARE_ANIMEVENT( AE_CITIZEN_GET_PACKAGE ) - DECLARE_ANIMEVENT( AE_CITIZEN_HEAL ) - - //========================================================= - // > SCHED_SCI_HEAL - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CITIZEN_HEAL, - - " Tasks" - " TASK_GET_PATH_TO_TARGET 0" - " TASK_MOVE_TO_TARGET_RANGE 50" - " TASK_STOP_MOVING 0" - " TASK_FACE_IDEAL 0" -// " TASK_SAY_HEAL 0" -// " TASK_PLAY_SEQUENCE_FACE_TARGET ACTIVITY:ACT_ARM" - " TASK_CIT_HEAL 0" -// " TASK_PLAY_SEQUENCE_FACE_TARGET ACTIVITY:ACT_DISARM" - " " - " Interrupts" - ) - -#if HL2_EPISODIC - //========================================================= - // > SCHED_CITIZEN_HEAL_TOSS - // this is for the episodic behavior where the citizen hurls the medkit - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CITIZEN_HEAL_TOSS, - - " Tasks" -// " TASK_GET_PATH_TO_TARGET 0" -// " TASK_MOVE_TO_TARGET_RANGE 50" - " TASK_STOP_MOVING 0" - " TASK_FACE_IDEAL 0" -// " TASK_SAY_HEAL 0" -// " TASK_PLAY_SEQUENCE_FACE_TARGET ACTIVITY:ACT_ARM" - " TASK_CIT_HEAL_TOSS 0" -// " TASK_PLAY_SEQUENCE_FACE_TARGET ACTIVITY:ACT_DISARM" - " " - " Interrupts" - ) -#endif - - //========================================================= - // > SCHED_CITIZEN_RANGE_ATTACK1_RPG - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CITIZEN_RANGE_ATTACK1_RPG, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_ANNOUNCE_ATTACK 1" // 1 = primary attack - " TASK_RANGE_ATTACK1 0" - " TASK_CIT_RPG_AUGER 1" - "" - " Interrupts" - ) - - //========================================================= - // > SCHED_CITIZEN_RANGE_ATTACK1_RPG - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CITIZEN_STRIDER_RANGE_ATTACK1_RPG, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_ANNOUNCE_ATTACK 1" // 1 = primary attack - " TASK_WAIT 1" - " TASK_RANGE_ATTACK1 0" - " TASK_CIT_RPG_AUGER 1" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_TAKE_COVER_FROM_ENEMY" - "" - " Interrupts" - ) - - - //========================================================= - // > SCHED_CITIZEN_PATROL - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CITIZEN_PATROL, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_WANDER 901024" // 90 to 1024 units - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_WAIT 3" - " TASK_WAIT_RANDOM 3" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_CITIZEN_PATROL" // keep doing it - "" - " Interrupts" - " COND_ENEMY_DEAD" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_NEW_ENEMY" - ) - - DEFINE_SCHEDULE - ( - SCHED_CITIZEN_MOURN_PLAYER, - - " Tasks" - " TASK_GET_PATH_TO_PLAYER 0" - " TASK_RUN_PATH_WITHIN_DIST 180" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_TARGET_PLAYER 0" - " TASK_FACE_TARGET 0" - " TASK_CIT_SPEAK_MOURNING 0" - " TASK_SUGGEST_STATE STATE:IDLE" - "" - " Interrupts" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_NEW_ENEMY" - ) - - DEFINE_SCHEDULE - ( - SCHED_CITIZEN_PLAY_INSPECT_ACTIVITY, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_CIT_PLAY_INSPECT_SEQUENCE 0" // Play the sequence the scanner requires - " TASK_WAIT 2" - "" - " Interrupts" - " " - ) - - DEFINE_SCHEDULE - ( - SCHED_CITIZEN_SIT_ON_TRAIN, - - " Tasks" - " TASK_CIT_SIT_ON_TRAIN 0" - " TASK_WAIT_RANDOM 1" - " TASK_CIT_LEAVE_TRAIN 0" - "" - " Interrupts" - ) - -AI_END_CUSTOM_NPC() - - - -//================================================================================================================== -// CITIZEN PLAYER-RESPONSE SYSTEM -// -// NOTE: This system is obsolete, and left here for legacy support. -// It has been superseded by the ai_eventresponse system. -// -//================================================================================================================== -CHandle g_pCitizenResponseSystem = NULL; - -CCitizenResponseSystem *GetCitizenResponse() -{ - return g_pCitizenResponseSystem; -} - -const char *CitizenResponseConcepts[MAX_CITIZEN_RESPONSES] = -{ - "TLK_CITIZEN_RESPONSE_SHOT_GUNSHIP", - "TLK_CITIZEN_RESPONSE_KILLED_GUNSHIP", - "TLK_VITALNPC_DIED", -}; - -LINK_ENTITY_TO_CLASS( ai_citizen_response_system, CCitizenResponseSystem ); - -BEGIN_DATADESC( CCitizenResponseSystem ) - DEFINE_ARRAY( m_flResponseAddedTime, FIELD_FLOAT, MAX_CITIZEN_RESPONSES ), - DEFINE_FIELD( m_flNextResponseTime, FIELD_FLOAT ), - - DEFINE_INPUTFUNC( FIELD_VOID, "ResponseVitalNPC", InputResponseVitalNPC ), - - DEFINE_THINKFUNC( ResponseThink ), -END_DATADESC() - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCitizenResponseSystem::Spawn() -{ - if ( g_pCitizenResponseSystem ) - { - Warning("Multiple citizen response systems in level.\n"); - UTIL_Remove( this ); - return; - } - g_pCitizenResponseSystem = this; - - // Invisible, non solid. - AddSolidFlags( FSOLID_NOT_SOLID ); - AddEffects( EF_NODRAW ); - SetThink( &CCitizenResponseSystem::ResponseThink ); - - m_flNextResponseTime = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCitizenResponseSystem::OnRestore() -{ - BaseClass::OnRestore(); - - g_pCitizenResponseSystem = this; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCitizenResponseSystem::AddResponseTrigger( citizenresponses_t iTrigger ) -{ - m_flResponseAddedTime[ iTrigger ] = gpGlobals->curtime; - - SetNextThink( gpGlobals->curtime + 0.1 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCitizenResponseSystem::InputResponseVitalNPC( inputdata_t &inputdata ) -{ - AddResponseTrigger( CR_VITALNPC_DIED ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCitizenResponseSystem::ResponseThink() -{ - bool bStayActive = false; - if ( AI_IsSinglePlayer() ) - { - for ( int i = 0; i < MAX_CITIZEN_RESPONSES; i++ ) - { - if ( m_flResponseAddedTime[i] ) - { - // Should it have expired by now? - if ( (m_flResponseAddedTime[i] + CITIZEN_RESPONSE_GIVEUP_TIME) < gpGlobals->curtime ) - { - m_flResponseAddedTime[i] = 0; - } - else if ( m_flNextResponseTime < gpGlobals->curtime ) - { - // Try and find the nearest citizen to the player - float flNearestDist = (CITIZEN_RESPONSE_DISTANCE * CITIZEN_RESPONSE_DISTANCE); - CBaseEntity *pNearestCitizen = NULL; - CBaseEntity *pCitizen = NULL; - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - while ( (pCitizen = gEntList.FindEntityByClassname( pCitizen, "npc_citizen" ) ) != NULL) - { - float flDistToPlayer = (pPlayer->WorldSpaceCenter() - pCitizen->WorldSpaceCenter()).LengthSqr(); - if ( flDistToPlayer < flNearestDist ) - { - flNearestDist = flDistToPlayer; - pNearestCitizen = pCitizen; - } - } - - // Found one? - if ( pNearestCitizen && ((CNPC_Citizen*)pNearestCitizen)->RespondedTo( CitizenResponseConcepts[i], false, false ) ) - { - m_flResponseAddedTime[i] = 0; - m_flNextResponseTime = gpGlobals->curtime + CITIZEN_RESPONSE_REFIRE_TIME; - - // Don't issue multiple responses - break; - } - } - else - { - bStayActive = true; - } - } - } - } - - // Do we need to keep thinking? - if ( bStayActive ) - { - SetNextThink( gpGlobals->curtime + 0.1 ); - } -} - -void CNPC_Citizen::AddInsignia() -{ - CBaseEntity *pMark = CreateEntityByName( "squadinsignia" ); - pMark->SetOwnerEntity( this ); - pMark->Spawn(); -} - -void CNPC_Citizen::RemoveInsignia() -{ - // This is crap right now. - CBaseEntity *FirstEnt(); - CBaseEntity *pEntity = gEntList.FirstEnt(); - - while( pEntity ) - { - if( pEntity->GetOwnerEntity() == this ) - { - // Is this my insignia? - CSquadInsignia *pInsignia = dynamic_cast(pEntity); - - if( pInsignia ) - { - UTIL_Remove( pInsignia ); - return; - } - } - - pEntity = gEntList.NextEnt( pEntity ); - } -} - -//----------------------------------------------------------------------------- -LINK_ENTITY_TO_CLASS( squadinsignia, CSquadInsignia ); - -void CSquadInsignia::Spawn() -{ - CAI_BaseNPC *pOwner = ( GetOwnerEntity() ) ? GetOwnerEntity()->MyNPCPointer() : NULL; - - if ( pOwner ) - { - int attachment = pOwner->LookupAttachment( "eyes" ); - if ( attachment ) - { - SetAbsAngles( GetOwnerEntity()->GetAbsAngles() ); - SetParent( GetOwnerEntity(), attachment ); - - Vector vecPosition; - vecPosition.Init( -2.5, 0, 3.9 ); - SetLocalOrigin( vecPosition ); - } - } - - SetModel( INSIGNIA_MODEL ); - SetSolid( SOLID_NONE ); -} - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Input : -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CNPC_Citizen::DrawDebugTextOverlays( void ) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - - Q_snprintf(tempstr,sizeof(tempstr),"Expression type: %s", szExpressionTypes[m_ExpressionType]); - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} diff --git a/game/server/hl2/npc_citizen17.h b/game/server/hl2/npc_citizen17.h deleted file mode 100644 index e4f5ef1ac..000000000 --- a/game/server/hl2/npc_citizen17.h +++ /dev/null @@ -1,426 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: The downtrodden citizens of City 17. Timid when unarmed, they will -// rise up against their Combine oppressors when given a weapon. -// -//=============================================================================// - -#ifndef NPC_CITIZEN_H -#define NPC_CITIZEN_H - -#include "npc_playercompanion.h" - -#include "ai_behavior_functank.h" - -struct SquadCandidate_t; - -//----------------------------------------------------------------------------- -// -// CLASS: CNPC_Citizen -// -//----------------------------------------------------------------------------- - -//------------------------------------- -// Spawnflags -//------------------------------------- - -#define SF_CITIZEN_FOLLOW ( 1 << 16 ) //65536 follow the player as soon as I spawn. -#define SF_CITIZEN_MEDIC ( 1 << 17 ) //131072 -#define SF_CITIZEN_RANDOM_HEAD ( 1 << 18 ) //262144 -#define SF_CITIZEN_AMMORESUPPLIER ( 1 << 19 ) //524288 -#define SF_CITIZEN_NOT_COMMANDABLE ( 1 << 20 ) //1048576 -#define SF_CITIZEN_IGNORE_SEMAPHORE ( 1 << 21 ) //2097152 Work outside the speech semaphore system -#define SF_CITIZEN_RANDOM_HEAD_MALE ( 1 << 22 ) //4194304 -#define SF_CITIZEN_RANDOM_HEAD_FEMALE ( 1 << 23 )//8388608 -#define SF_CITIZEN_USE_RENDER_BOUNDS ( 1 << 24 )//16777216 - -//------------------------------------- -// Animation events -//------------------------------------- - -enum CitizenType_t -{ - CT_DEFAULT, - CT_DOWNTRODDEN, - CT_REFUGEE, - CT_REBEL, - CT_UNIQUE -}; - -//----------------------------------------------------------------------------- -// Citizen expression types -//----------------------------------------------------------------------------- -enum CitizenExpressionTypes_t -{ - CIT_EXP_UNASSIGNED, // Defaults to this, selects other in spawn. - - CIT_EXP_SCARED, - CIT_EXP_NORMAL, - CIT_EXP_ANGRY, - - CIT_EXP_LAST_TYPE, -}; - -//------------------------------------- - -class CNPC_Citizen : public CNPC_PlayerCompanion -{ - DECLARE_CLASS( CNPC_Citizen, CNPC_PlayerCompanion ); -public: - CNPC_Citizen() - : m_iHead( -1 ) - { - } - - //--------------------------------- - bool CreateBehaviors(); - void Precache(); - void PrecacheAllOfType( CitizenType_t ); - void Spawn(); - void PostNPCInit(); - virtual void SelectModel(); - void SelectExpressionType(); - void Activate(); - virtual void OnGivenWeapon( CBaseCombatWeapon *pNewWeapon ); - void FixupMattWeapon(); - -#ifdef HL2_EPISODIC - virtual float GetJumpGravity() const { return 1.8f; } -#endif//HL2_EPISODIC - - void OnRestore(); - - //--------------------------------- - string_t GetModelName() const; - - Class_T Classify(); - - bool ShouldAlwaysThink(); - - //--------------------------------- - // Behavior - //--------------------------------- - bool ShouldBehaviorSelectSchedule( CAI_BehaviorBase *pBehavior ); - void GatherConditions(); - void PredictPlayerPush(); - void PrescheduleThink(); - void BuildScheduleTestBits(); - - bool FInViewCone( CBaseEntity *pEntity ); - - int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ); - int SelectSchedule(); - - int SelectSchedulePriorityAction(); - int SelectScheduleHeal(); - int SelectScheduleRetrieveItem(); - int SelectScheduleNonCombat(); - int SelectScheduleManhackCombat(); - int SelectScheduleCombat(); - bool ShouldDeferToFollowBehavior(); - int TranslateSchedule( int scheduleType ); - - bool ShouldAcceptGoal( CAI_BehaviorBase *pBehavior, CAI_GoalEntity *pGoal ); - void OnClearGoal( CAI_BehaviorBase *pBehavior, CAI_GoalEntity *pGoal ); - - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - - Activity NPC_TranslateActivity( Activity eNewActivity ); - void HandleAnimEvent( animevent_t *pEvent ); - void TaskFail( AI_TaskFailureCode_t code ); - - void PickupItem( CBaseEntity *pItem ); - - void SimpleUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - bool IgnorePlayerPushing( void ); - - int DrawDebugTextOverlays( void ); - - virtual const char *SelectRandomExpressionForState( NPC_STATE state ); - - //--------------------------------- - // Combat - //--------------------------------- - bool OnBeginMoveAndShoot(); - void OnEndMoveAndShoot(); - - virtual bool UseAttackSquadSlots() { return false; } - void LocateEnemySound(); - - bool IsManhackMeleeCombatant(); - - Vector GetActualShootPosition( const Vector &shootOrigin ); - void OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ); - - bool ShouldLookForBetterWeapon(); - - - //--------------------------------- - // Damage handling - //--------------------------------- - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - - //--------------------------------- - // Commander mode - //--------------------------------- - bool IsCommandable(); - bool IsPlayerAlly( CBasePlayer *pPlayer = NULL ); - bool CanJoinPlayerSquad(); - bool WasInPlayerSquad(); - bool HaveCommandGoal() const; - bool IsCommandMoving(); - bool ShouldAutoSummon(); - bool IsValidCommandTarget( CBaseEntity *pTarget ); - bool NearCommandGoal(); - bool VeryFarFromCommandGoal(); - bool TargetOrder( CBaseEntity *pTarget, CAI_BaseNPC **Allies, int numAllies ); - void MoveOrder( const Vector &vecDest, CAI_BaseNPC **Allies, int numAllies ); - void OnMoveOrder(); - void CommanderUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - bool ShouldSpeakRadio( CBaseEntity *pListener ); - void OnMoveToCommandGoalFailed(); - void AddToPlayerSquad(); - void RemoveFromPlayerSquad(); - void TogglePlayerSquadState(); - void UpdatePlayerSquad(); - static int __cdecl PlayerSquadCandidateSortFunc( const SquadCandidate_t *, const SquadCandidate_t * ); - void FixupPlayerSquad(); - void ClearFollowTarget(); - void UpdateFollowCommandPoint(); - bool IsFollowingCommandPoint(); - CAI_BaseNPC * GetSquadCommandRepresentative(); - void SetSquad( CAI_Squad *pSquad ); - void AddInsignia(); - void RemoveInsignia(); - bool SpeakCommandResponse( AIConcept_t concept, const char *modifiers = NULL ); - - //--------------------------------- - // Scanner interaction - //--------------------------------- - float GetNextScannerInspectTime() { return m_fNextInspectTime; } - void SetNextScannerInspectTime( float flTime ) { m_fNextInspectTime = flTime; } - bool HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt); - - //--------------------------------- - // Hints - //--------------------------------- - bool FValidateHintType ( CAI_Hint *pHint ); - - //--------------------------------- - // Special abilities - //--------------------------------- - bool IsMedic() { return HasSpawnFlags(SF_CITIZEN_MEDIC); } - bool IsAmmoResupplier() { return HasSpawnFlags(SF_CITIZEN_AMMORESUPPLIER); } - - bool CanHeal(); - bool ShouldHealTarget( CBaseEntity *pTarget, bool bActiveUse = false ); -#if HL2_EPISODIC - bool ShouldHealTossTarget( CBaseEntity *pTarget, bool bActiveUse = false ); -#endif - void Heal(); - - bool ShouldLookForHealthItem(); - -#if HL2_EPISODIC - void TossHealthKit( CBaseCombatCharacter *pThrowAt, const Vector &offset ); // create a healthkit and throw it at someone - void InputForceHealthKitToss( inputdata_t &inputdata ); -#endif - - //--------------------------------- - // Inputs - //--------------------------------- - void InputRemoveFromPlayerSquad( inputdata_t &inputdata ) { RemoveFromPlayerSquad(); } - void InputStartPatrolling( inputdata_t &inputdata ); - void InputStopPatrolling( inputdata_t &inputdata ); - void InputSetCommandable( inputdata_t &inputdata ); - void InputSetMedicOn( inputdata_t &inputdata ); - void InputSetMedicOff( inputdata_t &inputdata ); - void InputSetAmmoResupplierOn( inputdata_t &inputdata ); - void InputSetAmmoResupplierOff( inputdata_t &inputdata ); - void InputSpeakIdleResponse( inputdata_t &inputdata ); - - //--------------------------------- - // Sounds & speech - //--------------------------------- - void FearSound( void ); - void DeathSound( const CTakeDamageInfo &info ); - bool UseSemaphore( void ); - - virtual void OnChangeRunningBehavior( CAI_BehaviorBase *pOldBehavior, CAI_BehaviorBase *pNewBehavior ); - -private: - //----------------------------------------------------- - // Conditions, Schedules, Tasks - //----------------------------------------------------- - enum - { - COND_CIT_PLAYERHEALREQUEST = BaseClass::NEXT_CONDITION, - COND_CIT_COMMANDHEAL, - COND_CIT_HURTBYFIRE, - COND_CIT_START_INSPECTION, - - SCHED_CITIZEN_PLAY_INSPECT_ACTIVITY = BaseClass::NEXT_SCHEDULE, - SCHED_CITIZEN_HEAL, - SCHED_CITIZEN_RANGE_ATTACK1_RPG, - SCHED_CITIZEN_PATROL, - SCHED_CITIZEN_MOURN_PLAYER, - SCHED_CITIZEN_SIT_ON_TRAIN, - SCHED_CITIZEN_STRIDER_RANGE_ATTACK1_RPG, -#ifdef HL2_EPISODIC - SCHED_CITIZEN_HEAL_TOSS, -#endif - - TASK_CIT_HEAL = BaseClass::NEXT_TASK, - TASK_CIT_RPG_AUGER, - TASK_CIT_PLAY_INSPECT_SEQUENCE, - TASK_CIT_SIT_ON_TRAIN, - TASK_CIT_LEAVE_TRAIN, - TASK_CIT_SPEAK_MOURNING, -#ifdef HL2_EPISODIC - TASK_CIT_HEAL_TOSS, -#endif - - }; - - //----------------------------------------------------- - - int m_nInspectActivity; - float m_flNextFearSoundTime; - float m_flStopManhackFlinch; - float m_fNextInspectTime; // Next time I'm allowed to get inspected by a scanner - float m_flPlayerHealTime; - float m_flNextHealthSearchTime; // Next time I'm allowed to look for a healthkit - float m_flAllyHealTime; - float m_flPlayerGiveAmmoTime; - string_t m_iszAmmoSupply; - int m_iAmmoAmount; - bool m_bRPGAvoidPlayer; - bool m_bShouldPatrol; - string_t m_iszOriginalSquad; - float m_flTimeJoinedPlayerSquad; - bool m_bWasInPlayerSquad; - float m_flTimeLastCloseToPlayer; - string_t m_iszDenyCommandConcept; - - CSimpleSimTimer m_AutoSummonTimer; - Vector m_vAutoSummonAnchor; - - CitizenType_t m_Type; - CitizenExpressionTypes_t m_ExpressionType; - - int m_iHead; - - static CSimpleSimTimer gm_PlayerSquadEvaluateTimer; - - float m_flTimePlayerStare; // The game time at which the player started staring at me. - float m_flTimeNextHealStare; // Next time I'm allowed to heal a player who is staring at me. - - //----------------------------------------------------- - // Outputs - //----------------------------------------------------- - COutputEvent m_OnJoinedPlayerSquad; - COutputEvent m_OnLeftPlayerSquad; - COutputEvent m_OnFollowOrder; - COutputEvent m_OnStationOrder; - COutputEvent m_OnPlayerUse; - COutputEvent m_OnNavFailBlocked; - - //----------------------------------------------------- - CAI_FuncTankBehavior m_FuncTankBehavior; - - CHandle m_hSavedFollowGoalEnt; - - bool m_bNotifyNavFailBlocked; - bool m_bNeverLeavePlayerSquad; // Don't leave the player squad unless killed, or removed via Entity I/O. - - //----------------------------------------------------- - - DECLARE_DATADESC(); -#ifdef _XBOX -protected: -#endif - DEFINE_CUSTOM_AI; -}; - -//--------------------------------------------------------- -//--------------------------------------------------------- -inline bool CNPC_Citizen::NearCommandGoal() -{ - const float flDistSqr = COMMAND_GOAL_TOLERANCE * COMMAND_GOAL_TOLERANCE; - return ( ( GetAbsOrigin() - GetCommandGoal() ).LengthSqr() <= flDistSqr ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -inline bool CNPC_Citizen::VeryFarFromCommandGoal() -{ - const float flDistSqr = (12*50) * (12*50); - return ( ( GetAbsOrigin() - GetCommandGoal() ).LengthSqr() > flDistSqr ); -} - - - -//============================================================================== -// CITIZEN PLAYER-RESPONSE SYSTEM -// -// NOTE: This system is obsolete, and left here for legacy support. -// It has been superseded by the ai_eventresponse system. -// -//============================================================================== -#define CITIZEN_RESPONSE_DISTANCE 768 // Maximum distance for responding citizens -#define CITIZEN_RESPONSE_REFIRE_TIME 15.0 // Time after giving a response before giving any more -#define CITIZEN_RESPONSE_GIVEUP_TIME 4.0 // Time after a response trigger was fired before discarding it without responding - -enum citizenresponses_t -{ - CR_PLAYER_SHOT_GUNSHIP, // Player has shot the gunship with a bullet weapon - CR_PLAYER_KILLED_GUNSHIP, // Player has destroyed the gunship - CR_VITALNPC_DIED, // Mapmaker specified that an NPC that was vital has died - - // Add new responses here - - MAX_CITIZEN_RESPONSES, -}; - -//------------------------------------- - -class CCitizenResponseSystem : public CBaseEntity -{ - DECLARE_CLASS( CCitizenResponseSystem, CBaseEntity ); -public: - DECLARE_DATADESC(); - - void Spawn(); - void OnRestore(); - - void AddResponseTrigger( citizenresponses_t iTrigger ); - - void ResponseThink(); - - //--------------------------------- - // Inputs - //--------------------------------- - void InputResponseVitalNPC( inputdata_t &inputdata ); - -private: - float m_flResponseAddedTime[ MAX_CITIZEN_RESPONSES ]; // Time at which the response was added. 0 if we have no response. - float m_flNextResponseTime; -}; - -//------------------------------------- - -class CSquadInsignia : public CBaseAnimating -{ - DECLARE_CLASS( CSquadInsignia, CBaseAnimating ); - void Spawn(); -}; - -//------------------------------------- - -CCitizenResponseSystem *GetCitizenResponse(); - -//----------------------------------------------------------------------------- - -#endif //NPC_CITIZEN_H diff --git a/game/server/hl2/npc_combine.cpp b/game/server/hl2/npc_combine.cpp deleted file mode 100644 index f25267c62..000000000 --- a/game/server/hl2/npc_combine.cpp +++ /dev/null @@ -1,4057 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "ai_hull.h" -#include "ai_navigator.h" -#include "ai_motor.h" -#include "ai_squadslot.h" -#include "ai_squad.h" -#include "ai_route.h" -#include "ai_interactions.h" -#include "ai_tacticalservices.h" -#include "soundent.h" -#include "game.h" -#include "npcevent.h" -#include "npc_combine.h" -#include "activitylist.h" -#include "player.h" -#include "basecombatweapon.h" -#include "basegrenade_shared.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "globals.h" -#include "grenade_frag.h" -#include "ndebugoverlay.h" -#include "weapon_physcannon.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" -#include "npc_headcrab.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -int g_fCombineQuestion; // true if an idle grunt asked a question. Cleared when someone answers. YUCK old global from grunt code - -#define COMBINE_SKIN_DEFAULT 0 -#define COMBINE_SKIN_SHOTGUNNER 1 - - -#define COMBINE_GRENADE_THROW_SPEED 650 -#define COMBINE_GRENADE_TIMER 3.5 -#define COMBINE_GRENADE_FLUSH_TIME 3.0 // Don't try to flush an enemy who has been out of sight for longer than this. -#define COMBINE_GRENADE_FLUSH_DIST 256.0 // Don't try to flush an enemy who has moved farther than this distance from the last place I saw him. - -#define COMBINE_LIMP_HEALTH 20 -#define COMBINE_MIN_GRENADE_CLEAR_DIST 250 - -#define COMBINE_EYE_STANDING_POSITION Vector( 0, 0, 66 ) -#define COMBINE_GUN_STANDING_POSITION Vector( 0, 0, 57 ) -#define COMBINE_EYE_CROUCHING_POSITION Vector( 0, 0, 40 ) -#define COMBINE_GUN_CROUCHING_POSITION Vector( 0, 0, 36 ) -#define COMBINE_SHOTGUN_STANDING_POSITION Vector( 0, 0, 36 ) -#define COMBINE_SHOTGUN_CROUCHING_POSITION Vector( 0, 0, 36 ) -#define COMBINE_MIN_CROUCH_DISTANCE 256.0 - -//----------------------------------------------------------------------------- -// Static stuff local to this file. -//----------------------------------------------------------------------------- -// This is the index to the name of the shotgun's classname in the string pool -// so that we can get away with an integer compare rather than a string compare. -string_t s_iszShotgunClassname; - -//----------------------------------------------------------------------------- -// Interactions -//----------------------------------------------------------------------------- -int g_interactionCombineBash = 0; // melee bash attack - -//========================================================= -// Combines's Anim Events Go Here -//========================================================= -#define COMBINE_AE_RELOAD ( 2 ) -#define COMBINE_AE_KICK ( 3 ) -#define COMBINE_AE_AIM ( 4 ) -#define COMBINE_AE_GREN_TOSS ( 7 ) -#define COMBINE_AE_GREN_LAUNCH ( 8 ) -#define COMBINE_AE_GREN_DROP ( 9 ) -#define COMBINE_AE_CAUGHT_ENEMY ( 10) // grunt established sight with an enemy (player only) that had previously eluded the squad. - -int COMBINE_AE_BEGIN_ALTFIRE; -int COMBINE_AE_ALTFIRE; - -//========================================================= -// Combine activities -//========================================================= -//Activity ACT_COMBINE_STANDING_SMG1; -//Activity ACT_COMBINE_CROUCHING_SMG1; -//Activity ACT_COMBINE_STANDING_AR2; -//Activity ACT_COMBINE_CROUCHING_AR2; -//Activity ACT_COMBINE_WALKING_AR2; -//Activity ACT_COMBINE_STANDING_SHOTGUN; -//Activity ACT_COMBINE_CROUCHING_SHOTGUN; -Activity ACT_COMBINE_THROW_GRENADE; -Activity ACT_COMBINE_LAUNCH_GRENADE; -Activity ACT_COMBINE_BUGBAIT; -Activity ACT_COMBINE_AR2_ALTFIRE; -Activity ACT_WALK_EASY; -Activity ACT_WALK_MARCH; - -// ----------------------------------------------- -// > Squad slots -// ----------------------------------------------- -enum SquadSlot_T -{ - SQUAD_SLOT_GRENADE1 = LAST_SHARED_SQUADSLOT, - SQUAD_SLOT_GRENADE2, - SQUAD_SLOT_ATTACK_OCCLUDER, - SQUAD_SLOT_OVERWATCH, -}; - -enum TacticalVariant_T -{ - TACTICAL_VARIANT_DEFAULT = 0, - TACTICAL_VARIANT_PRESSURE_ENEMY, // Always try to close in on the player. - TACTICAL_VARIANT_PRESSURE_ENEMY_UNTIL_CLOSE, // Act like VARIANT_PRESSURE_ENEMY, but go to VARIANT_DEFAULT once within 30 feet -}; - -enum PathfindingVariant_T -{ - PATHFINDING_VARIANT_DEFAULT = 0, -}; - - -#define bits_MEMORY_PAIN_LIGHT_SOUND bits_MEMORY_CUSTOM1 -#define bits_MEMORY_PAIN_HEAVY_SOUND bits_MEMORY_CUSTOM2 -#define bits_MEMORY_PLAYER_HURT bits_MEMORY_CUSTOM3 - -LINK_ENTITY_TO_CLASS( npc_combine, CNPC_Combine ); - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CNPC_Combine ) - -DEFINE_FIELD( m_nKickDamage, FIELD_INTEGER ), -DEFINE_FIELD( m_vecTossVelocity, FIELD_VECTOR ), -DEFINE_FIELD( m_hForcedGrenadeTarget, FIELD_EHANDLE ), -DEFINE_FIELD( m_bShouldPatrol, FIELD_BOOLEAN ), -DEFINE_FIELD( m_bFirstEncounter, FIELD_BOOLEAN ), -DEFINE_FIELD( m_flNextPainSoundTime, FIELD_TIME ), -DEFINE_FIELD( m_flNextAlertSoundTime, FIELD_TIME ), -DEFINE_FIELD( m_flNextGrenadeCheck, FIELD_TIME ), -DEFINE_FIELD( m_flNextLostSoundTime, FIELD_TIME ), -DEFINE_FIELD( m_flAlertPatrolTime, FIELD_TIME ), -DEFINE_FIELD( m_flNextAltFireTime, FIELD_TIME ), -DEFINE_FIELD( m_nShots, FIELD_INTEGER ), -DEFINE_FIELD( m_flShotDelay, FIELD_FLOAT ), -DEFINE_FIELD( m_flStopMoveShootTime, FIELD_TIME ), -DEFINE_KEYFIELD( m_iNumGrenades, FIELD_INTEGER, "NumGrenades" ), -DEFINE_EMBEDDED( m_Sentences ), - -// m_AssaultBehavior (auto saved by AI) -// m_StandoffBehavior (auto saved by AI) -// m_FollowBehavior (auto saved by AI) -// m_FuncTankBehavior (auto saved by AI) -// m_RappelBehavior (auto saved by AI) -// m_ActBusyBehavior (auto saved by AI) - -DEFINE_INPUTFUNC( FIELD_VOID, "LookOff", InputLookOff ), -DEFINE_INPUTFUNC( FIELD_VOID, "LookOn", InputLookOn ), - -DEFINE_INPUTFUNC( FIELD_VOID, "StartPatrolling", InputStartPatrolling ), -DEFINE_INPUTFUNC( FIELD_VOID, "StopPatrolling", InputStopPatrolling ), - -DEFINE_INPUTFUNC( FIELD_STRING, "Assault", InputAssault ), - -DEFINE_INPUTFUNC( FIELD_VOID, "HitByBugbait", InputHitByBugbait ), - -DEFINE_INPUTFUNC( FIELD_STRING, "ThrowGrenadeAtTarget", InputThrowGrenadeAtTarget ), - -DEFINE_FIELD( m_iLastAnimEventHandled, FIELD_INTEGER ), -DEFINE_FIELD( m_fIsElite, FIELD_BOOLEAN ), -DEFINE_FIELD( m_vecAltFireTarget, FIELD_VECTOR ), - -DEFINE_KEYFIELD( m_iTacticalVariant, FIELD_INTEGER, "tacticalvariant" ), -DEFINE_KEYFIELD( m_iPathfindingVariant, FIELD_INTEGER, "pathfindingvariant" ), - -END_DATADESC() - - -//------------------------------------------------------------------------------ -// Constructor. -//------------------------------------------------------------------------------ -CNPC_Combine::CNPC_Combine() -{ - m_vecTossVelocity = vec3_origin; -} - - -//----------------------------------------------------------------------------- -// Create components -//----------------------------------------------------------------------------- -bool CNPC_Combine::CreateComponents() -{ - if ( !BaseClass::CreateComponents() ) - return false; - - m_Sentences.Init( this, "NPC_Combine.SentenceParameters" ); - return true; -} - - -//------------------------------------------------------------------------------ -// Purpose: Don't look, only get info from squad. -//------------------------------------------------------------------------------ -void CNPC_Combine::InputLookOff( inputdata_t &inputdata ) -{ - m_spawnflags |= SF_COMBINE_NO_LOOK; -} - -//------------------------------------------------------------------------------ -// Purpose: Enable looking. -//------------------------------------------------------------------------------ -void CNPC_Combine::InputLookOn( inputdata_t &inputdata ) -{ - m_spawnflags &= ~SF_COMBINE_NO_LOOK; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Combine::InputStartPatrolling( inputdata_t &inputdata ) -{ - m_bShouldPatrol = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Combine::InputStopPatrolling( inputdata_t &inputdata ) -{ - m_bShouldPatrol = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Combine::InputAssault( inputdata_t &inputdata ) -{ - m_AssaultBehavior.SetParameters( AllocPooledString(inputdata.value.String()), CUE_DONT_WAIT, RALLY_POINT_SELECT_DEFAULT ); -} - -//----------------------------------------------------------------------------- -// We were hit by bugbait -//----------------------------------------------------------------------------- -void CNPC_Combine::InputHitByBugbait( inputdata_t &inputdata ) -{ - SetCondition( COND_COMBINE_HIT_BY_BUGBAIT ); -} - -//----------------------------------------------------------------------------- -// Purpose: Force the combine soldier to throw a grenade at the target -// If I'm a combine elite, fire my combine ball at the target instead. -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_Combine::InputThrowGrenadeAtTarget( inputdata_t &inputdata ) -{ - // Ignore if we're inside a scripted sequence - if ( m_NPCState == NPC_STATE_SCRIPT && m_hCine ) - return; - - CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, inputdata.value.String(), NULL, inputdata.pActivator, inputdata.pCaller ); - if ( !pEntity ) - { - DevMsg("%s (%s) received ThrowGrenadeAtTarget input, but couldn't find target entity '%s'\n", GetClassname(), GetDebugName(), inputdata.value.String() ); - return; - } - - m_hForcedGrenadeTarget = pEntity; - m_flNextGrenadeCheck = 0; - - ClearSchedule( "Told to throw grenade via input" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Combine::Precache() -{ - PrecacheModel("models/Weapons/w_grenade.mdl"); - UTIL_PrecacheOther( "npc_handgrenade" ); - - PrecacheScriptSound( "NPC_Combine.GrenadeLaunch" ); - PrecacheScriptSound( "NPC_Combine.WeaponBash" ); - PrecacheScriptSound( "Weapon_CombineGuard.Special1" ); - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Combine::Activate() -{ - s_iszShotgunClassname = FindPooledString( "weapon_shotgun" ); - BaseClass::Activate(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CNPC_Combine::Spawn( void ) -{ - SetHullType(HULL_HUMAN); - SetHullSizeNormal(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - SetBloodColor( BLOOD_COLOR_RED ); - m_flFieldOfView = -0.2;// indicates the width of this NPC's forward view cone ( as a dotproduct result ) - m_NPCState = NPC_STATE_NONE; - m_flNextGrenadeCheck = gpGlobals->curtime + 1; - m_flNextPainSoundTime = 0; - m_flNextAlertSoundTime = 0; - m_bShouldPatrol = false; - - // CapabilitiesAdd( bits_CAP_TURN_HEAD | bits_CAP_MOVE_GROUND | bits_CAP_MOVE_JUMP | bits_CAP_MOVE_CLIMB); - // JAY: Disabled jump for now - hard to compare to HL1 - CapabilitiesAdd( bits_CAP_TURN_HEAD | bits_CAP_MOVE_GROUND ); - - CapabilitiesAdd( bits_CAP_AIM_GUN ); - - // Innate range attack for grenade - // CapabilitiesAdd(bits_CAP_INNATE_RANGE_ATTACK2 ); - - // Innate range attack for kicking - CapabilitiesAdd(bits_CAP_INNATE_MELEE_ATTACK1 ); - - // Can be in a squad - CapabilitiesAdd( bits_CAP_SQUAD); - CapabilitiesAdd( bits_CAP_USE_WEAPONS ); - - CapabilitiesAdd( bits_CAP_DUCK ); // In reloading and cover - - CapabilitiesAdd( bits_CAP_NO_HIT_SQUADMATES ); - - m_bFirstEncounter = true;// this is true when the grunt spawns, because he hasn't encountered an enemy yet. - - m_HackedGunPos = Vector ( 0, 0, 55 ); - - m_flStopMoveShootTime = FLT_MAX; // Move and shoot defaults on. - m_MoveAndShootOverlay.SetInitialDelay( 0.75 ); // But with a bit of a delay. - - m_flNextLostSoundTime = 0; - m_flAlertPatrolTime = 0; - - m_flNextAltFireTime = gpGlobals->curtime; - - NPCInit(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Combine::CreateBehaviors() -{ - AddBehavior( &m_RappelBehavior ); - AddBehavior( &m_ActBusyBehavior ); - AddBehavior( &m_AssaultBehavior ); - AddBehavior( &m_StandoffBehavior ); - AddBehavior( &m_FollowBehavior ); - AddBehavior( &m_FuncTankBehavior ); - - return BaseClass::CreateBehaviors(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Combine::PostNPCInit() -{ - if( IsElite() ) - { - // Give a warning if a Combine Soldier is equipped with anything other than - // an AR2. - if( !GetActiveWeapon() || !FClassnameIs( GetActiveWeapon(), "weapon_ar2" ) ) - { - DevWarning("**Combine Elite Soldier MUST be equipped with AR2\n"); - } - } - - BaseClass::PostNPCInit(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Combine::GatherConditions() -{ - BaseClass::GatherConditions(); - - ClearCondition( COND_COMBINE_ATTACK_SLOT_AVAILABLE ); - - if( GetState() == NPC_STATE_COMBAT ) - { - if( IsCurSchedule( SCHED_COMBINE_WAIT_IN_COVER, false ) ) - { - // Soldiers that are standing around doing nothing poll for attack slots so - // that they can respond quickly when one comes available. If they can - // occupy a vacant attack slot, they do so. This holds the slot until their - // schedule breaks and schedule selection runs again, essentially reserving this - // slot. If they do not select an attack schedule, then they'll release the slot. - if( OccupyStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - { - SetCondition( COND_COMBINE_ATTACK_SLOT_AVAILABLE ); - } - } - - if( IsUsingTacticalVariant(TACTICAL_VARIANT_PRESSURE_ENEMY_UNTIL_CLOSE) ) - { - if( GetEnemy() != NULL && !HasCondition(COND_ENEMY_OCCLUDED) ) - { - // Now we're close to our enemy, stop using the tactical variant. - if( GetAbsOrigin().DistToSqr(GetEnemy()->GetAbsOrigin()) < Square(30.0f * 12.0f) ) - m_iTacticalVariant = TACTICAL_VARIANT_DEFAULT; - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Combine::PrescheduleThink() -{ - BaseClass::PrescheduleThink(); - - // Speak any queued sentences - m_Sentences.UpdateSentenceQueue(); - - if ( IsOnFire() ) - { - SetCondition( COND_COMBINE_ON_FIRE ); - } - else - { - ClearCondition( COND_COMBINE_ON_FIRE ); - } - - extern ConVar ai_debug_shoot_positions; - if ( ai_debug_shoot_positions.GetBool() ) - NDebugOverlay::Cross3D( EyePosition(), 16, 0, 255, 0, false, 0.1 ); - - if( gpGlobals->curtime >= m_flStopMoveShootTime ) - { - // Time to stop move and shoot and start facing the way I'm running. - // This makes the combine look attentive when disengaging, but prevents - // them from always running around facing you. - // - // Only do this if it won't be immediately shut off again. - if( GetNavigator()->GetPathTimeToGoal() > 1.0f ) - { - m_MoveAndShootOverlay.SuspendMoveAndShoot( 5.0f ); - m_flStopMoveShootTime = FLT_MAX; - } - } - - if( m_flGroundSpeed > 0 && GetState() == NPC_STATE_COMBAT && m_MoveAndShootOverlay.IsSuspended() ) - { - // Return to move and shoot when near my goal so that I 'tuck into' the location facing my enemy. - if( GetNavigator()->GetPathTimeToGoal() <= 1.0f ) - { - m_MoveAndShootOverlay.SuspendMoveAndShoot( 0 ); - } - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Combine::DelayAltFireAttack( float flDelay ) -{ - float flNextAltFire = gpGlobals->curtime + flDelay; - - if( flNextAltFire > m_flNextAltFireTime ) - { - // Don't let this delay order preempt a previous request to wait longer. - m_flNextAltFireTime = flNextAltFire; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Combine::DelaySquadAltFireAttack( float flDelay ) -{ - // Make sure to delay my own alt-fire attack. - DelayAltFireAttack( flDelay ); - - AISquadIter_t iter; - CAI_BaseNPC *pSquadmate = m_pSquad ? m_pSquad->GetFirstMember( &iter ) : NULL; - while ( pSquadmate ) - { - CNPC_Combine *pCombine = dynamic_cast(pSquadmate); - - if( pCombine && pCombine->IsElite() ) - { - pCombine->DelayAltFireAttack( flDelay ); - } - - pSquadmate = m_pSquad->GetNextMember( &iter ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: degrees to turn in 0.1 seconds -//----------------------------------------------------------------------------- -float CNPC_Combine::MaxYawSpeed( void ) -{ - switch( GetActivity() ) - { - case ACT_TURN_LEFT: - case ACT_TURN_RIGHT: - return 45; - break; - case ACT_RUN: - case ACT_RUN_HURT: - return 15; - break; - case ACT_WALK: - case ACT_WALK_CROUCH: - return 25; - break; - case ACT_RANGE_ATTACK1: - case ACT_RANGE_ATTACK2: - case ACT_MELEE_ATTACK1: - case ACT_MELEE_ATTACK2: - return 35; - default: - return 35; - break; - } -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -bool CNPC_Combine::ShouldMoveAndShoot() -{ - // Set this timer so that gpGlobals->curtime can't catch up to it. - // Essentially, we're saying that we're not going to interfere with - // what the AI wants to do with move and shoot. - // - // If any code below changes this timer, the code is saying - // "It's OK to move and shoot until gpGlobals->curtime == m_flStopMoveShootTime" - m_flStopMoveShootTime = FLT_MAX; - - if( IsCurSchedule( SCHED_COMBINE_HIDE_AND_RELOAD, false ) ) - m_flStopMoveShootTime = gpGlobals->curtime + random->RandomFloat( 0.4f, 0.6f ); - - if( IsCurSchedule( SCHED_TAKE_COVER_FROM_BEST_SOUND, false ) ) - return false; - - if( IsCurSchedule( SCHED_COMBINE_TAKE_COVER_FROM_BEST_SOUND, false ) ) - return false; - - if( IsCurSchedule( SCHED_COMBINE_RUN_AWAY_FROM_BEST_SOUND, false ) ) - return false; - - if( HasCondition( COND_NO_PRIMARY_AMMO, false ) ) - m_flStopMoveShootTime = gpGlobals->curtime + random->RandomFloat( 0.4f, 0.6f ); - - if( m_pSquad && IsCurSchedule( SCHED_COMBINE_TAKE_COVER1, false ) ) - m_flStopMoveShootTime = gpGlobals->curtime + random->RandomFloat( 0.4f, 0.6f ); - - return BaseClass::ShouldMoveAndShoot(); -} - -//----------------------------------------------------------------------------- -// Purpose: turn in the direction of movement -// Output : -//----------------------------------------------------------------------------- -bool CNPC_Combine::OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval ) -{ - return BaseClass::OverrideMoveFacing( move, flInterval ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -Class_T CNPC_Combine::Classify ( void ) -{ - return CLASS_COMBINE; -} - - -//----------------------------------------------------------------------------- -// Continuous movement tasks -//----------------------------------------------------------------------------- -bool CNPC_Combine::IsCurTaskContinuousMove() -{ - const Task_t* pTask = GetTask(); - if ( pTask && (pTask->iTask == TASK_COMBINE_CHASE_ENEMY_CONTINUOUSLY) ) - return true; - - return BaseClass::IsCurTaskContinuousMove(); -} - - -//----------------------------------------------------------------------------- -// Chase the enemy, updating the target position as the player moves -//----------------------------------------------------------------------------- -void CNPC_Combine::StartTaskChaseEnemyContinuously( const Task_t *pTask ) -{ - CBaseEntity *pEnemy = GetEnemy(); - if ( !pEnemy ) - { - TaskFail( FAIL_NO_ENEMY ); - return; - } - - // We're done once we get close enough - if ( WorldSpaceCenter().DistToSqr( pEnemy->WorldSpaceCenter() ) <= pTask->flTaskData * pTask->flTaskData ) - { - TaskComplete(); - return; - } - - // TASK_GET_PATH_TO_ENEMY - if ( IsUnreachable( pEnemy ) ) - { - TaskFail(FAIL_NO_ROUTE); - return; - } - - if ( !GetNavigator()->SetGoal( GOALTYPE_ENEMY, AIN_NO_PATH_TASK_FAIL ) ) - { - // no way to get there =( - DevWarning( 2, "GetPathToEnemy failed!!\n" ); - RememberUnreachable( pEnemy ); - TaskFail(FAIL_NO_ROUTE); - return; - } - - // NOTE: This is TaskRunPath here. - if ( TranslateActivity( ACT_RUN ) != ACT_INVALID ) - { - GetNavigator()->SetMovementActivity( ACT_RUN ); - } - else - { - GetNavigator()->SetMovementActivity(ACT_WALK); - } - - // Cover is void once I move - Forget( bits_MEMORY_INCOVER ); - - if (GetNavigator()->GetGoalType() == GOALTYPE_NONE) - { - TaskComplete(); - GetNavigator()->ClearGoal(); // Clear residual state - return; - } - - // No shooting delay when in this mode - m_MoveAndShootOverlay.SetInitialDelay( 0.0 ); - - if (!GetNavigator()->IsGoalActive()) - { - SetIdealActivity( GetStoppedActivity() ); - } - else - { - // Check validity of goal type - ValidateNavGoal(); - } - - // set that we're probably going to stop before the goal - GetNavigator()->SetArrivalDistance( pTask->flTaskData ); - m_vSavePosition = GetEnemy()->WorldSpaceCenter(); -} - -void CNPC_Combine::RunTaskChaseEnemyContinuously( const Task_t *pTask ) -{ - if (!GetNavigator()->IsGoalActive()) - { - SetIdealActivity( GetStoppedActivity() ); - } - else - { - // Check validity of goal type - ValidateNavGoal(); - } - - CBaseEntity *pEnemy = GetEnemy(); - if ( !pEnemy ) - { - TaskFail( FAIL_NO_ENEMY ); - return; - } - - // We're done once we get close enough - if ( WorldSpaceCenter().DistToSqr( pEnemy->WorldSpaceCenter() ) <= pTask->flTaskData * pTask->flTaskData ) - { - GetNavigator()->StopMoving(); - TaskComplete(); - return; - } - - // Recompute path if the enemy has moved too much - if ( m_vSavePosition.DistToSqr( pEnemy->WorldSpaceCenter() ) < (pTask->flTaskData * pTask->flTaskData) ) - return; - - if ( IsUnreachable( pEnemy ) ) - { - TaskFail(FAIL_NO_ROUTE); - return; - } - - if ( !GetNavigator()->RefindPathToGoal() ) - { - TaskFail(FAIL_NO_ROUTE); - return; - } - - m_vSavePosition = pEnemy->WorldSpaceCenter(); -} - - -//========================================================= -// start task -//========================================================= -void CNPC_Combine::StartTask( const Task_t *pTask ) -{ - // NOTE: This reset is required because we change it in TASK_COMBINE_CHASE_ENEMY_CONTINUOUSLY - m_MoveAndShootOverlay.SetInitialDelay( 0.75 ); - - switch ( pTask->iTask ) - { - case TASK_COMBINE_SET_STANDING: - { - if ( pTask->flTaskData == 1.0f) - { - Stand(); - } - else - { - Crouch(); - } - TaskComplete(); - } - break; - - case TASK_COMBINE_CHASE_ENEMY_CONTINUOUSLY: - StartTaskChaseEnemyContinuously( pTask ); - break; - - case TASK_COMBINE_PLAY_SEQUENCE_FACE_ALTFIRE_TARGET: - SetIdealActivity( (Activity)(int)pTask->flTaskData ); - GetMotor()->SetIdealYawToTargetAndUpdate( m_vecAltFireTarget, AI_KEEP_YAW_SPEED ); - break; - - case TASK_COMBINE_SIGNAL_BEST_SOUND: - if( IsInSquad() && GetSquad()->NumMembers() > 1 ) - { - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - - if( pPlayer && OccupyStrategySlot( SQUAD_SLOT_EXCLUSIVE_HANDSIGN ) && pPlayer->FInViewCone( this ) ) - { - CSound *pSound; - pSound = GetBestSound(); - - Assert( pSound != NULL ); - - if ( pSound ) - { - Vector right, tosound; - - GetVectors( NULL, &right, NULL ); - - tosound = pSound->GetSoundReactOrigin() - GetAbsOrigin(); - VectorNormalize( tosound); - - tosound.z = 0; - right.z = 0; - - if( DotProduct( right, tosound ) > 0 ) - { - // Right - SetIdealActivity( ACT_SIGNAL_RIGHT ); - } - else - { - // Left - SetIdealActivity( ACT_SIGNAL_LEFT ); - } - - break; - } - } - } - - // Otherwise, just skip it. - TaskComplete(); - break; - - case TASK_ANNOUNCE_ATTACK: - { - // If Primary Attack - if ((int)pTask->flTaskData == 1) - { - // ----------------------------------------------------------- - // If enemy isn't facing me and I haven't attacked in a while - // annouce my attack before I start wailing away - // ----------------------------------------------------------- - CBaseCombatCharacter *pBCC = GetEnemyCombatCharacterPointer(); - - if (pBCC && pBCC->IsPlayer() && (!pBCC->FInViewCone ( this )) && - (gpGlobals->curtime - m_flLastAttackTime > 3.0) ) - { - m_flLastAttackTime = gpGlobals->curtime; - - m_Sentences.Speak( "COMBINE_ANNOUNCE", SENTENCE_PRIORITY_HIGH ); - - // Wait two seconds - SetWait( 2.0 ); - - if ( !IsCrouching() ) - { - SetActivity(ACT_IDLE); - } - else - { - SetActivity(ACT_COWER); // This is really crouch idle - } - } - // ------------------------------------------------------------- - // Otherwise move on - // ------------------------------------------------------------- - else - { - TaskComplete(); - } - } - else - { - m_Sentences.Speak( "COMBINE_THROW_GRENADE", SENTENCE_PRIORITY_MEDIUM ); - SetActivity(ACT_IDLE); - - // Wait two seconds - SetWait( 2.0 ); - } - break; - } - - case TASK_WALK_PATH: - case TASK_RUN_PATH: - // grunt no longer assumes he is covered if he moves - Forget( bits_MEMORY_INCOVER ); - BaseClass::StartTask( pTask ); - break; - - case TASK_COMBINE_FACE_TOSS_DIR: - break; - - case TASK_COMBINE_GET_PATH_TO_FORCED_GREN_LOS: - { - if ( !m_hForcedGrenadeTarget ) - { - TaskFail(FAIL_NO_ENEMY); - return; - } - - float flMaxRange = 2000; - float flMinRange = 0; - - Vector vecEnemy = m_hForcedGrenadeTarget->GetAbsOrigin(); - Vector vecEnemyEye = vecEnemy + m_hForcedGrenadeTarget->GetViewOffset(); - - Vector posLos; - bool found = false; - - if ( GetTacticalServices()->FindLateralLos( vecEnemyEye, &posLos ) ) - { - float dist = ( posLos - vecEnemyEye ).Length(); - if ( dist < flMaxRange && dist > flMinRange ) - found = true; - } - - if ( !found && GetTacticalServices()->FindLos( vecEnemy, vecEnemyEye, flMinRange, flMaxRange, 1.0, &posLos ) ) - { - found = true; - } - - if ( !found ) - { - TaskFail( FAIL_NO_SHOOT ); - } - else - { - // else drop into run task to offer an interrupt - m_vInterruptSavePosition = posLos; - } - } - break; - - case TASK_COMBINE_IGNORE_ATTACKS: - // must be in a squad - if (m_pSquad && m_pSquad->NumMembers() > 2) - { - // the enemy must be far enough away - if (GetEnemy() && (GetEnemy()->WorldSpaceCenter() - WorldSpaceCenter()).Length() > 512.0 ) - { - m_flNextAttack = gpGlobals->curtime + pTask->flTaskData; - } - } - TaskComplete( ); - break; - - case TASK_COMBINE_DEFER_SQUAD_GRENADES: - { - if ( m_pSquad ) - { - // iterate my squad and stop everyone from throwing grenades for a little while. - AISquadIter_t iter; - - CAI_BaseNPC *pSquadmate = m_pSquad ? m_pSquad->GetFirstMember( &iter ) : NULL; - while ( pSquadmate ) - { - CNPC_Combine *pCombine = dynamic_cast(pSquadmate); - - if( pCombine ) - { - pCombine->m_flNextGrenadeCheck = gpGlobals->curtime + 5; - } - - pSquadmate = m_pSquad->GetNextMember( &iter ); - } - } - - TaskComplete(); - break; - } - - case TASK_FACE_IDEAL: - case TASK_FACE_ENEMY: - { - if( pTask->iTask == TASK_FACE_ENEMY && HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - { - TaskComplete(); - return; - } - - BaseClass::StartTask( pTask ); - bool bIsFlying = (GetMoveType() == MOVETYPE_FLY) || (GetMoveType() == MOVETYPE_FLYGRAVITY); - if (bIsFlying) - { - SetIdealActivity( ACT_GLIDE ); - } - - } - break; - - case TASK_FIND_COVER_FROM_ENEMY: - { - if (GetHintGroup() == NULL_STRING) - { - CBaseEntity *pEntity = GetEnemy(); - - // FIXME: this should be generalized by the schedules that are selected, or in the definition of - // what "cover" means (i.e., trace attack vulnerability vs. physical attack vulnerability - if ( pEntity ) - { - // NOTE: This is a good time to check to see if the player is hurt. - // Have the combine notice this and call out - if ( !HasMemory(bits_MEMORY_PLAYER_HURT) && pEntity->IsPlayer() && pEntity->GetHealth() <= 20 ) - { - if ( m_pSquad ) - { - m_pSquad->SquadRemember(bits_MEMORY_PLAYER_HURT); - } - - m_Sentences.Speak( "COMBINE_PLAYERHIT", SENTENCE_PRIORITY_INVALID ); - JustMadeSound( SENTENCE_PRIORITY_HIGH ); - } - if ( pEntity->MyNPCPointer() ) - { - if ( !(pEntity->MyNPCPointer()->CapabilitiesGet( ) & bits_CAP_WEAPON_RANGE_ATTACK1) && - !(pEntity->MyNPCPointer()->CapabilitiesGet( ) & bits_CAP_INNATE_RANGE_ATTACK1) ) - { - TaskComplete(); - return; - } - } - } - } - BaseClass::StartTask( pTask ); - } - break; - case TASK_RANGE_ATTACK1: - { - m_nShots = GetActiveWeapon()->GetRandomBurst(); - m_flShotDelay = GetActiveWeapon()->GetFireRate(); - - m_flNextAttack = gpGlobals->curtime + m_flShotDelay - 0.1; - ResetIdealActivity( ACT_RANGE_ATTACK1 ); - m_flLastAttackTime = gpGlobals->curtime; - } - break; - - case TASK_COMBINE_DIE_INSTANTLY: - { - CTakeDamageInfo info; - - info.SetAttacker( this ); - info.SetInflictor( this ); - info.SetDamage( m_iHealth ); - info.SetDamageType( (int)pTask->flTaskData ); - info.SetDamageForce( Vector( 0.1, 0.1, 0.1 ) ); - - TakeDamage( info ); - - TaskComplete(); - } - break; - - default: - BaseClass:: StartTask( pTask ); - break; - } -} - -//========================================================= -// RunTask -//========================================================= -void CNPC_Combine::RunTask( const Task_t *pTask ) -{ - /* - { - CBaseEntity *pEnemy = GetEnemy(); - if (pEnemy) - { - NDebugOverlay::Line(Center(), pEnemy->Center(), 0,255,255, false, 0.1); - } - - } - */ - - /* - if (m_iMySquadSlot != SQUAD_SLOT_NONE) - { - char text[64]; - Q_snprintf( text, strlen( text ), "%d", m_iMySquadSlot ); - - NDebugOverlay::Text( Center() + Vector( 0, 0, 72 ), text, false, 0.1 ); - } - */ - - switch ( pTask->iTask ) - { - case TASK_COMBINE_CHASE_ENEMY_CONTINUOUSLY: - RunTaskChaseEnemyContinuously( pTask ); - break; - - case TASK_COMBINE_SIGNAL_BEST_SOUND: - AutoMovement( ); - if ( IsActivityFinished() ) - { - TaskComplete(); - } - break; - - case TASK_ANNOUNCE_ATTACK: - { - // Stop waiting if enemy facing me or lost enemy - CBaseCombatCharacter* pBCC = GetEnemyCombatCharacterPointer(); - if (!pBCC || pBCC->FInViewCone( this )) - { - TaskComplete(); - } - - if ( IsWaitFinished() ) - { - TaskComplete(); - } - } - break; - - case TASK_COMBINE_PLAY_SEQUENCE_FACE_ALTFIRE_TARGET: - GetMotor()->SetIdealYawToTargetAndUpdate( m_vecAltFireTarget, AI_KEEP_YAW_SPEED ); - - if ( IsActivityFinished() ) - { - TaskComplete(); - } - break; - - case TASK_COMBINE_FACE_TOSS_DIR: - { - // project a point along the toss vector and turn to face that point. - GetMotor()->SetIdealYawToTargetAndUpdate( GetLocalOrigin() + m_vecTossVelocity * 64, AI_KEEP_YAW_SPEED ); - - if ( FacingIdeal() ) - { - TaskComplete( true ); - } - break; - } - - case TASK_COMBINE_GET_PATH_TO_FORCED_GREN_LOS: - { - if ( !m_hForcedGrenadeTarget ) - { - TaskFail(FAIL_NO_ENEMY); - return; - } - - if ( GetTaskInterrupt() > 0 ) - { - ClearTaskInterrupt(); - - Vector vecEnemy = m_hForcedGrenadeTarget->GetAbsOrigin(); - AI_NavGoal_t goal( m_vInterruptSavePosition, ACT_RUN, AIN_HULL_TOLERANCE ); - - GetNavigator()->SetGoal( goal, AIN_CLEAR_TARGET ); - GetNavigator()->SetArrivalDirection( vecEnemy - goal.dest ); - } - else - { - TaskInterrupt(); - } - } - break; - - case TASK_RANGE_ATTACK1: - { - AutoMovement( ); - - Vector vecEnemyLKP = GetEnemyLKP(); - if (!FInAimCone( vecEnemyLKP )) - { - GetMotor()->SetIdealYawToTargetAndUpdate( vecEnemyLKP, AI_KEEP_YAW_SPEED ); - } - else - { - GetMotor()->SetIdealYawAndUpdate( GetMotor()->GetIdealYaw(), AI_KEEP_YAW_SPEED ); - } - - if ( gpGlobals->curtime >= m_flNextAttack ) - { - if ( IsActivityFinished() ) - { - if (--m_nShots > 0) - { - // DevMsg("ACT_RANGE_ATTACK1\n"); - ResetIdealActivity( ACT_RANGE_ATTACK1 ); - m_flLastAttackTime = gpGlobals->curtime; - m_flNextAttack = gpGlobals->curtime + m_flShotDelay - 0.1; - } - else - { - // DevMsg("TASK_RANGE_ATTACK1 complete\n"); - TaskComplete(); - } - } - } - else - { - // DevMsg("Wait\n"); - } - } - break; - - default: - { - BaseClass::RunTask( pTask ); - break; - } - } -} - -//------------------------------------------------------------------------------ -// Purpose : Override to always shoot at eyes (for ducking behind things) -// Input : -// Output : -//------------------------------------------------------------------------------ -Vector CNPC_Combine::BodyTarget( const Vector &posSrc, bool bNoisy ) -{ - Vector result = BaseClass::BodyTarget( posSrc, bNoisy ); - - // @TODO (toml 02-02-04): this seems wrong. Isn't this already be accounted for - // with the eye position used in the base BodyTarget() - if ( GetFlags() & FL_DUCKING ) - result -= Vector(0,0,24); - - return result; -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -bool CNPC_Combine::FVisible( CBaseEntity *pEntity, int traceMask, CBaseEntity **ppBlocker ) -{ - if( m_spawnflags & SF_COMBINE_NO_LOOK ) - { - // When no look is set, if enemy has eluded the squad, - // he's always invisble to me - if (GetEnemies()->HasEludedMe(pEntity)) - { - return false; - } - } - return BaseClass::FVisible(pEntity, traceMask, ppBlocker); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Combine::Event_Killed( const CTakeDamageInfo &info ) -{ - // if I was killed before I could finish throwing my grenade, drop - // a grenade item that the player can retrieve. - if( GetActivity() == ACT_RANGE_ATTACK2 ) - { - if( m_iLastAnimEventHandled != COMBINE_AE_GREN_TOSS ) - { - // Drop the grenade as an item. - Vector vecStart; - GetAttachment( "lefthand", vecStart ); - - CBaseEntity *pItem = DropItem( "weapon_frag", vecStart, RandomAngle(0,360) ); - - if ( pItem ) - { - IPhysicsObject *pObj = pItem->VPhysicsGetObject(); - - if ( pObj ) - { - Vector vel; - vel.x = random->RandomFloat( -100.0f, 100.0f ); - vel.y = random->RandomFloat( -100.0f, 100.0f ); - vel.z = random->RandomFloat( 800.0f, 1200.0f ); - AngularImpulse angImp = RandomAngularImpulse( -300.0f, 300.0f ); - - vel[2] = 0.0f; - pObj->AddVelocity( &vel, &angImp ); - } - - // In the Citadel we need to dissolve this - if ( PlayerHasMegaPhysCannon() ) - { - CBaseCombatWeapon *pWeapon = static_cast(pItem); - - pWeapon->Dissolve( NULL, gpGlobals->curtime, false, ENTITY_DISSOLVE_NORMAL ); - } - } - } - } - - BaseClass::Event_Killed( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: Override. Don't update if I'm not looking -// Input : -// Output : Returns true is new enemy, false is known enemy -//----------------------------------------------------------------------------- -bool CNPC_Combine::UpdateEnemyMemory( CBaseEntity *pEnemy, const Vector &position, CBaseEntity *pInformer ) -{ - if( m_spawnflags & SF_COMBINE_NO_LOOK ) - { - return false; - } - - return BaseClass::UpdateEnemyMemory( pEnemy, position, pInformer ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Allows for modification of the interrupt mask for the current schedule. -// In the most cases the base implementation should be called first. -//----------------------------------------------------------------------------- -void CNPC_Combine::BuildScheduleTestBits( void ) -{ - BaseClass::BuildScheduleTestBits(); - - if (gpGlobals->curtime < m_flNextAttack) - { - ClearCustomInterruptCondition( COND_CAN_RANGE_ATTACK1 ); - ClearCustomInterruptCondition( COND_CAN_RANGE_ATTACK2 ); - } - - SetCustomInterruptCondition( COND_COMBINE_HIT_BY_BUGBAIT ); - - if ( !IsCurSchedule( SCHED_COMBINE_BURNING_STAND ) ) - { - SetCustomInterruptCondition( COND_COMBINE_ON_FIRE ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Translate base class activities into combot activites -//----------------------------------------------------------------------------- -Activity CNPC_Combine::NPC_TranslateActivity( Activity eNewActivity ) -{ - //Slaming this back to ACT_COMBINE_BUGBAIT since we don't want ANYTHING to change our activity while we burn. - if ( HasCondition( COND_COMBINE_ON_FIRE ) ) - return BaseClass::NPC_TranslateActivity( ACT_COMBINE_BUGBAIT ); - - if (eNewActivity == ACT_RANGE_ATTACK2) - { - // grunt is going to a secondary long range attack. This may be a thrown - // grenade or fired grenade, we must determine which and pick proper sequence - if (Weapon_OwnsThisType( "weapon_grenadelauncher" ) ) - { - return ( Activity )ACT_COMBINE_LAUNCH_GRENADE; - } - else - { - return ( Activity )ACT_COMBINE_THROW_GRENADE; - } - } - else if (eNewActivity == ACT_IDLE) - { - if ( !IsCrouching() && ( m_NPCState == NPC_STATE_COMBAT || m_NPCState == NPC_STATE_ALERT ) ) - { - eNewActivity = ACT_IDLE_ANGRY; - } - } - - if ( m_AssaultBehavior.IsRunning() ) - { - switch ( eNewActivity ) - { - case ACT_IDLE: - eNewActivity = ACT_IDLE_ANGRY; - break; - - case ACT_WALK: - eNewActivity = ACT_WALK_AIM; - break; - - case ACT_RUN: - eNewActivity = ACT_RUN_AIM; - break; - - default: - break; - } - } - - return BaseClass::NPC_TranslateActivity( eNewActivity ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Overidden for human grunts because they hear the DANGER sound -// Input : -// Output : -//----------------------------------------------------------------------------- -int CNPC_Combine::GetSoundInterests( void ) -{ - return SOUND_WORLD | SOUND_COMBAT | SOUND_PLAYER | SOUND_DANGER | SOUND_PHYSICS_DANGER | SOUND_BULLET_IMPACT | SOUND_MOVE_AWAY; -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if this NPC can hear the specified sound -//----------------------------------------------------------------------------- -bool CNPC_Combine::QueryHearSound( CSound *pSound ) -{ - if ( pSound->SoundContext() & SOUND_CONTEXT_COMBINE_ONLY ) - return true; - - if ( pSound->SoundContext() & SOUND_CONTEXT_EXCLUDE_COMBINE ) - return false; - - return BaseClass::QueryHearSound( pSound ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Announce an assault if the enemy can see me and we are pretty -// close to him/her -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_Combine::AnnounceAssault(void) -{ - if (random->RandomInt(0,5) > 1) - return; - - // If enemy can see me make assualt sound - CBaseCombatCharacter* pBCC = GetEnemyCombatCharacterPointer(); - - if (!pBCC) - return; - - if (!FOkToMakeSound()) - return; - - // Make sure we are pretty close - if ( WorldSpaceCenter().DistToSqr( pBCC->WorldSpaceCenter() ) > (2000 * 2000)) - return; - - // Make sure we are in view cone of player - if (!pBCC->FInViewCone ( this )) - return; - - // Make sure player can see me - if ( FVisible( pBCC ) ) - { - m_Sentences.Speak( "COMBINE_ASSAULT" ); - } -} - - -void CNPC_Combine::AnnounceEnemyType( CBaseEntity *pEnemy ) -{ - const char *pSentenceName = "COMBINE_MONST"; - switch ( pEnemy->Classify() ) - { - case CLASS_PLAYER: - pSentenceName = "COMBINE_ALERT"; - break; - - case CLASS_PLAYER_ALLY: - case CLASS_CITIZEN_REBEL: - case CLASS_CITIZEN_PASSIVE: - case CLASS_VORTIGAUNT: - pSentenceName = "COMBINE_MONST_CITIZENS"; - break; - - case CLASS_PLAYER_ALLY_VITAL: - pSentenceName = "COMBINE_MONST_CHARACTER"; - break; - - case CLASS_ANTLION: - pSentenceName = "COMBINE_MONST_BUGS"; - break; - - case CLASS_ZOMBIE: - pSentenceName = "COMBINE_MONST_ZOMBIES"; - break; - - case CLASS_HEADCRAB: - case CLASS_BARNACLE: - pSentenceName = "COMBINE_MONST_PARASITES"; - break; - - default: - break; - } - - m_Sentences.Speak( pSentenceName, SENTENCE_PRIORITY_HIGH ); -} - -void CNPC_Combine::AnnounceEnemyKill( CBaseEntity *pEnemy ) -{ - if (!pEnemy ) - return; - - const char *pSentenceName = "COMBINE_KILL_MONST"; - switch ( pEnemy->Classify() ) - { - case CLASS_PLAYER: - pSentenceName = "COMBINE_PLAYER_DEAD"; - break; - - // no sentences for these guys yet - case CLASS_PLAYER_ALLY: - case CLASS_CITIZEN_REBEL: - case CLASS_CITIZEN_PASSIVE: - case CLASS_VORTIGAUNT: - break; - - case CLASS_PLAYER_ALLY_VITAL: - break; - - case CLASS_ANTLION: - break; - - case CLASS_ZOMBIE: - break; - - case CLASS_HEADCRAB: - case CLASS_BARNACLE: - break; - - default: - break; - } - - m_Sentences.Speak( pSentenceName, SENTENCE_PRIORITY_HIGH ); -} - -//----------------------------------------------------------------------------- -// Select the combat schedule -//----------------------------------------------------------------------------- -int CNPC_Combine::SelectCombatSchedule() -{ - // ----------- - // dead enemy - // ----------- - if ( HasCondition( COND_ENEMY_DEAD ) ) - { - // call base class, all code to handle dead enemies is centralized there. - return SCHED_NONE; - } - - // ----------- - // new enemy - // ----------- - if ( HasCondition( COND_NEW_ENEMY ) ) - { - CBaseEntity *pEnemy = GetEnemy(); - bool bFirstContact = false; - float flTimeSinceFirstSeen = gpGlobals->curtime - GetEnemies()->FirstTimeSeen( pEnemy ); - - if( flTimeSinceFirstSeen < 3.0f ) - bFirstContact = true; - - if ( m_pSquad && pEnemy ) - { - if ( HasCondition( COND_SEE_ENEMY ) ) - { - AnnounceEnemyType( pEnemy ); - } - - if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) && OccupyStrategySlot( SQUAD_SLOT_ATTACK1 ) ) - { - // Start suppressing if someone isn't firing already (SLOT_ATTACK1). This means - // I'm the guy who spotted the enemy, I should react immediately. - return SCHED_COMBINE_SUPPRESS; - } - - if ( m_pSquad->IsLeader( this ) || ( m_pSquad->GetLeader() && m_pSquad->GetLeader()->GetEnemy() != pEnemy ) ) - { - // I'm the leader, but I didn't get the job suppressing the enemy. We know this because - // This code only runs if the code above didn't assign me SCHED_COMBINE_SUPPRESS. - if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) && OccupyStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - { - return SCHED_RANGE_ATTACK1; - } - - if( HasCondition(COND_WEAPON_HAS_LOS) && IsStrategySlotRangeOccupied( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - { - // If everyone else is attacking and I have line of fire, wait for a chance to cover someone. - if( OccupyStrategySlot( SQUAD_SLOT_OVERWATCH ) ) - { - return SCHED_COMBINE_ENTER_OVERWATCH; - } - } - } - else - { - if ( m_pSquad->GetLeader() && FOkToMakeSound( SENTENCE_PRIORITY_MEDIUM ) ) - { - JustMadeSound( SENTENCE_PRIORITY_MEDIUM ); // squelch anything that isn't high priority so the leader can speak - } - - // First contact, and I'm solo, or not the squad leader. - if( HasCondition( COND_SEE_ENEMY ) && CanGrenadeEnemy() ) - { - if( OccupyStrategySlot( SQUAD_SLOT_GRENADE1 ) ) - { - return SCHED_RANGE_ATTACK2; - } - } - - if( !bFirstContact && OccupyStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - { - if( random->RandomInt(0, 100) < 60 ) - { - return SCHED_ESTABLISH_LINE_OF_FIRE; - } - else - { - return SCHED_COMBINE_PRESS_ATTACK; - } - } - - return SCHED_TAKE_COVER_FROM_ENEMY; - } - } - } - - // --------------------- - // no ammo - // --------------------- - if ( ( HasCondition ( COND_NO_PRIMARY_AMMO ) || HasCondition ( COND_LOW_PRIMARY_AMMO ) ) && !HasCondition( COND_CAN_MELEE_ATTACK1) ) - { - return SCHED_HIDE_AND_RELOAD; - } - - // ---------------------- - // LIGHT DAMAGE - // ---------------------- - if ( HasCondition( COND_LIGHT_DAMAGE ) ) - { - if ( GetEnemy() != NULL ) - { - // only try to take cover if we actually have an enemy! - - // FIXME: need to take cover for enemy dealing the damage - - // A standing guy will either crouch or run. - // A crouching guy tries to stay stuck in. - if( !IsCrouching() ) - { - if( GetEnemy() && random->RandomFloat( 0, 100 ) < 50 && CouldShootIfCrouching( GetEnemy() ) ) - { - Crouch(); - } - else - { - //!!!KELLY - this grunt was hit and is going to run to cover. - // m_Sentences.Speak( "COMBINE_COVER" ); - return SCHED_TAKE_COVER_FROM_ENEMY; - } - } - } - else - { - // How am I wounded in combat with no enemy? - Assert( GetEnemy() != NULL ); - } - } - - // If I'm scared of this enemy run away - if ( IRelationType( GetEnemy() ) == D_FR ) - { - if (HasCondition( COND_SEE_ENEMY ) || - HasCondition( COND_SEE_FEAR ) || - HasCondition( COND_LIGHT_DAMAGE ) || - HasCondition( COND_HEAVY_DAMAGE )) - { - FearSound(); - //ClearCommandGoal(); - return SCHED_RUN_FROM_ENEMY; - } - - // If I've seen the enemy recently, cower. Ignore the time for unforgettable enemies. - AI_EnemyInfo_t *pMemory = GetEnemies()->Find( GetEnemy() ); - if ( (pMemory && pMemory->bUnforgettable) || (GetEnemyLastTimeSeen() > (gpGlobals->curtime - 5.0)) ) - { - // If we're facing him, just look ready. Otherwise, face him. - if ( FInAimCone( GetEnemy()->EyePosition() ) ) - return SCHED_COMBAT_STAND; - - return SCHED_FEAR_FACE; - } - } - - int attackSchedule = SelectScheduleAttack(); - if ( attackSchedule != SCHED_NONE ) - return attackSchedule; - - if (HasCondition(COND_ENEMY_OCCLUDED)) - { - // stand up, just in case - Stand(); - DesireStand(); - - if( GetEnemy() && !(GetEnemy()->GetFlags() & FL_NOTARGET) && OccupyStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - { - // Charge in and break the enemy's cover! - return SCHED_ESTABLISH_LINE_OF_FIRE; - } - - // If I'm a long, long way away, establish a LOF anyway. Once I get there I'll - // start respecting the squad slots again. - float flDistSq = GetEnemy()->WorldSpaceCenter().DistToSqr( WorldSpaceCenter() ); - if ( flDistSq > Square(3000) ) - return SCHED_ESTABLISH_LINE_OF_FIRE; - - // Otherwise tuck in. - Remember( bits_MEMORY_INCOVER ); - return SCHED_COMBINE_WAIT_IN_COVER; - } - - // -------------------------------------------------------------- - // Enemy not occluded but isn't open to attack - // -------------------------------------------------------------- - if ( HasCondition( COND_SEE_ENEMY ) && !HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - { - if ( (HasCondition( COND_TOO_FAR_TO_ATTACK ) || IsUsingTacticalVariant(TACTICAL_VARIANT_PRESSURE_ENEMY) ) && OccupyStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 )) - { - return SCHED_COMBINE_PRESS_ATTACK; - } - - AnnounceAssault(); - return SCHED_COMBINE_ASSAULT; - } - - return SCHED_NONE; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int CNPC_Combine::SelectSchedule( void ) -{ - if ( IsWaitingToRappel() && BehaviorSelectSchedule() ) - { - return BaseClass::SelectSchedule(); - } - - if ( HasCondition(COND_COMBINE_ON_FIRE) ) - return SCHED_COMBINE_BURNING_STAND; - - int nSched = SelectFlinchSchedule(); - if ( nSched != SCHED_NONE ) - return nSched; - - if ( m_hForcedGrenadeTarget ) - { - if ( m_flNextGrenadeCheck < gpGlobals->curtime ) - { - Vector vecTarget = m_hForcedGrenadeTarget->WorldSpaceCenter(); - - if ( IsElite() ) - { - if ( FVisible( m_hForcedGrenadeTarget ) ) - { - m_vecAltFireTarget = vecTarget; - m_hForcedGrenadeTarget = NULL; - return SCHED_COMBINE_AR2_ALTFIRE; - } - } - else - { - // If we can, throw a grenade at the target. - // Ignore grenade count / distance / etc - if ( CheckCanThrowGrenade( vecTarget ) ) - { - m_hForcedGrenadeTarget = NULL; - return SCHED_COMBINE_FORCED_GRENADE_THROW; - } - } - } - - // Can't throw at the target, so lets try moving to somewhere where I can see it - if ( !FVisible( m_hForcedGrenadeTarget ) ) - { - return SCHED_COMBINE_MOVE_TO_FORCED_GREN_LOS; - } - } - - if ( m_NPCState != NPC_STATE_SCRIPT) - { - // If we're hit by bugbait, thrash around - if ( HasCondition( COND_COMBINE_HIT_BY_BUGBAIT ) ) - { - // Don't do this if we're mounting a func_tank - if ( m_FuncTankBehavior.IsMounted() == true ) - { - m_FuncTankBehavior.Dismount(); - } - - ClearCondition( COND_COMBINE_HIT_BY_BUGBAIT ); - return SCHED_COMBINE_BUGBAIT_DISTRACTION; - } - - // We've been told to move away from a target to make room for a grenade to be thrown at it - if ( HasCondition( COND_HEAR_MOVE_AWAY ) ) - { - return SCHED_MOVE_AWAY; - } - - // These things are done in any state but dead and prone - if (m_NPCState != NPC_STATE_DEAD && m_NPCState != NPC_STATE_PRONE ) - { - // Cower when physics objects are thrown at me - if ( HasCondition( COND_HEAR_PHYSICS_DANGER ) ) - { - return SCHED_FLINCH_PHYSICS; - } - - // grunts place HIGH priority on running away from danger sounds. - if ( HasCondition(COND_HEAR_DANGER) ) - { - CSound *pSound; - pSound = GetBestSound(); - - Assert( pSound != NULL ); - if ( pSound) - { - if (pSound->m_iType & SOUND_DANGER) - { - // I hear something dangerous, probably need to take cover. - // dangerous sound nearby!, call it out - const char *pSentenceName = "COMBINE_DANGER"; - - CBaseEntity *pSoundOwner = pSound->m_hOwner; - if ( pSoundOwner ) - { - CBaseGrenade *pGrenade = dynamic_cast(pSoundOwner); - if ( pGrenade && pGrenade->GetThrower() ) - { - if ( IRelationType( pGrenade->GetThrower() ) != D_LI ) - { - // special case call out for enemy grenades - pSentenceName = "COMBINE_GREN"; - } - } - } - - m_Sentences.Speak( pSentenceName, SENTENCE_PRIORITY_NORMAL, SENTENCE_CRITERIA_NORMAL ); - - // If the sound is approaching danger, I have no enemy, and I don't see it, turn to face. - if( !GetEnemy() && pSound->IsSoundType(SOUND_CONTEXT_DANGER_APPROACH) && pSound->m_hOwner && !FInViewCone(pSound->GetSoundReactOrigin()) ) - { - GetMotor()->SetIdealYawToTarget( pSound->GetSoundReactOrigin() ); - return SCHED_COMBINE_FACE_IDEAL_YAW; - } - - return SCHED_TAKE_COVER_FROM_BEST_SOUND; - } - - // JAY: This was disabled in HL1. Test? - if (!HasCondition( COND_SEE_ENEMY ) && ( pSound->m_iType & (SOUND_PLAYER | SOUND_COMBAT) )) - { - GetMotor()->SetIdealYawToTarget( pSound->GetSoundReactOrigin() ); - } - } - } - } - - if( BehaviorSelectSchedule() ) - { - return BaseClass::SelectSchedule(); - } - } - - switch ( m_NPCState ) - { - case NPC_STATE_IDLE: - { - if ( m_bShouldPatrol ) - return SCHED_COMBINE_PATROL; - } - // NOTE: Fall through! - - case NPC_STATE_ALERT: - { - if( HasCondition(COND_LIGHT_DAMAGE) || HasCondition(COND_HEAVY_DAMAGE) ) - { - AI_EnemyInfo_t *pDanger = GetEnemies()->GetDangerMemory(); - if( pDanger && FInViewCone(pDanger->vLastKnownLocation) && !BaseClass::FVisible(pDanger->vLastKnownLocation) ) - { - // I've been hurt, I'm facing the danger, but I don't see it, so move from this position. - return SCHED_TAKE_COVER_FROM_ORIGIN; - } - } - - if( HasCondition( COND_HEAR_COMBAT ) ) - { - CSound *pSound = GetBestSound(); - - if( pSound && pSound->IsSoundType( SOUND_COMBAT ) ) - { - if( m_pSquad && m_pSquad->GetSquadMemberNearestTo( pSound->GetSoundReactOrigin() ) == this && OccupyStrategySlot( SQUAD_SLOT_INVESTIGATE_SOUND ) ) - { - return SCHED_INVESTIGATE_SOUND; - } - } - } - - // Don't patrol if I'm in the middle of an assault, because I'll never return to the assault. - if ( !m_AssaultBehavior.HasAssaultCue() ) - { - if( m_bShouldPatrol || HasCondition( COND_COMBINE_SHOULD_PATROL ) ) - return SCHED_COMBINE_PATROL; - } - } - break; - - case NPC_STATE_COMBAT: - { - int nSched = SelectCombatSchedule(); - if ( nSched != SCHED_NONE ) - return nSched; - } - break; - - default: - break; - } - - // no special cases here, call the base class - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Combine::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ) -{ - if( failedSchedule == SCHED_COMBINE_TAKE_COVER1 ) - { - if( IsInSquad() && IsStrategySlotRangeOccupied(SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2) && HasCondition(COND_SEE_ENEMY) ) - { - // This eases the effects of an unfortunate bug that usually plagues shotgunners. Since their rate of fire is low, - // they spend relatively long periods of time without an attack squad slot. If you corner a shotgunner, usually - // the other memebers of the squad will hog all of the attack slots and pick schedules to move to establish line of - // fire. During this time, the shotgunner is prevented from attacking. If he also cannot find cover (the fallback case) - // he will stand around like an idiot, right in front of you. Instead of this, we have him run up to you for a melee attack. - return SCHED_COMBINE_MOVE_TO_MELEE; - } - } - - return BaseClass::SelectFailSchedule( failedSchedule, failedTask, taskFailCode ); -} - -//----------------------------------------------------------------------------- -// Should we charge the player? -//----------------------------------------------------------------------------- -bool CNPC_Combine::ShouldChargePlayer() -{ - return GetEnemy() && GetEnemy()->IsPlayer() && PlayerHasMegaPhysCannon() && !IsLimitingHintGroups(); -} - - -//----------------------------------------------------------------------------- -// Select attack schedules -//----------------------------------------------------------------------------- -#define COMBINE_MEGA_PHYSCANNON_ATTACK_DISTANCE 192 -#define COMBINE_MEGA_PHYSCANNON_ATTACK_DISTANCE_SQ (COMBINE_MEGA_PHYSCANNON_ATTACK_DISTANCE*COMBINE_MEGA_PHYSCANNON_ATTACK_DISTANCE) - -int CNPC_Combine::SelectScheduleAttack() -{ - // Drop a grenade? - if ( HasCondition( COND_COMBINE_DROP_GRENADE ) ) - return SCHED_COMBINE_DROP_GRENADE; - - // Kick attack? - if ( HasCondition( COND_CAN_MELEE_ATTACK1 ) ) - { - return SCHED_MELEE_ATTACK1; - } - - // If I'm fighting a combine turret (it's been hacked to attack me), I can't really - // hurt it with bullets, so become grenade happy. - if ( GetEnemy() && GetEnemy()->Classify() == CLASS_COMBINE && FClassnameIs(GetEnemy(), "npc_turret_floor") ) - { - // Don't do this until I've been fighting the turret for a few seconds - float flTimeAtFirstHand = GetEnemies()->TimeAtFirstHand(GetEnemy()); - if ( flTimeAtFirstHand != AI_INVALID_TIME ) - { - float flTimeEnemySeen = gpGlobals->curtime - flTimeAtFirstHand; - if ( flTimeEnemySeen > 4.0 ) - { - if ( CanGrenadeEnemy() && OccupyStrategySlot( SQUAD_SLOT_GRENADE1 ) ) - return SCHED_RANGE_ATTACK2; - } - } - - // If we're not in the viewcone of the turret, run up and hit it. Do this a bit later to - // give other squadmembers a chance to throw a grenade before I run in. - if ( !GetEnemy()->MyNPCPointer()->FInViewCone( this ) && OccupyStrategySlot( SQUAD_SLOT_GRENADE1 ) ) - return SCHED_COMBINE_CHARGE_TURRET; - } - - // When fighting against the player who's wielding a mega-physcannon, - // always close the distance if possible - // But don't do it if you're in a nav-limited hint group - if ( ShouldChargePlayer() ) - { - float flDistSq = GetEnemy()->WorldSpaceCenter().DistToSqr( WorldSpaceCenter() ); - if ( flDistSq <= COMBINE_MEGA_PHYSCANNON_ATTACK_DISTANCE_SQ ) - { - if( HasCondition(COND_SEE_ENEMY) ) - { - if ( OccupyStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - return SCHED_RANGE_ATTACK1; - } - else - { - if ( OccupyStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - return SCHED_COMBINE_PRESS_ATTACK; - } - } - - if ( HasCondition(COND_SEE_ENEMY) && !IsUnreachable( GetEnemy() ) ) - { - return SCHED_COMBINE_CHARGE_PLAYER; - } - } - - // Can I shoot? - if ( HasCondition(COND_CAN_RANGE_ATTACK1) ) - { - - // JAY: HL1 behavior missing? -#if 0 - if ( m_pSquad ) - { - // if the enemy has eluded the squad and a squad member has just located the enemy - // and the enemy does not see the squad member, issue a call to the squad to waste a - // little time and give the player a chance to turn. - if ( MySquadLeader()->m_fEnemyEluded && !HasConditions ( bits_COND_ENEMY_FACING_ME ) ) - { - MySquadLeader()->m_fEnemyEluded = FALSE; - return SCHED_GRUNT_FOUND_ENEMY; - } - } -#endif - - // Engage if allowed - if ( OccupyStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - { - return SCHED_RANGE_ATTACK1; - } - - // Throw a grenade if not allowed to engage with weapon. - if ( CanGrenadeEnemy() ) - { - if ( OccupyStrategySlot( SQUAD_SLOT_GRENADE1 ) ) - { - return SCHED_RANGE_ATTACK2; - } - } - - DesireCrouch(); - return SCHED_TAKE_COVER_FROM_ENEMY; - } - - if ( GetEnemy() && !HasCondition(COND_SEE_ENEMY) ) - { - // We don't see our enemy. If it hasn't been long since I last saw him, - // and he's pretty close to the last place I saw him, throw a grenade in - // to flush him out. A wee bit of cheating here... - - float flTime; - float flDist; - - flTime = gpGlobals->curtime - GetEnemies()->LastTimeSeen( GetEnemy() ); - flDist = ( GetEnemy()->GetAbsOrigin() - GetEnemies()->LastSeenPosition( GetEnemy() ) ).Length(); - - //Msg("Time: %f Dist: %f\n", flTime, flDist ); - if ( flTime <= COMBINE_GRENADE_FLUSH_TIME && flDist <= COMBINE_GRENADE_FLUSH_DIST && CanGrenadeEnemy( false ) && OccupyStrategySlot( SQUAD_SLOT_GRENADE1 ) ) - { - return SCHED_RANGE_ATTACK2; - } - } - - if (HasCondition(COND_WEAPON_SIGHT_OCCLUDED)) - { - // If they are hiding behind something that we can destroy, start shooting at it. - CBaseEntity *pBlocker = GetEnemyOccluder(); - if ( pBlocker && pBlocker->GetHealth() > 0 && OccupyStrategySlot( SQUAD_SLOT_ATTACK_OCCLUDER ) ) - { - return SCHED_SHOOT_ENEMY_COVER; - } - } - - return SCHED_NONE; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int CNPC_Combine::TranslateSchedule( int scheduleType ) -{ - switch( scheduleType ) - { - case SCHED_TAKE_COVER_FROM_ENEMY: - { - if ( m_pSquad ) - { - // Have to explicitly check innate range attack condition as may have weapon with range attack 2 - if ( g_pGameRules->IsSkillLevel( SKILL_HARD ) && - HasCondition(COND_CAN_RANGE_ATTACK2) && - OccupyStrategySlot( SQUAD_SLOT_GRENADE1 ) ) - { - m_Sentences.Speak( "COMBINE_THROW_GRENADE" ); - return SCHED_COMBINE_TOSS_GRENADE_COVER1; - } - else - { - if ( ShouldChargePlayer() && !IsUnreachable( GetEnemy() ) ) - return SCHED_COMBINE_CHARGE_PLAYER; - - return SCHED_COMBINE_TAKE_COVER1; - } - } - else - { - // Have to explicitly check innate range attack condition as may have weapon with range attack 2 - if ( random->RandomInt(0,1) && HasCondition(COND_CAN_RANGE_ATTACK2) ) - { - return SCHED_COMBINE_GRENADE_COVER1; - } - else - { - if ( ShouldChargePlayer() && !IsUnreachable( GetEnemy() ) ) - return SCHED_COMBINE_CHARGE_PLAYER; - - return SCHED_COMBINE_TAKE_COVER1; - } - } - } - case SCHED_TAKE_COVER_FROM_BEST_SOUND: - { - return SCHED_COMBINE_TAKE_COVER_FROM_BEST_SOUND; - } - break; - case SCHED_COMBINE_TAKECOVER_FAILED: - { - if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) && OccupyStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - { - return TranslateSchedule( SCHED_RANGE_ATTACK1 ); - } - - // Run somewhere randomly - return TranslateSchedule( SCHED_FAIL ); - break; - } - break; - case SCHED_FAIL_ESTABLISH_LINE_OF_FIRE: - { - if( !IsCrouching() ) - { - if( GetEnemy() && CouldShootIfCrouching( GetEnemy() ) ) - { - Crouch(); - return SCHED_COMBAT_FACE; - } - } - - if( HasCondition( COND_SEE_ENEMY ) ) - { - return TranslateSchedule( SCHED_TAKE_COVER_FROM_ENEMY ); - } - else if ( !m_AssaultBehavior.HasAssaultCue() ) - { - // Don't patrol if I'm in the middle of an assault, because - // I'll never return to the assault. - if ( GetEnemy() ) - { - RememberUnreachable( GetEnemy() ); - } - - return TranslateSchedule( SCHED_COMBINE_PATROL ); - } - } - break; - case SCHED_COMBINE_ASSAULT: - { - CBaseEntity *pEntity = GetEnemy(); - - // FIXME: this should be generalized by the schedules that are selected, or in the definition of - // what "cover" means (i.e., trace attack vulnerability vs. physical attack vulnerability - if (pEntity && pEntity->MyNPCPointer()) - { - if ( !(pEntity->MyNPCPointer()->CapabilitiesGet( ) & bits_CAP_WEAPON_RANGE_ATTACK1)) - { - return TranslateSchedule( SCHED_ESTABLISH_LINE_OF_FIRE ); - } - } - // don't charge forward if there's a hint group - if (GetHintGroup() != NULL_STRING) - { - return TranslateSchedule( SCHED_ESTABLISH_LINE_OF_FIRE ); - } - return SCHED_COMBINE_ASSAULT; - } - case SCHED_ESTABLISH_LINE_OF_FIRE: - { - // always assume standing - // Stand(); - - if( CanAltFireEnemy(true) && OccupyStrategySlot(SQUAD_SLOT_SPECIAL_ATTACK) ) - { - // If an elite in the squad could fire a combine ball at the player's last known position, - // do so! - return SCHED_COMBINE_AR2_ALTFIRE; - } - - if( IsUsingTacticalVariant( TACTICAL_VARIANT_PRESSURE_ENEMY ) && !IsRunningBehavior() ) - { - if( OccupyStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - { - return SCHED_COMBINE_PRESS_ATTACK; - } - } - - return SCHED_COMBINE_ESTABLISH_LINE_OF_FIRE; - } - break; - case SCHED_HIDE_AND_RELOAD: - { - // stand up, just in case - // Stand(); - // DesireStand(); - if( CanGrenadeEnemy() && OccupyStrategySlot( SQUAD_SLOT_GRENADE1 ) && random->RandomInt( 0, 100 ) < 20 ) - { - // If I COULD throw a grenade and I need to reload, 20% chance I'll throw a grenade before I hide to reload. - return SCHED_COMBINE_GRENADE_AND_RELOAD; - } - - // No running away in the citadel! - if ( ShouldChargePlayer() ) - return SCHED_RELOAD; - - return SCHED_COMBINE_HIDE_AND_RELOAD; - } - break; - case SCHED_RANGE_ATTACK1: - { - if ( HasCondition( COND_NO_PRIMARY_AMMO ) || HasCondition( COND_LOW_PRIMARY_AMMO ) ) - { - // Ditch the strategy slot for attacking (which we just reserved!) - VacateStrategySlot(); - return TranslateSchedule( SCHED_HIDE_AND_RELOAD ); - } - - if( CanAltFireEnemy(true) && OccupyStrategySlot(SQUAD_SLOT_SPECIAL_ATTACK) ) - { - // Since I'm holding this squadslot, no one else can try right now. If I die before the shot - // goes off, I won't have affected anyone else's ability to use this attack at their nearest - // convenience. - return SCHED_COMBINE_AR2_ALTFIRE; - } - - if ( IsCrouching() || ( CrouchIsDesired() && !HasCondition( COND_HEAVY_DAMAGE ) ) ) - { - // See if we can crouch and shoot - if (GetEnemy() != NULL) - { - float dist = (GetLocalOrigin() - GetEnemy()->GetLocalOrigin()).Length(); - - // only crouch if they are relatively far away - if (dist > COMBINE_MIN_CROUCH_DISTANCE) - { - // try crouching - Crouch(); - - Vector targetPos = GetEnemy()->BodyTarget(GetActiveWeapon()->GetLocalOrigin()); - - // if we can't see it crouched, stand up - if (!WeaponLOSCondition(GetLocalOrigin(),targetPos,false)) - { - Stand(); - } - } - } - } - else - { - // always assume standing - Stand(); - } - - return SCHED_COMBINE_RANGE_ATTACK1; - } - case SCHED_RANGE_ATTACK2: - { - // If my weapon can range attack 2 use the weapon - if (GetActiveWeapon() && GetActiveWeapon()->CapabilitiesGet() & bits_CAP_WEAPON_RANGE_ATTACK2) - { - return SCHED_RANGE_ATTACK2; - } - // Otherwise use innate attack - else - { - return SCHED_COMBINE_RANGE_ATTACK2; - } - } - // SCHED_COMBAT_FACE: - // SCHED_COMBINE_WAIT_FACE_ENEMY: - // SCHED_COMBINE_SWEEP: - // SCHED_COMBINE_COVER_AND_RELOAD: - // SCHED_COMBINE_FOUND_ENEMY: - - case SCHED_VICTORY_DANCE: - { - return SCHED_COMBINE_VICTORY_DANCE; - } - case SCHED_COMBINE_SUPPRESS: - { -#define MIN_SIGNAL_DIST 256 - if ( GetEnemy() != NULL && GetEnemy()->IsPlayer() && m_bFirstEncounter ) - { - float flDistToEnemy = ( GetEnemy()->GetAbsOrigin() - GetAbsOrigin() ).Length(); - - if( flDistToEnemy >= MIN_SIGNAL_DIST ) - { - m_bFirstEncounter = false;// after first encounter, leader won't issue handsigns anymore when he has a new enemy - return SCHED_COMBINE_SIGNAL_SUPPRESS; - } - } - - return SCHED_COMBINE_SUPPRESS; - } - case SCHED_FAIL: - { - if ( GetEnemy() != NULL ) - { - return SCHED_COMBINE_COMBAT_FAIL; - } - return SCHED_FAIL; - } - - case SCHED_COMBINE_PATROL: - { - // If I have an enemy, don't go off into random patrol mode. - if ( GetEnemy() && GetEnemy()->IsAlive() ) - return SCHED_COMBINE_PATROL_ENEMY; - - return SCHED_COMBINE_PATROL; - } - } - - return BaseClass::TranslateSchedule( scheduleType ); -} - -//========================================================= -//========================================================= -void CNPC_Combine::OnStartSchedule( int scheduleType ) -{ -} - -//========================================================= -// HandleAnimEvent - catches the monster-specific messages -// that occur when tagged animation frames are played. -//========================================================= -void CNPC_Combine::HandleAnimEvent( animevent_t *pEvent ) -{ - Vector vecShootDir; - Vector vecShootOrigin; - bool handledEvent = false; - - if (pEvent->type & AE_TYPE_NEWEVENTSYSTEM) - { - if ( pEvent->event == COMBINE_AE_BEGIN_ALTFIRE ) - { - EmitSound( "Weapon_CombineGuard.Special1" ); - handledEvent = true; - } - else if ( pEvent->event == COMBINE_AE_ALTFIRE ) - { - if( IsElite() ) - { - animevent_t fakeEvent; - - fakeEvent.pSource = this; - fakeEvent.event = EVENT_WEAPON_AR2_ALTFIRE; - GetActiveWeapon()->Operator_HandleAnimEvent( &fakeEvent, this ); - - // Stop other squad members from combine balling for a while. - DelaySquadAltFireAttack( 10.0f ); - - // I'm disabling this decrementor. At the time of this change, the elites - // don't bother to check if they have grenades anyway. This means that all - // elites have infinite combine balls, even if the designer marks the elite - // as having 0 grenades. By disabling this decrementor, yet enabling the code - // that makes sure the elite has grenades in order to fire a combine ball, we - // preserve the legacy behavior while making it possible for a designer to prevent - // elites from shooting combine balls by setting grenades to '0' in hammer. (sjb) EP2_OUTLAND_10 - // m_iNumGrenades--; - } - - handledEvent = true; - } - else - { - BaseClass::HandleAnimEvent( pEvent ); - } - } - else - { - switch( pEvent->event ) - { - case COMBINE_AE_AIM: - { - handledEvent = true; - break; - } - case COMBINE_AE_RELOAD: - - // We never actually run out of ammo, just need to refill the clip - if (GetActiveWeapon()) - { - GetActiveWeapon()->WeaponSound( RELOAD_NPC ); - GetActiveWeapon()->m_iClip1 = GetActiveWeapon()->GetMaxClip1(); - GetActiveWeapon()->m_iClip2 = GetActiveWeapon()->GetMaxClip2(); - } - ClearCondition(COND_LOW_PRIMARY_AMMO); - ClearCondition(COND_NO_PRIMARY_AMMO); - ClearCondition(COND_NO_SECONDARY_AMMO); - handledEvent = true; - break; - - case COMBINE_AE_GREN_TOSS: - { - Vector vecSpin; - vecSpin.x = random->RandomFloat( -1000.0, 1000.0 ); - vecSpin.y = random->RandomFloat( -1000.0, 1000.0 ); - vecSpin.z = random->RandomFloat( -1000.0, 1000.0 ); - - Vector vecStart; - GetAttachment( "lefthand", vecStart ); - - if( m_NPCState == NPC_STATE_SCRIPT ) - { - // Use a fixed velocity for grenades thrown in scripted state. - // Grenades thrown from a script do not count against grenades remaining for the AI to use. - Vector forward, up, vecThrow; - - GetVectors( &forward, NULL, &up ); - vecThrow = forward * 750 + up * 175; - Fraggrenade_Create( vecStart, vec3_angle, vecThrow, vecSpin, this, COMBINE_GRENADE_TIMER, true ); - } - else - { - // Use the Velocity that AI gave us. - Fraggrenade_Create( vecStart, vec3_angle, m_vecTossVelocity, vecSpin, this, COMBINE_GRENADE_TIMER, true ); - m_iNumGrenades--; - } - - // wait six seconds before even looking again to see if a grenade can be thrown. - m_flNextGrenadeCheck = gpGlobals->curtime + 6; - } - handledEvent = true; - break; - - case COMBINE_AE_GREN_LAUNCH: - { - EmitSound( "NPC_Combine.GrenadeLaunch" ); - - CBaseEntity *pGrenade = CreateNoSpawn( "npc_contactgrenade", Weapon_ShootPosition(), vec3_angle, this ); - pGrenade->KeyValue( "velocity", m_vecTossVelocity ); - pGrenade->Spawn( ); - - if ( g_pGameRules->IsSkillLevel(SKILL_HARD) ) - m_flNextGrenadeCheck = gpGlobals->curtime + random->RandomFloat( 2, 5 );// wait a random amount of time before shooting again - else - m_flNextGrenadeCheck = gpGlobals->curtime + 6;// wait six seconds before even looking again to see if a grenade can be thrown. - } - handledEvent = true; - break; - - case COMBINE_AE_GREN_DROP: - { - Vector vecStart; - GetAttachment( "lefthand", vecStart ); - - Fraggrenade_Create( vecStart, vec3_angle, m_vecTossVelocity, vec3_origin, this, COMBINE_GRENADE_TIMER, true ); - m_iNumGrenades--; - } - handledEvent = true; - break; - - case COMBINE_AE_KICK: - { - // Does no damage, because damage is applied based upon whether the target can handle the interaction - CBaseEntity *pHurt = CheckTraceHullAttack( 70, -Vector(16,16,18), Vector(16,16,18), 0, DMG_CLUB ); - CBaseCombatCharacter* pBCC = ToBaseCombatCharacter( pHurt ); - if (pBCC) - { - Vector forward, up; - AngleVectors( GetLocalAngles(), &forward, NULL, &up ); - - if ( !pBCC->DispatchInteraction( g_interactionCombineBash, NULL, this ) ) - { - if ( pBCC->IsPlayer() ) - { - pBCC->ViewPunch( QAngle(-12,-7,0) ); - pHurt->ApplyAbsVelocityImpulse( forward * 100 + up * 50 ); - } - - CTakeDamageInfo info( this, this, m_nKickDamage, DMG_CLUB ); - CalculateMeleeDamageForce( &info, forward, pBCC->GetAbsOrigin() ); - pBCC->TakeDamage( info ); - - EmitSound( "NPC_Combine.WeaponBash" ); - } - } - - m_Sentences.Speak( "COMBINE_KICK" ); - handledEvent = true; - break; - } - - case COMBINE_AE_CAUGHT_ENEMY: - m_Sentences.Speak( "COMBINE_ALERT" ); - handledEvent = true; - break; - - default: - BaseClass::HandleAnimEvent( pEvent ); - break; - } - } - - if( handledEvent ) - { - m_iLastAnimEventHandled = pEvent->event; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Get shoot position of BCC at an arbitrary position -// Input : -// Output : -//----------------------------------------------------------------------------- -Vector CNPC_Combine::Weapon_ShootPosition( ) -{ - bool bStanding = !IsCrouching(); - Vector right; - GetVectors( NULL, &right, NULL ); - - if ((CapabilitiesGet() & bits_CAP_DUCK) ) - { - if ( IsCrouchedActivity( GetActivity() ) ) - { - bStanding = false; - } - } - - // FIXME: rename this "estimated" since it's not based on animation - // FIXME: the orientation won't be correct when testing from arbitary positions for arbitary angles - - if ( bStanding ) - { - if( HasShotgun() ) - { - return GetAbsOrigin() + COMBINE_SHOTGUN_STANDING_POSITION + right * 8; - } - else - { - return GetAbsOrigin() + COMBINE_GUN_STANDING_POSITION + right * 8; - } - } - else - { - if( HasShotgun() ) - { - return GetAbsOrigin() + COMBINE_SHOTGUN_CROUCHING_POSITION + right * 8; - } - else - { - return GetAbsOrigin() + COMBINE_GUN_CROUCHING_POSITION + right * 8; - } - } -} - - -//========================================================= -// Speak Sentence - say your cued up sentence. -// -// Some grunt sentences (take cover and charge) rely on actually -// being able to execute the intended action. It's really lame -// when a grunt says 'COVER ME' and then doesn't move. The problem -// is that the sentences were played when the decision to TRY -// to move to cover was made. Now the sentence is played after -// we know for sure that there is a valid path. The schedule -// may still fail but in most cases, well after the grunt has -// started moving. -//========================================================= -void CNPC_Combine::SpeakSentence( int sentenceType ) -{ - switch( sentenceType ) - { - case 0: // assault - AnnounceAssault(); - break; - - case 1: // Flanking the player - // If I'm moving more than 20ft, I need to talk about it - if ( GetNavigator()->GetPath()->GetPathLength() > 20 * 12.0f ) - { - m_Sentences.Speak( "COMBINE_FLANK" ); - } - break; - } -} - -//========================================================= -// PainSound -//========================================================= -void CNPC_Combine::PainSound ( void ) -{ - // NOTE: The response system deals with this at the moment - if ( GetFlags() & FL_DISSOLVING ) - return; - - if ( gpGlobals->curtime > m_flNextPainSoundTime ) - { - const char *pSentenceName = "COMBINE_PAIN"; - float healthRatio = (float)GetHealth() / (float)GetMaxHealth(); - if ( !HasMemory(bits_MEMORY_PAIN_LIGHT_SOUND) && healthRatio > 0.9 ) - { - Remember( bits_MEMORY_PAIN_LIGHT_SOUND ); - pSentenceName = "COMBINE_TAUNT"; - } - else if ( !HasMemory(bits_MEMORY_PAIN_HEAVY_SOUND) && healthRatio < 0.25 ) - { - Remember( bits_MEMORY_PAIN_HEAVY_SOUND ); - pSentenceName = "COMBINE_COVER"; - } - - m_Sentences.Speak( pSentenceName, SENTENCE_PRIORITY_INVALID, SENTENCE_CRITERIA_ALWAYS ); - m_flNextPainSoundTime = gpGlobals->curtime + 1; - } -} - -//----------------------------------------------------------------------------- -// Purpose: implemented by subclasses to give them an opportunity to make -// a sound when they lose their enemy -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_Combine::LostEnemySound( void) -{ - if ( gpGlobals->curtime <= m_flNextLostSoundTime ) - return; - - const char *pSentence; - if (!(CBaseEntity*)GetEnemy() || gpGlobals->curtime - GetEnemyLastTimeSeen() > 10) - { - pSentence = "COMBINE_LOST_LONG"; - } - else - { - pSentence = "COMBINE_LOST_SHORT"; - } - - if ( m_Sentences.Speak( pSentence ) >= 0 ) - { - m_flNextLostSoundTime = gpGlobals->curtime + random->RandomFloat(5.0,15.0); - } -} - -//----------------------------------------------------------------------------- -// Purpose: implemented by subclasses to give them an opportunity to make -// a sound when they lose their enemy -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_Combine::FoundEnemySound( void) -{ - m_Sentences.Speak( "COMBINE_REFIND_ENEMY", SENTENCE_PRIORITY_HIGH ); -} - -//----------------------------------------------------------------------------- -// Purpose: Implemented by subclasses to give them an opportunity to make -// a sound before they attack -// Input : -// Output : -//----------------------------------------------------------------------------- - -// BUGBUG: It looks like this is never played because combine don't do SCHED_WAKE_ANGRY or anything else that does a TASK_SOUND_WAKE -void CNPC_Combine::AlertSound( void) -{ - if ( gpGlobals->curtime > m_flNextAlertSoundTime ) - { - m_Sentences.Speak( "COMBINE_GO_ALERT", SENTENCE_PRIORITY_HIGH ); - m_flNextAlertSoundTime = gpGlobals->curtime + 10.0f; - } -} - -//========================================================= -// NotifyDeadFriend -//========================================================= -void CNPC_Combine::NotifyDeadFriend ( CBaseEntity* pFriend ) -{ - if ( GetSquad()->NumMembers() < 2 ) - { - m_Sentences.Speak( "COMBINE_LAST_OF_SQUAD", SENTENCE_PRIORITY_INVALID, SENTENCE_CRITERIA_NORMAL ); - JustMadeSound(); - return; - } - // relaxed visibility test so that guys say this more often - //if( FInViewCone( pFriend ) && FVisible( pFriend ) ) - { - m_Sentences.Speak( "COMBINE_MAN_DOWN" ); - } - BaseClass::NotifyDeadFriend(pFriend); -} - -//========================================================= -// DeathSound -//========================================================= -void CNPC_Combine::DeathSound ( void ) -{ - // NOTE: The response system deals with this at the moment - if ( GetFlags() & FL_DISSOLVING ) - return; - - m_Sentences.Speak( "COMBINE_DIE", SENTENCE_PRIORITY_INVALID, SENTENCE_CRITERIA_ALWAYS ); -} - -//========================================================= -// IdleSound -//========================================================= -void CNPC_Combine::IdleSound( void ) -{ - if (g_fCombineQuestion || random->RandomInt(0,1)) - { - if (!g_fCombineQuestion) - { - // ask question or make statement - switch (random->RandomInt(0,2)) - { - case 0: // check in - if ( m_Sentences.Speak( "COMBINE_CHECK" ) >= 0 ) - { - g_fCombineQuestion = 1; - } - break; - - case 1: // question - if ( m_Sentences.Speak( "COMBINE_QUEST" ) >= 0 ) - { - g_fCombineQuestion = 2; - } - break; - - case 2: // statement - m_Sentences.Speak( "COMBINE_IDLE" ); - break; - } - } - else - { - switch (g_fCombineQuestion) - { - case 1: // check in - if ( m_Sentences.Speak( "COMBINE_CLEAR" ) >= 0 ) - { - g_fCombineQuestion = 0; - } - break; - case 2: // question - if ( m_Sentences.Speak( "COMBINE_ANSWER" ) >= 0 ) - { - g_fCombineQuestion = 0; - } - break; - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// This is for Grenade attacks. As the test for grenade attacks -// is expensive we don't want to do it every frame. Return true -// if we meet minimum set of requirements and then test for actual -// throw later if we actually decide to do a grenade attack. -// Input : -// Output : -//----------------------------------------------------------------------------- -int CNPC_Combine::RangeAttack2Conditions( float flDot, float flDist ) -{ - return COND_NONE; -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if the combine has grenades, hasn't checked lately, and -// can throw a grenade at the target point. -// Input : &vecTarget - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Combine::CanThrowGrenade( const Vector &vecTarget ) -{ - if( m_iNumGrenades < 1 ) - { - // Out of grenades! - return false; - } - - if (gpGlobals->curtime < m_flNextGrenadeCheck ) - { - // Not allowed to throw another grenade right now. - return false; - } - - float flDist; - flDist = ( vecTarget - GetAbsOrigin() ).Length(); - - if( flDist > 1024 || flDist < 128 ) - { - // Too close or too far! - m_flNextGrenadeCheck = gpGlobals->curtime + 1; // one full second. - return false; - } - - // ----------------------- - // If moving, don't check. - // ----------------------- - if ( m_flGroundSpeed != 0 ) - return false; - -#if 0 - Vector vecEnemyLKP = GetEnemyLKP(); - if ( !( GetEnemy()->GetFlags() & FL_ONGROUND ) && GetEnemy()->GetWaterLevel() == 0 && vecEnemyLKP.z > (GetAbsOrigin().z + WorldAlignMaxs().z) ) - { - //!!!BUGBUG - we should make this check movetype and make sure it isn't FLY? Players who jump a lot are unlikely to - // be grenaded. - // don't throw grenades at anything that isn't on the ground! - return COND_NONE; - } -#endif - - // --------------------------------------------------------------------- - // Are any of my squad members near the intended grenade impact area? - // --------------------------------------------------------------------- - if ( m_pSquad ) - { - if (m_pSquad->SquadMemberInRange( vecTarget, COMBINE_MIN_GRENADE_CLEAR_DIST )) - { - // crap, I might blow my own guy up. Don't throw a grenade and don't check again for a while. - m_flNextGrenadeCheck = gpGlobals->curtime + 1; // one full second. - - // Tell my squad members to clear out so I can get a grenade in - CSoundEnt::InsertSound( SOUND_MOVE_AWAY | SOUND_CONTEXT_COMBINE_ONLY, vecTarget, COMBINE_MIN_GRENADE_CLEAR_DIST, 0.1 ); - return false; - } - } - - return CheckCanThrowGrenade( vecTarget ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true if the combine can throw a grenade at the specified target point -// Input : &vecTarget - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Combine::CheckCanThrowGrenade( const Vector &vecTarget ) -{ - //NDebugOverlay::Line( EyePosition(), vecTarget, 0, 255, 0, false, 5 ); - - // --------------------------------------------------------------------- - // Check that throw is legal and clear - // --------------------------------------------------------------------- - // FIXME: this is only valid for hand grenades, not RPG's - Vector vecToss; - Vector vecMins = -Vector(4,4,4); - Vector vecMaxs = Vector(4,4,4); - if( FInViewCone( vecTarget ) && CBaseEntity::FVisible( vecTarget ) ) - { - vecToss = VecCheckThrow( this, EyePosition(), vecTarget, COMBINE_GRENADE_THROW_SPEED, 1.0, &vecMins, &vecMaxs ); - } - else - { - // Have to try a high toss. Do I have enough room? - trace_t tr; - AI_TraceLine( EyePosition(), EyePosition() + Vector( 0, 0, 64 ), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - if( tr.fraction != 1.0 ) - { - return false; - } - - vecToss = VecCheckToss( this, EyePosition(), vecTarget, -1, 1.0, true, &vecMins, &vecMaxs ); - } - - if ( vecToss != vec3_origin ) - { - m_vecTossVelocity = vecToss; - - // don't check again for a while. - m_flNextGrenadeCheck = gpGlobals->curtime + 1; // 1/3 second. - return true; - } - else - { - // don't check again for a while. - m_flNextGrenadeCheck = gpGlobals->curtime + 1; // one full second. - return false; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Combine::CanAltFireEnemy( bool bUseFreeKnowledge ) -{ - if (!IsElite() ) - return false; - - if (IsCrouching()) - return false; - - if( gpGlobals->curtime < m_flNextAltFireTime ) - return false; - - if( !GetEnemy() ) - return false; - - if (gpGlobals->curtime < m_flNextGrenadeCheck ) - return false; - - // See Steve Bond if you plan on changing this next piece of code!! (SJB) EP2_OUTLAND_10 - if (m_iNumGrenades < 1) - return false; - - CBaseEntity *pEnemy = GetEnemy(); - - if( !pEnemy->IsPlayer() && (!pEnemy->IsNPC() || !pEnemy->MyNPCPointer()->IsPlayerAlly()) ) - return false; - - Vector vecTarget; - - // Determine what point we're shooting at - if( bUseFreeKnowledge ) - { - vecTarget = GetEnemies()->LastKnownPosition( pEnemy ) + (pEnemy->GetViewOffset()*0.75);// approximates the chest - } - else - { - vecTarget = GetEnemies()->LastSeenPosition( pEnemy ) + (pEnemy->GetViewOffset()*0.75);// approximates the chest - } - - // Trace a hull about the size of the combine ball (don't shoot through grates!) - trace_t tr; - - Vector mins( -12, -12, -12 ); - Vector maxs( 12, 12, 12 ); - - Vector vShootPosition = EyePosition(); - - if ( GetActiveWeapon() ) - { - GetActiveWeapon()->GetAttachment( "muzzle", vShootPosition ); - } - - // Trace a hull about the size of the combine ball. - UTIL_TraceHull( vShootPosition, vecTarget, mins, maxs, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - float flLength = (vShootPosition - vecTarget).Length(); - - flLength *= tr.fraction; - - //If the ball can travel at least 65% of the distance to the player then let the NPC shoot it. - if( tr.fraction >= 0.65 && flLength > 128.0f ) - { - // Target is valid - m_vecAltFireTarget = vecTarget; - return true; - } - - - // Check again later - m_vecAltFireTarget = vec3_origin; - m_flNextGrenadeCheck = gpGlobals->curtime + 1.0f; - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Combine::CanGrenadeEnemy( bool bUseFreeKnowledge ) -{ - if( IsElite() ) - return false; - - CBaseEntity *pEnemy = GetEnemy(); - - Assert( pEnemy != NULL ); - - if( pEnemy ) - { - // I'm not allowed to throw grenades during dustoff - if ( IsCurSchedule(SCHED_DROPSHIP_DUSTOFF) ) - return false; - - if( bUseFreeKnowledge ) - { - // throw to where we think they are. - return CanThrowGrenade( GetEnemies()->LastKnownPosition( pEnemy ) ); - } - else - { - // hafta throw to where we last saw them. - return CanThrowGrenade( GetEnemies()->LastSeenPosition( pEnemy ) ); - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: For combine melee attack (kick/hit) -// Input : -// Output : -//----------------------------------------------------------------------------- -int CNPC_Combine::MeleeAttack1Conditions ( float flDot, float flDist ) -{ - if (flDist > 64) - { - return COND_NONE; // COND_TOO_FAR_TO_ATTACK; - } - else if (flDot < 0.7) - { - return COND_NONE; // COND_NOT_FACING_ATTACK; - } - - // Check Z - if ( GetEnemy() && fabs(GetEnemy()->GetAbsOrigin().z - GetAbsOrigin().z) > 64 ) - return COND_NONE; - - if ( dynamic_cast(GetEnemy()) != NULL ) - { - return COND_NONE; - } - - // Make sure not trying to kick through a window or something. - trace_t tr; - Vector vecSrc, vecEnd; - - vecSrc = WorldSpaceCenter(); - vecEnd = GetEnemy()->WorldSpaceCenter(); - - AI_TraceLine(vecSrc, vecEnd, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); - if( tr.m_pEnt != GetEnemy() ) - { - return COND_NONE; - } - - return COND_CAN_MELEE_ATTACK1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Vector -//----------------------------------------------------------------------------- -Vector CNPC_Combine::EyePosition( void ) -{ - if ( !IsCrouching() ) - { - return GetAbsOrigin() + COMBINE_EYE_STANDING_POSITION; - } - else - { - return GetAbsOrigin() + COMBINE_EYE_CROUCHING_POSITION; - } - - /* - Vector m_EyePos; - GetAttachment( "eyes", m_EyePos ); - return m_EyePos; - */ -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Vector CNPC_Combine::GetAltFireTarget() -{ - Assert( IsElite() ); - - return m_vecAltFireTarget; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : nActivity - -// Output : Vector -//----------------------------------------------------------------------------- -Vector CNPC_Combine::EyeOffset( Activity nActivity ) -{ - if (CapabilitiesGet() & bits_CAP_DUCK) - { - if ( IsCrouchedActivity( nActivity ) ) - return COMBINE_EYE_CROUCHING_POSITION; - - } - // if the hint doesn't tell anything, assume current state - if ( !IsCrouching() ) - { - return COMBINE_EYE_STANDING_POSITION; - } - else - { - return COMBINE_EYE_CROUCHING_POSITION; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Vector CNPC_Combine::GetCrouchEyeOffset( void ) -{ - return COMBINE_EYE_CROUCHING_POSITION; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Combine::SetActivity( Activity NewActivity ) -{ - BaseClass::SetActivity( NewActivity ); - - m_iLastAnimEventHandled = -1; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -NPC_STATE CNPC_Combine::SelectIdealState( void ) -{ - switch ( m_NPCState ) - { - case NPC_STATE_COMBAT: - { - if ( GetEnemy() == NULL ) - { - if ( !HasCondition( COND_ENEMY_DEAD ) ) - { - // Lost track of my enemy. Patrol. - SetCondition( COND_COMBINE_SHOULD_PATROL ); - } - return NPC_STATE_ALERT; - } - else if ( HasCondition( COND_ENEMY_DEAD ) ) - { - AnnounceEnemyKill(GetEnemy()); - } - } - - default: - { - return BaseClass::SelectIdealState(); - } - } - - return GetIdealState(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Combine::OnBeginMoveAndShoot() -{ - if ( BaseClass::OnBeginMoveAndShoot() ) - { - if( HasStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - return true; // already have the slot I need - - if( !HasStrategySlotRange( SQUAD_SLOT_GRENADE1, SQUAD_SLOT_ATTACK_OCCLUDER ) && OccupyStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - return true; - } - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Combine::OnEndMoveAndShoot() -{ - VacateStrategySlot(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -WeaponProficiency_t CNPC_Combine::CalcWeaponProficiency( CBaseCombatWeapon *pWeapon ) -{ - if( FClassnameIs( pWeapon, "weapon_ar2" ) ) - { - if( hl2_episodic.GetBool() ) - { - return WEAPON_PROFICIENCY_VERY_GOOD; - } - else - { - return WEAPON_PROFICIENCY_GOOD; - } - } - else if( FClassnameIs( pWeapon, "weapon_shotgun" ) ) - { - if( m_nSkin != COMBINE_SKIN_SHOTGUNNER ) - { - m_nSkin = COMBINE_SKIN_SHOTGUNNER; - } - - return WEAPON_PROFICIENCY_PERFECT; - } - else if( FClassnameIs( pWeapon, "weapon_smg1" ) ) - { - return WEAPON_PROFICIENCY_GOOD; - } - - return BaseClass::CalcWeaponProficiency( pWeapon ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Combine::HasShotgun() -{ - if( GetActiveWeapon() && GetActiveWeapon()->m_iClassname == s_iszShotgunClassname ) - { - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Only supports weapons that use clips. -//----------------------------------------------------------------------------- -bool CNPC_Combine::ActiveWeaponIsFullyLoaded() -{ - CBaseCombatWeapon *pWeapon = GetActiveWeapon(); - - if( !pWeapon ) - return false; - - if( !pWeapon->UsesClipsForAmmo1() ) - return false; - - return ( pWeapon->Clip1() >= pWeapon->GetMaxClip1() ); -} - - -//----------------------------------------------------------------------------- -// Purpose: This is a generic function (to be implemented by sub-classes) to -// handle specific interactions between different types of characters -// (For example the barnacle grabbing an NPC) -// Input : The type of interaction, extra info pointer, and who started it -// Output : true - if sub-class has a response for the interaction -// false - if sub-class has no response -//----------------------------------------------------------------------------- -bool CNPC_Combine::HandleInteraction(int interactionType, void *data, CBaseCombatCharacter *sourceEnt) -{ - if ( interactionType == g_interactionTurretStillStanding ) - { - // A turret that I've kicked recently is still standing 5 seconds later. - if ( sourceEnt == GetEnemy() ) - { - // It's still my enemy. Time to grenade it. - Vector forward, up; - AngleVectors( GetLocalAngles(), &forward, NULL, &up ); - m_vecTossVelocity = forward * 10; - SetCondition( COND_COMBINE_DROP_GRENADE ); - ClearSchedule( "Failed to kick over turret" ); - } - return true; - } - - return BaseClass::HandleInteraction( interactionType, data, sourceEnt ); -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -const char* CNPC_Combine::GetSquadSlotDebugName( int iSquadSlot ) -{ - switch( iSquadSlot ) - { - case SQUAD_SLOT_GRENADE1: return "SQUAD_SLOT_GRENADE1"; - break; - case SQUAD_SLOT_GRENADE2: return "SQUAD_SLOT_GRENADE2"; - break; - case SQUAD_SLOT_ATTACK_OCCLUDER: return "SQUAD_SLOT_ATTACK_OCCLUDER"; - break; - case SQUAD_SLOT_OVERWATCH: return "SQUAD_SLOT_OVERWATCH"; - break; - } - - return BaseClass::GetSquadSlotDebugName( iSquadSlot ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Combine::IsUsingTacticalVariant( int variant ) -{ - if( variant == TACTICAL_VARIANT_PRESSURE_ENEMY && m_iTacticalVariant == TACTICAL_VARIANT_PRESSURE_ENEMY_UNTIL_CLOSE ) - { - // Essentially, fib. Just say that we are a 'pressure enemy' soldier. - return true; - } - - return m_iTacticalVariant == variant; -} - -//----------------------------------------------------------------------------- -// For the purpose of determining whether to use a pathfinding variant, this -// function determines whether the current schedule is a schedule that -// 'approaches' the enemy. -//----------------------------------------------------------------------------- -bool CNPC_Combine::IsRunningApproachEnemySchedule() -{ - if( IsCurSchedule( SCHED_CHASE_ENEMY ) ) - return true; - - if( IsCurSchedule( SCHED_ESTABLISH_LINE_OF_FIRE ) ) - return true; - - if( IsCurSchedule( SCHED_COMBINE_PRESS_ATTACK, false ) ) - return true; - - return false; -} - -bool CNPC_Combine::ShouldPickADeathPose( void ) -{ - return !IsCrouching(); -} - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC( npc_combine, CNPC_Combine ) - -//Tasks -DECLARE_TASK( TASK_COMBINE_FACE_TOSS_DIR ) -DECLARE_TASK( TASK_COMBINE_IGNORE_ATTACKS ) -DECLARE_TASK( TASK_COMBINE_SIGNAL_BEST_SOUND ) -DECLARE_TASK( TASK_COMBINE_DEFER_SQUAD_GRENADES ) -DECLARE_TASK( TASK_COMBINE_CHASE_ENEMY_CONTINUOUSLY ) -DECLARE_TASK( TASK_COMBINE_DIE_INSTANTLY ) -DECLARE_TASK( TASK_COMBINE_PLAY_SEQUENCE_FACE_ALTFIRE_TARGET ) -DECLARE_TASK( TASK_COMBINE_GET_PATH_TO_FORCED_GREN_LOS ) -DECLARE_TASK( TASK_COMBINE_SET_STANDING ) - -//Activities -DECLARE_ACTIVITY( ACT_COMBINE_THROW_GRENADE ) -DECLARE_ACTIVITY( ACT_COMBINE_LAUNCH_GRENADE ) -DECLARE_ACTIVITY( ACT_COMBINE_BUGBAIT ) -DECLARE_ACTIVITY( ACT_COMBINE_AR2_ALTFIRE ) -DECLARE_ACTIVITY( ACT_WALK_EASY ) -DECLARE_ACTIVITY( ACT_WALK_MARCH ) - -DECLARE_ANIMEVENT( COMBINE_AE_BEGIN_ALTFIRE ) -DECLARE_ANIMEVENT( COMBINE_AE_ALTFIRE ) - -DECLARE_SQUADSLOT( SQUAD_SLOT_GRENADE1 ) -DECLARE_SQUADSLOT( SQUAD_SLOT_GRENADE2 ) - -DECLARE_CONDITION( COND_COMBINE_NO_FIRE ) -DECLARE_CONDITION( COND_COMBINE_DEAD_FRIEND ) -DECLARE_CONDITION( COND_COMBINE_SHOULD_PATROL ) -DECLARE_CONDITION( COND_COMBINE_HIT_BY_BUGBAIT ) -DECLARE_CONDITION( COND_COMBINE_DROP_GRENADE ) -DECLARE_CONDITION( COND_COMBINE_ON_FIRE ) -DECLARE_CONDITION( COND_COMBINE_ATTACK_SLOT_AVAILABLE ) - -DECLARE_INTERACTION( g_interactionCombineBash ); - -//========================================================= -// SCHED_COMBINE_TAKE_COVER_FROM_BEST_SOUND -// -// hide from the loudest sound source (to run from grenade) -//========================================================= -DEFINE_SCHEDULE -( - SCHED_COMBINE_TAKE_COVER_FROM_BEST_SOUND, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_COMBINE_RUN_AWAY_FROM_BEST_SOUND" - " TASK_STOP_MOVING 0" - " TASK_COMBINE_SIGNAL_BEST_SOUND 0" - " TASK_FIND_COVER_FROM_BEST_SOUND 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_REMEMBER MEMORY:INCOVER" - " TASK_FACE_REASONABLE 0" - "" - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_COMBINE_RUN_AWAY_FROM_BEST_SOUND, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_COWER" - " TASK_GET_PATH_AWAY_FROM_BEST_SOUND 600" - " TASK_RUN_PATH_TIMED 2" - " TASK_STOP_MOVING 0" - "" - " Interrupts" - ) - //========================================================= - // SCHED_COMBINE_COMBAT_FAIL - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_COMBAT_FAIL, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE " - " TASK_WAIT_FACE_ENEMY 2" - " TASK_WAIT_PVS 0" - "" - " Interrupts" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - ) - - //========================================================= - // SCHED_COMBINE_VICTORY_DANCE - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_VICTORY_DANCE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_WAIT 1.5" - " TASK_GET_PATH_TO_ENEMY_CORPSE 0" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_FACE_ENEMY 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_VICTORY_DANCE" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - ) - - //========================================================= - // SCHED_COMBINE_ASSAULT - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_ASSAULT, - - " Tasks " - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_COMBINE_ESTABLISH_LINE_OF_FIRE" - " TASK_SET_TOLERANCE_DISTANCE 48" - " TASK_GET_PATH_TO_ENEMY_LKP 0" - " TASK_COMBINE_IGNORE_ATTACKS 0.2" - " TASK_SPEAK_SENTENCE 0" - " TASK_RUN_PATH 0" - // " TASK_COMBINE_MOVE_AND_AIM 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_COMBINE_IGNORE_ATTACKS 0.0" - "" - " Interrupts " - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_ENEMY_UNREACHABLE" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK2" - " COND_TOO_FAR_TO_ATTACK" - " COND_HEAR_DANGER" - " COND_HEAR_MOVE_AWAY" - ) - - DEFINE_SCHEDULE - ( - SCHED_COMBINE_ESTABLISH_LINE_OF_FIRE, - - " Tasks " - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_FAIL_ESTABLISH_LINE_OF_FIRE" - " TASK_SET_TOLERANCE_DISTANCE 48" - " TASK_GET_PATH_TO_ENEMY_LKP_LOS 0" - " TASK_COMBINE_SET_STANDING 1" - " TASK_SPEAK_SENTENCE 1" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_COMBINE_IGNORE_ATTACKS 0.0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_COMBAT_FACE" - " " - " Interrupts " - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - //" COND_CAN_RANGE_ATTACK1" - //" COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - " COND_HEAR_DANGER" - " COND_HEAR_MOVE_AWAY" - " COND_HEAVY_DAMAGE" - ) - - //========================================================= - // SCHED_COMBINE_PRESS_ATTACK - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_PRESS_ATTACK, - - " Tasks " - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_COMBINE_ESTABLISH_LINE_OF_FIRE" - " TASK_SET_TOLERANCE_DISTANCE 72" - " TASK_GET_PATH_TO_ENEMY_LKP 0" - " TASK_COMBINE_SET_STANDING 1" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts " - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_ENEMY_UNREACHABLE" - " COND_NO_PRIMARY_AMMO" - " COND_LOW_PRIMARY_AMMO" - " COND_TOO_CLOSE_TO_ATTACK" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - " COND_HEAR_DANGER" - " COND_HEAR_MOVE_AWAY" - ) - - //========================================================= - // SCHED_COMBINE_COMBAT_FACE - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_COMBAT_FACE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_FACE_ENEMY 0" - " TASK_WAIT 1.5" - //" TASK_SET_SCHEDULE SCHEDULE:SCHED_COMBINE_SWEEP" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - ) - - //========================================================= - // SCHED_HIDE_AND_RELOAD - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_HIDE_AND_RELOAD, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_RELOAD" - " TASK_FIND_COVER_FROM_ENEMY 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_REMEMBER MEMORY:INCOVER" - " TASK_FACE_ENEMY 0" - " TASK_RELOAD 0" - "" - " Interrupts" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_HEAR_MOVE_AWAY" - ) - - //========================================================= - // SCHED_COMBINE_SIGNAL_SUPPRESS - // don't stop shooting until the clip is - // empty or combine gets hurt. - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_SIGNAL_SUPPRESS, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_IDEAL 0" - " TASK_PLAY_SEQUENCE_FACE_ENEMY ACTIVITY:ACT_SIGNAL_GROUP" - " TASK_COMBINE_SET_STANDING 0" - " TASK_RANGE_ATTACK1 0" - "" - " Interrupts" - " COND_ENEMY_DEAD" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_NO_PRIMARY_AMMO" - " COND_WEAPON_BLOCKED_BY_FRIEND" - " COND_WEAPON_SIGHT_OCCLUDED" - " COND_HEAR_DANGER" - " COND_HEAR_MOVE_AWAY" - " COND_COMBINE_NO_FIRE" - ) - - //========================================================= - // SCHED_COMBINE_SUPPRESS - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_SUPPRESS, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_COMBINE_SET_STANDING 0" - " TASK_RANGE_ATTACK1 0" - "" - " Interrupts" - " COND_ENEMY_DEAD" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_NO_PRIMARY_AMMO" - " COND_HEAR_DANGER" - " COND_HEAR_MOVE_AWAY" - " COND_COMBINE_NO_FIRE" - " COND_WEAPON_BLOCKED_BY_FRIEND" - ) - - //========================================================= - // SCHED_COMBINE_ENTER_OVERWATCH - // - // Parks a combine soldier in place looking at the player's - // last known position, ready to attack if the player pops out - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_ENTER_OVERWATCH, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_COMBINE_SET_STANDING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_FACE_ENEMY 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_COMBINE_OVERWATCH" - "" - " Interrupts" - " COND_HEAR_DANGER" - " COND_NEW_ENEMY" - ) - - //========================================================= - // SCHED_COMBINE_OVERWATCH - // - // Parks a combine soldier in place looking at the player's - // last known position, ready to attack if the player pops out - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_OVERWATCH, - - " Tasks" - " TASK_WAIT_FACE_ENEMY 10" - "" - " Interrupts" - " COND_CAN_RANGE_ATTACK1" - " COND_ENEMY_DEAD" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_NO_PRIMARY_AMMO" - " COND_HEAR_DANGER" - " COND_HEAR_MOVE_AWAY" - " COND_NEW_ENEMY" - ) - - //========================================================= - // SCHED_COMBINE_WAIT_IN_COVER - // we don't allow danger or the ability - // to attack to break a combine's run to cover schedule but - // when a combine is in cover we do want them to attack if they can. - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_WAIT_IN_COVER, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_COMBINE_SET_STANDING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" // Translated to cover - " TASK_WAIT_FACE_ENEMY 1" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - " COND_HEAR_DANGER" - " COND_HEAR_MOVE_AWAY" - " COND_COMBINE_ATTACK_SLOT_AVAILABLE" - ) - - //========================================================= - // SCHED_COMBINE_TAKE_COVER1 - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_TAKE_COVER1 , - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_COMBINE_TAKECOVER_FAILED" - " TASK_STOP_MOVING 0" - " TASK_WAIT 0.2" - " TASK_FIND_COVER_FROM_ENEMY 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_REMEMBER MEMORY:INCOVER" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_COMBINE_WAIT_IN_COVER" - "" - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_COMBINE_TAKECOVER_FAILED, - - " Tasks" - " TASK_STOP_MOVING 0" - "" - " Interrupts" - ) - - //========================================================= - // SCHED_COMBINE_GRENADE_COVER1 - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_GRENADE_COVER1, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FIND_COVER_FROM_ENEMY 99" - " TASK_FIND_FAR_NODE_COVER_FROM_ENEMY 384" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_SPECIAL_ATTACK2" - " TASK_CLEAR_MOVE_WAIT 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_COMBINE_WAIT_IN_COVER" - "" - " Interrupts" - ) - - //========================================================= - // SCHED_COMBINE_TOSS_GRENADE_COVER1 - // - // drop grenade then run to cover. - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_TOSS_GRENADE_COVER1, - - " Tasks" - " TASK_FACE_ENEMY 0" - " TASK_RANGE_ATTACK2 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_TAKE_COVER_FROM_ENEMY" - "" - " Interrupts" - ) - - //========================================================= - // SCHED_COMBINE_RANGE_ATTACK1 - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_RANGE_ATTACK1, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_ANNOUNCE_ATTACK 1" // 1 = primary attack - " TASK_WAIT_RANDOM 0.3" - " TASK_RANGE_ATTACK1 0" - " TASK_COMBINE_IGNORE_ATTACKS 0.5" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_HEAVY_DAMAGE" - " COND_LIGHT_DAMAGE" - " COND_LOW_PRIMARY_AMMO" - " COND_NO_PRIMARY_AMMO" - " COND_WEAPON_BLOCKED_BY_FRIEND" - " COND_TOO_CLOSE_TO_ATTACK" - " COND_GIVE_WAY" - " COND_HEAR_DANGER" - " COND_HEAR_MOVE_AWAY" - " COND_COMBINE_NO_FIRE" - "" - // Enemy_Occluded Don't interrupt on this. Means - // comibine will fire where player was after - // he has moved for a little while. Good effect!! - // WEAPON_SIGHT_OCCLUDED Don't block on this! Looks better for railings, etc. - ) - - //========================================================= - // AR2 Alt Fire Attack - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_AR2_ALTFIRE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_ANNOUNCE_ATTACK 1" - " TASK_COMBINE_PLAY_SEQUENCE_FACE_ALTFIRE_TARGET ACTIVITY:ACT_COMBINE_AR2_ALTFIRE" - "" - " Interrupts" - ) - - //========================================================= - // Mapmaker forced grenade throw - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_FORCED_GRENADE_THROW, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_COMBINE_FACE_TOSS_DIR 0" - " TASK_ANNOUNCE_ATTACK 2" // 2 = grenade - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_RANGE_ATTACK2" - " TASK_COMBINE_DEFER_SQUAD_GRENADES 0" - "" - " Interrupts" - ) - - //========================================================= - // Move to LOS of the mapmaker's forced grenade throw target - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_MOVE_TO_FORCED_GREN_LOS, - - " Tasks " - " TASK_SET_TOLERANCE_DISTANCE 48" - " TASK_COMBINE_GET_PATH_TO_FORCED_GREN_LOS 0" - " TASK_SPEAK_SENTENCE 1" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " " - " Interrupts " - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - " COND_HEAR_DANGER" - " COND_HEAR_MOVE_AWAY" - " COND_HEAVY_DAMAGE" - ) - - //========================================================= - // SCHED_COMBINE_RANGE_ATTACK2 - // - // secondary range attack. Overriden because base class stops attacking when the enemy is occluded. - // combines's grenade toss requires the enemy be occluded. - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_RANGE_ATTACK2, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_COMBINE_FACE_TOSS_DIR 0" - " TASK_ANNOUNCE_ATTACK 2" // 2 = grenade - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_RANGE_ATTACK2" - " TASK_COMBINE_DEFER_SQUAD_GRENADES 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_COMBINE_WAIT_IN_COVER" // don't run immediately after throwing grenade. - "" - " Interrupts" - ) - - - //========================================================= - // Throw a grenade, then run off and reload. - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_GRENADE_AND_RELOAD, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_COMBINE_FACE_TOSS_DIR 0" - " TASK_ANNOUNCE_ATTACK 2" // 2 = grenade - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_RANGE_ATTACK2" - " TASK_COMBINE_DEFER_SQUAD_GRENADES 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_HIDE_AND_RELOAD" // don't run immediately after throwing grenade. - "" - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_COMBINE_PATROL, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_WANDER 900540" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_FACE_REASONABLE 0" - " TASK_WAIT 3" - " TASK_WAIT_RANDOM 3" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_COMBINE_PATROL" // keep doing it - "" - " Interrupts" - " COND_ENEMY_DEAD" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_HEAR_MOVE_AWAY" - " COND_NEW_ENEMY" - " COND_SEE_ENEMY" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - ) - - DEFINE_SCHEDULE - ( - SCHED_COMBINE_BUGBAIT_DISTRACTION, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_RESET_ACTIVITY 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_COMBINE_BUGBAIT" - "" - " Interrupts" - "" - ) - - //========================================================= - // SCHED_COMBINE_CHARGE_TURRET - // - // Used to run straight at enemy turrets to knock them over. - // Prevents squadmates from throwing grenades during. - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_CHARGE_TURRET, - - " Tasks" - " TASK_COMBINE_DEFER_SQUAD_GRENADES 0" - " TASK_STOP_MOVING 0" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY_FAILED" - " TASK_GET_CHASE_PATH_TO_ENEMY 300" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_ENEMY_UNREACHABLE" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - " COND_TOO_CLOSE_TO_ATTACK" - " COND_TASK_FAILED" - " COND_LOST_ENEMY" - " COND_BETTER_WEAPON_AVAILABLE" - " COND_HEAR_DANGER" - ) - - //========================================================= - // SCHED_COMBINE_CHARGE_PLAYER - // - // Used to run straight at enemy player since physgun combat - // is more fun when the enemies are close - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_CHARGE_PLAYER, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY_FAILED" - " TASK_COMBINE_CHASE_ENEMY_CONTINUOUSLY 192" - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_ENEMY_UNREACHABLE" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - " COND_TASK_FAILED" - " COND_LOST_ENEMY" - " COND_HEAR_DANGER" - ) - - //========================================================= - // SCHED_COMBINE_DROP_GRENADE - // - // Place a grenade at my feet - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_DROP_GRENADE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_SPECIAL_ATTACK2" - " TASK_FIND_COVER_FROM_ENEMY 99" - " TASK_FIND_FAR_NODE_COVER_FROM_ENEMY 384" - " TASK_CLEAR_MOVE_WAIT 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - ) - - //========================================================= - // SCHED_COMBINE_PATROL_ENEMY - // - // Used instead if SCHED_COMBINE_PATROL if I have an enemy. - // Wait for the enemy a bit in the hopes of ambushing him. - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_COMBINE_PATROL_ENEMY, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_WAIT_FACE_ENEMY 1" - " TASK_WAIT_FACE_ENEMY_RANDOM 3" - "" - " Interrupts" - " COND_ENEMY_DEAD" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_HEAR_MOVE_AWAY" - " COND_NEW_ENEMY" - " COND_SEE_ENEMY" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - ) - - DEFINE_SCHEDULE - ( - SCHED_COMBINE_BURNING_STAND, - - " Tasks" - " TASK_SET_ACTIVITY ACTIVITY:ACT_COMBINE_BUGBAIT" - " TASK_RANDOMIZE_FRAMERATE 20" - " TASK_WAIT 2" - " TASK_WAIT_RANDOM 3" - " TASK_COMBINE_DIE_INSTANTLY DMG_BURN" - " TASK_WAIT 1.0" - " " - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_COMBINE_FACE_IDEAL_YAW, - - " Tasks" - " TASK_FACE_IDEAL 0" - " " - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_COMBINE_MOVE_TO_MELEE, - - " Tasks" - " TASK_STORE_ENEMY_POSITION_IN_SAVEPOSITION 0" - " TASK_GET_PATH_TO_SAVEPOSITION 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_CAN_MELEE_ATTACK1" - ) - - AI_END_CUSTOM_NPC() diff --git a/game/server/hl2/npc_combine.h b/game/server/hl2/npc_combine.h deleted file mode 100644 index 87fd269de..000000000 --- a/game/server/hl2/npc_combine.h +++ /dev/null @@ -1,297 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef NPC_COMBINE_H -#define NPC_COMBINE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_basenpc.h" -#include "ai_basehumanoid.h" -#include "ai_behavior.h" -#include "ai_behavior_assault.h" -#include "ai_behavior_standoff.h" -#include "ai_behavior_follow.h" -#include "ai_behavior_functank.h" -#include "ai_behavior_rappel.h" -#include "ai_behavior_actbusy.h" -#include "ai_sentence.h" -#include "ai_baseactor.h" - -// Used when only what combine to react to what the spotlight sees -#define SF_COMBINE_NO_LOOK (1 << 16) -#define SF_COMBINE_NO_GRENADEDROP ( 1 << 17 ) -#define SF_COMBINE_NO_AR2DROP ( 1 << 18 ) - -//========================================================= -// >> CNPC_Combine -//========================================================= -class CNPC_Combine : public CAI_BaseActor -{ - DECLARE_DATADESC(); - DEFINE_CUSTOM_AI; - DECLARE_CLASS( CNPC_Combine, CAI_BaseActor ); - -public: - CNPC_Combine(); - - // Create components - virtual bool CreateComponents(); - - bool CanThrowGrenade( const Vector &vecTarget ); - bool CheckCanThrowGrenade( const Vector &vecTarget ); - virtual bool CanGrenadeEnemy( bool bUseFreeKnowledge = true ); - virtual bool CanAltFireEnemy( bool bUseFreeKnowledge ); - int GetGrenadeConditions( float flDot, float flDist ); - int RangeAttack2Conditions( float flDot, float flDist ); // For innate grenade attack - int MeleeAttack1Conditions( float flDot, float flDist ); // For kick/punch - bool FVisible( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ); - virtual bool IsCurTaskContinuousMove(); - - virtual float GetJumpGravity() const { return 1.8f; } - - virtual Vector GetCrouchEyeOffset( void ); - - void Event_Killed( const CTakeDamageInfo &info ); - - - void SetActivity( Activity NewActivity ); - NPC_STATE SelectIdealState ( void ); - - // Input handlers. - void InputLookOn( inputdata_t &inputdata ); - void InputLookOff( inputdata_t &inputdata ); - void InputStartPatrolling( inputdata_t &inputdata ); - void InputStopPatrolling( inputdata_t &inputdata ); - void InputAssault( inputdata_t &inputdata ); - void InputHitByBugbait( inputdata_t &inputdata ); - void InputThrowGrenadeAtTarget( inputdata_t &inputdata ); - - bool UpdateEnemyMemory( CBaseEntity *pEnemy, const Vector &position, CBaseEntity *pInformer = NULL ); - - void Spawn( void ); - void Precache( void ); - void Activate(); - - Class_T Classify( void ); - bool IsElite() { return m_fIsElite; } - void DelayAltFireAttack( float flDelay ); - void DelaySquadAltFireAttack( float flDelay ); - float MaxYawSpeed( void ); - bool ShouldMoveAndShoot(); - bool OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval );; - void HandleAnimEvent( animevent_t *pEvent ); - Vector Weapon_ShootPosition( ); - - Vector EyeOffset( Activity nActivity ); - Vector EyePosition( void ); - Vector BodyTarget( const Vector &posSrc, bool bNoisy = true ); - Vector GetAltFireTarget(); - - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - void PostNPCInit(); - void GatherConditions(); - virtual void PrescheduleThink(); - - Activity NPC_TranslateActivity( Activity eNewActivity ); - void BuildScheduleTestBits( void ); - virtual int SelectSchedule( void ); - virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ); - int SelectScheduleAttack(); - - bool CreateBehaviors(); - - bool OnBeginMoveAndShoot(); - void OnEndMoveAndShoot(); - - // Combat - WeaponProficiency_t CalcWeaponProficiency( CBaseCombatWeapon *pWeapon ); - bool HasShotgun(); - bool ActiveWeaponIsFullyLoaded(); - - bool HandleInteraction(int interactionType, void *data, CBaseCombatCharacter *sourceEnt); - const char* GetSquadSlotDebugName( int iSquadSlot ); - - bool IsUsingTacticalVariant( int variant ); - bool IsUsingPathfindingVariant( int variant ) { return m_iPathfindingVariant == variant; } - - bool IsRunningApproachEnemySchedule(); - - // ------------- - // Sounds - // ------------- - void DeathSound( void ); - void PainSound( void ); - void IdleSound( void ); - void AlertSound( void ); - void LostEnemySound( void ); - void FoundEnemySound( void ); - void AnnounceAssault( void ); - void AnnounceEnemyType( CBaseEntity *pEnemy ); - void AnnounceEnemyKill( CBaseEntity *pEnemy ); - - void NotifyDeadFriend( CBaseEntity* pFriend ); - - virtual float HearingSensitivity( void ) { return 1.0; }; - int GetSoundInterests( void ); - virtual bool QueryHearSound( CSound *pSound ); - - // Speaking - void SpeakSentence( int sentType ); - - virtual int TranslateSchedule( int scheduleType ); - void OnStartSchedule( int scheduleType ); - - virtual bool ShouldPickADeathPose( void ); - -protected: - void SetKickDamage( int nDamage ) { m_nKickDamage = nDamage; } - CAI_Sentence< CNPC_Combine > *GetSentences() { return &m_Sentences; } - -private: - //========================================================= - // Combine S schedules - //========================================================= - enum - { - SCHED_COMBINE_SUPPRESS = BaseClass::NEXT_SCHEDULE, - SCHED_COMBINE_COMBAT_FAIL, - SCHED_COMBINE_VICTORY_DANCE, - SCHED_COMBINE_COMBAT_FACE, - SCHED_COMBINE_HIDE_AND_RELOAD, - SCHED_COMBINE_SIGNAL_SUPPRESS, - SCHED_COMBINE_ENTER_OVERWATCH, - SCHED_COMBINE_OVERWATCH, - SCHED_COMBINE_ASSAULT, - SCHED_COMBINE_ESTABLISH_LINE_OF_FIRE, - SCHED_COMBINE_PRESS_ATTACK, - SCHED_COMBINE_WAIT_IN_COVER, - SCHED_COMBINE_RANGE_ATTACK1, - SCHED_COMBINE_RANGE_ATTACK2, - SCHED_COMBINE_TAKE_COVER1, - SCHED_COMBINE_TAKE_COVER_FROM_BEST_SOUND, - SCHED_COMBINE_RUN_AWAY_FROM_BEST_SOUND, - SCHED_COMBINE_GRENADE_COVER1, - SCHED_COMBINE_TOSS_GRENADE_COVER1, - SCHED_COMBINE_TAKECOVER_FAILED, - SCHED_COMBINE_GRENADE_AND_RELOAD, - SCHED_COMBINE_PATROL, - SCHED_COMBINE_BUGBAIT_DISTRACTION, - SCHED_COMBINE_CHARGE_TURRET, - SCHED_COMBINE_DROP_GRENADE, - SCHED_COMBINE_CHARGE_PLAYER, - SCHED_COMBINE_PATROL_ENEMY, - SCHED_COMBINE_BURNING_STAND, - SCHED_COMBINE_AR2_ALTFIRE, - SCHED_COMBINE_FORCED_GRENADE_THROW, - SCHED_COMBINE_MOVE_TO_FORCED_GREN_LOS, - SCHED_COMBINE_FACE_IDEAL_YAW, - SCHED_COMBINE_MOVE_TO_MELEE, - NEXT_SCHEDULE, - }; - - //========================================================= - // Combine Tasks - //========================================================= - enum - { - TASK_COMBINE_FACE_TOSS_DIR = BaseClass::NEXT_TASK, - TASK_COMBINE_IGNORE_ATTACKS, - TASK_COMBINE_SIGNAL_BEST_SOUND, - TASK_COMBINE_DEFER_SQUAD_GRENADES, - TASK_COMBINE_CHASE_ENEMY_CONTINUOUSLY, - TASK_COMBINE_DIE_INSTANTLY, - TASK_COMBINE_PLAY_SEQUENCE_FACE_ALTFIRE_TARGET, - TASK_COMBINE_GET_PATH_TO_FORCED_GREN_LOS, - TASK_COMBINE_SET_STANDING, - NEXT_TASK - }; - - //========================================================= - // Combine Conditions - //========================================================= - enum Combine_Conds - { - COND_COMBINE_NO_FIRE = BaseClass::NEXT_CONDITION, - COND_COMBINE_DEAD_FRIEND, - COND_COMBINE_SHOULD_PATROL, - COND_COMBINE_HIT_BY_BUGBAIT, - COND_COMBINE_DROP_GRENADE, - COND_COMBINE_ON_FIRE, - COND_COMBINE_ATTACK_SLOT_AVAILABLE, - NEXT_CONDITION - }; - -private: - // Select the combat schedule - int SelectCombatSchedule(); - - // Should we charge the player? - bool ShouldChargePlayer(); - - // Chase the enemy, updating the target position as the player moves - void StartTaskChaseEnemyContinuously( const Task_t *pTask ); - void RunTaskChaseEnemyContinuously( const Task_t *pTask ); - - class CCombineStandoffBehavior : public CAI_ComponentWithOuter - { - typedef CAI_ComponentWithOuter BaseClass; - - virtual int SelectScheduleAttack() - { - int result = GetOuter()->SelectScheduleAttack(); - if ( result == SCHED_NONE ) - result = BaseClass::SelectScheduleAttack(); - return result; - } - }; - - // Rappel - virtual bool IsWaitingToRappel( void ) { return m_RappelBehavior.IsWaitingToRappel(); } - void BeginRappel() { m_RappelBehavior.BeginRappel(); } - -private: - int m_nKickDamage; - Vector m_vecTossVelocity; - EHANDLE m_hForcedGrenadeTarget; - bool m_bShouldPatrol; - bool m_bFirstEncounter;// only put on the handsign show in the squad's first encounter. - - // Time Variables - float m_flNextPainSoundTime; - float m_flNextAlertSoundTime; - float m_flNextGrenadeCheck; - float m_flNextLostSoundTime; - float m_flAlertPatrolTime; // When to stop doing alert patrol - float m_flNextAltFireTime; // Elites only. Next time to begin considering alt-fire attack. - - int m_nShots; - float m_flShotDelay; - float m_flStopMoveShootTime; - - CAI_Sentence< CNPC_Combine > m_Sentences; - - int m_iNumGrenades; - CAI_AssaultBehavior m_AssaultBehavior; - CCombineStandoffBehavior m_StandoffBehavior; - CAI_FollowBehavior m_FollowBehavior; - CAI_FuncTankBehavior m_FuncTankBehavior; - CAI_RappelBehavior m_RappelBehavior; - CAI_ActBusyBehavior m_ActBusyBehavior; - -public: - int m_iLastAnimEventHandled; - bool m_fIsElite; - Vector m_vecAltFireTarget; - - int m_iTacticalVariant; - int m_iPathfindingVariant; -}; - - -#endif // NPC_COMBINE_H diff --git a/game/server/hl2/npc_combinecamera.cpp b/game/server/hl2/npc_combinecamera.cpp deleted file mode 100644 index bcc6cf60b..000000000 --- a/game/server/hl2/npc_combinecamera.cpp +++ /dev/null @@ -1,1188 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Security cameras will track a default target (if they have one) -// until they either acquire an enemy to track or are told to track -// an entity via an input. If they lose their target they will -// revert to tracking their default target. They acquire enemies -// using the relationship table just like any other NPC. -// -// Cameras have two zones of awareness, an inner zone formed by the -// intersection of an inner FOV and an inner radius. The camera is -// fully aware of entities in the inner zone and will acquire enemies -// seen there. -// -// The outer zone of awareness is formed by the intersection of an -// outer FOV and an outer radius. The camera is only vaguely aware -// of entities in the outer zone and will flash amber when enemies -// are there, but will otherwise ignore them. -// -// They can be made angry via an input, at which time they sound an -// alarm and snap a few pictures of whatever they are tracking. They -// can also be set to become angry anytime they acquire an enemy. -// -//=============================================================================// - -#include "cbase.h" -#include "ai_basenpc.h" -#include "ai_senses.h" -#include "ai_memory.h" -#include "engine/IEngineSound.h" -#include "ammodef.h" -#include "Sprite.h" -#include "hl2/hl2_player.h" -#include "soundenvelope.h" -#include "explode.h" -#include "IEffects.h" -#include "animation.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// Debug visualization -ConVar g_debug_combine_camera("g_debug_combine_camera", "0"); - -#define COMBINE_CAMERA_MODEL "models/combine_camera/combine_camera.mdl" -#define COMBINE_CAMERA_GLOW_SPRITE "sprites/glow1.vmt" -#define COMBINE_CAMERA_FLASH_SPRITE "sprites/light_glow03.vmt" -#define COMBINE_CAMERA_BC_YAW "aim_yaw" -#define COMBINE_CAMERA_BC_PITCH "aim_pitch" - -#define COMBINE_CAMERA_SPREAD VECTOR_CONE_2DEGREES -#define COMBINE_CAMERA_MAX_WAIT 5 -#define COMBINE_CAMERA_PING_TIME 1.0f - -// Spawnflags -#define SF_COMBINE_CAMERA_BECOMEANGRY 0x00000020 -#define SF_COMBINE_CAMERA_IGNOREENEMIES 0x00000040 -#define SF_COMBINE_CAMERA_STARTINACTIVE 0x00000080 - -// Heights -#define COMBINE_CAMERA_RETRACT_HEIGHT 24 -#define COMBINE_CAMERA_DEPLOY_HEIGHT 64 - - -// Activities -int ACT_COMBINE_CAMERA_OPEN; -int ACT_COMBINE_CAMERA_CLOSE; -int ACT_COMBINE_CAMERA_OPEN_IDLE; -int ACT_COMBINE_CAMERA_CLOSED_IDLE; -int ACT_COMBINE_CAMERA_FIRE; - - -const float CAMERA_CLICK_INTERVAL = 0.5f; -const float CAMERA_MOVE_INTERVAL = 1.0f; - - -// -// The camera has two FOVs - a wide one for becoming slightly aware of someone, -// a narrow one for becoming totally aware of them. -// -const float CAMERA_FOV_WIDE = 0.5; -const float CAMERA_FOV_NARROW = 0.707; - - -// Camera states -enum cameraState_e -{ - CAMERA_SEARCHING, - CAMERA_AUTO_SEARCHING, - CAMERA_ACTIVE, - CAMERA_DEAD, -}; - - -// Eye states -enum eyeState_t -{ - CAMERA_EYE_IDLE, // Nothing abnormal in the inner or outer viewcone, dim green. - CAMERA_EYE_SEEKING_TARGET, // Something in the outer viewcone, flashes amber as it converges on the target. - CAMERA_EYE_FOUND_TARGET, // Something in the inner viewcone, bright amber. - CAMERA_EYE_ANGRY, // Found a target that we don't like: angry, bright red. - CAMERA_EYE_DORMANT, // Not active - CAMERA_EYE_DEAD, // Completely invisible - CAMERA_EYE_DISABLED, // Turned off, must be reactivated before it'll deploy again (completely invisible) - CAMERA_EYE_HAPPY, // Found a target that we like: go green for a second -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CNPC_CombineCamera : public CAI_BaseNPC -{ - DECLARE_CLASS(CNPC_CombineCamera, CAI_BaseNPC); -public: - - CNPC_CombineCamera(); - ~CNPC_CombineCamera(); - - void Precache(); - void Spawn(); - Vector HeadDirection2D(); - - int DrawDebugTextOverlays(); - - void Deploy(); - void ActiveThink(); - void SearchThink(); - void DeathThink(); - - void InputToggle(inputdata_t &inputdata); - void InputEnable(inputdata_t &inputdata); - void InputDisable(inputdata_t &inputdata); - void InputSetAngry(inputdata_t &inputdata); - void InputSetIdle(inputdata_t &inputdata); - - void DrawDebugGeometryOverlays(void); - - float MaxYawSpeed(); - - int OnTakeDamage(const CTakeDamageInfo &inputInfo); - - Class_T Classify() { return (m_bEnabled) ? CLASS_MILITARY : CLASS_NONE; } - - bool IsValidEnemy( CBaseEntity *pEnemy ); - bool FVisible(CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL); - - Vector EyeOffset(Activity nActivity) - { - Vector vecEyeOffset(0,0,-64); - GetEyePosition(GetModelPtr(), vecEyeOffset); - return vecEyeOffset; - } - - Vector EyePosition() - { - return GetAbsOrigin() + EyeOffset(GetActivity()); - } - -protected: - - CBaseEntity *GetTarget(); - bool UpdateFacing(); - void TrackTarget(CBaseEntity *pTarget); - - bool PreThink(cameraState_e state); - void SetEyeState(eyeState_t state); - void MaintainEye(); - void Ping(); - void Toggle(); - void Enable(); - void Disable(); - void SetHeight(float height); - - CBaseEntity *MaintainEnemy(); - void SetAngry(bool bAngry); - -protected: - int m_iAmmoType; - int m_iMinHealthDmg; - - int m_nInnerRadius; // The camera will only lock onto enemies that are within the inner radius. - int m_nOuterRadius; // The camera will flash amber when enemies are within the outer radius, but outside the inner radius. - - bool m_bActive; // The camera is deployed and looking for targets - bool m_bAngry; // The camera has gotten angry at someone and sounded an alarm. - bool m_bBlinkState; - bool m_bEnabled; // Denotes whether the camera is able to deploy or not - - string_t m_sDefaultTarget; - - EHANDLE m_hEnemyTarget; // Entity we acquired as an enemy. - - float m_flPingTime; - float m_flClickTime; // Time to take next picture while angry. - int m_nClickCount; // Counts pictures taken since we last became angry. - float m_flMoveSoundTime; - float m_flTurnOffEyeFlashTime; - float m_flEyeHappyTime; - - QAngle m_vecGoalAngles; - - CSprite *m_pEyeGlow; - CSprite *m_pEyeFlash; - - DECLARE_DATADESC(); -}; - - -BEGIN_DATADESC(CNPC_CombineCamera) - - DEFINE_FIELD(m_iAmmoType, FIELD_INTEGER), - DEFINE_KEYFIELD(m_iMinHealthDmg, FIELD_INTEGER, "minhealthdmg"), - DEFINE_KEYFIELD(m_nInnerRadius, FIELD_INTEGER, "innerradius"), - DEFINE_KEYFIELD(m_nOuterRadius, FIELD_INTEGER, "outerradius"), - DEFINE_FIELD(m_bActive, FIELD_BOOLEAN), - DEFINE_FIELD(m_bAngry, FIELD_BOOLEAN), - DEFINE_FIELD(m_bBlinkState, FIELD_BOOLEAN), - DEFINE_FIELD(m_bEnabled, FIELD_BOOLEAN), - DEFINE_KEYFIELD(m_sDefaultTarget, FIELD_STRING, "defaulttarget"), - DEFINE_FIELD(m_hEnemyTarget, FIELD_EHANDLE), - DEFINE_FIELD(m_flPingTime, FIELD_TIME), - DEFINE_FIELD(m_flClickTime, FIELD_TIME), - DEFINE_FIELD(m_nClickCount, FIELD_INTEGER ), - DEFINE_FIELD(m_flMoveSoundTime, FIELD_TIME), - DEFINE_FIELD(m_flTurnOffEyeFlashTime, FIELD_TIME), - DEFINE_FIELD(m_flEyeHappyTime, FIELD_TIME), - DEFINE_FIELD(m_vecGoalAngles, FIELD_VECTOR), - DEFINE_FIELD(m_pEyeGlow, FIELD_CLASSPTR), - DEFINE_FIELD(m_pEyeFlash, FIELD_CLASSPTR), - - DEFINE_THINKFUNC(Deploy), - DEFINE_THINKFUNC(ActiveThink), - DEFINE_THINKFUNC(SearchThink), - DEFINE_THINKFUNC(DeathThink), - - // Inputs - DEFINE_INPUTFUNC(FIELD_VOID, "Toggle", InputToggle), - DEFINE_INPUTFUNC(FIELD_VOID, "Enable", InputEnable), - DEFINE_INPUTFUNC(FIELD_VOID, "Disable", InputDisable), - DEFINE_INPUTFUNC(FIELD_VOID, "SetAngry", InputSetAngry), - DEFINE_INPUTFUNC(FIELD_VOID, "SetIdle", InputSetIdle), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS(npc_combine_camera, CNPC_CombineCamera); - - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CNPC_CombineCamera::CNPC_CombineCamera() -{ - m_bActive = false; - m_pEyeGlow = NULL; - m_pEyeFlash = NULL; - m_iAmmoType = -1; - m_iMinHealthDmg = 0; - m_flPingTime = 0; - m_bBlinkState = false; - m_bEnabled = false; - - m_vecGoalAngles.Init(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CNPC_CombineCamera::~CNPC_CombineCamera() -{ -} - - -//----------------------------------------------------------------------------- -// Purpose: Precache -//----------------------------------------------------------------------------- -void CNPC_CombineCamera::Precache() -{ - PrecacheModel(COMBINE_CAMERA_MODEL); - PrecacheModel(COMBINE_CAMERA_GLOW_SPRITE); - PrecacheModel(COMBINE_CAMERA_FLASH_SPRITE); - - // Activities - ADD_CUSTOM_ACTIVITY(CNPC_CombineCamera, ACT_COMBINE_CAMERA_OPEN); - ADD_CUSTOM_ACTIVITY(CNPC_CombineCamera, ACT_COMBINE_CAMERA_CLOSE); - ADD_CUSTOM_ACTIVITY(CNPC_CombineCamera, ACT_COMBINE_CAMERA_CLOSED_IDLE); - ADD_CUSTOM_ACTIVITY(CNPC_CombineCamera, ACT_COMBINE_CAMERA_OPEN_IDLE); - ADD_CUSTOM_ACTIVITY(CNPC_CombineCamera, ACT_COMBINE_CAMERA_FIRE); - - PrecacheScriptSound( "NPC_CombineCamera.Move" ); - PrecacheScriptSound( "NPC_CombineCamera.BecomeIdle" ); - PrecacheScriptSound( "NPC_CombineCamera.Active" ); - PrecacheScriptSound( "NPC_CombineCamera.Click" ); - PrecacheScriptSound( "NPC_CombineCamera.Ping" ); - PrecacheScriptSound( "NPC_CombineCamera.Angry" ); - PrecacheScriptSound( "NPC_CombineCamera.Die" ); - - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Spawn the entity -//----------------------------------------------------------------------------- -void CNPC_CombineCamera::Spawn() -{ - Precache(); - - SetModel(COMBINE_CAMERA_MODEL); - - m_pEyeFlash = CSprite::SpriteCreate(COMBINE_CAMERA_FLASH_SPRITE, GetLocalOrigin(), FALSE); - m_pEyeFlash->SetTransparency(kRenderGlow, 255, 255, 255, 0, kRenderFxNoDissipation); - m_pEyeFlash->SetAttachment(this, 2); - m_pEyeFlash->SetBrightness(0); - m_pEyeFlash->SetScale(1.0); - - BaseClass::Spawn(); - - m_HackedGunPos = Vector(0, 0, 12.75); - SetViewOffset(EyeOffset(ACT_IDLE)); - m_flFieldOfView = CAMERA_FOV_WIDE; - m_takedamage = DAMAGE_YES; - m_iHealth = 50; - m_bloodColor = BLOOD_COLOR_MECH; - - SetSolid(SOLID_BBOX); - AddSolidFlags(FSOLID_NOT_STANDABLE); - - SetHeight(COMBINE_CAMERA_RETRACT_HEIGHT); - - AddFlag(FL_AIMTARGET); - - SetPoseParameter(COMBINE_CAMERA_BC_YAW, 0); - SetPoseParameter(COMBINE_CAMERA_BC_PITCH, 0); - - m_iAmmoType = GetAmmoDef()->Index("Pistol"); - - // Create our eye sprite - m_pEyeGlow = CSprite::SpriteCreate(COMBINE_CAMERA_GLOW_SPRITE, GetLocalOrigin(), false); - m_pEyeGlow->SetTransparency(kRenderWorldGlow, 255, 0, 0, 128, kRenderFxNoDissipation); - m_pEyeGlow->SetAttachment(this, 2); - - // Set our enabled state - m_bEnabled = ((m_spawnflags & SF_COMBINE_CAMERA_STARTINACTIVE) == false); - - // Make sure the radii are sane. - if (m_nOuterRadius <= 0) - { - m_nOuterRadius = 300; - } - - if (m_nInnerRadius <= 0) - { - m_nInnerRadius = 450; - } - - if (m_nOuterRadius < m_nInnerRadius) - { - swap(m_nOuterRadius, m_nInnerRadius); - } - - // Do we start active? - if (m_bEnabled) - { - Deploy(); - } - else - { - SetEyeState(CAMERA_EYE_DISABLED); - } - - //Adrian: No shadows on these guys. - AddEffects( EF_NOSHADOW ); - - // Stagger our starting times - SetNextThink( gpGlobals->curtime + random->RandomFloat(0.1f, 0.3f) ); - - // Don't allow us to skip animation setup because our attachments are critical to us! - SetBoneCacheFlags( BCF_NO_ANIMATION_SKIP ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseEntity *CNPC_CombineCamera::GetTarget() -{ - return m_hEnemyTarget; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_CombineCamera::OnTakeDamage(const CTakeDamageInfo &inputInfo) -{ - if (!m_takedamage) - return 0; - - CTakeDamageInfo info = inputInfo; - - if (m_bActive == false) - info.ScaleDamage(0.1f); - - // If attacker can't do at least the min required damage to us, don't take any damage from them - if (info.GetDamage() < m_iMinHealthDmg) - return 0; - - m_iHealth -= info.GetDamage(); - - if (m_iHealth <= 0) - { - m_iHealth = 0; - m_takedamage = DAMAGE_NO; - - RemoveFlag(FL_NPC); // why are they set in the first place??? - - // FIXME: This needs to throw a ragdoll gib or something other than animating the retraction -- jdw - - ExplosionCreate(GetAbsOrigin(), GetLocalAngles(), this, 100, 100, false); - SetThink(&CNPC_CombineCamera::DeathThink); - - StopSound("Alert"); - - m_OnDamaged.FireOutput(info.GetInflictor(), this); - - SetNextThink( gpGlobals->curtime + 0.1f ); - - return 0; - } - - return 1; -} - - -//----------------------------------------------------------------------------- -// Purpose: Deploy and start searching for targets. -//----------------------------------------------------------------------------- -void CNPC_CombineCamera::Deploy() -{ - m_vecGoalAngles = GetAbsAngles(); - - SetNextThink( gpGlobals->curtime ); - - SetEyeState(CAMERA_EYE_IDLE); - m_bActive = true; - - SetHeight(COMBINE_CAMERA_DEPLOY_HEIGHT); - SetIdealActivity((Activity) ACT_COMBINE_CAMERA_OPEN_IDLE); - m_flPlaybackRate = 0; - SetThink(&CNPC_CombineCamera::SearchThink); - - EmitSound("NPC_CombineCamera.Move"); -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns the speed at which the camera can face a target -//----------------------------------------------------------------------------- -float CNPC_CombineCamera::MaxYawSpeed() -{ - if (m_hEnemyTarget) - return 180.0f; - - return 60.0f; -} - - -//----------------------------------------------------------------------------- -// Purpose: Causes the camera to face its desired angles -//----------------------------------------------------------------------------- -bool CNPC_CombineCamera::UpdateFacing() -{ - bool bMoved = false; - matrix3x4_t localToWorld; - - GetAttachment(LookupAttachment("eyes"), localToWorld); - - Vector vecGoalDir; - AngleVectors(m_vecGoalAngles, &vecGoalDir ); - - Vector vecGoalLocalDir; - VectorIRotate(vecGoalDir, localToWorld, vecGoalLocalDir); - - QAngle vecGoalLocalAngles; - VectorAngles(vecGoalLocalDir, vecGoalLocalAngles); - - // Update pitch - float flDiff = AngleNormalize(UTIL_ApproachAngle( vecGoalLocalAngles.x, 0.0, 0.1f * MaxYawSpeed())); - - int iPose = LookupPoseParameter(COMBINE_CAMERA_BC_PITCH); - SetPoseParameter(iPose, GetPoseParameter(iPose) + (flDiff / 1.5f)); - - if (fabs(flDiff) > 0.1f) - { - bMoved = true; - } - - // Update yaw - flDiff = AngleNormalize(UTIL_ApproachAngle( vecGoalLocalAngles.y, 0.0, 0.1f * MaxYawSpeed())); - - iPose = LookupPoseParameter(COMBINE_CAMERA_BC_YAW); - SetPoseParameter(iPose, GetPoseParameter(iPose) + (flDiff / 1.5f)); - - if (fabs(flDiff) > 0.1f) - { - bMoved = true; - } - - if (bMoved && (m_flMoveSoundTime < gpGlobals->curtime)) - { - EmitSound("NPC_CombineCamera.Move"); - m_flMoveSoundTime = gpGlobals->curtime + CAMERA_MOVE_INTERVAL; - } - - // You're going to make decisions based on this info. So bump the bone cache after you calculate everything - InvalidateBoneCache(); - - return bMoved; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Vector CNPC_CombineCamera::HeadDirection2D() -{ - Vector vecMuzzle, vecMuzzleDir; - - GetAttachment("eyes", vecMuzzle, &vecMuzzleDir ); - vecMuzzleDir.z = 0; - VectorNormalize(vecMuzzleDir); - - return vecMuzzleDir; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEntity - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_CombineCamera::FVisible(CBaseEntity *pEntity, int traceMask, CBaseEntity **ppBlocker) -{ - CBaseEntity *pHitEntity = NULL; - if ( BaseClass::FVisible( pEntity, traceMask, &pHitEntity ) ) - return true; - - // If we hit something that's okay to hit anyway, still fire - if ( pHitEntity && pHitEntity->MyCombatCharacterPointer() ) - { - if (IRelationType(pHitEntity) == D_HT) - return true; - } - - if (ppBlocker) - { - *ppBlocker = pHitEntity; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Enemies are only valid if they're inside our radius -//----------------------------------------------------------------------------- -bool CNPC_CombineCamera::IsValidEnemy( CBaseEntity *pEnemy ) -{ - Vector vecDelta = pEnemy->GetAbsOrigin() - GetAbsOrigin(); - float flDist = vecDelta.Length(); - if ( (flDist > m_nOuterRadius) || !FInViewCone(pEnemy) ) - return false; - - return BaseClass::IsValidEnemy( pEnemy ); -} - -//----------------------------------------------------------------------------- -// Purpose: Called when we have no scripted target. Looks for new enemies to track. -//----------------------------------------------------------------------------- -CBaseEntity *CNPC_CombineCamera::MaintainEnemy() -{ - if (HasSpawnFlags(SF_COMBINE_CAMERA_IGNOREENEMIES)) - return NULL; - - GetSenses()->Look(m_nOuterRadius); - - CBaseEntity *pEnemy = BestEnemy(); - if (pEnemy) - { - // See if our best enemy is too far away to care about. - Vector vecDelta = pEnemy->GetAbsOrigin() - GetAbsOrigin(); - float flDist = vecDelta.Length(); - if (flDist < m_nOuterRadius) - { - if (FInViewCone(pEnemy)) - { - // dvs: HACK: for checking multiple view cones - float flSaveFieldOfView = m_flFieldOfView; - m_flFieldOfView = CAMERA_FOV_NARROW; - - // Is the target visible? - bool bVisible = FVisible(pEnemy); - m_flFieldOfView = flSaveFieldOfView; - if ( bVisible ) - return pEnemy; - } - } - } - - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Think while actively tracking a target. -//----------------------------------------------------------------------------- -void CNPC_CombineCamera::ActiveThink() -{ - // Allow descended classes a chance to do something before the think function - if (PreThink(CAMERA_ACTIVE)) - return; - - // No active target, look for suspicious characters. - CBaseEntity *pTarget = MaintainEnemy(); - if ( !pTarget ) - { - // Nobody suspicious. Go back to being idle. - m_hEnemyTarget = NULL; - EmitSound("NPC_CombineCamera.BecomeIdle"); - SetAngry(false); - SetThink(&CNPC_CombineCamera::SearchThink); - SetNextThink( gpGlobals->curtime ); - return; - } - - // Examine the target until it reaches our inner radius - if ( pTarget != m_hEnemyTarget ) - { - Vector vecDelta = pTarget->GetAbsOrigin() - GetAbsOrigin(); - float flDist = vecDelta.Length(); - if ( (flDist < m_nInnerRadius) && FInViewCone(pTarget) ) - { - m_OnFoundEnemy.Set(pTarget, pTarget, this); - - // If it's a citizen, it's ok. If it's the player, it's not ok. - if ( pTarget->IsPlayer() ) - { - SetEyeState(CAMERA_EYE_FOUND_TARGET); - - if (HasSpawnFlags(SF_COMBINE_CAMERA_BECOMEANGRY)) - { - SetAngry(true); - } - else - { - EmitSound("NPC_CombineCamera.Active"); - } - - m_OnFoundPlayer.Set(pTarget, pTarget, this); - m_hEnemyTarget = pTarget; - } - else - { - SetEyeState(CAMERA_EYE_HAPPY); - m_flEyeHappyTime = gpGlobals->curtime + 2.0; - - // Now forget about this target forever - AddEntityRelationship( pTarget, D_NU, 99 ); - } - } - else - { - // If we get angry automatically, we get un-angry automatically - if ( HasSpawnFlags(SF_COMBINE_CAMERA_BECOMEANGRY) && m_bAngry ) - { - SetAngry(false); - } - m_hEnemyTarget = NULL; - - // We don't quite see this guy, but we sense him. - SetEyeState(CAMERA_EYE_SEEKING_TARGET); - } - } - - // Update our think time - SetNextThink( gpGlobals->curtime + 0.1f ); - - TrackTarget(pTarget); - MaintainEye(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pTarget - -//----------------------------------------------------------------------------- -void CNPC_CombineCamera::TrackTarget( CBaseEntity *pTarget ) -{ - if (!pTarget) - return; - - // Calculate direction to target - Vector vecMid = EyePosition(); - Vector vecMidTarget = pTarget->BodyTarget(vecMid); - Vector vecDirToTarget = vecMidTarget - vecMid; - - // We want to look at the target's eyes so we don't jitter - Vector vecDirToTargetEyes = pTarget->WorldSpaceCenter() - vecMid; - VectorNormalize(vecDirToTargetEyes); - - QAngle vecAnglesToTarget; - VectorAngles(vecDirToTargetEyes, vecAnglesToTarget); - - // Draw debug info - if (g_debug_combine_camera.GetBool()) - { - NDebugOverlay::Cross3D(vecMid, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05); - NDebugOverlay::Cross3D(pTarget->WorldSpaceCenter(), -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05); - NDebugOverlay::Line(vecMid, pTarget->WorldSpaceCenter(), 0, 255, 0, false, 0.05); - - NDebugOverlay::Cross3D(vecMid, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05); - NDebugOverlay::Cross3D(vecMidTarget, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05); - NDebugOverlay::Line(vecMid, vecMidTarget, 0, 255, 0, false, 0.05f); - } - - Vector vecMuzzle, vecMuzzleDir; - QAngle vecMuzzleAng; - - GetAttachment("eyes", vecMuzzle, &vecMuzzleDir); - - SetIdealActivity((Activity) ACT_COMBINE_CAMERA_OPEN_IDLE); - - m_vecGoalAngles.y = vecAnglesToTarget.y; - m_vecGoalAngles.x = vecAnglesToTarget.x; - - // Turn to face - UpdateFacing(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineCamera::MaintainEye() -{ - // Angry cameras take a few pictures of their target. - if ((m_bAngry) && (m_nClickCount <= 3)) - { - if ((m_flClickTime != 0) && (m_flClickTime < gpGlobals->curtime)) - { - m_pEyeFlash->SetScale(1.0); - m_pEyeFlash->SetBrightness(255); - m_pEyeFlash->SetColor(255,255,255); - - EmitSound("NPC_CombineCamera.Click"); - - m_flTurnOffEyeFlashTime = gpGlobals->curtime + 0.1; - m_flClickTime = gpGlobals->curtime + CAMERA_CLICK_INTERVAL; - } - else if ((m_flTurnOffEyeFlashTime != 0) && (m_flTurnOffEyeFlashTime < gpGlobals->curtime)) - { - m_flTurnOffEyeFlashTime = 0; - m_pEyeFlash->SetBrightness( 0, 0.25f ); - m_nClickCount++; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Target doesn't exist or has eluded us, so search for one -//----------------------------------------------------------------------------- -void CNPC_CombineCamera::SearchThink() -{ - // Allow descended classes a chance to do something before the think function - if (PreThink(CAMERA_SEARCHING)) - return; - - SetNextThink( gpGlobals->curtime + 0.05f ); - - SetIdealActivity((Activity) ACT_COMBINE_CAMERA_OPEN_IDLE); - - if ( !GetTarget() ) - { - // Try to acquire a new target - if (MaintainEnemy()) - { - SetThink( &CNPC_CombineCamera::ActiveThink ); - return; - } - } - - // Display that we're scanning - m_vecGoalAngles.x = 15.0f; - m_vecGoalAngles.y = GetAbsAngles().y + (sin(gpGlobals->curtime * 2.0f) * 45.0f); - - // Turn and ping - UpdateFacing(); - Ping(); - - SetEyeState(CAMERA_EYE_IDLE); -} - -//----------------------------------------------------------------------------- -// Purpose: Allows a generic think function before the others are called -// Input : state - which state the camera is currently in -//----------------------------------------------------------------------------- -bool CNPC_CombineCamera::PreThink(cameraState_e state) -{ - CheckPVSCondition(); - - MaintainActivity(); - StudioFrameAdvance(); - - // If we're disabled, shut down - if ( !m_bEnabled ) - { - SetIdealActivity((Activity) ACT_COMBINE_CAMERA_CLOSED_IDLE); - SetNextThink( gpGlobals->curtime + 0.1f ); - return true; - } - - // Do not interrupt current think function - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Sets the state of the glowing eye attached to the camera -// Input : state - state the eye should be in -//----------------------------------------------------------------------------- -void CNPC_CombineCamera::SetEyeState(eyeState_t state) -{ - // Must have a valid eye to affect - if (m_pEyeGlow == NULL) - return; - - if (m_bAngry) - { - m_pEyeGlow->SetColor(255, 0, 0); - m_pEyeGlow->SetBrightness(164, 0.1f); - m_pEyeGlow->SetScale(0.4f, 0.1f); - return; - } - - // If we're switching to IDLE, and we're still happy, use happy instead - if ( state == CAMERA_EYE_IDLE && m_flEyeHappyTime > gpGlobals->curtime ) - { - state = CAMERA_EYE_HAPPY; - } - - // Set the state - switch (state) - { - default: - case CAMERA_EYE_IDLE: - { - m_pEyeGlow->SetColor(0, 255, 0); - m_pEyeGlow->SetBrightness(164, 0.1f); - m_pEyeGlow->SetScale(0.4f, 0.1f); - break; - } - - case CAMERA_EYE_SEEKING_TARGET: - { - // Toggle our state - m_bBlinkState = !m_bBlinkState; - - // Amber - m_pEyeGlow->SetColor(255, 128, 0); - - if (m_bBlinkState) - { - // Fade up and scale up - m_pEyeGlow->SetScale(0.25f, 0.1f); - m_pEyeGlow->SetBrightness(164, 0.1f); - } - else - { - // Fade down and scale down - m_pEyeGlow->SetScale(0.2f, 0.1f); - m_pEyeGlow->SetBrightness(64, 0.1f); - } - - break; - } - - case CAMERA_EYE_FOUND_TARGET: - { - if (!m_bAngry) - { - // Amber - m_pEyeGlow->SetColor(255, 128, 0); - - // Fade up and scale up - m_pEyeGlow->SetScale(0.45f, 0.1f); - m_pEyeGlow->SetBrightness(220, 0.1f); - } - else - { - m_pEyeGlow->SetColor(255, 0, 0); - m_pEyeGlow->SetBrightness(164, 0.1f); - m_pEyeGlow->SetScale(0.4f, 0.1f); - } - - break; - } - - case CAMERA_EYE_DORMANT: // Fade out and scale down - { - m_pEyeGlow->SetColor(0, 255, 0); - m_pEyeGlow->SetScale(0.1f, 0.5f); - m_pEyeGlow->SetBrightness(64, 0.5f); - break; - } - - case CAMERA_EYE_DEAD: // Fade out slowly - { - m_pEyeGlow->SetColor(255, 0, 0); - m_pEyeGlow->SetScale(0.1f, 3.0f); - m_pEyeGlow->SetBrightness(0, 3.0f); - break; - } - - case CAMERA_EYE_DISABLED: - { - m_pEyeGlow->SetColor(0, 255, 0); - m_pEyeGlow->SetScale(0.1f, 1.0f); - m_pEyeGlow->SetBrightness(0, 1.0f); - break; - } - - case CAMERA_EYE_HAPPY: - { - m_pEyeGlow->SetColor(0, 255, 0); - m_pEyeGlow->SetBrightness(255, 0.1f); - m_pEyeGlow->SetScale(0.5f, 0.1f); - break; - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Make a pinging noise so the player knows where we are -//----------------------------------------------------------------------------- -void CNPC_CombineCamera::Ping() -{ - // See if it's time to ping again - if (m_flPingTime > gpGlobals->curtime) - return; - - // Ping! - EmitSound("NPC_CombineCamera.Ping"); - m_flPingTime = gpGlobals->curtime + COMBINE_CAMERA_PING_TIME; -} - - -//----------------------------------------------------------------------------- -// Purpose: Toggle the camera's state -//----------------------------------------------------------------------------- -void CNPC_CombineCamera::Toggle() -{ - if (m_bEnabled) - { - Disable(); - } - else - { - Enable(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Enable the camera and deploy -//----------------------------------------------------------------------------- -void CNPC_CombineCamera::Enable() -{ - m_bEnabled = true; - SetThink(&CNPC_CombineCamera::Deploy); - SetNextThink( gpGlobals->curtime + 0.05f ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Retire the camera until enabled again -//----------------------------------------------------------------------------- -void CNPC_CombineCamera::Disable() -{ - m_bEnabled = false; - m_hEnemyTarget = NULL; - SetNextThink( gpGlobals->curtime + 0.1f ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Toggle the camera's state via input function -//----------------------------------------------------------------------------- -void CNPC_CombineCamera::InputToggle(inputdata_t &inputdata) -{ - Toggle(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler to enable the camera. -//----------------------------------------------------------------------------- -void CNPC_CombineCamera::InputEnable(inputdata_t &inputdata) -{ - Enable(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler to disable the camera. -//----------------------------------------------------------------------------- -void CNPC_CombineCamera::InputDisable(inputdata_t &inputdata) -{ - Disable(); -} - - -//----------------------------------------------------------------------------- -// Purpose: When we become angry, we make an angry sound and start photographing -// whatever target we are tracking. -//----------------------------------------------------------------------------- -void CNPC_CombineCamera::SetAngry(bool bAngry) -{ - if ((bAngry) && (!m_bAngry)) - { - m_bAngry = true; - m_nClickCount = 0; - m_flClickTime = gpGlobals->curtime + 0.4; - EmitSound("NPC_CombineCamera.Angry"); - SetEyeState(CAMERA_EYE_ANGRY); - } - else if ((!bAngry) && (m_bAngry)) - { - m_bAngry = false; - - // make sure the flash is off (we might be in mid-flash) - m_pEyeFlash->SetBrightness(0); - SetEyeState(GetTarget() ? CAMERA_EYE_SEEKING_TARGET : CAMERA_EYE_IDLE); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineCamera::InputSetAngry(inputdata_t &inputdata) -{ - SetAngry(true); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineCamera::InputSetIdle(inputdata_t &inputdata) -{ - SetAngry(false); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineCamera::DeathThink() -{ - if (PreThink(CAMERA_DEAD)) - return; - - // Level out our angles - m_vecGoalAngles = GetAbsAngles(); - SetNextThink( gpGlobals->curtime + 0.1f ); - - if (m_lifeState != LIFE_DEAD) - { - m_lifeState = LIFE_DEAD; - - EmitSound("NPC_CombineCamera.Die"); - - // lots of smoke - Vector pos; - CollisionProp()->RandomPointInBounds( vec3_origin, Vector( 1, 1, 1 ), &pos ); - - CBroadcastRecipientFilter filter; - - te->Smoke(filter, 0.0, &pos, g_sModelIndexSmoke, 2.5, 10); - - g_pEffects->Sparks(pos); - - SetActivity((Activity) ACT_COMBINE_CAMERA_CLOSE); - } - - StudioFrameAdvance(); - - if (IsActivityFinished() && (UpdateFacing() == false)) - { - SetHeight(COMBINE_CAMERA_RETRACT_HEIGHT); - - m_flPlaybackRate = 0; - SetThink(NULL); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : height - -//----------------------------------------------------------------------------- -void CNPC_CombineCamera::SetHeight(float height) -{ - Vector forward, right, up; - AngleVectors(GetLocalAngles(), &forward, &right, &up); - - Vector mins = (forward * -16.0f) + (right * -16.0f); - Vector maxs = (forward * 16.0f) + (right * 16.0f) + (up * -height); - - if (mins.x > maxs.x) - { - swap(mins.x, maxs.x); - } - - if (mins.y > maxs.y) - { - swap(mins.y, maxs.y); - } - - if (mins.z > maxs.z) - { - swap(mins.z, maxs.z); - } - - SetCollisionBounds(mins, maxs); - - UTIL_SetSize(this, mins, maxs); -} - - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -//----------------------------------------------------------------------------- -int CNPC_CombineCamera::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - - Q_snprintf( tempstr, sizeof( tempstr ),"Enemy : %s", m_hEnemyTarget ? m_hEnemyTarget->GetDebugName() : ""); - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineCamera::DrawDebugGeometryOverlays(void) -{ - // ------------------------------ - // Draw viewcone if selected - // ------------------------------ - if ((m_debugOverlays & OVERLAY_NPC_VIEWCONE_BIT)) - { - float flViewRange = acos(CAMERA_FOV_NARROW); - Vector vEyeDir = EyeDirection2D( ); - Vector vLeftDir, vRightDir; - float fSin, fCos; - SinCos( flViewRange, &fSin, &fCos ); - - vLeftDir.x = vEyeDir.x * fCos - vEyeDir.y * fSin; - vLeftDir.y = vEyeDir.x * fSin + vEyeDir.y * fCos; - vLeftDir.z = vEyeDir.z; - fSin = sin(-flViewRange); - fCos = cos(-flViewRange); - vRightDir.x = vEyeDir.x * fCos - vEyeDir.y * fSin; - vRightDir.y = vEyeDir.x * fSin + vEyeDir.y * fCos; - vRightDir.z = vEyeDir.z; - - NDebugOverlay::BoxDirection(EyePosition(), Vector(0,0,-40), Vector(200,0,40), vLeftDir, 255, 255, 0, 50, 0 ); - NDebugOverlay::BoxDirection(EyePosition(), Vector(0,0,-40), Vector(200,0,40), vRightDir, 255, 255, 0, 50, 0 ); - NDebugOverlay::Box(EyePosition(), -Vector(2,2,2), Vector(2,2,2), 255, 255, 0, 128, 0 ); - } - - BaseClass::DrawDebugGeometryOverlays(); -} diff --git a/game/server/hl2/npc_combinedropship.cpp b/game/server/hl2/npc_combinedropship.cpp deleted file mode 100644 index 579a5fe9f..000000000 --- a/game/server/hl2/npc_combinedropship.cpp +++ /dev/null @@ -1,3007 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Large vehicle what delivers combine troops. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ai_default.h" -#include "ai_basenpc.h" -#include "soundenvelope.h" -#include "cbasehelicopter.h" -#include "ai_schedule.h" -#include "engine/IEngineSound.h" -#include "smoke_trail.h" -#include "IEffects.h" -#include "props.h" -#include "TemplateEntities.h" -#include "baseanimating.h" -#include "ai_senses.h" -#include "entitylist.h" -#include "ammodef.h" -#include "ndebugoverlay.h" -#include "npc_combines.h" -#include "soundent.h" -#include "mapentities.h" -#include "npc_rollermine.h" -#include "scripted.h" -#include "explode.h" -#include "gib.h" -#include "EntityFlame.h" -#include "entityblocker.h" -#include "eventqueue.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// Spawnflags -#define SF_DROPSHIP_WAIT_FOR_DROPOFF_INPUT ( 1 << 15 ) - -#define DROPSHIP_ACCEL_RATE 300 - -// Timers -#define DROPSHIP_LANDING_HOVER_TIME 5 // Time to spend on the ground if we have no troops to drop -#define DROPSHIP_TIME_BETWEEN_MINES 0.5f - -// Special actions -#define DROPSHIP_DEFAULT_SOLDIERS 4 -#define DROPSHIP_MAX_SOLDIERS 6 - -// Movement -#define DROPSHIP_BUFF_TIME 0.3f -#define DROPSHIP_MAX_LAND_TILT 2.5f -#define DROPSHIP_CONTAINER_HEIGHT 130.0f -#define DROPSHIP_MAX_SPEED (60 * 17.6) // 120 miles per hour. - -// Pathing data -#define DROPSHIP_LEAD_DISTANCE 800.0f -#define DROPSHIP_MIN_CHASE_DIST_DIFF 128.0f // Distance threshold used to determine when a target has moved enough to update our navigation to it -#define DROPSHIP_AVOID_DIST 256.0f -#define DROPSHIP_ARRIVE_DIST 128.0f - -#define CRATE_BBOX_MIN (Vector( -100, -80, -60 )) -#define CRATE_BBOX_MAX (Vector( 100, 80, 80 )) - -// Size -// With crate -#define DROPSHIP_BBOX_CRATE_MIN (-Vector(40,40,60)) -#define DROPSHIP_BBOX_CRATE_MAX (Vector(40,40,40)) -// Without crate -#define DROPSHIP_BBOX_MIN (-Vector(40,40,0)) -#define DROPSHIP_BBOX_MAX (Vector(40,40,40)) - -// Container gun -#define DROPSHIP_GUN_SPEED 10 // Rotation speed - -#define DROPSHIP_CRATE_ROCKET_HITS 4 - -enum DROP_STATES -{ - DROP_IDLE = 0, - DROP_NEXT, -}; - -enum CRATE_TYPES -{ - CRATE_JEEP = -3, - CRATE_APC = -2, - CRATE_STRIDER = -1, - CRATE_ROLLER_HOPPER, - CRATE_SOLDIER, - CRATE_NONE, -}; - -ConVar g_debug_dropship( "g_debug_dropship", "0" ); -ConVar sk_dropship_container_health( "sk_dropship_container_health", "750" ); -ConVar sk_npc_dmg_dropship( "sk_npc_dmg_dropship","5", FCVAR_NONE, "Dropship container cannon damage." ); - -//===================================== -// Animation Events -//===================================== -#define AE_DROPSHIP_RAMP_OPEN 1 // the tailgate is open. - -//===================================== -// Custom activities -//===================================== -// Without Cargo -Activity ACT_DROPSHIP_FLY_IDLE; // Flying. Vertical aspect -Activity ACT_DROPSHIP_FLY_IDLE_EXAGG; // Exaggerated version of the flying idle -// With Cargo -Activity ACT_DROPSHIP_FLY_IDLE_CARGO; // Flying. Vertical aspect -Activity ACT_DROPSHIP_DESCEND_IDLE; // waiting to touchdown -Activity ACT_DROPSHIP_DEPLOY_IDLE; // idle on the ground with door open. Troops are leaving. -Activity ACT_DROPSHIP_LIFTOFF; // transition back to FLY IDLE - -enum LandingState_t -{ - LANDING_NO = 0, - - // Dropoff - LANDING_LEVEL_OUT, // Heading to a point above the dropoff point - LANDING_DESCEND, // Descending from to the dropoff point - LANDING_TOUCHDOWN, - LANDING_UNLOADING, - LANDING_UNLOADED, - LANDING_LIFTOFF, - - // Pickup - LANDING_SWOOPING, // Swooping down to the target - - // Hovering, which we're saying is a type of landing since there's so much landing code to leverage - LANDING_START_HOVER, - LANDING_HOVER_LEVEL_OUT, - LANDING_HOVER_DESCEND, - LANDING_HOVER_TOUCHDOWN, - LANDING_END_HOVER, -}; - - -#define DROPSHIP_NEAR_SOUND_MIN_DISTANCE 1000 -#define DROPSHIP_NEAR_SOUND_MAX_DISTANCE 2500 -#define DROPSHIP_GROUND_WASH_MIN_ALTITUDE 100.0f -#define DROPSHIP_GROUND_WASH_MAX_ALTITUDE 750.0f - - - -//============================================================================= -// The combine dropship container -//============================================================================= -#define DROPSHIP_CONTAINER_MODEL "models/combine_dropship_container.mdl" - -#define DROPSHIP_CONTAINER_MAX_CHUNKS 3 -static const char *s_pChunkModelName[DROPSHIP_CONTAINER_MAX_CHUNKS] = -{ - "models/gibs/helicopter_brokenpiece_01.mdl", - "models/gibs/helicopter_brokenpiece_02.mdl", - "models/gibs/helicopter_brokenpiece_03.mdl", -}; - -#define DROPSHIP_CONTAINER_MAX_GIBS 1 -static const char *s_pGibModelName[DROPSHIP_CONTAINER_MAX_GIBS] = -{ - "models/combine_dropship_container.mdl", -}; - -class CCombineDropshipContainer : public CPhysicsProp -{ - DECLARE_CLASS( CCombineDropshipContainer, CPhysicsProp ); - DECLARE_DATADESC(); - -public: - void Precache(); - virtual void Spawn(); - virtual bool OverridePropdata( void ); - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - virtual void Event_Killed( const CTakeDamageInfo &info ); - -private: - enum - { - MAX_SMOKE_TRAILS = 4, - MAX_EXPLOSIONS = 4, - }; - - // Should we trigger a damage effect? - bool ShouldTriggerDamageEffect( int nPrevHealth, int nEffectCount ) const; - - // Add a smoke trail since we've taken more damage - void AddSmokeTrail( const Vector &vecPos ); - - // Pow! - void ThrowFlamingGib(); - - // Create a corpse - void CreateCorpse(); - -private: - int m_nSmokeTrailCount; - EHANDLE m_hLastInflictor; - float m_flLastHitTime; -}; - -//============================================================================= -// The combine dropship -//============================================================================= -class CNPC_CombineDropship : public CBaseHelicopter -{ - DECLARE_CLASS( CNPC_CombineDropship, CBaseHelicopter ); - -public: - ~CNPC_CombineDropship(); - - // Setup - void Spawn( void ); - void Precache( void ); - - void Activate( void ); - - // Thinking/init - void InitializeRotorSound( void ); - void StopLoopingSounds(); - void PrescheduleThink( void ); - - // Flight/sound - void Hunt( void ); - void Flight( void ); - float GetAltitude( void ); - void DoRotorWash( void ); - void UpdateRotorSoundPitch( int iPitch ); - void UpdatePickupNavigation( void ); - void UpdateLandTargetNavigation( void ); - void CalculateSoldierCount( int iSoldiers ); - - // Updates the facing direction - virtual void UpdateFacingDirection(); - - // Combat - void GatherEnemyConditions( CBaseEntity *pEnemy ); - void DoCombatStuff( void ); - void SpawnTroop( void ); - void DropMine( void ); - void UpdateContainerGunFacing( Vector &vecMuzzle, Vector &vecToTarget, Vector &vecAimDir, float *flTargetRange ); - bool FireCannonRound( void ); - void DoImpactEffect( trace_t &tr, int nDamageType ); - void StartCannon( void ); - void StopCannon( void ); - void MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ); - int OnTakeDamage_Alive( const CTakeDamageInfo &inputInfo ); - - // Input handlers. - void InputLandLeave( inputdata_t &inputdata ); - void InputLandTake( inputdata_t &inputdata ); - void InputSetLandTarget( inputdata_t &inputdata ); - void InputDropMines( inputdata_t &inputdata ); - void InputDropStrider( inputdata_t &inputdata ); - void InputDropAPC( inputdata_t &inputdata ); - - void InputPickup( inputdata_t &inputdata ); - void InputSetGunRange( inputdata_t &inputdata ); - void InputNPCFinishDustoff( inputdata_t &inputdata ); - void InputStopWaitingForDropoff( inputdata_t &inputdata ); - - void InputHover( inputdata_t &inputdata ); - - // From AI_TrackPather - virtual void InputFlyToPathTrack( inputdata_t &inputdata ); - - Vector GetDropoffFinishPosition( Vector vecOrigin, CAI_BaseNPC *pNPC, Vector vecMins, Vector vecMaxs ); - void LandCommon( bool bHover = false ); - - Class_T Classify( void ) { return CLASS_COMBINE_GUNSHIP; } - - // Drop the soldier container - void DropSoldierContainer( ); - - // Sounds - virtual void UpdateRotorWashVolume(); - -private: - void SetLandingState( LandingState_t landingState ); - LandingState_t GetLandingState() const { return (LandingState_t)m_iLandState; } - bool IsHovering(); - void UpdateGroundRotorWashSound( float flAltitude ); - void UpdateRotorWashVolume( CSoundPatch *pRotorSound, float flVolume, float flDeltaTime ); - -private: - // Timers - float m_flTimeTakeOff; - float m_flNextTroopSpawnAttempt; - float m_flDropDelay; // delta between each mine - float m_flTimeNextAttack; - float m_flLastTime; - - // States and counters - int m_iMineCount; // index for current mine # being deployed - int m_totalMinesToDrop; // total # of mines to drop as a group (based upon triggered input) - int m_soldiersToDrop; - int m_iDropState; - int m_iLandState; - float m_engineThrust; // for tracking sound volume/pitch - float m_existPitch; - float m_existRoll; - bool m_bDropMines; // signal to drop mines - bool m_bIsFiring; - int m_iBurstRounds; - bool m_leaveCrate; - bool m_bHasDroppedOff; - int m_iCrateType; - float m_flLandingSpeed; - float m_flGunRange; - bool m_bInvulnerable; - - QAngle m_vecAngAcceleration; - - // Misc Vars - CHandle m_hContainer; - EHANDLE m_hPickupTarget; - int m_iContainerMoveType; - bool m_bWaitForDropoffInput; - - DECLARE_DATADESC(); - DEFINE_CUSTOM_AI; - - EHANDLE m_hLandTarget; - string_t m_iszLandTarget; - - string_t m_iszAPCVehicleName; - - // Templates for soldier's dropped off - string_t m_sNPCTemplate[ DROPSHIP_MAX_SOLDIERS ]; - string_t m_sNPCTemplateData[ DROPSHIP_MAX_SOLDIERS ]; - string_t m_sDustoffPoints[ DROPSHIP_MAX_SOLDIERS ]; - int m_iCurrentTroopExiting; - EHANDLE m_hLastTroopToLeave; - - // Template for rollermines dropped by this dropship - string_t m_sRollermineTemplate; - string_t m_sRollermineTemplateData; - - // Cached attachment points - int m_iMuzzleAttachment; - int m_iMachineGunBaseAttachment; - int m_iMachineGunRefAttachment; - int m_iAttachmentTroopDeploy; - int m_iAttachmentDeployStart; - - // Sounds - CSoundPatch *m_pCannonSound; - CSoundPatch *m_pRotorOnGroundSound; - CSoundPatch *m_pDescendingWarningSound; - CSoundPatch *m_pNearRotorSound; - - // Outputs - COutputEvent m_OnFinishedDropoff; - COutputEvent m_OnFinishedPickup; - - COutputFloat m_OnContainerShotDownBeforeDropoff; - COutputEvent m_OnContainerShotDownAfterDropoff; - -protected: - // Because the combine dropship is a leaf class, we can use - // static variables to store this information, and save some memory. - // Should the dropship end up having inheritors, their activate may - // stomp these numbers, in which case you should make these ordinary members - // again. - static int m_poseBody_Accel, m_poseBody_Sway, m_poseCargo_Body_Accel, m_poseCargo_Body_Sway, - m_poseWeapon_Pitch, m_poseWeapon_Yaw; - static bool m_sbStaticPoseParamsLoaded; - virtual void PopulatePoseParameters( void ); -}; - -bool CNPC_CombineDropship::m_sbStaticPoseParamsLoaded = false; - -int CNPC_CombineDropship::m_poseBody_Accel = 0; -int CNPC_CombineDropship::m_poseBody_Sway = 0; -int CNPC_CombineDropship::m_poseCargo_Body_Accel = 0; -int CNPC_CombineDropship::m_poseCargo_Body_Sway = 0; -int CNPC_CombineDropship::m_poseWeapon_Pitch = 0; -int CNPC_CombineDropship::m_poseWeapon_Yaw = 0; - -//----------------------------------------------------------------------------- -// Purpose: Cache whatever pose parameters we intend to use -//----------------------------------------------------------------------------- -void CNPC_CombineDropship::PopulatePoseParameters( void ) -{ - if (!m_sbStaticPoseParamsLoaded) - { - m_poseBody_Accel = LookupPoseParameter( "body_accel"); - m_poseBody_Sway = LookupPoseParameter( "body_sway" ); - m_poseCargo_Body_Accel = LookupPoseParameter( "cargo_body_accel" ); - m_poseCargo_Body_Sway = LookupPoseParameter( "cargo_body_sway" ); - m_poseWeapon_Pitch = LookupPoseParameter( "weapon_pitch" ); - m_poseWeapon_Yaw = LookupPoseParameter( "weapon_yaw" ); - - m_sbStaticPoseParamsLoaded = true; - } - - BaseClass::PopulatePoseParameters(); -} - -//------------------------------------------------------------------------------ -// -// Combine Dropship Container implementation: -// -//------------------------------------------------------------------------------ -LINK_ENTITY_TO_CLASS( prop_dropship_container, CCombineDropshipContainer ) - -BEGIN_DATADESC( CCombineDropshipContainer ) - - DEFINE_FIELD( m_nSmokeTrailCount, FIELD_INTEGER ), - DEFINE_FIELD( m_hLastInflictor, FIELD_EHANDLE ), - DEFINE_FIELD( m_flLastHitTime, FIELD_TIME ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Precache -//----------------------------------------------------------------------------- -void CCombineDropshipContainer::Precache() -{ - PrecacheModel( DROPSHIP_CONTAINER_MODEL ); - - // Set this here to quiet base prop warnings - SetModel( DROPSHIP_CONTAINER_MODEL ); - - BaseClass::Precache(); - - int i; - for ( i = 0; i < DROPSHIP_CONTAINER_MAX_CHUNKS; ++i ) - { - PrecacheModel( s_pChunkModelName[i] ); - } - - for ( i = 0; i < DROPSHIP_CONTAINER_MAX_GIBS; ++i ) - { - PrecacheModel( s_pGibModelName[i] ); - } - - PropBreakablePrecacheAll( GetModelName() ); -} - - -//----------------------------------------------------------------------------- -// Spawn -//----------------------------------------------------------------------------- -void CCombineDropshipContainer::Spawn() -{ - // NOTE: Model must be set before spawn - SetModel( DROPSHIP_CONTAINER_MODEL ); - SetSolid( SOLID_VPHYSICS ); - - BaseClass::Spawn(); - -#ifdef _XBOX - AddEffects( EF_NOSHADOW ); -#endif //_XBOX - - m_iHealth = m_iMaxHealth = sk_dropship_container_health.GetFloat(); -} - - -//----------------------------------------------------------------------------- -// Allows us to use vphysics -//----------------------------------------------------------------------------- -bool CCombineDropshipContainer::OverridePropdata( void ) -{ - return true; -} - - -//----------------------------------------------------------------------------- -// Should we trigger a damage effect? -//----------------------------------------------------------------------------- -inline bool CCombineDropshipContainer::ShouldTriggerDamageEffect( int nPrevHealth, int nEffectCount ) const -{ - int nPrevRange = (int)( ((float)nPrevHealth / (float)GetMaxHealth()) * nEffectCount ); - int nRange = (int)( ((float)GetHealth() / (float)GetMaxHealth()) * nEffectCount ); - return ( nRange != nPrevRange ); -} - - -//----------------------------------------------------------------------------- -// Character killed (only fired once) -//----------------------------------------------------------------------------- -void CCombineDropshipContainer::CreateCorpse() -{ - m_lifeState = LIFE_DEAD; - - Vector vecNormalizedMins, vecNormalizedMaxs; - Vector vecAbsMins, vecAbsMaxs; - CollisionProp()->WorldSpaceAABB( &vecAbsMins, &vecAbsMaxs ); - CollisionProp()->WorldToNormalizedSpace( vecAbsMins, &vecNormalizedMins ); - CollisionProp()->WorldToNormalizedSpace( vecAbsMaxs, &vecNormalizedMaxs ); - - // Explode - Vector vecAbsPoint; - CPASFilter filter( GetAbsOrigin() ); - CollisionProp()->RandomPointInBounds( vecNormalizedMins, vecNormalizedMaxs, &vecAbsPoint); - te->Explosion( filter, 0.0f, &vecAbsPoint, g_sModelIndexFireball, - random->RandomInt( 4, 10 ), random->RandomInt( 8, 15 ), TE_EXPLFLAG_NOPARTICLES, 100, 0 ); - - // Break into chunks - Vector angVelocity; - QAngleToAngularImpulse( GetLocalAngularVelocity(), angVelocity ); - PropBreakableCreateAll( GetModelIndex(), VPhysicsGetObject(), GetAbsOrigin(), GetAbsAngles(), GetAbsVelocity(), angVelocity, 1.0, 250, COLLISION_GROUP_NPC, this ); - - // Create flaming gibs - int iChunks = random->RandomInt( 4, 6 ); - for ( int i = 0; i < iChunks; i++ ) - { - ThrowFlamingGib(); - } - - AddSolidFlags( FSOLID_NOT_SOLID ); - AddEffects( EF_NODRAW ); - UTIL_Remove( this ); -} - - -//----------------------------------------------------------------------------- -// Character killed (only fired once) -//----------------------------------------------------------------------------- -void CCombineDropshipContainer::ThrowFlamingGib( void ) -{ - Vector vecAbsMins, vecAbsMaxs; - CollisionProp()->WorldSpaceAABB( &vecAbsMins, &vecAbsMaxs ); - - Vector vecNormalizedMins, vecNormalizedMaxs; - CollisionProp()->WorldToNormalizedSpace( vecAbsMins, &vecNormalizedMins ); - CollisionProp()->WorldToNormalizedSpace( vecAbsMaxs, &vecNormalizedMaxs ); - - Vector vecAbsPoint; - CPASFilter filter( GetAbsOrigin() ); - CollisionProp()->RandomPointInBounds( vecNormalizedMins, vecNormalizedMaxs, &vecAbsPoint); - - // Throw a flaming, smoking chunk. - CGib *pChunk = CREATE_ENTITY( CGib, "gib" ); - pChunk->Spawn( "models/gibs/hgibs.mdl" ); - pChunk->SetBloodColor( DONT_BLEED ); - - QAngle vecSpawnAngles; - vecSpawnAngles.Random( -90, 90 ); - pChunk->SetAbsOrigin( vecAbsPoint ); - pChunk->SetAbsAngles( vecSpawnAngles ); - - int nGib = random->RandomInt( 0, DROPSHIP_CONTAINER_MAX_CHUNKS - 1 ); - pChunk->Spawn( s_pChunkModelName[nGib] ); - pChunk->SetOwnerEntity( this ); - pChunk->m_lifeTime = random->RandomFloat( 6.0f, 8.0f ); - pChunk->SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - IPhysicsObject *pPhysicsObject = pChunk->VPhysicsInitNormal( SOLID_VPHYSICS, pChunk->GetSolidFlags(), false ); - - // Set the velocity - if ( pPhysicsObject ) - { - pPhysicsObject->EnableMotion( true ); - Vector vecVelocity; - - QAngle angles; - angles.x = random->RandomFloat( -20, 20 ); - angles.y = random->RandomFloat( 0, 360 ); - angles.z = 0.0f; - AngleVectors( angles, &vecVelocity ); - - vecVelocity *= random->RandomFloat( 300, 900 ); - vecVelocity += GetAbsVelocity(); - - AngularImpulse angImpulse; - angImpulse = RandomAngularImpulse( -180, 180 ); - - pChunk->SetAbsVelocity( vecVelocity ); - pPhysicsObject->SetVelocity(&vecVelocity, &angImpulse ); - } - - CEntityFlame *pFlame = CEntityFlame::Create( pChunk, false ); - if ( pFlame != NULL ) - { - pFlame->SetLifetime( pChunk->m_lifeTime ); - } - - SmokeTrail *pSmokeTrail = SmokeTrail::CreateSmokeTrail(); - if( pSmokeTrail ) - { - pSmokeTrail->m_SpawnRate = 80; - pSmokeTrail->m_ParticleLifetime = 0.8f; - pSmokeTrail->m_StartColor.Init(0.3, 0.3, 0.3); - pSmokeTrail->m_EndColor.Init(0.5, 0.5, 0.5); - pSmokeTrail->m_StartSize = 10; - pSmokeTrail->m_EndSize = 40; - pSmokeTrail->m_SpawnRadius = 5; - pSmokeTrail->m_Opacity = 0.4; - pSmokeTrail->m_MinSpeed = 15; - pSmokeTrail->m_MaxSpeed = 25; - pSmokeTrail->SetLifetime( pChunk->m_lifeTime ); - pSmokeTrail->SetParent( pChunk, 0 ); - pSmokeTrail->SetLocalOrigin( vec3_origin ); - pSmokeTrail->SetMoveType( MOVETYPE_NONE ); - } -} - - -//----------------------------------------------------------------------------- -// Character killed (only fired once) -//----------------------------------------------------------------------------- -void CCombineDropshipContainer::Event_Killed( const CTakeDamageInfo &info ) -{ - if ( GetOwnerEntity() ) - { - CNPC_CombineDropship *pDropship = assert_cast(GetOwnerEntity() ); - pDropship->DropSoldierContainer(); - } - - CreateCorpse(); -} - - -//----------------------------------------------------------------------------- -// Damage effects -//----------------------------------------------------------------------------- -int CCombineDropshipContainer::OnTakeDamage( const CTakeDamageInfo &info ) -{ - if ( m_iHealth == 0 ) - return 0; - - // Airboat guns + explosive damage is all that can hurt it - if (( info.GetDamageType() & (DMG_BLAST | DMG_AIRBOAT) ) == 0 ) - return 0; - - CTakeDamageInfo dmgInfo = info; - - int nPrevHealth = GetHealth(); - - if ( info.GetDamageType() & DMG_BLAST ) - { - // This check is necessary to prevent double-counting of rocket damage - // from the blast hitting both the dropship + the container - if ( (info.GetInflictor() != m_hLastInflictor) || (gpGlobals->curtime != m_flLastHitTime) ) - { - m_iHealth -= (m_iMaxHealth / DROPSHIP_CRATE_ROCKET_HITS) + 1; - m_hLastInflictor = info.GetInflictor(); - m_flLastHitTime = gpGlobals->curtime; - } - } - else - { - m_iHealth -= dmgInfo.GetDamage(); - } - - if ( m_iHealth <= 0 ) - { - m_iHealth = 0; - Event_Killed( dmgInfo ); - return 0; - } - - // Spawn damage effects - if ( nPrevHealth != GetHealth() ) - { - if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_SMOKE_TRAILS ) ) - { - AddSmokeTrail( dmgInfo.GetDamagePosition() ); - } - - if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_EXPLOSIONS ) ) - { - ExplosionCreate( dmgInfo.GetDamagePosition(), vec3_angle, this, 1000, 500, - SF_ENVEXPLOSION_NODAMAGE | SF_ENVEXPLOSION_NOSPARKS | SF_ENVEXPLOSION_NODLIGHTS | SF_ENVEXPLOSION_NOSMOKE, 0 ); - UTIL_ScreenShake( dmgInfo.GetDamagePosition(), 25.0, 150.0, 1.0, 750.0f, SHAKE_START ); - - ThrowFlamingGib(); - } - } - - return 1; -} - - -//----------------------------------------------------------------------------- -// Add a smoke trail since we've taken more damage -//----------------------------------------------------------------------------- -void CCombineDropshipContainer::AddSmokeTrail( const Vector &vecPos ) -{ - // Start this trail out with a bang! - ExplosionCreate( vecPos, vec3_angle, this, 1000, 500, SF_ENVEXPLOSION_NODAMAGE | - SF_ENVEXPLOSION_NOSPARKS | SF_ENVEXPLOSION_NODLIGHTS | SF_ENVEXPLOSION_NOSMOKE, 0 ); - UTIL_ScreenShake( vecPos, 25.0, 150.0, 1.0, 750.0f, SHAKE_START ); - - if ( m_nSmokeTrailCount == MAX_SMOKE_TRAILS ) - return; - - SmokeTrail *pSmokeTrail = SmokeTrail::CreateSmokeTrail(); - if( !pSmokeTrail ) - return; - - // See if there's an attachment for this smoke trail - char buf[32]; - Q_snprintf( buf, 32, "damage%d", m_nSmokeTrailCount ); - int nAttachment = LookupAttachment( buf ); - - ++m_nSmokeTrailCount; - - pSmokeTrail->m_SpawnRate = 20; - pSmokeTrail->m_ParticleLifetime = 4.0f; - pSmokeTrail->m_StartColor.Init( 0.7f, 0.7f, 0.7f ); - pSmokeTrail->m_EndColor.Init( 0.6, 0.6, 0.6 ); - pSmokeTrail->m_StartSize = 15; - pSmokeTrail->m_EndSize = 50; - pSmokeTrail->m_SpawnRadius = 15; - pSmokeTrail->m_Opacity = 0.75f; - pSmokeTrail->m_MinSpeed = 10; - pSmokeTrail->m_MaxSpeed = 20; - pSmokeTrail->m_MinDirectedSpeed = 100.0f; - pSmokeTrail->m_MaxDirectedSpeed = 120.0f; - pSmokeTrail->SetLifetime( 5 ); - pSmokeTrail->SetParent( this, nAttachment ); - if ( nAttachment == 0 ) - { - pSmokeTrail->SetAbsOrigin( vecPos ); - } - else - { - pSmokeTrail->SetLocalOrigin( vec3_origin ); - } - - Vector vecForward( -1, 0, 0 ); - QAngle angles; - VectorAngles( vecForward, angles ); - pSmokeTrail->SetAbsAngles( angles ); - pSmokeTrail->SetMoveType( MOVETYPE_NONE ); -} - - -//------------------------------------------------------------------------------ -// -// Combine Dropship implementation: -// -//------------------------------------------------------------------------------ -LINK_ENTITY_TO_CLASS( npc_combinedropship, CNPC_CombineDropship ); - -BEGIN_DATADESC( CNPC_CombineDropship ) - - DEFINE_FIELD( m_flTimeTakeOff, FIELD_TIME ), - DEFINE_FIELD( m_flNextTroopSpawnAttempt, FIELD_TIME ), - DEFINE_FIELD( m_flDropDelay, FIELD_TIME ), - DEFINE_FIELD( m_flTimeNextAttack, FIELD_TIME ), - DEFINE_FIELD( m_flLastTime, FIELD_TIME ), - DEFINE_FIELD( m_iMineCount, FIELD_INTEGER ), - DEFINE_FIELD( m_totalMinesToDrop, FIELD_INTEGER ), - DEFINE_FIELD( m_soldiersToDrop, FIELD_INTEGER ), - DEFINE_FIELD( m_iDropState, FIELD_INTEGER ), - DEFINE_FIELD( m_bDropMines, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iLandState, FIELD_INTEGER ), - DEFINE_FIELD( m_engineThrust, FIELD_FLOAT ), - DEFINE_FIELD( m_bIsFiring, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iBurstRounds, FIELD_INTEGER ), - DEFINE_FIELD( m_existPitch, FIELD_FLOAT ), - DEFINE_FIELD( m_existRoll, FIELD_FLOAT ), - DEFINE_FIELD( m_leaveCrate, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_iCrateType, FIELD_INTEGER, "CrateType" ), - DEFINE_FIELD( m_flLandingSpeed, FIELD_FLOAT ), - DEFINE_KEYFIELD( m_flGunRange, FIELD_FLOAT, "GunRange" ), - DEFINE_FIELD( m_vecAngAcceleration,FIELD_VECTOR ), - DEFINE_FIELD( m_hContainer, FIELD_EHANDLE ), - DEFINE_FIELD( m_hPickupTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_iContainerMoveType, FIELD_INTEGER ), - DEFINE_FIELD( m_bWaitForDropoffInput, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hLandTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_bHasDroppedOff, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_bInvulnerable, FIELD_BOOLEAN, "Invulnerable" ), - DEFINE_KEYFIELD( m_iszLandTarget, FIELD_STRING, "LandTarget" ), - DEFINE_SOUNDPATCH( m_pRotorOnGroundSound ), - DEFINE_SOUNDPATCH( m_pDescendingWarningSound ), - DEFINE_SOUNDPATCH( m_pNearRotorSound ), - - DEFINE_KEYFIELD( m_iszAPCVehicleName, FIELD_STRING, "APCVehicleName" ), - - DEFINE_KEYFIELD( m_sRollermineTemplate, FIELD_STRING, "RollermineTemplate" ), - DEFINE_FIELD( m_sRollermineTemplateData, FIELD_STRING ), - - DEFINE_ARRAY( m_sNPCTemplateData, FIELD_STRING, DROPSHIP_MAX_SOLDIERS ), - DEFINE_KEYFIELD( m_sNPCTemplate[0], FIELD_STRING, "NPCTemplate" ), - DEFINE_KEYFIELD( m_sNPCTemplate[1], FIELD_STRING, "NPCTemplate2" ), - DEFINE_KEYFIELD( m_sNPCTemplate[2], FIELD_STRING, "NPCTemplate3" ), - DEFINE_KEYFIELD( m_sNPCTemplate[3], FIELD_STRING, "NPCTemplate4" ), - DEFINE_KEYFIELD( m_sNPCTemplate[4], FIELD_STRING, "NPCTemplate5" ), - DEFINE_KEYFIELD( m_sNPCTemplate[5], FIELD_STRING, "NPCTemplate6" ), - // Here to shut classcheck up - //DEFINE_ARRAY( m_sNPCTemplate, FIELD_STRING, DROPSHIP_MAX_SOLDIERS ), - //DEFINE_ARRAY( m_sDustoffPoints, FIELD_STRING, DROPSHIP_MAX_SOLDIERS ), - DEFINE_KEYFIELD( m_sDustoffPoints[0], FIELD_STRING, "Dustoff1" ), - DEFINE_KEYFIELD( m_sDustoffPoints[1], FIELD_STRING, "Dustoff2" ), - DEFINE_KEYFIELD( m_sDustoffPoints[2], FIELD_STRING, "Dustoff3" ), - DEFINE_KEYFIELD( m_sDustoffPoints[3], FIELD_STRING, "Dustoff4" ), - DEFINE_KEYFIELD( m_sDustoffPoints[4], FIELD_STRING, "Dustoff5" ), - DEFINE_KEYFIELD( m_sDustoffPoints[5], FIELD_STRING, "Dustoff6" ), - DEFINE_FIELD( m_iCurrentTroopExiting, FIELD_INTEGER ), - DEFINE_FIELD( m_hLastTroopToLeave, FIELD_EHANDLE ), - - DEFINE_FIELD( m_iMuzzleAttachment, FIELD_INTEGER ), - DEFINE_FIELD( m_iMachineGunBaseAttachment, FIELD_INTEGER ), - DEFINE_FIELD( m_iMachineGunRefAttachment, FIELD_INTEGER ), - DEFINE_FIELD( m_iAttachmentTroopDeploy, FIELD_INTEGER ), - DEFINE_FIELD( m_iAttachmentDeployStart , FIELD_INTEGER ), - - DEFINE_SOUNDPATCH( m_pCannonSound ), - - DEFINE_INPUTFUNC( FIELD_INTEGER, "LandLeaveCrate", InputLandLeave ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "LandTakeCrate", InputLandTake ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetLandTarget", InputSetLandTarget ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "DropMines", InputDropMines ), - DEFINE_INPUTFUNC( FIELD_VOID, "DropStrider", InputDropStrider ), - DEFINE_INPUTFUNC( FIELD_VOID, "DropAPC", InputDropAPC ), - DEFINE_INPUTFUNC( FIELD_STRING, "Pickup", InputPickup ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetGunRange", InputSetGunRange ), - DEFINE_INPUTFUNC( FIELD_STRING, "NPCFinishDustoff", InputNPCFinishDustoff ), - DEFINE_INPUTFUNC( FIELD_VOID, "StopWaitingForDropoff", InputStopWaitingForDropoff ), - DEFINE_INPUTFUNC( FIELD_STRING, "Hover", InputHover ), - DEFINE_INPUTFUNC( FIELD_STRING, "FlyToPathTrack", InputFlyToPathTrack ), - - DEFINE_OUTPUT( m_OnFinishedDropoff, "OnFinishedDropoff" ), - DEFINE_OUTPUT( m_OnFinishedPickup, "OnFinishedPickup" ), - - DEFINE_OUTPUT( m_OnContainerShotDownBeforeDropoff, "OnCrateShotDownBeforeDropoff" ), - DEFINE_OUTPUT( m_OnContainerShotDownAfterDropoff, "OnCrateShotDownAfterDropoff" ), - -END_DATADESC() - - -//------------------------------------------------------------------------------ -// Purpose : Destructor -//------------------------------------------------------------------------------ -CNPC_CombineDropship::~CNPC_CombineDropship(void) -{ - if ( m_hContainer ) - { - UTIL_Remove( m_hContainer ); // get rid of container - } -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::Spawn( void ) -{ - Precache( ); - SetModel( "models/combine_dropship.mdl" ); - -#ifdef _XBOX - AddEffects( EF_NOSHADOW ); -#endif //_XBOX - - InitPathingData( DROPSHIP_ARRIVE_DIST, DROPSHIP_MIN_CHASE_DIST_DIFF, DROPSHIP_AVOID_DIST ); - - m_iContainerMoveType = MOVETYPE_NONE; - m_iCurrentTroopExiting = 0; - m_bHasDroppedOff = false; - m_iMuzzleAttachment = -1; - m_iMachineGunBaseAttachment = -1; - m_iMachineGunRefAttachment = -1; - m_iAttachmentTroopDeploy = -1; - m_iAttachmentDeployStart = -1; - - // create the correct bin for the ship to carry - switch ( m_iCrateType ) - { - case CRATE_ROLLER_HOPPER: - break; - - case CRATE_SOLDIER: - m_hContainer = (CBaseAnimating*)CreateEntityByName( "prop_dropship_container" ); - if ( m_hContainer ) - { - m_hContainer->SetName( AllocPooledString("dropship_container") ); - m_hContainer->SetAbsOrigin( GetAbsOrigin() ); - m_hContainer->SetAbsAngles( GetAbsAngles() ); - m_hContainer->SetParent(this, 0); - m_hContainer->SetOwnerEntity(this); - m_hContainer->Spawn(); - - IPhysicsObject *pPhysicsObject = m_hContainer->VPhysicsGetObject(); - if ( pPhysicsObject ) - { - pPhysicsObject->SetShadow( 1e4, 1e4, false, false ); - pPhysicsObject->UpdateShadow( m_hContainer->GetAbsOrigin(), m_hContainer->GetAbsAngles(), false, 0 ); - } - - m_hContainer->SetMoveType( MOVETYPE_PUSH ); - m_hContainer->SetGroundEntity( NULL ); - - // Cache off container's attachment points - m_iAttachmentTroopDeploy = m_hContainer->LookupAttachment( "deploy_landpoint" ); - m_iAttachmentDeployStart = m_hContainer->LookupAttachment( "Deploy_Start" ); - m_iMuzzleAttachment = m_hContainer->LookupAttachment( "muzzle" ); - m_iMachineGunBaseAttachment = m_hContainer->LookupAttachment( "gun_base" ); - // NOTE: gun_ref must have the same position as gun_base, but rotates with the gun - m_iMachineGunRefAttachment = m_hContainer->LookupAttachment( "gun_ref" ); - } - break; - - case CRATE_STRIDER: - m_hContainer = (CBaseAnimating*)CreateEntityByName( "npc_strider" ); - m_hContainer->SetAbsOrigin( GetAbsOrigin() - Vector( 0, 0 , 100 ) ); - m_hContainer->SetAbsAngles( GetAbsAngles() ); - m_hContainer->SetParent(this, 0); - m_hContainer->SetOwnerEntity(this); - m_hContainer->Spawn(); - m_hContainer->SetAbsOrigin( GetAbsOrigin() - Vector( 0, 0 , 100 ) ); - break; - - case CRATE_APC: - { - m_soldiersToDrop = 0; - m_hContainer = (CBaseAnimating*)gEntList.FindEntityByName( NULL, m_iszAPCVehicleName ); - if ( !m_hContainer ) - { - Warning("Unable to find APC %s\n", STRING( m_iszAPCVehicleName ) ); - break; - } - - Vector apcPosition = GetAbsOrigin() - Vector( 0, 0 , 25 ); - QAngle apcAngles = GetAbsAngles(); - VMatrix mat, rot, result; - MatrixFromAngles( apcAngles, mat ); - MatrixBuildRotateZ( rot, -90 ); - MatrixMultiply( mat, rot, result ); - MatrixToAngles( result, apcAngles ); - - m_hContainer->Teleport( &apcPosition, &apcAngles, NULL ); - - m_iContainerMoveType = m_hContainer->GetMoveType(); - - IPhysicsObject *pPhysicsObject = m_hContainer->VPhysicsGetObject(); - if ( pPhysicsObject ) - { - pPhysicsObject->SetShadow( 1e4, 1e4, false, false ); - } - - m_hContainer->SetParent(this, 0); - m_hContainer->SetOwnerEntity(this); - m_hContainer->SetMoveType( MOVETYPE_PUSH ); - m_hContainer->SetGroundEntity( NULL ); - m_hContainer->UpdatePhysicsShadowToCurrentPosition(0); - } - break; - - case CRATE_JEEP: - m_hContainer = (CBaseAnimating*)CreateEntityByName( "prop_dynamic_override" ); - if ( m_hContainer ) - { - m_hContainer->SetModel( "models/buggy.mdl" ); - m_hContainer->SetName( AllocPooledString("dropship_jeep") ); - - m_hContainer->SetAbsOrigin( GetAbsOrigin() );//- Vector( 0, 0 , 25 ) ); - QAngle angles = GetAbsAngles(); - VMatrix mat, rot, result; - MatrixFromAngles( angles, mat ); - MatrixBuildRotateZ( rot, -90 ); - MatrixMultiply( mat, rot, result ); - MatrixToAngles( result, angles ); - m_hContainer->SetAbsAngles( angles ); - - m_hContainer->SetParent(this, 0); - m_hContainer->SetOwnerEntity(this); - m_hContainer->SetSolid( SOLID_VPHYSICS ); - m_hContainer->Spawn(); - } - break; - - case CRATE_NONE: - default: - break; - } - - // Setup our bbox - if ( m_hContainer ) - { - UTIL_SetSize( this, DROPSHIP_BBOX_CRATE_MIN, DROPSHIP_BBOX_CRATE_MAX ); - SetIdealActivity( (Activity)ACT_DROPSHIP_FLY_IDLE_CARGO ); - } - else - { - UTIL_SetSize( this, DROPSHIP_BBOX_MIN, DROPSHIP_BBOX_MAX ); - SetIdealActivity( (Activity)ACT_DROPSHIP_FLY_IDLE_EXAGG ); - } - - m_cullBoxMins = WorldAlignMins() - Vector(300,300,200); - m_cullBoxMaxs = WorldAlignMaxs() + Vector(300,300,200); - BaseClass::Spawn(); - - // Dropship ignores all damage, but can deal it to its carried container - m_takedamage = m_bInvulnerable ? DAMAGE_NO : DAMAGE_YES; - if ( m_bInvulnerable && m_hContainer ) - { - m_hContainer->m_takedamage = DAMAGE_NO; - } - - m_iHealth = 100; - m_flFieldOfView = 0.5; // 60 degrees - m_iBurstRounds = 15; - - InitBoneControllers(); - InitCustomSchedules(); - - m_flMaxSpeed = DROPSHIP_MAX_SPEED; - m_flMaxSpeedFiring = BASECHOPPER_MAX_FIRING_SPEED; - m_hPickupTarget = NULL; - m_hLandTarget = NULL; - - //!!!HACKHACK - // This tricks the AI code that constantly complains that the vehicle has no schedule. - SetSchedule( SCHED_IDLE_STAND ); - - SetLandingState( LANDING_NO ); - - if ( HasSpawnFlags( SF_DROPSHIP_WAIT_FOR_DROPOFF_INPUT ) ) - { - m_bWaitForDropoffInput = true; - } - else - { - m_bWaitForDropoffInput = false; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Called after spawning on map load or on a load from save game. -//----------------------------------------------------------------------------- -void CNPC_CombineDropship::Activate( void ) -{ - BaseClass::Activate(); - - if ( !m_sRollermineTemplateData ) - { - m_sRollermineTemplateData = NULL_STRING; - if ( m_sRollermineTemplate != NULL_STRING ) - { - // This must be the first time we're activated, not a load from save game. - // Look up the template in the template database. - m_sRollermineTemplateData = Templates_FindByTargetName(STRING(m_sRollermineTemplate)); - if ( m_sRollermineTemplateData == NULL_STRING ) - { - Warning( "npc_combinedropship %s: Rollermine Template %s not found!\n", STRING(GetEntityName()), STRING(m_sRollermineTemplate) ); - } - } - } -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::Precache( void ) -{ - // Models - PrecacheModel("models/combine_dropship.mdl"); - switch ( m_iCrateType ) - { - case CRATE_SOLDIER: - UTIL_PrecacheOther( "prop_dropship_container" ); - - // - // Precache the all templates that we are configured to spawn - // - for ( int i = 0; i < DROPSHIP_MAX_SOLDIERS; i++ ) - { - if ( m_sNPCTemplate[i] != NULL_STRING ) - { - if ( m_sNPCTemplateData[i] == NULL_STRING ) - { - m_sNPCTemplateData[i] = Templates_FindByTargetName(STRING(m_sNPCTemplate[i])); - } - if ( m_sNPCTemplateData[i] != NULL_STRING ) - { - CBaseEntity *pEntity = NULL; - MapEntity_ParseEntity( pEntity, STRING(m_sNPCTemplateData[i]), NULL ); - if ( pEntity != NULL ) - { - pEntity->Precache(); - UTIL_RemoveImmediate( pEntity ); - } - } - else - { - Warning( "npc_combinedropship %s: Template NPC %s not found!\n", STRING(GetEntityName()), STRING(m_sNPCTemplate[i]) ); - - // Use the first template we've got - m_sNPCTemplateData[i] = m_sNPCTemplateData[0]; - } - - // Make sure we've got a dustoff point for it - if ( m_sDustoffPoints[i] == NULL_STRING ) - { - Warning( "npc_combinedropship %s: Has no dustoff point for NPC %d!\n", STRING(GetEntityName()), i ); - } - } - else - { - m_sNPCTemplateData[i] = NULL_STRING; - } - } - break; - - case CRATE_JEEP: - PrecacheModel("models/buggy.mdl"); - break; - - default: - break; - } - - PrecacheScriptSound( "NPC_CombineDropship.RotorLoop" ); - PrecacheScriptSound( "NPC_CombineDropship.FireLoop" ); - PrecacheScriptSound( "NPC_CombineDropship.NearRotorLoop" ); - PrecacheScriptSound( "NPC_CombineDropship.OnGroundRotorLoop" ); - PrecacheScriptSound( "NPC_CombineDropship.DescendingWarningLoop" ); - PrecacheScriptSound( "NPC_CombineDropship.NearRotorLoop" ); - - if ( m_sRollermineTemplate != NULL_STRING ) - { - UTIL_PrecacheOther( "npc_rollermine" ); - } - - BaseClass::Precache(); - -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::Flight( void ) -{ - // Only run the flight model in some flight states - bool bRunFlight = ( GetLandingState() == LANDING_NO || - GetLandingState() == LANDING_LEVEL_OUT || - GetLandingState() == LANDING_LIFTOFF || - GetLandingState() == LANDING_SWOOPING || - GetLandingState() == LANDING_DESCEND || - GetLandingState() == LANDING_HOVER_LEVEL_OUT || - GetLandingState() == LANDING_HOVER_DESCEND ); - - Vector forward, right, up; - GetVectors( &forward, &right, &up ); - - float finspeed = 0; - float swayspeed = 0; - Vector vecImpulse = vec3_origin; - - //Adrian: Slowly lerp the orientation and position of the cargo into place... - //We assume CRATE_NONE means the dropship just picked up some random phys object. - if ( m_hContainer != NULL && ( m_iCrateType == CRATE_SOLDIER || m_iCrateType == CRATE_NONE ) ) - { - if ( m_hContainer->GetLocalOrigin() != vec3_origin ) - { - Vector vCurrentLocalOrigin = m_hContainer->GetLocalOrigin(); - Vector vLocalOrigin; - - VectorLerp( vCurrentLocalOrigin, vec3_origin, 0.05f, vLocalOrigin ); - - m_hContainer->SetLocalOrigin( vLocalOrigin ); - } - - if ( m_hContainer->GetLocalAngles() != vec3_angle ) - { - QAngle vCurrentLocalAngles = m_hContainer->GetLocalAngles(); - QAngle vLocalAngles; - - vLocalAngles = Lerp( 0.05f, vCurrentLocalAngles, vec3_angle ); - - m_hContainer->SetLocalAngles( vLocalAngles ); - } - } - - if ( bRunFlight ) - { - if( GetFlags() & FL_ONGROUND ) - { - // This would be really bad. - SetGroundEntity( NULL ); - } - - // calc desired acceleration - float dt = 1.0f; - - Vector accel; - float accelRate = DROPSHIP_ACCEL_RATE; - float maxSpeed = GetMaxSpeed(); - - if ( m_lifeState == LIFE_DYING ) - { - accelRate *= 5.0; - maxSpeed *= 5.0; - } - - float flCurrentSpeed = GetAbsVelocity().Length(); - float flDist = MIN( flCurrentSpeed + accelRate, maxSpeed ); - - Vector deltaPos; - if ( GetLandingState() == LANDING_SWOOPING ) - { - // Move directly to the target point - deltaPos = GetDesiredPosition(); - } - else - { - ComputeActualTargetPosition( flDist, dt, 0.0f, &deltaPos ); - } - deltaPos -= GetAbsOrigin(); - - //NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + deltaPos, 0, 255, 0, true, 0.1f ); - - // calc goal linear accel to hit deltaPos in dt time. - accel.x = 2.0 * (deltaPos.x - GetAbsVelocity().x * dt) / (dt * dt); - accel.y = 2.0 * (deltaPos.y - GetAbsVelocity().y * dt) / (dt * dt); - accel.z = 2.0 * (deltaPos.z - GetAbsVelocity().z * dt + 0.5 * 384 * dt * dt) / (dt * dt); - - float flDistFromPath = 0.0f; - Vector vecPoint, vecDelta; - if ( IsOnPathTrack() && GetLandingState() == LANDING_NO ) - { - // Also, add in a little force to get us closer to our current line segment if we can - ClosestPointToCurrentPath( &vecPoint ); - VectorSubtract( vecPoint, GetAbsOrigin(), vecDelta ); - flDistFromPath = VectorNormalize( vecDelta ); - if ( flDistFromPath > 200 ) - { - // Strongly constrain to an n unit pipe around the current path - // by damping out all impulse forces that would push us further from the pipe - float flAmount = (flDistFromPath - 200) / 200.0f; - flAmount = clamp( flAmount, 0, 1 ); - VectorMA( accel, flAmount * 200.0f, vecDelta, accel ); - } - } - - // don't fall faster than 0.2G or climb faster than 2G - accel.z = clamp( accel.z, 384 * 0.2, 384 * 2.0 ); - - Vector goalUp = accel; - VectorNormalize( goalUp ); - - // calc goal orientation to hit linear accel forces - float goalPitch = RAD2DEG( asin( DotProduct( forward, goalUp ) ) ); - float goalYaw = UTIL_VecToYaw( m_vecDesiredFaceDir ); - float goalRoll = RAD2DEG( asin( DotProduct( right, goalUp ) ) ); - - // clamp goal orientations - goalPitch = clamp( goalPitch, -45, 60 ); - goalRoll = clamp( goalRoll, -45, 45 ); - - // calc angular accel needed to hit goal pitch in dt time. - dt = 0.6; - QAngle goalAngAccel; - goalAngAccel.x = 2.0 * (AngleDiff( goalPitch, AngleNormalize( GetLocalAngles().x ) ) - GetLocalAngularVelocity().x * dt) / (dt * dt); - goalAngAccel.y = 2.0 * (AngleDiff( goalYaw, AngleNormalize( GetLocalAngles().y ) ) - GetLocalAngularVelocity().y * dt) / (dt * dt); - goalAngAccel.z = 2.0 * (AngleDiff( goalRoll, AngleNormalize( GetLocalAngles().z ) ) - GetLocalAngularVelocity().z * dt) / (dt * dt); - - goalAngAccel.x = clamp( goalAngAccel.x, -300, 300 ); - //goalAngAccel.y = clamp( goalAngAccel.y, -60, 60 ); - goalAngAccel.y = clamp( goalAngAccel.y, -120, 120 ); - goalAngAccel.z = clamp( goalAngAccel.z, -300, 300 ); - - // limit angular accel changes to simulate mechanical response times - dt = 0.1; - QAngle angAccelAccel; - angAccelAccel.x = (goalAngAccel.x - m_vecAngAcceleration.x) / dt; - angAccelAccel.y = (goalAngAccel.y - m_vecAngAcceleration.y) / dt; - angAccelAccel.z = (goalAngAccel.z - m_vecAngAcceleration.z) / dt; - - angAccelAccel.x = clamp( angAccelAccel.x, -1000, 1000 ); - angAccelAccel.y = clamp( angAccelAccel.y, -1000, 1000 ); - angAccelAccel.z = clamp( angAccelAccel.z, -1000, 1000 ); - - m_vecAngAcceleration += angAccelAccel * 0.1; - - // DevMsg( "pitch %6.1f (%6.1f:%6.1f) ", goalPitch, GetLocalAngles().x, m_vecAngVelocity.x ); - // DevMsg( "roll %6.1f (%6.1f:%6.1f) : ", goalRoll, GetLocalAngles().z, m_vecAngVelocity.z ); - // DevMsg( "%6.1f %6.1f %6.1f : ", goalAngAccel.x, goalAngAccel.y, goalAngAccel.z ); - // DevMsg( "%6.0f %6.0f %6.0f\n", angAccelAccel.x, angAccelAccel.y, angAccelAccel.z ); - - ApplySidewaysDrag( right ); - ApplyGeneralDrag(); - - QAngle angVel = GetLocalAngularVelocity(); - angVel += m_vecAngAcceleration * 0.1; - - //angVel.y = clamp( angVel.y, -60, 60 ); - //angVel.y = clamp( angVel.y, -120, 120 ); - angVel.y = clamp( angVel.y, -120, 120 ); - - SetLocalAngularVelocity( angVel ); - - m_flForce = m_flForce * 0.8 + (accel.z + fabs( accel.x ) * 0.1 + fabs( accel.y ) * 0.1) * 0.1 * 0.2; - - vecImpulse = m_flForce * up; - - if ( m_lifeState == LIFE_DYING ) - { - vecImpulse.z = -38.4; // 64ft/sec - } - else - { - vecImpulse.z -= 38.4; // 32ft/sec - } - - // Find our current velocity - Vector vecVelDir = GetAbsVelocity(); - - VectorNormalize( vecVelDir ); - - if ( flDistFromPath > 100 ) - { - // Strongly constrain to an n unit pipe around the current path - // by damping out all impulse forces that would push us further from the pipe - float flDot = DotProduct( vecImpulse, vecDelta ); - if ( flDot < 0.0f ) - { - VectorMA( vecImpulse, -flDot * 0.1f, vecDelta, vecImpulse ); - } - - // Also apply an extra impulse to compensate for the current velocity - flDot = DotProduct( vecVelDir, vecDelta ); - if ( flDot < 0.0f ) - { - VectorMA( vecImpulse, -flDot * 0.1f, vecDelta, vecImpulse ); - } - } - - // Find our acceleration direction - Vector vecAccelDir = vecImpulse; - VectorNormalize( vecAccelDir ); - - // Level out our plane of movement - vecAccelDir.z = 0.0f; - vecVelDir.z = 0.0f; - forward.z = 0.0f; - right.z = 0.0f; - - // Find out how "fast" we're moving in relation to facing and acceleration - finspeed = m_flForce * DotProduct( vecVelDir, vecAccelDir ); - swayspeed = m_flForce * DotProduct( vecVelDir, right ); - } - - // Use the correct pose params for the state of our container - int poseBodyAccel; - int poseBodySway; - if ( m_hContainer || GetLandingState() == LANDING_SWOOPING ) - { - poseBodyAccel = m_poseCargo_Body_Accel; - poseBodySway = m_poseCargo_Body_Sway; - SetPoseParameter( m_poseBody_Accel, 0 ); - SetPoseParameter( m_poseBody_Sway, 0 ); - } - else - { - poseBodyAccel = m_poseBody_Accel; - poseBodySway = m_poseBody_Sway; - SetPoseParameter( m_poseCargo_Body_Accel, 0 ); - SetPoseParameter( m_poseCargo_Body_Sway, 0 ); - } - - // If we're landing, deliberately tuck in the back end - if ( GetLandingState() == LANDING_DESCEND || GetLandingState() == LANDING_TOUCHDOWN || - GetLandingState() == LANDING_UNLOADING || GetLandingState() == LANDING_UNLOADED || IsHovering() ) - { - finspeed = -60; - } - - // Apply the acceleration blend to the fins - float finAccelBlend = SimpleSplineRemapVal( finspeed, -60, 60, -1, 1 ); - float curFinAccel = GetPoseParameter( poseBodyAccel ); - curFinAccel = UTIL_Approach( finAccelBlend, curFinAccel, 0.1f ); - SetPoseParameter( poseBodyAccel, EdgeLimitPoseParameter( poseBodyAccel, curFinAccel ) ); - - // Apply the spin sway to the fins - float finSwayBlend = SimpleSplineRemapVal( swayspeed, -60, 60, -1, 1 ); - float curFinSway = GetPoseParameter( poseBodySway ); - curFinSway = UTIL_Approach( finSwayBlend, curFinSway, 0.1f ); - SetPoseParameter( poseBodySway, EdgeLimitPoseParameter( poseBodySway, curFinSway ) ); - - if ( bRunFlight ) - { - // Add in our velocity pulse for this frame - ApplyAbsVelocityImpulse( vecImpulse ); - } - - //DevMsg("curFinAccel: %f, curFinSway: %f\n", curFinAccel, curFinSway ); -} - - -//------------------------------------------------------------------------------ -// Deals damage to what's behing carried -//------------------------------------------------------------------------------ -int CNPC_CombineDropship::OnTakeDamage_Alive( const CTakeDamageInfo &inputInfo ) -{ - // FIXME: To make this work for CRATE_STRIDER or CRATE_APC, we need to - // add code to the strider + apc to make them not take double-damage from rockets - // (owing to the blast hitting the crate + the dropship). See the dropship container - // code above to see how to do it. - if ( m_hContainer && !m_bInvulnerable ) - { - if ( (inputInfo.GetDamageType() & DMG_AIRBOAT) || (m_iCrateType == CRATE_SOLDIER) ) - { - m_hContainer->TakeDamage( inputInfo ); - } - } - - // don't die - return 0; -} - -//------------------------------------------------------------------------------ -// Updates the facing direction -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::UpdateFacingDirection( void ) -{ - if ( GetEnemy() ) - { - if ( !IsCrashing() && m_flLastSeen + 5 > gpGlobals->curtime ) - { - // If we've seen the target recently, face the target. - //Msg( "Facing Target \n" ); - m_vecDesiredFaceDir = m_vecTargetPosition - GetAbsOrigin(); - } - else - { - // Remain facing the way you were facing... - } - } - else - { - // Face our desired position. - if ( GetDesiredPosition().DistToSqr( GetAbsOrigin() ) > 1 ) - { - m_vecDesiredFaceDir = GetDesiredPosition() - GetAbsOrigin(); - } - else - { - GetVectors( &m_vecDesiredFaceDir, NULL, NULL ); - } - } - VectorNormalize( m_vecDesiredFaceDir ); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::InitializeRotorSound( void ) -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - - CPASAttenuationFilter filter( this ); - m_pRotorSound = controller.SoundCreate( filter, entindex(), "NPC_CombineDropship.RotorLoop" ); - m_pNearRotorSound = controller.SoundCreate( filter, entindex(), "NPC_CombineDropship.NearRotorLoop" ); - m_pRotorOnGroundSound = controller.SoundCreate( filter, entindex(), "NPC_CombineDropship.OnGroundRotorLoop" ); - m_pDescendingWarningSound = controller.SoundCreate( filter, entindex(), "NPC_CombineDropship.DescendingWarningLoop" ); - m_pCannonSound = controller.SoundCreate( filter, entindex(), "NPC_CombineDropship.FireLoop" ); - - // NOTE: m_pRotorSound is started up by the base class - if ( m_pCannonSound ) - { - controller.Play( m_pCannonSound, 0.0, 100 ); - } - - if ( m_pDescendingWarningSound ) - { - controller.Play( m_pDescendingWarningSound, 0.0, 100 ); - } - - if ( m_pRotorOnGroundSound ) - { - controller.Play( m_pRotorOnGroundSound, 0.0, 100 ); - } - - if ( m_pNearRotorSound ) - { - controller.Play( m_pNearRotorSound, 0.0, 100 ); - } - - m_engineThrust = 1.0f; - - BaseClass::InitializeRotorSound(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineDropship::StopLoopingSounds() -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - - if ( m_pCannonSound ) - { - controller.SoundDestroy( m_pCannonSound ); - m_pCannonSound = NULL; - } - - if ( m_pRotorOnGroundSound ) - { - controller.SoundDestroy( m_pRotorOnGroundSound ); - m_pRotorOnGroundSound = NULL; - } - - if ( m_pDescendingWarningSound ) - { - controller.SoundDestroy( m_pDescendingWarningSound ); - m_pDescendingWarningSound = NULL; - } - - if ( m_pNearRotorSound ) - { - controller.SoundDestroy( m_pNearRotorSound ); - m_pNearRotorSound = NULL; - } - - BaseClass::StopLoopingSounds(); -} - - -//------------------------------------------------------------------------------ -// Updates the rotor wash volume -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::UpdateRotorWashVolume( CSoundPatch *pRotorSound, float flVolume, float flDeltaTime ) -{ - if ( !pRotorSound ) - return; - - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - float flVolDelta = flVolume - controller.SoundGetVolume( pRotorSound ); - if ( flVolDelta ) - { - // We can change from 0 to 1 in 3 seconds. - // Figure out how many seconds flVolDelta will take. - float flRampTime = fabs( flVolDelta ) * flDeltaTime; - controller.SoundChangeVolume( pRotorSound, flVolume, flRampTime ); - } -} - - -//------------------------------------------------------------------------------ -// Updates the rotor wash volume -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::UpdateRotorWashVolume() -{ - float flNearFactor = 0.0f; - CBaseEntity *pPlayer = UTIL_PlayerByIndex( 1 ); - if (pPlayer) - { - float flDist = pPlayer->GetAbsOrigin().DistTo( GetAbsOrigin() ); - flDist = clamp( flDist, DROPSHIP_NEAR_SOUND_MIN_DISTANCE, DROPSHIP_NEAR_SOUND_MAX_DISTANCE ); - flNearFactor = RemapVal( flDist, DROPSHIP_NEAR_SOUND_MIN_DISTANCE, DROPSHIP_NEAR_SOUND_MAX_DISTANCE, 1.0f, 0.0f ); - } - - if ( m_pRotorSound ) - { - UpdateRotorWashVolume( m_pRotorSound, m_engineThrust * GetRotorVolume() * (1.0f - flNearFactor), 3.0f ); - } - - if ( m_pNearRotorSound ) - { - UpdateRotorWashVolume( m_pNearRotorSound, m_engineThrust * GetRotorVolume() * flNearFactor, 3.0f ); - } -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::UpdateRotorSoundPitch( int iPitch ) -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - - float rotorPitch = 0.2 + m_engineThrust * 0.8; - if ( m_pRotorSound ) - { - controller.SoundChangePitch( m_pRotorSound, iPitch + rotorPitch, 0.1 ); - } - - if ( m_pNearRotorSound ) - { - controller.SoundChangePitch( m_pNearRotorSound, iPitch + rotorPitch, 0.1 ); - } - - if (m_pRotorOnGroundSound) - { - controller.SoundChangePitch( m_pRotorOnGroundSound, iPitch + rotorPitch, 0.1 ); - } - - UpdateRotorWashVolume(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iSoldiers - -//----------------------------------------------------------------------------- -void CNPC_CombineDropship::CalculateSoldierCount( int iSoldiers ) -{ - if ( m_iCrateType >= 0 ) - { - m_soldiersToDrop = clamp( iSoldiers, 0, DROPSHIP_MAX_SOLDIERS ); - } - else - { - m_soldiersToDrop = 0; - } -} - -//------------------------------------------------------------------------------ -// Purpose : Leave crate being carried -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::InputLandLeave( inputdata_t &inputdata ) -{ - CalculateSoldierCount( inputdata.value.Int() ); - m_leaveCrate = true; - LandCommon(); -} - -//------------------------------------------------------------------------------ -// Purpose : Take crate being carried to next point -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::InputLandTake( inputdata_t &inputdata ) -{ - CalculateSoldierCount( inputdata.value.Int() ); - m_leaveCrate = false; - LandCommon(); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : bHover - If true, means we're landing on a hover point, not the ground -// Output : -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::LandCommon( bool bHover ) -{ - // If we don't have a crate, we're not able to land - if ( !m_hContainer && !bHover ) - return; - - //DevMsg( "Landing\n" ); - - if( bHover ) - { - SetLandingState( LANDING_HOVER_LEVEL_OUT ); - } - else - { - SetLandingState( LANDING_LEVEL_OUT ); - } - - SetLocalAngularVelocity( vec3_angle ); - - // Do we have a land target? - if ( m_iszLandTarget != NULL_STRING ) - { - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, m_iszLandTarget ); - if ( !pTarget ) - { - Warning("npc_combinedropship %s couldn't find land target named %s\n", STRING(GetEntityName()), STRING(m_iszLandTarget) ); - return; - } - - // Start heading to the point - m_hLandTarget = pTarget; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineDropship::InputSetLandTarget( inputdata_t &inputdata ) -{ - m_iszLandTarget = inputdata.value.StringID(); -} - -//------------------------------------------------------------------------------ -// Purpose : Drop mine inputs... done this way so generic path_corners can be used -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::InputDropMines( inputdata_t &inputdata ) -{ - m_totalMinesToDrop = inputdata.value.Int(); - if ( m_totalMinesToDrop >= 1 ) // catch bogus values being passed in - { - m_bDropMines = true; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_CombineDropship::InputDropStrider( inputdata_t &inputdata ) -{ - if ( !m_hContainer || !FClassnameIs( m_hContainer, "npc_strider" ) ) - { - Warning("npc_combinedropship %s was told to drop Strider, but isn't carrying one!\n", STRING(GetEntityName()) ); - return; - } - - QAngle angles = GetAbsAngles(); - - angles.x = 0.0; - angles.z = 0.0; - - m_hContainer->SetParent(NULL, 0); - m_hContainer->SetOwnerEntity(NULL); - m_hContainer->SetAbsAngles( angles ); - m_hContainer->SetAbsVelocity( vec3_origin ); - - m_hContainer = NULL; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_CombineDropship::InputDropAPC( inputdata_t &inputdata ) -{ - if ( !m_hContainer || !FClassnameIs( m_hContainer, "prop_vehicle_apc" ) ) - { - Warning("npc_combinedropship %s was told to drop APC, but isn't carrying one!\n", STRING(GetEntityName()) ); - return; - } - - m_hContainer->SetParent(NULL, 0); -// m_hContainer->SetOwnerEntity(NULL); - - Vector vecAbsVelocity = GetAbsVelocity(); - if ( vecAbsVelocity.z > 0 ) - { - vecAbsVelocity.z = 0.0f; - } - if ( m_hContainer->GetHealth() > 0 ) - { - vecAbsVelocity = vec3_origin; - } - - m_hContainer->SetAbsVelocity( vecAbsVelocity ); - m_hContainer->SetMoveType( (MoveType_t)m_iContainerMoveType ); - - // If the container has a physics object, remove it's shadow - IPhysicsObject *pPhysicsObject = m_hContainer->VPhysicsGetObject(); - if ( pPhysicsObject ) - { - pPhysicsObject->RemoveShadowController(); - } - - UTIL_SetSize( this, DROPSHIP_BBOX_MIN, DROPSHIP_BBOX_MAX ); - - m_hContainer = NULL; - m_OnFinishedDropoff.FireOutput( this, this ); - SetLandingState( LANDING_NO ); - m_hLandTarget = NULL; -} - - -//----------------------------------------------------------------------------- -// Drop the soldier container -//----------------------------------------------------------------------------- -void CNPC_CombineDropship::DropSoldierContainer( ) -{ - m_hContainer->SetParent(NULL, 0); -// m_hContainer->SetOwnerEntity(NULL); - - Vector vecAbsVelocity = GetAbsVelocity(); - if ( vecAbsVelocity.z > 0 ) - { - vecAbsVelocity.z = 0.0f; - } - - m_hContainer->SetAbsVelocity( vecAbsVelocity ); - m_hContainer->SetMoveType( MOVETYPE_VPHYSICS ); - - // If we have a troop in the process of exiting, kill him. - // We do this to avoid having to solve the AI problems resulting from it. - if ( m_hLastTroopToLeave ) - { - CTakeDamageInfo dmgInfo( this, this, vec3_origin, m_hContainer->GetAbsOrigin(), m_hLastTroopToLeave->GetMaxHealth(), DMG_GENERIC ); - m_hLastTroopToLeave->TakeDamage( dmgInfo ); - } - - // If the container has a physics object, remove it's shadow - IPhysicsObject *pPhysicsObject = m_hContainer->VPhysicsGetObject(); - if ( pPhysicsObject ) - { - pPhysicsObject->RemoveShadowController(); - pPhysicsObject->SetVelocity( &vecAbsVelocity, &vec3_origin ); - } - - UTIL_SetSize( this, DROPSHIP_BBOX_MIN, DROPSHIP_BBOX_MAX ); - - m_hContainer = NULL; - SetLandingState( LANDING_NO ); - m_hLandTarget = NULL; - - if ( m_bHasDroppedOff ) - { - m_OnContainerShotDownAfterDropoff.FireOutput( this, this ); - } - else - { - int iTroopsNotUnloaded = (m_soldiersToDrop - m_iCurrentTroopExiting); - if ( g_debug_dropship.GetInt() ) - { - Msg("Dropship died, troops not unloaded: %d\n", iTroopsNotUnloaded ); - } - - m_OnContainerShotDownBeforeDropoff.Set( iTroopsNotUnloaded, this, this ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Pick up a specified object -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_CombineDropship::InputPickup( inputdata_t &inputdata ) -{ - // Can't pickup if we're already carrying something - if ( m_hContainer ) - { - Warning("npc_combinedropship %s was told to pickup, but is already carrying something.\n", STRING(GetEntityName()) ); - return; - } - - string_t iszTargetName = inputdata.value.StringID(); - if ( iszTargetName == NULL_STRING ) - { - Warning("npc_combinedropship %s tried to pickup with no specified pickup target.\n", STRING(GetEntityName()) ); - return; - } - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, iszTargetName ); - if ( !pTarget ) - { - Warning("npc_combinedropship %s couldn't find pickup target named %s\n", STRING(GetEntityName()), STRING(iszTargetName) ); - return; - } - - // Start heading to the point - m_hPickupTarget = pTarget; - - m_bHasDroppedOff = false; - - // Disable collisions to my target - m_hPickupTarget->SetOwnerEntity(this); - if ( m_NPCState == NPC_STATE_IDLE ) - { - SetState( NPC_STATE_ALERT ); - } - SetLandingState( LANDING_SWOOPING ); - m_flLandingSpeed = GetAbsVelocity().Length(); - - UpdatePickupNavigation(); -} - -//----------------------------------------------------------------------------- -// Purpose: Set the range of the container's gun -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_CombineDropship::InputSetGunRange( inputdata_t &inputdata ) -{ - m_flGunRange = inputdata.value.Float(); -} - - -//------------------------------------------------------------------------------ -// Set the landing state -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::SetLandingState( LandingState_t landingState ) -{ - if ( landingState == m_iLandState ) - return; - - if ( m_pDescendingWarningSound ) - { - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - if ( ( landingState == LANDING_DESCEND ) || ( landingState == LANDING_TOUCHDOWN ) || ( landingState == LANDING_UNLOADING ) || ( landingState == LANDING_UNLOADED ) || ( landingState == LANDING_HOVER_DESCEND ) ) - { - controller.SoundChangeVolume( m_pDescendingWarningSound, m_bSuppressSound ? 0.0f : 1.0f, 0.3f ); - } - else - { - controller.SoundChangeVolume( m_pDescendingWarningSound, 0.0f, 0.0f ); - } - } - - m_iLandState = landingState; -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -bool CNPC_CombineDropship::IsHovering() -{ - bool bIsHovering = false; - - if( GetLandingState() > LANDING_START_HOVER && GetLandingState() < LANDING_END_HOVER ) - { - bIsHovering = true; - } - - return bIsHovering; -} - -//------------------------------------------------------------------------------ -// Update the ground rotorwash volume -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::UpdateGroundRotorWashSound( float flAltitude ) -{ - float flVolume = RemapValClamped( flAltitude, DROPSHIP_GROUND_WASH_MIN_ALTITUDE, DROPSHIP_GROUND_WASH_MAX_ALTITUDE, 1.0f, 0.0f ); - UpdateRotorWashVolume( m_pRotorOnGroundSound, flVolume * GetRotorVolume(), 0.5f ); -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::PrescheduleThink( void ) -{ - BaseClass::PrescheduleThink(); - - // "npc_kill" destroys our container - if (m_debugOverlays & OVERLAY_NPC_KILL_BIT) - { - if ( m_hContainer ) - { - CTakeDamageInfo dmgInfo( this, this, vec3_origin, vec3_origin, 1000, DMG_BLAST ); - m_hContainer->TakeDamage( dmgInfo ); - } - } - - // Update the ground rotorwash volume - float flAltitude = GetAltitude(); - UpdateGroundRotorWashSound( flAltitude ); - - // keep track of think time deltas for burn calc below - float dt = gpGlobals->curtime - m_flLastTime; - m_flLastTime = gpGlobals->curtime; - - switch( GetLandingState() ) - { - case LANDING_NO: - { - if ( IsActivityFinished() && (GetActivity() != ACT_DROPSHIP_FLY_IDLE_EXAGG && GetActivity() != ACT_DROPSHIP_FLY_IDLE_CARGO) ) - { - if ( m_hContainer ) - { - SetIdealActivity( (Activity)ACT_DROPSHIP_FLY_IDLE_CARGO ); - } - else - { - SetIdealActivity( (Activity)ACT_DROPSHIP_FLY_IDLE_EXAGG ); - } - } - - DoRotorWash(); - } - break; - - case LANDING_LEVEL_OUT: - case LANDING_HOVER_LEVEL_OUT: - { - // Approach the drop point - Vector vecToTarget = (GetDesiredPosition() - GetAbsOrigin()); - float flDistance = vecToTarget.Length(); - - // Are we there yet? - float flSpeed = GetAbsVelocity().Length(); - if ( flDistance < 70 && flSpeed < 100 ) - { - m_flLandingSpeed = flSpeed; - - if( IsHovering() ) - { - SetLandingState( LANDING_HOVER_DESCEND ); - } - else - { - SetLandingState( LANDING_DESCEND ); - } - - // save off current angles so we can work them out over time - QAngle angles = GetLocalAngles(); - m_existPitch = angles.x; - m_existRoll = angles.z; - } - - DoRotorWash(); - } - break; - - case LANDING_DESCEND: - case LANDING_HOVER_DESCEND: - { - /* - if ( IsActivityFinished() && GetActivity() != ACT_DROPSHIP_DESCEND_IDLE ) - { - SetActivity( (Activity)ACT_DROPSHIP_DESCEND_IDLE ); - } - */ - - if( IsHovering() && m_hLandTarget != NULL ) - { - // We're trying to hover above an arbitrary point, not above the ground. - // Recompute flAltitude to indicate the vertical distance from the land - // target so that touchdown is correctly detected. - flAltitude = GetAbsOrigin().z - m_hLandTarget->GetAbsOrigin().z; - } - - // Orient myself to the desired direction - bool bStillOrienting = false; - Vector targetDir; - if ( m_hLandTarget ) - { - // We've got a land target, so match it's orientation - AngleVectors( m_hLandTarget->GetAbsAngles(), &targetDir ); - } - else - { - // No land target. - targetDir = GetDesiredPosition() - GetAbsOrigin(); - } - - // Don't unload until we're facing the way the dropoff point specifies - float flTargetYaw = UTIL_VecToYaw( targetDir ); - float flDeltaYaw = UTIL_AngleDiff( flTargetYaw, GetAbsAngles().y ); - if ( fabs(flDeltaYaw) > 5 ) - { - bStillOrienting = true; - } - - // Ensure we land on the drop point. Stop dropping if we're still turning. - Vector vecToTarget = (GetDesiredPosition() - GetAbsOrigin()); - float flDistance = vecToTarget.Length(); - float flRampedSpeed = m_flLandingSpeed * (flDistance / 70); - Vector vecVelocity = (flRampedSpeed / flDistance) * vecToTarget; - -#define MAX_LAND_VEL -300.0f -#define MIN_LAND_VEL -75.0f -#define ALTITUDE_CAP 512.0f - - float flFactor = MIN( 1.0, flAltitude / ALTITUDE_CAP ); - float flDescendVelocity = MIN( -75, MAX_LAND_VEL * flFactor ); - - vecVelocity.z = flDescendVelocity; - - SetAbsVelocity( vecVelocity ); - - if ( flAltitude < 72 ) - { - QAngle angles = GetLocalAngles(); - - // Level out quickly. - angles.x = UTIL_Approach( 0.0, angles.x, 0.2 ); - angles.z = UTIL_Approach( 0.0, angles.z, 0.2 ); - - SetLocalAngles( angles ); - } - else - { - // randomly move as if buffeted by ground effects - // gently flatten ship from starting pitch/yaw - m_existPitch = UTIL_Approach( 0.0, m_existPitch, 1 ); - m_existRoll = UTIL_Approach( 0.0, m_existRoll, 1 ); - - QAngle angles = GetLocalAngles(); - angles.x = m_existPitch + ( sin( gpGlobals->curtime * 3.5f ) * DROPSHIP_MAX_LAND_TILT ); - angles.z = m_existRoll + ( sin( gpGlobals->curtime * 3.75f ) * DROPSHIP_MAX_LAND_TILT ); - SetLocalAngles( angles ); - } - - DoRotorWash(); - - // place danger sounds 1 foot above ground to get troops to scatter if they are below dropship - Vector vecBottom = GetAbsOrigin(); - vecBottom.z += WorldAlignMins().z; - Vector vecSpot = vecBottom + Vector(0, 0, -1) * (flAltitude - 12 ); - CSoundEnt::InsertSound( SOUND_DANGER, vecSpot, 400, 0.1, this, 0 ); - CSoundEnt::InsertSound( SOUND_PHYSICS_DANGER, vecSpot, 400, 0.1, this, 1 ); -// NDebugOverlay::Cross3D( vecSpot, -Vector(4,4,4), Vector(4,4,4), 255, 0, 255, false, 10.0f ); - - // now check to see if player is below us, if so, cause heat damage to them (i.e. get them to move) - trace_t tr; - Vector vecBBoxMin = CRATE_BBOX_MIN; // use flat box for check - vecBBoxMin.z = -5; - Vector vecBBoxMax = CRATE_BBOX_MAX; - vecBBoxMax.z = 5; - Vector pEndPoint = vecBottom + Vector(0, 0, -1) * ( flAltitude - 12 ); - AI_TraceHull( vecBottom, pEndPoint, vecBBoxMin, vecBBoxMax, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction < 1.0f ) - { - // Damage anything that's blocking me - if ( tr.m_pEnt && tr.m_pEnt->m_takedamage != DAMAGE_NO ) - { - CTakeDamageInfo info( this, this, 20 * dt, DMG_BURN ); - tr.m_pEnt->TakeDamage( info ); - } - } - - if ( !bStillOrienting && ((flAltitude <= 0.5f) || (m_iCrateType == CRATE_APC)) ) - { - if( IsHovering() ) - { - SetAbsVelocity( vec3_origin ); - SetLandingState( LANDING_HOVER_TOUCHDOWN ); - } - else - { - SetLandingState( LANDING_TOUCHDOWN ); - } - - // upon landing, make sure ship is flat - QAngle angles = GetLocalAngles(); - angles.x = 0; - angles.z = 0; - SetLocalAngles( angles ); - - // TODO: Release cargo anim - //SetActivity( (Activity)ACT_DROPSHIP_DESCEND_IDLE ); - return; - } - } - break; - - case LANDING_TOUCHDOWN: - case LANDING_HOVER_TOUCHDOWN: - { - /* - if ( IsActivityFinished() && ( GetActivity() != ACT_DROPSHIP_DESCEND_IDLE ) ) - { - SetActivity( (Activity)ACT_DROPSHIP_DESCEND_IDLE ); - } - */ - - // Wait here if we're supposed to wait for the dropoff input - if ( m_bWaitForDropoffInput ) - return; - - // Wait here till designer tells us to get moving again. - if ( IsHovering() ) - return; - - SetLandingState( LANDING_UNLOADING ); - - // If we're dropping off troops, we'll wait for them to be done. - // Otherwise, just pause on the ground for a few seconds and then leave. - if ( m_soldiersToDrop && m_hContainer) - { - m_flTimeTakeOff = 0; - m_flNextTroopSpawnAttempt = 0; - - // Open our container - m_hContainer->SetSequence( m_hContainer->LookupSequence("open_idle") ); - - // Start unloading troops - m_iCurrentTroopExiting = 0; - SpawnTroop(); - } - else - { - float flHoverTime = ( m_iCrateType >= 0 ) ? DROPSHIP_LANDING_HOVER_TIME : 0.5f; - m_flTimeTakeOff = gpGlobals->curtime + flHoverTime; - } - } - break; - - case LANDING_UNLOADING: - { - // If we've got no specified takeoff time, we're still waiting for troops to exit. Idle. - if ( !m_flTimeTakeOff ) - { - float idleVolume = 0.2f; - m_engineThrust = UTIL_Approach( idleVolume, m_engineThrust, 0.04f ); - if ( m_engineThrust > idleVolume ) - { - // Make sure we're kicking up dust/water as long as engine thrust is up - DoRotorWash(); - } - - // If we've lost the last troop who was leaving, he probably got killed during dustoff. - if ( !m_hLastTroopToLeave || !m_hLastTroopToLeave->IsAlive() ) - { - // If we still have troops onboard, spawn the next one - if ( m_iCurrentTroopExiting < m_soldiersToDrop ) - { - SpawnTroop(); - } - else - { - // We're out of troops, time to leave - m_flTimeTakeOff = gpGlobals->curtime + 0.5; - } - } - } - else - { - if( gpGlobals->curtime > m_flTimeTakeOff ) - { - SetLandingState( LANDING_LIFTOFF ); - SetActivity( (Activity)ACT_DROPSHIP_LIFTOFF ); - m_engineThrust = 1.0f; // ensure max volume once we're airborne - if ( m_bIsFiring ) - { - StopCannon(); // kill cannon sounds if they are on - } - - // detach container from ship - if ( m_hContainer && m_leaveCrate ) - { - m_hContainer->SetParent(NULL); - m_hContainer->SetMoveType( (MoveType_t)m_iContainerMoveType ); - - Vector vecAbsVelocity( 0, 0, GetAbsVelocity().z ); - if ( vecAbsVelocity.z > 0 ) - { - vecAbsVelocity.z = 0.0f; - } - - m_hContainer->SetAbsVelocity( vecAbsVelocity ); - - // If the container has a physics object, remove it's shadow - IPhysicsObject *pPhysicsObject = m_hContainer->VPhysicsGetObject(); - if ( pPhysicsObject ) - { - pPhysicsObject->RemoveShadowController(); - pPhysicsObject->SetVelocity( &vecAbsVelocity, &vec3_origin ); - } - - m_hContainer = NULL; - UTIL_SetSize( this, DROPSHIP_BBOX_MIN, DROPSHIP_BBOX_MAX ); - } - } - else if ( (m_flTimeTakeOff - gpGlobals->curtime) < 0.5f ) - { - // Manage engine wash and volume - m_engineThrust = UTIL_Approach( 1.0f, m_engineThrust, 0.1f ); - DoRotorWash(); - } - } - } - break; - - case LANDING_LIFTOFF: - { - // Once we're off the ground, start flying again - if ( flAltitude > 120 ) - { - SetLandingState( LANDING_NO ); - m_hLandTarget = NULL; - m_bHasDroppedOff = true; - m_OnFinishedDropoff.FireOutput( this, this ); - } - - if ( m_hContainer ) - { - m_hContainer->SetSequence( m_hContainer->LookupSequence("close_idle") ); - } - } - break; - - case LANDING_SWOOPING: - { - // Did we lose our pickup target? - if ( !m_hPickupTarget ) - { - SetLandingState( LANDING_NO ); - } - else - { - // Decrease altitude and speed to hit the target point. - Vector vecToTarget = (GetDesiredPosition() - GetAbsOrigin()); - float flDistance = vecToTarget.Length(); - - // Start cheating when we get near it - if ( flDistance < 50 ) - { - /* - if ( flDistance > 10 ) - { - // Cheat and ensure we touch the target - float flSpeed = GetAbsVelocity().Length(); - Vector vecVelocity = vecToTarget; - VectorNormalize( vecVelocity ); - SetAbsVelocity( vecVelocity * MIN(flSpeed,flDistance) ); - } - else - */ - { - // Grab the target - m_hContainer = m_hPickupTarget; - m_hPickupTarget = NULL; - m_iContainerMoveType = m_hContainer->GetMoveType(); - if ( m_bInvulnerable && m_hContainer ) - { - m_hContainer->m_takedamage = DAMAGE_NO; - } - - // If the container has a physics object, move it to shadow - IPhysicsObject *pPhysicsObject = m_hContainer->VPhysicsGetObject(); - if ( pPhysicsObject ) - { - pPhysicsObject->EnableMotion( true ); - pPhysicsObject->SetShadow( 1e4, 1e4, false, false ); - pPhysicsObject->UpdateShadow( GetAbsOrigin(), GetAbsAngles(), false, 0 ); - } - - m_hContainer->SetParent(this, 0); - m_hContainer->SetMoveType( MOVETYPE_PUSH ); - m_hContainer->SetGroundEntity( NULL ); - - m_OnFinishedPickup.FireOutput( this, this ); - SetLandingState( LANDING_NO ); - } - } - } - - DoRotorWash(); - } - break; - - default: - break; - } - - if ( !(CAI_BaseNPC::m_nDebugBits & bits_debugDisableAI) ) - { - DoCombatStuff(); - } - - if ( GetActivity() != GetIdealActivity() ) - { - //DevMsg( "setactivity" ); - SetActivity( GetIdealActivity() ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -#define DROPSHIP_WASH_ALTITUDE 1024.0 - -void CNPC_CombineDropship::DoRotorWash( void ) -{ - Vector vecForward; - GetVectors( &vecForward, NULL, NULL ); - - Vector vecRotorHub = GetAbsOrigin() + vecForward * -64; - - DrawRotorWash( DROPSHIP_WASH_ALTITUDE, vecRotorHub ); -} - - -//------------------------------------------------------------------------------ -// Purpose : Spawn the next NPC in our template list -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::SpawnTroop( void ) -{ - if ( !m_hContainer ) - { - // We're done, take off. - m_flTimeTakeOff = gpGlobals->curtime + 0.5; - return; - } - - // Are we fully unloaded? If so, take off. Otherwise, tell the next troop to exit. - if ( m_iCurrentTroopExiting >= m_soldiersToDrop || m_sNPCTemplateData[m_iCurrentTroopExiting] == NULL_STRING ) - { - // We're done, take off. - m_flTimeTakeOff = gpGlobals->curtime + 0.5; - return; - } - - m_hLastTroopToLeave = NULL; - - // Not time to try again yet? - if ( m_flNextTroopSpawnAttempt > gpGlobals->curtime ) - return; - - // HACK: This is a nasty piece of work. We want to make sure the deploy end is clear, and has enough - // room with our deploying NPC, but we don't want to create the NPC unless it's clear, and we don't - // know how much room he needs without spawning him. - // So, because we know that we only ever spawn combine soldiers at the moment, we'll just use their hull. - // HACK: Add some bloat because the endpoint isn't perfectly aligned with NPC end origin - Vector vecNPCMins = NAI_Hull::Mins( HULL_HUMAN ) - Vector(4,4,4); - Vector vecNPCMaxs = NAI_Hull::Maxs( HULL_HUMAN ) + Vector(4,4,4); - - // Scare NPCs away from our deploy endpoint to keep them away - Vector vecDeployEndPoint; - QAngle vecDeployEndAngles; - m_hContainer->GetAttachment( m_iAttachmentTroopDeploy, vecDeployEndPoint, vecDeployEndAngles ); - vecDeployEndPoint = GetDropoffFinishPosition( vecDeployEndPoint, NULL, vecNPCMins, vecNPCMaxs ); - CSoundEnt::InsertSound( SOUND_DANGER, vecDeployEndPoint, 120, 2.0f, this ); - - // Make sure there are no NPCs on the spot - trace_t tr; - CTraceFilterOnlyNPCsAndPlayer filter( this, COLLISION_GROUP_NONE ); - AI_TraceHull( vecDeployEndPoint, vecDeployEndPoint, vecNPCMins, vecNPCMaxs, MASK_SOLID, &filter, &tr ); - if ( tr.m_pEnt ) - { - if ( g_debug_dropship.GetInt() == 2 ) - { - NDebugOverlay::Box( vecDeployEndPoint, vecNPCMins, vecNPCMaxs, 255,0,0, 64, 0.5 ); - } - - m_flNextTroopSpawnAttempt = gpGlobals->curtime + 1; - return; - } - - if ( g_debug_dropship.GetInt() == 2 ) - { - NDebugOverlay::Box( vecDeployEndPoint, vecNPCMins, vecNPCMaxs, 0,255,0, 64, 0.5 ); - } - - // Get the spawn point inside the container - Vector vecSpawnOrigin; - QAngle vecSpawnAngles; - m_hContainer->GetAttachment( m_iAttachmentDeployStart, vecSpawnOrigin, vecSpawnAngles ); - - // Spawn the templated NPC - CBaseEntity *pEntity = NULL; - MapEntity_ParseEntity( pEntity, STRING(m_sNPCTemplateData[m_iCurrentTroopExiting]), NULL ); - - // Increment troop count - m_iCurrentTroopExiting++; - - if ( !pEntity ) - { - Warning("Dropship could not create template NPC\n" ); - return; - } - CAI_BaseNPC *pNPC = pEntity->MyNPCPointer(); - Assert( pNPC ); - - // Spawn an entity blocker. - CBaseEntity *pBlocker = CEntityBlocker::Create( vecDeployEndPoint, vecNPCMins, vecNPCMaxs, pNPC, true ); - g_EventQueue.AddEvent( pBlocker, "Kill", 2.5, this, this ); - if ( g_debug_dropship.GetInt() == 2 ) - { - NDebugOverlay::Box( vecDeployEndPoint, vecNPCMins, vecNPCMaxs, 255, 255, 255, 64, 2.5 ); - } - - // Ensure our NPCs are standing upright - vecSpawnAngles[PITCH] = vecSpawnAngles[ROLL] = 0; - - // Move it to the container spawnpoint - pNPC->SetAbsOrigin( vecSpawnOrigin ); - pNPC->SetAbsAngles( vecSpawnAngles ); - DispatchSpawn( pNPC ); - pNPC->m_NPCState = NPC_STATE_IDLE; - pNPC->Activate(); - - // Spawn a scripted sequence entity to make the NPC run out of the dropship - CAI_ScriptedSequence *pSequence = (CAI_ScriptedSequence*)CreateEntityByName( "scripted_sequence" ); - pSequence->KeyValue( "m_iszEntity", STRING(pNPC->GetEntityName()) ); - pSequence->KeyValue( "m_iszPlay", "Dropship_Deploy" ); - pSequence->KeyValue( "m_fMoveTo", "4" ); // CINE_MOVETO_TELEPORT - pSequence->KeyValue( "OnEndSequence", UTIL_VarArgs("%s,NPCFinishDustoff,%s,0,-1", STRING(GetEntityName()), STRING(pNPC->GetEntityName())) ); - pSequence->SetAbsOrigin( vecSpawnOrigin ); - pSequence->SetAbsAngles( vecSpawnAngles ); - pSequence->AddSpawnFlags( SF_SCRIPT_NOINTERRUPT | SF_SCRIPT_HIGH_PRIORITY | SF_SCRIPT_OVERRIDESTATE ); - pSequence->Spawn(); - pSequence->Activate(); - variant_t emptyVariant; - pSequence->AcceptInput( "BeginSequence", this, this, emptyVariant, 0 ); - - m_hLastTroopToLeave = pNPC; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns a safe position above/below the specified origin for the NPC to finish it's dropoff on -// Input : vecOrigin - -//----------------------------------------------------------------------------- -Vector CNPC_CombineDropship::GetDropoffFinishPosition( Vector vecOrigin, CAI_BaseNPC *pNPC, Vector vecMins, Vector vecMaxs ) -{ - // Use the NPC's if they're specified - if ( pNPC ) - { - vecMins = NAI_Hull::Mins( pNPC->GetHullType() ); - vecMaxs = NAI_Hull::Maxs( pNPC->GetHullType() ); - } - - trace_t tr; - AI_TraceHull( vecOrigin + Vector(0,0,32), vecOrigin, vecMins, vecMaxs, MASK_SOLID, pNPC, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction < 1.0 ) - { - if ( g_debug_dropship.GetInt() == 1 ) - { - NDebugOverlay::Box( vecOrigin, vecMins, vecMaxs, 255,0,0, 8, 4.0 ); - } - - // Try and find the ground - AI_TraceHull( vecOrigin + Vector(0,0,32), vecOrigin, vecMins, vecMaxs, MASK_SOLID, pNPC, COLLISION_GROUP_NONE, &tr ); - if ( !tr.startsolid ) - return (tr.endpos + Vector(0,0,1)); - } - else if ( g_debug_dropship.GetInt() == 1 ) - { - NDebugOverlay::Box( vecOrigin, vecMins, vecMaxs, 0,255,0, 8, 4.0 ); - } - - return vecOrigin; -} - -//----------------------------------------------------------------------------- -// Purpose: A troop we dropped of has now finished the scripted sequence -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_CombineDropship::InputNPCFinishDustoff( inputdata_t &inputdata ) -{ - CBaseEntity *pEnt = gEntList.FindEntityByName( NULL, inputdata.value.StringID(), NULL, inputdata.pActivator, inputdata.pCaller ); - if ( !pEnt ) - return; - - CAI_BaseNPC *pNPC = pEnt->MyNPCPointer(); - Assert( pNPC ); - - Vector vecOrigin = GetDropoffFinishPosition( pNPC->GetAbsOrigin(), pNPC, vec3_origin, vec3_origin ); - pNPC->SetAbsOrigin( vecOrigin ); - - // Do we have a dustoff point? - CBaseEntity *pDustoff = NULL; - if ( m_sDustoffPoints[m_iCurrentTroopExiting-1] != NULL_STRING ) - { - pDustoff = gEntList.FindEntityByName( NULL, m_sDustoffPoints[m_iCurrentTroopExiting-1] ); - if ( !pDustoff ) - { - Warning("npc_combinedropship %s couldn't find dustoff target named %s\n", STRING(GetEntityName()), STRING(m_sDustoffPoints[m_iCurrentTroopExiting-1]) ); - } - } - - if ( !pDustoff ) - { - // Make a move away sound to scare the combine away from this point - CSoundEnt::InsertSound( SOUND_MOVE_AWAY | SOUND_CONTEXT_COMBINE_ONLY, pNPC->GetAbsOrigin(), 128, 0.1 ); - } - else - { - if ( g_debug_dropship.GetInt() == 1 ) - { - NDebugOverlay::Box( pDustoff->GetAbsOrigin(), -Vector(10,10,10), Vector(10,10,10), 0,255,0, 8, 5.0 ); - } - - // Tell the NPC to move to the dustoff position - pNPC->SetState( NPC_STATE_ALERT ); - pNPC->ScheduledMoveToGoalEntity( SCHED_DROPSHIP_DUSTOFF, pDustoff, ACT_RUN ); - pNPC->GetNavigator()->SetArrivalDirection( pDustoff->GetAbsAngles() ); - - // Make sure they ignore a bunch of conditions - static int g_Conditions[] = - { - COND_CAN_MELEE_ATTACK1, - COND_CAN_MELEE_ATTACK2, - COND_CAN_RANGE_ATTACK1, - COND_CAN_RANGE_ATTACK2, - COND_ENEMY_DEAD, - COND_HEAR_BULLET_IMPACT, - COND_HEAR_COMBAT, - COND_HEAR_DANGER, - COND_NEW_ENEMY, - COND_PROVOKED, - COND_SEE_ENEMY, - COND_SEE_FEAR, - COND_SMELL, - COND_LIGHT_DAMAGE, - COND_HEAVY_DAMAGE, - COND_PHYSICS_DAMAGE, - COND_REPEATED_DAMAGE, - }; - pNPC->SetIgnoreConditions( g_Conditions, ARRAYSIZE(g_Conditions) ); - } - - // Unload the next troop - SpawnTroop(); -} - -//----------------------------------------------------------------------------- -// Purpose: Tells the dropship to stop waiting and dustoff -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_CombineDropship::InputStopWaitingForDropoff( inputdata_t &inputdata ) -{ - m_bWaitForDropoffInput = false; -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::InputHover( inputdata_t &inputdata ) -{ - m_iszLandTarget = inputdata.value.StringID(); - LandCommon( true ); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::InputFlyToPathTrack( inputdata_t &inputdata ) -{ - if( IsHovering() ) - { - SetLandingState( LANDING_NO ); - m_hLandTarget = NULL; - } - - CAI_TrackPather::InputFlyToPathTrack( inputdata ); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -float CNPC_CombineDropship::GetAltitude( void ) -{ - trace_t tr; - Vector vecBottom = GetAbsOrigin(); - - // Uneven terrain causes us problems, so trace our box down - AI_TraceEntity( this, vecBottom, vecBottom - Vector(0,0,4096), MASK_SOLID_BRUSHONLY, &tr ); - - float flAltitude = ( 4096 * tr.fraction ); - //DevMsg(" Altitude: %.3f\n", flAltitude ); - return flAltitude; -} - - -//----------------------------------------------------------------------------- -// Purpose: Drop rollermine from dropship -//----------------------------------------------------------------------------- -void CNPC_CombineDropship::DropMine( void ) -{ - NPC_Rollermine_DropFromPoint( GetAbsOrigin(), this, STRING(m_sRollermineTemplateData) ); -} - -//------------------------------------------------------------------------------ -// Purpose : Fly towards our pickup target -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::UpdatePickupNavigation( void ) -{ - // Try and touch the top of the object - Vector vecPickup = m_hPickupTarget->WorldSpaceCenter(); - vecPickup.z += (m_hPickupTarget->CollisionProp()->OBBSize().z * 0.5); - SetDesiredPosition( vecPickup ); - - //NDebugOverlay::Cross3D( GetDesiredPosition(), -Vector(32,32,32), Vector(32,32,32), 0, 255, 255, true, 0.1f ); -} - -//------------------------------------------------------------------------------ -// Purpose : Fly towards our land target -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::UpdateLandTargetNavigation( void ) -{ - Vector vecPickup = m_hLandTarget->WorldSpaceCenter(); - vecPickup.z += 256; - SetDesiredPosition( vecPickup ); - - //NDebugOverlay::Cross3D( GetDesiredPosition(), -Vector(32,32,32), Vector(32,32,32), 0, 255, 255, true, 0.1f ); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::Hunt( void ) -{ - // If we have a pickup target, fly to it - if ( m_hPickupTarget ) - { - UpdatePickupNavigation(); - } - else if ( m_hLandTarget ) - { - UpdateLandTargetNavigation(); - } - else if ( GetLandingState() == LANDING_NO ) - { - UpdateTrackNavigation(); - } - - // don't face player ever, only face nav points - Vector desiredDir = GetDesiredPosition() - GetAbsOrigin(); - VectorNormalize( desiredDir ); - // Face our desired position. - m_vecDesiredFaceDir = desiredDir; - - if ( GetLandingState() == LANDING_DESCEND || GetLandingState() == LANDING_LEVEL_OUT || IsHovering() ) - { - if ( m_hLandTarget ) - { - // We've got a land target, so match it's orientation - AngleVectors( m_hLandTarget->GetAbsAngles(), &m_vecDesiredFaceDir ); - } - else - { - // No land target. - m_vecDesiredFaceDir = GetDesiredPosition() - GetAbsOrigin(); - } - } - - UpdateEnemy(); - Flight(); - - UpdatePlayerDopplerShift( ); - -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineDropship::GatherEnemyConditions( CBaseEntity *pEnemy ) -{ - BaseClass::GatherEnemyConditions(pEnemy); - - // If we can't see the enemy for a few seconds, consider him unreachable - if ( !HasCondition(COND_SEE_ENEMY) ) - { - if ( gpGlobals->curtime - GetEnemyLastTimeSeen() >= 3.0f ) - { - MarkEnemyAsEluded(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: do all of the stuff related to having an enemy, attacking, etc. -//----------------------------------------------------------------------------- -void CNPC_CombineDropship::DoCombatStuff( void ) -{ - // Handle mines - if ( m_bDropMines ) - { - switch( m_iDropState ) - { - case DROP_IDLE: - { - m_iMineCount = m_totalMinesToDrop - 1; - - DropMine(); - // setup next individual drop time - m_flDropDelay = gpGlobals->curtime + DROPSHIP_TIME_BETWEEN_MINES; - // get ready to drop next mine, unless we're only supposed to drop 1 - if ( m_iMineCount ) - { - m_iDropState = DROP_NEXT; - } - else - { - m_bDropMines = false; // no more... - } - break; - } - case DROP_NEXT: - { - if ( gpGlobals->curtime > m_flDropDelay ) // time to drop next mine? - { - DropMine(); - m_flDropDelay = gpGlobals->curtime + DROPSHIP_TIME_BETWEEN_MINES; - - m_iMineCount--; - if ( !m_iMineCount ) - { - m_iDropState = DROP_IDLE; - m_bDropMines = false; // reset flag - } - } - break; - } - } - } - - // Handle guns - bool bStopGun = true; - if ( GetEnemy() ) - { - bStopGun = !FireCannonRound(); - } - - if ( bStopGun && m_bIsFiring ) - { - StopCannon(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Update the container's gun to face the enemy. -// Input : &vecMuzzle - The gun's muzzle/firing point -// &vecAimDir - The gun's current aim direction -//----------------------------------------------------------------------------- -void CNPC_CombineDropship::UpdateContainerGunFacing( Vector &vecMuzzle, Vector &vecToTarget, Vector &vecAimDir, float *flTargetRange ) -{ - Assert( m_hContainer ); - - // Get the desired aim vector - vecToTarget = GetEnemy()->WorldSpaceCenter( ); - - Vector vecBarrelPos, vecWorldBarrelPos; - QAngle worldBarrelAngle, vecAngles; - matrix3x4_t matRefToWorld; - m_hContainer->GetAttachment( m_iMuzzleAttachment, vecMuzzle, vecAngles ); - vecWorldBarrelPos = vecMuzzle; - worldBarrelAngle = vecAngles; - m_hContainer->GetAttachment( m_iMachineGunRefAttachment, matRefToWorld ); - VectorITransform( vecWorldBarrelPos, matRefToWorld, vecBarrelPos ); - - EntityMatrix parentMatrix; - parentMatrix.InitFromEntity( m_hContainer, m_iMachineGunBaseAttachment ); - Vector target = parentMatrix.WorldToLocal( vecToTarget ); - - float quadTarget = target.LengthSqr(); - float quadTargetXY = target.x*target.x + target.y*target.y; - - // Target is too close! Can't aim at it - if ( quadTarget > vecBarrelPos.LengthSqr() ) - { - // We're trying to aim the offset barrel at an arbitrary point. - // To calculate this, I think of the target as being on a sphere with - // it's center at the origin of the gun. - // The rotation we need is the opposite of the rotation that moves the target - // along the surface of that sphere to intersect with the gun's shooting direction - // To calculate that rotation, we simply calculate the intersection of the ray - // coming out of the barrel with the target sphere (that's the new target position) - // and use atan2() to get angles - - // angles from target pos to center - float targetToCenterYaw = atan2( target.y, target.x ); - float centerToGunYaw = atan2( vecBarrelPos.y, sqrt( quadTarget - (vecBarrelPos.y*vecBarrelPos.y) ) ); - - float targetToCenterPitch = atan2( target.z, sqrt( quadTargetXY ) ); - float centerToGunPitch = atan2( -vecBarrelPos.z, sqrt( quadTarget - (vecBarrelPos.z*vecBarrelPos.z) ) ); - - QAngle angles; - angles.Init( RAD2DEG(targetToCenterPitch+centerToGunPitch), RAD2DEG( targetToCenterYaw + centerToGunYaw ), 0 ); - - float flNewAngle = AngleNormalize( UTIL_ApproachAngle( angles.x, m_hContainer->GetPoseParameter(m_poseWeapon_Pitch), DROPSHIP_GUN_SPEED)); - m_hContainer->SetPoseParameter( m_poseWeapon_Pitch, flNewAngle ); - - flNewAngle = AngleNormalize( UTIL_ApproachAngle( angles.y, m_hContainer->GetPoseParameter(m_poseWeapon_Yaw), DROPSHIP_GUN_SPEED)); - m_hContainer->SetPoseParameter( m_poseWeapon_Yaw, flNewAngle ); - m_hContainer->StudioFrameAdvance(); - } - - vecToTarget -= vecMuzzle; - *flTargetRange = VectorNormalize( vecToTarget ); - AngleVectors( vecAngles, &vecAimDir ); -} - - -//------------------------------------------------------------------------------ -// Purpose: Fire a round from the cannon -// Notes: Only call this if you have an enemy. -// Returns true if the cannon round was actually fired -//------------------------------------------------------------------------------ -bool CNPC_CombineDropship::FireCannonRound( void ) -{ - // Try and aim my cannon at the enemy, if I have a container - if ( !m_hContainer || (m_iCrateType < 0) ) - return false; - - // Update the container gun, and get the vector to the enemy, and the gun's current aim direction - float flRange; - Vector vecMuzzle, vecAimDir, vecToEnemy; - UpdateContainerGunFacing( vecMuzzle, vecToEnemy, vecAimDir, &flRange ); - - // Out of range? - if ( flRange > m_flGunRange ) - return false; - - // Only fire if the target's close enough to our aim direction - float flCosAngle = DotProduct( vecToEnemy, vecAimDir ); - if ( flCosAngle < DOT_15DEGREE ) - { - m_flTimeNextAttack = gpGlobals->curtime + 0.1; - return false; - } - - // If we're out of rounds, reload - if ( m_iBurstRounds <= 0 ) - { - m_iBurstRounds = RandomInt( 10, 20 ); - m_flTimeNextAttack = gpGlobals->curtime + (m_iBurstRounds * 0.1); - return false; - } - - // HACK: Return true so the fire sound isn't stopped - if ( m_flTimeNextAttack > gpGlobals->curtime ) - return true; - - m_iBurstRounds--; - - // If we're not currently firing, start it up - if ( !m_bIsFiring ) - { - StartCannon(); - } - - // Add a muzzle flash - QAngle vecAimAngles; - VectorAngles( vecAimDir, vecAimAngles ); - g_pEffects->MuzzleFlash( vecMuzzle, vecAimAngles, random->RandomFloat( 5.0f, 7.0f ), MUZZLEFLASH_TYPE_GUNSHIP ); - m_flTimeNextAttack = gpGlobals->curtime + 0.05; - - // Clamp to account for inaccuracy in aiming w/ pose parameters - vecAimDir = vecToEnemy; - - // Fire the bullet - int ammoType = GetAmmoDef()->Index("CombineCannon"); - FireBullets( 1, vecMuzzle, vecAimDir, VECTOR_CONE_2DEGREES, 8192, ammoType, 1, -1, -1, sk_npc_dmg_dropship.GetInt() ); - - return true; -} - -//------------------------------------------------------------------------------ -// Scare AIs in the area where bullets are impacting -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::DoImpactEffect( trace_t &tr, int nDamageType ) -{ - CSoundEnt::InsertSound( SOUND_DANGER | SOUND_CONTEXT_REACT_TO_SOURCE, tr.endpos, 120, 0.3f, this ); - - BaseClass::DoImpactEffect( tr, nDamageType ); -} - -//------------------------------------------------------------------------------ -// Purpose : The proper way to begin the gunship cannon firing at the enemy. -// Input : -// : -// Output : -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::StartCannon( void ) -{ - m_bIsFiring = true; - - // Start up the cannon sound. - if ( m_pCannonSound ) - { - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundChangeVolume(m_pCannonSound, 1.0, 0.0); - } - -} - -//------------------------------------------------------------------------------ -// Purpose : The proper way to cease the gunship cannon firing. -// Input : -// : -// Output : -//------------------------------------------------------------------------------ -void CNPC_CombineDropship::StopCannon( void ) -{ - m_bIsFiring = false; - - // Stop the cannon sound. - if ( m_pCannonSound ) - { - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundChangeVolume(m_pCannonSound, 0.0, 0.1); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Used the gunship's tracer for now -//----------------------------------------------------------------------------- -void CNPC_CombineDropship::MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ) -{ - switch ( iTracerType ) - { - case TRACER_LINE: - { - float flTracerDist; - Vector vecDir; - Vector vecEndPos; - - vecDir = tr.endpos - vecTracerSrc; - - flTracerDist = VectorNormalize( vecDir ); - - UTIL_Tracer( vecTracerSrc, tr.endpos, 0, TRACER_DONT_USE_ATTACHMENT, 16000, true, "GunshipTracer" ); - } - break; - - default: - BaseClass::MakeTracer( vecTracerSrc, tr, iTracerType ); - break; - } -} - -AI_BEGIN_CUSTOM_NPC( npc_combinedropship, CNPC_CombineDropship ) - - DECLARE_ACTIVITY( ACT_DROPSHIP_FLY_IDLE ); - DECLARE_ACTIVITY( ACT_DROPSHIP_FLY_IDLE_EXAGG ); - DECLARE_ACTIVITY( ACT_DROPSHIP_DESCEND_IDLE ); - DECLARE_ACTIVITY( ACT_DROPSHIP_DEPLOY_IDLE ); - DECLARE_ACTIVITY( ACT_DROPSHIP_LIFTOFF ); - - DECLARE_ACTIVITY( ACT_DROPSHIP_FLY_IDLE_CARGO ); - -AI_END_CUSTOM_NPC() - - - diff --git a/game/server/hl2/npc_combinegunship.cpp b/game/server/hl2/npc_combinegunship.cpp deleted file mode 100644 index b225dc3cf..000000000 --- a/game/server/hl2/npc_combinegunship.cpp +++ /dev/null @@ -1,3228 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "baseanimating.h" -#include "ai_network.h" -#include "ai_default.h" -#include "ai_schedule.h" -#include "ai_hull.h" -#include "ai_node.h" -#include "ai_task.h" -#include "ai_motor.h" -#include "entitylist.h" -#include "basecombatweapon.h" -#include "soundenvelope.h" -#include "gib.h" -#include "gamerules.h" -#include "ammodef.h" -#include "cbasehelicopter.h" -#include "npcevent.h" -#include "ndebugoverlay.h" -#include "decals.h" -#include "explode.h" // temp (sjb) -#include "smoke_trail.h" // temp (sjb) -#include "IEffects.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "ar2_explosion.h" -#include "te_effect_dispatch.h" -#include "rope.h" -#include "effect_dispatch_data.h" -#include "trains.h" -#include "globals.h" -#include "physics_prop_ragdoll.h" -#include "iservervehicle.h" -#include "soundent.h" -#include "npc_citizen17.h" -#include "physics_saverestore.h" -#include "hl2_shareddefs.h" -#include "props.h" -#include "npc_attackchopper.h" -#include "citadel_effects_shared.h" -#include "eventqueue.h" -#include "beam_flags.h" -#include "ai_eventresponse.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define GUNSHIP_MSG_BIG_SHOT 1 -#define GUNSHIP_MSG_STREAKS 2 - -#define GUNSHIP_NUM_DAMAGE_OUTPUTS 4 - -extern short g_sModelIndexFireball; // holds the index for the fireball - -int g_iGunshipEffectIndex = -1; - -#define GUNSHIP_ACCEL_RATE 500 - -// Spawnflags -#define SF_GUNSHIP_NO_GROUND_ATTACK ( 1 << 12 ) -#define SF_GUNSHIP_USE_CHOPPER_MODEL ( 1 << 13 ) - -ConVar sk_gunship_burst_size("sk_gunship_burst_size", "15" ); -ConVar sk_gunship_burst_min("sk_gunship_burst_min", "800" ); -ConVar sk_gunship_burst_dist("sk_gunship_burst_dist", "768" ); - -// Number of times the gunship must be struck by explosive damage -ConVar sk_gunship_health_increments( "sk_gunship_health_increments", "0" ); - -/* - -Wedge's notes: - - Gunship should move its head according to flight model when the target is behind the gunship, - or when the target is too far away to shoot at. Otherwise, the head should aim at the target. - - Negative angvelocity.y is a RIGHT turn. - Negative angvelocity.x is UP - -*/ - -#define GUNSHIP_AP_MUZZLE 5 - -#define GUNSHIP_MAX_SPEED 1056.0f - -#define GUNSHIP_MAX_FIRING_SPEED 200.0f -#define GUNSHIP_MIN_ROCKET_DIST 1000.0f -#define GUNSHIP_MAX_GUN_DIST 2000.0f -#define GUNSHIP_ARRIVE_DIST 128.0f - -#define GUNSHIP_HOVER_SPEED 300.0f // play hover animation if moving slower than this. - -#define GUNSHIP_AE_THRUST 1 - -#define GUNSHIP_HEAD_MAX_UP -65 -#define GUNSHIP_HEAD_MAX_DOWN 60 -#define GUNSHIP_HEAD_MAX_LEFT 60 -#define GUNSHIP_HEAD_MAX_RIGHT -60 - -#define BASE_STITCH_VELOCITY 800 //Units per second -#define MAX_STITCH_VELOCITY 1000 //Units per second - -#define GUNSHIP_LEAD_DISTANCE 800.0f -#define GUNSHIP_AVOID_DIST 512.0f -#define GUNSHIP_STITCH_MIN 512.0f - -#define GUNSHIP_MIN_CHASE_DIST_DIFF 128.0f // Distance threshold used to determine when a target has moved enough to update our navigation to it - -#define MIN_GROUND_ATTACK_DIST 500.0f // Minimum distance a target has to be for the gunship to consider using the ground attack weapon -#define MIN_GROUND_ATTACK_HEIGHT_DIFF 128.0f // Target's position and hit position must be within this threshold vertically - -#define GUNSHIP_WASH_ALTITUDE 1024.0f - -#define GUNSHIP_MIN_DAMAGE_THRESHOLD 50.0f - -#define GUNSHIP_INNER_NAV_DIST 400.0f -#define GUNSHIP_OUTER_NAV_DIST 800.0f - -#define GUNSHIP_BELLYBLAST_TARGET_HEIGHT 512.0 // Height above targets that the gunship wants to be when bellyblasting - -#define GUNSHIP_MISSILE_MAX_RESPONSE_TIME 0.4 -#define GUNSHIP_MAX_HITS_PER_BURST 5 - -#define GUNSHIP_FLARE_IGNORE_TIME 6.0 - -//===================================== -// Custom activities -//===================================== -Activity ACT_GUNSHIP_PATROL; -Activity ACT_GUNSHIP_HOVER; -Activity ACT_GUNSHIP_CRASH; - -#define GUNSHIP_DEBUG_LEADING 1 -#define GUNSHIP_DEBUG_PATH 2 -#define GUNSHIP_DEBUG_STITCHING 3 -#define GUNSHIP_DEBUG_BELLYBLAST 4 - -ConVar g_debug_gunship( "g_debug_gunship", "0", FCVAR_CHEAT ); - -//----------------------------------------------------------------------------- -// Purpose: Dying gunship ragdoll controller -//----------------------------------------------------------------------------- -class CGunshipRagdollMotion : public IMotionEvent -{ - DECLARE_SIMPLE_DATADESC(); -public: - virtual simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) - { - linear = Vector(0,0,400); - angular = Vector(0,600,100); - - return SIM_GLOBAL_ACCELERATION; - } -}; - -BEGIN_SIMPLE_DATADESC( CGunshipRagdollMotion ) -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CTargetGunshipCrash : public CPointEntity -{ - DECLARE_CLASS( CTargetGunshipCrash, CPointEntity ); -public: - DECLARE_DATADESC(); - - void InputEnable( inputdata_t &inputdata ) - { - m_bDisabled = false; - } - void InputDisable( inputdata_t &inputdata ) - { - m_bDisabled = true; - } - bool IsDisabled( void ) - { - return m_bDisabled; - } - void GunshipCrashedOnTarget( void ) - { - m_OnCrashed.FireOutput( this, this ); - } - -private: - bool m_bDisabled; - - COutputEvent m_OnCrashed; -}; - -LINK_ENTITY_TO_CLASS( info_target_gunshipcrash, CTargetGunshipCrash ); - -BEGIN_DATADESC( CTargetGunshipCrash ) - DEFINE_FIELD( m_bDisabled, FIELD_BOOLEAN ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - - // Outputs - DEFINE_OUTPUT( m_OnCrashed, "OnCrashed" ), -END_DATADESC() - - -//=================================================================== -// Gunship - the combine dugongic like attack vehicle. -//=================================================================== -class CNPC_CombineGunship : public CBaseHelicopter -{ -public: - DECLARE_CLASS( CNPC_CombineGunship, CBaseHelicopter ); - - CNPC_CombineGunship( void ); - ~CNPC_CombineGunship( void ); - - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - DEFINE_CUSTOM_AI; - - void PlayPatrolLoop( void ); - void PlayAngryLoop( void ); - - void Spawn( void ); - void Precache( void ); - void OnRestore( void ); - void PrescheduleThink( void ); - void HelicopterPostThink( void ); - void StopLoopingSounds( void ); - - bool IsValidEnemy( CBaseEntity *pEnemy ); - void GatherEnemyConditions( CBaseEntity *pEnemy ); - - void Flight( void ); - - bool FVisible( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ); - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - void FireDamageOutputsUpto( int iDamageNumber ); - - virtual float GetAcceleration( void ) { return 15; } - - virtual void MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ); - virtual void DoImpactEffect( trace_t &tr, int nDamageType ); - - void MoveHead( void ); - void UpdateDesiredPosition( void ); - void DoCombat( void ); - bool ChooseEnemy( void ); - void DoMuzzleFlash( void ); - void Ping( void ); - - void FireCannonRound( void ); - - // Gunship death process - void Event_Killed( const CTakeDamageInfo &info ); - void BeginCrash( void ); // I'm going to go to a crash point and die there - void BeginDestruct( void ); // I want to die now, so create my ragdoll - void SelfDestruct( void ); // I'm now fully dead, so remove myself. - void CreateSmokeTrail( void ); - bool FindNearestGunshipCrash( void ); - - int BloodColor( void ) { return DONT_BLEED; } - void GibMonster( void ); - - void UpdateRotorSoundPitch( int iPitch ); - void InitializeRotorSound( void ); - - void ApplyGeneralDrag( void ); - void ApplySidewaysDrag( const Vector &vecRight ); - - void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - - void UpdateEnemyTarget( void ); - - Vector GetEnemyTarget( void ); - Vector GetMissileTarget( void ); - - float GroundDistToPosition( const Vector &pos ); - - bool FireGun( void ); - bool IsTargettingMissile( void ); - - Class_T Classify( void ) { return CLASS_COMBINE_GUNSHIP; } // for now - float GetAutoAimRadius() { return 144.0f; } - - // Input functions - void InputSetPenetrationDepth( inputdata_t &inputdata ); - void InputOmniscientOn( inputdata_t &inputdata ); - void InputOmniscientOff( inputdata_t &inputdata ); - void InputBlindfireOn( inputdata_t &inputdata ); - void InputBlindfireOff( inputdata_t &inputdata ); - void InputSelfDestruct( inputdata_t &inputdata ); - void InputSetDockingBBox( inputdata_t &inputdata ); - void InputSetNormalBBox( inputdata_t &inputdata ); - void InputEnableGroundAttack( inputdata_t &inputdata ); - void InputDisableGroundAttack( inputdata_t &inputdata ); - void InputDoGroundAttack( inputdata_t &inputdata ); - - //NOTENOTE: I'm rather queasy about adding these, as they can lead to nasty bugs... - void InputBecomeInvulnerable( inputdata_t &inputdata ); - void InputBecomeVulnerable( inputdata_t &inputdata ); - - bool PoseGunTowardTargetDirection( const Vector &vTargetDir ); - void StartCannonBurst( int iBurstSize ); - void StopCannonBurst( void ); - - bool CheckGroundAttack( void ); - void StartGroundAttack( void ); - void StopGroundAttack( bool bDoAttack ); - Vector GetGroundAttackHitPosition( void ); - void DoGroundAttackExplosion( void ); - void DrawRotorWash( float flAltitude, const Vector &vecRotorOrigin ); - - void ManageWarningBeam( void ); - void DoBellyBlastDamage( trace_t &tr, Vector vMins, Vector vMaxs ); - - // Updates the facing direction - void UpdateFacingDirection( void ); - void CreateBellyBlastEnergyCore( void ); - -protected: - // Because the combine gunship is a leaf class, we can use - // static variables to store this information, and save some memory. - // Should the gunship end up having inheritors, their activate may - // stomp these numbers, in which case you should make these ordinary members - // again. - static int m_poseFlex_Horz, m_poseFlex_Vert, m_posePitch, m_poseYaw, m_poseFin_Accel, m_poseFin_Sway; - static int m_poseWeapon_Pitch, m_poseWeapon_Yaw; - - static bool m_sbStaticPoseParamsLoaded; - virtual void PopulatePoseParameters( void ); - -private: - // Outputs - COutputEvent m_OnFireCannon; - COutputEvent m_OnCrashed; - - COutputEvent m_OnFirstDamage; // First damage tick - COutputEvent m_OnSecondDamage; - COutputEvent m_OnThirdDamage; - COutputEvent m_OnFourthDamage; - // Keep track of which damage outputs we've fired. This is necessary - // to ensure that the game doesn't break if a mapmaker has outputs that - // must be fired on gunships, and the player switches skill levels - // midway through a gunship battle. - bool m_bDamageOutputsFired[GUNSHIP_NUM_DAMAGE_OUTPUTS]; - - float m_flNextGroundAttack; // Time to wait before the next ground attack - bool m_bIsGroundAttacking; // Denotes that we are ground attacking - bool m_bCanGroundAttack; // Denotes whether we can ground attack or not - float m_flGroundAttackTime; // Delay before blast happens from ground attack - - CHandle m_pSmokeTrail; - EHANDLE m_hGroundAttackTarget; - - CSoundPatch *m_pAirExhaustSound; - CSoundPatch *m_pAirBlastSound; - CSoundPatch *m_pCannonSound; - - CBaseEntity *m_pRotorWashModel; - QAngle m_vecAngAcceleration; - - float m_flEndDestructTime; - - int m_iDoSmokePuff; - int m_iAmmoType; - int m_iBurstSize; - - bool m_fBlindfire; - bool m_fOmniscient; - bool m_bIsFiring; - int m_iBurstHits; - bool m_bPreFire; - bool m_bInvulnerable; - - float m_flTimeNextPing; - float m_flPenetrationDepth; - float m_flDeltaT; - float m_flTimeNextAttack; - float m_flNextSeeEnemySound; - float m_flNextRocket; - float m_flBurstDelay; - - Vector m_vecAttackPosition; - Vector m_vecAttackVelocity; - - // Used when the gunships using the chopper model - Vector m_angGun; - - // For my death throes - IPhysicsMotionController *m_pCrashingController; - CGunshipRagdollMotion m_crashCallback; - EHANDLE m_hRagdoll; - CHandle m_hCrashTarget; - float m_flNextGunshipCrashFind; - - CHandle m_hEnergyCore; - - CNetworkVector( m_vecHitPos ); - - // If true, playing patrol loop. - // Else, playing angry. - bool m_fPatrolLoopPlaying; -}; - -LINK_ENTITY_TO_CLASS( npc_combinegunship, CNPC_CombineGunship ); - -IMPLEMENT_SERVERCLASS_ST( CNPC_CombineGunship, DT_CombineGunship ) - SendPropVector(SENDINFO(m_vecHitPos), -1, SPROP_COORD), -END_SEND_TABLE() - -BEGIN_DATADESC( CNPC_CombineGunship ) - - DEFINE_ENTITYFUNC( FlyTouch ), - - DEFINE_FIELD( m_flNextGroundAttack,FIELD_TIME ), - DEFINE_FIELD( m_bIsGroundAttacking,FIELD_BOOLEAN ), - DEFINE_FIELD( m_bCanGroundAttack, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flGroundAttackTime,FIELD_TIME ), - DEFINE_FIELD( m_pRotorWashModel, FIELD_CLASSPTR ), - DEFINE_FIELD( m_pSmokeTrail, FIELD_EHANDLE ), - DEFINE_FIELD( m_hGroundAttackTarget, FIELD_EHANDLE ), - DEFINE_SOUNDPATCH( m_pAirExhaustSound ), - DEFINE_SOUNDPATCH( m_pAirBlastSound ), - DEFINE_SOUNDPATCH( m_pCannonSound ), - DEFINE_FIELD( m_vecAngAcceleration,FIELD_VECTOR ), - DEFINE_FIELD( m_flDeltaT, FIELD_FLOAT ), - DEFINE_FIELD( m_flTimeNextAttack, FIELD_TIME ), - DEFINE_FIELD( m_flNextSeeEnemySound, FIELD_TIME ), - DEFINE_FIELD( m_flEndDestructTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextRocket, FIELD_TIME ), - DEFINE_FIELD( m_iDoSmokePuff, FIELD_INTEGER ), - DEFINE_FIELD( m_iAmmoType, FIELD_INTEGER ), - DEFINE_FIELD( m_iBurstSize, FIELD_INTEGER ), - DEFINE_FIELD( m_flBurstDelay, FIELD_FLOAT ), - DEFINE_FIELD( m_fBlindfire, FIELD_BOOLEAN ), - DEFINE_FIELD( m_fOmniscient, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bIsFiring, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iBurstHits, FIELD_INTEGER ), - DEFINE_FIELD( m_flTimeNextPing, FIELD_TIME ), - DEFINE_FIELD( m_flPenetrationDepth,FIELD_FLOAT ), - DEFINE_FIELD( m_vecAttackPosition, FIELD_VECTOR ), - DEFINE_FIELD( m_vecAttackVelocity, FIELD_VECTOR ), - DEFINE_FIELD( m_angGun, FIELD_VECTOR ), - DEFINE_PHYSPTR( m_pCrashingController ), - DEFINE_EMBEDDED( m_crashCallback ), - DEFINE_FIELD( m_hRagdoll, FIELD_EHANDLE ), - DEFINE_FIELD( m_hCrashTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_vecHitPos, FIELD_VECTOR ), - DEFINE_FIELD( m_fPatrolLoopPlaying,FIELD_BOOLEAN ), - DEFINE_FIELD( m_bPreFire, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bInvulnerable, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flNextGunshipCrashFind, FIELD_TIME ), - - DEFINE_FIELD( m_hEnergyCore, FIELD_EHANDLE ), - - DEFINE_ARRAY( m_bDamageOutputsFired, FIELD_BOOLEAN, GUNSHIP_NUM_DAMAGE_OUTPUTS ), - - // Function pointers - DEFINE_INPUTFUNC( FIELD_VOID, "OmniscientOn", InputOmniscientOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "OmniscientOff", InputOmniscientOff ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetPenetrationDepth", InputSetPenetrationDepth ), - DEFINE_INPUTFUNC( FIELD_VOID, "BlindfireOn", InputBlindfireOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "BlindfireOff", InputBlindfireOff ), - DEFINE_INPUTFUNC( FIELD_VOID, "SelfDestruct", InputSelfDestruct ), - DEFINE_INPUTFUNC( FIELD_VOID, "SetDockingBBox", InputSetDockingBBox ), - DEFINE_INPUTFUNC( FIELD_VOID, "SetNormalBBox", InputSetNormalBBox ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableGroundAttack", InputEnableGroundAttack ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableGroundAttack", InputDisableGroundAttack ), - DEFINE_INPUTFUNC( FIELD_STRING, "DoGroundAttack", InputDoGroundAttack ), - - DEFINE_OUTPUT( m_OnFireCannon, "OnFireCannon" ), - DEFINE_OUTPUT( m_OnFirstDamage, "OnFirstDamage" ), - DEFINE_OUTPUT( m_OnSecondDamage, "OnSecondDamage" ), - DEFINE_OUTPUT( m_OnThirdDamage, "OnThirdDamage" ), - DEFINE_OUTPUT( m_OnFourthDamage, "OnFourthDamage" ), - DEFINE_OUTPUT( m_OnCrashed, "OnCrashed" ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CNPC_CombineGunship::CNPC_CombineGunship( void ) -{ - m_hGroundAttackTarget = NULL; - m_pSmokeTrail = NULL; - m_iAmmoType = -1; - m_pCrashingController = NULL; - m_hRagdoll = NULL; - m_hCrashTarget = NULL; -} - - -void CNPC_CombineGunship::CreateBellyBlastEnergyCore( void ) -{ - CCitadelEnergyCore *pCore = static_cast( CreateEntityByName( "env_citadel_energy_core" ) ); - - if ( pCore == NULL ) - return; - - m_hEnergyCore = pCore; - - int iAttachment = LookupAttachment( "BellyGun" ); - - Vector vOrigin; - QAngle vAngle; - - GetAttachment( iAttachment, vOrigin, vAngle ); - - pCore->SetAbsOrigin( vOrigin ); - pCore->SetAbsAngles( vAngle ); - - DispatchSpawn( pCore ); - pCore->Activate(); - - pCore->SetParent( this, iAttachment ); - pCore->SetScale( 4.0f ); -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CNPC_CombineGunship::Spawn( void ) -{ - Precache( ); - - if ( HasSpawnFlags( SF_GUNSHIP_USE_CHOPPER_MODEL ) ) - { - SetModel( "models/combine_helicopter.mdl" ); - } - else - { - SetModel( "models/gunship.mdl" ); - } - - ExtractBbox( SelectHeaviestSequence( ACT_GUNSHIP_PATROL ), m_cullBoxMins, m_cullBoxMaxs ); - BaseClass::Spawn(); - - InitPathingData( GUNSHIP_ARRIVE_DIST, GUNSHIP_MIN_CHASE_DIST_DIFF, sk_gunship_burst_min.GetFloat() ); - AddEFlags( EFL_NO_DISSOLVE | EFL_NO_MEGAPHYSCANNON_RAGDOLL | EFL_NO_PHYSCANNON_INTERACTION ); - - m_takedamage = DAMAGE_YES; - - SetHullType(HULL_LARGE_CENTERED); - SetHullSizeNormal(); - - m_iMaxHealth = m_iHealth = 100; - - m_flFieldOfView = -0.707; // 270 degrees - - m_fHelicopterFlags |= BITS_HELICOPTER_GUN_ON; - - InitBoneControllers(); - - InitCustomSchedules(); - - SetActivity( (Activity)ACT_GUNSHIP_PATROL ); - SetCollisionGroup( HL2COLLISION_GROUP_GUNSHIP ); - - m_flMaxSpeed = GUNSHIP_MAX_SPEED; - m_flMaxSpeedFiring = GUNSHIP_MAX_SPEED; - - m_flTimeNextAttack = gpGlobals->curtime; - m_flNextSeeEnemySound = gpGlobals->curtime; - - // Init the pose parameters - SetPoseParameter( "flex_horz", 0 ); - SetPoseParameter( "flex_vert", 0 ); - SetPoseParameter( "fin_accel", 0 ); - SetPoseParameter( "fin_sway", 0 ); - - if( m_iAmmoType == -1 ) - { - // Since there's no weapon to index the ammo type, - // do it manually here. - m_iAmmoType = GetAmmoDef()->Index("CombineCannon"); - } - - //!!!HACKHACK - // This tricks the AI code that constantly complains that the gunship has no schedule. - SetSchedule( SCHED_IDLE_STAND ); - - AddRelationship( "env_flare D_LI 9", NULL ); - AddRelationship( "rpg_missile D_HT 99", NULL ); - - m_flTimeNextPing = gpGlobals->curtime + 2; - - m_flPenetrationDepth = 24; - m_flBurstDelay = 2.0f; - - // Blindfire and Omniscience default to off - m_fBlindfire = false; - m_fOmniscient = false; - m_bIsFiring = false; - m_bPreFire = false; - m_bInvulnerable = false; - - // See if we should start being able to attack - m_bCanGroundAttack = ( m_spawnflags & SF_GUNSHIP_NO_GROUND_ATTACK ) ? false : true; - - m_flEndDestructTime = 0; - - m_iBurstSize = 0; - m_iBurstHits = 0; - - // Do not dissolve - AddEFlags( EFL_NO_DISSOLVE ); - - for ( int i = 0; i < GUNSHIP_NUM_DAMAGE_OUTPUTS; i++ ) - { - m_bDamageOutputsFired[i] = false; - } - - CapabilitiesAdd( bits_CAP_SQUAD); - - if ( hl2_episodic.GetBool() == true ) - { - CreateBellyBlastEnergyCore(); - } - - // Allows autoaim to help attack the gunship. - if( g_pGameRules->GetAutoAimMode() == AUTOAIM_ON_CONSOLE ) - { - AddFlag( FL_AIMTARGET ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Restore the motion controller -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::OnRestore( void ) -{ - BaseClass::OnRestore(); - - if ( m_pCrashingController ) - { - m_pCrashingController->SetEventHandler( &m_crashCallback ); - } -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CNPC_CombineGunship::Precache( void ) -{ - if ( HasSpawnFlags( SF_GUNSHIP_USE_CHOPPER_MODEL ) ) - { - PrecacheModel( "models/combine_helicopter.mdl" ); - Chopper_PrecacheChunks( this ); - } - else - { - PrecacheModel("models/gunship.mdl"); - } - - PrecacheModel("sprites/lgtning.vmt"); - - PrecacheMaterial( "effects/ar2ground2" ); - PrecacheMaterial( "effects/blueblackflash" ); - - PrecacheScriptSound( "NPC_CombineGunship.SearchPing" ); - PrecacheScriptSound( "NPC_CombineGunship.PatrolPing" ); - PrecacheScriptSound( "NPC_Strider.Charge" ); - PrecacheScriptSound( "NPC_Strider.Shoot" ); - PrecacheScriptSound( "NPC_CombineGunship.SeeEnemy" ); - PrecacheScriptSound( "NPC_CombineGunship.CannonStartSound" ); - PrecacheScriptSound( "NPC_CombineGunship.Explode"); - PrecacheScriptSound( "NPC_CombineGunship.Pain" ); - PrecacheScriptSound( "NPC_CombineGunship.CannonStopSound" ); - - PrecacheScriptSound( "NPC_CombineGunship.DyingSound" ); - PrecacheScriptSound( "NPC_CombineGunship.CannonSound" ); - PrecacheScriptSound( "NPC_CombineGunship.RotorSound" ); - PrecacheScriptSound( "NPC_CombineGunship.ExhaustSound" ); - PrecacheScriptSound( "NPC_CombineGunship.RotorBlastSound" ); - - if ( hl2_episodic.GetBool() == true ) - { - UTIL_PrecacheOther( "env_citadel_energy_core" ); - g_iGunshipEffectIndex = PrecacheModel( "sprites/physbeam.vmt" ); - } - - PropBreakablePrecacheAll( MAKE_STRING("models/gunship.mdl") ); - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: Cache whatever pose parameters we intend to use -//----------------------------------------------------------------------------- -bool CNPC_CombineGunship::m_sbStaticPoseParamsLoaded = false; -int CNPC_CombineGunship::m_poseFlex_Horz = 0; -int CNPC_CombineGunship::m_poseFlex_Vert = 0; -int CNPC_CombineGunship::m_posePitch = 0; -int CNPC_CombineGunship::m_poseYaw = 0; -int CNPC_CombineGunship::m_poseFin_Accel = 0; -int CNPC_CombineGunship::m_poseFin_Sway = 0; -int CNPC_CombineGunship::m_poseWeapon_Pitch = 0; -int CNPC_CombineGunship::m_poseWeapon_Yaw = 0; -void CNPC_CombineGunship::PopulatePoseParameters( void ) -{ - if (!m_sbStaticPoseParamsLoaded) - { - m_poseFlex_Horz = LookupPoseParameter( "flex_horz"); - m_poseFlex_Vert = LookupPoseParameter( "flex_vert" ); - m_posePitch = LookupPoseParameter( "pitch" ); - m_poseYaw = LookupPoseParameter( "yaw" ); - m_poseFin_Accel = LookupPoseParameter( "fin_accel" ); - m_poseFin_Sway = LookupPoseParameter( "fin_sway" ); - - m_poseWeapon_Pitch = LookupPoseParameter( "weapon_pitch" ); - m_poseWeapon_Yaw = LookupPoseParameter( "weapon_yaw" ); - - m_sbStaticPoseParamsLoaded = true; - } - - BaseClass::PopulatePoseParameters(); -} - - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -CNPC_CombineGunship::~CNPC_CombineGunship(void) -{ - StopLoopingSounds(); - - if ( m_pCrashingController ) - { - physenv->DestroyMotionController( m_pCrashingController ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::Ping( void ) -{ - if( IsCrashing() ) - return; - - if( GetEnemy() != NULL ) - { - if( !HasCondition(COND_SEE_ENEMY) && gpGlobals->curtime > m_flTimeNextPing ) - { - EmitSound( "NPC_CombineGunship.SearchPing" ); - m_flTimeNextPing = gpGlobals->curtime + 3; - } - } - else - { - if( gpGlobals->curtime > m_flTimeNextPing ) - { - EmitSound( "NPC_CombineGunship.PatrolPing" ); - m_flTimeNextPing = gpGlobals->curtime + 3; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &pos - -// Output : float -//----------------------------------------------------------------------------- -float CNPC_CombineGunship::GroundDistToPosition( const Vector &pos ) -{ - Vector vecDiff; - VectorSubtract( GetAbsOrigin(), pos, vecDiff ); - - // Only interested in the 2d dist - vecDiff.z = 0; - - return vecDiff.Length(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::PlayPatrolLoop( void ) -{ - m_fPatrolLoopPlaying = true; - /* - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundChangeVolume( m_pPatrolSound, 1.0, 1.0 ); - controller.SoundChangeVolume( m_pAngrySound, 0.0, 1.0 ); - */ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::PlayAngryLoop( void ) -{ - m_fPatrolLoopPlaying = false; - /* - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundChangeVolume( m_pPatrolSound, 0.0, 1.0 ); - controller.SoundChangeVolume( m_pAngrySound, 1.0, 1.0 ); - */ -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::HelicopterPostThink( void ) -{ - // After HelicopterThink() - if ( HasCondition( COND_ENEMY_DEAD ) ) - { - if ( m_bIsFiring ) - { - // Fire more shots at the dead body for effect - if ( m_iBurstSize > 8 ) - { - m_iBurstSize = 8; - } - } - - // Fade out search sound, fade in patrol sound. - PlayPatrolLoop(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Vector -//----------------------------------------------------------------------------- -Vector CNPC_CombineGunship::GetGroundAttackHitPosition( void ) -{ - trace_t tr; - Vector vecShootPos, vecShootDir; - - GetAttachment( "BellyGun", vecShootPos, &vecShootDir, NULL, NULL ); - - AI_TraceLine( vecShootPos, vecShootPos + Vector( 0, 0, -MAX_TRACE_LENGTH ), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - if ( m_hGroundAttackTarget ) - { - return Vector( tr.endpos.x, tr.endpos.y, m_hGroundAttackTarget->WorldSpaceCenter().z ); - } - return tr.endpos; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_CombineGunship::CheckGroundAttack( void ) -{ - if ( m_bCanGroundAttack == false ) - return false; - - if ( m_bIsGroundAttacking ) - return false; - - // Must have an enemy - if ( GetEnemy() == NULL ) - return false; - - // Must not have done it too recently - if ( m_flNextGroundAttack > gpGlobals->curtime ) - return false; - - Vector predPos, predDest; - - // Find where the enemy is most likely to be in two seconds - UTIL_PredictedPosition( GetEnemy(), 1.0f, &predPos ); - UTIL_PredictedPosition( this, 1.0f, &predDest ); - - Vector predGap = ( predDest - predPos ); - predGap.z = 0; - - float predDistance = predGap.Length(); - - // Must be within distance - if ( predDistance > MIN_GROUND_ATTACK_DIST ) - return false; - - // Can't ground attack missiles - if ( IsTargettingMissile() ) - return false; - - //FIXME: Check to make sure we're not firing too far above or below the target - if ( fabs( GetGroundAttackHitPosition().z - GetEnemy()->WorldSpaceCenter().z ) > MIN_GROUND_ATTACK_HEIGHT_DIFF ) - return false; - - //FIXME: Check for ground movement capabilities? - - //TODO: Check for friendly-fire - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::StartGroundAttack( void ) -{ - // Mark us as attacking - m_bIsGroundAttacking = true; - m_flGroundAttackTime = gpGlobals->curtime + 3.0f; - - // Setup the attack effects - Vector vecShootPos; - - GetAttachment( "BellyGun", vecShootPos ); - - EntityMessageBegin( this, true ); - WRITE_BYTE( GUNSHIP_MSG_STREAKS ); - WRITE_VEC3COORD( vecShootPos ); - MessageEnd(); - - CPASAttenuationFilter filter2( this, "NPC_Strider.Charge" ); - EmitSound( filter2, entindex(), "NPC_Strider.Charge" ); - - Vector endpos = GetGroundAttackHitPosition(); - - CSoundEnt::InsertSound ( SOUND_DANGER, endpos, 1024, 0.5f ); - - if ( hl2_episodic.GetBool() == true ) - { - if ( m_hEnergyCore ) - { - variant_t value; - value.SetFloat( 3.0f ); - - g_EventQueue.AddEvent( m_hEnergyCore, "StartCharge", value, 0, this, this ); - } - } -} - -#define GUNSHIP_BELLY_BLAST_RADIUS 256.0f -#define BELLY_BLAST_MAX_PUNCH 5 - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::ManageWarningBeam( void ) -{ - Vector vecSrc, vecShootDir; - GetAttachment( "BellyGun", vecSrc, NULL, NULL, NULL ); - - trace_t tr; - CTraceFilterSkipTwoEntities filter( m_hGroundAttackTarget, this, COLLISION_GROUP_NONE ); - - UTIL_TraceLine( vecSrc, m_vecHitPos, MASK_SOLID, &filter, &tr ); - - int iPunch = 0; - - while ( tr.endpos != m_vecHitPos ) - { - iPunch++; - - if ( iPunch > BELLY_BLAST_MAX_PUNCH ) - break; - - if ( tr.fraction != 1.0 ) - { - if ( tr.m_pEnt ) - { - CTakeDamageInfo info( this, this, 1.0f, DMG_ENERGYBEAM ); - - Vector vTargetDir = tr.m_pEnt->BodyTarget( tr.endpos, false ) - tr.endpos; - - VectorNormalize( vTargetDir ); - - info.SetDamagePosition( tr.endpos + ( tr.plane.normal * 64.0f ) ); - info.SetDamageForce( vTargetDir * 100 ); - - if ( tr.m_pEnt->m_takedamage != DAMAGE_NO ) - { - // Deal damage - tr.m_pEnt->TakeDamage( info ); - } - } - - Vector vDir = m_vecHitPos - vecSrc; - VectorNormalize( vDir ); - - Vector vStartPunch = tr.endpos + vDir * 1; - - UTIL_TraceLine( vStartPunch, m_vecHitPos, MASK_SOLID, &filter, &tr ); - - if ( tr.startsolid ) - { - float flLength = (vStartPunch - tr.endpos).Length(); - - Vector vEndPunch = vStartPunch + vDir * ( flLength * tr.fractionleftsolid ); - - UTIL_TraceLine( vEndPunch, m_vecHitPos, MASK_SOLID, &filter, &tr ); - - trace_t tr2; - UTIL_TraceLine( vEndPunch, vEndPunch - vDir * 2, MASK_SOLID, &filter, &tr2 ); - - if ( (m_flGroundAttackTime - gpGlobals->curtime) <= 2.0f ) - { - g_pEffects->EnergySplash( tr2.endpos + vDir * 8, tr2.plane.normal, true ); - } - - g_pEffects->Sparks( tr2.endpos, (int)(3.0f - (m_flGroundAttackTime-gpGlobals->curtime)), (int)(3.5f - (m_flGroundAttackTime-gpGlobals->curtime)), &tr2.plane.normal ); - - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::DoBellyBlastDamage( trace_t &tr, Vector vMins, Vector vMaxs ) -{ - CBaseEntity* pList[100]; - - if ( g_debug_gunship.GetInt() == GUNSHIP_DEBUG_BELLYBLAST ) - { - NDebugOverlay::Box( tr.endpos, vMins, vMaxs, 255, 255, 0, true, 5.0f ); - } - - int count = UTIL_EntitiesInBox( pList, 100, tr.endpos + vMins, tr.endpos + vMaxs, 0 ); - - for ( int i = 0; i < count; i++ ) - { - CBaseEntity *pEntity = pList[i]; - - if ( pEntity == this ) - continue; - - if ( pEntity->m_takedamage == DAMAGE_NO ) - continue; - - float damage = 150; - - if ( pEntity->IsPlayer() ) - { - float damageDist = ( pEntity->GetAbsOrigin() - tr.endpos ).Length(); - damage = RemapValClamped( damageDist, 0, 300, 200, 0 ); - } - - CTakeDamageInfo info( this, this, damage, DMG_DISSOLVE ); - - Vector vTargetDir = pEntity->BodyTarget( tr.endpos, false ) - tr.endpos; - - VectorNormalize( vTargetDir ); - - info.SetDamagePosition( tr.endpos + ( tr.plane.normal * 64.0f ) ); - info.SetDamageForce( vTargetDir * 25000 ); - - // Deal damage - pEntity->TakeDamage( info ); - - trace_t groundTrace; - UTIL_TraceLine( pEntity->GetAbsOrigin(), pEntity->GetAbsOrigin() - Vector( 0, 0, 256 ), MASK_SOLID, pEntity, COLLISION_GROUP_NONE, &groundTrace ); - - if ( tr.fraction < 1.0f ) - { - CEffectData data; - - // Find the floor and add a dissolve explosion at that point - data.m_flRadius = GUNSHIP_BELLY_BLAST_RADIUS * 0.5f; - data.m_vNormal = groundTrace.plane.normal; - data.m_vOrigin = groundTrace.endpos; - - DispatchEffect( "AR2Explosion", data ); - } - - // If the creature was killed, then dissolve it - if ( pEntity->GetHealth() <= 0.0f ) - { - if ( pEntity->GetBaseAnimating() != NULL && !pEntity->IsEFlagSet( EFL_NO_DISSOLVE ) ) - { - pEntity->GetBaseAnimating()->Dissolve( NULL, gpGlobals->curtime ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::DoGroundAttackExplosion( void ) -{ - // Fire the bullets - Vector vecSrc, vecShootDir; - Vector vecAttachmentOrigin; - GetAttachment( "BellyGun", vecAttachmentOrigin, &vecShootDir, NULL, NULL ); - - vecSrc = vecAttachmentOrigin; - - if ( m_hGroundAttackTarget ) - { - vecSrc = m_hGroundAttackTarget->GetAbsOrigin(); - } - - Vector impactPoint = vecSrc + ( Vector( 0, 0, -1 ) * MAX_TRACE_LENGTH ); - - trace_t tr; - UTIL_TraceLine( vecSrc, impactPoint, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - UTIL_DecalTrace( &tr, "Scorch" ); - - if ( hl2_episodic.GetBool() == true ) - { - g_pEffects->EnergySplash( tr.endpos, tr.plane.normal ); - - CBroadcastRecipientFilter filter; - te->BeamRingPoint( filter, 0.0, - tr.endpos, //origin - 0, //start radius - GUNSHIP_BELLY_BLAST_RADIUS, //end radius - g_iGunshipEffectIndex, //texture - 0, //halo index - 0, //start frame - 0, //framerate - 0.2, //life - 10, //width - 0, //spread - 0, //amplitude - 255, //r - 255, //g - 255, //b - 50, //a - 0, //speed - FBEAM_FADEOUT - ); - } - - // Send the effect over - CEffectData data; - - // Do an extra effect if we struck the world - if ( tr.m_pEnt && tr.m_pEnt->IsWorld() ) - { - data.m_flRadius = GUNSHIP_BELLY_BLAST_RADIUS; - data.m_vNormal = tr.plane.normal; - data.m_vOrigin = tr.endpos; - - DispatchEffect( "AR2Explosion", data ); - } - - float flZLength = vecAttachmentOrigin.z - tr.endpos.z; - - Vector vBeamMins = Vector( -16, -16, 0 ); - Vector vBeamMaxs = Vector( 16, 16, flZLength ); - - DoBellyBlastDamage( tr, vBeamMins, vBeamMaxs ); - - Vector vBlastMins = Vector( -GUNSHIP_BELLY_BLAST_RADIUS, -GUNSHIP_BELLY_BLAST_RADIUS, 0 ); - Vector vBlastMaxs = Vector( GUNSHIP_BELLY_BLAST_RADIUS, GUNSHIP_BELLY_BLAST_RADIUS, 96 ); - - DoBellyBlastDamage( tr, vBlastMins, vBlastMaxs ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::StopGroundAttack( bool bDoAttack ) -{ - if ( !m_bIsGroundAttacking ) - return; - - // Mark us as no longer attacking - m_bIsGroundAttacking = false; - m_flNextGroundAttack = gpGlobals->curtime + 4.0f; - m_flTimeNextAttack = gpGlobals->curtime + 2.0f; - - Vector hitPos = GetGroundAttackHitPosition(); - - // tell the client side effect to complete - EntityMessageBegin( this, true ); - WRITE_BYTE( GUNSHIP_MSG_BIG_SHOT ); - WRITE_VEC3COORD( hitPos ); - MessageEnd(); - - if ( hl2_episodic.GetBool() == true ) - { - if ( m_hEnergyCore ) - { - variant_t value; - value.SetFloat( 1.0f ); - - g_EventQueue.AddEvent( m_hEnergyCore, "Stop", value, 0, this, this ); - } - } - - // Only attack if told to - if ( bDoAttack ) - { - CPASAttenuationFilter filter2( this, "NPC_Strider.Shoot" ); - EmitSound( filter2, entindex(), "NPC_Strider.Shoot"); - - ApplyAbsVelocityImpulse( Vector( 0, 0, 200.0f ) ); - - //ExplosionCreate( hitPos, QAngle( 0, 0, 1 ), this, 500, 500, true ); - DoGroundAttackExplosion(); - } - - // If we were attacking a target, revert to our previous target - if ( m_hGroundAttackTarget ) - { - m_hGroundAttackTarget = NULL; - if ( GetDestPathTarget() ) - { - // Return to our old path - SetupNewCurrentTarget( GetDestPathTarget() ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::DrawRotorWash( float flAltitude, const Vector &vecRotorOrigin ) -{ - // If we have a ragdoll, we want the wash under that, not me - if ( m_hRagdoll ) - { - BaseClass::DrawRotorWash( flAltitude, m_hRagdoll->GetAbsOrigin() ); - return; - } - - BaseClass::DrawRotorWash( flAltitude, vecRotorOrigin ); -} - -//------------------------------------------------------------------------------ -// Purpose : Override the desired position if your derived helicopter is doing something special -//------------------------------------------------------------------------------ -void CNPC_CombineGunship::UpdateDesiredPosition( void ) -{ - if ( m_hCrashTarget ) - { - SetDesiredPosition( m_hCrashTarget->WorldSpaceCenter() + Vector(0,0,128) ); - } - else if ( m_hGroundAttackTarget ) - { - SetDesiredPosition( m_hGroundAttackTarget->GetAbsOrigin() + Vector(0,0,GUNSHIP_BELLYBLAST_TARGET_HEIGHT) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: do all of the stuff related to having an enemy, attacking, etc. -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::DoCombat( void ) -{ - // Check for enemy change-overs - if ( HasEnemy() ) - { - if ( HasCondition( COND_NEW_ENEMY ) ) - { - if ( GetEnemy() && GetEnemy()->IsPlayer() && m_flNextSeeEnemySound < gpGlobals->curtime ) - { - m_flNextSeeEnemySound = gpGlobals->curtime + 5.0; - - if ( !HasSpawnFlags( SF_GUNSHIP_USE_CHOPPER_MODEL ) ) - { - EmitSound( "NPC_CombineGunship.SeeEnemy" ); - } - } - - // If we're shooting at a missile, do it immediately! - if ( IsTargettingMissile() ) - { - EmitSound( "NPC_CombineGunship.SeeMissile" ); - - // Allow the gunship to attack again immediately - if ( ( m_flTimeNextAttack > gpGlobals->curtime ) && ( ( m_flTimeNextAttack - gpGlobals->curtime ) > GUNSHIP_MISSILE_MAX_RESPONSE_TIME ) ) - { - m_flTimeNextAttack = gpGlobals->curtime + GUNSHIP_MISSILE_MAX_RESPONSE_TIME; - m_iBurstSize = sk_gunship_burst_size.GetInt(); - } - } - - // Fade in angry sound, fade out patrol sound. - PlayAngryLoop(); - } - } - - // Do we have a belly blast target? - if ( m_hGroundAttackTarget && !m_bIsGroundAttacking ) - { - // If we're over it, blast. Can't use GetDesiredPosition() because it's not updated yet. - Vector vecTarget = m_hGroundAttackTarget->GetAbsOrigin() + Vector(0,0,GUNSHIP_BELLYBLAST_TARGET_HEIGHT); - Vector vecToTarget = (vecTarget - GetAbsOrigin()); - float flDistance = vecToTarget.Length(); - - // Get the difference between our velocity & the target's velocity - Vector vec2DVelocity = GetAbsVelocity(); - Vector vec2DTargetVelocity = m_hGroundAttackTarget->GetAbsVelocity(); - vec2DVelocity.z = vec2DTargetVelocity.z = 0; - float flVelocityDiff = (vec2DVelocity - vec2DTargetVelocity).Length(); - if ( flDistance < 100 && flVelocityDiff < 200 ) - { - StartGroundAttack(); - } - } - - // Update our firing - if ( m_bIsFiring ) - { - // Fire if we have rounds remaining in this burst - if ( ( m_iBurstSize > 0 ) && ( gpGlobals->curtime > m_flTimeNextAttack ) ) - { - UpdateEnemyTarget(); - FireCannonRound(); - } - else if ( m_iBurstSize < 1 ) - { - // We're done firing - StopCannonBurst(); - - if ( IsTargettingMissile() ) - { - m_flTimeNextAttack = gpGlobals->curtime + 0.5f; - } - } - } - else - { - // If we're not firing, look at the enemy - if ( GetEnemy() ) - { - m_vecAttackPosition = GetEnemy()->EyePosition(); - } - -#ifdef BELLYBLAST - // Check for a ground attack - if ( CheckGroundAttack() ) - { - StartGroundAttack(); - } -#endif - - // See if we're attacking - if ( m_bIsGroundAttacking ) - { - m_vecHitPos = GetGroundAttackHitPosition(); - - ManageWarningBeam(); - - // If our time is up, fire the blast and be done - if ( m_flGroundAttackTime < gpGlobals->curtime ) - { - // Fire! - StopGroundAttack( true ); - } - } - } - - // If we're using the chopper model, align the gun towards the target - if ( HasSpawnFlags( SF_GUNSHIP_USE_CHOPPER_MODEL ) ) - { - Vector vGunPosition; - GetAttachment( "gun", vGunPosition ); - Vector vecToAttackPos = (m_vecAttackPosition - vGunPosition); - PoseGunTowardTargetDirection( vecToAttackPos ); - } - - // Forget flares once I've seen them for a while - float flDeltaSeen = m_flLastSeen - m_flPrevSeen; - if ( GetEnemy() != NULL && GetEnemy()->Classify() == CLASS_FLARE && flDeltaSeen > GUNSHIP_FLARE_IGNORE_TIME ) - { - AddEntityRelationship( GetEnemy(), D_NU, 5 ); - - PlayPatrolLoop(); - - // Forget the flare now. - SetEnemy( NULL ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_CombineGunship::ChooseEnemy( void ) -{ - // If we're firing, don't switch enemies. This stops the gunship occasionally - // stopping a burst before he's really fired at all, which makes him look indecisive. - if ( m_bIsFiring ) - return true; - - return BaseClass::ChooseEnemy(); -} - -//----------------------------------------------------------------------------- -// Purpose: There's a lot of code in here now. We should consider moving -// helicopters and such to scheduled AI. (sjb) -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::MoveHead( void ) -{ - float flYaw = GetPoseParameter( m_poseFlex_Horz ); - float flPitch = GetPoseParameter( m_poseFlex_Vert ); - -/* - This head-turning code will cause the head to POP when switching from looking at the enemy - to looking according to the flight model. I will fix this later. Right now I'm turning - the code over to Ken for some aiming fixups. (sjb) -*/ - - while( 1 ) - { - if ( GetEnemy() != NULL ) - { - Vector vecToEnemy, vecAimDir; - float flDot; - - Vector vTargetPos, vGunPosition; - Vector vecTargetOffset; - QAngle vGunAngles; - - GetAttachment( "muzzle", vGunPosition, vGunAngles ); - - vTargetPos = GetEnemyTarget(); - - VectorSubtract( vTargetPos, vGunPosition, vecToEnemy ); - VectorNormalize( vecToEnemy ); - - // get angles relative to body position - AngleVectors( GetAbsAngles(), &vecAimDir ); - flDot = DotProduct( vecAimDir, vecToEnemy ); - - // Look at Enemy!! - if ( flDot > 0.3f ) - { - float flDiff; - - float flDesiredYaw = VecToYaw(vTargetPos - vGunPosition); - flDiff = UTIL_AngleDiff( flDesiredYaw, vGunAngles.y ) * 0.90; - flYaw = UTIL_Approach( flYaw + flDiff, flYaw, 5.0 ); - - float flDesiredPitch = UTIL_VecToPitch(vTargetPos - vGunPosition); - flDiff = UTIL_AngleDiff( flDesiredPitch, vGunAngles.x ) * 0.90; - flPitch = UTIL_Approach( flPitch + flDiff, flPitch, 5.0 ); - - break; - } - } - - // Look where going! -#if 1 // old way- look according to rotational velocity - flYaw = UTIL_Approach( GetLocalAngularVelocity().y, flYaw, 2.0 * 10 * m_flDeltaT ); - flPitch = UTIL_Approach( GetLocalAngularVelocity().x, flPitch, 2.0 * 10 * m_flDeltaT ); -#else // new way- look towards the next waypoint? - // !!!UNDONE -#endif - break; - } - - // Set the body flexes - SetPoseParameter( m_poseFlex_Vert, flPitch ); - SetPoseParameter( m_poseFlex_Horz, flYaw ); -} - - -//----------------------------------------------------------------------------- -// Purpose: There's a lot of code in here now. We should consider moving -// helicopters and such to scheduled AI. (sjb) -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::PrescheduleThink( void ) -{ - m_flDeltaT = gpGlobals->curtime - GetLastThink(); - - // Are we crashing? - if ( m_flEndDestructTime && gpGlobals->curtime > m_flEndDestructTime ) - { - // We're dead, remove ourselves - SelfDestruct(); - return; - } - - if( m_lifeState == LIFE_ALIVE ) - { - // Chopper doesn't ping - if ( !HasSpawnFlags( SF_GUNSHIP_USE_CHOPPER_MODEL ) ) - { - Ping(); - } - - DoCombat(); - MoveHead(); - } - else if( m_lifeState == LIFE_DYING ) - { - // Increase the number of explosions as he gets closer to death - bool bCreateExplosion = false; - float flTimeLeft = m_flEndDestructTime - gpGlobals->curtime; - if ( flTimeLeft > 1.5 ) - { - bCreateExplosion = (random->RandomInt( 0, 3 ) == 0); - } - else - { - bCreateExplosion = (random->RandomInt( 0, 2 ) == 0); - } - - if ( bCreateExplosion ) - { - Vector explodePoint; - if ( m_hRagdoll ) - { - m_hRagdoll->CollisionProp()->RandomPointInBounds( Vector(0.25,0.25,0.25), Vector(0.75,0.75,0.75), &explodePoint ); - } - else - { - CollisionProp()->RandomPointInBounds( Vector(0.25,0.25,0.25), Vector(0.75,0.75,0.75), &explodePoint ); - - // Knock the gunship a little, but not if we're trying to fly to a point - if ( !m_hCrashTarget ) - { - Vector vecPush = (GetAbsOrigin() - explodePoint); - VectorNormalize( vecPush ); - ApplyAbsVelocityImpulse( vecPush * 128 ); - } - } - - ExplosionCreate( explodePoint, QAngle(0,0,1), this, 100, 128, false ); - } - - // Have we reached our crash point? - if ( m_flNextGunshipCrashFind && !m_hRagdoll ) - { - // Update nearest crash point. The RPG that killed us may have knocked us - // closer to a different point than the one we were near when we first died. - if ( m_flNextGunshipCrashFind < gpGlobals->curtime ) - { - FindNearestGunshipCrash(); - } - - if ( m_hCrashTarget ) - { - MoveHead(); - - UpdateDesiredPosition(); - - // If we're over it, destruct - Vector vecToTarget = (GetDesiredPosition() - GetAbsOrigin()); - if ( vecToTarget.LengthSqr() < (384 * 384) ) - { - BeginDestruct(); - m_OnCrashed.FireOutput( this, this ); - m_hCrashTarget->GunshipCrashedOnTarget(); - return; - } - } - } - } - - BaseClass::PrescheduleThink(); - -#ifdef JACOBS_GUNSHIP - SetPoseParameter( m_posePitch, random->RandomFloat( GUNSHIP_HEAD_MAX_LEFT, GUNSHIP_HEAD_MAX_RIGHT ) ); - SetPoseParameter( m_poseYaw, random->RandomFloat( GUNSHIP_HEAD_MAX_UP, GUNSHIP_HEAD_MAX_DOWN ) ); -#endif - -} - -//------------------------------------------------------------------------------ -// Purpose : If the enemy is in front of the gun, load up a burst. -// Actual gunfire is handled in PrescheduleThink -// Input : -// Output : -//------------------------------------------------------------------------------ -bool CNPC_CombineGunship::FireGun( void ) -{ - if ( m_lifeState != LIFE_ALIVE ) - return false; - - if ( m_bIsGroundAttacking ) - return false; - - if ( GetEnemy() && !m_bIsFiring && gpGlobals->curtime > m_flTimeNextAttack ) - { - // We want to decelerate to attack - if (m_flGoalSpeed > GetMaxSpeedFiring() ) - { - m_flGoalSpeed = GetMaxSpeedFiring(); - } - - bool bTargetingMissile = IsTargettingMissile(); - if ( !bTargetingMissile && !m_bPreFire ) - { - m_bPreFire = true; - m_flTimeNextAttack = gpGlobals->curtime + 0.5f; - - EmitSound( "NPC_CombineGunship.CannonStartSound" ); - return false; - } - - //TODO: Emit the danger noise and wait until it's finished - - // Don't fire at an occluded enemy unless blindfire is on. - if ( HasCondition( COND_ENEMY_OCCLUDED ) && ( m_fBlindfire == false ) ) - return false; - - // Don't shoot if the enemy is too close - if ( !bTargetingMissile && GroundDistToPosition( GetEnemy()->GetAbsOrigin() ) < GUNSHIP_STITCH_MIN ) - return false; - - Vector vecAimDir, vecToEnemy; - Vector vecMuzzle, vecEnemyTarget; - - GetAttachment( "muzzle", vecMuzzle, &vecAimDir, NULL, NULL ); - vecEnemyTarget = GetEnemyTarget(); - - // Aim with the muzzle's attachment point. - VectorSubtract( vecEnemyTarget, vecMuzzle, vecToEnemy ); - - VectorNormalize( vecToEnemy ); - VectorNormalize( vecAimDir ); - - if ( DotProduct( vecToEnemy, vecAimDir ) > 0.9 ) - { - StartCannonBurst( sk_gunship_burst_size.GetInt() ); - return true; - } - - return false; - } - - return false; -} - -//------------------------------------------------------------------------------ -// Purpose: Fire a round from the cannon -// Notes: Only call this if you have an enemy. -//------------------------------------------------------------------------------ -void CNPC_CombineGunship::FireCannonRound( void ) -{ - Vector vecPenetrate; - trace_t tr; - - Vector vecToEnemy, vecEnemyTarget; - Vector vecMuzzle; - Vector vecAimDir; - - GetAttachment( "muzzle", vecMuzzle, &vecAimDir ); - vecEnemyTarget = GetEnemyTarget(); - - // Aim with the muzzle's attachment point. - VectorSubtract( vecEnemyTarget, vecMuzzle, vecToEnemy ); - VectorNormalize( vecToEnemy ); - - // If the gun is wildly off target, stop firing! - // FIXME - this should use a vector pointing - // to the enemy's location PLUS the stitching - // error! (sjb) !!!BUGBUG - - if ( g_debug_gunship.GetInt() == GUNSHIP_DEBUG_STITCHING ) - { - QAngle vecAimAngle; - Vector vForward, vRight, vUp; - GetAttachment( "muzzle", vecMuzzle, &vForward, &vRight, &vUp ); - AngleVectors( vecAimAngle, &vForward, &vRight, &vUp ); - NDebugOverlay::Line( vecMuzzle, vecEnemyTarget, 255, 255, 0, true, 1.0f ); - - NDebugOverlay::Line( vecMuzzle, vecMuzzle + ( vForward * 64.0f ), 255, 0, 0, true, 1.0f ); - NDebugOverlay::Line( vecMuzzle, vecMuzzle + ( vRight * 32.0f ), 0, 255, 0, true, 1.0f ); - NDebugOverlay::Line( vecMuzzle, vecMuzzle + ( vUp * 32.0f ), 0, 0, 255, true, 1.0f ); - } - - // Robin: Check the dotproduct to the enemy, NOT to the offsetted firing angle - // Fixes problems firing at close enemies, where the enemy is valid but - // the offset firing stitch isn't. - Vector vecDotCheck = vecToEnemy; - if ( GetEnemy() ) - { - VectorSubtract( GetEnemy()->GetAbsOrigin(), vecMuzzle, vecDotCheck ); - VectorNormalize( vecDotCheck ); - } - - if ( DotProduct( vecDotCheck, vecAimDir ) < 0.8f ) - { - StopCannonBurst(); - return; - } - - DoMuzzleFlash(); - - m_OnFireCannon.FireOutput( this, this, 0 ); - - m_flTimeNextAttack = gpGlobals->curtime + 0.05f; - - float flPrevHealth = 0; - if ( GetEnemy() ) - { - flPrevHealth = GetEnemy()->GetHealth(); - } - - // Make sure we hit missiles - if ( IsTargettingMissile() ) - { - // Fire a fake shot - FireBullets( 1, vecMuzzle, vecToEnemy, VECTOR_CONE_5DEGREES, 8192, m_iAmmoType, 1 ); - - CBaseEntity *pMissile = GetEnemy(); - - Vector missileDir, threatDir; - - AngleVectors( pMissile->GetAbsAngles(), &missileDir ); - - threatDir = ( WorldSpaceCenter() - pMissile->GetAbsOrigin() ); - float threatDist = VectorNormalize( threatDir ); - - // Check that the target is within some threshold - if ( ( DotProduct( threatDir, missileDir ) > 0.95f ) && ( threatDist < 1024.0f ) ) - { - if ( random->RandomInt( 0, 1 ) == 0 ) - { - CTakeDamageInfo info( this, this, 200, DMG_MISSILEDEFENSE ); - CalculateBulletDamageForce( &info, m_iAmmoType, -threatDir, WorldSpaceCenter() ); - GetEnemy()->TakeDamage( info ); - } - } - else - { - //FIXME: Some other metric - } - } - else - { - m_iBurstSize--; - - // Fire directly at the target - FireBulletsInfo_t info( 1, vecMuzzle, vecToEnemy, vec3_origin, MAX_COORD_RANGE, m_iAmmoType ); - info.m_iTracerFreq = 1; - CAmmoDef *pAmmoDef = GetAmmoDef(); - info.m_iPlayerDamage = pAmmoDef->PlrDamage( m_iAmmoType ); - - // If we've already hit the player, do 0 damage. This ensures we don't hit the - // player multiple times during a single burst. - if ( m_iBurstHits >= GUNSHIP_MAX_HITS_PER_BURST ) - { - info.m_iPlayerDamage = 1; - } - - FireBullets( info ); - - if ( GetEnemy() && flPrevHealth != GetEnemy()->GetHealth() ) - { - m_iBurstHits++; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::DoMuzzleFlash( void ) -{ - BaseClass::DoMuzzleFlash(); - - CEffectData data; - - data.m_nAttachmentIndex = LookupAttachment( "muzzle" ); - data.m_nEntIndex = entindex(); - DispatchEffect( "GunshipMuzzleFlash", data ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_CombineGunship::FVisible( CBaseEntity *pEntity, int traceMask, CBaseEntity **ppBlocker ) -{ - bool fReturn = BaseClass::FVisible( pEntity, traceMask, ppBlocker ); - - if( m_fOmniscient ) - { - if( !fReturn ) - { - // Set this condition so that we can check it later and know that the - // enemy truly is occluded, but the gunship regards it as visible due - // to omniscience. - SetCondition( COND_ENEMY_OCCLUDED ); - } - else - { - ClearCondition( COND_ENEMY_OCCLUDED ); - } - - return true; - } - - if( fReturn ) - { - ClearCondition( COND_ENEMY_OCCLUDED ); - } - else - { - SetCondition( COND_ENEMY_OCCLUDED ); - } - - return fReturn; -} - - -//----------------------------------------------------------------------------- -// Purpose: Change the depth that gunship bullets can penetrate through solids -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::InputSetPenetrationDepth( inputdata_t &inputdata ) -{ - m_flPenetrationDepth = inputdata.value.Float(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Allow the gunship to sense its enemy's location even when enemy -// is hidden from sight. -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::InputOmniscientOn( inputdata_t &inputdata ) -{ - m_fOmniscient = true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns the gunship to its default requirement that it see the -// enemy to know its current position -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::InputOmniscientOff( inputdata_t &inputdata ) -{ - m_fOmniscient = false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Allows the gunship to fire at an unseen enemy. The gunship is relying -// on hitting the target with bullets that will punch through the -// cover that the enemy is hiding behind. (Such as the Depot lighthouse) -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::InputBlindfireOn( inputdata_t &inputdata ) -{ - m_fBlindfire = true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns the gunship to default rules for attacking the enemy. The -// enemy must be seen to be fired at. -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::InputBlindfireOff( inputdata_t &inputdata ) -{ - m_fBlindfire = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Set the gunship's paddles flailing! -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::Event_Killed( const CTakeDamageInfo &info ) -{ - m_takedamage = DAMAGE_NO; - - StopCannonBurst(); - - // Replace the rotor sound with broken engine sound. - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundDestroy( m_pRotorSound ); - - // BUGBUG: Isn't this sound just going to get stomped when the base class calls StopLoopingSounds() ?? - CPASAttenuationFilter filter2( this ); - m_pRotorSound = controller.SoundCreate( filter2, entindex(), "NPC_CombineGunship.DyingSound" ); - controller.Play( m_pRotorSound, 1.0, 100 ); - - m_OnDeath.FireOutput( info.GetAttacker(), this ); - SendOnKilledGameEvent( info ); - - BeginCrash(); - - // we deliberately do not call BaseClass::EventKilled -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::BeginCrash( void ) -{ - m_lifeState = LIFE_DYING; - StopGroundAttack( false ); - - // Increase our smoke trail - CreateSmokeTrail(); - if ( m_pSmokeTrail ) - { - m_pSmokeTrail->SetLifetime( -1 ); - m_pSmokeTrail->m_StartSize = 64; - m_pSmokeTrail->m_EndSize = 128; - m_pSmokeTrail->m_Opacity = 0.5f; - } - - if ( !FindNearestGunshipCrash() ) - { - // We couldn't find a crash target, so just die right here. - BeginDestruct(); - return; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_CombineGunship::FindNearestGunshipCrash( void ) -{ - // Find the nearest crash point. If we find one, we'll try to fly to it and die. - // If we can't find one, we'll die right here. - bool bFoundAnyCrashTargets = false; - float flNearest = MAX_TRACE_LENGTH * MAX_TRACE_LENGTH; - CTargetGunshipCrash *pNearest = NULL; - CBaseEntity *pEnt = NULL; - while( (pEnt = gEntList.FindEntityByClassname(pEnt, "info_target_gunshipcrash")) != NULL ) - { - CTargetGunshipCrash *pCrashTarget = assert_cast(pEnt); - if ( pCrashTarget->IsDisabled() ) - continue; - - bFoundAnyCrashTargets = true; - - float flDist = ( pEnt->WorldSpaceCenter() - WorldSpaceCenter() ).LengthSqr(); - if( flDist < flNearest ) - { - trace_t tr; - UTIL_TraceLine( WorldSpaceCenter(), pEnt->WorldSpaceCenter(), MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr ); - if( tr.fraction == 1.0 ) - { - pNearest = pCrashTarget; - flNearest = flDist; - } - else if ( g_debug_gunship.GetInt() ) - { - NDebugOverlay::Line( WorldSpaceCenter(), tr.endpos, 255,0,0, true, 99); - } - } - } - - if ( !pNearest ) - { - // If we found a gunship crash, but none near enough, claim we did find one, so that we - // don't blow up yet. This will give us 3 seconds to attempt to find one before dying. - if ( !m_hCrashTarget && bFoundAnyCrashTargets ) - { - m_flNextGunshipCrashFind = gpGlobals->curtime + 0.5; - m_flEndDestructTime = gpGlobals->curtime + 3.0; - return true; - } - - return false; - } - - // Fly to the crash point and destruct there - m_hCrashTarget = pNearest; - m_flNextGunshipCrashFind = gpGlobals->curtime + 0.5; - m_flEndDestructTime = 0; - - if ( g_debug_gunship.GetInt() ) - { - NDebugOverlay::Line(GetAbsOrigin(), m_hCrashTarget->GetAbsOrigin(), 0,255,0, true, 0.5); - NDebugOverlay::Box( m_hCrashTarget->GetAbsOrigin(), -Vector(200,200,200), Vector(200,200,200), 0,255,0, 128, 0.5 ); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: I'm now ready to die. Create my ragdoll & hide myself. -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::BeginDestruct( void ) -{ - m_flEndDestructTime = gpGlobals->curtime + 3.0; - - // Clamp velocity - if( hl2_episodic.GetBool() && GetAbsVelocity().Length() > 700.0f ) - { - Vector vecVelocity = GetAbsVelocity(); - VectorNormalize( vecVelocity ); - SetAbsVelocity( vecVelocity * 700.0f ); - } - - CTakeDamageInfo info; - info.SetDamage( 40000 ); - CalculateExplosiveDamageForce( &info, GetAbsVelocity(), GetAbsOrigin() ); - - // Don't create a ragdoll if we're going to explode into gibs - if ( !m_hCrashTarget ) - return; - - // Switch to damaged skin - m_nSkin = 1; - - if ( HasSpawnFlags( SF_GUNSHIP_USE_CHOPPER_MODEL ) ) - { - Chopper_BecomeChunks( this ); - SetThink( &CNPC_CombineGunship::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 0.1f ); - AddEffects( EF_NODRAW ); - return; - } - - // Create the ragdoll - m_hRagdoll = CreateServerRagdoll( this, 0, info, COLLISION_GROUP_NONE ); - if ( !m_hRagdoll ) - { - // Failed, just explode - SelfDestruct(); - return; - } - - m_hRagdoll->SetName( AllocPooledString( UTIL_VarArgs("%s_ragdoll", STRING(GetEntityName())) ) ); - - // Tell the smoke trail to follow the ragdoll - CreateSmokeTrail(); - if ( m_pSmokeTrail ) - { - // Force the smoke trail to stay on, and tell it to follow the ragdoll - m_pSmokeTrail->SetLifetime( -1 ); - m_pSmokeTrail->FollowEntity( m_hRagdoll ); - - m_pSmokeTrail->m_StartSize = 64; - m_pSmokeTrail->m_EndSize = 128; - m_pSmokeTrail->m_Opacity = 0.5f; - } - - /* - // ROBIN: Disabled this for now. - // - // Create the crashing controller and attach it to the ragdoll physics objects - m_pCrashingController = physenv->CreateMotionController( &m_crashCallback ); - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int count = m_hRagdoll->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - for ( int i = 0; i < count; i++ ) - { - m_pCrashingController->AttachObject( pList[i], false ); - } - */ - - // Hide myself, because the ragdoll's now taken my place - AddEffects( EF_NODRAW ); - AddSolidFlags( FSOLID_NOT_SOLID ); -} - -//----------------------------------------------------------------------------- -// Purpose: Create a smoke trail -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::CreateSmokeTrail( void ) -{ - if ( m_pSmokeTrail ) - return; - - m_pSmokeTrail = SmokeTrail::CreateSmokeTrail(); - - if ( m_pSmokeTrail ) - { - m_pSmokeTrail->m_SpawnRate = 48; - m_pSmokeTrail->m_ParticleLifetime = 2.5f; - - m_pSmokeTrail->m_StartColor.Init( 0.25f, 0.25f, 0.25f ); - m_pSmokeTrail->m_EndColor.Init( 0.0, 0.0, 0.0 ); - - m_pSmokeTrail->m_StartSize = 24; - m_pSmokeTrail->m_EndSize = 128; - m_pSmokeTrail->m_SpawnRadius = 4; - m_pSmokeTrail->m_MinSpeed = 8; - m_pSmokeTrail->m_MaxSpeed = 64; - m_pSmokeTrail->m_Opacity = 0.2f; - - m_pSmokeTrail->SetLifetime( -1 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::ApplyGeneralDrag( void ) -{ - Vector vecNewVelocity = GetAbsVelocity(); - - // See if we need to stop more quickly - if ( m_bIsGroundAttacking ) - { - vecNewVelocity *= 0.95f; - } - else - { - vecNewVelocity *= 0.995; - } - - SetAbsVelocity( vecNewVelocity ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -void CNPC_CombineGunship::Flight( void ) -{ - if( GetFlags() & FL_ONGROUND ) - { - //This would be really bad. - SetGroundEntity( NULL ); - } - - if ( g_debug_gunship.GetInt() == GUNSHIP_DEBUG_PATH ) - { - NDebugOverlay::Line(GetLocalOrigin(), GetDesiredPosition(), 0,0,255, true, 0.1); - } - - // calc desired acceleration - float dt = 1.0f; - - Vector accel; - float accelRate = GUNSHIP_ACCEL_RATE; - float maxSpeed = GetMaxSpeed(); - - if ( m_lifeState == LIFE_DYING && m_hCrashTarget != NULL ) - { - // Gunship can fly faster to the place where it's supposed to crash, but - // maintain normal speeds if we haven't found a place to crash. - accelRate *= 2.0; - maxSpeed *= 4.0; - } - - float flCurrentSpeed = GetAbsVelocity().Length(); - float flDist = MIN( flCurrentSpeed + accelRate, maxSpeed ); - - Vector deltaPos; - if ( m_lifeState == LIFE_DYING || m_hGroundAttackTarget ) - { - // Move directly to the target point - deltaPos = GetDesiredPosition(); - } - else - { - ComputeActualTargetPosition( flDist, dt, 0.0f, &deltaPos ); - } - deltaPos -= GetAbsOrigin(); - - // calc goal linear accel to hit deltaPos in dt time. - accel.x = 2.0 * (deltaPos.x - GetAbsVelocity().x * dt) / (dt * dt); - accel.y = 2.0 * (deltaPos.y - GetAbsVelocity().y * dt) / (dt * dt); - accel.z = 2.0 * (deltaPos.z - GetAbsVelocity().z * dt + 0.5 * 384 * dt * dt) / (dt * dt); - - float flDistFromPath = 0.0f; - Vector vecPoint, vecDelta; - if ( m_lifeState != LIFE_DYING && IsOnPathTrack() ) - { - // Also, add in a little force to get us closer to our current line segment if we can - ClosestPointToCurrentPath( &vecPoint ); - VectorSubtract( vecPoint, GetAbsOrigin(), vecDelta ); - flDistFromPath = VectorNormalize( vecDelta ); - if ( flDistFromPath > GUNSHIP_OUTER_NAV_DIST ) - { - // Strongly constrain to an n unit pipe around the current path - // by damping out all impulse forces that would push us further from the pipe - float flAmount = (flDistFromPath - GUNSHIP_OUTER_NAV_DIST) / 200.0f; - flAmount = clamp( flAmount, 0, 1 ); - VectorMA( accel, flAmount * 200.0f, vecDelta, accel ); - } - } - - Vector vecAvoidForce; - CAvoidSphere::ComputeAvoidanceForces( this, 350.0f, 2.0f, &vecAvoidForce ); - accel += vecAvoidForce; - CAvoidBox::ComputeAvoidanceForces( this, 350.0f, 2.0f, &vecAvoidForce ); - accel += vecAvoidForce; - - if ( m_lifeState != LIFE_DYING || m_hCrashTarget == NULL ) - { - // don't fall faster than 0.2G or climb faster than 2G - accel.z = clamp( accel.z, 384 * 0.2, 384 * 2.0 ); - } - - Vector forward, right, up; - GetVectors( &forward, &right, &up ); - - Vector goalUp = accel; - VectorNormalize( goalUp ); - - // calc goal orientation to hit linear accel forces - float goalPitch = RAD2DEG( asin( DotProduct( forward, goalUp ) ) ); - float goalYaw = UTIL_VecToYaw( m_vecDesiredFaceDir ); - float goalRoll = RAD2DEG( asin( DotProduct( right, goalUp ) ) ); - - // clamp goal orientations - goalPitch = clamp( goalPitch, -45, 60 ); - goalRoll = clamp( goalRoll, -45, 45 ); - - // calc angular accel needed to hit goal pitch in dt time. - dt = 0.6; - QAngle goalAngAccel; - goalAngAccel.x = 2.0 * (AngleDiff( goalPitch, AngleNormalize( GetLocalAngles().x ) ) - GetLocalAngularVelocity().x * dt) / (dt * dt); - goalAngAccel.y = 2.0 * (AngleDiff( goalYaw, AngleNormalize( GetLocalAngles().y ) ) - GetLocalAngularVelocity().y * dt) / (dt * dt); - goalAngAccel.z = 2.0 * (AngleDiff( goalRoll, AngleNormalize( GetLocalAngles().z ) ) - GetLocalAngularVelocity().z * dt) / (dt * dt); - - goalAngAccel.x = clamp( goalAngAccel.x, -300, 300 ); - //goalAngAccel.y = clamp( goalAngAccel.y, -60, 60 ); - goalAngAccel.y = clamp( goalAngAccel.y, -120, 120 ); - goalAngAccel.z = clamp( goalAngAccel.z, -300, 300 ); - - // limit angular accel changes to similate mechanical response times - dt = 0.1; - QAngle angAccelAccel; - angAccelAccel.x = (goalAngAccel.x - m_vecAngAcceleration.x) / dt; - angAccelAccel.y = (goalAngAccel.y - m_vecAngAcceleration.y) / dt; - angAccelAccel.z = (goalAngAccel.z - m_vecAngAcceleration.z) / dt; - - angAccelAccel.x = clamp( angAccelAccel.x, -1000, 1000 ); - angAccelAccel.y = clamp( angAccelAccel.y, -1000, 1000 ); - angAccelAccel.z = clamp( angAccelAccel.z, -1000, 1000 ); - - m_vecAngAcceleration += angAccelAccel * 0.1; - - // DevMsg( "pitch %6.1f (%6.1f:%6.1f) ", goalPitch, GetLocalAngles().x, m_vecAngVelocity.x ); - // DevMsg( "roll %6.1f (%6.1f:%6.1f) : ", goalRoll, GetLocalAngles().z, m_vecAngVelocity.z ); - // DevMsg( "%6.1f %6.1f %6.1f : ", goalAngAccel.x, goalAngAccel.y, goalAngAccel.z ); - // DevMsg( "%6.0f %6.0f %6.0f\n", angAccelAccel.x, angAccelAccel.y, angAccelAccel.z ); - - ApplySidewaysDrag( right ); - ApplyGeneralDrag(); - - QAngle angVel = GetLocalAngularVelocity(); - angVel += m_vecAngAcceleration * 0.1; - - //angVel.y = clamp( angVel.y, -60, 60 ); - //angVel.y = clamp( angVel.y, -120, 120 ); - angVel.y = clamp( angVel.y, -120, 120 ); - - SetLocalAngularVelocity( angVel ); - - m_flForce = m_flForce * 0.8 + (accel.z + fabs( accel.x ) * 0.1 + fabs( accel.y ) * 0.1) * 0.1 * 0.2; - - Vector vecImpulse = m_flForce * up; - - if ( !m_hCrashTarget && m_lifeState == LIFE_DYING && !hl2_episodic.GetBool() ) - { - // Force gunship to the ground if it doesn't have a specific place to crash. - // EXCEPT In episodic, where forcing it to the ground means it crashes where the player can't see (attic showdown) (sjb) - vecImpulse.z = -10; - } - else - { - vecImpulse.z -= 38.4; // 32ft/sec - } - - // Find our current velocity - Vector vecVelDir = GetAbsVelocity(); - VectorNormalize( vecVelDir ); - - if ( flDistFromPath > GUNSHIP_INNER_NAV_DIST ) - { - // Strongly constrain to an n unit pipe around the current path - // by damping out all impulse forces that would push us further from the pipe - float flDot = DotProduct( vecImpulse, vecDelta ); - if ( flDot < 0.0f ) - { - VectorMA( vecImpulse, -flDot * 0.1f, vecDelta, vecImpulse ); - } - - // Also apply an extra impulse to compensate for the current velocity - flDot = DotProduct( vecVelDir, vecDelta ); - if ( flDot < 0.0f ) - { - VectorMA( vecImpulse, -flDot * 0.1f, vecDelta, vecImpulse ); - } - } - - // Find our acceleration direction - Vector vecAccelDir = vecImpulse; - VectorNormalize( vecAccelDir ); - - // Level out our plane of movement - vecAccelDir.z = 0.0f; - vecVelDir.z = 0.0f; - forward.z = 0.0f; - right.z = 0.0f; - - // Find out how "fast" we're moving in relation to facing and acceleration - float speed = m_flForce * DotProduct( vecVelDir, vecAccelDir );// * DotProduct( forward, vecVelDir ); - - // Apply the acceleration blend to the fins - float finAccelBlend = SimpleSplineRemapVal( speed, -60, 60, -1, 1 ); - float curFinAccel = GetPoseParameter( m_poseFin_Accel ); - - curFinAccel = UTIL_Approach( finAccelBlend, curFinAccel, 0.5f ); - SetPoseParameter( m_poseFin_Accel, curFinAccel ); - - speed = m_flForce * DotProduct( vecVelDir, right ); - - // Apply the spin sway to the fins - float finSwayBlend = SimpleSplineRemapVal( speed, -60, 60, -1, 1 ); - float curFinSway = GetPoseParameter( m_poseFin_Sway ); - - curFinSway = UTIL_Approach( finSwayBlend, curFinSway, 0.5f ); - SetPoseParameter( m_poseFin_Sway, curFinSway ); - - if ( g_debug_gunship.GetInt() == GUNSHIP_DEBUG_PATH ) - { - NDebugOverlay::Line(GetLocalOrigin(), GetLocalOrigin() + vecImpulse, 255,0,0, true, 0.1); - } - - // Add in our velocity pulse for this frame - ApplyAbsVelocityImpulse( vecImpulse ); -} - -//------------------------------------------------------------------------------ -// Updates the facing direction -//------------------------------------------------------------------------------ -void CNPC_CombineGunship::UpdateFacingDirection( void ) -{ - if ( GetEnemy() ) - { - if ( !IsCrashing() && m_flLastSeen + 5 > gpGlobals->curtime ) - { - // If we've seen the target recently, face the target. - //Msg( "Facing Target \n" ); - m_vecDesiredFaceDir = m_vecTargetPosition - GetAbsOrigin(); - } - else - { - // Remain facing the way you were facing... - } - } - else - { - // Face our desired position. - if ( GetDesiredPosition().DistToSqr( GetAbsOrigin() ) > 1 ) - { - m_vecDesiredFaceDir = GetDesiredPosition() - GetAbsOrigin(); - } - else - { - GetVectors( &m_vecDesiredFaceDir, NULL, NULL ); - } - } - VectorNormalize( m_vecDesiredFaceDir ); -} - -//------------------------------------------------------------------------------ -// Purpose : Fire up the Gunships 'second' rotor sound. The Search sound. -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_CombineGunship::InitializeRotorSound( void ) -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - - CPASAttenuationFilter filter( this ); - - m_pCannonSound = controller.SoundCreate( filter, entindex(), "NPC_CombineGunship.CannonSound" ); - m_pRotorSound = controller.SoundCreate( filter, entindex(), "NPC_CombineGunship.RotorSound" ); - m_pAirExhaustSound = controller.SoundCreate( filter, entindex(), "NPC_CombineGunship.ExhaustSound" ); - m_pAirBlastSound = controller.SoundCreate( filter, entindex(), "NPC_CombineGunship.RotorBlastSound" ); - - controller.Play( m_pCannonSound, 0.0, 100 ); - controller.Play( m_pAirExhaustSound, 0.0, 100 ); - controller.Play( m_pAirBlastSound, 0.0, 100 ); - - BaseClass::InitializeRotorSound(); -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_CombineGunship::UpdateRotorSoundPitch( int iPitch ) -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - - // Apply the pitch to both sounds. - controller.SoundChangePitch( m_pAirExhaustSound, iPitch, 0.1 ); - - // FIXME: Doesn't work in multiplayer - CBaseEntity *pPlayer = UTIL_PlayerByIndex(1); - if (pPlayer) - { - Vector pos; - Vector up; - GetAttachment( "rotor", pos, NULL, NULL, &up ); - - float flDistance = (pPlayer->WorldSpaceCenter() - pos).Length2DSqr(); - - // Fade in exhaust when we're far from the player - float flVolume = clamp( RemapVal( flDistance, (900*900), (1800*1800), 1, 0 ), 0, 1 ); - controller.SoundChangeVolume( m_pAirExhaustSound, flVolume * GetRotorVolume(), 0.1 ); - - // Fade in the blast when it's close to the player (in 2D) - flVolume = clamp( RemapVal( flDistance, (600*600), (700*700), 1, 0 ), 0, 1 ); - controller.SoundChangeVolume( m_pAirBlastSound, flVolume * GetRotorVolume(), 0.1 ); - } - - BaseClass::UpdateRotorSoundPitch( iPitch ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::ApplySidewaysDrag( const Vector &vecRight ) -{ - Vector vecVelocity = GetAbsVelocity(); - if( m_lifeState == LIFE_ALIVE ) - { - vecVelocity.x *= (1.0 - fabs( vecRight.x ) * 0.04); - vecVelocity.y *= (1.0 - fabs( vecRight.y ) * 0.04); - vecVelocity.z *= (1.0 - fabs( vecRight.z ) * 0.04); - } - else - { - vecVelocity.x *= (1.0 - fabs( vecRight.x ) * 0.03); - vecVelocity.y *= (1.0 - fabs( vecRight.y ) * 0.03); - vecVelocity.z *= (1.0 - fabs( vecRight.z ) * 0.09); - } - SetAbsVelocity( vecVelocity ); -} - -//------------------------------------------------------------------------------ -// Purpose: Explode the gunship. -//------------------------------------------------------------------------------ -void CNPC_CombineGunship::SelfDestruct( void ) -{ - SetThink( NULL ); - m_lifeState = LIFE_DEAD; - - StopLoopingSounds(); - StopCannonBurst(); - - Vector vecVelocity = GetAbsVelocity(); - vecVelocity.z = 0.0; // stop falling. - SetAbsVelocity( vecVelocity ); - - CBaseEntity *pBreakEnt = this; - - // If we've ragdolled, play the explosions on the ragdoll instead - Vector vecOrigin; - if ( m_hRagdoll ) - { - m_hRagdoll->EmitSound( "NPC_CombineGunship.Explode" ); - vecOrigin = m_hRagdoll->GetAbsOrigin(); - pBreakEnt = m_hRagdoll; - } - else - { - EmitSound( "NPC_CombineGunship.Explode" ); - vecOrigin = GetAbsOrigin(); - } - - // Create some explosions on the gunship body - Vector vecDelta; - for( int i = 0 ; i < 6 ; i++ ) - { - vecDelta = RandomVector( -200,200 ); - ExplosionCreate( vecOrigin + vecDelta, QAngle( -90, 0, 0 ), this, 10, 10, false ); - } - - AR2Explosion *pExplosion = AR2Explosion::CreateAR2Explosion( vecOrigin ); - if ( pExplosion ) - { - pExplosion->SetLifetime( 10 ); - } - - // If we don't have a crash target, explode into chunks - if ( !m_hCrashTarget ) - { - Vector angVelocity; - QAngleToAngularImpulse( pBreakEnt->GetLocalAngularVelocity(), angVelocity ); - PropBreakableCreateAll( pBreakEnt->GetModelIndex(), pBreakEnt->VPhysicsGetObject(), pBreakEnt->GetAbsOrigin(), pBreakEnt->GetAbsAngles(), pBreakEnt->GetAbsVelocity(), angVelocity, 1.0, 800, COLLISION_GROUP_NPC, pBreakEnt ); - - // Throw out some small chunks too - CPVSFilter filter( GetAbsOrigin() ); - for ( int i = 0; i < 20; i++ ) - { - Vector gibVelocity = RandomVector(-100,100) * 10; - int iModelIndex = modelinfo->GetModelIndex( g_PropDataSystem.GetRandomChunkModel( "MetalChunks" ) ); - te->BreakModel( filter, 0.0, GetAbsOrigin(), vec3_angle, Vector(40,40,40), gibVelocity, iModelIndex, 400, 1, 2.5, BREAK_METAL ); - } - - if ( m_hRagdoll ) - { - UTIL_Remove( m_hRagdoll ); - } - } - else - { - if ( m_pSmokeTrail ) - { - // If we have a ragdoll, let it smoke for a few more seconds - if ( m_hRagdoll ) - { - m_pSmokeTrail->SetLifetime(3.0f); - } - else - { - m_pSmokeTrail->SetLifetime(0.1f); - } - m_pSmokeTrail = NULL; - } - } - - UTIL_Remove( this ); - - // Record this so a nearby citizen can respond. - if ( GetCitizenResponse() ) - { - GetCitizenResponse()->AddResponseTrigger( CR_PLAYER_KILLED_GUNSHIP ); - } - -#ifdef HL2_EPISODIC - NPCEventResponse()->TriggerEvent( "TLK_CITIZEN_RESPONSE_KILLED_GUNSHIP", false, false ); -#endif -} - - -//------------------------------------------------------------------------------ -// Purpose : Explode the gunship. -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_CombineGunship::InputSelfDestruct( inputdata_t &inputdata ) -{ - BeginCrash(); -} - -//------------------------------------------------------------------------------ -// Purpose : Shrink the gunship's bbox so that it fits in docking bays -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_CombineGunship::InputSetDockingBBox( inputdata_t &inputdata ) -{ - Vector vecSize( 32, 32, 32 ); - - UTIL_SetSize( this, vecSize * -1, vecSize ); -} - -//------------------------------------------------------------------------------ -// Purpose : Set the gunship BBox to normal size -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_CombineGunship::InputSetNormalBBox( inputdata_t &inputdata ) -{ - Vector vecBBMin, vecBBMax; - - ExtractBbox( SelectHeaviestSequence( ACT_GUNSHIP_PATROL ), vecBBMin, vecBBMax ); - - // Trim the bounding box a bit. It's huge. -#define GUNSHIP_TRIM_BOX 38 - vecBBMin.x += GUNSHIP_TRIM_BOX; - vecBBMax.x -= GUNSHIP_TRIM_BOX; - vecBBMin.y += GUNSHIP_TRIM_BOX; - vecBBMax.y -= GUNSHIP_TRIM_BOX; - - UTIL_SetSize( this, vecBBMin, vecBBMax ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::InputEnableGroundAttack( inputdata_t &inputdata ) -{ - m_bCanGroundAttack = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::InputDisableGroundAttack( inputdata_t &inputdata ) -{ - m_bCanGroundAttack = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::InputDoGroundAttack( inputdata_t &inputdata ) -{ - // Was a target node specified? - CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, inputdata.value.StringID(), NULL, inputdata.pActivator, inputdata.pCaller ); - if ( pEntity ) - { - // Mapmaker wants us to ground attack a specific target - m_hGroundAttackTarget = pEntity; - } - else - { - StartGroundAttack(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &vGunPosition - -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::UpdateEnemyTarget( void ) -{ - Vector vGunPosition; - - GetAttachment( "muzzle", vGunPosition ); - - // Follow mode - Vector enemyPos; - bool bTargettingPlayer; - - if ( GetEnemy() != NULL ) - { - CBaseCombatCharacter *pCCEnemy = GetEnemy()->MyCombatCharacterPointer(); - if ( pCCEnemy != NULL && pCCEnemy->IsInAVehicle() ) - { - // Update against a driving target - enemyPos = GetEnemy()->WorldSpaceCenter(); - } - else - { - enemyPos = GetEnemy()->EyePosition(); - } - bTargettingPlayer = GetEnemy()->IsPlayer(); - } - else - { - enemyPos = m_vecAttackPosition; - bTargettingPlayer = false; - } - - // Direction towards the enemy - Vector targetDir = enemyPos - m_vecAttackPosition; - VectorNormalize( targetDir ); - - // Direction from the gunship to the enemy - Vector enemyDir = enemyPos - vGunPosition; - VectorNormalize( enemyDir ); - - float lastSpeed = VectorNormalize( m_vecAttackVelocity ); - QAngle chaseAngles, lastChaseAngles; - - VectorAngles( targetDir, chaseAngles ); - VectorAngles( m_vecAttackVelocity, lastChaseAngles ); - - // Debug info - if ( g_debug_gunship.GetInt() == GUNSHIP_DEBUG_STITCHING ) - { - // Final position - NDebugOverlay::Cross3D( m_vecAttackPosition, -Vector(2,2,2), Vector(2,2,2), 0, 0, 255, true, 4.0f ); - } - - float yawDiff = UTIL_AngleDiff( lastChaseAngles[YAW], chaseAngles[YAW] ); - - int maxYaw; - if ( bTargettingPlayer ) - { - maxYaw = 6; - } - else - { - maxYaw = 30; - } - - yawDiff = clamp( yawDiff, -maxYaw, maxYaw ); - - chaseAngles[PITCH] = 0.0f; - chaseAngles[ROLL] = 0.0f; - - bool bMaxHits = ( m_iBurstHits >= GUNSHIP_MAX_HITS_PER_BURST || (GetEnemy() && !GetEnemy()->IsAlive()) ); - - if ( bMaxHits ) - { - // We've hit our target. Stop chasing, and return to max speed. - chaseAngles[YAW] = lastChaseAngles[YAW]; - lastSpeed = BASE_STITCH_VELOCITY; - } - else - { - // Move towards the target yaw - chaseAngles[YAW] = UTIL_AngleMod( lastChaseAngles[YAW] - yawDiff ); - } - - // If we've hit the target already, or we're not close enough to it, then just stitch along - if ( bMaxHits || ( m_vecAttackPosition - enemyPos ).LengthSqr() > (64 * 64) ) - { - AngleVectors( chaseAngles, &targetDir ); - - // Update our new velocity - m_vecAttackVelocity = targetDir * lastSpeed; - - if ( g_debug_gunship.GetInt() == GUNSHIP_DEBUG_STITCHING ) - { - NDebugOverlay::Line( m_vecAttackPosition, m_vecAttackPosition + (m_vecAttackVelocity * 0.1), 255, 0, 0, true, 4.0f ); - } - - // Move along that velocity for this step in time - m_vecAttackPosition += ( m_vecAttackVelocity * 0.1f ); - m_vecAttackPosition.z = enemyPos.z; - } - else - { - // Otherwise always continue to hit an NPC when close enough - m_vecAttackPosition = enemyPos; - } -} - -//------------------------------------------------------------------------------ -// Purpose: Utility function to aim the helicopter gun at the direction -//------------------------------------------------------------------------------ -bool CNPC_CombineGunship::PoseGunTowardTargetDirection( const Vector &vTargetDir ) -{ - Vector vecOut; - VectorIRotate( vTargetDir, EntityToWorldTransform(), vecOut ); - - QAngle angles; - VectorAngles(vecOut, angles); - angles.y = AngleNormalize( angles.y ); - angles.x = AngleNormalize( angles.x ); - - if (angles.x > m_angGun.x) - { - m_angGun.x = MIN( angles.x, m_angGun.x + 12 ); - } - if (angles.x < m_angGun.x) - { - m_angGun.x = MAX( angles.x, m_angGun.x - 12 ); - } - if (angles.y > m_angGun.y) - { - m_angGun.y = MIN( angles.y, m_angGun.y + 12 ); - } - if (angles.y < m_angGun.y) - { - m_angGun.y = MAX( angles.y, m_angGun.y - 12 ); - } - - SetPoseParameter( m_poseWeapon_Pitch, -m_angGun.x ); - SetPoseParameter( m_poseWeapon_Yaw, m_angGun.y ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Vector -//----------------------------------------------------------------------------- -Vector CNPC_CombineGunship::GetMissileTarget( void ) -{ - return GetEnemy()->GetAbsOrigin(); -} - -//------------------------------------------------------------------------------ -// Purpose : Get the target position for the enemy- the position we fire upon. -// this is often modified by m_flAttackOffset to provide the 'stitching' -// behavior that's so popular with the kids these days (sjb) -// -// Input : vGunPosition - location of gunship's muzzle -// : pTarget = vector to paste enemy target into. -// Output : -//------------------------------------------------------------------------------ -Vector CNPC_CombineGunship::GetEnemyTarget( void ) -{ - // Make sure we have an enemy - if ( GetEnemy() == NULL ) - return m_vecAttackPosition; - - // If we're locked onto a missile, use special code to try and destroy it - if ( IsTargettingMissile() ) - return GetMissileTarget(); - - return m_vecAttackPosition; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &tr - -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::DoImpactEffect( trace_t &tr, int nDamageType ) -{ - UTIL_ImpactTrace( &tr, nDamageType, "ImpactGunship" ); - - // These glow effects don't sort properly, so they're cut for E3 2003 (sjb) -#if 0 - CEffectData data; - - data.m_vOrigin = tr.endpos; - data.m_vNormal = vec3_origin; - data.m_vAngles = vec3_angle; - - DispatchEffect( "GunshipImpact", data ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Make the gunship's signature blue tracer! -// Input : &vecTracerSrc - -// &tr - -// iTracerType - -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ) -{ - switch ( iTracerType ) - { - case TRACER_LINE: - { - float flTracerDist; - Vector vecDir; - Vector vecEndPos; - - vecDir = tr.endpos - vecTracerSrc; - - flTracerDist = VectorNormalize( vecDir ); - - UTIL_Tracer( vecTracerSrc, tr.endpos, 0, TRACER_DONT_USE_ATTACHMENT, 8000, true, "GunshipTracer" ); - } - break; - - default: - BaseClass::MakeTracer( vecTracerSrc, tr, iTracerType ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -// &vecDir - -// *ptr - -// Output : int -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - // Reflect bullets - if ( info.GetDamageType() & DMG_BULLET ) - { - if ( random->RandomInt( 0, 2 ) == 0 ) - { - Vector vecRicochetDir = vecDir * -1; - - vecRicochetDir.x += random->RandomFloat( -0.5, 0.5 ); - vecRicochetDir.y += random->RandomFloat( -0.5, 0.5 ); - vecRicochetDir.z += random->RandomFloat( -0.5, 0.5 ); - - VectorNormalize( vecRicochetDir ); - - Vector end = ptr->endpos + vecRicochetDir * 1024; - UTIL_Tracer( ptr->endpos, end, entindex(), TRACER_DONT_USE_ATTACHMENT, 3500 ); - } - - // If this is from a player, record it so a nearby citizen can respond. - if ( info.GetAttacker()->IsPlayer() ) - { - if ( GetCitizenResponse() ) - { - GetCitizenResponse()->AddResponseTrigger( CR_PLAYER_SHOT_GUNSHIP ); - } - -#ifdef HL2_EPISODIC - NPCEventResponse()->TriggerEvent( "TLK_CITIZEN_RESPONSE_SHOT_GUNSHIP", false, false ); -#endif - } - - return; - } - - BaseClass::TraceAttack( info, vecDir, ptr ); -} - -//----------------------------------------------------------------------------- -// Purpose: This is necessary to ensure that the game doesn't break if a mapmaker has outputs that -// must be fired on gunships, and the player switches skill levels -// midway through a gunship battle. -// Input : iDamageNumber - -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::FireDamageOutputsUpto( int iDamageNumber ) -{ - for ( int i = 0; i <= iDamageNumber; i++ ) - { - if ( !m_bDamageOutputsFired[i] ) - { - m_bDamageOutputsFired[i] = true; - - switch ( i ) - { - case 0: - //Msg("Fired first\n"); - m_OnFirstDamage.FireOutput( this, this ); - break; - - case 1: - //Msg("Fired second\n"); - m_OnSecondDamage.FireOutput( this, this ); - break; - - case 2: - //Msg("Fired third\n"); - m_OnThirdDamage.FireOutput( this, this ); - break; - - case 3: - //Msg("Fired fourth\n"); - m_OnFourthDamage.FireOutput( this, this ); - break; - } - } - } -} - -//------------------------------------------------------------------------------ -// Damage filtering -//------------------------------------------------------------------------------ -int CNPC_CombineGunship::OnTakeDamage_Alive( const CTakeDamageInfo &inputInfo ) -{ - // Allow npc_kill to kill me - if ( inputInfo.GetDamageType() != DMG_GENERIC ) - { - // Ignore mundane bullet damage. - if ( ( inputInfo.GetDamageType() & DMG_BLAST ) == false ) - return 0; - - // Ignore blasts less than this amount - if ( inputInfo.GetDamage() < GUNSHIP_MIN_DAMAGE_THRESHOLD ) - return 0; - } - - // Only take blast damage - CTakeDamageInfo info = inputInfo; - - // Make a pain sound - if ( !HasSpawnFlags( SF_GUNSHIP_USE_CHOPPER_MODEL ) ) - { - EmitSound( "NPC_CombineGunship.Pain" ); - } - - Vector damageDir = info.GetDamageForce(); - VectorNormalize( damageDir ); - - // Don't get knocked around if I'm ground attacking - if ( !m_bIsGroundAttacking ) - { - ApplyAbsVelocityImpulse( damageDir * 200.0f ); - } - - if ( m_bInvulnerable == false ) - { - // Take a percentage of our health away - // Adjust health for damage - int iHealthIncrements = sk_gunship_health_increments.GetInt(); - if ( g_pGameRules->IsSkillLevel( SKILL_EASY ) ) - { - iHealthIncrements = (int)ceil( iHealthIncrements * 0.5 ); - } - else if ( g_pGameRules->IsSkillLevel( SKILL_HARD ) ) - { - iHealthIncrements = (int)floor( iHealthIncrements * 1.5 ); - } - info.SetDamage( ( GetMaxHealth() / (float)iHealthIncrements ) + 1 ); - - // Find out which "stage" we're at in our health - int healthIncrement = iHealthIncrements - ( GetHealth() / (( GetMaxHealth() / iHealthIncrements )) ); - switch ( healthIncrement ) - { - case 1: - // If we're on Easy, we're half dead now, so fire the rest of our outputs too - // This is done in case the mapmaker's connected those inputs to something important - // that has to happen before the gunship dies. - if ( g_pGameRules->IsSkillLevel( SKILL_EASY ) ) - { - FireDamageOutputsUpto( 3 ); - } - else - { - FireDamageOutputsUpto( 1 ); - } - break; - - default: - FireDamageOutputsUpto( healthIncrement ); - break; - } - - // Start smoking when we're almost dead - CreateSmokeTrail(); - - if ( m_pSmokeTrail ) - { - if ( healthIncrement < 2 ) - { - m_pSmokeTrail->SetLifetime( 8.0 ); - } - - m_pSmokeTrail->FollowEntity( this, "exhaustl" ); - } - - // Move with the target - Vector gibVelocity = GetAbsVelocity() + (-damageDir * 200.0f); - - // Dump out metal gibs - CPVSFilter filter( GetAbsOrigin() ); - for ( int i = 0; i < 10; i++ ) - { - int iModelIndex = modelinfo->GetModelIndex( g_PropDataSystem.GetRandomChunkModel( "MetalChunks" ) ); - te->BreakModel( filter, 0.0, GetAbsOrigin(), vec3_angle, Vector(40,40,40), gibVelocity, iModelIndex, 400, 1, 2.5, BREAK_METAL ); - } - } - - return BaseClass::OnTakeDamage_Alive( info ); -} - - -//------------------------------------------------------------------------------ -// Purpose : The proper way to begin the gunship cannon firing at the enemy. -// Input : iBurstSize - the size of the burst, in rounds. -//------------------------------------------------------------------------------ -void CNPC_CombineGunship::StartCannonBurst( int iBurstSize ) -{ - m_iBurstSize = iBurstSize; - m_iBurstHits = 0; - - m_flTimeNextAttack = gpGlobals->curtime; - - // Start up the cannon sound. - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundChangeVolume( m_pCannonSound, 1.0, 0 ); - - m_bIsFiring = true; - - // Setup the initial position of the burst - if ( GetEnemy() ) - { - // Follow mode - Vector enemyPos; - UTIL_PredictedPosition( GetEnemy(), 2.0f, &enemyPos ); - - QAngle offsetAngles; - Vector offsetDir = ( WorldSpaceCenter() - enemyPos ); - VectorNormalize( offsetDir ); - VectorAngles( offsetDir, offsetAngles ); - - int angleOffset = random->RandomInt( 15, 30 ); - if ( random->RandomInt( 0, 1 ) ) - { - angleOffset *= -1; - } - offsetAngles[YAW] += angleOffset; - offsetAngles[PITCH] = 0; - offsetAngles[ROLL] = 0; - - AngleVectors( offsetAngles, &offsetDir ); - - float stitchOffset; - float enemyDist = GroundDistToPosition( GetEnemy()->GetAbsOrigin() ); - if ( enemyDist < ( sk_gunship_burst_dist.GetFloat() + GUNSHIP_STITCH_MIN ) ) - { - stitchOffset = GUNSHIP_STITCH_MIN; - } - else - { - stitchOffset = sk_gunship_burst_dist.GetFloat(); - } - - // Move out to the start of our stitch run - m_vecAttackPosition = enemyPos + ( offsetDir * stitchOffset ); - m_vecAttackPosition.z = enemyPos.z; - - // Point at our target - m_vecAttackVelocity = -offsetDir * BASE_STITCH_VELOCITY; - - CSoundEnt::InsertSound( SOUND_DANGER | SOUND_CONTEXT_REACT_TO_SOURCE, enemyPos, 512, 0.2f, this ); - } -} - - -//------------------------------------------------------------------------------ -// Purpose : The proper way to cease the gunship cannon firing. -//------------------------------------------------------------------------------ -void CNPC_CombineGunship::StopCannonBurst( void ) -{ - m_iBurstHits = 0; - m_bIsFiring = false; - m_bPreFire = false; - - // Reduce the burst time when we get lower in health - float flPerc = (float)GetHealth() / (float)GetMaxHealth(); - float flDelay = clamp( flPerc * m_flBurstDelay, 0.5, m_flBurstDelay ); - - // If we didn't finish the burst, don't wait so long - flPerc = 1.0 - (m_iBurstSize / sk_gunship_burst_size.GetFloat()); - flDelay *= flPerc; - - m_flTimeNextAttack = gpGlobals->curtime + flDelay; - m_iBurstSize = 0; - - // Stop the cannon sound. - if ( m_pCannonSound != NULL ) - { - CSoundEnvelopeController::GetController().SoundChangeVolume( m_pCannonSound, 0.0, 0.05 ); - } - - EmitSound( "NPC_CombineGunship.CannonStopSound" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::StopLoopingSounds( void ) -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - - if ( m_pCannonSound ) - { - controller.SoundDestroy( m_pCannonSound ); - m_pCannonSound = NULL; - } - - if ( m_pRotorSound ) - { - controller.SoundDestroy( m_pRotorSound ); - m_pRotorSound = NULL; - } - - if ( m_pAirExhaustSound ) - { - controller.SoundDestroy( m_pAirExhaustSound ); - m_pAirExhaustSound = NULL; - } - - if ( m_pAirBlastSound ) - { - controller.SoundDestroy( m_pAirBlastSound ); - m_pAirBlastSound = NULL; - } - - BaseClass::StopLoopingSounds(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEnemy - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_CombineGunship::IsValidEnemy( CBaseEntity *pEnemy ) -{ - // Always track missiles - if ( pEnemy->IsAlive() && !pEnemy->MyNPCPointer() && FClassnameIs( pEnemy, "rpg_missile" ) ) - return true; - - // If we're shooting off a burst, don't pick up a new enemy - if ( ( m_bIsFiring ) && ( ( GetEnemy() == NULL ) || ( GetEnemy() != pEnemy ) ) ) - return false; - - return BaseClass::IsValidEnemy( pEnemy ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::GatherEnemyConditions( CBaseEntity *pEnemy ) -{ - BaseClass::GatherEnemyConditions(pEnemy); - - // If we can't see the enemy for a few seconds, consider him unreachable - if ( !HasCondition(COND_SEE_ENEMY) ) - { - if ( gpGlobals->curtime - GetEnemyLastTimeSeen() >= 3.0f ) - { - MarkEnemyAsEluded(); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Tells us whether or not we're targetting an incoming missile -//----------------------------------------------------------------------------- -bool CNPC_CombineGunship::IsTargettingMissile( void ) -{ - if ( GetEnemy() == NULL ) - return false; - - if ( FClassnameIs( GetEnemy(), "rpg_missile" ) == false ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::InputBecomeInvulnerable( inputdata_t &input ) -{ - m_bInvulnerable = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineGunship::InputBecomeVulnerable( inputdata_t &input ) -{ - m_bInvulnerable = false; -} - -AI_BEGIN_CUSTOM_NPC( npc_combinegunship, CNPC_CombineGunship ) - -// DECLARE_TASK( ) - - DECLARE_ACTIVITY( ACT_GUNSHIP_PATROL ); - DECLARE_ACTIVITY( ACT_GUNSHIP_HOVER ); - DECLARE_ACTIVITY( ACT_GUNSHIP_CRASH ); - - //DECLARE_CONDITION( COND_ ) - - //========================================================= -// DEFINE_SCHEDULE -// ( -// SCHED_DUMMY, -// -// " Tasks" -// " TASK_FACE_ENEMY 0" -// " " -// " Interrupts" -// ) - - -AI_END_CUSTOM_NPC() - diff --git a/game/server/hl2/npc_combines.cpp b/game/server/hl2/npc_combines.cpp deleted file mode 100644 index b292a08b3..000000000 --- a/game/server/hl2/npc_combines.cpp +++ /dev/null @@ -1,431 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: This is the soldier version of the combine, analogous to the HL1 grunt. -// -//=============================================================================// - -#include "cbase.h" -#include "ai_hull.h" -#include "ai_motor.h" -#include "npc_combines.h" -#include "bitstring.h" -#include "engine/IEngineSound.h" -#include "soundent.h" -#include "ndebugoverlay.h" -#include "npcevent.h" -#include "hl2/hl2_player.h" -#include "game.h" -#include "ammodef.h" -#include "explode.h" -#include "ai_memory.h" -#include "Sprite.h" -#include "soundenvelope.h" -#include "weapon_physcannon.h" -#include "hl2_gamerules.h" -#include "gameweaponmanager.h" -#include "vehicle_base.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar sk_combine_s_health( "sk_combine_s_health","0"); -ConVar sk_combine_s_kick( "sk_combine_s_kick","0"); - -ConVar sk_combine_guard_health( "sk_combine_guard_health", "0"); -ConVar sk_combine_guard_kick( "sk_combine_guard_kick", "0"); - -// Whether or not the combine guard should spawn health on death -ConVar combine_guard_spawn_health( "combine_guard_spawn_health", "1" ); - -extern ConVar sk_plr_dmg_buckshot; -extern ConVar sk_plr_num_shotgun_pellets; - -//Whether or not the combine should spawn health on death -ConVar combine_spawn_health( "combine_spawn_health", "1" ); - -LINK_ENTITY_TO_CLASS( npc_combine_s, CNPC_CombineS ); - - -#define AE_SOLDIER_BLOCK_PHYSICS 20 // trying to block an incoming physics object - -extern Activity ACT_WALK_EASY; -extern Activity ACT_WALK_MARCH; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CombineS::Spawn( void ) -{ - Precache(); - SetModel( STRING( GetModelName() ) ); - - if( IsElite() ) - { - // Stronger, tougher. - SetHealth( sk_combine_guard_health.GetInt() ); - SetMaxHealth( sk_combine_guard_health.GetInt() ); - SetKickDamage( sk_combine_guard_kick.GetInt() ); - } - else - { - SetHealth( sk_combine_s_health.GetInt() ); - SetMaxHealth( sk_combine_s_health.GetInt() ); - SetKickDamage( sk_combine_s_kick.GetInt() ); - } - - CapabilitiesAdd( bits_CAP_ANIMATEDFACE ); - CapabilitiesAdd( bits_CAP_MOVE_SHOOT ); - CapabilitiesAdd( bits_CAP_DOORS_GROUP ); - - BaseClass::Spawn(); - -#if HL2_EPISODIC - if (m_iUseMarch && !HasSpawnFlags(SF_NPC_START_EFFICIENT)) - { - Msg( "Soldier %s is set to use march anim, but is not an efficient AI. The blended march anim can only be used for dead-ahead walks!\n", GetDebugName() ); - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_CombineS::Precache() -{ - const char *pModelName = STRING( GetModelName() ); - - if( !Q_stricmp( pModelName, "models/combine_super_soldier.mdl" ) ) - { - m_fIsElite = true; - } - else - { - m_fIsElite = false; - } - - if( !GetModelName() ) - { - SetModelName( MAKE_STRING( "models/combine_soldier.mdl" ) ); - } - - PrecacheModel( STRING( GetModelName() ) ); - - UTIL_PrecacheOther( "item_healthvial" ); - UTIL_PrecacheOther( "weapon_frag" ); - UTIL_PrecacheOther( "item_ammo_ar2_altfire" ); - - BaseClass::Precache(); -} - - -void CNPC_CombineS::DeathSound( const CTakeDamageInfo &info ) -{ - // NOTE: The response system deals with this at the moment - if ( GetFlags() & FL_DISSOLVING ) - return; - - GetSentences()->Speak( "COMBINE_DIE", SENTENCE_PRIORITY_INVALID, SENTENCE_CRITERIA_ALWAYS ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Soldiers use CAN_RANGE_ATTACK2 to indicate whether they can throw -// a grenade. Because they check only every half-second or so, this -// condition must persist until it is updated again by the code -// that determines whether a grenade can be thrown, so prevent the -// base class from clearing it out. (sjb) -//----------------------------------------------------------------------------- -void CNPC_CombineS::ClearAttackConditions( ) -{ - bool fCanRangeAttack2 = HasCondition( COND_CAN_RANGE_ATTACK2 ); - - // Call the base class. - BaseClass::ClearAttackConditions(); - - if( fCanRangeAttack2 ) - { - // We don't allow the base class to clear this condition because we - // don't sense for it every frame. - SetCondition( COND_CAN_RANGE_ATTACK2 ); - } -} - -void CNPC_CombineS::PrescheduleThink( void ) -{ - /*//FIXME: This doesn't need to be in here, it's all debug info - if( HasCondition( COND_HEAR_PHYSICS_DANGER ) ) - { - // Don't react unless we see the item!! - CSound *pSound = NULL; - - pSound = GetLoudestSoundOfType( SOUND_PHYSICS_DANGER ); - - if( pSound ) - { - if( FInViewCone( pSound->GetSoundReactOrigin() ) ) - { - DevMsg( "OH CRAP!\n" ); - NDebugOverlay::Line( EyePosition(), pSound->GetSoundReactOrigin(), 0, 0, 255, false, 2.0f ); - } - } - } - */ - - BaseClass::PrescheduleThink(); -} - -//----------------------------------------------------------------------------- -// Purpose: Allows for modification of the interrupt mask for the current schedule. -// In the most cases the base implementation should be called first. -//----------------------------------------------------------------------------- -void CNPC_CombineS::BuildScheduleTestBits( void ) -{ - //Interrupt any schedule with physics danger (as long as I'm not moving or already trying to block) - if ( m_flGroundSpeed == 0.0 && !IsCurSchedule( SCHED_FLINCH_PHYSICS ) ) - { - SetCustomInterruptCondition( COND_HEAR_PHYSICS_DANGER ); - } - - BaseClass::BuildScheduleTestBits(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int CNPC_CombineS::SelectSchedule ( void ) -{ - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -float CNPC_CombineS::GetHitgroupDamageMultiplier( int iHitGroup, const CTakeDamageInfo &info ) -{ - switch( iHitGroup ) - { - case HITGROUP_HEAD: - { - // Soldiers take double headshot damage - return 2.0f; - } - } - - return BaseClass::GetHitgroupDamageMultiplier( iHitGroup, info ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_CombineS::HandleAnimEvent( animevent_t *pEvent ) -{ - switch( pEvent->event ) - { - case AE_SOLDIER_BLOCK_PHYSICS: - DevMsg( "BLOCKING!\n" ); - m_fIsBlocking = true; - break; - - default: - BaseClass::HandleAnimEvent( pEvent ); - break; - } -} - -void CNPC_CombineS::OnChangeActivity( Activity eNewActivity ) -{ - // Any new sequence stops us blocking. - m_fIsBlocking = false; - - BaseClass::OnChangeActivity( eNewActivity ); - -#if HL2_EPISODIC - // Give each trooper a varied look for his march. Done here because if you do it earlier (eg Spawn, StartTask), the - // pose param gets overwritten. - if (m_iUseMarch) - { - SetPoseParameter("casual", RandomFloat()); - } -#endif -} - -void CNPC_CombineS::OnListened() -{ - BaseClass::OnListened(); - - if ( HasCondition( COND_HEAR_DANGER ) && HasCondition( COND_HEAR_PHYSICS_DANGER ) ) - { - if ( HasInterruptCondition( COND_HEAR_DANGER ) ) - { - ClearCondition( COND_HEAR_PHYSICS_DANGER ); - } - } - - // debugging to find missed schedules -#if 0 - if ( HasCondition( COND_HEAR_DANGER ) && !HasInterruptCondition( COND_HEAR_DANGER ) ) - { - DevMsg("Ignore danger in %s\n", GetCurSchedule()->GetName() ); - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -void CNPC_CombineS::Event_Killed( const CTakeDamageInfo &info ) -{ - // Don't bother if we've been told not to, or the player has a megaphyscannon - if ( combine_spawn_health.GetBool() == false || PlayerHasMegaPhysCannon() ) - { - BaseClass::Event_Killed( info ); - return; - } - - CBasePlayer *pPlayer = ToBasePlayer( info.GetAttacker() ); - - if ( !pPlayer ) - { - CPropVehicleDriveable *pVehicle = dynamic_cast( info.GetAttacker() ) ; - if ( pVehicle && pVehicle->GetDriver() && pVehicle->GetDriver()->IsPlayer() ) - { - pPlayer = assert_cast( pVehicle->GetDriver() ); - } - } - - if ( pPlayer != NULL ) - { - // Elites drop alt-fire ammo, so long as they weren't killed by dissolving. - if( IsElite() ) - { -#ifdef HL2_EPISODIC - if ( HasSpawnFlags( SF_COMBINE_NO_AR2DROP ) == false ) -#endif - { - CBaseEntity *pItem = DropItem( "item_ammo_ar2_altfire", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) ); - - if ( pItem ) - { - IPhysicsObject *pObj = pItem->VPhysicsGetObject(); - - if ( pObj ) - { - Vector vel = RandomVector( -64.0f, 64.0f ); - AngularImpulse angImp = RandomAngularImpulse( -300.0f, 300.0f ); - - vel[2] = 0.0f; - pObj->AddVelocity( &vel, &angImp ); - } - - if( info.GetDamageType() & DMG_DISSOLVE ) - { - CBaseAnimating *pAnimating = dynamic_cast(pItem); - - if( pAnimating ) - { - pAnimating->Dissolve( NULL, gpGlobals->curtime, false, ENTITY_DISSOLVE_NORMAL ); - } - } - else - { - WeaponManager_AddManaged( pItem ); - } - } - } - } - - CHalfLife2 *pHL2GameRules = static_cast(g_pGameRules); - - // Attempt to drop health - if ( pHL2GameRules->NPC_ShouldDropHealth( pPlayer ) ) - { - DropItem( "item_healthvial", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) ); - pHL2GameRules->NPC_DroppedHealth(); - } - - if ( HasSpawnFlags( SF_COMBINE_NO_GRENADEDROP ) == false ) - { - // Attempt to drop a grenade - if ( pHL2GameRules->NPC_ShouldDropGrenade( pPlayer ) ) - { - DropItem( "weapon_frag", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) ); - pHL2GameRules->NPC_DroppedGrenade(); - } - } - } - - BaseClass::Event_Killed( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_CombineS::IsLightDamage( const CTakeDamageInfo &info ) -{ - return BaseClass::IsLightDamage( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_CombineS::IsHeavyDamage( const CTakeDamageInfo &info ) -{ - // Combine considers AR2 fire to be heavy damage - if ( info.GetAmmoType() == GetAmmoDef()->Index("AR2") ) - return true; - - // 357 rounds are heavy damage - if ( info.GetAmmoType() == GetAmmoDef()->Index("357") ) - return true; - - // Shotgun blasts where at least half the pellets hit me are heavy damage - if ( info.GetDamageType() & DMG_BUCKSHOT ) - { - int iHalfMax = (int)(sk_plr_dmg_buckshot.GetFloat() * sk_plr_num_shotgun_pellets.GetInt() * 0.5); - if ( info.GetDamage() >= iHalfMax ) - return true; - } - - // Rollermine shocks - if( (info.GetDamageType() & DMG_SHOCK) && hl2_episodic.GetBool() ) - { - return true; - } - - return BaseClass::IsHeavyDamage( info ); -} - -#if HL2_EPISODIC -//----------------------------------------------------------------------------- -// Purpose: Translate base class activities into combot activites -//----------------------------------------------------------------------------- -Activity CNPC_CombineS::NPC_TranslateActivity( Activity eNewActivity ) -{ - // If the special ep2_outland_05 "use march" flag is set, use the more casual marching anim. - if ( m_iUseMarch && eNewActivity == ACT_WALK ) - { - eNewActivity = ACT_WALK_MARCH; - } - - return BaseClass::NPC_TranslateActivity( eNewActivity ); -} - - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CNPC_CombineS ) - - DEFINE_KEYFIELD( m_iUseMarch, FIELD_INTEGER, "usemarch" ), - -END_DATADESC() -#endif diff --git a/game/server/hl2/npc_combines.h b/game/server/hl2/npc_combines.h deleted file mode 100644 index 0949a1ab3..000000000 --- a/game/server/hl2/npc_combines.h +++ /dev/null @@ -1,61 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef NPC_COMBINES_H -#define NPC_COMBINES_H -#ifdef _WIN32 -#pragma once -#endif - -#include "npc_combine.h" - -//========================================================= -// >> CNPC_CombineS -//========================================================= -class CNPC_CombineS : public CNPC_Combine -{ - DECLARE_CLASS( CNPC_CombineS, CNPC_Combine ); -#if HL2_EPISODIC - DECLARE_DATADESC(); -#endif - -public: - void Spawn( void ); - void Precache( void ); - void DeathSound( const CTakeDamageInfo &info ); - void PrescheduleThink( void ); - void BuildScheduleTestBits( void ); - int SelectSchedule ( void ); - float GetHitgroupDamageMultiplier( int iHitGroup, const CTakeDamageInfo &info ); - void HandleAnimEvent( animevent_t *pEvent ); - void OnChangeActivity( Activity eNewActivity ); - void Event_Killed( const CTakeDamageInfo &info ); - void OnListened(); - - void ClearAttackConditions( void ); - - bool m_fIsBlocking; - - bool IsLightDamage( const CTakeDamageInfo &info ); - bool IsHeavyDamage( const CTakeDamageInfo &info ); - - virtual bool AllowedToIgnite( void ) { return true; } - -private: - bool ShouldHitPlayer( const Vector &targetDir, float targetDist ); - -#if HL2_EPISODIC -public: - Activity NPC_TranslateActivity( Activity eNewActivity ); - -protected: - /// whether to use the more casual march anim in ep2_outland_05 - int m_iUseMarch; -#endif - -}; - -#endif // NPC_COMBINES_H diff --git a/game/server/hl2/npc_cranedriver.cpp b/game/server/hl2/npc_cranedriver.cpp deleted file mode 100644 index 87c9bc708..000000000 --- a/game/server/hl2/npc_cranedriver.cpp +++ /dev/null @@ -1,791 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "ai_network.h" -#include "ai_default.h" -#include "ai_schedule.h" -#include "ai_hull.h" -#include "ai_node.h" -#include "ai_task.h" -#include "ai_senses.h" -#include "ai_navigator.h" -#include "ai_route.h" -#include "entitylist.h" -#include "soundenvelope.h" -#include "gamerules.h" -#include "ndebugoverlay.h" -#include "soundflags.h" -#include "trains.h" -#include "globalstate.h" -#include "vehicle_base.h" -#include "npc_vehicledriver.h" -#include "vehicle_crane.h" -#include "saverestore_utlvector.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern ConVar g_debug_vehicledriver; - -//========================================================= -// Custom schedules -//========================================================= -enum -{ - SCHED_CRANE_RANGE_ATTACK1 = LAST_VEHICLEDRIVER_SCHED, - SCHED_CRANE_FIND_LARGE_OBJECT, - SCHED_CRANE_PICKUP_OBJECT, - SCHED_CRANE_FORCED_GO, - SCHED_CRANE_CHASE_ENEMY, - SCHED_CRANE_FORCED_DROP, -}; - -//========================================================= -// Custom tasks -//========================================================= -enum -{ - TASK_CRANE_GET_POSITION_OVER_ENEMY = LAST_VEHICLEDRIVER_TASK, - TASK_CRANE_GET_POSITION_OVER_LASTPOSITION, - TASK_CRANE_GET_POSITION_OVER_OBJECT, - TASK_CRANE_TURN_MAGNET_OFF, - TASK_CRANE_FIND_OBJECT_TO_PICKUP, - TASK_CRANE_DROP_MAGNET, - TASK_END_FORCED_DROP, -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CNPC_CraneDriver : public CNPC_VehicleDriver -{ - DECLARE_CLASS( CNPC_CraneDriver, CNPC_VehicleDriver ); -public: - DECLARE_DATADESC(); - DEFINE_CUSTOM_AI; - - void Spawn( void ); - void Activate( void ); - - // AI - int RangeAttack1Conditions( float flDot, float flDist ); - int TranslateSchedule( int scheduleType ); - int SelectSchedule( void ); - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - void SetDesiredPosition( const Vector &vecPosition ); - - // Driving - void DriveVehicle( void ); - bool OverrideMove( float flInterval ); - - // Inputs - void InputForcePickup( inputdata_t &inputdata ); - void InputForceDrop( inputdata_t &inputdata ); - -protected: - CHandle m_hCrane; - - EHANDLE m_hPickupTarget; - float m_flDistanceToTarget; - CUtlVector< EHANDLE > m_PreviouslyPickedUpObjects; - bool m_bForcedPickup; - bool m_bForcedDropoff; - float m_flDropWait; - float m_flReleasePause; - float m_flReleaseAt; - - // Outputs - COutputEvent m_OnPickedUpObject; - COutputEvent m_OnDroppedObject; - COutputEvent m_OnPausingBeforeDrop; -}; - -BEGIN_DATADESC( CNPC_CraneDriver ) - // Inputs - DEFINE_INPUTFUNC( FIELD_STRING, "ForcePickup", InputForcePickup ), - DEFINE_INPUTFUNC( FIELD_STRING, "ForceDrop", InputForceDrop ), - - //DEFINE_FIELD( m_hCrane, FIELD_EHANDLE ), - DEFINE_FIELD( m_hPickupTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_flDistanceToTarget, FIELD_FLOAT ), - DEFINE_UTLVECTOR( m_PreviouslyPickedUpObjects, FIELD_EHANDLE ), - DEFINE_FIELD( m_bForcedPickup, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bForcedDropoff, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flDropWait, FIELD_FLOAT ), - DEFINE_KEYFIELD( m_flReleasePause, FIELD_FLOAT, "releasepause" ), - DEFINE_FIELD( m_flReleaseAt, FIELD_FLOAT ), - - // Outputs - DEFINE_OUTPUT( m_OnPickedUpObject, "OnPickedUpObject" ), - DEFINE_OUTPUT( m_OnDroppedObject, "OnDroppedObject" ), - DEFINE_OUTPUT( m_OnPausingBeforeDrop, "OnPausingBeforeDrop" ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( npc_cranedriver, CNPC_CraneDriver ); - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CNPC_CraneDriver::Spawn( void ) -{ - BaseClass::Spawn(); - - CapabilitiesClear(); - CapabilitiesAdd( bits_CAP_INNATE_RANGE_ATTACK1 ); - - m_flDistTooFar = 2048.0; - SetDistLook( 2048 ); - - m_PreviouslyPickedUpObjects.Purge(); - m_hPickupTarget = NULL; - m_bForcedPickup = false; - m_bForcedDropoff = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CraneDriver::Activate( void ) -{ - BaseClass::Activate(); - - m_hCrane = dynamic_cast((CBaseEntity*)m_hVehicleEntity); - if ( !m_hCrane ) - { - Warning( "npc_cranedriver %s couldn't find his crane named %s.\n", STRING(GetEntityName()), STRING(m_iszVehicleName) ); - UTIL_Remove( this ); - return; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int CNPC_CraneDriver::RangeAttack1Conditions( float flDot, float flDist ) -{ - if ( !HasCondition( COND_SEE_ENEMY ) ) - return COND_NONE; - - // Do our distance check in 2D - Vector2D vecOrigin2D( m_hCrane->GetAbsOrigin().x, m_hCrane->GetAbsOrigin().y ); - Vector2D vecEnemy2D( GetEnemy()->GetAbsOrigin().x, GetEnemy()->GetAbsOrigin().y ); - flDist = (vecOrigin2D - vecEnemy2D).Length(); - - // Maximum & Minimum size of the crane's reach - if ( flDist > MAX_CRANE_FLAT_REACH ) - return COND_TOO_FAR_TO_ATTACK; - - // Crane can't reach any closer than this - if ( flDist < MIN_CRANE_FLAT_REACH ) - return COND_TOO_CLOSE_TO_ATTACK; - - return COND_CAN_RANGE_ATTACK1; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_CraneDriver::SelectSchedule( void ) -{ - if ( HasSpawnFlags(SF_VEHICLEDRIVER_INACTIVE) ) - return BaseClass::SelectSchedule(); - - // If we've got an object to pickup, so go get it - if ( m_hPickupTarget ) - { - // Only clear the pickup target if we managed to pick something up - if ( m_hCrane->GetTotalMassOnCrane() > 0 ) - { - if ( m_bForcedPickup ) - { - m_OnPickedUpObject.FireOutput( m_hPickupTarget, this ); - } - - // Remember what we dropped so we go try something else if we can. - m_PreviouslyPickedUpObjects.AddToTail( m_hPickupTarget ); - m_hPickupTarget = NULL; - } - else - { - if ( m_NPCState == NPC_STATE_IDLE ) - { - SetIdealState( NPC_STATE_ALERT ); - } - return SCHED_CRANE_PICKUP_OBJECT; - } - } - - // If we're currently being forced to pickup something, do only that - if ( m_bForcedPickup ) - { - if ( m_hPickupTarget ) - return SCHED_CRANE_PICKUP_OBJECT; - - // We've picked up our target, we're waiting to be told where to put it - return SCHED_IDLE_STAND; - } - - // If we've been told to drop something off, do that - if ( m_bForcedDropoff ) - return SCHED_CRANE_FORCED_DROP; - - switch ( m_NPCState ) - { - case NPC_STATE_IDLE: - break; - - case NPC_STATE_ALERT: - break; - - case NPC_STATE_COMBAT: - if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - { - // Do we have anything on the crane? If not, look for something - if ( m_hCrane->GetTotalMassOnCrane() == 0 ) - return SCHED_CRANE_FIND_LARGE_OBJECT; - - // We've got something on the crane, so try and drop it on the enemy - return SCHED_CRANE_RANGE_ATTACK1; - } - - // We can't attack him, so if we don't have anything on the crane, grab something - if ( m_hCrane->GetTotalMassOnCrane() == 0 ) - return SCHED_CRANE_FIND_LARGE_OBJECT; - - default: - break; - } - - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_CraneDriver::TranslateSchedule( int scheduleType ) -{ - switch ( scheduleType ) - { - case SCHED_COMBAT_FACE: - // Vehicles can't rotate, so don't try and face - return TranslateSchedule( SCHED_CHASE_ENEMY ); - - case SCHED_ALERT_FACE: - // Vehicles can't rotate, so don't try and face - return SCHED_ALERT_STAND; - - case SCHED_FORCED_GO: - return SCHED_CRANE_FORCED_GO; - - case SCHED_CHASE_ENEMY: - return SCHED_CRANE_CHASE_ENEMY; - } - - return BaseClass::TranslateSchedule(scheduleType); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTask - -//----------------------------------------------------------------------------- -void CNPC_CraneDriver::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_WAIT_FOR_MOVEMENT: - break; - - case TASK_CRANE_GET_POSITION_OVER_ENEMY: - { - if ( !GetEnemy() ) - { - TaskFail(FAIL_NO_ROUTE); - return; - } - - SetDesiredPosition( GetEnemy()->GetAbsOrigin() ); - TaskComplete(); - } - break; - - case TASK_CRANE_GET_POSITION_OVER_OBJECT: - { - if ( !m_hPickupTarget ) - { - TaskFail("No object to pickup!"); - return; - } - - SetDesiredPosition( m_hPickupTarget->GetAbsOrigin() ); - TaskComplete(); - } - break; - - case TASK_CRANE_GET_POSITION_OVER_LASTPOSITION: - { - SetDesiredPosition( m_vecLastPosition ); - TaskComplete(); - } - break; - - case TASK_CRANE_TURN_MAGNET_OFF: - { - // If we picked up something, and we were being forced to pick something up, fire our output - if ( m_hCrane->GetTotalMassOnCrane() > 0 && m_bForcedDropoff ) - { - // Are we supposed to pause first? - if ( m_flReleasePause ) - { - m_flReleaseAt = gpGlobals->curtime + m_flReleasePause; - m_OnPausingBeforeDrop.FireOutput( this, this ); - return; - } - - m_OnDroppedObject.FireOutput( this, this ); - } - - m_hCrane->TurnMagnetOff(); - TaskComplete(); - } - break; - - case TASK_END_FORCED_DROP: - { - m_bForcedDropoff = false; - TaskComplete(); - } - break; - - case TASK_CRANE_FIND_OBJECT_TO_PICKUP: - { - Vector2D vecOrigin2D( m_hCrane->GetAbsOrigin().x, m_hCrane->GetAbsOrigin().y ); - - // Find a large physics object within our reach to pickup - float flLargestMass = 0; - CBaseEntity *pLargestEntity = NULL; - - CBaseEntity *pList[1024]; - Vector delta( m_flDistTooFar, m_flDistTooFar, m_flDistTooFar*2 ); - int count = UTIL_EntitiesInBox( pList, 1024, m_hCrane->GetAbsOrigin() - delta, m_hCrane->GetAbsOrigin() + delta, 0 ); - for ( int i = 0; i < count; i++ ) - { - if ( !pList[i] ) - continue; - // Ignore the crane & the magnet - if ( pList[i] == m_hCrane || pList[i] == m_hCrane->GetMagnet() ) - continue; - if ( m_PreviouslyPickedUpObjects.Find( pList[i] ) != m_PreviouslyPickedUpObjects.InvalidIndex() ) - continue; - - // Get the VPhysics object - IPhysicsObject *pPhysics = pList[i]->VPhysicsGetObject(); - if ( pPhysics && pList[i]->GetMoveType() == MOVETYPE_VPHYSICS ) - { - float flMass = pPhysics->GetMass(); - if ( flMass > flLargestMass && (flMass < MAXIMUM_CRANE_PICKUP_MASS) && (flMass > MINIMUM_CRANE_PICKUP_MASS) ) - { - // Biggest one we've found so far - - // Now make sure it's within our reach - // Do our distance check in 2D - Vector2D vecOrigin2D( m_hCrane->GetAbsOrigin().x, m_hCrane->GetAbsOrigin().y ); - Vector2D vecEnemy2D( pList[i]->GetAbsOrigin().x, pList[i]->GetAbsOrigin().y ); - float flDist = (vecOrigin2D - vecEnemy2D).Length(); - // Maximum & Minimum size of the crane's reach - if ( flDist > MAX_CRANE_FLAT_REACH ) - continue; - if ( flDist < MIN_CRANE_FLAT_REACH ) - continue; - - flLargestMass = flMass; - pLargestEntity = pList[i]; - } - } - } - - // If we didn't find anything new, clear our list of targets - if ( !pLargestEntity ) - { - m_PreviouslyPickedUpObjects.Purge(); - } - - if ( !pLargestEntity ) - { - TaskFail("Couldn't find anything to pick up!"); - return; - } - - m_hPickupTarget = pLargestEntity; - TaskComplete(); - } - break; - - case TASK_CRANE_DROP_MAGNET: - { - // Drop the magnet, but only end the task once the magnet's back up - m_pVehicleInterface->NPC_SecondaryFire(); - - // Don't check to see if drop's finished until this time is up. - // This is necessary because the crane won't start dropping this - // frame, and our cranedriver will think it's finished immediately. - m_flDropWait = gpGlobals->curtime + 0.5; - } - break; - - default: - BaseClass::StartTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CraneDriver::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_WAIT_FOR_MOVEMENT: - { - // Is the magnet over the target, and are we not moving too fast? - AngularImpulse angVel; - Vector vecVelocity; - CBaseEntity *pMagnet = m_hCrane->GetMagnet(); - IPhysicsObject *pVehiclePhysics = pMagnet->VPhysicsGetObject(); - pVehiclePhysics->GetVelocity( &vecVelocity, &angVel ); - float flVelocity = 100; - float flDistance = 90; - - // More accurate on forced drops - if ( m_bForcedPickup || m_bForcedDropoff ) - { - flVelocity = 10; - flDistance = 30; - } - - if ( m_flDistanceToTarget < flDistance && m_hCrane->GetTurnRate() < 0.1 && vecVelocity.Length() < flVelocity ) - { - TaskComplete(); - } - } - break; - - case TASK_CRANE_DROP_MAGNET: - { - // Wait for the magnet to get back up - if ( m_flDropWait < gpGlobals->curtime && !m_hCrane->IsDropping() ) - { - TaskComplete(); - } - } - break; - - case TASK_CRANE_TURN_MAGNET_OFF: - { - // We're waiting for the pause length before dropping whatever's on our magnet - if ( gpGlobals->curtime > m_flReleaseAt ) - { - if ( m_bForcedDropoff ) - { - m_OnDroppedObject.FireOutput( this, this ); - } - - m_hCrane->TurnMagnetOff(); - TaskComplete(); - } - } - break; - - default: - BaseClass::RunTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_CraneDriver::OverrideMove( float flInterval ) -{ - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CraneDriver::SetDesiredPosition( const Vector &vecPosition ) -{ - m_vecDesiredPosition = vecPosition; - m_flDistanceToTarget = 999; -} - -//----------------------------------------------------------------------------- -// Purpose: This takes the current place the NPC's trying to get to, figures out -// what keys to press to get the vehicle to go there, and then sends -// them to the vehicle. -//----------------------------------------------------------------------------- -void CNPC_CraneDriver::DriveVehicle( void ) -{ - // No targets? - if ( !GetEnemy() && m_vecDesiredPosition == vec3_origin ) - return; - - Vector vecTarget = m_vecDesiredPosition; - // Track our targets - if ( m_hPickupTarget ) - { - vecTarget = m_hPickupTarget->GetAbsOrigin(); - } - else if ( !m_bForcedPickup && !m_bForcedDropoff && GetEnemy() ) - { - vecTarget = GetEnemy()->GetAbsOrigin(); - } - - // Move the crane over the target - // Use the crane type as a targeting point - Vector vecCraneTip = m_hCrane->GetCraneTipPosition(); - Vector2D vecCraneTip2D( vecCraneTip.x, vecCraneTip.y ); - Vector2D vecTarget2D( vecTarget.x, vecTarget.y ); - Vector2D vecOrigin2D( m_hCrane->GetAbsOrigin().x, m_hCrane->GetAbsOrigin().y ); - - if ( g_debug_vehicledriver.GetInt() ) - { - NDebugOverlay::Box( vecTarget, -Vector(50,50,50), Vector(50,50,50), 0,255,0, true, 0.1 ); - NDebugOverlay::Box( vecCraneTip, -Vector(2,2,5000), Vector(2,2,5), 0,255,0, true, 0.1 ); - NDebugOverlay::Box( vecTarget, -Vector(2,2,5), Vector(2,2,5000), 0,255,0, true, 0.1 ); - } - // Store off the distance to our target - m_flDistanceToTarget = (vecTarget2D - vecCraneTip2D).Length(); - - // First determine whether we need to extend / retract the arm - float flDistToTarget = (vecOrigin2D - vecTarget2D).LengthSqr(); - float flDistToCurrent = (vecOrigin2D - vecCraneTip2D).LengthSqr(); - float flDelta = fabs(flDistToTarget - flDistToCurrent); - // Slow down as we get closer, but do it based upon our current extension rate - float flMinDelta = 50 + (50 * fabs(m_hCrane->GetExtensionRate() / CRANE_EXTENSION_RATE_MAX)); - flMinDelta *= flMinDelta; - if ( flDelta > flMinDelta ) - { - if ( flDistToCurrent > flDistToTarget ) - { - // Retract - m_pVehicleInterface->NPC_ThrottleReverse(); - } - else if ( flDistToCurrent < flDistToTarget ) - { - // Extend - m_pVehicleInterface->NPC_ThrottleForward(); - } - } - else - { - m_pVehicleInterface->NPC_ThrottleCenter(); - } - - // Then figure out if we need to rotate. Do it all in 2D space. - Vector vecRight, vecForward; - m_hCrane->GetVectors( &vecForward, &vecRight, NULL ); - vecRight.z = 0; - vecForward.z = 0; - VectorNormalize( vecRight ); - VectorNormalize( vecForward ); - Vector vecToTarget = ( vecTarget - m_hCrane->GetAbsOrigin() ); - vecToTarget.z = 0; - VectorNormalize( vecToTarget ); - float flDotRight = DotProduct( vecRight, vecToTarget ); - float flDotForward = DotProduct( vecForward, vecToTarget ); - - // Start slowing if we're going to hit the point soon - float flTurnInDeg = RAD2DEG( acos(flDotForward) ); - float flSpeed = m_hCrane->GetMaxTurnRate() * (flTurnInDeg / 15.0); - flSpeed = MIN( m_hCrane->GetMaxTurnRate(), flSpeed ); - if ( fabs(flSpeed) < 0.05 ) - { - // We're approaching the target, so stop turning - m_pVehicleInterface->NPC_TurnCenter(); - } - else - { - if ( flDotRight < 0 ) - { - // Turn right - m_pVehicleInterface->NPC_TurnRight( flSpeed ); - } - else if ( flDotRight > 0 ) - { - // Turn left - m_pVehicleInterface->NPC_TurnLeft( flSpeed ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Force the driver to pickup a specific entity -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_CraneDriver::InputForcePickup( inputdata_t &inputdata ) -{ - string_t iszPickupName = inputdata.value.StringID(); - if ( iszPickupName != NULL_STRING ) - { - // Turn the magnet off now to drop anything we might have already on the magnet - m_hCrane->TurnMagnetOff(); - m_hPickupTarget = gEntList.FindEntityByName( NULL, iszPickupName, NULL, inputdata.pActivator, inputdata.pCaller ); - m_bForcedPickup = true; - m_bForcedDropoff = false; - SetCondition( COND_PROVOKED ); - CLEARBITS( m_spawnflags, SF_VEHICLEDRIVER_INACTIVE ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Force the driver to drop his held entity at a specific point -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_CraneDriver::InputForceDrop( inputdata_t &inputdata ) -{ - string_t iszDropName = inputdata.value.StringID(); - if ( iszDropName != NULL_STRING ) - { - CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, iszDropName, NULL, inputdata.pActivator, inputdata.pCaller ); - if ( !pEntity ) - { - Warning("Crane couldn't find entity named %s\n", STRING(iszDropName) ); - return; - } - m_bForcedPickup = false; - m_bForcedDropoff = true; - SetDesiredPosition( pEntity->GetAbsOrigin() ); - SetCondition( COND_PROVOKED ); - CLEARBITS( m_spawnflags, SF_VEHICLEDRIVER_INACTIVE ); - } -} - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC( npc_cranedriver, CNPC_CraneDriver ) - - //Tasks - DECLARE_TASK( TASK_CRANE_GET_POSITION_OVER_ENEMY ) - DECLARE_TASK( TASK_CRANE_GET_POSITION_OVER_LASTPOSITION ) - DECLARE_TASK( TASK_CRANE_GET_POSITION_OVER_OBJECT ) - DECLARE_TASK( TASK_CRANE_TURN_MAGNET_OFF ) - DECLARE_TASK( TASK_END_FORCED_DROP ) - DECLARE_TASK( TASK_CRANE_FIND_OBJECT_TO_PICKUP ) - DECLARE_TASK( TASK_CRANE_DROP_MAGNET ) - - //Schedules - //================================================== - // SCHED_ANTLION_CHASE_ENEMY_BURROW - //================================================== - - DEFINE_SCHEDULE - ( - SCHED_CRANE_RANGE_ATTACK1, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY" - " TASK_CRANE_GET_POSITION_OVER_ENEMY 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_CRANE_TURN_MAGNET_OFF 0" - " " - " Interrupts" - " COND_ENEMY_DEAD" - " COND_NEW_ENEMY" - " COND_ENEMY_OCCLUDED" - " COND_ENEMY_TOO_FAR" - " COND_PROVOKED" - ) - - DEFINE_SCHEDULE - ( - SCHED_CRANE_FIND_LARGE_OBJECT, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY" - " TASK_CRANE_FIND_OBJECT_TO_PICKUP 0" - " " - " Interrupts" - " COND_ENEMY_DEAD" - " COND_NEW_ENEMY" - " COND_ENEMY_OCCLUDED" - " COND_ENEMY_TOO_FAR" - ) - - DEFINE_SCHEDULE - ( - SCHED_CRANE_PICKUP_OBJECT, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY" - " TASK_CRANE_GET_POSITION_OVER_OBJECT 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_CRANE_DROP_MAGNET 0" - " " - " Interrupts" - " COND_ENEMY_DEAD" - " COND_NEW_ENEMY" - " COND_ENEMY_OCCLUDED" - " COND_ENEMY_TOO_FAR" - " COND_PROVOKED" - ) - - DEFINE_SCHEDULE - ( - SCHED_CRANE_FORCED_GO, - - " Tasks" - " TASK_CRANE_GET_POSITION_OVER_LASTPOSITION 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_CRANE_TURN_MAGNET_OFF 0" - " TASK_WAIT 2" - " " - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_CRANE_CHASE_ENEMY, - - " Tasks" - " TASK_CRANE_GET_POSITION_OVER_ENEMY 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_WAIT 5" - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_ENEMY_UNREACHABLE" - " COND_CAN_RANGE_ATTACK1" - " COND_TOO_CLOSE_TO_ATTACK" - " COND_TASK_FAILED" - " COND_LOST_ENEMY" - " COND_PROVOKED" - ) - - DEFINE_SCHEDULE - ( - SCHED_CRANE_FORCED_DROP, - - " Tasks" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_CRANE_TURN_MAGNET_OFF 0" - " TASK_END_FORCED_DROP 0" - " TASK_WAIT 2" - " " - " Interrupts" - ) - -AI_END_CUSTOM_NPC() diff --git a/game/server/hl2/npc_crow.cpp b/game/server/hl2/npc_crow.cpp deleted file mode 100644 index 28ec4b609..000000000 --- a/game/server/hl2/npc_crow.cpp +++ /dev/null @@ -1,1602 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Crows. Simple ambient birds that fly away when they hear gunfire or -// when anything gets too close to them. -// -// TODO: landing -// TODO: death -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "game.h" -#include "ai_basenpc.h" -#include "ai_schedule.h" -#include "ai_hull.h" -#include "ai_hint.h" -#include "ai_motor.h" -#include "ai_navigator.h" -#include "hl2_shareddefs.h" -#include "ai_route.h" -#include "npcevent.h" -#include "gib.h" -#include "ai_interactions.h" -#include "ndebugoverlay.h" -#include "soundent.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "movevars_shared.h" -#include "npc_crow.h" -#include "ai_moveprobe.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// -// Custom activities. -// -static int ACT_CROW_TAKEOFF; -static int ACT_CROW_SOAR; -static int ACT_CROW_LAND; - -// -// Animation events. -// -static int AE_CROW_TAKEOFF; -static int AE_CROW_FLY; -static int AE_CROW_HOP; - -// -// Skill settings. -// -ConVar sk_crow_health( "sk_crow_health","1"); -ConVar sk_crow_melee_dmg( "sk_crow_melee_dmg","0"); - -LINK_ENTITY_TO_CLASS( npc_crow, CNPC_Crow ); -LINK_ENTITY_TO_CLASS( npc_seagull, CNPC_Seagull ); -LINK_ENTITY_TO_CLASS( npc_pigeon, CNPC_Pigeon ); - -BEGIN_DATADESC( CNPC_Crow ) - - DEFINE_FIELD( m_flGroundIdleMoveTime, FIELD_TIME ), - DEFINE_FIELD( m_bOnJeep, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flEnemyDist, FIELD_FLOAT ), - DEFINE_FIELD( m_nMorale, FIELD_INTEGER ), - DEFINE_FIELD( m_bReachedMoveGoal, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flHopStartZ, FIELD_FLOAT ), - DEFINE_FIELD( m_vDesiredTarget, FIELD_VECTOR ), - DEFINE_FIELD( m_vCurrentTarget, FIELD_VECTOR ), - DEFINE_FIELD( m_flSoarTime, FIELD_TIME ), - DEFINE_FIELD( m_bSoar, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bPlayedLoopingSound, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iBirdType, FIELD_INTEGER ), - DEFINE_FIELD( m_vLastStoredOrigin, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_flLastStuckCheck, FIELD_TIME ), - DEFINE_FIELD( m_flDangerSoundTime, FIELD_TIME ), - DEFINE_KEYFIELD( m_bIsDeaf, FIELD_BOOLEAN, "deaf" ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_STRING, "FlyAway", InputFlyAway ), - -END_DATADESC() - -static ConVar birds_debug( "birds_debug", "0" ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Crow::Spawn( void ) -{ - BaseClass::Spawn(); - -#ifdef _XBOX - // Always fade the corpse - AddSpawnFlags( SF_NPC_FADE_CORPSE ); -#endif // _XBOX - - const char *szModel = (char *)STRING( GetModelName() ); - if (!szModel || !*szModel) - { - szModel = "models/crow.mdl"; - SetModelName( AllocPooledString(szModel) ); - } - - Precache(); - SetModel( szModel ); - - m_iHealth = sk_crow_health.GetFloat(); - - SetHullType(HULL_TINY); - SetHullSizeNormal(); - - SetSolid( SOLID_BBOX ); - SetMoveType( MOVETYPE_STEP ); - - m_flFieldOfView = VIEW_FIELD_FULL; - SetViewOffset( Vector(6, 0, 11) ); // Position of the eyes relative to NPC's origin. - - m_flGroundIdleMoveTime = gpGlobals->curtime + random->RandomFloat( 0.0f, 5.0f ); - - SetBloodColor( BLOOD_COLOR_RED ); - m_NPCState = NPC_STATE_NONE; - - m_nMorale = random->RandomInt( 0, 12 ); - - SetCollisionGroup( HL2COLLISION_GROUP_CROW ); - - CapabilitiesClear(); - - bool bFlying = ( ( m_spawnflags & SF_CROW_FLYING ) != 0 ); - SetFlyingState( bFlying ? FlyState_Flying : FlyState_Walking ); - - // We don't mind zombies so much. They smell good! - AddClassRelationship( CLASS_ZOMBIE, D_NU, 0 ); - - m_bSoar = false; - m_bOnJeep = false; - m_flSoarTime = gpGlobals->curtime; - - NPCInit(); - - m_iBirdType = BIRDTYPE_CROW; - - m_vLastStoredOrigin = vec3_origin; - m_flLastStuckCheck = gpGlobals->curtime; - - m_flDangerSoundTime = gpGlobals->curtime; - - SetGoalEnt( NULL ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns this monster's classification in the relationship table. -//----------------------------------------------------------------------------- -Class_T CNPC_Crow::Classify( void ) -{ - return( CLASS_EARTH_FAUNA ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pEnemy - -//----------------------------------------------------------------------------- -void CNPC_Crow::GatherEnemyConditions( CBaseEntity *pEnemy ) -{ - m_flEnemyDist = (GetLocalOrigin() - pEnemy->GetLocalOrigin()).Length(); - - if ( m_flEnemyDist < 512 ) - { - SetCondition( COND_CROW_ENEMY_WAY_TOO_CLOSE ); - } - - if ( m_flEnemyDist < 1024 ) - { - SetCondition( COND_CROW_ENEMY_TOO_CLOSE ); - } - - BaseClass::GatherEnemyConditions(pEnemy); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : posSrc - -// Output : Vector -//----------------------------------------------------------------------------- -Vector CNPC_Crow::BodyTarget( const Vector &posSrc, bool bNoisy ) -{ - Vector vecResult; - vecResult = GetAbsOrigin(); - vecResult.z += 6; - return vecResult; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Crow::StopLoopingSounds( void ) -{ - // - // Stop whatever flap sound might be playing. - // - if ( m_bPlayedLoopingSound ) - { - StopSound( "NPC_Crow.Flap" ); - } - BaseClass::StopLoopingSounds(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Catches the monster-specific messages that occur when tagged -// animation frames are played. -// Input : pEvent - -//----------------------------------------------------------------------------- -void CNPC_Crow::HandleAnimEvent( animevent_t *pEvent ) -{ - if ( pEvent->event == AE_CROW_TAKEOFF ) - { - if ( GetNavigator()->GetPath()->GetCurWaypoint() ) - { - Takeoff( GetNavigator()->GetCurWaypointPos() ); - } - return; - } - - if( pEvent->event == AE_CROW_HOP ) - { - SetGroundEntity( NULL ); - - // - // Take him off ground so engine doesn't instantly reset FL_ONGROUND. - // - UTIL_SetOrigin( this, GetLocalOrigin() + Vector( 0 , 0 , 1 )); - - // - // How fast does the crow need to travel to reach the hop goal given gravity? - // - float flHopDistance = ( m_vSavePosition - GetLocalOrigin() ).Length(); - float gravity = sv_gravity.GetFloat(); - if ( gravity <= 1 ) - { - gravity = 1; - } - - float height = 0.25 * flHopDistance; - float speed = sqrt( 2 * gravity * height ); - float time = speed / gravity; - - // - // Scale the sideways velocity to get there at the right time - // - Vector vecJumpDir = m_vSavePosition - GetLocalOrigin(); - vecJumpDir = vecJumpDir / time; - - // - // Speed to offset gravity at the desired height. - // - vecJumpDir.z = speed; - - // - // Don't jump too far/fast. - // - float distance = vecJumpDir.Length(); - if ( distance > 650 ) - { - vecJumpDir = vecJumpDir * ( 650.0 / distance ); - } - - m_nMorale -= random->RandomInt( 1, 6 ); - if ( m_nMorale <= 0 ) - { - m_nMorale = 0; - } - - // Play a hop flap sound. - EmitSound( "NPC_Crow.Hop" ); - - SetAbsVelocity( vecJumpDir ); - return; - } - - if( pEvent->event == AE_CROW_FLY ) - { - // - // Start flying. - // - SetActivity( ACT_FLY ); - - m_bSoar = false; - m_flSoarTime = gpGlobals->curtime + random->RandomFloat( 3, 5 ); - - return; - } - - CAI_BaseNPC::HandleAnimEvent( pEvent ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : eNewActivity - -//----------------------------------------------------------------------------- -void CNPC_Crow::OnChangeActivity( Activity eNewActivity ) -{ -// if ( eNewActivity == ACT_FLY ) -// { -// m_flGroundSpeed = CROW_AIRSPEED; -// } -// - bool fRandomize = false; - if ( eNewActivity == ACT_FLY ) - { - fRandomize = true; - } - - BaseClass::OnChangeActivity( eNewActivity ); - if ( fRandomize ) - { - SetCycle( random->RandomFloat( 0.0, 0.75 ) ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that makes the crow fly away. -//----------------------------------------------------------------------------- -void CNPC_Crow::InputFlyAway( inputdata_t &inputdata ) -{ - string_t sTarget = MAKE_STRING( inputdata.value.String() ); - - if ( sTarget != NULL_STRING )// this npc has a target - { - CBaseEntity *pEnt = gEntList.FindEntityByName( NULL, sTarget ); - - if ( pEnt ) - { - trace_t tr; - AI_TraceLine ( EyePosition(), pEnt->GetAbsOrigin(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction != 1.0f ) - return; - - // Find the npc's initial target entity, stash it - SetGoalEnt( pEnt ); - } - } - else - SetGoalEnt( NULL ); - - SetCondition( COND_CROW_FORCED_FLY ); - SetCondition( COND_PROVOKED ); - -} - -void CNPC_Crow::UpdateEfficiency( bool bInPVS ) -{ - if ( IsFlying() ) - { - SetEfficiency( ( GetSleepState() != AISS_AWAKE ) ? AIE_DORMANT : AIE_NORMAL ); - SetMoveEfficiency( AIME_NORMAL ); - return; - } - - BaseClass::UpdateEfficiency( bInPVS ); -} - -//----------------------------------------------------------------------------- -// Purpose: Implements "deafness" -//----------------------------------------------------------------------------- -bool CNPC_Crow::QueryHearSound( CSound *pSound ) -{ - if( IsDeaf() ) - return false; - - return BaseClass::QueryHearSound( pSound ); -} - -//----------------------------------------------------------------------------- -// Purpose: Handles all flight movement because we don't ever build paths when -// when we are flying. -// Input : flInterval - Seconds to simulate. -//----------------------------------------------------------------------------- -bool CNPC_Crow::OverrideMove( float flInterval ) -{ - if ( GetNavigator()->GetPath()->CurWaypointNavType() == NAV_FLY && GetNavigator()->GetNavType() != NAV_FLY ) - { - SetNavType( NAV_FLY ); - } - - if ( IsFlying() ) - { - if ( GetNavigator()->GetPath()->GetCurWaypoint() ) - { - if ( m_flLastStuckCheck <= gpGlobals->curtime ) - { - if ( m_vLastStoredOrigin == GetAbsOrigin() ) - { - if ( GetAbsVelocity() == vec3_origin ) - { - float flDamage = m_iHealth; - - CTakeDamageInfo dmgInfo( this, this, flDamage, DMG_GENERIC ); - GuessDamageForce( &dmgInfo, vec3_origin - Vector( 0, 0, 0.1 ), GetAbsOrigin() ); - TakeDamage( dmgInfo ); - - return false; - } - else - { - m_vLastStoredOrigin = GetAbsOrigin(); - } - } - else - { - m_vLastStoredOrigin = GetAbsOrigin(); - } - - m_flLastStuckCheck = gpGlobals->curtime + 1.0f; - } - - if (m_bReachedMoveGoal ) - { - SetIdealActivity( (Activity)ACT_CROW_LAND ); - SetFlyingState( FlyState_Landing ); - TaskMovementComplete(); - } - else - { - SetIdealActivity ( ACT_FLY ); - MoveCrowFly( flInterval ); - } - - } - else if ( !GetTask() || GetTask()->iTask == TASK_WAIT_FOR_MOVEMENT ) - { - SetSchedule( SCHED_CROW_IDLE_FLY ); - SetFlyingState( FlyState_Flying ); - SetIdealActivity ( ACT_FLY ); - } - return true; - } - - return false; -} - -Activity CNPC_Crow::NPC_TranslateActivity( Activity eNewActivity ) -{ - if ( IsFlying() && eNewActivity == ACT_IDLE ) - { - return ACT_FLY; - } - - if ( eNewActivity == ACT_FLY ) - { - if ( m_flSoarTime < gpGlobals->curtime ) - { - //Adrian: This should be revisited. - if ( random->RandomInt( 0, 100 ) <= 50 && m_bSoar == false && GetAbsVelocity().z < 0 ) - { - m_bSoar = true; - m_flSoarTime = gpGlobals->curtime + random->RandomFloat( 1, 4 ); - } - else - { - m_bSoar = false; - m_flSoarTime = gpGlobals->curtime + random->RandomFloat( 3, 5 ); - } - } - - if ( m_bSoar == true ) - { - return (Activity)ACT_CROW_SOAR; - } - else - return ACT_FLY; - } - - return BaseClass::NPC_TranslateActivity( eNewActivity ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Handles all flight movement. -// Input : flInterval - Seconds to simulate. -//----------------------------------------------------------------------------- -void CNPC_Crow::MoveCrowFly( float flInterval ) -{ - // - // Bound interval so we don't get ludicrous motion when debugging - // or when framerate drops catastrophically. - // - if (flInterval > 1.0) - { - flInterval = 1.0; - } - - m_flDangerSoundTime = gpGlobals->curtime + 5.0f; - - // - // Determine the goal of our movement. - // - Vector vecMoveGoal = GetAbsOrigin(); - - if ( GetNavigator()->IsGoalActive() ) - { - vecMoveGoal = GetNavigator()->GetCurWaypointPos(); - - if ( GetNavigator()->CurWaypointIsGoal() == false ) - { - AI_ProgressFlyPathParams_t params( MASK_NPCSOLID ); - params.bTrySimplify = false; - - GetNavigator()->ProgressFlyPath( params ); // ignore result, crow handles completion directly - - // Fly towards the hint. - if ( GetNavigator()->GetPath()->GetCurWaypoint() ) - { - vecMoveGoal = GetNavigator()->GetCurWaypointPos(); - } - } - } - else - { - // No movement goal. - vecMoveGoal = GetAbsOrigin(); - SetAbsVelocity( vec3_origin ); - return; - } - - Vector vecMoveDir = ( vecMoveGoal - GetAbsOrigin() ); - Vector vForward; - AngleVectors( GetAbsAngles(), &vForward ); - - // - // Fly towards the movement goal. - // - float flDistance = ( vecMoveGoal - GetAbsOrigin() ).Length(); - - if ( vecMoveGoal != m_vDesiredTarget ) - { - m_vDesiredTarget = vecMoveGoal; - } - else - { - m_vCurrentTarget = ( m_vDesiredTarget - GetAbsOrigin() ); - VectorNormalize( m_vCurrentTarget ); - } - - float flLerpMod = 0.25f; - - if ( flDistance <= 256.0f ) - { - flLerpMod = 1.0f - ( flDistance / 256.0f ); - } - - - VectorLerp( vForward, m_vCurrentTarget, flLerpMod, vForward ); - - - if ( flDistance < CROW_AIRSPEED * flInterval ) - { - if ( GetNavigator()->IsGoalActive() ) - { - if ( GetNavigator()->CurWaypointIsGoal() ) - { - m_bReachedMoveGoal = true; - } - else - { - GetNavigator()->AdvancePath(); - } - } - else - m_bReachedMoveGoal = true; - } - - if ( GetHintNode() ) - { - AIMoveTrace_t moveTrace; - GetMoveProbe()->MoveLimit( NAV_FLY, GetAbsOrigin(), GetNavigator()->GetCurWaypointPos(), MASK_NPCSOLID, GetNavTargetEntity(), &moveTrace ); - - //See if it succeeded - if ( IsMoveBlocked( moveTrace.fStatus ) ) - { - Vector vNodePos = vecMoveGoal; - GetHintNode()->GetPosition(this, &vNodePos); - - GetNavigator()->SetGoal( vNodePos ); - } - } - - // - // Look to see if we are going to hit anything. - // - VectorNormalize( vForward ); - Vector vecDeflect; - if ( Probe( vForward, CROW_AIRSPEED * flInterval, vecDeflect ) ) - { - vForward = vecDeflect; - VectorNormalize( vForward ); - } - - SetAbsVelocity( vForward * CROW_AIRSPEED ); - - if ( GetAbsVelocity().Length() > 0 && GetNavigator()->CurWaypointIsGoal() && flDistance < CROW_AIRSPEED ) - { - SetIdealActivity( (Activity)ACT_CROW_LAND ); - } - - - //Bank and set angles. - Vector vRight; - QAngle vRollAngle; - - VectorAngles( vForward, vRollAngle ); - vRollAngle.z = 0; - - AngleVectors( vRollAngle, NULL, &vRight, NULL ); - - float flRoll = DotProduct( vRight, vecMoveDir ) * 45; - flRoll = clamp( flRoll, -45, 45 ); - - vRollAngle[ROLL] = flRoll; - SetAbsAngles( vRollAngle ); -} - -//----------------------------------------------------------------------------- -// Purpose: Looks ahead to see if we are going to hit something. If we are, a -// recommended avoidance path is returned. -// Input : vecMoveDir - -// flSpeed - -// vecDeflect - -// Output : Returns true if we hit something and need to deflect our course, -// false if all is well. -//----------------------------------------------------------------------------- -bool CNPC_Crow::Probe( const Vector &vecMoveDir, float flSpeed, Vector &vecDeflect ) -{ - // - // Look 1/2 second ahead. - // - trace_t tr; - AI_TraceHull( GetAbsOrigin(), GetAbsOrigin() + vecMoveDir * flSpeed, GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, HL2COLLISION_GROUP_CROW, &tr ); - if ( tr.fraction < 1.0f ) - { - // - // If we hit something, deflect flight path parallel to surface hit. - // - Vector vecUp; - CrossProduct( vecMoveDir, tr.plane.normal, vecUp ); - CrossProduct( tr.plane.normal, vecUp, vecDeflect ); - VectorNormalize( vecDeflect ); - return true; - } - - vecDeflect = vec3_origin; - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Switches between flying mode and ground mode. -//----------------------------------------------------------------------------- -void CNPC_Crow::SetFlyingState( FlyState_t eState ) -{ - if ( eState == FlyState_Flying ) - { - // Flying - SetGroundEntity( NULL ); - AddFlag( FL_FLY ); - SetNavType( NAV_FLY ); - CapabilitiesRemove( bits_CAP_MOVE_GROUND ); - CapabilitiesAdd( bits_CAP_MOVE_FLY ); - SetMoveType( MOVETYPE_STEP ); - m_vLastStoredOrigin = GetAbsOrigin(); - m_flLastStuckCheck = gpGlobals->curtime + 3.0f; - m_flGroundIdleMoveTime = gpGlobals->curtime + random->RandomFloat( 5.0f, 10.0f ); - } - else if ( eState == FlyState_Walking ) - { - // Walking - QAngle angles = GetAbsAngles(); - angles[PITCH] = 0.0f; - angles[ROLL] = 0.0f; - SetAbsAngles( angles ); - - RemoveFlag( FL_FLY ); - SetNavType( NAV_GROUND ); - CapabilitiesRemove( bits_CAP_MOVE_FLY ); - CapabilitiesAdd( bits_CAP_MOVE_GROUND ); - SetMoveType( MOVETYPE_STEP ); - m_vLastStoredOrigin = vec3_origin; - m_flGroundIdleMoveTime = gpGlobals->curtime + random->RandomFloat( 5.0f, 10.0f ); - } - else - { - // Falling - RemoveFlag( FL_FLY ); - SetNavType( NAV_GROUND ); - CapabilitiesRemove( bits_CAP_MOVE_FLY ); - CapabilitiesAdd( bits_CAP_MOVE_GROUND ); - SetMoveType( MOVETYPE_STEP ); - m_flGroundIdleMoveTime = gpGlobals->curtime + random->RandomFloat( 5.0f, 10.0f ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Performs a takeoff. Called via an animation event at the moment -// our feet leave the ground. -// Input : pGoalEnt - The entity that we are going to fly toward. -//----------------------------------------------------------------------------- -void CNPC_Crow::Takeoff( const Vector &vGoal ) -{ - if ( vGoal != vec3_origin ) - { - // - // Lift us off ground so engine doesn't instantly reset FL_ONGROUND. - // - UTIL_SetOrigin( this, GetAbsOrigin() + Vector( 0 , 0 , 1 )); - - // - // Fly straight at the goal entity at our maximum airspeed. - // - Vector vecMoveDir = vGoal - GetAbsOrigin(); - VectorNormalize( vecMoveDir ); - - // FIXME: pitch over time - - SetFlyingState( FlyState_Flying ); - - QAngle angles; - VectorAngles( vecMoveDir, angles ); - SetAbsAngles( angles ); - - SetAbsVelocity( vecMoveDir * CROW_TAKEOFF_SPEED ); - } -} - -void CNPC_Crow::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - CTakeDamageInfo newInfo = info; - - if ( info.GetDamageType() & DMG_PHYSGUN ) - { - Vector puntDir = ( info.GetDamageForce() * 5000.0f ); - - newInfo.SetDamage( m_iMaxHealth ); - - PainSound( newInfo ); - newInfo.SetDamageForce( puntDir ); - } - - BaseClass::TraceAttack( newInfo, vecDir, ptr ); -} - - -void CNPC_Crow::StartTargetHandling( CBaseEntity *pTargetEnt ) -{ - AI_NavGoal_t goal( GOALTYPE_PATHCORNER, pTargetEnt->GetAbsOrigin(), - ACT_FLY, - AIN_DEF_TOLERANCE, AIN_YAW_TO_DEST); - - if ( !GetNavigator()->SetGoal( goal ) ) - { - DevWarning( 2, "Can't Create Route!\n" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pTask - -//----------------------------------------------------------------------------- -void CNPC_Crow::StartTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - // - // This task enables us to build a path that requires flight. - // -// case TASK_CROW_PREPARE_TO_FLY: -// { -// SetFlyingState( FlyState_Flying ); -// TaskComplete(); -// break; -// } - - case TASK_CROW_TAKEOFF: - { - if ( random->RandomInt( 1, 4 ) == 1 ) - { - AlertSound(); - } - - FlapSound(); - - SetIdealActivity( ( Activity )ACT_CROW_TAKEOFF ); - break; - } - - case TASK_CROW_PICK_EVADE_GOAL: - { - if ( GetEnemy() != NULL ) - { - // - // Get our enemy's position in x/y. - // - Vector vecEnemyOrigin = GetEnemy()->GetAbsOrigin(); - vecEnemyOrigin.z = GetAbsOrigin().z; - - // - // Pick a hop goal a random distance along a vector away from our enemy. - // - m_vSavePosition = GetAbsOrigin() - vecEnemyOrigin; - VectorNormalize( m_vSavePosition ); - m_vSavePosition = GetAbsOrigin() + m_vSavePosition * ( 32 + random->RandomInt( 0, 32 ) ); - - GetMotor()->SetIdealYawToTarget( m_vSavePosition ); - TaskComplete(); - } - else - { - TaskFail( "No enemy" ); - } - break; - } - - case TASK_CROW_FALL_TO_GROUND: - { - SetFlyingState( FlyState_Falling ); - break; - } - - case TASK_FIND_HINTNODE: - { - if ( GetGoalEnt() ) - { - TaskComplete(); - return; - } - // Overloaded because we search over a greater distance. - if ( !GetHintNode() ) - { - SetHintNode(CAI_HintManager::FindHint( this, HINT_CROW_FLYTO_POINT, bits_HINT_NODE_NEAREST | bits_HINT_NODE_USE_GROUP, 10000 )); - } - - if ( GetHintNode() ) - { - TaskComplete(); - } - else - { - TaskFail( FAIL_NO_HINT_NODE ); - } - break; - } - - case TASK_GET_PATH_TO_HINTNODE: - { - //How did this happen?! - if ( GetGoalEnt() == this ) - { - SetGoalEnt( NULL ); - } - - if ( GetGoalEnt() ) - { - SetFlyingState( FlyState_Flying ); - StartTargetHandling( GetGoalEnt() ); - - m_bReachedMoveGoal = false; - TaskComplete(); - SetHintNode( NULL ); - return; - } - - if ( GetHintNode() ) - { - Vector vHintPos; - GetHintNode()->GetPosition(this, &vHintPos); - - SetNavType( NAV_FLY ); - CapabilitiesAdd( bits_CAP_MOVE_FLY ); - // @HACKHACK: Force allow triangulation. Too many HL2 maps were relying on this feature WRT fly nodes (toml 8/1/2007) - NPC_STATE state = GetState(); - m_NPCState = NPC_STATE_SCRIPT; - bool bFoundPath = GetNavigator()->SetGoal( vHintPos ); - m_NPCState = state; - if ( !bFoundPath ) - { - GetHintNode()->DisableForSeconds( .3 ); - SetHintNode(NULL); - } - CapabilitiesRemove( bits_CAP_MOVE_FLY ); - } - - if ( GetHintNode() ) - { - m_bReachedMoveGoal = false; - TaskComplete(); - } - else - { - TaskFail( FAIL_NO_ROUTE ); - } - break; - } - - // - // We have failed to fly normally. Pick a random "up" direction and fly that way. - // - case TASK_CROW_FLY: - { - float flYaw = UTIL_AngleMod( random->RandomInt( -180, 180 ) ); - - Vector vecNewVelocity( cos( DEG2RAD( flYaw ) ), sin( DEG2RAD( flYaw ) ), random->RandomFloat( 0.1f, 0.5f ) ); - vecNewVelocity *= CROW_AIRSPEED; - SetAbsVelocity( vecNewVelocity ); - - SetIdealActivity( ACT_FLY ); - - m_bSoar = false; - m_flSoarTime = gpGlobals->curtime + random->RandomFloat( 2, 5 ); - - break; - } - - case TASK_CROW_PICK_RANDOM_GOAL: - { - m_vSavePosition = GetLocalOrigin() + Vector( random->RandomFloat( -48.0f, 48.0f ), random->RandomFloat( -48.0f, 48.0f ), 0 ); - TaskComplete(); - break; - } - - case TASK_CROW_HOP: - { - SetIdealActivity( ACT_HOP ); - m_flHopStartZ = GetLocalOrigin().z; - break; - } - - case TASK_CROW_WAIT_FOR_BARNACLE_KILL: - { - break; - } - - default: - { - BaseClass::StartTask( pTask ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pTask - -//----------------------------------------------------------------------------- -void CNPC_Crow::RunTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_CROW_TAKEOFF: - { - if ( GetNavigator()->IsGoalActive() ) - { - GetMotor()->SetIdealYawToTargetAndUpdate( GetAbsOrigin() + GetNavigator()->GetCurWaypointPos(), AI_KEEP_YAW_SPEED ); - } - else - TaskFail( FAIL_NO_ROUTE ); - - if ( IsActivityFinished() ) - { - TaskComplete(); - SetIdealActivity( ACT_FLY ); - - m_bSoar = false; - m_flSoarTime = gpGlobals->curtime + random->RandomFloat( 2, 5 ); - } - - break; - } - - case TASK_CROW_HOP: - { - if ( IsActivityFinished() ) - { - TaskComplete(); - SetIdealActivity( ACT_IDLE ); - } - - if ( ( GetAbsOrigin().z < m_flHopStartZ ) && ( !( GetFlags() & FL_ONGROUND ) ) ) - { - // - // We've hopped off of something! See if we're going to fall very far. - // - trace_t tr; - AI_TraceLine( GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, -32 ), MASK_SOLID, this, HL2COLLISION_GROUP_CROW, &tr ); - if ( tr.fraction == 1.0f ) - { - // - // We're falling! Better fly away. SelectSchedule will check ONGROUND and do the right thing. - // - TaskComplete(); - } - else - { - // - // We'll be okay. Don't check again unless what we're hopping onto moves - // out from under us. - // - m_flHopStartZ = GetAbsOrigin().z - ( 32 * tr.fraction ); - } - } - - break; - } - - // - // Face the direction we are flying. - // - case TASK_CROW_FLY: - { - GetMotor()->SetIdealYawToTargetAndUpdate( GetAbsOrigin() + GetAbsVelocity(), AI_KEEP_YAW_SPEED ); - - break; - } - - case TASK_CROW_FALL_TO_GROUND: - { - if ( GetFlags() & FL_ONGROUND ) - { - SetFlyingState( FlyState_Walking ); - TaskComplete(); - } - break; - } - - case TASK_CROW_WAIT_FOR_BARNACLE_KILL: - { - if ( m_flNextFlinchTime < gpGlobals->curtime ) - { - m_flNextFlinchTime = gpGlobals->curtime + random->RandomFloat( 0.5f, 2.0f ); - // dvs: TODO: squirm - // dvs: TODO: spawn feathers - EmitSound( "NPC_Crow.Squawk" ); - } - break; - } - - default: - { - CAI_BaseNPC::RunTask( pTask ); - } - } -} - - -//------------------------------------------------------------------------------ -// Purpose: Override to do crow specific gibs. -// Output : Returns true to gib, false to not gib. -//----------------------------------------------------------------------------- -bool CNPC_Crow::CorpseGib( const CTakeDamageInfo &info ) -{ - EmitSound( "NPC_Crow.Gib" ); - - // TODO: crow gibs? - //CGib::SpawnSpecificGibs( this, CROW_GIB_COUNT, 300, 400, "models/gibs/crow_gibs.mdl"); - - return true; -} - -//----------------------------------------------------------------------------- -// Don't allow ridiculous forces to be applied to the crow. It only weighs -// 1.5kg, so extreme forces will give it ridiculous velocity. -//----------------------------------------------------------------------------- -#define CROW_RAGDOLL_SPEED_LIMIT 1000.0f // Crow ragdoll speed limit in inches per second. -bool CNPC_Crow::BecomeRagdollOnClient( const Vector &force ) -{ - Vector newForce = force; - - if( VPhysicsGetObject() ) - { - float flMass = VPhysicsGetObject()->GetMass(); - float speed = VectorNormalize( newForce ); - speed = MIN( speed, (CROW_RAGDOLL_SPEED_LIMIT * flMass) ); - newForce *= speed; - } - - return BaseClass::BecomeRagdollOnClient( newForce ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_Crow::FValidateHintType( CAI_Hint *pHint ) -{ - return( pHint->HintType() == HINT_CROW_FLYTO_POINT ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns the activity for the given hint type. -// Input : sHintType - -//----------------------------------------------------------------------------- -Activity CNPC_Crow::GetHintActivity( short sHintType, Activity HintsActivity ) -{ - if ( sHintType == HINT_CROW_FLYTO_POINT ) - { - return ACT_FLY; - } - - return BaseClass::GetHintActivity( sHintType, HintsActivity ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pevInflictor - -// pevAttacker - -// flDamage - -// bitsDamageType - -//----------------------------------------------------------------------------- -int CNPC_Crow::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - // TODO: spew a feather or two - return BaseClass::OnTakeDamage_Alive( info ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns the best new schedule for this NPC based on current conditions. -//----------------------------------------------------------------------------- -int CNPC_Crow::SelectSchedule( void ) -{ - if ( HasCondition( COND_CROW_BARNACLED ) ) - { - // Caught by a barnacle! - return SCHED_CROW_BARNACLED; - } - - // - // If we're flying, just find somewhere to fly to. - // - if ( IsFlying() ) - { - return SCHED_CROW_IDLE_FLY; - } - - // - // If we were told to fly away via our FlyAway input, do so ASAP. - // - if ( HasCondition( COND_CROW_FORCED_FLY ) ) - { - ClearCondition( COND_CROW_FORCED_FLY ); - return SCHED_CROW_FLY_AWAY; - } - - // - // If we're not flying but we're not on the ground, start flying. - // Maybe we hopped off of something? Don't do this immediately upon - // because we may be falling to the ground on spawn. - // - if ( !( GetFlags() & FL_ONGROUND ) && ( gpGlobals->curtime > 2.0 ) && m_bOnJeep == false ) - { - return SCHED_CROW_FLY_AWAY; - } - - // - // If we heard a gunshot or have taken damage, fly away. - // - if ( HasCondition( COND_LIGHT_DAMAGE ) || HasCondition( COND_HEAVY_DAMAGE ) ) - { - return SCHED_CROW_FLY_AWAY; - } - - if ( m_flDangerSoundTime <= gpGlobals->curtime ) - { - if ( HasCondition( COND_HEAR_DANGER ) || HasCondition( COND_HEAR_COMBAT ) ) - { - m_flDangerSoundTime = gpGlobals->curtime + 10.0f; - return SCHED_CROW_FLY_AWAY; - } - } - - // - // If someone we hate is getting WAY too close for comfort, fly away. - // - if ( HasCondition( COND_CROW_ENEMY_WAY_TOO_CLOSE ) ) - { - ClearCondition( COND_CROW_ENEMY_WAY_TOO_CLOSE ); - - m_nMorale = 0; - return SCHED_CROW_FLY_AWAY; - } - - // - // If someone we hate is getting a little too close for comfort, avoid them. - // - if ( HasCondition( COND_CROW_ENEMY_TOO_CLOSE ) && m_flDangerSoundTime <= gpGlobals->curtime ) - { - ClearCondition( COND_CROW_ENEMY_TOO_CLOSE ); - - if ( m_bOnJeep == true ) - { - m_nMorale = 0; - return SCHED_CROW_FLY_AWAY; - } - - if ( m_flEnemyDist > 400 ) - { - return SCHED_CROW_WALK_AWAY; - } - else if ( m_flEnemyDist > 300 ) - { - m_nMorale -= 1; - return SCHED_CROW_RUN_AWAY; - } - } - - switch ( m_NPCState ) - { - case NPC_STATE_IDLE: - case NPC_STATE_ALERT: - case NPC_STATE_COMBAT: - { - if ( !IsFlying() ) - { - if ( m_bOnJeep == true ) - return SCHED_IDLE_STAND; - - // - // If we are hanging out on the ground, see if it is time to pick a new place to walk to. - // - if ( gpGlobals->curtime > m_flGroundIdleMoveTime ) - { - m_flGroundIdleMoveTime = gpGlobals->curtime + random->RandomFloat( 10.0f, 20.0f ); - return SCHED_CROW_IDLE_WALK; - } - - return SCHED_IDLE_STAND; - } - - // TODO: need idle flying behaviors! - } - - default: - break; - } - - return BaseClass::SelectSchedule(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Crow::Precache( void ) -{ - BaseClass::Precache(); - - PrecacheModel( "models/crow.mdl" ); - PrecacheModel( "models/pigeon.mdl" ); - PrecacheModel( "models/seagull.mdl" ); - - //Crow - PrecacheScriptSound( "NPC_Crow.Hop" ); - PrecacheScriptSound( "NPC_Crow.Squawk" ); - PrecacheScriptSound( "NPC_Crow.Gib" ); - PrecacheScriptSound( "NPC_Crow.Idle" ); - PrecacheScriptSound( "NPC_Crow.Alert" ); - PrecacheScriptSound( "NPC_Crow.Die" ); - PrecacheScriptSound( "NPC_Crow.Pain" ); - PrecacheScriptSound( "NPC_Crow.Flap" ); - - //Seagull - PrecacheScriptSound( "NPC_Seagull.Pain" ); - PrecacheScriptSound( "NPC_Seagull.Idle" ); - - //Pigeon - PrecacheScriptSound( "NPC_Pigeon.Idle"); -} - - -//----------------------------------------------------------------------------- -// Purpose: Sounds. -//----------------------------------------------------------------------------- -void CNPC_Crow::IdleSound( void ) -{ - if ( m_iBirdType != BIRDTYPE_CROW ) - return; - - EmitSound( "NPC_Crow.Idle" ); -} - - -void CNPC_Crow::AlertSound( void ) -{ - if ( m_iBirdType != BIRDTYPE_CROW ) - return; - - EmitSound( "NPC_Crow.Alert" ); -} - - -void CNPC_Crow::PainSound( const CTakeDamageInfo &info ) -{ - if ( m_iBirdType != BIRDTYPE_CROW ) - return; - - EmitSound( "NPC_Crow.Pain" ); -} - - -void CNPC_Crow::DeathSound( const CTakeDamageInfo &info ) -{ - if ( m_iBirdType != BIRDTYPE_CROW ) - return; - - EmitSound( "NPC_Crow.Die" ); -} - -void CNPC_Crow::FlapSound( void ) -{ - EmitSound( "NPC_Crow.Flap" ); - m_bPlayedLoopingSound = true; -} - - -//----------------------------------------------------------------------------- -// Purpose: This is a generic function (to be implemented by sub-classes) to -// handle specific interactions between different types of characters -// (For example the barnacle grabbing an NPC) -// Input : Constant for the type of interaction -// Output : true - if sub-class has a response for the interaction -// false - if sub-class has no response -//----------------------------------------------------------------------------- -bool CNPC_Crow::HandleInteraction( int interactionType, void *data, CBaseCombatCharacter *sourceEnt ) -{ - if ( interactionType == g_interactionBarnacleVictimDangle ) - { - // Die instantly - return false; - } - else if ( interactionType == g_interactionBarnacleVictimGrab ) - { - if ( GetFlags() & FL_ONGROUND ) - { - SetGroundEntity( NULL ); - } - - // return ideal grab position - if (data) - { - // FIXME: need a good way to ensure this contract - *((Vector *)data) = GetAbsOrigin() + Vector( 0, 0, 5 ); - } - - StopLoopingSounds(); - - SetThink( NULL ); - return true; - } - - return BaseClass::HandleInteraction( interactionType, data, sourceEnt ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_Crow::DrawDebugTextOverlays( void ) -{ - int nOffset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - Q_snprintf( tempstr, sizeof( tempstr ), "morale: %d", m_nMorale ); - EntityText( nOffset, tempstr, 0 ); - nOffset++; - - if ( GetEnemy() != NULL ) - { - Q_snprintf( tempstr, sizeof( tempstr ), "enemy (dist): %s (%g)", GetEnemy()->GetClassname(), ( double )m_flEnemyDist ); - EntityText( nOffset, tempstr, 0 ); - nOffset++; - } - } - - return nOffset; -} - - -//----------------------------------------------------------------------------- -// Purpose: Determines which sounds the crow cares about. -//----------------------------------------------------------------------------- -int CNPC_Crow::GetSoundInterests( void ) -{ - return SOUND_WORLD | SOUND_COMBAT | SOUND_PLAYER | SOUND_DANGER; -} - - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC( npc_crow, CNPC_Crow ) - - DECLARE_TASK( TASK_CROW_FIND_FLYTO_NODE ) - //DECLARE_TASK( TASK_CROW_PREPARE_TO_FLY ) - DECLARE_TASK( TASK_CROW_TAKEOFF ) - DECLARE_TASK( TASK_CROW_FLY ) - DECLARE_TASK( TASK_CROW_PICK_RANDOM_GOAL ) - DECLARE_TASK( TASK_CROW_HOP ) - DECLARE_TASK( TASK_CROW_PICK_EVADE_GOAL ) - DECLARE_TASK( TASK_CROW_WAIT_FOR_BARNACLE_KILL ) - - // experiment - DECLARE_TASK( TASK_CROW_FALL_TO_GROUND ) - DECLARE_TASK( TASK_CROW_PREPARE_TO_FLY_RANDOM ) - - DECLARE_ACTIVITY( ACT_CROW_TAKEOFF ) - DECLARE_ACTIVITY( ACT_CROW_SOAR ) - DECLARE_ACTIVITY( ACT_CROW_LAND ) - - DECLARE_ANIMEVENT( AE_CROW_HOP ) - DECLARE_ANIMEVENT( AE_CROW_FLY ) - DECLARE_ANIMEVENT( AE_CROW_TAKEOFF ) - - - DECLARE_CONDITION( COND_CROW_ENEMY_TOO_CLOSE ) - DECLARE_CONDITION( COND_CROW_ENEMY_WAY_TOO_CLOSE ) - DECLARE_CONDITION( COND_CROW_FORCED_FLY ) - DECLARE_CONDITION( COND_CROW_BARNACLED ) - - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CROW_IDLE_WALK, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_IDLE_STAND" - " TASK_CROW_PICK_RANDOM_GOAL 0" - " TASK_GET_PATH_TO_SAVEPOSITION 0" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_WAIT_PVS 0" - " " - " Interrupts" - " COND_CROW_FORCED_FLY" - " COND_PROVOKED" - " COND_CROW_ENEMY_TOO_CLOSE" - " COND_NEW_ENEMY" - " COND_HEAVY_DAMAGE" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_HEAR_COMBAT" - ) - - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CROW_WALK_AWAY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CROW_FLY_AWAY" - " TASK_CROW_PICK_EVADE_GOAL 0" - " TASK_GET_PATH_TO_SAVEPOSITION 0" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " " - " Interrupts" - " COND_CROW_FORCED_FLY" - " COND_CROW_ENEMY_WAY_TOO_CLOSE" - " COND_NEW_ENEMY" - " COND_HEAVY_DAMAGE" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_HEAR_COMBAT" - ) - - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CROW_RUN_AWAY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CROW_FLY_AWAY" - " TASK_CROW_PICK_EVADE_GOAL 0" - " TASK_GET_PATH_TO_SAVEPOSITION 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " " - " Interrupts" - " COND_CROW_FORCED_FLY" - " COND_CROW_ENEMY_WAY_TOO_CLOSE" - " COND_NEW_ENEMY" - " COND_HEAVY_DAMAGE" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_HEAR_COMBAT" - ) - - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CROW_HOP_AWAY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CROW_FLY_AWAY" - " TASK_STOP_MOVING 0" - " TASK_CROW_PICK_EVADE_GOAL 0" - " TASK_FACE_IDEAL 0" - " TASK_CROW_HOP 0" - " " - " Interrupts" - " COND_CROW_FORCED_FLY" - " COND_HEAVY_DAMAGE" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_HEAR_COMBAT" - ) - - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CROW_IDLE_FLY, - - " Tasks" - " TASK_FIND_HINTNODE 0" - " TASK_GET_PATH_TO_HINTNODE 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " " - " Interrupts" - ) - - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CROW_FLY_AWAY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CROW_FLY_FAIL" - " TASK_STOP_MOVING 0" - " TASK_FIND_HINTNODE 0" - " TASK_GET_PATH_TO_HINTNODE 0" - " TASK_CROW_TAKEOFF 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " " - " Interrupts" - ) - - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CROW_FLY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CROW_FLY_FAIL" - " TASK_STOP_MOVING 0" - " TASK_CROW_TAKEOFF 0" - " TASK_CROW_FLY 0" - " " - " Interrupts" - ) - - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CROW_FLY_FAIL, - - " Tasks" - " TASK_CROW_FALL_TO_GROUND 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_CROW_IDLE_WALK" - " " - " Interrupts" - ) - - //========================================================= - // Crow is in the clutches of a barnacle - DEFINE_SCHEDULE - ( - SCHED_CROW_BARNACLED, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_HOP" - " TASK_CROW_WAIT_FOR_BARNACLE_KILL 0" - - " Interrupts" - ) - - -AI_END_CUSTOM_NPC() diff --git a/game/server/hl2/npc_crow.h b/game/server/hl2/npc_crow.h deleted file mode 100644 index f3ccffb68..000000000 --- a/game/server/hl2/npc_crow.h +++ /dev/null @@ -1,256 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef NPC_CROW_H -#define NPC_CROW_H -#ifdef _WIN32 -#pragma once -#endif - -#define BIRDTYPE_CROW 1 -#define BIRDTYPE_PIGEON 2 -#define BIRDTYPE_SEAGULL 3 - -// -// Spawnflags. -// -#define SF_CROW_FLYING 16 - -#define CROW_TAKEOFF_SPEED 170 -#define CROW_AIRSPEED 220 // FIXME: should be about 440, but I need to add acceleration - -// -// Custom schedules. -// -enum -{ - SCHED_CROW_IDLE_WALK = LAST_SHARED_SCHEDULE, - SCHED_CROW_IDLE_FLY, - - // - // Various levels of wanting to get away from something, selected - // by current value of m_nMorale. - // - SCHED_CROW_WALK_AWAY, - SCHED_CROW_RUN_AWAY, - SCHED_CROW_HOP_AWAY, - SCHED_CROW_FLY_AWAY, - - SCHED_CROW_FLY, - SCHED_CROW_FLY_FAIL, - - SCHED_CROW_BARNACLED, -}; - - -// -// Custom tasks. -// -enum -{ - TASK_CROW_FIND_FLYTO_NODE = LAST_SHARED_TASK, - //TASK_CROW_PREPARE_TO_FLY, - TASK_CROW_TAKEOFF, - //TASK_CROW_LAND, - TASK_CROW_FLY, - TASK_CROW_FLY_TO_HINT, - TASK_CROW_PICK_RANDOM_GOAL, - TASK_CROW_PICK_EVADE_GOAL, - TASK_CROW_HOP, - - TASK_CROW_FALL_TO_GROUND, - TASK_CROW_PREPARE_TO_FLY_RANDOM, - - TASK_CROW_WAIT_FOR_BARNACLE_KILL, -}; - - -// -// Custom conditions. -// -enum -{ - COND_CROW_ENEMY_TOO_CLOSE = LAST_SHARED_CONDITION, - COND_CROW_ENEMY_WAY_TOO_CLOSE, - COND_CROW_FORCED_FLY, - COND_CROW_BARNACLED, -}; - -enum FlyState_t -{ - FlyState_Walking = 0, - FlyState_Flying, - FlyState_Falling, - FlyState_Landing, -}; - - -//----------------------------------------------------------------------------- -// The crow class. -//----------------------------------------------------------------------------- -class CNPC_Crow : public CAI_BaseNPC -{ - DECLARE_CLASS( CNPC_Crow, CAI_BaseNPC ); - -public: - - // - // CBaseEntity: - // - virtual void Spawn( void ); - virtual void Precache( void ); - - virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true ); - - virtual int DrawDebugTextOverlays( void ); - - // - // CBaseCombatCharacter: - // - virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - virtual bool CorpseGib( const CTakeDamageInfo &info ); - bool BecomeRagdollOnClient( const Vector &force ); - - // - // CAI_BaseNPC: - // - virtual float MaxYawSpeed( void ) { return 120.0f; } - - virtual Class_T Classify( void ); - virtual void GatherEnemyConditions( CBaseEntity *pEnemy ); - - virtual void HandleAnimEvent( animevent_t *pEvent ); - virtual int GetSoundInterests( void ); - virtual int SelectSchedule( void ); - virtual void StartTask( const Task_t *pTask ); - virtual void RunTask( const Task_t *pTask ); - - virtual bool HandleInteraction( int interactionType, void *data, CBaseCombatCharacter *sourceEnt ); - - virtual void OnChangeActivity( Activity eNewActivity ); - - virtual bool OverrideMove( float flInterval ); - - virtual bool FValidateHintType( CAI_Hint *pHint ); - virtual Activity GetHintActivity( short sHintType, Activity HintsActivity ); - - virtual void PainSound( const CTakeDamageInfo &info ); - virtual void DeathSound( const CTakeDamageInfo &info ); - virtual void IdleSound( void ); - virtual void AlertSound( void ); - virtual void StopLoopingSounds( void ); - virtual void UpdateEfficiency( bool bInPVS ); - - virtual bool QueryHearSound( CSound *pSound ); - - void InputFlyAway( inputdata_t &inputdata ); - - void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - void StartTargetHandling( CBaseEntity *pTargetEnt ); - - DEFINE_CUSTOM_AI; - DECLARE_DATADESC(); - - int m_iBirdType; - bool m_bOnJeep; - -protected: - void SetFlyingState( FlyState_t eState ); - inline bool IsFlying( void ) const { return GetNavType() == NAV_FLY; } - - void Takeoff( const Vector &vGoal ); - void FlapSound( void ); - - void MoveCrowFly( float flInterval ); - bool Probe( const Vector &vecMoveDir, float flSpeed, Vector &vecDeflect ); - - bool IsDeaf() { return m_bIsDeaf; } - -protected: - float m_flGroundIdleMoveTime; - - float m_flEnemyDist; // Distance to GetEnemy(), cached in GatherEnemyConditions. - int m_nMorale; // Used to determine which avoidance schedule to pick. Degrades as I pick avoidance schedules. - - bool m_bReachedMoveGoal; - - float m_flHopStartZ; // Our Z coordinate when we started a hop. Used to check for accidentally hopping off things. - - bool m_bPlayedLoopingSound; - -private: - - Activity NPC_TranslateActivity( Activity eNewActivity ); - - float m_flSoarTime; - bool m_bSoar; - Vector m_vLastStoredOrigin; - float m_flLastStuckCheck; - - float m_flDangerSoundTime; - - Vector m_vDesiredTarget; - Vector m_vCurrentTarget; - - bool m_bIsDeaf; -}; - -//----------------------------------------------------------------------------- -// Purpose: Seagull. Crow with a different model. -//----------------------------------------------------------------------------- -class CNPC_Seagull : public CNPC_Crow -{ - DECLARE_CLASS( CNPC_Seagull, CNPC_Crow ); - -public: - - void Spawn( void ) - { - SetModelName( AllocPooledString("models/seagull.mdl") ); - BaseClass::Spawn(); - - m_iBirdType = BIRDTYPE_SEAGULL; - } - - void PainSound( const CTakeDamageInfo &info ) - { - EmitSound( "NPC_Seagull.Pain" ); - } - - void DeathSound( const CTakeDamageInfo &info ) - { - EmitSound( "NPC_Seagull.Pain" ); - } - - void IdleSound( void ) - { - EmitSound( "NPC_Seagull.Idle" ); - } -}; - -//----------------------------------------------------------------------------- -// Purpose: Pigeon. Crow with a different model. -//----------------------------------------------------------------------------- -class CNPC_Pigeon : public CNPC_Crow -{ - DECLARE_CLASS( CNPC_Pigeon, CNPC_Crow ); - -public: - void Spawn( void ) - { - SetModelName( AllocPooledString("models/pigeon.mdl") ); - BaseClass::Spawn(); - - m_iBirdType = BIRDTYPE_PIGEON; - } - - void IdleSound( void ) - { - EmitSound( "NPC_Pigeon.Idle" ); - } -}; - -#endif // NPC_CROW_H diff --git a/game/server/hl2/npc_dog.cpp b/game/server/hl2/npc_dog.cpp deleted file mode 100644 index c7db99284..000000000 --- a/game/server/hl2/npc_dog.cpp +++ /dev/null @@ -1,1784 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements d0g, the loving and caring head crushing Alyx companion. -// -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" -#include "ai_basenpc.h" -#include "ai_network.h" -#include "ai_navigator.h" -#include "ai_motor.h" -#include "ai_hull.h" -#include "beam_shared.h" -#include "ai_baseactor.h" -#include "npc_rollermine.h" -#include "saverestore_utlvector.h" -#include "physics_bone_follower.h" -#include "Sprite.h" -#include "ai_behavior_follow.h" -#include "collisionutils.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define EFFECT_COUNT 4 - -extern ConVar ai_debug_avoidancebounds; - -class CNPC_Dog : public CAI_BaseActor -{ -public: - DECLARE_DATADESC(); - DECLARE_CLASS( CNPC_Dog, CAI_BaseActor ); - Class_T Classify ( void ); - void Spawn( void ); - void Precache( void ); - void StartTask( const Task_t *pTask ); - void HandleAnimEvent( animevent_t *pEvent ); - int SelectSchedule( void ); - - bool FindPhysicsObject( const char *pPickupName, CBaseEntity *pIgnore = NULL ); - void RunTask( const Task_t *pTask ); - void CreateBeams( void ); - void ClearBeams( void ); - - void PrescheduleThink( void ); - - bool CanTargetSeeMe( void ); - - Vector FacingPosition( void ) { return WorldSpaceCenter(); } - float GetHeadDebounce( void ) { return 0.8; } // how much of previous head turn to use - - void InputSetPickupTarget( inputdata_t &inputdata ); - void InputStartCatchThrowBehavior( inputdata_t &inputdata ); - void InputStopCatchThrowBehavior( inputdata_t &inputdata ); - void InputPlayerPickupObject( inputdata_t &inputdata ); - - void InputStartWaitAndCatch( inputdata_t &inputdata ); - void InputStopWaitAndCatch( inputdata_t &inputdata ); - void InputSetThrowArcModifier( inputdata_t &inputdata ); - void InputSetThrowTarget( inputdata_t &inputdata ); - - void InputTurnBoneFollowersOff( inputdata_t &inputdata ); - void InputTurnBoneFollowersOn( inputdata_t &inputdata ); - - void CleanCatchAndThrow( bool bClearTimers = true ); - void SetTurnActivity ( void ); - void ThrowObject( const char *pAttachmentName ); - void PickupOrCatchObject( const char *pAttachmentName ); - void PullObject( bool bMantain ); - void SetupThrowTarget( void ); - - void GatherConditions( void ); - - Disposition_t IRelationType( CBaseEntity *pTarget ); - - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - - void MantainBoneFollowerCollisionGroups( int CollisionGroup ); - virtual void SetPlayerAvoidState( void ); - -protected: - enum - { - COND_DOG_LOST_PHYSICS_ENTITY = BaseClass::NEXT_CONDITION, - - NEXT_CONDITION, - }; - -protected: - float m_flNextSwat; - float m_flTimeToCatch; - float m_flTimeToPull; - EHANDLE m_hPhysicsEnt; - EHANDLE m_hThrowTarget; - - int m_iPhysGunAttachment; - bool m_bDoCatchThrowBehavior; - bool m_bDoWaitforObjectBehavior; - string_t m_sObjectName; - - COutputEvent m_OnThrow; - COutputEvent m_OnCatch; - COutputEvent m_OnPickup; - - float m_flThrowArcModifier; - int m_iContainerMoveType; - float m_flNextRouteTime; - - bool m_bHasObject; - bool m_bBeamEffects; - - CUtlVector< CHandle > m_hUnreachableObjects; - - // Contained Bone Follower manager - CBoneFollowerManager m_BoneFollowerManager; - - bool CreateVPhysics( void ); - void UpdateOnRemove( void ); - void NPCThink( void ); - void Event_Killed( const CTakeDamageInfo &info ); - - void CreateSprites( void ); - void ClearSprites( void ); - CHandle m_hGlowSprites[EFFECT_COUNT]; - CHandle m_hBeams[EFFECT_COUNT]; //This is temp. - - virtual bool CreateBehaviors( void ); - CAI_FollowBehavior m_FollowBehavior; - - bool m_bBoneFollowersActive; - - -protected: - - DEFINE_CUSTOM_AI; -}; - -LINK_ENTITY_TO_CLASS( npc_dog, CNPC_Dog ); - -BEGIN_DATADESC( CNPC_Dog ) - DEFINE_EMBEDDED( m_BoneFollowerManager ), -// m_FollowBehavior - DEFINE_FIELD( m_flNextSwat, FIELD_TIME ), - DEFINE_FIELD( m_flTimeToCatch, FIELD_TIME ), - DEFINE_FIELD( m_flTimeToPull, FIELD_TIME ), - DEFINE_FIELD( m_hPhysicsEnt, FIELD_EHANDLE ), - DEFINE_FIELD( m_hThrowTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_iPhysGunAttachment, FIELD_INTEGER ), - DEFINE_FIELD( m_bDoCatchThrowBehavior, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bDoWaitforObjectBehavior, FIELD_BOOLEAN ), - DEFINE_FIELD( m_sObjectName, FIELD_STRING ), - DEFINE_FIELD( m_flThrowArcModifier, FIELD_FLOAT ), - DEFINE_FIELD( m_flNextRouteTime, FIELD_TIME ), - DEFINE_FIELD( m_bHasObject, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iContainerMoveType, FIELD_INTEGER ), - DEFINE_FIELD( m_bBeamEffects, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bBoneFollowersActive, FIELD_BOOLEAN ), - DEFINE_UTLVECTOR( m_hUnreachableObjects, FIELD_EHANDLE ), - DEFINE_AUTO_ARRAY( m_hGlowSprites, FIELD_EHANDLE ), - DEFINE_AUTO_ARRAY( m_hBeams, FIELD_EHANDLE ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetPickupTarget", InputSetPickupTarget ), - DEFINE_INPUTFUNC( FIELD_STRING, "StartCatchThrowBehavior", InputStartCatchThrowBehavior ), - DEFINE_INPUTFUNC( FIELD_STRING, "StopCatchThrowBehavior", InputStopCatchThrowBehavior ), - DEFINE_INPUTFUNC( FIELD_VOID, "PlayerPickupObject", InputPlayerPickupObject ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartWaitAndCatch", InputStartWaitAndCatch ), - DEFINE_INPUTFUNC( FIELD_VOID, "StopWaitAndCatch", InputStopWaitAndCatch ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetThrowArcModifier", InputSetThrowArcModifier ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetThrowTarget", InputSetThrowTarget ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnBoneFollowersOff", InputTurnBoneFollowersOff ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnBoneFollowersOn", InputTurnBoneFollowersOn ), - DEFINE_OUTPUT( m_OnThrow, "OnDogThrow"), - DEFINE_OUTPUT( m_OnCatch, "OnDogCatch"), - DEFINE_OUTPUT( m_OnPickup, "OnDogPickup"), - -END_DATADESC() - -#define DOG_PHYSOBJ_MOVE_TO_DIST 96 -#define DOG_PULL_DISTANCE 200 -#define DOG_CATCH_DISTANCE 48 -#define DOG_PULL_VELOCITY_MOD 0.1f -#define DOG_PULL_ANGULARIMP_MOD 0.8f -#define DOG_PULL_TO_GUN_VEL_MOD 2.0f -#define DOG_MAX_THROW_MASS 250.0f -#define DOG_PHYSGUN_ATTACHMENT_NAME "physgun" - -// These bones have physics shadows -static const char *pFollowerBoneNames[] = -{ - // head - "Dog_Model.Eye", - "Dog_Model.Pelvis", -}; - -enum -{ - SCHED_DOG_FIND_OBJECT = LAST_SHARED_SCHEDULE, - SCHED_DOG_CATCH_OBJECT, - SCHED_DOG_WAIT_THROW_OBJECT, -}; - -//========================================================= -// tasks -//========================================================= -enum -{ - TASK_DOG_DELAY_SWAT = LAST_SHARED_TASK, - TASK_DOG_GET_PATH_TO_PHYSOBJ, - TASK_DOG_PICKUP_ITEM, - TASK_DOG_LAUNCH_ITEM, - TASK_DOG_FACE_OBJECT, - TASK_DOG_WAIT_FOR_OBJECT, - TASK_DOG_CATCH_OBJECT, - TASK_DOG_WAIT_FOR_TARGET_TO_FACE, - TASK_DOG_SETUP_THROW_TARGET, -}; - -int ACT_DOG_THROW; -int ACT_DOG_PICKUP; -int ACT_DOG_WAITING; -int ACT_DOG_CATCH; - -int AE_DOG_THROW; -int AE_DOG_PICKUP; -int AE_DOG_CATCH; -int AE_DOG_PICKUP_NOEFFECT; - -ConVar dog_max_wait_time( "dog_max_wait_time", "7" ); -ConVar dog_debug( "dog_debug", "0" ); - -//----------------------------------------------------------------------------- -// Classify - indicates this NPC's place in the -// relationship table. -//----------------------------------------------------------------------------- -Class_T CNPC_Dog::Classify ( void ) -{ - return CLASS_PLAYER_ALLY_VITAL; -} - -bool CNPC_Dog::CreateBehaviors( void ) -{ - AddBehavior( &m_FollowBehavior ); - - return BaseClass::CreateBehaviors(); -} - -Disposition_t CNPC_Dog::IRelationType( CBaseEntity *pTarget ) -{ - if ( NPC_Rollermine_IsRollermine( pTarget ) ) - { - if ( pTarget->HasSpawnFlags( SF_ROLLERMINE_FRIENDLY ) ) - return D_LI; - } - - return BaseClass::IRelationType( pTarget ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Dog::CreateVPhysics( void ) -{ - BaseClass::CreateVPhysics(); - - if ( m_bBoneFollowersActive == true && !m_BoneFollowerManager.GetNumBoneFollowers() ) - { - m_BoneFollowerManager.InitBoneFollowers( this, ARRAYSIZE(pFollowerBoneNames), pFollowerBoneNames ); - } - return true; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Dog::UpdateOnRemove( void ) -{ - m_BoneFollowerManager.DestroyBoneFollowers(); - BaseClass::UpdateOnRemove(); -} - -void CNPC_Dog::GatherConditions( void ) -{ - if ( IsInAScript() ) - { - ClearSenseConditions(); - return; - } - - BaseClass::GatherConditions(); -} - -int CNPC_Dog::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - if ( IsInAScript() ) - return 0; - - return BaseClass::OnTakeDamage_Alive( info ); -} - -//----------------------------------------------------------------------------- -// This function checks if Dog's collision group doesn't match his bone follower's and fixes them up. -//----------------------------------------------------------------------------- -void CNPC_Dog::MantainBoneFollowerCollisionGroups( int iCollisionGroup ) -{ - if ( m_bBoneFollowersActive == false ) - return; - - physfollower_t* pBone = m_BoneFollowerManager.GetBoneFollower( 0 ); - - if ( pBone && pBone->hFollower && pBone->hFollower->GetCollisionGroup() != iCollisionGroup ) - { - for ( int i = 0; i < m_BoneFollowerManager.GetNumBoneFollowers(); i++ ) - { - pBone = m_BoneFollowerManager.GetBoneFollower( i ); - - if ( pBone && pBone->hFollower ) - { - pBone->hFollower->SetCollisionGroup( iCollisionGroup ); - } - } - } -} - -void CNPC_Dog::SetPlayerAvoidState( void ) -{ - bool bIntersectingBoneFollowers = false; - bool bIntersectingNPCBox = false; - - Vector vNothing; - - GetSequenceLinearMotion( GetSequence(), &vNothing ); - bool bIsMoving = ( IsMoving() || ( vNothing != vec3_origin ) ); - - //If we are coming out of a script, check if we are stuck inside the player. - if ( m_bPerformAvoidance || ( ShouldPlayerAvoid() && bIsMoving ) ) - { - trace_t trace; - Vector vMins, vMaxs; - Vector vWorldMins, vWorldMaxs; - Vector vPlayerMins, vPlayerMaxs; - physfollower_t *pBone; - int i; - - CBasePlayer *pLocalPlayer = AI_GetSinglePlayer(); - - if ( pLocalPlayer ) - { - vWorldMins = WorldAlignMins(); - vWorldMaxs = WorldAlignMaxs(); - - vPlayerMins = pLocalPlayer->GetAbsOrigin() + pLocalPlayer->WorldAlignMins(); - vPlayerMaxs = pLocalPlayer->GetAbsOrigin() + pLocalPlayer->WorldAlignMaxs(); - - // check if the player intersects the bounds of any of the bone followers - for ( i = 0; i < m_BoneFollowerManager.GetNumBoneFollowers(); i++ ) - { - pBone = m_BoneFollowerManager.GetBoneFollower( i ); - if ( pBone && pBone->hFollower ) - { - pBone->hFollower->CollisionProp()->WorldSpaceSurroundingBounds( &vMins, &vMaxs ); - if ( IsBoxIntersectingBox( vMins, vMaxs, vPlayerMins, vPlayerMaxs ) ) - { - bIntersectingBoneFollowers = true; - break; - } - } - } - - bIntersectingNPCBox = IsBoxIntersectingBox( GetAbsOrigin() + vWorldMins, GetAbsOrigin() + vWorldMaxs, vPlayerMins, vPlayerMaxs ); - - if ( ai_debug_avoidancebounds.GetBool() ) - { - int iRed = ( bIntersectingNPCBox == true ) ? 255 : 0; - - NDebugOverlay::Box( GetAbsOrigin(), vWorldMins, vWorldMaxs, iRed, 0, 255, 64, 0.1 ); - - // draw the bounds of the bone followers - for ( i = 0; i < m_BoneFollowerManager.GetNumBoneFollowers(); i++ ) - { - pBone = m_BoneFollowerManager.GetBoneFollower( i ); - if ( pBone && pBone->hFollower ) - { - pBone->hFollower->CollisionProp()->WorldSpaceSurroundingBounds( &vMins, &vMaxs ); - iRed = ( IsBoxIntersectingBox( vMins, vMaxs, vPlayerMins, vPlayerMaxs ) ) ? 255 : 0; - - NDebugOverlay::Box( vec3_origin, vMins, vMaxs, iRed, 0, 255, 64, 0.1 ); - } - } - } - } - } - - m_bPlayerAvoidState = ShouldPlayerAvoid(); - m_bPerformAvoidance = bIntersectingNPCBox || bIntersectingBoneFollowers; - - if ( GetCollisionGroup() == COLLISION_GROUP_NPC || GetCollisionGroup() == COLLISION_GROUP_NPC_ACTOR ) - { - if ( bIntersectingNPCBox == true ) - { - SetCollisionGroup( COLLISION_GROUP_NPC_ACTOR ); - } - else - { - SetCollisionGroup( COLLISION_GROUP_NPC ); - } - - if ( bIntersectingBoneFollowers == true ) - { - MantainBoneFollowerCollisionGroups( COLLISION_GROUP_NPC_ACTOR ); - } - else - { - MantainBoneFollowerCollisionGroups( COLLISION_GROUP_NPC ); - } - } -} -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Dog::NPCThink( void ) -{ - BaseClass::NPCThink(); - - if ( m_hPhysicsEnt == NULL ) - { - ClearBeams(); - m_bHasObject = false; - } - - if ( m_bHasObject == true ) - { - RelaxAim(); - PullObject( true ); - } - - - // update follower bones - m_BoneFollowerManager.UpdateBoneFollowers(this); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Dog::Event_Killed( const CTakeDamageInfo &info ) -{ - m_BoneFollowerManager.DestroyBoneFollowers(); - BaseClass::Event_Killed( info ); -} - -//----------------------------------------------------------------------------- -// Spawn -//----------------------------------------------------------------------------- -void CNPC_Dog::Spawn( void ) -{ - m_bBoneFollowersActive = true; - - Precache(); - - BaseClass::Spawn(); - - SetModel( "models/dog.mdl" ); - - SetHullType( HULL_WIDE_HUMAN ); - SetHullSizeNormal(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - SetBloodColor( BLOOD_COLOR_MECH ); - - m_iHealth = 999; - m_flFieldOfView = 0.5;// indicates the width of this NPC's forward view cone ( as a dotproduct result ) - m_NPCState = NPC_STATE_NONE; - - m_takedamage = DAMAGE_NO; - - CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_OPEN_DOORS | bits_CAP_TURN_HEAD | bits_CAP_ANIMATEDFACE ); - CapabilitiesAdd( bits_CAP_FRIENDLY_DMG_IMMUNE ); - - NPCInit(); - - m_iPhysGunAttachment = LookupAttachment( DOG_PHYSGUN_ATTACHMENT_NAME ); - - m_bDoCatchThrowBehavior = false; - m_bDoWaitforObjectBehavior = false; - m_bHasObject = false; - m_bBeamEffects = true; - - m_flThrowArcModifier = 1.0f; - - m_flNextSwat = gpGlobals->curtime; - m_flNextRouteTime = gpGlobals->curtime; -} - - -void CNPC_Dog::PrescheduleThink( void ) -{ - BaseClass::PrescheduleThink(); - - if ( m_hPhysicsEnt ) - { - IPhysicsObject *pPhysObj = m_hPhysicsEnt->VPhysicsGetObject(); - - if ( pPhysObj && pPhysObj->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - { - m_hPhysicsEnt->SetOwnerEntity( NULL ); - } - } - - if ( m_flTimeToCatch < gpGlobals->curtime ) - m_flTimeToCatch = 0.0f; - - - if ( GetIdealActivity() == ACT_IDLE ) - { - if ( m_hPhysicsEnt && m_bHasObject == true ) - { - SetIdealActivity( (Activity)ACT_DOG_WAITING ); - } - } -} - -int CNPC_Dog::SelectSchedule ( void ) -{ - ClearCondition( COND_DOG_LOST_PHYSICS_ENTITY ); - - if ( GetState() == NPC_STATE_SCRIPT || IsInAScript() ) - return BaseClass::SelectSchedule(); - - if ( BehaviorSelectSchedule() ) - return BaseClass::SelectSchedule(); - - if ( m_bDoWaitforObjectBehavior == true ) - { - if ( m_hPhysicsEnt ) - return SCHED_DOG_CATCH_OBJECT; - } - - if ( m_bDoCatchThrowBehavior == true ) - { - if ( m_flTimeToCatch < 0.1 && m_flNextSwat <= gpGlobals->curtime ) - { - return SCHED_DOG_FIND_OBJECT; - } - - if ( m_flTimeToCatch > gpGlobals->curtime && m_hPhysicsEnt ) - return SCHED_DOG_CATCH_OBJECT; - } - else - { - if ( m_hPhysicsEnt ) - { - if ( m_bHasObject == true ) - { - return SCHED_DOG_WAIT_THROW_OBJECT; - } - } - } - - return BaseClass::SelectSchedule(); -} - -void CNPC_Dog::PullObject( bool bMantain ) -{ - if ( m_hPhysicsEnt == NULL ) - { - TaskFail( "Ack! No Phys Object!"); - return; - } - - IPhysicsObject *pPhysObj = m_hPhysicsEnt->VPhysicsGetObject(); - - if ( pPhysObj == NULL ) - { - TaskFail( "Pulling object with no Phys Object?!" ); - return; - } - - if( pPhysObj->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - { - m_bHasObject = false; - ClearBeams(); - TaskFail("Player Grabbed Ball"); - return; - } - - CreateBeams(); - - Vector vGunPos; - GetAttachment( m_iPhysGunAttachment, vGunPos ); - float flDistance = ( vGunPos - m_hPhysicsEnt->WorldSpaceCenter() ).Length(); - - if ( bMantain == false ) - { - if ( flDistance <= DOG_CATCH_DISTANCE ) - { - m_hPhysicsEnt->SetOwnerEntity( this ); - - GetNavigator()->StopMoving(); - - //Fire Output! - m_OnPickup.FireOutput( this, this ); - - m_bHasObject = true; - ClearBeams(); - TaskComplete(); - return; - } - } - - Vector vDir = ( vGunPos - m_hPhysicsEnt->WorldSpaceCenter() ); - - Vector vCurrentVel; - float flCurrentVel; - AngularImpulse vCurrentAI; - - pPhysObj->GetVelocity( &vCurrentVel, &vCurrentAI ); - flCurrentVel = vCurrentVel.Length(); - - VectorNormalize( vCurrentVel ); - VectorNormalize( vDir ); - - float flVelMod = DOG_PULL_VELOCITY_MOD; - - if ( bMantain == true ) - flVelMod *= 2; - - vCurrentVel = vCurrentVel * flCurrentVel * flVelMod; - - vCurrentAI = vCurrentAI * DOG_PULL_ANGULARIMP_MOD; - pPhysObj->SetVelocity( &vCurrentVel, &vCurrentAI ); - - vDir = vDir * flDistance * (DOG_PULL_TO_GUN_VEL_MOD * 2); - - Vector vAngle( 0, 0, 0 ); - pPhysObj->AddVelocity( &vDir, &vAngle ); -} - -//----------------------------------------------------------------------------- -// Precache - precaches all resources this NPC needs -//----------------------------------------------------------------------------- -void CNPC_Dog::Precache( void ) -{ - PrecacheModel( "models/dog.mdl" ); - - PrecacheScriptSound( "Weapon_PhysCannon.Launch" ); - - PrecacheModel( "sprites/orangelight1.vmt" ); - PrecacheModel( "sprites/physcannon_bluelight2.vmt" ); - PrecacheModel( "sprites/glow04_noz.vmt" ); - - BaseClass::Precache(); -} - -void CNPC_Dog::CleanCatchAndThrow( bool bClearTimers ) -{ - if ( m_hPhysicsEnt ) - { - if ( m_bHasObject == true ) - { - IPhysicsObject *pPhysObj = m_hPhysicsEnt->VPhysicsGetObject(); - - m_hPhysicsEnt->SetParent( NULL ); - m_hPhysicsEnt->SetOwnerEntity( NULL ); - - Vector vGunPos; - QAngle angGunAngles; - GetAttachment( m_iPhysGunAttachment, vGunPos, angGunAngles ); - - if ( pPhysObj ) - { - pPhysObj->Wake(); - pPhysObj->RemoveShadowController(); - pPhysObj->SetPosition( vGunPos, angGunAngles, true ); - } - else - { - Warning( "CleanCatchAndThrow: m_hPhysicsEnt->VPhysicsGetObject == NULL!\n" ); - } - - m_hPhysicsEnt->SetMoveType( (MoveType_t)m_iContainerMoveType ); - - if ( pPhysObj ) - { - pPhysObj->RecheckCollisionFilter(); - } - - ClearBeams(); - } - - m_hPhysicsEnt = NULL; - } - - if ( bClearTimers == true ) - { - m_bDoCatchThrowBehavior = false; - m_bDoWaitforObjectBehavior = false; - m_flTimeToCatch = 0.0f; - m_flNextSwat = 0.0f; - - SetCondition( COND_DOG_LOST_PHYSICS_ENTITY ); - } -} - -void CNPC_Dog::InputPlayerPickupObject ( inputdata_t &inputdata ) -{ - if ( m_bDoWaitforObjectBehavior == true ) - { - if ( m_hPhysicsEnt != inputdata.pCaller ) - { - if ( m_hPhysicsEnt != NULL ) - CleanCatchAndThrow( false ); - - //Reset this cause CleanCatchAndThrow clears it. - m_bDoWaitforObjectBehavior = true; - m_hPhysicsEnt = inputdata.pCaller; - } - } - else if ( m_bDoCatchThrowBehavior == true ) - { - if ( m_sObjectName != NULL_STRING ) - { - if ( m_hPhysicsEnt != inputdata.pCaller ) - { - if ( m_hPhysicsEnt != NULL ) - CleanCatchAndThrow( false ); - - //Reset this cause CleanCatchAndThrow clears it. - m_bDoCatchThrowBehavior = true; - m_hPhysicsEnt = inputdata.pCaller; - } - } - } -} - -void CNPC_Dog::InputSetThrowArcModifier( inputdata_t &inputdata ) -{ - m_flThrowArcModifier = inputdata.value.Float(); -} - -void CNPC_Dog::InputSetPickupTarget( inputdata_t &inputdata ) -{ - CleanCatchAndThrow( false ); - FindPhysicsObject( inputdata.value.String() ); -} - -void CNPC_Dog::InputStartWaitAndCatch( inputdata_t &inputdata ) -{ - CleanCatchAndThrow(); - m_bDoWaitforObjectBehavior = true; -} - -void CNPC_Dog::InputStopWaitAndCatch( inputdata_t &inputdata ) -{ - CleanCatchAndThrow(); -} - -void CNPC_Dog::InputStartCatchThrowBehavior( inputdata_t &inputdata ) -{ - CleanCatchAndThrow(); - - m_sObjectName = MAKE_STRING( inputdata.value.String() ); - m_bDoCatchThrowBehavior = true; - - m_flTimeToCatch = 0.0f; - m_flNextSwat = 0.0f; - - FindPhysicsObject( inputdata.value.String() ); -} - -void CNPC_Dog::InputStopCatchThrowBehavior( inputdata_t &inputdata ) -{ - m_bDoCatchThrowBehavior = false; - - m_flTimeToCatch = 0.0f; - m_flNextSwat = 0.0f; - m_sObjectName = NULL_STRING; - - CleanCatchAndThrow(); -} - -void CNPC_Dog::InputSetThrowTarget( inputdata_t &inputdata ) -{ - m_hThrowTarget = gEntList.FindEntityByName( NULL, inputdata.value.String(), NULL, inputdata.pActivator, inputdata.pCaller ); -} - -void CNPC_Dog::SetTurnActivity( void ) -{ - BaseClass::SetTurnActivity(); - - if ( GetIdealActivity() == ACT_IDLE ) - { - if ( m_hPhysicsEnt && m_bHasObject == true ) - SetIdealActivity( (Activity)ACT_DOG_WAITING ); - } -} - -void CNPC_Dog::ThrowObject( const char *pAttachmentName ) -{ - if ( m_hPhysicsEnt ) - { - m_bHasObject = false; - - IPhysicsObject *pPhysObj = m_hPhysicsEnt->VPhysicsGetObject(); - - if ( pPhysObj ) - { - Vector vGunPos; - QAngle angGunAngles; - - AngularImpulse angVelocity = RandomAngularImpulse( -250 , -250 ) / pPhysObj->GetMass(); - - InvalidateBoneCache(); - - int iAttachment = LookupAttachment( pAttachmentName ); - - if ( iAttachment == 0 ) - iAttachment = m_iPhysGunAttachment; - - GetAttachment( iAttachment, vGunPos, angGunAngles ); - - pPhysObj->Wake(); - - if ( pPhysObj->GetShadowController() ) - { - m_hPhysicsEnt->SetParent( NULL ); - m_hPhysicsEnt->SetMoveType( (MoveType_t)m_iContainerMoveType ); - m_hPhysicsEnt->SetOwnerEntity( this ); - - pPhysObj->RemoveShadowController(); - pPhysObj->SetPosition( m_hPhysicsEnt->GetLocalOrigin(), m_hPhysicsEnt->GetLocalAngles(), true ); - - pPhysObj->RecheckCollisionFilter(); - pPhysObj->RecheckContactPoints(); - } - - if ( m_hThrowTarget == NULL ) - m_hThrowTarget = AI_GetSinglePlayer(); - - Vector vThrowDirection; - - if ( m_hThrowTarget ) - { - Vector vThrowOrigin = m_hThrowTarget->GetAbsOrigin(); - - if ( m_hThrowTarget->IsPlayer() ) - vThrowOrigin = vThrowOrigin + Vector( random->RandomFloat( -128, 128 ), random->RandomFloat( -128, 128 ), 0 ); - - Vector vecToss = VecCheckToss( this, vGunPos, vThrowOrigin, m_flThrowArcModifier, 1.0f, true ); - - if( vecToss == vec3_origin ) - { - // Fix up an impossible throw so dog will at least toss the box in the target's general direction instead of dropping it. - // Also toss it up in the air so it will fall down and break. (Just throw the box up at a 45 degree angle) - Vector forward, up; - GetVectors( &forward, NULL, &up ); - - vecToss = forward + up; - VectorNormalize( vecToss ); - - vecToss *= pPhysObj->GetMass() * 30.0f; - } - - vThrowDirection = vecToss + ( m_hThrowTarget->GetSmoothedVelocity() / 2 ); - - Vector vLinearDrag; - - Vector unitVel = vThrowDirection; - VectorNormalize( unitVel ); - - float flTest = 1000 / vThrowDirection.Length(); - - float flDrag = pPhysObj->CalculateLinearDrag( vThrowDirection ); - vThrowDirection = vThrowDirection + ( unitVel * ( flDrag * flDrag ) ) / flTest; - - pPhysObj->SetVelocity( &vThrowDirection, &angVelocity ); - - m_flTimeToCatch = gpGlobals->curtime + dog_max_wait_time.GetFloat(); - - //Don't start pulling until the object is away from me. - //We base the time on the throw velocity. - m_flTimeToPull = gpGlobals->curtime + ( 1000 / vThrowDirection.Length() ); - } - - //Fire Output! - m_OnThrow.FireOutput( this, this ); - - ClearBeams(); - - if ( m_bBeamEffects == true ) - { - EmitSound( "Weapon_PhysCannon.Launch" ); - - CBeam *pBeam = CBeam::BeamCreate( "sprites/orangelight1.vmt", 1.8 ); - - if ( pBeam != NULL ) - { - pBeam->PointEntInit( m_hPhysicsEnt->WorldSpaceCenter(), this ); - pBeam->SetEndAttachment( m_iPhysGunAttachment ); - pBeam->SetWidth( 6.4 ); - pBeam->SetEndWidth( 12.8 ); - pBeam->SetBrightness( 255 ); - pBeam->SetColor( 255, 255, 255 ); - pBeam->LiveForTime( 0.2f ); - pBeam->RelinkBeam(); - pBeam->SetNoise( 2 ); - } - - Vector shotDir = ( m_hPhysicsEnt->WorldSpaceCenter() - vGunPos ); - VectorNormalize( shotDir ); - - CPVSFilter filter( m_hPhysicsEnt->WorldSpaceCenter() ); - te->GaussExplosion( filter, 0.0f, m_hPhysicsEnt->WorldSpaceCenter() - ( shotDir * 4.0f ), RandomVector(-1.0f, 1.0f), 0 ); - } - } - } -} - -void CNPC_Dog::PickupOrCatchObject( const char *pAttachmentName ) -{ - if ( m_hPhysicsEnt ) - { - InvalidateBoneCache(); - - int iAttachment = LookupAttachment( pAttachmentName ); - - if ( iAttachment == 0 ) - iAttachment = m_iPhysGunAttachment; - - // Move physobject to shadow - IPhysicsObject *pPhysicsObject = m_hPhysicsEnt->VPhysicsGetObject(); - if ( pPhysicsObject ) - { - pPhysicsObject->SetShadow( 1e4, 1e4, false, false ); - pPhysicsObject->UpdateShadow( GetAbsOrigin(), GetAbsAngles(), false, 0 ); - } - - m_iContainerMoveType = m_hPhysicsEnt->GetMoveType(); - m_hPhysicsEnt->SetMoveType( MOVETYPE_NONE ); - - m_hPhysicsEnt->SetParent( this, iAttachment ); - - m_hPhysicsEnt->SetLocalOrigin( vec3_origin ); - m_hPhysicsEnt->SetLocalAngles( vec3_angle ); - - m_hPhysicsEnt->SetGroundEntity( NULL ); - - - if ( m_hPhysicsEnt->GetOwnerEntity() == NULL ) - m_hPhysicsEnt->SetOwnerEntity( this ); - - if ( pPhysicsObject ) - pPhysicsObject->RecheckCollisionFilter(); - - m_bHasObject = true; - - //Fire Output! - m_OnPickup.FireOutput( this, this ); - } -} - -//----------------------------------------------------------------------------- -// HandleAnimEvent - catches the NPC-specific messages -// that occur when tagged animation frames are played. -//----------------------------------------------------------------------------- -void CNPC_Dog::HandleAnimEvent( animevent_t *pEvent ) -{ - if ( pEvent->event == AE_DOG_THROW ) - { - ThrowObject( pEvent->options ); - return; - } - - if ( pEvent->event == AE_DOG_PICKUP || pEvent->event == AE_DOG_CATCH || pEvent->event == AE_DOG_PICKUP_NOEFFECT ) - { - if ( pEvent->event == AE_DOG_PICKUP_NOEFFECT ) - m_bBeamEffects = false; - else - m_bBeamEffects = true; - - PickupOrCatchObject( pEvent->options ); - return; - } - - BaseClass::HandleAnimEvent( pEvent ); -} - -void CNPC_Dog::ClearBeams( void ) -{ - ClearSprites(); - - // Turn off sprites - for ( int i = 0; i < EFFECT_COUNT; i++ ) - { - if ( m_hBeams[i] != NULL ) - { - UTIL_Remove( m_hBeams[i] ); - m_hBeams[i] = NULL; - } - } -} - -void CNPC_Dog::ClearSprites( void ) -{ - // Turn off sprites - for ( int i = 0; i < EFFECT_COUNT; i++ ) - { - if ( m_hGlowSprites[i] != NULL ) - { - UTIL_Remove( m_hGlowSprites[i] ); - m_hGlowSprites[i] = NULL; - } - } -} - -void CNPC_Dog::CreateSprites( void ) -{ - //Create the glow sprites - for ( int i = 0; i < EFFECT_COUNT; i++ ) - { - if ( m_hGlowSprites[i] ) - continue; - - const char *attachNames[] = - { - "physgun", - "thumb", - "pinky", - "index", - }; - - m_hGlowSprites[i] = CSprite::SpriteCreate( "sprites/glow04_noz.vmt", GetAbsOrigin(), false ); - - m_hGlowSprites[i]->SetAttachment( this, LookupAttachment( attachNames[i] ) ); - m_hGlowSprites[i]->SetTransparency( kRenderGlow, 255, 128, 0, 64, kRenderFxNoDissipation ); - m_hGlowSprites[i]->SetBrightness( 255, 0.2f ); - m_hGlowSprites[i]->SetScale( 0.55f, 0.2f ); - } -} - -void CNPC_Dog::CreateBeams( void ) -{ - if ( m_bBeamEffects == false ) - { - ClearBeams(); - return; - } - - CreateSprites(); - - for ( int i = 0; i < EFFECT_COUNT; i++ ) - { - if ( m_hBeams[i] ) - continue; - - const char *attachNames[] = - { - "physgun", - "thumb", - "pinky", - "index", - }; - - m_hBeams[i] = CBeam::BeamCreate( "sprites/physcannon_bluelight2.vmt", 5.0 ); - - m_hBeams[i]->EntsInit( m_hPhysicsEnt, this ); - m_hBeams[i]->SetEndAttachment( LookupAttachment( attachNames[i] ) ); - m_hBeams[i]->SetBrightness( 255 ); - m_hBeams[i]->SetColor( 255, 255, 255 ); - m_hBeams[i]->SetNoise( 5.5 ); - m_hBeams[i]->SetRenderMode( kRenderTransAdd ); - } - -} - -bool CNPC_Dog::FindPhysicsObject( const char *pPickupName, CBaseEntity *pIgnore ) -{ - CBaseEntity *pEnt = NULL; - CBaseEntity *pNearest = NULL; - float flDist; - IPhysicsObject *pPhysObj = NULL; - float flNearestDist = 99999; - - if ( pPickupName != NULL && strlen( pPickupName ) > 0 ) - { - pEnt = gEntList.FindEntityByName( NULL, pPickupName ); - - if ( m_hUnreachableObjects.Find( pEnt ) == -1 ) - { - m_bHasObject = false; - m_hPhysicsEnt = pEnt; - return true; - } - } - - while ( ( pEnt = gEntList.FindEntityByClassname( pEnt, "prop_physics" ) ) != NULL ) - { - //We don't want this one. - if ( pEnt == pIgnore ) - continue; - - if ( m_hUnreachableObjects.Find( pEnt ) != -1 ) - continue; - - pPhysObj = pEnt->VPhysicsGetObject(); - - if( pPhysObj == NULL ) - continue; - - if ( pPhysObj->GetMass() > DOG_MAX_THROW_MASS ) - continue; - - Vector center = pEnt->WorldSpaceCenter(); - flDist = UTIL_DistApprox2D( GetAbsOrigin(), center ); - - vcollide_t *pCollide = modelinfo->GetVCollide( pEnt->GetModelIndex() ); - - if ( pCollide == NULL ) - continue; - - if ( pPhysObj->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - continue; - - if ( pPhysObj->IsMoveable() == false ) - continue; - - if ( pEnt->GetCollisionGroup() == COLLISION_GROUP_DEBRIS || - pEnt->GetCollisionGroup() == COLLISION_GROUP_INTERACTIVE_DEBRIS ) - continue; - - if ( center.z > EyePosition().z ) - continue; - - if ( flDist >= flNearestDist ) - continue; - - if ( FVisible( pEnt ) == false ) - continue; - - pNearest = pEnt; - flNearestDist = flDist; - } - - m_bHasObject = false; - m_hPhysicsEnt = pNearest; - - if ( dog_debug.GetBool() == true ) - { - if ( pNearest ) - NDebugOverlay::Box( pNearest->WorldSpaceCenter(), pNearest->CollisionProp()->OBBMins(), pNearest->CollisionProp()->OBBMaxs(), 255, 0, 255, true, 3 ); - } - - if( m_hPhysicsEnt == NULL ) - { - return false; - } - else - { - return true; - } -} - -//----------------------------------------------------------------------------- -// Can me enemy see me? -//----------------------------------------------------------------------------- -bool CNPC_Dog::CanTargetSeeMe( void ) -{ - CBaseEntity *pEntity = m_hThrowTarget; - - if ( pEntity ) - { - if ( pEntity->IsPlayer() == false ) - return true; - - CBasePlayer *pPlayer = dynamic_cast( pEntity ); - - if ( pPlayer ) - { - if ( m_hPhysicsEnt ) - { - if ( pPlayer->FVisible( m_hPhysicsEnt ) == false ) - return false; - } - - if ( pPlayer->FInViewCone( this ) ) - { - return true; - } - } - } - - return false; -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Dog::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - - case TASK_DOG_PICKUP_ITEM: - { - PullObject( false ); - } - break; - - case TASK_DOG_GET_PATH_TO_PHYSOBJ: - { - //Check this cause our object might have been deleted. - if ( m_hPhysicsEnt == NULL ) - FindPhysicsObject( NULL ); - - //And if we still can't find anything, then just go away. - if ( m_hPhysicsEnt == NULL ) - { - TaskFail( "Can't find an object I like!" ); - return; - } - - IPhysicsObject *pPhysicsObject = m_hPhysicsEnt->VPhysicsGetObject(); - - Vector vecGoalPos; - Vector vecDir; - - vecDir = GetLocalOrigin() - m_hPhysicsEnt->WorldSpaceCenter(); - VectorNormalize(vecDir); - vecDir.z = 0; - - if ( m_hPhysicsEnt->GetOwnerEntity() == NULL ) - m_hPhysicsEnt->SetOwnerEntity( this ); - - if ( pPhysicsObject ) - pPhysicsObject->RecheckCollisionFilter(); - - vecGoalPos = m_hPhysicsEnt->WorldSpaceCenter() + (vecDir * DOG_PHYSOBJ_MOVE_TO_DIST ); - - bool bBuiltRoute = false; - - //If I'm near my goal, then just walk to it. - Activity aActivity = ACT_RUN; - - if ( ( vecGoalPos - GetLocalOrigin() ).Length() <= 128 ) - aActivity = ACT_WALK; - - bBuiltRoute = GetNavigator()->SetGoal( AI_NavGoal_t( vecGoalPos, aActivity ), AIN_NO_PATH_TASK_FAIL ); - - if ( bBuiltRoute == true ) - TaskComplete(); - else - { - m_flTimeToCatch = gpGlobals->curtime + 0.1; - m_flNextRouteTime = gpGlobals->curtime + 0.3; - m_flNextSwat = gpGlobals->curtime + 0.1; - - if ( m_hUnreachableObjects.Find( m_hPhysicsEnt ) == -1 ) - m_hUnreachableObjects.AddToTail( m_hPhysicsEnt ); - - m_hPhysicsEnt = NULL; - - GetNavigator()->ClearGoal(); - } - } - break; - - case TASK_WAIT: - { - if ( IsWaitFinished() ) - { - TaskComplete(); - } - - if ( m_hPhysicsEnt ) - { - if ( m_bHasObject == false ) - { - GetMotor()->SetIdealYawToTarget( m_hPhysicsEnt->GetAbsOrigin() ); - GetMotor()->UpdateYaw(); - } - } - - break; - } - - case TASK_DOG_LAUNCH_ITEM: - if( IsActivityFinished() ) - { - if ( m_hPhysicsEnt ) - { - m_hPhysicsEnt->SetOwnerEntity( NULL ); - } - - TaskComplete(); - } - break; - - case TASK_DOG_WAIT_FOR_TARGET_TO_FACE: - { - if ( CanTargetSeeMe() ) - TaskComplete(); - } - break; - - case TASK_WAIT_FOR_MOVEMENT: - { - if ( GetState() == NPC_STATE_SCRIPT || IsInAScript() ) - { - BaseClass::RunTask( pTask ); - return; - } - - if ( m_hPhysicsEnt != NULL ) - { - IPhysicsObject *pPhysObj = m_hPhysicsEnt->VPhysicsGetObject(); - - if ( !pPhysObj ) - { - Warning( "npc_dog TASK_WAIT_FOR_MOVEMENT with NULL m_hPhysicsEnt->VPhysicsGetObject\n" ); - } - - if ( pPhysObj && pPhysObj->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - TaskFail( "Player picked it up!" ); - - //If the object is moving then my old goal might not be valid - //cancel the schedule and make it restart again in a bit. - if ( pPhysObj && pPhysObj->IsAsleep() == false && GetNavigator()->IsGoalActive() == false ) - { - Vector vecGoalPos; - Vector vecDir; - - vecDir = GetLocalOrigin() - m_hPhysicsEnt->WorldSpaceCenter(); - VectorNormalize(vecDir); - vecDir.z = 0; - - vecGoalPos = m_hPhysicsEnt->WorldSpaceCenter() + (vecDir * DOG_PHYSOBJ_MOVE_TO_DIST ); - - GetNavigator()->ClearGoal(); - - float flDistance = (vecGoalPos - GetLocalOrigin()).Length(); - - //If I'm near my goal, then just walk to it. - Activity aActivity = ACT_RUN; - - if ( ( vecGoalPos - GetLocalOrigin() ).Length() <= 128 ) - aActivity = ACT_WALK; - - GetNavigator()->SetGoal( AI_NavGoal_t( vecGoalPos, aActivity ), AIN_NO_PATH_TASK_FAIL ); - - if ( flDistance <= DOG_PHYSOBJ_MOVE_TO_DIST ) - { - TaskComplete(); - GetNavigator()->StopMoving(); - } - } - } - - BaseClass::RunTask( pTask ); - } - break; - - case TASK_DOG_WAIT_FOR_OBJECT: - { - if ( m_hPhysicsEnt != NULL ) - { - if ( FVisible( m_hPhysicsEnt ) == false ) - { - m_flTimeToCatch = 0.0f; - ClearBeams(); - TaskFail( "Lost sight of the object!" ); - m_hPhysicsEnt->SetOwnerEntity( NULL ); - return; - } - - m_hPhysicsEnt->SetOwnerEntity( this ); - - Vector vForward; - AngleVectors( GetAbsAngles(), &vForward ); - - - Vector vGunPos; - GetAttachment( m_iPhysGunAttachment, vGunPos ); - - Vector vToObject = m_hPhysicsEnt->WorldSpaceCenter() - vGunPos; - float flDistance = vToObject.Length(); - - VectorNormalize( vToObject ); - - SetAim( m_hPhysicsEnt->WorldSpaceCenter() - GetAbsOrigin() ); - - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - - float flDistanceToPlayer = flDistance; - - if ( pPlayer ) - { - flDistanceToPlayer = (pPlayer->GetAbsOrigin() - m_hPhysicsEnt->WorldSpaceCenter()).Length(); - } - - IPhysicsObject *pPhysObj = m_hPhysicsEnt->VPhysicsGetObject(); - if ( !pPhysObj ) - { - Warning( "npc_dog: TASK_DOG_WAIT_FOR_OBJECT with m_hPhysicsEnt->VPhysicsGetObject == NULL\n" ); - } - - if ( pPhysObj && !( pPhysObj->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) && flDistanceToPlayer > ( flDistance * 2 ) ) - { - if ( m_flTimeToPull <= gpGlobals->curtime ) - { - Vector vCurrentVel; - float flCurrentVel; - AngularImpulse vCurrentAI; - - pPhysObj->GetVelocity( &vCurrentVel, &vCurrentAI ); - - flCurrentVel = vCurrentVel.Length(); - VectorNormalize( vCurrentVel ); - - if ( pPhysObj && flDistance <= DOG_PULL_DISTANCE ) - { - Vector vDir = ( vGunPos - m_hPhysicsEnt->WorldSpaceCenter() ); - - VectorNormalize( vDir ); - - vCurrentVel = vCurrentVel * ( flCurrentVel * DOG_PULL_VELOCITY_MOD ); - - vCurrentAI = vCurrentAI * DOG_PULL_ANGULARIMP_MOD; - pPhysObj->SetVelocity( &vCurrentVel, &vCurrentAI ); - - vDir = vDir * flDistance * DOG_PULL_TO_GUN_VEL_MOD; - - Vector vAngle( 0, 0, 0 ); - pPhysObj->AddVelocity( &vDir, &vAngle ); - - CreateBeams(); - } - - float flDot = DotProduct( vCurrentVel, vForward ); - - if ( flDistance >= DOG_PULL_DISTANCE && flDistance <= ( DOG_PULL_DISTANCE * 2 ) && flDot > -0.3 ) - { - if ( pPhysObj->IsAsleep() == false && !( pPhysObj->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) ) - { - Vector vecGoalPos; - Vector vecDir; - - vecDir = GetLocalOrigin() - m_hPhysicsEnt->WorldSpaceCenter(); - VectorNormalize(vecDir); - vecDir.z = 0; - - vecGoalPos = m_hPhysicsEnt->WorldSpaceCenter() + (vecDir * DOG_PHYSOBJ_MOVE_TO_DIST ); - - GetNavigator()->ClearGoal(); - - //If I'm near my goal, then just walk to it. - Activity aActivity = ACT_RUN; - - if ( ( vecGoalPos - GetLocalOrigin() ).Length() <= 128 ) - aActivity = ACT_WALK; - - GetNavigator()->SetGoal( AI_NavGoal_t( vecGoalPos, aActivity ), AIN_NO_PATH_TASK_FAIL ); - } - } - } - } - - - float flDirDot = DotProduct( vToObject, vForward ); - - if ( flDirDot < 0.2 ) - { - GetMotor()->SetIdealYawToTarget( m_hPhysicsEnt->GetAbsOrigin() ); - GetMotor()->UpdateYaw(); - } - - if ( m_flTimeToCatch < gpGlobals->curtime && m_bDoWaitforObjectBehavior == false ) - { - m_hPhysicsEnt->SetOwnerEntity( NULL ); - m_flTimeToCatch = 0.0f; - ClearBeams(); - TaskFail( "Done waiting!" ); - } - else if ( pPhysObj && ( flDistance <= DOG_CATCH_DISTANCE && !( pPhysObj->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) ) ) - { - AngularImpulse vZero( 0, 0, 0 ); - pPhysObj->SetVelocity( &vec3_origin, &vZero ); - - GetNavigator()->StopMoving(); - - //Fire Output! - m_OnCatch.FireOutput( this, this ); - m_bHasObject = true; - ClearBeams(); - TaskComplete(); - } - } - else - { - GetNavigator()->StopMoving(); - - ClearBeams(); - TaskFail("No Physics Object!"); - } - - } - break; - - case TASK_DOG_CATCH_OBJECT: - if( IsActivityFinished() ) - { - m_flTimeToCatch = 0.0f; - TaskComplete(); - } - break; - default: - BaseClass::RunTask( pTask ); - break; - } -} - -void CNPC_Dog::SetupThrowTarget( void ) -{ - if ( m_hThrowTarget == NULL ) - { - m_hThrowTarget = AI_GetSinglePlayer(); - } - - SetTarget( m_hThrowTarget ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Dog::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - - case TASK_DOG_SETUP_THROW_TARGET: - { - SetupThrowTarget(); - TaskComplete(); - } - break; - case TASK_DOG_GET_PATH_TO_PHYSOBJ: - { - FindPhysicsObject( STRING( m_sObjectName ) ); - - if ( m_hPhysicsEnt == NULL ) - { - FindPhysicsObject( NULL ); - return; - } - - IPhysicsObject *pPhysicsObject = m_hPhysicsEnt->VPhysicsGetObject(); - - Vector vecGoalPos; - Vector vecDir; - - vecDir = GetLocalOrigin() - m_hPhysicsEnt->WorldSpaceCenter(); - VectorNormalize(vecDir); - vecDir.z = 0; - - if ( m_hPhysicsEnt->GetOwnerEntity() == NULL ) - m_hPhysicsEnt->SetOwnerEntity( this ); - - if ( pPhysicsObject ) - pPhysicsObject->RecheckCollisionFilter(); - - vecGoalPos = m_hPhysicsEnt->WorldSpaceCenter() + (vecDir * DOG_PHYSOBJ_MOVE_TO_DIST ); - - //If I'm near my goal, then just walk to it. - Activity aActivity = ACT_RUN; - - if ( ( vecGoalPos - GetLocalOrigin() ).Length() <= 128 ) - aActivity = ACT_WALK; - - if ( GetNavigator()->SetGoal( AI_NavGoal_t( vecGoalPos, aActivity ), AIN_NO_PATH_TASK_FAIL ) == false ) - { - if ( m_hUnreachableObjects.Find( m_hPhysicsEnt ) == -1 ) - m_hUnreachableObjects.AddToTail( m_hPhysicsEnt ); - - FindPhysicsObject( NULL, m_hPhysicsEnt ); - - m_flTimeToCatch = gpGlobals->curtime + 0.1; - m_flNextRouteTime = gpGlobals->curtime + 0.3; - m_flNextSwat = gpGlobals->curtime + 0.1; - - GetNavigator()->ClearGoal(); - } - else - { - TaskComplete(); - } - } - break; - - case TASK_DOG_FACE_OBJECT: - { - if( m_hPhysicsEnt == NULL ) - { - // Physics Object is gone! Probably was an explosive - // or something else broke it. - TaskFail("Physics ent NULL"); - return; - } - - Vector vecDir; - - vecDir = m_hPhysicsEnt->WorldSpaceCenter() - GetLocalOrigin(); - VectorNormalize(vecDir); - - GetMotor()->SetIdealYaw( UTIL_VecToYaw( vecDir ) ); - TaskComplete(); - } - break; - - case TASK_DOG_PICKUP_ITEM: - { - if( m_hPhysicsEnt == NULL ) - { - // Physics Object is gone! Probably was an explosive - // or something else broke it. - TaskFail("Physics ent NULL"); - return; - } - else - { - SetIdealActivity( (Activity)ACT_DOG_PICKUP ); - } - } - - break; - - case TASK_DOG_LAUNCH_ITEM: - { - if( m_hPhysicsEnt == NULL ) - { - // Physics Object is gone! Probably was an explosive - // or something else broke it. - TaskFail("Physics ent NULL"); - return; - } - else - { - if ( m_hPhysicsEnt == NULL || m_bHasObject == false ) - { - TaskFail( "Don't have the item!" ); - return; - } - - SetIdealActivity( (Activity)ACT_DOG_THROW ); - } - } - - break; - - case TASK_DOG_WAIT_FOR_TARGET_TO_FACE: - { - if ( CanTargetSeeMe() ) - TaskComplete(); - } - break; - - case TASK_DOG_WAIT_FOR_OBJECT: - { - SetIdealActivity( (Activity)ACT_DOG_WAITING ); - } - break; - - case TASK_DOG_CATCH_OBJECT: - { - SetIdealActivity( (Activity)ACT_DOG_CATCH ); - } - break; - - case TASK_DOG_DELAY_SWAT: - m_flNextSwat = gpGlobals->curtime + pTask->flTaskData; - - if ( m_hThrowTarget == NULL ) - m_hThrowTarget = AI_GetSinglePlayer(); - - TaskComplete(); - break; - - default: - BaseClass::StartTask( pTask ); - } -} - -void CNPC_Dog::InputTurnBoneFollowersOff( inputdata_t &inputdata ) -{ - if ( m_bBoneFollowersActive ) - { - m_bBoneFollowersActive = false; - m_BoneFollowerManager.DestroyBoneFollowers(); - } - -} - -void CNPC_Dog::InputTurnBoneFollowersOn( inputdata_t &inputdata ) -{ - if ( !m_bBoneFollowersActive ) - { - m_bBoneFollowersActive = true; - m_BoneFollowerManager.InitBoneFollowers( this, ARRAYSIZE(pFollowerBoneNames), pFollowerBoneNames ); - } -} - -AI_BEGIN_CUSTOM_NPC( npc_dog, CNPC_Dog ) - - DECLARE_USES_SCHEDULE_PROVIDER( CAI_FollowBehavior ) - - DECLARE_ACTIVITY( ACT_DOG_THROW ) - DECLARE_ACTIVITY( ACT_DOG_PICKUP ) - DECLARE_ACTIVITY( ACT_DOG_WAITING ) - DECLARE_ACTIVITY( ACT_DOG_CATCH ) - - DECLARE_CONDITION( COND_DOG_LOST_PHYSICS_ENTITY ) - - DECLARE_TASK( TASK_DOG_DELAY_SWAT ) - DECLARE_TASK( TASK_DOG_GET_PATH_TO_PHYSOBJ ) - DECLARE_TASK( TASK_DOG_LAUNCH_ITEM ) - DECLARE_TASK( TASK_DOG_PICKUP_ITEM ) - DECLARE_TASK( TASK_DOG_FACE_OBJECT ) - DECLARE_TASK( TASK_DOG_WAIT_FOR_OBJECT ) - DECLARE_TASK( TASK_DOG_CATCH_OBJECT ) - - DECLARE_TASK( TASK_DOG_WAIT_FOR_TARGET_TO_FACE ) - DECLARE_TASK( TASK_DOG_SETUP_THROW_TARGET ) - - DECLARE_ANIMEVENT( AE_DOG_THROW ) - DECLARE_ANIMEVENT( AE_DOG_PICKUP ) - DECLARE_ANIMEVENT( AE_DOG_CATCH ) - DECLARE_ANIMEVENT( AE_DOG_PICKUP_NOEFFECT ) - - - DEFINE_SCHEDULE - ( - SCHED_DOG_FIND_OBJECT, - - " Tasks" - " TASK_DOG_DELAY_SWAT 3" - " TASK_DOG_GET_PATH_TO_PHYSOBJ 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_DOG_FACE_OBJECT 0" - " TASK_FACE_IDEAL 0" - " TASK_DOG_PICKUP_ITEM 0" - " TASK_DOG_SETUP_THROW_TARGET 0" - " TASK_FACE_TARGET 0.5" - " TASK_DOG_WAIT_FOR_TARGET_TO_FACE 0" - " TASK_DOG_LAUNCH_ITEM 0" - "" - " Interrupts" - " COND_DOG_LOST_PHYSICS_ENTITY" - ) - - DEFINE_SCHEDULE - ( - SCHED_DOG_WAIT_THROW_OBJECT, - " Tasks" - " TASK_DOG_SETUP_THROW_TARGET 0" - " TASK_FACE_TARGET 0.5" - " TASK_DOG_WAIT_FOR_TARGET_TO_FACE 0" - " TASK_DOG_LAUNCH_ITEM 0" - "" - " Interrupts" - " COND_DOG_LOST_PHYSICS_ENTITY" - ) - - DEFINE_SCHEDULE - ( - SCHED_DOG_CATCH_OBJECT, - - " Tasks" - " TASK_DOG_WAIT_FOR_OBJECT 0" - " TASK_DOG_CATCH_OBJECT 0" - " TASK_FACE_PLAYER 0.5" - " TASK_DOG_WAIT_FOR_TARGET_TO_FACE 0" - " TASK_DOG_LAUNCH_ITEM 0" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_IDLE_STAND" - "" - " Interrupts" - " COND_DOG_LOST_PHYSICS_ENTITY" - ) - -AI_END_CUSTOM_NPC() diff --git a/game/server/hl2/npc_eli.cpp b/game/server/hl2/npc_eli.cpp deleted file mode 100644 index 6a67507c2..000000000 --- a/game/server/hl2/npc_eli.cpp +++ /dev/null @@ -1,163 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Dr. Eli Vance, earths last great hope, single-handedly fighting -// off both an evil alien invasion, as well as trying to stop -// that idiot lab assistant from putting the moves on his daughter. -//=============================================================================// - - -//----------------------------------------------------------------------------- -// Generic NPC - purely for scripted sequence work. -//----------------------------------------------------------------------------- -#include "cbase.h" -#include "npcevent.h" -#include "ai_basenpc.h" -#include "ai_hull.h" -#include "ai_baseactor.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// NPC's Anim Events Go Here -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CNPC_Eli : public CAI_BaseActor -{ -public: - DECLARE_CLASS( CNPC_Eli, CAI_BaseActor ); - - void Spawn( void ); - void Precache( void ); - Class_T Classify ( void ); - void HandleAnimEvent( animevent_t *pEvent ); - int GetSoundInterests( void ); - void SetupWithoutParent( void ); - void PrescheduleThink( void ); -}; - -LINK_ENTITY_TO_CLASS( npc_eli, CNPC_Eli ); - -//----------------------------------------------------------------------------- -// Classify - indicates this NPC's place in the -// relationship table. -//----------------------------------------------------------------------------- -Class_T CNPC_Eli::Classify ( void ) -{ - return CLASS_PLAYER_ALLY_VITAL; -} - - - -//----------------------------------------------------------------------------- -// HandleAnimEvent - catches the NPC-specific messages -// that occur when tagged animation frames are played. -//----------------------------------------------------------------------------- -void CNPC_Eli::HandleAnimEvent( animevent_t *pEvent ) -{ - switch( pEvent->event ) - { - case 1: - default: - BaseClass::HandleAnimEvent( pEvent ); - break; - } -} - -//----------------------------------------------------------------------------- -// GetSoundInterests - generic NPC can't hear. -//----------------------------------------------------------------------------- -int CNPC_Eli::GetSoundInterests ( void ) -{ - return 0; -} - -//----------------------------------------------------------------------------- -// Spawn -//----------------------------------------------------------------------------- -void CNPC_Eli::Spawn() -{ - // Eli is allowed to use multiple models, because he appears in the pod. - // He defaults to his normal model. - const char *szModel = (char *)STRING( GetModelName() ); - if (!szModel || !*szModel) - { - szModel = "models/eli.mdl"; - SetModelName( AllocPooledString(szModel) ); - } - - Precache(); - SetModel( szModel ); - - BaseClass::Spawn(); - - SetHullType(HULL_HUMAN); - SetHullSizeNormal(); - - // If Eli has a parent, he's currently inside a pod. Prevent him from moving. - if ( GetMoveParent() ) - { - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_NONE ); - - CapabilitiesAdd( bits_CAP_ANIMATEDFACE | bits_CAP_TURN_HEAD ); - CapabilitiesAdd( bits_CAP_FRIENDLY_DMG_IMMUNE ); - } - else - { - SetupWithoutParent(); - } - - AddEFlags( EFL_NO_DISSOLVE | EFL_NO_MEGAPHYSCANNON_RAGDOLL | EFL_NO_PHYSCANNON_INTERACTION ); - SetBloodColor( BLOOD_COLOR_RED ); - m_iHealth = 8; - m_flFieldOfView = 0.5;// indicates the width of this NPC's forward view cone ( as a dotproduct result ) - m_NPCState = NPC_STATE_NONE; - - NPCInit(); -} - -//----------------------------------------------------------------------------- -// Precache - precaches all resources this NPC needs -//----------------------------------------------------------------------------- -void CNPC_Eli::Precache() -{ - PrecacheModel( STRING( GetModelName() ) ); - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Eli::SetupWithoutParent( void ) -{ - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - - CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_OPEN_DOORS | bits_CAP_ANIMATEDFACE | bits_CAP_TURN_HEAD ); - CapabilitiesAdd( bits_CAP_FRIENDLY_DMG_IMMUNE ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Eli::PrescheduleThink( void ) -{ - BaseClass::PrescheduleThink(); - - // Figure out if Eli has just been removed from his parent - if ( GetMoveType() == MOVETYPE_NONE && !GetMoveParent() ) - { - SetupWithoutParent(); - SetupVPhysicsHull(); - } -} - -//----------------------------------------------------------------------------- -// AI Schedules Specific to this NPC -//----------------------------------------------------------------------------- diff --git a/game/server/hl2/npc_enemyfinder.cpp b/game/server/hl2/npc_enemyfinder.cpp deleted file mode 100644 index 5fa823eec..000000000 --- a/game/server/hl2/npc_enemyfinder.cpp +++ /dev/null @@ -1,774 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Bullseyes act as targets for other NPC's to attack and to trigger -// events -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "basecombatcharacter.h" -#include "ai_basenpc.h" -#include "decals.h" -#include "IEffects.h" -#include "ai_squad.h" -#include "ai_utils.h" -#include "ai_senses.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SF_ENEMY_FINDER_CHECK_VIS (1 << 16) -#define SF_ENEMY_FINDER_APC_VIS (1 << 17) -#define SF_ENEMY_FINDER_SHORT_MEMORY (1 << 18) -#define SF_ENEMY_FINDER_ENEMY_ALLOWED (1 << 19) - -ConVar ai_debug_enemyfinders( "ai_debug_enemyfinders", "0" ); - - -class CNPC_EnemyFinder : public CAI_BaseNPC -{ -public: - DECLARE_CLASS( CNPC_EnemyFinder, CAI_BaseNPC ); - - CNPC_EnemyFinder() - { - m_PlayerFreePass.SetOuter( this ); - } - - - void Precache( void ); - void Spawn( void ); - void StartNPC ( void ); - void PrescheduleThink(); - bool ShouldAlwaysThink(); - void UpdateEfficiency( bool bInPVS ) { SetEfficiency( ( GetSleepState() != AISS_AWAKE ) ? AIE_DORMANT : AIE_NORMAL ); SetMoveEfficiency( AIME_NORMAL ); } - void GatherConditions( void ); - bool ShouldChooseNewEnemy(); - bool IsValidEnemy( CBaseEntity *pTarget ); - bool CanBeAnEnemyOf( CBaseEntity *pEnemy ) { return HasSpawnFlags( SF_ENEMY_FINDER_ENEMY_ALLOWED ); } - bool FVisible( CBaseEntity *pEntity, int traceMask, CBaseEntity **ppBlocker ); - Class_T Classify( void ); - bool CanBeSeenBy( CAI_BaseNPC *pNPC ) { return CanBeAnEnemyOf( pNPC ); } // allows entities to be 'invisible' to NPC senses. - - virtual int SelectSchedule( void ); - virtual void DrawDebugGeometryOverlays( void ); - - // Input handlers. - void InputTurnOn( inputdata_t &inputdata ); - void InputTurnOff( inputdata_t &inputdata ); - - virtual void Wake( bool bFireOutput = true ); - -private: - int m_nStartOn; - float m_flMinSearchDist; - float m_flMaxSearchDist; - CAI_FreePass m_PlayerFreePass; - CSimpleSimTimer m_ChooseEnemyTimer; - - bool m_bEnemyStatus; - - COutputEvent m_OnLostEnemies; - COutputEvent m_OnAcquireEnemies; - - DECLARE_DATADESC(); - DEFINE_CUSTOM_AI; -}; - - -LINK_ENTITY_TO_CLASS( npc_enemyfinder, CNPC_EnemyFinder ); - - -//----------------------------------------------------------------------------- -// Custom schedules. -//----------------------------------------------------------------------------- -enum -{ - SCHED_EFINDER_SEARCH = LAST_SHARED_SCHEDULE, -}; - -IMPLEMENT_CUSTOM_AI( npc_enemyfinder, CNPC_EnemyFinder ); - -BEGIN_DATADESC( CNPC_EnemyFinder ) - - DEFINE_EMBEDDED( m_PlayerFreePass ), - DEFINE_EMBEDDED( m_ChooseEnemyTimer ), - - // Inputs - DEFINE_INPUT( m_nStartOn, FIELD_INTEGER, "StartOn" ), - DEFINE_INPUT( m_flFieldOfView, FIELD_FLOAT, "FieldOfView" ), - DEFINE_INPUT( m_flMinSearchDist, FIELD_FLOAT, "MinSearchDist" ), - DEFINE_INPUT( m_flMaxSearchDist, FIELD_FLOAT, "MaxSearchDist" ), - - DEFINE_FIELD( m_bEnemyStatus, FIELD_BOOLEAN ), - - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - - DEFINE_OUTPUT( m_OnLostEnemies, "OnLostEnemies"), - DEFINE_OUTPUT( m_OnAcquireEnemies, "OnAcquireEnemies"), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_EnemyFinder::InitCustomSchedules( void ) -{ - INIT_CUSTOM_AI( CNPC_EnemyFinder ); - - ADD_CUSTOM_SCHEDULE( CNPC_EnemyFinder, SCHED_EFINDER_SEARCH ); - AI_LOAD_SCHEDULE( CNPC_EnemyFinder, SCHED_EFINDER_SEARCH ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for turning the enemy finder on. -//----------------------------------------------------------------------------- -void CNPC_EnemyFinder::InputTurnOn( inputdata_t &inputdata ) -{ - SetThink( &CNPC_EnemyFinder::CallNPCThink ); - SetNextThink( gpGlobals->curtime ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for turning the enemy finder off. -//----------------------------------------------------------------------------- -void CNPC_EnemyFinder::InputTurnOff( inputdata_t &inputdata ) -{ - SetThink(NULL); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_EnemyFinder::Precache( void ) -{ - PrecacheModel( "models/player.mdl" ); - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CNPC_EnemyFinder::Spawn( void ) -{ - Precache(); - - SetModel( "models/player.mdl" ); - // This is a dummy model that is never used! - UTIL_SetSize(this, vec3_origin, vec3_origin); - - SetMoveType( MOVETYPE_NONE ); - SetBloodColor( DONT_BLEED ); - SetGravity( 0.0 ); - m_iHealth = 1; - - AddFlag( FL_NPC ); - - SetSolid( SOLID_NONE ); - - m_bEnemyStatus = false; - - if (m_flFieldOfView < -1.0) - { - DevMsg("ERROR: EnemyFinder field of view must be between -1.0 and 1.0\n"); - m_flFieldOfView = 0.5; - } - else if (m_flFieldOfView > 1.0) - { - DevMsg("ERROR: EnemyFinder field of view must be between -1.0 and 1.0\n"); - m_flFieldOfView = 1.0; - } - CapabilitiesAdd ( bits_CAP_SQUAD ); - - NPCInit(); - - // Set this after NPCInit() - m_takedamage = DAMAGE_NO; - AddEffects( EF_NODRAW ); - m_NPCState = NPC_STATE_ALERT; // always alert - - SetViewOffset( vec3_origin ); - if ( m_flMaxSearchDist ) - { - SetDistLook( m_flMaxSearchDist ); - } - - if ( HasSpawnFlags( SF_ENEMY_FINDER_SHORT_MEMORY ) ) - { - GetEnemies()->SetEnemyDiscardTime( 0.2 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : -//----------------------------------------------------------------------------- -int CNPC_EnemyFinder::SelectSchedule( void ) -{ - return SCHED_EFINDER_SEARCH; -} - -//------------------------------------------------------------------------------ -// -//------------------------------------------------------------------------------ -void CNPC_EnemyFinder::Wake( bool bFireOutput ) -{ - BaseClass::Wake( bFireOutput ); - - //Enemy finder is not allowed to become visible. - AddEffects( EF_NODRAW ); -} - -//------------------------------------------------------------------------------ -// -//------------------------------------------------------------------------------ -bool CNPC_EnemyFinder::FVisible( CBaseEntity *pTarget, int traceMask, CBaseEntity **ppBlocker ) -{ - float flTargetDist = GetAbsOrigin().DistTo( pTarget->GetAbsOrigin() ); - if ( flTargetDist < m_flMinSearchDist) - return false; - - if ( m_flMaxSearchDist && flTargetDist > m_flMaxSearchDist) - return false; - - if ( !FBitSet( m_spawnflags, SF_ENEMY_FINDER_CHECK_VIS) ) - return true; - - if ( !HasSpawnFlags(SF_ENEMY_FINDER_APC_VIS) ) - { - bool bIsVisible = BaseClass::FVisible( pTarget, traceMask, ppBlocker ); - - if ( bIsVisible && pTarget == m_PlayerFreePass.GetPassTarget() ) - bIsVisible = m_PlayerFreePass.ShouldAllowFVisible( bIsVisible ); - - return bIsVisible; - } - - // Make sure I can see the target from my position - trace_t tr; - - // Trace from launch position to target position. - // Use position above actual barral based on vertical launch speed - Vector vStartPos = GetAbsOrigin(); - Vector vEndPos = pTarget->EyePosition(); - - CBaseEntity *pVehicle = NULL; - if ( pTarget->IsPlayer() ) - { - CBasePlayer *pPlayer = assert_cast(pTarget); - pVehicle = pPlayer->GetVehicleEntity(); - } - - CTraceFilterSkipTwoEntities traceFilter( pTarget, pVehicle, COLLISION_GROUP_NONE ); - AI_TraceLine( vStartPos, vEndPos, MASK_SHOT, &traceFilter, &tr ); - if ( ppBlocker ) - { - *ppBlocker = tr.m_pEnt; - } - return (tr.fraction == 1.0); -} - - -//------------------------------------------------------------------------------ -bool CNPC_EnemyFinder::ShouldChooseNewEnemy() -{ - if ( m_ChooseEnemyTimer.Expired() ) - { - m_ChooseEnemyTimer.Set( 0.3 ); - return true; - } - return false; -} - -//------------------------------------------------------------------------------ -// Purpose : Override base class to check range and visibility -// Input : -// Output : -//------------------------------------------------------------------------------ -bool CNPC_EnemyFinder::IsValidEnemy( CBaseEntity *pTarget ) -{ - float flTargetDist = GetAbsOrigin().DistTo( pTarget->GetAbsOrigin() ); - if (flTargetDist < m_flMinSearchDist) - return false; - - if ( m_flMaxSearchDist && flTargetDist > m_flMaxSearchDist) - return false; - - if ( !FBitSet( m_spawnflags, SF_ENEMY_FINDER_CHECK_VIS) ) - return true; - - if ( GetSenses()->DidSeeEntity( pTarget ) ) - return true; - - // Trace from launch position to target position. - // Use position above actual barral based on vertical launch speed - Vector vStartPos = GetAbsOrigin(); - Vector vEndPos = pTarget->EyePosition(); - - // Test our line of sight to the target - trace_t tr; - AI_TraceLOS( vStartPos, vEndPos, this, &tr ); - - // If the player is in a vehicle, see if we can see that instead - if ( pTarget->IsPlayer() ) - { - CBasePlayer *pPlayer = assert_cast(pTarget); - if ( tr.m_pEnt == pPlayer->GetVehicleEntity() ) - return true; - } - - // Line must be clear - if ( tr.fraction == 1.0f || tr.m_pEnt == pTarget ) - return true; - - // Otherwise we can't see anything - return false; -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_EnemyFinder::StartNPC ( void ) -{ - AddSpawnFlags(SF_NPC_FALL_TO_GROUND); // this prevents CAI_BaseNPC from slamming the finder to - // the ground just because it's not MOVETYPE_FLY - BaseClass::StartNPC(); - - if ( AI_IsSinglePlayer() && m_PlayerFreePass.GetParams().duration > 0.1 ) - { - m_PlayerFreePass.SetPassTarget( UTIL_PlayerByIndex(1) ); - - AI_FreePassParams_t freePassParams = m_PlayerFreePass.GetParams(); - - freePassParams.coverDist = 120; - freePassParams.peekEyeDist = 1.75; - freePassParams.peekEyeDistZ = 4; - - m_PlayerFreePass.SetParams( freePassParams ); - } - - if (!m_nStartOn) - { - SetThink(NULL); - } -} - -//------------------------------------------------------------------------------ -void CNPC_EnemyFinder::PrescheduleThink() -{ - BaseClass::PrescheduleThink(); - - bool bHasEnemies = GetEnemies()->NumEnemies() > 0; - - if ( GetEnemies()->NumEnemies() > 0 ) - { - //If I haven't seen my enemy in half a second then we'll assume he's gone. - if ( gpGlobals->curtime - GetEnemyLastTimeSeen() >= 0.5f ) - { - bHasEnemies = false; - } - } - - if ( m_bEnemyStatus != bHasEnemies ) - { - if ( bHasEnemies ) - { - m_OnAcquireEnemies.FireOutput( this, this ); - } - else - { - m_OnLostEnemies.FireOutput( this, this ); - } - - m_bEnemyStatus = bHasEnemies; - } - - if( ai_debug_enemyfinders.GetBool() ) - { - m_debugOverlays |= OVERLAY_BBOX_BIT; - - if( IsInSquad() && GetSquad()->NumMembers() > 1 ) - { - AISquadIter_t iter; - CAI_BaseNPC *pSquadmate = m_pSquad ? m_pSquad->GetFirstMember( &iter ) : NULL; - while ( pSquadmate ) - { - NDebugOverlay::Line( WorldSpaceCenter(), pSquadmate->EyePosition(), 255, 255, 0, false, 0.1f ); - pSquadmate = m_pSquad->GetNextMember( &iter ); - } - } - } -} - -//------------------------------------------------------------------------------ -bool CNPC_EnemyFinder::ShouldAlwaysThink() -{ - if ( BaseClass::ShouldAlwaysThink() ) - return true; - - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer && IRelationType( pPlayer ) == D_HT ) - { - float playerDistSqr = GetAbsOrigin().DistToSqr( pPlayer->GetAbsOrigin() ); - - if ( !m_flMaxSearchDist || playerDistSqr <= Square(m_flMaxSearchDist) ) - { - if ( !FBitSet( m_spawnflags, SF_ENEMY_FINDER_CHECK_VIS) ) - return true; - - if ( playerDistSqr <= Square( 50 * 12 ) ) - return true; - } - } - - return false; -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_EnemyFinder::GatherConditions() -{ - // This works with old data because need to do before base class so as to not choose as enemy - m_PlayerFreePass.Update(); - BaseClass::GatherConditions(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -// Output : -//----------------------------------------------------------------------------- -Class_T CNPC_EnemyFinder::Classify( void ) -{ - if ( GetSquad() ) - { - AISquadIter_t iter; - CAI_BaseNPC *pSquadmate = GetSquad()->GetFirstMember( &iter ); - while ( pSquadmate ) - { - if ( pSquadmate != this && !pSquadmate->ClassMatches( GetClassname() ) ) - { - return pSquadmate->Classify(); - } - pSquadmate = GetSquad()->GetNextMember( &iter ); - } - } - - return CLASS_NONE; -} - -//----------------------------------------------------------------------------- -// Purpose: Add a visualizer to the text, if turned on -//----------------------------------------------------------------------------- -void CNPC_EnemyFinder::DrawDebugGeometryOverlays( void ) -{ - // Turn on npc_relationships if we're displaying text - int oldDebugOverlays = m_debugOverlays; - if ( m_debugOverlays & OVERLAY_TEXT_BIT ) - { - m_debugOverlays |= OVERLAY_NPC_RELATION_BIT; - } - - // Draw our base overlays - BaseClass::DrawDebugGeometryOverlays(); - - // Restore the old values - m_debugOverlays = oldDebugOverlays; -} - -ConVar ai_ef_hate_npc_frequency( "ai_ef_hate_npc_frequency", "5" ); -ConVar ai_ef_hate_npc_duration( "ai_ef_hate_npc_duration", "1.5" ); - -//----------------------------------------------------------------------------- -// Derived class with a few changes that make the Combine Cannon behave the -// way we want. -//----------------------------------------------------------------------------- -#define EF_COMBINE_CANNON_HATE_TIME_INVALID -1 -static CUtlVector s_ListEnemyfinders; - -class CNPC_EnemyFinderCombineCannon : public CNPC_EnemyFinder -{ -public: - DECLARE_CLASS( CNPC_EnemyFinderCombineCannon, CNPC_EnemyFinder ); - DECLARE_DATADESC(); - - CNPC_EnemyFinderCombineCannon() - { - m_flTimeNextHateNPC = gpGlobals->curtime; - m_flTimeStopHateNPC = EF_COMBINE_CANNON_HATE_TIME_INVALID; - }; - -public: - void Spawn(); - void Activate(); - void UpdateOnRemove(); - bool FVisible( CBaseEntity *pEntity, int traceMask, CBaseEntity **ppBlocker ); - bool IsValidEnemy( CBaseEntity *pTarget ); - void GatherConditions(); - - void InputSetWideFOVForSeconds( inputdata_t &inputdata ); - -public: - float m_flTimeNextHateNPC; - float m_flTimeStopHateNPC; - float m_flOriginalFOV; - float m_flTimeWideFOV; // If this is > gpGlobals->curtime, we have 180 degree viewcone. - string_t m_iszSnapToEnt; -}; -LINK_ENTITY_TO_CLASS( npc_enemyfinder_combinecannon, CNPC_EnemyFinderCombineCannon ); - -BEGIN_DATADESC( CNPC_EnemyFinderCombineCannon ) -DEFINE_FIELD( m_flTimeNextHateNPC, FIELD_TIME ), -DEFINE_FIELD( m_flTimeStopHateNPC, FIELD_TIME ), -DEFINE_FIELD( m_flOriginalFOV, FIELD_FLOAT ), -DEFINE_FIELD( m_flTimeWideFOV, FIELD_TIME ), -DEFINE_KEYFIELD( m_iszSnapToEnt, FIELD_STRING, "snaptoent" ), -DEFINE_INPUTFUNC( FIELD_FLOAT, "SetWideFOVForSeconds", InputSetWideFOVForSeconds ), -END_DATADESC() - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_EnemyFinderCombineCannon::Spawn() -{ - BaseClass::Spawn(); - m_flOriginalFOV = m_flFieldOfView; - m_flTimeWideFOV = -1.0f; - - if( m_iszSnapToEnt != NULL_STRING ) - { - CBaseEntity *pSnapToEnt = gEntList.FindEntityByName( NULL, m_iszSnapToEnt ); - - if( pSnapToEnt != NULL ) - { - //!!!HACKHACK - this eight-inch offset puts this enemyfinder perfectly on-bore - // with the prefab for a func_tank_combinecannon - UTIL_SetOrigin( this, pSnapToEnt->WorldSpaceCenter() + Vector( 0, 0, 8) ); - } - else - { - DevMsg( this, "Enemyfinder %s can't snap to %s because it doesn't exist\n", GetDebugName(), STRING(m_iszSnapToEnt) ); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_EnemyFinderCombineCannon::Activate() -{ - BaseClass::Activate(); - - // See if I'm in the list of Combine enemyfinders - // If not, add me. - if( s_ListEnemyfinders.Find(this) == -1 ) - { - s_ListEnemyfinders.AddToTail(this); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_EnemyFinderCombineCannon::UpdateOnRemove() -{ - BaseClass::UpdateOnRemove(); - - // See if I'm in the list of Combine enemyfinders - int index = s_ListEnemyfinders.Find(this); - if( index != -1 ) - { - s_ListEnemyfinders.Remove(index); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_EnemyFinderCombineCannon::FVisible( CBaseEntity *pEntity, int traceMask, CBaseEntity **ppBlocker ) -{ -#if 1 - CBaseEntity *pBlocker = NULL; - bool result; - - if(ppBlocker == NULL) - { - // Whoever called this didn't care about the blocker, but we do. - // So substitute our local pBlocker pointer and don't disturb ppBlocker - result = BaseClass::FVisible( pEntity, traceMask, &pBlocker ); - } - else - { - // Copy the ppBlocker to our local pBlocker pointer, but do not - // disturb the ppBlocker that was passed to us. - result = BaseClass::FVisible( pEntity, traceMask, ppBlocker ); - pBlocker = (*ppBlocker); - } - - if(pEntity->IsPlayer() && result == false) - { - // IF we are trying to see the player, but we don't, examine the blocker - // and see the player anyway if we can hurt the blocker. - if(pBlocker != NULL) - { - if( pBlocker->m_takedamage >= DAMAGE_YES ) // also DAMAGE_AIM - { - // Anytime the line of sight is blocked by something I can hurt, I have line of sight. - // This will make the func_tank_combinecannon shoot the blocking object. This will - // continue until the gun bores through to the player or clears all interposing breakables - // and finds its progress impeded by something truly solid. So lie, and say we CAN see the player. - result = true; - } - } - } - - return result; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Ignore NPC's most of the time when the player is a potential target. -// Go through short periods of time where NPCs may distract me -// -// ALSO- ignore NPC's (focus only on the player) when I'm in -// wide viewcone mode. -//----------------------------------------------------------------------------- -bool CNPC_EnemyFinderCombineCannon::IsValidEnemy( CBaseEntity *pTarget ) -{ - if( m_flTimeWideFOV > gpGlobals->curtime && !pTarget->IsPlayer() ) - { - // ONLY allowed to hate the player when I'm in hyper-vigilant wide FOV mode. - // This forces all guns in outland_09 to shoot at the player once any - // gun has fired at the player. This allows the other guns to specifically - // kill zombies most of the time, but immediately turn their attention to the - // player when necessary (by ignoring everything else) - return pTarget->IsPlayer(); - } - - bool bResult = BaseClass::IsValidEnemy( pTarget ); - - if( bResult && !pTarget->IsPlayer() ) - { - // This is a valid enemy, but we have to make sure no other enemyfinders for - // combine cannons are currently attacking it. - int i; - for( i = 0 ; i < s_ListEnemyfinders.Count() ; i++ ) - { - if( s_ListEnemyfinders[i] == this ) - continue; - - if( s_ListEnemyfinders[i]->GetEnemy() == pTarget ) - return false;// someone else is already busy with this target. - } - } - - /* - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - int iPlayerRelationPriority = -1; - - if( pPlayer != NULL ) - { - iPlayerRelationPriority = IRelationPriority(pPlayer); - } - - if( bResult == true && pTarget->IsNPC() && pPlayer != NULL && FInViewCone( pPlayer ) ) - { - if( HasCondition(COND_SEE_PLAYER) ) - { - // The player is visible! Immediately ignore all NPCs as enemies. - return false; - } - - // The base class wants to call this a valid enemy. We may choose to interfere - // If the player is in my viewcone. That means that my func_tank could potentially - // harass the player. This means I should meter the time I spend shooting at npcs - // NPCs so that I can focus on the player. - if( m_flTimeStopHateNPC != EF_COMBINE_CANNON_HATE_TIME_INVALID ) - { - // We currently hate NPC's. But is it time to stop? - if( gpGlobals->curtime > m_flTimeStopHateNPC ) - { - // Don't interfere with the result - m_flTimeStopHateNPC = EF_COMBINE_CANNON_HATE_TIME_INVALID; - m_flTimeNextHateNPC = gpGlobals->curtime + ai_ef_hate_npc_frequency.GetFloat(); - return bResult; - } - } - else - { - // We do not hate NPCs at the moment. Is it time to turn it on? - if( gpGlobals->curtime > m_flTimeNextHateNPC ) - { - m_flTimeStopHateNPC = gpGlobals->curtime + ai_ef_hate_npc_duration.GetFloat(); - } - else - { - // Stop harassing player to attack something else higher priority. - if( IRelationPriority(pTarget) > iPlayerRelationPriority ) - return bResult; - } - - // Make this enemy invalid. - return false; - } - } - */ - - return bResult; -} - -//----------------------------------------------------------------------------- -// Purpose: Control the width of my viewcone -//----------------------------------------------------------------------------- -void CNPC_EnemyFinderCombineCannon::GatherConditions() -{ - if( m_flTimeWideFOV > gpGlobals->curtime ) - { - // I'm in a hyper-vigilant period of time where I get a 270 degree viewcone - m_flFieldOfView = -0.5f; - } - else - { - m_flFieldOfView = m_flOriginalFOV; - } - - BaseClass::GatherConditions(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_EnemyFinderCombineCannon::InputSetWideFOVForSeconds( inputdata_t &inputdata ) -{ - m_flTimeWideFOV = gpGlobals->curtime + inputdata.value.Float(); -} - - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -//========================================================= -// > SCHED_EFINDER_SEARCH -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_EFINDER_SEARCH, - - " Tasks" - " TASK_WAIT_RANDOM 0.5 " - " " - " Interrupts" - " COND_NEW_ENEMY" -); diff --git a/game/server/hl2/npc_fastzombie.cpp b/game/server/hl2/npc_fastzombie.cpp deleted file mode 100644 index f85ac4a70..000000000 --- a/game/server/hl2/npc_fastzombie.cpp +++ /dev/null @@ -1,2159 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ai_basenpc.h" -#include "ai_default.h" -#include "ai_schedule.h" -#include "ai_hull.h" -#include "ai_motor.h" -#include "ai_memory.h" -#include "ai_route.h" -#include "soundent.h" -#include "game.h" -#include "npcevent.h" -#include "entitylist.h" -#include "ai_task.h" -#include "activitylist.h" -#include "engine/IEngineSound.h" -#include "npc_BaseZombie.h" -#include "movevars_shared.h" -#include "IEffects.h" -#include "props.h" -#include "physics_npc_solver.h" -#include "physics_prop_ragdoll.h" - -#ifdef HL2_EPISODIC -#include "episodic/ai_behavior_passenger_zombie.h" -#endif // HL2_EPISODIC - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define FASTZOMBIE_IDLE_PITCH 35 -#define FASTZOMBIE_MIN_PITCH 70 -#define FASTZOMBIE_MAX_PITCH 130 -#define FASTZOMBIE_SOUND_UPDATE_FREQ 0.5 - -#define FASTZOMBIE_MAXLEAP_Z 128 - -#define FASTZOMBIE_EXCITE_DIST 480.0 - -#define FASTZOMBIE_BASE_FREQ 1.5 - -// If flying at an enemy, and this close or closer, start playing the maul animation!! -#define FASTZOMBIE_MAUL_RANGE 300 - -#ifdef HL2_EPISODIC - -int AE_PASSENGER_PHYSICS_PUSH; -int AE_FASTZOMBIE_VEHICLE_LEAP; -int AE_FASTZOMBIE_VEHICLE_SS_DIE; // Killed while doing scripted sequence on vehicle - -#endif // HL2_EPISODIC - -enum -{ - COND_FASTZOMBIE_CLIMB_TOUCH = LAST_BASE_ZOMBIE_CONDITION, -}; - -envelopePoint_t envFastZombieVolumeJump[] = -{ - { 1.0f, 1.0f, - 0.1f, 0.1f, - }, - { 0.0f, 0.0f, - 1.0f, 1.2f, - }, -}; - -envelopePoint_t envFastZombieVolumePain[] = -{ - { 1.0f, 1.0f, - 0.1f, 0.1f, - }, - { 0.0f, 0.0f, - 1.0f, 1.0f, - }, -}; - -envelopePoint_t envFastZombieInverseVolumePain[] = -{ - { 0.0f, 0.0f, - 0.1f, 0.1f, - }, - { 1.0f, 1.0f, - 1.0f, 1.0f, - }, -}; - -envelopePoint_t envFastZombieVolumeJumpPostApex[] = -{ - { 1.0f, 1.0f, - 0.1f, 0.1f, - }, - { 0.0f, 0.0f, - 1.0f, 1.2f, - }, -}; - -envelopePoint_t envFastZombieVolumeClimb[] = -{ - { 1.0f, 1.0f, - 0.1f, 0.1f, - }, - { 0.0f, 0.0f, - 0.2f, 0.2f, - }, -}; - -envelopePoint_t envFastZombieMoanVolumeFast[] = -{ - { 1.0f, 1.0f, - 0.1f, 0.1f, - }, - { 0.0f, 0.0f, - 0.2f, 0.3f, - }, -}; - -envelopePoint_t envFastZombieMoanVolume[] = -{ - { 1.0f, 1.0f, - 0.1f, 0.1f, - }, - { 1.0f, 1.0f, - 0.2f, 0.2f, - }, - { 0.0f, 0.0f, - 1.0f, 0.4f, - }, -}; - -envelopePoint_t envFastZombieFootstepVolume[] = -{ - { 1.0f, 1.0f, - 0.1f, 0.1f, - }, - { 0.7f, 0.7f, - 0.2f, 0.2f, - }, -}; - -envelopePoint_t envFastZombieVolumeFrenzy[] = -{ - { 1.0f, 1.0f, - 0.1f, 0.1f, - }, - { 0.0f, 0.0f, - 2.0f, 2.0f, - }, -}; - - -//========================================================= -// animation events -//========================================================= -int AE_FASTZOMBIE_LEAP; -int AE_FASTZOMBIE_GALLOP_LEFT; -int AE_FASTZOMBIE_GALLOP_RIGHT; -int AE_FASTZOMBIE_CLIMB_LEFT; -int AE_FASTZOMBIE_CLIMB_RIGHT; - -//========================================================= -// tasks -//========================================================= -enum -{ - TASK_FASTZOMBIE_DO_ATTACK = LAST_SHARED_TASK + 100, // again, my !!!HACKHACK - TASK_FASTZOMBIE_LAND_RECOVER, - TASK_FASTZOMBIE_UNSTICK_JUMP, - TASK_FASTZOMBIE_JUMP_BACK, - TASK_FASTZOMBIE_VERIFY_ATTACK, -}; - -//========================================================= -// activities -//========================================================= -int ACT_FASTZOMBIE_LEAP_SOAR; -int ACT_FASTZOMBIE_LEAP_STRIKE; -int ACT_FASTZOMBIE_LAND_RIGHT; -int ACT_FASTZOMBIE_LAND_LEFT; -int ACT_FASTZOMBIE_FRENZY; -int ACT_FASTZOMBIE_BIG_SLASH; - -//========================================================= -// schedules -//========================================================= -enum -{ - SCHED_FASTZOMBIE_RANGE_ATTACK1 = LAST_SHARED_SCHEDULE + 100, // hack to get past the base zombie's schedules - SCHED_FASTZOMBIE_UNSTICK_JUMP, - SCHED_FASTZOMBIE_CLIMBING_UNSTICK_JUMP, - SCHED_FASTZOMBIE_MELEE_ATTACK1, - SCHED_FASTZOMBIE_TORSO_MELEE_ATTACK1, -}; - - - -//========================================================= -//========================================================= -class CFastZombie : public CNPC_BaseZombie -{ - DECLARE_CLASS( CFastZombie, CNPC_BaseZombie ); - -public: - void Spawn( void ); - void Precache( void ); - - void SetZombieModel( void ); - bool CanSwatPhysicsObjects( void ) { return false; } - - int TranslateSchedule( int scheduleType ); - - Activity NPC_TranslateActivity( Activity baseAct ); - - void LeapAttackTouch( CBaseEntity *pOther ); - void ClimbTouch( CBaseEntity *pOther ); - - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - int SelectSchedule( void ); - void OnScheduleChange( void ); - - void PrescheduleThink( void ); - - float InnateRange1MaxRange( void ); - int RangeAttack1Conditions( float flDot, float flDist ); - int MeleeAttack1Conditions( float flDot, float flDist ); - - virtual float GetClawAttackRange() const { return 50; } - - bool ShouldPlayFootstepMoan( void ) { return false; } - - void HandleAnimEvent( animevent_t *pEvent ); - - void PostNPCInit( void ); - - void LeapAttack( void ); - void LeapAttackSound( void ); - - void BecomeTorso( const Vector &vecTorsoForce, const Vector &vecLegsForce ); - - bool IsJumpLegal(const Vector &startPos, const Vector &apex, const Vector &endPos) const; - bool MovementCost( int moveType, const Vector &vecStart, const Vector &vecEnd, float *pCost ); - bool ShouldFailNav( bool bMovementFailed ); - - int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ); - - const char *GetMoanSound( int nSound ); - - void OnChangeActivity( Activity NewActivity ); - void OnStateChange( NPC_STATE OldState, NPC_STATE NewState ); - void Event_Killed( const CTakeDamageInfo &info ); - bool ShouldBecomeTorso( const CTakeDamageInfo &info, float flDamageThreshold ); - - virtual Vector GetAutoAimCenter() { return WorldSpaceCenter() - Vector( 0, 0, 12.0f ); } - - void PainSound( const CTakeDamageInfo &info ); - void DeathSound( const CTakeDamageInfo &info ); - void AlertSound( void ); - void IdleSound( void ); - void AttackSound( void ); - void AttackHitSound( void ); - void AttackMissSound( void ); - void FootstepSound( bool fRightFoot ); - void FootscuffSound( bool fRightFoot ) {}; // fast guy doesn't scuff - void StopLoopingSounds( void ); - - void SoundInit( void ); - void SetIdleSoundState( void ); - void SetAngrySoundState( void ); - - void BuildScheduleTestBits( void ); - - void BeginNavJump( void ); - void EndNavJump( void ); - - bool IsNavJumping( void ) { return m_fIsNavJumping; } - void OnNavJumpHitApex( void ); - - void BeginAttackJump( void ); - void EndAttackJump( void ); - - float MaxYawSpeed( void ); - - virtual const char *GetHeadcrabClassname( void ); - virtual const char *GetHeadcrabModel( void ); - virtual const char *GetLegsModel( void ); - virtual const char *GetTorsoModel( void ); - -//============================================================================= -#ifdef HL2_EPISODIC - -public: - virtual bool CreateBehaviors( void ); - virtual void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); - virtual void UpdateEfficiency( bool bInPVS ); - virtual bool IsInAVehicle( void ); - void InputAttachToVehicle( inputdata_t &inputdata ); - void VehicleLeapAttackTouch( CBaseEntity *pOther ); - -private: - void VehicleLeapAttack( void ); - bool CanEnterVehicle( CPropJeepEpisodic *pVehicle ); - - CAI_PassengerBehaviorZombie m_PassengerBehavior; - -#endif // HL2_EPISODIC -//============================================================================= - -protected: - - static const char *pMoanSounds[]; - - // Sound stuff - float m_flDistFactor; - unsigned char m_iClimbCount; // counts rungs climbed (for sound) - bool m_fIsNavJumping; - bool m_fIsAttackJumping; - bool m_fHitApex; - mutable float m_flJumpDist; - - bool m_fHasScreamed; - -private: - float m_flNextMeleeAttack; - bool m_fJustJumped; - float m_flJumpStartAltitude; - float m_flTimeUpdateSound; - - CSoundPatch *m_pLayer2; // used for climbing ladders, and when jumping (pre apex) - -public: - DEFINE_CUSTOM_AI; - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( npc_fastzombie, CFastZombie ); -LINK_ENTITY_TO_CLASS( npc_fastzombie_torso, CFastZombie ); - - -BEGIN_DATADESC( CFastZombie ) - - DEFINE_FIELD( m_flDistFactor, FIELD_FLOAT ), - DEFINE_FIELD( m_iClimbCount, FIELD_CHARACTER ), - DEFINE_FIELD( m_fIsNavJumping, FIELD_BOOLEAN ), - DEFINE_FIELD( m_fIsAttackJumping, FIELD_BOOLEAN ), - DEFINE_FIELD( m_fHitApex, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flJumpDist, FIELD_FLOAT ), - DEFINE_FIELD( m_fHasScreamed, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flNextMeleeAttack, FIELD_TIME ), - DEFINE_FIELD( m_fJustJumped, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flJumpStartAltitude, FIELD_FLOAT ), - DEFINE_FIELD( m_flTimeUpdateSound, FIELD_TIME ), - - // Function Pointers - DEFINE_ENTITYFUNC( LeapAttackTouch ), - DEFINE_ENTITYFUNC( ClimbTouch ), - DEFINE_SOUNDPATCH( m_pLayer2 ), - -#ifdef HL2_EPISODIC - DEFINE_ENTITYFUNC( VehicleLeapAttackTouch ), - DEFINE_INPUTFUNC( FIELD_STRING, "AttachToVehicle", InputAttachToVehicle ), -#endif // HL2_EPISODIC - -END_DATADESC() - - -const char *CFastZombie::pMoanSounds[] = -{ - "NPC_FastZombie.Moan1", -}; - -//----------------------------------------------------------------------------- -// The model we use for our legs when we get blowed up. -//----------------------------------------------------------------------------- -static const char *s_pLegsModel = "models/gibs/fast_zombie_legs.mdl"; - - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CFastZombie::Precache( void ) -{ - PrecacheModel("models/zombie/fast.mdl"); -#ifdef HL2_EPISODIC - PrecacheModel("models/zombie/Fast_torso.mdl"); - PrecacheScriptSound( "NPC_FastZombie.CarEnter1" ); - PrecacheScriptSound( "NPC_FastZombie.CarEnter2" ); - PrecacheScriptSound( "NPC_FastZombie.CarEnter3" ); - PrecacheScriptSound( "NPC_FastZombie.CarEnter4" ); - PrecacheScriptSound( "NPC_FastZombie.CarScream" ); -#endif - PrecacheModel( "models/gibs/fast_zombie_torso.mdl" ); - PrecacheModel( "models/gibs/fast_zombie_legs.mdl" ); - - PrecacheScriptSound( "NPC_FastZombie.LeapAttack" ); - PrecacheScriptSound( "NPC_FastZombie.FootstepRight" ); - PrecacheScriptSound( "NPC_FastZombie.FootstepLeft" ); - PrecacheScriptSound( "NPC_FastZombie.AttackHit" ); - PrecacheScriptSound( "NPC_FastZombie.AttackMiss" ); - PrecacheScriptSound( "NPC_FastZombie.LeapAttack" ); - PrecacheScriptSound( "NPC_FastZombie.Attack" ); - PrecacheScriptSound( "NPC_FastZombie.Idle" ); - PrecacheScriptSound( "NPC_FastZombie.AlertFar" ); - PrecacheScriptSound( "NPC_FastZombie.AlertNear" ); - PrecacheScriptSound( "NPC_FastZombie.GallopLeft" ); - PrecacheScriptSound( "NPC_FastZombie.GallopRight" ); - PrecacheScriptSound( "NPC_FastZombie.Scream" ); - PrecacheScriptSound( "NPC_FastZombie.RangeAttack" ); - PrecacheScriptSound( "NPC_FastZombie.Frenzy" ); - PrecacheScriptSound( "NPC_FastZombie.NoSound" ); - PrecacheScriptSound( "NPC_FastZombie.Die" ); - - PrecacheScriptSound( "NPC_FastZombie.Gurgle" ); - - PrecacheScriptSound( "NPC_FastZombie.Moan1" ); - - BaseClass::Precache(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CFastZombie::OnScheduleChange( void ) -{ - if ( m_flNextMeleeAttack > gpGlobals->curtime + 1 ) - { - // Allow melee attacks again. - m_flNextMeleeAttack = gpGlobals->curtime + 0.5; - } - - BaseClass::OnScheduleChange(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CFastZombie::SelectSchedule ( void ) -{ - -// ======================================================== -#ifdef HL2_EPISODIC - - // Defer all decisions to the behavior if it's running - if ( m_PassengerBehavior.CanSelectSchedule() ) - { - DeferSchedulingToBehavior( &m_PassengerBehavior ); - return BaseClass::SelectSchedule(); - } - -#endif //HL2_EPISODIC -// ======================================================== - - if ( HasCondition( COND_ZOMBIE_RELEASECRAB ) ) - { - // Death waits for no man. Or zombie. Or something. - return SCHED_ZOMBIE_RELEASECRAB; - } - - if ( HasCondition( COND_FASTZOMBIE_CLIMB_TOUCH ) ) - { - return SCHED_FASTZOMBIE_UNSTICK_JUMP; - } - - switch ( m_NPCState ) - { - case NPC_STATE_COMBAT: - if ( HasCondition( COND_LOST_ENEMY ) || ( HasCondition( COND_ENEMY_UNREACHABLE ) && MustCloseToAttack() ) ) - { - // Set state to alert and recurse! - SetState( NPC_STATE_ALERT ); - return SelectSchedule(); - } - break; - - case NPC_STATE_ALERT: - if ( HasCondition( COND_LOST_ENEMY ) || ( HasCondition( COND_ENEMY_UNREACHABLE ) && MustCloseToAttack() ) ) - { - ClearCondition( COND_LOST_ENEMY ); - ClearCondition( COND_ENEMY_UNREACHABLE ); - SetEnemy( NULL ); - -#ifdef DEBUG_ZOMBIES - DevMsg("Wandering\n"); -#endif - - // Just lost track of our enemy. - // Wander around a bit so we don't look like a dingus. - return SCHED_ZOMBIE_WANDER_MEDIUM; - } - break; - - default: - break; - } - - return BaseClass::SelectSchedule(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CFastZombie::PrescheduleThink( void ) -{ - BaseClass::PrescheduleThink(); - - if( GetGroundEntity() && GetGroundEntity()->Classify() == CLASS_HEADCRAB ) - { - // Kill! - CTakeDamageInfo info; - info.SetDamage( GetGroundEntity()->GetHealth() ); - info.SetAttacker( this ); - info.SetInflictor( this ); - info.SetDamageType( DMG_GENERIC ); - GetGroundEntity()->TakeDamage( info ); - } - - if( m_pMoanSound && gpGlobals->curtime > m_flTimeUpdateSound ) - { - // Manage the snorting sound, pitch up for closer. - float flDistNoBBox; - - if( GetEnemy() && m_NPCState == NPC_STATE_COMBAT ) - { - flDistNoBBox = ( GetEnemy()->WorldSpaceCenter() - WorldSpaceCenter() ).Length(); - flDistNoBBox -= WorldAlignSize().x; - } - else - { - // Calm down! - flDistNoBBox = FASTZOMBIE_EXCITE_DIST; - m_flTimeUpdateSound += 1.0; - } - - if( flDistNoBBox >= FASTZOMBIE_EXCITE_DIST && m_flDistFactor != 1.0 ) - { - // Go back to normal pitch. - m_flDistFactor = 1.0; - - ENVELOPE_CONTROLLER.SoundChangePitch( m_pMoanSound, FASTZOMBIE_IDLE_PITCH, FASTZOMBIE_SOUND_UPDATE_FREQ ); - } - else if( flDistNoBBox < FASTZOMBIE_EXCITE_DIST ) - { - // Zombie is close! Recalculate pitch. - int iPitch; - - m_flDistFactor = MIN( 1.0, 1 - flDistNoBBox / FASTZOMBIE_EXCITE_DIST ); - iPitch = (int)(FASTZOMBIE_MIN_PITCH + ( ( FASTZOMBIE_MAX_PITCH - FASTZOMBIE_MIN_PITCH ) * m_flDistFactor)); - ENVELOPE_CONTROLLER.SoundChangePitch( m_pMoanSound, iPitch, FASTZOMBIE_SOUND_UPDATE_FREQ ); - } - - m_flTimeUpdateSound = gpGlobals->curtime + FASTZOMBIE_SOUND_UPDATE_FREQ; - } - - // Crudely detect the apex of our jump - if( IsNavJumping() && !m_fHitApex && GetAbsVelocity().z <= 0.0 ) - { - OnNavJumpHitApex(); - } - - if( IsCurSchedule(SCHED_FASTZOMBIE_RANGE_ATTACK1, false) ) - { - // Think more frequently when flying quickly through the - // air, to update the server's location more often. - SetNextThink(gpGlobals->curtime); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Startup all of the sound patches that the fast zombie uses. -// -// -//----------------------------------------------------------------------------- -void CFastZombie::SoundInit( void ) -{ - if( !m_pMoanSound ) - { - // !!!HACKHACK - kickstart the moan sound. (sjb) - MoanSound( envFastZombieMoanVolume, ARRAYSIZE( envFastZombieMoanVolume ) ); - - // Clear the commands that the base class gave the moaning sound channel. - ENVELOPE_CONTROLLER.CommandClear( m_pMoanSound ); - } - - CPASAttenuationFilter filter( this ); - - if( !m_pLayer2 ) - { - // Set up layer2 - m_pLayer2 = ENVELOPE_CONTROLLER.SoundCreate( filter, entindex(), CHAN_VOICE, "NPC_FastZombie.Gurgle", ATTN_NORM ); - - // Start silent. - ENVELOPE_CONTROLLER.Play( m_pLayer2, 0.0, 100 ); - } - - SetIdleSoundState(); -} - -//----------------------------------------------------------------------------- -// Purpose: Make the zombie sound calm. -//----------------------------------------------------------------------------- -void CFastZombie::SetIdleSoundState( void ) -{ - // Main looping sound - if ( m_pMoanSound ) - { - ENVELOPE_CONTROLLER.SoundChangePitch( m_pMoanSound, FASTZOMBIE_IDLE_PITCH, 1.0 ); - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pMoanSound, 0.75, 1.0 ); - } - - // Second Layer - if ( m_pLayer2 ) - { - ENVELOPE_CONTROLLER.SoundChangePitch( m_pLayer2, 100, 1.0 ); - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pLayer2, 0.0, 1.0 ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Make the zombie sound pizzled -//----------------------------------------------------------------------------- -void CFastZombie::SetAngrySoundState( void ) -{ - if (( !m_pMoanSound ) || ( !m_pLayer2 )) - { - return; - } - - EmitSound( "NPC_FastZombie.LeapAttack" ); - - // Main looping sound - ENVELOPE_CONTROLLER.SoundChangePitch( m_pMoanSound, FASTZOMBIE_MIN_PITCH, 0.5 ); - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pMoanSound, 1.0, 0.5 ); - - // Second Layer - ENVELOPE_CONTROLLER.SoundChangePitch( m_pLayer2, 100, 1.0 ); - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pLayer2, 0.0, 1.0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CFastZombie::Spawn( void ) -{ - Precache(); - - m_fJustJumped = false; - - m_fIsTorso = m_fIsHeadless = false; - - if( FClassnameIs( this, "npc_fastzombie" ) ) - { - m_fIsTorso = false; - } - else - { - // This was placed as an npc_fastzombie_torso - m_fIsTorso = true; - } - -#ifdef HL2_EPISODIC - SetBloodColor( BLOOD_COLOR_ZOMBIE ); -#else - SetBloodColor( BLOOD_COLOR_YELLOW ); -#endif // HL2_EPISODIC - - m_iHealth = 50; - m_flFieldOfView = 0.2; - - CapabilitiesClear(); - CapabilitiesAdd( bits_CAP_MOVE_CLIMB | bits_CAP_MOVE_JUMP | bits_CAP_MOVE_GROUND | bits_CAP_INNATE_RANGE_ATTACK1 /* | bits_CAP_INNATE_MELEE_ATTACK1 */); - - if ( m_fIsTorso == true ) - { - CapabilitiesRemove( bits_CAP_MOVE_JUMP | bits_CAP_INNATE_RANGE_ATTACK1 ); - } - - m_flNextAttack = gpGlobals->curtime; - - m_pLayer2 = NULL; - m_iClimbCount = 0; - - EndNavJump(); - - m_flDistFactor = 1.0; - - BaseClass::Spawn(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CFastZombie::PostNPCInit( void ) -{ - SoundInit(); - - m_flTimeUpdateSound = gpGlobals->curtime; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the classname (ie "npc_headcrab") to spawn when our headcrab bails. -//----------------------------------------------------------------------------- -const char *CFastZombie::GetHeadcrabClassname( void ) -{ - return "npc_headcrab_fast"; -} - -const char *CFastZombie::GetHeadcrabModel( void ) -{ - return "models/headcrab.mdl"; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CFastZombie::MaxYawSpeed( void ) -{ - switch( GetActivity() ) - { - case ACT_TURN_LEFT: - case ACT_TURN_RIGHT: - return 120; - break; - - case ACT_RUN: - return 160; - break; - - case ACT_WALK: - case ACT_IDLE: - return 25; - break; - - default: - return 20; - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CFastZombie::SetZombieModel( void ) -{ - Hull_t lastHull = GetHullType(); - - if ( m_fIsTorso ) - { - SetModel( "models/zombie/fast_torso.mdl" ); - SetHullType(HULL_TINY); - } - else - { - SetModel( "models/zombie/fast.mdl" ); - SetHullType(HULL_HUMAN); - } - - SetBodygroup( ZOMBIE_BODYGROUP_HEADCRAB, !m_fIsHeadless ); - - SetHullSizeNormal( true ); - SetDefaultEyeOffset(); - SetActivity( ACT_IDLE ); - - // hull changed size, notify vphysics - // UNDONE: Solve this generally, systematically so other - // NPCs can change size - if ( lastHull != GetHullType() ) - { - if ( VPhysicsGetObject() ) - { - SetupVPhysicsHull(); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns the model to use for our legs ragdoll when we are blown in twain. -//----------------------------------------------------------------------------- -const char *CFastZombie::GetLegsModel( void ) -{ - return s_pLegsModel; -} - -const char *CFastZombie::GetTorsoModel( void ) -{ - return "models/gibs/fast_zombie_torso.mdl"; -} - - -//----------------------------------------------------------------------------- -// Purpose: See if I can swat the player -// -// -//----------------------------------------------------------------------------- -int CFastZombie::MeleeAttack1Conditions( float flDot, float flDist ) -{ - if ( !GetEnemy() ) - { - return COND_NONE; - } - - if( !(GetFlags() & FL_ONGROUND) ) - { - // Have to be on the ground! - return COND_NONE; - } - - if( gpGlobals->curtime < m_flNextMeleeAttack ) - { - return COND_NONE; - } - - int baseResult = BaseClass::MeleeAttack1Conditions( flDot, flDist ); - - // @TODO (toml 07-21-04): follow up with Steve to find out why fz was explicitly not using these conditions - if ( baseResult == COND_TOO_FAR_TO_ATTACK || baseResult == COND_NOT_FACING_ATTACK ) - { - return COND_NONE; - } - - return baseResult; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns a moan sound for this class of zombie. -//----------------------------------------------------------------------------- -const char *CFastZombie::GetMoanSound( int nSound ) -{ - return pMoanSounds[ nSound % ARRAYSIZE( pMoanSounds ) ]; -} - -//----------------------------------------------------------------------------- -// Purpose: Sound of a footstep -//----------------------------------------------------------------------------- -void CFastZombie::FootstepSound( bool fRightFoot ) -{ - if( fRightFoot ) - { - EmitSound( "NPC_FastZombie.FootstepRight" ); - } - else - { - EmitSound( "NPC_FastZombie.FootstepLeft" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Play a random attack hit sound -//----------------------------------------------------------------------------- -void CFastZombie::AttackHitSound( void ) -{ - EmitSound( "NPC_FastZombie.AttackHit" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Play a random attack miss sound -//----------------------------------------------------------------------------- -void CFastZombie::AttackMissSound( void ) -{ - // Play a random attack miss sound - EmitSound( "NPC_FastZombie.AttackMiss" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Play a random attack sound. -//----------------------------------------------------------------------------- -void CFastZombie::LeapAttackSound( void ) -{ - EmitSound( "NPC_FastZombie.LeapAttack" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Play a random attack sound. -//----------------------------------------------------------------------------- -void CFastZombie::AttackSound( void ) -{ - EmitSound( "NPC_FastZombie.Attack" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Play a random idle sound. -//----------------------------------------------------------------------------- -void CFastZombie::IdleSound( void ) -{ - EmitSound( "NPC_FastZombie.Idle" ); - MakeAISpookySound( 360.0f ); -} - -//----------------------------------------------------------------------------- -// Purpose: Play a random pain sound. -//----------------------------------------------------------------------------- -void CFastZombie::PainSound( const CTakeDamageInfo &info ) -{ - if ( m_pLayer2 ) - ENVELOPE_CONTROLLER.SoundPlayEnvelope( m_pLayer2, SOUNDCTRL_CHANGE_VOLUME, envFastZombieVolumePain, ARRAYSIZE(envFastZombieVolumePain) ); - if ( m_pMoanSound ) - ENVELOPE_CONTROLLER.SoundPlayEnvelope( m_pMoanSound, SOUNDCTRL_CHANGE_VOLUME, envFastZombieInverseVolumePain, ARRAYSIZE(envFastZombieInverseVolumePain) ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CFastZombie::DeathSound( const CTakeDamageInfo &info ) -{ - EmitSound( "NPC_FastZombie.Die" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Play a random alert sound. -//----------------------------------------------------------------------------- -void CFastZombie::AlertSound( void ) -{ - CBaseEntity *pPlayer = AI_GetSinglePlayer(); - - if( pPlayer ) - { - // Measure how far the player is, and play the appropriate type of alert sound. - // Doesn't matter if I'm getting mad at a different character, the player is the - // one that hears the sound. - float flDist; - - flDist = ( GetAbsOrigin() - pPlayer->GetAbsOrigin() ).Length(); - - if( flDist > 512 ) - { - EmitSound( "NPC_FastZombie.AlertFar" ); - } - else - { - EmitSound( "NPC_FastZombie.AlertNear" ); - } - } - -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -#define FASTZOMBIE_MINLEAP 200 -#define FASTZOMBIE_MAXLEAP 300 -float CFastZombie::InnateRange1MaxRange( void ) -{ - return FASTZOMBIE_MAXLEAP; -} - - -//----------------------------------------------------------------------------- -// Purpose: See if I can make my leaping attack!! -// -// -//----------------------------------------------------------------------------- -int CFastZombie::RangeAttack1Conditions( float flDot, float flDist ) -{ - - if (GetEnemy() == NULL) - { - return( COND_NONE ); - } - - if( !(GetFlags() & FL_ONGROUND) ) - { - return COND_NONE; - } - - if( gpGlobals->curtime < m_flNextAttack ) - { - return( COND_NONE ); - } - - // make sure the enemy isn't on a roof and I'm in the streets (Ravenholm) - float flZDist; - flZDist = fabs( GetEnemy()->GetLocalOrigin().z - GetLocalOrigin().z ); - if( flZDist > FASTZOMBIE_MAXLEAP_Z ) - { - return COND_TOO_FAR_TO_ATTACK; - } - - if( flDist > InnateRange1MaxRange() ) - { - return COND_TOO_FAR_TO_ATTACK; - } - - if( flDist < FASTZOMBIE_MINLEAP ) - { - return COND_NONE; - } - - if (flDot < 0.8) - { - return COND_NONE; - } - - if ( !IsMoving() ) - { - // I Have to be running!!! - return COND_NONE; - } - - // Don't jump at the player unless he's facing me. - // This allows the player to get away if he turns and sprints - CBasePlayer *pPlayer = static_cast( GetEnemy() ); - - if( pPlayer ) - { - // If the enemy is a player, don't attack from behind! - if( !pPlayer->FInViewCone( this ) ) - { - return COND_NONE; - } - } - - // Drumroll please! - // The final check! Is the path from my position to halfway between me - // and the player clear? - trace_t tr; - Vector vecDirToEnemy; - - vecDirToEnemy = GetEnemy()->WorldSpaceCenter() - WorldSpaceCenter(); - Vector vecHullMin( -16, -16, -16 ); - Vector vecHullMax( 16, 16, 16 ); - - // only check half the distance. (the first part of the jump) - vecDirToEnemy = vecDirToEnemy * 0.5; - - AI_TraceHull( WorldSpaceCenter(), WorldSpaceCenter() + vecDirToEnemy, vecHullMin, vecHullMax, MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - - if( tr.fraction != 1.0 ) - { - // There's some sort of obstacle pretty much right in front of me. - return COND_NONE; - } - - return COND_CAN_RANGE_ATTACK1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CFastZombie::HandleAnimEvent( animevent_t *pEvent ) -{ - if ( pEvent->event == AE_FASTZOMBIE_CLIMB_LEFT || pEvent->event == AE_FASTZOMBIE_CLIMB_RIGHT ) - { - if( ++m_iClimbCount % 3 == 0 ) - { - ENVELOPE_CONTROLLER.SoundChangePitch( m_pLayer2, random->RandomFloat( 100, 150 ), 0.0 ); - ENVELOPE_CONTROLLER.SoundPlayEnvelope( m_pLayer2, SOUNDCTRL_CHANGE_VOLUME, envFastZombieVolumeClimb, ARRAYSIZE(envFastZombieVolumeClimb) ); - } - - return; - } - - if ( pEvent->event == AE_FASTZOMBIE_LEAP ) - { - LeapAttack(); - return; - } - - if ( pEvent->event == AE_FASTZOMBIE_GALLOP_LEFT ) - { - EmitSound( "NPC_FastZombie.GallopLeft" ); - return; - } - - if ( pEvent->event == AE_FASTZOMBIE_GALLOP_RIGHT ) - { - EmitSound( "NPC_FastZombie.GallopRight" ); - return; - } - - if ( pEvent->event == AE_ZOMBIE_ATTACK_RIGHT ) - { - Vector right; - QAngle viewPunch(-3.0f, -5.0f, -3.0f); - AngleVectors( GetLocalAngles(), NULL, &right, NULL ); - right = right * -50; - - ClawAttack( GetClawAttackRange(), 3, viewPunch, right, ZOMBIE_BLOOD_RIGHT_HAND ); - return; - } - - if ( pEvent->event == AE_ZOMBIE_ATTACK_LEFT ) - { - Vector right; - AngleVectors( GetLocalAngles(), NULL, &right, NULL ); - QAngle viewPunch(-3.0f, -5.0f, -3.0f); - right = right * 50; - ClawAttack( GetClawAttackRange(), 3, viewPunch, right, ZOMBIE_BLOOD_LEFT_HAND ); - return; - } - -//============================================================================= -#ifdef HL2_EPISODIC - - // Do the leap attack - if ( pEvent->event == AE_FASTZOMBIE_VEHICLE_LEAP ) - { - VehicleLeapAttack(); - return; - } - - // Die while doing an SS in a vehicle - if ( pEvent->event == AE_FASTZOMBIE_VEHICLE_SS_DIE ) - { - if ( IsInAVehicle() ) - { - // Get the vehicle's present speed as a baseline - Vector vecVelocity = vec3_origin; - CBaseEntity *pVehicle = m_PassengerBehavior.GetTargetVehicle(); - if ( pVehicle ) - { - pVehicle->GetVelocity( &vecVelocity, NULL ); - } - - // TODO: We need to make this content driven -- jdw - Vector vecForward, vecRight, vecUp; - GetVectors( &vecForward, &vecRight, &vecUp ); - - vecVelocity += ( vecForward * -2500.0f ) + ( vecRight * 200.0f ) + ( vecUp * 300 ); - - // Always kill - float flDamage = GetMaxHealth() + 10; - - // Take the damage and die - CTakeDamageInfo info( this, this, vecVelocity * 25.0f, WorldSpaceCenter(), flDamage, (DMG_CRUSH|DMG_VEHICLE) ); - TakeDamage( info ); - } - return; - } - -#endif // HL2_EPISODIC -//============================================================================= - - BaseClass::HandleAnimEvent( pEvent ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Jump at the enemy!! (stole this from the headcrab) -// -// -//----------------------------------------------------------------------------- -void CFastZombie::LeapAttack( void ) -{ - SetGroundEntity( NULL ); - - BeginAttackJump(); - - LeapAttackSound(); - - // - // Take him off ground so engine doesn't instantly reset FL_ONGROUND. - // - UTIL_SetOrigin( this, GetLocalOrigin() + Vector( 0 , 0 , 1 )); - - Vector vecJumpDir; - CBaseEntity *pEnemy = GetEnemy(); - - if ( pEnemy ) - { - Vector vecEnemyPos = pEnemy->WorldSpaceCenter(); - - float gravity = sv_gravity.GetFloat(); - if ( gravity <= 1 ) - { - gravity = 1; - } - - // - // How fast does the zombie need to travel to reach my enemy's eyes given gravity? - // - float height = ( vecEnemyPos.z - GetAbsOrigin().z ); - - if ( height < 16 ) - { - height = 16; - } - else if ( height > 120 ) - { - height = 120; - } - float speed = sqrt( 2 * gravity * height ); - float time = speed / gravity; - - // - // Scale the sideways velocity to get there at the right time - // - vecJumpDir = vecEnemyPos - GetAbsOrigin(); - vecJumpDir = vecJumpDir / time; - - // - // Speed to offset gravity at the desired height. - // - vecJumpDir.z = speed; - - // - // Don't jump too far/fast. - // -#define CLAMP 1000.0 - float distance = vecJumpDir.Length(); - if ( distance > CLAMP ) - { - vecJumpDir = vecJumpDir * ( CLAMP / distance ); - } - - // try speeding up a bit. - SetAbsVelocity( vecJumpDir ); - m_flNextAttack = gpGlobals->curtime + 2; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFastZombie::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_FASTZOMBIE_VERIFY_ATTACK: - // Simply ensure that the zombie still has a valid melee attack - if( HasCondition( COND_CAN_MELEE_ATTACK1 ) ) - { - TaskComplete(); - } - else - { - TaskFail(""); - } - break; - - case TASK_FASTZOMBIE_JUMP_BACK: - { - SetActivity( ACT_IDLE ); - - SetGroundEntity( NULL ); - - BeginAttackJump(); - - Vector forward; - AngleVectors( GetLocalAngles(), &forward ); - - // - // Take him off ground so engine doesn't instantly reset FL_ONGROUND. - // - UTIL_SetOrigin( this, GetLocalOrigin() + Vector( 0 , 0 , 1 )); - - ApplyAbsVelocityImpulse( forward * -200 + Vector( 0, 0, 200 ) ); - } - break; - - case TASK_FASTZOMBIE_UNSTICK_JUMP: - { - SetGroundEntity( NULL ); - - // Call begin attack jump. A little bit later if we fail to pathfind, we check - // this value to see if we just jumped. If so, we assume we've jumped - // to someplace that's not pathing friendly, and so must jump again to get out. - BeginAttackJump(); - - // - // Take him off ground so engine doesn't instantly reset FL_ONGROUND. - // - UTIL_SetOrigin( this, GetLocalOrigin() + Vector( 0 , 0 , 1 )); - - CBaseEntity *pEnemy = GetEnemy(); - Vector vecJumpDir; - - if ( GetActivity() == ACT_CLIMB_UP || GetActivity() == ACT_CLIMB_DOWN ) - { - // Jump off the pipe backwards! - Vector forward; - - GetVectors( &forward, NULL, NULL ); - - ApplyAbsVelocityImpulse( forward * -200 ); - } - else if( pEnemy ) - { - vecJumpDir = pEnemy->GetLocalOrigin() - GetLocalOrigin(); - VectorNormalize( vecJumpDir ); - vecJumpDir.z = 0; - - ApplyAbsVelocityImpulse( vecJumpDir * 300 + Vector( 0, 0, 200 ) ); - } - else - { - DevMsg("UNHANDLED CASE! Stuck Fast Zombie with no enemy!\n"); - } - } - break; - - case TASK_WAIT_FOR_MOVEMENT: - // If we're waiting for movement, that means that pathfinding succeeded, and - // we're about to be moving. So we aren't stuck. So clear this flag. - m_fJustJumped = false; - - BaseClass::StartTask( pTask ); - break; - - case TASK_FACE_ENEMY: - { - // We don't use the base class implementation of this, because GetTurnActivity - // stomps our landing scrabble animations (sjb) - Vector flEnemyLKP = GetEnemyLKP(); - GetMotor()->SetIdealYawToTarget( flEnemyLKP ); - } - break; - - case TASK_FASTZOMBIE_LAND_RECOVER: - { - // Set the ideal yaw - Vector flEnemyLKP = GetEnemyLKP(); - GetMotor()->SetIdealYawToTarget( flEnemyLKP ); - - // figure out which way to turn. - float flDeltaYaw = GetMotor()->DeltaIdealYaw(); - - if( flDeltaYaw < 0 ) - { - SetIdealActivity( (Activity)ACT_FASTZOMBIE_LAND_RIGHT ); - } - else - { - SetIdealActivity( (Activity)ACT_FASTZOMBIE_LAND_LEFT ); - } - - - TaskComplete(); - } - break; - - case TASK_RANGE_ATTACK1: - - // Make melee attacks impossible until we land! - m_flNextMeleeAttack = gpGlobals->curtime + 60; - - SetTouch( &CFastZombie::LeapAttackTouch ); - break; - - case TASK_FASTZOMBIE_DO_ATTACK: - SetActivity( (Activity)ACT_FASTZOMBIE_LEAP_SOAR ); - break; - - default: - BaseClass::StartTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFastZombie::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_FASTZOMBIE_JUMP_BACK: - case TASK_FASTZOMBIE_UNSTICK_JUMP: - if( GetFlags() & FL_ONGROUND ) - { - TaskComplete(); - } - break; - - case TASK_RANGE_ATTACK1: - if( ( GetFlags() & FL_ONGROUND ) || ( m_pfnTouch == NULL ) ) - { - // All done when you touch the ground, or if our touch function has somehow cleared. - TaskComplete(); - - // Allow melee attacks again. - m_flNextMeleeAttack = gpGlobals->curtime + 0.5; - return; - } - break; - - default: - BaseClass::RunTask( pTask ); - break; - } -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CFastZombie::TranslateSchedule( int scheduleType ) -{ - switch( scheduleType ) - { - case SCHED_RANGE_ATTACK1: - { - // Scream right now, cause in half a second, we're gonna jump!! - - if( !m_fHasScreamed ) - { - // Only play that over-the-top attack scream once per combat state. - EmitSound( "NPC_FastZombie.Scream" ); - m_fHasScreamed = true; - } - else - { - EmitSound( "NPC_FastZombie.RangeAttack" ); - } - - return SCHED_FASTZOMBIE_RANGE_ATTACK1; - } - break; - - case SCHED_MELEE_ATTACK1: - if ( m_fIsTorso == true ) - { - return SCHED_FASTZOMBIE_TORSO_MELEE_ATTACK1; - } - else - { - return SCHED_FASTZOMBIE_MELEE_ATTACK1; - } - break; - - case SCHED_FASTZOMBIE_UNSTICK_JUMP: - if ( GetActivity() == ACT_CLIMB_UP || GetActivity() == ACT_CLIMB_DOWN || GetActivity() == ACT_CLIMB_DISMOUNT ) - { - return SCHED_FASTZOMBIE_CLIMBING_UNSTICK_JUMP; - } - else - { - return SCHED_FASTZOMBIE_UNSTICK_JUMP; - } - break; - case SCHED_MOVE_TO_WEAPON_RANGE: - { - float flZDist = fabs( GetEnemy()->GetLocalOrigin().z - GetLocalOrigin().z ); - if ( flZDist > FASTZOMBIE_MAXLEAP_Z ) - return SCHED_CHASE_ENEMY; - else // fall through to default - return BaseClass::TranslateSchedule( scheduleType ); - break; - } - - default: - return BaseClass::TranslateSchedule( scheduleType ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -Activity CFastZombie::NPC_TranslateActivity( Activity baseAct ) -{ - if ( baseAct == ACT_CLIMB_DOWN ) - return ACT_CLIMB_UP; - - return BaseClass::NPC_TranslateActivity( baseAct ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CFastZombie::LeapAttackTouch( CBaseEntity *pOther ) -{ - if ( !pOther->IsSolid() ) - { - // Touching a trigger or something. - return; - } - - // Stop the zombie and knock the player back - Vector vecNewVelocity( 0, 0, GetAbsVelocity().z ); - SetAbsVelocity( vecNewVelocity ); - - Vector forward; - AngleVectors( GetLocalAngles(), &forward ); - QAngle qaPunch( 15, random->RandomInt(-5,5), random->RandomInt(-5,5) ); - Vector velocityPunch = forward * 5; - - ClawAttack( GetClawAttackRange(), 5, qaPunch, velocityPunch, ZOMBIE_BLOOD_BOTH_HANDS ); - - SetTouch( NULL ); -} - -//----------------------------------------------------------------------------- -// Purpose: Lets us know if we touch the player while we're climbing. -//----------------------------------------------------------------------------- -void CFastZombie::ClimbTouch( CBaseEntity *pOther ) -{ - if ( pOther->IsPlayer() ) - { - // If I hit the player, shove him aside. - Vector vecDir = pOther->WorldSpaceCenter() - WorldSpaceCenter(); - vecDir.z = 0.0; // planar - VectorNormalize( vecDir ); - - if( IsXbox() ) - { - vecDir *= 400.0f; - } - else - { - vecDir *= 200.0f; - } - - pOther->VelocityPunch( vecDir ); - - if ( GetActivity() != ACT_CLIMB_DISMOUNT || - ( pOther->GetGroundEntity() == NULL && - GetNavigator()->IsGoalActive() && - pOther->GetAbsOrigin().z - GetNavigator()->GetCurWaypointPos().z < -1.0 ) ) - { - SetCondition( COND_FASTZOMBIE_CLIMB_TOUCH ); - } - - SetTouch( NULL ); - } - else if ( dynamic_cast(pOther) ) - { - NPCPhysics_CreateSolver( this, pOther, true, 5.0 ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Shuts down our looping sounds. -//----------------------------------------------------------------------------- -void CFastZombie::StopLoopingSounds( void ) -{ - if ( m_pMoanSound ) - { - ENVELOPE_CONTROLLER.SoundDestroy( m_pMoanSound ); - m_pMoanSound = NULL; - } - - if ( m_pLayer2 ) - { - ENVELOPE_CONTROLLER.SoundDestroy( m_pLayer2 ); - m_pLayer2 = NULL; - } - - BaseClass::StopLoopingSounds(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Fast zombie cannot range attack when he's a torso! -//----------------------------------------------------------------------------- -void CFastZombie::BecomeTorso( const Vector &vecTorsoForce, const Vector &vecLegsForce ) -{ - CapabilitiesRemove( bits_CAP_INNATE_RANGE_ATTACK1 ); - CapabilitiesRemove( bits_CAP_MOVE_JUMP ); - CapabilitiesRemove( bits_CAP_MOVE_CLIMB ); - - ReleaseHeadcrab( EyePosition(), vecLegsForce * 0.5, true, true, true ); - - BaseClass::BecomeTorso( vecTorsoForce, vecLegsForce ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true if a reasonable jumping distance -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CFastZombie::IsJumpLegal(const Vector &startPos, const Vector &apex, const Vector &endPos) const -{ - const float MAX_JUMP_RISE = 220.0f; - const float MAX_JUMP_DISTANCE = 512.0f; - const float MAX_JUMP_DROP = 384.0f; - - if ( BaseClass::IsJumpLegal( startPos, apex, endPos, MAX_JUMP_RISE, MAX_JUMP_DROP, MAX_JUMP_DISTANCE ) ) - { - // Hang onto the jump distance. The AI is going to want it. - m_flJumpDist = (startPos - endPos).Length(); - - return true; - } - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -bool CFastZombie::MovementCost( int moveType, const Vector &vecStart, const Vector &vecEnd, float *pCost ) -{ - float delta = vecEnd.z - vecStart.z; - - float multiplier = 1; - if ( moveType == bits_CAP_MOVE_JUMP ) - { - multiplier = ( delta < 0 ) ? 0.5 : 1.5; - } - else if ( moveType == bits_CAP_MOVE_CLIMB ) - { - multiplier = ( delta > 0 ) ? 0.5 : 4.0; - } - - *pCost *= multiplier; - - return ( multiplier != 1 ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -bool CFastZombie::ShouldFailNav( bool bMovementFailed ) -{ - if ( !BaseClass::ShouldFailNav( bMovementFailed ) ) - { - DevMsg( 2, "Fast zombie in scripted sequence probably hit bad node configuration at %s\n", VecToString( GetAbsOrigin() ) ); - - if ( GetNavigator()->GetPath()->CurWaypointNavType() == NAV_JUMP && GetNavigator()->RefindPathToGoal( false ) ) - { - return false; - } - DevMsg( 2, "Fast zombie failed to get to scripted sequence\n" ); - } - - return true; -} - - -//--------------------------------------------------------- -// Purpose: Notifier that lets us know when the fast -// zombie has hit the apex of a navigational jump. -//--------------------------------------------------------- -void CFastZombie::OnNavJumpHitApex( void ) -{ - m_fHitApex = true; // stop subsequent notifications -} - -//--------------------------------------------------------- -// Purpose: Overridden to detect when the zombie goes into -// and out of his climb state and his navigation -// jump state. -//--------------------------------------------------------- -void CFastZombie::OnChangeActivity( Activity NewActivity ) -{ - if ( NewActivity == ACT_FASTZOMBIE_FRENZY ) - { - // Scream!!!! - EmitSound( "NPC_FastZombie.Frenzy" ); - SetPlaybackRate( random->RandomFloat( .9, 1.1 ) ); - } - - if( NewActivity == ACT_JUMP ) - { - BeginNavJump(); - } - else if( GetActivity() == ACT_JUMP ) - { - EndNavJump(); - } - - if ( NewActivity == ACT_LAND ) - { - m_flNextAttack = gpGlobals->curtime + 1.0; - } - - if ( NewActivity == ACT_GLIDE ) - { - // Started a jump. - BeginNavJump(); - } - else if ( GetActivity() == ACT_GLIDE ) - { - // Landed a jump - EndNavJump(); - - if ( m_pMoanSound ) - ENVELOPE_CONTROLLER.SoundChangePitch( m_pMoanSound, FASTZOMBIE_MIN_PITCH, 0.3 ); - } - - if ( NewActivity == ACT_CLIMB_UP ) - { - // Started a climb! - if ( m_pMoanSound ) - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pMoanSound, 0.0, 0.2 ); - - SetTouch( &CFastZombie::ClimbTouch ); - } - else if ( GetActivity() == ACT_CLIMB_DISMOUNT || ( GetActivity() == ACT_CLIMB_UP && NewActivity != ACT_CLIMB_DISMOUNT ) ) - { - // Ended a climb - if ( m_pMoanSound ) - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pMoanSound, 1.0, 0.2 ); - - SetTouch( NULL ); - } - - BaseClass::OnChangeActivity( NewActivity ); -} - - -//========================================================= -// -//========================================================= -int CFastZombie::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ) -{ - if ( m_fJustJumped ) - { - // Assume we failed cause we jumped to a bad place. - m_fJustJumped = false; - return SCHED_FASTZOMBIE_UNSTICK_JUMP; - } - - return BaseClass::SelectFailSchedule( failedSchedule, failedTask, taskFailCode ); -} - -//========================================================= -// Purpose: Do some record keeping for jumps made for -// navigational purposes (i.e., not attack jumps) -//========================================================= -void CFastZombie::BeginNavJump( void ) -{ - m_fIsNavJumping = true; - m_fHitApex = false; - - ENVELOPE_CONTROLLER.SoundPlayEnvelope( m_pLayer2, SOUNDCTRL_CHANGE_VOLUME, envFastZombieVolumeJump, ARRAYSIZE(envFastZombieVolumeJump) ); -} - -//========================================================= -// -//========================================================= -void CFastZombie::EndNavJump( void ) -{ - m_fIsNavJumping = false; - m_fHitApex = false; -} - -//========================================================= -// -//========================================================= -void CFastZombie::BeginAttackJump( void ) -{ - // Set this to true. A little bit later if we fail to pathfind, we check - // this value to see if we just jumped. If so, we assume we've jumped - // to someplace that's not pathing friendly, and so must jump again to get out. - m_fJustJumped = true; - - m_flJumpStartAltitude = GetLocalOrigin().z; -} - -//========================================================= -// -//========================================================= -void CFastZombie::EndAttackJump( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFastZombie::BuildScheduleTestBits( void ) -{ - // FIXME: This is probably the desired call to make, but it opts into an untested base class path, we'll need to - // revisit this and figure out if we want that. -- jdw - // BaseClass::BuildScheduleTestBits(); - // - // For now, make sure our active behavior gets a chance to add its own bits - if ( GetRunningBehavior() ) - GetRunningBehavior()->BridgeBuildScheduleTestBits(); - -#ifdef HL2_EPISODIC - SetCustomInterruptCondition( COND_PROVOKED ); -#endif // HL2_EPISODIC - - // Any schedule that makes us climb should break if we touch player - if ( GetActivity() == ACT_CLIMB_UP || GetActivity() == ACT_CLIMB_DOWN || GetActivity() == ACT_CLIMB_DISMOUNT) - { - SetCustomInterruptCondition( COND_FASTZOMBIE_CLIMB_TOUCH ); - } - else - { - ClearCustomInterruptCondition( COND_FASTZOMBIE_CLIMB_TOUCH ); - } -} - -//========================================================= -// -//========================================================= -void CFastZombie::OnStateChange( NPC_STATE OldState, NPC_STATE NewState ) -{ - if( NewState == NPC_STATE_COMBAT ) - { - SetAngrySoundState(); - } - else if( (m_pMoanSound) && ( NewState == NPC_STATE_IDLE || NewState == NPC_STATE_ALERT ) ) ///!!!HACKHACK - sjb - { - // Don't make this sound while we're slumped - if ( IsSlumped() == false ) - { - // Set it up so that if the zombie goes into combat state sometime down the road - // that he'll be able to scream. - m_fHasScreamed = false; - - SetIdleSoundState(); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CFastZombie::Event_Killed( const CTakeDamageInfo &info ) -{ - // Shut up my screaming sounds. - CPASAttenuationFilter filter( this ); - EmitSound( filter, entindex(), "NPC_FastZombie.NoSound" ); - - CTakeDamageInfo dInfo = info; - -#if 0 - - // Become a server-side ragdoll and create a constraint at the hand - if ( m_PassengerBehavior.GetPassengerState() == PASSENGER_STATE_INSIDE ) - { - IPhysicsObject *pVehiclePhys = m_PassengerBehavior.GetTargetVehicle()->GetServerVehicle()->GetVehicleEnt()->VPhysicsGetObject(); - CBaseAnimating *pVehicleAnimating = m_PassengerBehavior.GetTargetVehicle()->GetServerVehicle()->GetVehicleEnt()->GetBaseAnimating(); - int nRightHandBone = 31;//GetBaseAnimating()->LookupBone( "ValveBiped.Bip01_R_Finger2" ); - Vector vecRightHandPos; - QAngle vecRightHandAngle; - GetAttachment( LookupAttachment( "Blood_Right" ), vecRightHandPos, vecRightHandAngle ); - //CTakeDamageInfo dInfo( GetEnemy(), GetEnemy(), RandomVector( -200, 200 ), WorldSpaceCenter(), 50.0f, DMG_CRUSH ); - dInfo.SetDamageType( info.GetDamageType() | DMG_REMOVENORAGDOLL ); - dInfo.ScaleDamageForce( 10.0f ); - CBaseEntity *pRagdoll = CreateServerRagdoll( GetBaseAnimating(), 0, info, COLLISION_GROUP_DEBRIS ); - - /* - GetBaseAnimating()->GetBonePosition( nRightHandBone, vecRightHandPos, vecRightHandAngle ); - - CBaseEntity *pRagdoll = CreateServerRagdollAttached( GetBaseAnimating(), - vec3_origin, - -1, - COLLISION_GROUP_DEBRIS, - pVehiclePhys, - pVehicleAnimating, - 0, - vecRightHandPos, - nRightHandBone, - vec3_origin );*/ - - } -#endif - - BaseClass::Event_Killed( dInfo ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CFastZombie::ShouldBecomeTorso( const CTakeDamageInfo &info, float flDamageThreshold ) -{ - if( m_fIsTorso ) - { - // Already split. - return false; - } - - // Break in half IF: - // - // Take half or more of max health in DMG_BLAST - if( (info.GetDamageType() & DMG_BLAST) && m_iHealth <= 0 ) - { - return true; - } - - return false; -} - -//============================================================================= -#ifdef HL2_EPISODIC - -//----------------------------------------------------------------------------- -// Purpose: Add the passenger behavior to our repertoire -//----------------------------------------------------------------------------- -bool CFastZombie::CreateBehaviors( void ) -{ - AddBehavior( &m_PassengerBehavior ); - - return BaseClass::CreateBehaviors(); -} - -//----------------------------------------------------------------------------- -// Purpose: Get on the vehicle! -//----------------------------------------------------------------------------- -void CFastZombie::InputAttachToVehicle( inputdata_t &inputdata ) -{ - // Interrupt us - SetCondition( COND_PROVOKED ); - - // Find the target vehicle - CBaseEntity *pEntity = FindNamedEntity( inputdata.value.String() ); - CPropJeepEpisodic *pVehicle = dynamic_cast(pEntity); - - // Get in the car if it's valid - if ( pVehicle && CanEnterVehicle( pVehicle ) ) - { - // Set her into a "passenger" behavior - m_PassengerBehavior.Enable( pVehicle ); - m_PassengerBehavior.AttachToVehicle(); - } - - RemoveSpawnFlags( SF_NPC_GAG ); -} - -//----------------------------------------------------------------------------- -// Purpose: Passed along from the vehicle's callback list -//----------------------------------------------------------------------------- -void CFastZombie::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) -{ - // Only do the override while riding on a vehicle - if ( m_PassengerBehavior.CanSelectSchedule() && m_PassengerBehavior.GetPassengerState() != PASSENGER_STATE_OUTSIDE ) - { - int damageType = 0; - float flDamage = CalculatePhysicsImpactDamage( index, pEvent, gZombiePassengerImpactDamageTable, 1.0, true, damageType ); - - if ( flDamage > 0 ) - { - Vector damagePos; - pEvent->pInternalData->GetContactPoint( damagePos ); - Vector damageForce = pEvent->postVelocity[index] * pEvent->pObjects[index]->GetMass(); - CTakeDamageInfo info( this, this, damageForce, damagePos, flDamage, (damageType|DMG_VEHICLE) ); - TakeDamage( info ); - } - return; - } - - BaseClass::VPhysicsCollision( index, pEvent ); -} - -//----------------------------------------------------------------------------- -// Purpose: FIXME: Fold this into LeapAttack using different jump targets! -//----------------------------------------------------------------------------- -void CFastZombie::VehicleLeapAttack( void ) -{ - CBaseEntity *pEnemy = GetEnemy(); - if ( pEnemy == NULL ) - return; - - Vector vecEnemyPos; - UTIL_PredictedPosition( pEnemy, 1.0f, &vecEnemyPos ); - - // Move - SetGroundEntity( NULL ); - BeginAttackJump(); - LeapAttackSound(); - - // Take him off ground so engine doesn't instantly reset FL_ONGROUND. - UTIL_SetOrigin( this, GetLocalOrigin() + Vector( 0 , 0 , 1 )); - - // FIXME: This should be the exact position we'll enter at, but this approximates it generally - //vecEnemyPos[2] += 16; - - Vector vecMins = GetHullMins(); - Vector vecMaxs = GetHullMaxs(); - Vector vecJumpDir = VecCheckToss( this, GetAbsOrigin(), vecEnemyPos, 0.1f, 1.0f, false, &vecMins, &vecMaxs ); - - SetAbsVelocity( vecJumpDir ); - m_flNextAttack = gpGlobals->curtime + 2.0f; - SetTouch( &CFastZombie::VehicleLeapAttackTouch ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CFastZombie::CanEnterVehicle( CPropJeepEpisodic *pVehicle ) -{ - if ( pVehicle == NULL ) - return false; - - return pVehicle->NPC_CanEnterVehicle( this, false ); -} - -//----------------------------------------------------------------------------- -// Purpose: FIXME: Move into behavior? -// Input : *pOther - -//----------------------------------------------------------------------------- -void CFastZombie::VehicleLeapAttackTouch( CBaseEntity *pOther ) -{ - if ( pOther->GetServerVehicle() ) - { - m_PassengerBehavior.AttachToVehicle(); - - // HACK: Stop us cold - SetLocalVelocity( vec3_origin ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Determine whether we're in a vehicle or not -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CFastZombie::IsInAVehicle( void ) -{ - // Must be active and getting in/out of vehicle - if ( m_PassengerBehavior.IsEnabled() && m_PassengerBehavior.GetPassengerState() != PASSENGER_STATE_OUTSIDE ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Override our efficiency so that we don't jitter when we're in the middle -// of our enter/exit animations. -// Input : bInPVS - Whether we're in the PVS or not -//----------------------------------------------------------------------------- -void CFastZombie::UpdateEfficiency( bool bInPVS ) -{ - // If we're transitioning and in the PVS, we override our efficiency - if ( IsInAVehicle() && bInPVS ) - { - PassengerState_e nState = m_PassengerBehavior.GetPassengerState(); - if ( nState == PASSENGER_STATE_ENTERING || nState == PASSENGER_STATE_EXITING ) - { - SetEfficiency( AIE_NORMAL ); - return; - } - } - - // Do the default behavior - BaseClass::UpdateEfficiency( bInPVS ); -} - -#endif // HL2_EPISODIC -//============================================================================= - -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC( npc_fastzombie, CFastZombie ) - - DECLARE_ACTIVITY( ACT_FASTZOMBIE_LEAP_SOAR ) - DECLARE_ACTIVITY( ACT_FASTZOMBIE_LEAP_STRIKE ) - DECLARE_ACTIVITY( ACT_FASTZOMBIE_LAND_RIGHT ) - DECLARE_ACTIVITY( ACT_FASTZOMBIE_LAND_LEFT ) - DECLARE_ACTIVITY( ACT_FASTZOMBIE_FRENZY ) - DECLARE_ACTIVITY( ACT_FASTZOMBIE_BIG_SLASH ) - - DECLARE_TASK( TASK_FASTZOMBIE_DO_ATTACK ) - DECLARE_TASK( TASK_FASTZOMBIE_LAND_RECOVER ) - DECLARE_TASK( TASK_FASTZOMBIE_UNSTICK_JUMP ) - DECLARE_TASK( TASK_FASTZOMBIE_JUMP_BACK ) - DECLARE_TASK( TASK_FASTZOMBIE_VERIFY_ATTACK ) - - DECLARE_CONDITION( COND_FASTZOMBIE_CLIMB_TOUCH ) - - //Adrian: events go here - DECLARE_ANIMEVENT( AE_FASTZOMBIE_LEAP ) - DECLARE_ANIMEVENT( AE_FASTZOMBIE_GALLOP_LEFT ) - DECLARE_ANIMEVENT( AE_FASTZOMBIE_GALLOP_RIGHT ) - DECLARE_ANIMEVENT( AE_FASTZOMBIE_CLIMB_LEFT ) - DECLARE_ANIMEVENT( AE_FASTZOMBIE_CLIMB_RIGHT ) - -#ifdef HL2_EPISODIC - // FIXME: Move! - DECLARE_ANIMEVENT( AE_PASSENGER_PHYSICS_PUSH ) - DECLARE_ANIMEVENT( AE_FASTZOMBIE_VEHICLE_LEAP ) - DECLARE_ANIMEVENT( AE_FASTZOMBIE_VEHICLE_SS_DIE ) -#endif // HL2_EPISODIC - - //========================================================= - // - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_FASTZOMBIE_RANGE_ATTACK1, - - " Tasks" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_RANGE_ATTACK1" - " TASK_SET_ACTIVITY ACTIVITY:ACT_FASTZOMBIE_LEAP_STRIKE" - " TASK_RANGE_ATTACK1 0" - " TASK_WAIT 0.1" - " TASK_FASTZOMBIE_LAND_RECOVER 0" // essentially just figure out which way to turn. - " TASK_FACE_ENEMY 0" - " " - " Interrupts" - ) - - //========================================================= - // I have landed somewhere that's pathfinding-unfriendly - // just try to jump out. - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_FASTZOMBIE_UNSTICK_JUMP, - - " Tasks" - " TASK_FASTZOMBIE_UNSTICK_JUMP 0" - " " - " Interrupts" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_FASTZOMBIE_CLIMBING_UNSTICK_JUMP, - - " Tasks" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_FASTZOMBIE_UNSTICK_JUMP 0" - " " - " Interrupts" - ) - - //========================================================= - // > Melee_Attack1 - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_FASTZOMBIE_MELEE_ATTACK1, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_MELEE_ATTACK1 0" - " TASK_MELEE_ATTACK1 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_FASTZOMBIE_FRENZY" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY" - " TASK_FASTZOMBIE_VERIFY_ATTACK 0" - " TASK_PLAY_SEQUENCE_FACE_ENEMY ACTIVITY:ACT_FASTZOMBIE_BIG_SLASH" - - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_ENEMY_OCCLUDED" - ); - - //========================================================= - // > Melee_Attack1 - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_FASTZOMBIE_TORSO_MELEE_ATTACK1, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_MELEE_ATTACK1 0" - " TASK_MELEE_ATTACK1 0" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY" - " TASK_FASTZOMBIE_VERIFY_ATTACK 0" - - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_ENEMY_OCCLUDED" - ); - -AI_END_CUSTOM_NPC() - - diff --git a/game/server/hl2/npc_fisherman.cpp b/game/server/hl2/npc_fisherman.cpp deleted file mode 100644 index 819c70580..000000000 --- a/game/server/hl2/npc_fisherman.cpp +++ /dev/null @@ -1,245 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "ai_default.h" -#include "ai_task.h" -#include "ai_schedule.h" -#include "ai_node.h" -#include "ai_hull.h" -#include "ai_hint.h" -#include "ai_squad.h" -#include "ai_senses.h" -#include "ai_navigator.h" -#include "ai_motor.h" -#include "ai_behavior.h" -#include "ai_baseactor.h" -#include "ai_behavior_lead.h" -#include "ai_behavior_follow.h" -#include "ai_behavior_standoff.h" -#include "ai_behavior_assault.h" -#include "npc_playercompanion.h" -#include "soundent.h" -#include "game.h" -#include "npcevent.h" -#include "entitylist.h" -#include "activitylist.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "sceneentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define FISHERMAN_MODEL "models/lostcoast/fisherman/fisherman.mdl" - -//========================================================= -// Fisherman activities -//========================================================= - -Activity ACT_FISHERMAN_HAT_UP; -Activity ACT_FISHERMAN_HAT_DOWN; - -//========================================================= -// animation events -//========================================================= -int AE_FISHERMAN_HAT_UP; -int AE_FISHERMAN_HAT_DOWN; -int AE_FISHERMAN_HAT_ON; -int AE_FISHERMAN_HAT_OFF; - -//--------------------------------------------------------- -// -//--------------------------------------------------------- - -class CNPC_Fisherman : public CNPC_PlayerCompanion -{ -public: - DECLARE_CLASS( CNPC_Fisherman, CNPC_PlayerCompanion ); - //DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - virtual void Precache() - { - // Prevents a warning - SelectModel( ); - BaseClass::Precache(); - - PrecacheScriptSound( "NPC_Fisherman.FootstepLeft" ); - PrecacheScriptSound( "NPC_Fisherman.FootstepRight" ); - PrecacheScriptSound( "NPC_Fisherman.Die" ); - - PrecacheInstancedScene( "scenes/Expressions/FishermanIdle.vcd" ); - PrecacheInstancedScene( "scenes/Expressions/FishermanAlert.vcd" ); - PrecacheInstancedScene( "scenes/Expressions/FishermanCombat.vcd" ); - } - - virtual void Activate() - { - BaseClass::Activate(); - - if (m_iHatState == -1) - { - m_iHatState = ACT_FISHERMAN_HAT_DOWN; - } - - // allocate layer, start with the hat down - m_iHatLayer = AddGesture( (Activity)m_iHatState, false ); - } - - void Spawn( void ); - void SelectModel(); - Class_T Classify( void ); - - void HandleAnimEvent( animevent_t *pEvent ); - - bool ShouldLookForBetterWeapon() { return false; } - virtual bool IgnorePlayerPushing( void ) { return true; } - void DeathSound( const CTakeDamageInfo &info ); - - int m_iHatLayer; // overlay layer for hat, don't save/restore. - int m_iHatState; // hat state, persistant. - - DEFINE_CUSTOM_AI; -}; - -LINK_ENTITY_TO_CLASS( npc_fisherman, CNPC_Fisherman ); - -//--------------------------------------------------------- -// -//--------------------------------------------------------- -/* -IMPLEMENT_SERVERCLASS_ST(CNPC_Fisherman, DT_NPC_Fisherman) -END_SEND_TABLE() -*/ - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CNPC_Fisherman ) - - // DEFINE_FIELD( m_iHatLayer, FIELD_INT ), - DEFINE_FIELD( m_iHatState, FIELD_INTEGER ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Fisherman::SelectModel() -{ - SetModelName( AllocPooledString( FISHERMAN_MODEL ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Fisherman::Spawn( void ) -{ - m_iHatLayer = -1; - m_iHatState = -1; - - Precache(); - - m_iHealth = 80; - -// m_iszIdleExpression = MAKE_STRING("scenes/Expressions/FishermanIdle.vcd"); -// m_iszAlertExpression = MAKE_STRING("scenes/Expressions/FishermanAlert.vcd"); -// m_iszCombatExpression = MAKE_STRING("scenes/Expressions/FishermanCombat.vcd"); - - BaseClass::Spawn(); - - AddEFlags( EFL_NO_DISSOLVE | EFL_NO_MEGAPHYSCANNON_RAGDOLL | EFL_NO_PHYSCANNON_INTERACTION ); - - NPCInit(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : -//----------------------------------------------------------------------------- -Class_T CNPC_Fisherman::Classify( void ) -{ - return CLASS_PLAYER_ALLY_VITAL; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Fisherman::HandleAnimEvent( animevent_t *pEvent ) -{ - if ( pEvent->event == NPC_EVENT_LEFTFOOT ) - { - EmitSound( "NPC_Fisherman.FootstepLeft", pEvent->eventtime ); - } - else if ( pEvent->event == NPC_EVENT_RIGHTFOOT ) - { - EmitSound( "NPC_Fisherman.FootstepRight", pEvent->eventtime ); - } - else if ( pEvent->event == AE_FISHERMAN_HAT_UP ) - { - if (m_iHatLayer != -1) - { - RemoveLayer( m_iHatLayer, 0.2, 0.2 ); - m_iHatLayer = -1; - } - - m_iHatState = ACT_FISHERMAN_HAT_UP; - m_iHatLayer = AddGesture( (Activity)m_iHatState, false ); - } - else if ( pEvent->event == AE_FISHERMAN_HAT_DOWN ) - { - if (m_iHatLayer != -1) - { - RemoveLayer( m_iHatLayer, 0.2, 0.2 ); - m_iHatLayer = -1; - } - - m_iHatState = ACT_FISHERMAN_HAT_DOWN; - m_iHatLayer = AddGesture( (Activity)m_iHatState, false ); - } - else if ( pEvent->event == AE_FISHERMAN_HAT_ON ) - { - m_iHatLayer = AddGesture( (Activity)m_iHatState, false ); - } - else if ( pEvent->event == AE_FISHERMAN_HAT_OFF ) - { - if (m_iHatLayer != -1) - { - RemoveLayer( m_iHatLayer, 0.2, 0.2 ); - m_iHatLayer = -1; - } - } - else - { - BaseClass::HandleAnimEvent( pEvent ); - } -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_Fisherman::DeathSound( const CTakeDamageInfo &info ) -{ - // Sentences don't play on dead NPCs - SentenceStop(); -} - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC( npc_fisherman, CNPC_Fisherman ) - - DECLARE_ACTIVITY( ACT_FISHERMAN_HAT_UP ) - DECLARE_ACTIVITY( ACT_FISHERMAN_HAT_DOWN ) - - DECLARE_ANIMEVENT( AE_FISHERMAN_HAT_UP ) - DECLARE_ANIMEVENT( AE_FISHERMAN_HAT_DOWN ) - DECLARE_ANIMEVENT( AE_FISHERMAN_HAT_ON ) - DECLARE_ANIMEVENT( AE_FISHERMAN_HAT_OFF ) - -AI_END_CUSTOM_NPC() diff --git a/game/server/hl2/npc_gman.cpp b/game/server/hl2/npc_gman.cpp deleted file mode 100644 index a8551976a..000000000 --- a/game/server/hl2/npc_gman.cpp +++ /dev/null @@ -1,165 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: The G-Man, misunderstood servant of the people -// -// $NoKeywords: $ -// -//=============================================================================// - - -//----------------------------------------------------------------------------- -// Generic NPC - purely for scripted sequence work. -//----------------------------------------------------------------------------- - -#include "cbase.h" -#include "npcevent.h" -#include "ai_basenpc.h" -#include "ai_hull.h" -#include "ai_behavior_follow.h" -#include "ai_playerally.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// NPC's Anim Events Go Here -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CNPC_GMan : public CAI_PlayerAlly -{ -public: - DECLARE_CLASS( CNPC_GMan, CAI_PlayerAlly ); - DECLARE_DATADESC(); - - void Spawn( void ); - void Precache( void ); - Class_T Classify ( void ); - void HandleAnimEvent( animevent_t *pEvent ); - virtual Disposition_t IRelationType(CBaseEntity *pTarget); - int GetSoundInterests ( void ); - bool CreateBehaviors( void ); - int SelectSchedule( void ); - -private: - CAI_FollowBehavior m_FollowBehavior; -}; - -LINK_ENTITY_TO_CLASS( npc_gman, CNPC_GMan ); - -BEGIN_DATADESC( CNPC_GMan ) -// (auto saved by AI) -// DEFINE_FIELD( m_FollowBehavior, FIELD_EMBEDDED ), (auto saved by AI) -END_DATADESC() - -//----------------------------------------------------------------------------- -// Classify - indicates this NPC's place in the -// relationship table. -//----------------------------------------------------------------------------- -Class_T CNPC_GMan::Classify ( void ) -{ - return CLASS_PLAYER_ALLY_VITAL; -} - - - -//----------------------------------------------------------------------------- -// HandleAnimEvent - catches the NPC-specific messages -// that occur when tagged animation frames are played. -//----------------------------------------------------------------------------- -void CNPC_GMan::HandleAnimEvent( animevent_t *pEvent ) -{ - switch( pEvent->event ) - { - case 1: - default: - BaseClass::HandleAnimEvent( pEvent ); - break; - } -} - -//----------------------------------------------------------------------------- -// GetSoundInterests - generic NPC can't hear. -//----------------------------------------------------------------------------- -int CNPC_GMan::GetSoundInterests ( void ) -{ - return 0; -} - - -//----------------------------------------------------------------------------- -// Spawn -//----------------------------------------------------------------------------- -void CNPC_GMan::Spawn() -{ - Precache(); - - BaseClass::Spawn(); - - SetModel( "models/gman.mdl" ); - - SetHullType(HULL_HUMAN); - SetHullSizeNormal(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - SetBloodColor( BLOOD_COLOR_RED ); - m_iHealth = 8; - m_flFieldOfView = 0.5;// indicates the width of this NPC's forward view cone ( as a dotproduct result ) - m_NPCState = NPC_STATE_NONE; - SetImpactEnergyScale( 0.0f ); // no physics damage on the gman - - CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_OPEN_DOORS | bits_CAP_ANIMATEDFACE | bits_CAP_TURN_HEAD ); - CapabilitiesAdd( bits_CAP_FRIENDLY_DMG_IMMUNE ); - AddEFlags( EFL_NO_DISSOLVE | EFL_NO_MEGAPHYSCANNON_RAGDOLL ); - - NPCInit(); -} - -//----------------------------------------------------------------------------- -// Precache - precaches all resources this NPC needs -//----------------------------------------------------------------------------- -void CNPC_GMan::Precache() -{ - PrecacheModel( "models/gman.mdl" ); - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// The G-Man isn't scared of anything. -//----------------------------------------------------------------------------- -Disposition_t CNPC_GMan::IRelationType(CBaseEntity *pTarget) -{ - return D_NU; -} - - -//========================================================= -// Purpose: -//========================================================= -bool CNPC_GMan::CreateBehaviors() -{ - AddBehavior( &m_FollowBehavior ); - - return BaseClass::CreateBehaviors(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_GMan::SelectSchedule( void ) -{ - if ( !BehaviorSelectSchedule() ) - { - } - - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -// AI Schedules Specific to this NPC -//----------------------------------------------------------------------------- diff --git a/game/server/hl2/npc_headcrab.cpp b/game/server/hl2/npc_headcrab.cpp deleted file mode 100644 index cc88fb429..000000000 --- a/game/server/hl2/npc_headcrab.cpp +++ /dev/null @@ -1,3987 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements the headcrab, a tiny, jumpy alien parasite. -// -// TODO: make poison headcrab hop in response to nearby bullet impacts? -// -//=============================================================================// - -#include "cbase.h" -#include "game.h" -#include "antlion_dust.h" -#include "ai_default.h" -#include "ai_schedule.h" -#include "ai_hint.h" -#include "ai_hull.h" -#include "ai_navigator.h" -#include "ai_moveprobe.h" -#include "ai_memory.h" -#include "bitstring.h" -#include "hl2_shareddefs.h" -#include "npcevent.h" -#include "soundent.h" -#include "npc_headcrab.h" -#include "gib.h" -#include "ai_interactions.h" -#include "ndebugoverlay.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "movevars_shared.h" -#include "world.h" -#include "npc_bullseye.h" -#include "physics_npc_solver.h" -#include "hl2_gamerules.h" -#include "decals.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define CRAB_ATTN_IDLE (float)1.5 -#define HEADCRAB_GUTS_GIB_COUNT 1 -#define HEADCRAB_LEGS_GIB_COUNT 3 -#define HEADCRAB_ALL_GIB_COUNT 5 - -#define HEADCRAB_RUNMODE_ACCELERATE 1 -#define HEADCRAB_RUNMODE_IDLE 2 -#define HEADCRAB_RUNMODE_DECELERATE 3 -#define HEADCRAB_RUNMODE_FULLSPEED 4 -#define HEADCRAB_RUNMODE_PAUSE 5 - -#define HEADCRAB_RUN_MINSPEED 0.5 -#define HEADCRAB_RUN_MAXSPEED 1.0 - -const float HEADCRAB_BURROWED_FOV = -1.0f; -const float HEADCRAB_UNBURROWED_FOV = 0.5f; - -#define HEADCRAB_IGNORE_WORLD_COLLISION_TIME 0.5 - -const int HEADCRAB_MIN_JUMP_DIST = 48; -const int HEADCRAB_MAX_JUMP_DIST = 256; - -#define HEADCRAB_BURROW_POINT_SEARCH_RADIUS 256.0 - -// Debugging -#define HEADCRAB_DEBUG_HIDING 1 - -#define HEADCRAB_BURN_SOUND_FREQUENCY 10 - -ConVar g_debug_headcrab( "g_debug_headcrab", "0", FCVAR_CHEAT ); - -//------------------------------------ -// Spawnflags -//------------------------------------ -#define SF_HEADCRAB_START_HIDDEN (1 << 16) -#define SF_HEADCRAB_START_HANGING (1 << 17) - - -//----------------------------------------------------------------------------- -// Think contexts. -//----------------------------------------------------------------------------- -static const char *s_pPitchContext = "PitchContext"; - - -//----------------------------------------------------------------------------- -// Animation events. -//----------------------------------------------------------------------------- -int AE_HEADCRAB_JUMPATTACK; -int AE_HEADCRAB_JUMP_TELEGRAPH; -int AE_POISONHEADCRAB_FLINCH_HOP; -int AE_POISONHEADCRAB_FOOTSTEP; -int AE_POISONHEADCRAB_THREAT_SOUND; -int AE_HEADCRAB_BURROW_IN; -int AE_HEADCRAB_BURROW_IN_FINISH; -int AE_HEADCRAB_BURROW_OUT; -int AE_HEADCRAB_CEILING_DETACH; - - -//----------------------------------------------------------------------------- -// Custom schedules. -//----------------------------------------------------------------------------- -enum -{ - SCHED_HEADCRAB_RANGE_ATTACK1 = LAST_SHARED_SCHEDULE, - SCHED_HEADCRAB_WAKE_ANGRY, - SCHED_HEADCRAB_WAKE_ANGRY_NO_DISPLAY, - SCHED_HEADCRAB_DROWN, - SCHED_HEADCRAB_FAIL_DROWN, - SCHED_HEADCRAB_AMBUSH, - SCHED_HEADCRAB_HOP_RANDOMLY, // get off something you're not supposed to be on. - SCHED_HEADCRAB_BARNACLED, - SCHED_HEADCRAB_UNHIDE, - SCHED_HEADCRAB_HARASS_ENEMY, - SCHED_HEADCRAB_FALL_TO_GROUND, - SCHED_HEADCRAB_RUN_TO_BURROW_IN, - SCHED_HEADCRAB_RUN_TO_SPECIFIC_BURROW, - SCHED_HEADCRAB_BURROW_IN, - SCHED_HEADCRAB_BURROW_WAIT, - SCHED_HEADCRAB_BURROW_OUT, - SCHED_HEADCRAB_WAIT_FOR_CLEAR_UNBURROW, - SCHED_HEADCRAB_CRAWL_FROM_CANISTER, - - SCHED_FAST_HEADCRAB_RANGE_ATTACK1, - - SCHED_HEADCRAB_CEILING_WAIT, - SCHED_HEADCRAB_CEILING_DROP, -}; - - -//========================================================= -// tasks -//========================================================= -enum -{ - TASK_HEADCRAB_HOP_ASIDE = LAST_SHARED_TASK, - TASK_HEADCRAB_HOP_OFF_NPC, - TASK_HEADCRAB_DROWN, - TASK_HEADCRAB_WAIT_FOR_BARNACLE_KILL, - TASK_HEADCRAB_UNHIDE, - TASK_HEADCRAB_HARASS_HOP, - TASK_HEADCRAB_FIND_BURROW_IN_POINT, - TASK_HEADCRAB_BURROW, - TASK_HEADCRAB_UNBURROW, - TASK_HEADCRAB_BURROW_WAIT, - TASK_HEADCRAB_CHECK_FOR_UNBURROW, - TASK_HEADCRAB_JUMP_FROM_CANISTER, - TASK_HEADCRAB_CLIMB_FROM_CANISTER, - - TASK_HEADCRAB_CEILING_WAIT, - TASK_HEADCRAB_CEILING_POSITION, - TASK_HEADCRAB_CEILING_DETACH, - TASK_HEADCRAB_CEILING_FALL, - TASK_HEADCRAB_CEILING_LAND, -}; - - -//========================================================= -// conditions -//========================================================= -enum -{ - COND_HEADCRAB_IN_WATER = LAST_SHARED_CONDITION, - COND_HEADCRAB_ILLEGAL_GROUNDENT, - COND_HEADCRAB_BARNACLED, - COND_HEADCRAB_UNHIDE, -}; - -//========================================================= -// private activities -//========================================================= -int ACT_HEADCRAB_THREAT_DISPLAY; -int ACT_HEADCRAB_HOP_LEFT; -int ACT_HEADCRAB_HOP_RIGHT; -int ACT_HEADCRAB_DROWN; -int ACT_HEADCRAB_BURROW_IN; -int ACT_HEADCRAB_BURROW_OUT; -int ACT_HEADCRAB_BURROW_IDLE; -int ACT_HEADCRAB_CRAWL_FROM_CANISTER_LEFT; -int ACT_HEADCRAB_CRAWL_FROM_CANISTER_CENTER; -int ACT_HEADCRAB_CRAWL_FROM_CANISTER_RIGHT; -int ACT_HEADCRAB_CEILING_IDLE; -int ACT_HEADCRAB_CEILING_DETACH; -int ACT_HEADCRAB_CEILING_FALL; -int ACT_HEADCRAB_CEILING_LAND; - - -//----------------------------------------------------------------------------- -// Skill settings. -//----------------------------------------------------------------------------- -ConVar sk_headcrab_health( "sk_headcrab_health","0"); -ConVar sk_headcrab_fast_health( "sk_headcrab_fast_health","0"); -ConVar sk_headcrab_poison_health( "sk_headcrab_poison_health","0"); -ConVar sk_headcrab_melee_dmg( "sk_headcrab_melee_dmg","0"); -ConVar sk_headcrab_poison_npc_damage( "sk_headcrab_poison_npc_damage", "0" ); - -BEGIN_DATADESC( CBaseHeadcrab ) - - // m_nGibCount - don't save - DEFINE_FIELD( m_bHidden, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flTimeDrown, FIELD_TIME ), - DEFINE_FIELD( m_bCommittedToJump, FIELD_BOOLEAN ), - DEFINE_FIELD( m_vecCommittedJumpPos, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_flNextNPCThink, FIELD_TIME ), - DEFINE_FIELD( m_flIgnoreWorldCollisionTime, FIELD_TIME ), - - DEFINE_KEYFIELD( m_bStartBurrowed, FIELD_BOOLEAN, "startburrowed" ), - DEFINE_FIELD( m_bBurrowed, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flBurrowTime, FIELD_TIME ), - DEFINE_FIELD( m_nContext, FIELD_INTEGER ), - DEFINE_FIELD( m_bCrawlFromCanister, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bMidJump, FIELD_BOOLEAN ), - DEFINE_FIELD( m_nJumpFromCanisterDir, FIELD_INTEGER ), - - DEFINE_FIELD( m_bHangingFromCeiling, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flIlluminatedTime, FIELD_TIME ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Burrow", InputBurrow ), - DEFINE_INPUTFUNC( FIELD_VOID, "BurrowImmediate", InputBurrowImmediate ), - DEFINE_INPUTFUNC( FIELD_VOID, "Unburrow", InputUnburrow ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartHangingFromCeiling", InputStartHangingFromCeiling ), - DEFINE_INPUTFUNC( FIELD_VOID, "DropFromCeiling", InputDropFromCeiling ), - - // Function Pointers - DEFINE_THINKFUNC( EliminateRollAndPitch ), - DEFINE_THINKFUNC( ThrowThink ), - DEFINE_ENTITYFUNC( LeapTouch ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseHeadcrab::Spawn( void ) -{ - //Precache(); - //SetModel( "models/headcrab.mdl" ); - //m_iHealth = sk_headcrab_health.GetFloat(); - -#ifdef _XBOX - // Always fade the corpse - AddSpawnFlags( SF_NPC_FADE_CORPSE ); -#endif // _XBOX - - SetHullType(HULL_TINY); - SetHullSizeNormal(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - - SetCollisionGroup( HL2COLLISION_GROUP_HEADCRAB ); - - SetViewOffset( Vector(6, 0, 11) ) ; // Position of the eyes relative to NPC's origin. - - SetBloodColor( BLOOD_COLOR_GREEN ); - m_flFieldOfView = 0.5; - m_NPCState = NPC_STATE_NONE; - m_nGibCount = HEADCRAB_ALL_GIB_COUNT; - - // Are we starting hidden? - if ( m_spawnflags & SF_HEADCRAB_START_HIDDEN ) - { - m_bHidden = true; - AddSolidFlags( FSOLID_NOT_SOLID ); - SetRenderColorA( 0 ); - m_nRenderMode = kRenderTransTexture; - AddEffects( EF_NODRAW ); - } - else - { - m_bHidden = false; - } - - CapabilitiesClear(); - CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_INNATE_RANGE_ATTACK1 ); - CapabilitiesAdd( bits_CAP_SQUAD ); - - // headcrabs get to cheat for 5 seconds (sjb) - GetEnemies()->SetFreeKnowledgeDuration( 5.0 ); - - m_bHangingFromCeiling = false; - m_flIlluminatedTime = -1; -} - -//----------------------------------------------------------------------------- -// Purpose: Stuff that must happen after NPCInit is called. -//----------------------------------------------------------------------------- -void CBaseHeadcrab::HeadcrabInit() -{ - // See if we're supposed to start burrowed - if ( m_bStartBurrowed ) - { - SetBurrowed( true ); - SetSchedule( SCHED_HEADCRAB_BURROW_WAIT ); - } - - if ( GetSpawnFlags() & SF_HEADCRAB_START_HANGING ) - { - SetSchedule( SCHED_HEADCRAB_CEILING_WAIT ); - m_flIlluminatedTime = -1; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Precaches all resources this monster needs. -//----------------------------------------------------------------------------- -void CBaseHeadcrab::Precache( void ) -{ - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -// The headcrab will crawl from the cannister, then jump to a burrow point -//----------------------------------------------------------------------------- -void CBaseHeadcrab::CrawlFromCanister() -{ - // This is necessary to prevent ground computations, etc. from happening - // while the crawling animation is occuring - AddFlag( FL_FLY ); - m_bCrawlFromCanister = true; - SetNextThink( gpGlobals->curtime ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : NewActivity - -//----------------------------------------------------------------------------- -void CBaseHeadcrab::OnChangeActivity( Activity NewActivity ) -{ - bool fRandomize = false; - float flRandomRange = 0.0; - - // If this crab is starting to walk or idle, pick a random point within - // the animation to begin. This prevents lots of crabs being in lockstep. - if ( NewActivity == ACT_IDLE ) - { - flRandomRange = 0.75; - fRandomize = true; - } - else if ( NewActivity == ACT_RUN ) - { - flRandomRange = 0.25; - fRandomize = true; - } - - BaseClass::OnChangeActivity( NewActivity ); - - if( fRandomize ) - { - SetCycle( random->RandomFloat( 0.0, flRandomRange ) ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Indicates this monster's place in the relationship table. -// Output : -//----------------------------------------------------------------------------- -Class_T CBaseHeadcrab::Classify( void ) -{ - if( m_bHidden ) - { - // Effectively invisible to other AI's while hidden. - return( CLASS_NONE ); - } - else - { - return( CLASS_HEADCRAB ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &posSrc - -// Output : Vector -//----------------------------------------------------------------------------- -Vector CBaseHeadcrab::BodyTarget( const Vector &posSrc, bool bNoisy ) -{ - Vector vecResult; - vecResult = GetAbsOrigin(); - vecResult.z += 6; - return vecResult; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -float CBaseHeadcrab::GetAutoAimRadius() -{ - if( g_pGameRules->GetAutoAimMode() == AUTOAIM_ON_CONSOLE ) - { - return 24.0f; - } - - return 12.0f; -} - - -//----------------------------------------------------------------------------- -// Purpose: Allows each sequence to have a different turn rate associated with it. -// Output : float -//----------------------------------------------------------------------------- -float CBaseHeadcrab::MaxYawSpeed( void ) -{ - return BaseClass::MaxYawSpeed(); -} - -//----------------------------------------------------------------------------- -// Because the AI code does a tracehull to find the ground under an NPC, headcrabs -// can often be seen standing with one edge of their box perched on a ledge and -// 80% or more of their body hanging out over nothing. This is often a case -// where a headcrab will be unable to pathfind out of its location. This heuristic -// very crudely tries to determine if this is the case by casting a simple ray -// down from the center of the headcrab. -//----------------------------------------------------------------------------- -#define HEADCRAB_MAX_LEDGE_HEIGHT 12.0f -bool CBaseHeadcrab::IsFirmlyOnGround() -{ - if( !(GetFlags()&FL_ONGROUND) ) - return false; - - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector( 0, 0, HEADCRAB_MAX_LEDGE_HEIGHT ), MASK_NPCSOLID, this, GetCollisionGroup(), &tr ); - return tr.fraction != 1.0; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CBaseHeadcrab::MoveOrigin( const Vector &vecDelta ) -{ - UTIL_SetOrigin( this, GetLocalOrigin() + vecDelta ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : vecPos - -//----------------------------------------------------------------------------- -void CBaseHeadcrab::ThrowAt( const Vector &vecPos ) -{ - JumpAttack( false, vecPos, true ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : vecPos - -//----------------------------------------------------------------------------- -void CBaseHeadcrab::JumpToBurrowHint( CAI_Hint *pHint ) -{ - Vector vecVel = VecCheckToss( this, GetAbsOrigin(), pHint->GetAbsOrigin(), 0.5f, 1.0f, false, NULL, NULL ); - - // Undershoot by a little because it looks bad if we overshoot and turn around to burrow. - vecVel *= 0.9f; - Leap( vecVel ); - - GrabHintNode( pHint ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : vecVel - -//----------------------------------------------------------------------------- -void CBaseHeadcrab::Leap( const Vector &vecVel ) -{ - SetTouch( &CBaseHeadcrab::LeapTouch ); - - SetCondition( COND_FLOATING_OFF_GROUND ); - SetGroundEntity( NULL ); - - m_flIgnoreWorldCollisionTime = gpGlobals->curtime + HEADCRAB_IGNORE_WORLD_COLLISION_TIME; - - if( HasHeadroom() ) - { - // Take him off ground so engine doesn't instantly reset FL_ONGROUND. - MoveOrigin( Vector( 0, 0, 1 ) ); - } - - SetAbsVelocity( vecVel ); - - // Think every frame so the player sees the headcrab where he actually is... - m_bMidJump = true; - SetThink( &CBaseHeadcrab::ThrowThink ); - SetNextThink( gpGlobals->curtime ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseHeadcrab::ThrowThink( void ) -{ - if (gpGlobals->curtime > m_flNextNPCThink) - { - NPCThink(); - m_flNextNPCThink = gpGlobals->curtime + 0.1; - } - - if( GetFlags() & FL_ONGROUND ) - { - SetThink( &CBaseHeadcrab::CallNPCThink ); - SetNextThink( gpGlobals->curtime + 0.1 ); - return; - } - - SetNextThink( gpGlobals->curtime ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Does a jump attack at the given position. -// Input : bRandomJump - Just hop in a random direction. -// vecPos - Position to jump at, ignored if bRandom is set to true. -// bThrown - -//----------------------------------------------------------------------------- -void CBaseHeadcrab::JumpAttack( bool bRandomJump, const Vector &vecPos, bool bThrown ) -{ - Vector vecJumpVel; - if ( !bRandomJump ) - { - float gravity = sv_gravity.GetFloat(); - if ( gravity <= 1 ) - { - gravity = 1; - } - - // How fast does the headcrab need to travel to reach the position given gravity? - float flActualHeight = vecPos.z - GetAbsOrigin().z; - float height = flActualHeight; - if ( height < 16 ) - { - height = 16; - } - else - { - float flMaxHeight = bThrown ? 400 : 120; - if ( height > flMaxHeight ) - { - height = flMaxHeight; - } - } - - // overshoot the jump by an additional 8 inches - // NOTE: This calculation jumps at a position INSIDE the box of the enemy (player) - // so if you make the additional height too high, the crab can land on top of the - // enemy's head. If we want to jump high, we'll need to move vecPos to the surface/outside - // of the enemy's box. - - float additionalHeight = 0; - if ( height < 32 ) - { - additionalHeight = 8; - } - - height += additionalHeight; - - // NOTE: This equation here is from vf^2 = vi^2 + 2*a*d - float speed = sqrt( 2 * gravity * height ); - float time = speed / gravity; - - // add in the time it takes to fall the additional height - // So the impact takes place on the downward slope at the original height - time += sqrt( (2 * additionalHeight) / gravity ); - - // Scale the sideways velocity to get there at the right time - VectorSubtract( vecPos, GetAbsOrigin(), vecJumpVel ); - vecJumpVel /= time; - - // Speed to offset gravity at the desired height. - vecJumpVel.z = speed; - - // Don't jump too far/fast. - float flJumpSpeed = vecJumpVel.Length(); - float flMaxSpeed = bThrown ? 1000.0f : 650.0f; - if ( flJumpSpeed > flMaxSpeed ) - { - vecJumpVel *= flMaxSpeed / flJumpSpeed; - } - } - else - { - // - // Jump hop, don't care where. - // - Vector forward, up; - AngleVectors( GetLocalAngles(), &forward, NULL, &up ); - vecJumpVel = Vector( forward.x, forward.y, up.z ) * 350; - } - - AttackSound(); - Leap( vecJumpVel ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Catches the monster-specific messages that occur when tagged -// animation frames are played. -// Input : *pEvent - -//----------------------------------------------------------------------------- -void CBaseHeadcrab::HandleAnimEvent( animevent_t *pEvent ) -{ - if ( pEvent->event == AE_HEADCRAB_JUMPATTACK ) - { - // Ignore if we're in mid air - if ( m_bMidJump ) - return; - - CBaseEntity *pEnemy = GetEnemy(); - - if ( pEnemy ) - { - if ( m_bCommittedToJump ) - { - JumpAttack( false, m_vecCommittedJumpPos ); - } - else - { - // Jump at my enemy's eyes. - JumpAttack( false, pEnemy->EyePosition() ); - } - - m_bCommittedToJump = false; - - } - else - { - // Jump hop, don't care where. - JumpAttack( true ); - } - - return; - } - - if ( pEvent->event == AE_HEADCRAB_CEILING_DETACH ) - { - SetMoveType( MOVETYPE_STEP ); - RemoveFlag( FL_ONGROUND ); - RemoveFlag( FL_FLY ); - - SetAbsVelocity( Vector ( 0, 0, -128 ) ); - return; - } - if ( pEvent->event == AE_HEADCRAB_JUMP_TELEGRAPH ) - { - TelegraphSound(); - - CBaseEntity *pEnemy = GetEnemy(); - - if ( pEnemy ) - { - // Once we telegraph, we MUST jump. This is also when commit to what point - // we jump at. Jump at our enemy's eyes. - m_vecCommittedJumpPos = pEnemy->EyePosition(); - m_bCommittedToJump = true; - } - - return; - } - - if ( pEvent->event == AE_HEADCRAB_BURROW_IN ) - { - EmitSound( "NPC_Headcrab.BurrowIn" ); - CreateDust(); - - return; - } - - if ( pEvent->event == AE_HEADCRAB_BURROW_IN_FINISH ) - { - SetBurrowed( true ); - return; - } - - if ( pEvent->event == AE_HEADCRAB_BURROW_OUT ) - { - Assert( m_bBurrowed ); - if ( m_bBurrowed ) - { - EmitSound( "NPC_Headcrab.BurrowOut" ); - CreateDust(); - SetBurrowed( false ); - - // We're done with this burrow hint node. It might be NULL here - // because we may have started burrowed (no hint node in that case). - GrabHintNode( NULL ); - } - - return; - } - - CAI_BaseNPC::HandleAnimEvent( pEvent ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Does all the fixup for going to/from the burrowed state. -//----------------------------------------------------------------------------- -void CBaseHeadcrab::SetBurrowed( bool bBurrowed ) -{ - if ( bBurrowed ) - { - AddEffects( EF_NODRAW ); - AddFlag( FL_NOTARGET ); - m_spawnflags |= SF_NPC_GAG; - AddSolidFlags( FSOLID_NOT_SOLID ); - m_takedamage = DAMAGE_NO; - m_flFieldOfView = HEADCRAB_BURROWED_FOV; - - SetState( NPC_STATE_IDLE ); - SetActivity( (Activity) ACT_HEADCRAB_BURROW_IDLE ); - } - else - { - RemoveEffects( EF_NODRAW ); - RemoveFlag( FL_NOTARGET ); - m_spawnflags &= ~SF_NPC_GAG; - RemoveSolidFlags( FSOLID_NOT_SOLID ); - m_takedamage = DAMAGE_YES; - m_flFieldOfView = HEADCRAB_UNBURROWED_FOV; - } - - m_bBurrowed = bBurrowed; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTask - -//----------------------------------------------------------------------------- -void CBaseHeadcrab::RunTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_HEADCRAB_CLIMB_FROM_CANISTER: - AutoMovement( ); - if ( IsActivityFinished() ) - { - TaskComplete(); - } - break; - - case TASK_HEADCRAB_JUMP_FROM_CANISTER: - GetMotor()->UpdateYaw(); - if ( FacingIdeal() ) - { - TaskComplete(); - } - break; - - case TASK_HEADCRAB_WAIT_FOR_BARNACLE_KILL: - if ( m_flNextFlinchTime < gpGlobals->curtime ) - { - m_flNextFlinchTime = gpGlobals->curtime + random->RandomFloat( 1.0f, 2.0f ); - CTakeDamageInfo info; - PainSound( info ); - } - break; - - case TASK_HEADCRAB_HOP_OFF_NPC: - if( GetFlags() & FL_ONGROUND ) - { - TaskComplete(); - } - else - { - // Face the direction I've been forced to jump. - GetMotor()->SetIdealYawToTargetAndUpdate( GetAbsOrigin() + GetAbsVelocity() ); - } - break; - - case TASK_HEADCRAB_DROWN: - if( gpGlobals->curtime > m_flTimeDrown ) - { - OnTakeDamage( CTakeDamageInfo( this, this, m_iHealth * 2, DMG_DROWN ) ); - } - break; - - case TASK_RANGE_ATTACK1: - case TASK_RANGE_ATTACK2: - case TASK_HEADCRAB_HARASS_HOP: - { - if ( IsActivityFinished() ) - { - TaskComplete(); - m_bMidJump = false; - SetTouch( NULL ); - SetThink( &CBaseHeadcrab::CallNPCThink ); - SetIdealActivity( ACT_IDLE ); - - if ( m_bAttackFailed ) - { - // our attack failed because we just ran into something solid. - // delay attacking for a while so we don't just repeatedly leap - // at the enemy from a bad location. - m_bAttackFailed = false; - m_flNextAttack = gpGlobals->curtime + 1.2f; - } - } - break; - } - - case TASK_HEADCRAB_CHECK_FOR_UNBURROW: - { - // Must wait for our next check time - if ( m_flBurrowTime > gpGlobals->curtime ) - return; - - // See if we can pop up - if ( ValidBurrowPoint( GetAbsOrigin() ) ) - { - m_spawnflags &= ~SF_NPC_GAG; - RemoveSolidFlags( FSOLID_NOT_SOLID ); - - TaskComplete(); - return; - } - - // Try again in a couple of seconds - m_flBurrowTime = gpGlobals->curtime + random->RandomFloat( 0.5f, 1.0f ); - - break; - } - - case TASK_HEADCRAB_BURROW_WAIT: - { - if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) || HasCondition( COND_CAN_RANGE_ATTACK2 ) ) - { - TaskComplete(); - } - - break; - } - - case TASK_HEADCRAB_CEILING_WAIT: - { -#ifdef HL2_EPISODIC - if ( DarknessLightSourceWithinRadius( this, DARKNESS_LIGHTSOURCE_SIZE ) ) - { - DropFromCeiling(); - } -#endif - - if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) || HasCondition( COND_CAN_RANGE_ATTACK2 ) ) - { - TaskComplete(); - } - - break; - } - - case TASK_HEADCRAB_CEILING_DETACH: - { - if ( IsActivityFinished() ) - { - ClearCondition( COND_CAN_RANGE_ATTACK1 ); - RemoveFlag(FL_FLY); - TaskComplete(); - } - } - break; - - case TASK_HEADCRAB_CEILING_FALL: - { - Vector vecPrPos; - trace_t tr; - - //Figure out where the headcrab is going to be in quarter of a second. - vecPrPos = GetAbsOrigin() + ( GetAbsVelocity() * 0.25f ); - UTIL_TraceHull( vecPrPos, vecPrPos, GetHullMins(), GetHullMaxs(), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.startsolid == true || GetFlags() & FL_ONGROUND ) - { - RemoveSolidFlags( FSOLID_NOT_SOLID ); - TaskComplete(); - } - } - break; - - case TASK_HEADCRAB_CEILING_LAND: - { - if ( IsActivityFinished() ) - { - RemoveSolidFlags( FSOLID_NOT_SOLID ); //double-dog verify that we're solid. - TaskComplete(); - m_bHangingFromCeiling = false; - } - } - break; - default: - { - BaseClass::RunTask( pTask ); - } - } -} - - -//----------------------------------------------------------------------------- -// Before jumping, headcrabs usually use SetOrigin() to lift themselves off the -// ground. If the headcrab doesn't have the clearance to so, they'll be stuck -// in the world. So this function makes sure there's headroom first. -//----------------------------------------------------------------------------- -bool CBaseHeadcrab::HasHeadroom() -{ - trace_t tr; - UTIL_TraceEntity( this, GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, 1 ), MASK_NPCSOLID, this, GetCollisionGroup(), &tr ); - -#if 0 - if( tr.fraction == 1.0f ) - { - Msg("Headroom\n"); - } - else - { - Msg("NO Headroom\n"); - } -#endif - - return (tr.fraction == 1.0); -} - -//----------------------------------------------------------------------------- -// Purpose: LeapTouch - this is the headcrab's touch function when it is in the air. -// Input : *pOther - -//----------------------------------------------------------------------------- -void CBaseHeadcrab::LeapTouch( CBaseEntity *pOther ) -{ - m_bMidJump = false; - - if ( IRelationType( pOther ) == D_HT ) - { - // Don't hit if back on ground - if ( !( GetFlags() & FL_ONGROUND ) ) - { - if ( pOther->m_takedamage != DAMAGE_NO ) - { - BiteSound(); - TouchDamage( pOther ); - - // attack succeeded, so don't delay our next attack if we previously thought we failed - m_bAttackFailed = false; - } - else - { - ImpactSound(); - } - } - else - { - ImpactSound(); - } - } - else if( !(GetFlags() & FL_ONGROUND) ) - { - // Still in the air... - if( !pOther->IsSolid() ) - { - // Touching a trigger or something. - return; - } - - // just ran into something solid, so the attack probably failed. make a note of it - // so that when the attack is done, we'll delay attacking for a while so we don't - // just repeatedly leap at the enemy from a bad location. - m_bAttackFailed = true; - - if( gpGlobals->curtime < m_flIgnoreWorldCollisionTime ) - { - // Headcrabs try to ignore the world, static props, and friends for a - // fraction of a second after they jump. This is because they often brush - // doorframes or props as they leap, and touching those objects turns off - // this touch function, which can cause them to hit the player and not bite. - // A timer probably isn't the best way to fix this, but it's one of our - // safer options at this point (sjb). - return; - } - } - - // Shut off the touch function. - SetTouch( NULL ); - SetThink ( &CBaseHeadcrab::CallNPCThink ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CBaseHeadcrab::CalcDamageInfo( CTakeDamageInfo *pInfo ) -{ - pInfo->Set( this, this, sk_headcrab_melee_dmg.GetFloat(), DMG_SLASH ); - CalculateMeleeDamageForce( pInfo, GetAbsVelocity(), GetAbsOrigin() ); - return (int)pInfo->GetDamage(); -} - -//----------------------------------------------------------------------------- -// Purpose: Deal the damage from the headcrab's touch attack. -//----------------------------------------------------------------------------- -void CBaseHeadcrab::TouchDamage( CBaseEntity *pOther ) -{ - CTakeDamageInfo info; - CalcDamageInfo( &info ); - pOther->TakeDamage( info ); -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBaseHeadcrab::GatherConditions( void ) -{ - // If we're hidden, just check to see if we should unhide - if ( m_bHidden ) - { - // See if there's enough room for our hull to fit here. If so, unhide. - trace_t tr; - AI_TraceHull( GetAbsOrigin(), GetAbsOrigin(),GetHullMins(), GetHullMaxs(), MASK_SHOT, this, GetCollisionGroup(), &tr ); - if ( tr.fraction == 1.0 ) - { - SetCondition( COND_PROVOKED ); - SetCondition( COND_HEADCRAB_UNHIDE ); - - if ( g_debug_headcrab.GetInt() == HEADCRAB_DEBUG_HIDING ) - { - NDebugOverlay::Box( GetAbsOrigin(), GetHullMins(), GetHullMaxs(), 0,255,0, true, 1.0 ); - } - } - else if ( g_debug_headcrab.GetInt() == HEADCRAB_DEBUG_HIDING ) - { - NDebugOverlay::Box( GetAbsOrigin(), GetHullMins(), GetHullMaxs(), 255,0,0, true, 0.1 ); - } - - // Prevent baseclass thinking, so we don't respond to enemy fire, etc. - return; - } - - BaseClass::GatherConditions(); - - if( m_lifeState == LIFE_ALIVE && GetWaterLevel() > 1 ) - { - // Start Drowning! - SetCondition( COND_HEADCRAB_IN_WATER ); - } - - // See if I've landed on an NPC or player or something else illegal - ClearCondition( COND_HEADCRAB_ILLEGAL_GROUNDENT ); - CBaseEntity *ground = GetGroundEntity(); - if( (GetFlags() & FL_ONGROUND) && ground && !ground->IsWorld() ) - { - if ( IsHangingFromCeiling() == false ) - { - if( ( ground->IsNPC() || ground->IsPlayer() ) ) - { - SetCondition( COND_HEADCRAB_ILLEGAL_GROUNDENT ); - } - else if( ground->VPhysicsGetObject() && (ground->VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD) ) - { - SetCondition( COND_HEADCRAB_ILLEGAL_GROUNDENT ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseHeadcrab::PrescheduleThink( void ) -{ - BaseClass::PrescheduleThink(); - - // Are we fading in after being hidden? - if ( !m_bHidden && (m_nRenderMode != kRenderNormal) ) - { - int iNewAlpha = MIN( 255, GetRenderColor().a + 120 ); - if ( iNewAlpha >= 255 ) - { - m_nRenderMode = kRenderNormal; - SetRenderColorA( 0 ); - } - else - { - SetRenderColorA( iNewAlpha ); - } - } - - // - // Make the crab coo a little bit in combat state. - // - if (( m_NPCState == NPC_STATE_COMBAT ) && ( random->RandomFloat( 0, 5 ) < 0.1 )) - { - IdleSound(); - } - - // Make sure we've turned off our burrow state if we're not in it - Activity eActivity = GetActivity(); - if ( m_bBurrowed && - ( eActivity != ACT_HEADCRAB_BURROW_IDLE ) && - ( eActivity != ACT_HEADCRAB_BURROW_OUT ) && - ( eActivity != ACT_HEADCRAB_BURROW_IN) ) - { - DevMsg( "Headcrab failed to unburrow properly!\n" ); - Assert( 0 ); - SetBurrowed( false ); - } - -} - - -//----------------------------------------------------------------------------- -// Eliminates roll + pitch from the headcrab -//----------------------------------------------------------------------------- -#define HEADCRAB_ROLL_ELIMINATION_TIME 0.3f -#define HEADCRAB_PITCH_ELIMINATION_TIME 0.3f - -//----------------------------------------------------------------------------- -// Eliminates roll + pitch potentially in the headcrab at canister jump time -//----------------------------------------------------------------------------- -void CBaseHeadcrab::EliminateRollAndPitch() -{ - QAngle angles = GetAbsAngles(); - angles.x = AngleNormalize( angles.x ); - angles.z = AngleNormalize( angles.z ); - if ( ( angles.x == 0.0f ) && ( angles.z == 0.0f ) ) - return; - - float flPitchRate = 90.0f / HEADCRAB_PITCH_ELIMINATION_TIME; - float flPitchDelta = flPitchRate * TICK_INTERVAL; - if ( fabs( angles.x ) <= flPitchDelta ) - { - angles.x = 0.0f; - } - else - { - flPitchDelta *= (angles.x > 0.0f) ? -1.0f : 1.0f; - angles.x += flPitchDelta; - } - - float flRollRate = 180.0f / HEADCRAB_ROLL_ELIMINATION_TIME; - float flRollDelta = flRollRate * TICK_INTERVAL; - if ( fabs( angles.z ) <= flRollDelta ) - { - angles.z = 0.0f; - } - else - { - flRollDelta *= (angles.z > 0.0f) ? -1.0f : 1.0f; - angles.z += flRollDelta; - } - - SetAbsAngles( angles ); - - SetContextThink( &CBaseHeadcrab::EliminateRollAndPitch, gpGlobals->curtime + TICK_INTERVAL, s_pPitchContext ); -} - - -//----------------------------------------------------------------------------- -// Begins the climb from the canister -//----------------------------------------------------------------------------- -void CBaseHeadcrab::BeginClimbFromCanister() -{ - Assert( GetMoveParent() ); - // Compute a desired position or hint - Vector vecForward, vecActualForward; - AngleVectors( GetMoveParent()->GetAbsAngles(), &vecActualForward ); - vecForward = vecActualForward; - vecForward.z = 0.0f; - VectorNormalize( vecForward ); - - Vector vecSearchCenter = GetAbsOrigin(); - CAI_Hint *pHint = CAI_HintManager::FindHint( this, HINT_HEADCRAB_BURROW_POINT, 0, HEADCRAB_BURROW_POINT_SEARCH_RADIUS, &vecSearchCenter ); - - if( !pHint && hl2_episodic.GetBool() ) - { - // Look for exit points within 10 feet. - pHint = CAI_HintManager::FindHint( this, HINT_HEADCRAB_EXIT_POD_POINT, 0, 120.0f, &vecSearchCenter ); - } - - if ( pHint && ( !pHint->IsLocked() ) ) - { - // Claim the hint node so other headcrabs don't try to take it! - GrabHintNode( pHint ); - - // Compute relative yaw.. - Vector vecDelta; - VectorSubtract( pHint->GetAbsOrigin(), vecSearchCenter, vecDelta ); - vecDelta.z = 0.0f; - VectorNormalize( vecDelta ); - - float flAngle = DotProduct( vecDelta, vecForward ); - if ( flAngle >= 0.707f ) - { - m_nJumpFromCanisterDir = 1; - } - else - { - // Check the cross product to see if it's on the left or right. - // All we care about is the sign of the z component. If it's +, the hint is on the left. - // If it's -, then the hint is on the right. - float flCrossZ = vecForward.x * vecDelta.y - vecDelta.x * vecForward.y; - m_nJumpFromCanisterDir = ( flCrossZ > 0 ) ? 0 : 2; - } - } - else - { - // Choose a random direction (forward, left, or right) - m_nJumpFromCanisterDir = random->RandomInt( 0, 2 ); - } - - Activity act; - switch( m_nJumpFromCanisterDir ) - { - case 0: - act = (Activity)ACT_HEADCRAB_CRAWL_FROM_CANISTER_LEFT; - break; - - default: - case 1: - act = (Activity)ACT_HEADCRAB_CRAWL_FROM_CANISTER_CENTER; - break; - - case 2: - act = (Activity)ACT_HEADCRAB_CRAWL_FROM_CANISTER_RIGHT; - break; - } - - SetIdealActivity( act ); -} - - -//----------------------------------------------------------------------------- -// Jumps from the canister -//----------------------------------------------------------------------------- -#define HEADCRAB_ATTACK_PLAYER_FROM_CANISTER_DIST 250.0f -#define HEADCRAB_ATTACK_PLAYER_FROM_CANISTER_COSANGLE 0.866f - -void CBaseHeadcrab::JumpFromCanister() -{ - Assert( GetMoveParent() ); - - Vector vecForward, vecActualForward, vecActualRight; - AngleVectors( GetMoveParent()->GetAbsAngles(), &vecActualForward, &vecActualRight, NULL ); - - switch( m_nJumpFromCanisterDir ) - { - case 0: - VectorMultiply( vecActualRight, -1.0f, vecForward ); - break; - case 1: - vecForward = vecActualForward; - break; - case 2: - vecForward = vecActualRight; - break; - } - - vecForward.z = 0.0f; - VectorNormalize( vecForward ); - QAngle headCrabAngles; - VectorAngles( vecForward, headCrabAngles ); - - SetActivity( ACT_RANGE_ATTACK1 ); - StudioFrameAdvanceManual( 0.0 ); - SetParent( NULL ); - RemoveFlag( FL_FLY ); - AddEffects( EF_NOINTERP ); - - GetMotor()->SetIdealYaw( headCrabAngles.y ); - - // Check to see if the player is within jump range. If so, jump at him! - bool bJumpedAtEnemy = false; - - // FIXME: Can't use GetEnemy() here because enemy only updates during - // schedules which are interruptible by COND_NEW_ENEMY or COND_LOST_ENEMY - CBaseEntity *pEnemy = BestEnemy(); - if ( pEnemy ) - { - Vector vecDirToEnemy; - VectorSubtract( pEnemy->GetAbsOrigin(), GetAbsOrigin(), vecDirToEnemy ); - vecDirToEnemy.z = 0.0f; - float flDist = VectorNormalize( vecDirToEnemy ); - if ( ( flDist < HEADCRAB_ATTACK_PLAYER_FROM_CANISTER_DIST ) && - ( DotProduct( vecDirToEnemy, vecForward ) >= HEADCRAB_ATTACK_PLAYER_FROM_CANISTER_COSANGLE ) ) - { - GrabHintNode( NULL ); - JumpAttack( false, pEnemy->EyePosition(), false ); - bJumpedAtEnemy = true; - } - } - - if ( !bJumpedAtEnemy ) - { - if ( GetHintNode() ) - { - JumpToBurrowHint( GetHintNode() ); - } - else - { - vecForward *= 100.0f; - vecForward += GetAbsOrigin(); - JumpAttack( false, vecForward, false ); - } - } - - EliminateRollAndPitch(); -} - -#define HEADCRAB_ILLUMINATED_TIME 0.15f - -void CBaseHeadcrab::DropFromCeiling( void ) -{ - if ( HL2GameRules()->IsAlyxInDarknessMode() ) - { - if ( IsHangingFromCeiling() ) - { - if ( m_flIlluminatedTime == -1 ) - { - m_flIlluminatedTime = gpGlobals->curtime + HEADCRAB_ILLUMINATED_TIME; - return; - } - - if ( m_flIlluminatedTime <= gpGlobals->curtime ) - { - if ( IsCurSchedule( SCHED_HEADCRAB_CEILING_DROP ) == false ) - { - SetSchedule( SCHED_HEADCRAB_CEILING_DROP ); - - CBaseEntity *pPlayer = AI_GetSinglePlayer(); - - if ( pPlayer ) - { - SetEnemy( pPlayer ); //Is this a bad thing to do? - UpdateEnemyMemory( pPlayer, pPlayer->GetAbsOrigin()); - } - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Player has illuminated this NPC with the flashlight -//----------------------------------------------------------------------------- -void CBaseHeadcrab::PlayerHasIlluminatedNPC( CBasePlayer *pPlayer, float flDot ) -{ - if ( flDot < 0.97387f ) - return; - - DropFromCeiling(); -} - -bool CBaseHeadcrab::CanBeAnEnemyOf( CBaseEntity *pEnemy ) -{ -#ifdef HL2_EPISODIC - if ( IsHangingFromCeiling() ) - return false; -#endif - - return BaseClass::CanBeAnEnemyOf( pEnemy ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pTask - -//----------------------------------------------------------------------------- -void CBaseHeadcrab::StartTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_HEADCRAB_WAIT_FOR_BARNACLE_KILL: - break; - - case TASK_HEADCRAB_BURROW_WAIT: - break; - - case TASK_HEADCRAB_CLIMB_FROM_CANISTER: - BeginClimbFromCanister(); - break; - - case TASK_HEADCRAB_JUMP_FROM_CANISTER: - JumpFromCanister(); - break; - - case TASK_HEADCRAB_CEILING_POSITION: - { - trace_t tr; - UTIL_TraceHull( GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, 512 ), NAI_Hull::Mins( GetHullType() ), NAI_Hull::Maxs( GetHullType() ), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - - // SetMoveType( MOVETYPE_NONE ); - AddFlag(FL_FLY); - m_bHangingFromCeiling = true; - - //Don't need this anymore - RemoveSpawnFlags( SF_HEADCRAB_START_HANGING ); - - SetAbsOrigin( tr.endpos ); - - TaskComplete(); - } - break; - - case TASK_HEADCRAB_CEILING_WAIT: - break; - - case TASK_HEADCRAB_CEILING_DETACH: - { - SetIdealActivity( (Activity)ACT_HEADCRAB_CEILING_DETACH ); - } - break; - - case TASK_HEADCRAB_CEILING_FALL: - { - SetIdealActivity( (Activity)ACT_HEADCRAB_CEILING_FALL ); - } - break; - - case TASK_HEADCRAB_CEILING_LAND: - { - SetIdealActivity( (Activity)ACT_HEADCRAB_CEILING_LAND ); - } - break; - - case TASK_HEADCRAB_HARASS_HOP: - { - // Just pop up into the air like you're trying to get at the - // enemy, even though it's known you can't reach them. - if ( GetEnemy() ) - { - Vector forward, up; - - GetVectors( &forward, NULL, &up ); - - m_vecCommittedJumpPos = GetAbsOrigin(); - m_vecCommittedJumpPos += up * random->RandomFloat( 80, 150 ); - m_vecCommittedJumpPos += forward * random->RandomFloat( 32, 80 ); - - m_bCommittedToJump = true; - - SetIdealActivity( ACT_RANGE_ATTACK1 ); - } - else - { - TaskFail( "No enemy" ); - } - } - break; - - case TASK_HEADCRAB_HOP_OFF_NPC: - { - CBaseEntity *ground = GetGroundEntity(); - if( ground ) - { - // If jumping off of a physics object that the player is holding, create a - // solver to prevent the headcrab from colliding with that object for a - // short time. - if( ground && ground->VPhysicsGetObject() ) - { - if( ground->VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - { - NPCPhysics_CreateSolver( this, ground, true, 0.5 ); - } - } - - - Vector vecJumpDir; - - // Jump in some random direction. This way if the person I'm standing on is - // against a wall, I'll eventually get away. - - vecJumpDir.z = 0; - vecJumpDir.x = 0; - vecJumpDir.y = 0; - - while( vecJumpDir.x == 0 && vecJumpDir.y == 0 ) - { - vecJumpDir.x = random->RandomInt( -1, 1 ); - vecJumpDir.y = random->RandomInt( -1, 1 ); - } - - vecJumpDir.NormalizeInPlace(); - - SetGroundEntity( NULL ); - - if( HasHeadroom() ) - { - // Bump up - MoveOrigin( Vector( 0, 0, 1 ) ); - } - - SetAbsVelocity( vecJumpDir * 200 + Vector( 0, 0, 200 ) ); - } - else - { - // *shrug* I guess they're gone now. Or dead. - TaskComplete(); - } - } - break; - - case TASK_HEADCRAB_DROWN: - { - // Set the gravity really low here! Sink slowly - SetGravity( UTIL_ScaleForGravity( 80 ) ); - m_flTimeDrown = gpGlobals->curtime + 4; - break; - } - - case TASK_RANGE_ATTACK1: - { -#ifdef WEDGE_FIX_THIS - CPASAttenuationFilter filter( this, ATTN_IDLE ); - EmitSound( filter, entindex(), CHAN_WEAPON, pAttackSounds[0], GetSoundVolume(), ATTN_IDLE, 0, GetVoicePitch() ); -#endif - SetIdealActivity( ACT_RANGE_ATTACK1 ); - break; - } - - case TASK_HEADCRAB_UNHIDE: - { - m_bHidden = false; - RemoveSolidFlags( FSOLID_NOT_SOLID ); - RemoveEffects( EF_NODRAW ); - - TaskComplete(); - break; - } - - case TASK_HEADCRAB_CHECK_FOR_UNBURROW: - { - if ( ValidBurrowPoint( GetAbsOrigin() ) ) - { - m_spawnflags &= ~SF_NPC_GAG; - RemoveSolidFlags( FSOLID_NOT_SOLID ); - TaskComplete(); - } - break; - } - - case TASK_HEADCRAB_FIND_BURROW_IN_POINT: - { - if ( FindBurrow( GetAbsOrigin(), pTask->flTaskData, true ) == false ) - { - TaskFail( "TASK_HEADCRAB_FIND_BURROW_IN_POINT: Unable to find burrow in position\n" ); - } - else - { - TaskComplete(); - } - break; - } - - case TASK_HEADCRAB_BURROW: - { - Burrow(); - TaskComplete(); - break; - } - - case TASK_HEADCRAB_UNBURROW: - { - Unburrow(); - TaskComplete(); - break; - } - - default: - { - BaseClass::StartTask( pTask ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: For innate melee attack -// Input : -// Output : -//----------------------------------------------------------------------------- -float CBaseHeadcrab::InnateRange1MinRange( void ) -{ - return HEADCRAB_MIN_JUMP_DIST; -} - -float CBaseHeadcrab::InnateRange1MaxRange( void ) -{ - return HEADCRAB_MAX_JUMP_DIST; -} - -int CBaseHeadcrab::RangeAttack1Conditions( float flDot, float flDist ) -{ - if ( gpGlobals->curtime < m_flNextAttack ) - return 0; - - if ( ( GetFlags() & FL_ONGROUND ) == false ) - return 0; - - // When we're burrowed ignore facing, because when we unburrow we'll cheat and face our enemy. - if ( !m_bBurrowed && ( flDot < 0.65 ) ) - return COND_NOT_FACING_ATTACK; - - // This code stops lots of headcrabs swarming you and blocking you - // whilst jumping up and down in your face over and over. It forces - // them to back up a bit. If this causes problems, consider using it - // for the fast headcrabs only, rather than just removing it.(sjb) - if ( flDist < HEADCRAB_MIN_JUMP_DIST ) - return COND_TOO_CLOSE_TO_ATTACK; - - if ( flDist > HEADCRAB_MAX_JUMP_DIST ) - return COND_TOO_FAR_TO_ATTACK; - - // Make sure the way is clear! - CBaseEntity *pEnemy = GetEnemy(); - if( pEnemy ) - { - bool bEnemyIsBullseye = ( dynamic_cast(pEnemy) != NULL ); - - trace_t tr; - AI_TraceLine( EyePosition(), pEnemy->EyePosition(), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.m_pEnt != GetEnemy() ) - { - if ( !bEnemyIsBullseye || tr.m_pEnt != NULL ) - return COND_NONE; - } - - if( GetEnemy()->EyePosition().z - 36.0f > GetAbsOrigin().z ) - { - // Only run this test if trying to jump at a player who is higher up than me, else this - // code will always prevent a headcrab from jumping down at an enemy, and sometimes prevent it - // jumping just slightly up at an enemy. - Vector vStartHullTrace = GetAbsOrigin(); - vStartHullTrace.z += 1.0; - - Vector vEndHullTrace = GetEnemy()->EyePosition() - GetAbsOrigin(); - vEndHullTrace.NormalizeInPlace(); - vEndHullTrace *= 8.0; - vEndHullTrace += GetAbsOrigin(); - - AI_TraceHull( vStartHullTrace, vEndHullTrace,GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, GetCollisionGroup(), &tr ); - - if ( tr.m_pEnt != NULL && tr.m_pEnt != GetEnemy() ) - { - return COND_TOO_CLOSE_TO_ATTACK; - } - } - } - - return COND_CAN_RANGE_ATTACK1; -} - - -//------------------------------------------------------------------------------ -// Purpose: Override to do headcrab specific gibs -// Output : -//------------------------------------------------------------------------------ -bool CBaseHeadcrab::CorpseGib( const CTakeDamageInfo &info ) -{ - EmitSound( "NPC_HeadCrab.Gib" ); - - return BaseClass::CorpseGib( info ); -} - -//------------------------------------------------------------------------------ -// Purpose: -// Input : -//------------------------------------------------------------------------------ -void CBaseHeadcrab::Touch( CBaseEntity *pOther ) -{ - // If someone has smacked me into a wall then gib! - if (m_NPCState == NPC_STATE_DEAD) - { - if (GetAbsVelocity().Length() > 250) - { - trace_t tr; - Vector vecDir = GetAbsVelocity(); - VectorNormalize(vecDir); - AI_TraceLine(GetAbsOrigin(), GetAbsOrigin() + vecDir * 100, - MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr); - float dotPr = DotProduct(vecDir,tr.plane.normal); - if ((tr.fraction != 1.0) && - (dotPr < -0.8) ) - { - CTakeDamageInfo info( GetWorldEntity(), GetWorldEntity(), 100.0f, DMG_CRUSH ); - - info.SetDamagePosition( tr.endpos ); - - Event_Gibbed( info ); - } - - } - } - BaseClass::Touch(pOther); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pevInflictor - -// pevAttacker - -// flDamage - -// bitsDamageType - -// Output : -//----------------------------------------------------------------------------- -int CBaseHeadcrab::OnTakeDamage_Alive( const CTakeDamageInfo &inputInfo ) -{ - CTakeDamageInfo info = inputInfo; - - // - // Don't take any acid damage. - // - if ( info.GetDamageType() & DMG_ACID ) - { - info.SetDamage( 0 ); - } - - // - // Certain death from melee bludgeon weapons! - // - if ( info.GetDamageType() & DMG_CLUB ) - { - info.SetDamage( m_iHealth ); - } - - if( info.GetDamageType() & DMG_BLAST ) - { - if( random->RandomInt( 0 , 1 ) == 0 ) - { - // Catch on fire randomly if damaged in a blast. - Ignite( 30 ); - } - } - - if( info.GetDamageType() & DMG_BURN ) - { - // Slow down burn damage so that headcrabs live longer while on fire. - info.ScaleDamage( 0.25 ); - -#define HEADCRAB_SCORCH_RATE 5 -#define HEADCRAB_SCORCH_FLOOR 30 - - if( IsOnFire() ) - { - Scorch( HEADCRAB_SCORCH_RATE, HEADCRAB_SCORCH_FLOOR ); - - if( m_iHealth <= 1 && (entindex() % 2) ) - { - // Some headcrabs leap at you with their dying breath - if( !IsCurSchedule( SCHED_HEADCRAB_RANGE_ATTACK1 ) && !IsRunningDynamicInteraction() ) - { - SetSchedule( SCHED_HEADCRAB_RANGE_ATTACK1 ); - } - } - } - - Ignite( 30 ); - } - - return CAI_BaseNPC::OnTakeDamage_Alive( info ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CBaseHeadcrab::ClampRagdollForce( const Vector &vecForceIn, Vector *vecForceOut ) -{ - // Assumes the headcrab mass is 5kg (100 feet per second) - float MAX_HEADCRAB_RAGDOLL_SPEED = 100.0f * 12.0f * 5.0f; - - Vector vecClampedForce; - BaseClass::ClampRagdollForce( vecForceIn, &vecClampedForce ); - - // Copy the force to vecForceOut, in case we don't change it. - *vecForceOut = vecClampedForce; - - float speed = VectorNormalize( vecClampedForce ); - if( speed > MAX_HEADCRAB_RAGDOLL_SPEED ) - { - // Don't let the ragdoll go as fast as it was going to. - vecClampedForce *= MAX_HEADCRAB_RAGDOLL_SPEED; - *vecForceOut = vecClampedForce; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CBaseHeadcrab::Event_Killed( const CTakeDamageInfo &info ) -{ - // Create a little decal underneath the headcrab - // This type of damage combination happens from dynamic scripted sequences - if ( info.GetDamageType() & (DMG_GENERIC | DMG_PREVENT_PHYSICS_FORCE) ) - { - trace_t tr; - AI_TraceLine( GetAbsOrigin()+Vector(0,0,1), GetAbsOrigin()-Vector(0,0,64), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - - UTIL_DecalTrace( &tr, "YellowBlood" ); - } - - BaseClass::Event_Killed( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : Type - -//----------------------------------------------------------------------------- -int CBaseHeadcrab::TranslateSchedule( int scheduleType ) -{ - switch( scheduleType ) - { - case SCHED_FALL_TO_GROUND: - return SCHED_HEADCRAB_FALL_TO_GROUND; - - case SCHED_WAKE_ANGRY: - { - if ( HaveSequenceForActivity((Activity)ACT_HEADCRAB_THREAT_DISPLAY) ) - return SCHED_HEADCRAB_WAKE_ANGRY; - else - return SCHED_HEADCRAB_WAKE_ANGRY_NO_DISPLAY; - } - - case SCHED_RANGE_ATTACK1: - return SCHED_HEADCRAB_RANGE_ATTACK1; - - case SCHED_FAIL_TAKE_COVER: - return SCHED_ALERT_FACE; - - case SCHED_CHASE_ENEMY_FAILED: - { - if( !GetEnemy() ) - break; - - if( !HasCondition( COND_SEE_ENEMY ) ) - break; - - float flZDiff; - flZDiff = GetEnemy()->GetAbsOrigin().z - GetAbsOrigin().z; - - // Make sure the enemy isn't so high above me that this would look silly. - if( flZDiff < 128.0f || flZDiff > 512.0f ) - return SCHED_COMBAT_PATROL; - - float flDist; - flDist = ( GetEnemy()->GetAbsOrigin() - GetAbsOrigin() ).Length2D(); - - // Maybe a patrol will bring me closer. - if( flDist > 384.0f ) - { - return SCHED_COMBAT_PATROL; - } - - return SCHED_HEADCRAB_HARASS_ENEMY; - } - break; - } - - return BaseClass::TranslateSchedule( scheduleType ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBaseHeadcrab::SelectSchedule( void ) -{ - if ( m_bCrawlFromCanister ) - { - m_bCrawlFromCanister = false; - return SCHED_HEADCRAB_CRAWL_FROM_CANISTER; - } - - // If we're hidden or waiting until seen, don't do much at all - if ( m_bHidden || HasSpawnFlags(SF_NPC_WAIT_TILL_SEEN) ) - { - if( HasCondition( COND_HEADCRAB_UNHIDE ) ) - { - // We've decided to unhide - return SCHED_HEADCRAB_UNHIDE; - } - - return m_bBurrowed ? (int)SCHED_HEADCRAB_BURROW_WAIT : (int)SCHED_IDLE_STAND; - } - - if ( GetSpawnFlags() & SF_HEADCRAB_START_HANGING && IsHangingFromCeiling() == false ) - { - return SCHED_HEADCRAB_CEILING_WAIT; - } - - if ( IsHangingFromCeiling() ) - { - if ( HL2GameRules()->IsAlyxInDarknessMode() == false && ( HasCondition( COND_CAN_RANGE_ATTACK1 ) || HasCondition( COND_NEW_ENEMY ) ) ) - return SCHED_HEADCRAB_CEILING_DROP; - - if ( HasCondition( COND_LIGHT_DAMAGE ) || HasCondition( COND_HEAVY_DAMAGE ) ) - return SCHED_HEADCRAB_CEILING_DROP; - - return SCHED_HEADCRAB_CEILING_WAIT; - } - - if ( m_bBurrowed ) - { - if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - return SCHED_HEADCRAB_BURROW_OUT; - - return SCHED_HEADCRAB_BURROW_WAIT; - } - - if( HasCondition( COND_HEADCRAB_IN_WATER ) ) - { - // No matter what, drown in water - return SCHED_HEADCRAB_DROWN; - } - - if( HasCondition( COND_HEADCRAB_ILLEGAL_GROUNDENT ) ) - { - // You're on an NPC's head. Get off. - return SCHED_HEADCRAB_HOP_RANDOMLY; - } - - if ( HasCondition( COND_HEADCRAB_BARNACLED ) ) - { - // Caught by a barnacle! - return SCHED_HEADCRAB_BARNACLED; - } - - switch ( m_NPCState ) - { - case NPC_STATE_ALERT: - { - if (HasCondition( COND_LIGHT_DAMAGE ) || HasCondition( COND_HEAVY_DAMAGE )) - { - if ( fabs( GetMotor()->DeltaIdealYaw() ) < ( 1.0 - m_flFieldOfView) * 60 ) // roughly in the correct direction - { - return SCHED_TAKE_COVER_FROM_ORIGIN; - } - else if ( SelectWeightedSequence( ACT_SMALL_FLINCH ) != -1 ) - { - m_flNextFlinchTime = gpGlobals->curtime + random->RandomFloat( 1, 3 ); - return SCHED_SMALL_FLINCH; - } - } - else if (HasCondition( COND_HEAR_DANGER ) || - HasCondition( COND_HEAR_PLAYER ) || - HasCondition( COND_HEAR_WORLD ) || - HasCondition( COND_HEAR_COMBAT )) - { - return SCHED_ALERT_FACE_BESTSOUND; - } - else - { - return SCHED_PATROL_WALK; - } - break; - } - - default: - break; - } - - if ( HasCondition( COND_FLOATING_OFF_GROUND ) ) - { - SetGravity( 1.0 ); - SetGroundEntity( NULL ); - return SCHED_FALL_TO_GROUND; - } - - if ( GetHintNode() && GetHintNode()->HintType() == HINT_HEADCRAB_BURROW_POINT ) - { - // Only burrow if we're not within leap attack distance of our enemy. - if ( ( GetEnemy() == NULL ) || ( ( GetEnemy()->GetAbsOrigin() - GetAbsOrigin() ).Length() > HEADCRAB_MAX_JUMP_DIST ) ) - { - return SCHED_HEADCRAB_RUN_TO_SPECIFIC_BURROW; - } - else - { - // Forget about burrowing, we've got folks to leap at! - GrabHintNode( NULL ); - } - } - - int nSchedule = BaseClass::SelectSchedule(); - if ( nSchedule == SCHED_SMALL_FLINCH ) - { - m_flNextFlinchTime = gpGlobals->curtime + random->RandomFloat( 1, 3 ); - } - - return nSchedule; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CBaseHeadcrab::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ) -{ - if ( failedSchedule == SCHED_BACK_AWAY_FROM_ENEMY && failedTask == TASK_FIND_BACKAWAY_FROM_SAVEPOSITION ) - { - if ( HasCondition( COND_SEE_ENEMY ) ) - { - return SCHED_RANGE_ATTACK1; - } - } - - if ( failedSchedule == SCHED_BACK_AWAY_FROM_ENEMY || failedSchedule == SCHED_PATROL_WALK || failedSchedule == SCHED_COMBAT_PATROL ) - { - if( !IsFirmlyOnGround() ) - { - return SCHED_HEADCRAB_HOP_RANDOMLY; - } - } - - return BaseClass::SelectFailSchedule( failedSchedule, failedTask, taskFailCode ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -// &vecDir - -// *ptr - -//----------------------------------------------------------------------------- -void CBaseHeadcrab::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - CTakeDamageInfo newInfo = info; - - // Ignore if we're in a dynamic scripted sequence - if ( info.GetDamageType() & DMG_PHYSGUN && !IsRunningDynamicInteraction() ) - { - Vector puntDir = ( info.GetDamageForce() * 1000.0f ); - - newInfo.SetDamage( m_iMaxHealth / 3.0f ); - - if( info.GetDamage() >= GetHealth() ) - { - // This blow will be fatal, so scale the damage force - // (it's a unit vector) so that the ragdoll will be - // affected. - newInfo.SetDamageForce( info.GetDamageForce() * 3000.0f ); - } - - PainSound( newInfo ); - SetGroundEntity( NULL ); - ApplyAbsVelocityImpulse( puntDir ); - } - - BaseClass::TraceAttack( newInfo, vecDir, ptr ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CBaseHeadcrab::Ignite( float flFlameLifetime, bool bNPCOnly, float flSize, bool bCalledByLevelDesigner ) -{ - // Can't start on fire if we're burrowed - if ( m_bBurrowed ) - return; - - bool bWasOnFire = IsOnFire(); - -#ifdef HL2_EPISODIC - if( GetHealth() > flFlameLifetime ) - { - // Add some burn time to very healthy headcrabs to fix a bug where - // black headcrabs would sometimes spontaneously extinguish (and survive) - flFlameLifetime += 10.0f; - } -#endif// HL2_EPISODIC - - BaseClass::Ignite( flFlameLifetime, bNPCOnly, flSize, bCalledByLevelDesigner ); - - if( !bWasOnFire ) - { -#ifdef HL2_EPISODIC - if ( HL2GameRules()->IsAlyxInDarknessMode() == true ) - { - GetEffectEntity()->AddEffects( EF_DIMLIGHT ); - } -#endif // HL2_EPISODIC - - // For the poison headcrab, who runs around when ignited - SetActivity( TranslateActivity(GetIdealActivity()) ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: This is a generic function (to be implemented by sub-classes) to -// handle specific interactions between different types of characters -// (For example the barnacle grabbing an NPC) -// Input : Constant for the type of interaction -// Output : true - if sub-class has a response for the interaction -// false - if sub-class has no response -//----------------------------------------------------------------------------- -bool CBaseHeadcrab::HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt) -{ - if (interactionType == g_interactionBarnacleVictimDangle) - { - // Die instantly - return false; - } - else if (interactionType == g_interactionVortigauntStomp) - { - SetIdealState( NPC_STATE_PRONE ); - return true; - } - else if (interactionType == g_interactionVortigauntStompFail) - { - SetIdealState( NPC_STATE_COMBAT ); - return true; - } - else if (interactionType == g_interactionVortigauntStompHit) - { - // Gib the existing guy, but only with legs and guts - m_nGibCount = HEADCRAB_LEGS_GIB_COUNT; - OnTakeDamage ( CTakeDamageInfo( sourceEnt, sourceEnt, m_iHealth, DMG_CRUSH|DMG_ALWAYSGIB ) ); - - // Create dead headcrab in its place - CBaseHeadcrab *pEntity = (CBaseHeadcrab*) CreateEntityByName( "npc_headcrab" ); - pEntity->Spawn(); - pEntity->SetLocalOrigin( GetLocalOrigin() ); - pEntity->SetLocalAngles( GetLocalAngles() ); - pEntity->m_NPCState = NPC_STATE_DEAD; - return true; - } - else if ( (interactionType == g_interactionVortigauntKick) - /* || (interactionType == g_interactionBullsquidThrow) */ - ) - { - SetIdealState( NPC_STATE_PRONE ); - - if( HasHeadroom() ) - { - MoveOrigin( Vector( 0, 0, 1 ) ); - } - - Vector vHitDir = GetLocalOrigin() - sourceEnt->GetLocalOrigin(); - VectorNormalize(vHitDir); - - CTakeDamageInfo info( sourceEnt, sourceEnt, m_iHealth+1, DMG_CLUB ); - CalculateMeleeDamageForce( &info, vHitDir, GetAbsOrigin() ); - - TakeDamage( info ); - - return true; - } - - return BaseClass::HandleInteraction( interactionType, data, sourceEnt ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseHeadcrab::FValidateHintType( CAI_Hint *pHint ) -{ - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &origin - -//----------------------------------------------------------------------------- -void CBaseHeadcrab::ClearBurrowPoint( const Vector &origin ) -{ - CBaseEntity *pEntity = NULL; - float flDist; - Vector vecSpot, vecCenter, vecForce; - - //Cause a ruckus - UTIL_ScreenShake( origin, 1.0f, 80.0f, 1.0f, 256.0f, SHAKE_START ); - - //Iterate on all entities in the vicinity. - for ( CEntitySphereQuery sphere( origin, 128 ); ( pEntity = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() ) - { - if ( pEntity->m_takedamage != DAMAGE_NO && pEntity->Classify() != CLASS_PLAYER && pEntity->VPhysicsGetObject() ) - { - vecSpot = pEntity->BodyTarget( origin ); - vecForce = ( vecSpot - origin ) + Vector( 0, 0, 16 ); - - // decrease damage for an ent that's farther from the bomb. - flDist = VectorNormalize( vecForce ); - - //float mass = pEntity->VPhysicsGetObject()->GetMass(); - CollisionProp()->RandomPointInBounds( vec3_origin, Vector( 1.0f, 1.0f, 1.0f ), &vecCenter ); - - if ( flDist <= 128.0f ) - { - pEntity->VPhysicsGetObject()->Wake(); - pEntity->VPhysicsGetObject()->ApplyForceOffset( vecForce * 250.0f, vecCenter ); - } - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Determine whether a point is valid or not for burrowing up into -// Input : &point - point to test for validity -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseHeadcrab::ValidBurrowPoint( const Vector &point ) -{ - trace_t tr; - - AI_TraceHull( point, point+Vector(0,0,1), GetHullMins(), GetHullMaxs(), - MASK_NPCSOLID, this, GetCollisionGroup(), &tr ); - - // See if we were able to get there - if ( ( tr.startsolid ) || ( tr.allsolid ) || ( tr.fraction < 1.0f ) ) - { - CBaseEntity *pEntity = tr.m_pEnt; - - //If it's a physics object, attempt to knock is away, unless it's a car - if ( ( pEntity ) && ( pEntity->VPhysicsGetObject() ) && ( pEntity->GetServerVehicle() == NULL ) ) - { - ClearBurrowPoint( point ); - } - - return false; - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseHeadcrab::GrabHintNode( CAI_Hint *pHint ) -{ - // Free up the node for use - ClearHintNode(); - - if ( pHint ) - { - SetHintNode( pHint ); - pHint->Lock( this ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Finds a point where the headcrab can burrow underground. -// Input : distance - radius to search for burrow spot in -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseHeadcrab::FindBurrow( const Vector &origin, float distance, bool excludeNear ) -{ - // Attempt to find a burrowing point - CHintCriteria hintCriteria; - - hintCriteria.SetHintType( HINT_HEADCRAB_BURROW_POINT ); - hintCriteria.SetFlag( bits_HINT_NODE_NEAREST ); - - hintCriteria.AddIncludePosition( origin, distance ); - - if ( excludeNear ) - { - hintCriteria.AddExcludePosition( origin, 128 ); - } - - CAI_Hint *pHint = CAI_HintManager::FindHint( this, hintCriteria ); - - if ( pHint == NULL ) - return false; - - GrabHintNode( pHint ); - - // Setup our path and attempt to run there - Vector vHintPos; - pHint->GetPosition( this, &vHintPos ); - - AI_NavGoal_t goal( vHintPos, ACT_RUN ); - - return GetNavigator()->SetGoal( goal ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseHeadcrab::Burrow( void ) -{ - // Stop us from taking damage and being solid - m_spawnflags |= SF_NPC_GAG; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseHeadcrab::Unburrow( void ) -{ - // Become solid again and visible - m_spawnflags &= ~SF_NPC_GAG; - RemoveSolidFlags( FSOLID_NOT_SOLID ); - m_takedamage = DAMAGE_YES; - - SetGroundEntity( NULL ); - - // If we have an enemy, come out facing them - if ( GetEnemy() ) - { - Vector dir = GetEnemy()->GetAbsOrigin() - GetAbsOrigin(); - VectorNormalize(dir); - - GetMotor()->SetIdealYaw( dir ); - - QAngle angles = GetLocalAngles(); - angles[YAW] = UTIL_VecToYaw( dir ); - SetLocalAngles( angles ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Tells the headcrab to unburrow as soon the space is clear. -//----------------------------------------------------------------------------- -void CBaseHeadcrab::InputUnburrow( inputdata_t &inputdata ) -{ - if ( IsAlive() == false ) - return; - - SetSchedule( SCHED_HEADCRAB_WAIT_FOR_CLEAR_UNBURROW ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Tells the headcrab to run to a nearby burrow point and burrow. -//----------------------------------------------------------------------------- -void CBaseHeadcrab::InputBurrow( inputdata_t &inputdata ) -{ - if ( IsAlive() == false ) - return; - - SetSchedule( SCHED_HEADCRAB_RUN_TO_BURROW_IN ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Tells the headcrab to burrow right where he is. -//----------------------------------------------------------------------------- -void CBaseHeadcrab::InputBurrowImmediate( inputdata_t &inputdata ) -{ - if ( IsAlive() == false ) - return; - - SetSchedule( SCHED_HEADCRAB_BURROW_IN ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseHeadcrab::InputStartHangingFromCeiling( inputdata_t &inputdata ) -{ - if ( IsAlive() == false ) - return; - - SetSchedule( SCHED_HEADCRAB_CEILING_WAIT ); - m_flIlluminatedTime = -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseHeadcrab::InputDropFromCeiling( inputdata_t &inputdata ) -{ - if ( IsAlive() == false ) - return; - - if ( IsHangingFromCeiling() == false ) - return; - - SetSchedule( SCHED_HEADCRAB_CEILING_DROP ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseHeadcrab::CreateDust( bool placeDecal ) -{ - trace_t tr; - AI_TraceLine( GetAbsOrigin()+Vector(0,0,1), GetAbsOrigin()-Vector(0,0,64), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction < 1.0f ) - { - const surfacedata_t *pdata = physprops->GetSurfaceData( tr.surface.surfaceProps ); - - if ( ( (char) pdata->game.material == CHAR_TEX_CONCRETE ) || ( (char) pdata->game.material == CHAR_TEX_DIRT ) ) - { - UTIL_CreateAntlionDust( tr.endpos + Vector(0, 0, 24), GetLocalAngles() ); - - //CEffectData data; - //data.m_vOrigin = GetAbsOrigin(); - //data.m_vNormal = tr.plane.normal; - //DispatchEffect( "headcrabdust", data ); - - if ( placeDecal ) - { - UTIL_DecalTrace( &tr, "Headcrab.Unburrow" ); - } - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHeadcrab::Precache( void ) -{ - PrecacheModel( "models/headcrabclassic.mdl" ); - - PrecacheScriptSound( "NPC_HeadCrab.Gib" ); - PrecacheScriptSound( "NPC_HeadCrab.Idle" ); - PrecacheScriptSound( "NPC_HeadCrab.Alert" ); - PrecacheScriptSound( "NPC_HeadCrab.Pain" ); - PrecacheScriptSound( "NPC_HeadCrab.Die" ); - PrecacheScriptSound( "NPC_HeadCrab.Attack" ); - PrecacheScriptSound( "NPC_HeadCrab.Bite" ); - PrecacheScriptSound( "NPC_Headcrab.BurrowIn" ); - PrecacheScriptSound( "NPC_Headcrab.BurrowOut" ); - - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHeadcrab::Spawn( void ) -{ - Precache(); - SetModel( "models/headcrabclassic.mdl" ); - - BaseClass::Spawn(); - - m_iHealth = sk_headcrab_health.GetFloat(); - m_flBurrowTime = 0.0f; - m_bCrawlFromCanister = false; - m_bMidJump = false; - - NPCInit(); - HeadcrabInit(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Activity CHeadcrab::NPC_TranslateActivity( Activity eNewActivity ) -{ - if ( eNewActivity == ACT_WALK ) - return ACT_RUN; - - return BaseClass::NPC_TranslateActivity( eNewActivity ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHeadcrab::IdleSound( void ) -{ - EmitSound( "NPC_HeadCrab.Idle" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHeadcrab::AlertSound( void ) -{ - EmitSound( "NPC_HeadCrab.Alert" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHeadcrab::PainSound( const CTakeDamageInfo &info ) -{ - if( IsOnFire() && random->RandomInt( 0, HEADCRAB_BURN_SOUND_FREQUENCY ) > 0 ) - { - // Don't squeak every think when burning. - return; - } - - EmitSound( "NPC_HeadCrab.Pain" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHeadcrab::DeathSound( const CTakeDamageInfo &info ) -{ - EmitSound( "NPC_HeadCrab.Die" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHeadcrab::TelegraphSound( void ) -{ - //FIXME: Need a real one - EmitSound( "NPC_HeadCrab.Alert" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHeadcrab::AttackSound( void ) -{ - EmitSound( "NPC_Headcrab.Attack" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHeadcrab::BiteSound( void ) -{ - EmitSound( "NPC_HeadCrab.Bite" ); -} - - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CFastHeadcrab ) - - DEFINE_FIELD( m_iRunMode, FIELD_INTEGER ), - DEFINE_FIELD( m_flRealGroundSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_flSlowRunTime, FIELD_TIME ), - DEFINE_FIELD( m_flPauseTime, FIELD_TIME ), - DEFINE_FIELD( m_vecJumpVel, FIELD_VECTOR ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFastHeadcrab::Precache( void ) -{ - PrecacheModel( "models/headcrab.mdl" ); - - PrecacheScriptSound( "NPC_FastHeadcrab.Idle" ); - PrecacheScriptSound( "NPC_FastHeadcrab.Alert" ); - PrecacheScriptSound( "NPC_FastHeadcrab.Pain" ); - PrecacheScriptSound( "NPC_FastHeadcrab.Die" ); - PrecacheScriptSound( "NPC_FastHeadcrab.Bite" ); - PrecacheScriptSound( "NPC_FastHeadcrab.Attack" ); - - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFastHeadcrab::Spawn( void ) -{ - Precache(); - SetModel( "models/headcrab.mdl" ); - - BaseClass::Spawn(); - - m_iHealth = sk_headcrab_health.GetFloat(); - - m_iRunMode = HEADCRAB_RUNMODE_IDLE; - m_flPauseTime = 999999; - - NPCInit(); - HeadcrabInit(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFastHeadcrab::IdleSound( void ) -{ - EmitSound( "NPC_FastHeadcrab.Idle" ); -} -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFastHeadcrab::AlertSound( void ) -{ - EmitSound( "NPC_FastHeadcrab.Alert" ); -} -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFastHeadcrab::PainSound( const CTakeDamageInfo &info ) -{ - if( IsOnFire() && random->RandomInt( 0, HEADCRAB_BURN_SOUND_FREQUENCY ) > 0 ) - { - // Don't squeak every think when burning. - return; - } - - EmitSound( "NPC_FastHeadcrab.Pain" ); -} -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFastHeadcrab::DeathSound( const CTakeDamageInfo &info ) -{ - EmitSound( "NPC_FastHeadcrab.Die" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFastHeadcrab::PrescheduleThink( void ) -{ -#if 1 // #IF 0 this to stop the accelrating/decelerating movement. -#define HEADCRAB_ACCELERATION 0.1 - if( IsAlive() && GetNavigator()->IsGoalActive() ) - { - switch( m_iRunMode ) - { - case HEADCRAB_RUNMODE_IDLE: - if ( GetActivity() == ACT_RUN ) - { - m_flRealGroundSpeed = m_flGroundSpeed; - m_iRunMode = HEADCRAB_RUNMODE_ACCELERATE; - m_flPlaybackRate = HEADCRAB_RUN_MINSPEED; - } - break; - - case HEADCRAB_RUNMODE_FULLSPEED: - if( gpGlobals->curtime > m_flSlowRunTime ) - { - m_iRunMode = HEADCRAB_RUNMODE_DECELERATE; - } - break; - - case HEADCRAB_RUNMODE_ACCELERATE: - if( m_flPlaybackRate < HEADCRAB_RUN_MAXSPEED ) - { - m_flPlaybackRate += HEADCRAB_ACCELERATION; - } - - if( m_flPlaybackRate >= HEADCRAB_RUN_MAXSPEED ) - { - m_flPlaybackRate = HEADCRAB_RUN_MAXSPEED; - m_iRunMode = HEADCRAB_RUNMODE_FULLSPEED; - - m_flSlowRunTime = gpGlobals->curtime + random->RandomFloat( 0.1, 1.0 ); - } - break; - - case HEADCRAB_RUNMODE_DECELERATE: - m_flPlaybackRate -= HEADCRAB_ACCELERATION; - - if( m_flPlaybackRate <= HEADCRAB_RUN_MINSPEED ) - { - m_flPlaybackRate = HEADCRAB_RUN_MINSPEED; - - // Now stop the crab. - m_iRunMode = HEADCRAB_RUNMODE_PAUSE; - SetActivity( ACT_IDLE ); - GetNavigator()->SetMovementActivity(ACT_IDLE); - m_flPauseTime = gpGlobals->curtime + random->RandomFloat( 0.2, 0.5 ); - m_flRealGroundSpeed = 0.0; - } - break; - - case HEADCRAB_RUNMODE_PAUSE: - { - if( gpGlobals->curtime > m_flPauseTime ) - { - m_iRunMode = HEADCRAB_RUNMODE_IDLE; - SetActivity( ACT_RUN ); - GetNavigator()->SetMovementActivity(ACT_RUN); - m_flPauseTime = gpGlobals->curtime - 1; - m_flRealGroundSpeed = m_flGroundSpeed; - } - } - break; - - default: - Warning( "BIG TIME HEADCRAB ERROR\n" ); - break; - } - - m_flGroundSpeed = m_flRealGroundSpeed * m_flPlaybackRate; - } - else - { - m_flPauseTime = gpGlobals->curtime - 1; - } -#endif - - BaseClass::PrescheduleThink(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : scheduleType - -//----------------------------------------------------------------------------- -int CFastHeadcrab::SelectSchedule( void ) -{ - if ( HasSpawnFlags(SF_NPC_WAIT_TILL_SEEN) ) - { - return SCHED_IDLE_STAND; - } - - if ( HasCondition(COND_CAN_RANGE_ATTACK1) && IsHangingFromCeiling() == false ) - { - if ( OccupyStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - return SCHED_RANGE_ATTACK1; - ClearCondition(COND_CAN_RANGE_ATTACK1); - } - - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : scheduleType - -//----------------------------------------------------------------------------- -int CFastHeadcrab::TranslateSchedule( int scheduleType ) -{ - switch( scheduleType ) - { - case SCHED_IDLE_STAND: - return SCHED_PATROL_WALK; - break; - - case SCHED_RANGE_ATTACK1: - return SCHED_FAST_HEADCRAB_RANGE_ATTACK1; - break; - - case SCHED_CHASE_ENEMY: - if ( !OccupyStrategySlotRange( SQUAD_SLOT_ENGAGE1, SQUAD_SLOT_ENGAGE4 ) ) - return SCHED_PATROL_WALK; - break; - } - - return BaseClass::TranslateSchedule( scheduleType ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTask - -//----------------------------------------------------------------------------- -void CFastHeadcrab::RunTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_RANGE_ATTACK1: - case TASK_RANGE_ATTACK2: - - if ( GetEnemy() ) - // Fast headcrab faces the target in flight. - GetMotor()->SetIdealYawAndUpdate( GetEnemy()->GetAbsOrigin() - GetAbsOrigin(), AI_KEEP_YAW_SPEED ); - - // Call back up into base headcrab for collision. - BaseClass::RunTask( pTask ); - break; - - case TASK_HEADCRAB_HOP_ASIDE: - if ( GetEnemy() ) - GetMotor()->SetIdealYawAndUpdate( GetEnemy()->GetAbsOrigin() - GetAbsOrigin(), AI_KEEP_YAW_SPEED ); - - if( GetFlags() & FL_ONGROUND ) - { - SetGravity(1.0); - SetMoveType( MOVETYPE_STEP ); - - if( GetEnemy() && ( GetEnemy()->GetAbsOrigin() - GetAbsOrigin() ).Length() > HEADCRAB_MAX_JUMP_DIST ) - { - TaskFail( ""); - } - - TaskComplete(); - } - break; - - default: - BaseClass::RunTask( pTask ); - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pTask - -//----------------------------------------------------------------------------- -void CFastHeadcrab::StartTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_HEADCRAB_HOP_ASIDE: - { - Vector vecDir, vecForward, vecRight; - bool fJumpIsLeft; - trace_t tr; - - GetVectors( &vecForward, &vecRight, NULL ); - - fJumpIsLeft = false; - if( random->RandomInt( 0, 100 ) < 50 ) - { - fJumpIsLeft = true; - vecRight.Negate(); - } - - vecDir = ( vecRight + ( vecForward * 2 ) ); - VectorNormalize( vecDir ); - vecDir *= 150.0; - - // This could be a problem. Since I'm adjusting the headcrab's gravity for flight, this check actually - // checks farther ahead than the crab will actually jump. (sjb) - AI_TraceHull( GetAbsOrigin(), GetAbsOrigin() + vecDir,GetHullMins(), GetHullMaxs(), MASK_SHOT, this, GetCollisionGroup(), &tr ); - - //NDebugOverlay::Line( tr.startpos, tr.endpos, 0, 255, 0, false, 1.0 ); - - if( tr.fraction == 1.0 ) - { - AIMoveTrace_t moveTrace; - GetMoveProbe()->MoveLimit( NAV_JUMP, GetAbsOrigin(), tr.endpos, MASK_NPCSOLID, GetEnemy(), &moveTrace ); - - // FIXME: Where should this happen? - m_vecJumpVel = moveTrace.vJumpVelocity; - - if( !IsMoveBlocked( moveTrace ) ) - { - SetAbsVelocity( m_vecJumpVel );// + 0.5f * Vector(0,0,sv_gravity.GetFloat()) * flInterval; - SetGravity( UTIL_ScaleForGravity( 1600 ) ); - SetGroundEntity( NULL ); - SetNavType( NAV_JUMP ); - - if( fJumpIsLeft ) - { - SetIdealActivity( (Activity)ACT_HEADCRAB_HOP_LEFT ); - GetNavigator()->SetMovementActivity( (Activity) ACT_HEADCRAB_HOP_LEFT ); - } - else - { - SetIdealActivity( (Activity)ACT_HEADCRAB_HOP_RIGHT ); - GetNavigator()->SetMovementActivity( (Activity) ACT_HEADCRAB_HOP_RIGHT ); - } - } - else - { - // Can't jump, just fall through. - TaskComplete(); - } - } - else - { - // Can't jump, just fall through. - TaskComplete(); - } - } - break; - - default: - { - BaseClass::StartTask( pTask ); - } - } -} - - -LINK_ENTITY_TO_CLASS( npc_headcrab, CHeadcrab ); -LINK_ENTITY_TO_CLASS( npc_headcrab_fast, CFastHeadcrab ); - - -//----------------------------------------------------------------------------- -// Purpose: Make the sound of this headcrab chomping a target. -// Input : -//----------------------------------------------------------------------------- -void CFastHeadcrab::BiteSound( void ) -{ - EmitSound( "NPC_FastHeadcrab.Bite" ); -} - -void CFastHeadcrab::AttackSound( void ) -{ - EmitSound( "NPC_FastHeadcrab.Attack" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -float CHeadcrab::MaxYawSpeed ( void ) -{ - switch ( GetActivity() ) - { - case ACT_IDLE: - return 30; - - case ACT_RUN: - case ACT_WALK: - return 20; - - case ACT_TURN_LEFT: - case ACT_TURN_RIGHT: - return 15; - - case ACT_RANGE_ATTACK1: - { - const Task_t *pCurTask = GetTask(); - if ( pCurTask && pCurTask->iTask == TASK_HEADCRAB_JUMP_FROM_CANISTER ) - return 15; - } - return 30; - - default: - return 30; - } - - return BaseClass::MaxYawSpeed(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Allows for modification of the interrupt mask for the current schedule. -// In the most cases the base implementation should be called first. -//----------------------------------------------------------------------------- -void CBaseHeadcrab::BuildScheduleTestBits( void ) -{ - if ( !IsCurSchedule(SCHED_HEADCRAB_DROWN) ) - { - // Interrupt any schedule unless already drowning. - SetCustomInterruptCondition( COND_HEADCRAB_IN_WATER ); - } - else - { - // Don't stop drowning just because you're in water! - ClearCustomInterruptCondition( COND_HEADCRAB_IN_WATER ); - } - - if( !IsCurSchedule(SCHED_HEADCRAB_HOP_RANDOMLY) ) - { - SetCustomInterruptCondition( COND_HEADCRAB_ILLEGAL_GROUNDENT ); - } - else - { - ClearCustomInterruptCondition( COND_HEADCRAB_ILLEGAL_GROUNDENT ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CFastHeadcrab::MaxYawSpeed( void ) -{ - switch ( GetActivity() ) - { - case ACT_IDLE: - { - return( 120 ); - } - - case ACT_RUN: - case ACT_WALK: - { - return( 150 ); - } - - case ACT_TURN_LEFT: - case ACT_TURN_RIGHT: - { - return( 120 ); - } - - case ACT_RANGE_ATTACK1: - { - return( 120 ); - } - - default: - { - return( 120 ); - } - } -} - - -bool CFastHeadcrab::QuerySeeEntity(CBaseEntity *pSightEnt, bool bOnlyHateOrFearIfNPC ) -{ - if ( IsHangingFromCeiling() == true ) - return BaseClass::QuerySeeEntity(pSightEnt, bOnlyHateOrFearIfNPC); - - if( m_NPCState != NPC_STATE_COMBAT ) - { - if( fabs( pSightEnt->GetAbsOrigin().z - GetAbsOrigin().z ) >= 150 ) - { - // Don't see things much higher or lower than me unless - // I'm already pissed. - return false; - } - } - - return BaseClass::QuerySeeEntity(pSightEnt, bOnlyHateOrFearIfNPC); -} - - -//----------------------------------------------------------------------------- -// Black headcrab stuff -//----------------------------------------------------------------------------- -int ACT_BLACKHEADCRAB_RUN_PANIC; - -BEGIN_DATADESC( CBlackHeadcrab ) - - DEFINE_FIELD( m_bPanicState, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flPanicStopTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextHopTime, FIELD_TIME ), - - DEFINE_ENTITYFUNC( EjectTouch ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( npc_headcrab_black, CBlackHeadcrab ); -LINK_ENTITY_TO_CLASS( npc_headcrab_poison, CBlackHeadcrab ); - - -//----------------------------------------------------------------------------- -// Purpose: Make the sound of this headcrab chomping a target. -//----------------------------------------------------------------------------- -void CBlackHeadcrab::BiteSound( void ) -{ - EmitSound( "NPC_BlackHeadcrab.Bite" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: The sound we make when leaping at our enemy. -//----------------------------------------------------------------------------- -void CBlackHeadcrab::AttackSound( void ) -{ - EmitSound( "NPC_BlackHeadcrab.Attack" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBlackHeadcrab::TelegraphSound( void ) -{ - EmitSound( "NPC_BlackHeadcrab.Telegraph" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBlackHeadcrab::Spawn( void ) -{ - Precache(); - SetModel( "models/headcrabblack.mdl" ); - - BaseClass::Spawn(); - - m_bPanicState = false; - m_iHealth = sk_headcrab_poison_health.GetFloat(); - - NPCInit(); - HeadcrabInit(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBlackHeadcrab::Precache( void ) -{ - PrecacheModel( "models/headcrabblack.mdl" ); - - PrecacheScriptSound( "NPC_BlackHeadcrab.Telegraph" ); - PrecacheScriptSound( "NPC_BlackHeadcrab.Attack" ); - PrecacheScriptSound( "NPC_BlackHeadcrab.Bite" ); - PrecacheScriptSound( "NPC_BlackHeadcrab.Threat" ); - PrecacheScriptSound( "NPC_BlackHeadcrab.Alert" ); - PrecacheScriptSound( "NPC_BlackHeadcrab.Idle" ); - PrecacheScriptSound( "NPC_BlackHeadcrab.Talk" ); - PrecacheScriptSound( "NPC_BlackHeadcrab.AlertVoice" ); - PrecacheScriptSound( "NPC_BlackHeadcrab.Pain" ); - PrecacheScriptSound( "NPC_BlackHeadcrab.Die" ); - PrecacheScriptSound( "NPC_BlackHeadcrab.Impact" ); - PrecacheScriptSound( "NPC_BlackHeadcrab.ImpactAngry" ); - - PrecacheScriptSound( "NPC_BlackHeadcrab.FootstepWalk" ); - PrecacheScriptSound( "NPC_BlackHeadcrab.Footstep" ); - - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns the max yaw speed for the current activity. -//----------------------------------------------------------------------------- -float CBlackHeadcrab::MaxYawSpeed( void ) -{ - // Not a constant, can't be in a switch statement. - if ( GetActivity() == ACT_BLACKHEADCRAB_RUN_PANIC ) - { - return 30; - } - - switch ( GetActivity() ) - { - case ACT_WALK: - case ACT_RUN: - { - return 10; - } - - case ACT_TURN_LEFT: - case ACT_TURN_RIGHT: - { - return( 30 ); - } - - case ACT_RANGE_ATTACK1: - { - return( 30 ); - } - - default: - { - return( 30 ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Activity CBlackHeadcrab::NPC_TranslateActivity( Activity eNewActivity ) -{ - if ( eNewActivity == ACT_RUN || eNewActivity == ACT_WALK ) - { - if( m_bPanicState || IsOnFire() ) - { - return ( Activity )ACT_BLACKHEADCRAB_RUN_PANIC; - } - } - - return BaseClass::NPC_TranslateActivity( eNewActivity ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBlackHeadcrab::PrescheduleThink( void ) -{ - BaseClass::PrescheduleThink(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBlackHeadcrab::TranslateSchedule( int scheduleType ) -{ - switch ( scheduleType ) - { - // Keep trying to take cover for at least a few seconds. - case SCHED_FAIL_TAKE_COVER: - { - if ( ( m_bPanicState ) && ( gpGlobals->curtime > m_flPanicStopTime ) ) - { - //DevMsg( "I'm sick of panicking\n" ); - m_bPanicState = false; - return SCHED_CHASE_ENEMY; - } - - break; - } - } - - return BaseClass::TranslateSchedule( scheduleType ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Allows for modification of the interrupt mask for the current schedule. -// In the most cases the base implementation should be called first. -//----------------------------------------------------------------------------- -void CBlackHeadcrab::BuildScheduleTestBits( void ) -{ - // Ignore damage if we're attacking or are fleeing and recently flinched. - if ( IsCurSchedule( SCHED_HEADCRAB_CRAWL_FROM_CANISTER ) || IsCurSchedule( SCHED_RANGE_ATTACK1 ) || ( IsCurSchedule( SCHED_TAKE_COVER_FROM_ENEMY ) && HasMemory( bits_MEMORY_FLINCHED ) ) ) - { - ClearCustomInterruptCondition( COND_LIGHT_DAMAGE ); - ClearCustomInterruptCondition( COND_HEAVY_DAMAGE ); - } - else - { - SetCustomInterruptCondition( COND_LIGHT_DAMAGE ); - SetCustomInterruptCondition( COND_HEAVY_DAMAGE ); - } - - // If we're committed to jump, carry on even if our enemy hides behind a crate. Or a barrel. - if ( IsCurSchedule( SCHED_RANGE_ATTACK1 ) && m_bCommittedToJump ) - { - ClearCustomInterruptCondition( COND_ENEMY_OCCLUDED ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : -//----------------------------------------------------------------------------- -int CBlackHeadcrab::SelectSchedule( void ) -{ - // don't override inherited behavior when hanging from ceiling - if ( !IsHangingFromCeiling() ) - { - if ( HasSpawnFlags(SF_NPC_WAIT_TILL_SEEN) ) - { - return SCHED_IDLE_STAND; - } - - if ( HasCondition( COND_LIGHT_DAMAGE ) || HasCondition( COND_HEAVY_DAMAGE ) ) - { - if ( ( gpGlobals->curtime >= m_flNextHopTime ) && SelectWeightedSequence( ACT_SMALL_FLINCH ) != -1 ) - { - m_flNextHopTime = gpGlobals->curtime + random->RandomFloat( 1, 3 ); - return SCHED_SMALL_FLINCH; - } - } - - if ( m_bPanicState ) - { - // We're looking for a place to hide, and we've found one. Lurk! - if ( HasMemory( bits_MEMORY_INCOVER ) ) - { - m_bPanicState = false; - m_flPanicStopTime = gpGlobals->curtime; - - return SCHED_HEADCRAB_AMBUSH; - } - - return SCHED_TAKE_COVER_FROM_ENEMY; - } - } - - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -// Purpose: Black headcrab's touch attack damage. Evil! -//----------------------------------------------------------------------------- -void CBlackHeadcrab::TouchDamage( CBaseEntity *pOther ) -{ - if ( pOther->m_iHealth > 1 ) - { - CTakeDamageInfo info; - if ( CalcDamageInfo( &info ) >= pOther->m_iHealth ) - info.SetDamage( pOther->m_iHealth - 1 ); - - pOther->TakeDamage( info ); - - if ( pOther->IsAlive() && pOther->m_iHealth > 1) - { - // Episodic change to avoid NPCs dying too quickly from poison bites - if ( hl2_episodic.GetBool() ) - { - if ( pOther->IsPlayer() ) - { - // That didn't finish them. Take them down to one point with poison damage. It'll heal. - pOther->TakeDamage( CTakeDamageInfo( this, this, pOther->m_iHealth - 1, DMG_POISON ) ); - } - else - { - // Just take some amount of slash damage instead - pOther->TakeDamage( CTakeDamageInfo( this, this, sk_headcrab_poison_npc_damage.GetFloat(), DMG_SLASH ) ); - } - } - else - { - // That didn't finish them. Take them down to one point with poison damage. It'll heal. - pOther->TakeDamage( CTakeDamageInfo( this, this, pOther->m_iHealth - 1, DMG_POISON ) ); - } - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Bails out of our host zombie, either because he died or was blown -// into two pieces by an explosion. -// Input : vecAngles - The yaw direction we should face. -// flVelocityScale - A multiplier for our ejection velocity. -// pEnemy - Who we should acquire as our enemy. Usually our zombie host's enemy. -//----------------------------------------------------------------------------- -void CBlackHeadcrab::Eject( const QAngle &vecAngles, float flVelocityScale, CBaseEntity *pEnemy ) -{ - SetGroundEntity( NULL ); - m_spawnflags |= SF_NPC_FALL_TO_GROUND; - - SetIdealState( NPC_STATE_ALERT ); - - if ( pEnemy ) - { - SetEnemy( pEnemy ); - UpdateEnemyMemory(pEnemy, pEnemy->GetAbsOrigin()); - } - - SetActivity( ACT_RANGE_ATTACK1 ); - - SetNextThink( gpGlobals->curtime ); - PhysicsSimulate(); - - GetMotor()->SetIdealYaw( vecAngles.y ); - - SetAbsVelocity( flVelocityScale * random->RandomInt( 20, 50 ) * - Vector( random->RandomFloat( -1.0, 1.0 ), random->RandomFloat( -1.0, 1.0 ), random->RandomFloat( 0.5, 1.0 ) ) ); - - m_bMidJump = false; - SetTouch( &CBlackHeadcrab::EjectTouch ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Touch function for when we are ejected from the poison zombie. -// Panic when we hit the ground. -//----------------------------------------------------------------------------- -void CBlackHeadcrab::EjectTouch( CBaseEntity *pOther ) -{ - LeapTouch( pOther ); - if ( GetFlags() & FL_ONGROUND ) - { - // Keep trying to take cover for at least a few seconds. - Panic( random->RandomFloat( 2, 8 ) ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Puts us in a state in which we just want to hide. We'll stop -// hiding after the given duration. -//----------------------------------------------------------------------------- -void CBlackHeadcrab::Panic( float flDuration ) -{ - m_flPanicStopTime = gpGlobals->curtime + flDuration; - m_bPanicState = true; -} - - -#if HL2_EPISODIC -//----------------------------------------------------------------------------- -// Purpose: Black headcrabs have 360-degree vision when they are in the ambush -// schedule. This is because they ignore sounds when in ambush, and -// you could walk up behind them without having them attack you. -// This vision extends only 24 feet. -//----------------------------------------------------------------------------- -#define CRAB_360_VIEW_DIST_SQR (12 * 12 * 24 * 24) -bool CBlackHeadcrab::FInViewCone( CBaseEntity *pEntity ) -{ - if( IsCurSchedule( SCHED_HEADCRAB_AMBUSH ) && - (( pEntity->IsNPC() || pEntity->IsPlayer() ) && pEntity->GetAbsOrigin().DistToSqr(GetAbsOrigin()) <= CRAB_360_VIEW_DIST_SQR ) ) - { - // Only see players and NPC's with 360 cone - // For instance, DON'T tell the eyeball/head tracking code that you can see an object that is behind you! - return true; - } - else - { - return BaseClass::FInViewCone( pEntity ); - } -} -#endif - - -//----------------------------------------------------------------------------- -// Purpose: Does a spastic hop in a random or provided direction. -// Input : pvecDir - 2D direction to hop, NULL picks a random direction. -//----------------------------------------------------------------------------- -void CBlackHeadcrab::JumpFlinch( const Vector *pvecDir ) -{ - SetGroundEntity( NULL ); - - // - // Take him off ground so engine doesn't instantly reset FL_ONGROUND. - // - if( HasHeadroom() ) - { - MoveOrigin( Vector( 0, 0, 1 ) ); - } - - // - // Jump in a random direction. - // - Vector up; - AngleVectors( GetLocalAngles(), NULL, NULL, &up ); - - if (pvecDir) - { - SetAbsVelocity( Vector( pvecDir->x * 4, pvecDir->y * 4, up.z ) * random->RandomFloat( 40, 80 ) ); - } - else - { - SetAbsVelocity( Vector( random->RandomFloat( -4, 4 ), random->RandomFloat( -4, 4 ), up.z ) * random->RandomFloat( 40, 80 ) ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Catches the monster-specific messages that occur when tagged -// animation frames are played. -// Input : pEvent - -//----------------------------------------------------------------------------- -void CBlackHeadcrab::HandleAnimEvent( animevent_t *pEvent ) -{ - if ( pEvent->event == AE_POISONHEADCRAB_FOOTSTEP ) - { - bool walk = ( GetActivity() == ACT_WALK ); // ? 1.0 : 0.6; !!cgreen! old code had bug - - if ( walk ) - { - EmitSound( "NPC_BlackHeadcrab.FootstepWalk" ); - } - else - { - EmitSound( "NPC_BlackHeadcrab.Footstep" ); - } - - return; - } - - if ( pEvent->event == AE_HEADCRAB_JUMP_TELEGRAPH ) - { - EmitSound( "NPC_BlackHeadcrab.Telegraph" ); - - CBaseEntity *pEnemy = GetEnemy(); - - if ( pEnemy ) - { - // Once we telegraph, we MUST jump. This is also when commit to what point - // we jump at. Jump at our enemy's eyes. - m_vecCommittedJumpPos = pEnemy->EyePosition(); - m_bCommittedToJump = true; - } - - return; - } - - if ( pEvent->event == AE_POISONHEADCRAB_THREAT_SOUND ) - { - EmitSound( "NPC_BlackHeadcrab.Threat" ); - EmitSound( "NPC_BlackHeadcrab.Alert" ); - - return; - } - - if ( pEvent->event == AE_POISONHEADCRAB_FLINCH_HOP ) - { - // - // Hop in a random direction, then run and hide. If we're already running - // to hide, jump forward -- hopefully that will take us closer to a hiding spot. - // - if (m_bPanicState) - { - Vector vecForward; - AngleVectors( GetLocalAngles(), &vecForward ); - JumpFlinch( &vecForward ); - } - else - { - JumpFlinch( NULL ); - } - - Panic( random->RandomFloat( 2, 5 ) ); - - return; - } - - BaseClass::HandleAnimEvent( pEvent ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CBlackHeadcrab::IsHeavyDamage( const CTakeDamageInfo &info ) -{ - if ( !HasMemory(bits_MEMORY_FLINCHED) && info.GetDamage() > 1.0f ) - { - // If I haven't flinched lately, any amount of damage is interpreted as heavy. - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBlackHeadcrab::IdleSound( void ) -{ - // TODO: hook up "Marco" / "Polo" talking with nearby buddies - if ( m_NPCState == NPC_STATE_IDLE ) - { - EmitSound( "NPC_BlackHeadcrab.Idle" ); - } - else if ( m_NPCState == NPC_STATE_ALERT ) - { - EmitSound( "NPC_BlackHeadcrab.Talk" ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBlackHeadcrab::AlertSound( void ) -{ - EmitSound( "NPC_BlackHeadcrab.AlertVoice" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBlackHeadcrab::PainSound( const CTakeDamageInfo &info ) -{ - if( IsOnFire() && random->RandomInt( 0, HEADCRAB_BURN_SOUND_FREQUENCY ) > 0 ) - { - // Don't squeak every think when burning. - return; - } - - EmitSound( "NPC_BlackHeadcrab.Pain" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBlackHeadcrab::DeathSound( const CTakeDamageInfo &info ) -{ - EmitSound( "NPC_BlackHeadcrab.Die" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Played when we jump and hit something that we can't bite. -//----------------------------------------------------------------------------- -void CBlackHeadcrab::ImpactSound( void ) -{ - EmitSound( "NPC_BlackHeadcrab.Impact" ); - - if ( !( GetFlags() & FL_ONGROUND ) ) - { - // Hit a wall - make a pissed off sound. - EmitSound( "NPC_BlackHeadcrab.ImpactAngry" ); - } -} - - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC( npc_headcrab, CBaseHeadcrab ) - - DECLARE_TASK( TASK_HEADCRAB_HOP_ASIDE ) - DECLARE_TASK( TASK_HEADCRAB_DROWN ) - DECLARE_TASK( TASK_HEADCRAB_HOP_OFF_NPC ) - DECLARE_TASK( TASK_HEADCRAB_WAIT_FOR_BARNACLE_KILL ) - DECLARE_TASK( TASK_HEADCRAB_UNHIDE ) - DECLARE_TASK( TASK_HEADCRAB_HARASS_HOP ) - DECLARE_TASK( TASK_HEADCRAB_BURROW ) - DECLARE_TASK( TASK_HEADCRAB_UNBURROW ) - DECLARE_TASK( TASK_HEADCRAB_FIND_BURROW_IN_POINT ) - DECLARE_TASK( TASK_HEADCRAB_BURROW_WAIT ) - DECLARE_TASK( TASK_HEADCRAB_CHECK_FOR_UNBURROW ) - DECLARE_TASK( TASK_HEADCRAB_JUMP_FROM_CANISTER ) - DECLARE_TASK( TASK_HEADCRAB_CLIMB_FROM_CANISTER ) - - DECLARE_TASK( TASK_HEADCRAB_CEILING_POSITION ) - DECLARE_TASK( TASK_HEADCRAB_CEILING_WAIT ) - DECLARE_TASK( TASK_HEADCRAB_CEILING_DETACH ) - DECLARE_TASK( TASK_HEADCRAB_CEILING_FALL ) - DECLARE_TASK( TASK_HEADCRAB_CEILING_LAND ) - - DECLARE_ACTIVITY( ACT_HEADCRAB_THREAT_DISPLAY ) - DECLARE_ACTIVITY( ACT_HEADCRAB_HOP_LEFT ) - DECLARE_ACTIVITY( ACT_HEADCRAB_HOP_RIGHT ) - DECLARE_ACTIVITY( ACT_HEADCRAB_DROWN ) - DECLARE_ACTIVITY( ACT_HEADCRAB_BURROW_IN ) - DECLARE_ACTIVITY( ACT_HEADCRAB_BURROW_OUT ) - DECLARE_ACTIVITY( ACT_HEADCRAB_BURROW_IDLE ) - DECLARE_ACTIVITY( ACT_HEADCRAB_CRAWL_FROM_CANISTER_LEFT ) - DECLARE_ACTIVITY( ACT_HEADCRAB_CRAWL_FROM_CANISTER_CENTER ) - DECLARE_ACTIVITY( ACT_HEADCRAB_CRAWL_FROM_CANISTER_RIGHT ) - DECLARE_ACTIVITY( ACT_HEADCRAB_CEILING_FALL ) - - DECLARE_ACTIVITY( ACT_HEADCRAB_CEILING_IDLE ) - DECLARE_ACTIVITY( ACT_HEADCRAB_CEILING_DETACH ) - DECLARE_ACTIVITY( ACT_HEADCRAB_CEILING_LAND ) - - DECLARE_CONDITION( COND_HEADCRAB_IN_WATER ) - DECLARE_CONDITION( COND_HEADCRAB_ILLEGAL_GROUNDENT ) - DECLARE_CONDITION( COND_HEADCRAB_BARNACLED ) - DECLARE_CONDITION( COND_HEADCRAB_UNHIDE ) - - //Adrian: events go here - DECLARE_ANIMEVENT( AE_HEADCRAB_JUMPATTACK ) - DECLARE_ANIMEVENT( AE_HEADCRAB_JUMP_TELEGRAPH ) - DECLARE_ANIMEVENT( AE_HEADCRAB_BURROW_IN ) - DECLARE_ANIMEVENT( AE_HEADCRAB_BURROW_IN_FINISH ) - DECLARE_ANIMEVENT( AE_HEADCRAB_BURROW_OUT ) - DECLARE_ANIMEVENT( AE_HEADCRAB_CEILING_DETACH ) - - //========================================================= - // > SCHED_HEADCRAB_RANGE_ATTACK1 - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HEADCRAB_RANGE_ATTACK1, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_RANGE_ATTACK1 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_FACE_IDEAL 0" - " TASK_WAIT_RANDOM 0.5" - "" - " Interrupts" - " COND_ENEMY_OCCLUDED" - " COND_NO_PRIMARY_AMMO" - ) - - //========================================================= - // - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HEADCRAB_WAKE_ANGRY, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE " - " TASK_FACE_IDEAL 0" - " TASK_SOUND_WAKE 0" - " TASK_PLAY_SEQUENCE_FACE_ENEMY ACTIVITY:ACT_HEADCRAB_THREAT_DISPLAY" - "" - " Interrupts" - ) - - //========================================================= - // - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HEADCRAB_WAKE_ANGRY_NO_DISPLAY, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE " - " TASK_FACE_IDEAL 0" - " TASK_SOUND_WAKE 0" - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - ) - - //========================================================= - // > SCHED_FAST_HEADCRAB_RANGE_ATTACK1 - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_FAST_HEADCRAB_RANGE_ATTACK1, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_RANGE_ATTACK1 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_FACE_IDEAL 0" - " TASK_WAIT_RANDOM 0.5" - "" - " Interrupts" - ) - - //========================================================= - // The irreversible process of drowning - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HEADCRAB_DROWN, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_HEADCRAB_FAIL_DROWN" - " TASK_SET_ACTIVITY ACTIVITY:ACT_HEADCRAB_DROWN" - " TASK_HEADCRAB_DROWN 0" - "" - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_HEADCRAB_FAIL_DROWN, - - " Tasks" - " TASK_HEADCRAB_DROWN 0" - "" - " Interrupts" - ) - - - //========================================================= - // Headcrab lurks in place and waits for a chance to jump on - // some unfortunate soul. - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HEADCRAB_AMBUSH, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT_INDEFINITE 0" - - " Interrupts" - " COND_SEE_ENEMY" - " COND_SEE_HATE" - " COND_CAN_RANGE_ATTACK1" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_PROVOKED" - ) - - //========================================================= - // Headcrab has landed atop another NPC or has landed on - // a ledge. Get down! - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HEADCRAB_HOP_RANDOMLY, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_HEADCRAB_HOP_OFF_NPC 0" - - " Interrupts" - ) - - //========================================================= - // Headcrab is in the clutches of a barnacle - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HEADCRAB_BARNACLED, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_HEADCRAB_DROWN" - " TASK_HEADCRAB_WAIT_FOR_BARNACLE_KILL 0" - - " Interrupts" - ) - - //========================================================= - // Headcrab is unhiding - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HEADCRAB_UNHIDE, - - " Tasks" - " TASK_HEADCRAB_UNHIDE 0" - - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_HEADCRAB_HARASS_ENEMY, - - " Tasks" - " TASK_FACE_ENEMY 0" - " TASK_HEADCRAB_HARASS_HOP 0" - " TASK_WAIT_FACE_ENEMY 1" - " TASK_SET_ROUTE_SEARCH_TIME 2" // Spend 2 seconds trying to build a path if stuck - " TASK_GET_PATH_TO_RANDOM_NODE 300" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " Interrupts" - " COND_NEW_ENEMY" - ) - - DEFINE_SCHEDULE - ( - SCHED_HEADCRAB_FALL_TO_GROUND, - - " Tasks" - " TASK_SET_ACTIVITY ACTIVITY:ACT_HEADCRAB_DROWN" - " TASK_FALL_TO_GROUND 0" - "" - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_HEADCRAB_CRAWL_FROM_CANISTER, - " Tasks" - " TASK_HEADCRAB_CLIMB_FROM_CANISTER 0" - " TASK_HEADCRAB_JUMP_FROM_CANISTER 0" - "" - " Interrupts" - ) - - //================================================== - // Burrow In - //================================================== - DEFINE_SCHEDULE - ( - SCHED_HEADCRAB_BURROW_IN, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY_FAILED" - " TASK_HEADCRAB_BURROW 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_HEADCRAB_BURROW_IN" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_HEADCRAB_BURROW_IDLE" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_HEADCRAB_BURROW_WAIT" - "" - " Interrupts" - " COND_TASK_FAILED" - ) - - //================================================== - // Run to a nearby burrow hint and burrow there - //================================================== - DEFINE_SCHEDULE - ( - SCHED_HEADCRAB_RUN_TO_BURROW_IN, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY_FAILED" - " TASK_HEADCRAB_FIND_BURROW_IN_POINT 512" - " TASK_SET_TOLERANCE_DISTANCE 8" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_HEADCRAB_BURROW_IN" - "" - " Interrupts" - " COND_TASK_FAILED" - " COND_GIVE_WAY" - " COND_CAN_RANGE_ATTACK1" - ) - - //================================================== - // Run to m_pHintNode and burrow there - //================================================== - DEFINE_SCHEDULE - ( - SCHED_HEADCRAB_RUN_TO_SPECIFIC_BURROW, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY_FAILED" - " TASK_SET_TOLERANCE_DISTANCE 8" - " TASK_GET_PATH_TO_HINTNODE 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_HEADCRAB_BURROW_IN" - "" - " Interrupts" - " COND_TASK_FAILED" - " COND_GIVE_WAY" - ) - - //================================================== - // Wait until we can unburrow and attack something - //================================================== - DEFINE_SCHEDULE - ( - SCHED_HEADCRAB_BURROW_WAIT, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_HEADCRAB_BURROW_WAIT" - " TASK_HEADCRAB_BURROW_WAIT 1" - "" - " Interrupts" - " COND_TASK_FAILED" - " COND_NEW_ENEMY" // HACK: We don't actually choose a new schedule on new enemy, but - // we need this interrupt so that the headcrab actually acquires - // new enemies while burrowed. (look in ai_basenpc.cpp for "DO NOT mess") - " COND_CAN_RANGE_ATTACK1" - ) - - //================================================== - // Burrow Out - //================================================== - DEFINE_SCHEDULE - ( - SCHED_HEADCRAB_BURROW_OUT, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_HEADCRAB_BURROW_WAIT" - " TASK_HEADCRAB_UNBURROW 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_HEADCRAB_BURROW_OUT" - "" - " Interrupts" - " COND_TASK_FAILED" - ) - - //================================================== - // Wait for it to be clear for unburrowing - //================================================== - DEFINE_SCHEDULE - ( - SCHED_HEADCRAB_WAIT_FOR_CLEAR_UNBURROW, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_HEADCRAB_BURROW_WAIT" - " TASK_HEADCRAB_CHECK_FOR_UNBURROW 1" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_HEADCRAB_BURROW_OUT" - "" - " Interrupts" - " COND_TASK_FAILED" - ) - - //================================================== - // Wait until we can drop. - //================================================== - DEFINE_SCHEDULE - ( - SCHED_HEADCRAB_CEILING_WAIT, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_HEADCRAB_CEILING_DROP" - " TASK_SET_ACTIVITY ACTIVITY:ACT_HEADCRAB_CEILING_IDLE" - " TASK_HEADCRAB_CEILING_POSITION 0" - " TASK_HEADCRAB_CEILING_WAIT 1" - "" - " Interrupts" - " COND_TASK_FAILED" - " COND_NEW_ENEMY" - " COND_CAN_RANGE_ATTACK1" - ) - - //================================================== - // Deatch from ceiling. - //================================================== - DEFINE_SCHEDULE - ( - SCHED_HEADCRAB_CEILING_DROP, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_HEADCRAB_CEILING_WAIT" - " TASK_HEADCRAB_CEILING_DETACH 0" - " TASK_HEADCRAB_CEILING_FALL 0" - " TASK_HEADCRAB_CEILING_LAND 0" - "" - " Interrupts" - " COND_TASK_FAILED" - ) - -AI_END_CUSTOM_NPC() - -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC( npc_headcrab_poison, CBlackHeadcrab ) - - DECLARE_ACTIVITY( ACT_BLACKHEADCRAB_RUN_PANIC ) - - //Adrian: events go here - DECLARE_ANIMEVENT( AE_POISONHEADCRAB_FLINCH_HOP ) - DECLARE_ANIMEVENT( AE_POISONHEADCRAB_FOOTSTEP ) - DECLARE_ANIMEVENT( AE_POISONHEADCRAB_THREAT_SOUND ) - -AI_END_CUSTOM_NPC() - - -AI_BEGIN_CUSTOM_NPC( npc_headcrab_fast, CFastHeadcrab ) - DECLARE_SQUADSLOT( SQUAD_SLOT_ENGAGE1 ) - DECLARE_SQUADSLOT( SQUAD_SLOT_ENGAGE2 ) - DECLARE_SQUADSLOT( SQUAD_SLOT_ENGAGE3 ) - DECLARE_SQUADSLOT( SQUAD_SLOT_ENGAGE4 ) -AI_END_CUSTOM_NPC() diff --git a/game/server/hl2/npc_headcrab.h b/game/server/hl2/npc_headcrab.h deleted file mode 100644 index 87ad163cc..000000000 --- a/game/server/hl2/npc_headcrab.h +++ /dev/null @@ -1,296 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Defines the headcrab, a tiny, jumpy alien parasite. -// -//=============================================================================// - -#ifndef NPC_HEADCRAB_H -#define NPC_HEADCRAB_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_squadslot.h" -#include "ai_basenpc.h" -#include "soundent.h" - - - -abstract_class CBaseHeadcrab : public CAI_BaseNPC -{ - DECLARE_CLASS( CBaseHeadcrab, CAI_BaseNPC ); - -public: - void Spawn( void ); - void Precache( void ); - void RunTask( const Task_t *pTask ); - void StartTask( const Task_t *pTask ); - - void OnChangeActivity( Activity NewActivity ); - - bool IsFirmlyOnGround(); - void MoveOrigin( const Vector &vecDelta ); - void ThrowAt( const Vector &vecPos ); - void ThrowThink( void ); - virtual void JumpAttack( bool bRandomJump, const Vector &vecPos = vec3_origin, bool bThrown = false ); - void JumpToBurrowHint( CAI_Hint *pHint ); - - bool HasHeadroom(); - void LeapTouch ( CBaseEntity *pOther ); - virtual void TouchDamage( CBaseEntity *pOther ); - bool CorpseGib( const CTakeDamageInfo &info ); - void Touch( CBaseEntity *pOther ); - Vector BodyTarget( const Vector &posSrc, bool bNoisy = true ); - float GetAutoAimRadius(); - void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - void Ignite( float flFlameLifetime, bool bNPCOnly = true, float flSize = 0.0f, bool bCalledByLevelDesigner = false ); - - float MaxYawSpeed( void ); - void GatherConditions( void ); - void PrescheduleThink( void ); - Class_T Classify( void ); - void HandleAnimEvent( animevent_t *pEvent ); - int RangeAttack1Conditions ( float flDot, float flDist ); - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - void ClampRagdollForce( const Vector &vecForceIn, Vector *vecForceOut ); - void Event_Killed( const CTakeDamageInfo &info ); - void BuildScheduleTestBits( void ); - bool FValidateHintType( CAI_Hint *pHint ); - - bool IsJumping( void ) { return m_bMidJump; } - - virtual void BiteSound( void ) = 0; - virtual void AttackSound( void ) {}; - virtual void ImpactSound( void ) {}; - virtual void TelegraphSound( void ) {}; - - virtual int SelectSchedule( void ); - virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ); - virtual int TranslateSchedule( int scheduleType ); - - virtual float GetReactionDelay( CBaseEntity *pEnemy ) { return 0.0; } - - bool HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt); - - void CrawlFromCanister(); - - virtual bool AllowedToIgnite( void ) { return true; } - - virtual bool CanBeAnEnemyOf( CBaseEntity *pEnemy ); - - bool IsHangingFromCeiling( void ) - { -#ifdef HL2_EPISODIC - return m_bHangingFromCeiling; -#else - return false; -#endif - } - - virtual void PlayerHasIlluminatedNPC( CBasePlayer *pPlayer, float flDot ); - - void DropFromCeiling( void ); - - DEFINE_CUSTOM_AI; - DECLARE_DATADESC(); - -protected: - void HeadcrabInit(); - - void Leap( const Vector &vecVel ); - - void GrabHintNode( CAI_Hint *pHint ); - bool FindBurrow( const Vector &origin, float distance, bool excludeNear ); - bool ValidBurrowPoint( const Vector &point ); - void ClearBurrowPoint( const Vector &origin ); - void Burrow( void ); - void Unburrow( void ); - void SetBurrowed( bool bBurrowed ); - void JumpFromCanister(); - - // Begins the climb from the canister - void BeginClimbFromCanister(); - - void InputBurrow( inputdata_t &inputdata ); - void InputBurrowImmediate( inputdata_t &inputdata ); - void InputUnburrow( inputdata_t &inputdata ); - - void InputStartHangingFromCeiling( inputdata_t &inputdata ); - void InputDropFromCeiling( inputdata_t &inputdata ); - - int CalcDamageInfo( CTakeDamageInfo *pInfo ); - void CreateDust( bool placeDecal = true ); - - // Eliminates roll + pitch potentially in the headcrab at canister jump time - void EliminateRollAndPitch(); - - float InnateRange1MinRange( void ); - float InnateRange1MaxRange( void ); - -protected: - int m_nGibCount; - float m_flTimeDrown; - Vector m_vecCommittedJumpPos; // The position of our enemy when we locked in our jump attack. - - float m_flNextNPCThink; - float m_flIgnoreWorldCollisionTime; - - bool m_bCommittedToJump; // Whether we have 'locked in' to jump at our enemy. - bool m_bCrawlFromCanister; - bool m_bStartBurrowed; - bool m_bBurrowed; - bool m_bHidden; - bool m_bMidJump; - bool m_bAttackFailed; // whether we ran into a wall during a jump. - - float m_flBurrowTime; - int m_nContext; // for FValidateHintType context - int m_nJumpFromCanisterDir; - - bool m_bHangingFromCeiling; - float m_flIlluminatedTime; -}; - - -//========================================================= -//========================================================= -// The ever popular chubby classic headcrab -//========================================================= -//========================================================= -class CHeadcrab : public CBaseHeadcrab -{ - DECLARE_CLASS( CHeadcrab, CBaseHeadcrab ); - -public: - void Precache( void ); - void Spawn( void ); - - float MaxYawSpeed( void ); - Activity NPC_TranslateActivity( Activity eNewActivity ); - - void BiteSound( void ); - void PainSound( const CTakeDamageInfo &info ); - void DeathSound( const CTakeDamageInfo &info ); - void IdleSound( void ); - void AlertSound( void ); - void AttackSound( void ); - void TelegraphSound( void ); -}; - -//========================================================= -//========================================================= -// The spindly, fast headcrab -//========================================================= -//========================================================= -class CFastHeadcrab : public CBaseHeadcrab -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( CFastHeadcrab, CBaseHeadcrab ); - - void Precache( void ); - void Spawn( void ); - bool QuerySeeEntity(CBaseEntity *pSightEnt, bool bOnlyHateOrFearIfNPC = false); - - float MaxYawSpeed( void ); - - void PrescheduleThink( void ); - void RunTask( const Task_t *pTask ); - void StartTask( const Task_t *pTask ); - - int SelectSchedule( void ); - int TranslateSchedule( int scheduleType ); - - int m_iRunMode; - float m_flRealGroundSpeed; - float m_flSlowRunTime; - float m_flPauseTime; - Vector m_vecJumpVel; - - void BiteSound( void ); - void PainSound( const CTakeDamageInfo &info ); - void DeathSound( const CTakeDamageInfo &info ); - void IdleSound( void ); - void AlertSound( void ); - void AttackSound( void ); - - enum SquadSlot_t - { - SQUAD_SLOT_ENGAGE1 = LAST_SHARED_SQUADSLOT, - SQUAD_SLOT_ENGAGE2, - SQUAD_SLOT_ENGAGE3, - SQUAD_SLOT_ENGAGE4, - }; - - DEFINE_CUSTOM_AI; -}; - - -//========================================================= -//========================================================= -// Treacherous black headcrab -//========================================================= -//========================================================= -class CBlackHeadcrab : public CBaseHeadcrab -{ - DECLARE_CLASS( CBlackHeadcrab, CBaseHeadcrab ); - -public: - void Eject( const QAngle &vecAngles, float flVelocityScale, CBaseEntity *pEnemy ); - void EjectTouch( CBaseEntity *pOther ); - - // - // CBaseHeadcrab implementation. - // - void TouchDamage( CBaseEntity *pOther ); - void BiteSound( void ); - void AttackSound( void ); - - // - // CAI_BaseNPC implementation. - // - virtual void PrescheduleThink( void ); - virtual void BuildScheduleTestBits( void ); - virtual int SelectSchedule( void ); - virtual int TranslateSchedule( int scheduleType ); - - virtual Activity NPC_TranslateActivity( Activity eNewActivity ); - virtual void HandleAnimEvent( animevent_t *pEvent ); - virtual float MaxYawSpeed( void ); - - virtual int GetSoundInterests( void ) { return (BaseClass::GetSoundInterests() | SOUND_DANGER | SOUND_BULLET_IMPACT); } - - bool IsHeavyDamage( const CTakeDamageInfo &info ); - - virtual void PainSound( const CTakeDamageInfo &info ); - virtual void DeathSound( const CTakeDamageInfo &info ); - virtual void IdleSound( void ); - virtual void AlertSound( void ); - virtual void ImpactSound( void ); - virtual void TelegraphSound( void ); -#if HL2_EPISODIC - virtual bool FInViewCone( CBaseEntity *pEntity ); -#endif - - // - // CBaseEntity implementation. - // - virtual void Precache( void ); - virtual void Spawn( void ); - - DEFINE_CUSTOM_AI; - DECLARE_DATADESC(); - -private: - - - void JumpFlinch( const Vector *pvecAwayFromPos ); - void Panic( float flDuration ); - - bool m_bPanicState; - float m_flPanicStopTime; - float m_flNextHopTime; // Keeps us from hopping too often due to damage. -}; - - -#endif // NPC_HEADCRAB_H diff --git a/game/server/hl2/npc_houndeye.cpp b/game/server/hl2/npc_houndeye.cpp deleted file mode 100644 index 806524199..000000000 --- a/game/server/hl2/npc_houndeye.cpp +++ /dev/null @@ -1,1395 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Houndeye - a spooky sonic dog. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "npc_houndeye.h" -#include "ai_default.h" -#include "ai_node.h" -#include "ai_route.h" -#include "AI_Navigator.h" -#include "AI_Motor.h" -#include "AI_Squad.h" -#include "AI_TacticalServices.h" -#include "soundent.h" -#include "EntityList.h" -#include "game.h" -#include "activitylist.h" -#include "hl2_shareddefs.h" -#include "grenade_energy.h" -#include "energy_wave.h" -#include "ai_interactions.h" -#include "ndebugoverlay.h" -#include "NPCEvent.h" -#include "player.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "movevars_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define HOUNDEYE_MAX_ATTACK_RADIUS 500 -#define HOUNDEYE_MIN_ATTACK_RADIUS 100 - -#define HOUNDEYE_EYE_FRAMES 4 // how many different switchable maps for the eye - -ConVar sk_Houndeye_health( "sk_Houndeye_health","0"); -ConVar sk_Houndeye_dmg_blast( "sk_Houndeye_dmg_blast","0"); - -//========================================================= -// Interactions -//========================================================= -int g_interactionHoundeyeGroupAttack = 0; -int g_interactionHoundeyeGroupRetreat = 0; -int g_interactionHoundeyeGroupRalley = 0; - -//========================================================= -// Specialized Tasks -//========================================================= -enum -{ - TASK_HOUND_CLOSE_EYE = LAST_SHARED_TASK, - TASK_HOUND_OPEN_EYE, - TASK_HOUND_THREAT_DISPLAY, - TASK_HOUND_FALL_ASLEEP, - TASK_HOUND_WAKE_UP, - TASK_HOUND_HOP_BACK, - - TASK_HOUND_GET_PATH_TO_CIRCLE, - TASK_HOUND_REVERSE_STRAFE_DIR, -}; - -//----------------------------------------------------------------------------- -// Custom Conditions -//----------------------------------------------------------------------------- -enum Houndeye_Conds -{ - COND_HOUND_GROUP_ATTACK = LAST_SHARED_CONDITION, - COND_HOUND_GROUP_RETREAT, - COND_HOUND_GROUP_RALLEY, -}; - -//========================================================= -// Specialized Shedules -//========================================================= -enum -{ - SCHED_HOUND_AGITATED = LAST_SHARED_SCHEDULE, - SCHED_HOUND_HOP_RETREAT, - SCHED_HOUND_RANGE_ATTACK1, - - SCHED_HOUND_ATTACK_STRAFE, - SCHED_HOUND_ATTACK_STRAFE_REVERSE, - SCHED_HOUND_GROUP_ATTACK, - SCHED_HOUND_GROUP_RETREAT, - SCHED_HOUND_CHASE_ENEMY, - SCHED_HOUND_COVER_WAIT, - SCHED_HOUND_GROUP_RALLEY, -}; - -//========================================================= -// Specialized activities -//========================================================= -int ACT_HOUND_GUARD; - -//========================================================= -// Monster's Anim Events Go Here -//========================================================= -#define HOUND_AE_WARN 1 -#define HOUND_AE_STARTATTACK 2 -#define HOUND_AE_THUMP 3 -#define HOUND_AE_ANGERSOUND1 4 -#define HOUND_AE_ANGERSOUND2 5 -#define HOUND_AE_HOPBACK 6 -#define HOUND_AE_CLOSE_EYE 7 -#define HOUND_AE_LEAP_HIT 8 - -//----------------------------------------------------------------------------- -// Purpose: Initialize the custom schedules -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_Houndeye::InitCustomSchedules(void) -{ - INIT_CUSTOM_AI(CNPC_Houndeye); - - ADD_CUSTOM_TASK(CNPC_Houndeye, TASK_HOUND_CLOSE_EYE); - ADD_CUSTOM_TASK(CNPC_Houndeye, TASK_HOUND_OPEN_EYE); - ADD_CUSTOM_TASK(CNPC_Houndeye, TASK_HOUND_THREAT_DISPLAY); - ADD_CUSTOM_TASK(CNPC_Houndeye, TASK_HOUND_FALL_ASLEEP); - ADD_CUSTOM_TASK(CNPC_Houndeye, TASK_HOUND_WAKE_UP); - ADD_CUSTOM_TASK(CNPC_Houndeye, TASK_HOUND_HOP_BACK); - - ADD_CUSTOM_TASK(CNPC_Houndeye, TASK_HOUND_GET_PATH_TO_CIRCLE); - ADD_CUSTOM_TASK(CNPC_Houndeye, TASK_HOUND_REVERSE_STRAFE_DIR); - - ADD_CUSTOM_CONDITION(CNPC_Houndeye, COND_HOUND_GROUP_ATTACK); - ADD_CUSTOM_CONDITION(CNPC_Houndeye, COND_HOUND_GROUP_RETREAT); - - ADD_CUSTOM_SCHEDULE(CNPC_Houndeye, SCHED_HOUND_HOP_RETREAT); - ADD_CUSTOM_SCHEDULE(CNPC_Houndeye, SCHED_HOUND_RANGE_ATTACK1); - ADD_CUSTOM_SCHEDULE(CNPC_Houndeye, SCHED_HOUND_ATTACK_STRAFE); - ADD_CUSTOM_SCHEDULE(CNPC_Houndeye, SCHED_HOUND_ATTACK_STRAFE_REVERSE); - ADD_CUSTOM_SCHEDULE(CNPC_Houndeye, SCHED_HOUND_GROUP_ATTACK); - ADD_CUSTOM_SCHEDULE(CNPC_Houndeye, SCHED_HOUND_GROUP_RETREAT); - ADD_CUSTOM_SCHEDULE(CNPC_Houndeye, SCHED_HOUND_CHASE_ENEMY); - ADD_CUSTOM_SCHEDULE(CNPC_Houndeye, SCHED_HOUND_COVER_WAIT); - ADD_CUSTOM_SCHEDULE(CNPC_Houndeye, SCHED_HOUND_GROUP_RALLEY); - - ADD_CUSTOM_ACTIVITY(CNPC_Houndeye, ACT_HOUND_GUARD); - - g_interactionHoundeyeGroupAttack = CBaseCombatCharacter::GetInteractionID(); - g_interactionHoundeyeGroupRetreat = CBaseCombatCharacter::GetInteractionID(); - g_interactionHoundeyeGroupRalley = CBaseCombatCharacter::GetInteractionID(); - - AI_LOAD_SCHEDULE(CNPC_Houndeye, SCHED_HOUND_HOP_RETREAT); - AI_LOAD_SCHEDULE(CNPC_Houndeye, SCHED_HOUND_RANGE_ATTACK1); - AI_LOAD_SCHEDULE(CNPC_Houndeye, SCHED_HOUND_ATTACK_STRAFE); - AI_LOAD_SCHEDULE(CNPC_Houndeye, SCHED_HOUND_ATTACK_STRAFE_REVERSE); - AI_LOAD_SCHEDULE(CNPC_Houndeye, SCHED_HOUND_GROUP_ATTACK); - AI_LOAD_SCHEDULE(CNPC_Houndeye, SCHED_HOUND_GROUP_RETREAT); - AI_LOAD_SCHEDULE(CNPC_Houndeye, SCHED_HOUND_CHASE_ENEMY); - AI_LOAD_SCHEDULE(CNPC_Houndeye, SCHED_HOUND_COVER_WAIT); - AI_LOAD_SCHEDULE(CNPC_Houndeye, SCHED_HOUND_GROUP_RALLEY); -} - -LINK_ENTITY_TO_CLASS( npc_houndeye, CNPC_Houndeye ); -IMPLEMENT_CUSTOM_AI( npc_houndeye, CNPC_Houndeye ); - -BEGIN_DATADESC( CNPC_Houndeye ) - - DEFINE_FIELD( m_fAsleep, FIELD_BOOLEAN ), - DEFINE_FIELD( m_fDontBlink, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flNextSecondaryAttack, FIELD_TIME ), - DEFINE_FIELD( m_bLoopClockwise, FIELD_BOOLEAN ), - DEFINE_FIELD( m_pEnergyWave, FIELD_CLASSPTR ), - DEFINE_FIELD( m_flEndEnergyWaveTime, FIELD_TIME ), - -END_DATADESC() - -//========================================================= -// Classify - indicates this monster's place in the -// relationship table. -//========================================================= -Class_T CNPC_Houndeye::Classify ( void ) -{ - return CLASS_HOUNDEYE; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int CNPC_Houndeye::RangeAttack1Conditions ( float flDot, float flDist ) -{ - // I'm not allowed to attack if standing in another hound eye - // (note houndeyes allowed to interpenetrate) - trace_t tr; - AI_TraceHull( GetAbsOrigin(), GetAbsOrigin() + Vector(0,0,0.1), - GetHullMins(), GetHullMaxs(), - MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - if (tr.startsolid) - { - CBaseEntity *pEntity = tr.m_pEnt; - if (pEntity->Classify() == CLASS_HOUNDEYE) - { - return( COND_NONE ); - } - } - - // If I'm really close to my enemy allow me to attack if - // I'm facing regardless of next attack time - if (flDist < 100 && flDot >= 0.3) - { - return COND_CAN_RANGE_ATTACK1; - } - if ( gpGlobals->curtime < m_flNextAttack ) - { - return( COND_NONE ); - } - if (flDist > ( HOUNDEYE_MAX_ATTACK_RADIUS * 0.5 )) - { - return COND_TOO_FAR_TO_ATTACK; - } - if (flDot < 0.3) - { - return COND_NOT_FACING_ATTACK; - } - return COND_CAN_RANGE_ATTACK1; -} - -//----------------------------------------------------------------------------- -// Purpose: Overidden for human grunts because they hear the DANGER sound -// Input : -// Output : -//----------------------------------------------------------------------------- -int CNPC_Houndeye::GetSoundInterests( void ) -{ - return SOUND_WORLD | - SOUND_COMBAT | - SOUND_PLAYER | - SOUND_DANGER; -} - -//========================================================= -// MaxYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -float CNPC_Houndeye::MaxYawSpeed ( void ) -{ - int ys = 90; - - switch ( GetActivity() ) - { - case ACT_CROUCHIDLE://sleeping! - ys = 0; - break; - case ACT_IDLE: - ys = 60; - break; - case ACT_WALK: - ys = 90; - break; - case ACT_RUN: - ys = 90; - break; - case ACT_TURN_LEFT: - case ACT_TURN_RIGHT: - ys = 90; - break; - } - return ys; -} - -//========================================================= -// HandleAnimEvent - catches the monster-specific messages -// that occur when tagged animation frames are played. -//========================================================= -void CNPC_Houndeye::HandleAnimEvent( animevent_t *pEvent ) -{ - switch ( pEvent->event ) - { - case HOUND_AE_WARN: - // do stuff for this event. - WarnSound(); - break; - - case HOUND_AE_STARTATTACK: - WarmUpSound(); - break; - - case HOUND_AE_HOPBACK: - { - float flGravity = sv_gravity.GetFloat(); - - SetGroundEntity( NULL ); - - Vector forward; - AngleVectors( GetLocalAngles(), &forward ); - Vector vecNewVelocity = forward * -200; - //jump up 36 inches - vecNewVelocity.z += sqrt( 2 * flGravity * 36 ); - SetAbsVelocity( vecNewVelocity ); - break; - } - - case HOUND_AE_THUMP: - // emit the shockwaves - SonicAttack(); - m_flNextAttack = gpGlobals->curtime + random->RandomFloat( 5.0, 8.0 ); - break; - - case HOUND_AE_ANGERSOUND1: - { - EmitSound( "NPC_Houndeye.Anger1" ); - } - break; - - case HOUND_AE_ANGERSOUND2: - { - EmitSound( "NPC_Houndeye.Anger2" ); - } - break; - - case HOUND_AE_CLOSE_EYE: - if ( !m_fDontBlink ) - { - //<> pev->skin = HOUNDEYE_EYE_FRAMES - 1; - } - break; - - case HOUND_AE_LEAP_HIT: - { - //<>return;//<> - SetGroundEntity( NULL ); - - // - // Take him off ground so engine doesn't instantly reset FL_ONGROUND. - // - UTIL_SetOrigin( this, GetLocalOrigin() + Vector( 0 , 0 , 1 )); - Vector vecJumpDir; - if ( GetEnemy() != NULL ) - { - Vector vecEnemyEyePos = GetEnemy()->EyePosition(); - - float gravity = sv_gravity.GetFloat(); - if ( gravity <= 1 ) - { - gravity = 1; - } - - // - // How fast does the houndeye need to travel to reach my enemy's eyes given gravity? - // - float height = ( vecEnemyEyePos.z - GetAbsOrigin().z ); - if ( height < 16 ) - { - height = 16; - } - else if ( height > 120 ) - { - height = 120; - } - float speed = sqrt( 2 * gravity * height ); - float time = speed / gravity; - - // - // Scale the sideways velocity to get there at the right time - // - vecJumpDir = vecEnemyEyePos - GetAbsOrigin(); - vecJumpDir = vecJumpDir / time; - - // - // Speed to offset gravity at the desired height. - // - vecJumpDir.z = speed; - - // - // Don't jump too far/fast. - // - float distance = vecJumpDir.Length(); - if ( distance > 650 ) - { - vecJumpDir = vecJumpDir * ( 650.0 / distance ); - } - } - else - { - Vector forward, up; - AngleVectors( GetLocalAngles(), &forward, NULL, &up ); - // - // Jump hop, don't care where. - // - vecJumpDir = Vector( forward.x, forward.y, up.z ) * 350; - } - - SetAbsVelocity( vecJumpDir ); - m_flNextAttack = gpGlobals->curtime + 2; - break; - } - default: - BaseClass::HandleAnimEvent( pEvent ); - break; - } -} - -//========================================================= -// Spawn -//========================================================= -void CNPC_Houndeye::Spawn() -{ - Precache( ); - - SetModel("models/houndeye.mdl"); - SetHullType(HULL_WIDE_SHORT); - SetHullSizeNormal(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - SetBloodColor( BLOOD_COLOR_YELLOW ); - m_iHealth = sk_Houndeye_health.GetFloat(); - m_flFieldOfView = 0.5;// indicates the width of this monster's forward view cone ( as a dotproduct result ) - m_NPCState = NPC_STATE_NONE; - m_fAsleep = false; // everyone spawns awake - m_fDontBlink = false; - CapabilitiesAdd( bits_CAP_SQUAD ); - CapabilitiesAdd( bits_CAP_MOVE_GROUND ); - CapabilitiesAdd( bits_CAP_INNATE_RANGE_ATTACK1 ); - CapabilitiesAdd( bits_CAP_TURN_HEAD ); - - m_flNextSecondaryAttack = 0; - m_bLoopClockwise = random->RandomInt(0,1) ? true : false; - - m_pEnergyWave = NULL; - m_flEndEnergyWaveTime = 0; - - SetCollisionGroup( HL2COLLISION_GROUP_HOUNDEYE ); - - NPCInit(); -} - -//========================================================= -// Precache - precaches all resources this monster needs -//========================================================= -void CNPC_Houndeye::Precache() -{ - PrecacheModel("models/houndeye.mdl"); - - PrecacheScriptSound( "NPC_Houndeye.Anger1" ); - PrecacheScriptSound( "NPC_Houndeye.Anger2" ); - PrecacheScriptSound( "NPC_Houndeye.SpeakSentence" ); - PrecacheScriptSound( "NPC_Houndeye.Idle" ); - PrecacheScriptSound( "NPC_Houndeye.WarmUp" ); - PrecacheScriptSound( "NPC_Houndeye.Warn" ); - PrecacheScriptSound( "NPC_Houndeye.Alert" ); - PrecacheScriptSound( "NPC_Houndeye.Die" ); - PrecacheScriptSound( "NPC_Houndeye.Pain" ); - PrecacheScriptSound( "NPC_Houndeye.Retreat" ); - PrecacheScriptSound( "NPC_Houndeye.SonicAttack" ); - - PrecacheScriptSound( "NPC_Houndeye.GroupAttack" ); - PrecacheScriptSound( "NPC_Houndeye.GroupFollow" ); - - - UTIL_PrecacheOther("grenade_energy"); - BaseClass::Precache(); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_Houndeye::SpeakSentence( int sentenceType ) -{ - if (gpGlobals->curtime > m_flSoundWaitTime) - { - EmitSound( "NPC_Houndeye.SpeakSentence" ); - m_flSoundWaitTime = gpGlobals->curtime + 1.0; - } -} - -//========================================================= -// IdleSound -//========================================================= -void CNPC_Houndeye::IdleSound ( void ) -{ - if (!FOkToMakeSound()) - { - return; - } - CPASAttenuationFilter filter( this,"NPC_Houndeye.Idle" ); - EmitSound( filter, entindex(),"NPC_Houndeye.Idle" ); -} - -//========================================================= -// IdleSound -//========================================================= -void CNPC_Houndeye::WarmUpSound ( void ) -{ - EmitSound( "NPC_Houndeye.WarmUp" ); -} - -//========================================================= -// WarnSound -//========================================================= -void CNPC_Houndeye::WarnSound ( void ) -{ - EmitSound( "NPC_Houndeye.Warn" ); -} - -//========================================================= -// AlertSound -//========================================================= -void CNPC_Houndeye::AlertSound ( void ) -{ - // only first squad member makes ALERT sound. - if ( m_pSquad && !m_pSquad->IsLeader( this ) ) - { - return; - } - - EmitSound( "NPC_Houndeye.Alert" ); -} - -//========================================================= -// DeathSound -//========================================================= -void CNPC_Houndeye::DeathSound ( void ) -{ - EmitSound( "NPC_Houndeye.Die" ); -} - -//========================================================= -// PainSound -//========================================================= -void CNPC_Houndeye::PainSound ( void ) -{ - EmitSound( "NPC_Houndeye.Pain" ); -} - -//========================================================= -// WriteBeamColor - writes a color vector to the network -// based on the size of the group. -//========================================================= -void CNPC_Houndeye::WriteBeamColor ( void ) -{ - BYTE bRed, bGreen, bBlue; - - if ( m_pSquad ) - { - switch ( m_pSquad->NumMembers() ) - { - case 2: - // no case for 0 or 1, cause those are impossible for monsters in Squads. - bRed = 101; - bGreen = 133; - bBlue = 221; - break; - case 3: - bRed = 67; - bGreen = 85; - bBlue = 255; - break; - case 4: - bRed = 62; - bGreen = 33; - bBlue = 211; - break; - default: - DevWarning( 2, "Unsupported Houndeye SquadSize!\n" ); - bRed = 188; - bGreen = 220; - bBlue = 255; - break; - } - } - else - { - // solo houndeye - weakest beam - bRed = 188; - bGreen = 220; - bBlue = 255; - } - - WRITE_BYTE( bRed ); - WRITE_BYTE( bGreen ); - WRITE_BYTE( bBlue ); -} - -//----------------------------------------------------------------------------- -// Purpose: Plays the engine sound. -//----------------------------------------------------------------------------- -void CNPC_Houndeye::NPCThink(void) -{ - if (m_pEnergyWave) - { - if (gpGlobals->curtime > m_flEndEnergyWaveTime) - { - UTIL_Remove(m_pEnergyWave); - m_pEnergyWave = NULL; - } - } - - // ----------------------------------------------------- - // Update collision group - // While I'm running I'm allowed to penetrate - // other houndeyes - // ----------------------------------------------------- - Vector vVelocity; - GetVelocity( &vVelocity, NULL ); - if (vVelocity.Length() > 10) - { - SetCollisionGroup( HL2COLLISION_GROUP_HOUNDEYE ); - } - else - { - // Don't go solid if resting in another houndeye - trace_t tr; - AI_TraceHull( GetAbsOrigin(), GetAbsOrigin() + Vector(0,0,1), - GetHullMins(), GetHullMaxs(), - MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - if (!tr.startsolid) - { - SetCollisionGroup( COLLISION_GROUP_NONE ); - } - else - { - SetCollisionGroup( HL2COLLISION_GROUP_HOUNDEYE ); - } - } -/* - if (GetCollisionGroup() == HL2COLLISION_GROUP_HOUNDEYE) - { - NDebugOverlay::Box(GetAbsOrigin(), GetHullMins(), GetHullMaxs(), 0, 255, 0, 0, 0); - } - else - { - NDebugOverlay::Box(GetAbsOrigin(), GetHullMins(), GetHullMaxs(), 255, 0, 0, 0, 0); - } -*/ - BaseClass::NPCThink(); -} - -//------------------------------------------------------------------------------ -// Purpose : Broadcast retreat occasionally when hurt -// Input : -// Output : -//------------------------------------------------------------------------------ -int CNPC_Houndeye::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - if (m_pSquad && random->RandomInt(0,10) == 10) - { - EmitSound( "NPC_Houndeye.Retreat" ); - m_flSoundWaitTime = gpGlobals->curtime + 1.0; - - m_pSquad->BroadcastInteraction( g_interactionHoundeyeGroupRetreat, NULL, this ); - } - - return BaseClass::OnTakeDamage_Alive( info ); -} - -//------------------------------------------------------------------------------ -// Purpose : Broadcast retreat when member of squad killed -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_Houndeye::Event_Killed( const CTakeDamageInfo &info ) -{ - EmitSound( "NPC_Houndeye.Retreat" ); - m_flSoundWaitTime = gpGlobals->curtime + 1.0; - - if (m_pSquad) - { - m_pSquad->BroadcastInteraction( g_interactionHoundeyeGroupRetreat, NULL, this ); - } - - BaseClass::Event_Killed( info ); -} - -//========================================================= -// SonicAttack -//========================================================= -void CNPC_Houndeye::SonicAttack ( void ) -{ - EmitSound( "NPC_Houndeye.SonicAttack" ); - - if (m_pEnergyWave) - { - UTIL_Remove(m_pEnergyWave); - } - Vector vFacingDir = EyeDirection3D( ); - m_pEnergyWave = (CEnergyWave*)Create( "energy_wave", EyePosition(), GetLocalAngles() ); - m_flEndEnergyWaveTime = gpGlobals->curtime + 1; //<> magic - m_pEnergyWave->SetAbsVelocity( 100*vFacingDir ); - - CBaseEntity *pEntity = NULL; - // iterate on all entities in the vicinity. - for ( CEntitySphereQuery sphere( GetAbsOrigin(), HOUNDEYE_MAX_ATTACK_RADIUS ); pEntity = sphere.GetCurrentEntity(); sphere.NextEntity() ) - { - if (pEntity->Classify() == CLASS_HOUNDEYE) - { - continue; - } - - if (pEntity->GetFlags() & FL_NOTARGET) - { - continue; - } - - IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject(); - - if ( pEntity->m_takedamage != DAMAGE_NO || pPhysicsObject) - { - // -------------------------- - // Adjust damage by distance - // -------------------------- - float flDist = (pEntity->WorldSpaceCenter() - GetAbsOrigin()).Length(); - float flDamageAdjuster = 1-( flDist / HOUNDEYE_MAX_ATTACK_RADIUS ); - - // -------------------------- - // Adjust damage by direction - // -------------------------- - Vector forward; - AngleVectors( GetAbsAngles(), &forward ); - Vector vEntDir = (pEntity->GetAbsOrigin() - GetAbsOrigin()); - VectorNormalize(vEntDir); - float flDotPr = DotProduct(forward,vEntDir); - flDamageAdjuster *= flDotPr; - - if (flDamageAdjuster < 0) - { - continue; - } - - // -------------------------- - // Adjust damage by visibility - // -------------------------- - if ( !FVisible( pEntity ) ) - { - if ( pEntity->IsPlayer() ) - { - // if this entity is a client, and is not in full view, inflict half damage. We do this so that players still - // take the residual damage if they don't totally leave the houndeye's effective radius. We restrict it to clients - // so that monsters in other parts of the level don't take the damage and get pissed. - flDamageAdjuster *= 0.5; - } - else if ( !FClassnameIs( pEntity, "func_breakable" ) && !FClassnameIs( pEntity, "func_pushable" ) ) - { - // do not hurt nonclients through walls, but allow damage to be done to breakables - continue; - } - } - - // ------------------------------ - // Apply the damage - // ------------------------------ - if (pEntity->m_takedamage != DAMAGE_NO) - { - CTakeDamageInfo info( this, this, flDamageAdjuster * sk_Houndeye_dmg_blast.GetFloat(), DMG_SONIC | DMG_ALWAYSGIB ); - CalculateExplosiveDamageForce( &info, (pEntity->GetAbsOrigin() - GetAbsOrigin()), pEntity->GetAbsOrigin() ); - - pEntity->TakeDamage( info ); - - // Throw the player - if ( pEntity->IsPlayer() ) - { - Vector forward; - AngleVectors( GetLocalAngles(), &forward ); - - Vector vecVelocity = pEntity->GetAbsVelocity(); - vecVelocity += forward * 250 * flDamageAdjuster; - vecVelocity.z = 300 * flDamageAdjuster; - pEntity->SetAbsVelocity( vecVelocity ); - pEntity->ViewPunch( QAngle(random->RandomInt(-20,20), 0, random->RandomInt(-20,20)) ); - } - } - // ------------------------------ - // Apply physics foces - // ------------------------------ - IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject(); - if (pPhysicsObject) - { - float flForce = flDamageAdjuster * 8000; - pPhysicsObject->ApplyForceCenter( (vEntDir+Vector(0,0,0.2)) * flForce ); - pPhysicsObject->ApplyTorqueCenter( vEntDir * flForce ); - } - } - } -} - -//========================================================= -// start task -//========================================================= -void CNPC_Houndeye::StartTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_HOUND_GET_PATH_TO_CIRCLE: - { - if (GetEnemy() == NULL) - { - TaskFail(FAIL_NO_ENEMY); - } - else - { - Vector vTargetPos = GetEnemyLKP(); - vTargetPos.z = GetFloorZ(vTargetPos); - - if (GetNavigator()->SetRadialGoal(vTargetPos, random->RandomInt(50,500), 90, 175, m_bLoopClockwise)) - { - TaskComplete(); - return; - } - TaskFail(FAIL_NO_ROUTE); - } - break; - } - case TASK_HOUND_REVERSE_STRAFE_DIR: - { - // Try the other direction - m_bLoopClockwise = (m_bLoopClockwise) ? false : true; - TaskComplete(); - break; - } - - // Override to set appropriate distances - case TASK_GET_PATH_TO_ENEMY_LOS: - { - float flMaxRange = HOUNDEYE_MAX_ATTACK_RADIUS * 0.9; - float flMinRange = HOUNDEYE_MIN_ATTACK_RADIUS; - Vector posLos; - bool foundLos = false; - - if (GetEnemy() != NULL) - { - foundLos = GetTacticalServices()->FindLos(GetEnemyLKP(),GetEnemy()->EyePosition(), flMinRange, flMaxRange, 0.0, &posLos); - } - else - { - TaskFail(FAIL_NO_TARGET); - return; - } - - if (foundLos) - { - GetNavigator()->SetGoal( AI_NavGoal_t( posLos, ACT_RUN, AIN_HULL_TOLERANCE ) ); - } - else - { - TaskFail(FAIL_NO_SHOOT); - } - break; - } - - case TASK_HOUND_FALL_ASLEEP: - { - m_fAsleep = true; // signal that hound is lying down (must stand again before doing anything else!) - TaskComplete( true ); - break; - } - case TASK_HOUND_WAKE_UP: - { - m_fAsleep = false; // signal that hound is standing again - TaskComplete( true ); - break; - } - case TASK_HOUND_OPEN_EYE: - { - m_fDontBlink = false; // turn blinking back on and that code will automatically open the eye - TaskComplete( true ); - break; - } - case TASK_HOUND_CLOSE_EYE: - { -//<> pev->skin = 0; - m_fDontBlink = true; // tell blink code to leave the eye alone. - break; - } - case TASK_HOUND_THREAT_DISPLAY: - { - SetIdealActivity( ACT_IDLE_ANGRY ); - break; - } - case TASK_HOUND_HOP_BACK: - { - SetIdealActivity( ACT_LEAP ); - break; - } - case TASK_RANGE_ATTACK1: - { - SetIdealActivity( ACT_RANGE_ATTACK1 ); - break; - } - default: - { - BaseClass::StartTask(pTask); - break; - } - } -} - -//========================================================= -// RunTask -//========================================================= -void CNPC_Houndeye::RunTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_HOUND_THREAT_DISPLAY: - { - GetMotor()->SetIdealYawToTargetAndUpdate( GetEnemyLKP(), AI_KEEP_YAW_SPEED ); - - if ( IsActivityFinished() ) - { - TaskComplete(); - } - - break; - } - case TASK_HOUND_CLOSE_EYE: - { - /*//<> - if ( pev->skin < HOUNDEYE_EYE_FRAMES - 1 ) - { - pev->skin++; - } - */ - break; - } - case TASK_HOUND_HOP_BACK: - { - if ( IsActivityFinished() ) - { - TaskComplete(); - } - break; - } - default: - { - BaseClass::RunTask(pTask); - break; - } - } -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_Houndeye::PrescheduleThink ( void ) -{ - BaseClass::PrescheduleThink(); - - // if the hound is mad and is running, make hunt noises. - if ( m_NPCState == NPC_STATE_COMBAT && ( GetActivity() == ACT_RUN ) && random->RandomFloat( 0, 1 ) < 0.2 ) - { - WarnSound(); - } - - // at random, initiate a blink if not already blinking or sleeping - if ( !m_fDontBlink ) - { - /*//<>//<> - if ( ( pev->skin == 0 ) && random->RandomInt(0,0x7F) == 0 ) - {// start blinking! - pev->skin = HOUNDEYE_EYE_FRAMES - 1; - } - else if ( pev->skin != 0 ) - {// already blinking - pev->skin--; - } - */ - } -} - -//----------------------------------------------------------------------------- -// Purpose: Override base class activiites -// Input : -// Output : -//----------------------------------------------------------------------------- -Activity CNPC_Houndeye::NPC_TranslateActivity( Activity eNewActivity ) -{ - if ( eNewActivity == ACT_IDLE && m_NPCState == NPC_STATE_COMBAT ) - { - return ACT_IDLE_ANGRY; - } - return eNewActivity; -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -int CNPC_Houndeye::TranslateSchedule( int scheduleType ) -{ - switch( scheduleType ) - { - case SCHED_IDLE_STAND: - { - return BaseClass::TranslateSchedule( scheduleType ); - } - case SCHED_RANGE_ATTACK1: - { - return SCHED_HOUND_RANGE_ATTACK1; - } - case SCHED_CHASE_ENEMY_FAILED: - { - return SCHED_COMBAT_FACE; - } - default: - { - return BaseClass::TranslateSchedule ( scheduleType ); - } - } -} - -//------------------------------------------------------------------------------ -// Purpose : Is anyone in the squad currently attacking -// Input : -// Output : -//------------------------------------------------------------------------------ -bool CNPC_Houndeye::IsAnyoneInSquadAttacking( void ) -{ - if (!m_pSquad) - { - return false; - } - - AISquadIter_t iter; - for (CAI_BaseNPC *pSquadMember = m_pSquad->GetFirstMember( &iter ); pSquadMember; pSquadMember = m_pSquad->GetNextMember( &iter ) ) - { - if (pSquadMember->IsCurSchedule(SCHED_HOUND_RANGE_ATTACK1)) - { - return true; - } - } - return false; -} - -//========================================================= -// SelectSchedule -//========================================================= -int CNPC_Houndeye::SelectSchedule( void ) -{ - switch ( m_NPCState ) - { - case NPC_STATE_IDLE: - case NPC_STATE_ALERT: - { - if ( HasCondition(COND_LIGHT_DAMAGE) || - HasCondition(COND_HEAVY_DAMAGE) ) - { - return SCHED_TAKE_COVER_FROM_ORIGIN; - } - break; - } - case NPC_STATE_COMBAT: - { - // dead enemy - - if ( HasCondition( COND_ENEMY_DEAD ) ) - { - // call base class, all code to handle dead enemies is centralized there. - return BaseClass::SelectSchedule(); - } - - // If a group attack was requested attack even if attack conditions not met - if ( HasCondition( COND_HOUND_GROUP_ATTACK )) - { - // Check that I'm not standing in another hound eye - // before attacking - trace_t tr; - AI_TraceHull( GetAbsOrigin(), GetAbsOrigin() + Vector(0,0,1), - GetHullMins(), GetHullMaxs(), - MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - if (!tr.startsolid) - { - return SCHED_HOUND_GROUP_ATTACK; - } - - // Otherwise attack as soon as I can - else - { - m_flNextAttack = gpGlobals->curtime; - SCHED_HOUND_ATTACK_STRAFE; - } - } - - // If a group retread was requested - if ( HasCondition( COND_HOUND_GROUP_RETREAT )) - { - return SCHED_HOUND_GROUP_RETREAT; - } - - if ( HasCondition( COND_LIGHT_DAMAGE ) | - HasCondition( COND_HEAVY_DAMAGE ) ) - { - if ( random->RandomFloat( 0 , 1 ) <= 0.4 ) - { - trace_t tr; - Vector forward; - AngleVectors( GetAbsAngles(), &forward ); - AI_TraceHull( GetAbsOrigin(), GetAbsOrigin() + forward * -128, - GetHullMins(), GetHullMaxs(), - MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction == 1.0 ) - { - // it's clear behind, so the hound will jump - return SCHED_HOUND_HOP_RETREAT; - } - } - - return SCHED_TAKE_COVER_FROM_ENEMY; - } - - // If a group rally was requested - if ( HasCondition( COND_HOUND_GROUP_RALLEY )) - { - return SCHED_HOUND_GROUP_RALLEY; - } - - if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - { - if (m_pSquad && random->RandomInt(0,4) == 0) - { - if (!IsAnyoneInSquadAttacking()) - { - EmitSound( "NPC_Houndeye.GroupAttack" ); - - m_flSoundWaitTime = gpGlobals->curtime + 1.0; - - m_pSquad->BroadcastInteraction( g_interactionHoundeyeGroupAttack, NULL, this ); - return SCHED_HOUND_GROUP_ATTACK; - } - } - //<>comment - SetCollisionGroup( COLLISION_GROUP_NONE ); - return SCHED_RANGE_ATTACK1; - } - else - { - if (m_pSquad && random->RandomInt(0,5) == 0) - { - if (!IsAnyoneInSquadAttacking()) - { - EmitSound( "NPC_Houndeye.GroupFollow" ); - - m_flSoundWaitTime = gpGlobals->curtime + 1.0; - - m_pSquad->BroadcastInteraction( g_interactionHoundeyeGroupRalley, NULL, this ); - return SCHED_HOUND_ATTACK_STRAFE; - } - } - return SCHED_HOUND_ATTACK_STRAFE; - } - break; - } - } - - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -// Purpose: This is a generic function (to be implemented by sub-classes) to -// handle specific interactions between different types of characters -// (For example the barnacle grabbing an NPC) -// Input : Constant for the type of interaction -// Output : true - if sub-class has a response for the interaction -// false - if sub-class has no response -//----------------------------------------------------------------------------- -bool CNPC_Houndeye::HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt) -{ - if (interactionType == g_interactionHoundeyeGroupAttack) - { - SetCondition(COND_HOUND_GROUP_ATTACK); - return true; - } - else if (interactionType == g_interactionHoundeyeGroupRetreat) - { - SetCondition(COND_HOUND_GROUP_RETREAT); - return true; - } - else if (interactionType == g_interactionHoundeyeGroupRalley) - { - SetCondition(COND_HOUND_GROUP_RALLEY); - SetTarget(sourceEnt); - m_bLoopClockwise = false; - return true; - } - - return false; -} - - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -//========================================================= -// SCHED_HOUND_ATTACK_STRAFE -// -// Run a cirle around my enemy -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_HOUND_ATTACK_STRAFE , - - " Tasks " - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_HOUND_ATTACK_STRAFE_REVERSE" - " TASK_HOUND_GET_PATH_TO_CIRCLE 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts " - " COND_WEAPON_SIGHT_OCCLUDED" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_HEAVY_DAMAGE" - " COND_CAN_RANGE_ATTACK1" - " COND_HOUND_GROUP_ATTACK" - " COND_HOUND_GROUP_RETREAT" -); - -//========================================================= -// SCHED_HOUND_ATTACK_STRAFE_REVERSE -// -// Run a cirle around my enemy -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_HOUND_ATTACK_STRAFE_REVERSE , - - " Tasks " - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_HOUND_CHASE_ENEMY" - " TASK_HOUND_REVERSE_STRAFE_DIR 0" - " TASK_HOUND_GET_PATH_TO_CIRCLE 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts " - " COND_WEAPON_SIGHT_OCCLUDED" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_HEAVY_DAMAGE" - " COND_CAN_RANGE_ATTACK1" - " COND_HOUND_GROUP_ATTACK" - " COND_HOUND_GROUP_RETREAT" -); - -//======================================================== -// SCHED_HOUND_CHASE_ENEMY -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_HOUND_CHASE_ENEMY, - - " Tasks" - " TASK_SET_TOLERANCE_DISTANCE 30 " - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY_FAILED" - " TASK_GET_PATH_TO_ENEMY 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_CAN_RANGE_ATTACK1" - " COND_HOUND_GROUP_ATTACK" - " COND_HOUND_GROUP_RETREAT" -); - -//========================================================= -// SCHED_HOUND_GROUP_ATTACK -// -// Face enemy, pause, then attack -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_HOUND_GROUP_ATTACK , - - " Tasks " - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE_ANGRY" - " TASK_SPEAK_SENTENCE 0" - " TASK_WAIT 1" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_HOUND_RANGE_ATTACK1" - "" - " Interrupts " - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_HEAVY_DAMAGE" -); - -//========================================================= -// > SCHED_HOUND_GROUP_RETREAT -// -// Take cover from enemy! -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_HOUND_GROUP_RETREAT, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_HOUND_ATTACK_STRAFE" - " TASK_STOP_MOVING 0" - " TASK_WAIT 0.2" - " TASK_SET_TOLERANCE_DISTANCE 24" - " TASK_FIND_COVER_FROM_ENEMY 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_REMEMBER MEMORY:INCOVER" - " TASK_FACE_ENEMY 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" // Translated to cover - " TASK_SET_SCHEDULE SCHEDULE:SCHED_HOUND_COVER_WAIT" - "" - " Interrupts" - " COND_NEW_ENEMY" -); - -//========================================================= -// > SCHED_HOUND_GROUP_RALLEY -// -// Run to rally hound! -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_HOUND_GROUP_RALLEY, - - " Tasks" - " TASK_SET_TOLERANCE_DISTANCE 30" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_HOUND_ATTACK_STRAFE" - " TASK_GET_PATH_TO_TARGET 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_HEAVY_DAMAGE" - " COND_HOUND_GROUP_ATTACK" - " COND_HOUND_GROUP_RETREAT" -); - -//========================================================= -// > SCHED_HOUND_COVER_WAIT -// -// Wait in cover till enemy see's me or I take damage -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_HOUND_COVER_WAIT, - - " Tasks" - " TASK_WAIT 2" - "" - " Interrupts" - " COND_SEE_ENEMY" - " COND_LIGHT_DAMAGE" -); - -//========================================================= -// > SCHED_HOUND_RANGE_ATTACK1 -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_HOUND_RANGE_ATTACK1, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE_ANGRY" - " TASK_FACE_IDEAL 0" - " TASK_RANGE_ATTACK1 0" - "" - " Interrupts" - //" COND_LIGHT_DAMAGE" // don't interupt on small damage - " COND_HEAVY_DAMAGE" -); - -//========================================================= -// > SCHED_HOUND_HOP_RETREAT -//========================================================= -AI_DEFINE_SCHEDULE -( - SCHED_HOUND_HOP_RETREAT, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_HOUND_HOP_BACK 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_TAKE_COVER_FROM_ENEMY" - "" - " Interrupts" -); diff --git a/game/server/hl2/npc_houndeye.h b/game/server/hl2/npc_houndeye.h deleted file mode 100644 index 7b5cc8baa..000000000 --- a/game/server/hl2/npc_houndeye.h +++ /dev/null @@ -1,72 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef NPC_HOUNDEYE_H -#define NPC_HOUNDEYE_H -#pragma once - - -#include "AI_BaseNPC.h" - -#include "energy_wave.h" - -class CNPC_Houndeye : public CAI_BaseNPC -{ - DECLARE_CLASS( CNPC_Houndeye, CAI_BaseNPC ); - -public: - void Spawn( void ); - void Precache( void ); - Class_T Classify ( void ); - void HandleAnimEvent( animevent_t *pEvent ); - float MaxYawSpeed ( void ); - void WarmUpSound ( void ); - void AlertSound( void ); - void DeathSound( const CTakeDamageInfo &info ); - void WarnSound( void ); - void PainSound( const CTakeDamageInfo &info ); - void IdleSound( void ); - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - int GetSoundInterests( void ); - void SonicAttack( void ); - void PrescheduleThink( void ); - void WriteBeamColor ( void ); - int RangeAttack1Conditions ( float flDot, float flDist ); - bool FCanActiveIdle ( void ); - virtual int TranslateSchedule( int scheduleType ); - Activity NPC_TranslateActivity( Activity eNewActivity ); - virtual int SelectSchedule( void ); - bool HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt); - void NPCThink(void); - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - void Event_Killed( const CTakeDamageInfo &info ); - bool IsAnyoneInSquadAttacking( void ); - void SpeakSentence( int sentenceType ); - - float m_flNextSecondaryAttack; - bool m_bLoopClockwise; - - CEnergyWave* m_pEnergyWave; - float m_flEndEnergyWaveTime; - - bool m_fAsleep;// some houndeyes sleep in idle mode if this is set, the houndeye is lying down - bool m_fDontBlink;// don't try to open/close eye if this bit is set! - - DEFINE_CUSTOM_AI; - - DECLARE_DATADESC(); -}; - - -#endif // NPC_HOUNDEYE_H diff --git a/game/server/hl2/npc_hydra.cpp b/game/server/hl2/npc_hydra.cpp deleted file mode 100644 index 7d4d0252e..000000000 --- a/game/server/hl2/npc_hydra.cpp +++ /dev/null @@ -1,1958 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -#include "npc_hydra.h" - -#include "ai_hull.h" -#include "saverestore_utlvector.h" -#include "physics_saverestore.h" -#include "vphysics/constraints.h" -#include "vcollide_parse.h" -#include "ragdoll_shared.h" -#include "physics_prop_ragdoll.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// -// CNPC_Hydra -// - -#define HYDRA_MAX_LENGTH 500 - -LINK_ENTITY_TO_CLASS( npc_hydra, CNPC_Hydra ); - -//========================================================= -// Hydra activities -//========================================================= -int ACT_HYDRA_COWER; -int ACT_HYDRA_STAB; - -//========================================================= -// Private conditions -//========================================================= - -//================================================== -// AntlionConditions -//================================================== - -enum -{ - COND_HYDRA_SNAGGED = LAST_SHARED_CONDITION, - COND_HYDRA_STUCK, - COND_HYDRA_OVERSHOOT, - COND_HYDRA_OVERSTRETCH, // longer than max distance - COND_HYDRA_STRIKE, // head hit something - COND_HYDRA_NOSTUCK // no segments are stuck -}; - -//========================================================= -// Hydra schedules -//========================================================= -enum -{ - SCHED_HYDRA_DEPLOY = LAST_SHARED_SCHEDULE, - SCHED_HYDRA_RETRACT, - SCHED_HYDRA_IDLE, - SCHED_HYDRA_STAB, // shoot out head and try to hit object - SCHED_HYDRA_PULLBACK, // - SCHED_HYDRA_TIGHTEN_SLACK, // snagged on something, tighten slack up to obstacle and try again from there - SCHED_HYDRA_RETREAT, - SCHED_HYDRA_THROW, - SCHED_HYDRA_RANGE_ATTACK -}; - -//========================================================= -// Hydra tasks -//========================================================= -enum -{ - TASK_HYDRA_RETRACT = LAST_SHARED_TASK, - TASK_HYDRA_DEPLOY, - TASK_HYDRA_GET_OBJECT, - TASK_HYDRA_THROW_OBJECT, - TASK_HYDRA_PREP_STAB, - TASK_HYDRA_STAB, - TASK_HYDRA_PULLBACK, - TASK_HYDRA_SET_MAX_TENSION, - TASK_HYDRA_SET_BLEND_TENSION -}; - - -//--------------------------------------------------------- -// Custom Client entity -//--------------------------------------------------------- -IMPLEMENT_SERVERCLASS_ST(CNPC_Hydra, DT_NPC_Hydra) - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 0 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 1 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 2 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 3 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 4 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 5 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 6 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 7 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 8 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 9 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 10 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 11 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 12 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 13 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 14 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 15 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 16 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 17 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 18 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 19 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 20 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 21 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 22 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 23 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 24 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 25 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 26 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 27 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 28 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 29 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 30 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecChain, 31 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO( m_vecHeadDir ), -1, SPROP_NORMAL ), - SendPropFloat( SENDINFO( m_flRelaxedLength ), 12, 0, 0.0, HYDRA_MAX_LENGTH * 1.5 ), -END_SEND_TABLE() - - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CNPC_Hydra ) - - DEFINE_AUTO_ARRAY( m_vecChain, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_activeChain, FIELD_INTEGER ), - DEFINE_FIELD( m_bHasStuckSegments, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flCurrentLength, FIELD_FLOAT ), - DEFINE_FIELD( m_vecHeadGoal, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_flHeadGoalInfluence, FIELD_FLOAT ), - DEFINE_FIELD( m_vecHeadDir, FIELD_VECTOR ), - DEFINE_FIELD( m_flRelaxedLength, FIELD_FLOAT ), - DEFINE_FIELD( m_vecOutward, FIELD_VECTOR ), - DEFINE_UTLVECTOR( m_body, FIELD_EMBEDDED ), - DEFINE_FIELD( m_idealLength, FIELD_FLOAT ), - DEFINE_FIELD( m_idealSegmentLength, FIELD_FLOAT ), - DEFINE_FIELD( m_bExtendSoundActive, FIELD_BOOLEAN ), - DEFINE_SOUNDPATCH( m_pExtendTentacleSound ), - DEFINE_FIELD( m_seed, FIELD_FLOAT ), - DEFINE_FIELD( m_vecTarget, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecTargetDir, FIELD_VECTOR ), - DEFINE_FIELD( m_flLastAdjustmentTime, FIELD_TIME ), - DEFINE_FIELD( m_flTaskStartTime, FIELD_TIME ), - DEFINE_FIELD( m_flTaskEndTime, FIELD_TIME ), - DEFINE_FIELD( m_flLengthTime, FIELD_TIME ), - DEFINE_FIELD( m_bStabbedEntity, FIELD_BOOLEAN ), - -END_DATADESC() - - -//------------------------------------- - -BEGIN_SIMPLE_DATADESC( HydraBone ) - DEFINE_FIELD( vecPos, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( vecDelta, FIELD_VECTOR ), - DEFINE_FIELD( flIdealLength, FIELD_FLOAT ), - DEFINE_FIELD( flActualLength, FIELD_FLOAT ), - DEFINE_FIELD( bStuck, FIELD_BOOLEAN ), - DEFINE_FIELD( bOnFire, FIELD_BOOLEAN ), - DEFINE_FIELD( vecGoalPos, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( flGoalInfluence,FIELD_FLOAT ), -END_DATADESC() - -//------------------------------------- - -static ConVar sv_hydraLength( "hydra_length", "100", FCVAR_ARCHIVE, "Hydra Length" ); -static ConVar sv_hydraSlack( "hydra_slack", "200", FCVAR_ARCHIVE, "Hydra Slack" ); - -static ConVar sv_hydraSegmentLength( "hydra_segment_length", "30", FCVAR_ARCHIVE, "Hydra Slack" ); - -static ConVar sv_hydraTest( "hydra_test", "1", FCVAR_ARCHIVE, "Hydra Slack" ); - -static ConVar sv_hydraBendTension( "hydra_bend_tension", "0.4", FCVAR_ARCHIVE, "Hydra Slack" ); -static ConVar sv_hydraBendDelta( "hydra_bend_delta", "50", FCVAR_ARCHIVE, "Hydra Slack" ); - -static ConVar sv_hydraGoalTension( "hydra_goal_tension", "0.5", FCVAR_ARCHIVE, "Hydra Slack" ); -static ConVar sv_hydraGoalDelta( "hydra_goal_delta", "400", FCVAR_ARCHIVE, "Hydra Slack" ); - -static ConVar sv_hydraMomentum( "hydra_momentum", "0.5", FCVAR_ARCHIVE, "Hydra Slack" ); - -static ConVar sv_hydraTestSpike( "sv_hydraTestSpike", "1", 0, "Hydra Test impaling code" ); - -//------------------------------------- -// Purpose: Initialize the custom schedules -//------------------------------------- - - -//------------------------------------- - -void CNPC_Hydra::Precache() -{ - PrecacheModel( "models/Hydra.mdl" ); - UTIL_PrecacheOther( "hydra_impale" ); - - PrecacheScriptSound( "NPC_Hydra.ExtendTentacle" ); - - BaseClass::Precache(); -} - - -void CNPC_Hydra::Activate( void ) -{ - CPASAttenuationFilter filter( this ); - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - m_pExtendTentacleSound = controller.SoundCreate( filter, entindex(), "NPC_Hydra.ExtendTentacle" ); - - controller.Play( m_pExtendTentacleSound, 1.0, 100 ); - - BaseClass::Activate(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns this monster's place in the relationship table. -//----------------------------------------------------------------------------- -Class_T CNPC_Hydra::Classify( void ) -{ - return CLASS_BARNACLE; -} - -//------------------------------------- - -#define HYDRA_OUTWARD_BIAS 16 -#define HYDRA_INWARD_BIAS 30 - -void CNPC_Hydra::Spawn() -{ - Precache(); - - BaseClass::Spawn(); - - SetModel( "models/Hydra.mdl" ); - - SetHullType(HULL_HUMAN); - SetHullSizeNormal(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - SetBloodColor( BLOOD_COLOR_RED ); - ClearEffects(); - m_iHealth = 20; - m_flFieldOfView = -1.0;// indicates the width of this NPC's forward view cone ( as a dotproduct result ) - m_NPCState = NPC_STATE_NONE; - - GetVectors( NULL, NULL, &m_vecOutward ); - - SetAbsAngles( QAngle( 0, 0, 0 ) ); - - m_vecChain.Set( 0, GetAbsOrigin( ) - m_vecOutward * 32 ); - m_vecChain.Set( 1, GetAbsOrigin( ) + m_vecOutward * 16 ); - - m_vecHeadGoal = m_vecChain[1] + m_vecOutward * HYDRA_OUTWARD_BIAS; - m_vecHeadDir = Vector( 0, 0, 1 ); - - // init bones - HydraBone bone; - bone.flActualLength = 0.0f; - bone.vecGoalPos = Vector(0.0f, 0.0f, 0.0f); - bone.vecPos = GetAbsOrigin( ) - m_vecOutward * HYDRA_INWARD_BIAS; - m_body.AddToTail( bone ); - bone.vecPos = m_vecChain[1]; - m_body.AddToTail( bone ); - bone.vecPos = m_vecHeadGoal; - m_body.AddToTail( bone ); - bone.vecPos = m_vecHeadGoal + m_vecHeadDir; - m_body.AddToTail( bone ); - - m_idealSegmentLength = sv_hydraSegmentLength.GetFloat(); - - for (int i = 2; i < CHAIN_LINKS; i++) - { - m_vecChain.Set( i, m_vecChain[i-1] ); - } - - m_seed = random->RandomFloat( 0.0, 2000.0 ); - - NPCInit(); - - m_takedamage = DAMAGE_NO; -} - - -//------------------------------------- - - -void CNPC_Hydra::RunAI( void ) -{ - CheckLength( ); - - AdjustLength( ); - - BaseClass::RunAI(); - - CalcGoalForces( ); - MoveBody( ); - - int i; - for (i = 1; i < CHAIN_LINKS && i < m_body.Count(); i++) - { - m_vecChain.Set( i, m_body[i].vecPos ); - -#if 0 - if (m_body[i].bStuck) - { - NDebugOverlay::Box(m_body[i].vecPos, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), 255, 0, 0, 20, .1); - } - else - { - NDebugOverlay::Box(m_body[i].vecPos, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), 0, 255, 0, 20, .1); - } - NDebugOverlay::Line( m_body[i].vecPos, m_body[i].vecPos + m_body[i].vecDelta, 0, 255, 0, true, .1); - NDebugOverlay::Line( m_body[i-1].vecPos, m_body[i].vecPos, 255, 255, 255, true, .1); -#endif - -#if 0 - char text[128]; - Q_snprintf( text, sizeof( text ), "%d", i ); - NDebugOverlay::Text( m_body[i].vecPos, text, false, 0.1 ); -#endif - -#if 0 - char text[128]; - Q_snprintf( text, sizeof( text ), "%4.0f", (m_body[i].vecPos - m_body[i-1].vecPos).Length() * 100 / m_idealSegmentLength - 100); - NDebugOverlay::Text( 0.5*(m_body[i-1].vecPos + m_body[i].vecPos), text, false, 0.1 ); -#endif - } - //NDebugOverlay::Box(m_body[i].vecPos, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), 0, 255, 0, 20, .1); - //NDebugOverlay::Box( m_vecHeadGoal, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), 255, 255, 0, 20, .1); - for (; i < CHAIN_LINKS; i++) - { - m_vecChain.Set( i, m_vecChain[i-1] ); - } -} - - - - -Vector CNPC_Hydra::TestPosition( float t ) -{ - // return GetAbsOrigin( ) + Vector( sin( (m_seed + t) * 2.3 ) * 15, cos( (m_seed + t) * 2.4 ) * 150, sin( ( m_seed + t ) * 1.8 ) * 50 ) + m_vecOutward * sv_hydraLength.GetFloat();; - t = (int)(t * 0.2); -#if 1 - Vector tmp = Vector( sin( (m_seed + t) * 0.8 ) * 15, cos( (m_seed + t) * 0.9 ) * 150, sin( ( m_seed + t ) * 0.4 ) * 50 ); - tmp += Vector( sin( (m_seed + t) * 1.0 ) * 4, cos( (m_seed + t) * 0.9 ) * 4, sin( ( m_seed + t ) * 1.1 ) * 6 ); - tmp += GetAbsOrigin( ) + m_vecOutward * sv_hydraLength.GetFloat(); - return tmp; -#else - - Vector tmp; - tmp.Init; - CBaseEntity *pPlayer = (CBaseEntity *)UTIL_GetLocalPlayer(); - if ( pPlayer ) - { - tmp = pPlayer->EyePosition( ); - - Vector delta = (tmp - GetAbsOrigin( )); - - if (delta.Length() > 200) - { - tmp = GetAbsOrigin( ) + Vector( 0, 0, 200 ); - } - m_vecHeadDir = (pPlayer->EyePosition( ) - m_body[m_body.Count()-2].vecPos); - VectorNormalize( m_vecHeadDir ); - } - - return tmp; -#endif - // m_vecHeadGoal = GetAbsOrigin( ) + Vector( sin( gpGlobals->curtime * 0.3 ) * 15, cos( gpGlobals->curtime * 0.4 ) * 150, sin( gpGlobals->curtime * 0.2 ) * 50 + dt ); -} - - - - -//----------------------------------------------------------------------------- -// Purpose: Calculate the bone forces based on goal positions, bending rules, stretching rules, etc. -// Input : -// Output : -//----------------------------------------------------------------------------- - -void CNPC_Hydra::CalcGoalForces( ) -{ - int i; - - int iFirst = 2; - int iLast = m_body.Count() - 1; - - // keep head segment straight - m_body[iLast].vecGoalPos = m_vecHeadGoal; // + m_vecHeadDir * m_body[iLast-1].flActualLength; - m_body[iLast].flGoalInfluence = m_flHeadGoalInfluence; - - m_body[iLast-1].vecGoalPos = m_vecHeadGoal - m_vecHeadDir * m_idealSegmentLength; - m_body[iLast-1].flGoalInfluence = 1.0; // m_flHeadGoalInfluence; - - - // momentum? - for (i = iFirst; i <= iLast; i++) - { - m_body[i].vecDelta = m_body[i].vecDelta * sv_hydraMomentum.GetFloat(); - } - - //Vector right, up; - //VectorVectors( m_vecHeadDir, right, up ); - - float flGoalSegmentLength = m_idealSegmentLength * ( m_idealLength / m_flCurrentLength); - - // goal forces -#if 1 - for (i = iFirst; i <= iLast; i++) - { - // DevMsg("(%d) %.2f\n", i, t ); - - float flInfluence = m_body[i].flGoalInfluence; - if (flInfluence > 0) - { - m_body[i].flGoalInfluence = 0.0; - - Vector v0 = (m_body[i].vecGoalPos - m_body[i].vecPos); - float length = v0.Length(); - if (length > sv_hydraGoalDelta.GetFloat()) - { - v0 = v0 * sv_hydraGoalDelta.GetFloat() / length; - } - m_body[i].vecDelta += v0 * flInfluence * sv_hydraGoalTension.GetFloat(); - // NDebugOverlay::Box(m_body[i].vecGoalPos, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), 255, 255, 0, flInfluence * 255, .1); - } - } -#endif - - // bending forces - for (i = iFirst-1; i <= iLast - 1; i++) - { - // DevMsg("(%d) %.2f\n", i, t ); - Vector v3 = m_body[i+1].vecPos - m_body[i-1].vecPos; - VectorNormalize( v3 ); - - Vector delta; - float length; - - //NDebugOverlay::Line( m_body[i].vecPos + v3 * flGoalSegmentLength, m_body[i].vecPos - v3 * flGoalSegmentLength, 255, 0, 0, true, .1); - - if (i+1 <= iLast) - { - // towards head - delta = (m_body[i].vecPos + v3 * flGoalSegmentLength - m_body[i+1].vecPos) * sv_hydraBendTension.GetFloat(); - length = delta.Length(); - if (length > sv_hydraBendDelta.GetFloat()) - { - delta = delta * (sv_hydraBendDelta.GetFloat() / length); - } - m_body[i+1].vecDelta += delta; - //NDebugOverlay::Line( m_body[i+1].vecPos, m_body[i+1].vecPos + delta, 255, 0, 0, true, .1); - } - - if (i-1 >= iFirst) - { - // towards tail - delta = (m_body[i].vecPos - v3 * flGoalSegmentLength - m_body[i-1].vecPos) * sv_hydraBendTension.GetFloat(); - length = delta.Length(); - if (length > sv_hydraBendDelta.GetFloat()) - { - delta = delta * (sv_hydraBendDelta.GetFloat() / length); - } - m_body[i-1].vecDelta += delta * 0.8; - //NDebugOverlay::Line( m_body[i-1].vecPos, m_body[i-1].vecPos + delta, 255, 0, 0, true, .1); - } - } - - m_body[0].vecDelta = Vector( 0, 0, 0 ); - m_body[1].vecDelta = Vector( 0, 0, 0 ); - - // normal gravity forces - for (i = iFirst; i <= iLast; i++) - { - if (!m_body[i].bStuck) - { - m_body[i].vecDelta.z -= 3.84 * 0.2; - } - } - -#if 0 - // move delta's back toward the root - for (i = iLast; i > iFirst; i--) - { - Vector tmp = m_body[i].vecDelta; - - m_body[i].vecDelta = tmp * 0.8; - m_body[i-1].vecDelta += tmp * 0.2; - } -#endif - - // prevent stretching - int maxChecks = m_body.Count() * 4; - i = iLast; - while (i > iFirst && maxChecks > 0) - { - bool didStretch = false; - Vector stretch = (m_body[i].vecPos + m_body[i].vecDelta) - (m_body[i-1].vecPos + m_body[i-1].vecDelta); - float t = VectorNormalize( stretch ); - if (t > flGoalSegmentLength) - { - float f0 = DotProduct( m_body[i].vecDelta, stretch ); - float f1 = DotProduct( m_body[i-1].vecDelta, stretch ); - if (f0 > 0 && f0 > f1) - { - // Vector limit = stretch * (f0 - flGoalSegmentLength); - Vector limit = stretch * (t - flGoalSegmentLength); - // propagate pulling back down the chain - m_body[i].vecDelta -= limit * 0.5; - m_body[i-1].vecDelta += limit * 0.5; - didStretch = true; - } - } - if (didStretch) - { - if (i < iLast) - { - i++; - } - } - else - { - i--; - } - maxChecks--; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Move the body, check for collisions -// Input : -// Output : -//----------------------------------------------------------------------------- - -void CNPC_Hydra::MoveBody( ) -{ - int i; - - int iFirst = 2; - int iLast = m_body.Count() - 1; - - // clear stuck flags - for (i = 0; i <= iLast; i++) - { - m_body[i].bStuck = false; - } - - // try to move all the nodes - for (i = iFirst; i <= iLast; i++) - { - trace_t tr; - - // check direct movement - AI_TraceHull(m_body[i].vecPos, m_body[i].vecPos + m_body[i].vecDelta, - Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), - MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr); - - Vector direct = tr.endpos; - Vector delta = Vector( 0, 0, 0 ); - - Vector slide = m_body[i].vecDelta; - if (tr.fraction != 1.0) - { - // slow down and remove all motion in the direction of the plane - direct += tr.plane.normal; - Vector impactSpeed = (slide * tr.plane.normal) * tr.plane.normal; - - slide = (slide - impactSpeed) * 0.8; - - if (tr.m_pEnt) - { - if (i == iLast) - { - Stab( tr.m_pEnt, impactSpeed, tr ); - } - else - { - Nudge( tr.m_pEnt, direct, impactSpeed ); - } - } - - // slow down and remove all motion in the direction of the plane - slide = (slide - (slide * tr.plane.normal) * tr.plane.normal) * 0.8; - - // try to move the remaining distance anyways - AI_TraceHull(direct, direct + slide * (1 - tr.fraction), - Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), - MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr); - - // NDebugOverlay::Line( m_body[i].vecPos, tr.endpos, 255, 255, 0, true, 1); - - direct = tr.endpos; - - m_body[i].bStuck = true; - - } - - // make sure the new segment doesn't intersect the world - AI_TraceHull(direct, m_body[i-1].vecPos, - Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), - MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr); - - if (tr.fraction == 1.0) - { - if (i+1 < iLast) - { - AI_TraceHull(direct, m_body[i+1].vecPos, - Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), - MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr); - } - - if (tr.fraction == 1.0) - { - m_body[i].vecPos = direct; - delta = slide; - } - else - { - // FIXME: compute nudge force - m_body[i].bStuck = true; - //m_body[i+1].bStuck = true; - } - } - else - { - // FIXME: compute nudge force - m_body[i].bStuck = true; - //m_body[i-1].bStuck = true; - } - - // m_body[i-1].vecDelta += (m_body[i].vecDelta - delta) * 0.25; - // m_body[i+1].vecDelta += (m_body[i].vecDelta - delta) * 0.25; - m_body[i].vecDelta = delta; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Push physics objects around if they get hit -// Input : vecContact = point in space where contact supposidly happened -// vecSpeed = in/sec of contact -// Output : -//----------------------------------------------------------------------------- - -void CNPC_Hydra::Nudge( CBaseEntity *pOther, const Vector &vecContact, const Vector &vecSpeed ) -{ - if ( pOther->GetMoveType() != MOVETYPE_VPHYSICS ) - { - return; - } - - IPhysicsObject *pOtherPhysics = pOther->VPhysicsGetObject(); - - // Put the force on the line between the "contact point" and hit object origin - //Vector posOther; - //pOtherPhysics->GetPosition( &posOther, NULL ); - - // force is a 30kg object going 100 in/s - pOtherPhysics->ApplyForceOffset( vecSpeed * 30, vecContact ); - -} - -//----------------------------------------------------------------------------- -// Purpose: Push physics objects around if they get hit -// Input : vecContact = point in space where contact supposidly happened -// vecSpeed = in/sec of contact -// Output : -//----------------------------------------------------------------------------- - -void CNPC_Hydra::Stab( CBaseEntity *pOther, const Vector &vecSpeed, trace_t &tr ) -{ - if (pOther->m_takedamage == DAMAGE_YES && !pOther->IsPlayer()) - { - Vector dir = vecSpeed; - VectorNormalize( dir ); - - if ( !sv_hydraTestSpike.GetInt() ) - { - ClearMultiDamage(); - // FIXME: this is bogus - CTakeDamageInfo info( this, this, pOther->m_iHealth+25, DMG_SLASH ); - CalculateMeleeDamageForce( &info, dir, tr.endpos ); - pOther->DispatchTraceAttack( info, dir, &tr ); - ApplyMultiDamage(); - } - else - { - CBaseAnimating *pAnimating = dynamic_cast(pOther); - if ( pAnimating ) - { - AttachStabbedEntity( pAnimating, vecSpeed * 30, tr ); - } - } - } - else - { - Nudge( pOther, tr.endpos, vecSpeed ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : vecContact = point in space where contact supposidly happened -// vecSpeed = in/sec of contact -// Output : -//----------------------------------------------------------------------------- - -void CNPC_Hydra::Kick( CBaseEntity *pHitEntity, const Vector &vecContact, const Vector &vecSpeed ) -{ - -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : vecContact = point in space where contact supposidly happened -// vecSpeed = in/sec of contact -// Output : -//----------------------------------------------------------------------------- - -void CNPC_Hydra::Splash( const Vector &vecSplashPos ) -{ - - -} - - -//----------------------------------------------------------------------------- -// Purpose: Calculate the actual hydra length -// Input : -// Output : -//----------------------------------------------------------------------------- - -void CNPC_Hydra::CheckLength( ) -{ - int i; - - ClearCondition( COND_HYDRA_SNAGGED ); - ClearCondition( COND_HYDRA_NOSTUCK ); - ClearCondition( COND_HYDRA_OVERSTRETCH ); - - m_bHasStuckSegments = m_body[m_body.Count() - 1].bStuck; - m_flCurrentLength = 0; - - for (i = 1; i < m_body.Count() - 1; i++) - { - float length = (m_body[i+1].vecPos - m_body[i].vecPos).Length(); - - Assert( m_body[i+1].vecPos.IsValid( ) ); - Assert( m_body[i].vecPos.IsValid( ) ); - - Assert( IsFinite( length ) ); - - m_body[i].flActualLength = length; - - m_flCurrentLength += length; - - // check for over streatched segements - if (length > m_idealSegmentLength * 3.0 && (m_body[i].bStuck || m_body[i+1].bStuck)) - { - //NDebugOverlay::Line( m_body[i].vecPos, m_body[i+1].vecPos, 255, 0, 0, true, 1.0); - SetCondition( COND_HYDRA_SNAGGED ); - } - if (m_body[i].bStuck) - { - m_bHasStuckSegments = true; - } - } - - if (m_flCurrentLength > HYDRA_MAX_LENGTH) // FIXME - { - SetCondition( COND_HYDRA_OVERSTRETCH ); - } - - if (!m_bHasStuckSegments) - { - SetCondition( COND_HYDRA_NOSTUCK ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Grow or shrink the hydra, as needed -// Input : -// Output : -//----------------------------------------------------------------------------- - -void CNPC_Hydra::AdjustLength( ) -{ - m_body[0].vecPos = m_body[1].vecPos - m_vecOutward * m_idealSegmentLength ; - - // DevMsg( "actual %.0f ideal %.0f relaxed %.0f\n", actualLength, m_idealLength, m_idealSegmentLength * (m_body.Count() - 3) ); - - CalcRelaxedLength( ); - - // "NPC_Hydra.ExtendTentacle" - - bool bAdjustFailed = false; - bool bShouldAdjust = false; - - if (m_flCurrentLength < m_idealLength) - { - if (m_flRelaxedLength + m_idealSegmentLength * 0.5 < m_idealLength) - { - bShouldAdjust = true; - //if (!GrowFromMostStretched( )) - if (!GrowFromVirtualRoot()) - { - bAdjustFailed = true; - } - } - } - else if (m_flCurrentLength > m_idealLength) - { - // if (relaxedLength > actualLength) - if (m_flRelaxedLength - m_idealSegmentLength * 0.5 > m_idealLength || HasCondition( COND_HYDRA_SNAGGED )) - { - bShouldAdjust = true; - if (!ContractFromRoot()) - { - if (!ContractBetweenStuckSegments()) - { - if (!ContractFromHead()) - { - bAdjustFailed = true; - } - } - } - } - else if (gpGlobals->curtime - m_flLastAdjustmentTime > 1.0) - { - bShouldAdjust = true; - // start to panic - if (!GrowFromMostStretched( )) - { - bAdjustFailed = true; - } - - // SplitLongestSegment( ); - /* - if (!ContractBetweenStuckSegments()) - { - if (!ContractFromHead()) - { - - } - } - */ - } - else - { - bAdjustFailed = true; - } - } - - if (!bAdjustFailed) - { - m_flLastAdjustmentTime = gpGlobals->curtime; - if (bShouldAdjust && !m_bExtendSoundActive) - { - m_bExtendSoundActive = true; - //CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - //controller.SoundChangeVolume( m_pExtendTentacleSound, 1.0, 0.1 ); - } - } - else if (bShouldAdjust) - { - m_bExtendSoundActive = false; - //CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - //controller.SoundChangeVolume( m_pExtendTentacleSound, 0.0, 0.3 ); - } - - CalcRelaxedLength( ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Remove nodes, starting at the end, regardless of length -// Input : -// Output : -//----------------------------------------------------------------------------- - -bool CNPC_Hydra::ContractFromHead( ) -{ - if (m_body.Count() <= 2) - { - return false; - } - - int iNode = m_body.Count() - 1; - - if (m_body[iNode].bStuck && m_body[iNode-1].flActualLength > m_idealSegmentLength * 2.0) - { - AddNodeBefore( iNode ); - iNode = m_body.Count() - 1; - } - - if (m_body.Count() <= 3) - { - return false; - } - - // always legal since no new link is being formed - - m_body.Remove( iNode ); - - CalcRelaxedLength( ); - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Starting at the first stuck node back from the head, find a node to remove -// between it and the actual root who is part of a chain that isn't too long. -// Input : -// Output : -//----------------------------------------------------------------------------- - -bool CNPC_Hydra::ContractBetweenStuckSegments( ) -{ - if (m_body.Count() <= 3) - return false; - - // first first stuck segment closest to head; - int iStuckHead = VirtualRoot( ); - if (iStuckHead < 3) - return false; - - // find a non stuck node with the shortest distance between its neighbors - int iShortest = -1; - float dist = m_idealSegmentLength * 2; - int i; - for (i = iStuckHead - 1; i > 2; i--) - { - if (!m_body[i].bStuck) - { - float length = (m_body[i-1].vecPos - m_body[i+1].vecPos).Length(); - // check segment length - if (length < dist ) - { - if (IsValidConnection( i-1, i+1 )) - { - dist = length; - iShortest = i; - } - } - } - } - if (iShortest == -1) - return false; - - // FIXME: check for tunneling - m_body.Remove( iShortest ); - - CalcRelaxedLength( ); - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Try to remove segment closest to root -// Input : -// Output : -//----------------------------------------------------------------------------- - -bool CNPC_Hydra::ContractFromRoot( ) -{ - if (m_body.Count() <= 3) - return false; - - // don't contract overly long segments - if (m_body[2].flActualLength > m_idealSegmentLength * 2.0) - return false; - - if (!IsValidConnection( 1, 3 )) - return false; - - m_body.Remove( 2 ); - - CalcRelaxedLength( ); - - return true; -} - - - -//----------------------------------------------------------------------------- -// Purpose: Find the first stuck node that's closest to the head -// Input : -// Output : -//----------------------------------------------------------------------------- - -int CNPC_Hydra::VirtualRoot( ) -{ - // first first stuck segment closest to head; - int iStuckHead; - for (iStuckHead = m_body.Count() - 2; iStuckHead > 1; iStuckHead--) - { - if (m_body[iStuckHead].bStuck) - { - return iStuckHead; - } - } - - return 1; -} - -//----------------------------------------------------------------------------- -// Purpose: Insert a node before the given node. -// Input : -// Output : -//----------------------------------------------------------------------------- - -bool CNPC_Hydra::AddNodeBefore( int iNode ) -{ - if (iNode < 1) - return false; - - HydraBone bone; - - bone.vecPos = (m_body[iNode].vecPos + m_body[iNode-1].vecPos) * 0.5; - bone.vecDelta = (m_body[iNode].vecDelta + m_body[iNode-1].vecDelta) * 0.5; - bone.vecGoalPos = Vector(0.0f, 0.0f, 0.0f); - - /* - // FIXME: can't do this, may be embedded in the world - int i0 = (iNode>2)?iNode-2:0; - int i1 = (iNode>1)?iNode-1:0; - int i2 = iNode; - int i3 = (iNode dist) - { - iLongest = iNode; - dist = m_body[iNode].flActualLength; - } - } - - if (m_body[iLongest].flActualLength <= dist) - { - return AddNodeAfter( iLongest ); - } - return false; -} - - -void CNPC_Hydra::CalcRelaxedLength( ) -{ - m_flRelaxedLength = m_idealSegmentLength * (m_body.Count() -2) + HYDRA_OUTWARD_BIAS; -} - - -bool CNPC_Hydra::IsValidConnection( int iNode0, int iNode1 ) -{ - trace_t tr; - // check to make sure new connection is valid - AI_TraceHull(m_body[iNode0].vecPos, m_body[iNode1].vecPos, - Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), - MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr); - - if (tr.fraction == 1.0) - { - return true; - } - return false; -} - - -//------------------------------------- - -float CNPC_Hydra::MaxYawSpeed() -{ - return 0; - - if( IsMoving() ) - { - return 20; - } - - switch( GetActivity() ) - { - case ACT_180_LEFT: - return 30; - break; - - case ACT_TURN_LEFT: - case ACT_TURN_RIGHT: - return 30; - break; - default: - return 15; - break; - } -} - -//------------------------------------- - -int CNPC_Hydra::TranslateSchedule( int scheduleType ) -{ - return BaseClass::TranslateSchedule( scheduleType ); -} - -//------------------------------------- - -void CNPC_Hydra::HandleAnimEvent( animevent_t *pEvent ) -{ - BaseClass::HandleAnimEvent( pEvent ); -} - -//------------------------------------- - -void CNPC_Hydra::PrescheduleThink() -{ - BaseClass::PrescheduleThink(); - if ( m_bStabbedEntity ) - { - UpdateStabbedEntity(); - } -} - -//------------------------------------- - -int CNPC_Hydra::SelectSchedule () -{ - switch ( m_NPCState ) - { - case NPC_STATE_IDLE: - { - SetState( NPC_STATE_ALERT ); - return SCHED_HYDRA_DEPLOY; - } - break; - - case NPC_STATE_ALERT: - { - return SCHED_HYDRA_STAB; - } - break; - - case NPC_STATE_COMBAT: - { - if (HasCondition( COND_HYDRA_SNAGGED )) - { - return SCHED_HYDRA_PULLBACK; - } - else if (HasCondition( COND_HYDRA_OVERSTRETCH )) - { - return SCHED_HYDRA_STAB; - } - return SCHED_HYDRA_STAB; - } - break; - - default: - break; - } - - return BaseClass::SelectSchedule(); -} - -//------------------------------------- - -void CNPC_Hydra::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_HYDRA_DEPLOY: - m_vecHeadGoal = GetAbsOrigin( ) + m_vecOutward * 100; - m_idealLength = 100; - m_vecHeadDir = m_vecOutward; - return; - case TASK_HYDRA_PREP_STAB: - { - m_flTaskEndTime = gpGlobals->curtime + pTask->flTaskData; - - // Go outward - m_vecHeadGoal = GetAbsOrigin( ) + m_vecOutward * 100; - SetTarget( (CBaseEntity *)UTIL_GetLocalPlayer() ); - if (GetEnemy()) - { - SetTarget( GetEnemy() ); - } - - //CPASAttenuationFilter filter( this, "NPC_Hydra.Alert" ); - //Vector vecHead = EyePosition(); - //EmitSound( filter, entindex(), "NPC_Hydra.Alert", &vecHead ); - } - return; - - case TASK_HYDRA_STAB: - { - //CPASAttenuationFilter filter( this, "NPC_Hydra.Attack" ); - //Vector vecHead = EyePosition(); - //EmitSound( filter, entindex(), "NPC_Hydra.Attack", &vecHead ); - - m_flTaskEndTime = gpGlobals->curtime + 0.5; - } - return; - - case TASK_HYDRA_PULLBACK: - m_vecHeadGoal = GetAbsOrigin( ) + m_vecOutward * pTask->flTaskData; - m_idealLength = pTask->flTaskData * 1.1; - return; - - default: - BaseClass::StartTask( pTask ); - break; - } - -} - -//------------------------------------- - -void CNPC_Hydra::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_HYDRA_DEPLOY: - { - m_flHeadGoalInfluence = 1.0; - float dist = (EyePosition() - m_vecHeadGoal).Length(); - - if (dist < m_idealSegmentLength) - { - TaskComplete(); - } - - AimHeadInTravelDirection( 0.2 ); - } - break; - - case TASK_HYDRA_PREP_STAB: - { - int i; - - if (m_body.Count() < 2) - { - TaskFail( "hydra is too short to begin stab" ); - return; - } - - CBaseEntity *pTarget = GetTarget(); - if (pTarget == NULL) - { - TaskFail( FAIL_NO_TARGET ); - } - - if (pTarget->IsPlayer()) - { - m_vecTarget = pTarget->EyePosition( ); - } - else - { - m_vecTarget = pTarget->BodyTarget( EyePosition( ) ); - } - - float distToTarget = (m_vecTarget - m_vecHeadGoal).Length(); - float distToBase = (m_vecHeadGoal - GetAbsOrigin()).Length(); - m_idealLength = distToTarget + distToBase * 0.5; - - if (m_idealLength > HYDRA_MAX_LENGTH) - m_idealLength = HYDRA_MAX_LENGTH; - - if (distToTarget < 100.0) - { - m_vecTargetDir = (m_vecTarget - m_vecHeadGoal); - VectorNormalize( m_vecTargetDir ); - m_vecHeadGoal = m_vecHeadGoal - m_vecTargetDir * (100 - distToTarget) * 0.5; - } - else if (distToTarget > 200.0) - { - m_vecTargetDir = (m_vecTarget - m_vecHeadGoal); - VectorNormalize( m_vecTargetDir ); - m_vecHeadGoal = m_vecHeadGoal - m_vecTargetDir * (200.0 - distToTarget) * 0.5; - } - - // face enemy - m_vecTargetDir = (m_vecTarget - m_body[m_body.Count()-1].vecPos); - VectorNormalize( m_vecTargetDir ); - m_vecHeadDir = m_vecHeadDir * 0.6 + m_vecTargetDir * 0.4; - VectorNormalize( m_vecHeadDir.GetForModify() ); - - // build tension towards strike time - float influence = 1.0 - (m_flTaskEndTime - gpGlobals->curtime) / pTask->flTaskData; - if (influence > 1) - influence = 1.0; - - influence = influence * influence * influence; - - m_flHeadGoalInfluence = influence; - - // keep head segment straight - i = m_body.Count() - 2; - m_body[i].vecGoalPos = m_vecHeadGoal - m_vecHeadDir * m_body[i].flActualLength; - m_body[i].flGoalInfluence = influence; - - // curve neck into spiral - float distBackFromHead = m_body[i].flActualLength; - Vector right, up; - VectorVectors( m_vecHeadDir, right, up ); - - for (i = i - 1; i > 1 && distBackFromHead < distToTarget; i--) - { - distBackFromHead += m_body[i].flActualLength; - - float r = (distBackFromHead / 200) * 3.1415 * 2; - - // spiral - Vector p0 = m_vecHeadGoal - - m_vecHeadDir * distBackFromHead * 0.5 - + cos( r ) * m_body[i].flActualLength * right - + sin( r ) * m_body[i].flActualLength * up; - - // base - r = (distBackFromHead / m_idealLength) * 3.1415 * 0.2; - r = sin( r ); - p0 = p0 * (1 - r) + r * GetAbsOrigin(); - - m_body[i].vecGoalPos = p0; - - m_body[i].flGoalInfluence = influence * (1.0 - (distBackFromHead / distToTarget)); - - /* - if ( (pEnemy->EyePosition( ) - m_body[i].vecPos).Length() < distBackFromHead) - { - if ( gpGlobals->curtime - m_flLastAttackTime > 4.0) - { - TaskComplete(); - } - return; - } - */ - } - - // look to see if any of the goal positions are stuck - for (i = i; i < m_body.Count() - 1; i++) - { - if (m_body[i].bStuck) - { - Vector delta = DotProduct( m_body[i].vecGoalPos - m_body[i].vecPos, m_vecHeadDir) * m_vecHeadDir; - m_vecHeadGoal -= delta * m_body[i].flGoalInfluence; - break; - } - } - - if ( gpGlobals->curtime >= m_flTaskEndTime ) - { - if (distToTarget < 500) - { - TaskComplete( ); - return; - } - else - { - TaskFail( "target is too far away" ); - return; - } - } - } - return; - - case TASK_HYDRA_STAB: - { - int i; - - if (m_body.Count() < 2) - { - TaskFail( "hydra is too short to begin stab" ); - return; - } - - if (m_flTaskEndTime <= gpGlobals->curtime) - { - TaskComplete( ); - return; - } - - m_flHeadGoalInfluence = 1.0; - - // face enemy - //m_vecHeadDir = (pEnemy->EyePosition( ) - m_body[m_body.Count()-1].vecPos); - //VectorNormalize( m_vecHeadDir.GetForModify() ); - - // keep head segment straight - i = m_body.Count() - 2; - m_body[i].vecGoalPos = m_vecHeadGoal + m_vecHeadDir * m_body[i].flActualLength; - m_body[i].flGoalInfluence = 1.0; - - Vector vecToTarget = (m_vecTarget - EyePosition( )); - - // check to see if we went past target - if (DotProduct( vecToTarget, m_vecHeadDir ) < 0.0) - { - TaskComplete( ); - return; - } - - float distToTarget = vecToTarget.Length(); - float distToBase = (EyePosition( ) - GetAbsOrigin()).Length(); - m_idealLength = distToTarget + distToBase; - - /* - if (distToTarget < 20) - { - m_vecHeadGoal = m_vecTarget; - SetLastAttackTime( gpGlobals->curtime ); - TaskComplete(); - return; - } - else - */ - { - // hit enemy - m_vecHeadGoal = m_vecTarget + m_vecHeadDir * 300; - } - - if (m_idealLength > HYDRA_MAX_LENGTH) - m_idealLength = HYDRA_MAX_LENGTH; - - // curve neck into spiral - float distBackFromHead = m_body[i].flActualLength; - Vector right, up; - VectorVectors( m_vecHeadDir, right, up ); - -#if 1 - for (i = i - 1; i > 1 && distBackFromHead < distToTarget; i--) - { - Vector p0 = m_vecHeadGoal - m_vecHeadDir * distBackFromHead * 1.0; - - m_body[i].vecGoalPos = p0; - - if ((m_vecTarget - m_body[i].vecPos).Length() > distToTarget + distBackFromHead) - { - m_body[i].flGoalInfluence = 1.0 - (distBackFromHead / distToTarget); - } - else - { - m_body[i].vecGoalPos = EyePosition( ) - m_vecHeadDir * distBackFromHead; - m_body[i].flGoalInfluence = 1.0 - (distBackFromHead / distToTarget); - } - - distBackFromHead += m_body[i].flActualLength; - } -#endif - } - return; - - case TASK_HYDRA_PULLBACK: - { - if (m_body.Count() < 2) - { - TaskFail( "hydra is too short to begin stab" ); - return; - } - CBaseEntity *pEnemy = (CBaseEntity *)UTIL_GetLocalPlayer(); - if (GetEnemy() != NULL) - { - pEnemy = GetEnemy(); - } - - AimHeadInTravelDirection( 0.2 ); - - // float dist = (EyePosition() - m_vecHeadGoal).Length(); - - if (m_flCurrentLength < m_idealLength + m_idealSegmentLength) - { - TaskComplete(); - } - } - break; - - default: - BaseClass::RunTask( pTask ); - break; - } - -} - -//------------------------------------- - -Vector CNPC_Hydra::EyePosition( ) -{ - int i = m_body.Count() - 1; - - if (i >= 0) - { - return m_body[i].vecPos; - } - return GetAbsOrigin(); -} - -const QAngle &CNPC_Hydra::EyeAngles() -{ - return GetAbsAngles(); -} - - -Vector CNPC_Hydra::BodyTarget( const Vector &posSrc, bool bNoisy) -{ - int i; - - if (m_body.Count() < 2) - { - return GetAbsOrigin(); - } - - int iShortest = 1; - float flShortestDist = (posSrc - m_body[iShortest].vecPos).LengthSqr(); - for (i = 2; i < m_body.Count(); i++) - { - float flDist = (posSrc - m_body[i].vecPos).LengthSqr(); - if (flDist < flShortestDist) - { - iShortest = i; - flShortestDist = flDist; - } - } - - // NDebugOverlay::Box(m_body[iShortest].vecPos, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), 0, 0, 255, 20, .1); - - return m_body[iShortest].vecPos; -} - - -void CNPC_Hydra::AimHeadInTravelDirection( float flInfluence ) -{ - - // aim in the direction of movement enemy - Vector delta = m_body[m_body.Count()-1].vecDelta; - VectorNormalize( delta ); - if (DotProduct( delta, m_vecHeadDir ) < 0) - { - delta = -delta; - } - - m_vecHeadDir = m_vecHeadDir * (1 - flInfluence) + delta * flInfluence; - VectorNormalize( m_vecHeadDir.GetForModify() ); -} - -//------------------------------------- - -//----------------------------------------------------------------------------- -// Purpose: Hydra impaling is done by creating an entity, forming a constraint -// between that entity and the target ragdoll, and then updating then -// entity to follow the hydra. -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// Purpose: This is the entity we create to follow the hydra -//----------------------------------------------------------------------------- -class CHydraImpale : public CBaseAnimating -{ - DECLARE_CLASS( CHydraImpale, CBaseAnimating ); -public: - DECLARE_DATADESC(); - - void Spawn( void ); - void Precache( void ); - void ImpaleThink( void ); - - IPhysicsConstraint *CreateConstraint( CNPC_Hydra *pHydra, IPhysicsObject *pTargetPhys, IPhysicsConstraintGroup *pGroup ); - static CHydraImpale *Create( CNPC_Hydra *pHydra, CBaseEntity *pObject2 ); - -public: - IPhysicsConstraint *m_pConstraint; - CHandle m_hHydra; -}; - -BEGIN_DATADESC( CHydraImpale ) - DEFINE_PHYSPTR( m_pConstraint ), - DEFINE_FIELD( m_hHydra, FIELD_EHANDLE ), - - DEFINE_THINKFUNC( ImpaleThink ), -END_DATADESC() - -LINK_ENTITY_TO_CLASS( hydra_impale, CHydraImpale ); - -//----------------------------------------------------------------------------- -// Purpose: To by usable by the constraint system, this needs to have a phys model. -//----------------------------------------------------------------------------- -void CHydraImpale::Spawn( void ) -{ - Precache(); - SetModel( "models/props_junk/cardboard_box001a.mdl" ); - AddEffects( EF_NODRAW ); - - // We don't want this to be solid, because we don't want it to collide with the hydra. - SetSolid( SOLID_VPHYSICS ); - AddSolidFlags( FSOLID_NOT_SOLID ); - VPhysicsInitShadow( false, false ); - - // Disable movement on this sucker, we're going to move him manually - SetMoveType( MOVETYPE_FLY ); - - BaseClass::Spawn(); - - m_pConstraint = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHydraImpale::Precache( void ) -{ - PrecacheModel( "models/props_junk/cardboard_box001a.mdl" ); - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: Update the impale entity's position to the hydra's desired -//----------------------------------------------------------------------------- -void CHydraImpale::ImpaleThink( void ) -{ - if ( !m_hHydra ) - { - // Remove ourselves. - m_pConstraint->Deactivate(); - UTIL_Remove( this ); - return; - } - - // Ask the Hydra where he'd like the ragdoll, and move ourselves there - Vector vecOrigin; - QAngle vecAngles; - m_hHydra->GetDesiredImpaledPosition( &vecOrigin, &vecAngles ); - SetAbsOrigin( vecOrigin ); - SetAbsAngles( vecAngles ); - - //NDebugOverlay::Cross3D( vecOrigin, Vector( -5, -5, -5 ), Vector( 5, 5, 5 ), 255, 0, 0, 20, .1); - - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -//----------------------------------------------------------------------------- -// Purpose: Activate/create the constraint -//----------------------------------------------------------------------------- -IPhysicsConstraint *CHydraImpale::CreateConstraint( CNPC_Hydra *pHydra, IPhysicsObject *pTargetPhys, IPhysicsConstraintGroup *pGroup ) -{ - m_hHydra = pHydra; - - IPhysicsObject *pImpalePhysObject = VPhysicsGetObject(); - Assert( pImpalePhysObject ); - - constraint_fixedparams_t fixed; - fixed.Defaults(); - fixed.InitWithCurrentObjectState( pImpalePhysObject, pTargetPhys ); - fixed.constraint.Defaults(); - - m_pConstraint = physenv->CreateFixedConstraint( pImpalePhysObject, pTargetPhys, pGroup, fixed ); - if ( m_pConstraint ) - { - m_pConstraint->SetGameData( (void *)this ); - } - - SetThink( &CHydraImpale::ImpaleThink ); - SetNextThink( gpGlobals->curtime ); - return m_pConstraint; -} - -//----------------------------------------------------------------------------- -// Purpose: Create a Hydra Impale between the hydra and the entity passed in -//----------------------------------------------------------------------------- -CHydraImpale *CHydraImpale::Create( CNPC_Hydra *pHydra, CBaseEntity *pTarget ) -{ - Vector vecOrigin; - QAngle vecAngles; - pHydra->GetDesiredImpaledPosition( &vecOrigin, &vecAngles ); - pTarget->Teleport( &vecOrigin, &vecAngles, &vec3_origin ); - - CHydraImpale *pImpale = (CHydraImpale *)CBaseEntity::Create( "hydra_impale", vecOrigin, vecAngles ); - if ( !pImpale ) - return NULL; - - IPhysicsObject *pTargetPhysObject = pTarget->VPhysicsGetObject(); - if ( !pTargetPhysObject ) - { - DevMsg(" Error: Tried to hydra_impale an entity without a physics model.\n" ); - return NULL; - } - - IPhysicsConstraintGroup *pGroup = NULL; - // Ragdoll? If so, use it's constraint group - CRagdollProp *pRagdoll = dynamic_cast(pTarget); - if ( pRagdoll ) - { - pGroup = pRagdoll->GetRagdoll()->pGroup; - } - - if ( !pImpale->CreateConstraint( pHydra, pTargetPhysObject, pGroup ) ) - return NULL; - - return pImpale; -} - -void CNPC_Hydra::AttachStabbedEntity( CBaseAnimating *pAnimating, Vector vecForce, trace_t &tr ) -{ - CTakeDamageInfo info( this, this, pAnimating->m_iHealth+25, DMG_SLASH ); - info.SetDamageForce( vecForce ); - info.SetDamagePosition( tr.endpos ); - - CBaseEntity *pRagdoll = CreateServerRagdoll( pAnimating, 0, info, COLLISION_GROUP_INTERACTIVE_DEBRIS ); - - // Create our impale entity - CHydraImpale::Create( this, pRagdoll ); - - m_bStabbedEntity = true; - - UTIL_Remove( pAnimating ); -} - -void CNPC_Hydra::UpdateStabbedEntity( void ) -{ - /* - CBaseEntity *pEntity = m_grabController.GetAttached(); - if ( !pEntity ) - { - DetachStabbedEntity( false ); - return; - } - - QAngle vecAngles(0,0,1); - Vector vecOrigin = m_body[m_body.Count()-2].vecPos; - - //NDebugOverlay::Cross3D( vecOrigin, Vector( -5, -5, -5 ), Vector( 5, 5, 5 ), 255, 0, 0, 20, .1); - - m_grabController.SetTargetPosition( vecOrigin, vecAngles ); - */ -} - -void CNPC_Hydra::DetachStabbedEntity( bool playSound ) -{ - /* - CBaseEntity *pObject = m_grabController.GetAttached(); - if ( pObject != NULL ) - { - IPhysicsObject *pPhysics = pObject->VPhysicsGetObject(); - - // Enable collision with this object again - if ( pPhysics != NULL ) - { - physenv->EnableCollisions( pPhysics, VPhysicsGetObject() ); - pPhysics->RecheckCollisionFilter(); - } - } - - m_grabController.DetachEntity(); - */ - - if ( playSound ) - { - //Play the detach sound - } - - m_bStabbedEntity = false; -} - -void CNPC_Hydra::GetDesiredImpaledPosition( Vector *vecOrigin, QAngle *vecAngles ) -{ - *vecOrigin = m_body[m_body.Count()-2].vecPos; - *vecAngles = QAngle(0,0,0); -} - -//----------------------------------------------------------------------------- -// -// CNPC_Hydra Schedules -// -//------------------------------------- - - -AI_BEGIN_CUSTOM_NPC( npc_hydra, CNPC_Hydra ) - - //Register our interactions - - //Conditions - DECLARE_CONDITION( COND_HYDRA_SNAGGED ) - DECLARE_CONDITION( COND_HYDRA_STUCK ) - DECLARE_CONDITION( COND_HYDRA_OVERSHOOT ) - DECLARE_CONDITION( COND_HYDRA_OVERSTRETCH ) - DECLARE_CONDITION( COND_HYDRA_STRIKE ) - DECLARE_CONDITION( COND_HYDRA_NOSTUCK ) - - //Squad slots - - //Tasks - DECLARE_TASK( TASK_HYDRA_RETRACT ) - DECLARE_TASK( TASK_HYDRA_DEPLOY ) - DECLARE_TASK( TASK_HYDRA_GET_OBJECT ) - DECLARE_TASK( TASK_HYDRA_THROW_OBJECT ) - DECLARE_TASK( TASK_HYDRA_PREP_STAB ) - DECLARE_TASK( TASK_HYDRA_STAB ) - DECLARE_TASK( TASK_HYDRA_PULLBACK ) - - //Activities - DECLARE_ACTIVITY( ACT_HYDRA_COWER ) - DECLARE_ACTIVITY( ACT_HYDRA_STAB ) - - //========================================================= - // > SCHED_HYDRA_STAND_LOOK - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HYDRA_DEPLOY, - - " Tasks" - " TASK_HYDRA_DEPLOY 0" - " TASK_WAIT 0.5" - "" - " Interrupts" - " COND_NEW_ENEMY" - ) - - //========================================================= - // > SCHED_HYDRA_COWER - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_HYDRA_RETRACT, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_HYDRA_COWER" - " TASK_WAIT 0.5" - "" - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_HYDRA_IDLE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_WAIT_INDEFINITE 0" - "" - " Interrupts " - " COND_NEW_ENEMY" - ) - - DEFINE_SCHEDULE - ( - SCHED_HYDRA_STAB, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_HYDRA_DEPLOY" - " TASK_HYDRA_PREP_STAB 4.0" - " TASK_HYDRA_STAB 0" - " TASK_WAIT 0.5" - // " TASK_HYDRA_PULLBACK 100" - "" - " Interrupts " - " COND_NEW_ENEMY" - " COND_HYDRA_OVERSTRETCH" - ) - - DEFINE_SCHEDULE - ( - SCHED_HYDRA_PULLBACK, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_WAIT 0.4" - " TASK_HYDRA_PULLBACK 100" - "" - " Interrupts " - " COND_NEW_ENEMY" - ) - - DEFINE_SCHEDULE - ( - SCHED_HYDRA_THROW, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_HYDRA_GET_OBJECT 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_HYDRA_THROW_OBJECT 0" - " TASK_WAIT 1" - "" - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_HYDRA_RANGE_ATTACK, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_ANNOUNCE_ATTACK 1" // 1 = primary attack - " TASK_FACE_ENEMY 0" - " TASK_RANGE_ATTACK1 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_ENEMY_OCCLUDED" - " COND_NO_PRIMARY_AMMO" - " COND_HEAR_DANGER" - ) - -AI_END_CUSTOM_NPC() - - diff --git a/game/server/hl2/npc_hydra.h b/game/server/hl2/npc_hydra.h deleted file mode 100644 index 3f8ca9f7a..000000000 --- a/game/server/hl2/npc_hydra.h +++ /dev/null @@ -1,179 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef NPC_HYDRA_H -#define NPC_HYDRA_H - -#if defined( _WIN32 ) -#pragma once -#endif - -#include "ai_basenpc.h" -#include "soundenvelope.h" - -class CNPC_Hydra; - -//----------------------------------------------------------------------------- -// CNPC_Hydra -// -//----------------------------------------------------------------------------- - -class HydraBone -{ -public: - HydraBone( void ) - { - vecPos = Vector( 0, 0, 0 ); - vecDelta = Vector( 0, 0, 0 ); - //vecBendDelta = Vector( 0, 0, 0 ); - //vecGoalDelta = Vector( 0, 0, 0 ); - //flBendTension = 0.0; - flIdealLength = 1.0; - flGoalInfluence = 0.0; - bStuck = false; - bOnFire = false; - }; - - Vector vecPos; - Vector vecDelta; - //float flBendTension; - float flIdealLength; - bool bStuck; - bool bOnFire; - - float flActualLength; - //Vector vecBendDelta; - //Vector vecGoalDelta; - // float flAccumLength; - - Vector vecGoalPos; - float flGoalInfluence; - - DECLARE_SIMPLE_DATADESC(); -}; - -class CNPC_Hydra : public CAI_BaseNPC -{ - DECLARE_CLASS( CNPC_Hydra, CAI_BaseNPC ); - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - -public: - CNPC_Hydra() - { - } - - void Spawn( void ); - void Precache( void ); - void Activate( void ); - - Class_T Classify( void ); - - void RunAI( void ); - - float MaxYawSpeed( void ); - int TranslateSchedule( int scheduleType ); - int SelectSchedule( void ); - - void PrescheduleThink( void ); - - void HandleAnimEvent( animevent_t *pEvent ); - - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - -#define CHAIN_LINKS 32 - - CNetworkArray( Vector, m_vecChain, CHAIN_LINKS ); - int m_activeChain; - - bool m_bHasStuckSegments; - float m_flCurrentLength; - - Vector m_vecHeadGoal; - float m_flHeadGoalInfluence; - CNetworkVector( m_vecHeadDir ); - - CNetworkVar( float, m_flRelaxedLength ); - - Vector m_vecOutward; - - CUtlVector < HydraBone > m_body; - - float m_idealLength; - float m_idealSegmentLength; - - Vector TestPosition( float t ); - - void CalcGoalForces( void ); - void MoveBody( void ); - - void AdjustLength( void ); - void CheckLength( void ); - - bool m_bExtendSoundActive; - CSoundPatch *m_pExtendTentacleSound; - - void Nudge( CBaseEntity *pHitEntity, const Vector &vecContact, const Vector &vecSpeed ); - void Stab( CBaseEntity *pHitEntity, const Vector &vecSpeed, trace_t &ptr ); - void Kick( CBaseEntity *pHitEntity, const Vector &vecContact, const Vector &vecSpeed ); - void Splash( const Vector &vecSplashPos ); - - // float FreeNeckLength( void ); - - virtual Vector EyePosition( void ); - virtual const QAngle &EyeAngles( void ); - - virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy) ; - - void AimHeadInTravelDirection( float flInfluence ); - - float m_seed; - - // -------------------------------- - Vector m_vecTarget; - Vector m_vecTargetDir; - - float m_flLastAdjustmentTime; - float m_flTaskStartTime; - float m_flTaskEndTime; - - float m_flLengthTime; // time of last successful length adjustment time - - // -------------------------------- - - bool ContractFromHead( void ); - bool ContractBetweenStuckSegments( void ); - bool ContractFromRoot( void ); - - int VirtualRoot( void ); - - bool AddNodeBefore( int iNode ); - bool AddNodeAfter( int iNode ); - - bool GrowFromVirtualRoot( void ); - bool GrowFromMostStretched( void ); - - void CalcRelaxedLength( void ); - - bool IsValidConnection( int iNode0, int iNode1 ); - - void AttachStabbedEntity( CBaseAnimating *pAnimating, Vector vecForce, trace_t &tr ); - void UpdateStabbedEntity( void ); - void DetachStabbedEntity( bool playSound ); - void GetDesiredImpaledPosition( Vector *vecOrigin, QAngle *vecAngles ); - - bool m_bStabbedEntity; - - DEFINE_CUSTOM_AI; - -private: -}; - -//----------------------------------------------------------------------------- - -#endif // NPC_HYDRA_H diff --git a/game/server/hl2/npc_ichthyosaur.cpp b/game/server/hl2/npc_ichthyosaur.cpp deleted file mode 100644 index 51b0e8f10..000000000 --- a/game/server/hl2/npc_ichthyosaur.cpp +++ /dev/null @@ -1,1558 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Ichthyosaur - buh bum... buh bum... -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ai_basenpc.h" -#include "ai_task.h" -#include "ai_default.h" -#include "ai_schedule.h" -#include "ai_hull.h" -#include "ai_interactions.h" -#include "ai_navigator.h" -#include "ai_motor.h" -#include "activitylist.h" -#include "game.h" -#include "npcevent.h" -#include "player.h" -#include "entitylist.h" -#include "soundenvelope.h" -#include "shake.h" -#include "ndebugoverlay.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "movevars_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar sk_ichthyosaur_health( "sk_ichthyosaur_health", "0" ); -ConVar sk_ichthyosaur_melee_dmg( "sk_ichthyosaur_melee_dmg", "0" ); - -#define ICHTHYOSAUR_MODEL "models/ichthyosaur.mdl" - -#define ICH_HEIGHT_PREFERENCE 16.0f -#define ICH_DEPTH_PREFERENCE 8.0f - -#define ICH_WAYPOINT_DISTANCE 64.0f - -#define ICH_AE_BITE 11 -#define ICH_AE_BITE_START 12 - -#define ICH_SWIM_SPEED_WALK 150 -#define ICH_SWIM_SPEED_RUN 500 - -#define ICH_MIN_TURN_SPEED 4.0f -#define ICH_MAX_TURN_SPEED 30.0f - -#define ENVELOPE_CONTROLLER (CSoundEnvelopeController::GetController()) - -#define FEELER_COLLISION 0 -#define FEELER_COLLISION_VISUALIZE (FEELER_COLLISION&&0) - -enum IchthyosaurMoveType_t -{ - ICH_MOVETYPE_SEEK = 0, // Fly through the target without stopping. - ICH_MOVETYPE_ARRIVE // Slow down and stop at target. -}; - -// -// CNPC_Ichthyosaur -// - -class CNPC_Ichthyosaur : public CAI_BaseNPC -{ -public: - DECLARE_CLASS( CNPC_Ichthyosaur, CAI_BaseNPC ); - DECLARE_DATADESC(); - - CNPC_Ichthyosaur( void ) {} - - int SelectSchedule( void ); - int MeleeAttack1Conditions( float flDot, float flDist ); - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - int TranslateSchedule( int type ); - - void Precache( void ); - void Spawn( void ); - void MoveFlyExecute( CBaseEntity *pTargetEnt, const Vector & vecDir, float flDistance, float flInterval ); - void HandleAnimEvent( animevent_t *pEvent ); - void PrescheduleThink( void ); - bool OverrideMove( float flInterval ); - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - void TranslateNavGoal( CBaseEntity *pEnemy, Vector &chasePosition ); - float GetDefaultNavGoalTolerance(); - - float MaxYawSpeed( void ); - - Class_T Classify( void ) { return CLASS_ANTLION; } //FIXME: No classification for various wildlife? - - bool FVisible( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ); - -private: - - bool SteerAvoidObstacles( Vector &Steer, const Vector &Velocity, const Vector &Forward, const Vector &Right, const Vector &Up ); - bool Beached( void ); - - void DoMovement( float flInterval, const Vector &MoveTarget, int eMoveType ); - void SteerArrive( Vector &Steer, const Vector &Target ); - void SteerSeek( Vector &Steer, const Vector &Target ); - void ClampSteer( Vector &SteerAbs, Vector &SteerRel, Vector &forward, Vector &right, Vector &up ); - void AddSwimNoise( Vector *velocity ); - - void Bite( void ); - void EnsnareVictim( CBaseEntity *pVictim ); - void ReleaseVictim( void ); - void DragVictim( float moveDist ); - - void SetPoses( Vector moveRel, float speed ); - - //void IchTouch( CBaseEntity *pOther ); - - float GetGroundSpeed( void ); - -#if FEELER_COLLISION - Vector DoProbe( const Vector &Probe ); - Vector m_LastSteer; -#endif - - CBaseEntity *m_pVictim; - - static const Vector m_vecAccelerationMax; - static const Vector m_vecAccelerationMin; - - Vector m_vecLastMoveTarget; - - float m_flNextBiteTime; - float m_flHoldTime; - float m_flSwimSpeed; - float m_flTailYaw; - float m_flTailPitch; - - float m_flNextPingTime; - float m_flNextGrowlTime; - - bool m_bHasMoveTarget; - bool m_bIgnoreSurface; - - //CSoundPatch *m_pSwimSound; - //CSoundPatch *m_pVoiceSound; - - DEFINE_CUSTOM_AI; -}; - -//Acceleration definitions -const Vector CNPC_Ichthyosaur::m_vecAccelerationMax = Vector( 256, 1024, 512 ); -const Vector CNPC_Ichthyosaur::m_vecAccelerationMin = Vector( -256, -1024, -512 ); - -//Data description -BEGIN_DATADESC( CNPC_Ichthyosaur ) - -// Silence classcheck -// DEFINE_FIELD( m_LastSteer, FIELD_VECTOR ), - - DEFINE_FIELD( m_pVictim, FIELD_CLASSPTR ), - DEFINE_FIELD( m_vecLastMoveTarget, FIELD_VECTOR ), - DEFINE_FIELD( m_flNextBiteTime, FIELD_FLOAT ), - DEFINE_FIELD( m_flHoldTime, FIELD_FLOAT ), - DEFINE_FIELD( m_flSwimSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_flTailYaw, FIELD_FLOAT ), - DEFINE_FIELD( m_flTailPitch, FIELD_FLOAT ), - DEFINE_FIELD( m_flNextPingTime, FIELD_FLOAT ), - DEFINE_FIELD( m_flNextGrowlTime, FIELD_FLOAT ), - DEFINE_FIELD( m_bHasMoveTarget, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bIgnoreSurface, FIELD_BOOLEAN ), - - //DEFINE_FUNCTION( IchTouch ), - -END_DATADESC() - -//Schedules -enum IchSchedules -{ - SCHED_ICH_CHASE_ENEMY = LAST_SHARED_SCHEDULE, - SCHED_ICH_PATROL_RUN, - SCHED_ICH_PATROL_WALK, - SCHED_ICH_DROWN_VICTIM, - SCHED_ICH_MELEE_ATTACK1, - SCHED_ICH_THRASH, -}; - -//Tasks -enum IchTasks -{ - TASK_ICH_GET_PATH_TO_RANDOM_NODE = LAST_SHARED_TASK, - TASK_ICH_GET_PATH_TO_DROWN_NODE, - TASK_ICH_THRASH_PATH, -}; - -//Activities -int ACT_ICH_THRASH; -int ACT_ICH_BITE_HIT; -int ACT_ICH_BITE_MISS; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Ichthyosaur::InitCustomSchedules( void ) -{ - INIT_CUSTOM_AI( CNPC_Ichthyosaur ); - - //Interaction REGISTER_INTERACTION( g_interactionAntlionAttacked ); - - //Schedules - ADD_CUSTOM_SCHEDULE( CNPC_Ichthyosaur, SCHED_ICH_CHASE_ENEMY ); - ADD_CUSTOM_SCHEDULE( CNPC_Ichthyosaur, SCHED_ICH_PATROL_RUN ); - ADD_CUSTOM_SCHEDULE( CNPC_Ichthyosaur, SCHED_ICH_PATROL_WALK ); - ADD_CUSTOM_SCHEDULE( CNPC_Ichthyosaur, SCHED_ICH_DROWN_VICTIM ); - ADD_CUSTOM_SCHEDULE( CNPC_Ichthyosaur, SCHED_ICH_MELEE_ATTACK1 ); - ADD_CUSTOM_SCHEDULE( CNPC_Ichthyosaur, SCHED_ICH_THRASH ); - - //Tasks - ADD_CUSTOM_TASK( CNPC_Ichthyosaur, TASK_ICH_GET_PATH_TO_RANDOM_NODE ); - ADD_CUSTOM_TASK( CNPC_Ichthyosaur, TASK_ICH_GET_PATH_TO_DROWN_NODE ); - ADD_CUSTOM_TASK( CNPC_Ichthyosaur, TASK_ICH_THRASH_PATH ); - - //Conditions ADD_CUSTOM_CONDITION( CNPC_CombineGuard, COND_ANTLIONGRUB_HEARD_SQUEAL ); - - //Activities - ADD_CUSTOM_ACTIVITY( CNPC_Ichthyosaur, ACT_ICH_THRASH ); - ADD_CUSTOM_ACTIVITY( CNPC_Ichthyosaur, ACT_ICH_BITE_HIT ); - ADD_CUSTOM_ACTIVITY( CNPC_Ichthyosaur, ACT_ICH_BITE_MISS ); - - AI_LOAD_SCHEDULE( CNPC_Ichthyosaur, SCHED_ICH_CHASE_ENEMY ); - AI_LOAD_SCHEDULE( CNPC_Ichthyosaur, SCHED_ICH_PATROL_RUN ); - AI_LOAD_SCHEDULE( CNPC_Ichthyosaur, SCHED_ICH_PATROL_WALK ); - AI_LOAD_SCHEDULE( CNPC_Ichthyosaur, SCHED_ICH_DROWN_VICTIM ); - AI_LOAD_SCHEDULE( CNPC_Ichthyosaur, SCHED_ICH_MELEE_ATTACK1 ); - AI_LOAD_SCHEDULE( CNPC_Ichthyosaur, SCHED_ICH_THRASH ); -} - -LINK_ENTITY_TO_CLASS( npc_ichthyosaur, CNPC_Ichthyosaur ); -IMPLEMENT_CUSTOM_AI( npc_ichthyosaur, CNPC_Ichthyosaur ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Ichthyosaur::Precache( void ) -{ - PrecacheModel( ICHTHYOSAUR_MODEL ); - - PrecacheScriptSound( "NPC_Ichthyosaur.Bite" ); - PrecacheScriptSound( "NPC_Ichthyosaur.BiteMiss" ); - PrecacheScriptSound( "NPC_Ichthyosaur.AttackGrowl" ); - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Ichthyosaur::Spawn( void ) -{ - Precache(); - - SetModel( ICHTHYOSAUR_MODEL ); - - SetHullType(HULL_LARGE_CENTERED); - SetHullSizeNormal(); - SetDefaultEyeOffset(); - - SetNavType( NAV_FLY ); - m_NPCState = NPC_STATE_NONE; - SetBloodColor( BLOOD_COLOR_RED ); - m_iHealth = sk_ichthyosaur_health.GetFloat(); - m_iMaxHealth = m_iHealth; - m_flFieldOfView = -0.707; // 270 degrees - SetDistLook( 1024 ); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - AddFlag( FL_FLY | FL_STEPMOVEMENT ); - - m_flGroundSpeed = ICH_SWIM_SPEED_RUN; - - m_bIgnoreSurface = false; - - m_flSwimSpeed = 0.0f; - m_flTailYaw = 0.0f; - m_flTailPitch = 0.0f; - - m_flNextBiteTime = gpGlobals->curtime; - m_flHoldTime = gpGlobals->curtime; - m_flNextPingTime = gpGlobals->curtime; - m_flNextGrowlTime = gpGlobals->curtime; - -#if FEELER_COLLISION - - Vector forward; - - GetVectors( &forward, NULL, NULL ); - - m_vecCurrentVelocity = forward * m_flGroundSpeed; - -#endif - - //SetTouch( IchTouch ); - - CapabilitiesClear(); - CapabilitiesAdd( bits_CAP_MOVE_FLY | bits_CAP_INNATE_MELEE_ATTACK1 ); - - NPCInit(); - - //m_pSwimSound = ENVELOPE_CONTROLLER.SoundCreate( edict(), CHAN_BODY, "xxxCONVERTTOGAMESOUNDS!!!npc/ichthyosaur/ich_amb1wav", ATTN_NORM ); - //m_pVoiceSound = ENVELOPE_CONTROLLER.SoundCreate( edict(), CHAN_VOICE, "xxxCONVERTTOGAMESOUNDS!!!npc/ichthyosaur/water_breathwav", ATTN_IDLE ); - - //ENVELOPE_CONTROLLER.Play( m_pSwimSound, 1.0f, 100 ); - //ENVELOPE_CONTROLLER.Play( m_pVoiceSound,1.0f, 100 ); - - BaseClass::Spawn(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOther - -//----------------------------------------------------------------------------- -/* -void CNPC_Ichthyosaur::IchTouch( CBaseEntity *pOther ) -{ -} -*/ - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_Ichthyosaur::SelectSchedule( void ) -{ - if ( m_NPCState == NPC_STATE_COMBAT ) - { - if ( m_flHoldTime > gpGlobals->curtime ) - return SCHED_ICH_DROWN_VICTIM; - - if ( m_flNextBiteTime > gpGlobals->curtime ) - return SCHED_PATROL_RUN; - - if ( HasCondition( COND_CAN_MELEE_ATTACK1 ) ) - return SCHED_MELEE_ATTACK1; - - return SCHED_CHASE_ENEMY; - } - - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -// Purpose: Handles movement towards the last move target. -// Input : flInterval - -//----------------------------------------------------------------------------- -bool CNPC_Ichthyosaur::OverrideMove( float flInterval ) -{ - m_flGroundSpeed = GetGroundSpeed(); - - if ( m_bHasMoveTarget ) - { - DoMovement( flInterval, m_vecLastMoveTarget, ICH_MOVETYPE_ARRIVE ); - } - else - { - DoMovement( flInterval, GetLocalOrigin(), ICH_MOVETYPE_ARRIVE ); - } - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &probe - -// Output : Vector -//----------------------------------------------------------------------------- -#if FEELER_COLLISION - -Vector CNPC_Ichthyosaur::DoProbe( const Vector &probe ) -{ - trace_t tr; - float fraction = 1.0f; - bool collided = false; - Vector normal = Vector( 0, 0, -1 ); - - float waterLevel = UTIL_WaterLevel( GetAbsOrigin(), GetAbsOrigin().z, GetAbsOrigin().z+150 ); - - waterLevel -= GetAbsOrigin().z; - waterLevel /= 150; - - if ( waterLevel < 1.0f ) - { - collided = true; - fraction = waterLevel; - } - - AI_TraceHull( GetAbsOrigin(), probe, GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - - if ( ( collided == false ) || ( tr.fraction < fraction ) ) - { - fraction = tr.fraction; - normal = tr.plane.normal; - } - - if ( ( fraction < 1.0f ) && ( GetEnemy() == NULL || tr.u.ent != GetEnemy()->pev ) ) - { -#if FEELER_COLLISION_VISUALIZE - NDebugOverlay::Line( GetLocalOrigin(), probe, 255, 0, 0, false, 0.1f ); -#endif - - Vector probeDir = probe - GetLocalOrigin(); - - Vector normalToProbeAndWallNormal = probeDir.Cross( normal ); - Vector steeringVector = normalToProbeAndWallNormal.Cross( probeDir ); - - Vector velDir = GetAbsVelocity(); - VectorNormalize( velDir ); - - float steeringForce = m_flGroundSpeed * ( 1.0f - fraction ) * normal.Dot( velDir ); - - if ( steeringForce < 0.0f ) - { - steeringForce = -steeringForce; - } - - velDir = steeringVector; - VectorNormalize( velDir ); - - steeringVector = steeringForce * velDir; - - return steeringVector; - } - -#if FEELER_COLLISION_VISUALIZE - NDebugOverlay::Line( GetLocalOrigin(), probe, 0, 255, 0, false, 0.1f ); -#endif - - return Vector( 0.0f, 0.0f, 0.0f ); -} - -#endif - -//----------------------------------------------------------------------------- -// Purpose: Move the victim of a drag along with us -// Input : moveDist - our amount of travel -//----------------------------------------------------------------------------- - -#define DRAG_OFFSET 50.0f - -void CNPC_Ichthyosaur::DragVictim( float moveDist ) -{ - Vector mins, maxs; - float width; - - mins = WorldAlignMins(); - maxs = WorldAlignMaxs(); - width = ( maxs.y - mins.y ) * 0.5f; - - Vector forward, up; - GetVectors( &forward, NULL, &up ); - - Vector newPos = GetAbsOrigin() + ( (forward+(up*0.25f)) * ( moveDist + width + DRAG_OFFSET ) ); - - trace_t tr; - AI_TraceEntity( this, m_pVictim->GetAbsOrigin(), newPos, MASK_NPCSOLID, &tr ); - - if ( ( tr.fraction == 1.0f ) && ( tr.m_pEnt != this ) ) - { - UTIL_SetOrigin( m_pVictim, tr.endpos ); - } - else - { - ReleaseVictim(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Determines the pose parameters for the bending of the body and tail speed -// Input : moveRel - the dot products for the deviation off of each direction (f,r,u) -// speed - speed of the fish -//----------------------------------------------------------------------------- -void CNPC_Ichthyosaur::SetPoses( Vector moveRel, float speed ) -{ - float movePerc, moveBase; - - //Find out how fast we're moving in our animations boundaries - if ( GetIdealActivity() == ACT_WALK ) - { - moveBase = 0.5f; - movePerc = moveBase * ( speed / ICH_SWIM_SPEED_WALK ); - } - else - { - moveBase = 1.0f; - movePerc = moveBase * ( speed / ICH_SWIM_SPEED_RUN ); - } - - Vector tailPosition; - float flSwimSpeed = movePerc; - - //Forward deviation - if ( moveRel.x > 0 ) - { - flSwimSpeed *= moveBase + (( moveRel.x / m_vecAccelerationMax.x )*moveBase); - } - else if ( moveRel.x < 0 ) - { - flSwimSpeed *= moveBase - (( moveRel.x / m_vecAccelerationMin.x )*moveBase); - } - - //Vertical deviation - if ( moveRel.z > 0 ) - { - tailPosition[PITCH] = -90.0f * ( moveRel.z / m_vecAccelerationMax.z ); - } - else if ( moveRel.z < 0 ) - { - tailPosition[PITCH] = 90.0f * ( moveRel.z / m_vecAccelerationMin.z ); - } - else - { - tailPosition[PITCH] = 0.0f; - } - - //Lateral deviation - if ( moveRel.y > 0 ) - { - tailPosition[ROLL] = 25 * moveRel.y / m_vecAccelerationMax.y; - tailPosition[YAW] = -1.0f * moveRel.y / m_vecAccelerationMax.y; - } - else if ( moveRel.y < 0 ) - { - tailPosition[ROLL] = -25 * moveRel.y / m_vecAccelerationMin.y; - tailPosition[YAW] = moveRel.y / m_vecAccelerationMin.y; - } - else - { - tailPosition[ROLL] = 0.0f; - tailPosition[YAW] = 0.0f; - } - - //Clamp - flSwimSpeed = clamp( flSwimSpeed, 0.25f, 1.0f ); - tailPosition[YAW] = clamp( tailPosition[YAW], -90.0f, 90.0f ); - tailPosition[PITCH] = clamp( tailPosition[PITCH], -90.0f, 90.0f ); - - //Blend - m_flTailYaw = ( m_flTailYaw * 0.8f ) + ( tailPosition[YAW] * 0.2f ); - m_flTailPitch = ( m_flTailPitch * 0.8f ) + ( tailPosition[PITCH] * 0.2f ); - m_flSwimSpeed = ( m_flSwimSpeed * 0.8f ) + ( flSwimSpeed * 0.2f ); - - //Pose the body - SetPoseParameter( 0, m_flSwimSpeed ); - SetPoseParameter( 1, m_flTailYaw ); - SetPoseParameter( 2, m_flTailPitch ); - - //FIXME: Until the sequence info is reset properly after SetPoseParameter - if ( ( GetActivity() == ACT_RUN ) || ( GetActivity() == ACT_WALK ) ) - { - ResetSequenceInfo(); - } - - //Face our current velocity - GetMotor()->SetIdealYawAndUpdate( UTIL_AngleMod( CalcIdealYaw( GetAbsOrigin() + GetAbsVelocity() ) ), AI_KEEP_YAW_SPEED ); - - float pitch = 0.0f; - - if ( speed != 0.0f ) - { - pitch = -RAD2DEG( asin( GetAbsVelocity().z / speed ) ); - } - - //FIXME: Framerate dependant - QAngle angles = GetLocalAngles(); - - angles.x = (angles.x * 0.8f) + (pitch * 0.2f); - angles.z = (angles.z * 0.9f) + (tailPosition[ROLL] * 0.1f); - - SetLocalAngles( angles ); -} - -#define LATERAL_NOISE_MAX 2.0f -#define LATERAL_NOISE_FREQ 1.0f - -#define VERTICAL_NOISE_MAX 2.0f -#define VERTICAL_NOISE_FREQ 1.0f - -//----------------------------------------------------------------------------- -// Purpose: -// Input : velocity - -//----------------------------------------------------------------------------- -void CNPC_Ichthyosaur::AddSwimNoise( Vector *velocity ) -{ - Vector right, up; - - GetVectors( NULL, &right, &up ); - - float lNoise, vNoise; - - lNoise = LATERAL_NOISE_MAX * sin( gpGlobals->curtime * LATERAL_NOISE_FREQ ); - vNoise = VERTICAL_NOISE_MAX * sin( gpGlobals->curtime * VERTICAL_NOISE_FREQ ); - - (*velocity) += ( right * lNoise ) + ( up * vNoise ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flInterval - -// &m_LastMoveTarget - -// eMoveType - -//----------------------------------------------------------------------------- -void CNPC_Ichthyosaur::DoMovement( float flInterval, const Vector &MoveTarget, int eMoveType ) -{ - // dvs: something is setting this bit, causing us to stop moving and get stuck that way - Forget( bits_MEMORY_TURNING ); - - Vector Steer, SteerAvoid, SteerRel; - Vector forward, right, up; - - //Get our orientation vectors. - GetVectors( &forward, &right, &up); - - if ( ( GetActivity() == ACT_MELEE_ATTACK1 ) && ( GetEnemy() != NULL ) ) - { - SteerSeek( Steer, GetEnemy()->GetAbsOrigin() ); - } - else - { - //If we are approaching our goal, use an arrival steering mechanism. - if ( eMoveType == ICH_MOVETYPE_ARRIVE ) - { - SteerArrive( Steer, MoveTarget ); - } - else - { - //Otherwise use a seek steering mechanism. - SteerSeek( Steer, MoveTarget ); - } - } - -#if FEELER_COLLISION - - Vector f, u, l, r, d; - - float probeLength = GetAbsVelocity().Length(); - - if ( probeLength < 150 ) - probeLength = 150; - - if ( probeLength > 500 ) - probeLength = 500; - - f = DoProbe( GetLocalOrigin() + (probeLength * forward) ); - r = DoProbe( GetLocalOrigin() + (probeLength/3 * (forward+right)) ); - l = DoProbe( GetLocalOrigin() + (probeLength/3 * (forward-right)) ); - u = DoProbe( GetLocalOrigin() + (probeLength/3 * (forward+up)) ); - d = DoProbe( GetLocalOrigin() + (probeLength/3 * (forward-up)) ); - - SteerAvoid = f+r+l+u+d; - - //NDebugOverlay::Line( GetLocalOrigin(), GetLocalOrigin()+SteerAvoid, 255, 255, 0, false, 0.1f ); - - if ( SteerAvoid.LengthSqr() ) - { - Steer = (SteerAvoid*0.5f); - } - - m_vecVelocity = m_vecVelocity + (Steer*0.5f); - - VectorNormalize( m_vecVelocity ); - - SteerRel.x = forward.Dot( m_vecVelocity ); - SteerRel.y = right.Dot( m_vecVelocity ); - SteerRel.z = up.Dot( m_vecVelocity ); - - m_vecVelocity *= m_flGroundSpeed; - -#else - - //See if we need to avoid any obstacles. - if ( SteerAvoidObstacles( SteerAvoid, GetAbsVelocity(), forward, right, up ) ) - { - //Take the avoidance vector - Steer = SteerAvoid; - } - - //Clamp our ideal steering vector to within our physical limitations. - ClampSteer( Steer, SteerRel, forward, right, up ); - - ApplyAbsVelocityImpulse( Steer * flInterval ); - -#endif - - Vector vecNewVelocity = GetAbsVelocity(); - float flLength = vecNewVelocity.Length(); - - //Clamp our final speed - if ( flLength > m_flGroundSpeed ) - { - vecNewVelocity *= ( m_flGroundSpeed / flLength ); - flLength = m_flGroundSpeed; - } - - Vector workVelocity = vecNewVelocity; - - AddSwimNoise( &workVelocity ); - - // Pose the fish properly - SetPoses( SteerRel, flLength ); - - //Drag our victim before moving - if ( m_pVictim != NULL ) - { - DragVictim( (workVelocity*flInterval).Length() ); - } - - //Move along the current velocity vector - if ( WalkMove( workVelocity * flInterval, MASK_NPCSOLID ) == false ) - { - //Attempt a half-step - if ( WalkMove( (workVelocity*0.5f) * flInterval, MASK_NPCSOLID) == false ) - { - //Restart the velocity - //VectorNormalize( m_vecVelocity ); - vecNewVelocity *= 0.5f; - } - else - { - //Cut our velocity in half - vecNewVelocity *= 0.5f; - } - } - - SetAbsVelocity( vecNewVelocity ); - -} - -//----------------------------------------------------------------------------- -// Purpose: Gets a steering vector to arrive at a target location with a -// relatively small velocity. -// Input : Steer - Receives the ideal steering vector. -// Target - Target position at which to arrive. -//----------------------------------------------------------------------------- -void CNPC_Ichthyosaur::SteerArrive(Vector &Steer, const Vector &Target) -{ - Vector Offset = Target - GetLocalOrigin(); - float fTargetDistance = Offset.Length(); - - float fIdealSpeed = m_flGroundSpeed * (fTargetDistance / ICH_WAYPOINT_DISTANCE); - float fClippedSpeed = MIN( fIdealSpeed, m_flGroundSpeed ); - - Vector DesiredVelocity( 0, 0, 0 ); - - if ( fTargetDistance > ICH_WAYPOINT_DISTANCE ) - { - DesiredVelocity = (fClippedSpeed / fTargetDistance) * Offset; - } - - Steer = DesiredVelocity - GetAbsVelocity(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Gets a steering vector to move towards a target position as quickly -// as possible. -// Input : Steer - Receives the ideal steering vector. -// Target - Target position to seek. -//----------------------------------------------------------------------------- -void CNPC_Ichthyosaur::SteerSeek( Vector &Steer, const Vector &Target ) -{ - Vector offset = Target - GetLocalOrigin(); - - VectorNormalize( offset ); - - Vector DesiredVelocity = m_flGroundSpeed * offset; - - Steer = DesiredVelocity - GetAbsVelocity(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &Steer - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Ichthyosaur::SteerAvoidObstacles(Vector &Steer, const Vector &Velocity, const Vector &Forward, const Vector &Right, const Vector &Up) -{ - trace_t tr; - - bool collided = false; - Vector dir = Velocity; - float speed = VectorNormalize( dir ); - - //Look ahead one second and avoid whatever is in our way. - AI_TraceHull( GetAbsOrigin(), GetAbsOrigin() + (dir*speed), GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - - Vector forward; - - GetVectors( &forward, NULL, NULL ); - - //If we're hitting our enemy, just continue on - if ( ( GetEnemy() != NULL ) && ( tr.m_pEnt == GetEnemy() ) ) - return false; - - if ( tr.fraction < 1.0f ) - { - CBaseEntity *pBlocker = tr.m_pEnt; - - if ( ( pBlocker != NULL ) && ( pBlocker->MyNPCPointer() != NULL ) ) - { - DevMsg( 2, "Avoiding an NPC\n" ); - - Vector HitOffset = tr.endpos - GetAbsOrigin(); - - Vector SteerUp = CrossProduct( HitOffset, Velocity ); - Steer = CrossProduct( SteerUp, Velocity ); - VectorNormalize( Steer ); - - /*Vector probeDir = tr.endpos - GetAbsOrigin(); - Vector normalToProbeAndWallNormal = probeDir.Cross( tr.plane.normal ); - - Steer = normalToProbeAndWallNormal.Cross( probeDir ); - VectorNormalize( Steer );*/ - - if ( tr.fraction > 0 ) - { - Steer = (Steer * Velocity.Length()) / tr.fraction; - //NDebugOverlay::Line( GetLocalOrigin(), GetLocalOrigin()+Steer, 255, 0, 0, false, 0.1f ); - } - else - { - Steer = (Steer * 1000 * Velocity.Length()); - //NDebugOverlay::Line( GetLocalOrigin(), GetLocalOrigin()+Steer, 255, 0, 0, false, 0.1f ); - } - } - else - { - if ( ( pBlocker != NULL ) && ( pBlocker == GetEnemy() ) ) - { - DevMsg( "Avoided collision\n" ); - return false; - } - - DevMsg( 2, "Avoiding the world\n" ); - - Vector steeringVector = tr.plane.normal; - - if ( tr.fraction == 0.0f ) - return false; - - Steer = steeringVector * ( Velocity.Length() / tr.fraction ); - - //NDebugOverlay::Line( GetLocalOrigin(), GetLocalOrigin()+Steer, 255, 0, 0, false, 0.1f ); - } - - //return true; - collided = true; - } - - //Try to remain 8 feet above the ground. - AI_TraceLine( GetAbsOrigin(), GetAbsOrigin() + Vector(0, 0, -ICH_HEIGHT_PREFERENCE), MASK_NPCSOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction < 1.0f ) - { - Steer += Vector( 0, 0, m_vecAccelerationMax.z / tr.fraction ); - collided = true; - } - - //Stay under the surface - if ( m_bIgnoreSurface == false ) - { - float waterLevel = ( UTIL_WaterLevel( GetAbsOrigin(), GetAbsOrigin().z, GetAbsOrigin().z+ICH_DEPTH_PREFERENCE ) - GetAbsOrigin().z ) / ICH_DEPTH_PREFERENCE; - - if ( waterLevel < 1.0f ) - { - Steer += -Vector( 0, 0, m_vecAccelerationMax.z / waterLevel ); - collided = true; - } - } - - return collided; -} - - -//----------------------------------------------------------------------------- -// Purpose: Clamps the desired steering vector based on the limitations of this -// vehicle. -// Input : SteerAbs - The vector indicating our ideal steering vector. Receives -// the clamped steering vector in absolute (x,y,z) coordinates. -// SteerRel - Receives the clamped steering vector in relative (forward, right, up) -// coordinates. -// forward - Our current forward vector. -// right - Our current right vector. -// up - Our current up vector. -//----------------------------------------------------------------------------- -void CNPC_Ichthyosaur::ClampSteer(Vector &SteerAbs, Vector &SteerRel, Vector &forward, Vector &right, Vector &up) -{ - float fForwardSteer = DotProduct(SteerAbs, forward); - float fRightSteer = DotProduct(SteerAbs, right); - float fUpSteer = DotProduct(SteerAbs, up); - - if (fForwardSteer > 0) - { - fForwardSteer = MIN(fForwardSteer, m_vecAccelerationMax.x); - } - else - { - fForwardSteer = MAX(fForwardSteer, m_vecAccelerationMin.x); - } - - if (fRightSteer > 0) - { - fRightSteer = MIN(fRightSteer, m_vecAccelerationMax.y); - } - else - { - fRightSteer = MAX(fRightSteer, m_vecAccelerationMin.y); - } - - if (fUpSteer > 0) - { - fUpSteer = MIN(fUpSteer, m_vecAccelerationMax.z); - } - else - { - fUpSteer = MAX(fUpSteer, m_vecAccelerationMin.z); - } - - SteerAbs = (fForwardSteer*forward) + (fRightSteer*right) + (fUpSteer*up); - - SteerRel.x = fForwardSteer; - SteerRel.y = fRightSteer; - SteerRel.z = fUpSteer; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTargetEnt - -// vecDir - -// flDistance - -// flInterval - -//----------------------------------------------------------------------------- -void CNPC_Ichthyosaur::MoveFlyExecute( CBaseEntity *pTargetEnt, const Vector &vecDir, float flDistance, float flInterval ) -{ - IchthyosaurMoveType_t eMoveType = ( GetNavigator()->CurWaypointIsGoal() ) ? ICH_MOVETYPE_ARRIVE : ICH_MOVETYPE_SEEK; - - m_flGroundSpeed = GetGroundSpeed(); - - Vector moveGoal = GetNavigator()->GetCurWaypointPos(); - - //See if we can move directly to our goal - if ( ( GetEnemy() != NULL ) && ( GetNavigator()->GetGoalTarget() == (CBaseEntity *) GetEnemy() ) ) - { - trace_t tr; - Vector goalPos = GetEnemy()->GetAbsOrigin() + ( GetEnemy()->GetSmoothedVelocity() * 0.5f ); - - AI_TraceHull( GetAbsOrigin(), goalPos, GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, GetEnemy(), COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction == 1.0f ) - { - moveGoal = tr.endpos; - } - } - - //Move - DoMovement( flInterval, moveGoal, eMoveType ); - - //Save the info from that run - m_vecLastMoveTarget = moveGoal; - m_bHasMoveTarget = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEntity - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Ichthyosaur::FVisible( CBaseEntity *pEntity, int traceMask, CBaseEntity **ppBlocker ) -{ - // don't look through water - if ( GetWaterLevel() != pEntity->GetWaterLevel() ) - return false; - - return BaseClass::FVisible( pEntity, traceMask, ppBlocker ); -} - -//----------------------------------------------------------------------------- -// Purpose: Get our conditions for a melee attack -// Input : flDot - -// flDist - -// Output : int -//----------------------------------------------------------------------------- -int CNPC_Ichthyosaur::MeleeAttack1Conditions( float flDot, float flDist ) -{ - Vector predictedDir = ( (GetEnemy()->GetAbsOrigin()+(GetEnemy()->GetSmoothedVelocity())) - GetAbsOrigin() ); - float flPredictedDist = VectorNormalize( predictedDir ); - - Vector vBodyDir; - GetVectors( &vBodyDir, NULL, NULL ); - - float flPredictedDot = DotProduct( predictedDir, vBodyDir ); - - if ( flPredictedDot < 0.8f ) - return COND_NOT_FACING_ATTACK; - - if ( ( flPredictedDist > ( GetAbsVelocity().Length() * 0.5f) ) && ( flDist > 128.0f ) ) - return COND_TOO_FAR_TO_ATTACK; - - return COND_CAN_MELEE_ATTACK1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEvent - -//----------------------------------------------------------------------------- -void CNPC_Ichthyosaur::HandleAnimEvent( animevent_t *pEvent ) -{ - switch ( pEvent->event ) - { - case ICH_AE_BITE: - Bite(); - break; - - case ICH_AE_BITE_START: - { - EmitSound( "NPC_Ichthyosaur.AttackGrowl" ); - } - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Ichthyosaur::Bite( void ) -{ - //Don't allow another bite too soon - if ( m_flNextBiteTime > gpGlobals->curtime ) - return; - - CBaseEntity *pHurt; - - //FIXME: E3 HACK - Always damage bullseyes if we're scripted to hit them - if ( ( GetEnemy() != NULL ) && ( GetEnemy()->Classify() == CLASS_BULLSEYE ) ) - { - pHurt = GetEnemy(); - } - else - { - pHurt = CheckTraceHullAttack( 108, Vector(-32,-32,-32), Vector(32,32,32), 0, DMG_CLUB ); - } - - //Hit something - if ( pHurt != NULL ) - { - CTakeDamageInfo info( this, this, sk_ichthyosaur_melee_dmg.GetInt(), DMG_CLUB ); - - if ( pHurt->IsPlayer() ) - { - CBasePlayer *pPlayer = ToBasePlayer( pHurt ); - - if ( pPlayer ) - { - if ( ( ( m_flHoldTime < gpGlobals->curtime ) && ( pPlayer->m_iHealth < (pPlayer->m_iMaxHealth*0.5f)) ) || ( pPlayer->GetWaterLevel() < 1 ) ) - { - //EnsnareVictim( pHurt ); - } - else - { - info.SetDamage( sk_ichthyosaur_melee_dmg.GetInt() * 3 ); - } - CalculateMeleeDamageForce( &info, GetAbsVelocity(), pHurt->GetAbsOrigin() ); - pHurt->TakeDamage( info ); - - color32 red = {64, 0, 0, 255}; - UTIL_ScreenFade( pPlayer, red, 0.5, 0, FFADE_IN ); - - //Disorient the player - QAngle angles = pPlayer->GetLocalAngles(); - - angles.x += random->RandomInt( 60, 25 ); - angles.y += random->RandomInt( 60, 25 ); - angles.z = 0.0f; - - pPlayer->SetLocalAngles( angles ); - - pPlayer->SnapEyeAngles( angles ); - } - } - else - { - CalculateMeleeDamageForce( &info, GetAbsVelocity(), pHurt->GetAbsOrigin() ); - pHurt->TakeDamage( info ); - } - - m_flNextBiteTime = gpGlobals->curtime + random->RandomFloat( 2.0f, 4.0f ); - - //Bubbles! - UTIL_Bubbles( pHurt->GetAbsOrigin()+Vector(-32.0f,-32.0f,-32.0f), pHurt->GetAbsOrigin()+Vector(32.0f,32.0f,0.0f), random->RandomInt( 16, 32 ) ); - - // Play a random attack hit sound - EmitSound( "NPC_Ichthyosaur.Bite" ); - - if ( GetActivity() == ACT_MELEE_ATTACK1 ) - { - SetActivity( (Activity) ACT_ICH_BITE_HIT ); - } - - return; - } - - //Play the miss animation and sound - if ( GetActivity() == ACT_MELEE_ATTACK1 ) - { - SetActivity( (Activity) ACT_ICH_BITE_MISS ); - } - - //Miss sound - EmitSound( "NPC_Ichthyosaur.BiteMiss" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Ichthyosaur::Beached( void ) -{ - trace_t tr; - Vector testPos; - - testPos = GetAbsOrigin() - Vector( 0, 0, ICH_DEPTH_PREFERENCE ); - - AI_TraceHull( GetAbsOrigin(), testPos, GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - - return ( tr.fraction < 1.0f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Ichthyosaur::PrescheduleThink( void ) -{ - BaseClass::PrescheduleThink(); - - //Ambient sounds - /* - if ( random->RandomInt( 0, 20 ) == 10 ) - { - if ( random->RandomInt( 0, 1 ) ) - { - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pSwimSound, random->RandomFloat( 0.0f, 0.5f ), 1.0f ); - } - else - { - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pVoiceSound, random->RandomFloat( 0.0f, 0.5f ), 1.0f ); - } - } - */ - - //Pings - if ( m_flNextPingTime < gpGlobals->curtime ) - { - m_flNextPingTime = gpGlobals->curtime + random->RandomFloat( 3.0f, 8.0f ); - } - - //Growls - if ( ( m_NPCState == NPC_STATE_COMBAT || m_NPCState == NPC_STATE_ALERT ) && ( m_flNextGrowlTime < gpGlobals->curtime ) ) - { - m_flNextGrowlTime = gpGlobals->curtime + random->RandomFloat( 2.0f, 6.0f ); - } - - //Randomly emit bubbles - if ( random->RandomInt( 0, 10 ) == 0 ) - { - UTIL_Bubbles( GetAbsOrigin()+(GetHullMins()*0.5f), GetAbsOrigin()+(GetHullMaxs()*0.5f), 1 ); - } - - //Check our water level - if ( GetWaterLevel() != 3 ) - { - if ( GetWaterLevel() < 2 ) - { - DevMsg( 2, "Came out of water\n" ); - - if ( Beached() ) - { - SetSchedule( SCHED_ICH_THRASH ); - - Vector vecNewVelocity = GetAbsVelocity(); - vecNewVelocity[2] = 8.0f; - SetAbsVelocity( vecNewVelocity ); - } - } - else - { - //TODO: Wake effects - } - } - - //If we have a victim, update them - if ( m_pVictim != NULL ) - { - //See if it's time to release the victim - if ( m_flHoldTime < gpGlobals->curtime ) - { - ReleaseVictim(); - return; - } - - Bite(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pevInflictor - -// *pAttacker - -// flDamage - -// bitsDamageType - -//----------------------------------------------------------------------------- -int CNPC_Ichthyosaur::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - //Release the player if he's struck us while being held - if ( m_flHoldTime > gpGlobals->curtime ) - { - ReleaseVictim(); - - //Don't give them as much time to flee - m_flNextBiteTime = gpGlobals->curtime + 2.0f; - - SetSchedule( SCHED_ICH_THRASH ); - } - - return BaseClass::OnTakeDamage_Alive( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Ichthyosaur::EnsnareVictim( CBaseEntity *pVictim ) -{ - CBaseCombatCharacter* pBCC = (CBaseCombatCharacter *) pVictim; - - if ( pBCC && pBCC->DispatchInteraction( g_interactionBarnacleVictimGrab, NULL, this ) ) - { - if ( pVictim->IsPlayer() ) - { - CBasePlayer *pPlayer = dynamic_cast< CBasePlayer * >((CBaseEntity *) pVictim); - - if ( pPlayer ) - { - m_flHoldTime = MAX( gpGlobals->curtime+3.0f, pPlayer->PlayerDrownTime() - 2.0f ); - } - } - else - { - m_flHoldTime = gpGlobals->curtime + 4.0f; - } - - m_pVictim = pVictim; - m_pVictim->AddSolidFlags( FSOLID_NOT_SOLID ); - - SetSchedule( SCHED_ICH_DROWN_VICTIM ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Ichthyosaur::ReleaseVictim( void ) -{ - CBaseCombatCharacter *pBCC = (CBaseCombatCharacter *) m_pVictim; - - pBCC->DispatchInteraction( g_interactionBarnacleVictimReleased, NULL, this ); - - m_pVictim->RemoveSolidFlags( FSOLID_NOT_SOLID ); - - m_pVictim = NULL; - m_flNextBiteTime = gpGlobals->curtime + 8.0f; - m_flHoldTime = gpGlobals->curtime - 0.1f; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : speed to move at -//----------------------------------------------------------------------------- -float CNPC_Ichthyosaur::GetGroundSpeed( void ) -{ - if ( m_flHoldTime > gpGlobals->curtime ) - return ICH_SWIM_SPEED_WALK/2.0f; - - if ( GetIdealActivity() == ACT_WALK ) - return ICH_SWIM_SPEED_WALK; - - if ( GetIdealActivity() == ACT_ICH_THRASH ) - return ICH_SWIM_SPEED_WALK; - - return ICH_SWIM_SPEED_RUN; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// Output : int -//----------------------------------------------------------------------------- -int CNPC_Ichthyosaur::TranslateSchedule( int type ) -{ - if ( type == SCHED_CHASE_ENEMY ) return SCHED_ICH_CHASE_ENEMY; - //if ( type == SCHED_IDLE_STAND ) return SCHED_PATROL_WALK; - if ( type == SCHED_PATROL_RUN ) return SCHED_ICH_PATROL_RUN; - if ( type == SCHED_PATROL_WALK ) return SCHED_ICH_PATROL_WALK; - if ( type == SCHED_MELEE_ATTACK1 ) return SCHED_ICH_MELEE_ATTACK1; - - return BaseClass::TranslateSchedule( type ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTask - -//----------------------------------------------------------------------------- -void CNPC_Ichthyosaur::StartTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_ICH_THRASH_PATH: - GetNavigator()->SetMovementActivity( (Activity) ACT_ICH_THRASH ); - TaskComplete(); - break; - - case TASK_ICH_GET_PATH_TO_RANDOM_NODE: - { - if ( GetEnemy() == NULL || !GetNavigator()->SetRandomGoal( GetEnemy()->GetLocalOrigin(), pTask->flTaskData ) ) - { - if (!GetNavigator()->SetRandomGoal( pTask->flTaskData ) ) - { - TaskFail(FAIL_NO_REACHABLE_NODE); - return; - } - } - - TaskComplete(); - } - break; - - case TASK_ICH_GET_PATH_TO_DROWN_NODE: - { - Vector drownPos = GetLocalOrigin() - Vector( 0, 0, pTask->flTaskData ); - - if ( GetNavigator()->SetGoal( drownPos, AIN_CLEAR_TARGET ) == false ) - { - TaskFail( FAIL_NO_ROUTE ); - return; - } - - TaskComplete(); - } - break; - - case TASK_MELEE_ATTACK1: - m_flPlaybackRate = 1.0f; - BaseClass::StartTask(pTask); - break; - - default: - BaseClass::StartTask(pTask); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTask - -//----------------------------------------------------------------------------- -void CNPC_Ichthyosaur::RunTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_ICH_GET_PATH_TO_RANDOM_NODE: - return; - break; - - case TASK_ICH_GET_PATH_TO_DROWN_NODE: - return; - break; - - default: - BaseClass::RunTask(pTask); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : desired yaw speed -//----------------------------------------------------------------------------- -float CNPC_Ichthyosaur::MaxYawSpeed( void ) -{ - if ( GetIdealActivity() == ACT_MELEE_ATTACK1 ) - return 16.0f; - - if ( GetIdealActivity() == ACT_ICH_THRASH ) - return 16.0f; - - //Ramp up the yaw speed as we increase our speed - return ICH_MIN_TURN_SPEED + ( (ICH_MAX_TURN_SPEED-ICH_MIN_TURN_SPEED) * ( fabs(GetAbsVelocity().Length()) / ICH_SWIM_SPEED_RUN ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEnemy - -// &chasePosition - -// &tolerance - -//----------------------------------------------------------------------------- -void CNPC_Ichthyosaur::TranslateNavGoal( CBaseEntity *pEnemy, Vector &chasePosition ) -{ - Vector offset = pEnemy->EyePosition() - pEnemy->GetAbsOrigin(); - chasePosition += offset; -} - -float CNPC_Ichthyosaur::GetDefaultNavGoalTolerance() -{ - return GetHullWidth()*2.0f; -} - - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -//================================================== -// SCHED_ICH_CHASE_ENEMY -//================================================== - -AI_DEFINE_SCHEDULE -( - SCHED_ICH_CHASE_ENEMY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ICH_PATROL_WALK" - " TASK_SET_TOLERANCE_DISTANCE 64" - " TASK_SET_GOAL GOAL:ENEMY" - " TASK_GET_PATH_TO_GOAL PATH:TRAVEL" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_ENEMY_UNREACHABLE" - " COND_CAN_MELEE_ATTACK1" - " COND_TOO_CLOSE_TO_ATTACK" - " COND_LOST_ENEMY" - " COND_TASK_FAILED" -); - -//================================================== -// SCHED_ICH_PATROL_RUN -//================================================== - -AI_DEFINE_SCHEDULE -( - SCHED_ICH_PATROL_RUN, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_COMBAT_FACE" - " TASK_SET_TOLERANCE_DISTANCE 64" - " TASK_SET_ROUTE_SEARCH_TIME 4" - " TASK_ICH_GET_PATH_TO_RANDOM_NODE 200" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_CAN_MELEE_ATTACK1" - " COND_GIVE_WAY" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" -); - -//================================================== -// SCHED_ICH_PATROL_WALK -//================================================== - -AI_DEFINE_SCHEDULE -( - SCHED_ICH_PATROL_WALK, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_COMBAT_FACE" - " TASK_SET_TOLERANCE_DISTANCE 64" - " TASK_SET_ROUTE_SEARCH_TIME 4" - " TASK_ICH_GET_PATH_TO_RANDOM_NODE 200" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_CAN_MELEE_ATTACK1" - " COND_GIVE_WAY" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" -); - -//================================================== -// SCHED_ICH_DROWN_VICTIM -//================================================== - -AI_DEFINE_SCHEDULE -( - SCHED_ICH_DROWN_VICTIM, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_COMBAT_FACE" - " TASK_SET_TOLERANCE_DISTANCE 64" - " TASK_SET_ROUTE_SEARCH_TIME 4" - " TASK_ICH_GET_PATH_TO_DROWN_NODE 256" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" -); - -//========================================================= -// SCHED_ICH_MELEE_ATTACK1 -//========================================================= - -AI_DEFINE_SCHEDULE -( - SCHED_ICH_MELEE_ATTACK1, - - " Tasks" - " TASK_ANNOUNCE_ATTACK 1" - " TASK_MELEE_ATTACK1 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_ENEMY_OCCLUDED" -); - -//================================================== -// SCHED_ICH_THRASH -//================================================== - -AI_DEFINE_SCHEDULE -( - SCHED_ICH_THRASH, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_COMBAT_FACE" - " TASK_SET_TOLERANCE_DISTANCE 64" - " TASK_SET_ROUTE_SEARCH_TIME 4" - " TASK_ICH_GET_PATH_TO_RANDOM_NODE 64" - " TASK_ICH_THRASH_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" -); diff --git a/game/server/hl2/npc_kleiner.cpp b/game/server/hl2/npc_kleiner.cpp deleted file mode 100644 index 34798497f..000000000 --- a/game/server/hl2/npc_kleiner.cpp +++ /dev/null @@ -1,125 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Dr. Kleiner, a suave ladies man leading the fight against the evil -// combine while constantly having to help his idiot assistant Gordon -// -//=============================================================================// - - -//----------------------------------------------------------------------------- -// Generic NPC - purely for scripted sequence work. -//----------------------------------------------------------------------------- -#include "cbase.h" -#include "npcevent.h" -#include "ai_basenpc.h" -#include "ai_hull.h" -#include "ai_baseactor.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// NPC's Anim Events Go Here -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CNPC_Kleiner : public CAI_BaseActor -{ -public: - DECLARE_CLASS( CNPC_Kleiner, CAI_BaseActor ); - - void Spawn( void ); - void Precache( void ); - Class_T Classify ( void ); - void HandleAnimEvent( animevent_t *pEvent ); - int GetSoundInterests ( void ); -}; - -LINK_ENTITY_TO_CLASS( npc_kleiner, CNPC_Kleiner ); - -//----------------------------------------------------------------------------- -// Classify - indicates this NPC's place in the -// relationship table. -//----------------------------------------------------------------------------- -Class_T CNPC_Kleiner::Classify ( void ) -{ - return CLASS_PLAYER_ALLY_VITAL; -} - - - -//----------------------------------------------------------------------------- -// HandleAnimEvent - catches the NPC-specific messages -// that occur when tagged animation frames are played. -//----------------------------------------------------------------------------- -void CNPC_Kleiner::HandleAnimEvent( animevent_t *pEvent ) -{ - switch( pEvent->event ) - { - case 1: - default: - BaseClass::HandleAnimEvent( pEvent ); - break; - } -} - -//----------------------------------------------------------------------------- -// GetSoundInterests - generic NPC can't hear. -//----------------------------------------------------------------------------- -int CNPC_Kleiner::GetSoundInterests ( void ) -{ - return 0; -} - -//----------------------------------------------------------------------------- -// Spawn -//----------------------------------------------------------------------------- -void CNPC_Kleiner::Spawn() -{ - // Allow custom model usage (mostly for monitors) - const char *szModel = (char *)STRING( GetModelName() ); - if (!szModel || !*szModel) - { - szModel = "models/kleiner.mdl"; - SetModelName( AllocPooledString(szModel) ); - } - - Precache(); - SetModel( szModel ); - - BaseClass::Spawn(); - - SetHullType(HULL_HUMAN); - SetHullSizeNormal(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - SetBloodColor( BLOOD_COLOR_RED ); - m_iHealth = 8; - m_flFieldOfView = 0.5;// indicates the width of this NPC's forward view cone ( as a dotproduct result ) - m_NPCState = NPC_STATE_NONE; - - CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_OPEN_DOORS | bits_CAP_ANIMATEDFACE | bits_CAP_TURN_HEAD ); - CapabilitiesAdd( bits_CAP_FRIENDLY_DMG_IMMUNE ); - - AddEFlags( EFL_NO_DISSOLVE | EFL_NO_MEGAPHYSCANNON_RAGDOLL | EFL_NO_PHYSCANNON_INTERACTION ); - - NPCInit(); -} - -//----------------------------------------------------------------------------- -// Precache - precaches all resources this NPC needs -//----------------------------------------------------------------------------- -void CNPC_Kleiner::Precache() -{ - PrecacheModel( STRING( GetModelName() ) ); - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// AI Schedules Specific to this NPC -//----------------------------------------------------------------------------- diff --git a/game/server/hl2/npc_launcher.cpp b/game/server/hl2/npc_launcher.cpp deleted file mode 100644 index 123649f4f..000000000 --- a/game/server/hl2/npc_launcher.cpp +++ /dev/null @@ -1,413 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ai_basenpc.h" -#include "ai_senses.h" -#include "ai_squad.h" -#include "grenade_homer.h" -#include "grenade_pathfollower.h" -#include "explode.h" -#include "ndebugoverlay.h" -#include "engine/IEngineSound.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define LAUNCHER_REST_TIME 3 - - -//------------------------------------ -// Spawnflags -//------------------------------------ -#define SF_LAUNCHER_CHECK_LOS (1 << 16) - - -//========================================================= -// >> CNPC_Launcher -//========================================================= -class CNPC_Launcher : public CAI_BaseNPC -{ - DECLARE_CLASS( CNPC_Launcher, CAI_BaseNPC ); - -public: - int m_nStartOn; - string_t m_sMissileModel; - string_t m_sLaunchSound; - string_t m_sFlySound; - int m_nSmokeTrail; - bool m_bSmokeLaunch; - int m_nLaunchDelay; - float m_flLaunchSpeed; - string_t m_sPathCornerName; // If following a path - float m_flHomingSpeed; - int m_nHomingStrength; - float m_flHomingDelay; // How long before homing starts - float m_flHomingRampUp; // How much time to ramp up to full homing - float m_flHomingDuration; // How long does homing last - float m_flHomingRampDown; // How long to ramp down to no homing - float m_flMissileGravity; - float m_flMinAttackDist; - float m_flMaxAttackDist; - float m_flSpinMagnitude; - float m_flSpinSpeed; - float m_flDamage; - float m_flDamageRadius; - - // ---------------- - // Outputs - // ---------------- - COutputEvent m_OnLaunch; // Triggered when missile is launched. - - // ---------------- - // Inputs - // ---------------- - void InputTurnOn( inputdata_t &inputdata ); - void InputTurnOff( inputdata_t &inputdata ); - void InputLOSCheckOn( inputdata_t &inputdata ); - void InputLOSCheckOff( inputdata_t &inputdata ); - void InputSetEnemy( inputdata_t &inputdata ); - void InputClearEnemy( inputdata_t &inputdata ); - void InputFireOnce( inputdata_t &inputdata ); - - void LauncherTurnOn(void); - - void Precache( void ); - void Spawn( void ); - Class_T Classify( void ); - bool IsValidEnemy(CBaseEntity *pTarget ); - void LaunchGrenade(CBaseEntity* pLauncher ); - void LauncherThink(void ); - bool FInViewCone( CBaseEntity *pEntity ); - - int DrawDebugTextOverlays(void); - - DECLARE_DATADESC(); -}; - - -BEGIN_DATADESC( CNPC_Launcher ) - - // Inputs - DEFINE_KEYFIELD( m_nStartOn, FIELD_INTEGER, "StartOn" ), - DEFINE_KEYFIELD( m_sMissileModel, FIELD_STRING, "MissileModel" ), - DEFINE_KEYFIELD( m_sLaunchSound, FIELD_STRING, "LaunchSound" ), - DEFINE_KEYFIELD( m_sFlySound, FIELD_STRING, "FlySound" ), - DEFINE_KEYFIELD( m_nSmokeTrail, FIELD_INTEGER, "SmokeTrail" ), - DEFINE_KEYFIELD( m_bSmokeLaunch, FIELD_BOOLEAN, "LaunchSmoke" ), - DEFINE_KEYFIELD( m_nLaunchDelay, FIELD_INTEGER, "LaunchDelay" ), - DEFINE_KEYFIELD( m_flLaunchSpeed, FIELD_FLOAT, "LaunchSpeed" ), - DEFINE_KEYFIELD( m_sPathCornerName, FIELD_STRING, "PathCornerName" ), - DEFINE_KEYFIELD( m_flHomingSpeed, FIELD_FLOAT, "HomingSpeed" ), - DEFINE_KEYFIELD( m_nHomingStrength, FIELD_INTEGER, "HomingStrength" ), - DEFINE_KEYFIELD( m_flHomingDelay, FIELD_FLOAT, "HomingDelay" ), - DEFINE_KEYFIELD( m_flHomingRampUp, FIELD_FLOAT, "HomingRampUp" ), - DEFINE_KEYFIELD( m_flHomingDuration, FIELD_FLOAT, "HomingDuration" ), - DEFINE_KEYFIELD( m_flHomingRampDown, FIELD_FLOAT, "HomingRampDown" ), - DEFINE_KEYFIELD( m_flGravity, FIELD_FLOAT, "Gravity" ), - DEFINE_KEYFIELD( m_flMinAttackDist, FIELD_FLOAT, "MinRange" ), - DEFINE_KEYFIELD( m_flMaxAttackDist, FIELD_FLOAT, "MaxRange" ), - DEFINE_KEYFIELD( m_flSpinMagnitude, FIELD_FLOAT, "SpinMagnitude" ), - DEFINE_KEYFIELD( m_flSpinSpeed, FIELD_FLOAT, "SpinSpeed" ), - DEFINE_KEYFIELD( m_flDamage, FIELD_FLOAT, "Damage" ), - DEFINE_KEYFIELD( m_flDamageRadius, FIELD_FLOAT, "DamageRadius" ), - DEFINE_FIELD( m_flMissileGravity, FIELD_FLOAT ), - - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - DEFINE_INPUTFUNC( FIELD_VOID, "LOSCheckOn", InputLOSCheckOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "LOSCheckOn", InputLOSCheckOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "FireOnce", InputFireOnce ), - DEFINE_INPUTFUNC( FIELD_EHANDLE, "SetEnemyEntity", InputSetEnemy ), - DEFINE_INPUTFUNC( FIELD_VOID, "ClearEnemyEntity", InputClearEnemy ), - - DEFINE_OUTPUT( m_OnLaunch, "OnLaunch" ), - - // Function Pointers - DEFINE_THINKFUNC( LauncherThink ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( npc_launcher, CNPC_Launcher ); - - -// =================== -// Input Functions -// =================== -void CNPC_Launcher::InputTurnOn( inputdata_t &inputdata ) -{ - LauncherTurnOn(); -} - -void CNPC_Launcher::InputTurnOff( inputdata_t &inputdata ) -{ - SetThink(NULL); -} - -void CNPC_Launcher::InputLOSCheckOn( inputdata_t &inputdata ) -{ - m_spawnflags |= SF_LAUNCHER_CHECK_LOS; -} - -void CNPC_Launcher::InputLOSCheckOff( inputdata_t &inputdata ) -{ - m_spawnflags &= ~SF_LAUNCHER_CHECK_LOS; -} - -void CNPC_Launcher::InputSetEnemy( inputdata_t &inputdata ) -{ - SetEnemy( inputdata.value.Entity().Get() ); -} - -void CNPC_Launcher::InputClearEnemy( inputdata_t &inputdata ) -{ - SetEnemy( NULL ); -} - -void CNPC_Launcher::InputFireOnce( inputdata_t &inputdata ) -{ - m_flNextAttack = 0; - - // If I using path following missiles just launch - if (m_sPathCornerName != NULL_STRING) - { - LaunchGrenade(NULL); - } - // Otherwise only launch if I have an enemy - else - { - LauncherThink(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Launcher::Precache( void ) -{ - // This is a dummy model that is never used! - PrecacheModel("models/player.mdl"); - PrecacheModel(STRING(m_sMissileModel)); - PrecacheScriptSound( STRING(m_sLaunchSound)); - PrecacheScriptSound( STRING(m_sFlySound)); - - UTIL_PrecacheOther( "grenade_homer"); - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Launcher::LauncherTurnOn(void) -{ - SetThink(&CNPC_Launcher::LauncherThink); - SetNextThink( gpGlobals->curtime ); - m_flNextAttack = 0; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Launcher::Spawn( void ) -{ - Precache(); - - // This is a dummy model that is never used! - SetModel( "models/player.mdl" ); - - UTIL_SetSize(this, vec3_origin, vec3_origin); - - m_takedamage = DAMAGE_NO; - - if (m_nHomingStrength > 100) - { - m_nHomingStrength = 100; - Warning("WARNING: NPC_Launcher Homing Strength must be between 0 and 100\n"); - } - - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NONE ); - SetBloodColor( DONT_BLEED ); - AddEffects( EF_NODRAW ); - - AddFlag( FL_NPC ); - - CapabilitiesAdd( bits_CAP_SQUAD ); - - InitRelationshipTable(); - - if (m_nStartOn) - { - LauncherTurnOn(); - } - - // ------------------------------------------------------- - // If I form squads add me to a squad - // ------------------------------------------------------- - // @TODO (toml 12-05-02): RECONCILE WITH SAVE/RESTORE - if (!m_pSquad) - { - m_pSquad = g_AI_SquadManager.FindCreateSquad(this, m_SquadName); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Class_T CNPC_Launcher::Classify( void ) -{ - return CLASS_NONE; -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CNPC_Launcher::LaunchGrenade( CBaseEntity* pEnemy ) -{ - // If a path following missile, create a path following missile - if (m_sPathCornerName != NULL_STRING) - { - CGrenadePathfollower *pGrenade = CGrenadePathfollower::CreateGrenadePathfollower( m_sMissileModel, m_sFlySound, GetAbsOrigin(), vec3_angle, edict() ); - pGrenade->SetDamage(m_flDamage); - pGrenade->SetDamageRadius(m_flDamageRadius); - pGrenade->Launch(m_flLaunchSpeed,m_sPathCornerName); - } - else - { - Vector vUp; - AngleVectors( GetAbsAngles(), NULL, NULL, &vUp ); - Vector vLaunchVelocity = (vUp * m_flLaunchSpeed); - - CGrenadeHomer *pGrenade = CGrenadeHomer::CreateGrenadeHomer( m_sMissileModel, m_sFlySound, GetAbsOrigin(), vec3_angle, edict() ); - pGrenade->Spawn( ); - pGrenade->SetSpin(m_flSpinMagnitude,m_flSpinSpeed); - pGrenade->SetHoming((0.01*m_nHomingStrength),m_flHomingDelay,m_flHomingRampUp,m_flHomingDuration,m_flHomingRampDown); - pGrenade->SetDamage(m_flDamage); - pGrenade->SetDamageRadius(m_flDamageRadius); - pGrenade->Launch(this,pEnemy,vLaunchVelocity,m_flHomingSpeed,GetGravity(),m_nSmokeTrail); - } - - CPASAttenuationFilter filter( this, 0.3 ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_WEAPON; - ep.m_pSoundName = STRING(m_sLaunchSound); - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - - if (m_bSmokeLaunch) - { - UTIL_Smoke(GetAbsOrigin(), random->RandomInt(20,30), random->RandomInt(10,15)); - } - m_flNextAttack = gpGlobals->curtime + LAUNCHER_REST_TIME; - -} - -//------------------------------------------------------------------------------ -// Purpose : Launcher sees 360 degrees -//------------------------------------------------------------------------------ -bool CNPC_Launcher::FInViewCone( CBaseEntity *pEntity ) -{ - return true; -} - -//------------------------------------------------------------------------------ -// Purpose : Override base class to check range and visibility -//------------------------------------------------------------------------------ -bool CNPC_Launcher::IsValidEnemy( CBaseEntity *pTarget ) -{ - // --------------------------------- - // Check range - // --------------------------------- - float flTargetDist = (GetAbsOrigin() - pTarget->GetAbsOrigin()).Length(); - if (flTargetDist < m_flMinAttackDist) - { - return false; - } - if (flTargetDist > m_flMaxAttackDist) - { - return false; - } - - if (!FBitSet (m_spawnflags, SF_LAUNCHER_CHECK_LOS)) - { - return true; - } - // ------------------------------------------------------ - // Make sure I can see the target from above my position - // ------------------------------------------------------ - trace_t tr; - - // Trace from launch position to target position. - // Use position above actual barral based on vertical launch speed - Vector vStartPos = GetAbsOrigin() + Vector(0,0,0.2*m_flLaunchSpeed); - Vector vEndPos = pTarget->GetAbsOrigin(); - AI_TraceLine( vStartPos, vEndPos, MASK_SHOT, pTarget, COLLISION_GROUP_NONE, &tr ); - - if (tr.fraction == 1.0) - { - return true; - } - return false; -} - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CNPC_Launcher::LauncherThink( void ) -{ - if (gpGlobals->curtime > m_flNextAttack) - { - // If enemy was set, fire at enemy - if (GetEnemy()) - { - LaunchGrenade(GetEnemy()); - m_OnLaunch.FireOutput(GetEnemy(), this); - m_flNextAttack = gpGlobals->curtime + m_nLaunchDelay; - } - // Otherwise look for enemy to fire at - else - { - GetSenses()->Look((int)m_flMaxAttackDist); - CBaseEntity* pBestEnemy = BestEnemy(); - - if (pBestEnemy) - { - LaunchGrenade(pBestEnemy); - m_OnLaunch.FireOutput(pBestEnemy, this); - m_flNextAttack = gpGlobals->curtime + m_nLaunchDelay; - } - } - } - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CNPC_Launcher::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - Q_snprintf(tempstr,sizeof(tempstr),"State: %s", (m_pfnThink) ? "On" : "Off" ); - EntityText(text_offset,tempstr,0); - text_offset++; - - Q_snprintf(tempstr,sizeof(tempstr),"LOS: %s", (FBitSet (m_spawnflags, SF_LAUNCHER_CHECK_LOS)) ? "On" : "Off" ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} diff --git a/game/server/hl2/npc_manhack.cpp b/game/server/hl2/npc_manhack.cpp deleted file mode 100644 index 23245f6a2..000000000 --- a/game/server/hl2/npc_manhack.cpp +++ /dev/null @@ -1,3428 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "soundenvelope.h" -#include "npc_manhack.h" -#include "ai_default.h" -#include "ai_node.h" -#include "ai_navigator.h" -#include "ai_pathfinder.h" -#include "ai_moveprobe.h" -#include "ai_memory.h" -#include "ai_squad.h" -#include "ai_route.h" -#include "explode.h" -#include "basegrenade_shared.h" -#include "ndebugoverlay.h" -#include "decals.h" -#include "gib.h" -#include "game.h" -#include "ai_interactions.h" -#include "IEffects.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "movevars_shared.h" -#include "npcevent.h" -#include "props.h" -#include "te_effect_dispatch.h" -#include "ai_squadslot.h" -#include "world.h" -#include "smoke_trail.h" -#include "func_break.h" -#include "physics_impact_damage.h" -#include "weapon_physcannon.h" -#include "physics_prop_ragdoll.h" -#include "soundent.h" -#include "ammodef.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// When the engine is running and the manhack is operating under power -// we don't let gravity affect him. -#define MANHACK_GRAVITY 0.000 - -#define MANHACK_GIB_COUNT 5 -#define MANHACK_INGORE_WATER_DIST 384 - -// Sound stuff -#define MANHACK_PITCH_DIST1 512 -#define MANHACK_MIN_PITCH1 (100) -#define MANHACK_MAX_PITCH1 (160) -#define MANHACK_WATER_PITCH1 (85) -#define MANHACK_VOLUME1 0.55 - -#define MANHACK_PITCH_DIST2 400 -#define MANHACK_MIN_PITCH2 (85) -#define MANHACK_MAX_PITCH2 (190) -#define MANHACK_WATER_PITCH2 (90) - -#define MANHACK_NOISEMOD_HIDE 5000 - -#define MANHACK_BODYGROUP_BLADE 1 -#define MANHACK_BODYGROUP_BLUR 2 -#define MANHACK_BODYGROUP_OFF 0 -#define MANHACK_BODYGROUP_ON 1 - -// ANIMATION EVENTS -#define MANHACK_AE_START_ENGINE 50 -#define MANHACK_AE_DONE_UNPACKING 51 -#define MANHACK_AE_OPEN_BLADE 52 - -//#define MANHACK_GLOW_SPRITE "sprites/laserdot.vmt" -#define MANHACK_GLOW_SPRITE "sprites/glow1.vmt" - -#define MANHACK_CHARGE_MIN_DIST 200 - -ConVar sk_manhack_health( "sk_manhack_health","0"); -ConVar sk_manhack_melee_dmg( "sk_manhack_melee_dmg","0"); -ConVar sk_manhack_v2( "sk_manhack_v2","1"); - -extern void SpawnBlood(Vector vecSpot, const Vector &vAttackDir, int bloodColor, float flDamage); -extern float GetFloorZ(const Vector &origin); - -//----------------------------------------------------------------------------- -// Private activities. -//----------------------------------------------------------------------------- -Activity ACT_MANHACK_UNPACK; - -//----------------------------------------------------------------------------- -// Manhack Conditions -//----------------------------------------------------------------------------- -enum ManhackConditions -{ - COND_MANHACK_START_ATTACK = LAST_SHARED_CONDITION, // We are able to do a bombing run on the current enemy. -}; - -//----------------------------------------------------------------------------- -// Manhack schedules. -//----------------------------------------------------------------------------- -enum ManhackSchedules -{ - SCHED_MANHACK_ATTACK_HOVER = LAST_SHARED_SCHEDULE, - SCHED_MANHACK_DEPLOY, - SCHED_MANHACK_REGROUP, - SCHED_MANHACK_SWARM_IDLE, - SCHED_MANHACK_SWARM, - SCHED_MANHACK_SWARM_FAILURE, -}; - - -//----------------------------------------------------------------------------- -// Manhack tasks. -//----------------------------------------------------------------------------- -enum ManhackTasks -{ - TASK_MANHACK_HOVER = LAST_SHARED_TASK, - TASK_MANHACK_UNPACK, - TASK_MANHACK_FIND_SQUAD_CENTER, - TASK_MANHACK_FIND_SQUAD_MEMBER, - TASK_MANHACK_MOVEAT_SAVEPOSITION, -}; - -BEGIN_DATADESC( CNPC_Manhack ) - - DEFINE_FIELD( m_vForceVelocity, FIELD_VECTOR), - - DEFINE_FIELD( m_vTargetBanking, FIELD_VECTOR), - DEFINE_FIELD( m_vForceMoveTarget, FIELD_POSITION_VECTOR), - DEFINE_FIELD( m_fForceMoveTime, FIELD_TIME), - DEFINE_FIELD( m_vSwarmMoveTarget, FIELD_POSITION_VECTOR), - DEFINE_FIELD( m_fSwarmMoveTime, FIELD_TIME), - DEFINE_FIELD( m_fEnginePowerScale, FIELD_FLOAT), - - DEFINE_FIELD( m_flNextEngineSoundTime, FIELD_TIME), - DEFINE_FIELD( m_flEngineStallTime, FIELD_TIME), - DEFINE_FIELD( m_flNextBurstTime, FIELD_TIME ), - DEFINE_FIELD( m_flWaterSuspendTime, FIELD_TIME), - DEFINE_FIELD( m_nLastSpinSound, FIELD_INTEGER ), - - // Death - DEFINE_FIELD( m_fSparkTime, FIELD_TIME), - DEFINE_FIELD( m_fSmokeTime, FIELD_TIME), - - DEFINE_FIELD( m_bDirtyPitch, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bGib, FIELD_BOOLEAN), - DEFINE_FIELD( m_bHeld, FIELD_BOOLEAN), - - DEFINE_FIELD( m_bHackedByAlyx, FIELD_BOOLEAN), - DEFINE_FIELD( m_vecLoiterPosition, FIELD_POSITION_VECTOR), - DEFINE_FIELD( m_fTimeNextLoiterPulse, FIELD_TIME), - - DEFINE_FIELD( m_flBumpSuppressTime, FIELD_TIME ), - - DEFINE_FIELD( m_bBladesActive, FIELD_BOOLEAN), - DEFINE_FIELD( m_flBladeSpeed, FIELD_FLOAT), - DEFINE_KEYFIELD( m_bIgnoreClipbrushes, FIELD_BOOLEAN, "ignoreclipbrushes" ), - DEFINE_FIELD( m_hSmokeTrail, FIELD_EHANDLE), - - // DEFINE_FIELD( m_pLightGlow, FIELD_CLASSPTR ), - // DEFINE_FIELD( m_pEyeGlow, FIELD_CLASSPTR ), - - DEFINE_FIELD( m_iPanel1, FIELD_INTEGER ), - DEFINE_FIELD( m_iPanel2, FIELD_INTEGER ), - DEFINE_FIELD( m_iPanel3, FIELD_INTEGER ), - DEFINE_FIELD( m_iPanel4, FIELD_INTEGER ), - - DEFINE_FIELD( m_nLastWaterLevel, FIELD_INTEGER ), - DEFINE_FIELD( m_bDoSwarmBehavior, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_nEnginePitch1, FIELD_INTEGER ), - DEFINE_FIELD( m_flEnginePitch1Time, FIELD_TIME ), - DEFINE_FIELD( m_nEnginePitch2, FIELD_INTEGER ), - DEFINE_FIELD( m_flEnginePitch2Time, FIELD_TIME ), - - // Physics Influence - DEFINE_FIELD( m_hPhysicsAttacker, FIELD_EHANDLE ), - DEFINE_FIELD( m_flLastPhysicsInfluenceTime, FIELD_TIME ), - - DEFINE_FIELD( m_flBurstDuration, FIELD_FLOAT ), - DEFINE_FIELD( m_vecBurstDirection, FIELD_VECTOR ), - DEFINE_FIELD( m_bShowingHostile, FIELD_BOOLEAN ), - - // Function Pointers - DEFINE_INPUTFUNC( FIELD_VOID, "DisableSwarm", InputDisableSwarm ), - DEFINE_INPUTFUNC( FIELD_VOID, "Unpack", InputUnpack ), - - DEFINE_ENTITYFUNC( CrashTouch ), - - DEFINE_BASENPCINTERACTABLE_DATADESC(), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( npc_manhack, CNPC_Manhack ); - -IMPLEMENT_SERVERCLASS_ST(CNPC_Manhack, DT_NPC_Manhack) - SendPropIntWithMinusOneFlag (SENDINFO(m_nEnginePitch1), 8 ), - SendPropFloat(SENDINFO(m_flEnginePitch1Time), 0, SPROP_NOSCALE), - SendPropIntWithMinusOneFlag(SENDINFO(m_nEnginePitch2), 8 ) -END_SEND_TABLE() - - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -CNPC_Manhack::CNPC_Manhack() -{ -#ifdef _DEBUG - m_vForceMoveTarget.Init(); - m_vSwarmMoveTarget.Init(); - m_vTargetBanking.Init(); - m_vForceVelocity.Init(); -#endif - m_bDirtyPitch = true; - m_nLastWaterLevel = 0; - m_nEnginePitch1 = -1; - m_nEnginePitch2 = -1; - m_flEnginePitch1Time = 0; - m_flEnginePitch1Time = 0; - m_bDoSwarmBehavior = true; - m_flBumpSuppressTime = 0; -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -CNPC_Manhack::~CNPC_Manhack() -{ -} - -//----------------------------------------------------------------------------- -// Purpose: Indicates this NPC's place in the relationship table. -//----------------------------------------------------------------------------- -Class_T CNPC_Manhack::Classify(void) -{ - return (m_bHeld||m_bHackedByAlyx) ? CLASS_PLAYER_ALLY : CLASS_MANHACK; -} - - - -//----------------------------------------------------------------------------- -// Purpose: Turns the manhack into a physics corpse when dying. -//----------------------------------------------------------------------------- -void CNPC_Manhack::Event_Dying(void) -{ - DestroySmokeTrail(); - SetHullSizeNormal(); - BaseClass::Event_Dying(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Manhack::GatherConditions() -{ - BaseClass::GatherConditions(); - - if( IsLoitering() && GetEnemy() ) - { - StopLoitering(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_Manhack::PrescheduleThink( void ) -{ - BaseClass::PrescheduleThink(); - - UpdatePanels(); - - if( m_flWaterSuspendTime > gpGlobals->curtime ) - { - // Stuck in water! - - // Reduce engine power so that the manhack lifts out of the water slowly. - m_fEnginePowerScale = 0.75; - } - - // ---------------------------------------- - // Am I in water? - // ---------------------------------------- - if ( GetWaterLevel() > 0 ) - { - if( m_nLastWaterLevel == 0 ) - { - Splash( WorldSpaceCenter() ); - } - - if( IsAlive() ) - { - // If I've been out of water for 2 seconds or more, I'm eligible to be stuck in water again. - if( gpGlobals->curtime - m_flWaterSuspendTime > 2.0 ) - { - m_flWaterSuspendTime = gpGlobals->curtime + 1.0; - } - } - } - else - { - if( m_nLastWaterLevel != 0 ) - { - Splash( WorldSpaceCenter() ); - } - } - - m_nLastWaterLevel = GetWaterLevel(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_Manhack::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - g_vecAttackDir = vecDir; - - if ( info.GetDamageType() & DMG_BULLET) - { - g_pEffects->Ricochet(ptr->endpos,ptr->plane.normal); - } - - if ( info.GetDamageType() & DMG_CLUB ) - { - // Clubbed! -// UTIL_Smoke(GetAbsOrigin(), random->RandomInt(10, 15), 10); - g_pEffects->Sparks( ptr->endpos, 1, 1, &ptr->plane.normal ); - } - - BaseClass::TraceAttack( info, vecDir, ptr ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Manhack::DeathSound( const CTakeDamageInfo &info ) -{ - StopSound("NPC_Manhack.Stunned"); - CPASAttenuationFilter filter2( this, "NPC_Manhack.Die" ); - EmitSound( filter2, entindex(), "NPC_Manhack.Die" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Manhack::ShouldGib( const CTakeDamageInfo &info ) -{ - return ( m_bGib ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_Manhack::Event_Killed( const CTakeDamageInfo &info ) -{ - // turn off the blur! - SetBodygroup( MANHACK_BODYGROUP_BLUR, MANHACK_BODYGROUP_OFF ); - - // Sparks - for (int i = 0; i < 3; i++) - { - Vector sparkPos = GetAbsOrigin(); - sparkPos.x += random->RandomFloat(-12,12); - sparkPos.y += random->RandomFloat(-12,12); - sparkPos.z += random->RandomFloat(-12,12); - g_pEffects->Sparks( sparkPos, 2 ); - } - - // Light - CBroadcastRecipientFilter filter; - te->DynamicLight( filter, 0.0, &GetAbsOrigin(), 255, 180, 100, 0, 100, 0.1, 0 ); - - if ( m_nEnginePitch1 < 0 ) - { - // Probably this manhack was killed immediately after spawning. Turn the sound - // on right now so that we can pitch it up for the crash! - SoundInit(); - } - - // Always gib when clubbed or blasted or crushed, or just randomly - if ( ( info.GetDamageType() & (DMG_CLUB|DMG_CRUSH|DMG_BLAST) ) || ( random->RandomInt( 0, 1 ) ) ) - { - m_bGib = true; - } - else - { - m_bGib = false; - - //FIXME: These don't stay with the ragdolls currently -- jdw - // Long fadeout on the sprites!! - KillSprites( 0.0f ); - } - - BaseClass::Event_Killed( info ); -} - -void CNPC_Manhack::HitPhysicsObject( CBaseEntity *pOther ) -{ - IPhysicsObject *pOtherPhysics = pOther->VPhysicsGetObject(); - Vector pos, posOther; - // Put the force on the line between the manhack origin and hit object origin - VPhysicsGetObject()->GetPosition( &pos, NULL ); - pOtherPhysics->GetPosition( &posOther, NULL ); - Vector dir = posOther - pos; - VectorNormalize(dir); - // size/2 is approx radius - pos += dir * WorldAlignSize().x * 0.5; - Vector cross; - - // UNDONE: Use actual manhack up vector so the fake blade is - // in the right plane? - // Get a vector in the x/y plane in the direction of blade spin (clockwise) - CrossProduct( dir, Vector(0,0,1), cross ); - VectorNormalize( cross ); - // force is a 30kg object going 100 in/s - pOtherPhysics->ApplyForceOffset( cross * 30 * 100, pos ); -} - - -//----------------------------------------------------------------------------- -// Take damage from being thrown by a physcannon -//----------------------------------------------------------------------------- -#define MANHACK_SMASH_SPEED 500.0 // How fast a manhack must slam into something to take full damage -void CNPC_Manhack::TakeDamageFromPhyscannon( CBasePlayer *pPlayer ) -{ - CTakeDamageInfo info; - info.SetDamageType( DMG_GENERIC ); - info.SetInflictor( this ); - info.SetAttacker( pPlayer ); - info.SetDamagePosition( GetAbsOrigin() ); - info.SetDamageForce( Vector( 1.0, 1.0, 1.0 ) ); - - // Convert velocity into damage. - Vector vel; - VPhysicsGetObject()->GetVelocity( &vel, NULL ); - float flSpeed = vel.Length(); - - float flFactor = flSpeed / MANHACK_SMASH_SPEED; - - // Clamp. Don't inflict negative damage or massive damage! - flFactor = clamp( flFactor, 0.0f, 2.0f ); - float flDamage = m_iMaxHealth * flFactor; - -#if 0 - Msg("Doing %f damage for %f speed!\n", flDamage, flSpeed ); -#endif - - info.SetDamage( flDamage ); - TakeDamage( info ); -} - - -//----------------------------------------------------------------------------- -// Take damage from a vehicle; it's like a really big crowbar -//----------------------------------------------------------------------------- -void CNPC_Manhack::TakeDamageFromVehicle( int index, gamevcollisionevent_t *pEvent ) -{ - // Use the vehicle velocity to determine the damage - int otherIndex = !index; - CBaseEntity *pOther = pEvent->pEntities[otherIndex]; - - float flSpeed = pEvent->preVelocity[ otherIndex ].Length(); - flSpeed = clamp( flSpeed, 300.0f, 600.0f ); - float flDamage = SimpleSplineRemapVal( flSpeed, 300.0f, 600.0f, 0.0f, 1.0f ); - if ( flDamage == 0.0f ) - return; - - flDamage *= 20.0f; - - Vector damagePos; - pEvent->pInternalData->GetContactPoint( damagePos ); - - Vector damageForce = 2.0f * pEvent->postVelocity[index] * pEvent->pObjects[index]->GetMass(); - if ( damageForce == vec3_origin ) - { - // This can happen if this entity is a func_breakable, and can't move. - // Use the velocity of the entity that hit us instead. - damageForce = 2.0f * pEvent->postVelocity[!index] * pEvent->pObjects[!index]->GetMass(); - } - Assert( damageForce != vec3_origin ); - CTakeDamageInfo dmgInfo( pOther, pOther, damageForce, damagePos, flDamage, DMG_CRUSH ); - TakeDamage( dmgInfo ); -} - - -//----------------------------------------------------------------------------- -// Take damage from combine ball -//----------------------------------------------------------------------------- -void CNPC_Manhack::TakeDamageFromPhysicsImpact( int index, gamevcollisionevent_t *pEvent ) -{ - CBaseEntity *pHitEntity = pEvent->pEntities[!index]; - - // NOTE: Bypass the normal impact energy scale here. - float flDamageScale = PlayerHasMegaPhysCannon() ? 10.0f : 1.0f; - int damageType = 0; - float damage = CalculateDefaultPhysicsDamage( index, pEvent, flDamageScale, true, damageType ); - if ( damage == 0 ) - return; - - Vector damagePos; - pEvent->pInternalData->GetContactPoint( damagePos ); - Vector damageForce = pEvent->postVelocity[index] * pEvent->pObjects[index]->GetMass(); - if ( damageForce == vec3_origin ) - { - // This can happen if this entity is motion disabled, and can't move. - // Use the velocity of the entity that hit us instead. - damageForce = pEvent->postVelocity[!index] * pEvent->pObjects[!index]->GetMass(); - } - - // FIXME: this doesn't pass in who is responsible if some other entity "caused" this collision - PhysCallbackDamage( this, CTakeDamageInfo( pHitEntity, pHitEntity, damageForce, damagePos, damage, damageType ), *pEvent, index ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -#define MANHACK_SMASH_TIME 0.35 // How long after being thrown from a physcannon that a manhack is eligible to die from impact -void CNPC_Manhack::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) -{ - BaseClass::VPhysicsCollision( index, pEvent ); - - // Take no impact damage while being carried. - if ( IsHeldByPhyscannon() ) - return; - - // Wake us up - if ( m_spawnflags & SF_MANHACK_PACKED_UP ) - { - SetCondition( COND_LIGHT_DAMAGE ); - } - - int otherIndex = !index; - CBaseEntity *pHitEntity = pEvent->pEntities[otherIndex]; - - CBasePlayer *pPlayer = HasPhysicsAttacker( MANHACK_SMASH_TIME ); - if( pPlayer ) - { - if (!pHitEntity) - { - TakeDamageFromPhyscannon( pPlayer ); - StopBurst( true ); - return; - } - - // Don't take damage from NPCs or server ragdolls killed by the manhack - CRagdollProp *pRagdollProp = dynamic_cast(pHitEntity); - if (!pHitEntity->IsNPC() && (!pRagdollProp || pRagdollProp->GetKiller() != this)) - { - TakeDamageFromPhyscannon( pPlayer ); - StopBurst( true ); - return; - } - } - - if ( pHitEntity ) - { - // It can take physics damage if it rams into a vehicle - if ( pHitEntity->GetServerVehicle() ) - { - TakeDamageFromVehicle( index, pEvent ); - } - else if ( pHitEntity->HasPhysicsAttacker( 0.5f ) ) - { - // It also can take physics damage from things thrown by the player. - TakeDamageFromPhysicsImpact( index, pEvent ); - } - else if ( FClassnameIs( pHitEntity, "prop_combine_ball" ) ) - { - // It also can take physics damage from a combine ball. - TakeDamageFromPhysicsImpact( index, pEvent ); - } - else if ( m_iHealth <= 0 ) - { - TakeDamageFromPhysicsImpact( index, pEvent ); - } - - StopBurst( true ); - } -} - - -void CNPC_Manhack::VPhysicsShadowCollision( int index, gamevcollisionevent_t *pEvent ) -{ - int otherIndex = !index; - CBaseEntity *pOther = pEvent->pEntities[otherIndex]; - - if ( pOther->GetMoveType() == MOVETYPE_VPHYSICS ) - { - HitPhysicsObject( pOther ); - } - BaseClass::VPhysicsShadowCollision( index, pEvent ); -} - -//----------------------------------------------------------------------------- -// Purpose: Manhack is out of control! (dying) Just explode as soon as you touch anything! -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_Manhack::CrashTouch( CBaseEntity *pOther ) -{ - CTakeDamageInfo info( GetWorldEntity(), GetWorldEntity(), 25, DMG_CRUSH ); - - CorpseGib( info ); -} - - -//----------------------------------------------------------------------------- -// Create smoke trail! -//----------------------------------------------------------------------------- -void CNPC_Manhack::CreateSmokeTrail() -{ - if ( HasSpawnFlags( SF_MANHACK_NO_DAMAGE_EFFECTS ) ) - return; - - if ( m_hSmokeTrail != NULL ) - return; - - SmokeTrail *pSmokeTrail = SmokeTrail::CreateSmokeTrail(); - if( !pSmokeTrail ) - return; - - pSmokeTrail->m_SpawnRate = 20; - pSmokeTrail->m_ParticleLifetime = 0.5f; - pSmokeTrail->m_StartSize = 8; - pSmokeTrail->m_EndSize = 32; - pSmokeTrail->m_SpawnRadius = 5; - pSmokeTrail->m_MinSpeed = 15; - pSmokeTrail->m_MaxSpeed = 25; - - pSmokeTrail->m_StartColor.Init( 0.4f, 0.4f, 0.4f ); - pSmokeTrail->m_EndColor.Init( 0, 0, 0 ); - - pSmokeTrail->SetLifetime(-1); - pSmokeTrail->FollowEntity(this); - - m_hSmokeTrail = pSmokeTrail; -} - -void CNPC_Manhack::DestroySmokeTrail() -{ - if ( m_hSmokeTrail.Get() ) - { - UTIL_Remove( m_hSmokeTrail ); - m_hSmokeTrail = NULL; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int CNPC_Manhack::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - // Hafta make a copy of info cause we might need to scale damage.(sjb) - CTakeDamageInfo tdInfo = info; - - if( tdInfo.GetAmmoType() == GetAmmoDef()->Index("SniperRound") ) - { - // Unfortunately, this is the easiest way to stop the sniper killing manhacks in one shot. - tdInfo.SetDamage( m_iMaxHealth>>1 ); - } - - if (info.GetDamageType() & DMG_PHYSGUN ) - { - m_flBladeSpeed = 20.0; - - // respond to physics - // FIXME: shouldn't this happen in a base class? Anyway to prevent it from happening twice? - VPhysicsTakeDamage( info ); - - // reduce damage to nothing - tdInfo.SetDamage( 1.0 ); - - StopBurst( true ); - } - else if ( info.GetDamageType() & DMG_AIRBOAT ) - { - // Airboat gun kills me instantly. - tdInfo.SetDamage( GetHealth() ); - } - else if (info.GetDamageType() & DMG_CLUB) - { - // Being hit by a club means a couple of things: - // - // -I'm going to be knocked away from the person that clubbed me. - // if fudging this vector a little bit could help me slam into a physics object, - // then make that adjustment. This is a simple heuristic. The manhack will be - // directed towards the physics object that is closest to g_vecAttackDir - // - - // -Take 150% damage from club attacks. This makes crowbar duels take two hits. - - tdInfo.ScaleDamage( 1.50 ); - -#define MANHACK_PHYS_SEARCH_SIZE 64 -#define MANHACK_PHYSICS_SEARCH_RADIUS 128 - - CBaseEntity *pList[ MANHACK_PHYS_SEARCH_SIZE ]; - - Vector attackDir = info.GetDamageForce(); - VectorNormalize( attackDir ); - - Vector testCenter = GetAbsOrigin() + ( attackDir * MANHACK_PHYSICS_SEARCH_RADIUS ); - Vector vecDelta( MANHACK_PHYSICS_SEARCH_RADIUS, MANHACK_PHYSICS_SEARCH_RADIUS, MANHACK_PHYSICS_SEARCH_RADIUS ); - - int count = UTIL_EntitiesInBox( pList, MANHACK_PHYS_SEARCH_SIZE, testCenter - vecDelta, testCenter + vecDelta, 0 ); - - Vector vecBestDir = g_vecAttackDir; - float flBestDot = 0.90; - IPhysicsObject *pPhysObj; - - int i; - for( i = 0 ; i < count ; i++ ) - { - pPhysObj = pList[ i ]->VPhysicsGetObject(); - - if( !pPhysObj || pPhysObj->GetMass() > 200 ) - { - // Not physics. - continue; - } - - Vector center = pList[ i ]->WorldSpaceCenter(); - - Vector vecDirToObject; - VectorSubtract( center, WorldSpaceCenter(), vecDirToObject ); - VectorNormalize( vecDirToObject ); - - float flDot; - - flDot = DotProduct( g_vecAttackDir, vecDirToObject ); - - - if( flDot > flBestDot ) - { - flBestDot = flDot; - vecBestDir = vecDirToObject; - } - } - - tdInfo.SetDamageForce( vecBestDir * info.GetDamage() * 200 ); - - // FIXME: shouldn't this happen in a base class? Anyway to prevent it from happening twice? - VPhysicsTakeDamage( tdInfo ); - - // Force us away (no more residual speed hits!) - m_vForceVelocity = vecBestDir * info.GetDamage() * 0.5f; - m_flBladeSpeed = 10.0; - - EmitSound( "NPC_Manhack.Bat" ); - - // tdInfo.SetDamage( 1.0 ); - - m_flEngineStallTime = gpGlobals->curtime + 0.5f; - StopBurst( true ); - } - else - { - m_flBladeSpeed = 20.0; - - Vector vecDamageDir = tdInfo.GetDamageForce(); - VectorNormalize( vecDamageDir ); - - m_flEngineStallTime = gpGlobals->curtime + 0.25f; - m_vForceVelocity = vecDamageDir * info.GetDamage() * 20.0f; - - tdInfo.SetDamageForce( tdInfo.GetDamageForce() * 20 ); - - VPhysicsTakeDamage( info ); - } - - int nRetVal = BaseClass::OnTakeDamage_Alive( tdInfo ); - if ( nRetVal ) - { - if ( m_iHealth > 0 ) - { - if ( info.GetDamageType() & DMG_CLUB ) - { - SetEyeState( MANHACK_EYE_STATE_STUNNED ); - } - - if ( m_iHealth <= ( m_iMaxHealth / 2 ) ) - { - CreateSmokeTrail(); - } - } - else - { - DestroySmokeTrail(); - } - } - - return nRetVal; -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -bool CNPC_Manhack::CorpseGib( const CTakeDamageInfo &info ) -{ - Vector vecGibVelocity; - AngularImpulse vecGibAVelocity; - - if( info.GetDamageType() & DMG_CLUB ) - { - // If clubbed to death, break apart before the attacker's eyes! - vecGibVelocity = g_vecAttackDir * -150; - - vecGibAVelocity.x = random->RandomFloat( -2000, 2000 ); - vecGibAVelocity.y = random->RandomFloat( -2000, 2000 ); - vecGibAVelocity.z = random->RandomFloat( -2000, 2000 ); - } - else - { - // Shower the pieces with my velocity. - vecGibVelocity = GetCurrentVelocity(); - - vecGibAVelocity.x = random->RandomFloat( -500, 500 ); - vecGibAVelocity.y = random->RandomFloat( -500, 500 ); - vecGibAVelocity.z = random->RandomFloat( -500, 500 ); - } - - PropBreakableCreateAll( GetModelIndex(), NULL, GetAbsOrigin(), GetAbsAngles(), vecGibVelocity, vecGibAVelocity, 1.0, 60, COLLISION_GROUP_DEBRIS ); - - RemoveDeferred(); - - KillSprites( 0.0f ); - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Explode the manhack if it's damaged while crashing -// Input : -// Output : -//----------------------------------------------------------------------------- -int CNPC_Manhack::OnTakeDamage_Dying( const CTakeDamageInfo &info ) -{ - // Ignore damage for the first 1 second of crashing behavior. - // If we don't do this, manhacks always just explode under - // sustained fire. - VPhysicsTakeDamage( info ); - - return 0; -} - -//----------------------------------------------------------------------------- -// Turn on the engine sound if we're gagged! -//----------------------------------------------------------------------------- -void CNPC_Manhack::OnStateChange( NPC_STATE OldState, NPC_STATE NewState ) -{ - if( m_vNoiseMod.z == MANHACK_NOISEMOD_HIDE && !(m_spawnflags & SF_NPC_WAIT_FOR_SCRIPT) && !(m_spawnflags & SF_MANHACK_PACKED_UP) ) - { - // This manhack should get a normal noisemod now. - float flNoiseMod = random->RandomFloat( 1.7, 2.3 ); - - // Just bob up and down. - SetNoiseMod( 0, 0, flNoiseMod ); - } - - if( NewState != NPC_STATE_IDLE && (m_spawnflags & SF_NPC_GAG) && (m_nEnginePitch1 < 0) ) - { - m_spawnflags &= ~SF_NPC_GAG; - SoundInit(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : Type - -//----------------------------------------------------------------------------- -void CNPC_Manhack::HandleAnimEvent( animevent_t *pEvent ) -{ - Vector vecNewVelocity; - switch( pEvent->event ) - { - case MANHACK_AE_START_ENGINE: - StartEye(); - StartEngine( true ); - m_spawnflags &= ~SF_MANHACK_PACKED_UP; - - // No bursts until fully unpacked! - m_flNextBurstTime = gpGlobals->curtime + FLT_MAX; - break; - - case MANHACK_AE_DONE_UNPACKING: - m_flNextBurstTime = gpGlobals->curtime + 2.0; - break; - - case MANHACK_AE_OPEN_BLADE: - m_bBladesActive = true; - break; - - default: - BaseClass::HandleAnimEvent( pEvent ); - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns whether or not the given activity would translate to flying. -//----------------------------------------------------------------------------- -bool CNPC_Manhack::IsFlyingActivity( Activity baseAct ) -{ - return ((baseAct == ACT_FLY || baseAct == ACT_IDLE || baseAct == ACT_RUN || baseAct == ACT_WALK) && m_bBladesActive); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : Type - -//----------------------------------------------------------------------------- -Activity CNPC_Manhack::NPC_TranslateActivity( Activity baseAct ) -{ - if (IsFlyingActivity( baseAct )) - { - return (Activity)ACT_FLY; - } - - return BaseClass::NPC_TranslateActivity( baseAct ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : Type - -//----------------------------------------------------------------------------- -int CNPC_Manhack::TranslateSchedule( int scheduleType ) -{ - // Fail-safe for deployment if packed up and interrupted - if ( m_spawnflags & SF_MANHACK_PACKED_UP ) - { - if ( scheduleType != SCHED_WAIT_FOR_SCRIPT ) - return SCHED_MANHACK_DEPLOY; - } - - switch ( scheduleType ) - { - case SCHED_MELEE_ATTACK1: - { - return SCHED_MANHACK_ATTACK_HOVER; - break; - } - case SCHED_BACK_AWAY_FROM_ENEMY: - { - return SCHED_MANHACK_REGROUP; - break; - } - case SCHED_CHASE_ENEMY: - { - // If we're waiting for our next attack opportunity, just swarm - if ( m_flNextBurstTime > gpGlobals->curtime ) - { - return SCHED_MANHACK_SWARM; - } - - if ( !m_bDoSwarmBehavior || OccupyStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - { - return SCHED_CHASE_ENEMY; - } - else - { - return SCHED_MANHACK_SWARM; - } - } - case SCHED_COMBAT_FACE: - { - // Don't care about facing enemy, handled automatically - return TranslateSchedule( SCHED_CHASE_ENEMY ); - break; - } - case SCHED_WAKE_ANGRY: - { - if( m_spawnflags & SF_MANHACK_PACKED_UP ) - { - return SCHED_MANHACK_DEPLOY; - } - else - { - return TranslateSchedule( SCHED_CHASE_ENEMY ); - } - break; - } - - case SCHED_IDLE_STAND: - case SCHED_ALERT_STAND: - case SCHED_ALERT_FACE: - { - if ( m_pSquad && m_bDoSwarmBehavior ) - { - return SCHED_MANHACK_SWARM_IDLE; - } - else - { - return BaseClass::TranslateSchedule(scheduleType); - } - } - - case SCHED_CHASE_ENEMY_FAILED: - { - // Relentless bastard! Doesn't fail (fail not valid anyway) - return TranslateSchedule( SCHED_CHASE_ENEMY ); - break; - } - - } - return BaseClass::TranslateSchedule(scheduleType); -} - -#define MAX_LOITER_DIST_SQR 144 // (12 inches sqr) -void CNPC_Manhack::Loiter() -{ - //NDebugOverlay::Line( GetAbsOrigin(), m_vecLoiterPosition, 255, 255, 255, false, 0.1 ); - - // Friendly manhack is loitering. - if( !m_bHeld ) - { - float distSqr = m_vecLoiterPosition.DistToSqr(GetAbsOrigin()); - - if( distSqr > MAX_LOITER_DIST_SQR ) - { - Vector vecDir = m_vecLoiterPosition - GetAbsOrigin(); - VectorNormalize( vecDir ); - - // Move back to our loiter position. - if( gpGlobals->curtime > m_fTimeNextLoiterPulse ) - { - // Apply a pulse of force if allowed right now. - if( distSqr > MAX_LOITER_DIST_SQR * 4.0f ) - { - //Msg("Big Pulse\n"); - m_vForceVelocity = vecDir * 12.0f; - } - else - { - //Msg("Small Pulse\n"); - m_vForceVelocity = vecDir * 6.0f; - } - - m_fTimeNextLoiterPulse = gpGlobals->curtime + 1.0f; - } - else - { - m_vForceVelocity = vec3_origin; - } - } - else - { - // Counteract velocity to slow down. - Vector velocity = GetCurrentVelocity(); - m_vForceVelocity = velocity * -0.5; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Manhack::MaintainGroundHeight( void ) -{ - float zSpeed = GetCurrentVelocity().z; - - if ( zSpeed > 32.0f ) - return; - - const float minGroundHeight = 52.0f; - - trace_t tr; - AI_TraceHull( GetAbsOrigin(), - GetAbsOrigin() - Vector( 0, 0, minGroundHeight ), - GetHullMins(), - GetHullMaxs(), - (MASK_NPCSOLID_BRUSHONLY), - this, - COLLISION_GROUP_NONE, - &tr ); - - if ( tr.fraction != 1.0f ) - { - float speedAdj = MAX( 16, (-zSpeed*0.5f) ); - - m_vForceVelocity += Vector(0,0,1) * ( speedAdj * ( 1.0f - tr.fraction ) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Handles movement towards the last move target. -// Input : flInterval - -//----------------------------------------------------------------------------- -bool CNPC_Manhack::OverrideMove( float flInterval ) -{ - SpinBlades( flInterval ); - - // Don't execute any move code if packed up. - if( HasSpawnFlags(SF_MANHACK_PACKED_UP|SF_MANHACK_CARRIED) ) - return true; - - if( IsLoitering() ) - { - Loiter(); - } - else - { - MaintainGroundHeight(); - } - - // So cops, etc. will try to avoid them - if ( !HasSpawnFlags( SF_MANHACK_NO_DANGER_SOUNDS ) && !m_bHeld ) - { - CSoundEnt::InsertSound( SOUND_DANGER, GetAbsOrigin(), 75, flInterval, this ); - } - - // ----------------------------------------------------------------- - // If I'm being forced to move somewhere - // ------------------------------------------------------------------ - if (m_fForceMoveTime > gpGlobals->curtime) - { - MoveToTarget(flInterval, m_vForceMoveTarget); - } - // ----------------------------------------------------------------- - // If I have a route, keep it updated and move toward target - // ------------------------------------------------------------------ - else if (GetNavigator()->IsGoalActive()) - { - bool bReducible = GetNavigator()->GetPath()->GetCurWaypoint()->IsReducible(); - const float strictTolerance = 64.0; - //NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + Vector(0, 0, 10 ), 255, 0, 0, true, 0.1); - if ( ProgressFlyPath( flInterval, GetEnemy(), MoveCollisionMask(), bReducible, strictTolerance ) == AINPP_COMPLETE ) - return true; - } - // ----------------------------------------------------------------- - // If I'm supposed to swarm somewhere, try to go there - // ------------------------------------------------------------------ - else if (m_fSwarmMoveTime > gpGlobals->curtime) - { - MoveToTarget(flInterval, m_vSwarmMoveTarget); - } - // ----------------------------------------------------------------- - // If I don't have anything better to do, just decelerate - // -------------------------------------------------------------- ---- - else - { - float myDecay = 9.5; - Decelerate( flInterval, myDecay ); - - m_vTargetBanking = vec3_origin; - - // ------------------------------------- - // If I have an enemy turn to face him - // ------------------------------------- - if (GetEnemy()) - { - TurnHeadToTarget(flInterval, GetEnemy()->EyePosition() ); - } - } - - if ( m_iHealth <= 0 ) - { - // Crashing!! - MoveExecute_Dead(flInterval); - } - else - { - // Alive! - MoveExecute_Alive(flInterval); - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_Manhack::TurnHeadRandomly(float flInterval ) -{ - float desYaw = random->RandomFloat(0,360); - - float iRate = 0.8; - // Make frame rate independent - float timeToUse = flInterval; - while (timeToUse > 0) - { - m_fHeadYaw = (iRate * m_fHeadYaw) + (1-iRate)*desYaw; - timeToUse =- 0.1; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_Manhack::MoveToTarget(float flInterval, const Vector &vMoveTarget) -{ - if (flInterval <= 0) - { - return; - } - - // ----------------------------------------- - // Don't steer if engine's have stalled - // ----------------------------------------- - if ( gpGlobals->curtime < m_flEngineStallTime || m_iHealth <= 0 ) - return; - - if ( GetEnemy() != NULL ) - { - TurnHeadToTarget( flInterval, GetEnemy()->EyePosition() ); - } - else - { - TurnHeadToTarget( flInterval, vMoveTarget ); - } - - // ------------------------------------- - // Move towards our target - // ------------------------------------- - float myAccel; - float myZAccel = 300.0f; - float myDecay = 0.3f; - - Vector targetDir; - float flDist; - - // If we're bursting, just head straight - if ( m_flBurstDuration > gpGlobals->curtime ) - { - float zDist = 500; - - // Steer towards our enemy if we're able to - if ( GetEnemy() != NULL ) - { - Vector steerDir = ( GetEnemy()->EyePosition() - GetAbsOrigin() ); - zDist = fabs( steerDir.z ); - VectorNormalize( steerDir ); - - float useTime = flInterval; - while ( useTime > 0.0f ) - { - m_vecBurstDirection += ( steerDir * 4.0f ); - useTime -= 0.1f; - } - - m_vecBurstDirection.z = steerDir.z; - - VectorNormalize( m_vecBurstDirection ); - } - - // Debug visualizations - /* - NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + ( targetDir * 64.0f ), 255, 0, 0, true, 2.1f ); - NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + ( steerDir * 64.0f ), 0, 255, 0, true, 2.1f ); - NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + ( m_vecBurstDirection * 64.0f ), 0, 0, 255, true, 2.1f ); - NDebugOverlay::Cross3D( GetAbsOrigin() , -Vector(8,8,8), Vector(8,8,8), 255, 0, 0, true, 2.1f ); - */ - - targetDir = m_vecBurstDirection; - - flDist = FLT_MAX; - myDecay = 0.3f; -#ifdef _XBOX - myAccel = 500; -#else - myAccel = 400; -#endif // _XBOX - myZAccel = MIN( 500, zDist / flInterval ); - } - else - { - Vector vecCurrentDir = GetCurrentVelocity(); - VectorNormalize( vecCurrentDir ); - - targetDir = vMoveTarget - GetAbsOrigin(); - flDist = VectorNormalize( targetDir ); - - float flDot = DotProduct( targetDir, vecCurrentDir ); - - // Otherwise we should steer towards our goal - if( flDot > 0.25 ) - { - // If my target is in front of me, my flight model is a bit more accurate. - myAccel = 300; - } - else - { - // Have a harder time correcting my course if I'm currently flying away from my target. - myAccel = 200; - } - } - - // Clamp lateral acceleration - if ( myAccel > ( flDist / flInterval ) ) - { - myAccel = flDist / flInterval; - } - - /* - // Boost vertical movement - if ( targetDir.z > 0 ) - { - // Z acceleration is faster when we thrust upwards. - // This is to help keep manhacks out of water. - myZAccel *= 5.0; - } - */ - - // Clamp vertical movement - if ( myZAccel > flDist / flInterval ) - { - myZAccel = flDist / flInterval; - } - - // Scale by our engine force - myAccel *= m_fEnginePowerScale; - myZAccel *= m_fEnginePowerScale; - - MoveInDirection( flInterval, targetDir, myAccel, myZAccel, myDecay ); - - // calc relative banking targets - Vector forward, right; - GetVectors( &forward, &right, NULL ); - m_vTargetBanking.x = 40 * DotProduct( forward, targetDir ); - m_vTargetBanking.z = 40 * DotProduct( right, targetDir ); - m_vTargetBanking.y = 0.0; -} - - -//----------------------------------------------------------------------------- -// Purpose: Ignore water if I'm close to my enemy -// Input : -// Output : -//----------------------------------------------------------------------------- -int CNPC_Manhack::MoveCollisionMask(void) -{ - return MASK_NPCSOLID; -} - - -//----------------------------------------------------------------------------- -// Purpose: Make a splash effect -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_Manhack::Splash( const Vector &vecSplashPos ) -{ - CEffectData data; - - data.m_fFlags = 0; - data.m_vOrigin = vecSplashPos; - data.m_vNormal = Vector( 0, 0, 1 ); - - data.m_flScale = 8.0f; - - int contents = GetWaterType(); - - // Verify we have valid contents - if ( !( contents & (CONTENTS_SLIME|CONTENTS_WATER))) - { - // We're leaving the water so we have to reverify what it was - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector( 0, 0, 256 ), (CONTENTS_WATER|CONTENTS_SLIME), this, COLLISION_GROUP_NONE, &tr ); - - // Re-validate this - if ( !(tr.contents&(CONTENTS_WATER|CONTENTS_SLIME)) ) - { - //NOTENOTE: We called a splash but we don't seem to be near water? - Assert( 0 ); - return; - } - - contents = tr.contents; - } - - // Mark us if we're in slime - if ( contents & CONTENTS_SLIME ) - { - data.m_fFlags |= FX_WATER_IN_SLIME; - } - - DispatchEffect( "watersplash", data ); -} - -//----------------------------------------------------------------------------- -// Computes the slice bounce velocity -//----------------------------------------------------------------------------- -void CNPC_Manhack::ComputeSliceBounceVelocity( CBaseEntity *pHitEntity, trace_t &tr ) -{ - if( pHitEntity->IsAlive() && FClassnameIs( pHitEntity, "func_breakable_surf" ) ) - { - // We want to see if the manhack hits a breakable pane of glass. To keep from checking - // The classname of the HitEntity on each impact, we only do this check if we hit - // something that's alive. Anyway, prevent the manhack bouncing off the pane of glass, - // since this impact will shatter the glass and let the manhack through. - return; - } - - Vector vecDir; - - // If the manhack isn't bouncing away from whatever he sliced, force it. - VectorSubtract( WorldSpaceCenter(), pHitEntity->WorldSpaceCenter(), vecDir ); - VectorNormalize( vecDir ); - vecDir *= 200; - vecDir[2] = 0.0f; - - // Knock it away from us - if ( VPhysicsGetObject() != NULL ) - { - VPhysicsGetObject()->ApplyForceOffset( vecDir * 4, GetAbsOrigin() ); - } - - // Also set our velocity - SetCurrentVelocity( vecDir ); -} - - -//----------------------------------------------------------------------------- -// Is the manhack being held? -//----------------------------------------------------------------------------- -bool CNPC_Manhack::IsHeldByPhyscannon( ) -{ - return VPhysicsGetObject() && (VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD); -} - - -//----------------------------------------------------------------------------- -// Purpose: We've touched something that we can hurt. Slice it! -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_Manhack::Slice( CBaseEntity *pHitEntity, float flInterval, trace_t &tr ) -{ - // Don't hurt the player if I'm in water - if( GetWaterLevel() > 0 && pHitEntity->IsPlayer() ) - return; - - // Can't slice players holding it with the phys cannon - if ( IsHeldByPhyscannon() ) - { - if ( pHitEntity && (pHitEntity == HasPhysicsAttacker( FLT_MAX )) ) - return; - } - - if ( pHitEntity->m_takedamage == DAMAGE_NO ) - return; - - // Damage must be scaled by flInterval so framerate independent - float flDamage = sk_manhack_melee_dmg.GetFloat() * flInterval; - - if ( pHitEntity->IsPlayer() ) - { - flDamage *= 2.0f; - } - - // Held manhacks do more damage - if ( IsHeldByPhyscannon() ) - { - // Deal 100 damage/sec - flDamage = 100.0f * flInterval; - } - else if ( pHitEntity->IsNPC() && HasPhysicsAttacker( MANHACK_SMASH_TIME ) ) - { - extern ConVar sk_combine_guard_health; - // NOTE: The else here is essential. - // The physics attacker *will* be set even when the manhack is held - flDamage = sk_combine_guard_health.GetFloat(); // the highest healthed fleshy enemy - } - else if ( dynamic_cast(pHitEntity) || dynamic_cast(pHitEntity) ) - { - // If we hit a prop, we want it to break immediately - flDamage = pHitEntity->GetHealth(); - } - else if ( pHitEntity->IsNPC() && IRelationType( pHitEntity ) == D_HT && FClassnameIs( pHitEntity, "npc_combine_s" ) ) - { - flDamage *= 6.0f; - } - - if (flDamage < 1.0f) - { - flDamage = 1.0f; - } - - CTakeDamageInfo info( this, this, flDamage, DMG_SLASH ); - - // check for actual "ownership" of damage - CBasePlayer *pPlayer = HasPhysicsAttacker( MANHACK_SMASH_TIME ); - if (pPlayer) - { - info.SetAttacker( pPlayer ); - } - - Vector dir = (tr.endpos - tr.startpos); - if ( dir == vec3_origin ) - { - dir = tr.m_pEnt->GetAbsOrigin() - GetAbsOrigin(); - } - CalculateMeleeDamageForce( &info, dir, tr.endpos ); - pHitEntity->TakeDamage( info ); - - // Spawn some extra blood where we hit - if ( pHitEntity->BloodColor() == DONT_BLEED ) - { - CEffectData data; - Vector velocity = GetCurrentVelocity(); - - data.m_vOrigin = tr.endpos; - data.m_vAngles = GetAbsAngles(); - - VectorNormalize( velocity ); - - data.m_vNormal = ( tr.plane.normal + velocity ) * 0.5;; - - DispatchEffect( "ManhackSparks", data ); - - EmitSound( "NPC_Manhack.Grind" ); - - //TODO: What we really want to do is get a material reference and emit the proper sprayage! - jdw - } - else - { - SpawnBlood(tr.endpos, g_vecAttackDir, pHitEntity->BloodColor(), 6 ); - EmitSound( "NPC_Manhack.Slice" ); - } - - // Pop back a little bit after hitting the player - ComputeSliceBounceVelocity( pHitEntity, tr ); - - // Save off when we last hit something - m_flLastDamageTime = gpGlobals->curtime; - - // Reset our state and give the player time to react - StopBurst( true ); -} - -//----------------------------------------------------------------------------- -// Purpose: We've touched something solid. Just bump it. -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_Manhack::Bump( CBaseEntity *pHitEntity, float flInterval, trace_t &tr ) -{ - if ( !VPhysicsGetObject() ) - return; - - // Surpressing this behavior - if ( m_flBumpSuppressTime > gpGlobals->curtime ) - return; - - if ( pHitEntity->GetMoveType() == MOVETYPE_VPHYSICS && pHitEntity->Classify()!=CLASS_MANHACK ) - { - HitPhysicsObject( pHitEntity ); - } - - // We've hit something so deflect our velocity based on the surface - // norm of what we've hit - if (flInterval > 0) - { - float moveLen = ( (GetCurrentVelocity() * flInterval) * (1.0 - tr.fraction) ).Length(); - - Vector moveVec = moveLen*tr.plane.normal/flInterval; - - // If I'm totally dead, don't bounce me up - if (m_iHealth <=0 && moveVec.z > 0) - { - moveVec.z = 0; - } - - // If I'm right over the ground don't push down - if (moveVec.z < 0) - { - float floorZ = GetFloorZ(GetAbsOrigin()); - if (fabs(GetAbsOrigin().z - floorZ) < 36.0f) - { - moveVec.z = 0; - } - } - - Vector myUp; - VPhysicsGetObject()->LocalToWorldVector( &myUp, Vector( 0.0, 0.0, 1.0 ) ); - - // plane must be something that could hit the blades - if (fabs( DotProduct( myUp, tr.plane.normal ) ) < 0.25 ) - { - CEffectData data; - Vector velocity = GetCurrentVelocity(); - - data.m_vOrigin = tr.endpos; - data.m_vAngles = GetAbsAngles(); - - VectorNormalize( velocity ); - - data.m_vNormal = ( tr.plane.normal + velocity ) * 0.5;; - - DispatchEffect( "ManhackSparks", data ); - - CBroadcastRecipientFilter filter; - - te->DynamicLight( filter, 0.0, &GetAbsOrigin(), 255, 180, 100, 0, 50, 0.3, 150 ); - - // add some spin, but only if we're not already going fast.. - Vector vecVelocity; - AngularImpulse vecAngVelocity; - VPhysicsGetObject()->GetVelocity( &vecVelocity, &vecAngVelocity ); - float flDot = DotProduct( myUp, vecAngVelocity ); - if ( fabs(flDot) < 100 ) - { - //AngularImpulse torque = myUp * (1000 - flDot * 10); - AngularImpulse torque = myUp * (1000 - flDot * 2); - VPhysicsGetObject()->ApplyTorqueCenter( torque ); - } - - if (!(m_spawnflags & SF_NPC_GAG)) - { - EmitSound( "NPC_Manhack.Grind" ); - } - - // For decals and sparks we must trace a line in the direction of the surface norm - // that we hit. - trace_t decalTrace; - AI_TraceLine( GetAbsOrigin(), GetAbsOrigin() - (tr.plane.normal * 24),MASK_SOLID, this, COLLISION_GROUP_NONE, &decalTrace ); - - if ( decalTrace.fraction != 1.0 ) - { - // Leave decal only if colliding horizontally - if ((DotProduct(Vector(0,0,1),decalTrace.plane.normal)<0.5) && (DotProduct(Vector(0,0,-1),decalTrace.plane.normal)<0.5)) - { - UTIL_DecalTrace( &decalTrace, "ManhackCut" ); - } - } - } - - // See if we will not have a valid surface - if ( tr.allsolid || tr.startsolid ) - { - // Build a fake reflection back along our current velocity because we can't know how to reflect off - // a non-existant surface! -- jdw - - Vector vecRandomDir = RandomVector( -1.0f, 1.0f ); - SetCurrentVelocity( vecRandomDir * 50.0f ); - m_flBumpSuppressTime = gpGlobals->curtime + 0.5f; - } - else - { - // This is a valid hit and we can deflect properly - - VectorNormalize( moveVec ); - float hitAngle = -DotProduct( tr.plane.normal, -moveVec ); - - Vector vReflection = 2.0 * tr.plane.normal * hitAngle + -moveVec; - - float flSpeed = GetCurrentVelocity().Length(); - SetCurrentVelocity( GetCurrentVelocity() + vReflection * flSpeed * 0.5f ); - } - } - - // ------------------------------------------------------------- - // If I'm on a path check LOS to my next node, and fail on path - // if I don't have LOS. Note this is the only place I do this, - // so the manhack has to collide before failing on a path - // ------------------------------------------------------------- - if (GetNavigator()->IsGoalActive() && !(GetNavigator()->GetPath()->CurWaypointFlags() & bits_WP_TO_PATHCORNER) ) - { - AIMoveTrace_t moveTrace; - GetMoveProbe()->MoveLimit( NAV_GROUND, GetAbsOrigin(), GetNavigator()->GetCurWaypointPos(), - MoveCollisionMask(), GetEnemy(), &moveTrace ); - - if (IsMoveBlocked( moveTrace ) && - !moveTrace.pObstruction->ClassMatches( GetClassname() )) - { - TaskFail(FAIL_NO_ROUTE); - GetNavigator()->ClearGoal(); - return; - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_Manhack::CheckCollisions(float flInterval) -{ - // Trace forward to see if I hit anything. But trace forward along the - // owner's view direction if you're being carried. - Vector vecTraceDir, vecCheckPos; - VPhysicsGetObject()->GetVelocity( &vecTraceDir, NULL ); - vecTraceDir *= flInterval; - if ( IsHeldByPhyscannon() ) - { - CBasePlayer *pCarrier = HasPhysicsAttacker( FLT_MAX ); - if ( pCarrier ) - { - if ( pCarrier->CollisionProp()->CalcDistanceFromPoint( WorldSpaceCenter() ) < 30 ) - { - AngleVectors( pCarrier->EyeAngles(), &vecTraceDir, NULL, NULL ); - vecTraceDir *= 40.0f; - } - } - } - - VectorAdd( GetAbsOrigin(), vecTraceDir, vecCheckPos ); - - trace_t tr; - CBaseEntity* pHitEntity = NULL; - - AI_TraceHull( GetAbsOrigin(), - vecCheckPos, - GetHullMins(), - GetHullMaxs(), - MoveCollisionMask(), - this, - COLLISION_GROUP_NONE, - &tr ); - - if ( (tr.fraction != 1.0 || tr.startsolid) && tr.m_pEnt) - { - PhysicsMarkEntitiesAsTouching( tr.m_pEnt, tr ); - pHitEntity = tr.m_pEnt; - - if( m_bHeld && tr.m_pEnt->MyNPCPointer() && tr.m_pEnt->MyNPCPointer()->IsPlayerAlly() ) - { - // Don't slice Alyx when she approaches to hack. We need a better solution for this!! - //Msg("Ignoring!\n"); - return; - } - - if ( pHitEntity != NULL && - pHitEntity->m_takedamage == DAMAGE_YES && - pHitEntity->Classify() != CLASS_MANHACK && - gpGlobals->curtime > m_flWaterSuspendTime ) - { - // Slice this thing - Slice( pHitEntity, flInterval, tr ); - m_flBladeSpeed = 20.0; - } - else - { - // Just bump into this thing. - Bump( pHitEntity, flInterval, tr ); - m_flBladeSpeed = 20.0; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -#define tempTIME_STEP = 0.5; -void CNPC_Manhack::PlayFlySound(void) -{ - float flEnemyDist; - - if( GetEnemy() ) - { - flEnemyDist = (GetAbsOrigin() - GetEnemy()->GetAbsOrigin()).Length(); - } - else - { - flEnemyDist = FLT_MAX; - } - - if( m_spawnflags & SF_NPC_GAG ) - { - // Quiet! - return; - } - - if( m_flWaterSuspendTime > gpGlobals->curtime ) - { - // Just went in water. Slow the motor!! - if( m_bDirtyPitch ) - { - m_nEnginePitch1 = MANHACK_WATER_PITCH1; - m_flEnginePitch1Time = gpGlobals->curtime + 0.5f; - m_nEnginePitch2 = MANHACK_WATER_PITCH2; - m_flEnginePitch2Time = gpGlobals->curtime + 0.5f; - m_bDirtyPitch = false; - } - } - // Spin sound based on distance from enemy (unless we're crashing) - else if (GetEnemy() && IsAlive() ) - { - if( flEnemyDist < MANHACK_PITCH_DIST1 ) - { - // recalculate pitch. - int iPitch1, iPitch2; - float flDistFactor; - - flDistFactor = MIN( 1.0, 1 - flEnemyDist / MANHACK_PITCH_DIST1 ); - iPitch1 = (int)(MANHACK_MIN_PITCH1 + ( ( MANHACK_MAX_PITCH1 - MANHACK_MIN_PITCH1 ) * flDistFactor)); - - // NOTE: MANHACK_PITCH_DIST2 must be < MANHACK_PITCH_DIST1 - flDistFactor = MIN( 1.0, 1 - flEnemyDist / MANHACK_PITCH_DIST2 ); - iPitch2 = (int)(MANHACK_MIN_PITCH2 + ( ( MANHACK_MAX_PITCH2 - MANHACK_MIN_PITCH2 ) * flDistFactor)); - - m_nEnginePitch1 = iPitch1; - m_flEnginePitch1Time = gpGlobals->curtime + 0.1f; - m_nEnginePitch2 = iPitch2; - m_flEnginePitch2Time = gpGlobals->curtime + 0.1f; - - m_bDirtyPitch = true; - } - else if( m_bDirtyPitch ) - { - m_nEnginePitch1 = MANHACK_MIN_PITCH1; - m_flEnginePitch1Time = gpGlobals->curtime + 0.1f; - m_nEnginePitch2 = MANHACK_MIN_PITCH2; - m_flEnginePitch2Time = gpGlobals->curtime + 0.2f; - m_bDirtyPitch = false; - } - } - // If no enemy just play low sound - else if( IsAlive() && m_bDirtyPitch ) - { - m_nEnginePitch1 = MANHACK_MIN_PITCH1; - m_flEnginePitch1Time = gpGlobals->curtime + 0.1f; - m_nEnginePitch2 = MANHACK_MIN_PITCH2; - m_flEnginePitch2Time = gpGlobals->curtime + 0.2f; - - m_bDirtyPitch = false; - } - - // Play special engine every once in a while - if (gpGlobals->curtime > m_flNextEngineSoundTime && flEnemyDist < 48) - { - m_flNextEngineSoundTime = gpGlobals->curtime + random->RandomFloat( 3.0, 10.0 ); - - EmitSound( "NPC_Manhack.EngineNoise" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_Manhack::MoveExecute_Alive(float flInterval) -{ - PhysicsCheckWaterTransition(); - - Vector vCurrentVelocity = GetCurrentVelocity(); - - // FIXME: move this - VPhysicsGetObject()->Wake(); - - if( m_fEnginePowerScale < GetMaxEnginePower() && gpGlobals->curtime > m_flWaterSuspendTime ) - { - // Power is low, and we're no longer stuck in water, so bring power up. - m_fEnginePowerScale += 0.05; - } - - // ---------------------------------------------------------------------------------------- - // Add time-coherent noise to the current velocity so that it never looks bolted in place. - // ---------------------------------------------------------------------------------------- - float noiseScale = 7.0f; - - if ( (CBaseEntity*)GetEnemy() ) - { - float flDist = (GetAbsOrigin() - GetEnemy()->GetAbsOrigin()).Length2D(); - - if( flDist < MANHACK_CHARGE_MIN_DIST ) - { - // Less noise up close. - noiseScale = 2.0; - } - - if ( IsInEffectiveTargetZone( GetEnemy() ) && flDist < MANHACK_CHARGE_MIN_DIST && gpGlobals->curtime > m_flNextBurstTime ) - { - Vector vecCurrentDir = GetCurrentVelocity(); - VectorNormalize( vecCurrentDir ); - - Vector vecToEnemy = ( GetEnemy()->EyePosition() - WorldSpaceCenter() ); - VectorNormalize( vecToEnemy ); - - float flDot = DotProduct( vecCurrentDir, vecToEnemy ); - - if ( flDot > 0.75 ) - { - Vector offsetDir = ( vecToEnemy - vecCurrentDir ); - VectorNormalize( offsetDir ); - - Vector offsetSpeed = GetCurrentVelocity() * flDot; - - //FIXME: This code sucks -- jdw - - offsetDir.z = 0.0f; - m_vForceVelocity += ( offsetDir * ( offsetSpeed.Length2D() * 0.25f ) ); - - // Commit to the attack- no steering for about a second - StartBurst( vecToEnemy ); - SetEyeState( MANHACK_EYE_STATE_CHARGE ); - } - } - - if ( gpGlobals->curtime > m_flBurstDuration ) - { - ShowHostile( false ); - } - } - - // ---------------------------------------------------------------------------------------- - // Add in any forced velocity - // ---------------------------------------------------------------------------------------- - SetCurrentVelocity( vCurrentVelocity + m_vForceVelocity ); - m_vForceVelocity = vec3_origin; - - if( !m_bHackedByAlyx || GetEnemy() ) - { - // If hacked and no enemy, don't drift! - AddNoiseToVelocity( noiseScale ); - } - - LimitSpeed( 200, ManhackMaxSpeed() ); - - if( m_flWaterSuspendTime > gpGlobals->curtime ) - { - if( UTIL_PointContents( GetAbsOrigin() ) & (CONTENTS_WATER|CONTENTS_SLIME) ) - { - // Ooops, we're submerged somehow. Move upwards until our origin is out of the water. - m_vCurrentVelocity.z = 20.0; - } - else - { - // Skimming the surface. Forbid any movement on Z - m_vCurrentVelocity.z = 0.0; - } - } - else if( GetWaterLevel() > 0 ) - { - // Allow the manhack to lift off, but not to go deeper. - m_vCurrentVelocity.z = MAX( m_vCurrentVelocity.z, 0 ); - } - - CheckCollisions(flInterval); - - // Blend out desired velocity when launched by the physcannon - if ( HasPhysicsAttacker( MANHACK_SMASH_TIME ) && (!IsHeldByPhyscannon()) && VPhysicsGetObject() ) - { - Vector vecCurrentVelocity; - VPhysicsGetObject()->GetVelocity( &vecCurrentVelocity, NULL ); - float flLerpFactor = (gpGlobals->curtime - m_flLastPhysicsInfluenceTime) / MANHACK_SMASH_TIME; - flLerpFactor = clamp( flLerpFactor, 0.0f, 1.0f ); - flLerpFactor = SimpleSplineRemapVal( flLerpFactor, 0.0f, 1.0f, 0.0f, 1.0f ); - VectorLerp( vecCurrentVelocity, m_vCurrentVelocity, flLerpFactor, m_vCurrentVelocity ); - } - - QAngle angles = GetLocalAngles(); - - // ------------------------------------------ - // Stalling - // ------------------------------------------ - if (gpGlobals->curtime < m_flEngineStallTime) - { - /* - // If I'm stalled add random noise - angles.x += -20+(random->RandomInt(-10,10)); - angles.z += -20+(random->RandomInt(0,40)); - - TurnHeadRandomly(flInterval); - */ - } - else - { - // Make frame rate independent - float iRate = 0.5; - float timeToUse = flInterval; - while (timeToUse > 0) - { - m_vCurrentBanking.x = (iRate * m_vCurrentBanking.x) + (1 - iRate)*(m_vTargetBanking.x); - m_vCurrentBanking.z = (iRate * m_vCurrentBanking.z) + (1 - iRate)*(m_vTargetBanking.z); - timeToUse =- 0.1; - } - angles.x = m_vCurrentBanking.x; - angles.z = m_vCurrentBanking.z; - angles.y = 0; - -#if 0 - // Using our steering if we're not otherwise affecting our panels - if ( m_flEngineStallTime < gpGlobals->curtime && m_flBurstDuration < gpGlobals->curtime ) - { - Vector delta( 10 * AngleDiff( m_vTargetBanking.x, m_vCurrentBanking.x ), -10 * AngleDiff( m_vTargetBanking.z, m_vCurrentBanking.z ), 0 ); - //Vector delta( 3 * AngleNormalize( m_vCurrentBanking.x ), -4 * AngleNormalize( m_vCurrentBanking.z ), 0 ); - VectorYawRotate( delta, -m_fHeadYaw, delta ); - - // DevMsg("%.0f %.0f\n", delta.x, delta.y ); - - SetPoseParameter( m_iPanel1, -delta.x - delta.y * 2); - SetPoseParameter( m_iPanel2, -delta.x + delta.y * 2); - SetPoseParameter( m_iPanel3, delta.x + delta.y * 2); - SetPoseParameter( m_iPanel4, delta.x - delta.y * 2); - - //SetPoseParameter( m_iPanel1, -delta.x ); - //SetPoseParameter( m_iPanel2, -delta.x ); - //SetPoseParameter( m_iPanel3, delta.x ); - //SetPoseParameter( m_iPanel4, delta.x ); - } -#endif - } - - // SetLocalAngles( angles ); - - if( m_lifeState != LIFE_DEAD ) - { - PlayFlySound(); - // SpinBlades( flInterval ); - // WalkMove( GetCurrentVelocity() * flInterval, MASK_NPCSOLID ); - } - -// NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + Vector(0, 0, -10 ), 0, 255, 0, true, 0.1); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_Manhack::SpinBlades(float flInterval) -{ - if (!m_bBladesActive) - { - SetBodygroup( MANHACK_BODYGROUP_BLADE, MANHACK_BODYGROUP_OFF ); - SetBodygroup( MANHACK_BODYGROUP_BLUR, MANHACK_BODYGROUP_OFF ); - m_flBladeSpeed = 0.0; - m_flPlaybackRate = 1.0; - return; - } - - if ( IsFlyingActivity( GetActivity() ) ) - { - // Blades may only ramp up while the engine is running - if ( m_flEngineStallTime < gpGlobals->curtime ) - { - if (m_flBladeSpeed < 10) - { - m_flBladeSpeed = m_flBladeSpeed * 2 + 1; - } - else - { - // accelerate engine - m_flBladeSpeed = m_flBladeSpeed + 80 * flInterval; - } - } - - if (m_flBladeSpeed > 100) - { - m_flBladeSpeed = 100; - } - - // blend through blades, blades+blur, blur - if (m_flBladeSpeed < 20) - { - SetBodygroup( MANHACK_BODYGROUP_BLADE, MANHACK_BODYGROUP_ON ); - SetBodygroup( MANHACK_BODYGROUP_BLUR, MANHACK_BODYGROUP_OFF ); - } - else if (m_flBladeSpeed < 40) - { - SetBodygroup( MANHACK_BODYGROUP_BLADE, MANHACK_BODYGROUP_ON ); - SetBodygroup( MANHACK_BODYGROUP_BLUR, MANHACK_BODYGROUP_ON ); - } - else - { - SetBodygroup( MANHACK_BODYGROUP_BLADE, MANHACK_BODYGROUP_OFF ); - SetBodygroup( MANHACK_BODYGROUP_BLUR, MANHACK_BODYGROUP_ON ); - } - - m_flPlaybackRate = m_flBladeSpeed / 100.0; - } - else - { - m_flBladeSpeed = 0.0; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Smokes and sparks, exploding periodically. Eventually it goes away. -//----------------------------------------------------------------------------- -void CNPC_Manhack::MoveExecute_Dead(float flInterval) -{ - if( GetWaterLevel() > 0 ) - { - // No movement if sinking in water. - return; - } - - // Periodically emit smoke. - if (gpGlobals->curtime > m_fSmokeTime && GetWaterLevel() == 0) - { -// UTIL_Smoke(GetAbsOrigin(), random->RandomInt(10, 15), 10); - m_fSmokeTime = gpGlobals->curtime + random->RandomFloat( 0.1, 0.3); - } - - // Periodically emit sparks. - if (gpGlobals->curtime > m_fSparkTime) - { - g_pEffects->Sparks( GetAbsOrigin() ); - m_fSparkTime = gpGlobals->curtime + random->RandomFloat(0.1, 0.3); - } - - Vector newVelocity = GetCurrentVelocity(); - - // accelerate faster and faster when dying - newVelocity = newVelocity + (newVelocity * 1.5 * flInterval ); - - // Lose lift - newVelocity.z -= 0.02*flInterval*(sv_gravity.GetFloat()); - - // ---------------------------------------------------------------------------------------- - // Add in any forced velocity - // ---------------------------------------------------------------------------------------- - newVelocity += m_vForceVelocity; - SetCurrentVelocity( newVelocity ); - m_vForceVelocity = vec3_origin; - - - // Lots of noise!! Out of control! - AddNoiseToVelocity( 5.0 ); - - - // ---------------------- - // Limit overall speed - // ---------------------- - LimitSpeed( -1, MANHACK_MAX_SPEED * 2.0 ); - - QAngle angles = GetLocalAngles(); - - // ------------------------------------------ - // If I'm dying, add random banking noise - // ------------------------------------------ - angles.x += -20+(random->RandomInt(0,40)); - angles.z += -20+(random->RandomInt(0,40)); - - CheckCollisions(flInterval); - PlayFlySound(); - - // SetLocalAngles( angles ); - - WalkMove( GetCurrentVelocity() * flInterval,MASK_NPCSOLID ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Manhack::Precache(void) -{ - // - // Model. - // - PrecacheModel("models/manhack.mdl"); - PrecacheModel( MANHACK_GLOW_SPRITE ); - PropBreakablePrecacheAll( MAKE_STRING("models/manhack.mdl") ); - - PrecacheScriptSound( "NPC_Manhack.Die" ); - PrecacheScriptSound( "NPC_Manhack.Bat" ); - PrecacheScriptSound( "NPC_Manhack.Grind" ); - PrecacheScriptSound( "NPC_Manhack.Slice" ); - PrecacheScriptSound( "NPC_Manhack.EngineNoise" ); - PrecacheScriptSound( "NPC_Manhack.Unpack" ); - PrecacheScriptSound( "NPC_Manhack.ChargeAnnounce" ); - PrecacheScriptSound( "NPC_Manhack.ChargeEnd" ); - PrecacheScriptSound( "NPC_Manhack.Stunned" ); - - // Sounds used on Client: - PrecacheScriptSound( "NPC_Manhack.EngineSound1" ); - PrecacheScriptSound( "NPC_Manhack.EngineSound2" ); - PrecacheScriptSound( "NPC_Manhack.BladeSound" ); - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_Manhack::GatherEnemyConditions( CBaseEntity *pEnemy ) -{ - // The Manhack "regroups" when its in attack range but to - // far above or below its enemy. Set the start attack - // condition if we are far enough away from the enemy - // or at the correct height - - // Don't bother with Z if the enemy is in a vehicle - float fl2DDist = 60.0f; - float flZDist = 12.0f; - - if ( GetEnemy()->IsPlayer() && assert_cast< CBasePlayer * >(GetEnemy())->IsInAVehicle() ) - { - flZDist = 24.0f; - } - - if ((GetAbsOrigin() - pEnemy->GetAbsOrigin()).Length2D() > fl2DDist) - { - SetCondition(COND_MANHACK_START_ATTACK); - } - else - { - float targetZ = pEnemy->EyePosition().z; - if (fabs(GetAbsOrigin().z - targetZ) < flZDist) - { - SetCondition(COND_MANHACK_START_ATTACK); - } - } - BaseClass::GatherEnemyConditions(pEnemy); -} - - -//----------------------------------------------------------------------------- -// Purpose: For innate melee attack -// Input : -// Output : -//----------------------------------------------------------------------------- -int CNPC_Manhack::MeleeAttack1Conditions( float flDot, float flDist ) -{ - if ( GetEnemy() == NULL ) - return COND_NONE; - - //TODO: We could also decide if we want to back up here - if ( m_flNextBurstTime > gpGlobals->curtime ) - return COND_NONE; - - float flMaxDist = 45; - float flMinDist = 24; - bool bEnemyInVehicle = GetEnemy()->IsPlayer() && assert_cast< CBasePlayer * >(GetEnemy())->IsInAVehicle(); - if ( GetEnemy()->IsPlayer() && assert_cast< CBasePlayer * >(GetEnemy())->IsInAVehicle() ) - { - flMinDist = 0; - flMaxDist = 200.0f; - } - - if (flDist > flMaxDist) - { - return COND_TOO_FAR_TO_ATTACK; - } - - if (flDist < flMinDist) - { - return COND_TOO_CLOSE_TO_ATTACK; - } - - // Check our current velocity and speed, if it's too far off, we need to settle - - // Don't bother with Z if the enemy is in a vehicle - if ( bEnemyInVehicle ) - { - return COND_CAN_MELEE_ATTACK1; - } - - // Assume the this check is in regards to my current enemy - // for the Manhacks spetial condition - float deltaZ = GetAbsOrigin().z - GetEnemy()->EyePosition().z; - if ( (deltaZ > 12.0f) || (deltaZ < -24.0f) ) - { - return COND_TOO_CLOSE_TO_ATTACK; - } - - return COND_CAN_MELEE_ATTACK1; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTask - -//----------------------------------------------------------------------------- -void CNPC_Manhack::RunTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - // Override this task so we go for the enemy at eye level - case TASK_MANHACK_HOVER: - { - break; - } - - // If my enemy has moved significantly, update my path - case TASK_WAIT_FOR_MOVEMENT: - { - CBaseEntity *pEnemy = GetEnemy(); - if (pEnemy && - (GetCurSchedule()->GetId() == SCHED_CHASE_ENEMY) && - GetNavigator()->IsGoalActive() ) - { - Vector vecEnemyPosition; - vecEnemyPosition = pEnemy->EyePosition(); - if ( GetNavigator()->GetGoalPos().DistToSqr(vecEnemyPosition) > 40 * 40 ) - { - GetNavigator()->UpdateGoalPos( vecEnemyPosition ); - } - } - BaseClass::RunTask(pTask); - break; - } - - case TASK_MANHACK_MOVEAT_SAVEPOSITION: - { - // do the movement thingy - -// NDebugOverlay::Line( GetAbsOrigin(), m_vSavePosition, 0, 255, 0, true, 0.1); - - Vector dir = (m_vSavePosition - GetAbsOrigin()); - float dist = VectorNormalize( dir ); - float t = m_fSwarmMoveTime - gpGlobals->curtime; - - if (t < 0.1) - { - if (dist > 256) - { - TaskFail( FAIL_NO_ROUTE ); - } - else - { - TaskComplete(); - } - } - else if (dist < 64) - { - m_vSwarmMoveTarget = GetAbsOrigin() - Vector( -dir.y, dir.x, 0 ) * 4; - } - else - { - m_vSwarmMoveTarget = GetAbsOrigin() + dir * 10; - } - break; - } - - default: - { - BaseClass::RunTask(pTask); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Manhack::Spawn(void) -{ - Precache(); - -#ifdef _XBOX - // Always fade the corpse - AddSpawnFlags( SF_NPC_FADE_CORPSE ); -#endif // _XBOX - - SetModel( "models/manhack.mdl" ); - SetHullType(HULL_TINY_CENTERED); - SetHullSizeNormal(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - - if ( HasSpawnFlags( SF_MANHACK_CARRIED ) ) - { - AddSolidFlags( FSOLID_NOT_SOLID ); - SetMoveType( MOVETYPE_NONE ); - } - else - { - SetMoveType( MOVETYPE_VPHYSICS ); - } - - m_iHealth = sk_manhack_health.GetFloat(); - SetViewOffset( Vector(0, 0, 10) ); // Position of the eyes relative to NPC's origin. - m_flFieldOfView = VIEW_FIELD_FULL; - m_NPCState = NPC_STATE_NONE; - - if ( m_spawnflags & SF_MANHACK_USE_AIR_NODES) - { - SetNavType(NAV_FLY); - } - else - { - SetNavType(NAV_GROUND); - } - - AddEFlags( EFL_NO_DISSOLVE | EFL_NO_MEGAPHYSCANNON_RAGDOLL ); - AddEffects( EF_NOSHADOW ); - - SetBloodColor( DONT_BLEED ); - SetCurrentVelocity( vec3_origin ); - m_vForceVelocity.Init(); - m_vCurrentBanking.Init(); - m_vTargetBanking.Init(); - - m_flNextBurstTime = gpGlobals->curtime; - - CapabilitiesAdd( bits_CAP_INNATE_MELEE_ATTACK1 | bits_CAP_MOVE_FLY | bits_CAP_SQUAD ); - - m_flNextEngineSoundTime = gpGlobals->curtime; - m_flWaterSuspendTime = gpGlobals->curtime; - m_flEngineStallTime = gpGlobals->curtime; - m_fForceMoveTime = gpGlobals->curtime; - m_vForceMoveTarget = vec3_origin; - m_fSwarmMoveTime = gpGlobals->curtime; - m_vSwarmMoveTarget = vec3_origin; - m_nLastSpinSound = -1; - - m_fSmokeTime = 0; - m_fSparkTime = 0; - - // Set the noise mod to huge numbers right now, in case this manhack starts out waiting for a script - // for instance, we don't want him to bob whilst he's waiting for a script. This allows designers - // to 'hide' manhacks in small places. (sjb) - SetNoiseMod( MANHACK_NOISEMOD_HIDE, MANHACK_NOISEMOD_HIDE, MANHACK_NOISEMOD_HIDE ); - - // Start out with full power! - m_fEnginePowerScale = GetMaxEnginePower(); - - // find panels - m_iPanel1 = LookupPoseParameter( "Panel1" ); - m_iPanel2 = LookupPoseParameter( "Panel2" ); - m_iPanel3 = LookupPoseParameter( "Panel3" ); - m_iPanel4 = LookupPoseParameter( "Panel4" ); - - m_fHeadYaw = 0; - - NPCInit(); - - // Manhacks are designed to slam into things, so don't take much damage from it! - SetImpactEnergyScale( 0.001 ); - - // Manhacks get 30 seconds worth of free knowledge. - GetEnemies()->SetFreeKnowledgeDuration( 30.0 ); - - // don't be an NPC, we want to collide with debris stuff - SetCollisionGroup( COLLISION_GROUP_NONE ); - - m_bHeld = false; - m_bHackedByAlyx = false; - StopLoitering(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Manhack::StartEye( void ) -{ - //Create our Eye sprite - if ( m_pEyeGlow == NULL ) - { - m_pEyeGlow = CSprite::SpriteCreate( MANHACK_GLOW_SPRITE, GetLocalOrigin(), false ); - m_pEyeGlow->SetAttachment( this, LookupAttachment( "Eye" ) ); - - if( m_bHackedByAlyx ) - { - m_pEyeGlow->SetTransparency( kRenderTransAdd, 0, 255, 0, 128, kRenderFxNoDissipation ); - m_pEyeGlow->SetColor( 0, 255, 0 ); - } - else - { - m_pEyeGlow->SetTransparency( kRenderTransAdd, 255, 0, 0, 128, kRenderFxNoDissipation ); - m_pEyeGlow->SetColor( 255, 0, 0 ); - } - - m_pEyeGlow->SetBrightness( 164, 0.1f ); - m_pEyeGlow->SetScale( 0.25f, 0.1f ); - m_pEyeGlow->SetAsTemporary(); - } - - //Create our light sprite - if ( m_pLightGlow == NULL ) - { - m_pLightGlow = CSprite::SpriteCreate( MANHACK_GLOW_SPRITE, GetLocalOrigin(), false ); - m_pLightGlow->SetAttachment( this, LookupAttachment( "Light" ) ); - - if( m_bHackedByAlyx ) - { - m_pLightGlow->SetTransparency( kRenderTransAdd, 0, 255, 0, 128, kRenderFxNoDissipation ); - m_pLightGlow->SetColor( 0, 255, 0 ); - } - else - { - m_pLightGlow->SetTransparency( kRenderTransAdd, 255, 0, 0, 128, kRenderFxNoDissipation ); - m_pLightGlow->SetColor( 255, 0, 0 ); - } - - m_pLightGlow->SetBrightness( 164, 0.1f ); - m_pLightGlow->SetScale( 0.25f, 0.1f ); - m_pLightGlow->SetAsTemporary(); - } -} - -//----------------------------------------------------------------------------- - -void CNPC_Manhack::Activate() -{ - BaseClass::Activate(); - - if ( IsAlive() ) - { - StartEye(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Get the engine sound started. Unless we're not supposed to have it on yet! -//----------------------------------------------------------------------------- -void CNPC_Manhack::PostNPCInit( void ) -{ - // SetAbsVelocity( vec3_origin ); - m_bBladesActive = (m_spawnflags & (SF_MANHACK_PACKED_UP|SF_MANHACK_CARRIED)) ? false : true; - BladesInit(); -} - -void CNPC_Manhack::BladesInit() -{ - if( !m_bBladesActive ) - { - // manhack is packed up, so has no power of its own. - // don't start the engine sounds. - // make us fall a little slower than we should, for visual's sake - SetGravity( UTIL_ScaleForGravity( 400 ) ); - - SetActivity( ACT_IDLE ); - } - else - { - bool engineSound = (m_spawnflags & SF_NPC_GAG) ? false : true; - StartEngine( engineSound ); - SetActivity( ACT_FLY ); - } -} - - -//----------------------------------------------------------------------------- -// Crank up the engine! -//----------------------------------------------------------------------------- -void CNPC_Manhack::StartEngine( bool fStartSound ) -{ - if( fStartSound ) - { - SoundInit(); - } - - // Make the blade appear. - SetBodygroup( 1, 1 ); - - // Pop up a little if falling fast! - Vector vecVelocity; - GetVelocity( &vecVelocity, NULL ); - if( ( m_spawnflags & SF_MANHACK_PACKED_UP ) && vecVelocity.z < 0 ) - { - // DevMsg(" POP UP \n" ); - // ApplyAbsVelocityImpulse( Vector(0,0,-vecVelocity.z*0.75) ); - } - - // Under powered flight now. - // SetMoveType( MOVETYPE_STEP ); - // SetGravity( MANHACK_GRAVITY ); - AddFlag( FL_FLY ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Start the manhack's engine sound. -//----------------------------------------------------------------------------- -void CNPC_Manhack::SoundInit( void ) -{ - m_nEnginePitch1 = MANHACK_MIN_PITCH1; - m_flEnginePitch1Time = gpGlobals->curtime; - m_nEnginePitch2 = MANHACK_MIN_PITCH2; - m_flEnginePitch2Time = gpGlobals->curtime; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Manhack::StopLoopingSounds(void) -{ - BaseClass::StopLoopingSounds(); - m_nEnginePitch1 = -1; - m_flEnginePitch1Time = gpGlobals->curtime; - m_nEnginePitch2 = -1; - m_flEnginePitch2Time = gpGlobals->curtime; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pTask - -//----------------------------------------------------------------------------- -void CNPC_Manhack::StartTask( const Task_t *pTask ) -{ - switch (pTask->iTask) - { - case TASK_MANHACK_UNPACK: - { - // Just play a sound for now. - EmitSound( "NPC_Manhack.Unpack" ); - - TaskComplete(); - } - break; - - case TASK_MANHACK_HOVER: - break; - - case TASK_MOVE_TO_TARGET_RANGE: - case TASK_GET_PATH_TO_GOAL: - case TASK_GET_PATH_TO_ENEMY_LKP: - case TASK_GET_PATH_TO_PLAYER: - { - BaseClass::StartTask( pTask ); - /* - // FIXME: why were these tasks considered bad? - _asm - { - int 3; - int 5; - } - */ - } - break; - - case TASK_FACE_IDEAL: - { - // this shouldn't ever happen, but if it does, don't choke - TaskComplete(); - } - break; - - case TASK_GET_PATH_TO_ENEMY: - { - if (IsUnreachable(GetEnemy())) - { - TaskFail(FAIL_NO_ROUTE); - return; - } - - CBaseEntity *pEnemy = GetEnemy(); - - if ( pEnemy == NULL ) - { - TaskFail(FAIL_NO_ENEMY); - return; - } - - if ( GetNavigator()->SetGoal( GOALTYPE_ENEMY ) ) - { - TaskComplete(); - } - else - { - // no way to get there =( - DevWarning( 2, "GetPathToEnemy failed!!\n" ); - RememberUnreachable(GetEnemy()); - TaskFail(FAIL_NO_ROUTE); - } - break; - } - break; - - case TASK_GET_PATH_TO_TARGET: - // DevMsg("TARGET\n"); - BaseClass::StartTask( pTask ); - break; - - case TASK_MANHACK_FIND_SQUAD_CENTER: - { - if (!m_pSquad) - { - m_vSavePosition = GetAbsOrigin(); - TaskComplete(); - break; - } - - // calc center of squad - int count = 0; - m_vSavePosition = Vector( 0, 0, 0 ); - - // give attacking members more influence - AISquadIter_t iter; - for (CAI_BaseNPC *pSquadMember = m_pSquad->GetFirstMember( &iter ); pSquadMember; pSquadMember = m_pSquad->GetNextMember( &iter ) ) - { - if (pSquadMember->HasStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 )) - { - m_vSavePosition += pSquadMember->GetAbsOrigin() * 10; - count += 10; - } - else - { - m_vSavePosition += pSquadMember->GetAbsOrigin(); - count++; - } - } - - // pull towards enemy - if (GetEnemy() != NULL) - { - m_vSavePosition += GetEnemyLKP() * 4; - count += 4; - } - - Assert( count != 0 ); - m_vSavePosition = m_vSavePosition * (1.0 / count); - - TaskComplete(); - } - break; - - case TASK_MANHACK_FIND_SQUAD_MEMBER: - { - if (m_pSquad) - { - CAI_BaseNPC *pSquadMember = m_pSquad->GetAnyMember(); - m_vSavePosition = pSquadMember->GetAbsOrigin(); - - // find attacking members - AISquadIter_t iter; - for (pSquadMember = m_pSquad->GetFirstMember( &iter ); pSquadMember; pSquadMember = m_pSquad->GetNextMember( &iter ) ) - { - // are they attacking? - if (pSquadMember->HasStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 )) - { - m_vSavePosition = pSquadMember->GetAbsOrigin(); - break; - } - // do they have a goal? - if (pSquadMember->GetNavigator()->IsGoalActive()) - { - m_vSavePosition = pSquadMember->GetAbsOrigin(); - break; - } - } - } - else - { - m_vSavePosition = GetAbsOrigin(); - } - - TaskComplete(); - } - break; - - case TASK_MANHACK_MOVEAT_SAVEPOSITION: - { - trace_t tr; - AI_TraceLine( GetAbsOrigin(), m_vSavePosition, MASK_NPCWORLDSTATIC, this, COLLISION_GROUP_NONE, &tr ); - if (tr.DidHitWorld()) - { - TaskFail( FAIL_NO_ROUTE ); - } - else - { - m_fSwarmMoveTime = gpGlobals->curtime + RandomFloat( pTask->flTaskData * 0.8, pTask->flTaskData * 1.2 ); - } - } - break; - - default: - BaseClass::StartTask(pTask); - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Manhack::UpdateOnRemove( void ) -{ - DestroySmokeTrail(); - KillSprites( 0.0 ); - BaseClass::UpdateOnRemove(); -} - - -//----------------------------------------------------------------------------- -// Purpose: This is a generic function (to be implemented by sub-classes) to -// handle specific interactions between different types of characters -// (For example the barnacle grabbing an NPC) -// Input : Constant for the type of interaction -// Output : true - if sub-class has a response for the interaction -// false - if sub-class has no response -//----------------------------------------------------------------------------- -bool CNPC_Manhack::HandleInteraction(int interactionType, void* data, CBaseCombatCharacter* sourceEnt) -{ - if (interactionType == g_interactionVortigauntClaw) - { - // Freeze so vortigaunt and hit me easier - - m_vForceMoveTarget.x = ((Vector *)data)->x; - m_vForceMoveTarget.y = ((Vector *)data)->y; - m_vForceMoveTarget.z = ((Vector *)data)->z; - m_fForceMoveTime = gpGlobals->curtime + 2.0; - return false; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CNPC_Manhack::ManhackMaxSpeed( void ) -{ - if( m_flWaterSuspendTime > gpGlobals->curtime ) - { - // Slower in water! - return MANHACK_MAX_SPEED * 0.1; - } - - if ( HasPhysicsAttacker( MANHACK_SMASH_TIME ) ) - { - return MANHACK_NPC_BURST_SPEED; - } - - return MANHACK_MAX_SPEED; -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : -//----------------------------------------------------------------------------- -void CNPC_Manhack::ClampMotorForces( Vector &linear, AngularImpulse &angular ) -{ - float scale = m_flBladeSpeed / 100.0; - - // Msg("%.0f %.0f %.0f\n", linear.x, linear.y, linear.z ); - - float fscale = 3000 * scale; - - if ( m_flEngineStallTime > gpGlobals->curtime ) - { - linear.x = 0.0f; - linear.y = 0.0f; - linear.z = clamp( linear.z, -fscale, fscale < 1200 ? 1200 : fscale ); - } - else - { - // limit reaction forces - linear.x = clamp( linear.x, -fscale, fscale ); - linear.y = clamp( linear.y, -fscale, fscale ); - linear.z = clamp( linear.z, -fscale, fscale < 1200 ? 1200 : fscale ); - } - - angular.x *= scale; - angular.y *= scale; - angular.z *= scale; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Manhack::KillSprites( float flDelay ) -{ - if( m_pEyeGlow ) - { - m_pEyeGlow->FadeAndDie( flDelay ); - m_pEyeGlow = NULL; - } - - if( m_pLightGlow ) - { - m_pLightGlow->FadeAndDie( flDelay ); - m_pLightGlow = NULL; - } - - // Re-enable for light trails - /* - if ( m_hLightTrail ) - { - m_hLightTrail->FadeAndDie( flDelay ); - m_hLightTrail = NULL; - } - */ -} - -//----------------------------------------------------------------------------- -// Purpose: Tests whether we're above the target's feet but also below their top -// Input : *pTarget - who we're testing against -//----------------------------------------------------------------------------- -bool CNPC_Manhack::IsInEffectiveTargetZone( CBaseEntity *pTarget ) -{ - Vector vecMaxPos, vecMinPos; - float ourHeight = WorldSpaceCenter().z; - - // If the enemy is in a vehicle, we need to get those bounds - if ( pTarget && pTarget->IsPlayer() && assert_cast< CBasePlayer * >(pTarget)->IsInAVehicle() ) - { - CBaseEntity *pVehicle = assert_cast< CBasePlayer * >(pTarget)->GetVehicleEntity(); - pVehicle->CollisionProp()->NormalizedToWorldSpace( Vector(0.0f,0.0f,1.0f), &vecMaxPos ); - pVehicle->CollisionProp()->NormalizedToWorldSpace( Vector(0.0f,0.0f,0.0f), &vecMinPos ); - - if ( ourHeight > vecMinPos.z && ourHeight < vecMaxPos.z ) - return true; - - return false; - } - - // Get the enemies top and bottom point - pTarget->CollisionProp()->NormalizedToWorldSpace( Vector(0.0f,0.0f,1.0f), &vecMaxPos ); -#ifdef _XBOX - pTarget->CollisionProp()->NormalizedToWorldSpace( Vector(0.0f,0.0f,0.5f), &vecMinPos ); // Only half the body is valid -#else - pTarget->CollisionProp()->NormalizedToWorldSpace( Vector(0.0f,0.0f,0.0f), &vecMinPos ); -#endif // _XBOX - // See if we're within that range - if ( ourHeight > vecMinPos.z && ourHeight < vecMaxPos.z ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEnemy - -// &chasePosition - -// &tolerance - -//----------------------------------------------------------------------------- -void CNPC_Manhack::TranslateNavGoal( CBaseEntity *pEnemy, Vector &chasePosition ) -{ - if ( pEnemy && pEnemy->IsPlayer() && assert_cast< CBasePlayer * >(pEnemy)->IsInAVehicle() ) - { - Vector vecNewPos; - CBaseEntity *pVehicle = assert_cast< CBasePlayer * >(pEnemy)->GetVehicleEntity(); - pVehicle->CollisionProp()->NormalizedToWorldSpace( Vector(0.5,0.5,0.5f), &vecNewPos ); - chasePosition.z = vecNewPos.z; - } - else - { - Vector vecTarget; - pEnemy->CollisionProp()->NormalizedToCollisionSpace( Vector(0,0,0.75f), &vecTarget ); - chasePosition.z += vecTarget.z; - } -} - -float CNPC_Manhack::GetDefaultNavGoalTolerance() -{ - return GetHullWidth(); -} - -//----------------------------------------------------------------------------- -// Purpose: Input that disables the manhack's swarm behavior -//----------------------------------------------------------------------------- -void CNPC_Manhack::InputDisableSwarm( inputdata_t &inputdata ) -{ - m_bDoSwarmBehavior = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_Manhack::InputUnpack( inputdata_t &inputdata ) -{ - if ( HasSpawnFlags( SF_MANHACK_PACKED_UP ) == false ) - return; - - SetCondition( COND_LIGHT_DAMAGE ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPhysGunUser - -// reason - -//----------------------------------------------------------------------------- -void CNPC_Manhack::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) -{ - m_hPhysicsAttacker = pPhysGunUser; - m_flLastPhysicsInfluenceTime = gpGlobals->curtime; - - if ( reason == PUNTED_BY_CANNON ) - { - StopLoitering(); - - m_bHeld = false; - - // There's about to be a massive change in velocity. - // Think immediately so we can do our slice traces, etc. - SetNextThink( gpGlobals->curtime + 0.01f ); - - // Stall our engine for awhile - m_flEngineStallTime = gpGlobals->curtime + 2.0f; - SetEyeState( MANHACK_EYE_STATE_STUNNED ); - } - else - { - // Suppress collisions between the manhack and the player; we're currently bumping - // almost certainly because it's not purely a physics object. - SetOwnerEntity( pPhysGunUser ); - m_bHeld = true; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPhysGunUser - -// Reason - -//----------------------------------------------------------------------------- -void CNPC_Manhack::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ) -{ - // Stop suppressing collisions between the manhack and the player - SetOwnerEntity( NULL ); - - m_bHeld = false; - - if ( Reason == LAUNCHED_BY_CANNON ) - { - m_hPhysicsAttacker = pPhysGunUser; - m_flLastPhysicsInfluenceTime = gpGlobals->curtime; - - // There's about to be a massive change in velocity. - // Think immediately so we can do our slice traces, etc. - SetNextThink( gpGlobals->curtime + 0.01f ); - - // Stall our engine for awhile - m_flEngineStallTime = gpGlobals->curtime + 2.0f; - SetEyeState( MANHACK_EYE_STATE_STUNNED ); - } - else - { - if( m_bHackedByAlyx && !GetEnemy() ) - { - // If a hacked manhack is released in peaceable conditions, - // just loiter, don't zip off. - StartLoitering( GetAbsOrigin() ); - } - - m_hPhysicsAttacker = NULL; - m_flLastPhysicsInfluenceTime = 0; - } -} - -void CNPC_Manhack::StartLoitering( const Vector &vecLoiterPosition ) -{ - //Msg("Start Loitering\n"); - - m_vTargetBanking = vec3_origin; - m_vecLoiterPosition = GetAbsOrigin(); - m_vForceVelocity = vec3_origin; - SetCurrentVelocity( vec3_origin ); -} - -CBasePlayer *CNPC_Manhack::HasPhysicsAttacker( float dt ) -{ - // If the player is holding me now, or I've been recently thrown - // then return a pointer to that player - if ( IsHeldByPhyscannon() || (gpGlobals->curtime - dt <= m_flLastPhysicsInfluenceTime) ) - { - return m_hPhysicsAttacker; - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Manhacks that have been hacked by Alyx get more engine power (fly faster) -//----------------------------------------------------------------------------- -float CNPC_Manhack::GetMaxEnginePower() -{ - if( m_bHackedByAlyx ) - { - return 2.0f; - } - - return 1.0f; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Manhack::UpdatePanels( void ) -{ - if ( m_flEngineStallTime > gpGlobals->curtime ) - { - SetPoseParameter( m_iPanel1, random->RandomFloat( 0.0f, 90.0f ) ); - SetPoseParameter( m_iPanel2, random->RandomFloat( 0.0f, 90.0f ) ); - SetPoseParameter( m_iPanel3, random->RandomFloat( 0.0f, 90.0f ) ); - SetPoseParameter( m_iPanel4, random->RandomFloat( 0.0f, 90.0f ) ); - return; - } - - float panelPosition = GetPoseParameter( m_iPanel1 ); - - if ( m_bShowingHostile ) - { - panelPosition = 90.0f;//UTIL_Approach( 90.0f, panelPosition, 90.0f ); - } - else - { - panelPosition = UTIL_Approach( 0.0f, panelPosition, 25.0f ); - } - - //FIXME: If we're going to have all these be equal, there's no need for 4 poses.. - SetPoseParameter( m_iPanel1, panelPosition ); - SetPoseParameter( m_iPanel2, panelPosition ); - SetPoseParameter( m_iPanel3, panelPosition ); - SetPoseParameter( m_iPanel4, panelPosition ); - - //TODO: Make these waver randomly? -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : hostile - -//----------------------------------------------------------------------------- -void CNPC_Manhack::ShowHostile( bool hostile /*= true*/) -{ - if ( m_bShowingHostile == hostile ) - return; - - //TODO: Open the manhack panels or close them, depending on the state - m_bShowingHostile = hostile; - - if ( hostile ) - { - EmitSound( "NPC_Manhack.ChargeAnnounce" ); - } - else - { - EmitSound( "NPC_Manhack.ChargeEnd" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Manhack::StartBurst( const Vector &vecDirection ) -{ - if ( m_flBurstDuration > gpGlobals->curtime ) - return; - - ShowHostile(); - - // Don't burst attack again for a couple seconds - m_flNextBurstTime = gpGlobals->curtime + 2.0; - m_flBurstDuration = gpGlobals->curtime + 1.0; - - // Save off where we were going towards and for how long - m_vecBurstDirection = vecDirection; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Manhack::StopBurst( bool bInterruptSchedule /*= false*/ ) -{ - if ( m_flBurstDuration < gpGlobals->curtime ) - return; - - ShowHostile( false ); - - // Stop our burst timers - m_flNextBurstTime = gpGlobals->curtime + 2.0f; //FIXME: Skill level based - m_flBurstDuration = gpGlobals->curtime - 0.1f; - - if ( bInterruptSchedule ) - { - // We need to rethink our current schedule - ClearSchedule( "Stopping burst" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Manhack::SetEyeState( int state ) -{ - // Make sure we're active - StartEye(); - - switch( state ) - { - case MANHACK_EYE_STATE_STUNNED: - { - if ( m_pEyeGlow ) - { - //Toggle our state - m_pEyeGlow->SetColor( 255, 128, 0 ); - m_pEyeGlow->SetScale( 0.15f, 0.1f ); - m_pEyeGlow->SetBrightness( 164, 0.1f ); - m_pEyeGlow->m_nRenderFX = kRenderFxStrobeFast; - } - - if ( m_pLightGlow ) - { - m_pLightGlow->SetColor( 255, 128, 0 ); - m_pLightGlow->SetScale( 0.15f, 0.1f ); - m_pLightGlow->SetBrightness( 164, 0.1f ); - m_pLightGlow->m_nRenderFX = kRenderFxStrobeFast; - } - - EmitSound("NPC_Manhack.Stunned"); - - break; - } - - case MANHACK_EYE_STATE_CHARGE: - { - if ( m_pEyeGlow ) - { - //Toggle our state - if( m_bHackedByAlyx ) - { - m_pEyeGlow->SetColor( 0, 255, 0 ); - } - else - { - m_pEyeGlow->SetColor( 255, 0, 0 ); - } - - m_pEyeGlow->SetScale( 0.25f, 0.5f ); - m_pEyeGlow->SetBrightness( 164, 0.1f ); - m_pEyeGlow->m_nRenderFX = kRenderFxNone; - } - - if ( m_pLightGlow ) - { - if( m_bHackedByAlyx ) - { - m_pLightGlow->SetColor( 0, 255, 0 ); - } - else - { - m_pLightGlow->SetColor( 255, 0, 0 ); - } - - m_pLightGlow->SetScale( 0.25f, 0.5f ); - m_pLightGlow->SetBrightness( 164, 0.1f ); - m_pLightGlow->m_nRenderFX = kRenderFxNone; - } - - break; - } - - default: - if ( m_pEyeGlow ) - m_pEyeGlow->m_nRenderFX = kRenderFxNone; - break; - } -} - - -unsigned int CNPC_Manhack::PhysicsSolidMaskForEntity( void ) const -{ - unsigned int mask = BaseClass::PhysicsSolidMaskForEntity(); - if ( m_bIgnoreClipbrushes ) - { - mask &= ~CONTENTS_MONSTERCLIP; - } - return mask; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Manhack::CreateVPhysics( void ) -{ - if ( HasSpawnFlags( SF_MANHACK_CARRIED ) ) - return false; - - return BaseClass::CreateVPhysics(); -} - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- -AI_BEGIN_CUSTOM_NPC( npc_manhack, CNPC_Manhack ) - - DECLARE_TASK( TASK_MANHACK_HOVER ); - DECLARE_TASK( TASK_MANHACK_UNPACK ); - DECLARE_TASK( TASK_MANHACK_FIND_SQUAD_CENTER ); - DECLARE_TASK( TASK_MANHACK_FIND_SQUAD_MEMBER ); - DECLARE_TASK( TASK_MANHACK_MOVEAT_SAVEPOSITION ); - - DECLARE_CONDITION( COND_MANHACK_START_ATTACK ); - - DECLARE_ACTIVITY( ACT_MANHACK_UNPACK ); - -//========================================================= -// > SCHED_MANHACK_ATTACK_HOVER -//========================================================= -DEFINE_SCHEDULE -( - SCHED_MANHACK_ATTACK_HOVER, - - " Tasks" - " TASK_SET_ACTIVITY ACTIVITY:ACT_FLY" - " TASK_MANHACK_HOVER 0" - " " - " Interrupts" - " COND_TOO_FAR_TO_ATTACK" - " COND_TOO_CLOSE_TO_ATTACK" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_ENEMY_OCCLUDED" -); - - -//========================================================= -// > SCHED_MANHACK_ATTACK_HOVER -//========================================================= -DEFINE_SCHEDULE -( - SCHED_MANHACK_DEPLOY, - - " Tasks" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_MANHACK_UNPACK" - " TASK_SET_ACTIVITY ACTIVITY:ACT_FLY" - " " -// " Interrupts" -); - -//========================================================= -// > SCHED_MANHACK_REGROUP -//========================================================= -DEFINE_SCHEDULE -( - SCHED_MANHACK_REGROUP, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_TOLERANCE_DISTANCE 24" - " TASK_STORE_ENEMY_POSITION_IN_SAVEPOSITION 0" - " TASK_FIND_BACKAWAY_FROM_SAVEPOSITION 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " " - " Interrupts" - " COND_MANHACK_START_ATTACK" - " COND_NEW_ENEMY" - " COND_CAN_MELEE_ATTACK1" -); - - - -//========================================================= -// > SCHED_MANHACK_SWARN -//========================================================= -DEFINE_SCHEDULE -( - SCHED_MANHACK_SWARM_IDLE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_MANHACK_SWARM_FAILURE" - " TASK_MANHACK_FIND_SQUAD_CENTER 0" - " TASK_MANHACK_MOVEAT_SAVEPOSITION 5" - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_ENEMY" - " COND_SEE_FEAR" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_SMELL" - " COND_PROVOKED" - " COND_GIVE_WAY" - " COND_HEAR_PLAYER" - " COND_HEAR_DANGER" - " COND_HEAR_COMBAT" - " COND_HEAR_BULLET_IMPACT" -); - - -DEFINE_SCHEDULE -( - SCHED_MANHACK_SWARM, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_MANHACK_SWARM_FAILURE" - " TASK_MANHACK_FIND_SQUAD_CENTER 0" - " TASK_MANHACK_MOVEAT_SAVEPOSITION 1" - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_CAN_MELEE_ATTACK1" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" -); - -DEFINE_SCHEDULE -( - SCHED_MANHACK_SWARM_FAILURE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_WAIT 2" - " TASK_WAIT_RANDOM 2" - " TASK_MANHACK_FIND_SQUAD_MEMBER 0" - " TASK_GET_PATH_TO_SAVEPOSITION 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " " - " Interrupts" - " COND_SEE_ENEMY" - " COND_NEW_ENEMY" -); - -AI_END_CUSTOM_NPC() diff --git a/game/server/hl2/npc_manhack.h b/game/server/hl2/npc_manhack.h deleted file mode 100644 index 1b7238abb..000000000 --- a/game/server/hl2/npc_manhack.h +++ /dev/null @@ -1,280 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef NPC_MANHACK_H -#define NPC_MANHACK_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_basenpc_physicsflyer.h" -#include "Sprite.h" -#include "SpriteTrail.h" -#include "player_pickup.h" - -// Start with the engine off and folded up. -#define SF_MANHACK_PACKED_UP (1 << 16) -#define SF_MANHACK_NO_DAMAGE_EFFECTS (1 << 17) -#define SF_MANHACK_USE_AIR_NODES (1 << 18) -#define SF_MANHACK_CARRIED (1 << 19) // Being carried by a metrocop -#define SF_MANHACK_NO_DANGER_SOUNDS (1 << 20) - -enum -{ - MANHACK_EYE_STATE_IDLE, - MANHACK_EYE_STATE_CHASE, - MANHACK_EYE_STATE_CHARGE, - MANHACK_EYE_STATE_STUNNED, -}; - -//----------------------------------------------------------------------------- -// Attachment points. -//----------------------------------------------------------------------------- -#define MANHACK_GIB_HEALTH 30 -#define MANHACK_INACTIVE_HEALTH 25 -#define MANHACK_MAX_SPEED 500 -#define MANHACK_BURST_SPEED 650 -#define MANHACK_NPC_BURST_SPEED 800 - -//----------------------------------------------------------------------------- -// Movement parameters. -//----------------------------------------------------------------------------- -#define MANHACK_WAYPOINT_DISTANCE 25 // Distance from waypoint that counts as arrival. - -class CSprite; -class SmokeTrail; -class CSoundPatch; - -//----------------------------------------------------------------------------- -// Manhack -//----------------------------------------------------------------------------- -class CNPC_Manhack : public CNPCBaseInteractive, public CDefaultPlayerPickupVPhysics -{ -DECLARE_CLASS( CNPC_Manhack, CNPCBaseInteractive ); -DECLARE_SERVERCLASS(); - -public: - CNPC_Manhack(); - ~CNPC_Manhack(); - - Class_T Classify(void); - - bool CorpseGib( const CTakeDamageInfo &info ); - void Event_Dying(void); - void Event_Killed( const CTakeDamageInfo &info ); - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - int OnTakeDamage_Dying( const CTakeDamageInfo &info ); - void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr); - void TranslateNavGoal( CBaseEntity *pEnemy, Vector &chasePosition ); - float GetDefaultNavGoalTolerance(); - - void UpdateOnRemove( void ); - void KillSprites( float flDelay ); - - void OnStateChange( NPC_STATE OldState, NPC_STATE NewState ); - - virtual bool CreateVPhysics( void ); - - virtual void DeathSound( const CTakeDamageInfo &info ); - virtual bool ShouldGib( const CTakeDamageInfo &info ); - - Activity NPC_TranslateActivity( Activity baseAct ); - virtual int TranslateSchedule( int scheduleType ); - int MeleeAttack1Conditions ( float flDot, float flDist ); - void HandleAnimEvent( animevent_t *pEvent ); - - bool OverrideMove(float flInterval); - void MoveToTarget(float flInterval, const Vector &MoveTarget); - void MoveExecute_Alive(float flInterval); - void MoveExecute_Dead(float flInterval); - int MoveCollisionMask(void); - - void TurnHeadRandomly( float flInterval ); - - void CrashTouch( CBaseEntity *pOther ); - - void StartEngine( bool fStartSound ); - - virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true ) { return WorldSpaceCenter(); } - - virtual float GetHeadTurnRate( void ) { return 45.0f; } // Degrees per second - - void CheckCollisions(float flInterval); - virtual void GatherEnemyConditions( CBaseEntity *pEnemy ); - void PlayFlySound(void); - virtual void StopLoopingSounds(void); - - void Precache(void); - void RunTask( const Task_t *pTask ); - void Spawn(void); - void Activate(); - void StartTask( const Task_t *pTask ); - - void BladesInit(); - void SoundInit( void ); - void StartEye( void ); - - bool HandleInteraction(int interactionType, void* data, CBaseCombatCharacter* sourceEnt); - - void PostNPCInit( void ); - - void GatherConditions(); - void PrescheduleThink( void ); - - void SpinBlades(float flInterval); - - void Slice( CBaseEntity *pHitEntity, float flInterval, trace_t &tr ); - void Bump( CBaseEntity *pHitEntity, float flInterval, trace_t &tr ); - void Splash( const Vector &vecSplashPos ); - - float ManhackMaxSpeed( void ); - virtual void VPhysicsShadowCollision( int index, gamevcollisionevent_t *pEvent ); - void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); - void HitPhysicsObject( CBaseEntity *pOther ); - virtual void ClampMotorForces( Vector &linear, AngularImpulse &angular ); - unsigned int PhysicsSolidMaskForEntity( void ) const; - - // Create smoke trail! - void CreateSmokeTrail(); - void DestroySmokeTrail(); - - void Ignite( float flFlameLifetime, bool bNPCOnly, float flSize, bool bCalledByLevelDesigner ) { return; } - - void InputDisableSwarm( inputdata_t &inputdata ); - void InputUnpack( inputdata_t &inputdata ); - - // CDefaultPlayerPickupVPhysics - virtual void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ); - virtual void OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ); - - CBasePlayer *HasPhysicsAttacker( float dt ); - - float GetMaxEnginePower(); - - // INPCInteractive Functions - virtual bool CanInteractWith( CAI_BaseNPC *pUser ) { return false; } // Disabled for now (sjb) - virtual bool HasBeenInteractedWith() { return m_bHackedByAlyx; } - virtual void NotifyInteraction( CAI_BaseNPC *pUser ) - { - // Turn the sprites off and on again so their colors will change. - KillSprites(0.0f); - m_bHackedByAlyx = true; - StartEye(); - } - - virtual void InputPowerdown( inputdata_t &inputdata ) - { - m_iHealth = 0; - } - - - DEFINE_CUSTOM_AI; - - DECLARE_DATADESC(); - -private: - - bool IsInEffectiveTargetZone( CBaseEntity *pTarget ); - void MaintainGroundHeight( void ); - - void StartBurst( const Vector &vecDirection ); - void StopBurst( bool bInterruptSchedule = false ); - - void UpdatePanels( void ); - void SetEyeState( int state ); - - void ShowHostile( bool hostile = true ); - - bool IsFlyingActivity( Activity baseAct ); - - // Computes the slice bounce velocity - void ComputeSliceBounceVelocity( CBaseEntity *pHitEntity, trace_t &tr ); - - // Take damage from being thrown by a physcannon - void TakeDamageFromPhyscannon( CBasePlayer *pPlayer ); - - // Take damage from a vehicle: - void TakeDamageFromVehicle( int index, gamevcollisionevent_t *pEvent ); - - // Take damage from physics impacts - void TakeDamageFromPhysicsImpact( int index, gamevcollisionevent_t *pEvent ); - - // Are we being held by the physcannon? - bool IsHeldByPhyscannon( ); - - void StartLoitering( const Vector &vecLoiterPosition ); - void StopLoitering() { m_vecLoiterPosition = vec3_invalid; m_fTimeNextLoiterPulse = gpGlobals->curtime; } - bool IsLoitering() { return m_vecLoiterPosition != vec3_invalid; } - void Loiter(); - - // - // Movement variables. - // - - Vector m_vForceVelocity; // Someone forced me to move - - Vector m_vTargetBanking; - - Vector m_vForceMoveTarget; // Will fly here - float m_fForceMoveTime; // If time is less than this - Vector m_vSwarmMoveTarget; // Will fly here - float m_fSwarmMoveTime; // If time is less than this - float m_fEnginePowerScale; // scale all thrust by this amount (usually 1.0!) - - float m_flNextEngineSoundTime; - float m_flEngineStallTime; - - float m_flNextBurstTime; - float m_flBurstDuration; - Vector m_vecBurstDirection; - - float m_flWaterSuspendTime; - int m_nLastSpinSound; - - // physics influence - CHandle m_hPhysicsAttacker; - float m_flLastPhysicsInfluenceTime; - - // Death - float m_fSparkTime; - float m_fSmokeTime; - - bool m_bDirtyPitch; // indicates whether we want the sound pitch updated.(sjb) - bool m_bShowingHostile; - - bool m_bBladesActive; - bool m_bIgnoreClipbrushes; - - float m_flBladeSpeed; - - CSprite *m_pEyeGlow; - CSprite *m_pLightGlow; - - CHandle m_hSmokeTrail; - - int m_iPanel1; - int m_iPanel2; - int m_iPanel3; - int m_iPanel4; - - int m_nLastWaterLevel; - bool m_bDoSwarmBehavior; - bool m_bGib; - - bool m_bHeld; - bool m_bHackedByAlyx; - Vector m_vecLoiterPosition; - float m_fTimeNextLoiterPulse; - - float m_flBumpSuppressTime; - - CNetworkVar( int, m_nEnginePitch1 ); - CNetworkVar( int, m_nEnginePitch2 ); - CNetworkVar( float, m_flEnginePitch1Time ); - CNetworkVar( float, m_flEnginePitch2Time ); -}; - -#endif //NPC_MANHACK_H diff --git a/game/server/hl2/npc_metropolice.cpp b/game/server/hl2/npc_metropolice.cpp deleted file mode 100644 index 9b55bba81..000000000 --- a/game/server/hl2/npc_metropolice.cpp +++ /dev/null @@ -1,5855 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "soundent.h" -#include "npcevent.h" -#include "globalstate.h" -#include "ai_squad.h" -#include "ai_tacticalservices.h" -#include "npc_manhack.h" -#include "npc_metropolice.h" -#include "weapon_stunstick.h" -#include "basegrenade_shared.h" -#include "ai_route.h" -#include "hl2_player.h" -#include "iservervehicle.h" -#include "items.h" -#include "hl2_gamerules.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//#define SF_METROPOLICE_ 0x00010000 -#define SF_METROPOLICE_SIMPLE_VERSION 0x00020000 -#define SF_METROPOLICE_ALWAYS_STITCH 0x00080000 -#define SF_METROPOLICE_NOCHATTER 0x00100000 -#define SF_METROPOLICE_ARREST_ENEMY 0x00200000 -#define SF_METROPOLICE_NO_FAR_STITCH 0x00400000 -#define SF_METROPOLICE_NO_MANHACK_DEPLOY 0x00800000 -#define SF_METROPOLICE_ALLOWED_TO_RESPOND 0x01000000 -#define SF_METROPOLICE_MID_RANGE_ATTACK 0x02000000 - -#define METROPOLICE_MID_RANGE_ATTACK_RANGE 3500.0f - -#define METROPOLICE_SQUAD_STITCH_MIN_INTERVAL 1.0f -#define METROPOLICE_SQUAD_STITCH_MAX_INTERVAL 1.2f - -#define AIM_ALONG_SIDE_LINE_OF_DEATH_DISTANCE 300.0f -#define AIM_ALONG_SIDE_STEER_DISTANCE 200.0f -#define AIM_ALONG_SIDE_DEFAULT_STITCH_LENGTH 750.0f -#define AIM_ALONG_SIDE_LINE_OF_DEATH_LEAD_TIME 0.0f -#define AIM_ALONG_SIDE_LINE_INITIAL_DRAW_FRACTION 0.2f - -#define AIM_BEHIND_DEFAULT_STITCH_LENGTH 1000.0f -#define AIM_BEHIND_MINIMUM_DISTANCE 650.0f -#define AIM_BEHIND_STEER_DISTANCE 150.0f - -#define RECENT_DAMAGE_INTERVAL 3.0f -#define RECENT_DAMAGE_THRESHOLD 0.2f - -#define VEHICLE_PREDICT_ACCELERATION 333.0f -#define VEHICLE_PREDICT_MAX_SPEED 600.0f - -#define METROPOLICE_MAX_WARNINGS 3 - -#define METROPOLICE_BODYGROUP_MANHACK 1 - -enum -{ - // NOTE: Exact #s are important, since they are referred to by number in schedules below - - METROPOLICE_SENTENCE_FREEZE = 0, - METROPOLICE_SENTENCE_HES_OVER_HERE = 1, - METROPOLICE_SENTENCE_HES_RUNNING = 2, - METROPOLICE_SENTENCE_TAKE_HIM_DOWN = 3, - METROPOLICE_SENTENCE_ARREST_IN_POSITION = 4, - METROPOLICE_SENTENCE_DEPLOY_MANHACK = 5, - METROPOLICE_SENTENCE_MOVE_INTO_POSITION = 6, - METROPOLICE_SENTENCE_HEARD_SOMETHING = 7, -}; - -enum -{ - METROPOLICE_ANNOUNCE_ATTACK_PRIMARY = 1, - METROPOLICE_ANNOUNCE_ATTACK_SECONDARY, - METROPOLICE_ANNOUNCE_ATTACK_HARASS, -}; - -enum -{ - METROPOLICE_CHATTER_WAIT_FOR_RESPONSE = 0, - METROPOLICE_CHATTER_ASK_QUESTION = 1, - METROPOLICE_CHATTER_RESPONSE = 2, - - METROPOLICE_CHATTER_RESPONSE_TYPE_COUNT = 2, -}; - - -enum SpeechMemory_t -{ - bits_MEMORY_PAIN_LIGHT_SOUND = bits_MEMORY_CUSTOM1, - bits_MEMORY_PAIN_HEAVY_SOUND = bits_MEMORY_CUSTOM2, - bits_MEMORY_PLAYER_HURT = bits_MEMORY_CUSTOM3, - bits_MEMORY_PLAYER_HARASSED = bits_MEMORY_CUSTOM4, -}; - -//Metrocop -int g_interactionMetrocopStartedStitch = 0; -int g_interactionMetrocopIdleChatter = 0; -int g_interactionMetrocopClearSentenceQueues = 0; - -extern int g_interactionHitByPlayerThrownPhysObj; - -ConVar sk_metropolice_stitch_reaction( "sk_metropolice_stitch_reaction","1.0"); -ConVar sk_metropolice_stitch_tight_hitcount( "sk_metropolice_stitch_tight_hitcount","2"); -ConVar sk_metropolice_stitch_at_hitcount( "sk_metropolice_stitch_at_hitcount","1"); -ConVar sk_metropolice_stitch_behind_hitcount( "sk_metropolice_stitch_behind_hitcount","3"); -ConVar sk_metropolice_stitch_along_hitcount( "sk_metropolice_stitch_along_hitcount","2"); - - -ConVar sk_metropolice_health( "sk_metropolice_health","0"); -ConVar sk_metropolice_simple_health( "sk_metropolice_simple_health","26"); -ConVar sk_metropolice_stitch_distance( "sk_metropolice_stitch_distance","1000"); - -ConVar metropolice_chase_use_follow( "metropolice_chase_use_follow", "0" ); -ConVar metropolice_move_and_melee("metropolice_move_and_melee", "1" ); -ConVar metropolice_charge("metropolice_charge", "1" ); - -// How many clips of pistol ammo a metropolice carries. -#define METROPOLICE_NUM_CLIPS 5 -#define METROPOLICE_BURST_RELOAD_COUNT 20 - -int AE_METROPOLICE_BATON_ON; -int AE_METROPOLICE_BATON_OFF; -int AE_METROPOLICE_SHOVE; -int AE_METROPOLICE_START_DEPLOY; -int AE_METROPOLICE_DRAW_PISTOL; // was 50 -int AE_METROPOLICE_DEPLOY_MANHACK; // was 51 - -// ----------------------------------------------- -// > Squad slots -// ----------------------------------------------- -enum SquadSlot_T -{ - SQUAD_SLOT_POLICE_CHARGE_ENEMY = LAST_SHARED_SQUADSLOT, - SQUAD_SLOT_POLICE_HARASS, // Yell at the player with a megaphone, etc. - SQUAD_SLOT_POLICE_DEPLOY_MANHACK, - SQUAD_SLOT_POLICE_ADVANCE, - SQUAD_SLOT_POLICE_ATTACK_OCCLUDER1, - SQUAD_SLOT_POLICE_ATTACK_OCCLUDER2, - SQUAD_SLOT_POLICE_COVERING_FIRE1, - SQUAD_SLOT_POLICE_COVERING_FIRE2, - SQUAD_SLOT_POLICE_ARREST_ENEMY, -}; - -//========================================================= -// Metro Police Activities -//========================================================= -int ACT_METROPOLICE_DRAW_PISTOL; -int ACT_METROPOLICE_DEPLOY_MANHACK; -int ACT_METROPOLICE_FLINCH_BEHIND; - -int ACT_WALK_BATON; -int ACT_IDLE_ANGRY_BATON; -int ACT_PUSH_PLAYER; -int ACT_MELEE_ATTACK_THRUST; -int ACT_ACTIVATE_BATON; -int ACT_DEACTIVATE_BATON; - -LINK_ENTITY_TO_CLASS( npc_metropolice, CNPC_MetroPolice ); - -BEGIN_DATADESC( CNPC_MetroPolice ) - - DEFINE_EMBEDDED( m_BatonSwingTimer ), - DEFINE_EMBEDDED( m_NextChargeTimer ), - DEFINE_FIELD( m_flBatonDebounceTime, FIELD_FLOAT ), - DEFINE_FIELD( m_bShouldActivateBaton, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iPistolClips, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_fWeaponDrawn, FIELD_BOOLEAN, "weapondrawn" ), - DEFINE_FIELD( m_LastShootSlot, FIELD_INTEGER ), - DEFINE_EMBEDDED( m_TimeYieldShootSlot ), - DEFINE_EMBEDDED( m_Sentences ), - DEFINE_FIELD( m_bPlayerIsNear, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_vecBurstTargetPos, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecBurstDelta, FIELD_VECTOR ), - DEFINE_FIELD( m_nBurstHits, FIELD_INTEGER ), - DEFINE_FIELD( m_nMaxBurstHits, FIELD_INTEGER ), - DEFINE_FIELD( m_flBurstPredictTime, FIELD_TIME ), - DEFINE_FIELD( m_nBurstReloadCount, FIELD_INTEGER ), - DEFINE_FIELD( m_vecBurstLineOfDeathDelta, FIELD_VECTOR ), - DEFINE_FIELD( m_vecBurstLineOfDeathOrigin, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_flBurstSteerDistance, FIELD_FLOAT ), - DEFINE_FIELD( m_nBurstMode, FIELD_INTEGER ), - DEFINE_FIELD( m_nBurstSteerMode, FIELD_INTEGER ), - DEFINE_FIELD( m_vecBurstPredictedVelocityDir, FIELD_VECTOR ), - DEFINE_FIELD( m_vecBurstPredictedSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_flValidStitchTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextLedgeCheckTime, FIELD_TIME ), - DEFINE_FIELD( m_flTaskCompletionTime, FIELD_TIME ), - DEFINE_FIELD( m_flLastPhysicsFlinchTime, FIELD_TIME ), - DEFINE_FIELD( m_flLastDamageFlinchTime, FIELD_TIME ), - - DEFINE_FIELD( m_hManhack, FIELD_EHANDLE ), - DEFINE_FIELD( m_hBlockingProp, FIELD_EHANDLE ), - - DEFINE_FIELD( m_nRecentDamage, FIELD_INTEGER ), - DEFINE_FIELD( m_flRecentDamageTime, FIELD_TIME ), - - DEFINE_FIELD( m_flNextPainSoundTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextLostSoundTime, FIELD_TIME ), - DEFINE_FIELD( m_nIdleChatterType, FIELD_INTEGER ), - - DEFINE_FIELD( m_bSimpleCops, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flLastHitYaw, FIELD_FLOAT ), - - DEFINE_FIELD( m_bPlayerTooClose, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bKeepFacingPlayer, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flChasePlayerTime, FIELD_TIME ), - DEFINE_FIELD( m_vecPreChaseOrigin, FIELD_VECTOR ), - DEFINE_FIELD( m_flPreChaseYaw, FIELD_FLOAT ), - DEFINE_FIELD( m_nNumWarnings, FIELD_INTEGER ), - DEFINE_FIELD( m_iNumPlayerHits, FIELD_INTEGER ), - - // m_ActBusyBehavior (auto saved by AI) - // m_StandoffBehavior (auto saved by AI) - // m_AssaultBehavior (auto saved by AI) - // m_FuncTankBehavior (auto saved by AI) - // m_RappelBehavior (auto saved by AI) - // m_PolicingBehavior (auto saved by AI) - // m_FollowBehavior (auto saved by AI) - - DEFINE_KEYFIELD( m_iManhacks, FIELD_INTEGER, "manhacks" ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableManhackToss", InputEnableManhackToss ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetPoliceGoal", InputSetPoliceGoal ), - DEFINE_INPUTFUNC( FIELD_VOID, "ActivateBaton", InputActivateBaton ), - - DEFINE_USEFUNC( PrecriminalUse ), - - DEFINE_OUTPUT( m_OnStunnedPlayer, "OnStunnedPlayer" ), - DEFINE_OUTPUT( m_OnCupCopped, "OnCupCopped" ), - -END_DATADESC() - -//------------------------------------------------------------------------------ - -float CNPC_MetroPolice::gm_flTimeLastSpokePeek; - -//------------------------------------------------------------------------------ -// Purpose -//------------------------------------------------------------------------------ -CBaseEntity *CNPC_MetroPolice::CheckTraceHullAttack( float flDist, const Vector &mins, const Vector &maxs, int iDamage, int iDmgType, float forceScale, bool bDamageAnyNPC ) -{ - // If only a length is given assume we want to trace in our facing direction - Vector forward; - AngleVectors( GetAbsAngles(), &forward ); - Vector vStart = GetAbsOrigin(); - - // The ideal place to start the trace is in the center of the attacker's bounding box. - // however, we need to make sure there's enough clearance. Some of the smaller monsters aren't - // as big as the hull we try to trace with. (SJB) - float flVerticalOffset = WorldAlignSize().z * 0.5; - - if( flVerticalOffset < maxs.z ) - { - // There isn't enough room to trace this hull, it's going to drag the ground. - // so make the vertical offset just enough to clear the ground. - flVerticalOffset = maxs.z + 1.0; - } - - vStart.z += flVerticalOffset; - Vector vEnd = vStart + (forward * flDist ); - return CheckTraceHullAttack( vStart, vEnd, mins, maxs, iDamage, iDmgType, forceScale, bDamageAnyNPC ); -} - -//------------------------------------------------------------------------------ -// Melee filter for police -//------------------------------------------------------------------------------ -class CTraceFilterMetroPolice : public CTraceFilterEntitiesOnly -{ -public: - // It does have a base, but we'll never network anything below here.. - DECLARE_CLASS_NOBASE( CTraceFilterMetroPolice ); - - CTraceFilterMetroPolice( const IHandleEntity *passentity, int collisionGroup, CTakeDamageInfo *dmgInfo, float flForceScale, bool bDamageAnyNPC ) - : m_pPassEnt(passentity), m_collisionGroup(collisionGroup), m_dmgInfo(dmgInfo), m_pHit(NULL), m_flForceScale(flForceScale), m_bDamageAnyNPC(bDamageAnyNPC) - { - } - - virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) - { - if ( !StandardFilterRules( pHandleEntity, contentsMask ) ) - return false; - - if ( !PassServerEntityFilter( pHandleEntity, m_pPassEnt ) ) - return false; - - // Don't test if the game code tells us we should ignore this collision... - CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); - - if ( pEntity ) - { - if ( !pEntity->ShouldCollide( m_collisionGroup, contentsMask ) ) - return false; - - if ( !g_pGameRules->ShouldCollide( m_collisionGroup, pEntity->GetCollisionGroup() ) ) - return false; - - if ( pEntity->m_takedamage == DAMAGE_NO ) - return false; - - // Translate the vehicle into its driver for damage - if ( pEntity->GetServerVehicle() != NULL ) - { - CBaseEntity *pDriver = pEntity->GetServerVehicle()->GetPassenger(); - - if ( pDriver != NULL ) - { - pEntity = pDriver; - } - } - - Vector attackDir = pEntity->WorldSpaceCenter() - m_dmgInfo->GetAttacker()->WorldSpaceCenter(); - VectorNormalize( attackDir ); - - CTakeDamageInfo info = (*m_dmgInfo); - CalculateMeleeDamageForce( &info, attackDir, info.GetAttacker()->WorldSpaceCenter(), m_flForceScale ); - - if( !(pEntity->GetFlags() & FL_ONGROUND) ) - { - // Don't hit airborne entities so hard. They fly farther since - // there's no friction with the ground. - info.ScaleDamageForce( 0.001 ); - } - - CBaseCombatCharacter *pBCC = info.GetAttacker()->MyCombatCharacterPointer(); - CBaseCombatCharacter *pVictimBCC = pEntity->MyCombatCharacterPointer(); - - // Only do these comparisons between NPCs - if ( pBCC && pVictimBCC ) - { - // Can only damage other NPCs that we hate - if ( m_bDamageAnyNPC || pBCC->IRelationType( pEntity ) == D_HT || pEntity->IsPlayer() ) - { - if ( info.GetDamage() ) - { - // If gordon's a criminal, do damage now - if ( !pEntity->IsPlayer() || GlobalEntity_GetState( "gordon_precriminal" ) == GLOBAL_OFF ) - { - if ( pEntity->IsPlayer() && ((CBasePlayer *)pEntity)->IsSuitEquipped() ) - { - info.ScaleDamage( .25 ); - info.ScaleDamageForce( .25 ); - } - - pEntity->TakeDamage( info ); - } - } - - m_pHit = pEntity; - return true; - } - } - else - { - // Make sure if the player is holding this, he drops it - Pickup_ForcePlayerToDropThisObject( pEntity ); - - // Otherwise just damage passive objects in our way - if ( info.GetDamage() ) - { - pEntity->TakeDamage( info ); - } - } - } - - return false; - } - -public: - const IHandleEntity *m_pPassEnt; - int m_collisionGroup; - CTakeDamageInfo *m_dmgInfo; - CBaseEntity *m_pHit; - float m_flForceScale; - bool m_bDamageAnyNPC; -}; - -//------------------------------------------------------------------------------ -// Purpose : start and end trace position, amount -// of damage to do, and damage type. Returns a pointer to -// the damaged entity in case the NPC wishes to do -// other stuff to the victim (punchangle, etc) -// -// Used for many contact-range melee attacks. Bites, claws, etc. -// Input : -// Output : -//------------------------------------------------------------------------------ -CBaseEntity *CNPC_MetroPolice::CheckTraceHullAttack( const Vector &vStart, const Vector &vEnd, const Vector &mins, const Vector &maxs, int iDamage, int iDmgType, float flForceScale, bool bDamageAnyNPC ) -{ - - CTakeDamageInfo dmgInfo( this, this, iDamage, DMG_SLASH ); - - CTraceFilterMetroPolice traceFilter( this, COLLISION_GROUP_NONE, &dmgInfo, flForceScale, bDamageAnyNPC ); - - Ray_t ray; - ray.Init( vStart, vEnd, mins, maxs ); - - trace_t tr; - enginetrace->TraceRay( ray, MASK_SHOT, &traceFilter, &tr ); - - CBaseEntity *pEntity = traceFilter.m_pHit; - - if ( pEntity == NULL ) - { - // See if perhaps I'm trying to claw/bash someone who is standing on my head. - Vector vecTopCenter; - Vector vecEnd; - Vector vecMins, vecMaxs; - - // Do a tracehull from the top center of my bounding box. - vecTopCenter = GetAbsOrigin(); - CollisionProp()->WorldSpaceAABB( &vecMins, &vecMaxs ); - vecTopCenter.z = vecMaxs.z + 1.0f; - vecEnd = vecTopCenter; - vecEnd.z += 2.0f; - - ray.Init( vecTopCenter, vEnd, mins, maxs ); - enginetrace->TraceRay( ray, MASK_SHOT_HULL, &traceFilter, &tr ); - - pEntity = traceFilter.m_pHit; - } - - return pEntity; -} - -//----------------------------------------------------------------------------- -// My buddies got killed! -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::NotifyDeadFriend( CBaseEntity* pFriend ) -{ - BaseClass::NotifyDeadFriend(pFriend); - - if ( pFriend == m_hManhack ) - { - m_Sentences.Speak( "METROPOLICE_MANHACK_KILLED", SENTENCE_PRIORITY_NORMAL, SENTENCE_CRITERIA_NORMAL ); - DevMsg("My manhack died!\n"); - m_hManhack = NULL; - return; - } - - // No notifications for squadmates' dead manhacks - if ( FClassnameIs( pFriend, "npc_manhack" ) ) - return; - - // Reset idle chatter, we may never get a response back - if ( m_nIdleChatterType == METROPOLICE_CHATTER_WAIT_FOR_RESPONSE ) - { - m_nIdleChatterType = METROPOLICE_CHATTER_ASK_QUESTION; - } - - if ( GetSquad()->NumMembers() < 2 ) - { - m_Sentences.Speak( "METROPOLICE_LAST_OF_SQUAD", SENTENCE_PRIORITY_MEDIUM, SENTENCE_CRITERIA_NORMAL ); - return; - } - - m_Sentences.Speak( "METROPOLICE_MAN_DOWN", SENTENCE_PRIORITY_MEDIUM ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CNPC_MetroPolice::CNPC_MetroPolice() -{ -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::OnScheduleChange() -{ - BaseClass::OnScheduleChange(); - - if ( GetEnemy() && HasCondition( COND_ENEMY_DEAD ) ) - { - AnnounceEnemyKill( GetEnemy() ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::PrescheduleThink( void ) -{ - BaseClass::PrescheduleThink(); - - // Speak any queued sentences - m_Sentences.UpdateSentenceQueue(); - - // Look at near players, always - m_bPlayerIsNear = false; - if ( PlayerIsCriminal() == false ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); - - if ( pPlayer && ( pPlayer->WorldSpaceCenter() - WorldSpaceCenter() ).LengthSqr() < (128*128) ) - { - m_bPlayerIsNear = true; - AddLookTarget( pPlayer, 0.75f, 5.0f ); - - if ( ( m_PolicingBehavior.IsEnabled() == false ) && ( m_nNumWarnings >= METROPOLICE_MAX_WARNINGS ) ) - { - m_flBatonDebounceTime = gpGlobals->curtime + random->RandomFloat( 2.5f, 4.0f ); - SetTarget( pPlayer ); - SetBatonState( true ); - } - } - else - { - if ( m_PolicingBehavior.IsEnabled() == false && gpGlobals->curtime > m_flBatonDebounceTime ) - { - SetBatonState( false ); - } - - m_bKeepFacingPlayer = false; - } - } - - if( IsOnFire() ) - { - SetCondition( COND_METROPOLICE_ON_FIRE ); - } - else - { - ClearCondition( COND_METROPOLICE_ON_FIRE ); - } - - if (gpGlobals->curtime > m_flRecentDamageTime + RECENT_DAMAGE_INTERVAL) - { - m_nRecentDamage = 0; - m_flRecentDamageTime = 0; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &move - -// flInterval - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_MetroPolice::OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval ) -{ - // Don't do this if we're scripted - if ( IsInAScript() ) - return BaseClass::OverrideMoveFacing( move, flInterval ); - - // ROBIN: Disabled at request of mapmakers for now - /* - // If we're moving during a police sequence, always face our target - if ( m_PolicingBehavior.IsEnabled() ) - { - CBaseEntity *pTarget = m_PolicingBehavior.GetGoalTarget(); - - if ( pTarget ) - { - AddFacingTarget( pTarget, pTarget->WorldSpaceCenter(), 1.0f, 0.2f ); - } - } - */ - - return BaseClass::OverrideMoveFacing( move, flInterval ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::Precache( void ) -{ - if ( HasSpawnFlags( SF_NPC_START_EFFICIENT ) ) - { - SetModelName( AllocPooledString("models/police_cheaple.mdl" ) ); - } - else - { - SetModelName( AllocPooledString("models/police.mdl") ); - } - - PrecacheModel( STRING( GetModelName() ) ); - - UTIL_PrecacheOther( "npc_manhack" ); - - PrecacheScriptSound( "NPC_Metropolice.Shove" ); - PrecacheScriptSound( "NPC_MetroPolice.WaterSpeech" ); - PrecacheScriptSound( "NPC_MetroPolice.HidingSpeech" ); - enginesound->PrecacheSentenceGroup( "METROPOLICE" ); - - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -// Create components -//----------------------------------------------------------------------------- -bool CNPC_MetroPolice::CreateComponents() -{ - if ( !BaseClass::CreateComponents() ) - return false; - - m_Sentences.Init( this, "NPC_Metropolice.SentenceParameters" ); - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::Spawn( void ) -{ - Precache(); - -#ifdef _XBOX - // Always fade the corpse - AddSpawnFlags( SF_NPC_FADE_CORPSE ); -#endif // _XBOX - - SetModel( STRING( GetModelName() ) ); - - SetHullType(HULL_HUMAN); - SetHullSizeNormal(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - SetBloodColor( BLOOD_COLOR_RED ); - m_nIdleChatterType = METROPOLICE_CHATTER_ASK_QUESTION; - m_bSimpleCops = HasSpawnFlags( SF_METROPOLICE_SIMPLE_VERSION ); - if ( HasSpawnFlags( SF_METROPOLICE_NOCHATTER ) ) - { - AddSpawnFlags( SF_NPC_GAG ); - } - - if (!m_bSimpleCops) - { - m_iHealth = sk_metropolice_health.GetFloat(); - } - else - { - m_iHealth = sk_metropolice_simple_health.GetFloat(); - } - - m_flFieldOfView = -0.2;// indicates the width of this NPC's forward view cone ( as a dotproduct result ) - m_NPCState = NPC_STATE_NONE; - if ( !HasSpawnFlags( SF_NPC_START_EFFICIENT ) ) - { - CapabilitiesAdd( bits_CAP_TURN_HEAD | bits_CAP_ANIMATEDFACE ); - CapabilitiesAdd( bits_CAP_AIM_GUN | bits_CAP_MOVE_SHOOT ); - } - CapabilitiesAdd( bits_CAP_MOVE_GROUND ); - CapabilitiesAdd( bits_CAP_USE_WEAPONS | bits_CAP_NO_HIT_SQUADMATES ); - CapabilitiesAdd( bits_CAP_SQUAD ); - CapabilitiesAdd( bits_CAP_DUCK | bits_CAP_DOORS_GROUP ); - CapabilitiesAdd( bits_CAP_USE_SHOT_REGULATOR ); - - m_nBurstHits = 0; - m_HackedGunPos = Vector ( 0, 0, 55 ); - - m_iPistolClips = METROPOLICE_NUM_CLIPS; - - NPCInit(); - - // NOTE: This must occur *after* init, since init sets default dist look - if ( HasSpawnFlags( SF_METROPOLICE_MID_RANGE_ATTACK ) ) - { - m_flDistTooFar = METROPOLICE_MID_RANGE_ATTACK_RANGE; - SetDistLook( METROPOLICE_MID_RANGE_ATTACK_RANGE ); - } - - m_hManhack = NULL; - - if ( GetActiveWeapon() ) - { - CBaseCombatWeapon *pWeapon; - - pWeapon = GetActiveWeapon(); - - if( !FClassnameIs( pWeapon, "weapon_pistol" ) ) - { - m_fWeaponDrawn = true; - } - - if( !m_fWeaponDrawn ) - { - GetActiveWeapon()->AddEffects( EF_NODRAW ); - } - } - - - m_TimeYieldShootSlot.Set( 2, 6 ); - - GetEnemies()->SetFreeKnowledgeDuration( 6.0 ); - - m_bShouldActivateBaton = false; - m_flValidStitchTime = -1.0f; - m_flNextLedgeCheckTime = -1.0f; - m_nBurstReloadCount = METROPOLICE_BURST_RELOAD_COUNT; - SetBurstMode( false ); - - // Clear out spawnflag if we're missing the smg1 - if( HasSpawnFlags( SF_METROPOLICE_ALWAYS_STITCH ) ) - { - if ( !Weapon_OwnsThisType( "weapon_smg1" ) ) - { - Warning( "Warning! Metrocop is trying to use the stitch behavior but he has no smg1!\n" ); - RemoveSpawnFlags( SF_METROPOLICE_ALWAYS_STITCH ); - } - } - - m_nNumWarnings = 0; - m_bPlayerTooClose = false; - m_bKeepFacingPlayer = false; - m_flChasePlayerTime = 0; - m_vecPreChaseOrigin = vec3_origin; - m_flPreChaseYaw = 0; - - SetUse( &CNPC_MetroPolice::PrecriminalUse ); - - // Start us with a visible manhack if we have one - if ( m_iManhacks ) - { - SetBodygroup( METROPOLICE_BODYGROUP_MANHACK, true ); - } -} - - -//----------------------------------------------------------------------------- -// Update weapon ranges -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::Weapon_Equip( CBaseCombatWeapon *pWeapon ) -{ - BaseClass::Weapon_Equip( pWeapon ); - - if ( HasSpawnFlags(SF_METROPOLICE_MID_RANGE_ATTACK) && GetActiveWeapon() ) - { - GetActiveWeapon()->m_fMaxRange1 = METROPOLICE_MID_RANGE_ATTACK_RANGE; - GetActiveWeapon()->m_fMaxRange2 = METROPOLICE_MID_RANGE_ATTACK_RANGE; - } -} - - -//----------------------------------------------------------------------------- -// FuncTankBehavior-related sentences -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::SpeakFuncTankSentence( int nSentenceType ) -{ - switch ( nSentenceType ) - { - case FUNCTANK_SENTENCE_MOVE_TO_MOUNT: - m_Sentences.Speak( "METROPOLICE_FT_APPROACH", SENTENCE_PRIORITY_MEDIUM ); - break; - - case FUNCTANK_SENTENCE_JUST_MOUNTED: - m_Sentences.Speak( "METROPOLICE_FT_MOUNT", SENTENCE_PRIORITY_HIGH ); - break; - - case FUNCTANK_SENTENCE_SCAN_FOR_ENEMIES: - m_Sentences.Speak( "METROPOLICE_FT_SCAN", SENTENCE_PRIORITY_NORMAL ); - break; - - case FUNCTANK_SENTENCE_DISMOUNTING: - m_Sentences.Speak( "METROPOLICE_FT_DISMOUNT", SENTENCE_PRIORITY_HIGH ); - break; - } -} - - -//----------------------------------------------------------------------------- -// Standoff Behavior-related sentences -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::SpeakStandoffSentence( int nSentenceType ) -{ - switch ( nSentenceType ) - { - case STANDOFF_SENTENCE_BEGIN_STANDOFF: - m_Sentences.Speak( "METROPOLICE_SO_BEGIN", SENTENCE_PRIORITY_HIGH, SENTENCE_CRITERIA_SQUAD_LEADER ); - break; - - case STANDOFF_SENTENCE_END_STANDOFF: - m_Sentences.Speak( "METROPOLICE_SO_END", SENTENCE_PRIORITY_HIGH, SENTENCE_CRITERIA_SQUAD_LEADER ); - break; - - case STANDOFF_SENTENCE_OUT_OF_AMMO: - AnnounceOutOfAmmo( ); - break; - - case STANDOFF_SENTENCE_FORCED_TAKE_COVER: - m_Sentences.Speak( "METROPOLICE_SO_FORCE_COVER" ); - break; - - case STANDOFF_SENTENCE_STAND_CHECK_TARGET: - if ( gm_flTimeLastSpokePeek != 0 && gpGlobals->curtime - gm_flTimeLastSpokePeek > 20 ) - { - m_Sentences.Speak( "METROPOLICE_SO_PEEK" ); - gm_flTimeLastSpokePeek = gpGlobals->curtime; - } - break; - } -} - -//----------------------------------------------------------------------------- -// Assault Behavior-related sentences -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::SpeakAssaultSentence( int nSentenceType ) -{ - switch ( nSentenceType ) - { - case ASSAULT_SENTENCE_HIT_RALLY_POINT: - m_Sentences.SpeakQueued( "METROPOLICE_AS_HIT_RALLY", SENTENCE_PRIORITY_NORMAL ); - break; - - case ASSAULT_SENTENCE_HIT_ASSAULT_POINT: - m_Sentences.SpeakQueued( "METROPOLICE_AS_HIT_ASSAULT", SENTENCE_PRIORITY_NORMAL ); - break; - - case ASSAULT_SENTENCE_SQUAD_ADVANCE_TO_RALLY: - if ( m_Sentences.Speak( "METROPOLICE_AS_ADV_RALLY", SENTENCE_PRIORITY_MEDIUM, SENTENCE_CRITERIA_SQUAD_LEADER ) >= 0 ) - { - GetSquad()->BroadcastInteraction( g_interactionMetrocopClearSentenceQueues, NULL ); - } - break; - - case ASSAULT_SENTENCE_SQUAD_ADVANCE_TO_ASSAULT: - if ( m_Sentences.Speak( "METROPOLICE_AS_ADV_ASSAULT", SENTENCE_PRIORITY_MEDIUM, SENTENCE_CRITERIA_SQUAD_LEADER ) >= 0 ) - { - GetSquad()->BroadcastInteraction( g_interactionMetrocopClearSentenceQueues, NULL ); - } - break; - - case ASSAULT_SENTENCE_COVER_NO_AMMO: - AnnounceOutOfAmmo( ); - break; - - case ASSAULT_SENTENCE_UNDER_ATTACK: - m_Sentences.Speak( "METROPOLICE_GO_ALERT" ); - break; - } -} - - -//----------------------------------------------------------------------------- -// Speaking while using TASK_SPEAK_SENTENCE -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::SpeakSentence( int nSentenceType ) -{ - if ( !PlayerIsCriminal() ) - return; - - if ( nSentenceType >= SENTENCE_BASE_BEHAVIOR_INDEX ) - { - if ( GetRunningBehavior() == &m_FuncTankBehavior ) - { - SpeakFuncTankSentence( nSentenceType ); - return; - } - - if ( GetRunningBehavior() == &m_StandoffBehavior ) - { - SpeakStandoffSentence( nSentenceType ); - return; - } - - if ( GetRunningBehavior() == &m_AssaultBehavior ) - { - SpeakAssaultSentence( nSentenceType ); - return; - } - } - - switch ( nSentenceType ) - { - case METROPOLICE_SENTENCE_FREEZE: - m_Sentences.Speak( "METROPOLICE_FREEZE", SENTENCE_PRIORITY_MEDIUM, SENTENCE_CRITERIA_NORMAL ); - break; - - case METROPOLICE_SENTENCE_HES_OVER_HERE: - m_Sentences.Speak( "METROPOLICE_OVER_HERE", SENTENCE_PRIORITY_MEDIUM, SENTENCE_CRITERIA_NORMAL ); - break; - - case METROPOLICE_SENTENCE_HES_RUNNING: - m_Sentences.Speak( "METROPOLICE_HES_RUNNING", SENTENCE_PRIORITY_HIGH, SENTENCE_CRITERIA_NORMAL ); - break; - - case METROPOLICE_SENTENCE_TAKE_HIM_DOWN: - m_Sentences.Speak( "METROPOLICE_TAKE_HIM_DOWN", SENTENCE_PRIORITY_HIGH, SENTENCE_CRITERIA_NORMAL ); - break; - - case METROPOLICE_SENTENCE_ARREST_IN_POSITION: - m_Sentences.Speak( "METROPOLICE_ARREST_IN_POS", SENTENCE_PRIORITY_MEDIUM, SENTENCE_CRITERIA_NORMAL ); - break; - - case METROPOLICE_SENTENCE_DEPLOY_MANHACK: - m_Sentences.Speak( "METROPOLICE_DEPLOY_MANHACK" ); - break; - - case METROPOLICE_SENTENCE_MOVE_INTO_POSITION: - { - CBaseEntity *pEntity = GetEnemy(); - - // NOTE: This is a good time to check to see if the player is hurt. - // Have the cops notice this and call out - if ( pEntity && !HasSpawnFlags( SF_METROPOLICE_ARREST_ENEMY ) ) - { - if ( pEntity->IsPlayer() && (pEntity->GetHealth() <= 20) ) - { - if ( !HasMemory(bits_MEMORY_PLAYER_HURT) ) - { - if ( m_Sentences.Speak( "METROPOLICE_PLAYERHIT", SENTENCE_PRIORITY_HIGH ) >= 0 ) - { - m_pSquad->SquadRemember(bits_MEMORY_PLAYER_HURT); - } - } - } - - if ( GetNavigator()->GetPath()->GetPathLength() > 20 * 12.0f ) - { - m_Sentences.Speak( "METROPOLICE_FLANK" ); - } - } - } - break; - - case METROPOLICE_SENTENCE_HEARD_SOMETHING: - if ( ( GetState() == NPC_STATE_ALERT ) || ( GetState() == NPC_STATE_IDLE ) ) - { - m_Sentences.Speak( "METROPOLICE_HEARD_SOMETHING", SENTENCE_PRIORITY_MEDIUM ); - } - break; - } -} - - -//----------------------------------------------------------------------------- -// Speaking -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::AnnounceEnemyType( CBaseEntity *pEnemy ) -{ - if ( !pEnemy || !m_pSquad ) - return; - - // Don't announce enemies when the player isn't a criminal - if ( !PlayerIsCriminal() ) - return; - - // Don't announce enemies when I'm in arrest behavior - if ( HasSpawnFlags( SF_METROPOLICE_ARREST_ENEMY ) ) - return; - - if ( m_pSquad->IsLeader( this ) || ( m_pSquad->GetLeader() && m_pSquad->GetLeader()->GetEnemy() != GetEnemy() ) ) - { - // First contact, and I'm the squad leader. - const char *pSentenceName = "METROPOLICE_MONST"; - switch ( pEnemy->Classify() ) - { - case CLASS_PLAYER: - { - CBasePlayer *pPlayer = assert_cast( pEnemy ); - if ( pPlayer && pPlayer->IsInAVehicle() ) - { - pSentenceName = "METROPOLICE_MONST_PLAYER_VEHICLE"; - } - else - { - pSentenceName = "METROPOLICE_MONST_PLAYER"; - } - } - break; - - case CLASS_PLAYER_ALLY: - case CLASS_CITIZEN_REBEL: - case CLASS_CITIZEN_PASSIVE: - case CLASS_VORTIGAUNT: - pSentenceName = "METROPOLICE_MONST_CITIZENS"; - break; - - case CLASS_PLAYER_ALLY_VITAL: - pSentenceName = "METROPOLICE_MONST_CHARACTER"; - break; - - case CLASS_ANTLION: - pSentenceName = "METROPOLICE_MONST_BUGS"; - break; - - case CLASS_ZOMBIE: - pSentenceName = "METROPOLICE_MONST_ZOMBIES"; - break; - - case CLASS_HEADCRAB: - case CLASS_BARNACLE: - pSentenceName = "METROPOLICE_MONST_PARASITES"; - break; - - default: - break; - } - - m_Sentences.Speak( pSentenceName, SENTENCE_PRIORITY_HIGH ); - } - else - { - if ( m_pSquad->GetLeader() && FOkToMakeSound( SENTENCE_PRIORITY_MEDIUM ) ) - { - // squelch anything that isn't high priority so the leader can speak - JustMadeSound( SENTENCE_PRIORITY_MEDIUM ); - } - } - -} - - -//----------------------------------------------------------------------------- -// Speaking -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::AnnounceEnemyKill( CBaseEntity *pEnemy ) -{ - if ( !pEnemy ) - return; - - const char *pSentenceName = "METROPOLICE_KILL_MONST"; - switch ( pEnemy->Classify() ) - { - case CLASS_PLAYER: - pSentenceName = "METROPOLICE_KILL_PLAYER"; - break; - - // no sentences for these guys yet - case CLASS_PLAYER_ALLY: - case CLASS_CITIZEN_REBEL: - case CLASS_CITIZEN_PASSIVE: - case CLASS_VORTIGAUNT: - pSentenceName = "METROPOLICE_KILL_CITIZENS"; - break; - - case CLASS_PLAYER_ALLY_VITAL: - pSentenceName = "METROPOLICE_KILL_CHARACTER"; - break; - - case CLASS_ANTLION: - pSentenceName = "METROPOLICE_KILL_BUGS"; - break; - - case CLASS_ZOMBIE: - pSentenceName = "METROPOLICE_KILL_ZOMBIES"; - break; - - case CLASS_HEADCRAB: - case CLASS_BARNACLE: - pSentenceName = "METROPOLICE_KILL_PARASITES"; - break; - - default: - break; - } - - m_Sentences.Speak( pSentenceName, SENTENCE_PRIORITY_HIGH ); -} - - -//----------------------------------------------------------------------------- -// Announce out of ammo -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::AnnounceOutOfAmmo( ) -{ - if ( HasCondition( COND_NO_PRIMARY_AMMO ) ) - { - m_Sentences.Speak( "METROPOLICE_COVER_NO_AMMO" ); - } - else - { - m_Sentences.Speak( "METROPOLICE_COVER_LOW_AMMO" ); - } -} - -//----------------------------------------------------------------------------- -// We're taking cover from danger -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::AnnounceTakeCoverFromDanger( CSound *pSound ) -{ - CBaseEntity *pSoundOwner = pSound->m_hOwner; - if ( pSoundOwner ) - { - CBaseGrenade *pGrenade = dynamic_cast(pSoundOwner); - if ( pGrenade ) - { - if ( IRelationType( pGrenade->GetThrower() ) != D_LI ) - { - // special case call out for enemy grenades - m_Sentences.Speak( "METROPOLICE_DANGER_GREN", SENTENCE_PRIORITY_HIGH, SENTENCE_CRITERIA_NORMAL ); - } - return; - } - - if ( pSoundOwner->GetServerVehicle() ) - { - m_Sentences.Speak( "METROPOLICE_DANGER_VEHICLE", SENTENCE_PRIORITY_HIGH, SENTENCE_CRITERIA_NORMAL ); - return; - } - - if ( FClassnameIs( pSoundOwner, "npc_manhack" ) ) - { - if ( pSoundOwner->HasPhysicsAttacker( 1.0f ) ) - { - m_Sentences.Speak( "METROPOLICE_DANGER_MANHACK", SENTENCE_PRIORITY_HIGH, SENTENCE_CRITERIA_NORMAL ); - } - return; - } - } - - // I hear something dangerous, probably need to take cover. - // dangerous sound nearby!, call it out - const char *pSentenceName = "METROPOLICE_DANGER"; - m_Sentences.Speak( pSentenceName, SENTENCE_PRIORITY_HIGH, SENTENCE_CRITERIA_NORMAL ); -} - - - -//----------------------------------------------------------------------------- -// Are we currently firing a burst? -//----------------------------------------------------------------------------- -bool CNPC_MetroPolice::IsCurrentlyFiringBurst() const -{ - return (m_nBurstMode != BURST_NOT_ACTIVE); -} - - -//----------------------------------------------------------------------------- -// Is my enemy currently in an airboat? -//----------------------------------------------------------------------------- -bool CNPC_MetroPolice::IsEnemyInAnAirboat() const -{ - // Should this be a condition?? - if ( !GetEnemy() || !GetEnemy()->IsPlayer() ) - return false; - - CBaseEntity *pVehicle = static_cast( GetEnemy() )->GetVehicleEntity(); - if ( !pVehicle ) - return false; - - // NOTE: Could just return true if in a vehicle maybe - return FClassnameIs( pVehicle, "prop_vehicle_airboat" ); -} - - -//----------------------------------------------------------------------------- -// Returns the airboat -//----------------------------------------------------------------------------- -CBaseEntity *CNPC_MetroPolice::GetEnemyAirboat() const -{ - // Should this be a condition?? - if ( !GetEnemy() || !GetEnemy()->IsPlayer() ) - return false; - - return static_cast( GetEnemy() )->GetVehicleEntity(); -} - - -//----------------------------------------------------------------------------- -// Which entity are we actually trying to shoot at? -//----------------------------------------------------------------------------- -CBaseEntity *CNPC_MetroPolice::GetShootTarget() -{ - // Should this be a condition?? - CBaseEntity *pEnemy = GetEnemy(); - if ( !pEnemy || !pEnemy->IsPlayer() ) - return pEnemy; - - CBaseEntity *pVehicle = static_cast( pEnemy )->GetVehicleEntity(); - return pVehicle ? pVehicle : pEnemy; -} - - -//----------------------------------------------------------------------------- -// Set up the shot regulator based on the equipped weapon -//----------------------------------------------------------------------------- - -// Ranges across which to tune fire rates -const float MIN_PISTOL_MODIFY_DIST = 15 * 12; -const float MAX_PISTOL_MODIFY_DIST = 150 * 12; - -// Range for rest period minimums -const float MIN_MIN_PISTOL_REST_INTERVAL = 0.6; -const float MAX_MIN_PISTOL_REST_INTERVAL = 1.2; - -// Range for rest period maximums -const float MIN_MAX_PISTOL_REST_INTERVAL = 1.2; -const float MAX_MAX_PISTOL_REST_INTERVAL = 2.0; - -// Range for burst minimums -const int MIN_MIN_PISTOL_BURST = 2; -const int MAX_MIN_PISTOL_BURST = 4; - -// Range for burst maximums -const int MIN_MAX_PISTOL_BURST = 5; -const int MAX_MAX_PISTOL_BURST = 8; - -void CNPC_MetroPolice::OnUpdateShotRegulator( ) -{ - BaseClass::OnUpdateShotRegulator(); - - // FIXME: This code (except the burst interval) could be used for all weapon types - if( Weapon_OwnsThisType( "weapon_pistol" ) ) - { - if ( m_nBurstMode == BURST_NOT_ACTIVE ) - { - if ( GetEnemy() ) - { - float dist = WorldSpaceCenter().DistTo( GetEnemy()->WorldSpaceCenter() ); - - dist = clamp( dist, MIN_PISTOL_MODIFY_DIST, MAX_PISTOL_MODIFY_DIST ); - - float factor = (dist - MIN_PISTOL_MODIFY_DIST) / (MAX_PISTOL_MODIFY_DIST - MIN_PISTOL_MODIFY_DIST); - - int nMinBurst = (int)(MIN_MIN_PISTOL_BURST + ( MAX_MIN_PISTOL_BURST - MIN_MIN_PISTOL_BURST ) * (1.0 - factor)); - int nMaxBurst = (int)(MIN_MAX_PISTOL_BURST + ( MAX_MAX_PISTOL_BURST - MIN_MAX_PISTOL_BURST ) * (1.0 - factor)); - float flMinRestInterval = MIN_MIN_PISTOL_REST_INTERVAL + ( MAX_MIN_PISTOL_REST_INTERVAL - MIN_MIN_PISTOL_REST_INTERVAL ) * factor; - float flMaxRestInterval = MIN_MAX_PISTOL_REST_INTERVAL + ( MAX_MAX_PISTOL_REST_INTERVAL - MIN_MAX_PISTOL_REST_INTERVAL ) * factor; - - GetShotRegulator()->SetRestInterval( flMinRestInterval, flMaxRestInterval ); - GetShotRegulator()->SetBurstShotCountRange( nMinBurst, nMaxBurst ); - } - else - { - GetShotRegulator()->SetBurstShotCountRange(GetActiveWeapon()->GetMinBurst(), GetActiveWeapon()->GetMaxBurst() ); - GetShotRegulator()->SetRestInterval( 0.6, 1.4 ); - } - } - - // Add some noise into the pistol - GetShotRegulator()->SetBurstInterval( 0.2f, 0.5f ); - } -} - - -//----------------------------------------------------------------------------- -// Burst mode! -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::SetBurstMode( bool bEnable ) -{ - int nOldBurstMode = m_nBurstMode; - m_nBurstSteerMode = BURST_STEER_NONE; - m_flBurstPredictTime = gpGlobals->curtime - 1.0f; - if ( GetActiveWeapon() ) - { - m_nBurstMode = bEnable ? BURST_ACTIVE : BURST_NOT_ACTIVE; - if ( bEnable ) - { - m_nBurstHits = 0; - } - } - else - { - m_nBurstMode = BURST_NOT_ACTIVE; - } - - if ( m_nBurstMode != nOldBurstMode ) - { - OnUpdateShotRegulator(); - if ( m_nBurstMode == BURST_NOT_ACTIVE ) - { - // Check for inconsistency... - int nMinBurstCount, nMaxBurstCount; - GetShotRegulator()->GetBurstShotCountRange( &nMinBurstCount, &nMaxBurstCount ); - if ( GetShotRegulator()->GetBurstShotsRemaining() > nMaxBurstCount ) - { - GetShotRegulator()->SetBurstShotsRemaining( nMaxBurstCount ); - } - } - } -} - - -//----------------------------------------------------------------------------- -// Should we attempt to stitch? -//----------------------------------------------------------------------------- -bool CNPC_MetroPolice::ShouldAttemptToStitch() -{ - if ( IsEnemyInAnAirboat() ) - return true; - - if ( !GetShootTarget() ) - return false; - - if ( HasSpawnFlags( SF_METROPOLICE_ALWAYS_STITCH ) ) - { - // Don't stitch if the player is at the same level or higher - if ( GetEnemy()->GetAbsOrigin().z - GetAbsOrigin().z > -36 ) - return false; - - return true; - } - - return false; -} - - -//----------------------------------------------------------------------------- -// position to shoot at -//----------------------------------------------------------------------------- -Vector CNPC_MetroPolice::StitchAimTarget( const Vector &posSrc, bool bNoisy ) -{ - // This will make us aim a stitch at the feet of the player so we can see it - if ( !GetEnemy()->IsPlayer() ) - return GetShootTarget()->BodyTarget( posSrc, bNoisy ); - - if ( !IsEnemyInAnAirboat() ) - { - Vector vecBodyTarget; - if ( ( GetEnemy()->GetWaterLevel() == 0 ) && ( GetEnemy()->GetFlags() & FL_ONGROUND ) ) - { - GetEnemy()->CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 0.08f ), &vecBodyTarget ); - return vecBodyTarget; - } - - // Underwater? Just use the normal thing - if ( GetEnemy()->GetWaterLevel() == 3 ) - return GetShootTarget()->BodyTarget( posSrc, bNoisy ); - - // Trace down... - trace_t trace; - GetEnemy()->CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 1.0f ), &vecBodyTarget ); - float flHeight = GetEnemy()->WorldAlignSize().z; - UTIL_TraceLine( vecBodyTarget, vecBodyTarget + Vector( 0, 0, -flHeight -80 ), - (MASK_SOLID_BRUSHONLY | MASK_WATER), NULL, COLLISION_GROUP_NONE, &trace ); - return trace.endpos; - } - - // NOTE: HACK! Ths 0.08 is where the water level happens to be. - // We probably want to find the exact water level and use that as the z position. - Vector vecBodyTarget; - if ( !bNoisy ) - { - GetShootTarget()->CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 0.08f ), &vecBodyTarget ); - } - else - { - GetShootTarget()->CollisionProp()->RandomPointInBounds( Vector( 0.25f, 0.25f, 0.08f ), Vector( 0.75f, 0.75f, 0.08f ), &vecBodyTarget ); - } - - return vecBodyTarget; -} - - -//----------------------------------------------------------------------------- -// Burst mode! -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::AimBurstRandomly( int nMinCount, int nMaxCount, float flMinDelay, float flMaxDelay ) -{ - if ( !IsCurrentlyFiringBurst() ) - return; - - GetShotRegulator()->SetParameters( nMinCount, nMaxCount, flMinDelay, flMaxDelay ); - GetShotRegulator()->Reset( true ); - - int nShotCount = GetShotRegulator()->GetBurstShotsRemaining(); - - Vector vecDelta = StitchAimTarget( GetAbsOrigin(), true ) - Weapon_ShootPosition(); - VectorNormalize( vecDelta ); - - // Choose a random direction vector perpendicular to the delta position - Vector vecRight, vecUp; - VectorVectors( vecDelta, vecRight, vecUp ); - float flAngle = random->RandomFloat( 0.0f, 2 * M_PI ); - VectorMultiply( vecRight, cos(flAngle), m_vecBurstDelta ); - VectorMA( m_vecBurstDelta, sin(flAngle), vecUp, m_vecBurstDelta ); - - // The size of this determines the cone angle - m_vecBurstDelta *= 0.4f; - - VectorMA( vecDelta, -0.5f, m_vecBurstDelta, m_vecBurstTargetPos ); - m_vecBurstTargetPos += Weapon_ShootPosition(); - - m_vecBurstDelta /= (nShotCount - 1); -} - - -//----------------------------------------------------------------------------- -// Choose a random vector somewhere between the two specified vectors -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::RandomDirectionBetweenVectors( const Vector &vecStart, const Vector &vecEnd, Vector *pResult ) -{ - Assert( fabs( vecStart.Length() - 1.0f ) < 1e-3 ); - Assert( fabs( vecEnd.Length() - 1.0f ) < 1e-3 ); - - float flCosAngle = DotProduct( vecStart, vecEnd ); - if ( fabs( flCosAngle - 1.0f ) < 1e-3 ) - { - *pResult = vecStart; - return; - } - - Vector vecNormal; - CrossProduct( vecStart, vecEnd, vecNormal ); - float flLength = VectorNormalize( vecNormal ); - if ( flLength < 1e-3 ) - { - // This is wrong for anti-parallel vectors. so what? - *pResult = vecStart; - return; - } - - // Rotate the starting angle the specified amount - float flAngle = acos(flCosAngle) * random->RandomFloat( 0.0f, 1.0f ); - VMatrix rotationMatrix; - MatrixBuildRotationAboutAxis( rotationMatrix, vecNormal, flAngle ); - Vector3DMultiply( rotationMatrix, vecStart, *pResult ); -} - - -//----------------------------------------------------------------------------- -// Compute a predicted shoot target position n seconds into the future -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::PredictShootTargetPosition( float flDeltaTime, float flMinLeadDist, float flAddVelocity, Vector *pVecTarget, Vector *pVecTargetVelocity ) -{ - CBaseEntity *pShootTarget = GetShootTarget(); - *pVecTarget = StitchAimTarget( GetAbsOrigin(), true ); - - Vector vecSmoothedVel = pShootTarget->GetSmoothedVelocity(); - - // When we're in the air, don't predict vertical motion - if( (pShootTarget->GetFlags() & FL_ONGROUND) == 0 ) - { - vecSmoothedVel.z = 0.0f; - } - - Vector vecVelocity; - AngularImpulse angImpulse; - GetShootTarget()->GetVelocity( &vecVelocity, &angImpulse ); - - Vector vecLeadVector; - VMatrix rotationMatrix; - float flAngVel = VectorNormalize( angImpulse ); - flAngVel -= 30.0f; - if ( flAngVel > 0.0f ) - { - MatrixBuildRotationAboutAxis( rotationMatrix, angImpulse, flAngVel * flDeltaTime * 0.333f ); - Vector3DMultiply( rotationMatrix, vecSmoothedVel, vecLeadVector ); - } - else - { - vecLeadVector = vecSmoothedVel; - } - - if ( flAddVelocity != 0.0f ) - { - Vector vecForward; - pShootTarget->GetVectors( &vecForward, NULL, NULL ); - VectorMA( vecLeadVector, flAddVelocity, vecForward, vecLeadVector ); - } - - *pVecTargetVelocity = vecLeadVector; - - if ( (vecLeadVector.LengthSqr() * flDeltaTime * flDeltaTime) < flMinLeadDist * flMinLeadDist ) - { - VectorNormalize( vecLeadVector ); - vecLeadVector *= flMinLeadDist; - } - else - { - vecLeadVector *= flDeltaTime; - } - - *pVecTarget += vecLeadVector; -} - - -//----------------------------------------------------------------------------- -// Compute a predicted velocity n seconds into the future (given a known acceleration rate) -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::PredictShootTargetVelocity( float flDeltaTime, Vector *pVecTargetVel ) -{ - *pVecTargetVel = GetShootTarget()->GetSmoothedVelocity(); - - // Unless there's a big angular velocity, we can assume he accelerates - // along the forward direction. Predict acceleration for - Vector vecForward; - GetShootTarget()->GetVectors( &vecForward, NULL, NULL ); - -// float flBlendFactor = 1.0f; -// VectorMA( *pVecTargetVel, flBlendFactor * VEHICLE_PREDICT_ACCELERATION, vecForward, *pVecTargetVel ); -// if ( pVecTargetVel->LengthSqr() > (VEHICLE_PREDICT_MAX_SPEED * VEHICLE_PREDICT_MAX_SPEED) ) -// { -// VectorNormalize( *pVecTargetVel ); -// *pVecTargetVel *= VEHICLE_PREDICT_MAX_SPEED; -// } -} - - -//----------------------------------------------------------------------------- -// How many shots will I fire in a particular amount of time? -//----------------------------------------------------------------------------- -int CNPC_MetroPolice::CountShotsInTime( float flDeltaTime ) const -{ - return (int)(flDeltaTime / GetActiveWeapon()->GetFireRate() + 0.5f); -} - -float CNPC_MetroPolice::GetTimeForShots( int nShotCount ) const -{ - return nShotCount * GetActiveWeapon()->GetFireRate(); -} - - -//----------------------------------------------------------------------------- -// Visualize stitch -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::VisualizeStitch( const Vector &vecStart, const Vector &vecEnd ) -{ - NDebugOverlay::Cross3D( vecStart, -Vector(32,32,32), Vector(32,32,32), 255, 0, 0, false, 5.0f ); - NDebugOverlay::Cross3D( vecEnd, -Vector(32,32,32), Vector(32,32,32), 0, 255, 0, false, 5.0f ); - NDebugOverlay::Line( vecStart, vecEnd, 0, 255, 0, true, 5.0f ); -} - - -//----------------------------------------------------------------------------- -// Visualize line of death -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::VisualizeLineOfDeath( ) -{ - Vector vecAcross, vecStart; - CrossProduct( m_vecBurstLineOfDeathDelta, Vector( 0, 0, 1 ), vecAcross ); - VectorNormalize( vecAcross ); - NDebugOverlay::Line( m_vecBurstLineOfDeathOrigin, m_vecBurstLineOfDeathOrigin + m_vecBurstLineOfDeathDelta, 255, 255, 0, false, 5.0f ); - VectorMA( m_vecBurstLineOfDeathOrigin, m_flBurstSteerDistance, vecAcross, vecStart ); - NDebugOverlay::Line( vecStart, vecStart + m_vecBurstLineOfDeathDelta, 255, 0, 0, false, 5.0f ); - VectorMA( m_vecBurstLineOfDeathOrigin, -m_flBurstSteerDistance, vecAcross, vecStart ); - NDebugOverlay::Line( vecStart, vecStart + m_vecBurstLineOfDeathDelta, 255, 0, 0, false, 5.0f ); -} - - -//----------------------------------------------------------------------------- -// Burst mode! -//----------------------------------------------------------------------------- -#define AIM_AT_NEAR_DISTANCE_MIN 400.0f -#define AIM_AT_NEAR_DISTANCE_MAX 1000.0f -#define AIM_AT_NEAR_DISTANCE_DELTA (AIM_AT_NEAR_DISTANCE_MAX - AIM_AT_NEAR_DISTANCE_MIN) -#define AIM_AT_NEAR_DISTANCE_BONUS -200.0f - -#define AIM_AT_FAR_DISTANCE_MIN 2000.0f -#define AIM_AT_FAR_DISTANCE_BONUS_DISTANCE 500.0f -#define AIM_AT_FAR_DISTANCE_BONUS 200.0f // Add this much bonus after each BONUS_DISTANCE - - -//----------------------------------------------------------------------------- -// Modify the stitch length -//----------------------------------------------------------------------------- -float CNPC_MetroPolice::ComputeDistanceStitchModifier( float flDistanceToTarget ) const -{ - if ( flDistanceToTarget < AIM_AT_NEAR_DISTANCE_MIN ) - { - return AIM_AT_NEAR_DISTANCE_BONUS; - } - - if ( flDistanceToTarget < AIM_AT_NEAR_DISTANCE_MAX ) - { - float flFraction = 1.0f - ((flDistanceToTarget - AIM_AT_NEAR_DISTANCE_MIN) / AIM_AT_NEAR_DISTANCE_DELTA); - return flFraction * AIM_AT_NEAR_DISTANCE_BONUS; - } - - if ( flDistanceToTarget > AIM_AT_FAR_DISTANCE_MIN ) - { - float flFactor = (flDistanceToTarget - AIM_AT_FAR_DISTANCE_MIN) / AIM_AT_FAR_DISTANCE_BONUS_DISTANCE; - return flFactor * AIM_AT_FAR_DISTANCE_BONUS; - } - - return 0.0f; -} - - -//----------------------------------------------------------------------------- -// Set up the shot regulator -//----------------------------------------------------------------------------- -int CNPC_MetroPolice::SetupBurstShotRegulator( float flReactionTime ) -{ - // We want a certain amount of reaction time before the shots hit the boat - int nDesiredShotCount = CountShotsInTime( flReactionTime ); - GetShotRegulator()->SetBurstShotCountRange( nDesiredShotCount, nDesiredShotCount ); - GetShotRegulator()->SetRestInterval( 0.7f, 0.9f ); - GetShotRegulator()->Reset( true ); - int nShots = GetShotRegulator()->GetBurstShotsRemaining(); - OnRangeAttack1(); - return nShots; -} - - -//----------------------------------------------------------------------------- -// Shoots a burst right at the player -//----------------------------------------------------------------------------- -#define TIGHT_GROUP_MIN_DIST 750.0f -#define TIGHT_GROUP_MIN_SPEED 400.0f - -void CNPC_MetroPolice::AimBurstTightGrouping( float flShotTime ) -{ - if ( !IsCurrentlyFiringBurst() ) - return; - - // We want a certain amount of reaction time before the shots hit the boat - SetupBurstShotRegulator( flShotTime ); - - // Max number of times we can hit the enemy. - // Can hit more if we're slow + close - float flDistToTargetSqr = GetShootTarget()->WorldSpaceCenter().DistToSqr( Weapon_ShootPosition() ); - - int nHitCount = sk_metropolice_stitch_tight_hitcount.GetInt(); - - Vector vecTargetVel; - GetShootTarget()->GetVelocity( &vecTargetVel, NULL ); - if (( flDistToTargetSqr > TIGHT_GROUP_MIN_DIST*TIGHT_GROUP_MIN_DIST ) || - ( vecTargetVel.LengthSqr() > TIGHT_GROUP_MIN_SPEED * TIGHT_GROUP_MIN_SPEED )) - { - m_nMaxBurstHits = random->RandomInt( nHitCount, nHitCount + 1 ); - } - else - { - m_nMaxBurstHits = random->RandomInt( 2 * nHitCount - 1, 2 * nHitCount + 1 ); - } - - m_nBurstMode = BURST_TIGHT_GROUPING; - - // This helps the NPC model aim at the correct point - m_nBurstSteerMode = BURST_STEER_EXACTLY_TOWARD_TARGET; - m_vecBurstTargetPos = GetEnemy()->WorldSpaceCenter(); -} - - -//----------------------------------------------------------------------------- -// Reaction time for stitch -//----------------------------------------------------------------------------- -#define AIM_AT_TIME_DELTA_SPEED 100.0f -#define AIM_AT_TIME_DELTA_DIST 500.0f -#define AIM_AT_TIME_SPEED_COUNT 6 -#define AIM_AT_TIME_DIST_COUNT 7 - -static float s_pReactionFraction[AIM_AT_TIME_DIST_COUNT][AIM_AT_TIME_SPEED_COUNT] = -{ - { 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 1.0f }, - { 0.5f, 0.5f, 0.5f, 0.5f, 0.75f, 1.0f }, - { 0.5f, 0.5f, 0.5f, 0.65f, 0.8f, 1.0f }, - { 0.5f, 0.5f, 0.5f, 0.75f, 1.0f, 1.0f }, - { 0.5f, 0.5f, 0.75f, 1.0f, 1.0f, 1.0f }, - { 0.75f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }, -}; - -float CNPC_MetroPolice::AimBurstAtReactionTime( float flReactionTime, float flDistToTarget, float flCurrentSpeed ) -{ - flReactionTime *= sk_metropolice_stitch_reaction.GetFloat(); - - if ( IsEnemyInAnAirboat() ) - { - float u = flCurrentSpeed / AIM_AT_TIME_DELTA_SPEED; - float v = flDistToTarget / AIM_AT_TIME_DELTA_DIST; - int nu = (int)u; - int nv = (int)v; - if (( nu < AIM_AT_TIME_SPEED_COUNT - 1 ) && ( nv < AIM_AT_TIME_DIST_COUNT - 1 )) - { - float fu = u - nu; - float fv = v - nv; - float flReactionFactor = s_pReactionFraction[nv][nu] * (1.0f - fu) * (1.0f - fv); - flReactionFactor += s_pReactionFraction[nv+1][nu] * (1.0f - fu) * fv; - flReactionFactor += s_pReactionFraction[nv][nu+1] * fu * (1.0f - fv); - flReactionFactor += s_pReactionFraction[nv+1][nu+1] * fu * fv; - - flReactionTime *= flReactionFactor; - } - } - - return flReactionTime; -} - - -//----------------------------------------------------------------------------- -// Burst mode! -//----------------------------------------------------------------------------- -#define AIM_AT_SHOT_DELTA_SPEED 100.0f -#define AIM_AT_SHOT_DELTA_DIST 500.0f -#define AIM_AT_SHOT_SPEED_COUNT 6 -#define AIM_AT_SHOT_DIST_COUNT 6 - -static float s_pShotCountFraction[AIM_AT_TIME_DIST_COUNT][AIM_AT_TIME_SPEED_COUNT] = -{ - { 3.0f, 3.0f, 2.5f, 1.5f, 1.0f, 0.0f }, - { 3.0f, 3.0f, 2.5f, 1.25f, 0.5f, 0.0f }, - { 2.5f, 2.5f, 2.0f, 1.0f, 0.0f, 0.0f }, - { 2.0f, 2.0f, 1.5f, 0.5f, 0.0f, 0.0f }, - { 1.0f, 1.0f, 1.0f, 0.5f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }, -}; - -int CNPC_MetroPolice::AimBurstAtSetupHitCount( float flDistToTarget, float flCurrentSpeed ) -{ - // Max number of times we can hit the enemy - int nHitCount = sk_metropolice_stitch_at_hitcount.GetInt(); - m_nMaxBurstHits = random->RandomInt( nHitCount, nHitCount + 1 ); - - if ( IsEnemyInAnAirboat() ) - { - float u = flCurrentSpeed / AIM_AT_SHOT_DELTA_SPEED; - float v = flDistToTarget / AIM_AT_SHOT_DELTA_DIST; - int nu = (int)u; - int nv = (int)v; - if (( nu < AIM_AT_SHOT_SPEED_COUNT - 1 ) && ( nv < AIM_AT_SHOT_DIST_COUNT - 1 )) - { - float fu = u - nu; - float fv = v - nv; - float flShotFactor = s_pShotCountFraction[nv][nu] * (1.0f - fu) * (1.0f - fv); - flShotFactor += s_pShotCountFraction[nv+1][nu] * (1.0f - fu) * fv; - flShotFactor += s_pShotCountFraction[nv][nu+1] * fu * (1.0f - fv); - flShotFactor += s_pShotCountFraction[nv+1][nu+1] * fu * fv; - - int nExtraShots = (int)(nHitCount * flShotFactor); - m_nMaxBurstHits += random->RandomInt( nExtraShots, nExtraShots + 1 ); - return nExtraShots; - } - } - - return 0; -} - - -//----------------------------------------------------------------------------- -// Burst mode! -//----------------------------------------------------------------------------- -#define AIM_AT_DEFAULT_STITCH_SHOT_DIST 40.0f -#define AIM_AT_SPEED_BONUS 200.0f -#define AIM_AT_REACTION_TIME_FRACTION 0.8f -#define AIM_AT_NEAR_REACTION_TIME_FRACTION 0.3f -#define AIM_AT_STEER_DISTANCE 125.0f - -void CNPC_MetroPolice::AimBurstAtEnemy( float flReactionTime ) -{ - if ( !IsCurrentlyFiringBurst() ) - return; - - Vector vecVelocity; - GetShootTarget()->GetVelocity( &vecVelocity, NULL ); - float flCurrentSpeed = vecVelocity.Length(); - float flDistToTargetSqr = GetShootTarget()->WorldSpaceCenter().AsVector2D().DistToSqr( Weapon_ShootPosition().AsVector2D() ); - float flDistToTarget = sqrt(flDistToTargetSqr); - - flReactionTime = AimBurstAtReactionTime( flReactionTime, flDistToTarget, flCurrentSpeed ); - - // We want a certain amount of reaction time before the shots hit the boat - int nShotCount = SetupBurstShotRegulator( flReactionTime ); - - bool bIsInVehicle = IsEnemyInAnAirboat(); - if ( bIsInVehicle ) - { - m_nBurstMode = BURST_LOCK_ON_AFTER_HIT; - m_flBurstSteerDistance = AIM_AT_STEER_DISTANCE; - } - else - { - m_nBurstMode = BURST_ACTIVE; - m_flBurstSteerDistance = 0; - } - m_nBurstSteerMode = BURST_STEER_WITHIN_LINE_OF_DEATH; - - // Max number of times we can hit the enemy - int nExtraShots = AimBurstAtSetupHitCount( flDistToTarget, flCurrentSpeed ); - float flExtraTime = GetTimeForShots( nExtraShots ) + (1.0f - AIM_AT_REACTION_TIME_FRACTION) * flReactionTime; - float flReactionFraction = 1.0f - flExtraTime / flReactionTime; - if ( flReactionFraction < 0.5f ) - { - flReactionFraction = 0.5f; - } - - float flFirstHitTime = flReactionTime * flReactionFraction; - Vector vecShootAt, vecShootAtVel; - PredictShootTargetPosition( flFirstHitTime, 0.0f, 0.0f, &vecShootAt, &vecShootAtVel ); - - Vector vecDelta; - VectorSubtract( vecShootAt, Weapon_ShootPosition(), vecDelta ); - float flDistanceToTarget = vecDelta.Length(); - - // Always stitch horizontally... - vecDelta.z = 0.0f; - - // The max stitch distance here is used to guarantee the cop doesn't try to lead - // the airboat so much that he ends up shooting behind himself - float flMaxStitchDistance = VectorNormalize( vecDelta ); - flMaxStitchDistance -= 50.0f; - if ( flMaxStitchDistance < 0 ) - { - flMaxStitchDistance = 0.0f; - } - - float flStitchLength = nShotCount * AIM_AT_DEFAULT_STITCH_SHOT_DIST; - - // Modify the stitch length based on distance from the shooter - flStitchLength += ComputeDistanceStitchModifier( flDistanceToTarget ); - - if ( bIsInVehicle ) - { - // Make longer stitches if the enemy is going faster - Vector vecEnemyVelocity = GetShootTarget()->GetSmoothedVelocity(); - if( (GetShootTarget()->GetFlags() & FL_ONGROUND) == 0 ) - { - vecEnemyVelocity.z = 0.0f; - } - - float flEnemySpeed = VectorNormalize( vecEnemyVelocity ); - flStitchLength += AIM_AT_SPEED_BONUS * ( flEnemySpeed / 100.0f ); - - // Add in a little randomness across the direction of motion... - // Always put it on the side we're currently looking at - Vector vecAcross; - CrossProduct( vecEnemyVelocity, Vector( 0, 0, 1 ), vecAcross ); - VectorNormalize( vecAcross ); - - Vector eyeForward; - AngleVectors( GetEnemy()->EyeAngles(), &eyeForward ); - if ( DotProduct( vecAcross, eyeForward ) < 0.0f ) - { - vecAcross *= -1.0f; - } - - float flMinAdd = RemapVal( flEnemySpeed, 0.0f, 200.0f, 70.0f, 30.0f ); - VectorMA( vecShootAt, random->RandomFloat( flMinAdd, 100.0f ), vecAcross, vecShootAt ); - } - - // Compute the distance along the stitch direction to the cop. we don't want to cross that line - Vector vecStitchStart, vecStitchEnd; - VectorMA( vecShootAt, -MIN( flStitchLength * flReactionFraction, flMaxStitchDistance ), vecDelta, vecStitchStart ); - VectorMA( vecShootAt, flStitchLength * (1.0f - flReactionFraction), vecDelta, vecStitchEnd ); - - // Trace down a bit to hit the ground if we're above the ground... - trace_t trace; - UTIL_TraceLine( vecStitchStart, vecStitchStart + Vector( 0, 0, -512 ), (MASK_SOLID_BRUSHONLY | MASK_WATER), NULL, COLLISION_GROUP_NONE, &trace ); - m_vecBurstTargetPos = trace.endpos; - VectorSubtract( vecStitchEnd, m_vecBurstTargetPos, m_vecBurstDelta ); - - m_vecBurstLineOfDeathOrigin = m_vecBurstTargetPos; - m_vecBurstLineOfDeathDelta = m_vecBurstDelta; - - m_vecBurstDelta /= (nShotCount - 1); - -// VisualizeStitch( m_vecBurstTargetPos, vecStitchEnd ); -// VisualizeLineOfDeath(); -} - - -//----------------------------------------------------------------------------- -// Burst mode! -//----------------------------------------------------------------------------- -#define AIM_IN_FRONT_OF_DEFAULT_STITCH_LENGTH 1000.0f -#define AIM_IN_FRONT_OF_MINIMUM_DISTANCE 500.0f -#define AIM_IN_FRONT_DRAW_LINE_OF_DEATH_FRACTION 0.5f -#define AIM_IN_FRONT_STEER_DISTANCE 150.0f -#define AIM_IN_FRONT_REACTION_FRACTION 0.8f -#define AIM_IN_FRONT_EXTRA_VEL 200.0f - -void CNPC_MetroPolice::AimBurstInFrontOfEnemy( float flReactionTime ) -{ - if ( !IsCurrentlyFiringBurst() ) - return; - - flReactionTime *= sk_metropolice_stitch_reaction.GetFloat(); - - // We want a certain amount of reaction time before the shots hit the boat - int nShotCount = SetupBurstShotRegulator( flReactionTime ); - - // Max number of times we can hit the player in the airboat - m_nMaxBurstHits = random->RandomInt( 3, 4 ); - m_nBurstMode = BURST_LOCK_ON_AFTER_HIT; - m_nBurstSteerMode = BURST_STEER_WITHIN_LINE_OF_DEATH; - - // The goal here is to slow him down. Choose a target position such that we predict - // where he'd be in he accelerated by N over the reaction time. Prevent him from getting there. - Vector vecShootAt, vecShootAtVel, vecAcross; - PredictShootTargetPosition( flReactionTime * AIM_IN_FRONT_REACTION_FRACTION, - AIM_IN_FRONT_OF_MINIMUM_DISTANCE, 0.0f, &vecShootAt, &vecShootAtVel ); - - // Now add in some extra vel in a random direction + try to prevent that.... - Vector vecTargetToGun, vecExtraDistance; - VectorSubtract( Weapon_ShootPosition(), vecShootAt, vecTargetToGun ); - VectorNormalize( vecTargetToGun ); - VectorNormalize( vecShootAtVel ); - RandomDirectionBetweenVectors( vecShootAtVel, vecTargetToGun, &vecExtraDistance ); - vecExtraDistance *= AIM_IN_FRONT_EXTRA_VEL; - vecShootAt += vecExtraDistance; - - CrossProduct( vecExtraDistance, Vector( 0, 0, 1 ), vecAcross ); - VectorNormalize( vecAcross ); - - float flStitchLength = AIM_IN_FRONT_OF_DEFAULT_STITCH_LENGTH; - - Vector vecEndPoint1, vecEndPoint2; - VectorSubtract( Weapon_ShootPosition(), StitchAimTarget( GetAbsOrigin(), false ), vecTargetToGun ); - float flSign = ( DotProduct( vecAcross, vecTargetToGun ) >= 0.0f ) ? 1.0f : -1.0f; - VectorMA( vecShootAt, flSign * flStitchLength * AIM_IN_FRONT_REACTION_FRACTION, vecAcross, vecEndPoint1 ); - VectorMA( vecShootAt, -flSign * flStitchLength * (1.0f - AIM_IN_FRONT_REACTION_FRACTION), vecAcross, vecEndPoint2 ); - - m_vecBurstTargetPos = vecEndPoint1; - VectorSubtract( vecEndPoint2, vecEndPoint1, m_vecBurstDelta ); - - // This defines the line of death, which, when crossed, results in damage - m_vecBurstLineOfDeathOrigin = m_vecBurstTargetPos; - m_vecBurstLineOfDeathDelta = m_vecBurstDelta; - m_flBurstSteerDistance = AIM_IN_FRONT_STEER_DISTANCE; - - // Make the visual representation of the line of death lie closest to the boat. - VectorMA( m_vecBurstTargetPos, -AIM_IN_FRONT_STEER_DISTANCE, vecShootAtVel, m_vecBurstTargetPos ); - m_vecBurstDelta /= (nShotCount - 1); - -// VisualizeStitch( m_vecBurstTargetPos, m_vecBurstTargetPos + m_vecBurstDelta * (nShotCount - 1) ); -// VisualizeLineOfDeath(); -} - - -//----------------------------------------------------------------------------- -// Aim burst behind enemy -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::AimBurstBehindEnemy( float flShotTime ) -{ - if ( !IsCurrentlyFiringBurst() ) - return; - - flShotTime *= sk_metropolice_stitch_reaction.GetFloat(); - - // We want a certain amount of reaction time before the shots hit the boat - int nShotCount = SetupBurstShotRegulator( flShotTime ); - - // Max number of times we can hit the player in the airboat - int nHitCount = sk_metropolice_stitch_behind_hitcount.GetInt(); - m_nMaxBurstHits = random->RandomInt( nHitCount, nHitCount + 1 ); - m_nBurstMode = BURST_LOCK_ON_AFTER_HIT; - m_nBurstSteerMode = BURST_STEER_WITHIN_LINE_OF_DEATH; - - // Shoot across the enemy in between the enemy and me - Vector vecShootAt, vecShootAtVel, vecAcross; - PredictShootTargetPosition( 0.0f, 0.0f, 0.0f, &vecShootAt, &vecShootAtVel ); - - // Choose a point in between the shooter + the target - Vector vecDelta; - VectorSubtract( Weapon_ShootPosition(), vecShootAt, vecDelta ); - vecDelta.z = 0.0f; - float flDistTo = VectorNormalize( vecDelta ); - if ( flDistTo > AIM_BEHIND_MINIMUM_DISTANCE ) - { - flDistTo = AIM_BEHIND_MINIMUM_DISTANCE; - } - VectorMA( vecShootAt, flDistTo, vecDelta, vecShootAt ); - CrossProduct( vecDelta, Vector( 0, 0, 1 ), vecAcross ); - - float flStitchLength = AIM_BEHIND_DEFAULT_STITCH_LENGTH; - - Vector vecEndPoint1, vecEndPoint2; - VectorMA( vecShootAt, -flStitchLength * 0.5f, vecAcross, vecEndPoint1 ); - VectorMA( vecShootAt, flStitchLength * 0.5f, vecAcross, vecEndPoint2 ); - - m_vecBurstTargetPos = vecEndPoint1; - VectorSubtract( vecEndPoint2, vecEndPoint1, m_vecBurstDelta ); - - // This defines the line of death, which, when crossed, results in damage - m_vecBurstLineOfDeathOrigin = m_vecBurstTargetPos; - m_vecBurstLineOfDeathDelta = m_vecBurstDelta; - m_flBurstSteerDistance = AIM_BEHIND_STEER_DISTANCE; - - // Make the visual representation of the line of death lie closest to the boat. - VectorMA( m_vecBurstTargetPos, -AIM_BEHIND_STEER_DISTANCE, vecDelta, m_vecBurstTargetPos ); - m_vecBurstDelta /= (nShotCount - 1); - -// VisualizeStitch( m_vecBurstTargetPos, m_vecBurstTargetPos + m_vecBurstDelta * (nShotCount - 1) ); -// VisualizeLineOfDeath(); -} - - -//----------------------------------------------------------------------------- -// Burst mode! -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::AimBurstAlongSideOfEnemy( float flFollowTime ) -{ - if ( !IsCurrentlyFiringBurst() ) - return; - - flFollowTime *= sk_metropolice_stitch_reaction.GetFloat(); - - // We want a certain amount of reaction time before the shots hit the boat - int nShotCount = SetupBurstShotRegulator( flFollowTime ); - - // Max number of times we can hit the player in the airboat - int nHitCount = sk_metropolice_stitch_along_hitcount.GetInt(); - m_nMaxBurstHits = random->RandomInt( nHitCount, nHitCount + 1 ); - m_nBurstMode = BURST_LOCK_ON_AFTER_HIT; - m_nBurstSteerMode = BURST_STEER_WITHIN_LINE_OF_DEATH; - - Vector vecShootAt, vecShootAtVel, vecAcross; - PredictShootTargetPosition( AIM_ALONG_SIDE_LINE_OF_DEATH_LEAD_TIME, 225.0f, 0.0f, &vecShootAt, &vecShootAtVel ); - CrossProduct( vecShootAtVel, Vector( 0, 0, 1 ), vecAcross ); - VectorNormalize( vecAcross ); - - // Choose the side of the vehicle which is closer to the shooter - Vector vecSidePoint; - Vector vecTargetToGun; - VectorSubtract( Weapon_ShootPosition(), vecShootAt, vecTargetToGun ); - float flSign = ( DotProduct( vecTargetToGun, vecAcross ) > 0.0f ) ? 1.0f : -1.0f; - float flDist = AIM_ALONG_SIDE_LINE_OF_DEATH_DISTANCE + random->RandomFloat( 0.0f, 50.0f ); - VectorMA( vecShootAt, flSign * flDist, vecAcross, vecSidePoint ); - - vecShootAtVel.z = 0.0f; - float flTargetSpeed = VectorNormalize( vecShootAtVel ); - float flStitchLength = MAX( AIM_IN_FRONT_OF_DEFAULT_STITCH_LENGTH, flTargetSpeed * flFollowTime * 0.9 ); - - // This defines the line of death, which, when crossed, results in damage - m_vecBurstLineOfDeathOrigin = vecSidePoint; - VectorMultiply( vecShootAtVel, flStitchLength, m_vecBurstLineOfDeathDelta ); - - // Pull the endpoint a little toward the NPC firing it... - float flExtraDist = random->RandomFloat( 25.0f, 50.0f ); - VectorNormalize( vecTargetToGun ); - if ( flSign * DotProduct( vecTargetToGun, vecShootAtVel ) < 0.1f ) - { - flExtraDist += 100.0f; - } - VectorMA( m_vecBurstLineOfDeathDelta, flSign * flExtraDist, vecAcross, m_vecBurstLineOfDeathDelta ); - - m_flBurstSteerDistance = AIM_ALONG_SIDE_STEER_DISTANCE; - m_vecBurstDelta = m_vecBurstLineOfDeathDelta; - m_vecBurstTargetPos = m_vecBurstLineOfDeathOrigin; - - // Make the visual representation of the line of death lie closest to the boat. - VectorMA( m_vecBurstTargetPos, -flSign * AIM_ALONG_SIDE_STEER_DISTANCE, vecAcross, m_vecBurstTargetPos ); - m_vecBurstDelta /= (nShotCount - 1); - -// VisualizeStitch( m_vecBurstTargetPos, m_vecBurstTargetPos + m_vecBurstDelta * (nShotCount - 1) ); -// VisualizeLineOfDeath(); -} - - -//----------------------------------------------------------------------------- -// Different burst steering modes -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::SteerBurstTowardTargetUseSpeedOnly( const Vector &vecShootAt, - const Vector &vecShootAtVelocity, float flPredictTime, int nShotsTillPredict ) -{ - // Only account for changes in *speed*; ignore all changes in velocity direction, etc. - // This one only hits the player if there is *no* steering, just acceleration or decceleration - Vector vecBurstDir = m_vecBurstPredictedVelocityDir; - float flActualSpeed = DotProduct( vecShootAtVelocity, vecBurstDir ); - - vecBurstDir *= (flActualSpeed - m_vecBurstPredictedSpeed) * flPredictTime; - vecBurstDir /= (nShotsTillPredict - 1); - - m_vecBurstPredictedSpeed = flActualSpeed; - m_vecBurstDelta += vecBurstDir; -} - -void CNPC_MetroPolice::SteerBurstTowardTargetUseVelocity( const Vector &vecShootAt, const Vector &vecShootAtVelocity, int nShotsTillPredict ) -{ - // Only account for all velocity changes - // This one looks scary in that it always gets near to the player, - // but it never usually hits actually. - Vector vecBurstDir = m_vecBurstLineOfDeathDelta; - m_vecBurstLineOfDeathDelta = vecShootAtVelocity; - vecBurstDir = vecShootAtVelocity - vecBurstDir; - vecBurstDir /= (nShotsTillPredict - 1); - - m_vecBurstDelta += vecBurstDir; -} - -void CNPC_MetroPolice::SteerBurstTowardTargetUsePosition( const Vector &vecShootAt, const Vector &vecShootAtVelocity, int nShotsTillPredict ) -{ - // Account for velocity + position changes - // This method *always* hits - VectorSubtract( vecShootAt, m_vecBurstTargetPos, m_vecBurstDelta ); - m_vecBurstDelta /= (nShotsTillPredict - 1); -} - -void CNPC_MetroPolice::SteerBurstTowardPredictedPoint( const Vector &vecShootAt, const Vector &vecShootAtVelocity, int nShotsTillPredict ) -{ - // Account for velocity + position changes, but only within a constrained cylinder - Vector vecConstrainedShootPosition; - CalcClosestPointOnLine( vecShootAt, m_vecBurstLineOfDeathOrigin, m_vecBurstLineOfDeathOrigin + m_vecBurstLineOfDeathDelta, vecConstrainedShootPosition ); - - Vector vecDelta; - VectorSubtract( vecShootAt, vecConstrainedShootPosition, vecDelta ); - if ( vecDelta.LengthSqr( ) <= m_flBurstSteerDistance * m_flBurstSteerDistance ) - { - vecConstrainedShootPosition = vecShootAt; - } - else - { - VectorNormalize( vecDelta ); - VectorMA( vecConstrainedShootPosition, m_flBurstSteerDistance, vecDelta, vecConstrainedShootPosition ); - } - - // This method *always* hits if the entity is within the cylinder - VectorSubtract( vecConstrainedShootPosition, m_vecBurstTargetPos, m_vecBurstDelta ); - if ( nShotsTillPredict >= 2 ) - { - m_vecBurstDelta /= (nShotsTillPredict - 1); - } -} - -#define STEER_LINE_OF_DEATH_MAX_DISTANCE 250.0f - -void CNPC_MetroPolice::SteerBurstWithinLineOfDeath( ) -{ - // Account for velocity + position changes, but only within a constrained cylinder - Vector vecShootAt; - vecShootAt = StitchAimTarget( GetAbsOrigin(), false ); - - // If the target close to the current point the shot is on, - // move the shot toward the point - Vector vecPointOnLineOfDeath; - CalcClosestPointOnLine( m_vecBurstTargetPos, m_vecBurstLineOfDeathOrigin, m_vecBurstLineOfDeathOrigin + m_vecBurstLineOfDeathDelta, vecPointOnLineOfDeath ); - - Vector vecDelta; - VectorSubtract( vecShootAt, vecPointOnLineOfDeath, vecDelta ); - if ( vecDelta.LengthSqr( ) <= m_flBurstSteerDistance * m_flBurstSteerDistance ) - { - VectorSubtract( vecShootAt, m_vecBurstTargetPos, m_vecBurstDelta ); - if ( m_vecBurstDelta.LengthSqr() > (STEER_LINE_OF_DEATH_MAX_DISTANCE * STEER_LINE_OF_DEATH_MAX_DISTANCE) ) - { - VectorNormalize( m_vecBurstDelta ); - m_vecBurstDelta *= STEER_LINE_OF_DEATH_MAX_DISTANCE; - } - } - else - { - // Just make the burst go back and forth alont the line of death... - Vector vecNext = m_vecBurstTargetPos + m_vecBurstDelta; - - float t; - CalcClosestPointOnLine( vecNext, m_vecBurstLineOfDeathOrigin, m_vecBurstLineOfDeathOrigin + m_vecBurstLineOfDeathDelta, vecPointOnLineOfDeath, &t ); - if (( t < -0.1f ) || ( t > 1.1f )) - { - m_vecBurstDelta *= -1.0f; - - // This is necessary to make it not look like a machine is firing the gun - Vector vecBurstDir = m_vecBurstDelta; - float flLength = VectorNormalize( vecBurstDir ); - vecBurstDir *= random->RandomFloat( -flLength * 0.5f, flLength * 0.5f ); - - m_vecBurstTargetPos += vecBurstDir; - } - } -} - - -//----------------------------------------------------------------------------- -// Burst mode! -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::SteerBurstTowardTarget( ) -{ - switch ( m_nBurstSteerMode ) - { - case BURST_STEER_NONE: - return; - - case BURST_STEER_EXACTLY_TOWARD_TARGET: - // Necessary to get the cop looking at the target - m_vecBurstTargetPos = GetEnemy()->WorldSpaceCenter(); - return; - - case BURST_STEER_ADJUST_FOR_SPEED_CHANGES: - { - // Predict the airboat position at the point where we were expecting to hit them - if ( m_flBurstPredictTime <= gpGlobals->curtime ) - return; - - float flPredictTime = m_flBurstPredictTime - gpGlobals->curtime; - int nShotsTillPredict = CountShotsInTime( flPredictTime ); - if ( nShotsTillPredict <= 1 ) - return; - - Vector vecShootAt, vecShootAtVelocity; - PredictShootTargetPosition( flPredictTime, 0.0f, 0.0f, &vecShootAt, &vecShootAtVelocity ); - SteerBurstTowardTargetUseSpeedOnly( vecShootAt, vecShootAtVelocity, flPredictTime, nShotsTillPredict ); - } - break; - - case BURST_STEER_TOWARD_PREDICTED_POINT: - // Don't course-correct until the predicted time - if ( m_flBurstPredictTime >= gpGlobals->curtime ) - return; - - // fall through! - - case BURST_STEER_WITHIN_LINE_OF_DEATH: - break; - } - - SteerBurstWithinLineOfDeath( ); -} - - -//----------------------------------------------------------------------------- -// Various burst trajectory methods -//----------------------------------------------------------------------------- -Vector CNPC_MetroPolice::ComputeBurstLockOnTrajectory( const Vector &shootOrigin ) -{ - Vector vecTrajectory; - VectorSubtract( GetEnemy()->WorldSpaceCenter(), shootOrigin, vecTrajectory ); - VectorNormalize( vecTrajectory ); - return vecTrajectory; -} - -Vector CNPC_MetroPolice::ComputeBurstDeliberatelyMissTrajectory( const Vector &shootOrigin ) -{ - m_vecBurstTargetPos.z += 8.0f; - - Vector vecTrajectory; - VectorSubtract( m_vecBurstTargetPos, shootOrigin, vecTrajectory ); - VectorNormalize( vecTrajectory ); - return vecTrajectory; -} - -Vector CNPC_MetroPolice::ComputeBurstTrajectory( const Vector &shootOrigin ) -{ - // Perform the stitch - Vector vecPos = m_vecBurstTargetPos; - - // For players, don't let them jump over the burst. - CBaseEntity *pEnemy = GetEnemy(); - bool bIsPlayerOnFoot = pEnemy && pEnemy->IsPlayer() && !IsEnemyInAnAirboat(); - if ( bIsPlayerOnFoot ) - { - Vector vecNormalizedPt; - pEnemy->CollisionProp()->WorldToNormalizedSpace( vecPos, &vecNormalizedPt ); - if ( (vecNormalizedPt.x >= -0.1f) && (vecNormalizedPt.x <= 1.1f) && - (vecNormalizedPt.y >= -0.1f) && (vecNormalizedPt.y <= 1.1f) && - (vecNormalizedPt.z >= -0.7f) && (vecNormalizedPt.z < 1.1f) ) - { - vecPos.z = pEnemy->WorldSpaceCenter().z; - } - } - - vecPos -= shootOrigin; - - // Add a little noise. Even though it's non-physical, it looks better - // to have the same amount of noise regardless of distance from the shooter - // Always make the noise perpendicular to the burst direction - float flNoise = bIsPlayerOnFoot ? 16.0f : 32.0f; - Vector vecNoise; - CrossProduct( m_vecBurstDelta, Vector( 0, 0, 1 ), vecNoise ); - VectorNormalize( vecNoise ); - vecNoise *= random->RandomFloat( -flNoise, flNoise ); - vecPos += vecNoise; - - VectorNormalize( vecPos ); - - // X360BUG: Was causing compiler crash in release, still? -// if ( IsPC() ) - { - // Allow for steering towards the target. - SteerBurstTowardTarget(); - } - - // Update the burst target position - m_vecBurstTargetPos += m_vecBurstDelta; - -// NDebugOverlay::Cross3D( m_vecBurstTargetPos, -Vector(32,32,32), Vector(32,32,32), 255, 0, 255, false, 1.0f ); - - return vecPos; -} - - -//----------------------------------------------------------------------------- -// Deliberately aims as close as possible w/o hitting -//----------------------------------------------------------------------------- -Vector CNPC_MetroPolice::AimCloseToTargetButMiss( CBaseEntity *pTarget, const Vector &shootOrigin ) -{ - Vector vecNormalizedSpace; - pTarget->CollisionProp()->WorldToNormalizedSpace( shootOrigin, &vecNormalizedSpace ); - vecNormalizedSpace -= Vector( 0.5f, 0.5f, 0.5f ); - float flDist = VectorNormalize( vecNormalizedSpace ); - float flMinRadius = flDist * sqrt(3.0) / sqrt( flDist * flDist - 3 ); - - // Choose random points in a plane perpendicular to the shoot origin. - Vector vecRandomDir; - vecRandomDir.Random( -1.0f, 1.0f ); - VectorMA( vecRandomDir, -DotProduct( vecNormalizedSpace, vecRandomDir ), vecNormalizedSpace, vecRandomDir ); - VectorNormalize( vecRandomDir ); - vecRandomDir *= flMinRadius; - - vecRandomDir *= 0.5f; - vecRandomDir += Vector( 0.5f, 0.5f, 0.5f ); - - Vector vecBodyTarget; - pTarget->CollisionProp()->NormalizedToWorldSpace( vecRandomDir, &vecBodyTarget ); - vecBodyTarget -= shootOrigin; - return vecBodyTarget; -} - - -//----------------------------------------------------------------------------- -// A burst that goes right at the enemy -//----------------------------------------------------------------------------- -#define MIN_TIGHT_BURST_DIST 1000.0f -#define MAX_TIGHT_BURST_DIST 2000.0f - -Vector CNPC_MetroPolice::ComputeTightBurstTrajectory( const Vector &shootOrigin ) -{ - CBaseEntity *pEnemy = GetEnemy(); - if ( !pEnemy ) - { - return BaseClass::GetActualShootTrajectory( shootOrigin ); - } - - // Aim around the player... - if ( m_nBurstHits >= m_nMaxBurstHits ) - { - return AimCloseToTargetButMiss( pEnemy, shootOrigin ); - } - - float flDist = shootOrigin.DistTo( pEnemy->WorldSpaceCenter() ); - float flMin = -0.2f; - float flMax = 1.2f; - if ( flDist > MIN_TIGHT_BURST_DIST ) - { - flDist = clamp( flDist, MIN_TIGHT_BURST_DIST, MAX_TIGHT_BURST_DIST ); - flMin = SimpleSplineRemapVal( flDist, MIN_TIGHT_BURST_DIST, MAX_TIGHT_BURST_DIST, -0.2f, -0.7f ); - flMax = SimpleSplineRemapVal( flDist, MIN_TIGHT_BURST_DIST, MAX_TIGHT_BURST_DIST, 1.2f, 1.7f ); - } - - // Aim randomly at the player. Since body target uses the vehicle body target, - // we instead are going to not use it - Vector vecBodyTarget; - pEnemy->CollisionProp()->RandomPointInBounds( Vector( flMin, flMin, flMin ), Vector( flMax, flMax, flMax * 0.75f ), &vecBodyTarget ); - vecBodyTarget -= shootOrigin; - return vecBodyTarget; -} - - -//----------------------------------------------------------------------------- -// Burst mode! -//----------------------------------------------------------------------------- -Vector CNPC_MetroPolice::GetActualShootTrajectory( const Vector &shootOrigin ) -{ - switch ( m_nBurstMode ) - { - case BURST_NOT_ACTIVE: - return BaseClass::GetActualShootTrajectory( shootOrigin ); - - case BURST_LOCKED_ON: - if ( m_nBurstHits < m_nMaxBurstHits ) - { - return ComputeBurstLockOnTrajectory( shootOrigin ); - } - - // Start shooting over the head of the enemy - GetShootTarget()->CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 1.0f ), &m_vecBurstTargetPos ); - m_nBurstMode = BURST_DELIBERATELY_MISS; - // NOTE: Fall through to BURST_DELIBERATELY_MISS!! - - case BURST_DELIBERATELY_MISS: - return ComputeBurstDeliberatelyMissTrajectory( shootOrigin ); - - case BURST_LOCK_ON_AFTER_HIT: - // See if our target is within the bounds of the enemy - if ( GetShootTarget()->CollisionProp()->IsPointInBounds( m_vecBurstTargetPos ) ) - { - // Now raytrace against only the world + (good for cops on bridges) - trace_t tr; - CTraceFilterWorldOnly traceFilter; - UTIL_TraceLine( Weapon_ShootPosition(), m_vecBurstTargetPos, MASK_SOLID, &traceFilter, &tr ); - if ( tr.fraction == 1.0f ) - { - m_nBurstMode = BURST_LOCKED_ON; - } - } - // NOTE: Fall through to BURST_ACTIVE! - - case BURST_ACTIVE: - // Stitch toward the target, we haven't hit it yet - return ComputeBurstTrajectory( shootOrigin ); - - case BURST_TIGHT_GROUPING: - // This one goes right at the enemy - return ComputeTightBurstTrajectory( shootOrigin ); - } - - Assert(0); - return vec3_origin; -} - - -//----------------------------------------------------------------------------- -// Burst mode! -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::FireBullets( const FireBulletsInfo_t &info ) -{ - CBaseEntity *pEnemy = GetEnemy(); - bool bIsPlayer = pEnemy && pEnemy->IsPlayer(); - if ( bIsPlayer && IsCurrentlyFiringBurst() ) - { - FireBulletsInfo_t actualInfo = info; - if ( m_nBurstHits < m_nMaxBurstHits ) - { - CBasePlayer *pPlayer = assert_cast(pEnemy); - - // This makes it so that if the player gets hit underwater, - // he won't take damage if his viewpoint is above water. - if ( !IsEnemyInAnAirboat() && ( pPlayer->GetWaterLevel() != 3 ) ) - { - actualInfo.m_nFlags |= FIRE_BULLETS_DONT_HIT_UNDERWATER; - } - - // This test is here to see if we've damaged the player - int nPrevHealth = pPlayer->GetHealth(); - int nPrevArmor = pPlayer->ArmorValue(); - - BaseClass::FireBullets( actualInfo ); - - if (( pPlayer->GetHealth() < nPrevHealth ) || ( pPlayer->ArmorValue() < nPrevArmor )) - { - ++m_nBurstHits; - } - } - else - { - actualInfo.m_pAdditionalIgnoreEnt = pEnemy; - BaseClass::FireBullets( actualInfo ); - } - } - else - { - BaseClass::FireBullets( info ); - } -} - - -//----------------------------------------------------------------------------- -// Behaviors! Lovely behaviors -//----------------------------------------------------------------------------- -bool CNPC_MetroPolice::CreateBehaviors() -{ - AddBehavior( &m_RappelBehavior ); - AddBehavior( &m_FollowBehavior ); - AddBehavior( &m_PolicingBehavior ); - AddBehavior( &m_ActBusyBehavior ); - AddBehavior( &m_AssaultBehavior ); - AddBehavior( &m_StandoffBehavior ); - AddBehavior( &m_FuncTankBehavior ); - - return BaseClass::CreateBehaviors(); -} - -void CNPC_MetroPolice::InputEnableManhackToss( inputdata_t &inputdata ) -{ - if ( HasSpawnFlags( SF_METROPOLICE_NO_MANHACK_DEPLOY ) ) - { - RemoveSpawnFlags( SF_METROPOLICE_NO_MANHACK_DEPLOY ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::InputSetPoliceGoal( inputdata_t &inputdata ) -{ - CBaseEntity *pGoal = gEntList.FindEntityByName( NULL, inputdata.value.String() ); - - if ( pGoal == NULL ) - { - DevMsg( "SetPoliceGoal: %s (%s) unable to find ai_goal_police: %s\n", GetClassname(), GetDebugName(), inputdata.value.String() ); - return; - } - - CAI_PoliceGoal *pPoliceGoal = dynamic_cast(pGoal); - - if ( pPoliceGoal == NULL ) - { - DevMsg( "SetPoliceGoal: %s (%s)'s target %s is not an ai_goal_police entity!\n", GetClassname(), GetDebugName(), inputdata.value.String() ); - return; - } - - m_PolicingBehavior.Enable( pPoliceGoal ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::InputActivateBaton( inputdata_t &inputdata ) -{ - SetBatonState( inputdata.value.Bool() ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::AlertSound( void ) -{ - m_Sentences.Speak( "METROPOLICE_GO_ALERT" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::DeathSound( const CTakeDamageInfo &info ) -{ - if ( IsOnFire() ) - return; - - m_Sentences.Speak( "METROPOLICE_DIE", SENTENCE_PRIORITY_INVALID, SENTENCE_CRITERIA_ALWAYS ); -} - - -//----------------------------------------------------------------------------- -// Purpose: implemented by subclasses to give them an opportunity to make -// a sound when they lose their enemy -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::LostEnemySound( void) -{ - // Don't announce enemies when the player isn't a criminal - if ( !PlayerIsCriminal() ) - return; - - if ( gpGlobals->curtime <= m_flNextLostSoundTime ) - return; - - const char *pSentence; - if (!(CBaseEntity*)GetEnemy() || gpGlobals->curtime - GetEnemyLastTimeSeen() > 10) - { - pSentence = "METROPOLICE_LOST_LONG"; - } - else - { - pSentence = "METROPOLICE_LOST_SHORT"; - } - - if ( m_Sentences.Speak( pSentence ) >= 0 ) - { - m_flNextLostSoundTime = gpGlobals->curtime + random->RandomFloat(5.0,15.0); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: implemented by subclasses to give them an opportunity to make -// a sound when they lose their enemy -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::FoundEnemySound( void) -{ - // Don't announce enemies when I'm in arrest behavior - if ( HasSpawnFlags( SF_METROPOLICE_ARREST_ENEMY ) ) - return; - - m_Sentences.Speak( "METROPOLICE_REFIND_ENEMY", SENTENCE_PRIORITY_HIGH ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Indicates whether or not this npc should play an idle sound now. -//----------------------------------------------------------------------------- -bool CNPC_MetroPolice::ShouldPlayIdleSound( void ) -{ - // If someone is waiting for a response, then respond! - if ( ( m_NPCState == NPC_STATE_IDLE ) || ( m_NPCState == NPC_STATE_ALERT ) ) - { - if ( m_nIdleChatterType >= METROPOLICE_CHATTER_RESPONSE ) - return FOkToMakeSound(); - } - - return BaseClass::ShouldPlayIdleSound(); -} - - -//----------------------------------------------------------------------------- -// IdleSound -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::IdleSound( void ) -{ - bool bIsCriminal = PlayerIsCriminal(); - - // This happens when the NPC is waiting for his buddies to respond to him - switch( m_nIdleChatterType ) - { - case METROPOLICE_CHATTER_WAIT_FOR_RESPONSE: - break; - - case METROPOLICE_CHATTER_ASK_QUESTION: - { - if ( m_bPlayerIsNear && !HasMemory(bits_MEMORY_PLAYER_HARASSED) ) - { - if ( m_Sentences.Speak( "METROPOLICE_IDLE_HARASS_PLAYER", SENTENCE_PRIORITY_NORMAL, SENTENCE_CRITERIA_NORMAL ) >= 0 ) - { - Remember( bits_MEMORY_PLAYER_HARASSED ); - if ( GetSquad() ) - { - GetSquad()->SquadRemember(bits_MEMORY_PLAYER_HARASSED); - } - } - return; - } - - if ( !random->RandomInt(0,1) ) - break; - - int nQuestionType = random->RandomInt( 0, METROPOLICE_CHATTER_RESPONSE_TYPE_COUNT ); - if ( !IsInSquad() || ( nQuestionType == METROPOLICE_CHATTER_RESPONSE_TYPE_COUNT ) ) - { - m_Sentences.Speak( bIsCriminal ? "METROPOLICE_IDLE_CR" : "METROPOLICE_IDLE" ); - break; - } - - static const char *pQuestion[2][METROPOLICE_CHATTER_RESPONSE_TYPE_COUNT] = - { - { "METROPOLICE_IDLE_CHECK", "METROPOLICE_IDLE_QUEST" }, - { "METROPOLICE_IDLE_CHECK_CR", "METROPOLICE_IDLE_QUEST_CR" }, - }; - - if ( m_Sentences.Speak( pQuestion[bIsCriminal][nQuestionType] ) >= 0 ) - { - GetSquad()->BroadcastInteraction( g_interactionMetrocopIdleChatter, (void*)(METROPOLICE_CHATTER_RESPONSE + nQuestionType), this ); - m_nIdleChatterType = METROPOLICE_CHATTER_WAIT_FOR_RESPONSE; - } - } - break; - - default: - { - int nResponseType = m_nIdleChatterType - METROPOLICE_CHATTER_RESPONSE; - - static const char *pResponse[2][METROPOLICE_CHATTER_RESPONSE_TYPE_COUNT] = - { - { "METROPOLICE_IDLE_CLEAR", "METROPOLICE_IDLE_ANSWER" }, - { "METROPOLICE_IDLE_CLEAR_CR", "METROPOLICE_IDLE_ANSWER_CR" }, - }; - - if ( m_Sentences.Speak( pResponse[bIsCriminal][nResponseType] ) >= 0 ) - { - GetSquad()->BroadcastInteraction( g_interactionMetrocopIdleChatter, (void*)(METROPOLICE_CHATTER_ASK_QUESTION), this ); - m_nIdleChatterType = METROPOLICE_CHATTER_ASK_QUESTION; - } - } - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::PainSound( const CTakeDamageInfo &info ) -{ - if ( gpGlobals->curtime < m_flNextPainSoundTime ) - return; - - // Don't make pain sounds if I'm on fire. The looping sound will take care of that for us. - if ( IsOnFire() ) - return; - - float healthRatio = (float)GetHealth() / (float)GetMaxHealth(); - if ( healthRatio > 0.0f ) - { - const char *pSentenceName = "METROPOLICE_PAIN"; - if ( !HasMemory(bits_MEMORY_PAIN_HEAVY_SOUND) && (healthRatio < 0.25f) ) - { - Remember( bits_MEMORY_PAIN_HEAVY_SOUND | bits_MEMORY_PAIN_LIGHT_SOUND ); - pSentenceName = "METROPOLICE_PAIN_HEAVY"; - } - else if ( !HasMemory(bits_MEMORY_PAIN_LIGHT_SOUND) && healthRatio > 0.8f ) - { - Remember( bits_MEMORY_PAIN_LIGHT_SOUND ); - pSentenceName = "METROPOLICE_PAIN_LIGHT"; - } - - // This causes it to speak it no matter what; doesn't bother with setting sounds. - m_Sentences.Speak( pSentenceName, SENTENCE_PRIORITY_INVALID, SENTENCE_CRITERIA_ALWAYS ); - m_flNextPainSoundTime = gpGlobals->curtime + 1; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_MetroPolice::GetSoundInterests( void ) -{ - return SOUND_WORLD | SOUND_COMBAT | SOUND_PLAYER | SOUND_PLAYER_VEHICLE | SOUND_DANGER | - SOUND_PHYSICS_DANGER | SOUND_BULLET_IMPACT | SOUND_MOVE_AWAY; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CNPC_MetroPolice::MaxYawSpeed( void ) -{ - switch( GetActivity() ) - { - case ACT_TURN_LEFT: - case ACT_TURN_RIGHT: - return 120; - - case ACT_RUN: - case ACT_RUN_HURT: - return 15; - - case ACT_WALK: - case ACT_WALK_CROUCH: - case ACT_RUN_CROUCH: - return 25; - - default: - return 45; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -Class_T CNPC_MetroPolice::Classify ( void ) -{ - return CLASS_METROPOLICE; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_MetroPolice::PlayerIsCriminal( void ) -{ - if ( m_PolicingBehavior.IsEnabled() && m_PolicingBehavior.TargetIsHostile() ) - return true; - - if ( GlobalEntity_GetState( "gordon_precriminal" ) == GLOBAL_ON ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Overridden because if the player is a criminal, we hate them. -// Input : pTarget - Entity with which to determine relationship. -// Output : Returns relationship value. -//----------------------------------------------------------------------------- -Disposition_t CNPC_MetroPolice::IRelationType(CBaseEntity *pTarget) -{ - Disposition_t disp = BaseClass::IRelationType(pTarget); - - if ( pTarget == NULL ) - return disp; - - // If the player's not a criminal, then we don't necessary hate him - if ( pTarget->Classify() == CLASS_PLAYER ) - { - if ( !PlayerIsCriminal() && (disp == D_HT) ) - { - // If we're pissed at the player, we're allowed to hate them. - if ( m_flChasePlayerTime && m_flChasePlayerTime > gpGlobals->curtime ) - return D_HT; - return D_NU; - } - } - - return disp; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEvent - -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::OnAnimEventStartDeployManhack( void ) -{ - Assert( m_iManhacks ); - - if ( m_iManhacks <= 0 ) - { - DevMsg( "Error: Throwing manhack but out of manhacks!\n" ); - return; - } - - m_iManhacks--; - - // Turn off the manhack on our body - if ( m_iManhacks <= 0 ) - { - SetBodygroup( METROPOLICE_BODYGROUP_MANHACK, false ); - } - - // Create the manhack to throw - CNPC_Manhack *pManhack = (CNPC_Manhack *)CreateEntityByName( "npc_manhack" ); - - Vector vecOrigin; - QAngle vecAngles; - - int handAttachment = LookupAttachment( "LHand" ); - GetAttachment( handAttachment, vecOrigin, vecAngles ); - - pManhack->SetLocalOrigin( vecOrigin ); - pManhack->SetLocalAngles( vecAngles ); - pManhack->AddSpawnFlags( (SF_MANHACK_PACKED_UP|SF_MANHACK_CARRIED|SF_NPC_WAIT_FOR_SCRIPT) ); - - // Also fade if our parent is marked to do it - if ( HasSpawnFlags( SF_NPC_FADE_CORPSE ) ) - { - pManhack->AddSpawnFlags( SF_NPC_FADE_CORPSE ); - } - - pManhack->Spawn(); - - // Make us move with his hand until we're deployed - pManhack->SetParent( this, handAttachment ); - - m_hManhack = pManhack; -} - -//----------------------------------------------------------------------------- -// Anim event handlers -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::OnAnimEventDeployManhack( animevent_t *pEvent ) -{ - // Let it go - ReleaseManhack(); - - Vector forward, right; - GetVectors( &forward, &right, NULL ); - - IPhysicsObject *pPhysObj = m_hManhack->VPhysicsGetObject(); - - if ( pPhysObj ) - { - Vector yawOff = right * random->RandomFloat( -1.0f, 1.0f ); - - Vector forceVel = ( forward + yawOff * 16.0f ) + Vector( 0, 0, 250 ); - Vector forceAng = vec3_origin; - - // Give us velocity - pPhysObj->AddVelocity( &forceVel, &forceAng ); - } - - // Stop dealing with this manhack - m_hManhack = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::OnAnimEventShove( void ) -{ - CBaseEntity *pHurt = CheckTraceHullAttack( 16, Vector(-16,-16,-16), Vector(16,16,16), 15, DMG_CLUB, 1.0f, false ); - - if ( pHurt ) - { - Vector vecForceDir = ( pHurt->WorldSpaceCenter() - WorldSpaceCenter() ); - - CBasePlayer *pPlayer = ToBasePlayer( pHurt ); - - if ( pPlayer != NULL ) - { - //Kick the player angles - pPlayer->ViewPunch( QAngle( 8, 14, 0 ) ); - - Vector dir = pHurt->GetAbsOrigin() - GetAbsOrigin(); - VectorNormalize(dir); - - QAngle angles; - VectorAngles( dir, angles ); - Vector forward, right; - AngleVectors( angles, &forward, &right, NULL ); - - //If not on ground, then don't make them fly! - if ( !(pHurt->GetFlags() & FL_ONGROUND ) ) - forward.z = 0.0f; - - //Push the target back - pHurt->ApplyAbsVelocityImpulse( forward * 250.0f ); - - // Force the player to drop anyting they were holding - pPlayer->ForceDropOfCarriedPhysObjects(); - } - - // Play a random attack hit sound - EmitSound( "NPC_Metropolice.Shove" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::OnAnimEventBatonOn( void ) -{ -#ifndef HL2MP - - CWeaponStunStick *pStick = dynamic_cast(GetActiveWeapon()); - - if ( pStick ) - { - pStick->SetStunState( true ); - } -#endif - -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::OnAnimEventBatonOff( void ) -{ -#ifndef HL2MP - - CWeaponStunStick *pStick = dynamic_cast(GetActiveWeapon()); - - if ( pStick ) - { - pStick->SetStunState( false ); - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// Input : *pEvent - -// -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::HandleAnimEvent( animevent_t *pEvent ) -{ - // Shove! - if ( pEvent->event == AE_METROPOLICE_SHOVE ) - { - OnAnimEventShove(); - return; - } - - if ( pEvent->event == AE_METROPOLICE_BATON_ON ) - { - OnAnimEventBatonOn(); - return; - } - - if ( pEvent->event == AE_METROPOLICE_BATON_OFF ) - { - OnAnimEventBatonOff(); - return; - } - - if ( pEvent->event == AE_METROPOLICE_START_DEPLOY ) - { - OnAnimEventStartDeployManhack(); - return; - } - - if ( pEvent->event == AE_METROPOLICE_DRAW_PISTOL ) - { - m_fWeaponDrawn = true; - if( GetActiveWeapon() ) - { - GetActiveWeapon()->RemoveEffects( EF_NODRAW ); - } - return; - } - - if ( pEvent->event == AE_METROPOLICE_DEPLOY_MANHACK ) - { - OnAnimEventDeployManhack( pEvent ); - return; - } - - BaseClass::HandleAnimEvent( pEvent ); -} - - -//----------------------------------------------------------------------------- -// Purpose: This is a generic function (to be implemented by sub-classes) to -// handle specific interactions between different types of characters -// (For example the barnacle grabbing an NPC) -// Input : Constant for the type of interaction -// Output : true - if sub-class has a response for the interaction -// false - if sub-class has no response -//----------------------------------------------------------------------------- -bool CNPC_MetroPolice::HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt) -{ - if ( interactionType == g_interactionMetrocopStartedStitch ) - { - // If anybody in our squad started a stitch, we can't for a little while - m_flValidStitchTime = gpGlobals->curtime + random->RandomFloat( METROPOLICE_SQUAD_STITCH_MIN_INTERVAL, METROPOLICE_SQUAD_STITCH_MAX_INTERVAL ); - return true; - } - - if ( interactionType == g_interactionMetrocopIdleChatter ) - { - m_nIdleChatterType = (int)data; - return true; - } - - if ( interactionType == g_interactionMetrocopClearSentenceQueues ) - { - m_Sentences.ClearQueue(); - return true; - } - - // React to being hit by physics objects - if ( interactionType == g_interactionHitByPlayerThrownPhysObj ) - { - // Ignore if I'm in scripted state - if ( !IsInAScript() && (m_NPCState != NPC_STATE_SCRIPT) ) - { - SetCondition( COND_METROPOLICE_PHYSOBJECT_ASSAULT ); - } - else - { - AdministerJustice(); - } - - // See if the object is the cupcop can. If so, fire the output (for x360 achievement) - CBaseProp *pProp = (CBaseProp*)data; - if( pProp != NULL ) - { - if( pProp->NameMatches("cupcop_can") ) - m_OnCupCopped.FireOutput( this, NULL ); - } - - return true; - } - - return BaseClass::HandleInteraction( interactionType, data, sourceEnt ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Activity CNPC_MetroPolice::NPC_TranslateActivity( Activity newActivity ) -{ - if( IsOnFire() && newActivity == ACT_RUN ) - { - return ACT_RUN_ON_FIRE; - } - - // If we're shoving, see if we should be more forceful in doing so - if ( newActivity == ACT_PUSH_PLAYER ) - { - if ( m_nNumWarnings >= METROPOLICE_MAX_WARNINGS ) - return ACT_MELEE_ATTACK1; - } - - newActivity = BaseClass::NPC_TranslateActivity( newActivity ); - - // This will put him into an angry idle, which will then be translated - // by the weapon to the appropriate type. - if ( m_fWeaponDrawn && newActivity == ACT_IDLE && ( GetState() == NPC_STATE_COMBAT || BatonActive() ) ) - { - newActivity = ACT_IDLE_ANGRY; - } - - return newActivity; -} - -//----------------------------------------------------------------------------- -// Purpose: Makes the held manhack solid -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::ReleaseManhack( void ) -{ - Assert( m_hManhack ); - - // Make us physical - m_hManhack->RemoveSpawnFlags( SF_MANHACK_CARRIED ); - m_hManhack->CreateVPhysics(); - - // Release us - m_hManhack->RemoveSolidFlags( FSOLID_NOT_SOLID ); - m_hManhack->SetMoveType( MOVETYPE_VPHYSICS ); - m_hManhack->SetParent( NULL ); - - // Make us active - m_hManhack->RemoveSpawnFlags( SF_NPC_WAIT_FOR_SCRIPT ); - m_hManhack->ClearSchedule( "Manhack released by metropolice" ); - - // Start him with knowledge of our current enemy - if ( GetEnemy() ) - { - m_hManhack->SetEnemy( GetEnemy() ); - m_hManhack->SetState( NPC_STATE_COMBAT ); - - m_hManhack->UpdateEnemyMemory( GetEnemy(), GetEnemy()->GetAbsOrigin() ); - } - - // Place him into our squad so we can communicate - if ( m_pSquad ) - { - m_pSquad->AddToSquad( m_hManhack ); - } -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::Event_Killed( const CTakeDamageInfo &info ) -{ - // Release the manhack if we're in the middle of deploying him - if ( m_hManhack && m_hManhack->IsAlive() ) - { - ReleaseManhack(); - m_hManhack = NULL; - } - - CBasePlayer *pPlayer = ToBasePlayer( info.GetAttacker() ); - - if ( pPlayer != NULL ) - { - CHalfLife2 *pHL2GameRules = static_cast(g_pGameRules); - - // Attempt to drop health - if ( pHL2GameRules->NPC_ShouldDropHealth( pPlayer ) ) - { - DropItem( "item_healthvial", WorldSpaceCenter()+RandomVector(-4,4), RandomAngle(0,360) ); - pHL2GameRules->NPC_DroppedHealth(); - } - } - - BaseClass::Event_Killed( info ); -} - -//----------------------------------------------------------------------------- -// Try to enter a slot where we shoot a pistol -//----------------------------------------------------------------------------- -bool CNPC_MetroPolice::TryToEnterPistolSlot( int nSquadSlot ) -{ - // This logic here will not allow us to occupy the a squad slot - // too soon after we already were in it. - if ( ( m_LastShootSlot != nSquadSlot || !m_TimeYieldShootSlot.Expired() ) && - OccupyStrategySlot( nSquadSlot ) ) - { - if ( m_LastShootSlot != nSquadSlot ) - { - m_TimeYieldShootSlot.Reset(); - m_LastShootSlot = nSquadSlot; - } - return true; - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Combat schedule selection -//----------------------------------------------------------------------------- -int CNPC_MetroPolice::SelectRangeAttackSchedule() -{ - if ( HasSpawnFlags( SF_METROPOLICE_ALWAYS_STITCH ) ) - { - int nSched = SelectMoveToLedgeSchedule(); - if ( nSched != SCHED_NONE ) - return nSched; - } - - // Range attack if we're able - if( TryToEnterPistolSlot( SQUAD_SLOT_ATTACK1 ) || TryToEnterPistolSlot( SQUAD_SLOT_ATTACK2 )) - return SCHED_RANGE_ATTACK1; - - // We're not in a shoot slot... so we've allowed someone else to grab it - m_LastShootSlot = SQUAD_SLOT_NONE; - - if( CanDeployManhack() && OccupyStrategySlot( SQUAD_SLOT_POLICE_DEPLOY_MANHACK ) ) - { - return SCHED_METROPOLICE_DEPLOY_MANHACK; - } - - return SCHED_METROPOLICE_ADVANCE; -} - - -//----------------------------------------------------------------------------- -// How many squad members are trying to arrest the player? -//----------------------------------------------------------------------------- -int CNPC_MetroPolice::SquadArrestCount() -{ - int nCount = 0; - - AISquadIter_t iter; - CAI_BaseNPC *pSquadmate = m_pSquad->GetFirstMember( &iter ); - while ( pSquadmate ) - { - if ( pSquadmate->IsCurSchedule( SCHED_METROPOLICE_ARREST_ENEMY ) || - pSquadmate->IsCurSchedule( SCHED_METROPOLICE_WARN_AND_ARREST_ENEMY ) ) - { - ++nCount; - } - - pSquadmate = m_pSquad->GetNextMember( &iter ); - } - - return nCount; -} - - -//----------------------------------------------------------------------------- -// Arrest schedule selection -//----------------------------------------------------------------------------- -int CNPC_MetroPolice::SelectScheduleArrestEnemy() -{ - if ( !HasSpawnFlags( SF_METROPOLICE_ARREST_ENEMY ) || !IsInSquad() ) - return SCHED_NONE; - - if ( !HasCondition( COND_SEE_ENEMY ) ) - return SCHED_NONE; - - if ( !m_fWeaponDrawn ) - return SCHED_METROPOLICE_DRAW_PISTOL; - - // First guy that sees the enemy will tell him to freeze - if ( OccupyStrategySlot( SQUAD_SLOT_POLICE_ARREST_ENEMY ) ) - return SCHED_METROPOLICE_WARN_AND_ARREST_ENEMY; - - // Squad members 1 -> n will simply gain a line of sight - return SCHED_METROPOLICE_ARREST_ENEMY; -} - - -//----------------------------------------------------------------------------- -// Combat schedule selection -//----------------------------------------------------------------------------- -int CNPC_MetroPolice::SelectScheduleNewEnemy() -{ - int nSched = SelectScheduleArrestEnemy(); - if ( nSched != SCHED_NONE ) - return nSched; - - if ( HasCondition( COND_NEW_ENEMY ) ) - { - m_flNextLedgeCheckTime = gpGlobals->curtime; - - if( CanDeployManhack() && OccupyStrategySlot( SQUAD_SLOT_POLICE_DEPLOY_MANHACK ) ) - return SCHED_METROPOLICE_DEPLOY_MANHACK; - } - - if ( !m_fWeaponDrawn ) - return SCHED_METROPOLICE_DRAW_PISTOL; - - // Switch our baton on, if it's not already - if ( HasBaton() && BatonActive() == false && IsCurSchedule( SCHED_METROPOLICE_ACTIVATE_BATON ) == false ) - { - SetTarget( GetEnemy() ); - SetBatonState( true ); - m_flBatonDebounceTime = gpGlobals->curtime + random->RandomFloat( 2.5f, 4.0f ); - return SCHED_METROPOLICE_ACTIVATE_BATON; - } - - return SCHED_NONE; -} - - -//----------------------------------------------------------------------------- -// Sound investigation -//----------------------------------------------------------------------------- -int CNPC_MetroPolice::SelectScheduleInvestigateSound() -{ - // SEE_ENEMY is set if LOS is available *and* we're looking the right way - // Don't investigate if the player's not a criminal. - if ( PlayerIsCriminal() && !HasCondition( COND_SEE_ENEMY ) ) - { - if ( HasCondition( COND_HEAR_COMBAT ) || HasCondition( COND_HEAR_PLAYER ) ) - { - if ( m_pSquad && OccupyStrategySlot( SQUAD_SLOT_INVESTIGATE_SOUND ) ) - { - return SCHED_METROPOLICE_INVESTIGATE_SOUND; - } - } - } - - return SCHED_NONE; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_MetroPolice::OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) -{ - if ( pMoveGoal->directTrace.pObstruction ) - { - // Is it a physics prop? Store it off as the last thing to block me - CPhysicsProp *pProp = dynamic_cast( pMoveGoal->directTrace.pObstruction ); - if ( pProp && pProp->GetHealth() ) - { - m_hBlockingProp = pProp; - } - else - { - m_hBlockingProp = NULL; - } - } - - return BaseClass::OnObstructionPreSteer( pMoveGoal, distClear, pResult ); -} - -//----------------------------------------------------------------------------- -// Combat schedule selection -//----------------------------------------------------------------------------- -int CNPC_MetroPolice::SelectScheduleNoDirectEnemy() -{ - // If you can't attack, but you can deploy a manhack, do it! - if( CanDeployManhack() && OccupyStrategySlot( SQUAD_SLOT_POLICE_DEPLOY_MANHACK ) ) - return SCHED_METROPOLICE_DEPLOY_MANHACK; - - // If you can't attack, but you have a baton & there's a physics object in front of you, swat it - if ( m_hBlockingProp && HasBaton() ) - { - SetTarget( m_hBlockingProp ); - m_hBlockingProp = NULL; - return SCHED_METROPOLICE_SMASH_PROP; - } - - return SCHED_METROPOLICE_CHASE_ENEMY; -} - - -//----------------------------------------------------------------------------- -// Combat schedule selection -//----------------------------------------------------------------------------- -int CNPC_MetroPolice::SelectCombatSchedule() -{ - // Announce a new enemy - if ( HasCondition( COND_NEW_ENEMY ) ) - { - AnnounceEnemyType( GetEnemy() ); - } - - int nResult = SelectScheduleNewEnemy(); - if ( nResult != SCHED_NONE ) - return nResult; - - if( !m_fWeaponDrawn ) - { - return SCHED_METROPOLICE_DRAW_PISTOL; - } - - if (!HasBaton() && ((float)m_nRecentDamage / (float)GetMaxHealth()) > RECENT_DAMAGE_THRESHOLD) - { - m_nRecentDamage = 0; - m_flRecentDamageTime = 0; - m_Sentences.Speak( "METROPOLICE_COVER_HEAVY_DAMAGE", SENTENCE_PRIORITY_MEDIUM, SENTENCE_CRITERIA_NORMAL ); - - return SCHED_TAKE_COVER_FROM_ENEMY; - } - - if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - { - if ( !GetShotRegulator()->IsInRestInterval() ) - return SelectRangeAttackSchedule(); - else - return SCHED_METROPOLICE_ADVANCE; - } - - if ( HasCondition( COND_CAN_MELEE_ATTACK1 ) ) - { - if ( m_BatonSwingTimer.Expired() ) - { - // Stop chasing the player now that we've taken a swing at them - m_flChasePlayerTime = 0; - m_BatonSwingTimer.Set( 1.0, 1.75 ); - return SCHED_MELEE_ATTACK1; - } - else - return SCHED_COMBAT_FACE; - } - - if ( HasCondition( COND_TOO_CLOSE_TO_ATTACK ) ) - { - return SCHED_BACK_AWAY_FROM_ENEMY; - } - - if ( HasCondition( COND_LOW_PRIMARY_AMMO ) || HasCondition( COND_NO_PRIMARY_AMMO ) ) - { - AnnounceOutOfAmmo( ); - return SCHED_HIDE_AND_RELOAD; - } - - if ( HasCondition(COND_WEAPON_SIGHT_OCCLUDED) && !HasBaton() ) - { - // If they are hiding behind something that we can destroy, start shooting at it. - CBaseEntity *pBlocker = GetEnemyOccluder(); - if ( pBlocker && pBlocker->GetHealth() > 0 && OccupyStrategySlotRange( SQUAD_SLOT_POLICE_ATTACK_OCCLUDER1, SQUAD_SLOT_POLICE_ATTACK_OCCLUDER2 ) ) - { - m_Sentences.Speak( "METROPOLICE_SHOOT_COVER" ); - return SCHED_SHOOT_ENEMY_COVER; - } - } - - if (HasCondition(COND_ENEMY_OCCLUDED)) - { - if ( GetEnemy() && !(GetEnemy()->GetFlags() & FL_NOTARGET) ) - { - // Charge in and break the enemy's cover! - return SCHED_ESTABLISH_LINE_OF_FIRE; - } - } - - nResult = SelectScheduleNoDirectEnemy(); - if ( nResult != SCHED_NONE ) - return nResult; - - return SCHED_NONE; -} - -//----------------------------------------------------------------------------- -// Purpose: This is a bridge between stunstick, NPC and its behavior -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_MetroPolice::ShouldKnockOutTarget( CBaseEntity *pTarget ) -{ - if ( m_PolicingBehavior.IsEnabled() && m_PolicingBehavior.ShouldKnockOutTarget( pTarget ) ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: This is a bridge between stunstick, NPC and its behavior -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::KnockOutTarget( CBaseEntity *pTarget ) -{ - if ( m_PolicingBehavior.IsEnabled() ) - { - m_PolicingBehavior.KnockOutTarget( pTarget ); - } -} - -//----------------------------------------------------------------------------- -// Can me enemy see me? -//----------------------------------------------------------------------------- -bool CNPC_MetroPolice::CanEnemySeeMe( ) -{ - if ( GetEnemy()->IsPlayer() ) - { - if ( static_cast(GetEnemy())->FInViewCone( this ) ) - { - return true; - } - } - return false; -} - - -//----------------------------------------------------------------------------- -// Choose weights about where we can use particular stitching behaviors -//----------------------------------------------------------------------------- -#define STITCH_MIN_DISTANCE 1000.0f -#define STITCH_MIN_DISTANCE_SLOW 1250.0f - -#define STITCH_AT_CONE 0.866f // cos(30) -#define STITCH_AT_CONE_WHEN_VISIBLE_MAX 0.3f // cos(?) -#define STITCH_AT_CONE_WHEN_VISIBLE_MIN 0.707f // cos(45) -#define STITCH_AT_COS_MIN_SPIN_ANGLE 0.2f - -float CNPC_MetroPolice::StitchAtWeight( float flDist, float flSpeed, float flDot, float flReactionTime, const Vector &vecTargetToGun ) -{ - // Can't do an 'attacking' stitch if it's too soon - if ( m_flValidStitchTime > gpGlobals->curtime ) - return 0.0f; - - // No squad slots? no way. - if( IsStrategySlotRangeOccupied( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - return false; - - // Don't do it if the player doesn't have enough time to react - if ( flDist < STITCH_MIN_DISTANCE ) - return 0.0f; - - // Don't do it if the player is farther but really slow - if ( ( flDist < STITCH_MIN_DISTANCE_SLOW ) && ( flSpeed < 150.0f ) ) - return 0.0f; - - // Does the predicted stitch position cross the plane from me to the target's initial position? - // If so, it'll look really dumb. Disallow that. - Vector vecGunToPredictedTarget, vecShootAtVel; - PredictShootTargetPosition( flReactionTime, 0.0f, 0.0f, &vecGunToPredictedTarget, &vecShootAtVel ); - vecGunToPredictedTarget -= Weapon_ShootPosition(); - vecGunToPredictedTarget.z = 0.0f; - VectorNormalize( vecGunToPredictedTarget ); - - Vector2D vecGunToTarget; - Vector2DMultiply( vecTargetToGun.AsVector2D(), -1.0f, vecGunToTarget ); - Vector2DNormalize( vecGunToTarget ); - if ( DotProduct2D( vecGunToTarget, vecGunToPredictedTarget.AsVector2D() ) <= STITCH_AT_COS_MIN_SPIN_ANGLE ) - return 0.0f; - - // If the cop is in the view cone, then up the cone in which the stitch will occur - float flConeAngle = STITCH_AT_CONE; - if ( CanEnemySeeMe() ) - { - flDist = clamp( flDist, 1500.0f, 2500.0f ); - flConeAngle = RemapVal( flDist, 1500.0f, 2500.0f, STITCH_AT_CONE_WHEN_VISIBLE_MIN, STITCH_AT_CONE_WHEN_VISIBLE_MAX ); - } - - flDot = clamp( flDot, -1.0f, flConeAngle ); - return RemapVal( flDot, -1.0f, flConeAngle, 0.5f, 1.0f ); -} - - -#define STITCH_ACROSS_CONE 0.5f // cos(60) - -float CNPC_MetroPolice::StitchAcrossWeight( float flDist, float flSpeed, float flDot, float flReactionTime ) -{ - return 0.0f; - - // Can't do an 'attacking' stitch if it's too soon - if ( m_flValidStitchTime > gpGlobals->curtime ) - return 0.0f; - - // No squad slots? no way. - if( IsStrategySlotRangeOccupied( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - return 0.0f; - - if ( flDist < STITCH_MIN_DISTANCE ) - return 0.0f; - - // Don't do it if the player doesn't have enough time to react - if ( flDist < flSpeed * flReactionTime ) - return 0.0f; - - // We want to stitch across if we're within the stitch across cone - if ( flDot < STITCH_ACROSS_CONE ) - return 0.0f; - - return 1.0f; -} - - -#define STITCH_ALONG_MIN_CONE 0.866f // cos(30) -#define STITCH_ALONG_MIN_CONE_WHEN_VISIBLE 0.707f // cos(45) -#define STITCH_ALONG_MAX_CONE -0.4f // -#define STITCH_ALONG_MIN_SPEED 300.0f - -float CNPC_MetroPolice::StitchAlongSideWeight( float flDist, float flSpeed, float flDot ) -{ - // No squad slots? no way. - if( IsStrategySlotRangeOccupied( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) && - IsStrategySlotRangeOccupied( SQUAD_SLOT_POLICE_COVERING_FIRE1, SQUAD_SLOT_POLICE_COVERING_FIRE2 ) ) - return 0.0f; - - if ( flDist < (AIM_ALONG_SIDE_LINE_OF_DEATH_DISTANCE + AIM_ALONG_SIDE_STEER_DISTANCE + 100.0f) ) - return 0.0f; - - if ( flSpeed < STITCH_ALONG_MIN_SPEED ) - return 0.0f; - - // We want to stitch across if we're within the stitch across cone - float flMinConeAngle = STITCH_ALONG_MIN_CONE; - bool bCanEnemySeeMe = CanEnemySeeMe( ); - if ( bCanEnemySeeMe ) - { - flMinConeAngle = STITCH_ALONG_MIN_CONE_WHEN_VISIBLE; - } - - if (( flDot > flMinConeAngle ) || ( flDot < STITCH_ALONG_MAX_CONE )) - return 0.0f; - - return bCanEnemySeeMe ? 1.0f : 2.0f; -} - -#define STITCH_BEHIND_MIN_CONE 0.0f // cos(90) - -float CNPC_MetroPolice::StitchBehindWeight( float flDist, float flSpeed, float flDot ) -{ - return 0.0f; - - // No squad slots? no way. - if( IsStrategySlotRangeOccupied( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) && - IsStrategySlotRangeOccupied( SQUAD_SLOT_POLICE_COVERING_FIRE1, SQUAD_SLOT_POLICE_COVERING_FIRE2 ) ) - return 0.0f; - - if ( flDist < AIM_BEHIND_MINIMUM_DISTANCE ) - return 0.0f; - - // We want to stitch across if we're within the stitch across cone - if ( flDot > STITCH_BEHIND_MIN_CONE ) - return 0.0f; - - // If we're close, reduce the chances of this if we're also slow - if ( flDist < STITCH_MIN_DISTANCE ) - { - flSpeed = clamp( flSpeed, 300.0f, 450.0f ); - float flWeight = RemapVal( flSpeed, 300.0f, 450.0f, 0.0f, 1.0f ); - return flWeight; - } - - return 1.0f; -} - -float CNPC_MetroPolice::StitchTightWeight( float flDist, float flSpeed, const Vector &vecTargetToGun, const Vector &vecVelocity ) -{ - // No squad slots? no way. - if( IsStrategySlotRangeOccupied( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) && - IsStrategySlotRangeOccupied( SQUAD_SLOT_POLICE_COVERING_FIRE1, SQUAD_SLOT_POLICE_COVERING_FIRE2 ) ) - return 0.0f; - - if ( flDist > STITCH_MIN_DISTANCE ) - { - if ( flDist > 2000.0f ) - return 0.0f; - - // We can stitch tight if they are close and no other rules apply. - return 0.0001f; - } - - // If we're heading right at him, them fire it! - Vector vecTargetToGunDir = vecTargetToGun; - Vector vecVelocityDir = vecVelocity; - VectorNormalize( vecTargetToGunDir ); - VectorNormalize( vecVelocityDir ); - - if ( DotProduct( vecTargetToGunDir, vecVelocityDir ) > 0.95f ) - return 8.0f; - - // If we're on the same level, fire at him! - if ( ( fabs(vecTargetToGun.z) < 50.0f ) && ( flDist < STITCH_MIN_DISTANCE ) ) - return 1.0f; - - flSpeed = clamp( flSpeed, 300.0f, 450.0f ); - float flWeight = RemapVal( flSpeed, 300.0f, 450.0f, 1.0f, 0.0f ); - return flWeight; -} - - -//----------------------------------------------------------------------------- -// Combat schedule selection -//----------------------------------------------------------------------------- -#define STITCH_REACTION_TIME 2.0f -#define STITCH_SCHEDULE_COUNT 5 - -int CNPC_MetroPolice::SelectStitchSchedule() -{ - // If the boat is very close to us, we're going to stitch at it - // even if the squad slot is full.. - Vector vecTargetToGun; - Vector vecTarget = StitchAimTarget( GetAbsOrigin(), false ); - VectorSubtract( Weapon_ShootPosition(), vecTarget, vecTargetToGun ); - - Vector2D vecTargetToGun2D = vecTargetToGun.AsVector2D(); - float flDist = Vector2DNormalize( vecTargetToGun2D ); - - if ( HasSpawnFlags( SF_METROPOLICE_NO_FAR_STITCH ) ) - { - if ( flDist > 6000.0f ) - return SCHED_NONE; - } - - float flReactionTime = STITCH_REACTION_TIME * sk_metropolice_stitch_reaction.GetFloat(); - Vector vecVelocity; - PredictShootTargetVelocity( flReactionTime, &vecVelocity ); - - Vector2D vecVelocity2D = vecVelocity.AsVector2D(); - float flSpeed = Vector2DNormalize( vecVelocity2D ); - float flDot = DotProduct2D( vecTargetToGun2D, vecVelocity2D ); - - float flWeight[STITCH_SCHEDULE_COUNT]; - flWeight[0] = StitchAtWeight( flDist, flSpeed, flDot, flReactionTime, vecTargetToGun ); - flWeight[1] = flWeight[0] + StitchAcrossWeight( flDist, flSpeed, flDot, flReactionTime ); - flWeight[2] = flWeight[1] + StitchTightWeight( flDist, flSpeed, vecTargetToGun, vecVelocity ); - flWeight[3] = flWeight[2] + StitchAlongSideWeight( flDist, flSpeed, flDot ); - flWeight[4] = flWeight[3] + StitchBehindWeight( flDist, flSpeed, flDot ); - - if ( flWeight[STITCH_SCHEDULE_COUNT - 1] == 0.0f ) - return SCHED_NONE; - - int pSched[STITCH_SCHEDULE_COUNT] = - { - SCHED_METROPOLICE_AIM_STITCH_AT_AIRBOAT, - SCHED_METROPOLICE_AIM_STITCH_IN_FRONT_OF_AIRBOAT, - SCHED_METROPOLICE_AIM_STITCH_TIGHTLY, - SCHED_METROPOLICE_AIM_STITCH_ALONG_SIDE_OF_AIRBOAT, - SCHED_METROPOLICE_AIM_STITCH_BEHIND_AIRBOAT, - }; - - int i; - float flRand = random->RandomFloat( 0.0f, flWeight[STITCH_SCHEDULE_COUNT - 1] ); - for ( i = 0; i < STITCH_SCHEDULE_COUNT; ++i ) - { - if ( flRand <= flWeight[i] ) - break; - } - - // If we're basically a covering activity, take up that slot - if ( i >= 3 ) - { - if( OccupyStrategySlotRange( SQUAD_SLOT_POLICE_COVERING_FIRE1, SQUAD_SLOT_POLICE_COVERING_FIRE2 ) ) - { - return pSched[i]; - } - } - - if( OccupyStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - { - if ( IsInSquad() && (i < 2) ) - { - GetSquad()->BroadcastInteraction( g_interactionMetrocopStartedStitch, NULL ); - } - - return pSched[i]; - } - - return SCHED_NONE; -} - - -//----------------------------------------------------------------------------- -// Combat schedule selection -//----------------------------------------------------------------------------- -int CNPC_MetroPolice::SelectMoveToLedgeSchedule() -{ - // Prevent a bunch of unnecessary raycasts. - if ( m_flNextLedgeCheckTime > gpGlobals->curtime ) - return SCHED_NONE; - - // If the NPC is above the airboat (say, on a bridge), make sure he - // goes to the closest ledge. (may need a spawnflag for this) - if ( (GetAbsOrigin().z - GetShootTarget()->GetAbsOrigin().z) >= 150.0f ) - { - m_flNextLedgeCheckTime = gpGlobals->curtime + 3.0f; - - // We need to be able to shoot downward at a 60 degree angle. - Vector vecDelta; - VectorSubtract( GetShootTarget()->WorldSpaceCenter(), Weapon_ShootPosition(), vecDelta ); - vecDelta.z = 0.0f; - VectorNormalize( vecDelta ); - - // At this point, vecDelta is 45 degrees below horizontal. - vecDelta.z = -1; - vecDelta *= 100.0f; - - trace_t tr; - CTraceFilterWorldOnly traceFilter; - UTIL_TraceLine( Weapon_ShootPosition(), Weapon_ShootPosition() + vecDelta, MASK_SOLID, &traceFilter, &tr ); - - if (tr.endpos.z >= GetAbsOrigin().z - 25.0f ) - return SCHED_METROPOLICE_ESTABLISH_STITCH_LINE_OF_FIRE; - } - - return SCHED_NONE; -} - - -//----------------------------------------------------------------------------- -// Combat schedule selection -//----------------------------------------------------------------------------- -int CNPC_MetroPolice::SelectAirboatRangeAttackSchedule() -{ - // Move to a ledge, if we need to. - int nSched = SelectMoveToLedgeSchedule(); - if ( nSched != SCHED_NONE ) - return nSched; - - if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - { - nSched = SelectStitchSchedule(); - if ( nSched != SCHED_NONE ) - { - m_LastShootSlot = SQUAD_SLOT_NONE; - return nSched; - } - } - - if( CanDeployManhack() && OccupyStrategySlot( SQUAD_SLOT_POLICE_DEPLOY_MANHACK ) ) - { - return SCHED_METROPOLICE_DEPLOY_MANHACK; - } - - return SCHED_METROPOLICE_ESTABLISH_LINE_OF_FIRE; -} - - -//----------------------------------------------------------------------------- -// Combat schedule selection for when the enemy is in an airboat -//----------------------------------------------------------------------------- -int CNPC_MetroPolice::SelectAirboatCombatSchedule() -{ - int nResult = SelectScheduleNewEnemy(); - if ( nResult != SCHED_NONE ) - return nResult; - - // We're assuming here that the cops who attack airboats have SMGs -// Assert( Weapon_OwnsThisType( "weapon_smg1" ) ); - - if ( HasCondition( COND_SEE_ENEMY ) ) - { - return SelectAirboatRangeAttackSchedule(); - } - - if ( HasCondition( COND_WEAPON_SIGHT_OCCLUDED ) ) - { - // If they are hiding behind something also attack. Don't bother - // shooting the destroyable thing; it'll happen anyways with the SMG - CBaseEntity *pBlocker = GetEnemyOccluder(); - if ( pBlocker && pBlocker->GetHealth() > 0 && OccupyStrategySlotRange( SQUAD_SLOT_POLICE_ATTACK_OCCLUDER1, SQUAD_SLOT_POLICE_ATTACK_OCCLUDER2 ) ) - { - return SelectAirboatRangeAttackSchedule(); - } - } - - nResult = SelectScheduleNoDirectEnemy(); - if ( nResult != SCHED_NONE ) - return nResult; - - return SCHED_NONE; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_MetroPolice::IsHeavyDamage( const CTakeDamageInfo &info ) -{ - // Metropolice considers bullet fire heavy damage - if ( info.GetDamageType() & DMG_BULLET ) - return true; - - return BaseClass::IsHeavyDamage( info ); -} - -//----------------------------------------------------------------------------- -// TraceAttack -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - // This is needed so we can keep track of the direction of the shot - // because we're going to use it to choose the flinch animation - if ( m_bSimpleCops ) - { - if ( m_takedamage == DAMAGE_YES ) - { - Vector vecLastHitDirection; - VectorIRotate( vecDir, EntityToWorldTransform(), vecLastHitDirection ); - - // Point *at* the shooter - vecLastHitDirection *= -1.0f; - - QAngle lastHitAngles; - VectorAngles( vecLastHitDirection, lastHitAngles ); - m_flLastHitYaw = lastHitAngles.y; - } - } - - BaseClass::TraceAttack( info, vecDir, ptr ); -} - -//----------------------------------------------------------------------------- -// Determines the best type of flinch anim to play. -//----------------------------------------------------------------------------- -Activity CNPC_MetroPolice::GetFlinchActivity( bool bHeavyDamage, bool bGesture ) -{ - if ( !bGesture && m_bSimpleCops ) - { - // Version for getting shot from behind - if ( ( m_flLastHitYaw > 90 ) && ( m_flLastHitYaw < 270 ) ) - { - Activity flinchActivity = (Activity)ACT_METROPOLICE_FLINCH_BEHIND; - if ( SelectWeightedSequence ( flinchActivity ) != ACTIVITY_NOT_AVAILABLE ) - return flinchActivity; - } - - if ( ( LastHitGroup() == HITGROUP_CHEST ) || - ( LastHitGroup() == HITGROUP_LEFTLEG ) || - ( LastHitGroup() == HITGROUP_RIGHTLEG ) ) - { - Activity flinchActivity = ACT_FLINCH_STOMACH; - if ( SelectWeightedSequence ( ACT_FLINCH_STOMACH ) != ACTIVITY_NOT_AVAILABLE ) - return flinchActivity; - } - } - - return BaseClass::GetFlinchActivity( bHeavyDamage, bGesture ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::PlayFlinchGesture( void ) -{ - BaseClass::PlayFlinchGesture(); - - // To ensure old playtested difficulty stays the same, stop cops shooting for a bit after gesture flinches - GetShotRegulator()->FireNoEarlierThan( gpGlobals->curtime + 0.5 ); -} - -//----------------------------------------------------------------------------- -// We're taking cover from danger -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::AnnounceHarrassment( void ) -{ - static const char *pWarnings[3] = - { - "METROPOLICE_BACK_UP_A", - "METROPOLICE_BACK_UP_B", - "METROPOLICE_BACK_UP_C", - }; - - m_Sentences.Speak( pWarnings[ random->RandomInt( 0, ARRAYSIZE(pWarnings)-1 ) ], SENTENCE_PRIORITY_MEDIUM, SENTENCE_CRITERIA_NORMAL ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::IncrementPlayerCriminalStatus( void ) -{ - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); - - if ( pPlayer ) - { - AddLookTarget( pPlayer, 0.8f, 5.0f ); - - if ( m_nNumWarnings < METROPOLICE_MAX_WARNINGS ) - { - m_nNumWarnings++; - } - - if ( m_nNumWarnings >= (METROPOLICE_MAX_WARNINGS-1) ) - { - SetTarget( pPlayer ); - SetBatonState( true ); - } - } - - m_flBatonDebounceTime = gpGlobals->curtime + random->RandomFloat( 2.0f, 4.0f ); - - AnnounceHarrassment(); - - m_bKeepFacingPlayer = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CNPC_MetroPolice::SelectShoveSchedule( void ) -{ - IncrementPlayerCriminalStatus(); - - // Stop chasing the player now that we've taken a swing at them - m_flChasePlayerTime = 0; - return SCHED_METROPOLICE_SHOVE; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CNPC_MetroPolice::GetIdealAccel( void ) const -{ - return GetIdealSpeed() * 2.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: Chase after a player who's just pissed us off, and hit him -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::AdministerJustice( void ) -{ - if ( !AI_IsSinglePlayer() ) - return; - - // If we're allowed to chase the player, do so. Otherwise, just threaten. - if ( !IsInAScript() && (m_NPCState != NPC_STATE_SCRIPT) && HasSpawnFlags( SF_METROPOLICE_ALLOWED_TO_RESPOND ) ) - { - if ( m_vecPreChaseOrigin == vec3_origin ) - { - m_vecPreChaseOrigin = GetAbsOrigin(); - m_flPreChaseYaw = GetAbsAngles().y; - } - m_flChasePlayerTime = gpGlobals->curtime + RandomFloat( 3, 7 ); - - // Attack the target - CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); - SetEnemy( pPlayer ); - SetState( NPC_STATE_COMBAT ); - UpdateEnemyMemory( pPlayer, pPlayer->GetAbsOrigin() ); - } - else - { - // Watch the player for a time. - m_bKeepFacingPlayer = true; - - // Try and find a nearby cop to administer justice - CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); - int nAIs = g_AI_Manager.NumAIs(); - for ( int i = 0; i < nAIs; i++ ) - { - if ( ppAIs[i] == this ) - continue; - - if ( ppAIs[i]->Classify() == CLASS_METROPOLICE && FClassnameIs( ppAIs[i], "npc_metropolice" ) ) - { - CNPC_MetroPolice *pNPC = assert_cast(ppAIs[i]); - if ( pNPC->HasSpawnFlags( SF_METROPOLICE_ALLOWED_TO_RESPOND ) ) - { - // Is he within site & range? - if ( FVisible(pNPC) && pNPC->FVisible( UTIL_PlayerByIndex(1) ) && - UTIL_DistApprox( WorldSpaceCenter(), pNPC->WorldSpaceCenter() ) < 512 ) - { - pNPC->AdministerJustice(); - break; - } - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Schedule selection -//----------------------------------------------------------------------------- -int CNPC_MetroPolice::SelectSchedule( void ) -{ - if ( !GetEnemy() && HasCondition( COND_IN_PVS ) && AI_GetSinglePlayer() && !AI_GetSinglePlayer()->IsAlive() ) - { - return SCHED_PATROL_WALK; - } - - if ( HasCondition(COND_METROPOLICE_ON_FIRE) ) - { - m_Sentences.Speak( "METROPOLICE_ON_FIRE", SENTENCE_PRIORITY_INVALID, SENTENCE_CRITERIA_ALWAYS ); - return SCHED_METROPOLICE_BURNING_STAND; - } - - // React to being struck by a physics object - if ( HasCondition( COND_METROPOLICE_PHYSOBJECT_ASSAULT ) ) - { - ClearCondition( COND_METROPOLICE_PHYSOBJECT_ASSAULT ); - - // See which state our player relationship is in - if ( PlayerIsCriminal() == false ) - { - m_Sentences.Speak( "METROPOLICE_HIT_BY_PHYSOBJECT", SENTENCE_PRIORITY_INVALID, SENTENCE_CRITERIA_ALWAYS ); - m_nNumWarnings = METROPOLICE_MAX_WARNINGS; - AdministerJustice(); - } - else if ( GlobalEntity_GetState( "gordon_precriminal" ) == GLOBAL_ON ) - { - // We're not allowed to respond, but warn them - m_Sentences.Speak( "METROPOLICE_IDLE_HARASS_PLAYER", SENTENCE_PRIORITY_INVALID, SENTENCE_CRITERIA_ALWAYS ); - } - } - - int nSched = SelectFlinchSchedule(); - if ( nSched != SCHED_NONE ) - return nSched; - - if ( HasBaton() ) - { - // See if we're being told to activate our baton - if ( m_bShouldActivateBaton && BatonActive() == false && IsCurSchedule( SCHED_METROPOLICE_ACTIVATE_BATON ) == false ) - return SCHED_METROPOLICE_ACTIVATE_BATON; - - if ( m_bShouldActivateBaton == false && BatonActive() && IsCurSchedule( SCHED_METROPOLICE_DEACTIVATE_BATON ) == false ) - return SCHED_METROPOLICE_DEACTIVATE_BATON; - - if( metropolice_chase_use_follow.GetBool() ) - { - if( GetEnemy() ) - { - AI_FollowParams_t params; - params.formation = AIF_TIGHT; - m_FollowBehavior.SetParameters( params ); - m_FollowBehavior.SetFollowTarget( GetEnemy() ); - } - } - } - - // See if the player is in our face (unless we're scripting) - if ( PlayerIsCriminal() == false ) - { - if ( !IsInAScript() && (HasCondition( COND_METROPOLICE_PLAYER_TOO_CLOSE ) || m_bPlayerTooClose) ) - { - // Don't hit the player too many times in a row, unless he's trying to push a cop who hasn't moved - if ( m_iNumPlayerHits < 3 || m_vecPreChaseOrigin == vec3_origin ) - { - ClearCondition( COND_METROPOLICE_PLAYER_TOO_CLOSE ); - m_bPlayerTooClose = false; - - return SelectShoveSchedule(); - } - } - else if ( m_iNumPlayerHits ) - { - // If we're not in combat, and we've got a pre-chase origin, move back to it - if ( ( m_NPCState != NPC_STATE_COMBAT ) && - ( m_vecPreChaseOrigin != vec3_origin ) && - ( m_flChasePlayerTime < gpGlobals->curtime ) ) - { - return SCHED_METROPOLICE_RETURN_TO_PRECHASE; - } - } - } - - // Cower when physics objects are thrown at me - if ( HasCondition( COND_HEAR_PHYSICS_DANGER ) ) - { - if ( m_flLastPhysicsFlinchTime + 4.0f <= gpGlobals->curtime ) - { - m_flLastPhysicsFlinchTime = gpGlobals->curtime; - return SCHED_FLINCH_PHYSICS; - } - } - - // Always run for cover from danger sounds - if ( HasCondition(COND_HEAR_DANGER) ) - { - CSound *pSound; - pSound = GetBestSound(); - - Assert( pSound != NULL ); - if ( pSound ) - { - if (pSound->m_iType & SOUND_DANGER) - { - AnnounceTakeCoverFromDanger( pSound ); - return SCHED_TAKE_COVER_FROM_BEST_SOUND; - } - if (!HasCondition( COND_SEE_ENEMY ) && ( pSound->m_iType & (SOUND_PLAYER | SOUND_PLAYER_VEHICLE | SOUND_COMBAT) )) - { - GetMotor()->SetIdealYawToTarget( pSound->GetSoundReactOrigin() ); - } - } - } - - bool bHighHealth = ((float)GetHealth() / (float)GetMaxHealth() > 0.75f); - - // This will cause the cops to run backwards + shoot at the same time - if ( !bHighHealth && !HasBaton() ) - { - if ( GetActiveWeapon() && (GetActiveWeapon()->m_iClip1 <= 5) ) - { - m_Sentences.Speak( "METROPOLICE_COVER_LOW_AMMO" ); - return SCHED_HIDE_AND_RELOAD; - } - } - - if( HasCondition( COND_NO_PRIMARY_AMMO ) ) - { - if ( bHighHealth ) - return SCHED_RELOAD; - - AnnounceOutOfAmmo( ); - return SCHED_HIDE_AND_RELOAD; - } - - // If we're clubbing someone who threw something at us. chase them - if ( m_NPCState == NPC_STATE_COMBAT && m_flChasePlayerTime > gpGlobals->curtime ) - return SCHED_CHASE_ENEMY; - - if ( !BehaviorSelectSchedule() ) - { - // If we've warned the player at all, watch him like a hawk - if ( m_bKeepFacingPlayer && !PlayerIsCriminal() ) - return SCHED_TARGET_FACE; - - switch( m_NPCState ) - { - case NPC_STATE_IDLE: - { - nSched = SelectScheduleInvestigateSound(); - if ( nSched != SCHED_NONE ) - return nSched; - break; - } - - case NPC_STATE_ALERT: - { - nSched = SelectScheduleInvestigateSound(); - if ( nSched != SCHED_NONE ) - return nSched; - } - break; - - case NPC_STATE_COMBAT: - if (!IsEnemyInAnAirboat() || !Weapon_OwnsThisType( "weapon_smg1" ) ) - { - int nResult = SelectCombatSchedule(); - if ( nResult != SCHED_NONE ) - return nResult; - } - else - { - int nResult = SelectAirboatCombatSchedule(); - if ( nResult != SCHED_NONE ) - return nResult; - } - break; - - default: - break; - } - } - - // If we're not in combat, and we've got a pre-chase origin, move back to it - if ( ( m_NPCState != NPC_STATE_COMBAT ) && - ( m_vecPreChaseOrigin != vec3_origin ) && - ( m_flChasePlayerTime < gpGlobals->curtime ) ) - { - return SCHED_METROPOLICE_RETURN_TO_PRECHASE; - } - - return BaseClass::SelectSchedule(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : failedSchedule - -// failedTask - -// taskFailCode - -// Output : int -//----------------------------------------------------------------------------- -int CNPC_MetroPolice::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ) -{ - if ( failedSchedule == SCHED_METROPOLICE_CHASE_ENEMY ) - { - return SCHED_METROPOLICE_ESTABLISH_LINE_OF_FIRE; - } - - return BaseClass::SelectFailSchedule( failedSchedule, failedTask, taskFailCode ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_MetroPolice::TranslateSchedule( int scheduleType ) -{ - switch( scheduleType ) - { - case SCHED_ALERT_FACE_BESTSOUND: - if ( !IsCurSchedule( SCHED_METROPOLICE_ALERT_FACE_BESTSOUND, false ) ) - { - return SCHED_METROPOLICE_ALERT_FACE_BESTSOUND; - } - return SCHED_ALERT_FACE_BESTSOUND; - - case SCHED_CHASE_ENEMY: - - if ( !IsRunningBehavior() ) - { - return SCHED_METROPOLICE_CHASE_ENEMY; - } - - break; - - case SCHED_ESTABLISH_LINE_OF_FIRE: - case SCHED_METROPOLICE_ESTABLISH_LINE_OF_FIRE: - if ( IsEnemyInAnAirboat() ) - { - int nSched = SelectMoveToLedgeSchedule(); - if ( nSched != SCHED_NONE ) - return nSched; - } - return SCHED_METROPOLICE_ESTABLISH_LINE_OF_FIRE; - - case SCHED_WAKE_ANGRY: - return SCHED_METROPOLICE_WAKE_ANGRY; - - case SCHED_FAIL_TAKE_COVER: - - if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - { - // Must be able to shoot now - if( TryToEnterPistolSlot( SQUAD_SLOT_ATTACK1 ) || TryToEnterPistolSlot( SQUAD_SLOT_ATTACK2 ) ) - return SCHED_RANGE_ATTACK1; - } - - if ( HasCondition( COND_NO_PRIMARY_AMMO ) ) - return SCHED_RELOAD; - return SCHED_RUN_RANDOM; - - case SCHED_RANGE_ATTACK1: - Assert( !HasCondition( COND_NO_PRIMARY_AMMO ) ); - - if( !m_fWeaponDrawn ) - { - return SCHED_METROPOLICE_DRAW_PISTOL; - } - - if( Weapon_OwnsThisType( "weapon_smg1" ) ) - { - if ( IsEnemyInAnAirboat() ) - { - int nSched = SelectStitchSchedule(); - if ( nSched != SCHED_NONE ) - return nSched; - } - - if ( ShouldAttemptToStitch() ) - { - return SCHED_METROPOLICE_SMG_BURST_ATTACK; - } - else - { - return SCHED_METROPOLICE_SMG_NORMAL_ATTACK; - } - } - break; - case SCHED_METROPOLICE_ADVANCE: - if ( m_NextChargeTimer.Expired() && metropolice_charge.GetBool() ) - { - if ( Weapon_OwnsThisType( "weapon_pistol" ) ) - { - if ( GetEnemy() && GetEnemy()->GetAbsOrigin().DistToSqr( GetAbsOrigin() ) > 300*300 ) - { - if ( OccupyStrategySlot( SQUAD_SLOT_POLICE_CHARGE_ENEMY ) ) - { - m_NextChargeTimer.Set( 3, 7 ); - return SCHED_METROPOLICE_CHARGE; - } - } - } - else - { - m_NextChargeTimer.Set( 99999 ); - } - } - break; - } - - - return BaseClass::TranslateSchedule( scheduleType ); -} - - -//----------------------------------------------------------------------------- -// Can't move and shoot when the enemy is an airboat -//----------------------------------------------------------------------------- -bool CNPC_MetroPolice::ShouldMoveAndShoot() -{ - if ( HasSpawnFlags( SF_METROPOLICE_ARREST_ENEMY ) ) - return false; - - if ( ShouldAttemptToStitch() ) - return false; - - return BaseClass::ShouldMoveAndShoot(); -} - - -//----------------------------------------------------------------------------- -// Only move and shoot when attacking -//----------------------------------------------------------------------------- -bool CNPC_MetroPolice::OnBeginMoveAndShoot() -{ - if ( BaseClass::OnBeginMoveAndShoot() ) - { - if( HasStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - return true; // already have the slot I need - - if( OccupyStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Only move and shoot when attacking -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::OnEndMoveAndShoot() -{ - VacateStrategySlot(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pTask - -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::StartTask( const Task_t *pTask ) -{ - switch (pTask->iTask) - { - case TASK_METROPOLICE_WAIT_FOR_SENTENCE: - { - if ( FOkToMakeSound( (int)pTask->flTaskData ) ) - { - TaskComplete(); - } - } - break; - - case TASK_METROPOLICE_GET_PATH_TO_PRECHASE: - { - Assert( m_vecPreChaseOrigin != vec3_origin ); - if ( GetNavigator()->SetGoal( m_vecPreChaseOrigin ) ) - { - QAngle vecAngles( 0, m_flPreChaseYaw, 0 ); - GetNavigator()->SetArrivalDirection( vecAngles ); - TaskComplete(); - } - else - { - TaskFail( FAIL_NO_ROUTE ); - } - break; - } - - case TASK_METROPOLICE_CLEAR_PRECHASE: - { - m_vecPreChaseOrigin = vec3_origin; - m_flPreChaseYaw = 0; - TaskComplete(); - break; - } - - case TASK_METROPOLICE_ACTIVATE_BATON: - { - // Simply early out if we're in here without a baton - if ( HasBaton() == false ) - { - TaskComplete(); - break; - } - - bool activate = ( pTask->flTaskData != 0 ); - - if ( activate ) - { - if ( BatonActive() || m_bShouldActivateBaton == false ) - { - TaskComplete(); - break; - } - - m_Sentences.Speak( "METROPOLICE_ACTIVATE_BATON", SENTENCE_PRIORITY_NORMAL, SENTENCE_CRITERIA_NORMAL ); - SetIdealActivity( (Activity) ACT_ACTIVATE_BATON ); - } - else - { - if ( BatonActive() == false || m_bShouldActivateBaton ) - { - TaskComplete(); - break; - } - - m_Sentences.Speak( "METROPOLICE_DEACTIVATE_BATON", SENTENCE_PRIORITY_NORMAL, SENTENCE_CRITERIA_NORMAL ); - SetIdealActivity( (Activity) ACT_DEACTIVATE_BATON ); - } - } - break; - - case TASK_METROPOLICE_DIE_INSTANTLY: - { - CTakeDamageInfo info; - - info.SetAttacker( this ); - info.SetInflictor( this ); - info.SetDamage( m_iHealth ); - info.SetDamageType( (int)pTask->flTaskData ); - info.SetDamageForce( Vector( 0.1, 0.1, 0.1 ) ); - - TakeDamage( info ); - - TaskComplete(); - } - break; - - case TASK_METROPOLICE_RESET_LEDGE_CHECK_TIME: - m_flNextLedgeCheckTime = gpGlobals->curtime; - TaskComplete(); - break; - - case TASK_METROPOLICE_LEAD_ARREST_ENEMY: - case TASK_METROPOLICE_ARREST_ENEMY: - m_flTaskCompletionTime = gpGlobals->curtime + pTask->flTaskData; - break; - - case TASK_METROPOLICE_SIGNAL_FIRING_TIME: - EnemyResistingArrest(); - TaskComplete(); - break; - - case TASK_METROPOLICE_GET_PATH_TO_STITCH: - { - if ( !ShouldAttemptToStitch() ) - { - TaskFail( FAIL_NO_ROUTE ); - break; - } - - Vector vecTarget, vecTargetVel; - PredictShootTargetPosition( 0.5f, 0.0f, 0.0f, &vecTarget, &vecTargetVel ); - - vecTarget -= GetAbsOrigin(); - vecTarget.z = 0.0f; - float flDist = VectorNormalize( vecTarget ); - if ( GetNavigator()->SetVectorGoal( vecTarget, flDist ) ) - { - TaskComplete(); - } - else - { - TaskFail( FAIL_NO_ROUTE ); - } - } - break; - - // Stitching aiming - case TASK_METROPOLICE_AIM_STITCH_TIGHTLY: - SetBurstMode( true ); - AimBurstTightGrouping( pTask->flTaskData ); - TaskComplete(); - break; - - case TASK_METROPOLICE_AIM_STITCH_AT_PLAYER: - SetBurstMode( true ); - AimBurstAtEnemy( pTask->flTaskData ); - TaskComplete(); - break; - - case TASK_METROPOLICE_AIM_STITCH_AT_AIRBOAT: - if ( IsEnemyInAnAirboat() ) - { - SetBurstMode( true ); - AimBurstAtEnemy( pTask->flTaskData ); - TaskComplete(); - } - else - { - TaskFail(FAIL_NO_TARGET); - } - break; - - case TASK_METROPOLICE_AIM_STITCH_IN_FRONT_OF_AIRBOAT: - if ( IsEnemyInAnAirboat() ) - { - SetBurstMode( true ); - AimBurstInFrontOfEnemy( pTask->flTaskData ); - TaskComplete(); - } - else - { - TaskFail(FAIL_NO_TARGET); - } - break; - - case TASK_METROPOLICE_AIM_STITCH_ALONG_SIDE_OF_AIRBOAT: - if ( IsEnemyInAnAirboat() ) - { - SetBurstMode( true ); - AimBurstAlongSideOfEnemy( pTask->flTaskData ); - TaskComplete(); - } - else - { - TaskFail(FAIL_NO_TARGET); - } - break; - - case TASK_METROPOLICE_AIM_STITCH_BEHIND_AIRBOAT: - if ( IsEnemyInAnAirboat() ) - { - SetBurstMode( true ); - AimBurstBehindEnemy( pTask->flTaskData ); - TaskComplete(); - } - else - { - TaskFail(FAIL_NO_TARGET); - } - break; - - case TASK_METROPOLICE_BURST_ATTACK: - ResetIdealActivity( ACT_RANGE_ATTACK1 ); - break; - - case TASK_METROPOLICE_STOP_FIRE_BURST: - { - SetBurstMode( false ); - TaskComplete(); - } - break; - - case TASK_METROPOLICE_HARASS: - { - if( !( m_spawnflags & SF_METROPOLICE_NOCHATTER ) ) - { - if( GetEnemy() && GetEnemy()->GetWaterLevel() > 0 ) - { - EmitSound( "NPC_MetroPolice.WaterSpeech" ); - } - else - { - EmitSound( "NPC_MetroPolice.HidingSpeech" ); - } - } - - TaskComplete(); - } - break; - - case TASK_METROPOLICE_RELOAD_FOR_BURST: - { - if (GetActiveWeapon()) - { - int nDesiredShotCount = CountShotsInTime( pTask->flTaskData ); - - // Do our fake reload to simulate a bigger clip without having to change the SMG1 - int nAddCount = nDesiredShotCount - GetActiveWeapon()->Clip1(); - if ( nAddCount > 0 ) - { - if ( m_nBurstReloadCount >= nAddCount ) - { - GetActiveWeapon()->m_iClip1 += nAddCount; - m_nBurstReloadCount -= nAddCount; - } - } - - if ( nDesiredShotCount <= GetActiveWeapon()->Clip1() ) - { - TaskComplete(); - break; - } - } - - // Fake a TASK_RELOAD to make sure we've got a full clip... - Task_t reloadTask; - reloadTask.iTask = TASK_RELOAD; - reloadTask.flTaskData = 0.0f; - StartTask( &reloadTask ); - } - break; - - case TASK_RELOAD: - m_nBurstReloadCount = METROPOLICE_BURST_RELOAD_COUNT; - BaseClass::StartTask( pTask ); - break; - - case TASK_METROPOLICE_GET_PATH_TO_BESTSOUND_LOS: - { - } - break; - - default: - BaseClass::StartTask( pTask ); - break; - } -} - - -//----------------------------------------------------------------------------- -// -// Run tasks! -// -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -// He's resisting arrest! -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::EnemyResistingArrest() -{ - // Prevent any other arrest from being made in this squad - // and tell them all that the player is resisting arrest! - - if ( m_pSquad != NULL ) - { - AISquadIter_t iter; - CAI_BaseNPC *pSquadmate = m_pSquad->GetFirstMember( &iter ); - while ( pSquadmate ) - { - pSquadmate->RemoveSpawnFlags( SF_METROPOLICE_ARREST_ENEMY ); - pSquadmate->SetCondition( COND_METROPOLICE_ENEMY_RESISTING_ARREST ); - pSquadmate = m_pSquad->GetNextMember( &iter ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pTask - -//----------------------------------------------------------------------------- -#define FLEEING_DISTANCE_SQR (100 * 100) - -void CNPC_MetroPolice::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_WAIT_FOR_MOVEMENT: - BaseClass::RunTask( pTask ); - break; - - case TASK_METROPOLICE_WAIT_FOR_SENTENCE: - { - if ( FOkToMakeSound( (int)pTask->flTaskData ) ) - { - TaskComplete(); - } - } - break; - - case TASK_METROPOLICE_ACTIVATE_BATON: - AutoMovement(); - - if ( IsActivityFinished() ) - { - TaskComplete(); - } - break; - - case TASK_METROPOLICE_BURST_ATTACK: - { - AutoMovement( ); - - Vector vecAimPoint; - GetMotor()->SetIdealYawToTargetAndUpdate( m_vecBurstTargetPos, AI_KEEP_YAW_SPEED ); - - if ( IsActivityFinished() ) - { - if ( GetShotRegulator()->IsInRestInterval() ) - { - TaskComplete(); - } - else - { - OnRangeAttack1(); - ResetIdealActivity( ACT_RANGE_ATTACK1 ); - } - } - } - break; - - case TASK_METROPOLICE_RELOAD_FOR_BURST: - { - // Fake a TASK_RELOAD - Task_t reloadTask; - reloadTask.iTask = TASK_RELOAD; - reloadTask.flTaskData = 0.0f; - RunTask( &reloadTask ); - } - break; - - case TASK_METROPOLICE_LEAD_ARREST_ENEMY: - case TASK_METROPOLICE_ARREST_ENEMY: - { - if ( !GetEnemy() ) - { - TaskComplete(); - break; - } - - if ( gpGlobals->curtime >= m_flTaskCompletionTime ) - { - TaskComplete(); - break; - } - - // Complete the arrest after the last squad member has a bead on the enemy - // But only if you're the first guy who saw him - if ( pTask->iTask == TASK_METROPOLICE_LEAD_ARREST_ENEMY ) - { - int nArrestCount = SquadArrestCount(); - if ( nArrestCount == m_pSquad->NumMembers() ) - { - TaskComplete(); - break; - } - - // Do a distance check of the enemy from his initial position. - // Shoot if he gets too far. - if ( m_vSavePosition.DistToSqr( GetEnemy()->GetAbsOrigin() ) > FLEEING_DISTANCE_SQR ) - { - SpeakSentence( METROPOLICE_SENTENCE_HES_RUNNING ); - EnemyResistingArrest(); - break; - } - } - - // Keep aiming at the enemy - if ( GetEnemy() && FacingIdeal() ) - { - float flNewIdealYaw = CalcIdealYaw( GetEnemy()->EyePosition() ); - if ( fabs(UTIL_AngleDiff( GetMotor()->GetIdealYaw(), flNewIdealYaw )) >= 45.0f ) - { - GetMotor()->SetIdealYawToTarget( GetEnemy()->EyePosition() ); - SetTurnActivity(); - } - } - GetMotor()->UpdateYaw(); - } - break; - - case TASK_METROPOLICE_GET_PATH_TO_BESTSOUND_LOS: - { - switch( GetTaskInterrupt() ) - { - case 0: - { - CSound *pSound = GetBestSound(); - if (!pSound) - { - TaskFail(FAIL_NO_SOUND); - } - else - { - float flMaxRange = 2000; - float flMinRange = 0; - if ( GetActiveWeapon() ) - { - flMaxRange = MAX( GetActiveWeapon()->m_fMaxRange1, GetActiveWeapon()->m_fMaxRange2 ); - flMinRange = MIN( GetActiveWeapon()->m_fMinRange1, GetActiveWeapon()->m_fMinRange2 ); - } - - // Check against NPC's max range - if (flMaxRange > m_flDistTooFar) - { - flMaxRange = m_flDistTooFar; - } - - // Why not doing lateral LOS first? - - Vector losTarget = pSound->GetSoundReactOrigin(); - if ( GetTacticalServices()->FindLos( pSound->GetSoundReactOrigin(), losTarget, flMinRange, flMaxRange, 1.0, &m_vInterruptSavePosition ) ) - { - TaskInterrupt(); - } - else - { - TaskFail(FAIL_NO_SHOOT); - } - } - } - break; - - case 1: - { - AI_NavGoal_t goal( m_vInterruptSavePosition, ACT_RUN, AIN_HULL_TOLERANCE ); - GetNavigator()->SetGoal( goal ); - } - break; - } - } - break; - - default: - BaseClass::RunTask( pTask ); - break; - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pevInflictor - -// pAttacker - -// flDamage - -// bitsDamageType - -// Output : int -//----------------------------------------------------------------------------- -int CNPC_MetroPolice::OnTakeDamage_Alive( const CTakeDamageInfo &inputInfo ) -{ - CTakeDamageInfo info = inputInfo; - - if ( HasSpawnFlags( SF_METROPOLICE_ARREST_ENEMY ) ) - { - EnemyResistingArrest(); - } - -#if 0 - // Die instantly from a hit in idle/alert states - if( m_NPCState == NPC_STATE_IDLE || m_NPCState == NPC_STATE_ALERT ) - { - info.SetDamage( m_iHealth ); - } -#endif //0 - - if (info.GetAttacker() == GetEnemy()) - { - // Keep track of recent damage by my attacker. If it seems like we're - // being killed, consider running off and hiding. - m_nRecentDamage = (int)(m_nRecentDamage + info.GetDamage()); - m_flRecentDamageTime = gpGlobals->curtime; - } - - return BaseClass::OnTakeDamage_Alive( info ); -} - - -//----------------------------------------------------------------------------- -// Purpose: I want to deploy a manhack. Can I? -//----------------------------------------------------------------------------- -bool CNPC_MetroPolice::CanDeployManhack( void ) -{ - if ( HasSpawnFlags( SF_METROPOLICE_NO_MANHACK_DEPLOY ) ) - return false; - - // Nope, already have one out. - if( m_hManhack != NULL ) - return false; - - // Nope, don't have any! - if( m_iManhacks < 1 ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Allows for modification of the interrupt mask for the current schedule. -// In the most cases the base implementation should be called first. -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::BuildScheduleTestBits( void ) -{ - BaseClass::BuildScheduleTestBits(); - - if ( PlayerIsCriminal() == false ) - { - SetCustomInterruptCondition( COND_METROPOLICE_PHYSOBJECT_ASSAULT ); - } - - //FIXME: Always interrupt for now - if ( !IsInAScript() && - !IsCurSchedule( SCHED_METROPOLICE_SHOVE ) && - !IsCurSchedule( SCHED_MELEE_ATTACK1 ) && - !IsCurSchedule( SCHED_RELOAD ) && - !IsCurSchedule( SCHED_METROPOLICE_ACTIVATE_BATON ) ) - { - SetCustomInterruptCondition( COND_METROPOLICE_PLAYER_TOO_CLOSE ); - } - - if ( !IsCurSchedule( SCHED_METROPOLICE_BURNING_RUN ) && !IsCurSchedule( SCHED_METROPOLICE_BURNING_STAND ) && !IsMoving() ) - { - SetCustomInterruptCondition( COND_METROPOLICE_ON_FIRE ); - } - - if (IsCurSchedule(SCHED_TAKE_COVER_FROM_ENEMY)) - { - ClearCustomInterruptCondition( COND_LIGHT_DAMAGE ); - ClearCustomInterruptCondition( COND_HEAVY_DAMAGE ); - } - - if ( !IsCurSchedule( SCHED_CHASE_ENEMY ) && - !IsCurSchedule( SCHED_METROPOLICE_ACTIVATE_BATON ) && - !IsCurSchedule( SCHED_METROPOLICE_DEACTIVATE_BATON ) && - !IsCurSchedule( SCHED_METROPOLICE_SHOVE ) && - !IsCurSchedule( SCHED_METROPOLICE_RETURN_TO_PRECHASE ) ) - { - SetCustomInterruptCondition( COND_METROPOLICE_CHANGE_BATON_STATE ); - } - - if ( IsCurSchedule( SCHED_MELEE_ATTACK1 ) ) - { - if ( gpGlobals->curtime - m_flLastDamageFlinchTime < 10.0 ) - { - ClearCustomInterruptCondition( COND_LIGHT_DAMAGE ); - ClearCustomInterruptCondition( COND_HEAVY_DAMAGE ); - } - } - else if ( HasBaton() && IsCurSchedule( SCHED_COMBAT_FACE ) && !m_BatonSwingTimer.Expired() ) - { - ClearCustomInterruptCondition( COND_CAN_MELEE_ATTACK1 ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -WeaponProficiency_t CNPC_MetroPolice::CalcWeaponProficiency( CBaseCombatWeapon *pWeapon ) -{ - if( FClassnameIs( pWeapon, "weapon_pistol" ) ) - { - return WEAPON_PROFICIENCY_POOR; - } - - if( FClassnameIs( pWeapon, "weapon_smg1" ) ) - { - return WEAPON_PROFICIENCY_VERY_GOOD; - } - - return BaseClass::CalcWeaponProficiency( pWeapon ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::GatherConditions( void ) -{ - BaseClass::GatherConditions(); - - if ( m_bPlayerTooClose == false ) - { - ClearCondition( COND_METROPOLICE_PLAYER_TOO_CLOSE ); - } - - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); - - // FIXME: Player can be NULL here during level transitions. - if ( !pPlayer ) - return; - - float distToPlayerSqr = ( pPlayer->GetAbsOrigin() - GetAbsOrigin() ).LengthSqr(); - - // See if we're too close - if ( pPlayer->GetGroundEntity() == this ) - { - // Always beat a player on our head - m_iNumPlayerHits = 0; - SetCondition( COND_METROPOLICE_PLAYER_TOO_CLOSE ); - } - else if ( (distToPlayerSqr < (42.0f*42.0f) && FVisible(pPlayer)) ) - { - // Ignore the player if we've been beating him, but not if we haven't moved - if ( m_iNumPlayerHits < 3 || m_vecPreChaseOrigin == vec3_origin ) - { - SetCondition( COND_METROPOLICE_PLAYER_TOO_CLOSE ); - } - } - else - { - ClearCondition( COND_METROPOLICE_PLAYER_TOO_CLOSE ); - - // Don't clear out the player hit count for a few seconds after we last hit him - // This avoids states where two metropolice have the player pinned between them. - if ( (gpGlobals->curtime - GetLastAttackTime()) > 3 ) - { - m_iNumPlayerHits = 0; - } - - m_bPlayerTooClose = false; - } - - if( metropolice_move_and_melee.GetBool() ) - { - if( IsMoving() && HasCondition(COND_CAN_MELEE_ATTACK1) && HasBaton() ) - { - if ( m_BatonSwingTimer.Expired() ) - { - m_BatonSwingTimer.Set( 1.0, 1.75 ); - - Activity activity = TranslateActivity( ACT_MELEE_ATTACK_SWING_GESTURE ); - Assert( activity != ACT_INVALID ); - AddGesture( activity ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_MetroPolice::HasBaton( void ) -{ - CBaseCombatWeapon *pWeapon = GetActiveWeapon(); - - if ( pWeapon ) - return FClassnameIs( pWeapon, "weapon_stunstick" ); - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_MetroPolice::BatonActive( void ) -{ -#ifndef HL2MP - - CWeaponStunStick *pStick = dynamic_cast(GetActiveWeapon()); - - if ( pStick ) - return pStick->GetStunState(); -#endif - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : state - -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::SetBatonState( bool state ) -{ - if ( !HasBaton() ) - return; - - if ( m_bShouldActivateBaton != state ) - { - m_bShouldActivateBaton = state; - SetCondition( COND_METROPOLICE_CHANGE_BATON_STATE ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pSound - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_MetroPolice::QueryHearSound( CSound *pSound ) -{ - // Only behave differently if the player is pre-criminal - if ( PlayerIsCriminal() == false ) - { - // If the person making the sound was a friend, don't respond - if ( pSound->IsSoundType( SOUND_DANGER ) && pSound->m_hOwner && IRelationType( pSound->m_hOwner ) == D_NU ) - return false; - } - - return BaseClass::QueryHearSound( pSound ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -// *pEvent - -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) -{ - BaseClass::VPhysicsCollision( index, pEvent ); - - int otherIndex = !index; - - CBaseEntity *pHitEntity = pEvent->pEntities[otherIndex]; - - if ( pEvent->pObjects[otherIndex]->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - { - CHL2_Player *pPlayer = dynamic_cast(UTIL_PlayerByIndex( 1 )); - - // See if it's being held by the player - if ( pPlayer != NULL && pPlayer->IsHoldingEntity( pHitEntity ) ) - { - //TODO: Play an angry sentence, "Get that outta here!" - - if ( IsCurSchedule( SCHED_METROPOLICE_SHOVE ) == false ) - { - SetCondition( COND_METROPOLICE_PLAYER_TOO_CLOSE ); - m_bPlayerTooClose = true; - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTarget - -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::StunnedTarget( CBaseEntity *pTarget ) -{ - SetLastAttackTime( gpGlobals->curtime ); - - if ( pTarget && pTarget->IsPlayer() ) - { - m_OnStunnedPlayer.FireOutput( this, this ); - m_iNumPlayerHits++; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Use response for when the player is pre-criminal -//----------------------------------------------------------------------------- -void CNPC_MetroPolice::PrecriminalUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - if ( IsInAScript() ) - return; - // Don't respond if I'm busy hating the player - if ( IRelationType( pActivator ) == D_HT || ((GetState() != NPC_STATE_ALERT) && (GetState() != NPC_STATE_IDLE)) ) - return; - if ( PlayerIsCriminal() ) - return; - - // Treat it like the player's bothered the cop - IncrementPlayerCriminalStatus(); - - // If we've hit max warnings, and we're allowed to chase, go for it - if ( m_nNumWarnings == METROPOLICE_MAX_WARNINGS ) - { - AdministerJustice(); - } -} - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- -AI_BEGIN_CUSTOM_NPC( npc_metropolice, CNPC_MetroPolice ) - - gm_flTimeLastSpokePeek = 0; - - DECLARE_ANIMEVENT( AE_METROPOLICE_BATON_ON ); - DECLARE_ANIMEVENT( AE_METROPOLICE_BATON_OFF ); - DECLARE_ANIMEVENT( AE_METROPOLICE_SHOVE ); - DECLARE_ANIMEVENT( AE_METROPOLICE_START_DEPLOY ); - DECLARE_ANIMEVENT( AE_METROPOLICE_DRAW_PISTOL ); - DECLARE_ANIMEVENT( AE_METROPOLICE_DEPLOY_MANHACK ); - - DECLARE_SQUADSLOT( SQUAD_SLOT_POLICE_CHARGE_ENEMY ); - DECLARE_SQUADSLOT( SQUAD_SLOT_POLICE_HARASS ); - DECLARE_SQUADSLOT( SQUAD_SLOT_POLICE_DEPLOY_MANHACK ); - DECLARE_SQUADSLOT( SQUAD_SLOT_POLICE_ATTACK_OCCLUDER1 ); - DECLARE_SQUADSLOT( SQUAD_SLOT_POLICE_ATTACK_OCCLUDER2 ); - DECLARE_SQUADSLOT( SQUAD_SLOT_POLICE_ARREST_ENEMY ); - - DECLARE_ACTIVITY( ACT_METROPOLICE_DRAW_PISTOL ); - DECLARE_ACTIVITY( ACT_METROPOLICE_DEPLOY_MANHACK ); - DECLARE_ACTIVITY( ACT_METROPOLICE_FLINCH_BEHIND ); - DECLARE_ACTIVITY( ACT_PUSH_PLAYER ); - DECLARE_ACTIVITY( ACT_MELEE_ATTACK_THRUST ); - DECLARE_ACTIVITY( ACT_ACTIVATE_BATON ); - DECLARE_ACTIVITY( ACT_DEACTIVATE_BATON ); - DECLARE_ACTIVITY( ACT_WALK_BATON ); - DECLARE_ACTIVITY( ACT_IDLE_ANGRY_BATON ); - - DECLARE_INTERACTION( g_interactionMetrocopStartedStitch ); - DECLARE_INTERACTION( g_interactionMetrocopIdleChatter ); - DECLARE_INTERACTION( g_interactionMetrocopClearSentenceQueues ); - - DECLARE_TASK( TASK_METROPOLICE_HARASS ); - DECLARE_TASK( TASK_METROPOLICE_DIE_INSTANTLY ); - DECLARE_TASK( TASK_METROPOLICE_BURST_ATTACK ); - DECLARE_TASK( TASK_METROPOLICE_STOP_FIRE_BURST ); - DECLARE_TASK( TASK_METROPOLICE_AIM_STITCH_AT_PLAYER ); - DECLARE_TASK( TASK_METROPOLICE_AIM_STITCH_AT_AIRBOAT ); - DECLARE_TASK( TASK_METROPOLICE_AIM_STITCH_IN_FRONT_OF_AIRBOAT ); - DECLARE_TASK( TASK_METROPOLICE_AIM_STITCH_TIGHTLY ); - DECLARE_TASK( TASK_METROPOLICE_AIM_STITCH_ALONG_SIDE_OF_AIRBOAT ); - DECLARE_TASK( TASK_METROPOLICE_AIM_STITCH_BEHIND_AIRBOAT ); - DECLARE_TASK( TASK_METROPOLICE_RELOAD_FOR_BURST ); - DECLARE_TASK( TASK_METROPOLICE_GET_PATH_TO_STITCH ); - DECLARE_TASK( TASK_METROPOLICE_RESET_LEDGE_CHECK_TIME ); - DECLARE_TASK( TASK_METROPOLICE_GET_PATH_TO_BESTSOUND_LOS ); - DECLARE_TASK( TASK_METROPOLICE_ARREST_ENEMY ); - DECLARE_TASK( TASK_METROPOLICE_LEAD_ARREST_ENEMY ); - DECLARE_TASK( TASK_METROPOLICE_SIGNAL_FIRING_TIME ); - DECLARE_TASK( TASK_METROPOLICE_ACTIVATE_BATON ); - DECLARE_TASK( TASK_METROPOLICE_WAIT_FOR_SENTENCE ); - DECLARE_TASK( TASK_METROPOLICE_GET_PATH_TO_PRECHASE ); - DECLARE_TASK( TASK_METROPOLICE_CLEAR_PRECHASE ); - - DECLARE_CONDITION( COND_METROPOLICE_ON_FIRE ); - DECLARE_CONDITION( COND_METROPOLICE_ENEMY_RESISTING_ARREST ); -// DECLARE_CONDITION( COND_METROPOLICE_START_POLICING ); - DECLARE_CONDITION( COND_METROPOLICE_PLAYER_TOO_CLOSE ); - DECLARE_CONDITION( COND_METROPOLICE_CHANGE_BATON_STATE ); - DECLARE_CONDITION( COND_METROPOLICE_PHYSOBJECT_ASSAULT ); - - - //========================================================= -//========================================================= -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_WAKE_ANGRY, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_FACE_ENEMY 0" - " " - " Interrupts" -); - - -//========================================================= -// > InvestigateSound -// -// sends a monster to the location of the -// sound that was just heard to check things out. -//========================================================= -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_INVESTIGATE_SOUND, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_STORE_LASTPOSITION 0" - " TASK_METROPOLICE_GET_PATH_TO_BESTSOUND_LOS 0" - " TASK_FACE_IDEAL 0" -// " TASK_SET_TOLERANCE_DISTANCE 32" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_WAIT 5" - " TASK_GET_PATH_TO_LASTPOSITION 0" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_CLEAR_LASTPOSITION 0" - " TASK_FACE_REASONABLE 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_FEAR" - " COND_SEE_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" -); - - -//========================================================= -//========================================================= -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_HARASS, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_WAIT_FACE_ENEMY 6" - " TASK_METROPOLICE_HARASS 0" - " TASK_WAIT_PVS 0" - " " - " Interrupts" - " " - " COND_CAN_RANGE_ATTACK1" - " COND_NEW_ENEMY" -); - - -//========================================================= -//========================================================= -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_DRAW_PISTOL, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_PLAY_SEQUENCE_FACE_ENEMY ACTIVITY:ACT_METROPOLICE_DRAW_PISTOL" - " TASK_WAIT_FACE_ENEMY 0.1" - " " - " Interrupts" - " " -); - - -//========================================================= -// > ChaseEnemy -//========================================================= -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_CHASE_ENEMY, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_METROPOLICE_ESTABLISH_LINE_OF_FIRE" - " TASK_SET_TOLERANCE_DISTANCE 24" - " TASK_GET_CHASE_PATH_TO_ENEMY 300" - " TASK_SPEAK_SENTENCE 6" // METROPOLICE_SENTENCE_MOVE_INTO_POSITION - " TASK_RUN_PATH 0" - " TASK_METROPOLICE_RESET_LEDGE_CHECK_TIME 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_FACE_ENEMY 0" - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_ENEMY_UNREACHABLE" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK2" - " COND_TOO_CLOSE_TO_ATTACK" - " COND_TASK_FAILED" - " COND_LOST_ENEMY" - " COND_BETTER_WEAPON_AVAILABLE" - " COND_HEAR_DANGER" -); - - -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_ESTABLISH_LINE_OF_FIRE, - - " Tasks " - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_FAIL_ESTABLISH_LINE_OF_FIRE" - " TASK_FACE_ENEMY 0" - " TASK_SET_TOLERANCE_DISTANCE 48" - " TASK_GET_PATH_TO_ENEMY_LKP_LOS 0" - " TASK_SPEAK_SENTENCE 6" // METROPOLICE_SENTENCE_MOVE_INTO_POSITION - " TASK_RUN_PATH 0" - " TASK_METROPOLICE_RESET_LEDGE_CHECK_TIME 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_COMBAT_FACE" - " " - " Interrupts " - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - " COND_HEAR_DANGER" - " COND_HEAVY_DAMAGE" -); - - -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_ESTABLISH_STITCH_LINE_OF_FIRE, - - " Tasks " - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_FAIL_ESTABLISH_LINE_OF_FIRE" - " TASK_FACE_ENEMY 0" - " TASK_SET_TOLERANCE_DISTANCE 48" - " TASK_METROPOLICE_GET_PATH_TO_STITCH 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_COMBAT_FACE" - " " - " Interrupts " - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_HEAR_DANGER" - " COND_HEAVY_DAMAGE" -); - - -//========================================================= -// The uninterruptible portion of this behavior, whereupon -// the police actually releases the manhack. -//========================================================= -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_DEPLOY_MANHACK, - - " Tasks" - " TASK_SPEAK_SENTENCE 5" // METROPOLICE_SENTENCE_DEPLOY_MANHACK - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_METROPOLICE_DEPLOY_MANHACK" - " " - " Interrupts" - " " -); - - -//=============================================== -//=============================================== - -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_ADVANCE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE_ANGRY" - " TASK_FACE_ENEMY 0" - " TASK_WAIT_FACE_ENEMY 1" // give the guy some time to come out on his own - " TASK_WAIT_FACE_ENEMY_RANDOM 3" - " TASK_GET_PATH_TO_ENEMY_LOS 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE_ANGRY" - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - " COND_CAN_RANGE_ATTACK1" - " COND_ENEMY_DEAD" - "" -); - -//=============================================== -//=============================================== - -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_CHARGE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_METROPOLICE_ADVANCE" -// " TASK_SET_TOLERANCE_DISTANCE 24" - " TASK_STORE_LASTPOSITION 0" - " TASK_GET_CHASE_PATH_TO_ENEMY 300" - " TASK_RUN_PATH_FOR_UNITS 150" - " TASK_STOP_MOVING 1" - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_LOST_ENEMY" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - " COND_HEAR_DANGER" - " COND_METROPOLICE_PLAYER_TOO_CLOSE" -); - -//========================================================= -//========================================================= -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_BURNING_RUN, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_METROPOLICE_BURNING_STAND" - " TASK_SET_TOLERANCE_DISTANCE 24" - " TASK_GET_PATH_TO_ENEMY 0" - " TASK_RUN_PATH_TIMED 10" - " TASK_METROPOLICE_DIE_INSTANTLY 0" - " " - " Interrupts" -); - -//========================================================= -//========================================================= -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_BURNING_STAND, - - " Tasks" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE_ON_FIRE" - " TASK_WAIT 1.5" - " TASK_METROPOLICE_DIE_INSTANTLY DMG_BURN" - " TASK_WAIT 1.0" - " " - " Interrupts" -); - -//========================================================= -//========================================================= -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_RETURN_TO_PRECHASE, - - " Tasks" - " TASK_WAIT_RANDOM 1" - " TASK_METROPOLICE_GET_PATH_TO_PRECHASE 0" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_METROPOLICE_CLEAR_PRECHASE 0" - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - " COND_TASK_FAILED" - " COND_LOST_ENEMY" - " COND_HEAR_DANGER" -); - -//=============================================== -//=============================================== -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_ALERT_FACE_BESTSOUND, - - " Tasks" - " TASK_SPEAK_SENTENCE 7" // METROPOLICE_SENTENCE_HEARD_SOMETHING - " TASK_SET_SCHEDULE SCHEDULE:SCHED_ALERT_FACE_BESTSOUND" - "" - " Interrupts" - "" -) - - -//=============================================== -//=============================================== -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_ENEMY_RESISTING_ARREST, - - " Tasks" - " TASK_METROPOLICE_SIGNAL_FIRING_TIME 0" - "" - " Interrupts" - "" -) - - -//=============================================== -//=============================================== -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_WARN_AND_ARREST_ENEMY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_METROPOLICE_ENEMY_RESISTING_ARREST" - " TASK_STOP_MOVING 0" - " TASK_PLAY_SEQUENCE_FACE_ENEMY ACTIVITY:ACT_IDLE_ANGRY" - " TASK_SPEAK_SENTENCE 0" // "Freeze!" - " TASK_METROPOLICE_ARREST_ENEMY 0.5" - " TASK_STORE_ENEMY_POSITION_IN_SAVEPOSITION 0" - " TASK_METROPOLICE_ARREST_ENEMY 1" - " TASK_METROPOLICE_WAIT_FOR_SENTENCE 1" - " TASK_SPEAK_SENTENCE 1" // "He's over here!" - " TASK_METROPOLICE_LEAD_ARREST_ENEMY 5" - " TASK_METROPOLICE_ARREST_ENEMY 2" - " TASK_METROPOLICE_WAIT_FOR_SENTENCE 1" - " TASK_SPEAK_SENTENCE 3" // "Take him down!" - " TASK_METROPOLICE_ARREST_ENEMY 1.5" - " TASK_METROPOLICE_WAIT_FOR_SENTENCE 2" - " TASK_METROPOLICE_SIGNAL_FIRING_TIME 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_ENEMY_DEAD" - " COND_METROPOLICE_ENEMY_RESISTING_ARREST" - "" -); - -//=============================================== -//=============================================== -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_ARREST_ENEMY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_METROPOLICE_ENEMY_RESISTING_ARREST" - " TASK_GET_PATH_TO_ENEMY_LOS 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_PLAY_SEQUENCE_FACE_ENEMY ACTIVITY:ACT_IDLE_ANGRY" - " TASK_METROPOLICE_WAIT_FOR_SENTENCE 0" - " TASK_SPEAK_SENTENCE 4" - " TASK_METROPOLICE_ARREST_ENEMY 30" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_ENEMY_DEAD" - " COND_METROPOLICE_ENEMY_RESISTING_ARREST" - " COND_WEAPON_BLOCKED_BY_FRIEND" - " COND_WEAPON_SIGHT_OCCLUDED" - "" -); - - -//=============================================== -//=============================================== -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_SMG_NORMAL_ATTACK, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_ANNOUNCE_ATTACK 1" // 1 = primary attack - " TASK_METROPOLICE_STOP_FIRE_BURST 0" - " TASK_RANGE_ATTACK1 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_ENEMY_OCCLUDED" - " COND_NO_PRIMARY_AMMO" - " COND_HEAR_DANGER" - " COND_WEAPON_BLOCKED_BY_FRIEND" - " COND_WEAPON_SIGHT_OCCLUDED" -); - - -//=============================================== -//=============================================== -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_SMG_BURST_ATTACK, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_ANNOUNCE_ATTACK 1" // 1 = primary attack - " TASK_METROPOLICE_RELOAD_FOR_BURST 1.4" - " TASK_METROPOLICE_AIM_STITCH_AT_PLAYER 1.4" - " TASK_METROPOLICE_BURST_ATTACK 0" - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_NO_PRIMARY_AMMO" - " COND_HEAR_DANGER" - " COND_WEAPON_BLOCKED_BY_FRIEND" - -); - -//=============================================== -//=============================================== -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_AIM_STITCH_TIGHTLY, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_ANNOUNCE_ATTACK 1" // 1 = primary attack - " TASK_METROPOLICE_RELOAD_FOR_BURST 1.0" - " TASK_METROPOLICE_AIM_STITCH_TIGHTLY 1.0" - " TASK_METROPOLICE_BURST_ATTACK 0" - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_NO_PRIMARY_AMMO" - " COND_HEAR_DANGER" - " COND_WEAPON_BLOCKED_BY_FRIEND" - -); - - -//=============================================== -//=============================================== -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_AIM_STITCH_AT_AIRBOAT, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_ANNOUNCE_ATTACK 1" // 1 = primary attack - " TASK_METROPOLICE_RELOAD_FOR_BURST 2.5" - " TASK_METROPOLICE_AIM_STITCH_AT_AIRBOAT 2.5" - " TASK_METROPOLICE_BURST_ATTACK 0" - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_NO_PRIMARY_AMMO" - " COND_HEAR_DANGER" - " COND_WEAPON_BLOCKED_BY_FRIEND" - -); - -//=============================================== -//=============================================== -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_AIM_STITCH_IN_FRONT_OF_AIRBOAT, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_ANNOUNCE_ATTACK 1" // 1 = primary attack - " TASK_METROPOLICE_RELOAD_FOR_BURST 2.5" - " TASK_METROPOLICE_AIM_STITCH_IN_FRONT_OF_AIRBOAT 2.5" - " TASK_METROPOLICE_BURST_ATTACK 0" - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_NO_PRIMARY_AMMO" - " COND_HEAR_DANGER" - " COND_WEAPON_BLOCKED_BY_FRIEND" - -); - -//=============================================== -//=============================================== -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_AIM_STITCH_ALONG_SIDE_OF_AIRBOAT, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_ANNOUNCE_ATTACK 1" // 1 = primary attack - " TASK_METROPOLICE_RELOAD_FOR_BURST 2.5" - " TASK_METROPOLICE_AIM_STITCH_ALONG_SIDE_OF_AIRBOAT 2.5" - " TASK_METROPOLICE_BURST_ATTACK 0" - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_NO_PRIMARY_AMMO" - " COND_HEAR_DANGER" - " COND_WEAPON_BLOCKED_BY_FRIEND" - -); - -//=============================================== -//=============================================== -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_AIM_STITCH_BEHIND_AIRBOAT, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_ANNOUNCE_ATTACK 1" // 1 = primary attack - " TASK_METROPOLICE_RELOAD_FOR_BURST 2.5" - " TASK_METROPOLICE_AIM_STITCH_BEHIND_AIRBOAT 2.5" - " TASK_METROPOLICE_BURST_ATTACK 0" - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_NO_PRIMARY_AMMO" - " COND_HEAR_DANGER" - " COND_WEAPON_BLOCKED_BY_FRIEND" - -); - -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_SHOVE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_PLAYER 0.1" //FIXME: This needs to be the target or enemy - " TASK_METROPOLICE_ACTIVATE_BATON 1" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_PUSH_PLAYER" - "" - " Interrupts" -); - -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_ACTIVATE_BATON, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_TARGET 0" - " TASK_METROPOLICE_ACTIVATE_BATON 1" - "" - " Interrupts" -); - -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_DEACTIVATE_BATON, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_METROPOLICE_ACTIVATE_BATON 0" - "" - " Interrupts" -); - -DEFINE_SCHEDULE -( - SCHED_METROPOLICE_SMASH_PROP, - - " Tasks" - " TASK_GET_PATH_TO_TARGET 0" - " TASK_MOVE_TO_TARGET_RANGE 50" - " TASK_STOP_MOVING 0" - " TASK_FACE_TARGET 0" - " TASK_ANNOUNCE_ATTACK 1" // 1 = primary attack - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_MELEE_ATTACK1" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" -); - -AI_END_CUSTOM_NPC() - diff --git a/game/server/hl2/npc_metropolice.h b/game/server/hl2/npc_metropolice.h deleted file mode 100644 index af34953f1..000000000 --- a/game/server/hl2/npc_metropolice.h +++ /dev/null @@ -1,470 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef NPC_METROPOLICE_H -#define NPC_METROPOLICE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "rope.h" -#include "rope_shared.h" -#include "ai_baseactor.h" -#include "ai_basenpc.h" -#include "ai_goal_police.h" -#include "ai_behavior.h" -#include "ai_behavior_standoff.h" -#include "ai_behavior_assault.h" -#include "ai_behavior_functank.h" -#include "ai_behavior_actbusy.h" -#include "ai_behavior_rappel.h" -#include "ai_behavior_police.h" -#include "ai_behavior_follow.h" -#include "ai_sentence.h" -#include "props.h" - -class CNPC_MetroPolice; - -class CNPC_MetroPolice : public CAI_BaseActor -{ - DECLARE_CLASS( CNPC_MetroPolice, CAI_BaseActor ); - DECLARE_DATADESC(); - -public: - CNPC_MetroPolice(); - - virtual bool CreateComponents(); - bool CreateBehaviors(); - void Spawn( void ); - void Precache( void ); - - Class_T Classify( void ); - Disposition_t IRelationType(CBaseEntity *pTarget); - float MaxYawSpeed( void ); - void HandleAnimEvent( animevent_t *pEvent ); - Activity NPC_TranslateActivity( Activity newActivity ); - - Vector EyeDirection3D( void ) { return CAI_BaseHumanoid::EyeDirection3D(); } // cops don't have eyes - - virtual void Event_Killed( const CTakeDamageInfo &info ); - - virtual void OnScheduleChange(); - - float GetIdealAccel( void ) const; - int ObjectCaps( void ) { return UsableNPCObjectCaps(BaseClass::ObjectCaps()); } - void PrecriminalUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - // These are overridden so that the cop can shove and move a non-criminal player safely - CBaseEntity *CheckTraceHullAttack( float flDist, const Vector &mins, const Vector &maxs, int iDamage, int iDmgType, float forceScale, bool bDamageAnyNPC ); - CBaseEntity *CheckTraceHullAttack( const Vector &vStart, const Vector &vEnd, const Vector &mins, const Vector &maxs, int iDamage, int iDmgType, float flForceScale, bool bDamageAnyNPC ); - - virtual int SelectSchedule( void ); - virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ); - virtual int TranslateSchedule( int scheduleType ); - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - virtual Vector GetActualShootTrajectory( const Vector &shootOrigin ); - virtual void FireBullets( const FireBulletsInfo_t &info ); - virtual bool HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt); - virtual void Weapon_Equip( CBaseCombatWeapon *pWeapon ); - - //virtual bool OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval ); - bool OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ); - bool ShouldBruteForceFailedNav() { return false; } - - virtual void GatherConditions( void ); - - virtual bool OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval ); - - // Can't move and shoot when the enemy is an airboat - virtual bool ShouldMoveAndShoot(); - - // TraceAttack - virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - - // Speaking - virtual void SpeakSentence( int nSentenceType ); - - // Set up the shot regulator based on the equipped weapon - virtual void OnUpdateShotRegulator( ); - - bool ShouldKnockOutTarget( CBaseEntity *pTarget ); - void KnockOutTarget( CBaseEntity *pTarget ); - void StunnedTarget( CBaseEntity *pTarget ); - void AdministerJustice( void ); - - bool QueryHearSound( CSound *pSound ); - - void SetBatonState( bool state ); - bool BatonActive( void ); - - CAI_Sentence< CNPC_MetroPolice > *GetSentences() { return &m_Sentences; } - - virtual bool AllowedToIgnite( void ) { return true; } - - void PlayFlinchGesture( void ); - -protected: - // Determines the best type of flinch anim to play. - virtual Activity GetFlinchActivity( bool bHeavyDamage, bool bGesture ); - - // Only move and shoot when attacking - virtual bool OnBeginMoveAndShoot(); - virtual void OnEndMoveAndShoot(); - -private: - bool PlayerIsCriminal( void ); - void ReleaseManhack( void ); - - // Speech-related methods - void AnnounceTakeCoverFromDanger( CSound *pSound ); - void AnnounceEnemyType( CBaseEntity *pEnemy ); - void AnnounceEnemyKill( CBaseEntity *pEnemy ); - void AnnounceHarrassment( ); - void AnnounceOutOfAmmo( ); - - // Behavior-related sentences - void SpeakFuncTankSentence( int nSentenceType ); - void SpeakAssaultSentence( int nSentenceType ); - void SpeakStandoffSentence( int nSentenceType ); - - virtual void LostEnemySound( void ); - virtual void FoundEnemySound( void ); - virtual void AlertSound( void ); - virtual void PainSound( const CTakeDamageInfo &info ); - virtual void DeathSound( const CTakeDamageInfo &info ); - virtual void IdleSound( void ); - virtual bool ShouldPlayIdleSound( void ); - - // Burst mode! - void SetBurstMode( bool bEnable ); - - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - - int GetSoundInterests( void ); - - void BuildScheduleTestBits( void ); - - bool CanDeployManhack( void ); - - bool ShouldHitPlayer( const Vector &targetDir, float targetDist ); - - void PrescheduleThink( void ); - - void SetPlayerCriminalDuration( float time ); - - void IncrementPlayerCriminalStatus( void ); - - virtual bool UseAttackSquadSlots() { return true; } - - WeaponProficiency_t CalcWeaponProficiency( CBaseCombatWeapon *pWeapon ); - - // Inputs - void InputEnableManhackToss( inputdata_t &inputdata ); - void InputSetPoliceGoal( inputdata_t &inputdata ); - void InputActivateBaton( inputdata_t &inputdata ); - - void NotifyDeadFriend ( CBaseEntity* pFriend ); - - // Stitch aiming! - void AimBurstRandomly( int nMinCount, int nMaxCount, float flMinDelay, float flMaxDelay ); - void AimBurstAtEnemy( float flReactionTime ); - void AimBurstInFrontOfEnemy( float flReactionTime ); - void AimBurstAlongSideOfEnemy( float flFollowTime ); - void AimBurstBehindEnemy( float flFollowTime ); - void AimBurstTightGrouping( float flShotTime ); - - // Anim event handlers - void OnAnimEventDeployManhack( animevent_t *pEvent ); - void OnAnimEventShove( void ); - void OnAnimEventBatonOn( void ); - void OnAnimEventBatonOff( void ); - void OnAnimEventStartDeployManhack( void ); - void OnAnimEventPreDeployManhack( void ); - - bool HasBaton( void ); - - // Normal schedule selection - int SelectCombatSchedule(); - int SelectScheduleNewEnemy(); - int SelectScheduleArrestEnemy(); - int SelectRangeAttackSchedule(); - int SelectScheduleNoDirectEnemy(); - int SelectScheduleInvestigateSound(); - int SelectShoveSchedule( void ); - - bool TryToEnterPistolSlot( int nSquadSlot ); - - // Airboat schedule selection - int SelectAirboatCombatSchedule(); - int SelectAirboatRangeAttackSchedule(); - - // Handle flinching - bool IsHeavyDamage( const CTakeDamageInfo &info ); - - // Is my enemy currently in an airboat? - bool IsEnemyInAnAirboat() const; - - // Returns the airboat - CBaseEntity *GetEnemyAirboat() const; - - // Compute a predicted enemy position n seconds into the future - void PredictShootTargetPosition( float flDeltaTime, float flMinLeadDist, float flAddVelocity, Vector *pVecTarget, Vector *pVecTargetVel ); - - // Compute a predicted velocity n seconds into the future (given a known acceleration rate) - void PredictShootTargetVelocity( float flDeltaTime, Vector *pVecTargetVel ); - - // How many shots will I fire in a particular amount of time? - int CountShotsInTime( float flDeltaTime ) const; - float GetTimeForShots( int nShotCount ) const; - - // Visualize stitch - void VisualizeStitch( const Vector &vecStart, const Vector &vecEnd ); - - // Visualize line of death - void VisualizeLineOfDeath( ); - - // Modify the stitch length - float ComputeDistanceStitchModifier( float flDistanceToTarget ) const; - - // Adjusts the burst toward the target as it's being fired. - void SteerBurstTowardTarget( ); - - // Methods to compute shot trajectory based on burst mode - Vector ComputeBurstLockOnTrajectory( const Vector &shootOrigin ); - Vector ComputeBurstDeliberatelyMissTrajectory( const Vector &shootOrigin ); - Vector ComputeBurstTrajectory( const Vector &shootOrigin ); - Vector ComputeTightBurstTrajectory( const Vector &shootOrigin ); - - // Are we currently firing a burst? - bool IsCurrentlyFiringBurst() const; - - // Which entity are we actually trying to shoot at? - CBaseEntity *GetShootTarget(); - - // Different burst steering modes - void SteerBurstTowardTargetUseSpeedOnly( const Vector &vecShootAt, const Vector &vecShootAtVelocity, float flPredictTime, int nShotsTillPredict ); - void SteerBurstTowardTargetUseVelocity( const Vector &vecShootAt, const Vector &vecShootAtVelocity, int nShotsTillPredict ); - void SteerBurstTowardTargetUsePosition( const Vector &vecShootAt, const Vector &vecShootAtVelocity, int nShotsTillPredict ); - void SteerBurstTowardPredictedPoint( const Vector &vecShootAt, const Vector &vecShootAtVelocity, int nShotsTillPredict ); - void SteerBurstWithinLineOfDeath( ); - - // Set up the shot regulator - int SetupBurstShotRegulator( float flReactionTime ); - - // Choose a random vector somewhere between the two specified vectors - void RandomDirectionBetweenVectors( const Vector &vecStart, const Vector &vecEnd, Vector *pResult ); - - // Stitch selector - float StitchAtWeight( float flDist, float flSpeed, float flDot, float flReactionTime, const Vector &vecTargetToGun ); - float StitchAcrossWeight( float flDist, float flSpeed, float flDot, float flReactionTime ); - float StitchAlongSideWeight( float flDist, float flSpeed, float flDot ); - float StitchBehindWeight( float flDist, float flSpeed, float flDot ); - float StitchTightWeight( float flDist, float flSpeed, const Vector &vecTargetToGun, const Vector &vecVelocity ); - int SelectStitchSchedule(); - - // Can me enemy see me? - bool CanEnemySeeMe( ); - - // Combat schedule selection - int SelectMoveToLedgeSchedule(); - - // position to shoot at - Vector StitchAimTarget( const Vector &posSrc, bool bNoisy ); - - // Should we attempt to stitch? - bool ShouldAttemptToStitch(); - - // Deliberately aims as close as possible w/o hitting - Vector AimCloseToTargetButMiss( CBaseEntity *pTarget, const Vector &shootOrigin ); - - // Compute the actual reaction time based on distance + speed modifiers - float AimBurstAtReactionTime( float flReactonTime, float flDistToTargetSqr, float flCurrentSpeed ); - int AimBurstAtSetupHitCount( float flDistToTargetSqr, float flCurrentSpeed ); - - // How many squad members are trying to arrest the player? - int SquadArrestCount(); - - // He's resisting arrest! - void EnemyResistingArrest(); - void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); - - // Rappel - virtual bool IsWaitingToRappel( void ) { return m_RappelBehavior.IsWaitingToRappel(); } - void BeginRappel() { m_RappelBehavior.BeginRappel(); } - -private: - enum - { - BURST_NOT_ACTIVE = 0, - BURST_ACTIVE, - BURST_LOCK_ON_AFTER_HIT, - BURST_LOCKED_ON, - BURST_DELIBERATELY_MISS, - BURST_TIGHT_GROUPING, - }; - - enum - { - BURST_STEER_NONE = 0, - BURST_STEER_TOWARD_PREDICTED_POINT, - BURST_STEER_WITHIN_LINE_OF_DEATH, - BURST_STEER_ADJUST_FOR_SPEED_CHANGES, - BURST_STEER_EXACTLY_TOWARD_TARGET, - }; - - enum - { - COND_METROPOLICE_ON_FIRE = BaseClass::NEXT_CONDITION, - COND_METROPOLICE_ENEMY_RESISTING_ARREST, - COND_METROPOLICE_PLAYER_TOO_CLOSE, - COND_METROPOLICE_CHANGE_BATON_STATE, - COND_METROPOLICE_PHYSOBJECT_ASSAULT, - - }; - - enum - { - SCHED_METROPOLICE_WALK = BaseClass::NEXT_SCHEDULE, - SCHED_METROPOLICE_WAKE_ANGRY, - SCHED_METROPOLICE_HARASS, - SCHED_METROPOLICE_CHASE_ENEMY, - SCHED_METROPOLICE_ESTABLISH_LINE_OF_FIRE, - SCHED_METROPOLICE_DRAW_PISTOL, - SCHED_METROPOLICE_DEPLOY_MANHACK, - SCHED_METROPOLICE_ADVANCE, - SCHED_METROPOLICE_CHARGE, - SCHED_METROPOLICE_BURNING_RUN, - SCHED_METROPOLICE_BURNING_STAND, - SCHED_METROPOLICE_SMG_NORMAL_ATTACK, - SCHED_METROPOLICE_SMG_BURST_ATTACK, - SCHED_METROPOLICE_AIM_STITCH_AT_AIRBOAT, - SCHED_METROPOLICE_AIM_STITCH_IN_FRONT_OF_AIRBOAT, - SCHED_METROPOLICE_AIM_STITCH_TIGHTLY, - SCHED_METROPOLICE_AIM_STITCH_ALONG_SIDE_OF_AIRBOAT, - SCHED_METROPOLICE_AIM_STITCH_BEHIND_AIRBOAT, - SCHED_METROPOLICE_ESTABLISH_STITCH_LINE_OF_FIRE, - SCHED_METROPOLICE_INVESTIGATE_SOUND, - SCHED_METROPOLICE_WARN_AND_ARREST_ENEMY, - SCHED_METROPOLICE_ARREST_ENEMY, - SCHED_METROPOLICE_ENEMY_RESISTING_ARREST, - SCHED_METROPOLICE_WARN_TARGET, - SCHED_METROPOLICE_HARASS_TARGET, - SCHED_METROPOLICE_SUPPRESS_TARGET, - SCHED_METROPOLICE_RETURN_FROM_HARASS, - SCHED_METROPOLICE_SHOVE, - SCHED_METROPOLICE_ACTIVATE_BATON, - SCHED_METROPOLICE_DEACTIVATE_BATON, - SCHED_METROPOLICE_ALERT_FACE_BESTSOUND, - SCHED_METROPOLICE_RETURN_TO_PRECHASE, - SCHED_METROPOLICE_SMASH_PROP, - }; - - enum - { - TASK_METROPOLICE_HARASS = BaseClass::NEXT_TASK, - TASK_METROPOLICE_DIE_INSTANTLY, - TASK_METROPOLICE_BURST_ATTACK, - TASK_METROPOLICE_STOP_FIRE_BURST, - TASK_METROPOLICE_AIM_STITCH_AT_PLAYER, - TASK_METROPOLICE_AIM_STITCH_AT_AIRBOAT, - TASK_METROPOLICE_AIM_STITCH_TIGHTLY, - TASK_METROPOLICE_AIM_STITCH_IN_FRONT_OF_AIRBOAT, - TASK_METROPOLICE_AIM_STITCH_ALONG_SIDE_OF_AIRBOAT, - TASK_METROPOLICE_AIM_STITCH_BEHIND_AIRBOAT, - TASK_METROPOLICE_RELOAD_FOR_BURST, - TASK_METROPOLICE_GET_PATH_TO_STITCH, - TASK_METROPOLICE_RESET_LEDGE_CHECK_TIME, - TASK_METROPOLICE_GET_PATH_TO_BESTSOUND_LOS, - TASK_METROPOLICE_AIM_WEAPON_AT_ENEMY, - TASK_METROPOLICE_ARREST_ENEMY, - TASK_METROPOLICE_LEAD_ARREST_ENEMY, - TASK_METROPOLICE_SIGNAL_FIRING_TIME, - TASK_METROPOLICE_ACTIVATE_BATON, - TASK_METROPOLICE_WAIT_FOR_SENTENCE, - TASK_METROPOLICE_GET_PATH_TO_PRECHASE, - TASK_METROPOLICE_CLEAR_PRECHASE, - }; - -private: - - int m_iPistolClips; // How many clips the cop has in reserve - int m_iManhacks; // How many manhacks the cop has - bool m_fWeaponDrawn; // Is my weapon drawn? (ready to use) - bool m_bSimpleCops; // The easy version of the cops - int m_LastShootSlot; - CRandSimTimer m_TimeYieldShootSlot; - CSimpleSimTimer m_BatonSwingTimer; - CSimpleSimTimer m_NextChargeTimer; - - // All related to burst firing - Vector m_vecBurstTargetPos; - Vector m_vecBurstDelta; - int m_nBurstHits; - int m_nMaxBurstHits; - int m_nBurstReloadCount; - Vector m_vecBurstLineOfDeathDelta; - Vector m_vecBurstLineOfDeathOrigin; - int m_nBurstMode; - int m_nBurstSteerMode; - float m_flBurstSteerDistance; - float m_flBurstPredictTime; - Vector m_vecBurstPredictedVelocityDir; - float m_vecBurstPredictedSpeed; - float m_flValidStitchTime; - float m_flNextLedgeCheckTime; - float m_flTaskCompletionTime; - - bool m_bShouldActivateBaton; - float m_flBatonDebounceTime; // Minimum amount of time before turning the baton off - float m_flLastPhysicsFlinchTime; - float m_flLastDamageFlinchTime; - - // Sentences - float m_flNextPainSoundTime; - float m_flNextLostSoundTime; - int m_nIdleChatterType; - bool m_bPlayerIsNear; - - // Policing state - bool m_bPlayerTooClose; - bool m_bKeepFacingPlayer; - float m_flChasePlayerTime; - Vector m_vecPreChaseOrigin; - float m_flPreChaseYaw; - int m_nNumWarnings; - int m_iNumPlayerHits; - - // Outputs - COutputEvent m_OnStunnedPlayer; - COutputEvent m_OnCupCopped; - - AIHANDLE m_hManhack; - CHandle m_hBlockingProp; - - CAI_ActBusyBehavior m_ActBusyBehavior; - CAI_StandoffBehavior m_StandoffBehavior; - CAI_AssaultBehavior m_AssaultBehavior; - CAI_FuncTankBehavior m_FuncTankBehavior; - CAI_RappelBehavior m_RappelBehavior; - CAI_PolicingBehavior m_PolicingBehavior; - CAI_FollowBehavior m_FollowBehavior; - - CAI_Sentence< CNPC_MetroPolice > m_Sentences; - - int m_nRecentDamage; - float m_flRecentDamageTime; - - // The last hit direction, measured as a yaw relative to our orientation - float m_flLastHitYaw; - - static float gm_flTimeLastSpokePeek; - -public: - DEFINE_CUSTOM_AI; -}; - -#endif // NPC_METROPOLICE_H diff --git a/game/server/hl2/npc_missiledefense.cpp b/game/server/hl2/npc_missiledefense.cpp deleted file mode 100644 index ddfc06acc..000000000 --- a/game/server/hl2/npc_missiledefense.cpp +++ /dev/null @@ -1,496 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ai_basenpc.h" -#include "ai_hull.h" -#include "ai_senses.h" -#include "ai_memory.h" -#include "soundent.h" -#include "smoke_trail.h" -#include "weapon_rpg.h" -#include "gib.h" -#include "ndebugoverlay.h" -#include "IEffects.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "ammodef.h" -#include "hl2_shareddefs.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define MD_FULLAMMO 50 - - -#define MD_BC_YAW 0 -#define MD_BC_PITCH 1 -#define MD_AP_LGUN 2 -#define MD_AP_RGUN 1 -#define MD_GIB_COUNT 4 -#define MD_GIB_MODEL "models/gibs/missile_defense_gibs.mdl" -#define MD_YAW_SPEED 24 -#define MD_PITCH_SPEED 12 - -//========================================================= -//========================================================= -class CNPC_MissileDefense : public CAI_BaseNPC -{ - DECLARE_CLASS( CNPC_MissileDefense, CAI_BaseNPC ); - DECLARE_DATADESC(); - -public: - CNPC_MissileDefense( void ) { }; - void Precache( void ); - void Spawn( void ); - Class_T Classify( void ) { return CLASS_NONE; } - int GetSoundInterests( void ) { return SOUND_NONE; } - float MaxYawSpeed( void ) { return 90.f; } - - void RunAI(void); - void FireCannons( void ); - void AimGun( void ); - void EnemyShootPosition(CBaseEntity* pEnemy, Vector *vPosition); - - void Event_Killed( const CTakeDamageInfo &info ); - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - void Gib(); - void GetGunAim( Vector *vecAim ); - ~CNPC_MissileDefense(); - - Vector m_vGunAng; - int m_iAmmoLoaded; - float m_flReloadedTime; -}; - -LINK_ENTITY_TO_CLASS( npc_missiledefense, CNPC_MissileDefense ); - -//========================================================= -//========================================================= -BEGIN_DATADESC( CNPC_MissileDefense ) - - DEFINE_FIELD( m_iAmmoLoaded, FIELD_INTEGER ), - DEFINE_FIELD( m_flReloadedTime, FIELD_TIME ), - DEFINE_FIELD( m_vGunAng, FIELD_VECTOR ), - -END_DATADESC() - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_MissileDefense::Precache( void ) -{ - PrecacheModel("models/missile_defense.mdl"); - PrecacheModel(MD_GIB_MODEL); - - PrecacheScriptSound( "NPC_MissileDefense.Attack" ); - PrecacheScriptSound( "NPC_MissileDefense.Reload" ); - PrecacheScriptSound( "NPC_MissileDefense.Turn" ); - -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_MissileDefense::GetGunAim( Vector *vecAim ) -{ - Vector vecPos; - QAngle vecAng; - - GetAttachment( MD_AP_LGUN, vecPos, vecAng ); - - vecAng.x = GetLocalAngles().x + GetBoneController( MD_BC_PITCH ); - vecAng.z = 0; - vecAng.y = GetLocalAngles().y + GetBoneController( MD_BC_YAW ); - - Vector vecForward; - AngleVectors( vecAng, &vecForward ); - - *vecAim = vecForward; -} - - -#define NOISE 0.035f -#define MD_ATTN_CANNON 0.4 -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_MissileDefense::FireCannons( void ) -{ - // ---------------------------------------------- - // Make sure I have an enemy - // ---------------------------------------------- - if (GetEnemy() == NULL) - { - return; - } - - // ---------------------------------------------- - // Make sure I have ammo - // ---------------------------------------------- - if( m_iAmmoLoaded < 1 ) - { - return; - } - // ---------------------------------------------- - // Make sure gun it pointing in right direction - // ---------------------------------------------- - Vector vGunDir; - GetGunAim( &vGunDir ); - Vector vTargetPos; - EnemyShootPosition(GetEnemy(),&vTargetPos); - - Vector vTargetDir = vTargetPos - GetAbsOrigin(); - VectorNormalize( vTargetDir ); - - float fDotPr = DotProduct( vGunDir, vTargetDir ); - if (fDotPr < 0.95) - { - return; - } - - // ---------------------------------------------- - // Check line of sight - // ---------------------------------------------- - trace_t tr; - AI_TraceLine( GetEnemy()->EyePosition(), GetAbsOrigin(), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr); - if (tr.fraction < 1.0) - { - return; - } - - Vector vecRight; - Vector vecDir; - Vector vecCenter; - AngleVectors( GetLocalAngles(), NULL, &vecRight, NULL ); - - vecCenter = WorldSpaceCenter(); - - if( GetEnemy() == NULL ) - { - return; - } - - bool fSound = false; - if( random->RandomInt( 0, 3 ) == 0 ) - { - fSound = true; - } - - - EmitSound( "NPC_MissileDefense.Attack" ); - - Vector vecGun; - QAngle vecAng; - - GetAttachment( MD_AP_LGUN, vecGun, vecAng ); - - Vector vecTarget; - EnemyShootPosition(GetEnemy(),&vecTarget); - - vecDir = vecTarget - vecCenter; - VectorNormalize(vecDir); - vecDir.x += random->RandomFloat( -NOISE, NOISE ); - vecDir.y += random->RandomFloat( -NOISE, NOISE ); - - Vector vecStart = vecGun + vecDir * 110; - Vector vecEnd = vecGun + vecDir * 4096; - UTIL_Tracer( vecStart, vecEnd, 0, TRACER_DONT_USE_ATTACHMENT, 3000 + random->RandomFloat( 0, 2000 ), fSound ); - - vecDir = vecTarget - vecCenter; - VectorNormalize(vecDir); - vecDir.x += random->RandomFloat( -NOISE, NOISE ); - vecDir.y += random->RandomFloat( -NOISE, NOISE ); - vecDir.z += random->RandomFloat( -NOISE, NOISE ); - - GetAttachment( MD_AP_RGUN, vecGun, vecAng ); - vecStart = vecGun + vecDir * 110; - vecEnd = vecGun + vecDir * 4096; - UTIL_Tracer( vecStart, vecEnd, 0, TRACER_DONT_USE_ATTACHMENT, 3000 + random->RandomFloat( 0, 2000 ) ); - - m_iAmmoLoaded -= 2; - - if( m_iAmmoLoaded < 1 ) - { - // Incite a reload. - EmitSound( "NPC_MissileDefense.Reload" ); - m_flReloadedTime = gpGlobals->curtime + 0.3; - return; - } - - // Do damage to the missile based on distance. - // if < 1, make damage 0. - - float flDist = (GetEnemy()->GetLocalOrigin() - vecGun).Length(); - float flDamage; - - flDamage = 4000 - flDist; - - flDamage /= 1000.0; - - if( flDamage > 0 ) - { - if( flDist <= 1500 ) - { - flDamage *= 2; - } - - CTakeDamageInfo info( this, this, flDamage, DMG_MISSILEDEFENSE ); - CalculateBulletDamageForce( &info, GetAmmoDef()->Index("SMG1"), vecDir, GetEnemy()->GetAbsOrigin() ); - GetEnemy()->TakeDamage( info ); - } -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_MissileDefense::Spawn( void ) -{ - Precache(); - - SetModel( "models/missile_defense.mdl" ); - UTIL_SetSize( this, Vector( -36, -36 , 0 ), Vector( 36, 36, 64 ) ); - - SetSolid( SOLID_BBOX ); - SetMoveType( MOVETYPE_NONE ); - m_takedamage = DAMAGE_YES; - SetBloodColor( DONT_BLEED ); - m_iHealth = 10; - m_flFieldOfView = 0.1; - m_NPCState = NPC_STATE_NONE; - CapabilitiesClear(); - CapabilitiesAdd ( bits_CAP_INNATE_RANGE_ATTACK1 ); - - // Hate missiles - AddClassRelationship( CLASS_MISSILE, D_HT, 5 ); - - m_spawnflags |= SF_NPC_LONG_RANGE; - - m_flReloadedTime = gpGlobals->curtime; - - InitBoneControllers(); - - NPCInit(); - - SetBoneController( MD_BC_YAW, 10 ); - SetBoneController( MD_BC_PITCH, 0 ); - - SetBodygroup( 1, 1 ); - SetBodygroup( 2, 1 ); - SetBodygroup( 3, 1 ); - SetBodygroup( 4, 1 ); - - m_NPCState = NPC_STATE_IDLE; -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -int CNPC_MissileDefense::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - // Only take blast damage - if (info.GetDamageType() & DMG_BLAST ) - { - return BaseClass::OnTakeDamage_Alive( info ); - } - else - { - return 0; - } -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_MissileDefense::Event_Killed( const CTakeDamageInfo &info ) -{ - StopSound( "NPC_MissileDefense.Turn" ); - Gib(); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_MissileDefense::Gib(void) -{ - // Sparks - for (int i = 0; i < 4; i++) - { - Vector sparkPos = GetAbsOrigin(); - sparkPos.x += random->RandomFloat(-12,12); - sparkPos.y += random->RandomFloat(-12,12); - sparkPos.z += random->RandomFloat(-12,12); - g_pEffects->Sparks(sparkPos); - } - // Smoke - UTIL_Smoke(GetAbsOrigin(), random->RandomInt(10, 15), 10); - - // Light - CBroadcastRecipientFilter filter; - - te->DynamicLight( filter, 0.0, - &GetAbsOrigin(), 255, 180, 100, 0, 100, 0.1, 0 ); - - // Remove top parts - SetBodygroup( 1, 0 ); - SetBodygroup( 2, 0 ); - SetBodygroup( 3, 0 ); - SetBodygroup( 4, 0 ); - m_takedamage = 0; - SetThink(NULL); - - // Throw manhackgibs - CGib::SpawnSpecificGibs( this, MD_GIB_COUNT, 300, 500, MD_GIB_MODEL); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_MissileDefense::RunAI( void ) -{ - // If my enemy is dead clear the memory and reset m_hEnemy - if (GetEnemy() != NULL && - !GetEnemy()->IsAlive()) - { - ClearEnemyMemory(); - SetEnemy( NULL ); - } - - if (GetEnemy() == NULL ) - { - GetSenses()->Look( 4092 ); - SetEnemy( BestEnemy( ) ); - - if (GetEnemy() != NULL) - { - m_iAmmoLoaded = MD_FULLAMMO; - m_flReloadedTime = gpGlobals->curtime; - } - } - - if( m_iAmmoLoaded < 1 && gpGlobals->curtime > m_flReloadedTime ) - { - m_iAmmoLoaded = MD_FULLAMMO; - } - - AimGun(); - FireCannons(); - SetNextThink( gpGlobals->curtime + 0.05 ); -} - -//------------------------------------------------------------------------------ -// Purpose : Add a little prediction into my enemy aim position -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_MissileDefense::EnemyShootPosition(CBaseEntity* pEnemy, Vector *vPosition) -{ - // This should never happen, but just in case - if (!pEnemy) - { - return; - } - - *vPosition = pEnemy->GetAbsOrigin(); - - // Add prediction but prevents us from flipping around as enemy approaches us - float flDist = (pEnemy->GetAbsOrigin() - GetAbsOrigin()).Length(); - Vector vPredVel = pEnemy->GetSmoothedVelocity() * 0.5; - if ( flDist > vPredVel.Length()) - { - *vPosition += vPredVel; - } -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_MissileDefense::AimGun( void ) -{ - if (GetEnemy() == NULL) - { - StopSound( "NPC_MissileDefense.Turn" ); - return; - } - - Vector forward, right, up; - AngleVectors( GetLocalAngles(), &forward, &right, &up ); - - // Get gun attachment points - Vector vBasePos; - QAngle vBaseAng; - GetAttachment( MD_AP_LGUN, vBasePos, vBaseAng ); - - Vector vTargetPos; - EnemyShootPosition(GetEnemy(),&vTargetPos); - - Vector vTargetDir = vTargetPos - vBasePos; - VectorNormalize( vTargetDir ); - - Vector vecOut; - vecOut.x = DotProduct( forward, vTargetDir ); - vecOut.y = -DotProduct( right, vTargetDir ); - vecOut.z = DotProduct( up, vTargetDir ); - - QAngle angles; - VectorAngles(vecOut, angles); - - if (angles.y > 180) - angles.y = angles.y - 360; - if (angles.y < -180) - angles.y = angles.y + 360; - if (angles.x > 180) - angles.x = angles.x - 360; - if (angles.x < -180) - angles.x = angles.x + 360; - - float flOldX = m_vGunAng.x; - float flOldY = m_vGunAng.y; - - if (angles.x > m_vGunAng.x) - m_vGunAng.x = MIN( angles.x, m_vGunAng.x + MD_PITCH_SPEED ); - if (angles.x < m_vGunAng.x) - m_vGunAng.x = MAX( angles.x, m_vGunAng.x - MD_PITCH_SPEED ); - if (angles.y > m_vGunAng.y) - m_vGunAng.y = MIN( angles.y, m_vGunAng.y + MD_YAW_SPEED ); - if (angles.y < m_vGunAng.y) - m_vGunAng.y = MAX( angles.y, m_vGunAng.y - MD_YAW_SPEED ); - - m_vGunAng.y = SetBoneController( MD_BC_YAW, m_vGunAng.y ); - m_vGunAng.x = SetBoneController( MD_BC_PITCH, m_vGunAng.x ); - - if (flOldX != m_vGunAng.x || flOldY != m_vGunAng.y) - { - EmitSound( "NPC_MissileDefense.Turn" ); - } - else - { - StopSound( "NPC_MissileDefense.Turn" ); - } -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -CNPC_MissileDefense::~CNPC_MissileDefense(void) -{ - StopSound( "NPC_MissileDefense.Turn" ); -} diff --git a/game/server/hl2/npc_monk.cpp b/game/server/hl2/npc_monk.cpp deleted file mode 100644 index 3b6849058..000000000 --- a/game/server/hl2/npc_monk.cpp +++ /dev/null @@ -1,776 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Father Grigori, a benevolent monk who is the last remaining human -// in Ravenholm. He keeps to the rooftops and uses a big ole elephant -// gun to send his zombified former friends to a peaceful death. -// -//=============================================================================// - -#include "cbase.h" -#include "ai_baseactor.h" -#include "ai_hull.h" -#include "ammodef.h" -#include "gamerules.h" -#include "IEffects.h" -#include "engine/IEngineSound.h" -#include "ai_behavior.h" -#include "ai_behavior_assault.h" -#include "ai_behavior_lead.h" -#include "npcevent.h" -#include "ai_playerally.h" -#include "ai_senses.h" -#include "soundent.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar monk_headshot_freq( "monk_headshot_freq", "2" ); - -//----------------------------------------------------------------------------- -// Activities. -//----------------------------------------------------------------------------- -int ACT_MONK_GUN_IDLE; - -class CNPC_Monk : public CAI_PlayerAlly -{ - DECLARE_CLASS( CNPC_Monk, CAI_PlayerAlly ); - -public: - - CNPC_Monk() {} - void Spawn(); - void Precache(); - - bool CreateBehaviors(); - int GetSoundInterests(); - void BuildScheduleTestBits( void ); - Class_T Classify( void ); - - bool ShouldBackAway(); - - bool IsValidEnemy( CBaseEntity *pEnemy ); - - int TranslateSchedule( int scheduleType ); - int SelectSchedule (); - - void HandleAnimEvent( animevent_t *pEvent ); - Activity NPC_TranslateActivity( Activity eNewActivity ); - - void PainSound( const CTakeDamageInfo &info ); - void DeathSound( const CTakeDamageInfo &info ); - - WeaponProficiency_t CalcWeaponProficiency( CBaseCombatWeapon *pWeapon ); - Vector GetActualShootPosition( const Vector &shootOrigin ); - Vector GetActualShootTrajectory( const Vector &shootOrigin ); - - void PrescheduleThink(); - - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - - void GatherConditions(); - - bool PassesDamageFilter( const CTakeDamageInfo &info ); - void OnKilledNPC( CBaseCombatCharacter *pKilled ); - - bool IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos ) const; - int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ); - - DECLARE_DATADESC(); - -private: - //----------------------------------------------------- - // Conditions, Schedules, Tasks - //----------------------------------------------------- - enum - { - SCHED_MONK_RANGE_ATTACK1 = BaseClass::NEXT_SCHEDULE, - SCHED_MONK_BACK_AWAY_FROM_ENEMY, - SCHED_MONK_BACK_AWAY_AND_RELOAD, - SCHED_MONK_NORMAL_RELOAD, - }; - - enum - { - //TASK_MONK_FIRST_TASK = BaseClass::NEXT_TASK, - }; - - DEFINE_CUSTOM_AI; - - // Inputs - void InputPerfectAccuracyOn( inputdata_t &inputdata ); - void InputPerfectAccuracyOff( inputdata_t &inputdata ); - - CAI_AssaultBehavior m_AssaultBehavior; - CAI_LeadBehavior m_LeadBehavior; - int m_iNumZombies; - int m_iDangerousZombies; - bool m_bPerfectAccuracy; - bool m_bMournedPlayer; - -}; - -BEGIN_DATADESC( CNPC_Monk ) -// m_AssaultBehavior -// m_LeadBehavior - DEFINE_FIELD( m_iNumZombies, FIELD_INTEGER ), - DEFINE_FIELD( m_iDangerousZombies, FIELD_INTEGER ), - DEFINE_FIELD( m_bPerfectAccuracy, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bMournedPlayer, FIELD_BOOLEAN ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "PerfectAccuracyOn", InputPerfectAccuracyOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "PerfectAccuracyOff", InputPerfectAccuracyOff ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( npc_monk, CNPC_Monk ); - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Monk::CreateBehaviors() -{ - AddBehavior( &m_LeadBehavior ); - AddBehavior( &m_AssaultBehavior ); - - return BaseClass::CreateBehaviors(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Monk::GetSoundInterests() -{ - return SOUND_WORLD | - SOUND_COMBAT | - SOUND_PLAYER | - SOUND_DANGER; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Monk::BuildScheduleTestBits( void ) -{ - // FIXME: we need a way to make scenes non-interruptible -#if 0 - if ( IsCurSchedule( SCHED_RANGE_ATTACK1 ) || IsCurSchedule( SCHED_SCENE_GENERIC ) ) - { - ClearCustomInterruptCondition( COND_LIGHT_DAMAGE ); - ClearCustomInterruptCondition( COND_HEAVY_DAMAGE ); - ClearCustomInterruptCondition( COND_NEW_ENEMY ); - ClearCustomInterruptCondition( COND_HEAR_DANGER ); - } -#endif - - // Don't interrupt while shooting the gun - const Task_t* pTask = GetTask(); - if ( pTask && (pTask->iTask == TASK_RANGE_ATTACK1) ) - { - ClearCustomInterruptCondition( COND_HEAVY_DAMAGE ); - ClearCustomInterruptCondition( COND_ENEMY_OCCLUDED ); - ClearCustomInterruptCondition( COND_HEAR_DANGER ); - ClearCustomInterruptCondition( COND_WEAPON_BLOCKED_BY_FRIEND ); - ClearCustomInterruptCondition( COND_WEAPON_SIGHT_OCCLUDED ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Class_T CNPC_Monk::Classify( void ) -{ - return CLASS_PLAYER_ALLY_VITAL; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Activity CNPC_Monk::NPC_TranslateActivity( Activity eNewActivity ) -{ - eNewActivity = BaseClass::NPC_TranslateActivity( eNewActivity ); - - if ( (m_NPCState == NPC_STATE_COMBAT || m_NPCState == NPC_STATE_ALERT) ) - { - bool bGunUp = false; - - bGunUp = (gpGlobals->curtime - m_flLastAttackTime < 4); - bGunUp = bGunUp || (GetEnemy() && !HasCondition( COND_TOO_FAR_TO_ATTACK )); - - if (bGunUp) - { - if ( eNewActivity == ACT_IDLE ) - { - eNewActivity = ACT_IDLE_ANGRY; - } - // keep aiming a little longer than normal since the shot takes so long and there's no good way to do a transitions between movement types :/ - else if ( eNewActivity == ACT_WALK ) - { - eNewActivity = ACT_WALK_AIM; - } - else if ( eNewActivity == ACT_RUN ) - { - eNewActivity = ACT_RUN_AIM; - } - } - } - - // We need these so that we can pick up the shotgun to throw it in the balcony scene - if ( eNewActivity == ACT_IDLE_ANGRY_SHOTGUN ) - { - eNewActivity = ACT_IDLE_ANGRY_SMG1; - } - else if ( eNewActivity == ACT_WALK_AIM_SHOTGUN ) - { - eNewActivity = ACT_WALK_AIM_RIFLE; - } - else if ( eNewActivity == ACT_RUN_AIM_SHOTGUN ) - { - eNewActivity = ACT_RUN_AIM_RIFLE; - } - else if ( eNewActivity == ACT_RANGE_ATTACK_SHOTGUN_LOW ) - { - return ACT_RANGE_ATTACK_SMG1_LOW; - } - - return eNewActivity; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Monk::Precache() -{ - PrecacheModel( "models/Monk.mdl" ); - - PrecacheScriptSound( "NPC_Citizen.FootstepLeft" ); - PrecacheScriptSound( "NPC_Citizen.FootstepRight" ); - - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Monk::Spawn() -{ - Precache(); - - BaseClass::Spawn(); - - SetModel( "models/Monk.mdl" ); - - SetHullType(HULL_HUMAN); - SetHullSizeNormal(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - SetBloodColor( BLOOD_COLOR_RED ); - m_iHealth = 100; - m_flFieldOfView = m_flFieldOfView = -0.707; // 270` - m_NPCState = NPC_STATE_NONE; - - m_HackedGunPos = Vector ( 0, 0, 55 ); - - CapabilitiesAdd( bits_CAP_TURN_HEAD | bits_CAP_DOORS_GROUP | bits_CAP_MOVE_GROUND ); - CapabilitiesAdd( bits_CAP_USE_WEAPONS ); - CapabilitiesAdd( bits_CAP_ANIMATEDFACE ); - CapabilitiesAdd( bits_CAP_FRIENDLY_DMG_IMMUNE ); - CapabilitiesAdd( bits_CAP_AIM_GUN ); - CapabilitiesAdd( bits_CAP_MOVE_SHOOT ); - - NPCInit(); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_Monk::PainSound( const CTakeDamageInfo &info ) -{ - SpeakIfAllowed( TLK_WOUND ); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_Monk::DeathSound( const CTakeDamageInfo &info ) -{ - // Sentences don't play on dead NPCs - SentenceStop(); - - Speak( TLK_DEATH ); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -WeaponProficiency_t CNPC_Monk::CalcWeaponProficiency( CBaseCombatWeapon *pWeapon ) -{ - return WEAPON_PROFICIENCY_PERFECT; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Vector CNPC_Monk::GetActualShootPosition( const Vector &shootOrigin ) -{ - return BaseClass::GetActualShootPosition( shootOrigin ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Vector CNPC_Monk::GetActualShootTrajectory( const Vector &shootOrigin ) -{ - if( GetEnemy() && GetEnemy()->Classify() == CLASS_ZOMBIE ) - { - Vector vecShootDir; - - if( m_bPerfectAccuracy || random->RandomInt( 1, monk_headshot_freq.GetInt() ) == 1 ) - { - vecShootDir = GetEnemy()->HeadTarget( shootOrigin ) - shootOrigin; - } - else - { - vecShootDir = GetEnemy()->BodyTarget( shootOrigin ) - shootOrigin; - } - - VectorNormalize( vecShootDir ); - return vecShootDir; - } - - return BaseClass::GetActualShootTrajectory( shootOrigin ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pEvent - -//----------------------------------------------------------------------------- -void CNPC_Monk::HandleAnimEvent( animevent_t *pEvent ) -{ - switch( pEvent->event ) - { - case NPC_EVENT_LEFTFOOT: - { - EmitSound( "NPC_Citizen.FootstepLeft", pEvent->eventtime ); - } - break; - case NPC_EVENT_RIGHTFOOT: - { - EmitSound( "NPC_Citizen.FootstepRight", pEvent->eventtime ); - } - break; - - default: - BaseClass::HandleAnimEvent( pEvent ); - break; - } -} - -//------------------------------------- -// Grigori tries to stand his ground until -// enemies are very close. -//------------------------------------- -#define MONK_STAND_GROUND_HEIGHT 24.0 -bool CNPC_Monk::ShouldBackAway() -{ - if( !GetEnemy() ) - return false; - - if( GetAbsOrigin().z - GetEnemy()->GetAbsOrigin().z >= MONK_STAND_GROUND_HEIGHT ) - { - // This is a fairly special case. Grigori looks better fighting from his assault points in the - // elevated places of the Graveyard, so we prevent his back away behavior anytime he has a height - // advantage on his enemy. - return false; - } - - float flDist; - flDist = ( GetAbsOrigin() - GetEnemy()->GetAbsOrigin() ).Length(); - - if( flDist <= 180 ) - return true; - - return false; -} - -//------------------------------------- - -bool CNPC_Monk::IsValidEnemy( CBaseEntity *pEnemy ) -{ - if ( BaseClass::IsValidEnemy( pEnemy ) && GetActiveWeapon() ) - { - float flDist; - - flDist = ( GetAbsOrigin() - pEnemy->GetAbsOrigin() ).Length(); - if( flDist <= GetActiveWeapon()->m_fMaxRange1 ) - return true; - } - return false; -} - - -//------------------------------------- - -int CNPC_Monk::TranslateSchedule( int scheduleType ) -{ - switch( scheduleType ) - { - case SCHED_MOVE_AWAY_FAIL: - // Our first method of backing away failed. Try another. - return SCHED_MONK_BACK_AWAY_FROM_ENEMY; - break; - - case SCHED_RANGE_ATTACK1: - { - if( ShouldBackAway() ) - { - // Get some room, rely on move and shoot. - return SCHED_MOVE_AWAY; - } - - return SCHED_MONK_RANGE_ATTACK1; - } - break; - - case SCHED_HIDE_AND_RELOAD: - case SCHED_RELOAD: - if( ShouldBackAway() ) - { - return SCHED_MONK_BACK_AWAY_AND_RELOAD; - } - - return SCHED_RELOAD; - break; - } - - return BaseClass::TranslateSchedule( scheduleType ); -} - - -//------------------------------------- - -void CNPC_Monk::PrescheduleThink() -{ - BaseClass::PrescheduleThink(); -} - -//------------------------------------- - -int CNPC_Monk::SelectSchedule() -{ - if( HasCondition( COND_HEAR_DANGER ) ) - { - SpeakIfAllowed( TLK_DANGER ); - return SCHED_TAKE_COVER_FROM_BEST_SOUND; - } - - if ( HasCondition( COND_TALKER_PLAYER_DEAD ) && !m_bMournedPlayer && IsOkToSpeak() ) - { - m_bMournedPlayer = true; - Speak( TLK_IDLE ); - } - - if( !BehaviorSelectSchedule() ) - { - if ( HasCondition ( COND_NO_PRIMARY_AMMO ) ) - { - return SCHED_HIDE_AND_RELOAD; - } - } - - return BaseClass::SelectSchedule(); -} - -//------------------------------------- - -void CNPC_Monk::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_RELOAD: - { - if ( GetActiveWeapon() && GetActiveWeapon()->HasPrimaryAmmo() ) - { - // Don't reload if you have done so while moving (See BACK_AWAY_AND_RELOAD schedule). - TaskComplete(); - return; - } - - if( m_iNumZombies >= 2 && random->RandomInt( 1, 3 ) == 1 ) - { - SpeakIfAllowed( TLK_ATTACKING ); - } - - Activity reloadGesture = TranslateActivity( ACT_GESTURE_RELOAD ); - if ( reloadGesture != ACT_INVALID && IsPlayingGesture( reloadGesture ) ) - { - ResetIdealActivity( ACT_IDLE ); - return; - } - - BaseClass::StartTask( pTask ); - } - break; - - default: - BaseClass::StartTask( pTask ); - break; - } -} - - -void CNPC_Monk::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_RELOAD: - { - Activity reloadGesture = TranslateActivity( ACT_GESTURE_RELOAD ); - if ( GetIdealActivity() != ACT_RELOAD && reloadGesture != ACT_INVALID ) - { - if ( !IsPlayingGesture( reloadGesture ) ) - { - if ( GetShotRegulator() ) - { - GetShotRegulator()->Reset( false ); - } - - TaskComplete(); - } - return; - } - - BaseClass::RunTask( pTask ); - } - break; - - default: - BaseClass::RunTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Monk::GatherConditions() -{ - BaseClass::GatherConditions(); - - // Build my zombie danger index! - m_iNumZombies = 0; - m_iDangerousZombies = 0; - - AISightIter_t iter; - CBaseEntity *pSightEnt; - pSightEnt = GetSenses()->GetFirstSeenEntity( &iter ); - while( pSightEnt ) - { - if( pSightEnt->Classify() == CLASS_ZOMBIE && pSightEnt->IsAlive() ) - { - // Is this zombie coming for me? - CAI_BaseNPC *pZombie = dynamic_cast(pSightEnt); - - if( pZombie && pZombie->GetEnemy() == this ) - { - m_iNumZombies++; - - // if this zombie is close enough to attack, add him to the zombie danger! - float flDist; - - flDist = (pZombie->GetAbsOrigin() - GetAbsOrigin()).Length2DSqr(); - - if( flDist <= 128.0f * 128.0f ) - { - m_iDangerousZombies++; - } - } - } - - pSightEnt = GetSenses()->GetNextSeenEntity( &iter ); - } - - if( m_iDangerousZombies >= 3 || (GetEnemy() && GetHealth() < 25) ) - { - // I see many zombies, or I'm quite injured. - SpeakIfAllowed( TLK_HELP_ME ); - } - - // NOTE!!!!!! This code assumes grigori is using annabelle! - ClearCondition(COND_LOW_PRIMARY_AMMO); - if ( GetActiveWeapon() ) - { - if ( GetActiveWeapon()->UsesPrimaryAmmo() ) - { - if (!GetActiveWeapon()->HasPrimaryAmmo() ) - { - SetCondition(COND_NO_PRIMARY_AMMO); - } - else if ( m_NPCState != NPC_STATE_COMBAT && GetActiveWeapon()->UsesClipsForAmmo1() && GetActiveWeapon()->Clip1() < 2 ) - { - // Don't send a low ammo message unless we're not in combat. - SetCondition(COND_LOW_PRIMARY_AMMO); - } - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Monk::PassesDamageFilter( const CTakeDamageInfo &info ) -{ - if ( info.GetAttacker()->ClassMatches( "npc_headcrab_black" ) || info.GetAttacker()->ClassMatches( "npc_headcrab_poison" ) ) - return false; - - return BaseClass::PassesDamageFilter( info ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Monk::OnKilledNPC( CBaseCombatCharacter *pKilled ) -{ - if ( !pKilled ) - { - return; - } - - if ( pKilled->Classify() == CLASS_ZOMBIE ) - { - // Don't speak if the gun is empty, cause grigori will want to speak while he's reloading. - if ( GetActiveWeapon() ) - { - if ( GetActiveWeapon()->UsesPrimaryAmmo() && !GetActiveWeapon()->HasPrimaryAmmo() ) - { - // Gun is empty. I'm about to reload. - if( m_iNumZombies >= 2 ) - { - // Don't talk about killing a single zombie if there are more coming. - // the reload behavior will say "come to me, children", etc. - return; - } - } - } - - if( m_iNumZombies == 1 || random->RandomInt( 1, 3 ) == 1 ) - { - SpeakIfAllowed( TLK_ENEMY_DEAD ); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_Monk::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ) -{ - if( failedSchedule == SCHED_MONK_BACK_AWAY_FROM_ENEMY ) - { - if( HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - { - // Most likely backed into a corner. Just blaze away. - return SCHED_MONK_RANGE_ATTACK1; - } - } - - return BaseClass::SelectFailSchedule( failedSchedule, failedTask, taskFailCode ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Monk::IsJumpLegal( const Vector &startPos, const Vector &apex, const Vector &endPos ) const -{ - if ( startPos.z - endPos.z < 0 ) - return false; - return BaseClass::IsJumpLegal( startPos, apex, endPos ); -} - -//----------------------------------------------------------------------------- -// Every shot's a headshot. Useful for scripted Grigoris -//----------------------------------------------------------------------------- -void CNPC_Monk::InputPerfectAccuracyOn( inputdata_t &inputdata ) -{ - m_bPerfectAccuracy = true; -} - -//----------------------------------------------------------------------------- -// Turn off perfect accuracy. -//----------------------------------------------------------------------------- -void CNPC_Monk::InputPerfectAccuracyOff( inputdata_t &inputdata ) -{ - m_bPerfectAccuracy = false; -} - - -//----------------------------------------------------------------------------- -// -// CNPC_Monk Schedules -// -//----------------------------------------------------------------------------- -AI_BEGIN_CUSTOM_NPC( npc_monk, CNPC_Monk ) - - DECLARE_ACTIVITY( ACT_MONK_GUN_IDLE ) - - DEFINE_SCHEDULE - ( - SCHED_MONK_RANGE_ATTACK1, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_ANNOUNCE_ATTACK 1" // 1 = primary attack - " TASK_RANGE_ATTACK1 0" - "" - " Interrupts" - " COND_HEAVY_DAMAGE" - " COND_ENEMY_OCCLUDED" - " COND_HEAR_DANGER" - " COND_WEAPON_BLOCKED_BY_FRIEND" - " COND_WEAPON_SIGHT_OCCLUDED" - ) - - DEFINE_SCHEDULE - ( - SCHED_MONK_BACK_AWAY_FROM_ENEMY, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_STORE_ENEMY_POSITION_IN_SAVEPOSITION 0" - " TASK_FIND_BACKAWAY_FROM_SAVEPOSITION 0" - " TASK_WALK_PATH_TIMED 4.0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - ); - - DEFINE_SCHEDULE - ( - SCHED_MONK_BACK_AWAY_AND_RELOAD, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_MONK_NORMAL_RELOAD" - " TASK_STOP_MOVING 0" - " TASK_STORE_ENEMY_POSITION_IN_SAVEPOSITION 0" - " TASK_FIND_BACKAWAY_FROM_SAVEPOSITION 0" - " TASK_WALK_PATH_TIMED 2.0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_RELOAD 0" - "" - " Interrupts" - " COND_ENEMY_DEAD" - ); - - DEFINE_SCHEDULE - ( - SCHED_MONK_NORMAL_RELOAD, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_RELOAD 0" - "" - " Interrupts" - " COND_HEAR_DANGER" - ); - - -AI_END_CUSTOM_NPC() diff --git a/game/server/hl2/npc_mossman.cpp b/game/server/hl2/npc_mossman.cpp deleted file mode 100644 index 11dd108b3..000000000 --- a/game/server/hl2/npc_mossman.cpp +++ /dev/null @@ -1,152 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Dr. Mossman, stalwart heroine, doing what is right in the face of -// near certain doom, all while fighting off the clumsy advances of her -// misogynistic colleges. -//=============================================================================// - - -//----------------------------------------------------------------------------- -// Generic NPC - purely for scripted sequence work. -//----------------------------------------------------------------------------- - -#include "cbase.h" -#include "npcevent.h" -#include "ai_basenpc.h" -#include "ai_hull.h" -#include "ai_baseactor.h" -#include "ai_playerally.h" -#include "ai_behavior_follow.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// NPC's Anim Events Go Here -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CNPC_Mossman : public CAI_PlayerAlly -{ -public: - DECLARE_CLASS( CNPC_Mossman, CAI_PlayerAlly ); - DECLARE_DATADESC(); - - void Spawn( void ); - void Precache( void ); - Class_T Classify ( void ); - void HandleAnimEvent( animevent_t *pEvent ); - int GetSoundInterests ( void ); - bool CreateBehaviors( void ); - int SelectSchedule( void ); - -private: - CAI_FollowBehavior m_FollowBehavior; -}; - -LINK_ENTITY_TO_CLASS( npc_mossman, CNPC_Mossman ); - -BEGIN_DATADESC( CNPC_Mossman ) -// DEFINE_FIELD( m_FollowBehavior, FIELD_EMBEDDED ), (auto saved by AI) -END_DATADESC() - -//----------------------------------------------------------------------------- -// Classify - indicates this NPC's place in the -// relationship table. -//----------------------------------------------------------------------------- -Class_T CNPC_Mossman::Classify ( void ) -{ - return CLASS_PLAYER_ALLY_VITAL; -} - - - -//----------------------------------------------------------------------------- -// HandleAnimEvent - catches the NPC-specific messages -// that occur when tagged animation frames are played. -//----------------------------------------------------------------------------- -void CNPC_Mossman::HandleAnimEvent( animevent_t *pEvent ) -{ - switch( pEvent->event ) - { - case 1: - default: - BaseClass::HandleAnimEvent( pEvent ); - break; - } -} - -//----------------------------------------------------------------------------- -// GetSoundInterests - generic NPC can't hear. -//----------------------------------------------------------------------------- -int CNPC_Mossman::GetSoundInterests ( void ) -{ - return 0; -} - -//----------------------------------------------------------------------------- -// Spawn -//----------------------------------------------------------------------------- -void CNPC_Mossman::Spawn() -{ - Precache(); - - BaseClass::Spawn(); - - SetModel( "models/mossman.mdl" ); - - SetHullType(HULL_HUMAN); - SetHullSizeNormal(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - SetBloodColor( BLOOD_COLOR_RED ); - m_iHealth = 8; - m_flFieldOfView = 0.5;// indicates the width of this NPC's forward view cone ( as a dotproduct result ) - m_NPCState = NPC_STATE_NONE; - - CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_OPEN_DOORS | bits_CAP_ANIMATEDFACE | bits_CAP_TURN_HEAD ); - CapabilitiesAdd( bits_CAP_FRIENDLY_DMG_IMMUNE ); - AddEFlags( EFL_NO_DISSOLVE | EFL_NO_MEGAPHYSCANNON_RAGDOLL | EFL_NO_PHYSCANNON_INTERACTION ); - - NPCInit(); -} - -//----------------------------------------------------------------------------- -// Precache - precaches all resources this NPC needs -//----------------------------------------------------------------------------- -void CNPC_Mossman::Precache() -{ - PrecacheModel( "models/mossman.mdl" ); - - BaseClass::Precache(); -} - -//========================================================= -// Purpose: -//========================================================= -bool CNPC_Mossman::CreateBehaviors() -{ - AddBehavior( &m_FollowBehavior ); - - return BaseClass::CreateBehaviors(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_Mossman::SelectSchedule( void ) -{ - if ( !BehaviorSelectSchedule() ) - { - } - - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -// AI Schedules Specific to this NPC -//----------------------------------------------------------------------------- diff --git a/game/server/hl2/npc_playercompanion.cpp b/game/server/hl2/npc_playercompanion.cpp deleted file mode 100644 index 1ad7c9bc4..000000000 --- a/game/server/hl2/npc_playercompanion.cpp +++ /dev/null @@ -1,3997 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" - -#include "npc_playercompanion.h" - -#include "combine_mine.h" -#include "fire.h" -#include "func_tank.h" -#include "globalstate.h" -#include "npcevent.h" -#include "props.h" -#include "BasePropDoor.h" - -#include "ai_hint.h" -#include "ai_localnavigator.h" -#include "ai_memory.h" -#include "ai_pathfinder.h" -#include "ai_route.h" -#include "ai_senses.h" -#include "ai_squad.h" -#include "ai_squadslot.h" -#include "ai_tacticalservices.h" -#include "ai_interactions.h" -#include "filesystem.h" -#include "collisionutils.h" -#include "grenade_frag.h" -#include -#include "physics_npc_solver.h" - -ConVar ai_debug_readiness("ai_debug_readiness", "0" ); -ConVar ai_use_readiness("ai_use_readiness", "1" ); // 0 = off, 1 = on, 2 = on for player squad only -ConVar ai_readiness_decay( "ai_readiness_decay", "120" );// How many seconds it takes to relax completely -ConVar ai_new_aiming( "ai_new_aiming", "1" ); - -#define GetReadinessUse() ai_use_readiness.GetInt() - -extern ConVar g_debug_transitions; - -#define PLAYERCOMPANION_TRANSITION_SEARCH_DISTANCE (100*12) - -int AE_COMPANION_PRODUCE_FLARE; -int AE_COMPANION_LIGHT_FLARE; -int AE_COMPANION_RELEASE_FLARE; - -#define MAX_TIME_BETWEEN_BARRELS_EXPLODING 5.0f -#define MAX_TIME_BETWEEN_CONSECUTIVE_PLAYER_KILLS 3.0f - -//----------------------------------------------------------------------------- -// An aimtarget becomes invalid if it gets this close -//----------------------------------------------------------------------------- -#define COMPANION_AIMTARGET_NEAREST 24.0f -#define COMPANION_AIMTARGET_NEAREST_SQR 576.0f - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -BEGIN_DATADESC( CNPC_PlayerCompanion ) - - DEFINE_FIELD( m_bMovingAwayFromPlayer, FIELD_BOOLEAN ), - DEFINE_EMBEDDED( m_SpeechWatch_PlayerLooking ), - DEFINE_EMBEDDED( m_FakeOutMortarTimer ), - -// (recomputed) -// m_bWeightPathsInCover - -// These are auto-saved by AI -// DEFINE_FIELD( m_AssaultBehavior, CAI_AssaultBehavior ), -// DEFINE_FIELD( m_FollowBehavior, CAI_FollowBehavior ), -// DEFINE_FIELD( m_StandoffBehavior, CAI_StandoffBehavior ), -// DEFINE_FIELD( m_LeadBehavior, CAI_LeadBehavior ), -// DEFINE_FIELD( m_OperatorBehavior, FIELD_EMBEDDED ), -// m_ActBusyBehavior -// m_PassengerBehavior -// m_FearBehavior - - DEFINE_INPUTFUNC( FIELD_VOID, "OutsideTransition", InputOutsideTransition ), - DEFINE_INPUTFUNC( FIELD_VOID, "SetReadinessPanic", InputSetReadinessPanic ), - DEFINE_INPUTFUNC( FIELD_VOID, "SetReadinessStealth", InputSetReadinessStealth ), - DEFINE_INPUTFUNC( FIELD_VOID, "SetReadinessLow", InputSetReadinessLow ), - DEFINE_INPUTFUNC( FIELD_VOID, "SetReadinessMedium", InputSetReadinessMedium ), - DEFINE_INPUTFUNC( FIELD_VOID, "SetReadinessHigh", InputSetReadinessHigh ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "LockReadiness", InputLockReadiness ), - -//------------------------------------------------------------------------------ -#ifdef HL2_EPISODIC - DEFINE_FIELD( m_hFlare, FIELD_EHANDLE ), - - DEFINE_INPUTFUNC( FIELD_STRING, "EnterVehicle", InputEnterVehicle ), - DEFINE_INPUTFUNC( FIELD_STRING, "EnterVehicleImmediately", InputEnterVehicleImmediately ), - DEFINE_INPUTFUNC( FIELD_VOID, "ExitVehicle", InputExitVehicle ), - DEFINE_INPUTFUNC( FIELD_VOID, "CancelEnterVehicle", InputCancelEnterVehicle ), -#endif // HL2_EPISODIC -//------------------------------------------------------------------------------ - - DEFINE_INPUTFUNC( FIELD_STRING, "GiveWeapon", InputGiveWeapon ), - - DEFINE_FIELD( m_flReadiness, FIELD_FLOAT ), - DEFINE_FIELD( m_flReadinessSensitivity, FIELD_FLOAT ), - DEFINE_FIELD( m_bReadinessCapable, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flReadinessLockedUntil, FIELD_TIME ), - DEFINE_FIELD( m_fLastBarrelExploded, FIELD_TIME ), - DEFINE_FIELD( m_iNumConsecutiveBarrelsExploded, FIELD_INTEGER ), - DEFINE_FIELD( m_fLastPlayerKill, FIELD_TIME ), - DEFINE_FIELD( m_iNumConsecutivePlayerKills, FIELD_INTEGER ), - - // m_flBoostSpeed (recomputed) - - DEFINE_EMBEDDED( m_AnnounceAttackTimer ), - - DEFINE_FIELD( m_hAimTarget, FIELD_EHANDLE ), - - DEFINE_KEYFIELD( m_bAlwaysTransition, FIELD_BOOLEAN, "AlwaysTransition" ), - DEFINE_KEYFIELD( m_bDontPickupWeapons, FIELD_BOOLEAN, "DontPickupWeapons" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "EnableAlwaysTransition", InputEnableAlwaysTransition ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableAlwaysTransition", InputDisableAlwaysTransition ), - - DEFINE_INPUTFUNC( FIELD_VOID, "EnableWeaponPickup", InputEnableWeaponPickup ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableWeaponPickup", InputDisableWeaponPickup ), - - -#if HL2_EPISODIC - DEFINE_INPUTFUNC( FIELD_VOID, "ClearAllOutputs", InputClearAllOuputs ), -#endif - - DEFINE_OUTPUT( m_OnWeaponPickup, "OnWeaponPickup" ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -CNPC_PlayerCompanion::eCoverType CNPC_PlayerCompanion::gm_fCoverSearchType; -bool CNPC_PlayerCompanion::gm_bFindingCoverFromAllEnemies; -string_t CNPC_PlayerCompanion::gm_iszMortarClassname; -string_t CNPC_PlayerCompanion::gm_iszFloorTurretClassname; -string_t CNPC_PlayerCompanion::gm_iszGroundTurretClassname; -string_t CNPC_PlayerCompanion::gm_iszShotgunClassname; -string_t CNPC_PlayerCompanion::gm_iszRollerMineClassname; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -bool CNPC_PlayerCompanion::CreateBehaviors() -{ -#ifdef HL2_EPISODIC - AddBehavior( &m_FearBehavior ); - AddBehavior( &m_PassengerBehavior ); -#endif // HL2_EPISODIC - - AddBehavior( &m_ActBusyBehavior ); - -#ifdef HL2_EPISODIC - AddBehavior( &m_OperatorBehavior ); - AddBehavior( &m_StandoffBehavior ); - AddBehavior( &m_AssaultBehavior ); - AddBehavior( &m_FollowBehavior ); - AddBehavior( &m_LeadBehavior ); -#else - AddBehavior( &m_AssaultBehavior ); - AddBehavior( &m_StandoffBehavior ); - AddBehavior( &m_FollowBehavior ); - AddBehavior( &m_LeadBehavior ); -#endif//HL2_EPISODIC - - return BaseClass::CreateBehaviors(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::Precache() -{ - gm_iszMortarClassname = AllocPooledString( "func_tankmortar" ); - gm_iszFloorTurretClassname = AllocPooledString( "npc_turret_floor" ); - gm_iszGroundTurretClassname = AllocPooledString( "npc_turret_ground" ); - gm_iszShotgunClassname = AllocPooledString( "weapon_shotgun" ); - gm_iszRollerMineClassname = AllocPooledString( "npc_rollermine" ); - - PrecacheModel( STRING( GetModelName() ) ); - -#ifdef HL2_EPISODIC - // The flare we're able to pull out - PrecacheModel( "models/props_junk/flare.mdl" ); -#endif // HL2_EPISODIC - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::Spawn() -{ - SelectModel(); - - Precache(); - - SetModel( STRING( GetModelName() ) ); - - SetHullType(HULL_HUMAN); - SetHullSizeNormal(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetBloodColor( BLOOD_COLOR_RED ); - m_flFieldOfView = 0.02; - m_NPCState = NPC_STATE_NONE; - - CapabilitiesClear(); - CapabilitiesAdd( bits_CAP_SQUAD ); - - if ( !HasSpawnFlags( SF_NPC_START_EFFICIENT ) ) - { - CapabilitiesAdd( bits_CAP_ANIMATEDFACE | bits_CAP_TURN_HEAD ); - CapabilitiesAdd( bits_CAP_USE_WEAPONS | bits_CAP_AIM_GUN | bits_CAP_MOVE_SHOOT ); - CapabilitiesAdd( bits_CAP_DUCK | bits_CAP_DOORS_GROUP ); - CapabilitiesAdd( bits_CAP_USE_SHOT_REGULATOR ); - } - CapabilitiesAdd( bits_CAP_NO_HIT_PLAYER | bits_CAP_NO_HIT_SQUADMATES | bits_CAP_FRIENDLY_DMG_IMMUNE ); - CapabilitiesAdd( bits_CAP_MOVE_GROUND ); - SetMoveType( MOVETYPE_STEP ); - - m_HackedGunPos = Vector( 0, 0, 55 ); - - SetAimTarget(NULL); - m_bReadinessCapable = IsReadinessCapable(); - SetReadinessValue( 0.0f ); - SetReadinessSensitivity( random->RandomFloat( 0.7, 1.3 ) ); - m_flReadinessLockedUntil = 0.0f; - - m_AnnounceAttackTimer.Set( 10, 30 ); - -#ifdef HL2_EPISODIC - // We strip this flag because it's been made obsolete by the StartScripting behavior - if ( HasSpawnFlags( SF_NPC_ALTCOLLISION ) ) - { - Warning( "NPC %s using alternate collision! -- DISABLED\n", STRING( GetEntityName() ) ); - RemoveSpawnFlags( SF_NPC_ALTCOLLISION ); - } - - m_hFlare = NULL; -#endif // HL2_EPISODIC - - BaseClass::Spawn(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_PlayerCompanion::Restore( IRestore &restore ) -{ - int baseResult = BaseClass::Restore( restore ); - - if ( gpGlobals->eLoadType == MapLoad_Transition ) - { - m_StandoffBehavior.SetActive( false ); - } - -#ifdef HL2_EPISODIC - // We strip this flag because it's been made obsolete by the StartScripting behavior - if ( HasSpawnFlags( SF_NPC_ALTCOLLISION ) ) - { - Warning( "NPC %s using alternate collision! -- DISABLED\n", STRING( GetEntityName() ) ); - RemoveSpawnFlags( SF_NPC_ALTCOLLISION ); - } -#endif // HL2_EPISODIC - - return baseResult; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_PlayerCompanion::ObjectCaps() -{ - int caps = UsableNPCObjectCaps( BaseClass::ObjectCaps() ); - return caps; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::ShouldAlwaysThink() -{ - return ( BaseClass::ShouldAlwaysThink() || ( GetFollowBehavior().GetFollowTarget() && GetFollowBehavior().GetFollowTarget()->IsPlayer() ) ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Disposition_t CNPC_PlayerCompanion::IRelationType( CBaseEntity *pTarget ) -{ - if ( !pTarget ) - return D_NU; - - Disposition_t baseRelationship = BaseClass::IRelationType( pTarget ); - - if ( baseRelationship != D_LI ) - { - if ( IsTurret( pTarget ) ) - { - // Citizens are afeared of turrets, so long as the turret - // is active... that is, not classifying itself as CLASS_NONE - if( pTarget->Classify() != CLASS_NONE ) - { - if( !hl2_episodic.GetBool() && IsSafeFromFloorTurret(GetAbsOrigin(), pTarget) ) - { - return D_NU; - } - - return D_FR; - } - } - else if ( baseRelationship == D_HT && - pTarget->IsNPC() && - ((CAI_BaseNPC *)pTarget)->GetActiveWeapon() && - ((CAI_BaseNPC *)pTarget)->GetActiveWeapon()->ClassMatches( gm_iszShotgunClassname ) && - ( !GetActiveWeapon() || !GetActiveWeapon()->ClassMatches( gm_iszShotgunClassname ) ) ) - { - if ( (pTarget->GetAbsOrigin() - GetAbsOrigin()).LengthSqr() < Square( 25 * 12 ) ) - { - // Ignore enemies on the floor above us - if ( fabs(pTarget->GetAbsOrigin().z - GetAbsOrigin().z) < 100 ) - return D_FR; - } - } - } - - return baseRelationship; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::IsSilentSquadMember() const -{ - if ( (const_cast(this))->Classify() == CLASS_PLAYER_ALLY_VITAL && m_pSquad && MAKE_STRING(m_pSquad->GetName()) == GetPlayerSquadName() ) - { - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::GatherConditions() -{ - BaseClass::GatherConditions(); - - if ( AI_IsSinglePlayer() ) - { - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - - if ( Classify() == CLASS_PLAYER_ALLY_VITAL ) - { - bool bInPlayerSquad = ( m_pSquad && MAKE_STRING(m_pSquad->GetName()) == GetPlayerSquadName() ); - if ( bInPlayerSquad ) - { - if ( GetState() == NPC_STATE_SCRIPT || ( !HasCondition( COND_SEE_PLAYER ) && (GetAbsOrigin() - pPlayer->GetAbsOrigin()).LengthSqr() > Square(50 * 12) ) ) - { - RemoveFromSquad(); - } - } - else if ( GetState() != NPC_STATE_SCRIPT ) - { - if ( HasCondition( COND_SEE_PLAYER ) && (GetAbsOrigin() - pPlayer->GetAbsOrigin()).LengthSqr() < Square(25 * 12) ) - { - if ( hl2_episodic.GetBool() ) - { - // Don't stomp our squad if we're in one - if ( GetSquad() == NULL ) - { - AddToSquad( GetPlayerSquadName() ); - } - } - else - { - AddToSquad( GetPlayerSquadName() ); - } - } - } - } - - m_flBoostSpeed = 0; - - if ( m_AnnounceAttackTimer.Expired() && - ( GetLastEnemyTime() == 0.0 || gpGlobals->curtime - GetLastEnemyTime() > 20 ) ) - { - // Always delay when an encounter begins - m_AnnounceAttackTimer.Set( 4, 8 ); - } - - if ( GetFollowBehavior().GetFollowTarget() && - ( GetFollowBehavior().GetFollowTarget()->IsPlayer() || GetCommandGoal() != vec3_invalid ) && - GetFollowBehavior().IsMovingToFollowTarget() && - GetFollowBehavior().GetGoalRange() > 0.1 && - BaseClass::GetIdealSpeed() > 0.1 ) - { - Vector vPlayerToFollower = GetAbsOrigin() - pPlayer->GetAbsOrigin(); - float dist = vPlayerToFollower.NormalizeInPlace(); - - bool bDoSpeedBoost = false; - if ( !HasCondition( COND_IN_PVS ) ) - bDoSpeedBoost = true; - else if ( GetFollowBehavior().GetFollowTarget()->IsPlayer() ) - { - if ( dist > GetFollowBehavior().GetGoalRange() * 2 ) - { - float dot = vPlayerToFollower.Dot( pPlayer->EyeDirection3D() ); - if ( dot < 0 ) - { - bDoSpeedBoost = true; - } - } - } - - if ( bDoSpeedBoost ) - { - float lag = dist / GetFollowBehavior().GetGoalRange(); - - float mult; - - if ( lag > 10.0 ) - mult = 2.0; - else if ( lag > 5.0 ) - mult = 1.5; - else if ( lag > 3.0 ) - mult = 1.25; - else - mult = 1.1; - - m_flBoostSpeed = pPlayer->GetSmoothedVelocity().Length(); - - if ( m_flBoostSpeed < BaseClass::GetIdealSpeed() ) - m_flBoostSpeed = BaseClass::GetIdealSpeed(); - - m_flBoostSpeed *= mult; - } - } - } - - // Update our readiness if we're - if ( IsReadinessCapable() ) - { - UpdateReadiness(); - } - - PredictPlayerPush(); - - // Grovel through memories, don't forget enemies parented to func_tankmortar entities. - // !!!LATER - this should really call out and ask if I want to forget the enemy in question. - AIEnemiesIter_t iter; - for( AI_EnemyInfo_t *pMemory = GetEnemies()->GetFirst(&iter); pMemory != NULL; pMemory = GetEnemies()->GetNext(&iter) ) - { - if ( IsMortar( pMemory->hEnemy ) || IsSniper( pMemory->hEnemy ) ) - { - pMemory->bUnforgettable = ( IRelationType( pMemory->hEnemy ) < D_LI ); - pMemory->bEludedMe = false; - } - } - - if ( GetMotor()->IsDeceleratingToGoal() && IsCurTaskContinuousMove() && - HasCondition( COND_PLAYER_PUSHING) && IsCurSchedule( SCHED_MOVE_AWAY ) ) - { - ClearSchedule( "Being pushed by player" ); - } - - CBaseEntity *pEnemy = GetEnemy(); - m_bWeightPathsInCover = false; - if ( pEnemy ) - { - if ( IsMortar( pEnemy ) || IsSniper( pEnemy ) ) - { - m_bWeightPathsInCover = true; - } - } - - ClearCondition( COND_PC_SAFE_FROM_MORTAR ); - if ( IsCurSchedule( SCHED_TAKE_COVER_FROM_BEST_SOUND ) ) - { - CSound *pSound = GetBestSound( SOUND_DANGER ); - - if ( pSound && (pSound->SoundType() & SOUND_CONTEXT_MORTAR) ) - { - float flDistSq = (pSound->GetSoundOrigin() - GetAbsOrigin() ).LengthSqr(); - if ( flDistSq > Square( MORTAR_BLAST_RADIUS + GetHullWidth() * 2 ) ) - SetCondition( COND_PC_SAFE_FROM_MORTAR ); - } - } - - // Handle speech AI. Don't do AI speech if we're in scripts unless permitted by the EnableSpeakWhileScripting input. - if ( m_NPCState == NPC_STATE_IDLE || m_NPCState == NPC_STATE_ALERT || m_NPCState == NPC_STATE_COMBAT || - ( ( m_NPCState == NPC_STATE_SCRIPT ) && CanSpeakWhileScripting() ) ) - { - DoCustomSpeechAI(); - } - - if ( AI_IsSinglePlayer() && hl2_episodic.GetBool() && !GetEnemy() && HasCondition( COND_HEAR_PLAYER ) ) - { - Vector los = ( UTIL_GetLocalPlayer()->EyePosition() - EyePosition() ); - los.z = 0; - VectorNormalize( los ); - - if ( DotProduct( los, EyeDirection2D() ) > DOT_45DEGREE ) - { - ClearCondition( COND_HEAR_PLAYER ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::DoCustomSpeechAI( void ) -{ - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - - // Don't allow this when we're getting in the car -#ifdef HL2_EPISODIC - bool bPassengerInTransition = ( IsInAVehicle() && ( m_PassengerBehavior.GetPassengerState() == PASSENGER_STATE_ENTERING || m_PassengerBehavior.GetPassengerState() == PASSENGER_STATE_EXITING ) ); -#else - bool bPassengerInTransition = false; -#endif - - Vector vecEyePosition = EyePosition(); - if ( bPassengerInTransition == false && pPlayer && pPlayer->FInViewCone( vecEyePosition ) && pPlayer->FVisible( vecEyePosition ) ) - { - if ( m_SpeechWatch_PlayerLooking.Expired() ) - { - SpeakIfAllowed( TLK_LOOK ); - m_SpeechWatch_PlayerLooking.Stop(); - } - } - else - { - m_SpeechWatch_PlayerLooking.Start( 1.0f ); - } - - // Mention the player is dead - if ( HasCondition( COND_TALKER_PLAYER_DEAD ) ) - { - SpeakIfAllowed( TLK_PLDEAD ); - } -} - -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::PredictPlayerPush() -{ - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer && pPlayer->GetSmoothedVelocity().LengthSqr() >= Square(140)) - { - Vector predictedPosition = pPlayer->WorldSpaceCenter() + pPlayer->GetSmoothedVelocity() * .4; - Vector delta = WorldSpaceCenter() - predictedPosition; - if ( delta.z < GetHullHeight() * .5 && delta.Length2DSqr() < Square(GetHullWidth() * 1.414) ) - TestPlayerPushing( pPlayer ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Allows for modification of the interrupt mask for the current schedule. -// In the most cases the base implementation should be called first. -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::BuildScheduleTestBits() -{ - BaseClass::BuildScheduleTestBits(); - - // Always interrupt to get into the car - SetCustomInterruptCondition( COND_PC_BECOMING_PASSENGER ); - - if ( IsCurSchedule(SCHED_RANGE_ATTACK1) ) - { - SetCustomInterruptCondition( COND_PLAYER_PUSHING ); - } - - if ( ( ConditionInterruptsCurSchedule( COND_GIVE_WAY ) || - IsCurSchedule(SCHED_HIDE_AND_RELOAD ) || - IsCurSchedule(SCHED_RELOAD ) || - IsCurSchedule(SCHED_STANDOFF ) || - IsCurSchedule(SCHED_TAKE_COVER_FROM_ENEMY ) || - IsCurSchedule(SCHED_COMBAT_FACE ) || - IsCurSchedule(SCHED_ALERT_FACE ) || - IsCurSchedule(SCHED_COMBAT_STAND ) || - IsCurSchedule(SCHED_ALERT_FACE_BESTSOUND) || - IsCurSchedule(SCHED_ALERT_STAND) ) ) - { - SetCustomInterruptCondition( COND_HEAR_MOVE_AWAY ); - SetCustomInterruptCondition( COND_PLAYER_PUSHING ); - SetCustomInterruptCondition( COND_PC_HURTBYFIRE ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CSound *CNPC_PlayerCompanion::GetBestSound( int validTypes ) -{ - AISoundIter_t iter; - - CSound *pCurrentSound = GetSenses()->GetFirstHeardSound( &iter ); - while ( pCurrentSound ) - { - // the npc cares about this sound, and it's close enough to hear. - if ( pCurrentSound->FIsSound() ) - { - if( pCurrentSound->SoundContext() & SOUND_CONTEXT_MORTAR ) - { - return pCurrentSound; - } - } - - pCurrentSound = GetSenses()->GetNextHeardSound( &iter ); - } - - return BaseClass::GetBestSound( validTypes ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::QueryHearSound( CSound *pSound ) -{ - if( !BaseClass::QueryHearSound(pSound) ) - return false; - - switch( pSound->SoundTypeNoContext() ) - { - case SOUND_READINESS_LOW: - SetReadinessLevel( AIRL_RELAXED, false, true ); - return false; - - case SOUND_READINESS_MEDIUM: - SetReadinessLevel( AIRL_STIMULATED, false, true ); - return false; - - case SOUND_READINESS_HIGH: - SetReadinessLevel( AIRL_AGITATED, false, true ); - return false; - - default: - return true; - } -} - -//----------------------------------------------------------------------------- - -bool CNPC_PlayerCompanion::QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC ) -{ - CAI_BaseNPC *pOther = pEntity->MyNPCPointer(); - if ( pOther && - ( pOther->GetState() == NPC_STATE_ALERT || GetState() == NPC_STATE_ALERT || pOther->GetState() == NPC_STATE_COMBAT || GetState() == NPC_STATE_COMBAT ) && - pOther->IsPlayerAlly() ) - { - return true; - } - - return BaseClass::QuerySeeEntity( pEntity, bOnlyHateOrFearIfNPC ); -} - - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::ShouldIgnoreSound( CSound *pSound ) -{ - if ( !BaseClass::ShouldIgnoreSound( pSound ) ) - { - if ( pSound->IsSoundType( SOUND_DANGER ) && !SoundIsVisible(pSound) ) - return true; - -#ifdef HL2_EPISODIC - // Ignore vehicle sounds when we're driving in them - if ( pSound->m_hOwner && pSound->m_hOwner->GetServerVehicle() != NULL ) - { - if ( m_PassengerBehavior.GetPassengerState() == PASSENGER_STATE_INSIDE && - m_PassengerBehavior.GetTargetVehicle() == pSound->m_hOwner->GetServerVehicle()->GetVehicleEnt() ) - return true; - } -#endif // HL2_EPISODIC - } - - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_PlayerCompanion::SelectSchedule() -{ - m_bMovingAwayFromPlayer = false; - -#ifdef HL2_EPISODIC - // Always defer to passenger if it's running - if ( ShouldDeferToPassengerBehavior() ) - { - DeferSchedulingToBehavior( &m_PassengerBehavior ); - return BaseClass::SelectSchedule(); - } -#endif // HL2_EPISODIC - - if ( m_ActBusyBehavior.IsRunning() && m_ActBusyBehavior.NeedsToPlayExitAnim() ) - { - trace_t tr; - Vector vUp = GetAbsOrigin(); - vUp.z += .25; - - AI_TraceHull( GetAbsOrigin(), vUp, GetHullMins(), - GetHullMaxs(), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.startsolid ) - { - if ( HasCondition( COND_HEAR_DANGER ) ) - { - m_ActBusyBehavior.StopBusying(); - } - DeferSchedulingToBehavior( &m_ActBusyBehavior ); - return BaseClass::SelectSchedule(); - } - } - - int nSched = SelectFlinchSchedule(); - if ( nSched != SCHED_NONE ) - return nSched; - - int schedule = SelectScheduleDanger(); - if ( schedule != SCHED_NONE ) - return schedule; - - schedule = SelectSchedulePriorityAction(); - if ( schedule != SCHED_NONE ) - return schedule; - - if ( ShouldDeferToFollowBehavior() ) - { - DeferSchedulingToBehavior( &(GetFollowBehavior()) ); - } - else if ( !BehaviorSelectSchedule() ) - { - if ( m_NPCState == NPC_STATE_IDLE || m_NPCState == NPC_STATE_ALERT ) - { - schedule = SelectScheduleNonCombat(); - if ( schedule != SCHED_NONE ) - return schedule; - } - else if ( m_NPCState == NPC_STATE_COMBAT ) - { - schedule = SelectScheduleCombat(); - if ( schedule != SCHED_NONE ) - return schedule; - } - } - - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_PlayerCompanion::SelectScheduleDanger() -{ - if( HasCondition( COND_HEAR_DANGER ) ) - { - CSound *pSound; - pSound = GetBestSound( SOUND_DANGER ); - - ASSERT( pSound != NULL ); - - if ( pSound && (pSound->m_iType & SOUND_DANGER) ) - { - if ( !(pSound->SoundContext() & (SOUND_CONTEXT_MORTAR|SOUND_CONTEXT_FROM_SNIPER)) || IsOkToCombatSpeak() ) - SpeakIfAllowed( TLK_DANGER ); - - if ( HasCondition( COND_PC_SAFE_FROM_MORTAR ) ) - { - // Just duck and cover if far away from the explosion, or in cover. - return SCHED_COWER; - } -#if 1 - else if( pSound && (pSound->m_iType & SOUND_CONTEXT_FROM_SNIPER) ) - { - return SCHED_COWER; - } -#endif - - return SCHED_TAKE_COVER_FROM_BEST_SOUND; - } - } - - if ( GetEnemy() && - m_FakeOutMortarTimer.Expired() && - GetFollowBehavior().GetFollowTarget() && - IsMortar( GetEnemy() ) && - assert_cast(GetEnemy())->GetEnemy() == this && - assert_cast(GetEnemy())->FInViewCone( this ) && - assert_cast(GetEnemy())->FVisible( this ) ) - { - m_FakeOutMortarTimer.Set( 7 ); - return SCHED_PC_FAKEOUT_MORTAR; - } - - if ( HasCondition( COND_HEAR_MOVE_AWAY ) ) - return SCHED_MOVE_AWAY; - - if ( HasCondition( COND_PC_HURTBYFIRE ) ) - { - ClearCondition( COND_PC_HURTBYFIRE ); - return SCHED_MOVE_AWAY; - } - - return SCHED_NONE; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_PlayerCompanion::SelectSchedulePriorityAction() -{ - if ( GetGroundEntity() && !IsInAScript() ) - { - if ( GetGroundEntity()->IsPlayer() ) - { - return SCHED_PC_GET_OFF_COMPANION; - } - - if ( GetGroundEntity()->IsNPC() && - IRelationType( GetGroundEntity() ) == D_LI && - WorldSpaceCenter().z - GetGroundEntity()->WorldSpaceCenter().z > GetHullHeight() * .5 ) - { - return SCHED_PC_GET_OFF_COMPANION; - } - } - - int schedule = SelectSchedulePlayerPush(); - if ( schedule != SCHED_NONE ) - { - if ( GetFollowBehavior().IsRunning() ) - KeepRunningBehavior(); - return schedule; - } - - return SCHED_NONE; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_PlayerCompanion::SelectSchedulePlayerPush() -{ - if ( HasCondition( COND_PLAYER_PUSHING ) && !IsInAScript() && !IgnorePlayerPushing() ) - { - // Ignore move away before gordon becomes the man - if ( GlobalEntity_GetState("gordon_precriminal") != GLOBAL_ON ) - { - m_bMovingAwayFromPlayer = true; - return SCHED_MOVE_AWAY; - } - } - - return SCHED_NONE; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::IgnorePlayerPushing( void ) -{ - if ( hl2_episodic.GetBool() ) - { - // Ignore player pushes if we're leading him - if ( m_LeadBehavior.IsRunning() && m_LeadBehavior.HasGoal() ) - return true; - if ( m_AssaultBehavior.IsRunning() && m_AssaultBehavior.OnStrictAssault() ) - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_PlayerCompanion::SelectScheduleCombat() -{ - if ( CanReload() && (HasCondition ( COND_NO_PRIMARY_AMMO ) || HasCondition(COND_LOW_PRIMARY_AMMO)) ) - { - return SCHED_HIDE_AND_RELOAD; - } - - return SCHED_NONE; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::CanReload( void ) -{ - if ( IsRunningDynamicInteraction() ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::ShouldDeferToFollowBehavior() -{ - if ( !GetFollowBehavior().CanSelectSchedule() || !GetFollowBehavior().FarFromFollowTarget() ) - return false; - - if ( m_StandoffBehavior.CanSelectSchedule() && !m_StandoffBehavior.IsBehindBattleLines( GetFollowBehavior().GetFollowTarget()->GetAbsOrigin() ) ) - return false; - - if ( HasCondition(COND_BETTER_WEAPON_AVAILABLE) && !GetActiveWeapon() ) - { - // Unarmed allies should arm themselves as soon as the opportunity presents itself. - return false; - } - - // Even though assault and act busy are placed ahead of the follow behavior in precedence, the below - // code is necessary because we call ShouldDeferToFollowBehavior BEFORE we call the generic - // BehaviorSelectSchedule, which tries the behaviors in priority order. - if ( m_AssaultBehavior.CanSelectSchedule() && hl2_episodic.GetBool() ) - { - return false; - } - - if ( hl2_episodic.GetBool() ) - { - if ( m_ActBusyBehavior.CanSelectSchedule() && m_ActBusyBehavior.IsCombatActBusy() ) - { - return false; - } - } - - return true; -} - -//----------------------------------------------------------------------------- -// CalcReasonableFacing() is asking us if there's any reason why we wouldn't -// want to look in this direction. -// -// Right now this is used to help prevent citizens aiming their guns at each other -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::IsValidReasonableFacing( const Vector &vecSightDir, float sightDist ) -{ - if( !GetActiveWeapon() ) - { - // If I'm not armed, it doesn't matter if I'm looking at another citizen. - return true; - } - - if( ai_new_aiming.GetBool() ) - { - Vector vecEyePositionCentered = GetAbsOrigin(); - vecEyePositionCentered.z = EyePosition().z; - - if( IsSquadmateInSpread(vecEyePositionCentered, vecEyePositionCentered + vecSightDir * 240.0f, VECTOR_CONE_15DEGREES.x, 12.0f * 3.0f) ) - { - return false; - } - } - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_PlayerCompanion::TranslateSchedule( int scheduleType ) -{ - switch( scheduleType ) - { - case SCHED_IDLE_STAND: - case SCHED_ALERT_STAND: - if( GetActiveWeapon() ) - { - // Everyone with less than half a clip takes turns reloading when not fighting. - CBaseCombatWeapon *pWeapon = GetActiveWeapon(); - - if( CanReload() && pWeapon->UsesClipsForAmmo1() && pWeapon->Clip1() < ( pWeapon->GetMaxClip1() * .5 ) && OccupyStrategySlot( SQUAD_SLOT_EXCLUSIVE_RELOAD ) ) - { - if ( AI_IsSinglePlayer() ) - { - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - pWeapon = pPlayer->GetActiveWeapon(); - if( pWeapon && pWeapon->UsesClipsForAmmo1() && - pWeapon->Clip1() < ( pWeapon->GetMaxClip1() * .75 ) && - pPlayer->GetAmmoCount( pWeapon->GetPrimaryAmmoType() ) ) - { - SpeakIfAllowed( TLK_PLRELOAD ); - } - } - return SCHED_RELOAD; - } - } - break; - - case SCHED_COWER: - return SCHED_PC_COWER; - - case SCHED_TAKE_COVER_FROM_BEST_SOUND: - { - CSound *pSound = GetBestSound(SOUND_DANGER); - - if( pSound && pSound->m_hOwner ) - { - if( pSound->m_hOwner->IsNPC() && FClassnameIs( pSound->m_hOwner, "npc_zombine" ) ) - { - // Run fully away from a Zombine with a grenade. - return SCHED_PC_TAKE_COVER_FROM_BEST_SOUND; - } - } - - return SCHED_PC_MOVE_TOWARDS_COVER_FROM_BEST_SOUND; - } - - case SCHED_FLEE_FROM_BEST_SOUND: - return SCHED_PC_FLEE_FROM_BEST_SOUND; - - case SCHED_ESTABLISH_LINE_OF_FIRE: - case SCHED_MOVE_TO_WEAPON_RANGE: - if ( IsMortar( GetEnemy() ) ) - return SCHED_TAKE_COVER_FROM_ENEMY; - break; - - case SCHED_CHASE_ENEMY: - if ( IsMortar( GetEnemy() ) ) - return SCHED_TAKE_COVER_FROM_ENEMY; - if ( GetEnemy() && FClassnameIs( GetEnemy(), "npc_combinegunship" ) ) - return SCHED_ESTABLISH_LINE_OF_FIRE; - break; - - case SCHED_ESTABLISH_LINE_OF_FIRE_FALLBACK: - // If we're fighting a gunship, try again - if ( GetEnemy() && FClassnameIs( GetEnemy(), "npc_combinegunship" ) ) - return SCHED_ESTABLISH_LINE_OF_FIRE; - break; - - case SCHED_RANGE_ATTACK1: - if ( IsMortar( GetEnemy() ) ) - return SCHED_TAKE_COVER_FROM_ENEMY; - - if ( GetShotRegulator()->IsInRestInterval() ) - return SCHED_STANDOFF; - - if( !OccupyStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - return SCHED_STANDOFF; - break; - - case SCHED_FAIL_TAKE_COVER: - if ( IsEnemyTurret() ) - { - return SCHED_PC_FAIL_TAKE_COVER_TURRET; - } - break; - case SCHED_RUN_FROM_ENEMY_FALLBACK: - { - if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - { - return SCHED_RANGE_ATTACK1; - } - break; - } - } - - return BaseClass::TranslateSchedule( scheduleType ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_SOUND_WAKE: - LocateEnemySound(); - SetWait( 0.5 ); - break; - - case TASK_ANNOUNCE_ATTACK: - { - if ( GetActiveWeapon() && m_AnnounceAttackTimer.Expired() ) - { - if ( SpeakIfAllowed( TLK_ATTACKING, UTIL_VarArgs("attacking_with_weapon:%s", GetActiveWeapon()->GetClassname()) ) ) - { - m_AnnounceAttackTimer.Set( 10, 30 ); - } - } - - BaseClass::StartTask( pTask ); - break; - } - - case TASK_PC_WAITOUT_MORTAR: - if ( HasCondition( COND_NO_HEAR_DANGER ) ) - TaskComplete(); - break; - - case TASK_MOVE_AWAY_PATH: - { - if ( m_bMovingAwayFromPlayer ) - SpeakIfAllowed( TLK_PLPUSH ); - - BaseClass::StartTask( pTask ); - } - break; - - case TASK_PC_GET_PATH_OFF_COMPANION: - { - Assert( ( GetGroundEntity() && ( GetGroundEntity()->IsPlayer() || ( GetGroundEntity()->IsNPC() && IRelationType( GetGroundEntity() ) == D_LI ) ) ) ); - GetNavigator()->SetAllowBigStep( GetGroundEntity() ); - ChainStartTask( TASK_MOVE_AWAY_PATH, 48 ); - - /* - trace_t tr; - UTIL_TraceHull( GetAbsOrigin(), GetAbsOrigin(), GetHullMins(), GetHullMaxs(), MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr ); - if ( tr.startsolid && tr.m_pEnt == GetGroundEntity() ) - { - // Allow us to move through the entity for a short time - NPCPhysics_CreateSolver( this, GetGroundEntity(), true, 2.0f ); - } - */ - } - break; - - default: - BaseClass::StartTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_SOUND_WAKE: - if( IsWaitFinished() ) - { - TaskComplete(); - } - break; - - case TASK_PC_WAITOUT_MORTAR: - { - if ( HasCondition( COND_NO_HEAR_DANGER ) ) - TaskComplete(); - } - break; - - case TASK_MOVE_AWAY_PATH: - { - BaseClass::RunTask( pTask ); - - if ( GetNavigator()->IsGoalActive() && !GetEnemy() ) - { - AddFacingTarget( EyePosition() + BodyDirection2D() * 240, 1.0, 2.0 ); - } - } - break; - - case TASK_PC_GET_PATH_OFF_COMPANION: - { - if ( AI_IsSinglePlayer() ) - { - GetNavigator()->SetAllowBigStep( UTIL_GetLocalPlayer() ); - } - ChainRunTask( TASK_MOVE_AWAY_PATH, 48 ); - } - break; - - default: - BaseClass::RunTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -// Parses this NPC's activity remap from the actremap.txt file -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::PrepareReadinessRemap( void ) -{ - CUtlVector< CActivityRemap > entries; - UTIL_LoadActivityRemapFile( "scripts/actremap.txt", "npc_playercompanion", entries ); - - for ( int i = 0; i < entries.Count(); i++ ) - { - CCompanionActivityRemap ActRemap; - Q_memcpy( &ActRemap, &entries[i], sizeof( CActivityRemap ) ); - - KeyValues *pExtraBlock = ActRemap.GetExtraKeyValueBlock(); - - if ( pExtraBlock ) - { - KeyValues *pKey = pExtraBlock->GetFirstSubKey(); - - while ( pKey ) - { - const char *pKeyName = pKey->GetName(); - const char *pKeyValue = pKey->GetString(); - - if ( !stricmp( pKeyName, "readiness" ) ) - { - ActRemap.m_fUsageBits |= bits_REMAP_READINESS; - - if ( !stricmp( pKeyValue, "AIRL_PANIC" ) ) - { - ActRemap.m_readiness = AIRL_PANIC; - } - else if ( !stricmp( pKeyValue, "AIRL_STEALTH" ) ) - { - ActRemap.m_readiness = AIRL_STEALTH; - } - else if ( !stricmp( pKeyValue, "AIRL_RELAXED" ) ) - { - ActRemap.m_readiness = AIRL_RELAXED; - } - else if ( !stricmp( pKeyValue, "AIRL_STIMULATED" ) ) - { - ActRemap.m_readiness = AIRL_STIMULATED; - } - else if ( !stricmp( pKeyValue, "AIRL_AGITATED" ) ) - { - ActRemap.m_readiness = AIRL_AGITATED; - } - } - else if ( !stricmp( pKeyName, "aiming" ) ) - { - ActRemap.m_fUsageBits |= bits_REMAP_AIMING; - - if ( !stricmp( pKeyValue, "TRS_NONE" ) ) - { - // This is the new way to say that we don't care, the tri-state was abandoned (jdw) - ActRemap.m_fUsageBits &= ~bits_REMAP_AIMING; - } - else if ( !stricmp( pKeyValue, "TRS_FALSE" ) || !stricmp( pKeyValue, "FALSE" ) ) - { - ActRemap.m_bAiming = false; - } - else if ( !stricmp( pKeyValue, "TRS_TRUE" ) || !stricmp( pKeyValue, "TRUE" ) ) - { - ActRemap.m_bAiming = true; - } - } - else if ( !stricmp( pKeyName, "weaponrequired" ) ) - { - ActRemap.m_fUsageBits |= bits_REMAP_WEAPON_REQUIRED; - - if ( !stricmp( pKeyValue, "TRUE" ) ) - { - ActRemap.m_bWeaponRequired = true; - } - else if ( !stricmp( pKeyValue, "FALSE" ) ) - { - ActRemap.m_bWeaponRequired = false; - } - } - else if ( !stricmp( pKeyName, "invehicle" ) ) - { - ActRemap.m_fUsageBits |= bits_REMAP_IN_VEHICLE; - - if ( !stricmp( pKeyValue, "TRUE" ) ) - { - ActRemap.m_bInVehicle = true; - } - else if ( !stricmp( pKeyValue, "FALSE" ) ) - { - ActRemap.m_bInVehicle = false; - } - } - - pKey = pKey->GetNextKey(); - } - } - - const char *pActName = ActivityList_NameForIndex( (int)ActRemap.mappedActivity ); - - if ( GetActivityID( pActName ) == ACT_INVALID ) - { - AddActivityToSR( pActName, (int)ActRemap.mappedActivity ); - } - - m_activityMappings.AddToTail( ActRemap ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::Activate( void ) -{ - BaseClass::Activate(); - - PrepareReadinessRemap(); -} - -//----------------------------------------------------------------------------- -// Purpose: Translate an activity given a list of criteria -//----------------------------------------------------------------------------- -Activity CNPC_PlayerCompanion::TranslateActivityReadiness( Activity activity ) -{ - // If we're in an actbusy, we don't want to mess with this - if ( m_ActBusyBehavior.IsActive() ) - return activity; - - if ( m_bReadinessCapable && - ( GetReadinessUse() == AIRU_ALWAYS || - ( GetReadinessUse() == AIRU_ONLY_PLAYER_SQUADMATES && (IsInPlayerSquad()||Classify()==CLASS_PLAYER_ALLY_VITAL) ) ) ) - { - bool bShouldAim = ShouldBeAiming(); - - for ( int i = 0; i < m_activityMappings.Count(); i++ ) - { - // Get our activity remap - CCompanionActivityRemap actremap = m_activityMappings[i]; - - // Activity must match - if ( activity != actremap.activity ) - continue; - - // Readiness must match - if ( ( actremap.m_fUsageBits & bits_REMAP_READINESS ) && GetReadinessLevel() != actremap.m_readiness ) - continue; - - // Deal with weapon state - if ( ( actremap.m_fUsageBits & bits_REMAP_WEAPON_REQUIRED ) && actremap.m_bWeaponRequired ) - { - // Must have a weapon - if ( GetActiveWeapon() == NULL ) - continue; - - // Must either not care about aiming, or agree on aiming - if ( actremap.m_fUsageBits & bits_REMAP_AIMING ) - { - if ( bShouldAim && actremap.m_bAiming == false ) - continue; - - if ( bShouldAim == false && actremap.m_bAiming ) - continue; - } - } - - // Must care about vehicle status - if ( actremap.m_fUsageBits & bits_REMAP_IN_VEHICLE ) - { - // Deal with the two vehicle states - if ( actremap.m_bInVehicle && IsInAVehicle() == false ) - continue; - - if ( actremap.m_bInVehicle == false && IsInAVehicle() ) - continue; - } - - // We've successfully passed all criteria for remapping this - return actremap.mappedActivity; - } - } - - return activity; -} - - -//----------------------------------------------------------------------------- -// Purpose: Override base class activiites -//----------------------------------------------------------------------------- -Activity CNPC_PlayerCompanion::NPC_TranslateActivity( Activity activity ) -{ - if ( activity == ACT_COWER ) - return ACT_COVER_LOW; - - if ( activity == ACT_RUN && ( IsCurSchedule( SCHED_TAKE_COVER_FROM_BEST_SOUND ) || IsCurSchedule( SCHED_FLEE_FROM_BEST_SOUND ) ) ) - { - if ( random->RandomInt( 0, 1 ) && HaveSequenceForActivity( ACT_RUN_PROTECTED ) ) - activity = ACT_RUN_PROTECTED; - } - - activity = BaseClass::NPC_TranslateActivity( activity ); - - if ( activity == ACT_IDLE ) - { - if ( (m_NPCState == NPC_STATE_COMBAT || m_NPCState == NPC_STATE_ALERT) && gpGlobals->curtime - m_flLastAttackTime < 3) - { - activity = ACT_IDLE_ANGRY; - } - } - - return TranslateActivityReadiness( activity ); -} - -//------------------------------------------------------------------------------ -// Purpose: Handle animation events -//------------------------------------------------------------------------------ -void CNPC_PlayerCompanion::HandleAnimEvent( animevent_t *pEvent ) -{ -#ifdef HL2_EPISODIC - // Create a flare and parent to our hand - if ( pEvent->event == AE_COMPANION_PRODUCE_FLARE ) - { - m_hFlare = static_cast(CreateEntityByName( "prop_physics" )); - if ( m_hFlare != NULL ) - { - // Set the model - m_hFlare->SetModel( "models/props_junk/flare.mdl" ); - - // Set the parent attachment - m_hFlare->SetParent( this ); - m_hFlare->SetParentAttachment( "SetParentAttachment", pEvent->options, false ); - } - - return; - } - - // Start the flare up with proper fanfare - if ( pEvent->event == AE_COMPANION_LIGHT_FLARE ) - { - if ( m_hFlare != NULL ) - { - m_hFlare->CreateFlare( 5*60.0f ); - } - - return; - } - - // Drop the flare to the ground - if ( pEvent->event == AE_COMPANION_RELEASE_FLARE ) - { - // Detach - m_hFlare->SetParent( NULL ); - m_hFlare->Spawn(); - m_hFlare->RemoveInteraction( PROPINTER_PHYSGUN_CREATE_FLARE ); - - // Disable collisions between the NPC and the flare - PhysDisableEntityCollisions( this, m_hFlare ); - - // TODO: Find the velocity of the attachment point, at this time, in the animation cycle - - // Construct a toss velocity - Vector vecToss; - AngleVectors( GetAbsAngles(), &vecToss ); - VectorNormalize( vecToss ); - vecToss *= random->RandomFloat( 64.0f, 72.0f ); - vecToss[2] += 64.0f; - - // Throw it - IPhysicsObject *pObj = m_hFlare->VPhysicsGetObject(); - pObj->ApplyForceCenter( vecToss ); - - // Forget about the flare at this point - m_hFlare = NULL; - - return; - } -#endif // HL2_EPISODIC - - switch( pEvent->event ) - { - case EVENT_WEAPON_RELOAD: - if ( GetActiveWeapon() ) - { - GetActiveWeapon()->WeaponSound( RELOAD_NPC ); - GetActiveWeapon()->m_iClip1 = GetActiveWeapon()->GetMaxClip1(); - ClearCondition(COND_LOW_PRIMARY_AMMO); - ClearCondition(COND_NO_PRIMARY_AMMO); - ClearCondition(COND_NO_SECONDARY_AMMO); - } - break; - - default: - BaseClass::HandleAnimEvent( pEvent ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: This is a generic function (to be implemented by sub-classes) to -// handle specific interactions between different types of characters -// (For example the barnacle grabbing an NPC) -// Input : Constant for the type of interaction -// Output : true - if sub-class has a response for the interaction -// false - if sub-class has no response -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt) -{ - if (interactionType == g_interactionHitByPlayerThrownPhysObj ) - { - if ( IsOkToSpeakInResponseToPlayer() ) - { - Speak( TLK_PLYR_PHYSATK ); - } - return true; - } - - return BaseClass::HandleInteraction( interactionType, data, sourceEnt ); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -int CNPC_PlayerCompanion::GetSoundInterests() -{ - return SOUND_WORLD | - SOUND_COMBAT | - SOUND_PLAYER | - SOUND_DANGER | - SOUND_BULLET_IMPACT | - SOUND_MOVE_AWAY | - SOUND_READINESS_LOW | - SOUND_READINESS_MEDIUM | - SOUND_READINESS_HIGH; -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_PlayerCompanion::Touch( CBaseEntity *pOther ) -{ - BaseClass::Touch( pOther ); - - // Did the player touch me? - if ( pOther->IsPlayer() || ( pOther->VPhysicsGetObject() && (pOther->VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) ) ) - { - // Ignore if pissed at player - if ( m_afMemory & bits_MEMORY_PROVOKED ) - return; - - TestPlayerPushing( ( pOther->IsPlayer() ) ? pOther : AI_GetSinglePlayer() ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::ModifyOrAppendCriteria( AI_CriteriaSet& set ) -{ - BaseClass::ModifyOrAppendCriteria( set ); - if ( GetEnemy() && IsMortar( GetEnemy() ) ) - { - set.RemoveCriteria( "enemy" ); - set.AppendCriteria( "enemy", STRING(gm_iszMortarClassname) ); - } - - if ( HasCondition( COND_PC_HURTBYFIRE ) ) - { - set.AppendCriteria( "hurt_by_fire", "1" ); - } - - if ( m_bReadinessCapable ) - { - switch( GetReadinessLevel() ) - { - case AIRL_PANIC: - set.AppendCriteria( "readiness", "panic" ); - break; - - case AIRL_STEALTH: - set.AppendCriteria( "readiness", "stealth" ); - break; - - case AIRL_RELAXED: - set.AppendCriteria( "readiness", "relaxed" ); - break; - - case AIRL_STIMULATED: - set.AppendCriteria( "readiness", "stimulated" ); - break; - - case AIRL_AGITATED: - set.AppendCriteria( "readiness", "agitated" ); - break; - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::IsReadinessCapable() -{ - if ( GlobalEntity_GetState("gordon_precriminal") == GLOBAL_ON ) - return false; - -#ifndef HL2_EPISODIC - // Allow episodic companions to use readiness even if unarmed. This allows for the panicked - // citizens in ep1_c17_05 (sjb) - if( !GetActiveWeapon() ) - return false; -#endif - - if( GetActiveWeapon() && LookupActivity("ACT_IDLE_AIM_RIFLE_STIMULATED") == ACT_INVALID ) - return false; - - if( GetActiveWeapon() && FClassnameIs( GetActiveWeapon(), "weapon_rpg" ) ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::AddReadiness( float flAdd, bool bOverrideLock ) -{ - if( IsReadinessLocked() && !bOverrideLock ) - return; - - SetReadinessValue( GetReadinessValue() + flAdd ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::SubtractReadiness( float flSub, bool bOverrideLock ) -{ - if( IsReadinessLocked() && !bOverrideLock ) - return; - - // Prevent readiness from going below 0 (below 0 is only for scripted states) - SetReadinessValue( MAX(GetReadinessValue() - flSub, 0) ); -} - -//----------------------------------------------------------------------------- -// This method returns false if the NPC is not allowed to change readiness at this point. -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::AllowReadinessValueChange( void ) -{ - if ( GetIdealActivity() == ACT_IDLE || GetIdealActivity() == ACT_WALK || GetIdealActivity() == ACT_RUN ) - return true; - - if ( HasActiveLayer() == true ) - return false; - - return false; -} - -//----------------------------------------------------------------------------- -// NOTE: This function ignores the lock. Use the interface functions. -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::SetReadinessValue( float flSet ) -{ - if ( AllowReadinessValueChange() == false ) - return; - - int priorReadiness = GetReadinessLevel(); - - flSet = MIN( 1.0f, flSet ); - flSet = MAX( READINESS_MIN_VALUE, flSet ); - - m_flReadiness = flSet; - - if( GetReadinessLevel() != priorReadiness ) - { - // We've been bumped up into a different readiness level. - // Interrupt IDLE schedules (if we're playing one) so that - // we can pick the proper animation. - SetCondition( COND_IDLE_INTERRUPT ); - - // Force us to recalculate our animation. If we don't do this, - // our translated activity may change, but not our root activity, - // and then we won't actually visually change anims. - ResetActivity(); - - //Force the NPC to recalculate it's arrival sequence since it'll most likely be wrong now that we changed readiness level. - GetNavigator()->SetArrivalSequence( ACT_INVALID ); - - ReadinessLevelChanged( priorReadiness ); - } -} - -//----------------------------------------------------------------------------- -// if bOverrideLock, you'll change the readiness level even if we're within -// a time period during which someone else has locked the level. -// -// if bSlam, you'll allow the readiness level to be set lower than current. -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::SetReadinessLevel( int iLevel, bool bOverrideLock, bool bSlam ) -{ - if( IsReadinessLocked() && !bOverrideLock ) - return; - - switch( iLevel ) - { - case AIRL_PANIC: - if( bSlam ) - SetReadinessValue( READINESS_MODE_PANIC ); - break; - case AIRL_STEALTH: - if( bSlam ) - SetReadinessValue( READINESS_MODE_STEALTH ); - break; - case AIRL_RELAXED: - if( bSlam || GetReadinessValue() < READINESS_VALUE_RELAXED ) - SetReadinessValue( READINESS_VALUE_RELAXED ); - break; - case AIRL_STIMULATED: - if( bSlam || GetReadinessValue() < READINESS_VALUE_STIMULATED ) - SetReadinessValue( READINESS_VALUE_STIMULATED ); - break; - case AIRL_AGITATED: - if( bSlam || GetReadinessValue() < READINESS_VALUE_AGITATED ) - SetReadinessValue( READINESS_VALUE_AGITATED ); - break; - default: - DevMsg("ERROR: Bad readiness level\n"); - break; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_PlayerCompanion::GetReadinessLevel() -{ - if ( m_bReadinessCapable == false ) - return AIRL_RELAXED; - - if( m_flReadiness == READINESS_MODE_PANIC ) - { - return AIRL_PANIC; - } - - if( m_flReadiness == READINESS_MODE_STEALTH ) - { - return AIRL_STEALTH; - } - - if( m_flReadiness <= READINESS_VALUE_RELAXED ) - { - return AIRL_RELAXED; - } - - if( m_flReadiness <= READINESS_VALUE_STIMULATED ) - { - return AIRL_STIMULATED; - } - - return AIRL_AGITATED; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::UpdateReadiness() -{ - // Only update readiness if it's not in a scripted state - if ( !IsInScriptedReadinessState() ) - { - if( HasCondition(COND_HEAR_COMBAT) || HasCondition(COND_HEAR_BULLET_IMPACT) ) - SetReadinessLevel( AIRL_STIMULATED, false, false ); - - if( HasCondition(COND_HEAR_DANGER) || HasCondition(COND_SEE_ENEMY) ) - SetReadinessLevel( AIRL_AGITATED, false, false ); - - if( m_flReadiness > 0.0f && GetReadinessDecay() > 0 ) - { - // Decay. - SubtractReadiness( ( 0.1 * (1.0f/GetReadinessDecay())) * m_flReadinessSensitivity ); - } - } - - if( ai_debug_readiness.GetBool() && AI_IsSinglePlayer() ) - { - // Draw the readiness-o-meter - Vector vecSpot; - Vector vecOffset( 0, 0, 12 ); - const float BARLENGTH = 12.0f; - const float GRADLENGTH = 4.0f; - - Vector right; - UTIL_PlayerByIndex( 1 )->GetVectors( NULL, &right, NULL ); - - if ( IsInScriptedReadinessState() ) - { - // Just print the name of the scripted state - vecSpot = EyePosition() + vecOffset; - - if( GetReadinessLevel() == AIRL_STEALTH ) - { - NDebugOverlay::Text( vecSpot, "Stealth", true, 0.1 ); - } - else if( GetReadinessLevel() == AIRL_PANIC ) - { - NDebugOverlay::Text( vecSpot, "Panic", true, 0.1 ); - } - else - { - NDebugOverlay::Text( vecSpot, "Unspecified", true, 0.1 ); - } - } - else - { - vecSpot = EyePosition() + vecOffset; - NDebugOverlay::Line( vecSpot, vecSpot + right * GRADLENGTH, 255, 255, 255, false, 0.1 ); - - vecSpot = EyePosition() + vecOffset + Vector( 0, 0, BARLENGTH * READINESS_VALUE_RELAXED ); - NDebugOverlay::Line( vecSpot, vecSpot + right * GRADLENGTH, 0, 255, 0, false, 0.1 ); - - vecSpot = EyePosition() + vecOffset + Vector( 0, 0, BARLENGTH * READINESS_VALUE_STIMULATED ); - NDebugOverlay::Line( vecSpot, vecSpot + right * GRADLENGTH, 255, 255, 0, false, 0.1 ); - - vecSpot = EyePosition() + vecOffset + Vector( 0, 0, BARLENGTH * READINESS_VALUE_AGITATED ); - NDebugOverlay::Line( vecSpot, vecSpot + right * GRADLENGTH, 255, 0, 0, false, 0.1 ); - - vecSpot = EyePosition() + vecOffset; - NDebugOverlay::Line( vecSpot, vecSpot + Vector( 0, 0, BARLENGTH * GetReadinessValue() ), 255, 255, 0, false, 0.1 ); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -float CNPC_PlayerCompanion::GetReadinessDecay() -{ - return ai_readiness_decay.GetFloat(); -} - -//----------------------------------------------------------------------------- -// Passing NULL to clear the aim target is acceptible. -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::SetAimTarget( CBaseEntity *pTarget ) -{ - if( pTarget != NULL && IsAllowedToAim() ) - { - m_hAimTarget = pTarget; - } - else - { - m_hAimTarget = NULL; - } - - Activity NewActivity = NPC_TranslateActivity(GetActivity()); - - //Don't set the ideal activity to an activity that might not be there. - if ( SelectWeightedSequence( NewActivity ) == ACT_INVALID ) - return; - - if (NewActivity != GetActivity() ) - { - SetIdealActivity( NewActivity ); - } - -#if 0 - if( m_hAimTarget ) - { - Msg("New Aim Target: %s\n", m_hAimTarget->GetClassname() ); - NDebugOverlay::Line(EyePosition(), m_hAimTarget->WorldSpaceCenter(), 255, 255, 0, false, 0.1 ); - } -#endif -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::StopAiming( const char *pszReason ) -{ -#if 0 - if( pszReason ) - { - Msg("Stopped aiming because %s\n", pszReason ); - } -#endif - - SetAimTarget(NULL); - - Activity NewActivity = NPC_TranslateActivity(GetActivity()); - if (NewActivity != GetActivity()) - { - SetIdealActivity( NewActivity ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -#define COMPANION_MAX_LOOK_TIME 3.0f -#define COMPANION_MIN_LOOK_TIME 1.0f -#define COMPANION_MAX_TACTICAL_TARGET_DIST 1800.0f // 150 feet - -bool CNPC_PlayerCompanion::PickTacticalLookTarget( AILookTargetArgs_t *pArgs ) -{ - if( HasCondition( COND_SEE_ENEMY ) ) - { - // Don't bother. We're dealing with our enemy. - return false; - } - - float flMinLookTime; - float flMaxLookTime; - - // Excited companions will look at each target only briefly and then find something else to look at. - flMinLookTime = COMPANION_MIN_LOOK_TIME + ((COMPANION_MAX_LOOK_TIME-COMPANION_MIN_LOOK_TIME) * (1.0f - GetReadinessValue()) ); - - switch( GetReadinessLevel() ) - { - case AIRL_RELAXED: - // Linger on targets, look at them for quite a while. - flMinLookTime = COMPANION_MAX_LOOK_TIME + random->RandomFloat( 0.0f, 2.0f ); - break; - - case AIRL_STIMULATED: - // Look around a little quicker. - flMinLookTime = COMPANION_MIN_LOOK_TIME + random->RandomFloat( 0.0f, COMPANION_MAX_LOOK_TIME - 1.0f ); - break; - - case AIRL_AGITATED: - // Look around very quickly - flMinLookTime = COMPANION_MIN_LOOK_TIME; - break; - } - - flMaxLookTime = flMinLookTime + random->RandomFloat( 0.0f, 0.5f ); - pArgs->flDuration = random->RandomFloat( flMinLookTime, flMaxLookTime ); - - if( HasCondition(COND_SEE_PLAYER) && hl2_episodic.GetBool() ) - { - // 1/3rd chance to authoritatively look at player - if( random->RandomInt( 0, 2 ) == 0 ) - { - pArgs->hTarget = AI_GetSinglePlayer(); - return true; - } - } - - // Use hint nodes - CAI_Hint *pHint; - CHintCriteria hintCriteria; - - hintCriteria.AddHintType( HINT_WORLD_VISUALLY_INTERESTING ); - hintCriteria.AddHintType( HINT_WORLD_VISUALLY_INTERESTING_DONT_AIM ); - hintCriteria.AddHintType( HINT_WORLD_VISUALLY_INTERESTING_STEALTH ); - hintCriteria.SetFlag( bits_HINT_NODE_VISIBLE | bits_HINT_NODE_IN_VIEWCONE | bits_HINT_NPC_IN_NODE_FOV ); - hintCriteria.AddIncludePosition( GetAbsOrigin(), COMPANION_MAX_TACTICAL_TARGET_DIST ); - - { - AI_PROFILE_SCOPE( CNPC_PlayerCompanion_FindHint_PickTacticalLookTarget ); - pHint = CAI_HintManager::FindHint( this, hintCriteria ); - } - - if( pHint ) - { - pArgs->hTarget = pHint; - - // Turn this node off for a few seconds to stop others aiming at the same thing (except for stealth nodes) - if ( pHint->HintType() != HINT_WORLD_VISUALLY_INTERESTING_STEALTH ) - { - pHint->DisableForSeconds( 5.0f ); - } - return true; - } - - // See what the base class thinks. - return BaseClass::PickTacticalLookTarget( pArgs ); -} - -//----------------------------------------------------------------------------- -// Returns true if changing target. -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::FindNewAimTarget() -{ - if( GetEnemy() ) - { - // Don't bother. Aim at enemy. - return false; - } - - if( !m_bReadinessCapable || GetReadinessLevel() == AIRL_RELAXED ) - { - // If I'm relaxed (don't want to aim), or physically incapable, - // don't run this hint node searching code. - return false; - } - - CAI_Hint *pHint; - CHintCriteria hintCriteria; - CBaseEntity *pPriorAimTarget = GetAimTarget(); - - hintCriteria.SetHintType( HINT_WORLD_VISUALLY_INTERESTING ); - hintCriteria.SetFlag( bits_HINT_NODE_VISIBLE | bits_HINT_NODE_IN_VIEWCONE | bits_HINT_NPC_IN_NODE_FOV ); - hintCriteria.AddIncludePosition( GetAbsOrigin(), COMPANION_MAX_TACTICAL_TARGET_DIST ); - pHint = CAI_HintManager::FindHint( this, hintCriteria ); - - if( pHint ) - { - if( (pHint->GetAbsOrigin() - GetAbsOrigin()).Length2D() < COMPANION_AIMTARGET_NEAREST ) - { - // Too close! - return false; - } - - if( !HasAimLOS(pHint) ) - { - // No LOS - return false; - } - - if( pHint != pPriorAimTarget ) - { - // Notify of the change. - SetAimTarget( pHint ); - return true; - } - } - - // Didn't find an aim target, or found the same one. - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::OnNewLookTarget() -{ - if( ai_new_aiming.GetBool() ) - { - if( GetLooktarget() ) - { - // See if our looktarget is a reasonable aim target. - CAI_Hint *pHint = dynamic_cast( GetLooktarget() ); - - if( pHint ) - { - if( pHint->HintType() == HINT_WORLD_VISUALLY_INTERESTING && - (pHint->GetAbsOrigin() - GetAbsOrigin()).Length2D() > COMPANION_AIMTARGET_NEAREST && - FInAimCone(pHint->GetAbsOrigin()) && - HasAimLOS(pHint) ) - { - SetAimTarget( pHint ); - return; - } - } - } - - // Search for something else. - FindNewAimTarget(); - } - else - { - if( GetLooktarget() ) - { - // Have picked a new entity to look at. Should we copy it to the aim target? - if( IRelationType( GetLooktarget() ) == D_LI ) - { - // Don't aim at friends, just keep the old target (if any) - return; - } - - if( (GetLooktarget()->GetAbsOrigin() - GetAbsOrigin()).Length2D() < COMPANION_AIMTARGET_NEAREST ) - { - // Too close! - return; - } - - if( !HasAimLOS( GetLooktarget() ) ) - { - // No LOS - return; - } - - SetAimTarget( GetLooktarget() ); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::ShouldBeAiming() -{ - if( !IsAllowedToAim() ) - { - return false; - } - - if( !GetEnemy() && !GetAimTarget() ) - { - return false; - } - - if( GetEnemy() && !HasCondition(COND_SEE_ENEMY) ) - { - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -#define PC_MAX_ALLOWED_AIM 2 -bool CNPC_PlayerCompanion::IsAllowedToAim() -{ - if( !m_pSquad ) - return true; - - if( GetReadinessLevel() == AIRL_AGITATED ) - { - // Agitated companions can always aim. This makes the squad look - // more alert as a whole when something very serious/dangerous has happened. - return true; - } - - int count = 0; - - // If I'm in a squad, only a certain number of us can aim. - AISquadIter_t iter; - for ( CAI_BaseNPC *pSquadmate = m_pSquad->GetFirstMember(&iter); pSquadmate; pSquadmate = m_pSquad->GetNextMember(&iter) ) - { - CNPC_PlayerCompanion *pCompanion = dynamic_cast(pSquadmate); - if( pCompanion && pCompanion != this && pCompanion->GetAimTarget() != NULL ) - { - count++; - } - } - - if( count < PC_MAX_ALLOWED_AIM ) - { - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::HasAimLOS( CBaseEntity *pAimTarget ) -{ - trace_t tr; - UTIL_TraceLine( Weapon_ShootPosition(), pAimTarget->WorldSpaceCenter(), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - if( tr.fraction < 0.5 || (tr.m_pEnt && (tr.m_pEnt->IsNPC()||tr.m_pEnt->IsPlayer())) ) - { - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::AimGun() -{ - Vector vecAimDir; - - if( !GetEnemy() ) - { - if( GetAimTarget() && FInViewCone(GetAimTarget()) ) - { - float flDist; - Vector vecAimTargetLoc = GetAimTarget()->WorldSpaceCenter(); - - flDist = (vecAimTargetLoc - GetAbsOrigin()).Length2DSqr(); - - // Throw away a looktarget if it gets too close. We don't want guys turning around as - // they walk through doorways which contain a looktarget. - if( flDist < COMPANION_AIMTARGET_NEAREST_SQR ) - { - StopAiming("Target too near"); - return; - } - - // Aim at my target if it's in my cone - vecAimDir = vecAimTargetLoc - Weapon_ShootPosition();; - VectorNormalize( vecAimDir ); - SetAim( vecAimDir); - - if( !HasAimLOS(GetAimTarget()) ) - { - // LOS is broken. - if( !FindNewAimTarget() ) - { - // No alternative available right now. Stop aiming. - StopAiming("No LOS"); - } - } - - return; - } - else - { - if( GetAimTarget() ) - { - // We're aiming at something, but we're about to stop because it's out of viewcone. - // Try to find something else. - if( FindNewAimTarget() ) - { - // Found something else to aim at. - return; - } - else - { - // ditch the aim target, it's gone out of view. - StopAiming("Went out of view cone"); - } - } - - if( GetReadinessLevel() == AIRL_AGITATED ) - { - // Aim down! Agitated animations don't have non-aiming versions, so - // just point the weapon down. - Vector vecSpot = EyePosition(); - Vector forward, up; - GetVectors( &forward, NULL, &up ); - vecSpot += forward * 128 + up * -64; - - vecAimDir = vecSpot - Weapon_ShootPosition(); - VectorNormalize( vecAimDir ); - SetAim( vecAimDir); - return; - } - } - } - - BaseClass::AimGun(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CBaseEntity *CNPC_PlayerCompanion::GetAlternateMoveShootTarget() -{ - if( GetAimTarget() && !GetAimTarget()->IsNPC() && GetReadinessLevel() != AIRL_RELAXED ) - { - return GetAimTarget(); - } - - return BaseClass::GetAlternateMoveShootTarget(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::IsValidEnemy( CBaseEntity *pEnemy ) -{ - if ( GetFollowBehavior().GetFollowTarget() && GetFollowBehavior().GetFollowTarget()->IsPlayer() && IsSniper( pEnemy ) ) - { - AI_EnemyInfo_t *pInfo = GetEnemies()->Find( pEnemy ); - if ( pInfo ) - { - if ( gpGlobals->curtime - pInfo->timeLastSeen > 10 ) - { - if ( !((CAI_BaseNPC*)pEnemy)->HasCondition( COND_IN_PVS ) ) - return false; - } - } - } - - return BaseClass::IsValidEnemy( pEnemy ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::IsSafeFromFloorTurret( const Vector &vecLocation, CBaseEntity *pTurret ) -{ - float dist = ( vecLocation - pTurret->EyePosition() ).LengthSqr(); - - if ( dist > Square( 4.0*12.0 ) ) - { - if ( !pTurret->MyNPCPointer()->FInViewCone( vecLocation ) ) - { -#if 0 // Draws a green line to turrets I'm safe from - NDebugOverlay::Line( vecLocation, pTurret->WorldSpaceCenter(), 0, 255, 0, false, 0.1 ); -#endif - return true; - } - } - -#if 0 // Draws a red lines to ones I'm not safe from. - NDebugOverlay::Line( vecLocation, pTurret->WorldSpaceCenter(), 255, 0, 0, false, 0.1 ); -#endif - return false; -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -bool CNPC_PlayerCompanion::ShouldMoveAndShoot( void ) -{ - return BaseClass::ShouldMoveAndShoot(); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -#define PC_LARGER_BURST_RANGE (12.0f * 10.0f) // If an enemy is this close, player companions fire larger continuous bursts. -void CNPC_PlayerCompanion::OnUpdateShotRegulator() -{ - BaseClass::OnUpdateShotRegulator(); - - if( GetEnemy() && HasCondition(COND_CAN_RANGE_ATTACK1) ) - { - if( GetAbsOrigin().DistTo( GetEnemy()->GetAbsOrigin() ) <= PC_LARGER_BURST_RANGE ) - { - if( hl2_episodic.GetBool() ) - { - // Longer burst - int longBurst = random->RandomInt( 10, 15 ); - GetShotRegulator()->SetBurstShotsRemaining( longBurst ); - GetShotRegulator()->SetRestInterval( 0.1, 0.2 ); - } - else - { - // Longer burst - GetShotRegulator()->SetBurstShotsRemaining( GetShotRegulator()->GetBurstShotsRemaining() * 2 ); - - // Shorter Rest interval - float flMinInterval, flMaxInterval; - GetShotRegulator()->GetRestInterval( &flMinInterval, &flMaxInterval ); - GetShotRegulator()->SetRestInterval( flMinInterval * 0.6f, flMaxInterval * 0.6f ); - } - } - } -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_PlayerCompanion::DecalTrace( trace_t *pTrace, char const *decalName ) -{ - // Do not decal a player companion's head or face, no matter what. - if( pTrace->hitgroup == HITGROUP_HEAD ) - return; - - BaseClass::DecalTrace( pTrace, decalName ); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -bool CNPC_PlayerCompanion::FCanCheckAttacks() -{ - if( GetEnemy() && ( IsSniper(GetEnemy()) || IsMortar(GetEnemy()) || IsTurret(GetEnemy()) ) ) - { - // Don't attack the sniper or the mortar. - return false; - } - - return BaseClass::FCanCheckAttacks(); -} - -//----------------------------------------------------------------------------- -// Purpose: Return the actual position the NPC wants to fire at when it's trying -// to hit it's current enemy. -//----------------------------------------------------------------------------- -#define CITIZEN_HEADSHOT_FREQUENCY 3 // one in this many shots at a zombie will be aimed at the zombie's head -Vector CNPC_PlayerCompanion::GetActualShootPosition( const Vector &shootOrigin ) -{ - if( GetEnemy() && GetEnemy()->Classify() == CLASS_ZOMBIE && random->RandomInt( 1, CITIZEN_HEADSHOT_FREQUENCY ) == 1 ) - { - return GetEnemy()->HeadTarget( shootOrigin ); - } - - return BaseClass::GetActualShootPosition( shootOrigin ); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -WeaponProficiency_t CNPC_PlayerCompanion::CalcWeaponProficiency( CBaseCombatWeapon *pWeapon ) -{ - if( FClassnameIs( pWeapon, "weapon_ar2" ) ) - { - return WEAPON_PROFICIENCY_VERY_GOOD; - } - - return WEAPON_PROFICIENCY_PERFECT; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::Weapon_CanUse( CBaseCombatWeapon *pWeapon ) -{ - if( BaseClass::Weapon_CanUse( pWeapon ) ) - { - // If this weapon is a shotgun, take measures to control how many - // are being used in this squad. Don't allow a companion to pick up - // a shotgun if a squadmate already has one. - if( pWeapon->ClassMatches( gm_iszShotgunClassname ) ) - { - return (NumWeaponsInSquad("weapon_shotgun") < 1 ); - } - else - { - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::ShouldLookForBetterWeapon() -{ - if ( m_bDontPickupWeapons ) - return false; - - return BaseClass::ShouldLookForBetterWeapon(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::Weapon_Equip( CBaseCombatWeapon *pWeapon ) -{ - BaseClass::Weapon_Equip( pWeapon ); - m_bReadinessCapable = IsReadinessCapable(); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_PlayerCompanion::PickupWeapon( CBaseCombatWeapon *pWeapon ) -{ - BaseClass::PickupWeapon( pWeapon ); - SpeakIfAllowed( TLK_NEWWEAPON ); - m_OnWeaponPickup.FireOutput( this, this ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -const int MAX_NON_SPECIAL_MULTICOVER = 2; - -CUtlVector g_MultiCoverSearchEnemies; -CNPC_PlayerCompanion * g_pMultiCoverSearcher; - -//------------------------------------- - -int __cdecl MultiCoverCompare( AI_EnemyInfo_t * const *ppLeft, AI_EnemyInfo_t * const *ppRight ) -{ - const AI_EnemyInfo_t *pLeft = *ppLeft; - const AI_EnemyInfo_t *pRight = *ppRight; - - if ( !pLeft->hEnemy && !pRight->hEnemy) - return 0; - - if ( !pLeft->hEnemy ) - return 1; - - if ( !pRight->hEnemy ) - return -1; - - if ( pLeft->hEnemy == g_pMultiCoverSearcher->GetEnemy() ) - return -1; - - if ( pRight->hEnemy == g_pMultiCoverSearcher->GetEnemy() ) - return 1; - - bool bLeftIsSpecial = ( CNPC_PlayerCompanion::IsMortar( pLeft->hEnemy ) || CNPC_PlayerCompanion::IsSniper( pLeft->hEnemy ) ); - bool bRightIsSpecial = ( CNPC_PlayerCompanion::IsMortar( pLeft->hEnemy ) || CNPC_PlayerCompanion::IsSniper( pLeft->hEnemy ) ); - - if ( !bLeftIsSpecial && bRightIsSpecial ) - return 1; - - if ( bLeftIsSpecial && !bRightIsSpecial ) - return -1; - - float leftRelevantTime = ( pLeft->timeLastSeen == AI_INVALID_TIME || pLeft->timeLastSeen == 0 ) ? -99999 : pLeft->timeLastSeen; - if ( pLeft->timeLastReceivedDamageFrom != AI_INVALID_TIME && pLeft->timeLastReceivedDamageFrom > leftRelevantTime ) - leftRelevantTime = pLeft->timeLastReceivedDamageFrom; - - float rightRelevantTime = ( pRight->timeLastSeen == AI_INVALID_TIME || pRight->timeLastSeen == 0 ) ? -99999 : pRight->timeLastSeen; - if ( pRight->timeLastReceivedDamageFrom != AI_INVALID_TIME && pRight->timeLastReceivedDamageFrom > rightRelevantTime ) - rightRelevantTime = pRight->timeLastReceivedDamageFrom; - - if ( leftRelevantTime < rightRelevantTime ) - return -1; - - if ( leftRelevantTime > rightRelevantTime ) - return 1; - - float leftDistSq = g_pMultiCoverSearcher->GetAbsOrigin().DistToSqr( pLeft->hEnemy->GetAbsOrigin() ); - float rightDistSq = g_pMultiCoverSearcher->GetAbsOrigin().DistToSqr( pRight->hEnemy->GetAbsOrigin() ); - - if ( leftDistSq < rightDistSq ) - return -1; - - if ( leftDistSq > rightDistSq ) - return 1; - - return 0; -} - -//------------------------------------- - -void CNPC_PlayerCompanion::SetupCoverSearch( CBaseEntity *pEntity ) -{ - if ( IsTurret( pEntity ) ) - gm_fCoverSearchType = CT_TURRET; - - gm_bFindingCoverFromAllEnemies = false; - g_pMultiCoverSearcher = this; - - if ( Classify() == CLASS_PLAYER_ALLY_VITAL || IsInPlayerSquad() ) - { - if ( GetEnemy() ) - { - if ( !pEntity || GetEnemies()->NumEnemies() > 1 ) - { - if ( !pEntity ) // if pEntity is NULL, test is against a point in space, so always to search against current enemy too - gm_bFindingCoverFromAllEnemies = true; - - AIEnemiesIter_t iter; - for ( AI_EnemyInfo_t *pEnemyInfo = GetEnemies()->GetFirst(&iter); pEnemyInfo != NULL; pEnemyInfo = GetEnemies()->GetNext(&iter) ) - { - CBaseEntity *pEnemy = pEnemyInfo->hEnemy; - if ( pEnemy ) - { - if ( pEnemy != GetEnemy() ) - { - if ( pEnemyInfo->timeAtFirstHand == AI_INVALID_TIME || gpGlobals->curtime - pEnemyInfo->timeLastSeen > 10.0 ) - continue; - gm_bFindingCoverFromAllEnemies = true; - } - g_MultiCoverSearchEnemies.AddToTail( pEnemyInfo ); - } - } - - if ( g_MultiCoverSearchEnemies.Count() == 0 ) - { - gm_bFindingCoverFromAllEnemies = false; - } - else if ( gm_bFindingCoverFromAllEnemies ) - { - g_MultiCoverSearchEnemies.Sort( MultiCoverCompare ); - Assert( g_MultiCoverSearchEnemies[0]->hEnemy == GetEnemy() ); - } - } - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::CleanupCoverSearch() -{ - gm_fCoverSearchType = CT_NORMAL; - g_MultiCoverSearchEnemies.RemoveAll(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::FindCoverPos( CBaseEntity *pEntity, Vector *pResult) -{ - AI_PROFILE_SCOPE(CNPC_PlayerCompanion_FindCoverPos); - - ASSERT_NO_REENTRY(); - - bool result = false; - - SetupCoverSearch( pEntity ); - - if ( gm_bFindingCoverFromAllEnemies ) - { - result = BaseClass::FindCoverPos( pEntity, pResult ); - gm_bFindingCoverFromAllEnemies = false; - } - - if ( !result ) - result = BaseClass::FindCoverPos( pEntity, pResult ); - - CleanupCoverSearch(); - - return result; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -bool CNPC_PlayerCompanion::FindCoverPosInRadius( CBaseEntity *pEntity, const Vector &goalPos, float coverRadius, Vector *pResult ) -{ - AI_PROFILE_SCOPE(CNPC_PlayerCompanion_FindCoverPosInRadius); - - ASSERT_NO_REENTRY(); - - bool result = false; - - SetupCoverSearch( pEntity ); - - if ( gm_bFindingCoverFromAllEnemies ) - { - result = BaseClass::FindCoverPosInRadius( pEntity, goalPos, coverRadius, pResult ); - gm_bFindingCoverFromAllEnemies = false; - } - - if ( !result ) - { - result = BaseClass::FindCoverPosInRadius( pEntity, goalPos, coverRadius, pResult ); - } - - CleanupCoverSearch(); - - return result; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -bool CNPC_PlayerCompanion::FindCoverPos( CSound *pSound, Vector *pResult ) -{ - AI_PROFILE_SCOPE(CNPC_PlayerCompanion_FindCoverPos); - - bool result = false; - bool bIsMortar = ( pSound->SoundContext() == SOUND_CONTEXT_MORTAR ); - - SetupCoverSearch( NULL ); - - if ( gm_bFindingCoverFromAllEnemies ) - { - result = ( bIsMortar ) ? FindMortarCoverPos( pSound, pResult ) : - BaseClass::FindCoverPos( pSound, pResult ); - gm_bFindingCoverFromAllEnemies = false; - } - - if ( !result ) - { - result = ( bIsMortar ) ? FindMortarCoverPos( pSound, pResult ) : - BaseClass::FindCoverPos( pSound, pResult ); - } - - CleanupCoverSearch(); - - return result; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -bool CNPC_PlayerCompanion::FindMortarCoverPos( CSound *pSound, Vector *pResult ) -{ - bool result = false; - - Assert( pSound->SoundContext() == SOUND_CONTEXT_MORTAR ); - gm_fCoverSearchType = CT_MORTAR; - result = GetTacticalServices()->FindLateralCover( pSound->GetSoundOrigin(), 0, pResult ); - if ( !result ) - { - result = GetTacticalServices()->FindCoverPos( pSound->GetSoundOrigin(), - pSound->GetSoundOrigin(), - 0, - CoverRadius(), - pResult ); - } - gm_fCoverSearchType = CT_NORMAL; - - return result; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::IsCoverPosition( const Vector &vecThreat, const Vector &vecPosition ) -{ - if ( gm_bFindingCoverFromAllEnemies ) - { - for ( int i = 0; i < g_MultiCoverSearchEnemies.Count(); i++ ) - { - // @TODO (toml 07-27-04): Should skip checking points near already checked points - AI_EnemyInfo_t *pEnemyInfo = g_MultiCoverSearchEnemies[i]; - Vector testPos; - CBaseEntity *pEnemy = pEnemyInfo->hEnemy; - if ( !pEnemy ) - continue; - - if ( pEnemy == GetEnemy() || IsMortar( pEnemy ) || IsSniper( pEnemy ) || i < MAX_NON_SPECIAL_MULTICOVER ) - { - testPos = pEnemyInfo->vLastKnownLocation + pEnemy->GetViewOffset(); - } - else - break; - - gm_bFindingCoverFromAllEnemies = false; - bool result = IsCoverPosition( testPos, vecPosition ); - gm_bFindingCoverFromAllEnemies = true; - - if ( !result ) - return false; - } - - if ( gm_fCoverSearchType != CT_MORTAR && GetEnemy() && vecThreat.DistToSqr( GetEnemy()->EyePosition() ) < 1 ) - return true; - - // else fall through - } - - if ( gm_fCoverSearchType == CT_TURRET && GetEnemy() && IsSafeFromFloorTurret( vecPosition, GetEnemy() ) ) - { - return true; - } - - if ( gm_fCoverSearchType == CT_MORTAR ) - { - CSound *pSound = GetBestSound( SOUND_DANGER ); - Assert ( pSound && pSound->SoundContext() == SOUND_CONTEXT_MORTAR ); - if( pSound ) - { - // Don't get closer to the shell - Vector vecToSound = vecThreat - GetAbsOrigin(); - Vector vecToPosition = vecPosition - GetAbsOrigin(); - VectorNormalize( vecToPosition ); - VectorNormalize( vecToSound ); - - if ( vecToPosition.AsVector2D().Dot( vecToSound.AsVector2D() ) > 0 ) - return false; - - // Anything outside the radius is okay - float flDistSqr = (vecPosition - vecThreat).Length2DSqr(); - float radiusSq = Square( pSound->Volume() ); - if( flDistSqr > radiusSq ) - { - return true; - } - } - } - - return BaseClass::IsCoverPosition( vecThreat, vecPosition ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::IsMortar( CBaseEntity *pEntity ) -{ - if ( !pEntity ) - return false; - CBaseEntity *pEntityParent = pEntity->GetParent(); - return ( pEntityParent && pEntityParent->GetClassname() == STRING(gm_iszMortarClassname) ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::IsSniper( CBaseEntity *pEntity ) -{ - if ( !pEntity ) - return false; - return ( pEntity->Classify() == CLASS_PROTOSNIPER ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::IsTurret( CBaseEntity *pEntity ) -{ - if ( !pEntity ) - return false; - const char *pszClassname = pEntity->GetClassname(); - return ( pszClassname == STRING(gm_iszFloorTurretClassname) || pszClassname == STRING(gm_iszGroundTurretClassname) ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::IsGunship( CBaseEntity *pEntity ) -{ - if( !pEntity ) - return false; - return (pEntity->Classify() == CLASS_COMBINE_GUNSHIP ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_PlayerCompanion::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - if( info.GetAttacker() ) - { - bool bIsEnvFire; - if( ( bIsEnvFire = FClassnameIs( info.GetAttacker(), "env_fire" ) ) != false || FClassnameIs( info.GetAttacker(), "entityflame" ) || FClassnameIs( info.GetAttacker(), "env_entity_igniter" ) ) - { - GetMotor()->SetIdealYawToTarget( info.GetAttacker()->GetAbsOrigin() ); - SetCondition( COND_PC_HURTBYFIRE ); - } - - // @Note (toml 07-25-04): there isn't a good solution to player companions getting injured by - // fires that have huge damage radii that extend outside the rendered - // fire. Recovery from being injured by fire will also not be done - // before we ship/ Here we trade one bug (guys standing around dying - // from flames they appear to not be near), for a lesser one - // this guy was standing in a fire and didn't react. Since - // the levels are supposed to have the centers of all the fires - // npc clipped, this latter case should be rare. - if ( bIsEnvFire ) - { - if ( ( GetAbsOrigin() - info.GetAttacker()->GetAbsOrigin() ).Length2DSqr() > Square(12 + GetHullWidth() * .5 ) ) - { - return 0; - } - } - } - - return BaseClass::OnTakeDamage_Alive( info ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttackerEnt ) -{ - AI_PROFILE_SCOPE( CNPC_PlayerCompanion_OnFriendDamaged ); - BaseClass::OnFriendDamaged( pSquadmate, pAttackerEnt ); - - CAI_BaseNPC *pAttacker = pAttackerEnt->MyNPCPointer(); - if ( pAttacker ) - { - bool bDirect = ( pSquadmate->FInViewCone(pAttacker) && - ( ( pSquadmate->IsPlayer() && HasCondition(COND_SEE_PLAYER) ) || - ( pSquadmate->MyNPCPointer() && pSquadmate->MyNPCPointer()->IsPlayerAlly() && - GetSenses()->DidSeeEntity( pSquadmate ) ) ) ); - if ( bDirect ) - { - UpdateEnemyMemory( pAttacker, pAttacker->GetAbsOrigin(), pSquadmate ); - } - else - { - if ( FVisible( pSquadmate ) ) - { - AI_EnemyInfo_t *pInfo = GetEnemies()->Find( pAttacker ); - if ( !pInfo || ( gpGlobals->curtime - pInfo->timeLastSeen ) > 15.0 ) - UpdateEnemyMemory( pAttacker, pSquadmate->GetAbsOrigin(), pSquadmate ); - } - } - - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer && IsInPlayerSquad() && ( pPlayer->GetAbsOrigin().AsVector2D() - GetAbsOrigin().AsVector2D() ).LengthSqr() < Square( 25*12 ) && IsAllowedToSpeak( TLK_WATCHOUT ) ) - { - if ( !pPlayer->FInViewCone( pAttacker ) ) - { - Vector2D vPlayerDir = pPlayer->EyeDirection2D().AsVector2D(); - Vector2D vEnemyDir = pAttacker->EyePosition().AsVector2D() - pPlayer->EyePosition().AsVector2D(); - vEnemyDir.NormalizeInPlace(); - float dot = vPlayerDir.Dot( vEnemyDir ); - if ( dot < 0 ) - Speak( TLK_WATCHOUT, "dangerloc:behind" ); - else if ( ( pPlayer->GetAbsOrigin().AsVector2D() - pAttacker->GetAbsOrigin().AsVector2D() ).LengthSqr() > Square( 40*12 ) ) - Speak( TLK_WATCHOUT, "dangerloc:far" ); - } - else if ( pAttacker->GetAbsOrigin().z - pPlayer->GetAbsOrigin().z > 128 ) - { - Speak( TLK_WATCHOUT, "dangerloc:above" ); - } - else if ( pAttacker->GetHullType() <= HULL_TINY && ( pPlayer->GetAbsOrigin().AsVector2D() - pAttacker->GetAbsOrigin().AsVector2D() ).LengthSqr() > Square( 100*12 ) ) - { - Speak( TLK_WATCHOUT, "dangerloc:far" ); - } - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::IsValidMoveAwayDest( const Vector &vecDest ) -{ - // Don't care what the destination is unless I have an enemy and - // that enemy is a sniper (for now). - if( !GetEnemy() ) - { - return true; - } - - if( GetEnemy()->Classify() != CLASS_PROTOSNIPER ) - { - return true; - } - - if( IsCoverPosition( GetEnemy()->EyePosition(), vecDest + GetViewOffset() ) ) - { - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::FValidateHintType( CAI_Hint *pHint ) -{ - switch( pHint->HintType() ) - { - case HINT_PLAYER_SQUAD_TRANSITON_POINT: - case HINT_WORLD_VISUALLY_INTERESTING_DONT_AIM: - case HINT_PLAYER_ALLY_MOVE_AWAY_DEST: - case HINT_PLAYER_ALLY_FEAR_DEST: - return true; - break; - - default: - break; - } - - return BaseClass::FValidateHintType( pHint ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::ValidateNavGoal() -{ - bool result; - if ( GetNavigator()->GetGoalType() == GOALTYPE_COVER ) - { - if ( IsEnemyTurret() ) - gm_fCoverSearchType = CT_TURRET; - } - result = BaseClass::ValidateNavGoal(); - gm_fCoverSearchType = CT_NORMAL; - return result; -} - -const float AVOID_TEST_DIST = 18.0f*12.0f; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -#define COMPANION_EPISODIC_AVOID_ENTITY_FLAME_RADIUS 18.0f -bool CNPC_PlayerCompanion::OverrideMove( float flInterval ) -{ - bool overrode = BaseClass::OverrideMove( flInterval ); - - if ( !overrode && GetNavigator()->GetGoalType() != GOALTYPE_NONE ) - { - string_t iszEnvFire = AllocPooledString( "env_fire" ); - string_t iszBounceBomb = AllocPooledString( "combine_mine" ); - -#ifdef HL2_EPISODIC - string_t iszNPCTurretFloor = AllocPooledString( "npc_turret_floor" ); - string_t iszEntityFlame = AllocPooledString( "entityflame" ); -#endif // HL2_EPISODIC - - if ( IsCurSchedule( SCHED_TAKE_COVER_FROM_BEST_SOUND ) ) - { - CSound *pSound = GetBestSound( SOUND_DANGER ); - if( pSound && pSound->SoundContext() == SOUND_CONTEXT_MORTAR ) - { - // Try not to get any closer to the center - GetLocalNavigator()->AddObstacle( pSound->GetSoundOrigin(), (pSound->GetSoundOrigin() - GetAbsOrigin()).Length2D() * 0.5, AIMST_AVOID_DANGER ); - } - } - - CBaseEntity *pEntity = NULL; - trace_t tr; - - // For each possible entity, compare our known interesting classnames to its classname, via ID - while( ( pEntity = OverrideMoveCache_FindTargetsInRadius( pEntity, GetAbsOrigin(), AVOID_TEST_DIST ) ) != NULL ) - { - // Handle each type - if ( pEntity->m_iClassname == iszEnvFire ) - { - Vector vMins, vMaxs; - if ( FireSystem_GetFireDamageDimensions( pEntity, &vMins, &vMaxs ) ) - { - UTIL_TraceLine( WorldSpaceCenter(), pEntity->WorldSpaceCenter(), MASK_FIRE_SOLID, pEntity, COLLISION_GROUP_NONE, &tr ); - if (tr.fraction == 1.0 && !tr.startsolid) - { - GetLocalNavigator()->AddObstacle( pEntity->GetAbsOrigin(), ( ( vMaxs.x - vMins.x ) * 1.414 * 0.5 ) + 6.0, AIMST_AVOID_DANGER ); - } - } - } -#ifdef HL2_EPISODIC - else if ( pEntity->m_iClassname == iszNPCTurretFloor ) - { - UTIL_TraceLine( WorldSpaceCenter(), pEntity->WorldSpaceCenter(), MASK_BLOCKLOS, pEntity, COLLISION_GROUP_NONE, &tr ); - if (tr.fraction == 1.0 && !tr.startsolid) - { - float radius = 1.4 * pEntity->CollisionProp()->BoundingRadius2D(); - GetLocalNavigator()->AddObstacle( pEntity->WorldSpaceCenter(), radius, AIMST_AVOID_OBJECT ); - } - } - else if( pEntity->m_iClassname == iszEntityFlame && pEntity->GetParent() && !pEntity->GetParent()->IsNPC() ) - { - float flDist = pEntity->WorldSpaceCenter().DistTo( WorldSpaceCenter() ); - - if( flDist > COMPANION_EPISODIC_AVOID_ENTITY_FLAME_RADIUS ) - { - // If I'm not in the flame, prevent me from getting close to it. - // If I AM in the flame, avoid placing an obstacle until the flame frightens me away from itself. - UTIL_TraceLine( WorldSpaceCenter(), pEntity->WorldSpaceCenter(), MASK_BLOCKLOS, pEntity, COLLISION_GROUP_NONE, &tr ); - if (tr.fraction == 1.0 && !tr.startsolid) - { - GetLocalNavigator()->AddObstacle( pEntity->WorldSpaceCenter(), COMPANION_EPISODIC_AVOID_ENTITY_FLAME_RADIUS, AIMST_AVOID_OBJECT ); - } - } - } -#endif // HL2_EPISODIC - else if ( pEntity->m_iClassname == iszBounceBomb ) - { - CBounceBomb *pBomb = static_cast(pEntity); - if ( pBomb && !pBomb->IsPlayerPlaced() && pBomb->IsAwake() ) - { - UTIL_TraceLine( WorldSpaceCenter(), pEntity->WorldSpaceCenter(), MASK_BLOCKLOS, pEntity, COLLISION_GROUP_NONE, &tr ); - if (tr.fraction == 1.0 && !tr.startsolid) - { - GetLocalNavigator()->AddObstacle( pEntity->GetAbsOrigin(), BOUNCEBOMB_DETONATE_RADIUS * .8, AIMST_AVOID_DANGER ); - } - } - } - } - } - - return overrode; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::MovementCost( int moveType, const Vector &vecStart, const Vector &vecEnd, float *pCost ) -{ - bool bResult = BaseClass::MovementCost( moveType, vecStart, vecEnd, pCost ); - if ( moveType == bits_CAP_MOVE_GROUND ) - { - if ( IsCurSchedule( SCHED_TAKE_COVER_FROM_BEST_SOUND ) ) - { - CSound *pSound = GetBestSound( SOUND_DANGER ); - if( pSound && (pSound->SoundContext() & (SOUND_CONTEXT_MORTAR|SOUND_CONTEXT_FROM_SNIPER)) ) - { - Vector vecToSound = pSound->GetSoundReactOrigin() - GetAbsOrigin(); - Vector vecToPosition = vecEnd - GetAbsOrigin(); - VectorNormalize( vecToPosition ); - VectorNormalize( vecToSound ); - - if ( vecToPosition.AsVector2D().Dot( vecToSound.AsVector2D() ) > 0 ) - { - *pCost *= 1.5; - bResult = true; - } - } - } - - if ( m_bWeightPathsInCover && GetEnemy() ) - { - if ( BaseClass::IsCoverPosition( GetEnemy()->EyePosition(), vecEnd ) ) - { - *pCost *= 0.1; - bResult = true; - } - } - } - return bResult; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -float CNPC_PlayerCompanion::GetIdealSpeed() const -{ - float baseSpeed = BaseClass::GetIdealSpeed(); - - if ( baseSpeed < m_flBoostSpeed ) - return m_flBoostSpeed; - - return baseSpeed; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -float CNPC_PlayerCompanion::GetIdealAccel() const -{ - float multiplier = 1.0; - if ( AI_IsSinglePlayer() ) - { - if ( m_bMovingAwayFromPlayer && (UTIL_PlayerByIndex(1)->GetAbsOrigin() - GetAbsOrigin()).Length2DSqr() < Square(3.0*12.0) ) - multiplier = 2.0; - } - return BaseClass::GetIdealAccel() * multiplier; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ) -{ - if ( pMoveGoal->directTrace.flTotalDist - pMoveGoal->directTrace.flDistObstructed < GetHullWidth() * 1.5 ) - { - CAI_BaseNPC *pBlocker = pMoveGoal->directTrace.pObstruction->MyNPCPointer(); - if ( pBlocker && pBlocker->IsPlayerAlly() && !pBlocker->IsMoving() && !pBlocker->IsInAScript() && - ( IsCurSchedule( SCHED_NEW_WEAPON ) || - IsCurSchedule( SCHED_GET_HEALTHKIT ) || - pBlocker->IsCurSchedule( SCHED_FAIL ) || - ( IsInPlayerSquad() && !pBlocker->IsInPlayerSquad() ) || - Classify() == CLASS_PLAYER_ALLY_VITAL || - IsInAScript() ) ) - - { - if ( pBlocker->ConditionInterruptsCurSchedule( COND_GIVE_WAY ) || - pBlocker->ConditionInterruptsCurSchedule( COND_PLAYER_PUSHING ) ) - { - // HACKHACK - pBlocker->GetMotor()->SetIdealYawToTarget( WorldSpaceCenter() ); - pBlocker->SetSchedule( SCHED_MOVE_AWAY ); - } - - } - } - - if ( pMoveGoal->directTrace.pObstruction ) - { - } - - return BaseClass::OnObstructionPreSteer( pMoveGoal, distClear, pResult ); -} - -//----------------------------------------------------------------------------- -// Purpose: Whether or not we should always transition with the player -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::ShouldAlwaysTransition( void ) -{ - // No matter what, come through - if ( m_bAlwaysTransition ) - return true; - - // Squadmates always come with - if ( IsInPlayerSquad() ) - return true; - - // If we're following the player, then come along - if ( GetFollowBehavior().GetFollowTarget() && GetFollowBehavior().GetFollowTarget()->IsPlayer() ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::InputOutsideTransition( inputdata_t &inputdata ) -{ - if ( !AI_IsSinglePlayer() ) - return; - - // Must want to do this - if ( ShouldAlwaysTransition() == false ) - return; - - // If we're in a vehicle, that vehicle will transition with us still inside (which is preferable) - if ( IsInAVehicle() ) - return; - - CBaseEntity *pPlayer = UTIL_GetLocalPlayer(); - const Vector &playerPos = pPlayer->GetAbsOrigin(); - - // Mark us as already having succeeded if we're vital or always meant to come with the player - bool bAlwaysTransition = ( ( Classify() == CLASS_PLAYER_ALLY_VITAL ) || m_bAlwaysTransition ); - bool bPathToPlayer = bAlwaysTransition; - - if ( bAlwaysTransition == false ) - { - AI_Waypoint_t *pPathToPlayer = GetPathfinder()->BuildRoute( GetAbsOrigin(), playerPos, pPlayer, 0 ); - - if ( pPathToPlayer ) - { - bPathToPlayer = true; - CAI_Path tempPath; - tempPath.SetWaypoints( pPathToPlayer ); // path object will delete waypoints - GetPathfinder()->UnlockRouteNodes( pPathToPlayer ); - } - } - - -#ifdef USE_PATHING_LENGTH_REQUIREMENT_FOR_TELEPORT - float pathLength = tempPath.GetPathDistanceToGoal( GetAbsOrigin() ); - - if ( pathLength > 150 * 12 ) - return; -#endif - - bool bMadeIt = false; - Vector teleportLocation; - - CAI_Hint *pHint = CAI_HintManager::FindHint( this, HINT_PLAYER_SQUAD_TRANSITON_POINT, bits_HINT_NODE_NEAREST, PLAYERCOMPANION_TRANSITION_SEARCH_DISTANCE, &playerPos ); - while ( pHint ) - { - pHint->Lock(this); - pHint->Unlock(0.5); // prevent other squadmates and self from using during transition. - - pHint->GetPosition( GetHullType(), &teleportLocation ); - if ( GetNavigator()->CanFitAtPosition( teleportLocation, MASK_NPCSOLID ) ) - { - bMadeIt = true; - if ( !bPathToPlayer && ( playerPos - GetAbsOrigin() ).LengthSqr() > Square(40*12) ) - { - AI_Waypoint_t *pPathToTeleport = GetPathfinder()->BuildRoute( GetAbsOrigin(), teleportLocation, pPlayer, 0 ); - - if ( !pPathToTeleport ) - { - DevMsg( 2, "NPC \"%s\" failed to teleport to transition a point because there is no path\n", STRING(GetEntityName()) ); - bMadeIt = false; - } - else - { - CAI_Path tempPath; - GetPathfinder()->UnlockRouteNodes( pPathToTeleport ); - tempPath.SetWaypoints( pPathToTeleport ); // path object will delete waypoints - } - } - - if ( bMadeIt ) - { - DevMsg( 2, "NPC \"%s\" teleported to transition point %d\n", STRING(GetEntityName()), pHint->GetNodeId() ); - break; - } - } - else - { - if ( g_debug_transitions.GetBool() ) - { - NDebugOverlay::Box( teleportLocation, GetHullMins(), GetHullMaxs(), 255,0,0, 8, 999 ); - } - } - pHint = CAI_HintManager::FindHint( this, HINT_PLAYER_SQUAD_TRANSITON_POINT, bits_HINT_NODE_NEAREST, PLAYERCOMPANION_TRANSITION_SEARCH_DISTANCE, &playerPos ); - } - if ( !bMadeIt ) - { - // Force us if we didn't find a normal route - if ( bAlwaysTransition ) - { - bMadeIt = FindSpotForNPCInRadius( &teleportLocation, pPlayer->GetAbsOrigin(), this, 32.0*1.414, true ); - if ( !bMadeIt ) - bMadeIt = FindSpotForNPCInRadius( &teleportLocation, pPlayer->GetAbsOrigin(), this, 32.0*1.414, false ); - } - } - - if ( bMadeIt ) - { - Teleport( &teleportLocation, NULL, NULL ); - } - else - { - DevMsg( 2, "NPC \"%s\" failed to find a suitable transition a point\n", STRING(GetEntityName()) ); - } - - BaseClass::InputOutsideTransition( inputdata ); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_PlayerCompanion::InputSetReadinessPanic( inputdata_t &inputdata ) -{ - SetReadinessLevel( AIRL_PANIC, true, true ); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_PlayerCompanion::InputSetReadinessStealth( inputdata_t &inputdata ) -{ - SetReadinessLevel( AIRL_STEALTH, true, true ); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_PlayerCompanion::InputSetReadinessLow( inputdata_t &inputdata ) -{ - SetReadinessLevel( AIRL_RELAXED, true, true ); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_PlayerCompanion::InputSetReadinessMedium( inputdata_t &inputdata ) -{ - SetReadinessLevel( AIRL_STIMULATED, true, true ); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_PlayerCompanion::InputSetReadinessHigh( inputdata_t &inputdata ) -{ - SetReadinessLevel( AIRL_AGITATED, true, true ); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_PlayerCompanion::InputLockReadiness( inputdata_t &inputdata ) -{ - float value = inputdata.value.Float(); - LockReadiness( value ); -} - -//----------------------------------------------------------------------------- -// Purpose: Locks the readiness state of the NCP -// Input : time - if -1, the lock is effectively infinite -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::LockReadiness( float duration ) -{ - if ( duration == -1.0f ) - { - m_flReadinessLockedUntil = FLT_MAX; - } - else - { - m_flReadinessLockedUntil = gpGlobals->curtime + duration; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Unlocks the readiness state -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::UnlockReadiness( void ) -{ - // Set to the past - m_flReadinessLockedUntil = gpGlobals->curtime - 0.1f; -} - -//------------------------------------------------------------------------------ -#ifdef HL2_EPISODIC - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::ShouldDeferToPassengerBehavior( void ) -{ - if ( m_PassengerBehavior.CanSelectSchedule() ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Determines if this player companion is capable of entering a vehicle -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::CanEnterVehicle( void ) -{ - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::CanExitVehicle( void ) -{ - // See if we can exit our vehicle - CPropJeepEpisodic *pVehicle = dynamic_cast(m_PassengerBehavior.GetTargetVehicle()); - if ( pVehicle != NULL && pVehicle->NPC_CanExitVehicle( this, true ) == false ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *lpszVehicleName - -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::EnterVehicle( CBaseEntity *pEntityVehicle, bool bImmediately ) -{ - // Must be allowed to do this - if ( CanEnterVehicle() == false ) - return; - - // Find the target vehicle - CPropJeepEpisodic *pVehicle = dynamic_cast(pEntityVehicle); - - // Get in the car if it's valid - if ( pVehicle != NULL && pVehicle->NPC_CanEnterVehicle( this, true ) ) - { - // Set her into a "passenger" behavior - m_PassengerBehavior.Enable( pVehicle, bImmediately ); - m_PassengerBehavior.EnterVehicle(); - - // Only do this if we're outside the vehicle - if ( m_PassengerBehavior.GetPassengerState() == PASSENGER_STATE_OUTSIDE ) - { - SetCondition( COND_PC_BECOMING_PASSENGER ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Get into the requested vehicle -// Input : &inputdata - contains the entity name of the vehicle to enter -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::InputEnterVehicle( inputdata_t &inputdata ) -{ - CBaseEntity *pEntity = FindNamedEntity( inputdata.value.String() ); - EnterVehicle( pEntity, false ); -} - -//----------------------------------------------------------------------------- -// Purpose: Get into the requested vehicle immediately (no animation, pop) -// Input : &inputdata - contains the entity name of the vehicle to enter -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::InputEnterVehicleImmediately( inputdata_t &inputdata ) -{ - CBaseEntity *pEntity = FindNamedEntity( inputdata.value.String() ); - EnterVehicle( pEntity, true ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::InputExitVehicle( inputdata_t &inputdata ) -{ - // See if we're allowed to exit the vehicle - if ( CanExitVehicle() == false ) - return; - - m_PassengerBehavior.ExitVehicle(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::InputCancelEnterVehicle( inputdata_t &inputdata ) -{ - m_PassengerBehavior.CancelEnterVehicle(); -} - -//----------------------------------------------------------------------------- -// Purpose: Forces the NPC out of the vehicle they're riding in -// Input : bImmediate - If we need to exit immediately, teleport to any exit location -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::ExitVehicle( void ) -{ - // For now just get out - m_PassengerBehavior.ExitVehicle(); - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::IsInAVehicle( void ) const -{ - // Must be active and getting in/out of vehicle - if ( m_PassengerBehavior.IsEnabled() && m_PassengerBehavior.GetPassengerState() != PASSENGER_STATE_OUTSIDE ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : IServerVehicle - -//----------------------------------------------------------------------------- -IServerVehicle *CNPC_PlayerCompanion::GetVehicle( void ) -{ - if ( IsInAVehicle() ) - { - CPropVehicleDriveable *pDriveableVehicle = m_PassengerBehavior.GetTargetVehicle(); - if ( pDriveableVehicle != NULL ) - return pDriveableVehicle->GetServerVehicle(); - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CBaseEntity -//----------------------------------------------------------------------------- -CBaseEntity *CNPC_PlayerCompanion::GetVehicleEntity( void ) -{ - if ( IsInAVehicle() ) - { - CPropVehicleDriveable *pDriveableVehicle = m_PassengerBehavior.GetTargetVehicle(); - return pDriveableVehicle; - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Override our efficiency so that we don't jitter when we're in the middle -// of our enter/exit animations. -// Input : bInPVS - Whether we're in the PVS or not -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::UpdateEfficiency( bool bInPVS ) -{ - // If we're transitioning and in the PVS, we override our efficiency - if ( IsInAVehicle() && bInPVS ) - { - PassengerState_e nState = m_PassengerBehavior.GetPassengerState(); - if ( nState == PASSENGER_STATE_ENTERING || nState == PASSENGER_STATE_EXITING ) - { - SetEfficiency( AIE_NORMAL ); - return; - } - } - - // Do the default behavior - BaseClass::UpdateEfficiency( bInPVS ); -} - -//----------------------------------------------------------------------------- -// Purpose: Whether or not we can dynamically interact with another NPC -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::CanRunAScriptedNPCInteraction( bool bForced /*= false*/ ) -{ - // TODO: Allow this but only for interactions who stem from being in a vehicle? - if ( IsInAVehicle() ) - return false; - - return BaseClass::CanRunAScriptedNPCInteraction( bForced ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::IsAllowedToDodge( void ) -{ - // TODO: Allow this but only for interactions who stem from being in a vehicle? - if ( IsInAVehicle() ) - return false; - - return BaseClass::IsAllowedToDodge(); -} - -#endif //HL2_EPISODIC -//------------------------------------------------------------------------------ - -//----------------------------------------------------------------------------- -// Purpose: Always transition along with the player -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::InputEnableAlwaysTransition( inputdata_t &inputdata ) -{ - m_bAlwaysTransition = true; -} - -//----------------------------------------------------------------------------- -// Purpose: Stop always transitioning along with the player -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::InputDisableAlwaysTransition( inputdata_t &inputdata ) -{ - m_bAlwaysTransition = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Stop picking up weapons from the ground -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::InputEnableWeaponPickup( inputdata_t &inputdata ) -{ - m_bDontPickupWeapons = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Return to default behavior of picking up better weapons on the ground -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::InputDisableWeaponPickup( inputdata_t &inputdata ) -{ - m_bDontPickupWeapons = true; -} - -//------------------------------------------------------------------------------ -// Purpose: Give the NPC in question the weapon specified -//------------------------------------------------------------------------------ -void CNPC_PlayerCompanion::InputGiveWeapon( inputdata_t &inputdata ) -{ - // Give the NPC the specified weapon - string_t iszWeaponName = inputdata.value.StringID(); - if ( iszWeaponName != NULL_STRING ) - { - if( Classify() == CLASS_PLAYER_ALLY_VITAL ) - { - m_iszPendingWeapon = iszWeaponName; - } - else - { - GiveWeapon( iszWeaponName ); - } - } -} - -#if HL2_EPISODIC -//------------------------------------------------------------------------------ -// Purpose: Delete all outputs from this NPC. -//------------------------------------------------------------------------------ -void CNPC_PlayerCompanion::InputClearAllOuputs( inputdata_t &inputdata ) -{ - datamap_t *dmap = GetDataDescMap(); - while ( dmap ) - { - int fields = dmap->dataNumFields; - for ( int i = 0; i < fields; i++ ) - { - typedescription_t *dataDesc = &dmap->dataDesc[i]; - if ( ( dataDesc->fieldType == FIELD_CUSTOM ) && ( dataDesc->flags & FTYPEDESC_OUTPUT ) ) - { - CBaseEntityOutput *pOutput = (CBaseEntityOutput *)((int)this + (int)dataDesc->fieldOffset[0]); - pOutput->DeleteAllElements(); - /* - int nConnections = pOutput->NumberOfElements(); - for ( int j = 0; j < nConnections; j++ ) - { - - } - */ - } - } - - dmap = dmap->baseMap; - } -} -#endif - -//----------------------------------------------------------------------------- -// Purpose: Player in our squad killed something -// Input : *pVictim - Who he killed -// &info - How they died -//----------------------------------------------------------------------------- -void CNPC_PlayerCompanion::OnPlayerKilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info ) -{ - // filter everything that comes in here that isn't an NPC - CAI_BaseNPC *pCombatVictim = dynamic_cast( pVictim ); - if ( !pCombatVictim ) - { - return; - } - - CBaseEntity *pInflictor = info.GetInflictor(); - int iNumBarrels = 0; - int iConsecutivePlayerKills = 0; - bool bPuntedGrenade = false; - bool bVictimWasEnemy = false; - bool bVictimWasMob = false; - bool bVictimWasAttacker = false; - bool bHeadshot = false; - bool bOneShot = false; - - if ( dynamic_cast( pInflictor ) && ( info.GetDamageType() & DMG_BLAST ) ) - { - // if a barrel explodes that was initiated by the player within a few seconds of the previous one, - // increment a counter to keep track of how many have exploded in a row. - if ( gpGlobals->curtime - m_fLastBarrelExploded >= MAX_TIME_BETWEEN_BARRELS_EXPLODING ) - { - m_iNumConsecutiveBarrelsExploded = 0; - } - m_iNumConsecutiveBarrelsExploded++; - m_fLastBarrelExploded = gpGlobals->curtime; - - iNumBarrels = m_iNumConsecutiveBarrelsExploded; - } - else - { - // if player kills an NPC within a few seconds of the previous kill, - // increment a counter to keep track of how many he's killed in a row. - if ( gpGlobals->curtime - m_fLastPlayerKill >= MAX_TIME_BETWEEN_CONSECUTIVE_PLAYER_KILLS ) - { - m_iNumConsecutivePlayerKills = 0; - } - m_iNumConsecutivePlayerKills++; - m_fLastPlayerKill = gpGlobals->curtime; - iConsecutivePlayerKills = m_iNumConsecutivePlayerKills; - } - - // don't comment on kills when she can't see the victim - if ( !FVisible( pVictim ) ) - { - return; - } - - // check if the player killed an enemy by punting a grenade - if ( pInflictor && Fraggrenade_WasPunted( pInflictor ) && Fraggrenade_WasCreatedByCombine( pInflictor ) ) - { - bPuntedGrenade = true; - } - - // check if the victim was Alyx's enemy - if ( GetEnemy() == pVictim ) - { - bVictimWasEnemy = true; - } - - AI_EnemyInfo_t *pEMemory = GetEnemies()->Find( pVictim ); - if ( pEMemory != NULL ) - { - // was Alyx being mobbed by this enemy? - bVictimWasMob = pEMemory->bMobbedMe; - - // has Alyx recieved damage from this enemy? - if ( pEMemory->timeLastReceivedDamageFrom > 0 ) { - bVictimWasAttacker = true; - } - } - - // Was it a headshot? - if ( ( pCombatVictim->LastHitGroup() == HITGROUP_HEAD ) && ( info.GetDamageType() & DMG_BULLET ) ) - { - bHeadshot = true; - } - - // Did the player kill the enemy with 1 shot? - if ( ( pCombatVictim->GetDamageCount() == 1 ) && ( info.GetDamageType() & DMG_BULLET ) ) - { - bOneShot = true; - } - - // set up the speech modifiers - CFmtStrN<512> modifiers( "num_barrels:%d,distancetoplayerenemy:%f,playerAmmo:%s,consecutive_player_kills:%d," - "punted_grenade:%d,victim_was_enemy:%d,victim_was_mob:%d,victim_was_attacker:%d,headshot:%d,oneshot:%d", - iNumBarrels, EnemyDistance( pVictim ), info.GetAmmoName(), iConsecutivePlayerKills, - bPuntedGrenade, bVictimWasEnemy, bVictimWasMob, bVictimWasAttacker, bHeadshot, bOneShot ); - - SpeakIfAllowed( TLK_PLAYER_KILLED_NPC, modifiers ); - - BaseClass::OnPlayerKilledOther( pVictim, info ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_PlayerCompanion::IsNavigationUrgent( void ) -{ - bool bBase = BaseClass::IsNavigationUrgent(); - - // Consider follow & assault behaviour urgent - if ( !bBase && (m_FollowBehavior.IsActive() || ( m_AssaultBehavior.IsRunning() && m_AssaultBehavior.IsUrgent() )) && Classify() == CLASS_PLAYER_ALLY_VITAL ) - { - // But only if the blocker isn't the player, and isn't a physics object that's still moving - CBaseEntity *pBlocker = GetNavigator()->GetBlockingEntity(); - if ( pBlocker && !pBlocker->IsPlayer() ) - { - IPhysicsObject *pPhysObject = pBlocker->VPhysicsGetObject(); - if ( pPhysObject && !pPhysObject->IsAsleep() ) - return false; - if ( pBlocker->IsNPC() ) - return false; - } - - // If we're within the player's viewcone, then don't teleport. - - // This test was made more general because previous iterations had cases where characters - // could not see the player but the player could in fact see them. Now the NPC's facing is - // irrelevant and the player's viewcone is more authorative. -- jdw - - CBasePlayer *pLocalPlayer = AI_GetSinglePlayer(); - if ( pLocalPlayer->FInViewCone( EyePosition() ) ) - return false; - - return true; - } - - return bBase; -} - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC( player_companion_base, CNPC_PlayerCompanion ) - - // AI Interaction for being hit by a physics object - DECLARE_INTERACTION(g_interactionHitByPlayerThrownPhysObj) - DECLARE_INTERACTION(g_interactionPlayerPuntedHeavyObject) - - DECLARE_CONDITION( COND_PC_HURTBYFIRE ) - DECLARE_CONDITION( COND_PC_SAFE_FROM_MORTAR ) - DECLARE_CONDITION( COND_PC_BECOMING_PASSENGER ) - - DECLARE_TASK( TASK_PC_WAITOUT_MORTAR ) - DECLARE_TASK( TASK_PC_GET_PATH_OFF_COMPANION ) - - DECLARE_ANIMEVENT( AE_COMPANION_PRODUCE_FLARE ) - DECLARE_ANIMEVENT( AE_COMPANION_LIGHT_FLARE ) - DECLARE_ANIMEVENT( AE_COMPANION_RELEASE_FLARE ) - - //========================================================= - // > TakeCoverFromBestSound - // - // Find cover and move towards it, but only do so for a short - // time. This is appropriate when the dangerous item is going - // to detonate very soon. This way our NPC doesn't run a great - // distance from an object that explodes shortly after the NPC - // gets underway. - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_PC_MOVE_TOWARDS_COVER_FROM_BEST_SOUND, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_FLEE_FROM_BEST_SOUND" - " TASK_STOP_MOVING 0" - " TASK_SET_TOLERANCE_DISTANCE 24" - " TASK_STORE_BESTSOUND_REACTORIGIN_IN_SAVEPOSITION 0" - " TASK_FIND_COVER_FROM_BEST_SOUND 0" - " TASK_RUN_PATH_TIMED 1.0" - " TASK_STOP_MOVING 0" - " TASK_FACE_SAVEPOSITION 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" // Translated to cover - "" - " Interrupts" - " COND_PC_SAFE_FROM_MORTAR" - ) - - DEFINE_SCHEDULE - ( - SCHED_PC_TAKE_COVER_FROM_BEST_SOUND, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_FLEE_FROM_BEST_SOUND" - " TASK_STOP_MOVING 0" - " TASK_SET_TOLERANCE_DISTANCE 24" - " TASK_STORE_BESTSOUND_REACTORIGIN_IN_SAVEPOSITION 0" - " TASK_FIND_COVER_FROM_BEST_SOUND 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_FACE_SAVEPOSITION 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" // Translated to cover - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_PC_SAFE_FROM_MORTAR" - ) - - DEFINE_SCHEDULE - ( - SCHED_PC_COWER, - - " Tasks" - " TASK_WAIT_RANDOM 0.1" - " TASK_SET_ACTIVITY ACTIVITY:ACT_COWER" - " TASK_PC_WAITOUT_MORTAR 0" - " TASK_WAIT 0.1" - " TASK_WAIT_RANDOM 0.5" - "" - " Interrupts" - " " - ) - - //========================================================= - // - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_PC_FLEE_FROM_BEST_SOUND, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_COWER" - " TASK_GET_PATH_AWAY_FROM_BEST_SOUND 600" - " TASK_RUN_PATH_TIMED 1.5" - " TASK_STOP_MOVING 0" - " TASK_TURN_LEFT 179" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_PC_SAFE_FROM_MORTAR" - ) - - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_PC_FAIL_TAKE_COVER_TURRET, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_COWER" - " TASK_STOP_MOVING 0" - " TASK_MOVE_AWAY_PATH 600" - " TASK_RUN_PATH_FLEE 100" - " TASK_STOP_MOVING 0" - " TASK_TURN_LEFT 179" - "" - " Interrupts" - " COND_NEW_ENEMY" - ) - - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_PC_FAKEOUT_MORTAR, - - " Tasks" - " TASK_MOVE_AWAY_PATH 300" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_HEAR_DANGER" - ) - - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_PC_GET_OFF_COMPANION, - - " Tasks" - " TASK_PC_GET_PATH_OFF_COMPANION 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - "" - ) - -AI_END_CUSTOM_NPC() - - -// -// Special movement overrides for player companions -// - -#define NUM_OVERRIDE_MOVE_CLASSNAMES 4 - -class COverrideMoveCache : public IEntityListener -{ -public: - - void LevelInitPreEntity( void ) - { - CacheClassnames(); - gEntList.AddListenerEntity( this ); - Clear(); - } - void LevelShutdownPostEntity( void ) - { - gEntList.RemoveListenerEntity( this ); - Clear(); - } - - inline void Clear( void ) - { - m_Cache.Purge(); - } - - inline bool MatchesCriteria( CBaseEntity *pEntity ) - { - for ( int i = 0; i < NUM_OVERRIDE_MOVE_CLASSNAMES; i++ ) - { - if ( pEntity->m_iClassname == m_Classname[i] ) - return true; - } - - return false; - } - - virtual void OnEntitySpawned( CBaseEntity *pEntity ) - { - if ( MatchesCriteria( pEntity ) ) - { - m_Cache.AddToTail( pEntity ); - } - }; - - virtual void OnEntityDeleted( CBaseEntity *pEntity ) - { - if ( !m_Cache.Count() ) - return; - - if ( MatchesCriteria( pEntity ) ) - { - m_Cache.FindAndRemove( pEntity ); - } - }; - - CBaseEntity *FindTargetsInRadius( CBaseEntity *pFirstEntity, const Vector &vecOrigin, float flRadius ) - { - if ( !m_Cache.Count() ) - return NULL; - - int nIndex = m_Cache.InvalidIndex(); - - // If we're starting with an entity, start there and move past it - if ( pFirstEntity != NULL ) - { - nIndex = m_Cache.Find( pFirstEntity ); - nIndex = m_Cache.Next( nIndex ); - if ( nIndex == m_Cache.InvalidIndex() ) - return NULL; - } - else - { - nIndex = m_Cache.Head(); - } - - CBaseEntity *pTarget = NULL; - const float flRadiusSqr = Square( flRadius ); - - // Look through each cached target, looking for one in our range - while ( nIndex != m_Cache.InvalidIndex() ) - { - pTarget = m_Cache[nIndex]; - if ( pTarget && ( pTarget->GetAbsOrigin() - vecOrigin ).LengthSqr() < flRadiusSqr ) - return pTarget; - - nIndex = m_Cache.Next( nIndex ); - } - - return NULL; - } - - void ForceRepopulateList( void ) - { - Clear(); - CacheClassnames(); - - CBaseEntity *pEnt = gEntList.FirstEnt(); - while( pEnt ) - { - if( MatchesCriteria( pEnt ) ) - { - m_Cache.AddToTail( pEnt ); - } - - pEnt = gEntList.NextEnt( pEnt ); - } - } - -private: - inline void CacheClassnames( void ) - { - m_Classname[0] = AllocPooledString( "env_fire" ); - m_Classname[1] = AllocPooledString( "combine_mine" ); - m_Classname[2] = AllocPooledString( "npc_turret_floor" ); - m_Classname[3] = AllocPooledString( "entityflame" ); - } - - CUtlLinkedList m_Cache; - string_t m_Classname[NUM_OVERRIDE_MOVE_CLASSNAMES]; -}; - -// Singleton for access -COverrideMoveCache g_OverrideMoveCache; -COverrideMoveCache *OverrideMoveCache( void ) { return &g_OverrideMoveCache; } - -CBaseEntity *OverrideMoveCache_FindTargetsInRadius( CBaseEntity *pFirstEntity, const Vector &vecOrigin, float flRadius ) -{ - return g_OverrideMoveCache.FindTargetsInRadius( pFirstEntity, vecOrigin, flRadius ); -} - -void OverrideMoveCache_ForceRepopulateList( void ) -{ - g_OverrideMoveCache.ForceRepopulateList(); -} - -void OverrideMoveCache_LevelInitPreEntity( void ) -{ - g_OverrideMoveCache.LevelInitPreEntity(); -} - -void OverrideMoveCache_LevelShutdownPostEntity( void ) -{ - g_OverrideMoveCache.LevelShutdownPostEntity(); -} - diff --git a/game/server/hl2/npc_playercompanion.h b/game/server/hl2/npc_playercompanion.h deleted file mode 100644 index 6db231ac5..000000000 --- a/game/server/hl2/npc_playercompanion.h +++ /dev/null @@ -1,439 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Base class for humanoid NPCs intended to fight along side player in close -// environments -// -//=============================================================================// - -#ifndef NPC_PLAYERCOMPANION_H -#define NPC_PLAYERCOMPANION_H - -#include "ai_playerally.h" - -#include "ai_behavior_follow.h" -#include "ai_behavior_standoff.h" -#include "ai_behavior_assault.h" -#include "ai_behavior_lead.h" -#include "ai_behavior_actbusy.h" -#include "ai_behavior_fear.h" - -#ifdef HL2_EPISODIC -#include "ai_behavior_operator.h" -#include "ai_behavior_passenger_companion.h" -#endif - -#if defined( _WIN32 ) -#pragma once -#endif - -enum AIReadiness_t -{ - AIRL_PANIC = -2, - AIRL_STEALTH = -1, - AIRL_RELAXED = 0, - AIRL_STIMULATED, - AIRL_AGITATED, -}; - -enum AIReadinessUse_t -{ - AIRU_NEVER, - AIRU_ALWAYS, - AIRU_ONLY_PLAYER_SQUADMATES, -}; - - -class CCompanionActivityRemap : public CActivityRemap -{ -public: - CCompanionActivityRemap( void ) : - m_fUsageBits( 0 ), - m_readiness( AIRL_RELAXED ), - m_bAiming( false ), - m_bWeaponRequired( false ), - m_bInVehicle( false ) {} - - // This bitfield maps which bits of data are being utilized by this data structure, since not all criteria - // in the parsed file are essential. You must add corresponding bits to the definitions below and maintain - // their state in the parsing of the file, as well as check the bitfield before accessing the data. This - // could be encapsulated into this class, but we'll probably move away from this model and closer to something - // more akin to the response rules -- jdw - - int m_fUsageBits; - - AIReadiness_t m_readiness; - bool m_bAiming; - bool m_bWeaponRequired; - bool m_bInVehicle; // For future expansion, this needs to speak more to the exact seat, role, and vehicle -}; - -// Usage bits for remap "extra" parsing - if these bits are set, the associated data has changed -#define bits_REMAP_READINESS (1<<0) -#define bits_REMAP_AIMING (1<<1) -#define bits_REMAP_WEAPON_REQUIRED (1<<2) -#define bits_REMAP_IN_VEHICLE (1<<3) - -// Readiness modes that only change due to mapmaker scripts -#define READINESS_MIN_VALUE -2 -#define READINESS_MODE_PANIC -2 -#define READINESS_MODE_STEALTH -1 - -// Readiness modes that change normally -#define READINESS_VALUE_RELAXED 0.1f -#define READINESS_VALUE_STIMULATED 0.95f -#define READINESS_VALUE_AGITATED 1.0f - -class CPhysicsProp; - -//----------------------------------------------------------------------------- -// -// CLASS: CNPC_PlayerCompanion -// -//----------------------------------------------------------------------------- - -class CNPC_PlayerCompanion : public CAI_PlayerAlly -{ - DECLARE_CLASS( CNPC_PlayerCompanion, CAI_PlayerAlly ); - -public: - //--------------------------------- - bool CreateBehaviors(); - void Precache(); - void Spawn(); - virtual void SelectModel() {}; - - virtual int Restore( IRestore &restore ); - virtual void DoCustomSpeechAI( void ); - - //--------------------------------- - int ObjectCaps(); - bool ShouldAlwaysThink(); - - Disposition_t IRelationType( CBaseEntity *pTarget ); - - bool IsSilentSquadMember() const; - - //--------------------------------- - // Behavior - //--------------------------------- - void GatherConditions(); - virtual void PredictPlayerPush(); - void BuildScheduleTestBits(); - - CSound *GetBestSound( int validTypes = ALL_SOUNDS ); - bool QueryHearSound( CSound *pSound ); - bool QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC = false ); - bool ShouldIgnoreSound( CSound * ); - - int SelectSchedule(); - - virtual int SelectScheduleDanger(); - virtual int SelectSchedulePriorityAction(); - virtual int SelectScheduleNonCombat() { return SCHED_NONE; } - virtual int SelectScheduleCombat(); - int SelectSchedulePlayerPush(); - - virtual bool CanReload( void ); - - virtual bool ShouldDeferToFollowBehavior(); - bool ShouldDeferToPassengerBehavior( void ); - - bool IsValidReasonableFacing( const Vector &vecSightDir, float sightDist ); - - int TranslateSchedule( int scheduleType ); - - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - - Activity TranslateActivityReadiness( Activity activity ); - Activity NPC_TranslateActivity( Activity eNewActivity ); - void HandleAnimEvent( animevent_t *pEvent ); - bool HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt); - - int GetSoundInterests(); - - void Touch( CBaseEntity *pOther ); - - virtual bool IgnorePlayerPushing( void ); - - void ModifyOrAppendCriteria( AI_CriteriaSet& set ); - void Activate( void ); - - void PrepareReadinessRemap( void ); - - virtual bool IsNavigationUrgent( void ); - - //--------------------------------- - // Readiness - //--------------------------------- - -protected: - virtual bool IsReadinessCapable(); - bool IsReadinessLocked() { return gpGlobals->curtime < m_flReadinessLockedUntil; } - void AddReadiness( float flAdd, bool bOverrideLock = false ); - void SubtractReadiness( float flAdd, bool bOverrideLock = false ); - void SetReadinessValue( float flSet ); - void SetReadinessSensitivity( float flSensitivity ) { m_flReadinessSensitivity = flSensitivity; } - virtual void UpdateReadiness(); - virtual float GetReadinessDecay(); - bool IsInScriptedReadinessState( void ) { return (m_flReadiness < 0 ); } - - CUtlVector< CCompanionActivityRemap > m_activityMappings; - -public: - float GetReadinessValue() { return m_flReadiness; } - int GetReadinessLevel(); - void SetReadinessLevel( int iLevel, bool bOverrideLock, bool bSlam ); - void LockReadiness( float duration = -1.0f ); // Defaults to indefinitely locked - void UnlockReadiness( void ); - - virtual void ReadinessLevelChanged( int iPriorLevel ) { } - - void InputGiveWeapon( inputdata_t &inputdata ); - -#ifdef HL2_EPISODIC - //--------------------------------- - // Vehicle passenger - //--------------------------------- - void InputEnterVehicle( inputdata_t &inputdata ); - void InputEnterVehicleImmediately( inputdata_t &inputdata ); - void InputCancelEnterVehicle( inputdata_t &inputdata ); - void InputExitVehicle( inputdata_t &inputdata ); - bool CanEnterVehicle( void ); - bool CanExitVehicle( void ); - void EnterVehicle( CBaseEntity *pEntityVehicle, bool bImmediately ); - virtual bool ExitVehicle( void ); - - virtual void UpdateEfficiency( bool bInPVS ); - virtual bool IsInAVehicle( void ) const; - virtual IServerVehicle *GetVehicle( void ); - virtual CBaseEntity *GetVehicleEntity( void ); - - virtual bool CanRunAScriptedNPCInteraction( bool bForced = false ); - virtual bool IsAllowedToDodge( void ); - -#endif // HL2_EPISODIC - -public: - - virtual void OnPlayerKilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info ); - - //--------------------------------- - //--------------------------------- - bool PickTacticalLookTarget( AILookTargetArgs_t *pArgs ); - - //--------------------------------- - // Aiming - //--------------------------------- - CBaseEntity *GetAimTarget() { return m_hAimTarget; } - void SetAimTarget( CBaseEntity *pTarget ); - void StopAiming( const char *pszReason = NULL ); - bool FindNewAimTarget(); - void OnNewLookTarget(); - bool ShouldBeAiming(); - virtual bool IsAllowedToAim(); - bool HasAimLOS( CBaseEntity *pAimTarget ); - void AimGun(); - CBaseEntity *GetAlternateMoveShootTarget(); - - //--------------------------------- - // Combat - //--------------------------------- - virtual void LocateEnemySound() {}; - - bool IsValidEnemy( CBaseEntity *pEnemy ); - - bool IsSafeFromFloorTurret( const Vector &vecLocation, CBaseEntity *pTurret ); - - bool ShouldMoveAndShoot( void ); - void OnUpdateShotRegulator(); - - void DecalTrace( trace_t *pTrace, char const *decalName ); - bool FCanCheckAttacks(); - Vector GetActualShootPosition( const Vector &shootOrigin ); - WeaponProficiency_t CalcWeaponProficiency( CBaseCombatWeapon *pWeapon ); - bool ShouldLookForBetterWeapon(); - bool Weapon_CanUse( CBaseCombatWeapon *pWeapon ); - void Weapon_Equip( CBaseCombatWeapon *pWeapon ); - void PickupWeapon( CBaseCombatWeapon *pWeapon ); - - bool FindCoverPos( CBaseEntity *pEntity, Vector *pResult); - bool FindCoverPosInRadius( CBaseEntity *pEntity, const Vector &goalPos, float coverRadius, Vector *pResult ); - bool FindCoverPos( CSound *pSound, Vector *pResult ); - bool FindMortarCoverPos( CSound *pSound, Vector *pResult ); - bool IsCoverPosition( const Vector &vecThreat, const Vector &vecPosition ); - - bool IsEnemyTurret() { return ( GetEnemy() && IsTurret(GetEnemy()) ); } - - static bool IsMortar( CBaseEntity *pEntity ); - static bool IsSniper( CBaseEntity *pEntity ); - static bool IsTurret( CBaseEntity *pEntity ); - static bool IsGunship( CBaseEntity *pEntity ); - - //--------------------------------- - // Damage handling - //--------------------------------- - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - void OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker ); - - //--------------------------------- - // Hints - //--------------------------------- - bool FValidateHintType ( CAI_Hint *pHint ); - - //--------------------------------- - // Navigation - //--------------------------------- - bool IsValidMoveAwayDest( const Vector &vecDest ); - bool ValidateNavGoal(); - bool OverrideMove( float flInterval ); // Override to take total control of movement (return true if done so) - bool MovementCost( int moveType, const Vector &vecStart, const Vector &vecEnd, float *pCost ); - float GetIdealSpeed() const; - float GetIdealAccel() const; - bool OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ); - - //--------------------------------- - // Inputs - //--------------------------------- - void InputOutsideTransition( inputdata_t &inputdata ); - void InputSetReadinessPanic( inputdata_t &inputdata ); - void InputSetReadinessStealth( inputdata_t &inputdata ); - void InputSetReadinessLow( inputdata_t &inputdata ); - void InputSetReadinessMedium( inputdata_t &inputdata ); - void InputSetReadinessHigh( inputdata_t &inputdata ); - void InputLockReadiness( inputdata_t &inputdata ); -#if HL2_EPISODIC - void InputClearAllOuputs( inputdata_t &inputdata ); ///< annihilate every output on this npc -#endif - - bool AllowReadinessValueChange( void ); - -protected: - //----------------------------------------------------- - // Conditions, Schedules, Tasks - //----------------------------------------------------- - enum - { - COND_PC_HURTBYFIRE = BaseClass::NEXT_CONDITION, - COND_PC_SAFE_FROM_MORTAR, - COND_PC_BECOMING_PASSENGER, - NEXT_CONDITION, - - SCHED_PC_COWER = BaseClass::NEXT_SCHEDULE, - SCHED_PC_MOVE_TOWARDS_COVER_FROM_BEST_SOUND, - SCHED_PC_TAKE_COVER_FROM_BEST_SOUND, - SCHED_PC_FLEE_FROM_BEST_SOUND, - SCHED_PC_FAIL_TAKE_COVER_TURRET, - SCHED_PC_FAKEOUT_MORTAR, - SCHED_PC_GET_OFF_COMPANION, - NEXT_SCHEDULE, - - TASK_PC_WAITOUT_MORTAR = BaseClass::NEXT_TASK, - TASK_PC_GET_PATH_OFF_COMPANION, - NEXT_TASK, - }; - -private: - void SetupCoverSearch( CBaseEntity *pEntity ); - void CleanupCoverSearch(); - - //----------------------------------------------------- - - bool m_bMovingAwayFromPlayer; - bool m_bWeightPathsInCover; - - enum eCoverType - { - CT_NORMAL, - CT_TURRET, - CT_MORTAR - }; - - static eCoverType gm_fCoverSearchType; - static bool gm_bFindingCoverFromAllEnemies; - - CSimpleSimTimer m_FakeOutMortarTimer; - - // Derived classes should not use the expresser directly - virtual CAI_Expresser *GetExpresser() { return BaseClass::GetExpresser(); } - -protected: - //----------------------------------------------------- - - virtual CAI_FollowBehavior &GetFollowBehavior( void ) { return m_FollowBehavior; } - - CAI_AssaultBehavior m_AssaultBehavior; - CAI_FollowBehavior m_FollowBehavior; - CAI_StandoffBehavior m_StandoffBehavior; - CAI_LeadBehavior m_LeadBehavior; - CAI_ActBusyBehavior m_ActBusyBehavior; -#ifdef HL2_EPISODIC - CAI_OperatorBehavior m_OperatorBehavior; - CAI_PassengerBehaviorCompanion m_PassengerBehavior; - CAI_FearBehavior m_FearBehavior; -#endif - //----------------------------------------------------- - - bool ShouldAlwaysTransition( void ); - - // Readiness is a value that's fed by various events in the NPC's AI. It is used - // to make decisions about what type of posture the NPC should be in (relaxed, agitated). - // It is not used to make decisions about what to do in the AI. - float m_flReadiness; - float m_flReadinessSensitivity; - bool m_bReadinessCapable; - float m_flReadinessLockedUntil; - float m_fLastBarrelExploded; - float m_fLastPlayerKill; - int m_iNumConsecutiveBarrelsExploded; // Companions keep track of the # of consecutive barrels exploded by the player and speaks a response as it increases - int m_iNumConsecutivePlayerKills; // Alyx keeps track of the # of consecutive kills by the player and speaks a response as it increases - - //----------------------------------------------------- - - float m_flBoostSpeed; - - //----------------------------------------------------- - - CSimpleSimTimer m_AnnounceAttackTimer; - - //----------------------------------------------------- - - EHANDLE m_hAimTarget; - -#ifdef HL2_EPISODIC - CHandle m_hFlare; -#endif // HL2_EPISODIC - - //----------------------------------------------------- - - static string_t gm_iszMortarClassname; - static string_t gm_iszFloorTurretClassname; - static string_t gm_iszGroundTurretClassname; - static string_t gm_iszShotgunClassname; - static string_t gm_iszRollerMineClassname; - - //----------------------------------------------------- - - void InputEnableAlwaysTransition( inputdata_t &inputdata ); - void InputDisableAlwaysTransition( inputdata_t &inputdata ); - bool m_bAlwaysTransition; - bool m_bDontPickupWeapons; - - void InputEnableWeaponPickup( inputdata_t &inputdata ); - void InputDisableWeaponPickup( inputdata_t &inputdata ); - - COutputEvent m_OnWeaponPickup; - - CStopwatch m_SpeechWatch_PlayerLooking; - - DECLARE_DATADESC(); - DEFINE_CUSTOM_AI; -}; - -// Used for quick override move searches against certain types of entities -void OverrideMoveCache_ForceRepopulateList( void ); -CBaseEntity *OverrideMoveCache_FindTargetsInRadius( CBaseEntity *pFirstEntity, const Vector &vecOrigin, float flRadius ); -void OverrideMoveCache_LevelInitPreEntity( void ); -void OverrideMoveCache_LevelShutdownPostEntity( void ); - -#endif // NPC_PLAYERCOMPANION_H diff --git a/game/server/hl2/npc_rollermine.cpp b/game/server/hl2/npc_rollermine.cpp deleted file mode 100644 index 783f26e6b..000000000 --- a/game/server/hl2/npc_rollermine.cpp +++ /dev/null @@ -1,3041 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ai_default.h" -#include "ai_task.h" -#include "ai_schedule.h" -#include "ai_hull.h" -#include "ai_squadslot.h" -#include "ai_basenpc.h" -#include "ai_navigator.h" -#include "ai_interactions.h" -#include "ndebugoverlay.h" -#include "explode.h" -#include "bitstring.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "decals.h" -#include "antlion_dust.h" -#include "ai_memory.h" -#include "ai_squad.h" -#include "ai_senses.h" -#include "beam_shared.h" -#include "iservervehicle.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" -#include "physics_saverestore.h" -#include "vphysics/constraints.h" -#include "vehicle_base.h" -#include "eventqueue.h" -#include "te_effect_dispatch.h" -#include "npc_rollermine.h" -#include "func_break.h" -#include "soundenvelope.h" -#include "mapentities.h" -#include "RagdollBoogie.h" -#include "physics_collisionevent.h" -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define ROLLERMINE_MAX_TORQUE_FACTOR 5 -extern short g_sModelIndexWExplosion; - -ConVar sk_rollermine_shock( "sk_rollermine_shock","0"); -ConVar sk_rollermine_stun_delay("sk_rollermine_stun_delay", "1"); -ConVar sk_rollermine_vehicle_intercept( "sk_rollermine_vehicle_intercept","1"); - -enum -{ - ROLLER_SKIN_REGULAR = 0, - ROLLER_SKIN_FRIENDLY, - ROLLER_SKIN_DETONATE, -}; -//----------------------------------------------------------------------------- -// CRollerController implementation -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// Purpose: This class only implements the IMotionEvent-specific behavior -// It keeps track of the forces so they can be integrated -//----------------------------------------------------------------------------- -class CRollerController : public IMotionEvent -{ - DECLARE_SIMPLE_DATADESC(); - -public: - IMotionEvent::simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ); - - AngularImpulse m_vecAngular; - Vector m_vecLinear; - - void Off( void ) { m_fIsStopped = true; } - void On( void ) { m_fIsStopped = false; } - - bool IsOn( void ) { return !m_fIsStopped; } - -private: - bool m_fIsStopped; -}; - -BEGIN_SIMPLE_DATADESC( CRollerController ) - - DEFINE_FIELD( m_vecAngular, FIELD_VECTOR ), - DEFINE_FIELD( m_vecLinear, FIELD_VECTOR ), - DEFINE_FIELD( m_fIsStopped, FIELD_BOOLEAN ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -IMotionEvent::simresult_e CRollerController::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) -{ - if( m_fIsStopped ) - { - return SIM_NOTHING; - } - - linear = m_vecLinear; - angular = m_vecAngular; - - return IMotionEvent::SIM_LOCAL_ACCELERATION; -} -//----------------------------------------------------------------------------- - - -#define ROLLERMINE_IDLE_SEE_DIST 2048 -#define ROLLERMINE_NORMAL_SEE_DIST 2048 -#define ROLLERMINE_WAKEUP_DIST 256 -#define ROLLERMINE_SEE_VEHICLESONLY_BEYOND_IDLE 300 // See every other than vehicles upto this distance (i.e. old idle see dist) -#define ROLLERMINE_SEE_VEHICLESONLY_BEYOND_NORMAL 800 // See every other than vehicles upto this distance (i.e. old normal see dist) - -#define ROLLERMINE_RETURN_TO_PLAYER_DIST (200*200) - -#define ROLLERMINE_MIN_ATTACK_DIST 1 -#define ROLLERMINE_MAX_ATTACK_DIST 4096 - -#define ROLLERMINE_OPEN_THRESHOLD 256 - -#define ROLLERMINE_VEHICLE_OPEN_THRESHOLD 400 -#define ROLLERMINE_VEHICLE_HOP_THRESHOLD 300 - -#define ROLLERMINE_HOP_DELAY 2 // Don't allow hops faster than this - -//#define ROLLERMINE_REQUIRED_TO_EXPLODE_VEHICLE 4 - -#define ROLLERMINE_FEAR_DISTANCE (300*300) - -//========================================================= -// Custom schedules -//========================================================= -enum -{ - SCHED_ROLLERMINE_RANGE_ATTACK1 = LAST_SHARED_SCHEDULE, - SCHED_ROLLERMINE_CHASE_ENEMY, - SCHED_ROLLERMINE_BURIED_WAIT, - SCHED_ROLLERMINE_BURIED_UNBURROW, - SCHED_ROLLERMINE_FLEE, - SCHED_ROLLERMINE_ALERT_STAND, - SCHED_ROLLERMINE_NUDGE_TOWARDS_NODES, - SCHED_ROLLERMINE_PATH_TO_PLAYER, - SCHED_ROLLERMINE_ROLL_TO_PLAYER, - SCHED_ROLLERMINE_POWERDOWN, -}; - -//========================================================= -// Custom tasks -//========================================================= -enum -{ - TASK_ROLLERMINE_CHARGE_ENEMY = LAST_SHARED_TASK, - TASK_ROLLERMINE_BURIED_WAIT, - TASK_ROLLERMINE_UNBURROW, - TASK_ROLLERMINE_GET_PATH_TO_FLEE, - TASK_ROLLERMINE_NUDGE_TOWARDS_NODES, - TASK_ROLLERMINE_RETURN_TO_PLAYER, - TASK_ROLLERMINE_POWERDOWN, -}; - - -// This are little 'sound event' flags. Set the flag after you play the -// sound, and the sound will not be allowed to play until the flag is then cleared. -#define ROLLERMINE_SE_CLEAR 0x00000000 -#define ROLLERMINE_SE_CHARGE 0x00000001 -#define ROLLERMINE_SE_TAUNT 0x00000002 -#define ROLLERMINE_SE_SHARPEN 0x00000004 -#define ROLLERMINE_SE_TOSSED 0x00000008 - -enum rollingsoundstate_t { ROLL_SOUND_NOT_READY = 0, ROLL_SOUND_OFF, ROLL_SOUND_CLOSED, ROLL_SOUND_OPEN }; - -//========================================================= -//========================================================= -class CNPC_RollerMine : public CNPCBaseInteractive, public CDefaultPlayerPickupVPhysics -{ - DECLARE_CLASS( CNPC_RollerMine, CNPCBaseInteractive ); - DECLARE_SERVERCLASS(); - -public: - - CNPC_RollerMine( void ) { m_bTurnedOn = true; m_bUniformSight = false; } - ~CNPC_RollerMine( void ); - - void Spawn( void ); - bool CreateVPhysics(); - void RunAI(); - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - void SpikeTouch( CBaseEntity *pOther ); - void ShockTouch( CBaseEntity *pOther ); - void CloseTouch( CBaseEntity *pOther ); - void EmbedTouch( CBaseEntity *pOther ); - float GetAttackDamageScale( CBaseEntity *pVictim ); - void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); - void Precache( void ); - void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ); - void OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ); - void StopLoopingSounds( void ); - void PrescheduleThink(); - bool ShouldSavePhysics() { return true; } - void OnRestore(); - void Bury( trace_t *tr ); - bool QuerySeeEntity(CBaseEntity *pSightEnt, bool bOnlyHateOrFearIfNPC = false ); - - int RangeAttack1Conditions ( float flDot, float flDist ); - int SelectSchedule( void ); - int TranslateSchedule( int scheduleType ); - int GetHackedIdleSchedule( void ); - - bool OverrideMove( float flInterval ) { return true; } - bool IsValidEnemy( CBaseEntity *pEnemy ); - bool IsPlayerVehicle( CBaseEntity *pEntity ); - bool IsShocking() { return gpGlobals->curtime < m_flShockTime ? true : false; } - void UpdateRollingSound(); - void UpdatePingSound(); - void StopRollingSound(); - void StopPingSound(); - float RollingSpeed(); - float GetStunDelay(); - void EmbedOnGroundImpact(); - void UpdateEfficiency( bool bInPVS ) { SetEfficiency( ( GetSleepState() != AISS_AWAKE ) ? AIE_DORMANT : AIE_NORMAL ); SetMoveEfficiency( AIME_NORMAL ); } - void DrawDebugGeometryOverlays() - { - if (m_debugOverlays & OVERLAY_BBOX_BIT) - { - float dist = GetSenses()->GetDistLook(); - Vector range(dist, dist, 64); - NDebugOverlay::Box( GetAbsOrigin(), -range, range, 255, 0, 0, 0, 0 ); - } - BaseClass::DrawDebugGeometryOverlays(); - } - // UNDONE: Put this in the qc file! - Vector EyePosition() - { - // This takes advantage of the fact that the system knows - // that the abs origin is at the center of the rollermine - // and that the OBB is actually world-aligned despite the - // fact that SOLID_VPHYSICS is being used - Vector eye = CollisionProp()->GetCollisionOrigin(); - eye.z += CollisionProp()->OBBMaxs().z; - return eye; - } - - int OnTakeDamage( const CTakeDamageInfo &info ); - void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - - Class_T Classify() - { - if( !m_bTurnedOn ) - return CLASS_NONE; - - //About to blow up after being hacked so do damage to the player. - if ( m_bHackedByAlyx && ( m_flPowerDownDetonateTime > 0.0f && m_flPowerDownDetonateTime <= gpGlobals->curtime ) ) - return CLASS_COMBINE; - - return ( m_bHeld || m_bHackedByAlyx ) ? CLASS_HACKED_ROLLERMINE : CLASS_COMBINE; - } - - virtual bool ShouldGoToIdleState() - { - return gpGlobals->curtime > m_flGoIdleTime ? true : false; - } - - virtual void OnStateChange( NPC_STATE OldState, NPC_STATE NewState ); - - // Vehicle interception - bool EnemyInVehicle( void ); - float VehicleHeading( CBaseEntity *pVehicle ); - - NPC_STATE SelectIdealState(); - - // Vehicle sticking - void StickToVehicle( CBaseEntity *pOther ); - void AnnounceArrivalToOthers( CBaseEntity *pOther ); - void UnstickFromVehicle( void ); - CBaseEntity *GetVehicleStuckTo( void ); - int CountRollersOnMyVehicle( CUtlVector *pRollerList ); - void InputConstraintBroken( inputdata_t &inputdata ); - void InputRespondToChirp( inputdata_t &inputdata ); - void InputRespondToExplodeChirp( inputdata_t &inputdata ); - void InputJoltVehicle( inputdata_t &inputdata ); - void InputTurnOn( inputdata_t &inputdata ); - void InputTurnOff( inputdata_t &inputdata ); - void InputPowerdown( inputdata_t &inputdata ); - - void PreventUnstickUntil( float flTime ) { m_flPreventUnstickUntil = flTime; } - - virtual unsigned int PhysicsSolidMaskForEntity( void ) const; - - void SetRollerSkin( void ); - - COutputEvent m_OnPhysGunDrop; - COutputEvent m_OnPhysGunPickup; - -protected: - DEFINE_CUSTOM_AI; - DECLARE_DATADESC(); - - bool BecomePhysical(); - void WakeNeighbors(); - bool WakeupMine( CAI_BaseNPC *pNPC ); - - void Open( void ); - void Close( void ); - void Explode( void ); - void PreDetonate( void ); - void Hop( float height ); - - void ShockTarget( CBaseEntity *pOther ); - - bool IsActive() { return m_flActiveTime > gpGlobals->curtime ? false : true; } - - // INPCInteractive Functions - virtual bool CanInteractWith( CAI_BaseNPC *pUser ) { return true; } - virtual bool HasBeenInteractedWith() { return m_bHackedByAlyx; } - virtual void NotifyInteraction( CAI_BaseNPC *pUser ); - - CSoundPatch *m_pRollSound; - CSoundPatch *m_pPingSound; - - CRollerController m_RollerController; - IPhysicsMotionController *m_pMotionController; - - float m_flSeeVehiclesOnlyBeyond; - float m_flChargeTime; - float m_flGoIdleTime; - float m_flShockTime; - float m_flForwardSpeed; - int m_iSoundEventFlags; - rollingsoundstate_t m_rollingSoundState; - - CNetworkVar( bool, m_bIsOpen ); - CNetworkVar( float, m_flActiveTime ); //If later than the current time, this will force the mine to be active - - bool m_bHeld; //Whether or not the player is holding the mine - EHANDLE m_hVehicleStuckTo; - float m_flPreventUnstickUntil; - float m_flNextHop; - bool m_bStartBuried; - bool m_bBuried; - bool m_bIsPrimed; - bool m_wakeUp; - bool m_bEmbedOnGroundImpact; - CNetworkVar( bool, m_bHackedByAlyx ); - - // Constraint used to stick us to a vehicle - IPhysicsConstraint *m_pConstraint; - - bool m_bTurnedOn; - bool m_bUniformSight; - - CNetworkVar( bool, m_bPowerDown ); - float m_flPowerDownTime; - float m_flPowerDownDetonateTime; - - static string_t gm_iszDropshipClassname; -}; - -string_t CNPC_RollerMine::gm_iszDropshipClassname; - -LINK_ENTITY_TO_CLASS( npc_rollermine, CNPC_RollerMine ); - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -BEGIN_DATADESC( CNPC_RollerMine ) - - DEFINE_SOUNDPATCH( m_pRollSound ), - DEFINE_SOUNDPATCH( m_pPingSound ), - DEFINE_EMBEDDED( m_RollerController ), - DEFINE_PHYSPTR( m_pMotionController ), - - DEFINE_FIELD( m_flSeeVehiclesOnlyBeyond, FIELD_FLOAT ), - DEFINE_FIELD( m_flActiveTime, FIELD_TIME ), - DEFINE_FIELD( m_flChargeTime, FIELD_TIME ), - DEFINE_FIELD( m_flGoIdleTime, FIELD_TIME ), - DEFINE_FIELD( m_flShockTime, FIELD_TIME ), - DEFINE_FIELD( m_flForwardSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_bIsOpen, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bHeld, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hVehicleStuckTo, FIELD_EHANDLE ), - DEFINE_FIELD( m_flPreventUnstickUntil, FIELD_TIME ), - DEFINE_FIELD( m_flNextHop, FIELD_FLOAT ), - DEFINE_FIELD( m_bIsPrimed, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iSoundEventFlags, FIELD_INTEGER ), - DEFINE_FIELD( m_rollingSoundState, FIELD_INTEGER ), - - DEFINE_KEYFIELD( m_bStartBuried, FIELD_BOOLEAN, "StartBuried" ), - DEFINE_FIELD( m_bBuried, FIELD_BOOLEAN ), - DEFINE_FIELD( m_wakeUp, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bEmbedOnGroundImpact, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bHackedByAlyx, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_bPowerDown, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flPowerDownTime, FIELD_TIME ), - DEFINE_FIELD( m_flPowerDownDetonateTime, FIELD_TIME ), - - DEFINE_PHYSPTR( m_pConstraint ), - - DEFINE_FIELD( m_bTurnedOn, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_bUniformSight, FIELD_BOOLEAN, "uniformsightdist" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "ConstraintBroken", InputConstraintBroken ), - DEFINE_INPUTFUNC( FIELD_VOID, "RespondToChirp", InputRespondToChirp ), - DEFINE_INPUTFUNC( FIELD_VOID, "RespondToExplodeChirp", InputRespondToExplodeChirp ), - DEFINE_INPUTFUNC( FIELD_VOID, "JoltVehicle", InputJoltVehicle ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - DEFINE_INPUTFUNC( FIELD_VOID, "PowerDown", InputPowerdown ), - - // Function Pointers - DEFINE_ENTITYFUNC( SpikeTouch ), - DEFINE_ENTITYFUNC( ShockTouch ), - DEFINE_ENTITYFUNC( CloseTouch ), - DEFINE_ENTITYFUNC( EmbedTouch ), - DEFINE_THINKFUNC( Explode ), - DEFINE_THINKFUNC( PreDetonate ), - - DEFINE_OUTPUT( m_OnPhysGunDrop, "OnPhysGunDrop" ), - DEFINE_OUTPUT( m_OnPhysGunPickup, "OnPhysGunPickup" ), - - DEFINE_BASENPCINTERACTABLE_DATADESC(), - -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CNPC_RollerMine, DT_RollerMine ) - SendPropInt(SENDINFO(m_bIsOpen), 1, SPROP_UNSIGNED ), - SendPropFloat(SENDINFO(m_flActiveTime), 0, SPROP_NOSCALE ), - SendPropInt(SENDINFO(m_bHackedByAlyx), 1, SPROP_UNSIGNED ), - SendPropInt(SENDINFO(m_bPowerDown), 1, SPROP_UNSIGNED ), -END_SEND_TABLE() - -bool NPC_Rollermine_IsRollermine( CBaseEntity *pEntity ) -{ - CNPC_RollerMine *pRoller = dynamic_cast(pEntity); - return pRoller ? true : false; -} - -CBaseEntity *NPC_Rollermine_DropFromPoint( const Vector &originStart, CBaseEntity *pOwner, const char *pszTemplate ) -{ - CBaseEntity *pEntity = NULL; - CNPC_RollerMine *pMine = NULL; - - // Use the template, if we have it - if ( pszTemplate && pszTemplate[0] ) - { - MapEntity_ParseEntity( pEntity, pszTemplate, NULL ); - pMine = dynamic_cast(pEntity); - } - else - { - pMine = (CNPC_RollerMine*)CreateEntityByName("npc_rollermine"); - } - - if ( pMine ) - { - pMine->SetAbsOrigin( originStart ); - pMine->SetOwnerEntity( pOwner ); - pMine->Spawn(); - - if ( !pszTemplate || !pszTemplate[0] ) - { - pMine->EmbedOnGroundImpact(); - } - } - else - { - Warning( "NULL Ent in Rollermine Create!\n" ); - } - - return pMine; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CNPC_RollerMine::~CNPC_RollerMine( void ) -{ - if ( m_pMotionController != NULL ) - { - physenv->DestroyMotionController( m_pMotionController ); - m_pMotionController = NULL; - } - - UnstickFromVehicle(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_RollerMine::Precache( void ) -{ - PrecacheModel( "models/roller.mdl" ); - PrecacheModel( "models/roller_spikes.mdl" ); - - PrecacheModel( "sprites/bluelight1.vmt" ); - PrecacheModel( "sprites/rollermine_shock.vmt" ); - PrecacheModel( "sprites/rollermine_shock_yellow.vmt" ); - - PrecacheScriptSound( "NPC_RollerMine.Taunt" ); - PrecacheScriptSound( "NPC_RollerMine.OpenSpikes" ); - PrecacheScriptSound( "NPC_RollerMine.Warn" ); - PrecacheScriptSound( "NPC_RollerMine.Shock" ); - PrecacheScriptSound( "NPC_RollerMine.ExplodeChirp" ); - PrecacheScriptSound( "NPC_RollerMine.Chirp" ); - PrecacheScriptSound( "NPC_RollerMine.ChirpRespond" ); - PrecacheScriptSound( "NPC_RollerMine.ExplodeChirpRespond" ); - PrecacheScriptSound( "NPC_RollerMine.JoltVehicle" ); - PrecacheScriptSound( "NPC_RollerMine.Tossed" ); - PrecacheScriptSound( "NPC_RollerMine.Hurt" ); - - PrecacheScriptSound( "NPC_RollerMine.Roll" ); - PrecacheScriptSound( "NPC_RollerMine.RollWithSpikes" ); - PrecacheScriptSound( "NPC_RollerMine.Ping" ); - PrecacheScriptSound( "NPC_RollerMine.Held" ); - - PrecacheScriptSound( "NPC_RollerMine.Reprogram" ); - - PrecacheMaterial( "effects/rollerglow" ); - - gm_iszDropshipClassname = AllocPooledString( "npc_combinedropship" ); // For fast string compares. -#ifdef HL2_EPISODIC - PrecacheScriptSound( "RagdollBoogie.Zap" ); -#endif - - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_RollerMine::Spawn( void ) -{ - Precache(); - - SetSolid( SOLID_VPHYSICS ); - AddSolidFlags( FSOLID_FORCE_WORLD_ALIGNED | FSOLID_NOT_STANDABLE ); - - BaseClass::Spawn(); - - AddEFlags( EFL_NO_DISSOLVE ); - - CapabilitiesClear(); - CapabilitiesAdd( bits_CAP_MOVE_GROUND | bits_CAP_INNATE_RANGE_ATTACK1 | bits_CAP_SQUAD ); - - m_pRollSound = NULL; - - m_bIsOpen = true; - Close(); - - m_bPowerDown = false; - - m_flFieldOfView = -1.0f; - m_flForwardSpeed = -1200; - m_bloodColor = DONT_BLEED; - - SetHullType(HULL_SMALL_CENTERED); - - SetHullSizeNormal(); - - m_flActiveTime = 0; - - m_bBuried = m_bStartBuried; - if ( m_bStartBuried ) - { - trace_t tr; - Bury( &tr ); - } - - NPCInit(); - - m_takedamage = DAMAGE_EVENTS_ONLY; - SetDistLook( ROLLERMINE_IDLE_SEE_DIST ); - - if( m_bUniformSight ) - { - m_flSeeVehiclesOnlyBeyond = ROLLERMINE_IDLE_SEE_DIST; - } - else - { - m_flSeeVehiclesOnlyBeyond = ROLLERMINE_SEE_VEHICLESONLY_BEYOND_IDLE; - } - - //Suppress superfluous warnings from animation system - m_flGroundSpeed = 20; - m_NPCState = NPC_STATE_NONE; - - m_rollingSoundState = ROLL_SOUND_OFF; - - m_pConstraint = NULL; - m_hVehicleStuckTo = NULL; - m_flPreventUnstickUntil = 0; - m_flNextHop = 0; - - m_flPowerDownDetonateTime = 0.0f; - m_bPowerDown = false; - m_flPowerDownTime = 0.0f; - - //Set their yaw speed to 0 so the motor doesn't rotate them. - GetMotor()->SetYawSpeed( 0.0f ); - SetRollerSkin(); -} - -//----------------------------------------------------------------------------- -// Set the contents types that are solid by default to this NPC -//----------------------------------------------------------------------------- -unsigned int CNPC_RollerMine::PhysicsSolidMaskForEntity( void ) const -{ - if ( HasSpawnFlags( SF_ROLLERMINE_PROP_COLLISION ) ) - return MASK_SOLID; - - return MASK_NPCSOLID; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_RollerMine::Bury( trace_t *tr ) -{ - AI_TraceHull( GetAbsOrigin() + Vector(0,0,64), GetAbsOrigin() - Vector( 0, 0, MAX_TRACE_LENGTH ), Vector(-16,-16,-16), Vector(16,16,16), MASK_NPCSOLID, this, GetCollisionGroup(), tr ); - - //NDebugOverlay::Box( tr->startpos, Vector(-16,-16,-16), Vector(16,16,16), 255, 0, 0, 64, 10.0 ); - //NDebugOverlay::Box( tr->endpos, Vector(-16,-16,-16), Vector(16,16,16), 0, 255, 0, 64, 10.0 ); - - // Move into the ground layer - Vector buriedPos = tr->endpos - Vector( 0, 0, GetHullHeight() * 0.5 ); - Teleport( &buriedPos, NULL, &vec3_origin ); - SetMoveType( MOVETYPE_NONE ); - - SetSchedule( SCHED_ROLLERMINE_BURIED_WAIT ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_RollerMine::WakeupMine( CAI_BaseNPC *pNPC ) -{ - if ( pNPC && pNPC->m_iClassname == m_iClassname && pNPC != this ) - { - CNPC_RollerMine *pMine = dynamic_cast(pNPC); - if ( pMine ) - { - if ( pMine->m_NPCState == NPC_STATE_IDLE ) - { - pMine->m_wakeUp = false; - pMine->SetIdealState( NPC_STATE_ALERT ); - return true; - } - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_RollerMine::WakeNeighbors() -{ - if ( !m_wakeUp || !IsActive() ) - return; - m_wakeUp = false; - - if ( m_pSquad ) - { - AISquadIter_t iter; - for (CAI_BaseNPC *pSquadMember = m_pSquad->GetFirstMember( &iter ); pSquadMember; pSquadMember = m_pSquad->GetNextMember( &iter ) ) - { - WakeupMine( pSquadMember ); - } - return; - } - - CBaseEntity *entityList[64]; - Vector range(ROLLERMINE_WAKEUP_DIST,ROLLERMINE_WAKEUP_DIST,64); - int boxCount = UTIL_EntitiesInBox( entityList, ARRAYSIZE(entityList), GetAbsOrigin()-range, GetAbsOrigin()+range, FL_NPC ); - //NDebugOverlay::Box( GetAbsOrigin(), -range, range, 255, 0, 0, 64, 10.0 ); - int wakeCount = 0; - while ( boxCount > 0 ) - { - boxCount--; - CAI_BaseNPC *pNPC = entityList[boxCount]->MyNPCPointer(); - if ( WakeupMine( pNPC ) ) - { - wakeCount++; - if ( wakeCount >= 2 ) - return; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_RollerMine::OnStateChange( NPC_STATE OldState, NPC_STATE NewState ) -{ - if ( NewState == NPC_STATE_IDLE ) - { - SetDistLook( ROLLERMINE_IDLE_SEE_DIST ); - m_flDistTooFar = ROLLERMINE_IDLE_SEE_DIST; - - if( m_bUniformSight ) - { - m_flSeeVehiclesOnlyBeyond = ROLLERMINE_IDLE_SEE_DIST; - } - else - { - m_flSeeVehiclesOnlyBeyond = ROLLERMINE_SEE_VEHICLESONLY_BEYOND_IDLE; - } - - m_RollerController.m_vecAngular = vec3_origin; - m_wakeUp = true; - } - else - { - if ( OldState == NPC_STATE_IDLE ) - { - // wake the neighbors! - WakeNeighbors(); - } - SetDistLook( ROLLERMINE_NORMAL_SEE_DIST ); - - if( m_bUniformSight ) - { - m_flSeeVehiclesOnlyBeyond = ROLLERMINE_NORMAL_SEE_DIST; - } - else - { - m_flSeeVehiclesOnlyBeyond = ROLLERMINE_SEE_VEHICLESONLY_BEYOND_NORMAL; - } - - m_flDistTooFar = ROLLERMINE_NORMAL_SEE_DIST; - } - BaseClass::OnStateChange( OldState, NewState ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -NPC_STATE CNPC_RollerMine::SelectIdealState( void ) -{ - switch ( m_NPCState ) - { - case NPC_STATE_COMBAT: - { - if ( HasCondition( COND_ENEMY_TOO_FAR ) ) - { - ClearEnemyMemory(); - SetEnemy( NULL ); - m_flGoIdleTime = gpGlobals->curtime + 10; - return NPC_STATE_ALERT; - } - } - - default: - break; - } - - return BaseClass::SelectIdealState(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_RollerMine::BecomePhysical( void ) -{ - VPhysicsDestroyObject(); - - RemoveSolidFlags( FSOLID_NOT_SOLID ); - - //Setup the physics controller on the roller - IPhysicsObject *pPhysicsObject = VPhysicsInitNormal( SOLID_VPHYSICS, GetSolidFlags() , false ); - - if ( pPhysicsObject == NULL ) - return false; - - m_pMotionController = physenv->CreateMotionController( &m_RollerController ); - m_pMotionController->AttachObject( pPhysicsObject, true ); - - SetMoveType( MOVETYPE_VPHYSICS ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_RollerMine::OnRestore() -{ - BaseClass::OnRestore(); - if ( m_pMotionController ) - { - m_pMotionController->SetEventHandler( &m_RollerController ); - } - - // If we're stuck to a vehicle over a level transition, restart our jolt inputs - if ( GetVehicleStuckTo() ) - { - if ( !g_EventQueue.HasEventPending( this, "JoltVehicle" ) ) - { - g_EventQueue.AddEvent( this, "JoltVehicle", RandomFloat(3,6), NULL, NULL ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_RollerMine::CreateVPhysics() -{ - if ( m_bBuried ) - { - VPhysicsInitStatic(); - return true; - } - else - { - return BecomePhysical(); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_RollerMine::RunAI() -{ - if( m_bTurnedOn ) - { - // Scare combine if hacked by Alyx. - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - - Vector vecVelocity; - - if ( pPhysicsObject != NULL ) - { - pPhysicsObject->GetVelocity( &vecVelocity, NULL ); - } - - if( !m_bHeld && vecVelocity.Length() > 64.0 ) - { - if( m_bHackedByAlyx ) - { - // Scare combine - CSoundEnt::InsertSound( (SOUND_DANGER | SOUND_CONTEXT_COMBINE_ONLY | SOUND_CONTEXT_REACT_TO_SOURCE | SOUND_CONTEXT_DANGER_APPROACH), WorldSpaceCenter() + Vector( 0, 0, 32 ) + vecVelocity * 0.5f, 120, 0.2f, this, SOUNDENT_CHANNEL_REPEATED_DANGER ); - } - else - { - // Scare player allies - CSoundEnt::InsertSound( (SOUND_DANGER | SOUND_CONTEXT_EXCLUDE_COMBINE | SOUND_CONTEXT_REACT_TO_SOURCE | SOUND_CONTEXT_DANGER_APPROACH), WorldSpaceCenter() + Vector( 0, 0, 32 ) + vecVelocity * 0.5f, 120, 0.2f, this, SOUNDENT_CHANNEL_REPEATED_DANGER ); - } - } - - BaseClass::RunAI(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int CNPC_RollerMine::RangeAttack1Conditions( float flDot, float flDist ) -{ - if( HasCondition( COND_SEE_ENEMY ) == false ) - return COND_NONE; - - if ( EnemyInVehicle() ) - return COND_CAN_RANGE_ATTACK1; - - if( flDist > ROLLERMINE_MAX_ATTACK_DIST ) - return COND_TOO_FAR_TO_ATTACK; - - if (flDist < ROLLERMINE_MIN_ATTACK_DIST ) - return COND_TOO_CLOSE_TO_ATTACK; - - return COND_CAN_RANGE_ATTACK1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int CNPC_RollerMine::SelectSchedule( void ) -{ - if ( m_bPowerDown ) - return SCHED_ROLLERMINE_POWERDOWN; - - if ( m_bBuried ) - { - if ( HasCondition(COND_NEW_ENEMY) || HasCondition(COND_LIGHT_DAMAGE) ) - return SCHED_ROLLERMINE_BURIED_UNBURROW; - - return SCHED_ROLLERMINE_BURIED_WAIT; - } - - //If we're held, don't try and do anything - if ( ( m_bHeld ) || !IsActive() || m_hVehicleStuckTo ) - return SCHED_ALERT_STAND; - - // If we can see something we're afraid of, run from it - if ( HasCondition( COND_SEE_FEAR ) ) - return SCHED_ROLLERMINE_FLEE; - - switch( m_NPCState ) - { - case NPC_STATE_COMBAT: - - if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - return SCHED_ROLLERMINE_RANGE_ATTACK1; - - return SCHED_ROLLERMINE_CHASE_ENEMY; - break; - - default: - break; - } - - // Rollermines never wait to fall to the ground - ClearCondition( COND_FLOATING_OFF_GROUND ); - - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_RollerMine::GetHackedIdleSchedule( void ) -{ - // If we've been hacked, return to the player - if ( !m_bHackedByAlyx || m_bHeld ) - return SCHED_NONE; - - // Are we near the player? - CBaseEntity *pPlayer = gEntList.FindEntityByName( NULL, "!player" ); - if ( !pPlayer ) - return SCHED_NONE; - - if ( !HasCondition(COND_SEE_PLAYER) ) - return SCHED_ROLLERMINE_PATH_TO_PLAYER; - - if ( GetAbsOrigin().DistToSqr( pPlayer->GetAbsOrigin() ) > ROLLERMINE_RETURN_TO_PLAYER_DIST ) - return SCHED_ROLLERMINE_ROLL_TO_PLAYER; - - return SCHED_NONE; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CNPC_RollerMine::TranslateSchedule( int scheduleType ) -{ - switch( scheduleType ) - { - case SCHED_IDLE_STAND: - { - int iSched = GetHackedIdleSchedule(); - if ( iSched != SCHED_NONE ) - return iSched; - - return SCHED_IDLE_STAND; - } - break; - - case SCHED_ALERT_STAND: - { - int iSched = GetHackedIdleSchedule(); - if ( iSched != SCHED_NONE ) - return iSched; - - return SCHED_ROLLERMINE_ALERT_STAND; - } - break; - - case SCHED_ROLLERMINE_RANGE_ATTACK1: - if( HasCondition(COND_ENEMY_OCCLUDED) ) - { - // Because of an unfortunate arrangement of cascading failing schedules, the rollermine - // could end up here with instructions to drive towards the target, although the target is - // not in sight. Nudge around randomly until we're back on the nodegraph. - return SCHED_ROLLERMINE_NUDGE_TOWARDS_NODES; - } - break; - } - - return scheduleType; -} - - -#if 0 -#define ROLLERMINE_DETECTION_RADIUS 350 -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_RollerMine::DetectedEnemyInProximity( void ) -{ - CBaseEntity *pEnt = NULL; - CBaseEntity *pBestEnemy = NULL; - float flBestDist = MAX_TRACE_LENGTH; - - while ( ( pEnt = gEntList.FindEntityInSphere( pEnt, GetAbsOrigin(), ROLLERMINE_DETECTION_RADIUS ) ) != NULL ) - { - if ( IRelationType( pEnt ) != D_HT ) - continue; - - float distance = ( pEnt->GetAbsOrigin() - GetAbsOrigin() ).Length(); - - if ( distance >= flBestDist ) - continue; - - pBestEnemy = pEnt; - flBestDist = distance; - } - - if ( pBestEnemy != NULL ) - { - SetEnemy( pBestEnemy ); - return true; - } - - return false; -} -#endif - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pSightEnt - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_RollerMine::QuerySeeEntity(CBaseEntity *pSightEnt, bool bOnlyHateOrFearIfNPC) -{ - if ( IRelationType( pSightEnt ) == D_FR ) - { - // Only see feared objects up close - float flDist = (WorldSpaceCenter() - pSightEnt->WorldSpaceCenter()).LengthSqr(); - if ( flDist > ROLLERMINE_FEAR_DISTANCE ) - return false; - } - - return BaseClass::QuerySeeEntity(pSightEnt, bOnlyHateOrFearIfNPC); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_RollerMine::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_FACE_REASONABLE: - case TASK_FACE_SAVEPOSITION: - case TASK_FACE_LASTPOSITION: - case TASK_FACE_TARGET: - case TASK_FACE_AWAY_FROM_SAVEPOSITION: - case TASK_FACE_HINTNODE: - case TASK_FACE_ENEMY: - case TASK_FACE_PLAYER: - case TASK_FACE_PATH: - case TASK_FACE_IDEAL: - // This only applies to NPCs that aren't spheres with omnidirectional eyesight. - TaskComplete(); - break; - - case TASK_ROLLERMINE_UNBURROW: - - { - AddSolidFlags( FSOLID_NOT_SOLID ); - SetMoveType( MOVETYPE_NOCLIP ); - SetAbsVelocity( Vector( 0, 0, 256 ) ); - Open(); - - trace_t tr; - AI_TraceLine( GetAbsOrigin()+Vector(0,0,1), GetAbsOrigin()-Vector(0,0,64), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction < 1.0f ) - { - UTIL_CreateAntlionDust( tr.endpos + Vector(0,0,24), GetLocalAngles() ); - } - } - - return; - break; - - case TASK_ROLLERMINE_BURIED_WAIT: - if ( HasCondition( COND_SEE_ENEMY ) ) - { - TaskComplete(); - } - break; - - case TASK_STOP_MOVING: - - //Stop turning - m_RollerController.m_vecAngular = vec3_origin; - - TaskComplete(); - return; - break; - - case TASK_WAIT_FOR_MOVEMENT: - { - // TASK_RUN_PATH and TASK_WALK_PATH work different on the rollermine and run until movement is done, - // so movement is already complete when entering this task. - TaskComplete(); - } - break; - - case TASK_WALK_PATH: - case TASK_RUN_PATH: - { - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - - if ( pPhysicsObject == NULL ) - { - assert(0); - TaskFail("Roller lost internal physics object?"); - return; - } - - pPhysicsObject->Wake(); - } - break; - - case TASK_ROLLERMINE_CHARGE_ENEMY: - case TASK_ROLLERMINE_RETURN_TO_PLAYER: - { - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - - if ( pPhysicsObject == NULL ) - { - assert(0); - TaskFail("Roller lost internal physics object?"); - return; - } - - pPhysicsObject->Wake(); - - m_flChargeTime = gpGlobals->curtime; - } - - break; - - case TASK_ROLLERMINE_GET_PATH_TO_FLEE: - { - // Find the nearest thing we're afraid of, and move away from it. - float flNearest = ROLLERMINE_FEAR_DISTANCE; - EHANDLE hNearestEnemy = NULL; - AIEnemiesIter_t iter; - for( AI_EnemyInfo_t *pEMemory = GetEnemies()->GetFirst( &iter ); pEMemory != NULL; pEMemory = GetEnemies()->GetNext( &iter ) ) - { - CBaseEntity *pEnemy = pEMemory->hEnemy; - if ( !pEnemy || !pEnemy->IsAlive() ) - continue; - if ( IRelationType( pEnemy ) != D_FR ) - continue; - - float flDist = (WorldSpaceCenter() - pEnemy->WorldSpaceCenter()).LengthSqr(); - if ( flDist < flNearest ) - { - flNearest = flDist; - hNearestEnemy = pEnemy; - } - } - - if ( !hNearestEnemy ) - { - TaskFail("Couldn't find nearest feared object."); - break; - } - - GetMotor()->SetIdealYawToTarget( hNearestEnemy->WorldSpaceCenter() ); - ChainStartTask( TASK_MOVE_AWAY_PATH, pTask->flTaskData ); - } - break; - - case TASK_ROLLERMINE_NUDGE_TOWARDS_NODES: - { - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - - if( pPhysicsObject ) - { - // Try a few times to find a direction to shove ourself - for( int i = 0 ; i < 4 ; i++ ) - { - int x,y; - - x = random->RandomInt( -1, 1 ); - y = random->RandomInt( -1, 1 ); - - Vector vecNudge(x, y, 0.0f); - - trace_t tr; - - // Try to move in a direction with a couple of feet of clearance. - UTIL_TraceLine( WorldSpaceCenter(), WorldSpaceCenter() + vecNudge * 24.0f, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - if( tr.fraction == 1.0 ) - { - vecNudge *= (pPhysicsObject->GetMass() * 75.0f); - vecNudge += Vector(0,0,pPhysicsObject->GetMass() * 75.0f); - pPhysicsObject->ApplyForceCenter( vecNudge ); - break; - } - } - } - - TaskComplete(); - } - break; - - case TASK_ROLLERMINE_POWERDOWN: - break; - - default: - BaseClass::StartTask( pTask ); - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_RollerMine::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_ROLLERMINE_UNBURROW: - { - Vector vCenter = WorldSpaceCenter(); - - // Robin: HACK: Bloat the rollermine check to catch the model switch (roller.mdl->roller_spikes.mdl) - trace_t tr; - AI_TraceHull( vCenter, vCenter, Vector(-16,-16,-16), Vector(16,16,16), MASK_NPCSOLID, this, GetCollisionGroup(), &tr ); - - if ( tr.fraction == 1 && tr.allsolid != 1 && (tr.startsolid != 1) ) - { - if ( BecomePhysical() ) - { - Hop( 256 ); - m_bBuried = false; - TaskComplete(); - SetIdealState( NPC_STATE_ALERT ); - } - } - } - - return; - break; - - case TASK_ROLLERMINE_BURIED_WAIT: - if ( HasCondition( COND_SEE_ENEMY ) || HasCondition( COND_LIGHT_DAMAGE ) ) - { - TaskComplete(); - } - break; - - case TASK_ROLLERMINE_GET_PATH_TO_FLEE: - { - ChainRunTask( TASK_MOVE_AWAY_PATH, pTask->flTaskData ); - } - break; - - case TASK_WAIT_FOR_MOVEMENT: - { - // TASK_RUN_PATH and TASK_WALK_PATH work different on the rollermine and run until movement is done, - // so movement is already complete when entering this task. - TaskComplete(); - } - break; - - case TASK_RUN_PATH: - case TASK_WALK_PATH: - - if ( m_bHeld || m_hVehicleStuckTo ) - { - TaskFail( "Player interrupted by grabbing" ); - break; - } - - // If we were fleeing, but we've lost sight of the thing scaring us, stop - if ( IsCurSchedule(SCHED_ROLLERMINE_FLEE) && !HasCondition( COND_SEE_FEAR ) ) - { - TaskComplete(); - break; - } - - if ( !GetNavigator()->IsGoalActive() ) - { - TaskComplete(); - return; - } - - // Start turning early - if( (GetLocalOrigin() - GetNavigator()->GetCurWaypointPos() ).Length() <= 64 ) - { - if( GetNavigator()->CurWaypointIsGoal() ) - { - // Hit the brakes a bit. - float yaw = UTIL_VecToYaw( GetNavigator()->GetCurWaypointPos() - GetLocalOrigin() ); - Vector vecRight; - AngleVectors( QAngle( 0, yaw, 0 ), NULL, &vecRight, NULL ); - - m_RollerController.m_vecAngular += WorldToLocalRotation( SetupMatrixAngles(GetLocalAngles()), vecRight, -m_flForwardSpeed * 5 ); - - TaskComplete(); - return; - } - - GetNavigator()->AdvancePath(); - } - - { - float yaw = UTIL_VecToYaw( GetNavigator()->GetCurWaypointPos() - GetLocalOrigin() ); - - Vector vecRight; - Vector vecToPath; // points at the path - AngleVectors( QAngle( 0, yaw, 0 ), &vecToPath, &vecRight, NULL ); - - // figure out if the roller is turning. If so, cut the throttle a little. - float flDot; - Vector vecVelocity; - - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - - if ( pPhysicsObject == NULL ) - { - assert(0); - TaskFail("Roller lost internal physics object?"); - return; - } - - pPhysicsObject->GetVelocity( &vecVelocity, NULL ); - - VectorNormalize( vecVelocity ); - - vecVelocity.z = 0; - - flDot = DotProduct( vecVelocity, vecToPath ); - - m_RollerController.m_vecAngular = vec3_origin; - - if( flDot > 0.25 && flDot < 0.7 ) - { - // Feed a little torque backwards into the axis perpendicular to the velocity. - // This will help get rid of momentum that would otherwise make us overshoot our goal. - Vector vecCompensate; - - vecCompensate.x = vecVelocity.y; - vecCompensate.y = -vecVelocity.x; - vecCompensate.z = 0; - - m_RollerController.m_vecAngular = WorldToLocalRotation( SetupMatrixAngles(GetLocalAngles()), vecCompensate, m_flForwardSpeed * -0.75 ); - } - - if( m_bHackedByAlyx ) - { - // Move faster. - m_RollerController.m_vecAngular += WorldToLocalRotation( SetupMatrixAngles(GetLocalAngles()), vecRight, m_flForwardSpeed * 2.0f ); - } - else - { - m_RollerController.m_vecAngular += WorldToLocalRotation( SetupMatrixAngles(GetLocalAngles()), vecRight, m_flForwardSpeed ); - } - } - break; - - case TASK_ROLLERMINE_CHARGE_ENEMY: - { - if ( !GetEnemy() ) - { - TaskFail( FAIL_NO_ENEMY ); - break; - } - - if ( m_bHeld || m_hVehicleStuckTo ) - { - TaskComplete(); - break; - } - - CBaseEntity *pEnemy = GetEnemy(); - Vector vecTargetPosition = pEnemy->GetAbsOrigin(); - - // If we're chasing a vehicle, try and get ahead of it - if ( EnemyInVehicle() ) - { - CBaseCombatCharacter *pCCEnemy = pEnemy->MyCombatCharacterPointer(); - float flT; - - // Project it's velocity and find our closest point on that line. Do it all in 2d space. - Vector vecVehicleVelocity = pCCEnemy->GetVehicleEntity()->GetSmoothedVelocity(); - Vector vecProjected = vecTargetPosition + (vecVehicleVelocity * 1.0); - Vector2D vecProjected2D( vecProjected.x, vecProjected.y ); - Vector2D vecTargetPosition2D( vecTargetPosition.x, vecTargetPosition.y ); - Vector2D vecOrigin2D( GetAbsOrigin().x, GetAbsOrigin().y ); - Vector2D vecIntercept2D; - - CalcClosestPointOnLine2D( vecOrigin2D, vecTargetPosition2D, vecProjected2D, vecIntercept2D, &flT ); - Vector vecIntercept( vecIntercept2D.x, vecIntercept2D.y, GetAbsOrigin().z ); - - //NDebugOverlay::Line( vecTargetPosition, vecProjected, 0,255,0, true, 0.1 ); - - // If we're ahead of the line somewhere, try to intercept - if ( flT > 0 ) - { - // If it's beyond the end of the intercept line, just move towards the end of the line - if ( flT > 1 ) - { - vecIntercept.x = vecProjected.x; - vecIntercept.y = vecProjected.y; - } - - // If we're closer to the intercept point than to the vehicle, move towards the intercept - if ( (GetAbsOrigin() - vecTargetPosition).LengthSqr() > (GetAbsOrigin() - vecIntercept).LengthSqr() ) - { - //NDebugOverlay::Box( vecIntercept, -Vector(20,20,20), Vector(20,20,20), 255,0,0, 0.1, 0.1 ); - - // Only use this position if it's clear - if ( enginetrace->GetPointContents( vecIntercept ) != CONTENTS_SOLID ) - { - vecTargetPosition = vecIntercept; - } - } - } - - //NDebugOverlay::Box( vecTargetPosition, -Vector(20,20,20), Vector(20,20,20), 255,255,255, 0.1, 0.1 ); - } - - float flTorqueFactor; - Vector vecToTarget = vecTargetPosition - GetLocalOrigin(); - float yaw = UTIL_VecToYaw( vecToTarget ); - Vector vecRight; - - AngleVectors( QAngle( 0, yaw, 0 ), NULL, &vecRight, NULL ); - - //NDebugOverlay::Line( GetLocalOrigin(), GetLocalOrigin() + (GetEnemy()->GetLocalOrigin() - GetLocalOrigin()), 0,255,0, true, 0.1 ); - - float flDot; - - // Figure out whether to continue the charge. - // (Have I overrun the target?) - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - - if ( pPhysicsObject == NULL ) - { -// Assert(0); - TaskFail("Roller lost internal physics object?"); - return; - } - - Vector vecVelocity; - pPhysicsObject->GetVelocity( &vecVelocity, NULL ); - VectorNormalize( vecVelocity ); - - VectorNormalize( vecToTarget ); - - flDot = DotProduct( vecVelocity, vecToTarget ); - - // more torque the longer the roller has been going. - flTorqueFactor = 1 + (gpGlobals->curtime - m_flChargeTime) * 2; - - float flMaxTorque = ROLLERMINE_MAX_TORQUE_FACTOR; - - // Friendly rollermines go a little slower - if ( HasSpawnFlags( SF_ROLLERMINE_FRIENDLY ) ) - { - flMaxTorque *= 0.75; - } - - if( flTorqueFactor < 1 ) - { - flTorqueFactor = 1; - } - else if( flTorqueFactor > flMaxTorque) - { - flTorqueFactor = flMaxTorque; - } - - Vector vecCompensate; - - vecCompensate.x = vecVelocity.y; - vecCompensate.y = -vecVelocity.x; - vecCompensate.z = 0; - VectorNormalize( vecCompensate ); - - m_RollerController.m_vecAngular = WorldToLocalRotation( SetupMatrixAngles(GetLocalAngles()), vecCompensate, m_flForwardSpeed * -0.75 ); - m_RollerController.m_vecAngular += WorldToLocalRotation( SetupMatrixAngles(GetLocalAngles()), vecRight, m_flForwardSpeed * flTorqueFactor ); - - // Taunt when I get closer - if( !(m_iSoundEventFlags & ROLLERMINE_SE_TAUNT) && UTIL_DistApprox( GetLocalOrigin(), vecTargetPosition ) <= 400 ) - { - m_iSoundEventFlags |= ROLLERMINE_SE_TAUNT; // Don't repeat. - - EmitSound( "NPC_RollerMine.Taunt" ); - } - - // Jump earlier when chasing a vehicle - float flThreshold = ROLLERMINE_OPEN_THRESHOLD; - if ( EnemyInVehicle() ) - { - flThreshold = ROLLERMINE_VEHICLE_OPEN_THRESHOLD; - } - - // Open the spikes if i'm close enough to cut the enemy!! - if( ( m_bIsOpen == false ) && ( ( UTIL_DistApprox( GetAbsOrigin(), GetEnemy()->GetAbsOrigin() ) <= flThreshold ) || !IsActive() ) ) - { - Open(); - } - else if ( m_bIsOpen ) - { - float flDistance = UTIL_DistApprox( GetAbsOrigin(), GetEnemy()->GetAbsOrigin() ); - if ( flDistance >= flThreshold ) - { - // Otherwise close them if the enemy is getting away! - Close(); - } - else if ( EnemyInVehicle() && flDistance < ROLLERMINE_VEHICLE_HOP_THRESHOLD ) - { - // Keep trying to hop when we're ramming a vehicle, so we're visible to the player - if ( vecVelocity.x != 0 && vecVelocity.y != 0 && flTorqueFactor > 3 && flDot > 0.0 ) - { - Hop( 300 ); - } - } - } - - // If we drive past, close the blades and make a new plan. - if ( !EnemyInVehicle() ) - { - if( vecVelocity.x != 0 && vecVelocity.y != 0 ) - { - if( gpGlobals->curtime - m_flChargeTime > 1.0 && flTorqueFactor > 1 && flDot < 0.0 ) - { - if( m_bIsOpen ) - { - Close(); - } - - TaskComplete(); - } - } - } - } - break; - - case TASK_ROLLERMINE_RETURN_TO_PLAYER: - { - if ( ConditionsGathered() && !HasCondition(COND_SEE_PLAYER) ) - { - TaskFail( FAIL_NO_PLAYER ); - return; - } - - CBaseEntity *pPlayer = gEntList.FindEntityByName( NULL, "!player" ); - if ( !pPlayer || m_bHeld || m_hVehicleStuckTo ) - { - TaskFail( FAIL_NO_TARGET ); - return; - } - - Vector vecTargetPosition = pPlayer->GetAbsOrigin(); - float flTorqueFactor; - Vector vecToTarget = vecTargetPosition - GetLocalOrigin(); - float yaw = UTIL_VecToYaw( vecToTarget ); - Vector vecRight; - - AngleVectors( QAngle( 0, yaw, 0 ), NULL, &vecRight, NULL ); - - float flDot; - - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - if ( pPhysicsObject == NULL ) - { - TaskFail("Roller lost internal physics object?"); - return; - } - - Vector vecVelocity; - pPhysicsObject->GetVelocity( &vecVelocity, NULL ); - VectorNormalize( vecVelocity ); - VectorNormalize( vecToTarget ); - - flDot = DotProduct( vecVelocity, vecToTarget ); - - // more torque the longer the roller has been going. - flTorqueFactor = 1 + (gpGlobals->curtime - m_flChargeTime) * 2; - - float flMaxTorque = ROLLERMINE_MAX_TORQUE_FACTOR * 0.75; - if( flTorqueFactor < 1 ) - { - flTorqueFactor = 1; - } - else if( flTorqueFactor > flMaxTorque) - { - flTorqueFactor = flMaxTorque; - } - - Vector vecCompensate; - - vecCompensate.x = vecVelocity.y; - vecCompensate.y = -vecVelocity.x; - vecCompensate.z = 0; - VectorNormalize( vecCompensate ); - - m_RollerController.m_vecAngular = WorldToLocalRotation( SetupMatrixAngles(GetLocalAngles()), vecCompensate, m_flForwardSpeed * -0.75 ); - m_RollerController.m_vecAngular += WorldToLocalRotation( SetupMatrixAngles(GetLocalAngles()), vecRight, m_flForwardSpeed * flTorqueFactor ); - - // Once we're near the player, slow & stop - if ( GetAbsOrigin().DistToSqr( vecTargetPosition ) < (ROLLERMINE_RETURN_TO_PLAYER_DIST*2.0) ) - { - TaskComplete(); - } - } - break; - - case TASK_ROLLERMINE_POWERDOWN: - { - if ( m_flPowerDownTime <= gpGlobals->curtime ) - { - m_flNextHop = gpGlobals->curtime; - m_flPowerDownTime = gpGlobals->curtime + RandomFloat( 0.3, 0.9 ); - EmitSound( "NPC_RollerMine.Hurt" ); - - CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin(), 400, 0.5f, this ); - - if ( m_bIsOpen == false ) - { - Open(); - } - else - { - Close(); - } - } - - if ( m_flPowerDownDetonateTime <= gpGlobals->curtime ) - { - SetThink( &CNPC_RollerMine::PreDetonate ); - SetNextThink( gpGlobals->curtime + 0.5f ); - } - - // No TaskComplete() here, because the task will never complete. The rollermine will explode. - } - break; - - default: - BaseClass::RunTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_RollerMine::Open( void ) -{ - // Friendly rollers cannot open - if ( HasSpawnFlags( SF_ROLLERMINE_FRIENDLY ) ) - return; - - if ( m_bIsOpen == false ) - { - SetModel( "models/roller_spikes.mdl" ); - SetRollerSkin(); - - EmitSound( "NPC_RollerMine.OpenSpikes" ); - - SetTouch( &CNPC_RollerMine::ShockTouch ); - m_bIsOpen = true; - - // Don't hop if we're constrained - if ( !m_pConstraint ) - { - if ( EnemyInVehicle() ) - { - Hop( 256 ); - } - else if ( !GetEnemy() || GetEnemy()->Classify() != CLASS_BULLSEYE ) // Don't hop when attacking bullseyes - { - Hop( 128 ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_RollerMine::SetRollerSkin( void ) -{ - if ( m_bPowerDown == true ) - { - m_nSkin = (int)ROLLER_SKIN_DETONATE; - } - else if ( m_bHackedByAlyx == true ) - { - m_nSkin = (int)ROLLER_SKIN_FRIENDLY; - } - else - { - m_nSkin = (int)ROLLER_SKIN_REGULAR; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_RollerMine::Close( void ) -{ - // Not allowed to close while primed, because we're going to detonate on touch - if ( m_bIsPrimed ) - return; - - if ( m_bIsOpen && !IsShocking() ) - { - SetModel( "models/roller.mdl" ); - - SetRollerSkin(); - - SetTouch( NULL ); - m_bIsOpen = false; - - m_iSoundEventFlags = ROLLERMINE_SE_CLEAR; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_RollerMine::SpikeTouch( CBaseEntity *pOther ) -{ - /* - if ( pOther->IsSolidFlagSet(FSOLID_TRIGGER | FSOLID_VOLUME_CONTENTS) ) - return; - - if ( m_bHeld ) - return; - - if ( pOther->IsPlayer() ) - return; - - if ( pOther->m_takedamage != DAMAGE_YES ) - return; - - // If we just hit a breakable glass object, don't explode. We want to blow through it. - CBreakable *pBreakable = dynamic_cast(pOther); - if ( pBreakable && pBreakable->GetMaterialType() == matGlass ) - return; - - Explode(); - EmitSound( "NPC_RollerMine.Warn" ); - */ - - //FIXME: Either explode within certain rules, never explode, or just shock the hit victim -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_RollerMine::CloseTouch( CBaseEntity *pOther ) -{ - if ( pOther->IsSolidFlagSet(FSOLID_TRIGGER | FSOLID_VOLUME_CONTENTS) ) - return; - - if ( IsShocking() ) - return; - - bool bOtherIsDead = ( pOther->MyNPCPointer() && !pOther->MyNPCPointer()->IsAlive() ); - bool bOtherIsNotarget = ( ( pOther->GetFlags() & FL_NOTARGET ) != 0 ); - - if ( !bOtherIsDead && !bOtherIsNotarget ) - { - Disposition_t disp = IRelationType(pOther); - - if ( (disp == D_HT || disp == D_FR) ) - { - ShockTouch( pOther ); - return; - } - } - - Close(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_RollerMine::EmbedTouch( CBaseEntity *pOther ) -{ - if ( pOther->IsSolidFlagSet(FSOLID_TRIGGER | FSOLID_VOLUME_CONTENTS) ) - return; - - m_bEmbedOnGroundImpact = false; - - // Did we hit the world? - if ( pOther->entindex() == 0 ) - { - m_bBuried = true; - trace_t tr; - Bury( &tr ); - - // Destroy out physics object and become static - VPhysicsDestroyObject(); - CreateVPhysics(); - - // Drop a decal on the ground where we impacted - UTIL_DecalTrace( &tr, "Rollermine.Crater" ); - - // Make some dust - UTIL_CreateAntlionDust( tr.endpos, GetLocalAngles() ); - } - - // Don't try and embed again - SetTouch( NULL ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_RollerMine::IsPlayerVehicle( CBaseEntity *pEntity ) -{ - IServerVehicle *pVehicle = pEntity->GetServerVehicle(); - if ( pVehicle ) - { - CBasePlayer *pPlayer = ToBasePlayer( pVehicle->GetPassenger() ); - if ( pPlayer != NULL ) - { - Disposition_t disp = IRelationType(pPlayer); - - if ( disp == D_HT || disp == D_FR ) - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pVictim - -// Output : float -//----------------------------------------------------------------------------- -float CNPC_RollerMine::GetAttackDamageScale( CBaseEntity *pVictim ) -{ - // If we're friendly, don't damage players or player-friendly NPCs, even with collisions - if ( HasSpawnFlags( SF_ROLLERMINE_FRIENDLY ) ) - { - if ( pVictim->IsPlayer() ) - return 0; - - if ( pVictim->MyNPCPointer() ) - { - // If we don't hate the player, we're immune - CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); - if ( pPlayer && pVictim->MyNPCPointer()->IRelationType( pPlayer ) != D_HT ) - return 0.0; - } - } - - return BaseClass::GetAttackDamageScale( pVictim ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOther - -//----------------------------------------------------------------------------- -void CNPC_RollerMine::ShockTarget( CBaseEntity *pOther ) -{ - CBeam *pBeam; - - if( m_bHackedByAlyx ) - { - pBeam = CBeam::BeamCreate( "sprites/rollermine_shock_yellow.vmt", 4 ); - } - else - { - pBeam = CBeam::BeamCreate( "sprites/rollermine_shock.vmt", 4 ); - } - - int startAttach = -1; - - CBaseAnimating *pAnimating = dynamic_cast(pOther); - - if ( pBeam != NULL ) - { - pBeam->EntsInit( pOther, this ); - - if ( pAnimating && pAnimating->GetModel() ) - { - startAttach = pAnimating->LookupAttachment("beam_damage" ); - pBeam->SetStartAttachment( startAttach ); - } - - // Change this up a little for first person hits - if ( pOther->IsPlayer() ) - { - pBeam->SetEndWidth( 8 ); - pBeam->SetNoise( 4 ); - pBeam->LiveForTime( 0.2f ); - } - else - { - pBeam->SetEndWidth( 16 ); - pBeam->SetNoise( 16 ); - pBeam->LiveForTime( 0.5f ); - } - - pBeam->SetEndAttachment( 1 ); - pBeam->SetWidth( 1 ); - pBeam->SetBrightness( 255 ); - pBeam->SetColor( 255, 255, 255 ); - pBeam->RelinkBeam(); - } - - Vector shockPos = pOther->WorldSpaceCenter(); - - if ( startAttach > 0 && pAnimating ) - { - pAnimating->GetAttachment( startAttach, shockPos ); - } - - Vector shockDir = ( GetAbsOrigin() - shockPos ); - VectorNormalize( shockDir ); - - CPVSFilter filter( shockPos ); - te->GaussExplosion( filter, 0.0f, shockPos, shockDir, 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_RollerMine::NotifyInteraction( CAI_BaseNPC *pUser ) -{ - // For now, turn green so we can tell who is hacked. - m_bHackedByAlyx = true; - SetRollerSkin(); - GetEnemies()->SetFreeKnowledgeDuration( 30.0f ); - - // Play the hax0red sound - EmitSound( "NPC_RollerMine.Reprogram" ); - - // Force the rollermine open here. At very least, this ensures that the - // correct, smaller bounding box is recomputed around it. - Open(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_RollerMine::ShockTouch( CBaseEntity *pOther ) -{ - if ( pOther->IsSolidFlagSet(FSOLID_TRIGGER | FSOLID_VOLUME_CONTENTS) ) - return; - - if ( m_bHeld || m_hVehicleStuckTo || gpGlobals->curtime < m_flShockTime ) - return; - - // error? - Assert( !m_bIsPrimed ); - - Disposition_t disp = IRelationType(pOther); - - // Ignore anyone that I'm friendly or neutral to. - if( disp != D_HT && disp != D_FR) - return; - - IPhysicsObject *pPhysics = VPhysicsGetObject(); - - // Calculate a collision force - Vector impulse = WorldSpaceCenter() - pOther->WorldSpaceCenter(); - impulse.z = 0; - VectorNormalize( impulse ); - impulse.z = 0.75; - VectorNormalize( impulse ); - impulse *= 600; - - // Stun the roller - m_flActiveTime = gpGlobals->curtime + GetStunDelay(); - - // If we're a 'friendly' rollermine, just push the player a bit - if ( HasSpawnFlags( SF_ROLLERMINE_FRIENDLY ) ) - { - if ( pOther->IsPlayer() ) - { - Vector vecForce = -impulse * 0.5; - pOther->ApplyAbsVelocityImpulse( vecForce ); - } - return; - } - - // jump up at a 30 degree angle away from the guy we hit - SetTouch( &CNPC_RollerMine::CloseTouch ); - Vector vel; - pPhysics->SetVelocity( &impulse, NULL ); - EmitSound( "NPC_RollerMine.Shock" ); - // Do a shock effect - ShockTarget( pOther ); - - m_flShockTime = gpGlobals->curtime + 1.25; - - // Calculate physics force - Vector out; - pOther->CollisionProp()->CalcNearestPoint( WorldSpaceCenter(), &out ); - - Vector vecForce = ( -impulse * pPhysics->GetMass() * 10 ); - CTakeDamageInfo info( this, this, vecForce, out, sk_rollermine_shock.GetFloat(), DMG_SHOCK ); - - if( FClassnameIs( pOther, "npc_combine_s" ) ) - { - if( pOther->GetHealth() <= (pOther->GetMaxHealth() / 2) ) - { - // Instant special death for a combine soldier who has less than half health. - Vector vecDamageForce = pOther->WorldSpaceCenter() - WorldSpaceCenter(); - VectorNormalize( vecDamageForce ); - - IPhysicsObject *pPhysics = pOther->VPhysicsGetObject(); - - if( pPhysics ) - { - vecDamageForce *= (pPhysics->GetMass() * 200.0f); - - // Slam Z component with some good, reliable upwards velocity. - vecDamageForce.z = pPhysics->GetMass() * 200.0f; - } - - pOther->MyCombatCharacterPointer()->BecomeRagdollBoogie( this, vecDamageForce, 5.0f, SF_RAGDOLL_BOOGIE_ELECTRICAL ); - return; - } - else - { - info.SetDamage( pOther->GetMaxHealth()/2 ); - } - } - - pOther->TakeDamage( info ); - - // Knock players back a bit - if ( pOther->IsPlayer() ) - { - vecForce = -impulse; - pOther->ApplyAbsVelocityImpulse( vecForce ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_RollerMine::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) -{ - // Make sure we don't keep hitting the same entity - int otherIndex = !index; - CBaseEntity *pOther = pEvent->pEntities[otherIndex]; - if ( pEvent->deltaCollisionTime < 0.5 && (pOther == this) ) - return; - - BaseClass::VPhysicsCollision( index, pEvent ); - - // If we've just hit a vehicle, we want to stick to it - if ( m_bHeld || m_hVehicleStuckTo || !IsPlayerVehicle( pOther ) ) - { - // Are we supposed to be embedding ourselves? - if ( m_bEmbedOnGroundImpact ) - { - // clear the flag so we don't queue more than once - m_bEmbedOnGroundImpact = false; - // call this when physics is done - g_PostSimulationQueue.QueueCall( this, &CNPC_RollerMine::EmbedTouch, pOther ); - } - return; - } - - StickToVehicle( pOther ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOther - -//----------------------------------------------------------------------------- -void CNPC_RollerMine::StickToVehicle( CBaseEntity *pOther ) -{ - IPhysicsObject *pOtherPhysics = pOther->VPhysicsGetObject(); - if ( !pOtherPhysics ) - return; - - // Don't stick to the wheels - if ( pOtherPhysics->GetCallbackFlags() & CALLBACK_IS_VEHICLE_WHEEL ) - return; - - // Destroy our constraint. This can happen if we had our constraint broken - // and we still haven't cleaned up our constraint. - UnstickFromVehicle(); - - // We've hit the vehicle that the player's in. - // Stick to it and slow it down. - m_hVehicleStuckTo = pOther; - - IPhysicsObject *pPhysics = VPhysicsGetObject(); - - // Constrain us to the vehicle - constraint_fixedparams_t fixed; - fixed.Defaults(); - fixed.InitWithCurrentObjectState( pOtherPhysics, pPhysics ); - fixed.constraint.Defaults(); - fixed.constraint.forceLimit = ImpulseScale( pPhysics->GetMass(), 200 ); - fixed.constraint.torqueLimit = ImpulseScale( pPhysics->GetMass(), 800 ); - m_pConstraint = physenv->CreateFixedConstraint( pOtherPhysics, pPhysics, NULL, fixed ); - m_pConstraint->SetGameData( (void *)this ); - - // Kick the vehicle so the player knows we've arrived - Vector impulse = pOther->GetAbsOrigin() - GetAbsOrigin(); - VectorNormalize( impulse ); - impulse.z = -0.75; - VectorNormalize( impulse ); - impulse *= 600; - Vector vecForce = impulse * pPhysics->GetMass() * 10; - pOtherPhysics->ApplyForceOffset( vecForce, GetAbsOrigin() ); - - // Get the velocity at the point we're sticking to - Vector vecVelocity; - pOtherPhysics->GetVelocityAtPoint( GetAbsOrigin(), &vecVelocity ); - AngularImpulse angNone( 0.0f, 0.0f, 0.0f ); - pPhysics->SetVelocity( &vecVelocity, &angNone ); - - // Make sure we're spiky - Open(); - - AnnounceArrivalToOthers( pOther ); - - // Also, jolt the vehicle sometime in the future - g_EventQueue.AddEvent( this, "JoltVehicle", RandomFloat(3,6), NULL, NULL ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_RollerMine::CountRollersOnMyVehicle( CUtlVector *pRollerList ) -{ - CBaseEntity *entityList[64]; - Vector range(256,256,256); - pRollerList->AddToTail( this ); - int boxCount = UTIL_EntitiesInBox( entityList, ARRAYSIZE(entityList), GetAbsOrigin()-range, GetAbsOrigin()+range, FL_NPC ); - for ( int i = 0; i < boxCount; i++ ) - { - CAI_BaseNPC *pNPC = entityList[i]->MyNPCPointer(); - if ( pNPC && pNPC->m_iClassname == m_iClassname && pNPC != this ) - { - // Found another rollermine - CNPC_RollerMine *pMine = dynamic_cast(pNPC); - Assert( pMine ); - - // Is he stuck to the same vehicle? - if ( pMine->GetVehicleStuckTo() == GetVehicleStuckTo() ) - { - pRollerList->AddToTail( pMine ); - } - } - } - - return pRollerList->Count(); -} - -//----------------------------------------------------------------------------- -// Purpose: Tell other rollermines on the vehicle that I've just arrived -// Input : *pOther - -//----------------------------------------------------------------------------- -void CNPC_RollerMine::AnnounceArrivalToOthers( CBaseEntity *pOther ) -{ - // Now talk to any other rollermines stuck to the same vehicle - CUtlVector aRollersOnVehicle; - int iRollers = CountRollersOnMyVehicle( &aRollersOnVehicle ); - - // Stop all rollers on the vehicle falling off due to the force of the arriving one - for ( int i = 0; i < iRollers; i++ ) - { - aRollersOnVehicle[i]->PreventUnstickUntil( gpGlobals->curtime + 1 ); - } - - // See if we've got enough rollers on the vehicle to start being mean - /* - if ( iRollers >= ROLLERMINE_REQUIRED_TO_EXPLODE_VEHICLE ) - { - // Alert the others - EmitSound( "NPC_RollerMine.ExplodeChirp" ); - - // Tell everyone to explode shortly - for ( int i = 0; i < iRollers; i++ ) - { - variant_t emptyVariant; - g_EventQueue.AddEvent( aRollersOnVehicle[i], "RespondToExplodeChirp", RandomFloat(2,5), NULL, NULL ); - } - } - else - { - */ - // If there's other rollers on the vehicle, talk to them - if ( iRollers > 1 ) - { - // Chirp to the others - EmitSound( "NPC_RollerMine.Chirp" ); - - // Tell the others to respond (skip first slot, because that's me) - for ( int i = 1; i < iRollers; i++ ) - { - variant_t emptyVariant; - g_EventQueue.AddEvent( aRollersOnVehicle[i], "RespondToChirp", RandomFloat(2,3), NULL, NULL ); - } - } -// } -} - -//----------------------------------------------------------------------------- -// Purpose: Physics system has just told us our constraint has been broken -//----------------------------------------------------------------------------- -void CNPC_RollerMine::InputConstraintBroken( inputdata_t &inputdata ) -{ - // Prevent rollermines being dislodged right as they stick - if ( m_flPreventUnstickUntil > gpGlobals->curtime ) - return; - - // We can't delete it here safely - UnstickFromVehicle(); - Close(); - - // dazed - m_RollerController.m_vecAngular.Init(); - m_flActiveTime = gpGlobals->curtime + GetStunDelay(); -} - -//----------------------------------------------------------------------------- -// Purpose: Respond to another rollermine that's chirped at us -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_RollerMine::InputRespondToChirp( inputdata_t &inputdata ) -{ - EmitSound( "NPC_RollerMine.ChirpRespond" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Respond to another rollermine's signal to detonate -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_RollerMine::InputRespondToExplodeChirp( inputdata_t &inputdata ) -{ - EmitSound( "NPC_RollerMine.ExplodeChirpRespond" ); - - Explode(); -} - -//----------------------------------------------------------------------------- -// Purpose: Apply a physics force to the vehicle we're in -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_RollerMine::InputJoltVehicle( inputdata_t &inputdata ) -{ - Assert( GetVehicleStuckTo() ); - - // First, tell all rollers on the vehicle not to fall off - CUtlVector aRollersOnVehicle; - int iRollers = CountRollersOnMyVehicle( &aRollersOnVehicle ); - for ( int i = 0; i < iRollers; i++ ) - { - aRollersOnVehicle[i]->PreventUnstickUntil( gpGlobals->curtime + 1 ); - } - - // Now smack the vehicle - Vector impulse = GetVehicleStuckTo()->GetAbsOrigin() - GetAbsOrigin(); - VectorNormalize( impulse ); - // Randomly apply a little vertical lift, to get the wheels off the ground - impulse.z = RandomFloat( 0.5, 1.0 ); - VectorNormalize( impulse ); - IPhysicsObject *pVehiclePhysics = GetVehicleStuckTo()->VPhysicsGetObject(); - Vector vecForce = impulse * ImpulseScale( pVehiclePhysics->GetMass(), RandomFloat(150,250) ); - pVehiclePhysics->ApplyForceOffset( vecForce, GetAbsOrigin() ); - - // Play sounds & effects - EmitSound( "NPC_RollerMine.JoltVehicle" ); - - // UNDONE: Good Zap effects - /* - CBeam *pBeam = CBeam::BeamCreate( "sprites/rollermine_shock.vmt", 4 ); - if ( pBeam ) - { - pBeam->EntsInit( GetVehicleStuckTo(), this ); - CBaseAnimating *pAnimating = dynamic_cast( GetVehicleStuckTo() ); - if ( pAnimating ) - { - int startAttach = pAnimating->LookupAttachment("beam_damage" ); - pBeam->SetStartAttachment( startAttach ); - } - pBeam->SetEndAttachment( 1 ); - pBeam->SetWidth( 8 ); - pBeam->SetEndWidth( 8 ); - pBeam->SetBrightness( 255 ); - pBeam->SetColor( 255, 255, 255 ); - pBeam->LiveForTime( 0.5f ); - pBeam->RelinkBeam(); - pBeam->SetNoise( 30 ); - } - */ - - ShockTarget( GetVehicleStuckTo() ); - - // Jolt again soon - g_EventQueue.AddEvent( this, "JoltVehicle", RandomFloat(3,6), NULL, NULL ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_RollerMine::InputTurnOn( inputdata_t &inputdata ) -{ - m_RollerController.On(); - m_bTurnedOn = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_RollerMine::InputTurnOff( inputdata_t &inputdata ) -{ - m_RollerController.Off(); - m_bTurnedOn = false; - StopLoopingSounds(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_RollerMine::InputPowerdown( inputdata_t &inputdata ) -{ - m_bPowerDown = true; - m_flPowerDownTime = gpGlobals->curtime + RandomFloat( 0.1, 0.5 ); - m_flPowerDownDetonateTime = m_flPowerDownTime + RandomFloat( 1.5, 4.0 ); - - ClearSchedule( "Received power down input" ); -} - -//----------------------------------------------------------------------------- -// Purpose: If we were stuck to a vehicle, remove ourselves -//----------------------------------------------------------------------------- -void CNPC_RollerMine::UnstickFromVehicle( void ) -{ - if ( m_pConstraint ) - { - physenv->DestroyConstraint( m_pConstraint ); - m_pConstraint = NULL; - } - - // Cancel any pending jolt events - g_EventQueue.CancelEventOn( this, "JoltVehicle" ); - - m_hVehicleStuckTo = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseEntity *CNPC_RollerMine::GetVehicleStuckTo( void ) -{ - if ( !m_pConstraint ) - return NULL; - - return m_hVehicleStuckTo; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPhysGunUser - -//----------------------------------------------------------------------------- -void CNPC_RollerMine::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) -{ - // Are we just being punted? - if ( reason == PUNTED_BY_CANNON ) - { - // Be stunned - m_flActiveTime = gpGlobals->curtime + GetStunDelay(); - return; - } - - //Stop turning - m_RollerController.m_vecAngular = vec3_origin; - - UnstickFromVehicle(); - - m_OnPhysGunPickup.FireOutput( pPhysGunUser, this ); - m_bHeld = true; - m_RollerController.Off(); - EmitSound( "NPC_RollerMine.Held" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPhysGunUser - -//----------------------------------------------------------------------------- -void CNPC_RollerMine::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ) -{ - m_bHeld = false; - m_flActiveTime = gpGlobals->curtime + GetStunDelay(); - m_RollerController.On(); - - // explode on contact if launched from the physgun - if ( Reason == LAUNCHED_BY_CANNON ) - { - if ( m_bIsOpen ) - { - //m_bIsPrimed = true; - SetTouch( &CNPC_RollerMine::SpikeTouch ); - // enable world/prop touch too - VPhysicsGetObject()->SetCallbackFlags( VPhysicsGetObject()->GetCallbackFlags() | CALLBACK_GLOBAL_TOUCH|CALLBACK_GLOBAL_TOUCH_STATIC ); - } - EmitSound( "NPC_RollerMine.Tossed" ); - } - - m_OnPhysGunDrop.FireOutput( pPhysGunUser, this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -// Output : float -//----------------------------------------------------------------------------- -int CNPC_RollerMine::OnTakeDamage( const CTakeDamageInfo &info ) -{ - if ( !(info.GetDamageType() & DMG_BURN) ) - { - if ( GetMoveType() == MOVETYPE_VPHYSICS ) - { - AngularImpulse angVel; - angVel.Random( -400.0f, 400.0f ); - VPhysicsGetObject()->AddVelocity( NULL, &angVel ); - m_RollerController.m_vecAngular *= 0.8f; - - VPhysicsTakeDamage( info ); - } - SetCondition( COND_LIGHT_DAMAGE ); - } - - if ( info.GetDamageType() & (DMG_BURN|DMG_BLAST) ) - { - if ( info.GetAttacker() && info.GetAttacker()->m_iClassname != m_iClassname ) - { - SetThink( &CNPC_RollerMine::PreDetonate ); - SetNextThink( gpGlobals->curtime + random->RandomFloat( 0.1f, 0.5f ) ); - } - else - { - // dazed - m_RollerController.m_vecAngular.Init(); - m_flActiveTime = gpGlobals->curtime + GetStunDelay(); - Hop( 300 ); - } - } - - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: Causes the roller to hop into the air -//----------------------------------------------------------------------------- -void CNPC_RollerMine::Hop( float height ) -{ - if ( m_flNextHop > gpGlobals->curtime ) - return; - - if ( GetMoveType() == MOVETYPE_VPHYSICS ) - { - IPhysicsObject *pPhysObj = VPhysicsGetObject(); - pPhysObj->ApplyForceCenter( Vector(0,0,1) * height * pPhysObj->GetMass() ); - - AngularImpulse angVel; - angVel.Random( -400.0f, 400.0f ); - pPhysObj->AddVelocity( NULL, &angVel ); - - m_flNextHop = gpGlobals->curtime + ROLLERMINE_HOP_DELAY; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Makes warning noise before actual explosion occurs -//----------------------------------------------------------------------------- -void CNPC_RollerMine::PreDetonate( void ) -{ - Hop( 300 ); - - SetTouch( NULL ); - SetThink( &CNPC_RollerMine::Explode ); - SetNextThink( gpGlobals->curtime + 0.5f ); - - EmitSound( "NPC_RollerMine.Hurt" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_RollerMine::Explode( void ) -{ - m_takedamage = DAMAGE_NO; - - //FIXME: Hack to make thrown mines more deadly and fun - float expDamage = m_bIsPrimed ? 100 : 25; - - //If we've been hacked and we're blowing up cause we've been shut down then do moderate damage. - if ( m_bPowerDown == true ) - { - expDamage = 50; - } - - // Underwater explosion? - if ( UTIL_PointContents( GetAbsOrigin() ) & MASK_WATER ) - { - CEffectData data; - data.m_vOrigin = WorldSpaceCenter(); - data.m_flMagnitude = expDamage; - data.m_flScale = 128; - data.m_fFlags = ( SF_ENVEXPLOSION_NOSPARKS | SF_ENVEXPLOSION_NODLIGHTS | SF_ENVEXPLOSION_NOSMOKE ); - DispatchEffect( "WaterSurfaceExplosion", data ); - } - else - { - ExplosionCreate( WorldSpaceCenter(), GetLocalAngles(), this, (int)expDamage, 128, true ); - } - - CTakeDamageInfo info( this, this, 1, DMG_GENERIC ); - Event_Killed( info ); - - // Remove myself a frame from now to avoid doing it in the middle of running AI - SetThink( &CNPC_RollerMine::SUB_Remove ); - SetNextThink( gpGlobals->curtime ); -} - -const float MAX_ROLLING_SPEED = 720; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CNPC_RollerMine::RollingSpeed() -{ - IPhysicsObject *pPhysics = VPhysicsGetObject(); - if ( !m_hVehicleStuckTo && !m_bHeld && pPhysics && !pPhysics->IsAsleep() ) - { - AngularImpulse angVel; - pPhysics->GetVelocity( NULL, &angVel ); - float rollingSpeed = angVel.Length() - 90; - rollingSpeed = clamp( rollingSpeed, 1, MAX_ROLLING_SPEED ); - rollingSpeed *= (1/MAX_ROLLING_SPEED); - return rollingSpeed; - } - return 0; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -float CNPC_RollerMine::GetStunDelay() -{ - if( m_bHackedByAlyx ) - { - return 0.1f; - } - else - { - return sk_rollermine_stun_delay.GetFloat(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: We've been dropped by a dropship. Embed in the ground if we land on it. -//----------------------------------------------------------------------------- -void CNPC_RollerMine::EmbedOnGroundImpact() -{ - m_bEmbedOnGroundImpact = true; - - SetTouch( &CNPC_RollerMine::EmbedTouch ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_RollerMine::PrescheduleThink() -{ - // Are we underwater? - if ( UTIL_PointContents( GetAbsOrigin() ) & MASK_WATER ) - { - // As soon as we're far enough underwater, detonate - Vector vecAboveMe = GetAbsOrigin() + Vector(0,0,64); - if ( UTIL_PointContents( vecAboveMe ) & MASK_WATER ) - { - Explode(); - return; - } - } - - UpdateRollingSound(); - UpdatePingSound(); - BaseClass::PrescheduleThink(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_RollerMine::UpdateRollingSound() -{ - if ( m_rollingSoundState == ROLL_SOUND_NOT_READY ) - return; - - rollingsoundstate_t soundState = ROLL_SOUND_OFF; - float rollingSpeed = RollingSpeed(); - if ( rollingSpeed > 0 ) - { - soundState = m_bIsOpen ? ROLL_SOUND_OPEN : ROLL_SOUND_CLOSED; - } - - - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - CSoundParameters params; - switch( soundState ) - { - case ROLL_SOUND_CLOSED: - CBaseEntity::GetParametersForSound( "NPC_RollerMine.Roll", params, NULL ); - break; - case ROLL_SOUND_OPEN: - CBaseEntity::GetParametersForSound( "NPC_RollerMine.RollWithSpikes", params, NULL ); - break; - - case ROLL_SOUND_OFF: - // no sound - break; - - default: - break; - } - - // start the new sound playing if necessary - if ( m_rollingSoundState != soundState ) - { - StopRollingSound(); - - m_rollingSoundState = soundState; - - if ( m_rollingSoundState == ROLL_SOUND_OFF ) - return; - - CPASAttenuationFilter filter( this ); - m_pRollSound = controller.SoundCreate( filter, entindex(), params.channel, params.soundname, params.soundlevel ); - controller.Play( m_pRollSound, params.volume, params.pitch ); - m_rollingSoundState = soundState; - } - - if ( m_pRollSound ) - { - // for tuning - //DevMsg("SOUND: %s, VOL: %.1f\n", m_rollingSoundState == ROLL_SOUND_CLOSED ? "CLOSED" : "OPEN ", rollingSpeed ); - controller.SoundChangePitch( m_pRollSound, params.pitchlow + (params.pitchhigh - params.pitchlow) * rollingSpeed, 0.1 ); - controller.SoundChangeVolume( m_pRollSound, params.volume * rollingSpeed, 0.1 ); - } -} - - -void CNPC_RollerMine::StopRollingSound() -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundDestroy( m_pRollSound ); - m_pRollSound = NULL; -} - -void CNPC_RollerMine::UpdatePingSound() -{ - float pingSpeed = 0; - if ( m_bIsOpen && !IsShocking() && !m_bHeld ) - { - CBaseEntity *pEnemy = GetEnemy(); - if ( pEnemy ) - { - pingSpeed = EnemyDistance( pEnemy ); - pingSpeed = clamp( pingSpeed, 1, ROLLERMINE_OPEN_THRESHOLD ); - pingSpeed *= (1.0f/ROLLERMINE_OPEN_THRESHOLD); - } - } - - if ( pingSpeed > 0 ) - { - pingSpeed = 1-pingSpeed; - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - CSoundParameters params; - CBaseEntity::GetParametersForSound( "NPC_RollerMine.Ping", params, NULL ); - if ( !m_pPingSound ) - { - CPASAttenuationFilter filter( this ); - m_pPingSound = controller.SoundCreate( filter, entindex(), params.channel, params.soundname, params.soundlevel ); - controller.Play( m_pPingSound, params.volume, 101 ); - } - - controller.SoundChangePitch( m_pPingSound, params.pitchlow + (params.pitchhigh - params.pitchlow) * pingSpeed, 0.1 ); - controller.SoundChangeVolume( m_pPingSound, params.volume, 0.1 ); - //DevMsg("PING: %.1f\n", pingSpeed ); - - } - else - { - StopPingSound(); - } -} - - -void CNPC_RollerMine::StopPingSound() -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundDestroy( m_pPingSound ); - m_pPingSound = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_RollerMine::StopLoopingSounds( void ) -{ - StopRollingSound(); - StopPingSound(); - BaseClass::StopLoopingSounds(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEnemy - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_RollerMine::IsValidEnemy( CBaseEntity *pEnemy ) -{ - // If the enemy's over the vehicle detection range, and it's not a player in a vehicle, ignore it - if ( pEnemy ) - { - float flDistance = GetAbsOrigin().DistTo( pEnemy->GetAbsOrigin() ); - if ( flDistance >= m_flSeeVehiclesOnlyBeyond ) - { - // Handle vehicles - CBaseCombatCharacter *pCCEnemy = pEnemy->MyCombatCharacterPointer(); - if ( pCCEnemy != NULL && pCCEnemy->IsInAVehicle() ) - { - // If we're buried, we only care when they're heading directly towards us - if ( m_bBuried ) - return ( VehicleHeading( pCCEnemy->GetVehicle()->GetVehicleEnt() ) > DOT_20DEGREE ); - - // If we're not buried, chase him as long as he's not heading away from us - return ( VehicleHeading( pCCEnemy->GetVehicleEntity() ) > 0 ); - } - - return false; - } - - // Never pick something I fear - if ( IRelationType( pEnemy ) == D_FR ) - return false; - - // Don't attack flying things. - if ( pEnemy->GetMoveType() == MOVETYPE_FLY ) - return false; - } - - return BaseClass::IsValidEnemy( pEnemy ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_RollerMine::EnemyInVehicle( void ) -{ - // Clearly the enemy is not... - if ( GetEnemy() == NULL ) - return false; - - // If the target is in a vehicle, let the convar choose - CBaseCombatCharacter *pCCEnemy = GetEnemy()->MyCombatCharacterPointer(); - if ( pCCEnemy != NULL && pCCEnemy->IsInAVehicle() ) - return ( sk_rollermine_vehicle_intercept.GetBool() ); - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CNPC_RollerMine::VehicleHeading( CBaseEntity *pVehicle ) -{ - Vector vecVelocity = pVehicle->GetSmoothedVelocity(); - float flSpeed = VectorNormalize( vecVelocity ); - Vector vecToMine = GetAbsOrigin() - pVehicle->GetAbsOrigin(); - VectorNormalize( vecToMine ); - - // If it's not moving, consider it moving towards us, but not directly - // This will enable already active rollers to chase the vehicle if it's stationary. - if ( flSpeed < 10 ) - return 0.1; - - return DotProduct( vecVelocity, vecToMine ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -// &vecDir - -// *ptr - -//----------------------------------------------------------------------------- -void CNPC_RollerMine::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - if ( info.GetDamageType() & (DMG_BULLET | DMG_CLUB) ) - { - CTakeDamageInfo newInfo( info ); - - // If we're stuck to the car, increase it even more - if ( GetVehicleStuckTo() ) - { - newInfo.SetDamageForce( info.GetDamageForce() * 40 ); - } - else - { - newInfo.SetDamageForce( info.GetDamageForce() * 20 ); - } - - BaseClass::TraceAttack( newInfo, vecDir, ptr ); - return; - } - - BaseClass::TraceAttack( info, vecDir, ptr ); -} - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC( npc_rollermine, CNPC_RollerMine ) - - //Tasks - DECLARE_TASK( TASK_ROLLERMINE_CHARGE_ENEMY ) - DECLARE_TASK( TASK_ROLLERMINE_BURIED_WAIT ) - DECLARE_TASK( TASK_ROLLERMINE_UNBURROW ) - DECLARE_TASK( TASK_ROLLERMINE_GET_PATH_TO_FLEE ) - DECLARE_TASK( TASK_ROLLERMINE_NUDGE_TOWARDS_NODES ) - DECLARE_TASK( TASK_ROLLERMINE_RETURN_TO_PLAYER ) - DECLARE_TASK( TASK_ROLLERMINE_POWERDOWN ) - - //Schedules - - DEFINE_SCHEDULE - ( - SCHED_ROLLERMINE_BURIED_WAIT, - - " Tasks" - " TASK_ROLLERMINE_BURIED_WAIT 0" - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - ) - - DEFINE_SCHEDULE - ( - SCHED_ROLLERMINE_BURIED_UNBURROW, - - " Tasks" - " TASK_ROLLERMINE_UNBURROW 0" - " " - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_ROLLERMINE_RANGE_ATTACK1, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY" - " TASK_ROLLERMINE_CHARGE_ENEMY 0" - " " - " Interrupts" - " COND_ENEMY_DEAD" - " COND_NEW_ENEMY" - " COND_ENEMY_OCCLUDED" - " COND_ENEMY_TOO_FAR" - ) - - DEFINE_SCHEDULE - ( - SCHED_ROLLERMINE_CHASE_ENEMY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ROLLERMINE_RANGE_ATTACK1" - " TASK_SET_TOLERANCE_DISTANCE 24" - " TASK_GET_PATH_TO_ENEMY 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " " - " Interrupts" - " COND_ENEMY_DEAD" - " COND_ENEMY_UNREACHABLE" - " COND_ENEMY_TOO_FAR" - " COND_CAN_RANGE_ATTACK1" - " COND_TASK_FAILED" - " COND_SEE_FEAR" - ) - - DEFINE_SCHEDULE - ( - SCHED_ROLLERMINE_FLEE, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_IDLE_STAND" - " TASK_ROLLERMINE_GET_PATH_TO_FLEE 300" - " TASK_RUN_PATH 0" - " TASK_STOP_MOVING 0" - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_TASK_FAILED" - ) - - DEFINE_SCHEDULE - ( - SCHED_ROLLERMINE_ALERT_STAND, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_REASONABLE 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT 2" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_ENEMY" - " COND_SEE_FEAR" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_PROVOKED" - " COND_SMELL" - " COND_HEAR_COMBAT" // sound flags - " COND_HEAR_WORLD" - " COND_HEAR_PLAYER" - " COND_HEAR_DANGER" - " COND_HEAR_BULLET_IMPACT" - " COND_IDLE_INTERRUPT" - ) - - DEFINE_SCHEDULE - ( - SCHED_ROLLERMINE_NUDGE_TOWARDS_NODES, - - " Tasks" - " TASK_ROLLERMINE_NUDGE_TOWARDS_NODES 0" - " TASK_WAIT 1.5" - "" - " Interrupts" - "" - ) - - DEFINE_SCHEDULE - ( - SCHED_ROLLERMINE_PATH_TO_PLAYER, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ROLLERMINE_ALERT_STAND" - " TASK_SET_TOLERANCE_DISTANCE 200" - " TASK_GET_PATH_TO_PLAYER 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_ENEMY" - " COND_SEE_FEAR" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_PROVOKED" - " COND_SMELL" - " COND_HEAR_COMBAT" // sound flags - " COND_HEAR_WORLD" - " COND_HEAR_PLAYER" - " COND_HEAR_DANGER" - " COND_HEAR_BULLET_IMPACT" - " COND_IDLE_INTERRUPT" - " COND_SEE_PLAYER" - ) - - DEFINE_SCHEDULE - ( - SCHED_ROLLERMINE_ROLL_TO_PLAYER, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_ROLLERMINE_ALERT_STAND" - " TASK_SET_TOLERANCE_DISTANCE 200" - " TASK_ROLLERMINE_RETURN_TO_PLAYER 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_ENEMY" - " COND_SEE_FEAR" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_PROVOKED" - " COND_SMELL" - " COND_HEAR_COMBAT" // sound flags - " COND_HEAR_WORLD" - " COND_HEAR_PLAYER" - " COND_HEAR_DANGER" - " COND_HEAR_BULLET_IMPACT" - " COND_IDLE_INTERRUPT" - ) - - DEFINE_SCHEDULE - ( - SCHED_ROLLERMINE_POWERDOWN, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_ROLLERMINE_POWERDOWN 0" - "" - " Interrupts" - "" - ); - -AI_END_CUSTOM_NPC() diff --git a/game/server/hl2/npc_rollermine.h b/game/server/hl2/npc_rollermine.h deleted file mode 100644 index c29dd1216..000000000 --- a/game/server/hl2/npc_rollermine.h +++ /dev/null @@ -1,22 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef NPC_ROLLERMINE_H -#define NPC_ROLLERMINE_H -#ifdef _WIN32 -#pragma once -#endif - -//------------------------------------ -// Spawnflags -//------------------------------------ -#define SF_ROLLERMINE_FRIENDLY (1 << 16) -#define SF_ROLLERMINE_PROP_COLLISION (1 << 17) - -bool NPC_Rollermine_IsRollermine( CBaseEntity *pEntity ); -CBaseEntity *NPC_Rollermine_DropFromPoint( const Vector &originStart, CBaseEntity *pOwner, const char *pszTemplate ); - -#endif // NPC_ROLLERMINE_H diff --git a/game/server/hl2/npc_scanner.cpp b/game/server/hl2/npc_scanner.cpp deleted file mode 100644 index f1f7ccf1f..000000000 --- a/game/server/hl2/npc_scanner.cpp +++ /dev/null @@ -1,3029 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" -#include "soundenvelope.h" -#include "ai_hint.h" -#include "ai_moveprobe.h" -#include "ai_squad.h" -#include "beam_shared.h" -#include "globalstate.h" -#include "soundent.h" -#include "npc_citizen17.h" -#include "gib.h" -#include "spotlightend.h" -#include "IEffects.h" -#include "items.h" -#include "ai_route.h" -#include "player_pickup.h" -#include "weapon_physcannon.h" -#include "hl2_player.h" -#include "npc_scanner.h" -#include "materialsystem/imaterialsystemhardwareconfig.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Singleton interfaces -//----------------------------------------------------------------------------- -extern IMaterialSystemHardwareConfig *g_pMaterialSystemHardwareConfig; - -//----------------------------------------------------------------------------- -// Parameters for how the scanner relates to citizens. -//----------------------------------------------------------------------------- -#define SCANNER_CIT_INSPECT_DELAY 10 // Check for citizens this often -#define SCANNER_CIT_INSPECT_GROUND_DIST 500 // How far to look for citizens to inspect -#define SCANNER_CIT_INSPECT_FLY_DIST 1500 // How far to look for citizens to inspect - -#define SCANNER_CIT_INSPECT_LENGTH 5 // How long does the inspection last -#define SCANNER_HINT_INSPECT_LENGTH 5 // How long does the inspection last -#define SCANNER_SOUND_INSPECT_LENGTH 5 // How long does the inspection last - -#define SCANNER_HINT_INSPECT_DELAY 15 // Check for hint nodes this often - -#define SPOTLIGHT_WIDTH 32 - -#define SCANNER_SPOTLIGHT_NEAR_DIST 64 -#define SCANNER_SPOTLIGHT_FAR_DIST 256 -#define SCANNER_SPOTLIGHT_FLY_HEIGHT 72 -#define SCANNER_NOSPOTLIGHT_FLY_HEIGHT 72 - -#define SCANNER_FLASH_MIN_DIST 900 // How far does flash effect enemy -#define SCANNER_FLASH_MAX_DIST 1200 // How far does flash effect enemy - -#define SCANNER_FLASH_MAX_VALUE 240 // How bright is maximum flash - -#define SCANNER_PHOTO_NEAR_DIST 64 -#define SCANNER_PHOTO_FAR_DIST 128 - -#define SCANNER_FOLLOW_DIST 128 - -#define SCANNER_NUM_GIBS 6 // Number of gibs in gib file - -// Strider Scout Scanners -#define SCANNER_SCOUT_MAX_SPEED 150 - -ConVar sk_scanner_health( "sk_scanner_health","0"); -ConVar g_debug_cscanner( "g_debug_cscanner", "0" ); - -//----------------------------------------------------------------------------- -// Private activities. -//----------------------------------------------------------------------------- -static int ACT_SCANNER_SMALL_FLINCH_ALERT = 0; -static int ACT_SCANNER_SMALL_FLINCH_COMBAT = 0; -static int ACT_SCANNER_INSPECT = 0; -static int ACT_SCANNER_WALK_ALERT = 0; -static int ACT_SCANNER_WALK_COMBAT = 0; -static int ACT_SCANNER_FLARE = 0; -static int ACT_SCANNER_RETRACT = 0; -static int ACT_SCANNER_FLARE_PRONGS = 0; -static int ACT_SCANNER_RETRACT_PRONGS = 0; -static int ACT_SCANNER_FLARE_START = 0; - -//----------------------------------------------------------------------------- -// Interactions -//----------------------------------------------------------------------------- -int g_interactionScannerInspect = 0; -int g_interactionScannerInspectBegin = 0; -int g_interactionScannerInspectHandsUp = 0; -int g_interactionScannerInspectShowArmband = 0;//<>still to be completed -int g_interactionScannerInspectDone = 0; -int g_interactionScannerSupportEntity = 0; -int g_interactionScannerSupportPosition = 0; - -//----------------------------------------------------------------------------- -// Animation events -//------------------------------------------------------------------------ -int AE_SCANNER_CLOSED; - -//----------------------------------------------------------------------------- -// Attachment points -//----------------------------------------------------------------------------- -#define SCANNER_ATTACHMENT_LIGHT "light" -#define SCANNER_ATTACHMENT_FLASH 1 -#define SCANNER_ATTACHMENT_LPRONG 2 -#define SCANNER_ATTACHMENT_RPRONG 3 - -//----------------------------------------------------------------------------- -// Other defines. -//----------------------------------------------------------------------------- -#define SCANNER_MAX_BEAMS 4 - -BEGIN_DATADESC( CNPC_CScanner ) - - DEFINE_SOUNDPATCH( m_pEngineSound ), - - DEFINE_EMBEDDED( m_KilledInfo ), - DEFINE_FIELD( m_flGoalOverrideDistance, FIELD_FLOAT ), - DEFINE_FIELD( m_bPhotoTaken, FIELD_BOOLEAN ), - DEFINE_FIELD( m_vInspectPos, FIELD_VECTOR ), - DEFINE_FIELD( m_fInspectEndTime, FIELD_TIME ), - DEFINE_FIELD( m_fCheckCitizenTime, FIELD_TIME ), - DEFINE_FIELD( m_fCheckHintTime, FIELD_TIME ), - DEFINE_KEYFIELD( m_bShouldInspect, FIELD_BOOLEAN, "ShouldInspect" ), - DEFINE_KEYFIELD( m_bOnlyInspectPlayers, FIELD_BOOLEAN, "OnlyInspectPlayers" ), - DEFINE_KEYFIELD( m_bNeverInspectPlayers,FIELD_BOOLEAN, "NeverInspectPlayers" ), - DEFINE_FIELD( m_fNextPhotographTime, FIELD_TIME ), -// DEFINE_FIELD( m_pEyeFlash, FIELD_CLASSPTR ), - DEFINE_FIELD( m_vSpotlightTargetPos, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vSpotlightCurrentPos, FIELD_POSITION_VECTOR ), -// don't save (recreated after restore/transition) -// DEFINE_FIELD( m_hSpotlight, FIELD_EHANDLE ), -// DEFINE_FIELD( m_hSpotlightTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_vSpotlightDir, FIELD_VECTOR ), - DEFINE_FIELD( m_vSpotlightAngVelocity, FIELD_VECTOR ), - DEFINE_FIELD( m_flSpotlightCurLength, FIELD_FLOAT ), - DEFINE_FIELD( m_fNextSpotlightTime, FIELD_TIME ), - DEFINE_FIELD( m_nHaloSprite, FIELD_INTEGER ), - DEFINE_FIELD( m_fNextFlySoundTime, FIELD_TIME ), - DEFINE_FIELD( m_nFlyMode, FIELD_INTEGER ), - DEFINE_FIELD( m_nPoseTail, FIELD_INTEGER ), - DEFINE_FIELD( m_nPoseDynamo, FIELD_INTEGER ), - DEFINE_FIELD( m_nPoseFlare, FIELD_INTEGER ), - DEFINE_FIELD( m_nPoseFaceVert, FIELD_INTEGER ), - DEFINE_FIELD( m_nPoseFaceHoriz, FIELD_INTEGER ), - - DEFINE_FIELD( m_bIsClawScanner, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bIsOpen, FIELD_BOOLEAN ), - - // DEFINE_FIELD( m_bHasSpoken, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_pSmokeTrail, FIELD_CLASSPTR ), - DEFINE_FIELD( m_flFlyNoiseBase, FIELD_FLOAT ), - DEFINE_FIELD( m_flEngineStallTime, FIELD_TIME ), - - DEFINE_FIELD( m_vecDiveBombDirection, FIELD_VECTOR ), - DEFINE_FIELD( m_flDiveBombRollForce, FIELD_FLOAT ), - - DEFINE_KEYFIELD( m_flSpotlightMaxLength, FIELD_FLOAT, "SpotlightLength"), - DEFINE_KEYFIELD( m_flSpotlightGoalWidth, FIELD_FLOAT, "SpotlightWidth"), - - // Physics Influence - DEFINE_FIELD( m_hPhysicsAttacker, FIELD_EHANDLE ), - DEFINE_FIELD( m_flLastPhysicsInfluenceTime, FIELD_TIME ), - - DEFINE_KEYFIELD( m_bNoLight, FIELD_BOOLEAN, "SpotlightDisabled" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "DisableSpotlight", InputDisableSpotlight ), - DEFINE_INPUTFUNC( FIELD_STRING, "InspectTargetPhoto", InputInspectTargetPhoto ), - DEFINE_INPUTFUNC( FIELD_STRING, "InspectTargetSpotlight", InputInspectTargetSpotlight ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "InputShouldInspect", InputShouldInspect ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetFollowTarget", InputSetFollowTarget ), - DEFINE_INPUTFUNC( FIELD_VOID, "ClearFollowTarget", InputClearFollowTarget ), - - DEFINE_INPUTFUNC( FIELD_STRING, "DeployMine", InputDeployMine ), - DEFINE_INPUTFUNC( FIELD_STRING, "EquipMine", InputEquipMine ), - - DEFINE_OUTPUT( m_OnPhotographPlayer, "OnPhotographPlayer" ), - DEFINE_OUTPUT( m_OnPhotographNPC, "OnPhotographNPC" ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS(npc_cscanner, CNPC_CScanner); - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CNPC_CScanner::CNPC_CScanner() -{ -#ifdef _DEBUG - m_vInspectPos.Init(); - m_vSpotlightTargetPos.Init(); - m_vSpotlightCurrentPos.Init(); - m_vSpotlightDir.Init(); - m_vSpotlightAngVelocity.Init(); -#endif - m_bShouldInspect = true; - m_bOnlyInspectPlayers = false; - m_bNeverInspectPlayers = false; - - char szMapName[256]; - Q_strncpy(szMapName, STRING(gpGlobals->mapname), sizeof(szMapName) ); - Q_strlower(szMapName); - - if( !Q_strnicmp( szMapName, "d3_c17", 6 ) ) - { - // Streetwar scanners are claw scanners - m_bIsClawScanner = true; - } - else - { - m_bIsClawScanner = false; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CScanner::Spawn(void) -{ - // Check for user error - if (m_flSpotlightMaxLength <= 0) - { - DevMsg("CNPC_CScanner::Spawn: Invalid spotlight length <= 0, setting to 500\n"); - m_flSpotlightMaxLength = 500; - } - - if (m_flSpotlightGoalWidth <= 0) - { - DevMsg("CNPC_CScanner::Spawn: Invalid spotlight width <= 0, setting to 100\n"); - m_flSpotlightGoalWidth = 100; - } - - if (m_flSpotlightGoalWidth > MAX_BEAM_WIDTH ) - { - DevMsg("CNPC_CScanner::Spawn: Invalid spotlight width %.1f (max %.1f).\n", m_flSpotlightGoalWidth, MAX_BEAM_WIDTH ); - m_flSpotlightGoalWidth = MAX_BEAM_WIDTH; - } - - Precache(); - - if( m_bIsClawScanner ) - { - SetModel( "models/shield_scanner.mdl"); - } - else - { - SetModel( "models/combine_scanner.mdl"); - } - - m_iHealth = sk_scanner_health.GetFloat(); - m_iMaxHealth = m_iHealth; - - // ------------------------------------ - // Init all class vars - // ------------------------------------ - m_vInspectPos = vec3_origin; - m_fInspectEndTime = 0; - m_fCheckCitizenTime = gpGlobals->curtime + SCANNER_CIT_INSPECT_DELAY; - m_fCheckHintTime = gpGlobals->curtime + SCANNER_HINT_INSPECT_DELAY; - m_fNextPhotographTime = 0; - - m_vSpotlightTargetPos = vec3_origin; - m_vSpotlightCurrentPos = vec3_origin; - - m_hSpotlight = NULL; - m_hSpotlightTarget = NULL; - - AngleVectors( GetLocalAngles(), &m_vSpotlightDir ); - m_vSpotlightAngVelocity = vec3_origin; - - m_pEyeFlash = 0; - m_fNextSpotlightTime = 0; - m_nFlyMode = SCANNER_FLY_PATROL; - m_vCurrentBanking = m_vSpotlightDir; - m_flSpotlightCurLength = m_flSpotlightMaxLength; - - m_nPoseTail = LookupPoseParameter( "tail_control" ); - m_nPoseDynamo = LookupPoseParameter( "dynamo_wheel" ); - m_nPoseFlare = LookupPoseParameter( "alert_control" ); - m_nPoseFaceVert = LookupPoseParameter( "flex_vert" ); - m_nPoseFaceHoriz = LookupPoseParameter( "flex_horz" ); - - // -------------------------------------------- - - CapabilitiesAdd( bits_CAP_INNATE_MELEE_ATTACK1 ); - - m_bPhotoTaken = false; - - BaseClass::Spawn(); - - // Watch for this error state - if ( m_bOnlyInspectPlayers && m_bNeverInspectPlayers ) - { - Assert( 0 ); - Warning( "ERROR: Scanner set to never and always inspect players!\n" ); - } -} - - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -void CNPC_CScanner::Activate() -{ - BaseClass::Activate(); - - // Have to do this here because sprites do not go across level transitions - m_pEyeFlash = CSprite::SpriteCreate( "sprites/blueflare1.vmt", GetLocalOrigin(), FALSE ); - m_pEyeFlash->SetTransparency( kRenderGlow, 255, 255, 255, 0, kRenderFxNoDissipation ); - m_pEyeFlash->SetAttachment( this, LookupAttachment( SCANNER_ATTACHMENT_LIGHT ) ); - m_pEyeFlash->SetBrightness( 0 ); - m_pEyeFlash->SetScale( 1.4 ); -} - -//------------------------------------------------------------------------------ -// Purpose: Override to split in two when attacked -//------------------------------------------------------------------------------ -int CNPC_CScanner::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - // Turn off my spotlight when shot - SpotlightDestroy(); - m_fNextSpotlightTime = gpGlobals->curtime + 2.0f; - - return (BaseClass::OnTakeDamage_Alive( info )); -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CNPC_CScanner::Gib( void ) -{ - if ( IsMarkedForDeletion() ) - return; - - // Spawn all gibs - if( m_bIsClawScanner ) - { - CGib::SpawnSpecificGibs( this, 1, 500, 250, "models/gibs/Shield_Scanner_Gib1.mdl"); - CGib::SpawnSpecificGibs( this, 1, 500, 250, "models/gibs/Shield_Scanner_Gib2.mdl"); - CGib::SpawnSpecificGibs( this, 1, 500, 250, "models/gibs/Shield_Scanner_Gib3.mdl"); - CGib::SpawnSpecificGibs( this, 1, 500, 250, "models/gibs/Shield_Scanner_Gib4.mdl"); - CGib::SpawnSpecificGibs( this, 1, 500, 250, "models/gibs/Shield_Scanner_Gib5.mdl"); - CGib::SpawnSpecificGibs( this, 1, 500, 250, "models/gibs/Shield_Scanner_Gib6.mdl"); - } - else - { - CGib::SpawnSpecificGibs( this, 1, 500, 250, "models/gibs/scanner_gib01.mdl" ); - CGib::SpawnSpecificGibs( this, 1, 500, 250, "models/gibs/scanner_gib02.mdl" ); - CGib::SpawnSpecificGibs( this, 1, 500, 250, "models/gibs/scanner_gib04.mdl" ); - CGib::SpawnSpecificGibs( this, 1, 500, 250, "models/gibs/scanner_gib05.mdl" ); - } - - // Add a random chance of spawning a battery... - if ( !HasSpawnFlags(SF_NPC_NO_WEAPON_DROP) && random->RandomFloat( 0.0f, 1.0f) < 0.3f ) - { - CItem *pBattery = (CItem*)CreateEntityByName("item_battery"); - if ( pBattery ) - { - pBattery->SetAbsOrigin( GetAbsOrigin() ); - pBattery->SetAbsVelocity( GetAbsVelocity() ); - pBattery->SetLocalAngularVelocity( GetLocalAngularVelocity() ); - pBattery->ActivateWhenAtRest(); - pBattery->Spawn(); - } - } - - DeployMine(); - - BaseClass::Gib(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pInflictor - -// pAttacker - -// flDamage - -// bitsDamageType - -//----------------------------------------------------------------------------- -void CNPC_CScanner::Event_Killed( const CTakeDamageInfo &info ) -{ - // Copy off the takedamage info that killed me, since we're not going to call - // up into the base class's Event_Killed() until we gib. (gibbing is ultimate death) - m_KilledInfo = info; - - DeployMine(); - - ClearInspectTarget(); - - // Interrupt whatever schedule I'm on - SetCondition(COND_SCHEDULE_DONE); - - // Remove spotlight - SpotlightDestroy(); - - // Remove sprite - UTIL_Remove(m_pEyeFlash); - m_pEyeFlash = NULL; - - // If I have an enemy and I'm up high, do a dive bomb (unless dissolved) - if ( !m_bIsClawScanner && GetEnemy() != NULL && (info.GetDamageType() & DMG_DISSOLVE) == false ) - { - Vector vecDelta = GetLocalOrigin() - GetEnemy()->GetLocalOrigin(); - if ( ( vecDelta.z > 120 ) && ( vecDelta.Length() > 360 ) ) - { - // If I'm divebombing, don't take any more damage. It will make Event_Killed() be called again. - // This is especially bad if someone machineguns the divebombing scanner. - AttackDivebomb(); - return; - } - } - - Gib(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Tells use whether or not the NPC cares about a given type of hint node. -// Input : sHint - -// Output : TRUE if the NPC is interested in this hint type, FALSE if not. -//----------------------------------------------------------------------------- -bool CNPC_CScanner::FValidateHintType(CAI_Hint *pHint) -{ - return( pHint->HintType() == HINT_WORLD_WINDOW ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : Type - -//----------------------------------------------------------------------------- -int CNPC_CScanner::TranslateSchedule( int scheduleType ) -{ - switch ( scheduleType ) - { - case SCHED_IDLE_STAND: - { - return SCHED_SCANNER_PATROL; - } - - case SCHED_SCANNER_PATROL: - return SCHED_CSCANNER_PATROL; - } - return BaseClass::TranslateSchedule(scheduleType); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : idealActivity - -// *pIdealWeaponActivity - -// Output : int -//----------------------------------------------------------------------------- -Activity CNPC_CScanner::NPC_TranslateActivity( Activity eNewActivity ) -{ - if( !m_bIsClawScanner ) - { - return BaseClass::NPC_TranslateActivity( eNewActivity ); - } - - // The claw scanner came along a little late and doesn't have the activities - // of the city scanner. So Just pick between these three - if( eNewActivity == ACT_DISARM ) - { - // Closing up. - return eNewActivity; - } - - if( m_bIsOpen ) - { - return ACT_IDLE_ANGRY; - } - else - { - return ACT_IDLE; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_CScanner::HandleAnimEvent( animevent_t *pEvent ) -{ - if( pEvent->event == AE_SCANNER_CLOSED ) - { - m_bIsOpen = false; - SetActivity( ACT_IDLE ); - return; - } - - BaseClass::HandleAnimEvent( pEvent ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const char *CNPC_CScanner::GetEngineSound( void ) -{ - if( m_bIsClawScanner ) - return "NPC_SScanner.FlyLoop"; - - return "NPC_CScanner.FlyLoop"; -} - -//----------------------------------------------------------------------------- -// Purpose: Plays the engine sound. -//----------------------------------------------------------------------------- -void CNPC_CScanner::NPCThink(void) -{ - if (!IsAlive()) - { - SetActivity((Activity)ACT_SCANNER_RETRACT_PRONGS); - StudioFrameAdvance( ); - SetNextThink( gpGlobals->curtime + 0.1f ); - } - else - { - BaseClass::NPCThink(); - SpotlightUpdate(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CScanner::Precache(void) -{ - // Model - if( m_bIsClawScanner ) - { - PrecacheModel("models/shield_scanner.mdl"); - - PrecacheModel("models/gibs/Shield_Scanner_Gib1.mdl"); - PrecacheModel("models/gibs/Shield_Scanner_Gib2.mdl"); - PrecacheModel("models/gibs/Shield_Scanner_Gib3.mdl"); - PrecacheModel("models/gibs/Shield_Scanner_Gib4.mdl"); - PrecacheModel("models/gibs/Shield_Scanner_Gib5.mdl"); - PrecacheModel("models/gibs/Shield_Scanner_Gib6.mdl"); - - PrecacheScriptSound( "NPC_SScanner.Shoot"); - PrecacheScriptSound( "NPC_SScanner.Alert" ); - PrecacheScriptSound( "NPC_SScanner.Die" ); - PrecacheScriptSound( "NPC_SScanner.Combat" ); - PrecacheScriptSound( "NPC_SScanner.Idle" ); - PrecacheScriptSound( "NPC_SScanner.Pain" ); - PrecacheScriptSound( "NPC_SScanner.TakePhoto" ); - PrecacheScriptSound( "NPC_SScanner.AttackFlash" ); - PrecacheScriptSound( "NPC_SScanner.DiveBombFlyby" ); - PrecacheScriptSound( "NPC_SScanner.DiveBomb" ); - PrecacheScriptSound( "NPC_SScanner.DeployMine" ); - - PrecacheScriptSound( "NPC_SScanner.FlyLoop" ); - UTIL_PrecacheOther( "combine_mine" ); - } - else - { - PrecacheModel("models/combine_scanner.mdl"); - - PrecacheModel("models/gibs/scanner_gib01.mdl" ); - PrecacheModel("models/gibs/scanner_gib02.mdl" ); - PrecacheModel("models/gibs/scanner_gib02.mdl" ); - PrecacheModel("models/gibs/scanner_gib04.mdl" ); - PrecacheModel("models/gibs/scanner_gib05.mdl" ); - - PrecacheScriptSound( "NPC_CScanner.Shoot"); - PrecacheScriptSound( "NPC_CScanner.Alert" ); - PrecacheScriptSound( "NPC_CScanner.Die" ); - PrecacheScriptSound( "NPC_CScanner.Combat" ); - PrecacheScriptSound( "NPC_CScanner.Idle" ); - PrecacheScriptSound( "NPC_CScanner.Pain" ); - PrecacheScriptSound( "NPC_CScanner.TakePhoto" ); - PrecacheScriptSound( "NPC_CScanner.AttackFlash" ); - PrecacheScriptSound( "NPC_CScanner.DiveBombFlyby" ); - PrecacheScriptSound( "NPC_CScanner.DiveBomb" ); - PrecacheScriptSound( "NPC_CScanner.DeployMine" ); - - PrecacheScriptSound( "NPC_CScanner.FlyLoop" ); - } - - // Sprites - m_nHaloSprite = PrecacheModel("sprites/light_glow03.vmt"); - PrecacheModel( "sprites/glow_test02.vmt" ); - - BaseClass::Precache(); -} - -//------------------------------------------------------------------------------ -// Purpose: Request help inspecting from other squad members -//------------------------------------------------------------------------------ -void CNPC_CScanner::RequestInspectSupport(void) -{ - if (m_pSquad) - { - AISquadIter_t iter; - for (CAI_BaseNPC *pSquadMember = m_pSquad->GetFirstMember( &iter ); pSquadMember; pSquadMember = m_pSquad->GetNextMember( &iter ) ) - { - if (pSquadMember != this) - { - if (GetTarget()) - { - pSquadMember->DispatchInteraction(g_interactionScannerSupportEntity,((void *)((CBaseEntity*)GetTarget())),this); - } - else - { - pSquadMember->DispatchInteraction(g_interactionScannerSupportPosition,((void *)m_vInspectPos.Base()),this); - } - } - } - } -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -bool CNPC_CScanner::IsValidInspectTarget(CBaseEntity *pEntity) -{ - // If a citizen, make sure he can be inspected again - if (pEntity->Classify() == CLASS_CITIZEN_PASSIVE) - { - if (((CNPC_Citizen*)pEntity)->GetNextScannerInspectTime() > gpGlobals->curtime) - { - return false; - } - } - - // Make sure no other squad member has already chosen to - // inspect this entity - if (m_pSquad) - { - AISquadIter_t iter; - for (CAI_BaseNPC *pSquadMember = m_pSquad->GetFirstMember( &iter ); pSquadMember; pSquadMember = m_pSquad->GetNextMember( &iter ) ) - { - if (pSquadMember->GetTarget() == pEntity) - { - return false; - } - } - } - - // Do not inspect friendly targets - if ( IRelationType( pEntity ) == D_LI ) - return false; - - return true; -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -CBaseEntity* CNPC_CScanner::BestInspectTarget(void) -{ - if ( !m_bShouldInspect ) - return NULL; - - CBaseEntity* pBestEntity = NULL; - float fBestDist = MAX_COORD_RANGE; - float fTestDist; - - CBaseEntity *pEntity = NULL; - - // If I have a spotlight, search from the spotlight position - // otherwise search from my position - Vector vSearchOrigin; - float fSearchDist; - if (m_hSpotlightTarget != NULL) - { - vSearchOrigin = m_hSpotlightTarget->GetAbsOrigin(); - fSearchDist = SCANNER_CIT_INSPECT_GROUND_DIST; - } - else - { - vSearchOrigin = WorldSpaceCenter(); - fSearchDist = SCANNER_CIT_INSPECT_FLY_DIST; - } - - if ( m_bOnlyInspectPlayers ) - { - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( !pPlayer ) - return NULL; - - if ( !pPlayer->IsAlive() || (pPlayer->GetFlags() & FL_NOTARGET) ) - return NULL; - - return WorldSpaceCenter().DistToSqr( pPlayer->EyePosition() ) <= (fSearchDist * fSearchDist) ? pPlayer : NULL; - } - - CUtlVector candidates; - float fSearchDistSq = fSearchDist * fSearchDist; - int i; - - // Inspect players unless told otherwise - if ( m_bNeverInspectPlayers == false ) - { - // Players - for ( i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBaseEntity *pPlayer = UTIL_PlayerByIndex( i ); - - if ( pPlayer ) - { - if ( vSearchOrigin.DistToSqr(pPlayer->GetAbsOrigin()) < fSearchDistSq ) - { - candidates.AddToTail( pPlayer ); - } - } - } - } - - // NPCs - CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); - - for ( i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - if ( ppAIs[i] != this && vSearchOrigin.DistToSqr(ppAIs[i]->GetAbsOrigin()) < fSearchDistSq ) - { - candidates.AddToTail( ppAIs[i] ); - } - } - - for ( i = 0; i < candidates.Count(); i++ ) - { - pEntity = candidates[i]; - Assert( pEntity != this && (pEntity->MyNPCPointer() || pEntity->IsPlayer() ) ); - - CAI_BaseNPC *pNPC = pEntity->MyNPCPointer(); - if ( ( pNPC && pNPC->Classify() == CLASS_CITIZEN_PASSIVE ) || pEntity->IsPlayer() ) - { - if ( pEntity->GetFlags() & FL_NOTARGET ) - continue; - - if ( pEntity->IsAlive() == false ) - continue; - - // Ensure it's within line of sight - if ( !FVisible( pEntity ) ) - continue; - - fTestDist = ( GetAbsOrigin() - pEntity->EyePosition() ).Length(); - if ( fTestDist < fBestDist ) - { - if ( IsValidInspectTarget( pEntity ) ) - { - fBestDist = fTestDist; - pBestEntity = pEntity; - } - } - } - } - return pBestEntity; -} - - -//------------------------------------------------------------------------------ -// Purpose: Clears any previous inspect target and set inspect target to -// the given entity and set the durection of the inspection -//------------------------------------------------------------------------------ -void CNPC_CScanner::SetInspectTargetToEnt(CBaseEntity *pEntity, float fInspectDuration) -{ - ClearInspectTarget(); - SetTarget(pEntity); - - m_fInspectEndTime = gpGlobals->curtime + fInspectDuration; -} - - -//------------------------------------------------------------------------------ -// Purpose: Clears any previous inspect target and set inspect target to -// the given hint node and set the durection of the inspection -//------------------------------------------------------------------------------ -void CNPC_CScanner::SetInspectTargetToHint(CAI_Hint *pHint, float fInspectDuration) -{ - ClearInspectTarget(); - - float yaw = pHint->Yaw(); - // -------------------------------------------- - // Figure out the location that the hint hits - // -------------------------------------------- - Vector vHintDir = UTIL_YawToVector( yaw ); - - Vector vHintOrigin; - pHint->GetPosition( this, &vHintOrigin ); - - Vector vHintEnd = vHintOrigin + (vHintDir * 512); - - trace_t tr; - AI_TraceLine ( vHintOrigin, vHintEnd, MASK_BLOCKLOS, this, COLLISION_GROUP_NONE, &tr); - - if ( g_debug_cscanner.GetBool() ) - { - NDebugOverlay::Line( vHintOrigin, tr.endpos, 255, 0, 0, true, 4.0f ); - NDebugOverlay::Cross3D( tr.endpos, -Vector(8,8,8), Vector(8,8,8), 255, 0, 0, true, 4.0f ); - } - - if (tr.fraction == 1.0f ) - { - DevMsg("ERROR: Scanner hint node not facing a surface!\n"); - } - else - { - SetHintNode( pHint ); - m_vInspectPos = tr.endpos; - pHint->Lock( this ); - - m_fInspectEndTime = gpGlobals->curtime + fInspectDuration; - } -} - - -//------------------------------------------------------------------------------ -// Purpose: Clears any previous inspect target and set inspect target to -// the given position and set the durection of the inspection -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_CScanner::SetInspectTargetToPos(const Vector &vInspectPos, float fInspectDuration) -{ - ClearInspectTarget(); - m_vInspectPos = vInspectPos; - - m_fInspectEndTime = gpGlobals->curtime + fInspectDuration; -} - - -//------------------------------------------------------------------------------ -// Purpose: Clears out any previous inspection targets -//------------------------------------------------------------------------------ -void CNPC_CScanner::ClearInspectTarget(void) -{ - if ( GetIdealState() != NPC_STATE_SCRIPT ) - { - SetTarget( NULL ); - } - - ClearHintNode( SCANNER_HINT_INSPECT_LENGTH ); - m_vInspectPos = vec3_origin; -} - - -//------------------------------------------------------------------------------ -// Purpose: Returns true if there is a position to be inspected. -//------------------------------------------------------------------------------ -bool CNPC_CScanner::HaveInspectTarget( void ) -{ - if ( GetTarget() != NULL ) - return true; - - if ( m_vInspectPos != vec3_origin ) - return true; - - return false; -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -Vector CNPC_CScanner::InspectTargetPosition(void) -{ - // If we have a target, return an adjust position - if ( GetTarget() != NULL ) - { - Vector vEyePos = GetTarget()->EyePosition(); - - // If in spotlight mode, aim for ground below target unless is client - if ( m_nFlyMode == SCANNER_FLY_SPOT && !(GetTarget()->GetFlags() & FL_CLIENT) ) - { - Vector vInspectPos; - vInspectPos.x = vEyePos.x; - vInspectPos.y = vEyePos.y; - vInspectPos.z = GetFloorZ( vEyePos ); - - // Let's take three-quarters between eyes and ground - vInspectPos.z += ( vEyePos.z - vInspectPos.z ) * 0.75f; - - return vInspectPos; - } - else - { - // Otherwise aim for eyes - return vEyePos; - } - } - else if ( m_vInspectPos != vec3_origin ) - { - return m_vInspectPos; - } - else - { - DevMsg("InspectTargetPosition called with no target!\n"); - - return m_vInspectPos; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CScanner::InputShouldInspect( inputdata_t &inputdata ) -{ - m_bShouldInspect = ( inputdata.value.Int() != 0 ); - - if ( !m_bShouldInspect ) - { - if ( GetEnemy() == GetTarget() ) - SetEnemy(NULL); - ClearInspectTarget(); - SetTarget(NULL); - SpotlightDestroy(); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_CScanner::DeployMine() -{ - CBaseEntity *child; - // iterate through all children - for ( child = FirstMoveChild(); child != NULL; child = child->NextMovePeer() ) - { - if( FClassnameIs( child, "combine_mine" ) ) - { - child->SetParent( NULL ); - child->SetAbsVelocity( GetAbsVelocity() ); - child->SetOwnerEntity( this ); - - ScannerEmitSound( "DeployMine" ); - - IPhysicsObject *pPhysObj = child->VPhysicsGetObject(); - if( pPhysObj ) - { - // Make sure the mine's awake - pPhysObj->Wake(); - } - - if( m_bIsClawScanner ) - { - // Fold up. - SetActivity( ACT_DISARM ); - } - - return; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CNPC_CScanner::GetMaxSpeed() -{ - if( IsStriderScout() ) - { - return SCANNER_SCOUT_MAX_SPEED; - } - - return BaseClass::GetMaxSpeed(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CScanner::InputDeployMine(inputdata_t &inputdata) -{ - DeployMine(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CScanner::InputEquipMine(inputdata_t &inputdata) -{ - CBaseEntity *child; - // iterate through all children - for ( child = FirstMoveChild(); child != NULL; child = child->NextMovePeer() ) - { - if( FClassnameIs( child, "combine_mine" ) ) - { - // Already have a mine! - return; - } - } - - CBaseEntity *pEnt; - - pEnt = CreateEntityByName( "combine_mine" ); - bool bPlacedMine = false; - - if( m_bIsClawScanner ) - { - Vector vecOrigin; - QAngle angles; - int attachment; - - attachment = LookupAttachment( "claw" ); - - if( attachment > -1 ) - { - GetAttachment( attachment, vecOrigin, angles ); - - pEnt->SetAbsOrigin( vecOrigin ); - pEnt->SetAbsAngles( angles ); - pEnt->SetOwnerEntity( this ); - pEnt->SetParent( this, attachment ); - - m_bIsOpen = true; - SetActivity( ACT_IDLE_ANGRY ); - bPlacedMine = true; - } - } - - - if( !bPlacedMine ) - { - Vector vecMineLocation = GetAbsOrigin(); - vecMineLocation.z -= 32.0; - - pEnt->SetAbsOrigin( vecMineLocation ); - pEnt->SetAbsAngles( GetAbsAngles() ); - pEnt->SetOwnerEntity( this ); - pEnt->SetParent( this ); - } - - pEnt->Spawn(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Tells the scanner to go photograph an entity. -// Input : String name or classname of the entity to inspect. -//----------------------------------------------------------------------------- -void CNPC_CScanner::InputInspectTargetPhoto(inputdata_t &inputdata) -{ - m_vLastPatrolDir = vec3_origin; - m_bPhotoTaken = false; - InspectTarget( inputdata, SCANNER_FLY_PHOTO ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Tells the scanner to go spotlight an entity. -// Input : String name or classname of the entity to inspect. -//----------------------------------------------------------------------------- -void CNPC_CScanner::InputInspectTargetSpotlight(inputdata_t &inputdata) -{ - InspectTarget( inputdata, SCANNER_FLY_SPOT ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Tells the scanner to go photo or spotlight an entity. -// Input : String name or classname of the entity to inspect. -//----------------------------------------------------------------------------- -void CNPC_CScanner::InspectTarget( inputdata_t &inputdata, ScannerFlyMode_t eFlyMode ) -{ - CBaseEntity *pEnt = gEntList.FindEntityGeneric( NULL, inputdata.value.String(), this, inputdata.pActivator ); - - if ( pEnt != NULL ) - { - // Set and begin to inspect our target - SetInspectTargetToEnt( pEnt, SCANNER_CIT_INSPECT_LENGTH ); - - m_nFlyMode = eFlyMode; - SetCondition( COND_CSCANNER_HAVE_INSPECT_TARGET ); - - // Stop us from any other navigation we were doing - GetNavigator()->ClearGoal(); - } - else - { - DevMsg( "InspectTarget: target %s not found!\n", inputdata.value.String() ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_CScanner::MovingToInspectTarget( void ) -{ - // If we're flying to a photograph target and the photo isn't yet taken, we're still moving to it - if ( m_nFlyMode == SCANNER_FLY_PHOTO && m_bPhotoTaken == false ) - return true; - - // If we're still on a path, then we're still moving - if ( HaveInspectTarget() && GetNavigator()->IsGoalActive() ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CScanner::GatherConditions( void ) -{ - BaseClass::GatherConditions(); - - // Clear out our old conditions - ClearCondition( COND_CSCANNER_INSPECT_DONE ); - ClearCondition( COND_CSCANNER_HAVE_INSPECT_TARGET ); - ClearCondition( COND_CSCANNER_SPOT_ON_TARGET ); - ClearCondition( COND_CSCANNER_CAN_PHOTOGRAPH ); - - // We don't do any of these checks if we have an enemy - if ( GetEnemy() ) - return; - - // -------------------------------------- - // COND_CSCANNER_INSPECT_DONE - // - // If my inspection over - // --------------------------------------------------------- - - // Refresh our timing if we're still moving to our inspection target - if ( MovingToInspectTarget() ) - { - m_fInspectEndTime = gpGlobals->curtime + SCANNER_CIT_INSPECT_LENGTH; - } - - // Update our follow times - if ( HaveInspectTarget() && gpGlobals->curtime > m_fInspectEndTime && m_nFlyMode != SCANNER_FLY_FOLLOW ) - { - SetCondition ( COND_CSCANNER_INSPECT_DONE ); - - m_fCheckCitizenTime = gpGlobals->curtime + SCANNER_CIT_INSPECT_DELAY; - m_fCheckHintTime = gpGlobals->curtime + SCANNER_HINT_INSPECT_DELAY; - ClearInspectTarget(); - } - - // ---------------------------------------------------------- - // If I heard a sound and I don't have an enemy, inspect it - // ---------------------------------------------------------- - if ( ( HasCondition( COND_HEAR_COMBAT ) || HasCondition( COND_HEAR_DANGER ) ) && m_nFlyMode != SCANNER_FLY_FOLLOW ) - { - CSound *pSound = GetBestSound(); - - if ( pSound ) - { - // Chase an owner if we can - if ( pSound->m_hOwner != NULL ) - { - // Don't inspect sounds of things we like - if ( IRelationType( pSound->m_hOwner ) != D_LI ) - { - // Only bother if we can see it - if ( FVisible( pSound->m_hOwner ) ) - { - SetInspectTargetToEnt( pSound->m_hOwner, SCANNER_SOUND_INSPECT_LENGTH ); - } - } - } - else - { - // Otherwise chase the specific sound - Vector vSoundPos = pSound->GetSoundOrigin(); - SetInspectTargetToPos( vSoundPos, SCANNER_SOUND_INSPECT_LENGTH ); - } - - m_nFlyMode = (random->RandomInt(0,2)==0) ? SCANNER_FLY_SPOT : SCANNER_FLY_PHOTO; - } - } - - // -------------------------------------- - // COND_CSCANNER_HAVE_INSPECT_TARGET - // - // Look for a nearby citizen or player to hassle. - // --------------------------------------------------------- - - // Check for citizens to inspect - if ( gpGlobals->curtime > m_fCheckCitizenTime && HaveInspectTarget() == false ) - { - CBaseEntity *pBestEntity = BestInspectTarget(); - - if ( pBestEntity != NULL ) - { - SetInspectTargetToEnt( pBestEntity, SCANNER_CIT_INSPECT_LENGTH ); - m_nFlyMode = (random->RandomInt(0,3)==0) ? SCANNER_FLY_SPOT : SCANNER_FLY_PHOTO; - SetCondition ( COND_CSCANNER_HAVE_INSPECT_TARGET ); - } - } - - // Check for hints to inspect - if ( gpGlobals->curtime > m_fCheckHintTime && HaveInspectTarget() == false ) - { - SetHintNode( CAI_HintManager::FindHint( this, HINT_WORLD_WINDOW, 0, SCANNER_CIT_INSPECT_FLY_DIST ) ); - - if ( GetHintNode() ) - { - m_fCheckHintTime = gpGlobals->curtime + SCANNER_HINT_INSPECT_DELAY; - - m_nFlyMode = (random->RandomInt(0,2)==0) ? SCANNER_FLY_SPOT : SCANNER_FLY_PHOTO; - - SetInspectTargetToHint( GetHintNode(), SCANNER_HINT_INSPECT_LENGTH ); - - SetCondition ( COND_CSCANNER_HAVE_INSPECT_TARGET ); - } - } - - // -------------------------------------- - // COND_CSCANNER_SPOT_ON_TARGET - // - // True when spotlight is on target ent - // -------------------------------------- - - if ( m_hSpotlightTarget != NULL && HaveInspectTarget() && m_hSpotlightTarget->GetSmoothedVelocity().Length() < 25 ) - { - // If I have a target entity, check my spotlight against the - // actual position of the entity - if (GetTarget()) - { - float fInspectDist = (m_vSpotlightTargetPos - m_vSpotlightCurrentPos).Length(); - if ( fInspectDist < 100 ) - { - SetCondition( COND_CSCANNER_SPOT_ON_TARGET ); - } - } - // Otherwise just check by beam direction - else - { - Vector vTargetDir = SpotlightTargetPos() - GetLocalOrigin(); - VectorNormalize(vTargetDir); - float dotpr = DotProduct(vTargetDir, m_vSpotlightDir); - if (dotpr > 0.95) - { - SetCondition( COND_CSCANNER_SPOT_ON_TARGET ); - } - } - } - - // -------------------------------------------- - // COND_CSCANNER_CAN_PHOTOGRAPH - // - // True when can photograph target ent - // -------------------------------------------- - - ClearCondition( COND_CSCANNER_CAN_PHOTOGRAPH ); - - if ( m_nFlyMode == SCANNER_FLY_PHOTO ) - { - // Make sure I have something to photograph and I'm ready to photograph and I'm not moving to fast - if ( gpGlobals->curtime > m_fNextPhotographTime && HaveInspectTarget() && GetCurrentVelocity().LengthSqr() < (64*64) ) - { - // Check that I'm in the right distance range - float fInspectDist = (InspectTargetPosition() - GetAbsOrigin()).Length2D(); - - // See if we're within range - if ( fInspectDist > SCANNER_PHOTO_NEAR_DIST && fInspectDist < SCANNER_PHOTO_FAR_DIST ) - { - // Make sure we're looking at the target - if ( UTIL_AngleDiff( GetAbsAngles().y, VecToYaw( InspectTargetPosition() - GetAbsOrigin() ) ) < 4.0f ) - { - trace_t tr; - AI_TraceLine ( GetAbsOrigin(), InspectTargetPosition(), MASK_BLOCKLOS, GetTarget(), COLLISION_GROUP_NONE, &tr); - - if ( tr.fraction == 1.0f ) - { - SetCondition( COND_CSCANNER_CAN_PHOTOGRAPH ); - } - } - } - } - } -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CNPC_CScanner::PrescheduleThink(void) -{ - BaseClass::PrescheduleThink(); - - // Go back to idling if we're done - if ( GetIdealActivity() == ACT_SCANNER_FLARE_START ) - { - if ( IsSequenceFinished() ) - { - SetIdealActivity( (Activity) ACT_IDLE ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Overridden because if the player is a criminal, we hate them. -// Input : pTarget - Entity with which to determine relationship. -// Output : Returns relationship value. -//----------------------------------------------------------------------------- -Disposition_t CNPC_CScanner::IRelationType(CBaseEntity *pTarget) -{ - // If it's the player and they are a criminal, we hates them - if ( pTarget->Classify() == CLASS_PLAYER ) - { - if ( GlobalEntity_GetState("gordon_precriminal") == GLOBAL_ON ) - return D_NU; - } - - return BaseClass::IRelationType( pTarget ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTask - -//----------------------------------------------------------------------------- -void CNPC_CScanner::RunTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_CSCANNER_PHOTOGRAPH: - { - if ( IsWaitFinished() ) - { - // If light was on turn it off - if ( m_pEyeFlash->GetBrightness() > 0 ) - { - m_pEyeFlash->SetBrightness( 0 ); - - // I'm done with this target - if ( gpGlobals->curtime > m_fInspectEndTime ) - { - ClearInspectTarget(); - TaskComplete(); - } - // Otherwise take another picture - else - { - SetWait( 5.0f, 10.0f ); - } - } - // If light was off, take another picture - else - { - TakePhoto(); - SetWait( 0.1f ); - } - } - break; - } - case TASK_CSCANNER_ATTACK_PRE_FLASH: - { - AttackPreFlash(); - - if ( IsWaitFinished() ) - { - TaskComplete(); - } - break; - } - case TASK_CSCANNER_ATTACK_FLASH: - { - if (IsWaitFinished()) - { - AttackFlashBlind(); - TaskComplete(); - } - break; - } - default: - { - BaseClass::RunTask(pTask); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Gets the appropriate next schedule based on current condition -// bits. -//----------------------------------------------------------------------------- -int CNPC_CScanner::SelectSchedule(void) -{ - // Turn our flash off in case we were interrupted while it was on. - if ( m_pEyeFlash ) - { - m_pEyeFlash->SetBrightness( 0 ); - } - - // ---------------------------------------------------- - // If I'm dead, go into a dive bomb - // ---------------------------------------------------- - if ( m_iHealth <= 0 ) - { - m_flSpeed = SCANNER_MAX_DIVE_BOMB_SPEED; - return SCHED_SCANNER_ATTACK_DIVEBOMB; - } - - // ------------------------------- - // If I'm in a script sequence - // ------------------------------- - if ( m_NPCState == NPC_STATE_SCRIPT ) - return(BaseClass::SelectSchedule()); - - // ------------------------------- - // Flinch - // ------------------------------- - if ( HasCondition(COND_LIGHT_DAMAGE) || HasCondition(COND_HEAVY_DAMAGE) ) - { - if ( IsHeldByPhyscannon( ) ) - return SCHED_SMALL_FLINCH; - - if ( m_NPCState == NPC_STATE_IDLE ) - return SCHED_SMALL_FLINCH; - - if ( m_NPCState == NPC_STATE_ALERT ) - { - if ( m_iHealth < ( 3 * sk_scanner_health.GetFloat() / 4 )) - return SCHED_TAKE_COVER_FROM_ORIGIN; - - if ( SelectWeightedSequence( ACT_SMALL_FLINCH ) != -1 ) - return SCHED_SMALL_FLINCH; - } - else - { - if ( random->RandomInt( 0, 10 ) < 4 ) - return SCHED_SMALL_FLINCH; - } - } - - // I'm being held by the physcannon... struggle! - if ( IsHeldByPhyscannon( ) ) - return SCHED_SCANNER_HELD_BY_PHYSCANNON; - - // ---------------------------------------------------------- - // If I have an enemy - // ---------------------------------------------------------- - if ( GetEnemy() != NULL && GetEnemy()->IsAlive() && m_bShouldInspect ) - { - // Always chase the enemy - SetInspectTargetToEnt( GetEnemy(), 9999 ); - - // Patrol if the enemy has vanished - if ( HasCondition( COND_LOST_ENEMY ) ) - return SCHED_SCANNER_PATROL; - - // Chase via route if we're directly blocked - if ( HasCondition( COND_SCANNER_FLY_BLOCKED ) ) - return SCHED_SCANNER_CHASE_ENEMY; - - // Attack if it's time - if ( gpGlobals->curtime < m_flNextAttack ) - return SCHED_CSCANNER_SPOTLIGHT_HOVER; - - // Melee attack if possible - if ( HasCondition( COND_CAN_MELEE_ATTACK1 ) ) - { - if ( random->RandomInt(0,1) ) - return SCHED_CSCANNER_ATTACK_FLASH; - - // TODO: a schedule where he makes an alarm sound? - return SCHED_SCANNER_CHASE_ENEMY; - } - - // If I'm far from the enemy, stay up high and approach in spotlight mode - float fAttack2DDist = ( GetEnemyLKP() - GetAbsOrigin() ).Length2D(); - - if ( fAttack2DDist > SCANNER_ATTACK_FAR_DIST ) - return SCHED_CSCANNER_SPOTLIGHT_HOVER; - - // Otherwise fly in low for attack - return SCHED_SCANNER_ATTACK_HOVER; - } - - // ---------------------------------------------------------- - // If I have something to inspect - // ---------------------------------------------------------- - if ( HaveInspectTarget() ) - { - // Pathfind to our goal - if ( HasCondition( COND_SCANNER_FLY_BLOCKED ) ) - return SCHED_CSCANNER_MOVE_TO_INSPECT; - - // If I was chasing, pick with photographing or spotlighting - if ( m_nFlyMode == SCANNER_FLY_CHASE ) - { - m_nFlyMode = (random->RandomInt(0,1)==0) ? SCANNER_FLY_SPOT : SCANNER_FLY_PHOTO; - } - - // Handle spotlight - if ( m_nFlyMode == SCANNER_FLY_SPOT ) - { - if (HasCondition( COND_CSCANNER_SPOT_ON_TARGET )) - { - if (GetTarget()) - { - RequestInspectSupport(); - - CAI_BaseNPC *pNPC = GetTarget()->MyNPCPointer(); - // If I'm leading the inspection, so verbal inspection - if (pNPC && pNPC->GetTarget() == this) - { - return SCHED_CSCANNER_SPOTLIGHT_INSPECT_CIT; - } - - return SCHED_CSCANNER_SPOTLIGHT_HOVER; - } - - return SCHED_CSCANNER_SPOTLIGHT_INSPECT_POS; - } - - return SCHED_CSCANNER_SPOTLIGHT_HOVER; - } - - // Handle photographing - if ( m_nFlyMode == SCANNER_FLY_PHOTO ) - { - if ( HasCondition( COND_CSCANNER_CAN_PHOTOGRAPH )) - return SCHED_CSCANNER_PHOTOGRAPH; - - return SCHED_CSCANNER_PHOTOGRAPH_HOVER; - } - - // Handle following after a target - if ( m_nFlyMode == SCANNER_FLY_FOLLOW ) - { - //TODO: Randomly make noise, photograph, etc - return SCHED_SCANNER_FOLLOW_HOVER; - } - - // Handle patrolling - if ( ( m_nFlyMode == SCANNER_FLY_PATROL ) || ( m_nFlyMode == SCANNER_FLY_FAST ) ) - return SCHED_SCANNER_PATROL; - } - - // Default to patrolling around - return SCHED_SCANNER_PATROL; -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CNPC_CScanner::SpotlightDestroy(void) -{ - if ( m_hSpotlight ) - { - UTIL_Remove(m_hSpotlight); - m_hSpotlight = NULL; - - UTIL_Remove(m_hSpotlightTarget); - m_hSpotlightTarget = NULL; - } -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CNPC_CScanner::SpotlightCreate(void) -{ - // Make sure we don't already have one - if ( m_hSpotlight != NULL ) - return; - - // Can we create a spotlight yet? - if ( gpGlobals->curtime < m_fNextSpotlightTime ) - return; - - // If I have an enemy, start spotlight on my enemy - if (GetEnemy() != NULL) - { - Vector vEnemyPos = GetEnemyLKP(); - Vector vTargetPos = vEnemyPos; - vTargetPos.z = GetFloorZ(vEnemyPos); - m_vSpotlightDir = vTargetPos - GetLocalOrigin(); - VectorNormalize(m_vSpotlightDir); - } - // If I have an target, start spotlight on my target - else if (GetTarget() != NULL) - { - Vector vTargetPos = GetTarget()->GetLocalOrigin(); - vTargetPos.z = GetFloorZ(GetTarget()->GetLocalOrigin()); - m_vSpotlightDir = vTargetPos - GetLocalOrigin(); - VectorNormalize(m_vSpotlightDir); - } - // Other wise just start looking down - else - { - m_vSpotlightDir = Vector(0,0,-1); - } - - trace_t tr; - AI_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + m_vSpotlightDir * 2024, MASK_OPAQUE, this, COLLISION_GROUP_NONE, &tr ); - - m_hSpotlightTarget = (CSpotlightEnd*)CreateEntityByName( "spotlight_end" ); - m_hSpotlightTarget->Spawn(); - m_hSpotlightTarget->SetLocalOrigin( tr.endpos ); - m_hSpotlightTarget->SetOwnerEntity( this ); - // YWB: Because the scanner only moves the target during think, make sure we interpolate over 0.1 sec instead of every tick!!! - m_hSpotlightTarget->SetSimulatedEveryTick( false ); - - // Using the same color as the beam... - m_hSpotlightTarget->SetRenderColor( 255, 255, 255 ); - m_hSpotlightTarget->m_Radius = m_flSpotlightMaxLength; - - m_hSpotlight = CBeam::BeamCreate( "sprites/glow_test02.vmt", SPOTLIGHT_WIDTH ); - // Set the temporary spawnflag on the beam so it doesn't save (we'll recreate it on restore) - m_hSpotlight->AddSpawnFlags( SF_BEAM_TEMPORARY ); - m_hSpotlight->SetColor( 255, 255, 255 ); - m_hSpotlight->SetHaloTexture( m_nHaloSprite ); - m_hSpotlight->SetHaloScale( 32 ); - m_hSpotlight->SetEndWidth( m_hSpotlight->GetWidth() ); - m_hSpotlight->SetBeamFlags( (FBEAM_SHADEOUT|FBEAM_NOTILE) ); - m_hSpotlight->SetBrightness( 32 ); - m_hSpotlight->SetNoise( 0 ); - m_hSpotlight->EntsInit( this, m_hSpotlightTarget ); - m_hSpotlight->SetHDRColorScale( 0.75f ); // Scale this back a bit on HDR maps - // attach to light - m_hSpotlight->SetStartAttachment( LookupAttachment( SCANNER_ATTACHMENT_LIGHT ) ); - - m_vSpotlightAngVelocity = vec3_origin; -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -Vector CNPC_CScanner::SpotlightTargetPos(void) -{ - // ---------------------------------------------- - // If I have an enemy - // ---------------------------------------------- - if (GetEnemy() != NULL) - { - // If I can see my enemy aim for him - if (HasCondition(COND_SEE_ENEMY)) - { - // If its client aim for his eyes - if (GetEnemy()->GetFlags() & FL_CLIENT) - { - m_vSpotlightTargetPos = GetEnemy()->EyePosition(); - } - // Otherwise same for his feet - else - { - m_vSpotlightTargetPos = GetEnemy()->GetLocalOrigin(); - m_vSpotlightTargetPos.z = GetFloorZ(GetEnemy()->GetLocalOrigin()); - } - } - // Otherwise aim for last known position if I can see LKP - else - { - Vector vLKP = GetEnemyLKP(); - m_vSpotlightTargetPos.x = vLKP.x; - m_vSpotlightTargetPos.y = vLKP.y; - m_vSpotlightTargetPos.z = GetFloorZ(vLKP); - } - } - // ---------------------------------------------- - // If I have an inspect target - // ---------------------------------------------- - else if (HaveInspectTarget()) - { - m_vSpotlightTargetPos = InspectTargetPosition(); - } - else - { - // This creates a nice patrol spotlight sweep - // in the direction that I'm travelling - m_vSpotlightTargetPos = GetCurrentVelocity(); - m_vSpotlightTargetPos.z = 0; - VectorNormalize( m_vSpotlightTargetPos ); - m_vSpotlightTargetPos *= 5; - - float noiseScale = 2.5; - const Vector &noiseMod = GetNoiseMod(); - m_vSpotlightTargetPos.x += noiseScale*sin(noiseMod.x * gpGlobals->curtime + noiseMod.x); - m_vSpotlightTargetPos.y += noiseScale*cos(noiseMod.y* gpGlobals->curtime + noiseMod.y); - m_vSpotlightTargetPos.z -= fabs(noiseScale*cos(noiseMod.z* gpGlobals->curtime + noiseMod.z) ); - m_vSpotlightTargetPos = GetLocalOrigin()+m_vSpotlightTargetPos * 2024; - } - - return m_vSpotlightTargetPos; -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -Vector CNPC_CScanner::SpotlightCurrentPos(void) -{ - Vector vTargetDir = SpotlightTargetPos() - GetLocalOrigin(); - VectorNormalize(vTargetDir); - - if (!m_hSpotlight) - { - DevMsg("Spotlight pos. called w/o spotlight!\n"); - return vec3_origin; - } - // ------------------------------------------------- - // Beam has momentum relative to it's ground speed - // so sclae the turn rate based on its distance - // from the beam source - // ------------------------------------------------- - float fBeamDist = (m_hSpotlightTarget->GetLocalOrigin() - GetLocalOrigin()).Length(); - - float fBeamTurnRate = atan(50/fBeamDist); - Vector vNewAngVelocity = fBeamTurnRate * (vTargetDir - m_vSpotlightDir); - - float myDecay = 0.4; - m_vSpotlightAngVelocity = (myDecay * m_vSpotlightAngVelocity + (1-myDecay) * vNewAngVelocity); - - // ------------------------------ - // Limit overall angular speed - // ----------------------------- - if (m_vSpotlightAngVelocity.Length() > 1) - { - - Vector velDir = m_vSpotlightAngVelocity; - VectorNormalize(velDir); - m_vSpotlightAngVelocity = velDir * 1; - } - - // ------------------------------ - // Calculate new beam direction - // ------------------------------ - m_vSpotlightDir = m_vSpotlightDir + m_vSpotlightAngVelocity; - m_vSpotlightDir = m_vSpotlightDir; - VectorNormalize(m_vSpotlightDir); - - - // --------------------------------------------- - // Get beam end point. Only collide with - // solid objects, not npcs - // --------------------------------------------- - trace_t tr; - Vector vTraceEnd = GetAbsOrigin() + (m_vSpotlightDir * 2 * m_flSpotlightMaxLength); - AI_TraceLine ( GetAbsOrigin(), vTraceEnd, MASK_OPAQUE, this, COLLISION_GROUP_NONE, &tr); - - return (tr.endpos); -} - - -//------------------------------------------------------------------------------ -// Purpose: Update the direction and position of my spotlight -//------------------------------------------------------------------------------ -void CNPC_CScanner::SpotlightUpdate(void) -{ - //FIXME: JDW - E3 Hack - if ( m_bNoLight ) - { - if ( m_hSpotlight ) - { - SpotlightDestroy(); - } - - return; - } - - if ((m_nFlyMode != SCANNER_FLY_SPOT) && - (m_nFlyMode != SCANNER_FLY_PATROL) && - (m_nFlyMode != SCANNER_FLY_FAST)) - { - if ( m_hSpotlight ) - { - SpotlightDestroy(); - } - return; - } - - // If I don't have a spotlight attempt to create one - - if ( m_hSpotlight == NULL ) - { - SpotlightCreate(); - - if ( m_hSpotlight== NULL ) - return; - } - - // Calculate the new homing target position - m_vSpotlightCurrentPos = SpotlightCurrentPos(); - - // ------------------------------------------------------------------ - // If I'm not facing the spotlight turn it off - // ------------------------------------------------------------------ - Vector vSpotDir = m_vSpotlightCurrentPos - GetAbsOrigin(); - VectorNormalize(vSpotDir); - - Vector vForward; - AngleVectors( GetAbsAngles(), &vForward ); - - float dotpr = DotProduct( vForward, vSpotDir ); - - if ( dotpr < 0.0 ) - { - // Leave spotlight off for a while - m_fNextSpotlightTime = gpGlobals->curtime + 3.0f; - - SpotlightDestroy(); - return; - } - - // -------------------------------------------------------------- - // Update spotlight target velocity - // -------------------------------------------------------------- - Vector vTargetDir = (m_vSpotlightCurrentPos - m_hSpotlightTarget->GetLocalOrigin()); - float vTargetDist = vTargetDir.Length(); - - Vector vecNewVelocity = vTargetDir; - VectorNormalize(vecNewVelocity); - vecNewVelocity *= (10 * vTargetDist); - - // If a large move is requested, just jump to final spot as we - // probably hit a discontinuity - if (vecNewVelocity.Length() > 200) - { - VectorNormalize(vecNewVelocity); - vecNewVelocity *= 200; - m_hSpotlightTarget->SetLocalOrigin( m_vSpotlightCurrentPos ); - } - m_hSpotlightTarget->SetAbsVelocity( vecNewVelocity ); - - m_hSpotlightTarget->m_vSpotlightOrg = GetAbsOrigin(); - - // Avoid sudden change in where beam fades out when cross disconinuities - m_hSpotlightTarget->m_vSpotlightDir = m_hSpotlightTarget->GetLocalOrigin() - m_hSpotlightTarget->m_vSpotlightOrg; - float flBeamLength = VectorNormalize( m_hSpotlightTarget->m_vSpotlightDir ); - m_flSpotlightCurLength = (0.80*m_flSpotlightCurLength) + (0.2*flBeamLength); - - // Fade out spotlight end if past max length. - if (m_flSpotlightCurLength > 2*m_flSpotlightMaxLength) - { - m_hSpotlightTarget->SetRenderColorA( 0 ); - m_hSpotlight->SetFadeLength(m_flSpotlightMaxLength); - } - else if (m_flSpotlightCurLength > m_flSpotlightMaxLength) - { - m_hSpotlightTarget->SetRenderColorA( (byte)((1-((m_flSpotlightCurLength-m_flSpotlightMaxLength)/m_flSpotlightMaxLength))) ); - m_hSpotlight->SetFadeLength(m_flSpotlightMaxLength); - } - else - { - m_hSpotlightTarget->SetRenderColorA( 1 ); - m_hSpotlight->SetFadeLength(m_flSpotlightCurLength); - } - - // Adjust end width to keep beam width constant - float flNewWidth = SPOTLIGHT_WIDTH * ( flBeamLength/m_flSpotlightMaxLength); - - m_hSpotlight->SetWidth(flNewWidth); - m_hSpotlight->SetEndWidth(flNewWidth); - - m_hSpotlightTarget->m_flLightScale = 0.0; -} - -//----------------------------------------------------------------------------- -// Purpose: Called just before we are deleted. -//----------------------------------------------------------------------------- -void CNPC_CScanner::UpdateOnRemove( void ) -{ - SpotlightDestroy(); - BaseClass::UpdateOnRemove(); -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CNPC_CScanner::TakePhoto(void) -{ - ScannerEmitSound( "TakePhoto" ); - - m_pEyeFlash->SetScale( 1.4 ); - m_pEyeFlash->SetBrightness( 255 ); - m_pEyeFlash->SetColor(255,255,255); - - Vector vRawPos = InspectTargetPosition(); - Vector vLightPos = vRawPos; - - // If taking picture of entity, aim at feet - if ( GetTarget() ) - { - if ( GetTarget()->IsPlayer() ) - { - m_OnPhotographPlayer.FireOutput( GetTarget(), this ); - BlindFlashTarget( GetTarget() ); - } - - if ( GetTarget()->MyNPCPointer() != NULL ) - { - m_OnPhotographNPC.FireOutput( GetTarget(), this ); - GetTarget()->MyNPCPointer()->DispatchInteraction( g_interactionScannerInspectBegin, NULL, this ); - } - } - - SetIdealActivity( (Activity) ACT_SCANNER_FLARE_START ); - - m_bPhotoTaken = true; -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CNPC_CScanner::AttackPreFlash(void) -{ - ScannerEmitSound( "TakePhoto" ); - - // If off turn on, if on turn off - if (m_pEyeFlash->GetBrightness() == 0) - { - m_pEyeFlash->SetScale( 0.5 ); - m_pEyeFlash->SetBrightness( 255 ); - m_pEyeFlash->SetColor(255,0,0); - } - else - { - m_pEyeFlash->SetBrightness( 0 ); - } -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CNPC_CScanner::AttackFlash(void) -{ - ScannerEmitSound( "AttackFlash" ); - m_pEyeFlash->SetScale( 1.8 ); - m_pEyeFlash->SetBrightness( 255 ); - m_pEyeFlash->SetColor(255,255,255); - - if (GetEnemy() != NULL) - { - Vector pos = GetEnemyLKP(); - CBroadcastRecipientFilter filter; - te->DynamicLight( filter, 0.0, &pos, 200, 200, 255, 0, 300, 0.2, 50 ); - - if (GetEnemy()->IsPlayer()) - { - m_OnPhotographPlayer.FireOutput(GetTarget(), this); - } - else if( GetEnemy()->MyNPCPointer() ) - { - m_OnPhotographNPC.FireOutput(GetTarget(), this); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTarget - -//----------------------------------------------------------------------------- -void CNPC_CScanner::BlindFlashTarget( CBaseEntity *pTarget ) -{ - // Tell all the striders this person is here! - CAI_BaseNPC ** ppAIs = g_AI_Manager.AccessAIs(); - int nAIs = g_AI_Manager.NumAIs(); - - if( IsStriderScout() ) - { - for ( int i = 0; i < nAIs; i++ ) - { - if( FClassnameIs( ppAIs[ i ], "npc_strider" ) ) - { - ppAIs[ i ]->UpdateEnemyMemory( pTarget, pTarget->GetAbsOrigin(), this ); - } - } - } - - // Only bother with player - if ( pTarget->IsPlayer() == false ) - return; - - // Scale the flash value by how closely the player is looking at me - Vector vFlashDir = GetAbsOrigin() - pTarget->EyePosition(); - VectorNormalize(vFlashDir); - - Vector vFacing; - AngleVectors( pTarget->EyeAngles(), &vFacing ); - - float dotPr = DotProduct( vFlashDir, vFacing ); - - // Not if behind us - if ( dotPr > 0.5f ) - { - // Make sure nothing in the way - trace_t tr; - AI_TraceLine ( GetAbsOrigin(), pTarget->EyePosition(), MASK_OPAQUE, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.startsolid == false && tr.fraction == 1.0) - { - color32 white = { 255, 255, 255, (byte)(SCANNER_FLASH_MAX_VALUE * dotPr) }; - - if ( ( g_pMaterialSystemHardwareConfig != NULL ) && ( g_pMaterialSystemHardwareConfig->GetHDRType() != HDR_TYPE_NONE ) ) - { - white.a = ( byte )( ( float )white.a * 0.9f ); - } - - float flFadeTime = ( IsX360() ) ? 0.5f : 3.0f; - UTIL_ScreenFade( pTarget, white, flFadeTime, 0.5, FFADE_IN ); - } - } -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CNPC_CScanner::AttackFlashBlind(void) -{ - if( GetEnemy() ) - { - BlindFlashTarget( GetEnemy() ); - } - - m_pEyeFlash->SetBrightness( 0 ); - - float fAttackDelay = random->RandomFloat(SCANNER_ATTACK_MIN_DELAY,SCANNER_ATTACK_MAX_DELAY); - - if( IsStriderScout() ) - { - // Make strider scouts more snappy. - fAttackDelay *= 0.5; - } - - m_flNextAttack = gpGlobals->curtime + fAttackDelay; - m_fNextSpotlightTime = gpGlobals->curtime + 1.0f; -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CNPC_CScanner::AttackDivebomb( void ) -{ - if (m_hSpotlight) - { - SpotlightDestroy(); - } - - BaseClass::AttackDivebomb(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pTask - -//----------------------------------------------------------------------------- -void CNPC_CScanner::StartTask( const Task_t *pTask ) -{ - switch (pTask->iTask) - { - case TASK_CSCANNER_GET_PATH_TO_INSPECT_TARGET: - { - // Must have somewhere to fly to - if ( HaveInspectTarget() == false ) - { - TaskFail( "No inspection target to fly to!\n" ); - return; - } - - if ( GetTarget() ) - { - //FIXME: Tweak - //Vector idealPos = IdealGoalForMovement( InspectTargetPosition(), GetAbsOrigin(), 128.0f, 128.0f ); - - AI_NavGoal_t goal( GOALTYPE_TARGETENT, vec3_origin ); - - if ( GetNavigator()->SetGoal( goal ) ) - { - TaskComplete(); - return; - } - } - else - { - AI_NavGoal_t goal( GOALTYPE_LOCATION, InspectTargetPosition() ); - - if ( GetNavigator()->SetGoal( goal ) ) - { - TaskComplete(); - return; - } - } - - // Don't try and inspect this target again for a few seconds - CNPC_Citizen *pCitizen = dynamic_cast( GetTarget() ); - if ( pCitizen ) - { - pCitizen->SetNextScannerInspectTime( gpGlobals->curtime + 5.0 ); - } - - TaskFail("No route to inspection target!\n"); - } - break; - - case TASK_CSCANNER_SPOT_INSPECT_ON: - { - if (GetTarget() == NULL) - { - TaskFail(FAIL_NO_TARGET); - } - else - { - CAI_BaseNPC* pNPC = GetTarget()->MyNPCPointer(); - if (!pNPC) - { - TaskFail(FAIL_NO_TARGET); - } - else - { - pNPC->DispatchInteraction(g_interactionScannerInspectBegin,NULL,this); - - // Now we need some time to inspect - m_fInspectEndTime = gpGlobals->curtime + SCANNER_CIT_INSPECT_LENGTH; - TaskComplete(); - } - } - break; - } - case TASK_CSCANNER_SPOT_INSPECT_WAIT: - { - if (GetTarget() == NULL) - { - TaskFail(FAIL_NO_TARGET); - } - else - { - CAI_BaseNPC* pNPC = GetTarget()->MyNPCPointer(); - if (!pNPC) - { - SetTarget( NULL ); - TaskFail(FAIL_NO_TARGET); - } - else - { - //<>//<> armband too! - pNPC->DispatchInteraction(g_interactionScannerInspectHandsUp,NULL,this); - } - TaskComplete(); - } - break; - } - case TASK_CSCANNER_SPOT_INSPECT_OFF: - { - if (GetTarget() == NULL) - { - TaskFail(FAIL_NO_TARGET); - } - else - { - CAI_BaseNPC* pNPC = GetTarget()->MyNPCPointer(); - if (!pNPC) - { - TaskFail(FAIL_NO_TARGET); - } - else - { - pNPC->DispatchInteraction(g_interactionScannerInspectDone,NULL,this); - - // Clear target entity and don't inspect again for a while - SetTarget( NULL ); - m_fCheckCitizenTime = gpGlobals->curtime + SCANNER_CIT_INSPECT_DELAY; - TaskComplete(); - } - } - break; - } - case TASK_CSCANNER_CLEAR_INSPECT_TARGET: - { - ClearInspectTarget(); - - TaskComplete(); - break; - } - - case TASK_CSCANNER_SET_FLY_SPOT: - { - m_nFlyMode = SCANNER_FLY_SPOT; - TaskComplete(); - break; - } - - case TASK_CSCANNER_SET_FLY_PHOTO: - { - m_nFlyMode = SCANNER_FLY_PHOTO; - m_bPhotoTaken = false; - - // Leave spotlight off for a while - m_fNextSpotlightTime = gpGlobals->curtime + 2.0; - - TaskComplete(); - break; - } - - case TASK_CSCANNER_PHOTOGRAPH: - { - TakePhoto(); - SetWait( 0.1 ); - break; - } - - case TASK_CSCANNER_ATTACK_PRE_FLASH: - { - if( IsStriderScout() ) - { - Vector vecScare = GetEnemy()->EarPosition(); - Vector vecDir = WorldSpaceCenter() - vecScare; - VectorNormalize( vecDir ); - vecScare += vecDir * 64.0f; - - CSoundEnt::InsertSound( SOUND_DANGER, vecScare, 256, 1.0, this ); - } - - if (m_pEyeFlash) - { - AttackPreFlash(); - // Flash red for a while - SetWait( 1.0f ); - } - else - { - TaskFail("No Flash"); - } - break; - } - - case TASK_CSCANNER_ATTACK_FLASH: - { - AttackFlash(); - // Blinding occurs slightly later - SetWait( 0.05 ); - break; - } - - // Override to go to inspect target position whether or not is an entity - case TASK_GET_PATH_TO_TARGET: - { - if (!HaveInspectTarget()) - { - TaskFail(FAIL_NO_TARGET); - } - else if (GetHintNode()) - { - Vector vNodePos; - GetHintNode()->GetPosition(this,&vNodePos); - - GetNavigator()->SetGoal( vNodePos ); - } - else - { - AI_NavGoal_t goal( (const Vector &)InspectTargetPosition() ); - goal.pTarget = GetTarget(); - GetNavigator()->SetGoal( goal ); - } - break; - } - default: - BaseClass::StartTask(pTask); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const char *CNPC_CScanner::GetScannerSoundPrefix( void ) -{ - if( m_bIsClawScanner ) - return "NPC_SScanner"; - - return "NPC_CScanner"; -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -float CNPC_CScanner::MinGroundDist( void ) -{ - if ( m_nFlyMode == SCANNER_FLY_SPOT && !GetHintNode() ) - { - return SCANNER_SPOTLIGHT_FLY_HEIGHT; - } - - return SCANNER_NOSPOTLIGHT_FLY_HEIGHT; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CScanner::AdjustScannerVelocity( void ) -{ - if ( m_bIsClawScanner ) - { - m_vCurrentVelocity *= ( 1 + sin( ( gpGlobals->curtime + m_flFlyNoiseBase ) * 2.5f ) * .1 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flInterval - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_CScanner::OverrideMove( float flInterval ) -{ - // ---------------------------------------------- - // If dive bombing - // ---------------------------------------------- - if (m_nFlyMode == SCANNER_FLY_DIVE) - { - MoveToDivebomb( flInterval ); - } - else - { - Vector vMoveTargetPos(0,0,0); - CBaseEntity *pMoveTarget = NULL; - - if ( !GetNavigator()->IsGoalActive() || ( GetNavigator()->GetCurWaypointFlags() | bits_WP_TO_PATHCORNER ) ) - { - // Select move target - if ( GetTarget() != NULL ) - { - pMoveTarget = GetTarget(); - } - else if ( GetEnemy() != NULL ) - { - pMoveTarget = GetEnemy(); - } - - // Select move target position - if ( HaveInspectTarget() ) - { - vMoveTargetPos = InspectTargetPosition(); - } - else if ( GetEnemy() != NULL ) - { - vMoveTargetPos = GetEnemy()->GetAbsOrigin(); - } - } - else - { - vMoveTargetPos = GetNavigator()->GetCurWaypointPos(); - } - - ClearCondition( COND_SCANNER_FLY_CLEAR ); - ClearCondition( COND_SCANNER_FLY_BLOCKED ); - - // See if we can fly there directly - if ( pMoveTarget || HaveInspectTarget() ) - { - trace_t tr; - AI_TraceHull( GetAbsOrigin(), vMoveTargetPos, GetHullMins(), GetHullMaxs(), MASK_NPCSOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - - float fTargetDist = (1.0f-tr.fraction)*(GetAbsOrigin() - vMoveTargetPos).Length(); - - if ( ( tr.m_pEnt == pMoveTarget ) || ( fTargetDist < 50 ) ) - { - if ( g_debug_cscanner.GetBool() ) - { - NDebugOverlay::Line(GetLocalOrigin(), vMoveTargetPos, 0,255,0, true, 0); - NDebugOverlay::Cross3D(tr.endpos,Vector(-5,-5,-5),Vector(5,5,5),0,255,0,true,0.1); - } - - SetCondition( COND_SCANNER_FLY_CLEAR ); - } - else - { - //HANDY DEBUG TOOL - if ( g_debug_cscanner.GetBool() ) - { - NDebugOverlay::Line(GetLocalOrigin(), vMoveTargetPos, 255,0,0, true, 0); - NDebugOverlay::Cross3D(tr.endpos,Vector(-5,-5,-5),Vector(5,5,5),255,0,0,true,0.1); - } - - SetCondition( COND_SCANNER_FLY_BLOCKED ); - } - } - - // If I have a route, keep it updated and move toward target - if ( GetNavigator()->IsGoalActive() ) - { - if ( OverridePathMove( pMoveTarget, flInterval ) ) - { - BlendPhyscannonLaunchSpeed(); - return true; - } - } - else if (m_nFlyMode == SCANNER_FLY_SPOT) - { - MoveToSpotlight( flInterval ); - } - // If photographing - else if ( m_nFlyMode == SCANNER_FLY_PHOTO ) - { - MoveToPhotograph( flInterval ); - } - else if ( m_nFlyMode == SCANNER_FLY_FOLLOW ) - { - MoveToSpotlight( flInterval ); - } - // ---------------------------------------------- - // If attacking - // ---------------------------------------------- - else if (m_nFlyMode == SCANNER_FLY_ATTACK) - { - if ( m_hSpotlight ) - { - SpotlightDestroy(); - } - - MoveToAttack( flInterval ); - } - // ----------------------------------------------------------------- - // If I don't have a route, just decelerate - // ----------------------------------------------------------------- - else if (!GetNavigator()->IsGoalActive()) - { - float myDecay = 9.5; - Decelerate( flInterval, myDecay); - } - } - - MoveExecute_Alive( flInterval ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Accelerates toward a given position. -// Input : flInterval - Time interval over which to move. -// vecMoveTarget - Position to move toward. -//----------------------------------------------------------------------------- -void CNPC_CScanner::MoveToTarget( float flInterval, const Vector &vecMoveTarget ) -{ - // Don't move if stalling - if ( m_flEngineStallTime > gpGlobals->curtime ) - return; - - // Look at our inspection target if we have one - if ( GetEnemy() != NULL ) - { - // Otherwise at our enemy - TurnHeadToTarget( flInterval, GetEnemy()->EyePosition() ); - } - else if ( HaveInspectTarget() ) - { - TurnHeadToTarget( flInterval, InspectTargetPosition() ); - } - else - { - // Otherwise face our motion direction - TurnHeadToTarget( flInterval, vecMoveTarget ); - } - - // ------------------------------------- - // Move towards our target - // ------------------------------------- - float myAccel; - float myZAccel = 400.0f; - float myDecay = 0.15f; - - Vector vecCurrentDir; - - // Get the relationship between my current velocity and the way I want to be going. - vecCurrentDir = GetCurrentVelocity(); - VectorNormalize( vecCurrentDir ); - - Vector targetDir = vecMoveTarget - GetAbsOrigin(); - float flDist = VectorNormalize(targetDir); - - float flDot; - flDot = DotProduct( targetDir, vecCurrentDir ); - - if( flDot > 0.25 ) - { - // If my target is in front of me, my flight model is a bit more accurate. - myAccel = 250; - } - else - { - // Have a harder time correcting my course if I'm currently flying away from my target. - myAccel = 128; - } - - if ( myAccel > flDist / flInterval ) - { - myAccel = flDist / flInterval; - } - - if ( myZAccel > flDist / flInterval ) - { - myZAccel = flDist / flInterval; - } - - MoveInDirection( flInterval, targetDir, myAccel, myZAccel, myDecay ); - - // calc relative banking targets - Vector forward, right, up; - GetVectors( &forward, &right, &up ); - - m_vCurrentBanking.x = targetDir.x; - m_vCurrentBanking.z = 120.0f * DotProduct( right, targetDir ); - m_vCurrentBanking.y = 0; - - float speedPerc = SimpleSplineRemapVal( GetCurrentVelocity().Length(), 0.0f, GetMaxSpeed(), 0.0f, 1.0f ); - - speedPerc = clamp( speedPerc, 0.0f, 1.0f ); - - m_vCurrentBanking *= speedPerc; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flInterval - -//----------------------------------------------------------------------------- -void CNPC_CScanner::MoveToSpotlight( float flInterval ) -{ - if ( flInterval <= 0 ) - return; - - Vector vTargetPos; - - if ( HaveInspectTarget() ) - { - vTargetPos = InspectTargetPosition(); - } - else if ( GetEnemy() != NULL ) - { - vTargetPos = GetEnemyLKP(); - } - else - { - return; - } - - //float flDesiredDist = SCANNER_SPOTLIGHT_NEAR_DIST + ( ( SCANNER_SPOTLIGHT_FAR_DIST - SCANNER_SPOTLIGHT_NEAR_DIST ) / 2 ); - - float flIdealHeightDiff = SCANNER_SPOTLIGHT_NEAR_DIST; - if( IsEnemyPlayerInSuit() ) - { - flIdealHeightDiff *= 0.5; - } - - Vector idealPos = IdealGoalForMovement( vTargetPos, GetAbsOrigin(), GetGoalDistance(), flIdealHeightDiff ); - - MoveToTarget( flInterval, idealPos ); - - //TODO: Re-implement? - - /* - // ------------------------------------------------ - // Also keep my distance from other squad members - // unless I'm inspecting - // ------------------------------------------------ - if (m_pSquad && - gpGlobals->curtime > m_fInspectEndTime) - { - CBaseEntity* pNearest = m_pSquad->NearestSquadMember(this); - if (pNearest) - { - Vector vNearestDir = (pNearest->GetLocalOrigin() - GetLocalOrigin()); - if (vNearestDir.Length() < SCANNER_SQUAD_FLY_DIST) - { - vNearestDir = pNearest->GetLocalOrigin() - GetLocalOrigin(); - VectorNormalize(vNearestDir); - vFlyDirection -= 0.5*vNearestDir; - } - } - } - - // --------------------------------------------------------- - // Add evasion if I have taken damage recently - // --------------------------------------------------------- - if ((m_flLastDamageTime + SCANNER_EVADE_TIME) > gpGlobals->curtime) - { - vFlyDirection = vFlyDirection + VelocityToEvade(GetEnemyCombatCharacterPointer()); - } - */ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CNPC_CScanner::GetGoalDistance( void ) -{ - if ( m_flGoalOverrideDistance != 0.0f ) - return m_flGoalOverrideDistance; - - switch ( m_nFlyMode ) - { - case SCANNER_FLY_PHOTO: - return ( SCANNER_PHOTO_NEAR_DIST + ( ( SCANNER_PHOTO_FAR_DIST - SCANNER_PHOTO_NEAR_DIST ) / 2 ) ); - break; - - case SCANNER_FLY_SPOT: - { - float goalDist = ( SCANNER_SPOTLIGHT_NEAR_DIST + ( ( SCANNER_SPOTLIGHT_FAR_DIST - SCANNER_SPOTLIGHT_NEAR_DIST ) / 2 ) ); - if( IsEnemyPlayerInSuit() ) - { - goalDist *= 0.5; - } - return goalDist; - } - break; - - case SCANNER_FLY_FOLLOW: - return ( SCANNER_FOLLOW_DIST ); - break; - - default: - break; - } - - return BaseClass::GetGoalDistance(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CScanner::MoveToPhotograph(float flInterval) -{ - if ( HaveInspectTarget() == false ) - return; - - //float flDesiredDist = SCANNER_PHOTO_NEAR_DIST + ( ( SCANNER_PHOTO_FAR_DIST - SCANNER_PHOTO_NEAR_DIST ) / 2 ); - - Vector idealPos = IdealGoalForMovement( InspectTargetPosition(), GetAbsOrigin(), GetGoalDistance(), 32.0f ); - - MoveToTarget( flInterval, idealPos ); - - //FIXME: Re-implement? - - /* - // ------------------------------------------------ - // Also keep my distance from other squad members - // unless I'm inspecting - // ------------------------------------------------ - if (m_pSquad && - gpGlobals->curtime > m_fInspectEndTime) - { - CBaseEntity* pNearest = m_pSquad->NearestSquadMember(this); - if (pNearest) - { - Vector vNearestDir = (pNearest->GetLocalOrigin() - GetLocalOrigin()); - if (vNearestDir.Length() < SCANNER_SQUAD_FLY_DIST) - { - vNearestDir = pNearest->GetLocalOrigin() - GetLocalOrigin(); - VectorNormalize(vNearestDir); - vFlyDirection -= 0.5*vNearestDir; - } - } - } - */ -} - - -//----------------------------------------------------------------------------- -// Purpose: This is a generic function (to be implemented by sub-classes) to -// handle specific interactions between different types of characters -// (For example the barnacle grabbing an NPC) -// Input : Constant for the type of interaction -// Output : true - if sub-class has a response for the interaction -// false - if sub-class has no response -//----------------------------------------------------------------------------- -bool CNPC_CScanner::HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* pSourceEnt) -{ - // TODO:: - doing this by just an interrupt contition would be a lot better! - if (interactionType == g_interactionScannerSupportEntity) - { - // Only accept help request if I'm not already busy - if (GetEnemy() == NULL && !HaveInspectTarget()) - { - // Only accept if target is a reasonable distance away - CBaseEntity* pTarget = (CBaseEntity*)data; - float fTargetDist = (pTarget->GetLocalOrigin() - GetLocalOrigin()).Length(); - - if (fTargetDist < SCANNER_SQUAD_HELP_DIST) - { - float fInspectTime = (((CNPC_CScanner*)pSourceEnt)->m_fInspectEndTime - gpGlobals->curtime); - SetInspectTargetToEnt(pTarget,fInspectTime); - - if (random->RandomInt(0,2)==0) - { - SetSchedule(SCHED_CSCANNER_PHOTOGRAPH_HOVER); - } - else - { - SetSchedule(SCHED_CSCANNER_SPOTLIGHT_HOVER); - } - return true; - } - } - } - else if (interactionType == g_interactionScannerSupportPosition) - { - // Only accept help request if I'm not already busy - if (GetEnemy() == NULL && !HaveInspectTarget()) - { - // Only accept if target is a reasonable distance away - Vector vInspectPos; - vInspectPos.x = ((Vector *)data)->x; - vInspectPos.y = ((Vector *)data)->y; - vInspectPos.z = ((Vector *)data)->z; - - float fTargetDist = (vInspectPos - GetLocalOrigin()).Length(); - - if (fTargetDist < SCANNER_SQUAD_HELP_DIST) - { - float fInspectTime = (((CNPC_CScanner*)pSourceEnt)->m_fInspectEndTime - gpGlobals->curtime); - SetInspectTargetToPos(vInspectPos,fInspectTime); - - if (random->RandomInt(0,2)==0) - { - SetSchedule(SCHED_CSCANNER_PHOTOGRAPH_HOVER); - } - else - { - SetSchedule(SCHED_CSCANNER_SPOTLIGHT_HOVER); - } - return true; - } - } - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_CScanner::InputDisableSpotlight( inputdata_t &inputdata ) -{ - m_bNoLight = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CNPC_CScanner::GetHeadTurnRate( void ) -{ - if ( GetEnemy() ) - return 800.0f; - - if ( HaveInspectTarget() ) - return 500.0f; - - return BaseClass::GetHeadTurnRate(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_CScanner::InputSetFollowTarget( inputdata_t &inputdata ) -{ - InspectTarget( inputdata, SCANNER_FLY_FOLLOW ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CNPC_CScanner::InputClearFollowTarget( inputdata_t &inputdata ) -{ - SetInspectTargetToEnt( NULL, 0 ); - - m_nFlyMode = SCANNER_FLY_PATROL; -} - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC( npc_cscanner, CNPC_CScanner ) - DECLARE_TASK(TASK_CSCANNER_SET_FLY_PHOTO) - DECLARE_TASK(TASK_CSCANNER_SET_FLY_SPOT) - DECLARE_TASK(TASK_CSCANNER_PHOTOGRAPH) - DECLARE_TASK(TASK_CSCANNER_ATTACK_PRE_FLASH) - DECLARE_TASK(TASK_CSCANNER_ATTACK_FLASH) - DECLARE_TASK(TASK_CSCANNER_SPOT_INSPECT_ON) - DECLARE_TASK(TASK_CSCANNER_SPOT_INSPECT_WAIT) - DECLARE_TASK(TASK_CSCANNER_SPOT_INSPECT_OFF) - DECLARE_TASK(TASK_CSCANNER_CLEAR_INSPECT_TARGET) - DECLARE_TASK(TASK_CSCANNER_GET_PATH_TO_INSPECT_TARGET) - - DECLARE_CONDITION(COND_CSCANNER_HAVE_INSPECT_TARGET) - DECLARE_CONDITION(COND_CSCANNER_INSPECT_DONE) - DECLARE_CONDITION(COND_CSCANNER_CAN_PHOTOGRAPH) - DECLARE_CONDITION(COND_CSCANNER_SPOT_ON_TARGET) - - DECLARE_ACTIVITY(ACT_SCANNER_SMALL_FLINCH_ALERT) - DECLARE_ACTIVITY(ACT_SCANNER_SMALL_FLINCH_COMBAT) - DECLARE_ACTIVITY(ACT_SCANNER_INSPECT) - DECLARE_ACTIVITY(ACT_SCANNER_WALK_ALERT) - DECLARE_ACTIVITY(ACT_SCANNER_WALK_COMBAT) - DECLARE_ACTIVITY(ACT_SCANNER_FLARE) - DECLARE_ACTIVITY(ACT_SCANNER_RETRACT) - DECLARE_ACTIVITY(ACT_SCANNER_FLARE_PRONGS) - DECLARE_ACTIVITY(ACT_SCANNER_RETRACT_PRONGS) - DECLARE_ACTIVITY(ACT_SCANNER_FLARE_START) - - DECLARE_ANIMEVENT( AE_SCANNER_CLOSED ) - - DECLARE_INTERACTION(g_interactionScannerInspect) - DECLARE_INTERACTION(g_interactionScannerInspectBegin) - DECLARE_INTERACTION(g_interactionScannerInspectDone) - DECLARE_INTERACTION(g_interactionScannerInspectHandsUp) - DECLARE_INTERACTION(g_interactionScannerInspectShowArmband) - DECLARE_INTERACTION(g_interactionScannerSupportEntity) - DECLARE_INTERACTION(g_interactionScannerSupportPosition) - - //========================================================= - // > SCHED_CSCANNER_PATROL - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CSCANNER_PATROL, - - " Tasks" - " TASK_CSCANNER_CLEAR_INSPECT_TARGET 0" - " TASK_SCANNER_SET_FLY_PATROL 0" - " TASK_SET_TOLERANCE_DISTANCE 32" - " TASK_SET_ROUTE_SEARCH_TIME 5" // Spend 5 seconds trying to build a path if stuck - " TASK_GET_PATH_TO_RANDOM_NODE 2000" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_GIVE_WAY" - " COND_NEW_ENEMY" - " COND_SEE_ENEMY" - " COND_SEE_FEAR" - " COND_HEAR_COMBAT" - " COND_HEAR_DANGER" - " COND_HEAR_PLAYER" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_PROVOKED" - " COND_CSCANNER_HAVE_INSPECT_TARGET" - " COND_SCANNER_GRABBED_BY_PHYSCANNON" - ) - - //========================================================= - // > SCHED_CSCANNER_SPOTLIGHT_HOVER - // - // Hover above target entity, trying to get spotlight - // on my target - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CSCANNER_SPOTLIGHT_HOVER, - - " Tasks" - " TASK_CSCANNER_SET_FLY_SPOT 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_WALK " - " TASK_WAIT 1" - "" - " Interrupts" - " COND_CSCANNER_SPOT_ON_TARGET" - " COND_CSCANNER_INSPECT_DONE" - " COND_SCANNER_FLY_BLOCKED" - " COND_NEW_ENEMY" - " COND_SCANNER_GRABBED_BY_PHYSCANNON" - ) - - //========================================================= - // > SCHED_CSCANNER_SPOTLIGHT_INSPECT_POS - // - // Inspect a position once spotlight is on it - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CSCANNER_SPOTLIGHT_INSPECT_POS, - - " Tasks" - " TASK_CSCANNER_SET_FLY_SPOT 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_SCANNER_INSPECT" - " TASK_SPEAK_SENTENCE 3" // Curious sound - " TASK_WAIT 5" - " TASK_CSCANNER_CLEAR_INSPECT_TARGET 0" - "" - " Interrupts" - " COND_CSCANNER_INSPECT_DONE" - " COND_HEAR_DANGER" - " COND_HEAR_COMBAT" - " COND_NEW_ENEMY" - " COND_SCANNER_GRABBED_BY_PHYSCANNON" - ) - - //========================================================= - // > SCHED_CSCANNER_SPOTLIGHT_INSPECT_CIT - // - // Inspect a citizen once spotlight is on it - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CSCANNER_SPOTLIGHT_INSPECT_CIT, - - " Tasks" - " TASK_CSCANNER_SET_FLY_SPOT 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_SCANNER_INSPECT" - " TASK_SPEAK_SENTENCE 0" // Stop! - " TASK_WAIT 1" - " TASK_CSCANNER_SPOT_INSPECT_ON 0" - " TASK_WAIT 2" - " TASK_SPEAK_SENTENCE 1" // Hands on head or Show Armband! - " TASK_WAIT 1" - " TASK_CSCANNER_SPOT_INSPECT_WAIT 0" - " TASK_WAIT 5" - " TASK_SPEAK_SENTENCE 2" // Free to go! - " TASK_WAIT 1" - " TASK_CSCANNER_SPOT_INSPECT_OFF 0" - " TASK_CSCANNER_CLEAR_INSPECT_TARGET 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_SCANNER_GRABBED_BY_PHYSCANNON" - ) - - //========================================================= - // > SCHED_CSCANNER_PHOTOGRAPH_HOVER - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CSCANNER_PHOTOGRAPH_HOVER, - - " Tasks" - " TASK_CSCANNER_SET_FLY_PHOTO 0" - " TASK_WAIT 2" - "" - " Interrupts" - " COND_CSCANNER_INSPECT_DONE" - " COND_CSCANNER_CAN_PHOTOGRAPH" - " COND_SCANNER_FLY_BLOCKED" - " COND_NEW_ENEMY" - " COND_SCANNER_GRABBED_BY_PHYSCANNON" - ) - - //========================================================= - // > SCHED_CSCANNER_PHOTOGRAPH - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CSCANNER_PHOTOGRAPH, - - " Tasks" - " TASK_CSCANNER_SET_FLY_PHOTO 0" - " TASK_CSCANNER_PHOTOGRAPH 0" - "" - " Interrupts" - " COND_CSCANNER_INSPECT_DONE" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_SCANNER_GRABBED_BY_PHYSCANNON" - ) - - //========================================================= - // > SCHED_CSCANNER_ATTACK_FLASH - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CSCANNER_ATTACK_FLASH, - - " Tasks" - " TASK_SCANNER_SET_FLY_ATTACK 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_CSCANNER_ATTACK_PRE_FLASH 0 " - " TASK_CSCANNER_ATTACK_FLASH 0" - " TASK_WAIT 0.5" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_SCANNER_GRABBED_BY_PHYSCANNON" - ) - - //========================================================= - // > SCHED_CSCANNER_MOVE_TO_INSPECT - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_CSCANNER_MOVE_TO_INSPECT, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_SCANNER_PATROL" - " TASK_SET_TOLERANCE_DISTANCE 128" - " TASK_CSCANNER_GET_PATH_TO_INSPECT_TARGET 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - "" - " Interrupts" - " COND_SCANNER_FLY_CLEAR" - " COND_NEW_ENEMY" - " COND_SCANNER_GRABBED_BY_PHYSCANNON" - ) - -AI_END_CUSTOM_NPC() - -//----------------------------------------------------------------------------- -// Claw Scanner -// -// Scanner that always spawns as a claw scanner -//----------------------------------------------------------------------------- - -class CNPC_ClawScanner : public CNPC_CScanner -{ -DECLARE_CLASS( CNPC_ClawScanner, CNPC_CScanner ); - -public: - CNPC_ClawScanner(); - DECLARE_DATADESC(); -}; - -BEGIN_DATADESC( CNPC_ClawScanner ) -END_DATADESC() - - -LINK_ENTITY_TO_CLASS(npc_clawscanner, CNPC_ClawScanner); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CNPC_ClawScanner::CNPC_ClawScanner() -{ - // override our superclass's setting - BecomeClawScanner(); -} diff --git a/game/server/hl2/npc_scanner.h b/game/server/hl2/npc_scanner.h deleted file mode 100644 index 9a061c8ea..000000000 --- a/game/server/hl2/npc_scanner.h +++ /dev/null @@ -1,215 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef NPC_SCANNER_H -#define NPC_SCANNER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "npc_basescanner.h" - -//------------------------------------ -// Spawnflags -//------------------------------------ -#define SF_CSCANNER_NO_DYNAMIC_LIGHT (1 << 16) -#define SF_CSCANNER_STRIDER_SCOUT (1 << 17) - -class CBeam; -class CSprite; -class SmokeTrail; -class CSpotlightEnd; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CNPC_CScanner : public CNPC_BaseScanner -{ - DECLARE_CLASS( CNPC_CScanner, CNPC_BaseScanner ); - -public: - CNPC_CScanner(); - - int GetSoundInterests( void ) { return (SOUND_WORLD|SOUND_COMBAT|SOUND_PLAYER|SOUND_DANGER); } - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - - bool FValidateHintType(CAI_Hint *pHint); - - virtual int TranslateSchedule( int scheduleType ); - Disposition_t IRelationType(CBaseEntity *pTarget); - - void NPCThink( void ); - - void GatherConditions( void ); - void PrescheduleThink( void ); - void Precache(void); - void RunTask( const Task_t *pTask ); - int SelectSchedule(void); - virtual const char *GetScannerSoundPrefix( void ); - void Spawn(void); - void Activate(); - void StartTask( const Task_t *pTask ); - void UpdateOnRemove( void ); - void DeployMine(); - float GetMaxSpeed(); - virtual void Gib( void ); - - void HandleAnimEvent( animevent_t *pEvent ); - Activity NPC_TranslateActivity( Activity eNewActivity ); - - void InputDisableSpotlight( inputdata_t &inputdata ); - void InputSetFollowTarget( inputdata_t &inputdata ); - void InputClearFollowTarget( inputdata_t &inputdata ); - void InputInspectTargetPhoto( inputdata_t &inputdata ); - void InputInspectTargetSpotlight( inputdata_t &inputdata ); - void InputDeployMine( inputdata_t &inputdata ); - void InputEquipMine( inputdata_t &inputdata ); - void InputShouldInspect( inputdata_t &inputdata ); - - void InspectTarget( inputdata_t &inputdata, ScannerFlyMode_t eFlyMode ); - - void Event_Killed( const CTakeDamageInfo &info ); - - const char *GetEngineSound( void ); - - virtual float MinGroundDist(void); - virtual void AdjustScannerVelocity( void ); - - virtual float GetHeadTurnRate( void ); - -public: - bool HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt); - - // ------------------------------ - // Inspecting - // ------------------------------ - Vector m_vInspectPos; - float m_fInspectEndTime; - float m_fCheckCitizenTime; // Time to look for citizens to harass - float m_fCheckHintTime; // Time to look for hints to inspect - bool m_bShouldInspect; - bool m_bOnlyInspectPlayers; - bool m_bNeverInspectPlayers; - - void SetInspectTargetToEnt(CBaseEntity *pEntity, float fInspectDuration); - void SetInspectTargetToPos(const Vector &vInspectPos, float fInspectDuration); - void SetInspectTargetToHint(CAI_Hint *pHint, float fInspectDuration); - void ClearInspectTarget(void); - bool HaveInspectTarget(void); - Vector InspectTargetPosition(void); - bool IsValidInspectTarget(CBaseEntity *pEntity); - CBaseEntity* BestInspectTarget(void); - void RequestInspectSupport(void); - - bool IsStriderScout() { return HasSpawnFlags( SF_CSCANNER_STRIDER_SCOUT ); } - - // ------------------------ - // Photographing - // ------------------------ - float m_fNextPhotographTime; - CSprite* m_pEyeFlash; - - void TakePhoto( void ); - void BlindFlashTarget( CBaseEntity *pTarget ); - - // ------------------------------ - // Spotlight - // ------------------------------ - Vector m_vSpotlightTargetPos; - Vector m_vSpotlightCurrentPos; - CHandle m_hSpotlight; - CHandle m_hSpotlightTarget; - Vector m_vSpotlightDir; - Vector m_vSpotlightAngVelocity; - float m_flSpotlightCurLength; - float m_flSpotlightMaxLength; - float m_flSpotlightGoalWidth; - float m_fNextSpotlightTime; - int m_nHaloSprite; - - void SpotlightUpdate(void); - Vector SpotlightTargetPos(void); - Vector SpotlightCurrentPos(void); - void SpotlightCreate(void); - void SpotlightDestroy(void); - -protected: - void BecomeClawScanner( void ) { m_bIsClawScanner = true; } - -private: - bool MovingToInspectTarget( void ); - virtual float GetGoalDistance( void ); - - bool m_bIsClawScanner; // Formerly the shield scanner. - bool m_bIsOpen; // Only for claw scanner - - COutputEvent m_OnPhotographPlayer; - COutputEvent m_OnPhotographNPC; - - bool OverrideMove(float flInterval); - void MoveToTarget(float flInterval, const Vector &MoveTarget); - void MoveToSpotlight(float flInterval); - void MoveToPhotograph(float flInterval); - - // Attacks - bool m_bNoLight; - bool m_bPhotoTaken; - - void AttackPreFlash(void); - void AttackFlash(void); - void AttackFlashBlind(void); - - virtual void AttackDivebomb(void); - - DEFINE_CUSTOM_AI; - - // Custom interrupt conditions - enum - { - COND_CSCANNER_HAVE_INSPECT_TARGET = BaseClass::NEXT_CONDITION, - COND_CSCANNER_INSPECT_DONE, - COND_CSCANNER_CAN_PHOTOGRAPH, - COND_CSCANNER_SPOT_ON_TARGET, - - NEXT_CONDITION, - }; - - // Custom schedules - enum - { - SCHED_CSCANNER_SPOTLIGHT_HOVER = BaseClass::NEXT_SCHEDULE, - SCHED_CSCANNER_SPOTLIGHT_INSPECT_POS, - SCHED_CSCANNER_SPOTLIGHT_INSPECT_CIT, - SCHED_CSCANNER_PHOTOGRAPH_HOVER, - SCHED_CSCANNER_PHOTOGRAPH, - SCHED_CSCANNER_ATTACK_FLASH, - SCHED_CSCANNER_MOVE_TO_INSPECT, - SCHED_CSCANNER_PATROL, - - NEXT_SCHEDULE, - }; - - // Custom tasks - enum - { - TASK_CSCANNER_SET_FLY_PHOTO = BaseClass::NEXT_TASK, - TASK_CSCANNER_SET_FLY_SPOT, - TASK_CSCANNER_PHOTOGRAPH, - TASK_CSCANNER_ATTACK_PRE_FLASH, - TASK_CSCANNER_ATTACK_FLASH, - TASK_CSCANNER_SPOT_INSPECT_ON, - TASK_CSCANNER_SPOT_INSPECT_WAIT, - TASK_CSCANNER_SPOT_INSPECT_OFF, - TASK_CSCANNER_CLEAR_INSPECT_TARGET, - TASK_CSCANNER_GET_PATH_TO_INSPECT_TARGET, - - NEXT_TASK, - }; - - DECLARE_DATADESC(); -}; - -#endif // NPC_SCANNER_H diff --git a/game/server/hl2/npc_spotlight.cpp b/game/server/hl2/npc_spotlight.cpp deleted file mode 100644 index 9e57f897d..000000000 --- a/game/server/hl2/npc_spotlight.cpp +++ /dev/null @@ -1,1544 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ai_basenpc.h" -#include "ai_default.h" -#include "ai_senses.h" -#include "ai_node.h" // for hint defintions -#include "ai_network.h" -#include "ai_hint.h" -#include "ai_squad.h" -#include "beam_shared.h" -#include "globalstate.h" -#include "soundent.h" -#include "ndebugoverlay.h" -#include "entitylist.h" -#include "npc_citizen17.h" -#include "scriptedtarget.h" -#include "ai_interactions.h" -#include "spotlightend.h" -#include "beam_flags.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SPOTLIGHT_SWING_FORWARD 1 -#define SPOTLIGHT_SWING_BACK -1 - -//------------------------------------ -// Spawnflags -//------------------------------------ -#define SF_SPOTLIGHT_START_TRACK_ON (1 << 16) -#define SF_SPOTLIGHT_START_LIGHT_ON (1 << 17) -#define SF_SPOTLIGHT_NO_DYNAMIC_LIGHT (1 << 18) -#define SF_SPOTLIGHT_NEVER_MOVE (1 << 19) - - -//----------------------------------------------------------------------------- -// Parameters for how the spotlight behaves -//----------------------------------------------------------------------------- -#define SPOTLIGHT_ENTITY_INSPECT_LENGTH 15 // How long does the inspection last -#define SPOTLIGHT_HINT_INSPECT_LENGTH 15 // How long does the inspection last -#define SPOTLIGHT_SOUND_INSPECT_LENGTH 1 // How long does the inspection last - -#define SPOTLIGHT_HINT_INSPECT_DELAY 20 // Check for hint nodes this often -#define SPOTLIGHT_ENTITY_INSPECT_DELAY 1 // Check for citizens this often - -#define SPOTLIGHT_HINT_SEARCH_DIST 1000 // How far from self do I look for hints? -#define SPOTLIGHT_ENTITY_SEARCH_DIST 100 // How far from spotlight do I look for entities? -#define SPOTLIGHT_ACTIVE_SEARCH_DIST 200 // How far from spotlight do I look when already have entity - -#define SPOTLIGHT_BURN_TARGET_THRESH 60 // How close need to get to burn target -#define SPOTLIGHT_MAX_SPEED_SCALE 2 - -//#define SPOTLIGHT_DEBUG - - -// ----------------------------------- -// Spotlight flags -// ----------------------------------- -enum SpotlightFlags_t -{ - BITS_SPOTLIGHT_LIGHT_ON = 0x00000001, // Light is on - BITS_SPOTLIGHT_TRACK_ON = 0x00000002, // Tracking targets / scanning - BITS_SPOTLIGHT_SMOOTH_RETURN = 0x00001000, // If out of range, don't pop back to position -}; - - -class CBeam; - - -class CNPC_Spotlight : public CAI_BaseNPC -{ - DECLARE_CLASS( CNPC_Spotlight, CAI_BaseNPC ); - - public: - CNPC_Spotlight(); - Class_T Classify(void); - int UpdateTransmitState(void); - void Event_Killed( const CTakeDamageInfo &info ); - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - int GetSoundInterests( void ); - - bool FValidateHintType(CAI_Hint *pHint); - - Disposition_t IRelationType(CBaseEntity *pTarget); - float HearingSensitivity( void ) { return 4.0; }; - - void NPCThink(void); - bool HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt); - - void UpdateTargets(void); - void Precache(void); - void Spawn(void); - - public: - - int m_fSpotlightFlags; - - // ------------------------------ - // Scripted Spotlight Motion - // ------------------------------ - CScriptedTarget* m_pScriptedTarget; // My current scripted target - void SetScriptedTarget( CScriptedTarget *pScriptedTarget ); - - // ------------------------------ - // Inspecting - // ------------------------------ - Vector m_vInspectPos; - float m_flInspectEndTime; - float m_flNextEntitySearchTime; - float m_flNextHintSearchTime; // Time to look for hints to inspect - - void SetInspectTargetToEntity(CBaseEntity *pEntity, float fInspectDuration); - void SetInspectTargetToEnemy(CBaseEntity *pEntity); - void SetInspectTargetToPos(const Vector &vInspectPos, float fInspectDuration); - void SetInspectTargetToHint(CAI_Hint *pHint, float fInspectDuration); - void ClearInspectTarget(void); - bool HaveInspectTarget(void); - Vector InspectTargetPosition(void); - CBaseEntity* BestInspectTarget(void); - void RequestInspectSupport(void); - - // ------------------------------- - // Outputs - // ------------------------------- - bool m_bHadEnemy; // Had an enemy - COutputEvent m_pOutputAlert; // Alerted by sound - COutputEHANDLE m_pOutputDetect; // Found enemy, output it's name - COutputEHANDLE m_pOutputLost; // Lost enemy - COutputEHANDLE m_pOutputSquadDetect; // Squad Found enemy - COutputEHANDLE m_pOutputSquadLost; // Squad Lost enemy - COutputVector m_pOutputPosition; // End position of spotlight beam - - // ------------------------------ - // Spotlight - // ------------------------------ - float m_flYaw; - float m_flYawCenter; - float m_flYawRange; // +/- around center - float m_flYawSpeed; - float m_flYawDir; - - float m_flPitch; - float m_flPitchCenter; - float m_flPitchMin; - float m_flPitchMax; - float m_flPitchSpeed; - float m_flPitchDir; - - float m_flIdleSpeed; // Speed when no enemy - float m_flAlertSpeed; // Speed when found enemy - - Vector m_vSpotlightTargetPos; - Vector m_vSpotlightCurrentPos; - CBeam* m_pSpotlight; - CSpotlightEnd* m_pSpotlightTarget; - Vector m_vSpotlightDir; - int m_nHaloSprite; - - float m_flSpotlightMaxLength; - float m_flSpotlightCurLength; - float m_flSpotlightGoalWidth; - - void SpotlightUpdate(void); - Vector SpotlightCurrentPos(void); - void SpotlightSetTargetYawAndPitch(void); - float SpotlightSpeed(void); - void SpotlightCreate(void); - void SpotlightDestroy(void); - bool SpotlightIsPositionLegal(const Vector &vTestPos); - - // ------------------------------ - // Inputs - // ------------------------------ - void InputLightOn( inputdata_t &inputdata ); - void InputLightOff( inputdata_t &inputdata ); - void InputTrackOn( inputdata_t &inputdata ); - void InputTrackOff( inputdata_t &inputdata ); - - protected: - - DECLARE_DATADESC(); -}; - - -BEGIN_DATADESC( CNPC_Spotlight ) - DEFINE_FIELD( m_vInspectPos, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_flYaw, FIELD_FLOAT ), - DEFINE_FIELD( m_flYawCenter, FIELD_FLOAT ), - DEFINE_FIELD( m_flYawSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_flYawDir, FIELD_FLOAT ), - DEFINE_FIELD( m_flPitch, FIELD_FLOAT ), - DEFINE_FIELD( m_flPitchCenter, FIELD_FLOAT ), - DEFINE_FIELD( m_flPitchSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_flPitchDir, FIELD_FLOAT ), - DEFINE_FIELD( m_flSpotlightCurLength, FIELD_FLOAT ), - - DEFINE_FIELD( m_fSpotlightFlags, FIELD_INTEGER ), - DEFINE_FIELD( m_flInspectEndTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextEntitySearchTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextHintSearchTime, FIELD_TIME ), - DEFINE_FIELD( m_bHadEnemy, FIELD_BOOLEAN ), - DEFINE_FIELD( m_vSpotlightTargetPos, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vSpotlightCurrentPos, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_pSpotlight, FIELD_CLASSPTR ), - DEFINE_FIELD( m_pSpotlightTarget, FIELD_CLASSPTR ), - DEFINE_FIELD( m_vSpotlightDir, FIELD_VECTOR ), - DEFINE_FIELD( m_nHaloSprite, FIELD_INTEGER ), - DEFINE_FIELD( m_pScriptedTarget, FIELD_CLASSPTR ), - - DEFINE_KEYFIELD( m_flYawRange, FIELD_FLOAT, "YawRange"), - DEFINE_KEYFIELD( m_flPitchMin, FIELD_FLOAT, "PitchMin"), - DEFINE_KEYFIELD( m_flPitchMax, FIELD_FLOAT, "PitchMax"), - DEFINE_KEYFIELD( m_flIdleSpeed, FIELD_FLOAT, "IdleSpeed"), - DEFINE_KEYFIELD( m_flAlertSpeed, FIELD_FLOAT, "AlertSpeed"), - DEFINE_KEYFIELD( m_flSpotlightMaxLength,FIELD_FLOAT, "SpotlightLength"), - DEFINE_KEYFIELD( m_flSpotlightGoalWidth,FIELD_FLOAT, "SpotlightWidth"), - - // DEBUG m_pScriptedTarget - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "LightOn", InputLightOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "LightOff", InputLightOff ), - DEFINE_INPUTFUNC( FIELD_VOID, "TrackOn", InputTrackOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TrackOff", InputTrackOff ), - - // Outputs - DEFINE_OUTPUT(m_pOutputAlert, "OnAlert" ), - DEFINE_OUTPUT(m_pOutputDetect, "DetectedEnemy" ), - DEFINE_OUTPUT(m_pOutputLost, "LostEnemy" ), - DEFINE_OUTPUT(m_pOutputSquadDetect, "SquadDetectedEnemy" ), - DEFINE_OUTPUT(m_pOutputSquadLost, "SquadLostEnemy" ), - DEFINE_OUTPUT(m_pOutputPosition, "LightPosition" ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS(npc_spotlight, CNPC_Spotlight); - -CNPC_Spotlight::CNPC_Spotlight() -{ -#ifdef _DEBUG - m_vInspectPos.Init(); - m_vSpotlightTargetPos.Init(); - m_vSpotlightCurrentPos.Init(); - m_vSpotlightDir.Init(); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Indicates this NPC's place in the relationship table. -//----------------------------------------------------------------------------- -Class_T CNPC_Spotlight::Classify(void) -{ - return(CLASS_MILITARY); -} - -//------------------------------------------------------------------------------------- -// Purpose : Send even though we don't have a model so spotlight gets proper position -// Input : -// Output : -//------------------------------------------------------------------------------------- -int CNPC_Spotlight::UpdateTransmitState(void) -{ - return SetTransmitState( FL_EDICT_PVSCHECK ); -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -int CNPC_Spotlight::GetSoundInterests( void ) -{ - return (SOUND_COMBAT | SOUND_DANGER); -} - -//------------------------------------------------------------------------------ -// Purpose : Override to split in two when attacked -// Input : -// Output : -//------------------------------------------------------------------------------ -int CNPC_Spotlight::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - // Deflect spotlight - Vector vCrossProduct; - CrossProduct(m_vSpotlightDir,g_vecAttackDir, vCrossProduct); - if (vCrossProduct.y > 0) - { - m_flYaw += random->RandomInt(10,20); - } - else - { - m_flYaw -= random->RandomInt(10,20); - } - - return (BaseClass::OnTakeDamage_Alive( info )); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pInflictor - -// pAttacker - -// flDamage - -// bitsDamageType - -//----------------------------------------------------------------------------- -void CNPC_Spotlight::Event_Killed( const CTakeDamageInfo &info ) -{ - // Interrupt whatever schedule I'm on - SetCondition(COND_SCHEDULE_DONE); - - // Remove spotlight - SpotlightDestroy(); - - // Otherwise, turn into a physics object and fall to the ground - CBaseCombatCharacter::Event_Killed( info ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Tells use whether or not the NPC cares about a given type of hint node. -// Input : sHint - -// Output : TRUE if the NPC is interested in this hint type, FALSE if not. -//----------------------------------------------------------------------------- -bool CNPC_Spotlight::FValidateHintType(CAI_Hint *pHint) -{ - if (pHint->HintType() == HINT_WORLD_WINDOW) - { - Vector vHintPos; - pHint->GetPosition(this,&vHintPos); - if (SpotlightIsPositionLegal(vHintPos)) - { - return true; - } - } - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Plays the engine sound. -//----------------------------------------------------------------------------- -void CNPC_Spotlight::NPCThink(void) -{ - SetNextThink( gpGlobals->curtime + 0.1f );// keep npc thinking. - - if (CAI_BaseNPC::m_nDebugBits & bits_debugDisableAI) - { - if (m_pSpotlightTarget) - { - m_pSpotlightTarget->SetAbsVelocity( vec3_origin ); - } - } - else if (IsAlive()) - { - GetSenses()->Listen(); - UpdateTargets(); - SpotlightUpdate(); - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Spotlight::Precache(void) -{ - // - // Model. - // - PrecacheModel("models/combot.mdl"); - PrecacheModel("models/gibs/combot_gibs.mdl"); - - // - // Sprites. - // - PrecacheModel("sprites/spotlight.vmt"); - m_nHaloSprite = PrecacheModel("sprites/blueflare1.vmt"); - - BaseClass::Precache(); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -CBaseEntity* CNPC_Spotlight::BestInspectTarget(void) -{ - // Only look for inspect targets when spotlight it on - if (m_pSpotlightTarget == NULL) - { - return NULL; - } - - float fBestDistance = MAX_COORD_RANGE; - int nBestPriority = -1000; - int nBestRelationship = D_NU; - - // Get my best enemy first - CBaseEntity* pBestEntity = BestEnemy(); - if (pBestEntity) - { - // If the enemy isn't visibile - if (!FVisible(pBestEntity)) - { - // If he hasn't been seen in a while and hasn't already eluded - // the squad, make the enemy as eluded and fire a lost squad output - float flTimeLastSeen = GetEnemies()->LastTimeSeen(pBestEntity); - if (!GetEnemies()->HasEludedMe(pBestEntity) && - flTimeLastSeen + 0.5 < gpGlobals->curtime) - { - GetEnemies()->MarkAsEluded(pBestEntity); - m_pOutputSquadLost.Set(*((EHANDLE *)pBestEntity),this,this); - } - pBestEntity = NULL; - } - - // If he has eluded me or isn't in the legal range of my spotligth reject - else if (GetEnemies()->HasEludedMe(pBestEntity) || - !SpotlightIsPositionLegal(GetEnemies()->LastKnownPosition(pBestEntity)) ) - { - pBestEntity = NULL; - } - } - - CBaseEntity *pEntity = NULL; - - // Search from the spotlight position - Vector vSearchOrigin = m_pSpotlightTarget->GetAbsOrigin(); - float flSearchDist; - if (HaveInspectTarget()) - { - flSearchDist = SPOTLIGHT_ACTIVE_SEARCH_DIST; - } - else - { - flSearchDist = SPOTLIGHT_ENTITY_SEARCH_DIST; - } - for ( CEntitySphereQuery sphere( vSearchOrigin, SPOTLIGHT_ENTITY_SEARCH_DIST ); (pEntity = sphere.GetCurrentEntity()) != NULL; sphere.NextEntity() ) - { - if (pEntity->GetFlags() & (FL_CLIENT|FL_NPC)) - { - - if (pEntity->GetFlags() & FL_NOTARGET) - { - continue; - } - - - if (!pEntity->IsAlive()) - { - continue; - } - - if ((pEntity->Classify() == CLASS_MILITARY)|| - (pEntity->Classify() == CLASS_BULLSEYE)) - { - continue; - } - - if (m_pSquad && m_pSquad->SquadIsMember(pEntity)) - { - continue; - } - - // Disregard if the entity is out of the view cone, occluded, - if( !FVisible( pEntity ) ) - { - continue; - } - - // If it's a new enemy or one that had eluded me - if (!GetEnemies()->HasMemory(pEntity) || - GetEnemies()->HasEludedMe(pEntity) ) - { - m_pOutputSquadDetect.Set(*((EHANDLE *)pEntity),this,this); - } - UpdateEnemyMemory(pEntity,pEntity->GetAbsOrigin()); - - CBaseCombatCharacter* pBCC = (CBaseCombatCharacter*)pEntity; - float fTestDistance = (GetAbsOrigin() - pBCC->EyePosition()).Length(); - int nTestRelationship = IRelationType(pBCC); - int nTestPriority = IRelationPriority ( pBCC ); - - // Only follow hated entities if I'm not in idle state - if (nTestRelationship != D_HT && m_NPCState != NPC_STATE_IDLE) - { - continue; - } - - // ------------------------------------------- - // Choose hated entites over everything else - // ------------------------------------------- - if (nTestRelationship == D_HT && nBestRelationship != D_HT) - { - pBestEntity = pBCC; - fBestDistance = fTestDistance; - nBestPriority = nTestPriority; - nBestRelationship = nTestRelationship; - } - // ------------------------------------------- - // If both are hated, or both are not - // ------------------------------------------- - else if( (nTestRelationship != D_HT && nBestRelationship != D_HT) || - (nTestRelationship == D_HT && nBestRelationship == D_HT) ) - { - // -------------------------------------- - // Pick one with the higher priority - // -------------------------------------- - if (nTestPriority > nBestPriority) - { - pBestEntity = pBCC; - fBestDistance = fTestDistance; - nBestPriority = nTestPriority; - nBestRelationship = nTestRelationship; - } - // ----------------------------------------- - // If priority the same pick best distance - // ----------------------------------------- - else if (nTestPriority == nBestPriority) - { - if (fTestDistance < fBestDistance) - { - pBestEntity = pBCC; - fBestDistance = fTestDistance; - nBestPriority = nTestPriority; - nBestRelationship = nTestRelationship; - } - } - } - } - } - return pBestEntity; -} - -//------------------------------------------------------------------------------ -// Purpose : Clears any previous inspect target and set inspect target to -// the given entity and set the durection of the inspection -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_Spotlight::SetInspectTargetToEntity(CBaseEntity *pEntity, float fInspectDuration) -{ - ClearInspectTarget(); - SetTarget(pEntity); - m_flInspectEndTime = gpGlobals->curtime + fInspectDuration; -} - -//------------------------------------------------------------------------------ -// Purpose : Clears any previous inspect target and set inspect target to -// the given entity and set the durection of the inspection -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_Spotlight::SetInspectTargetToEnemy(CBaseEntity *pEntity) -{ - ClearInspectTarget(); - SetEnemy( pEntity ); - m_bHadEnemy = true; - m_flInspectEndTime = 0; - SetState(NPC_STATE_COMBAT); - - EHANDLE hEnemy; - hEnemy.Set( GetEnemy() ); - m_pOutputDetect.Set(hEnemy, NULL, this); -} - -//------------------------------------------------------------------------------ -// Purpose : Clears any previous inspect target and set inspect target to -// the given hint node and set the durection of the inspection -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_Spotlight::SetInspectTargetToHint(CAI_Hint *pHintNode, float fInspectDuration) -{ - ClearInspectTarget(); - - // -------------------------------------------- - // Figure out the location that the hint hits - // -------------------------------------------- - float fHintYaw = DEG2RAD(pHintNode->Yaw()); - Vector vHintDir = Vector(cos(fHintYaw),sin(fHintYaw),0); - Vector vHintOrigin; - pHintNode->GetPosition(this,&vHintOrigin); - Vector vHintEnd = vHintOrigin + (vHintDir * 500); - trace_t tr; - AI_TraceLine ( vHintOrigin, vHintEnd, MASK_OPAQUE, this, COLLISION_GROUP_NONE, &tr); - if (tr.fraction == 1.0) - { - DevMsg("ERROR: Scanner hint node not facing a surface!\n"); - } - else - { - SetHintNode( pHintNode ); - m_vInspectPos = tr.endpos; - pHintNode->Lock(this); - - m_flInspectEndTime = gpGlobals->curtime + fInspectDuration; - } -} - -//------------------------------------------------------------------------------ -// Purpose : Clears any previous inspect target and set inspect target to -// the given position and set the durection of the inspection -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_Spotlight::SetInspectTargetToPos(const Vector &vInspectPos, float fInspectDuration) -{ - ClearInspectTarget(); - m_vInspectPos = vInspectPos; - - m_flInspectEndTime = gpGlobals->curtime + fInspectDuration; -} - -//------------------------------------------------------------------------------ -// Purpose : Clears out any previous inspection targets -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_Spotlight::ClearInspectTarget(void) -{ - // If I'm losing an enemy, fire a message - if (m_bHadEnemy) - { - m_bHadEnemy = false; - - EHANDLE hEnemy; - hEnemy.Set( GetEnemy() ); - - m_pOutputLost.Set(hEnemy,this,this); - } - - // If I'm in combat state, go to alert - if (m_NPCState == NPC_STATE_COMBAT) - { - SetState(NPC_STATE_ALERT); - } - - SetTarget( NULL ); - SetEnemy( NULL ); - ClearHintNode( SPOTLIGHT_HINT_INSPECT_LENGTH ); - m_vInspectPos = vec3_origin; - m_flYawDir = random->RandomInt(0,1) ? 1 : -1; - m_flPitchDir = random->RandomInt(0,1) ? 1 : -1; -} - -//------------------------------------------------------------------------------ -// Purpose : Returns true if there is a position to be inspected and sets -// vTargetPos to the inspection position -// Input : -// Output : -//------------------------------------------------------------------------------ -bool CNPC_Spotlight::HaveInspectTarget(void) -{ - if (GetEnemy() != NULL) - { - return true; - } - else if (GetTarget() != NULL) - { - return true; - } - if (m_vInspectPos != vec3_origin) - { - return true; - } - return false; -} - -//------------------------------------------------------------------------------ -// Purpose : Returns true if there is a position to be inspected and sets -// vTargetPos to the inspection position -// Input : -// Output : -//------------------------------------------------------------------------------ -Vector CNPC_Spotlight::InspectTargetPosition(void) -{ - if (GetEnemy() != NULL) - { - // If in spotlight mode, aim for ground below target unless is client - if (!(GetEnemy()->GetFlags() & FL_CLIENT)) - { - Vector vInspectPos; - vInspectPos.x = GetEnemy()->GetAbsOrigin().x; - vInspectPos.y = GetEnemy()->GetAbsOrigin().y; - vInspectPos.z = GetFloorZ(GetEnemy()->GetAbsOrigin()+Vector(0,0,1)); - return vInspectPos; - } - // Otherwise aim for eyes - else - { - return GetEnemy()->EyePosition(); - } - } - else if (GetTarget() != NULL) - { - // If in spotlight mode, aim for ground below target unless is client - if (!(GetTarget()->GetFlags() & FL_CLIENT)) - { - Vector vInspectPos; - vInspectPos.x = GetTarget()->GetAbsOrigin().x; - vInspectPos.y = GetTarget()->GetAbsOrigin().y; - vInspectPos.z = GetFloorZ(GetTarget()->GetAbsOrigin()); - return vInspectPos; - } - // Otherwise aim for eyes - else - { - return GetTarget()->EyePosition(); - } - } - else if (m_vInspectPos != vec3_origin) - { - return m_vInspectPos; - } - else - { - DevMsg("InspectTargetPosition called with no target!\n"); - return m_vInspectPos; - } -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_Spotlight::UpdateTargets(void) -{ - if (m_fSpotlightFlags & BITS_SPOTLIGHT_TRACK_ON) - { - // -------------------------------------------------------------------------- - // Look for a nearby entity to inspect - // -------------------------------------------------------------------------- - CBaseEntity *pBestEntity = BestInspectTarget(); - - // If I found one - if (pBestEntity) - { - // If it's an enemy - if (IRelationType(pBestEntity) == D_HT) - { - // If I'm not already inspecting an enemy take it - if (GetEnemy() == NULL) - { - SetInspectTargetToEnemy(pBestEntity); - if (m_pSquad) - { - AISquadIter_t iter; - for (CAI_BaseNPC *pSquadMember = m_pSquad->GetFirstMember( &iter ); pSquadMember; pSquadMember = m_pSquad->GetNextMember( &iter ) ) - { - // reset members who aren't activly engaged in fighting - if (pSquadMember->GetEnemy() != pBestEntity && !pSquadMember->HasCondition( COND_SEE_ENEMY)) - { - // give them a new enemy - pSquadMember->SetLastAttackTime( 0 ); - pSquadMember->SetCondition ( COND_NEW_ENEMY ); - } - } - } - } - // If I am inspecting an enemy, take it if priority is higher - else - { - if (IRelationPriority(pBestEntity) > IRelationPriority(GetEnemy())) - { - SetInspectTargetToEnemy(pBestEntity); - } - } - } - // If its not an enemy - else - { - // If I'm not already inspeting something take it - if (GetTarget() == NULL) - { - SetInspectTargetToEntity(pBestEntity,SPOTLIGHT_ENTITY_INSPECT_LENGTH); - } - // If I am inspecting somethin, take if priority is higher - else - { - if (IRelationPriority(pBestEntity) > IRelationPriority(GetTarget())) - { - SetInspectTargetToEntity(pBestEntity,SPOTLIGHT_ENTITY_INSPECT_LENGTH); - } - } - } - } - - // --------------------------------------- - // If I'm not current inspecting an enemy - // --------------------------------------- - if (GetEnemy() == NULL) - { - // ----------------------------------------------------------- - // If my inspection over clear my inspect target. - // ----------------------------------------------------------- - if (HaveInspectTarget() && - gpGlobals->curtime > m_flInspectEndTime ) - { - m_flNextEntitySearchTime = gpGlobals->curtime + SPOTLIGHT_ENTITY_INSPECT_DELAY; - m_flNextHintSearchTime = gpGlobals->curtime + SPOTLIGHT_HINT_INSPECT_DELAY; - ClearInspectTarget(); - } - - // -------------------------------------------------------------- - // If I heard a sound inspect it - // -------------------------------------------------------------- - if (HasCondition(COND_HEAR_COMBAT) || HasCondition(COND_HEAR_DANGER) ) - { - CSound *pSound = GetBestSound(); - if (pSound) - { - Vector vSoundPos = pSound->GetSoundOrigin(); - // Only alert to sound if in my swing range - if (SpotlightIsPositionLegal(vSoundPos)) - { - SetInspectTargetToPos(vSoundPos,SPOTLIGHT_SOUND_INSPECT_LENGTH); - - // Fire alert output - m_pOutputAlert.FireOutput(NULL,this); - - SetState(NPC_STATE_ALERT); - } - } - } - - // -------------------------------------- - // Check for hints to inspect - // -------------------------------------- - if (gpGlobals->curtime > m_flNextHintSearchTime && - !HaveInspectTarget() ) - { - SetHintNode(CAI_HintManager::FindHint(this, HINT_NONE, 0, SPOTLIGHT_HINT_SEARCH_DIST)); - - if (GetHintNode()) - { - m_flNextHintSearchTime = gpGlobals->curtime + SPOTLIGHT_HINT_INSPECT_LENGTH; - SetInspectTargetToHint(GetHintNode(),SPOTLIGHT_HINT_INSPECT_LENGTH); - } - } - } - - // ------------------------------------------------------- - // Make sure inspect target is still in a legal position - // (Don't care about enemies) - // ------------------------------------------------------- - if (GetTarget()) - { - if (!SpotlightIsPositionLegal(GetEnemies()->LastKnownPosition(GetTarget()))) - { - ClearInspectTarget(); - } - else if (!FVisible(GetTarget())) - { - ClearInspectTarget(); - } - } - if (GetEnemy()) - { - if (!FVisible(GetEnemy())) - { - ClearInspectTarget(); - } - // If enemy is dead inspect for a couple of seconds on move on - else if (!GetEnemy()->IsAlive()) - { - SetInspectTargetToPos( GetEnemy()->GetAbsOrigin(), 1.0); - } - else - { - UpdateEnemyMemory(GetEnemy(),GetEnemy()->GetAbsOrigin()); - } - } - - // ----------------------------------------- - // See if I'm at my burn target - // ------------------------------------------ - if (!HaveInspectTarget() && - m_pScriptedTarget && - m_pSpotlightTarget != NULL ) - { - float fTargetDist = (m_vSpotlightTargetPos - m_vSpotlightCurrentPos).Length(); - if (fTargetDist < SPOTLIGHT_BURN_TARGET_THRESH ) - { - // Update scripted target - SetScriptedTarget( m_pScriptedTarget->NextScriptedTarget()); - } - else - { - Vector vTargetDir = m_vSpotlightTargetPos - m_vSpotlightCurrentPos; - VectorNormalize(vTargetDir); - float flDot = DotProduct(m_vSpotlightDir,vTargetDir); - if (flDot > 0.99 ) - { - // Update scripted target - SetScriptedTarget( m_pScriptedTarget->NextScriptedTarget()); - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Overridden because if the player is a criminal, we hate them. -// Input : pTarget - Entity with which to determine relationship. -// Output : Returns relationship value. -//----------------------------------------------------------------------------- -Disposition_t CNPC_Spotlight::IRelationType(CBaseEntity *pTarget) -{ - // - // If it's the player and they are a criminal, we hate them. - // - if (pTarget->Classify() == CLASS_PLAYER) - { - if (GlobalEntity_GetState("gordon_precriminal") == GLOBAL_ON) - { - return(D_NU); - } - } - - return(CBaseCombatCharacter::IRelationType(pTarget)); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_Spotlight::SpotlightDestroy(void) -{ - if (m_pSpotlight) - { - UTIL_Remove(m_pSpotlight); - m_pSpotlight = NULL; - - UTIL_Remove(m_pSpotlightTarget); - m_pSpotlightTarget = NULL; - } -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_Spotlight::SpotlightCreate(void) -{ - - // If I have an enemy, start spotlight on my enemy - if (GetEnemy() != NULL) - { - Vector vEnemyPos = GetEnemyLKP(); - Vector vTargetPos = vEnemyPos; - vTargetPos.z = GetFloorZ(vEnemyPos); - m_vSpotlightDir = vTargetPos - GetAbsOrigin(); - VectorNormalize(m_vSpotlightDir); - } - // If I have an target, start spotlight on my target - else if (GetTarget() != NULL) - { - Vector vTargetPos = GetTarget()->GetAbsOrigin(); - vTargetPos.z = GetFloorZ(GetTarget()->GetAbsOrigin()); - m_vSpotlightDir = vTargetPos - GetAbsOrigin(); - VectorNormalize(m_vSpotlightDir); - } - else - { - AngleVectors( GetAbsAngles(), &m_vSpotlightDir ); - } - - trace_t tr; - AI_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + m_vSpotlightDir * m_flSpotlightMaxLength, - MASK_OPAQUE, this, COLLISION_GROUP_NONE, &tr); - - m_pSpotlightTarget = (CSpotlightEnd*)CreateEntityByName( "spotlight_end" ); - m_pSpotlightTarget->Spawn(); - m_pSpotlightTarget->SetLocalOrigin( tr.endpos ); - m_pSpotlightTarget->SetOwnerEntity( this ); - m_pSpotlightTarget->m_clrRender = m_clrRender; - m_pSpotlightTarget->m_Radius = m_flSpotlightMaxLength; - - if ( FBitSet (m_spawnflags, SF_SPOTLIGHT_NO_DYNAMIC_LIGHT) ) - { - m_pSpotlightTarget->m_flLightScale = 0.0; - } - - m_pSpotlight = CBeam::BeamCreate( "sprites/spotlight.vmt", 2.0 ); - m_pSpotlight->SetColor( m_clrRender->r, m_clrRender->g, m_clrRender->b ); - m_pSpotlight->SetHaloTexture(m_nHaloSprite); - m_pSpotlight->SetHaloScale(40); - m_pSpotlight->SetEndWidth(m_flSpotlightGoalWidth); - m_pSpotlight->SetBeamFlags(FBEAM_SHADEOUT); - m_pSpotlight->SetBrightness( 80 ); - m_pSpotlight->SetNoise( 0 ); - m_pSpotlight->EntsInit( this, m_pSpotlightTarget ); -} - -//------------------------------------------------------------------------------ -// Purpose : Returns true is spotlight can reach position -// Input : -// Output : -//------------------------------------------------------------------------------ -bool CNPC_Spotlight::SpotlightIsPositionLegal(const Vector &vTestPos) -{ - Vector vTargetDir = vTestPos - GetAbsOrigin(); - VectorNormalize(vTargetDir); - QAngle vTargetAngles; - VectorAngles(vTargetDir,vTargetAngles); - - // Make sure target is in a legal position - if (UTIL_AngleDistance( vTargetAngles[YAW], m_flYawCenter ) > m_flYawRange) - { - return false; - } - else if (UTIL_AngleDistance( vTargetAngles[YAW], m_flYawCenter ) < -m_flYawRange) - { - return false; - } - if (UTIL_AngleDistance( vTargetAngles[PITCH], m_flPitchCenter ) > m_flPitchMax) - { - return false; - } - else if (UTIL_AngleDistance( vTargetAngles[PITCH], m_flPitchCenter ) < m_flPitchMin) - { - return false; - } - return true; -} - -//------------------------------------------------------------------------------ -// Purpose : Converts spotlight target position into desired yaw and pitch -// directions to reach target -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_Spotlight::SpotlightSetTargetYawAndPitch(void) -{ - Vector vTargetDir = m_vSpotlightTargetPos - GetAbsOrigin(); - VectorNormalize(vTargetDir); - QAngle vTargetAngles; - VectorAngles(vTargetDir,vTargetAngles); - - float flYawDiff = UTIL_AngleDistance(vTargetAngles[YAW], m_flYaw); - if ( flYawDiff > 0) - { - m_flYawDir = SPOTLIGHT_SWING_FORWARD; - } - else - { - m_flYawDir = SPOTLIGHT_SWING_BACK; - } - - //DevMsg("%f %f (%f)\n",vTargetAngles[YAW], m_flYaw,flYawDiff); - - float flPitchDiff = UTIL_AngleDistance(vTargetAngles[PITCH], m_flPitch); - if (flPitchDiff > 0) - { - m_flPitchDir = SPOTLIGHT_SWING_FORWARD; - } - else - { - m_flPitchDir = SPOTLIGHT_SWING_BACK; - } - - //DevMsg("%f %f (%f)\n",vTargetAngles[PITCH], m_flPitch,flPitchDiff); - - - if ( fabs(flYawDiff) < 2) - { - m_flYawDir *= 0.5; - } - if ( fabs(flPitchDiff) < 2) - { - m_flPitchDir *= 0.5; - } -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -float CNPC_Spotlight::SpotlightSpeed(void) -{ - float fSpeedScale = 1.0; - float fInspectDist = (m_vSpotlightTargetPos - m_vSpotlightCurrentPos).Length(); - if (fInspectDist < 100) - { - fSpeedScale = 0.25; - } - - if (!HaveInspectTarget() && m_pScriptedTarget) - { - return (fSpeedScale * m_pScriptedTarget->MoveSpeed()); - } - else if (m_NPCState == NPC_STATE_COMBAT || - m_NPCState == NPC_STATE_ALERT ) - { - return (fSpeedScale * m_flAlertSpeed); - } - else - { - return (fSpeedScale * m_flIdleSpeed); - } -} -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -Vector CNPC_Spotlight::SpotlightCurrentPos(void) -{ - if (!m_pSpotlight) - { - DevMsg("Spotlight pos. called w/o spotlight!\n"); - return vec3_origin; - } - - if (HaveInspectTarget()) - { - m_vSpotlightTargetPos = InspectTargetPosition(); - SpotlightSetTargetYawAndPitch(); - } - else if (m_pScriptedTarget) - { - m_vSpotlightTargetPos = m_pScriptedTarget->GetAbsOrigin(); - SpotlightSetTargetYawAndPitch(); - - // I'm allowed to move outside my normal range when - // tracking burn targets. Return smoothly when I'm done - m_fSpotlightFlags |= BITS_SPOTLIGHT_SMOOTH_RETURN; - } - else - { - // Make random movement frame independent - if (random->RandomInt(0,10) == 0) - { - m_flYawDir *= -1; - } - if (random->RandomInt(0,10) == 0) - { - m_flPitchDir *= -1; - } - } - // Calculate new pitch and yaw velocity - float flSpeed = SpotlightSpeed(); - float flNewYawSpeed = m_flYawDir * flSpeed; - float flNewPitchSpeed = m_flPitchDir * flSpeed; - - // Adjust current velocity - float myYawDecay = 0.8; - float myPitchDecay = 0.7; - m_flYawSpeed = (myYawDecay * m_flYawSpeed + (1-myYawDecay) * flNewYawSpeed ); - m_flPitchSpeed = (myPitchDecay * m_flPitchSpeed + (1-myPitchDecay) * flNewPitchSpeed); - - // Keep speed with in bounds - float flMaxSpeed = SPOTLIGHT_MAX_SPEED_SCALE * SpotlightSpeed(); - if (m_flYawSpeed > flMaxSpeed) m_flYawSpeed = flMaxSpeed; - else if (m_flYawSpeed < -flMaxSpeed) m_flYawSpeed = -flMaxSpeed; - if (m_flPitchSpeed > flMaxSpeed) m_flPitchSpeed = flMaxSpeed; - else if (m_flPitchSpeed < -flMaxSpeed) m_flPitchSpeed = -flMaxSpeed; - - // Calculate new pitch and yaw positions - m_flYaw += m_flYawSpeed; - m_flPitch += m_flPitchSpeed; - - // Keep yaw in 0/360 range - if (m_flYaw < 0 ) m_flYaw +=360; - if (m_flYaw > 360) m_flYaw -=360; - - // --------------------------------------------- - // Check yaw and pitch boundaries unless I have - // a burn target, or an enemy - // --------------------------------------------- - if (( HaveInspectTarget() && GetEnemy() == NULL ) || - (!HaveInspectTarget() && !m_pScriptedTarget ) ) - { - bool bInRange = true; - if (UTIL_AngleDistance( m_flYaw, m_flYawCenter ) > m_flYawRange) - { - if (m_fSpotlightFlags & BITS_SPOTLIGHT_SMOOTH_RETURN) - { - bInRange = false; - } - else - { - m_flYaw = m_flYawCenter + m_flYawRange; - } - m_flYawDir = SPOTLIGHT_SWING_BACK; - } - else if (UTIL_AngleDistance( m_flYaw, m_flYawCenter ) < -m_flYawRange) - { - if (m_fSpotlightFlags & BITS_SPOTLIGHT_SMOOTH_RETURN) - { - bInRange = false; - } - else - { - m_flYaw = m_flYawCenter - m_flYawRange; - } - m_flYawDir = SPOTLIGHT_SWING_FORWARD; - } - if (UTIL_AngleDistance( m_flPitch, m_flPitchCenter ) > m_flPitchMax) - { - if (m_fSpotlightFlags & BITS_SPOTLIGHT_SMOOTH_RETURN) - { - bInRange = false; - } - else - { - m_flPitch = m_flPitchCenter + m_flPitchMax; - } - m_flPitchDir = SPOTLIGHT_SWING_BACK; - } - else if (UTIL_AngleDistance( m_flPitch, m_flPitchCenter ) < m_flPitchMin) - { - if (m_fSpotlightFlags & BITS_SPOTLIGHT_SMOOTH_RETURN) - { - bInRange = false; - } - else - { - m_flPitch = m_flPitchCenter + m_flPitchMin; - } - m_flPitchDir = SPOTLIGHT_SWING_FORWARD; - } - - // If in range I'm done doing a smooth return - if (bInRange) - { - m_fSpotlightFlags &= ~BITS_SPOTLIGHT_SMOOTH_RETURN; - } - } - // Convert pitch and yaw to forward angle - QAngle vAngle = vec3_angle; - vAngle[YAW] = m_flYaw; - vAngle[PITCH] = m_flPitch; - AngleVectors( vAngle, &m_vSpotlightDir ); - - // --------------------------------------------- - // Get beam end point. Only collide with - // solid objects, not npcs - // --------------------------------------------- - trace_t tr; - AI_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + (m_vSpotlightDir * 2 * m_flSpotlightMaxLength), - (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTER|CONTENTS_DEBRIS), - this, COLLISION_GROUP_NONE, &tr); - - return (tr.endpos); -} - - -//------------------------------------------------------------------------------ -// Purpose : Update the direction and position of my spotlight -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_Spotlight::SpotlightUpdate(void) -{ - // --------------------------------------------------- - // Go back to idle state after a while - // --------------------------------------------------- - if (m_NPCState == NPC_STATE_ALERT && - m_flLastStateChangeTime + 30 < gpGlobals->curtime ) - { - SetState(NPC_STATE_IDLE); - } - - // --------------------------------------------------- - // If I don't have a spotlight attempt to create one - // --------------------------------------------------- - if (!m_pSpotlight && - m_fSpotlightFlags & BITS_SPOTLIGHT_LIGHT_ON ) - { - SpotlightCreate(); - } - if (!m_pSpotlight) - { - return; - } - - // ----------------------------------------------------- - // If spotlight flag is off destroy spotlight and exit - // ----------------------------------------------------- - if (!(m_fSpotlightFlags & BITS_SPOTLIGHT_LIGHT_ON)) - { - if (m_pSpotlight) - { - SpotlightDestroy(); - return; - } - } - - if (m_fSpotlightFlags & BITS_SPOTLIGHT_TRACK_ON) - { - // ------------------------------------------- - // Calculate the new spotlight position - // -------------------------------------------- - m_vSpotlightCurrentPos = SpotlightCurrentPos(); - } - // -------------------------------------------------------------- - // Update spotlight target velocity - // -------------------------------------------------------------- - Vector vTargetDir = (m_vSpotlightCurrentPos - m_pSpotlightTarget->GetAbsOrigin()); - float vTargetDist = vTargetDir.Length(); - - Vector vecNewVelocity = vTargetDir; - VectorNormalize(vecNewVelocity); - vecNewVelocity *= (10 * vTargetDist); - - // If a large move is requested, just jump to final spot as we - // probably hit a discontinuity - if (vecNewVelocity.Length() > 200) - { - VectorNormalize(vecNewVelocity); - vecNewVelocity *= 200; - VectorNormalize(vTargetDir); - m_pSpotlightTarget->SetLocalOrigin( m_vSpotlightCurrentPos ); - } - m_pSpotlightTarget->SetAbsVelocity( vecNewVelocity ); - m_pSpotlightTarget->m_vSpotlightOrg = GetAbsOrigin(); - - // Avoid sudden change in where beam fades out when cross disconinuities - m_pSpotlightTarget->m_vSpotlightDir = m_pSpotlightTarget->GetLocalOrigin() - m_pSpotlightTarget->m_vSpotlightOrg; - float flBeamLength = VectorNormalize( m_pSpotlightTarget->m_vSpotlightDir ); - m_flSpotlightCurLength = (0.60*m_flSpotlightCurLength) + (0.4*flBeamLength); - - // Fade out spotlight end if past max length. - if (m_flSpotlightCurLength > 2*m_flSpotlightMaxLength) - { - m_pSpotlightTarget->SetRenderColorA( 0 ); - m_pSpotlight->SetFadeLength(m_flSpotlightMaxLength); - } - else if (m_flSpotlightCurLength > m_flSpotlightMaxLength) - { - m_pSpotlightTarget->SetRenderColorA( (byte)((1-((m_flSpotlightCurLength-m_flSpotlightMaxLength)/m_flSpotlightMaxLength))) ); - m_pSpotlight->SetFadeLength(m_flSpotlightMaxLength); - } - else - { - m_pSpotlightTarget->SetRenderColorA( 1 ); - m_pSpotlight->SetFadeLength(m_flSpotlightCurLength); - } - - - // Adjust end width to keep beam width constant - float flNewWidth = m_flSpotlightGoalWidth*(flBeamLength/m_flSpotlightMaxLength); - m_pSpotlight->SetEndWidth(flNewWidth); - - // Adjust width of light on the end. - if ( FBitSet (m_spawnflags, SF_SPOTLIGHT_NO_DYNAMIC_LIGHT) ) - { - m_pSpotlightTarget->m_flLightScale = 0.0; - } - else - { - // <> - magic number 1.8 depends on sprite size - m_pSpotlightTarget->m_flLightScale = 1.8*flNewWidth; - } - - m_pOutputPosition.Set(m_pSpotlightTarget->GetLocalOrigin(),this,this); - -#ifdef SPOTLIGHT_DEBUG - NDebugOverlay::Cross3D(m_vSpotlightCurrentPos,Vector(-5,-5,-5),Vector(5,5,5),0,255,0,true,0.1); - NDebugOverlay::Cross3D(m_vSpotlightTargetPos,Vector(-5,-5,-5),Vector(5,5,5),255,0,0,true,0.1); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Spotlight::Spawn(void) -{ - // Check for user error - if (m_flSpotlightMaxLength <= 0) - { - DevMsg("CNPC_Spotlight::Spawn: Invalid spotlight length <= 0, setting to 500\n"); - m_flSpotlightMaxLength = 500; - } - - if (m_flSpotlightGoalWidth <= 0) - { - DevMsg("CNPC_Spotlight::Spawn: Invalid spotlight width <= 0, setting to 10\n"); - m_flSpotlightGoalWidth = 10; - } - - if (m_flSpotlightGoalWidth > MAX_BEAM_WIDTH) - { - DevMsg("CNPC_Spotlight::Spawn: Invalid spotlight width %.1f (max %.1f)\n", m_flSpotlightGoalWidth, MAX_BEAM_WIDTH ); - m_flSpotlightGoalWidth = MAX_BEAM_WIDTH; - } - - Precache(); - - // This is a dummy model that is never used! - SetModel( "models/player.mdl" ); - - // No Hull for now - UTIL_SetSize(this,vec3_origin,vec3_origin); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - m_bloodColor = DONT_BLEED; - SetViewOffset( Vector(0, 0, 10) ); // Position of the eyes relative to NPC's origin. - m_flFieldOfView = VIEW_FIELD_FULL; - m_NPCState = NPC_STATE_IDLE; - - CapabilitiesAdd( bits_CAP_SQUAD); - - // ------------------------------------ - // Init all class vars - // ------------------------------------ - m_vInspectPos = vec3_origin; - m_flInspectEndTime = 0; - m_flNextEntitySearchTime= gpGlobals->curtime + SPOTLIGHT_ENTITY_INSPECT_DELAY; - m_flNextHintSearchTime = gpGlobals->curtime + SPOTLIGHT_HINT_INSPECT_DELAY; - m_bHadEnemy = false; - - m_vSpotlightTargetPos = vec3_origin; - m_vSpotlightCurrentPos = vec3_origin; - m_pSpotlight = NULL; - m_pSpotlightTarget = NULL; - m_vSpotlightDir = vec3_origin; - //m_nHaloSprite // Set in precache - m_flSpotlightCurLength = m_flSpotlightMaxLength; - - m_flYaw = 0; - m_flYawSpeed = 0; - m_flYawCenter = GetLocalAngles().y; - m_flYawDir = random->RandomInt(0,1) ? 1 : -1; - //m_flYawRange = 90; // Keyfield in WC - - m_flPitch = 0; - m_flPitchSpeed = 0; - m_flPitchCenter = GetLocalAngles().x; - m_flPitchDir = random->RandomInt(0,1) ? 1 : -1; - //m_flPitchMin = 35; // Keyfield in WC - //m_flPitchMax = 50; // Keyfield in WC - //m_flIdleSpeed = 2; // Keyfield in WC - //m_flAlertSpeed = 5; // Keyfield in WC - - m_fSpotlightFlags = 0; - if (FBitSet ( m_spawnflags, SF_SPOTLIGHT_START_TRACK_ON )) - { - m_fSpotlightFlags |= BITS_SPOTLIGHT_TRACK_ON; - } - if (FBitSet ( m_spawnflags, SF_SPOTLIGHT_START_LIGHT_ON )) - { - m_fSpotlightFlags |= BITS_SPOTLIGHT_LIGHT_ON; - } - - // If I'm never moving just turn on the spotlight and don't think again - if (FBitSet ( m_spawnflags, SF_SPOTLIGHT_NEVER_MOVE )) - { - SpotlightCreate(); - } - else - { - NPCInit(); - SetThink(&CAI_BaseNPC::CallNPCThink); - } - - AddEffects( EF_NODRAW ); - SetMoveType( MOVETYPE_NONE ); - SetGravity( 0.0 ); -} - -//------------------------------------------------------------------------------ -// Purpose: Inputs -//------------------------------------------------------------------------------ -void CNPC_Spotlight::InputLightOn( inputdata_t &inputdata ) -{ - m_fSpotlightFlags |= BITS_SPOTLIGHT_LIGHT_ON; -} - -void CNPC_Spotlight::InputLightOff( inputdata_t &inputdata ) -{ - m_fSpotlightFlags &= ~BITS_SPOTLIGHT_LIGHT_ON; -} - -void CNPC_Spotlight::InputTrackOn( inputdata_t &inputdata ) -{ - m_fSpotlightFlags |= BITS_SPOTLIGHT_TRACK_ON; -} - -void CNPC_Spotlight::InputTrackOff( inputdata_t &inputdata ) -{ - m_fSpotlightFlags &= ~BITS_SPOTLIGHT_TRACK_ON; -} - - -//------------------------------------------------------------------------------ -// Purpose : Starts cremator doing scripted burn to a location -//------------------------------------------------------------------------------ -void CNPC_Spotlight::SetScriptedTarget( CScriptedTarget *pScriptedTarget ) -{ - if (pScriptedTarget) - { - m_pScriptedTarget = pScriptedTarget; - m_vSpotlightTargetPos = m_pScriptedTarget->GetAbsOrigin(); - } - else - { - m_pScriptedTarget = NULL; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: This is a generic function (to be implemented by sub-classes) to -// handle specific interactions between different types of characters -// (For example the barnacle grabbing an NPC) -// Input : Constant for the type of interaction -// Output : true - if sub-class has a response for the interaction -// false - if sub-class has no response -//----------------------------------------------------------------------------- -bool CNPC_Spotlight::HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt) -{ - if (interactionType == g_interactionScriptedTarget) - { - // If I already have a scripted target, reject the new one - if (m_pScriptedTarget && sourceEnt) - { - return false; - } - else - { - SetScriptedTarget((CScriptedTarget*)sourceEnt); - return true; - } - } - return false; -} diff --git a/game/server/hl2/npc_stalker.cpp b/game/server/hl2/npc_stalker.cpp deleted file mode 100644 index 4853d0677..000000000 --- a/game/server/hl2/npc_stalker.cpp +++ /dev/null @@ -1,1512 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "soundent.h" -#include "game.h" -#include "beam_shared.h" -#include "Sprite.h" -#include "npcevent.h" -#include "npc_stalker.h" -#include "ai_hull.h" -#include "ai_default.h" -#include "ai_node.h" -#include "ai_network.h" -#include "ai_hint.h" -#include "ai_link.h" -#include "ai_waypoint.h" -#include "ai_navigator.h" -#include "ai_senses.h" -#include "ai_squadslot.h" -#include "ai_squad.h" -#include "ai_memory.h" -#include "ai_tacticalservices.h" -#include "ai_moveprobe.h" -#include "npc_talker.h" -#include "activitylist.h" -#include "bitstring.h" -#include "decals.h" -#include "player.h" -#include "entitylist.h" -#include "ndebugoverlay.h" -#include "ai_interactions.h" -#include "animation.h" -#include "scriptedtarget.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "world.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//#define STALKER_DEBUG -#define MIN_STALKER_FIRE_RANGE 64 -#define MAX_STALKER_FIRE_RANGE 3600 // 3600 feet. -#define STALKER_LASER_ATTACHMENT 1 -#define STALKER_TRIGGER_DIST 200 // Enemy dist. that wakes up the stalker -#define STALKER_SENTENCE_VOLUME (float)0.35 -#define STALKER_LASER_DURATION 99999 -#define STALKER_LASER_RECHARGE 1 -#define STALKER_PLAYER_AGGRESSION 1 - -enum StalkerBeamPower_e -{ - STALKER_BEAM_LOW, - STALKER_BEAM_MED, - STALKER_BEAM_HIGH, -}; - -//Animation events -#define STALKER_AE_MELEE_HIT 1 - -ConVar sk_stalker_health( "sk_stalker_health","0"); -ConVar sk_stalker_melee_dmg( "sk_stalker_melee_dmg","0"); - -extern void SpawnBlood(Vector vecSpot, const Vector &vAttackDir, int bloodColor, float flDamage); - -LINK_ENTITY_TO_CLASS( npc_stalker, CNPC_Stalker ); - -float g_StalkerBeamThinkTime = 0.0; //0.025; - - -//========================================================= -// Private activities. -//========================================================= -static int ACT_STALKER_WORK = 0; - -//========================================================= -// Stalker schedules -//========================================================= -enum -{ - SCHED_STALKER_CHASE_ENEMY = LAST_SHARED_SCHEDULE, - SCHED_STALKER_RANGE_ATTACK, - SCHED_STALKER_ACQUIRE_PLAYER, - SCHED_STALKER_PATROL, -}; - -//========================================================= -// Stalker Tasks -//========================================================= -enum -{ - TASK_STALKER_ZIGZAG = LAST_SHARED_TASK, - TASK_STALKER_SCREAM, -}; - -// ----------------------------------------------- -// > Squad slots -// ----------------------------------------------- -enum SquadSlot_T -{ - SQUAD_SLOT_CHASE_ENEMY_1 = LAST_SHARED_SQUADSLOT, - SQUAD_SLOT_CHASE_ENEMY_2, -}; - -//----------------------------------------------------------------------------- - -BEGIN_DATADESC( CNPC_Stalker ) - - DEFINE_KEYFIELD( m_eBeamPower, FIELD_INTEGER, "BeamPower" ), - DEFINE_FIELD( m_vLaserDir, FIELD_VECTOR), - DEFINE_FIELD( m_vLaserTargetPos, FIELD_POSITION_VECTOR), - DEFINE_FIELD( m_fBeamEndTime, FIELD_FLOAT), - DEFINE_FIELD( m_fBeamRechargeTime, FIELD_FLOAT), - DEFINE_FIELD( m_fNextDamageTime, FIELD_FLOAT), - DEFINE_FIELD( m_bPlayingHitWall, FIELD_FLOAT), - DEFINE_FIELD( m_bPlayingHitFlesh, FIELD_FLOAT), - DEFINE_FIELD( m_pBeam, FIELD_CLASSPTR), - DEFINE_FIELD( m_pLightGlow, FIELD_CLASSPTR), - DEFINE_FIELD( m_flNextNPCThink, FIELD_FLOAT), - DEFINE_FIELD( m_vLaserCurPos, FIELD_POSITION_VECTOR), - DEFINE_FIELD( m_flNextAttackSoundTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextBreatheSoundTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextScrambleSoundTime, FIELD_TIME ), - DEFINE_FIELD( m_nextSmokeTime, FIELD_TIME ), - DEFINE_FIELD( m_iPlayerAggression, FIELD_INTEGER ), - DEFINE_FIELD( m_flNextScreamTime, FIELD_TIME ), - - // Function Pointers - DEFINE_THINKFUNC( StalkerThink ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int CNPC_Stalker::OnTakeDamage_Alive( const CTakeDamageInfo &inputInfo ) -{ - CTakeDamageInfo info = inputInfo; - - // -------------------------------------------- - // Don't take a lot of damage from Vortigaunt - // -------------------------------------------- - if (info.GetAttacker()->Classify() == CLASS_VORTIGAUNT) - { - info.ScaleDamage( 0.25 ); - } - - - int ret = BaseClass::OnTakeDamage_Alive( info ); - - // If player shot me make sure I'm mad at him even if I wasn't earlier - if ( (info.GetAttacker()->GetFlags() & FL_CLIENT) ) - { - AddClassRelationship( CLASS_PLAYER, D_HT, 0 ); - } - return ret; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CNPC_Stalker::MaxYawSpeed( void ) -{ -#ifdef HL2_EPISODIC - return 10.0f; -#else - switch( GetActivity() ) - { - case ACT_TURN_LEFT: - case ACT_TURN_RIGHT: - return 160; - break; - case ACT_RUN: - case ACT_RUN_HURT: - return 280; - break; - default: - return 160; - break; - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -// Output : int -//----------------------------------------------------------------------------- -Class_T CNPC_Stalker::Classify( void ) -{ - return CLASS_STALKER; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Stalker::PrescheduleThink() -{ - if (gpGlobals->curtime > m_flNextBreatheSoundTime) - { - EmitSound( "NPC_Stalker.Ambient01" ); - m_flNextBreatheSoundTime = gpGlobals->curtime + 3.0 + random->RandomFloat( 0.0, 5.0 ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Stalker::IsValidEnemy( CBaseEntity *pEnemy ) -{ - Class_T enemyClass = pEnemy->Classify(); - - if( enemyClass == CLASS_PLAYER || enemyClass == CLASS_PLAYER_ALLY || enemyClass == CLASS_PLAYER_ALLY_VITAL ) - { - // Don't get angry at these folks unless provoked. - if( m_iPlayerAggression < STALKER_PLAYER_AGGRESSION ) - { - return false; - } - } - - if( enemyClass == CLASS_BULLSEYE && pEnemy->GetParent() ) - { - // This bullseye is in heirarchy with something. If that - // something is held by the physcannon, this bullseye is - // NOT a valid enemy. - IPhysicsObject *pPhys = pEnemy->GetParent()->VPhysicsGetObject(); - if( pPhys && (pPhys->GetGameFlags() & FVPHYSICS_PLAYER_HELD) ) - { - return false; - } - } - - if( GetEnemy() && HasCondition(COND_SEE_ENEMY) ) - { - // Short attention span. If I have an enemy, stick with it. - if( GetEnemy() != pEnemy ) - { - return false; - } - } - - if( IsStrategySlotRangeOccupied( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) && !HasStrategySlotRange( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - { - return false; - } - - if( !FVisible(pEnemy) ) - { - // Don't take an enemy you can't see. Since stalkers move way too slowly to - // establish line of fire, usually an enemy acquired by means other than - // the Stalker's own eyesight will always get away while the stalker plods - // slowly to their last known position. So don't take enemies you can't see. - return false; - } - - return BaseClass::IsValidEnemy(pEnemy); -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CNPC_Stalker::Spawn( void ) -{ - Precache( ); - - SetModel( "models/stalker.mdl" ); - SetHullType(HULL_HUMAN); - SetHullSizeNormal(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - m_bloodColor = DONT_BLEED; - m_iHealth = sk_stalker_health.GetFloat(); - m_flFieldOfView = 0.1;// indicates the width of this NPC's forward view cone ( as a dotproduct result ) - m_NPCState = NPC_STATE_NONE; - CapabilitiesAdd( bits_CAP_SQUAD | bits_CAP_MOVE_GROUND ); - CapabilitiesAdd( bits_CAP_INNATE_RANGE_ATTACK1); - - m_flNextAttackSoundTime = 0; - m_flNextBreatheSoundTime = gpGlobals->curtime + random->RandomFloat( 0.0, 10.0 ); - m_flNextScrambleSoundTime = 0; - m_nextSmokeTime = 0; - m_bPlayingHitWall = false; - m_bPlayingHitFlesh = false; - - m_fBeamEndTime = 0; - m_fBeamRechargeTime = 0; - m_fNextDamageTime = 0; - - NPCInit(); - - m_flDistTooFar = MAX_STALKER_FIRE_RANGE; - - m_iPlayerAggression = 0; - - GetSenses()->SetDistLook(MAX_STALKER_FIRE_RANGE - 1); -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CNPC_Stalker::Precache( void ) -{ - PrecacheModel("models/stalker.mdl"); - PrecacheModel("sprites/laser.vmt"); - - PrecacheModel("sprites/redglow1.vmt"); - PrecacheModel("sprites/orangeglow1.vmt"); - PrecacheModel("sprites/yellowglow1.vmt"); - - PrecacheScriptSound( "NPC_Stalker.BurnFlesh" ); - PrecacheScriptSound( "NPC_Stalker.BurnWall" ); - PrecacheScriptSound( "NPC_Stalker.FootstepLeft" ); - PrecacheScriptSound( "NPC_Stalker.FootstepRight" ); - PrecacheScriptSound( "NPC_Stalker.Hit" ); - PrecacheScriptSound( "NPC_Stalker.Ambient01" ); - PrecacheScriptSound( "NPC_Stalker.Scream" ); - PrecacheScriptSound( "NPC_Stalker.Pain" ); - PrecacheScriptSound( "NPC_Stalker.Die" ); - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Stalker::CreateBehaviors() -{ - AddBehavior( &m_ActBusyBehavior ); - - return BaseClass::CreateBehaviors(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_Stalker::IdleSound ( void ) -{ -} - -void CNPC_Stalker::OnScheduleChange() -{ - KillAttackBeam(); - - BaseClass::OnScheduleChange(); -} -//----------------------------------------------------------------------------- -// Purpose: -// Input : pInflictor - -// pAttacker - -// flDamage - -// bitsDamageType - -//----------------------------------------------------------------------------- -void CNPC_Stalker::Event_Killed( const CTakeDamageInfo &info ) -{ - if( IsInSquad() && info.GetAttacker()->IsPlayer() ) - { - AISquadIter_t iter; - for ( CAI_BaseNPC *pSquadMember = GetSquad()->GetFirstMember( &iter ); pSquadMember; pSquadMember = GetSquad()->GetNextMember( &iter ) ) - { - if ( pSquadMember->IsAlive() && pSquadMember != this ) - { - CNPC_Stalker *pStalker = dynamic_cast (pSquadMember); - - if( pStalker && pStalker->FVisible(info.GetAttacker()) ) - { - pStalker->m_iPlayerAggression++; - } - } - } - } - - KillAttackBeam(); - BaseClass::Event_Killed( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_Stalker::DeathSound( const CTakeDamageInfo &info ) -{ - EmitSound( "NPC_Stalker.Die" ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_Stalker::PainSound( const CTakeDamageInfo &info ) -{ - EmitSound( "NPC_Stalker.Pain" ); - m_flNextScrambleSoundTime = gpGlobals->curtime + 1.5; - m_flNextBreatheSoundTime = gpGlobals->curtime + 1.5; - m_flNextAttackSoundTime = gpGlobals->curtime + 1.5; -}; - -//----------------------------------------------------------------------------- -// Purpose: Translates squad slot positions into schedules -// Input : -// Output : -//----------------------------------------------------------------------------- -#if 0 -// @TODO (toml 07-18-03): this function is never called. Presumably what it is trying to do still needs to be done... -int CNPC_Stalker::GetSlotSchedule(int slotID) -{ - switch (slotID) - { - - case SQUAD_SLOT_CHASE_ENEMY_1: - case SQUAD_SLOT_CHASE_ENEMY_2: - return SCHED_STALKER_CHASE_ENEMY; - break; - } - return SCHED_NONE; -} -#endif - - -void CNPC_Stalker::UpdateAttackBeam( void ) -{ - CBaseEntity *pEnemy = GetEnemy(); - // If not burning at a target - if (pEnemy) - { - if (gpGlobals->curtime > m_fBeamEndTime) - { - TaskComplete(); - } - else - { - Vector enemyLKP = GetEnemyLKP(); - m_vLaserTargetPos = enemyLKP + pEnemy->GetViewOffset(); - - // Face my enemy - GetMotor()->SetIdealYawToTargetAndUpdate( enemyLKP ); - - // --------------------------------------------- - // Get beam end point - // --------------------------------------------- - Vector vecSrc = LaserStartPosition(GetAbsOrigin()); - Vector targetDir = m_vLaserTargetPos - vecSrc; - VectorNormalize(targetDir); - // -------------------------------------------------------- - // If beam position and laser dir are way off, end attack - // -------------------------------------------------------- - if ( DotProduct(targetDir,m_vLaserDir) < 0.5 ) - { - TaskComplete(); - return; - } - - trace_t tr; - AI_TraceLine( vecSrc, vecSrc + m_vLaserDir * MAX_STALKER_FIRE_RANGE, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); - // --------------------------------------------- - // If beam not long enough, stop attacking - // --------------------------------------------- - if (tr.fraction == 1.0) - { - TaskComplete(); - return; - } - - CSoundEnt::InsertSound(SOUND_DANGER, tr.endpos, 60, 0.025, this); - } - } - else - { - TaskFail(FAIL_NO_ENEMY); - } -} - -//========================================================= -// start task -//========================================================= -void CNPC_Stalker::StartTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_STALKER_SCREAM: - { - if( gpGlobals->curtime > m_flNextScreamTime ) - { - EmitSound( "NPC_Stalker.Scream" ); - m_flNextScreamTime = gpGlobals->curtime + random->RandomFloat( 10.0, 15.0 ); - } - - TaskComplete(); - } - - case TASK_ANNOUNCE_ATTACK: - { - // If enemy isn't facing me and I haven't attacked in a while - // annouce my attack before I start wailing away - CBaseCombatCharacter *pBCC = GetEnemyCombatCharacterPointer(); - - if (pBCC && (!pBCC->FInViewCone ( this )) && - (gpGlobals->curtime - m_flLastAttackTime > 1.0) ) - { - m_flLastAttackTime = gpGlobals->curtime; - - // Always play this sound - EmitSound( "NPC_Stalker.Scream" ); - m_flNextScrambleSoundTime = gpGlobals->curtime + 2; - m_flNextBreatheSoundTime = gpGlobals->curtime + 2; - - // Wait two seconds - SetWait( 2.0 ); - SetActivity(ACT_IDLE); - } - break; - } - case TASK_STALKER_ZIGZAG: - break; - case TASK_RANGE_ATTACK1: - { - CBaseEntity *pEnemy = GetEnemy(); - if (pEnemy) - { - m_vLaserTargetPos = GetEnemyLKP() + pEnemy->GetViewOffset(); - - // Never hit target on first try - Vector missPos = m_vLaserTargetPos; - - if( pEnemy->Classify() == CLASS_BULLSEYE && hl2_episodic.GetBool() ) - { - missPos.x += 60 + 120*random->RandomInt(-1,1); - missPos.y += 60 + 120*random->RandomInt(-1,1); - } - else - { - missPos.x += 80*random->RandomInt(-1,1); - missPos.y += 80*random->RandomInt(-1,1); - } - - // ---------------------------------------------------------------------- - // If target is facing me and not running towards me shoot below his feet - // so he can see the laser coming - // ---------------------------------------------------------------------- - CBaseCombatCharacter *pBCC = ToBaseCombatCharacter(pEnemy); - if (pBCC) - { - Vector targetToMe = (pBCC->GetAbsOrigin() - GetAbsOrigin()); - Vector vBCCFacing = pBCC->BodyDirection2D( ); - if ((DotProduct(vBCCFacing,targetToMe) < 0) && - (pBCC->GetSmoothedVelocity().Length() < 50)) - { - missPos.z -= 150; - } - // -------------------------------------------------------- - // If facing away or running towards laser, - // shoot above target's head - // -------------------------------------------------------- - else - { - missPos.z += 60; - } - } - m_vLaserDir = missPos - LaserStartPosition(GetAbsOrigin()); - VectorNormalize(m_vLaserDir); - } - else - { - TaskFail(FAIL_NO_ENEMY); - return; - } - - StartAttackBeam(); - SetActivity(ACT_RANGE_ATTACK1); - break; - } - case TASK_GET_PATH_TO_ENEMY_LOS: - { - if ( GetEnemy() != NULL ) - { - BaseClass:: StartTask( pTask ); - return; - } - - Vector posLos; - - if (GetTacticalServices()->FindLos(m_vLaserCurPos, m_vLaserCurPos, MIN_STALKER_FIRE_RANGE, MAX_STALKER_FIRE_RANGE, 1.0, &posLos)) - { - AI_NavGoal_t goal( posLos, ACT_RUN, AIN_HULL_TOLERANCE ); - GetNavigator()->SetGoal( goal ); - } - else - { - TaskFail(FAIL_NO_SHOOT); - } - break; - } - case TASK_FACE_ENEMY: - { - if ( GetEnemy() != NULL ) - { - BaseClass:: StartTask( pTask ); - return; - } - GetMotor()->SetIdealYawToTarget( m_vLaserCurPos ); - break; - } - default: - BaseClass:: StartTask( pTask ); - break; - } -} - -//========================================================= -// RunTask -//========================================================= -void CNPC_Stalker::RunTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_ANNOUNCE_ATTACK: - { - // Stop waiting if enemy facing me or lost enemy - CBaseCombatCharacter* pBCC = GetEnemyCombatCharacterPointer(); - if (!pBCC || pBCC->FInViewCone( this )) - { - TaskComplete(); - } - - if ( IsWaitFinished() ) - { - TaskComplete(); - } - break; - } - - case TASK_STALKER_ZIGZAG : - { - - if (GetNavigator()->GetGoalType() == GOALTYPE_NONE) - { - TaskComplete(); - GetNavigator()->StopMoving(); // Stop moving - } - else if (!GetNavigator()->IsGoalActive()) - { - SetIdealActivity( GetStoppedActivity() ); - } - else if (ValidateNavGoal()) - { - SetIdealActivity( GetNavigator()->GetMovementActivity() ); - AddZigZagToPath(); - } - break; - } - case TASK_RANGE_ATTACK1: - UpdateAttackBeam(); - if ( !TaskIsRunning() || HasCondition( COND_TASK_FAILED )) - { - KillAttackBeam(); - } - break; - - case TASK_FACE_ENEMY: - { - if ( GetEnemy() != NULL ) - { - BaseClass:: RunTask( pTask ); - return; - } - GetMotor()->SetIdealYawToTargetAndUpdate( m_vLaserCurPos ); - - if ( FacingIdeal() ) - { - TaskComplete(); - } - break; - } - default: - { - BaseClass::RunTask( pTask ); - break; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int CNPC_Stalker::SelectSchedule( void ) -{ - if ( BehaviorSelectSchedule() ) - { - return BaseClass::SelectSchedule(); - } - - switch ( m_NPCState ) - { - case NPC_STATE_IDLE: - case NPC_STATE_ALERT: - { - if( HasCondition(COND_IN_PVS) ) - { - return SCHED_STALKER_PATROL; - } - - return SCHED_IDLE_STAND; - - break; - } - - case NPC_STATE_COMBAT: - { - // ----------- - // new enemy - // ----------- - if( HasCondition( COND_NEW_ENEMY ) ) - { - if( GetEnemy()->IsPlayer() ) - { - return SCHED_STALKER_ACQUIRE_PLAYER; - } - } - - if( HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - { - if( OccupyStrategySlotRange(SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2) ) - { - return SCHED_RANGE_ATTACK1; - } - else - { - return SCHED_STALKER_PATROL; - } - } - - if( !HasCondition(COND_SEE_ENEMY) ) - { - return SCHED_STALKER_PATROL; - } - - return SCHED_COMBAT_FACE; - - break; - } - - default: - break; - } - - // no special cases here, call the base class - return BaseClass::SelectSchedule(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int CNPC_Stalker::TranslateSchedule( int scheduleType ) -{ - switch( scheduleType ) - { - case SCHED_RANGE_ATTACK1: - { - return SCHED_STALKER_RANGE_ATTACK; - } - case SCHED_FAIL_ESTABLISH_LINE_OF_FIRE: - { - return SCHED_COMBAT_STAND; - break; - } - case SCHED_FAIL_TAKE_COVER: - { - return SCHED_RUN_RANDOM; - break; - } - } - - return BaseClass::TranslateSchedule( scheduleType ); -} - -//------------------------------------------------------------------------------ -// Purpose : Returns position of laser for any given position of the staler -// Input : -// Output : -//------------------------------------------------------------------------------ -Vector CNPC_Stalker::LaserStartPosition(Vector vStalkerPos) -{ - // Get attachment position - Vector vAttachPos; - GetAttachment(STALKER_LASER_ATTACHMENT,vAttachPos); - - // Now convert to vStalkerPos - vAttachPos = vAttachPos - GetAbsOrigin() + vStalkerPos; - return vAttachPos; -} - -//------------------------------------------------------------------------------ -// Purpose : Calculate position of beam -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_Stalker::CalcBeamPosition(void) -{ - Vector targetDir = m_vLaserTargetPos - LaserStartPosition(GetAbsOrigin()); - VectorNormalize(targetDir); - - // --------------------------------------- - // Otherwise if burning towards an enemy - // --------------------------------------- - if ( GetEnemy() ) - { - // --------------------------------------- - // Integrate towards target position - // --------------------------------------- - float iRate = 0.95; - - if( GetEnemy()->Classify() == CLASS_BULLSEYE ) - { - // Seek bullseyes faster - iRate = 0.8; - } - - m_vLaserDir.x = (iRate * m_vLaserDir.x + (1-iRate) * targetDir.x); - m_vLaserDir.y = (iRate * m_vLaserDir.y + (1-iRate) * targetDir.y); - m_vLaserDir.z = (iRate * m_vLaserDir.z + (1-iRate) * targetDir.z); - VectorNormalize( m_vLaserDir ); - - // ----------------------------------------- - // Add time-coherent noise to the position - // Must be scaled with distance - // ----------------------------------------- - float fTargetDist = (GetAbsOrigin() - m_vLaserTargetPos).Length(); - float noiseScale = atan(0.2/fTargetDist); - float m_fNoiseModX = 5; - float m_fNoiseModY = 5; - float m_fNoiseModZ = 5; - - m_vLaserDir.x += 5*noiseScale*sin(m_fNoiseModX * gpGlobals->curtime + m_fNoiseModX); - m_vLaserDir.y += 5*noiseScale*sin(m_fNoiseModY * gpGlobals->curtime + m_fNoiseModY); - m_vLaserDir.z += 5*noiseScale*sin(m_fNoiseModZ * gpGlobals->curtime + m_fNoiseModZ); - } -} - - -void CNPC_Stalker::StartAttackBeam( void ) -{ - if ( m_fBeamEndTime > gpGlobals->curtime || m_fBeamRechargeTime > gpGlobals->curtime ) - { - // UNDONE: Debug this and fix!?!?! - m_fBeamRechargeTime = gpGlobals->curtime; - } - // --------------------------------------------- - // If I don't have a beam yet, create one - // --------------------------------------------- - // UNDONE: Why would I ever have a beam already?!?!?! - if (!m_pBeam) - { - Vector vecSrc = LaserStartPosition(GetAbsOrigin()); - trace_t tr; - AI_TraceLine ( vecSrc, vecSrc + m_vLaserDir * MAX_STALKER_FIRE_RANGE, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); - if ( tr.fraction >= 1.0 ) - { - // too far - TaskComplete(); - return; - } - - m_pBeam = CBeam::BeamCreate( "sprites/laser.vmt", 2.0 ); - m_pBeam->PointEntInit( tr.endpos, this ); - m_pBeam->SetEndAttachment( STALKER_LASER_ATTACHMENT ); - m_pBeam->SetBrightness( 255 ); - m_pBeam->SetNoise( 0 ); - - switch (m_eBeamPower) - { - case STALKER_BEAM_LOW: - m_pBeam->SetColor( 255, 0, 0 ); - m_pLightGlow = CSprite::SpriteCreate( "sprites/redglow1.vmt", GetAbsOrigin(), FALSE ); - break; - case STALKER_BEAM_MED: - m_pBeam->SetColor( 255, 50, 0 ); - m_pLightGlow = CSprite::SpriteCreate( "sprites/orangeglow1.vmt", GetAbsOrigin(), FALSE ); - break; - case STALKER_BEAM_HIGH: - m_pBeam->SetColor( 255, 150, 0 ); - m_pLightGlow = CSprite::SpriteCreate( "sprites/yellowglow1.vmt", GetAbsOrigin(), FALSE ); - break; - } - - // ---------------------------- - // Light myself in a red glow - // ---------------------------- - m_pLightGlow->SetTransparency( kRenderGlow, 255, 200, 200, 0, kRenderFxNoDissipation ); - m_pLightGlow->SetAttachment( this, 1 ); - m_pLightGlow->SetBrightness( 255 ); - m_pLightGlow->SetScale( 0.65 ); - -#if 0 - CBaseEntity *pEnemy = GetEnemy(); - // -------------------------------------------------------- - // Play start up sound - client should always hear this! - // -------------------------------------------------------- - if (pEnemy != NULL && (pEnemy->IsPlayer()) ) - { - EmitAmbientSound( 0, pEnemy->GetAbsOrigin(), "NPC_Stalker.AmbientLaserStart" ); - } - else - { - EmitAmbientSound( 0, GetAbsOrigin(), "NPC_Stalker.AmbientLaserStart" ); - } -#endif - } - - SetThink( &CNPC_Stalker::StalkerThink ); - - m_flNextNPCThink = GetNextThink(); - SetNextThink( gpGlobals->curtime + g_StalkerBeamThinkTime ); - m_fBeamEndTime = gpGlobals->curtime + STALKER_LASER_DURATION; -} - -//------------------------------------------------------------------------------ -// Purpose : Update beam more often then regular NPC think so it doesn't -// move so jumpily over the ground -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_Stalker::StalkerThink(void) -{ - DrawAttackBeam(); - if (gpGlobals->curtime >= m_flNextNPCThink) - { - NPCThink(); - m_flNextNPCThink = GetNextThink(); - } - - if ( m_pBeam ) - { - SetNextThink( gpGlobals->curtime + g_StalkerBeamThinkTime ); - - // sanity check?! - const Task_t *pTask = GetTask(); - if ( !pTask || pTask->iTask != TASK_RANGE_ATTACK1 || !TaskIsRunning() ) - { - KillAttackBeam(); - } - } - else - { - DevMsg( 2, "In StalkerThink() but no stalker beam found?\n" ); - SetNextThink( m_flNextNPCThink ); - } -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CNPC_Stalker::NotifyDeadFriend( CBaseEntity *pFriend ) -{ - BaseClass::NotifyDeadFriend(pFriend); -} - -void CNPC_Stalker::DoSmokeEffect( const Vector &position ) -{ - if ( gpGlobals->curtime > m_nextSmokeTime ) - { - m_nextSmokeTime = gpGlobals->curtime + 0.5; - UTIL_Smoke(position, random->RandomInt(5, 10), 10); - } -} - -//------------------------------------------------------------------------------ -// Purpose : Draw attack beam and do damage / decals -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_Stalker::DrawAttackBeam(void) -{ - if (!m_pBeam) - return; - - // --------------------------------------------- - // Get beam end point - // --------------------------------------------- - Vector vecSrc = LaserStartPosition(GetAbsOrigin()); - trace_t tr; - AI_TraceLine( vecSrc, vecSrc + m_vLaserDir * MAX_STALKER_FIRE_RANGE, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); - - CalcBeamPosition(); - - bool bInWater = (UTIL_PointContents ( tr.endpos ) & MASK_WATER)?true:false; - // --------------------------------------------- - // Update the beam position - // --------------------------------------------- - m_pBeam->SetStartPos( tr.endpos ); - m_pBeam->RelinkBeam(); - - Vector vAttachPos; - GetAttachment(STALKER_LASER_ATTACHMENT,vAttachPos); - - Vector vecAimDir = tr.endpos - vAttachPos; - VectorNormalize( vecAimDir ); - - SetAim( vecAimDir ); - - // -------------------------------------------- - // Play burn sounds - // -------------------------------------------- - CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( tr.m_pEnt ); - if (pBCC) - { - if (gpGlobals->curtime > m_fNextDamageTime) - { - ClearMultiDamage(); - - float damage = 0.0; - switch (m_eBeamPower) - { - case STALKER_BEAM_LOW: - damage = 1; - break; - case STALKER_BEAM_MED: - damage = 3; - break; - case STALKER_BEAM_HIGH: - damage = 10; - break; - } - - CTakeDamageInfo info( this, this, damage, DMG_SHOCK ); - CalculateMeleeDamageForce( &info, m_vLaserDir, tr.endpos ); - pBCC->DispatchTraceAttack( info, m_vLaserDir, &tr ); - ApplyMultiDamage(); - m_fNextDamageTime = gpGlobals->curtime + 0.1; - } - if (pBCC->Classify()!=CLASS_BULLSEYE) - { - if (!m_bPlayingHitFlesh) - { - CPASAttenuationFilter filter( m_pBeam,"NPC_Stalker.BurnFlesh" ); - filter.MakeReliable(); - - EmitSound( filter, m_pBeam->entindex(),"NPC_Stalker.BurnFlesh" ); - m_bPlayingHitFlesh = true; - } - if (m_bPlayingHitWall) - { - StopSound( m_pBeam->entindex(), "NPC_Stalker.BurnWall" ); - m_bPlayingHitWall = false; - } - - tr.endpos.z -= 24.0f; - if (!bInWater) - { - DoSmokeEffect(tr.endpos + tr.plane.normal * 8); - } - } - } - - if (!pBCC || pBCC->Classify()==CLASS_BULLSEYE) - { - if (!m_bPlayingHitWall) - { - CPASAttenuationFilter filter( m_pBeam, "NPC_Stalker.BurnWall" ); - filter.MakeReliable(); - - EmitSound( filter, m_pBeam->entindex(), "NPC_Stalker.BurnWall" ); - m_bPlayingHitWall = true; - } - if (m_bPlayingHitFlesh) - { - StopSound(m_pBeam->entindex(), "NPC_Stalker.BurnFlesh" ); - m_bPlayingHitFlesh = false; - } - - UTIL_DecalTrace( &tr, "RedGlowFade"); - UTIL_DecalTrace( &tr, "FadingScorch" ); - - tr.endpos.z -= 24.0f; - if (!bInWater) - { - DoSmokeEffect(tr.endpos + tr.plane.normal * 8); - } - } - - if (bInWater) - { - UTIL_Bubbles(tr.endpos-Vector(3,3,3),tr.endpos+Vector(3,3,3),10); - } - - /* - CBroadcastRecipientFilter filter; - TE_DynamicLight( filter, 0.0, EyePosition(), 255, 0, 0, 5, 0.2, 0 ); - */ -} - -//------------------------------------------------------------------------------ -// Purpose : Draw attack beam and do damage / decals -// Input : -// Output : -//------------------------------------------------------------------------------ -void CNPC_Stalker::KillAttackBeam(void) -{ - if ( !m_pBeam ) - return; - - // Kill sound - StopSound(m_pBeam->entindex(), "NPC_Stalker.BurnWall" ); - StopSound(m_pBeam->entindex(), "NPC_Stalker.BurnFlesh" ); - - UTIL_Remove( m_pLightGlow ); - UTIL_Remove( m_pBeam); - m_pBeam = NULL; - m_bPlayingHitWall = false; - m_bPlayingHitFlesh = false; - - SetThink(&CNPC_Stalker::CallNPCThink); - if ( m_flNextNPCThink > gpGlobals->curtime ) - { - SetNextThink( m_flNextNPCThink ); - } - - // Beam has to recharge - m_fBeamRechargeTime = gpGlobals->curtime + STALKER_LASER_RECHARGE; - - ClearCondition( COND_CAN_RANGE_ATTACK1 ); - - RelaxAim(); -} - -//----------------------------------------------------------------------------- -// Purpose: Override so can handle LOS to m_pScriptedTarget -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CNPC_Stalker::InnateWeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions ) -{ - // -------------------- - // Check for occlusion - // -------------------- - // Base class version assumes innate weapon position is at eye level - Vector barrelPos = LaserStartPosition(ownerPos); - trace_t tr; - AI_TraceLine( barrelPos, targetPos, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); - - if ( tr.fraction == 1.0 ) - { - return true; - } - - CBaseEntity *pBE = tr.m_pEnt; - CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pBE ); - if ( pBE == GetEnemy() ) - { - return true; - } - else if (pBCC) - { - if (IRelationType( pBCC ) == D_HT) - { - return true; - } - else if (bSetConditions) - { - SetCondition(COND_WEAPON_BLOCKED_BY_FRIEND); - } - } - else if (bSetConditions) - { - SetCondition(COND_WEAPON_SIGHT_OCCLUDED); - SetEnemyOccluder(pBE); - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: For innate melee attack -// Input : -// Output : -//----------------------------------------------------------------------------- -int CNPC_Stalker::MeleeAttack1Conditions ( float flDot, float flDist ) -{ - if (flDist > MIN_STALKER_FIRE_RANGE) - { - return COND_TOO_FAR_TO_ATTACK; - } - else if (flDot < 0.7) - { - return COND_NOT_FACING_ATTACK; - } - return COND_CAN_MELEE_ATTACK1; -} - -//----------------------------------------------------------------------------- -// Purpose: For innate range attack -// Input : -// Output : -//----------------------------------------------------------------------------- -int CNPC_Stalker::RangeAttack1Conditions( float flDot, float flDist ) -{ - if (gpGlobals->curtime < m_fBeamRechargeTime ) - { - return COND_NONE; - } - - if( IsStrategySlotRangeOccupied( SQUAD_SLOT_ATTACK1, SQUAD_SLOT_ATTACK2 ) ) - { - // Couldn't attack if I wanted to. - return COND_NONE; - } - - if (flDist <= MIN_STALKER_FIRE_RANGE) - { - return COND_TOO_CLOSE_TO_ATTACK; - } - else if (flDist > (MAX_STALKER_FIRE_RANGE * 0.66f) ) - { - return COND_TOO_FAR_TO_ATTACK; - } - else if (flDot < 0.7) - { - return COND_NOT_FACING_ATTACK; - } - return COND_CAN_RANGE_ATTACK1; -} - -//----------------------------------------------------------------------------- -// Purpose: Catch stalker specific messages -// Input : -// Output : -//----------------------------------------------------------------------------- -void CNPC_Stalker::HandleAnimEvent( animevent_t *pEvent ) -{ - switch( pEvent->event ) - { - case NPC_EVENT_LEFTFOOT: - { - EmitSound( "NPC_Stalker.FootstepLeft", pEvent->eventtime ); - } - break; - case NPC_EVENT_RIGHTFOOT: - { - EmitSound( "NPC_Stalker.FootstepRight", pEvent->eventtime ); - } - break; - - case STALKER_AE_MELEE_HIT: - { - CBaseEntity *pHurt; - - pHurt = CheckTraceHullAttack( 32, Vector(-16,-16,-16), Vector(16,16,16), sk_stalker_melee_dmg.GetInt(), DMG_SLASH ); - - if ( pHurt ) - { - if ( pHurt->GetFlags() & (FL_NPC|FL_CLIENT) ) - { - pHurt->ViewPunch( QAngle( 5, 0, random->RandomInt(-10,10)) ); - } - - // Spawn some extra blood if we hit a BCC - CBaseCombatCharacter* pBCC = ToBaseCombatCharacter( pHurt ); - if (pBCC) - { - SpawnBlood(pBCC->EyePosition(), g_vecAttackDir, pBCC->BloodColor(), sk_stalker_melee_dmg.GetFloat()); - } - - // Play a attack hit sound - EmitSound( "NPC_Stalker.Hit" ); - } - break; - } - default: - BaseClass::HandleAnimEvent( pEvent ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Tells use whether or not the NPC cares about a given type of hint node. -// Input : sHint - -// Output : TRUE if the NPC is interested in this hint type, FALSE if not. -//----------------------------------------------------------------------------- -bool CNPC_Stalker::FValidateHintType(CAI_Hint *pHint) -{ - return(pHint->HintType() == HINT_WORLD_WORK_POSITION); -} - -//----------------------------------------------------------------------------- -// Purpose: Override in subclasses to associate specific hint types -// with activities -// Input : -// Output : -//----------------------------------------------------------------------------- -Activity CNPC_Stalker::GetHintActivity( short sHintType, Activity HintsActivity ) -{ - if (sHintType == HINT_WORLD_WORK_POSITION) - { - return ( Activity )ACT_STALKER_WORK; - } - - return BaseClass::GetHintActivity( sHintType, HintsActivity ); -} - -//----------------------------------------------------------------------------- -// Purpose: Override in subclasses to give specific hint types delays -// before they can be used again -// Input : -// Output : -//----------------------------------------------------------------------------- -float CNPC_Stalker::GetHintDelay( short sHintType ) -{ - if (sHintType == HINT_WORLD_WORK_POSITION) - { - return 2.0; - } - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -#define ZIG_ZAG_SIZE 3600 - -void CNPC_Stalker::AddZigZagToPath(void) -{ - // If already on a detour don't add a zigzag - if (GetNavigator()->GetCurWaypointFlags() & bits_WP_TO_DETOUR) - { - return; - } - - // If enemy isn't facing me or occluded, don't add a zigzag - if (HasCondition(COND_ENEMY_OCCLUDED) || !HasCondition ( COND_ENEMY_FACING_ME )) - { - return; - } - - Vector waypointPos = GetNavigator()->GetCurWaypointPos(); - Vector waypointDir = (waypointPos - GetAbsOrigin()); - - // If the distance to the next node is greater than ZIG_ZAG_SIZE - // then add a random zig/zag to the path - if (waypointDir.LengthSqr() > ZIG_ZAG_SIZE) - { - // Pick a random distance for the zigzag (less that sqrt(ZIG_ZAG_SIZE) - float distance = random->RandomFloat( 30, 60 ); - - // Get me a vector orthogonal to the direction of motion - VectorNormalize( waypointDir ); - Vector vDirUp(0,0,1); - Vector vDir; - CrossProduct( waypointDir, vDirUp, vDir); - - // Pick a random direction (left/right) for the zigzag - if (random->RandomInt(0,1)) - { - vDir = -1 * vDir; - } - - // Get zigzag position in direction of target waypoint - Vector zigZagPos = GetAbsOrigin() + waypointDir * 60; - - // Now offset - zigZagPos = zigZagPos + (vDir * distance); - - // Now make sure that we can still get to the zigzag position and the waypoint - AIMoveTrace_t moveTrace1, moveTrace2; - GetMoveProbe()->MoveLimit( NAV_GROUND, GetAbsOrigin(), zigZagPos, MASK_NPCSOLID, NULL, &moveTrace1); - GetMoveProbe()->MoveLimit( NAV_GROUND, zigZagPos, waypointPos, MASK_NPCSOLID, NULL, &moveTrace2); - if ( !IsMoveBlocked( moveTrace1 ) && !IsMoveBlocked( moveTrace2 ) ) - { - GetNavigator()->PrependWaypoint( zigZagPos, NAV_GROUND, bits_WP_TO_DETOUR ); - } - } -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -CNPC_Stalker::CNPC_Stalker(void) -{ -#ifdef _DEBUG - m_vLaserDir.Init(); - m_vLaserTargetPos.Init(); - m_vLaserCurPos.Init(); -#endif -} - - -//------------------------------------------------------------------------------ -// -// Schedules -// -//------------------------------------------------------------------------------ - -AI_BEGIN_CUSTOM_NPC( npc_stalker, CNPC_Stalker ) - - DECLARE_TASK(TASK_STALKER_ZIGZAG) - DECLARE_TASK(TASK_STALKER_SCREAM) - - DECLARE_ACTIVITY(ACT_STALKER_WORK) - - DECLARE_SQUADSLOT(SQUAD_SLOT_CHASE_ENEMY_1) - DECLARE_SQUADSLOT(SQUAD_SLOT_CHASE_ENEMY_2) - - - //========================================================= - // > SCHED_STALKER_RANGE_ATTACK - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_STALKER_RANGE_ATTACK, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_RANGE_ATTACK1 0" - "" - " Interrupts" - " COND_CAN_MELEE_ATTACK1" - " COND_HEAVY_DAMAGE" - " COND_REPEATED_DAMAGE" - " COND_HEAR_DANGER" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_ENEMY_OCCLUDED" // Don't break on this. Keep shooting at last location - ) - - //========================================================= - // > SCHED_STALKER_CHASE_ENEMY - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_STALKER_CHASE_ENEMY, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_CHASE_ENEMY_FAILED" - " TASK_SET_TOLERANCE_DISTANCE 24" - " TASK_GET_PATH_TO_ENEMY 0" - " TASK_RUN_PATH 0" - " TASK_STALKER_ZIGZAG 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK2" - " COND_TOO_CLOSE_TO_ATTACK" - " COND_TASK_FAILED" - " COND_HEAR_DANGER" - ) - - DEFINE_SCHEDULE - ( - SCHED_STALKER_ACQUIRE_PLAYER, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_ENEMY 0" - " TASK_WAIT_RANDOM 0.5" - " TASK_STALKER_SCREAM 0" - " TASK_WAIT 0.5" - " TASK_WAIT_RANDOM 0.5" - "" - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_STALKER_PATROL, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_WAIT 0.5"// This makes them look a bit more vigilant, instead of INSTANTLY patrolling after some other action. - " TASK_WAIT_RANDOM 0.5" - " TASK_WANDER 18000600" - " TASK_FACE_PATH 0" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STOP_MOVING 0" - " TASK_FACE_REASONABLE 0" - " TASK_SET_SCHEDULE SCHEDULE:SCHED_STALKER_PATROL" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_CAN_RANGE_ATTACK1" - " COND_SEE_ENEMY" - ) - -AI_END_CUSTOM_NPC() diff --git a/game/server/hl2/npc_stalker.h b/game/server/hl2/npc_stalker.h deleted file mode 100644 index 3d42ae66b..000000000 --- a/game/server/hl2/npc_stalker.h +++ /dev/null @@ -1,115 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef NPC_STALKER_H -#define NPC_STALKER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_basenpc.h" -#include "entityoutput.h" -#include "ai_behavior.h" -#include "ai_behavior_actbusy.h" - -class CBeam; -class CSprite; -class CScriptedTarget; - -typedef CAI_BehaviorHost CAI_BaseStalker; - -class CNPC_Stalker : public CAI_BaseStalker -{ - DECLARE_CLASS( CNPC_Stalker, CAI_BaseStalker ); - -public: - float m_flNextAttackSoundTime; - float m_flNextBreatheSoundTime; - float m_flNextScrambleSoundTime; - float m_flNextNPCThink; - - // ------------------------------ - // Laser Beam - // ------------------------------ - int m_eBeamPower; - Vector m_vLaserDir; - Vector m_vLaserTargetPos; - float m_fBeamEndTime; - float m_fBeamRechargeTime; - float m_fNextDamageTime; - float m_nextSmokeTime; - float m_bPlayingHitWall; - float m_bPlayingHitFlesh; - CBeam* m_pBeam; - CSprite* m_pLightGlow; - int m_iPlayerAggression; - float m_flNextScreamTime; - - void KillAttackBeam(void); - void DrawAttackBeam(void); - void CalcBeamPosition(void); - Vector LaserStartPosition(Vector vStalkerPos); - - Vector m_vLaserCurPos; // Last position successfully burned - bool InnateWeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions ); - - // ------------------------------ - // Dormancy - // ------------------------------ - CAI_Schedule* WakeUp(void); - void GoDormant(void); - -public: - void Spawn( void ); - void Precache( void ); - bool CreateBehaviors(); - float MaxYawSpeed( void ); - Class_T Classify ( void ); - - void PrescheduleThink(); - - bool IsValidEnemy( CBaseEntity *pEnemy ); - - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - virtual int SelectSchedule ( void ); - virtual int TranslateSchedule( int scheduleType ); - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - void OnScheduleChange(); - - void StalkerThink(void); - void NotifyDeadFriend( CBaseEntity *pFriend ); - - int MeleeAttack1Conditions ( float flDot, float flDist ); - int RangeAttack1Conditions ( float flDot, float flDist ); - void HandleAnimEvent( animevent_t *pEvent ); - - bool FValidateHintType(CAI_Hint *pHint); - Activity GetHintActivity( short sHintType, Activity HintsActivity ); - float GetHintDelay( short sHintType ); - - void IdleSound( void ); - void DeathSound( const CTakeDamageInfo &info ); - void PainSound( const CTakeDamageInfo &info ); - - void Event_Killed( const CTakeDamageInfo &info ); - void DoSmokeEffect( const Vector &position ); - - void AddZigZagToPath(void); - void StartAttackBeam(); - void UpdateAttackBeam(); - - CNPC_Stalker(void); - - DECLARE_DATADESC(); - DEFINE_CUSTOM_AI; - -private: - CAI_ActBusyBehavior m_ActBusyBehavior; -}; - -#endif // NPC_STALKER_H diff --git a/game/server/hl2/npc_strider.cpp b/game/server/hl2/npc_strider.cpp deleted file mode 100644 index 4aedc5aff..000000000 --- a/game/server/hl2/npc_strider.cpp +++ /dev/null @@ -1,5745 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Giant walking strider thing! -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -#include "npc_strider.h" - -#include "ai_senses.h" -#include "ai_task.h" -#include "ai_default.h" -#include "ai_schedule.h" -#include "ai_hull.h" -#include "ai_basenpc.h" -#include "ai_pathfinder.h" -#include "ai_waypoint.h" -#include "ai_link.h" -#include "ai_hint.h" -#include "ai_tacticalservices.h" -#include "ai_behavior_follow.h" -#include "simtimer.h" -#include "trains.h" -#include "npcevent.h" -#include "te_particlesystem.h" -#include "shake.h" -#include "soundent.h" -#include "IEffects.h" -#include "engine/IEngineSound.h" -#include "bone_setup.h" -#include "vcollide_parse.h" -#include "studio.h" -#include "physics_bone_follower.h" -#include "ai_navigator.h" -#include "ai_route.h" -#include "ammodef.h" -#include "npc_bullseye.h" -#include "rope.h" -#include "ai_memory.h" -#include "player_pickup.h" -#include "collisionutils.h" -#include "in_buttons.h" -#include "steamjet.h" -#include "physics_prop_ragdoll.h" -#include "vehicle_base.h" -#include "coordsize.h" -#include "hl2_shareddefs.h" -#include "te_effect_dispatch.h" -#include "beam_flags.h" -#include "prop_combine_ball.h" -#include "explode.h" -#include "filters.h" -#include "saverestore_utlvector.h" -#include "eventqueue.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -int g_interactionPlayerLaunchedRPG = 0; - -// Changing this classname avoids bugs where ai_relationship entities that change the -// strider's relationship with bullseyes would affect its relationship with the focus -LINK_ENTITY_TO_CLASS( bullseye_strider_focus, CNPC_Bullseye ); - - -//----------------------------------------------------------------------------- - -ConVar strider_immolate( "strider_immolate", "0" ); -ConVar sk_strider_health( "sk_strider_health", "350" ); -ConVar npc_strider_height_adj("npc_strider_height_adj", "0" ); -ConVar strider_eyepositions( "strider_eyepositions", "0" ); -ConVar strider_show_focus( "strider_show_focus", "0" ); -ConVar strider_distributed_fire( "strider_distributed_fire", "1" ); -ConVar strider_show_cannonlos( "strider_show_cannonlos", "0" ); -ConVar strider_show_weapon_los_z( "strider_show_weapon_los_z", "0" ); -ConVar strider_show_weapon_los_condition( "strider_show_weapon_los_condition", "0" ); -ConVar strider_idle_test( "strider_idle_test", "0" ); -ConVar strider_always_use_procedural_height( "strider_always_use_procedural_height", "0" ); -ConVar strider_test_height( "strider_test_height", "0" ); -ConVar strider_pct_height_no_crouch_move( "strider_pct_height_no_crouch_move", "90" ); - -ConVar strider_peek_time( "strider_peek_time", "0.75" ); -ConVar strider_peek_time_after_damage( "strider_peek_time_after_damage", "4.0" ); -ConVar strider_peek_eye_dist( "strider_peek_eye_dist", "1.75" ); -ConVar strider_peek_eye_dist_z( "strider_peek_eye_dist_z", "4.0" ); -ConVar strider_free_pass_start_time( "strider_free_pass_start_time", "3" ); -ConVar strider_free_pass_cover_dist( "strider_free_pass_cover_dist", "120" ); -ConVar strider_free_pass_duration( "strider_free_pass_duration", "2" ); -ConVar strider_free_pass_refill_rate( "strider_free_pass_refill_rate", "0.5" ); -ConVar strider_free_pass_move_tolerance( "strider_free_pass_move_tolerance", "320" ); -ConVar strider_free_knowledge( "strider_free_knowledge", "0.5" ); - -ConVar strider_free_pass_after_escorts_dead( "strider_free_pass_after_escorts_dead", "2.5" ); -ConVar strider_free_pass_tolerance_after_escorts_dead( "strider_free_pass_tolerance_after_escorts_dead", "600" ); - -ConVar npc_strider_shake_ropes_radius( "npc_strider_shake_ropes_radius", "1200" ); -ConVar npc_strider_shake_ropes_magnitude( "npc_strider_shake_ropes_magnitude", "150" ); - -ConVar strider_ar2_altfire_dmg( "strider_ar2_altfire_dmg", "25" ); - -// Number of RPG hits it takes to kill a strider on each skill level. -ConVar sk_strider_num_missiles1("sk_strider_num_missiles1", "5"); -ConVar sk_strider_num_missiles2("sk_strider_num_missiles2", "7"); -ConVar sk_strider_num_missiles3("sk_strider_num_missiles3", "7"); - -ConVar strider_missile_suppress_dist( "strider_missile_suppress_dist", "240" ); -ConVar strider_missile_suppress_time( "strider_missile_suppress_time", "3" ); - - -//----------------------------------------------------------------------------- - -extern ConVar sv_gravity; - -extern void CreateConcussiveBlast( const Vector &origin, const Vector &surfaceNormal, CBaseEntity *pOwner, float magnitude ); - -//----------------------------------------------------------------------------- - -enum bodygroups -{ - STRIDER_BODYGROUP_VENT = 1, -}; - -//----------------------------------------------------------------------------- - -#define STRIDER_DEFAULT_SHOOT_DURATION 2.5 // spend this much time stitching to each target. -#define STRIDER_SHOOT_ON_TARGET_TIME 0.5 // How much of DEFAULT_SHOOT_DURATION is spent on-target (vs. stitching up to a target) -#define STRIDER_SHOOT_VARIATION 1.0 // up to 1 second of variance -#define STRIDER_SHOOT_DOWNTIME 1.0 // This much downtime between bursts -#define STRIDER_SUBSEQUENT_TARGET_DURATION 1.5 // Spend this much time stitching to targets chosen by distributed fire. -#define STRIDER_IGNORE_TARGET_DURATION 1.0 -#define STRIDER_IGNORE_PLAYER_DURATION 1.5 -#define STRIDER_DEFAULT_RATE_OF_FIRE 5 // Rounds per second - -#define STRIDER_EP1_RATE_OF_FIRE 10.0f -#define STRIDER_EP1_SHOOT_ON_TARGET_TIME 0.3f -#define STRIDER_EP1_SHOOT_DURATION 1.1f -#define STRIDER_EP1_SHOOT_DOWNTIME 1.0f -#define STRIDER_EP1_SHOOT_VARIATION 0.3f - -//Animation events -#define STRIDER_AE_FOOTSTEP_LEFT 1 -#define STRIDER_AE_FOOTSTEP_RIGHT 2 -#define STRIDER_AE_FOOTSTEP_BACK 3 -#define STRIDER_AE_FOOTSTEP_LEFTM 4 -#define STRIDER_AE_FOOTSTEP_RIGHTM 5 -#define STRIDER_AE_FOOTSTEP_BACKM 6 -#define STRIDER_AE_FOOTSTEP_LEFTL 7 -#define STRIDER_AE_FOOTSTEP_RIGHTL 8 -#define STRIDER_AE_FOOTSTEP_BACKL 9 -#define STRIDER_AE_WHOOSH_LEFT 11 -#define STRIDER_AE_WHOOSH_RIGHT 12 -#define STRIDER_AE_WHOOSH_BACK 13 -#define STRIDER_AE_CREAK_LEFT 21 -#define STRIDER_AE_CREAK_RIGHT 22 -#define STRIDER_AE_CREAK_BACK 23 -#define STRIDER_AE_SHOOTCANNON 100 -#define STRIDER_AE_CANNONHIT 101 -#define STRIDER_AE_SHOOTMINIGUN 105 -#define STRIDER_AE_STOMPHITL 110 -#define STRIDER_AE_STOMPHITR 111 -#define STRIDER_AE_FLICKL 112 -#define STRIDER_AE_FLICKR 113 -#define STRIDER_AE_WINDUPCANNON 114 - -#define STRIDER_AE_DIE 999 - -// UNDONE: Share properly with the client code!!! -#define STRIDER_MSG_BIG_SHOT 1 -#define STRIDER_MSG_STREAKS 2 -#define STRIDER_MSG_DEAD 3 -#define STOMP_IK_SLOT 11 - -// can hit anything within this range -#define STRIDER_STOMP_RANGE 260 - -// Crouch down if trying to shoot an enemy that's this close -#define STRIDER_CROUCH_RANGE 4000.0f - -// Stand up again if crouched and engaging an enemy at this distance -#define STRIDER_STAND_RANGE 6000.0f - -#define STRIDER_NO_TRACK_NAME "null" - -// Time after which if you haven't seen your enemy you stop facing him -#define STRIDER_TIME_STOP_FACING_ENEMY 3.0 - -// Spawnflags -enum -{ - SF_CAN_STOMP_PLAYER = 0x10000, - SF_TAKE_MINIMAL_DAMAGE_FROM_NPCS = 0x20000 -}; - -const float STRIDER_SPEED = 500; -const float STRIDER_SPEED_CHANGE = .0067; // per think - - -static void MoveToGround( Vector *position, CBaseEntity *ignore, const Vector &mins, const Vector &maxs ); - -int s_iImpactEffectTexture = -1; - -//================================================== -// Custom Activities -//================================================== - -int ACT_STRIDER_LOOKL; -int ACT_STRIDER_LOOKR; -int ACT_STRIDER_DEPLOYRA1; -int ACT_STRIDER_AIMRA1; -int ACT_STRIDER_FINISHRA1; -int ACT_STRIDER_DODGER; -int ACT_STRIDER_DODGEL; -int ACT_STRIDER_STOMPL; -int ACT_STRIDER_STOMPR; -int ACT_STRIDER_FLICKL; -int ACT_STRIDER_FLICKR; -int ACT_STRIDER_CARRIED; -int ACT_STRIDER_DEPLOY; -int ACT_STRIDER_GESTURE_DEATH; - -// UNDONE: Split sleep into 3 activities (start, loop, end) -int ACT_STRIDER_SLEEP; - -// These bones have physics shadows -// It allows a one-way interaction between the strider and -// the physics world -static const char *pFollowerBoneNames[] = -{ - // Head - "Combine_Strider.Body_Bone", -#ifdef HL2_EPISODIC - "Combine_Strider.Neck_Bone", - "Combine_Strider.Gun_Bone1", - "Combine_Strider.Gun_Bone2", -#endif //HL2_EPISODIC - - // lower legs - "Combine_Strider.Leg_Left_Bone1", - "Combine_Strider.Leg_Right_Bone1", - "Combine_Strider.Leg_Hind_Bone1", - - // upper legs - "Combine_Strider.Leg_Left_Bone", - "Combine_Strider.Leg_Right_Bone", - "Combine_Strider.Leg_Hind_Bone", -}; - -// NOTE: These indices must directly correlate with the above list! -enum -{ - STRIDER_BODY_FOLLOWER_INDEX = 0, -#ifdef HL2_EPISODIC - STRIDER_NECK_FOLLOWER_INDEX, - STRIDER_GUN1_FOLLOWER_INDEX, - STRIDER_GUN2_FOLLOWER_INDEX, -#endif //HL2_EPISODIC - - STRIDER_LEFT_LEG_FOLLOWER_INDEX, - STRIDER_RIGHT_LEG_FOLLOWER_INDEX, - STRIDER_BACK_LEG_FOLLOWER_INDEX, - - STRIDER_LEFT_UPPERLEG_FOLLOWER_INDEX, - STRIDER_RIGHT_UPPERLEG_FOLLOWER_INDEX, - STRIDER_BACK_UPPERLEG_FOLLOWER_INDEX, -}; - -#define MINIGUN_MAX_YAW 90.0f -#define MINIGUN_MIN_YAW -90.0f -#define MINIGUN_MAX_PITCH 45.0f -#define MINIGUN_MIN_PITCH -45.0f - -//----------------------------------------------------------------------------- -// -// CNPC_Strider -// -//----------------------------------------------------------------------------- - -IMPLEMENT_SERVERCLASS_ST(CNPC_Strider, DT_NPC_Strider) - SendPropVector(SENDINFO(m_vecHitPos), -1, SPROP_COORD), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecIKTarget, 0 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecIKTarget, 1 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecIKTarget, 2 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecIKTarget, 3 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecIKTarget, 4 ), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NETWORKARRAYELEM( m_vecIKTarget, 5 ), -1, SPROP_COORD ), -END_SEND_TABLE() - -//------------------------------------- - -LINK_ENTITY_TO_CLASS( npc_strider, CNPC_Strider ); - -//------------------------------------- - -BEGIN_DATADESC( CNPC_Strider ) - -#ifdef HL2_EPISODIC - DEFINE_UTLVECTOR( m_hAttachedBusters, FIELD_EHANDLE ), -#endif // HL2_EPISODIC - - DEFINE_EMBEDDED( m_EnemyUpdatedTimer ), - DEFINE_EMBEDDEDBYREF( m_pMinigun ), - DEFINE_FIELD( m_miniGunAmmo, FIELD_INTEGER ), - DEFINE_FIELD( m_miniGunDirectAmmo, FIELD_INTEGER ), - DEFINE_FIELD( m_nextStompTime, FIELD_TIME ), - DEFINE_FIELD( m_nextShootTime, FIELD_TIME ), - DEFINE_FIELD( m_ragdollTime, FIELD_TIME ), - DEFINE_FIELD( m_miniGunShootDuration, FIELD_FLOAT ), - DEFINE_FIELD( m_aimYaw, FIELD_FLOAT ), - DEFINE_FIELD( m_aimPitch, FIELD_FLOAT ), - DEFINE_FIELD( m_blastHit, FIELD_VECTOR ), - DEFINE_FIELD( m_blastNormal, FIELD_VECTOR ), - DEFINE_FIELD( m_vecHitPos, FIELD_POSITION_VECTOR ), - DEFINE_AUTO_ARRAY( m_vecIKTarget, FIELD_POSITION_VECTOR ), - - DEFINE_EMBEDDED( m_PlayerFreePass ), - - DEFINE_EMBEDDED( m_PostureAnimationTimer ), - - DEFINE_EMBEDDED( m_BoneFollowerManager ), - - // m_iszStriderBusterName - recreated at load time - // m_iszMagnadeClassname - recreated at load time - // m_iszHunterClassname - recreated at load time - - DEFINE_FIELD( m_hRagdoll, FIELD_EHANDLE ), - DEFINE_FIELD( m_hCannonTarget, FIELD_EHANDLE ), - DEFINE_EMBEDDED( m_AttemptCannonLOSTimer ), - - DEFINE_FIELD( m_flSpeedScale, FIELD_FLOAT ), - DEFINE_FIELD( m_flTargetSpeedScale, FIELD_FLOAT ), - - DEFINE_EMBEDDED( m_LowZCorrectionTimer ), - DEFINE_FIELD( m_BodyTargetBone, FIELD_INTEGER ), - - DEFINE_FIELD( m_iVisibleEnemies, FIELD_INTEGER ), - DEFINE_FIELD( m_flTargetAcquiredTime, FIELD_FLOAT ), - DEFINE_FIELD( m_bCrouchLocked, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bNoCrouchWalk, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bDontCrouch, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bNoMoveToLOS, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_bDisableBoneFollowers, FIELD_BOOLEAN, "disablephysics" ), - - DEFINE_FIELD( m_idealHeight, FIELD_FLOAT ), - DEFINE_FIELD( m_HeightVelocity, FIELD_FLOAT ), - - DEFINE_FIELD( m_prevYaw, FIELD_FLOAT ), - DEFINE_FIELD( m_doTurn, FIELD_FLOAT ), - DEFINE_FIELD( m_doLeft, FIELD_FLOAT ), - DEFINE_FIELD( m_doRight, FIELD_FLOAT ), - DEFINE_FIELD( m_flNextTurnAct, FIELD_TIME ), - - DEFINE_FIELD( m_strTrackName, FIELD_STRING ), - DEFINE_FIELD( m_hFocus, FIELD_EHANDLE ), - DEFINE_FIELD( m_hSmoke, FIELD_EHANDLE ), - - DEFINE_FIELD( m_flTimeLastAlertSound, FIELD_TIME ), - DEFINE_FIELD( m_flTimeNextHuntSound, FIELD_TIME ), - DEFINE_FIELD( m_flTimePlayerMissileDetected, FIELD_TIME ), - DEFINE_FIELD( m_hPlayersMissile, FIELD_EHANDLE ), - DEFINE_FIELD( m_bMinigunUseDirectFire, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_bUseAggressiveBehavior, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_bFastCrouch, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bMinigunEnabled, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bExploding, FIELD_BOOLEAN ), - - // inputs - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetMinigunTime", InputSetMinigunTime ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetMinigunTarget", InputSetMinigunTarget ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetCannonTarget", InputSetCannonTarget ), - DEFINE_INPUTFUNC( FIELD_STRING, "FlickRagdoll", InputFlickRagdoll ), - DEFINE_INPUTFUNC( FIELD_VOID, "Crouch", InputCrouch ), - DEFINE_INPUTFUNC( FIELD_VOID, "CrouchInstantly", InputCrouchInstantly ), - DEFINE_INPUTFUNC( FIELD_VOID, "Stand", InputStand ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetHeight", InputSetHeight ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetTargetPath", InputSetTargetPath ), - DEFINE_INPUTFUNC( FIELD_STRING, "ClearTargetPath", InputClearTargetPath ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableCrouchWalk", InputDisableCrouchWalk ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableCrouchWalk", InputEnableCrouchWalk ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableAggressiveBehavior", InputEnableAggressiveBehavior ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableAggressiveBehavior", InputDisableAggressiveBehavior ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableMinigun", InputDisableMinigun ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableMinigun", InputEnableMinigun ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "StopShootingMinigunForSeconds", InputStopShootingMinigunForSeconds ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableCrouch", InputDisableCrouch ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableMoveToLOS", InputDisableMoveToLOS ), - DEFINE_INPUTFUNC( FIELD_STRING, "DisableCollisionWith", InputDisableCollisionWith ), - DEFINE_INPUTFUNC( FIELD_STRING, "EnableCollisionWith", InputEnableCollisionWith ), - DEFINE_INPUTFUNC( FIELD_VOID, "Explode", InputExplode ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "ScaleGroundSpeed", InputScaleGroundSpeed ), - - // Function Pointers -// DEFINE_FUNCTION( JumpTouch ), - DEFINE_THINKFUNC( CarriedThink ), - DEFINE_THINKFUNC( CannonHitThink ), - -END_DATADESC() - -//--------------------------------------------------------- - -float CNPC_Strider::gm_strideLength; - -int CNPC_Strider::gm_BodyHeightPoseParam; -int CNPC_Strider::gm_YawControl; -int CNPC_Strider::gm_PitchControl; -int CNPC_Strider::gm_CannonAttachment; - -float CNPC_Strider::gm_zCannonDist; -float CNPC_Strider::gm_zMinigunDist; -Vector CNPC_Strider::gm_vLocalRelativePositionCannon; -Vector CNPC_Strider::gm_vLocalRelativePositionMinigun; - -//--------------------------------------------------------- -//--------------------------------------------------------- -CNPC_Strider::CNPC_Strider() -{ - m_strTrackName = MAKE_STRING( STRIDER_NO_TRACK_NAME ); - m_hFocus = NULL; - m_pMinigun = new CStriderMinigun; - m_hSmoke = NULL; - m_PlayerFreePass.SetOuter( this ); - m_bExploding = false; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -CNPC_Strider::~CNPC_Strider() -{ - delete m_pMinigun; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::Precache() -{ - if ( !GetModelName() ) - { - SetModelName( MAKE_STRING( "models/combine_strider.mdl" ) ); - } - - PrecacheModel( STRING( GetModelName() ) ); - - PropBreakablePrecacheAll( GetModelName() ); - - PrecacheScriptSound( "NPC_Strider.StriderBusterExplode" ); - PrecacheScriptSound( "explode_5" ); - PrecacheScriptSound( "NPC_Strider.Charge" ); - PrecacheScriptSound( "NPC_Strider.RagdollDetach" ); - PrecacheScriptSound( "NPC_Strider.Whoosh" ); - PrecacheScriptSound( "NPC_Strider.Creak" ); - PrecacheScriptSound( "NPC_Strider.Alert" ); - PrecacheScriptSound( "NPC_Strider.Pain" ); - PrecacheScriptSound( "NPC_Strider.Death" ); - PrecacheScriptSound( "NPC_Strider.FireMinigun" ); - PrecacheScriptSound( "NPC_Strider.Shoot" ); - PrecacheScriptSound( "NPC_Strider.OpenHatch" ); - PrecacheScriptSound( "NPC_Strider.Footstep" ); - PrecacheScriptSound( "NPC_Strider.Skewer" ); - PrecacheScriptSound( "NPC_Strider.Hunt" ); - PrecacheMaterial( "effects/water_highlight" ); - s_iImpactEffectTexture = PrecacheModel( "sprites/physbeam.vmt" ); - PrecacheMaterial( "sprites/bluelaser1" ); - PrecacheMaterial( "effects/blueblacklargebeam" ); - PrecacheMaterial( "effects/strider_pinch_dudv" ); - PrecacheMaterial( "effects/blueblackflash" ); - PrecacheMaterial( "effects/strider_bulge_dudv" ); - PrecacheMaterial( "effects/strider_muzzle" ); - - PrecacheModel( "models/chefhat.mdl" ); - - UTIL_PrecacheOther( "sparktrail" ); - - BaseClass::Precache(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::Spawn() -{ - Precache(); - - m_miniGunAmmo = GetAmmoDef()->Index("StriderMinigun"); - m_miniGunDirectAmmo = GetAmmoDef()->Index("StriderMinigunDirect"); - m_pMinigun->Init(); - - EnableServerIK(); - - SetModel( STRING( GetModelName() ) ); - - BaseClass::Spawn(); - - //m_debugOverlays |= OVERLAY_NPC_ROUTE_BIT | OVERLAY_BBOX_BIT; - SetHullType( HULL_LARGE_CENTERED ); - SetHullSizeNormal(); - SetDefaultEyeOffset(); - - SetNavType( NAV_FLY ); - m_flGroundSpeed = STRIDER_SPEED; - m_flSpeedScale = m_flTargetSpeedScale = 1.0; - m_NPCState = NPC_STATE_NONE; - m_bloodColor = DONT_BLEED; - - m_iHealth = sk_strider_health.GetFloat(); - m_iMaxHealth = 500; - - m_flFieldOfView = 0.0; // 180 degrees - - AddFlag( FL_FLY ); - SetCollisionGroup( HL2COLLISION_GROUP_STRIDER ); - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_STEP ); - AddEFlags( EFL_NO_DISSOLVE | EFL_NO_MEGAPHYSCANNON_RAGDOLL ); - - // Cached for quick comparisons - m_iszStriderBusterName = AllocPooledString( "weapon_striderbuster" ); - m_iszMagnadeClassname = AllocPooledString( "npc_grenade_magna" ); - m_iszHunterClassname = AllocPooledString( "npc_hunter" ); - - // BMCD: Force collision hooks - AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST ); - SetupGlobalModelData(); - - CapabilitiesAdd( bits_CAP_MOVE_FLY | bits_CAP_INNATE_RANGE_ATTACK2 | bits_CAP_INNATE_MELEE_ATTACK1 | bits_CAP_INNATE_MELEE_ATTACK2 | bits_CAP_SQUAD ); - - // Don't allow us to skip animation setup because our attachments are critical to us! - SetBoneCacheFlags( BCF_NO_ANIMATION_SKIP ); - - // find the ground, move up to strider stand height - Vector mins(-16,-16,-16), maxs(16,16,16); - Vector origin = GetLocalOrigin(); - - MoveToGround( &origin, this, mins, maxs ); - origin.z += GetMaxHeight();//(GetAbsOrigin().z - vecSurroundMins.z) + mins.z; - - SetLocalOrigin( origin ); - - NPCInit(); - - // Strider doesn't care about missiles for now. - AddClassRelationship( CLASS_MISSILE, D_NU, 0 ); - - m_bCrouchLocked = false; - m_bMinigunEnabled = true; - - m_PostureAnimationTimer.Set( 8, 16 ); - - m_BodyTargetBone = -1; - - CreateFocus(); - - m_EnemyUpdatedTimer.Set( 0 ); - - // Don't minigun things farther than 500 feet away. - m_flDistTooFar = 500.0f * 12.0f; - - GetEnemies()->SetFreeKnowledgeDuration( strider_free_knowledge.GetFloat() ); - - m_hPlayersMissile.Set( NULL ); - m_flTimeNextHuntSound = gpGlobals->curtime - 1.0f; -} - -void CNPC_Strider::SetupGlobalModelData() -{ - gm_BodyHeightPoseParam = LookupPoseParameter( "body_height" ); - gm_YawControl = LookupPoseParameter( "yaw" ); - gm_PitchControl = LookupPoseParameter( "pitch" ); - gm_CannonAttachment = LookupAttachment( "BigGun" ); - - // BMCD: Get the conservative boxes from sequences - Vector mins, maxs; - ExtractBbox( SelectHeaviestSequence( ACT_WALK ), mins, maxs ); - CNPC_Strider::gm_strideLength = (maxs.x - mins.x) * 0.5; - - // UNDONE: use crouch when crouched - CollisionProp()->SetSurroundingBoundsType( USE_HITBOXES ); -} - -void CNPC_Strider::OnRestore() -{ - BaseClass::OnRestore(); - SetupGlobalModelData(); - CreateVPhysics(); - - // Cached for quick comparisons - m_iszStriderBusterName = FindPooledString( "weapon_striderbuster" ); - m_iszMagnadeClassname = FindPooledString( "npc_grenade_magna" ); -} - -bool CNPC_Strider::m_sbStaticPoseParamsLoaded = false; -int CNPC_Strider::m_poseMiniGunYaw = 0; -int CNPC_Strider::m_poseMiniGunPitch = 0; -//----------------------------------------------------------------------------- -// Purpose: Cache whatever pose parameters we intend to use -//----------------------------------------------------------------------------- -void CNPC_Strider::PopulatePoseParameters( void ) -{ - if (!m_sbStaticPoseParamsLoaded) - { - m_poseMiniGunYaw = LookupPoseParameter( "miniGunYaw"); - m_poseMiniGunPitch = LookupPoseParameter( "miniGunPitch" ); - - m_sbStaticPoseParamsLoaded = true; - } - - BaseClass::PopulatePoseParameters(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Strider::CreateVPhysics() -{ - // The strider has bone followers for every solid part of its body, - // so there's no reason for the bounding box to be solid. - //BaseClass::CreateVPhysics(); - - if ( !m_bDisableBoneFollowers ) - { - InitBoneFollowers(); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Strider::InitBoneFollowers( void ) -{ - // Don't do this if we're already loaded - if ( m_BoneFollowerManager.GetNumBoneFollowers() != 0 ) - return; - - // Init our followers - m_BoneFollowerManager.InitBoneFollowers( this, ARRAYSIZE(pFollowerBoneNames), pFollowerBoneNames ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::PostNPCInit() -{ - BaseClass::PostNPCInit(); - - if( CarriedByDropship() ) - { - SetMoveType( MOVETYPE_NONE ); - SetActivity( (Activity)ACT_STRIDER_CARRIED ); - SetThink( &CNPC_Strider::CarriedThink ); - RemoveFlag( FL_FLY ); - } - - m_PlayerFreePass.SetPassTarget( UTIL_PlayerByIndex(1) ); - - AI_FreePassParams_t freePassParams = - { - strider_free_pass_start_time.GetFloat(), // timeToTrigger - strider_free_pass_duration.GetFloat(), // duration - strider_free_pass_move_tolerance.GetFloat(), // moveTolerance - strider_free_pass_refill_rate.GetFloat(), // refillRate - strider_free_pass_cover_dist.GetFloat(), // coverDist - strider_peek_time.GetFloat(), // peekTime - strider_peek_time_after_damage.GetFloat(), // peekTimeAfterDamage - strider_peek_eye_dist.GetFloat(), // peekEyeDist - strider_peek_eye_dist_z.GetFloat(), // peekEyeDistZ - }; - - m_PlayerFreePass.SetParams( freePassParams ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::Activate() -{ - BaseClass::Activate(); - - const char *pszBodyTargetBone = "combine_strider.neck_bone"; - - m_BodyTargetBone = LookupBone( pszBodyTargetBone ); - - if ( m_BodyTargetBone == -1 ) - { - DevMsg( "Couldn't find npc_strider bone %s, which is used as target for others\n", pszBodyTargetBone ); - } - - gm_BodyHeightPoseParam = LookupPoseParameter( "body_height" ); - gm_YawControl = LookupPoseParameter( "yaw" ); - gm_PitchControl = LookupPoseParameter( "pitch" ); - gm_CannonAttachment = LookupAttachment( "BigGun" ); - - if ( gm_zCannonDist == 0 ) - { - // Have to create a virgin strider to ensure proper pose - CNPC_Strider *pStrider = (CNPC_Strider *)CreateEntityByName( "npc_strider" ); - Assert(pStrider); - pStrider->m_bDisableBoneFollowers = true; // don't create these since we're just going to destroy him - DispatchSpawn( pStrider ); - - pStrider->SetActivity( ACT_DIERAGDOLL ); - pStrider->InvalidateBoneCache(); - gm_zCannonDist = pStrider->CannonPosition().z - pStrider->GetAbsOrigin().z; - - // Currently just using the gun for the vertical component! - Vector defEyePos; - pStrider->GetAttachment( "minigunbase", defEyePos ); - gm_zMinigunDist = defEyePos.z - pStrider->GetAbsOrigin().z; - - Vector position; - pStrider->GetAttachment( "biggun", position ); - VectorITransform( position, pStrider->EntityToWorldTransform(), gm_vLocalRelativePositionCannon ); - - pStrider->GetAttachment( "minigun", position ); - VectorITransform( position, pStrider->EntityToWorldTransform(), gm_vLocalRelativePositionMinigun ); - UTIL_Remove( pStrider ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::UpdateOnRemove() -{ - m_BoneFollowerManager.DestroyBoneFollowers(); - -#ifdef HL2_EPISODIC - m_hAttachedBusters.Purge(); -#endif // HL2_EPISODIC - - BaseClass::UpdateOnRemove(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::InitBoneControllers() -{ - BaseClass::InitBoneControllers( ); - - SetHeight( GetMaxHeight() ); - SetIdealHeight( GetMaxHeight() ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -Class_T CNPC_Strider::Classify() -{ - if( CarriedByDropship() ) - return CLASS_NONE; - - return CLASS_COMBINE; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Strider::ShouldAttractAutoAim( CBaseEntity *pAimingEnt ) -{ -#ifdef HL2_EPISODIC - if( m_hAttachedBusters.Count() > 0 ) - return false; -#endif//HL2_EPISODIC - - return BaseClass::ShouldAttractAutoAim( pAimingEnt ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CNPC_Strider::DrawDebugTextOverlays() -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - EntityText(text_offset,CFmtStr("Ideal Height: %.1f; Height: %.1f", GetIdealHeight(), GetHeight()),0); - text_offset++; - if ( m_PlayerFreePass.HasPass() ) - { - EntityText(text_offset,CFmtStr("Free pass: %.1f", m_PlayerFreePass.GetTimeRemaining()),0); - text_offset++; - } - - CBaseEntity *pPlayer = UTIL_PlayerByIndex(1); - if ( pPlayer ) - { - if ( GetSenses()->ShouldSeeEntity( pPlayer ) && GetSenses()->CanSeeEntity( pPlayer ) ) - { - EntityText(text_offset,"See player",0); - text_offset++; - } - else - { - float temp = m_PlayerFreePass.GetTimeRemaining(); - m_PlayerFreePass.SetTimeRemaining( 0 ); - - if ( BaseClass::FVisible( pPlayer ) && !FVisible( pPlayer ) ) - { - EntityText(text_offset,"Player peeking",0); - text_offset++; - } - m_PlayerFreePass.SetTimeRemaining( temp ); - } - } - - if ( m_flTargetSpeedScale != 1.0 ) - { - EntityText(text_offset,CFmtStr( "Speed scaled to %.1f", m_flGroundSpeed ),0); - text_offset++; - } - } - - return text_offset; -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -Vector CNPC_Strider::EyePosition() -{ - Vector eyePosition = GetAdjustedOrigin(); - eyePosition.z += gm_zMinigunDist; - return eyePosition; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -const Vector &CNPC_Strider::GetViewOffset() -{ - Vector vOffset; - - vOffset.x = 0; - vOffset.y = 0; - vOffset.z = ( GetHeight() - GetMaxHeightModel() ) + gm_zMinigunDist; - - Assert( VectorsAreEqual( GetAbsOrigin() + vOffset, EyePosition(), 0.1 )); - - SetViewOffset( vOffset ); - - return BaseClass::GetViewOffset(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::CalculateIKLocks( float currentTime ) -{ - BaseClass::CalculateIKLocks( currentTime ); - if ( m_pIk && m_pIk->m_target.Count() ) - { - Assert(m_pIk->m_target.Count() > STOMP_IK_SLOT); - // HACKHACK: Hardcoded 11??? Not a cleaner way to do this - CIKTarget &target = m_pIk->m_target[STOMP_IK_SLOT]; - target.SetPos( m_vecHitPos.Get() ); - for ( int i = 0; i < NUM_STRIDER_IK_TARGETS; i++ ) - { - target = m_pIk->m_target[i]; - - if (!target.IsActive()) - continue; - - m_vecIKTarget.Set( i, target.est.pos ); - -#if 0 - // yellow box at target pos - helps debugging - //if (i == 0) - NDebugOverlay::Line( GetAbsOrigin(), m_vecIKTarget[i], 255, 255, 0, 0, 0.1 ); - NDebugOverlay::Box( m_vecIKTarget[i], Vector(-8,-8,-8), Vector(8,8,8), 255, 255, 0, 0, 4.0 ); -#endif - } - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::NPCThink(void) -{ - if ( m_hRagdoll.Get() ) - { - m_nextStompTime = gpGlobals->curtime + 5; - } - - if ( m_flTargetSpeedScale > 0.01 ) - { - float deltaSpeedScale = m_flSpeedScale - m_flTargetSpeedScale; - if ( fabsf( deltaSpeedScale ) > .01 ) - { - if ( deltaSpeedScale < 0 ) - { - m_flSpeedScale += STRIDER_SPEED_CHANGE; - if ( m_flSpeedScale > m_flTargetSpeedScale ) - { - m_flSpeedScale = m_flTargetSpeedScale; - } - } - else - { - m_flSpeedScale -= STRIDER_SPEED_CHANGE; - if ( m_flSpeedScale < m_flTargetSpeedScale ) - { - m_flSpeedScale = m_flTargetSpeedScale; - } - } - } - else - { - m_flSpeedScale = m_flTargetSpeedScale; - } - } - else - { - m_flTargetSpeedScale = 1.0; - } - - BaseClass::NPCThink(); - - m_pMinigun->Think( this, 0.1 ); - - // update follower bones - m_BoneFollowerManager.UpdateBoneFollowers(this); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::PrescheduleThink() -{ - if( IsUsingAggressiveBehavior() && GetEnemy() && GetEnemy()->IsPlayer() ) - { - AddFacingTarget( GetEnemy(), GetEnemies()->LastKnownPosition( GetEnemy() ) , 1.0, 2.0 ); - } - - // Next missile will kill me! - if( GetHealth() <= 50 && random->RandomInt( 0, 20 ) == 0 ) - { - CBaseEntity *pTrail = CreateEntityByName( "sparktrail" ); - pTrail->SetOwnerEntity( this ); - pTrail->Spawn(); - } - -#if 0 - NDebugOverlay::Cross3D( GetAdjustedOrigin(), 16, 128, 128, 128, false, .1 ); - Vector vIdealOrigin = GetAbsOrigin(); - vIdealOrigin.z -= GetMaxHeightModel() - GetIdealHeight(); - NDebugOverlay::Cross3D( vIdealOrigin, 16, 255, 255, 255, false, .1 ); -#endif - - if( strider_eyepositions.GetBool() ) - { - NDebugOverlay::Cross3D( EyePosition(), 16, 0, 255, 0, false, 0.1 ); - NDebugOverlay::Cross3D( EyePositionCrouched(), 16, 255, 255, 0, false, 0.1 ); - } - - if( strider_show_focus.GetBool() ) - { - QAngle angles; - - angles.x = gpGlobals->curtime * 20.0f; - angles.y = angles.x * 0.5f; - angles.z = 0.0f; - - NDebugOverlay::Cross3DOriented( GetFocus()->GetAbsOrigin(), angles, 24, 255, 255, 0, false, 0.1 ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::GatherConditions() -{ - if ( AIGetNumFollowers( this, m_iszHunterClassname ) == 0 ) - { - // This works with old data because need to do before base class so as to not choose as enemy - if ( m_PlayerFreePass.HasPass() || ( !m_pMinigun->IsShooting() || GetEnemy() != m_PlayerFreePass.GetPassTarget() ) ) // no free pass when in midst of shooting at target - m_PlayerFreePass.Update(); - } - else - { - m_PlayerFreePass.Reset( strider_free_pass_after_escorts_dead.GetFloat(), strider_free_pass_tolerance_after_escorts_dead.GetFloat() ); - } - - if( IsUsingAggressiveBehavior() ) - { - if( m_PlayerFreePass.HasPass() && !m_pMinigun->IsShooting() ) - { - // Make the minigun stitch - m_bMinigunUseDirectFire = false; - } - } - - //--------------------------------- - - BaseClass::GatherConditions(); - - if( IsUsingAggressiveBehavior() ) - { - if( GetEnemy() ) - { - if( HasCondition( COND_SEE_ENEMY ) ) - { - // Keep setting up to play my hunt sound at some random time after losing sight of my enemy. - m_flTimeNextHuntSound = gpGlobals->curtime + 1.0f; - } - else - { - if( gpGlobals->curtime >= m_flTimeNextHuntSound && !m_pMinigun->IsShooting() ) - { - HuntSound(); - } - } - } - - if( m_hPlayersMissile ) - { - if( !m_pMinigun->IsShooting() && GetEnemy() && GetEnemy()->IsPlayer() ) - { - // If the missile is closer to the player than I am, stay suppressed. This is essentially - // allowing the missile to strike me if it was fired off before I started shooting. - // If the missile passes me or goes way off course, I can shoot. - float flPlayerMissileDist; - float flPlayerStriderDist; - - flPlayerMissileDist = GetEnemy()->GetAbsOrigin().DistTo( m_hPlayersMissile->GetAbsOrigin() ); - flPlayerStriderDist = GetEnemy()->GetAbsOrigin().DistTo( EyePosition() ); - float flDiff = flPlayerMissileDist - flPlayerStriderDist; - - // Figure out how long it's been since I've fired my cannon because of a player's missile. - float flTimeSuppressed = gpGlobals->curtime - m_flTimePlayerMissileDetected; - - if( flDiff < strider_missile_suppress_dist.GetFloat() && flTimeSuppressed < strider_missile_suppress_time.GetFloat() ) - { - // Defer the minigun until/unless the missile has passed me by 10 feet - m_pMinigun->StopShootingForSeconds( this, GetEnemy(), 0.5f ); - } - } - } - } - - // This pair of conditions is nice to have around... - if( m_pMinigun->IsShooting() ) - { - SetCondition( COND_STRIDER_MINIGUN_SHOOTING ); - } - else - { - SetCondition( COND_STRIDER_MINIGUN_NOT_SHOOTING ); - } - - if( GetCannonTarget() ) - { - SetCondition( COND_STRIDER_HAS_CANNON_TARGET ); - - if( strider_show_cannonlos.GetBool() ) - { - trace_t tr; - UTIL_TraceLine( CannonPosition(), GetCannonTarget()->WorldSpaceCenter(), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - NDebugOverlay::Line( tr.startpos, tr.endpos, 0, 255, 0, false, 0.1 ); - - if( tr.fraction != 1.0 ) - NDebugOverlay::Line( tr.endpos, GetCannonTarget()->WorldSpaceCenter(), 255, 0, 0, false, 0.1 ); - } - } - else - { - ClearCondition( COND_STRIDER_HAS_CANNON_TARGET ); - } - - ClearCondition( COND_CAN_RANGE_ATTACK2 ); - ClearCondition( COND_STRIDER_HAS_LOS_Z ); - - // If not locked into a crouch, look into adjusting height to attack targets. - if( !m_bCrouchLocked && !m_bDontCrouch ) - { - if( m_hCannonTarget != NULL ) - { - if( !IsStriderCrouching() && !IsStriderStanding() ) - { - if ( WeaponLOSCondition( GetAdjustedOrigin(), m_hCannonTarget->GetAbsOrigin(), false ) ) - { - SetCondition( COND_CAN_RANGE_ATTACK2 ); - } - else - { - GatherHeightConditions( GetAdjustedOrigin(), m_hCannonTarget ); - } - } - } - else if( GetEnemy() ) - { - if ( strider_distributed_fire.GetBool() && !IsUsingAggressiveBehavior() ) - { - m_iVisibleEnemies = 0; - AIEnemiesIter_t iter; - - for( AI_EnemyInfo_t *pEMemory = GetEnemies()->GetFirst(&iter); pEMemory != NULL; pEMemory = GetEnemies()->GetNext(&iter) ) - { - if( IRelationType( pEMemory->hEnemy ) != D_NU && IRelationType( pEMemory->hEnemy ) != D_LI ) - { - if( pEMemory->timeLastSeen == gpGlobals->curtime ) - { - m_iVisibleEnemies++; - } - } - } - - // If I'm on target and see more targets than just this one, move on to another target for a bit! - // Because the Mingun's state will stay "on target" until the minigun gets a chance to think, - // and this function may be called several times per strider think, don't call this code anymore in the same - // think when a new enemy is chosen. - // - // Don't switch targets if shooting at a bullseye! Level designers depend on bullseyes. - if( GetEnemy() && m_pMinigun->IsShooting() && GetTimeEnemyAcquired() != gpGlobals->curtime ) - { - if( m_pMinigun->IsOnTarget( 3 ) && !FClassnameIs( GetEnemy(), "npc_bullseye" ) ) - { - if( m_iVisibleEnemies > 1 ) - { - // Time to ignore this guy for a little while and switch targets. - GetEnemies()->SetTimeValidEnemy( GetEnemy(), gpGlobals->curtime + ( STRIDER_IGNORE_TARGET_DURATION * m_iVisibleEnemies ) ); - SetEnemy( NULL, false ); - ChooseEnemy(); - } - else if( GetEnemy()->IsPlayer() && GetEnemy() == m_pMinigun->GetTarget() ) - { - // Give the poor target a break. - m_pMinigun->StopShootingForSeconds( this, GetEnemy(), GetMinigunShootDowntime() ); - } - } - } - } - - if ( GetEnemy() ) // Can go null above - { - if ( !IsStriderCrouching() && !IsStriderStanding() && - ( !HasCondition( COND_SEE_ENEMY ) || - !WeaponLOSCondition( GetAdjustedOrigin(), GetEnemy()->BodyTarget( GetAdjustedOrigin() ), false ) ) ) - { -#if 0 - if ( !HasCondition( COND_STRIDER_SHOULD_CROUCH ) && !HasCondition( COND_STRIDER_SHOULD_CROUCH ) ) - SetIdealHeight( MIN( GetMaxHeight(), GetHeight() + 75.0 * 0.1 ) ); // default to rising up -#endif - GatherHeightConditions( GetAdjustedOrigin(), GetEnemy() ); - } - } - } - else - SetIdealHeight( GetMaxHeight() ); - } - else - { - if( m_hCannonTarget != NULL && CurrentWeaponLOSCondition( m_hCannonTarget->GetAbsOrigin(), false ) ) - SetCondition( COND_CAN_RANGE_ATTACK2 ); - } - - if( m_bDontCrouch ) - { - if( HasCondition( COND_STRIDER_SHOULD_CROUCH ) ) - { - Msg("TELL WEDGE I'M TRYING TO CROUCH!\n"); - } - - ClearCondition( COND_STRIDER_SHOULD_CROUCH ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::GatherHeightConditions( const Vector &vTestPos, CBaseEntity *pEntity ) -{ - if ( HasCondition( COND_STRIDER_SHOULD_CROUCH ) && HasCondition( COND_STRIDER_SHOULD_CROUCH ) ) - return; - - float maxZ = (GetAbsOrigin().z - (GetMaxHeightModel() - GetMaxHeight())); - float minZ = (maxZ - ( GetMaxHeight() - GetMinHeight()));; - float newHeight = FLT_MAX; - - if( FInViewCone( pEntity ) && GetWeaponLosZ( vTestPos, minZ, maxZ, GetHeightRange() * .1, pEntity, &newHeight ) ) - { - bool bDoProceduralHeightChange = true; - newHeight = GetMaxHeightModel() - ( GetAbsOrigin().z - newHeight); - - if ( m_LowZCorrectionTimer.Expired() ) - { - // Hack to handle discrepency between ideal gun pos and actual pos due to strider head tilt in crouch pos - if ( pEntity && fabs( newHeight - GetHeight() ) < 12 && newHeight < GetMinHeight() + GetHeightRange() * .33 ) - { - Vector muzzlePos; - Vector targetPos = pEntity->BodyTarget( GetAdjustedOrigin() ); - - GetAttachment( "minigun", muzzlePos ); - - trace_t tr; - AI_TraceLine( muzzlePos, targetPos, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); - - if ( ( tr.m_pEnt != pEntity) && tr.fraction != 1.0 && !CanShootThrough( tr, targetPos ) ) - { - if ( !GetWeaponLosZ( vTestPos, minZ + GetHeightRange() * .33, maxZ, GetHeightRange() * .1, pEntity, &newHeight ) ) - { - return; - } - newHeight = GetMaxHeightModel() - ( GetAbsOrigin().z - newHeight); - } - else - { - m_LowZCorrectionTimer.Set( 5.0 ); - } - } - } - - if ( !strider_always_use_procedural_height.GetBool() ) - { - // If going from max to min, or min to max, use animations 60% of the time - if ( fabsf(GetMaxHeight() - GetHeight()) < 0.1 && fabsf(GetMinHeight() - newHeight) < 0.1 ) - { - if ( random->RandomInt(1, 10 ) <= 6 ) - { - SetCondition( COND_STRIDER_SHOULD_CROUCH ); - bDoProceduralHeightChange = false; - } - } - else if ( fabsf(GetMinHeight() - GetHeight()) < 0.1 && fabsf(GetMaxHeight() - newHeight) < 0.1 ) - { - if ( random->RandomInt(1, 10 ) <= 6 ) - { - SetCondition( COND_STRIDER_SHOULD_STAND ); - bDoProceduralHeightChange = false; - } - } - - // Otherwise, if going from near max or near min to the other, use animations based on time - if ( bDoProceduralHeightChange && m_PostureAnimationTimer.Expired() ) - { - if ( GetHeight() - GetMinHeight() > GetHeightRange() * .85 && newHeight - GetMinHeight() < GetHeightRange() * .15 ) - { - m_PostureAnimationTimer.Reset(); - SetCondition( COND_STRIDER_SHOULD_CROUCH ); - bDoProceduralHeightChange = false; - } - else if ( newHeight - GetMinHeight() > GetHeightRange() * .85 && GetHeight() - GetMinHeight() < GetHeightRange() * .15 ) - { - m_PostureAnimationTimer.Reset(); - SetCondition( COND_STRIDER_SHOULD_STAND ); - bDoProceduralHeightChange = false; - } - } - } - - if ( bDoProceduralHeightChange ) - { - SetCondition( COND_STRIDER_HAS_LOS_Z ); - SetIdealHeight( newHeight ); - if ( strider_test_height.GetFloat() > .1 ) - SetIdealHeight( strider_test_height.GetFloat() ); - } - else - SetIdealHeight( GetHeight() ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::OnStateChange( NPC_STATE oldState, NPC_STATE newState ) -{ - if ( oldState == NPC_STATE_SCRIPT ) - { - m_pMinigun->Enable( this, m_bMinigunEnabled ); - } - else if ( newState == NPC_STATE_SCRIPT ) - { - m_pMinigun->Enable( this, false ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::BuildScheduleTestBits() -{ - BaseClass::BuildScheduleTestBits(); - if (m_NPCState != NPC_STATE_SCRIPT) - { - SetCustomInterruptCondition( COND_STRIDER_DO_FLICK ); - } - - if( IsCurSchedule( SCHED_ESTABLISH_LINE_OF_FIRE_FALLBACK, false ) || IsCurSchedule( SCHED_ESTABLISH_LINE_OF_FIRE, false ) ) - { - SetCustomInterruptCondition( COND_STRIDER_MINIGUN_SHOOTING ); - } - - if( IsCurSchedule( SCHED_IDLE_STAND ) ) - { - SetCustomInterruptCondition( COND_STRIDER_HAS_CANNON_TARGET ); - } - - // If our base-class schedule breaks on CAN_RANGE_ATTACK1, then also break - // on HAS_CANNON_TARGET. - if( GetCurSchedule()->HasInterrupt( COND_CAN_RANGE_ATTACK1 ) && HasCondition( COND_STRIDER_HAS_CANNON_TARGET ) ) - { - SetCustomInterruptCondition( COND_STRIDER_HAS_CANNON_TARGET ); - } - - if( IsCurSchedule( SCHED_IDLE_WALK ) || IsCurSchedule( SCHED_IDLE_STAND ) && hl2_episodic.GetBool() ) - { - SetCustomInterruptCondition(COND_STRIDER_SHOULD_CROUCH); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CNPC_Strider::SelectSchedule() -{ -/* - if( GetMoveType() != MOVETYPE_FLY ) - { - // Dropship just released me. - SetMoveType( MOVETYPE_FLY ); - return SCHED_STRIDER_FALL_TO_GROUND; - } -*/ - if ( strider_idle_test.GetBool() ) - { - m_pMinigun->Enable( this, false ); - return SCHED_IDLE_STAND; - } - else - { - m_pMinigun->Enable( this, m_bMinigunEnabled ); - } - - if( m_NPCState == NPC_STATE_SCRIPT ) - return BaseClass::SelectSchedule(); - - // If we're starting to die, then just wait for this to happen - if ( m_lifeState == LIFE_DYING ) - return SCHED_IDLE_STAND; - - if( m_NPCState == NPC_STATE_DEAD ) - return SCHED_STRIDER_DIE; - - if( HasPendingTargetPath() ) - { -#if 0 - if( IsInCrouchedPosture() && !m_bCrouchLocked ) - { - // Make the strider stand! - return SCHED_STRIDER_STAND; - } - else - { - SetTargetPath(); - } -#else - SetTargetPath(); -#endif - } - - //--------------------------------- - - if( HasCondition( COND_STRIDER_SHOULD_CROUCH ) && GetHeight() - GetMinHeight() > GetHeightRange() * .5 ) - { - return SCHED_STRIDER_CROUCH; - } - if( HasCondition( COND_STRIDER_SHOULD_STAND ) && !m_bCrouchLocked && GetHeight() - GetMinHeight() < GetHeightRange() * .5 ) - { - return SCHED_STRIDER_STAND; - } - - if( HasCondition( COND_CAN_RANGE_ATTACK2 ) ) - { - return SCHED_STRIDER_RANGE_ATTACK2; - } - else if( m_AttemptCannonLOSTimer.Expired() && HasCondition( COND_STRIDER_HAS_CANNON_TARGET ) ) - { - m_AttemptCannonLOSTimer.Set( 5 ); - return SCHED_STRIDER_ESTABLISH_LINE_OF_FIRE_CANNON; - } - - //--------------------------------- - - if( m_NPCState == NPC_STATE_COMBAT ) - { - if ( !HasCondition( COND_NEW_ENEMY ) ) - { - if ( m_hRagdoll.Get() && (gpGlobals->curtime > m_ragdollTime || HasCondition( COND_STRIDER_DO_FLICK ) ) ) - { - return SCHED_STRIDER_FLICKL; - } - } - - if ( HasCondition( COND_STRIDER_SHOULD_CROUCH ) ) - { - return SCHED_STRIDER_CROUCH; - } - - if ( HasCondition( COND_STRIDER_SHOULD_STAND ) ) - { - return SCHED_STRIDER_STAND; - } - - if ( HasCondition( COND_CAN_MELEE_ATTACK1 ) ) - { - return SCHED_MELEE_ATTACK1; - } - if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - { - return SCHED_STRIDER_RANGE_ATTACK1; - } - - ClearCondition( COND_STRIDER_ENEMY_UPDATED ); - if ( !m_EnemyUpdatedTimer.Expired() ) - { - int baseResult = BaseClass::SelectSchedule(); - if ( baseResult != SCHED_COMBAT_FACE || !GetGoalEnt() ) - return baseResult; - } - - if ( !GetGoalEnt() ) - return BaseClass::SelectSchedule(); - - return SCHED_STRIDER_HUNT; - } - - //--------------------------------- - - if ( !GetGoalEnt() ) - return SCHED_IDLE_STAND; - - return SCHED_STRIDER_HUNT; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- - -#define TIME_CARE_ENEMY 7.0 - -int CNPC_Strider::TranslateSchedule( int scheduleType ) -{ - switch( scheduleType ) - { - case SCHED_RANGE_ATTACK1: - return SCHED_STRIDER_RANGE_ATTACK1; - case SCHED_RANGE_ATTACK2: - return SCHED_STRIDER_RANGE_ATTACK2; - case SCHED_MELEE_ATTACK1: - return SCHED_STRIDER_STOMPL; - case SCHED_MELEE_ATTACK2: - return SCHED_STRIDER_STOMPR; - case SCHED_CHASE_ENEMY: - { - if( HasCondition( COND_SEE_ENEMY ) ) - { - return SCHED_STRIDER_COMBAT_FACE; - } - - return SCHED_STRIDER_CHASE_ENEMY; - } - - case SCHED_ESTABLISH_LINE_OF_FIRE: - case SCHED_ESTABLISH_LINE_OF_FIRE_FALLBACK: - if ( m_bNoMoveToLOS ) - { - return SCHED_COMBAT_FACE; - } - - if ( !m_bCrouchLocked ) - { - if( IsInCrouchedPosture() ) - { - if( m_pMinigun->IsShooting() ) - { - // Don't stand yet. - return SCHED_STRIDER_COMBAT_FACE; - } - } - else if ( HasCondition( COND_STRIDER_HAS_LOS_Z ) && HasCondition( COND_SEE_ENEMY ) ) - { - return SCHED_STRIDER_COMBAT_FACE; - } - } - if ( scheduleType == SCHED_ESTABLISH_LINE_OF_FIRE_FALLBACK ) - { - if ( gpGlobals->curtime - GetEnemyLastTimeSeen() < TIME_CARE_ENEMY ) - return SCHED_STRIDER_COMBAT_FACE; - else if ( GetGoalEnt() ) - return SCHED_STRIDER_HUNT; - else - { - if( IsUsingAggressiveBehavior() ) - { - return SCHED_STRIDER_AGGRESSIVE_COMBAT_STAND; - } - - return SCHED_COMBAT_PATROL; - } - } - - break; - - case SCHED_COMBAT_FACE: - return SCHED_STRIDER_COMBAT_FACE; - break; - } - - return BaseClass::TranslateSchedule( scheduleType ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::StartTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_GET_PATH_TO_ENEMY_LOS: - ChainStartTask( TASK_GET_PATH_TO_ENEMY_LKP_LOS, pTask->flTaskData ); - break; - - case TASK_STRIDER_FALL_TO_GROUND: - break; - - case TASK_STRIDER_FIRE_CANNON: - FireCannon(); - TaskComplete(); - break; - - case TASK_STRIDER_SET_CANNON_HEIGHT: - { - if ( m_hCannonTarget ) - SetAbsIdealHeight( m_hCannonTarget->WorldSpaceCenter().z ); - TaskComplete(); - } - break; - - case TASK_STRIDER_AIM: - { - // Stop the minigun for a bit, the big gun's about to shoot! - m_pMinigun->StopShootingForSeconds( this, m_pMinigun->GetTarget(), 5 ); - - //SetIdealActivity( (Activity)ACT_STRIDER_AIMRA1 ); - SetWait( pTask->flTaskData ); - m_aimYaw = 0; - m_aimPitch = 0; - // clear out the previous shooting - SetPoseParameter( gm_YawControl, m_aimYaw ); - SetPoseParameter( gm_PitchControl, m_aimPitch ); - Vector vecShootPos; - GetAttachment( gm_CannonAttachment, vecShootPos ); - - // tell the client side effect to complete - EntityMessageBegin( this, true ); - WRITE_BYTE( STRIDER_MSG_STREAKS ); - WRITE_VEC3COORD( vecShootPos ); - MessageEnd(); - CPASAttenuationFilter filter2( this, "NPC_Strider.Charge" ); - EmitSound( filter2, entindex(), "NPC_Strider.Charge" ); - - // CPVSFilter filter( vecShootPos ); - //te->StreakSphere( filter, 0, 0, 150, 100, entindex(), gm_CannonAttachment ); - } - break; - - case TASK_STRIDER_DODGE: - break; - - case TASK_STRIDER_STOMP: - { - m_nextStompTime = gpGlobals->curtime + 5; - Activity stompAct = (Activity) ( pTask->flTaskData > 0 ? ACT_STRIDER_STOMPR : ACT_STRIDER_STOMPL ); - ResetIdealActivity( stompAct ); - } - break; - - case TASK_RANGE_ATTACK1: - CBaseCombatWeapon *pWeapon; - pWeapon = GetActiveWeapon(); - - if( pWeapon ) - { - pWeapon->PrimaryAttack(); - } - else - { - TaskFail("no primary weapon"); - } - - TaskComplete(); - break; - - case TASK_STRIDER_BREAKDOWN: - SetIdealActivity( (Activity)ACT_STRIDER_SLEEP ); - break; - - case TASK_STRIDER_REFRESH_HUNT_PATH: - Assert( GetGoalEnt() ); - if ( GetGoalEnt() ) - { - AI_NavGoal_t goal(GOALTYPE_PATHCORNER, GetGoalEnt()->GetLocalOrigin(), ACT_WALK, AIN_DEF_TOLERANCE, AIN_YAW_TO_DEST); - - TranslateNavGoal( GetGoalEnt(), goal.dest ); - - if ( ( m_debugOverlays & OVERLAY_NPC_SELECTED_BIT ) && ( m_debugOverlays & OVERLAY_NPC_ROUTE_BIT ) ) - { - NDebugOverlay::Line( GetAbsOrigin() + Vector( 0, 0, 4), goal.dest, 255, 0, 255, true, 3 ); - } - - if ( GetNavigator()->SetGoal( goal ) ) - { - TaskComplete(); - break; - } - TaskFail( FAIL_NO_ROUTE ); - } - break; - - case TASK_STRIDER_START_MOVING: - TaskComplete(); - break; - - case TASK_STRIDER_GET_PATH_TO_CANNON_LOS: - { - if ( GetCannonTarget() == NULL ) - { - TaskFail("No Cannon Target"); - return; - } - - AI_PROFILE_SCOPE(CAI_BaseNPC_FindLosToEnemy); - Vector vecEnemy = GetCannonTarget()->WorldSpaceCenter(); - - float flMaxRange = 4096; - float flMinRange = 0; - - Vector posLos; - bool found = false; - - if ( GetTacticalServices()->FindLateralLos( vecEnemy, &posLos ) ) - { - found = true; - } - - if ( !found && GetTacticalServices()->FindLos( vecEnemy, vecEnemy, flMinRange, flMaxRange, 1.0, &posLos ) ) - { - found = true; - } - - if ( found ) - { - AI_NavGoal_t goal( posLos, ACT_RUN, AIN_HULL_TOLERANCE ); - - GetNavigator()->SetGoal( goal, AIN_CLEAR_TARGET ); - GetNavigator()->SetArrivalDirection( vecEnemy - goal.dest ); - - // Add the cannon target as a high priority facing entity. - AddFacingTarget( GetCannonTarget(), GetCannonTarget()->WorldSpaceCenter(), 5.0, 5.0 ); - } - else - { - TaskFail( "Can't get LOS to Cannon Target" ); - } - } - break; - - case TASK_STRIDER_GET_PATH_TO_CANNON_TARGET: - { - if( !m_hCannonTarget ) - { - TaskFail( "No cannon target!\n" ); - return; - } - - AI_NavGoal_t goal( m_hCannonTarget->GetAbsOrigin() ); - - TranslateNavGoal( m_hCannonTarget, goal.dest ); - - if ( GetNavigator()->SetGoal( goal, AIN_CLEAR_TARGET ) ) - { - TaskComplete(); - } - else - { - DevWarning( 2, "GetPathToCannonTarget failed!!\n" ); - TaskFail(FAIL_NO_ROUTE); - } - } - break; - - case TASK_STRIDER_FACE_CANNON_TARGET: - if ( m_hCannonTarget != NULL ) - { - GetMotor()->SetIdealYawToTarget( m_hCannonTarget->WorldSpaceCenter() ); - SetTurnActivity(); - } - else - { - TaskFail(FAIL_NO_TARGET); - } - break; - - case TASK_STRIDER_SET_HEIGHT: - SetIdealHeight( pTask->flTaskData ); - TaskComplete(); - break; - - default: - BaseClass::StartTask( pTask ); - break; - } -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::RunTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_GET_PATH_TO_ENEMY_LOS: - ChainRunTask( TASK_GET_PATH_TO_ENEMY_LKP_LOS, pTask->flTaskData ); - break; - - case TASK_STRIDER_FALL_TO_GROUND: - { - // This doesn't work right now. (sjb) - Vector vecVelocity = GetAbsVelocity(); - - vecVelocity.z -= (sv_gravity.GetFloat() * 0.1); - - SetAbsVelocity( vecVelocity ); - - Vector pos = GetAbsOrigin(); - TranslateNavGoal( NULL, pos ); - - if( GetAbsOrigin().z - pos.z <= 0.0f ) - { - SetAbsVelocity( vec3_origin ); - TaskComplete(); - } - } - break; - - case TASK_STRIDER_AIM: - { - // BUGBUG: Need the real flInterval here, not just 0.1 - AimCannonAt( GetCannonTarget(), 0.1 ); - if ( IsWaitFinished() ) - { - TaskComplete(); - } - } - break; - - case TASK_STRIDER_DODGE: - TaskComplete(); - break; - - case TASK_STRIDER_STOMP: - if ( IsActivityFinished() ) - { - TaskComplete(); - } - if ( GetEnemy() ) - { - m_vecHitPos = CalculateStompHitPosition( GetEnemy() ); - } - break; - - case TASK_STRIDER_BREAKDOWN: - if ( IsActivityFinished() ) - { - // UNDONE: Fix this bug! - //Assert(!IsMarkedForDeletion()); - if ( !IsMarkedForDeletion() ) - { - CTakeDamageInfo info; - CreateServerRagdoll( this, 0, info, COLLISION_GROUP_NONE ); - TaskComplete(); - UTIL_Remove(this); - } - } - break; - - case TASK_STRIDER_FACE_CANNON_TARGET: - GetMotor()->UpdateYaw(); - if ( FacingIdeal() ) - { - TaskComplete(); - } - break; - - case TASK_PLAY_SEQUENCE: - if( m_bFastCrouch && pTask->flTaskData == ACT_CROUCH ) - { - SetPlaybackRate( 10.0f ); - if( IsSequenceFinished() ) - { - m_bFastCrouch = false; - } - } - - // Hack to make sure client doesn't pop after stand/crouch is done - if ( GetCycle() > 0.5 ) - { - if ( IsStriderStanding() && GetHeight() != GetMaxHeight() ) - SetHeight( GetMaxHeight() ); - else if ( IsStriderCrouching() && GetHeight() != GetMinHeight() ) - SetHeight( GetMinHeight() ); - SetIdealHeight( GetHeight() ); - } - BaseClass::RunTask( pTask ); - break; - - default: - BaseClass::RunTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Strider::Explode( void ) -{ - Vector velocity = vec3_origin; - AngularImpulse angVelocity = RandomAngularImpulse( -150, 150 ); - - // Break into pieces - breakablepropparams_t params( EyePosition(), GetAbsAngles(), velocity, angVelocity ); - params.impactEnergyScale = 1.0f; - params.defBurstScale = 600.0f; - params.defCollisionGroup = COLLISION_GROUP_NPC; - PropBreakableCreateAll( GetModelIndex(), NULL, params, this, -1, true, true ); - - // Go away - m_lifeState = LIFE_DEAD; - - SetThink( &CNPC_Strider::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - AddEffects( EF_NODRAW ); - - StopSmoking(); - - m_BoneFollowerManager.DestroyBoneFollowers(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_Strider::HandleInteraction( int interactionType, void *data, CBaseCombatCharacter* sourceEnt ) -{ - if ( interactionType == g_interactionPlayerLaunchedRPG ) - { - m_flTimePlayerMissileDetected = gpGlobals->curtime; - m_hPlayersMissile = sourceEnt; - return true; - } - - return BaseClass::HandleInteraction( interactionType, data, sourceEnt ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::HandleAnimEvent( animevent_t *pEvent ) -{ - Vector footPosition; - - switch( pEvent->event ) - { - case STRIDER_AE_DIE: - { - Explode(); - } - break; - case STRIDER_AE_SHOOTCANNON: - { - FireCannon(); - } - break; - case STRIDER_AE_WINDUPCANNON: - { - AimCannonAt( GetCannonTarget(), 0.1 ); - - // Stop the minigun for a bit, the big gun's about to shoot! - m_pMinigun->StopShootingForSeconds( this, m_pMinigun->GetTarget(), 5 ); - - m_aimYaw = 0; - m_aimPitch = 0; - - // clear out the previous shooting - SetPoseParameter( gm_YawControl, m_aimYaw ); - SetPoseParameter( gm_PitchControl, m_aimPitch ); - Vector vecShootPos; - GetAttachment( gm_CannonAttachment, vecShootPos ); - - // tell the client side effect to start - EntityMessageBegin( this, true ); - WRITE_BYTE( STRIDER_MSG_STREAKS ); - WRITE_VEC3COORD( vecShootPos ); - MessageEnd(); - CPASAttenuationFilter filter2( this, "NPC_Strider.Charge" ); - EmitSound( filter2, entindex(), "NPC_Strider.Charge" ); - } - break; - case STRIDER_AE_CANNONHIT: - CreateConcussiveBlast( m_blastHit, m_blastNormal, this, 2.5 ); - break; - - case STRIDER_AE_SHOOTMINIGUN: - { - CBaseEntity *pTarget = gEntList.FindEntityGeneric( NULL, pEvent->options, this, this ); - if ( pTarget ) - { - Vector vecTarget = pTarget->CollisionProp()->WorldSpaceCenter(); - ShootMinigun( &vecTarget, 0 ); - } - break; - } - - case STRIDER_AE_STOMPHITL: - StompHit( STRIDER_LEFT_LEG_FOLLOWER_INDEX ); - break; - case STRIDER_AE_STOMPHITR: - StompHit( STRIDER_RIGHT_LEG_FOLLOWER_INDEX ); - break; - case STRIDER_AE_FLICKL: - case STRIDER_AE_FLICKR: - { - CBaseEntity *pRagdoll = m_hRagdoll; - if ( pRagdoll ) - { - CPASAttenuationFilter filter( pRagdoll, "NPC_Strider.RagdollDetach" ); - EmitSound( filter, pRagdoll->entindex(), "NPC_Strider.RagdollDetach" ); - DetachAttachedRagdoll( pRagdoll ); - } - m_hRagdoll = NULL; - } - break; - - case STRIDER_AE_FOOTSTEP_LEFT: - case STRIDER_AE_FOOTSTEP_LEFTM: - case STRIDER_AE_FOOTSTEP_LEFTL: - LeftFootHit( pEvent->eventtime ); - break; - case STRIDER_AE_FOOTSTEP_RIGHT: - case STRIDER_AE_FOOTSTEP_RIGHTM: - case STRIDER_AE_FOOTSTEP_RIGHTL: - RightFootHit( pEvent->eventtime ); - break; - case STRIDER_AE_FOOTSTEP_BACK: - case STRIDER_AE_FOOTSTEP_BACKM: - case STRIDER_AE_FOOTSTEP_BACKL: - BackFootHit( pEvent->eventtime ); - break; - case STRIDER_AE_WHOOSH_LEFT: - { - GetAttachment( "left foot", footPosition ); - - CPASAttenuationFilter filter( this, "NPC_Strider.Whoosh" ); - EmitSound( filter, 0, "NPC_Strider.Whoosh", &footPosition ); - } - break; - case STRIDER_AE_WHOOSH_RIGHT: - { - GetAttachment( "right foot", footPosition ); - - CPASAttenuationFilter filter( this, "NPC_Strider.Whoosh" ); - EmitSound( filter, 0, "NPC_Strider.Whoosh", &footPosition ); - } - break; - case STRIDER_AE_WHOOSH_BACK: - { - GetAttachment( "back foot", footPosition ); - - CPASAttenuationFilter filter( this, "NPC_Strider.Whoosh" ); - EmitSound( filter, 0, "NPC_Strider.Whoosh", &footPosition ); - } - break; - case STRIDER_AE_CREAK_LEFT: - case STRIDER_AE_CREAK_BACK: - case STRIDER_AE_CREAK_RIGHT: - { - EmitSound( "NPC_Strider.Creak" ); - } - break; - default: - BaseClass::HandleAnimEvent( pEvent ); - break; - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -Disposition_t CNPC_Strider::IRelationType( CBaseEntity *pTarget ) -{ - if ( IsCannonTarget( pTarget ) ) - return D_HT; - - return BaseClass::IRelationType( pTarget ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::AddEntityRelationship( CBaseEntity *pEntity, Disposition_t nDisposition, int nPriority ) -{ - if ( nDisposition == D_HT && pEntity->ClassMatches("npc_bullseye") ) - UpdateEnemyMemory( pEntity, pEntity->GetAbsOrigin() ); - BaseClass::AddEntityRelationship( pEntity, nDisposition, nPriority ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Strider::ScheduledMoveToGoalEntity( int scheduleType, CBaseEntity *pGoalEntity, Activity movementActivity ) -{ - if ( IsCurSchedule( SCHED_STRIDER_RANGE_ATTACK2, false ) ) - { - SetGoalEnt( pGoalEntity ); - return true; - } - return BaseClass::ScheduledMoveToGoalEntity( scheduleType, pGoalEntity, movementActivity ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Strider::ScheduledFollowPath( int scheduleType, CBaseEntity *pPathStart, Activity movementActivity ) -{ - m_strTrackName = pPathStart->GetEntityName(); - if ( IsCurSchedule( SCHED_STRIDER_RANGE_ATTACK2, false ) ) - { - SetGoalEnt( pPathStart ); - return true; - } - return BaseClass::ScheduledFollowPath( scheduleType, pPathStart, movementActivity ); -} - - -//--------------------------------------------------------- -// Disables the minigun until EnableMinigun input is received. -//--------------------------------------------------------- -void CNPC_Strider::InputDisableMinigun( inputdata_t &inputdata ) -{ - m_bMinigunEnabled = false; - m_pMinigun->Enable( this, false ); -} - - -//--------------------------------------------------------- -// Enables the minigun. -//--------------------------------------------------------- -void CNPC_Strider::InputEnableMinigun( inputdata_t &inputdata ) -{ - m_bMinigunEnabled = true; - m_pMinigun->Enable( this, true ); -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::InputSetMinigunTime( inputdata_t &inputdata ) -{ - m_miniGunShootDuration = inputdata.value.Float(); - m_pMinigun->SetShootDuration( m_miniGunShootDuration ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::InputSetMinigunTarget( inputdata_t &inputdata ) -{ - CBaseEntity *pTargetEntity = gEntList.FindEntityByName( NULL, inputdata.value.String(), NULL, inputdata.pActivator, inputdata.pCaller ); - - m_pMinigun->StopShootingForSeconds( this, m_pMinigun->GetTarget(), 0 ); - m_pMinigun->ShootAtTarget( this, pTargetEntity, m_miniGunShootDuration ); - m_miniGunShootDuration = 0; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::InputSetCannonTarget( inputdata_t &inputdata ) -{ - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, inputdata.value.String(), NULL, inputdata.pActivator, inputdata.pCaller ); - - if ( pTarget ) - { - if ( m_hCannonTarget == pTarget ) - return; - - CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); - CNPC_Strider *pStrider; - for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - if ( ppAIs[i] != this && ppAIs[i]->ClassMatches( GetClassname() ) ) - { - pStrider = (CNPC_Strider *)(ppAIs[i]); - if ( pStrider->GetCannonTarget() == pTarget ) - return; // Already accounted for - } - } - - if( pTarget->MyCombatCharacterPointer() && pTarget->IsAlive() ) - { - m_hCannonTarget = pTarget; - m_AttemptCannonLOSTimer.Force(); - return; - } - } - - m_hCannonTarget = NULL; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::InputFlickRagdoll( inputdata_t &inputdata ) -{ - if ( m_hRagdoll.Get() ) - { - SetCondition( COND_STRIDER_DO_FLICK ); - } -} - - -/* - IPhysicsObject *pPhysics0 = FindPhysicsObjectByName( STRING(m_nameAttach1), this ); - IPhysicsObject *pPhysics1 = FindPhysicsObjectByName( STRING(m_nameAttach2), this ); - - if ( !pPhysics0 ) - { - pPhysics0 = g_PhysWorldObject; - } - if ( !pPhysics1 ) - { - pPhysics1 = g_PhysWorldObject; - } - - if ( pPhysics0 != pPhysics1 ) - { - m_disabled = !bEnable; - m_succeeded = true; - if ( bEnable ) - { - PhysEnableEntityCollisions( pPhysics0, pPhysics1 ); - } - else - { - PhysDisableEntityCollisions( pPhysics0, pPhysics1 ); - } - } - else - { - m_succeeded = false; - } -*/ -/* -#pragma warning(push) -#pragma warning(disable : 4706) // I know what I'm doing -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::InputDisableCollisionWith( inputdata_t &inputdata ) -{ - IPhysicsObject *pIgnorePhys = FindPhysicsObjectByName( inputdata.value.String(), this ); - if ( !pIgnorePhys ) - return; - - int idx; - CBoneFollower *pFol; - - for (idx = 0 ; pFol = GetBoneFollowerByIndex(idx) ; ++idx) // stop when the function starts returning null (idx is no longer good) - { - IPhysicsObject *pFollowPhys = pFol->VPhysicsGetObject(); - Assert(pFollowPhys); - PhysDisableEntityCollisions( pIgnorePhys, pFollowPhys ); - } -} -#pragma warning(pop) -*/ - - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::InputDisableCollisionWith( inputdata_t &inputdata ) -{ - IPhysicsObject *pIgnorePhys = FindPhysicsObjectByName( inputdata.value.String(), this ); - if ( !pIgnorePhys ) - return; - - - // CBoneFollower *pFol; - - for (int idx = m_BoneFollowerManager.GetNumBoneFollowers() - 1 ; idx >= 0 ; --idx) // stop when the function starts returning null (idx is no longer good) - { - IPhysicsObject *pFollowPhys = GetBoneFollowerByIndex(idx)->VPhysicsGetObject(); - Assert(pFollowPhys); - PhysDisableEntityCollisions( pIgnorePhys, pFollowPhys ); - } -} - - - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::InputEnableCollisionWith( inputdata_t &inputdata ) -{ - IPhysicsObject *pIgnorePhys = FindPhysicsObjectByName( inputdata.value.String(), this ); - if ( !pIgnorePhys ) - return; - - int idx; - // CBoneFollower *pFol; - - for (idx = m_BoneFollowerManager.GetNumBoneFollowers() - 1 ; idx >= 0 ; --idx) // stop when the function starts returning null (idx is no longer good) - { - /* - pFol = GetBoneFollowerByIndex(idx); - Assert(pFol); - IPhysicsObject *pFollowPhys = pFol->VPhysicsGetObject(); - Assert(pFollowPhys); - */ - IPhysicsObject *pFollowPhys = GetBoneFollowerByIndex(idx)->VPhysicsGetObject(); - PhysEnableEntityCollisions( pIgnorePhys, pFollowPhys ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::InputCrouch( inputdata_t &inputdata ) -{ - if ( !IsCurSchedule( SCHED_STRIDER_CROUCH ) && !IsInCrouchedPosture() ) - SetCondition( COND_STRIDER_SHOULD_CROUCH ); - m_bCrouchLocked = true; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::InputCrouchInstantly( inputdata_t &inputdata ) -{ - if ( !IsCurSchedule( SCHED_STRIDER_CROUCH ) && !IsInCrouchedPosture() ) - { - m_bFastCrouch = true; - SetCondition( COND_STRIDER_SHOULD_CROUCH ); - } - m_bCrouchLocked = true; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::InputStand( inputdata_t &inputdata ) -{ - if ( !IsCurSchedule( SCHED_STRIDER_STAND ) && !IsInStandingPosture() ) - SetCondition( COND_STRIDER_SHOULD_STAND ); - m_bCrouchLocked = false; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::InputSetHeight( inputdata_t &inputdata ) -{ - SetIdealHeight( inputdata.value.Float() ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::InputSetTargetPath( inputdata_t &inputdata ) -{ - m_strTrackName = MAKE_STRING( inputdata.value.String() ); - SetGoalEnt( NULL ); - - if( !IsStriderCrouching() && !IsStriderStanding() && !IsInCrouchedPosture() ) - { - SetTargetPath(); - } - - // Otherwise, we just leave the track name set and the AI will - // get to it as soon as possible (as soon as the strider can be - // made to stand). -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::InputClearTargetPath( inputdata_t &inputdata ) -{ - if (GetNavigator()->IsGoalActive() && GetNavigator()->GetGoalType() == GOALTYPE_PATHCORNER ) - { - GetNavigator()->ClearGoal(); - ClearSchedule( "Target path cleared via input" ); - } - m_strTrackName = MAKE_STRING( STRIDER_NO_TRACK_NAME ); - SetGoalEnt(NULL); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::InputDisableCrouchWalk( inputdata_t &inputdata ) -{ - m_bNoCrouchWalk = true; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::InputEnableCrouchWalk( inputdata_t &inputdata ) -{ - m_bNoCrouchWalk = false; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::InputEnableAggressiveBehavior( inputdata_t &inputdata ) -{ - m_bUseAggressiveBehavior = true; - GetEnemies()->SetEnemyDiscardTime( 601.0f ); // Make the assert in SetFreeKnowledgeDuration() happy. - GetEnemies()->SetFreeKnowledgeDuration( 600.0f ); - - AI_FreePassParams_t params = m_PlayerFreePass.GetParams(); - params.duration = 0.8f; - params.coverDist = 1200.0f; - m_PlayerFreePass.SetParams( params ); - - GetTacticalServices()->AllowFindLateralLos( false ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::InputDisableAggressiveBehavior( inputdata_t &inputdata ) -{ - m_bUseAggressiveBehavior = false; - GetEnemies()->SetFreeKnowledgeDuration( strider_free_knowledge.GetFloat() ); - GetEnemies()->SetEnemyDiscardTime( AI_DEF_ENEMY_DISCARD_TIME ); - - AI_FreePassParams_t params = m_PlayerFreePass.GetParams(); - params.duration = strider_free_pass_duration.GetFloat(); - params.coverDist = strider_free_pass_cover_dist.GetFloat(); - m_PlayerFreePass.SetParams( params ); - - GetTacticalServices()->AllowFindLateralLos( true ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::InputStopShootingMinigunForSeconds( inputdata_t &inputdata ) -{ - m_pMinigun->StopShootingForSeconds( this, NULL, inputdata.value.Float() ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::InputDisableCrouch( inputdata_t &inputdata ) -{ - m_bDontCrouch = true; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::InputDisableMoveToLOS( inputdata_t &inputdata ) -{ - m_bNoMoveToLOS = true; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::InputExplode( inputdata_t &inputdata ) -{ - CTakeDamageInfo killInfo; - killInfo.SetAttacker( this ); - killInfo.SetInflictor( this ); - killInfo.SetDamage( GetHealth() ); - TakeDamage( killInfo ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::InputScaleGroundSpeed( inputdata_t &inputdata ) -{ - m_flTargetSpeedScale = inputdata.value.Float(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Strider::FVisible( CBaseEntity *pEntity, int traceMask, CBaseEntity **ppBlocker ) -{ - bool bIsVisible = BaseClass::FVisible( pEntity, traceMask, ppBlocker ); - - if ( bIsVisible && pEntity == m_PlayerFreePass.GetPassTarget() ) - { - bIsVisible = m_PlayerFreePass.ShouldAllowFVisible( bIsVisible ); - - if( !bIsVisible && IsUsingAggressiveBehavior() && FInViewCone(pEntity) ) - { - AlertSound(); - } - } - - return bIsVisible; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -Vector CNPC_Strider::BodyTarget( const Vector &posSrc, bool bNoisy ) -{ - if ( m_BodyTargetBone != -1 ) - { - Vector position; - QAngle angles; - GetBonePosition( m_BodyTargetBone, position, angles ); - return position; - } - return BaseClass::BodyTarget( posSrc, bNoisy ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Strider::IsValidEnemy( CBaseEntity *pTarget ) -{ - if ( HasCannonTarget() ) - { - return IsCannonTarget(pTarget); - } - - if ( pTarget->IsPlayer() ) - { - if ( AIGetNumFollowers( this, m_iszHunterClassname ) > 0 ) - return false; - } - - CBaseCombatCharacter *pEnemy = ToBaseCombatCharacter( pTarget ); - if ( pEnemy ) - { - // Test our enemy filter - if ( m_hEnemyFilter.Get()!= NULL && m_hEnemyFilter->PassesFilter( this, pEnemy ) == false ) - return false; - - return true; - } - - return BaseClass::IsValidEnemy( pTarget ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Strider::UpdateEnemyMemory( CBaseEntity *pEnemy, const Vector &position, CBaseEntity *pInformer ) -{ - if( pInformer && FClassnameIs( pInformer, "npc_cscanner" ) ) - { - EmitSound( "NPC_Strider.Alert" ); - // Move Strider's focus to this location and make strider mad at it - // (but less mad than at any other potential entities in the scene). -#if 1 - GetFocus()->SetAbsOrigin( position + Vector( 0, 0, 32 ) ); -#else - trace_t tr; - AI_TraceLine( EyePosition(), position + Vector( 0, 0, 32 ), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - GetFocus()->SetAbsOrigin( tr.endpos ); -#endif - - SetCondition( COND_STRIDER_ENEMY_UPDATED ); - - m_EnemyUpdatedTimer.Set( 20 ); - - AddEntityRelationship( GetFocus(), D_HT, -1 ); - - if( pEnemy->IsPlayer() ) - { - m_PlayerFreePass.Revoke(); - } - - BaseClass::UpdateEnemyMemory( GetFocus(), GetFocus()->GetAbsOrigin(), pInformer ); - - // Change the informer to myself so that information provided by a scanner is - // as good as firsthand knowledge insofar as enemy memory is concerned. - pInformer = this; - } - - return BaseClass::UpdateEnemyMemory( pEnemy, position, pInformer ); -} - -//--------------------------------------------------------- -// HACKHACK: The base class looks at distance from the head of the strider -// But when stomping, we need distance from the feet. Recompute it here. -// UNDONE: make enemy distance aware of strider -//--------------------------------------------------------- -float CNPC_Strider::StriderEnemyDistance( CBaseEntity *pEnemy ) -{ - Vector enemyDelta = pEnemy->WorldSpaceCenter() - WorldSpaceCenter(); - - // NOTE: We ignore rotation for computing height. Assume it isn't an effect - // we care about, so we simply use OBBSize().z for height. - // Otherwise you'd do this: - // float enemyHeight = enemyMaxs.z - enemyMins.z; - - float enemyHeight = pEnemy->CollisionProp()->OBBSize().z; - Vector striderSurroundMins, striderSurroundMaxs; - CollisionProp()->WorldSpaceSurroundingBounds( &striderSurroundMins, &striderSurroundMaxs ); - float myHeight = striderSurroundMaxs.z - striderSurroundMins.z; - - // max distance our centers can be apart with the boxes still overlapping - float flMaxZDist = ( enemyHeight + myHeight ) * 0.5f; - - // see if the enemy is closer to my head, feet or in between - if ( enemyDelta.z > flMaxZDist ) - { - // enemy feet above my head, compute distance from my head to his feet - enemyDelta.z -= flMaxZDist; - } - else if ( enemyDelta.z < -flMaxZDist ) - { - // enemy head below my feet, return distance between my feet and his head - enemyDelta.z += flMaxZDist; - } - else - { - // boxes overlap in Z, no delta - enemyDelta.z = 0; - } - - return enemyDelta.Length(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Strider::FCanCheckAttacks() -{ - // Strider has direct and indirect attacks, so he's always checking - // as long as the enemy is in front of him. - if( FInViewCone( GetEnemy() ) ) - { - return true; - } - - return false; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CNPC_Strider::RangeAttack2Conditions( float flDot, float flDist ) -{ - // All of this code has moved to GatherConditions(), since the - // strider uses the cannon on things that aren't the enemy! - return COND_NONE; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CNPC_Strider::MeleeAttack1Conditions( float flDot, float flDist ) -{ - if ( m_bDisableBoneFollowers ) - { - return COND_NONE; - } - - if (gpGlobals->curtime < m_nextStompTime) - { - return COND_NONE; - } - - if ( IsInCrouchedPosture() ) - { - return COND_NONE; - } - - CBaseEntity *pEnemy = GetEnemy(); - if ( !pEnemy ) - return COND_NONE; - - // No more stabbing players. - if ( pEnemy->IsPlayer() && !HasSpawnFlags(SF_CAN_STOMP_PLAYER) ) - return COND_NONE; - - if( !HasCondition( COND_SEE_ENEMY ) ) - { - return COND_NONE; - } - - // recompute this because the base class function does not work for the strider - flDist = StriderEnemyDistance( pEnemy ); - - if ( flDist > STRIDER_STOMP_RANGE ) - { - return COND_NONE; - } - - // strider will cross his feet, but only 6ft over - Vector right; - GetVectors( NULL, &right, NULL ); - if ( DotProduct( pEnemy->GetAbsOrigin() - GetAbsOrigin(), right ) > 72 ) - { - return COND_NONE; - } - - // Don't skewer if crouched too low. - if( GetHeight() < GetMaxHeight() - ( (GetMaxHeight()-GetMinHeight()) / 2 ) ) - { - return COND_NONE; - } - - // Don't skewer if target is too high above or below ground. - Vector vecGround = GetAbsOrigin(); - MoveToGround( &vecGround, this, Vector( -16, -16, -16 ), Vector( 16, 16, 16 ) ); - if( fabs( vecGround.z - GetEnemy()->GetAbsOrigin().z ) > 64.0f ) - { - return COND_NONE; - } - - // too far, but don't change schedules/movement - return COND_CAN_MELEE_ATTACK1; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CNPC_Strider::MeleeAttack2Conditions( float flDot, float flDist ) -{ - // HACKHACK: Disabled until we get a good right-leg animation - return COND_NONE; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Strider::WeaponLOSCondition(const Vector &ownerPos, const Vector &targetPos, bool bSetConditions) -{ - CBaseEntity *pTargetEnt; - Vector vRootOffset; - Vector vBarrelOffset; - - vRootOffset.x = vRootOffset.y = 0; - if ( GetCannonTarget() ) - { - //Assert( targetPos == GetCannonTarget()->GetAbsOrigin() ); - pTargetEnt = GetCannonTarget(); - vRootOffset.z = gm_zCannonDist; - vBarrelOffset = gm_vLocalRelativePositionCannon; - } - else - { - pTargetEnt = GetEnemy(); - vRootOffset.z = gm_zMinigunDist; - vBarrelOffset = gm_vLocalRelativePositionMinigun; - } - - trace_t tr; - AI_TraceLine( ownerPos + vRootOffset, targetPos, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); - - // Hit the enemy, or hit nothing (traced all the way to a nonsolid enemy like a bullseye) - if ( ( pTargetEnt && tr.m_pEnt == pTargetEnt) || tr.fraction == 1.0 || CanShootThrough( tr, targetPos ) ) - { - Vector vBarrelPos; - matrix3x4_t losTestToWorld; - - Vector xaxis; - VectorSubtract( targetPos, ownerPos, xaxis ); - - // @TODO (toml 03-07-04): Add an angle test - //float flAngle = acos( xaxis.z / xaxis.Length() ); - - xaxis.z = 0.0f; - float flLength = VectorNormalize( xaxis ); - if ( flLength < 1e-3 ) - return false; - - Vector yaxis( -xaxis.y, xaxis.x, 0.0f ); - - MatrixInitialize( losTestToWorld, ownerPos, xaxis, yaxis, Vector(0,0,1) ); - - VectorTransform( vBarrelOffset, losTestToWorld, vBarrelPos ); - - AI_TraceLine( vBarrelPos, targetPos, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); - if ( ( pTargetEnt && tr.m_pEnt == pTargetEnt) || tr.fraction == 1.0 || CanShootThrough( tr, targetPos ) ) - { - if ( strider_show_weapon_los_condition.GetBool() ) - { - NDebugOverlay::Line( ownerPos + vRootOffset, targetPos, 255, 0, 255, false, 0.1 ); - NDebugOverlay::Line( vBarrelPos, targetPos, 128, 0, 128, false, 0.1 ); - } - return true; - } - else - { - if ( strider_show_weapon_los_condition.GetBool() ) - { - NDebugOverlay::Line( ownerPos + vRootOffset, targetPos, 255, 0, 255, false, 0.1 ); - NDebugOverlay::Line( vBarrelPos, tr.endpos, 128, 0, 0, false, 0.1 ); - } - } - } - else - { - if ( strider_show_weapon_los_condition.GetBool() ) - { - NDebugOverlay::Line( ownerPos + vRootOffset, tr.endpos, 255, 0, 0, false, 0.1 ); - } - } - - return false; -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Strider::CurrentWeaponLOSCondition(const Vector &targetPos, bool bSetConditions) -{ - return WeaponLOSCondition( GetAdjustedOrigin(), targetPos, bSetConditions ); -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Strider::IsValidShootPosition( const Vector &vecCoverLocation, CAI_Node *pNode, CAI_Hint const *pHint ) -{ - if ( ( pNode && !pHint ) || ( pHint && pHint->HintType() != HINT_STRIDER_NODE ) ) - return false; - return BaseClass::IsValidShootPosition( vecCoverLocation, pNode, pHint ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Strider::TestShootPosition(const Vector &vecShootPos, const Vector &targetPos ) -{ - if ( BaseClass::TestShootPosition( vecShootPos, targetPos ) ) - { - return true; - } - - // What if I crouched? - float zDelta = ( ( vecShootPos.z - targetPos.z ) + gm_vLocalRelativePositionMinigun.z ) - 12; - if ( zDelta > 0 ) - { - if ( zDelta > GetHeightRange() ) - zDelta = GetHeightRange(); - - Vector vecTestPos = vecShootPos; - vecTestPos.z -= zDelta; - - if ( BaseClass::TestShootPosition( vecTestPos, targetPos ) ) - { - return true; - } - } - return false; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -Vector CNPC_Strider::Weapon_ShootPosition( ) -{ - Vector vecShootPos; - GetAttachment( gm_CannonAttachment, vecShootPos ); - - return vecShootPos; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ) -{ - float flTracerDist; - Vector vecDir; - Vector vecEndPos; - - vecDir = tr.endpos - vecTracerSrc; - - flTracerDist = VectorNormalize( vecDir ); - - UTIL_Tracer( vecTracerSrc, tr.endpos, 0, TRACER_DONT_USE_ATTACHMENT, 5000, true, "StriderTracer" ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::DoImpactEffect( trace_t &tr, int nDamageType ) -{ - BaseClass::DoImpactEffect( tr, nDamageType ); - - // Add a halo - CBroadcastRecipientFilter filter; - te->BeamRingPoint( filter, 0.0, - tr.endpos, //origin - 0, //start radius - 64, //end radius - s_iImpactEffectTexture, //texture - 0, //halo index - 0, //start frame - 0, //framerate - 0.2, //life - 10, //width - 0, //spread - 0, //amplitude - 255, //r - 255, //g - 255, //b - 50, //a - 0, //speed - FBEAM_FADEOUT - ); - - g_pEffects->EnergySplash( tr.endpos, tr.plane.normal ); - - // Punch the effect through? - if( tr.m_pEnt && !tr.m_pEnt->MyNPCPointer() ) - { - Vector vecDir = tr.endpos - tr.startpos; - VectorNormalize( vecDir ); - - trace_t retrace; - - Vector vecReTrace = tr.endpos + vecDir * 12; - - if( UTIL_PointContents( vecReTrace ) == CONTENTS_EMPTY ) - { - AI_TraceLine( vecReTrace, vecReTrace - vecDir * 24, MASK_SHOT, NULL, COLLISION_GROUP_NONE, &retrace ); - - BaseClass::DoImpactEffect( retrace, nDamageType ); - } - } -} - -//--------------------------------------------------------- -// Trace didn't hit the intended target, but should the strider -// shoot anyway? We use this to get the strider to destroy -// breakables that are between him and his target. -//--------------------------------------------------------- -bool CNPC_Strider::CanShootThrough( const trace_t &tr, const Vector &vecTarget ) -{ - if( GetCannonTarget() ) - { - // Cannon does not have this behavior. - return false; - } - - if( !tr.m_pEnt ) - { - return false; - } - - if( !tr.m_pEnt->GetHealth() ) - { - return false; - } - - // Would a trace ignoring this entity continue to the target? - trace_t continuedTrace; - AI_TraceLine( tr.endpos, vecTarget, MASK_SHOT, tr.m_pEnt, COLLISION_GROUP_NONE, &continuedTrace ); - - if( continuedTrace.fraction != 1.0 ) - { - if( continuedTrace.m_pEnt != GetEnemy() ) - { - return false; - } - } - - return true; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::CreateFocus() -{ - m_hFocus = CreateEntityByName( "bullseye_strider_focus" ); - - ASSERT( m_hFocus != NULL ); - m_hFocus->AddSpawnFlags( SF_BULLSEYE_NONSOLID | SF_BULLSEYE_NODAMAGE ); - m_hFocus->SetAbsOrigin( GetAbsOrigin() ); - m_hFocus->Spawn(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -CNPC_Bullseye *CNPC_Strider::GetFocus() -{ - ASSERT( m_hFocus != NULL ); - - CNPC_Bullseye *pBull = dynamic_cast(m_hFocus.Get()); - - return pBull; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Strider::GetWeaponLosZ( const Vector &vOrigin, float minZ, float maxZ, float increment, CBaseEntity *pTarget, float *pResult ) -{ - Vector vTestPos; - Vector vTargetPos = pTarget->BodyTarget(vOrigin, false); - Vector vIncrement( 0, 0, increment ); - - // Try right where am - if ( vOrigin.z >= minZ && vOrigin.z <= maxZ ) - { - vTestPos = vOrigin; - if ( WeaponLOSCondition( vTestPos, vTargetPos, false ) ) - { - if ( strider_show_weapon_los_z.GetBool() ) - NDebugOverlay::Line( vTestPos, vTargetPos, 0, 255, 0, false, 0.1 ); - *pResult = vTestPos.z; - return true; - } - } - - // Try at adjusted height of target - vTestPos.z = ( vTargetPos.z - gm_vLocalRelativePositionMinigun.z ) + 12; - - if ( vTestPos.z >= minZ && vTestPos.z <= maxZ ) - { - if ( WeaponLOSCondition( vTestPos, vTargetPos, false ) ) - { - if ( strider_show_weapon_los_z.GetBool() ) - NDebugOverlay::Line( vTestPos, vTargetPos, 0, 255, 0, false, 0.1 ); - *pResult = vTestPos.z; - return true; - } - } - - - // Try at max height - vTestPos.z = maxZ; - if ( WeaponLOSCondition( vTestPos, vTargetPos, false ) ) - { - if ( strider_show_weapon_los_z.GetBool() ) - NDebugOverlay::Line( vOrigin, vTargetPos, 0, 255, 0, false, 0.1 ); - *pResult = vTestPos.z; - return true; - } - - // Try min height - vTestPos.z = minZ; - if ( WeaponLOSCondition( vTestPos, vTargetPos, false ) ) - { - if ( strider_show_weapon_los_z.GetBool() ) - NDebugOverlay::Line( vTestPos, vTargetPos, 0, 255, 0, false, 0.1 ); - *pResult = vTestPos.z; - return true; - } - - // Test up from min - vTestPos = vOrigin + vIncrement; - while ( vTestPos.z <= maxZ && !WeaponLOSCondition( vTestPos, vTargetPos, false ) ) - { - vTestPos += vIncrement; - } - - if ( vTestPos.z <= maxZ ) - { - if ( strider_show_weapon_los_z.GetBool() ) - NDebugOverlay::Line( vTestPos, vTargetPos, 0, 255, 0, false, 0.1 ); - *pResult = vTestPos.z; - return true; - } - - // Test down - vTestPos = vOrigin - vIncrement; - while ( vTestPos.z >= minZ && !WeaponLOSCondition( vTestPos, vTargetPos, false ) ) - { - vTestPos -= vIncrement; - } - - if ( vTestPos.z >= minZ ) - { - if ( strider_show_weapon_los_z.GetBool() ) - NDebugOverlay::Line( vTestPos, vTargetPos, 0, 255, 0, false, 0.1 ); - *pResult = vTestPos.z; - return true; - } - - return false; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::AlertSound() -{ - if( ( gpGlobals->curtime - m_flTimeLastAlertSound ) > 2.0f ) - { - EmitSound( "NPC_Strider.Alert" ); - m_flTimeLastAlertSound = gpGlobals->curtime; - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::PainSound( const CTakeDamageInfo &info ) -{ - // This means that we've exploded into pieces and have no way to whimper - if ( ShouldExplodeFromDamage( info ) ) - return; - - EmitSound( "NPC_Strider.Pain" ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::DeathSound( const CTakeDamageInfo &info ) -{ - // This means that we've exploded into pieces and have no way to whimper - if ( m_bExploding ) - { - EmitSound( "NPC_Strider.StriderBusterExplode" ); - EmitSound( "explode_5" ); - return; - } - - EmitSound( "NPC_Strider.Death" ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::HuntSound() -{ - if( m_PlayerFreePass.HasPass() ) - { - EmitSound( "NPC_Strider.Hunt" ); - m_flTimeNextHuntSound = gpGlobals->curtime + random->RandomFloat( 8.0f, 12.0f ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::TraceAttack( const CTakeDamageInfo &inputInfo, const Vector &vecDir, trace_t *ptr ) -{ - CTakeDamageInfo info = inputInfo; - - bool ricochetBullets = true; - - if ( info.GetAttacker()->IsPlayer() ) - { - if ( !HasMemory( bits_MEMORY_PROVOKED ) ) - { - GetEnemies()->ClearMemory( info.GetAttacker() ); - Remember( bits_MEMORY_PROVOKED ); - SetCondition( COND_LIGHT_DAMAGE ); - } - } - -#ifdef HL2_EPISODIC - - // Attempt to hit strider busters in the area - float flDistSqr; - for ( int i = 0; i < m_hAttachedBusters.Count(); i++ ) - { - if ( m_hAttachedBusters[i] == NULL ) - continue; - - flDistSqr = ( m_hAttachedBusters[i]->WorldSpaceCenter() - inputInfo.GetDamagePosition() ).LengthSqr(); - if ( flDistSqr < Square( 50.0f ) ) - { - // Kill the buster and stop the trace going through - CTakeDamageInfo killInfo = inputInfo; - killInfo.SetDamage( 100 ); - - m_hAttachedBusters[i]->TakeDamage( killInfo ); - return; - } - } - -#endif //HL2_EPISODIC - - if ( (info.GetDamageType() & DMG_BULLET) && ricochetBullets ) - { - g_pEffects->Ricochet(ptr->endpos,ptr->plane.normal); - if ( ptr->hitgroup != HITGROUP_HEAD ) - { - info.SetDamage( 0.01 ); - } - } - - BaseClass::TraceAttack( info, vecDir, ptr ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CNPC_Strider::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - // don't take damage from my own weapons!!! - if ( info.GetInflictor() && info.GetInflictor()->GetOwnerEntity() == this ) - return 0; - - // special interaction with combine balls - if ( UTIL_IsCombineBall( info.GetInflictor() ) ) - return TakeDamageFromCombineBall( info ); - - if ( info.GetDamageType() == DMG_GENERIC ) - return BaseClass::OnTakeDamage_Alive( info ); - - if( IsUsingAggressiveBehavior() ) - { - // Any damage the player inflicts gets my attention, even if it doesn't actually harm me. - if ( info.GetAttacker()->IsPlayer() ) - { - UpdateEnemyMemory( info.GetAttacker(), info.GetAttacker()->GetAbsOrigin() ); - } - } - - //int healthIncrement = 5 - ( m_iHealth / ( m_iMaxHealth / 5 ) ); - if ( (info.GetDamageType() & DMG_BLAST) && info.GetMaxDamage() > 50 ) - { - Vector headPos = BodyTarget( info.GetDamagePosition(), false ); - - float dist = CalcDistanceToAABB( WorldAlignMins(), WorldAlignMaxs(), info.GetDamagePosition() - headPos ); - // close enough to do damage? - if ( dist < 200 ) - { - bool bPlayer = info.GetAttacker()->IsPlayer(); - if ( bPlayer ) - { - m_PlayerFreePass.Revoke(); - AddFacingTarget( info.GetAttacker(), info.GetAttacker()->GetAbsOrigin(), 1.0, 2.0 ); - - UpdateEnemyMemory( info.GetAttacker(), info.GetAttacker()->GetAbsOrigin() ); - } - else - AddFacingTarget( info.GetAttacker(), info.GetAttacker()->GetAbsOrigin(), 0.5, 2.0 ); - - // Default to NPC damage value - int damage = 20; - - if( HasSpawnFlags(SF_TAKE_MINIMAL_DAMAGE_FROM_NPCS) ) - damage = 1; - - if( bPlayer ) - { - if( g_pGameRules->IsSkillLevel(SKILL_EASY) ) - { - damage = GetMaxHealth() / sk_strider_num_missiles1.GetInt(); - } - else if( g_pGameRules->IsSkillLevel(SKILL_HARD) ) - { - damage = GetMaxHealth() / sk_strider_num_missiles3.GetInt(); - } - else // Medium, or unspecified - { - damage = GetMaxHealth() / sk_strider_num_missiles2.GetInt(); - } - } - - m_iHealth -= damage; - - m_OnDamaged.FireOutput( info.GetAttacker(), this); - - if( info.GetAttacker()->IsPlayer() ) - { - m_OnDamagedByPlayer.FireOutput( info.GetAttacker(), this ); - - // This also counts as being harmed by player's squad. - m_OnDamagedByPlayerSquad.FireOutput( info.GetAttacker(), this ); - } - else - { - // See if the person that injured me is an NPC. - CAI_BaseNPC *pAttacker = dynamic_cast( info.GetAttacker() ); - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - - if( pAttacker && pAttacker->IsAlive() && pPlayer ) - { - if( pAttacker->GetSquad() != NULL && pAttacker->IsInPlayerSquad() ) - { - m_OnDamagedByPlayerSquad.FireOutput( info.GetAttacker(), this ); - } - } - } - - if ( m_iHealth <= ( m_iMaxHealth / 2 ) ) - { - m_OnHalfHealth.FireOutput(this, this); - } - - RestartGesture( ACT_GESTURE_SMALL_FLINCH ); - PainSound( info ); - - // Interrupt our gun during the flinch - m_pMinigun->StopShootingForSeconds( this, m_pMinigun->GetTarget(), 1.1f ); - - GetEnemies()->OnTookDamageFrom( info.GetAttacker() ); - - if( !IsSmoking() && m_iHealth <= sk_strider_health.GetInt() / 2 ) - { - StartSmoking(); - } - return damage; - } - -// NOTE: Currently radius damage doesn't even call this because it uses the origin, not the box for distance -#if 0 - NDebugOverlay::Box( headPos, WorldAlignMins(), WorldAlignMaxs(), 255, 0, 0, 0, 5.0 ); - NDebugOverlay::Cross3D( inf - o.GetDamagePosition(), 24, 0, 255, 0, false, 5.0 ); - // too far from head, apply damage to nearest leg? -#endif - } - -#if 0 - if ( (info.GetDamageType() & DMG_BULLET) && info.GetDamage() > 1 && m_iHealth > 1 ) - { - m_iHealth -= 1; - return 1; - } -#endif - - return 0; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CNPC_Strider::TakeDamageFromCombineBall( const CTakeDamageInfo &info ) -{ - float damage = info.GetDamage(); - - // If it's only an AR2 alt-fire, we don't take much damage - if ( UTIL_IsAR2CombineBall( info.GetInflictor() ) ) - { - damage = strider_ar2_altfire_dmg.GetFloat(); - } - else - { - // Always start smoking when we're struck by a normal combine ball - StartSmoking(); - } - - if( info.GetAttacker() && info.GetAttacker()->IsPlayer() ) - { - // Route combine ball damage through the regular skill level code. - damage = g_pGameRules->AdjustPlayerDamageInflicted(damage); - } - - AddFacingTarget( info.GetInflictor(), info.GetInflictor()->GetAbsOrigin(), 0.5, 2.0 ); - if ( !UTIL_IsAR2CombineBall( info.GetInflictor() ) ) - RestartGesture( ACT_GESTURE_BIG_FLINCH ); - else - RestartGesture( ACT_GESTURE_SMALL_FLINCH ); - - PainSound( info ); - - m_iHealth -= damage; - - return (int)damage; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::Event_Killed( const CTakeDamageInfo &info ) -{ - // Do a special death if we're killed by a combine ball in the Citadel - if ( info.GetInflictor() && UTIL_IsCombineBall( info.GetInflictor() ) ) - { - if ( m_lifeState == LIFE_DYING ) - return; - - // Tracker 23610: Strider playing death sounds twice (AI_BaseNPC calls it in Event_Killed, too) - // DeathSound( info ); - m_lifeState = LIFE_DYING; - - // Start dying - RestartGesture( (Activity) ACT_STRIDER_GESTURE_DEATH ); - - // Stop our mini-cannon - m_pMinigun->StopShootingForSeconds( this, m_pMinigun->GetTarget(), 100.0f ); - } - else - { - StopSmoking(); - - m_BoneFollowerManager.DestroyBoneFollowers(); - - } - - if( IsUsingAggressiveBehavior() ) - { - // Lifted this code from the gunship. - Vector vecExplode; - GetAttachment( "minigun", vecExplode ); - ExplosionCreate( vecExplode, QAngle(0,0,1), this, 100, 128, false ); - } - - // Determine if we're going to explode into pieces - m_bExploding = ShouldExplodeFromDamage( info ); - - BaseClass::Event_Killed( info ); - - // Stop our large cannon - EntityMessageBegin( this, true ); - WRITE_BYTE( STRIDER_MSG_DEAD ); - MessageEnd(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::RagdollDeathEffect( CRagdollProp *pRagdoll, float flDuration ) -{ - UTIL_ScreenShake( EyePosition(), 50, 150.0, 1.0, 1024, SHAKE_START ); - - int i; - for( i = 0 ; i < 2 ; i++ ) - { - SmokeTrail *pSmoke = SmokeTrail::CreateSmokeTrail(); - if ( pSmoke ) - { - if( i == 0 ) - { - pSmoke->m_SpawnRate = 16; - pSmoke->m_Opacity = 0.25; - pSmoke->m_StartColor.Init( 0.45f, 0.45f, 0.45f ); - } - else - { - pSmoke->m_SpawnRate = 32; - pSmoke->m_Opacity = 0.3; - pSmoke->m_StartColor.Init( 0.5f, 0.5f, 0.5f ); - } - - pSmoke->m_ParticleLifetime = 3.0; - pSmoke->m_StartSize = 16; - pSmoke->m_EndSize = 64; - pSmoke->m_SpawnRadius = 20; - pSmoke->m_MinSpeed = 8; - pSmoke->m_MaxSpeed = 64; - pSmoke->m_EndColor.Init( 0, 0, 0 ); - - pSmoke->SetLifetime( flDuration ); - - if( i == 0 ) - { - pSmoke->FollowEntity( pRagdoll, "MiniGunBase" ); - } - else - { - pSmoke->FollowEntity( pRagdoll, "vehicle_driver_eyes" ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Strider::ShouldExplodeFromDamage( const CTakeDamageInfo &info ) -{ - CBaseEntity *pInflictor = info.GetInflictor(); - if ( pInflictor == NULL ) - return false; - - // Combine balls make us explode - if ( UTIL_IsCombineBall( info.GetInflictor() ) ) - return true; - - // Stickybombs make us explode - CBaseEntity *pAttacker = info.GetAttacker(); - if ( pAttacker != NULL && (FClassnameIs( pAttacker, "weapon_striderbuster" ) || - FClassnameIs( pAttacker, "npc_grenade_magna" ))) - return true; - - if ( pInflictor == this && pAttacker == this ) - return true; - - return false; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -ConVarRef mat_dxlevel( "mat_dxlevel" ); -bool CNPC_Strider::BecomeRagdoll( const CTakeDamageInfo &info, const Vector &forceVector ) -{ - // Combine balls make us explode - if ( m_bExploding ) - { - Explode(); - } - else - { - // Otherwise just keel over - CRagdollProp *pRagdoll = NULL; - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer && mat_dxlevel.GetInt() > 0 ) - { - int dxlevel = mat_dxlevel.GetInt(); - int maxRagdolls = ( dxlevel >= 90 ) ? 2 : ( dxlevel >= 80 ) ? 1 : 0; - - if ( maxRagdolls > 0 ) - { - CUtlVectorFixed striderRagdolls; - while ( ( pRagdoll = gEntList.NextEntByClass( pRagdoll ) ) != NULL ) - { - if ( pRagdoll->GetModelName() == GetModelName() && !pRagdoll->IsFading() ) - { - Assert( striderRagdolls.Count() < striderRagdolls.NumAllocated() ); - if ( striderRagdolls.Count() < striderRagdolls.NumAllocated() ) - striderRagdolls.AddToTail( pRagdoll ); - } - } - - if ( striderRagdolls.Count() >= maxRagdolls ) - { - float distSqrFurthest = FLT_MAX; - CRagdollProp *pFurthest = NULL; - - for ( int i = 0; i < striderRagdolls.Count(); i++ ) - { - float distSqrCur = CalcSqrDistanceToAABB( striderRagdolls[i]->WorldAlignMins(), striderRagdolls[i]->WorldAlignMaxs(), pPlayer->GetAbsOrigin() ); - if ( distSqrCur < distSqrFurthest ) - { - distSqrFurthest = distSqrCur; - pFurthest = striderRagdolls[i]; - } - } - - if ( pFurthest ) - pFurthest->FadeOut( 0.75, 1.5 ); - } - } - - pRagdoll = assert_cast( CreateServerRagdoll( this, m_nForceBone, info, HL2COLLISION_GROUP_STRIDER ) ); - pRagdoll->DisableAutoFade(); - - if ( maxRagdolls == 0 ) - { - pRagdoll->FadeOut( 6.0, .75 ); - RagdollDeathEffect( pRagdoll, 6.0f ); - } - else - { - RagdollDeathEffect( pRagdoll, 600.0f ); - } - } - else - { - // Otherwise just keel over - pRagdoll = assert_cast( CreateServerRagdoll( this, m_nForceBone, info, HL2COLLISION_GROUP_STRIDER ) ); - pRagdoll->DisableAutoFade(); - } - } - - UTIL_Remove(this); - - return true; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::StartSmoking( void ) -{ - if ( m_hSmoke != NULL ) - return; - - m_hSmoke = SmokeTrail::CreateSmokeTrail(); - - if ( m_hSmoke ) - { - m_hSmoke->m_SpawnRate = 32; - m_hSmoke->m_ParticleLifetime = 3.0; - m_hSmoke->m_StartSize = 16; - m_hSmoke->m_EndSize = 64; - m_hSmoke->m_SpawnRadius = 20; - m_hSmoke->m_MinSpeed = 8; - m_hSmoke->m_MaxSpeed = 64; - m_hSmoke->m_Opacity = 0.3; - - m_hSmoke->m_StartColor.Init( 0.25f, 0.25f, 0.25f ); - m_hSmoke->m_EndColor.Init( 0, 0, 0 ); - m_hSmoke->SetLifetime( 500.0f ); - m_hSmoke->FollowEntity( this, "MiniGunBase" ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::StopSmoking( float flDelay ) -{ - if ( m_hSmoke ) - { - m_hSmoke->SetLifetime( flDelay ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::SetHeight( float h ) -{ - if ( h > GetMaxHeight() ) - h = GetMaxHeight(); - else if ( h < GetMinHeight() ) - h = GetMinHeight(); - - SetPoseParameter( gm_BodyHeightPoseParam, h ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::SetIdealHeight( float h ) -{ - if ( h > GetMaxHeight() ) - h = GetMaxHeight(); - else if ( h < GetMinHeight() ) - h = GetMinHeight(); - - m_idealHeight = h; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::SetAbsIdealHeight( float z ) -{ - float h = GetMaxHeight() - ( z - GetAbsOrigin().z ); - - SetIdealHeight( h ); -} - -//--------------------------------------------------------- -// At this moment, am I in the PROCESS of crouching? -// as in, and I transitioning from standing to crouch? -//--------------------------------------------------------- -bool CNPC_Strider::IsStriderCrouching() -{ - if( IsCurSchedule( SCHED_STRIDER_CROUCH, false ) ) - return true; - - return false; -} - -//--------------------------------------------------------- -// As IsStriderCrouching(), but for obvious differences. -//--------------------------------------------------------- -bool CNPC_Strider::IsStriderStanding() -{ - if( IsCurSchedule( SCHED_STRIDER_STAND, false ) ) - return true; - - return false; -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- - -bool CNPC_Strider::OverrideMove( float flInterval ) -{ - if ( GetCannonTarget() ) - { - AddFacingTarget( GetCannonTarget(), GetCannonTarget()->GetAbsOrigin(), 1.0, 0.5 ); - } - else if ( GetEnemy() ) - { - bool bPlayer = GetEnemy()->IsPlayer(); - float timeSinceSeenEnemy = gpGlobals->curtime - GetEnemyLastTimeSeen(); - if ( ( !bPlayer && timeSinceSeenEnemy < STRIDER_TIME_STOP_FACING_ENEMY ) || - ( bPlayer && !m_PlayerFreePass.HasPass() ) ) - { - AddFacingTarget( GetEnemy(), GetEnemies()->LastKnownPosition( GetEnemy() ), 1.0, 0.5 ); - } - - if ( !m_bCrouchLocked && !m_hCannonTarget && GetIdealHeight() < GetMaxHeight() && timeSinceSeenEnemy > TIME_CARE_ENEMY ) - SetIdealHeight( GetMaxHeight() ); - } - else if ( !m_bCrouchLocked && !m_hCannonTarget ) - SetIdealHeight( GetMaxHeight() ); - - if ( strider_test_height.GetFloat() > .1 ) - SetIdealHeight( strider_test_height.GetFloat() ); - - // If we're not supposed to crouch walk and we're under the threshold for what we consider crouch walking, stand back up! - if ( !m_bCrouchLocked && m_bNoCrouchWalk && IsMoving() && ( GetIdealHeight() < ( GetMinHeight() + GetHeightRange() * ( strider_pct_height_no_crouch_move.GetFloat() / 100.0 ) ) ) ) - { - SetIdealHeight( GetMinHeight() + GetHeightRange() * ( strider_pct_height_no_crouch_move.GetFloat() / 100.0 ) ); - } - - float heightMove = GetIdealHeight() - GetHeight(); - float heightMoveSign = ( heightMove < 0 ) ? -1 : 1; - heightMove = fabsf( heightMove ); - if ( heightMove > 0.01 ) - { - const float maxVelocity = 300; - const float minVelocity = 10; - - #define HEIGHTINVDECAY 0.8 // maintain X percent of velocity when slowing down - #define HEIGHTDECAYTIME 0.4161 // Sum( 1..cycle, HEIGHTINVDECAY^cycle ) - #define HEIGHTACCEL 0.5 // accel toward maxVelocity by X percent each cycle - - if (fabsf( m_HeightVelocity ) < minVelocity) - m_HeightVelocity = minVelocity * heightMoveSign; - - if (heightMove < m_HeightVelocity * heightMoveSign * HEIGHTDECAYTIME ) - { - m_HeightVelocity = m_HeightVelocity * HEIGHTINVDECAY; - - if (heightMove < m_HeightVelocity * heightMoveSign * flInterval) - { - m_HeightVelocity = heightMove * heightMoveSign / flInterval; - } - } - else - { - m_HeightVelocity = m_HeightVelocity * (1.0f - HEIGHTACCEL) + maxVelocity * HEIGHTACCEL * heightMoveSign; - if (heightMove < m_HeightVelocity * heightMoveSign * HEIGHTDECAYTIME) - { - m_HeightVelocity = heightMove * heightMoveSign / HEIGHTDECAYTIME; - } - } - - float newHeight = GetHeight() + m_HeightVelocity * flInterval; - SetHeight( newHeight ); - } - - // FIXME: where should this go? - MaintainTurnActivity( ); - - return false; -} - - -void CNPC_Strider::MaintainTurnActivity( void ) -{ - // detect that the npc has turned - if (m_prevYaw != GetAbsAngles().y) - { - float diff = UTIL_AngleDiff( m_prevYaw, GetAbsAngles().y ); - if (diff < 0.0) - { - m_doLeft += -diff; - } - else - { - m_doRight += diff; - } - m_prevYaw = GetAbsAngles().y; - } - // accumulate turn angle, delay response for short turns - m_doTurn += m_doRight + m_doLeft; - if (!IsMoving() && m_doTurn > 180.0f && m_flNextTurnAct < gpGlobals->curtime ) - { - int iSeq = ACT_INVALID; - if (m_doLeft > m_doRight) - { - iSeq = SelectWeightedSequence( ACT_GESTURE_TURN_LEFT ); - } - else - { - iSeq = SelectWeightedSequence( ACT_GESTURE_TURN_RIGHT ); - } - if (iSeq != ACT_INVALID) - { - int iLayer = AddGestureSequence( iSeq ); - if (iLayer != -1) - { - SetLayerPriority( iLayer, 100 ); - // increase speed if we're getting behind or they're turning quickly - if (m_doTurn > 360.0) - { - SetLayerPlaybackRate( iLayer, 1.5 ); - } - m_flNextTurnAct = gpGlobals->curtime + GetLayerDuration( iLayer ); - } - else - { - // too busy, try again in half a second - m_flNextTurnAct = gpGlobals->curtime + 0.5; - } - } - m_doTurn = m_doLeft = m_doRight = 0.0; - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Strider::IsUnusableNode(int iNodeID, CAI_Hint *pHint) -{ - if ( !BaseClass::IsUnusableNode(iNodeID, pHint) ) - { - if ( pHint && pHint->HintType() == HINT_STRIDER_NODE ) - return false; - } - return true; -} - -//--------------------------------------------------------- -// Purpose: Compute the nav position for the strider's origin relative to this enemy. -//--------------------------------------------------------- -void CNPC_Strider::TranslateNavGoal( CBaseEntity *pEnemy, Vector &chasePosition ) -{ - if ( pEnemy ) - { - if ( ! (pEnemy->GetFlags() & FL_ONGROUND) ) - { - MoveToGround( &chasePosition, pEnemy, pEnemy->WorldAlignMins(), pEnemy->WorldAlignMaxs() ); - } - - // move down to enemy's feet for enemy origin at chasePosition - chasePosition.z += pEnemy->WorldAlignMins().z; - - } - else - { - MoveToGround( &chasePosition, NULL, Vector( -16, -16, 0 ), Vector( 16, 16, 32 ) ); - } - - // move up to strider stand height - chasePosition.z += GetMaxHeight() + npc_strider_height_adj.GetFloat(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Strider::HasPendingTargetPath() -{ - bool bReturn = ( !FStrEq( STRING(m_strTrackName), STRIDER_NO_TRACK_NAME ) && !GetGoalEnt() ); - - return bReturn; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::SetTargetPath() -{ - SetGoalEnt( NULL ); - CBaseEntity *pGoalEnt = gEntList.FindEntityByName( NULL, m_strTrackName ); - if ( pGoalEnt == NULL ) - { - DevWarning( "%s: Could not find target path '%s'!\n", GetClassname(), STRING( m_strTrackName ) ); - - // Don't try anymore. It just hurts the AI. - m_strTrackName = MAKE_STRING( STRIDER_NO_TRACK_NAME ); - - UTIL_Remove( this ); - return; - } - - const Vector &absOrigin = GetAbsOrigin(); - CBaseEntity *pClosestEnt = NULL; - CBaseEntity *pCurEnt = pGoalEnt; - float distClosestSq = FLT_MAX; - - CUtlRBTree visits; - SetDefLessFunc(visits); - - while ( pCurEnt && visits.Find( pCurEnt ) == visits.InvalidIndex() ) - { - float distCurSq = ( pCurEnt->GetAbsOrigin() - absOrigin ).LengthSqr(); - if ( distCurSq < distClosestSq ) - { - distClosestSq = distCurSq; - pClosestEnt = pCurEnt; - } - visits.Insert( pCurEnt ); - pCurEnt = GetNavigator()->GetNextPathcorner( pCurEnt ); - } - - ScheduledFollowPath( SCHED_IDLE_WALK, pClosestEnt, ACT_WALK ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- - -float CNPC_Strider::GetDefaultNavGoalTolerance() -{ - return 64; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::OnMovementComplete() -{ - if ( GetGoalEnt() && - ( IsCurSchedule( SCHED_IDLE_WALK ) || - IsCurSchedule( SCHED_ALERT_WALK ) || - IsCurSchedule( SCHED_COMBAT_WALK ) || - IsCurSchedule( SCHED_STRIDER_HUNT ) ) ) - { - m_strTrackName = MAKE_STRING( STRIDER_NO_TRACK_NAME ); - SetGoalEnt( NULL ); - } - BaseClass::OnMovementComplete(); -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -float CNPC_Strider::GetSequenceGroundSpeed( CStudioHdr *pStudioHdr, int iSequence ) -{ - return ( BaseClass::GetSequenceGroundSpeed( pStudioHdr, iSequence ) * m_flSpeedScale ); -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -float CNPC_Strider::MaxYawSpeed() -{ - switch( GetActivity() ) - { - case ACT_90_LEFT: - case ACT_90_RIGHT: - return 10; - - case ACT_TURN_LEFT: - case ACT_TURN_RIGHT: - return 10; - - case ACT_WALK: - return 10; - - default: - return 10; // should be zero, but this makes it easy to see when he's turning with default AI code - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Strider::DoMuzzleFlash( void ) -{ - BaseClass::DoMuzzleFlash(); - - CEffectData data; - - data.m_nAttachmentIndex = LookupAttachment( "MiniGun" ); - data.m_nEntIndex = entindex(); - DispatchEffect( "StriderMuzzleFlash", data ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::ShootMinigun( const Vector *pTarget, float aimError, const Vector &vecSpread ) -{ - if ( pTarget ) - { - Vector muzzlePos; - QAngle muzzleAng; - - GetAttachment( "minigun", muzzlePos, muzzleAng ); - - Vector vecShootDir = *pTarget - muzzlePos; - VectorNormalize( vecShootDir ); - - if( m_bMinigunUseDirectFire ) - { - // exactly on target w/tracer - FireBullets( 1, muzzlePos, vecShootDir, vecSpread, 8192, m_miniGunDirectAmmo, 1 ); - } - else - { - // exactly on target w/tracer - FireBullets( 1, muzzlePos, vecShootDir, vecSpread, 8192, m_miniGunAmmo, 1 ); - } - - //g_pEffects->MuzzleFlash( muzzlePos, muzzleAng, random->RandomFloat( 2.0f, 4.0f ) , MUZZLEFLASH_TYPE_STRIDER ); - DoMuzzleFlash(); - - EmitSound( "NPC_Strider.FireMinigun" ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::UpdateMinigunControls( float &yaw, float &pitch ) -{ - SetPoseParameter( m_poseMiniGunYaw, yaw ); - SetPoseParameter( m_poseMiniGunPitch, pitch ); - - yaw = GetPoseParameter( m_poseMiniGunYaw ); - pitch = GetPoseParameter( m_poseMiniGunPitch ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::GetViewCone( StriderMinigunViewcone_t &cone ) -{ - cone.origin = EyePosition(); - GetVectors( &cone.axis, NULL, NULL ); - cone.cosAngle = 0.5; // 60 degree cone - cone.length = 2048; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::OnMinigunStopShooting( CBaseEntity *pTarget ) -{ - // Stop hating the focus. - if( GetFocus() && pTarget == GetFocus() ) - { - AddEntityRelationship( GetFocus(), D_NU, 0 ); - } - - if( IsUsingAggressiveBehavior() ) - { - // From now on, direct fire. - m_bMinigunUseDirectFire = true; - } -} - -//--------------------------------------------------------- -// How fast the minigun fires (rounds per second) -//--------------------------------------------------------- -float CNPC_Strider::GetMinigunRateOfFire() -{ - if( IsUsingAggressiveBehavior() && m_bMinigunUseDirectFire ) - return STRIDER_EP1_RATE_OF_FIRE; - - return STRIDER_DEFAULT_RATE_OF_FIRE; -} - -//--------------------------------------------------------- -// How much of shoot duration is spent firing directly at -// the target (the balance of time is spent stitching towards) -//--------------------------------------------------------- -float CNPC_Strider::GetMinigunOnTargetTime() -{ - if( IsUsingAggressiveBehavior() ) - { - if( m_bMinigunUseDirectFire ) - { - // On target the whole time. Just send a large number that - // will be clipped, since shooting duration is random and - // we don't know how long the burst will actually be. - return 100.0f; - } - - return STRIDER_EP1_SHOOT_ON_TARGET_TIME; - } - - return STRIDER_SHOOT_ON_TARGET_TIME; -} - -//--------------------------------------------------------- -// How long (seconds) a burst of minigun fire lasts. -//--------------------------------------------------------- -float CNPC_Strider::GetMinigunShootDuration() -{ - if( IsUsingAggressiveBehavior() ) - return STRIDER_EP1_SHOOT_DURATION; - - return STRIDER_DEFAULT_SHOOT_DURATION; -} - -//--------------------------------------------------------- -// How long (seconds) a strider must wait between bursts -//--------------------------------------------------------- -float CNPC_Strider::GetMinigunShootDowntime() -{ - if( IsUsingAggressiveBehavior() ) - return STRIDER_EP1_SHOOT_DOWNTIME; - - return STRIDER_SHOOT_DOWNTIME; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -float CNPC_Strider::GetMinigunShootVariation() -{ - if( IsUsingAggressiveBehavior() ) - { - if( m_bMinigunUseDirectFire ) - return 0.0f; - - return STRIDER_EP1_SHOOT_VARIATION; - } - - return STRIDER_SHOOT_VARIATION; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -Vector CNPC_Strider::CannonPosition() -{ - Vector position; - - // Currently just using the gun for the vertical component! - GetAttachment( "biggun", position ); - position.x = GetAbsOrigin().x; - position.y = GetAbsOrigin().y; - - return position; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -CBaseEntity *CNPC_Strider::GetCannonTarget() -{ - CBaseEntity *pTarget = m_hCannonTarget; - return pTarget; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Strider::HasCannonTarget() const -{ - return ( m_hCannonTarget.Get() != NULL ); -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Strider::IsCannonTarget( CBaseEntity *pTarget ) const -{ - CBaseEntity *pCannonTarget = m_hCannonTarget; - if ( pCannonTarget && pCannonTarget == pTarget ) - { - return true; - } - - return false; -} - -//--------------------------------------------------------- -// Purpose: Aim Gun at a target -// Output : Returns true if you hit the target, false if not there yet -//--------------------------------------------------------- -bool CNPC_Strider::AimCannonAt( CBaseEntity *pEntity, float flInterval ) -{ - if ( !pEntity ) - return true; - - matrix3x4_t gunMatrix; - GetAttachment( gm_CannonAttachment, gunMatrix ); - - // transform the enemy into gun space - m_vecHitPos = pEntity->GetAbsOrigin(); - Vector localEnemyPosition; - VectorITransform( pEntity->GetAbsOrigin(), gunMatrix, localEnemyPosition ); - - // do a look at in gun space (essentially a delta-lookat) - QAngle localEnemyAngles; - VectorAngles( localEnemyPosition, localEnemyAngles ); - - // convert to +/- 180 degrees - localEnemyAngles.x = UTIL_AngleDiff( localEnemyAngles.x, 0 ); - localEnemyAngles.y = UTIL_AngleDiff( localEnemyAngles.y, 0 ); - - float targetYaw = m_aimYaw + localEnemyAngles.y; - float targetPitch = m_aimPitch + localEnemyAngles.x; - - Vector unitAngles = Vector( localEnemyAngles.x, localEnemyAngles.y, localEnemyAngles.z ); - float angleDiff = VectorNormalize(unitAngles); - const float aimSpeed = 16; - - // Exponentially approach the target - float yawSpeed = fabsf(aimSpeed*flInterval*localEnemyAngles.y); - float pitchSpeed = fabsf(aimSpeed*flInterval*localEnemyAngles.x); - - yawSpeed = MAX(yawSpeed,5); - pitchSpeed = MAX(pitchSpeed,5); - - m_aimYaw = UTIL_Approach( targetYaw, m_aimYaw, yawSpeed ); - m_aimPitch = UTIL_Approach( targetPitch, m_aimPitch, pitchSpeed ); - - SetPoseParameter( gm_YawControl, m_aimYaw ); - SetPoseParameter( gm_PitchControl, m_aimPitch ); - - // read back to avoid drift when hitting limits - // as long as the velocity is less than the delta between the limit and 180, this is fine. - m_aimPitch = GetPoseParameter( gm_PitchControl ); - m_aimYaw = GetPoseParameter( gm_YawControl ); - - // UNDONE: Zero out any movement past the limit and go ahead and fire if the strider hit its - // target except for clamping. Need to clamp targets to limits and compare? - if ( angleDiff < 1 ) - return true; - - return false; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::FireCannon() -{ - ASSERT( m_hCannonTarget != NULL ); - if ( !m_hCannonTarget ) - { - DevMsg( "Strider firing cannon at NULL target\n" ); - - // Turn the cannon off - EntityMessageBegin( this, true ); - WRITE_BYTE( STRIDER_MSG_DEAD ); - MessageEnd(); - - return; - } - - if ( GetNextThink( "CANNON_HIT" ) > gpGlobals->curtime ) - { - DevMsg( "Strider refiring cannon?\n" ); - return; - } - - m_nextShootTime = gpGlobals->curtime + 5; - trace_t tr; - Vector vecShootPos; - GetAttachment( gm_CannonAttachment, vecShootPos ); - - Vector vecShootDir; - vecShootDir = m_hCannonTarget->WorldSpaceCenter() - vecShootPos; - float flDist = VectorNormalize( vecShootDir ); - - AI_TraceLine( vecShootPos, vecShootPos + vecShootDir * flDist, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - m_blastHit = tr.endpos; - m_blastHit += tr.plane.normal * 16; - m_blastNormal = tr.plane.normal; - - // tell the client side effect to complete - EntityMessageBegin( this, true ); - WRITE_BYTE( STRIDER_MSG_BIG_SHOT ); - WRITE_VEC3COORD( tr.endpos ); - MessageEnd(); - - CPASAttenuationFilter filter2( this, "NPC_Strider.Shoot" ); - EmitSound( filter2, entindex(), "NPC_Strider.Shoot"); - SetContextThink( &CNPC_Strider::CannonHitThink, gpGlobals->curtime + 0.2f, "CANNON_HIT" ); -} - -void CNPC_Strider::CannonHitThink() -{ - CBaseEntity *pCannonTarget = m_hCannonTarget; - if ( pCannonTarget ) - { - bool fAlive = pCannonTarget->IsAlive(); - - CreateConcussiveBlast( m_blastHit, m_blastNormal, this, 2.5 ); - - // If the target was alive, check to make sure it is now dead. If not, - // Kill it and warn the designer. - if( fAlive && pCannonTarget->IsAlive() ) - { - DevWarning("* * * * * * * * * * * * * * *\n"); - DevWarning("NASTYGRAM: STRIDER failed to kill its cannon target. Killing directly...\n"); - DevWarning("* * * * * * * * * * * * * * *\n"); - - CTakeDamageInfo info; - - info.SetDamage( pCannonTarget->GetHealth() ); - info.SetDamageType( DMG_GENERIC ); - info.SetAttacker( this ); - info.SetInflictor( this ); - - pCannonTarget->TakeDamage( info ); - } - - // Clear this guy now that we've shot him - m_hCannonTarget = NULL; - } - - // Allow the cannon back on. - m_pMinigun->StopShootingForSeconds( this, m_pMinigun->GetTarget(), 1 ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::VPhysicsShadowCollision( int index, gamevcollisionevent_t *pEvent ) -{ - if ( !HasMemory( bits_MEMORY_PROVOKED ) ) - { - // if the player threw this in the last 1 seconds - CBasePlayer *pPlayer = pEvent->pEntities[!index]->HasPhysicsAttacker( 1 ); - if ( pPlayer ) - { - GetEnemies()->ClearMemory( pPlayer ); - Remember( bits_MEMORY_PROVOKED ); - SetCondition( COND_LIGHT_DAMAGE ); - } - } - - int otherIndex = !index; - CBaseEntity *pOther = pEvent->pEntities[otherIndex]; - if ( pOther && UTIL_IsCombineBall( pOther ) ) - { - Vector damagePos; - pEvent->pInternalData->GetContactPoint( damagePos ); - CTakeDamageInfo dmgInfo( pOther, pOther, vec3_origin, damagePos, (m_iMaxHealth / 3) + 1, DMG_BLAST | DMG_PREVENT_PHYSICS_FORCE ); - - // FIXME: is there a better way for physics objects to keep track of what root entity responsible for them moving? - CBasePlayer *pPlayer = pOther->HasPhysicsAttacker( 1.0 ); - if (pPlayer) - { - dmgInfo.SetAttacker( pPlayer ); - } - - // UNDONE: Find one near damagePos? - m_nForceBone = 0; - PhysCallbackDamage( this, dmgInfo, *pEvent, index ); - return; - } - - BaseClass::VPhysicsShadowCollision( index, pEvent ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Strider::TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ) -{ - // Let normal hitbox code handle rays - if ( mask & CONTENTS_HITBOX ) - { - return BaseClass::TestCollision( ray, mask, trace ); - } - - if ( IntersectRayWithBox( ray, WorldAlignMins() + GetAbsOrigin(), WorldAlignMaxs() + GetAbsOrigin(), DIST_EPSILON, &trace ) ) - { - trace.hitbox = 0; - trace.hitgroup = HITGROUP_HEAD; - return true; - } - return false; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Strider::CarriedByDropship() -{ - if( GetOwnerEntity() && FClassnameIs( GetOwnerEntity(), "npc_combinedropship" ) ) - return true; - - return false; -} - -//--------------------------------------------------------- -// Carried by a dropship -//--------------------------------------------------------- -void CNPC_Strider::CarriedThink() -{ - SetNextThink( gpGlobals->curtime + 0.05 ); - StudioFrameAdvance(); - - Vector vecGround = GetAbsOrigin(); - TranslateNavGoal( NULL, vecGround ); - - if( !CarriedByDropship() ) - { - SetSolid( SOLID_BBOX ); - SetThink ( &CAI_BaseNPC::CallNPCThink ); - } -} - - - - -//--------------------------------------------------------- -//--------------------------------------------------------- -Vector CNPC_Strider::LeftFootHit( float eventtime ) -{ - Vector footPosition; - QAngle angles; - - GetAttachment( "left foot", footPosition, angles ); - - if ( hl2_episodic.GetBool() ) - { - CPASAttenuationFilter filter( this, "NPC_Strider.FootstepEverywhere" ); - EmitSound( filter, 0, "NPC_Strider.FootstepEverywhere", &footPosition, eventtime ); - } - else - { - CPASAttenuationFilter filter( this, "NPC_Strider.Footstep" ); - EmitSound( filter, 0, "NPC_Strider.Footstep", &footPosition, eventtime ); - } - - FootFX( footPosition ); - - return footPosition; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -Vector CNPC_Strider::RightFootHit( float eventtime ) -{ - Vector footPosition; - - GetAttachment( "right foot", footPosition ); - - if ( hl2_episodic.GetBool() ) - { - CPASAttenuationFilter filter( this, "NPC_Strider.FootstepEverywhere" ); - EmitSound( filter, 0, "NPC_Strider.FootstepEverywhere", &footPosition, eventtime ); - } - else - { - CPASAttenuationFilter filter( this, "NPC_Strider.Footstep" ); - EmitSound( filter, 0, "NPC_Strider.Footstep", &footPosition, eventtime ); - } - - FootFX( footPosition ); - - return footPosition; -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -Vector CNPC_Strider::BackFootHit( float eventtime ) -{ - Vector footPosition; - - GetAttachment( "back foot", footPosition ); - - if ( hl2_episodic.GetBool() ) - { - CPASAttenuationFilter filter( this, "NPC_Strider.FootstepEverywhere" ); - EmitSound( filter, 0, "NPC_Strider.FootstepEverywhere", &footPosition, eventtime ); - } - else - { - CPASAttenuationFilter filter( this, "NPC_Strider.Footstep" ); - EmitSound( filter, 0, "NPC_Strider.Footstep", &footPosition, eventtime ); - } - - FootFX( footPosition ); - - return footPosition; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -static Vector GetAttachmentPositionInSpaceOfBone( CStudioHdr *pStudioHdr, const char *pAttachmentName, int outputBoneIndex ) -{ - int attachment = Studio_FindAttachment( pStudioHdr, pAttachmentName ); - - Vector localAttach; - const mstudioattachment_t &pAttachment = pStudioHdr->pAttachment(attachment); - int iBone = pStudioHdr->GetAttachmentBone( attachment ); - MatrixGetColumn( pAttachment.local, 3, localAttach ); - - matrix3x4_t inputToOutputBone; - Studio_CalcBoneToBoneTransform( pStudioHdr, iBone, outputBoneIndex, inputToOutputBone ); - - Vector out; - VectorTransform( localAttach, inputToOutputBone, out ); - - return out; -} - -//------------------------------------- - -void CNPC_Strider::StompHit( int followerBoneIndex ) -{ - CStudioHdr *pStudioHdr = GetModelPtr(); - physfollower_t *bone = m_BoneFollowerManager.GetBoneFollower( followerBoneIndex ); - if ( !bone ) - return; - - const char *pBoneNames[] = {"left skewer", "right skewer" }; - int nameIndex = followerBoneIndex == STRIDER_LEFT_LEG_FOLLOWER_INDEX ? 0 : 1; - Vector localHit = GetAttachmentPositionInSpaceOfBone( pStudioHdr, pBoneNames[nameIndex], bone->boneIndex ); - IPhysicsObject *pLegPhys = bone->hFollower->VPhysicsGetObject(); - - // now transform into the worldspace of the current position of the leg's physics - matrix3x4_t legToWorld; - pLegPhys->GetPositionMatrix( &legToWorld ); - Vector hitPosition; - VectorTransform( localHit, legToWorld, hitPosition ); - - //NDebugOverlay::Box( hitPosition, Vector(-16,-16,-16), Vector(16,16,16), 0, 255, 0, 255, 1.0 ); - CBaseEntity *pEnemy = GetEnemy(); - CAI_BaseNPC *pNPC = pEnemy ? pEnemy->MyNPCPointer() : NULL; - bool bIsValidTarget = pNPC && pNPC->GetModelPtr(); - if ( HasSpawnFlags( SF_CAN_STOMP_PLAYER ) ) - { - bIsValidTarget = bIsValidTarget || ( pEnemy && pEnemy->IsPlayer() ); - } - - if ( !bIsValidTarget ) - return; - - Vector delta; - VectorSubtract( pEnemy->GetAbsOrigin(), hitPosition, delta ); - if ( delta.LengthSqr() > (STRIDER_STOMP_RANGE * STRIDER_STOMP_RANGE) ) - return; - - // DVS E3 HACK: Assume we stab our victim midway between their eyes and their center. - Vector vecStabPos = ( pEnemy->WorldSpaceCenter() + pEnemy->EyePosition() ) * 0.5f; - hitPosition = pEnemy->GetAbsOrigin(); - - Vector footPosition; - GetAttachment( "left foot", footPosition ); - - CPASAttenuationFilter filter( this, "NPC_Strider.Skewer" ); - EmitSound( filter, 0, "NPC_Strider.Skewer", &hitPosition ); - - CTakeDamageInfo damageInfo( this, this, 500, DMG_CRUSH ); - Vector forward; - pEnemy->GetVectors( &forward, NULL, NULL ); - damageInfo.SetDamagePosition( hitPosition ); - damageInfo.SetDamageForce( -50 * 300 * forward ); - pEnemy->TakeDamage( damageInfo ); - - if ( !pNPC || pNPC->IsAlive() ) - return; - - Vector vecBloodDelta = footPosition - vecStabPos; - vecBloodDelta.z = 0; // effect looks better - VectorNormalize( vecBloodDelta ); - UTIL_BloodSpray( vecStabPos + vecBloodDelta * 4, vecBloodDelta, BLOOD_COLOR_RED, 8, FX_BLOODSPRAY_ALL ); - UTIL_BloodSpray( vecStabPos + vecBloodDelta * 4, vecBloodDelta, BLOOD_COLOR_RED, 11, FX_BLOODSPRAY_DROPS ); - CBaseEntity *pRagdoll = CreateServerRagdollAttached( pNPC, vec3_origin, -1, COLLISION_GROUP_DEBRIS, pLegPhys, this, bone->boneIndex, vecStabPos, -1, localHit ); - if ( pRagdoll ) - { - // the strider might drag this through the world - pRagdoll->AddSolidFlags( FSOLID_NOT_SOLID ); - - m_hRagdoll = pRagdoll; - m_ragdollTime = gpGlobals->curtime + 10; - UTIL_Remove( pNPC ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_Strider::FootFX( const Vector &origin ) -{ - trace_t tr; - AI_TraceLine( origin + Vector(0, 0, 48), origin - Vector(0,0,100), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - float yaw = random->RandomInt(0,120); - - if ( UTIL_PointContents( tr.endpos + Vector( 0, 0, 1 ) ) & MASK_WATER ) - { - float flWaterZ = UTIL_FindWaterSurface( tr.endpos, tr.endpos.z, tr.endpos.z + 100.0f ); - - CEffectData data; - data.m_fFlags = 0; - data.m_vOrigin = tr.endpos; - data.m_vOrigin.z = flWaterZ; - data.m_vNormal = Vector( 0, 0, 1 ); - data.m_flScale = random->RandomFloat( 10.0, 14.0 ); - - DispatchEffect( "watersplash", data ); - } - else - { - for ( int i = 0; i < 3; i++ ) - { - Vector dir = UTIL_YawToVector( yaw + i*120 ) * 10; - VectorNormalize( dir ); - dir.z = 0.25; - VectorNormalize( dir ); - g_pEffects->Dust( tr.endpos, dir, 12, 50 ); - } - } - UTIL_ScreenShake( tr.endpos, 4.0, 1.0, 0.5, 1000, SHAKE_START, false ); - - if ( npc_strider_shake_ropes_radius.GetInt() ) - { - CRopeKeyframe::ShakeRopes( tr.endpos, npc_strider_shake_ropes_radius.GetFloat(), npc_strider_shake_ropes_magnitude.GetFloat() ); - } - - // - // My feet are scary things! NOTE: We might want to make danger sounds as the feet move - // through the air. Then soldiers could run from the feet, which would look cool. - // - CSoundEnt::InsertSound( SOUND_DANGER|SOUND_CONTEXT_EXCLUDE_COMBINE, tr.endpos, 512, 1.0f, this ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -Vector CNPC_Strider::CalculateStompHitPosition( CBaseEntity *pEnemy ) -{ - Vector skewerPosition, footPosition; - GetAttachment( "left skewer", skewerPosition ); - GetAttachment( "left foot", footPosition ); - Vector vecStabPos = ( pEnemy->WorldSpaceCenter() + pEnemy->EyePosition() ) * 0.5f; - - return vecStabPos - skewerPosition + footPosition; -} - -//----------------------------------------------------------------------------- -// Strider Navigation -//----------------------------------------------------------------------------- - -static void MoveToGround( Vector *position, CBaseEntity *ignore, const Vector &mins, const Vector &maxs ) -{ - trace_t tr; - // Find point on floor where enemy would stand at chasePosition - Vector floor = *position; - floor.z -= 1024; - AI_TraceHull( *position, floor, mins, maxs, MASK_NPCSOLID_BRUSHONLY, ignore, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction < 1 ) - { - position->z = tr.endpos.z; - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void AdjustStriderNodePosition( CAI_Network *pNetwork, CAI_Node *pNode ) -{ - if ( pNode->GetHint() && pNode->GetHint()->HintType() == HINT_STRIDER_NODE ) - { - CNPC_Strider *pStrider = (CNPC_Strider *)gEntList.FindEntityByClassname( NULL, "npc_strider" ); - bool bCreated = false; - if ( !pStrider ) - { - bool allowPrecache = CBaseEntity::IsPrecacheAllowed(); - CBaseEntity::SetAllowPrecache( true ); - pStrider = (CNPC_Strider *)CreateEntityByName( "npc_strider" ); - pStrider->m_bDisableBoneFollowers = true; // don't create these since we're just going to destroy him - DispatchSpawn( pStrider ); - CBaseEntity::SetAllowPrecache( allowPrecache ); - bCreated = true; - } - - if ( pStrider ) - { - pStrider->TranslateNavGoal( NULL, pNode->AccessOrigin() ); - if ( bCreated ) - UTIL_Remove( pStrider ); - } - } -} - - -//--------------------------------------------------------- -// Implement a navigator so that the strider can get closer to the ground when he's walking on a slope -// This gives him enough reach for his legs to IK to lower ground points -//--------------------------------------------------------- -void LookaheadPath( const Vector ¤t, AI_Waypoint_t *pWaypoint, float dist, Vector &nextPos ) -{ - if ( !pWaypoint ) - return; - - Vector dir = pWaypoint->GetPos() - current; - float dist2D = dir.Length2D(); - if ( dist2D > 0.1 ) - { - if ( dist <= dist2D ) - { - nextPos = ((dist / dist2D) * dir) + current; - return; - } - } - nextPos = pWaypoint->GetPos(); - dist -= dist2D; - dir = nextPos; - - LookaheadPath( dir, pWaypoint->GetNext(), dist, nextPos ); -} - -//--------------------------------------------------------- -// Find the forward slope and lower the strider height when moving downward -//--------------------------------------------------------- -void CNPC_Strider::CNavigator::MoveCalcBaseGoal( AILocalMoveGoal_t *pMoveGoal ) -{ - BaseClass::MoveCalcBaseGoal( pMoveGoal ); - Vector dest = pMoveGoal->target; - LookaheadPath( GetAbsOrigin(), pMoveGoal->pPath->GetCurWaypoint(), CNPC_Strider::gm_strideLength, dest ); - - //NDebugOverlay::Box( dest, Vector(-16,-16,-16), Vector(16,16,16), 0, 255, 0, 255, 0.1 ); - Vector unitDir = pMoveGoal->dir * CNPC_Strider::gm_strideLength; - unitDir.z = dest.z - GetAbsOrigin().z; - VectorNormalize( unitDir ); - float heightAdj = unitDir.z * CNPC_Strider::gm_strideLength; - pMoveGoal->flags |= ( AILMG_NO_STEER | AILMG_NO_AVOIDANCE_PATHS ); - if ( heightAdj < -1 ) - { - heightAdj = clamp( heightAdj, -192, 0 ); - pMoveGoal->target.z += heightAdj; - pMoveGoal->dir = unitDir * CNPC_Strider::gm_strideLength * 0.1; - pMoveGoal->dir.z += heightAdj; - VectorNormalize( pMoveGoal->dir ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Strider::CNavigator::MoveUpdateWaypoint( AIMoveResult_t *pResult ) -{ - // Note that goal & waypoint tolerances are handled in progress blockage cases (e.g., OnObstructionPreSteer) - - AI_Waypoint_t *pCurWaypoint = GetPath()->GetCurWaypoint(); - float waypointDist = (pCurWaypoint->GetPos() - GetAbsOrigin()).Length2D(); - bool bIsGoal = CurWaypointIsGoal(); - // HACKHACK: adjust this tolerance - // The strider is following paths most of the time, but he needs a bunch of freedom - // to adjust himself to make his feet look good. - float tolerance = 10.0; - - if ( waypointDist <= tolerance ) - { - if ( bIsGoal ) - { - OnNavComplete(); - *pResult = AIMR_OK; - - } - else - { - AdvancePath(); - *pResult = AIMR_CHANGE_TYPE; - } - return true; - } - - return false; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Strider::CNavigator::DoFindPathToPos() -{ - DbgNavMsg( GetOuter(), "Strider overriding DoFindPathToPos\n"); - if ( BaseClass::DoFindPathToPos() ) - { - // Do special optimization on our first path segment - DbgNavMsg( GetOuter(), "Strider base pathfind worked\n"); - CAI_WaypointList waypoints( GetPath()->GetCurWaypoint() ); - AI_Waypoint_t *pFirstWaypoint = waypoints.GetFirst(); - AI_Waypoint_t *pLast = waypoints.GetLast(); - - if ( pFirstWaypoint->IsReducible() && - pFirstWaypoint->GetNext() && - pFirstWaypoint->GetNext()->iNodeID != NO_NODE && - pFirstWaypoint->GetNext()->NavType() == GetNavType() ) - { - // Find nearest point on the line segment of our path - Vector vOrigin = GetOuter()->GetAbsOrigin(); - Vector vClosest; - CalcClosestPointOnLineSegment( vOrigin, - pFirstWaypoint->GetPos(), - pFirstWaypoint->GetNext()->GetPos(), - vClosest ); - - // Find both these positions as offset from the ground - TranslateNavGoal( GetPath()->GetTarget(), vClosest ); - TranslateNavGoal( GetPath()->GetTarget(), vOrigin ); - - // If we're seemingly beyond the waypoint and our hull is near enough to the path segment, advance to the next node - const float EPS = 0.1f; - bool bPastStartNode = ( ( pFirstWaypoint->GetPos() - vClosest ).Length() > EPS ); - bool bNearPathSegment = ( ( vOrigin - vClosest ).Length() < GetHullWidth() * 0.5f ); - if ( bPastStartNode && bNearPathSegment ) - { - GetPath()->Advance(); - } - } - - if ( pLast->iNodeID == NO_NODE ) - { - AI_Waypoint_t *pLastNodeWaypoint = pLast->GetPrev(); - - if ( pLastNodeWaypoint && pLastNodeWaypoint->iNodeID == NO_NODE ) - { - // Pathfinder triangulated to goal - Assert( pLastNodeWaypoint->GetPrev() ); - if ( pLastNodeWaypoint->GetPrev() ) - { - pLastNodeWaypoint->GetPrev()->SetNext( pLast ); - delete pLastNodeWaypoint; - pLastNodeWaypoint = pLast->GetPrev(); - } - } - - Assert( pLastNodeWaypoint ); - if ( pLastNodeWaypoint ) - { - Assert( pLastNodeWaypoint->iNodeID != NO_NODE ); - if ( pLastNodeWaypoint->iNodeID != NO_NODE ) - { - CAI_Node *pLastNode = GetNetwork()->GetNode( pLastNodeWaypoint->iNodeID ); - float bestDistSq = ( pLast->vecLocation - pLastNodeWaypoint->vecLocation ).LengthSqr(); - Vector vNewEnd = vec3_invalid; - int segmentDestClosest = NO_NODE; - - for (int link=0; link < pLastNode->NumLinks();link++) - { - CAI_Link *pLink = pLastNode->GetLinkByIndex(link); - if ( !( pLink->m_LinkInfo & bits_LINK_OFF ) && (pLink->m_iAcceptedMoveTypes[GetHullType()] & bits_CAP_MOVE_FLY) ) - { - CAI_Node *pTestNode = GetNetwork()->GetNode( pLink->DestNodeID( pLastNodeWaypoint->iNodeID ) ); - if ( pTestNode->GetHint() && pTestNode->GetHint()->HintType() == HINT_STRIDER_NODE ) - { - Vector vClosest; - CalcClosestPointOnLineSegment( pLast->vecLocation, - pLastNodeWaypoint->vecLocation, pTestNode->GetPosition(GetHullType()), - vClosest ); - float distTestSq = ( pLast->vecLocation - vClosest ).LengthSqr(); - if ( distTestSq < bestDistSq ) - { - bestDistSq = distTestSq; - vNewEnd = vClosest; - segmentDestClosest = pTestNode->GetId(); - } - } - } - } - - if ( vNewEnd == vec3_invalid ) - { - DbgNavMsg( GetOuter(), "Strider resetting goal to last node waypoint\n"); - pLastNodeWaypoint->SetNext( NULL ); - pLastNodeWaypoint->ModifyFlags( bits_WP_TO_GOAL, true ); - delete pLast; - } - else if ( !pLastNodeWaypoint->GetPrev() || pLastNodeWaypoint->GetPrev()->iNodeID != segmentDestClosest ) - { - DbgNavMsg( GetOuter(), "Strider resetting goal to nearest point on graph\n"); - pLast->vecLocation = vNewEnd; - } - else - { - DbgNavMsg( GetOuter(), "Strider resetting goal to nearest point on graph, on node\n"); - pLastNodeWaypoint->vecLocation = vNewEnd; - pLastNodeWaypoint->SetNext( NULL ); - pLastNodeWaypoint->ModifyFlags( bits_WP_TO_GOAL, true ); - delete pLast; - } - GetPath()->ResetGoalPosition( GetPath()->GetGoalWaypoint()->vecLocation ); - } - } - } - else - DbgNavMsg( GetOuter(), "Goal ended on node\n"); - return true; - } - else - DbgNavMsg( GetOuter(), "Strider base pathfind failed\n"); - - return false; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Strider::CNavigator::ShouldOptimizeInitialPathSegment( AI_Waypoint_t *pFirstWaypoint ) -{ - // We do our own special initial path optimization DoFindPathToPos() - return false; -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_Strider::CNavigator::GetStoppingPath( CAI_WaypointList *pClippedWaypoints ) -{ - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns if a bone follower is a leg piece or not -// Input : *pFollower - Bone follower we're testing -// Output : Returns true if the bone follower is a part of the strider's legs -//----------------------------------------------------------------------------- -bool CNPC_Strider::IsLegBoneFollower( CBoneFollower *pFollower ) -{ - // Find the index of this bone follower, if we have it - int nFollowerIndex = GetBoneFollowerIndex( pFollower ); - if ( nFollowerIndex == -1 ) - return false; - - // See if we're a leg - if ( nFollowerIndex >= STRIDER_LEFT_LEG_FOLLOWER_INDEX && - nFollowerIndex <= STRIDER_BACK_UPPERLEG_FOLLOWER_INDEX ) - return true; - - // We're something else - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Finds a bone follower via a supplied index -// Input : nIndex - index our bone follower manager will use to retrieve the follower -// Output : NULL if not found, otherwise the bone follower we were seeking -//----------------------------------------------------------------------------- -CBoneFollower *CNPC_Strider::GetBoneFollowerByIndex( int nIndex ) -{ - physfollower_t *pFollower = m_BoneFollowerManager.GetBoneFollower( nIndex ); - if ( pFollower != NULL ) - return pFollower->hFollower; - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the index of a bone follower in our system -// Input : *pFollower - Follower we're looking for -// Output : -1 if not found, otherwise the index of the follower -//----------------------------------------------------------------------------- -int CNPC_Strider::GetBoneFollowerIndex( CBoneFollower *pFollower ) -{ - return m_BoneFollowerManager.GetBoneFollowerIndex( pFollower ); -} - -//----------------------------------------------------------------------------- -// Purpose: The strider ignores certain entities this way -// Input : *pEntity - Entity in question -// Output : Returns true if we should collide with the entity -//----------------------------------------------------------------------------- -bool CNPC_Strider::ShouldProbeCollideAgainstEntity( CBaseEntity *pEntity ) -{ - if ( pEntity->m_iClassname == m_iszStriderBusterName ) - return false; - - return BaseClass::ShouldProbeCollideAgainstEntity( pEntity ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Lets us keep track of attached Strider busters -// Input : *pAttached - strider buster that is attached -//----------------------------------------------------------------------------- -#ifdef HL2_EPISODIC -void CNPC_Strider::StriderBusterAttached( CBaseEntity *pAttached ) -{ - // Add another to the list - m_hAttachedBusters.AddToTail( pAttached ); - m_PlayerFreePass.Revoke(); - - variant_t target; - target.SetString( AllocPooledString( "!player" ) ); - g_EventQueue.AddEvent( this, "UpdateEnemyMemory", target, 1.0, this, this ); -} - - -void CNPC_Strider::StriderBusterDetached( CBaseEntity *pAttached ) -{ - int elem = m_hAttachedBusters.Find(pAttached); - if (elem >= 0) - { - m_hAttachedBusters.FastRemove(elem); - } -} - -#endif // HL2_EPISODIC - -//----------------------------------------------------------------------------- -// -// Strider Minigun -// -//----------------------------------------------------------------------------- - -BEGIN_DATADESC_NO_BASE( CStriderMinigun ) - - DEFINE_FIELD( m_enable, FIELD_BOOLEAN ), - DEFINE_FIELD( m_minigunState, FIELD_INTEGER ), - DEFINE_FIELD( m_nextBulletTime, FIELD_TIME ), - DEFINE_FIELD( m_burstTime, FIELD_TIME ), - DEFINE_FIELD( m_nextTwitchTime, FIELD_TIME ), - DEFINE_FIELD( m_randomState, FIELD_INTEGER ), - DEFINE_FIELD( m_hTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_bWarnedAI, FIELD_BOOLEAN ), - DEFINE_FIELD( m_shootDuration, FIELD_TIME ), - DEFINE_FIELD( m_vecAnchor, FIELD_VECTOR ), - DEFINE_FIELD( m_bOverrideEnemy, FIELD_BOOLEAN ), - DEFINE_FIELD( m_vecLastTargetPos, FIELD_VECTOR ), - DEFINE_FIELD( m_iOnTargetShots, FIELD_INTEGER ), - - // Silence, Classcheck! - // DEFINE_FIELD( m_yaw, StriderMinigunAnimController_t ), - // DEFINE_FIELD( m_pitch, StriderMinigunAnimController_t ), - - DEFINE_FIELD( m_yaw.current, FIELD_FLOAT ), - DEFINE_FIELD( m_yaw.target, FIELD_FLOAT ), - DEFINE_FIELD( m_yaw.rate, FIELD_FLOAT ), - DEFINE_FIELD( m_pitch.current, FIELD_FLOAT ), - DEFINE_FIELD( m_pitch.target, FIELD_FLOAT ), - DEFINE_FIELD( m_pitch.rate, FIELD_FLOAT ), - - -END_DATADESC() - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CStriderMinigun::Init() -{ - m_enable = true; - m_nextTwitchTime = gpGlobals->curtime; - m_randomState = 0; - m_yaw.current = m_yaw.target = 0; - m_pitch.current = m_pitch.target = 0; - m_yaw.rate = 360; - m_pitch.rate = 180; - - SetState( MINIGUN_OFF ); - m_burstTime = gpGlobals->curtime; - m_nextBulletTime = FLT_MAX; - m_vecAnchor = vec3_invalid; - m_shootDuration = STRIDER_DEFAULT_SHOOT_DURATION; - m_bOverrideEnemy = false; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CStriderMinigun::ShouldFindTarget( IMinigunHost *pHost ) -{ - ASSERT( pHost != NULL ); - - if( !GetTarget() ) - { - // No target. Find one. - return true; - } - - if( m_bOverrideEnemy ) - { - return false; - } - - if( pHost->GetEntity()->GetEnemy() ) - { - return GetTarget() != pHost->GetEntity()->GetEnemy(); - } - - return true; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -float CStriderMinigun::GetAimError() -{ - return fabs(m_yaw.target-m_yaw.current) + fabs(m_pitch.target-m_pitch.current); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CStriderMinigun::AimAtPoint( IStriderMinigunHost *pHost, const Vector &vecPoint, bool bSnap ) -{ - matrix3x4_t gunMatrix; - CAI_BaseNPC *pOwner = pHost->GetEntity(); - - int mingunAttachment = pOwner->LookupAttachment( "minigunbase" ); - pOwner->GetAttachment( mingunAttachment, gunMatrix ); - - Vector forward, pos; - MatrixGetColumn( gunMatrix, 0, forward ); - MatrixGetColumn( gunMatrix, 3, pos ); - - // transform the point into gun space - Vector localPointPosition; - VectorITransform( vecPoint, gunMatrix, localPointPosition ); - - // do a look at in gun space (essentially a delta-lookat) - QAngle localPointAngles; - VectorAngles( localPointPosition, localPointAngles ); - - // convert to +/- 180 degrees - float pdiff, ydiff; - pdiff = UTIL_AngleDiff( localPointAngles.x, 0 ); - ydiff = UTIL_AngleDiff( localPointAngles.y, 0 ); - - m_pitch.target += 0.5 * pdiff; - m_yaw.target -= 0.5 * ydiff; - - m_pitch.target = MAX( MINIGUN_MIN_PITCH, m_pitch.target ); - m_pitch.target = MIN( MINIGUN_MAX_PITCH, m_pitch.target ); - m_yaw.target = MAX( MINIGUN_MIN_YAW, m_yaw.target ); - m_yaw.target = MIN( MINIGUN_MAX_YAW, m_yaw.target ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CStriderMinigun::AimAtTarget( IStriderMinigunHost *pHost, CBaseEntity *pTarget, bool bSnap ) -{ - if ( pTarget && !(CAI_BaseNPC::m_nDebugBits & bits_debugDisableAI) ) - { - Vector vecTargetPos = pTarget->BodyTarget( pHost->GetEntity()->EyePosition() ); - AimAtPoint( pHost, vecTargetPos, bSnap ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CStriderMinigun::ShootAtTarget( IStriderMinigunHost *pHost, CBaseEntity *pTarget, float shootTime ) -{ - if ( !pTarget && !(CAI_BaseNPC::m_nDebugBits & bits_debugDisableAI) ) - return; - - variant_t emptyVariant; - pTarget->AcceptInput( "InputTargeted", pHost->GetEntity(), pHost->GetEntity(), emptyVariant, 0 ); - Enable( NULL, true ); - if ( shootTime <= 0 ) - { - shootTime = random->RandomFloat( 4, 8 ); - } - SetTarget( pHost, pTarget, true ); - - StartShooting( pHost, pTarget, shootTime ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CStriderMinigun::StartShooting( IStriderMinigunHost *pHost, CBaseEntity *pTarget, float duration ) -{ - bool bHasSetAnchor = false; - - SetState( MINIGUN_SHOOTING ); - - m_nextBulletTime = gpGlobals->curtime; - m_burstTime = gpGlobals->curtime + duration; - - m_shootDuration = duration; - - // don't twitch while shooting - m_nextTwitchTime = FLT_MAX; - - if( pTarget->IsPlayer() ) - { - // Don't shoot a player in the back if they aren't looking. - // Give them a chance to see they're being fired at. - CBasePlayer *pPlayer = dynamic_cast(pTarget); - - if( !pPlayer->FInViewCone( pHost->GetEntity() ) ) - { - // Player doesn't see me. Try to start shooting so that they can see - // the bullet impacts. - m_vecAnchor = pPlayer->EyePosition(); - - Vector vecPlayerLook; - Vector vecToPlayer; - - // Check in 2D. - vecPlayerLook = pPlayer->EyeDirection3D(); - vecPlayerLook.z = 0.0; - VectorNormalize( vecPlayerLook ); - - vecToPlayer = pPlayer->EyePosition() - pHost->GetEntity()->EyePosition(); - vecToPlayer.z = 0.0; - VectorNormalize( vecToPlayer ); - - float flDot = DotProduct( vecToPlayer, vecPlayerLook ); - - if( flDot < 0.95 ) - { - // If the player is looking sufficiently to a side, start 30 feet out in that direction. - m_vecAnchor += pPlayer->EyeDirection3D() * 320; - bHasSetAnchor = true; - } - else - { - // Start over their head, cause firing the direction they are looking will drill them. - // in the back! - m_vecAnchor += Vector( 0, 0, random->RandomFloat( 160, 240 ) ); - - // Move it to one side of the other randomly, just to get it off center. - Vector right; - pPlayer->GetVectors( NULL, &right, NULL ); - m_vecAnchor += right * random->RandomFloat( -100, 100 ); - bHasSetAnchor = true; - } - } - } - - if( !bHasSetAnchor ) - { - m_vecAnchor = pTarget->WorldSpaceCenter(); - - Vector right; - pTarget->GetVectors( NULL, &right, NULL ); - - // Start 5 or 10 feet off target. - Vector offset = right * random->RandomFloat( 60, 120 ); - - // Flip a coin to decide left or right. - if( random->RandomInt( 0, 1 ) == 0 ) - { - offset *= -1; - } - - m_vecAnchor += offset; - - // Start below them, too. - m_vecAnchor.z -= random->RandomFloat( 80, 200 ); - } - - pHost->OnMinigunStartShooting( pTarget ); -} - -//--------------------------------------------------------- -// Fixes up the math for stitching. -//--------------------------------------------------------- -void CStriderMinigun::ExtendShooting( float timeExtend ) -{ - m_burstTime = gpGlobals->curtime + timeExtend; - m_shootDuration = timeExtend; - m_bWarnedAI = false; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CStriderMinigun::SetShootDuration( float duration ) -{ -} - -//--------------------------------------------------------- -// Is the gun turned as far as it can go? -//--------------------------------------------------------- -bool CStriderMinigun::IsPegged( int dir ) -{ - bool up, down, left, right, any; - - up = down = left = right = any = false; - - if( m_yaw.current >= 89.0 ) - any = right = true; - - if( m_yaw.current <= -89.0 ) - any = left = true; - - if( m_pitch.current >= 44.0 ) - any = down = true; - - if( m_pitch.current <= -44.0 ) - any = up = true; - - switch( dir ) - { - case MINIGUN_PEGGED_UP: - return up; - - case MINIGUN_PEGGED_DOWN: - return down; - - case MINIGUN_PEGGED_LEFT: - return left; - - case MINIGUN_PEGGED_RIGHT: - return right; - - default: - return (any && !up); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CStriderMinigun::StopShootingForSeconds( IStriderMinigunHost *pHost, CBaseEntity *pTarget, float duration ) -{ - if ( IsShooting() ) - { - SetState( MINIGUN_OFF ); - } - - m_burstTime = gpGlobals->curtime + duration; - m_nextBulletTime = FLT_MAX; - - ClearOnTarget(); - m_nextTwitchTime = gpGlobals->curtime + random->RandomFloat( 2.0, 4.0 ); - pHost->OnMinigunStopShooting( pTarget ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CStriderMinigun::SetState( int newState ) -{ - m_minigunState = newState; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CStriderMinigun::SetTarget( IStriderMinigunHost *pHost, CBaseEntity *pTarget, bool bOverrideEnemy ) -{ - m_hTarget = pTarget; - - if( pTarget ) - { - // New target, we haven't scared this guy yet! - m_bWarnedAI = false; - - if( m_vecAnchor == vec3_invalid ) - { - Vector right; - pHost->GetEntity()->GetVectors( NULL, &right, NULL ); - - m_vecAnchor = pTarget->GetAbsOrigin() - Vector( 0, 0, 256 ); - m_vecAnchor += right * random->RandomFloat( -60.0f, 60.0f ); - } - } - - ClearOnTarget(); - - m_bOverrideEnemy = bOverrideEnemy; -} - -//--------------------------------------------------------- -// The strider minigun can track and fire at targets in a fairly -// large arc. It looks unnatural for a Strider to acquire a target -// off to one side and begin firing at it, so we don't let the -// minigun BEGIN shooting at a target unless the target is fairly -// well in front of the Strider. Once firing, the gun is allowed -// to track the target anywhere for the duration of that burst of -// minigun fire. This is tuned by eye. (sjb) -//--------------------------------------------------------- -bool CStriderMinigun::CanStartShooting( IStriderMinigunHost *pHost, CBaseEntity *pTargetEnt ) -{ - if ( CAI_BaseNPC::m_nDebugBits & bits_debugDisableAI ) - return false; - - if( !pTargetEnt ) - return false; - - if( gpGlobals->curtime < m_burstTime ) - return false; - - CNPC_Strider *pStrider = dynamic_cast(pHost->GetEntity() ); - if ( pTargetEnt->IsPlayer() && pStrider->HasPass() ) - return false; - - if( !m_bOverrideEnemy ) - { - if( pTargetEnt != pHost->GetEntity()->GetEnemy() ) - { - return false; - } - - // If the strider can't see the enemy, this may be because the enemy is - // hiding behind something breakable. If the weapon has LOS, fire away. - if( !pHost->GetEntity()->HasCondition( COND_SEE_ENEMY ) ) - { - Assert( pStrider != NULL ); - - if( !pStrider->WeaponLOSCondition( pStrider->GetAdjustedOrigin(), pTargetEnt->WorldSpaceCenter(), false ) ) - { - if( pStrider->IsUsingAggressiveBehavior() && pTargetEnt->IsPlayer() && !pStrider->HasPass() ) - { - // I can shoot the player's cover until he hides long enough to earn a free pass. - float flTimeSinceLastSeen = gpGlobals->curtime - pStrider->GetEnemies()->LastTimeSeen(pTargetEnt); - - if( flTimeSinceLastSeen <= 2.0f ) - return true; - } - - return false; - } - } - } - - Vector los = ( pTargetEnt->WorldSpaceCenter() - pHost->GetEntity()->EyePosition() ); - - // Following code stolen from FVisible. This check done in 2d intentionally. - los.z = 0; - VectorNormalize( los ); - - Vector facingDir = pHost->GetEntity()->EyeDirection2D( ); - float flDot = DotProduct( los, facingDir ); - - // Too far to a side. - if ( flDot <= .707 ) - return false; - - return true; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CStriderMinigun::Enable( IMinigunHost *pHost, bool enable ) -{ - m_enable = enable; - if ( !m_enable ) - { - m_yaw.current = m_yaw.target = 0; - m_pitch.current = m_pitch.target = 0; - if ( pHost ) - { - // KENB pHost->UpdateMinigunControls( m_yaw.current, m_pitch.current ); - } - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CStriderMinigun::Think( IStriderMinigunHost *pHost, float dt ) -{ - if ( !m_enable ) - return; - - if ( CAI_BaseNPC::m_nDebugBits & bits_debugDisableAI ) - return; - - if( ShouldFindTarget( pHost ) ) - { - CBaseEntity *pOldTarget = GetTarget(); - - // Take my host's enemy. - SetTarget( pHost, pHost->GetEntity()->GetEnemy() ); - - if( IsShooting() ) - { - // Changing targets hot! - if( pOldTarget ) - { - m_vecAnchor = pOldTarget->WorldSpaceCenter(); - } - - ExtendShooting( STRIDER_SUBSEQUENT_TARGET_DURATION + random->RandomFloat( 0, 0.5 ) ); - } - - pHost->NewTarget(); - } - - if ( !GetTarget() && m_nextTwitchTime <= gpGlobals->curtime ) - { - // invert one and randomize the other. - // This has the effect of making the gun cross the field of - // view more often - like he's looking around - m_randomState = !m_randomState; - if ( m_randomState ) - { - m_yaw.Random( MINIGUN_MIN_YAW, MINIGUN_MAX_YAW, 360, 720 ); - m_pitch.target = -m_pitch.target; - } - else - { - m_pitch.Random( MINIGUN_MIN_PITCH, MINIGUN_MAX_PITCH, 270, 360 ); - m_yaw.target = -m_yaw.target; - } - m_nextTwitchTime = gpGlobals->curtime + random->RandomFloat( 0.3, 2 ); - } - - CBaseEntity *pTargetEnt = m_hTarget.Get(); - - if ( pTargetEnt ) - { - pHost->GetEntity()->InvalidateBoneCache(); - AimAtTarget( pHost, pTargetEnt ); - } - - // Update the minigun's pose parameters using approaching. - m_yaw.Update( dt ); - m_pitch.Update( dt ); - - pHost->UpdateMinigunControls( m_yaw.current, m_pitch.current ); - - // Start or stop shooting. - if( IsShooting() ) - { - if( gpGlobals->curtime > m_burstTime || !pTargetEnt ) - { - // Time to stop firing. - if( m_bOverrideEnemy ) - { - // Get rid of this target. - SetTarget( pHost, NULL ); - } - - StopShootingForSeconds( pHost, pTargetEnt, pHost->GetMinigunShootDowntime() ); - } - } - else - { - if( CanStartShooting( pHost, pTargetEnt ) ) - { - StartShooting( pHost, pTargetEnt, pHost->GetMinigunShootDuration() + random->RandomFloat( 0, pHost->GetMinigunShootVariation() ) ); - } - } - - // Fire the next bullet! - if ( m_nextBulletTime <= gpGlobals->curtime && !IsPegged() ) - { - if( pTargetEnt && pTargetEnt == pHost->GetEntity()->GetEnemy() ) - { - // Shooting at the Strider's enemy. Strafe to target! - float flRemainingShootTime = m_burstTime - gpGlobals->curtime; - - // Skim a little time off of the factor, leave a moment of on-target - // time. This guarantees that the minigun will strike the target a few times. - float flFactor = (flRemainingShootTime - pHost->GetMinigunOnTargetTime() ) / m_shootDuration; - - flFactor = MAX( 0.0f, flFactor ); - - Vector vecTarget = pTargetEnt->BodyTarget( assert_cast(pHost->GetEntity())->GetAdjustedOrigin()); - - Vector vecLine = m_vecAnchor - vecTarget; - - float flDist = VectorNormalize( vecLine ); - - vecTarget += vecLine * flDist * flFactor; - - if( flFactor == 0.0 ) - { - m_vecAnchor = vecTarget; - RecordShotOnTarget(); - } - - if ( GetTarget() ) - { - pHost->ShootMinigun( &vecTarget, GetAimError(), vec3_origin ); - - if( flFactor <= 0.5 && !m_bWarnedAI ) - { - m_bWarnedAI = true; - - CSoundEnt::InsertSound( SOUND_DANGER | SOUND_CONTEXT_REACT_TO_SOURCE, pTargetEnt->EarPosition() + Vector( 0, 0, 1 ), 120, MAX( 1.0, flRemainingShootTime ), pHost->GetEntity() ); - } - } - } - else - { - const Vector *pTargetPoint = pTargetEnt ? &pTargetEnt->GetAbsOrigin() : NULL; - pHost->ShootMinigun( pTargetPoint, GetAimError() ); - } - - m_nextBulletTime = gpGlobals->curtime + (1.0f / pHost->GetMinigunRateOfFire() ); - } -} - -LINK_ENTITY_TO_CLASS( sparktrail, CSparkTrail ); - -void CSparkTrail::Precache() -{ - BaseClass::Precache(); - - PrecacheScriptSound( "DoSpark" ); -} - -void CSparkTrail::Spawn() -{ - Precache(); - - EmitSound( "DoSpark" ); - - m_iHealth = 20 + random->RandomInt( 0, 5 ); - UTIL_SetOrigin( this, GetOwnerEntity()->EyePosition() ); - - Vector vecVelocity; - - vecVelocity.x = random->RandomFloat( 100, 400 ); - vecVelocity.y = random->RandomFloat( 100, 400 ); - vecVelocity.z = random->RandomFloat( 0, 100 ); - - if( random->RandomInt( 0, 1 ) == 0 ) - vecVelocity.x *= -1; - - if( random->RandomInt( 0, 1 ) == 0 ) - vecVelocity.y *= -1; - - UTIL_SetSize( this, Vector( 0, 0, 0 ), Vector( 0, 0, 0 ) ); - SetMoveType( MOVETYPE_FLYGRAVITY ); - SetSolid( SOLID_NONE ); - - if( random->RandomInt( 0, 2 ) == 0 ) - { - vecVelocity *= 2.0; - m_iHealth /= 2; - SetMoveType( MOVETYPE_FLY ); - } - - SetAbsVelocity( vecVelocity ); - - SetThink( &CSparkTrail::SparkThink ); - SetNextThink( gpGlobals->curtime ); -} - -void CSparkTrail::SparkThink() -{ - SetNextThink( gpGlobals->curtime + 0.05 ); - - g_pEffects->Sparks( GetAbsOrigin() ); - - if( m_iHealth-- < 1 ) - { - UTIL_Remove( this ); - } -} - -BEGIN_DATADESC( CSparkTrail ) - DEFINE_THINKFUNC( SparkThink ), -END_DATADESC() - - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- -AI_BEGIN_CUSTOM_NPC( npc_strider, CNPC_Strider ) - - DECLARE_TASK( TASK_STRIDER_AIM ) - DECLARE_TASK( TASK_STRIDER_DODGE ) - DECLARE_TASK( TASK_STRIDER_STOMP ) - DECLARE_TASK( TASK_STRIDER_BREAKDOWN ) - DECLARE_TASK( TASK_STRIDER_START_MOVING ) - DECLARE_TASK( TASK_STRIDER_REFRESH_HUNT_PATH ) - DECLARE_TASK( TASK_STRIDER_GET_PATH_TO_CANNON_TARGET ) - DECLARE_TASK( TASK_STRIDER_FACE_CANNON_TARGET ) - DECLARE_TASK( TASK_STRIDER_SET_HEIGHT ) - DECLARE_TASK( TASK_STRIDER_GET_PATH_TO_CANNON_LOS ) - DECLARE_TASK( TASK_STRIDER_FIRE_CANNON ) - DECLARE_TASK( TASK_STRIDER_SET_CANNON_HEIGHT ) - DECLARE_TASK( TASK_STRIDER_FALL_TO_GROUND ) - - DECLARE_ACTIVITY( ACT_STRIDER_LOOKL ) - DECLARE_ACTIVITY( ACT_STRIDER_LOOKR ) - DECLARE_ACTIVITY( ACT_STRIDER_DEPLOYRA1 ) - DECLARE_ACTIVITY( ACT_STRIDER_AIMRA1 ) - DECLARE_ACTIVITY( ACT_STRIDER_FINISHRA1 ) - DECLARE_ACTIVITY( ACT_STRIDER_DODGER ) - DECLARE_ACTIVITY( ACT_STRIDER_DODGEL ) - DECLARE_ACTIVITY( ACT_STRIDER_STOMPL ) - DECLARE_ACTIVITY( ACT_STRIDER_STOMPR ) - DECLARE_ACTIVITY( ACT_STRIDER_FLICKL ) - DECLARE_ACTIVITY( ACT_STRIDER_FLICKR ) - DECLARE_ACTIVITY( ACT_STRIDER_SLEEP ) - DECLARE_ACTIVITY( ACT_STRIDER_CARRIED ) - DECLARE_ACTIVITY( ACT_STRIDER_DEPLOY ) - DECLARE_ACTIVITY( ACT_STRIDER_GESTURE_DEATH ) - - DECLARE_CONDITION( COND_STRIDER_DO_FLICK ) - DECLARE_CONDITION( COND_TRACK_PATH_GO ) - DECLARE_CONDITION( COND_STRIDER_SHOULD_CROUCH ) - DECLARE_CONDITION( COND_STRIDER_SHOULD_STAND ) - DECLARE_CONDITION( COND_STRIDER_MINIGUN_SHOOTING ) - DECLARE_CONDITION( COND_STRIDER_MINIGUN_NOT_SHOOTING ) - DECLARE_CONDITION( COND_STRIDER_HAS_CANNON_TARGET ) - DECLARE_CONDITION( COND_STRIDER_ENEMY_UPDATED ) - DECLARE_CONDITION( COND_STRIDER_HAS_LOS_Z ) - - DECLARE_INTERACTION( g_interactionPlayerLaunchedRPG ) - - //========================================================= - // Hunt (Basic logic for strider thinking) - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_STRIDER_HUNT, - - " Tasks" - " TASK_STRIDER_REFRESH_HUNT_PATH 0" - " TASK_STRIDER_START_MOVING 0" - " TASK_WAIT 4" - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_STRIDER_SHOULD_CROUCH" - " COND_STRIDER_HAS_CANNON_TARGET" - " COND_STRIDER_ENEMY_UPDATED" - ) - - //========================================================= - // Attack (Deploy/shoot/finish) - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_STRIDER_RANGE_ATTACK1, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_FACE_ENEMY 0" - " TASK_RANGE_ATTACK1 0" - " TASK_WAIT 5" // let the immolator work its magic - " " - " Interrupts" - ) - - //========================================================= - // Attack (Deploy/shoot/finish) - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_STRIDER_RANGE_ATTACK2, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_STRIDER_FACE_CANNON_TARGET 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT 1" - " TASK_STRIDER_AIM 1.25" - " TASK_STRIDER_FIRE_CANNON 0" - " TASK_WAIT 1" - " " - " Interrupts" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_STRIDER_CROUCH, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_CROUCH" - " " - " Interrupts" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_STRIDER_STAND, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_STAND" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_STRIDER_SET_HEIGHT 500" - " " - " Interrupts" - ) - - //========================================================= - // Dodge Incoming missile - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_STRIDER_DODGE, - - " Tasks" - " TASK_STRIDER_DODGE 0" - " " - " Interrupts" - ) - - //========================================================= - // Break down and die - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_STRIDER_DIE, - - " Tasks" - " TASK_STRIDER_BREAKDOWN 0" - " " - " Interrupts" - ) - - //========================================================= - // Stomp on an enemy - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_STRIDER_STOMPL, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_STRIDER_STOMP 0" - " " - " Interrupts" - ); - - // Stomp on an enemy - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_STRIDER_STOMPR, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_STRIDER_STOMP 1" - " " - " Interrupts" - ) - - DEFINE_SCHEDULE - ( - SCHED_STRIDER_FLICKL, - - " Tasks" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_STRIDER_FLICKL" - " " - " Interrupts" - ) - DEFINE_SCHEDULE - ( - SCHED_STRIDER_FLICKR, - - " Tasks" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_STRIDER_FLICKR" - " " - " Interrupts" - ) - DEFINE_SCHEDULE - ( - SCHED_STRIDER_ATTACK_CANNON_TARGET, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_STRIDER_GET_PATH_TO_CANNON_TARGET 0" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " " - " Interrupts" - " COND_CAN_RANGE_ATTACK2" - " COND_STRIDER_SHOULD_CROUCH" - ) - - DEFINE_SCHEDULE - ( - SCHED_STRIDER_CHASE_ENEMY, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_GET_CHASE_PATH_TO_ENEMY 300" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_FACE_ENEMY 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_ENEMY_UNREACHABLE" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK2" - " COND_TOO_CLOSE_TO_ATTACK" - " COND_LOST_ENEMY" - " COND_STRIDER_HAS_CANNON_TARGET" - ) - - DEFINE_SCHEDULE - ( - SCHED_STRIDER_COMBAT_FACE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT_FACE_ENEMY 1" - "" - " Interrupts" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_STRIDER_HAS_CANNON_TARGET" - ) - - DEFINE_SCHEDULE - ( - SCHED_STRIDER_AGGRESSIVE_COMBAT_STAND, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT 1" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_SEE_ENEMY" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - " COND_CAN_MELEE_ATTACK1" - " COND_CAN_MELEE_ATTACK2" - " COND_IDLE_INTERRUPT" - ) - - DEFINE_SCHEDULE - ( - SCHED_STRIDER_ESTABLISH_LINE_OF_FIRE_CANNON, - - " Tasks " - " TASK_STRIDER_GET_PATH_TO_CANNON_LOS 0" - " TASK_RUN_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_STRIDER_FACE_CANNON_TARGET 0" - "" - " Interrupts " - " COND_CAN_RANGE_ATTACK2" - " COND_STRIDER_SHOULD_CROUCH" - " COND_STRIDER_SHOULD_STAND" - ) - - DEFINE_SCHEDULE - ( - SCHED_STRIDER_FALL_TO_GROUND, - - " Tasks " - " TASK_STRIDER_FALL_TO_GROUND 0" - "" - " Interrupts " - ) - - -AI_END_CUSTOM_NPC() - -//============================================================================= diff --git a/game/server/hl2/npc_strider.h b/game/server/hl2/npc_strider.h deleted file mode 100644 index b74fb05a1..000000000 --- a/game/server/hl2/npc_strider.h +++ /dev/null @@ -1,645 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef NPC_STRIDER_H -#define NPC_STRIDER_H - -#include "ai_blended_movement.h" -#include "ai_pathfinder.h" -#include "ai_navigator.h" -#include "ai_utils.h" -#include "smoke_trail.h" -#include "physics_bone_follower.h" -#include "physics_prop_ragdoll.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -#include "tier0/memdbgon.h" - -class CNPC_Strider; -class CNPC_Bullseye; -class CStriderMinigun; - -//----------------------------------------------------------------------------- -// -// Support for moving Strider air nodes to the correct Z for the Strider -// regardless of Hammer placement -// -//----------------------------------------------------------------------------- - -class CAI_Network; -class CAI_Node; -struct StriderMinigunViewcone_t; -struct AI_EnemyInfo_t; - -void AdjustStriderNodePosition( CAI_Network *pNetwork, CAI_Node *pNode ); - -//----------------------------------------------------------------------------- -// -// Strider Minigun -// -//----------------------------------------------------------------------------- - -abstract_class IMinigunHost -{ -public: - virtual void ShootMinigun( const Vector *pTarget, float aimError, const Vector &vecSpread = vec3_origin ) = 0; - virtual void UpdateMinigunControls( float &yaw, float &pitch ) = 0; - virtual void GetViewCone( StriderMinigunViewcone_t &cone ) = 0; - virtual void NewTarget() = 0; - virtual void OnMinigunStartShooting( CBaseEntity *pTarget ) = 0; - virtual void OnMinigunStopShooting( CBaseEntity *pTarget ) = 0; - virtual CAI_BaseNPC *GetEntity() = 0; -}; - -abstract_class IStriderMinigunHost : public IMinigunHost -{ -public: - virtual float GetMinigunRateOfFire() = 0; - virtual float GetMinigunOnTargetTime() = 0; - virtual float GetMinigunShootDuration() = 0; - virtual float GetMinigunShootDowntime() = 0; - virtual float GetMinigunShootVariation() = 0; -}; - -//----------------------------------------------------------------------------- -// -// npc_strider -// -//----------------------------------------------------------------------------- - -const int NUM_STRIDER_IK_TARGETS = 6; - -//--------------------------------------------------------- - -class CNPC_Strider : public CAI_BlendingHost, - public IStriderMinigunHost -{ - DECLARE_CLASS( CNPC_Strider, CAI_BaseNPC ); - DECLARE_SERVERCLASS(); - -public: - CNPC_Strider(); - ~CNPC_Strider(); - - //--------------------------------- - - void Precache(); - void Spawn(); - bool CreateVPhysics(); - void InitBoneFollowers( void ); - void PostNPCInit(); - void Activate(); - void UpdateOnRemove(); - void InitBoneControllers(); - void OnRestore(); - - Class_T Classify(); - bool ShouldAttractAutoAim( CBaseEntity *pAimingEnt ); - - virtual float GetAutoAimRadius() { return 80.0f; } - - int DrawDebugTextOverlays(); - - void UpdateEfficiency( bool bInPVS ) { SetEfficiency( ( GetSleepState() != AISS_AWAKE ) ? AIE_DORMANT : AIE_NORMAL ); SetMoveEfficiency( AIME_NORMAL ); } - virtual bool ShouldProbeCollideAgainstEntity( CBaseEntity *pEntity ); - - //--------------------------------- - - virtual Vector GetNodeViewOffset() { return BaseClass::GetDefaultEyeOffset(); } - - Vector EyePosition(); - const Vector & GetViewOffset(); - Vector EyePositionCrouched() { return GetAbsOrigin() - Vector( 0, 0, 330 ); } - - //--------------------------------- - // CBaseAnimating - void CalculateIKLocks( float currentTime ); - float GetIdealAccel() const { return GetIdealSpeed(); } - - //--------------------------------- - // Behavior - //--------------------------------- - void NPCThink(); - void PrescheduleThink(); - void GatherConditions(); - void CheckFlinches() {} // Strider handles on own - void GatherHeightConditions( const Vector &vTestPos, CBaseEntity *pEntity ); - void OnStateChange( NPC_STATE oldState, NPC_STATE newState ); - void BuildScheduleTestBits(); - int SelectSchedule(); - int TranslateSchedule( int scheduleType ); - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - bool HandleInteraction( int interactionType, void *data, CBaseCombatCharacter* sourceEnt ); - void HandleAnimEvent( animevent_t *pEvent ); - - Disposition_t IRelationType( CBaseEntity *pTarget ); - void AddEntityRelationship( CBaseEntity *pEntity, Disposition_t nDisposition, int nPriority ); - - bool ScheduledMoveToGoalEntity( int scheduleType, CBaseEntity *pGoalEntity, Activity movementActivity ); - bool ScheduledFollowPath( int scheduleType, CBaseEntity *pPathStart, Activity movementActivity ); - - //--------------------------------- - // Inputs - //--------------------------------- - void InputSetMinigunTime( inputdata_t &inputdata ); - void InputSetMinigunTarget( inputdata_t &inputdata ); - void InputDisableMinigun( inputdata_t &inputdata ); - void InputEnableMinigun( inputdata_t &inputdata ); - void InputSetCannonTarget( inputdata_t &inputdata ); - void InputFlickRagdoll( inputdata_t &inputdata ); - void InputDisableCollisionWith( inputdata_t &inputdata ); - void InputEnableCollisionWith( inputdata_t &inputdata ); - void InputCrouch( inputdata_t &inputdata ); - void InputCrouchInstantly( inputdata_t &inputdata ); - void InputStand( inputdata_t &inputdata ); - void InputSetHeight( inputdata_t &inputdata ); - void InputSetTargetPath( inputdata_t &inputdata ); - void InputClearTargetPath( inputdata_t &inputdata ); - void InputDisableCrouchWalk( inputdata_t &inputdata ); - void InputEnableCrouchWalk( inputdata_t &inputdata ); - void InputEnableAggressiveBehavior( inputdata_t &inputdata ); - void InputDisableAggressiveBehavior( inputdata_t &inputdata ); - void InputStopShootingMinigunForSeconds( inputdata_t &inputdata ); - void InputDisableCrouch( inputdata_t &inputdata ); - void InputDisableMoveToLOS( inputdata_t &inputdata ); - void InputExplode( inputdata_t &inputdata ); - void InputScaleGroundSpeed( inputdata_t &inputdata ); - - //--------------------------------- - // Combat - //--------------------------------- - bool HasPass() { return m_PlayerFreePass.HasPass(); } - - bool FVisible( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ); - Vector BodyTarget( const Vector &posSrc, bool bNoisy ); - - bool IsValidEnemy( CBaseEntity *pTarget ); - bool UpdateEnemyMemory( CBaseEntity *pEnemy, const Vector &position, CBaseEntity *pInformer = NULL ); - float StriderEnemyDistance( CBaseEntity *pEnemy ); - - bool FCanCheckAttacks(); - int RangeAttack2Conditions( float flDot, float flDist ); - int MeleeAttack1Conditions( float flDot, float flDist ); - int MeleeAttack2Conditions( float flDot, float flDist ); - bool WeaponLOSCondition(const Vector &ownerPos, const Vector &targetPos, bool bSetConditions); - bool CurrentWeaponLOSCondition(const Vector &targetPos, bool bSetConditions); - bool IsValidShootPosition ( const Vector &vecCoverLocation, CAI_Node *pNode, CAI_Hint const *pHint ); - bool TestShootPosition(const Vector &vecShootPos, const Vector &targetPos ); - - Vector Weapon_ShootPosition(); - - void MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ); - void DoImpactEffect( trace_t &tr, int nDamageType ); - void DoMuzzleFlash( void ); - - bool CanShootThrough( const trace_t &tr, const Vector &vecTarget ); - - void CreateFocus(); - CNPC_Bullseye * GetFocus(); - - bool GetWeaponLosZ( const Vector &vOrigin, float minZ, float maxZ, float increment, CBaseEntity *pTarget, float *pResult ); - - //--------------------------------- - // Sounds & speech - //--------------------------------- - void AlertSound(); - void PainSound( const CTakeDamageInfo &info ); - void DeathSound( const CTakeDamageInfo &info ); - void HuntSound(); - - //--------------------------------- - // Damage handling - //--------------------------------- - void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - int TakeDamageFromCombineBall( const CTakeDamageInfo &info ); - void Event_Killed( const CTakeDamageInfo &info ); - void RagdollDeathEffect( CRagdollProp *pRagdoll, float flDuration ); - bool BecomeRagdoll( const CTakeDamageInfo &info, const Vector &forceVector ); - void StartSmoking(); - void StopSmoking( float flDelay = 0.1 ); - bool IsSmoking() { return m_hSmoke != NULL; } - void Explode(); - - //--------------------------------- - // Posture - //--------------------------------- - float GetMaxHeightModel() const { return 500.0; } - float GetMaxHeight() const { return 490.0; } - float GetMinHeight() const { return 200.0; } - float GetHeightRange() const { return GetMaxHeight() - GetMinHeight(); } - void SetHeight( float h ); - float GetHeight() { return GetPoseParameter( gm_BodyHeightPoseParam ); } - void SetIdealHeight( float h ); - void SetAbsIdealHeight( float z ); - float GetIdealHeight() { return m_idealHeight; } - Vector GetAdjustedOrigin() { Vector result = GetAbsOrigin(); result.z -= GetMaxHeightModel() - GetHeight(); return result; } - - bool IsInCrouchedPosture() { return GetIdealHeight() < GetMaxHeight() * .5; } - bool IsInStandingPosture() { return !IsInCrouchedPosture(); } - bool IsStriderCrouching(); - bool IsStriderStanding(); - void SetupGlobalModelData(); - - virtual bool CanBecomeServerRagdoll( void ) { return false; } - - //--------------------------------- - // Navigation & Movement - //--------------------------------- - class CNavigator : public CAI_ComponentWithOuter - { - typedef CAI_ComponentWithOuter BaseClass; - public: - CNavigator( CNPC_Strider *pOuter ) - : BaseClass( pOuter ) - { - } - - void MoveCalcBaseGoal( AILocalMoveGoal_t *pMoveGoal ); - bool MoveUpdateWaypoint( AIMoveResult_t *pResult ); - bool DoFindPathToPos(); - bool ShouldOptimizeInitialPathSegment( AI_Waypoint_t *pFirstWaypoint ); - bool GetStoppingPath( CAI_WaypointList *pClippedWaypoints ); - }; - - class CPathfinder : public CAI_Pathfinder - { - typedef CAI_Pathfinder BaseClass; - public: - CPathfinder( CNPC_Strider *pOuter ) : BaseClass( pOuter ) {} - virtual bool CanUseLocalNavigation() { return false; } - }; - - friend class CNavigator; - friend void AdjustStriderNodePosition( CAI_Network *pNetwork, CAI_Node *pNode ); - - bool OverrideMove( float flInterval ); - void MaintainTurnActivity( void ); - bool IsUnusableNode(int iNodeID, CAI_Hint *pHint); // Override for special NPC behavior - void TranslateNavGoal( CBaseEntity *pEnemy, Vector &chasePosition ); - bool HasPendingTargetPath(); - void SetTargetPath(); - float GetDefaultNavGoalTolerance(); - void OnMovementComplete(); - float GetSequenceGroundSpeed( CStudioHdr *pStudioHdr, int iSequence ); - - float MaxYawSpeed(); - - CAI_Navigator * CreateNavigator() { return new CNavigator( this ); } - CAI_Pathfinder *CreatePathfinder() { return new CPathfinder( this ); } - - //--------------------------------- - // Minigun - //--------------------------------- - void ShootMinigun( const Vector *pTarget, float aimError, const Vector &vecSpread = vec3_origin ); - void UpdateMinigunControls( float &yaw, float &pitch ); - void GetViewCone( StriderMinigunViewcone_t &cone ); - void NewTarget() { m_flTargetAcquiredTime = gpGlobals->curtime; } - void OnMinigunStartShooting( CBaseEntity *pTarget ) {}; - void OnMinigunStopShooting( CBaseEntity *pTarget ); - float GetMinigunRateOfFire(); - float GetMinigunOnTargetTime(); - float GetMinigunShootDuration(); - float GetMinigunShootDowntime(); - float GetMinigunShootVariation(); - - CAI_BaseNPC * GetEntity() { return this; } - - bool IsUsingAggressiveBehavior() { return m_bUseAggressiveBehavior; } - - //--------------------------------- - // Cannon - //--------------------------------- - Vector CannonPosition(); - CBaseEntity * GetCannonTarget(); - bool HasCannonTarget() const; - bool IsCannonTarget( CBaseEntity *pTarget ) const; - bool AimCannonAt( CBaseEntity *pEntity, float flInterval ); - void FireCannon(); - void CannonHitThink(); - - //--------------------------------- - // Collision handling - //--------------------------------- - - void VPhysicsShadowCollision( int index, gamevcollisionevent_t *pEvent ); - bool TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ); - - // Conservative collision volumes - static float gm_strideLength; - -#ifdef HL2_EPISODIC - void StriderBusterAttached( CBaseEntity *pAttached ); - void StriderBusterDetached( CBaseEntity *pAttached ); -#endif // HL2_EPISODIC - -public: - - //--------------------------------- - // Misc - //--------------------------------- - bool CarriedByDropship(); - void CarriedThink(); - - //--------------------------------- - // Foot handling - //--------------------------------- - Vector LeftFootHit( float eventtime ); - Vector RightFootHit( float eventtime ); - Vector BackFootHit( float eventtime ); - void StompHit( int followerBoneIndex ); - - void FootFX( const Vector &origin ); - Vector CalculateStompHitPosition( CBaseEntity *pEnemy ); - bool IsLegBoneFollower( CBoneFollower *pFollower ); - CBoneFollower *GetBoneFollowerByIndex( int nIndex ); - int GetBoneFollowerIndex( CBoneFollower *pFollower ); - -protected: - // Because the strider is a leaf class, we can use - // static variables to store this information, and save some memory. - // Should the strider end up having inheritors, their activate may - // stomp these numbers, in which case you should make these ordinary members - // again. - // - // The strider also caches some pose parameters in SetupGlobalModelData(). - static int m_poseMiniGunYaw, m_poseMiniGunPitch; - static bool m_sbStaticPoseParamsLoaded; - virtual void PopulatePoseParameters( void ); - -private: - - bool ShouldExplodeFromDamage( const CTakeDamageInfo &info ); - bool m_bExploding; - - //----------------------------------------------------- - // Conditions, Schedules, Tasks - //----------------------------------------------------- - enum - { - SCHED_STRIDER_RANGE_ATTACK1 = BaseClass::NEXT_SCHEDULE, - SCHED_STRIDER_RANGE_ATTACK2, // Immolator - SCHED_STRIDER_CROUCH, - SCHED_STRIDER_STAND, - SCHED_STRIDER_DODGE, - SCHED_STRIDER_STOMPL, - SCHED_STRIDER_STOMPR, - SCHED_STRIDER_FLICKL, - SCHED_STRIDER_FLICKR, - SCHED_STRIDER_HUNT, - SCHED_STRIDER_DIE, - SCHED_STRIDER_ATTACK_CANNON_TARGET, - SCHED_STRIDER_CHASE_ENEMY, - SCHED_STRIDER_COMBAT_FACE, - SCHED_STRIDER_AGGRESSIVE_COMBAT_STAND, - SCHED_STRIDER_ESTABLISH_LINE_OF_FIRE_CANNON, - SCHED_STRIDER_FALL_TO_GROUND, - - TASK_STRIDER_AIM = BaseClass::NEXT_TASK, - TASK_STRIDER_DODGE, - TASK_STRIDER_STOMP, - TASK_STRIDER_BREAKDOWN, - TASK_STRIDER_START_MOVING, - TASK_STRIDER_REFRESH_HUNT_PATH, - TASK_STRIDER_GET_PATH_TO_CANNON_TARGET, - TASK_STRIDER_FACE_CANNON_TARGET, - TASK_STRIDER_SET_HEIGHT, - TASK_STRIDER_GET_PATH_TO_CANNON_LOS, - TASK_STRIDER_SET_CANNON_HEIGHT, - TASK_STRIDER_FIRE_CANNON, - TASK_STRIDER_FALL_TO_GROUND, - - COND_STRIDER_DO_FLICK = BaseClass::NEXT_CONDITION, - COND_TRACK_PATH_GO, - COND_STRIDER_SHOULD_CROUCH, - COND_STRIDER_SHOULD_STAND, - COND_STRIDER_MINIGUN_SHOOTING, - COND_STRIDER_MINIGUN_NOT_SHOOTING, - COND_STRIDER_HAS_CANNON_TARGET, - COND_STRIDER_ENEMY_UPDATED, - COND_STRIDER_HAS_LOS_Z, - }; - - string_t m_iszStriderBusterName; - string_t m_iszMagnadeClassname; - string_t m_iszHunterClassname; - - CStriderMinigun *m_pMinigun; - int m_miniGunAmmo; - int m_miniGunDirectAmmo; - float m_nextShootTime; - float m_nextStompTime; - float m_ragdollTime; - float m_miniGunShootDuration; - float m_aimYaw; - float m_aimPitch; - Vector m_blastHit; - Vector m_blastNormal; - CNetworkVector( m_vecHitPos ); - CNetworkArray( Vector, m_vecIKTarget, NUM_STRIDER_IK_TARGETS ); - - CRandSimTimer m_PostureAnimationTimer; - - EHANDLE m_hRagdoll; - - EHANDLE m_hCannonTarget; - CSimpleSimTimer m_AttemptCannonLOSTimer; - - float m_flSpeedScale; - float m_flTargetSpeedScale; - - CSimpleSimTimer m_LowZCorrectionTimer; - - // Contained Bone Follower manager - CBoneFollowerManager m_BoneFollowerManager; - - int m_BodyTargetBone; - - bool m_bDisableBoneFollowers; - - int m_iVisibleEnemies; - float m_flTargetAcquiredTime; - bool m_bCrouchLocked; // Designer made the strider crouch. Don't let the AI stand him up. - bool m_bNoCrouchWalk; - bool m_bDontCrouch; - bool m_bNoMoveToLOS; - bool m_bFastCrouch; - bool m_bMinigunEnabled; // If false, minigun disabled by level designer until further notice. - - float m_idealHeight; - float m_HeightVelocity; - - // FIXME: move to a base class to handle turning for blended movement derived characters - float m_prevYaw; - float m_doTurn; - float m_doLeft; - float m_doRight; - float m_flNextTurnAct; - - string_t m_strTrackName; - - EHANDLE m_hFocus; - - float m_flTimeLastAlertSound; - float m_flTimeNextHuntSound; - bool m_bUseAggressiveBehavior; - float m_flTimePlayerMissileDetected; - EHANDLE m_hPlayersMissile; - bool m_bMinigunUseDirectFire; - - CHandle m_hSmoke; - - CSimpleSimTimer m_EnemyUpdatedTimer; - - CAI_FreePass m_PlayerFreePass; - -#ifdef HL2_EPISODIC - CUtlVector< EHANDLE > m_hAttachedBusters; // List of busters attached to us -#endif // HL2_EPISODIC - - static float gm_zCannonDist; - static float gm_zMinigunDist; - static Vector gm_vLocalRelativePositionCannon; - static Vector gm_vLocalRelativePositionMinigun; - - static int gm_YawControl; - static int gm_PitchControl; - static int gm_CannonAttachment; - static int gm_BodyHeightPoseParam; - - DEFINE_CUSTOM_AI; - - DECLARE_DATADESC(); -}; - -//----------------------------------------------------------------------------- -//--------------------------------------------------------- - -enum StriderMinigunPeg_t -{ - MINIGUN_PEGGED_DONT_CARE = 0, - MINIGUN_PEGGED_UP, - MINIGUN_PEGGED_DOWN, - MINIGUN_PEGGED_LEFT, - MINIGUN_PEGGED_RIGHT, -}; - -//--------------------------------------------------------- - -struct StriderMinigunViewcone_t -{ - Vector origin; - Vector axis; - float cosAngle; - float length; -}; - -//--------------------------------------------------------- - -struct StriderMinigunAnimController_t -{ - float current; - float target; - float rate; - - void Update( float dt, bool approach = true ) - { - if( approach ) - { - current = Approach( target, current, rate * dt ); - } - else - { - current = target; - } - } - - void Random( float minTarget, float maxTarget, float minRate, float maxRate ) - { - target = random->RandomFloat( minTarget, maxTarget ); - rate = random->RandomFloat( minRate, maxRate ); - } -}; - -//--------------------------------------------------------- - -class CStriderMinigun -{ -public: - DECLARE_DATADESC(); - - void Init(); - void SetTarget( IStriderMinigunHost *pHost, CBaseEntity *pTarget, bool bOverrideEnemy = false ); - CBaseEntity *GetTarget() { return m_hTarget.Get(); } - void Think( IStriderMinigunHost *pHost, float dt ); - void SetState( int newState ); - bool ShouldFindTarget( IMinigunHost *pHost ); - void AimAtPoint( IStriderMinigunHost *pHost, const Vector &vecPoint, bool bSnap = false ); - void AimAtTarget( IStriderMinigunHost *pHost, CBaseEntity *pTarget, bool bSnap = false ); - void ShootAtTarget( IStriderMinigunHost *pHost, CBaseEntity *pTarget, float shootTime ); - void StartShooting( IStriderMinigunHost *pHost, CBaseEntity *pTarget, float duration ); - void ExtendShooting( float timeExtend ); - void SetShootDuration( float duration ); - void StopShootingForSeconds( IStriderMinigunHost *pHost, CBaseEntity *pTarget, float duration ); - bool IsPegged( int dir = MINIGUN_PEGGED_DONT_CARE ); - bool CanStartShooting( IStriderMinigunHost *pHost, CBaseEntity *pTargetEnt ); - float GetBurstTimeRemaining() { return m_burstTime - gpGlobals->curtime; } - - void RecordShotOnTarget() { m_iOnTargetShots++; } - void ClearOnTarget() { m_iOnTargetShots = 0; } - bool IsOnTarget( int numShots = 0 ) { return ( numShots == 0 ) ? (m_iOnTargetShots > 0) : (m_iOnTargetShots >= numShots); } - - void Enable( IMinigunHost *pHost, bool enable ); - float GetAimError(); - - enum minigunstates_t - { - MINIGUN_OFF = 0, - MINIGUN_SHOOTING = 1, - }; - - int GetState() { return m_minigunState; } - bool IsShooting() { return GetState() == MINIGUN_SHOOTING; } - -private: - bool m_enable; - int m_minigunState; - float m_nextBulletTime; // Minigun is shooting, when can I fire my next bullet? - float m_burstTime; // If firing, how long till done? If not, how long till I can? - float m_nextTwitchTime; - int m_randomState; - EHANDLE m_hTarget; - StriderMinigunAnimController_t m_yaw; - StriderMinigunAnimController_t m_pitch; - bool m_bWarnedAI; - float m_shootDuration; - Vector m_vecAnchor; // A burst starts here and goes to the target's orgin. - bool m_bOverrideEnemy; // The minigun wants something other than the Strider's enemy as a target right now. - Vector m_vecLastTargetPos; // Last place minigun saw the target. - int m_iOnTargetShots; -}; - - -class CSparkTrail : public CPointEntity -{ - DECLARE_CLASS( CSparkTrail, CPointEntity ); - void Spawn( void ); - void SparkThink( void ); - - virtual void Precache(); - - DECLARE_DATADESC(); -}; - -#include "tier0/memdbgoff.h" - -#endif // NPC_STRIDER_H - -//============================================================================= diff --git a/game/server/hl2/npc_turret.cpp b/game/server/hl2/npc_turret.cpp deleted file mode 100644 index 9edd0bd71..000000000 --- a/game/server/hl2/npc_turret.cpp +++ /dev/null @@ -1,1198 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// TODO: -// Take advantage of new NPC fields like GetEnemy() and get rid of that OFFSET() stuff -// Revisit enemy validation stuff, maybe it's not necessary with the newest NPC code -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "Sprite.h" -#include "basecombatweapon.h" -#include "AI_BaseNPC.h" -#include "AI_Senses.h" -#include "AI_Memory.h" -#include "gamerules.h" -#include "ammodef.h" -#include "ndebugoverlay.h" -#include "IEffects.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" - -class CSprite; - -#define TURRET_RANGE (100 * 12) -#define TURRET_SPREAD VECTOR_CONE_5DEGREES -#define TURRET_TURNRATE 360 // max angles per second -#define TURRET_MAXWAIT 15 // seconds turret will stay active w/o a target -#define TURRET_MAXSPIN 5 // seconds turret barrel will spin w/o a target -#define TURRET_MACHINE_VOLUME 0.5 - -#define TURRET_BC_YAW "aim_yaw" -#define TURRET_BC_PITCH "aim_pitch" - -#define TURRET_ORIENTATION_FLOOR 0 -#define TURRET_ORIENTATION_CEILING 1 - -//========================================================= -// private activities -//========================================================= -int ACT_TURRET_OPEN; -int ACT_TURRET_CLOSE; -int ACT_TURRET_OPEN_IDLE; -int ACT_TURRET_CLOSED_IDLE; -int ACT_TURRET_FIRE; -int ACT_TURRET_RELOAD; - -// =============================================== -// Private spawn flags (must be above (1<<15)) -// =============================================== -#define SF_NPC_TURRET_AUTOACTIVATE 0x00000020 -#define SF_NPC_TURRET_STARTINACTIVE 0x00000040 - -extern short g_sModelIndexSmoke; // (in combatweapon.cpp) holds the index for the smoke cloud - -ConVar sk_miniturret_health( "sk_miniturret_health","0"); -ConVar sk_sentry_health( "sk_sentry_health","0"); -ConVar sk_turret_health( "sk_turret_health","0"); - -class CBaseTurret : public CAI_BaseNPC -{ - DECLARE_CLASS( CBaseTurret, CAI_BaseNPC ); -public: - void Spawn(void); - virtual void Precache(void); - bool KeyValue( const char *szKeyName, const char *szValue ); - //void TurretUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - virtual Class_T Classify(void); - - int BloodColor( void ) { return DONT_BLEED; } - bool Event_Gibbed( void ) { return FALSE; } // UNDONE: Throw turret gibs? - - Vector EyeOffset( Activity nActivity ); - Vector EyePosition( void ); - - // Inputs - void InputToggle( inputdata_t &inputdata ); - - // Think functions - - void ActiveThink(void); - void SearchThink(void); - void AutoSearchThink(void); - void TurretDeath(void); - - void Deploy(void); - void Retire(void); - - void Initialize(void); - - virtual void Ping(void); - virtual void EyeOn(void); - virtual void EyeOff(void); - - DECLARE_DATADESC(); - - // other functions - int MoveTurret(void); - virtual void Shoot(const Vector &vecSrc, const Vector &vecDirToEnemy) { }; - - CSprite *m_pEyeGlow; - int m_eyeBrightness; - - int m_iDeployHeight; - int m_iRetractHeight; - int m_iMinPitch; - - int m_iBaseTurnRate; // angles per second - float m_fTurnRate; // actual turn rate - int m_iOn; - int m_fBeserk; // Sometimes this bitch will just freak out - int m_iAutoStart; // true if the turret auto deploys when a target - // enters its range - - Vector m_vecLastSight; // Last seen position - float m_flLastSight; // Last time we saw a target - float m_flMaxWait; // Max time to search w/o a target - - // movement - float m_flStartYaw; - QAngle m_vecGoalAngles; - - int m_iAmmoType; - - float m_flPingTime; // Time until the next ping, used when searching - float m_flDamageTime; // Time we last took damage. - - COutputEvent m_OnDeploy; - COutputEvent m_OnRetire; - - // external - //COutputEvent m_OnDamaged; - //COutputEvent m_OnDeath; - //COutputEvent m_OnHalfHealth; - //COutputEHANDLE m_OnFoundEnemy; - //COutputEvent m_OnLostEnemyLOS; - //COutputEvent m_OnLostEnemy; - //COutputEHANDLE m_OnFoundPlayer; - //COutputEvent m_OnLostPlayerLOS; - //COutputEvent m_OnLostPlayer; - //COutputEvent m_OnHearWorld; - //COutputEvent m_OnHearPlayer; - //COutputEvent m_OnHearCombat; - -}; - - -BEGIN_DATADESC( CBaseTurret ) - - DEFINE_FIELD( m_pEyeGlow, FIELD_CLASSPTR ), - DEFINE_FIELD( m_eyeBrightness, FIELD_INTEGER ), - DEFINE_FIELD( m_iDeployHeight, FIELD_INTEGER ), - DEFINE_FIELD( m_iRetractHeight, FIELD_INTEGER ), - DEFINE_FIELD( m_iMinPitch, FIELD_INTEGER ), - - DEFINE_FIELD( m_iBaseTurnRate, FIELD_INTEGER ), - DEFINE_FIELD( m_fTurnRate, FIELD_FLOAT ), - DEFINE_FIELD( m_iOn, FIELD_INTEGER ), - DEFINE_FIELD( m_fBeserk, FIELD_INTEGER ), - DEFINE_FIELD( m_iAutoStart, FIELD_INTEGER ), - - DEFINE_FIELD( m_vecLastSight, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_flLastSight, FIELD_TIME ), - DEFINE_FIELD( m_flMaxWait, FIELD_FLOAT ), - - DEFINE_FIELD( m_flStartYaw, FIELD_FLOAT ), - DEFINE_FIELD( m_vecGoalAngles, FIELD_VECTOR ), - - DEFINE_FIELD( m_iAmmoType, FIELD_INTEGER ), - - DEFINE_FIELD( m_flPingTime, FIELD_TIME ), - DEFINE_FIELD( m_flDamageTime, FIELD_TIME ), - - // Function pointers - //DEFINE_USEFUNC( TurretUse ), - DEFINE_THINKFUNC( ActiveThink ), - DEFINE_THINKFUNC( SearchThink ), - DEFINE_THINKFUNC( AutoSearchThink ), - DEFINE_THINKFUNC( TurretDeath ), - DEFINE_THINKFUNC( Deploy ), - DEFINE_THINKFUNC( Retire ), - DEFINE_THINKFUNC( Initialize ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - - // Outputs - DEFINE_OUTPUT(m_OnDeploy, "OnDeploy"), - DEFINE_OUTPUT(m_OnRetire, "OnRetire"), - -END_DATADESC() - - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -Vector CBaseTurret::EyeOffset( Activity nActivity ) -{ - return Vector( 0, 0, -20 ); -} - - -Vector CBaseTurret::EyePosition( void ) -{ - Vector vecOrigin; - QAngle vecAngles; - - GetAttachment( "eyes", vecOrigin, vecAngles ); - return vecOrigin; -} - -bool CBaseTurret::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "maxsleep")) - { - m_flMaxWait = atof(szValue); - } - else if (FStrEq(szKeyName, "turnrate")) - { - m_iBaseTurnRate = atoi(szValue); - } - else if (FStrEq(szKeyName, "style") || - FStrEq(szKeyName, "height") || - FStrEq(szKeyName, "value1") || - FStrEq(szKeyName, "value2") || - FStrEq(szKeyName, "value3")) - { - } - else - return BaseClass::KeyValue( szKeyName, szValue ); - - return true; -} - - -void CBaseTurret::Spawn() -{ - Precache( ); - SetNextThink( gpGlobals->curtime + 1 ); - SetMoveType( MOVETYPE_FLY ); - SetSequence(0); - SetCycle(0); - SetSolid( SOLID_SLIDEBOX ); - m_takedamage = DAMAGE_YES; - AddFlag( FL_AIMTARGET ); - - m_iAmmoType = g_pGameRules->GetAmmoDef()->Index("SMG1"); - - AddFlag( FL_NPC ); - - if (( m_spawnflags & SF_NPC_TURRET_AUTOACTIVATE ) && !( m_spawnflags & SF_NPC_TURRET_STARTINACTIVE )) - { - m_iAutoStart = true; - } - - ResetSequenceInfo( ); - - SetPoseParameter( TURRET_BC_YAW, 0 ); - SetPoseParameter( TURRET_BC_PITCH, 0 ); - - // Activities - ADD_CUSTOM_ACTIVITY( CBaseTurret, ACT_TURRET_OPEN ); - ADD_CUSTOM_ACTIVITY( CBaseTurret, ACT_TURRET_CLOSE ); - ADD_CUSTOM_ACTIVITY( CBaseTurret, ACT_TURRET_CLOSED_IDLE ); - ADD_CUSTOM_ACTIVITY( CBase`matTurret, ACT_TURRET_OPEN_IDLE ); - ADD_CUSTOM_ACTIVITY( CBaseTurret, ACT_TURRET_FIRE ); - ADD_CUSTOM_ACTIVITY( CBaseTurret, ACT_TURRET_RELOAD ); -} - - -void CBaseTurret::Precache( ) -{ - BaseClass::Precache(); - - PrecacheScriptSound( "NPC_Turret.Ping" ); - PrecacheScriptSound( "NPC_Turret.Deploy" ); - PrecacheScriptSound( "NPC_Turret.Retire" ); - PrecacheScriptSound( "NPC_Turret.Alert" ); - PrecacheScriptSound( "NPC_Turret.Die" ); -} - -void CBaseTurret::Initialize(void) -{ - m_iOn = 0; - m_fBeserk = 0; - - SetPoseParameter( TURRET_BC_YAW, 0 ); - SetPoseParameter( TURRET_BC_PITCH, 0 ); - - if (m_iBaseTurnRate == 0) m_iBaseTurnRate = TURRET_TURNRATE; - if (m_flMaxWait == 0) m_flMaxWait = TURRET_MAXWAIT; - - m_vecGoalAngles = GetAbsAngles(); - - if (m_iAutoStart) - { - m_flLastSight = gpGlobals->curtime + m_flMaxWait; - SetThink(&CBaseTurret::AutoSearchThink); - SetNextThink( gpGlobals->curtime + .1 ); - } - else - SetThink(&CBaseEntity::SUB_DoNothing); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for toggling the turret on/off. -//----------------------------------------------------------------------------- -void CBaseTurret::InputToggle( inputdata_t &inputdata ) -{ - //if ( !ShouldToggle( useType, m_iOn ) ) - // return; - - if (m_iOn) - { - SetEnemy( NULL ); - SetNextThink( gpGlobals->curtime + 0.1f ); - m_iAutoStart = FALSE;// switching off a turret disables autostart - //!!!! this should spin down first!!BUGBUG - SetThink(&CBaseTurret::Retire); - } - else - { - SetNextThink( gpGlobals->curtime + 0.1f ); // turn on delay - - // if the turret is flagged as an autoactivate turret, re-enable its ability open self. - if ( m_spawnflags & SF_NPC_TURRET_AUTOACTIVATE ) - { - m_iAutoStart = TRUE; - } - - SetThink(&CBaseTurret::Deploy); - } -} - - -void CBaseTurret::Ping( void ) -{ - // make the pinging noise every second while searching - if (m_flPingTime == 0) - m_flPingTime = gpGlobals->curtime + 1; - else if (m_flPingTime <= gpGlobals->curtime) - { - m_flPingTime = gpGlobals->curtime + 1; - EmitSound( "NPC_Turret.Ping" ); - EyeOn( ); - } - else if (m_eyeBrightness > 0) - { - EyeOff( ); - } -} - - -void CBaseTurret::EyeOn( ) -{ - if (m_pEyeGlow) - { - if (m_eyeBrightness != 255) - { - m_eyeBrightness = 255; - } - m_pEyeGlow->SetBrightness( m_eyeBrightness ); - } -} - - -void CBaseTurret::EyeOff( ) -{ - if (m_pEyeGlow) - { - if (m_eyeBrightness > 0) - { - m_eyeBrightness = MAX( 0, m_eyeBrightness - 30 ); - m_pEyeGlow->SetBrightness( m_eyeBrightness ); - } - } -} - - -void CBaseTurret::ActiveThink(void) -{ - int fAttack = 0; - Vector vecDirToEnemy; - - SetNextThink( gpGlobals->curtime + 0.1f ); - StudioFrameAdvance( ); - - if ((!m_iOn) || (GetEnemy() == NULL)) - { - SetEnemy( NULL ); - m_flLastSight = gpGlobals->curtime + m_flMaxWait; - SetThink(&CBaseTurret::SearchThink); - return; - } - - // if it's dead, look for something new - if ( !GetEnemy()->IsAlive() ) - { - if (!m_flLastSight) - { - m_flLastSight = gpGlobals->curtime + 0.5; // continue-shooting timeout - } - else - { - if (gpGlobals->curtime > m_flLastSight) - { - SetEnemy( NULL ); - m_flLastSight = gpGlobals->curtime + m_flMaxWait; - SetThink(&CBaseTurret::SearchThink); - return; - } - } - } - - Vector vecMid = EyePosition( ); - Vector vecMidEnemy = GetEnemy()->BodyTarget(vecMid); - - // g_pEffects->Sparks( vecMid ); - // g_pEffects->Sparks( vecMidEnemy ); - - // Look for our current enemy - //int fEnemyVisible = FBoxVisible( this, GetEnemy(), vecMidEnemy ); - int fEnemyVisible = FInViewCone( GetEnemy() ) && FVisible( GetEnemy() ); - - vecDirToEnemy = vecMidEnemy - vecMid; // calculate dir and dist to enemy - // NDebugOverlay::Line( vecMid, vecMidEnemy, 0, 255, 0, false, 0.1 ); - - float flDistToEnemy = vecDirToEnemy.Length(); - - QAngle vecAnglesToEnemy; - VectorNormalize( vecDirToEnemy ); - VectorAngles( vecDirToEnemy, vecAnglesToEnemy ); - - // Current enmey is not visible. - if (!fEnemyVisible || (flDistToEnemy > TURRET_RANGE)) - { - // DevMsg( "lost you\n" ); - - if (!m_flLastSight) - { - m_flLastSight = gpGlobals->curtime + 0.5; - } - else - { - // Should we look for a new target? - if (gpGlobals->curtime > m_flLastSight) - { - ClearEnemyMemory(); - SetEnemy( NULL ); - m_flLastSight = gpGlobals->curtime + m_flMaxWait; - SetThink(&CBaseTurret::SearchThink); - return; - } - } - fEnemyVisible = 0; - } - else - { - m_vecLastSight = vecMidEnemy; - } - - Vector vecLOS = vecDirToEnemy; //vecMid - m_vecLastSight; - VectorNormalize( vecLOS ); - - Vector vecMuzzle, vecMuzzleDir; - QAngle vecMuzzleAng; - GetAttachment( "eyes", vecMuzzle, vecMuzzleAng ); - - AngleVectors( vecMuzzleAng, &vecMuzzleDir ); - - // Is the Gun looking at the target - if (DotProduct(vecLOS, vecMuzzleDir) <= 0.9848) // 10 degree slop - { - fAttack = FALSE; - } - else - { - fAttack = TRUE; - } - - // fire the gun - if (fAttack || m_fBeserk) - { - SetActivity(ACT_RESET); - SetActivity( (Activity)ACT_TURRET_FIRE ); - Shoot(vecMuzzle, vecMuzzleDir ); - } - else - { - SetActivity( (Activity)ACT_TURRET_OPEN_IDLE ); - } - - //move the gun - if (m_fBeserk) - { - // DevMsg( "berserk" ); - - if (random->RandomInt(0,9) == 0) - { - m_vecGoalAngles.y = random->RandomFloat(-180,180); - m_vecGoalAngles.x = random->RandomFloat(-90,90); - OnTakeDamage( CTakeDamageInfo( this, this, 1, DMG_GENERIC ) ); // don't beserk forever - return; - } - } - else if (fEnemyVisible) - { - // DevMsg( "->[%.2f]\n", vec.x); - m_vecGoalAngles.y = vecAnglesToEnemy.y; - m_vecGoalAngles.x = vecAnglesToEnemy.x; - - } - - MoveTurret(); -} - - -void CBaseTurret::Deploy(void) -{ - SetNextThink( gpGlobals->curtime + 0.1f ); - StudioFrameAdvance( ); - - if ( GetActivity() != ACT_TURRET_OPEN ) - { - m_iOn = 1; - SetActivity( (Activity)ACT_TURRET_OPEN ); - EmitSound( "NPC_Turret.Deploy" ); - - m_OnDeploy.FireOutput(NULL, this); - } - - if (m_fSequenceFinished) - { - Vector curmins, curmaxs; - curmins = WorldAlignMins(); - curmaxs = WorldAlignMaxs(); - - curmaxs.z = m_iDeployHeight; - curmins.z = -m_iDeployHeight; - - SetCollisionBounds( curmins, curmaxs ); - - Relink(); - - SetActivity( (Activity)ACT_TURRET_OPEN_IDLE ); - - m_flPlaybackRate = 0; - SetThink(&CBaseTurret::SearchThink); - } - - m_flLastSight = gpGlobals->curtime + m_flMaxWait; -} - -void CBaseTurret::Retire(void) -{ - // make the turret level - m_vecGoalAngles = GetAbsAngles( ); - - SetNextThink( gpGlobals->curtime + 0.1f ); - - StudioFrameAdvance( ); - - EyeOff( ); - - if ( GetActivity() != ACT_TURRET_CLOSE ) - { - SetActivity( (Activity)ACT_TURRET_OPEN_IDLE ); - - if (!MoveTurret()) - { - SetActivity( (Activity)ACT_TURRET_CLOSE ); - EmitSound( "NPC_Turret.Retire" ); - - m_OnRetire.FireOutput(NULL, this); - } - } - else if (m_fSequenceFinished) - { - m_iOn = 0; - m_flLastSight = 0; - - SetActivity( (Activity)ACT_TURRET_CLOSED_IDLE ); - - Vector curmins, curmaxs; - curmins = WorldAlignMins(); - curmaxs = WorldAlignMaxs(); - - curmaxs.z = m_iRetractHeight; - curmins.z = -m_iRetractHeight; - - SetCollisionBounds( curmins, curmaxs ); - Relink(); - - if (m_iAutoStart) - { - SetThink(&CBaseTurret::AutoSearchThink); - SetNextThink( gpGlobals->curtime + .1 ); - } - else - { - SetThink(&CBaseEntity::SUB_DoNothing); - } - } -} - - -// -// This search function will sit with the turret deployed and look for a new target. -// After a set amount of time, the barrel will spin down. After m_flMaxWait, the turret will -// retact. -// -void CBaseTurret::SearchThink(void) -{ - // ensure rethink - SetActivity( (Activity)ACT_TURRET_OPEN_IDLE ); - - StudioFrameAdvance( ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - Ping( ); - - // If we have a target and we're still healthy - if (GetEnemy() != NULL) - { - if (!GetEnemy()->IsAlive() ) - SetEnemy( NULL );// Dead enemy forces a search for new one - } - - // Acquire Target - if (GetEnemy() == NULL) - { - GetSenses()->Look(TURRET_RANGE); - SetEnemy( BestEnemy() ); - } - - // If we've found a target, spin up the barrel and start to attack - if (GetEnemy() != NULL) - { - m_flLastSight = 0; - SetThink(&CBaseTurret::ActiveThink); - } - else - { - // Are we out of time, do we need to retract? - if (gpGlobals->curtime > m_flLastSight) - { - //Before we retrace, make sure that we are spun down. - m_flLastSight = 0; - SetThink(&CBaseTurret::Retire); - } - - // generic hunt for new victims - m_vecGoalAngles.y = (m_vecGoalAngles.y + 0.1 * m_iBaseTurnRate); - if (m_vecGoalAngles.y >= 360) - m_vecGoalAngles.y -= 360; - - MoveTurret(); - } -} - - -// -// This think function will deploy the turret when something comes into range. This is for -// automatically activated turrets. -// -void CBaseTurret::AutoSearchThink(void) -{ - // ensure rethink - StudioFrameAdvance( ); - SetNextThink( gpGlobals->curtime + random->RandomFloat( 0.2, 0.3 ) ); - - // If we have a target and we're still healthy - - if (GetEnemy() != NULL) - { - if (!GetEnemy()->IsAlive() ) - SetEnemy( NULL );// Dead enemy forces a search for new one - } - - // Acquire Target - - if (GetEnemy() == NULL) - { - GetSenses()->Look( TURRET_RANGE ); - SetEnemy( BestEnemy() ); - } - - if (GetEnemy() != NULL) - { - SetThink(&CBaseTurret::Deploy); - EmitSound( "NPC_Turret.Alert" ); - } -} - - -void CBaseTurret :: TurretDeath( void ) -{ - StudioFrameAdvance( ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - if (m_lifeState != LIFE_DEAD) - { - m_lifeState = LIFE_DEAD; - - EmitSound( "NPC_Turret.Die" ); - - SetActivity( (Activity)ACT_TURRET_CLOSE ); - - EyeOn( ); - } - - EyeOff( ); - - if (m_flDamageTime + random->RandomFloat( 0, 2 ) > gpGlobals->curtime) - { - // lots of smoke - Vector pos; - CollisionProp()->RandomPointInBounds( vec3_origin, Vector( 1, 1, 1 ), &pos ); - pos.z = CollisionProp()->GetCollisionOrigin().z; - - CBroadcastRecipientFilter filter; - te->Smoke( filter, 0.0, &pos, - g_sModelIndexSmoke, - 2.5, - 10 ); - } - - if (m_flDamageTime + random->RandomFloat( 0, 5 ) > gpGlobals->curtime) - { - Vector vecSrc; - CollisionProp()->RandomPointInBounds( vec3_origin, Vector( 1, 1, 1 ), &vecSrc ); - g_pEffects->Sparks( vecSrc ); - } - - if (m_fSequenceFinished && !MoveTurret( ) && m_flDamageTime + 5 < gpGlobals->curtime) - { - m_flPlaybackRate = 0; - SetThink( NULL ); - } -} - - - -void CBaseTurret::TraceAttack( const CTakeDamageInfo &inputInfo, const Vector &vecDir, trace_t *ptr ) -{ - CTakeDamageInfo info = inputInfo; - - if ( ptr->hitgroup == 10 ) - { - // hit armor - if ( m_flDamageTime != gpGlobals->curtime || (random->RandomInt(0,10) < 1) ) - { - g_pEffects->Ricochet( ptr->endpos, (vecDir*-1.0f) ); - m_flDamageTime = gpGlobals->curtime; - } - - info.SetDamage( 0.1 );// don't hurt the NPC much, but allow bits_COND_LIGHT_DAMAGE to be generated - } - - if ( !m_takedamage ) - return; - - AddMultiDamage( info, this ); -} - - -int CBaseTurret::OnTakeDamage( const CTakeDamageInfo &inputInfo ) -{ - if ( !m_takedamage ) - return 0; - - CTakeDamageInfo info = inputInfo; - - if (!m_iOn) - info.ScaleDamage( 0.1f ); - - m_iHealth -= info.GetDamage(); - if (m_iHealth <= 0) - { - m_iHealth = 0; - m_takedamage = DAMAGE_NO; - m_flDamageTime = gpGlobals->curtime; - - RemoveFlag( FL_NPC ); // why are they set in the first place??? - - SetThink(&CBaseTurret::TurretDeath); - - m_OnDamaged.FireOutput( info.GetInflictor(), this ); - - SetNextThink( gpGlobals->curtime + 0.1f ); - - return 0; - } - - if (m_iHealth <= 10) - { - if (m_iOn && (1 || random->RandomInt(0, 0x7FFF) > 800)) - { - m_fBeserk = 1; - SetThink(&CBaseTurret::SearchThink); - } - } - - return 1; -} - - -int CBaseTurret::MoveTurret(void) -{ - bool bDidMove = false; - int iPose; - - matrix3x4_t localToWorld; - - GetAttachment( LookupAttachment( "eyes" ), localToWorld ); - - Vector vecGoalDir; - AngleVectors( m_vecGoalAngles, &vecGoalDir ); - - Vector vecGoalLocalDir; - VectorIRotate( vecGoalDir, localToWorld, vecGoalLocalDir ); - - QAngle vecGoalLocalAngles; - VectorAngles( vecGoalLocalDir, vecGoalLocalAngles ); - - float flDiff; - QAngle vecNewAngles; - - // update pitch - flDiff = AngleNormalize( UTIL_ApproachAngle( vecGoalLocalAngles.x, 0.0, 0.1 * m_iBaseTurnRate ) ); - iPose = LookupPoseParameter( TURRET_BC_PITCH ); - SetPoseParameter( iPose, GetPoseParameter( iPose ) + flDiff / 1.5 ); - - if (fabs(flDiff) > 0.1) - { - bDidMove = true; - } - - // update yaw, with acceleration -#if 0 - float flDist = AngleNormalize( vecGoalLocalAngles.y ); - float flNewDist; - float flNewTurnRate; - - ChangeDistance( 0.1, flDist, 0.0, m_fTurnRate, m_iBaseTurnRate, m_iBaseTurnRate * 4, flNewDist, flNewTurnRate ); - m_fTurnRate = flNewTurnRate; - flDiff = flDist - flNewDist; -#else - flDiff = AngleNormalize( UTIL_ApproachAngle( vecGoalLocalAngles.y, 0.0, 0.1 * m_iBaseTurnRate ) ); -#endif - - iPose = LookupPoseParameter( TURRET_BC_YAW ); - SetPoseParameter( iPose, GetPoseParameter( iPose ) + flDiff / 1.5 ); - if (fabs(flDiff) > 0.1) - { - bDidMove = true; - } - - if (bDidMove) - { - // DevMsg( "(%.2f, %.2f)\n", AngleNormalize( vecGoalLocalAngles.x ), AngleNormalize( vecGoalLocalAngles.y ) ); - } - return bDidMove; -} - -// -// ID as a machine -// -Class_T CBaseTurret::Classify ( void ) - -{ - if (m_iOn || m_iAutoStart) - { - return CLASS_MILITARY; - } - - return CLASS_MILITARY; -} - - - - -////////////////////////////////////////////////////////////////////////////////////////////////////// - - -class CCeilingTurret : public CBaseTurret -{ - DECLARE_CLASS( CCeilingTurret, CBaseTurret ); -public: - void Spawn(void); - void Precache(void); - - // other functions - void Shoot( const Vector &vecSrc, const Vector &vecDirToEnemy ); -}; - -#define TURRET_GLOW_SPRITE "sprites/glow01.vmt" - -LINK_ENTITY_TO_CLASS( npc_turret_ceiling, CCeilingTurret ); - -void CCeilingTurret::Spawn() -{ - Vector up; - - Precache( ); - - SetModel( "models/combine_turrets/ceiling_turret.mdl" ); - - BaseClass::Spawn( ); - - m_iHealth = sk_turret_health.GetFloat(); - m_HackedGunPos = Vector( 0, 0, 12.75 ); - - AngleVectors( GetAbsAngles(), NULL, NULL, &up ); - SetViewOffset( up * Vector( 0, 0, -64 ) ); - - m_flFieldOfView = VIEW_FIELD_FULL; - - m_iRetractHeight = 16; - m_iDeployHeight = 32; - m_iMinPitch = -45; - UTIL_SetSize(this, Vector(-32, -32, -m_iRetractHeight), Vector(32, 32, m_iRetractHeight)); - - SetThink(&CBaseTurret::Initialize); - - m_pEyeGlow = CSprite::SpriteCreate( TURRET_GLOW_SPRITE, GetAbsOrigin(), FALSE ); - m_pEyeGlow->SetTransparency( kRenderGlow, 255, 0, 0, 0, kRenderFxNoDissipation ); - m_pEyeGlow->SetAttachment( this, 2 ); - m_eyeBrightness = 0; - - SetNextThink( gpGlobals->curtime + 0.3 ); -} - -void CCeilingTurret::Precache() -{ - PrecacheModel( "models/combine_turrets/ceiling_turret.mdl"); - PrecacheModel( TURRET_GLOW_SPRITE ); - - PrecacheScriptSound( "CeilingTurret.Shoot" ); - BaseClass::Precache(); -} - -void CCeilingTurret::Shoot(const Vector &vecSrc, const Vector &vecDirToEnemy) -{ - //NDebugOverlay::Line( vecSrc, vecSrc + vecDirToEnemy * 512, 0, 255, 255, false, 0.1 ); - FireBullets( 1, vecSrc, vecDirToEnemy, TURRET_SPREAD, TURRET_RANGE, m_iAmmoType, 1 ); - EmitSound( "CeilingTurret.Shoot" ); - - DoMuzzleFlash(); -} - -////////////////////////////////////////////////////////////////////////////////////////////////////// - -#if 0 - -class CMiniTurret : public CBaseTurret -{ - DECLARE_CLASS( CMiniTurret, CBaseTurret ); -public: - void Spawn( ); - void Precache(void); - // other functions - void Shoot(const Vector &vecSrc, const Vector &vecDirToEnemy); -}; - -LINK_ENTITY_TO_CLASS( npc_miniturret, CMiniTurret ); - - -void CMiniTurret::Spawn() -{ - Precache( ); - SetModel( "models/miniturret.mdl" ); - m_iHealth = sk_miniturret_health.GetFloat(); - m_HackedGunPos = Vector( 0, 0, 12.75 ); - m_vecViewOffset.z = 12.75; - m_flFieldOfView = VIEW_FIELD_NARROW; - - CBaseTurret::Spawn( ); - - m_iAmmoType = g_pGameRules->GetAmmoDef()->Index("Pistol"); - - m_iRetractHeight = 16; - m_iDeployHeight = 32; - m_iMinPitch = -45; - UTIL_SetSize(this, Vector(-16, -16, -m_iRetractHeight), Vector(16, 16, m_iRetractHeight)); - - SetThink(Initialize); - SetNextThink( gpGlobals->curtime + 0.3; ); -} - - -void CMiniTurret::Precache() -{ - PrecacheModel ("models/miniturret.mdl"); - - PrecacheScriptSound( "MiniTurret.Shoot" ); - - BaseClass::Precache(); -} - - - -void CMiniTurret::Shoot(const Vector &vecSrc, const Vector &vecDirToEnemy) -{ - FireBullets( 1, vecSrc, vecDirToEnemy, TURRET_SPREAD, TURRET_RANGE, m_iAmmoType, 1 ); - - EmitSound( "MiniTurret.Shoot" ); - - DoMuzzleFlash(); -} - - -#endif - - -//========================================================= -// Sentry gun - smallest turret, placed near grunt entrenchments -//========================================================= -class CSentry : public CBaseTurret -{ - DECLARE_CLASS( CSentry, CBaseTurret ); -public: - void Spawn( ); - void Precache(void); - // other functions - void Shoot(const Vector &vecSrc, const Vector &vecDirToEnemy); - int OnTakeDamage( const CTakeDamageInfo &info ); - void SentryTouch( CBaseEntity *pOther ); - void SentryDeath( void ); - -protected: - - DECLARE_DATADESC(); -}; - - -BEGIN_DATADESC( CSentry ) - - // Function pointers - DEFINE_ENTITYFUNC( SentryTouch ), - DEFINE_THINKFUNC( SentryDeath ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( NPC_sentry, CSentry ); - -void CSentry::Precache() -{ - PrecacheModel ("models/sentry.mdl"); - - PrecacheScriptSound( "Sentry.Shoot" ); - PrecacheScriptSound( "Sentry.Die" ); - - BaseClass::Precache(); -} - -void CSentry::Spawn() -{ - Vector viewOffs; - - Precache( ); - SetModel( "models/sentry.mdl" ); - m_iHealth = sk_sentry_health.GetFloat(); - m_HackedGunPos = Vector( 0, 0, 48 ); - - viewOffs = GetViewOffset(); - viewOffs.z = 48; - SetViewOffset(viewOffs); - - m_flMaxWait = 1E6; - - CBaseTurret::Spawn(); - m_iRetractHeight = 64; - m_iDeployHeight = 64; - m_iMinPitch = -60; - UTIL_SetSize(this, Vector(-16, -16, -m_iRetractHeight), Vector(16, 16, m_iRetractHeight)); - - SetTouch(&CSentry::SentryTouch); - SetThink(&CBaseTurret::Initialize); - SetNextThink( gpGlobals->curtime + 0.3 ); -} - -void CSentry::Shoot(const Vector &vecSrc, const Vector &vecDirToEnemy) -{ - FireBullets( 1, vecSrc, vecDirToEnemy, TURRET_SPREAD, TURRET_RANGE, m_iAmmoType, 1 ); - - EmitSound( "Sentry.Shoot" ); - - DoMuzzleFlash(); -} - - -int CSentry::OnTakeDamage( const CTakeDamageInfo &info ) -{ - if ( !m_takedamage ) - return 0; - - if (!m_iOn) - { - SetThink( &CBaseTurret::Deploy ); - SetNextThink( gpGlobals->curtime + 0.1f ); - } - - m_iHealth -= info.GetDamage(); - if (m_iHealth <= 0) - { - m_iHealth = 0; - m_takedamage = DAMAGE_NO; - m_flDamageTime = gpGlobals->curtime; - - RemoveFlag( FL_NPC ); // why are they set in the first place??? - - SetThink(&CSentry::SentryDeath); - m_OnDamaged.FireOutput( info.GetInflictor(), this ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - return 0; - } - - return 1; -} - - -void CSentry::SentryTouch( CBaseEntity *pOther ) -{ - if ( pOther && (pOther->IsPlayer() || (pOther->GetFlags() & FL_NPC)) ) - { - OnTakeDamage( CTakeDamageInfo( pOther, pOther, 0, 0 ) ); - } -} - - -void CSentry :: SentryDeath( void ) -{ - StudioFrameAdvance( ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - if (m_lifeState != LIFE_DEAD) - { - m_lifeState = LIFE_DEAD; - - EmitSound( "Sentry.Die" ); - - SetPoseParameter( TURRET_BC_YAW, 0 ); - SetPoseParameter( TURRET_BC_PITCH, 0 ); - - SetActivity( (Activity)ACT_TURRET_CLOSE ); - - SetSolid( SOLID_NOT ); - QAngle angles = GetAbsAngles(); - angles.y = UTIL_AngleMod( angles.y + random->RandomInt( 0, 2 ) * 120 ); - SetAbsAngles( angles ); - - EyeOn( ); - } - - EyeOff( ); - - Vector vecSrc; - QAngle vecAng; - GetAttachment( "eyes", vecSrc, vecAng ); - - if (m_flDamageTime + random->RandomFloat( 0, 2 ) > gpGlobals->curtime) - { - // lots of smoke - Vector pos = vecSrc + Vector( random->RandomFloat( -16, 16 ), - random->RandomFloat( -16, 16 ), - -32 ); - - CBroadcastRecipientFilter filter; - te->Smoke( filter, 0.0, &pos, - g_sModelIndexSmoke, - 1.5, - 8 ); - } - - if (m_flDamageTime + random->RandomFloat( 0, 8 ) > gpGlobals->curtime) - { - g_pEffects->Sparks( vecSrc ); - } - - if (m_fSequenceFinished && m_flDamageTime + 5 < gpGlobals->curtime) - { - m_flPlaybackRate = 0; - SetThink( NULL ); - } -} - diff --git a/game/server/hl2/npc_turret_ceiling.cpp b/game/server/hl2/npc_turret_ceiling.cpp deleted file mode 100644 index 3e8786960..000000000 --- a/game/server/hl2/npc_turret_ceiling.cpp +++ /dev/null @@ -1,1127 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ai_basenpc.h" -#include "ai_senses.h" -#include "ai_memory.h" -#include "engine/IEngineSound.h" -#include "ammodef.h" -#include "Sprite.h" -#include "hl2/hl2_player.h" -#include "soundenvelope.h" -#include "explode.h" -#include "IEffects.h" -#include "animation.h" -#include "basehlcombatweapon_shared.h" -#include "iservervehicle.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//Debug visualization -ConVar g_debug_turret_ceiling( "g_debug_turret_ceiling", "0" ); - -#define CEILING_TURRET_MODEL "models/combine_turrets/ceiling_turret.mdl" -#define CEILING_TURRET_GLOW_SPRITE "sprites/glow1.vmt" -/* // we now inherit these from the ai_basenpc baseclass -#define CEILING_TURRET_BC_YAW "aim_yaw" -#define CEILING_TURRET_BC_PITCH "aim_pitch" -*/ -#define CEILING_TURRET_RANGE 1500 -#define CEILING_TURRET_SPREAD VECTOR_CONE_2DEGREES -#define CEILING_TURRET_MAX_WAIT 5 -#define CEILING_TURRET_PING_TIME 1.0f //LPB!! - -#define CEILING_TURRET_VOICE_PITCH_LOW 45 -#define CEILING_TURRET_VOICE_PITCH_HIGH 100 - -//Aiming variables -#define CEILING_TURRET_MAX_NOHARM_PERIOD 0.0f -#define CEILING_TURRET_MAX_GRACE_PERIOD 3.0f - -//Spawnflags -#define SF_CEILING_TURRET_AUTOACTIVATE 0x00000020 -#define SF_CEILING_TURRET_STARTINACTIVE 0x00000040 -#define SF_CEILING_TURRET_NEVERRETIRE 0x00000080 -#define SF_CEILING_TURRET_OUT_OF_AMMO 0x00000100 - -//Heights -#define CEILING_TURRET_RETRACT_HEIGHT 24 -#define CEILING_TURRET_DEPLOY_HEIGHT 64 - -//Activities -int ACT_CEILING_TURRET_OPEN; -int ACT_CEILING_TURRET_CLOSE; -int ACT_CEILING_TURRET_OPEN_IDLE; -int ACT_CEILING_TURRET_CLOSED_IDLE; -int ACT_CEILING_TURRET_FIRE; -int ACT_CEILING_TURRET_DRYFIRE; - -//Turret states -enum turretState_e -{ - TURRET_SEARCHING, - TURRET_AUTO_SEARCHING, - TURRET_ACTIVE, - TURRET_DEPLOYING, - TURRET_RETIRING, - TURRET_DEAD, -}; - -//Eye states -enum eyeState_t -{ - TURRET_EYE_SEE_TARGET, //Sees the target, bright and big - TURRET_EYE_SEEKING_TARGET, //Looking for a target, blinking (bright) - TURRET_EYE_DORMANT, //Not active - TURRET_EYE_DEAD, //Completely invisible - TURRET_EYE_DISABLED, //Turned off, must be reactivated before it'll deploy again (completely invisible) -}; - -// -// Ceiling Turret -// - -class CNPC_CeilingTurret : public CAI_BaseNPC -{ - DECLARE_CLASS( CNPC_CeilingTurret, CAI_BaseNPC ); -public: - - CNPC_CeilingTurret( void ); - ~CNPC_CeilingTurret( void ); - - void Precache( void ); - void Spawn( void ); - - // Think functions - void Retire( void ); - void Deploy( void ); - void ActiveThink( void ); - void SearchThink( void ); - void AutoSearchThink( void ); - void DeathThink( void ); - - // Inputs - void InputToggle( inputdata_t &inputdata ); - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - - void SetLastSightTime(); - - float MaxYawSpeed( void ); - - int OnTakeDamage( const CTakeDamageInfo &inputInfo ); - - virtual bool CanBeAnEnemyOf( CBaseEntity *pEnemy ); - - Class_T Classify( void ) - { - if( m_bEnabled ) - return CLASS_COMBINE; - - return CLASS_NONE; - } - - bool FVisible( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ); - - Vector EyeOffset( Activity nActivity ) - { - Vector vecEyeOffset(0,0,-64); - GetEyePosition( GetModelPtr(), vecEyeOffset ); - return vecEyeOffset; - } - - Vector EyePosition( void ) - { - return GetAbsOrigin() + EyeOffset(GetActivity()); - } - - Vector GetAttackSpread( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget ) - { - return VECTOR_CONE_5DEGREES * ((CBaseHLCombatWeapon::GetDefaultProficiencyValues())[ WEAPON_PROFICIENCY_PERFECT ].spreadscale); - } - -protected: - - bool PreThink( turretState_e state ); - void Shoot( const Vector &vecSrc, const Vector &vecDirToEnemy ); - void SetEyeState( eyeState_t state ); - void Ping( void ); - void Toggle( void ); - void Enable( void ); - void Disable( void ); - void SpinUp( void ); - void SpinDown( void ); - void SetHeight( float height ); - - bool UpdateFacing( void ); - - int m_iAmmoType; - int m_iMinHealthDmg; - - bool m_bAutoStart; - bool m_bActive; //Denotes the turret is deployed and looking for targets - bool m_bBlinkState; - bool m_bEnabled; //Denotes whether the turret is able to deploy or not - - float m_flShotTime; - float m_flLastSight; - float m_flPingTime; - - QAngle m_vecGoalAngles; - - CSprite *m_pEyeGlow; - - COutputEvent m_OnDeploy; - COutputEvent m_OnRetire; - COutputEvent m_OnTipped; - - DECLARE_DATADESC(); -}; - -//Datatable -BEGIN_DATADESC( CNPC_CeilingTurret ) - - DEFINE_FIELD( m_iAmmoType, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_iMinHealthDmg, FIELD_INTEGER, "minhealthdmg" ), - DEFINE_FIELD( m_bAutoStart, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bActive, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bBlinkState, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flShotTime, FIELD_TIME ), - DEFINE_FIELD( m_flLastSight, FIELD_TIME ), - DEFINE_FIELD( m_flPingTime, FIELD_TIME ), - DEFINE_FIELD( m_vecGoalAngles, FIELD_VECTOR ), - DEFINE_FIELD( m_pEyeGlow, FIELD_CLASSPTR ), - - DEFINE_THINKFUNC( Retire ), - DEFINE_THINKFUNC( Deploy ), - DEFINE_THINKFUNC( ActiveThink ), - DEFINE_THINKFUNC( SearchThink ), - DEFINE_THINKFUNC( AutoSearchThink ), - DEFINE_THINKFUNC( DeathThink ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - - DEFINE_OUTPUT( m_OnDeploy, "OnDeploy" ), - DEFINE_OUTPUT( m_OnRetire, "OnRetire" ), - DEFINE_OUTPUT( m_OnTipped, "OnTipped" ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( npc_turret_ceiling, CNPC_CeilingTurret ); - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CNPC_CeilingTurret::CNPC_CeilingTurret( void ) -{ - m_bActive = false; - m_pEyeGlow = NULL; - m_iAmmoType = -1; - m_iMinHealthDmg = 0; - m_bAutoStart = false; - m_flPingTime = 0; - m_flShotTime = 0; - m_flLastSight = 0; - m_bBlinkState = false; - m_bEnabled = false; - - m_vecGoalAngles.Init(); -} - -CNPC_CeilingTurret::~CNPC_CeilingTurret( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: Precache -//----------------------------------------------------------------------------- -void CNPC_CeilingTurret::Precache( void ) -{ - PrecacheModel( CEILING_TURRET_MODEL ); - PrecacheModel( CEILING_TURRET_GLOW_SPRITE ); - - // Activities - ADD_CUSTOM_ACTIVITY( CNPC_CeilingTurret, ACT_CEILING_TURRET_OPEN ); - ADD_CUSTOM_ACTIVITY( CNPC_CeilingTurret, ACT_CEILING_TURRET_CLOSE ); - ADD_CUSTOM_ACTIVITY( CNPC_CeilingTurret, ACT_CEILING_TURRET_CLOSED_IDLE ); - ADD_CUSTOM_ACTIVITY( CNPC_CeilingTurret, ACT_CEILING_TURRET_OPEN_IDLE ); - ADD_CUSTOM_ACTIVITY( CNPC_CeilingTurret, ACT_CEILING_TURRET_FIRE ); - ADD_CUSTOM_ACTIVITY( CNPC_CeilingTurret, ACT_CEILING_TURRET_DRYFIRE ); - - PrecacheScriptSound( "NPC_CeilingTurret.Retire" ); - PrecacheScriptSound( "NPC_CeilingTurret.Deploy" ); - PrecacheScriptSound( "NPC_CeilingTurret.Move" ); - PrecacheScriptSound( "NPC_CeilingTurret.Active" ); - PrecacheScriptSound( "NPC_CeilingTurret.Alert" ); - PrecacheScriptSound( "NPC_CeilingTurret.ShotSounds" ); - PrecacheScriptSound( "NPC_CeilingTurret.Ping" ); - PrecacheScriptSound( "NPC_CeilingTurret.Die" ); - - PrecacheScriptSound( "NPC_FloorTurret.DryFire" ); - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: Spawn the entity -//----------------------------------------------------------------------------- -void CNPC_CeilingTurret::Spawn( void ) -{ - Precache(); - - SetModel( CEILING_TURRET_MODEL ); - - BaseClass::Spawn(); - - m_HackedGunPos = Vector( 0, 0, 12.75 ); - SetViewOffset( EyeOffset( ACT_IDLE ) ); - m_flFieldOfView = 0.0f; - m_takedamage = DAMAGE_YES; - m_iHealth = 1000; - m_bloodColor = BLOOD_COLOR_MECH; - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - - SetHeight( CEILING_TURRET_RETRACT_HEIGHT ); - - AddFlag( FL_AIMTARGET ); - AddEFlags( EFL_NO_DISSOLVE ); - - SetPoseParameter( m_poseAim_Yaw, 0 ); - SetPoseParameter( m_poseAim_Pitch, 0 ); - - m_iAmmoType = GetAmmoDef()->Index( "AR2" ); - - //Create our eye sprite - m_pEyeGlow = CSprite::SpriteCreate( CEILING_TURRET_GLOW_SPRITE, GetLocalOrigin(), false ); - m_pEyeGlow->SetTransparency( kRenderTransAdd, 255, 0, 0, 128, kRenderFxNoDissipation ); - m_pEyeGlow->SetAttachment( this, 2 ); - - //Set our autostart state - m_bAutoStart = !!( m_spawnflags & SF_CEILING_TURRET_AUTOACTIVATE ); - m_bEnabled = ( ( m_spawnflags & SF_CEILING_TURRET_STARTINACTIVE ) == false ); - - //Do we start active? - if ( m_bAutoStart && m_bEnabled ) - { - SetThink( &CNPC_CeilingTurret::AutoSearchThink ); - SetEyeState( TURRET_EYE_DORMANT ); - } - else - { - SetEyeState( TURRET_EYE_DISABLED ); - } - - //Stagger our starting times - SetNextThink( gpGlobals->curtime + random->RandomFloat( 0.1f, 0.3f ) ); - - // Don't allow us to skip animation setup because our attachments are critical to us! - SetBoneCacheFlags( BCF_NO_ANIMATION_SKIP ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_CeilingTurret::OnTakeDamage( const CTakeDamageInfo &inputInfo ) -{ - if ( !m_takedamage ) - return 0; - - CTakeDamageInfo info = inputInfo; - - if ( m_bActive == false ) - info.ScaleDamage( 0.1f ); - - // If attacker can't do at least the min required damage to us, don't take any damage from them - if ( info.GetDamage() < m_iMinHealthDmg ) - return 0; - - m_iHealth -= info.GetDamage(); - - if ( m_iHealth <= 0 ) - { - m_iHealth = 0; - m_takedamage = DAMAGE_NO; - - RemoveFlag( FL_NPC ); // why are they set in the first place??? - - //FIXME: This needs to throw a ragdoll gib or something other than animating the retraction -- jdw - - ExplosionCreate( GetAbsOrigin(), GetLocalAngles(), this, 100, 100, false ); - SetThink( &CNPC_CeilingTurret::DeathThink ); - - StopSound( "NPC_CeilingTurret.Alert" ); - - m_OnDamaged.FireOutput( info.GetInflictor(), this ); - - SetNextThink( gpGlobals->curtime + 0.1f ); - - return 0; - } - - return 1; -} - -//----------------------------------------------------------------------------- -// Purpose: Retract and stop attacking -//----------------------------------------------------------------------------- -void CNPC_CeilingTurret::Retire( void ) -{ - if ( PreThink( TURRET_RETIRING ) ) - return; - - //Level out the turret - m_vecGoalAngles = GetAbsAngles(); - SetNextThink( gpGlobals->curtime ); - - //Set ourselves to close - if ( GetActivity() != ACT_CEILING_TURRET_CLOSE ) - { - //Set our visible state to dormant - SetEyeState( TURRET_EYE_DORMANT ); - - SetActivity( (Activity) ACT_CEILING_TURRET_OPEN_IDLE ); - - //If we're done moving to our desired facing, close up - if ( UpdateFacing() == false ) - { - SetActivity( (Activity) ACT_CEILING_TURRET_CLOSE ); - EmitSound( "NPC_CeilingTurret.Retire" ); - - //Notify of the retraction - m_OnRetire.FireOutput( NULL, this ); - } - } - else if ( IsActivityFinished() ) - { - SetHeight( CEILING_TURRET_RETRACT_HEIGHT ); - - m_bActive = false; - m_flLastSight = 0; - - SetActivity( (Activity) ACT_CEILING_TURRET_CLOSED_IDLE ); - - //Go back to auto searching - if ( m_bAutoStart ) - { - SetThink( &CNPC_CeilingTurret::AutoSearchThink ); - SetNextThink( gpGlobals->curtime + 0.05f ); - } - else - { - //Set our visible state to dormant - SetEyeState( TURRET_EYE_DISABLED ); - SetThink( &CNPC_CeilingTurret::SUB_DoNothing ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Deploy and start attacking -//----------------------------------------------------------------------------- -void CNPC_CeilingTurret::Deploy( void ) -{ - if ( PreThink( TURRET_DEPLOYING ) ) - return; - - m_vecGoalAngles = GetAbsAngles(); - - SetNextThink( gpGlobals->curtime ); - - //Show we've seen a target - SetEyeState( TURRET_EYE_SEE_TARGET ); - - //Open if we're not already - if ( GetActivity() != ACT_CEILING_TURRET_OPEN ) - { - m_bActive = true; - SetActivity( (Activity) ACT_CEILING_TURRET_OPEN ); - EmitSound( "NPC_CeilingTurret.Deploy" ); - - //Notify we're deploying - m_OnDeploy.FireOutput( NULL, this ); - } - - //If we're done, then start searching - if ( IsActivityFinished() ) - { - SetHeight( CEILING_TURRET_DEPLOY_HEIGHT ); - - SetActivity( (Activity) ACT_CEILING_TURRET_OPEN_IDLE ); - - m_flShotTime = gpGlobals->curtime + 1.0f; - - m_flPlaybackRate = 0; - SetThink( &CNPC_CeilingTurret::SearchThink ); - - EmitSound( "NPC_CeilingTurret.Move" ); - } - - SetLastSightTime(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_CeilingTurret::SetLastSightTime() -{ - if( HasSpawnFlags( SF_CEILING_TURRET_NEVERRETIRE ) ) - { - m_flLastSight = FLT_MAX; - } - else - { - m_flLastSight = gpGlobals->curtime + CEILING_TURRET_MAX_WAIT; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the speed at which the turret can face a target -//----------------------------------------------------------------------------- -float CNPC_CeilingTurret::MaxYawSpeed( void ) -{ - //TODO: Scale by difficulty? - return 360.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: Causes the turret to face its desired angles -//----------------------------------------------------------------------------- -bool CNPC_CeilingTurret::UpdateFacing( void ) -{ - bool bMoved = false; - matrix3x4_t localToWorld; - - GetAttachment( LookupAttachment( "eyes" ), localToWorld ); - - Vector vecGoalDir; - AngleVectors( m_vecGoalAngles, &vecGoalDir ); - - Vector vecGoalLocalDir; - VectorIRotate( vecGoalDir, localToWorld, vecGoalLocalDir ); - - if ( g_debug_turret_ceiling.GetBool() ) - { - Vector vecMuzzle, vecMuzzleDir; - QAngle vecMuzzleAng; - - GetAttachment( "eyes", vecMuzzle, vecMuzzleAng ); - AngleVectors( vecMuzzleAng, &vecMuzzleDir ); - - NDebugOverlay::Cross3D( vecMuzzle, -Vector(2,2,2), Vector(2,2,2), 255, 255, 0, false, 0.05 ); - NDebugOverlay::Cross3D( vecMuzzle+(vecMuzzleDir*256), -Vector(2,2,2), Vector(2,2,2), 255, 255, 0, false, 0.05 ); - NDebugOverlay::Line( vecMuzzle, vecMuzzle+(vecMuzzleDir*256), 255, 255, 0, false, 0.05 ); - - NDebugOverlay::Cross3D( vecMuzzle, -Vector(2,2,2), Vector(2,2,2), 255, 0, 0, false, 0.05 ); - NDebugOverlay::Cross3D( vecMuzzle+(vecGoalDir*256), -Vector(2,2,2), Vector(2,2,2), 255, 0, 0, false, 0.05 ); - NDebugOverlay::Line( vecMuzzle, vecMuzzle+(vecGoalDir*256), 255, 0, 0, false, 0.05 ); - } - - QAngle vecGoalLocalAngles; - VectorAngles( vecGoalLocalDir, vecGoalLocalAngles ); - - // Update pitch - float flDiff = AngleNormalize( UTIL_ApproachAngle( vecGoalLocalAngles.x, 0.0, 0.1f * MaxYawSpeed() ) ); - - SetPoseParameter( m_poseAim_Pitch, GetPoseParameter( m_poseAim_Pitch ) + ( flDiff / 1.5f ) ); - - if ( fabs( flDiff ) > 0.1f ) - { - bMoved = true; - } - - // Update yaw - flDiff = AngleNormalize( UTIL_ApproachAngle( vecGoalLocalAngles.y, 0.0, 0.1f * MaxYawSpeed() ) ); - - SetPoseParameter( m_poseAim_Yaw, GetPoseParameter( m_poseAim_Yaw ) + ( flDiff / 1.5f ) ); - - if ( fabs( flDiff ) > 0.1f ) - { - bMoved = true; - } - - InvalidateBoneCache(); - - return bMoved; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEntity - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_CeilingTurret::FVisible( CBaseEntity *pEntity, int traceMask, CBaseEntity **ppBlocker ) -{ - CBaseEntity *pHitEntity = NULL; - if ( BaseClass::FVisible( pEntity, traceMask, &pHitEntity ) ) - return true; - - // If we hit something that's okay to hit anyway, still fire - if ( pHitEntity && pHitEntity->MyCombatCharacterPointer() ) - { - if (IRelationType(pHitEntity) == D_HT) - return true; - } - - if (ppBlocker) - { - *ppBlocker = pHitEntity; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Allows the turret to fire on targets if they're visible -//----------------------------------------------------------------------------- -void CNPC_CeilingTurret::ActiveThink( void ) -{ - //Allow descended classes a chance to do something before the think function - if ( PreThink( TURRET_ACTIVE ) ) - return; - - //Update our think time - SetNextThink( gpGlobals->curtime + 0.1f ); - - //If we've become inactive, go back to searching - if ( ( m_bActive == false ) || ( GetEnemy() == NULL ) ) - { - SetEnemy( NULL ); - SetLastSightTime(); - SetThink( &CNPC_CeilingTurret::SearchThink ); - m_vecGoalAngles = GetAbsAngles(); - return; - } - - //Get our shot positions - Vector vecMid = EyePosition(); - Vector vecMidEnemy = GetEnemy()->GetAbsOrigin(); - - //Store off our last seen location - UpdateEnemyMemory( GetEnemy(), vecMidEnemy ); - - //Look for our current enemy - bool bEnemyVisible = FInViewCone( GetEnemy() ) && FVisible( GetEnemy() ) && GetEnemy()->IsAlive(); - - //Calculate dir and dist to enemy - Vector vecDirToEnemy = vecMidEnemy - vecMid; - float flDistToEnemy = VectorNormalize( vecDirToEnemy ); - - //We want to look at the enemy's eyes so we don't jitter - Vector vecDirToEnemyEyes = GetEnemy()->WorldSpaceCenter() - vecMid; - VectorNormalize( vecDirToEnemyEyes ); - - QAngle vecAnglesToEnemy; - VectorAngles( vecDirToEnemyEyes, vecAnglesToEnemy ); - - //Draw debug info - if ( g_debug_turret_ceiling.GetBool() ) - { - NDebugOverlay::Cross3D( vecMid, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 ); - NDebugOverlay::Cross3D( GetEnemy()->WorldSpaceCenter(), -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 ); - NDebugOverlay::Line( vecMid, GetEnemy()->WorldSpaceCenter(), 0, 255, 0, false, 0.05 ); - - NDebugOverlay::Cross3D( vecMid, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 ); - NDebugOverlay::Cross3D( vecMidEnemy, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 ); - NDebugOverlay::Line( vecMid, vecMidEnemy, 0, 255, 0, false, 0.05f ); - } - - //Current enemy is not visible - if ( ( bEnemyVisible == false ) || ( flDistToEnemy > CEILING_TURRET_RANGE )) - { - if ( m_flLastSight ) - { - m_flLastSight = gpGlobals->curtime + 0.5f; - } - else if ( gpGlobals->curtime > m_flLastSight ) - { - // Should we look for a new target? - ClearEnemyMemory(); - SetEnemy( NULL ); - SetLastSightTime(); - SetThink( &CNPC_CeilingTurret::SearchThink ); - m_vecGoalAngles = GetAbsAngles(); - - SpinDown(); - - return; - } - - bEnemyVisible = false; - } - - Vector vecMuzzle, vecMuzzleDir; - QAngle vecMuzzleAng; - - GetAttachment( "eyes", vecMuzzle, vecMuzzleAng ); - AngleVectors( vecMuzzleAng, &vecMuzzleDir ); - - if ( m_flShotTime < gpGlobals->curtime ) - { - //Fire the gun - if ( DotProduct( vecDirToEnemy, vecMuzzleDir ) >= 0.9848 ) // 10 degree slop - { - if ( m_spawnflags & SF_CEILING_TURRET_OUT_OF_AMMO ) - { - SetActivity( (Activity) ACT_CEILING_TURRET_DRYFIRE ); - } - else - { - SetActivity( (Activity) ACT_CEILING_TURRET_FIRE ); - } - - //Fire the weapon - Shoot( vecMuzzle, vecMuzzleDir ); - } - } - else - { - SetActivity( (Activity) ACT_CEILING_TURRET_OPEN_IDLE ); - } - - //If we can see our enemy, face it - if ( bEnemyVisible ) - { - m_vecGoalAngles.y = vecAnglesToEnemy.y; - m_vecGoalAngles.x = vecAnglesToEnemy.x; - } - - //Turn to face - UpdateFacing(); -} - -//----------------------------------------------------------------------------- -// Purpose: Target doesn't exist or has eluded us, so search for one -//----------------------------------------------------------------------------- -void CNPC_CeilingTurret::SearchThink( void ) -{ - //Allow descended classes a chance to do something before the think function - if ( PreThink( TURRET_SEARCHING ) ) - return; - - SetNextThink( gpGlobals->curtime + 0.05f ); - - SetActivity( (Activity) ACT_CEILING_TURRET_OPEN_IDLE ); - - //If our enemy has died, pick a new enemy - if ( ( GetEnemy() != NULL ) && ( GetEnemy()->IsAlive() == false ) ) - { - SetEnemy( NULL ); - } - - //Acquire the target - if ( GetEnemy() == NULL ) - { - GetSenses()->Look( CEILING_TURRET_RANGE ); - CBaseEntity *pEnemy = BestEnemy(); - if ( pEnemy ) - { - SetEnemy( pEnemy ); - } - } - - //If we've found a target, spin up the barrel and start to attack - if ( GetEnemy() != NULL ) - { - //Give players a grace period - if ( GetEnemy()->IsPlayer() ) - { - m_flShotTime = gpGlobals->curtime + 0.5f; - } - else - { - m_flShotTime = gpGlobals->curtime + 0.1f; - } - - m_flLastSight = 0; - SetThink( &CNPC_CeilingTurret::ActiveThink ); - SetEyeState( TURRET_EYE_SEE_TARGET ); - - SpinUp(); - EmitSound( "NPC_CeilingTurret.Active" ); - return; - } - - //Are we out of time and need to retract? - if ( gpGlobals->curtime > m_flLastSight ) - { - //Before we retrace, make sure that we are spun down. - m_flLastSight = 0; - SetThink( &CNPC_CeilingTurret::Retire ); - return; - } - - //Display that we're scanning - m_vecGoalAngles.x = 15.0f; - m_vecGoalAngles.y = GetAbsAngles().y + ( sin( gpGlobals->curtime * 2.0f ) * 45.0f ); - - //Turn and ping - UpdateFacing(); - Ping(); -} - -//----------------------------------------------------------------------------- -// Purpose: Watch for a target to wander into our view -//----------------------------------------------------------------------------- -void CNPC_CeilingTurret::AutoSearchThink( void ) -{ - //Allow descended classes a chance to do something before the think function - if ( PreThink( TURRET_AUTO_SEARCHING ) ) - return; - - //Spread out our thinking - SetNextThink( gpGlobals->curtime + random->RandomFloat( 0.2f, 0.4f ) ); - - //If the enemy is dead, find a new one - if ( ( GetEnemy() != NULL ) && ( GetEnemy()->IsAlive() == false ) ) - { - SetEnemy( NULL ); - } - - //Acquire Target - if ( GetEnemy() == NULL ) - { - GetSenses()->Look( CEILING_TURRET_RANGE ); - SetEnemy( BestEnemy() ); - } - - //Deploy if we've got an active target - if ( GetEnemy() != NULL ) - { - SetThink( &CNPC_CeilingTurret::Deploy ); - EmitSound( "NPC_CeilingTurret.Alert" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Fire! -//----------------------------------------------------------------------------- -void CNPC_CeilingTurret::Shoot( const Vector &vecSrc, const Vector &vecDirToEnemy ) -{ - if ( m_spawnflags & SF_CEILING_TURRET_OUT_OF_AMMO ) - { - EmitSound( "NPC_FloorTurret.DryFire"); - EmitSound( "NPC_CeilingTurret.Activate" ); - - if ( RandomFloat( 0, 1 ) > 0.7 ) - { - m_flShotTime = gpGlobals->curtime + random->RandomFloat( 0.5, 1.5 ); - } - else - { - m_flShotTime = gpGlobals->curtime; - } - return; - } - - FireBulletsInfo_t info; - - if ( GetEnemy() != NULL ) - { - Vector vecDir = GetActualShootTrajectory( vecSrc ); - - info.m_vecSrc = vecSrc; - info.m_vecDirShooting = vecDir; - info.m_iTracerFreq = 1; - info.m_iShots = 1; - info.m_pAttacker = this; - info.m_vecSpread = VECTOR_CONE_PRECALCULATED; - info.m_flDistance = MAX_COORD_RANGE; - info.m_iAmmoType = m_iAmmoType; - } - else - { - // Just shoot where you're facing! - Vector vecMuzzle, vecMuzzleDir; - QAngle vecMuzzleAng; - - info.m_vecSrc = vecSrc; - info.m_vecDirShooting = vecDirToEnemy; - info.m_iTracerFreq = 1; - info.m_iShots = 1; - info.m_pAttacker = this; - info.m_vecSpread = GetAttackSpread( NULL, NULL ); - info.m_flDistance = MAX_COORD_RANGE; - info.m_iAmmoType = m_iAmmoType; - } - - FireBullets( info ); - EmitSound( "NPC_CeilingTurret.ShotSounds" ); - DoMuzzleFlash(); -} - -//----------------------------------------------------------------------------- -// Purpose: Allows a generic think function before the others are called -// Input : state - which state the turret is currently in -//----------------------------------------------------------------------------- -bool CNPC_CeilingTurret::PreThink( turretState_e state ) -{ - CheckPVSCondition(); - - //Animate - StudioFrameAdvance(); - - //Do not interrupt current think function - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Sets the state of the glowing eye attached to the turret -// Input : state - state the eye should be in -//----------------------------------------------------------------------------- -void CNPC_CeilingTurret::SetEyeState( eyeState_t state ) -{ - //Must have a valid eye to affect - if ( m_pEyeGlow == NULL ) - return; - - //Set the state - switch( state ) - { - default: - case TURRET_EYE_SEE_TARGET: //Fade in and scale up - m_pEyeGlow->SetColor( 255, 0, 0 ); - m_pEyeGlow->SetBrightness( 164, 0.1f ); - m_pEyeGlow->SetScale( 0.4f, 0.1f ); - break; - - case TURRET_EYE_SEEKING_TARGET: //Ping-pongs - - //Toggle our state - m_bBlinkState = !m_bBlinkState; - m_pEyeGlow->SetColor( 255, 128, 0 ); - - if ( m_bBlinkState ) - { - //Fade up and scale up - m_pEyeGlow->SetScale( 0.25f, 0.1f ); - m_pEyeGlow->SetBrightness( 164, 0.1f ); - } - else - { - //Fade down and scale down - m_pEyeGlow->SetScale( 0.2f, 0.1f ); - m_pEyeGlow->SetBrightness( 64, 0.1f ); - } - - break; - - case TURRET_EYE_DORMANT: //Fade out and scale down - m_pEyeGlow->SetColor( 0, 255, 0 ); - m_pEyeGlow->SetScale( 0.1f, 0.5f ); - m_pEyeGlow->SetBrightness( 64, 0.5f ); - break; - - case TURRET_EYE_DEAD: //Fade out slowly - m_pEyeGlow->SetColor( 255, 0, 0 ); - m_pEyeGlow->SetScale( 0.1f, 3.0f ); - m_pEyeGlow->SetBrightness( 0, 3.0f ); - break; - - case TURRET_EYE_DISABLED: - m_pEyeGlow->SetColor( 0, 255, 0 ); - m_pEyeGlow->SetScale( 0.1f, 1.0f ); - m_pEyeGlow->SetBrightness( 0, 1.0f ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Make a pinging noise so the player knows where we are -//----------------------------------------------------------------------------- -void CNPC_CeilingTurret::Ping( void ) -{ - //See if it's time to ping again - if ( m_flPingTime > gpGlobals->curtime ) - return; - - //Ping! - EmitSound( "NPC_CeilingTurret.Ping" ); - - SetEyeState( TURRET_EYE_SEEKING_TARGET ); - - m_flPingTime = gpGlobals->curtime + CEILING_TURRET_PING_TIME; -} - -//----------------------------------------------------------------------------- -// Purpose: Toggle the turret's state -//----------------------------------------------------------------------------- -void CNPC_CeilingTurret::Toggle( void ) -{ - //Toggle the state - if ( m_bEnabled ) - { - Disable(); - } - else - { - Enable(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Enable the turret and deploy -//----------------------------------------------------------------------------- -void CNPC_CeilingTurret::Enable( void ) -{ - m_bEnabled = true; - - // if the turret is flagged as an autoactivate turret, re-enable its ability open self. - if ( m_spawnflags & SF_CEILING_TURRET_AUTOACTIVATE ) - { - m_bAutoStart = true; - } - - SetThink( &CNPC_CeilingTurret::Deploy ); - SetNextThink( gpGlobals->curtime + 0.05f ); -} - -//----------------------------------------------------------------------------- -// Purpose: Retire the turret until enabled again -//----------------------------------------------------------------------------- -void CNPC_CeilingTurret::Disable( void ) -{ - m_bEnabled = false; - m_bAutoStart = false; - - SetEnemy( NULL ); - SetThink( &CNPC_CeilingTurret::Retire ); - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -//----------------------------------------------------------------------------- -// Purpose: Toggle the turret's state via input function -//----------------------------------------------------------------------------- -void CNPC_CeilingTurret::InputToggle( inputdata_t &inputdata ) -{ - Toggle(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CeilingTurret::InputEnable( inputdata_t &inputdata ) -{ - Enable(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CeilingTurret::InputDisable( inputdata_t &inputdata ) -{ - Disable(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CeilingTurret::SpinUp( void ) -{ -} - -#define CEILING_TURRET_MIN_SPIN_DOWN 1.0f - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CeilingTurret::SpinDown( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_CeilingTurret::DeathThink( void ) -{ - if ( PreThink( TURRET_DEAD ) ) - return; - - //Level out our angles - m_vecGoalAngles = GetAbsAngles(); - SetNextThink( gpGlobals->curtime ); - - if ( m_lifeState != LIFE_DEAD ) - { - m_lifeState = LIFE_DEAD; - - EmitSound( "NPC_CeilingTurret.Die" ); - - SetActivity( (Activity) ACT_CEILING_TURRET_CLOSE ); - } - - // lots of smoke - Vector pos; - CollisionProp()->RandomPointInBounds( vec3_origin, Vector( 1, 1, 1 ), &pos ); - - CBroadcastRecipientFilter filter; - - te->Smoke( filter, 0.0, &pos, g_sModelIndexSmoke, 2.5, 10 ); - - g_pEffects->Sparks( pos ); - - if ( IsActivityFinished() && ( UpdateFacing() == false ) ) - { - SetHeight( CEILING_TURRET_RETRACT_HEIGHT ); - - m_flPlaybackRate = 0; - SetThink( NULL ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : height - -//----------------------------------------------------------------------------- -void CNPC_CeilingTurret::SetHeight( float height ) -{ - Vector forward, right, up; - AngleVectors( GetLocalAngles(), &forward, &right, &up ); - - Vector mins = ( forward * -16.0f ) + ( right * -16.0f ); - Vector maxs = ( forward * 16.0f ) + ( right * 16.0f ) + ( up * -height ); - - if ( mins.x > maxs.x ) - { - swap( mins.x, maxs.x ); - } - - if ( mins.y > maxs.y ) - { - swap( mins.y, maxs.y ); - } - - if ( mins.z > maxs.z ) - { - swap( mins.z, maxs.z ); - } - - SetCollisionBounds( mins, maxs ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEnemy - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_CeilingTurret::CanBeAnEnemyOf( CBaseEntity *pEnemy ) -{ - // If we're out of ammo, make friendly companions ignore us - if ( m_spawnflags & SF_CEILING_TURRET_OUT_OF_AMMO ) - { - if ( pEnemy->Classify() == CLASS_PLAYER_ALLY_VITAL ) - return false; - } - - return BaseClass::CanBeAnEnemyOf( pEnemy ); -} diff --git a/game/server/hl2/npc_turret_floor.cpp b/game/server/hl2/npc_turret_floor.cpp deleted file mode 100644 index 32cec8e5e..000000000 --- a/game/server/hl2/npc_turret_floor.cpp +++ /dev/null @@ -1,2330 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "npc_turret_floor.h" -#include "ai_senses.h" -#include "ai_memory.h" -#include "engine/IEngineSound.h" -#include "ammodef.h" -#include "hl2/hl2_player.h" -#include "soundenvelope.h" -#include "physics_saverestore.h" -#include "IEffects.h" -#include "basehlcombatweapon_shared.h" -#include "phys_controller.h" -#include "ai_interactions.h" -#include "Sprite.h" -#include "beam_shared.h" -#include "props.h" -#include "particle_parse.h" - -#ifdef PORTAL - #include "prop_portal_shared.h" - #include "portal_util_shared.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -const char *GetMassEquivalent(float flMass); - -#define DISABLE_SHOT 0 - -//Debug visualization -ConVar g_debug_turret( "g_debug_turret", "0" ); - -extern ConVar physcannon_tracelength; - -// Interactions -int g_interactionTurretStillStanding = 0; - -float CNPC_FloorTurret::fMaxTipControllerVelocity = 300.0f * 300.0f; -float CNPC_FloorTurret::fMaxTipControllerAngularVelocity = 90.0f * 90.0f; - -#define LASER_BEAM_SPRITE "effects/laser1.vmt" - -#define FLOOR_TURRET_MODEL "models/combine_turrets/floor_turret.mdl" -#define FLOOR_TURRET_MODEL_CITIZEN "models/combine_turrets/citizen_turret.mdl" -#define FLOOR_TURRET_GLOW_SPRITE "sprites/glow1.vmt" -// #define FLOOR_TURRET_BC_YAW "aim_yaw" -// #define FLOOR_TURRET_BC_PITCH "aim_pitch" -#define FLOOR_TURRET_RANGE 1200 -#define FLOOR_TURRET_MAX_WAIT 5 -#define FLOOR_TURRET_SHORT_WAIT 2.0 // Used for FAST_RETIRE spawnflag -#define FLOOR_TURRET_PING_TIME 1.0f //LPB!! - -#define FLOOR_TURRET_VOICE_PITCH_LOW 45 -#define FLOOR_TURRET_VOICE_PITCH_HIGH 100 - -//Aiming variables -#define FLOOR_TURRET_MAX_NOHARM_PERIOD 0.0f -#define FLOOR_TURRET_MAX_GRACE_PERIOD 3.0f - -//Activities -int ACT_FLOOR_TURRET_OPEN; -int ACT_FLOOR_TURRET_CLOSE; -int ACT_FLOOR_TURRET_OPEN_IDLE; -int ACT_FLOOR_TURRET_CLOSED_IDLE; -int ACT_FLOOR_TURRET_FIRE; - -//Datatable -BEGIN_DATADESC( CNPC_FloorTurret ) - - DEFINE_FIELD( m_iAmmoType, FIELD_INTEGER ), - DEFINE_FIELD( m_bAutoStart, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bActive, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bBlinkState, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bNoAlarmSounds, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_flShotTime, FIELD_TIME ), - DEFINE_FIELD( m_flLastSight, FIELD_TIME ), - DEFINE_FIELD( m_flThrashTime, FIELD_TIME ), - DEFINE_FIELD( m_flPingTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextActivateSoundTime, FIELD_TIME ), - DEFINE_FIELD( m_bCarriedByPlayer, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bUseCarryAngles, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flPlayerDropTime, FIELD_TIME ), - DEFINE_FIELD( m_hLastNPCToKickMe, FIELD_EHANDLE ), - DEFINE_FIELD( m_flKnockOverFailedTime, FIELD_TIME ), - DEFINE_FIELD( m_flDestructStartTime, FIELD_TIME ), - DEFINE_FIELD( m_hFizzleEffect, FIELD_EHANDLE ), - - DEFINE_FIELD( m_vecGoalAngles,FIELD_VECTOR ), - DEFINE_FIELD( m_iEyeAttachment, FIELD_INTEGER ), - DEFINE_FIELD( m_iMuzzleAttachment, FIELD_INTEGER ), - DEFINE_FIELD( m_iEyeState, FIELD_INTEGER ), - DEFINE_FIELD( m_hEyeGlow, FIELD_EHANDLE ), - DEFINE_FIELD( m_pMotionController,FIELD_EHANDLE), - DEFINE_FIELD( m_vecEnemyLKP, FIELD_VECTOR ), - DEFINE_FIELD( m_hLaser, FIELD_EHANDLE ), - DEFINE_FIELD( m_bSelfDestructing, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_hPhysicsAttacker, FIELD_EHANDLE ), - DEFINE_FIELD( m_flLastPhysicsInfluenceTime, FIELD_TIME ), - - DEFINE_FIELD( m_bHackedByAlyx, FIELD_BOOLEAN ), - - DEFINE_KEYFIELD( m_iKeySkin, FIELD_INTEGER, "SkinNumber" ), - - DEFINE_THINKFUNC( Retire ), - DEFINE_THINKFUNC( Deploy ), - DEFINE_THINKFUNC( ActiveThink ), - DEFINE_THINKFUNC( SearchThink ), - DEFINE_THINKFUNC( AutoSearchThink ), - DEFINE_THINKFUNC( TippedThink ), - DEFINE_THINKFUNC( InactiveThink ), - DEFINE_THINKFUNC( SuppressThink ), - DEFINE_THINKFUNC( DisabledThink ), - DEFINE_THINKFUNC( SelfDestructThink ), - DEFINE_THINKFUNC( BreakThink ), - - DEFINE_USEFUNC( ToggleUse ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - DEFINE_INPUTFUNC( FIELD_VOID, "DepleteAmmo", InputDepleteAmmo ), - DEFINE_INPUTFUNC( FIELD_VOID, "RestoreAmmo", InputRestoreAmmo ), - DEFINE_INPUTFUNC( FIELD_VOID, "SelfDestruct", InputSelfDestruct ), - - DEFINE_OUTPUT( m_OnDeploy, "OnDeploy" ), - DEFINE_OUTPUT( m_OnRetire, "OnRetire" ), - DEFINE_OUTPUT( m_OnTipped, "OnTipped" ), - DEFINE_OUTPUT( m_OnPhysGunPickup, "OnPhysGunPickup" ), - DEFINE_OUTPUT( m_OnPhysGunDrop, "OnPhysGunDrop" ), - - DEFINE_BASENPCINTERACTABLE_DATADESC(), - - // DEFINE_FIELD( m_ShotSounds, FIELD_SHORT ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( npc_turret_floor, CNPC_FloorTurret ); - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CNPC_FloorTurret::CNPC_FloorTurret( void ) : - m_iAmmoType( -1 ), - m_bAutoStart( false ), - m_bActive( false ), - m_bBlinkState( false ), - m_bEnabled( false ), - m_bSelfDestructing( false ), - m_flShotTime( 0.0f ), - m_flLastSight( 0.0f ), - m_flThrashTime( 0.0f ), - m_flPingTime( 0.0f ), - m_flNextActivateSoundTime( 0.0f ), - m_bCarriedByPlayer( false ), - m_bUseCarryAngles( false ), - m_flPlayerDropTime( 0.0f ), - m_hEyeGlow( NULL ), - m_hLaser( NULL ), - m_pMotionController( NULL ) -{ - m_vecGoalAngles.Init(); - - m_vecEnemyLKP = vec3_invalid; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Class_T CNPC_FloorTurret::Classify( void ) -{ - if ( m_bEnabled ) - { - // Hacked or friendly turrets don't attack players - if( m_bHackedByAlyx || IsCitizenTurret() ) - return CLASS_PLAYER_ALLY; - - return CLASS_COMBINE; - } - - return CLASS_NONE; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::UpdateOnRemove( void ) -{ - if ( m_pMotionController != NULL ) - { - UTIL_Remove( m_pMotionController ); - m_pMotionController = NULL; - } - - if ( m_hLaser != NULL ) - { - UTIL_Remove( m_hLaser ); - m_hLaser = NULL; - } - - if ( m_hEyeGlow != NULL ) - { - UTIL_Remove( m_hEyeGlow ); - m_hEyeGlow = NULL; - } - - BaseClass::UpdateOnRemove(); -} - -//----------------------------------------------------------------------------- -// Purpose: Precache -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::Precache( void ) -{ - const char *pModelName = STRING( GetModelName() ); - pModelName = ( pModelName && pModelName[ 0 ] != '\0' ) ? pModelName : FLOOR_TURRET_MODEL; - PrecacheModel( pModelName ); - PrecacheModel( FLOOR_TURRET_GLOW_SPRITE ); - - PropBreakablePrecacheAll( MAKE_STRING( pModelName ) ); - - if ( IsCitizenTurret() ) - { - PrecacheModel( LASER_BEAM_SPRITE ); - PrecacheScriptSound( "NPC_FloorTurret.AlarmPing"); - } - - // Activities - ADD_CUSTOM_ACTIVITY( CNPC_FloorTurret, ACT_FLOOR_TURRET_OPEN ); - ADD_CUSTOM_ACTIVITY( CNPC_FloorTurret, ACT_FLOOR_TURRET_CLOSE ); - ADD_CUSTOM_ACTIVITY( CNPC_FloorTurret, ACT_FLOOR_TURRET_CLOSED_IDLE ); - ADD_CUSTOM_ACTIVITY( CNPC_FloorTurret, ACT_FLOOR_TURRET_OPEN_IDLE ); - ADD_CUSTOM_ACTIVITY( CNPC_FloorTurret, ACT_FLOOR_TURRET_FIRE ); - - PrecacheScriptSound( "NPC_FloorTurret.Retire" ); - PrecacheScriptSound( "NPC_FloorTurret.Deploy" ); - PrecacheScriptSound( "NPC_FloorTurret.Move" ); - PrecacheScriptSound( "NPC_Combine.WeaponBash" ); - PrecacheScriptSound( "NPC_FloorTurret.Activate" ); - PrecacheScriptSound( "NPC_FloorTurret.Alert" ); - m_ShotSounds = PrecacheScriptSound( "NPC_FloorTurret.ShotSounds" ); - PrecacheScriptSound( "NPC_FloorTurret.Die" ); - PrecacheScriptSound( "NPC_FloorTurret.Retract"); - PrecacheScriptSound( "NPC_FloorTurret.Alarm"); - PrecacheScriptSound( "NPC_FloorTurret.Ping"); - PrecacheScriptSound( "NPC_FloorTurret.DryFire"); - PrecacheScriptSound( "NPC_FloorTurret.Destruct" ); - -#ifdef HL2_EPISODIC - PrecacheParticleSystem( "explosion_turret_break" ); -#endif // HL2_EPISODIC - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: Spawn the entity -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::Spawn( void ) -{ - Precache(); - - const char *pModelName = STRING( GetModelName() ); - SetModel( ( pModelName && pModelName[ 0 ] != '\0' ) ? pModelName : FLOOR_TURRET_MODEL ); - - // If we're a citizen turret, we use a different skin - if ( IsCitizenTurret() ) - { - if (m_iKeySkin == 0) - { // select a "random" skin -- rather than being truly random, use a static variable - // to cycle through them evenly. The static won't be saved across save/load, but - // frankly I don't care so much about that. - // m_nSkin = random->RandomInt( 1, 4 ); - static unsigned int nextSkin = 0; - m_nSkin = nextSkin + 1; - - // add one mod 4 - nextSkin = (nextSkin + 1) & 0x03; - } - else - { // at least make sure that it's in the right range - m_nSkin = clamp(m_iKeySkin,1,4); - } - } - - BaseClass::Spawn(); - - SetBlocksLOS( false ); - - m_HackedGunPos = Vector( 0, 0, 12.75 ); - SetViewOffset( EyeOffset( ACT_IDLE ) ); - m_flFieldOfView = 0.4f; // 60 degrees - m_takedamage = DAMAGE_EVENTS_ONLY; - m_iHealth = 100; - m_iMaxHealth = 100; - - AddEFlags( EFL_NO_DISSOLVE ); - - SetPoseParameter( m_poseAim_Yaw, 0 ); - SetPoseParameter( m_poseAim_Pitch, 0 ); - - m_iAmmoType = GetAmmoDef()->Index( "PISTOL" ); - - m_iMuzzleAttachment = LookupAttachment( "eyes" ); - m_iEyeAttachment = LookupAttachment( "light" ); - - // FIXME: Do we ever need m_bAutoStart? (Sawyer) - m_spawnflags |= SF_FLOOR_TURRET_AUTOACTIVATE; - - //Set our autostart state - m_bAutoStart = !!( m_spawnflags & SF_FLOOR_TURRET_AUTOACTIVATE ); - m_bEnabled = ( ( m_spawnflags & SF_FLOOR_TURRET_STARTINACTIVE ) == false ); - - //Do we start active? - if ( m_bAutoStart && m_bEnabled ) - { - SetThink( &CNPC_FloorTurret::AutoSearchThink ); - SetEyeState( TURRET_EYE_DORMANT ); - } - else - { - SetThink( &CNPC_FloorTurret::DisabledThink ); - SetEyeState( TURRET_EYE_DISABLED ); - } - - // Start - if ( OnSide() ) - { - SetThink( &CNPC_FloorTurret::DisabledThink ); - SetEyeState( TURRET_EYE_DISABLED ); - } - - //Stagger our starting times - SetNextThink( gpGlobals->curtime + random->RandomFloat( 0.1f, 0.3f ) ); - - SetUse( &CNPC_FloorTurret::ToggleUse ); - - // Don't allow us to skip animation setup because our attachments are critical to us! - SetBoneCacheFlags( BCF_NO_ANIMATION_SKIP ); - - CreateVPhysics(); - - SetState(NPC_STATE_IDLE); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::Activate( void ) -{ - BaseClass::Activate(); - - // Force the eye state to the current state so that our glows are recreated after transitions - SetEyeState( m_iEyeState ); - - if ( !m_pMotionController ) - { - // Create the motion controller - m_pMotionController = CTurretTipController::CreateTipController( this ); - - // Enable the controller - if ( m_pMotionController != NULL ) - { - m_pMotionController->Enable(); - } - } -} - -//----------------------------------------------------------------------------- - -bool CNPC_FloorTurret::CreateVPhysics( void ) -{ - //Spawn our physics hull - if ( VPhysicsInitNormal( SOLID_VPHYSICS, 0, false ) == NULL ) - { - DevMsg( "npc_turret_floor unable to spawn physics object!\n" ); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Retract and stop attacking -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::Retire( void ) -{ - if ( PreThink( TURRET_RETIRING ) ) - return; - - //Level out the turret - m_vecGoalAngles = GetAbsAngles(); - SetNextThink( gpGlobals->curtime + 0.05f ); - - //Set ourselves to close - if ( GetActivity() != ACT_FLOOR_TURRET_CLOSE ) - { - //Set our visible state to dormant - SetEyeState( TURRET_EYE_DORMANT ); - - SetActivity( (Activity) ACT_FLOOR_TURRET_OPEN_IDLE ); - - //If we're done moving to our desired facing, close up - if ( UpdateFacing() == false ) - { - SetActivity( (Activity) ACT_FLOOR_TURRET_CLOSE ); - EmitSound( "NPC_FloorTurret.Retire" ); - - //Notify of the retraction - m_OnRetire.FireOutput( NULL, this ); - } - } - else if ( IsActivityFinished() ) - { - m_bActive = false; - m_flLastSight = 0; - - SetActivity( (Activity) ACT_FLOOR_TURRET_CLOSED_IDLE ); - - //Go back to auto searching - if ( m_bAutoStart ) - { - SetThink( &CNPC_FloorTurret::AutoSearchThink ); - SetNextThink( gpGlobals->curtime + 0.05f ); - } - else - { - //Set our visible state to dormant - SetEyeState( TURRET_EYE_DISABLED ); - SetThink( &CNPC_FloorTurret::DisabledThink ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Deploy and start attacking -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::Deploy( void ) -{ - if ( PreThink( TURRET_DEPLOYING ) ) - return; - - m_vecGoalAngles = GetAbsAngles(); - - SetNextThink( gpGlobals->curtime + 0.05f ); - - //Show we've seen a target - SetEyeState( TURRET_EYE_SEE_TARGET ); - - //Open if we're not already - if ( GetActivity() != ACT_FLOOR_TURRET_OPEN ) - { - m_bActive = true; - SetActivity( (Activity) ACT_FLOOR_TURRET_OPEN ); - EmitSound( "NPC_FloorTurret.Deploy" ); - - //Notify we're deploying - m_OnDeploy.FireOutput( NULL, this ); - } - - //If we're done, then start searching - if ( IsActivityFinished() ) - { - SetActivity( (Activity) ACT_FLOOR_TURRET_OPEN_IDLE ); - - m_flShotTime = gpGlobals->curtime + 1.0f; - - m_flPlaybackRate = 0; - SetThink( &CNPC_FloorTurret::SearchThink ); - - EmitSound( "NPC_FloorTurret.Move" ); - } - - m_flLastSight = gpGlobals->curtime + FLOOR_TURRET_MAX_WAIT; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) -{ - m_hPhysicsAttacker = pPhysGunUser; - m_flLastPhysicsInfluenceTime = gpGlobals->curtime; - - // Drop our mass a lot so that we can be moved easily with +USE - if ( reason != PUNTED_BY_CANNON ) - { - Assert( VPhysicsGetObject() ); - - m_bCarriedByPlayer = true; - m_OnPhysGunPickup.FireOutput( this, this ); - - // We want to use preferred carry angles if we're not nicely upright - Vector vecToTurret = pPhysGunUser->GetAbsOrigin() - GetAbsOrigin(); - vecToTurret.z = 0; - VectorNormalize( vecToTurret ); - - // We want to use preferred carry angles if we're not nicely upright - Vector forward, up; - GetVectors( &forward, NULL, &up ); - - bool bUpright = DotProduct( up, Vector(0,0,1) ) > 0.9f; - bool bBehind = DotProduct( vecToTurret, forward ) < 0.85f; - - // Correct our angles only if we're not upright or we're mostly behind the turret - if ( hl2_episodic.GetBool() ) - { - m_bUseCarryAngles = ( bUpright == false || bBehind ); - } - else - { - m_bUseCarryAngles = ( bUpright == false ); - } - } - - // Clear out our last NPC to kick me, because it makes no sense now - m_hLastNPCToKickMe = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ) -{ - m_hPhysicsAttacker = pPhysGunUser; - m_flLastPhysicsInfluenceTime = gpGlobals->curtime; - - m_bCarriedByPlayer = false; - m_bUseCarryAngles = false; - m_OnPhysGunDrop.FireOutput( this, this ); - - // If this is a friendly turret, remember that it was just dropped - if ( IRelationType( pPhysGunUser ) != D_HT ) - { - m_flPlayerDropTime = gpGlobals->curtime + 2.0; - } - - // Restore our mass to the original value - Assert( VPhysicsGetObject() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Whether this should return carry angles -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_FloorTurret::HasPreferredCarryAnglesForPlayer( CBasePlayer *pPlayer ) -{ - // Don't use preferred angles on enemy turrets - if ( IRelationType( pPlayer ) == D_HT ) - return false; - - return m_bUseCarryAngles; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_FloorTurret::OnAttemptPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) -{ - // Prevent players pulling enemy turrets from afar if they're in front of the turret - if ( reason == PICKED_UP_BY_CANNON && IRelationType( pPhysGunUser ) == D_HT ) - { - Vector vecForward; - GetVectors( &vecForward, NULL, NULL ); - Vector vecForce = (pPhysGunUser->GetAbsOrigin() - GetAbsOrigin()); - float flDistance = VectorNormalize( vecForce ); - - // If it's over the physcannon tracelength, we're pulling it - if ( flDistance > physcannon_tracelength.GetFloat() ) - { - float flDot = DotProduct( vecForward, vecForce ); - if ( flDot > 0.5 ) - return false; - } - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_FloorTurret::HandleInteraction(int interactionType, void *data, CBaseCombatCharacter *sourceEnt) -{ - if ( interactionType == g_interactionCombineBash ) - { - // We've been bashed by a combine soldier. Remember who it was, if we haven't got an active kicker - if ( !m_hLastNPCToKickMe ) - { - m_hLastNPCToKickMe = sourceEnt; - m_flKnockOverFailedTime = gpGlobals->curtime + 3.0; - } - - // Get knocked away - Vector forward, up; - AngleVectors( sourceEnt->GetLocalAngles(), &forward, NULL, &up ); - ApplyAbsVelocityImpulse( forward * 100 + up * 50 ); - CTakeDamageInfo info( sourceEnt, sourceEnt, 30, DMG_CLUB ); - CalculateMeleeDamageForce( &info, forward, GetAbsOrigin() ); - TakeDamage( info ); - - EmitSound( "NPC_Combine.WeaponBash" ); - return true; - } - - return BaseClass::HandleInteraction( interactionType, data, sourceEnt ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the speed at which the turret can face a target -//----------------------------------------------------------------------------- -float CNPC_FloorTurret::MaxYawSpeed( void ) -{ - //TODO: Scale by difficulty? - return 360.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if this turret was recently dropped by a player -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_FloorTurret::WasJustDroppedByPlayer( void ) -{ - if ( m_flPlayerDropTime > gpGlobals->curtime ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Causes the turret to face its desired angles -//----------------------------------------------------------------------------- -bool CNPC_FloorTurret::UpdateFacing( void ) -{ - bool bMoved = false; - UpdateMuzzleMatrix(); - - Vector vecGoalDir; - AngleVectors( m_vecGoalAngles, &vecGoalDir ); - - Vector vecGoalLocalDir; - VectorIRotate( vecGoalDir, m_muzzleToWorld, vecGoalLocalDir ); - - if ( g_debug_turret.GetBool() ) - { - Vector vecMuzzle, vecMuzzleDir; - - MatrixGetColumn( m_muzzleToWorld, 3, vecMuzzle ); - MatrixGetColumn( m_muzzleToWorld, 0, vecMuzzleDir ); - - NDebugOverlay::Cross3D( vecMuzzle, -Vector(2,2,2), Vector(2,2,2), 255, 255, 0, false, 0.05 ); - NDebugOverlay::Cross3D( vecMuzzle+(vecMuzzleDir*256), -Vector(2,2,2), Vector(2,2,2), 255, 255, 0, false, 0.05 ); - NDebugOverlay::Line( vecMuzzle, vecMuzzle+(vecMuzzleDir*256), 255, 255, 0, false, 0.05 ); - - NDebugOverlay::Cross3D( vecMuzzle, -Vector(2,2,2), Vector(2,2,2), 255, 0, 0, false, 0.05 ); - NDebugOverlay::Cross3D( vecMuzzle+(vecGoalDir*256), -Vector(2,2,2), Vector(2,2,2), 255, 0, 0, false, 0.05 ); - NDebugOverlay::Line( vecMuzzle, vecMuzzle+(vecGoalDir*256), 255, 0, 0, false, 0.05 ); - } - - QAngle vecGoalLocalAngles; - VectorAngles( vecGoalLocalDir, vecGoalLocalAngles ); - - // Update pitch - float flDiff = AngleNormalize( UTIL_ApproachAngle( vecGoalLocalAngles.x, 0.0, 0.05f * MaxYawSpeed() ) ); - - SetPoseParameter( m_poseAim_Pitch, GetPoseParameter( m_poseAim_Pitch ) + ( flDiff / 1.5f ) ); - - if ( fabs( flDiff ) > 0.1f ) - { - bMoved = true; - } - - // Update yaw - flDiff = AngleNormalize( UTIL_ApproachAngle( vecGoalLocalAngles.y, 0.0, 0.05f * MaxYawSpeed() ) ); - - SetPoseParameter( m_poseAim_Yaw, GetPoseParameter( m_poseAim_Yaw ) + ( flDiff / 1.5f ) ); - - if ( fabs( flDiff ) > 0.1f ) - { - bMoved = true; - } - - // You're going to make decisions based on this info. So bump the bone cache after you calculate everything - InvalidateBoneCache(); - - return bMoved; -} - -void CNPC_FloorTurret::DryFire( void ) -{ - EmitSound( "NPC_FloorTurret.DryFire"); - EmitSound( "NPC_FloorTurret.Activate" ); - - if ( RandomFloat( 0, 1 ) > 0.5 ) - { - m_flShotTime = gpGlobals->curtime + random->RandomFloat( 1, 2.5 ); - } - else - { - m_flShotTime = gpGlobals->curtime; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Turret will continue to fire on a target's position when it loses sight of it -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::SuppressThink( void ) -{ - //Allow descended classes a chance to do something before the think function - if ( PreThink( TURRET_SUPPRESSING ) ) - return; - - //Update our think time - SetNextThink( gpGlobals->curtime + 0.1f ); - - // Look for a new enemy - HackFindEnemy(); - - //If we've acquired an enemy, start firing at it - if ( !GetEnemy() ) - { - SetThink( &CNPC_FloorTurret::ActiveThink ); - return; - } - - //See if we're done suppressing - if ( gpGlobals->curtime > m_flLastSight ) - { - // Should we look for a new target? - ClearEnemyMemory(); - SetEnemy( NULL ); - SetThink( &CNPC_FloorTurret::SearchThink ); - m_vecGoalAngles = GetAbsAngles(); - - SpinDown(); - - if ( m_spawnflags & SF_FLOOR_TURRET_FASTRETIRE ) - { - // Retire quickly in this case. (The case where we saw the player, but he hid again). - m_flLastSight = gpGlobals->curtime + FLOOR_TURRET_SHORT_WAIT; - } - else - { - m_flLastSight = gpGlobals->curtime + FLOOR_TURRET_MAX_WAIT; - } - - return; - } - - //Get our shot positions - Vector vecMid = EyePosition(); - Vector vecMidEnemy = m_vecEnemyLKP; - - //Calculate dir and dist to enemy - Vector vecDirToEnemy = vecMidEnemy - vecMid; - - //We want to look at the enemy's eyes so we don't jitter - Vector vecDirToEnemyEyes = vecMidEnemy - vecMid; - VectorNormalize( vecDirToEnemyEyes ); - - QAngle vecAnglesToEnemy; - VectorAngles( vecDirToEnemyEyes, vecAnglesToEnemy ); - - //Draw debug info - if ( g_debug_turret.GetBool() ) - { - NDebugOverlay::Cross3D( vecMid, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 ); - NDebugOverlay::Cross3D( vecMidEnemy, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 ); - NDebugOverlay::Line( vecMid, vecMidEnemy, 0, 255, 0, false, 0.05f ); - } - - if ( m_flShotTime < gpGlobals->curtime && m_vecEnemyLKP != vec3_invalid ) - { - Vector vecMuzzle, vecMuzzleDir; - UpdateMuzzleMatrix(); - MatrixGetColumn( m_muzzleToWorld, 0, vecMuzzleDir ); - MatrixGetColumn( m_muzzleToWorld, 3, vecMuzzle ); - - //Fire the gun - if ( DotProduct( vecDirToEnemy, vecMuzzleDir ) >= 0.9848 ) // 10 degree slop - { - if( m_spawnflags & SF_FLOOR_TURRET_OUT_OF_AMMO ) - { - DryFire(); - } - else - { - ResetActivity(); - SetActivity( (Activity) ACT_FLOOR_TURRET_FIRE ); - - //Fire the weapon -#if !DISABLE_SHOT - Shoot( vecMuzzle, vecMuzzleDir ); -#endif - } - } - } - else - { - SetActivity( (Activity) ACT_FLOOR_TURRET_OPEN_IDLE ); - } - - //If we can see our enemy, face it - m_vecGoalAngles.y = vecAnglesToEnemy.y; - m_vecGoalAngles.x = vecAnglesToEnemy.x; - - //Turn to face - UpdateFacing(); -} - -//----------------------------------------------------------------------------- -// Purpose: Allows the turret to fire on targets if they're visible -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::ActiveThink( void ) -{ - //Allow descended classes a chance to do something before the think function - if ( PreThink( TURRET_ACTIVE ) ) - return; - - HackFindEnemy(); - - //Update our think time - SetNextThink( gpGlobals->curtime + 0.1f ); - - //If we've become inactive, go back to searching - if ( ( m_bActive == false ) || ( GetEnemy() == NULL ) ) - { - SetEnemy( NULL ); - m_flLastSight = gpGlobals->curtime + FLOOR_TURRET_MAX_WAIT; - SetThink( &CNPC_FloorTurret::SearchThink ); - m_vecGoalAngles = GetAbsAngles(); - return; - } - - //Get our shot positions - Vector vecMid = EyePosition(); - Vector vecMidEnemy = GetEnemy()->BodyTarget( vecMid ); - - // Store off our last seen location so we can suppress it later - m_vecEnemyLKP = vecMidEnemy; - - //Look for our current enemy - bool bEnemyInFOV = FInViewCone( GetEnemy() ); - bool bEnemyVisible = FVisible( GetEnemy() ) && GetEnemy()->IsAlive(); - - // Robin: This is a hack to get around the fact that the muzzle for the turret - // is outside it's vcollide. This means that if it leans against a thin wall, - // the muzzle can be on the other side of the wall, where it's then able to see - // and shoot at targets. This check ensures that nothing has come between the - // center of the turret and the muzzle. - if ( bEnemyVisible ) - { - trace_t tr; - Vector vecCenter; - CollisionProp()->CollisionToWorldSpace( Vector(0,0,52), &vecCenter ); - UTIL_TraceLine( vecCenter, vecMid, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction != 1.0 ) - { - bEnemyVisible = false; - } - } - - //Calculate dir and dist to enemy - Vector vecDirToEnemy = vecMidEnemy - vecMid; - float flDistToEnemy = VectorNormalize( vecDirToEnemy ); - - //Draw debug info - if ( g_debug_turret.GetBool() ) - { - NDebugOverlay::Cross3D( vecMid, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 ); - NDebugOverlay::Cross3D( GetEnemy()->WorldSpaceCenter(), -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 ); - NDebugOverlay::Line( vecMid, GetEnemy()->WorldSpaceCenter(), 0, 255, 0, false, 0.05 ); - - NDebugOverlay::Cross3D( vecMid, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 ); - NDebugOverlay::Cross3D( vecMidEnemy, -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 0.05 ); - NDebugOverlay::Line( vecMid, vecMidEnemy, 0, 255, 0, false, 0.05f ); - } - - //See if they're past our FOV of attack - if ( bEnemyInFOV == false ) - { - // Should we look for a new target? - ClearEnemyMemory(); - SetEnemy( NULL ); - - if ( m_spawnflags & SF_FLOOR_TURRET_FASTRETIRE ) - { - // Retire quickly in this case. (The case where we saw the player, but he hid again). - m_flLastSight = gpGlobals->curtime + FLOOR_TURRET_SHORT_WAIT; - } - else - { - m_flLastSight = gpGlobals->curtime + FLOOR_TURRET_MAX_WAIT; - } - - SetThink( &CNPC_FloorTurret::SearchThink ); - m_vecGoalAngles = GetAbsAngles(); - - SpinDown(); - - return; - } - - //Current enemy is not visible - if ( ( bEnemyVisible == false ) || ( flDistToEnemy > FLOOR_TURRET_RANGE )) - { - m_flLastSight = gpGlobals->curtime + 2.0f; - - ClearEnemyMemory(); - SetEnemy( NULL ); - SetThink( &CNPC_FloorTurret::SuppressThink ); - - return; - } - - if ( g_debug_turret.GetBool() ) - { - Vector vecMuzzle, vecMuzzleDir; - - UpdateMuzzleMatrix(); - MatrixGetColumn( m_muzzleToWorld, 0, vecMuzzleDir ); - MatrixGetColumn( m_muzzleToWorld, 3, vecMuzzle ); - - // Visualize vertical firing ranges - for ( int i = 0; i < 4; i++ ) - { - QAngle angMaxDownPitch = GetAbsAngles(); - - switch( i ) - { - case 0: angMaxDownPitch.x -= 15; break; - case 1: angMaxDownPitch.x += 15; break; - case 2: angMaxDownPitch.x -= 25; break; - case 3: angMaxDownPitch.x += 25; break; - default: - break; - } - - Vector vecMaxDownPitch; - AngleVectors( angMaxDownPitch, &vecMaxDownPitch ); - NDebugOverlay::Line( vecMuzzle, vecMuzzle + (vecMaxDownPitch*256), 255, 255, 255, false, 0.1 ); - } - } - - if ( m_flShotTime < gpGlobals->curtime ) - { - Vector vecMuzzle, vecMuzzleDir; - - UpdateMuzzleMatrix(); - MatrixGetColumn( m_muzzleToWorld, 0, vecMuzzleDir ); - MatrixGetColumn( m_muzzleToWorld, 3, vecMuzzle ); - - Vector2D vecDirToEnemy2D = vecDirToEnemy.AsVector2D(); - Vector2D vecMuzzleDir2D = vecMuzzleDir.AsVector2D(); - - bool bCanShoot = true; - float minCos3d = DOT_10DEGREE; // 10 degrees slop - - if ( flDistToEnemy < 60.0 ) - { - vecDirToEnemy2D.NormalizeInPlace(); - vecMuzzleDir2D.NormalizeInPlace(); - - bCanShoot = ( vecDirToEnemy2D.Dot(vecMuzzleDir2D) >= DOT_10DEGREE ); - minCos3d = 0.7071; // 45 degrees - } - - //Fire the gun - if ( bCanShoot ) // 10 degree slop XY - { - float dot3d = DotProduct( vecDirToEnemy, vecMuzzleDir ); - - if( m_spawnflags & SF_FLOOR_TURRET_OUT_OF_AMMO ) - { - DryFire(); - } - else - { - if ( dot3d >= minCos3d ) - { - ResetActivity(); - SetActivity( (Activity) ACT_FLOOR_TURRET_FIRE ); - - //Fire the weapon -#if !DISABLE_SHOT - Shoot( vecMuzzle, vecMuzzleDir, (dot3d < DOT_10DEGREE) ); -#endif - } - } - } - } - else - { - SetActivity( (Activity) ACT_FLOOR_TURRET_OPEN_IDLE ); - } - - //If we can see our enemy, face it - if ( bEnemyVisible ) - { - //We want to look at the enemy's eyes so we don't jitter - Vector vecDirToEnemyEyes = GetEnemy()->WorldSpaceCenter() - vecMid; - VectorNormalize( vecDirToEnemyEyes ); - - QAngle vecAnglesToEnemy; - VectorAngles( vecDirToEnemyEyes, vecAnglesToEnemy ); - - m_vecGoalAngles.y = vecAnglesToEnemy.y; - m_vecGoalAngles.x = vecAnglesToEnemy.x; - } - - //Turn to face - UpdateFacing(); -} - -//----------------------------------------------------------------------------- -// Purpose: Target doesn't exist or has eluded us, so search for one -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::SearchThink( void ) -{ - //Allow descended classes a chance to do something before the think function - if ( PreThink( TURRET_SEARCHING ) ) - return; - - SetNextThink( gpGlobals->curtime + 0.05f ); - - SetActivity( (Activity) ACT_FLOOR_TURRET_OPEN_IDLE ); - - //If our enemy has died, pick a new enemy - if ( ( GetEnemy() != NULL ) && ( GetEnemy()->IsAlive() == false ) ) - { - SetEnemy( NULL ); - } - - //Acquire the target - if ( GetEnemy() == NULL ) - { - HackFindEnemy(); - } - - //If we've found a target, spin up the barrel and start to attack - if ( GetEnemy() != NULL ) - { - //Give players a grace period - if ( GetEnemy()->IsPlayer() ) - { - m_flShotTime = gpGlobals->curtime + 0.5f; - } - else - { - m_flShotTime = gpGlobals->curtime + 0.1f; - } - - m_flLastSight = 0; - SetThink( &CNPC_FloorTurret::ActiveThink ); - SetEyeState( TURRET_EYE_SEE_TARGET ); - - SpinUp(); - - if ( gpGlobals->curtime > m_flNextActivateSoundTime ) - { - EmitSound( "NPC_FloorTurret.Activate" ); - m_flNextActivateSoundTime = gpGlobals->curtime + 3.0; - } - return; - } - - //Are we out of time and need to retract? - if ( gpGlobals->curtime > m_flLastSight ) - { - //Before we retrace, make sure that we are spun down. - m_flLastSight = 0; - SetThink( &CNPC_FloorTurret::Retire ); - return; - } - - //Display that we're scanning - m_vecGoalAngles.x = GetAbsAngles().x + ( sin( gpGlobals->curtime * 1.0f ) * 15.0f ); - m_vecGoalAngles.y = GetAbsAngles().y + ( sin( gpGlobals->curtime * 2.0f ) * 60.0f ); - - //Turn and ping - UpdateFacing(); - Ping(); -} - -//----------------------------------------------------------------------------- -// Purpose: Watch for a target to wander into our view -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::AutoSearchThink( void ) -{ - //Allow descended classes a chance to do something before the think function - if ( PreThink( TURRET_AUTO_SEARCHING ) ) - return; - - //Spread out our thinking - SetNextThink( gpGlobals->curtime + random->RandomFloat( 0.2f, 0.4f ) ); - - //If the enemy is dead, find a new one - if ( ( GetEnemy() != NULL ) && ( GetEnemy()->IsAlive() == false ) ) - { - SetEnemy( NULL ); - } - - //Acquire Target - if ( GetEnemy() == NULL ) - { - HackFindEnemy(); - } - - //Deploy if we've got an active target - if ( GetEnemy() != NULL ) - { - SetThink( &CNPC_FloorTurret::Deploy ); - if ( !m_bNoAlarmSounds ) - { - EmitSound( "NPC_FloorTurret.Alert" ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Fire! -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::Shoot( const Vector &vecSrc, const Vector &vecDirToEnemy, bool bStrict ) -{ - FireBulletsInfo_t info; - - if ( !bStrict && GetEnemy() != NULL ) - { - Vector vecDir = GetActualShootTrajectory( vecSrc ); - - info.m_vecSrc = vecSrc; - info.m_vecDirShooting = vecDir; - info.m_iTracerFreq = 1; - info.m_iShots = 1; - info.m_pAttacker = this; - info.m_vecSpread = VECTOR_CONE_PRECALCULATED; - info.m_flDistance = MAX_COORD_RANGE; - info.m_iAmmoType = m_iAmmoType; - } - else - { - info.m_vecSrc = vecSrc; - info.m_vecDirShooting = vecDirToEnemy; - info.m_iTracerFreq = 1; - info.m_iShots = 1; - info.m_pAttacker = this; - info.m_vecSpread = GetAttackSpread( NULL, GetEnemy() ); - info.m_flDistance = MAX_COORD_RANGE; - info.m_iAmmoType = m_iAmmoType; - } - - FireBullets( info ); - EmitSound( "NPC_FloorTurret.ShotSounds", m_ShotSounds ); - DoMuzzleFlash(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEnemy - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_FloorTurret::IsValidEnemy( CBaseEntity *pEnemy ) -{ - if ( m_NPCState == NPC_STATE_DEAD ) - return false; - - // Don't shoot at other turrets. - if ( pEnemy->m_iClassname == m_iClassname ) - return false; - - // If our eye is stuck in something, don't shoot - if ( UTIL_PointContents(EyePosition()) & MASK_SHOT ) - return false; - - // Turrets have limited vertical aim capability - // - Can only aim +-15 degrees, + the 10 degree slop they're allowed. - Vector vEnemyPos = pEnemy->EyePosition(); - -#ifdef PORTAL - if ( !FInViewCone( pEnemy ) || !FVisible( pEnemy ) ) - { - CProp_Portal *pPortal = FInViewConeThroughPortal( pEnemy ); - - if ( pPortal ) - { - // Translate our target across the portal - UTIL_Portal_PointTransform( pPortal->m_hLinkedPortal->MatrixThisToLinked(), vEnemyPos, vEnemyPos ); - } - } -#endif - - Vector los = ( vEnemyPos - EyePosition() ); - - QAngle angleToTarget; - VectorAngles( los, angleToTarget ); - float flZDiff = fabs( AngleNormalize( angleToTarget.x - GetAbsAngles().x) ); - if ( flZDiff > 28.0f && los.LengthSqr() > 4096.0f ) - return false; - - return BaseClass::IsValidEnemy( pEnemy ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEnemy - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_FloorTurret::CanBeAnEnemyOf( CBaseEntity *pEnemy ) -{ - // If we're out of ammo, make friendly companions ignore us - if ( m_spawnflags & SF_FLOOR_TURRET_OUT_OF_AMMO ) - { - if ( pEnemy->Classify() == CLASS_PLAYER_ALLY_VITAL ) - return false; - } - - // If we're on the side, we're never anyone's enemy - if ( OnSide() ) - return false; - - return BaseClass::CanBeAnEnemyOf( pEnemy ); -} - -//----------------------------------------------------------------------------- -// Purpose: The turret has been tipped over and will thrash for awhile -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::TippedThink( void ) -{ - // Update our PVS state - CheckPVSCondition(); - - //Animate - StudioFrameAdvance(); - - SetNextThink( gpGlobals->curtime + 0.05f ); - SetEnemy( NULL ); - - // If we're not on side anymore, stop thrashing - if ( !OnSide() ) - { - ReturnToLife(); - return; - } - - //See if we should continue to thrash - if ( gpGlobals->curtime < m_flThrashTime ) - { - if ( m_flShotTime < gpGlobals->curtime ) - { - if( m_spawnflags & SF_FLOOR_TURRET_OUT_OF_AMMO ) - { - DryFire(); - } - else if ( IsCitizenTurret() == false ) // Citizen turrets don't wildly fire - { - Vector vecMuzzle, vecMuzzleDir; - UpdateMuzzleMatrix(); - MatrixGetColumn( m_muzzleToWorld, 0, vecMuzzleDir ); - MatrixGetColumn( m_muzzleToWorld, 3, vecMuzzle ); - - ResetActivity(); - SetActivity( (Activity) ACT_FLOOR_TURRET_FIRE ); - -#if !DISABLE_SHOT - Shoot( vecMuzzle, vecMuzzleDir ); -#endif - } - - m_flShotTime = gpGlobals->curtime + 0.05f; - } - - m_vecGoalAngles.x = GetAbsAngles().x + random->RandomFloat( -60, 60 ); - m_vecGoalAngles.y = GetAbsAngles().y + random->RandomFloat( -60, 60 ); - - UpdateFacing(); - } - else - { - //Face forward - m_vecGoalAngles = GetAbsAngles(); - - //Set ourselves to close - if ( GetActivity() != ACT_FLOOR_TURRET_CLOSE ) - { - SetActivity( (Activity) ACT_FLOOR_TURRET_OPEN_IDLE ); - - //If we're done moving to our desired facing, close up - if ( UpdateFacing() == false ) - { - //Make any last death noises and anims - EmitSound( "NPC_FloorTurret.Die" ); - SpinDown(); - - SetActivity( (Activity) ACT_FLOOR_TURRET_CLOSE ); - EmitSound( "NPC_FloorTurret.Retract" ); - - CTakeDamageInfo info; - info.SetDamage( 1 ); - info.SetDamageType( DMG_CRUSH ); - Event_Killed( info ); - } - } - else if ( IsActivityFinished() ) - { - m_bActive = false; - m_flLastSight = 0; - - SetActivity( (Activity) ACT_FLOOR_TURRET_CLOSED_IDLE ); - - // Don't need to store last NPC anymore, because I've been knocked over - if ( m_hLastNPCToKickMe ) - { - m_hLastNPCToKickMe = NULL; - m_flKnockOverFailedTime = 0; - } - - //Try to look straight - if ( UpdateFacing() == false ) - { - m_OnTipped.FireOutput( this, this ); - SetEyeState( TURRET_EYE_DEAD ); - SetCollisionGroup( COLLISION_GROUP_DEBRIS_TRIGGER ); - - // Start thinking slowly to see if we're ever set upright somehow - SetThink( &CNPC_FloorTurret::InactiveThink ); - SetNextThink( gpGlobals->curtime + 1.0f ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: This turret is dead. See if it ever becomes upright again, and if -// so, become active again. -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::InactiveThink( void ) -{ - // Update our PVS state - CheckPVSCondition(); - - // Wake up if we're not on our side - if ( !OnSide() && m_bEnabled ) - { - ReturnToLife(); - return; - } - - if ( IsCitizenTurret() ) - { - // Blink if we have ammo or our current blink is "on" and we need to turn it off again - if ( HasSpawnFlags( SF_FLOOR_TURRET_OUT_OF_AMMO ) == false || m_bBlinkState ) - { - // If we're on our side, ping and complain to the player - if ( m_bBlinkState == false ) - { - // Ping when the light is going to come back on - EmitSound( "NPC_FloorTurret.AlarmPing" ); - } - - SetEyeState( TURRET_EYE_ALARM ); - SetNextThink( gpGlobals->curtime + 0.25f ); - } - } - else - { - SetNextThink( gpGlobals->curtime + 1.0f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::ReturnToLife( void ) -{ - m_flThrashTime = 0; - - // Enable the tip controller - m_pMotionController->Enable( true ); - - // Return to life - SetState( NPC_STATE_IDLE ); - m_lifeState = LIFE_ALIVE; - SetCollisionGroup( COLLISION_GROUP_NONE ); - - // Become active again - Enable(); -} - -//----------------------------------------------------------------------------- -// Purpose: The turret is not doing anything at all -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::DisabledThink( void ) -{ - SetNextThink( gpGlobals->curtime + 0.5 ); - if ( OnSide() ) - { - m_OnTipped.FireOutput( this, this ); - SetEyeState( TURRET_EYE_DEAD ); - SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - SetThink( NULL ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: The turret doesn't run base AI properly, which is a bad decision. -// As a result, it has to manually find enemies. -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::HackFindEnemy( void ) -{ - // We have to refresh our memories before finding enemies, so - // dead enemies are cleared out before new ones are added. - GetEnemies()->RefreshMemories(); - - GetSenses()->Look( FLOOR_TURRET_RANGE ); - SetEnemy( BestEnemy() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Determines whether the turret is upright enough to function -// Output : Returns true if the turret is tipped over -//----------------------------------------------------------------------------- -inline bool CNPC_FloorTurret::OnSide( void ) -{ - Vector up; - GetVectors( NULL, NULL, &up ); - - return ( DotProduct( up, Vector(0,0,1) ) < 0.5f ); -} - -//----------------------------------------------------------------------------- -// Purpose: Allows a generic think function before the others are called -// Input : state - which state the turret is currently in -//----------------------------------------------------------------------------- -bool CNPC_FloorTurret::PreThink( turretState_e state ) -{ - // Hack to disable turrets when ai is disabled - if ( CAI_BaseNPC::m_nDebugBits & bits_debugDisableAI ) - { - // Push our think out into the future - SetNextThink( gpGlobals->curtime + 0.1f ); - return true; - } - - CheckPVSCondition(); - - //Animate - StudioFrameAdvance(); - - // We're gonna blow up, so don't interrupt us - if ( state == TURRET_SELF_DESTRUCTING ) - return false; - - //See if we've tipped, but only do this if we're not being carried - if ( !IsBeingCarriedByPlayer() ) - { - if ( OnSide() == false ) - { - // If I still haven't fallen over after an NPC has tried to knock me down, let them know - if ( m_hLastNPCToKickMe && m_flKnockOverFailedTime < gpGlobals->curtime ) - { - m_hLastNPCToKickMe->DispatchInteraction( g_interactionTurretStillStanding, NULL, this ); - m_hLastNPCToKickMe = NULL; - } - - //Debug visualization - if ( g_debug_turret.GetBool() ) - { - Vector up; - GetVectors( NULL, NULL, &up ); - - NDebugOverlay::Line( GetAbsOrigin()+(up*32), GetAbsOrigin()+(up*128), 0, 255, 0, false, 2.0f ); - NDebugOverlay::Cross3D( GetAbsOrigin()+(up*32), -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 2.0f ); - NDebugOverlay::Cross3D( GetAbsOrigin()+(up*128), -Vector(2,2,2), Vector(2,2,2), 0, 255, 0, false, 2.0f ); - } - } - else - { - if ( HasSpawnFlags( SF_FLOOR_TURRET_OUT_OF_AMMO ) == false ) - { - //Thrash around for a bit - m_flThrashTime = gpGlobals->curtime + random->RandomFloat( 2.0f, 2.5f ); - SetNextThink( gpGlobals->curtime + 0.05f ); - - SetThink( &CNPC_FloorTurret::TippedThink ); - SetEyeState( TURRET_EYE_SEE_TARGET ); - - SpinUp(); - if ( !m_bNoAlarmSounds ) - { - EmitSound( "NPC_FloorTurret.Alarm" ); - } - } - else - { - // Take away the laser - UTIL_Remove( m_hLaser ); - m_hLaser = NULL; - - // Become inactive - SetThink( &CNPC_FloorTurret::InactiveThink ); - SetEyeState( TURRET_EYE_DEAD ); - } - - //Stop being targetted - SetState( NPC_STATE_DEAD ); - m_lifeState = LIFE_DEAD; - - //Disable the tip controller - m_pMotionController->Enable( false ); - - //Debug visualization - if ( g_debug_turret.GetBool() ) - { - Vector up; - GetVectors( NULL, NULL, &up ); - - NDebugOverlay::Line( GetAbsOrigin()+(up*32), GetAbsOrigin()+(up*128), 255, 0, 0, false, 2.0f ); - NDebugOverlay::Cross3D( GetAbsOrigin()+(up*32), -Vector(2,2,2), Vector(2,2,2), 255, 0, 0, false, 2.0f ); - NDebugOverlay::Cross3D( GetAbsOrigin()+(up*128), -Vector(2,2,2), Vector(2,2,2), 255, 0, 0, false, 2.0f ); - } - - //Interrupt current think function - return true; - } - } - - //Do not interrupt current think function - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Sets the state of the glowing eye attached to the turret -// Input : state - state the eye should be in -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::SetEyeState( eyeState_t state ) -{ - // Must have a valid eye to affect - if ( !m_hEyeGlow ) - { - // Create our eye sprite - m_hEyeGlow = CSprite::SpriteCreate( FLOOR_TURRET_GLOW_SPRITE, GetLocalOrigin(), false ); - if ( !m_hEyeGlow ) - return; - - m_hEyeGlow->SetTransparency( kRenderWorldGlow, 255, 0, 0, 128, kRenderFxNoDissipation ); - m_hEyeGlow->SetAttachment( this, m_iEyeAttachment ); - } - - // Add the laser if it doesn't already exist - if ( IsCitizenTurret() && HasSpawnFlags( SF_FLOOR_TURRET_OUT_OF_AMMO ) == false && m_hLaser == NULL ) - { - m_hLaser = CBeam::BeamCreate( LASER_BEAM_SPRITE, 1.0f ); - if ( m_hLaser == NULL ) - return; - - m_hLaser->EntsInit( this, this ); - m_hLaser->FollowEntity( this ); - m_hLaser->SetStartAttachment( LookupAttachment( "laser_start" ) ); - m_hLaser->SetEndAttachment( LookupAttachment( "laser_end" ) ); - m_hLaser->SetNoise( 0 ); - m_hLaser->SetColor( 255, 0, 0 ); - m_hLaser->SetScrollRate( 0 ); - m_hLaser->SetWidth( 1.0f ); - m_hLaser->SetEndWidth( 1.0f ); - m_hLaser->SetBrightness( 160 ); - m_hLaser->SetBeamFlags( SF_BEAM_SHADEIN ); - } - - m_iEyeState = state; - - //Set the state - switch( state ) - { - default: - case TURRET_EYE_SEE_TARGET: //Fade in and scale up - m_hEyeGlow->SetColor( 255, 0, 0 ); - m_hEyeGlow->SetBrightness( 164, 0.1f ); - m_hEyeGlow->SetScale( 0.4f, 0.1f ); - break; - - case TURRET_EYE_SEEKING_TARGET: //Ping-pongs - - //Toggle our state - m_bBlinkState = !m_bBlinkState; - m_hEyeGlow->SetColor( 255, 128, 0 ); - - if ( m_bBlinkState ) - { - //Fade up and scale up - m_hEyeGlow->SetScale( 0.25f, 0.1f ); - m_hEyeGlow->SetBrightness( 164, 0.1f ); - } - else - { - //Fade down and scale down - m_hEyeGlow->SetScale( 0.2f, 0.1f ); - m_hEyeGlow->SetBrightness( 64, 0.1f ); - } - - break; - - case TURRET_EYE_DORMANT: //Fade out and scale down - m_hEyeGlow->SetColor( 0, 255, 0 ); - m_hEyeGlow->SetScale( 0.1f, 0.5f ); - m_hEyeGlow->SetBrightness( 64, 0.5f ); - break; - - case TURRET_EYE_DEAD: //Fade out slowly - m_hEyeGlow->SetColor( 255, 0, 0 ); - m_hEyeGlow->SetScale( 0.1f, 3.0f ); - m_hEyeGlow->SetBrightness( 0, 3.0f ); - break; - - case TURRET_EYE_DISABLED: - m_hEyeGlow->SetColor( 0, 255, 0 ); - m_hEyeGlow->SetScale( 0.1f, 1.0f ); - m_hEyeGlow->SetBrightness( 0, 1.0f ); - break; - - case TURRET_EYE_ALARM: - { - //Toggle our state - m_bBlinkState = !m_bBlinkState; - m_hEyeGlow->SetColor( 255, 0, 0 ); - - if ( m_bBlinkState ) - { - //Fade up and scale up - m_hEyeGlow->SetScale( 0.75f, 0.05f ); - m_hEyeGlow->SetBrightness( 192, 0.05f ); - } - else - { - //Fade down and scale down - m_hEyeGlow->SetScale( 0.25f, 0.25f ); - m_hEyeGlow->SetBrightness( 64, 0.25f ); - } - } - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Make a pinging noise so the player knows where we are -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::Ping( void ) -{ - //See if it's time to ping again - if ( m_flPingTime > gpGlobals->curtime ) - return; - - //Ping! - EmitSound( "NPC_FloorTurret.Ping" ); - - SetEyeState( TURRET_EYE_SEEKING_TARGET ); - - m_flPingTime = gpGlobals->curtime + FLOOR_TURRET_PING_TIME; -} - -//----------------------------------------------------------------------------- -// Purpose: Toggle the turret's state -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::Toggle( void ) -{ - //This turret is on its side, it can't function - if ( OnSide() || ( IsAlive() == false ) ) - return; - - //Toggle the state - if ( m_bEnabled ) - { - Disable(); - } - else - { - Enable(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Enable the turret and deploy -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::Enable( void ) -{ - // Don't interrupt blowing up! - if ( m_bSelfDestructing ) - return; - - // Always allow us to come back to life, even if not right now - m_bEnabled = true; - - //This turret is on its side, it can't function - if ( OnSide() || ( IsAlive() == false ) ) - return; - - // if the turret is flagged as an autoactivate turret, re-enable its ability open self. - if ( m_spawnflags & SF_FLOOR_TURRET_AUTOACTIVATE ) - { - m_bAutoStart = true; - } - - SetThink( &CNPC_FloorTurret::Deploy ); - SetNextThink( gpGlobals->curtime + 0.05f ); -} - -//----------------------------------------------------------------------------- -// Purpose: Retire the turret until enabled again -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::Disable( void ) -{ - //This turret is on its side, it can't function - if ( OnSide() || ( IsAlive() == false ) || m_bSelfDestructing ) - return; - - if ( m_bEnabled ) - { - m_bEnabled = false; - m_bAutoStart = false; - - SetEnemy( NULL ); - SetThink( &CNPC_FloorTurret::Retire ); - SetNextThink( gpGlobals->curtime + 0.1f ); - } - else - SetThink( &CNPC_FloorTurret::DisabledThink ); -} - -//----------------------------------------------------------------------------- -// Purpose: Toggle the turret's state via input function -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::InputToggle( inputdata_t &inputdata ) -{ - Toggle(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::InputEnable( inputdata_t &inputdata ) -{ - Enable(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::InputDisable( inputdata_t &inputdata ) -{ - Disable(); -} - -//----------------------------------------------------------------------------- -// Purpose: Stops the turret from firing live rounds (still attempts to though) -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::InputDepleteAmmo( inputdata_t &inputdata ) -{ - AddSpawnFlags( SF_FLOOR_TURRET_OUT_OF_AMMO ); -} - -//----------------------------------------------------------------------------- -// Purpose: Allows the turret to fire live rounds again -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::InputRestoreAmmo( inputdata_t &inputdata ) -{ - RemoveSpawnFlags( SF_FLOOR_TURRET_OUT_OF_AMMO ); -} - -//----------------------------------------------------------------------------- -// Purpose: Allow players and npc's to turn the turret on and off -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::ToggleUse ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - switch( useType ) - { - case USE_OFF: - Disable(); - break; - case USE_ON: - Enable(); - break; - case USE_SET: - break; - case USE_TOGGLE: - Toggle( ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Reduce physics forces from the front -//----------------------------------------------------------------------------- -int CNPC_FloorTurret::VPhysicsTakeDamage( const CTakeDamageInfo &info ) -{ - bool bShouldIgnoreFromFront = false; - - // Ignore crossbow bolts hitting us from the front - bShouldIgnoreFromFront = ( info.GetDamageType() & DMG_BULLET ) != 0; - - // Ignore bullets from the front - if ( !bShouldIgnoreFromFront ) - { - bShouldIgnoreFromFront = FClassnameIs( info.GetInflictor(), "crossbow_bolt" ); - } - - // Did it hit us on the front? - if ( bShouldIgnoreFromFront ) - { - Vector vecForward; - GetVectors( &vecForward, NULL, NULL ); - Vector vecForce = info.GetDamageForce(); - VectorNormalize( vecForce ); - float flDot = DotProduct( vecForward, vecForce ); - if ( flDot < -0.85 ) - return 0; - } - - return BaseClass::VPhysicsTakeDamage( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -//----------------------------------------------------------------------------- -int CNPC_FloorTurret::OnTakeDamage( const CTakeDamageInfo &info ) -{ - CTakeDamageInfo newInfo = info; - - if ( info.GetDamageType() & (DMG_SLASH|DMG_CLUB) ) - { - // Take extra force from melee hits - newInfo.ScaleDamageForce( 2.0f ); - - // Disable our upright controller for some time - if ( m_pMotionController != NULL ) - { - m_pMotionController->Suspend( 2.0f ); - } - } - else if ( info.GetDamageType() & DMG_BLAST ) - { - newInfo.ScaleDamageForce( 2.0f ); - } - else if ( (info.GetDamageType() & DMG_BULLET) && !(info.GetDamageType() & DMG_BUCKSHOT) ) - { - // Bullets, but not buckshot, do extra push - newInfo.ScaleDamageForce( 2.5f ); - } - - // Manually apply vphysics because AI_BaseNPC takedamage doesn't call back to CBaseEntity OnTakeDamage - VPhysicsTakeDamage( newInfo ); - - // Bump up our search time - m_flLastSight = gpGlobals->curtime + FLOOR_TURRET_MAX_WAIT; - - // Start looking around in anger if we were idle - if ( IsAlive() && m_bEnabled && m_bAutoStart && GetActivity() == ACT_FLOOR_TURRET_CLOSED_IDLE && m_bSelfDestructing == false ) - { - SetThink( &CNPC_FloorTurret::Deploy ); - } - - return BaseClass::OnTakeDamage( newInfo ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::SpinUp( void ) -{ -} - -#define FLOOR_TURRET_MIN_SPIN_DOWN 1.0f - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const QAngle -//----------------------------------------------------------------------------- -QAngle CNPC_FloorTurret::PreferredCarryAngles( void ) -{ - // FIXME: Embed this into the class - static QAngle g_prefAngles; - - Vector vecUserForward; - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - pPlayer->EyeVectors( &vecUserForward ); - - // If we're looking up, then face directly forward - if ( vecUserForward.z >= 0.0f ) - return vec3_angle; - - // Otherwise, stay "upright" - g_prefAngles.Init(); - g_prefAngles.x = -pPlayer->EyeAngles().x; - - return g_prefAngles; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::SpinDown( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pVictim - -// Output : float -//----------------------------------------------------------------------------- -float CNPC_FloorTurret::GetAttackDamageScale( CBaseEntity *pVictim ) -{ - CBaseCombatCharacter *pBCC = pVictim->MyCombatCharacterPointer(); - - // Do extra damage to antlions & combine - if ( pBCC ) - { - if ( pBCC->Classify() == CLASS_ANTLION ) - return 2.0; - - if ( pBCC->Classify() == CLASS_COMBINE ) - return 2.0; - } - - return BaseClass::GetAttackDamageScale( pVictim ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Vector CNPC_FloorTurret::GetAttackSpread( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget ) -{ - WeaponProficiency_t weaponProficiency = WEAPON_PROFICIENCY_AVERAGE; - - // Switch our weapon proficiency based upon our target - if ( pTarget ) - { - if ( pTarget->Classify() == CLASS_PLAYER || pTarget->Classify() == CLASS_ANTLION || pTarget->Classify() == CLASS_ZOMBIE ) - { - // Make me much more accurate - weaponProficiency = WEAPON_PROFICIENCY_PERFECT; - } - else if ( pTarget->Classify() == CLASS_COMBINE ) - { - // Make me more accurate - weaponProficiency = WEAPON_PROFICIENCY_VERY_GOOD; - } - } - - return VECTOR_CONE_10DEGREES * ((CBaseHLCombatWeapon::GetDefaultProficiencyValues())[ weaponProficiency ].spreadscale); -} - -//------------------------------------------------------------------------------ -// Do we have a physics attacker? -//------------------------------------------------------------------------------ -CBasePlayer *CNPC_FloorTurret::HasPhysicsAttacker( float dt ) -{ - // If the player is holding me now, or I've been recently thrown - // then return a pointer to that player - if ( IsHeldByPhyscannon( ) || (gpGlobals->curtime - dt <= m_flLastPhysicsInfluenceTime) ) - { - return m_hPhysicsAttacker; - } - return NULL; -} -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CNPC_FloorTurret::DrawDebugTextOverlays( void ) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - if (VPhysicsGetObject()) - { - char tempstr[512]; - Q_snprintf(tempstr, sizeof(tempstr),"Mass: %.2f kg / %.2f lb (%s)", VPhysicsGetObject()->GetMass(), kg2lbs(VPhysicsGetObject()->GetMass()), GetMassEquivalent(VPhysicsGetObject()->GetMass())); - EntityText( text_offset, tempstr, 0); - text_offset++; - } - } - - return text_offset; -} - -void CNPC_FloorTurret::UpdateMuzzleMatrix() -{ - if ( gpGlobals->tickcount != m_muzzleToWorldTick ) - { - m_muzzleToWorldTick = gpGlobals->tickcount; - GetAttachment( m_iMuzzleAttachment, m_muzzleToWorld ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: We override this code because otherwise we start to move into the -// tricky realm of player avoidance. Since we don't go through the -// normal NPC thinking but we ARE an NPC (...) we miss a bunch of -// book keeping. This means we can become invisible and then never -// reappear. -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::PlayerPenetratingVPhysics( void ) -{ - // We don't care! -} - -#define SELF_DESTRUCT_DURATION 4.0f -#define SELF_DESTRUCT_BEEP_MIN_DELAY 0.1f -#define SELF_DESTRUCT_BEEP_MAX_DELAY 0.75f -#define SELF_DESTRUCT_BEEP_MIN_PITCH 100.0f -#define SELF_DESTRUCT_BEEP_MAX_PITCH 225.0f - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::BreakThink( void ) -{ - Vector vecUp; - GetVectors( NULL, NULL, &vecUp ); - Vector vecOrigin = WorldSpaceCenter() + ( vecUp * 12.0f ); - - // Our effect -#ifdef HL2_EPISODIC - DispatchParticleEffect( "explosion_turret_break", vecOrigin, GetAbsAngles() ); -#endif // HL2_EPISODIC - - // K-boom - RadiusDamage( CTakeDamageInfo( this, this, 15.0f, DMG_BLAST ), vecOrigin, (10*12), CLASS_NONE, this ); - - EmitSound( "NPC_FloorTurret.Destruct" ); - - breakablepropparams_t params( GetAbsOrigin(), GetAbsAngles(), vec3_origin, RandomAngularImpulse( -800.0f, 800.0f ) ); - params.impactEnergyScale = 1.0f; - params.defCollisionGroup = COLLISION_GROUP_INTERACTIVE; - - // no damage/damage force? set a burst of 100 for some movement - params.defBurstScale = 100; - PropBreakableCreateAll( GetModelIndex(), VPhysicsGetObject(), params, this, -1, true ); - - // Throw out some small chunks too obscure the explosion even more - CPVSFilter filter( vecOrigin ); - for ( int i = 0; i < 4; i++ ) - { - Vector gibVelocity = RandomVector(-100,100); - int iModelIndex = modelinfo->GetModelIndex( g_PropDataSystem.GetRandomChunkModel( "MetalChunks" ) ); - te->BreakModel( filter, 0.0, vecOrigin, GetAbsAngles(), Vector(40,40,40), gibVelocity, iModelIndex, 150, 4, 2.5, BREAK_METAL ); - } - - // We're done! - UTIL_Remove( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: The countdown to destruction! -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::SelfDestructThink( void ) -{ - // Continue to animate - PreThink( TURRET_SELF_DESTRUCTING ); - - // If we're done, explode - if ( ( gpGlobals->curtime - m_flDestructStartTime ) >= SELF_DESTRUCT_DURATION ) - { - SetThink( &CNPC_FloorTurret::BreakThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); - UTIL_Remove( m_hFizzleEffect ); - m_hFizzleEffect = NULL; - return; - } - - // Find out where we are in the cycle of our destruction - float flDestructPerc = clamp( ( gpGlobals->curtime - m_flDestructStartTime ) / SELF_DESTRUCT_DURATION, 0.0f, 1.0f ); - - // Figure out when our next beep should occur - float flBeepTime = SELF_DESTRUCT_BEEP_MAX_DELAY + ( ( SELF_DESTRUCT_BEEP_MIN_DELAY - SELF_DESTRUCT_BEEP_MAX_DELAY ) * flDestructPerc ); - - // If it's time to beep again, do so - if ( gpGlobals->curtime > ( m_flPingTime + flBeepTime ) ) - { - // Figure out what our beep pitch will be - float flBeepPitch = SELF_DESTRUCT_BEEP_MIN_PITCH + ( ( SELF_DESTRUCT_BEEP_MAX_PITCH - SELF_DESTRUCT_BEEP_MIN_PITCH ) * flDestructPerc ); - - StopSound( "NPC_FloorTurret.AlarmPing" ); - - // Play the beep - CPASAttenuationFilter filter( this, "NPC_FloorTurret.AlarmPing" ); - EmitSound_t params; - params.m_pSoundName = "NPC_FloorTurret.AlarmPing"; - params.m_nPitch = (int)floor( flBeepPitch ); - params.m_nFlags = SND_CHANGE_PITCH; - EmitSound( filter, entindex(), params ); - - // Flash our eye - SetEyeState( TURRET_EYE_ALARM ); - - // Save this as the last time we pinged - m_flPingTime = gpGlobals->curtime; - - // Randomly twitch - m_vecGoalAngles.x = GetAbsAngles().x + random->RandomFloat( -60*flDestructPerc, 60*flDestructPerc ); - m_vecGoalAngles.y = GetAbsAngles().y + random->RandomFloat( -60*flDestructPerc, 60*flDestructPerc ); - } - - UpdateFacing(); - - // Think again! - SetNextThink( gpGlobals->curtime + 0.05f ); -} - -//----------------------------------------------------------------------------- -// Purpose: Make us explode -//----------------------------------------------------------------------------- -void CNPC_FloorTurret::InputSelfDestruct( inputdata_t &inputdata ) -{ - // Ka-boom! - m_flDestructStartTime = gpGlobals->curtime; - m_flPingTime = gpGlobals->curtime; - m_bSelfDestructing = true; - - SetThink( &CNPC_FloorTurret::SelfDestructThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - // Create the dust effect in place - m_hFizzleEffect = (CParticleSystem *) CreateEntityByName( "info_particle_system" ); - if ( m_hFizzleEffect != NULL ) - { - Vector vecUp; - GetVectors( NULL, NULL, &vecUp ); - - // Setup our basic parameters - m_hFizzleEffect->KeyValue( "start_active", "1" ); - m_hFizzleEffect->KeyValue( "effect_name", "explosion_turret_fizzle" ); - m_hFizzleEffect->SetParent( this ); - m_hFizzleEffect->SetAbsOrigin( WorldSpaceCenter() + ( vecUp * 12.0f ) ); - DispatchSpawn( m_hFizzleEffect ); - m_hFizzleEffect->Activate(); - } -} - -// -// Tip controller -// - -LINK_ENTITY_TO_CLASS( floorturret_tipcontroller, CTurretTipController ); - - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CTurretTipController ) - - DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flSuspendTime, FIELD_TIME ), - DEFINE_FIELD( m_worldGoalAxis, FIELD_VECTOR ), - DEFINE_FIELD( m_localTestAxis, FIELD_VECTOR ), - DEFINE_PHYSPTR( m_pController ), - DEFINE_FIELD( m_angularLimit, FIELD_FLOAT ), - DEFINE_FIELD( m_pParentTurret, FIELD_CLASSPTR ), - -END_DATADESC() - - - -CTurretTipController::~CTurretTipController() -{ - if ( m_pController ) - { - physenv->DestroyMotionController( m_pController ); - m_pController = NULL; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTurretTipController::Spawn( void ) -{ - m_bEnabled = true; - - // align the object's local Z axis - m_localTestAxis.Init( 0, 0, 1 ); - // with the world's Z axis - m_worldGoalAxis.Init( 0, 0, 1 ); - - // recover from up to 25 degrees / sec angular velocity - m_angularLimit = 25; - m_flSuspendTime = 0; - - SetMoveType( MOVETYPE_NONE ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTurretTipController::Activate( void ) -{ - BaseClass::Activate(); - - if ( m_pParentTurret == NULL ) - { - UTIL_Remove(this); - return; - } - - IPhysicsObject *pPhys = m_pParentTurret->VPhysicsGetObject(); - - if ( pPhys == NULL ) - { - UTIL_Remove(this); - return; - } - - //Setup the motion controller - if ( !m_pController ) - { - m_pController = physenv->CreateMotionController( (IMotionEvent *)this ); - m_pController->AttachObject( pPhys, true ); - } - else - { - m_pController->SetEventHandler( this ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Actual simulation for tip controller -//----------------------------------------------------------------------------- -IMotionEvent::simresult_e CTurretTipController::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) -{ - if ( Enabled() == false ) - return SIM_NOTHING; - - // Don't simulate if we're being carried by the player - if ( m_pParentTurret->IsBeingCarriedByPlayer() ) - return SIM_NOTHING; - - float flAngularLimit = m_angularLimit; - - // If we were just dropped by a friendly player, stabilise better - if ( m_pParentTurret->WasJustDroppedByPlayer() ) - { - // Increase the controller strength a little - flAngularLimit += 20; - } - else - { - // If the turret has some vertical velocity, don't simulate - Vector vecVelocity; - AngularImpulse angImpulse; - pObject->GetVelocity( &vecVelocity, &angImpulse ); - if ( (vecVelocity.LengthSqr() > CNPC_FloorTurret::fMaxTipControllerVelocity) || (angImpulse.LengthSqr() > CNPC_FloorTurret::fMaxTipControllerAngularVelocity) ) - return SIM_NOTHING; - } - - linear.Init(); - - AngularImpulse angVel; - pObject->GetVelocity( NULL, &angVel ); - - matrix3x4_t matrix; - // get the object's local to world transform - pObject->GetPositionMatrix( &matrix ); - - // Get the alignment axis in object space - Vector currentLocalTargetAxis; - VectorIRotate( m_worldGoalAxis, matrix, currentLocalTargetAxis ); - - float invDeltaTime = (1/deltaTime); - angular = ComputeRotSpeedToAlignAxes( m_localTestAxis, currentLocalTargetAxis, angVel, 1.0, invDeltaTime * invDeltaTime, flAngularLimit * invDeltaTime ); - - return SIM_LOCAL_ACCELERATION; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTurretTipController::Enable( bool state ) -{ - m_bEnabled = state; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : time - -//----------------------------------------------------------------------------- -void CTurretTipController::Suspend( float time ) -{ - m_flSuspendTime = gpGlobals->curtime + time; -} - - -float CTurretTipController::SuspendedTill( void ) -{ - return m_flSuspendTime; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CTurretTipController::Enabled( void ) -{ - if ( m_flSuspendTime > gpGlobals->curtime ) - return false; - - return m_bEnabled; -} - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- -AI_BEGIN_CUSTOM_NPC( npc_turret_floor, CNPC_FloorTurret ) - - DECLARE_INTERACTION( g_interactionTurretStillStanding ); - -AI_END_CUSTOM_NPC() diff --git a/game/server/hl2/npc_turret_floor.h b/game/server/hl2/npc_turret_floor.h deleted file mode 100644 index f47398fdb..000000000 --- a/game/server/hl2/npc_turret_floor.h +++ /dev/null @@ -1,306 +0,0 @@ -#ifndef NPC_TURRET_FLOOR_H -#define NPC_TURRET_FLOOR_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_basenpc.h" -#include "player_pickup.h" -#include "particle_system.h" - -//Turret states -enum turretState_e -{ - TURRET_SEARCHING, - TURRET_AUTO_SEARCHING, - TURRET_ACTIVE, - TURRET_SUPPRESSING, - TURRET_DEPLOYING, - TURRET_RETIRING, - TURRET_TIPPED, - TURRET_SELF_DESTRUCTING, - - TURRET_STATE_TOTAL -}; - -//Eye states -enum eyeState_t -{ - TURRET_EYE_SEE_TARGET, //Sees the target, bright and big - TURRET_EYE_SEEKING_TARGET, //Looking for a target, blinking (bright) - TURRET_EYE_DORMANT, //Not active - TURRET_EYE_DEAD, //Completely invisible - TURRET_EYE_DISABLED, //Turned off, must be reactivated before it'll deploy again (completely invisible) - TURRET_EYE_ALARM, // On side, but warning player to pick it back up -}; - -//Spawnflags -// BUG: These all stomp Base NPC spawnflags. Any Base NPC code called by this -// this class may have undesired side effects due to these being set. -#define SF_FLOOR_TURRET_AUTOACTIVATE 0x00000020 -#define SF_FLOOR_TURRET_STARTINACTIVE 0x00000040 -#define SF_FLOOR_TURRET_FASTRETIRE 0x00000080 -#define SF_FLOOR_TURRET_OUT_OF_AMMO 0x00000100 -#define SF_FLOOR_TURRET_CITIZEN 0x00000200 // Citizen modified turret - -class CTurretTipController; -class CBeam; -class CSprite; - -//----------------------------------------------------------------------------- -// Purpose: Floor turret -//----------------------------------------------------------------------------- -class CNPC_FloorTurret : public CNPCBaseInteractive, public CDefaultPlayerPickupVPhysics -{ - DECLARE_CLASS( CNPC_FloorTurret, CNPCBaseInteractive ); -public: - - CNPC_FloorTurret( void ); - - virtual void Precache( void ); - virtual void Spawn( void ); - virtual void Activate( void ); - virtual bool CreateVPhysics( void ); - virtual void UpdateOnRemove( void ); - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - virtual void PlayerPenetratingVPhysics( void ); - virtual int VPhysicsTakeDamage( const CTakeDamageInfo &info ); - virtual bool CanBecomeServerRagdoll( void ) { return false; } - -#ifdef HL2_EPISODIC - // We don't want to be NPCSOLID because we'll collide with NPC clips - virtual unsigned int PhysicsSolidMaskForEntity( void ) const { return MASK_SOLID; } -#endif // HL2_EPISODIC - - // Player pickup - virtual void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ); - virtual void OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ); - virtual bool HasPreferredCarryAnglesForPlayer( CBasePlayer *pPlayer ); - virtual QAngle PreferredCarryAngles( void ); - virtual bool OnAttemptPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ); - - const char *GetTracerType( void ) { return "AR2Tracer"; } - - bool ShouldSavePhysics() { return true; } - - bool HandleInteraction( int interactionType, void *data, CBaseCombatCharacter *sourceEnt ); - - // Think functions - virtual void Retire( void ); - virtual void Deploy( void ); - virtual void ActiveThink( void ); - virtual void SearchThink( void ); - virtual void AutoSearchThink( void ); - virtual void TippedThink( void ); - virtual void InactiveThink( void ); - virtual void SuppressThink( void ); - virtual void DisabledThink( void ); - virtual void SelfDestructThink( void ); - virtual void BreakThink( void ); - virtual void HackFindEnemy( void ); - - virtual float GetAttackDamageScale( CBaseEntity *pVictim ); - virtual Vector GetAttackSpread( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget ); - - // Do we have a physics attacker? - CBasePlayer *HasPhysicsAttacker( float dt ); - bool IsHeldByPhyscannon( ) { return VPhysicsGetObject() && (VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD); } - - // Use functions - void ToggleUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - int ObjectCaps() - { - return BaseClass::ObjectCaps() | FCAP_IMPULSE_USE; - } - - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) - { - CBasePlayer *pPlayer = ToBasePlayer( pActivator ); - if ( pPlayer ) - { - pPlayer->PickupObject( this, false ); - } - } - - // Inputs - void InputToggle( inputdata_t &inputdata ); - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - void InputDepleteAmmo( inputdata_t &inputdata ); - void InputRestoreAmmo( inputdata_t &inputdata ); - void InputSelfDestruct( inputdata_t &inputdata ); - - virtual bool IsValidEnemy( CBaseEntity *pEnemy ); - bool CanBeAnEnemyOf( CBaseEntity *pEnemy ); - bool IsBeingCarriedByPlayer( void ) { return m_bCarriedByPlayer; } - bool WasJustDroppedByPlayer( void ); - - int BloodColor( void ) { return DONT_BLEED; } - float MaxYawSpeed( void ); - - virtual Class_T Classify( void ); - - Vector EyePosition( void ) - { - UpdateMuzzleMatrix(); - - Vector vecOrigin; - MatrixGetColumn( m_muzzleToWorld, 3, vecOrigin ); - - Vector vecForward; - MatrixGetColumn( m_muzzleToWorld, 0, vecForward ); - - // Note: We back up into the model to avoid an edge case where the eyes clip out of the world and - // cause problems with the PVS calculations -- jdw - - vecOrigin -= vecForward * 8.0f; - - return vecOrigin; - } - - Vector EyeOffset( Activity nActivity ) { return Vector( 0, 0, 58 ); } - - // Restore the turret to working operation after falling over - void ReturnToLife( void ); - - int DrawDebugTextOverlays( void ); - - // INPCInteractive Functions - virtual bool CanInteractWith( CAI_BaseNPC *pUser ) { return false; } // Disabled for now (sjb) - virtual bool HasBeenInteractedWith() { return m_bHackedByAlyx; } - virtual void NotifyInteraction( CAI_BaseNPC *pUser ) - { - // For now, turn green so we can tell who is hacked. - SetRenderColor( 0, 255, 0 ); - m_bHackedByAlyx = true; - } - - static float fMaxTipControllerVelocity; - static float fMaxTipControllerAngularVelocity; - -protected: - - virtual bool PreThink( turretState_e state ); - virtual void Shoot( const Vector &vecSrc, const Vector &vecDirToEnemy, bool bStrict = false ); - virtual void SetEyeState( eyeState_t state ); - void Ping( void ); - void Toggle( void ); - void Enable( void ); - void Disable( void ); - void SpinUp( void ); - void SpinDown( void ); - - virtual bool OnSide( void ); - - bool IsCitizenTurret( void ) { return HasSpawnFlags( SF_FLOOR_TURRET_CITIZEN ); } - bool UpdateFacing( void ); - void DryFire( void ); - void UpdateMuzzleMatrix(); - -protected: - matrix3x4_t m_muzzleToWorld; - int m_muzzleToWorldTick; - int m_iAmmoType; - - bool m_bAutoStart; - bool m_bActive; //Denotes the turret is deployed and looking for targets - bool m_bBlinkState; - bool m_bEnabled; //Denotes whether the turret is able to deploy or not - bool m_bNoAlarmSounds; - bool m_bSelfDestructing; // Going to blow up - - float m_flDestructStartTime; - float m_flShotTime; - float m_flLastSight; - float m_flThrashTime; - float m_flPingTime; - float m_flNextActivateSoundTime; - bool m_bCarriedByPlayer; - bool m_bUseCarryAngles; - float m_flPlayerDropTime; - int m_iKeySkin; - - CHandle m_hLastNPCToKickMe; // Stores the last NPC who tried to knock me over - float m_flKnockOverFailedTime; // Time at which we should tell the NPC that he failed to knock me over - - QAngle m_vecGoalAngles; - - int m_iEyeAttachment; - int m_iMuzzleAttachment; - eyeState_t m_iEyeState; - CHandle m_hEyeGlow; - CHandle m_hLaser; - CHandle m_pMotionController; - - CHandle m_hFizzleEffect; - Vector m_vecEnemyLKP; - - // physics influence - CHandle m_hPhysicsAttacker; - float m_flLastPhysicsInfluenceTime; - - static const char *m_pShotSounds[]; - - COutputEvent m_OnDeploy; - COutputEvent m_OnRetire; - COutputEvent m_OnTipped; - COutputEvent m_OnPhysGunPickup; - COutputEvent m_OnPhysGunDrop; - - bool m_bHackedByAlyx; - HSOUNDSCRIPTHANDLE m_ShotSounds; - - DECLARE_DATADESC(); - DEFINE_CUSTOM_AI; -}; - -// -// Tip controller -// - -class CTurretTipController : public CPointEntity, public IMotionEvent -{ - DECLARE_CLASS( CTurretTipController, CPointEntity ); - DECLARE_DATADESC(); - -public: - - ~CTurretTipController( void ); - void Spawn( void ); - void Activate( void ); - void Enable( bool state = true ); - void Suspend( float time ); - float SuspendedTill( void ); - - bool Enabled( void ); - - static CTurretTipController *CreateTipController( CNPC_FloorTurret *pOwner ) - { - if ( pOwner == NULL ) - return NULL; - - CTurretTipController *pController = (CTurretTipController *) Create( "floorturret_tipcontroller", pOwner->GetAbsOrigin(), pOwner->GetAbsAngles() ); - - if ( pController != NULL ) - { - pController->m_pParentTurret = pOwner; - } - - return pController; - } - - // IMotionEvent - virtual simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ); - -private: - bool m_bEnabled; - float m_flSuspendTime; - Vector m_worldGoalAxis; - Vector m_localTestAxis; - IPhysicsMotionController *m_pController; - float m_angularLimit; - CNPC_FloorTurret *m_pParentTurret; -}; - -#endif //#ifndef NPC_TURRET_FLOOR_H diff --git a/game/server/hl2/npc_turret_ground.cpp b/game/server/hl2/npc_turret_ground.cpp deleted file mode 100644 index 560b58ece..000000000 --- a/game/server/hl2/npc_turret_ground.cpp +++ /dev/null @@ -1,704 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Combine gun turret that emerges from a trapdoor in the ground. -// -//=============================================================================// -#include "cbase.h" -#include "npc_turret_ground.h" -#include "ai_default.h" -#include "ai_task.h" -#include "ai_schedule.h" -#include "ai_hull.h" -#include "ai_senses.h" -#include "ai_memory.h" -#include "soundent.h" -#include "game.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "npcevent.h" -#include "IEffects.h" -#include "ammodef.h" -#include "beam_shared.h" -#include "explode.h" -#include "te_effect_dispatch.h" - -#define GROUNDTURRET_BEAM_SPRITE "materials/effects/bluelaser2.vmt" - -#define GROUNDTURRET_VIEWCONE 60.0f // (degrees) -#define GROUNDTURRET_RETIRE_TIME 7.0f - -ConVar ai_newgroundturret ( "ai_newgroundturret", "0" ); - - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -LINK_ENTITY_TO_CLASS( npc_turret_ground, CNPC_GroundTurret ); - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CNPC_GroundTurret ) - DEFINE_FIELD( m_iAmmoType, FIELD_INTEGER ), - DEFINE_FIELD( m_pSmoke, FIELD_CLASSPTR ), - DEFINE_FIELD( m_vecSpread, FIELD_VECTOR ), - DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flTimeNextShoot, FIELD_TIME ), - DEFINE_FIELD( m_flTimeLastSawEnemy, FIELD_TIME ), - DEFINE_FIELD( m_iDeathSparks, FIELD_INTEGER ), - DEFINE_FIELD( m_bHasExploded, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flSensingDist, FIELD_FLOAT ), - DEFINE_FIELD( m_flTimeNextPing, FIELD_TIME ), - DEFINE_FIELD( m_bSeeEnemy, FIELD_BOOLEAN ), - DEFINE_FIELD( m_vecClosedPos, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecLightOffset, FIELD_POSITION_VECTOR ), - - DEFINE_THINKFUNC( DeathEffects ), - - DEFINE_OUTPUT( m_OnAreaClear, "OnAreaClear" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - - // DEFINE_FIELD( m_ShotSounds, FIELD_SHORT ), -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_GroundTurret::Precache( void ) -{ - PrecacheModel( GROUNDTURRET_BEAM_SPRITE ); - PrecacheModel( "models/combine_turrets/ground_turret.mdl" ); - - PrecacheScriptSound( "NPC_CeilingTurret.Deploy" ); - m_ShotSounds = PrecacheScriptSound( "NPC_FloorTurret.ShotSounds" ); - PrecacheScriptSound( "NPC_FloorTurret.Die" ); - PrecacheScriptSound( "NPC_FloorTurret.Ping" ); - PrecacheScriptSound( "DoSpark" ); - - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_GroundTurret::Spawn( void ) -{ - Precache(); - - UTIL_SetModel( this, "models/combine_turrets/ground_turret.mdl" ); - - SetNavType( NAV_FLY ); - SetSolid( SOLID_VPHYSICS ); - - SetBloodColor( DONT_BLEED ); - m_iHealth = 125; - m_flFieldOfView = cos( ((GROUNDTURRET_VIEWCONE / 2.0f) * M_PI / 180.0f) ); - m_NPCState = NPC_STATE_NONE; - - m_vecSpread.x = 0.5; - m_vecSpread.y = 0.5; - m_vecSpread.z = 0.5; - - CapabilitiesClear(); - - AddEFlags( EFL_NO_DISSOLVE ); - - NPCInit(); - - CapabilitiesAdd( bits_CAP_SIMPLE_RADIUS_DAMAGE ); - - m_iAmmoType = GetAmmoDef()->Index( "PISTOL" ); - - m_pSmoke = NULL; - - m_bHasExploded = false; - m_bEnabled = false; - - if( ai_newgroundturret.GetBool() ) - { - m_flSensingDist = 384; - SetDistLook( m_flSensingDist ); - } - else - { - m_flSensingDist = 2048; - } - - if( !GetParent() ) - { - DevMsg("ERROR! npc_ground_turret with no parent!\n"); - UTIL_Remove(this); - return; - } - - m_flTimeNextShoot = gpGlobals->curtime; - m_flTimeNextPing = gpGlobals->curtime; - - m_vecClosedPos = GetAbsOrigin(); - - StudioFrameAdvance(); - - Vector vecPos; - - GetAttachment( "eyes", vecPos ); - SetViewOffset( vecPos - GetAbsOrigin() ); - - GetAttachment( "light", vecPos ); - m_vecLightOffset = vecPos - GetAbsOrigin(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CNPC_GroundTurret::CreateVPhysics( void ) -{ - //Spawn our physics hull - if ( !VPhysicsInitStatic() ) - { - DevMsg( "npc_turret_ground unable to spawn physics object!\n" ); - } - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_GroundTurret::PrescheduleThink() -{ - if( UTIL_FindClientInPVS(edict()) ) - { - SetNextThink( gpGlobals->curtime + 0.03f ); - } - else - { - SetNextThink( gpGlobals->curtime + 0.1f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : -//----------------------------------------------------------------------------- -Class_T CNPC_GroundTurret::Classify( void ) -{ - if( !IsOpen() ) - { - // NPC's should disregard me if I'm closed. - return CLASS_NONE; - } - else - { - return CLASS_COMBINE; - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_GroundTurret::PostNPCInit() -{ - BaseClass::PostNPCInit(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CNPC_GroundTurret::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - if( !info.GetInflictor() ) - { - return 0; - } - - // Only take damage from self (kill input from my bullseye) or missiles. - if( info.GetInflictor() != this && info.GetInflictor()->Classify() != CLASS_MISSILE ) - { - return 0; - } - - CTakeDamageInfo infoCopy = info; - - if( info.GetInflictor() == this ) - { - // Taking damage from myself, make sure it's fatal. - infoCopy.SetDamage( GetHealth() ); - infoCopy.SetDamageType( DMG_REMOVENORAGDOLL | DMG_GENERIC ); - } - - return BaseClass::OnTakeDamage_Alive( infoCopy ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_GroundTurret::Event_Killed( const CTakeDamageInfo &info ) -{ - BaseClass::Event_Killed( info ); - - if ( m_pSmoke != NULL ) - return; - - m_pSmoke = SmokeTrail::CreateSmokeTrail(); - - if ( m_pSmoke ) - { - m_pSmoke->m_SpawnRate = 18; - m_pSmoke->m_ParticleLifetime = 3.0; - m_pSmoke->m_StartSize = 8; - m_pSmoke->m_EndSize = 32; - m_pSmoke->m_SpawnRadius = 16; - m_pSmoke->m_MinSpeed = 8; - m_pSmoke->m_MaxSpeed = 32; - m_pSmoke->m_Opacity = 0.6; - - m_pSmoke->m_StartColor.Init( 0.25f, 0.25f, 0.25f ); - m_pSmoke->m_EndColor.Init( 0, 0, 0 ); - m_pSmoke->SetLifetime( 30.0f ); - m_pSmoke->FollowEntity( this ); - } - - m_iDeathSparks = random->RandomInt( 6, 12 ); - - SetThink( &CNPC_GroundTurret::DeathEffects ); - SetNextThink( gpGlobals->curtime + 1.5f ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_GroundTurret::DeathEffects() -{ - if( !m_bHasExploded ) - { - //ExplosionCreate( GetAbsOrigin(), QAngle( 0, 0, 1 ), this, 150, 150, false ); - CTakeDamageInfo info; - DeathSound( info ); - m_bHasExploded = true; - SetNextThink( gpGlobals->curtime + 0.5 ); - } - else - { - // Sparks - EmitSound( "DoSpark" ); - m_iDeathSparks--; - - if( m_iDeathSparks == 0 ) - { - SetThink(NULL); - return; - } - - SetNextThink( gpGlobals->curtime + random->RandomFloat( 0.5, 2.5 ) ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_GroundTurret::DeathSound( const CTakeDamageInfo &info ) -{ - EmitSound("NPC_FloorTurret.Die"); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_GroundTurret::MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ) -{ -#if 1 - //BaseClass::MakeTracer( vecTracerSrc, tr, iTracerType ); - UTIL_Tracer( vecTracerSrc, tr.endpos, 0, TRACER_DONT_USE_ATTACHMENT, 5000, true, "AR2Tracer" ); -#else - CBeam *pBeam; - int width = 2; - - pBeam = CBeam::BeamCreate( GROUNDTURRET_BEAM_SPRITE, width ); - if ( !pBeam ) - return; - - pBeam->SetStartPos( vecTracerSrc ); - pBeam->SetEndPos( tr.endpos ); - pBeam->SetWidth( width ); - pBeam->SetEndWidth( width / 4.0f ); - - pBeam->SetBrightness( 100 ); - pBeam->SetColor( 0, 145+random->RandomInt( -16, 16 ), 255 ); - pBeam->RelinkBeam(); - pBeam->LiveForTime( random->RandomFloat( 0.2f, 0.5f ) ); -#endif -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_GroundTurret::GatherConditions() -{ - if( !IsEnabled() ) - { - return; - } - - if( !IsOpen() && !UTIL_FindClientInPVS( edict() ) ) - { - return; - } - - // Throw away old enemies so the turret can retire - AIEnemiesIter_t iter; - - for( AI_EnemyInfo_t *pEMemory = GetEnemies()->GetFirst(&iter); pEMemory != NULL; pEMemory = GetEnemies()->GetNext(&iter) ) - { - if( pEMemory->timeLastSeen < gpGlobals->curtime - GROUNDTURRET_RETIRE_TIME ) - { - pEMemory->hEnemy = NULL; - } - } - - BaseClass::GatherConditions(); - - if( GetEnemy() && HasCondition(COND_SEE_ENEMY) ) - { - m_flTimeLastSawEnemy = gpGlobals->curtime; - } - else - { - if( gpGlobals->curtime - m_flTimeLastSawEnemy >= GROUNDTURRET_RETIRE_TIME ) - { - m_OnAreaClear.FireOutput(this, this); - m_flTimeLastSawEnemy = FLT_MAX; - return; - } - } - - if( HasCondition( COND_SEE_ENEMY ) ) - { - m_bSeeEnemy = true; - } - else - { - m_bSeeEnemy = false; - } - - if( GetEnemy() && m_bSeeEnemy && IsEnabled() ) - { - if( m_flTimeNextShoot < gpGlobals->curtime ) - { - Shoot(); - } - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -Vector CNPC_GroundTurret::EyePosition() -{ - if( ai_newgroundturret.GetBool() ) - { - return GetAbsOrigin() + Vector( 0, 0, 6 ); - } - - return GetAbsOrigin() + GetViewOffset(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_GroundTurret::FVisible( CBaseEntity *pEntity, int traceMask, CBaseEntity **ppBlocker ) -{ - if ( BaseClass::FVisible( pEntity, traceMask, ppBlocker ) ) - return true; - if ( ( pEntity->GetAbsOrigin().AsVector2D() - GetAbsOrigin().AsVector2D() ).LengthSqr() < Square(10*12) && - FInViewCone( pEntity->GetAbsOrigin() ) && - BaseClass::FVisible( pEntity->GetAbsOrigin() + Vector( 0, 0, 1 ), traceMask, ppBlocker ) ) - return true; - return false; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_GroundTurret::QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC) -{ - float flDist; - - flDist = (pEntity->GetAbsOrigin() - EyePosition()).Length2DSqr(); - - if( flDist <= m_flSensingDist * m_flSensingDist ) - { - return BaseClass::QuerySeeEntity(pEntity, bOnlyHateOrFearIfNPC); - } - - return false; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_GroundTurret::IsEnabled() -{ - if( ai_newgroundturret.GetBool() ) - { - return true; - } - - return m_bEnabled; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPC_GroundTurret::IsOpen() -{ - // The method is hacky but in the end, this does actually give - // us a pretty good idea if the turret is open or closed. - return( fabs(GetAbsOrigin().z - m_vecClosedPos.z ) > 1.0f ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_GroundTurret::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_GROUNDTURRET_SCAN: - Scan(); - break; - - default: - BaseClass::StartTask( pTask ); - break; - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPC_GroundTurret::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_GROUNDTURRET_SCAN: - Scan(); - break; - - default: - BaseClass::RunTask( pTask ); - break; - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CNPC_GroundTurret::SelectSchedule( void ) -{ - return SCHED_GROUND_TURRET_IDLE; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CNPC_GroundTurret::TranslateSchedule( int scheduleType ) -{ - switch( scheduleType ) - { - case SCHED_IDLE_STAND: - return SCHED_GROUND_TURRET_IDLE; - break; - } - - return BaseClass::TranslateSchedule( scheduleType ); -} - -//----------------------------------------------------------------------------- -// Purpose: Override base class activiites -// Input : -// Output : -//----------------------------------------------------------------------------- -Activity CNPC_GroundTurret::NPC_TranslateActivity( Activity activity ) -{ - return ACT_IDLE; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_GroundTurret::Shoot() -{ - FireBulletsInfo_t info; - - Vector vecSrc = EyePosition(); - Vector vecDir; - - GetVectors( &vecDir, NULL, NULL ); - - for( int i = 0 ; i < 1 ; i++ ) - { - info.m_vecSrc = vecSrc; - - if( i > 0 || !GetEnemy()->IsPlayer() ) - { - // Subsequent shots or shots at non-players random - GetVectors( &info.m_vecDirShooting, NULL, NULL ); - info.m_vecSpread = m_vecSpread; - } - else - { - // First shot is at the enemy. - info.m_vecDirShooting = GetActualShootTrajectory( vecSrc ); - info.m_vecSpread = VECTOR_CONE_PRECALCULATED; - } - - info.m_iTracerFreq = 1; - info.m_iShots = 1; - info.m_pAttacker = this; - info.m_flDistance = MAX_COORD_RANGE; - info.m_iAmmoType = m_iAmmoType; - - FireBullets( info ); - } - - // Do the AR2 muzzle flash - CEffectData data; - data.m_nEntIndex = entindex(); - data.m_nAttachmentIndex = LookupAttachment( "eyes" ); - data.m_flScale = 1.0f; - data.m_fFlags = MUZZLEFLASH_COMBINE; - DispatchEffect( "MuzzleFlash", data ); - - EmitSound( "NPC_FloorTurret.ShotSounds", m_ShotSounds ); - - if( IsX360() ) - { - m_flTimeNextShoot = gpGlobals->curtime + 0.2; - } - else - { - m_flTimeNextShoot = gpGlobals->curtime + 0.09; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_GroundTurret::ProjectBeam( const Vector &vecStart, const Vector &vecDir, int width, int brightness, float duration ) -{ - CBeam *pBeam; - pBeam = CBeam::BeamCreate( GROUNDTURRET_BEAM_SPRITE, width ); - if ( !pBeam ) - return; - - trace_t tr; - AI_TraceLine( vecStart, vecStart + vecDir * m_flSensingDist, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - pBeam->SetStartPos( tr.endpos ); - pBeam->SetEndPos( tr.startpos ); - pBeam->SetWidth( width ); - pBeam->SetEndWidth( 0.1 ); - pBeam->SetFadeLength( 16 ); - - pBeam->SetBrightness( brightness ); - pBeam->SetColor( 0, 145+random->RandomInt( -16, 16 ), 255 ); - pBeam->RelinkBeam(); - pBeam->LiveForTime( duration ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_GroundTurret::Scan() -{ - if( m_bSeeEnemy ) - { - // Using a bool for this check because the condition gets wiped out by changing schedules. - return; - } - - if( IsOpeningOrClosing() ) - { - // Moving. - return; - } - - if( !IsOpen() ) - { - // Closed - return; - } - - if( !UTIL_FindClientInPVS(edict()) ) - { - return; - } - - if( gpGlobals->curtime >= m_flTimeNextPing ) - { - EmitSound( "NPC_FloorTurret.Ping" ); - m_flTimeNextPing = gpGlobals->curtime + 1.0f; - } - - QAngle scanAngle; - Vector forward; - Vector vecEye = GetAbsOrigin() + m_vecLightOffset; - - // Draw the outer extents - scanAngle = GetAbsAngles(); - scanAngle.y += (GROUNDTURRET_VIEWCONE / 2.0f); - AngleVectors( scanAngle, &forward, NULL, NULL ); - ProjectBeam( vecEye, forward, 1, 30, 0.1 ); - - scanAngle = GetAbsAngles(); - scanAngle.y -= (GROUNDTURRET_VIEWCONE / 2.0f); - AngleVectors( scanAngle, &forward, NULL, NULL ); - ProjectBeam( vecEye, forward, 1, 30, 0.1 ); - - // Draw a sweeping beam - scanAngle = GetAbsAngles(); - scanAngle.y += (GROUNDTURRET_VIEWCONE / 2.0f) * sin( gpGlobals->curtime * 3.0f ); - - AngleVectors( scanAngle, &forward, NULL, NULL ); - ProjectBeam( vecEye, forward, 1, 30, 0.3 ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_GroundTurret::InputEnable( inputdata_t &inputdata ) -{ - m_bEnabled = true; - - // Because the turret might not ever ACQUIRE an enemy, we need to arrange to - // retire after a few seconds. - m_flTimeLastSawEnemy = gpGlobals->curtime; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_GroundTurret::InputDisable( inputdata_t &inputdata ) -{ - m_bEnabled = false; -} - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC( npc_groundturret, CNPC_GroundTurret ) - - DECLARE_TASK( TASK_GROUNDTURRET_SCAN ); - - DEFINE_SCHEDULE - ( - SCHED_GROUND_TURRET_IDLE, - - " Tasks " - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_GROUNDTURRET_SCAN 0" - "" - " Interrupts " - " COND_NEW_ENEMY" - " COND_SEE_ENEMY" - " COND_LOST_ENEMY" - ) - - DEFINE_SCHEDULE - ( - SCHED_GROUND_TURRET_ATTACK, - - " Tasks " - " TASK_WAIT_INDEFINITE 0" - "" - " Interrupts " - " COND_NEW_ENEMY" - " COND_LOST_ENEMY" - " COND_SEE_ENEMY" - ) - -AI_END_CUSTOM_NPC() - diff --git a/game/server/hl2/npc_turret_ground.h b/game/server/hl2/npc_turret_ground.h deleted file mode 100644 index 97a360654..000000000 --- a/game/server/hl2/npc_turret_ground.h +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef NPC_TURRET_GROUND_H -#define NPC_TURRET_GROUND_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_basenpc.h" -#include "smoke_trail.h" - -//========================================================= -//========================================================= -class CNPC_GroundTurret : public CAI_BaseNPC -{ -public: - DECLARE_CLASS( CNPC_GroundTurret, CAI_BaseNPC ); - DECLARE_DATADESC(); - - void Precache( void ); - virtual void Spawn( void ); - bool CreateVPhysics( void ); - void PrescheduleThink(); - Class_T Classify( void ); - - void PostNPCInit(); - - // Damage & Death - virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - void Event_Killed( const CTakeDamageInfo &info ); - void DeathEffects(); - bool CanBecomeRagdoll( void ) { return false; } - void DeathSound( const CTakeDamageInfo &info ); - - // Combat - void MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ); - Vector GetAttackSpread( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget ) - { - return VECTOR_CONE_5DEGREES; - } - - - // Sensing - void GatherConditions(); - Vector EyePosition(); - bool FVisible( CBaseEntity *pEntity, int traceMask, CBaseEntity **ppBlocker ); - bool QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC = false ); - - - bool IsOpeningOrClosing() { return (GetAbsVelocity().z != 0.0f); } - bool IsEnabled(); - bool IsOpen(); - - // Tasks & Schedules - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - virtual int SelectSchedule( void ); - virtual int TranslateSchedule( int scheduleType ); - - // Activities & Animation - Activity NPC_TranslateActivity( Activity eNewActivity ); - virtual void Shoot(); - virtual void Scan(); - void ProjectBeam( const Vector &vecStart, const Vector &vecDir, int width, int brightness, float duration ); - - // Local - void SetActive( bool bActive ) {} - - // Inputs - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - - // Outputs - COutputEvent m_OnAreaClear; - - DEFINE_CUSTOM_AI; - -protected: - //----------------------------------------------------- - // Conditions, Schedules, Tasks - //----------------------------------------------------- - enum - { - SCHED_GROUND_TURRET_IDLE = BaseClass::NEXT_SCHEDULE, - SCHED_GROUND_TURRET_ATTACK, - - TASK_GROUNDTURRET_SCAN = BaseClass::NEXT_TASK, - }; - - int m_iAmmoType; - SmokeTrail *m_pSmoke; - - bool m_bEnabled; - - float m_flTimeNextShoot; - float m_flTimeLastSawEnemy; - Vector m_vecSpread; - bool m_bHasExploded; - int m_iDeathSparks; - float m_flSensingDist; - bool m_bSeeEnemy; - float m_flTimeNextPing; - - Vector m_vecClosedPos; - - Vector m_vecLightOffset; - - HSOUNDSCRIPTHANDLE m_ShotSounds; -}; - -#endif //#ifndef NPC_TURRET_GROUND_H diff --git a/game/server/hl2/npc_vortigaunt_episodic.cpp b/game/server/hl2/npc_vortigaunt_episodic.cpp deleted file mode 100644 index 4fcbed231..000000000 --- a/game/server/hl2/npc_vortigaunt_episodic.cpp +++ /dev/null @@ -1,3410 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ==== -// -// Purpose: Vortigaunt - now much friendlier! -// -//============================================================================= - -#include "cbase.h" -#include "beam_shared.h" -#include "globalstate.h" -#include "npcevent.h" -#include "Sprite.h" -#include "IEffects.h" -#include "te_effect_dispatch.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" -#include "physics_prop_ragdoll.h" -#include "RagdollBoogie.h" -#include "ai_squadslot.h" -#include "npc_antlion.h" -#include "particle_parse.h" -#include "particle_system.h" -#include "ai_senses.h" - -#include "npc_vortigaunt_episodic.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define HAND_LEFT 0 -#define HAND_RIGHT 1 -#define HAND_BOTH 2 - -class CVortigauntChargeToken; - -#define VORTIGAUNT_LIMP_HEALTH 20 -#define VORTIGAUNT_SENTENCE_VOLUME (float)0.35 // volume of vortigaunt sentences -#define VORTIGAUNT_VOL 0.35 // volume of vortigaunt sounds -#define VORTIGAUNT_ATTN ATTN_NORM // attenutation of vortigaunt sentences -#define VORTIGAUNT_HEAL_RECHARGE 30.0 // How long to rest between heals -#define VORTIGAUNT_ZAP_GLOWGROW_TIME 0.5 // How long does glow last -#define VORTIGAUNT_HEAL_GLOWGROW_TIME 1.4 // How long does glow last -#define VORTIGAUNT_GLOWFADE_TIME 0.5 // How long does it fade -#define VORTIGAUNT_CURE_LIFESPAN 8.0 // cure tokens only live this long (so they don't get stuck on geometry) - -#define VORTIGAUNT_BLUE_FADE_TIME 2.25f // takes this long to fade from green to blue or back - -#define VORTIGAUNT_FEAR_ZOMBIE_DIST_SQR Square(60) // back away from zombies inside this radius - -#define PLAYER_CRITICAL_HEALTH_PERC 0.15f - -#define TLK_SQUISHED_GRUB "TLK_SQUISHED_GRUB" // response rule for vortigaunts when they step on a grub - -static const char *VORTIGAUNT_LEFT_CLAW = "leftclaw"; -static const char *VORTIGAUNT_RIGHT_CLAW = "rightclaw"; - -//static const char *VORT_CURE = "VORT_CURE"; -static const char *VORT_CURESTOP = "VORT_CURESTOP"; -//static const char *VORT_CURE_INTERRUPT = "VORT_CURE_INTERRUPT"; -static const char *VORT_ATTACK = "VORT_ATTACK"; -//static const char *VORT_MAD = "VORT_MAD"; -//static const char *VORT_SHOT = "VORT_SHOT"; -static const char *VORT_PAIN = "VORT_PAIN"; -static const char *VORT_DIE = "VORT_DIE"; -//static const char *VORT_KILL = "VORT_KILL"; -//static const char *VORT_LINE_FIRE = "VORT_LINE_FIRE"; -static const char *VORT_POK = "VORT_POK"; -static const char *VORT_EXTRACT_START = "VORT_EXTRACT_START"; -static const char *VORT_EXTRACT_FINISH = "VORT_EXTRACT_FINISH"; - -// Target must be within this range to heal -#define HEAL_RANGE (40*12) //ft -#define HEAL_SEARCH_RANGE (40*12) //ft - -ConVar sk_vortigaunt_armor_charge( "sk_vortigaunt_armor_charge","30"); -ConVar sk_vortigaunt_armor_charge_per_token( "sk_vortigaunt_armor_charge_per_token","5"); - -ConVar sk_vortigaunt_health( "sk_vortigaunt_health","0"); -ConVar sk_vortigaunt_dmg_claw( "sk_vortigaunt_dmg_claw","0"); -ConVar sk_vortigaunt_dmg_rake( "sk_vortigaunt_dmg_rake","0"); -ConVar sk_vortigaunt_dmg_zap( "sk_vortigaunt_dmg_zap","0"); -ConVar sk_vortigaunt_zap_range( "sk_vortigaunt_zap_range", "100", FCVAR_NONE, "Range of vortigaunt's ranged attack (feet)" ); -ConVar sk_vortigaunt_vital_antlion_worker_dmg("sk_vortigaunt_vital_antlion_worker_dmg", "0.2", FCVAR_NONE, "Vital-ally vortigaunts scale damage taken from antlion workers by this amount." ); - -ConVar g_debug_vortigaunt_aim( "g_debug_vortigaunt_aim", "0" ); - -// FIXME: Move to shared code! -#define VORTFX_ZAPBEAM 0 // Beam that damages the target -#define VORTFX_ARMBEAM 1 // Smaller beams from the hands as we charge up - -//----------------------------------------------------------------------------- -// Interactions -//----------------------------------------------------------------------------- -int g_interactionVortigauntStomp = 0; -int g_interactionVortigauntStompFail = 0; -int g_interactionVortigauntStompHit = 0; -int g_interactionVortigauntKick = 0; -int g_interactionVortigauntClaw = 0; - -//========================================================= -// Vortigaunt activities -//========================================================= -int ACT_VORTIGAUNT_AIM; -int ACT_VORTIGAUNT_START_HEAL; -int ACT_VORTIGAUNT_HEAL_LOOP; -int ACT_VORTIGAUNT_END_HEAL; -int ACT_VORTIGAUNT_TO_ACTION; -int ACT_VORTIGAUNT_TO_IDLE; -int ACT_VORTIGAUNT_HEAL; // Heal gesture -int ACT_VORTIGAUNT_DISPEL; -int ACT_VORTIGAUNT_ANTLION_THROW; - -//========================================================= -// Monster's Anim Events Go Here -//========================================================= -int AE_VORTIGAUNT_CLAW_LEFT; -int AE_VORTIGAUNT_CLAW_RIGHT; -int AE_VORTIGAUNT_ZAP_POWERUP; -int AE_VORTIGAUNT_ZAP_SHOOT; -int AE_VORTIGAUNT_ZAP_DONE; -int AE_VORTIGAUNT_HEAL_STARTGLOW; -int AE_VORTIGAUNT_HEAL_STARTBEAMS; -int AE_VORTIGAUNT_HEAL_STARTSOUND; -int AE_VORTIGAUNT_SWING_SOUND; -int AE_VORTIGAUNT_SHOOT_SOUNDSTART; -int AE_VORTIGAUNT_HEAL_PAUSE; - -int AE_VORTIGAUNT_START_DISPEL; // Start the warm-up -int AE_VORTIGAUNT_ACCEL_DISPEL; // Indicates we're ramping up -int AE_VORTIGAUNT_DISPEL; // Actual blast - -int AE_VORTIGAUNT_START_HURT_GLOW; // Start the hurt handglow: 0=left, 1=right -int AE_VORTIGAUNT_STOP_HURT_GLOW; // Turn off the hurt handglow: 0=left, 1=right - -int AE_VORTIGAUNT_START_HEAL_GLOW; // 0 - Left, 1 - Right -int AE_VORTIGAUNT_STOP_HEAL_GLOW; // ' - -//----------------------------------------------------------------------------- -// Squad slots -//----------------------------------------------------------------------------- -enum SquadSlot_T -{ - SQUAD_SLOT_HEAL_PLAYER = LAST_SHARED_SQUADSLOT, -}; - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CNPC_Vortigaunt ) - - DEFINE_FIELD( m_eHealState, FIELD_INTEGER ), - DEFINE_FIELD( m_flNextHealTokenTime, FIELD_TIME ), - DEFINE_ARRAY( m_hHandEffect, FIELD_EHANDLE, 2 ), - DEFINE_FIELD( m_flNextHealTime, FIELD_TIME ), - DEFINE_FIELD( m_bPlayerRequestedHeal, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flDispelTestTime, FIELD_TIME ), - DEFINE_FIELD( m_flHealHinderedTime, FIELD_FLOAT ), - DEFINE_FIELD( m_nLightningSprite, FIELD_INTEGER), - DEFINE_FIELD( m_fGlowAge, FIELD_FLOAT), - DEFINE_FIELD( m_fGlowChangeTime, FIELD_TIME), - DEFINE_FIELD( m_bGlowTurningOn, FIELD_BOOLEAN), - DEFINE_FIELD( m_nCurGlowIndex, FIELD_INTEGER), - DEFINE_FIELD( m_flNextHealTime, FIELD_TIME), - DEFINE_FIELD( m_flPainTime, FIELD_TIME), - DEFINE_FIELD( m_nextLineFireTime, FIELD_TIME), - DEFINE_KEYFIELD( m_bArmorRechargeEnabled,FIELD_BOOLEAN, "ArmorRechargeEnabled" ), - DEFINE_FIELD( m_bForceArmorRecharge, FIELD_BOOLEAN), - DEFINE_FIELD( m_bExtractingBugbait, FIELD_BOOLEAN), - DEFINE_FIELD( m_iLeftHandAttachment, FIELD_INTEGER ), - DEFINE_FIELD( m_iRightHandAttachment, FIELD_INTEGER ), - DEFINE_FIELD( m_hHealTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_flBlueEndFadeTime, FIELD_TIME ), - DEFINE_FIELD( m_bIsBlue, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bIsBlack, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flAimDelay, FIELD_TIME ), - DEFINE_FIELD( m_bCarryingNPC, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_bRegenerateHealth, FIELD_BOOLEAN, "HealthRegenerateEnabled" ), - - // m_AssaultBehavior (auto saved by AI) - // m_LeadBehavior - // DEFINE_FIELD( m_bStopLoopingSounds, FIELD_BOOLEAN ), - - // Function Pointers - DEFINE_USEFUNC( Use ), - - DEFINE_INPUTFUNC( FIELD_VOID, "EnableArmorRecharge", InputEnableArmorRecharge ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableArmorRecharge", InputDisableArmorRecharge ), - DEFINE_INPUTFUNC( FIELD_STRING, "ChargeTarget", InputChargeTarget ), - DEFINE_INPUTFUNC( FIELD_STRING, "ExtractBugbait", InputExtractBugbait ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableHealthRegeneration", InputEnableHealthRegeneration ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableHealthRegeneration",InputDisableHealthRegeneration ), - DEFINE_INPUTFUNC( FIELD_VOID, "Dispel", InputDispel ), - DEFINE_INPUTFUNC( FIELD_VOID, "BeginCarryNPC", InputBeginCarryNPC ), - DEFINE_INPUTFUNC( FIELD_VOID, "EndCarryNPC", InputEndCarryNPC ), - - DEFINE_INPUTFUNC( FIELD_BOOLEAN, "TurnBlue", InputTurnBlue ), - DEFINE_INPUTFUNC( FIELD_BOOLEAN, "TurnBlack", InputTurnBlack ), - - // Outputs - DEFINE_OUTPUT(m_OnFinishedExtractingBugbait, "OnFinishedExtractingBugbait"), - DEFINE_OUTPUT(m_OnFinishedChargingTarget, "OnFinishedChargingTarget"), - DEFINE_OUTPUT(m_OnPlayerUse, "OnPlayerUse" ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( npc_vortigaunt, CNPC_Vortigaunt ); - -IMPLEMENT_SERVERCLASS_ST( CNPC_Vortigaunt, DT_NPC_Vortigaunt ) - SendPropTime( SENDINFO (m_flBlueEndFadeTime ) ), - SendPropBool( SENDINFO( m_bIsBlue )), - SendPropBool( SENDINFO ( m_bIsBlack ) ), -END_SEND_TABLE() - -// for special behavior with rollermines -static bool IsRoller( CBaseEntity *pRoller ) -{ - return FClassnameIs( pRoller, "npc_rollermine" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CNPC_Vortigaunt::CNPC_Vortigaunt( void ) : -m_flNextHealTime( 3.0f ), // Let the player settle before we decide to do this -m_bPlayerRequestedHeal( false ), -m_eHealState( HEAL_STATE_NONE ), -m_nNumTokensToSpawn( 0 ), -m_flAimDelay( 0.0f ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: Determines whether or not the player is below a certain percentage -// of their maximum health -// Input : flPerc - Percentage to test against -// Output : Returns true if less than supplied parameter -//----------------------------------------------------------------------------- -bool CNPC_Vortigaunt::PlayerBelowHealthPercentage( CBasePlayer *pPlayer, float flPerc ) -{ - if ( pPlayer == NULL ) - return false; - - if ( pPlayer->ArmorValue() ) - return false; - - float flMaxHealth = pPlayer->GetMaxHealth(); - if ( flMaxHealth == 0.0f ) - return false; - - float flHealthPerc = (flMaxHealth != 0 ) ? (float) pPlayer->GetHealth() / flMaxHealth : 0.0f; - return ( flHealthPerc <= flPerc ); -} - -#define VORT_START_EXTRACT_SENTENCE 500 -#define VORT_FINISH_EXTRACT_SENTENCE 501 - -//------------------------------------------------------------------------------ -// Purpose: Make the vort speak a line -//------------------------------------------------------------------------------ -void CNPC_Vortigaunt::SpeakSentence( int sentenceType ) -{ - if (sentenceType == VORT_START_EXTRACT_SENTENCE) - { - Speak( VORT_EXTRACT_START ); - } - else if (sentenceType == VORT_FINISH_EXTRACT_SENTENCE) - { - Speak( VORT_EXTRACT_FINISH ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::StartTask( const Task_t *pTask ) -{ - switch ( pTask->iTask) - { - - case TASK_ANNOUNCE_ATTACK: - { - // We override this to add our innate weapon - if ( m_AnnounceAttackTimer.Expired() ) - { - if ( SpeakIfAllowed( TLK_ATTACKING, "attacking_with_weapon:zap" ) ) - { - m_AnnounceAttackTimer.Set( 10, 30 ); - } - } - - BaseClass::StartTask( pTask ); - break; - } - - // Sets our target to the entity that we cached earlier. - case TASK_VORTIGAUNT_GET_HEAL_TARGET: - { - if ( m_hHealTarget == NULL ) - { - TaskFail( FAIL_NO_TARGET ); - } - else - { - SetTarget( m_hHealTarget ); - TaskComplete(); - } - - break; - } - - case TASK_VORTIGAUNT_EXTRACT_WARMUP: - { - ResetIdealActivity( (Activity) ACT_VORTIGAUNT_TO_ACTION ); - break; - } - - case TASK_VORTIGAUNT_EXTRACT: - { - SetActivity( (Activity) ACT_RANGE_ATTACK1 ); - break; - } - - case TASK_VORTIGAUNT_EXTRACT_COOLDOWN: - { - ResetIdealActivity( (Activity)ACT_VORTIGAUNT_TO_IDLE ); - break; - } - - case TASK_VORTIGAUNT_FIRE_EXTRACT_OUTPUT: - { - // Cheat, and fire both outputs - m_OnFinishedExtractingBugbait.FireOutput( this, this ); - TaskComplete(); - break; - } - - case TASK_VORTIGAUNT_HEAL: - { - // Start the layer up and give it a higher priority than normal - int nLayer = AddGesture( (Activity) ACT_VORTIGAUNT_HEAL ); - SetLayerPriority( nLayer, 1 ); - - m_eHealState = HEAL_STATE_WARMUP; - - CBasePlayer *pPlayer = ToBasePlayer( m_hHealTarget ); - if ( pPlayer == NULL ) - { - TaskFail( "NULL Player in heal schedule!\n" ); - return; - } - - // Figure out how many tokens to spawn - float flArmorDelta = (float) sk_vortigaunt_armor_charge.GetInt() - pPlayer->ArmorValue(); - m_nNumTokensToSpawn = (int)ceil( flArmorDelta / sk_vortigaunt_armor_charge_per_token.GetInt() ); - - // If we're forced to recharge, then at least send one - if ( m_bForceArmorRecharge && m_nNumTokensToSpawn <= 0 ) - m_nNumTokensToSpawn = 1; - - TaskComplete(); - break; - } - - case TASK_VORTIGAUNT_WAIT_FOR_PLAYER: - { - // Wait for the player to get near (before starting the bugbait sequence) - break; - } - - case TASK_VORTIGAUNT_DISPEL_ANTLIONS: - { - if ( IsOkToCombatSpeak() ) - { - Speak( TLK_VORTIGAUNT_DISPEL ); - } - - ResetIdealActivity( (Activity) ACT_VORTIGAUNT_DISPEL ); - break; - } - - default: - { - BaseClass::StartTask( pTask ); - break; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::RunTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_RANGE_ATTACK1: - { - // If our enemy is gone, dead or out of sight, pick a new one (only if we're not delaying this behavior) - if ( ( HasCondition( COND_ENEMY_OCCLUDED ) || - GetEnemy() == NULL || - GetEnemy()->IsAlive() == false ) && - m_flAimDelay < gpGlobals->curtime ) - { - CBaseEntity *pNewEnemy = BestEnemy(); - if ( pNewEnemy != NULL ) - { - SetEnemy( pNewEnemy ); - SetState( NPC_STATE_COMBAT ); - } - } - - BaseClass::RunTask( pTask ); - break; - } - - case TASK_VORTIGAUNT_EXTRACT_WARMUP: - { - if ( IsActivityFinished() ) - { - TaskComplete(); - } - break; - } - - case TASK_VORTIGAUNT_EXTRACT: - { - if ( IsActivityFinished() ) - { - TaskComplete(); - } - break; - } - - case TASK_VORTIGAUNT_EXTRACT_COOLDOWN: - { - if ( IsActivityFinished() ) - { - m_bExtractingBugbait = false; - TaskComplete(); - } - break; - } - - case TASK_VORTIGAUNT_WAIT_FOR_PLAYER: - { - // Wait for the player to get near (before starting the bugbait sequence) - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer != NULL ) - { - GetMotor()->SetIdealYawToTargetAndUpdate( pPlayer->GetAbsOrigin(), AI_KEEP_YAW_SPEED ); - SetTurnActivity(); - if ( GetMotor()->DeltaIdealYaw() < 10 ) - { - // Wait for the player to get close enough - if ( ( GetAbsOrigin() - pPlayer->GetAbsOrigin() ).LengthSqr() < Square(32*12) ) - { - TaskComplete(); - } - } - } - else - { - TaskFail( FAIL_NO_PLAYER ); - } - break; - } - - case TASK_VORTIGAUNT_DISPEL_ANTLIONS: - { - if ( IsSequenceFinished() ) - { - TaskComplete(); - } - - break; - } - - default: - { - BaseClass::RunTask( pTask ); - break; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::AlertSound( void ) -{ - if ( GetEnemy() != NULL && IsOkToCombatSpeak() ) - { - Speak( VORT_ATTACK ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Allows each sequence to have a different turn rate associated with it. -// Output : float CNPC_Vortigaunt::MaxYawSpeed -//----------------------------------------------------------------------------- -float CNPC_Vortigaunt::MaxYawSpeed ( void ) -{ - switch ( GetActivity() ) - { - case ACT_IDLE: - return 35; - break; - case ACT_WALK: - return 35; - break; - case ACT_RUN: - return 45; - break; - default: - return 35; - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Normal facing position is the eyes, but with the vort eyes on such a -// long swing arm, this causes stability issues when an npc is trying to -// face a vort that's also turning their head -// Output : -//----------------------------------------------------------------------------- -Vector CNPC_Vortigaunt::FacingPosition( void ) -{ - return WorldSpaceCenter(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Normal body target is the mid-point between the center and the eyes, but -// the vort's eyes are so far offset, that this is usually in the middle of -// empty space -// Output : -//----------------------------------------------------------------------------- - -Vector CNPC_Vortigaunt::BodyTarget( const Vector &posSrc, bool bNoisy ) -{ - Vector low = WorldSpaceCenter() - ( WorldSpaceCenter() - GetAbsOrigin() ) * .25; - - Vector high; - int iBone = LookupBone( "ValveBiped.neck1" ); - if (iBone >= 0) - { - QAngle angHigh; - GetBonePosition( iBone, high, angHigh ); - } - else - { - high = WorldSpaceCenter(); - } - - Vector delta = high - low; - Vector result; - if ( bNoisy ) - { - // bell curve - float rand1 = random->RandomFloat( 0.0, 0.5 ); - float rand2 = random->RandomFloat( 0.0, 0.5 ); - result = low + delta * rand1 + delta * rand2; - } - else - result = low + delta * 0.5; - - return result; -} - -//----------------------------------------------------------------------------- -// Purpose: Try a more predictive approach -//----------------------------------------------------------------------------- -bool CNPC_Vortigaunt::InnateWeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions ) -{ - // Try and figure out a rough idea of where we'll be after a certain time delta and base our - // conditions on that instead. This is necessary because the vortigaunt takes a long time to - // deliver his attack and looks very strange if he starts to attack when he'd never be able to hit - // due to movement. - - const float flTimeDelta = 0.5f; - Vector vecNewOwnerPos; - Vector vecNewTargetPos; - UTIL_PredictedPosition( this, flTimeDelta, &vecNewOwnerPos ); - UTIL_PredictedPosition( GetEnemy(), flTimeDelta, &vecNewTargetPos ); - - Vector vecDelta = vecNewTargetPos - GetEnemy()->GetAbsOrigin(); - Vector vecFinalTargetPos = GetEnemy()->BodyTarget( vecNewOwnerPos ) + vecDelta; - - // Debug data - /* - NDebugOverlay::Box( GetEnemy()->BodyTarget( vecNewOwnerPos ), -Vector(4,4,4), Vector(4,4,4), 255, 0, 0, 0, 3.0f ); - NDebugOverlay::Box( vecFinalTargetPos, -Vector(4,4,4), Vector(4,4,4), 255, 255, 0, 0, 3.0f ); - NDebugOverlay::HorzArrow( GetEnemy()->BodyTarget( vecNewOwnerPos ), vecFinalTargetPos, 12.0f, 255, 0, 0, 16.0f, true, 3.0f ); - NDebugOverlay::HorzArrow( vecNewOwnerPos, GetEnemy()->BodyTarget( vecNewOwnerPos ), 8.0f, 255, 255, 0, 32.0f, true, 3.0f ); - */ - - return BaseClass::InnateWeaponLOSCondition( vecNewOwnerPos, vecFinalTargetPos, bSetConditions ); -} - -//------------------------------------------------------------------------------ -// Purpose : For innate range attack -//------------------------------------------------------------------------------ -int CNPC_Vortigaunt::RangeAttack1Conditions( float flDot, float flDist ) -{ - if ( GetEnemy() == NULL ) - return COND_NONE; - - if ( gpGlobals->curtime < m_flNextAttack ) - return COND_NONE; - - // Don't do shooting while playing a scene - if ( IsCurSchedule( SCHED_SCENE_GENERIC ) ) - return COND_NONE; - - // dvs: Allow up-close range attacks for episodic as the vort's melee - // attack is rather ineffective. -#ifndef HL2_EPISODIC - if ( flDist <= 70 ) - { - return( COND_TOO_CLOSE_TO_ATTACK ); - } - else -#else - if ( flDist < 32.0f ) - return COND_TOO_CLOSE_TO_ATTACK; -#endif // HL2_EPISODIC - if ( flDist > InnateRange1MaxRange() ) - { - return( COND_TOO_FAR_TO_ATTACK ); - } - else if ( flDot < 0.65 ) - { - return( COND_NOT_FACING_ATTACK ); - } - -#ifdef HL2_EPISODIC - - // Do an extra check for workers near myself or the player - if ( IsAntlionWorker( GetEnemy() ) ) - { - // See if it's too close to me - if ( ( GetAbsOrigin() - GetEnemy()->GetAbsOrigin() ).LengthSqr() < Square( AntlionWorkerBurstRadius() ) ) - return COND_TOO_CLOSE_TO_ATTACK; - - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer && ( pPlayer->GetAbsOrigin() - GetEnemy()->GetAbsOrigin() ).LengthSqr() < Square( AntlionWorkerBurstRadius() ) ) - { - // Warn the player to get away! - CFmtStrN<128> modifiers( "antlion_worker:true" ); - SpeakIfAllowed( TLK_DANGER, modifiers ); - return COND_NONE; - } - } - -#endif // HL2_EPISODIC - - return COND_CAN_RANGE_ATTACK1; -} - -//----------------------------------------------------------------------------- -// Purpose: Test for close-up dispel -//----------------------------------------------------------------------------- -int CNPC_Vortigaunt::MeleeAttack1Conditions( float flDot, float flDist ) -{ - if ( m_flDispelTestTime > gpGlobals->curtime ) - return COND_NONE; - - m_flDispelTestTime = gpGlobals->curtime + 1.0f; - - if ( GetEnemy() && GetEnemy()->Classify() == CLASS_ANTLION ) - { - if ( NumAntlionsInRadius(128) > 3 ) - { - m_flDispelTestTime = gpGlobals->curtime + 15.0f; - return COND_VORTIGAUNT_DISPEL_ANTLIONS; - } - } - - return COND_NONE; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flRadius - -// Output : int -//----------------------------------------------------------------------------- -int CNPC_Vortigaunt::NumAntlionsInRadius( float flRadius ) -{ - CBaseEntity *sEnemySearch[16]; - int nNumAntlions = 0; - int nNumEnemies = UTIL_EntitiesInBox( sEnemySearch, ARRAYSIZE(sEnemySearch), GetAbsOrigin()-Vector(flRadius,flRadius,flRadius), GetAbsOrigin()+Vector(flRadius,flRadius,flRadius), FL_NPC ); - for ( int i = 0; i < nNumEnemies; i++ ) - { - // We only care about antlions - if ( sEnemySearch[i] == NULL || sEnemySearch[i]->Classify() != CLASS_ANTLION ) - continue; - - nNumAntlions++; - } - - return nNumAntlions; -} - -//----------------------------------------------------------------------------- -// Purpose: Used for a more powerful, concussive blast -//----------------------------------------------------------------------------- -int CNPC_Vortigaunt::RangeAttack2Conditions( float flDot, float flDist ) -{ - return COND_NONE; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::HandleAnimEvent( animevent_t *pEvent ) -{ - // Start our heal glows (choreo driven) - if ( pEvent->event == AE_VORTIGAUNT_START_HEAL_GLOW ) - { - StartHandGlow( VORTIGAUNT_BEAM_HEAL, atoi( pEvent->options ) ); - return; - } - - // Stop our heal glows (choreo driven) - if ( pEvent->event == AE_VORTIGAUNT_STOP_HEAL_GLOW ) - { - EndHandGlow(); - return; - } - - // Start our hurt glows (choreo driven) - if ( pEvent->event == AE_VORTIGAUNT_START_HURT_GLOW ) - { - StartHandGlow( VORTIGAUNT_BEAM_DISPEL, atoi( pEvent->options ) ); - return; - } - - // Stop our hurt glows (choreo driven) - if ( pEvent->event == AE_VORTIGAUNT_STOP_HURT_GLOW ) - { - EndHandGlow(); - return; - } - - // Start our dispel effect - if ( pEvent->event == AE_VORTIGAUNT_START_DISPEL ) - { - StartHandGlow( VORTIGAUNT_BEAM_DISPEL, HAND_LEFT ); - StartHandGlow( VORTIGAUNT_BEAM_DISPEL, HAND_RIGHT ); - - // Boom! - //EmitSound( "NPC_Vortigaunt.DispelImpact" ); - CSoundParameters params; - if ( GetParametersForSound( "NPC_Vortigaunt.DispelImpact", params, NULL ) ) - { - CPASAttenuationFilter filter( this ); - EmitSound_t ep( params ); - ep.m_nChannel = CHAN_BODY; - EmitSound( filter, entindex(), ep ); - } - return; - } - - if ( pEvent->event == AE_VORTIGAUNT_ACCEL_DISPEL ) - { - // TODO: Increase the size? - return; - } - - // Kaboom! - if ( pEvent->event == AE_VORTIGAUNT_DISPEL ) - { - DispelAntlions( GetAbsOrigin(), 400.0f ); - return; - } - - // Start of our heal loop - if ( pEvent->event == AE_VORTIGAUNT_HEAL_PAUSE ) - { - StartHealing(); - return; - } - - if ( pEvent->event == AE_VORTIGAUNT_ZAP_POWERUP ) - { - if ( m_fGlowChangeTime > gpGlobals->curtime ) - return; - - int nHand = 0; - if ( pEvent->options ) - { - nHand = atoi( pEvent->options ); - } - - if ( ( nHand == HAND_LEFT ) || (nHand == HAND_BOTH ) ) - { - ArmBeam( VORTIGAUNT_BEAM_ZAP, HAND_LEFT ); - } - - if ( ( nHand == HAND_RIGHT ) || (nHand == HAND_BOTH ) ) - { - ArmBeam( VORTIGAUNT_BEAM_ZAP, HAND_RIGHT ); - } - - // Make hands glow if not already glowing - if ( m_fGlowAge == 0 ) - { - if ( ( nHand == HAND_LEFT ) || (nHand == HAND_BOTH ) ) - { - StartHandGlow( VORTIGAUNT_BEAM_ZAP, HAND_LEFT ); - } - - if ( ( nHand == HAND_RIGHT ) || (nHand == HAND_BOTH ) ) - { - StartHandGlow( VORTIGAUNT_BEAM_ZAP, HAND_RIGHT ); - } - m_fGlowAge = 1; - } - - CPASAttenuationFilter filter( this ); - - CSoundParameters params; - if ( GetParametersForSound( "NPC_Vortigaunt.ZapPowerup", params, NULL ) ) - { - EmitSound_t ep( params ); - //ep.m_nPitch = 100 + m_iBeams * 10; - ep.m_nPitch = 150; - - EmitSound( filter, entindex(), ep ); - - m_bStopLoopingSounds = true; - } - return; - } - - if ( pEvent->event == AE_VORTIGAUNT_ZAP_SHOOT ) - { - ClearBeams(); - - ClearMultiDamage(); - - int nHand = 0; - if ( pEvent->options ) - { - nHand = atoi( pEvent->options ); - } - - if ( ( nHand == HAND_LEFT ) || (nHand == HAND_BOTH ) ) - { - ZapBeam( HAND_LEFT ); - } - - if ( ( nHand == HAND_RIGHT ) || (nHand == HAND_BOTH ) ) - { - ZapBeam( HAND_RIGHT ); - } - - EndHandGlow(); - - EmitSound( "NPC_Vortigaunt.ClawBeam" ); - m_bStopLoopingSounds = true; - ApplyMultiDamage(); - - // Suppress our aiming until we're done with the animation - m_flAimDelay = gpGlobals->curtime + 0.75f; - - if ( m_bExtractingBugbait ) - { - // Spawn bugbait! - CBaseCombatWeapon *pWeapon = Weapon_Create( "weapon_bugbait" ); - if ( pWeapon ) - { - // Starting above the body, spawn closer and closer to the vort until it's clear - Vector vecSpawnOrigin = GetTarget()->WorldSpaceCenter() + Vector(0, 0, 32); - int iNumAttempts = 4; - Vector vecToVort = (WorldSpaceCenter() - vecSpawnOrigin); - float flDistance = VectorNormalize( vecToVort ) / (iNumAttempts-1); - int i = 0; - for (; i < iNumAttempts; i++ ) - { - trace_t tr; - CTraceFilterSkipTwoEntities traceFilter( GetTarget(), this, COLLISION_GROUP_NONE ); - AI_TraceLine( vecSpawnOrigin, vecSpawnOrigin, MASK_SHOT, &traceFilter, &tr ); - - if ( tr.fraction == 1.0 && !tr.m_pEnt ) - { - // Make sure it can fit there - AI_TraceHull( vecSpawnOrigin, vecSpawnOrigin, -Vector(16,16,16), Vector(16,16,48), MASK_SHOT, &traceFilter, &tr ); - if ( tr.fraction == 1.0 && !tr.m_pEnt ) - break; - } - - //NDebugOverlay::Box( vecSpawnOrigin, pWeapon->WorldAlignMins(), pWeapon->WorldAlignMins(), 255,0,0, 64, 100 ); - - // Move towards the vort - vecSpawnOrigin = vecSpawnOrigin + (vecToVort * flDistance); - } - - // HACK: If we've still failed, just spawn it on the player - if ( i == iNumAttempts ) - { - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer ) - { - vecSpawnOrigin = pPlayer->WorldSpaceCenter(); - } - } - - //NDebugOverlay::Box( vecSpawnOrigin, -Vector(20,20,20), Vector(20,20,20), 0,255,0, 64, 100 ); - - pWeapon->SetAbsOrigin( vecSpawnOrigin ); - pWeapon->Drop( Vector(0,0,1) ); - } - - CEffectData data; - - data.m_vOrigin = GetTarget()->WorldSpaceCenter(); - data.m_vNormal = WorldSpaceCenter() - GetTarget()->WorldSpaceCenter(); - VectorNormalize( data.m_vNormal ); - - data.m_flScale = 4; - - DispatchEffect( "AntlionGib", data ); - } - - // Stagger the next time we can attack - m_flNextAttack = gpGlobals->curtime + random->RandomFloat( 2.0f, 3.0f ); - return; - } - - if ( pEvent->event == AE_VORTIGAUNT_ZAP_DONE ) - { - ClearBeams(); - return; - } - - if ( pEvent->event == AE_VORTIGAUNT_HEAL_STARTGLOW ) - { - // Make hands glow - StartHandGlow( VORTIGAUNT_BEAM_HEAL, HAND_RIGHT ); - m_eHealState = HEAL_STATE_WARMUP; - return; - } - - if ( pEvent->event == AE_VORTIGAUNT_HEAL_STARTSOUND ) - { - CPASAttenuationFilter filter( this ); - - CSoundParameters params; - if ( GetParametersForSound( "NPC_Vortigaunt.StartHealLoop", params, NULL ) ) - { - EmitSound_t ep( params ); - //ep.m_nPitch = 100 + m_iBeams * 10; - ep.m_nPitch = 150; - - EmitSound( filter, entindex(), ep ); - m_bStopLoopingSounds = true; - } - return; - } - - if ( pEvent->event == AE_VORTIGAUNT_SWING_SOUND ) - { - EmitSound( "NPC_Vortigaunt.Swing" ); - return; - } - - if ( pEvent->event == AE_VORTIGAUNT_SHOOT_SOUNDSTART ) - { - if ( m_fGlowChangeTime > gpGlobals->curtime ) - return; - - CPASAttenuationFilter filter( this ); - CSoundParameters params; - if ( GetParametersForSound( "NPC_Vortigaunt.StartShootLoop", params, NULL ) ) - { - EmitSound_t ep( params ); - //ep.m_nPitch = 100 + m_iBeams * 10; - ep.m_nPitch = 150; - - EmitSound( filter, entindex(), ep ); - m_bStopLoopingSounds = true; - } - return; - } - - if ( pEvent->event == AE_NPC_LEFTFOOT ) - { - EmitSound( "NPC_Vortigaunt.FootstepLeft", pEvent->eventtime ); - return; - } - - if ( pEvent->event == AE_NPC_RIGHTFOOT ) - { - EmitSound( "NPC_Vortigaunt.FootstepRight", pEvent->eventtime ); - return; - } - - BaseClass::HandleAnimEvent( pEvent ); -} - - -//------------------------------------------------------------------------------ -// Purpose : Turn blue or green -//------------------------------------------------------------------------------ -void CNPC_Vortigaunt::InputTurnBlue( inputdata_t &data ) -{ - bool goBlue = data.value.Bool(); - if (goBlue != m_bIsBlue) - { - m_bIsBlue = goBlue; - m_flBlueEndFadeTime = gpGlobals->curtime + VORTIGAUNT_BLUE_FADE_TIME; - } -} - -//------------------------------------------------------------------------------ -// Purpose : Turn blue or green -//------------------------------------------------------------------------------ -void CNPC_Vortigaunt::InputTurnBlack( inputdata_t &data ) -{ - bool goBlack = data.value.Bool(); - if (goBlack != m_bIsBlack) - { - m_bIsBlack = goBlack; - } -} - -//------------------------------------------------------------------------------ -// Purpose : Translate some activites for the Vortigaunt -//------------------------------------------------------------------------------ -Activity CNPC_Vortigaunt::NPC_TranslateActivity( Activity eNewActivity ) -{ - // This is a hack solution for the Vort carrying Alyx in Ep2 - if ( IsCarryingNPC() ) - { - if ( eNewActivity == ACT_IDLE ) - return ACT_IDLE_CARRY; - - if ( eNewActivity == ACT_WALK || eNewActivity == ACT_WALK_AIM || eNewActivity == ACT_RUN || eNewActivity == ACT_RUN_AIM ) - return ACT_WALK_CARRY; - } - - // NOTE: This is a stand-in until the readiness system can handle non-weapon holding NPC's - if ( eNewActivity == ACT_IDLE ) - { - // More than relaxed means we're stimulated - if ( GetReadinessLevel() >= AIRL_STIMULATED ) - return ACT_IDLE_STIMULATED; - } - - if ( eNewActivity == ACT_RANGE_ATTACK2 ) - return (Activity) ACT_VORTIGAUNT_DISPEL; - - return BaseClass::NPC_TranslateActivity( eNewActivity ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::UpdateOnRemove( void) -{ - ClearBeams(); - ClearHandGlow(); - - // Chain at end to mimic destructor unwind order - BaseClass::UpdateOnRemove(); -} - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CNPC_Vortigaunt::Event_Killed( const CTakeDamageInfo &info ) -{ - ClearBeams(); - ClearHandGlow(); - - BaseClass::Event_Killed( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::Spawn( void ) -{ -#if !defined( HL2_EPISODIC ) - // Disable back-away - AddSpawnFlags( SF_NPC_NO_PLAYER_PUSHAWAY ); -#endif // HL2_EPISODIC - - // Allow multiple models (for slaves), but default to vortigaunt.mdl - const char *szModel = (char *)STRING( GetModelName() ); - if (!szModel || !*szModel) - { - szModel = "models/vortigaunt.mdl"; - SetModelName( AllocPooledString(szModel) ); - } - - BaseClass::Spawn(); - - m_HackedGunPos.x = 0.0f; - m_HackedGunPos.y = 0.0f; - m_HackedGunPos.z = 48.0f; - - SetHullType( HULL_WIDE_HUMAN ); - SetHullSizeNormal(); - - m_bloodColor = BLOOD_COLOR_GREEN; - m_iHealth = sk_vortigaunt_health.GetFloat(); - SetViewOffset( Vector ( 0, 0, 64 ) );// position of the eyes relative to monster's origin. - - CapabilitiesAdd( bits_CAP_INNATE_MELEE_ATTACK1 | bits_CAP_INNATE_RANGE_ATTACK1 ); - CapabilitiesRemove( bits_CAP_USE_SHOT_REGULATOR ); - - m_flEyeIntegRate = 0.6f; // Got a big eyeball so turn it slower - m_bForceArmorRecharge = false; - m_flHealHinderedTime = 0.0f; - - m_nCurGlowIndex = 0; - - m_bStopLoopingSounds = false; - - m_iLeftHandAttachment = LookupAttachment( VORTIGAUNT_LEFT_CLAW ); - m_iRightHandAttachment = LookupAttachment( VORTIGAUNT_RIGHT_CLAW ); - - NPCInit(); - - SetUse( &CNPC_Vortigaunt::Use ); - - // Setup our re-fire times when moving and shooting - GetShotRegulator()->SetBurstInterval( 2.0f, 2.0f ); - GetShotRegulator()->SetBurstShotCountRange( 1, 1 ); - GetShotRegulator()->SetRestInterval( 2.0f, 2.0f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::Precache() -{ - UTIL_PrecacheOther( "vort_charge_token" ); - - PrecacheModel( STRING( GetModelName() ) ); - - m_nLightningSprite = PrecacheModel("sprites/lgtning.vmt"); - PrecacheModel("sprites/vortring1.vmt"); - - // HACK: Only precache this for EP2 because reslists cannot be rebuilt - 08/22/07 - jdw - if ( hl2_episodic.GetBool() ) - { - char modDir[MAX_PATH]; - if ( UTIL_GetModDir( modDir, sizeof(modDir) ) ) - { - if ( !Q_stricmp( modDir, "ep2" ) ) - { - PrecacheMaterial( "effects/rollerglow" ); - } - } - } - - PrecacheScriptSound( "NPC_Vortigaunt.SuitOn" ); - PrecacheScriptSound( "NPC_Vortigaunt.SuitCharge" ); - PrecacheScriptSound( "NPC_Vortigaunt.ZapPowerup" ); - PrecacheScriptSound( "NPC_Vortigaunt.ClawBeam" ); - PrecacheScriptSound( "NPC_Vortigaunt.StartHealLoop" ); - PrecacheScriptSound( "NPC_Vortigaunt.Swing" ); - PrecacheScriptSound( "NPC_Vortigaunt.StartShootLoop" ); - PrecacheScriptSound( "NPC_Vortigaunt.FootstepLeft" ); - PrecacheScriptSound( "NPC_Vortigaunt.FootstepRight" ); - PrecacheScriptSound( "NPC_Vortigaunt.DispelStart" ); - PrecacheScriptSound( "NPC_Vortigaunt.DispelImpact" ); - PrecacheScriptSound( "NPC_Vortigaunt.Explode" ); - - PrecacheParticleSystem( "vortigaunt_beam" ); - PrecacheParticleSystem( "vortigaunt_beam_charge" ); - PrecacheParticleSystem( "vortigaunt_hand_glow" ); - - PrecacheMaterial( "sprites/light_glow02_add" ); - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: Interpret a player +USE'ing us -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - m_OnPlayerUse.FireOutput( pActivator, pCaller ); - - // Foremost, try and heal a wounded player - if ( HealBehaviorAvailable() ) - { - // See if we should heal the player - CBaseEntity *pHealTarget = FindHealTarget(); - if ( pHealTarget != NULL ) - { - SetCondition( COND_PROVOKED ); - SetHealTarget( pHealTarget, true ); - return; - } - } - - // Next, try to speak the +USE concept - if ( IsOkToSpeakInResponseToPlayer() && m_eHealState == HEAL_STATE_NONE ) - { - if ( Speak( TLK_USE ) == false ) - { - // If we haven't said hi, say that first - if ( !SpokeConcept( TLK_HELLO ) ) - { - Speak( TLK_HELLO ); - } - else - { - Speak( TLK_IDLE ); - } - } - else - { - // Don't say hi after you've said your +USE speech - SetSpokeConcept( TLK_HELLO, NULL ); - } - } -} - -//========================================================= -// PainSound -//========================================================= -void CNPC_Vortigaunt::PainSound( const CTakeDamageInfo &info ) -{ - if ( gpGlobals->curtime < m_flPainTime ) - return; - - m_flPainTime = gpGlobals->curtime + random->RandomFloat(0.5, 0.75); - - Speak( VORT_PAIN ); -} - -//========================================================= -// DeathSound -//========================================================= -void CNPC_Vortigaunt::DeathSound( const CTakeDamageInfo &info ) -{ - Speak( VORT_DIE ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::TraceAttack( const CTakeDamageInfo &inputInfo, const Vector &vecDir, trace_t *ptr ) -{ - CTakeDamageInfo info = inputInfo; - - if ( (info.GetDamageType() & DMG_SHOCK) && FClassnameIs( info.GetAttacker(), GetClassname() ) ) - { - // mask off damage from other vorts for now - info.SetDamage( 0.01 ); - } - - switch( ptr->hitgroup) - { - case HITGROUP_CHEST: - case HITGROUP_STOMACH: - if (info.GetDamageType() & (DMG_BULLET | DMG_SLASH | DMG_BLAST)) - { - info.ScaleDamage( 0.5f ); - } - break; - case 10: - if (info.GetDamageType() & (DMG_BULLET | DMG_SLASH | DMG_CLUB)) - { - info.SetDamage( info.GetDamage() - 20 ); - if (info.GetDamage() <= 0) - { - g_pEffects->Ricochet( ptr->endpos, (vecDir*-1.0f) ); - info.SetDamage( 0.01 ); - } - } - // always a head shot - ptr->hitgroup = HITGROUP_HEAD; - break; - } - - BaseClass::TraceAttack( info, vecDir, ptr ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_Vortigaunt::TranslateSchedule( int scheduleType ) -{ - switch( scheduleType ) - { - case SCHED_ALERT_FACE_BESTSOUND: - return SCHED_VORT_ALERT_FACE_BESTSOUND; - break; - - case SCHED_TAKE_COVER_FROM_BEST_SOUND: - - // Stand still if we're in the middle of an attack. Failing to do so can make us miss our shot! - if ( IsPlayingGesture( ACT_GESTURE_RANGE_ATTACK1 ) ) - return SCHED_COMBAT_FACE; - - return SCHED_VORT_FLEE_FROM_BEST_SOUND; - break; - - case SCHED_COWER: - case SCHED_PC_COWER: - // Vort doesn't have cower animations - return SCHED_COMBAT_FACE; - break; - - case SCHED_RANGE_ATTACK1: - - // If we're told to fire when we're already firing, just face our target. If we don't do this, we get a bizarre double-shot - if ( IsPlayingGesture( ACT_GESTURE_RANGE_ATTACK1 ) ) - return SCHED_COMBAT_FACE; - - // Otherwise we use our own schedule to attack - return SCHED_VORTIGAUNT_RANGE_ATTACK; - break; - - /* - case SCHED_CHASE_ENEMY: - case SCHED_ESTABLISH_LINE_OF_FIRE: - case SCHED_ESTABLISH_LINE_OF_FIRE_FALLBACK: - - // Don't go running off after an enemy just because we're in an attack delay! This has to do with - // the base systems assuming that held weapons are driving certain decisions when this creature - // uses an innate ability. - if ( ( GetNextAttack() > gpGlobals->curtime ) && HasCondition( COND_ENEMY_TOO_FAR ) == false ) - return SCHED_COMBAT_FACE; - - break; - */ - } - - return BaseClass::TranslateSchedule( scheduleType ); -} - -//----------------------------------------------------------------------------- -// Purpose: Sets the heal target for the vort and preps him for completing the action -// Input : *pTarget - Target we're after -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::SetHealTarget( CBaseEntity *pTarget, bool bPlayerRequested ) -{ - SetCondition( COND_VORTIGAUNT_CAN_HEAL ); - OccupyStrategySlot( SQUAD_SLOT_HEAL_PLAYER ); - m_hHealTarget = pTarget; - m_bPlayerRequestedHeal = bPlayerRequested; -} - -//----------------------------------------------------------------------------- -// Purpose: Finds a player in range that can be healed -// Output : Target that can be healed -//----------------------------------------------------------------------------- -CBaseEntity *CNPC_Vortigaunt::FindHealTarget( void ) -{ - // Need to be looking at the player to decide to heal them. - //if ( HasCondition( COND_SEE_PLAYER ) == false ) - // return false; - - // Find a likely target in range - CBaseEntity *pEntity = PlayerInRange( GetAbsOrigin(), HEAL_SEARCH_RANGE ); - - // Make sure we can heal that target - if ( ShouldHealTarget( pEntity ) == false ) - return NULL; - - return pEntity; -} - -//----------------------------------------------------------------------------- -// Purpose: Whether or not the vort is able to attempt to heal targets -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Vortigaunt::HealBehaviorAvailable( void ) -{ - // Cannot already be healing - if ( m_eHealState != HEAL_STATE_NONE ) - return false; - - // Must be allowed to do this behavior - if ( m_bArmorRechargeEnabled == false ) - return false; - - // Don't interrupt a script - if ( IsInAScript() || m_NPCState == NPC_STATE_SCRIPT ) - return false; - - // Cannot interrupt bugbait extraction - if ( IsCurSchedule( SCHED_VORTIGAUNT_EXTRACT_BUGBAIT ) ) - return false; - - // Don't bother while we're under attack - if ( GetEnemy() != NULL ) - return false; - - // Can't heal if we're leading the player - if ( IsLeading() ) - return false; - - // Must be a valid squad activity to do - if ( IsStrategySlotRangeOccupied( SQUAD_SLOT_HEAL_PLAYER, SQUAD_SLOT_HEAL_PLAYER ) ) - return false; - - // Heal is valid - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Determines whether or not the -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Vortigaunt::ShouldHealTarget( CBaseEntity *pTarget ) -{ - // Must have a valid target - if ( pTarget == NULL ) - return false; - - // If we're scripting or waiting to run one, we won't heal a target - if ( IsInAScript() || HasSpawnFlags( SF_NPC_WAIT_FOR_SCRIPT ) ) - return false; - - // We only heal players - CBasePlayer *pPlayer = ToBasePlayer( pTarget ); - if ( pPlayer == NULL ) - return false; - - // Make sure the player's got a suit - if ( pPlayer->IsSuitEquipped() == false ) - return false; - - // Don't heal a target we can't see..? - if ( pPlayer->GetFlags() & FL_NOTARGET ) - return false; - - // See if the player needs armor - if ( pPlayer->ArmorValue() >= (sk_vortigaunt_armor_charge.GetFloat()*0.66f) ) - return false; - - // Must be alive! - if ( pPlayer->IsAlive() == false ) - return false; - - // Only consider things in here if the player is NOT at critical health or the heal is a passive one (not requested) - if ( PlayerBelowHealthPercentage( pPlayer, PLAYER_CRITICAL_HEALTH_PERC ) == false || m_bPlayerRequestedHeal ) - { - // Don't heal when fighting - if ( m_NPCState == NPC_STATE_COMBAT ) - return false; - - // No enemies - if ( GetEnemy() ) - return false; - - // No recent damage - if ( HasCondition( COND_LIGHT_DAMAGE ) || HasCondition( COND_HEAVY_DAMAGE ) ) - return false; - } - - // Allow the heal - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CNPC_Vortigaunt::SelectHealSchedule( void ) -{ - // If our lead behavior has a goal, don't wait around to heal anyone - if ( m_LeadBehavior.HasGoal() ) - return SCHED_NONE; - - // Break out of healing if a script has started - if ( IsInAScript() && m_bForceArmorRecharge == false ) - { - if ( m_eHealState != HEAL_STATE_NONE ) - { - StopHealing( true ); - } - - return SCHED_NONE; - } - - // Cannot already be healing the player - if ( m_hHealTarget != NULL ) - { - // For now, just grab the global, single player - CBasePlayer *pPlayer = ToBasePlayer( m_hHealTarget ); - - // Check for an interruption occurring - if ( PlayerBelowHealthPercentage( pPlayer, PLAYER_CRITICAL_HEALTH_PERC ) == false && HasCondition( COND_HEAVY_DAMAGE ) ) - { - StopHealing( true ); - return SCHED_NONE; - } - - // See if we're in an ideal position to heal - if ( m_eHealState != HEAL_STATE_HEALING && m_eHealState != HEAL_STATE_WARMUP && HasCondition( COND_VORTIGAUNT_HEAL_VALID ) ) - return SCHED_VORTIGAUNT_HEAL; - - // If the player is too far away or blocked, give chase - if ( HasCondition( COND_VORTIGAUNT_HEAL_TARGET_TOO_FAR ) || - HasCondition( COND_VORTIGAUNT_HEAL_TARGET_BLOCKED ) ) - return SCHED_VORTIGAUNT_RUN_TO_PLAYER; - - // Stand and face the player - if ( HasCondition( COND_VORTIGAUNT_HEAL_TARGET_BEHIND_US ) || HasCondition( COND_VORTIGAUNT_HEAL_VALID ) ) - return SCHED_VORTIGAUNT_FACE_PLAYER; - } - - return SCHED_NONE; -} - -//----------------------------------------------------------------------------- -// Purpose: Watch this function path for a route around our normal schedule changing callbacks -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::ClearSchedule( const char *szReason ) -{ - MaintainGlows(); - - BaseClass::ClearSchedule( szReason ); -} - -//----------------------------------------------------------------------------- -// Purpose: Watch our glows and turn them off appropriately -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::OnScheduleChange( void ) -{ - BaseClass::OnScheduleChange(); - - // If we're in the middle of healing, don't bother doing this - if ( m_eHealState != HEAL_STATE_NONE ) - return; - - // If we're changing sequences, always clear - EndHandGlow( VORTIGAUNT_BEAM_ALL ); - m_fGlowChangeTime = gpGlobals->curtime + 0.1f; // No more glows for this amount of time! -} - -//------------------------------------------------------------------------------ -// Purpose: Select a schedule -//------------------------------------------------------------------------------ -int CNPC_Vortigaunt::SelectSchedule( void ) -{ - // Always recharge in this case - if ( m_bForceArmorRecharge ) - { - m_flNextHealTime = 0; - int nSchedule = SelectHealSchedule(); - return nSchedule; - } - -#ifndef HL2_EPISODIC - if ( BehaviorSelectSchedule() ) - return BaseClass::SelectSchedule(); -#else - if ( IsInAScript() ) - return BaseClass::SelectSchedule(); -#endif - - // If we're currently supposed to be doing something scripted, do it immediately. - if ( m_bExtractingBugbait ) - return SCHED_VORTIGAUNT_EXTRACT_BUGBAIT; - - int schedule = SelectHealSchedule(); - if ( schedule != SCHED_NONE ) - return schedule; - - if ( HasCondition(COND_VORTIGAUNT_DISPEL_ANTLIONS ) ) - { - ClearCondition( COND_VORTIGAUNT_DISPEL_ANTLIONS ); - return SCHED_VORTIGAUNT_DISPEL_ANTLIONS; - } - - // Heal a player if they can be - if ( HasCondition( COND_VORTIGAUNT_CAN_HEAL ) ) - return SCHED_VORTIGAUNT_HEAL; - - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -int CNPC_Vortigaunt::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ) -{ - if ( failedSchedule == SCHED_BACK_AWAY_FROM_ENEMY ) - { - if ( GetEnemy() && GetSenses()->CanSeeEntity( GetEnemy() ) ) - { - return SCHED_RANGE_ATTACK1; - } - } - - return BaseClass::SelectFailSchedule( failedSchedule, failedTask, taskFailCode ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::DeclineFollowing( void ) -{ - Speak( VORT_POK ); -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if you're willing to be idly talked to by other friends. -//----------------------------------------------------------------------------- -bool CNPC_Vortigaunt::CanBeUsedAsAFriend( void ) -{ - // We don't want to be used if we're busy - if ( IsCurSchedule( SCHED_VORTIGAUNT_HEAL ) ) - return false; - - if ( IsCurSchedule( SCHED_VORTIGAUNT_EXTRACT_BUGBAIT ) ) - return false; - - return BaseClass::CanBeUsedAsAFriend(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -#define VORT_360_VIEW_DIST_SQR ((60*12)*(60*12)) -bool CNPC_Vortigaunt::FInViewCone( CBaseEntity *pEntity ) -{ - // Vort can see 360 degrees but only at limited distance - if( ( pEntity->IsNPC() || pEntity->IsPlayer() ) && pEntity->GetAbsOrigin().DistToSqr(GetAbsOrigin()) <= VORT_360_VIEW_DIST_SQR ) - return true; - - return BaseClass::FInViewCone( pEntity ); -} - -//----------------------------------------------------------------------------- -// Purpose: Start our heal loop -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::StartHealing( void ) -{ - // Find the layer and stop it from moving forward in the cycle - int nLayer = FindGestureLayer( (Activity) ACT_VORTIGAUNT_HEAL ); - SetLayerPlaybackRate( nLayer, 0.0f ); - - // We're now in the healing loop - m_eHealState = HEAL_STATE_HEALING; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::StopHealing( bool bInterrupt ) -{ - // Clear out our healing states - m_eHealState = HEAL_STATE_NONE; - m_bForceArmorRecharge = false; - m_hHealTarget = NULL; - - EndHandGlow( VORTIGAUNT_BEAM_HEAL ); - VacateStrategySlot(); - - // See if we're completely interrupting the heal or just ending normally - if ( bInterrupt ) - { - RemoveGesture( (Activity) ACT_VORTIGAUNT_HEAL ); - m_flNextHealTime = gpGlobals->curtime + 2.0f; - } - else - { - // Start our animation back up again - int nLayer = FindGestureLayer( (Activity) ACT_VORTIGAUNT_HEAL ); - SetLayerPlaybackRate( nLayer, 1.0f ); - - m_flNextHealTime = gpGlobals->curtime + VORTIGAUNT_HEAL_RECHARGE; - m_OnFinishedChargingTarget.FireOutput( this, this ); - } - - // Give us time to stop our animation before we start attacking (otherwise we get weird collisions) - SetNextAttack( gpGlobals->curtime + 2.0f ); -} - -//----------------------------------------------------------------------------- -// Purpose: Update our heal schedule and gestures if we're currently healing -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::MaintainHealSchedule( void ) -{ - // Need to be healing - if ( m_eHealState == HEAL_STATE_NONE ) - return; - - // For now, we only heal the player - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer == NULL ) - return; - - // FIXME: How can this happen? - if ( m_AssaultBehavior.GetOuter() != NULL ) - { - // Interrupt us on an urgent assault - if ( m_AssaultBehavior.IsRunning() && ( m_AssaultBehavior.IsUrgent() || m_AssaultBehavior.OnStrictAssault() ) ) - { - StopHealing( true ); - return; - } - } - - // Don't let us shoot while we're healing - GetShotRegulator()->FireNoEarlierThan( gpGlobals->curtime + 0.5f ); - - // If we're in the healing phase, heal our target (if able) - if ( m_eHealState == HEAL_STATE_HEALING ) - { - // FIXME: We need to have better logic controlling this - if ( HasCondition( COND_VORTIGAUNT_HEAL_VALID ) ) - { - if ( m_flNextHealTokenTime < gpGlobals->curtime ) - { - CBasePlayer *pPlayer = ToBasePlayer( m_hHealTarget ); - - // We're done, so stop playing the animation - if ( m_nNumTokensToSpawn <= 0 || ( m_bForceArmorRecharge == false && ( pPlayer && pPlayer->ArmorValue() >= sk_vortigaunt_armor_charge.GetInt() ) ) ) - { - m_flHealHinderedTime = 0.0f; - m_nNumTokensToSpawn = 0; - SpeakIfAllowed( VORT_CURESTOP ); - StopHealing( false ); - return; - } - - // Create a charge token - Vector vecHandPos; - QAngle vecHandAngles; - GetAttachment( m_iRightHandAttachment, vecHandPos, vecHandAngles ); - CVortigauntChargeToken::CreateChargeToken( vecHandPos, this, m_hHealTarget ); - m_flNextHealTokenTime = gpGlobals->curtime + random->RandomFloat( 0.5f, 1.0f ); - m_nNumTokensToSpawn--; - - // If we're stopping, delay our animation a bit so it's not so robotic - if ( m_nNumTokensToSpawn <= 0 ) - { - m_nNumTokensToSpawn = 0; - m_flNextHealTokenTime = gpGlobals->curtime + 1.0f; - } - } - } - else - { - /* - // NOTENOTE: It's better if the vort give up than ignore things around him to try and continue -- jdw - - // Increment a counter to let us know how long we've failed - m_flHealHinderedTime += gpGlobals->curtime - GetLastThink(); - - if ( m_flHealHinderedTime > 2.0f ) - { - // If too long, stop trying - StopHealing(); - } - */ - - bool bInterrupt = false; - if ( HasCondition( COND_NEW_ENEMY ) ) - { - bInterrupt = true; - } - - StopHealing( true ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -inline bool CNPC_Vortigaunt::InAttackSequence( void ) -{ - if ( m_MoveAndShootOverlay.IsMovingAndShooting() ) - return true; - - if ( GetActivity() == ACT_RANGE_ATTACK1 ) - return true; - - if ( GetActivity() == ACT_VORTIGAUNT_DISPEL ) - return true; - - if ( IsPlayingGesture( ACT_GESTURE_RANGE_ATTACK1 ) ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Watch our beams and make sure we don't leave them on mistakenly -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::MaintainGlows( void ) -{ - // Verify that if we're not in an attack gesture, that we're not doing an attack glow - if ( InAttackSequence() == false && m_eHealState == HEAL_STATE_NONE ) - { - EndHandGlow( VORTIGAUNT_BEAM_ALL ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Squelch looping sounds and glows after a restore. -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::OnRestore( void ) -{ - BaseClass::OnRestore(); - - m_bStopLoopingSounds = true; -} - -//----------------------------------------------------------------------------- -// Purpose: Do various non-schedule specific maintainence -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::PrescheduleThink( void ) -{ - // Update our healing (if active) - MaintainHealSchedule(); - - // Let the base class have a go - BaseClass::PrescheduleThink(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &move - -// flInterval - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Vortigaunt::OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval ) -{ - // If we're in our aiming gesture, then always face our target as we run - Activity nActivity = NPC_TranslateActivity( ACT_GESTURE_RANGE_ATTACK1 ); - if ( IsPlayingGesture( nActivity ) || - IsCurSchedule( SCHED_PC_MOVE_TOWARDS_COVER_FROM_BEST_SOUND ) || - IsCurSchedule( SCHED_VORT_FLEE_FROM_BEST_SOUND ) || - IsCurSchedule( SCHED_TAKE_COVER_FROM_BEST_SOUND ) ) - { - Vector vecEnemyLKP = GetEnemyLKP(); - AddFacingTarget( GetEnemy(), vecEnemyLKP, 1.0, 0.2 ); - } - - return BaseClass::OverrideMoveFacing( move, flInterval ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::BuildScheduleTestBits( void ) -{ - // Call to base - BaseClass::BuildScheduleTestBits(); - - // Allow healing to interrupt us if we're standing around - if ( IsCurSchedule( SCHED_IDLE_STAND ) || - IsCurSchedule( SCHED_ALERT_STAND ) ) - { - if ( m_eHealState == HEAL_STATE_NONE ) - { - SetCustomInterruptCondition( COND_VORTIGAUNT_CAN_HEAL ); - SetCustomInterruptCondition( COND_VORTIGAUNT_DISPEL_ANTLIONS ); - } - } - - // Always interrupt when healing - if ( m_eHealState != HEAL_STATE_NONE ) - { - // Interrupt if we're not already adjusting - if ( IsCurSchedule( SCHED_VORTIGAUNT_RUN_TO_PLAYER ) == false ) - { - SetCustomInterruptCondition( COND_VORTIGAUNT_HEAL_TARGET_TOO_FAR ); - SetCustomInterruptCondition( COND_VORTIGAUNT_HEAL_TARGET_BLOCKED ); - - // Interrupt if we're not already turning - if ( IsCurSchedule( SCHED_VORTIGAUNT_FACE_PLAYER ) == false ) - { - SetCustomInterruptCondition( COND_VORTIGAUNT_HEAL_TARGET_BEHIND_US ); - } - } - } - - if ( IsCurSchedule( SCHED_COMBAT_STAND ) ) - { - SetCustomInterruptCondition( COND_VORTIGAUNT_DISPEL_ANTLIONS ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Small beam from arm to nearby geometry -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::ArmBeam( int beamType, int nHand ) -{ - trace_t tr; - float flDist = 1.0; - int side = ( nHand == HAND_LEFT ) ? -1 : 1; - - Vector forward, right, up; - AngleVectors( GetLocalAngles(), &forward, &right, &up ); - Vector vecSrc = GetLocalOrigin() + up * 36 + right * side * 16 + forward * 32; - - for (int i = 0; i < 3; i++) - { - Vector vecAim = forward * random->RandomFloat( -1, 1 ) + right * side * random->RandomFloat( 0, 1 ) + up * random->RandomFloat( -1, 1 ); - trace_t tr1; - AI_TraceLine ( vecSrc, vecSrc + vecAim * (10*12), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr1); - - // Don't hit the sky - if ( tr1.surface.flags & SURF_SKY ) - continue; - - // Choose a farther distance if we have one - if ( flDist > tr1.fraction ) - { - tr = tr1; - flDist = tr.fraction; - } - } - - // Couldn't find anything close enough - if ( flDist == 1.0 ) - return; - - // Tell the client to start an arm beam - unsigned char uchAttachment = (nHand==HAND_LEFT) ? m_iLeftHandAttachment : m_iRightHandAttachment; - EntityMessageBegin( this, true ); - WRITE_BYTE( VORTFX_ARMBEAM ); - WRITE_LONG( entindex() ); - WRITE_BYTE( uchAttachment ); - WRITE_VEC3COORD( tr.endpos ); - WRITE_VEC3NORMAL( tr.plane.normal ); - MessageEnd(); -} - -//------------------------------------------------------------------------------ -// Purpose : Put glowing sprites on hands -//------------------------------------------------------------------------------ -void CNPC_Vortigaunt::StartHandGlow( int beamType, int nHand ) -{ - // We need this because there's a rare case where a scene can interrupt and turn off our hand glows, but are then - // turned back on in the same frame due to how animations are applied and anim events are executed after the AI frame. - if ( m_fGlowChangeTime > gpGlobals->curtime ) - return; - - switch( beamType ) - { - case VORTIGAUNT_BEAM_DISPEL: - case VORTIGAUNT_BEAM_HEAL: - case VORTIGAUNT_BEAM_ZAP: - { - // Validate the hand's range - if ( nHand >= (int)ARRAYSIZE( m_hHandEffect ) ) - return; - - // Start up - if ( m_hHandEffect[nHand] == NULL ) - { - // Create the token if it doesn't already exist - m_hHandEffect[nHand] = CVortigauntEffectDispel::CreateEffectDispel( GetAbsOrigin(), this, NULL ); - if ( m_hHandEffect[nHand] == NULL ) - return; - } - - // Stomp our settings - m_hHandEffect[nHand]->SetParent( this, (nHand==HAND_LEFT) ? m_iLeftHandAttachment : m_iRightHandAttachment ); - m_hHandEffect[nHand]->SetMoveType( MOVETYPE_NONE ); - m_hHandEffect[nHand]->SetLocalOrigin( Vector( 8.0f, 4.0f, 0.0f ) ); - } - break; - - case VORTIGAUNT_BEAM_ALL: - Assert( 0 ); - break; - } -} - -//------------------------------------------------------------------------------ -// Purpose: Fade glow from hands. -//------------------------------------------------------------------------------ -void CNPC_Vortigaunt::EndHandGlow( int beamType /*= VORTIGAUNT_BEAM_ALL*/ ) -{ - if ( m_hHandEffect[0] ) - { - m_hHandEffect[0]->FadeAndDie(); - m_hHandEffect[0] = NULL; - } - - if ( m_hHandEffect[1] ) - { - m_hHandEffect[1]->FadeAndDie(); - m_hHandEffect[1] = NULL; - } - - // Zap - if ( beamType == VORTIGAUNT_BEAM_ZAP || beamType == VORTIGAUNT_BEAM_ALL ) - { - m_fGlowAge = 0; - - // Stop our smaller beams as well - ClearBeams(); - } -} - -extern int ACT_ANTLION_ZAP_FLIP; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_Vortigaunt::IsValidEnemy( CBaseEntity *pEnemy ) -{ - if ( IsRoller( pEnemy ) ) - { - CAI_BaseNPC *pNPC = pEnemy->MyNPCPointer(); - if ( pNPC && pNPC->GetEnemy() != NULL ) - return true; - return false; - } - - // Wait until our animation is finished - if ( GetEnemy() == NULL && m_flAimDelay > gpGlobals->curtime ) - return false; - - return BaseClass::IsValidEnemy( pEnemy ); -} - -//----------------------------------------------------------------------------- -// Purpose: Creates a blast where the beam has struck a target -// Input : &vecOrigin - position to eminate from -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::CreateBeamBlast( const Vector &vecOrigin ) -{ - CSprite *pBlastSprite = CSprite::SpriteCreate( "sprites/vortring1.vmt", vecOrigin, true ); - if ( pBlastSprite != NULL ) - { - pBlastSprite->SetTransparency( kRenderTransAddFrameBlend, 255, 255, 255, 255, kRenderFxNone ); - pBlastSprite->SetBrightness( 255 ); - pBlastSprite->SetScale( random->RandomFloat( 1.0f, 1.5f ) ); - pBlastSprite->AnimateAndDie( 45.0f ); - pBlastSprite->EmitSound( "NPC_Vortigaunt.Explode" ); - } - - CPVSFilter filter( vecOrigin ); - te->GaussExplosion( filter, 0.0f, vecOrigin, Vector( 0, 0, 1 ), 0 ); -} - -#define COS_30 0.866025404f // sqrt(3) / 2 -#define COS_60 0.5 // sqrt(1) / 2 - -//----------------------------------------------------------------------------- -// Purpose: Heavy damage directly forward -// Input : nHand - Handedness of the beam -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::ZapBeam( int nHand ) -{ - Vector forward; - GetVectors( &forward, NULL, NULL ); - - Vector vecSrc = GetAbsOrigin() + GetViewOffset(); - Vector vecAim = GetShootEnemyDir( vecSrc, false ); // We want a clear shot to their core - - if ( GetEnemy() ) - { - Vector vecTarget = GetEnemy()->BodyTarget( vecSrc, false ); - - if ( g_debug_vortigaunt_aim.GetBool() ) - { - NDebugOverlay::Cross3D( vecTarget, 4.0f, 255, 0, 0, true, 10.0f ); - CBaseAnimating *pAnim = GetEnemy()->GetBaseAnimating(); - if ( pAnim ) - { - pAnim->DrawServerHitboxes( 10.0f ); - } - } - } - - // If we're too far off our center, the shot must miss! - if ( DotProduct( vecAim, forward ) < COS_60 ) - { - // Missed, so just shoot forward - vecAim = forward; - } - - trace_t tr; - - if ( m_bExtractingBugbait == true ) - { - CRagdollProp *pTest = dynamic_cast< CRagdollProp *>( GetTarget() ); - - if ( pTest ) - { - ragdoll_t *m_ragdoll = pTest->GetRagdoll(); - - if ( m_ragdoll ) - { - Vector vOrigin; - m_ragdoll->list[0].pObject->GetPosition( &vOrigin, 0 ); - - AI_TraceLine( vecSrc, vOrigin, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); - } - - CRagdollBoogie::Create( pTest, 200, gpGlobals->curtime, 1.0f ); - } - } - else - { - AI_TraceLine( vecSrc, vecSrc + ( vecAim * InnateRange1MaxRange() ), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); - } - - if ( g_debug_vortigaunt_aim.GetBool() ) - { - NDebugOverlay::Line( tr.startpos, tr.endpos, 255, 0, 0, true, 10.0f ); - } - - // Send a message to the client to create a "zap" beam - unsigned char uchAttachment = (nHand==HAND_LEFT) ? m_iLeftHandAttachment : m_iRightHandAttachment; - EntityMessageBegin( this, true ); - WRITE_BYTE( VORTFX_ZAPBEAM ); - WRITE_BYTE( uchAttachment ); - WRITE_VEC3COORD( tr.endpos ); - MessageEnd(); - - CBaseEntity *pEntity = tr.m_pEnt; - if ( pEntity != NULL && m_takedamage ) - { - if ( g_debug_vortigaunt_aim.GetBool() ) - { - NDebugOverlay::Box( tr.endpos, -Vector(2,2,2), Vector(2,2,2), 255, 0, 0, 8, 10.0f ); - } - - CTakeDamageInfo dmgInfo( this, this, sk_vortigaunt_dmg_zap.GetFloat(), DMG_SHOCK ); - dmgInfo.SetDamagePosition( tr.endpos ); - VectorNormalize( vecAim );// not a unit vec yet - // hit like a 5kg object flying 100 ft/s - dmgInfo.SetDamageForce( 5 * 100 * 12 * vecAim ); - - // Our zaps do special things to antlions - if ( FClassnameIs( pEntity, "npc_antlion" ) ) - { - // Make a worker flip instead of explode - if ( IsAntlionWorker( pEntity ) ) - { - CNPC_Antlion *pAntlion = static_cast(pEntity); - pAntlion->Flip(); - } - else - { - // Always gib the antlion hit! - dmgInfo.ScaleDamage( 4.0f ); - } - - // Look in a ring and flip other antlions nearby - DispelAntlions( tr.endpos, 200.0f, false ); - } - - // Send the damage to the recipient - pEntity->DispatchTraceAttack( dmgInfo, vecAim, &tr ); - } - - // Create a cover for the end of the beam - CreateBeamBlast( tr.endpos ); -} - -//------------------------------------------------------------------------------ -// Purpose: Clear glow from hands immediately -//------------------------------------------------------------------------------ -void CNPC_Vortigaunt::ClearHandGlow( void ) -{ - if ( m_hHandEffect[0] != NULL ) - { - UTIL_Remove( m_hHandEffect[0] ); - m_hHandEffect[0] = NULL; - } - - if ( m_hHandEffect[1] != NULL ) - { - UTIL_Remove( m_hHandEffect[1] ); - m_hHandEffect[1] = NULL; - } - - m_fGlowAge = 0; -} - -//------------------------------------------------------------------------------ -// Purpose: remove all beams -//------------------------------------------------------------------------------ -void CNPC_Vortigaunt::ClearBeams( void ) -{ - // Stop looping suit charge sound. - if ( m_bStopLoopingSounds ) - { - StopSound( "NPC_Vortigaunt.StartHealLoop" ); - StopSound( "NPC_Vortigaunt.StartShootLoop" ); - StopSound( "NPC_Vortigaunt.SuitCharge" ); - StopSound( "NPC_Vortigaunt.ZapPowerup" ); - m_bStopLoopingSounds = false; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::InputEnableArmorRecharge( inputdata_t &data ) -{ - m_bArmorRechargeEnabled = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::InputDisableArmorRecharge( inputdata_t &data ) -{ - m_bArmorRechargeEnabled = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::InputChargeTarget( inputdata_t &data ) -{ - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, data.value.String(), NULL, data.pActivator, data.pCaller ); - - // Must be valid - if ( pTarget == NULL ) - { - DevMsg( 1, "Unable to charge from unknown entity: %s!\n", data.value.String() ); - return; - } - - int playerArmor = (pTarget->IsPlayer()) ? ((CBasePlayer *)pTarget)->ArmorValue() : 0; - - if ( playerArmor >= 100 || ( pTarget->GetFlags() & FL_NOTARGET ) ) - { - m_OnFinishedChargingTarget.FireOutput( this, this ); - return; - } - - m_hHealTarget = pTarget; - m_bForceArmorRecharge = true; - - SetCondition( COND_PROVOKED ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::InputExtractBugbait( inputdata_t &data ) -{ - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, data.value.String(), NULL, data.pActivator, data.pCaller ); - - // Must be valid - if ( pTarget == NULL ) - { - DevMsg( 1, "Unable to extract bugbait from unknown entity %s!\n", data.value.String() ); - return; - } - - // Keep this as our target - SetTarget( pTarget ); - - // Start to extract - m_bExtractingBugbait = true; - SetSchedule( SCHED_VORTIGAUNT_EXTRACT_BUGBAIT ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Allows the vortigaunt to use health regeneration -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::InputEnableHealthRegeneration( inputdata_t &data ) -{ - m_bRegenerateHealth = true; -} - -//----------------------------------------------------------------------------- -// Purpose: Stops the vortigaunt from using health regeneration (default) -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::InputDisableHealthRegeneration( inputdata_t &data ) -{ - m_bRegenerateHealth = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_Vortigaunt::IRelationPriority( CBaseEntity *pTarget ) -{ - int priority = BaseClass::IRelationPriority( pTarget ); - - if ( pTarget == NULL ) - return priority; - - CBaseEntity *pEnemy = GetEnemy(); - - // Handle antlion cases - if ( pEnemy != NULL && pEnemy != pTarget ) - { - // I have an enemy that is not this thing. If that enemy is near, I shouldn't become distracted. - if ( GetAbsOrigin().DistToSqr( pEnemy->GetAbsOrigin()) < Square(15*12) ) - return priority; - } - - // Targets near our follow target have a higher priority to us - if ( m_FollowBehavior.GetFollowTarget() && - m_FollowBehavior.GetFollowTarget()->GetAbsOrigin().DistToSqr( pTarget->GetAbsOrigin() ) < Square(25*12) ) - { - priority++; - } - - // Flipped antlions are of lower priority - CAI_BaseNPC *pNPC = pTarget->MyNPCPointer(); - if ( pNPC && pNPC->Classify() == CLASS_ANTLION && pNPC->GetActivity() == ACT_ANTLION_ZAP_FLIP ) - priority--; - - return priority; -} - -//----------------------------------------------------------------------------- -// Purpose: back away from overly close zombies -//----------------------------------------------------------------------------- -Disposition_t CNPC_Vortigaunt::IRelationType( CBaseEntity *pTarget ) -{ - if ( pTarget == NULL ) - return D_NU; - - Disposition_t disposition = BaseClass::IRelationType( pTarget ); - - if ( pTarget->Classify() == CLASS_ZOMBIE && disposition == D_HT ) - { - if( GetAbsOrigin().DistToSqr(pTarget->GetAbsOrigin()) < VORTIGAUNT_FEAR_ZOMBIE_DIST_SQR ) - { - // Be afraid of a zombie that's near if I'm not allowed to dodge. This will make Alyx back away. - return D_FR; - } - } - - return disposition; -} - -//----------------------------------------------------------------------------- -// Purpose: Determines whether the heal gesture can successfully reach the player -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Vortigaunt::HealGestureHasLOS( void ) -{ - //For now the player is always our target - CBaseEntity *pTargetEnt = AI_GetSinglePlayer(); - if ( pTargetEnt == NULL ) - return false; - - // Find our left hand as the starting point - Vector vecHandPos; - QAngle vecHandAngle; - GetAttachment( m_iRightHandAttachment, vecHandPos, vecHandAngle ); - - // Trace to our target, skipping ourselves and the target - trace_t tr; - CTraceFilterSkipTwoEntities filter( this, pTargetEnt, COLLISION_GROUP_NONE ); - UTIL_TraceLine( vecHandPos, pTargetEnt->WorldSpaceCenter(), MASK_SHOT, &filter, &tr ); - - // Must be clear - if ( tr.fraction < 1.0f || tr.startsolid || tr.allsolid ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Gather conditions for our healing behavior -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::GatherHealConditions( void ) -{ - ClearCondition( COND_VORTIGAUNT_HEAL_TARGET_TOO_FAR ); - ClearCondition( COND_VORTIGAUNT_HEAL_TARGET_BLOCKED ); - ClearCondition( COND_VORTIGAUNT_HEAL_TARGET_BEHIND_US ); - - // We stop if there are enemies around - if ( m_bArmorRechargeEnabled == false || - HasCondition( COND_NEW_ENEMY ) || - HasCondition( COND_HEAR_DANGER ) || - HasCondition( COND_HEAVY_DAMAGE ) ) - { - ClearCondition( COND_VORTIGAUNT_HEAL_VALID ); - return; - } - - // Start by assuming that we'll succeed - SetCondition( COND_VORTIGAUNT_HEAL_VALID ); - - // Just assume we should - if ( m_bForceArmorRecharge ) - return; - - // For now we only act on the player - CBasePlayer *pPlayer = ToBasePlayer( m_hHealTarget ); - if ( pPlayer != NULL ) - { - Vector vecToPlayer = ( pPlayer->WorldSpaceCenter() - WorldSpaceCenter() ); - - // Make sure he's still within heal range - if ( vecToPlayer.LengthSqr() > (HEAL_RANGE*HEAL_RANGE) ) - { - SetCondition( COND_VORTIGAUNT_HEAL_TARGET_TOO_FAR ); - // NOTE: We allow him to send tokens over large distances - //ClearCondition( COND_VORTIGAUNT_HEAL_VALID ); - } - - vecToPlayer.z = 0.0f; - VectorNormalize( vecToPlayer ); - Vector facingDir = BodyDirection2D(); - - // Check our direction towards the player - if ( DotProduct( vecToPlayer, facingDir ) < VIEW_FIELD_NARROW ) - { - SetCondition( COND_VORTIGAUNT_HEAL_TARGET_BEHIND_US ); - ClearCondition( COND_VORTIGAUNT_HEAL_VALID ); - } - - // Now ensure he's not blocked - if ( HealGestureHasLOS() == false ) - { - SetCondition( COND_VORTIGAUNT_HEAL_TARGET_BLOCKED ); - ClearCondition( COND_VORTIGAUNT_HEAL_VALID ); - } - } - else - { - ClearCondition( COND_VORTIGAUNT_HEAL_VALID ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Gather conditions specific to this NPC -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::GatherConditions( void ) -{ - // Call our base - BaseClass::GatherConditions(); - - // See if we're able to heal now - if ( HealBehaviorAvailable() && ( m_flNextHealTime < gpGlobals->curtime ) ) - { - // See if we should heal the player - CBaseEntity *pHealTarget = FindHealTarget(); - if ( pHealTarget != NULL ) - { - SetHealTarget( pHealTarget, false ); - } - - // Don't try again for a period of time - m_flNextHealTime = gpGlobals->curtime + 2.0f; - } - - // Get our state for healing - GatherHealConditions(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::DispelAntlions( const Vector &vecOrigin, float flRadius, bool bDispel /*= true*/ ) -{ - // More effects - if ( bDispel ) - { - UTIL_ScreenShake( vecOrigin, 20.0f, 150.0, 1.0, 1250.0f, SHAKE_START ); - - CBroadcastRecipientFilter filter2; - te->BeamRingPoint( filter2, 0, vecOrigin, //origin - 64, //start radius - 800, //end radius - m_nLightningSprite, //texture - 0, //halo index - 0, //start frame - 2, //framerate - 0.1f, //life - 128, //width - 0, //spread - 0, //amplitude - 255, //r - 255, //g - 225, //b - 32, //a - 0, //speed - FBEAM_FADEOUT - ); - - //Shockring - te->BeamRingPoint( filter2, 0, vecOrigin + Vector( 0, 0, 16 ), //origin - 64, //start radius - 800, //end radius - m_nLightningSprite, //texture - 0, //halo index - 0, //start frame - 2, //framerate - 0.2f, //life - 64, //width - 0, //spread - 0, //amplitude - 255, //r - 255, //g - 225, //b - 200, //a - 0, //speed - FBEAM_FADEOUT - ); - - // Ground effects - CEffectData data; - data.m_vOrigin = vecOrigin; - - DispatchEffect( "VortDispel", data ); - } - - // Make antlions flip all around us! - trace_t tr; - CBaseEntity *pEnemySearch[32]; - int nNumEnemies = UTIL_EntitiesInBox( pEnemySearch, ARRAYSIZE(pEnemySearch), vecOrigin-Vector(flRadius,flRadius,flRadius), vecOrigin+Vector(flRadius,flRadius,flRadius), FL_NPC ); - for ( int i = 0; i < nNumEnemies; i++ ) - { - // We only care about antlions - if ( IsAntlion( pEnemySearch[i] ) == false ) - continue; - - CNPC_Antlion *pAntlion = static_cast(pEnemySearch[i]); - if ( pAntlion->IsWorker() == false ) - { - // Attempt to trace a line to hit the target - UTIL_TraceLine( vecOrigin, pAntlion->BodyTarget( vecOrigin ), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction < 1.0f && tr.m_pEnt != pAntlion ) - continue; - - Vector vecDir = ( pAntlion->GetAbsOrigin() - vecOrigin ); - vecDir[2] = 0.0f; - float flDist = VectorNormalize( vecDir ); - - float flFalloff = RemapValClamped( flDist, 0, flRadius*0.75f, 1.0f, 0.1f ); - - vecDir *= ( flRadius * 1.5f * flFalloff ); - vecDir[2] += ( flRadius * 0.5f * flFalloff ); - - pAntlion->ApplyAbsVelocityImpulse( vecDir ); - - // gib nearby antlions, knock over distant ones. - if ( flDist < 128 && bDispel ) - { - // splat! - vecDir[2] += 400.0f * flFalloff; - CTakeDamageInfo dmgInfo( this, this, vecDir, pAntlion->GetAbsOrigin() , 100, DMG_SHOCK ); - pAntlion->TakeDamage( dmgInfo ); - } - else - { - // Turn them over - pAntlion->Flip( true ); - - // Display an effect between us and the flipped creature - // Tell the client to start an arm beam - /* - unsigned char uchAttachment = pAntlion->LookupAttachment( "mouth" ); - EntityMessageBegin( this, true ); - WRITE_BYTE( VORTFX_ARMBEAM ); - WRITE_LONG( pAntlion->entindex() ); - WRITE_BYTE( uchAttachment ); - WRITE_VEC3COORD( vecOrigin ); - WRITE_VEC3NORMAL( Vector( 0, 0, 1 ) ); - MessageEnd(); - */ - } - } - } - - // Stop our effects - if ( bDispel ) - { - EndHandGlow( VORTIGAUNT_BEAM_ALL ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Simply tell us to dispel -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::InputDispel( inputdata_t &data ) -{ - SetCondition( COND_VORTIGAUNT_DISPEL_ANTLIONS ); -} - -//----------------------------------------------------------------------------- -// Purpose: Decide when we're allowed to interact with other NPCs -//----------------------------------------------------------------------------- -bool CNPC_Vortigaunt::CanRunAScriptedNPCInteraction( bool bForced /*= false*/ ) -{ - // Never interrupt a range attack! - if ( InAttackSequence() ) - return false; - - // Can't do them while we're trying to heal the player - if ( m_eHealState != HEAL_STATE_NONE ) - return false; - - return BaseClass::CanRunAScriptedNPCInteraction( bForced ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : interrupt - -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::SetScriptedScheduleIgnoreConditions( Interruptability_t interrupt ) -{ - // First add our base conditions to ignore - BaseClass::SetScriptedScheduleIgnoreConditions( interrupt ); - - static int g_VortConditions[] = - { - COND_VORTIGAUNT_CAN_HEAL, - COND_VORTIGAUNT_DISPEL_ANTLIONS, - COND_VORTIGAUNT_HEAL_TARGET_TOO_FAR, - COND_VORTIGAUNT_HEAL_TARGET_BLOCKED, - COND_VORTIGAUNT_HEAL_TARGET_BEHIND_US, - COND_VORTIGAUNT_HEAL_VALID - }; - - ClearIgnoreConditions( g_VortConditions, ARRAYSIZE(g_VortConditions) ); - - // Ignore these if we're damage only - if ( interrupt > GENERAL_INTERRUPTABILITY ) - SetIgnoreConditions( g_VortConditions, ARRAYSIZE(g_VortConditions) ); -} - -//----------------------------------------------------------------------------- -// !!!HACKHACK - EP2 - Stop vortigaunt taking all physics damage to prevent it dying -// in freak accidents resembling spontaneous stress damage death (which are now impossible) -// Also stop it taking damage from flames: Fixes it being burnt to death from entity flames -// attached to random debris chunks while inside scripted sequences. -//----------------------------------------------------------------------------- -int CNPC_Vortigaunt::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - if( info.GetDamageType() & (DMG_CRUSH | DMG_BURN) ) - return 0; - - // vital vortigaunts (eg the vortigoth in ep2) take less damage from explosions - // so that zombines don't blow them up disappointingly. They take less damage - // still from antlion workers. - if ( Classify() == CLASS_PLAYER_ALLY_VITAL ) - { - // half damage - CTakeDamageInfo subInfo = info; - - // take less damage from antlion worker acid/poison - if ( info.GetAttacker()->Classify() == CLASS_ANTLION && - (info.GetDamageType() & ( DMG_ACID | DMG_POISON ))!=0 - ) - { - subInfo.ScaleDamage( sk_vortigaunt_vital_antlion_worker_dmg.GetFloat() ); - } - - else if ( info.GetDamageType() & DMG_BLAST ) - { - subInfo.ScaleDamage( 0.5f ); - } - - return BaseClass::OnTakeDamage_Alive( subInfo ); - } - - return BaseClass::OnTakeDamage_Alive( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: Override move and shoot if we're following someone -//----------------------------------------------------------------------------- -bool CNPC_Vortigaunt::ShouldMoveAndShoot( void ) -{ - if ( m_FollowBehavior.IsActive() ) - return true; - - return BaseClass::ShouldMoveAndShoot(); -} - -//----------------------------------------------------------------------------- -// Purpose: notification from a grub that I squished it. This special case -// function is necessary because what you would think to be the ordinary -// channels are in fact missing: Event_KilledOther doesn't actually do anything -// and KilledNPC expects a BaseCombatCharacter, and always uses the same Speak -// line. -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::OnSquishedGrub( const CBaseEntity *pGrub ) -{ - Speak(TLK_SQUISHED_GRUB); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::AimGun( void ) -{ - // If our aim lock is on, don't bother - if ( m_flAimDelay >= gpGlobals->curtime ) - return; - - // Aim at our target - if ( GetEnemy() ) - { - Vector vecShootOrigin; - - vecShootOrigin = Weapon_ShootPosition(); - Vector vecShootDir; - - // Aim where it is - vecShootDir = GetShootEnemyDir( vecShootOrigin, false ); - - if ( g_debug_vortigaunt_aim.GetBool() ) - { - NDebugOverlay::Line( WorldSpaceCenter(), WorldSpaceCenter() + vecShootDir * 256.0f, 255, 0, 0, true, 0.1f ); - } - - SetAim( vecShootDir ); - } - else - { - RelaxAim(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: A scripted sequence has interrupted us -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::OnStartScene( void ) -{ - // Watch our hand state - EndHandGlow( VORTIGAUNT_BEAM_ALL ); - m_fGlowChangeTime = gpGlobals->curtime + 0.1f; // No more glows for this amount of time! - - BaseClass::OnStartScene(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPC_Vortigaunt::IsInterruptable( void ) -{ - // Don't interrupt my attack schedule! - if ( InAttackSequence() ) - return false; - - return BaseClass::IsInterruptable(); -} - -//----------------------------------------------------------------------------- -// Purpose: Start overriding our animations to "carry" an NPC -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::InputBeginCarryNPC( inputdata_t &indputdata ) -{ - m_bCarryingNPC = true; -} - -//----------------------------------------------------------------------------- -// Purpose: Stop overriding our animations for carrying an NPC -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::InputEndCarryNPC( inputdata_t &indputdata ) -{ - m_bCarryingNPC = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Turn off flinching under certain circumstances -//----------------------------------------------------------------------------- -bool CNPC_Vortigaunt::CanFlinch( void ) -{ - if ( IsActiveDynamicInteraction() ) - return false; - - if ( IsPlayingGesture( ACT_GESTURE_RANGE_ATTACK1 ) ) - return false; - - if ( IsCurSchedule( SCHED_VORTIGAUNT_DISPEL_ANTLIONS ) || IsCurSchedule( SCHED_RANGE_ATTACK1 ) ) - return false; - - return BaseClass::CanFlinch(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Vortigaunt::OnUpdateShotRegulator( void ) -{ - // Do nothing, we're not really running this code in a normal manner - GetShotRegulator()->SetBurstInterval( 2.0f, 2.0f ); - GetShotRegulator()->SetBurstShotCountRange( 1, 1 ); - GetShotRegulator()->SetRestInterval( 2.0f, 2.0f ); -} - -/* -IMPLEMENT_SERVERCLASS_ST( CVortigauntChargeToken, DT_VortigauntChargeToken ) - SendPropFloat( SENDINFO(m_flFadeOutTime), 0, SPROP_NOSCALE), - SendPropBool( SENDINFO(m_bFadeOut) ), - SendPropFloat( SENDINFO(m_flScale), 0, SPROP_NOSCALE), -END_SEND_TABLE() -*/ - -//------------------------------------------------------------------------------ -// -// Schedules -// -//------------------------------------------------------------------------------ - -AI_BEGIN_CUSTOM_NPC( npc_vortigaunt, CNPC_Vortigaunt ) - - DECLARE_USES_SCHEDULE_PROVIDER( CAI_LeadBehavior ) - - DECLARE_TASK(TASK_VORTIGAUNT_HEAL) - DECLARE_TASK(TASK_VORTIGAUNT_EXTRACT) - DECLARE_TASK(TASK_VORTIGAUNT_FIRE_EXTRACT_OUTPUT) - DECLARE_TASK(TASK_VORTIGAUNT_WAIT_FOR_PLAYER) - - DECLARE_TASK( TASK_VORTIGAUNT_EXTRACT_WARMUP ) - DECLARE_TASK( TASK_VORTIGAUNT_EXTRACT_COOLDOWN ) - DECLARE_TASK( TASK_VORTIGAUNT_GET_HEAL_TARGET ) - DECLARE_TASK( TASK_VORTIGAUNT_DISPEL_ANTLIONS ) - - DECLARE_ACTIVITY( ACT_VORTIGAUNT_AIM) - DECLARE_ACTIVITY( ACT_VORTIGAUNT_START_HEAL ) - DECLARE_ACTIVITY( ACT_VORTIGAUNT_HEAL_LOOP ) - DECLARE_ACTIVITY( ACT_VORTIGAUNT_END_HEAL ) - DECLARE_ACTIVITY( ACT_VORTIGAUNT_TO_ACTION ) - DECLARE_ACTIVITY( ACT_VORTIGAUNT_TO_IDLE ) - DECLARE_ACTIVITY( ACT_VORTIGAUNT_HEAL ) - DECLARE_ACTIVITY( ACT_VORTIGAUNT_DISPEL ) - DECLARE_ACTIVITY( ACT_VORTIGAUNT_ANTLION_THROW ) - - DECLARE_CONDITION( COND_VORTIGAUNT_CAN_HEAL ) - DECLARE_CONDITION( COND_VORTIGAUNT_HEAL_TARGET_TOO_FAR ) - DECLARE_CONDITION( COND_VORTIGAUNT_HEAL_TARGET_BLOCKED ) - DECLARE_CONDITION( COND_VORTIGAUNT_HEAL_TARGET_BEHIND_US ) - DECLARE_CONDITION( COND_VORTIGAUNT_HEAL_VALID ) - DECLARE_CONDITION( COND_VORTIGAUNT_DISPEL_ANTLIONS ) - - DECLARE_SQUADSLOT( SQUAD_SLOT_HEAL_PLAYER ) - - DECLARE_ANIMEVENT( AE_VORTIGAUNT_CLAW_LEFT ) - DECLARE_ANIMEVENT( AE_VORTIGAUNT_CLAW_RIGHT ) - DECLARE_ANIMEVENT( AE_VORTIGAUNT_ZAP_POWERUP ) - DECLARE_ANIMEVENT( AE_VORTIGAUNT_ZAP_SHOOT ) - DECLARE_ANIMEVENT( AE_VORTIGAUNT_ZAP_DONE ) - DECLARE_ANIMEVENT( AE_VORTIGAUNT_HEAL_STARTGLOW ) - DECLARE_ANIMEVENT( AE_VORTIGAUNT_HEAL_STARTBEAMS ) - DECLARE_ANIMEVENT( AE_VORTIGAUNT_HEAL_STARTSOUND ) - DECLARE_ANIMEVENT( AE_VORTIGAUNT_SWING_SOUND ) - DECLARE_ANIMEVENT( AE_VORTIGAUNT_SHOOT_SOUNDSTART ) - DECLARE_ANIMEVENT( AE_VORTIGAUNT_HEAL_PAUSE ) - - DECLARE_ANIMEVENT( AE_VORTIGAUNT_START_DISPEL ) - DECLARE_ANIMEVENT( AE_VORTIGAUNT_ACCEL_DISPEL ) - DECLARE_ANIMEVENT( AE_VORTIGAUNT_DISPEL ) - - DECLARE_ANIMEVENT( AE_VORTIGAUNT_START_HURT_GLOW ) - DECLARE_ANIMEVENT( AE_VORTIGAUNT_STOP_HURT_GLOW ) - - DECLARE_ANIMEVENT( AE_VORTIGAUNT_START_HEAL_GLOW ) - DECLARE_ANIMEVENT( AE_VORTIGAUNT_STOP_HEAL_GLOW ) - - //========================================================= - // > SCHED_VORTIGAUNT_RANGE_ATTACK - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_VORTIGAUNT_RANGE_ATTACK, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_FACE_IDEAL 0" - " TASK_ANNOUNCE_ATTACK 0" - " TASK_RANGE_ATTACK1 0" - " TASK_WAIT 0.2" // Wait a sec before killing beams - "" - " Interrupts" - " COND_NO_CUSTOM_INTERRUPTS" - ); - - - //========================================================= - // > SCHED_VORTIGAUNT_HEAL - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_VORTIGAUNT_HEAL, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_VORTIGAUNT_STAND" - " TASK_STOP_MOVING 0" - " TASK_VORTIGAUNT_GET_HEAL_TARGET 0" - " TASK_GET_PATH_TO_TARGET 0" - " TASK_MOVE_TO_TARGET_RANGE 350" - " TASK_STOP_MOVING 0" - " TASK_FACE_PLAYER 0" - " TASK_VORTIGAUNT_HEAL 0" - "" - " Interrupts" - " COND_HEAVY_DAMAGE" - ); - - //========================================================= - // > SCHED_VORTIGAUNT_STAND - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_VORTIGAUNT_STAND, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_WAIT 2" // repick IDLESTAND every two seconds." - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_SMELL" - " COND_PROVOKED" - " COND_HEAR_COMBAT" - " COND_HEAR_DANGER" - " COND_VORTIGAUNT_DISPEL_ANTLIONS" - " COND_VORTIGAUNT_CAN_HEAL" - ); - - //========================================================= - // > SCHED_VORTIGAUNT_EXTRACT_BUGBAIT - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_VORTIGAUNT_EXTRACT_BUGBAIT, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_VORTIGAUNT_STAND" - " TASK_STOP_MOVING 0" - " TASK_GET_PATH_TO_TARGET 0" - " TASK_MOVE_TO_TARGET_RANGE 128" // Move within 128 of target ent (client) - " TASK_STOP_MOVING 0" - " TASK_VORTIGAUNT_WAIT_FOR_PLAYER 0" - " TASK_SPEAK_SENTENCE 500" // Start extracting sentence - " TASK_WAIT_FOR_SPEAK_FINISH 1" - " TASK_FACE_TARGET 0" - " TASK_WAIT_FOR_SPEAK_FINISH 1" - " TASK_VORTIGAUNT_EXTRACT_WARMUP 0" - " TASK_VORTIGAUNT_EXTRACT 0" - " TASK_VORTIGAUNT_EXTRACT_COOLDOWN 0" - " TASK_VORTIGAUNT_FIRE_EXTRACT_OUTPUT 0" - " TASK_SPEAK_SENTENCE 501" // Finish extracting sentence - " TASK_WAIT_FOR_SPEAK_FINISH 1" - " TASK_WAIT 2" - "" - " Interrupts" - ) - - //========================================================= - // > SCHED_VORTIGAUNT_FACE_PLAYER - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_VORTIGAUNT_FACE_PLAYER, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_TARGET_PLAYER 0" - " TASK_FACE_PLAYER 0" - " TASK_WAIT 3" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_VORTIGAUNT_DISPEL_ANTLIONS" - " COND_VORTIGAUNT_HEAL_TARGET_TOO_FAR" - " COND_VORTIGAUNT_HEAL_TARGET_BLOCKED" - " COND_VORTIGAUNT_HEAL_TARGET_BEHIND_US" - ); - - //========================================================= - // > SCHED_VORTIGAUNT_RUN_TO_PLAYER - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_VORTIGAUNT_RUN_TO_PLAYER, - - " Tasks" - " TASK_TARGET_PLAYER 0" - " TASK_GET_PATH_TO_TARGET 0" - " TASK_MOVE_TO_TARGET_RANGE 350" - "" - " Interrupts" - " COND_HEAVY_DAMAGE" - ); - - //========================================================= - // > SCHED_VORTIGAUNT_DISPEL_ANTLIONS - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_VORTIGAUNT_DISPEL_ANTLIONS, - - " Tasks" - " TASK_VORTIGAUNT_DISPEL_ANTLIONS 0" - "" - " Interrupts" - " COND_NO_CUSTOM_INTERRUPTS" - ); - - //========================================================= - // - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_VORT_FLEE_FROM_BEST_SOUND, - - " Tasks" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_COWER" - " TASK_GET_PATH_AWAY_FROM_BEST_SOUND 600" - " TASK_RUN_PATH_TIMED 1.5" - " TASK_STOP_MOVING 0" - "" - " Interrupts" - ) - - //========================================================= - // > AlertFace best sound - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_VORT_ALERT_FACE_BESTSOUND, - - " Tasks" - " TASK_STORE_BESTSOUND_REACTORIGIN_IN_SAVEPOSITION 0" - " TASK_STOP_MOVING 0" - " TASK_FACE_SAVEPOSITION 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_SEE_FEAR" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_PROVOKED" - " COND_HEAR_DANGER" - ); -AI_END_CUSTOM_NPC() - - -//============================================================================= -// -// Charge Token -// -//============================================================================= - -LINK_ENTITY_TO_CLASS( vort_charge_token, CVortigauntChargeToken ); - -BEGIN_DATADESC( CVortigauntChargeToken ) - DEFINE_FIELD( m_hTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_flLifetime, FIELD_TIME ), - DEFINE_FIELD( m_bFadeOut, FIELD_BOOLEAN ), - - DEFINE_ENTITYFUNC( SeekThink ), - DEFINE_ENTITYFUNC( SeekTouch ), -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CVortigauntChargeToken, DT_VortigauntChargeToken ) - SendPropBool( SENDINFO(m_bFadeOut) ), -END_SEND_TABLE() - -CVortigauntChargeToken::CVortigauntChargeToken( void ) : -m_hTarget( NULL ) -{ - m_bFadeOut = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Create a charge token for the player to collect -// Input : &vecOrigin - Where we start -// *pOwner - Who created us -// *pTarget - Who we're seeking towards -//----------------------------------------------------------------------------- -CVortigauntChargeToken *CVortigauntChargeToken::CreateChargeToken( const Vector &vecOrigin, CBaseEntity *pOwner, CBaseEntity *pTarget ) -{ - CVortigauntChargeToken *pToken = (CVortigauntChargeToken *) CreateEntityByName( "vort_charge_token" ); - if ( pToken == NULL ) - return NULL; - - // Set up our internal data - UTIL_SetOrigin( pToken, vecOrigin ); - pToken->SetOwnerEntity( pOwner ); - pToken->SetTargetEntity( pTarget ); - pToken->SetThink( &CVortigauntChargeToken::SeekThink ); - pToken->SetTouch( &CVortigauntChargeToken::SeekTouch ); - pToken->Spawn(); - - // Start out at the same velocity as our owner - Vector vecInitialVelocity; - CBaseAnimating *pAnimating = dynamic_cast(pOwner); - if ( pAnimating != NULL ) - { - vecInitialVelocity = pAnimating->GetGroundSpeedVelocity(); - } - else - { - vecInitialVelocity = pTarget->GetSmoothedVelocity(); - } - - // Start out at that speed - pToken->SetAbsVelocity( vecInitialVelocity ); - - return pToken; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CVortigauntChargeToken::Precache( void ) -{ - PrecacheParticleSystem( "vortigaunt_charge_token" ); -} - -//----------------------------------------------------------------------------- -// Purpose: We want to move through grates! -//----------------------------------------------------------------------------- -unsigned int CVortigauntChargeToken::PhysicsSolidMaskForEntity( void ) const -{ - return MASK_SHOT; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CVortigauntChargeToken::Spawn( void ) -{ - Precache(); - - // Point-sized - UTIL_SetSize( this, -Vector(1,1,1), Vector(1,1,1) ); - - SetMoveType( MOVETYPE_FLY ); - SetSolid( SOLID_BBOX ); - SetSolidFlags( FSOLID_TRIGGER | FSOLID_NOT_SOLID ); - SetGravity( 0.0f ); - - // No model but we still need to force this! - AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); - - SetNextThink( gpGlobals->curtime + 0.05f ); - - m_flLifetime = gpGlobals->curtime + VORTIGAUNT_CURE_LIFESPAN; - - BaseClass::Spawn(); -} - -//----------------------------------------------------------------------------- -// Purpose: Creates an influence vector which causes the token to move away from obstructions -//----------------------------------------------------------------------------- -Vector CVortigauntChargeToken::GetSteerVector( const Vector &vecForward ) -{ - Vector vecSteer = vec3_origin; - Vector vecRight, vecUp; - VectorVectors( vecForward, vecRight, vecUp ); - - // Use two probes fanned out a head of us - Vector vecProbe; - float flSpeed = GetAbsVelocity().Length(); - - // Try right - vecProbe = vecForward + vecRight; - vecProbe *= flSpeed; - - // We ignore multiple targets - CTraceFilterSimpleList filterSkip( COLLISION_GROUP_NONE ); - filterSkip.AddEntityToIgnore( this ); - filterSkip.AddEntityToIgnore( GetOwnerEntity() ); - filterSkip.AddEntityToIgnore( m_hTarget ); - - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + vecProbe, MASK_SHOT, &filterSkip, &tr ); - vecSteer -= vecRight * 100.0f * ( 1.0f - tr.fraction ); - - // Try left - vecProbe = vecForward - vecRight; - vecProbe *= flSpeed; - - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + vecProbe, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - vecSteer += vecRight * 100.0f * ( 1.0f - tr.fraction ); - - return vecSteer; -} - -#define VTOKEN_MAX_SPEED 320.0f // U/sec -#define VTOKEN_ACCEL_SPEED 320.0f // ' - -//----------------------------------------------------------------------------- -// Purpose: Move towards our target entity with accel/decel parameters -//----------------------------------------------------------------------------- -void CVortigauntChargeToken::SeekThink( void ) -{ - // Move away from the creator and towards the target - if ( m_hTarget == NULL || m_flLifetime < gpGlobals->curtime ) - { - // TODO: Play an extinguish sound and fade out - FadeAndDie(); - return; - } - - // Find the direction towards our goal and start to go there - Vector vecDir = ( m_hTarget->WorldSpaceCenter() - GetAbsOrigin() ); - VectorNormalize( vecDir ); - - float flSpeed = GetAbsVelocity().Length(); - float flDelta = gpGlobals->curtime - GetLastThink(); - - if ( flSpeed < VTOKEN_MAX_SPEED ) - { - // Accelerate by the desired amount - flSpeed += ( VTOKEN_ACCEL_SPEED * flDelta ); - if ( flSpeed > VTOKEN_MAX_SPEED ) - { - flSpeed = VTOKEN_MAX_SPEED; - } - } - - // Steer! - Vector vecRight, vecUp; - VectorVectors( vecDir, vecRight, vecUp ); - Vector vecOffset = vec3_origin; - vecOffset += vecUp * cos( gpGlobals->curtime * 20.0f ) * 200.0f * gpGlobals->frametime; - vecOffset += vecRight * sin( gpGlobals->curtime * 15.0f ) * 200.0f * gpGlobals->frametime; - - vecOffset += GetSteerVector( vecDir ); - - SetAbsVelocity( ( vecDir * flSpeed ) + vecOffset ); - SetNextThink( gpGlobals->curtime + 0.05f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CVortigauntChargeToken::SeekTouch( CBaseEntity *pOther ) -{ - // Make sure this is a player - CBasePlayer *pPlayer = ToBasePlayer( pOther ); - if ( pPlayer == NULL ) - return; - - // FIXME: This probably isn't that interesting for single player missions - if ( pPlayer != m_hTarget ) - return; - - // TODO: Play a special noise for this event! - EmitSound( "NPC_Vortigaunt.SuitOn" ); - - // Charge the suit's armor - if ( pPlayer->ArmorValue() < sk_vortigaunt_armor_charge.GetInt() ) - { - pPlayer->IncrementArmorValue( sk_vortigaunt_armor_charge_per_token.GetInt()+random->RandomInt( -1, 1 ), sk_vortigaunt_armor_charge.GetInt() ); - } - - // Stay attached to the thing we hit as we fade away - SetSolidFlags( FSOLID_NOT_SOLID ); - SetMoveType( MOVETYPE_NONE ); - SetParent( pOther ); - - // TODO: Play a "poof!" effect here? - FadeAndDie(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flTime - -//----------------------------------------------------------------------------- -void CVortigauntChargeToken::FadeAndDie( void ) -{ - SetTouch( NULL ); - - SetAbsVelocity( vec3_origin ); - - m_bFadeOut = true; - SetThink( &CBaseEntity::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 2.0f ); -} - -//============================================================================= -// -// Dispel Effect -// -//============================================================================= - -LINK_ENTITY_TO_CLASS( vort_effect_dispel, CVortigauntEffectDispel ); - -BEGIN_DATADESC( CVortigauntEffectDispel ) - DEFINE_FIELD( m_bFadeOut, FIELD_BOOLEAN ), -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CVortigauntEffectDispel, DT_VortigauntEffectDispel ) - SendPropBool( SENDINFO(m_bFadeOut) ), -END_SEND_TABLE() - -CVortigauntEffectDispel::CVortigauntEffectDispel( void ) -{ - m_bFadeOut = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Create a charge token for the player to collect -// Input : &vecOrigin - Where we start -// *pOwner - Who created us -// *pTarget - Who we're seeking towards -//----------------------------------------------------------------------------- -CVortigauntEffectDispel *CVortigauntEffectDispel::CreateEffectDispel( const Vector &vecOrigin, CBaseEntity *pOwner, CBaseEntity *pTarget ) -{ - CVortigauntEffectDispel *pToken = (CVortigauntEffectDispel *) CreateEntityByName( "vort_effect_dispel" ); - if ( pToken == NULL ) - return NULL; - - // Set up our internal data - UTIL_SetOrigin( pToken, vecOrigin ); - pToken->SetOwnerEntity( pOwner ); - pToken->Spawn(); - - return pToken; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CVortigauntEffectDispel::Spawn( void ) -{ - Precache(); - - UTIL_SetSize( this, Vector( -8, -8, -8 ), Vector( 8, 8, 8 ) ); - - SetSolid( SOLID_BBOX ); - SetSolidFlags( FSOLID_NOT_SOLID ); - - // No model but we still need to force this! - AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); - - BaseClass::Spawn(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flTime - -//----------------------------------------------------------------------------- -void CVortigauntEffectDispel::FadeAndDie( void ) -{ - m_bFadeOut = true; - SetThink( &CBaseEntity::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 2.0f ); -} - - -//============================================================================= -// -// Flesh effect target (used for orchestrating the "Invisible Alyx" moment -// -//============================================================================= - -#ifdef HL2_EPISODIC - -class CFleshEffectTarget : public CPointEntity -{ - DECLARE_CLASS( CFleshEffectTarget, CPointEntity ); - -public: - void InputSetRadius( inputdata_t &inputData ); - - virtual void Spawn( void ) - { - BaseClass::Spawn(); - - AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); - } - -private: - - CNetworkVar( float, m_flRadius ); - CNetworkVar( float, m_flScaleTime ); - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( point_flesh_effect_target, CFleshEffectTarget ); - -BEGIN_DATADESC( CFleshEffectTarget ) - - DEFINE_FIELD( m_flScaleTime, FIELD_TIME ), - DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "radius" ), - - DEFINE_INPUTFUNC( FIELD_VECTOR, "SetRadius", InputSetRadius ), - -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CFleshEffectTarget, DT_FleshEffectTarget ) - SendPropFloat( SENDINFO(m_flRadius), 0, SPROP_NOSCALE), - SendPropFloat( SENDINFO(m_flScaleTime), 0, SPROP_NOSCALE), -END_SEND_TABLE() - -void CFleshEffectTarget::InputSetRadius( inputdata_t &inputData ) -{ - Vector vecRadius; - inputData.value.Vector3D( vecRadius ); - - m_flRadius = vecRadius.x; - m_flScaleTime = vecRadius.y; -} - -#endif // HL2_EPISODIC diff --git a/game/server/hl2/npc_vortigaunt_episodic.h b/game/server/hl2/npc_vortigaunt_episodic.h deleted file mode 100644 index 1a455b57f..000000000 --- a/game/server/hl2/npc_vortigaunt_episodic.h +++ /dev/null @@ -1,344 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: This is the base version of the vortigaunt -// -//=============================================================================// - -#ifndef NPC_VORTIGAUNT_H -#define NPC_VORTIGAUNT_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_basenpc.h" -#include "ai_behavior.h" -#include "ai_behavior_lead.h" -#include "ai_behavior_standoff.h" -#include "ai_behavior_assault.h" -#include "npc_playercompanion.h" - -#define VORTIGAUNT_MAX_BEAMS 8 - -#define VORTIGAUNT_BEAM_ALL -1 -#define VORTIGAUNT_BEAM_ZAP 0 -#define VORTIGAUNT_BEAM_HEAL 1 -#define VORTIGAUNT_BEAM_DISPEL 2 - -class CBeam; -class CSprite; -class CVortigauntChargeToken; -class CVortigauntEffectDispel; - -extern ConVar sk_vortigaunt_zap_range; - -enum VortigauntHealState_t -{ - HEAL_STATE_NONE, // Not trying to heal - HEAL_STATE_WARMUP, // In the "warm-up" phase of healing - HEAL_STATE_HEALING, // In the process of healing - HEAL_STATE_COOLDOWN, // in the "cooldown" phase of healing -}; - -//========================================================= -// >> CNPC_Vortigaunt -//========================================================= -class CNPC_Vortigaunt : public CNPC_PlayerCompanion -{ - DECLARE_CLASS( CNPC_Vortigaunt, CNPC_PlayerCompanion ); - -public: - CNPC_Vortigaunt( void ); - - virtual void Spawn( void ); - virtual void Precache( void ); - virtual float MaxYawSpeed( void ); - - virtual Vector FacingPosition( void ); - virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true ); - - virtual void PrescheduleThink( void ); - virtual void BuildScheduleTestBits( void ); - virtual void OnScheduleChange( void ); - - virtual int RangeAttack1Conditions( float flDot, float flDist ); // Primary zap - virtual int RangeAttack2Conditions( float flDot, float flDist ); // Concussive zap (larger) - virtual bool InnateWeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions ); - virtual int MeleeAttack1Conditions( float flDot, float flDist ); // Dispel - virtual float InnateRange1MinRange( void ) { return 0.0f; } - virtual float InnateRange1MaxRange( void ) { return sk_vortigaunt_zap_range.GetFloat()*12; } - virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - virtual bool FInViewCone( CBaseEntity *pEntity ); - virtual bool ShouldMoveAndShoot( void ); - - // vorts have a very long head/neck swing, so debounce heavily - virtual float GetHeadDebounce( void ) { return 0.7; } // how much of previous head turn to use - - virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - virtual void AlertSound( void ); - virtual Class_T Classify ( void ) { return IsGameEndAlly() ? CLASS_PLAYER_ALLY_VITAL : CLASS_VORTIGAUNT; } - virtual void HandleAnimEvent( animevent_t *pEvent ); - virtual Activity NPC_TranslateActivity( Activity eNewActivity ); - - virtual void UpdateOnRemove( void ); - virtual void Event_Killed( const CTakeDamageInfo &info ); - virtual void GatherConditions( void ); - virtual void RunTask( const Task_t *pTask ); - virtual void StartTask( const Task_t *pTask ); - virtual void ClearSchedule( const char *szReason ); - - virtual void DeclineFollowing( void ); - virtual bool CanBeUsedAsAFriend( void ); - virtual bool IsPlayerAlly( void ) { return true; } - - // Override these to set behavior - virtual int TranslateSchedule( int scheduleType ); - virtual int SelectSchedule( void ); - virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ); - virtual bool IsValidEnemy( CBaseEntity *pEnemy ); - bool IsLeading( void ) { return ( GetRunningBehavior() == &m_LeadBehavior && m_LeadBehavior.HasGoal() ); } - - void DeathSound( const CTakeDamageInfo &info ); - void PainSound( const CTakeDamageInfo &info ); - - virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - virtual void SpeakSentence( int sentType ); - - virtual int IRelationPriority( CBaseEntity *pTarget ); - virtual Disposition_t IRelationType( CBaseEntity *pTarget ); - virtual bool IsReadinessCapable( void ) { return true; } - virtual float GetReadinessDecay() { return 30.0f; } - virtual bool ShouldRegenerateHealth( void ) { return m_bRegenerateHealth; } - virtual bool CanRunAScriptedNPCInteraction( bool bForced = false ); - virtual void AimGun( void ); - virtual void OnUpdateShotRegulator( void ); - - void InputEnableArmorRecharge( inputdata_t &data ); - void InputDisableArmorRecharge( inputdata_t &data ); - void InputExtractBugbait( inputdata_t &data ); - void InputChargeTarget( inputdata_t &data ); - void InputDispel( inputdata_t &data ); - void InputBeginCarryNPC( inputdata_t &indputdata ); - void InputEndCarryNPC( inputdata_t &indputdata ); - - // Health regeneration - void InputEnableHealthRegeneration( inputdata_t &data ); - void InputDisableHealthRegeneration( inputdata_t &data ); - - // color - void InputTurnBlue( inputdata_t &data ); - void InputTurnBlack( inputdata_t &data ); - - virtual void SetScriptedScheduleIgnoreConditions( Interruptability_t interrupt ); - virtual void OnRestore( void ); - virtual bool OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval ); - virtual void OnStartScene( void ); - virtual bool IsInterruptable( void ); - virtual bool CanFlinch( void ); - - // used so a grub can notify me that I stepped on it. Says a line. - void OnSquishedGrub( const CBaseEntity *pGrub ); - -private: - - int NumAntlionsInRadius( float flRadius ); - void DispelAntlions( const Vector &vecOrigin, float flRadius, bool bDispel = true ); - bool HealGestureHasLOS( void ); - bool PlayerBelowHealthPercentage( CBasePlayer *pPlayer, float flPerc ); - void StartHealing( void ); - void StopHealing( bool bInterrupt = false ); - void MaintainHealSchedule( void ); - bool ShouldHealTarget( CBaseEntity *pTarget ); - int SelectHealSchedule( void ); - - void CreateBeamBlast( const Vector &vecOrigin ); - -private: - //========================================================= - // Vortigaunt schedules - //========================================================= - enum - { - SCHED_VORTIGAUNT_STAND = BaseClass::NEXT_SCHEDULE, - SCHED_VORTIGAUNT_RANGE_ATTACK, - SCHED_VORTIGAUNT_HEAL, - SCHED_VORTIGAUNT_EXTRACT_BUGBAIT, - SCHED_VORTIGAUNT_FACE_PLAYER, - SCHED_VORTIGAUNT_RUN_TO_PLAYER, - SCHED_VORTIGAUNT_DISPEL_ANTLIONS, - SCHED_VORT_FLEE_FROM_BEST_SOUND, - SCHED_VORT_ALERT_FACE_BESTSOUND, - }; - - //========================================================= - // Vortigaunt Tasks - //========================================================= - enum - { - TASK_VORTIGAUNT_HEAL_WARMUP = BaseClass::NEXT_TASK, - TASK_VORTIGAUNT_HEAL, - TASK_VORTIGAUNT_EXTRACT_WARMUP, - TASK_VORTIGAUNT_EXTRACT, - TASK_VORTIGAUNT_EXTRACT_COOLDOWN, - TASK_VORTIGAUNT_FIRE_EXTRACT_OUTPUT, - TASK_VORTIGAUNT_WAIT_FOR_PLAYER, - TASK_VORTIGAUNT_GET_HEAL_TARGET, - TASK_VORTIGAUNT_DISPEL_ANTLIONS - }; - - //========================================================= - // Vortigaunt Conditions - //========================================================= - enum - { - COND_VORTIGAUNT_CAN_HEAL = BaseClass::NEXT_CONDITION, - COND_VORTIGAUNT_HEAL_TARGET_TOO_FAR, // Outside or heal range - COND_VORTIGAUNT_HEAL_TARGET_BLOCKED, // Blocked by an obstruction - COND_VORTIGAUNT_HEAL_TARGET_BEHIND_US, // Not within our "forward" range - COND_VORTIGAUNT_HEAL_VALID, // All conditions satisfied - COND_VORTIGAUNT_DISPEL_ANTLIONS, // Repulse all antlions around us - }; - - // ------------ - // Beams - // ------------ - inline bool InAttackSequence( void ); - void ClearBeams( void ); - void ArmBeam( int beamType, int nHand ); - void ZapBeam( int nHand ); - int m_nLightningSprite; - - // --------------- - // Glow - // ---------------- - void ClearHandGlow( void ); - float m_fGlowAge; - float m_fGlowChangeTime; - bool m_bGlowTurningOn; - int m_nCurGlowIndex; - - CHandle m_hHandEffect[2]; - - void StartHandGlow( int beamType, int nHand ); - void EndHandGlow( int beamType = VORTIGAUNT_BEAM_ALL ); - void MaintainGlows( void ); - - // ---------------- - // Healing - // ---------------- - bool m_bRegenerateHealth; - float m_flNextHealTime; // Next time allowed to heal player - EHANDLE m_hHealTarget; // The person that I'm going to heal. - bool m_bPlayerRequestedHeal; // This adds some priority to our heal (allows it to happen in combat, etc) - float m_flNextHealTokenTime; - - VortigauntHealState_t m_eHealState; - - CBaseEntity *FindHealTarget( void ); - bool HealBehaviorAvailable( void ); - void SetHealTarget( CBaseEntity *pTarget, bool bPlayerRequested ); - void GatherHealConditions( void ); - - int m_nNumTokensToSpawn; - float m_flHealHinderedTime; - float m_flPainTime; - float m_nextLineFireTime; - - bool m_bArmorRechargeEnabled; - bool m_bForceArmorRecharge; - float m_flDispelTestTime; - - bool m_bExtractingBugbait; - - bool IsCarryingNPC( void ) const { return m_bCarryingNPC; } - bool m_bCarryingNPC; - - COutputEvent m_OnFinishedExtractingBugbait; - COutputEvent m_OnFinishedChargingTarget; - COutputEvent m_OnPlayerUse; - - //Adrian: Let's do it the right way! - int m_iLeftHandAttachment; - int m_iRightHandAttachment; - bool m_bStopLoopingSounds; - float m_flAimDelay; // Amount of time to suppress aiming - - // used for fading from green vort to blue vort - CNetworkVar( bool, m_bIsBlue ); - CNetworkVar( float, m_flBlueEndFadeTime ); - - // used for fading to black - CNetworkVar( bool, m_bIsBlack ); - -public: - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - DEFINE_CUSTOM_AI; -}; - -//============================================================================= -// -// Charge Token -// -//============================================================================= - -class CVortigauntChargeToken : public CBaseEntity -{ - DECLARE_CLASS( CVortigauntChargeToken, CBaseEntity ); - -public: - - static CVortigauntChargeToken *CreateChargeToken( const Vector &vecOrigin, CBaseEntity *pOwner, CBaseEntity *pTarget ); - - CVortigauntChargeToken( void ); - - virtual void Spawn( void ); - virtual void Precache( void ); - virtual unsigned int PhysicsSolidMaskForEntity( void ) const; - - void FadeAndDie( void ); - void SeekThink( void ); - void SeekTouch( CBaseEntity *pOther ); - void SetTargetEntity( CBaseEntity *pTarget ) { m_hTarget = pTarget; } - -private: - - Vector GetSteerVector( const Vector &vecForward ); - - float m_flLifetime; - EHANDLE m_hTarget; - - CNetworkVar( bool, m_bFadeOut ); - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); -}; - -//============================================================================= -// -// Dispel Effect -// -//============================================================================= - -class CVortigauntEffectDispel : public CBaseEntity -{ - DECLARE_CLASS( CVortigauntEffectDispel, CBaseEntity ); - -public: - - static CVortigauntEffectDispel *CreateEffectDispel( const Vector &vecOrigin, CBaseEntity *pOwner, CBaseEntity *pTarget ); - - CVortigauntEffectDispel( void ); - - virtual void Spawn( void ); - - void FadeAndDie( void ); - -private: - - CNetworkVar( bool, m_bFadeOut ); - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); -}; - -#endif // NPC_VORTIGAUNT_H diff --git a/game/server/hl2/npc_zombie.cpp b/game/server/hl2/npc_zombie.cpp deleted file mode 100644 index fad3fb9ad..000000000 --- a/game/server/hl2/npc_zombie.cpp +++ /dev/null @@ -1,1001 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: A slow-moving, once-human headcrab victim with only melee attacks. -// -//=============================================================================// - -#include "cbase.h" - -#include "doors.h" - -#include "simtimer.h" -#include "npc_BaseZombie.h" -#include "ai_hull.h" -#include "ai_navigator.h" -#include "ai_memory.h" -#include "gib.h" -#include "soundenvelope.h" -#include "engine/IEngineSound.h" -#include "ammodef.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// ACT_FLINCH_PHYSICS - - -ConVar sk_zombie_health( "sk_zombie_health","0"); - -envelopePoint_t envZombieMoanVolumeFast[] = -{ - { 7.0f, 7.0f, - 0.1f, 0.1f, - }, - { 0.0f, 0.0f, - 0.2f, 0.3f, - }, -}; - -envelopePoint_t envZombieMoanVolume[] = -{ - { 1.0f, 1.0f, - 0.1f, 0.1f, - }, - { 1.0f, 1.0f, - 0.2f, 0.2f, - }, - { 0.0f, 0.0f, - 0.3f, 0.4f, - }, -}; - -envelopePoint_t envZombieMoanVolumeLong[] = -{ - { 1.0f, 1.0f, - 0.3f, 0.5f, - }, - { 1.0f, 1.0f, - 0.6f, 1.0f, - }, - { 0.0f, 0.0f, - 0.3f, 0.4f, - }, -}; - -envelopePoint_t envZombieMoanIgnited[] = -{ - { 1.0f, 1.0f, - 0.5f, 1.0f, - }, - { 1.0f, 1.0f, - 30.0f, 30.0f, - }, - { 0.0f, 0.0f, - 0.5f, 1.0f, - }, -}; - - -//============================================================================= -//============================================================================= - -class CZombie : public CAI_BlendingHost -{ - DECLARE_DATADESC(); - DECLARE_CLASS( CZombie, CAI_BlendingHost ); - -public: - CZombie() - : m_DurationDoorBash( 2, 6), - m_NextTimeToStartDoorBash( 3.0 ) - { - } - - void Spawn( void ); - void Precache( void ); - - void SetZombieModel( void ); - void MoanSound( envelopePoint_t *pEnvelope, int iEnvelopeSize ); - bool ShouldBecomeTorso( const CTakeDamageInfo &info, float flDamageThreshold ); - bool CanBecomeLiveTorso() { return !m_fIsHeadless; } - - void GatherConditions( void ); - - int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ); - int TranslateSchedule( int scheduleType ); - -#ifndef HL2_EPISODIC - void CheckFlinches() {} // Zombie has custom flinch code -#endif // HL2_EPISODIC - - Activity NPC_TranslateActivity( Activity newActivity ); - - void OnStateChange( NPC_STATE OldState, NPC_STATE NewState ); - - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - - virtual const char *GetLegsModel( void ); - virtual const char *GetTorsoModel( void ); - virtual const char *GetHeadcrabClassname( void ); - virtual const char *GetHeadcrabModel( void ); - - virtual bool OnObstructingDoor( AILocalMoveGoal_t *pMoveGoal, - CBaseDoor *pDoor, - float distClear, - AIMoveResult_t *pResult ); - - Activity SelectDoorBash(); - - void Ignite( float flFlameLifetime, bool bNPCOnly = true, float flSize = 0.0f, bool bCalledByLevelDesigner = false ); - void Extinguish(); - int OnTakeDamage_Alive( const CTakeDamageInfo &inputInfo ); - bool IsHeavyDamage( const CTakeDamageInfo &info ); - bool IsSquashed( const CTakeDamageInfo &info ); - void BuildScheduleTestBits( void ); - - void PrescheduleThink( void ); - int SelectSchedule ( void ); - - void PainSound( const CTakeDamageInfo &info ); - void DeathSound( const CTakeDamageInfo &info ); - void AlertSound( void ); - void IdleSound( void ); - void AttackSound( void ); - void AttackHitSound( void ); - void AttackMissSound( void ); - void FootstepSound( bool fRightFoot ); - void FootscuffSound( bool fRightFoot ); - - const char *GetMoanSound( int nSound ); - -public: - DEFINE_CUSTOM_AI; - -protected: - static const char *pMoanSounds[]; - - -private: - CHandle< CBaseDoor > m_hBlockingDoor; - float m_flDoorBashYaw; - - CRandSimTimer m_DurationDoorBash; - CSimTimer m_NextTimeToStartDoorBash; - - Vector m_vPositionCharged; -}; - -LINK_ENTITY_TO_CLASS( npc_zombie, CZombie ); -LINK_ENTITY_TO_CLASS( npc_zombie_torso, CZombie ); - -//--------------------------------------------------------- -//--------------------------------------------------------- -const char *CZombie::pMoanSounds[] = -{ - "NPC_BaseZombie.Moan1", - "NPC_BaseZombie.Moan2", - "NPC_BaseZombie.Moan3", - "NPC_BaseZombie.Moan4", -}; - -//========================================================= -// Conditions -//========================================================= -enum -{ - COND_BLOCKED_BY_DOOR = LAST_BASE_ZOMBIE_CONDITION, - COND_DOOR_OPENED, - COND_ZOMBIE_CHARGE_TARGET_MOVED, -}; - -//========================================================= -// Schedules -//========================================================= -enum -{ - SCHED_ZOMBIE_BASH_DOOR = LAST_BASE_ZOMBIE_SCHEDULE, - SCHED_ZOMBIE_WANDER_ANGRILY, - SCHED_ZOMBIE_CHARGE_ENEMY, - SCHED_ZOMBIE_FAIL, -}; - -//========================================================= -// Tasks -//========================================================= -enum -{ - TASK_ZOMBIE_EXPRESS_ANGER = LAST_BASE_ZOMBIE_TASK, - TASK_ZOMBIE_YAW_TO_DOOR, - TASK_ZOMBIE_ATTACK_DOOR, - TASK_ZOMBIE_CHARGE_ENEMY, -}; - -//----------------------------------------------------------------------------- - -int ACT_ZOMBIE_TANTRUM; -int ACT_ZOMBIE_WALLPOUND; - -BEGIN_DATADESC( CZombie ) - - DEFINE_FIELD( m_hBlockingDoor, FIELD_EHANDLE ), - DEFINE_FIELD( m_flDoorBashYaw, FIELD_FLOAT ), - DEFINE_EMBEDDED( m_DurationDoorBash ), - DEFINE_EMBEDDED( m_NextTimeToStartDoorBash ), - DEFINE_FIELD( m_vPositionCharged, FIELD_POSITION_VECTOR ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CZombie::Precache( void ) -{ - BaseClass::Precache(); - - PrecacheModel( "models/zombie/classic.mdl" ); - PrecacheModel( "models/zombie/classic_torso.mdl" ); - PrecacheModel( "models/zombie/classic_legs.mdl" ); - - PrecacheScriptSound( "Zombie.FootstepRight" ); - PrecacheScriptSound( "Zombie.FootstepLeft" ); - PrecacheScriptSound( "Zombie.FootstepLeft" ); - PrecacheScriptSound( "Zombie.ScuffRight" ); - PrecacheScriptSound( "Zombie.ScuffLeft" ); - PrecacheScriptSound( "Zombie.AttackHit" ); - PrecacheScriptSound( "Zombie.AttackMiss" ); - PrecacheScriptSound( "Zombie.Pain" ); - PrecacheScriptSound( "Zombie.Die" ); - PrecacheScriptSound( "Zombie.Alert" ); - PrecacheScriptSound( "Zombie.Idle" ); - PrecacheScriptSound( "Zombie.Attack" ); - - PrecacheScriptSound( "NPC_BaseZombie.Moan1" ); - PrecacheScriptSound( "NPC_BaseZombie.Moan2" ); - PrecacheScriptSound( "NPC_BaseZombie.Moan3" ); - PrecacheScriptSound( "NPC_BaseZombie.Moan4" ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CZombie::Spawn( void ) -{ - Precache(); - - if( FClassnameIs( this, "npc_zombie" ) ) - { - m_fIsTorso = false; - } - else - { - // This was placed as an npc_zombie_torso - m_fIsTorso = true; - } - - m_fIsHeadless = false; - -#ifdef HL2_EPISODIC - SetBloodColor( BLOOD_COLOR_ZOMBIE ); -#else - SetBloodColor( BLOOD_COLOR_GREEN ); -#endif // HL2_EPISODIC - - m_iHealth = sk_zombie_health.GetFloat(); - m_flFieldOfView = 0.2; - - CapabilitiesClear(); - - //GetNavigator()->SetRememberStaleNodes( false ); - - BaseClass::Spawn(); - - m_flNextMoanSound = gpGlobals->curtime + random->RandomFloat( 1.0, 4.0 ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CZombie::PrescheduleThink( void ) -{ - if( gpGlobals->curtime > m_flNextMoanSound ) - { - if( CanPlayMoanSound() ) - { - // Classic guy idles instead of moans. - IdleSound(); - - m_flNextMoanSound = gpGlobals->curtime + random->RandomFloat( 2.0, 5.0 ); - } - else - { - m_flNextMoanSound = gpGlobals->curtime + random->RandomFloat( 1.0, 2.0 ); - } - } - - BaseClass::PrescheduleThink(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CZombie::SelectSchedule ( void ) -{ - if( HasCondition( COND_PHYSICS_DAMAGE ) && !m_ActBusyBehavior.IsActive() ) - { - return SCHED_FLINCH_PHYSICS; - } - - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -// Purpose: Sound of a footstep -//----------------------------------------------------------------------------- -void CZombie::FootstepSound( bool fRightFoot ) -{ - if( fRightFoot ) - { - EmitSound( "Zombie.FootstepRight" ); - } - else - { - EmitSound( "Zombie.FootstepLeft" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Sound of a foot sliding/scraping -//----------------------------------------------------------------------------- -void CZombie::FootscuffSound( bool fRightFoot ) -{ - if( fRightFoot ) - { - EmitSound( "Zombie.ScuffRight" ); - } - else - { - EmitSound( "Zombie.ScuffLeft" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Play a random attack hit sound -//----------------------------------------------------------------------------- -void CZombie::AttackHitSound( void ) -{ - EmitSound( "Zombie.AttackHit" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Play a random attack miss sound -//----------------------------------------------------------------------------- -void CZombie::AttackMissSound( void ) -{ - // Play a random attack miss sound - EmitSound( "Zombie.AttackMiss" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CZombie::PainSound( const CTakeDamageInfo &info ) -{ - // We're constantly taking damage when we are on fire. Don't make all those noises! - if ( IsOnFire() ) - { - return; - } - - EmitSound( "Zombie.Pain" ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CZombie::DeathSound( const CTakeDamageInfo &info ) -{ - EmitSound( "Zombie.Die" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CZombie::AlertSound( void ) -{ - EmitSound( "Zombie.Alert" ); - - // Don't let a moan sound cut off the alert sound. - m_flNextMoanSound += random->RandomFloat( 2.0, 4.0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns a moan sound for this class of zombie. -//----------------------------------------------------------------------------- -const char *CZombie::GetMoanSound( int nSound ) -{ - return pMoanSounds[ nSound % ARRAYSIZE( pMoanSounds ) ]; -} - -//----------------------------------------------------------------------------- -// Purpose: Play a random idle sound. -//----------------------------------------------------------------------------- -void CZombie::IdleSound( void ) -{ - if( GetState() == NPC_STATE_IDLE && random->RandomFloat( 0, 1 ) == 0 ) - { - // Moan infrequently in IDLE state. - return; - } - - if( IsSlumped() ) - { - // Sleeping zombies are quiet. - return; - } - - EmitSound( "Zombie.Idle" ); - MakeAISpookySound( 360.0f ); -} - -//----------------------------------------------------------------------------- -// Purpose: Play a random attack sound. -//----------------------------------------------------------------------------- -void CZombie::AttackSound( void ) -{ - EmitSound( "Zombie.Attack" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the classname (ie "npc_headcrab") to spawn when our headcrab bails. -//----------------------------------------------------------------------------- -const char *CZombie::GetHeadcrabClassname( void ) -{ - return "npc_headcrab"; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -const char *CZombie::GetHeadcrabModel( void ) -{ - return "models/headcrabclassic.mdl"; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const char *CZombie::GetLegsModel( void ) -{ - return "models/zombie/classic_legs.mdl"; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -const char *CZombie::GetTorsoModel( void ) -{ - return "models/zombie/classic_torso.mdl"; -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CZombie::SetZombieModel( void ) -{ - Hull_t lastHull = GetHullType(); - - if ( m_fIsTorso ) - { - SetModel( "models/zombie/classic_torso.mdl" ); - SetHullType( HULL_TINY ); - } - else - { - SetModel( "models/zombie/classic.mdl" ); - SetHullType( HULL_HUMAN ); - } - - SetBodygroup( ZOMBIE_BODYGROUP_HEADCRAB, !m_fIsHeadless ); - - SetHullSizeNormal( true ); - SetDefaultEyeOffset(); - SetActivity( ACT_IDLE ); - - // hull changed size, notify vphysics - // UNDONE: Solve this generally, systematically so other - // NPCs can change size - if ( lastHull != GetHullType() ) - { - if ( VPhysicsGetObject() ) - { - SetupVPhysicsHull(); - } - } -} - -//--------------------------------------------------------- -// Classic zombie only uses moan sound if on fire. -//--------------------------------------------------------- -void CZombie::MoanSound( envelopePoint_t *pEnvelope, int iEnvelopeSize ) -{ - if( IsOnFire() ) - { - BaseClass::MoanSound( pEnvelope, iEnvelopeSize ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CZombie::ShouldBecomeTorso( const CTakeDamageInfo &info, float flDamageThreshold ) -{ - if( IsSlumped() ) - { - // Never break apart a slouched zombie. This is because the most fun - // slouched zombies to kill are ones sleeping leaning against explosive - // barrels. If you break them in half in the blast, the force of being - // so close to the explosion makes the body pieces fly at ridiculous - // velocities because the pieces weigh less than the whole. - return false; - } - - return BaseClass::ShouldBecomeTorso( info, flDamageThreshold ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CZombie::GatherConditions( void ) -{ - BaseClass::GatherConditions(); - - static int conditionsToClear[] = - { - COND_BLOCKED_BY_DOOR, - COND_DOOR_OPENED, - COND_ZOMBIE_CHARGE_TARGET_MOVED, - }; - - ClearConditions( conditionsToClear, ARRAYSIZE( conditionsToClear ) ); - - if ( m_hBlockingDoor == NULL || - ( m_hBlockingDoor->m_toggle_state == TS_AT_TOP || - m_hBlockingDoor->m_toggle_state == TS_GOING_UP ) ) - { - ClearCondition( COND_BLOCKED_BY_DOOR ); - if ( m_hBlockingDoor != NULL ) - { - SetCondition( COND_DOOR_OPENED ); - m_hBlockingDoor = NULL; - } - } - else - SetCondition( COND_BLOCKED_BY_DOOR ); - - if ( ConditionInterruptsCurSchedule( COND_ZOMBIE_CHARGE_TARGET_MOVED ) ) - { - if ( GetNavigator()->IsGoalActive() ) - { - const float CHARGE_RESET_TOLERANCE = 60.0; - if ( !GetEnemy() || - ( m_vPositionCharged - GetEnemyLKP() ).Length() > CHARGE_RESET_TOLERANCE ) - { - SetCondition( COND_ZOMBIE_CHARGE_TARGET_MOVED ); - } - - } - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- - -int CZombie::SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ) -{ - if ( HasCondition( COND_BLOCKED_BY_DOOR ) && m_hBlockingDoor != NULL ) - { - ClearCondition( COND_BLOCKED_BY_DOOR ); - if ( m_NextTimeToStartDoorBash.Expired() && failedSchedule != SCHED_ZOMBIE_BASH_DOOR ) - return SCHED_ZOMBIE_BASH_DOOR; - m_hBlockingDoor = NULL; - } - - if ( failedSchedule != SCHED_ZOMBIE_CHARGE_ENEMY && - IsPathTaskFailure( taskFailCode ) && - random->RandomInt( 1, 100 ) < 50 ) - { - return SCHED_ZOMBIE_CHARGE_ENEMY; - } - - if ( failedSchedule != SCHED_ZOMBIE_WANDER_ANGRILY && - ( failedSchedule == SCHED_TAKE_COVER_FROM_ENEMY || - failedSchedule == SCHED_CHASE_ENEMY_FAILED ) ) - { - return SCHED_ZOMBIE_WANDER_ANGRILY; - } - - return BaseClass::SelectFailSchedule( failedSchedule, failedTask, taskFailCode ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- - -int CZombie::TranslateSchedule( int scheduleType ) -{ - if ( scheduleType == SCHED_COMBAT_FACE && IsUnreachable( GetEnemy() ) ) - return SCHED_TAKE_COVER_FROM_ENEMY; - - if ( !m_fIsTorso && scheduleType == SCHED_FAIL ) - return SCHED_ZOMBIE_FAIL; - - return BaseClass::TranslateSchedule( scheduleType ); -} - -//--------------------------------------------------------- - -Activity CZombie::NPC_TranslateActivity( Activity newActivity ) -{ - newActivity = BaseClass::NPC_TranslateActivity( newActivity ); - - if ( newActivity == ACT_RUN ) - return ACT_WALK; - - if ( m_fIsTorso && ( newActivity == ACT_ZOMBIE_TANTRUM ) ) - return ACT_IDLE; - - return newActivity; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CZombie::OnStateChange( NPC_STATE OldState, NPC_STATE NewState ) -{ - BaseClass::OnStateChange( OldState, NewState ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- - -void CZombie::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_ZOMBIE_EXPRESS_ANGER: - { - if ( random->RandomInt( 1, 4 ) == 2 ) - { - SetIdealActivity( (Activity)ACT_ZOMBIE_TANTRUM ); - } - else - { - TaskComplete(); - } - - break; - } - - case TASK_ZOMBIE_YAW_TO_DOOR: - { - AssertMsg( m_hBlockingDoor != NULL, "Expected condition handling to break schedule before landing here" ); - if ( m_hBlockingDoor != NULL ) - { - GetMotor()->SetIdealYaw( m_flDoorBashYaw ); - } - TaskComplete(); - break; - } - - case TASK_ZOMBIE_ATTACK_DOOR: - { - m_DurationDoorBash.Reset(); - SetIdealActivity( SelectDoorBash() ); - break; - } - - case TASK_ZOMBIE_CHARGE_ENEMY: - { - if ( !GetEnemy() ) - TaskFail( FAIL_NO_ENEMY ); - else if ( GetNavigator()->SetVectorGoalFromTarget( GetEnemy()->GetLocalOrigin() ) ) - { - m_vPositionCharged = GetEnemy()->GetLocalOrigin(); - TaskComplete(); - } - else - TaskFail( FAIL_NO_ROUTE ); - break; - } - - default: - BaseClass::StartTask( pTask ); - break; - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- - -void CZombie::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_ZOMBIE_ATTACK_DOOR: - { - if ( IsActivityFinished() ) - { - if ( m_DurationDoorBash.Expired() ) - { - TaskComplete(); - m_NextTimeToStartDoorBash.Reset(); - } - else - ResetIdealActivity( SelectDoorBash() ); - } - break; - } - - case TASK_ZOMBIE_CHARGE_ENEMY: - { - break; - } - - case TASK_ZOMBIE_EXPRESS_ANGER: - { - if ( IsActivityFinished() ) - { - TaskComplete(); - } - break; - } - - default: - BaseClass::RunTask( pTask ); - break; - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- - -bool CZombie::OnObstructingDoor( AILocalMoveGoal_t *pMoveGoal, CBaseDoor *pDoor, - float distClear, AIMoveResult_t *pResult ) -{ - if ( BaseClass::OnObstructingDoor( pMoveGoal, pDoor, distClear, pResult ) ) - { - if ( IsMoveBlocked( *pResult ) && pMoveGoal->directTrace.vHitNormal != vec3_origin ) - { - m_hBlockingDoor = pDoor; - m_flDoorBashYaw = UTIL_VecToYaw( pMoveGoal->directTrace.vHitNormal * -1 ); - } - return true; - } - - return false; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- - -Activity CZombie::SelectDoorBash() -{ - if ( random->RandomInt( 1, 3 ) == 1 ) - return ACT_MELEE_ATTACK1; - return (Activity)ACT_ZOMBIE_WALLPOUND; -} - -//--------------------------------------------------------- -// Zombies should scream continuously while burning, so long -// as they are alive... but NOT IN GERMANY! -//--------------------------------------------------------- -void CZombie::Ignite( float flFlameLifetime, bool bNPCOnly, float flSize, bool bCalledByLevelDesigner ) -{ - if( !IsOnFire() && IsAlive() ) - { - BaseClass::Ignite( flFlameLifetime, bNPCOnly, flSize, bCalledByLevelDesigner ); - - if ( !UTIL_IsLowViolence() ) - { - RemoveSpawnFlags( SF_NPC_GAG ); - - MoanSound( envZombieMoanIgnited, ARRAYSIZE( envZombieMoanIgnited ) ); - - if ( m_pMoanSound ) - { - ENVELOPE_CONTROLLER.SoundChangePitch( m_pMoanSound, 120, 1.0 ); - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pMoanSound, 1, 1.0 ); - } - } - } -} - -//--------------------------------------------------------- -// If a zombie stops burning and hasn't died, quiet him down -//--------------------------------------------------------- -void CZombie::Extinguish() -{ - if( m_pMoanSound ) - { - ENVELOPE_CONTROLLER.SoundChangeVolume( m_pMoanSound, 0, 2.0 ); - ENVELOPE_CONTROLLER.SoundChangePitch( m_pMoanSound, 100, 2.0 ); - m_flNextMoanSound = gpGlobals->curtime + random->RandomFloat( 2.0, 4.0 ); - } - - BaseClass::Extinguish(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CZombie::OnTakeDamage_Alive( const CTakeDamageInfo &inputInfo ) -{ -#ifndef HL2_EPISODIC - if ( inputInfo.GetDamageType() & DMG_BUCKSHOT ) - { - if( !m_fIsTorso && inputInfo.GetDamage() > (m_iMaxHealth/3) ) - { - // Always flinch if damaged a lot by buckshot, even if not shot in the head. - // The reason for making sure we did at least 1/3rd of the zombie's max health - // is so the zombie doesn't flinch every time the odd shotgun pellet hits them, - // and so the maximum number of times you'll see a zombie flinch like this is 2.(sjb) - AddGesture( ACT_GESTURE_FLINCH_HEAD ); - } - } -#endif // HL2_EPISODIC - - return BaseClass::OnTakeDamage_Alive( inputInfo ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CZombie::IsHeavyDamage( const CTakeDamageInfo &info ) -{ -#ifdef HL2_EPISODIC - if ( info.GetDamageType() & DMG_BUCKSHOT ) - { - if ( !m_fIsTorso && info.GetDamage() > (m_iMaxHealth/3) ) - return true; - } - - // Randomly treat all damage as heavy - if ( info.GetDamageType() & (DMG_BULLET | DMG_BUCKSHOT) ) - { - // Don't randomly flinch if I'm melee attacking - if ( !HasCondition(COND_CAN_MELEE_ATTACK1) && (RandomFloat() > 0.5) ) - { - // Randomly forget I've flinched, so that I'll be forced to play a big flinch - // If this doesn't happen, it means I may not fully flinch if I recently flinched - if ( RandomFloat() > 0.75 ) - { - Forget(bits_MEMORY_FLINCHED); - } - - return true; - } - } -#endif // HL2_EPISODIC - - return BaseClass::IsHeavyDamage(info); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -#define ZOMBIE_SQUASH_MASS 300.0f // Anything this heavy or heavier squashes a zombie good. (show special fx) -bool CZombie::IsSquashed( const CTakeDamageInfo &info ) -{ - if( GetHealth() > 0 ) - { - return false; - } - - if( info.GetDamageType() & DMG_CRUSH ) - { - IPhysicsObject *pCrusher = info.GetInflictor()->VPhysicsGetObject(); - if( pCrusher && pCrusher->GetMass() >= ZOMBIE_SQUASH_MASS && info.GetInflictor()->WorldSpaceCenter().z > EyePosition().z ) - { - // This heuristic detects when a zombie has been squashed from above by a heavy - // item. Done specifically so we can add gore effects to Ravenholm cartraps. - // The zombie must take physics damage from a 300+kg object that is centered above its eyes (comes from above) - return true; - } - } - - return false; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CZombie::BuildScheduleTestBits( void ) -{ - BaseClass::BuildScheduleTestBits(); - - if( !m_fIsTorso && !IsCurSchedule( SCHED_FLINCH_PHYSICS ) && !m_ActBusyBehavior.IsActive() ) - { - SetCustomInterruptCondition( COND_PHYSICS_DAMAGE ); - } -} - - -//============================================================================= - -AI_BEGIN_CUSTOM_NPC( npc_zombie, CZombie ) - - DECLARE_CONDITION( COND_BLOCKED_BY_DOOR ) - DECLARE_CONDITION( COND_DOOR_OPENED ) - DECLARE_CONDITION( COND_ZOMBIE_CHARGE_TARGET_MOVED ) - - DECLARE_TASK( TASK_ZOMBIE_EXPRESS_ANGER ) - DECLARE_TASK( TASK_ZOMBIE_YAW_TO_DOOR ) - DECLARE_TASK( TASK_ZOMBIE_ATTACK_DOOR ) - DECLARE_TASK( TASK_ZOMBIE_CHARGE_ENEMY ) - - DECLARE_ACTIVITY( ACT_ZOMBIE_TANTRUM ); - DECLARE_ACTIVITY( ACT_ZOMBIE_WALLPOUND ); - - DEFINE_SCHEDULE - ( - SCHED_ZOMBIE_BASH_DOOR, - - " Tasks" - " TASK_SET_ACTIVITY ACTIVITY:ACT_ZOMBIE_TANTRUM" - " TASK_SET_FAIL_SCHEDULE SCHEDULE:SCHED_TAKE_COVER_FROM_ENEMY" - " TASK_ZOMBIE_YAW_TO_DOOR 0" - " TASK_FACE_IDEAL 0" - " TASK_ZOMBIE_ATTACK_DOOR 0" - "" - " Interrupts" - " COND_ZOMBIE_RELEASECRAB" - " COND_ENEMY_DEAD" - " COND_NEW_ENEMY" - " COND_DOOR_OPENED" - ) - - DEFINE_SCHEDULE - ( - SCHED_ZOMBIE_WANDER_ANGRILY, - - " Tasks" - " TASK_WANDER 480240" // 48 units to 240 units. - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 4" - "" - " Interrupts" - " COND_ZOMBIE_RELEASECRAB" - " COND_ENEMY_DEAD" - " COND_NEW_ENEMY" - " COND_DOOR_OPENED" - ) - - DEFINE_SCHEDULE - ( - SCHED_ZOMBIE_CHARGE_ENEMY, - - - " Tasks" - " TASK_ZOMBIE_CHARGE_ENEMY 0" - " TASK_WALK_PATH 0" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_ZOMBIE_TANTRUM" /* placeholder until frustration/rage/fence shake animation available */ - "" - " Interrupts" - " COND_ZOMBIE_RELEASECRAB" - " COND_ENEMY_DEAD" - " COND_NEW_ENEMY" - " COND_DOOR_OPENED" - " COND_ZOMBIE_CHARGE_TARGET_MOVED" - ) - - DEFINE_SCHEDULE - ( - SCHED_ZOMBIE_FAIL, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_ZOMBIE_TANTRUM" - " TASK_WAIT 1" - " TASK_WAIT_PVS 0" - "" - " Interrupts" - " COND_CAN_RANGE_ATTACK1 " - " COND_CAN_RANGE_ATTACK2 " - " COND_CAN_MELEE_ATTACK1 " - " COND_CAN_MELEE_ATTACK2" - " COND_GIVE_WAY" - " COND_DOOR_OPENED" - ) - -AI_END_CUSTOM_NPC() - -//============================================================================= diff --git a/game/server/hl2/npc_zombine.cpp b/game/server/hl2/npc_zombine.cpp deleted file mode 100644 index 1faaf1f90..000000000 --- a/game/server/hl2/npc_zombine.cpp +++ /dev/null @@ -1,1032 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Combine Zombie... Zombie Combine... its like a... Zombine... get it? -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ai_basenpc.h" -#include "ai_default.h" -#include "ai_schedule.h" -#include "ai_hull.h" -#include "ai_motor.h" -#include "ai_memory.h" -#include "ai_route.h" -#include "ai_squad.h" -#include "soundent.h" -#include "game.h" -#include "npcevent.h" -#include "entitylist.h" -#include "ai_task.h" -#include "activitylist.h" -#include "engine/IEngineSound.h" -#include "npc_BaseZombie.h" -#include "movevars_shared.h" -#include "IEffects.h" -#include "props.h" -#include "physics_npc_solver.h" -#include "hl2_player.h" -#include "hl2_gamerules.h" - -#include "basecombatweapon.h" -#include "basegrenade_shared.h" -#include "grenade_frag.h" - -#include "ai_interactions.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -enum -{ - SQUAD_SLOT_ZOMBINE_SPRINT1 = LAST_SHARED_SQUADSLOT, - SQUAD_SLOT_ZOMBINE_SPRINT2, -}; - -#define MIN_SPRINT_TIME 3.5f -#define MAX_SPRINT_TIME 5.5f - -#define MIN_SPRINT_DISTANCE 64.0f -#define MAX_SPRINT_DISTANCE 1024.0f - -#define SPRINT_CHANCE_VALUE 10 -#define SPRINT_CHANCE_VALUE_DARKNESS 50 - -#define GRENADE_PULL_MAX_DISTANCE 256.0f - -#define ZOMBINE_MAX_GRENADES 1 - -int ACT_ZOMBINE_GRENADE_PULL; -int ACT_ZOMBINE_GRENADE_WALK; -int ACT_ZOMBINE_GRENADE_RUN; -int ACT_ZOMBINE_GRENADE_IDLE; -int ACT_ZOMBINE_ATTACK_FAST; -int ACT_ZOMBINE_GRENADE_FLINCH_BACK; -int ACT_ZOMBINE_GRENADE_FLINCH_FRONT; -int ACT_ZOMBINE_GRENADE_FLINCH_WEST; -int ACT_ZOMBINE_GRENADE_FLINCH_EAST; - -int AE_ZOMBINE_PULLPIN; - -extern bool IsAlyxInDarknessMode(); - -ConVar sk_zombie_soldier_health( "sk_zombie_soldier_health","0"); - -float g_flZombineGrenadeTimes = 0; - -class CNPC_Zombine : public CAI_BlendingHost, public CDefaultPlayerPickupVPhysics -{ - DECLARE_DATADESC(); - DECLARE_CLASS( CNPC_Zombine, CAI_BlendingHost ); - -public: - - void Spawn( void ); - void Precache( void ); - - void SetZombieModel( void ); - - virtual void PrescheduleThink( void ); - virtual int SelectSchedule( void ); - virtual void BuildScheduleTestBits( void ); - - virtual void HandleAnimEvent( animevent_t *pEvent ); - - virtual const char *GetLegsModel( void ); - virtual const char *GetTorsoModel( void ); - virtual const char *GetHeadcrabClassname( void ); - virtual const char *GetHeadcrabModel( void ); - - virtual void PainSound( const CTakeDamageInfo &info ); - virtual void DeathSound( const CTakeDamageInfo &info ); - virtual void AlertSound( void ); - virtual void IdleSound( void ); - virtual void AttackSound( void ); - virtual void AttackHitSound( void ); - virtual void AttackMissSound( void ); - virtual void FootstepSound( bool fRightFoot ); - virtual void FootscuffSound( bool fRightFoot ); - virtual void MoanSound( envelopePoint_t *pEnvelope, int iEnvelopeSize ); - - virtual void Event_Killed( const CTakeDamageInfo &info ); - virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - virtual void RunTask( const Task_t *pTask ); - virtual int MeleeAttack1Conditions ( float flDot, float flDist ); - - virtual bool ShouldBecomeTorso( const CTakeDamageInfo &info, float flDamageThreshold ); - - virtual void OnScheduleChange ( void ); - virtual bool CanRunAScriptedNPCInteraction( bool bForced ); - - void GatherGrenadeConditions( void ); - - virtual Activity NPC_TranslateActivity( Activity baseAct ); - - const char *GetMoanSound( int nSound ); - - bool AllowedToSprint( void ); - void Sprint( bool bMadSprint = false ); - void StopSprint( void ); - - void DropGrenade( Vector vDir ); - - bool IsSprinting( void ) { return m_flSprintTime > gpGlobals->curtime; } - bool HasGrenade( void ) { return m_hGrenade != NULL; } - - int TranslateSchedule( int scheduleType ); - - void InputStartSprint ( inputdata_t &inputdata ); - void InputPullGrenade ( inputdata_t &inputdata ); - - virtual CBaseEntity *OnFailedPhysGunPickup ( Vector vPhysgunPos ); - - //Called when we want to let go of a grenade and let the physcannon pick it up. - void ReleaseGrenade( Vector vPhysgunPos ); - - virtual bool HandleInteraction( int interactionType, void *data, CBaseCombatCharacter *sourceEnt ); - - enum - { - COND_ZOMBINE_GRENADE = LAST_BASE_ZOMBIE_CONDITION, - }; - - enum - { - SCHED_ZOMBINE_PULL_GRENADE = LAST_BASE_ZOMBIE_SCHEDULE, - }; - -public: - DEFINE_CUSTOM_AI; - -private: - - float m_flSprintTime; - float m_flSprintRestTime; - - float m_flSuperFastAttackTime; - float m_flGrenadePullTime; - - int m_iGrenadeCount; - - EHANDLE m_hGrenade; - -protected: - static const char *pMoanSounds[]; - -}; - -LINK_ENTITY_TO_CLASS( npc_zombine, CNPC_Zombine ); - -BEGIN_DATADESC( CNPC_Zombine ) - DEFINE_FIELD( m_flSprintTime, FIELD_TIME ), - DEFINE_FIELD( m_flSprintRestTime, FIELD_TIME ), - DEFINE_FIELD( m_flSuperFastAttackTime, FIELD_TIME ), - DEFINE_FIELD( m_hGrenade, FIELD_EHANDLE ), - DEFINE_FIELD( m_flGrenadePullTime, FIELD_TIME ), - DEFINE_FIELD( m_iGrenadeCount, FIELD_INTEGER ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartSprint", InputStartSprint ), - DEFINE_INPUTFUNC( FIELD_VOID, "PullGrenade", InputPullGrenade ), -END_DATADESC() - -//--------------------------------------------------------- -//--------------------------------------------------------- -const char *CNPC_Zombine::pMoanSounds[] = -{ - "ATV_engine_null", -}; - -void CNPC_Zombine::Spawn( void ) -{ - Precache(); - - m_fIsTorso = false; - m_fIsHeadless = false; - -#ifdef HL2_EPISODIC - SetBloodColor( BLOOD_COLOR_ZOMBIE ); -#else - SetBloodColor( BLOOD_COLOR_GREEN ); -#endif // HL2_EPISODIC - - m_iHealth = sk_zombie_soldier_health.GetFloat(); - SetMaxHealth( m_iHealth ); - - m_flFieldOfView = 0.2; - - CapabilitiesClear(); - - BaseClass::Spawn(); - - m_flSprintTime = 0.0f; - m_flSprintRestTime = 0.0f; - - m_flNextMoanSound = gpGlobals->curtime + random->RandomFloat( 1.0, 4.0 ); - - g_flZombineGrenadeTimes = gpGlobals->curtime; - m_flGrenadePullTime = gpGlobals->curtime; - - m_iGrenadeCount = ZOMBINE_MAX_GRENADES; -} - -void CNPC_Zombine::Precache( void ) -{ - BaseClass::Precache(); - - PrecacheModel( "models/zombie/zombie_soldier.mdl" ); - - PrecacheScriptSound( "Zombie.FootstepRight" ); - PrecacheScriptSound( "Zombie.FootstepLeft" ); - PrecacheScriptSound( "Zombine.ScuffRight" ); - PrecacheScriptSound( "Zombine.ScuffLeft" ); - PrecacheScriptSound( "Zombie.AttackHit" ); - PrecacheScriptSound( "Zombie.AttackMiss" ); - PrecacheScriptSound( "Zombine.Pain" ); - PrecacheScriptSound( "Zombine.Die" ); - PrecacheScriptSound( "Zombine.Alert" ); - PrecacheScriptSound( "Zombine.Idle" ); - PrecacheScriptSound( "Zombine.ReadyGrenade" ); - - PrecacheScriptSound( "ATV_engine_null" ); - PrecacheScriptSound( "Zombine.Charge" ); - PrecacheScriptSound( "Zombie.Attack" ); -} - -void CNPC_Zombine::SetZombieModel( void ) -{ - SetModel( "models/zombie/zombie_soldier.mdl" ); - SetHullType( HULL_HUMAN ); - - SetBodygroup( ZOMBIE_BODYGROUP_HEADCRAB, !m_fIsHeadless ); - - SetHullSizeNormal( true ); - SetDefaultEyeOffset(); - SetActivity( ACT_IDLE ); -} - -void CNPC_Zombine::PrescheduleThink( void ) -{ - GatherGrenadeConditions(); - - if( gpGlobals->curtime > m_flNextMoanSound ) - { - if( CanPlayMoanSound() ) - { - // Classic guy idles instead of moans. - IdleSound(); - - m_flNextMoanSound = gpGlobals->curtime + random->RandomFloat( 10.0, 15.0 ); - } - else - { - m_flNextMoanSound = gpGlobals->curtime + random->RandomFloat( 2.5, 5.0 ); - } - } - - if ( HasGrenade () ) - { - CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin() + GetSmoothedVelocity() * 0.5f , 256, 0.1, this, SOUNDENT_CHANNEL_ZOMBINE_GRENADE ); - - if( IsSprinting() && GetEnemy() && GetEnemy()->Classify() == CLASS_PLAYER_ALLY_VITAL && HasCondition( COND_SEE_ENEMY ) ) - { - if( GetAbsOrigin().DistToSqr(GetEnemy()->GetAbsOrigin()) < Square( 144 ) ) - { - StopSprint(); - } - } - } - - BaseClass::PrescheduleThink(); -} - -void CNPC_Zombine::OnScheduleChange( void ) -{ - if ( HasCondition( COND_CAN_MELEE_ATTACK1 ) && IsSprinting() == true ) - { - m_flSuperFastAttackTime = gpGlobals->curtime + 1.0f; - } - - BaseClass::OnScheduleChange(); -} -bool CNPC_Zombine::CanRunAScriptedNPCInteraction( bool bForced ) -{ - if ( HasGrenade() == true ) - return false; - - return BaseClass::CanRunAScriptedNPCInteraction( bForced ); -} - -int CNPC_Zombine::SelectSchedule( void ) -{ - if ( GetHealth() <= 0 ) - return BaseClass::SelectSchedule(); - - if ( HasCondition( COND_ZOMBINE_GRENADE ) ) - { - ClearCondition( COND_ZOMBINE_GRENADE ); - - return SCHED_ZOMBINE_PULL_GRENADE; - } - - return BaseClass::SelectSchedule(); -} - -void CNPC_Zombine::BuildScheduleTestBits( void ) -{ - BaseClass::BuildScheduleTestBits(); - - SetCustomInterruptCondition( COND_ZOMBINE_GRENADE ); -} - -Activity CNPC_Zombine::NPC_TranslateActivity( Activity baseAct ) -{ - if ( baseAct == ACT_MELEE_ATTACK1 ) - { - if ( m_flSuperFastAttackTime > gpGlobals->curtime || HasGrenade() ) - { - return (Activity)ACT_ZOMBINE_ATTACK_FAST; - } - } - - if ( baseAct == ACT_IDLE ) - { - if ( HasGrenade() ) - { - return (Activity)ACT_ZOMBINE_GRENADE_IDLE; - } - } - - return BaseClass::NPC_TranslateActivity( baseAct ); -} - -int CNPC_Zombine::MeleeAttack1Conditions ( float flDot, float flDist ) -{ - int iBase = BaseClass::MeleeAttack1Conditions( flDot, flDist ); - - if( HasGrenade() ) - { - //Adrian: stop spriting if we get close enough to melee and we have a grenade - //this gives NPCs time to move away from you (before it was almost impossible cause of the high sprint speed) - if ( iBase == COND_CAN_MELEE_ATTACK1 ) - { - StopSprint(); - } - } - - return iBase; -} - -void CNPC_Zombine::GatherGrenadeConditions( void ) -{ - if ( m_iGrenadeCount <= 0 ) - return; - - if ( g_flZombineGrenadeTimes > gpGlobals->curtime ) - return; - - if ( m_flGrenadePullTime > gpGlobals->curtime ) - return; - - if ( m_flSuperFastAttackTime >= gpGlobals->curtime ) - return; - - if ( HasGrenade() ) - return; - - if ( GetEnemy() == NULL ) - return; - - if ( FVisible( GetEnemy() ) == false ) - return; - - if ( IsSprinting() ) - return; - - if ( IsOnFire() ) - return; - - if ( IsRunningDynamicInteraction() == true ) - return; - - if ( m_ActBusyBehavior.IsActive() ) - return; - - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - - if ( pPlayer && pPlayer->FVisible( this ) ) - { - float flLengthToPlayer = (pPlayer->GetAbsOrigin() - GetAbsOrigin()).Length(); - float flLengthToEnemy = flLengthToPlayer; - - if ( pPlayer != GetEnemy() ) - { - flLengthToEnemy = ( GetEnemy()->GetAbsOrigin() - GetAbsOrigin()).Length(); - } - - if ( flLengthToPlayer <= GRENADE_PULL_MAX_DISTANCE && flLengthToEnemy <= GRENADE_PULL_MAX_DISTANCE ) - { - float flPullChance = 1.0f - ( flLengthToEnemy / GRENADE_PULL_MAX_DISTANCE ); - m_flGrenadePullTime = gpGlobals->curtime + 0.5f; - - if ( flPullChance >= random->RandomFloat( 0.0f, 1.0f ) ) - { - g_flZombineGrenadeTimes = gpGlobals->curtime + 10.0f; - SetCondition( COND_ZOMBINE_GRENADE ); - } - } - } -} - -int CNPC_Zombine::TranslateSchedule( int scheduleType ) -{ - return BaseClass::TranslateSchedule( scheduleType ); -} - -void CNPC_Zombine::DropGrenade( Vector vDir ) -{ - if ( m_hGrenade == NULL ) - return; - - m_hGrenade->SetParent( NULL ); - m_hGrenade->SetOwnerEntity( NULL ); - - Vector vGunPos; - QAngle angles; - GetAttachment( "grenade_attachment", vGunPos, angles ); - - IPhysicsObject *pPhysObj = m_hGrenade->VPhysicsGetObject(); - - if ( pPhysObj == NULL ) - { - m_hGrenade->SetMoveType( MOVETYPE_VPHYSICS ); - m_hGrenade->SetSolid( SOLID_VPHYSICS ); - m_hGrenade->SetCollisionGroup( COLLISION_GROUP_WEAPON ); - - m_hGrenade->CreateVPhysics(); - } - - if ( pPhysObj ) - { - pPhysObj->Wake(); - pPhysObj->SetPosition( vGunPos, angles, true ); - pPhysObj->ApplyForceCenter( vDir * 0.2f ); - - pPhysObj->RecheckCollisionFilter(); - } - - m_hGrenade = NULL; -} - -void CNPC_Zombine::Event_Killed( const CTakeDamageInfo &info ) -{ - BaseClass::Event_Killed( info ); - - if ( HasGrenade() ) - { - DropGrenade( vec3_origin ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: This is a generic function (to be implemented by sub-classes) to -// handle specific interactions between different types of characters -// (For example the barnacle grabbing an NPC) -// Input : Constant for the type of interaction -// Output : true - if sub-class has a response for the interaction -// false - if sub-class has no response -//----------------------------------------------------------------------------- -bool CNPC_Zombine::HandleInteraction( int interactionType, void *data, CBaseCombatCharacter *sourceEnt ) -{ - if ( interactionType == g_interactionBarnacleVictimGrab ) - { - if ( HasGrenade() ) - { - DropGrenade( vec3_origin ); - } - } - - return BaseClass::HandleInteraction( interactionType, data, sourceEnt ); -} - -void CNPC_Zombine::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - BaseClass::TraceAttack( info, vecDir, ptr ); - - //Only knock grenades off their hands if it's a player doing the damage. - if ( info.GetAttacker() && info.GetAttacker()->IsNPC() ) - return; - - if ( info.GetDamageType() & ( DMG_BULLET | DMG_CLUB ) ) - { - if ( ptr->hitgroup == HITGROUP_LEFTARM ) - { - if ( HasGrenade() ) - { - DropGrenade( info.GetDamageForce() ); - StopSprint(); - } - } - } -} - -void CNPC_Zombine::HandleAnimEvent( animevent_t *pEvent ) -{ - if ( pEvent->event == AE_ZOMBINE_PULLPIN ) - { - Vector vecStart; - QAngle angles; - GetAttachment( "grenade_attachment", vecStart, angles ); - - CBaseGrenade *pGrenade = Fraggrenade_Create( vecStart, vec3_angle, vec3_origin, AngularImpulse( 0, 0, 0 ), this, 3.5f, true ); - - if ( pGrenade ) - { - // Move physobject to shadow - IPhysicsObject *pPhysicsObject = pGrenade->VPhysicsGetObject(); - - if ( pPhysicsObject ) - { - pGrenade->VPhysicsDestroyObject(); - - int iAttachment = LookupAttachment( "grenade_attachment"); - - pGrenade->SetMoveType( MOVETYPE_NONE ); - pGrenade->SetSolid( SOLID_NONE ); - pGrenade->SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - - pGrenade->SetAbsOrigin( vecStart ); - pGrenade->SetAbsAngles( angles ); - - pGrenade->SetParent( this, iAttachment ); - - pGrenade->SetDamage( 200.0f ); - m_hGrenade = pGrenade; - - EmitSound( "Zombine.ReadyGrenade" ); - - // Tell player allies nearby to regard me! - CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); - CAI_BaseNPC *pNPC; - for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - pNPC = ppAIs[i]; - - if( pNPC->Classify() == CLASS_PLAYER_ALLY || pNPC->Classify() == CLASS_PLAYER_ALLY_VITAL && pNPC->FVisible(this) ) - { - int priority; - Disposition_t disposition; - - priority = pNPC->IRelationPriority(this); - disposition = pNPC->IRelationType(this); - - pNPC->AddEntityRelationship( this, disposition, priority + 1 ); - } - } - } - - m_iGrenadeCount--; - } - - return; - } - - if ( pEvent->event == AE_NPC_ATTACK_BROADCAST ) - { - if ( HasGrenade() ) - return; - } - - BaseClass::HandleAnimEvent( pEvent ); -} - -bool CNPC_Zombine::AllowedToSprint( void ) -{ - if ( IsOnFire() ) - return false; - - //If you're sprinting then there's no reason to sprint again. - if ( IsSprinting() ) - return false; - - int iChance = SPRINT_CHANCE_VALUE; - - CHL2_Player *pPlayer = dynamic_cast ( AI_GetSinglePlayer() ); - - if ( pPlayer ) - { - if ( HL2GameRules()->IsAlyxInDarknessMode() && pPlayer->FlashlightIsOn() == false ) - { - iChance = SPRINT_CHANCE_VALUE_DARKNESS; - } - - //Bigger chance of this happening if the player is not looking at the zombie - if ( pPlayer->FInViewCone( this ) == false ) - { - iChance *= 2; - } - } - - if ( HasGrenade() ) - { - iChance *= 4; - } - - //Below 25% health they'll always sprint - if ( ( GetHealth() > GetMaxHealth() * 0.5f ) ) - { - if ( IsStrategySlotRangeOccupied( SQUAD_SLOT_ZOMBINE_SPRINT1, SQUAD_SLOT_ZOMBINE_SPRINT2 ) == true ) - return false; - - if ( random->RandomInt( 0, 100 ) > iChance ) - return false; - - if ( m_flSprintRestTime > gpGlobals->curtime ) - return false; - } - - float flLength = ( GetEnemy()->WorldSpaceCenter() - WorldSpaceCenter() ).Length(); - - if ( flLength > MAX_SPRINT_DISTANCE ) - return false; - - return true; -} - -void CNPC_Zombine::StopSprint( void ) -{ - GetNavigator()->SetMovementActivity( ACT_WALK ); - - m_flSprintTime = gpGlobals->curtime; - m_flSprintRestTime = m_flSprintTime + random->RandomFloat( 2.5f, 5.0f ); -} - -void CNPC_Zombine::Sprint( bool bMadSprint ) -{ - if ( IsSprinting() ) - return; - - OccupyStrategySlotRange( SQUAD_SLOT_ZOMBINE_SPRINT1, SQUAD_SLOT_ZOMBINE_SPRINT2 ); - GetNavigator()->SetMovementActivity( ACT_RUN ); - - float flSprintTime = random->RandomFloat( MIN_SPRINT_TIME, MAX_SPRINT_TIME ); - - //If holding a grenade then sprint until it blows up. - if ( HasGrenade() || bMadSprint == true ) - { - flSprintTime = 9999; - } - - m_flSprintTime = gpGlobals->curtime + flSprintTime; - - //Don't sprint for this long after I'm done with this sprint run. - m_flSprintRestTime = m_flSprintTime + random->RandomFloat( 2.5f, 5.0f ); - - EmitSound( "Zombine.Charge" ); -} - -void CNPC_Zombine::RunTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_WAIT_FOR_MOVEMENT_STEP: - case TASK_WAIT_FOR_MOVEMENT: - { - BaseClass::RunTask( pTask ); - - if ( IsOnFire() && IsSprinting() ) - { - StopSprint(); - } - - //Only do this if I have an enemy - if ( GetEnemy() ) - { - if ( AllowedToSprint() == true ) - { - Sprint( ( GetHealth() <= GetMaxHealth() * 0.5f ) ); - return; - } - - if ( HasGrenade() ) - { - if ( IsSprinting() ) - { - GetNavigator()->SetMovementActivity( (Activity)ACT_ZOMBINE_GRENADE_RUN ); - } - else - { - GetNavigator()->SetMovementActivity( (Activity)ACT_ZOMBINE_GRENADE_WALK ); - } - - return; - } - - if ( GetNavigator()->GetMovementActivity() != ACT_WALK ) - { - if ( IsSprinting() == false ) - { - GetNavigator()->SetMovementActivity( ACT_WALK ); - } - } - } - else - { - GetNavigator()->SetMovementActivity( ACT_WALK ); - } - - break; - } - default: - { - BaseClass::RunTask( pTask ); - break; - } - } -} - -void CNPC_Zombine::InputStartSprint ( inputdata_t &inputdata ) -{ - Sprint(); -} - -void CNPC_Zombine::InputPullGrenade ( inputdata_t &inputdata ) -{ - g_flZombineGrenadeTimes = gpGlobals->curtime + 5.0f; - SetCondition( COND_ZOMBINE_GRENADE ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns a moan sound for this class of zombie. -//----------------------------------------------------------------------------- -const char *CNPC_Zombine::GetMoanSound( int nSound ) -{ - return pMoanSounds[ nSound % ARRAYSIZE( pMoanSounds ) ]; -} - -//----------------------------------------------------------------------------- -// Purpose: Sound of a footstep -//----------------------------------------------------------------------------- -void CNPC_Zombine::FootstepSound( bool fRightFoot ) -{ - if( fRightFoot ) - { - EmitSound( "Zombie.FootstepRight" ); - } - else - { - EmitSound( "Zombie.FootstepLeft" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Overloaded so that explosions don't split the zombine in twain. -//----------------------------------------------------------------------------- -bool CNPC_Zombine::ShouldBecomeTorso( const CTakeDamageInfo &info, float flDamageThreshold ) -{ - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Sound of a foot sliding/scraping -//----------------------------------------------------------------------------- -void CNPC_Zombine::FootscuffSound( bool fRightFoot ) -{ - if( fRightFoot ) - { - EmitSound( "Zombine.ScuffRight" ); - } - else - { - EmitSound( "Zombine.ScuffLeft" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Play a random attack hit sound -//----------------------------------------------------------------------------- -void CNPC_Zombine::AttackHitSound( void ) -{ - EmitSound( "Zombie.AttackHit" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Play a random attack miss sound -//----------------------------------------------------------------------------- -void CNPC_Zombine::AttackMissSound( void ) -{ - // Play a random attack miss sound - EmitSound( "Zombie.AttackMiss" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Zombine::PainSound( const CTakeDamageInfo &info ) -{ - // We're constantly taking damage when we are on fire. Don't make all those noises! - if ( IsOnFire() ) - { - return; - } - - EmitSound( "Zombine.Pain" ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CNPC_Zombine::DeathSound( const CTakeDamageInfo &info ) -{ - EmitSound( "Zombine.Die" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_Zombine::AlertSound( void ) -{ - EmitSound( "Zombine.Alert" ); - - // Don't let a moan sound cut off the alert sound. - m_flNextMoanSound += random->RandomFloat( 2.0, 4.0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: Play a random idle sound. -//----------------------------------------------------------------------------- -void CNPC_Zombine::IdleSound( void ) -{ - if( GetState() == NPC_STATE_IDLE && random->RandomFloat( 0, 1 ) == 0 ) - { - // Moan infrequently in IDLE state. - return; - } - - if( IsSlumped() ) - { - // Sleeping zombies are quiet. - return; - } - - EmitSound( "Zombine.Idle" ); - MakeAISpookySound( 360.0f ); -} - -//----------------------------------------------------------------------------- -// Purpose: Play a random attack sound. -//----------------------------------------------------------------------------- -void CNPC_Zombine::AttackSound( void ) -{ - -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -const char *CNPC_Zombine::GetHeadcrabModel( void ) -{ - return "models/headcrabclassic.mdl"; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const char *CNPC_Zombine::GetLegsModel( void ) -{ - return "models/zombie/zombie_soldier_legs.mdl"; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -const char *CNPC_Zombine::GetTorsoModel( void ) -{ - return "models/zombie/zombie_soldier_torso.mdl"; -} - -//--------------------------------------------------------- -// Classic zombie only uses moan sound if on fire. -//--------------------------------------------------------- -void CNPC_Zombine::MoanSound( envelopePoint_t *pEnvelope, int iEnvelopeSize ) -{ - if( IsOnFire() ) - { - BaseClass::MoanSound( pEnvelope, iEnvelopeSize ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the classname (ie "npc_headcrab") to spawn when our headcrab bails. -//----------------------------------------------------------------------------- -const char *CNPC_Zombine::GetHeadcrabClassname( void ) -{ - return "npc_headcrab"; -} - -void CNPC_Zombine::ReleaseGrenade( Vector vPhysgunPos ) -{ - if ( HasGrenade() == false ) - return; - - Vector vDir = vPhysgunPos - m_hGrenade->GetAbsOrigin(); - VectorNormalize( vDir ); - - Activity aActivity; - - Vector vForward, vRight; - GetVectors( &vForward, &vRight, NULL ); - - float flDotForward = DotProduct( vForward, vDir ); - float flDotRight = DotProduct( vRight, vDir ); - - bool bNegativeForward = false; - bool bNegativeRight = false; - - if ( flDotForward < 0.0f ) - { - bNegativeForward = true; - flDotForward = flDotForward * -1; - } - - if ( flDotRight < 0.0f ) - { - bNegativeRight = true; - flDotRight = flDotRight * -1; - } - - if ( flDotRight > flDotForward ) - { - if ( bNegativeRight == true ) - aActivity = (Activity)ACT_ZOMBINE_GRENADE_FLINCH_WEST; - else - aActivity = (Activity)ACT_ZOMBINE_GRENADE_FLINCH_EAST; - } - else - { - if ( bNegativeForward == true ) - aActivity = (Activity)ACT_ZOMBINE_GRENADE_FLINCH_BACK; - else - aActivity = (Activity)ACT_ZOMBINE_GRENADE_FLINCH_FRONT; - } - - AddGesture( aActivity ); - - DropGrenade( vec3_origin ); - - if ( IsSprinting() ) - { - StopSprint(); - } - else - { - Sprint(); - } -} - -CBaseEntity *CNPC_Zombine::OnFailedPhysGunPickup( Vector vPhysgunPos ) -{ - CBaseEntity *pGrenade = m_hGrenade; - ReleaseGrenade( vPhysgunPos ); - return pGrenade; -} - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC( npc_zombine, CNPC_Zombine ) - - //Squad slots - DECLARE_SQUADSLOT( SQUAD_SLOT_ZOMBINE_SPRINT1 ) - DECLARE_SQUADSLOT( SQUAD_SLOT_ZOMBINE_SPRINT2 ) - - DECLARE_CONDITION( COND_ZOMBINE_GRENADE ) - - DECLARE_ACTIVITY( ACT_ZOMBINE_GRENADE_PULL ) - DECLARE_ACTIVITY( ACT_ZOMBINE_GRENADE_WALK ) - DECLARE_ACTIVITY( ACT_ZOMBINE_GRENADE_RUN ) - DECLARE_ACTIVITY( ACT_ZOMBINE_GRENADE_IDLE ) - DECLARE_ACTIVITY( ACT_ZOMBINE_ATTACK_FAST ) - DECLARE_ACTIVITY( ACT_ZOMBINE_GRENADE_FLINCH_BACK ) - DECLARE_ACTIVITY( ACT_ZOMBINE_GRENADE_FLINCH_FRONT ) - DECLARE_ACTIVITY( ACT_ZOMBINE_GRENADE_FLINCH_WEST) - DECLARE_ACTIVITY( ACT_ZOMBINE_GRENADE_FLINCH_EAST ) - - DECLARE_ANIMEVENT( AE_ZOMBINE_PULLPIN ) - - - DEFINE_SCHEDULE - ( - SCHED_ZOMBINE_PULL_GRENADE, - - " Tasks" - " TASK_PLAY_SEQUENCE ACTIVITY:ACT_ZOMBINE_GRENADE_PULL" - - - " Interrupts" - - ) - -AI_END_CUSTOM_NPC() - - - diff --git a/game/server/hl2/point_apc_controller.cpp b/game/server/hl2/point_apc_controller.cpp deleted file mode 100644 index 678cec87b..000000000 --- a/game/server/hl2/point_apc_controller.cpp +++ /dev/null @@ -1,498 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "basecombatweapon.h" -#include "explode.h" -#include "eventqueue.h" -#include "gamerules.h" -#include "ammodef.h" -#include "in_buttons.h" -#include "soundent.h" -#include "ndebugoverlay.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" - -#include "player.h" -#include "entitylist.h" -#include "iservervehicle.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SF_TANK_ACTIVE 0x0001 - - -class CAPCController : public CPointEntity -{ - typedef CPointEntity BaseClass; -public: - ~CAPCController( void ); - void Spawn( void ); - void Precache( void ); - bool KeyValue( const char *szKeyName, const char *szValue ); - void Think( void ); - void TrackTarget( void ); - - void StartRotSound( void ); - void StopRotSound( void ); - - // Bmodels don't go across transitions - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } - - inline bool IsActive( void ) { return (m_spawnflags & SF_TANK_ACTIVE)?TRUE:FALSE; } - - // Input handlers. - void InputActivate( inputdata_t &inputdata ); - void InputDeactivate( inputdata_t &inputdata ); - - void ActivateRocketGuidance(void); - void DeactivateRocketGuidance(void); - - bool InRange( float range ); - - Vector WorldBarrelPosition( void ) - { - EntityMatrix tmp; - tmp.InitFromEntity( this ); - return tmp.LocalToWorld( m_barrelPos ); - } - - void UpdateMatrix( void ) - { - m_parentMatrix.InitFromEntity( GetParent() ? GetParent() : NULL ); - } - QAngle AimBarrelAt( const Vector &parentTarget ); - - bool ShouldSavePhysics() { return false; } - - DECLARE_DATADESC(); - - CBaseEntity *FindTarget( string_t targetName, CBaseEntity *pActivator ); - -protected: - float m_yawCenter; // "Center" yaw - float m_yawRate; // Max turn rate to track targets - // Zero is full rotation - float m_yawTolerance; // Tolerance angle - - float m_pitchCenter; // "Center" pitch - float m_pitchRate; // Max turn rate on pitch - float m_pitchTolerance; // Tolerance angle - - float m_minRange; // Minimum range to aim/track - float m_maxRange; // Max range to aim/track - - Vector m_barrelPos; // Length of the barrel - - Vector m_sightOrigin; // Last sight of target - - string_t m_soundStartRotate; - string_t m_soundStopRotate; - string_t m_soundLoopRotate; - - string_t m_targetEntityName; - EHANDLE m_hTarget; - EntityMatrix m_parentMatrix; - - COutputVector m_OnFireAtTarget; - - float m_flFiringDelay; - bool m_bFireDelayed; -}; - -LINK_ENTITY_TO_CLASS( point_apc_controller, CAPCController ); - -BEGIN_DATADESC( CAPCController ) - - DEFINE_FIELD( m_yawCenter, FIELD_FLOAT ), - DEFINE_KEYFIELD( m_yawRate, FIELD_FLOAT, "yawrate" ), - DEFINE_KEYFIELD( m_yawTolerance, FIELD_FLOAT, "yawtolerance" ), - - - DEFINE_FIELD( m_pitchCenter, FIELD_FLOAT ), - DEFINE_KEYFIELD( m_pitchRate, FIELD_FLOAT, "pitchrate" ), - DEFINE_KEYFIELD( m_pitchTolerance, FIELD_FLOAT, "pitchtolerance" ), - - DEFINE_KEYFIELD( m_minRange, FIELD_FLOAT, "minRange" ), - DEFINE_KEYFIELD( m_maxRange, FIELD_FLOAT, "maxRange" ), - DEFINE_FIELD( m_barrelPos, FIELD_VECTOR ), - DEFINE_FIELD( m_sightOrigin, FIELD_VECTOR ), - DEFINE_KEYFIELD( m_soundStartRotate, FIELD_SOUNDNAME, "rotatestartsound" ), - DEFINE_KEYFIELD( m_soundStopRotate, FIELD_SOUNDNAME, "rotatestopsound" ), - DEFINE_KEYFIELD( m_soundLoopRotate, FIELD_SOUNDNAME, "rotatesound" ), - DEFINE_KEYFIELD( m_targetEntityName, FIELD_STRING, "targetentityname" ), - DEFINE_FIELD( m_hTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_parentMatrix, FIELD_VMATRIX_WORLDSPACE ), - DEFINE_FIELD( m_flFiringDelay, FIELD_FLOAT ), - DEFINE_FIELD( m_bFireDelayed, FIELD_BOOLEAN ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ), - DEFINE_INPUTFUNC( FIELD_VOID, "Deactivate", InputDeactivate ), - - // Outputs - DEFINE_OUTPUT(m_OnFireAtTarget, "OnFireAtTarget"), - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CAPCController::~CAPCController( void ) -{ - if ( m_soundLoopRotate != NULL_STRING ) - { - StopSound( entindex(), CHAN_STATIC, STRING(m_soundLoopRotate) ); - } -} - -//------------------------------------------------------------------------------ -// Purpose: Input handler for activating the tank. -//------------------------------------------------------------------------------ -void CAPCController::InputActivate( inputdata_t &inputdata ) -{ - ActivateRocketGuidance(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAPCController::ActivateRocketGuidance(void) -{ - m_spawnflags |= SF_TANK_ACTIVE; - SetNextThink( gpGlobals->curtime + 0.1f ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for deactivating the tank. -//----------------------------------------------------------------------------- -void CAPCController::InputDeactivate( inputdata_t &inputdata ) -{ - DeactivateRocketGuidance(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAPCController::DeactivateRocketGuidance(void) -{ - m_spawnflags &= ~SF_TANK_ACTIVE; - StopRotSound(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : targetName - -// pActivator - -//----------------------------------------------------------------------------- -CBaseEntity *CAPCController::FindTarget( string_t targetName, CBaseEntity *pActivator ) -{ - return gEntList.FindEntityGenericNearest( STRING( targetName ), GetAbsOrigin(), 0, this, pActivator ); -} - -//----------------------------------------------------------------------------- -// Purpose: Caches entity key values until spawn is called. -// Input : szKeyName - -// szValue - -// Output : -//----------------------------------------------------------------------------- -bool CAPCController::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "barrel")) - { - m_barrelPos.x = atof(szValue); - } - else if (FStrEq(szKeyName, "barrely")) - { - m_barrelPos.y = atof(szValue); - } - else if (FStrEq(szKeyName, "barrelz")) - { - m_barrelPos.z = atof(szValue); - } - else - return BaseClass::KeyValue( szKeyName, szValue ); - - return true; -} - -//----------------------------------------- -// Spawn -//----------------------------------------- -void CAPCController::Spawn( void ) -{ - Precache(); - - m_yawCenter = GetLocalAngles().y; - m_pitchCenter = GetLocalAngles().x; - - if ( IsActive() ) - { - SetNextThink( gpGlobals->curtime + 1.0f ); - } - - UpdateMatrix(); -} - - -//----------------------------------------- -// Precache -//----------------------------------------- -void CAPCController::Precache( void ) -{ - if ( m_soundStartRotate != NULL_STRING ) - PrecacheScriptSound( STRING(m_soundStartRotate) ); - if ( m_soundStopRotate != NULL_STRING ) - PrecacheScriptSound( STRING(m_soundStopRotate) ); - if ( m_soundLoopRotate != NULL_STRING ) - PrecacheScriptSound( STRING(m_soundLoopRotate) ); -} - - -//----------------------------------------- -// InRange -//----------------------------------------- -bool CAPCController::InRange( float range ) -{ - if ( range < m_minRange ) - return FALSE; - if ( m_maxRange > 0 && range > m_maxRange ) - return FALSE; - - return TRUE; -} - - -//----------------------------------------- -// Think -//----------------------------------------- -void CAPCController::Think( void ) -{ - // refresh the matrix - UpdateMatrix(); - - SetLocalAngularVelocity( vec3_angle ); - TrackTarget(); - - if ( fabs(GetLocalAngularVelocity().x) > 1 || fabs(GetLocalAngularVelocity().y) > 1 ) - StartRotSound(); - else - StopRotSound(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Aim the offset barrel at a position in parent space -// Input : parentTarget - the position of the target in parent space -// Output : Vector - angles in local space -//----------------------------------------------------------------------------- -QAngle CAPCController::AimBarrelAt( const Vector &parentTarget ) -{ - Vector target = parentTarget - GetLocalOrigin(); - float quadTarget = target.LengthSqr(); - float quadTargetXY = target.x*target.x + target.y*target.y; - - // We're trying to aim the offset barrel at an arbitrary point. - // To calculate this, I think of the target as being on a sphere with - // it's center at the origin of the gun. - // The rotation we need is the opposite of the rotation that moves the target - // along the surface of that sphere to intersect with the gun's shooting direction - // To calculate that rotation, we simply calculate the intersection of the ray - // coming out of the barrel with the target sphere (that's the new target position) - // and use atan2() to get angles - - // angles from target pos to center - float targetToCenterYaw = atan2( target.y, target.x ); - float centerToGunYaw = atan2( m_barrelPos.y, sqrt( quadTarget - (m_barrelPos.y*m_barrelPos.y) ) ); - - float targetToCenterPitch = atan2( target.z, sqrt( quadTargetXY ) ); - float centerToGunPitch = atan2( -m_barrelPos.z, sqrt( quadTarget - (m_barrelPos.z*m_barrelPos.z) ) ); - return QAngle( -RAD2DEG(targetToCenterPitch+centerToGunPitch), RAD2DEG( targetToCenterYaw + centerToGunYaw ), 0 ); -} - -void CAPCController::TrackTarget( void ) -{ - trace_t tr; - bool updateTime = FALSE, lineOfSight; - QAngle angles; - Vector barrelEnd; - CBaseEntity *pTarget = NULL; - - barrelEnd.Init(); - - if ( IsActive() ) - { - SetNextThink( gpGlobals->curtime + 0.1f ); - } - else - { - return; - } - - // ----------------------------------- - // Get world target position - // ----------------------------------- - barrelEnd = WorldBarrelPosition(); - Vector worldTargetPosition; - CBaseEntity *pEntity = (CBaseEntity *)m_hTarget; - if ( !pEntity || ( pEntity->GetFlags() & FL_NOTARGET ) ) - { - m_hTarget = FindTarget( m_targetEntityName, NULL ); - if ( IsActive() ) - { - SetNextThink( gpGlobals->curtime + 2 ); // Wait 2 sec s - } - - return; - } - pTarget = pEntity; - - // Calculate angle needed to aim at target - worldTargetPosition = pEntity->EyePosition(); - - float range = (worldTargetPosition - barrelEnd).Length(); - - if ( !InRange( range ) ) - { - m_bFireDelayed = false; - return; - } - - UTIL_TraceLine( barrelEnd, worldTargetPosition, MASK_BLOCKLOS, this, COLLISION_GROUP_NONE, &tr ); - - lineOfSight = FALSE; - // No line of sight, don't track - if ( tr.fraction == 1.0 || tr.m_pEnt == pTarget ) - { - lineOfSight = TRUE; - - CBaseEntity *pInstance = pTarget; - if ( InRange( range ) && pInstance && pInstance->IsAlive() ) - { - updateTime = TRUE; - - // Sight position is BodyTarget with no noise (so gun doesn't bob up and down) - m_sightOrigin = pInstance->BodyTarget( GetLocalOrigin(), false ); - } - } - - // Convert targetPosition to parent - angles = AimBarrelAt( m_parentMatrix.WorldToLocal( m_sightOrigin ) ); - - - // Force the angles to be relative to the center position - float offsetY = UTIL_AngleDistance( angles.y, m_yawCenter ); - float offsetX = UTIL_AngleDistance( angles.x, m_pitchCenter ); - angles.y = m_yawCenter + offsetY; - angles.x = m_pitchCenter + offsetX; - - // Move toward target at rate or less - float distY = UTIL_AngleDistance( angles.y, GetLocalAngles().y ); - - QAngle vecAngVel = GetLocalAngularVelocity(); - vecAngVel.y = distY * 10; - vecAngVel.y = clamp( vecAngVel.y, -m_yawRate, m_yawRate ); - - // Move toward target at rate or less - float distX = UTIL_AngleDistance( angles.x, GetLocalAngles().x ); - vecAngVel.x = distX * 10; - vecAngVel.x = clamp( vecAngVel.x, -m_pitchRate, m_pitchRate ); - SetLocalAngularVelocity( vecAngVel ); - - SetMoveDoneTime( 0.1 ); - - Vector forward; - AngleVectors( GetLocalAngles(), &forward ); - forward = m_parentMatrix.ApplyRotation( forward ); - - AngleVectors(angles, &forward); - - if ( lineOfSight == TRUE ) - { - // FIXME: This will ultimately have to deal with NPCs being in the vehicle as well - // See if the target is in a vehicle. If so, check its relationship - CBasePlayer *pPlayer = ToBasePlayer( pTarget ); - if ( pPlayer && pPlayer->IsInAVehicle() ) - { - IServerVehicle *pVehicle = pPlayer->GetVehicle(); - if ( pVehicle->ClassifyPassenger( pPlayer, CLASS_PLAYER ) == CLASS_PLAYER) - { - if ( !m_bFireDelayed ) - { - m_bFireDelayed = true; - m_flFiringDelay = gpGlobals->curtime + 1.5; // setup delay time before we start firing - return; - } - if ( gpGlobals->curtime > m_flFiringDelay ) - { - m_OnFireAtTarget.Set(forward, this, this); // tell apc to fire rockets, and what direction - } - } - } - } - else - { - m_bFireDelayed = false; // reset flag since we can no longer see target - } -} - -void CAPCController::StartRotSound( void ) -{ - if ( m_soundLoopRotate != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - filter.MakeReliable(); - - EmitSound_t ep; - ep.m_nChannel = CHAN_STATIC; - ep.m_pSoundName = (char*)STRING(m_soundLoopRotate); - ep.m_SoundLevel = SNDLVL_NORM; - ep.m_flVolume = 0.85; - - EmitSound( filter, entindex(), ep ); - } - - if ( m_soundStartRotate != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_BODY; - ep.m_pSoundName = (char*)STRING(m_soundStartRotate); - ep.m_SoundLevel = SNDLVL_NORM; - ep.m_flVolume = 1.0f; - - EmitSound( filter, entindex(), ep ); - } -} - - -void CAPCController::StopRotSound( void ) -{ - if ( m_soundLoopRotate != NULL_STRING ) - { - StopSound( entindex(), CHAN_STATIC, (char*)STRING(m_soundLoopRotate) ); - } - if ( m_soundStopRotate != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_BODY; - ep.m_pSoundName = (char*)STRING(m_soundStopRotate); - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - } -} - diff --git a/game/server/hl2/prop_combine_ball.cpp b/game/server/hl2/prop_combine_ball.cpp deleted file mode 100644 index 8416dd294..000000000 --- a/game/server/hl2/prop_combine_ball.cpp +++ /dev/null @@ -1,2194 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: combine ball - can be held by the super physcannon and launched -// by the AR2's alt-fire -// -//=============================================================================// - -#include "cbase.h" -#include "prop_combine_ball.h" -#include "props.h" -#include "explode.h" -#include "saverestore_utlvector.h" -#include "hl2_shareddefs.h" -#include "materialsystem/imaterial.h" -#include "beam_flags.h" -#include "physics_prop_ragdoll.h" -#include "soundent.h" -#include "soundenvelope.h" -#include "te_effect_dispatch.h" -#include "ai_basenpc.h" -#include "npc_bullseye.h" -#include "filters.h" -#include "SpriteTrail.h" -#include "decals.h" -#include "hl2_player.h" -#include "eventqueue.h" -#include "physics_collisionevent.h" -#include "GameStats.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define PROP_COMBINE_BALL_MODEL "models/effects/combineball.mdl" -#define PROP_COMBINE_BALL_SPRITE_TRAIL "sprites/combineball_trail_black_1.vmt" - -#define PROP_COMBINE_BALL_LIFETIME 4.0f // Seconds - -#define PROP_COMBINE_BALL_HOLD_DISSOLVE_TIME 8.0f - -#define SF_COMBINE_BALL_BOUNCING_IN_SPAWNER 0x10000 - -#define MAX_COMBINEBALL_RADIUS 12 - -ConVar sk_npc_dmg_combineball( "sk_npc_dmg_combineball","15", FCVAR_REPLICATED); -ConVar sk_combineball_guidefactor( "sk_combineball_guidefactor","0.5", FCVAR_REPLICATED); -ConVar sk_combine_ball_search_radius( "sk_combine_ball_search_radius", "512", FCVAR_REPLICATED); -ConVar sk_combineball_seek_angle( "sk_combineball_seek_angle","15.0", FCVAR_REPLICATED); -ConVar sk_combineball_seek_kill( "sk_combineball_seek_kill","0", FCVAR_REPLICATED); - -// For our ring explosion -int s_nExplosionTexture = -1; - -//----------------------------------------------------------------------------- -// Context think -//----------------------------------------------------------------------------- -static const char *s_pWhizThinkContext = "WhizThinkContext"; -static const char *s_pHoldDissolveContext = "HoldDissolveContext"; -static const char *s_pExplodeTimerContext = "ExplodeTimerContext"; -static const char *s_pAnimThinkContext = "AnimThinkContext"; -static const char *s_pCaptureContext = "CaptureContext"; -static const char *s_pRemoveContext = "RemoveContext"; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : radius - -// Output : CBaseEntity -//----------------------------------------------------------------------------- -CBaseEntity *CreateCombineBall( const Vector &origin, const Vector &velocity, float radius, float mass, float lifetime, CBaseEntity *pOwner ) -{ - CPropCombineBall *pBall = static_cast( CreateEntityByName( "prop_combine_ball" ) ); - pBall->SetRadius( radius ); - - pBall->SetAbsOrigin( origin ); - pBall->SetOwnerEntity( pOwner ); - pBall->SetOriginalOwner( pOwner ); - - pBall->SetAbsVelocity( velocity ); - pBall->Spawn(); - - pBall->SetState( CPropCombineBall::STATE_THROWN ); - pBall->SetSpeed( velocity.Length() ); - - pBall->EmitSound( "NPC_CombineBall.Launch" ); - - PhysSetGameFlags( pBall->VPhysicsGetObject(), FVPHYSICS_WAS_THROWN ); - - pBall->StartWhizSoundThink(); - - pBall->SetMass( mass ); - pBall->StartLifetime( lifetime ); - pBall->SetWeaponLaunched( true ); - - return pBall; -} - -//----------------------------------------------------------------------------- -// Purpose: Allows game to know if the physics object should kill allies or not -//----------------------------------------------------------------------------- -CBasePlayer *CPropCombineBall::HasPhysicsAttacker( float dt ) -{ - // Must have an owner - if ( GetOwnerEntity() == NULL ) - return false; - - // Must be a player - if ( GetOwnerEntity()->IsPlayer() == false ) - return false; - - // We don't care about the time passed in - return static_cast(GetOwnerEntity()); -} - -//----------------------------------------------------------------------------- -// Purpose: Determines whether a physics object is a combine ball or not -// Input : *pObj - Object to test -// Output : Returns true on success, false on failure. -// Notes : This function cannot identify a combine ball that is held by -// the physcannon because any object held by the physcannon is -// COLLISIONGROUP_DEBRIS. -//----------------------------------------------------------------------------- -bool UTIL_IsCombineBall( CBaseEntity *pEntity ) -{ - // Must be the correct collision group - if ( pEntity->GetCollisionGroup() != HL2COLLISION_GROUP_COMBINE_BALL ) - return false; - - //NOTENOTE: This allows ANY combine ball to pass the test - - /* - CPropCombineBall *pBall = dynamic_cast(pEntity); - - if ( pBall && pBall->WasWeaponLaunched() ) - return false; - */ - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Determines whether a physics object is an AR2 combine ball or not -// Input : *pEntity - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool UTIL_IsAR2CombineBall( CBaseEntity *pEntity ) -{ - // Must be the correct collision group - if ( pEntity->GetCollisionGroup() != HL2COLLISION_GROUP_COMBINE_BALL ) - return false; - - CPropCombineBall *pBall = dynamic_cast(pEntity); - - if ( pBall && pBall->WasWeaponLaunched() ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Uses a deeper casting check to determine if pEntity is a combine -// ball. This function exists because the normal (much faster) check -// in UTIL_IsCombineBall() can never identify a combine ball held by -// the physcannon because the physcannon changes the held entity's -// collision group. -// Input : *pEntity - Entity to check -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool UTIL_IsCombineBallDefinite( CBaseEntity *pEntity ) -{ - CPropCombineBall *pBall = dynamic_cast(pEntity); - - return pBall != NULL; -} - -//----------------------------------------------------------------------------- -// -// Spawns combine balls -// -//----------------------------------------------------------------------------- -#define SF_SPAWNER_START_DISABLED 0x1000 -#define SF_SPAWNER_POWER_SUPPLY 0x2000 - - - -//----------------------------------------------------------------------------- -// Implementation of CPropCombineBall -//----------------------------------------------------------------------------- -LINK_ENTITY_TO_CLASS( prop_combine_ball, CPropCombineBall ); - -//----------------------------------------------------------------------------- -// Save/load: -//----------------------------------------------------------------------------- -BEGIN_DATADESC( CPropCombineBall ) - - DEFINE_FIELD( m_flLastBounceTime, FIELD_TIME ), - DEFINE_FIELD( m_flRadius, FIELD_FLOAT ), - DEFINE_FIELD( m_nState, FIELD_CHARACTER ), - DEFINE_FIELD( m_pGlowTrail, FIELD_CLASSPTR ), - DEFINE_SOUNDPATCH( m_pHoldingSound ), - DEFINE_FIELD( m_bFiredGrabbedOutput, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bEmit, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bHeld, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bLaunched, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bStruckEntity, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bWeaponLaunched, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bForward, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flSpeed, FIELD_FLOAT ), - - DEFINE_FIELD( m_flNextDamageTime, FIELD_TIME ), - DEFINE_FIELD( m_flLastCaptureTime, FIELD_TIME ), - DEFINE_FIELD( m_bCaptureInProgress, FIELD_BOOLEAN ), - DEFINE_FIELD( m_nBounceCount, FIELD_INTEGER ), - DEFINE_FIELD( m_nMaxBounces, FIELD_INTEGER ), - DEFINE_FIELD( m_bBounceDie, FIELD_BOOLEAN ), - - - DEFINE_FIELD( m_hSpawner, FIELD_EHANDLE ), - - DEFINE_THINKFUNC( ExplodeThink ), - DEFINE_THINKFUNC( WhizSoundThink ), - DEFINE_THINKFUNC( DieThink ), - DEFINE_THINKFUNC( DissolveThink ), - DEFINE_THINKFUNC( DissolveRampSoundThink ), - DEFINE_THINKFUNC( AnimThink ), - DEFINE_THINKFUNC( CaptureBySpawner ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Explode", InputExplode ), - DEFINE_INPUTFUNC( FIELD_VOID, "FadeAndRespawn", InputFadeAndRespawn ), - DEFINE_INPUTFUNC( FIELD_VOID, "Kill", InputKill ), - DEFINE_INPUTFUNC( FIELD_VOID, "Socketed", InputSocketed ), - -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CPropCombineBall, DT_PropCombineBall ) - SendPropBool( SENDINFO( m_bEmit ) ), - SendPropFloat( SENDINFO( m_flRadius ), 0, SPROP_NOSCALE ), - SendPropBool( SENDINFO( m_bHeld ) ), - SendPropBool( SENDINFO( m_bLaunched ) ), -END_SEND_TABLE() - -//----------------------------------------------------------------------------- -// Gets at the spawner -//----------------------------------------------------------------------------- -inline CFuncCombineBallSpawner *CPropCombineBall::GetSpawner() -{ - return m_hSpawner; -} - -//----------------------------------------------------------------------------- -// Precache -//----------------------------------------------------------------------------- -void CPropCombineBall::Precache( void ) -{ - //NOTENOTE: We don't call into the base class because it chains multiple - // precaches we don't need to incur - - PrecacheModel( PROP_COMBINE_BALL_MODEL ); - PrecacheModel( PROP_COMBINE_BALL_SPRITE_TRAIL ); - - s_nExplosionTexture = PrecacheModel( "sprites/lgtning.vmt" ); - - PrecacheScriptSound( "NPC_CombineBall.Launch" ); - PrecacheScriptSound( "NPC_CombineBall.KillImpact" ); - - if ( hl2_episodic.GetBool() ) - { - PrecacheScriptSound( "NPC_CombineBall_Episodic.Explosion" ); - PrecacheScriptSound( "NPC_CombineBall_Episodic.WhizFlyby" ); - PrecacheScriptSound( "NPC_CombineBall_Episodic.Impact" ); - } - else - { - PrecacheScriptSound( "NPC_CombineBall.Explosion" ); - PrecacheScriptSound( "NPC_CombineBall.WhizFlyby" ); - PrecacheScriptSound( "NPC_CombineBall.Impact" ); - } - - PrecacheScriptSound( "NPC_CombineBall.HoldingInPhysCannon" ); -} - - -//----------------------------------------------------------------------------- -// Spherical vphysics -//----------------------------------------------------------------------------- -bool CPropCombineBall::OverridePropdata() -{ - return true; -} - - -//----------------------------------------------------------------------------- -// Spherical vphysics -//----------------------------------------------------------------------------- -void CPropCombineBall::SetState( int state ) -{ - if ( m_nState != state ) - { - if ( m_nState == STATE_NOT_THROWN ) - { - m_flLastCaptureTime = gpGlobals->curtime; - } - - m_nState = state; - } -} - -bool CPropCombineBall::IsInField() const -{ - return (m_nState == STATE_NOT_THROWN); -} - - -//----------------------------------------------------------------------------- -// Sets the radius -//----------------------------------------------------------------------------- -void CPropCombineBall::SetRadius( float flRadius ) -{ - m_flRadius = clamp( flRadius, 1, MAX_COMBINEBALL_RADIUS ); -} - -//----------------------------------------------------------------------------- -// Create vphysics -//----------------------------------------------------------------------------- -bool CPropCombineBall::CreateVPhysics() -{ - SetSolid( SOLID_BBOX ); - - float flSize = m_flRadius; - - SetCollisionBounds( Vector(-flSize, -flSize, -flSize), Vector(flSize, flSize, flSize) ); - objectparams_t params = g_PhysDefaultObjectParams; - params.pGameData = static_cast(this); - int nMaterialIndex = physprops->GetSurfaceIndex("metal_bouncy"); - IPhysicsObject *pPhysicsObject = physenv->CreateSphereObject( flSize, nMaterialIndex, GetAbsOrigin(), GetAbsAngles(), ¶ms, false ); - if ( !pPhysicsObject ) - return false; - - VPhysicsSetObject( pPhysicsObject ); - SetMoveType( MOVETYPE_VPHYSICS ); - pPhysicsObject->Wake(); - - pPhysicsObject->SetMass( 750.0f ); - pPhysicsObject->EnableGravity( false ); - pPhysicsObject->EnableDrag( false ); - - float flDamping = 0.0f; - float flAngDamping = 0.5f; - pPhysicsObject->SetDamping( &flDamping, &flAngDamping ); - pPhysicsObject->SetInertia( Vector( 1e30, 1e30, 1e30 ) ); - - if( WasFiredByNPC() ) - { - // Don't do impact damage. Just touch them and do your dissolve damage and move on. - PhysSetGameFlags( pPhysicsObject, FVPHYSICS_NO_NPC_IMPACT_DMG ); - } - else - { - PhysSetGameFlags( pPhysicsObject, FVPHYSICS_DMG_DISSOLVE | FVPHYSICS_HEAVY_OBJECT ); - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Spawn: -//----------------------------------------------------------------------------- -void CPropCombineBall::Spawn( void ) -{ - BaseClass::Spawn(); - - SetModel( PROP_COMBINE_BALL_MODEL ); - - if( ShouldHitPlayer() ) - { - // This allows the combine ball to hit the player. - SetCollisionGroup( HL2COLLISION_GROUP_COMBINE_BALL_NPC ); - } - else - { - SetCollisionGroup( HL2COLLISION_GROUP_COMBINE_BALL ); - } - - CreateVPhysics(); - - Vector vecAbsVelocity = GetAbsVelocity(); - VPhysicsGetObject()->SetVelocity( &vecAbsVelocity, NULL ); - - m_nState = STATE_NOT_THROWN; - m_flLastBounceTime = -1.0f; - m_bFiredGrabbedOutput = false; - m_bForward = true; - m_bCaptureInProgress = false; - - // No shadow! - AddEffects( EF_NOSHADOW ); - - // Start up the eye trail - m_pGlowTrail = CSpriteTrail::SpriteTrailCreate( PROP_COMBINE_BALL_SPRITE_TRAIL, GetAbsOrigin(), false ); - - if ( m_pGlowTrail != NULL ) - { - m_pGlowTrail->FollowEntity( this ); - m_pGlowTrail->SetTransparency( kRenderTransAdd, 0, 0, 0, 255, kRenderFxNone ); - m_pGlowTrail->SetStartWidth( m_flRadius ); - m_pGlowTrail->SetEndWidth( 0 ); - m_pGlowTrail->SetLifeTime( 0.1f ); - m_pGlowTrail->TurnOff(); - } - - m_bEmit = true; - m_bHeld = false; - m_bLaunched = false; - m_bStruckEntity = false; - m_bWeaponLaunched = false; - - m_flNextDamageTime = gpGlobals->curtime; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCombineBall::StartAnimating( void ) -{ - // Start our animation cycle. Use the random to avoid everything thinking the same frame - SetContextThink( &CPropCombineBall::AnimThink, gpGlobals->curtime + random->RandomFloat( 0.0f, 0.1f), s_pAnimThinkContext ); - - int nSequence = LookupSequence( "idle" ); - - SetCycle( 0 ); - m_flAnimTime = gpGlobals->curtime; - ResetSequence( nSequence ); - ResetClientsideFrame(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCombineBall::StopAnimating( void ) -{ - SetContextThink( NULL, gpGlobals->curtime, s_pAnimThinkContext ); -} - -//----------------------------------------------------------------------------- -// Put it into the spawner -//----------------------------------------------------------------------------- -void CPropCombineBall::CaptureBySpawner( ) -{ - m_bCaptureInProgress = true; - m_bFiredGrabbedOutput = false; - - // Slow down the ball - Vector vecVelocity; - VPhysicsGetObject()->GetVelocity( &vecVelocity, NULL ); - float flSpeed = VectorNormalize( vecVelocity ); - if ( flSpeed > 25.0f ) - { - vecVelocity *= flSpeed * 0.4f; - VPhysicsGetObject()->SetVelocity( &vecVelocity, NULL ); - - // Slow it down until we can set its velocity ok - SetContextThink( &CPropCombineBall::CaptureBySpawner, gpGlobals->curtime + 0.01f, s_pCaptureContext ); - return; - } - - // Ok, we're captured - SetContextThink( NULL, gpGlobals->curtime, s_pCaptureContext ); - ReplaceInSpawner( GetSpawner()->GetBallSpeed() ); - m_bCaptureInProgress = false; -} - -//----------------------------------------------------------------------------- -// Put it into the spawner -//----------------------------------------------------------------------------- -void CPropCombineBall::ReplaceInSpawner( float flSpeed ) -{ - m_bForward = true; - m_nState = STATE_NOT_THROWN; - - // Prevent it from exploding - ClearLifetime( ); - - // Stop whiz noises - SetContextThink( NULL, gpGlobals->curtime, s_pWhizThinkContext ); - - // Slam velocity to what the field wants - Vector vecTarget, vecVelocity; - GetSpawner()->GetTargetEndpoint( m_bForward, &vecTarget ); - VectorSubtract( vecTarget, GetAbsOrigin(), vecVelocity ); - VectorNormalize( vecVelocity ); - vecVelocity *= flSpeed; - VPhysicsGetObject()->SetVelocity( &vecVelocity, NULL ); - - // Set our desired speed to the spawner's speed. This will be - // our speed on our first bounce in the field. - SetSpeed( flSpeed ); -} - - -float CPropCombineBall::LastCaptureTime() const -{ - if ( IsInField() || IsBeingCaptured() ) - return gpGlobals->curtime; - - return m_flLastCaptureTime; -} - -//----------------------------------------------------------------------------- -// Purpose: Starts the lifetime countdown on the ball -// Input : flDuration - number of seconds to live before exploding -//----------------------------------------------------------------------------- -void CPropCombineBall::StartLifetime( float flDuration ) -{ - SetContextThink( &CPropCombineBall::ExplodeThink, gpGlobals->curtime + flDuration, s_pExplodeTimerContext ); -} - -//----------------------------------------------------------------------------- -// Purpose: Stops the lifetime on the ball from expiring -//----------------------------------------------------------------------------- -void CPropCombineBall::ClearLifetime( void ) -{ - // Prevent it from exploding - SetContextThink( NULL, gpGlobals->curtime, s_pExplodeTimerContext ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : mass - -//----------------------------------------------------------------------------- -void CPropCombineBall::SetMass( float mass ) -{ - IPhysicsObject *pObj = VPhysicsGetObject(); - - if ( pObj != NULL ) - { - pObj->SetMass( mass ); - pObj->SetInertia( Vector( 500, 500, 500 ) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CPropCombineBall::ShouldHitPlayer() const -{ - if ( GetOwnerEntity() ) - { - CAI_BaseNPC *pNPC = GetOwnerEntity()->MyNPCPointer(); - if ( pNPC && !pNPC->IsPlayerAlly() ) - { - return true; - } - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCombineBall::InputKill( inputdata_t &inputdata ) -{ - // tell owner ( if any ) that we're dead.This is mostly for NPCMaker functionality. - CBaseEntity *pOwner = GetOwnerEntity(); - if ( pOwner ) - { - pOwner->DeathNotice( this ); - SetOwnerEntity( NULL ); - } - - UTIL_Remove( this ); - - NotifySpawnerOfRemoval(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCombineBall::InputSocketed( inputdata_t &inputdata ) -{ - // tell owner ( if any ) that we're dead.This is mostly for NPCMaker functionality. - CBaseEntity *pOwner = GetOwnerEntity(); - if ( pOwner ) - { - pOwner->DeathNotice( this ); - SetOwnerEntity( NULL ); - } - - // if our owner is a player, tell them we were socketed - CHL2_Player *pPlayer = dynamic_cast( pOwner ); - if ( pPlayer ) - { - pPlayer->CombineBallSocketed( this ); - } - - UTIL_Remove( this ); - - NotifySpawnerOfRemoval(); -} - -//----------------------------------------------------------------------------- -// Cleanup. -//----------------------------------------------------------------------------- -void CPropCombineBall::UpdateOnRemove() -{ - if ( m_pGlowTrail != NULL ) - { - UTIL_Remove( m_pGlowTrail ); - m_pGlowTrail = NULL; - } - - //Sigh... this is the only place where I can get a message after the ball is done dissolving. - if ( hl2_episodic.GetBool() ) - { - if ( IsDissolving() ) - { - if ( GetSpawner() ) - { - GetSpawner()->BallGrabbed( this ); - NotifySpawnerOfRemoval(); - } - } - } - - BaseClass::UpdateOnRemove(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCombineBall::ExplodeThink( void ) -{ - DoExplosion(); -} - -//----------------------------------------------------------------------------- -// Purpose: Tell the respawner to make a new one -//----------------------------------------------------------------------------- -void CPropCombineBall::NotifySpawnerOfRemoval( void ) -{ - if ( GetSpawner() ) - { - GetSpawner()->RespawnBallPostExplosion(); - } -} - -//----------------------------------------------------------------------------- -// Fade out. -//----------------------------------------------------------------------------- -void CPropCombineBall::DieThink() -{ - if ( GetSpawner() ) - { - //Let the spawner know we died so it does it's thing - if( hl2_episodic.GetBool() && IsInField() ) - { - GetSpawner()->BallGrabbed( this ); - } - - GetSpawner()->RespawnBall( 0.1 ); - } - - UTIL_Remove( this ); -} - - -//----------------------------------------------------------------------------- -// Fade out. -//----------------------------------------------------------------------------- -void CPropCombineBall::FadeOut( float flDuration ) -{ - AddSolidFlags( FSOLID_NOT_SOLID ); - - // Start up the eye trail - if ( m_pGlowTrail != NULL ) - { - m_pGlowTrail->SetBrightness( 0, flDuration ); - } - - SetThink( &CPropCombineBall::DieThink ); - SetNextThink( gpGlobals->curtime + flDuration ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCombineBall::StartWhizSoundThink( void ) -{ - SetContextThink( &CPropCombineBall::WhizSoundThink, gpGlobals->curtime + 2.0f * TICK_INTERVAL, s_pWhizThinkContext ); -} - -//----------------------------------------------------------------------------- -// Danger sounds. -//----------------------------------------------------------------------------- -void CPropCombineBall::WhizSoundThink() -{ - Vector vecPosition, vecVelocity; - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - - if ( pPhysicsObject == NULL ) - { - //NOTENOTE: We should always have been created at this point - Assert( 0 ); - SetContextThink( &CPropCombineBall::WhizSoundThink, gpGlobals->curtime + 2.0f * TICK_INTERVAL, s_pWhizThinkContext ); - return; - } - - pPhysicsObject->GetPosition( &vecPosition, NULL ); - pPhysicsObject->GetVelocity( &vecVelocity, NULL ); - - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - if ( pPlayer ) - { - Vector vecDelta; - VectorSubtract( pPlayer->GetAbsOrigin(), vecPosition, vecDelta ); - VectorNormalize( vecDelta ); - if ( DotProduct( vecDelta, vecVelocity ) > 0.5f ) - { - Vector vecEndPoint; - VectorMA( vecPosition, 2.0f * TICK_INTERVAL, vecVelocity, vecEndPoint ); - float flDist = CalcDistanceToLineSegment( pPlayer->GetAbsOrigin(), vecPosition, vecEndPoint ); - if ( flDist < 200.0f ) - { - CPASAttenuationFilter filter( vecPosition, ATTN_NORM ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_STATIC; - if ( hl2_episodic.GetBool() ) - { - ep.m_pSoundName = "NPC_CombineBall_Episodic.WhizFlyby"; - } - else - { - ep.m_pSoundName = "NPC_CombineBall.WhizFlyby"; - } - ep.m_flVolume = 1.0f; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - - SetContextThink( &CPropCombineBall::WhizSoundThink, gpGlobals->curtime + 0.5f, s_pWhizThinkContext ); - return; - } - } - } - - SetContextThink( &CPropCombineBall::WhizSoundThink, gpGlobals->curtime + 2.0f * TICK_INTERVAL, s_pWhizThinkContext ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCombineBall::SetBallAsLaunched( void ) -{ - // Give the ball a duration - StartLifetime( PROP_COMBINE_BALL_LIFETIME ); - - m_bHeld = false; - m_bLaunched = true; - SetState( STATE_THROWN ); - - VPhysicsGetObject()->SetMass( 750.0f ); - VPhysicsGetObject()->SetInertia( Vector( 1e30, 1e30, 1e30 ) ); - - StopLoopingSounds(); - EmitSound( "NPC_CombineBall.Launch" ); - - WhizSoundThink(); -} - -//----------------------------------------------------------------------------- -// Lighten the mass so it's zippy toget to the gun -//----------------------------------------------------------------------------- -void CPropCombineBall::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) -{ - CDefaultPlayerPickupVPhysics::OnPhysGunPickup( pPhysGunUser, reason ); - - if ( m_nMaxBounces == -1 ) - { - m_nMaxBounces = 0; - } - - if ( !m_bFiredGrabbedOutput ) - { - if ( GetSpawner() ) - { - GetSpawner()->BallGrabbed( this ); - } - - m_bFiredGrabbedOutput = true; - } - - if ( m_pGlowTrail ) - { - m_pGlowTrail->TurnOff(); - m_pGlowTrail->SetRenderColor( 0, 0, 0, 0 ); - } - - if ( reason != PUNTED_BY_CANNON ) - { - SetState( STATE_HOLDING ); - CPASAttenuationFilter filter( GetAbsOrigin(), ATTN_NORM ); - filter.MakeReliable(); - - EmitSound_t ep; - ep.m_nChannel = CHAN_STATIC; - - if( hl2_episodic.GetBool() ) - { - ep.m_pSoundName = "NPC_CombineBall_Episodic.HoldingInPhysCannon"; - } - else - { - ep.m_pSoundName = "NPC_CombineBall.HoldingInPhysCannon"; - } - - ep.m_flVolume = 1.0f; - ep.m_SoundLevel = SNDLVL_NORM; - - // Now we own this ball - SetPlayerLaunched( pPhysGunUser ); - - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - m_pHoldingSound = controller.SoundCreate( filter, entindex(), ep ); - controller.Play( m_pHoldingSound, 1.0f, 100 ); - - // Don't collide with anything we may have to pull the ball through - SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - - VPhysicsGetObject()->SetMass( 20.0f ); - VPhysicsGetObject()->SetInertia( Vector( 100, 100, 100 ) ); - - // Make it not explode - ClearLifetime( ); - - m_bHeld = true; - m_bLaunched = false; - - //Let the ball know is not being captured by one of those ball fields anymore. - // - m_bCaptureInProgress = false; - - - SetContextThink( &CPropCombineBall::DissolveRampSoundThink, gpGlobals->curtime + GetBallHoldSoundRampTime(), s_pHoldDissolveContext ); - - StartAnimating(); - } - else - { - Vector vecVelocity; - VPhysicsGetObject()->GetVelocity( &vecVelocity, NULL ); - - SetSpeed( vecVelocity.Length() ); - - // Set us as being launched by the player - SetPlayerLaunched( pPhysGunUser ); - - SetBallAsLaunched(); - - StopAnimating(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Reset the ball to be deadly to NPCs after we've picked it up -//----------------------------------------------------------------------------- -void CPropCombineBall::SetPlayerLaunched( CBasePlayer *pOwner ) -{ - // Now we own this ball - SetOwnerEntity( pOwner ); - SetWeaponLaunched( false ); - - if( VPhysicsGetObject() ) - { - PhysClearGameFlags( VPhysicsGetObject(), FVPHYSICS_NO_NPC_IMPACT_DMG ); - PhysSetGameFlags( VPhysicsGetObject(), FVPHYSICS_DMG_DISSOLVE | FVPHYSICS_HEAVY_OBJECT ); - } -} - -//----------------------------------------------------------------------------- -// Activate death-spin! -//----------------------------------------------------------------------------- -void CPropCombineBall::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ) -{ - CDefaultPlayerPickupVPhysics::OnPhysGunDrop( pPhysGunUser, Reason ); - - SetState( STATE_THROWN ); - WhizSoundThink(); - - m_bHeld = false; - m_bLaunched = true; - - // Stop with the dissolving - SetContextThink( NULL, gpGlobals->curtime, s_pHoldDissolveContext ); - - // We're ready to start colliding again. - SetCollisionGroup( HL2COLLISION_GROUP_COMBINE_BALL ); - - if ( m_pGlowTrail ) - { - m_pGlowTrail->TurnOn(); - m_pGlowTrail->SetRenderColor( 255, 255, 255, 255 ); - } - - // Set our desired speed to be launched at - SetSpeed( 1500.0f ); - SetPlayerLaunched( pPhysGunUser ); - - if ( Reason != LAUNCHED_BY_CANNON ) - { - // Choose a random direction (forward facing) - Vector vecForward; - pPhysGunUser->GetVectors( &vecForward, NULL, NULL ); - - QAngle shotAng; - VectorAngles( vecForward, shotAng ); - - // Offset by some small cone - shotAng[PITCH] += random->RandomInt( -55, 55 ); - shotAng[YAW] += random->RandomInt( -55, 55 ); - - AngleVectors( shotAng, &vecForward, NULL, NULL ); - - vecForward *= GetSpeed(); - - VPhysicsGetObject()->SetVelocity( &vecForward, &vec3_origin ); - } - else - { - // This will have the consequence of making it so that the - // ball is launched directly down the crosshair even if the player is moving. - VPhysicsGetObject()->SetVelocity( &vec3_origin, &vec3_origin ); - } - - SetBallAsLaunched(); - StopAnimating(); -} - -//------------------------------------------------------------------------------ -// Stop looping sounds -//------------------------------------------------------------------------------ -void CPropCombineBall::StopLoopingSounds() -{ - if ( m_pHoldingSound ) - { - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.Shutdown( m_pHoldingSound ); - controller.SoundDestroy( m_pHoldingSound ); - m_pHoldingSound = NULL; - } -} - - -//------------------------------------------------------------------------------ -// Pow! -//------------------------------------------------------------------------------ -void CPropCombineBall::DissolveRampSoundThink( ) -{ - float dt = GetBallHoldDissolveTime() - GetBallHoldSoundRampTime(); - if ( m_pHoldingSound ) - { - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundChangePitch( m_pHoldingSound, 150, dt ); - } - SetContextThink( &CPropCombineBall::DissolveThink, gpGlobals->curtime + dt, s_pHoldDissolveContext ); -} - - -//------------------------------------------------------------------------------ -// Pow! -//------------------------------------------------------------------------------ -void CPropCombineBall::DissolveThink( ) -{ - DoExplosion(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -float CPropCombineBall::GetBallHoldDissolveTime() -{ - float flDissolveTime = PROP_COMBINE_BALL_HOLD_DISSOLVE_TIME; - - if( g_pGameRules->IsSkillLevel( 1 ) && hl2_episodic.GetBool() ) - { - // Give players more time to handle/aim combine balls on Easy. - flDissolveTime *= 1.5f; - } - - return flDissolveTime; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -float CPropCombineBall::GetBallHoldSoundRampTime() -{ - return GetBallHoldDissolveTime() - 1.0f; -} - -//------------------------------------------------------------------------------ -// Pow! -//------------------------------------------------------------------------------ -void CPropCombineBall::DoExplosion( ) -{ - // don't do this twice - if ( GetMoveType() == MOVETYPE_NONE ) - return; - - if ( PhysIsInCallback() ) - { - g_PostSimulationQueue.QueueCall( this, &CPropCombineBall::DoExplosion ); - return; - } - // Tell the respawner to make a new one - if ( GetSpawner() ) - { - GetSpawner()->RespawnBallPostExplosion(); - } - - //Shockring - CBroadcastRecipientFilter filter2; - - if ( OutOfBounces() == false ) - { - if ( hl2_episodic.GetBool() ) - { - EmitSound( "NPC_CombineBall_Episodic.Explosion" ); - } - else - { - EmitSound( "NPC_CombineBall.Explosion" ); - } - - UTIL_ScreenShake( GetAbsOrigin(), 20.0f, 150.0, 1.0, 1250.0f, SHAKE_START ); - - CEffectData data; - - data.m_vOrigin = GetAbsOrigin(); - - DispatchEffect( "cball_explode", data ); - - te->BeamRingPoint( filter2, 0, GetAbsOrigin(), //origin - m_flRadius, //start radius - 1024, //end radius - s_nExplosionTexture, //texture - 0, //halo index - 0, //start frame - 2, //framerate - 0.2f, //life - 64, //width - 0, //spread - 0, //amplitude - 255, //r - 255, //g - 225, //b - 32, //a - 0, //speed - FBEAM_FADEOUT - ); - - //Shockring - te->BeamRingPoint( filter2, 0, GetAbsOrigin(), //origin - m_flRadius, //start radius - 1024, //end radius - s_nExplosionTexture, //texture - 0, //halo index - 0, //start frame - 2, //framerate - 0.5f, //life - 64, //width - 0, //spread - 0, //amplitude - 255, //r - 255, //g - 225, //b - 64, //a - 0, //speed - FBEAM_FADEOUT - ); - } - else - { - //Shockring - te->BeamRingPoint( filter2, 0, GetAbsOrigin(), //origin - 128, //start radius - 384, //end radius - s_nExplosionTexture, //texture - 0, //halo index - 0, //start frame - 2, //framerate - 0.25f, //life - 48, //width - 0, //spread - 0, //amplitude - 255, //r - 255, //g - 225, //b - 64, //a - 0, //speed - FBEAM_FADEOUT - ); - } - - if( hl2_episodic.GetBool() ) - { - CSoundEnt::InsertSound( SOUND_COMBAT | SOUND_CONTEXT_EXPLOSION, WorldSpaceCenter(), 180, 0.25, this ); - } - - // Turn us off and wait because we need our trails to finish up properly - SetAbsVelocity( vec3_origin ); - SetMoveType( MOVETYPE_NONE ); - AddSolidFlags( FSOLID_NOT_SOLID ); - - m_bEmit = false; - - - if( !m_bStruckEntity && hl2_episodic.GetBool() && GetOwnerEntity() != NULL ) - { - // Notify the player proxy that this combine ball missed so that it can fire an output. - CHL2_Player *pPlayer = dynamic_cast( GetOwnerEntity() ); - if ( pPlayer ) - { - pPlayer->MissedAR2AltFire(); - } - } - - SetContextThink( &CPropCombineBall::SUB_Remove, gpGlobals->curtime + 0.5f, s_pRemoveContext ); - StopLoopingSounds(); -} - -//----------------------------------------------------------------------------- -// Enable/disable -//----------------------------------------------------------------------------- -void CPropCombineBall::InputExplode( inputdata_t &inputdata ) -{ - DoExplosion(); -} - -//----------------------------------------------------------------------------- -// Enable/disable -//----------------------------------------------------------------------------- -void CPropCombineBall::InputFadeAndRespawn( inputdata_t &inputdata ) -{ - FadeOut( 0.1f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCombineBall::CollisionEventToTrace( int index, gamevcollisionevent_t *pEvent, trace_t &tr ) -{ - UTIL_ClearTrace( tr ); - pEvent->pInternalData->GetSurfaceNormal( tr.plane.normal ); - pEvent->pInternalData->GetContactPoint( tr.endpos ); - tr.plane.dist = DotProduct( tr.plane.normal, tr.endpos ); - VectorMA( tr.endpos, -1.0f, pEvent->preVelocity[index], tr.startpos ); - tr.m_pEnt = pEvent->pEntities[!index]; - tr.fraction = 0.01f; // spoof! -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CPropCombineBall::DissolveEntity( CBaseEntity *pEntity ) -{ - if( pEntity->IsEFlagSet( EFL_NO_DISSOLVE ) ) - return false; - -#ifdef HL2MP - if ( pEntity->IsPlayer() ) - { - m_bStruckEntity = true; - return false; - } -#endif - - if( !pEntity->IsNPC() && !(dynamic_cast(pEntity)) ) - return false; - - pEntity->GetBaseAnimating()->Dissolve( "", gpGlobals->curtime, false, ENTITY_DISSOLVE_NORMAL ); - - // Note that we've struck an entity - m_bStruckEntity = true; - - // Force an NPC to not drop their weapon if dissolved -// CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pEntity ); -// if ( pBCC != NULL ) -// { -// pEntity->AddSpawnFlags( SF_NPC_NO_WEAPON_DROP ); -// } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCombineBall::OnHitEntity( CBaseEntity *pHitEntity, float flSpeed, int index, gamevcollisionevent_t *pEvent ) -{ - // Detonate on the strider + the bone followers in the strider - if ( FClassnameIs( pHitEntity, "npc_strider" ) || - (pHitEntity->GetOwnerEntity() && FClassnameIs( pHitEntity->GetOwnerEntity(), "npc_strider" )) ) - { - DoExplosion(); - return; - } - - CTakeDamageInfo info( this, GetOwnerEntity(), GetAbsVelocity(), GetAbsOrigin(), sk_npc_dmg_combineball.GetFloat(), DMG_DISSOLVE ); - - bool bIsDissolving = (pHitEntity->GetFlags() & FL_DISSOLVING) != 0; - bool bShouldHit = pHitEntity->PassesDamageFilter( info ); - - //One more check - //Combine soldiers are not allowed to hurt their friends with combine balls (they can still shoot and hurt each other with grenades). - CBaseCombatCharacter *pBCC = pHitEntity->MyCombatCharacterPointer(); - - if ( pBCC ) - { - bShouldHit = pBCC->IRelationType( GetOwnerEntity() ) != D_LI; - } - - if ( !bIsDissolving && bShouldHit == true ) - { - if ( pHitEntity->PassesDamageFilter( info ) ) - { - if( WasFiredByNPC() || m_nMaxBounces == -1 ) - { - // Since Combine balls fired by NPCs do a metered dose of damage per impact, we have to ignore touches - // for a little while after we hit someone, or the ball will immediately touch them again and do more - // damage. - if( gpGlobals->curtime >= m_flNextDamageTime ) - { - EmitSound( "NPC_CombineBall.KillImpact" ); - - if ( pHitEntity->IsNPC() && pHitEntity->Classify() != CLASS_PLAYER_ALLY_VITAL && hl2_episodic.GetBool() == true ) - { - if ( pHitEntity->Classify() != CLASS_PLAYER_ALLY || pHitEntity->Classify() == CLASS_PLAYER_ALLY && m_bStruckEntity == false ) - { - info.SetDamage( pHitEntity->GetMaxHealth() ); - m_bStruckEntity = true; - } - } - else - { - // Ignore touches briefly. - m_flNextDamageTime = gpGlobals->curtime + 0.1f; - } - - pHitEntity->TakeDamage( info ); - } - } - else - { - if ( (m_nState == STATE_THROWN) && (pHitEntity->IsNPC() || dynamic_cast(pHitEntity) )) - { - EmitSound( "NPC_CombineBall.KillImpact" ); - } - if ( (m_nState != STATE_HOLDING) ) - { - - CBasePlayer *pPlayer = ToBasePlayer( GetOwnerEntity() ); - if ( pPlayer && UTIL_IsAR2CombineBall( this ) && ToBaseCombatCharacter( pHitEntity ) ) - { - gamestats->Event_WeaponHit( pPlayer, false, "weapon_ar2", info ); - } - - DissolveEntity( pHitEntity ); - if ( pHitEntity->ClassMatches( "npc_hunter" ) ) - { - DoExplosion(); - return; - } - } - } - } - } - - Vector vecFinalVelocity; - if ( IsInField() ) - { - // Don't deflect when in a spawner field - vecFinalVelocity = pEvent->preVelocity[index]; - } - else - { - // Don't slow down when hitting other entities. - vecFinalVelocity = pEvent->postVelocity[index]; - VectorNormalize( vecFinalVelocity ); - vecFinalVelocity *= GetSpeed(); - } - PhysCallbackSetVelocity( pEvent->pObjects[index], vecFinalVelocity ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCombineBall::DoImpactEffect( const Vector &preVelocity, int index, gamevcollisionevent_t *pEvent ) -{ - // Do that crazy impact effect! - trace_t tr; - CollisionEventToTrace( !index, pEvent, tr ); - - CBaseEntity *pTraceEntity = pEvent->pEntities[index]; - UTIL_TraceLine( tr.startpos - preVelocity * 2.0f, tr.startpos + preVelocity * 2.0f, MASK_SOLID, pTraceEntity, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction < 1.0f ) - { - // See if we hit the sky - if ( tr.surface.flags & SURF_SKY ) - { - DoExplosion(); - return; - } - - // Send the effect over - CEffectData data; - - data.m_flRadius = 16; - data.m_vNormal = tr.plane.normal; - data.m_vOrigin = tr.endpos + tr.plane.normal * 1.0f; - - DispatchEffect( "cball_bounce", data ); - } - - if ( hl2_episodic.GetBool() ) - { - EmitSound( "NPC_CombineBall_Episodic.Impact" ); - } - else - { - EmitSound( "NPC_CombineBall.Impact" ); - } -} - -//----------------------------------------------------------------------------- -// Tells whether this combine ball should consider deflecting towards this entity. -//----------------------------------------------------------------------------- -bool CPropCombineBall::IsAttractiveTarget( CBaseEntity *pEntity ) -{ - if ( !pEntity->IsAlive() ) - return false; - - if ( pEntity->GetFlags() & EF_NODRAW ) - return false; - - // Don't guide toward striders - if ( FClassnameIs( pEntity, "npc_strider" ) ) - return false; - - if( WasFiredByNPC() ) - { - // Fired by an NPC - if( !pEntity->IsNPC() && !pEntity->IsPlayer() ) - return false; - - // Don't seek entities of the same class. - if ( pEntity->m_iClassname == GetOwnerEntity()->m_iClassname ) - return false; - } - else - { - -#ifndef HL2MP - if ( GetOwnerEntity() ) - { - // Things we check if this ball has an owner that's not an NPC. - if( GetOwnerEntity()->IsPlayer() ) - { - if( pEntity->Classify() == CLASS_PLAYER || - pEntity->Classify() == CLASS_PLAYER_ALLY || - pEntity->Classify() == CLASS_PLAYER_ALLY_VITAL ) - { - // Not attracted to other players or allies. - return false; - } - } - } - - // The default case. - if ( !pEntity->IsNPC() ) - return false; - - if( pEntity->Classify() == CLASS_BULLSEYE ) - return false; - -#else - if ( pEntity->IsPlayer() == false ) - return false; - - if ( pEntity == GetOwnerEntity() ) - return false; - - //No tracking teammates in teammode! - if ( g_pGameRules->IsTeamplay() ) - { - if ( g_pGameRules->PlayerRelationship( GetOwnerEntity(), pEntity ) == GR_TEAMMATE ) - return false; - } -#endif - - // We must be able to hit them - trace_t tr; - UTIL_TraceLine( WorldSpaceCenter(), pEntity->BodyTarget( WorldSpaceCenter() ), MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction < 1.0f && tr.m_pEnt != pEntity ) - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Deflects the ball toward enemies in case of a collision -//----------------------------------------------------------------------------- -void CPropCombineBall::DeflectTowardEnemy( float flSpeed, int index, gamevcollisionevent_t *pEvent ) -{ - // Bounce toward a particular enemy; choose one that's closest to my new velocity. - Vector vecVelDir = pEvent->postVelocity[index]; - VectorNormalize( vecVelDir ); - - CBaseEntity *pBestTarget = NULL; - - Vector vecStartPoint; - pEvent->pInternalData->GetContactPoint( vecStartPoint ); - - float flBestDist = MAX_COORD_FLOAT; - - CBaseEntity *list[1024]; - - Vector vecDelta; - float distance, flDot; - - // If we've already hit something, get accurate - bool bSeekKill = m_bStruckEntity && (WasWeaponLaunched() || sk_combineball_seek_kill.GetInt() ); - - if ( bSeekKill ) - { - int nCount = UTIL_EntitiesInSphere( list, 1024, GetAbsOrigin(), sk_combine_ball_search_radius.GetFloat(), FL_NPC | FL_CLIENT ); - - for ( int i = 0; i < nCount; i++ ) - { - if ( !IsAttractiveTarget( list[i] ) ) - continue; - - VectorSubtract( list[i]->WorldSpaceCenter(), vecStartPoint, vecDelta ); - distance = VectorNormalize( vecDelta ); - - if ( distance < flBestDist ) - { - // Check our direction - if ( DotProduct( vecDelta, vecVelDir ) > 0.0f ) - { - pBestTarget = list[i]; - flBestDist = distance; - } - } - } - } - else - { - float flMaxDot = 0.966f; - if ( !WasWeaponLaunched() ) - { - float flMaxDot = sk_combineball_seek_angle.GetFloat(); - float flGuideFactor = sk_combineball_guidefactor.GetFloat(); - for ( int i = m_nBounceCount; --i >= 0; ) - { - flMaxDot *= flGuideFactor; - } - flMaxDot = cos( flMaxDot * M_PI / 180.0f ); - - if ( flMaxDot > 1.0f ) - { - flMaxDot = 1.0f; - } - } - - // Otherwise only help out a little - Vector extents = Vector(256, 256, 256); - Ray_t ray; - ray.Init( vecStartPoint, vecStartPoint + 2048 * vecVelDir, -extents, extents ); - int nCount = UTIL_EntitiesAlongRay( list, 1024, ray, FL_NPC | FL_CLIENT ); - for ( int i = 0; i < nCount; i++ ) - { - if ( !IsAttractiveTarget( list[i] ) ) - continue; - - VectorSubtract( list[i]->WorldSpaceCenter(), vecStartPoint, vecDelta ); - distance = VectorNormalize( vecDelta ); - flDot = DotProduct( vecDelta, vecVelDir ); - - if ( flDot > flMaxDot ) - { - if ( distance < flBestDist ) - { - pBestTarget = list[i]; - flBestDist = distance; - } - } - } - } - - if ( pBestTarget ) - { - Vector vecDelta; - VectorSubtract( pBestTarget->WorldSpaceCenter(), vecStartPoint, vecDelta ); - VectorNormalize( vecDelta ); - vecDelta *= GetSpeed(); - PhysCallbackSetVelocity( pEvent->pObjects[index], vecDelta ); - } -} - - -//----------------------------------------------------------------------------- -// Bounce inside the spawner: -//----------------------------------------------------------------------------- -void CPropCombineBall::BounceInSpawner( float flSpeed, int index, gamevcollisionevent_t *pEvent ) -{ - GetSpawner()->RegisterReflection( this, m_bForward ); - - m_bForward = !m_bForward; - - Vector vecTarget; - GetSpawner()->GetTargetEndpoint( m_bForward, &vecTarget ); - - Vector vecVelocity; - VectorSubtract( vecTarget, GetAbsOrigin(), vecVelocity ); - VectorNormalize( vecVelocity ); - vecVelocity *= flSpeed; - - PhysCallbackSetVelocity( pEvent->pObjects[index], vecVelocity ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CPropCombineBall::IsHittableEntity( CBaseEntity *pHitEntity ) -{ - if ( pHitEntity->IsWorld() ) - return false; - - if ( pHitEntity->GetMoveType() == MOVETYPE_PUSH ) - { - if( pHitEntity->GetOwnerEntity() && FClassnameIs(pHitEntity->GetOwnerEntity(), "npc_strider") ) - { - // The Strider's Bone Followers are MOVETYPE_PUSH, and we want the combine ball to hit these. - return true; - } - - // If the entity we hit can take damage, we're good - if ( pHitEntity->m_takedamage == DAMAGE_YES ) - return true; - - return false; - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCombineBall::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) -{ - Vector preVelocity = pEvent->preVelocity[index]; - float flSpeed = VectorNormalize( preVelocity ); - - if ( m_nMaxBounces == -1 ) - { - const surfacedata_t *pHit = physprops->GetSurfaceData( pEvent->surfaceProps[!index] ); - - if( pHit->game.material != CHAR_TEX_FLESH || !hl2_episodic.GetBool() ) - { - CBaseEntity *pHitEntity = pEvent->pEntities[!index]; - if ( pHitEntity && IsHittableEntity( pHitEntity ) ) - { - OnHitEntity( pHitEntity, flSpeed, index, pEvent ); - } - - // Remove self without affecting the object that was hit. (Unless it was flesh) - NotifySpawnerOfRemoval(); - PhysCallbackRemove( this->NetworkProp() ); - - // disable dissolve damage so we don't kill off the player when he's the one we hit - PhysClearGameFlags( VPhysicsGetObject(), FVPHYSICS_DMG_DISSOLVE ); - return; - } - } - - // Prevents impact sounds, effects, etc. when it's in the field - if ( !IsInField() ) - { - BaseClass::VPhysicsCollision( index, pEvent ); - } - - if ( m_nState == STATE_HOLDING ) - return; - - // If we've collided going faster than our desired, then up our desired - if ( flSpeed > GetSpeed() ) - { - SetSpeed( flSpeed ); - } - - // Make sure we don't slow down - Vector vecFinalVelocity = pEvent->postVelocity[index]; - VectorNormalize( vecFinalVelocity ); - vecFinalVelocity *= GetSpeed(); - PhysCallbackSetVelocity( pEvent->pObjects[index], vecFinalVelocity ); - - CBaseEntity *pHitEntity = pEvent->pEntities[!index]; - if ( pHitEntity && IsHittableEntity( pHitEntity ) ) - { - OnHitEntity( pHitEntity, flSpeed, index, pEvent ); - return; - } - - if ( IsInField() ) - { - if ( HasSpawnFlags( SF_COMBINE_BALL_BOUNCING_IN_SPAWNER ) && GetSpawner() ) - { - BounceInSpawner( GetSpeed(), index, pEvent ); - return; - } - - PhysCallbackSetVelocity( pEvent->pObjects[index], vec3_origin ); - - // Delay the fade out so that we don't change our - // collision rules inside a vphysics callback. - variant_t emptyVariant; - g_EventQueue.AddEvent( this, "FadeAndRespawn", 0.01, NULL, NULL ); - return; - } - - if ( IsBeingCaptured() ) - return; - - // Do that crazy impact effect! - DoImpactEffect( preVelocity, index, pEvent ); - - // Only do the bounce so often - if ( gpGlobals->curtime - m_flLastBounceTime < 0.25f ) - return; - - // Save off our last bounce time - m_flLastBounceTime = gpGlobals->curtime; - - // Reset the sound timer - SetContextThink( &CPropCombineBall::WhizSoundThink, gpGlobals->curtime + 0.01, s_pWhizThinkContext ); - - // Deflect towards nearby enemies - DeflectTowardEnemy( flSpeed, index, pEvent ); - - // Once more bounce - ++m_nBounceCount; - - if ( OutOfBounces() && m_bBounceDie == false ) - { - StartLifetime( 0.5 ); - //Hack: Stop this from being called by doing this. - m_bBounceDie = true; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCombineBall::AnimThink( void ) -{ - StudioFrameAdvance(); - SetContextThink( &CPropCombineBall::AnimThink, gpGlobals->curtime + 0.1f, s_pAnimThinkContext ); -} - -//----------------------------------------------------------------------------- -// -// Implementation of CPropCombineBall -// -//----------------------------------------------------------------------------- -LINK_ENTITY_TO_CLASS( func_combine_ball_spawner, CFuncCombineBallSpawner ); - - -//----------------------------------------------------------------------------- -// Save/load: -//----------------------------------------------------------------------------- -BEGIN_DATADESC( CFuncCombineBallSpawner ) - - DEFINE_KEYFIELD( m_nBallCount, FIELD_INTEGER, "ballcount" ), - DEFINE_KEYFIELD( m_flMinSpeed, FIELD_FLOAT, "minspeed" ), - DEFINE_KEYFIELD( m_flMaxSpeed, FIELD_FLOAT, "maxspeed" ), - DEFINE_KEYFIELD( m_flBallRadius, FIELD_FLOAT, "ballradius" ), - DEFINE_KEYFIELD( m_flBallRespawnTime, FIELD_FLOAT, "ballrespawntime" ), - DEFINE_FIELD( m_flRadius, FIELD_FLOAT ), - DEFINE_FIELD( m_nBallsRemainingInField, FIELD_INTEGER ), - DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ), - DEFINE_UTLVECTOR( m_BallRespawnTime, FIELD_TIME ), - DEFINE_FIELD( m_flDisableTime, FIELD_TIME ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - - DEFINE_OUTPUT( m_OnBallGrabbed, "OnBallGrabbed" ), - DEFINE_OUTPUT( m_OnBallReinserted, "OnBallReinserted" ), - DEFINE_OUTPUT( m_OnBallHitTopSide, "OnBallHitTopSide" ), - DEFINE_OUTPUT( m_OnBallHitBottomSide, "OnBallHitBottomSide" ), - DEFINE_OUTPUT( m_OnLastBallGrabbed, "OnLastBallGrabbed" ), - DEFINE_OUTPUT( m_OnFirstBallReinserted, "OnFirstBallReinserted" ), - - DEFINE_THINKFUNC( BallThink ), - DEFINE_ENTITYFUNC( GrabBallTouch ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -CFuncCombineBallSpawner::CFuncCombineBallSpawner() -{ - m_flBallRespawnTime = 0.0f; - m_flBallRadius = 20.0f; - m_flDisableTime = 0.0f; - m_bShooter = false; -} - - -//----------------------------------------------------------------------------- -// Spawn a ball -//----------------------------------------------------------------------------- -void CFuncCombineBallSpawner::SpawnBall() -{ - CPropCombineBall *pBall = static_cast( CreateEntityByName( "prop_combine_ball" ) ); - - float flRadius = m_flBallRadius; - pBall->SetRadius( flRadius ); - - Vector vecAbsOrigin; - ChoosePointInBox( &vecAbsOrigin ); - Vector zaxis; - MatrixGetColumn( EntityToWorldTransform(), 2, zaxis ); - VectorMA( vecAbsOrigin, flRadius, zaxis, vecAbsOrigin ); - - pBall->SetAbsOrigin( vecAbsOrigin ); - pBall->SetSpawner( this ); - - float flSpeed = random->RandomFloat( m_flMinSpeed, m_flMaxSpeed ); - - zaxis *= flSpeed; - pBall->SetAbsVelocity( zaxis ); - if ( HasSpawnFlags( SF_SPAWNER_POWER_SUPPLY ) ) - { - pBall->AddSpawnFlags( SF_COMBINE_BALL_BOUNCING_IN_SPAWNER ); - } - - pBall->Spawn(); -} - -void CFuncCombineBallSpawner::Precache() -{ - BaseClass::Precache(); - - UTIL_PrecacheOther( "prop_combine_ball" ); -} - -//----------------------------------------------------------------------------- -// Spawn -//----------------------------------------------------------------------------- -void CFuncCombineBallSpawner::Spawn() -{ - BaseClass::Spawn(); - - Precache(); - - AddEffects( EF_NODRAW ); - SetModel( STRING( GetModelName() ) ); - SetSolid( SOLID_BSP ); - AddSolidFlags( FSOLID_NOT_SOLID ); - m_nBallsRemainingInField = m_nBallCount; - - float flWidth = CollisionProp()->OBBSize().x; - float flHeight = CollisionProp()->OBBSize().y; - m_flRadius = MIN( flWidth, flHeight ) * 0.5f; - if ( m_flRadius <= 0.0f && m_bShooter == false ) - { - Warning("Zero dimension func_combine_ball_spawner! Removing...\n"); - UTIL_Remove( this ); - return; - } - - // Compute a respawn time - float flDeltaT = 1.0f; - if ( !( m_flMinSpeed == 0 && m_flMaxSpeed == 0 ) ) - { - flDeltaT = (CollisionProp()->OBBSize().z - 2 * m_flBallRadius) / ((m_flMinSpeed + m_flMaxSpeed) * 0.5f); - flDeltaT /= m_nBallCount; - } - - m_BallRespawnTime.EnsureCapacity( m_nBallCount ); - for ( int i = 0; i < m_nBallCount; ++i ) - { - RespawnBall( (float)i * flDeltaT ); - } - - m_bEnabled = true; - if ( HasSpawnFlags( SF_SPAWNER_START_DISABLED ) ) - { - inputdata_t inputData; - InputDisable( inputData ); - } - else - { - SetThink( &CFuncCombineBallSpawner::BallThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); - } -} - - -//----------------------------------------------------------------------------- -// Enable/disable -//----------------------------------------------------------------------------- -void CFuncCombineBallSpawner::InputEnable( inputdata_t &inputdata ) -{ - if ( m_bEnabled ) - return; - - m_bEnabled = true; - m_flDisableTime = 0.0f; - - for ( int i = m_BallRespawnTime.Count(); --i >= 0; ) - { - m_BallRespawnTime[i] += gpGlobals->curtime; - } - - SetThink( &CFuncCombineBallSpawner::BallThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -void CFuncCombineBallSpawner::InputDisable( inputdata_t &inputdata ) -{ - if ( !m_bEnabled ) - return; - - m_flDisableTime = gpGlobals->curtime; - m_bEnabled = false; - - for ( int i = m_BallRespawnTime.Count(); --i >= 0; ) - { - m_BallRespawnTime[i] -= gpGlobals->curtime; - } - - SetThink( NULL ); -} - - -//----------------------------------------------------------------------------- -// Choose a random point inside the cylinder -//----------------------------------------------------------------------------- -void CFuncCombineBallSpawner::ChoosePointInBox( Vector *pVecPoint ) -{ - float flXBoundary = ( CollisionProp()->OBBSize().x != 0 ) ? m_flBallRadius / CollisionProp()->OBBSize().x : 0.0f; - float flYBoundary = ( CollisionProp()->OBBSize().y != 0 ) ? m_flBallRadius / CollisionProp()->OBBSize().y : 0.0f; - if ( flXBoundary > 0.5f ) - { - flXBoundary = 0.5f; - } - if ( flYBoundary > 0.5f ) - { - flYBoundary = 0.5f; - } - - CollisionProp()->RandomPointInBounds( - Vector( flXBoundary, flYBoundary, 0.0f ), Vector( 1.0f - flXBoundary, 1.0f - flYBoundary, 0.0f ), pVecPoint ); -} - - -//----------------------------------------------------------------------------- -// Choose a random point inside the cylinder -//----------------------------------------------------------------------------- -void CFuncCombineBallSpawner::ChoosePointInCylinder( Vector *pVecPoint ) -{ - float flXRange = m_flRadius / CollisionProp()->OBBSize().x; - float flYRange = m_flRadius / CollisionProp()->OBBSize().y; - - Vector vecEndPoint1, vecEndPoint2; - CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 0.0f ), &vecEndPoint1 ); - CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 1.0f ), &vecEndPoint2 ); - - // Choose a point inside the cylinder - float flDistSq; - do - { - CollisionProp()->RandomPointInBounds( - Vector( 0.5f - flXRange, 0.5f - flYRange, 0.0f ), - Vector( 0.5f + flXRange, 0.5f + flYRange, 0.0f ), - pVecPoint ); - - flDistSq = CalcDistanceSqrToLine( *pVecPoint, vecEndPoint1, vecEndPoint2 ); - - } while ( flDistSq > m_flRadius * m_flRadius ); -} - - -//----------------------------------------------------------------------------- -// Register that a reflection occurred -//----------------------------------------------------------------------------- -void CFuncCombineBallSpawner::RegisterReflection( CPropCombineBall *pBall, bool bForward ) -{ - if ( bForward ) - { - m_OnBallHitTopSide.FireOutput( pBall, this ); - } - else - { - m_OnBallHitBottomSide.FireOutput( pBall, this ); - } -} - - -//----------------------------------------------------------------------------- -// Choose a random point on the -//----------------------------------------------------------------------------- -void CFuncCombineBallSpawner::GetTargetEndpoint( bool bForward, Vector *pVecEndPoint ) -{ - float flZValue = bForward ? 1.0f : 0.0f; - - CollisionProp()->RandomPointInBounds( - Vector( 0.0f, 0.0f, flZValue ), Vector( 1.0f, 1.0f, flZValue ), pVecEndPoint ); -} - - -//----------------------------------------------------------------------------- -// Fire ball grabbed output -//----------------------------------------------------------------------------- -void CFuncCombineBallSpawner::BallGrabbed( CBaseEntity *pCombineBall ) -{ - m_OnBallGrabbed.FireOutput( pCombineBall, this ); - --m_nBallsRemainingInField; - if ( m_nBallsRemainingInField == 0 ) - { - m_OnLastBallGrabbed.FireOutput( pCombineBall, this ); - } - - // Wait for another ball to touch this to re-power it up. - if ( HasSpawnFlags( SF_SPAWNER_POWER_SUPPLY ) ) - { - AddSolidFlags( FSOLID_TRIGGER ); - SetTouch( &CFuncCombineBallSpawner::GrabBallTouch ); - } - - // Stop the ball thinking in case it was in the middle of being captured (which could re-add incorrectly) - if ( pCombineBall != NULL ) - { - pCombineBall->SetContextThink( NULL, gpGlobals->curtime, s_pCaptureContext ); - } -} - - -//----------------------------------------------------------------------------- -// Fire ball grabbed output -//----------------------------------------------------------------------------- -void CFuncCombineBallSpawner::GrabBallTouch( CBaseEntity *pOther ) -{ - // Safety net for two balls hitting this at once - if ( m_nBallsRemainingInField >= m_nBallCount ) - return; - - if ( pOther->GetCollisionGroup() != HL2COLLISION_GROUP_COMBINE_BALL ) - return; - - CPropCombineBall *pBall = dynamic_cast( pOther ); - Assert( pBall ); - - // Don't grab AR2 alt-fire - if ( pBall->WasWeaponLaunched() || !pBall->VPhysicsGetObject() ) - return; - - // Don't grab balls that are already in the field.. - if ( pBall->IsInField() ) - return; - - // Don't grab fading out balls... - if ( !pBall->IsSolid() ) - return; - - // Don't capture balls that were very recently in the field (breaks punting) - if ( gpGlobals->curtime - pBall->LastCaptureTime() < 0.5f ) - return; - - // Now we're bouncing in this spawner - pBall->AddSpawnFlags( SF_COMBINE_BALL_BOUNCING_IN_SPAWNER ); - - // Tell the respawner we're no longer its ball - pBall->NotifySpawnerOfRemoval(); - - pBall->SetOwnerEntity( NULL ); - pBall->SetSpawner( this ); - pBall->CaptureBySpawner(); - - ++m_nBallsRemainingInField; - - if ( m_nBallsRemainingInField >= m_nBallCount ) - { - RemoveSolidFlags( FSOLID_TRIGGER ); - SetTouch( NULL ); - } - - m_OnBallReinserted.FireOutput( pBall, this ); - if ( m_nBallsRemainingInField == 1 ) - { - m_OnFirstBallReinserted.FireOutput( pBall, this ); - } -} - - -//----------------------------------------------------------------------------- -// Get a speed for the ball to insert -//----------------------------------------------------------------------------- -float CFuncCombineBallSpawner::GetBallSpeed( ) const -{ - return random->RandomFloat( m_flMinSpeed, m_flMaxSpeed ); -} - - -//----------------------------------------------------------------------------- -// Balls call this when they've been removed from the spawner -//----------------------------------------------------------------------------- -void CFuncCombineBallSpawner::RespawnBall( float flRespawnTime ) -{ - // Insert the time in sorted order, - // which by definition means to always insert at the start - m_BallRespawnTime.AddToTail( gpGlobals->curtime + flRespawnTime - m_flDisableTime ); -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -void CFuncCombineBallSpawner::RespawnBallPostExplosion( void ) -{ - if ( m_flBallRespawnTime < 0 ) - return; - - if ( m_flBallRespawnTime == 0.0f ) - { - m_BallRespawnTime.AddToTail( gpGlobals->curtime + 4.0f - m_flDisableTime ); - } - else - { - m_BallRespawnTime.AddToTail( gpGlobals->curtime + m_flBallRespawnTime - m_flDisableTime ); - } -} - -//----------------------------------------------------------------------------- -// Ball think -//----------------------------------------------------------------------------- -void CFuncCombineBallSpawner::BallThink() -{ - for ( int i = m_BallRespawnTime.Count(); --i >= 0; ) - { - if ( m_BallRespawnTime[i] < gpGlobals->curtime ) - { - SpawnBall(); - m_BallRespawnTime.FastRemove( i ); - } - } - - // There are no more to respawn - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -BEGIN_DATADESC( CPointCombineBallLauncher ) - DEFINE_KEYFIELD( m_flConeDegrees, FIELD_FLOAT, "launchconenoise" ), - DEFINE_KEYFIELD( m_iszBullseyeName, FIELD_STRING, "bullseyename" ), - DEFINE_KEYFIELD( m_iBounces, FIELD_INTEGER, "maxballbounces" ), - DEFINE_INPUTFUNC( FIELD_VOID, "LaunchBall", InputLaunchBall ), -END_DATADESC() - -#define SF_COMBINE_BALL_LAUNCHER_ATTACH_BULLSEYE 0x00000001 -#define SF_COMBINE_BALL_LAUNCHER_COLLIDE_PLAYER 0x00000002 - -LINK_ENTITY_TO_CLASS( point_combine_ball_launcher, CPointCombineBallLauncher ); - -CPointCombineBallLauncher::CPointCombineBallLauncher() -{ - m_bShooter = true; - m_flConeDegrees = 0.0f; - m_iBounces = 0; -} - -void CPointCombineBallLauncher::Spawn( void ) -{ - m_bShooter = true; - - BaseClass::Spawn(); -} - -void CPointCombineBallLauncher::InputLaunchBall ( inputdata_t &inputdata ) -{ - SpawnBall(); -} - -//----------------------------------------------------------------------------- -// Spawn a ball -//----------------------------------------------------------------------------- -void CPointCombineBallLauncher::SpawnBall() -{ - CPropCombineBall *pBall = static_cast( CreateEntityByName( "prop_combine_ball" ) ); - - if ( pBall == NULL ) - return; - - float flRadius = m_flBallRadius; - pBall->SetRadius( flRadius ); - - Vector vecAbsOrigin = GetAbsOrigin(); - Vector zaxis; - - pBall->SetAbsOrigin( vecAbsOrigin ); - pBall->SetSpawner( this ); - - float flSpeed = random->RandomFloat( m_flMinSpeed, m_flMaxSpeed ); - - Vector vDirection; - QAngle qAngle = GetAbsAngles(); - - qAngle = qAngle + QAngle ( random->RandomFloat( -m_flConeDegrees, m_flConeDegrees ), random->RandomFloat( -m_flConeDegrees, m_flConeDegrees ), 0 ); - - AngleVectors( qAngle, &vDirection, NULL, NULL ); - - vDirection *= flSpeed; - pBall->SetAbsVelocity( vDirection ); - - DispatchSpawn(pBall); - pBall->Activate(); - pBall->SetState( CPropCombineBall::STATE_LAUNCHED ); - pBall->SetMaxBounces( m_iBounces ); - - if ( HasSpawnFlags( SF_COMBINE_BALL_LAUNCHER_COLLIDE_PLAYER ) ) - { - pBall->SetCollisionGroup( HL2COLLISION_GROUP_COMBINE_BALL_NPC ); - } - - if( GetSpawnFlags() & SF_COMBINE_BALL_LAUNCHER_ATTACH_BULLSEYE ) - { - CNPC_Bullseye *pBullseye = static_cast( CreateEntityByName( "npc_bullseye" ) ); - - if( pBullseye ) - { - pBullseye->SetAbsOrigin( pBall->GetAbsOrigin() ); - pBullseye->SetAbsAngles( QAngle( 0, 0, 0 ) ); - pBullseye->KeyValue( "solid", "6" ); - pBullseye->KeyValue( "targetname", STRING(m_iszBullseyeName) ); - pBullseye->Spawn(); - - DispatchSpawn(pBullseye); - pBullseye->Activate(); - - pBullseye->SetParent(pBall); - pBullseye->SetHealth(10); - } - } -} - -// ################################################################### -// > FilterClass -// ################################################################### -class CFilterCombineBall : public CBaseFilter -{ - DECLARE_CLASS( CFilterCombineBall, CBaseFilter ); - DECLARE_DATADESC(); - -public: - int m_iBallType; - - bool PassesFilterImpl( CBaseEntity *pCaller, CBaseEntity *pEntity ) - { - CPropCombineBall *pBall = dynamic_cast(pEntity ); - - if ( pBall ) - { - //Playtest HACK: If we have an NPC owner then we were shot from an AR2. - if ( pBall->GetOwnerEntity() && pBall->GetOwnerEntity()->IsNPC() ) - return false; - - return pBall->GetState() == m_iBallType; - } - - return false; - } -}; - -LINK_ENTITY_TO_CLASS( filter_combineball_type, CFilterCombineBall ); - -BEGIN_DATADESC( CFilterCombineBall ) - // Keyfields - DEFINE_KEYFIELD( m_iBallType, FIELD_INTEGER, "balltype" ), -END_DATADESC() diff --git a/game/server/hl2/prop_combine_ball.h b/game/server/hl2/prop_combine_ball.h deleted file mode 100644 index 6de82aeda..000000000 --- a/game/server/hl2/prop_combine_ball.h +++ /dev/null @@ -1,299 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef PROP_COMBINE_BALL_H -#define PROP_COMBINE_BALL_H -#ifdef _WIN32 -#pragma once -#endif - - -//----------------------------------------------------------------------------- -// Includes -//----------------------------------------------------------------------------- -#include "player_pickup.h" // for combine ball inheritance - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class CFuncCombineBallSpawner; -class CSpriteTrail; - -//----------------------------------------------------------------------------- -// Looks for enemies, bounces a max # of times before it breaks -//----------------------------------------------------------------------------- -class CPropCombineBall : public CBaseAnimating, public CDefaultPlayerPickupVPhysics -{ - DECLARE_CLASS( CPropCombineBall, CBaseAnimating ); - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - -public: - virtual void Precache(); - virtual void Spawn(); - virtual void UpdateOnRemove(); - void StopLoopingSounds(); - - virtual void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ); - virtual void OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ); - virtual void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); - - virtual bool OverridePropdata(); - virtual bool CreateVPhysics(); - - CFuncCombineBallSpawner *GetSpawner(); - - virtual void ExplodeThink( void ); - - // Override of IPlayerPickupVPhysics; - virtual bool ShouldPuntUseLaunchForces( PhysGunForce_t reason ) { return ( reason == PHYSGUN_FORCE_PUNTED ); } - - void SetRadius( float flRadius ); - void SetSpeed( float flSpeed ) { m_flSpeed = flSpeed; } - float GetSpeed( void ) const { return m_flSpeed; } - - void CaptureBySpawner( ); - bool IsBeingCaptured() const { return m_bCaptureInProgress; } - - void ReplaceInSpawner( float flSpeed ); - - // Input - void InputExplode( inputdata_t &inputdata ); - void InputFadeAndRespawn( inputdata_t &inputdata ); - void InputKill( inputdata_t &inputdata ); - void InputSocketed( inputdata_t &inputdata ); - - enum - { - STATE_NOT_THROWN = 0, - STATE_HOLDING, - STATE_THROWN, - STATE_LAUNCHED, //by a combine_ball launcher - }; - - void SetState( int state ); - bool IsInField() const; - - void StartWhizSoundThink( void ); - - void StartLifetime( float flDuration ); - void ClearLifetime( ); - void SetMass( float mass ); - - void SetWeaponLaunched( bool state = true ) { m_bWeaponLaunched = state; m_bLaunched = state; } - bool WasWeaponLaunched( void ) const { return m_bWeaponLaunched; } - - bool WasFiredByNPC() const { return (GetOwnerEntity() && GetOwnerEntity()->IsNPC()); } - - bool ShouldHitPlayer() const; - - virtual CBasePlayer *HasPhysicsAttacker( float dt ); - - void SetSpawner( CFuncCombineBallSpawner *pSpawner ) { m_hSpawner = pSpawner; } - void NotifySpawnerOfRemoval( void ); - - - float LastCaptureTime() const; - - unsigned char GetState() const { return m_nState; } - - int NumBounces( void ) const { return m_nBounceCount; } - - void SetMaxBounces( int iBounces ) - { - m_nMaxBounces = iBounces; - } - - void SetEmitState( bool bEmit ) - { - m_bEmit = bEmit; - } - - void SetOriginalOwner( CBaseEntity *pEntity ) { m_hOriginalOwner = pEntity; } - CBaseEntity *GetOriginalOwner() { return m_hOriginalOwner; } - -private: - - void SetPlayerLaunched( CBasePlayer *pOwner ); - - float GetBallHoldDissolveTime(); - float GetBallHoldSoundRampTime(); - - // Pow! - void DoExplosion( ); - - void StartAnimating( void ); - void StopAnimating( void ); - - void SetBallAsLaunched( void ); - - void CollisionEventToTrace( int index, gamevcollisionevent_t *pEvent, trace_t &tr ); - bool DissolveEntity( CBaseEntity *pEntity ); - void OnHitEntity( CBaseEntity *pHitEntity, float flSpeed, int index, gamevcollisionevent_t *pEvent ); - void DoImpactEffect( const Vector &preVelocity, int index, gamevcollisionevent_t *pEvent ); - - // Bounce inside the spawner: - void BounceInSpawner( float flSpeed, int index, gamevcollisionevent_t *pEvent ); - - bool IsAttractiveTarget( CBaseEntity *pEntity ); - - // Deflects the ball toward enemies in case of a collision - void DeflectTowardEnemy( float flSpeed, int index, gamevcollisionevent_t *pEvent ); - - // Is this something we can potentially dissolve? - bool IsHittableEntity( CBaseEntity *pHitEntity ); - - // Sucky. - void WhizSoundThink(); - void DieThink(); - void DissolveThink(); - void DissolveRampSoundThink(); - void AnimThink( void ); - - void FadeOut( float flDuration ); - - - bool OutOfBounces( void ) const - { - return ( m_nState == STATE_LAUNCHED && m_nMaxBounces != 0 && m_nBounceCount >= m_nMaxBounces ); - } - -private: - - int m_nBounceCount; - int m_nMaxBounces; - bool m_bBounceDie; - - float m_flLastBounceTime; - - bool m_bFiredGrabbedOutput; - bool m_bStruckEntity; // Has hit an entity already (control accuracy) - bool m_bWeaponLaunched; // Means this was fired from the AR2 - bool m_bForward; // Movement direction in ball spawner - - unsigned char m_nState; - bool m_bCaptureInProgress; - - float m_flSpeed; - - CSpriteTrail *m_pGlowTrail; - CSoundPatch *m_pHoldingSound; - - float m_flNextDamageTime; - float m_flLastCaptureTime; - - CHandle < CFuncCombineBallSpawner > m_hSpawner; - - EHANDLE m_hOriginalOwner; - - CNetworkVar( bool, m_bEmit ); - CNetworkVar( bool, m_bHeld ); - CNetworkVar( bool, m_bLaunched ); - CNetworkVar( float, m_flRadius ); -}; - -class CFuncCombineBallSpawner : public CBaseEntity -{ - DECLARE_CLASS( CFuncCombineBallSpawner, CBaseEntity ); - DECLARE_DATADESC(); - -public: - CFuncCombineBallSpawner(); - - virtual void Spawn(); - virtual void Precache(); - - // Balls call this to figure out where to bounce to - void GetTargetEndpoint( bool bForward, Vector *pVecEndpoint ); - - // Balls call this when they've been removed from the spawner - void RespawnBall( float flRespawnTime ); - void RespawnBallPostExplosion( void ); - - // Fire ball grabbed output - void BallGrabbed( CBaseEntity *pEntity ); - - // Get speed of ball to place into the field - float GetBallSpeed( ) const; - - // Register that a reflection occurred - void RegisterReflection( CPropCombineBall *pBall, bool bForward ); - - // Spawn a ball - virtual void SpawnBall(); - -private: - - // Choose a random point inside the cylinder - void ChoosePointInCylinder( Vector *pVecPoint ); - - // Choose a random point inside the box - void ChoosePointInBox( Vector *pVecPoint ); - - // Used to determine when to respawn balls - void BallThink(); - - // Input - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - - // Fire ball grabbed output - void GrabBallTouch( CBaseEntity *pOther ); - -public: - bool m_bShooter; - float m_flBallRadius; - float m_flBallRespawnTime; - float m_flMinSpeed; - float m_flMaxSpeed; - -private: - CUtlVector< float > m_BallRespawnTime; - int m_nBallCount; - int m_nBallsRemainingInField; - float m_flRadius; - float m_flDisableTime; - bool m_bEnabled; - - COutputEvent m_OnBallGrabbed; - COutputEvent m_OnBallReinserted; - COutputEvent m_OnBallHitTopSide; - COutputEvent m_OnBallHitBottomSide; - COutputEvent m_OnLastBallGrabbed; - COutputEvent m_OnFirstBallReinserted; -}; - - -class CPointCombineBallLauncher : public CFuncCombineBallSpawner -{ - DECLARE_CLASS( CPointCombineBallLauncher, CFuncCombineBallSpawner ); - - DECLARE_DATADESC(); - -public: - - virtual void Spawn( void ); - virtual void SpawnBall( void ); - void InputLaunchBall ( inputdata_t &inputdata ); - - CPointCombineBallLauncher(); - -private: - - int m_iBounces; - float m_flConeDegrees; - string_t m_iszBullseyeName; -}; - -// Creates a combine ball -CBaseEntity *CreateCombineBall( const Vector &origin, const Vector &velocity, float radius, float mass, float lifetime, CBaseEntity *pOwner ); - -// Query function to find out if a physics object is a combine ball (used for collision checks) -bool UTIL_IsCombineBall( CBaseEntity *pEntity ); -bool UTIL_IsCombineBallDefinite( CBaseEntity *pEntity ); -bool UTIL_IsAR2CombineBall( CBaseEntity *pEntity ); - -#endif // PROP_COMBINE_BALL_H diff --git a/game/server/hl2/prop_thumper.cpp b/game/server/hl2/prop_thumper.cpp deleted file mode 100644 index 19828fa42..000000000 --- a/game/server/hl2/prop_thumper.cpp +++ /dev/null @@ -1,283 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements the big scary boom-boom machine Antlions fear. -// -//=============================================================================// - -#include "cbase.h" -#include "baseentity.h" -#include "npcevent.h" -#include "rotorwash.h" -#include "soundenvelope.h" -#include "engine/IEngineSound.h" -#include "npc_antlion.h" -#include "te_effect_dispatch.h" - -#if HL2_EPISODIC -#define THUMPER_RADIUS m_iEffectRadius // this const is only used inside the thumper anyway -#else -#define THUMPER_RADIUS 1000 -#endif - - -#define STATE_CHANGE_MODIFIER 0.02f -#define THUMPER_SOUND_DURATION 1.5f -#define THUMPER_MIN_SCALE 128 -#define THUMPER_MODEL_NAME "models/props_combine/CombineThumper002.mdl" - - -ConVar thumper_show_radius("thumper_show_radius","0",FCVAR_CHEAT,"If true, advisor will use her custom impact damage table."); - - -class CPropThumper : public CBaseAnimating -{ -public: - DECLARE_CLASS( CPropThumper, CBaseAnimating ); - DECLARE_DATADESC(); - - virtual void Spawn( void ); - virtual void Precache( void ); - virtual void Think ( void ); - virtual void HandleAnimEvent( animevent_t *pEvent ); - virtual void StopLoopingSounds( void ); - - void InputDisable( inputdata_t &inputdata ); - void InputEnable( inputdata_t &inputdata ); - - void InitMotorSound( void ); - - void HandleState( void ); - - void Thump( void ); - -private: - - bool m_bEnabled; - int m_iHammerAttachment; - CSoundPatch* m_sndMotor; - EHANDLE m_hRepellantEnt; - int m_iDustScale; - - COutputEvent m_OnThumped; // Fired when thumper goes off - -#if HL2_EPISODIC - int m_iEffectRadius; -#endif -}; - -LINK_ENTITY_TO_CLASS( prop_thumper, CPropThumper ); - -//----------------------------------------------------------------------------- -// Save/load -//----------------------------------------------------------------------------- -BEGIN_DATADESC( CPropThumper ) - DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hRepellantEnt, FIELD_EHANDLE ), - DEFINE_FIELD( m_iHammerAttachment, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_iDustScale, FIELD_INTEGER, "dustscale" ), -#if HL2_EPISODIC - DEFINE_KEYFIELD( m_iEffectRadius, FIELD_INTEGER, "EffectRadius" ), -#endif - DEFINE_SOUNDPATCH( m_sndMotor ), - DEFINE_THINKFUNC( Think ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - - DEFINE_OUTPUT( m_OnThumped, "OnThumped" ), -END_DATADESC() - -void CPropThumper::Spawn( void ) -{ - const char *szModel = (char *)STRING( GetModelName() ); - if (!szModel || !*szModel) - { - szModel = THUMPER_MODEL_NAME; - SetModelName( AllocPooledString(szModel) ); - } - - Precache(); - SetModel( szModel ); - - SetSolid( SOLID_VPHYSICS ); - SetMoveType( MOVETYPE_NONE ); - VPhysicsInitStatic(); - - BaseClass::Spawn(); - - m_bEnabled = true; - - SetThink( &CPropThumper::Think ); - SetNextThink( gpGlobals->curtime + 1.0f ); - - int iSequence = SelectHeaviestSequence ( ACT_IDLE ); - - if ( iSequence != ACT_INVALID ) - { - SetSequence( iSequence ); - ResetSequenceInfo(); - - //Do this so we get the nice ramp-up effect. - m_flPlaybackRate = random->RandomFloat( 0.0f, 1.0f); - } - - m_iHammerAttachment = LookupAttachment( "hammer" ); - - CAntlionRepellant *pRepellant = (CAntlionRepellant*)CreateEntityByName( "point_antlion_repellant" ); - - if ( pRepellant ) - { - pRepellant->Spawn(); - pRepellant->SetAbsOrigin( GetAbsOrigin() ); - pRepellant->SetRadius( THUMPER_RADIUS ); - - m_hRepellantEnt = pRepellant; - } - - if ( m_iDustScale == 0 ) - m_iDustScale = THUMPER_MIN_SCALE; - -#if HL2_EPISODIC - if ( m_iEffectRadius == 0 ) - m_iEffectRadius = 1000; -#endif - -} - -void CPropThumper::Precache( void ) -{ - BaseClass::Precache(); - - PrecacheModel( STRING( GetModelName() ) ); - PrecacheScriptSound( "coast.thumper_hit" ); - PrecacheScriptSound( "coast.thumper_ambient" ); - PrecacheScriptSound( "coast.thumper_dust" ); - PrecacheScriptSound( "coast.thumper_startup" ); - PrecacheScriptSound( "coast.thumper_shutdown" ); - PrecacheScriptSound( "coast.thumper_large_hit" ); -} - -void CPropThumper::InitMotorSound( void ) -{ - CPASAttenuationFilter filter( this ); - m_sndMotor = (CSoundEnvelopeController::GetController()).SoundCreate( filter, entindex(), CHAN_STATIC, "coast.thumper_ambient" , ATTN_NORM ); - - if ( m_sndMotor ) - { - (CSoundEnvelopeController::GetController()).Play( m_sndMotor, 1.0f, 100 ); - } -} - -void CPropThumper::HandleState( void ) -{ - if ( m_bEnabled == false ) - { - m_flPlaybackRate = MAX( m_flPlaybackRate - STATE_CHANGE_MODIFIER, 0.0f ); - } - else - { - m_flPlaybackRate = MIN( m_flPlaybackRate + STATE_CHANGE_MODIFIER, 1.0f ); - } - - (CSoundEnvelopeController::GetController()).Play( m_sndMotor, 1.0f, m_flPlaybackRate * 100 ); -} - -void CPropThumper::Think( void ) -{ - StudioFrameAdvance(); - DispatchAnimEvents( this ); - SetNextThink( gpGlobals->curtime + 0.1 ); - - if ( m_sndMotor == NULL ) - InitMotorSound(); - else - HandleState(); -} - -void CPropThumper::Thump ( void ) -{ - if ( m_iHammerAttachment != -1 ) - { - Vector vOrigin; - GetAttachment( m_iHammerAttachment, vOrigin ); - - CEffectData data; - - data.m_nEntIndex = entindex(); - data.m_vOrigin = vOrigin; - data.m_flScale = m_iDustScale * m_flPlaybackRate; - DispatchEffect( "ThumperDust", data ); - UTIL_ScreenShake( vOrigin, 10.0 * m_flPlaybackRate, m_flPlaybackRate, m_flPlaybackRate / 2, THUMPER_RADIUS * m_flPlaybackRate, SHAKE_START, false ); - } - - EmitSound( "coast.thumper_dust" ); - CSoundEnt::InsertSound ( SOUND_THUMPER, GetAbsOrigin(), (int)(THUMPER_RADIUS * m_flPlaybackRate), THUMPER_SOUND_DURATION, this ); - - if ( thumper_show_radius.GetBool() ) - { - NDebugOverlay::Box( GetAbsOrigin(), Vector(-THUMPER_RADIUS, -THUMPER_RADIUS, -THUMPER_RADIUS), Vector(THUMPER_RADIUS, THUMPER_RADIUS, THUMPER_RADIUS), - 255, 64, 64, 255, THUMPER_SOUND_DURATION ); - } - - if ( m_flPlaybackRate < 0.7f ) - return; - - if( m_iDustScale == THUMPER_MIN_SCALE ) - EmitSound( "coast.thumper_hit" ); - else - EmitSound( "coast.thumper_large_hit" ); - - // Signal that we've thumped - m_OnThumped.FireOutput( this, this ); -} - -void CPropThumper::HandleAnimEvent( animevent_t *pEvent ) -{ - if ( pEvent->event == AE_THUMPER_THUMP ) - { - Thump(); - return; - } - - BaseClass::HandleAnimEvent( pEvent ); -} - - -//----------------------------------------------------------------------------- -// Shuts down sounds -//----------------------------------------------------------------------------- -void CPropThumper::StopLoopingSounds( void ) -{ - if ( m_sndMotor != NULL ) - { - (CSoundEnvelopeController::GetController()).SoundDestroy( m_sndMotor ); - m_sndMotor = NULL; - } - - BaseClass::StopLoopingSounds(); -} - -void CPropThumper::InputDisable( inputdata_t &inputdata ) -{ - m_bEnabled = false; - - EmitSound( "coast.thumper_shutdown" ); - - if ( m_hRepellantEnt ) - { - variant_t emptyVariant; - m_hRepellantEnt->AcceptInput( "Disable", this, this, emptyVariant, 0 ); - } -} - -void CPropThumper::InputEnable( inputdata_t &inputdata ) -{ - m_bEnabled = true; - - EmitSound( "coast.thumper_startup" ); - - if ( m_hRepellantEnt ) - { - variant_t emptyVariant; - m_hRepellantEnt->AcceptInput( "Enable", this, this, emptyVariant, 0 ); - } -} diff --git a/game/server/hl2/proto_sniper.cpp b/game/server/hl2/proto_sniper.cpp deleted file mode 100644 index b07d8d8ee..000000000 --- a/game/server/hl2/proto_sniper.cpp +++ /dev/null @@ -1,3496 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ai_default.h" -#include "ai_basenpc.h" -#include "ammodef.h" -#include "ai_task.h" -#include "ai_schedule.h" -#include "ai_node.h" -#include "ai_hull.h" -#include "ai_memory.h" -#include "ai_senses.h" -#include "beam_shared.h" -#include "game.h" -#include "npcevent.h" -#include "entitylist.h" -#include "activitylist.h" -#include "soundent.h" -#include "gib.h" -#include "ndebugoverlay.h" -#include "smoke_trail.h" -#include "weapon_rpg.h" -#include "player.h" -#include "mathlib/mathlib.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "IEffects.h" -#include "effect_color_tables.h" -#include "npc_rollermine.h" -#include "eventqueue.h" - -#include "effect_dispatch_data.h" -#include "te_effect_dispatch.h" - -#include "collisionutils.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern Vector PointOnLineNearestPoint(const Vector& vStartPos, const Vector& vEndPos, const Vector& vPoint); - -ConVar bulletSpeed( "bulletspeed", "6000" ); -ConVar sniperLines( "showsniperlines", "0" ); -ConVar sniperviewdist("sniperviewdist", "35" ); -ConVar showsniperdist("showsniperdist", "0" ); -ConVar sniperspeak( "sniperspeak", "0" ); -ConVar sniper_xbox_delay( "sniper_xbox_delay", "1" ); - -// Moved to HL2_SharedGameRules because these are referenced by shared AmmoDef functions -extern ConVar sk_dmg_sniper_penetrate_plr; -extern ConVar sk_dmg_sniper_penetrate_npc; - -// No model, impervious to damage. -#define SF_SNIPER_HIDDEN (1 << 16) -#define SF_SNIPER_VIEWCONE (1 << 17) ///< when set, sniper only sees in a small cone around the laser. -#define SF_SNIPER_NOCORPSE (1 << 18) ///< when set, no corpse -#define SF_SNIPER_STARTDISABLED (1 << 19) -#define SF_SNIPER_FAST (1 << 20) ///< This is faster-shooting sniper. Paint time is decreased 25%. Bullet speed increases 150%. -#define SF_SNIPER_NOSWEEP (1 << 21) ///< This sniper doesn't sweep to the target or use decoys. - -// If the last time I fired at someone was between 0 and this many seconds, draw -// a bead on them much faster. (use subsequent paint time) -#define SNIPER_FASTER_ATTACK_PERIOD 3.0f - -// These numbers determine the interval between shots. They used to be constants, -// but are now keyfields. HL2 backwards compatibility was maintained by supplying -// default values in the constructor. -#if 0 -// How long to aim at someone before shooting them. -#define SNIPER_PAINT_ENEMY_TIME 1.0f -// ...plus this -#define SNIPER_PAINT_NPC_TIME_NOISE 0.75f -#else -// How long to aim at someone before shooting them. -#define SNIPER_DEFAULT_PAINT_ENEMY_TIME 1.0f -// ...plus this -#define SNIPER_DEFAULT_PAINT_NPC_TIME_NOISE 0.75f -#endif - -#define SNIPER_SUBSEQUENT_PAINT_TIME ( ( IsXbox() ) ? 1.0f : 0.4f ) - -#define SNIPER_FOG_PAINT_ENEMY_TIME 0.25f -#define SNIPER_PAINT_DECOY_TIME 2.0f -#define SNIPER_PAINT_FRUSTRATED_TIME 1.0f -#define SNIPER_QUICKAIM_TIME 0.2f -#define SNIPER_PAINT_NO_SHOT_TIME 0.7f - -#define SNIPER_DECOY_MAX_MASS 200.0f - -// #def'ing this will turn on heaps of sniper debug messages. -#undef SNIPER_DEBUG - -// Target protection -#define SNIPER_PROTECTION_MINDIST (1024.0*1024.0) // Distance around protect target that sniper does priority modification in -#define SNIPER_PROTECTION_PRIORITYCAP 100.0 // Max addition to priority of an enemy right next to the protect target, falls to 0 at SNIPER_PROTECTION_MINDIST. - -//--------------------------------------------------------- -// Like an infotarget, but shares a spawnflag that has -// relevance to the sniper. -//--------------------------------------------------------- -#define SF_SNIPERTARGET_SHOOTME 1 -#define SF_SNIPERTARGET_NOINTERRUPT 2 -#define SF_SNIPERTARGET_SNAPSHOT 4 -#define SF_SNIPERTARGET_RESUME 8 -#define SF_SNIPERTARGET_SNAPTO 16 -#define SF_SNIPERTARGET_FOCUS 32 - - -#define SNIPER_DECOY_RADIUS 256 -#define SNIPER_NUM_DECOYS 5 - -#define NUM_OLDDECOYS 5 - -#define NUM_PENETRATIONS 3 - -#define PENETRATION_THICKNESS 5 - -#define SNIPER_MAX_GROUP_TARGETS 16 - - -//========================================================= -//========================================================= -class CSniperTarget : public CPointEntity -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( CSniperTarget, CPointEntity ); - - bool KeyValue( const char *szKeyName, const char *szValue ); - - string_t m_iszGroupName; -}; - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CSniperTarget ) - - DEFINE_FIELD( m_iszGroupName, FIELD_STRING ), - -END_DATADESC() - - -//========================================================= -//========================================================= -class CSniperBullet : public CBaseEntity -{ -public: - DECLARE_CLASS( CSniperBullet, CBaseEntity ); - - CSniperBullet( void ) { Init(); } - - Vector m_vecDir; - - Vector m_vecStart; - Vector m_vecEnd; - - float m_flLastThink; - float m_SoundTime; - int m_AmmoType; - int m_PenetratedAmmoType; - float m_Speed; - bool m_bDirectShot; - - void Precache( void ); - bool IsActive( void ) { return m_fActive; } - - bool Start( const Vector &vecOrigin, const Vector &vecTarget, CBaseEntity *pOwner, bool bDirectShot ); - void Stop( void ); - - void BulletThink( void ); - - void Init( void ); - - DECLARE_DATADESC(); - -private: - - // Only one shot per sniper at a time. If a bullet hasn't - // hit, the shooter must wait. - bool m_fActive; - - // This tracks how many times this single bullet has - // struck. This is for penetration, so the bullet can - // go through things. - int m_iImpacts; -}; - - -//========================================================= -//========================================================= -class CProtoSniper : public CAI_BaseNPC -{ - DECLARE_CLASS( CProtoSniper, CAI_BaseNPC ); - -public: - CProtoSniper( void ); - void Precache( void ); - void Spawn( void ); - Class_T Classify( void ); - float MaxYawSpeed( void ); - Vector EyePosition( void ); - - void UpdateEfficiency( bool bInPVS ) { SetEfficiency( ( GetSleepState() != AISS_AWAKE ) ? AIE_DORMANT : AIE_NORMAL ); SetMoveEfficiency( AIME_NORMAL ); } - - bool IsLaserOn( void ) { return m_pBeam != NULL; } - - void Event_Killed( const CTakeDamageInfo &info ); - void Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info ); - void UpdateOnRemove( void ); - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - bool WeaponLOSCondition(const Vector &ownerPos, const Vector &targetPos, bool bSetConditions) {return true;} - int IRelationPriority( CBaseEntity *pTarget ); - bool IsFastSniper() { return HasSpawnFlags(SF_SNIPER_FAST); } - - bool QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC = false ); - - virtual bool FInViewCone( CBaseEntity *pEntity ); - - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - int RangeAttack1Conditions ( float flDot, float flDist ); - bool FireBullet( const Vector &vecTarget, bool bDirectShot ); - float GetBulletSpeed(); - Vector DesiredBodyTarget( CBaseEntity *pTarget ); - Vector LeadTarget( CBaseEntity *pTarget ); - CBaseEntity *PickDeadPlayerTarget(); - - virtual int SelectSchedule( void ); - virtual int TranslateSchedule( int scheduleType ); - - bool KeyValue( const char *szKeyName, const char *szValue ); - - void PrescheduleThink( void ); - - static const char *pAttackSounds[]; - - bool FCanCheckAttacks ( void ); - bool FindDecoyObject( void ); - - void ScopeGlint(); - - int GetSoundInterests( void ); - void OnListened(); - - Vector GetBulletOrigin( void ); - - virtual int Restore( IRestore &restore ); - - virtual void OnScheduleChange( void ); - - bool FVisible( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ); - - bool ShouldNotDistanceCull() { return true; } - - int DrawDebugTextOverlays(); - - void NotifyShotMissedTarget(); - -private: - - bool ShouldSnapShot( void ); - void ClearTargetGroup( void ); - - float GetPositionParameter( float flTime, bool fLinear ); - - void GetPaintAim( const Vector &vecStart, const Vector &vecGoal, float flParameter, Vector *pProgress ); - - bool IsSweepingRandomly( void ) { return m_iNumGroupTargets > 0; } - - void ClearOldDecoys( void ); - void AddOldDecoy( CBaseEntity *pDecoy ); - bool HasOldDecoy( CBaseEntity *pDecoy ); - bool FindFrustratedShot( float flNoise ); - - bool VerifyShot( CBaseEntity *pTarget ); - - void SetSweepTarget( const char *pszTarget ); - - // Inputs - void InputEnableSniper( inputdata_t &inputdata ); - void InputDisableSniper( inputdata_t &inputdata ); - void InputSetDecoyRadius( inputdata_t &inputdata ); - void InputSweepTarget( inputdata_t &inputdata ); - void InputSweepTargetHighestPriority( inputdata_t &inputdata ); - void InputSweepGroupRandomly( inputdata_t &inputdata ); - void InputStopSweeping( inputdata_t &inputdata ); - void InputProtectTarget( inputdata_t &inputdata ); - -#if HL2_EPISODIC - void InputSetPaintInterval( inputdata_t &inputdata ); - void InputSetPaintIntervalVariance( inputdata_t &inputdata ); -#endif - - void LaserOff( void ); - void LaserOn( const Vector &vecTarget, const Vector &vecDeviance ); - - void PaintTarget( const Vector &vecTarget, float flPaintTime ); - - bool IsPlayerAllySniper(); - -private: - - /// This is the variable from which m_flPaintTime gets set. - /// How long to aim at someone before shooting them. - float m_flKeyfieldPaintTime; - - /// A random number from 0 to this is added to m_flKeyfieldPaintTime - /// to yield m_flPaintTime's initial delay. - float m_flKeyfieldPaintTimeNoise; - - // This keeps track of the last spot the laser painted. For - // continuous sweeping that changes direction. - Vector m_vecPaintCursor; - float m_flPaintTime; - - bool m_fWeaponLoaded; - bool m_fEnabled; - bool m_fIsPatient; - float m_flPatience; - int m_iMisses; - EHANDLE m_hDecoyObject; - EHANDLE m_hSweepTarget; - Vector m_vecDecoyObjectTarget; - Vector m_vecFrustratedTarget; - Vector m_vecPaintStart; // used to track where a sweep starts for the purpose of interpolating. - - float m_flFrustration; - - float m_flThinkInterval; - - float m_flDecoyRadius; - - CBeam *m_pBeam; - - bool m_fSnapShot; - - int m_iNumGroupTargets; - CBaseEntity *m_pGroupTarget[ SNIPER_MAX_GROUP_TARGETS ]; - - bool m_bSweepHighestPriority; // My hack :[ (sjb) - int m_iBeamBrightness; - - // bullet stopping energy shield effect. - float m_flShieldDist; - float m_flShieldRadius; - - float m_flTimeLastAttackedPlayer; - - // Protection - EHANDLE m_hProtectTarget; // Entity that this sniper is supposed to protect - float m_flDangerEnemyDistance; // Distance to the enemy nearest the protect target - - // Have I warned the target that I'm pointing my laser at them? - bool m_bWarnedTargetEntity; - - float m_flTimeLastShotMissed; - bool m_bKilledPlayer; - bool m_bShootZombiesInChest; ///< if true, do not try to shoot zombies in the headcrab - - COutputEvent m_OnShotFired; - - DEFINE_CUSTOM_AI; - - DECLARE_DATADESC(); -}; - - -//========================================================= -//========================================================= -// NOTES about the Sniper: -// -// PATIENCE: -// The concept of "patience" is simply a restriction placed -// on how close a target has to be to the sniper before the -// sniper will take his first shot at the target. This -// distance is referred to as "patience" is set by the ` -// designer in Worldcraft. The sniper won't attack unless -// the target enters this radius. Once the sniper takes -// this first shot, he will not return to a patient state. -// He will then shoot at any/all targets to which there is -// a clear shot, regardless of distance. (sjb) -// -// -// TODO: Sniper accumulates frustration while reloading. -// probably should subtract reload time from frustration. -//========================================================= -//========================================================= - - -//========================================================= -//========================================================= -short sFlashSprite; -short sHaloSprite; - -//========================================================= -//========================================================= -BEGIN_DATADESC( CProtoSniper ) - - DEFINE_FIELD( m_fWeaponLoaded, FIELD_BOOLEAN ), - DEFINE_FIELD( m_fEnabled, FIELD_BOOLEAN ), - DEFINE_FIELD( m_fIsPatient, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flPatience, FIELD_FLOAT ), - DEFINE_FIELD( m_iMisses, FIELD_INTEGER ), - DEFINE_FIELD( m_hDecoyObject, FIELD_EHANDLE ), - DEFINE_FIELD( m_hSweepTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_vecDecoyObjectTarget, FIELD_VECTOR ), - DEFINE_FIELD( m_vecFrustratedTarget, FIELD_VECTOR ), - DEFINE_FIELD( m_vecPaintStart, FIELD_VECTOR ), - DEFINE_FIELD( m_flPaintTime, FIELD_TIME ), - DEFINE_FIELD( m_vecPaintCursor, FIELD_VECTOR ), - DEFINE_FIELD( m_flFrustration, FIELD_TIME ), - DEFINE_FIELD( m_flThinkInterval, FIELD_FLOAT ), - DEFINE_FIELD( m_flDecoyRadius, FIELD_FLOAT ), - DEFINE_FIELD( m_pBeam, FIELD_CLASSPTR ), - DEFINE_FIELD( m_fSnapShot, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iNumGroupTargets, FIELD_INTEGER ), - DEFINE_ARRAY( m_pGroupTarget, FIELD_CLASSPTR, SNIPER_MAX_GROUP_TARGETS ), - DEFINE_KEYFIELD( m_iBeamBrightness, FIELD_INTEGER, "beambrightness" ), - - - DEFINE_KEYFIELD(m_flShieldDist, FIELD_FLOAT, "shielddistance" ), - DEFINE_KEYFIELD(m_flShieldRadius, FIELD_FLOAT, "shieldradius" ), - DEFINE_KEYFIELD(m_bShootZombiesInChest, FIELD_BOOLEAN, "shootZombiesInChest" ), - - DEFINE_KEYFIELD(m_flKeyfieldPaintTime, FIELD_FLOAT, "PaintInterval" ), - DEFINE_KEYFIELD(m_flKeyfieldPaintTimeNoise, FIELD_FLOAT, "PaintIntervalVariance" ), - - DEFINE_FIELD( m_flTimeLastAttackedPlayer, FIELD_TIME ), - DEFINE_FIELD( m_hProtectTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_flDangerEnemyDistance, FIELD_FLOAT ), - - DEFINE_FIELD( m_bSweepHighestPriority, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_bWarnedTargetEntity, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flTimeLastShotMissed, FIELD_TIME ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "EnableSniper", InputEnableSniper ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableSniper", InputDisableSniper ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetDecoyRadius", InputSetDecoyRadius ), - DEFINE_INPUTFUNC( FIELD_STRING, "SweepTarget", InputSweepTarget ), - DEFINE_INPUTFUNC( FIELD_STRING, "SweepTargetHighestPriority", InputSweepTargetHighestPriority ), - DEFINE_INPUTFUNC( FIELD_STRING, "SweepGroupRandomly", InputSweepGroupRandomly ), - DEFINE_INPUTFUNC( FIELD_STRING, "StopSweeping", InputStopSweeping ), - DEFINE_INPUTFUNC( FIELD_STRING, "ProtectTarget", InputProtectTarget ), - -#if HL2_EPISODIC - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetPaintInterval", InputSetPaintInterval ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetPaintIntervalVariance", InputSetPaintIntervalVariance ), -#endif - - // Outputs - DEFINE_OUTPUT( m_OnShotFired, "OnShotFired" ), - -END_DATADESC() - - - -//========================================================= -//========================================================= -BEGIN_DATADESC( CSniperBullet ) - - DEFINE_FIELD( m_SoundTime, FIELD_TIME ), - DEFINE_FIELD( m_AmmoType, FIELD_INTEGER ), - DEFINE_FIELD( m_PenetratedAmmoType, FIELD_INTEGER ), - DEFINE_FIELD( m_fActive, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iImpacts, FIELD_INTEGER ), - DEFINE_FIELD( m_vecOrigin, FIELD_VECTOR ), - DEFINE_FIELD( m_vecDir, FIELD_VECTOR ), - DEFINE_FIELD( m_flLastThink, FIELD_TIME ), - DEFINE_FIELD( m_Speed, FIELD_FLOAT ), - DEFINE_FIELD( m_bDirectShot, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_vecStart, FIELD_VECTOR ), - DEFINE_FIELD( m_vecEnd, FIELD_VECTOR ), - - DEFINE_THINKFUNC( BulletThink ), - -END_DATADESC() - -//========================================================= -// Private conditions -//========================================================= -enum Sniper_Conds -{ - COND_SNIPER_CANATTACKDECOY = LAST_SHARED_CONDITION, - COND_SNIPER_SUPPRESSED, - COND_SNIPER_ENABLED, - COND_SNIPER_DISABLED, - COND_SNIPER_FRUSTRATED, - COND_SNIPER_SWEEP_TARGET, - COND_SNIPER_NO_SHOT, -}; - - -//========================================================= -// schedules -//========================================================= -enum -{ - SCHED_PSNIPER_SCAN = LAST_SHARED_SCHEDULE, - SCHED_PSNIPER_CAMP, - SCHED_PSNIPER_ATTACK, - SCHED_PSNIPER_RELOAD, - SCHED_PSNIPER_ATTACKDECOY, - SCHED_PSNIPER_SUPPRESSED, - SCHED_PSNIPER_DISABLEDWAIT, - SCHED_PSNIPER_FRUSTRATED_ATTACK, - SCHED_PSNIPER_SWEEP_TARGET, - SCHED_PSNIPER_SWEEP_TARGET_NOINTERRUPT, - SCHED_PSNIPER_SNAPATTACK, - SCHED_PSNIPER_NO_CLEAR_SHOT, - SCHED_PSNIPER_PLAYER_DEAD, -}; - -//========================================================= -// tasks -//========================================================= -enum -{ - TASK_SNIPER_FRUSTRATED_ATTACK = LAST_SHARED_TASK, - TASK_SNIPER_PAINT_ENEMY, - TASK_SNIPER_PAINT_DECOY, - TASK_SNIPER_PAINT_FRUSTRATED, - TASK_SNIPER_PAINT_SWEEP_TARGET, - TASK_SNIPER_ATTACK_CURSOR, - TASK_SNIPER_PAINT_NO_SHOT, - TASK_SNIPER_PLAYER_DEAD, -}; - - - -CProtoSniper::CProtoSniper( void ) : m_flKeyfieldPaintTime(SNIPER_DEFAULT_PAINT_ENEMY_TIME), - m_flKeyfieldPaintTimeNoise(SNIPER_DEFAULT_PAINT_NPC_TIME_NOISE) -{ -#ifdef _DEBUG - m_vecPaintCursor.Init(); - m_vecDecoyObjectTarget.Init(); - m_vecFrustratedTarget.Init(); - m_vecPaintStart.Init(); -#endif - - m_iMisses = 0; - m_flDecoyRadius = SNIPER_DECOY_RADIUS; - m_fSnapShot = false; - m_iBeamBrightness = 100; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CProtoSniper::QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC ) -{ - Disposition_t disp = IRelationType(pEntity); - if( disp != D_HT ) - { - // Don't bother with anything I wouldn't shoot. - return false; - } - - if( !FInViewCone(pEntity) ) - { - // Yes, this does call FInViewCone twice a frame for all entities checked for - // visibility, but doing this allows us to cut out a bunch of traces that would - // be done by VerifyShot for entities that aren't even in our viewcone. - return false; - } - - if( VerifyShot( pEntity ) ) - { - return BaseClass::QuerySeeEntity(pEntity, bOnlyHateOrFearIfNPC); - } - - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CProtoSniper::FInViewCone ( CBaseEntity *pEntity ) -{ - if( pEntity->GetFlags() & FL_CLIENT ) - { - CBasePlayer *pPlayer; - - pPlayer = ToBasePlayer( pEntity ); - - if( m_spawnflags & SF_SNIPER_VIEWCONE ) - { - // See how close this spot is to the laser. - Vector vecEyes; - Vector vecLOS; - float flDist; - Vector vecNearestPoint; - - vecEyes = EyePosition(); - vecLOS = m_vecPaintCursor - vecEyes; - VectorNormalize(vecLOS); - - vecNearestPoint = PointOnLineNearestPoint( EyePosition(), EyePosition() + vecLOS * 8192, pPlayer->EyePosition() ); - - flDist = ( pPlayer->EyePosition() - vecNearestPoint ).Length(); - - if( showsniperdist.GetFloat() != 0 ) - { - Msg( "Dist from beam: %f\n", flDist ); - } - - if( flDist <= sniperviewdist.GetFloat() ) - { - return true; - } - - return false; - } - } - - return BaseClass::FInViewCone( pEntity->EyePosition() ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CProtoSniper::LaserOff( void ) -{ - if( m_pBeam ) - { - UTIL_Remove( m_pBeam); - m_pBeam = NULL; - } - - SetNextThink( gpGlobals->curtime + 0.1f ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -#define LASER_LEAD_DIST 64 -void CProtoSniper::LaserOn( const Vector &vecTarget, const Vector &vecDeviance ) -{ - if (!m_pBeam) - { - m_pBeam = CBeam::BeamCreate( "effects/bluelaser1.vmt", 1.0f ); - m_pBeam->SetColor( 0, 100, 255 ); - } - else - { - // Beam seems to be on. - //return; - } - - // Don't aim right at the guy right now. - Vector vecInitialAim; - - if( vecDeviance == vec3_origin ) - { - // Start the aim where it last left off! - vecInitialAim = m_vecPaintCursor; - } - else - { - vecInitialAim = vecTarget; - } - - vecInitialAim.x += random->RandomFloat( -vecDeviance.x, vecDeviance.x ); - vecInitialAim.y += random->RandomFloat( -vecDeviance.y, vecDeviance.y ); - vecInitialAim.z += random->RandomFloat( -vecDeviance.z, vecDeviance.z ); - - // The beam is backwards, sortof. The endpoint is the sniper. This is - // so that the beam can be tapered to very thin where it emits from the sniper. - m_pBeam->PointsInit( vecInitialAim, GetBulletOrigin() ); - m_pBeam->SetBrightness( 255 ); - m_pBeam->SetNoise( 0 ); - m_pBeam->SetWidth( 1.0f ); - m_pBeam->SetEndWidth( 0 ); - m_pBeam->SetScrollRate( 0 ); - m_pBeam->SetFadeLength( 0 ); - m_pBeam->SetHaloTexture( sHaloSprite ); - m_pBeam->SetHaloScale( 4.0f ); - - m_vecPaintStart = vecInitialAim; - - // Think faster whilst painting. Higher resolution on the - // beam movement. - SetNextThink( gpGlobals->curtime + 0.02 ); -} - -//----------------------------------------------------------------------------- -// Crikey! -//----------------------------------------------------------------------------- -float CProtoSniper::GetPositionParameter( float flTime, bool fLinear ) -{ - float flElapsedTime; - float flTimeParameter; - - flElapsedTime = flTime - (GetWaitFinishTime() - gpGlobals->curtime); - - flTimeParameter = ( flElapsedTime / flTime ); - - if( fLinear ) - { - return flTimeParameter; - } - else - { - return (1 + sin( (M_PI * flTimeParameter) - (M_PI / 2) ) ) / 2; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CProtoSniper::GetPaintAim( const Vector &vecStart, const Vector &vecGoal, float flParameter, Vector *pProgress ) -{ -#if 0 - Vector vecDelta; - - vecDelta = vecGoal - vecStart; - - float flDist = VectorNormalize( vecDelta ); - - vecDelta = vecStart + vecDelta * (flDist * flParameter); - - vecDelta = (vecDelta - GetBulletOrigin() ).Normalize(); - - *pProgress = vecDelta; -#else - // Quaternions - Vector vecIdealDir; - QAngle vecIdealAngles; - QAngle vecCurrentAngles; - Vector vecCurrentDir; - Vector vecBulletOrigin = GetBulletOrigin(); - - // vecIdealDir is where the gun should be aimed when the painting - // time is up. This can be approximate. This is only for drawing the - // laser, not actually aiming the weapon. A large discrepancy will look - // bad, though. - vecIdealDir = vecGoal - vecBulletOrigin; - VectorNormalize(vecIdealDir); - - // Now turn vecIdealDir into angles! - VectorAngles( vecIdealDir, vecIdealAngles ); - - // This is the vector of the beam's current aim. - vecCurrentDir = vecStart - vecBulletOrigin; - VectorNormalize(vecCurrentDir); - - // Turn this to angles, too. - VectorAngles( vecCurrentDir, vecCurrentAngles ); - - Quaternion idealQuat; - Quaternion currentQuat; - Quaternion aimQuat; - - AngleQuaternion( vecIdealAngles, idealQuat ); - AngleQuaternion( vecCurrentAngles, currentQuat ); - - QuaternionSlerp( currentQuat, idealQuat, flParameter, aimQuat ); - - QuaternionAngles( aimQuat, vecCurrentAngles ); - - // Rebuild the current aim vector. - AngleVectors( vecCurrentAngles, &vecCurrentDir ); - - *pProgress = vecCurrentDir; -#endif -} - -//----------------------------------------------------------------------------- -// Sweep the laser sight towards the point where the gun should be aimed -//----------------------------------------------------------------------------- -void CProtoSniper::PaintTarget( const Vector &vecTarget, float flPaintTime ) -{ - Vector vecCurrentDir; - Vector vecStart; - - // vecStart is the barrel of the gun (or the laser sight) - vecStart = GetBulletOrigin(); - - float P; - - // keep painttime from hitting 0 exactly. - flPaintTime = MAX( flPaintTime, 0.000001f ); - - P = GetPositionParameter( flPaintTime, false ); - - // Vital allies are sharper about avoiding the sniper. - if( P > 0.25f && GetEnemy() && GetEnemy()->IsNPC() && HasCondition(COND_SEE_ENEMY) && !m_bWarnedTargetEntity ) - { - m_bWarnedTargetEntity = true; - - if( GetEnemy()->Classify() == CLASS_PLAYER_ALLY_VITAL && GetEnemy()->MyNPCPointer()->FVisible(this) ) - { - CSoundEnt::InsertSound( SOUND_DANGER | SOUND_CONTEXT_REACT_TO_SOURCE, GetEnemy()->EarPosition(), 16, 1.0f, this ); - } - } - - GetPaintAim( m_vecPaintStart, vecTarget, clamp(P,0.0f,1.0f), &vecCurrentDir ); - -#if 1 -#define THRESHOLD 0.8f - float flNoiseScale; - - if ( P >= THRESHOLD ) - { - flNoiseScale = 1 - (1 / (1 - THRESHOLD)) * ( P - THRESHOLD ); - } - else if ( P <= 1 - THRESHOLD ) - { - flNoiseScale = P / (1 - THRESHOLD); - } - else - { - flNoiseScale = 1; - } - - // mult by P - vecCurrentDir.x += flNoiseScale * ( sin( 3 * M_PI * gpGlobals->curtime ) * 0.0006 ); - vecCurrentDir.y += flNoiseScale * ( sin( 2 * M_PI * gpGlobals->curtime + 0.5 * M_PI ) * 0.0006 ); - vecCurrentDir.z += flNoiseScale * ( sin( 1.5 * M_PI * gpGlobals->curtime + M_PI ) * 0.0006 ); -#endif - - trace_t tr; - - UTIL_TraceLine( vecStart, vecStart + vecCurrentDir * 8192, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - m_pBeam->SetStartPos( tr.endpos ); - m_pBeam->RelinkBeam(); - - m_vecPaintCursor = tr.endpos; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CProtoSniper::IsPlayerAllySniper() -{ - CBaseEntity *pPlayer = AI_GetSinglePlayer(); - - return IRelationType( pPlayer ) == D_LI; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CProtoSniper::InputSetDecoyRadius( inputdata_t &inputdata ) -{ - m_flDecoyRadius = (float)inputdata.value.Int(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CProtoSniper::OnScheduleChange( void ) -{ - LaserOff(); - - BaseClass::OnScheduleChange(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CProtoSniper::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "radius")) - { - m_flPatience = atof(szValue); - - // If the designer specifies a patience radius of 0, the - // sniper won't have any patience at all. The sniper will - // shoot at the first target it sees regardless of distance. - if( m_flPatience == 0.0 ) - { - m_fIsPatient = false; - } - else - { - m_fIsPatient = true; - } - - return true; - } - else if( FStrEq(szKeyName, "misses") ) - { - m_iMisses = atoi( szValue ); - return true; - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } -} - -LINK_ENTITY_TO_CLASS( npc_sniper, CProtoSniper ); -LINK_ENTITY_TO_CLASS( proto_sniper, CProtoSniper ); -LINK_ENTITY_TO_CLASS( sniperbullet, CSniperBullet ); - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CProtoSniper::Precache( void ) -{ - PrecacheModel("models/combine_soldier.mdl"); - sHaloSprite = PrecacheModel("sprites/light_glow03.vmt"); - sFlashSprite = PrecacheModel( "sprites/muzzleflash1.vmt" ); - PrecacheModel("effects/bluelaser1.vmt"); - - UTIL_PrecacheOther( "sniperbullet" ); - - PrecacheScriptSound( "NPC_Sniper.Die" ); - PrecacheScriptSound( "NPC_Sniper.TargetDestroyed" ); - PrecacheScriptSound( "NPC_Sniper.HearDanger"); - PrecacheScriptSound( "NPC_Sniper.FireBullet" ); - PrecacheScriptSound( "NPC_Sniper.Reload" ); - PrecacheScriptSound( "NPC_Sniper.SonicBoom" ); - - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CProtoSniper::Spawn( void ) -{ - Precache(); - - /// HACK: - SetModel( "models/combine_soldier.mdl" ); - - //m_hBullet = (CSniperBullet *)Create( "sniperbullet", GetBulletOrigin(), GetLocalAngles(), NULL ); - - //Assert( m_hBullet != NULL ); - - SetHullType( HULL_HUMAN ); - SetHullSizeNormal(); - - UTIL_SetSize( this, Vector( -16, -16 , 0 ), Vector( 16, 16, 64 ) ); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_FLY ); - m_bloodColor = DONT_BLEED; - m_iHealth = 10; - m_flFieldOfView = 0.2; - m_NPCState = NPC_STATE_NONE; - - if( HasSpawnFlags( SF_SNIPER_STARTDISABLED ) ) - { - m_fEnabled = false; - } - else - { - m_fEnabled = true; - } - - CapabilitiesClear(); - CapabilitiesAdd( bits_CAP_INNATE_RANGE_ATTACK1 ); - CapabilitiesAdd( bits_CAP_SIMPLE_RADIUS_DAMAGE ); - - m_HackedGunPos = Vector ( 0, 0, 0 ); - - m_spawnflags |= SF_NPC_LONG_RANGE; - m_spawnflags |= SF_NPC_ALWAYSTHINK; - - m_pBeam = NULL; - m_bSweepHighestPriority = false; - - ClearOldDecoys(); - - NPCInit(); - - if( m_spawnflags & SF_SNIPER_HIDDEN ) - { - AddEffects( EF_NODRAW ); - AddSolidFlags( FSOLID_NOT_SOLID ); - } - - // Point the cursor straight ahead so that the sniper's - // first sweep of the laser doesn't look weird. - Vector vecForward; - AngleVectors( GetLocalAngles(), &vecForward ); - m_vecPaintCursor = GetBulletOrigin() + vecForward * 1024; - - m_fWeaponLoaded = true; - - //m_debugOverlays |= OVERLAY_TEXT_BIT; - - // none! - GetEnemies()->SetFreeKnowledgeDuration( 0.0 ); - - m_flTimeLastAttackedPlayer = 0.0f; - m_bWarnedTargetEntity = false; - m_bKilledPlayer = false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CProtoSniper::SetSweepTarget( const char *pszTarget ) -{ - CBaseEntity *pTarget; - - // In case the sniper was sweeping a random set of targets when asked to sweep a normal chain. - ClearTargetGroup(); - - pTarget = gEntList.FindEntityByName( NULL, pszTarget ); - - if( !pTarget ) - { - DevMsg( "**Sniper %s cannot find sweep target %s\n", GetClassname(), pszTarget ); - m_hSweepTarget = NULL; - return; - } - - m_hSweepTarget = pTarget; -} - -//----------------------------------------------------------------------------- -// Purpose: Forces an idle sniper to paint the specified target. -//----------------------------------------------------------------------------- -void CProtoSniper::InputSweepTarget( inputdata_t &inputdata ) -{ - SetSweepTarget( inputdata.value.String() ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CProtoSniper::InputSweepTargetHighestPriority( inputdata_t &inputdata ) -{ - SetSweepTarget( inputdata.value.String() ); - m_bSweepHighestPriority = true; - - if( GetCurSchedule() && stricmp( GetCurSchedule()->GetName(), "SCHED_PSNIPER_RELOAD" ) ) - { - // If you're doing anything except reloading, stop and do this. - ClearSchedule( "Told to sweep target via input" ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CProtoSniper::ClearTargetGroup( void ) -{ - int i; - - for( i = 0 ; i < SNIPER_MAX_GROUP_TARGETS ; i++ ) - { - m_pGroupTarget[ i ] = NULL; - } - - m_iNumGroupTargets = 0; -} - - -//----------------------------------------------------------------------------- -// Purpose: Similar to SweepTarget, but forces the sniper to sweep targets -// in a group (bound by groupname) randomly until interrupted. -//----------------------------------------------------------------------------- -void CProtoSniper::InputSweepGroupRandomly( inputdata_t &inputdata ) -{ - ClearTargetGroup(); - - CBaseEntity *pEnt; - - // PERFORMANCE - // Go through the whole ent list? This could hurt. (sjb) - // Gary: Yes, this sucks. :) - pEnt = gEntList.FirstEnt(); - - do - { - CSniperTarget *pTarget; - - pTarget = dynamic_cast(pEnt); - - // If the pointer is null, this isn't a sniper target. - if( pTarget ) - { - if( !strcmp( inputdata.value.String(), STRING( pTarget->m_iszGroupName ) ) ) - { - m_pGroupTarget[ m_iNumGroupTargets ] = pTarget; - m_iNumGroupTargets++; - } - } - - pEnt = gEntList.NextEnt( pEnt ); - - } while( pEnt ); - - m_hSweepTarget = m_pGroupTarget[ random->RandomInt( 0, m_iNumGroupTargets - 1 ) ]; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CProtoSniper::InputStopSweeping( inputdata_t &inputdata ) -{ - m_hSweepTarget = NULL; - ClearSchedule( "Told to stop sweeping via input" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CProtoSniper::InputProtectTarget( inputdata_t &inputdata ) -{ - m_hProtectTarget = gEntList.FindEntityByName( NULL, inputdata.value.String(), NULL, inputdata.pActivator, inputdata.pCaller ); - - if ( !m_hProtectTarget ) - { - DevMsg( "Sniper %s cannot find protect target %s\n", GetClassname(), inputdata.value.String() ); - return; - } - - m_flDangerEnemyDistance = 0; -} - - - -#if HL2_EPISODIC -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CProtoSniper::InputSetPaintInterval( inputdata_t &inputdata ) -{ - m_flKeyfieldPaintTime = inputdata.value.Float(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CProtoSniper::InputSetPaintIntervalVariance( inputdata_t &inputdata ) -{ - m_flKeyfieldPaintTimeNoise = inputdata.value.Float(); -} -#endif - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTarget - -// Output : int -//----------------------------------------------------------------------------- -int CProtoSniper::IRelationPriority( CBaseEntity *pTarget ) -{ - int priority = BaseClass::IRelationPriority( pTarget ); - - // If we have a target to protect, increase priority on targets closer to it - if ( m_hProtectTarget ) - { - float flDistance = (pTarget->GetAbsOrigin() - m_hProtectTarget->GetAbsOrigin()).LengthSqr(); - if ( flDistance <= SNIPER_PROTECTION_MINDIST ) - { - float flBonus = (1.0 - (flDistance / SNIPER_PROTECTION_MINDIST)) * SNIPER_PROTECTION_PRIORITYCAP; - priority += (int)flBonus; - - if ( m_debugOverlays & OVERLAY_NPC_SELECTED_BIT ) - { - NDebugOverlay::Text( pTarget->GetAbsOrigin() + Vector(0,0,16), UTIL_VarArgs("P: %d (b %f)!", priority, flBonus), false, 0.1 ); - } - } - } - - return priority; -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -// Output : -//----------------------------------------------------------------------------- -Class_T CProtoSniper::Classify( void ) -{ - if( m_fEnabled ) - { - return CLASS_PROTOSNIPER; - } - else - { - return CLASS_NONE; - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Vector CProtoSniper::GetBulletOrigin( void ) -{ - if( m_spawnflags & SF_SNIPER_HIDDEN ) - { - return GetAbsOrigin(); - } - else - { - Vector vecForward; - AngleVectors( GetLocalAngles(), &vecForward ); - return WorldSpaceCenter() + vecForward * 20; - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CProtoSniper::ClearOldDecoys( void ) -{ -#if 0 - int i; - - for( i = 0 ; i < NUM_OLDDECOYS ; i++ ) - { - m_pOldDecoys[ i ] = NULL; - } - - m_iOldDecoySlot = 0; -#endif -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CProtoSniper::HasOldDecoy( CBaseEntity *pDecoy ) -{ -#if 0 - int i; - - for( i = 0 ; i < NUM_OLDDECOYS ; i++ ) - { - if( m_pOldDecoys[ i ] == pDecoy ) - { - return true; - } - } -#endif - - return false; -} - - -//----------------------------------------------------------------------------- -// The list of old decoys is just a circular list. We put decoys that we've -// already fired at in this list. When they've been pushed off the list by others, -// then they are valid targets again. -//----------------------------------------------------------------------------- -void CProtoSniper::AddOldDecoy( CBaseEntity *pDecoy ) -{ -#if 0 - m_pOldDecoys[ m_iOldDecoySlot ] = pDecoy; - m_iOldDecoySlot++; - - if( m_iOldDecoySlot == NUM_OLDDECOYS ) - { - m_iOldDecoySlot = 0; - } -#endif -} - - -//----------------------------------------------------------------------------- -// Purpose: Only blast damage can hurt a sniper. -// -// -// Output : -//----------------------------------------------------------------------------- -#define SNIPER_MAX_INFLICTOR_DIST 15.0f * 12.0f // 15 feet. -int CProtoSniper::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - if( !m_fEnabled ) - { - // As good as not existing. - return 0; - } - - if( !info.GetInflictor() ) - return 0; - - CTakeDamageInfo newInfo = info; - - // Allow SetHealth() & npc_kill inputs to hurt the sniper - if ( info.GetDamageType() == DMG_GENERIC && info.GetInflictor() == this ) - return CAI_BaseNPC::OnTakeDamage_Alive( newInfo ); - - if( !(info.GetDamageType() & (DMG_BLAST|DMG_BURN) ) ) - { - // Only blasts and burning hurt - return 0; - } - - if( (info.GetDamageType() & DMG_BLAST) && info.GetDamage() < m_iHealth ) - { - // Only blasts powerful enough to kill hurt - return 0; - } - - float flDist = GetAbsOrigin().DistTo( info.GetInflictor()->GetAbsOrigin() ); - if( flDist > SNIPER_MAX_INFLICTOR_DIST ) - { - // Sniper only takes damage from explosives that are nearby. This makes a sniper - // susceptible to a grenade that lands in his nest, but not to a large explosion - // that goes off elsewhere and just happens to be able to trace into the sniper's - // nest. - return 0; - } - - if( info.GetDamageType() & DMG_BURN ) - { - newInfo.SetDamage( m_iHealth ); - } - - return CAI_BaseNPC::OnTakeDamage_Alive( newInfo ); -} - -//----------------------------------------------------------------------------- -// Purpose: When a sniper is killed, we launch a fake ragdoll corpse as if the -// sniper was blasted out of his nest. -// -// -// Output : -//----------------------------------------------------------------------------- -void CProtoSniper::Event_Killed( const CTakeDamageInfo &info ) -{ - if( !(m_spawnflags & SF_SNIPER_NOCORPSE) ) - { - Vector vecForward; - - float flForce = random->RandomFloat( 500, 700 ) * 10; - - AngleVectors( GetLocalAngles(), &vecForward ); - - float flFadeTime = 0.0; - - if( HasSpawnFlags( SF_NPC_FADE_CORPSE ) ) - { - flFadeTime = 5.0; - } - - CBaseEntity *pGib; - bool bShouldIgnite = IsOnFire() || hl2_episodic.GetBool(); - pGib = CreateRagGib( "models/combine_soldier.mdl", GetLocalOrigin(), GetLocalAngles(), (vecForward * flForce) + Vector(0, 0, 600), flFadeTime, bShouldIgnite ); - - } - - m_OnDeath.FireOutput( info.GetAttacker(), this ); - - // Tell my killer that he got me! - if( info.GetAttacker() ) - { - info.GetAttacker()->Event_KilledOther(this, info); - g_EventQueue.AddEvent( info.GetAttacker(), "KilledNPC", 0.3, this, this ); - } - - LaserOff(); - - EmitSound( "NPC_Sniper.Die" ); - - UTIL_Remove( this ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CProtoSniper::Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info ) -{ - if( pVictim && pVictim->IsPlayer() ) - { - m_bKilledPlayer = true; - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CProtoSniper::UpdateOnRemove( void ) -{ - LaserOff(); - BaseClass::UpdateOnRemove(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CProtoSniper::SelectSchedule ( void ) -{ - if( HasCondition(COND_ENEMY_DEAD) && sniperspeak.GetBool() ) - { - EmitSound( "NPC_Sniper.TargetDestroyed" ); - } - - if( !m_fWeaponLoaded ) - { - // Reload is absolute priority. - return SCHED_RELOAD; - } - - if( !AI_GetSinglePlayer()->IsAlive() && m_bKilledPlayer ) - { - if( HasCondition(COND_IN_PVS) ) - { - return SCHED_PSNIPER_PLAYER_DEAD; - } - } - - if( HasCondition( COND_HEAR_DANGER ) ) - { - // Next priority is to be suppressed! - ScopeGlint(); - - CSound *pSound = GetBestSound(); - - if( pSound && pSound->IsSoundType( SOUND_DANGER ) && BaseClass::FVisible( pSound->GetSoundReactOrigin() ) ) - { - // The sniper will scream if the sound of a grenade about to detonate is heard. - // If this COND_HEAR_DANGER is due to the sound really being SOUND_DANGER_SNIPERONLY, - // the sniper keeps quiet, because the player's grenade might miss the mark. - - // Make sure the sound is visible, otherwise the sniper will scream at a grenade that - // probably won't harm him. - - // Also, don't play the sound effect if we're an ally. - if ( IsPlayerAllySniper() == false ) - { - EmitSound( "NPC_Sniper.HearDanger" ); - } - } - - return SCHED_PSNIPER_SUPPRESSED; - } - - // OK. If you fall through all the cases above, but you're DISABLED, - // play the schedule that waits a little while and tries again. - if( !m_fEnabled ) - { - return SCHED_PSNIPER_DISABLEDWAIT; - } - - if( HasCondition( COND_SNIPER_SWEEP_TARGET ) ) - { - // Sweep a target. Scripted by level designers! - if( m_hSweepTarget && m_hSweepTarget->HasSpawnFlags( SF_SNIPERTARGET_NOINTERRUPT ) || m_bSweepHighestPriority ) - { - return SCHED_PSNIPER_SWEEP_TARGET_NOINTERRUPT; - } - else - { - return SCHED_PSNIPER_SWEEP_TARGET; - } - } - - if( GetEnemy() == NULL || HasCondition( COND_ENEMY_DEAD ) ) - { - // Look for an enemy. - SetEnemy( NULL ); - return SCHED_PSNIPER_SCAN; - } - - if( HasCondition( COND_SNIPER_FRUSTRATED ) ) - { - return SCHED_PSNIPER_FRUSTRATED_ATTACK; - } - - if( HasCondition( COND_SNIPER_CANATTACKDECOY ) ) - { - return SCHED_RANGE_ATTACK2; - } - - if( HasCondition( COND_SNIPER_NO_SHOT ) ) - { - return SCHED_PSNIPER_NO_CLEAR_SHOT; - } - - if( HasCondition( COND_CAN_RANGE_ATTACK1 ) ) - { - // shoot! - return SCHED_RANGE_ATTACK1; - } - else - { - // Camp on this target - return SCHED_PSNIPER_CAMP; - } -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CProtoSniper::GetSoundInterests( void ) -{ - // Suppress when you hear danger sound - if( m_fEnabled ) - { - return SOUND_DANGER | SOUND_DANGER_SNIPERONLY; - } - - return SOUND_NONE; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CProtoSniper::OnListened() -{ - BaseClass::OnListened(); - - AISoundIter_t iter; - Vector forward; - - GetVectors( &forward, NULL, NULL ); - - CSound *pCurrentSound = GetSenses()->GetFirstHeardSound( &iter ); - while ( pCurrentSound ) - { - // the npc cares about this sound, and it's close enough to hear. - if ( pCurrentSound->FIsSound() ) - { - // this is an audible sound. - if( pCurrentSound->SoundTypeNoContext() == SOUND_DANGER_SNIPERONLY ) - { - SetCondition( COND_HEAR_DANGER ); - } -#if 0 - if( pCurrentSound->IsSoundType( SOUND_BULLET_IMPACT ) ) - { - // Clip this bullet to the shield. - if( pCurrentSound->m_hOwner ) - { - Ray_t ray; - cplane_t plane; - - ray.Init( pCurrentSound->m_hOwner->EyePosition(), pCurrentSound->GetSoundOrigin(), Vector( 0, 0, 0 ), Vector( 0, 0, 0 ) ); - - plane.normal = forward; - plane.type = PLANE_ANYX; - plane.dist = DotProduct( plane.normal, WorldSpaceCenter() + forward * m_flShieldDist ); - plane.signbits = SignbitsForPlane(&plane); - - float fraction = IntersectRayWithPlane( ray, plane ); - - Vector vecImpactPoint = ray.m_Start + ray.m_Delta * fraction; - - float flDist = (vecImpactPoint - (WorldSpaceCenter() + forward * m_flShieldDist)).LengthSqr(); - - if( flDist <= (m_flShieldRadius * m_flShieldRadius) ) - { - CEffectData data; - - data.m_vOrigin = vecImpactPoint; - data.m_vNormal = vec3_origin; - data.m_vAngles = vec3_angle; - data.m_nColor = COMMAND_POINT_YELLOW; - - DispatchEffect( "CommandPointer", data ); - } - } - } -#endif - } - - pCurrentSound = GetSenses()->GetNextHeardSound( &iter ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CProtoSniper::FCanCheckAttacks ( void ) -{ - return true; -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CProtoSniper::FindDecoyObject( void ) -{ -#define SEARCH_DEPTH 50 - - CBaseEntity *pDecoys[ SNIPER_NUM_DECOYS ]; - CBaseEntity *pList[ SEARCH_DEPTH ]; - CBaseEntity *pCurrent; - int count; - int i; - Vector vecTarget = GetEnemy()->WorldSpaceCenter(); - Vector vecDelta; - - m_hDecoyObject = NULL; - - for( i = 0 ; i < SNIPER_NUM_DECOYS ; i++ ) - { - pDecoys[ i ] = NULL; - } - - vecDelta.x = m_flDecoyRadius; - vecDelta.y = m_flDecoyRadius; - vecDelta.z = m_flDecoyRadius; - - count = UTIL_EntitiesInBox( pList, SEARCH_DEPTH, vecTarget - vecDelta, vecTarget + vecDelta, 0 ); - - // Now we have the list of entities near the target. - // Dig through that list and build the list of decoys. - int iIterator = 0; - - for( i = 0 ; i < count ; i++ ) - { - pCurrent = pList[ i ]; - - if( FClassnameIs( pCurrent, "func_breakable" ) || FClassnameIs( pCurrent, "prop_physics" ) || FClassnameIs( pCurrent, "func_physbox" ) ) - { - if( !pCurrent->VPhysicsGetObject() ) - continue; - - if( pCurrent->VPhysicsGetObject()->GetMass() > SNIPER_DECOY_MAX_MASS ) - { - // Skip this very heavy object. Probably a car or dumpster. - continue; - } - - if( pCurrent->VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - { - // Ah! If the player is holding something, try to shoot it! - if( FVisible( pCurrent ) ) - { - m_hDecoyObject = pCurrent; - m_vecDecoyObjectTarget = pCurrent->WorldSpaceCenter(); - return true; - } - } - - // This item meets criteria for a decoy object to shoot at. - - // But have we shot at this item recently? If we HAVE, don't add it. -#if 0 - if( !HasOldDecoy( pCurrent ) ) -#endif - { - pDecoys[ iIterator ] = pCurrent; - - if( iIterator == SNIPER_NUM_DECOYS - 1 ) - { - break; - } - else - { - iIterator++; - } - } - } - } - - if( iIterator == 0 ) - { - return false; - } - - // try 4 times to pick a random object from the list - // and trace to it. If the trace goes off, that's the object! - - for( i = 0 ; i < 4 ; i++ ) - { - CBaseEntity *pProspect; - trace_t tr; - - // Pick one of the decoys at random. - pProspect = pDecoys[ random->RandomInt( 0, iIterator - 1 ) ]; - - Vector vecDecoyTarget; - Vector vecDirToDecoy; - Vector vecBulletOrigin; - - vecBulletOrigin = GetBulletOrigin(); - pProspect->CollisionProp()->RandomPointInBounds( Vector( .1, .1, .1 ), Vector( .6, .6, .6 ), &vecDecoyTarget ); - - // When trying to trace to an object using its absmin + some fraction of its size, it's best - // to lengthen the trace a little beyond the object's bounding box in case it's a more complex - // object, or not axially aligned. - vecDirToDecoy = vecDecoyTarget - vecBulletOrigin; - VectorNormalize(vecDirToDecoy); - - - // Right now, tracing with MASK_BLOCKLOS and checking the fraction as well as the object the trace - // has hit makes it possible for the decoy behavior to shoot through glass. - UTIL_TraceLine( vecBulletOrigin, vecDecoyTarget + vecDirToDecoy * 32, - MASK_BLOCKLOS, this, COLLISION_GROUP_NONE, &tr); - - if( tr.m_pEnt == pProspect || tr.fraction == 1.0 ) - { - // Great! A shot will hit this object. - m_hDecoyObject = pProspect; - m_vecDecoyObjectTarget = tr.endpos; - - // Throw some noise in, don't always hit the center. - Vector vecNoise; - pProspect->CollisionProp()->RandomPointInBounds( Vector( 0.25, 0.25, 0.25 ), Vector( 0.75, 0.75, 0.75 ), &vecNoise ); - m_vecDecoyObjectTarget += vecNoise - pProspect->GetAbsOrigin(); - return true; - } - } - - return false; -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -#define SNIPER_SNAP_SHOT_VELOCITY 125 -bool CProtoSniper::ShouldSnapShot( void ) -{ - if( GetEnemy()->IsPlayer() ) - { - if( GetEnemy()->GetSmoothedVelocity().Length() >= SNIPER_SNAP_SHOT_VELOCITY ) - { - return true; - } - else - { - return false; - } - } - - // Right now, always snapshot at NPC's - return true; -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CProtoSniper::VerifyShot( CBaseEntity *pTarget ) -{ - trace_t tr; - - Vector vecTarget = DesiredBodyTarget( pTarget ); - UTIL_TraceLine( GetBulletOrigin(), vecTarget, MASK_SHOT, pTarget, COLLISION_GROUP_NONE, &tr ); - - if( tr.fraction != 1.0 ) - { - if( pTarget->IsPlayer() ) - { - // if the target is the player, do another trace to see if we can shoot his eyeposition. This should help - // improve sniper responsiveness in cases where the player is hiding his chest from the sniper with his - // head in full view. - UTIL_TraceLine( GetBulletOrigin(), pTarget->EyePosition(), MASK_SHOT, pTarget, COLLISION_GROUP_NONE, &tr ); - - if( tr.fraction == 1.0 ) - { - return true; - } - } - - // Trace hit something. - if( tr.m_pEnt ) - { - if( tr.m_pEnt->m_takedamage == DAMAGE_YES ) - { - // Just shoot it if I can hurt it. Probably a breakable or glass pane. - return true; - } - } - - return false; - } - else - { - return true; - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CProtoSniper::RangeAttack1Conditions ( float flDot, float flDist ) -{ - float fFrustration; - fFrustration = gpGlobals->curtime - m_flFrustration; - - //Msg( "Frustration: %f\n", fFrustration ); - - if( HasCondition( COND_SEE_ENEMY ) && !HasCondition( COND_ENEMY_OCCLUDED ) ) - { - if( VerifyShot( GetEnemy() ) ) - { - // Can see the enemy, have a clear shot to his midsection - ClearCondition( COND_SNIPER_NO_SHOT ); - } - else - { - // Can see the enemy, but can't take a shot at his midsection - SetCondition( COND_SNIPER_NO_SHOT ); - return COND_NONE; - } - - if( m_fIsPatient ) - { - // This sniper has a clear shot at the target, but can not take - // the shot if he is being patient and the target is outside - // of the patience radius. - - float flDist; - - flDist = ( GetLocalOrigin() - GetEnemy()->GetLocalOrigin() ).Length2D(); - - if( flDist <= m_flPatience ) - { - // This target is close enough to attack! - return COND_CAN_RANGE_ATTACK1; - } - else - { - // Be patient... - return COND_NONE; - } - } - else - { - // Not being patient. Clear for attack. - return COND_CAN_RANGE_ATTACK1; - } - } - - if( fFrustration >= 2 && !m_fIsPatient ) - { - if( !(m_spawnflags & SF_SNIPER_NOSWEEP) && !m_hDecoyObject && FindDecoyObject() ) - { - // If I don't have a decoy, try to find one and shoot it. - return COND_SNIPER_CANATTACKDECOY; - } - - - if( fFrustration >= 2.5 ) - { - // Otherwise, just fire somewhere near the hiding enemy. - return COND_SNIPER_FRUSTRATED; - } - } - - return COND_NONE; -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CProtoSniper::TranslateSchedule( int scheduleType ) -{ - switch( scheduleType ) - { - case SCHED_RANGE_ATTACK1: - if( m_hSweepTarget != NULL && m_fSnapShot && ShouldSnapShot() ) - { - return SCHED_PSNIPER_SNAPATTACK; - } - - return SCHED_PSNIPER_ATTACK; - break; - - case SCHED_RANGE_ATTACK2: - return SCHED_PSNIPER_ATTACKDECOY; - break; - - case SCHED_RELOAD: - return SCHED_PSNIPER_RELOAD; - break; - } - return BaseClass::TranslateSchedule( scheduleType ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CProtoSniper::ScopeGlint() -{ - CEffectData data; - - data.m_vOrigin = GetAbsOrigin(); - data.m_vNormal = vec3_origin; - data.m_vAngles = vec3_angle; - data.m_nColor = COMMAND_POINT_BLUE; - - DispatchEffect( "CommandPointer", data ); -} - - -//--------------------------------------------------------- -// This starts the bullet state machine. The actual effects -// of the bullet will happen later. This function schedules -// those effects. -// -// fDirectShot indicates whether the bullet is a "direct shot" -// that is - fired with the intent that it will strike the -// enemy. Otherwise, the bullet is intended to strike a -// decoy object or nothing at all in particular. -//--------------------------------------------------------- -bool CProtoSniper::FireBullet( const Vector &vecTarget, bool bDirectShot ) -{ - CSniperBullet *pBullet; - Vector vecBulletOrigin; - - vecBulletOrigin = GetBulletOrigin(); - - pBullet = (CSniperBullet *)Create( "sniperbullet", GetBulletOrigin(), GetLocalAngles(), NULL ); - - Assert( pBullet != NULL ); - - if( !pBullet->Start( vecBulletOrigin, vecTarget, this, bDirectShot ) ) - { - // Bullet must still be active. - return false; - } - - pBullet->SetOwnerEntity( this ); - - CPASAttenuationFilter filternoatten( this, ATTN_NONE ); - EmitSound( filternoatten, entindex(), "NPC_Sniper.FireBullet" ); - - CPVSFilter filter( vecBulletOrigin ); - te->Sprite( filter, 0.0, &vecBulletOrigin, sFlashSprite, 0.3, 255 ); - - // force a reload when we're done - m_fWeaponLoaded = false; - - // Once the sniper takes a shot, turn the patience off! - m_fIsPatient = false; - - // Alleviate frustration, too! - m_flFrustration = gpGlobals->curtime; - - // This may have been a snap shot. - // Don't allow subsequent snap shots. - m_fSnapShot = false; - - // Return to normal priority - m_bSweepHighestPriority = false; - - // Sniper had to be aiming here to fire here. - // Make it the cursor. - m_vecPaintCursor = vecTarget; - - m_hDecoyObject.Set( NULL ); - - m_OnShotFired.FireOutput( GetEnemy(), this ); - - return true; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -float CProtoSniper::GetBulletSpeed() -{ - float speed = bulletSpeed.GetFloat(); - - if( IsFastSniper() ) - { - speed *= 2.5f; - } - - return speed; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CProtoSniper::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_SNIPER_PLAYER_DEAD: - { - m_hSweepTarget = AI_GetSinglePlayer(); - SetWait( 4.0f ); - LaserOn( m_hSweepTarget->GetAbsOrigin(), vec3_origin ); - } - break; - - case TASK_SNIPER_ATTACK_CURSOR: - break; - - case TASK_RANGE_ATTACK1: - // Start task does nothing here. - // We fall through to RunTask() which will keep trying to take - // the shot until the weapon is ready to fire. In some rare cases, - // the weapon may be ready to fire before the single bullet allocated - // to the sniper has hit its target. - break; - - case TASK_RANGE_ATTACK2: - // Don't call up to base class, it will try to set the activity. - break; - - case TASK_SNIPER_PAINT_SWEEP_TARGET: - if ( !m_hSweepTarget.Get() ) - { - TaskFail( FAIL_NO_TARGET ); - return; - } - - SetWait( m_hSweepTarget->m_flSpeed ); - - // Snap directly to this target if this spawnflag is set. - // Otherwise, sweep from wherever the cursor was. - if( m_hSweepTarget->HasSpawnFlags( SF_SNIPERTARGET_SNAPTO ) ) - { - m_vecPaintCursor = m_hSweepTarget->GetLocalOrigin(); - } - - LaserOn( m_hSweepTarget->GetLocalOrigin(), vec3_origin ); - break; - - case TASK_SNIPER_PAINT_ENEMY: - // Everytime we start to paint an enemy, this is reset to false. - m_bWarnedTargetEntity = false; - - // If the sniper has a sweep target, clear it, unless it's flagged to resume - if( m_hSweepTarget != NULL ) - { - if ( !m_hSweepTarget->HasSpawnFlags( SF_SNIPERTARGET_RESUME) ) - { - ClearTargetGroup(); - m_hSweepTarget = NULL; - } - } - - if( m_spawnflags & SF_SNIPER_VIEWCONE ) - { - SetWait( SNIPER_FOG_PAINT_ENEMY_TIME ); - - // Just turn it on where it is. - LaserOn( m_vecPaintCursor, vec3_origin ); - } - else - { - if( GetEnemy()->IsPlayer() ) - { - float delay = 0; -#ifdef _XBOX - delay += sniper_xbox_delay.GetFloat(); -#endif - - if( gpGlobals->curtime - m_flTimeLastAttackedPlayer <= SNIPER_FASTER_ATTACK_PERIOD ) - { - SetWait( SNIPER_SUBSEQUENT_PAINT_TIME + delay ); - m_flPaintTime = SNIPER_SUBSEQUENT_PAINT_TIME + delay; - } - else - { - SetWait( m_flKeyfieldPaintTime + delay ); - m_flPaintTime = m_flKeyfieldPaintTime + delay; - } - } - else - { - m_flPaintTime = m_flKeyfieldPaintTimeNoise > 0 ? - m_flKeyfieldPaintTime + random->RandomFloat( 0, m_flKeyfieldPaintTimeNoise ) : - m_flKeyfieldPaintTime - ; - - if( IsFastSniper() ) - { - // Get the shot off a little faster. - m_flPaintTime *= 0.75f; - } - - SetWait( m_flPaintTime ); - } - - Vector vecCursor; - - if ( m_spawnflags & SF_SNIPER_NOSWEEP ) - { - LaserOn( m_vecPaintCursor, vec3_origin ); - } - else - { - // Try to start the laser where the player can't miss seeing it! - AngleVectors( GetEnemy()->GetLocalAngles(), &vecCursor ); - vecCursor = vecCursor * 300; - vecCursor += GetEnemy()->EyePosition(); - LaserOn( vecCursor, Vector( 16, 16, 16 ) ); - } - - } - - // Scope glints if shooting at player. - if( GetEnemy()->IsPlayer() ) - { - ScopeGlint(); - } - - break; - - case TASK_SNIPER_PAINT_NO_SHOT: - SetWait( SNIPER_PAINT_NO_SHOT_TIME ); - if( FindFrustratedShot( pTask->flTaskData ) ) - { - LaserOff(); - LaserOn( m_vecFrustratedTarget, vec3_origin ); - } - else - { - TaskFail( "Frustrated shot with no enemy" ); - } - break; - - case TASK_SNIPER_PAINT_FRUSTRATED: - m_flPaintTime = SNIPER_PAINT_FRUSTRATED_TIME + random->RandomFloat( 0, SNIPER_PAINT_FRUSTRATED_TIME ); - SetWait( m_flPaintTime ); - if( FindFrustratedShot( pTask->flTaskData ) ) - { - LaserOff(); - LaserOn( m_vecFrustratedTarget, vec3_origin ); - } - else - { - TaskFail( "Frustrated shot with no enemy" ); - } - break; - - case TASK_SNIPER_PAINT_DECOY: - SetWait( pTask->flTaskData ); - LaserOn( m_vecDecoyObjectTarget, Vector( 64, 64, 64 ) ); - break; - - case TASK_RELOAD: - { - CPASAttenuationFilter filter( this ); - EmitSound( filter, entindex(), "NPC_Sniper.Reload" ); - m_fWeaponLoaded = true; - TaskComplete(); - } - break; - - case TASK_SNIPER_FRUSTRATED_ATTACK: - //FindFrustratedShot(); - break; - - default: - BaseClass::StartTask( pTask ); - break; - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CProtoSniper::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_SNIPER_PLAYER_DEAD: - if( IsWaitFinished() ) - { - m_hSweepTarget = PickDeadPlayerTarget(); - m_vecPaintStart = m_vecPaintCursor; - SetWait( 4.0f ); - } - else - { - PaintTarget( m_hSweepTarget->GetAbsOrigin(), 4.0f ); - } - break; - - case TASK_SNIPER_ATTACK_CURSOR: - if( FireBullet( m_vecPaintCursor, true ) ) - { - TaskComplete(); - } - break; - - case TASK_RANGE_ATTACK1: - // Fire at enemy. - if( FireBullet( LeadTarget( GetEnemy() ), true ) ) - { - // Msg("Firing at %s\n",GetEnemy()->GetEntityName().ToCStr()); - - if( GetEnemy() && GetEnemy()->IsPlayer() ) - { - m_flTimeLastAttackedPlayer = gpGlobals->curtime; - } - - TaskComplete(); - } - else - { - // Msg("Firebullet %s is false\n",GetEnemy()->GetEntityName().ToCStr()); - } - break; - - case TASK_SNIPER_FRUSTRATED_ATTACK: - if( FireBullet( m_vecFrustratedTarget, false ) ) - { - TaskComplete(); - } - break; - - case TASK_SNIPER_PAINT_SWEEP_TARGET: - if ( !m_hSweepTarget.Get() ) - { - TaskFail( FAIL_NO_TARGET ); - return; - } - - if( IsWaitFinished() ) - { - // Time up! Paint the next target in the chain, or stop. - CBaseEntity *pNext; - pNext = gEntList.FindEntityByName( NULL, m_hSweepTarget->m_target ); - - if ( m_hSweepTarget->HasSpawnFlags( SF_SNIPERTARGET_SHOOTME ) ) - { - FireBullet( m_hSweepTarget->GetLocalOrigin(), false ); - TaskComplete(); // Force a reload. - } - - if( pNext || IsSweepingRandomly() ) - { - // Bump the timer up, update the cursor, paint the new target! - // This is done regardless of whether we just fired at the current target. - - m_vecPaintCursor = m_hSweepTarget->GetLocalOrigin(); - if( IsSweepingRandomly() ) - { - // If sweeping randomly, just pick another target. - CBaseEntity *pOldTarget; - - pOldTarget = m_hSweepTarget; - - // Pick another target in the group. Don't shoot at the one we just shot at. - if( m_iNumGroupTargets > 1 ) - { - do - { - m_hSweepTarget = m_pGroupTarget[ random->RandomInt( 0, m_iNumGroupTargets - 1 ) ]; - } while( m_hSweepTarget == pOldTarget ); - } - } - else - { - // If not, go with the next target in the chain. - m_hSweepTarget = pNext; - } - - m_vecPaintStart = m_vecPaintCursor; - SetWait( m_hSweepTarget->m_flSpeed ); - } - else - { - m_hSweepTarget = NULL; - LaserOff(); - TaskComplete(); - } - -#if 0 - NDebugOverlay::Line(GetBulletOrigin(), m_hSweepTarget->GetLocalOrigin(), 0,255,0, true, 20 ); -#endif - } - else - { - if ( m_hSweepTarget->HasSpawnFlags( SF_SNIPERTARGET_SNAPSHOT ) ) - { - m_fSnapShot = true; - } - - PaintTarget( m_hSweepTarget->GetAbsOrigin(), m_hSweepTarget->m_flSpeed ); - } - - break; - - case TASK_SNIPER_PAINT_ENEMY: - if( IsWaitFinished() ) - { - TaskComplete(); - } - - PaintTarget( LeadTarget( GetEnemy() ), m_flPaintTime ); - break; - - case TASK_SNIPER_PAINT_DECOY: - if( IsWaitFinished() ) - { - TaskComplete(); - } - - PaintTarget( m_vecDecoyObjectTarget, pTask->flTaskData ); - break; - - case TASK_SNIPER_PAINT_NO_SHOT: - if( IsWaitFinished() ) - { - //HACKHACK(sjb) - // This condition should be turned off - // by a task. - ClearCondition( COND_SNIPER_NO_SHOT ); - TaskComplete(); - } - - PaintTarget( m_vecFrustratedTarget, SNIPER_PAINT_NO_SHOT_TIME ); - break; - - case TASK_SNIPER_PAINT_FRUSTRATED: - if( IsWaitFinished() ) - { - TaskComplete(); - } - - PaintTarget( m_vecFrustratedTarget, m_flPaintTime ); - break; - - case TASK_RANGE_ATTACK2: - // Fire at decoy - if( m_hDecoyObject == NULL ) - { - TaskFail("sniper: bad decoy"); - break; - } - - if( FireBullet( m_vecDecoyObjectTarget, false ) ) - { - //Msg( "Fired at decoy\n" ); - AddOldDecoy( m_hDecoyObject ); - TaskComplete(); - } - break; - - default: - BaseClass::RunTask( pTask ); - break; - } -} - - -//----------------------------------------------------------------------------- -// The sniper throws away the circular list of old decoys when we restore. -//----------------------------------------------------------------------------- -int CProtoSniper::Restore( IRestore &restore ) -{ - ClearOldDecoys(); - - return BaseClass::Restore( restore ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -float CProtoSniper::MaxYawSpeed( void ) -{ - return 60; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CProtoSniper::PrescheduleThink( void ) -{ - BaseClass::PrescheduleThink(); - - // If a sweep target is set, keep asking the AI to sweep the target - if( m_hSweepTarget != NULL ) - { - if( m_bSweepHighestPriority || (!HasCondition( COND_CAN_RANGE_ATTACK1 ) && !HasCondition( COND_SNIPER_NO_SHOT ) ) ) - { - SetCondition( COND_SNIPER_SWEEP_TARGET ); - } - } - else - { - ClearCondition( COND_SNIPER_SWEEP_TARGET ); - } - - // Think faster if the beam is on, this gives the beam higher resolution. - if( m_pBeam ) - { - SetNextThink( gpGlobals->curtime + 0.03 ); - } - else - { - SetNextThink( gpGlobals->curtime + 0.1f ); - } - - // If the enemy has just stepped into view, or we've acquired a new enemy, - // Record the last time we've seen the enemy as right now. - // - // If the enemy has been out of sight for a full second, mark him eluded. - if( GetEnemy() != NULL ) - { - if( gpGlobals->curtime - GetEnemies()->LastTimeSeen( GetEnemy() ) > 30 ) - { - // Stop pestering enemies after 30 seconds of frustration. - GetEnemies()->ClearMemory( GetEnemy() ); - SetEnemy(NULL); - } - } - - // Suppress at the sound of danger. Incoming missiles, for example. - if( HasCondition( COND_HEAR_DANGER ) ) - { - SetCondition( COND_SNIPER_SUPPRESSED ); - } -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -Vector CProtoSniper::EyePosition( void ) -{ - if( m_spawnflags & SF_SNIPER_HIDDEN ) - { - return GetLocalOrigin(); - } - else - { - return BaseClass::EyePosition(); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -Vector CProtoSniper::DesiredBodyTarget( CBaseEntity *pTarget ) -{ - // By default, aim for the center - Vector vecTarget = pTarget->WorldSpaceCenter(); - - float flTimeSinceLastMiss = gpGlobals->curtime - m_flTimeLastShotMissed; - - if( pTarget->GetFlags() & FL_CLIENT ) - { - if( !BaseClass::FVisible( vecTarget ) ) - { - // go to the player's eyes if his center is concealed. - // Bump up an inch so the player's not looking straight down a beam. - vecTarget = pTarget->EyePosition() + Vector( 0, 0, 1 ); - } - } - else - { - if( pTarget->Classify() == CLASS_HEADCRAB ) - { - // Headcrabs are tiny inside their boxes. - vecTarget = pTarget->GetAbsOrigin(); - vecTarget.z += 4.0; - } - else if( !m_bShootZombiesInChest && pTarget->Classify() == CLASS_ZOMBIE ) - { - if( flTimeSinceLastMiss > 0.0f && flTimeSinceLastMiss < 4.0f && hl2_episodic.GetBool() ) - { - vecTarget = pTarget->BodyTarget( GetBulletOrigin(), false ); - } - else - { - // Shoot zombies in the headcrab - vecTarget = pTarget->HeadTarget( GetBulletOrigin() ); - } - } - else if( pTarget->Classify() == CLASS_ANTLION ) - { - // Shoot about a few inches above the origin. This makes it easy to hit antlions - // even if they are on their backs. - vecTarget = pTarget->GetAbsOrigin(); - vecTarget.z += 18.0f; - } - else if( pTarget->Classify() == CLASS_EARTH_FAUNA ) - { - // Shoot birds in the center - } - else - { - // Shoot NPCs in the chest - vecTarget.z += 8.0f; - } - } - - return vecTarget; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -Vector CProtoSniper::LeadTarget( CBaseEntity *pTarget ) -{ - float targetTime; - float targetDist; - //float adjustedShotDist; - //float actualShotDist; - Vector vecAdjustedShot; - Vector vecTarget; - trace_t tr; - - /* - NDebugOverlay::EntityBounds(pTarget, - 255,255,0,96,0.1f); - */ - if( sniperLines.GetBool() ) - { - Msg("Sniper %s is targeting %s\n", GetDebugName(), pTarget ? pTarget->GetDebugName() : "nobody" ); - } - - if( pTarget == NULL ) - { - // no target - return vec3_origin; - } - - // Get target - vecTarget = DesiredBodyTarget( pTarget ); - - // Get bullet time to target - targetDist = (vecTarget - GetBulletOrigin() ).Length(); - targetTime = targetDist / GetBulletSpeed(); - - // project target's velocity over that time. - Vector vecVelocity = vec3_origin; - - if( pTarget->IsPlayer() || pTarget->Classify() == CLASS_MISSILE ) - { - // This target is a client, who has an actual velocity. - vecVelocity = pTarget->GetSmoothedVelocity(); - - // Slow the vertical velocity down a lot, or the sniper will - // lead a jumping player by firing several feet above his head. - // THIS may affect the sniper hitting a player that's ascending/descending - // ladders. If so, we'll have to check for the player's ladder flag. - if( pTarget->GetFlags() & FL_CLIENT ) - { - vecVelocity.z *= 0.25; - } - } - else - { - if( pTarget->MyNPCPointer() && pTarget->MyNPCPointer()->GetNavType() == NAV_FLY ) - { - // Take a flying monster's velocity directly. - vecVelocity = pTarget->GetAbsVelocity(); - } - else - { - // Have to build a velocity vector using the character's current groundspeed. - CBaseAnimating *pAnimating; - - pAnimating = (CBaseAnimating *)pTarget; - - Assert( pAnimating != NULL ); - - QAngle vecAngle; - vecAngle.y = pAnimating->GetSequenceMoveYaw( pAnimating->GetSequence() ); - vecAngle.x = 0; - vecAngle.z = 0; - - vecAngle.y += pTarget->GetLocalAngles().y; - - AngleVectors( vecAngle, &vecVelocity ); - - vecVelocity = vecVelocity * pAnimating->m_flGroundSpeed; - } - } - - if( m_iMisses > 0 && !FClassnameIs( pTarget, "npc_bullseye" ) ) - { - // I'm supposed to miss this shot, so aim above the target's head. - // BUT DON'T miss bullseyes, and don't count the shot. - vecAdjustedShot = vecTarget; - vecAdjustedShot.z += 16; - - m_iMisses--; - - // NDebugOverlay::Cross3D(vecAdjustedShot,12.0f,255,0,0,false,1); - - return vecAdjustedShot; - } - - vecAdjustedShot = vecTarget + ( vecVelocity * targetTime ); - - // if the adjusted shot falls well short of the target, take the straight shot. - // it's not very interesting for the bullet to hit something far away from the - // target. (for instance, if a sign or ledge or something is between the player - // and the sniper, and the sniper would hit this object if he tries to lead the player) - - // NDebugOverlay::Cross3D(vecAdjustedShot,12.0f,5,255,0,false,1); - - if( sniperLines.GetFloat() == 1.0f ) - { - Vector vecBulletOrigin; - vecBulletOrigin = GetBulletOrigin(); - CPVSFilter filter( GetLocalOrigin() ); - te->ShowLine( filter, 0.0, &vecBulletOrigin, &vecAdjustedShot ); - } - - - -/* - UTIL_TraceLine( vecBulletOrigin, vecAdjustedShot, MASK_SHOT, this, &tr ); - - actualShotDist = (tr.endpos - vecBulletOrigin ).Length(); - adjustedShotDist = ( vecAdjustedShot - vecBulletOrigin ).Length(); - - ///////////////////////////////////////////// - // the shot taken should hit within 10% of the sniper's distance to projected target. - // else, shoot straight. (there's some object in the way of the adjusted shot) - ///////////////////////////////////////////// - if( actualShotDist <= adjustedShotDist * 0.9 ) - { - vecAdjustedShot = vecTarget; - } -*/ - return vecAdjustedShot; -} - -//--------------------------------------------------------- -// Sniper killed the player. Pick the player's body or something -// nearby to point the laser at, so that the player can get -// a fix on the sniper's location. -//--------------------------------------------------------- -CBaseEntity *CProtoSniper::PickDeadPlayerTarget() -{ - const int iSearchSize = 32; - CBaseEntity *pTarget = AI_GetSinglePlayer(); - CBaseEntity *pEntities[ iSearchSize ]; - - int iNumEntities = UTIL_EntitiesInSphere( pEntities, iSearchSize, AI_GetSinglePlayer()->GetAbsOrigin(), 180.0f, 0 ); - - // Not very robust, but doesn't need to be. Randomly select a nearby object in the list that isn't an NPC. - if( iNumEntities > 0 ) - { - int i; - - // Try a few times to randomly select a target. - for( i = 0 ; i < 10 ; i++ ) - { - CBaseEntity *pCandidate = pEntities[ random->RandomInt(0, iNumEntities - 1) ]; - - if( !pCandidate->IsNPC() && FInViewCone(pCandidate) ) - { - return pCandidate; - } - } - } - - // Fall through to accept the player as a target. - return pTarget; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CProtoSniper::InputEnableSniper( inputdata_t &inputdata ) -{ - ClearCondition( COND_SNIPER_DISABLED ); - SetCondition( COND_SNIPER_ENABLED ); - - m_fEnabled = true; -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CProtoSniper::InputDisableSniper( inputdata_t &inputdata ) -{ - ClearCondition( COND_SNIPER_ENABLED ); - SetCondition( COND_SNIPER_DISABLED ); - - m_fEnabled = false; -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CProtoSniper::FindFrustratedShot( float flNoise ) -{ - Vector vecForward; - Vector vecStart; - Vector vecAimAt; - Vector vecAim; - - if( !GetEnemy() ) - { - return false; - } - - // Just pick a spot somewhere around the target. - // Try a handful of times to pick a spot that guarantees the - // target will see the laser. -#define MAX_TRIES 15 - for( int i = 0 ; i < MAX_TRIES ; i++ ) - { - Vector vecSpot = GetEnemyLKP(); - - vecSpot.x += random->RandomFloat( -64, 64 ); - vecSpot.y += random->RandomFloat( -64, 64 ); - vecSpot.z += random->RandomFloat( -40, 40 ); - - // Help move the frustrated spot off the target's BBOX in X/Y space. - if( vecSpot.x < 0 ) - vecSpot.x -= 32; - else - vecSpot.x += 32; - - if( vecSpot.y < 0 ) - vecSpot.y -= 32; - else - vecSpot.y += 32; - - Vector vecSrc, vecDir; - - vecSrc = GetAbsOrigin(); - vecDir = vecSpot - vecSrc; - VectorNormalize( vecDir ); - - if( GetEnemy()->FVisible( vecSpot ) || i == MAX_TRIES - 1 ) - { - trace_t tr; - AI_TraceLine(vecSrc, vecSrc + vecDir * 8192, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); - - if( !GetEnemy()->FVisible( tr.endpos ) ) - { - // Dont accept this point unless we are out of tries! - if( i != MAX_TRIES - 1 ) - { - continue; - } - } - m_vecFrustratedTarget = tr.endpos; - break; - } - } - -#if 0 - NDebugOverlay::Line(vecStart, tr.endpos, 0,255,0, true, 20 ); -#endif - - return true; -} - - -//--------------------------------------------------------- -// See all NPC's easily. -// -// Only see the player if you can trace to both of his -// eyeballs. That is, allow the player to peek around corners. -// This is a little more expensive than the base class' check! -//--------------------------------------------------------- -#define SNIPER_EYE_DIST 0.75 -#define SNIPER_TARGET_VERTICAL_OFFSET Vector( 0, 0, 5 ); -bool CProtoSniper::FVisible( CBaseEntity *pEntity, int traceMask, CBaseEntity **ppBlocker ) -{ - if( m_spawnflags & SF_SNIPER_VIEWCONE ) - { - // Viewcone snipers are blind with their laser off. - if( !IsLaserOn() ) - { - return false; - } - } - - if( !pEntity->IsPlayer() ) - { - // NPC - return BaseClass::FVisible( pEntity, traceMask, ppBlocker ); - } - - if ( pEntity->GetFlags() & FL_NOTARGET ) - { - return false; - } - - Vector vecVerticalOffset; - Vector vecRight; - Vector vecEye; - trace_t tr; - - if( fabs( GetAbsOrigin().z - pEntity->WorldSpaceCenter().z ) <= 120.f ) - { - // If the player is around the same elevation, look straight at his eyes. - // At the same elevation, the vertical peeking allowance makes it too easy - // for a player to dispatch the sniper from cover. - vecVerticalOffset = vec3_origin; - } - else - { - // Otherwise, look at a spot below his eyes. This allows the player to back away - // from his cover a bit and have a peek at the sniper without being detected. - vecVerticalOffset = SNIPER_TARGET_VERTICAL_OFFSET; - } - - AngleVectors( pEntity->GetLocalAngles(), NULL, &vecRight, NULL ); - - vecEye = vecRight * SNIPER_EYE_DIST - vecVerticalOffset; - UTIL_TraceLine( EyePosition(), pEntity->EyePosition() + vecEye, MASK_BLOCKLOS, this, COLLISION_GROUP_NONE, &tr ); - -#if 0 - NDebugOverlay::Line(EyePosition(), tr.endpos, 0,255,0, true, 0.1); -#endif - - bool fCheckFailed = false; - - if( tr.fraction != 1.0 ) - { - fCheckFailed = true; - } - - // Don't check the other eye if the first eye failed. - if( !fCheckFailed ) - { - vecEye = -vecRight * SNIPER_EYE_DIST - vecVerticalOffset; - UTIL_TraceLine( EyePosition(), pEntity->EyePosition() + vecEye, MASK_BLOCKLOS, this, COLLISION_GROUP_NONE, &tr ); - -#if 0 - NDebugOverlay::Line(EyePosition(), tr.endpos, 0,255,0, true, 0.1); -#endif - - if( tr.fraction != 1.0 ) - { - fCheckFailed = true; - } - } - - if( !fCheckFailed ) - { - // Can see the player. - return true; - } - - // Now, if the check failed, see if the player is ducking and has recently - // fired a muzzleflash. If yes, see if you'd be able to see the player if - // they were standing in their current position instead of ducking. Since - // the sniper doesn't have a clear shot in this situation, he will harrass - // near the player. - CBasePlayer *pPlayer; - - pPlayer = ToBasePlayer( pEntity ); - - if( (pPlayer->GetFlags() & FL_DUCKING) && pPlayer->MuzzleFlashTime() > gpGlobals->curtime ) - { - vecEye = pPlayer->EyePosition() + Vector( 0, 0, 32 ); - UTIL_TraceLine( EyePosition(), vecEye, MASK_BLOCKLOS, this, COLLISION_GROUP_NONE, &tr ); - - if( tr.fraction != 1.0 ) - { - // Everything failed. - if (ppBlocker) - { - *ppBlocker = tr.m_pEnt; - } - return false; - } - else - { - // Fake being able to see the player. - return true; - } - } - - if (ppBlocker) - { - *ppBlocker = tr.m_pEnt; - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Returns the current text offset from the top -//----------------------------------------------------------------------------- -int CProtoSniper::DrawDebugTextOverlays() -{ - int text_offset = 0; - - // --------------------- - // Print Baseclass text - // --------------------- - text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - - CSniperTarget *pTarget = NULL; - if ( m_iNumGroupTargets > 0 ) - { - pTarget = dynamic_cast(m_pGroupTarget[0]); - } - - Q_snprintf( tempstr, sizeof( tempstr ), "Sweep group (count): %s (%d)", pTarget != NULL ? STRING( pTarget->m_iszGroupName ) : "", m_iNumGroupTargets ); - EntityText( text_offset, tempstr, 0 ); - text_offset++; - - for ( int i = 0; i < m_iNumGroupTargets; i++ ) - { - if ( m_pGroupTarget[i] != NULL ) - { - NDebugOverlay::VertArrow( EyePosition(), m_pGroupTarget[i]->GetAbsOrigin(), 8, 0, 255, 0, 0, true, 0); - } - } - } - - return text_offset; -} - -//----------------------------------------------------------------------------- -// Inform the sniper that a bullet missed its intended target. We don't know -// which bullet or which target. -//----------------------------------------------------------------------------- -void CProtoSniper::NotifyShotMissedTarget() -{ - m_flTimeLastShotMissed = gpGlobals->curtime; - // In episodic, aim at the (easier to hit at distance or high speed) centers - // of the bodies of NPC targets. This change makes Alyx sniper less likely to - // miss zombie and zombines over and over because of the large amount of head movement - // in these NPCs' walk and run animations. -} - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC( proto_sniper, CProtoSniper ) - - DECLARE_CONDITION( COND_SNIPER_CANATTACKDECOY ); - DECLARE_CONDITION( COND_SNIPER_SUPPRESSED ); - DECLARE_CONDITION( COND_SNIPER_ENABLED ); - DECLARE_CONDITION( COND_SNIPER_DISABLED ); - DECLARE_CONDITION( COND_SNIPER_FRUSTRATED ); - DECLARE_CONDITION( COND_SNIPER_SWEEP_TARGET ); - DECLARE_CONDITION( COND_SNIPER_NO_SHOT ); - - DECLARE_TASK( TASK_SNIPER_FRUSTRATED_ATTACK ); - DECLARE_TASK( TASK_SNIPER_PAINT_ENEMY ); - DECLARE_TASK( TASK_SNIPER_PAINT_DECOY ); - DECLARE_TASK( TASK_SNIPER_PAINT_FRUSTRATED ); - DECLARE_TASK( TASK_SNIPER_PAINT_SWEEP_TARGET ); - DECLARE_TASK( TASK_SNIPER_ATTACK_CURSOR ); - DECLARE_TASK( TASK_SNIPER_PAINT_NO_SHOT ); - DECLARE_TASK( TASK_SNIPER_PLAYER_DEAD ); - - //========================================================= - // SCAN - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_PSNIPER_SCAN, - - " Tasks" - " TASK_WAIT_INDEFINITE 0" - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_HEAR_DANGER" - " COND_SNIPER_DISABLED" - " COND_SNIPER_SWEEP_TARGET" - ) - - //========================================================= - // CAMP - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_PSNIPER_CAMP, - - " Tasks" - " TASK_WAIT_INDEFINITE 0" - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_CAN_RANGE_ATTACK1" - " COND_SNIPER_CANATTACKDECOY" - " COND_SNIPER_SUPPRESSED" - " COND_HEAR_DANGER" - " COND_SNIPER_DISABLED" - " COND_SNIPER_FRUSTRATED" - " COND_SNIPER_SWEEP_TARGET" - ) - - //========================================================= - // ATTACK - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_PSNIPER_ATTACK, - - " Tasks" - " TASK_SNIPER_PAINT_ENEMY 0" - " TASK_RANGE_ATTACK1 0" - " " - " Interrupts" - " COND_ENEMY_OCCLUDED" - " COND_ENEMY_DEAD" - " COND_HEAR_DANGER" - " COND_SNIPER_DISABLED" - ) - - //========================================================= - // ATTACK - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_PSNIPER_SNAPATTACK, - - " Tasks" - " TASK_SNIPER_ATTACK_CURSOR 0" - " " - " Interrupts" - " COND_ENEMY_OCCLUDED" - " COND_ENEMY_DEAD" - " COND_NEW_ENEMY" - " COND_HEAR_DANGER" - " COND_SNIPER_DISABLED" - ) - - //========================================================= - // RELOAD - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_PSNIPER_RELOAD, - - " Tasks" - " TASK_RELOAD 0" - " TASK_WAIT 1.0" - " " - " Interrupts" - " COND_HEAR_DANGER" - ) - - //========================================================= - // Attack decoy - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_PSNIPER_ATTACKDECOY, - - " Tasks" - " TASK_SNIPER_PAINT_DECOY 2.0" - " TASK_RANGE_ATTACK2 0" - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_HEAR_DANGER" - " COND_CAN_RANGE_ATTACK1" - " COND_SNIPER_DISABLED" - " COND_SNIPER_SWEEP_TARGET" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_PSNIPER_SUPPRESSED, - - " Tasks" - " TASK_WAIT 2.0" - " " - " Interrupts" - ) - - //========================================================= - // Sniper is allowed to process a couple conditions while - // disabled, but mostly he waits until he's enabled. - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_PSNIPER_DISABLEDWAIT, - - " Tasks" - " TASK_WAIT 0.5" - " " - " Interrupts" - " COND_SNIPER_ENABLED" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_PSNIPER_FRUSTRATED_ATTACK, - - " Tasks" - " TASK_WAIT 2.0" - " TASK_SNIPER_PAINT_FRUSTRATED 0.05" - " TASK_SNIPER_PAINT_FRUSTRATED 0.025" - " TASK_SNIPER_PAINT_FRUSTRATED 0.0" - " TASK_SNIPER_FRUSTRATED_ATTACK 0.0" - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_SNIPER_DISABLED" - " COND_CAN_RANGE_ATTACK1" - " COND_SEE_ENEMY" - " COND_HEAR_DANGER" - " COND_SNIPER_SWEEP_TARGET" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_PSNIPER_SWEEP_TARGET, - - " Tasks" - " TASK_SNIPER_PAINT_SWEEP_TARGET 0.0" - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_SNIPER_DISABLED" - " COND_CAN_RANGE_ATTACK1" - " COND_HEAR_DANGER" - " COND_SNIPER_NO_SHOT" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_PSNIPER_SWEEP_TARGET_NOINTERRUPT, - - " Tasks" - " TASK_SNIPER_PAINT_SWEEP_TARGET 0.0" - " " - " Interrupts" - " COND_SNIPER_DISABLED" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_PSNIPER_NO_CLEAR_SHOT, - - " Tasks" - " TASK_SNIPER_PAINT_NO_SHOT 0.0" - " TASK_SNIPER_PAINT_NO_SHOT 0.075" - " TASK_SNIPER_PAINT_NO_SHOT 0.05" - " TASK_SNIPER_PAINT_NO_SHOT 0.0" - " " - " Interrupts" - " COND_NEW_ENEMY" - " COND_ENEMY_DEAD" - " COND_SNIPER_DISABLED" - " COND_CAN_RANGE_ATTACK1" - " COND_HEAR_DANGER" - ) - - //========================================================= - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_PSNIPER_PLAYER_DEAD, - - " Tasks" - " TASK_SNIPER_PLAYER_DEAD 0" - " " - " Interrupts" - ) - -AI_END_CUSTOM_NPC() - -//----------------------------------------------------------------------------- -// -// Sniper Bullet -// -//----------------------------------------------------------------------------- - - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CSniperBullet::Precache() -{ -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CSniperBullet::BulletThink( void ) -{ - // Set the bullet up to think again. - SetNextThink( gpGlobals->curtime + 0.05 ); - - if( !GetOwnerEntity() ) - { - // Owner died! - Stop(); - return; - } - - if( gpGlobals->curtime >= m_SoundTime ) - { - // See if it's time to make the sonic boom. - CPASAttenuationFilter filter( this, ATTN_NONE ); - EmitSound( filter, entindex(), "NPC_Sniper.SonicBoom" ); - - if( GetOwnerEntity() ) - { - CAI_BaseNPC *pSniper; - CAI_BaseNPC *pEnemyNPC; - pSniper = GetOwnerEntity()->MyNPCPointer(); - - if( pSniper && pSniper->GetEnemy() ) - { - pEnemyNPC = pSniper->GetEnemy()->MyNPCPointer(); - - // Warn my enemy if they can see the sniper. - if( pEnemyNPC && GetOwnerEntity() && pEnemyNPC->FVisible( GetOwnerEntity()->WorldSpaceCenter() ) ) - { - CSoundEnt::InsertSound( SOUND_DANGER | SOUND_CONTEXT_FROM_SNIPER, pSniper->GetEnemy()->EarPosition(), 16, 1.0f, GetOwnerEntity() ); - } - } - } - - // No way the bullet will live this long. - m_SoundTime = 1e9; - } - - // Trace this timeslice of the bullet. - Vector vecStart; - Vector vecEnd; - float flInterval; - - flInterval = gpGlobals->curtime - GetLastThink(); - vecStart = GetAbsOrigin(); - vecEnd = vecStart + ( m_vecDir * (m_Speed * flInterval) ); - float flDist = (vecStart - vecEnd).Length(); - - //Msg("."); - - trace_t tr; - AI_TraceLine( vecStart, vecEnd, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - if( tr.fraction != 1.0 ) - { - // This slice of bullet will hit something. - GetOwnerEntity()->FireBullets( 1, vecStart, m_vecDir, vec3_origin, flDist, m_AmmoType, 0 ); - m_iImpacts++; - -#ifdef HL2_EPISODIC - if( tr.m_pEnt->IsNPC() || m_iImpacts == NUM_PENETRATIONS ) -#else - if( tr.m_pEnt->m_takedamage == DAMAGE_YES || m_iImpacts == NUM_PENETRATIONS ) -#endif//HL2_EPISODIC - { - // Bullet stops when it hits an NPC, or when it has penetrated enough times. - - if( tr.m_pEnt && tr.m_pEnt->VPhysicsGetObject() ) - { - if( tr.m_pEnt->VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - { - Pickup_ForcePlayerToDropThisObject(tr.m_pEnt); - } - } - - Stop(); - return; - } - else - { - #define STEP_SIZE 2 - #define NUM_STEPS 6 - // Try to slide a 'cursor' through the object that was hit. - Vector vecCursor = tr.endpos; - - for( int i = 0 ; i < NUM_STEPS ; i++ ) - { - //Msg("-"); - vecCursor += m_vecDir * STEP_SIZE; - - if( UTIL_PointContents( vecCursor ) != CONTENTS_SOLID ) - { - // Passed out of a solid! - SetAbsOrigin( vecCursor ); - - // Fire another tracer. - AI_TraceLine( vecCursor, vecCursor + m_vecDir * 8192, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - UTIL_Tracer( vecCursor, tr.endpos, 0, TRACER_DONT_USE_ATTACHMENT, m_Speed, true, "StriderTracer" ); - return; - } - } - - // Bullet also stops when it fails to exit material after penetrating this far. - //Msg("#\n"); - if( m_bDirectShot ) - { - CProtoSniper *pSniper = dynamic_cast(GetOwnerEntity()); - if( pSniper ) - { - pSniper->NotifyShotMissedTarget(); - } - } - - Stop(); - return; - } - } - else - { - SetAbsOrigin( vecEnd ); - } -} - - -//========================================================= -//========================================================= -bool CSniperBullet::Start( const Vector &vecOrigin, const Vector &vecTarget, CBaseEntity *pOwner, bool bDirectShot ) -{ - m_flLastThink = gpGlobals->curtime; - - if( m_AmmoType == -1 ) - { - // This guy doesn't have a REAL weapon, per say, but he does fire - // sniper rounds. Since there's no weapon to index the ammo type, - // do it manually here. - m_AmmoType = GetAmmoDef()->Index("SniperRound"); - - // This is the bullet that is used for all subsequent FireBullets() calls after the first - // call penetrates a surface and keeps going. - m_PenetratedAmmoType = GetAmmoDef()->Index("SniperPenetratedRound"); - } - - if( m_fActive ) - { - return false; - } - - SetOwnerEntity( pOwner ); - - UTIL_SetOrigin( this, vecOrigin ); - - m_vecDir = vecTarget - vecOrigin; - VectorNormalize( m_vecDir ); - - // Set speed; - CProtoSniper *pSniper = dynamic_cast(pOwner); - - if( pSniper ) - { - m_Speed = pSniper->GetBulletSpeed(); - } - else - { - m_Speed = bulletSpeed.GetFloat(); - } - - // Start the tracer here, and tell it to end at the end of the last trace - // the trace comes from the loop above that does penetration. - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + m_vecDir * 8192, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - UTIL_Tracer( vecOrigin, tr.endpos, 0, TRACER_DONT_USE_ATTACHMENT, m_Speed, true, "StriderTracer" ); - - float flElapsedTime = ( (tr.startpos - tr.endpos).Length() / m_Speed ); - m_SoundTime = gpGlobals->curtime + flElapsedTime * 0.5; - - SetThink( &CSniperBullet::BulletThink ); - SetNextThink( gpGlobals->curtime ); - m_fActive = true; - m_bDirectShot = bDirectShot; - return true; - -/* - int i; - - // Try to find all of the things the bullet can go through along the way. - //------------------------------- - //------------------------------- - m_vecDir = vecTarget - vecOrigin; - VectorNormalize( m_vecDir ); - - trace_t tr; - - - // Elapsed time counts how long the bullet is in motion through this simulation. - float flElapsedTime = 0; - - for( i = 0 ; i < NUM_PENETRATIONS ; i++ ) - { - // Trace to the target. - UTIL_TraceLine( GetAbsOrigin(), vecTarget, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - flShotDist = (tr.endpos - GetAbsOrigin()).Length(); - - // Record the two endpoints of the segment and the time at which this bullet hits, - // and the time at which it's supposed to hit its mark. - m_ImpactTime[ i ] = flElapsedTime + ( flShotDist / GetBulletSpeed() ); - m_vecStart[ i ] = tr.startpos; - m_vecEnd[ i ] = tr.endpos; - - // The elapsed time is now pushed forward by how long it takes the bullet - // to travel through this segment. - flElapsedTime += ( flShotDist / GetBulletSpeed() ); - - // Never let gpGlobals->curtime get added to the elapsed time! - m_ImpactTime[ i ] += gpGlobals->curtime; - - CBaseEntity *pEnt; - - pEnt = tr.m_pEnt; - - if( !pEnt || - pEnt->MyNPCPointer() || - UTIL_DistApprox2D( tr.endpos, vecTarget ) <= 4 || - FClassnameIs( pEnt, "prop_physics" ) ) - { - // If we're close to the target, assume the shot is going to hit - // the target and stop penetrating. - // - // If we're going to hit an NPC, stop penetrating. - // - // If we hit a physics prop, stop penetrating. - // - // Otherwise, keep looping. - break; - } - - // We're going to try to penetrate whatever the bullet has hit. - - // Push through the object by the penetration distance, then trace back. - Vector vecCursor; - - vecCursor = tr.endpos; - vecCursor += m_vecDir * PENETRATION_THICKNESS; - - UTIL_TraceLine( vecCursor, vecCursor + m_vecDir * -2, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - -#if 1 - if( tr.startsolid ) - { - // The cursor is inside the solid. Solid is too thick to penetrate. -#ifdef SNIPER_DEBUG - Msg( "SNIPER STARTSOLID\n" ); -#endif - break; - } -#endif - - // Now put the bullet at this point and continue. - UTIL_SetOrigin( this, vecCursor ); - } - //------------------------------- - //------------------------------- -*/ - - -/* -#ifdef SNIPER_DEBUG - Msg( "PENETRATING %d items", i ); -#endif // SNIPER_DEBUG - -#ifdef SNIPER_DEBUG - Msg( "Dist: %f Travel Time: %f\n", flShotDist, m_ImpactTime ); -#endif // SNIPER_DEBUG -*/ -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CSniperBullet::Init( void ) -{ -#ifdef SNIPER_DEBUG - Msg( "Bullet stopped\n" ); -#endif // SNIPER_DEBUG - - m_fActive = false; - m_vecDir.Init(); - m_AmmoType = -1; - m_SoundTime = 1e9; - m_iImpacts = 0; -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CSniperBullet::Stop( void ) -{ - // The bullet doesn't retire immediately because it still has a sound - // in the world that is relying on the bullet's position as a react origin. - // So stick around for another second or so. - SetThink( &CBaseEntity::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 1.0 ); -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CSniperTarget::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "groupname")) - { - m_iszGroupName = AllocPooledString( szValue ); - return true; - } - else - { - return CPointEntity::KeyValue( szKeyName, szValue ); - } -} - -LINK_ENTITY_TO_CLASS( info_snipertarget, CSniperTarget ); - - diff --git a/game/server/hl2/rotorwash.cpp b/game/server/hl2/rotorwash.cpp deleted file mode 100644 index 9720061e2..000000000 --- a/game/server/hl2/rotorwash.cpp +++ /dev/null @@ -1,103 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "rotorwash.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// ============================================== -// Rotorwash entity -// ============================================== - -class CRotorWashEmitter : public CBaseEntity -{ -public: - DECLARE_CLASS( CRotorWashEmitter, CBaseEntity ); - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - void SetAltitude( float flAltitude ) { m_flAltitude = flAltitude; } - void SetEmit( bool state ) { m_bEmit = state; } - void Spawn ( void ); - void Precache( void ); - int ShouldTransmit( const CCheckTransmitInfo *pInfo ); - int UpdateTransmitState( void ); - -protected: - - CNetworkVar( bool, m_bEmit ); - CNetworkVar( float, m_flAltitude ); -}; - -IMPLEMENT_SERVERCLASS_ST( CRotorWashEmitter, DT_RotorWashEmitter ) - SendPropFloat(SENDINFO(m_flAltitude), -1, SPROP_NOSCALE ), -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( env_rotorwash_emitter, CRotorWashEmitter ); - -BEGIN_DATADESC( CRotorWashEmitter ) - DEFINE_FIELD( m_bEmit, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_flAltitude, FIELD_FLOAT, "altitude" ), -END_DATADESC() - -void CRotorWashEmitter::Spawn( void ) -{ - Precache(); - BaseClass::Spawn(); - SetEmit( false ); -} - -void CRotorWashEmitter::Precache( void ) -{ - PrecacheMaterial( "effects/splashwake3" ); -} - -int CRotorWashEmitter::ShouldTransmit( const CCheckTransmitInfo *pInfo ) -{ - if ( GetParent() ) - { - return GetParent()->ShouldTransmit( pInfo ); - } - - return FL_EDICT_PVSCHECK; -} - -int CRotorWashEmitter::UpdateTransmitState( void ) -{ - if ( GetParent() ) - { - return SetTransmitState( FL_EDICT_FULLCHECK ); - } - - return SetTransmitState( FL_EDICT_PVSCHECK ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &localOrigin - -// &localAngles - -// *pOwner - -// flAltitude - -// Output : CBaseEntity -//----------------------------------------------------------------------------- -CBaseEntity *CreateRotorWashEmitter( const Vector &localOrigin, const QAngle &localAngles, CBaseEntity *pOwner, float flAltitude ) -{ - CRotorWashEmitter *pEmitter = (CRotorWashEmitter *) CreateEntityByName( "env_rotorwash_emitter" ); - - if ( pEmitter == NULL ) - return NULL; - - pEmitter->SetAbsOrigin( localOrigin ); - pEmitter->SetAbsAngles( localAngles ); - pEmitter->FollowEntity( pOwner ); - - pEmitter->SetAltitude( flAltitude ); - pEmitter->SetEmit( false ); - - return pEmitter; -} diff --git a/game/server/hl2/rotorwash.h b/game/server/hl2/rotorwash.h deleted file mode 100644 index 5122bd683..000000000 --- a/game/server/hl2/rotorwash.h +++ /dev/null @@ -1,15 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ROTORWASH_H -#define ROTORWASH_H -#ifdef _WIN32 -#pragma once -#endif - -CBaseEntity *CreateRotorWashEmitter( const Vector &localOrigin, const QAngle &localAngles, CBaseEntity *pOwner, float flAltitude ); - -#endif // ROTORWASH_H diff --git a/game/server/hl2/script_intro.cpp b/game/server/hl2/script_intro.cpp deleted file mode 100644 index 5c7d27660..000000000 --- a/game/server/hl2/script_intro.cpp +++ /dev/null @@ -1,396 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#include "cbase.h" -#include "eventqueue.h" -#include "script_intro.h" -#include "point_camera.h" -#include "ai_utils.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// Used by server and client to calculate our FOV blend at any given frame -extern float ScriptInfo_CalculateFOV( float flFOVBlendStartTime, float flNextFOVBlendTime, int nFOV, int nNextFOV, bool bSplineRamp ); - -// Global point to the active intro script -CHandle g_hIntroScript; - -LINK_ENTITY_TO_CLASS(script_intro, CScriptIntro); - -BEGIN_DATADESC(CScriptIntro) - // Keys - DEFINE_FIELD( m_vecCameraView, FIELD_VECTOR ), - DEFINE_FIELD( m_vecCameraViewAngles, FIELD_VECTOR ), - DEFINE_FIELD( m_vecPlayerView, FIELD_VECTOR ), - DEFINE_FIELD( m_vecPlayerViewAngles, FIELD_VECTOR ), - DEFINE_FIELD( m_iBlendMode, FIELD_INTEGER ), - DEFINE_FIELD( m_iQueuedBlendMode, FIELD_INTEGER ), - DEFINE_FIELD( m_iQueuedNextBlendMode, FIELD_INTEGER ), - DEFINE_FIELD( m_iNextBlendMode, FIELD_INTEGER ), - DEFINE_FIELD( m_flNextBlendTime, FIELD_TIME ), - DEFINE_FIELD( m_flBlendStartTime, FIELD_TIME ), - DEFINE_FIELD( m_bActive, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iNextFOV, FIELD_INTEGER ), - DEFINE_FIELD( m_flNextFOVBlendTime, FIELD_TIME ), - DEFINE_FIELD( m_flFOVBlendStartTime, FIELD_TIME ), - DEFINE_FIELD( m_iFOV, FIELD_INTEGER ), - DEFINE_ARRAY( m_flFadeColor, FIELD_FLOAT, 3 ), - DEFINE_FIELD( m_flFadeAlpha, FIELD_FLOAT ), - DEFINE_FIELD( m_flFadeDuration, FIELD_FLOAT ), - DEFINE_FIELD( m_hCameraEntity, FIELD_EHANDLE ), - DEFINE_FIELD( m_iStartFOV, FIELD_INTEGER ), - - DEFINE_KEYFIELD( m_bAlternateFOV, FIELD_BOOLEAN, "alternatefovchange" ), - - // Inputs - DEFINE_INPUTFUNC(FIELD_STRING, "SetCameraViewEntity", InputSetCameraViewEntity ), - DEFINE_INPUTFUNC(FIELD_INTEGER, "SetBlendMode", InputSetBlendMode ), - DEFINE_INPUTFUNC(FIELD_INTEGER, "SetNextFOV", InputSetNextFOV ), - DEFINE_INPUTFUNC(FIELD_FLOAT, "SetFOVBlendTime", InputSetFOVBlendTime ), - DEFINE_INPUTFUNC(FIELD_INTEGER, "SetFOV", InputSetFOV ), - DEFINE_INPUTFUNC(FIELD_INTEGER, "SetNextBlendMode", InputSetNextBlendMode ), - DEFINE_INPUTFUNC(FIELD_FLOAT, "SetNextBlendTime", InputSetNextBlendTime ), - DEFINE_INPUTFUNC(FIELD_VOID, "Activate", InputActivate ), - DEFINE_INPUTFUNC(FIELD_VOID, "Deactivate", InputDeactivate ), - DEFINE_INPUTFUNC(FIELD_STRING, "FadeTo", InputFadeTo ), - DEFINE_INPUTFUNC(FIELD_STRING, "SetFadeColor", InputSetFadeColor ), - - DEFINE_THINKFUNC( BlendComplete ), - -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CScriptIntro, DT_ScriptIntro ) - SendPropVector(SENDINFO(m_vecCameraView), -1, SPROP_COORD), - SendPropVector(SENDINFO(m_vecCameraViewAngles), -1, SPROP_COORD), - SendPropInt( SENDINFO( m_iBlendMode ), 5 ), - SendPropInt( SENDINFO( m_iNextBlendMode ), 5 ), - SendPropFloat( SENDINFO( m_flNextBlendTime ), 10 ), - SendPropFloat( SENDINFO( m_flBlendStartTime ), 10 ), - SendPropBool( SENDINFO( m_bActive ) ), - - - // Fov & fov blends - SendPropInt( SENDINFO( m_iFOV ), 9 ), - SendPropInt( SENDINFO( m_iNextFOV ), 9 ), - SendPropInt( SENDINFO( m_iStartFOV ), 9 ), - SendPropFloat( SENDINFO( m_flNextFOVBlendTime ), 10 ), - SendPropFloat( SENDINFO( m_flFOVBlendStartTime ), 10 ), - - SendPropBool( SENDINFO( m_bAlternateFOV ) ), - - // Fades - SendPropFloat( SENDINFO( m_flFadeAlpha ), 10 ), - SendPropArray( - SendPropFloat( SENDINFO_ARRAY(m_flFadeColor), 32, SPROP_NOSCALE), - m_flFadeColor), - SendPropFloat( SENDINFO( m_flFadeDuration ), 10, SPROP_ROUNDDOWN, 0.0f, 255.0 ), - SendPropEHandle(SENDINFO( m_hCameraEntity ) ), -END_SEND_TABLE() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CScriptIntro::Spawn( void ) -{ - m_iNextBlendMode = -1; - m_iQueuedBlendMode = -1; - m_iQueuedNextBlendMode = -1; - AddSolidFlags( FSOLID_NOT_SOLID ); - SetSize( -Vector(5,5,5), Vector(5,5,5) ); - m_bActive = false; - m_iNextFOV = 0; - m_iFOV = 0; - m_iStartFOV = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CScriptIntro::Activate( void ) -{ - // Restore our script pointer, this is necessary to trigger other internal logic to due with PVS checks - if ( m_bActive ) - { - g_hIntroScript = this; - } - - BaseClass::Activate(); -} - -void CScriptIntro::Precache() -{ - PrecacheMaterial( "scripted/intro_screenspaceeffect" ); - BaseClass::Precache(); -} - -//------------------------------------------------------------------------------ -// Purpose : Send even though we don't have a model. -//------------------------------------------------------------------------------ -int CScriptIntro::UpdateTransmitState() -{ - return SetTransmitState( FL_EDICT_ALWAYS ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CScriptIntro::InputSetCameraViewEntity( inputdata_t &inputdata ) -{ - // Find the specified entity - string_t iszEntityName = inputdata.value.StringID(); - if ( iszEntityName == NULL_STRING ) - return; - - CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, iszEntityName, NULL, inputdata.pActivator, inputdata.pCaller ); - if ( !pEntity ) - { - Warning("script_intro %s couldn't find SetCameraViewEntity named %s\n", STRING(GetEntityName()), STRING(iszEntityName) ); - return; - } - - m_hCameraEntity = pEntity; - m_vecCameraView = pEntity->GetAbsOrigin(); - m_vecCameraViewAngles = pEntity->GetAbsAngles(); -} - -//----------------------------------------------------------------------------- -// Purpose: Fill out the origin that should be included in the player's PVS -//----------------------------------------------------------------------------- -bool CScriptIntro::GetIncludedPVSOrigin( Vector *pOrigin, CBaseEntity **ppCamera ) -{ - if ( m_bActive && m_hCameraEntity.Get() ) - { - *ppCamera = m_hCameraEntity.Get(); - *pOrigin = m_hCameraEntity.Get()->GetAbsOrigin(); - return true; - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Used for debugging -//----------------------------------------------------------------------------- -static ConVar cl_spewscriptintro( "cl_spewscriptintro", "0" ); - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CScriptIntro::InputSetBlendMode( inputdata_t &inputdata ) -{ - m_iBlendMode = m_iNextBlendMode = inputdata.value.Int(); - m_flBlendStartTime = m_flNextBlendTime = gpGlobals->curtime; - m_iQueuedBlendMode = -1; - SetContextThink( NULL, gpGlobals->curtime, "BlendComplete" ); - - if ( cl_spewscriptintro.GetInt() ) - { - DevMsg( 1, "%.2f INPUT: Blend mode set to %d\n", gpGlobals->curtime, m_iBlendMode ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CScriptIntro::InputSetNextBlendMode( inputdata_t &inputdata ) -{ - m_iQueuedNextBlendMode = inputdata.value.Int(); - - if ( cl_spewscriptintro.GetInt() ) - { - DevMsg( 1, "%.2f INPUT: Next Blend mode set to %d\n", gpGlobals->curtime, m_iQueuedNextBlendMode ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CScriptIntro::InputSetNextFOV( inputdata_t &inputdata ) -{ - m_iNextFOV = inputdata.value.Int(); -} - -//------------------------------------------------------------------------ -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CScriptIntro::InputSetFOVBlendTime( inputdata_t &inputdata ) -{ - // Cache our FOV starting point before we update our data here - if ( m_flNextFOVBlendTime >= gpGlobals->curtime ) - { - // We're already in a blend, so capture where we are at this point in time - m_iStartFOV = ScriptInfo_CalculateFOV( m_flFOVBlendStartTime, m_flNextFOVBlendTime, m_iStartFOV, m_iNextFOV, m_bAlternateFOV ); - } - else - { - // If we weren't blending, then we need to construct a proper starting point from scratch - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( pPlayer ) - { - m_iStartFOV = ( m_iFOV ) ? m_iFOV : pPlayer->GetFOV(); - } - else - { - m_iStartFOV = m_iFOV; - } - } - - m_flNextFOVBlendTime = gpGlobals->curtime + inputdata.value.Float(); - m_flFOVBlendStartTime = gpGlobals->curtime; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CScriptIntro::InputSetFOV( inputdata_t &inputdata ) -{ - m_iFOV = inputdata.value.Int(); - m_iStartFOV = m_iFOV; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CScriptIntro::InputSetNextBlendTime( inputdata_t &inputdata ) -{ - m_flNextBlendTime = gpGlobals->curtime + inputdata.value.Float(); - m_flBlendStartTime = gpGlobals->curtime; - - // This logic is used to support continued calls to SetNextBlendMode - // without intervening calls to SetBlendMode - if ( m_iQueuedBlendMode >= 0 ) - { - m_iBlendMode = m_iQueuedBlendMode; - } - - if ( m_iQueuedNextBlendMode < 0 ) - { - Warning( "script_intro: Warning!! Set blend time without setting next blend mode!\n" ); - m_iQueuedNextBlendMode = m_iBlendMode; - } - - m_iNextBlendMode = m_iQueuedNextBlendMode; - m_iQueuedNextBlendMode = -1; - m_iQueuedBlendMode = m_iNextBlendMode; - - if ( cl_spewscriptintro.GetInt() ) - { - DevMsg( 1, "%.2f BLEND STARTED: %d to %d, end at %.2f\n", gpGlobals->curtime, m_iBlendMode, m_iNextBlendMode, m_flNextBlendTime.Get() ); - } - - SetContextThink( &CScriptIntro::BlendComplete, m_flNextBlendTime, "BlendComplete" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CScriptIntro::BlendComplete( ) -{ - m_iBlendMode = m_iNextBlendMode; - m_flBlendStartTime = m_flNextBlendTime = gpGlobals->curtime; - m_iQueuedBlendMode = -1; - SetContextThink( NULL, gpGlobals->curtime, "BlendComplete" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CScriptIntro::InputActivate( inputdata_t &inputdata ) -{ - m_bActive = true; - g_hIntroScript = this; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CScriptIntro::InputDeactivate( inputdata_t &inputdata ) -{ - m_bActive = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CScriptIntro::InputFadeTo( inputdata_t &inputdata ) -{ - char parseString[255]; - Q_strncpy(parseString, inputdata.value.String(), sizeof(parseString)); - - // Get the fade alpha - char *pszParam = strtok(parseString," "); - if ( !pszParam || !pszParam[0] ) - { - Warning("%s (%s) received FadeTo input without an alpha. Syntax: \n", GetClassname(), GetDebugName() ); - return; - } - float flAlpha = atof( pszParam ); - - // Get the fade duration - pszParam = strtok(NULL," "); - if ( !pszParam || !pszParam[0] ) - { - Warning("%s (%s) received FadeTo input without a duration. Syntax: \n", GetClassname(), GetDebugName() ); - return; - } - - // Set the two variables - m_flFadeAlpha = flAlpha; - m_flFadeDuration = atof( pszParam ); - - //Msg("%.2f INPUT FADE: Fade to %.2f. End at %.2f\n", gpGlobals->curtime, m_flFadeAlpha.Get(), gpGlobals->curtime + m_flFadeDuration.Get() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CScriptIntro::InputSetFadeColor( inputdata_t &inputdata ) -{ - char parseString[255]; - Q_strncpy(parseString, inputdata.value.String(), sizeof(parseString)); - - // Get the fade colors - char *pszParam = strtok(parseString," "); - if ( !pszParam || !pszParam[0] ) - { - Warning("%s (%s) received SetFadeColor input without correct parameters. Syntax: >\n", GetClassname(), GetDebugName() ); - return; - } - float flR = atof( pszParam ); - - pszParam = strtok(NULL," "); - if ( !pszParam || !pszParam[0] ) - { - Warning("%s (%s) received SetFadeColor input without correct parameters. Syntax: >\n", GetClassname(), GetDebugName() ); - return; - } - float flG = atof( pszParam ); - - pszParam = strtok(NULL," "); - if ( !pszParam || !pszParam[0] ) - { - Warning("%s (%s) received SetFadeColor input without correct parameters. Syntax: >\n", GetClassname(), GetDebugName() ); - return; - } - float flB = atof( pszParam ); - - // Use the colors - m_flFadeColor.Set( 0, flR ); - m_flFadeColor.Set( 1, flG ); - m_flFadeColor.Set( 2, flB ); -} diff --git a/game/server/hl2/script_intro.h b/game/server/hl2/script_intro.h deleted file mode 100644 index d25ef1343..000000000 --- a/game/server/hl2/script_intro.h +++ /dev/null @@ -1,85 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef SCRIPT_INTRO_H -#define SCRIPT_INTRO_H -#ifdef _WIN32 -#pragma once -#endif - - -class CPointCamera; - - -//----------------------------------------------------------------------------- -// Purpose: An entity that's used to control the intro sequence -//----------------------------------------------------------------------------- -class CScriptIntro : public CBaseEntity -{ - DECLARE_CLASS(CScriptIntro, CBaseEntity); -public: - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - virtual void Spawn( void ); - virtual void Precache(); - virtual void Activate( void ); - virtual int UpdateTransmitState(void); - - // Inputs - void InputSetPlayerViewEntity( inputdata_t &inputdata ); - void InputSetCameraViewEntity( inputdata_t &inputdata ); - void InputSetBlendMode( inputdata_t &inputdata ); - void InputSetNextBlendMode( inputdata_t &inputdata ); - void InputSetNextFOV( inputdata_t &inputdata ); - void InputSetFOVBlendTime( inputdata_t &inputdata ); - void InputSetFOV( inputdata_t &inputdata ); - void InputSetNextBlendTime( inputdata_t &inputdata ); - void InputActivate( inputdata_t &inputdata ); - void InputDeactivate( inputdata_t &inputdata ); - - void InputFadeTo( inputdata_t &inputdata ); - void InputSetFadeColor( inputdata_t &inputdata ); - - bool GetIncludedPVSOrigin( Vector *pOrigin, CBaseEntity **ppCamera ); - -private: - // Think func used to finish the blend off - void BlendComplete( ); - -private: - CNetworkVar( Vector, m_vecPlayerView ); - CNetworkVar( QAngle, m_vecPlayerViewAngles ); - CNetworkVar( Vector, m_vecCameraView ); - CNetworkVar( QAngle, m_vecCameraViewAngles ); - CNetworkVar( int, m_iBlendMode ); - CNetworkVar( int, m_iNextBlendMode ); - CNetworkVar( float, m_flNextBlendTime ); - CNetworkVar( float, m_flBlendStartTime ); - CNetworkVar( int, m_iStartFOV ); - CNetworkVar( bool, m_bActive ); - - // Fov & fov blends - CNetworkVar( int, m_iNextFOV ); - CNetworkVar( float, m_flNextFOVBlendTime ); - CNetworkVar( float, m_flFOVBlendStartTime ); - CNetworkVar( int, m_iFOV ); - CNetworkVar( bool, m_bAlternateFOV ); - - // Fades - CNetworkArray( float, m_flFadeColor, 3 ); - CNetworkVar( float, m_flFadeAlpha); - CNetworkVar( float, m_flFadeDuration ); - - CNetworkVar( EHANDLE, m_hCameraEntity ); - - int m_iQueuedBlendMode; - int m_iQueuedNextBlendMode; -}; - -extern CHandle g_hIntroScript; - -#endif // SCRIPT_INTRO_H diff --git a/game/server/hl2/te_gaussexplosion.cpp b/game/server/hl2/te_gaussexplosion.cpp deleted file mode 100644 index aae9868c3..000000000 --- a/game/server/hl2/te_gaussexplosion.cpp +++ /dev/null @@ -1,67 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "te_particlesystem.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//============================================================================= -// Gauss explosion -//============================================================================= - -class CTEGaussExplosion : public CTEParticleSystem -{ -public: - DECLARE_CLASS( CTEGaussExplosion, CTEParticleSystem ); - DECLARE_SERVERCLASS(); - - CTEGaussExplosion( const char *name ); - virtual ~CTEGaussExplosion( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ) { }; - - CNetworkVar( int, m_nType ); - CNetworkVector( m_vecDirection ); -}; - - -CTEGaussExplosion::CTEGaussExplosion( const char *name ) : BaseClass( name ) -{ - m_nType = 0; - m_vecDirection.Init(); -} - -CTEGaussExplosion::~CTEGaussExplosion( void ) -{ -} - -IMPLEMENT_SERVERCLASS_ST( CTEGaussExplosion, DT_TEGaussExplosion ) - SendPropInt( SENDINFO(m_nType), 2, SPROP_UNSIGNED ), - SendPropVector( SENDINFO(m_vecDirection), -1, SPROP_COORD ), -END_SEND_TABLE() - -static CTEGaussExplosion g_TEGaussExplosion( "GaussExplosion" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &pos - -// &angles - -//----------------------------------------------------------------------------- -void TE_GaussExplosion( IRecipientFilter& filter, float delay, - const Vector &pos, const Vector &dir, int type ) -{ - g_TEGaussExplosion.m_vecOrigin = pos; - g_TEGaussExplosion.m_vecDirection = dir; - g_TEGaussExplosion.m_nType = type; - - //Send it - g_TEGaussExplosion.Create( filter, delay ); -} - - - diff --git a/game/server/hl2/trigger_super_armor.cpp b/game/server/hl2/trigger_super_armor.cpp deleted file mode 100644 index a14b44ebc..000000000 --- a/game/server/hl2/trigger_super_armor.cpp +++ /dev/null @@ -1,179 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Spawn and use functions for editor-placed triggers. -// -//=============================================================================// - -#include "cbase.h" -#include "triggers.h" -#include "soundenvelope.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar sk_max_super_armor( "sk_max_super_armor","500"); - -#define MAX_SUPER_ARMOR sk_max_super_armor.GetInt() - - -//----------------------------------------------------------------------------- -// Trigger that bestows super armor -//----------------------------------------------------------------------------- -class CTriggerSuperArmor : public CTriggerMultiple -{ - DECLARE_CLASS( CTriggerSuperArmor, CTriggerMultiple ); - DECLARE_DATADESC(); - -public: - - virtual void StartTouch( CBaseEntity *pOther ); - virtual void EndTouch( CBaseEntity *pOther ); - -private: - - virtual void Precache(); - virtual void Spawn( void ); - void StartLoopingSounds( CBaseEntity *pEntity ); - void StopLoopingSounds(); - void RechargeThink(); - - CSoundPatch *m_pChargingSound; - float m_flLoopingSoundTime; -}; - - -LINK_ENTITY_TO_CLASS( trigger_super_armor, CTriggerSuperArmor ); - -BEGIN_DATADESC( CTriggerSuperArmor ) - - DEFINE_SOUNDPATCH( m_pChargingSound ), - DEFINE_FIELD( m_flLoopingSoundTime, FIELD_TIME ), - - DEFINE_THINKFUNC( RechargeThink ), - -END_DATADESC() - - -static const char *s_pRechargeThinkContext = "RechargeThink"; - - -void CTriggerSuperArmor::Precache() -{ - BaseClass::Precache(); - - PrecacheScriptSound( "TriggerSuperArmor.StartCharging" ); - PrecacheScriptSound( "TriggerSuperArmor.DoneCharging" ); - - PrecacheScriptSound( "TriggerSuperArmor.Charging" ); -} - -//----------------------------------------------------------------------------- -// No retrigger -//----------------------------------------------------------------------------- -void CTriggerSuperArmor::Spawn( void ) -{ - Precache(); - - BaseClass::Spawn(); -} - - -//----------------------------------------------------------------------------- -// Starts looping sounds -//----------------------------------------------------------------------------- -void CTriggerSuperArmor::StartLoopingSounds( CBaseEntity *pEntity ) -{ - if ( m_pChargingSound ) - return; - - CReliableBroadcastRecipientFilter filter; - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - m_pChargingSound = controller.SoundCreate( filter, pEntity->entindex(), "TriggerSuperArmor.Charging" ); -} - - -//----------------------------------------------------------------------------- -// Stops looping sounds -//----------------------------------------------------------------------------- -void CTriggerSuperArmor::StopLoopingSounds() -{ - if ( m_pChargingSound ) - { - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - controller.SoundDestroy( m_pChargingSound ); - m_pChargingSound = NULL; - } - - BaseClass::StopLoopingSounds(); -} - - -//----------------------------------------------------------------------------- -// Begins super-powering the entities -//----------------------------------------------------------------------------- -void CTriggerSuperArmor::StartTouch( CBaseEntity *pOther ) -{ - BaseClass::StartTouch( pOther ); - - if ( !pOther->IsPlayer() ) - return; - - if ( m_hTouchingEntities.Count() == 1 ) - { - SetContextThink( &CTriggerSuperArmor::RechargeThink, gpGlobals->curtime + 0.01f, s_pRechargeThinkContext ); - pOther->EmitSound( "TriggerSuperArmor.StartCharging" ); - m_flLoopingSoundTime = 0.56f + gpGlobals->curtime; - } -} - - -//----------------------------------------------------------------------------- -// Ends super-powerings the entities -//----------------------------------------------------------------------------- -void CTriggerSuperArmor::EndTouch( CBaseEntity *pOther ) -{ - BaseClass::EndTouch( pOther ); - - if ( !pOther->IsPlayer() ) - return; - - if ( m_hTouchingEntities.Count() == 0 ) - { - StopLoopingSounds(); - SetContextThink( NULL, gpGlobals->curtime + 0.01f, s_pRechargeThinkContext ); - } -} - - -//----------------------------------------------------------------------------- -// Super-powers the entities -//----------------------------------------------------------------------------- -void CTriggerSuperArmor::RechargeThink() -{ - Assert( m_hTouchingEntities.Count() == 1 ); - for ( int i = m_hTouchingEntities.Count(); --i >= 0; ) - { - CBasePlayer *pPlayer = assert_cast( m_hTouchingEntities[i].Get() ); - - if (( pPlayer->ArmorValue() < MAX_SUPER_ARMOR ) || ( pPlayer->GetHealth() < 100 )) - { - pPlayer->TakeHealth( 5, DMG_GENERIC ); - pPlayer->IncrementArmorValue( 15, MAX_SUPER_ARMOR ); - - if ( pPlayer->ArmorValue() >= MAX_SUPER_ARMOR ) - { - pPlayer->EmitSound( "TriggerSuperArmor.DoneCharging" ); - StopLoopingSounds(); - } - else - { - if ( m_flLoopingSoundTime < gpGlobals->curtime ) - { - StartLoopingSounds( m_hTouchingEntities[i] ); - } - } - } - } - - SetContextThink( &CTriggerSuperArmor::RechargeThink, gpGlobals->curtime + 0.1f, s_pRechargeThinkContext ); -} diff --git a/game/server/hl2/vehicle_airboat.cpp b/game/server/hl2/vehicle_airboat.cpp deleted file mode 100644 index de2fba65c..000000000 --- a/game/server/hl2/vehicle_airboat.cpp +++ /dev/null @@ -1,2095 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "vehicle_base.h" -#include "engine/IEngineSound.h" -#include "in_buttons.h" -#include "ammodef.h" -#include "IEffects.h" -#include "beam_shared.h" -#include "weapon_gauss.h" -#include "soundenvelope.h" -#include "decals.h" -#include "soundent.h" -#include "te_effect_dispatch.h" -#include "physics_saverestore.h" -#include "movevars_shared.h" -#include "npc_attackchopper.h" -#include "weapon_rpg.h" -#include "vphysics/constraints.h" -#include "world.h" -#include "rumble_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern ConVar sv_vehicle_autoaim_scale; - -#define VEHICLE_HITBOX_DRIVER 1 - -// -// Body groups. -// -#define AIRBOAT_BODYGROUP_GUN 1 -#define AIRBOAT_BODYGROUP_PROP 2 -#define AIRBOAT_BODYGROUP_BLUR 3 - -#define AIRBOAT_LOCK_SPEED 10 // Airboat must be going slower than this for player to enter or exit, in in/sec - -#define AIRBOAT_DELTA_LENGTH_MAX 12.0f // 1 foot -#define AIRBOAT_FRAMETIME_MIN 1e-6 - -#define AIRBOAT_SPLASH_RIPPLE 0 -#define AIRBOAT_SPLASH_SPRAY 1 -#define AIRBOAT_SPLASH_RIPPLE_SIZE 20.0f - -// -// Pose parameters. -// -#define AIRBOAT_GUN_YAW "vehicle_weapon_yaw" -#define AIRBOAT_GUN_PITCH "vehicle_weapon_pitch" -#define AIRBOAT_FRAME_FLEX_LEFT "Frame_Flex_L" -#define AIRBOAT_FRAME_FLEX_RIGHT "Frame_Flex_R" - -#define CANNON_MAX_UP_PITCH 60.0f -#define CANNON_MAX_DOWN_PITCH 30.0f -#define CANNON_MAX_RIGHT_YAW 165.0f -#define CANNON_MAX_LEFT_YAW 75.0f - -#define CANNON_HEAVY_SHOT_INTERVAL 0.2f -#define CANNON_SHAKE_INTERVAL 1.0f - -static ConVar sk_airboat_max_ammo("sk_airboat_max_ammo", "100" ); -static ConVar sk_airboat_recharge_rate("sk_airboat_recharge_rate", "15" ); -static ConVar sk_airboat_drain_rate("sk_airboat_drain_rate", "10" ); -static ConVar hud_airboathint_numentries( "hud_airboathint_numentries", "10", FCVAR_NONE ); -static ConVar airboat_fatal_stress( "airboat_fatal_stress", "5000", FCVAR_NONE, "Amount of stress in kg that would kill the airboat driver." ); - -extern ConVar autoaim_max_dist; - -class CPropAirboat : public CPropVehicleDriveable -{ - DECLARE_CLASS( CPropAirboat, CPropVehicleDriveable ); - -public: - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - // CPropVehicle - virtual void ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ); - virtual void DriveVehicle( float flFrameTime, CUserCmd *ucmd, int iButtonsDown, int iButtonsReleased ); - void DampenEyePosition( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles ); - bool ShouldThink() { return true; } - - // CBaseEntity - void Think(void); - void Precache( void ); - void Spawn( void ); - virtual void OnRestore(); - virtual void Activate(); - virtual void UpdateOnRemove(); - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() | FCAP_USE_IN_RADIUS; }; - virtual void DoMuzzleFlash( void ); - virtual void StopLoopingSounds(); - - // position to shoot at - virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy ); - virtual Vector GetSmoothedVelocity( void ); - - virtual void EnterVehicle( CBaseCombatCharacter *pPlayer ); - - virtual bool AllowBlockedExit( CBaseCombatCharacter *pPlayer, int nRole ) { return false; } - virtual void PreExitVehicle( CBaseCombatCharacter *pPlayer, int nRole ); - virtual void ExitVehicle( int nRole ); - - void ComputePDControllerCoefficients( float *pCoefficientsOut, float flFrequency, float flDampening, float flDeltaTime ); - void DampenForwardMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime ); - void DampenUpMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime ); - - virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - - void VPhysicsUpdate( IPhysicsObject *pPhysics ); - - // Scraping noises for the various things we drive on. - virtual void VPhysicsFriction( IPhysicsObject *pObject, float energy, int surfaceProps, int surfacePropsHit ); - - bool HeadlightIsOn( void ) { return m_bHeadlightIsOn; } - void HeadlightTurnOn( void ); - void HeadlightTurnOff( void ); - - virtual bool ShouldDrawWaterImpacts( void ); - - bool ShouldForceExit() { return m_bForcedExit; } - void ClearForcedExit() { m_bForcedExit = false; } - - // Input handlers. - void InputWake( inputdata_t &inputdata ); - void InputExitVehicle( inputdata_t &inputdata ); - void InputEnableGun( inputdata_t &inputdata ); - void InputStartRotorWashForces( inputdata_t &inputdata ); - void InputStopRotorWashForces( inputdata_t &inputdata ); - - // Allows the shooter to change the impact effect of his bullets - virtual void DoImpactEffect( trace_t &tr, int nDamageType ); - - // Airboat passengers do not directly receive damage from blasts or radiation damage - virtual bool PassengerShouldReceiveDamage( CTakeDamageInfo &info ) - { - if ( info.GetDamageType() & DMG_VEHICLE ) - return true; - - return (info.GetDamageType() & (DMG_RADIATION|DMG_BLAST|DMG_CRUSH) ) == 0; - } - - const char *GetTracerType( void ); - -private: - - void CreateAntiFlipConstraint(); - - void ApplyStressDamage( IPhysicsObject *pPhysics ); - float CalculatePhysicsStressDamage( vphysics_objectstress_t *pStressOut, IPhysicsObject *pPhysics ); - - void CreateDangerSounds( void ); - - void FireGun( ); - - void UpdateSplashEffects( void ); - void CreateSplash( int nSplashType ); - - // Purpose: Aim Gun at a target - void AimGunAt( const Vector &endPos, float flInterval ); - - // Purpose: Returns the direction the gun is currently aiming at - void GetGunAimDirection( Vector *resultDir ); - - // Recharges the ammo based on speed - void RechargeAmmo(); - - // Removes the ammo... - void RemoveAmmo( float flAmmoAmount ); - - // Purpose: - void ComputeAimPoint( Vector *pVecAimPoint ); - - // Do the right thing for the gun - void UpdateGunState( CUserCmd *ucmd ); - - // Sound management - void CreateSounds(); - void UpdateSound(); - void UpdateWeaponSound(); - void UpdateEngineSound( CSoundEnvelopeController &controller, float speedRatio ); - void UpdateFanSound( CSoundEnvelopeController &controller, float speedRatio ); - void UpdateWaterSound( CSoundEnvelopeController &controller, float speedRatio ); - - void UpdatePropeller(); - void UpdateGauge(); - - void CreatePlayerBlocker(); - void DestroyPlayerBlocker(); - void EnablePlayerBlocker( bool bEnable ); - -private: - - enum - { - GUN_STATE_IDLE = 0, - GUN_STATE_FIRING, - }; - - Vector m_vecLastEyePos; - Vector m_vecLastEyeTarget; - Vector m_vecEyeSpeed; - - //float m_flHandbrakeTime; // handbrake after the fact to keep vehicles from rolling - //bool m_bInitialHandbrake; - - bool m_bForcedExit; - - int m_nGunRefAttachment; - int m_nGunBarrelAttachment; - float m_aimYaw; - float m_aimPitch; - float m_flChargeRemainder; - float m_flDrainRemainder; - int m_nGunState; - float m_flNextHeavyShotTime; - float m_flNextGunShakeTime; - - CNetworkVar( int, m_nAmmoCount ); - CNetworkVar( bool, m_bHeadlightIsOn ); - EHANDLE m_hAvoidSphere; - - int m_nSplashAttachment; - - float m_flPrevThrottle; // Throttle during last think. Used for detecting state changes. - float m_flSpinRate; // Current rate of spin of propeller: 0 = min, 1.0 = max - float m_flTargetSpinRate; // Target rate of spin of propeller: 0 = min, 1.0 = max - float m_flPropTime; // Time to turn on/off the prop. - float m_flBlurTime; // Time to turn on/off the blur. - - CSoundPatch *m_pFanSound; - CSoundPatch *m_pFanMaxSpeedSound; - CSoundPatch *m_pEngineSound; - CSoundPatch *m_pWaterFastSound; - CSoundPatch *m_pWaterStoppedSound; - CSoundPatch *m_pGunFiringSound; - - float m_flEngineIdleTime; // Time to start playing the engine's idle sound. - float m_flEngineDuckTime; // Time to reduce the volume of the engine's idle sound. - - bool m_bFadeOutFan; // Fade out fan sound after cruising at max speed for a while. - - int m_nPrevWaterLevel; // Used for detecting transitions into/out of water. - float m_flWaterStoppedPitchTime; // Time to pitch shift the water stopped sound. - - float m_flLastImpactEffectTime; - int m_iNumberOfEntries; - - IPhysicsConstraint *m_pAntiFlipConstraint; // A ragdoll constraint that prevents us from flipping. - - CHandle m_hPlayerBlocker; - - CNetworkVar( Vector, m_vecPhysVelocity ); - - CNetworkVar( int, m_nExactWaterLevel ); - - IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_nWaterLevel ); - -}; - -IMPLEMENT_SERVERCLASS_ST( CPropAirboat, DT_PropAirboat ) - SendPropBool( SENDINFO( m_bHeadlightIsOn ) ), - SendPropInt( SENDINFO( m_nAmmoCount ), 9 ), - SendPropInt( SENDINFO( m_nExactWaterLevel ) ), - SendPropInt( SENDINFO( m_nWaterLevel ) ), - SendPropVector( SENDINFO( m_vecPhysVelocity ) ), -END_SEND_TABLE(); - -LINK_ENTITY_TO_CLASS( prop_vehicle_airboat, CPropAirboat ); - -BEGIN_DATADESC( CPropAirboat ) - DEFINE_FIELD( m_vecLastEyePos, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecLastEyeTarget, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecEyeSpeed, FIELD_VECTOR ), - -// DEFINE_FIELD( m_flHandbrakeTime, FIELD_TIME ), -// DEFINE_FIELD( m_bInitialHandbrake,FIELD_BOOLEAN ), -// DEFINE_FIELD( m_nGunRefAttachment, FIELD_INTEGER ), -// DEFINE_FIELD( m_nGunBarrelAttachment, FIELD_INTEGER ), - DEFINE_FIELD( m_aimYaw, FIELD_FLOAT ), - DEFINE_FIELD( m_aimPitch, FIELD_FLOAT ), - DEFINE_FIELD( m_flChargeRemainder, FIELD_FLOAT ), - DEFINE_FIELD( m_flDrainRemainder, FIELD_FLOAT ), - DEFINE_FIELD( m_nGunState, FIELD_INTEGER ), - DEFINE_FIELD( m_flNextHeavyShotTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextGunShakeTime, FIELD_TIME ), - DEFINE_FIELD( m_nAmmoCount, FIELD_INTEGER ), - DEFINE_FIELD( m_bHeadlightIsOn, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hAvoidSphere, FIELD_EHANDLE ), -// DEFINE_FIELD( m_nSplashAttachment, FIELD_INTEGER ), - DEFINE_FIELD( m_hPlayerBlocker, FIELD_EHANDLE ), - - DEFINE_FIELD( m_vecPhysVelocity, FIELD_VECTOR ), - DEFINE_FIELD( m_nExactWaterLevel, FIELD_INTEGER ), - - DEFINE_FIELD( m_flPrevThrottle, FIELD_FLOAT ), - DEFINE_FIELD( m_flSpinRate, FIELD_FLOAT ), - DEFINE_FIELD( m_flTargetSpinRate, FIELD_FLOAT ), - DEFINE_FIELD( m_flPropTime, FIELD_TIME ), - DEFINE_FIELD( m_flBlurTime, FIELD_TIME ), - DEFINE_FIELD( m_bForcedExit, FIELD_BOOLEAN ), - - DEFINE_SOUNDPATCH( m_pFanSound ), - DEFINE_SOUNDPATCH( m_pFanMaxSpeedSound ), - DEFINE_SOUNDPATCH( m_pEngineSound ), - DEFINE_SOUNDPATCH( m_pWaterFastSound ), - DEFINE_SOUNDPATCH( m_pWaterStoppedSound ), - DEFINE_SOUNDPATCH( m_pGunFiringSound ), - - DEFINE_PHYSPTR( m_pAntiFlipConstraint ), - - DEFINE_FIELD( m_flEngineIdleTime, FIELD_TIME ), - DEFINE_FIELD( m_flEngineDuckTime, FIELD_TIME ), - DEFINE_FIELD( m_bFadeOutFan, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_nPrevWaterLevel, FIELD_INTEGER ), - DEFINE_FIELD( m_flWaterStoppedPitchTime, FIELD_TIME ), - - DEFINE_FIELD( m_flLastImpactEffectTime, FIELD_TIME ), - DEFINE_FIELD( m_iNumberOfEntries, FIELD_INTEGER ), - - DEFINE_INPUTFUNC( FIELD_BOOLEAN, "EnableGun", InputEnableGun ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartRotorWashForces", InputStartRotorWashForces ), - DEFINE_INPUTFUNC( FIELD_VOID, "StopRotorWashForces", InputStopRotorWashForces ), - DEFINE_INPUTFUNC( FIELD_VOID, "ExitVehicle", InputExitVehicle ), - DEFINE_INPUTFUNC( FIELD_VOID, "Wake", InputWake ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAirboat::Precache( void ) -{ - BaseClass::Precache(); - - PrecacheScriptSound( "Airboat_engine_stop" ); - PrecacheScriptSound( "Airboat_engine_start" ); - - PrecacheScriptSound( "Airboat.FireGunHeavy" ); - PrecacheScriptSound( "Airboat.FireGunRevDown"); - - PrecacheScriptSound( "Airboat_engine_idle" ); - PrecacheScriptSound( "Airboat_engine_fullthrottle" ); - PrecacheScriptSound( "Airboat_fan_idle" ); - PrecacheScriptSound( "Airboat_fan_fullthrottle" ); - PrecacheScriptSound( "Airboat_water_stopped" ); - PrecacheScriptSound( "Airboat_water_fast" ); - PrecacheScriptSound( "Airboat_impact_splash" ); - PrecacheScriptSound( "Airboat_impact_hard" ); - - PrecacheScriptSound( "Airboat_headlight_on" ); - PrecacheScriptSound( "Airboat_headlight_off" ); - - PrecacheScriptSound( "Airboat.FireGunLoop" ); - - PrecacheMaterial( "effects/splashwake1" ); - PrecacheMaterial( "effects/splashwake4" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAirboat::Spawn( void ) -{ - m_nAmmoCount = m_bHasGun ? 0 : -1; - m_hAvoidSphere = CreateHelicopterAvoidanceSphere( this, 0, 50.0f, false ); - m_flLastImpactEffectTime = -1; - m_iNumberOfEntries = 0; - - // Setup vehicle as a ray-cast airboat. - SetVehicleType( VEHICLE_TYPE_AIRBOAT_RAYCAST ); - SetCollisionGroup( COLLISION_GROUP_VEHICLE ); - BaseClass::Spawn(); - - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetAnimatedEveryTick( true ); - - // Handbrake data. - //m_flHandbrakeTime = gpGlobals->curtime + 0.1; - //m_bInitialHandbrake = false; - m_VehiclePhysics.SetHasBrakePedal( false ); - - m_flMinimumSpeedToEnterExit = AIRBOAT_LOCK_SPEED; - - m_takedamage = DAMAGE_EVENTS_ONLY; - - SetBodygroup(AIRBOAT_BODYGROUP_GUN, m_bHasGun); - SetBodygroup(AIRBOAT_BODYGROUP_PROP, true); - - SetPoseParameter( AIRBOAT_GUN_YAW, 0 ); - SetPoseParameter( AIRBOAT_GUN_PITCH, 0 ); - SetPoseParameter( AIRBOAT_FRAME_FLEX_LEFT, 0 ); - SetPoseParameter( AIRBOAT_FRAME_FLEX_RIGHT, 0 ); - - m_aimYaw = 0; - m_aimPitch = 0; - m_bUnableToFire = true; - m_nGunState = GUN_STATE_IDLE; - - SetPoseParameter( "Steer_Shock", 0.0f ); - - // Get the physics object so we can adjust the buoyancy. - IPhysicsObject *pPhysAirboat = VPhysicsGetObject(); - if ( pPhysAirboat ) - { - pPhysAirboat->SetBuoyancyRatio( 0.0f ); - PhysSetGameFlags( pPhysAirboat, FVPHYSICS_HEAVY_OBJECT ); - } - - //CreateAntiFlipConstraint(); -} - -//----------------------------------------------------------------------------- -// Purpose: Create a ragdoll constraint that prevents us from flipping. -//----------------------------------------------------------------------------- -void CPropAirboat::CreateAntiFlipConstraint() -{ - constraint_ragdollparams_t ragdoll; - ragdoll.Defaults(); - - // Don't prevent the boat from moving, just flipping. - ragdoll.onlyAngularLimits = true; - - // Put the ragdoll constraint in the space of the airboat. - SetIdentityMatrix( ragdoll.constraintToAttached ); - BuildObjectRelativeXform( g_PhysWorldObject, VPhysicsGetObject(), ragdoll.constraintToReference ); - - ragdoll.axes[0].minRotation = -100; - ragdoll.axes[0].maxRotation = 100; - ragdoll.axes[1].minRotation = -100; - ragdoll.axes[1].maxRotation = 100; - ragdoll.axes[2].minRotation = -180; - ragdoll.axes[2].maxRotation = 180; - - m_pAntiFlipConstraint = physenv->CreateRagdollConstraint( g_PhysWorldObject, VPhysicsGetObject(), NULL, ragdoll ); - - //NDebugOverlay::Cross3DOriented( ragdoll.constraintToReference, 128, 255, true, 100 ); -} - - -//----------------------------------------------------------------------------- -// Attachment indices -//----------------------------------------------------------------------------- -void CPropAirboat::UpdateOnRemove() -{ - BaseClass::UpdateOnRemove(); - - if ( m_hAvoidSphere ) - { - UTIL_Remove( m_hAvoidSphere ); - m_hAvoidSphere = NULL; - } -} - - -//----------------------------------------------------------------------------- -// Attachment indices -//----------------------------------------------------------------------------- -void CPropAirboat::Activate() -{ - BaseClass::Activate(); - - m_nGunRefAttachment = LookupAttachment( "gun" ); - m_nGunBarrelAttachment = LookupAttachment( "muzzle" ); - m_nSplashAttachment = LookupAttachment( "splash_pt" ); - - CreateSounds(); - - CBaseServerVehicle *pServerVehicle = dynamic_cast(GetServerVehicle()); - if ( pServerVehicle ) - { - if( pServerVehicle->GetPassenger() ) - { - // If a boat comes back from a save game with a driver, make sure the engine rumble starts up. - pServerVehicle->StartEngineRumble(); - } - } - - //CreatePlayerBlocker(); - //EnablePlayerBlocker( true ); -} - - -void CPropAirboat::CreatePlayerBlocker() -{ - Assert( m_hPlayerBlocker == NULL ); - DestroyPlayerBlocker(); - - m_hPlayerBlocker = CEntityBlocker::Create( GetAbsOrigin(), Vector( -84, -32, 0 ), Vector( 54, 32, 84 ), this, false ); - if ( m_hPlayerBlocker != NULL ) - { - m_hPlayerBlocker->SetParent( this ); - m_hPlayerBlocker->SetLocalOrigin( vec3_origin ); - m_hPlayerBlocker->SetLocalAngles( vec3_angle ); - m_hPlayerBlocker->SetCollisionGroup( COLLISION_GROUP_PLAYER ); - m_hPlayerBlocker->AddSolidFlags( FSOLID_NOT_SOLID ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAirboat::DestroyPlayerBlocker() -{ - if ( m_hPlayerBlocker != NULL ) - { - UTIL_Remove( m_hPlayerBlocker ); - } - - m_hPlayerBlocker = NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : bEnable - -//----------------------------------------------------------------------------- -void CPropAirboat::EnablePlayerBlocker( bool bEnable ) -{ - if ( m_hPlayerBlocker != NULL ) - { - if ( bEnable ) - { - m_hPlayerBlocker->RemoveSolidFlags( FSOLID_NOT_SOLID ); - } - else - { - m_hPlayerBlocker->AddSolidFlags( FSOLID_NOT_SOLID ); - } - } -} - - -//----------------------------------------------------------------------------- -// Update the weapon sounds -//----------------------------------------------------------------------------- -#define MIN_CHARGE_SOUND 0.4f -#define MIN_PITCH_CHANGE ( MIN_CHARGE_SOUND + ( ( 1.0f - MIN_CHARGE_SOUND ) / 3.0f ) ) -#define VOLUME_CHANGE_TIME 0.5f - -void CPropAirboat::UpdateWeaponSound() -{ - if ( HasGun() ) - { - CSoundEnvelopeController *pController = &CSoundEnvelopeController::GetController(); - float flVolume = pController->SoundGetVolume( m_pGunFiringSound ); - if ( (m_nGunState == GUN_STATE_IDLE) || (m_nAmmoCount == 0) ) - { - if ( flVolume != 0.0f ) - { - pController->SoundChangeVolume( m_pGunFiringSound, 0.0f, 0.01f ); - } - } - else - { - if ( flVolume != 1.0f ) - { - pController->SoundChangeVolume( m_pGunFiringSound, 1.0f, 0.01f ); - } - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Force the player to exit the vehicle. -//----------------------------------------------------------------------------- -void CPropAirboat::InputExitVehicle( inputdata_t &inputdata ) -{ - m_bForcedExit = true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Force the airboat to wake up. This was needed to fix a last-minute -// bug for the XBox -- the airboat didn't fall with the platform -// in d1_canals_10b. -//----------------------------------------------------------------------------- -void CPropAirboat::InputWake( inputdata_t &inputdata ) -{ - VPhysicsGetObject()->Wake(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler to enable or disable the airboat's mounted gun. -//----------------------------------------------------------------------------- -void CPropAirboat::InputEnableGun( inputdata_t &inputdata ) -{ - m_bHasGun = inputdata.value.Bool(); - SetBodygroup(AIRBOAT_BODYGROUP_GUN, m_bHasGun); - - // When enabling the gun, give full ammo - if ( m_bHasGun ) - { - m_nAmmoCount = sk_airboat_max_ammo.GetInt(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler to enable or disable the airboat's mounted gun. -//----------------------------------------------------------------------------- -void CPropAirboat::InputStartRotorWashForces( inputdata_t &inputdata ) -{ - RemoveEFlags( EFL_NO_ROTORWASH_PUSH ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler to enable or disable the airboat's mounted gun. -//----------------------------------------------------------------------------- -void CPropAirboat::InputStopRotorWashForces( inputdata_t &inputdata ) -{ - AddEFlags( EFL_NO_ROTORWASH_PUSH ); -} - - -//----------------------------------------------------------------------------- -// Creating vphysics -//----------------------------------------------------------------------------- -void CPropAirboat::OnRestore() -{ - BaseClass::OnRestore(); - - IPhysicsObject *pPhysAirboat = VPhysicsGetObject(); - if ( pPhysAirboat ) - { - pPhysAirboat->SetBuoyancyRatio( 0.0f ); - PhysSetGameFlags( pPhysAirboat, FVPHYSICS_HEAVY_OBJECT ); - } - - // If the player's in the vehicle, NPCs should ignore it - if ( GetDriver() ) - { - SetNavIgnore(); - } -} - - -//----------------------------------------------------------------------------- -// Used for navigation -//----------------------------------------------------------------------------- -void CPropAirboat::EnterVehicle( CBaseCombatCharacter *pPlayer ) -{ - BaseClass::EnterVehicle( pPlayer ); - - //EnablePlayerBlocker( false ); - - // NPCs like manhacks should try to hit us - SetNavIgnore(); - - // Play the engine start sound. - float flDuration; - EmitSound( "Airboat_engine_start", 0.0, &flDuration ); - m_VehiclePhysics.TurnOn(); - - // Start playing the engine's idle sound as the startup sound finishes. - m_flEngineIdleTime = gpGlobals->curtime + flDuration - 0.1; -} - - -//----------------------------------------------------------------------------- -// Purpose: Called when exiting, just before playing the exit animation. -//----------------------------------------------------------------------------- -void CPropAirboat::PreExitVehicle( CBaseCombatCharacter *pPlayer, int nRole ) -{ - if ( HeadlightIsOn() ) - { - HeadlightTurnOff(); - } - - // Stop shooting. - m_nGunState = GUN_STATE_IDLE; - - CBaseEntity *pDriver = GetDriver(); - CBasePlayer *pPlayerDriver; - if( pDriver && pDriver->IsPlayer() ) - { - pPlayerDriver = dynamic_cast(pDriver); - if( pPlayerDriver ) - { - pPlayerDriver->RumbleEffect( RUMBLE_AIRBOAT_GUN, 0, RUMBLE_FLAG_STOP ); - } - } - - BaseClass::PreExitVehicle( pPlayer, nRole ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Called when exiting, after completing the exit animation. -// Input : iRole - -//----------------------------------------------------------------------------- -void CPropAirboat::ExitVehicle( int nRole ) -{ - CBaseEntity *pDriver = GetDriver(); - - //EnablePlayerBlocker( true ); - - BaseClass::ExitVehicle( nRole ); - - if (!pDriver) - return; - -#if 0 - // On ORANGE BOX this is causing a big blank box to show up, which is worse - // than the HUD hint persisting for a little while, so don't do it. (sjb) - // clear the hint - UTIL_HudHintText( pDriver, "" ); -#endif - - // NPCs like manhacks should try to avoid us again - ClearNavIgnore(); - - // Play the engine shutoff sound. - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_BODY; - ep.m_pSoundName = "Airboat_engine_stop"; - ep.m_flVolume = controller.SoundGetVolume( m_pEngineSound ); - ep.m_SoundLevel = SNDLVL_NORM; - ep.m_nPitch = (int)controller.SoundGetPitch( m_pEngineSound ); - - EmitSound( filter, entindex(), ep ); - m_VehiclePhysics.TurnOff(); - - // Shut off the airboat sounds. - controller.SoundChangeVolume( m_pEngineSound, 0.0, 0.0 ); - controller.SoundChangeVolume( m_pFanSound, 0.0, 0.0 ); - controller.SoundChangeVolume( m_pFanMaxSpeedSound, 0.0, 0.0 ); - controller.SoundChangeVolume( m_pWaterStoppedSound, 0.0, 0.0 ); - controller.SoundChangeVolume( m_pWaterFastSound, 0.0, 0.0 ); - controller.SoundChangeVolume( m_pGunFiringSound, 0.0, 0.0 ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAirboat::HeadlightTurnOn( void ) -{ - EmitSound( "Airboat_headlight_on" ); - m_bHeadlightIsOn = true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAirboat::HeadlightTurnOff( void ) -{ - EmitSound( "Airboat_headlight_off" ); - m_bHeadlightIsOn = false; -} - - -//----------------------------------------------------------------------------- -// position to shoot at -//----------------------------------------------------------------------------- -Vector CPropAirboat::BodyTarget( const Vector &posSrc, bool bNoisy ) -{ - Vector vecPosition; - QAngle angles; - if ( GetServerVehicle()->GetPassenger() ) - { - // FIXME: Reconcile this with other functions that store a cached version of the results here? - GetServerVehicle()->GetVehicleViewPosition( VEHICLE_ROLE_DRIVER, &vecPosition, &angles ); - } - else - { - vecPosition = WorldSpaceCenter(); - } - return vecPosition; -} - - -//----------------------------------------------------------------------------- -// Smoothed velocity -//----------------------------------------------------------------------------- -#define SMOOTHED_MIN_VELOCITY 75.0f -#define SMOOTHED_MAX_VELOCITY 150.0f - -Vector CPropAirboat::GetSmoothedVelocity( void ) -{ - // If we're going too slow, return the forward direction as the velocity - // for NPC prediction purposes - Vector vecSmoothedVelocity = BaseClass::GetSmoothedVelocity(); - float flSpeed = vecSmoothedVelocity.Length(); - if ( flSpeed >= SMOOTHED_MAX_VELOCITY ) - return vecSmoothedVelocity; - - Vector vecForward; - GetVectors( &vecForward, NULL, NULL ); - vecForward *= MAX( flSpeed, 1.0f ); - if ( flSpeed <= SMOOTHED_MIN_VELOCITY ) - return vecForward; - - float flBlend = SimpleSplineRemapVal( flSpeed, SMOOTHED_MIN_VELOCITY, SMOOTHED_MAX_VELOCITY, 0.0f, 1.0f ); - VectorLerp( vecForward, vecSmoothedVelocity, flBlend, vecSmoothedVelocity ); - return vecSmoothedVelocity; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAirboat::TraceAttack( const CTakeDamageInfo &inputInfo, const Vector &vecDir, trace_t *ptr ) -{ - CTakeDamageInfo info = inputInfo; - if ( ptr->hitbox != VEHICLE_HITBOX_DRIVER ) - { - if ( inputInfo.GetDamageType() & DMG_BULLET ) - { - info.ScaleDamage( 0.0001 ); - } - } - - BaseClass::TraceAttack( info, vecDir, ptr ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -// &vecEnd - -// *pTraceFilter - -// *pVecTracerDest - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CPropAirboat::ShouldDrawWaterImpacts( void ) -{ - // The airboat spits out so much crap that we need to do cheaper versions - // of the impact effects. Also, we need to do less of them. - if ( m_flLastImpactEffectTime >= gpGlobals->curtime ) - return false; - - m_flLastImpactEffectTime = gpGlobals->curtime + 0.05f; - - return true; -} - -//----------------------------------------------------------------------------- -// Allows the shooter to change the impact effect of his bullets -//----------------------------------------------------------------------------- -void CPropAirboat::DoImpactEffect( trace_t &tr, int nDamageType ) -{ - // The airboat spits out so much crap that we need to do cheaper versions - // of the impact effects. Also, we need to do less of them. - if ( m_flLastImpactEffectTime == gpGlobals->curtime ) - return; - - // Randomly drop out - if ( random->RandomInt( 0, 5 ) ) - return; - - m_flLastImpactEffectTime = gpGlobals->curtime; - UTIL_ImpactTrace( &tr, nDamageType, "AirboatGunImpact" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CPropAirboat::OnTakeDamage( const CTakeDamageInfo &info ) -{ - // Do scaled up physics damage to the airboat - CTakeDamageInfo physDmg = info; - physDmg.ScaleDamage( 5 ); - if ( physDmg.GetDamageType() & DMG_BLAST ) - { - physDmg.SetDamageForce( info.GetDamageForce() * 10 ); - } - VPhysicsTakeDamage( physDmg ); - - // Check to do damage to driver - if ( m_hPlayer != NULL ) - { - // Don't pass along physics damage - if ( info.GetDamageType() & (DMG_CRUSH|DMG_RADIATION) ) - return 0; - - // Take the damage (strip out the DMG_BLAST) - CTakeDamageInfo playerDmg = info; - - // Mark that we're passing it to the player so the base player accepts the damage - playerDmg.SetDamageType( info.GetDamageType() | DMG_VEHICLE ); - - // Deal the damage to the passenger - m_hPlayer->TakeDamage( playerDmg ); - } - - return 0; -} - - -//----------------------------------------------------------------------------- -// Scraping noises for the various things we drive on. -//----------------------------------------------------------------------------- -void CPropAirboat::VPhysicsFriction( IPhysicsObject *pObject, float energy, int surfaceProps, int surfacePropsHit ) -{ - // don't make noise for hidden/invisible/sky materials - const surfacedata_t *phit = physprops->GetSurfaceData( surfacePropsHit ); - const surfacedata_t *pprops = physprops->GetSurfaceData( surfaceProps ); - if ( phit->game.material == 'X' || pprops->game.material == 'X' ) - return; - - // FIXME: Make different scraping sounds here - float flVolume = 0.3f; - - surfacedata_t *psurf = physprops->GetSurfaceData( surfaceProps ); - const char *pSoundName = physprops->GetString( psurf->sounds.scrapeRough ); - - PhysFrictionSound( this, pObject, pSoundName, psurf->soundhandles.scrapeRough, flVolume ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Aim Gun at a target position. -//----------------------------------------------------------------------------- -// This fixes an optimizer bug that was causing targetYaw and targetPitch to -// always be reported as clamped, thus disabling the gun. Ack! -#ifdef _MSC_VER -#pragma optimize("", off) -#endif -void CPropAirboat::AimGunAt( const Vector &aimPos, float flInterval ) -{ - matrix3x4_t gunMatrix; - GetAttachment( m_nGunRefAttachment, gunMatrix ); - - // transform the target position into gun space - Vector localTargetPosition; - VectorITransform( aimPos, gunMatrix, localTargetPosition ); - VectorNormalize( localTargetPosition ); - m_bUnableToFire = false; - m_vecGunCrosshair = aimPos; - - // do a look at in gun space (essentially a delta-lookat) - QAngle localTargetAngles; - VectorAngles( localTargetPosition, localTargetAngles ); - - // convert to +/- 180 degrees - localTargetAngles.x = UTIL_AngleDiff( localTargetAngles.x, 0 ); - localTargetAngles.y = UTIL_AngleDiff( localTargetAngles.y, 0 ); - - float targetYaw = m_aimYaw + localTargetAngles.y; - float targetPitch = m_aimPitch + localTargetAngles.x; - - // Constrain our angles - float newTargetYaw = clamp( targetYaw, -CANNON_MAX_RIGHT_YAW, CANNON_MAX_LEFT_YAW ); - float newTargetPitch = clamp( targetPitch, -CANNON_MAX_UP_PITCH, CANNON_MAX_DOWN_PITCH ); - - // If the angles have been clamped, we're looking outside of our valid range - if ( ( newTargetYaw != targetYaw ) || ( newTargetPitch != targetPitch ) ) - { - m_bUnableToFire = true; - } - - targetYaw = newTargetYaw; - targetPitch = newTargetPitch; - - m_aimYaw = targetYaw; - m_aimPitch = targetPitch; - - SetPoseParameter( AIRBOAT_GUN_YAW, m_aimYaw); - SetPoseParameter( AIRBOAT_GUN_PITCH, m_aimPitch ); - - InvalidateBoneCache(); - - // read back to avoid drift when hitting limits - // as long as the velocity is less than the delta between the limit and 180, this is fine. - m_aimPitch = GetPoseParameter( AIRBOAT_GUN_PITCH ); - m_aimYaw = GetPoseParameter( AIRBOAT_GUN_YAW ); -} -#ifdef _MSC_VER -#pragma optimize("", on) -#endif - -//----------------------------------------------------------------------------- -// Removes the ammo... -//----------------------------------------------------------------------------- -void CPropAirboat::RemoveAmmo( float flAmmoAmount ) -{ - m_flDrainRemainder += flAmmoAmount; - int nAmmoToRemove = (int)m_flDrainRemainder; - m_flDrainRemainder -= nAmmoToRemove; - m_nAmmoCount -= nAmmoToRemove; - if ( m_nAmmoCount < 0 ) - { - m_nAmmoCount = 0; - m_flDrainRemainder = 0.0f; - } -} - - -//----------------------------------------------------------------------------- -// Recharges the ammo... -//----------------------------------------------------------------------------- -void CPropAirboat::RechargeAmmo(void) -{ - if ( !m_bHasGun ) - { - m_nAmmoCount = -1; - return; - } - - int nMaxAmmo = sk_airboat_max_ammo.GetInt(); - if ( m_nAmmoCount == nMaxAmmo ) - return; - - float flRechargeRate = sk_airboat_recharge_rate.GetInt(); - float flChargeAmount = flRechargeRate * gpGlobals->frametime; - if ( m_flDrainRemainder != 0.0f ) - { - if ( m_flDrainRemainder >= flChargeAmount ) - { - m_flDrainRemainder -= flChargeAmount; - return; - } - else - { - flChargeAmount -= m_flDrainRemainder; - m_flDrainRemainder = 0.0f; - } - } - - m_flChargeRemainder += flChargeAmount; - int nAmmoToAdd = (int)m_flChargeRemainder; - m_flChargeRemainder -= nAmmoToAdd; - m_nAmmoCount += nAmmoToAdd; - if ( m_nAmmoCount > nMaxAmmo ) - { - m_nAmmoCount = nMaxAmmo; - m_flChargeRemainder = 0.0f; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAirboat::ComputeAimPoint( Vector *pVecAimPoint ) -{ - Vector vecEyeDirection; - - if( g_pGameRules->GetAutoAimMode() == AUTOAIM_ON_CONSOLE ) - { - // Use autoaim as the eye dir. - autoaim_params_t params; - - params.m_fScale = AUTOAIM_SCALE_DEFAULT * sv_vehicle_autoaim_scale.GetFloat(); - params.m_fMaxDist = autoaim_max_dist.GetFloat(); - m_hPlayer->GetAutoaimVector( params ); - - vecEyeDirection = params.m_vecAutoAimDir; - } - else - { - m_hPlayer->EyeVectors( &vecEyeDirection, NULL, NULL ); - } - - Vector vecEndPos; - VectorMA( m_hPlayer->EyePosition(), MAX_TRACE_LENGTH, vecEyeDirection, vecEndPos ); - trace_t trace; - UTIL_TraceLine( m_hPlayer->EyePosition(), vecEndPos, MASK_SHOT, this, COLLISION_GROUP_NONE, &trace ); - *pVecAimPoint = trace.endpos; -} - - -//----------------------------------------------------------------------------- -// Purpose: Manages animation and sound state. -//----------------------------------------------------------------------------- -void CPropAirboat::Think(void) -{ - BaseClass::Think(); - - // set handbrake after physics sim settles down -// if ( gpGlobals->curtime < m_flHandbrakeTime ) -// { -// SetNextThink( gpGlobals->curtime ); -// } -// else if ( !m_bInitialHandbrake ) // after initial timer expires, set the handbrake -// { -// m_bInitialHandbrake = true; -// m_VehiclePhysics.SetHandbrake( true ); -// m_VehiclePhysics.Think(); -// } - - // Find the vertical extents of the boat - Vector startPos, endPos; - CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 1.0f ), &startPos ); - CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 0.0f ), &endPos ); - - // Look for water along that volume. - // Make a very vertically thin box and sweep it along the ray. - Vector vecMins = CollisionProp()->OBBMins(); - Vector vecMaxs = CollisionProp()->OBBMaxs(); - vecMins.z = -0.1f; - vecMaxs.z = 0.1f; - - trace_t tr; - UTIL_TraceHull( startPos, endPos, vecMins, vecMaxs, (CONTENTS_WATER|CONTENTS_SLIME), this, COLLISION_GROUP_NONE, &tr ); - - // If we hit something, then save off the info - if ( tr.fraction != 1.0f ) - { - m_nExactWaterLevel = tr.endpos.z; - - // Classify what we're in - if ( tr.contents & CONTENTS_SLIME ) - { - // We fake this value to mean type, instead of level - SetWaterLevel( 2 ); - } - else - { - // This simply signifies water - SetWaterLevel( 1 ); - } - } - else - { - // Not in water - SetWaterLevel( 0 ); - } - - StudioFrameAdvance(); - - // If the enter or exit animation has finished, tell the server vehicle - if ( IsSequenceFinished() && ( m_bEnterAnimOn || m_bExitAnimOn ) ) - { - // The first few time we get into the jeep, print the jeep help - if ( m_iNumberOfEntries < hud_airboathint_numentries.GetInt() && !m_bExitAnimOn ) - { - UTIL_HudHintText( m_hPlayer, "#Valve_Hint_BoatKeys" ); - m_iNumberOfEntries++; - } - - GetServerVehicle()->HandleEntryExitFinish( m_bExitAnimOn, false ); - - // Start the vehicle's idle animation - ResetSequence(LookupSequence("propeller_spin1")); - ResetClientsideFrame(); - } - - // FIXME: Slam the crosshair every think -- if we don't do this it disappears randomly, never to return. - if ( ( m_hPlayer.Get() != NULL ) && !( m_bEnterAnimOn || m_bExitAnimOn ) ) - { - m_hPlayer->m_Local.m_iHideHUD &= ~HIDEHUD_VEHICLE_CROSSHAIR; - } - - // Aim the gun - if ( HasGun() && m_hPlayer.Get() && !m_bEnterAnimOn && !m_bExitAnimOn ) - { - Vector vecAimPoint; - ComputeAimPoint( &vecAimPoint ); - AimGunAt( vecAimPoint, gpGlobals->frametime ); - } - - if ( ShouldForceExit() ) - { - ClearForcedExit(); - m_hPlayer->LeaveVehicle(); - } - - if ( HasGun() && ( m_nGunState == GUN_STATE_IDLE ) ) - { - RechargeAmmo(); - } - - UpdateSound(); - UpdatePropeller(); - UpdateGauge(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAirboat::UpdatePropeller() -{ - if ((m_bExitAnimOn) || (m_bEnterAnimOn)) - return; - - #define SPIN_RATE_MED 0.2 - #define SPIN_RATE_HIGH 0.6 - - // Determine target spin rate from throttle. - float flTargetSpinRate = m_flThrottle; - if ((flTargetSpinRate == 0) && (m_hPlayer)) - { - // Always keep the fan moving a little when we have a driver. - flTargetSpinRate = 0.2; - } - - // Save the current spin rate to determine state transitions. - float flPrevSpinRate = m_flSpinRate; - - // Determine new spin rate, - if (m_flSpinRate < flTargetSpinRate) - { - if (flTargetSpinRate > 0) - { - m_flSpinRate += gpGlobals->frametime * 1.0; - } - else - { - m_flSpinRate += gpGlobals->frametime * 0.4; - } - - if (m_flSpinRate > flTargetSpinRate) - { - m_flSpinRate = flTargetSpinRate; - } - } - else if (m_flSpinRate > flTargetSpinRate) - { - m_flSpinRate -= gpGlobals->frametime * 0.4; - if (m_flSpinRate < flTargetSpinRate) - { - m_flSpinRate = flTargetSpinRate; - } - } - - // Update prop & blur based on new spin rate. - if (fabs(m_flSpinRate) > SPIN_RATE_HIGH) - { - if (fabs(flPrevSpinRate) <= SPIN_RATE_HIGH) - { - SetBodygroup(AIRBOAT_BODYGROUP_PROP, false); - SetBodygroup(AIRBOAT_BODYGROUP_BLUR, true); - SetSequence(LookupSequence("propeller_spin1")); - } - } - else if (fabs(m_flSpinRate) > SPIN_RATE_MED) - { - if ((fabs(flPrevSpinRate) <= SPIN_RATE_MED) || (fabs(flPrevSpinRate) > SPIN_RATE_HIGH)) - { - SetBodygroup(AIRBOAT_BODYGROUP_PROP, true); - SetBodygroup(AIRBOAT_BODYGROUP_BLUR, true); - SetSequence(LookupSequence("propeller_spin1")); - } - } - else - { - if (fabs(flPrevSpinRate) > SPIN_RATE_MED) - { - SetBodygroup(AIRBOAT_BODYGROUP_PROP, true); - SetBodygroup(AIRBOAT_BODYGROUP_BLUR, false); - SetSequence(LookupSequence("propeller_spin1")); - } - } - - SetPlaybackRate( m_flSpinRate ); - - m_flPrevThrottle = m_flThrottle; -} - - -//----------------------------------------------------------------------------- -// Purpose: Updates the speedometer. -//----------------------------------------------------------------------------- -void CPropAirboat::UpdateGauge() -{ - CFourWheelVehiclePhysics *pPhysics = GetPhysics(); - int speed = pPhysics->GetSpeed(); - int maxSpeed = pPhysics->GetMaxSpeed(); - float speedRatio = clamp( (float)speed / (float)maxSpeed, 0, 1 ); - - SetPoseParameter( "Gauge", speedRatio ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAirboat::CreateSounds() -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - - CPASAttenuationFilter filter( this ); - - if (!m_pEngineSound) - { - m_pEngineSound = controller.SoundCreate( filter, entindex(), "Airboat_engine_idle" ); - controller.Play( m_pEngineSound, 0, 100 ); - } - - if (!m_pFanSound) - { - m_pFanSound = controller.SoundCreate( filter, entindex(), "Airboat_fan_idle" ); - controller.Play( m_pFanSound, 0, 100 ); - } - - if (!m_pFanMaxSpeedSound) - { - m_pFanMaxSpeedSound = controller.SoundCreate( filter, entindex(), "Airboat_fan_fullthrottle" ); - controller.Play( m_pFanMaxSpeedSound, 0, 100 ); - } - - if (!m_pWaterStoppedSound) - { - m_pWaterStoppedSound = controller.SoundCreate( filter, entindex(), "Airboat_water_stopped" ); - controller.Play( m_pWaterStoppedSound, 0, 100 ); - } - - if (!m_pWaterFastSound) - { - m_pWaterFastSound = controller.SoundCreate( filter, entindex(), "Airboat_water_fast" ); - controller.Play( m_pWaterFastSound, 0, 100 ); - } - - if (!m_pGunFiringSound) - { - m_pGunFiringSound = controller.SoundCreate( filter, entindex(), "Airboat.FireGunLoop" ); - controller.Play( m_pGunFiringSound, 0, 100 ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAirboat::StopLoopingSounds() -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - - controller.SoundDestroy( m_pEngineSound ); - m_pEngineSound = NULL; - - controller.SoundDestroy( m_pFanSound ); - m_pFanSound = NULL; - - controller.SoundDestroy( m_pFanMaxSpeedSound ); - m_pFanMaxSpeedSound = NULL; - - controller.SoundDestroy( m_pWaterStoppedSound ); - m_pWaterStoppedSound = NULL; - - controller.SoundDestroy( m_pWaterFastSound ); - m_pWaterFastSound = NULL; - - controller.SoundDestroy( m_pGunFiringSound ); - m_pGunFiringSound = NULL; - - BaseClass::StopLoopingSounds(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Manage the state of the engine sound. -//----------------------------------------------------------------------------- -void CPropAirboat::UpdateEngineSound( CSoundEnvelopeController &controller, float speedRatio ) -{ - #define ENGINE_MIN_VOLUME 0.22 - #define ENGINE_MAX_VOLUME 0.62 - #define ENGINE_MIN_PITCH 80 - #define ENGINE_MAX_PITCH 140 - #define ENGINE_DUCK_TIME 4.0 - - if ( controller.SoundGetVolume(m_pEngineSound ) == 0 ) - { - if ( gpGlobals->curtime > m_flEngineIdleTime ) - { - // If we've finished playing the engine start sound, start playing the idle sound. - controller.Play( m_pEngineSound, ENGINE_MAX_VOLUME, 100 ); - - // Ramp down the engine idle sound over time so that we can ramp it back up again based on speed. - controller.SoundChangeVolume( m_pEngineSound, ENGINE_MIN_VOLUME, ENGINE_DUCK_TIME ); - controller.SoundChangePitch( m_pEngineSound, ENGINE_MIN_PITCH, ENGINE_DUCK_TIME ); - - // Reduce the volume of the engine idle sound after our ears get 'used' to it. - m_flEngineDuckTime = gpGlobals->curtime + ENGINE_DUCK_TIME; - } - } - else if ( gpGlobals->curtime > m_flEngineDuckTime ) - { - controller.SoundChangeVolume( m_pEngineSound, RemapValClamped(speedRatio, 0, 1.0, ENGINE_MIN_VOLUME, ENGINE_MAX_VOLUME ), 0.0 ); - controller.SoundChangePitch( m_pEngineSound, RemapValClamped( speedRatio, 0, 1.0, ENGINE_MIN_PITCH, ENGINE_MAX_PITCH ), 0 ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAirboat::UpdateFanSound( CSoundEnvelopeController &controller, float speedRatio ) -{ - #define FAN_MIN_VOLUME 0.0 - #define FAN_MAX_VOLUME 0.82 - #define FAN_DUCK_VOLUME 0.22 - #define FAN_CHANGE_VOLUME_TIME 1.0 // seconds over which to change the volume - #define FAN_DUCK_TIME 2.0 // seconds over which to duck the fan sound - - // Manage the state of the fan sound. - if (speedRatio >= 0.8) - { - // Crossfade between a 'max speed' fan sound and the normal fan sound. - controller.SoundChangeVolume( m_pFanSound, RemapValClamped( speedRatio, 0.8, 1.0, FAN_MAX_VOLUME, FAN_MIN_VOLUME ), FAN_CHANGE_VOLUME_TIME ); - controller.SoundChangeVolume( m_pFanMaxSpeedSound, RemapValClamped( speedRatio, 0.8, 1.0, FAN_MIN_VOLUME, FAN_MAX_VOLUME ), FAN_CHANGE_VOLUME_TIME ); - - if (!m_bFadeOutFan) - { - m_bFadeOutFan = true; - controller.SoundChangeVolume( m_pFanSound, FAN_DUCK_VOLUME, FAN_DUCK_TIME ); - } - } - else - { - m_bFadeOutFan = false; - controller.SoundChangeVolume( m_pFanSound, RemapValClamped( fabs(m_flThrottle), 0, 1.0, FAN_MIN_VOLUME, FAN_MAX_VOLUME ), 0.25 ); - controller.SoundChangeVolume( m_pFanMaxSpeedSound, 0.0, 0.0 ); - } - - controller.SoundChangePitch( m_pFanSound, 100 * (fabs(m_flThrottle) + 0.2), 0.25 ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAirboat::UpdateWaterSound( CSoundEnvelopeController &controller, float speedRatio ) -{ - int nWaterLevel = GetWaterLevel(); - - // Manage the state of the water stopped sound (gentle lapping at the pontoons). - if ( nWaterLevel == 0 ) - { - controller.SoundChangeVolume(m_pWaterStoppedSound, 0.0, 0.0); - } - else - { - if ( m_nPrevWaterLevel == 0 ) - { - Vector vecVelocityWorld; - GetVelocity( &vecVelocityWorld, NULL ); - - if ( ( fabs( vecVelocityWorld.x ) > 400 ) || ( fabs( vecVelocityWorld.y ) > 400 ) || ( fabs( vecVelocityWorld.z ) > 400 ) ) - { - // Landed in the water. Play a splash sound. - EmitSound( "Airboat_impact_splash" ); - - if ( fabs( vecVelocityWorld.z ) > 200 ) - { - // Landed hard in the water. Play a smack sound. - EmitSound( "Airboat_impact_hard" ); - } - } - } - - if (speedRatio <= 0.1) - { - if (!controller.SoundGetVolume(m_pWaterStoppedSound)) - { - // Fade in the water stopped sound over 2 seconds. - controller.SoundChangeVolume(m_pWaterStoppedSound, 1.0, 2.0); - m_flWaterStoppedPitchTime = gpGlobals->curtime + random->RandomFloat(1.0, 3.0); - } - else if (gpGlobals->curtime > m_flWaterStoppedPitchTime) - { - controller.SoundChangeVolume(m_pWaterStoppedSound, random->RandomFloat(0.2, 1.0), random->RandomFloat(1.0, 3.0)); - controller.SoundChangePitch(m_pWaterStoppedSound, random->RandomFloat(90, 110), random->RandomFloat(1.0, 3.0)); - m_flWaterStoppedPitchTime = gpGlobals->curtime + random->RandomFloat(2.0, 4.0); - } - } - else - { - if (controller.SoundGetVolume(m_pWaterStoppedSound)) - { - // Fade out the water stopped sound over 1 second. - controller.SoundChangeVolume(m_pWaterStoppedSound, 0.0, 1.0); - } - } - } - - // Manage the state of the water fast sound (water hissing under the pontoons). - if ( nWaterLevel == 0 ) - { - controller.SoundChangeVolume(m_pWaterFastSound, 0.0, 0.0); - } - else - { - controller.SoundChangeVolume( m_pWaterFastSound, speedRatio, 0.0 ); - } - - m_nPrevWaterLevel = nWaterLevel; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAirboat::UpdateSound() -{ - if (!GetDriver()) - return; - - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - - // Sample the data that we need for sounds. - CFourWheelVehiclePhysics *pPhysics = GetPhysics(); - int speed = pPhysics->GetSpeed(); - int maxSpeed = pPhysics->GetMaxSpeed(); - float speedRatio = clamp((float)speed / (float)maxSpeed, 0, 1); - - //Msg("speedRatio=%f\n", speedRatio); - - UpdateWeaponSound(); - UpdateEngineSound( controller, speedRatio ); - UpdateFanSound( controller, speedRatio ); - UpdateWaterSound( controller, speedRatio ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAirboat::UpdateSplashEffects( void ) -{ - // Splash effects. - CreateSplash( AIRBOAT_SPLASH_RIPPLE ); -// CreateSplash( AIRBOAT_SPLASH_SPRAY ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const char *CPropAirboat::GetTracerType( void ) -{ - if ( gpGlobals->curtime >= m_flNextHeavyShotTime ) - return "AirboatGunHeavyTracer"; - - return "AirboatGunTracer"; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAirboat::DoMuzzleFlash( void ) -{ - CEffectData data; - data.m_nEntIndex = entindex(); - data.m_nAttachmentIndex = m_nGunBarrelAttachment; - data.m_flScale = 1.0f; - DispatchEffect( "AirboatMuzzleFlash", data ); - - BaseClass::DoMuzzleFlash(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -#define GUN_WINDUP_TIME 1.5f - -void CPropAirboat::FireGun( ) -{ - // Get the gun position. - Vector vecGunPosition; - Vector vecForward; - GetAttachment( m_nGunBarrelAttachment, vecGunPosition, &vecForward ); - - // NOTE: For the airboat, unable to fire really means the aim is clamped - Vector vecAimPoint; - if ( !m_bUnableToFire ) - { - // Trace from eyes and see what we hit. - ComputeAimPoint( &vecAimPoint ); - } - else - { - // We hit the clamp; just fire whichever way the gun is facing - VectorMA( vecGunPosition, 1000.0f, vecForward, vecAimPoint ); - } - - // Get a ray from the gun to the target. - Vector vecRay = vecAimPoint - vecGunPosition; - VectorNormalize( vecRay ); - - /* - // Get the aiming direction - Vector vecRay; - AngleVectors( vecGunAngles, &vecRay ); - VectorNormalize( vecRay ); - */ - - CAmmoDef *pAmmoDef = GetAmmoDef(); - int ammoType = pAmmoDef->Index( "AirboatGun" ); - - FireBulletsInfo_t info; - info.m_vecSrc = vecGunPosition; - info.m_vecDirShooting = vecRay; - info.m_flDistance = 4096; - info.m_iAmmoType = ammoType; - info.m_nFlags = FIRE_BULLETS_TEMPORARY_DANGER_SOUND; - - if ( gpGlobals->curtime >= m_flNextHeavyShotTime ) - { - info.m_iShots = 1; - info.m_vecSpread = VECTOR_CONE_PRECALCULATED; - info.m_flDamageForceScale = 1000.0f; - } - else - { - info.m_iShots = 2; - info.m_vecSpread = VECTOR_CONE_5DEGREES; - } - - FireBullets( info ); - - CBaseEntity *pDriver = GetDriver(); - CBasePlayer *pPlayerDriver; - if( pDriver && pDriver->IsPlayer() ) - { - pPlayerDriver = dynamic_cast(pDriver); - if( pPlayerDriver ) - { - pPlayerDriver->RumbleEffect( RUMBLE_AIRBOAT_GUN, 0, RUMBLE_FLAG_LOOP|RUMBLE_FLAG_ONLYONE ); - } - } - - DoMuzzleFlash(); - - // NOTE: This must occur after FireBullets - if ( gpGlobals->curtime >= m_flNextHeavyShotTime ) - { - m_flNextHeavyShotTime = gpGlobals->curtime + CANNON_HEAVY_SHOT_INTERVAL; - } - - if ( gpGlobals->curtime >= m_flNextGunShakeTime ) - { - UTIL_ScreenShakeObject( this, WorldSpaceCenter(), 0.2, 250.0, CANNON_SHAKE_INTERVAL, 250, SHAKE_START ); - m_flNextGunShakeTime = gpGlobals->curtime + 0.5 * CANNON_SHAKE_INTERVAL; - } - - // Specifically kill APC missiles in the cone. But we're going to totally cheat - // because it's hard to hit them when they are close. - // Use the player's eye position as the center of the cone. - if ( !m_hPlayer ) - return; - - Vector vecEyeDirection, vecEyePosition; - if ( !m_bUnableToFire ) - { - if ( IsX360() ) - { - GetAttachment( m_nGunBarrelAttachment, vecEyePosition, &vecEyeDirection ); - } - else - { - vecEyePosition = m_hPlayer->EyePosition(); - m_hPlayer->EyeVectors( &vecEyeDirection, NULL, NULL ); - } - } - else - { - vecEyePosition = vecGunPosition; - vecEyeDirection = vecRay; - } - - CAPCMissile *pEnt = FindAPCMissileInCone( vecEyePosition, vecEyeDirection, 2.5f ); - if ( pEnt && (pEnt->GetHealth() > 0) ) - { - CTakeDamageInfo info( this, this, 1, DMG_AIRBOAT ); - CalculateBulletDamageForce( &info, ammoType, vecRay, pEnt->WorldSpaceCenter() ); - pEnt->TakeDamage( info ); - - Vector vecVelocity = pEnt->GetAbsVelocity(); - - // Pick a vector perpendicular to the vecRay which will push it away from the airboat - Vector vecPerp; - CrossProduct( Vector( 0, 0, 1 ), vecRay, vecPerp ); - vecPerp.z = 0.0f; - if ( VectorNormalize( vecPerp ) > 1e-3 ) - { - Vector vecCurrentDir; - GetVectors( &vecCurrentDir, NULL, NULL ); - if ( DotProduct( vecPerp, vecCurrentDir ) > 0.0f ) - { - vecPerp *= -1.0f; - } - - vecPerp *= random->RandomFloat( 15, 25 ); - vecVelocity += vecPerp; - pEnt->SetAbsVelocity( vecVelocity ); -// pEnt->DisableGuiding(); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -#define FIRING_DISCHARGE_RATE (1.0f / 3.0f) - -void CPropAirboat::UpdateGunState( CUserCmd *ucmd ) -{ - bool bStopRumble = false; - - if ( ucmd->buttons & IN_ATTACK ) - { - if ( m_nGunState == GUN_STATE_IDLE ) - { -// AddGestureSequence( LookupSequence( "fire_gun" ) ); - m_nGunState = GUN_STATE_FIRING; - } - - if ( m_nAmmoCount > 0 ) - { - RemoveAmmo( FIRING_DISCHARGE_RATE ); - FireGun( ); - - if ( m_nAmmoCount == 0 ) - { - EmitSound( "Airboat.FireGunRevDown" ); - bStopRumble = true; -// RemoveAllGestures(); - } - } - } - else - { - if ( m_nGunState != GUN_STATE_IDLE ) - { - if ( m_nAmmoCount != 0 ) - { - EmitSound( "Airboat.FireGunRevDown" ); - bStopRumble = true; -// RemoveAllGestures(); - } - m_nGunState = GUN_STATE_IDLE; - } - } - - if( bStopRumble ) - { - CBaseEntity *pDriver = GetDriver(); - CBasePlayer *pPlayerDriver; - if( pDriver && pDriver->IsPlayer() ) - { - pPlayerDriver = dynamic_cast(pDriver); - if( pPlayerDriver ) - { - pPlayerDriver->RumbleEffect( RUMBLE_AIRBOAT_GUN, 0, RUMBLE_FLAG_STOP ); - } - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAirboat::DriveVehicle( float flFrameTime, CUserCmd *ucmd, int iButtonsDown, int iButtonsReleased ) -{ - if ( ucmd->impulse == 100 ) - { - if (HeadlightIsOn()) - { - HeadlightTurnOff(); - } - else - { - HeadlightTurnOn(); - } - } - - // Fire gun. - if ( HasGun() ) - { - UpdateGunState( ucmd ); - } - - m_VehiclePhysics.UpdateDriverControls( ucmd, TICK_INTERVAL ); - - // Create splashes. - UpdateSplashEffects(); - - // Save this data. - m_flThrottle = m_VehiclePhysics.GetThrottle(); - m_nSpeed = m_VehiclePhysics.GetSpeed(); - m_nRPM = m_VehiclePhysics.GetRPM(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -// *pMoveData - -//----------------------------------------------------------------------------- -void CPropAirboat::ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ) -{ - BaseClass::ProcessMovement( pPlayer, pMoveData ); - - if ( gpGlobals->frametime != 0 ) - { - // Create danger sounds in front of the vehicle. - CreateDangerSounds(); - - // Play a sound around us to make NPCs pay attention to us - if ( m_VehiclePhysics.GetThrottle() > 0 ) - { - CSoundEnt::InsertSound( SOUND_PLAYER_VEHICLE, pPlayer->GetAbsOrigin(), 3500, 0.1f, pPlayer, SOUNDENT_CHANNEL_REPEATED_PHYSICS_DANGER ); - } - } - - Vector vecVelocityWorld; - GetVelocity( &vecVelocityWorld, NULL ); - Vector vecVelocityLocal; - WorldToEntitySpace( GetAbsOrigin() + vecVelocityWorld, &vecVelocityLocal ); - - m_vecPhysVelocity = vecVelocityLocal; -} - - -//----------------------------------------------------------------------------- -// Purpose: Create danger sounds in front of the vehicle. -//----------------------------------------------------------------------------- -void CPropAirboat::CreateDangerSounds( void ) -{ - QAngle vehicleAngles = GetLocalAngles(); - Vector vecStart = GetAbsOrigin(); - Vector vecDir, vecRight; - - GetVectors( &vecDir, &vecRight, NULL ); - - const float soundDuration = 0.25; - float speed = m_VehiclePhysics.GetHLSpeed(); - - // Make danger sounds ahead of the vehicle - if ( fabs(speed) > 120 ) - { - Vector vecSpot; - - float steering = m_VehiclePhysics.GetSteering(); - if ( steering != 0 ) - { - if ( speed > 0 ) - { - vecDir += vecRight * steering * 0.5; - } - else - { - vecDir -= vecRight * steering * 0.5; - } - VectorNormalize(vecDir); - } - - const float radius = speed * 0.4; - - // 0.7 seconds ahead - vecSpot = vecStart + vecDir * (speed * 0.7f); - CSoundEnt::InsertSound( SOUND_DANGER, vecSpot, (int)radius, soundDuration, this, SOUNDENT_CHANNEL_REPEATED_DANGER ); - CSoundEnt::InsertSound( SOUND_PHYSICS_DANGER, vecSpot, (int)radius, soundDuration, this, SOUNDENT_CHANNEL_REPEATED_PHYSICS_DANGER ); - //NDebugOverlay::Box(vecSpot, Vector(-radius,-radius,-radius),Vector(radius,radius,radius), 255, 0, 255, 0, soundDuration); - -#if 0 - // put sounds a bit to left and right but slightly closer to vehicle to make - // a "cone" of sound in front of it. - trace_t tr; - vecSpot = vecStart + vecDir * (speed * 0.5f) - vecRight * speed * 0.5; - UTIL_TraceLine( vecStart, vecSpot, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - CSoundEnt::InsertSound( SOUND_DANGER, vecSpot, 400, soundDuration, this, 1 ); - - vecSpot = vecStart + vecDir * (speed * 0.5f) + vecRight * speed * 0.5; - UTIL_TraceLine( vecStart, vecSpot, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - CSoundEnt::InsertSound( SOUND_DANGER, vecSpot, 400, soundDuration, this, 2); -#endif - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAirboat::DampenEyePosition( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles ) -{ - // Get the frametime. (Check to see if enough time has passed to warrent dampening). - float flFrameTime = gpGlobals->frametime; - if ( flFrameTime < AIRBOAT_FRAMETIME_MIN ) - { - vecVehicleEyePos = m_vecLastEyePos; - DampenUpMotion( vecVehicleEyePos, vecVehicleEyeAngles, 0.0f ); - return; - } - - // Keep static the sideways motion. - - // Dampen forward/backward motion. - DampenForwardMotion( vecVehicleEyePos, vecVehicleEyeAngles, flFrameTime ); - - // Blend up/down motion. - DampenUpMotion( vecVehicleEyePos, vecVehicleEyeAngles, flFrameTime ); -} - - -//----------------------------------------------------------------------------- -// Use the controller as follows: -// speed += ( pCoefficientsOut[0] * ( targetPos - currentPos ) + pCoefficientsOut[1] * ( targetSpeed - currentSpeed ) ) * flDeltaTime; -//----------------------------------------------------------------------------- -void CPropAirboat::ComputePDControllerCoefficients( float *pCoefficientsOut, - float flFrequency, float flDampening, - float flDeltaTime ) -{ - float flKs = 9.0f * flFrequency * flFrequency; - float flKd = 4.5f * flFrequency * flDampening; - - float flScale = 1.0f / ( 1.0f + flKd * flDeltaTime + flKs * flDeltaTime * flDeltaTime ); - - pCoefficientsOut[0] = flKs * flScale; - pCoefficientsOut[1] = ( flKd + flKs * flDeltaTime ) * flScale; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAirboat::DampenForwardMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime ) -{ - // Get forward vector. - Vector vecForward; - AngleVectors( vecVehicleEyeAngles, &vecForward); - - // Simulate the eye position forward based on the data from last frame - // (assumes no acceleration - it will get that from the "spring"). - Vector vecCurrentEyePos = m_vecLastEyePos + m_vecEyeSpeed * flFrameTime; - - // Calculate target speed based on the current vehicle eye position and the last vehicle eye position and frametime. - Vector vecVehicleEyeSpeed = ( vecVehicleEyePos - m_vecLastEyeTarget ) / flFrameTime; - m_vecLastEyeTarget = vecVehicleEyePos; - - // Calculate the speed and position deltas. - Vector vecDeltaSpeed = vecVehicleEyeSpeed - m_vecEyeSpeed; - Vector vecDeltaPos = vecVehicleEyePos - vecCurrentEyePos; - - // Clamp. - if ( vecDeltaPos.Length() > AIRBOAT_DELTA_LENGTH_MAX ) - { - float flSign = vecForward.Dot( vecVehicleEyeSpeed ) >= 0.0f ? -1.0f : 1.0f; - vecVehicleEyePos += flSign * ( vecForward * AIRBOAT_DELTA_LENGTH_MAX ); - m_vecLastEyePos = vecVehicleEyePos; - m_vecEyeSpeed = vecVehicleEyeSpeed; - return; - } - - // Generate an updated (dampening) speed for use in next frames position extrapolation. - float flCoefficients[2]; - ComputePDControllerCoefficients( flCoefficients, r_AirboatViewDampenFreq.GetFloat(), r_AirboatViewDampenDamp.GetFloat(), flFrameTime ); - m_vecEyeSpeed += ( ( flCoefficients[0] * vecDeltaPos + flCoefficients[1] * vecDeltaSpeed ) * flFrameTime ); - - // Save off data for next frame. - m_vecLastEyePos = vecCurrentEyePos; - - // Move eye forward/backward. - Vector vecForwardOffset = vecForward * ( vecForward.Dot( vecDeltaPos ) ); - vecVehicleEyePos -= vecForwardOffset; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAirboat::DampenUpMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime ) -{ - // Get up vector. - Vector vecUp; - AngleVectors( vecVehicleEyeAngles, NULL, NULL, &vecUp ); - vecUp.z = clamp( vecUp.z, 0.0f, vecUp.z ); - vecVehicleEyePos.z += r_AirboatViewZHeight.GetFloat() * vecUp.z; - - // NOTE: Should probably use some damped equation here. -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAirboat::CreateSplash( int nSplashType ) -{ - if ( GetWaterLevel( ) == 0 ) - return; - - Vector vecSplashPoint; - Vector vecForward, vecUp; - GetAttachment( m_nSplashAttachment, vecSplashPoint, &vecForward, &vecUp, NULL ); - - CEffectData data; - data.m_fFlags = 0; - data.m_vOrigin = vecSplashPoint; - if ( GetWaterType() & CONTENTS_SLIME ) - { - data.m_fFlags |= FX_WATER_IN_SLIME; - } - - switch ( nSplashType ) - { - case AIRBOAT_SPLASH_SPRAY: - { - Vector vecSplashDir; - vecSplashDir = ( vecForward + vecUp ) * 0.5f; - VectorNormalize( vecSplashDir ); - data.m_vNormal = vecSplashDir; - data.m_flScale = 10.0f + random->RandomFloat( 0, 10.0f * 0.25 ); - //DispatchEffect( "waterripple", data ); - DispatchEffect( "watersplash", data ); - } - case AIRBOAT_SPLASH_RIPPLE: - { - /* - Vector vecSplashDir; - vecSplashDir = vecUp; - data.m_vNormal = vecSplashDir; - data.m_flScale = AIRBOAT_SPLASH_RIPPLE_SIZE + random->RandomFloat( 0, AIRBOAT_SPLASH_RIPPLE_SIZE * 0.25 ); - DispatchEffect( "waterripple", data ); - */ - } - default: - { - return; - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Overloaded to calculate stress damage. -//----------------------------------------------------------------------------- -void CPropAirboat::VPhysicsUpdate( IPhysicsObject *pPhysics ) -{ - BaseClass::VPhysicsUpdate( pPhysics ); - - if ( airboat_fatal_stress.GetFloat() > 0 ) - { - ApplyStressDamage( pPhysics ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns the damage that should be dealt to the driver due to -// stress (vphysics objects exerting pressure on us). -//----------------------------------------------------------------------------- -float CPropAirboat::CalculatePhysicsStressDamage( vphysics_objectstress_t *pStressOut, IPhysicsObject *pPhysics ) -{ - vphysics_objectstress_t stressOut; - CalculateObjectStress( pPhysics, this, &stressOut ); - - //if ( ( stressOut.exertedStress > 100 ) || ( stressOut.receivedStress > 100 ) ) - // Msg( "stress: %f %d %f\n", stressOut.exertedStress, stressOut.hasNonStaticStress, stressOut.receivedStress ); - - // Make sure the stress isn't from being stuck inside some static object. - // If we're being crushed by more than the fatal stress amount, kill the driver. - if ( stressOut.hasNonStaticStress && ( stressOut.receivedStress > airboat_fatal_stress.GetFloat() ) ) - { - // if stuck, don't do this! - if ( !(pPhysics->GetGameFlags() & FVPHYSICS_PENETRATING) ) - { - // Kill the driver! - return 1000; - } - } - - return 0; -} - - -//----------------------------------------------------------------------------- -// Purpose: Applies stress damage to the player/driver. -//----------------------------------------------------------------------------- -void CPropAirboat::ApplyStressDamage( IPhysicsObject *pPhysics ) -{ - vphysics_objectstress_t stressOut = {0.0f, 0.0f, false, false}; - float damage = CalculatePhysicsStressDamage( &stressOut, pPhysics ); - if ( ( damage > 0 ) && ( m_hPlayer != NULL ) ) - { - CTakeDamageInfo dmgInfo( GetWorldEntity(), GetWorldEntity(), vec3_origin, vec3_origin, damage, DMG_CRUSH ); - dmgInfo.SetDamageForce( Vector( 0, 0, -stressOut.receivedStress * sv_gravity.GetFloat() * gpGlobals->frametime ) ); - dmgInfo.SetDamagePosition( GetAbsOrigin() ); - m_hPlayer->TakeDamage( dmgInfo ); - } -} - diff --git a/game/server/hl2/vehicle_apc.cpp b/game/server/hl2/vehicle_apc.cpp deleted file mode 100644 index c7283e342..000000000 --- a/game/server/hl2/vehicle_apc.cpp +++ /dev/null @@ -1,1105 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "vehicle_apc.h" -#include "ammodef.h" -#include "IEffects.h" -#include "engine/IEngineSound.h" -#include "weapon_rpg.h" -#include "in_buttons.h" -#include "globalstate.h" -#include "soundent.h" -#include "ai_basenpc.h" -#include "ndebugoverlay.h" -#include "gib.h" -#include "EntityFlame.h" -#include "smoke_trail.h" -#include "explode.h" -#include "effect_dispatch_data.h" -#include "te_effect_dispatch.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -#define ROCKET_ATTACK_RANGE_MAX 5500.0f -#define ROCKET_ATTACK_RANGE_MIN 1250.0f - -#define MACHINE_GUN_ATTACK_RANGE_MAX 1250.0f -#define MACHINE_GUN_ATTACK_RANGE_MIN 0.0f - -#define MACHINE_GUN_MAX_UP_PITCH 30 -#define MACHINE_GUN_MAX_DOWN_PITCH 10 -#define MACHINE_GUN_MAX_LEFT_YAW 30 -#define MACHINE_GUN_MAX_RIGHT_YAW 30 - -#define MACHINE_GUN_BURST_SIZE 10 -#define MACHINE_GUN_BURST_TIME 0.075f -#define MACHINE_GUN_BURST_PAUSE_TIME 2.0f - -#define ROCKET_SALVO_SIZE 5 -#define ROCKET_DELAY_TIME 1.5 -#define ROCKET_MIN_BURST_PAUSE_TIME 3 -#define ROCKET_MAX_BURST_PAUSE_TIME 4 -#define ROCKET_SPEED 800 -#define DEATH_VOLLEY_ROCKET_COUNT 4 -#define DEATH_VOLLEY_MIN_FIRE_TIME 0.333 -#define DEATH_VOLLEY_MAX_FIRE_TIME 0.166 - -extern short g_sModelIndexFireball; // Echh... - - -ConVar sk_apc_health( "sk_apc_health", "750" ); - - -#define APC_MAX_CHUNKS 3 -static const char *s_pChunkModelName[APC_MAX_CHUNKS] = -{ - "models/gibs/helicopter_brokenpiece_01.mdl", - "models/gibs/helicopter_brokenpiece_02.mdl", - "models/gibs/helicopter_brokenpiece_03.mdl", -}; - -#define APC_MAX_GIBS 6 -static const char *s_pGibModelName[APC_MAX_GIBS] = -{ - "models/combine_apc_destroyed_gib01.mdl", - "models/combine_apc_destroyed_gib02.mdl", - "models/combine_apc_destroyed_gib03.mdl", - "models/combine_apc_destroyed_gib04.mdl", - "models/combine_apc_destroyed_gib05.mdl", - "models/combine_apc_destroyed_gib06.mdl", -}; - - -LINK_ENTITY_TO_CLASS( prop_vehicle_apc, CPropAPC ); - - -BEGIN_DATADESC( CPropAPC ) - - DEFINE_FIELD( m_flDangerSoundTime, FIELD_TIME ), - DEFINE_FIELD( m_flHandbrakeTime, FIELD_TIME ), - DEFINE_FIELD( m_bInitialHandbrake, FIELD_BOOLEAN ), - DEFINE_FIELD( m_nSmokeTrailCount, FIELD_INTEGER ), - DEFINE_FIELD( m_flMachineGunTime, FIELD_TIME ), - DEFINE_FIELD( m_iMachineGunBurstLeft, FIELD_INTEGER ), -// DEFINE_FIELD( m_nMachineGunMuzzleAttachment, FIELD_INTEGER ), -// DEFINE_FIELD( m_nMachineGunBaseAttachment, FIELD_INTEGER ), -// DEFINE_FIELD( m_vecBarrelPos, FIELD_VECTOR ), - DEFINE_FIELD( m_bInFiringCone, FIELD_BOOLEAN ), -// DEFINE_FIELD( m_hLaserDot, FIELD_EHANDLE ), - DEFINE_FIELD( m_hRocketTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_iRocketSalvoLeft, FIELD_INTEGER ), - DEFINE_FIELD( m_flRocketTime, FIELD_TIME ), -// DEFINE_FIELD( m_nRocketAttachment, FIELD_INTEGER ), - DEFINE_FIELD( m_nRocketSide, FIELD_INTEGER ), - DEFINE_FIELD( m_hSpecificRocketTarget, FIELD_EHANDLE ), - DEFINE_KEYFIELD( m_strMissileHint, FIELD_STRING, "missilehint" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Destroy", InputDestroy ), - DEFINE_INPUTFUNC( FIELD_STRING, "FireMissileAt", InputFireMissileAt ), - - DEFINE_OUTPUT( m_OnDeath, "OnDeath" ), - DEFINE_OUTPUT( m_OnFiredMissile, "OnFiredMissile" ), - DEFINE_OUTPUT( m_OnDamaged, "OnDamaged" ), - DEFINE_OUTPUT( m_OnDamagedByPlayer, "OnDamagedByPlayer" ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAPC::Precache( void ) -{ - BaseClass::Precache(); - - int i; - for ( i = 0; i < APC_MAX_CHUNKS; ++i ) - { - PrecacheModel( s_pChunkModelName[i] ); - } - - for ( i = 0; i < APC_MAX_GIBS; ++i ) - { - PrecacheModel( s_pGibModelName[i] ); - } - - PrecacheScriptSound( "Weapon_AR2.Single" ); - PrecacheScriptSound( "PropAPC.FireRocket" ); - PrecacheScriptSound( "combine.door_lock" ); -} - - -//------------------------------------------------ -// Spawn -//------------------------------------------------ -void CPropAPC::Spawn( void ) -{ - BaseClass::Spawn(); - SetBlocksLOS( true ); - m_iHealth = m_iMaxHealth = sk_apc_health.GetFloat(); - SetCycle( 0 ); - m_iMachineGunBurstLeft = MACHINE_GUN_BURST_SIZE; - m_iRocketSalvoLeft = ROCKET_SALVO_SIZE; - m_nRocketSide = 0; - m_lifeState = LIFE_ALIVE; - m_bInFiringCone = false; - - m_flHandbrakeTime = gpGlobals->curtime + 0.1; - m_bInitialHandbrake = false; - - // Reset the gun to a default pose. - SetPoseParameter( "vehicle_weapon_pitch", 0 ); - SetPoseParameter( "vehicle_weapon_yaw", 90 ); - - CreateAPCLaserDot(); - - if( g_pGameRules->GetAutoAimMode() == AUTOAIM_ON_CONSOLE ) - { - AddFlag( FL_AIMTARGET ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Create a laser -//----------------------------------------------------------------------------- -void CPropAPC::CreateAPCLaserDot( void ) -{ - // Create a laser if we don't have one - if ( m_hLaserDot == NULL ) - { - m_hLaserDot = CreateLaserDot( GetAbsOrigin(), this, false ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CPropAPC::ShouldAttractAutoAim( CBaseEntity *pAimingEnt ) -{ - if( g_pGameRules->GetAutoAimMode() == AUTOAIM_ON_CONSOLE && pAimingEnt->IsPlayer() && GetDriver() ) - { - return true; - } - - return BaseClass::ShouldAttractAutoAim( pAimingEnt ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAPC::Activate() -{ - BaseClass::Activate(); - - m_nRocketAttachment = LookupAttachment( "cannon_muzzle" ); - m_nMachineGunMuzzleAttachment = LookupAttachment( "muzzle" ); - m_nMachineGunBaseAttachment = LookupAttachment( "gun_base" ); - - // NOTE: gun_ref must have the same position as gun_base, but rotates with the gun - int nMachineGunRefAttachment = LookupAttachment( "gun_def" ); - - Vector vecWorldBarrelPos; - matrix3x4_t matRefToWorld; - GetAttachment( m_nMachineGunMuzzleAttachment, vecWorldBarrelPos ); - GetAttachment( nMachineGunRefAttachment, matRefToWorld ); - VectorITransform( vecWorldBarrelPos, matRefToWorld, m_vecBarrelPos ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAPC::UpdateOnRemove( void ) -{ - if ( m_hLaserDot ) - { - UTIL_Remove( m_hLaserDot ); - m_hLaserDot = NULL; - } - BaseClass::UpdateOnRemove(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAPC::CreateServerVehicle( void ) -{ - // Create our armed server vehicle - m_pServerVehicle = new CAPCFourWheelServerVehicle(); - m_pServerVehicle->SetVehicle( this ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pMoveData - -//----------------------------------------------------------------------------- -Class_T CPropAPC::ClassifyPassenger( CBaseCombatCharacter *pPassenger, Class_T defaultClassification ) -{ - return CLASS_COMBINE; -} - - -//----------------------------------------------------------------------------- -// Purpose: Damage events as modified for the passenger of the APC, not the APC itself -//----------------------------------------------------------------------------- -float CPropAPC::PassengerDamageModifier( const CTakeDamageInfo &info ) -{ - CTakeDamageInfo DmgInfo = info; - - // bullets, slashing and headbutts don't hurt us in the apc, neither do rockets - if( (DmgInfo.GetDamageType() & DMG_BULLET) || (DmgInfo.GetDamageType() & DMG_SLASH) || - (DmgInfo.GetDamageType() & DMG_CLUB) || (DmgInfo.GetDamageType() & DMG_BLAST) ) - return (0); - - // Accept everything else by default - return 1.0; -} - - -//----------------------------------------------------------------------------- -// position of eyes -//----------------------------------------------------------------------------- -Vector CPropAPC::EyePosition( ) -{ - Vector vecEyePosition; - CollisionProp()->NormalizedToWorldSpace( Vector( 0.5, 0.5, 1.0 ), &vecEyePosition ); - return vecEyePosition; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Vector CPropAPC::BodyTarget( const Vector &posSrc, bool bNoisy ) -{ - if( g_pGameRules->GetAutoAimMode() == AUTOAIM_ON_CONSOLE ) - { - return WorldSpaceCenter(); - } - - return BaseClass::BodyTarget( posSrc, bNoisy ); -} - -//----------------------------------------------------------------------------- -// Add a smoke trail since we've taken more damage -//----------------------------------------------------------------------------- -void CPropAPC::AddSmokeTrail( const Vector &vecPos ) -{ - // Start this trail out with a bang! - ExplosionCreate( vecPos, vec3_angle, this, 1000, 500, SF_ENVEXPLOSION_NODAMAGE | - SF_ENVEXPLOSION_NOSPARKS | SF_ENVEXPLOSION_NODLIGHTS | SF_ENVEXPLOSION_NOSMOKE | - SF_ENVEXPLOSION_NOFIREBALLSMOKE, 0 ); - UTIL_ScreenShake( vecPos, 25.0, 150.0, 1.0, 750.0f, SHAKE_START ); - - if ( m_nSmokeTrailCount == MAX_SMOKE_TRAILS ) - return; - - SmokeTrail *pSmokeTrail = SmokeTrail::CreateSmokeTrail(); - if( !pSmokeTrail ) - return; - - // See if there's an attachment for this smoke trail - char buf[32]; - Q_snprintf( buf, 32, "damage%d", m_nSmokeTrailCount ); - int nAttachment = LookupAttachment( buf ); - - ++m_nSmokeTrailCount; - - pSmokeTrail->m_SpawnRate = 4; - pSmokeTrail->m_ParticleLifetime = 5.0f; - pSmokeTrail->m_StartColor.Init( 0.7f, 0.7f, 0.7f ); - pSmokeTrail->m_EndColor.Init( 0.6, 0.6, 0.6 ); - pSmokeTrail->m_StartSize = 32; - pSmokeTrail->m_EndSize = 64; - pSmokeTrail->m_SpawnRadius = 4; - pSmokeTrail->m_Opacity = 0.5f; - pSmokeTrail->m_MinSpeed = 16; - pSmokeTrail->m_MaxSpeed = 16; - pSmokeTrail->m_MinDirectedSpeed = 16.0f; - pSmokeTrail->m_MaxDirectedSpeed = 16.0f; - pSmokeTrail->SetLifetime( 5 ); - pSmokeTrail->SetParent( this, nAttachment ); - - Vector vecForward( 0, 0, 1 ); - QAngle angles; - VectorAngles( vecForward, angles ); - - if ( nAttachment == 0 ) - { - pSmokeTrail->SetAbsOrigin( vecPos ); - pSmokeTrail->SetAbsAngles( angles ); - } - else - { - pSmokeTrail->SetLocalOrigin( vec3_origin ); - pSmokeTrail->SetLocalAngles( angles ); - } - - pSmokeTrail->SetMoveType( MOVETYPE_NONE ); -} - - -//------------------------------------------------------------------------------ -// Pow! -//------------------------------------------------------------------------------ -void CPropAPC::ExplodeAndThrowChunk( const Vector &vecExplosionPos ) -{ - ExplosionCreate( vecExplosionPos, vec3_angle, this, 1000, 500, - SF_ENVEXPLOSION_NODAMAGE | SF_ENVEXPLOSION_NOSPARKS | SF_ENVEXPLOSION_NODLIGHTS | - SF_ENVEXPLOSION_NOSMOKE | SF_ENVEXPLOSION_NOFIREBALLSMOKE, 0 ); - UTIL_ScreenShake( vecExplosionPos, 25.0, 150.0, 1.0, 750.0f, SHAKE_START ); - - // Drop a flaming, smoking chunk. - CGib *pChunk = CREATE_ENTITY( CGib, "gib" ); - pChunk->Spawn( "models/gibs/hgibs.mdl" ); - pChunk->SetBloodColor( DONT_BLEED ); - - QAngle vecSpawnAngles; - vecSpawnAngles.Random( -90, 90 ); - pChunk->SetAbsOrigin( vecExplosionPos ); - pChunk->SetAbsAngles( vecSpawnAngles ); - - int nGib = random->RandomInt( 0, APC_MAX_CHUNKS - 1 ); - pChunk->Spawn( s_pChunkModelName[nGib] ); - pChunk->SetOwnerEntity( this ); - pChunk->m_lifeTime = random->RandomFloat( 6.0f, 8.0f ); - pChunk->SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - IPhysicsObject *pPhysicsObject = pChunk->VPhysicsInitNormal( SOLID_VPHYSICS, pChunk->GetSolidFlags(), false ); - - // Set the velocity - if ( pPhysicsObject ) - { - pPhysicsObject->EnableMotion( true ); - Vector vecVelocity; - - QAngle angles; - angles.x = random->RandomFloat( -40, 0 ); - angles.y = random->RandomFloat( 0, 360 ); - angles.z = 0.0f; - AngleVectors( angles, &vecVelocity ); - - vecVelocity *= random->RandomFloat( 300, 900 ); - vecVelocity += GetAbsVelocity(); - - AngularImpulse angImpulse; - angImpulse = RandomAngularImpulse( -180, 180 ); - - pChunk->SetAbsVelocity( vecVelocity ); - pPhysicsObject->SetVelocity(&vecVelocity, &angImpulse ); - } - - CEntityFlame *pFlame = CEntityFlame::Create( pChunk, false ); - if ( pFlame != NULL ) - { - pFlame->SetLifetime( pChunk->m_lifeTime ); - } -} - - -//----------------------------------------------------------------------------- -// Should we trigger a damage effect? -//----------------------------------------------------------------------------- -inline bool CPropAPC::ShouldTriggerDamageEffect( int nPrevHealth, int nEffectCount ) const -{ - int nPrevRange = (int)( ((float)nPrevHealth / (float)GetMaxHealth()) * nEffectCount ); - int nRange = (int)( ((float)GetHealth() / (float)GetMaxHealth()) * nEffectCount ); - return ( nRange != nPrevRange ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAPC::Event_Killed( const CTakeDamageInfo &info ) -{ - m_OnDeath.FireOutput( info.GetAttacker(), this ); - - Vector vecAbsMins, vecAbsMaxs; - CollisionProp()->WorldSpaceAABB( &vecAbsMins, &vecAbsMaxs ); - - Vector vecNormalizedMins, vecNormalizedMaxs; - CollisionProp()->WorldToNormalizedSpace( vecAbsMins, &vecNormalizedMins ); - CollisionProp()->WorldToNormalizedSpace( vecAbsMaxs, &vecNormalizedMaxs ); - - Vector vecAbsPoint; - CPASFilter filter( GetAbsOrigin() ); - for (int i = 0; i < 5; i++) - { - CollisionProp()->RandomPointInBounds( vecNormalizedMins, vecNormalizedMaxs, &vecAbsPoint ); - te->Explosion( filter, random->RandomFloat( 0.0, 1.0 ), &vecAbsPoint, - g_sModelIndexFireball, random->RandomInt( 4, 10 ), - random->RandomInt( 8, 15 ), - ( i < 2 ) ? TE_EXPLFLAG_NODLIGHTS : TE_EXPLFLAG_NOPARTICLES | TE_EXPLFLAG_NOFIREBALLSMOKE | TE_EXPLFLAG_NODLIGHTS, - 100, 0 ); - } - - // TODO: make the gibs spawn in sync with the delayed explosions - int nGibs = random->RandomInt( 1, 4 ); - for ( int i = 0; i < nGibs; i++) - { - // Throw a flaming, smoking chunk. - CGib *pChunk = CREATE_ENTITY( CGib, "gib" ); - pChunk->Spawn( "models/gibs/hgibs.mdl" ); - pChunk->SetBloodColor( DONT_BLEED ); - - QAngle vecSpawnAngles; - vecSpawnAngles.Random( -90, 90 ); - pChunk->SetAbsOrigin( vecAbsPoint ); - pChunk->SetAbsAngles( vecSpawnAngles ); - - int nGib = random->RandomInt( 0, APC_MAX_CHUNKS - 1 ); - pChunk->Spawn( s_pChunkModelName[nGib] ); - pChunk->SetOwnerEntity( this ); - pChunk->m_lifeTime = random->RandomFloat( 6.0f, 8.0f ); - pChunk->SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - IPhysicsObject *pPhysicsObject = pChunk->VPhysicsInitNormal( SOLID_VPHYSICS, pChunk->GetSolidFlags(), false ); - - // Set the velocity - if ( pPhysicsObject ) - { - pPhysicsObject->EnableMotion( true ); - Vector vecVelocity; - - QAngle angles; - angles.x = random->RandomFloat( -20, 20 ); - angles.y = random->RandomFloat( 0, 360 ); - angles.z = 0.0f; - AngleVectors( angles, &vecVelocity ); - - vecVelocity *= random->RandomFloat( 300, 900 ); - vecVelocity += GetAbsVelocity(); - - AngularImpulse angImpulse; - angImpulse = RandomAngularImpulse( -180, 180 ); - - pChunk->SetAbsVelocity( vecVelocity ); - pPhysicsObject->SetVelocity(&vecVelocity, &angImpulse ); - } - - CEntityFlame *pFlame = CEntityFlame::Create( pChunk, false ); - if ( pFlame != NULL ) - { - pFlame->SetLifetime( pChunk->m_lifeTime ); - } - } - - UTIL_ScreenShake( vecAbsPoint, 25.0, 150.0, 1.0, 750.0f, SHAKE_START ); - - if( hl2_episodic.GetBool() ) - { - // EP1 perf hit - Ignite( 6, false ); - } - else - { - Ignite( 60, false ); - } - - m_lifeState = LIFE_DYING; - - // Spawn a lesser amount if the player is close - m_iRocketSalvoLeft = DEATH_VOLLEY_ROCKET_COUNT; - m_flRocketTime = gpGlobals->curtime; -} - - - -//----------------------------------------------------------------------------- -// Purpose: Blows it up! -//----------------------------------------------------------------------------- -void CPropAPC::InputDestroy( inputdata_t &inputdata ) -{ - CTakeDamageInfo info( this, this, m_iHealth, DMG_BLAST ); - info.SetDamagePosition( WorldSpaceCenter() ); - info.SetDamageForce( Vector( 0, 0, 1 ) ); - TakeDamage( info ); -} - - -//----------------------------------------------------------------------------- -// Aim the next rocket at a specific target -//----------------------------------------------------------------------------- -void CPropAPC::InputFireMissileAt( inputdata_t &inputdata ) -{ - string_t strMissileTarget = MAKE_STRING( inputdata.value.String() ); - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, strMissileTarget, NULL, inputdata.pActivator, inputdata.pCaller ); - if ( pTarget == NULL ) - { - DevWarning( "%s: Could not find target '%s'!\n", GetClassname(), STRING( strMissileTarget ) ); - return; - } - - m_hSpecificRocketTarget = pTarget; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CPropAPC::OnTakeDamage( const CTakeDamageInfo &info ) -{ - if ( m_iHealth == 0 ) - return 0; - - m_OnDamaged.FireOutput( info.GetAttacker(), this ); - - if ( info.GetAttacker() && info.GetAttacker()->IsPlayer() ) - { - m_OnDamagedByPlayer.FireOutput( info.GetAttacker(), this ); - } - - CTakeDamageInfo dmgInfo = info; - if ( dmgInfo.GetDamageType() & (DMG_BLAST | DMG_AIRBOAT) ) - { - int nPrevHealth = GetHealth(); - - m_iHealth -= dmgInfo.GetDamage(); - if ( m_iHealth <= 0 ) - { - m_iHealth = 0; - Event_Killed( dmgInfo ); - return 0; - } - - // Chain -// BaseClass::OnTakeDamage( dmgInfo ); - - // Spawn damage effects - if ( nPrevHealth != GetHealth() ) - { - if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_SMOKE_TRAILS ) ) - { - AddSmokeTrail( dmgInfo.GetDamagePosition() ); - } - - if ( ShouldTriggerDamageEffect( nPrevHealth, MAX_EXPLOSIONS ) ) - { - ExplodeAndThrowChunk( dmgInfo.GetDamagePosition() ); - } - } - } - return 1; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pMoveData - -//----------------------------------------------------------------------------- -void CPropAPC::ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ) -{ - BaseClass::ProcessMovement( pPlayer, pMoveData ); - - if ( m_flDangerSoundTime > gpGlobals->curtime ) - return; - - QAngle vehicleAngles = GetLocalAngles(); - Vector vecStart = GetAbsOrigin(); - Vector vecDir; - - GetVectors( &vecDir, NULL, NULL ); - - // Make danger sounds ahead of the APC - trace_t tr; - Vector vecSpot, vecLeftDir, vecRightDir; - - // lay down sound path - vecSpot = vecStart + vecDir * 600; - CSoundEnt::InsertSound( SOUND_DANGER, vecSpot, 400, 0.1, this ); - - // put sounds a bit to left and right but slightly closer to APC to make a "cone" of sound - // in front of it - QAngle leftAngles = vehicleAngles; - leftAngles[YAW] += 20; - VehicleAngleVectors( leftAngles, &vecLeftDir, NULL, NULL ); - vecSpot = vecStart + vecLeftDir * 400; - UTIL_TraceLine( vecStart, vecSpot, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - CSoundEnt::InsertSound( SOUND_DANGER, vecSpot, 400, 0.1, this ); - - QAngle rightAngles = vehicleAngles; - rightAngles[YAW] -= 20; - VehicleAngleVectors( rightAngles, &vecRightDir, NULL, NULL ); - vecSpot = vecStart + vecRightDir * 400; - UTIL_TraceLine( vecStart, vecSpot, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - CSoundEnt::InsertSound( SOUND_DANGER, vecSpot, 400, 0.1, this); - - m_flDangerSoundTime = gpGlobals->curtime + 0.3; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAPC::Think( void ) -{ - BaseClass::Think(); - - SetNextThink( gpGlobals->curtime ); - - if ( !m_bInitialHandbrake ) // after initial timer expires, set the handbrake - { - m_bInitialHandbrake = true; - m_VehiclePhysics.SetHandbrake( true ); - m_VehiclePhysics.Think(); - } - - StudioFrameAdvance(); - - if ( IsSequenceFinished() ) - { - int iSequence = SelectWeightedSequence( ACT_IDLE ); - if ( iSequence > ACTIVITY_NOT_AVAILABLE ) - { - SetCycle( 0 ); - m_flAnimTime = gpGlobals->curtime; - ResetSequence( iSequence ); - ResetClientsideFrame(); - } - } - - if (m_debugOverlays & OVERLAY_NPC_KILL_BIT) - { - CTakeDamageInfo info( this, this, m_iHealth, DMG_BLAST ); - info.SetDamagePosition( WorldSpaceCenter() ); - info.SetDamageForce( Vector( 0, 0, 1 ) ); - TakeDamage( info ); - } -} - - -//----------------------------------------------------------------------------- -// Aims the secondary weapon at a target -//----------------------------------------------------------------------------- -void CPropAPC::AimSecondaryWeaponAt( CBaseEntity *pTarget ) -{ - m_hRocketTarget = pTarget; - - // Update the rocket target - CreateAPCLaserDot(); - - if ( m_hRocketTarget ) - { - m_hLaserDot->SetAbsOrigin( m_hRocketTarget->BodyTarget( WorldSpaceCenter(), false ) ); - } - SetLaserDotTarget( m_hLaserDot, m_hRocketTarget ); - EnableLaserDot( m_hLaserDot, m_hRocketTarget != NULL ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAPC::DriveVehicle( float flFrameTime, CUserCmd *ucmd, int iButtonsDown, int iButtonsReleased ) -{ - switch( m_lifeState ) - { - case LIFE_ALIVE: - { - int iButtons = ucmd->buttons; - if ( iButtons & IN_ATTACK ) - { - FireMachineGun(); - } - else if ( iButtons & IN_ATTACK2 ) - { - FireRocket(); - } - } - break; - - case LIFE_DYING: - FireDying( ); - break; - - case LIFE_DEAD: - return; - } - - BaseClass::DriveVehicle( flFrameTime, ucmd, iButtonsDown, iButtonsReleased ); -} - -void CPropAPC::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - BaseClass::Use( pActivator, pCaller, useType, value ); - - if ( pActivator->IsPlayer() ) - { - EmitSound ( "combine.door_lock" ); - } -} - - -//----------------------------------------------------------------------------- -// Primary gun -//----------------------------------------------------------------------------- -void CPropAPC::AimPrimaryWeapon( const Vector &vecWorldTarget ) -{ - EntityMatrix parentMatrix; - parentMatrix.InitFromEntity( this, m_nMachineGunBaseAttachment ); - Vector target = parentMatrix.WorldToLocal( vecWorldTarget ); - - float quadTarget = target.LengthSqr(); - float quadTargetXY = target.x*target.x + target.y*target.y; - - // Target is too close! Can't aim at it - if ( quadTarget > m_vecBarrelPos.LengthSqr() ) - { - // We're trying to aim the offset barrel at an arbitrary point. - // To calculate this, I think of the target as being on a sphere with - // it's center at the origin of the gun. - // The rotation we need is the opposite of the rotation that moves the target - // along the surface of that sphere to intersect with the gun's shooting direction - // To calculate that rotation, we simply calculate the intersection of the ray - // coming out of the barrel with the target sphere (that's the new target position) - // and use atan2() to get angles - - // angles from target pos to center - float targetToCenterYaw = atan2( target.y, target.x ); - float centerToGunYaw = atan2( m_vecBarrelPos.y, sqrt( quadTarget - (m_vecBarrelPos.y*m_vecBarrelPos.y) ) ); - - float targetToCenterPitch = atan2( target.z, sqrt( quadTargetXY ) ); - float centerToGunPitch = atan2( -m_vecBarrelPos.z, sqrt( quadTarget - (m_vecBarrelPos.z*m_vecBarrelPos.z) ) ); - - QAngle angles; - angles.Init( -RAD2DEG(targetToCenterPitch+centerToGunPitch), RAD2DEG( targetToCenterYaw + centerToGunYaw ), 0 ); - - SetPoseParameter( "vehicle_weapon_yaw", angles.y ); - SetPoseParameter( "vehicle_weapon_pitch", angles.x ); - StudioFrameAdvance(); - - float curPitch = GetPoseParameter( "vehicle_weapon_pitch" ); - float curYaw = GetPoseParameter( "vehicle_weapon_yaw" ); - m_bInFiringCone = (fabs(curPitch - angles.x) < 1e-3) && (fabs(curYaw - angles.y) < 1e-3); - } - else - { - m_bInFiringCone = false; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const char *CPropAPC::GetTracerType( void ) -{ - return "HelicopterTracer"; -} - - -//----------------------------------------------------------------------------- -// Allows the shooter to change the impact effect of his bullets -//----------------------------------------------------------------------------- -void CPropAPC::DoImpactEffect( trace_t &tr, int nDamageType ) -{ - UTIL_ImpactTrace( &tr, nDamageType, "HelicopterImpact" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAPC::DoMuzzleFlash( void ) -{ - CEffectData data; - data.m_nEntIndex = entindex(); - data.m_nAttachmentIndex = m_nMachineGunMuzzleAttachment; - data.m_flScale = 1.0f; - DispatchEffect( "ChopperMuzzleFlash", data ); - - BaseClass::DoMuzzleFlash(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAPC::FireMachineGun( void ) -{ - if ( m_flMachineGunTime > gpGlobals->curtime ) - return; - - // If we're still firing the salvo, fire quickly - m_iMachineGunBurstLeft--; - if ( m_iMachineGunBurstLeft > 0 ) - { - m_flMachineGunTime = gpGlobals->curtime + MACHINE_GUN_BURST_TIME; - } - else - { - // Reload the salvo - m_iMachineGunBurstLeft = MACHINE_GUN_BURST_SIZE; - m_flMachineGunTime = gpGlobals->curtime + MACHINE_GUN_BURST_PAUSE_TIME; - } - - Vector vecMachineGunShootPos; - Vector vecMachineGunDir; - GetAttachment( m_nMachineGunMuzzleAttachment, vecMachineGunShootPos, &vecMachineGunDir ); - - // Fire the round - int bulletType = GetAmmoDef()->Index("AR2"); - FireBullets( 1, vecMachineGunShootPos, vecMachineGunDir, VECTOR_CONE_8DEGREES, MAX_TRACE_LENGTH, bulletType, 1 ); - DoMuzzleFlash(); - - EmitSound( "Weapon_AR2.Single" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAPC::GetRocketShootPosition( Vector *pPosition ) -{ - GetAttachment( m_nRocketAttachment, *pPosition ); -} - - -//----------------------------------------------------------------------------- -// Create a corpse -//----------------------------------------------------------------------------- -void CPropAPC::CreateCorpse( ) -{ - m_lifeState = LIFE_DEAD; - - for ( int i = 0; i < APC_MAX_GIBS; ++i ) - { - CPhysicsProp *pGib = assert_cast(CreateEntityByName( "prop_physics" )); - pGib->SetAbsOrigin( GetAbsOrigin() ); - pGib->SetAbsAngles( GetAbsAngles() ); - pGib->SetAbsVelocity( GetAbsVelocity() ); - pGib->SetModel( s_pGibModelName[i] ); - pGib->Spawn(); - pGib->SetMoveType( MOVETYPE_VPHYSICS ); - - float flMass = pGib->GetMass(); - if ( flMass < 200 ) - { - Vector vecVelocity; - pGib->GetMassCenter( &vecVelocity ); - vecVelocity -= WorldSpaceCenter(); - vecVelocity.z = fabs(vecVelocity.z); - VectorNormalize( vecVelocity ); - - // Apply a force that would make a 100kg mass travel 150 - 300 m/s - float flRandomVel = random->RandomFloat( 150, 300 ); - vecVelocity *= (100 * flRandomVel) / flMass; - vecVelocity.z += 100.0f; - AngularImpulse angImpulse = RandomAngularImpulse( -500, 500 ); - - IPhysicsObject *pObj = pGib->VPhysicsGetObject(); - if ( pObj != NULL ) - { - pObj->AddVelocity( &vecVelocity, &angImpulse ); - } - pGib->SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - } - if( hl2_episodic.GetBool() ) - { - // EP1 perf hit - pGib->Ignite( 6, false ); - } - else - { - pGib->Ignite( 60, false ); - } - } - - AddSolidFlags( FSOLID_NOT_SOLID ); - AddEffects( EF_NODRAW ); - UTIL_Remove( this ); -} - - -//----------------------------------------------------------------------------- -// Death volley -//----------------------------------------------------------------------------- -void CPropAPC::FireDying( ) -{ - if ( m_flRocketTime > gpGlobals->curtime ) - return; - - Vector vecRocketOrigin; - GetRocketShootPosition( &vecRocketOrigin ); - - Vector vecDir; - vecDir.Random( -1.0f, 1.0f ); - if ( vecDir.z < 0.0f ) - { - vecDir.z *= -1.0f; - } - - VectorNormalize( vecDir ); - - Vector vecVelocity; - VectorMultiply( vecDir, ROCKET_SPEED * random->RandomFloat( 0.75f, 1.25f ), vecVelocity ); - - QAngle angles; - VectorAngles( vecDir, angles ); - - CAPCMissile *pRocket = (CAPCMissile *) CAPCMissile::Create( vecRocketOrigin, angles, vecVelocity, this ); - float flDeathTime = random->RandomFloat( 0.3f, 0.5f ); - if ( random->RandomFloat( 0.0f, 1.0f ) < 0.3f ) - { - pRocket->ExplodeDelay( flDeathTime ); - } - else - { - pRocket->AugerDelay( flDeathTime ); - } - - // Make erratic firing - m_flRocketTime = gpGlobals->curtime + random->RandomFloat( DEATH_VOLLEY_MIN_FIRE_TIME, DEATH_VOLLEY_MAX_FIRE_TIME ); - if ( --m_iRocketSalvoLeft <= 0 ) - { - CreateCorpse(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAPC::FireRocket( void ) -{ - if ( m_flRocketTime > gpGlobals->curtime ) - return; - - // If we're still firing the salvo, fire quickly - m_iRocketSalvoLeft--; - if ( m_iRocketSalvoLeft > 0 ) - { - m_flRocketTime = gpGlobals->curtime + ROCKET_DELAY_TIME; - } - else - { - // Reload the salvo - m_iRocketSalvoLeft = ROCKET_SALVO_SIZE; - m_flRocketTime = gpGlobals->curtime + random->RandomFloat( ROCKET_MIN_BURST_PAUSE_TIME, ROCKET_MAX_BURST_PAUSE_TIME ); - } - - Vector vecRocketOrigin; - GetRocketShootPosition( &vecRocketOrigin ); - - static float s_pSide[] = { 0.966, 0.866, 0.5, -0.5, -0.866, -0.966 }; - - Vector forward; - GetVectors( &forward, NULL, NULL ); - - Vector vecDir; - CrossProduct( Vector( 0, 0, 1 ), forward, vecDir ); - vecDir.z = 1.0f; - vecDir.x *= s_pSide[m_nRocketSide]; - vecDir.y *= s_pSide[m_nRocketSide]; - if ( ++m_nRocketSide >= 6 ) - { - m_nRocketSide = 0; - } - - VectorNormalize( vecDir ); - - Vector vecVelocity; - VectorMultiply( vecDir, ROCKET_SPEED, vecVelocity ); - - QAngle angles; - VectorAngles( vecDir, angles ); - - CAPCMissile *pRocket = (CAPCMissile *)CAPCMissile::Create( vecRocketOrigin, angles, vecVelocity, this ); - pRocket->IgniteDelay(); - - if ( m_hSpecificRocketTarget ) - { - pRocket->AimAtSpecificTarget( m_hSpecificRocketTarget ); - m_hSpecificRocketTarget = NULL; - } - else if ( m_strMissileHint != NULL_STRING ) - { - pRocket->SetGuidanceHint( STRING( m_strMissileHint ) ); - } - - EmitSound( "PropAPC.FireRocket" ); - m_OnFiredMissile.FireOutput( this, this ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CPropAPC::MaxAttackRange() const -{ - return ROCKET_ATTACK_RANGE_MAX; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropAPC::OnRestore( void ) -{ - IServerVehicle *pServerVehicle = GetServerVehicle(); - if ( pServerVehicle != NULL ) - { - // Restore the passenger information we're holding on to - pServerVehicle->RestorePassengerInfo(); - } -} - -//======================================================================================================================================== -// APC FOUR WHEEL PHYSICS VEHICLE SERVER VEHICLE -//======================================================================================================================================== -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAPCFourWheelServerVehicle::NPC_AimPrimaryWeapon( Vector vecTarget ) -{ - CPropAPC *pAPC = ((CPropAPC*)m_pVehicle); - pAPC->AimPrimaryWeapon( vecTarget ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAPCFourWheelServerVehicle::NPC_AimSecondaryWeapon( Vector vecTarget ) -{ - // Add some random noise -// Vector vecOffset = vecTarget + RandomVector( -128, 128 ); -// ((CPropAPC*)m_pVehicle)->AimSecondaryWeaponAt( vecOffset ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAPCFourWheelServerVehicle::Weapon_PrimaryRanges( float *flMinRange, float *flMaxRange ) -{ - *flMinRange = MACHINE_GUN_ATTACK_RANGE_MIN; - *flMaxRange = MACHINE_GUN_ATTACK_RANGE_MAX; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAPCFourWheelServerVehicle::Weapon_SecondaryRanges( float *flMinRange, float *flMaxRange ) -{ - *flMinRange = ROCKET_ATTACK_RANGE_MIN; - *flMaxRange = ROCKET_ATTACK_RANGE_MAX; -} - -//----------------------------------------------------------------------------- -// Purpose: Return the time at which this vehicle's primary weapon can fire again -//----------------------------------------------------------------------------- -float CAPCFourWheelServerVehicle::Weapon_PrimaryCanFireAt( void ) -{ - return ((CPropAPC*)m_pVehicle)->PrimaryWeaponFireTime(); -} - -//----------------------------------------------------------------------------- -// Purpose: Return the time at which this vehicle's secondary weapon can fire again -//----------------------------------------------------------------------------- -float CAPCFourWheelServerVehicle::Weapon_SecondaryCanFireAt( void ) -{ - return ((CPropAPC*)m_pVehicle)->SecondaryWeaponFireTime(); -} - diff --git a/game/server/hl2/vehicle_apc.h b/game/server/hl2/vehicle_apc.h deleted file mode 100644 index 742f1e809..000000000 --- a/game/server/hl2/vehicle_apc.h +++ /dev/null @@ -1,162 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef VEHICLE_APC_H -#define VEHICLE_APC_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "vehicle_base.h" -#include "smoke_trail.h" - -//----------------------------------------------------------------------------- -// Purpose: Four wheel physics vehicle server vehicle with weaponry -//----------------------------------------------------------------------------- -class CAPCFourWheelServerVehicle : public CFourWheelServerVehicle -{ - typedef CFourWheelServerVehicle BaseClass; -// IServerVehicle -public: - bool NPC_HasPrimaryWeapon( void ) { return true; } - void NPC_AimPrimaryWeapon( Vector vecTarget ); - bool NPC_HasSecondaryWeapon( void ) { return true; } - void NPC_AimSecondaryWeapon( Vector vecTarget ); - - // Weaponry - void Weapon_PrimaryRanges( float *flMinRange, float *flMaxRange ); - void Weapon_SecondaryRanges( float *flMinRange, float *flMaxRange ); - float Weapon_PrimaryCanFireAt( void ); // Return the time at which this vehicle's primary weapon can fire again - float Weapon_SecondaryCanFireAt( void ); // Return the time at which this vehicle's secondary weapon can fire again -}; - - -//----------------------------------------------------------------------------- -// A driveable vehicle with a gun that shoots wherever the driver looks. -//----------------------------------------------------------------------------- -class CPropAPC : public CPropVehicleDriveable -{ - DECLARE_CLASS( CPropAPC, CPropVehicleDriveable ); -public: - // CBaseEntity - virtual void Precache( void ); - void Think( void ); - virtual void Spawn(void); - virtual void Activate(); - virtual void UpdateOnRemove( void ); - virtual void OnRestore( void ); - - // CPropVehicle - virtual void CreateServerVehicle( void ); - virtual void DriveVehicle( float flFrameTime, CUserCmd *ucmd, int iButtonsDown, int iButtonsReleased ); - virtual void ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ); - virtual Class_T ClassifyPassenger( CBaseCombatCharacter *pPassenger, Class_T defaultClassification ); - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - virtual float PassengerDamageModifier( const CTakeDamageInfo &info ); - - // Weaponry - const Vector &GetPrimaryGunOrigin( void ); - void AimPrimaryWeapon( const Vector &vecForward ); - void AimSecondaryWeaponAt( CBaseEntity *pTarget ); - float PrimaryWeaponFireTime( void ) { return m_flMachineGunTime; } - float SecondaryWeaponFireTime( void ) { return m_flRocketTime; } - float MaxAttackRange() const; - bool IsInPrimaryFiringCone() const { return m_bInFiringCone; } - - // Muzzle flashes - const char *GetTracerType( void ) ; - void DoImpactEffect( trace_t &tr, int nDamageType ); - void DoMuzzleFlash( void ); - - virtual Vector EyePosition( ); // position of eyes - Vector BodyTarget( const Vector &posSrc, bool bNoisy ); - - - virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - -private: - enum - { - MAX_SMOKE_TRAILS = 4, - MAX_EXPLOSIONS = 4, - }; - - // Should we trigger a damage effect? - bool ShouldTriggerDamageEffect( int nPrevHealth, int nEffectCount ) const; - - // Add a smoke trail since we've taken more damage - void AddSmokeTrail( const Vector &vecPos ); - - // Creates the breakable husk of an attack chopper - void CreateChopperHusk(); - - // Pow! - void ExplodeAndThrowChunk( const Vector &vecExplosionPos ); - - void Event_Killed( const CTakeDamageInfo &info ); - - // Purpose: - void GetRocketShootPosition( Vector *pPosition ); - - void FireMachineGun( void ); - void FireRocket( void ); - - // Death volley - void FireDying( ); - - // Create a corpse - void CreateCorpse( ); - - // Blows da shizzle up - void InputDestroy( inputdata_t &inputdata ); - void InputFireMissileAt( inputdata_t &inputdata ); - - void CreateAPCLaserDot( void ); - - virtual bool ShouldAttractAutoAim( CBaseEntity *pAimingEnt ); - - -private: - // Danger sounds made by the APC - float m_flDangerSoundTime; - - // handbrake after the fact to keep vehicles from rolling - float m_flHandbrakeTime; - bool m_bInitialHandbrake; - - // Damage effects - int m_nSmokeTrailCount; - - // Machine gun attacks - int m_nMachineGunMuzzleAttachment; - int m_nMachineGunBaseAttachment; - float m_flMachineGunTime; - int m_iMachineGunBurstLeft; - Vector m_vecBarrelPos; - bool m_bInFiringCone; - - // Rocket attacks - EHANDLE m_hLaserDot; - EHANDLE m_hRocketTarget; - int m_iRocketSalvoLeft; - float m_flRocketTime; - int m_nRocketAttachment; - int m_nRocketSide; - EHANDLE m_hSpecificRocketTarget; - string_t m_strMissileHint; - - COutputEvent m_OnDeath; - COutputEvent m_OnFiredMissile; - COutputEvent m_OnDamaged; - COutputEvent m_OnDamagedByPlayer; - - DECLARE_DATADESC(); -}; - -#endif // VEHICLE_APC_H - diff --git a/game/server/hl2/vehicle_cannon.cpp b/game/server/hl2/vehicle_cannon.cpp deleted file mode 100644 index 17ecb949d..000000000 --- a/game/server/hl2/vehicle_cannon.cpp +++ /dev/null @@ -1,749 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "vehicle_base.h" -#include "engine/IEngineSound.h" -#include "in_buttons.h" -#include "soundenvelope.h" -#include "soundent.h" -#include "physics_saverestore.h" -#include "vphysics/constraints.h" -#include "vcollide_parse.h" -#include "ndebugoverlay.h" -#include "npc_vehicledriver.h" -#include "hl2_player.h" -#include "explode.h" -#include "particle_smokegrenade.h" -#include "te_effect_dispatch.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CPropCannon; - -// Crane bones that have physics followers -static const char *pCannonFollowerBoneNames[] = -{ - "base", - "arm", - "platform", -}; - -#define CANNON_EXTENSION_RATE_MAX 0.01 -#define CANNON_TURN_RATE_MAX 1.2 - -#define MAX_CANNON_FLAT_REACH 1400.0 -#define MIN_CANNON_FLAT_REACH 700.0 -#define CANNON_EXTENSION_ACCEL 0.006 -#define CANNON_EXTENSION_DECEL 0.02 -#define CANNON_TURN_ACCEL 0.2 -#define CANNON_DECEL 0.5 - -#define CANNON_SLOWRAISE_TIME 5.0 - -#define CANNON_PROJECTILE_MODEL "models/props_combine/headcrabcannister01a.mdl" - -ConVar g_cannon_reloadtime( "g_cannon_reloadtime", "3", FCVAR_CHEAT | FCVAR_GAMEDLL ); -ConVar g_cannon_max_traveltime( "g_cannon_max_traveltime", "1.5", FCVAR_CHEAT | FCVAR_GAMEDLL ); -ConVar g_cannon_debug( "g_cannon_debug", "0", FCVAR_CHEAT | FCVAR_GAMEDLL ); -ConVar g_cannon_damageandradius( "g_cannon_damageandradius", "512", FCVAR_CHEAT | FCVAR_GAMEDLL ); - -// Turning stats -enum -{ - CANNON_TURNING_NOT, - CANNON_TURNING_LEFT, - CANNON_TURNING_RIGHT, -}; - -//----------------------------------------------------------------------------- -// Purpose: Crane vehicle server -//----------------------------------------------------------------------------- -class CCannonServerVehicle : public CBaseServerVehicle -{ - typedef CBaseServerVehicle BaseClass; -// IServerVehicle -public: - void GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV = NULL ); - - -protected: - CPropCannon *GetCannon( void ); -}; - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CPropCannon : public CBaseProp, public IDrivableVehicle -{ - DECLARE_CLASS( CPropCannon, CBaseProp ); -public: - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - CPropCannon( void ) - { - m_ServerVehicle.SetVehicle( this ); - } - - //IDrivableVehicle's Pure Virtuals - virtual CBaseEntity *GetDriver( void ); - virtual void ItemPostFrame( CBasePlayer *pPlayer ); - virtual void SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ); - virtual void ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ) { return; } - virtual void FinishMove( CBasePlayer *player, CUserCmd *ucmd, CMoveData *move ) { return; } - virtual bool CanEnterVehicle( CBaseEntity *pEntity ); - virtual bool CanExitVehicle( CBaseEntity *pEntity ); - virtual void SetVehicleEntryAnim( bool bOn ) { m_bEnterAnimOn = bOn; } - virtual void SetVehicleExitAnim( bool bOn, Vector vecEyeExitEndpoint ) { m_bExitAnimOn = bOn; if ( bOn ) m_vecEyeExitEndpoint = vecEyeExitEndpoint; } - virtual void EnterVehicle( CBaseCombatCharacter *pPassenger ); - virtual bool AllowBlockedExit( CBaseCombatCharacter *pPassenger, int nRole ) { return true; } - virtual bool AllowMidairExit( CBaseCombatCharacter *pPassenger, int nRole ) { return false; } - virtual void PreExitVehicle( CBaseCombatCharacter *pPassenger, int nRole ) {} - virtual void ExitVehicle( int nRole ); - virtual string_t GetVehicleScriptName() { return m_vehicleScript; } - virtual bool PassengerShouldReceiveDamage( CTakeDamageInfo &info ) { return false; } - - // If this is a vehicle, returns the vehicle interface - virtual IServerVehicle *GetServerVehicle() { return &m_ServerVehicle; } - - virtual void Precache( void ); - virtual void Spawn( void ); - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() | FCAP_IMPULSE_USE; }; - virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - virtual void Think( void ); - - virtual bool CreateVPhysics( void ); - virtual void UpdateOnRemove( void ); - - void DriveCannon( int iDriverButtons, int iButtonsPressed ); - void ResetUseKey( CBasePlayer *pPlayer ); - void InitCannonSpeeds( void ); - void RunCraneMovement( float flTime ); - void LaunchProjectile( void ); - void ProjectileExplosion( void ); - -private: - - string_t m_vehicleScript; - - // Entering / Exiting - bool m_bLocked; - - CNetworkVar( bool, m_bEnterAnimOn ); - CNetworkVar( bool, m_bExitAnimOn ); - CNetworkVector( m_vecEyeExitEndpoint ); - - CNetworkHandle( CBasePlayer, m_hPlayer ); - - COutputEvent m_playerOn; - COutputEvent m_playerOff; - - int m_iTurning; - float m_flTurn; - - // Crane arm extension / retraction - bool m_bExtending; - float m_flExtension; - float m_flExtensionRate; - - // Speeds - float m_flMaxExtensionSpeed; - float m_flMaxTurnSpeed; - float m_flExtensionAccel; - float m_flExtensionDecel; - float m_flTurnAccel; - float m_flTurnDecel; - - float m_flFlyTime; - Vector m_vCrashPoint; - - float m_flNextAttackTime; - -protected: - // Contained IServerVehicle - CCannonServerVehicle m_ServerVehicle; - - // Contained Bone Follower manager - CBoneFollowerManager m_BoneFollowerManager; -}; - -LINK_ENTITY_TO_CLASS( prop_vehicle_cannon, CPropCannon ); - -BEGIN_DATADESC( CPropCannon ) - DEFINE_KEYFIELD( m_vehicleScript, FIELD_STRING, "vehiclescript" ), - DEFINE_OUTPUT( m_playerOn, "PlayerOn" ), - DEFINE_OUTPUT( m_playerOff, "PlayerOff" ), - - DEFINE_EMBEDDED( m_BoneFollowerManager ), - - DEFINE_FIELD( m_iTurning, FIELD_INTEGER ), - DEFINE_FIELD( m_flTurn, FIELD_FLOAT ), - DEFINE_FIELD( m_hPlayer, FIELD_EHANDLE ), - - DEFINE_FIELD( m_bExtending, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flExtension, FIELD_FLOAT ), - DEFINE_FIELD( m_flExtensionRate, FIELD_FLOAT ), - - DEFINE_FIELD( m_flMaxExtensionSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_flMaxTurnSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_flExtensionAccel, FIELD_FLOAT ), - DEFINE_FIELD( m_flExtensionDecel, FIELD_FLOAT ), - - DEFINE_FIELD( m_flTurnAccel, FIELD_FLOAT ), - DEFINE_FIELD( m_flTurnDecel, FIELD_FLOAT ), - - DEFINE_FIELD( m_flFlyTime, FIELD_TIME ), - DEFINE_FIELD( m_vCrashPoint, FIELD_POSITION_VECTOR ), - - DEFINE_FIELD( m_flNextAttackTime, FIELD_TIME ), - -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST(CPropCannon, DT_PropCannon) - SendPropEHandle(SENDINFO(m_hPlayer)), - SendPropBool(SENDINFO(m_bEnterAnimOn)), - SendPropBool(SENDINFO(m_bExitAnimOn)), - SendPropVector(SENDINFO(m_vecEyeExitEndpoint), -1, SPROP_COORD), -END_SEND_TABLE(); - -//------------------------------------------------ -// Precache -//------------------------------------------------ -void CPropCannon::Precache( void ) -{ - BaseClass::Precache(); - m_ServerVehicle.Initialize( STRING( m_vehicleScript ) ); - - PrecacheModel( CANNON_PROJECTILE_MODEL ); - - PrecacheScriptSound( "HeadcrabCanister.LaunchSound" ); - PrecacheScriptSound( "HeadcrabCanister.Explosion" ); - PrecacheScriptSound( "Weapon_Mortar.Incomming" ); -} - - -//------------------------------------------------ -// Spawn -//------------------------------------------------ -void CPropCannon::Spawn( void ) -{ - Precache(); - SetModel( STRING( GetModelName() ) ); - SetCollisionGroup( COLLISION_GROUP_VEHICLE ); - - BaseClass::Spawn(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_SOLID ); - SetMoveType( MOVETYPE_NOCLIP ); - - m_takedamage = DAMAGE_EVENTS_ONLY; - - m_takedamage = DAMAGE_EVENTS_ONLY; - m_flTurn = 0; - m_flExtension = 0; - - m_flFlyTime = 0.0f; - m_flNextAttackTime = gpGlobals->curtime; - - InitCannonSpeeds(); - - SetPoseParameter( "armextensionpose", m_flExtension ); - - CreateVPhysics(); - SetNextThink( gpGlobals->curtime ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCannon::InitCannonSpeeds( void ) -{ - m_flMaxExtensionSpeed = CANNON_EXTENSION_RATE_MAX * 2; - m_flMaxTurnSpeed = CANNON_TURN_RATE_MAX * 2; - m_flExtensionAccel = CANNON_EXTENSION_ACCEL * 2; - m_flExtensionDecel = CANNON_EXTENSION_DECEL * 2; - m_flTurnAccel = CANNON_TURN_ACCEL * 2; - m_flTurnDecel = CANNON_DECEL * 2; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseEntity *CPropCannon::GetDriver( void ) -{ - return m_hPlayer; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCannon::EnterVehicle( CBaseCombatCharacter *pPassenger ) -{ - if ( pPassenger == NULL ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( pPassenger ); - if ( pPlayer != NULL ) - { - // Remove any player who may be in the vehicle at the moment - if ( m_hPlayer ) - { - ExitVehicle( VEHICLE_ROLE_DRIVER ); - } - - m_hPlayer = pPlayer; - m_playerOn.FireOutput( pPlayer, this, 0 ); - - //m_ServerVehicle.SoundStart(); - } - else - { - // NPCs not supported yet - jdw - Assert( 0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCannon::ExitVehicle( int nRole ) -{ - CBasePlayer *pPlayer = m_hPlayer; - if ( !pPlayer ) - return; - - m_hPlayer = NULL; - ResetUseKey( pPlayer ); - m_playerOff.FireOutput( pPlayer, this, 0 ); - m_bEnterAnimOn = false; - - //m_ServerVehicle.SoundShutdown( 1.0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: Return true of the player's allowed to enter / exit the vehicle -//----------------------------------------------------------------------------- -bool CPropCannon::CanEnterVehicle( CBaseEntity *pEntity ) -{ - // Prevent entering if the vehicle's being driven by an NPC - if ( GetDriver() && GetDriver() != pEntity ) - return false; - - // Prevent entering if the vehicle's locked - return ( !m_bLocked ); -} - -//----------------------------------------------------------------------------- -// Purpose: Return true of the player's allowed to enter / exit the vehicle -//----------------------------------------------------------------------------- -bool CPropCannon::CanExitVehicle( CBaseEntity *pEntity ) -{ - // Prevent exiting if the vehicle's locked, or rotating - // Adrian: Check also if I'm currently jumping in or out. - return ( !m_bLocked && (GetLocalAngularVelocity() == vec3_angle) && m_bExitAnimOn == false && m_bEnterAnimOn == false ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCannon::ResetUseKey( CBasePlayer *pPlayer ) -{ - pPlayer->m_afButtonPressed &= ~IN_USE; -} - -//----------------------------------------------------------------------------- -// Purpose: Pass player movement into the crane's driving system -//----------------------------------------------------------------------------- -void CPropCannon::SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) -{ - // If the player's entering/exiting the vehicle, prevent movement - if ( !m_bEnterAnimOn && !m_bExitAnimOn ) - { - DriveCannon( ucmd->buttons, player->m_afButtonPressed ); - } - - // Run the crane's movement - RunCraneMovement( gpGlobals->frametime ); -} - -//----------------------------------------------------------------------------- -// Purpose: Crane rotates around with +left and +right, and extends/retracts -// the cable with +forward and +back. -//----------------------------------------------------------------------------- -void CPropCannon::DriveCannon( int iDriverButtons, int iButtonsPressed ) -{ - bool bWasExtending = m_bExtending; - - // Handle rotation of the crane - if ( iDriverButtons & IN_MOVELEFT ) - { - // Try adding some randomness to make it feel shaky? - float flTurnAdd = m_flTurnAccel; - // If we're turning back on ourselves, use decel speed - if ( m_flTurn < 0 ) - { - flTurnAdd = MAX( flTurnAdd, m_flTurnDecel ); - } - - m_flTurn = UTIL_Approach( m_flMaxTurnSpeed, m_flTurn, flTurnAdd * gpGlobals->frametime ); - - m_iTurning = CANNON_TURNING_LEFT; - } - else if ( iDriverButtons & IN_MOVERIGHT ) - { - // Try adding some randomness to make it feel shaky? - float flTurnAdd = m_flTurnAccel; - // If we're turning back on ourselves, increase the rate - if ( m_flTurn > 0 ) - { - flTurnAdd = MAX( flTurnAdd, m_flTurnDecel ); - } - m_flTurn = UTIL_Approach( -m_flMaxTurnSpeed, m_flTurn, flTurnAdd * gpGlobals->frametime ); - - m_iTurning = CANNON_TURNING_RIGHT; - } - else - { - m_flTurn = UTIL_Approach( 0, m_flTurn, m_flTurnDecel * gpGlobals->frametime ); - m_iTurning = CANNON_TURNING_NOT; - } - - SetLocalAngularVelocity( QAngle(0,m_flTurn * 10,0) ); - - // Handle extension / retraction of the arm - if ( iDriverButtons & IN_FORWARD ) - { - m_flExtensionRate = UTIL_Approach( m_flMaxExtensionSpeed, m_flExtensionRate, m_flExtensionAccel * gpGlobals->frametime ); - m_bExtending = true; - } - else if ( iDriverButtons & IN_BACK ) - { - m_flExtensionRate = UTIL_Approach( -m_flMaxExtensionSpeed, m_flExtensionRate, m_flExtensionAccel * gpGlobals->frametime ); - m_bExtending = true; - } - else - { - m_flExtensionRate = UTIL_Approach( 0, m_flExtensionRate, m_flExtensionDecel * gpGlobals->frametime ); - m_bExtending = false; - } - - //Msg("Turn: %f\nExtensionRate: %f\n", m_flTurn, m_flExtensionRate ); - - //If we're holding down an attack button, update our state - if ( iButtonsPressed & (IN_ATTACK | IN_ATTACK2) ) - { - if ( m_flNextAttackTime <= gpGlobals->curtime ) - { - LaunchProjectile(); - } - } - - float flSpeedPercentage = clamp( fabs(m_flTurn) / m_flMaxTurnSpeed, 0, 1 ); - vbs_sound_update_t params; - params.Defaults(); - params.bThrottleDown = (m_iTurning != CANNON_TURNING_NOT); - params.flCurrentSpeedFraction = flSpeedPercentage; - params.flWorldSpaceSpeed = 0; - - m_ServerVehicle.SoundUpdate( params ); - - // Play sounds for arm extension / retraction - if ( m_bExtending && !bWasExtending ) - { - m_ServerVehicle.StopSound( VS_ENGINE2_STOP ); - m_ServerVehicle.PlaySound( VS_ENGINE2_START ); - } - else if ( !m_bExtending && bWasExtending ) - { - m_ServerVehicle.StopSound( VS_ENGINE2_START ); - m_ServerVehicle.PlaySound( VS_ENGINE2_STOP ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -// *pMoveData - -//----------------------------------------------------------------------------- -void CPropCannon::RunCraneMovement( float flTime ) -{ - if ( m_flExtensionRate ) - { - // Extend / Retract the crane - m_flExtension = clamp( m_flExtension + (m_flExtensionRate * 10 * flTime), 0, 2 ); - SetPoseParameter( "armextensionpose", m_flExtension ); - StudioFrameAdvance(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *player - -//----------------------------------------------------------------------------- -void CPropCannon::ItemPostFrame( CBasePlayer *player ) -{ - -} - -void CPropCannon::ProjectileExplosion( void ) -{ - ExplosionCreate( m_vCrashPoint, vec3_angle, NULL, 512, 512, false ); - - // do damage - CTakeDamageInfo info( this, this, g_cannon_damageandradius.GetInt(), DMG_BLAST ); - - info.SetDamagePosition( m_vCrashPoint ); - RadiusDamage( info, m_vCrashPoint, g_cannon_damageandradius.GetInt(), CLASS_NONE, NULL ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCannon::Think( void ) -{ - SetNextThink( gpGlobals->curtime + 0.1 ); - - if ( GetDriver() ) - { - BaseClass::Think(); - } - - if ( GetDriver() ) - { - BaseClass::Think(); - - // play enter animation - StudioFrameAdvance(); - - // If the enter or exit animation has finished, tell the server vehicle - if ( IsSequenceFinished() && (m_bExitAnimOn || m_bEnterAnimOn) ) - { - if ( m_bEnterAnimOn ) - { - // Finished entering, display the hint for using the crane - //UTIL_HudHintText( m_hPlayer, "#Valve_Hint_CraneKeys" ); - } - - GetServerVehicle()->HandleEntryExitFinish( m_bExitAnimOn, true ); - } - } - else - { - // Run the crane's movement - // RunCraneMovement( 0.1 ); - } - - // Update follower bones - m_BoneFollowerManager.UpdateBoneFollowers(this); - - if ( m_flFlyTime > 0.0f ) - { - if ( m_flFlyTime - 1.0f <= gpGlobals->curtime && m_flFlyTime - 0.8f > gpGlobals->curtime) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_STATIC; - ep.m_pSoundName = "Weapon_Mortar.Incomming"; - ep.m_flVolume = 255; - ep.m_SoundLevel = SNDLVL_180dB; - - EmitSound( filter, entindex(), ep ); - } - - if ( m_flFlyTime <= gpGlobals->curtime ) - { - if ( m_vCrashPoint != vec3_origin ) - { - ProjectileExplosion(); - } - - CEffectData data; - - data.m_vOrigin = m_vCrashPoint; - data.m_flScale = 512; - DispatchEffect( "ThumperDust", data ); - - m_flFlyTime = 0.0f; - } - } - -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCannon::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - CBasePlayer *pPlayer = ToBasePlayer( pActivator ); - if ( !pPlayer ) - return; - - ResetUseKey( pPlayer ); - - GetServerVehicle()->HandlePassengerEntry( pPlayer, (value>0) ); -} - -void CPropCannon::LaunchProjectile( void ) -{ - //ADRIANTODO: Come back to this once we get the right model and remove all the fix ups caused by temp content. - - Vector vTipPos, vTipForward, vTipRight, vUp; - - GetAttachment( "cable_tip", vTipPos, &vTipForward, &vTipRight, &vUp ); - - bool bCollided = false; - bool bInSky = false; - float gravity = -gpGlobals->frametime * 600; - Vector vOrigin = vTipPos; - Vector vVelocity = vTipRight * 2500; - - float flDistance = 0.0f; - - int iFailSafe = 0; - - while ( bCollided == false && iFailSafe < 100000 ) - { - Vector vOldOrigin = vOrigin; - vOrigin = vOrigin + vVelocity * gpGlobals->frametime; - - flDistance += (vOrigin - vOldOrigin).Length(); - - if ( g_cannon_debug.GetBool() == true ) - { - NDebugOverlay::Line( vOldOrigin, vOrigin, 0, 255, 0, true, 5 ); - } - - trace_t pm; - UTIL_TraceLine( vOldOrigin, vOrigin, MASK_SOLID, this, COLLISION_GROUP_NONE, &pm ); - - if ( pm.surface.flags & SURF_SKY || pm.allsolid == true ) - { - bInSky = true; - iFailSafe++; - } - else - { - bInSky = false; - } - - iFailSafe++; - - if ( pm.fraction != 1.0f && bInSky == false ) - { - bCollided = true; - vOrigin = pm.endpos; - - if ( g_cannon_debug.GetBool() == true ) - { - NDebugOverlay::Box( vOrigin, Vector( 256, 256, 256 ), Vector( -256, -256, -256 ), 255, 0, 0, 0, 5 ); - } - } - else - { - vVelocity[2] += gravity; - } - } - - float flTravelTime = flDistance / vVelocity.Length(); - - if ( flTravelTime > g_cannon_max_traveltime.GetFloat() ) - { - flTravelTime = g_cannon_max_traveltime.GetFloat(); - - if ( bCollided == false ) - { - vOrigin = vec3_origin; - } - } - - m_flFlyTime = gpGlobals->curtime + flTravelTime; - m_vCrashPoint = vOrigin; - - m_flNextAttackTime = gpGlobals->curtime + g_cannon_reloadtime.GetFloat(); - - EmitSound( "HeadcrabCanister.LaunchSound" ); - - UTIL_ScreenShake( GetDriver()->GetAbsOrigin(), 50.0, 150.0, 1.0, 750, SHAKE_START, true ); -} - -//======================================================================================================================================== -// CRANE VEHICLE SERVER VEHICLE -//======================================================================================================================================== -CPropCannon *CCannonServerVehicle::GetCannon( void ) -{ - return (CPropCannon*)GetDrivableVehicle(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CPropCannon::CreateVPhysics( void ) -{ - BaseClass::CreateVPhysics(); - m_BoneFollowerManager.InitBoneFollowers( this, ARRAYSIZE(pCannonFollowerBoneNames), pCannonFollowerBoneNames ); - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCannon::UpdateOnRemove( void ) -{ - m_BoneFollowerManager.DestroyBoneFollowers(); - BaseClass::UpdateOnRemove(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCannonServerVehicle::GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV /*= NULL*/ ) -{ - Assert( nRole == VEHICLE_ROLE_DRIVER ); - CBasePlayer *pPlayer = ToBasePlayer( GetDrivableVehicle()->GetDriver() ); - Assert( pPlayer ); - - *pAbsAngles = pPlayer->EyeAngles(); // yuck. this is an in/out parameter. - - float flPitchFactor = 1.0; - matrix3x4_t vehicleEyePosToWorld; - Vector vehicleEyeOrigin; - QAngle vehicleEyeAngles; - GetCannon()->GetAttachment( "vehicle_driver_eyes", vehicleEyeOrigin, vehicleEyeAngles ); - AngleMatrix( vehicleEyeAngles, vehicleEyePosToWorld ); - - // Compute the relative rotation between the unperterbed eye attachment + the eye angles - matrix3x4_t cameraToWorld; - AngleMatrix( *pAbsAngles, cameraToWorld ); - - matrix3x4_t worldToEyePos; - MatrixInvert( vehicleEyePosToWorld, worldToEyePos ); - - matrix3x4_t vehicleCameraToEyePos; - ConcatTransforms( worldToEyePos, cameraToWorld, vehicleCameraToEyePos ); - - // Now perterb the attachment point - vehicleEyeAngles.x = RemapAngleRange( PITCH_CURVE_ZERO * flPitchFactor, PITCH_CURVE_LINEAR, vehicleEyeAngles.x ); - vehicleEyeAngles.z = RemapAngleRange( ROLL_CURVE_ZERO * flPitchFactor, ROLL_CURVE_LINEAR, vehicleEyeAngles.z ); - AngleMatrix( vehicleEyeAngles, vehicleEyeOrigin, vehicleEyePosToWorld ); - - // Now treat the relative eye angles as being relative to this new, perterbed view position... - matrix3x4_t newCameraToWorld; - ConcatTransforms( vehicleEyePosToWorld, vehicleCameraToEyePos, newCameraToWorld ); - - // output new view abs angles - MatrixAngles( newCameraToWorld, *pAbsAngles ); - - // UNDONE: *pOrigin would already be correct in single player if the HandleView() on the server ran after vphysics - MatrixGetColumn( newCameraToWorld, 3, *pAbsOrigin ); -} diff --git a/game/server/hl2/vehicle_crane.cpp b/game/server/hl2/vehicle_crane.cpp deleted file mode 100644 index f325bae22..000000000 --- a/game/server/hl2/vehicle_crane.cpp +++ /dev/null @@ -1,1117 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "vehicle_base.h" -#include "engine/IEngineSound.h" -#include "in_buttons.h" -#include "soundenvelope.h" -#include "soundent.h" -#include "physics_saverestore.h" -#include "vphysics/constraints.h" -#include "vcollide_parse.h" -#include "ndebugoverlay.h" -#include "npc_vehicledriver.h" -#include "vehicle_crane.h" -#include "hl2_player.h" -#include "rumble_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define VEHICLE_HITBOX_DRIVER 1 - -extern ConVar g_debug_vehicledriver; - -// Crane spring constants -#define CRANE_SPRING_CONSTANT_HANGING 2e5f -#define CRANE_SPRING_CONSTANT_INITIAL_RAISING (CRANE_SPRING_CONSTANT_HANGING * 0.5) -#define CRANE_SPRING_CONSTANT_LOWERING 30.0f -#define CRANE_SPRING_DAMPING 2e5f -#define CRANE_SPRING_RELATIVE_DAMPING 2 - -// Crane bones that have physics followers -static const char *pCraneFollowerBoneNames[] = -{ - "base", - "arm", - "platform", -}; - -// Crane tip -LINK_ENTITY_TO_CLASS( crane_tip, CCraneTip ); - -BEGIN_DATADESC( CCraneTip ) - - DEFINE_PHYSPTR( m_pSpring ), - -END_DATADESC() - -// Crane -LINK_ENTITY_TO_CLASS( prop_vehicle_crane, CPropCrane ); - -BEGIN_DATADESC( CPropCrane ) - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Lock", InputLock ), - DEFINE_INPUTFUNC( FIELD_VOID, "Unlock", InputUnlock ), - DEFINE_INPUTFUNC( FIELD_VOID, "ForcePlayerIn", InputForcePlayerIn ), - - // Keys - DEFINE_EMBEDDED( m_ServerVehicle ), - DEFINE_EMBEDDED( m_BoneFollowerManager ), - - DEFINE_FIELD( m_hPlayer, FIELD_EHANDLE ), - DEFINE_FIELD( m_bMagnetOn, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hNPCDriver, FIELD_EHANDLE ), - DEFINE_FIELD( m_nNPCButtons, FIELD_INTEGER ), - DEFINE_FIELD( m_bLocked, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bEnterAnimOn, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bExitAnimOn, FIELD_BOOLEAN ), - DEFINE_FIELD( m_vecEyeExitEndpoint, FIELD_POSITION_VECTOR ), - DEFINE_OUTPUT( m_playerOn, "PlayerOn" ), - DEFINE_OUTPUT( m_playerOff, "PlayerOff" ), - DEFINE_FIELD( m_iTurning, FIELD_INTEGER ), - DEFINE_FIELD( m_bStartSoundAtCrossover, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flTurn, FIELD_FLOAT ), - DEFINE_FIELD( m_bExtending, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flExtension, FIELD_FLOAT ), - DEFINE_FIELD( m_flExtensionRate, FIELD_FLOAT ), - DEFINE_FIELD( m_bDropping, FIELD_BOOLEAN ), - //DEFINE_FIELD( m_flNextDangerSoundTime, FIELD_TIME ), - //DEFINE_FIELD( m_flNextCreakSound, FIELD_TIME ), - DEFINE_FIELD( m_flNextDropAllowedTime, FIELD_TIME ), - DEFINE_FIELD( m_flSlowRaiseTime, FIELD_TIME ), - DEFINE_FIELD( m_flMaxExtensionSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_flMaxTurnSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_flExtensionAccel, FIELD_FLOAT ), - DEFINE_FIELD( m_flExtensionDecel, FIELD_FLOAT ), - DEFINE_FIELD( m_flTurnAccel, FIELD_FLOAT ), - DEFINE_FIELD( m_flTurnDecel, FIELD_FLOAT ), - DEFINE_KEYFIELD( m_iszMagnetName, FIELD_STRING, "magnetname" ), - DEFINE_FIELD( m_hCraneMagnet, FIELD_EHANDLE ), - DEFINE_FIELD( m_hCraneTip, FIELD_EHANDLE ), - DEFINE_FIELD( m_hRope, FIELD_EHANDLE ), - DEFINE_PHYSPTR( m_pConstraintGroup ), - DEFINE_KEYFIELD( m_vehicleScript, FIELD_STRING, "vehiclescript" ), - -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST(CPropCrane, DT_PropCrane) - SendPropEHandle(SENDINFO(m_hPlayer)), - SendPropBool(SENDINFO(m_bMagnetOn)), - SendPropBool(SENDINFO(m_bEnterAnimOn)), - SendPropBool(SENDINFO(m_bExitAnimOn)), - SendPropVector(SENDINFO(m_vecEyeExitEndpoint), -1, SPROP_COORD), -END_SEND_TABLE(); - - -//------------------------------------------------ -// Precache -//------------------------------------------------ -void CPropCrane::Precache( void ) -{ - BaseClass::Precache(); - m_ServerVehicle.Initialize( STRING(m_vehicleScript) ); -} - - -//------------------------------------------------ -// Spawn -//------------------------------------------------ -void CPropCrane::Spawn( void ) -{ - Precache(); - SetModel( STRING( GetModelName() ) ); - SetCollisionGroup( COLLISION_GROUP_VEHICLE ); - - BaseClass::Spawn(); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_SOLID ); - SetMoveType( MOVETYPE_NOCLIP ); - - m_takedamage = DAMAGE_EVENTS_ONLY; - m_flTurn = 0; - m_flExtension = 0; - m_flNextDangerSoundTime = 0; - m_flNextCreakSound = 0; - m_flNextDropAllowedTime = 0; - m_flSlowRaiseTime = 0; - m_bDropping = false; - m_bMagnetOn = false; - - InitCraneSpeeds(); - - SetPoseParameter( "armextensionpose", m_flExtension ); - - CreateVPhysics(); - SetNextThink( gpGlobals->curtime ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCrane::Activate( void ) -{ - BaseClass::Activate(); - - // If we load a game, we don't need to set this all up again. - if ( m_hCraneMagnet ) - return; - - // Find our magnet - if ( m_iszMagnetName == NULL_STRING ) - { - Warning( "prop_vehicle_crane %s has no magnet entity specified!\n", STRING(GetEntityName()) ); - UTIL_Remove( this ); - return; - } - - m_hCraneMagnet = dynamic_cast(gEntList.FindEntityByName( NULL, STRING(m_iszMagnetName) )); - if ( !m_hCraneMagnet ) - { - Warning( "prop_vehicle_crane %s failed to find magnet %s.\n", STRING(GetEntityName()), STRING(m_iszMagnetName) ); - UTIL_Remove( this ); - return; - } - - // We want the magnet to cast a long shadow - m_hCraneMagnet->SetShadowCastDistance( 2048 ); - - // Create our constraint group - constraint_groupparams_t group; - group.Defaults(); - m_pConstraintGroup = physenv->CreateConstraintGroup( group ); - m_hCraneMagnet->SetConstraintGroup( m_pConstraintGroup ); - - // Create our crane tip - Vector vecOrigin; - QAngle vecAngles; - GetCraneTipPosition( &vecOrigin, &vecAngles ); - m_hCraneTip = CCraneTip::Create( m_hCraneMagnet, m_pConstraintGroup, vecOrigin, vecAngles ); - if ( !m_hCraneTip ) - { - UTIL_Remove( this ); - return; - } - m_pConstraintGroup->Activate(); - - // Make a rope to connect 'em - int iIndex = m_hCraneMagnet->LookupAttachment("magnetcable_a"); - m_hRope = CRopeKeyframe::Create( this, m_hCraneMagnet, 1, iIndex ); - if ( m_hRope ) - { - m_hRope->m_Width = 3; - m_hRope->m_nSegments = ROPE_MAX_SEGMENTS / 2; - m_hRope->EnableWind( false ); - m_hRope->SetupHangDistance( 0 ); - m_hRope->m_RopeLength = (m_hCraneMagnet->GetAbsOrigin() - m_hCraneTip->GetAbsOrigin()).Length() * 1.1; - } - - // Start with the magnet off - TurnMagnetOff(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CPropCrane::CreateVPhysics( void ) -{ - BaseClass::CreateVPhysics(); - m_BoneFollowerManager.InitBoneFollowers( this, ARRAYSIZE(pCraneFollowerBoneNames), pCraneFollowerBoneNames ); - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCrane::UpdateOnRemove( void ) -{ - m_BoneFollowerManager.DestroyBoneFollowers(); - BaseClass::UpdateOnRemove(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCrane::InitCraneSpeeds( void ) -{ - m_flMaxExtensionSpeed = CRANE_EXTENSION_RATE_MAX * 2; - m_flMaxTurnSpeed = CRANE_TURN_RATE_MAX * 2; - m_flExtensionAccel = CRANE_EXTENSION_ACCEL * 2; - m_flExtensionDecel = CRANE_EXTENSION_DECEL * 2; - m_flTurnAccel = CRANE_TURN_ACCEL * 2; - m_flTurnDecel = CRANE_DECEL * 2; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCrane::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - if ( ptr->hitbox == VEHICLE_HITBOX_DRIVER ) - { - if ( m_hPlayer != NULL ) - { - m_hPlayer->TakeDamage( info ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CPropCrane::OnTakeDamage( const CTakeDamageInfo &inputInfo ) -{ - //Do scaled up physics damage to the car - CTakeDamageInfo info = inputInfo; - info.ScaleDamage( 25 ); - - // reset the damage - info.SetDamage( inputInfo.GetDamage() ); - - //Check to do damage to driver - if ( m_hPlayer != NULL ) - { - //Take no damage from physics damages - if ( info.GetDamageType() & DMG_CRUSH ) - return 0; - - //Take the damage - m_hPlayer->TakeDamage( info ); - } - - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Vector CPropCrane::BodyTarget( const Vector &posSrc, bool bNoisy ) -{ - Vector shotPos; - matrix3x4_t matrix; - - int eyeAttachmentIndex = LookupAttachment("vehicle_driver_eyes"); - GetAttachment( eyeAttachmentIndex, matrix ); - MatrixGetColumn( matrix, 3, shotPos ); - - if ( bNoisy ) - { - shotPos[0] += random->RandomFloat( -8.0f, 8.0f ); - shotPos[1] += random->RandomFloat( -8.0f, 8.0f ); - shotPos[2] += random->RandomFloat( -8.0f, 8.0f ); - } - - return shotPos; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCrane::Think(void) -{ - SetNextThink( gpGlobals->curtime + 0.1 ); - - if ( GetDriver() ) - { - BaseClass::Think(); - - if ( m_hNPCDriver ) - { - GetServerVehicle()->NPC_DriveVehicle(); - } - - // play enter animation - StudioFrameAdvance(); - - // If the enter or exit animation has finished, tell the server vehicle - if ( IsSequenceFinished() && (m_bExitAnimOn || m_bEnterAnimOn) ) - { - if ( m_bEnterAnimOn ) - { - // Finished entering, display the hint for using the crane - UTIL_HudHintText( m_hPlayer, "#Valve_Hint_CraneKeys" ); - } - - GetServerVehicle()->HandleEntryExitFinish( m_bExitAnimOn, true ); - } - } - else - { - // Run the crane's movement - RunCraneMovement( 0.1 ); - } - - // Update follower bones - m_BoneFollowerManager.UpdateBoneFollowers(this); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *player - -//----------------------------------------------------------------------------- -void CPropCrane::ItemPostFrame( CBasePlayer *player ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCrane::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - CBasePlayer *pPlayer = ToBasePlayer( pActivator ); - if ( !pPlayer ) - return; - - ResetUseKey( pPlayer ); - - GetServerVehicle()->HandlePassengerEntry( pPlayer, (value>0) ); -} - -//----------------------------------------------------------------------------- -// Purpose: Return true of the player's allowed to enter / exit the vehicle -//----------------------------------------------------------------------------- -bool CPropCrane::CanEnterVehicle( CBaseEntity *pEntity ) -{ - // Prevent entering if the vehicle's being driven by an NPC - if ( GetDriver() && GetDriver() != pEntity ) - return false; - - // Prevent entering if the vehicle's locked - return ( !m_bLocked ); -} - -//----------------------------------------------------------------------------- -// Purpose: Return true of the player's allowed to enter / exit the vehicle -//----------------------------------------------------------------------------- -bool CPropCrane::CanExitVehicle( CBaseEntity *pEntity ) -{ - // Prevent exiting if the vehicle's locked, or rotating - // Adrian: Check also if I'm currently jumping in or out. - return ( !m_bLocked && (GetLocalAngularVelocity() == vec3_angle) && m_bExitAnimOn == false && m_bEnterAnimOn == false ); -} - -//----------------------------------------------------------------------------- -// Purpose: Override base class to add display -//----------------------------------------------------------------------------- -void CPropCrane::DrawDebugGeometryOverlays(void) -{ - // Draw if BBOX is on - if ( m_debugOverlays & OVERLAY_BBOX_BIT ) - { - Vector vecPoint = m_hCraneMagnet->GetAbsOrigin(); - int iIndex = m_hCraneMagnet->LookupAttachment("magnetcable_a"); - if ( iIndex >= 0 ) - { - m_hCraneMagnet->GetAttachment( iIndex, vecPoint ); - } - - NDebugOverlay::Line( m_hCraneTip->GetAbsOrigin(), vecPoint, 255,255,255, true, 0.1 ); - } - - BaseClass::DrawDebugGeometryOverlays(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCrane::EnterVehicle( CBaseCombatCharacter *pPassenger ) -{ - if ( pPassenger == NULL ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( pPassenger ); - if ( pPlayer != NULL ) - { - // Remove any player who may be in the vehicle at the moment - if ( m_hPlayer ) - { - ExitVehicle( VEHICLE_ROLE_DRIVER ); - } - - m_hPlayer = pPlayer; - m_playerOn.FireOutput( pPlayer, this, 0 ); - - m_hPlayer->RumbleEffect( RUMBLE_FLAT_BOTH, 0, RUMBLE_FLAG_LOOP ); - m_hPlayer->RumbleEffect( RUMBLE_FLAT_BOTH, 10, RUMBLE_FLAG_UPDATE_SCALE ); - - m_ServerVehicle.SoundStart(); - } - else - { - // NPCs not yet supported - jdw - Assert( 0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCrane::ExitVehicle( int nRole ) -{ - CBasePlayer *pPlayer = m_hPlayer; - if ( !pPlayer ) - return; - - m_hPlayer = NULL; - ResetUseKey( pPlayer ); - m_playerOff.FireOutput( pPlayer, this, 0 ); - m_bEnterAnimOn = false; - - m_ServerVehicle.SoundShutdown( 1.0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCrane::ResetUseKey( CBasePlayer *pPlayer ) -{ - pPlayer->m_afButtonPressed &= ~IN_USE; -} - -//----------------------------------------------------------------------------- -// Purpose: Pass player movement into the crane's driving system -//----------------------------------------------------------------------------- -void CPropCrane::SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) -{ - // If the player's entering/exiting the vehicle, prevent movement - if ( !m_bEnterAnimOn && !m_bExitAnimOn ) - { - int buttons = ucmd->buttons; - if ( !(buttons & (IN_MOVELEFT|IN_MOVERIGHT)) ) - { - if ( ucmd->sidemove < 0 ) - { - buttons |= IN_MOVELEFT; - } - else if ( ucmd->sidemove > 0 ) - { - buttons |= IN_MOVERIGHT; - } - } - DriveCrane( buttons, player->m_afButtonPressed ); - } - - // Run the crane's movement - RunCraneMovement( gpGlobals->frametime ); -} - -//----------------------------------------------------------------------------- -// Purpose: Crane rotates around with +left and +right, and extends/retracts -// the cable with +forward and +back. -//----------------------------------------------------------------------------- -void CPropCrane::DriveCrane( int iDriverButtons, int iButtonsPressed, float flNPCSteering ) -{ - bool bWasExtending = m_bExtending; - - // Handle rotation of the crane - if ( iDriverButtons & IN_MOVELEFT ) - { - // NPCs may cheat and set the steering - if ( flNPCSteering ) - { - m_flTurn = flNPCSteering; - } - else - { - // Try adding some randomness to make it feel shaky? - float flTurnAdd = m_flTurnAccel; - // If we're turning back on ourselves, use decel speed - if ( m_flTurn < 0 ) - { - flTurnAdd = MAX( flTurnAdd, m_flTurnDecel ); - } - - m_flTurn = UTIL_Approach( m_flMaxTurnSpeed, m_flTurn, flTurnAdd * gpGlobals->frametime ); - } - m_iTurning = TURNING_LEFT; - } - else if ( iDriverButtons & IN_MOVERIGHT ) - { - // NPCs may cheat and set the steering - if ( flNPCSteering ) - { - m_flTurn = flNPCSteering; - } - else - { - // Try adding some randomness to make it feel shaky? - float flTurnAdd = m_flTurnAccel; - // If we're turning back on ourselves, increase the rate - if ( m_flTurn > 0 ) - { - flTurnAdd = MAX( flTurnAdd, m_flTurnDecel ); - } - m_flTurn = UTIL_Approach( -m_flMaxTurnSpeed, m_flTurn, flTurnAdd * gpGlobals->frametime ); - } - m_iTurning = TURNING_RIGHT; - } - else - { - m_flTurn = UTIL_Approach( 0, m_flTurn, m_flTurnDecel * gpGlobals->frametime ); - m_iTurning = TURNING_NOT; - } - - if ( m_hPlayer ) - { - float maxTurn = GetMaxTurnRate(); - static float maxRumble = 0.35f; - static float minRumble = 0.1f; - float rumbleRange = maxRumble - minRumble; - float rumble; - - float factor = fabs(m_flTurn) / maxTurn; - factor = MIN( factor, 1.0f ); - rumble = minRumble + (rumbleRange * factor); - - m_hPlayer->RumbleEffect( RUMBLE_FLAT_BOTH, (int)(rumble * 100), RUMBLE_FLAG_UPDATE_SCALE ); - } - - SetLocalAngularVelocity( QAngle(0,m_flTurn * 10,0) ); - - // Handle extension / retraction of the arm - if ( iDriverButtons & IN_FORWARD ) - { - m_flExtensionRate = UTIL_Approach( m_flMaxExtensionSpeed, m_flExtensionRate, m_flExtensionAccel * gpGlobals->frametime ); - m_bExtending = true; - } - else if ( iDriverButtons & IN_BACK ) - { - m_flExtensionRate = UTIL_Approach( -m_flMaxExtensionSpeed, m_flExtensionRate, m_flExtensionAccel * gpGlobals->frametime ); - m_bExtending = true; - } - else - { - m_flExtensionRate = UTIL_Approach( 0, m_flExtensionRate, m_flExtensionDecel * gpGlobals->frametime ); - m_bExtending = false; - } - - //Msg("Turn: %f\nExtensionRate: %f\n", m_flTurn, m_flExtensionRate ); - - //If we're holding down an attack button, update our state - if ( iButtonsPressed & (IN_ATTACK | IN_ATTACK2) ) - { - // If we have something on the magnet, turn the magnet off - if ( m_hCraneMagnet->GetTotalMassAttachedObjects() ) - { - TurnMagnetOff(); - } - else if ( !m_bDropping && m_flNextDropAllowedTime < gpGlobals->curtime ) - { - TurnMagnetOn(); - - // Drop the magnet till it hits something - m_bDropping = true; - m_hCraneMagnet->ResetHasHitSomething(); - m_hCraneTip->m_pSpring->SetSpringConstant( CRANE_SPRING_CONSTANT_LOWERING ); - - m_ServerVehicle.PlaySound( VS_MISC1 ); - } - } - - float flSpeedPercentage = clamp( fabs(m_flTurn) / m_flMaxTurnSpeed, 0, 1 ); - vbs_sound_update_t params; - params.Defaults(); - params.bThrottleDown = (m_iTurning != TURNING_NOT); - params.flCurrentSpeedFraction = flSpeedPercentage; - params.flWorldSpaceSpeed = 0; - - m_ServerVehicle.SoundUpdate( params ); - - // Play sounds for arm extension / retraction - if ( m_bExtending && !bWasExtending ) - { - m_ServerVehicle.StopSound( VS_ENGINE2_STOP ); - m_ServerVehicle.PlaySound( VS_ENGINE2_START ); - } - else if ( !m_bExtending && bWasExtending ) - { - m_ServerVehicle.StopSound( VS_ENGINE2_START ); - m_ServerVehicle.PlaySound( VS_ENGINE2_STOP ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCrane::RecalculateCraneTip( void ) -{ - Vector vecOrigin; - QAngle vecAngles; - GetCraneTipPosition( &vecOrigin, &vecAngles ); - m_hCraneTip->SetAbsOrigin( vecOrigin ); - - // NOTE: We need to do this because we're not using Physics... - if ( m_hCraneTip->VPhysicsGetObject() ) - { - m_hCraneTip->VPhysicsGetObject()->UpdateShadow( vecOrigin, vec3_angle, true, TICK_INTERVAL * 2.0f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -// *pMoveData - -//----------------------------------------------------------------------------- -void CPropCrane::RunCraneMovement( float flTime ) -{ - if ( m_flExtensionRate ) - { - // Extend / Retract the crane - m_flExtension = clamp( m_flExtension + (m_flExtensionRate * 10 * flTime), 0, 2 ); - SetPoseParameter( "armextensionpose", m_flExtension ); - StudioFrameAdvance(); - } - - // Drop the magnet until it hits the ground - if ( m_bDropping ) - { - // Drop until the magnet hits something - if ( m_hCraneMagnet->HasHitSomething() ) - { - // We hit the ground, stop dropping - m_hCraneTip->m_pSpring->SetSpringConstant( CRANE_SPRING_CONSTANT_INITIAL_RAISING ); - m_bDropping = false; - m_flNextDropAllowedTime = gpGlobals->curtime + 3.0; - m_flSlowRaiseTime = gpGlobals->curtime; - - m_ServerVehicle.PlaySound( VS_MISC2 ); - } - } - else if ( (m_flSlowRaiseTime + CRANE_SLOWRAISE_TIME) > gpGlobals->curtime ) - { - float flDelta = (gpGlobals->curtime - m_flSlowRaiseTime); - - flDelta = clamp( flDelta, 0, CRANE_SLOWRAISE_TIME ); - float flCurrentSpringConstant = RemapVal( flDelta, 0, CRANE_SLOWRAISE_TIME, CRANE_SPRING_CONSTANT_INITIAL_RAISING, CRANE_SPRING_CONSTANT_HANGING ); - m_hCraneTip->m_pSpring->SetSpringConstant( flCurrentSpringConstant ); - } - - // If we've moved in any way, update the tip - if ( m_bDropping || m_flExtensionRate || GetLocalAngularVelocity() != vec3_angle ) - { - RecalculateCraneTip(); - } - - // Make danger sounds underneath the magnet if we have something attached to it - /* - if ( (m_flNextDangerSoundTime < gpGlobals->curtime) && (m_hCraneMagnet->GetTotalMassAttachedObjects() > 0) ) - { - // Trace down from the magnet and make a danger sound on the ground - trace_t tr; - Vector vecSource = m_hCraneMagnet->GetAbsOrigin(); - UTIL_TraceLine( vecSource, vecSource - Vector(0,0,2048), MASK_SOLID_BRUSHONLY, m_hCraneMagnet, 0, &tr ); - - if ( tr.fraction < 1.0 ) - { - // Make the volume proportional to the amount of mass on the magnet - float flVolume = clamp( (m_hCraneMagnet->GetTotalMassAttachedObjects() * 0.5), 100.f, 600.f ); - CSoundEnt::InsertSound( SOUND_DANGER, tr.endpos, flVolume, 0.2, this ); - - //Msg("Total: %.2f Volume: %.2f\n", m_hCraneMagnet->GetTotalMassAttachedObjects(), flVolume ); - //Vector vecVolume = Vector(flVolume,flVolume,flVolume) * 0.5; - //NDebugOverlay::Box( tr.endpos, -vecVolume, vecVolume, 255,0,0, false, 0.3 ); - //NDebugOverlay::Cross3D( tr.endpos, -Vector(10,10,10), Vector(10,10,10), 255,0,0, false, 0.3 ); - } - - m_flNextDangerSoundTime = gpGlobals->curtime + 0.3; - } - */ - - // Play creak sounds on the magnet if there's heavy weight on it - if ( (m_flNextCreakSound < gpGlobals->curtime) && (m_hCraneMagnet->GetTotalMassAttachedObjects() > 100) ) - { - // Randomly play creaks from the magnet, and increase the chance based on the turning speed - float flSpeedPercentage = clamp( fabs(m_flTurn) / m_flMaxTurnSpeed, 0, 1 ); - if ( RandomFloat(0,1) > (0.95 - (0.1 * flSpeedPercentage)) ) - { - if ( m_ServerVehicle.m_vehicleSounds.iszSound[VS_MISC4] != NULL_STRING ) - { - CPASAttenuationFilter filter( m_hCraneMagnet ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_VOICE; - ep.m_pSoundName = STRING(m_ServerVehicle.m_vehicleSounds.iszSound[VS_MISC4]); - ep.m_flVolume = 1.0f; - ep.m_SoundLevel = SNDLVL_NORM; - - CBaseEntity::EmitSound( filter, m_hCraneMagnet->entindex(), ep ); - } - m_flNextCreakSound = gpGlobals->curtime + 5.0; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCrane::TurnMagnetOn( void ) -{ - if ( !m_hCraneMagnet->IsOn() ) - { - variant_t emptyVariant; - m_hCraneMagnet->AcceptInput( "Toggle", this, this, emptyVariant, USE_TOGGLE ); - m_ServerVehicle.PlaySound( VS_MISC3 ); - - m_bMagnetOn = true; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCrane::TurnMagnetOff( void ) -{ - if ( m_hCraneMagnet->IsOn() ) - { - variant_t emptyVariant; - m_hCraneMagnet->AcceptInput( "Toggle", this, this, emptyVariant, USE_TOGGLE ); - m_ServerVehicle.PlaySound( VS_MISC3 ); - - m_bMagnetOn = false; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const Vector &CPropCrane::GetCraneTipPosition( void ) -{ - return m_hCraneTip->GetAbsOrigin(); -} - -//----------------------------------------------------------------------------- -// Purpose: Fills out the values with the desired position of the crane's tip -//----------------------------------------------------------------------------- -void CPropCrane::GetCraneTipPosition( Vector *vecOrigin, QAngle *vecAngles ) -{ - GetAttachment( "cable_tip", *vecOrigin, *vecAngles ); -} - -//----------------------------------------------------------------------------- -// Purpose: Vehicles are permanently oriented off angle for vphysics. -//----------------------------------------------------------------------------- -void CPropCrane::GetVectors(Vector* pForward, Vector* pRight, Vector* pUp) const -{ - // This call is necessary to cause m_rgflCoordinateFrame to be recomputed - const matrix3x4_t &entityToWorld = EntityToWorldTransform(); - - if (pForward != NULL) - { - MatrixGetColumn( entityToWorld, 1, *pForward ); - } - - if (pRight != NULL) - { - MatrixGetColumn( entityToWorld, 0, *pRight ); - } - - if (pUp != NULL) - { - MatrixGetColumn( entityToWorld, 2, *pUp ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseEntity *CPropCrane::GetDriver( void ) -{ - if ( m_hNPCDriver ) - return m_hNPCDriver; - - return m_hPlayer; -} - -//----------------------------------------------------------------------------- -// Purpose: Prevent the player from entering / exiting the vehicle -//----------------------------------------------------------------------------- -void CPropCrane::InputLock( inputdata_t &inputdata ) -{ - m_bLocked = true; -} - -//----------------------------------------------------------------------------- -// Purpose: Allow the player to enter / exit the vehicle -//----------------------------------------------------------------------------- -void CPropCrane::InputUnlock( inputdata_t &inputdata ) -{ - m_bLocked = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CPropCrane::InputForcePlayerIn( inputdata_t &inputdata ) -{ - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); - if ( pPlayer && !m_hPlayer ) - { - GetServerVehicle()->HandlePassengerEntry( pPlayer, 0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropCrane::SetNPCDriver( CNPC_VehicleDriver *pDriver ) -{ - m_hNPCDriver = pDriver; - m_nNPCButtons = 0; - - if ( pDriver ) - { - m_flMaxExtensionSpeed = CRANE_EXTENSION_RATE_MAX * 1.5; - m_flMaxTurnSpeed = CRANE_TURN_RATE_MAX * 1.5; - m_flExtensionAccel = CRANE_EXTENSION_ACCEL * 2; - m_flExtensionDecel = CRANE_EXTENSION_DECEL * 20; // Npcs stop quickly to make them more accurate - m_flTurnAccel = CRANE_TURN_ACCEL * 2; - m_flTurnDecel = CRANE_DECEL * 10; // Npcs stop quickly to make them more accurate - - // Set our owner entity to be the NPC, so it can path check without hitting us - SetOwnerEntity( pDriver ); - } - else - { - // Restore player crane speeds - InitCraneSpeeds(); - SetOwnerEntity( NULL ); - - // Shutdown the crane's sounds - m_ServerVehicle.SoundShutdown( 1.0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Allows us to turn off the rumble -//----------------------------------------------------------------------------- -void CPropCrane::PreExitVehicle( CBaseCombatCharacter *pPlayer, int nRole ) -{ - if ( pPlayer != m_hPlayer ) - return; - - if ( m_hPlayer != NULL ) - { - // Stop rumbles - m_hPlayer->RumbleEffect( RUMBLE_FLAT_BOTH, 0, RUMBLE_FLAG_STOP ); - } -} - -//======================================================================================================================================== -// CRANE VEHICLE SERVER VEHICLE -//======================================================================================================================================== -CPropCrane *CCraneServerVehicle::GetCrane( void ) -{ - return (CPropCrane*)GetDrivableVehicle(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCraneServerVehicle::GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV /*= NULL*/ ) -{ - // FIXME: This needs to be reconciled with the other versions of this function! - Assert( nRole == VEHICLE_ROLE_DRIVER ); - CBasePlayer *pPlayer = ToBasePlayer( GetDrivableVehicle()->GetDriver() ); - Assert( pPlayer ); - - *pAbsAngles = pPlayer->EyeAngles(); // yuck. this is an in/out parameter. - - float flPitchFactor = 1.0; - matrix3x4_t vehicleEyePosToWorld; - Vector vehicleEyeOrigin; - QAngle vehicleEyeAngles; - GetCrane()->GetAttachment( "vehicle_driver_eyes", vehicleEyeOrigin, vehicleEyeAngles ); - AngleMatrix( vehicleEyeAngles, vehicleEyePosToWorld ); - - // Compute the relative rotation between the unperterbed eye attachment + the eye angles - matrix3x4_t cameraToWorld; - AngleMatrix( *pAbsAngles, cameraToWorld ); - - matrix3x4_t worldToEyePos; - MatrixInvert( vehicleEyePosToWorld, worldToEyePos ); - - matrix3x4_t vehicleCameraToEyePos; - ConcatTransforms( worldToEyePos, cameraToWorld, vehicleCameraToEyePos ); - - // Now perterb the attachment point - vehicleEyeAngles.x = RemapAngleRange( PITCH_CURVE_ZERO * flPitchFactor, PITCH_CURVE_LINEAR, vehicleEyeAngles.x ); - vehicleEyeAngles.z = RemapAngleRange( ROLL_CURVE_ZERO * flPitchFactor, ROLL_CURVE_LINEAR, vehicleEyeAngles.z ); - AngleMatrix( vehicleEyeAngles, vehicleEyeOrigin, vehicleEyePosToWorld ); - - // Now treat the relative eye angles as being relative to this new, perterbed view position... - matrix3x4_t newCameraToWorld; - ConcatTransforms( vehicleEyePosToWorld, vehicleCameraToEyePos, newCameraToWorld ); - - // output new view abs angles - MatrixAngles( newCameraToWorld, *pAbsAngles ); - - // UNDONE: *pOrigin would already be correct in single player if the HandleView() on the server ran after vphysics - MatrixGetColumn( newCameraToWorld, 3, *pAbsOrigin ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCraneServerVehicle::NPC_SetDriver( CNPC_VehicleDriver *pDriver ) -{ - GetCrane()->SetNPCDriver( pDriver ); - - if ( pDriver ) - { - SetVehicleVolume( 1.0 ); // Vehicles driven by NPCs are louder - GetCrane()->SetSimulatedEveryTick( false ); - } - else - { - SetVehicleVolume( 0.5 ); - GetCrane()->SetSimulatedEveryTick( true ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCraneServerVehicle::NPC_DriveVehicle( void ) -{ - if ( g_debug_vehicledriver.GetInt() ) - { - if ( m_nNPCButtons ) - { - Vector vecForward, vecRight; - GetCrane()->GetVectors( &vecForward, &vecRight, NULL ); - if ( m_nNPCButtons & IN_FORWARD ) - { - NDebugOverlay::Line( GetCrane()->GetAbsOrigin(), GetCrane()->GetAbsOrigin() + vecForward * 200, 0,255,0, true, 0.1 ); - } - if ( m_nNPCButtons & IN_BACK ) - { - NDebugOverlay::Line( GetCrane()->GetAbsOrigin(), GetCrane()->GetAbsOrigin() - vecForward * 200, 0,255,0, true, 0.1 ); - } - if ( m_nNPCButtons & IN_MOVELEFT ) - { - NDebugOverlay::Line( GetCrane()->GetAbsOrigin(), GetCrane()->GetAbsOrigin() - vecRight * 200, 0,255,0, true, 0.1 ); - } - if ( m_nNPCButtons & IN_MOVERIGHT ) - { - NDebugOverlay::Line( GetCrane()->GetAbsOrigin(), GetCrane()->GetAbsOrigin() + vecRight * 200, 0,255,0, true, 0.1 ); - } - if ( m_nNPCButtons & IN_JUMP ) - { - NDebugOverlay::Box( GetCrane()->GetAbsOrigin(), -Vector(20,20,20), Vector(20,20,20), 0,255,0, true, 0.1 ); - } - } - } - - GetCrane()->DriveCrane( m_nNPCButtons, m_nNPCButtons, m_flTurnDegrees ); - - // Clear out attack buttons each frame - m_nNPCButtons &= ~IN_ATTACK; - m_nNPCButtons &= ~IN_ATTACK2; - - // Run the crane's movement - GetCrane()->RunCraneMovement( 0.1 ); -} - -//=============================================================================================================================== -// CRANE CABLE TIP -//=============================================================================================================================== -//----------------------------------------------------------------------------- -// Purpose: To by usable by the constraint system, this needs to have a phys model. -//----------------------------------------------------------------------------- -void CCraneTip::Spawn( void ) -{ - Precache(); - SetModel( "models/props_junk/cardboard_box001a.mdl" ); - AddEffects( EF_NODRAW ); - - // We don't want this to be solid, because we don't want it to collide with the hydra. - SetSolid( SOLID_VPHYSICS ); - AddSolidFlags( FSOLID_NOT_SOLID ); - VPhysicsInitShadow( false, false ); - - // Disable movement on this sucker, we're going to move him manually - SetMoveType( MOVETYPE_NONE ); - - BaseClass::Spawn(); - - m_pSpring = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCraneTip::Precache( void ) -{ - PrecacheModel( "models/props_junk/cardboard_box001a.mdl" ); - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: Activate/create the constraint -//----------------------------------------------------------------------------- -bool CCraneTip::CreateConstraint( CBaseAnimating *pCraneMagnet, IPhysicsConstraintGroup *pGroup ) -{ - IPhysicsObject *pPhysObject = VPhysicsGetObject(); - IPhysicsObject *pCraneMagnetPhysObject = pCraneMagnet->VPhysicsGetObject(); - if ( !pCraneMagnetPhysObject ) - { - Msg(" Error: Tried to create a crane_tip with a crane magnet that has no physics model.\n" ); - return false; - } - Assert( pPhysObject ); - - // Check to see if it's got an attachment point to connect to - Vector vecPoint = pCraneMagnet->GetAbsOrigin(); - int iIndex = pCraneMagnet->LookupAttachment("magnetcable_a"); - if ( iIndex >= 0 ) - { - pCraneMagnet->GetAttachment( iIndex, vecPoint ); - } - - // Create our spring - /* - constraint_lengthparams_t length; - length.Defaults(); - length.InitWorldspace( pPhysObject, pCraneMagnetPhysObject, GetAbsOrigin(), vecPoint ); - length.constraint.Defaults(); - m_pConstraint = physenv->CreateLengthConstraint( pPhysObject, pCraneMagnetPhysObject, pGroup, length ); - */ - - springparams_t spring; - spring.constant = CRANE_SPRING_CONSTANT_HANGING; - spring.damping = CRANE_SPRING_DAMPING; - spring.naturalLength = (GetAbsOrigin() - vecPoint).Length(); - spring.relativeDamping = CRANE_SPRING_RELATIVE_DAMPING; - spring.startPosition = GetAbsOrigin(); - spring.endPosition = vecPoint; - spring.useLocalPositions = false; - spring.onlyStretch = true; - m_pSpring = physenv->CreateSpring( pPhysObject, pCraneMagnetPhysObject, &spring ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Create a Hydra Impale between the hydra and the entity passed in -//----------------------------------------------------------------------------- -CCraneTip *CCraneTip::Create( CBaseAnimating *pCraneMagnet, IPhysicsConstraintGroup *pGroup, const Vector &vecOrigin, const QAngle &vecAngles ) -{ - CCraneTip *pCraneTip = (CCraneTip *)CBaseEntity::Create( "crane_tip", vecOrigin, vecAngles ); - if ( !pCraneTip ) - return NULL; - - if ( !pCraneTip->CreateConstraint( pCraneMagnet, pGroup ) ) - return NULL; - - return pCraneTip; -} - diff --git a/game/server/hl2/vehicle_crane.h b/game/server/hl2/vehicle_crane.h deleted file mode 100644 index 8a819bcbd..000000000 --- a/game/server/hl2/vehicle_crane.h +++ /dev/null @@ -1,250 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -// -// Purpose: -// -//============================================================================= - -#ifndef VEHICLE_CRANE_H -#define VEHICLE_CRANE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "physobj.h" -#include "rope.h" -#include "rope_shared.h" -#include "physics_bone_follower.h" - -#define CRANE_EXTENSION_RATE_MAX 0.01 -#define CRANE_TURN_RATE_MAX 1.2 -#define MAXIMUM_CRANE_PICKUP_MASS 10000 -#define MINIMUM_CRANE_PICKUP_MASS 500 - -#define MAX_CRANE_FLAT_REACH 1400.0 -#define MIN_CRANE_FLAT_REACH 700.0 -#define CRANE_EXTENSION_ACCEL 0.006 -#define CRANE_EXTENSION_DECEL 0.02 -#define CRANE_TURN_ACCEL 0.2 -#define CRANE_DECEL 0.5 - -#define CRANE_SLOWRAISE_TIME 5.0 - -// Turning stats -enum -{ - TURNING_NOT, - TURNING_LEFT, - TURNING_RIGHT, -}; - -class CPropCrane; - -//----------------------------------------------------------------------------- -// Purpose: This is the entity we attach to the tip of the crane and dangle the cable from -//----------------------------------------------------------------------------- -class CCraneTip : public CBaseAnimating -{ - DECLARE_CLASS( CCraneTip, CBaseAnimating ); -public: - DECLARE_DATADESC(); - - ~CCraneTip( void ) - { - if ( m_pSpring ) - { - physenv->DestroySpring( m_pSpring ); - } - } - - void Spawn( void ); - void Precache( void ); - - bool CreateConstraint( CBaseAnimating *pMagnet, IPhysicsConstraintGroup *pGroup ); - static CCraneTip *Create( CBaseAnimating *pCraneMagnet, IPhysicsConstraintGroup *pGroup, const Vector &vecOrigin, const QAngle &vecAngles ); - -public: - IPhysicsSpring *m_pSpring; -}; - -//----------------------------------------------------------------------------- -// Purpose: Crane vehicle server -//----------------------------------------------------------------------------- -class CCraneServerVehicle : public CBaseServerVehicle -{ - typedef CBaseServerVehicle BaseClass; -// IServerVehicle -public: - void GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV = NULL ); - - // NPC Driving - void NPC_SetDriver( CNPC_VehicleDriver *pDriver ); - void NPC_DriveVehicle( void ); - - virtual bool IsPassengerEntering( void ) { return false; } // NOTE: This mimics the scenario HL2 would have seen - virtual bool IsPassengerExiting( void ) { return false; } - -protected: - CPropCrane *GetCrane( void ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CPropCrane : public CBaseProp, public IDrivableVehicle -{ - DECLARE_CLASS( CPropCrane, CBaseProp ); -public: - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - CPropCrane( void ) - { - m_ServerVehicle.SetVehicle( this ); - } - - ~CPropCrane( void ) - { - physenv->DestroyConstraintGroup( m_pConstraintGroup ); - } - - // CBaseEntity - virtual void Precache( void ); - void Spawn( void ); - void Activate( void ); - void UpdateOnRemove( void ); - bool CreateVPhysics( void ); - void InitCraneSpeeds( void ); - void Think(void); - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() | FCAP_IMPULSE_USE; }; - virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - virtual void DrawDebugGeometryOverlays( void ); - - virtual bool PassengerShouldReceiveDamage( CTakeDamageInfo &info ) - { - if ( info.GetDamageType() & DMG_VEHICLE ) - return true; - - return (info.GetDamageType() & (DMG_RADIATION|DMG_BLAST) ) == 0; - } - - virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true ); - virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - - void PlayerControlInit( CBasePlayer *pPlayer ); - void PlayerControlShutdown( void ); - void ResetUseKey( CBasePlayer *pPlayer ); - - void DriveCrane( int iDriverButtons, int iButtonsPressed, float flNPCSteering = 0.0 ); - void RunCraneMovement( float flTime ); - - void TurnMagnetOn( void ); - void TurnMagnetOff( void ); - const Vector &GetCraneTipPosition( void ); - float GetExtensionRate( void ) { return m_flExtensionRate; } - float GetTurnRate( void ) { return m_flTurn; } - float GetMaxTurnRate( void ) { return m_flMaxTurnSpeed; } - CPhysMagnet *GetMagnet( void ) { return m_hCraneMagnet; } - float GetTotalMassOnCrane( void ) { return m_hCraneMagnet->GetTotalMassAttachedObjects(); } - bool IsDropping( void ) { return m_bDropping; } - - // Inputs - void InputLock( inputdata_t &inputdata ); - void InputUnlock( inputdata_t &inputdata ); - void InputForcePlayerIn( inputdata_t &inputdata ); - - // Crane handling - void GetCraneTipPosition( Vector *vecOrigin, QAngle *vecAngles ); - void RecalculateCraneTip( void ); - void GetVectors(Vector* pForward, Vector* pRight, Vector* pUp) const; - - void SetNPCDriver( CNPC_VehicleDriver *pDriver ); - -// IDrivableVehicle -public: - virtual CBaseEntity *GetDriver( void ); - virtual void ItemPostFrame( CBasePlayer *pPlayer ); - virtual void SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ); - virtual void ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ) { return; } - virtual void FinishMove( CBasePlayer *player, CUserCmd *ucmd, CMoveData *move ) { return; } - virtual bool CanEnterVehicle( CBaseEntity *pEntity ); - virtual bool CanExitVehicle( CBaseEntity *pEntity ); - virtual void SetVehicleEntryAnim( bool bOn ) { m_bEnterAnimOn = bOn; } - virtual void SetVehicleExitAnim( bool bOn, Vector vecEyeExitEndpoint ) { m_bExitAnimOn = bOn; if ( bOn ) m_vecEyeExitEndpoint = vecEyeExitEndpoint; } - virtual void EnterVehicle( CBaseCombatCharacter *pPassenger ); - - virtual bool AllowBlockedExit( CBaseCombatCharacter *pPassenger, int nRole ) { return true; } - virtual bool AllowMidairExit( CBaseCombatCharacter *pPassenger, int nRole ) { return false; } - virtual void PreExitVehicle( CBaseCombatCharacter *pPassenger, int nRole ); - virtual void ExitVehicle( int nRole ); - virtual string_t GetVehicleScriptName() { return m_vehicleScript; } - - // If this is a vehicle, returns the vehicle interface - virtual IServerVehicle *GetServerVehicle() { return &m_ServerVehicle; } - -protected: - // Contained IServerVehicle - CCraneServerVehicle m_ServerVehicle; - // Contained Bone Follower manager - CBoneFollowerManager m_BoneFollowerManager; - -private: - - CNetworkHandle( CBasePlayer, m_hPlayer ); - CNetworkVar( bool, m_bMagnetOn ); - - // NPC Driving - CHandle m_hNPCDriver; - int m_nNPCButtons; - - // Entering / Exiting - bool m_bLocked; - CNetworkVar( bool, m_bEnterAnimOn ); - CNetworkVar( bool, m_bExitAnimOn ); - CNetworkVector( m_vecEyeExitEndpoint ); - COutputEvent m_playerOn; - COutputEvent m_playerOff; - - // Turning - int m_iTurning; - bool m_bStartSoundAtCrossover; - float m_flTurn; - - // Crane arm extension / retraction - bool m_bExtending; - float m_flExtension; - float m_flExtensionRate; - - // Magnet movement - bool m_bDropping; - float m_flNextDangerSoundTime; - float m_flNextCreakSound; - float m_flNextDropAllowedTime; - float m_flSlowRaiseTime; - - // Speeds - float m_flMaxExtensionSpeed; - float m_flMaxTurnSpeed; - float m_flExtensionAccel; - float m_flExtensionDecel; - float m_flTurnAccel; - float m_flTurnDecel; - - // Cable Tip & Magnet - string_t m_iszMagnetName; - CHandle m_hCraneMagnet; - CHandle m_hCraneTip; - CHandle m_hRope; - IPhysicsConstraintGroup *m_pConstraintGroup; - - // Vehicle script filename - string_t m_vehicleScript; -}; - -#endif // VEHICLE_CRANE_H diff --git a/game/server/hl2/vehicle_jeep.cpp b/game/server/hl2/vehicle_jeep.cpp deleted file mode 100644 index 08a11c847..000000000 --- a/game/server/hl2/vehicle_jeep.cpp +++ /dev/null @@ -1,1723 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "engine/IEngineSound.h" -#include "in_buttons.h" -#include "ammodef.h" -#include "IEffects.h" -#include "beam_shared.h" -#include "weapon_gauss.h" -#include "soundenvelope.h" -#include "decals.h" -#include "soundent.h" -#include "grenade_ar2.h" -#include "te_effect_dispatch.h" -#include "hl2_player.h" -#include "ndebugoverlay.h" -#include "movevars_shared.h" -#include "bone_setup.h" -#include "ai_basenpc.h" -#include "ai_hint.h" -#include "npc_crow.h" -#include "globalstate.h" -#include "vehicle_jeep.h" -#include "eventqueue.h" -#include "rumble_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define VEHICLE_HITBOX_DRIVER 1 -#define LOCK_SPEED 10 -#define JEEP_GUN_YAW "vehicle_weapon_yaw" -#define JEEP_GUN_PITCH "vehicle_weapon_pitch" -#define JEEP_GUN_SPIN "gun_spin" -#define JEEP_GUN_SPIN_RATE 20 - -#define CANNON_MAX_UP_PITCH 20 -#define CANNON_MAX_DOWN_PITCH 20 -#define CANNON_MAX_LEFT_YAW 90 -#define CANNON_MAX_RIGHT_YAW 90 - -#define OVERTURNED_EXIT_WAITTIME 2.0f - -#define JEEP_AMMOCRATE_HITGROUP 5 - -#define JEEP_STEERING_SLOW_ANGLE 50.0f -#define JEEP_STEERING_FAST_ANGLE 15.0f - -#define JEEP_AMMO_CRATE_CLOSE_DELAY 2.0f - -#define JEEP_DELTA_LENGTH_MAX 12.0f // 1 foot -#define JEEP_FRAMETIME_MIN 1e-6 - -// Seagull perching -const char *g_pJeepThinkContext = "JeepSeagullThink"; -#define JEEP_SEAGULL_THINK_INTERVAL 10.0 // Interval between checks for seagull perches -#define JEEP_SEAGULL_POOP_INTERVAL 45.0 // Interval between checks for seagull poopage -#define JEEP_SEAGULL_HIDDEN_TIME 15.0 // Time for which the player must be hidden from the jeep for a seagull to perch -#define JEEP_SEAGULL_MAX_TIME 60.0 // Time at which a seagull will definately perch on the jeep - -ConVar sk_jeep_gauss_damage( "sk_jeep_gauss_damage", "15" ); -ConVar hud_jeephint_numentries( "hud_jeephint_numentries", "10", FCVAR_NONE ); -ConVar g_jeepexitspeed( "g_jeepexitspeed", "100", FCVAR_CHEAT ); - -extern ConVar autoaim_max_dist; -extern ConVar sv_vehicle_autoaim_scale; - - -//============================================================================= -// -// Jeep water data. -// - -BEGIN_SIMPLE_DATADESC( JeepWaterData_t ) - DEFINE_ARRAY( m_bWheelInWater, FIELD_BOOLEAN, JEEP_WHEEL_COUNT ), - DEFINE_ARRAY( m_bWheelWasInWater, FIELD_BOOLEAN, JEEP_WHEEL_COUNT ), - DEFINE_ARRAY( m_vecWheelContactPoints, FIELD_VECTOR, JEEP_WHEEL_COUNT ), - DEFINE_ARRAY( m_flNextRippleTime, FIELD_TIME, JEEP_WHEEL_COUNT ), - DEFINE_FIELD( m_bBodyInWater, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bBodyWasInWater, FIELD_BOOLEAN ), -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: Four wheel physics vehicle server vehicle with weaponry -//----------------------------------------------------------------------------- -class CJeepFourWheelServerVehicle : public CFourWheelServerVehicle -{ - typedef CFourWheelServerVehicle BaseClass; -// IServerVehicle -public: - bool NPC_HasPrimaryWeapon( void ) { return true; } - void NPC_AimPrimaryWeapon( Vector vecTarget ); - int GetExitAnimToUse( Vector &vecEyeExitEndpoint, bool &bAllPointsBlocked ); -}; - -BEGIN_DATADESC( CPropJeep ) - DEFINE_FIELD( m_bGunHasBeenCutOff, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flDangerSoundTime, FIELD_TIME ), - DEFINE_FIELD( m_nBulletType, FIELD_INTEGER ), - DEFINE_FIELD( m_bCannonCharging, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flCannonTime, FIELD_TIME ), - DEFINE_FIELD( m_flCannonChargeStartTime, FIELD_TIME ), - DEFINE_FIELD( m_vecGunOrigin, FIELD_POSITION_VECTOR ), - DEFINE_SOUNDPATCH( m_sndCannonCharge ), - DEFINE_FIELD( m_nSpinPos, FIELD_INTEGER ), - DEFINE_FIELD( m_aimYaw, FIELD_FLOAT ), - DEFINE_FIELD( m_aimPitch, FIELD_FLOAT ), - DEFINE_FIELD( m_throttleDisableTime, FIELD_TIME ), - DEFINE_FIELD( m_flHandbrakeTime, FIELD_TIME ), - DEFINE_FIELD( m_bInitialHandbrake, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flOverturnedTime, FIELD_TIME ), - DEFINE_FIELD( m_flAmmoCrateCloseTime, FIELD_TIME ), - DEFINE_FIELD( m_vecLastEyePos, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecLastEyeTarget, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecEyeSpeed, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecTargetSpeed, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_bHeadlightIsOn, FIELD_BOOLEAN ), - DEFINE_EMBEDDED( m_WaterData ), - - DEFINE_FIELD( m_iNumberOfEntries, FIELD_INTEGER ), - DEFINE_FIELD( m_nAmmoType, FIELD_INTEGER ), - - DEFINE_FIELD( m_flPlayerExitedTime, FIELD_TIME ), - DEFINE_FIELD( m_flLastSawPlayerAt, FIELD_TIME ), - DEFINE_FIELD( m_hLastPlayerInVehicle, FIELD_EHANDLE ), - DEFINE_FIELD( m_hSeagull, FIELD_EHANDLE ), - DEFINE_FIELD( m_bHasPoop, FIELD_BOOLEAN ), - - DEFINE_INPUTFUNC( FIELD_VOID, "ShowHudHint", InputShowHudHint ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartRemoveTauCannon", InputStartRemoveTauCannon ), - DEFINE_INPUTFUNC( FIELD_VOID, "FinishRemoveTauCannon", InputFinishRemoveTauCannon ), - - DEFINE_THINKFUNC( JeepSeagullThink ), -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CPropJeep, DT_PropJeep ) - SendPropBool( SENDINFO( m_bHeadlightIsOn ) ), -END_SEND_TABLE(); - -// This is overriden for the episodic jeep -#ifndef HL2_EPISODIC -LINK_ENTITY_TO_CLASS( prop_vehicle_jeep, CPropJeep ); -#endif - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CPropJeep::CPropJeep( void ) -{ - m_bHasGun = true; - m_bGunHasBeenCutOff = false; - m_bCannonCharging = false; - m_flCannonChargeStartTime = 0; - m_flCannonTime = 0; - m_nBulletType = -1; - m_flOverturnedTime = 0.0f; - m_iNumberOfEntries = 0; - - m_vecEyeSpeed.Init(); - - InitWaterData(); - - m_bUnableToFire = true; - m_flAmmoCrateCloseTime = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::CreateServerVehicle( void ) -{ - // Create our armed server vehicle - m_pServerVehicle = new CJeepFourWheelServerVehicle(); - m_pServerVehicle->SetVehicle( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::Precache( void ) -{ - UTIL_PrecacheOther( "npc_seagull" ); - - PrecacheScriptSound( "PropJeep.AmmoClose" ); - PrecacheScriptSound( "PropJeep.FireCannon" ); - PrecacheScriptSound( "PropJeep.FireChargedCannon" ); - PrecacheScriptSound( "PropJeep.AmmoOpen" ); - - PrecacheScriptSound( "Jeep.GaussCharge" ); - - PrecacheModel( GAUSS_BEAM_SPRITE ); - - BaseClass::Precache(); -} - -//------------------------------------------------ -// Spawn -//------------------------------------------------ -void CPropJeep::Spawn( void ) -{ - // Setup vehicle as a real-wheels car. - SetVehicleType( VEHICLE_TYPE_CAR_WHEELS ); - - BaseClass::Spawn(); - m_flHandbrakeTime = gpGlobals->curtime + 0.1; - m_bInitialHandbrake = false; - - m_flMinimumSpeedToEnterExit = LOCK_SPEED; - - m_nBulletType = GetAmmoDef()->Index("GaussEnergy"); - - CAmmoDef *pAmmoDef = GetAmmoDef(); - m_nAmmoType = pAmmoDef->Index("GaussEnergy"); - - if ( m_bHasGun ) - { - SetBodygroup( 1, true ); - - // Initialize pose parameters - SetPoseParameter( JEEP_GUN_YAW, 0 ); - SetPoseParameter( JEEP_GUN_PITCH, 0 ); - m_nSpinPos = 0; - SetPoseParameter( JEEP_GUN_SPIN, m_nSpinPos ); - m_aimYaw = 0; - m_aimPitch = 0; - } - else - { - SetBodygroup( 1, false ); - } - - AddSolidFlags( FSOLID_NOT_STANDABLE ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CPropJeep::Activate() -{ - BaseClass::Activate(); - - CBaseServerVehicle *pServerVehicle = dynamic_cast(GetServerVehicle()); - if ( pServerVehicle ) - { - if( pServerVehicle->GetPassenger() ) - { - // If a jeep comes back from a save game with a driver, make sure the engine rumble starts up. - pServerVehicle->StartEngineRumble(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &tr - -// nDamageType - -//----------------------------------------------------------------------------- -void CPropJeep::DoImpactEffect( trace_t &tr, int nDamageType ) -{ - //Draw our beam - DrawBeam( tr.startpos, tr.endpos, 2.4 ); - - if ( (tr.surface.flags & SURF_SKY) == false ) - { - CPVSFilter filter( tr.endpos ); - te->GaussExplosion( filter, 0.0f, tr.endpos, tr.plane.normal, 0 ); - - UTIL_ImpactTrace( &tr, m_nBulletType ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::TraceAttack( const CTakeDamageInfo &inputInfo, const Vector &vecDir, trace_t *ptr ) -{ - CTakeDamageInfo info = inputInfo; - if ( ptr->hitbox != VEHICLE_HITBOX_DRIVER ) - { - if ( inputInfo.GetDamageType() & DMG_BULLET ) - { - info.ScaleDamage( 0.0001 ); - } - } - - BaseClass::TraceAttack( info, vecDir, ptr ); -} - -//----------------------------------------------------------------------------- -// Purpose: Modifies the passenger's damage taken through us -//----------------------------------------------------------------------------- -float CPropJeep::PassengerDamageModifier( const CTakeDamageInfo &info ) -{ - if ( info.GetInflictor() && FClassnameIs( info.GetInflictor(), "hunter_flechette" ) ) - return 0.1f; - - return 1.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CPropJeep::OnTakeDamage( const CTakeDamageInfo &inputInfo ) -{ - //Do scaled up physics damage to the car - CTakeDamageInfo info = inputInfo; - info.ScaleDamage( 25 ); - - // HACKHACK: Scale up grenades until we get a better explosion/pressure damage system - if ( inputInfo.GetDamageType() & DMG_BLAST ) - { - info.SetDamageForce( inputInfo.GetDamageForce() * 10 ); - } - - VPhysicsTakeDamage( info ); - - // reset the damage - info.SetDamage( inputInfo.GetDamage() ); - - // small amounts of shock damage disrupt the car, but aren't transferred to the player - if ( info.GetDamageType() == DMG_SHOCK ) - { - if ( info.GetDamage() <= 10 ) - { - // take 10% damage and make the engine stall - info.ScaleDamage( 0.1 ); - m_throttleDisableTime = gpGlobals->curtime + 2; - } - } - - //Check to do damage to driver - if ( GetDriver() ) - { - // Never take crush damage - if ( info.GetDamageType() & DMG_CRUSH ) - return 0; - - // Scale the damage and mark that we're passing it in so the base player accepts the damage - info.ScaleDamage( PassengerDamageModifier( info ) ); - info.SetDamageType( info.GetDamageType() | DMG_VEHICLE ); - - // Deal the damage to the passenger - GetDriver()->TakeDamage( info ); - } - - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Vector CPropJeep::BodyTarget( const Vector &posSrc, bool bNoisy ) -{ - Vector shotPos; - matrix3x4_t matrix; - - int eyeAttachmentIndex = LookupAttachment("vehicle_driver_eyes"); - GetAttachment( eyeAttachmentIndex, matrix ); - MatrixGetColumn( matrix, 3, shotPos ); - - if ( bNoisy ) - { - shotPos[0] += random->RandomFloat( -8.0f, 8.0f ); - shotPos[1] += random->RandomFloat( -8.0f, 8.0f ); - shotPos[2] += random->RandomFloat( -8.0f, 8.0f ); - } - - return shotPos; -} - -//----------------------------------------------------------------------------- -// Purpose: Aim Gun at a target -//----------------------------------------------------------------------------- -void CPropJeep::AimGunAt( Vector *endPos, float flInterval ) -{ - Vector aimPos = *endPos; - - // See if the gun should be allowed to aim - if ( IsOverturned() || m_bEngineLocked || m_bHasGun == false ) - { - SetPoseParameter( JEEP_GUN_YAW, 0 ); - SetPoseParameter( JEEP_GUN_PITCH, 0 ); - SetPoseParameter( JEEP_GUN_SPIN, 0 ); - return; - - // Make the gun go limp and look "down" - Vector v_forward, v_up; - AngleVectors( GetLocalAngles(), NULL, &v_forward, &v_up ); - aimPos = WorldSpaceCenter() + ( v_forward * -32.0f ) - Vector( 0, 0, 128.0f ); - } - - matrix3x4_t gunMatrix; - GetAttachment( LookupAttachment("gun_ref"), gunMatrix ); - - // transform the enemy into gun space - Vector localEnemyPosition; - VectorITransform( aimPos, gunMatrix, localEnemyPosition ); - - // do a look at in gun space (essentially a delta-lookat) - QAngle localEnemyAngles; - VectorAngles( localEnemyPosition, localEnemyAngles ); - - // convert to +/- 180 degrees - localEnemyAngles.x = UTIL_AngleDiff( localEnemyAngles.x, 0 ); - localEnemyAngles.y = UTIL_AngleDiff( localEnemyAngles.y, 0 ); - - float targetYaw = m_aimYaw + localEnemyAngles.y; - float targetPitch = m_aimPitch + localEnemyAngles.x; - - // Constrain our angles - float newTargetYaw = clamp( targetYaw, -CANNON_MAX_LEFT_YAW, CANNON_MAX_RIGHT_YAW ); - float newTargetPitch = clamp( targetPitch, -CANNON_MAX_DOWN_PITCH, CANNON_MAX_UP_PITCH ); - - // If the angles have been clamped, we're looking outside of our valid range - if ( fabs(newTargetYaw-targetYaw) > 1e-4 || fabs(newTargetPitch-targetPitch) > 1e-4 ) - { - m_bUnableToFire = true; - } - - targetYaw = newTargetYaw; - targetPitch = newTargetPitch; - - // Exponentially approach the target - float yawSpeed = 8; - float pitchSpeed = 8; - - m_aimYaw = UTIL_Approach( targetYaw, m_aimYaw, yawSpeed ); - m_aimPitch = UTIL_Approach( targetPitch, m_aimPitch, pitchSpeed ); - - SetPoseParameter( JEEP_GUN_YAW, -m_aimYaw); - SetPoseParameter( JEEP_GUN_PITCH, -m_aimPitch ); - - InvalidateBoneCache(); - - // read back to avoid drift when hitting limits - // as long as the velocity is less than the delta between the limit and 180, this is fine. - m_aimPitch = -GetPoseParameter( JEEP_GUN_PITCH ); - m_aimYaw = -GetPoseParameter( JEEP_GUN_YAW ); - - // Now draw crosshair for actual aiming point - Vector vecMuzzle, vecMuzzleDir; - QAngle vecMuzzleAng; - - GetAttachment( "Muzzle", vecMuzzle, vecMuzzleAng ); - AngleVectors( vecMuzzleAng, &vecMuzzleDir ); - - trace_t tr; - UTIL_TraceLine( vecMuzzle, vecMuzzle + (vecMuzzleDir * MAX_TRACE_LENGTH), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - // see if we hit something, if so, adjust endPos to hit location - if ( tr.fraction < 1.0 ) - { - m_vecGunCrosshair = vecMuzzle + ( vecMuzzleDir * MAX_TRACE_LENGTH * tr.fraction ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::InitWaterData( void ) -{ - m_WaterData.m_bBodyInWater = false; - m_WaterData.m_bBodyWasInWater = false; - - for ( int iWheel = 0; iWheel < JEEP_WHEEL_COUNT; ++iWheel ) - { - m_WaterData.m_bWheelInWater[iWheel] = false; - m_WaterData.m_bWheelWasInWater[iWheel] = false; - m_WaterData.m_vecWheelContactPoints[iWheel].Init(); - m_WaterData.m_flNextRippleTime[iWheel] = 0; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::HandleWater( void ) -{ - // Only check the wheels and engine in water if we have a driver (player). - if ( !GetDriver() ) - return; - - // Check to see if we are in water. - if ( CheckWater() ) - { - for ( int iWheel = 0; iWheel < JEEP_WHEEL_COUNT; ++iWheel ) - { - // Create an entry/exit splash! - if ( m_WaterData.m_bWheelInWater[iWheel] != m_WaterData.m_bWheelWasInWater[iWheel] ) - { - CreateSplash( m_WaterData.m_vecWheelContactPoints[iWheel] ); - CreateRipple( m_WaterData.m_vecWheelContactPoints[iWheel] ); - } - - // Create ripples. - if ( m_WaterData.m_bWheelInWater[iWheel] && m_WaterData.m_bWheelWasInWater[iWheel] ) - { - if ( m_WaterData.m_flNextRippleTime[iWheel] < gpGlobals->curtime ) - { - // Stagger ripple times - m_WaterData.m_flNextRippleTime[iWheel] = gpGlobals->curtime + RandomFloat( 0.1, 0.3 ); - CreateRipple( m_WaterData.m_vecWheelContactPoints[iWheel] ); - } - } - } - } - - // Save of data from last think. - for ( int iWheel = 0; iWheel < JEEP_WHEEL_COUNT; ++iWheel ) - { - m_WaterData.m_bWheelWasInWater[iWheel] = m_WaterData.m_bWheelInWater[iWheel]; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CPropJeep::CheckWater( void ) -{ - bool bInWater = false; - - // Check all four wheels. - for ( int iWheel = 0; iWheel < JEEP_WHEEL_COUNT; ++iWheel ) - { - // Get the current wheel and get its contact point. - IPhysicsObject *pWheel = m_VehiclePhysics.GetWheel( iWheel ); - if ( !pWheel ) - continue; - - // Check to see if we hit water. - if ( pWheel->GetContactPoint( &m_WaterData.m_vecWheelContactPoints[iWheel], NULL ) ) - { - m_WaterData.m_bWheelInWater[iWheel] = ( UTIL_PointContents( m_WaterData.m_vecWheelContactPoints[iWheel] ) & MASK_WATER ) ? true : false; - if ( m_WaterData.m_bWheelInWater[iWheel] ) - { - bInWater = true; - } - } - } - - // Check the body and the BONNET. - int iEngine = LookupAttachment( "vehicle_engine" ); - Vector vecEnginePoint; - QAngle vecEngineAngles; - GetAttachment( iEngine, vecEnginePoint, vecEngineAngles ); - - m_WaterData.m_bBodyInWater = ( UTIL_PointContents( vecEnginePoint ) & MASK_WATER ) ? true : false; - if ( m_WaterData.m_bBodyInWater ) - { - if ( m_bHasPoop ) - { - RemoveAllDecals(); - m_bHasPoop = false; - } - - if ( !m_VehiclePhysics.IsEngineDisabled() ) - { - m_VehiclePhysics.SetDisableEngine( true ); - } - } - else - { - if ( m_VehiclePhysics.IsEngineDisabled() ) - { - m_VehiclePhysics.SetDisableEngine( false ); - } - } - - if ( bInWater ) - { - // Check the player's water level. - CheckWaterLevel(); - } - - return bInWater; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::CheckWaterLevel( void ) -{ - CBaseEntity *pEntity = GetDriver(); - if ( pEntity && pEntity->IsPlayer() ) - { - CBasePlayer *pPlayer = static_cast( pEntity ); - - Vector vecAttachPoint; - QAngle vecAttachAngles; - - // Check eyes. (vehicle_driver_eyes point) - int iAttachment = LookupAttachment( "vehicle_driver_eyes" ); - GetAttachment( iAttachment, vecAttachPoint, vecAttachAngles ); - - // Add the jeep's Z view offset - Vector vecUp; - AngleVectors( vecAttachAngles, NULL, NULL, &vecUp ); - vecUp.z = clamp( vecUp.z, 0.0f, vecUp.z ); - vecAttachPoint.z += r_JeepViewZHeight.GetFloat() * vecUp.z; - - bool bEyes = ( UTIL_PointContents( vecAttachPoint ) & MASK_WATER ) ? true : false; - if ( bEyes ) - { - pPlayer->SetWaterLevel( WL_Eyes ); - return; - } - - // Check waist. (vehicle_engine point -- see parent function). - if ( m_WaterData.m_bBodyInWater ) - { - pPlayer->SetWaterLevel( WL_Waist ); - return; - } - - // Check feet. (vehicle_feet_passenger0 point) - iAttachment = LookupAttachment( "vehicle_feet_passenger0" ); - GetAttachment( iAttachment, vecAttachPoint, vecAttachAngles ); - bool bFeet = ( UTIL_PointContents( vecAttachPoint ) & MASK_WATER ) ? true : false; - if ( bFeet ) - { - pPlayer->SetWaterLevel( WL_Feet ); - return; - } - - // Not in water. - pPlayer->SetWaterLevel( WL_NotInWater ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::CreateSplash( const Vector &vecPosition ) -{ - // Splash data. - CEffectData data; - data.m_fFlags = 0; - data.m_vOrigin = vecPosition; - data.m_vNormal.Init( 0.0f, 0.0f, 1.0f ); - VectorAngles( data.m_vNormal, data.m_vAngles ); - data.m_flScale = 10.0f + random->RandomFloat( 0, 2 ); - - // Create the splash.. - DispatchEffect( "watersplash", data ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::CreateRipple( const Vector &vecPosition ) -{ - // Ripple data. - CEffectData data; - data.m_fFlags = 0; - data.m_vOrigin = vecPosition; - data.m_vNormal.Init( 0.0f, 0.0f, 1.0f ); - VectorAngles( data.m_vNormal, data.m_vAngles ); - data.m_flScale = 10.0f + random->RandomFloat( 0, 2 ); - if ( GetWaterType() & CONTENTS_SLIME ) - { - data.m_fFlags |= FX_WATER_IN_SLIME; - } - - // Create the ripple. - DispatchEffect( "waterripple", data ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::Think( void ) -{ - BaseClass::Think(); - - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - - if ( m_bEngineLocked ) - { - m_bUnableToFire = true; - - if ( pPlayer != NULL ) - { - pPlayer->m_Local.m_iHideHUD |= HIDEHUD_VEHICLE_CROSSHAIR; - } - } - else if ( m_bHasGun ) - { - // Start this as false and update it again each frame - m_bUnableToFire = false; - - if ( pPlayer != NULL ) - { - pPlayer->m_Local.m_iHideHUD &= ~HIDEHUD_VEHICLE_CROSSHAIR; - } - } - - // Water!? - HandleWater(); - - SetSimulationTime( gpGlobals->curtime ); - - SetNextThink( gpGlobals->curtime ); - SetAnimatedEveryTick( true ); - - if ( !m_bInitialHandbrake ) // after initial timer expires, set the handbrake - { - m_bInitialHandbrake = true; - m_VehiclePhysics.SetHandbrake( true ); - m_VehiclePhysics.Think(); - } - - // Check overturned status. - if ( !IsOverturned() ) - { - m_flOverturnedTime = 0.0f; - } - else - { - m_flOverturnedTime += gpGlobals->frametime; - } - - // spin gun if charging cannon - //FIXME: Don't bother for E3 - if ( m_bCannonCharging ) - { - m_nSpinPos += JEEP_GUN_SPIN_RATE; - SetPoseParameter( JEEP_GUN_SPIN, m_nSpinPos ); - } - - // Aim gun based on the player view direction. - if ( m_bHasGun && m_hPlayer && !m_bExitAnimOn && !m_bEnterAnimOn ) - { - Vector vecEyeDir, vecEyePos; - m_hPlayer->EyePositionAndVectors( &vecEyePos, &vecEyeDir, NULL, NULL ); - - if( g_pGameRules->GetAutoAimMode() == AUTOAIM_ON_CONSOLE ) - { - autoaim_params_t params; - - params.m_fScale = AUTOAIM_SCALE_DEFAULT * sv_vehicle_autoaim_scale.GetFloat(); - params.m_fMaxDist = autoaim_max_dist.GetFloat(); - m_hPlayer->GetAutoaimVector( params ); - - // Use autoaim as the eye dir if there is an autoaim ent. - vecEyeDir = params.m_vecAutoAimDir; - } - - // Trace out from the player's eye point. - Vector vecEndPos = vecEyePos + ( vecEyeDir * MAX_TRACE_LENGTH ); - trace_t trace; - UTIL_TraceLine( vecEyePos, vecEndPos, MASK_SHOT, this, COLLISION_GROUP_NONE, &trace ); - - // See if we hit something, if so, adjust end position to hit location. - if ( trace.fraction < 1.0 ) - { - vecEndPos = vecEyePos + ( vecEyeDir * MAX_TRACE_LENGTH * trace.fraction ); - } - - //m_vecLookCrosshair = vecEndPos; - AimGunAt( &vecEndPos, 0.1f ); - } - - StudioFrameAdvance(); - - // If the enter or exit animation has finished, tell the server vehicle - if ( IsSequenceFinished() && (m_bExitAnimOn || m_bEnterAnimOn) ) - { - if ( m_bEnterAnimOn ) - { - m_VehiclePhysics.ReleaseHandbrake(); - StartEngine(); - - // HACKHACK: This forces the jeep to play a sound when it gets entered underwater - if ( m_VehiclePhysics.IsEngineDisabled() ) - { - CBaseServerVehicle *pServerVehicle = dynamic_cast(GetServerVehicle()); - if ( pServerVehicle ) - { - pServerVehicle->SoundStartDisabled(); - } - } - - // The first few time we get into the jeep, print the jeep help - if ( m_iNumberOfEntries < hud_jeephint_numentries.GetInt() ) - { - g_EventQueue.AddEvent( this, "ShowHudHint", 1.5f, this, this ); - } - } - - if ( hl2_episodic.GetBool() ) - { - // Set its running animation idle - if ( m_bEnterAnimOn ) - { - // Idle running - int nSequence = SelectWeightedSequence( ACT_IDLE_STIMULATED ); - if ( nSequence > ACTIVITY_NOT_AVAILABLE ) - { - SetCycle( 0 ); - m_flAnimTime = gpGlobals->curtime; - ResetSequence( nSequence ); - ResetClientsideFrame(); - } - } - } - - // If we're exiting and have had the tau cannon removed, we don't want to reset the animation - if ( hl2_episodic.GetBool() ) - { - // Reset on exit anim - GetServerVehicle()->HandleEntryExitFinish( m_bExitAnimOn, m_bExitAnimOn ); - } - else - { - GetServerVehicle()->HandleEntryExitFinish( m_bExitAnimOn, !(m_bExitAnimOn && TauCannonHasBeenCutOff()) ); - } - } - - // See if the ammo crate needs to close - if ( ( m_flAmmoCrateCloseTime < gpGlobals->curtime ) && ( GetSequence() == LookupSequence( "ammo_open" ) ) ) - { - m_flAnimTime = gpGlobals->curtime; - m_flPlaybackRate = 0.0; - SetCycle( 0 ); - ResetSequence( LookupSequence( "ammo_close" ) ); - } - else if ( ( GetSequence() == LookupSequence( "ammo_close" ) ) && IsSequenceFinished() ) - { - m_flAnimTime = gpGlobals->curtime; - m_flPlaybackRate = 0.0; - SetCycle( 0 ); - - int nSequence = SelectWeightedSequence( ACT_IDLE ); - ResetSequence( nSequence ); - - CPASAttenuationFilter sndFilter( this, "PropJeep.AmmoClose" ); - EmitSound( sndFilter, entindex(), "PropJeep.AmmoClose" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &startPos - -// &endPos - -// width - -// useMuzzle - -//----------------------------------------------------------------------------- -void CPropJeep::DrawBeam( const Vector &startPos, const Vector &endPos, float width ) -{ - //Tracer down the middle - UTIL_Tracer( startPos, endPos, 0, TRACER_DONT_USE_ATTACHMENT, 6500, false, "GaussTracer" ); - - //Draw the main beam shaft - CBeam *pBeam = CBeam::BeamCreate( GAUSS_BEAM_SPRITE, 0.5 ); - - pBeam->SetStartPos( startPos ); - pBeam->PointEntInit( endPos, this ); - pBeam->SetEndAttachment( LookupAttachment("Muzzle") ); - pBeam->SetWidth( width ); - pBeam->SetEndWidth( 0.05f ); - pBeam->SetBrightness( 255 ); - pBeam->SetColor( 255, 185+random->RandomInt( -16, 16 ), 40 ); - pBeam->RelinkBeam(); - pBeam->LiveForTime( 0.1f ); - - //Draw electric bolts along shaft - pBeam = CBeam::BeamCreate( GAUSS_BEAM_SPRITE, 3.0f ); - - pBeam->SetStartPos( startPos ); - pBeam->PointEntInit( endPos, this ); - pBeam->SetEndAttachment( LookupAttachment("Muzzle") ); - - pBeam->SetBrightness( random->RandomInt( 64, 255 ) ); - pBeam->SetColor( 255, 255, 150+random->RandomInt( 0, 64 ) ); - pBeam->RelinkBeam(); - pBeam->LiveForTime( 0.1f ); - pBeam->SetNoise( 1.6f ); - pBeam->SetEndWidth( 0.1f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::FireCannon( void ) -{ - //Don't fire again if it's been too soon - if ( m_flCannonTime > gpGlobals->curtime ) - return; - - if ( m_bUnableToFire ) - return; - - m_flCannonTime = gpGlobals->curtime + 0.2f; - m_bCannonCharging = false; - - //Find the direction the gun is pointing in - Vector aimDir; - GetCannonAim( &aimDir ); - - FireBulletsInfo_t info( 1, m_vecGunOrigin, aimDir, VECTOR_CONE_1DEGREES, MAX_TRACE_LENGTH, m_nAmmoType ); - - info.m_nFlags = FIRE_BULLETS_ALLOW_WATER_SURFACE_IMPACTS; - info.m_pAttacker = m_hPlayer; - - FireBullets( info ); - - // Register a muzzleflash for the AI - if ( m_hPlayer ) - { - m_hPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 ); - m_hPlayer->RumbleEffect( RUMBLE_PISTOL, 0, RUMBLE_FLAG_RESTART ); - } - - CPASAttenuationFilter sndFilter( this, "PropJeep.FireCannon" ); - EmitSound( sndFilter, entindex(), "PropJeep.FireCannon" ); - - // make cylinders of gun spin a bit - m_nSpinPos += JEEP_GUN_SPIN_RATE; - //SetPoseParameter( JEEP_GUN_SPIN, m_nSpinPos ); //FIXME: Don't bother with this for E3, won't look right -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::FireChargedCannon( void ) -{ - bool penetrated = false; - - m_bCannonCharging = false; - m_flCannonTime = gpGlobals->curtime + 0.5f; - - StopChargeSound(); - - CPASAttenuationFilter sndFilter( this, "PropJeep.FireChargedCannon" ); - EmitSound( sndFilter, entindex(), "PropJeep.FireChargedCannon" ); - - if( m_hPlayer ) - { - m_hPlayer->RumbleEffect( RUMBLE_357, 0, RUMBLE_FLAG_RESTART ); - } - - //Find the direction the gun is pointing in - Vector aimDir; - GetCannonAim( &aimDir ); - - Vector endPos = m_vecGunOrigin + ( aimDir * MAX_TRACE_LENGTH ); - - //Shoot a shot straight out - trace_t tr; - UTIL_TraceLine( m_vecGunOrigin, endPos, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - ClearMultiDamage(); - - //Find how much damage to do - float flChargeAmount = ( gpGlobals->curtime - m_flCannonChargeStartTime ) / MAX_GAUSS_CHARGE_TIME; - - //Clamp this - if ( flChargeAmount > 1.0f ) - { - flChargeAmount = 1.0f; - } - - //Determine the damage amount - //FIXME: Use ConVars! - float flDamage = 15 + ( ( 250 - 15 ) * flChargeAmount ); - - CBaseEntity *pHit = tr.m_pEnt; - - //Look for wall penetration - if ( tr.DidHitWorld() && !(tr.surface.flags & SURF_SKY) ) - { - //Try wall penetration - UTIL_ImpactTrace( &tr, m_nBulletType, "ImpactJeep" ); - UTIL_DecalTrace( &tr, "RedGlowFade" ); - - CPVSFilter filter( tr.endpos ); - te->GaussExplosion( filter, 0.0f, tr.endpos, tr.plane.normal, 0 ); - - Vector testPos = tr.endpos + ( aimDir * 48.0f ); - - UTIL_TraceLine( testPos, tr.endpos, MASK_SHOT, GetDriver(), COLLISION_GROUP_NONE, &tr ); - - if ( tr.allsolid == false ) - { - UTIL_DecalTrace( &tr, "RedGlowFade" ); - - penetrated = true; - } - } - else if ( pHit != NULL ) - { - CTakeDamageInfo dmgInfo( this, GetDriver(), flDamage, DMG_SHOCK ); - CalculateBulletDamageForce( &dmgInfo, GetAmmoDef()->Index("GaussEnergy"), aimDir, tr.endpos, 1.0f + flChargeAmount * 4.0f ); - - //Do direct damage to anything in our path - pHit->DispatchTraceAttack( dmgInfo, aimDir, &tr ); - } - - ApplyMultiDamage(); - - //Kick up an effect - if ( !(tr.surface.flags & SURF_SKY) ) - { - UTIL_ImpactTrace( &tr, m_nBulletType, "ImpactJeep" ); - - //Do a gauss explosion - CPVSFilter filter( tr.endpos ); - te->GaussExplosion( filter, 0.0f, tr.endpos, tr.plane.normal, 0 ); - } - - //Show the effect - DrawBeam( m_vecGunOrigin, tr.endpos, 9.6 ); - - // Register a muzzleflash for the AI - if ( m_hPlayer ) - { - m_hPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 0.5f ); - } - - //Rock the car - IPhysicsObject *pObj = VPhysicsGetObject(); - - if ( pObj != NULL ) - { - Vector shoveDir = aimDir * -( flDamage * 500.0f ); - - pObj->ApplyForceOffset( shoveDir, m_vecGunOrigin ); - } - - //Do radius damage if we didn't penetrate the wall - if ( penetrated == true ) - { - RadiusDamage( CTakeDamageInfo( this, this, flDamage, DMG_SHOCK ), tr.endpos, 200.0f, CLASS_NONE, NULL ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::ChargeCannon( void ) -{ - //Don't fire again if it's been too soon - if ( m_flCannonTime > gpGlobals->curtime ) - return; - - //See if we're starting a charge - if ( m_bCannonCharging == false ) - { - m_flCannonChargeStartTime = gpGlobals->curtime; - m_bCannonCharging = true; - - //Start charging sound - CPASAttenuationFilter filter( this ); - m_sndCannonCharge = (CSoundEnvelopeController::GetController()).SoundCreate( filter, entindex(), CHAN_STATIC, "Jeep.GaussCharge", ATTN_NORM ); - - if ( m_hPlayer ) - { - m_hPlayer->RumbleEffect( RUMBLE_FLAT_LEFT, (int)(0.1 * 100), RUMBLE_FLAG_RESTART | RUMBLE_FLAG_LOOP | RUMBLE_FLAG_INITIAL_SCALE ); - } - - assert(m_sndCannonCharge!=NULL); - if ( m_sndCannonCharge != NULL ) - { - (CSoundEnvelopeController::GetController()).Play( m_sndCannonCharge, 1.0f, 50 ); - (CSoundEnvelopeController::GetController()).SoundChangePitch( m_sndCannonCharge, 250, 3.0f ); - } - - return; - } - else - { - float flChargeAmount = ( gpGlobals->curtime - m_flCannonChargeStartTime ) / MAX_GAUSS_CHARGE_TIME; - if ( flChargeAmount > 1.0f ) - { - flChargeAmount = 1.0f; - } - - float rumble = flChargeAmount * 0.5f; - - if( m_hPlayer ) - { - m_hPlayer->RumbleEffect( RUMBLE_FLAT_LEFT, (int)(rumble * 100), RUMBLE_FLAG_UPDATE_SCALE ); - } - } - - //TODO: Add muzzle effect? - - //TODO: Check for overcharge and have the weapon simply fire or instead "decharge"? -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::StopChargeSound( void ) -{ - if ( m_sndCannonCharge != NULL ) - { - (CSoundEnvelopeController::GetController()).SoundFadeOut( m_sndCannonCharge, 0.1f ); - } - - if( m_hPlayer ) - { - m_hPlayer->RumbleEffect( RUMBLE_FLAT_LEFT, 0, RUMBLE_FLAG_STOP ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Finds the true aiming position of the gun (looks at what player -// is looking at and adjusts) -// Input : &resultDir - direction to be calculated -//----------------------------------------------------------------------------- -void CPropJeep::GetCannonAim( Vector *resultDir ) -{ - Vector muzzleOrigin; - QAngle muzzleAngles; - - GetAttachment( LookupAttachment("gun_ref"), muzzleOrigin, muzzleAngles ); - - AngleVectors( muzzleAngles, resultDir ); -} - -//----------------------------------------------------------------------------- -// Purpose: If the player uses the jeep while at the back, he gets ammo from the crate instead -//----------------------------------------------------------------------------- -void CPropJeep::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - CBasePlayer *pPlayer = ToBasePlayer( pActivator ); - - if ( pPlayer == NULL) - return; - - // Find out if the player's looking at our ammocrate hitbox - Vector vecForward; - pPlayer->EyeVectors( &vecForward, NULL, NULL ); - - trace_t tr; - Vector vecStart = pPlayer->EyePosition(); - UTIL_TraceLine( vecStart, vecStart + vecForward * 1024, MASK_SOLID | CONTENTS_DEBRIS | CONTENTS_HITBOX, pPlayer, COLLISION_GROUP_NONE, &tr ); - - if ( tr.m_pEnt == this && tr.hitgroup == JEEP_AMMOCRATE_HITGROUP ) - { - // Player's using the crate. - // Fill up his SMG ammo. - pPlayer->GiveAmmo( 300, "SMG1"); - - if ( ( GetSequence() != LookupSequence( "ammo_open" ) ) && ( GetSequence() != LookupSequence( "ammo_close" ) ) ) - { - // Open the crate - m_flAnimTime = gpGlobals->curtime; - m_flPlaybackRate = 0.0; - SetCycle( 0 ); - ResetSequence( LookupSequence( "ammo_open" ) ); - - CPASAttenuationFilter sndFilter( this, "PropJeep.AmmoOpen" ); - EmitSound( sndFilter, entindex(), "PropJeep.AmmoOpen" ); - } - - m_flAmmoCrateCloseTime = gpGlobals->curtime + JEEP_AMMO_CRATE_CLOSE_DELAY; - return; - } - - // Fall back and get in the vehicle instead - BaseClass::Use( pActivator, pCaller, useType, value ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CPropJeep::CanExitVehicle( CBaseEntity *pEntity ) -{ - return ( !m_bEnterAnimOn && !m_bExitAnimOn && !m_bLocked && (m_nSpeed <= g_jeepexitspeed.GetFloat() ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::DampenEyePosition( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles ) -{ - // Get the frametime. (Check to see if enough time has passed to warrent dampening). - float flFrameTime = gpGlobals->frametime; - if ( flFrameTime < JEEP_FRAMETIME_MIN ) - { - vecVehicleEyePos = m_vecLastEyePos; - DampenUpMotion( vecVehicleEyePos, vecVehicleEyeAngles, 0.0f ); - return; - } - - // Keep static the sideways motion. - - // Dampen forward/backward motion. - DampenForwardMotion( vecVehicleEyePos, vecVehicleEyeAngles, flFrameTime ); - - // Blend up/down motion. - DampenUpMotion( vecVehicleEyePos, vecVehicleEyeAngles, flFrameTime ); -} - -//----------------------------------------------------------------------------- -// Use the controller as follows: -// speed += ( pCoefficientsOut[0] * ( targetPos - currentPos ) + pCoefficientsOut[1] * ( targetSpeed - currentSpeed ) ) * flDeltaTime; -//----------------------------------------------------------------------------- -void CPropJeep::ComputePDControllerCoefficients( float *pCoefficientsOut, - float flFrequency, float flDampening, - float flDeltaTime ) -{ - float flKs = 9.0f * flFrequency * flFrequency; - float flKd = 4.5f * flFrequency * flDampening; - - float flScale = 1.0f / ( 1.0f + flKd * flDeltaTime + flKs * flDeltaTime * flDeltaTime ); - - pCoefficientsOut[0] = flKs * flScale; - pCoefficientsOut[1] = ( flKd + flKs * flDeltaTime ) * flScale; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::DampenForwardMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime ) -{ - // Get forward vector. - Vector vecForward; - AngleVectors( vecVehicleEyeAngles, &vecForward); - - // Simulate the eye position forward based on the data from last frame - // (assumes no acceleration - it will get that from the "spring"). - Vector vecCurrentEyePos = m_vecLastEyePos + m_vecEyeSpeed * flFrameTime; - - // Calculate target speed based on the current vehicle eye position and the last vehicle eye position and frametime. - Vector vecVehicleEyeSpeed = ( vecVehicleEyePos - m_vecLastEyeTarget ) / flFrameTime; - m_vecLastEyeTarget = vecVehicleEyePos; - - // Calculate the speed and position deltas. - Vector vecDeltaSpeed = vecVehicleEyeSpeed - m_vecEyeSpeed; - Vector vecDeltaPos = vecVehicleEyePos - vecCurrentEyePos; - - // Clamp. - if ( vecDeltaPos.Length() > JEEP_DELTA_LENGTH_MAX ) - { - float flSign = vecForward.Dot( vecVehicleEyeSpeed ) >= 0.0f ? -1.0f : 1.0f; - vecVehicleEyePos += flSign * ( vecForward * JEEP_DELTA_LENGTH_MAX ); - m_vecLastEyePos = vecVehicleEyePos; - m_vecEyeSpeed = vecVehicleEyeSpeed; - return; - } - - // Generate an updated (dampening) speed for use in next frames position extrapolation. - float flCoefficients[2]; - ComputePDControllerCoefficients( flCoefficients, r_JeepViewDampenFreq.GetFloat(), r_JeepViewDampenDamp.GetFloat(), flFrameTime ); - m_vecEyeSpeed += ( ( flCoefficients[0] * vecDeltaPos + flCoefficients[1] * vecDeltaSpeed ) * flFrameTime ); - - // Save off data for next frame. - m_vecLastEyePos = vecCurrentEyePos; - - // Move eye forward/backward. - Vector vecForwardOffset = vecForward * ( vecForward.Dot( vecDeltaPos ) ); - vecVehicleEyePos -= vecForwardOffset; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::DampenUpMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime ) -{ - // Get up vector. - Vector vecUp; - AngleVectors( vecVehicleEyeAngles, NULL, NULL, &vecUp ); - vecUp.z = clamp( vecUp.z, 0.0f, vecUp.z ); - vecVehicleEyePos.z += r_JeepViewZHeight.GetFloat() * vecUp.z; - - // NOTE: Should probably use some damped equation here. -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) -{ - // If we are overturned and hit any key - leave the vehicle (IN_USE is already handled!). - if ( m_flOverturnedTime > OVERTURNED_EXIT_WAITTIME ) - { - if ( (ucmd->buttons & (IN_FORWARD|IN_BACK|IN_MOVELEFT|IN_MOVERIGHT|IN_SPEED|IN_JUMP|IN_ATTACK|IN_ATTACK2) ) && !m_bExitAnimOn ) - { - // Can't exit yet? We're probably still moving. Swallow the keys. - if ( !CanExitVehicle(player) ) - return; - - if ( !GetServerVehicle()->HandlePassengerExit( m_hPlayer ) && ( m_hPlayer != NULL ) ) - { - m_hPlayer->PlayUseDenySound(); - } - return; - } - } - - // If the throttle is disabled or we're upside-down, don't allow throttling (including turbo) - CUserCmd tmp; - if ( ( m_throttleDisableTime > gpGlobals->curtime ) || ( IsOverturned() ) ) - { - m_bUnableToFire = true; - - tmp = (*ucmd); - tmp.buttons &= ~(IN_FORWARD|IN_BACK|IN_SPEED); - ucmd = &tmp; - } - - BaseClass::SetupMove( player, ucmd, pHelper, move ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::DriveVehicle( float flFrameTime, CUserCmd *ucmd, int iButtonsDown, int iButtonsReleased ) -{ - int iButtons = ucmd->buttons; - - //Adrian: No headlights on Superfly. -/* if ( ucmd->impulse == 100 ) - { - if (HeadlightIsOn()) - { - HeadlightTurnOff(); - } - else - { - HeadlightTurnOn(); - } - }*/ - - // Only handle the cannon if the vehicle has one - if ( m_bHasGun ) - { - // If we're holding down an attack button, update our state - if ( IsOverturned() == false ) - { - if ( iButtons & IN_ATTACK ) - { - if ( m_bCannonCharging ) - { - FireChargedCannon(); - } - else - { - FireCannon(); - } - } - else if ( iButtons & IN_ATTACK2 ) - { - ChargeCannon(); - } - } - - // If we've released our secondary button, fire off our cannon - if ( ( iButtonsReleased & IN_ATTACK2 ) && ( m_bCannonCharging ) ) - { - FireChargedCannon(); - } - } - - BaseClass::DriveVehicle( flFrameTime, ucmd, iButtonsDown, iButtonsReleased ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -// *pMoveData - -//----------------------------------------------------------------------------- -void CPropJeep::ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ) -{ - BaseClass::ProcessMovement( pPlayer, pMoveData ); - - // Create dangers sounds in front of the vehicle. - CreateDangerSounds(); -} - -//----------------------------------------------------------------------------- -// Purpose: Create danger sounds in front of the vehicle. -//----------------------------------------------------------------------------- -void CPropJeep::CreateDangerSounds( void ) -{ - QAngle dummy; - GetAttachment( "Muzzle", m_vecGunOrigin, dummy ); - - if ( m_flDangerSoundTime > gpGlobals->curtime ) - return; - - QAngle vehicleAngles = GetLocalAngles(); - Vector vecStart = GetAbsOrigin(); - Vector vecDir, vecRight; - - GetVectors( &vecDir, &vecRight, NULL ); - - const float soundDuration = 0.25; - float speed = m_VehiclePhysics.GetHLSpeed(); - - // Make danger sounds ahead of the jeep - if ( fabs(speed) > 120 ) - { - Vector vecSpot; - - float steering = m_VehiclePhysics.GetSteering(); - if ( steering != 0 ) - { - if ( speed > 0 ) - { - vecDir += vecRight * steering * 0.5; - } - else - { - vecDir -= vecRight * steering * 0.5; - } - VectorNormalize(vecDir); - } - const float radius = speed * 0.4; - - // 0.3 seconds ahead of the jeep - vecSpot = vecStart + vecDir * (speed * 1.1f); - CSoundEnt::InsertSound( SOUND_DANGER | SOUND_CONTEXT_PLAYER_VEHICLE, vecSpot, (int)radius, soundDuration, this, 0 ); - CSoundEnt::InsertSound( SOUND_PHYSICS_DANGER | SOUND_CONTEXT_PLAYER_VEHICLE, vecSpot, (int)radius, soundDuration, this, 1 ); - //NDebugOverlay::Box(vecSpot, Vector(-radius,-radius,-radius),Vector(radius,radius,radius), 255, 0, 255, 0, soundDuration); - -#if 0 - trace_t tr; - // put sounds a bit to left and right but slightly closer to Jeep to make a "cone" of sound - // in front of it - vecSpot = vecStart + vecDir * (speed * 0.75f) - vecRight * speed * 0.5; - UTIL_TraceLine( vecStart, vecSpot, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - CSoundEnt::InsertSound( SOUND_DANGER, vecSpot, 400, soundDuration, this, 1 ); - - vecSpot = vecStart + vecDir * (speed * 0.75f) + vecRight * speed * 0.5; - UTIL_TraceLine( vecStart, vecSpot, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - CSoundEnt::InsertSound( SOUND_DANGER, vecSpot, 400, soundDuration, this, 2); -#endif - } - - // Make engine sounds even when we're not going fast. - CSoundEnt::InsertSound( SOUND_PLAYER | SOUND_CONTEXT_PLAYER_VEHICLE, GetAbsOrigin(), 800, soundDuration, this, 0 ); - - m_flDangerSoundTime = gpGlobals->curtime + 0.1; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::EnterVehicle( CBaseCombatCharacter *pPassenger ) -{ - CBasePlayer *pPlayer = ToBasePlayer( pPassenger ); - if ( !pPlayer ) - return; - - CheckWater(); - BaseClass::EnterVehicle( pPassenger ); - - // Start looking for seagulls to land - m_hLastPlayerInVehicle = m_hPlayer; - SetContextThink( NULL, 0, g_pJeepThinkContext ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::ExitVehicle( int nRole ) -{ - HeadlightTurnOff(); - - BaseClass::ExitVehicle( nRole ); - - //If the player has exited, stop charging - StopChargeSound(); - m_bCannonCharging = false; - - // Remember when we last saw the player - m_flPlayerExitedTime = gpGlobals->curtime; - m_flLastSawPlayerAt = gpGlobals->curtime; - - if ( GlobalEntity_GetState( "no_seagulls_on_jeep" ) == GLOBAL_OFF ) - { - // Look for fly nodes - CHintCriteria hintCriteria; - hintCriteria.SetHintType( HINT_CROW_FLYTO_POINT ); - hintCriteria.AddIncludePosition( GetAbsOrigin(), 4500 ); - CAI_Hint *pHint = CAI_HintManager::FindHint( GetAbsOrigin(), hintCriteria ); - if ( pHint ) - { - // Start looking for seagulls to perch on me - SetContextThink( &CPropJeep::JeepSeagullThink, gpGlobals->curtime + JEEP_SEAGULL_THINK_INTERVAL, g_pJeepThinkContext ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: See if we should spawn a seagull on the jeep -//----------------------------------------------------------------------------- -void CPropJeep::JeepSeagullThink( void ) -{ - if ( !m_hLastPlayerInVehicle ) - return; - - CBaseEntity *pBlocker; - - // Do we already have a seagull? - if ( m_hSeagull ) - { - CNPC_Seagull *pSeagull = dynamic_cast( m_hSeagull.Get() ); - - if ( pSeagull ) - { - // Is he still on us? - if ( pSeagull->m_bOnJeep == true ) - { - // Make the existing seagull spawn more poop over time - if ( pSeagull->IsAlive() ) - { - AddSeagullPoop( pSeagull->GetAbsOrigin() ); - } - - SetContextThink( &CPropJeep::JeepSeagullThink, gpGlobals->curtime + JEEP_SEAGULL_POOP_INTERVAL, g_pJeepThinkContext ); - } - else - { - // Our seagull's moved off us. - m_hSeagull = NULL; - SetContextThink( &CPropJeep::JeepSeagullThink, gpGlobals->curtime + JEEP_SEAGULL_THINK_INTERVAL, g_pJeepThinkContext ); - } - } - - return; - } - - // Only spawn seagulls if we're upright and out of water - if ( m_WaterData.m_bBodyInWater || IsOverturned() ) - { - SetContextThink( &CPropJeep::JeepSeagullThink, gpGlobals->curtime + JEEP_SEAGULL_THINK_INTERVAL, g_pJeepThinkContext ); - return; - } - - // Is the player visible? - if ( FVisible( m_hLastPlayerInVehicle, MASK_SOLID_BRUSHONLY, &pBlocker ) ) - { - m_flLastSawPlayerAt = gpGlobals->curtime; - SetContextThink( &CPropJeep::JeepSeagullThink, gpGlobals->curtime + JEEP_SEAGULL_THINK_INTERVAL, g_pJeepThinkContext ); - return; - } - - // Start checking quickly - SetContextThink( &CPropJeep::JeepSeagullThink, gpGlobals->curtime + 0.2, g_pJeepThinkContext ); - - // Not taken enough time yet? - float flHiddenTime = (gpGlobals->curtime - m_flLastSawPlayerAt); - if ( flHiddenTime < JEEP_SEAGULL_HIDDEN_TIME ) - return; - - // Random chance based upon the time it's taken - float flChance = clamp( flHiddenTime / JEEP_SEAGULL_MAX_TIME, 0.0, 1.0 ); - if ( RandomFloat(0,1) < flChance ) - { - SpawnPerchedSeagull(); - - // Don't think for a while - SetContextThink( &CPropJeep::JeepSeagullThink, gpGlobals->curtime + JEEP_SEAGULL_POOP_INTERVAL, g_pJeepThinkContext ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::SpawnPerchedSeagull( void ) -{ - // Find a point on the car to sit - Vector vecOrigin; - QAngle vecAngles; - int iAttachment = Studio_FindRandomAttachment( GetModelPtr(), "seagull_perch" ); - if ( iAttachment == -1 ) - return; - - // Spawn the seagull - GetAttachment( iAttachment+1, vecOrigin, vecAngles ); - //vecOrigin.z += 16; - - CNPC_Seagull *pSeagull = (CNPC_Seagull*)CBaseEntity::Create("npc_seagull", vecOrigin, vecAngles, NULL ); - - if ( !pSeagull ) - return; - - pSeagull->AddSpawnFlags( SF_NPC_FADE_CORPSE ); - pSeagull->SetGroundEntity( this ); - pSeagull->AddFlag( FL_ONGROUND ); - pSeagull->SetOwnerEntity( this ); - pSeagull->SetMoveType( MOVETYPE_FLY ); - pSeagull->m_bOnJeep = true; - - m_hSeagull = pSeagull; - - AddSeagullPoop( vecOrigin ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &vecOrigin - -//----------------------------------------------------------------------------- -void CPropJeep::AddSeagullPoop( const Vector &vecOrigin ) -{ - // Drop some poop decals! - int iDecals = RandomInt( 1,2 ); - for ( int i = 0; i < iDecals; i++ ) - { - Vector vecPoop = vecOrigin; - - // get circular gaussian spread - float x, y, z; - do - { - x = random->RandomFloat(-0.5,0.5) + random->RandomFloat(-0.5,0.5); - y = random->RandomFloat(-0.5,0.5) + random->RandomFloat(-0.5,0.5); - z = x*x+y*y; - } while (z > 1); - vecPoop += Vector( x * 90, y * 90, 128 ); - - trace_t tr; - UTIL_TraceLine( vecPoop, vecPoop - Vector(0,0,512), MASK_SHOT, m_hSeagull, COLLISION_GROUP_NONE, &tr ); - UTIL_DecalTrace( &tr, "BirdPoop" ); - } - - m_bHasPoop = true; -} - -//----------------------------------------------------------------------------- -// Purpose: Show people how to drive! -//----------------------------------------------------------------------------- -void CPropJeep::InputShowHudHint( inputdata_t &inputdata ) -{ - CBaseServerVehicle *pServerVehicle = dynamic_cast(GetServerVehicle()); - if ( pServerVehicle ) - { - if( pServerVehicle->GetPassenger( VEHICLE_ROLE_DRIVER ) ) - { - UTIL_HudHintText( m_hPlayer, "#Valve_Hint_JeepKeys" ); - m_iNumberOfEntries++; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::InputStartRemoveTauCannon( inputdata_t &inputdata ) -{ - // Start the gun removal animation - m_flAnimTime = gpGlobals->curtime; - m_flPlaybackRate = 0.0; - SetCycle( 0 ); - ResetSequence( LookupSequence( "tau_levitate" ) ); - - m_bGunHasBeenCutOff = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::InputFinishRemoveTauCannon( inputdata_t &inputdata ) -{ - // Remove & hide the gun - SetBodygroup( 1, false ); - m_bHasGun = false; -} - -//======================================================================================================================================== -// JEEP FOUR WHEEL PHYSICS VEHICLE SERVER VEHICLE -//======================================================================================================================================== -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CJeepFourWheelServerVehicle::NPC_AimPrimaryWeapon( Vector vecTarget ) -{ - ((CPropJeep*)m_pVehicle)->AimGunAt( &vecTarget, 0.1f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &vecEyeExitEndpoint - -// Output : int -//----------------------------------------------------------------------------- -int CJeepFourWheelServerVehicle::GetExitAnimToUse( Vector &vecEyeExitEndpoint, bool &bAllPointsBlocked ) -{ - bAllPointsBlocked = false; - - if ( !m_bParsedAnimations ) - { - // Load the entry/exit animations from the vehicle - ParseEntryExitAnims(); - m_bParsedAnimations = true; - } - - CBaseAnimating *pAnimating = dynamic_cast(m_pVehicle); - // If we don't have the gun anymore, we want to get out using the "gun-less" animation - if ( pAnimating && ((CPropJeep*)m_pVehicle)->TauCannonHasBeenCutOff() ) - { - // HACK: We know the tau-cannon removed exit anim uses the first upright anim's exit details - trace_t tr; - - // Convert our offset points to worldspace ones - Vector vehicleExitOrigin = m_ExitAnimations[0].vecExitPointLocal; - QAngle vehicleExitAngles = m_ExitAnimations[0].vecExitAnglesLocal; - UTIL_ParentToWorldSpace( pAnimating, vehicleExitOrigin, vehicleExitAngles ); - - // Ensure the endpoint is clear by dropping a point down from above - vehicleExitOrigin -= VEC_VIEW; - Vector vecMove = Vector(0,0,64); - Vector vecStart = vehicleExitOrigin + vecMove; - Vector vecEnd = vehicleExitOrigin - vecMove; - UTIL_TraceHull( vecStart, vecEnd, VEC_HULL_MIN, VEC_HULL_MAX, MASK_SOLID, NULL, COLLISION_GROUP_NONE, &tr ); - - Assert( !tr.startsolid && tr.fraction < 1.0 ); - m_vecCurrentExitEndPoint = vecStart + ((vecEnd - vecStart) * tr.fraction); - vecEyeExitEndpoint = m_vecCurrentExitEndPoint + VEC_VIEW; - m_iCurrentExitAnim = 0; - return pAnimating->LookupSequence( "exit_tauremoved" ); - } - - return BaseClass::GetExitAnimToUse( vecEyeExitEndpoint, bAllPointsBlocked ); -} diff --git a/game/server/hl2/vehicle_jeep.h b/game/server/hl2/vehicle_jeep.h deleted file mode 100644 index cdceec0cf..000000000 --- a/game/server/hl2/vehicle_jeep.h +++ /dev/null @@ -1,169 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef VEHICLE_JEEP_H -#define VEHICLE_JEEP_H -#ifdef _WIN32 -#pragma once -#endif - -#include "vehicle_base.h" - -#define JEEP_WHEEL_COUNT 4 - -struct JeepWaterData_t -{ - bool m_bWheelInWater[JEEP_WHEEL_COUNT]; - bool m_bWheelWasInWater[JEEP_WHEEL_COUNT]; - Vector m_vecWheelContactPoints[JEEP_WHEEL_COUNT]; - float m_flNextRippleTime[JEEP_WHEEL_COUNT]; - bool m_bBodyInWater; - bool m_bBodyWasInWater; - - DECLARE_SIMPLE_DATADESC(); -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CPropJeep : public CPropVehicleDriveable -{ -protected: - DECLARE_CLASS( CPropJeep, CPropVehicleDriveable ); - -public: - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - CPropJeep( void ); - - // CPropVehicle - virtual void ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ); - virtual void DriveVehicle( float flFrameTime, CUserCmd *ucmd, int iButtonsDown, int iButtonsReleased ); - virtual void SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ); - virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - virtual void DampenEyePosition( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles ); - virtual bool AllowBlockedExit( CBasePlayer *pPlayer, int nRole ) { return false; } - virtual bool CanExitVehicle( CBaseEntity *pEntity ); - virtual bool IsVehicleBodyInWater() { return m_WaterData.m_bBodyInWater; } - - // Passengers do not directly receive damage from blasts or radiation damage - virtual bool PassengerShouldReceiveDamage( CTakeDamageInfo &info ) - { - if ( GetServerVehicle() && GetServerVehicle()->IsPassengerExiting() ) - return false; - - if ( info.GetDamageType() & DMG_VEHICLE ) - return true; - - return (info.GetDamageType() & (DMG_RADIATION|DMG_BLAST) ) == 0; - } - - // CBaseEntity - void Think(void); - void Precache( void ); - void Spawn( void ); - void Activate( void ); - - virtual void CreateServerVehicle( void ); - virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true ); - virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - virtual float PassengerDamageModifier( const CTakeDamageInfo &info ); - - virtual void EnterVehicle( CBaseCombatCharacter *pPassenger ); - virtual void ExitVehicle( int nRole ); - - void AimGunAt( Vector *endPos, float flInterval ); - bool TauCannonHasBeenCutOff( void ) { return m_bGunHasBeenCutOff; } - - // NPC Driving - bool NPC_HasPrimaryWeapon( void ) { return true; } - void NPC_AimPrimaryWeapon( Vector vecTarget ); - - const char *GetTracerType( void ) { return "AR2Tracer"; } - void DoImpactEffect( trace_t &tr, int nDamageType ); - - bool HeadlightIsOn( void ) { return m_bHeadlightIsOn; } - void HeadlightTurnOn( void ) { m_bHeadlightIsOn = true; } - void HeadlightTurnOff( void ) { m_bHeadlightIsOn = false; } - -private: - - void FireCannon( void ); - void ChargeCannon( void ); - void FireChargedCannon( void ); - - void DrawBeam( const Vector &startPos, const Vector &endPos, float width ); - void StopChargeSound( void ); - void GetCannonAim( Vector *resultDir ); - - void InitWaterData( void ); - void CheckWaterLevel( void ); - void CreateSplash( const Vector &vecPosition ); - void CreateRipple( const Vector &vecPosition ); - - void CreateDangerSounds( void ); - - void ComputePDControllerCoefficients( float *pCoefficientsOut, float flFrequency, float flDampening, float flDeltaTime ); - void DampenForwardMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime ); - void DampenUpMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime ); - - void JeepSeagullThink( void ); - void SpawnPerchedSeagull( void ); - void AddSeagullPoop( const Vector &vecOrigin ); - - void InputShowHudHint( inputdata_t &inputdata ); - void InputStartRemoveTauCannon( inputdata_t &inputdata ); - void InputFinishRemoveTauCannon( inputdata_t &inputdata ); - -protected: - - virtual void HandleWater( void ); - bool CheckWater( void ); - - bool m_bGunHasBeenCutOff; - float m_flDangerSoundTime; - int m_nBulletType; - bool m_bCannonCharging; - float m_flCannonTime; - float m_flCannonChargeStartTime; - Vector m_vecGunOrigin; - CSoundPatch *m_sndCannonCharge; - int m_nSpinPos; - float m_aimYaw; - float m_aimPitch; - float m_throttleDisableTime; - float m_flAmmoCrateCloseTime; - - // handbrake after the fact to keep vehicles from rolling - float m_flHandbrakeTime; - bool m_bInitialHandbrake; - - float m_flOverturnedTime; - - Vector m_vecLastEyePos; - Vector m_vecLastEyeTarget; - Vector m_vecEyeSpeed; - Vector m_vecTargetSpeed; - - JeepWaterData_t m_WaterData; - - int m_iNumberOfEntries; - int m_nAmmoType; - - // Seagull perching - float m_flPlayerExitedTime; // Time at which the player last left this vehicle - float m_flLastSawPlayerAt; // Time at which we last saw the player - EHANDLE m_hLastPlayerInVehicle; - EHANDLE m_hSeagull; - bool m_bHasPoop; - - CNetworkVar( bool, m_bHeadlightIsOn ); -}; - -#endif // VEHICLE_JEEP_H diff --git a/game/server/hl2/vehicle_jetski.cpp b/game/server/hl2/vehicle_jetski.cpp deleted file mode 100644 index 2c14ae4ba..000000000 --- a/game/server/hl2/vehicle_jetski.cpp +++ /dev/null @@ -1,552 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "vehicle_base.h" -#include "engine/IEngineSound.h" -#include "in_buttons.h" -#include "ammodef.h" -#include "IEffects.h" -#include "beam_shared.h" -#include "weapon_gauss.h" -#include "soundenvelope.h" -#include "decals.h" -#include "soundent.h" -#include "te_effect_dispatch.h" - -#define VEHICLE_HITBOX_DRIVER 1 - -#define JETSKI_SHOCK_LENGTH_LONG2 0.35f // -#define JETSKI_SHOCK_LENGTH_LONG 0.25f // meters (about 12 inches) -#define JETSKI_SHOCK_LENGTH_REST 0.15f // meters (about 8 inches) -#define JETSKI_SHOCK_LENGTH_SHORT 0.1f // meters (about 4 inches) - -#define JETSKI_PITCH_AND_ROLL_RATE 0.02f - -#define JETSKI_FRICTION_MIN 0.3f -#define JETSKI_FRICTION_MAX 0.8f - -#define JETSKI_SPLASH_DISTANCE 40.0f -#define JETSKI_SPLASH_SPRAY 1 -#define JETSKI_SPLASH_SPRAY_SIZE 2.0f -#define JETSKI_SPLASH_GURGLE 2 -#define JETSKI_SPLASH_GURGLE_SIZE 8.0f -#define JETSKI_SPLASH_RIPPLE 3 -#define JETSKI_SPLASH_RIPPLE_SIZE 10.0f - -#define JETSKI_DRAG_NO_THRUST_IN_WATER 10.0f -#define JETSKI_DRAG_NO_THRUST_ON_WATER 30.0f -#define JETSKI_DRAG_LEAN_ADD 10.0f -#define JETSKI_DRAG_IN_REVERSE 10.0f -#define JETSKI_DRAG_IN_THRUST 5.0f - -#define JETSKI_STEERING_EPS 0.01f -#define JETSKI_STEERING_IN_PLACE 90.0f -#define JETSKI_STEERING_NORMAL 45.0f -#define JETSKI_STEERING_LEAN 60.0f - -#define JETSKI_ROTATE_IN_PLACE_RATIO 0.35f - -class CPropJetski : public CPropVehicleDriveable -{ - DECLARE_CLASS( CPropJetski, CPropVehicleDriveable ); - DECLARE_DATADESC(); - -public: - - // CPropVehicle - virtual void ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ); - virtual void DriveVehicle( CBasePlayer *pPlayer, CUserCmd *ucmd ); - virtual void SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ); - - // CBaseEntity - void Think(void); - void Precache( void ); - void Spawn( void ); - - virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - -private: - - void OnTurn( CUserCmd *ucmd ); - void OnSpeed( CUserCmd *ucmd ); - void UpdateTurnAndSpeed( void ); - - void CreateSplash( int nSplashType ); - - bool UpdateLean( CUserCmd *ucmd ); - float CalculateFriction( CUserCmd *ucmd ); - float CalculateDrag( CUserCmd *ucmd ); - -private: - - float m_flSpringLengthApproach[4]; // - float m_flFrictionWheels[4]; - - float m_flHandbrakeTime; // handbrake after the fact to keep vehicles from rolling - bool m_bInitialHandbrake; - - float m_springLen[4]; - IPhysicsVehicleController *m_pVehicle; -}; - -LINK_ENTITY_TO_CLASS( prop_vehicle_jetski, CPropJetski ); - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CPropJetski ) - - DEFINE_AUTO_ARRAY( m_flSpringLengthApproach, FIELD_FLOAT ), - DEFINE_AUTO_ARRAY( m_flFrictionWheels, FIELD_FLOAT ), - DEFINE_FIELD( m_flHandbrakeTime, FIELD_TIME ), - DEFINE_FIELD( m_bInitialHandbrake, FIELD_BOOLEAN ), - DEFINE_AUTO_ARRAY( m_springLen, FIELD_FLOAT ), - DEFINE_PHYSPTR( m_pVehicle ), - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJetski::Precache( void ) -{ - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJetski::Spawn( void ) -{ - // Setup vehicle as a ray-cast jetski. - SetVehicleType( VEHICLE_TYPE_JETSKI_RAYCAST ); - - BaseClass::Spawn(); - - // Handbrake data. - m_flHandbrakeTime = gpGlobals->curtime + 0.1; - m_bInitialHandbrake = false; - m_VehiclePhysics.SetHasBrakePedal( false ); - - // Slow reverse. - m_VehiclePhysics.SetMaxReverseThrottle( -0.3f ); - - // Setup vehicle variables. - m_pVehicle = m_VehiclePhysics.GetVehicle(); - for ( int i = 0; i < 4; i++ ) - { - m_springLen[i] = JETSKI_SHOCK_LENGTH_REST; - } - - m_takedamage = DAMAGE_EVENTS_ONLY; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJetski::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - if ( ptr->hitbox == VEHICLE_HITBOX_DRIVER ) - { - if ( m_hPlayer != NULL ) - { - m_hPlayer->TakeDamage( info ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CPropJetski::OnTakeDamage( const CTakeDamageInfo &info ) -{ - //Do scaled up physic damage to the car - CTakeDamageInfo physDmg = info; - physDmg.ScaleDamage( 25 ); - VPhysicsTakeDamage( physDmg ); - - //Check to do damage to driver - if ( m_hPlayer != NULL ) - { - //Take no damage from physics damages - if ( info.GetDamageType() & DMG_CRUSH ) - return 0; - - //Take the damage - m_hPlayer->TakeDamage( info ); - } - - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJetski::Think(void) -{ - BaseClass::Think(); - - // set handbrake after physics sim settles down - if ( gpGlobals->curtime < m_flHandbrakeTime ) - { - SetNextThink( gpGlobals->curtime ); - } - else if ( !m_bInitialHandbrake ) // after initial timer expires, set the handbrake - { - m_bInitialHandbrake = true; - m_VehiclePhysics.SetHandbrake( true ); - m_VehiclePhysics.Think(); - } - - - // play enter animation - if ( (m_bEnterAnimOn || m_bExitAnimOn) && !IsSequenceFinished() ) - { - StudioFrameAdvance(); - } - else if ( IsSequenceFinished() ) - { - if ( m_bExitAnimOn ) - { - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - if ( pPlayer ) - { - pPlayer->LeaveVehicle(); // now that sequence is finished, leave car - Vector vecEyes; - QAngle vecEyeAng; - GetAttachment( "vehicle_driver_eyes", vecEyes, vecEyeAng ); - vecEyeAng.x = 0; - vecEyeAng.z = 0; - pPlayer->SnapEyeAngles( vecEyeAng ); - } - m_bExitAnimOn = false; - } - int iSequence = SelectWeightedSequence( ACT_IDLE ); - if ( iSequence > ACTIVITY_NOT_AVAILABLE ) - { - SetCycle(0); - m_flAnimTime = gpGlobals->curtime; - ResetSequence( iSequence ); - ResetClientsideFrame(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJetski::OnTurn( CUserCmd *ucmd ) -{ -#if 0 - // Check for lean and adjust the turning radius accordingly. - if ( ucmd->buttons & IN_JUMP ) - { - m_VehiclePhysics.SetSteeringDegrees( JETSKI_STEERING_LEAN ); - } - else - { - m_VehiclePhysics.SetSteeringDegrees( JETSKI_STEERING_NORMAL ); - } - -#endif - float flSteering = m_VehiclePhysics.GetSteering(); - bool bLeft = ( flSteering < -JETSKI_STEERING_EPS ); - bool bRight = ( flSteering > JETSKI_STEERING_EPS ); - - float flAbsSteering = fabsf( flSteering ); - float flInvAbsSteering = 1.0f - flAbsSteering; - - // Get the speed and ratio to max speed. - float flSpeed = m_VehiclePhysics.GetSpeed(); - float flMaxSpeed = m_VehiclePhysics.GetMaxSpeed(); - float flRatio = flSpeed / flMaxSpeed; - float flScale = 1.0f - flRatio; - flScale *= 0.95f; - flScale += 0.05f; - - flAbsSteering *= flScale; - flInvAbsSteering *= flScale; - - m_flSpringLengthApproach[0] = JETSKI_SHOCK_LENGTH_SHORT; // Front-Left - m_flSpringLengthApproach[1] = JETSKI_SHOCK_LENGTH_SHORT; // Front-Right - m_flSpringLengthApproach[2] = JETSKI_SHOCK_LENGTH_SHORT; // Back-Left - m_flSpringLengthApproach[3] = JETSKI_SHOCK_LENGTH_SHORT; // Back-Right - - return; - - // Roll right. - if( bRight ) - { - float flLengthRight = JETSKI_SHOCK_LENGTH_SHORT + ( JETSKI_SHOCK_LENGTH_REST - JETSKI_SHOCK_LENGTH_SHORT ) * flInvAbsSteering; - float flLengthLeft = JETSKI_SHOCK_LENGTH_REST + ( JETSKI_SHOCK_LENGTH_LONG - JETSKI_SHOCK_LENGTH_REST ) * flAbsSteering; - - m_flSpringLengthApproach[0] = flLengthLeft; // Front-Left - m_flSpringLengthApproach[1] = flLengthRight; // Front-Right - m_flSpringLengthApproach[2] = flLengthLeft; // Back-Left - m_flSpringLengthApproach[3] = flLengthRight; // Back-Right - } - // Roll left. - else if ( bLeft ) - { - float flLengthRight = JETSKI_SHOCK_LENGTH_REST + ( JETSKI_SHOCK_LENGTH_LONG - JETSKI_SHOCK_LENGTH_REST ) * flAbsSteering; - float flLengthLeft = JETSKI_SHOCK_LENGTH_SHORT + ( JETSKI_SHOCK_LENGTH_REST - JETSKI_SHOCK_LENGTH_SHORT ) * flInvAbsSteering; - - m_flSpringLengthApproach[0] = flLengthLeft; // Front-Left - m_flSpringLengthApproach[1] = flLengthRight; // Front-Right - m_flSpringLengthApproach[2] = flLengthLeft; // Back-Left - m_flSpringLengthApproach[3] = flLengthRight; // Back-Right - } - // Return springs to their normal height - else - { - m_flSpringLengthApproach[0] = JETSKI_SHOCK_LENGTH_REST; // Front-Left - m_flSpringLengthApproach[1] = JETSKI_SHOCK_LENGTH_REST; // Front-Right - m_flSpringLengthApproach[2] = JETSKI_SHOCK_LENGTH_REST; // Back-Left - m_flSpringLengthApproach[3] = JETSKI_SHOCK_LENGTH_REST; // Back-Right - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CPropJetski::UpdateLean( CUserCmd *ucmd ) -{ - // Are we leaning back? - if ( ucmd->buttons & IN_JUMP ) - { - m_pVehicle->SetLeanBack( true ); - return true; - } - - m_pVehicle->SetLeanBack( false ); - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CPropJetski::CalculateFriction( CUserCmd *ucmd ) -{ - // Get the speed and ratio to max speed. - float flSpeed = m_VehiclePhysics.GetSpeed(); - float flMaxSpeed = m_VehiclePhysics.GetMaxSpeed(); - float flRatio = flSpeed / flMaxSpeed; - - float flFriction = JETSKI_FRICTION_MAX; - - flRatio = 1.0f - ( float )pow( flRatio, 4 ); - flFriction = JETSKI_FRICTION_MIN + ( JETSKI_FRICTION_MAX - JETSKI_FRICTION_MIN ) * flRatio; - - flFriction = clamp( flFriction, JETSKI_FRICTION_MIN, JETSKI_FRICTION_MAX ); - - // Debug! - Msg( "Speed = %f, Friction = %f", flSpeed, flFriction ); - - return flFriction; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CPropJetski::CalculateDrag( CUserCmd *ucmd ) -{ - // Get the speed and ratio to max speed. - float flSpeed = m_VehiclePhysics.GetSpeed(); - float flMaxSpeed = m_VehiclePhysics.GetMaxSpeed(); - float flRatio = flSpeed / flMaxSpeed; - - float flDrag = 0.0f; - - bool bLean = UpdateLean( ucmd ); - -#if 0 - if ( bLean ) - { - flDrag += JETSKI_DRAG_LEAN_ADD; - } - float flNormalizedRatio = ( flRatio - 0.4f ) * 1.667f; - float flSplineRatio = SimpleSpline( flNormalizedRatio ); - - flFriction = JETSKI_FRICTION_MAX + ( JETSKI_FRICTION_MIN - JETSKI_FRICTION_MAX ) * flSplineRatio; - flDrag = JETSKI_DRAG_IN_WATER + ( JETSKI_DRAG_ON_WATER - JETSKI_DRAG_IN_WATER ) * flNormalizedRatio; - - // Leaning backwards. - if ( bLean ) - { - flDrag += JETSKI_DRAG_LEAN_ADD; - } - } - -#define JETSKI_DRAG_NO_THRUST_IN_WATER 10.0f -#define JETSKI_DRAG_NO_THRUST_ON_WATER 30.0f -#define JETSKI_DRAG_LEAN_ADD 10.0f -#define JETSKI_DRAG_IN_REVERSE 10.0f -#define JETSKI_DRAG_IN_THRUST 5.0f -#endif - - // Debug - Msg( "Drag = %f\n", flDrag ); - - return flDrag; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJetski::OnSpeed( CUserCmd *ucmd ) -{ - // Get the physics object so we can adjust the drag. - IPhysicsObject *pPhysJetski = VPhysicsGetObject(); - if ( !pPhysJetski ) - return; - - float flFriction = CalculateFriction( ucmd ); - float flDrag = CalculateDrag( ucmd ); - - // Update the friction of the jetski "fake wheels." - for ( int iWheel = 0; iWheel < 4; ++iWheel ) - { - m_flFrictionWheels[iWheel] = flFriction; - } - - // Update the Damp coefficient on the jetski. - float flZero = 0.0f; - pPhysJetski->SetDragCoefficient( &flDrag, &flZero ); - -#if 0 - // Splash effects. - if ( flRatio > 0.1f ) - { - CreateSplash( JETSKI_SPLASH_RIPPLE ); - } - - float flRandom = random->RandomFloat( 0.0f, 1.0f ); - if ( flRatio > 0.8f && flRandom < 0.15f ) - { - CreateSplash( JETSKI_SPLASH_SPRAY ); - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJetski::UpdateTurnAndSpeed( void ) -{ -#if 1 - // Update springs. - m_springLen[0] = UTIL_Approach( m_flSpringLengthApproach[0], m_springLen[0], JETSKI_PITCH_AND_ROLL_RATE ); - m_pVehicle->SetSpringLength( 0, m_springLen[0] ); - m_springLen[1] = UTIL_Approach( m_flSpringLengthApproach[1], m_springLen[1], JETSKI_PITCH_AND_ROLL_RATE ); - m_pVehicle->SetSpringLength( 1, m_springLen[1] ); - m_springLen[2] = UTIL_Approach( m_flSpringLengthApproach[2], m_springLen[2], JETSKI_PITCH_AND_ROLL_RATE ); - m_pVehicle->SetSpringLength( 2, m_springLen[2] ); - m_springLen[3] = UTIL_Approach( m_flSpringLengthApproach[3], m_springLen[3], JETSKI_PITCH_AND_ROLL_RATE ); - m_pVehicle->SetSpringLength( 3, m_springLen[3] ); -#endif - - // Update wheel frictions. - for ( int iWheel = 0; iWheel < 4; ++iWheel ) - { - m_pVehicle->SetWheelFriction( iWheel, m_flFrictionWheels[iWheel] ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJetski::DriveVehicle( CBasePlayer *pPlayer, CUserCmd *ucmd ) -{ - //Lose control when the player dies - if ( pPlayer->IsAlive() == false ) - return; - - OnTurn( ucmd ); - OnSpeed( ucmd ); - UpdateTurnAndSpeed(); - - m_VehiclePhysics.UpdateDriverControls( ucmd, ucmd->frametime ); - - // Save this data. - m_nSpeed = m_VehiclePhysics.GetSpeed(); - m_nRPM = m_VehiclePhysics.GetRPM(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -// *pMoveData - -//----------------------------------------------------------------------------- -void CPropJetski::ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ) -{ - BaseClass::ProcessMovement( pPlayer, pMoveData ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJetski::SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) -{ - DriveVehicle( player, ucmd ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJetski::CreateSplash( int nSplashType ) -{ - Vector vecSplashPoint; - QAngle vecSplashAngles; - GetAttachment( "splash_pt", vecSplashPoint, vecSplashAngles ); - - Vector vecForward, vecUp; - AngleVectors( vecSplashAngles, &vecForward, &vecUp, NULL ); - - CEffectData data; - data.m_vOrigin = vecSplashPoint; - - switch ( nSplashType ) - { - case JETSKI_SPLASH_SPRAY: - { - Vector vecSplashDir; - vecSplashDir = ( vecForward + vecUp ) * 0.5f; - VectorNormalize( vecSplashDir ); - data.m_vNormal = vecSplashDir; - data.m_flScale = JETSKI_SPLASH_SPRAY_SIZE + random->RandomFloat( 0, JETSKI_SPLASH_SPRAY_SIZE * 0.25 ); - DispatchEffect( "waterripple", data ); - DispatchEffect( "watersplash", data ); - } - case JETSKI_SPLASH_GURGLE: - { - Vector vecSplashDir; - vecSplashDir = vecUp; - data.m_vNormal = vecSplashDir; - - data.m_flScale = JETSKI_SPLASH_GURGLE_SIZE + random->RandomFloat( 0, JETSKI_SPLASH_GURGLE_SIZE * 0.25 ); - DispatchEffect( "waterripple", data ); - DispatchEffect( "watersplash", data ); - } - case JETSKI_SPLASH_RIPPLE: - { - Vector vecSplashDir; - vecSplashDir = vecUp; - data.m_vNormal = vecSplashDir; - data.m_flScale = JETSKI_SPLASH_RIPPLE_SIZE + random->RandomFloat( 0, JETSKI_SPLASH_RIPPLE_SIZE * 0.25 ); - DispatchEffect( "waterripple", data ); - } - default: - { - return; - } - } -} diff --git a/game/server/hl2/vehicle_prisoner_pod.cpp b/game/server/hl2/vehicle_prisoner_pod.cpp deleted file mode 100644 index 7c72c3744..000000000 --- a/game/server/hl2/vehicle_prisoner_pod.cpp +++ /dev/null @@ -1,735 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" -#include "vehicle_base.h" -#include "engine/IEngineSound.h" -#include "in_buttons.h" -#include "soundenvelope.h" -#include "soundent.h" -#include "physics_saverestore.h" -#include "vphysics/constraints.h" -#include "vcollide_parse.h" -#include "ndebugoverlay.h" -#include "hl2_player.h" -#include "props.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define VEHICLE_HITBOX_DRIVER 1 - - -// -// Anim events. -// -enum -{ - AE_POD_OPEN = 1, // The pod is now open and can be entered or exited. - AE_POD_CLOSE = 2, // The pod is now closed and cannot be entered or exited. -}; - - -extern ConVar g_debug_vehicledriver; - - -class CPropVehiclePrisonerPod; - - -// Pod bones that have physics followers -/*static const char *pPodFollowerBoneNames[] = -{ - "base", -};*/ - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CPrisonerPodServerVehicle : public CBaseServerVehicle -{ - typedef CBaseServerVehicle BaseClass; - -// IServerVehicle -public: - void GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV = NULL ); - virtual void ItemPostFrame( CBasePlayer *pPlayer ); - - virtual bool IsPassengerEntering( void ) { return false; } // NOTE: This mimics the scenario HL2 would have seen - virtual bool IsPassengerExiting( void ) { return false; } - -protected: - - CPropVehiclePrisonerPod *GetPod( void ); -}; - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CPropVehiclePrisonerPod : public CPhysicsProp, public IDrivableVehicle -{ - DECLARE_CLASS( CPropVehiclePrisonerPod, CPhysicsProp ); - -public: - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - CPropVehiclePrisonerPod( void ) - { - m_ServerVehicle.SetVehicle( this ); - } - - ~CPropVehiclePrisonerPod( void ) - { - } - - // CBaseEntity - virtual void Precache( void ); - void Spawn( void ); - void Think(void); - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() | FCAP_IMPULSE_USE; }; - virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - virtual void DrawDebugGeometryOverlays( void ); - - virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true ); - virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - - void PlayerControlInit( CBasePlayer *pPlayer ); - void PlayerControlShutdown( void ); - void ResetUseKey( CBasePlayer *pPlayer ); - - virtual bool OverridePropdata() { return true; } - - void GetVectors(Vector* pForward, Vector* pRight, Vector* pUp) const; - - bool ShouldForceExit() { return m_bForcedExit; } - void ClearForcedExit() { m_bForcedExit = false; } - - // CBaseAnimating - void HandleAnimEvent( animevent_t *pEvent ); - - // Inputs - void InputEnterVehicleImmediate( inputdata_t &inputdata ); - void InputEnterVehicle( inputdata_t &inputdata ); - void InputExitVehicle( inputdata_t &inputdata ); - void InputLock( inputdata_t &inputdata ); - void InputUnlock( inputdata_t &inputdata ); - void InputOpen( inputdata_t &inputdata ); - void InputClose( inputdata_t &inputdata ); - - CNetworkHandle( CBasePlayer, m_hPlayer ); - -// IDrivableVehicle -public: - - virtual bool PassengerShouldReceiveDamage( CTakeDamageInfo &info ) - { - if ( info.GetDamageType() & DMG_VEHICLE ) - return true; - - return (info.GetDamageType() & (DMG_RADIATION|DMG_BLAST) ) == 0; - } - - virtual CBaseEntity *GetDriver( void ); - virtual void ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ) { return; } - virtual void FinishMove( CBasePlayer *player, CUserCmd *ucmd, CMoveData *move ) { return; } - virtual bool CanEnterVehicle( CBaseEntity *pEntity ); - virtual bool CanExitVehicle( CBaseEntity *pEntity ); - virtual void SetVehicleEntryAnim( bool bOn ); - virtual void SetVehicleExitAnim( bool bOn, Vector vecEyeExitEndpoint ) { m_bExitAnimOn = bOn; if ( bOn ) m_vecEyeExitEndpoint = vecEyeExitEndpoint; } - virtual void EnterVehicle( CBaseCombatCharacter *pPassenger ); - - virtual bool AllowBlockedExit( CBaseCombatCharacter *pPassenger, int nRole ) { return true; } - virtual bool AllowMidairExit( CBaseCombatCharacter *pPassenger, int nRole ) { return true; } - virtual void PreExitVehicle( CBaseCombatCharacter *pPassenger, int nRole ) {} - virtual void ExitVehicle( int nRole ); - - virtual void ItemPostFrame( CBasePlayer *pPlayer ) {} - virtual void SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) {} - virtual string_t GetVehicleScriptName() { return m_vehicleScript; } - - // If this is a vehicle, returns the vehicle interface - virtual IServerVehicle *GetServerVehicle() { return &m_ServerVehicle; } - -protected: - - // Contained IServerVehicle - CPrisonerPodServerVehicle m_ServerVehicle; - -private: - - // Entering / Exiting - bool m_bLocked; - CNetworkVar( bool, m_bEnterAnimOn ); - CNetworkVar( bool, m_bExitAnimOn ); - CNetworkVector( m_vecEyeExitEndpoint ); - bool m_bForcedExit; - - // Vehicle script filename - string_t m_vehicleScript; - - COutputEvent m_playerOn; - COutputEvent m_playerOff; - COutputEvent m_OnOpen; - COutputEvent m_OnClose; -}; - -LINK_ENTITY_TO_CLASS( prop_vehicle_prisoner_pod, CPropVehiclePrisonerPod ); - - -BEGIN_DATADESC( CPropVehiclePrisonerPod ) - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Lock", InputLock ), - DEFINE_INPUTFUNC( FIELD_VOID, "Unlock", InputUnlock ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnterVehicle", InputEnterVehicle ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnterVehicleImmediate", InputEnterVehicleImmediate ), - DEFINE_INPUTFUNC( FIELD_VOID, "ExitVehicle", InputExitVehicle ), - DEFINE_INPUTFUNC( FIELD_VOID, "Open", InputOpen ), - DEFINE_INPUTFUNC( FIELD_VOID, "Close", InputClose ), - - // Keys - DEFINE_EMBEDDED( m_ServerVehicle ), - - DEFINE_FIELD( m_hPlayer, FIELD_EHANDLE ), - DEFINE_FIELD( m_bEnterAnimOn, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bExitAnimOn, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bForcedExit, FIELD_BOOLEAN ), - DEFINE_FIELD( m_vecEyeExitEndpoint, FIELD_POSITION_VECTOR ), - - DEFINE_KEYFIELD( m_vehicleScript, FIELD_STRING, "vehiclescript" ), - DEFINE_KEYFIELD( m_bLocked, FIELD_BOOLEAN, "vehiclelocked" ), - - DEFINE_OUTPUT( m_playerOn, "PlayerOn" ), - DEFINE_OUTPUT( m_playerOff, "PlayerOff" ), - DEFINE_OUTPUT( m_OnOpen, "OnOpen" ), - DEFINE_OUTPUT( m_OnClose, "OnClose" ), - -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST(CPropVehiclePrisonerPod, DT_PropVehiclePrisonerPod) - SendPropEHandle(SENDINFO(m_hPlayer)), - SendPropBool(SENDINFO(m_bEnterAnimOn)), - SendPropBool(SENDINFO(m_bExitAnimOn)), - SendPropVector(SENDINFO(m_vecEyeExitEndpoint), -1, SPROP_COORD), -END_SEND_TABLE(); - - -//------------------------------------------------ -// Precache -//------------------------------------------------ -void CPropVehiclePrisonerPod::Precache( void ) -{ - BaseClass::Precache(); - - PrecacheScriptSound( "d3_citadel.pod_open" ); - PrecacheScriptSound( "d3_citadel.pod_close" ); - - m_ServerVehicle.Initialize( STRING(m_vehicleScript) ); -} - - -//------------------------------------------------ -// Spawn -//------------------------------------------------ -void CPropVehiclePrisonerPod::Spawn( void ) -{ - Precache(); - SetModel( STRING( GetModelName() ) ); - SetCollisionGroup( COLLISION_GROUP_VEHICLE ); - - BaseClass::Spawn(); - - m_takedamage = DAMAGE_EVENTS_ONLY; - - SetNextThink( gpGlobals->curtime ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehiclePrisonerPod::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - if ( ptr->hitbox == VEHICLE_HITBOX_DRIVER ) - { - if ( m_hPlayer != NULL ) - { - m_hPlayer->TakeDamage( info ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CPropVehiclePrisonerPod::OnTakeDamage( const CTakeDamageInfo &inputInfo ) -{ - // Do scaled up physics damage to the pod - CTakeDamageInfo info = inputInfo; - info.ScaleDamage( 25 ); - - // reset the damage - info.SetDamage( inputInfo.GetDamage() ); - - // Check to do damage to prisoner - if ( m_hPlayer != NULL ) - { - // Take no damage from physics damages - if ( info.GetDamageType() & DMG_CRUSH ) - return 0; - - // Take the damage - m_hPlayer->TakeDamage( info ); - } - - return 0; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Vector CPropVehiclePrisonerPod::BodyTarget( const Vector &posSrc, bool bNoisy ) -{ - Vector shotPos; - matrix3x4_t matrix; - - int eyeAttachmentIndex = LookupAttachment("vehicle_driver_eyes"); - GetAttachment( eyeAttachmentIndex, matrix ); - MatrixGetColumn( matrix, 3, shotPos ); - - if ( bNoisy ) - { - shotPos[0] += random->RandomFloat( -8.0f, 8.0f ); - shotPos[1] += random->RandomFloat( -8.0f, 8.0f ); - shotPos[2] += random->RandomFloat( -8.0f, 8.0f ); - } - - return shotPos; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehiclePrisonerPod::Think(void) -{ - SetNextThink( gpGlobals->curtime + 0.1 ); - - if ( GetDriver() ) - { - BaseClass::Think(); - - // If the enter or exit animation has finished, tell the server vehicle - if ( IsSequenceFinished() && (m_bExitAnimOn || m_bEnterAnimOn) ) - { - GetServerVehicle()->HandleEntryExitFinish( m_bExitAnimOn, true ); - } - } - - StudioFrameAdvance(); - DispatchAnimEvents( this ); -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CPropVehiclePrisonerPod::InputOpen( inputdata_t &inputdata ) -{ - int nSequence = LookupSequence( "open" ); - - // Set to the desired anim, or default anim if the desired is not present - if ( nSequence > ACTIVITY_NOT_AVAILABLE ) - { - SetCycle( 0 ); - m_flAnimTime = gpGlobals->curtime; - ResetSequence( nSequence ); - ResetClientsideFrame(); - EmitSound( "d3_citadel.pod_open" ); - } - else - { - // Not available try to get default anim - Msg( "Prisoner pod %s: missing open sequence\n", GetDebugName() ); - SetSequence( 0 ); - } -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CPropVehiclePrisonerPod::InputClose( inputdata_t &inputdata ) -{ - // The enter anim closes the pod, so don't do this redundantly! - if ( m_bLocked || m_bEnterAnimOn ) - return; - - int nSequence = LookupSequence( "close" ); - - // Set to the desired anim, or default anim if the desired is not present - if ( nSequence > ACTIVITY_NOT_AVAILABLE ) - { - SetCycle( 0 ); - m_flAnimTime = gpGlobals->curtime; - ResetSequence( nSequence ); - ResetClientsideFrame(); - EmitSound( "d3_citadel.pod_close" ); - } - else - { - // Not available try to get default anim - Msg( "Prisoner pod %s: missing close sequence\n", GetDebugName() ); - SetSequence( 0 ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehiclePrisonerPod::HandleAnimEvent( animevent_t *pEvent ) -{ - if ( pEvent->event == AE_POD_OPEN ) - { - m_OnOpen.FireOutput( this, this ); - m_bLocked = false; - } - else if ( pEvent->event == AE_POD_CLOSE ) - { - m_OnClose.FireOutput( this, this ); - m_bLocked = true; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehiclePrisonerPod::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - CBasePlayer *pPlayer = ToBasePlayer( pActivator ); - if ( !pPlayer ) - return; - - ResetUseKey( pPlayer ); - - GetServerVehicle()->HandlePassengerEntry( pPlayer, (value > 0) ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Return true of the player's allowed to enter / exit the vehicle -//----------------------------------------------------------------------------- -bool CPropVehiclePrisonerPod::CanEnterVehicle( CBaseEntity *pEntity ) -{ - // Prevent entering if the vehicle's being driven by an NPC - if ( GetDriver() && GetDriver() != pEntity ) - return false; - - // Prevent entering if the vehicle's locked - return !m_bLocked; -} - - -//----------------------------------------------------------------------------- -// Purpose: Return true of the player is allowed to exit the vehicle. -//----------------------------------------------------------------------------- -bool CPropVehiclePrisonerPod::CanExitVehicle( CBaseEntity *pEntity ) -{ - // Prevent exiting if the vehicle's locked, rotating, or playing an entry/exit anim. - return ( !m_bLocked && (GetLocalAngularVelocity() == vec3_angle) && !m_bEnterAnimOn && !m_bExitAnimOn ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Override base class to add display -//----------------------------------------------------------------------------- -void CPropVehiclePrisonerPod::DrawDebugGeometryOverlays(void) -{ - // Draw if BBOX is on - if ( m_debugOverlays & OVERLAY_BBOX_BIT ) - { - } - - BaseClass::DrawDebugGeometryOverlays(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehiclePrisonerPod::EnterVehicle( CBaseCombatCharacter *pPassenger ) -{ - if ( pPassenger == NULL ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( pPassenger ); - if ( pPlayer != NULL ) - { - // Remove any player who may be in the vehicle at the moment - if ( m_hPlayer ) - { - ExitVehicle( VEHICLE_ROLE_DRIVER ); - } - - m_hPlayer = pPlayer; - m_playerOn.FireOutput( pPlayer, this, 0 ); - - m_ServerVehicle.SoundStart(); - } - else - { - // NPCs are not supported yet - jdw - Assert( 0 ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehiclePrisonerPod::SetVehicleEntryAnim( bool bOn ) -{ - m_bEnterAnimOn = bOn; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehiclePrisonerPod::ExitVehicle( int nRole ) -{ - CBasePlayer *pPlayer = m_hPlayer; - if ( !pPlayer ) - return; - - m_hPlayer = NULL; - ResetUseKey( pPlayer ); - - m_playerOff.FireOutput( pPlayer, this, 0 ); - m_bEnterAnimOn = false; - - m_ServerVehicle.SoundShutdown( 1.0 ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehiclePrisonerPod::ResetUseKey( CBasePlayer *pPlayer ) -{ - pPlayer->m_afButtonPressed &= ~IN_USE; -} - - -//----------------------------------------------------------------------------- -// Purpose: Vehicles are permanently oriented off angle for vphysics. -//----------------------------------------------------------------------------- -void CPropVehiclePrisonerPod::GetVectors(Vector* pForward, Vector* pRight, Vector* pUp) const -{ - // This call is necessary to cause m_rgflCoordinateFrame to be recomputed - const matrix3x4_t &entityToWorld = EntityToWorldTransform(); - - if (pForward != NULL) - { - MatrixGetColumn( entityToWorld, 1, *pForward ); - } - - if (pRight != NULL) - { - MatrixGetColumn( entityToWorld, 0, *pRight ); - } - - if (pUp != NULL) - { - MatrixGetColumn( entityToWorld, 2, *pUp ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseEntity *CPropVehiclePrisonerPod::GetDriver( void ) -{ - return m_hPlayer; -} - -//----------------------------------------------------------------------------- -// Purpose: Prevent the player from entering / exiting the vehicle -//----------------------------------------------------------------------------- -void CPropVehiclePrisonerPod::InputLock( inputdata_t &inputdata ) -{ - m_bLocked = true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Allow the player to enter / exit the vehicle -//----------------------------------------------------------------------------- -void CPropVehiclePrisonerPod::InputUnlock( inputdata_t &inputdata ) -{ - m_bLocked = false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Force the player to enter the vehicle. -//----------------------------------------------------------------------------- -void CPropVehiclePrisonerPod::InputEnterVehicle( inputdata_t &inputdata ) -{ - if ( m_bEnterAnimOn ) - return; - - // Try the activator first & use them if they are a player. - CBaseCombatCharacter *pPassenger = ToBaseCombatCharacter( inputdata.pActivator ); - if ( pPassenger == NULL ) - { - // Activator was not a player, just grab the singleplayer player. - pPassenger = UTIL_PlayerByIndex( 1 ); - if ( pPassenger == NULL ) - return; - } - - // FIXME: I hate code like this. I should really add a parameter to HandlePassengerEntry - // to allow entry into locked vehicles - bool bWasLocked = m_bLocked; - m_bLocked = false; - GetServerVehicle()->HandlePassengerEntry( pPassenger, true ); - m_bLocked = bWasLocked; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CPropVehiclePrisonerPod::InputEnterVehicleImmediate( inputdata_t &inputdata ) -{ - if ( m_bEnterAnimOn ) - return; - - // Try the activator first & use them if they are a player. - CBaseCombatCharacter *pPassenger = ToBaseCombatCharacter( inputdata.pActivator ); - if ( pPassenger == NULL ) - { - // Activator was not a player, just grab the singleplayer player. - pPassenger = UTIL_PlayerByIndex( 1 ); - if ( pPassenger == NULL ) - return; - } - - CBasePlayer *pPlayer = ToBasePlayer( pPassenger ); - if ( pPlayer != NULL ) - { - if ( pPlayer->IsInAVehicle() ) - { - // Force the player out of whatever vehicle they are in. - pPlayer->LeaveVehicle(); - } - - pPlayer->GetInVehicle( GetServerVehicle(), VEHICLE_ROLE_DRIVER ); - } - else - { - // NPCs are not currently supported - jdw - Assert( 0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Force the player to exit the vehicle. -//----------------------------------------------------------------------------- -void CPropVehiclePrisonerPod::InputExitVehicle( inputdata_t &inputdata ) -{ - m_bForcedExit = true; -} - - -//======================================================================================================================================== -// CRANE VEHICLE SERVER VEHICLE -//======================================================================================================================================== -CPropVehiclePrisonerPod *CPrisonerPodServerVehicle::GetPod( void ) -{ - return (CPropVehiclePrisonerPod *)GetDrivableVehicle(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pPlayer - -//----------------------------------------------------------------------------- -void CPrisonerPodServerVehicle::ItemPostFrame( CBasePlayer *player ) -{ - Assert( player == GetDriver() ); - - GetDrivableVehicle()->ItemPostFrame( player ); - - if (( player->m_afButtonPressed & IN_USE ) || GetPod()->ShouldForceExit() ) - { - GetPod()->ClearForcedExit(); - if ( GetDrivableVehicle()->CanExitVehicle(player) ) - { - // Let the vehicle try to play the exit animation - if ( !HandlePassengerExit( player ) && ( player != NULL ) ) - { - player->PlayUseDenySound(); - } - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPrisonerPodServerVehicle::GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV /*= NULL*/ ) -{ - // FIXME: This needs to be reconciled with the other versions of this function! - Assert( nRole == VEHICLE_ROLE_DRIVER ); - CBasePlayer *pPlayer = ToBasePlayer( GetDrivableVehicle()->GetDriver() ); - Assert( pPlayer ); - - *pAbsAngles = pPlayer->EyeAngles(); // yuck. this is an in/out parameter. - - float flPitchFactor = 1.0; - matrix3x4_t vehicleEyePosToWorld; - Vector vehicleEyeOrigin; - QAngle vehicleEyeAngles; - GetPod()->GetAttachment( "vehicle_driver_eyes", vehicleEyeOrigin, vehicleEyeAngles ); - AngleMatrix( vehicleEyeAngles, vehicleEyePosToWorld ); - - // Compute the relative rotation between the unperterbed eye attachment + the eye angles - matrix3x4_t cameraToWorld; - AngleMatrix( *pAbsAngles, cameraToWorld ); - - matrix3x4_t worldToEyePos; - MatrixInvert( vehicleEyePosToWorld, worldToEyePos ); - - matrix3x4_t vehicleCameraToEyePos; - ConcatTransforms( worldToEyePos, cameraToWorld, vehicleCameraToEyePos ); - - // Now perterb the attachment point - vehicleEyeAngles.x = RemapAngleRange( PITCH_CURVE_ZERO * flPitchFactor, PITCH_CURVE_LINEAR, vehicleEyeAngles.x ); - vehicleEyeAngles.z = RemapAngleRange( ROLL_CURVE_ZERO * flPitchFactor, ROLL_CURVE_LINEAR, vehicleEyeAngles.z ); - AngleMatrix( vehicleEyeAngles, vehicleEyeOrigin, vehicleEyePosToWorld ); - - // Now treat the relative eye angles as being relative to this new, perterbed view position... - matrix3x4_t newCameraToWorld; - ConcatTransforms( vehicleEyePosToWorld, vehicleCameraToEyePos, newCameraToWorld ); - - // output new view abs angles - MatrixAngles( newCameraToWorld, *pAbsAngles ); - - // UNDONE: *pOrigin would already be correct in single player if the HandleView() on the server ran after vphysics - MatrixGetColumn( newCameraToWorld, 3, *pAbsOrigin ); -} diff --git a/game/server/hl2/vehicle_viewcontroller.cpp b/game/server/hl2/vehicle_viewcontroller.cpp deleted file mode 100644 index 8a163b59a..000000000 --- a/game/server/hl2/vehicle_viewcontroller.cpp +++ /dev/null @@ -1,180 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: This is a bastardization of the vehicle code for the choreography -// group who want to have smooth view lerping code out of a keyframed -// controlled player viewpoint. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "vehicle_base.h" -#include "hl2_player.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CPropVehicleViewController : public CPropVehicleDriveable -{ - DECLARE_CLASS( CPropVehicleViewController, CPropVehicleDriveable ); -public: - DECLARE_DATADESC(); - - // CBaseEntity - void Spawn( void ); - void Think(void); - - // CPropVehicle - virtual void SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ); - virtual void EnterVehicle( CBasePlayer *pPlayer ); - virtual void ExitVehicle( int nRole ); - - // Inputs to force the player in/out of the vehicle - void InputForcePlayerIn( inputdata_t &inputdata ); - void InputForcePlayerOut( inputdata_t &inputdata ); -}; - -BEGIN_DATADESC( CPropVehicleViewController ) - DEFINE_INPUTFUNC( FIELD_STRING, "ForcePlayerIn", InputForcePlayerIn ), - DEFINE_INPUTFUNC( FIELD_VOID, "ForcePlayerOut", InputForcePlayerOut ), -END_DATADESC() - -LINK_ENTITY_TO_CLASS( vehicle_viewcontroller, CPropVehicleViewController ); - -//------------------------------------------------ -// Spawn -//------------------------------------------------ -void CPropVehicleViewController::Spawn( void ) -{ - BaseClass::Spawn(); - AddSolidFlags( FSOLID_NOT_STANDABLE ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleViewController::Think(void) -{ - BaseClass::Think(); - - SetSimulationTime( gpGlobals->curtime ); - SetNextThink( gpGlobals->curtime ); - SetAnimatedEveryTick( true ); - - StudioFrameAdvance(); - - // If the exit anim has finished, move the player to the right spot and stop animating - if ( IsSequenceFinished() && (m_bExitAnimOn || m_bEnterAnimOn) ) - { - // If we're exiting and have had the tau cannon removed, we don't want to reset the animation - GetServerVehicle()->HandleEntryExitFinish( m_bExitAnimOn, false ); - m_bExitAnimOn = false; - m_bEnterAnimOn = false; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleViewController::SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) -{ - // Does nothing, because this vehicle doesn't drive -} - -//----------------------------------------------------------------------------- -// Purpose: -// NOTE: Doesn't call the base call enter vehicle on purpose! -//----------------------------------------------------------------------------- -void CPropVehicleViewController::EnterVehicle( CBasePlayer *pPlayer ) -{ - if ( !pPlayer ) - return; - - m_hPlayer = pPlayer; - - pPlayer->SetViewOffset( vec3_origin ); - pPlayer->ShowCrosshair( false ); - m_playerOn.FireOutput( pPlayer, this, 0 ); - - // Start Thinking - SetNextThink( gpGlobals->curtime ); - - m_VehiclePhysics.GetVehicle()->OnVehicleEnter(); - - // Stop the player sprint and flashlight. - CHL2_Player *pHL2Player = dynamic_cast( pPlayer ); - if ( pHL2Player ) - { - if ( pHL2Player->IsSprinting() ) - { - pHL2Player->StopSprinting(); - } - - if ( pHL2Player->FlashlightIsOn() ) - { - pHL2Player->FlashlightTurnOff(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleViewController::ExitVehicle( int nRole ) -{ - BaseClass::ExitVehicle( nRole ); - m_bEnterAnimOn = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleViewController::InputForcePlayerIn( inputdata_t &inputdata ) -{ - CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); - if ( !pPlayer ) - return; - - ResetUseKey( pPlayer ); - - // Get the entry animation from the input - int iEntryAnim = ACTIVITY_NOT_AVAILABLE; - if ( inputdata.value.StringID() != NULL_STRING ) - { - iEntryAnim = LookupSequence( inputdata.value.String() ); - if ( iEntryAnim == ACTIVITY_NOT_AVAILABLE ) - { - Warning("vehicle_viewcontroller %s could not find specified entry animation %s\n", STRING(GetEntityName()), inputdata.value.String() ); - return; - } - } - - // Make sure we successfully got in the vehicle - if ( pPlayer->GetInVehicle( GetServerVehicle(), VEHICLE_ROLE_DRIVER ) == false ) - { - // The player was unable to enter the vehicle and the output has failed - Assert( 0 ); - return; - } - - // Setup the "enter" vehicle sequence - SetCycle( 0 ); - m_flAnimTime = gpGlobals->curtime; - ResetSequence( iEntryAnim ); - ResetClientsideFrame(); - m_bEnterAnimOn = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleViewController::InputForcePlayerOut( inputdata_t &inputdata ) -{ - if ( !GetDriver() ) - return; - - GetServerVehicle()->HandlePassengerExit( m_hPlayer ); -} diff --git a/game/server/hl2/weapon_357.cpp b/game/server/hl2/weapon_357.cpp deleted file mode 100644 index 4c486bfb2..000000000 --- a/game/server/hl2/weapon_357.cpp +++ /dev/null @@ -1,160 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: 357 - hand gun -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" -#include "basehlcombatweapon.h" -#include "basecombatcharacter.h" -#include "ai_basenpc.h" -#include "player.h" -#include "gamerules.h" -#include "in_buttons.h" -#include "soundent.h" -#include "game.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "te_effect_dispatch.h" -#include "GameStats.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// CWeapon357 -//----------------------------------------------------------------------------- - -class CWeapon357 : public CBaseHLCombatWeapon -{ - DECLARE_CLASS( CWeapon357, CBaseHLCombatWeapon ); -public: - - CWeapon357( void ); - - void PrimaryAttack( void ); - void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); - - float WeaponAutoAimScale() { return 0.6f; } - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( weapon_357, CWeapon357 ); - -PRECACHE_WEAPON_REGISTER( weapon_357 ); - -IMPLEMENT_SERVERCLASS_ST( CWeapon357, DT_Weapon357 ) -END_SEND_TABLE() - -BEGIN_DATADESC( CWeapon357 ) -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -CWeapon357::CWeapon357( void ) -{ - m_bReloadsSingly = false; - m_bFiresUnderwater = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeapon357::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - switch( pEvent->event ) - { - case EVENT_WEAPON_RELOAD: - { - CEffectData data; - - // Emit six spent shells - for ( int i = 0; i < 6; i++ ) - { - data.m_vOrigin = pOwner->WorldSpaceCenter() + RandomVector( -4, 4 ); - data.m_vAngles = QAngle( 90, random->RandomInt( 0, 360 ), 0 ); - data.m_nEntIndex = entindex(); - - DispatchEffect( "ShellEject", data ); - } - - break; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeapon357::PrimaryAttack( void ) -{ - // Only the player fires this way so we can cast - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if ( !pPlayer ) - { - return; - } - - if ( m_iClip1 <= 0 ) - { - if ( !m_bFireOnEmpty ) - { - Reload(); - } - else - { - WeaponSound( EMPTY ); - m_flNextPrimaryAttack = 0.15; - } - - return; - } - - m_iPrimaryAttacks++; - gamestats->Event_WeaponFired( pPlayer, true, GetClassname() ); - - WeaponSound( SINGLE ); - pPlayer->DoMuzzleFlash(); - - SendWeaponAnim( ACT_VM_PRIMARYATTACK ); - pPlayer->SetAnimation( PLAYER_ATTACK1 ); - - m_flNextPrimaryAttack = gpGlobals->curtime + 0.75; - m_flNextSecondaryAttack = gpGlobals->curtime + 0.75; - - m_iClip1--; - - Vector vecSrc = pPlayer->Weapon_ShootPosition(); - Vector vecAiming = pPlayer->GetAutoaimVector( AUTOAIM_SCALE_DEFAULT ); - - pPlayer->FireBullets( 1, vecSrc, vecAiming, vec3_origin, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 0 ); - - pPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 ); - - //Disorient the player - QAngle angles = pPlayer->GetLocalAngles(); - - angles.x += random->RandomInt( -1, 1 ); - angles.y += random->RandomInt( -1, 1 ); - angles.z = 0; - - pPlayer->SnapEyeAngles( angles ); - - pPlayer->ViewPunch( QAngle( -8, random->RandomFloat( -2, 2 ), 0 ) ); - - CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 600, 0.2, GetOwner() ); - - if ( !m_iClip1 && pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 ) - { - // HEV suit - indicate out of ammo condition - pPlayer->SetSuitUpdate( "!HEV_AMO0", FALSE, 0 ); - } -} diff --git a/game/server/hl2/weapon_alyxgun.cpp b/game/server/hl2/weapon_alyxgun.cpp deleted file mode 100644 index 587215d6d..000000000 --- a/game/server/hl2/weapon_alyxgun.cpp +++ /dev/null @@ -1,326 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" - -#include "weapon_alyxgun.h" -#include "npcevent.h" -#include "ai_basenpc.h" -#include "globalstate.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -IMPLEMENT_SERVERCLASS_ST(CWeaponAlyxGun, DT_WeaponAlyxGun) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_alyxgun, CWeaponAlyxGun ); -PRECACHE_WEAPON_REGISTER(weapon_alyxgun); - -BEGIN_DATADESC( CWeaponAlyxGun ) -END_DATADESC() - -acttable_t CWeaponAlyxGun::m_acttable[] = -{ - { ACT_IDLE, ACT_IDLE_PISTOL, true }, - { ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_PISTOL, true }, - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_PISTOL, true }, - { ACT_RELOAD, ACT_RELOAD_PISTOL, true }, - { ACT_WALK_AIM, ACT_WALK_AIM_PISTOL, true }, - { ACT_RUN_AIM, ACT_RUN_AIM_PISTOL, true }, - { ACT_COVER_LOW, ACT_COVER_PISTOL_LOW, true }, - { ACT_RANGE_AIM_LOW, ACT_RANGE_AIM_PISTOL_LOW, true }, - { ACT_GESTURE_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK_PISTOL,true }, - { ACT_RELOAD_LOW, ACT_RELOAD_PISTOL_LOW, true }, - { ACT_RANGE_ATTACK1_LOW, ACT_RANGE_ATTACK_PISTOL_LOW, true }, - { ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_PISTOL, true }, - - // Readiness activities (not aiming) - { ACT_IDLE_RELAXED, ACT_IDLE_PISTOL, false },//never aims - { ACT_IDLE_STIMULATED, ACT_IDLE_STIMULATED, false }, - { ACT_IDLE_AGITATED, ACT_IDLE_ANGRY_PISTOL, false },//always aims - { ACT_IDLE_STEALTH, ACT_IDLE_STEALTH_PISTOL, false }, - - { ACT_WALK_RELAXED, ACT_WALK, false },//never aims - { ACT_WALK_STIMULATED, ACT_WALK_STIMULATED, false }, - { ACT_WALK_AGITATED, ACT_WALK_AIM_PISTOL, false },//always aims - { ACT_WALK_STEALTH, ACT_WALK_STEALTH_PISTOL, false }, - - { ACT_RUN_RELAXED, ACT_RUN, false },//never aims - { ACT_RUN_STIMULATED, ACT_RUN_STIMULATED, false }, - { ACT_RUN_AGITATED, ACT_RUN_AIM_PISTOL, false },//always aims - { ACT_RUN_STEALTH, ACT_RUN_STEALTH_PISTOL, false }, - - // Readiness activities (aiming) - { ACT_IDLE_AIM_RELAXED, ACT_IDLE_PISTOL, false },//never aims - { ACT_IDLE_AIM_STIMULATED, ACT_IDLE_ANGRY_PISTOL, false }, - { ACT_IDLE_AIM_AGITATED, ACT_IDLE_ANGRY_PISTOL, false },//always aims - { ACT_IDLE_AIM_STEALTH, ACT_IDLE_STEALTH_PISTOL, false }, - - { ACT_WALK_AIM_RELAXED, ACT_WALK, false },//never aims - { ACT_WALK_AIM_STIMULATED, ACT_WALK_AIM_PISTOL, false }, - { ACT_WALK_AIM_AGITATED, ACT_WALK_AIM_PISTOL, false },//always aims - { ACT_WALK_AIM_STEALTH, ACT_WALK_AIM_STEALTH_PISTOL, false },//always aims - - { ACT_RUN_AIM_RELAXED, ACT_RUN, false },//never aims - { ACT_RUN_AIM_STIMULATED, ACT_RUN_AIM_PISTOL, false }, - { ACT_RUN_AIM_AGITATED, ACT_RUN_AIM_PISTOL, false },//always aims - { ACT_RUN_AIM_STEALTH, ACT_RUN_AIM_STEALTH_PISTOL, false },//always aims - //End readiness activities - - // Crouch activities - { ACT_CROUCHIDLE_STIMULATED, ACT_CROUCHIDLE_STIMULATED, false }, - { ACT_CROUCHIDLE_AIM_STIMULATED,ACT_RANGE_AIM_PISTOL_LOW, false },//always aims - { ACT_CROUCHIDLE_AGITATED, ACT_RANGE_AIM_PISTOL_LOW, false },//always aims - - // Readiness translations - { ACT_READINESS_RELAXED_TO_STIMULATED, ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED, false }, - { ACT_READINESS_RELAXED_TO_STIMULATED_WALK, ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED_WALK, false }, - { ACT_READINESS_AGITATED_TO_STIMULATED, ACT_READINESS_PISTOL_AGITATED_TO_STIMULATED, false }, - { ACT_READINESS_STIMULATED_TO_RELAXED, ACT_READINESS_PISTOL_STIMULATED_TO_RELAXED, false }, - - -// { ACT_ARM, ACT_ARM_PISTOL, true }, -// { ACT_DISARM, ACT_DISARM_PISTOL, true }, -}; - -IMPLEMENT_ACTTABLE(CWeaponAlyxGun); - -#define TOOCLOSETIMER_OFF 0.0f -#define ALYX_TOOCLOSETIMER 1.0f // Time an enemy must be tooclose before Alyx is allowed to shoot it. - -//========================================================= -CWeaponAlyxGun::CWeaponAlyxGun( ) -{ - m_fMinRange1 = 1; - m_fMaxRange1 = 5000; - - m_flTooCloseTimer = TOOCLOSETIMER_OFF; - -#ifdef HL2_EPISODIC - m_fMinRange1 = 60; - m_fMaxRange1 = 2048; -#endif//HL2_EPISODIC -} - -CWeaponAlyxGun::~CWeaponAlyxGun( ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponAlyxGun::Precache( void ) -{ - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CWeaponAlyxGun::Equip( CBaseCombatCharacter *pOwner ) -{ - BaseClass::Equip( pOwner ); -} - -//----------------------------------------------------------------------------- -// Purpose: Try to encourage Alyx not to use her weapon at point blank range, -// but don't prevent her from defending herself if cornered. -// Input : flDot - -// flDist - -// Output : int -//----------------------------------------------------------------------------- -int CWeaponAlyxGun::WeaponRangeAttack1Condition( float flDot, float flDist ) -{ -#ifdef HL2_EPISODIC - - if( flDist < m_fMinRange1 ) - { - // If Alyx is not able to fire because an enemy is too close, start a timer. - // If the condition persists, allow her to ignore it and defend herself. The idea - // is to stop Alyx being content to fire point blank at enemies if she's able to move - // away, without making her defenseless if she's not able to move. - float flTime; - - if( m_flTooCloseTimer == TOOCLOSETIMER_OFF ) - { - m_flTooCloseTimer = gpGlobals->curtime; - } - - flTime = gpGlobals->curtime - m_flTooCloseTimer; - - if( flTime > ALYX_TOOCLOSETIMER ) - { - // Fake the range to allow Alyx to shoot. - flDist = m_fMinRange1 + 1.0f; - } - } - else - { - m_flTooCloseTimer = TOOCLOSETIMER_OFF; - } - - int nBaseCondition = BaseClass::WeaponRangeAttack1Condition( flDot, flDist ); - - // While in a vehicle, we extend our aiming cone (this relies on COND_NOT_FACING_ATTACK - // TODO: This needs to be rolled in at the animation level - if ( GetOwner()->IsInAVehicle() ) - { - Vector vecRoughDirection = ( GetOwner()->GetEnemy()->WorldSpaceCenter() - WorldSpaceCenter() ); - Vector vecRight; - GetVectors( NULL, &vecRight, NULL ); - bool bRightSide = ( DotProduct( vecRoughDirection, vecRight ) > 0.0f ); - float flTargetDot = ( bRightSide ) ? -0.7f : 0.0f; - - if ( nBaseCondition == COND_NOT_FACING_ATTACK && flDot >= flTargetDot ) - { - nBaseCondition = COND_CAN_RANGE_ATTACK1; - } - } - - return nBaseCondition; - -#else - - return BaseClass::WeaponRangeAttack1Condition( flDot, flDist ); - -#endif//HL2_EPISODIC -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flDot - -// flDist - -// Output : int -//----------------------------------------------------------------------------- -int CWeaponAlyxGun::WeaponRangeAttack2Condition( float flDot, float flDist ) -{ - return COND_NONE; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOperator - -//----------------------------------------------------------------------------- -void CWeaponAlyxGun::FireNPCPrimaryAttack( CBaseCombatCharacter *pOperator, bool bUseWeaponAngles ) -{ - Vector vecShootOrigin, vecShootDir; - CAI_BaseNPC *npc = pOperator->MyNPCPointer(); - ASSERT( npc != NULL ); - - if ( bUseWeaponAngles ) - { - QAngle angShootDir; - GetAttachment( LookupAttachment( "muzzle" ), vecShootOrigin, angShootDir ); - AngleVectors( angShootDir, &vecShootDir ); - } - else - { - vecShootOrigin = pOperator->Weapon_ShootPosition(); - vecShootDir = npc->GetActualShootTrajectory( vecShootOrigin ); - } - - WeaponSound( SINGLE_NPC ); - - if( hl2_episodic.GetBool() ) - { - pOperator->FireBullets( 1, vecShootOrigin, vecShootDir, VECTOR_CONE_PRECALCULATED, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 1 ); - } - else - { - pOperator->FireBullets( 1, vecShootOrigin, vecShootDir, VECTOR_CONE_PRECALCULATED, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 2 ); - } - - pOperator->DoMuzzleFlash(); - - if( hl2_episodic.GetBool() ) - { - // Never fire Alyx's last bullet just in case there's an emergency - // and she needs to be able to shoot without reloading. - if( m_iClip1 > 1 ) - { - m_iClip1 = m_iClip1 - 1; - } - } - else - { - m_iClip1 = m_iClip1 - 1; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponAlyxGun::Operator_ForceNPCFire( CBaseCombatCharacter *pOperator, bool bSecondary ) -{ - // Ensure we have enough rounds in the clip - m_iClip1++; - - // HACK: We need the gun to fire its muzzle flash - if ( bSecondary == false ) - { - SetActivity( ACT_RANGE_ATTACK_PISTOL, 0.0f ); - } - - FireNPCPrimaryAttack( pOperator, true ); -} - -//----------------------------------------------------------------------------- -void CWeaponAlyxGun::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - switch( pEvent->event ) - { - case EVENT_WEAPON_PISTOL_FIRE: - { - FireNPCPrimaryAttack( pOperator, false ); - break; - } - - default: - BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Whether or not Alyx is in the injured mode -//----------------------------------------------------------------------------- -bool IsAlyxInInjuredMode( void ) -{ - if ( hl2_episodic.GetBool() == false ) - return false; - - return ( GlobalEntity_GetState("ep2_alyx_injured") == GLOBAL_ON ); -} - -//----------------------------------------------------------------------------- -const Vector& CWeaponAlyxGun::GetBulletSpread( void ) -{ - static const Vector cone = VECTOR_CONE_2DEGREES; - static const Vector injuredCone = VECTOR_CONE_6DEGREES; - - if ( IsAlyxInInjuredMode() ) - return injuredCone; - - return cone; -} - -//----------------------------------------------------------------------------- -float CWeaponAlyxGun::GetMinRestTime( void ) -{ - if ( IsAlyxInInjuredMode() ) - return 1.5f; - - return BaseClass::GetMinRestTime(); -} - -//----------------------------------------------------------------------------- -float CWeaponAlyxGun::GetMaxRestTime( void ) -{ - if ( IsAlyxInInjuredMode() ) - return 3.0f; - - return BaseClass::GetMaxRestTime(); -} diff --git a/game/server/hl2/weapon_alyxgun.h b/game/server/hl2/weapon_alyxgun.h deleted file mode 100644 index 4fb06b9e3..000000000 --- a/game/server/hl2/weapon_alyxgun.h +++ /dev/null @@ -1,60 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef WEAPON_ALYXGUN_H -#define WEAPON_ALYXGUN_H - -#include "basehlcombatweapon.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -class CWeaponAlyxGun : public CHLSelectFireMachineGun -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( CWeaponAlyxGun, CHLSelectFireMachineGun ); - - CWeaponAlyxGun(); - ~CWeaponAlyxGun(); - - DECLARE_SERVERCLASS(); - - void Precache( void ); - - virtual int GetMinBurst( void ) { return 4; } - virtual int GetMaxBurst( void ) { return 7; } - virtual float GetMinRestTime( void ); - virtual float GetMaxRestTime( void ); - - virtual void Equip( CBaseCombatCharacter *pOwner ); - - float GetFireRate( void ) { return 0.1f; } - int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } - int WeaponRangeAttack1Condition( float flDot, float flDist ); - int WeaponRangeAttack2Condition( float flDot, float flDist ); - - virtual const Vector& GetBulletSpread( void ); - - void FireNPCPrimaryAttack( CBaseCombatCharacter *pOperator, bool bUseWeaponAngles ); - - void Operator_ForceNPCFire( CBaseCombatCharacter *pOperator, bool bSecondary ); - void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); - - virtual void SetPickupTouch( void ) - { - // Alyx gun cannot be picked up - SetTouch(NULL); - } - - float m_flTooCloseTimer; - - DECLARE_ACTTABLE(); - -}; - -#endif // WEAPON_ALYXGUN_H diff --git a/game/server/hl2/weapon_annabelle.cpp b/game/server/hl2/weapon_annabelle.cpp deleted file mode 100644 index c46067832..000000000 --- a/game/server/hl2/weapon_annabelle.cpp +++ /dev/null @@ -1,348 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Grigori's personal shotgun (npc_monk) -// -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" -#include "basehlcombatweapon_shared.h" -#include "basecombatcharacter.h" -#include "ai_basenpc.h" -#include "player.h" -#include "gamerules.h" // For g_pGameRules -#include "in_buttons.h" -#include "soundent.h" -#include "vstdlib/random.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern ConVar sk_auto_reload_time; - -class CWeaponAnnabelle : public CBaseHLCombatWeapon -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( CWeaponAnnabelle, CBaseHLCombatWeapon ); - - DECLARE_SERVERCLASS(); - -private: - bool m_bNeedPump; // When emptied completely - bool m_bDelayedFire1; // Fire primary when finished reloading - bool m_bDelayedFire2; // Fire secondary when finished reloading - -public: - void Precache( void ); - - int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } - - virtual const Vector& GetBulletSpread( void ) - { - static Vector cone = vec3_origin; - return cone; - } - - virtual int GetMinBurst() { return 1; } - virtual int GetMaxBurst() { return 3; } - - void ItemHolsterFrame( void ); - bool StartReload( void ); - bool Reload( void ); - void FillClip( void ); - void FinishReload( void ); - void CheckHolsterReload( void ); - void Pump( void ); - void DryFire( void ); - virtual float GetFireRate( void ) { return 1.5; }; - virtual float GetMinRestTime() { return 1.0; } - virtual float GetMaxRestTime() { return 1.5; } - - void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); - - DECLARE_ACTTABLE(); - - CWeaponAnnabelle(void); -}; - -IMPLEMENT_SERVERCLASS_ST(CWeaponAnnabelle, DT_WeaponAnnabelle) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_annabelle, CWeaponAnnabelle ); -PRECACHE_WEAPON_REGISTER(weapon_annabelle); - -BEGIN_DATADESC( CWeaponAnnabelle ) - DEFINE_FIELD( m_bNeedPump, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bDelayedFire1, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bDelayedFire2, FIELD_BOOLEAN ), -END_DATADESC() - -acttable_t CWeaponAnnabelle::m_acttable[] = -{ - { ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_SMG1, true }, - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SHOTGUN, true }, - { ACT_RELOAD, ACT_RELOAD_SMG1, true }, - { ACT_WALK, ACT_WALK_RIFLE, true }, - { ACT_WALK_AIM, ACT_WALK_AIM_RIFLE, true }, - { ACT_WALK_CROUCH, ACT_WALK_CROUCH_RIFLE, false }, - { ACT_WALK_CROUCH_AIM, ACT_WALK_CROUCH_AIM_RIFLE, false }, - { ACT_RUN, ACT_RUN_RIFLE, true }, - { ACT_RUN_AIM, ACT_RUN_AIM_RIFLE, true }, - { ACT_RUN_CROUCH, ACT_RUN_CROUCH_RIFLE, false }, - { ACT_RUN_CROUCH_AIM, ACT_RUN_CROUCH_AIM_RIFLE, false }, - { ACT_GESTURE_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK_SHOTGUN, true }, - { ACT_RELOAD_LOW, ACT_RELOAD_SMG1_LOW, false }, - { ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SMG1, false }, -}; - -IMPLEMENT_ACTTABLE(CWeaponAnnabelle); - -void CWeaponAnnabelle::Precache( void ) -{ - CBaseCombatWeapon::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeaponAnnabelle::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - switch( pEvent->event ) - { - case EVENT_WEAPON_SHOTGUN_FIRE: - { - Vector vecShootOrigin, vecShootDir; - vecShootOrigin = pOperator->Weapon_ShootPosition(); - CAI_BaseNPC *npc = pOperator->MyNPCPointer(); - ASSERT( npc != NULL ); - WeaponSound( SINGLE_NPC ); - pOperator->DoMuzzleFlash(); - m_iClip1 = m_iClip1 - 1; - - vecShootDir = npc->GetActualShootTrajectory( vecShootOrigin ); - pOperator->FireBullets( 1, vecShootOrigin, vecShootDir, VECTOR_CONE_PRECALCULATED, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 0 ); - } - break; - - default: - CBaseCombatWeapon::Operator_HandleAnimEvent( pEvent, pOperator ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Override so only reload one shell at a time -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CWeaponAnnabelle::StartReload( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - return false; - - if (pOwner->GetAmmoCount(m_iPrimaryAmmoType) <= 0) - return false; - - if (m_iClip1 >= GetMaxClip1()) - return false; - - // If shotgun totally emptied then a pump animation is needed - if (m_iClip1 <= 0) - { - m_bNeedPump = true; - } - - int j = MIN(1, pOwner->GetAmmoCount(m_iPrimaryAmmoType)); - - if (j <= 0) - return false; - - SendWeaponAnim( ACT_SHOTGUN_RELOAD_START ); - - // Make shotgun shell visible - SetBodygroup(1,0); - - pOwner->m_flNextAttack = gpGlobals->curtime; - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - - m_bInReload = true; - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Override so only reload one shell at a time -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CWeaponAnnabelle::Reload( void ) -{ - // Check that StartReload was called first - if (!m_bInReload) - { - Warning("ERROR: Shotgun Reload called incorrectly!\n"); - } - - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - return false; - - if (pOwner->GetAmmoCount(m_iPrimaryAmmoType) <= 0) - return false; - - if (m_iClip1 >= GetMaxClip1()) - return false; - - int j = MIN(1, pOwner->GetAmmoCount(m_iPrimaryAmmoType)); - - if (j <= 0) - return false; - - FillClip(); - // Play reload on different channel as otherwise steals channel away from fire sound - WeaponSound(RELOAD); - SendWeaponAnim( ACT_VM_RELOAD ); - - pOwner->m_flNextAttack = gpGlobals->curtime; - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Play finish reload anim and fill clip -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeaponAnnabelle::FinishReload( void ) -{ - // Make shotgun shell invisible - SetBodygroup(1,1); - - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - return; - - m_bInReload = false; - - // Finish reload animation - SendWeaponAnim( ACT_SHOTGUN_RELOAD_FINISH ); - - pOwner->m_flNextAttack = gpGlobals->curtime; - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); -} - -//----------------------------------------------------------------------------- -// Purpose: Play finish reload anim and fill clip -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeaponAnnabelle::FillClip( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - return; - - // Add them to the clip - if ( pOwner->GetAmmoCount( m_iPrimaryAmmoType ) > 0 ) - { - if ( Clip1() < GetMaxClip1() ) - { - m_iClip1++; - pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Play weapon pump anim -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeaponAnnabelle::Pump( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - return; - - m_bNeedPump = false; - - WeaponSound( SPECIAL1 ); - - // Finish reload animation - SendWeaponAnim( ACT_SHOTGUN_PUMP ); - - pOwner->m_flNextAttack = gpGlobals->curtime + SequenceDuration(); - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CWeaponAnnabelle::DryFire( void ) -{ - WeaponSound(EMPTY); - SendWeaponAnim( ACT_VM_DRYFIRE ); - - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponAnnabelle::ItemHolsterFrame( void ) -{ - // Must be player held - if ( GetOwner() && GetOwner()->IsPlayer() == false ) - return; - - // We can't be active - if ( GetOwner()->GetActiveWeapon() == this ) - return; - - // If it's been longer than three seconds, reload - if ( ( gpGlobals->curtime - m_flHolsterTime ) > sk_auto_reload_time.GetFloat() ) - { - // Reset the timer - m_flHolsterTime = gpGlobals->curtime; - - if ( GetOwner() == NULL ) - return; - - if ( m_iClip1 == GetMaxClip1() ) - return; - - // Just load the clip with no animations - int ammoFill = MIN( (GetMaxClip1() - m_iClip1), GetOwner()->GetAmmoCount( GetPrimaryAmmoType() ) ); - - GetOwner()->RemoveAmmo( ammoFill, GetPrimaryAmmoType() ); - m_iClip1 += ammoFill; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -CWeaponAnnabelle::CWeaponAnnabelle( void ) -{ - m_bReloadsSingly = true; - - m_bNeedPump = false; - m_bDelayedFire1 = false; - m_bDelayedFire2 = false; - - m_fMinRange1 = 0.0; - m_fMaxRange1 = 500; - m_fMinRange2 = 0.0; - m_fMaxRange2 = 200; -} diff --git a/game/server/hl2/weapon_ar1.cpp b/game/server/hl2/weapon_ar1.cpp deleted file mode 100644 index 3cb0415bd..000000000 --- a/game/server/hl2/weapon_ar1.cpp +++ /dev/null @@ -1,182 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "basehlcombatweapon.h" -#include "npcevent.h" -#include "basecombatcharacter.h" -#include "ai_basenpc.h" -#include "player.h" -#include "in_buttons.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define DAMAGE_PER_SECOND 10 - -#define MAX_SETTINGS 5 - -float RateOfFire[ MAX_SETTINGS ] = -{ - 0.1, - 0.2, - 0.5, - 0.7, - 1.0, -}; - -float Damage[ MAX_SETTINGS ] = -{ - 2, - 4, - 10, - 14, - 20, -}; - - -//========================================================= -//========================================================= -class CWeaponAR1 : public CHLMachineGun -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( CWeaponAR1, CHLMachineGun ); - - DECLARE_SERVERCLASS(); - - CWeaponAR1(); - - int m_ROF; - - void Precache( void ); - bool Deploy( void ); - - float GetFireRate( void ) {return RateOfFire[ m_ROF ];} - - int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } - - void SecondaryAttack( void ); - - virtual void FireBullets( const FireBulletsInfo_t &info ); - - virtual const Vector& GetBulletSpread( void ) - { - static const Vector cone = VECTOR_CONE_10DEGREES; - return cone; - } - - void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) - { - switch( pEvent->event ) - { - case EVENT_WEAPON_AR1: - { - Vector vecShootOrigin, vecShootDir; - vecShootOrigin = pOperator->Weapon_ShootPosition( ); - - CAI_BaseNPC *npc = pOperator->MyNPCPointer(); - ASSERT( npc != NULL ); - - vecShootDir = npc->GetActualShootTrajectory( vecShootOrigin ); - - WeaponSound(SINGLE_NPC); - pOperator->FireBullets( 1, vecShootOrigin, vecShootDir, VECTOR_CONE_PRECALCULATED, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 2 ); - pOperator->DoMuzzleFlash(); - } - break; - default: - CBaseCombatWeapon::Operator_HandleAnimEvent( pEvent, pOperator ); - break; - } - } - DECLARE_ACTTABLE(); -}; - -IMPLEMENT_SERVERCLASS_ST(CWeaponAR1, DT_WeaponAR1) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_ar1, CWeaponAR1 ); -PRECACHE_WEAPON_REGISTER(weapon_ar1); - -acttable_t CWeaponAR1::m_acttable[] = -{ - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_AR1, true }, -}; - -IMPLEMENT_ACTTABLE(CWeaponAR1); - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CWeaponAR1 ) - - DEFINE_FIELD( m_ROF, FIELD_INTEGER ), - -END_DATADESC() - - -CWeaponAR1::CWeaponAR1( ) -{ - m_ROF = 0; -} - -void CWeaponAR1::Precache( void ) -{ - BaseClass::Precache(); -} - -bool CWeaponAR1::Deploy( void ) -{ - //CBaseCombatCharacter *pOwner = m_hOwner; - return BaseClass::Deploy(); -} - - -//========================================================= -//========================================================= -void CWeaponAR1::FireBullets( const FireBulletsInfo_t &info ) -{ - if(CBasePlayer *pPlayer = ToBasePlayer( GetOwner() )) - { - pPlayer->FireBullets( info ); - } -} - - -void CWeaponAR1::SecondaryAttack( void ) -{ - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - if ( pPlayer ) - { - pPlayer->m_nButtons &= ~IN_ATTACK2; - } - - m_flNextSecondaryAttack = gpGlobals->curtime + 0.1; - - m_ROF += 1; - - if( m_ROF == MAX_SETTINGS ) - { - m_ROF = 0; - } - - int i; - - Msg( "\n" ); - for( i = 0 ; i < MAX_SETTINGS ; i++ ) - { - if( i == m_ROF ) - { - Msg( "|" ); - } - else - { - Msg( "-" ); - } - } - Msg( "\n" ); -} diff --git a/game/server/hl2/weapon_ar2.cpp b/game/server/hl2/weapon_ar2.cpp deleted file mode 100644 index 2b8fdd198..000000000 --- a/game/server/hl2/weapon_ar2.cpp +++ /dev/null @@ -1,512 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "basecombatweapon.h" -#include "npcevent.h" -#include "basecombatcharacter.h" -#include "ai_basenpc.h" -#include "player.h" -#include "weapon_ar2.h" -#include "grenade_ar2.h" -#include "gamerules.h" -#include "game.h" -#include "in_buttons.h" -#include "ai_memory.h" -#include "soundent.h" -#include "hl2_player.h" -#include "EntityFlame.h" -#include "weapon_flaregun.h" -#include "te_effect_dispatch.h" -#include "prop_combine_ball.h" -#include "beam_shared.h" -#include "npc_combine.h" -#include "rumble_shared.h" -#include "GameStats.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar sk_weapon_ar2_alt_fire_radius( "sk_weapon_ar2_alt_fire_radius", "10" ); -ConVar sk_weapon_ar2_alt_fire_duration( "sk_weapon_ar2_alt_fire_duration", "2" ); -ConVar sk_weapon_ar2_alt_fire_mass( "sk_weapon_ar2_alt_fire_mass", "150" ); - -//========================================================= -//========================================================= - -BEGIN_DATADESC( CWeaponAR2 ) - - DEFINE_FIELD( m_flDelayedFire, FIELD_TIME ), - DEFINE_FIELD( m_bShotDelayed, FIELD_BOOLEAN ), - //DEFINE_FIELD( m_nVentPose, FIELD_INTEGER ), - -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST(CWeaponAR2, DT_WeaponAR2) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_ar2, CWeaponAR2 ); -PRECACHE_WEAPON_REGISTER(weapon_ar2); - -acttable_t CWeaponAR2::m_acttable[] = -{ - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_AR2, true }, - { ACT_RELOAD, ACT_RELOAD_SMG1, true }, // FIXME: hook to AR2 unique - { ACT_IDLE, ACT_IDLE_SMG1, true }, // FIXME: hook to AR2 unique - { ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_SMG1, true }, // FIXME: hook to AR2 unique - - { ACT_WALK, ACT_WALK_RIFLE, true }, - -// Readiness activities (not aiming) - { ACT_IDLE_RELAXED, ACT_IDLE_SMG1_RELAXED, false },//never aims - { ACT_IDLE_STIMULATED, ACT_IDLE_SMG1_STIMULATED, false }, - { ACT_IDLE_AGITATED, ACT_IDLE_ANGRY_SMG1, false },//always aims - - { ACT_WALK_RELAXED, ACT_WALK_RIFLE_RELAXED, false },//never aims - { ACT_WALK_STIMULATED, ACT_WALK_RIFLE_STIMULATED, false }, - { ACT_WALK_AGITATED, ACT_WALK_AIM_RIFLE, false },//always aims - - { ACT_RUN_RELAXED, ACT_RUN_RIFLE_RELAXED, false },//never aims - { ACT_RUN_STIMULATED, ACT_RUN_RIFLE_STIMULATED, false }, - { ACT_RUN_AGITATED, ACT_RUN_AIM_RIFLE, false },//always aims - -// Readiness activities (aiming) - { ACT_IDLE_AIM_RELAXED, ACT_IDLE_SMG1_RELAXED, false },//never aims - { ACT_IDLE_AIM_STIMULATED, ACT_IDLE_AIM_RIFLE_STIMULATED, false }, - { ACT_IDLE_AIM_AGITATED, ACT_IDLE_ANGRY_SMG1, false },//always aims - - { ACT_WALK_AIM_RELAXED, ACT_WALK_RIFLE_RELAXED, false },//never aims - { ACT_WALK_AIM_STIMULATED, ACT_WALK_AIM_RIFLE_STIMULATED, false }, - { ACT_WALK_AIM_AGITATED, ACT_WALK_AIM_RIFLE, false },//always aims - - { ACT_RUN_AIM_RELAXED, ACT_RUN_RIFLE_RELAXED, false },//never aims - { ACT_RUN_AIM_STIMULATED, ACT_RUN_AIM_RIFLE_STIMULATED, false }, - { ACT_RUN_AIM_AGITATED, ACT_RUN_AIM_RIFLE, false },//always aims -//End readiness activities - - { ACT_WALK_AIM, ACT_WALK_AIM_RIFLE, true }, - { ACT_WALK_CROUCH, ACT_WALK_CROUCH_RIFLE, true }, - { ACT_WALK_CROUCH_AIM, ACT_WALK_CROUCH_AIM_RIFLE, true }, - { ACT_RUN, ACT_RUN_RIFLE, true }, - { ACT_RUN_AIM, ACT_RUN_AIM_RIFLE, true }, - { ACT_RUN_CROUCH, ACT_RUN_CROUCH_RIFLE, true }, - { ACT_RUN_CROUCH_AIM, ACT_RUN_CROUCH_AIM_RIFLE, true }, - { ACT_GESTURE_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK_AR2, false }, - { ACT_COVER_LOW, ACT_COVER_SMG1_LOW, false }, // FIXME: hook to AR2 unique - { ACT_RANGE_AIM_LOW, ACT_RANGE_AIM_AR2_LOW, false }, - { ACT_RANGE_ATTACK1_LOW, ACT_RANGE_ATTACK_SMG1_LOW, true }, // FIXME: hook to AR2 unique - { ACT_RELOAD_LOW, ACT_RELOAD_SMG1_LOW, false }, - { ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SMG1, true }, -// { ACT_RANGE_ATTACK2, ACT_RANGE_ATTACK_AR2_GRENADE, true }, -}; - -IMPLEMENT_ACTTABLE(CWeaponAR2); - -CWeaponAR2::CWeaponAR2( ) -{ - m_fMinRange1 = 65; - m_fMaxRange1 = 2048; - - m_fMinRange2 = 256; - m_fMaxRange2 = 1024; - - m_nShotsFired = 0; - m_nVentPose = -1; - - m_bAltFiresUnderwater = false; -} - -void CWeaponAR2::Precache( void ) -{ - BaseClass::Precache(); - - UTIL_PrecacheOther( "prop_combine_ball" ); - UTIL_PrecacheOther( "env_entity_dissolver" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Handle grenade detonate in-air (even when no ammo is left) -//----------------------------------------------------------------------------- -void CWeaponAR2::ItemPostFrame( void ) -{ - // See if we need to fire off our secondary round - if ( m_bShotDelayed && gpGlobals->curtime > m_flDelayedFire ) - { - DelayedAttack(); - } - - // Update our pose parameter for the vents - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner ) - { - CBaseViewModel *pVM = pOwner->GetViewModel(); - - if ( pVM ) - { - if ( m_nVentPose == -1 ) - { - m_nVentPose = pVM->LookupPoseParameter( "VentPoses" ); - } - - float flVentPose = RemapValClamped( m_nShotsFired, 0, 5, 0.0f, 1.0f ); - pVM->SetPoseParameter( m_nVentPose, flVentPose ); - } - } - - BaseClass::ItemPostFrame(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Activity -//----------------------------------------------------------------------------- -Activity CWeaponAR2::GetPrimaryAttackActivity( void ) -{ - if ( m_nShotsFired < 2 ) - return ACT_VM_PRIMARYATTACK; - - if ( m_nShotsFired < 3 ) - return ACT_VM_RECOIL1; - - if ( m_nShotsFired < 4 ) - return ACT_VM_RECOIL2; - - return ACT_VM_RECOIL3; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &tr - -// nDamageType - -//----------------------------------------------------------------------------- -void CWeaponAR2::DoImpactEffect( trace_t &tr, int nDamageType ) -{ - CEffectData data; - - data.m_vOrigin = tr.endpos + ( tr.plane.normal * 1.0f ); - data.m_vNormal = tr.plane.normal; - - DispatchEffect( "AR2Impact", data ); - - BaseClass::DoImpactEffect( tr, nDamageType ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponAR2::DelayedAttack( void ) -{ - m_bShotDelayed = false; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - // Deplete the clip completely - SendWeaponAnim( ACT_VM_SECONDARYATTACK ); - m_flNextSecondaryAttack = pOwner->m_flNextAttack = gpGlobals->curtime + SequenceDuration(); - - // Register a muzzleflash for the AI - pOwner->DoMuzzleFlash(); - pOwner->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 ); - - WeaponSound( WPN_DOUBLE ); - - pOwner->RumbleEffect(RUMBLE_SHOTGUN_DOUBLE, 0, RUMBLE_FLAG_RESTART ); - - // Fire the bullets - Vector vecSrc = pOwner->Weapon_ShootPosition( ); - Vector vecAiming = pOwner->GetAutoaimVector( AUTOAIM_SCALE_DEFAULT ); - Vector impactPoint = vecSrc + ( vecAiming * MAX_TRACE_LENGTH ); - - // Fire the bullets - Vector vecVelocity = vecAiming * 1000.0f; - - // Fire the combine ball - CreateCombineBall( vecSrc, - vecVelocity, - sk_weapon_ar2_alt_fire_radius.GetFloat(), - sk_weapon_ar2_alt_fire_mass.GetFloat(), - sk_weapon_ar2_alt_fire_duration.GetFloat(), - pOwner ); - - // View effects - color32 white = {255, 255, 255, 64}; - UTIL_ScreenFade( pOwner, white, 0.1, 0, FFADE_IN ); - - //Disorient the player - QAngle angles = pOwner->GetLocalAngles(); - - angles.x += random->RandomInt( -4, 4 ); - angles.y += random->RandomInt( -4, 4 ); - angles.z = 0; - - pOwner->SnapEyeAngles( angles ); - - pOwner->ViewPunch( QAngle( random->RandomInt( -8, -12 ), random->RandomInt( 1, 2 ), 0 ) ); - - // Decrease ammo - pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType ); - - // Can shoot again immediately - m_flNextPrimaryAttack = gpGlobals->curtime + 0.5f; - - // Can blow up after a short delay (so have time to release mouse button) - m_flNextSecondaryAttack = gpGlobals->curtime + 1.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponAR2::SecondaryAttack( void ) -{ - if ( m_bShotDelayed ) - return; - - // Cannot fire underwater - if ( GetOwner() && GetOwner()->GetWaterLevel() == 3 ) - { - SendWeaponAnim( ACT_VM_DRYFIRE ); - BaseClass::WeaponSound( EMPTY ); - m_flNextSecondaryAttack = gpGlobals->curtime + 0.5f; - return; - } - - m_bShotDelayed = true; - m_flNextPrimaryAttack = m_flNextSecondaryAttack = m_flDelayedFire = gpGlobals->curtime + 0.5f; - - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - if( pPlayer ) - { - pPlayer->RumbleEffect(RUMBLE_AR2_ALT_FIRE, 0, RUMBLE_FLAG_RESTART ); - } - - SendWeaponAnim( ACT_VM_FIDGET ); - WeaponSound( SPECIAL1 ); - - m_iSecondaryAttacks++; - gamestats->Event_WeaponFired( pPlayer, false, GetClassname() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Override if we're waiting to release a shot -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponAR2::CanHolster( void ) -{ - if ( m_bShotDelayed ) - return false; - - return BaseClass::CanHolster(); -} - -//----------------------------------------------------------------------------- -// Purpose: Override if we're waiting to release a shot -//----------------------------------------------------------------------------- -bool CWeaponAR2::Reload( void ) -{ - if ( m_bShotDelayed ) - return false; - - return BaseClass::Reload(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOperator - -//----------------------------------------------------------------------------- -void CWeaponAR2::FireNPCPrimaryAttack( CBaseCombatCharacter *pOperator, bool bUseWeaponAngles ) -{ - Vector vecShootOrigin, vecShootDir; - - CAI_BaseNPC *npc = pOperator->MyNPCPointer(); - ASSERT( npc != NULL ); - - if ( bUseWeaponAngles ) - { - QAngle angShootDir; - GetAttachment( LookupAttachment( "muzzle" ), vecShootOrigin, angShootDir ); - AngleVectors( angShootDir, &vecShootDir ); - } - else - { - vecShootOrigin = pOperator->Weapon_ShootPosition(); - vecShootDir = npc->GetActualShootTrajectory( vecShootOrigin ); - } - - WeaponSoundRealtime( SINGLE_NPC ); - - CSoundEnt::InsertSound( SOUND_COMBAT|SOUND_CONTEXT_GUNFIRE, pOperator->GetAbsOrigin(), SOUNDENT_VOLUME_MACHINEGUN, 0.2, pOperator, SOUNDENT_CHANNEL_WEAPON, pOperator->GetEnemy() ); - - pOperator->FireBullets( 1, vecShootOrigin, vecShootDir, VECTOR_CONE_PRECALCULATED, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 2 ); - - // NOTENOTE: This is overriden on the client-side - // pOperator->DoMuzzleFlash(); - - m_iClip1 = m_iClip1 - 1; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponAR2::FireNPCSecondaryAttack( CBaseCombatCharacter *pOperator, bool bUseWeaponAngles ) -{ - WeaponSound( WPN_DOUBLE ); - - if ( !GetOwner() ) - return; - - CAI_BaseNPC *pNPC = GetOwner()->MyNPCPointer(); - if ( !pNPC ) - return; - - // Fire! - Vector vecSrc; - Vector vecAiming; - - if ( bUseWeaponAngles ) - { - QAngle angShootDir; - GetAttachment( LookupAttachment( "muzzle" ), vecSrc, angShootDir ); - AngleVectors( angShootDir, &vecAiming ); - } - else - { - vecSrc = pNPC->Weapon_ShootPosition( ); - - Vector vecTarget; - - CNPC_Combine *pSoldier = dynamic_cast( pNPC ); - if ( pSoldier ) - { - // In the distant misty past, elite soldiers tried to use bank shots. - // Therefore, we must ask them specifically what direction they are shooting. - vecTarget = pSoldier->GetAltFireTarget(); - } - else - { - // All other users of the AR2 alt-fire shoot directly at their enemy. - if ( !pNPC->GetEnemy() ) - return; - - vecTarget = pNPC->GetEnemy()->BodyTarget( vecSrc ); - } - - vecAiming = vecTarget - vecSrc; - VectorNormalize( vecAiming ); - } - - Vector impactPoint = vecSrc + ( vecAiming * MAX_TRACE_LENGTH ); - - float flAmmoRatio = 1.0f; - float flDuration = RemapValClamped( flAmmoRatio, 0.0f, 1.0f, 0.5f, sk_weapon_ar2_alt_fire_duration.GetFloat() ); - float flRadius = RemapValClamped( flAmmoRatio, 0.0f, 1.0f, 4.0f, sk_weapon_ar2_alt_fire_radius.GetFloat() ); - - // Fire the bullets - Vector vecVelocity = vecAiming * 1000.0f; - - // Fire the combine ball - CreateCombineBall( vecSrc, - vecVelocity, - flRadius, - sk_weapon_ar2_alt_fire_mass.GetFloat(), - flDuration, - pNPC ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponAR2::Operator_ForceNPCFire( CBaseCombatCharacter *pOperator, bool bSecondary ) -{ - if ( bSecondary ) - { - FireNPCSecondaryAttack( pOperator, true ); - } - else - { - // Ensure we have enough rounds in the clip - m_iClip1++; - - FireNPCPrimaryAttack( pOperator, true ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEvent - -// *pOperator - -//----------------------------------------------------------------------------- -void CWeaponAR2::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - switch( pEvent->event ) - { - case EVENT_WEAPON_AR2: - { - FireNPCPrimaryAttack( pOperator, false ); - } - break; - - case EVENT_WEAPON_AR2_ALTFIRE: - { - FireNPCSecondaryAttack( pOperator, false ); - } - break; - - default: - CBaseCombatWeapon::Operator_HandleAnimEvent( pEvent, pOperator ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponAR2::AddViewKick( void ) -{ - #define EASY_DAMPEN 0.5f - #define MAX_VERTICAL_KICK 8.0f //Degrees - #define SLIDE_LIMIT 5.0f //Seconds - - //Get the view kick - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if (!pPlayer) - return; - - float flDuration = m_fFireDuration; - - if( g_pGameRules->GetAutoAimMode() == AUTOAIM_ON_CONSOLE ) - { - // On the 360 (or in any configuration using the 360 aiming scheme), don't let the - // AR2 progressive into the late, highly inaccurate stages of its kick. Just - // spoof the time to make it look (to the kicking code) like we haven't been - // firing for very long. - flDuration = MIN( flDuration, 0.75f ); - } - - DoMachineGunKick( pPlayer, EASY_DAMPEN, MAX_VERTICAL_KICK, flDuration, SLIDE_LIMIT ); -} - -//----------------------------------------------------------------------------- -const WeaponProficiencyInfo_t *CWeaponAR2::GetProficiencyValues() -{ - static WeaponProficiencyInfo_t proficiencyTable[] = - { - { 7.0, 0.75 }, - { 5.00, 0.75 }, - { 3.0, 0.85 }, - { 5.0/3.0, 0.75 }, - { 1.00, 1.0 }, - }; - - COMPILE_TIME_ASSERT( ARRAYSIZE(proficiencyTable) == WEAPON_PROFICIENCY_PERFECT + 1); - - return proficiencyTable; -} diff --git a/game/server/hl2/weapon_ar2.h b/game/server/hl2/weapon_ar2.h deleted file mode 100644 index 75043b299..000000000 --- a/game/server/hl2/weapon_ar2.h +++ /dev/null @@ -1,79 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Projectile shot from the AR2 -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef WEAPONAR2_H -#define WEAPONAR2_H - -#include "basegrenade_shared.h" -#include "basehlcombatweapon.h" - -class CWeaponAR2 : public CHLMachineGun -{ -public: - DECLARE_CLASS( CWeaponAR2, CHLMachineGun ); - - CWeaponAR2(); - - DECLARE_SERVERCLASS(); - - void ItemPostFrame( void ); - void Precache( void ); - - void SecondaryAttack( void ); - void DelayedAttack( void ); - - const char *GetTracerType( void ) { return "AR2Tracer"; } - - void AddViewKick( void ); - - void FireNPCPrimaryAttack( CBaseCombatCharacter *pOperator, bool bUseWeaponAngles ); - void FireNPCSecondaryAttack( CBaseCombatCharacter *pOperator, bool bUseWeaponAngles ); - void Operator_ForceNPCFire( CBaseCombatCharacter *pOperator, bool bSecondary ); - void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); - - int GetMinBurst( void ) { return 2; } - int GetMaxBurst( void ) { return 5; } - float GetFireRate( void ) { return 0.1f; } - - bool CanHolster( void ); - bool Reload( void ); - - int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } - - Activity GetPrimaryAttackActivity( void ); - - void DoImpactEffect( trace_t &tr, int nDamageType ); - - virtual const Vector& GetBulletSpread( void ) - { - static Vector cone; - - cone = VECTOR_CONE_3DEGREES; - - return cone; - } - - const WeaponProficiencyInfo_t *GetProficiencyValues(); - -protected: - - float m_flDelayedFire; - bool m_bShotDelayed; - int m_nVentPose; - - DECLARE_ACTTABLE(); - DECLARE_DATADESC(); -}; - - -#endif //WEAPONAR2_H diff --git a/game/server/hl2/weapon_brickbat.cpp b/game/server/hl2/weapon_brickbat.cpp deleted file mode 100644 index 82b9626b4..000000000 --- a/game/server/hl2/weapon_brickbat.cpp +++ /dev/null @@ -1,663 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: This is the brickbat weapon -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" -#include "basehlcombatweapon.h" -#include "basecombatcharacter.h" -#include "ai_basenpc.h" -#include "ai_memory.h" -#include "player.h" -#include "gamerules.h" // For g_pGameRules -#include "weapon_brickbat.h" -#include "grenade_brickbat.h" -#include "ammodef.h" -#include "in_buttons.h" -#include "game.h" -#include "IEffects.h" -#include "vstdlib/random.h" -#include "baseviewmodel.h" -#include "movevars_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern ConVar sk_npc_dmg_brickbat; -extern ConVar sk_plr_dmg_brickbat; - -struct BrickbatAmmo_s -{ - const char *m_sClassName; - int m_nAmmoType; - int m_nMaxCarry; - const char *m_sViewModel; - const char *m_sWorldModel; -}; - -BrickbatAmmo_s BrickBatAmmoArray[NUM_BRICKBAT_AMMO_TYPES] = -{ - { "grenade_rockbb", BRICKBAT_ROCK, 5, "models/weapons/v_bb_bottle.mdl", "models/props_junk/Rock001a.mdl" }, - { "grenade_beerbottle", BRICKBAT_BOTTLE, 3, "models/weapons/v_bb_bottle.mdl", "models/weapons/w_bb_bottle.mdl" }, -}; - -IMPLEMENT_SERVERCLASS_ST(CWeaponBrickbat, DT_WeaponBrickbat) -END_SEND_TABLE() - -//LINK_ENTITY_TO_CLASS( weapon_brickbat, CWeaponBrickbat ); -//PRECACHE_WEAPON_REGISTER(weapon_brickbat); - -acttable_t CWeaponBrickbat::m_acttable[] = -{ - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_THROW, true }, -}; -IMPLEMENT_ACTTABLE(CWeaponBrickbat); - - - -BEGIN_DATADESC( CWeaponBrickbat ) - - DEFINE_FIELD( m_bNeedDraw, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bNeedThrow, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iThrowBits, FIELD_INTEGER ), - DEFINE_FIELD( m_fNextThrowCheck, FIELD_TIME ), - DEFINE_FIELD( m_vecTossVelocity, FIELD_VECTOR ), - DEFINE_ARRAY( m_nAmmoCount, FIELD_INTEGER, NUM_BRICKBAT_AMMO_TYPES ), - DEFINE_KEYFIELD( m_iCurrentAmmoType, FIELD_INTEGER, "BrickbatType" ), - - // Function Pointers - DEFINE_FUNCTION( BrickbatTouch ), - -END_DATADESC() - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CWeaponBrickbat::Precache( void ) -{ - for (size_t i = 0; i < ARRAYSIZE(BrickBatAmmoArray); i++) - { - PrecacheModel(BrickBatAmmoArray[i].m_sWorldModel); - PrecacheModel(BrickBatAmmoArray[i].m_sViewModel); - } - - UTIL_PrecacheOther("grenade_molotov"); - - BaseClass::Precache(); -} - -void CWeaponBrickbat::Spawn( void ) -{ - m_bNeedDraw = true; - m_bNeedThrow = false; - - for (int i=0;iUseTriggerBounds( false ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const char *CWeaponBrickbat::GetViewModel( int viewmodelindex /*=0*/ ) -{ - return BrickBatAmmoArray[m_iCurrentAmmoType].m_sViewModel; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const char *CWeaponBrickbat::GetWorldModel( void ) -{ - return BrickBatAmmoArray[m_iCurrentAmmoType].m_sWorldModel; -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -bool CWeaponBrickbat::Deploy( void ) -{ - SetModel( GetViewModel() ); - m_bNeedDraw = false; - m_bNeedThrow = false; - return DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), ACT_VM_DRAW, (char*)GetAnimPrefix() ); -} - -//------------------------------------------------------------------------------ -// Purpose : Override to use brickbats pickup touch function -// Input : -// Output : -//------------------------------------------------------------------------------ -void CWeaponBrickbat::SetPickupTouch( void ) -{ - SetTouch( &CWeaponBrickbat::BrickbatTouch ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Override so give correct ammo -// Input : pOther - the entity that touched me -// Output : -//----------------------------------------------------------------------------- -void CWeaponBrickbat::BrickbatTouch( CBaseEntity *pOther ) -{ - // --------------------------------------------------- - // First give weapon to touching entity if allowed - // Skip ammo given portion by setting clips to zero - // and handle ammo giving here - // --------------------------------------------------- - BaseClass::DefaultTouch(pOther); - - //FIXME: This ammo handling code is a bit bogus, need a real solution if brickbats are going to live - - /* - // ---------------------------------------------------- - // Give brickbat ammo if touching client - // ---------------------------------------------------- - if (pOther->GetFlags() & FL_CLIENT) - { - CBaseCombatCharacter* pBCC = ToBaseCombatCharacter( pOther ); - - // Exit if game rules say I can't have any more of this ammo type. - if ( g_pGameRules->CanHaveAmmo( pBCC, m_iPrimaryAmmoType ) == false ) - return; - - // ------------------------------------------------ - // If already owned weapon of this type remove me - // ------------------------------------------------ - CWeaponBrickbat* oldWeapon = (CWeaponBrickbat*)pBCC->Weapon_OwnsThisType( GetClassname() ); - - // Remove physics object if is one - VPhysicsDestroyObject(); - - if ( ( oldWeapon != NULL ) && ( oldWeapon != this ) ) - { - // Only pick up if not at max ammo amount - if (oldWeapon->m_nAmmoCount[m_iCurrentAmmoType] < BrickBatAmmoArray[m_iCurrentAmmoType].m_nMaxCarry) - { - oldWeapon->m_nAmmoCount[m_iCurrentAmmoType]++; - pBCC->GiveAmmo( 1, oldWeapon->m_iPrimaryAmmoType ); - UTIL_Remove( this ); - } - } - else - { - // Only pick up if not at max ammo amount - if (m_nAmmoCount[m_iCurrentAmmoType] < BrickBatAmmoArray[m_iCurrentAmmoType].m_nMaxCarry) - { - m_nAmmoCount[m_iCurrentAmmoType]++; - pBCC->GiveAmmo( 1, m_iPrimaryAmmoType ); - - SetThink (NULL); - } - } - - // ----------------------------------------------------- - // Switch to this weapon if the only weapon I own - // ----------------------------------------------------- - if (!pBCC->GetActiveWeapon() && pBCC->GetActiveWeapon() != this) - { - pBCC->Weapon_Switch(oldWeapon); - } - } - */ -} - - -//----------------------------------------------------------------------------- -// Purpose: Gets event from anim stream and throws the object -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeaponBrickbat::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - switch( pEvent->event ) - { - case EVENT_WEAPON_THROW: - { - CAI_BaseNPC *pNPC = GetOwner()->MyNPCPointer(); - - if (!pNPC) - { - return; - } - - Vector vec_target = pNPC->GetEnemyLKP(); - - // ----------------------------------------------------- - // Get position of throw - // ----------------------------------------------------- - // If owner has a hand, set position to the hand bone position - Vector launchPos; - int iBIndex = pNPC->LookupBone("Bip01 R Hand"); - if (iBIndex != -1) { - Vector origin; - QAngle angles; - pNPC->GetBonePosition( iBIndex, launchPos, angles); - } - // Otherwise just set to in front of the owner - else { - Vector vFacingDir = pNPC->BodyDirection2D( ); - vFacingDir = vFacingDir * 60.0; - launchPos = pNPC->GetLocalOrigin()+vFacingDir; - } - - ThrowBrickbat( launchPos, m_vecTossVelocity, sk_npc_dmg_brickbat.GetFloat()); - - // Drop the weapon and remove as no more ammo - pNPC->Weapon_Drop( this ); - UTIL_Remove( this ); - } - break; - default: - BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CWeaponBrickbat::ObjectInWay( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - if (!pOwner) - { - return false; - } - - Vector vecSrc = pOwner->Weapon_ShootPosition( ); - Vector vecAiming = pOwner->BodyDirection2D( ); - - trace_t tr; - - Vector vecEnd = vecSrc + (vecAiming * 32); - UTIL_TraceLine( vecSrc, vecEnd, MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); - - if (tr.fraction < 1.0) - { - // Don't block on a living creature - if (tr.m_pEnt) - { - CBaseEntity *pEntity = tr.m_pEnt; - CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pEntity ); - if (pBCC) - { - return false; - } - } - return true; - } - else - { - return false; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Override to allow throw w/o LOS -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CWeaponBrickbat::WeaponLOSCondition(const Vector &ownerPos, const Vector &targetPos,bool bSetConditions) -{ - // <> should test if can throw from present location here... - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Override to check throw -// Input : -// Output : -//----------------------------------------------------------------------------- -int CWeaponBrickbat::WeaponRangeAttack1Condition( float flDot, float flDist ) -{ - // If things haven't changed too much since last time - // just return that previously calculated value - if (gpGlobals->curtime < m_fNextThrowCheck ) - { - return m_iThrowBits; - } - - if ( flDist < m_fMinRange1) - { - m_iThrowBits = COND_TOO_CLOSE_TO_ATTACK; - } - else if (flDist > m_fMaxRange1) - { - m_iThrowBits = COND_TOO_FAR_TO_ATTACK; - } - else if (flDot < 0.5) - { - m_iThrowBits = COND_NOT_FACING_ATTACK; - } - - // If moving, can't throw. - else if ( m_flGroundSpeed != 0 ) - { - m_iThrowBits = COND_NONE; - } - else - { - // Ok we should check again as some time has passed - // This function is only used by NPC's so we can cast to a Base Monster - CAI_BaseNPC *pNPC = GetOwner()->MyNPCPointer(); - CBaseEntity *pEnemy = pNPC->GetEnemy(); - - if (!pEnemy) - { - return COND_NONE; - } - - // Get Enemy Position - Vector vecTarget; - pEnemy->CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 0.0f ), &vecTarget ); - - // Get Toss Vector - Vector throwStart = pNPC->Weapon_ShootPosition(); - Vector vecToss; - CBaseEntity* pBlocker = NULL; - float throwDist = (throwStart - vecTarget).Length(); - float fGravity = sv_gravity.GetFloat(); - float throwLimit = pNPC->ThrowLimit(throwStart, vecTarget, fGravity, 35, WorldAlignMins(), WorldAlignMaxs(), pEnemy, &vecToss, &pBlocker); - - // If I can make the throw (or most of the throw) - if (!throwLimit || (throwLimit != throwDist && throwLimit > 0.8*throwDist)) - { - m_vecTossVelocity = vecToss; - m_iThrowBits = COND_CAN_RANGE_ATTACK1; - - } - else - { - m_iThrowBits = COND_NONE; - } - - } - // don't check again for a while. - m_fNextThrowCheck = gpGlobals->curtime + 0.33; // 1/3 second. - - return m_iThrowBits; -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CWeaponBrickbat::ThrowBrickbat( Vector vecSrc, Vector vecVelocity, float damage) -{ - CGrenade_Brickbat *pBrickbat = (CGrenade_Brickbat*)Create( BrickBatAmmoArray[m_iCurrentAmmoType].m_sClassName, vecSrc, vec3_angle, GetOwner() ); - - if (!pBrickbat) - { - Msg("Brickbat type (%s) not defined!\n",BrickBatAmmoArray[m_iCurrentAmmoType].m_sClassName); - return; - } - - AngularImpulse vecAngVel; - // Tumble through the air - vecAngVel.x = random->RandomFloat ( -100, -500 ); - vecAngVel.z = random->RandomFloat ( -100, -500 ); - vecAngVel.y = random->RandomFloat ( -100, -500 ); - - // If physically simulated - IPhysicsObject *pPhysicsObject = pBrickbat->VPhysicsGetObject(); - if ( pPhysicsObject ) - { - pPhysicsObject->AddVelocity( &vecVelocity, &vecAngVel ); - } - // Otherwise - else - { - pBrickbat->SetAbsVelocity( vecVelocity ); - - QAngle angVel; - AngularImpulseToQAngle( vecAngVel, angVel ); - pBrickbat->SetLocalAngularVelocity( angVel ); - } - - pBrickbat->SetThrower( GetOwner() ); - pBrickbat->SetOwnerEntity( ((CBaseEntity*)GetOwner()) ); - pBrickbat->SetDamage(damage); - - m_nAmmoCount[m_iCurrentAmmoType]--; - - m_bNeedThrow = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CWeaponBrickbat::PrimaryAttack( void ) -{ - - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if (!pPlayer) - { - return; - } - - SendWeaponAnim(ACT_VM_PULLBACK); - - // Don't fire again until fire animation has completed - float flSequenceEndTime = gpGlobals->curtime + SequenceDuration(); - pPlayer->m_flNextAttack = m_flNextPrimaryAttack = m_flNextSecondaryAttack = flSequenceEndTime; - - m_bNeedThrow = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CWeaponBrickbat::Throw( void ) -{ - - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if (!pPlayer) - { - return; - } - - Vector vecSrc = pPlayer->WorldSpaceCenter(); - Vector vecFacing = pPlayer->BodyDirection3D( ); - vecSrc = vecSrc + vecFacing * 18.0; - vecSrc.z += 24.0f; - - // Player may have turned to face a wall during the throw anim in which case - // we don't want to throw the SLAM into the wall - if (ObjectInWay()) - { - vecSrc = pPlayer->WorldSpaceCenter() + vecFacing * 5.0; - } - - Vector vecAiming = pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES ); - vecAiming.z += 0.20; // Raise up so passes through reticle - - ThrowBrickbat(vecSrc, vecAiming*800, sk_plr_dmg_brickbat.GetFloat()); - pPlayer->RemoveAmmo( 1, m_iPrimaryAmmoType ); - - SendWeaponAnim(ACT_VM_THROW); - - // Don't fire again until fire animation has completed - float flSequenceEndTime = gpGlobals->curtime + SequenceDuration(); - pPlayer->m_flNextAttack = m_flNextPrimaryAttack = m_flNextSecondaryAttack = flSequenceEndTime; - - m_bNeedThrow = false; - m_bNeedDraw = true; -} -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CWeaponBrickbat::SecondaryAttack( void ) -{ - int counter = 0; - while (counter < NUM_BRICKBAT_AMMO_TYPES) - { - m_iCurrentAmmoType = ((++m_iCurrentAmmoType)%NUM_BRICKBAT_AMMO_TYPES); - - // If I've found a category with ammo stop looking - if (m_nAmmoCount[m_iCurrentAmmoType] > 0) - { - DrawAmmo(); - return; - } - counter++; - } - // I'm out of all ammo types -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CWeaponBrickbat::DrawAmmo( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - // ------------------------------------------- - // Make sure I have ammo of the current type - // ------------------------------------------- - int counter = 0; - while (m_nAmmoCount[m_iCurrentAmmoType] <=0) - { - m_iCurrentAmmoType = ((++m_iCurrentAmmoType)%NUM_BRICKBAT_AMMO_TYPES); - counter++; - - // ---------------------------------------------------- - // No ammo of any types so drop the weapon and destroy - // ---------------------------------------------------- - if (counter >= NUM_BRICKBAT_AMMO_TYPES) - { - pOwner->Weapon_Drop( this, NULL, NULL ); - UTIL_Remove(this); - return; - } - } - SetModel( BrickBatAmmoArray[m_iCurrentAmmoType].m_sViewModel); - CBaseViewModel *vm = pOwner->GetViewModel(); - if ( vm ) - { - vm->SetModel( BrickBatAmmoArray[m_iCurrentAmmoType].m_sViewModel ); - } - - //Msg("Drawing %s...\n",BrickBatAmmoArray[m_iCurrentAmmoType].m_sClassName); - m_bNeedDraw = false; - - SendWeaponAnim(ACT_VM_DRAW); - - // Don't fire again until fire animation has completed - float flSequenceEndTime = gpGlobals->curtime + SequenceDuration(); - pOwner->m_flNextAttack = m_flNextPrimaryAttack = m_flNextSecondaryAttack = flSequenceEndTime; -} - -//----------------------------------------------------------------------------- -// Purpose: Override so shotgun can do mulitple reloads in a row -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeaponBrickbat::ItemPostFrame( void ) -{ - /* HANDY FOR DEBUG - for (int i=0;im_nButtons & IN_ATTACK2) && (m_flNextSecondaryAttack <= gpGlobals->curtime)) - { - SecondaryAttack(); - } - else if ((pOwner->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime)) - { - // Uses secondary ammo only - if (pOwner->GetAmmoCount(m_iPrimaryAmmoType)) - { - PrimaryAttack(); - } - } - else if (m_bNeedDraw) - { - DrawAmmo(); - } - else - { - SendWeaponAnim( ACT_VM_IDLE ); - //pOwner->m_flNextAttack = gpGlobals->curtime + SequenceDuration(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeaponBrickbat::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - if ( info.GetDamageType() & DMG_BULLET) - { - if ( BrickBatAmmoArray[m_iCurrentAmmoType].m_nAmmoType == BRICKBAT_ROCK ) - { - g_pEffects->Ricochet(ptr->endpos,ptr->plane.normal); - } - } - BaseClass::TraceAttack( info, vecDir, ptr ); -} - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -CWeaponBrickbat::CWeaponBrickbat( void ) -{ -#ifdef _DEBUG - m_vecTossVelocity.Init(); -#endif - - m_fMinRange1 = 200; - m_fMaxRange1 = 1000; -} diff --git a/game/server/hl2/weapon_brickbat.h b/game/server/hl2/weapon_brickbat.h deleted file mode 100644 index 99441ff9b..000000000 --- a/game/server/hl2/weapon_brickbat.h +++ /dev/null @@ -1,82 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Weapon that throws things from the hand -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef WEAPON_BRICKBAT_H -#define WEAPON_BRICKBAT_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "basehlcombatweapon.h" - -enum BrickbatAmmo_t -{ - BRICKBAT_ROCK = 0, - BRICKBAT_BOTTLE, - - NUM_BRICKBAT_AMMO_TYPES -}; - -class CGrenade_Brickbat; - -class CWeaponBrickbat : public CBaseHLCombatWeapon -{ -public: - DECLARE_CLASS( CWeaponBrickbat, CBaseHLCombatWeapon ); - - DECLARE_SERVERCLASS(); - -public: - int m_iCurrentAmmoType; - - void Precache( void ); - void Spawn( void ); - bool Deploy( void ); - - virtual const char *GetViewModel( int viewmodelindex =0 ); - virtual const char *GetWorldModel( void ); - - void DrawAmmo( void ); - - virtual int WeaponRangeAttack1Condition( float flDot, float flDist ); - virtual bool WeaponLOSCondition(const Vector &ownerPos, const Vector &targetPos, bool bSetConditions); - - void SetPickupTouch( void ); - void BrickbatTouch( CBaseEntity *pOther ); // default weapon touch - void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } - - bool ObjectInWay( void ); - - void ThrowBrickbat( Vector vecSrc, Vector vecVelocity, float damage); - void ItemPostFrame( void ); - void PrimaryAttack( void ); - void SecondaryAttack( void ); - void Throw( void ); - - void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); - - DECLARE_DATADESC(); - DECLARE_ACTTABLE(); - - CWeaponBrickbat(void); - -private: - bool m_bNeedDraw; - bool m_bNeedThrow; - int m_iThrowBits; // Save the current throw bits state - float m_fNextThrowCheck; // When to check throw ability next - Vector m_vecTossVelocity; - - int m_nAmmoCount[NUM_BRICKBAT_AMMO_TYPES]; // How much ammo of each type do I own? -}; - -#endif //WEAPON_BRICKBAT_H diff --git a/game/server/hl2/weapon_bugbait.cpp b/game/server/hl2/weapon_bugbait.cpp deleted file mode 100644 index d24f03eae..000000000 --- a/game/server/hl2/weapon_bugbait.cpp +++ /dev/null @@ -1,441 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "basehlcombatweapon.h" -#include "engine/IEngineSound.h" -#include "npcevent.h" -#include "in_buttons.h" -#include "antlion_maker.h" -#include "grenade_bugbait.h" -#include "GameStats.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// -// Bug Bait Weapon -// - -class CWeaponBugBait : public CBaseHLCombatWeapon -{ - DECLARE_CLASS( CWeaponBugBait, CBaseHLCombatWeapon ); -public: - - DECLARE_SERVERCLASS(); - - CWeaponBugBait( void ); - - void Spawn( void ); - void FallInit( void ); - - int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } - - void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); - - void Drop( const Vector &vecVelocity ); - void BugbaitStickyTouch( CBaseEntity *pOther ); - void OnPickedUp( CBaseCombatCharacter *pNewOwner ); - bool Deploy( void ); - bool Holster( CBaseCombatWeapon *pSwitchingTo ); - - void ItemPostFrame( void ); - void Precache( void ); - void PrimaryAttack( void ); - void SecondaryAttack( void ); - void ThrowGrenade( CBasePlayer *pPlayer ); - - bool HasAnyAmmo( void ) { return true; } - - bool Reload( void ); - - void SetSporeEmitterState( bool state = true ); - - bool ShouldDisplayHUDHint() { return true; } - - DECLARE_DATADESC(); - -protected: - - bool m_bDrawBackFinished; - bool m_bRedraw; - bool m_bEmitSpores; - EHANDLE m_hSporeTrail; -}; - -IMPLEMENT_SERVERCLASS_ST(CWeaponBugBait, DT_WeaponBugBait) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_bugbait, CWeaponBugBait ); -PRECACHE_WEAPON_REGISTER( weapon_bugbait ); - -BEGIN_DATADESC( CWeaponBugBait ) - - DEFINE_FIELD( m_hSporeTrail, FIELD_EHANDLE ), - DEFINE_FIELD( m_bRedraw, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bEmitSpores, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bDrawBackFinished, FIELD_BOOLEAN ), - - DEFINE_FUNCTION( BugbaitStickyTouch ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CWeaponBugBait::CWeaponBugBait( void ) -{ - m_bDrawBackFinished = false; - m_bRedraw = false; - m_hSporeTrail = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponBugBait::Spawn( void ) -{ - BaseClass::Spawn(); - - // Increase the bugbait's pickup volume. It spawns inside the antlion guard's body, - // and playtesters seem to be wary about moving into the body. - SetSize( Vector( -4, -4, -4), Vector(4, 4, 4) ); - CollisionProp()->UseTriggerBounds( true, 100 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponBugBait::FallInit( void ) -{ - // Bugbait shouldn't be physics, because it musn't roll/move away from it's spawnpoint. - // The game will break if the player can't pick it up, so it must stay still. - SetModel( GetWorldModel() ); - - VPhysicsDestroyObject(); - SetMoveType( MOVETYPE_FLYGRAVITY ); - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_TRIGGER ); - - SetPickupTouch(); - - SetThink( &CBaseCombatWeapon::FallThink ); - - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponBugBait::Precache( void ) -{ - BaseClass::Precache(); - - UTIL_PrecacheOther( "npc_grenade_bugbait" ); - - PrecacheScriptSound( "Weapon_Bugbait.Splat" ); - -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponBugBait::Drop( const Vector &vecVelocity ) -{ - BaseClass::Drop( vecVelocity ); - - // On touch, stick & stop moving. Increase our thinktime a bit so we don't stomp the touch for a bit - SetNextThink( gpGlobals->curtime + 3.0 ); - SetTouch( &CWeaponBugBait::BugbaitStickyTouch ); - - m_hSporeTrail = SporeExplosion::CreateSporeExplosion(); - if ( m_hSporeTrail ) - { - SporeExplosion *pSporeExplosion = (SporeExplosion *)m_hSporeTrail.Get(); - - QAngle angles; - VectorAngles( Vector(0,0,1), angles ); - - pSporeExplosion->SetAbsAngles( angles ); - pSporeExplosion->SetAbsOrigin( GetAbsOrigin() ); - pSporeExplosion->SetParent( this ); - - pSporeExplosion->m_flSpawnRate = 16.0f; - pSporeExplosion->m_flParticleLifetime = 0.5f; - pSporeExplosion->SetRenderColor( 0, (int)0.5f, (int)0.25f, (int)0.15f ); - - pSporeExplosion->m_flStartSize = 32; - pSporeExplosion->m_flEndSize = 48; - pSporeExplosion->m_flSpawnRadius = 4; - - pSporeExplosion->SetLifetime( 9999 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Stick to the world when we touch it -//----------------------------------------------------------------------------- -void CWeaponBugBait::BugbaitStickyTouch( CBaseEntity *pOther ) -{ - if ( !pOther->IsWorld() ) - return; - - // Stop moving, wait for pickup - SetMoveType( MOVETYPE_NONE ); - SetThink( NULL ); - SetPickupTouch(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPicker - -//----------------------------------------------------------------------------- -void CWeaponBugBait::OnPickedUp( CBaseCombatCharacter *pNewOwner ) -{ - BaseClass::OnPickedUp( pNewOwner ); - - if ( m_hSporeTrail ) - { - UTIL_Remove( m_hSporeTrail ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponBugBait::PrimaryAttack( void ) -{ - if ( m_bRedraw ) - return; - - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if ( pPlayer == NULL ) - return; - - SendWeaponAnim( ACT_VM_HAULBACK ); - - m_flTimeWeaponIdle = FLT_MAX; - m_flNextPrimaryAttack = FLT_MAX; - - m_iPrimaryAttacks++; - gamestats->Event_WeaponFired( pPlayer, true, GetClassname() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponBugBait::SecondaryAttack( void ) -{ - // Squeeze! - CPASAttenuationFilter filter( this ); - - EmitSound( filter, entindex(), "Weapon_Bugbait.Splat" ); - - if ( CGrenadeBugBait::ActivateBugbaitTargets( GetOwner(), GetAbsOrigin(), true ) == false ) - { - g_AntlionMakerManager.BroadcastFollowGoal( GetOwner() ); - } - - SendWeaponAnim( ACT_VM_SECONDARYATTACK ); - m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration(); - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( pOwner ) - { - m_iSecondaryAttacks++; - gamestats->Event_WeaponFired( pOwner, false, GetClassname() ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -//----------------------------------------------------------------------------- -void CWeaponBugBait::ThrowGrenade( CBasePlayer *pPlayer ) -{ - Vector vForward, vRight, vUp, vThrowPos, vThrowVel; - - pPlayer->EyeVectors( &vForward, &vRight, &vUp ); - - vThrowPos = pPlayer->EyePosition(); - - vThrowPos += vForward * 18.0f; - vThrowPos += vRight * 12.0f; - - pPlayer->GetVelocity( &vThrowVel, NULL ); - vThrowVel += vForward * 1000; - - CGrenadeBugBait *pGrenade = BugBaitGrenade_Create( vThrowPos, vec3_angle, vThrowVel, QAngle(600,random->RandomInt(-1200,1200),0), pPlayer ); - - if ( pGrenade != NULL ) - { - // If the shot is clear to the player, give the missile a grace period - trace_t tr; - UTIL_TraceLine( pPlayer->EyePosition(), pPlayer->EyePosition() + ( vForward * 128 ), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction == 1.0 ) - { - pGrenade->SetGracePeriod( 0.1f ); - } - } - - m_bRedraw = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEvent - -// *pOperator - -//----------------------------------------------------------------------------- -void CWeaponBugBait::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - switch( pEvent->event ) - { - case EVENT_WEAPON_SEQUENCE_FINISHED: - m_bDrawBackFinished = true; - break; - - case EVENT_WEAPON_THROW: - ThrowGrenade( pOwner ); - break; - - default: - BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponBugBait::Reload( void ) -{ - if ( ( m_bRedraw ) && ( m_flNextPrimaryAttack <= gpGlobals->curtime ) ) - { - //Redraw the weapon - SendWeaponAnim( ACT_VM_DRAW ); - - //Update our times - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - - //Mark this as done - m_bRedraw = false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponBugBait::ItemPostFrame( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - // See if we're cocked and ready to throw - if ( m_bDrawBackFinished ) - { - if ( ( pOwner->m_nButtons & IN_ATTACK ) == false ) - { - SendWeaponAnim( ACT_VM_THROW ); - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - m_bDrawBackFinished = false; - } - } - else - { - //See if we're attacking - if ( ( pOwner->m_nButtons & IN_ATTACK ) && ( m_flNextPrimaryAttack < gpGlobals->curtime ) ) - { - PrimaryAttack(); - } - else if ( ( pOwner->m_nButtons & IN_ATTACK2 ) && ( m_flNextSecondaryAttack < gpGlobals->curtime ) ) - { - SecondaryAttack(); - } - } - - if ( m_bRedraw ) - { - if ( IsViewModelSequenceFinished() ) - { - Reload(); - } - } - - WeaponIdle(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CWeaponBugBait::Deploy( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return false; - - /* - if ( m_hSporeTrail == NULL ) - { - m_hSporeTrail = SporeTrail::CreateSporeTrail(); - - m_hSporeTrail->m_bEmit = true; - m_hSporeTrail->m_flSpawnRate = 100.0f; - m_hSporeTrail->m_flParticleLifetime = 2.0f; - m_hSporeTrail->m_flStartSize = 1.0f; - m_hSporeTrail->m_flEndSize = 4.0f; - m_hSporeTrail->m_flSpawnRadius = 8.0f; - - m_hSporeTrail->m_vecEndColor = Vector( 0, 0, 0 ); - - CBaseViewModel *vm = pOwner->GetViewModel(); - - if ( vm != NULL ) - { - m_hSporeTrail->FollowEntity( vm ); - } - } - */ - - m_bRedraw = false; - m_bDrawBackFinished = false; - - return BaseClass::Deploy(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CWeaponBugBait::Holster( CBaseCombatWeapon *pSwitchingTo ) -{ - m_bRedraw = false; - m_bDrawBackFinished = false; - - return BaseClass::Holster( pSwitchingTo ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : true - -//----------------------------------------------------------------------------- -void CWeaponBugBait::SetSporeEmitterState( bool state ) -{ - m_bEmitSpores = state; -} diff --git a/game/server/hl2/weapon_cguard.cpp b/game/server/hl2/weapon_cguard.cpp deleted file mode 100644 index 67043a6d2..000000000 --- a/game/server/hl2/weapon_cguard.cpp +++ /dev/null @@ -1,481 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Combine guard gun, strider destroyer -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "basehlcombatweapon.h" -#include "basecombatcharacter.h" -#include "player.h" -#include "grenade_ar2.h" -#include "soundent.h" -#include "explode.h" -#include "shake.h" -#include "energy_wave.h" -#include "te_particlesystem.h" -#include "ndebugoverlay.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//Concussive explosion entity - -class CTEConcussiveExplosion : public CTEParticleSystem -{ -public: - DECLARE_CLASS( CTEConcussiveExplosion, CTEParticleSystem ); - DECLARE_SERVERCLASS(); - - CTEConcussiveExplosion( const char *name ); - virtual ~CTEConcussiveExplosion( void ); - - CNetworkVector( m_vecNormal ); - CNetworkVar( float, m_flScale ); - CNetworkVar( int, m_nRadius ); - CNetworkVar( int, m_nMagnitude ); -}; - -IMPLEMENT_SERVERCLASS_ST( CTEConcussiveExplosion, DT_TEConcussiveExplosion ) - SendPropVector( SENDINFO(m_vecNormal), -1, SPROP_COORD ), - SendPropFloat( SENDINFO(m_flScale), 0, SPROP_NOSCALE ), - SendPropInt( SENDINFO(m_nRadius), 32, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nMagnitude), 32, SPROP_UNSIGNED ), -END_SEND_TABLE() - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -CTEConcussiveExplosion::CTEConcussiveExplosion( const char *name ) : BaseClass( name ) -{ - m_nRadius = 0; - m_nMagnitude = 0; - m_flScale = 0.0f; - - m_vecNormal.Init(); -} - -//----------------------------------------------------------------------------- -// Purpose: Destructor -//----------------------------------------------------------------------------- -CTEConcussiveExplosion::~CTEConcussiveExplosion( void ) -{ -} - - -// Singleton to fire TEExplosion objects -static CTEConcussiveExplosion g_TEConcussiveExplosion( "ConcussiveExplosion" ); - -void TE_ConcussiveExplosion( IRecipientFilter& filter, float delay, - const Vector* pos, float scale, int radius, int magnitude, const Vector* normal ) -{ - g_TEConcussiveExplosion.m_vecOrigin = *pos; - g_TEConcussiveExplosion.m_flScale = scale; - g_TEConcussiveExplosion.m_nRadius = radius; - g_TEConcussiveExplosion.m_nMagnitude = magnitude; - - if ( normal ) - g_TEConcussiveExplosion.m_vecNormal = *normal; - else - g_TEConcussiveExplosion.m_vecNormal = Vector(0,0,1); - - // Send it over the wire - g_TEConcussiveExplosion.Create( filter, delay ); -} - -//Temp ent for the blast - -class CConcussiveBlast : public CBaseEntity -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( CConcussiveBlast, CBaseEntity ); - - int m_spriteTexture; - - CConcussiveBlast( void ) {} - - //----------------------------------------------------------------------------- - // Purpose: - // Output : - //----------------------------------------------------------------------------- - void Precache( void ) - { - m_spriteTexture = PrecacheModel( "sprites/lgtning.vmt" ); - - BaseClass::Precache(); - } - - //----------------------------------------------------------------------------- - // Purpose: - // Output : - //----------------------------------------------------------------------------- - - void Explode( float magnitude ) - { - //Create a concussive explosion - CPASFilter filter( GetAbsOrigin() ); - - Vector vecForward; - AngleVectors( GetAbsAngles(), &vecForward ); - TE_ConcussiveExplosion( filter, 0.0, - &GetAbsOrigin(),//position - 1.0f, //scale - (int)(256*magnitude), //radius - (int)(175*magnitude), //magnitude - &vecForward ); //normal - - int colorRamp = random->RandomInt( 128, 255 ); - - //Shockring - CBroadcastRecipientFilter filter2; - te->BeamRingPoint( filter2, 0, - GetAbsOrigin(), //origin - 16, //start radius - 300*magnitude, //end radius - m_spriteTexture, //texture - 0, //halo index - 0, //start frame - 2, //framerate - 0.3f, //life - 128, //width - 16, //spread - 0, //amplitude - colorRamp, //r - colorRamp, //g - 255, //g - 24, //a - 128 //speed - ); - - //Do the radius damage - RadiusDamage( CTakeDamageInfo( this, GetOwnerEntity(), 200, DMG_BLAST|DMG_DISSOLVE ), GetAbsOrigin(), 256, CLASS_NONE, NULL ); - - UTIL_Remove( this ); - } -}; - -LINK_ENTITY_TO_CLASS( concussiveblast, CConcussiveBlast ); - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CConcussiveBlast ) - -// DEFINE_FIELD( m_spriteTexture, FIELD_INTEGER ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: Create a concussive blast entity and detonate it -//----------------------------------------------------------------------------- -void CreateConcussiveBlast( const Vector &origin, const Vector &surfaceNormal, CBaseEntity *pOwner, float magnitude ) -{ - QAngle angles; - VectorAngles( surfaceNormal, angles ); - CConcussiveBlast *pBlast = (CConcussiveBlast *) CBaseEntity::Create( "concussiveblast", origin, angles, pOwner ); - - if ( pBlast ) - { - pBlast->Explode( magnitude ); - } -} - -// Combine Guard weapon - -#if 0 - -class CWeaponCGuard : public CBaseHLCombatWeapon -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( CWeaponCGuard, CBaseHLCombatWeapon ); - - DECLARE_SERVERCLASS(); - - CWeaponCGuard( void ); - - void Precache( void ); - void PrimaryAttack( void ); - void AddViewKick( void ); - void DelayedFire( void ); - void ItemPostFrame( void ); - void AlertTargets( void ); - void UpdateLasers( void ); - - int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } - - DECLARE_ACTTABLE(); - -protected: - float m_flChargeTime; - bool m_bFired; - - int m_beamIndex; - int m_haloIndex; -}; - - -IMPLEMENT_SERVERCLASS_ST(CWeaponCGuard, DT_WeaponCGuard) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_cguard, CWeaponCGuard ); -PRECACHE_WEAPON_REGISTER( weapon_cguard ); - - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CWeaponCGuard ) - - DEFINE_FIELD( m_flChargeTime, FIELD_TIME ), - DEFINE_FIELD( m_bFired, FIELD_BOOLEAN ), -// DEFINE_FIELD( m_beamIndex, FIELD_INTEGER ), -// DEFINE_FIELD( m_haloIndex, FIELD_INTEGER ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Maps base activities to weapons-specific ones so our characters do the right things. -//----------------------------------------------------------------------------- -acttable_t CWeaponCGuard::m_acttable[] = -{ - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SNIPER_RIFLE, true } -}; - -IMPLEMENT_ACTTABLE( CWeaponCGuard ); - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CWeaponCGuard::CWeaponCGuard( void ) -{ - m_flNextPrimaryAttack = gpGlobals->curtime; - m_flChargeTime = gpGlobals->curtime; - m_bFired = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCGuard::Precache( void ) -{ - UTIL_PrecacheOther( "concussiveblast" ); - - m_beamIndex = PrecacheModel( "sprites/bluelaser1.vmt" ); - m_haloIndex = PrecacheModel( "sprites/blueshaft1.vmt" ); - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCGuard::AlertTargets( void ) -{ - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if ( pPlayer == NULL ) - return; - - // Fire the bullets - Vector vecSrc = pPlayer->Weapon_ShootPosition( ); - Vector vecAiming = pPlayer->GetRadialAutoVector( NEW_AUTOAIM_RADIUS, NEW_AUTOAIM_DIST ); - - Vector impactPoint = vecSrc + ( vecAiming * MAX_TRACE_LENGTH ); - - trace_t tr; - - UTIL_TraceLine( vecSrc, impactPoint, MASK_SHOT, pPlayer, COLLISION_GROUP_NONE, &tr ); - - if ( (vecSrc-tr.endpos).Length() > 1024 ) - return; - - CSoundEnt::InsertSound( SOUND_DANGER, tr.endpos, 128, 0.5f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCGuard::UpdateLasers( void ) -{ - //Only update the lasers whilst charging - if ( ( m_flChargeTime < gpGlobals->curtime ) || ( m_bFired ) ) - return; - - Vector start, end, v_forward, v_right, v_up; - - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if ( pPlayer == NULL ) - return; - - pPlayer->GetVectors( &v_forward, &v_right, &v_up ); - - //Get the position of the laser - start = pPlayer->Weapon_ShootPosition( ); - - start += ( v_forward * 8.0f ) + ( v_right * 3.0f ) + ( v_up * -2.0f ); - - end = start + ( v_forward * MAX_TRACE_LENGTH ); - - float angleOffset = ( 1.0f - ( m_flChargeTime - gpGlobals->curtime ) ) / 1.0f; - Vector offset[4]; - - offset[0] = Vector( 0.0f, 0.5f, -0.5f ); - offset[1] = Vector( 0.0f, 0.5f, 0.5f ); - offset[2] = Vector( 0.0f, -0.5f, -0.5f ); - offset[3] = Vector( 0.0f, -0.5f, 0.5f ); - - QAngle v_ang; - Vector v_dir; - - angleOffset *= 2.0f; - - if ( angleOffset > 1.0f ) - angleOffset = 1.0f; - - for ( int i = 0; i < 4; i++ ) - { - Vector ofs = start + ( v_forward * offset[i][0] ) + ( v_right * offset[i][1] ) + ( v_up * offset[i][2] ); - - float hScale = ( offset[i][1] <= 0.0f ) ? 1.0f : -1.0f; - float vScale = ( offset[i][2] <= 0.0f ) ? 1.0f : -1.0f; - - VectorAngles( v_forward, v_ang ); - v_ang[PITCH] = UTIL_AngleMod( v_ang[PITCH] + ( (1.0f-angleOffset) * 15.0f * vScale ) ); - v_ang[YAW] = UTIL_AngleMod( v_ang[YAW] + ( (1.0f-angleOffset) * 15.0f * hScale ) ); - - AngleVectors( v_ang, &v_dir ); - - trace_t tr; - UTIL_TraceLine( ofs, ofs + ( v_dir * MAX_TRACE_LENGTH ), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - UTIL_Beam( ofs, tr.endpos, m_beamIndex, 0, 0, 2.0f, 0.1f, 2, 0, 1, 0, 255, 255, 255, 32, 100 ); - - UTIL_Beam( ofs, tr.endpos, m_haloIndex, 0, 0, 2.0f, 0.1f, 4, 0, 1, 16, 255, 255, 255, 8, 100 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCGuard::PrimaryAttack( void ) -{ - if ( m_flChargeTime >= gpGlobals->curtime ) - return; - - AlertTargets(); - - WeaponSound( SPECIAL1 ); - - //UTIL_ScreenShake( GetAbsOrigin(), 10.0f, 100.0f, 2.0f, 128, SHAKE_START, false ); - - m_flChargeTime = gpGlobals->curtime + 1.0f; - m_bFired = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCGuard::ItemPostFrame( void ) -{ - //FIXME: UpdateLasers(); - - if ( ( m_flChargeTime < gpGlobals->curtime ) && ( m_bFired == false ) ) - { - DelayedFire(); - } - - BaseClass::ItemPostFrame(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCGuard::DelayedFire( void ) -{ - if ( m_flChargeTime >= gpGlobals->curtime ) - return; - - if ( m_bFired ) - return; - - m_bFired = true; - - // Only the player fires this way so we can cast - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if ( pPlayer == NULL ) - return; - - // Abort here to handle burst and auto fire modes - if ( (GetMaxClip1() != -1 && m_iClip1 == 0) || (GetMaxClip1() == -1 && !pPlayer->GetAmmoCount(m_iPrimaryAmmoType) ) ) - return; - - // MUST call sound before removing a round from the clip of a CMachineGun - WeaponSound(SINGLE); - - pPlayer->DoMuzzleFlash(); - - // To make the firing framerate independent, we may have to fire more than one bullet here on low-framerate systems, - // especially if the weapon we're firing has a really fast rate of fire. - if ( GetSequence() != SelectWeightedSequence( ACT_VM_PRIMARYATTACK ) ) - { - m_flNextPrimaryAttack = gpGlobals->curtime; - } - - // Make sure we don't fire more than the amount in the clip, if this weapon uses clips - if ( UsesClipsForAmmo1() ) - { - m_iClip1 = m_iClip1 - 1; - } - - // Fire the bullets - Vector vecSrc = pPlayer->Weapon_ShootPosition( ); - Vector vecAiming = pPlayer->GetRadialAutoVector( NEW_AUTOAIM_RADIUS, NEW_AUTOAIM_DIST ); - - //Factor in the view kick - AddViewKick(); - - Vector impactPoint = vecSrc + ( vecAiming * MAX_TRACE_LENGTH ); - - trace_t tr; - UTIL_TraceHull( vecSrc, impactPoint, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ), MASK_SHOT, pPlayer, COLLISION_GROUP_NONE, &tr ); - - CreateConcussiveBlast( tr.endpos, tr.plane.normal, this, 1.0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCGuard::AddViewKick( void ) -{ - //Get the view kick - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if ( pPlayer == NULL ) - return; - - color32 white = {255, 255, 255, 64}; - UTIL_ScreenFade( pPlayer, white, 0.1, 0, FFADE_IN ); - - //Disorient the player - QAngle angles = pPlayer->GetLocalAngles(); - - angles.x += random->RandomInt( -5, 5 ); - angles.y += random->RandomInt( -8, 8 ); - angles.z = 0.0f; - - SetLocalAngles( angles ); - - pPlayer->SnapEyeAngles( angles ); - - pPlayer->ViewPunch( QAngle( random->RandomInt( -8, -12 ), random->RandomInt( -2, 2 ), random->RandomInt( -8, 8 ) ) ); -} - -#endif diff --git a/game/server/hl2/weapon_citizenpackage.cpp b/game/server/hl2/weapon_citizenpackage.cpp deleted file mode 100644 index 90501e9fd..000000000 --- a/game/server/hl2/weapon_citizenpackage.cpp +++ /dev/null @@ -1,74 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "weapon_citizenpackage.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -IMPLEMENT_SERVERCLASS_ST(CWeaponCitizenPackage, DT_WeaponCitizenPackage) -END_SEND_TABLE() - -BEGIN_DATADESC( CWeaponCitizenPackage ) -END_DATADESC() - -LINK_ENTITY_TO_CLASS( weapon_citizenpackage, CWeaponCitizenPackage ); -PRECACHE_WEAPON_REGISTER(weapon_citizenpackage); - -acttable_t CWeaponCitizenPackage::m_acttable[] = -{ - { ACT_IDLE, ACT_IDLE_PACKAGE, false }, - { ACT_WALK, ACT_WALK_PACKAGE, false }, -}; -IMPLEMENT_ACTTABLE(CWeaponCitizenPackage); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCitizenPackage::ItemPostFrame( void ) -{ - // Do nothing -} - -//----------------------------------------------------------------------------- -// Purpose: Remove the citizen package if it's ever dropped -//----------------------------------------------------------------------------- -void CWeaponCitizenPackage::Drop( const Vector &vecVelocity ) -{ - BaseClass::Drop( vecVelocity ); - UTIL_Remove( this ); -} - - - -//----------------------------------------------------------------------------- -// Purpose: Citizen suitcase -//----------------------------------------------------------------------------- -class CWeaponCitizenSuitcase : public CWeaponCitizenPackage -{ - DECLARE_CLASS( CWeaponCitizenSuitcase, CWeaponCitizenPackage ); -public: - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - DECLARE_ACTTABLE(); -}; - -IMPLEMENT_SERVERCLASS_ST(CWeaponCitizenSuitcase, DT_WeaponCitizenSuitcase) -END_SEND_TABLE() - -BEGIN_DATADESC( CWeaponCitizenSuitcase ) -END_DATADESC() - -LINK_ENTITY_TO_CLASS( weapon_citizensuitcase, CWeaponCitizenSuitcase ); -PRECACHE_WEAPON_REGISTER(weapon_citizensuitcase); - -acttable_t CWeaponCitizenSuitcase::m_acttable[] = -{ - { ACT_IDLE, ACT_IDLE_SUITCASE, false }, - { ACT_WALK, ACT_WALK_SUITCASE, false }, -}; -IMPLEMENT_ACTTABLE(CWeaponCitizenSuitcase); diff --git a/game/server/hl2/weapon_citizenpackage.h b/game/server/hl2/weapon_citizenpackage.h deleted file mode 100644 index 44231a1fe..000000000 --- a/game/server/hl2/weapon_citizenpackage.h +++ /dev/null @@ -1,31 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= -#ifndef WEAPON_CITIZENPACKAGE_H -#define WEAPON_CITIZENPACKAGE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "basehlcombatweapon.h" - -//============================================================================= -// -// Weapon - Citizen Package Class -// -class CWeaponCitizenPackage : public CBaseHLCombatWeapon -{ - DECLARE_CLASS( CWeaponCitizenPackage, CBaseHLCombatWeapon ); -public: - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - DECLARE_ACTTABLE(); - - void ItemPostFrame( void ); - void Drop( const Vector &vecVelocity ); -}; - -#endif // WEAPON_CITIZENPACKAGE_H diff --git a/game/server/hl2/weapon_crossbow.cpp b/game/server/hl2/weapon_crossbow.cpp deleted file mode 100644 index 9ebf479cf..000000000 --- a/game/server/hl2/weapon_crossbow.cpp +++ /dev/null @@ -1,982 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" -#include "basehlcombatweapon_shared.h" -#include "basecombatcharacter.h" -#include "ai_basenpc.h" -#include "player.h" -#include "gamerules.h" -#include "in_buttons.h" -#include "soundent.h" -#include "game.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "IEffects.h" -#include "te_effect_dispatch.h" -#include "Sprite.h" -#include "SpriteTrail.h" -#include "beam_shared.h" -#include "rumble_shared.h" -#include "GameStats.h" -#include "decals.h" - -#ifdef PORTAL - #include "portal_util_shared.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//#define BOLT_MODEL "models/crossbow_bolt.mdl" -#define BOLT_MODEL "models/weapons/w_missile_closed.mdl" - -#define BOLT_AIR_VELOCITY 2500 -#define BOLT_WATER_VELOCITY 1500 - -extern ConVar sk_plr_dmg_crossbow; -extern ConVar sk_npc_dmg_crossbow; - -void TE_StickyBolt( IRecipientFilter& filter, float delay, Vector vecDirection, const Vector *origin ); - -#define BOLT_SKIN_NORMAL 0 -#define BOLT_SKIN_GLOW 1 - -//----------------------------------------------------------------------------- -// Crossbow Bolt -//----------------------------------------------------------------------------- -class CCrossbowBolt : public CBaseCombatCharacter -{ - DECLARE_CLASS( CCrossbowBolt, CBaseCombatCharacter ); - -public: - CCrossbowBolt() { }; - ~CCrossbowBolt(); - - Class_T Classify( void ) { return CLASS_NONE; } - -public: - void Spawn( void ); - void Precache( void ); - void BubbleThink( void ); - void BoltTouch( CBaseEntity *pOther ); - bool CreateVPhysics( void ); - unsigned int PhysicsSolidMaskForEntity() const; - static CCrossbowBolt *BoltCreate( const Vector &vecOrigin, const QAngle &angAngles, CBasePlayer *pentOwner = NULL ); - -protected: - - bool CreateSprites( void ); - - CHandle m_pGlowSprite; - //CHandle m_pGlowTrail; - - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); -}; -LINK_ENTITY_TO_CLASS( crossbow_bolt, CCrossbowBolt ); - -BEGIN_DATADESC( CCrossbowBolt ) - // Function Pointers - DEFINE_FUNCTION( BubbleThink ), - DEFINE_FUNCTION( BoltTouch ), - - // These are recreated on reload, they don't need storage - DEFINE_FIELD( m_pGlowSprite, FIELD_EHANDLE ), - //DEFINE_FIELD( m_pGlowTrail, FIELD_EHANDLE ), - -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CCrossbowBolt, DT_CrossbowBolt ) -END_SEND_TABLE() - -CCrossbowBolt *CCrossbowBolt::BoltCreate( const Vector &vecOrigin, const QAngle &angAngles, CBasePlayer *pentOwner ) -{ - // Create a new entity with CCrossbowBolt private data - CCrossbowBolt *pBolt = (CCrossbowBolt *)CreateEntityByName( "crossbow_bolt" ); - UTIL_SetOrigin( pBolt, vecOrigin ); - pBolt->SetAbsAngles( angAngles ); - pBolt->Spawn(); - pBolt->SetOwnerEntity( pentOwner ); - - return pBolt; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CCrossbowBolt::~CCrossbowBolt( void ) -{ - if ( m_pGlowSprite ) - { - UTIL_Remove( m_pGlowSprite ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CCrossbowBolt::CreateVPhysics( void ) -{ - // Create the object in the physics system - VPhysicsInitNormal( SOLID_BBOX, FSOLID_NOT_STANDABLE, false ); - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -unsigned int CCrossbowBolt::PhysicsSolidMaskForEntity() const -{ - return ( BaseClass::PhysicsSolidMaskForEntity() | CONTENTS_HITBOX ) & ~CONTENTS_GRATE; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CCrossbowBolt::CreateSprites( void ) -{ - // Start up the eye glow - m_pGlowSprite = CSprite::SpriteCreate( "sprites/light_glow02_noz.vmt", GetLocalOrigin(), false ); - - if ( m_pGlowSprite != NULL ) - { - m_pGlowSprite->FollowEntity( this ); - m_pGlowSprite->SetTransparency( kRenderGlow, 255, 255, 255, 128, kRenderFxNoDissipation ); - m_pGlowSprite->SetScale( 0.2f ); - m_pGlowSprite->TurnOff(); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCrossbowBolt::Spawn( void ) -{ - Precache( ); - - SetModel( "models/crossbow_bolt.mdl" ); - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_CUSTOM ); - UTIL_SetSize( this, -Vector(0.3f,0.3f,0.3f), Vector(0.3f,0.3f,0.3f) ); - SetSolid( SOLID_BBOX ); - SetGravity( 0.05f ); - - // Make sure we're updated if we're underwater - UpdateWaterState(); - - SetTouch( &CCrossbowBolt::BoltTouch ); - - SetThink( &CCrossbowBolt::BubbleThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - CreateSprites(); - - // Make us glow until we've hit the wall - m_nSkin = BOLT_SKIN_GLOW; -} - - -void CCrossbowBolt::Precache( void ) -{ - PrecacheModel( BOLT_MODEL ); - - // This is used by C_TEStickyBolt, despte being different from above!!! - PrecacheModel( "models/crossbow_bolt.mdl" ); - - PrecacheModel( "sprites/light_glow02_noz.vmt" ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCrossbowBolt::BoltTouch( CBaseEntity *pOther ) -{ - if ( pOther->IsSolidFlagSet(FSOLID_VOLUME_CONTENTS | FSOLID_TRIGGER) ) - { - // Some NPCs are triggers that can take damage (like antlion grubs). We should hit them. - if ( ( pOther->m_takedamage == DAMAGE_NO ) || ( pOther->m_takedamage == DAMAGE_EVENTS_ONLY ) ) - return; - } - - if ( pOther->m_takedamage != DAMAGE_NO ) - { - trace_t tr, tr2; - tr = BaseClass::GetTouchTrace(); - Vector vecNormalizedVel = GetAbsVelocity(); - - ClearMultiDamage(); - VectorNormalize( vecNormalizedVel ); - -#if defined(HL2_EPISODIC) - //!!!HACKHACK - specific hack for ep2_outland_10 to allow crossbow bolts to pass through her bounding box when she's crouched in front of the player - // (the player thinks they have clear line of sight because Alyx is crouching, but her BBOx is still full-height and blocks crossbow bolts. - if( GetOwnerEntity() && GetOwnerEntity()->IsPlayer() && pOther->Classify() == CLASS_PLAYER_ALLY_VITAL && FStrEq(STRING(gpGlobals->mapname), "ep2_outland_10") ) - { - // Change the owner to stop further collisions with Alyx. We do this by making her the owner. - // The player won't get credit for this kill but at least the bolt won't magically disappear! - SetOwnerEntity( pOther ); - return; - } -#endif//HL2_EPISODIC - - if( GetOwnerEntity() && GetOwnerEntity()->IsPlayer() && pOther->IsNPC() ) - { - CTakeDamageInfo dmgInfo( this, GetOwnerEntity(), sk_plr_dmg_crossbow.GetFloat(), DMG_NEVERGIB ); - dmgInfo.AdjustPlayerDamageInflictedForSkillLevel(); - CalculateMeleeDamageForce( &dmgInfo, vecNormalizedVel, tr.endpos, 0.7f ); - dmgInfo.SetDamagePosition( tr.endpos ); - pOther->DispatchTraceAttack( dmgInfo, vecNormalizedVel, &tr ); - - CBasePlayer *pPlayer = ToBasePlayer( GetOwnerEntity() ); - if ( pPlayer ) - { - gamestats->Event_WeaponHit( pPlayer, true, "weapon_crossbow", dmgInfo ); - } - - } - else - { - CTakeDamageInfo dmgInfo( this, GetOwnerEntity(), sk_plr_dmg_crossbow.GetFloat(), DMG_BULLET | DMG_NEVERGIB ); - CalculateMeleeDamageForce( &dmgInfo, vecNormalizedVel, tr.endpos, 0.7f ); - dmgInfo.SetDamagePosition( tr.endpos ); - pOther->DispatchTraceAttack( dmgInfo, vecNormalizedVel, &tr ); - } - - ApplyMultiDamage(); - - //Adrian: keep going through the glass. - if ( pOther->GetCollisionGroup() == COLLISION_GROUP_BREAKABLE_GLASS ) - return; - - if ( !pOther->IsAlive() ) - { - // We killed it! - const surfacedata_t *pdata = physprops->GetSurfaceData( tr.surface.surfaceProps ); - if ( pdata->game.material == CHAR_TEX_GLASS ) - { - return; - } - } - - SetAbsVelocity( Vector( 0, 0, 0 ) ); - - // play body "thwack" sound - EmitSound( "Weapon_Crossbow.BoltHitBody" ); - - Vector vForward; - - AngleVectors( GetAbsAngles(), &vForward ); - VectorNormalize ( vForward ); - - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + vForward * 128, MASK_BLOCKLOS, pOther, COLLISION_GROUP_NONE, &tr2 ); - - if ( tr2.fraction != 1.0f ) - { -// NDebugOverlay::Box( tr2.endpos, Vector( -16, -16, -16 ), Vector( 16, 16, 16 ), 0, 255, 0, 0, 10 ); -// NDebugOverlay::Box( GetAbsOrigin(), Vector( -16, -16, -16 ), Vector( 16, 16, 16 ), 0, 0, 255, 0, 10 ); - - if ( tr2.m_pEnt == NULL || ( tr2.m_pEnt && tr2.m_pEnt->GetMoveType() == MOVETYPE_NONE ) ) - { - CEffectData data; - - data.m_vOrigin = tr2.endpos; - data.m_vNormal = vForward; - data.m_nEntIndex = tr2.fraction != 1.0f; - - DispatchEffect( "BoltImpact", data ); - } - } - - SetTouch( NULL ); - SetThink( NULL ); - - if ( !g_pGameRules->IsMultiplayer() ) - { - UTIL_Remove( this ); - } - } - else - { - trace_t tr; - tr = BaseClass::GetTouchTrace(); - - // See if we struck the world - if ( pOther->GetMoveType() == MOVETYPE_NONE && !( tr.surface.flags & SURF_SKY ) ) - { - EmitSound( "Weapon_Crossbow.BoltHitWorld" ); - - // if what we hit is static architecture, can stay around for a while. - Vector vecDir = GetAbsVelocity(); - float speed = VectorNormalize( vecDir ); - - // See if we should reflect off this surface - float hitDot = DotProduct( tr.plane.normal, -vecDir ); - - if ( ( hitDot < 0.5f ) && ( speed > 100 ) ) - { - Vector vReflection = 2.0f * tr.plane.normal * hitDot + vecDir; - - QAngle reflectAngles; - - VectorAngles( vReflection, reflectAngles ); - - SetLocalAngles( reflectAngles ); - - SetAbsVelocity( vReflection * speed * 0.75f ); - - // Start to sink faster - SetGravity( 1.0f ); - } - else - { - SetThink( &CCrossbowBolt::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 2.0f ); - - //FIXME: We actually want to stick (with hierarchy) to what we've hit - SetMoveType( MOVETYPE_NONE ); - - Vector vForward; - - AngleVectors( GetAbsAngles(), &vForward ); - VectorNormalize ( vForward ); - - CEffectData data; - - data.m_vOrigin = tr.endpos; - data.m_vNormal = vForward; - data.m_nEntIndex = 0; - - DispatchEffect( "BoltImpact", data ); - - UTIL_ImpactTrace( &tr, DMG_BULLET ); - - AddEffects( EF_NODRAW ); - SetTouch( NULL ); - SetThink( &CCrossbowBolt::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 2.0f ); - - if ( m_pGlowSprite != NULL ) - { - m_pGlowSprite->TurnOn(); - m_pGlowSprite->FadeAndDie( 3.0f ); - } - } - - // Shoot some sparks - if ( UTIL_PointContents( GetAbsOrigin() ) != CONTENTS_WATER) - { - g_pEffects->Sparks( GetAbsOrigin() ); - } - } - else - { - // Put a mark unless we've hit the sky - if ( ( tr.surface.flags & SURF_SKY ) == false ) - { - UTIL_ImpactTrace( &tr, DMG_BULLET ); - } - - UTIL_Remove( this ); - } - } - - if ( g_pGameRules->IsMultiplayer() ) - { -// SetThink( &CCrossbowBolt::ExplodeThink ); -// SetNextThink( gpGlobals->curtime + 0.1f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCrossbowBolt::BubbleThink( void ) -{ - QAngle angNewAngles; - - VectorAngles( GetAbsVelocity(), angNewAngles ); - SetAbsAngles( angNewAngles ); - - SetNextThink( gpGlobals->curtime + 0.1f ); - - // Make danger sounds out in front of me, to scare snipers back into their hole - CSoundEnt::InsertSound( SOUND_DANGER_SNIPERONLY, GetAbsOrigin() + GetAbsVelocity() * 0.2, 120, 0.5f, this, SOUNDENT_CHANNEL_REPEATED_DANGER ); - - if ( GetWaterLevel() == 0 ) - return; - - UTIL_BubbleTrail( GetAbsOrigin() - GetAbsVelocity() * 0.1f, GetAbsOrigin(), 5 ); -} - - -//----------------------------------------------------------------------------- -// CWeaponCrossbow -//----------------------------------------------------------------------------- - -class CWeaponCrossbow : public CBaseHLCombatWeapon -{ - DECLARE_CLASS( CWeaponCrossbow, CBaseHLCombatWeapon ); -public: - - CWeaponCrossbow( void ); - - virtual void Precache( void ); - virtual void PrimaryAttack( void ); - virtual void SecondaryAttack( void ); - virtual bool Deploy( void ); - virtual void Drop( const Vector &vecVelocity ); - virtual bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); - virtual bool Reload( void ); - virtual void ItemPostFrame( void ); - virtual void ItemBusyFrame( void ); - virtual void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); - virtual bool SendWeaponAnim( int iActivity ); - virtual bool IsWeaponZoomed() { return m_bInZoom; } - - bool ShouldDisplayHUDHint() { return true; } - - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - -private: - - void StopEffects( void ); - void SetSkin( int skinNum ); - void CheckZoomToggle( void ); - void FireBolt( void ); - void ToggleZoom( void ); - - // Various states for the crossbow's charger - enum ChargerState_t - { - CHARGER_STATE_START_LOAD, - CHARGER_STATE_START_CHARGE, - CHARGER_STATE_READY, - CHARGER_STATE_DISCHARGE, - CHARGER_STATE_OFF, - }; - - void CreateChargerEffects( void ); - void SetChargerState( ChargerState_t state ); - void DoLoadEffect( void ); - -private: - - // Charger effects - ChargerState_t m_nChargeState; - CHandle m_hChargerSprite; - - bool m_bInZoom; - bool m_bMustReload; -}; - -LINK_ENTITY_TO_CLASS( weapon_crossbow, CWeaponCrossbow ); - -PRECACHE_WEAPON_REGISTER( weapon_crossbow ); - -IMPLEMENT_SERVERCLASS_ST( CWeaponCrossbow, DT_WeaponCrossbow ) -END_SEND_TABLE() - -BEGIN_DATADESC( CWeaponCrossbow ) - - DEFINE_FIELD( m_bInZoom, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bMustReload, FIELD_BOOLEAN ), - DEFINE_FIELD( m_nChargeState, FIELD_INTEGER ), - DEFINE_FIELD( m_hChargerSprite, FIELD_EHANDLE ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -CWeaponCrossbow::CWeaponCrossbow( void ) -{ - m_bReloadsSingly = true; - m_bFiresUnderwater = true; - m_bAltFiresUnderwater = true; - m_bInZoom = false; - m_bMustReload = false; -} - -#define CROSSBOW_GLOW_SPRITE "sprites/light_glow02_noz.vmt" -#define CROSSBOW_GLOW_SPRITE2 "sprites/blueflare1.vmt" - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCrossbow::Precache( void ) -{ - UTIL_PrecacheOther( "crossbow_bolt" ); - - PrecacheScriptSound( "Weapon_Crossbow.BoltHitBody" ); - PrecacheScriptSound( "Weapon_Crossbow.BoltHitWorld" ); - PrecacheScriptSound( "Weapon_Crossbow.BoltSkewer" ); - - PrecacheModel( CROSSBOW_GLOW_SPRITE ); - PrecacheModel( CROSSBOW_GLOW_SPRITE2 ); - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCrossbow::PrimaryAttack( void ) -{ - if ( m_bInZoom && g_pGameRules->IsMultiplayer() ) - { -// FireSniperBolt(); - FireBolt(); - } - else - { - FireBolt(); - } - - // Signal a reload - m_bMustReload = true; - - SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration( ACT_VM_PRIMARYATTACK ) ); - - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - if ( pPlayer ) - { - m_iPrimaryAttacks++; - gamestats->Event_WeaponFired( pPlayer, true, GetClassname() ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCrossbow::SecondaryAttack( void ) -{ - //NOTENOTE: The zooming is handled by the post/busy frames -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponCrossbow::Reload( void ) -{ - if ( BaseClass::Reload() ) - { - m_bMustReload = false; - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCrossbow::CheckZoomToggle( void ) -{ - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if ( pPlayer->m_afButtonPressed & IN_ATTACK2 ) - { - ToggleZoom(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCrossbow::ItemBusyFrame( void ) -{ - // Allow zoom toggling even when we're reloading - CheckZoomToggle(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCrossbow::ItemPostFrame( void ) -{ - // Allow zoom toggling - CheckZoomToggle(); - - if ( m_bMustReload && HasWeaponIdleTimeElapsed() ) - { - Reload(); - } - - BaseClass::ItemPostFrame(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCrossbow::FireBolt( void ) -{ - if ( m_iClip1 <= 0 ) - { - if ( !m_bFireOnEmpty ) - { - Reload(); - } - else - { - WeaponSound( EMPTY ); - m_flNextPrimaryAttack = 0.15; - } - - return; - } - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - pOwner->RumbleEffect( RUMBLE_357, 0, RUMBLE_FLAG_RESTART ); - - Vector vecAiming = pOwner->GetAutoaimVector( 0 ); - Vector vecSrc = pOwner->Weapon_ShootPosition(); - - QAngle angAiming; - VectorAngles( vecAiming, angAiming ); - -#if defined(HL2_EPISODIC) - // !!!HACK - the other piece of the Alyx crossbow bolt hack for Outland_10 (see ::BoltTouch() for more detail) - if( FStrEq(STRING(gpGlobals->mapname), "ep2_outland_10") ) - { - trace_t tr; - UTIL_TraceLine( vecSrc, vecSrc + vecAiming * 24.0f, MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); - - if( tr.m_pEnt != NULL && tr.m_pEnt->Classify() == CLASS_PLAYER_ALLY_VITAL ) - { - // If Alyx is right in front of the player, make sure the bolt starts outside of the player's BBOX, or the bolt - // will instantly collide with the player after the owner of the bolt is switched to Alyx in ::BoltTouch(). We - // avoid this altogether by making it impossible for the bolt to collide with the player. - vecSrc += vecAiming * 24.0f; - } - } -#endif - - CCrossbowBolt *pBolt = CCrossbowBolt::BoltCreate( vecSrc, angAiming, pOwner ); - - if ( pOwner->GetWaterLevel() == 3 ) - { - pBolt->SetAbsVelocity( vecAiming * BOLT_WATER_VELOCITY ); - } - else - { - pBolt->SetAbsVelocity( vecAiming * BOLT_AIR_VELOCITY ); - } - - m_iClip1--; - - pOwner->ViewPunch( QAngle( -2, 0, 0 ) ); - - WeaponSound( SINGLE ); - WeaponSound( SPECIAL2 ); - - CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 200, 0.2 ); - - SendWeaponAnim( ACT_VM_PRIMARYATTACK ); - - if ( !m_iClip1 && pOwner->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 ) - { - // HEV suit - indicate out of ammo condition - pOwner->SetSuitUpdate("!HEV_AMO0", FALSE, 0); - } - - m_flNextPrimaryAttack = m_flNextSecondaryAttack = gpGlobals->curtime + 0.75; - - DoLoadEffect(); - SetChargerState( CHARGER_STATE_DISCHARGE ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponCrossbow::Deploy( void ) -{ - if ( m_iClip1 <= 0 ) - { - return DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), ACT_CROSSBOW_DRAW_UNLOADED, (char*)GetAnimPrefix() ); - } - - SetSkin( BOLT_SKIN_GLOW ); - - return BaseClass::Deploy(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pSwitchingTo - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponCrossbow::Holster( CBaseCombatWeapon *pSwitchingTo ) -{ - StopEffects(); - return BaseClass::Holster( pSwitchingTo ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCrossbow::ToggleZoom( void ) -{ - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if ( pPlayer == NULL ) - return; - - if ( m_bInZoom ) - { - if ( pPlayer->SetFOV( this, 0, 0.2f ) ) - { - m_bInZoom = false; - } - } - else - { - if ( pPlayer->SetFOV( this, 20, 0.1f ) ) - { - m_bInZoom = true; - } - } -} - -#define BOLT_TIP_ATTACHMENT 2 - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCrossbow::CreateChargerEffects( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( m_hChargerSprite != NULL ) - return; - - m_hChargerSprite = CSprite::SpriteCreate( CROSSBOW_GLOW_SPRITE, GetAbsOrigin(), false ); - - if ( m_hChargerSprite ) - { - m_hChargerSprite->SetAttachment( pOwner->GetViewModel(), BOLT_TIP_ATTACHMENT ); - m_hChargerSprite->SetTransparency( kRenderTransAdd, 255, 128, 0, 255, kRenderFxNoDissipation ); - m_hChargerSprite->SetBrightness( 0 ); - m_hChargerSprite->SetScale( 0.1f ); - m_hChargerSprite->TurnOff(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : skinNum - -//----------------------------------------------------------------------------- -void CWeaponCrossbow::SetSkin( int skinNum ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - CBaseViewModel *pViewModel = pOwner->GetViewModel(); - - if ( pViewModel == NULL ) - return; - - pViewModel->m_nSkin = skinNum; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCrossbow::DoLoadEffect( void ) -{ - SetSkin( BOLT_SKIN_GLOW ); - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - CBaseViewModel *pViewModel = pOwner->GetViewModel(); - - if ( pViewModel == NULL ) - return; - - CEffectData data; - - data.m_nEntIndex = pViewModel->entindex(); - data.m_nAttachmentIndex = 1; - - DispatchEffect( "CrossbowLoad", data ); - - CSprite *pBlast = CSprite::SpriteCreate( CROSSBOW_GLOW_SPRITE2, GetAbsOrigin(), false ); - - if ( pBlast ) - { - pBlast->SetAttachment( pOwner->GetViewModel(), 1 ); - pBlast->SetTransparency( kRenderTransAdd, 255, 255, 255, 255, kRenderFxNone ); - pBlast->SetBrightness( 128 ); - pBlast->SetScale( 0.2f ); - pBlast->FadeOutFromSpawn(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : state - -//----------------------------------------------------------------------------- -void CWeaponCrossbow::SetChargerState( ChargerState_t state ) -{ - // Make sure we're setup - CreateChargerEffects(); - - // Don't do this twice - if ( state == m_nChargeState ) - return; - - m_nChargeState = state; - - switch( m_nChargeState ) - { - case CHARGER_STATE_START_LOAD: - - WeaponSound( SPECIAL1 ); - - // Shoot some sparks and draw a beam between the two outer points - DoLoadEffect(); - - break; - - case CHARGER_STATE_START_CHARGE: - { - if ( m_hChargerSprite == NULL ) - break; - - m_hChargerSprite->SetBrightness( 32, 0.5f ); - m_hChargerSprite->SetScale( 0.025f, 0.5f ); - m_hChargerSprite->TurnOn(); - } - - break; - - case CHARGER_STATE_READY: - { - // Get fully charged - if ( m_hChargerSprite == NULL ) - break; - - m_hChargerSprite->SetBrightness( 80, 1.0f ); - m_hChargerSprite->SetScale( 0.1f, 0.5f ); - m_hChargerSprite->TurnOn(); - } - - break; - - case CHARGER_STATE_DISCHARGE: - { - SetSkin( BOLT_SKIN_NORMAL ); - - if ( m_hChargerSprite == NULL ) - break; - - m_hChargerSprite->SetBrightness( 0 ); - m_hChargerSprite->TurnOff(); - } - - break; - - case CHARGER_STATE_OFF: - { - SetSkin( BOLT_SKIN_NORMAL ); - - if ( m_hChargerSprite == NULL ) - break; - - m_hChargerSprite->SetBrightness( 0 ); - m_hChargerSprite->TurnOff(); - } - break; - - default: - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEvent - -// *pOperator - -//----------------------------------------------------------------------------- -void CWeaponCrossbow::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - switch( pEvent->event ) - { - case EVENT_WEAPON_THROW: - SetChargerState( CHARGER_STATE_START_LOAD ); - break; - - case EVENT_WEAPON_THROW2: - SetChargerState( CHARGER_STATE_START_CHARGE ); - break; - - case EVENT_WEAPON_THROW3: - SetChargerState( CHARGER_STATE_READY ); - break; - - default: - BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Set the desired activity for the weapon and its viewmodel counterpart -// Input : iActivity - activity to play -//----------------------------------------------------------------------------- -bool CWeaponCrossbow::SendWeaponAnim( int iActivity ) -{ - int newActivity = iActivity; - - // The last shot needs a non-loaded activity - if ( ( newActivity == ACT_VM_IDLE ) && ( m_iClip1 <= 0 ) ) - { - newActivity = ACT_VM_FIDGET; - } - - //For now, just set the ideal activity and be done with it - return BaseClass::SendWeaponAnim( newActivity ); -} - -//----------------------------------------------------------------------------- -// Purpose: Stop all zooming and special effects on the viewmodel -//----------------------------------------------------------------------------- -void CWeaponCrossbow::StopEffects( void ) -{ - // Stop zooming - if ( m_bInZoom ) - { - ToggleZoom(); - } - - // Turn off our sprites - SetChargerState( CHARGER_STATE_OFF ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCrossbow::Drop( const Vector &vecVelocity ) -{ - StopEffects(); - BaseClass::Drop( vecVelocity ); -} diff --git a/game/server/hl2/weapon_crowbar.cpp b/game/server/hl2/weapon_crowbar.cpp deleted file mode 100644 index 144510aa9..000000000 --- a/game/server/hl2/weapon_crowbar.cpp +++ /dev/null @@ -1,203 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Crowbar - an old favorite -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "basehlcombatweapon.h" -#include "player.h" -#include "gamerules.h" -#include "ammodef.h" -#include "mathlib/mathlib.h" -#include "in_buttons.h" -#include "soundent.h" -#include "basebludgeonweapon.h" -#include "vstdlib/random.h" -#include "npcevent.h" -#include "ai_basenpc.h" -#include "weapon_crowbar.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar sk_plr_dmg_crowbar ( "sk_plr_dmg_crowbar","0"); -ConVar sk_npc_dmg_crowbar ( "sk_npc_dmg_crowbar","0"); - -//----------------------------------------------------------------------------- -// CWeaponCrowbar -//----------------------------------------------------------------------------- - -IMPLEMENT_SERVERCLASS_ST(CWeaponCrowbar, DT_WeaponCrowbar) -END_SEND_TABLE() - -#ifndef HL2MP -LINK_ENTITY_TO_CLASS( weapon_crowbar, CWeaponCrowbar ); -PRECACHE_WEAPON_REGISTER( weapon_crowbar ); -#endif - -acttable_t CWeaponCrowbar::m_acttable[] = -{ - { ACT_MELEE_ATTACK1, ACT_MELEE_ATTACK_SWING, true }, - { ACT_IDLE, ACT_IDLE_ANGRY_MELEE, false }, - { ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_MELEE, false }, -}; - -IMPLEMENT_ACTTABLE(CWeaponCrowbar); - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CWeaponCrowbar::CWeaponCrowbar( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: Get the damage amount for the animation we're doing -// Input : hitActivity - currently played activity -// Output : Damage amount -//----------------------------------------------------------------------------- -float CWeaponCrowbar::GetDamageForActivity( Activity hitActivity ) -{ - if ( ( GetOwner() != NULL ) && ( GetOwner()->IsPlayer() ) ) - return sk_plr_dmg_crowbar.GetFloat(); - - return sk_npc_dmg_crowbar.GetFloat(); -} - -//----------------------------------------------------------------------------- -// Purpose: Add in a view kick for this weapon -//----------------------------------------------------------------------------- -void CWeaponCrowbar::AddViewKick( void ) -{ - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if ( pPlayer == NULL ) - return; - - QAngle punchAng; - - punchAng.x = random->RandomFloat( 1.0f, 2.0f ); - punchAng.y = random->RandomFloat( -2.0f, -1.0f ); - punchAng.z = 0.0f; - - pPlayer->ViewPunch( punchAng ); -} - - -//----------------------------------------------------------------------------- -// Attempt to lead the target (needed because citizens can't hit manhacks with the crowbar!) -//----------------------------------------------------------------------------- -ConVar sk_crowbar_lead_time( "sk_crowbar_lead_time", "0.9" ); - -int CWeaponCrowbar::WeaponMeleeAttack1Condition( float flDot, float flDist ) -{ - // Attempt to lead the target (needed because citizens can't hit manhacks with the crowbar!) - CAI_BaseNPC *pNPC = GetOwner()->MyNPCPointer(); - CBaseEntity *pEnemy = pNPC->GetEnemy(); - if (!pEnemy) - return COND_NONE; - - Vector vecVelocity; - vecVelocity = pEnemy->GetSmoothedVelocity( ); - - // Project where the enemy will be in a little while - float dt = sk_crowbar_lead_time.GetFloat(); - dt += random->RandomFloat( -0.3f, 0.2f ); - if ( dt < 0.0f ) - dt = 0.0f; - - Vector vecExtrapolatedPos; - VectorMA( pEnemy->WorldSpaceCenter(), dt, vecVelocity, vecExtrapolatedPos ); - - Vector vecDelta; - VectorSubtract( vecExtrapolatedPos, pNPC->WorldSpaceCenter(), vecDelta ); - - if ( fabs( vecDelta.z ) > 70 ) - { - return COND_TOO_FAR_TO_ATTACK; - } - - Vector vecForward = pNPC->BodyDirection2D( ); - vecDelta.z = 0.0f; - float flExtrapolatedDist = Vector2DNormalize( vecDelta.AsVector2D() ); - if ((flDist > 64) && (flExtrapolatedDist > 64)) - { - return COND_TOO_FAR_TO_ATTACK; - } - - float flExtrapolatedDot = DotProduct2D( vecDelta.AsVector2D(), vecForward.AsVector2D() ); - if ((flDot < 0.7) && (flExtrapolatedDot < 0.7)) - { - return COND_NOT_FACING_ATTACK; - } - - return COND_CAN_MELEE_ATTACK1; -} - - -//----------------------------------------------------------------------------- -// Animation event handlers -//----------------------------------------------------------------------------- -void CWeaponCrowbar::HandleAnimEventMeleeHit( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - // Trace up or down based on where the enemy is... - // But only if we're basically facing that direction - Vector vecDirection; - AngleVectors( GetAbsAngles(), &vecDirection ); - - CBaseEntity *pEnemy = pOperator->MyNPCPointer() ? pOperator->MyNPCPointer()->GetEnemy() : NULL; - if ( pEnemy ) - { - Vector vecDelta; - VectorSubtract( pEnemy->WorldSpaceCenter(), pOperator->Weapon_ShootPosition(), vecDelta ); - VectorNormalize( vecDelta ); - - Vector2D vecDelta2D = vecDelta.AsVector2D(); - Vector2DNormalize( vecDelta2D ); - if ( DotProduct2D( vecDelta2D, vecDirection.AsVector2D() ) > 0.8f ) - { - vecDirection = vecDelta; - } - } - - Vector vecEnd; - VectorMA( pOperator->Weapon_ShootPosition(), 50, vecDirection, vecEnd ); - CBaseEntity *pHurt = pOperator->CheckTraceHullAttack( pOperator->Weapon_ShootPosition(), vecEnd, - Vector(-16,-16,-16), Vector(36,36,36), sk_npc_dmg_crowbar.GetInt(), DMG_CLUB, 0.75 ); - - // did I hit someone? - if ( pHurt ) - { - // play sound - WeaponSound( MELEE_HIT ); - - // Fake a trace impact, so the effects work out like a player's crowbaw - trace_t traceHit; - UTIL_TraceLine( pOperator->Weapon_ShootPosition(), pHurt->GetAbsOrigin(), MASK_SHOT_HULL, pOperator, COLLISION_GROUP_NONE, &traceHit ); - ImpactEffect( traceHit ); - } - else - { - WeaponSound( MELEE_MISS ); - } -} - - -//----------------------------------------------------------------------------- -// Animation event -//----------------------------------------------------------------------------- -void CWeaponCrowbar::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - switch( pEvent->event ) - { - case EVENT_WEAPON_MELEE_HIT: - HandleAnimEventMeleeHit( pEvent, pOperator ); - break; - - default: - BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); - break; - } -} diff --git a/game/server/hl2/weapon_crowbar.h b/game/server/hl2/weapon_crowbar.h deleted file mode 100644 index 23bf654de..000000000 --- a/game/server/hl2/weapon_crowbar.h +++ /dev/null @@ -1,54 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef WEAPON_CROWBAR_H -#define WEAPON_CROWBAR_H - -#include "basebludgeonweapon.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -#ifdef HL2MP -#error weapon_crowbar.h must not be included in hl2mp. The windows compiler will use the wrong class elsewhere if it is. -#endif - -#define CROWBAR_RANGE 75.0f -#define CROWBAR_REFIRE 0.4f - -//----------------------------------------------------------------------------- -// CWeaponCrowbar -//----------------------------------------------------------------------------- - -class CWeaponCrowbar : public CBaseHLBludgeonWeapon -{ -public: - DECLARE_CLASS( CWeaponCrowbar, CBaseHLBludgeonWeapon ); - - DECLARE_SERVERCLASS(); - DECLARE_ACTTABLE(); - - CWeaponCrowbar(); - - float GetRange( void ) { return CROWBAR_RANGE; } - float GetFireRate( void ) { return CROWBAR_REFIRE; } - - void AddViewKick( void ); - float GetDamageForActivity( Activity hitActivity ); - - virtual int WeaponMeleeAttack1Condition( float flDot, float flDist ); - void SecondaryAttack( void ) { return; } - - // Animation event - virtual void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); - -private: - // Animation event handlers - void HandleAnimEventMeleeHit( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); -}; - -#endif // WEAPON_CROWBAR_H diff --git a/game/server/hl2/weapon_extinguisher.cpp b/game/server/hl2/weapon_extinguisher.cpp deleted file mode 100644 index e510fc5dc..000000000 --- a/game/server/hl2/weapon_extinguisher.cpp +++ /dev/null @@ -1,380 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "basehlcombatweapon.h" -#include "gamerules.h" -#include "game.h" -#include "in_buttons.h" -#include "extinguisherjet.h" -#include "entitylist.h" -#include "fire.h" -#include "ar2_explosion.h" -#include "ndebugoverlay.h" -#include "engine/IEngineSound.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar fire_extinguisher_debug( "fire_extinguisher_debug", "0" ); -ConVar fire_extinguisher_radius( "fire_extinguisher_radius", "45" ); -ConVar fire_extinguisher_distance( "fire_extinguisher_distance", "200" ); -ConVar fire_extinguisher_strength( "fire_extinguisher_strength", "0.97" ); //TODO: Stub for real numbers -ConVar fire_extinguisher_explode_radius( "fire_extinguisher_explode_radius", "256" ); -ConVar fire_extinguisher_explode_strength( "fire_extinguisher_explode_strength", "0.3" ); //TODO: Stub for real numbers - -#define EXTINGUISHER_AMMO_RATE 0.2 - -extern short g_sModelIndexFireball; // (in combatweapon.cpp) holds the index for the smoke cloud - -class CWeaponExtinguisher: public CHLSelectFireMachineGun -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( CWeaponExtinguisher, CHLSelectFireMachineGun ); - - DECLARE_SERVERCLASS(); - - CWeaponExtinguisher(); - - void Spawn( void ); - void Precache( void ); - - void ItemPostFrame( void ); - void Event_Killed( const CTakeDamageInfo &info ); - void Equip( CBaseCombatCharacter *pOwner ); - -protected: - - void StartJet( void ); - void StopJet( void ); - - CExtinguisherJet *m_pJet; -}; - -IMPLEMENT_SERVERCLASS_ST(CWeaponExtinguisher, DT_WeaponExtinguisher) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_extinguisher, CWeaponExtinguisher ); -PRECACHE_WEAPON_REGISTER( weapon_extinguisher ); - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CWeaponExtinguisher ) - - DEFINE_FIELD( m_pJet, FIELD_CLASSPTR ), - -END_DATADESC() - - -CWeaponExtinguisher::CWeaponExtinguisher( void ) -{ - m_pJet = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponExtinguisher::Precache( void ) -{ - BaseClass::Precache(); - - PrecacheScriptSound( "ExtinguisherCharger.Use" ); - - UTIL_PrecacheOther( "env_extinguisherjet" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponExtinguisher::Spawn( void ) -{ - BaseClass::Spawn(); - - m_takedamage = DAMAGE_YES; - m_iHealth = 25;//FIXME: Define -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOwner - -//----------------------------------------------------------------------------- -void CWeaponExtinguisher::Equip( CBaseCombatCharacter *pOwner ) -{ - BaseClass::Equip( pOwner ); - - m_takedamage = DAMAGE_NO; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pInflictor - -// *pAttacker - -// flDamage - -// bitsDamageType - -//----------------------------------------------------------------------------- -void CWeaponExtinguisher::Event_Killed( const CTakeDamageInfo &info ) -{ - //TODO: Use a real effect - if ( AR2Explosion *pExplosion = AR2Explosion::CreateAR2Explosion( GetAbsOrigin() ) ) - { - pExplosion->SetLifetime( 10 ); - } - - //TODO: Use a real effect - CPASFilter filter( GetAbsOrigin() ); - - te->Explosion( filter, 0.0, - &GetAbsOrigin(), - g_sModelIndexFireball, - 2.0, - 15, - TE_EXPLFLAG_NONE, - 250, - 100 ); - - //Put out fire in a radius - FireSystem_ExtinguishInRadius( GetAbsOrigin(), fire_extinguisher_explode_radius.GetInt(), fire_extinguisher_explode_strength.GetFloat() ); - - SetThink( &CBaseEntity::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -//----------------------------------------------------------------------------- -// Purpose: Turn the jet effect and noise on -//----------------------------------------------------------------------------- -void CWeaponExtinguisher::StartJet( void ) -{ - //See if the jet needs to be created - if ( m_pJet == NULL ) - { - m_pJet = (CExtinguisherJet *) CreateEntityByName( "env_extinguisherjet" ); - - if ( m_pJet == NULL ) - { - Msg( "Unable to create jet for weapon_extinguisher!\n" ); - return; - } - - //Setup the jet - m_pJet->m_bEmit = false; - UTIL_SetOrigin( m_pJet, GetAbsOrigin() ); - m_pJet->SetParent( this ); - - m_pJet->m_bUseMuzzlePoint = true; - m_pJet->m_bAutoExtinguish = false; - m_pJet->m_nLength = fire_extinguisher_distance.GetInt(); - } - - //Turn the jet on - if ( m_pJet != NULL ) - { - m_pJet->TurnOn(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Turn the jet effect and noise off -//----------------------------------------------------------------------------- -void CWeaponExtinguisher::StopJet( void ) -{ - //Turn the jet off - if ( m_pJet != NULL ) - { - m_pJet->TurnOff(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponExtinguisher::ItemPostFrame( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - //Only shoot if we have ammo - if ( pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0 ) - { - StopJet(); - return; - } - - //See if we should try and extinguish fires - if ( pOwner->m_nButtons & IN_ATTACK ) - { - //Drain ammo - if ( m_flNextPrimaryAttack < gpGlobals->curtime ) - { - pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType ); - m_flNextPrimaryAttack = gpGlobals->curtime + EXTINGUISHER_AMMO_RATE; - } - - //If we're just run out... - if ( pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0 ) - { - StopJet(); - return; - } - - //Turn the jet on - StartJet(); - - Vector vTestPos, vMuzzlePos; - Vector vForward, vRight, vUp; - - pOwner->EyeVectors( &vForward, &vRight, &vUp ); - - vMuzzlePos = pOwner->Weapon_ShootPosition( ); - - //FIXME: Need to get the exact same muzzle point! - - //FIXME: This needs to be adjusted so the server collision matches the visuals on the client - vMuzzlePos += vForward * 15.0f; - vMuzzlePos += vRight * 6.0f; - vMuzzlePos += vUp * -4.0f; - - QAngle aTmp; - VectorAngles( vForward, aTmp ); - aTmp[PITCH] += 10; - AngleVectors( aTmp, &vForward ); - - vTestPos = vMuzzlePos + ( vForward * fire_extinguisher_distance.GetInt() ); - - trace_t tr; - UTIL_TraceLine( vMuzzlePos, vTestPos, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - //Extinguish the fire where we hit - FireSystem_ExtinguishInRadius( tr.endpos, fire_extinguisher_radius.GetInt(), fire_extinguisher_strength.GetFloat() ); - - //Debug visualization - if ( fire_extinguisher_debug.GetInt() ) - { - int radius = fire_extinguisher_radius.GetInt(); - - NDebugOverlay::Line( vMuzzlePos, tr.endpos, 0, 0, 128, false, 0.0f ); - - NDebugOverlay::Box( vMuzzlePos, Vector(-1, -1, -1), Vector(1, 1, 1), 0, 0, 128, false, 0.0f ); - NDebugOverlay::Box( tr.endpos, Vector(-2, -2, -2), Vector(2, 2, 2), 0, 0, 128, false, 0.0f ); - NDebugOverlay::Box( tr.endpos, Vector(-radius, -radius, -radius), Vector(radius, radius, radius), 0, 0, 255, false, 0.0f ); - } - } - else - { - StopJet(); - } -} - -class CExtinguisherCharger : public CBaseToggle -{ -public: - DECLARE_CLASS( CExtinguisherCharger, CBaseToggle ); - - void Spawn( void ); - bool CreateVPhysics(); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - virtual int ObjectCaps( void ) { return (BaseClass::ObjectCaps() | FCAP_CONTINUOUS_USE) & ~FCAP_ACROSS_TRANSITION; } - -protected: - float m_flNextCharge; - bool m_bSoundOn; - - void TurnOff( void ); - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( func_extinguishercharger, CExtinguisherCharger ); - -BEGIN_DATADESC( CExtinguisherCharger ) - - DEFINE_FIELD( m_flNextCharge, FIELD_TIME), - DEFINE_FIELD( m_bSoundOn, FIELD_BOOLEAN ), - - DEFINE_FUNCTION( TurnOff ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: Spawn the object -//----------------------------------------------------------------------------- -void CExtinguisherCharger::Spawn( void ) -{ - Precache(); - - SetSolid( SOLID_BSP ); - SetMoveType( MOVETYPE_PUSH ); - - SetModel( STRING( GetModelName() ) ); - - m_bSoundOn = false; - - CreateVPhysics(); -} - -//----------------------------------------------------------------------------- - -bool CExtinguisherCharger::CreateVPhysics() -{ - VPhysicsInitStatic(); - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pActivator - -// *pCaller - -// useType - -// value - -//----------------------------------------------------------------------------- -void CExtinguisherCharger::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - // Make sure that we have a caller - if ( pActivator == NULL ) - return; - - // If it's not a player, ignore - if ( pActivator->IsPlayer() == false ) - return; - - // Turn our sound on, if it's not already - if ( m_bSoundOn == false ) - { - EmitSound( "ExtinguisherCharger.Use" ); - m_bSoundOn = true; - } - - SetNextThink( gpGlobals->curtime + 0.25 ); - - SetThink( &CExtinguisherCharger::TurnOff ); - - CBasePlayer *pPlayer = ToBasePlayer( pActivator ); - - if ( pPlayer ) - { - //FIXME: Need a way to do this silently - pPlayer->GiveAmmo( 1, "extinguisher" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CExtinguisherCharger::TurnOff( void ) -{ - //Turn the sound off - if ( m_bSoundOn ) - { - StopSound( "ExtinguisherCharger.Use" ); - m_bSoundOn = false; - } -} diff --git a/game/server/hl2/weapon_flaregun.cpp b/game/server/hl2/weapon_flaregun.cpp deleted file mode 100644 index c9eda78e1..000000000 --- a/game/server/hl2/weapon_flaregun.cpp +++ /dev/null @@ -1,755 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Flare gun (fffsssssssssss!!) -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "player.h" -#include "gamerules.h" -#include "basehlcombatweapon.h" -#include "decals.h" -#include "soundenvelope.h" -#include "IEffects.h" -#include "engine/IEngineSound.h" -#include "weapon_flaregun.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -/******************************************************************** - NOTE: if you are looking at this file becase you would like flares - to be considered as fires (and thereby trigger gas traps), be aware - that the env_flare class is actually found in weapon_flaregun.cpp - and is really a repurposed piece of ammunition. (env_flare isn't the - rod-like safety flare prop, but rather the bit of flame on the end.) - - You will have some difficulty making it work here, because CFlare - does not inherit from CFire and will thus not be enumerated by - CFireSphere::EnumElement(). In order to have flares be detected and - used by this system, you will need to promote certain member functions - of CFire into an interface class from which both CFire and CFlare - inherit. You will also need to modify CFireSphere::EnumElement so that - it properly disambiguates between fires and flares. - - For some partial work towards this end, see changelist 192474. - - ********************************************************************/ - - -#define FLARE_LAUNCH_SPEED 1500 - -LINK_ENTITY_TO_CLASS( env_flare, CFlare ); - -BEGIN_DATADESC( CFlare ) - - DEFINE_FIELD( m_pOwner, FIELD_CLASSPTR ), - DEFINE_FIELD( m_nBounces, FIELD_INTEGER ), - DEFINE_FIELD( m_flTimeBurnOut, FIELD_TIME ), - DEFINE_KEYFIELD( m_flScale, FIELD_FLOAT, "scale" ), - DEFINE_KEYFIELD( m_flDuration, FIELD_FLOAT, "duration" ), - DEFINE_FIELD( m_flNextDamage, FIELD_TIME ), - DEFINE_SOUNDPATCH( m_pBurnSound ), - DEFINE_FIELD( m_bFading, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bLight, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bSmoke, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bPropFlare, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bInActiveList, FIELD_BOOLEAN ), - DEFINE_FIELD( m_pNextFlare, FIELD_CLASSPTR ), - - //Input functions - DEFINE_INPUTFUNC( FIELD_FLOAT, "Start", InputStart ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "Die", InputDie ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "Launch", InputLaunch), - - // Function Pointers - DEFINE_FUNCTION( FlareTouch ), - DEFINE_FUNCTION( FlareBurnTouch ), - DEFINE_FUNCTION( FlareThink ), - -END_DATADESC() - -//Data-tables -IMPLEMENT_SERVERCLASS_ST( CFlare, DT_Flare ) - SendPropFloat( SENDINFO( m_flTimeBurnOut ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO( m_flScale ), 0, SPROP_NOSCALE ), - SendPropInt( SENDINFO( m_bLight ), 1, SPROP_UNSIGNED ), - SendPropInt( SENDINFO( m_bSmoke ), 1, SPROP_UNSIGNED ), - SendPropInt( SENDINFO( m_bPropFlare ), 1, SPROP_UNSIGNED ), -END_SEND_TABLE() - -CFlare *CFlare::activeFlares = NULL; - -CFlare *CFlare::GetActiveFlares( void ) -{ - return CFlare::activeFlares; -} - -Class_T CFlare::Classify( void ) -{ - return CLASS_FLARE; -} - -CBaseEntity *CreateFlare( Vector vOrigin, QAngle Angles, CBaseEntity *pOwner, float flDuration ) -{ - CFlare *pFlare = CFlare::Create( vOrigin, Angles, pOwner, flDuration ); - - if ( pFlare ) - { - pFlare->m_bPropFlare = true; - } - - return pFlare; -} - -void KillFlare( CBaseEntity *pOwnerEntity, CBaseEntity *pEntity, float flKillTime ) -{ - CFlare *pFlare = dynamic_cast< CFlare *>( pEntity ); - - if ( pFlare ) - { - float flDieTime = (pFlare->m_flTimeBurnOut - gpGlobals->curtime) - flKillTime; - - if ( flDieTime > 1.0f ) - { - pFlare->Die( flDieTime ); - pOwnerEntity->SetNextThink( gpGlobals->curtime + flDieTime + 3.0f ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CFlare::CFlare( void ) -{ - m_flScale = 1.0f; - m_nBounces = 0; - m_bFading = false; - m_bLight = true; - m_bSmoke = true; - m_flNextDamage = gpGlobals->curtime; - m_lifeState = LIFE_ALIVE; - m_iHealth = 100; - m_bPropFlare = false; - m_bInActiveList = false; - m_pNextFlare = NULL; -} - -CFlare::~CFlare() -{ - CSoundEnvelopeController::GetController().SoundDestroy( m_pBurnSound ); - m_pBurnSound = NULL; - - RemoveFromActiveFlares(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFlare::Precache( void ) -{ - PrecacheModel("models/weapons/flare.mdl" ); - - PrecacheScriptSound( "Weapon_FlareGun.Burn" ); - - // FIXME: needed to precache the fire model. Shouldn't have to do this. - UTIL_PrecacheOther( "_firesmoke" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &restore - -// Output : int -//----------------------------------------------------------------------------- -int CFlare::Restore( IRestore &restore ) -{ - int result = BaseClass::Restore( restore ); - - if ( m_spawnflags & SF_FLARE_NO_DLIGHT ) - { - m_bLight = false; - } - - if ( m_spawnflags & SF_FLARE_NO_SMOKE ) - { - m_bSmoke = false; - } - - return result; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFlare::Spawn( void ) -{ - Precache(); - - SetModel( "models/weapons/flare.mdl" ); - - UTIL_SetSize( this, Vector( -2, -2, -2 ), Vector( 2, 2, 2 ) ); - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_SOLID ); - - SetMoveType( MOVETYPE_NONE ); - SetFriction( 0.6f ); - SetGravity( UTIL_ScaleForGravity( 400 ) ); - m_flTimeBurnOut = gpGlobals->curtime + 30; - - AddEffects( EF_NOSHADOW|EF_NORECEIVESHADOW ); - - if ( m_spawnflags & SF_FLARE_NO_DLIGHT ) - { - m_bLight = false; - } - - if ( m_spawnflags & SF_FLARE_NO_SMOKE ) - { - m_bSmoke = false; - } - - if ( m_spawnflags & SF_FLARE_INFINITE ) - { - m_flTimeBurnOut = -1.0f; - } - - if ( m_spawnflags & SF_FLARE_START_OFF ) - { - AddEffects( EF_NODRAW ); - } - - AddFlag( FL_OBJECT ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFlare::Activate( void ) -{ - BaseClass::Activate(); - - // Start the burning sound if we're already on - if ( ( m_spawnflags & SF_FLARE_START_OFF ) == false ) - { - StartBurnSound(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFlare::StartBurnSound( void ) -{ - if ( m_pBurnSound == NULL ) - { - CPASAttenuationFilter filter( this ); - m_pBurnSound = CSoundEnvelopeController::GetController().SoundCreate( - filter, entindex(), CHAN_WEAPON, "Weapon_FlareGun.Burn", 3.0f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : vecOrigin - -// vecAngles - -// *pOwner - -// Output : CFlare -//----------------------------------------------------------------------------- -CFlare *CFlare::Create( Vector vecOrigin, QAngle vecAngles, CBaseEntity *pOwner, float lifetime ) -{ - CFlare *pFlare = (CFlare *) CreateEntityByName( "env_flare" ); - - if ( pFlare == NULL ) - return NULL; - - UTIL_SetOrigin( pFlare, vecOrigin ); - - pFlare->SetLocalAngles( vecAngles ); - pFlare->Spawn(); - pFlare->SetTouch( &CFlare::FlareTouch ); - pFlare->SetThink( &CFlare::FlareThink ); - - //Start up the flare - pFlare->Start( lifetime ); - - //Don't start sparking immediately - pFlare->SetNextThink( gpGlobals->curtime + 0.5f ); - - //Burn out time - pFlare->m_flTimeBurnOut = gpGlobals->curtime + lifetime; - - pFlare->RemoveSolidFlags( FSOLID_NOT_SOLID ); - pFlare->AddSolidFlags( FSOLID_NOT_STANDABLE ); - - pFlare->SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); - - pFlare->SetOwnerEntity( pOwner ); - pFlare->m_pOwner = pOwner; - - return pFlare; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -unsigned int CFlare::PhysicsSolidMaskForEntity( void ) const -{ - return MASK_NPCSOLID; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFlare::FlareThink( void ) -{ - float deltaTime = ( m_flTimeBurnOut - gpGlobals->curtime ); - - if ( !m_bInActiveList && ( ( deltaTime > FLARE_BLIND_TIME ) || ( m_flTimeBurnOut == -1.0f ) ) ) - { - AddToActiveFlares(); - } - - if ( m_flTimeBurnOut != -1.0f ) - { - //Fading away - if ( ( deltaTime <= FLARE_DECAY_TIME ) && ( m_bFading == false ) ) - { - m_bFading = true; - CSoundEnvelopeController::GetController().SoundChangePitch( m_pBurnSound, 60, deltaTime ); - CSoundEnvelopeController::GetController().SoundFadeOut( m_pBurnSound, deltaTime ); - } - - // if flare is no longer bright, remove it from active flare list - if ( m_bInActiveList && ( deltaTime <= FLARE_BLIND_TIME ) ) - { - RemoveFromActiveFlares(); - } - - //Burned out - if ( m_flTimeBurnOut < gpGlobals->curtime ) - { - UTIL_Remove( this ); - return; - } - } - - //Act differently underwater - if ( GetWaterLevel() > 1 ) - { - UTIL_Bubbles( GetAbsOrigin() + Vector( -2, -2, -2 ), GetAbsOrigin() + Vector( 2, 2, 2 ), 1 ); - m_bSmoke = false; - } - else - { - //Shoot sparks - if ( random->RandomInt( 0, 8 ) == 1 ) - { - g_pEffects->Sparks( GetAbsOrigin() ); - } - } - - //Next update - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOther - -//----------------------------------------------------------------------------- -void CFlare::FlareBurnTouch( CBaseEntity *pOther ) -{ - if ( pOther && pOther->m_takedamage && ( m_flNextDamage < gpGlobals->curtime ) ) - { - pOther->TakeDamage( CTakeDamageInfo( this, m_pOwner, 1, (DMG_BULLET|DMG_BURN) ) ); - m_flNextDamage = gpGlobals->curtime + 1.0f; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOther - -//----------------------------------------------------------------------------- -void CFlare::FlareTouch( CBaseEntity *pOther ) -{ - Assert( pOther ); - if ( !pOther->IsSolid() ) - return; - - if ( ( m_nBounces < 10 ) && ( GetWaterLevel() < 1 ) ) - { - // Throw some real chunks here - g_pEffects->Sparks( GetAbsOrigin() ); - } - - //If the flare hit a person or NPC, do damage here. - if ( pOther && pOther->m_takedamage ) - { - /* - The Flare is the iRifle round right now. No damage, just ignite. (sjb) - - //Damage is a function of how fast the flare is flying. - int iDamage = GetAbsVelocity().Length() / 50.0f; - - if ( iDamage < 5 ) - { - //Clamp minimum damage - iDamage = 5; - } - - //Use m_pOwner, not GetOwnerEntity() - pOther->TakeDamage( CTakeDamageInfo( this, m_pOwner, iDamage, (DMG_BULLET|DMG_BURN) ) ); - m_flNextDamage = gpGlobals->curtime + 1.0f; - */ - - CBaseAnimating *pAnim; - - pAnim = dynamic_cast(pOther); - if( pAnim ) - { - pAnim->Ignite( 30.0f ); - } - - Vector vecNewVelocity = GetAbsVelocity(); - vecNewVelocity *= 0.1f; - SetAbsVelocity( vecNewVelocity ); - - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); - SetGravity(1.0f); - - - Die( 0.5 ); - - return; - } - else - { - // hit the world, check the material type here, see if the flare should stick. - trace_t tr; - tr = CBaseEntity::GetTouchTrace(); - - //Only do this on the first bounce - if ( m_nBounces == 0 ) - { - const surfacedata_t *pdata = physprops->GetSurfaceData( tr.surface.surfaceProps ); - - if ( pdata != NULL ) - { - //Only embed into concrete and wood (jdw: too obscure for players?) - //if ( ( pdata->gameMaterial == 'C' ) || ( pdata->gameMaterial == 'W' ) ) - { - Vector impactDir = ( tr.endpos - tr.startpos ); - VectorNormalize( impactDir ); - - float surfDot = tr.plane.normal.Dot( impactDir ); - - //Do not stick to ceilings or on shallow impacts - if ( ( tr.plane.normal.z > -0.5f ) && ( surfDot < -0.9f ) ) - { - RemoveSolidFlags( FSOLID_NOT_SOLID ); - AddSolidFlags( FSOLID_TRIGGER ); - UTIL_SetOrigin( this, tr.endpos + ( tr.plane.normal * 2.0f ) ); - SetAbsVelocity( vec3_origin ); - SetMoveType( MOVETYPE_NONE ); - - SetTouch( &CFlare::FlareBurnTouch ); - - int index = decalsystem->GetDecalIndexForName( "SmallScorch" ); - if ( index >= 0 ) - { - CBroadcastRecipientFilter filter; - te->Decal( filter, 0.0, &tr.endpos, &tr.startpos, ENTINDEX( tr.m_pEnt ), tr.hitbox, index ); - } - - CPASAttenuationFilter filter2( this, "Flare.Touch" ); - EmitSound( filter2, entindex(), "Flare.Touch" ); - - return; - } - } - } - } - - //Scorch decal - if ( GetAbsVelocity().LengthSqr() > (250*250) ) - { - int index = decalsystem->GetDecalIndexForName( "FadingScorch" ); - if ( index >= 0 ) - { - CBroadcastRecipientFilter filter; - te->Decal( filter, 0.0, &tr.endpos, &tr.startpos, ENTINDEX( tr.m_pEnt ), tr.hitbox, index ); - } - } - - // Change our flight characteristics - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); - SetGravity( UTIL_ScaleForGravity( 640 ) ); - - m_nBounces++; - - //After the first bounce, smacking into whoever fired the flare is fair game - SetOwnerEntity( this ); - - // Slow down - Vector vecNewVelocity = GetAbsVelocity(); - vecNewVelocity.x *= 0.8f; - vecNewVelocity.y *= 0.8f; - SetAbsVelocity( vecNewVelocity ); - - //Stopped? - if ( GetAbsVelocity().Length() < 64.0f ) - { - SetAbsVelocity( vec3_origin ); - SetMoveType( MOVETYPE_NONE ); - RemoveSolidFlags( FSOLID_NOT_SOLID ); - AddSolidFlags( FSOLID_TRIGGER ); - SetTouch( &CFlare::FlareBurnTouch ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFlare::Start( float lifeTime ) -{ - StartBurnSound(); - - if ( m_pBurnSound != NULL ) - { - CSoundEnvelopeController::GetController().Play( m_pBurnSound, 0.0f, 60 ); - CSoundEnvelopeController::GetController().SoundChangeVolume( m_pBurnSound, 0.8f, 2.0f ); - CSoundEnvelopeController::GetController().SoundChangePitch( m_pBurnSound, 100, 2.0f ); - } - - if ( lifeTime > 0 ) - { - m_flTimeBurnOut = gpGlobals->curtime + lifeTime; - } - else - { - m_flTimeBurnOut = -1.0f; - } - - RemoveEffects( EF_NODRAW ); - - SetThink( &CFlare::FlareThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFlare::Die( float fadeTime ) -{ - m_flTimeBurnOut = gpGlobals->curtime + fadeTime; - - SetThink( &CFlare::FlareThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFlare::Launch( const Vector &direction, float speed ) -{ - // Make sure we're visible - if ( m_spawnflags & SF_FLARE_INFINITE ) - { - Start( -1 ); - } - else - { - Start( 8.0f ); - } - - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); - - // Punch our velocity towards our facing - SetAbsVelocity( direction * speed ); - - SetGravity( 1.0f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CFlare::InputStart( inputdata_t &inputdata ) -{ - Start( inputdata.value.Float() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CFlare::InputDie( inputdata_t &inputdata ) -{ - Die( inputdata.value.Float() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CFlare::InputLaunch( inputdata_t &inputdata ) -{ - Vector direction; - AngleVectors( GetAbsAngles(), &direction ); - - float speed = inputdata.value.Float(); - - if ( speed == 0 ) - { - speed = FLARE_LAUNCH_SPEED; - } - - Launch( direction, speed ); -} - -//----------------------------------------------------------------------------- -// Purpose: Removes flare from active flare list -//----------------------------------------------------------------------------- -void CFlare::RemoveFromActiveFlares( void ) -{ - CFlare *pFlare; - CFlare *pPrevFlare; - - if ( !m_bInActiveList ) - return; - - pPrevFlare = NULL; - for( pFlare = CFlare::activeFlares; pFlare != NULL; pFlare = pFlare->m_pNextFlare ) - { - if ( pFlare == this ) - { - if ( pPrevFlare ) - { - pPrevFlare->m_pNextFlare = m_pNextFlare; - } - else - { - activeFlares = m_pNextFlare; - } - break; - } - pPrevFlare = pFlare; - } - - m_pNextFlare = NULL; - m_bInActiveList = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Adds flare to active flare list -//----------------------------------------------------------------------------- -void CFlare::AddToActiveFlares( void ) -{ - if ( !m_bInActiveList ) - { - m_pNextFlare = CFlare::activeFlares; - CFlare::activeFlares = this; - m_bInActiveList = true; - } -} - -#if 0 - -IMPLEMENT_SERVERCLASS_ST(CFlaregun, DT_Flaregun) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_flaregun, CFlaregun ); -PRECACHE_WEAPON_REGISTER( weapon_flaregun ); - -//----------------------------------------------------------------------------- -// Purpose: Precache -//----------------------------------------------------------------------------- -void CFlaregun::Precache( void ) -{ - BaseClass::Precache(); - - PrecacheScriptSound( "Flare.Touch" ); - - PrecacheScriptSound( "Weapon_FlareGun.Burn" ); - - UTIL_PrecacheOther( "env_flare" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Main attack -//----------------------------------------------------------------------------- -void CFlaregun::PrimaryAttack( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - if ( m_iClip1 <= 0 ) - { - SendWeaponAnim( ACT_VM_DRYFIRE ); - pOwner->m_flNextAttack = gpGlobals->curtime + SequenceDuration(); - return; - } - - m_iClip1 = m_iClip1 - 1; - - SendWeaponAnim( ACT_VM_PRIMARYATTACK ); - pOwner->m_flNextAttack = gpGlobals->curtime + 1; - - CFlare *pFlare = CFlare::Create( pOwner->Weapon_ShootPosition(), pOwner->EyeAngles(), pOwner, FLARE_DURATION ); - - if ( pFlare == NULL ) - return; - - Vector forward; - pOwner->EyeVectors( &forward ); - - pFlare->SetAbsVelocity( forward * 1500 ); - - WeaponSound( SINGLE ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFlaregun::SecondaryAttack( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - if ( m_iClip1 <= 0 ) - { - SendWeaponAnim( ACT_VM_DRYFIRE ); - pOwner->m_flNextAttack = gpGlobals->curtime + SequenceDuration(); - return; - } - - m_iClip1 = m_iClip1 - 1; - - SendWeaponAnim( ACT_VM_PRIMARYATTACK ); - pOwner->m_flNextAttack = gpGlobals->curtime + 1; - - CFlare *pFlare = CFlare::Create( pOwner->Weapon_ShootPosition(), pOwner->EyeAngles(), pOwner, FLARE_DURATION ); - - if ( pFlare == NULL ) - return; - - Vector forward; - pOwner->EyeVectors( &forward ); - - pFlare->SetAbsVelocity( forward * 500 ); - pFlare->SetGravity(1.0f); - pFlare->SetFriction( 0.85f ); - pFlare->SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); - - WeaponSound( SINGLE ); -} - -#endif diff --git a/game/server/hl2/weapon_flaregun.h b/game/server/hl2/weapon_flaregun.h deleted file mode 100644 index 412ce889f..000000000 --- a/game/server/hl2/weapon_flaregun.h +++ /dev/null @@ -1,106 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "basehlcombatweapon.h" -#include "soundenvelope.h" - -#ifndef WEAPON_FLAREGUN_H -#define WEAPON_FLAREGUN_H -#ifdef _WIN32 -#pragma once -#endif - -#define SF_FLARE_NO_DLIGHT 0x00000001 -#define SF_FLARE_NO_SMOKE 0x00000002 -#define SF_FLARE_INFINITE 0x00000004 -#define SF_FLARE_START_OFF 0x00000008 - -#define FLARE_DURATION 30.0f -#define FLARE_DECAY_TIME 10.0f -#define FLARE_BLIND_TIME 6.0f - -//--------------------- -// Flare -//--------------------- - -class CFlare : public CBaseCombatCharacter -{ -public: - DECLARE_CLASS( CFlare, CBaseCombatCharacter ); - - CFlare(); - ~CFlare(); - - static CFlare * GetActiveFlares( void ); - CFlare * GetNextFlare( void ) const { return m_pNextFlare; } - - static CFlare *Create( Vector vecOrigin, QAngle vecAngles, CBaseEntity *pOwner, float lifetime ); - - virtual unsigned int PhysicsSolidMaskForEntity( void ) const; - - void Spawn( void ); - void Precache( void ); - int Restore( IRestore &restore ); - void Activate( void ); - - void StartBurnSound( void ); - - void Start( float lifeTime ); - void Die( float fadeTime ); - void Launch( const Vector &direction, float speed ); - - Class_T Classify( void ); - - void FlareTouch( CBaseEntity *pOther ); - void FlareBurnTouch( CBaseEntity *pOther ); - void FlareThink( void ); - - void InputStart( inputdata_t &inputdata ); - void InputDie( inputdata_t &inputdata ); - void InputLaunch( inputdata_t &inputdata ); - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - static CFlare *activeFlares; - - CBaseEntity *m_pOwner; - int m_nBounces; // how many times has this flare bounced? - CNetworkVar( float, m_flTimeBurnOut ); // when will the flare burn out? - CNetworkVar( float, m_flScale ); - float m_flDuration; - float m_flNextDamage; - - CSoundPatch *m_pBurnSound; - bool m_bFading; - CNetworkVar( bool, m_bLight ); - CNetworkVar( bool, m_bSmoke ); - CNetworkVar( bool, m_bPropFlare ); - - bool m_bInActiveList; - CFlare * m_pNextFlare; - - void RemoveFromActiveFlares( void ); - void AddToActiveFlares( void ); -}; - -//--------------------- -// Flaregun -//--------------------- -class CFlaregun:public CBaseHLCombatWeapon -{ -public: - DECLARE_CLASS( CFlaregun, CBaseHLCombatWeapon ); - - DECLARE_SERVERCLASS(); - - void Precache( void ); - void PrimaryAttack( void ); - void SecondaryAttack( void ); -}; - -#endif // WEAPON_FLAREGUN_H - diff --git a/game/server/hl2/weapon_frag.cpp b/game/server/hl2/weapon_frag.cpp deleted file mode 100644 index 0e2e48c44..000000000 --- a/game/server/hl2/weapon_frag.cpp +++ /dev/null @@ -1,480 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "basehlcombatweapon.h" -#include "player.h" -#include "gamerules.h" -#include "grenade_frag.h" -#include "npcevent.h" -#include "engine/IEngineSound.h" -#include "items.h" -#include "in_buttons.h" -#include "soundent.h" -#include "GameStats.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define GRENADE_TIMER 3.0f //Seconds - -#define GRENADE_PAUSED_NO 0 -#define GRENADE_PAUSED_PRIMARY 1 -#define GRENADE_PAUSED_SECONDARY 2 - -#define GRENADE_RADIUS 4.0f // inches - -//----------------------------------------------------------------------------- -// Fragmentation grenades -//----------------------------------------------------------------------------- -class CWeaponFrag: public CBaseHLCombatWeapon -{ - DECLARE_CLASS( CWeaponFrag, CBaseHLCombatWeapon ); -public: - DECLARE_SERVERCLASS(); - -public: - CWeaponFrag(); - - void Precache( void ); - void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); - void PrimaryAttack( void ); - void SecondaryAttack( void ); - void DecrementAmmo( CBaseCombatCharacter *pOwner ); - void ItemPostFrame( void ); - - bool Deploy( void ); - bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); - - int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } - - bool Reload( void ); - - bool ShouldDisplayHUDHint() { return true; } - -private: - void ThrowGrenade( CBasePlayer *pPlayer ); - void RollGrenade( CBasePlayer *pPlayer ); - void LobGrenade( CBasePlayer *pPlayer ); - // check a throw from vecSrc. If not valid, move the position back along the line to vecEye - void CheckThrowPosition( CBasePlayer *pPlayer, const Vector &vecEye, Vector &vecSrc ); - - bool m_bRedraw; //Draw the weapon again after throwing a grenade - - int m_AttackPaused; - bool m_fDrawbackFinished; - - DECLARE_ACTTABLE(); - - DECLARE_DATADESC(); -}; - - -BEGIN_DATADESC( CWeaponFrag ) - DEFINE_FIELD( m_bRedraw, FIELD_BOOLEAN ), - DEFINE_FIELD( m_AttackPaused, FIELD_INTEGER ), - DEFINE_FIELD( m_fDrawbackFinished, FIELD_BOOLEAN ), -END_DATADESC() - -acttable_t CWeaponFrag::m_acttable[] = -{ - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SLAM, true }, -}; - -IMPLEMENT_ACTTABLE(CWeaponFrag); - -IMPLEMENT_SERVERCLASS_ST(CWeaponFrag, DT_WeaponFrag) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_frag, CWeaponFrag ); -PRECACHE_WEAPON_REGISTER(weapon_frag); - - - -CWeaponFrag::CWeaponFrag() : - CBaseHLCombatWeapon(), - m_bRedraw( false ) -{ - -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponFrag::Precache( void ) -{ - BaseClass::Precache(); - - UTIL_PrecacheOther( "npc_grenade_frag" ); - - PrecacheScriptSound( "WeaponFrag.Throw" ); - PrecacheScriptSound( "WeaponFrag.Roll" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CWeaponFrag::Deploy( void ) -{ - m_bRedraw = false; - m_fDrawbackFinished = false; - - return BaseClass::Deploy(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponFrag::Holster( CBaseCombatWeapon *pSwitchingTo ) -{ - m_bRedraw = false; - m_fDrawbackFinished = false; - - return BaseClass::Holster( pSwitchingTo ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEvent - -// *pOperator - -//----------------------------------------------------------------------------- -void CWeaponFrag::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - bool fThrewGrenade = false; - - switch( pEvent->event ) - { - case EVENT_WEAPON_SEQUENCE_FINISHED: - m_fDrawbackFinished = true; - break; - - case EVENT_WEAPON_THROW: - ThrowGrenade( pOwner ); - DecrementAmmo( pOwner ); - fThrewGrenade = true; - break; - - case EVENT_WEAPON_THROW2: - RollGrenade( pOwner ); - DecrementAmmo( pOwner ); - fThrewGrenade = true; - break; - - case EVENT_WEAPON_THROW3: - LobGrenade( pOwner ); - DecrementAmmo( pOwner ); - fThrewGrenade = true; - break; - - default: - BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); - break; - } - -#define RETHROW_DELAY 0.5 - if( fThrewGrenade ) - { - m_flNextPrimaryAttack = gpGlobals->curtime + RETHROW_DELAY; - m_flNextSecondaryAttack = gpGlobals->curtime + RETHROW_DELAY; - m_flTimeWeaponIdle = FLT_MAX; //NOTE: This is set once the animation has finished up! - - // Make a sound designed to scare snipers back into their holes! - CBaseCombatCharacter *pOwner = GetOwner(); - - if( pOwner ) - { - Vector vecSrc = pOwner->Weapon_ShootPosition(); - Vector vecDir; - - AngleVectors( pOwner->EyeAngles(), &vecDir ); - - trace_t tr; - - UTIL_TraceLine( vecSrc, vecSrc + vecDir * 1024, MASK_SOLID_BRUSHONLY, pOwner, COLLISION_GROUP_NONE, &tr ); - - CSoundEnt::InsertSound( SOUND_DANGER_SNIPERONLY, tr.endpos, 384, 0.2, pOwner ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponFrag::Reload( void ) -{ - if ( !HasPrimaryAmmo() ) - return false; - - if ( ( m_bRedraw ) && ( m_flNextPrimaryAttack <= gpGlobals->curtime ) && ( m_flNextSecondaryAttack <= gpGlobals->curtime ) ) - { - //Redraw the weapon - SendWeaponAnim( ACT_VM_DRAW ); - - //Update our times - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration(); - m_flTimeWeaponIdle = gpGlobals->curtime + SequenceDuration(); - - //Mark this as done - m_bRedraw = false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponFrag::SecondaryAttack( void ) -{ - if ( m_bRedraw ) - return; - - if ( !HasPrimaryAmmo() ) - return; - - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( pOwner ); - - if ( pPlayer == NULL ) - return; - - // Note that this is a secondary attack and prepare the grenade attack to pause. - m_AttackPaused = GRENADE_PAUSED_SECONDARY; - SendWeaponAnim( ACT_VM_PULLBACK_LOW ); - - // Don't let weapon idle interfere in the middle of a throw! - m_flTimeWeaponIdle = FLT_MAX; - m_flNextSecondaryAttack = FLT_MAX; - - // If I'm now out of ammo, switch away - if ( !HasPrimaryAmmo() ) - { - pPlayer->SwitchToNextBestWeapon( this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponFrag::PrimaryAttack( void ) -{ - if ( m_bRedraw ) - return; - - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - { - return; - } - - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );; - - if ( !pPlayer ) - return; - - // Note that this is a primary attack and prepare the grenade attack to pause. - m_AttackPaused = GRENADE_PAUSED_PRIMARY; - SendWeaponAnim( ACT_VM_PULLBACK_HIGH ); - - // Put both of these off indefinitely. We do not know how long - // the player will hold the grenade. - m_flTimeWeaponIdle = FLT_MAX; - m_flNextPrimaryAttack = FLT_MAX; - - // If I'm now out of ammo, switch away - if ( !HasPrimaryAmmo() ) - { - pPlayer->SwitchToNextBestWeapon( this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOwner - -//----------------------------------------------------------------------------- -void CWeaponFrag::DecrementAmmo( CBaseCombatCharacter *pOwner ) -{ - pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponFrag::ItemPostFrame( void ) -{ - if( m_fDrawbackFinished ) - { - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if (pOwner) - { - switch( m_AttackPaused ) - { - case GRENADE_PAUSED_PRIMARY: - if( !(pOwner->m_nButtons & IN_ATTACK) ) - { - SendWeaponAnim( ACT_VM_THROW ); - m_fDrawbackFinished = false; - } - break; - - case GRENADE_PAUSED_SECONDARY: - if( !(pOwner->m_nButtons & IN_ATTACK2) ) - { - //See if we're ducking - if ( pOwner->m_nButtons & IN_DUCK ) - { - //Send the weapon animation - SendWeaponAnim( ACT_VM_SECONDARYATTACK ); - } - else - { - //Send the weapon animation - SendWeaponAnim( ACT_VM_HAULBACK ); - } - - m_fDrawbackFinished = false; - } - break; - - default: - break; - } - } - } - - BaseClass::ItemPostFrame(); - - if ( m_bRedraw ) - { - if ( IsViewModelSequenceFinished() ) - { - Reload(); - } - } -} - - // check a throw from vecSrc. If not valid, move the position back along the line to vecEye -void CWeaponFrag::CheckThrowPosition( CBasePlayer *pPlayer, const Vector &vecEye, Vector &vecSrc ) -{ - trace_t tr; - - UTIL_TraceHull( vecEye, vecSrc, -Vector(GRENADE_RADIUS+2,GRENADE_RADIUS+2,GRENADE_RADIUS+2), Vector(GRENADE_RADIUS+2,GRENADE_RADIUS+2,GRENADE_RADIUS+2), - pPlayer->PhysicsSolidMaskForEntity(), pPlayer, pPlayer->GetCollisionGroup(), &tr ); - - if ( tr.DidHit() ) - { - vecSrc = tr.endpos; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -//----------------------------------------------------------------------------- -void CWeaponFrag::ThrowGrenade( CBasePlayer *pPlayer ) -{ - Vector vecEye = pPlayer->EyePosition(); - Vector vForward, vRight; - - pPlayer->EyeVectors( &vForward, &vRight, NULL ); - Vector vecSrc = vecEye + vForward * 18.0f + vRight * 8.0f; - CheckThrowPosition( pPlayer, vecEye, vecSrc ); -// vForward[0] += 0.1f; - vForward[2] += 0.1f; - - Vector vecThrow; - pPlayer->GetVelocity( &vecThrow, NULL ); - vecThrow += vForward * 1200; - Fraggrenade_Create( vecSrc, vec3_angle, vecThrow, AngularImpulse(600,random->RandomInt(-1200,1200),0), pPlayer, GRENADE_TIMER, false ); - - m_bRedraw = true; - - WeaponSound( SINGLE ); - - m_iPrimaryAttacks++; - gamestats->Event_WeaponFired( pPlayer, true, GetClassname() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -//----------------------------------------------------------------------------- -void CWeaponFrag::LobGrenade( CBasePlayer *pPlayer ) -{ - Vector vecEye = pPlayer->EyePosition(); - Vector vForward, vRight; - - pPlayer->EyeVectors( &vForward, &vRight, NULL ); - Vector vecSrc = vecEye + vForward * 18.0f + vRight * 8.0f + Vector( 0, 0, -8 ); - CheckThrowPosition( pPlayer, vecEye, vecSrc ); - - Vector vecThrow; - pPlayer->GetVelocity( &vecThrow, NULL ); - vecThrow += vForward * 350 + Vector( 0, 0, 50 ); - Fraggrenade_Create( vecSrc, vec3_angle, vecThrow, AngularImpulse(200,random->RandomInt(-600,600),0), pPlayer, GRENADE_TIMER, false ); - - WeaponSound( WPN_DOUBLE ); - - m_bRedraw = true; - - m_iPrimaryAttacks++; - gamestats->Event_WeaponFired( pPlayer, true, GetClassname() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -//----------------------------------------------------------------------------- -void CWeaponFrag::RollGrenade( CBasePlayer *pPlayer ) -{ - // BUGBUG: Hardcoded grenade width of 4 - better not change the model :) - Vector vecSrc; - pPlayer->CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 0.0f ), &vecSrc ); - vecSrc.z += GRENADE_RADIUS; - - Vector vecFacing = pPlayer->BodyDirection2D( ); - // no up/down direction - vecFacing.z = 0; - VectorNormalize( vecFacing ); - trace_t tr; - UTIL_TraceLine( vecSrc, vecSrc - Vector(0,0,16), MASK_PLAYERSOLID, pPlayer, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction != 1.0 ) - { - // compute forward vec parallel to floor plane and roll grenade along that - Vector tangent; - CrossProduct( vecFacing, tr.plane.normal, tangent ); - CrossProduct( tr.plane.normal, tangent, vecFacing ); - } - vecSrc += (vecFacing * 18.0); - CheckThrowPosition( pPlayer, pPlayer->WorldSpaceCenter(), vecSrc ); - - Vector vecThrow; - pPlayer->GetVelocity( &vecThrow, NULL ); - vecThrow += vecFacing * 700; - // put it on its side - QAngle orientation(0,pPlayer->GetLocalAngles().y,-90); - // roll it - AngularImpulse rotSpeed(0,0,720); - Fraggrenade_Create( vecSrc, orientation, vecThrow, rotSpeed, pPlayer, GRENADE_TIMER, false ); - - WeaponSound( SPECIAL1 ); - - m_bRedraw = true; - - m_iPrimaryAttacks++; - gamestats->Event_WeaponFired( pPlayer, true, GetClassname() ); -} - diff --git a/game/server/hl2/weapon_gauss.h b/game/server/hl2/weapon_gauss.h deleted file mode 100644 index 4f8472868..000000000 --- a/game/server/hl2/weapon_gauss.h +++ /dev/null @@ -1,25 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "basehlcombatweapon.h" - -#ifndef WEAPON_GAUSS_H -#define WEAPON_GAUSS_H -#ifdef _WIN32 -#pragma once -#endif - - -#define GAUSS_BEAM_SPRITE "sprites/laserbeam.vmt" - -#define GAUSS_CHARGE_TIME 0.2f -#define MAX_GAUSS_CHARGE 16 -#define MAX_GAUSS_CHARGE_TIME 3 -#define DANGER_GAUSS_CHARGE_TIME 10 -#define GAUSS_NUM_BEAMS 4 - - -#endif // WEAPON_GAUSS_H diff --git a/game/server/hl2/weapon_immolator.cpp b/game/server/hl2/weapon_immolator.cpp deleted file mode 100644 index 54019c77d..000000000 --- a/game/server/hl2/weapon_immolator.cpp +++ /dev/null @@ -1,373 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "basehlcombatweapon.h" -#include "basecombatcharacter.h" -#include "player.h" -#include "soundent.h" -#include "te_particlesystem.h" -#include "ndebugoverlay.h" -#include "in_buttons.h" -#include "ai_basenpc.h" -#include "ai_memory.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define MAX_BURN_RADIUS 256 -#define RADIUS_GROW_RATE 50.0 // units/sec - -#define IMMOLATOR_TARGET_INVALID Vector( FLT_MAX, FLT_MAX, FLT_MAX ) - -class CWeaponImmolator : public CBaseHLCombatWeapon -{ -public: - DECLARE_CLASS( CWeaponImmolator, CBaseHLCombatWeapon ); - - DECLARE_SERVERCLASS(); - - CWeaponImmolator( void ); - - void Precache( void ); - void PrimaryAttack( void ); - void ItemPostFrame( void ); - - int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } - - void ImmolationDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore ); - virtual bool WeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions ); - virtual int WeaponRangeAttack1Condition( float flDot, float flDist ); - - void Update(); - void UpdateThink(); - - void StartImmolating(); - void StopImmolating(); - bool IsImmolating() { return m_flBurnRadius != 0.0; } - - DECLARE_ACTTABLE(); - DECLARE_DATADESC(); - - int m_beamIndex; - - float m_flBurnRadius; - float m_flTimeLastUpdatedRadius; - - Vector m_vecImmolatorTarget; -}; - -IMPLEMENT_SERVERCLASS_ST(CWeaponImmolator, DT_WeaponImmolator) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( info_target_immolator, CPointEntity ); -LINK_ENTITY_TO_CLASS( weapon_immolator, CWeaponImmolator ); -PRECACHE_WEAPON_REGISTER( weapon_immolator ); - -BEGIN_DATADESC( CWeaponImmolator ) - - DEFINE_FIELD( m_beamIndex, FIELD_INTEGER ), - DEFINE_FIELD( m_flBurnRadius, FIELD_FLOAT ), - DEFINE_FIELD( m_flTimeLastUpdatedRadius, FIELD_TIME ), - DEFINE_FIELD( m_vecImmolatorTarget, FIELD_VECTOR ), - - DEFINE_ENTITYFUNC( UpdateThink ), -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Maps base activities to weapons-specific ones so our characters do the right things. -//----------------------------------------------------------------------------- -acttable_t CWeaponImmolator::m_acttable[] = -{ - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SNIPER_RIFLE, true } -}; - -IMPLEMENT_ACTTABLE( CWeaponImmolator ); - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CWeaponImmolator::CWeaponImmolator( void ) -{ - m_fMaxRange1 = 4096; - StopImmolating(); -} - -void CWeaponImmolator::StartImmolating() -{ - // Start the radius really tiny because we use radius == 0.0 to - // determine whether the immolator is operating or not. - m_flBurnRadius = 0.1; - m_flTimeLastUpdatedRadius = gpGlobals->curtime; - SetThink( &CWeaponImmolator::UpdateThink ); - SetNextThink( gpGlobals->curtime ); - - CSoundEnt::InsertSound( SOUND_DANGER, m_vecImmolatorTarget, 256, 5.0, GetOwner() ); -} - -void CWeaponImmolator::StopImmolating() -{ - m_flBurnRadius = 0.0; - SetThink( NULL ); - m_vecImmolatorTarget= IMMOLATOR_TARGET_INVALID; - m_flNextPrimaryAttack = gpGlobals->curtime + 5.0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponImmolator::Precache( void ) -{ - m_beamIndex = PrecacheModel( "sprites/bluelaser1.vmt" ); - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponImmolator::PrimaryAttack( void ) -{ - WeaponSound( SINGLE ); - - if( !IsImmolating() ) - { - StartImmolating(); - } -} - -//----------------------------------------------------------------------------- -// This weapon is said to have Line of Sight when it CAN'T see the target, but -// can see a place near the target than can. -//----------------------------------------------------------------------------- -bool CWeaponImmolator::WeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions ) -{ - CAI_BaseNPC* npcOwner = GetOwner()->MyNPCPointer(); - - if( !npcOwner ) - { - return false; - } - - if( IsImmolating() ) - { - // Don't update while Immolating. This is a committed attack. - return false; - } - - // Assume we won't find a target. - m_vecImmolatorTarget = targetPos; - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Weapon firing conditions -//----------------------------------------------------------------------------- -int CWeaponImmolator::WeaponRangeAttack1Condition( float flDot, float flDist ) -{ - if( m_flNextPrimaryAttack > gpGlobals->curtime ) - { - // Too soon to attack! - return COND_NONE; - } - - if( IsImmolating() ) - { - // Once is enough! - return COND_NONE; - } - - if( m_vecImmolatorTarget == IMMOLATOR_TARGET_INVALID ) - { - // No target! - return COND_NONE; - } - - if ( flDist > m_fMaxRange1 ) - { - return COND_TOO_FAR_TO_ATTACK; - } - else if ( flDot < 0.5f ) // UNDONE: Why check this here? Isn't the AI checking this already? - { - return COND_NOT_FACING_ATTACK; - } - - return COND_CAN_RANGE_ATTACK1; -} - -void CWeaponImmolator::UpdateThink( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - - if( pOwner && !pOwner->IsAlive() ) - { - StopImmolating(); - return; - } - - Update(); - SetNextThink( gpGlobals->curtime + 0.05 ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CWeaponImmolator::Update() -{ - float flDuration = gpGlobals->curtime - m_flTimeLastUpdatedRadius; - if( flDuration != 0.0 ) - { - m_flBurnRadius += RADIUS_GROW_RATE * flDuration; - } - - // Clamp - m_flBurnRadius = MIN( m_flBurnRadius, MAX_BURN_RADIUS ); - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - Vector vecSrc; - Vector vecAiming; - - if( pOwner ) - { - vecSrc = pOwner->Weapon_ShootPosition( ); - vecAiming = pOwner->GetAutoaimVector(AUTOAIM_2DEGREES); - } - else - { - CBaseCombatCharacter *pOwner = GetOwner(); - - vecSrc = pOwner->Weapon_ShootPosition( ); - vecAiming = m_vecImmolatorTarget - vecSrc; - VectorNormalize( vecAiming ); - } - - trace_t tr; - UTIL_TraceLine( vecSrc, vecSrc + vecAiming * MAX_TRACE_LENGTH, MASK_SHOT, pOwner, COLLISION_GROUP_NONE, &tr ); - - int brightness; - brightness = (int)(255 * (m_flBurnRadius / MAX_BURN_RADIUS)); - UTIL_Beam( vecSrc, - tr.endpos, - m_beamIndex, - 0, //halo index - 0, //frame start - 2, //framerate - 0.1f, //life - 20, // width - 1, // endwidth - 0, // fadelength, - 1, // noise - - 0, // red - 255, // green - 0, // blue, - - brightness, // bright - 100 // speed - ); - - - if( tr.DidHitWorld() ) - { - int beams; - - for( beams = 0 ; beams < 5 ; beams++ ) - { - Vector vecDest; - - // Random unit vector - vecDest.x = random->RandomFloat( -1, 1 ); - vecDest.y = random->RandomFloat( -1, 1 ); - vecDest.z = random->RandomFloat( 0, 1 ); - - // Push out to radius dist. - vecDest = tr.endpos + vecDest * m_flBurnRadius; - - UTIL_Beam( tr.endpos, - vecDest, - m_beamIndex, - 0, //halo index - 0, //frame start - 2, //framerate - 0.15f, //life - 20, // width - 1, // endwidth - 0, // fadelength, - 15, // noise - - 0, // red - 255, // green - 0, // blue, - - 128, // bright - 100 // speed - ); - } - - // Immolator starts to hurt a few seconds after the effect is seen - if( m_flBurnRadius > 64.0 ) - { - ImmolationDamage( CTakeDamageInfo( this, this, 1, DMG_BURN ), tr.endpos, m_flBurnRadius, CLASS_NONE ); - } - } - else - { - // The attack beam struck some kind of entity directly. - } - - m_flTimeLastUpdatedRadius = gpGlobals->curtime; - - if( m_flBurnRadius >= MAX_BURN_RADIUS ) - { - StopImmolating(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponImmolator::ItemPostFrame( void ) -{ - BaseClass::ItemPostFrame(); -} - - - -void CWeaponImmolator::ImmolationDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore ) -{ - CBaseEntity *pEntity = NULL; - trace_t tr; - Vector vecSpot; - - Vector vecSrc = vecSrcIn; - - // iterate on all entities in the vicinity. - for ( CEntitySphereQuery sphere( vecSrc, flRadius ); (pEntity = sphere.GetCurrentEntity()) != NULL; sphere.NextEntity() ) - { - CBaseCombatCharacter *pBCC; - - pBCC = pEntity->MyCombatCharacterPointer(); - - if ( pBCC && !pBCC->IsOnFire() ) - { - // UNDONE: this should check a damage mask, not an ignore - if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore ) - { - continue; - } - - if( pEntity == GetOwner() ) - { - continue; - } - - pBCC->Ignite( random->RandomFloat( 15, 20 ) ); - } - } -} diff --git a/game/server/hl2/weapon_irifle.cpp b/game/server/hl2/weapon_irifle.cpp deleted file mode 100644 index 39a793e5b..000000000 --- a/game/server/hl2/weapon_irifle.cpp +++ /dev/null @@ -1,132 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -//========= Copyright 1996-2003, Valve LLC, All rights reserved. ============ -// -// Purpose: This is the incendiary rifle. -// -//============================================================================= - - -#include "cbase.h" -#include "npcevent.h" -#include "basehlcombatweapon.h" -#include "basecombatcharacter.h" -#include "soundent.h" -#include "player.h" -#include "IEffects.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "weapon_flaregun.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//########################################################################### -// >> CWeaponIRifle -//########################################################################### - -class CWeaponIRifle : public CBaseHLCombatWeapon -{ -public: - - CWeaponIRifle(); - - DECLARE_SERVERCLASS(); - DECLARE_CLASS( CWeaponIRifle, CBaseHLCombatWeapon ); - - void Precache( void ); - bool Deploy( void ); - - void PrimaryAttack( void ); - virtual float GetFireRate( void ) { return 1; }; - - int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } - - virtual const Vector& GetBulletSpread( void ) - { - static Vector cone = VECTOR_CONE_3DEGREES; - return cone; - } - - DECLARE_ACTTABLE(); -}; - -IMPLEMENT_SERVERCLASS_ST(CWeaponIRifle, DT_WeaponIRifle) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_irifle, CWeaponIRifle ); -PRECACHE_WEAPON_REGISTER(weapon_irifle); - -//--------------------------------------------------------- -// Activity table -//--------------------------------------------------------- -acttable_t CWeaponIRifle::m_acttable[] = -{ - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_ML, true }, -}; -IMPLEMENT_ACTTABLE(CWeaponIRifle); - -//--------------------------------------------------------- -// Constructor -//--------------------------------------------------------- -CWeaponIRifle::CWeaponIRifle() -{ - m_bReloadsSingly = true; - - m_fMinRange1 = 65; - m_fMinRange2 = 65; - m_fMaxRange1 = 200; - m_fMaxRange2 = 200; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CWeaponIRifle::Precache( void ) -{ - BaseClass::Precache(); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CWeaponIRifle::PrimaryAttack( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - m_iClip1 = m_iClip1 - 1; - - SendWeaponAnim( ACT_VM_PRIMARYATTACK ); - pOwner->m_flNextAttack = gpGlobals->curtime + 1; - - CFlare *pFlare = CFlare::Create( pOwner->Weapon_ShootPosition(), pOwner->EyeAngles(), pOwner, FLARE_DURATION ); - - if ( pFlare == NULL ) - return; - - Vector forward; - pOwner->EyeVectors( &forward ); - - pFlare->SetAbsVelocity( forward * 1500 ); - - WeaponSound( SINGLE ); -} - -//--------------------------------------------------------- -// BUGBUG - don't give ammo here. -//--------------------------------------------------------- -bool CWeaponIRifle::Deploy( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - if (pOwner) - { - pOwner->GiveAmmo( 90, m_iPrimaryAmmoType); - } - return BaseClass::Deploy(); -} diff --git a/game/server/hl2/weapon_manhack.cpp b/game/server/hl2/weapon_manhack.cpp deleted file mode 100644 index 8b1b89cbf..000000000 --- a/game/server/hl2/weapon_manhack.cpp +++ /dev/null @@ -1,104 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - - -#include "cbase.h" -#include "basehlcombatweapon.h" -#include "player.h" -#include "gamerules.h" -#include "ammodef.h" -#include "in_buttons.h" -#include "bone_setup.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CWeapon_Manhack : public CBaseHLCombatWeapon -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( CWeapon_Manhack, CBaseHLCombatWeapon ); - - DECLARE_SERVERCLASS(); - - void Spawn( void ); - void Precache( void ); - - void ItemPostFrame( void ); - void PrimaryAttack( void ); - void SecondaryAttack( void ); - - float m_flBladeYaw; -}; - -IMPLEMENT_SERVERCLASS_ST( CWeapon_Manhack, DT_Weapon_Manhack) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_manhack, CWeapon_Manhack ); -PRECACHE_WEAPON_REGISTER(weapon_manhack); - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CWeapon_Manhack ) - - DEFINE_FIELD( m_flBladeYaw, FIELD_FLOAT ), - -END_DATADESC() - -void CWeapon_Manhack::Spawn( ) -{ - // Call base class first - BaseClass::Spawn(); - - Precache( ); - SetModel( GetViewModel() ); - - FallInit();// get ready to fall down. - - m_flBladeYaw = 0.0f; - AddSolidFlags( FSOLID_NOT_SOLID ); -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CWeapon_Manhack::ItemPostFrame( void ) -{ - WeaponIdle( ); -} - -void CWeapon_Manhack::Precache( void ) -{ - BaseClass::Precache(); -} - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CWeapon_Manhack::PrimaryAttack() -{ -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CWeapon_Manhack::SecondaryAttack() -{ -} - - - diff --git a/game/server/hl2/weapon_molotov.cpp b/game/server/hl2/weapon_molotov.cpp deleted file mode 100644 index 162b655e3..000000000 --- a/game/server/hl2/weapon_molotov.cpp +++ /dev/null @@ -1,453 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: This is the molotov weapon -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" -#include "basehlcombatweapon.h" -#include "basecombatcharacter.h" -#include "ai_basenpc.h" -#include "ai_memory.h" -#include "player.h" -#include "gamerules.h" // For g_pGameRules -#include "weapon_molotov.h" -#include "grenade_molotov.h" -#include "in_buttons.h" -#include "game.h" -#include "vstdlib/random.h" -#include "movevars_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -BEGIN_DATADESC( CWeaponMolotov ) - - DEFINE_FIELD( m_nNumAmmoTypes, FIELD_INTEGER ), - DEFINE_FIELD( m_bNeedDraw, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iThrowBits, FIELD_INTEGER ), - DEFINE_FIELD( m_fNextThrowCheck, FIELD_TIME ), - DEFINE_FIELD( m_vecTossVelocity, FIELD_VECTOR ), - - // Function Pointers - DEFINE_FUNCTION( MolotovTouch ), - -END_DATADESC() - - -IMPLEMENT_SERVERCLASS_ST(CWeaponMolotov, DT_WeaponMolotov) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_molotov, CWeaponMolotov ); -PRECACHE_WEAPON_REGISTER(weapon_molotov); - -acttable_t CWeaponMolotov::m_acttable[] = -{ - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_THROW, true }, -}; -IMPLEMENT_ACTTABLE(CWeaponMolotov); - - -void CWeaponMolotov::Precache( void ) -{ - PrecacheModel("models/props_junk/w_garb_beerbottle.mdl"); //<> need real model - BaseClass::Precache(); -} - -void CWeaponMolotov::Spawn( void ) -{ - // Call base class first - BaseClass::Spawn(); - - m_bNeedDraw = true; - - SetModel( GetWorldModel() ); - UTIL_SetSize(this, Vector( -6, -6, -2), Vector(6, 6, 2)); -} - -//------------------------------------------------------------------------------ -// Purpose : Override to use molotovs pickup touch function -// Input : -// Output : -//------------------------------------------------------------------------------ -void CWeaponMolotov::SetPickupTouch( void ) -{ - SetTouch(&CWeaponMolotov::MolotovTouch); -} - -//----------------------------------------------------------------------------- -// Purpose: Override so give correct ammo -// Input : pOther - the entity that touched me -// Output : -//----------------------------------------------------------------------------- -void CWeaponMolotov::MolotovTouch( CBaseEntity *pOther ) -{ - // --------------------------------------------------- - // First give weapon to touching entity if allowed - // --------------------------------------------------- - BaseClass::DefaultTouch(pOther); - - // ---------------------------------------------------- - // Give molotov ammo if touching client - // ---------------------------------------------------- - if (pOther->GetFlags() & FL_CLIENT) - { - // ------------------------------------------------ - // If already owned weapon of this type remove me - // ------------------------------------------------ - CBaseCombatCharacter* pBCC = ToBaseCombatCharacter( pOther ); - CWeaponMolotov* oldWeapon = (CWeaponMolotov*)pBCC->Weapon_OwnsThisType( GetClassname() ); - if (oldWeapon != this) - { - UTIL_Remove( this ); - } - else - { - pBCC->GiveAmmo( 1, m_iSecondaryAmmoType ); - SetThink (NULL); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Gets event from anim stream and throws the object -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeaponMolotov::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - switch( pEvent->event ) - { - case EVENT_WEAPON_THROW: - { - CAI_BaseNPC *pNPC = GetOwner()->MyNPCPointer(); - if (!pNPC) - { - return; - } - - CBaseEntity *pEnemy = pNPC->GetEnemy(); - if (!pEnemy) - { - return; - } - - Vector vec_target = pNPC->GetEnemyLKP(); - - // ----------------------------------------------------- - // Get position of throw - // ----------------------------------------------------- - // If owner has a hand, set position to the hand bone position - Vector launchPos; - int iBIndex = pNPC->LookupBone("Bip01 R Hand"); - if (iBIndex != -1) - { - Vector origin; - QAngle angles; - pNPC->GetBonePosition( iBIndex, launchPos, angles); - } - // Otherwise just set to in front of the owner - else - { - Vector vFacingDir = pNPC->BodyDirection2D( ); - vFacingDir = vFacingDir * 60.0; - launchPos = pNPC->GetAbsOrigin()+vFacingDir; - } - - - //Vector vecVelocity = VecCheckToss( pNPC, launchPos, vec_target, 1.0 ); - - ThrowMolotov( launchPos, m_vecTossVelocity); - - // Drop the weapon and remove as no more ammo - pNPC->Weapon_Drop( this ); - UTIL_Remove( this ); - } - break; - default: - BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CWeaponMolotov::ObjectInWay( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - if (!pOwner) - { - return false; - } - - Vector vecSrc = pOwner->Weapon_ShootPosition( ); - Vector vecAiming = pOwner->BodyDirection2D( ); - - trace_t tr; - - Vector vecEnd = vecSrc + (vecAiming * 32); - UTIL_TraceLine( vecSrc, vecEnd, MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); - - if (tr.fraction < 1.0) - { - // Don't block on a living creature - if (tr.m_pEnt) - { - CBaseEntity *pEntity = tr.m_pEnt; - CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pEntity ); - if (pBCC) - { - return false; - } - } - return true; - } - else - { - return false; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Override to allow throw w/o LOS -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CWeaponMolotov::WeaponLOSCondition(const Vector &ownerPos, const Vector &targetPos,bool bSetConditions) -{ - // <> should test if can throw from present location here... - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Override to check throw -// Input : -// Output : -//----------------------------------------------------------------------------- -int CWeaponMolotov::WeaponRangeAttack1Condition( float flDot, float flDist ) -{ - // If things haven't changed too much since last time - // just return that previously calculated value - if (gpGlobals->curtime < m_fNextThrowCheck ) - { - return m_iThrowBits; - } - - if ( flDist < m_fMinRange1) { - m_iThrowBits = COND_TOO_CLOSE_TO_ATTACK; - } - else if (flDist > m_fMaxRange1) { - m_iThrowBits = COND_TOO_FAR_TO_ATTACK; - } - else if (flDot < 0.5) { - m_iThrowBits = COND_NOT_FACING_ATTACK; - } - - // If moving, can't throw. - else if ( m_flGroundSpeed != 0 ) - { - m_iThrowBits = COND_NONE; - } - else { - // Ok we should check again as some time has passed - // This function is only used by NPC's so we can cast to a Base Monster - CAI_BaseNPC *pNPC = GetOwner()->MyNPCPointer(); - CBaseEntity *pEnemy = pNPC->GetEnemy(); - - if (!pEnemy) - { - m_iThrowBits = COND_NONE; - } - // Get Enemy Position - Vector vecTarget; - pEnemy->CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 0.0f ), &vecTarget ); - - // Get Toss Vector - Vector throwStart = pNPC->Weapon_ShootPosition(); - Vector vecToss; - CBaseEntity* pBlocker = NULL; - float throwDist = (throwStart - vecTarget).Length(); - float fGravity = sv_gravity.GetFloat(); - float throwLimit = pNPC->ThrowLimit(throwStart, vecTarget, fGravity, 35, WorldAlignMins(), WorldAlignMaxs(), pEnemy, &vecToss, &pBlocker); - - // If I can make the throw (or most of the throw) - if (!throwLimit || (throwLimit != throwDist && throwLimit > 0.8*throwDist)) - { - m_vecTossVelocity = vecToss; - m_iThrowBits = COND_CAN_RANGE_ATTACK1; - - } - else - { - m_iThrowBits = COND_NONE; - } - - } - // don't check again for a while. - m_fNextThrowCheck = gpGlobals->curtime + 0.33; // 1/3 second. - - return m_iThrowBits; -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CWeaponMolotov::ThrowMolotov( const Vector &vecSrc, const Vector &vecVelocity) -{ - CGrenade_Molotov *pMolotov = (CGrenade_Molotov*)Create( "grenade_molotov", vecSrc, vec3_angle, GetOwner() ); - - if (!pMolotov) - { - Msg("Couldn't make molotov!\n"); - return; - } - pMolotov->SetAbsVelocity( vecVelocity ); - - // Tumble through the air - QAngle angVel( random->RandomFloat ( -100, -500 ), random->RandomFloat ( -100, -500 ), random->RandomFloat ( -100, -500 ) ); - pMolotov->SetLocalAngularVelocity( angVel ); - - pMolotov->SetThrower( GetOwner() ); - pMolotov->SetOwnerEntity( ((CBaseEntity*)GetOwner()) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CWeaponMolotov::PrimaryAttack( void ) -{ - - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if (!pPlayer) - { - return; - } - - Vector vecSrc = pPlayer->WorldSpaceCenter(); - Vector vecFacing = pPlayer->BodyDirection3D( ); - vecSrc = vecSrc + vecFacing * 18.0; - // BUGBUG: is this some hack because it's not at the eye position???? - vecSrc.z += 24.0f; - - // Player may have turned to face a wall during the throw anim in which case - // we don't want to throw the SLAM into the wall - if (ObjectInWay()) - { - vecSrc = pPlayer->WorldSpaceCenter() + vecFacing * 5.0; - } - - Vector vecAiming = pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES ); - vecAiming.z += 0.20; // Raise up so passes through reticle - - ThrowMolotov(vecSrc, vecAiming*800); - pPlayer->RemoveAmmo( 1, m_iSecondaryAmmoType ); - - - // Don't fire again until fire animation has completed - //m_flNextPrimaryAttack = gpGlobals->curtime + CurSequenceDuration(); - //<> - till real animation is avaible - m_flNextPrimaryAttack = gpGlobals->curtime + 1.0; - m_flNextSecondaryAttack = gpGlobals->curtime + 1.0; - - m_bNeedDraw = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CWeaponMolotov::SecondaryAttack( void ) -{ - //<> - // Hmmm... what should I do here? -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CWeaponMolotov::DrawAmmo( void ) -{ - // ------------------------------------------- - // Make sure I have ammo of the current type - // ------------------------------------------- - CBaseCombatCharacter *pOwner = GetOwner(); - if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) <=0) - { - pOwner->Weapon_Drop( this ); - UTIL_Remove(this); - return; - } - Msg("Drawing Molotov...\n"); - m_bNeedDraw = false; - - //<> - till real animation is avaible - m_flNextPrimaryAttack = gpGlobals->curtime + 2.0; - m_flNextSecondaryAttack = gpGlobals->curtime + 2.0; - -} - -//----------------------------------------------------------------------------- -// Purpose: Override so shotgun can do mulitple reloads in a row -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeaponMolotov::ItemPostFrame( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if (!pOwner) - { - return; - } - - - if ((pOwner->m_nButtons & IN_ATTACK2) && (m_flNextSecondaryAttack <= gpGlobals->curtime)) - { - SecondaryAttack(); - } - else if ((pOwner->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime)) - { - // Uses secondary ammo only - if (pOwner->GetAmmoCount(m_iSecondaryAmmoType)) - { - PrimaryAttack(); - } - } - else if (m_bNeedDraw) - { - DrawAmmo(); - } - else - { - WeaponIdle( ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -CWeaponMolotov::CWeaponMolotov( void ) -{ -#ifdef _DEBUG - m_vecTossVelocity.Init(); -#endif - - m_fMinRange1 = 200; - m_fMaxRange1 = 1000; -} diff --git a/game/server/hl2/weapon_molotov.h b/game/server/hl2/weapon_molotov.h deleted file mode 100644 index 154022ac3..000000000 --- a/game/server/hl2/weapon_molotov.h +++ /dev/null @@ -1,65 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Molotov weapon -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#include "basehlcombatweapon.h" - -#ifndef WEAPON_MOLOTOV_H -#define WEAPON_MOLOTOV_H - -class CGrenade_Molotov; - -class CWeaponMolotov : public CBaseHLCombatWeapon -{ -public: - DECLARE_CLASS( CWeaponMolotov, CBaseHLCombatWeapon ); - - DECLARE_SERVERCLASS(); - -private: - int m_nNumAmmoTypes; - bool m_bNeedDraw; - int m_iThrowBits; // Save the current throw bits state - float m_fNextThrowCheck; // When to check throw ability next - Vector m_vecTossVelocity; - -public: - - void Precache( void ); - void Spawn( void ); - - void DrawAmmo( void ); - - virtual int WeaponRangeAttack1Condition( float flDot, float flDist ); - virtual bool WeaponLOSCondition(const Vector &ownerPos, const Vector &targetPos, bool bSetConditions); - - void SetPickupTouch( void ); - void MolotovTouch( CBaseEntity *pOther ); // default weapon touch - - int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } - - bool ObjectInWay( void ); - - void ThrowMolotov( const Vector &vecSrc, const Vector &vecVelocity); - void ItemPostFrame( void ); - void PrimaryAttack( void ); - void SecondaryAttack( void ); - - void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); - - DECLARE_ACTTABLE(); - DECLARE_DATADESC(); - - CWeaponMolotov(void); -}; - -#endif //WEAPON_MOLOTOV_H diff --git a/game/server/hl2/weapon_physcannon.cpp b/game/server/hl2/weapon_physcannon.cpp deleted file mode 100644 index 9e81769e7..000000000 --- a/game/server/hl2/weapon_physcannon.cpp +++ /dev/null @@ -1,4564 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Physics cannon -// -//=============================================================================// - -#include "cbase.h" -#include "player.h" -#include "gamerules.h" -#include "soundenvelope.h" -#include "engine/IEngineSound.h" -#include "physics.h" -#include "in_buttons.h" -#include "soundent.h" -#include "IEffects.h" -#include "ndebugoverlay.h" -#include "shake.h" -#include "hl2_player.h" -#include "beam_shared.h" -#include "Sprite.h" -#include "util.h" -#include "weapon_physcannon.h" -#include "physics_saverestore.h" -#include "ai_basenpc.h" -#include "player_pickup.h" -#include "physics_prop_ragdoll.h" -#include "globalstate.h" -#include "props.h" -#include "movevars_shared.h" -#include "basehlcombatweapon.h" -#include "te_effect_dispatch.h" -#include "vphysics/friction.h" -#include "saverestore_utlvector.h" -#include "prop_combine_ball.h" -#include "physobj.h" -#include "hl2_gamerules.h" -#include "citadel_effects_shared.h" -#include "eventqueue.h" -#include "model_types.h" -#include "ai_interactions.h" -#include "rumble_shared.h" -#include "GameStats.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -static const char *s_pWaitForUpgradeContext = "WaitForUpgrade"; - -ConVar g_debug_physcannon( "g_debug_physcannon", "0" ); - -ConVar physcannon_minforce( "physcannon_minforce", "700" ); -ConVar physcannon_maxforce( "physcannon_maxforce", "1500" ); -ConVar physcannon_maxmass( "physcannon_maxmass", "250" ); -ConVar physcannon_tracelength( "physcannon_tracelength", "250" ); -ConVar physcannon_mega_tracelength( "physcannon_mega_tracelength", "850" ); -ConVar physcannon_chargetime("physcannon_chargetime", "2" ); -ConVar physcannon_pullforce( "physcannon_pullforce", "4000" ); -ConVar physcannon_mega_pullforce( "physcannon_mega_pullforce", "8000" ); -ConVar physcannon_cone( "physcannon_cone", "0.97" ); -ConVar physcannon_ball_cone( "physcannon_ball_cone", "0.997" ); -ConVar physcannon_punt_cone( "physcannon_punt_cone", "0.997" ); -ConVar player_throwforce( "player_throwforce", "1000" ); -ConVar physcannon_dmg_glass( "physcannon_dmg_glass", "15" ); -ConVar physcannon_right_turrets( "physcannon_right_turrets", "0" ); - -extern ConVar hl2_normspeed; -extern ConVar hl2_walkspeed; - -#define PHYSCANNON_BEAM_SPRITE "sprites/orangelight1.vmt" -#define PHYSCANNON_GLOW_SPRITE "sprites/glow04_noz.vmt" -#define PHYSCANNON_ENDCAP_SPRITE "sprites/orangeflare1.vmt" -#define PHYSCANNON_CENTER_GLOW "sprites/orangecore1.vmt" -#define PHYSCANNON_BLAST_SPRITE "sprites/orangecore2.vmt" - -#define MEGACANNON_BEAM_SPRITE "sprites/lgtning_noz.vmt" -#define MEGACANNON_GLOW_SPRITE "sprites/blueflare1_noz.vmt" -#define MEGACANNON_ENDCAP_SPRITE "sprites/blueflare1_noz.vmt" -#define MEGACANNON_CENTER_GLOW "effects/fluttercore.vmt" -#define MEGACANNON_BLAST_SPRITE "effects/fluttercore.vmt" - -#define MEGACANNON_RAGDOLL_BOOGIE_SPRITE "sprites/lgtning_noz.vmt" - -#define MEGACANNON_MODEL "models/weapons/v_superphyscannon.mdl" -#define MEGACANNON_SKIN 1 - -// ------------------------------------------------------------------------- -// Physcannon trace filter to handle special cases -// ------------------------------------------------------------------------- - -class CTraceFilterPhyscannon : public CTraceFilterSimple -{ -public: - DECLARE_CLASS( CTraceFilterPhyscannon, CTraceFilterSimple ); - - CTraceFilterPhyscannon( const IHandleEntity *passentity, int collisionGroup ) - : CTraceFilterSimple( NULL, collisionGroup ), m_pTraceOwner( passentity ) { } - - // For this test, we only test against entities (then world brushes afterwards) - virtual TraceType_t GetTraceType() const { return TRACE_ENTITIES_ONLY; } - - bool HasContentsGrate( CBaseEntity *pEntity ) - { - // FIXME: Move this into the GetModelContents() function in base entity - - // Find the contents based on the model type - int nModelType = modelinfo->GetModelType( pEntity->GetModel() ); - if ( nModelType == mod_studio ) - { - CBaseAnimating *pAnim = dynamic_cast(pEntity); - if ( pAnim != NULL ) - { - CStudioHdr *pStudioHdr = pAnim->GetModelPtr(); - if ( pStudioHdr != NULL && (pStudioHdr->contents() & CONTENTS_GRATE) ) - return true; - } - } - else if ( nModelType == mod_brush ) - { - // Brushes poll their contents differently - int contents = modelinfo->GetModelContents( pEntity->GetModelIndex() ); - if ( contents & CONTENTS_GRATE ) - return true; - } - - return false; - } - - virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) - { - // Only skip ourselves (not things we own) - if ( pHandleEntity == m_pTraceOwner ) - return false; - - // Get the entity referenced by this handle - CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); - if ( pEntity == NULL ) - return false; - - // Handle grate entities differently - if ( HasContentsGrate( pEntity ) ) - { - // See if it's a grabbable physics prop - CPhysicsProp *pPhysProp = dynamic_cast(pEntity); - if ( pPhysProp != NULL ) - return pPhysProp->CanBePickedUpByPhyscannon(); - - // See if it's a grabbable physics prop - if ( FClassnameIs( pEntity, "prop_physics" ) ) - { - CPhysicsProp *pPhysProp = dynamic_cast(pEntity); - if ( pPhysProp != NULL ) - return pPhysProp->CanBePickedUpByPhyscannon(); - - // Somehow had a classname that didn't match the class! - Assert(0); - } - else if ( FClassnameIs( pEntity, "func_physbox" ) ) - { - // Must be a moveable physbox - CPhysBox *pPhysBox = dynamic_cast(pEntity); - if ( pPhysBox ) - return pPhysBox->CanBePickedUpByPhyscannon(); - - // Somehow had a classname that didn't match the class! - Assert(0); - } - - // Don't bother with any other sort of grated entity - return false; - } - - // Use the default rules - return BaseClass::ShouldHitEntity( pHandleEntity, contentsMask ); - } - -protected: - const IHandleEntity *m_pTraceOwner; -}; - -// We want to test against brushes alone -class CTraceFilterOnlyBrushes : public CTraceFilterSimple -{ -public: - DECLARE_CLASS( CTraceFilterOnlyBrushes, CTraceFilterSimple ); - CTraceFilterOnlyBrushes( int collisionGroup ) : CTraceFilterSimple( NULL, collisionGroup ) {} - virtual TraceType_t GetTraceType() const { return TRACE_WORLD_ONLY; } -}; - -//----------------------------------------------------------------------------- -// this will hit skip the pass entity, but not anything it owns -// (lets player grab own grenades) -class CTraceFilterNoOwnerTest : public CTraceFilterSimple -{ -public: - DECLARE_CLASS( CTraceFilterNoOwnerTest, CTraceFilterSimple ); - - CTraceFilterNoOwnerTest( const IHandleEntity *passentity, int collisionGroup ) - : CTraceFilterSimple( NULL, collisionGroup ), m_pPassNotOwner(passentity) - { - } - - virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) - { - if ( pHandleEntity != m_pPassNotOwner ) - return BaseClass::ShouldHitEntity( pHandleEntity, contentsMask ); - - return false; - } - -protected: - const IHandleEntity *m_pPassNotOwner; -}; - -//----------------------------------------------------------------------------- -// Purpose: Trace a line the special physcannon way! -//----------------------------------------------------------------------------- -void UTIL_PhyscannonTraceLine( const Vector &vecAbsStart, const Vector &vecAbsEnd, CBaseEntity *pTraceOwner, trace_t *pTrace ) -{ - // Default to HL2 vanilla - if ( hl2_episodic.GetBool() == false ) - { - CTraceFilterNoOwnerTest filter( pTraceOwner, COLLISION_GROUP_NONE ); - UTIL_TraceLine( vecAbsStart, vecAbsEnd, (MASK_SHOT|CONTENTS_GRATE), &filter, pTrace ); - return; - } - - // First, trace against entities - CTraceFilterPhyscannon filter( pTraceOwner, COLLISION_GROUP_NONE ); - UTIL_TraceLine( vecAbsStart, vecAbsEnd, (MASK_SHOT|CONTENTS_GRATE), &filter, pTrace ); - - // If we've hit something, test again to make sure no brushes block us - if ( pTrace->m_pEnt != NULL ) - { - trace_t testTrace; - CTraceFilterOnlyBrushes brushFilter( COLLISION_GROUP_NONE ); - UTIL_TraceLine( pTrace->startpos, pTrace->endpos, MASK_SHOT, &brushFilter, &testTrace ); - - // If we hit a brush, replace the trace with that result - if ( testTrace.fraction < 1.0f || testTrace.startsolid || testTrace.allsolid ) - { - *pTrace = testTrace; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Trace a hull for the physcannon -//----------------------------------------------------------------------------- -void UTIL_PhyscannonTraceHull( const Vector &vecAbsStart, const Vector &vecAbsEnd, const Vector &vecAbsMins, const Vector &vecAbsMaxs, CBaseEntity *pTraceOwner, trace_t *pTrace ) -{ - // Default to HL2 vanilla - if ( hl2_episodic.GetBool() == false ) - { - CTraceFilterNoOwnerTest filter( pTraceOwner, COLLISION_GROUP_NONE ); - UTIL_TraceHull( vecAbsStart, vecAbsEnd, vecAbsMins, vecAbsMaxs, (MASK_SHOT|CONTENTS_GRATE), &filter, pTrace ); - return; - } - - // First, trace against entities - CTraceFilterPhyscannon filter( pTraceOwner, COLLISION_GROUP_NONE ); - UTIL_TraceHull( vecAbsStart, vecAbsEnd, vecAbsMins, vecAbsMaxs, (MASK_SHOT|CONTENTS_GRATE), &filter, pTrace ); - - // If we've hit something, test again to make sure no brushes block us - if ( pTrace->m_pEnt != NULL ) - { - trace_t testTrace; - CTraceFilterOnlyBrushes brushFilter( COLLISION_GROUP_NONE ); - UTIL_TraceHull( pTrace->startpos, pTrace->endpos, vecAbsMins, vecAbsMaxs, MASK_SHOT, &brushFilter, &testTrace ); - - // If we hit a brush, replace the trace with that result - if ( testTrace.fraction < 1.0f || testTrace.startsolid || testTrace.allsolid ) - { - *pTrace = testTrace; - } - } -} - -static void MatrixOrthogonalize( matrix3x4_t &matrix, int column ) -{ - Vector columns[3]; - int i; - - for ( i = 0; i < 3; i++ ) - { - MatrixGetColumn( matrix, i, columns[i] ); - } - - int index0 = column; - int index1 = (column+1)%3; - int index2 = (column+2)%3; - - columns[index2] = CrossProduct( columns[index0], columns[index1] ); - columns[index1] = CrossProduct( columns[index2], columns[index0] ); - VectorNormalize( columns[index2] ); - VectorNormalize( columns[index1] ); - MatrixSetColumn( columns[index1], index1, matrix ); - MatrixSetColumn( columns[index2], index2, matrix ); -} - -#define SIGN(x) ( (x) < 0 ? -1 : 1 ) - -static QAngle AlignAngles( const QAngle &angles, float cosineAlignAngle ) -{ - matrix3x4_t alignMatrix; - AngleMatrix( angles, alignMatrix ); - - // NOTE: Must align z first - for ( int j = 3; --j >= 0; ) - { - Vector vec; - MatrixGetColumn( alignMatrix, j, vec ); - for ( int i = 0; i < 3; i++ ) - { - if ( fabs(vec[i]) > cosineAlignAngle ) - { - vec[i] = SIGN(vec[i]); - vec[(i+1)%3] = 0; - vec[(i+2)%3] = 0; - MatrixSetColumn( vec, j, alignMatrix ); - MatrixOrthogonalize( alignMatrix, j ); - break; - } - } - } - - QAngle out; - MatrixAngles( alignMatrix, out ); - return out; -} - - -/*static void TraceCollideAgainstBBox( const CPhysCollide *pCollide, const Vector &start, const Vector &end, const QAngle &angles, const Vector &boxOrigin, const Vector &mins, const Vector &maxs, trace_t *ptr ) -{ - physcollision->TraceBox( boxOrigin, boxOrigin + (start-end), mins, maxs, pCollide, start, angles, ptr ); - - if ( ptr->DidHit() ) - { - ptr->endpos = start * (1-ptr->fraction) + end * ptr->fraction; - ptr->startpos = start; - ptr->plane.dist = -ptr->plane.dist; - ptr->plane.normal *= -1; - } -}*/ - -//----------------------------------------------------------------------------- -// Purpose: Finds the nearest ragdoll sub-piece to a location and returns it -// Input : *pTarget - entity that is the potential ragdoll -// &position - position we're testing against -// Output : IPhysicsObject - sub-object (if any) -//----------------------------------------------------------------------------- -IPhysicsObject *GetRagdollChildAtPosition( CBaseEntity *pTarget, const Vector &position ) -{ - // Check for a ragdoll - if ( dynamic_cast( pTarget ) == NULL ) - return NULL; - - // Get the root - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int count = pTarget->VPhysicsGetObjectList( pList, ARRAYSIZE( pList ) ); - - IPhysicsObject *pBestChild = NULL; - float flBestDist = 99999999.0f; - float flDist; - Vector vPos; - - // Find the nearest child to where we're looking - for ( int i = 0; i < count; i++ ) - { - pList[i]->GetPosition( &vPos, NULL ); - - flDist = ( position - vPos ).LengthSqr(); - - if ( flDist < flBestDist ) - { - pBestChild = pList[i]; - flBestDist = flDist; - } - } - - // Make this our base now - pTarget->VPhysicsSwapObject( pBestChild ); - - return pTarget->VPhysicsGetObject(); -} - -//----------------------------------------------------------------------------- -// Purpose: Computes a local matrix for the player clamped to valid carry ranges -//----------------------------------------------------------------------------- -// when looking level, hold bottom of object 8 inches below eye level -#define PLAYER_HOLD_LEVEL_EYES -8 - -// when looking down, hold bottom of object 0 inches from feet -#define PLAYER_HOLD_DOWN_FEET 2 - -// when looking up, hold bottom of object 24 inches above eye level -#define PLAYER_HOLD_UP_EYES 24 - -// use a +/-30 degree range for the entire range of motion of pitch -#define PLAYER_LOOK_PITCH_RANGE 30 - -// player can reach down 2ft below his feet (otherwise he'll hold the object above the bottom) -#define PLAYER_REACH_DOWN_DISTANCE 24 - -static void ComputePlayerMatrix( CBasePlayer *pPlayer, matrix3x4_t &out ) -{ - if ( !pPlayer ) - return; - - QAngle angles = pPlayer->EyeAngles(); - Vector origin = pPlayer->EyePosition(); - - // 0-360 / -180-180 - //angles.x = init ? 0 : AngleDistance( angles.x, 0 ); - //angles.x = clamp( angles.x, -PLAYER_LOOK_PITCH_RANGE, PLAYER_LOOK_PITCH_RANGE ); - angles.x = 0; - - float feet = pPlayer->GetAbsOrigin().z + pPlayer->WorldAlignMins().z; - float eyes = origin.z; - float zoffset = 0; - // moving up (negative pitch is up) - if ( angles.x < 0 ) - { - zoffset = RemapVal( angles.x, 0, -PLAYER_LOOK_PITCH_RANGE, PLAYER_HOLD_LEVEL_EYES, PLAYER_HOLD_UP_EYES ); - } - else - { - zoffset = RemapVal( angles.x, 0, PLAYER_LOOK_PITCH_RANGE, PLAYER_HOLD_LEVEL_EYES, PLAYER_HOLD_DOWN_FEET + (feet - eyes) ); - } - origin.z += zoffset; - angles.x = 0; - AngleMatrix( angles, origin, out ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -// derive from this so we can add save/load data to it -struct game_shadowcontrol_params_t : public hlshadowcontrol_params_t -{ - DECLARE_SIMPLE_DATADESC(); -}; - -BEGIN_SIMPLE_DATADESC( game_shadowcontrol_params_t ) - - DEFINE_FIELD( targetPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( targetRotation, FIELD_VECTOR ), - DEFINE_FIELD( maxAngular, FIELD_FLOAT ), - DEFINE_FIELD( maxDampAngular, FIELD_FLOAT ), - DEFINE_FIELD( maxSpeed, FIELD_FLOAT ), - DEFINE_FIELD( maxDampSpeed, FIELD_FLOAT ), - DEFINE_FIELD( dampFactor, FIELD_FLOAT ), - DEFINE_FIELD( teleportDistance, FIELD_FLOAT ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -class CGrabController : public IMotionEvent -{ - DECLARE_SIMPLE_DATADESC(); - -public: - - CGrabController( void ); - ~CGrabController( void ); - void AttachEntity( CBasePlayer *pPlayer, CBaseEntity *pEntity, IPhysicsObject *pPhys, bool bIsMegaPhysCannon, const Vector &vGrabPosition, bool bUseGrabPosition ); - void DetachEntity( bool bClearVelocity ); - void OnRestore(); - - bool UpdateObject( CBasePlayer *pPlayer, float flError ); - - void SetTargetPosition( const Vector &target, const QAngle &targetOrientation ); - float ComputeError(); - float GetLoadWeight( void ) const { return m_flLoadWeight; } - void SetAngleAlignment( float alignAngleCosine ) { m_angleAlignment = alignAngleCosine; } - void SetIgnorePitch( bool bIgnore ) { m_bIgnoreRelativePitch = bIgnore; } - QAngle TransformAnglesToPlayerSpace( const QAngle &anglesIn, CBasePlayer *pPlayer ); - QAngle TransformAnglesFromPlayerSpace( const QAngle &anglesIn, CBasePlayer *pPlayer ); - - CBaseEntity *GetAttached() { return (CBaseEntity *)m_attachedEntity; } - - IMotionEvent::simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ); - float GetSavedMass( IPhysicsObject *pObject ); - - bool IsObjectAllowedOverhead( CBaseEntity *pEntity ); - -private: - // Compute the max speed for an attached object - void ComputeMaxSpeed( CBaseEntity *pEntity, IPhysicsObject *pPhysics ); - - game_shadowcontrol_params_t m_shadow; - float m_timeToArrive; - float m_errorTime; - float m_error; - float m_contactAmount; - float m_angleAlignment; - bool m_bCarriedEntityBlocksLOS; - bool m_bIgnoreRelativePitch; - - float m_flLoadWeight; - float m_savedRotDamping[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - float m_savedMass[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - EHANDLE m_attachedEntity; - QAngle m_vecPreferredCarryAngles; - bool m_bHasPreferredCarryAngles; - float m_flDistanceOffset; - - QAngle m_attachedAnglesPlayerSpace; - Vector m_attachedPositionObjectSpace; - - IPhysicsMotionController *m_controller; - - bool m_bAllowObjectOverhead; // Can the player hold this object directly overhead? (Default is NO) - - friend class CWeaponPhysCannon; -}; - -BEGIN_SIMPLE_DATADESC( CGrabController ) - - DEFINE_EMBEDDED( m_shadow ), - - DEFINE_FIELD( m_timeToArrive, FIELD_FLOAT ), - DEFINE_FIELD( m_errorTime, FIELD_FLOAT ), - DEFINE_FIELD( m_error, FIELD_FLOAT ), - DEFINE_FIELD( m_contactAmount, FIELD_FLOAT ), - DEFINE_AUTO_ARRAY( m_savedRotDamping, FIELD_FLOAT ), - DEFINE_AUTO_ARRAY( m_savedMass, FIELD_FLOAT ), - DEFINE_FIELD( m_flLoadWeight, FIELD_FLOAT ), - DEFINE_FIELD( m_bCarriedEntityBlocksLOS, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bIgnoreRelativePitch, FIELD_BOOLEAN ), - DEFINE_FIELD( m_attachedEntity, FIELD_EHANDLE ), - DEFINE_FIELD( m_angleAlignment, FIELD_FLOAT ), - DEFINE_FIELD( m_vecPreferredCarryAngles, FIELD_VECTOR ), - DEFINE_FIELD( m_bHasPreferredCarryAngles, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flDistanceOffset, FIELD_FLOAT ), - DEFINE_FIELD( m_attachedAnglesPlayerSpace, FIELD_VECTOR ), - DEFINE_FIELD( m_attachedPositionObjectSpace, FIELD_VECTOR ), - DEFINE_FIELD( m_bAllowObjectOverhead, FIELD_BOOLEAN ), - - // Physptrs can't be inside embedded classes - // DEFINE_PHYSPTR( m_controller ), - -END_DATADESC() - -const float DEFAULT_MAX_ANGULAR = 360.0f * 10.0f; -const float REDUCED_CARRY_MASS = 1.0f; - -CGrabController::CGrabController( void ) -{ - m_shadow.dampFactor = 1.0; - m_shadow.teleportDistance = 0; - m_errorTime = 0; - m_error = 0; - // make this controller really stiff! - m_shadow.maxSpeed = 1000; - m_shadow.maxAngular = DEFAULT_MAX_ANGULAR; - m_shadow.maxDampSpeed = m_shadow.maxSpeed*2; - m_shadow.maxDampAngular = m_shadow.maxAngular; - m_attachedEntity = NULL; - m_vecPreferredCarryAngles = vec3_angle; - m_bHasPreferredCarryAngles = false; - m_flDistanceOffset = 0; -} - -CGrabController::~CGrabController( void ) -{ - DetachEntity( false ); -} - -void CGrabController::OnRestore() -{ - if ( m_controller ) - { - m_controller->SetEventHandler( this ); - } -} - -void CGrabController::SetTargetPosition( const Vector &target, const QAngle &targetOrientation ) -{ - m_shadow.targetPosition = target; - m_shadow.targetRotation = targetOrientation; - - m_timeToArrive = gpGlobals->frametime; - - CBaseEntity *pAttached = GetAttached(); - if ( pAttached ) - { - IPhysicsObject *pObj = pAttached->VPhysicsGetObject(); - - if ( pObj != NULL ) - { - pObj->Wake(); - } - else - { - DetachEntity( false ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CGrabController::ComputeError() -{ - if ( m_errorTime <= 0 ) - return 0; - - CBaseEntity *pAttached = GetAttached(); - if ( pAttached ) - { - Vector pos; - IPhysicsObject *pObj = pAttached->VPhysicsGetObject(); - - if ( pObj ) - { - pObj->GetShadowPosition( &pos, NULL ); - - float error = (m_shadow.targetPosition - pos).Length(); - if ( m_errorTime > 0 ) - { - if ( m_errorTime > 1 ) - { - m_errorTime = 1; - } - float speed = error / m_errorTime; - if ( speed > m_shadow.maxSpeed ) - { - error *= 0.5; - } - m_error = (1-m_errorTime) * m_error + error * m_errorTime; - } - } - else - { - DevMsg( "Object attached to Physcannon has no physics object\n" ); - DetachEntity( false ); - return 9999; // force detach - } - } - - if ( pAttached->IsEFlagSet( EFL_IS_BEING_LIFTED_BY_BARNACLE ) ) - { - m_error *= 3.0f; - } - - m_errorTime = 0; - - return m_error; -} - - -#define MASS_SPEED_SCALE 60 -#define MAX_MASS 40 - -void CGrabController::ComputeMaxSpeed( CBaseEntity *pEntity, IPhysicsObject *pPhysics ) -{ - m_shadow.maxSpeed = 1000; - m_shadow.maxAngular = DEFAULT_MAX_ANGULAR; - - // Compute total mass... - float flMass = PhysGetEntityMass( pEntity ); - float flMaxMass = physcannon_maxmass.GetFloat(); - if ( flMass <= flMaxMass ) - return; - - float flLerpFactor = clamp( flMass, flMaxMass, 500.0f ); - flLerpFactor = SimpleSplineRemapVal( flLerpFactor, flMaxMass, 500.0f, 0.0f, 1.0f ); - - float invMass = pPhysics->GetInvMass(); - float invInertia = pPhysics->GetInvInertia().Length(); - - float invMaxMass = 1.0f / MAX_MASS; - float ratio = invMaxMass / invMass; - invMass = invMaxMass; - invInertia *= ratio; - - float maxSpeed = invMass * MASS_SPEED_SCALE * 200; - float maxAngular = invInertia * MASS_SPEED_SCALE * 360; - - m_shadow.maxSpeed = Lerp( flLerpFactor, m_shadow.maxSpeed, maxSpeed ); - m_shadow.maxAngular = Lerp( flLerpFactor, m_shadow.maxAngular, maxAngular ); -} - - -QAngle CGrabController::TransformAnglesToPlayerSpace( const QAngle &anglesIn, CBasePlayer *pPlayer ) -{ - if ( m_bIgnoreRelativePitch ) - { - matrix3x4_t test; - QAngle angleTest = pPlayer->EyeAngles(); - angleTest.x = 0; - AngleMatrix( angleTest, test ); - return TransformAnglesToLocalSpace( anglesIn, test ); - } - return TransformAnglesToLocalSpace( anglesIn, pPlayer->EntityToWorldTransform() ); -} - -QAngle CGrabController::TransformAnglesFromPlayerSpace( const QAngle &anglesIn, CBasePlayer *pPlayer ) -{ - if ( m_bIgnoreRelativePitch ) - { - matrix3x4_t test; - QAngle angleTest = pPlayer->EyeAngles(); - angleTest.x = 0; - AngleMatrix( angleTest, test ); - return TransformAnglesToWorldSpace( anglesIn, test ); - } - return TransformAnglesToWorldSpace( anglesIn, pPlayer->EntityToWorldTransform() ); -} - - -void CGrabController::AttachEntity( CBasePlayer *pPlayer, CBaseEntity *pEntity, IPhysicsObject *pPhys, bool bIsMegaPhysCannon, const Vector &vGrabPosition, bool bUseGrabPosition ) -{ - // play the impact sound of the object hitting the player - // used as feedback to let the player know he picked up the object - int hitMaterial = pPhys->GetMaterialIndex(); - int playerMaterial = pPlayer->VPhysicsGetObject() ? pPlayer->VPhysicsGetObject()->GetMaterialIndex() : hitMaterial; - PhysicsImpactSound( pPlayer, pPhys, CHAN_STATIC, hitMaterial, playerMaterial, 1.0, 64 ); - Vector position; - QAngle angles; - pPhys->GetPosition( &position, &angles ); - // If it has a preferred orientation, use that instead. - Pickup_GetPreferredCarryAngles( pEntity, pPlayer, pPlayer->EntityToWorldTransform(), angles ); - -// ComputeMaxSpeed( pEntity, pPhys ); - - // If we haven't been killed by a grab, we allow the gun to grab the nearest part of a ragdoll - if ( bUseGrabPosition ) - { - IPhysicsObject *pChild = GetRagdollChildAtPosition( pEntity, vGrabPosition ); - - if ( pChild ) - { - pPhys = pChild; - } - } - - // Carried entities can never block LOS - m_bCarriedEntityBlocksLOS = pEntity->BlocksLOS(); - pEntity->SetBlocksLOS( false ); - m_controller = physenv->CreateMotionController( this ); - m_controller->AttachObject( pPhys, true ); - // Don't do this, it's causing trouble with constraint solvers. - //m_controller->SetPriority( IPhysicsMotionController::HIGH_PRIORITY ); - - pPhys->Wake(); - PhysSetGameFlags( pPhys, FVPHYSICS_PLAYER_HELD ); - SetTargetPosition( position, angles ); - m_attachedEntity = pEntity; - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int count = pEntity->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - m_flLoadWeight = 0; - float damping = 10; - float flFactor = count / 7.5f; - if ( flFactor < 1.0f ) - { - flFactor = 1.0f; - } - for ( int i = 0; i < count; i++ ) - { - float mass = pList[i]->GetMass(); - pList[i]->GetDamping( NULL, &m_savedRotDamping[i] ); - m_flLoadWeight += mass; - m_savedMass[i] = mass; - - // reduce the mass to prevent the player from adding crazy amounts of energy to the system - pList[i]->SetMass( REDUCED_CARRY_MASS / flFactor ); - pList[i]->SetDamping( NULL, &damping ); - } - - // Give extra mass to the phys object we're actually picking up - pPhys->SetMass( REDUCED_CARRY_MASS ); - pPhys->EnableDrag( false ); - - m_errorTime = bIsMegaPhysCannon ? -1.5f : -1.0f; // 1 seconds until error starts accumulating - m_error = 0; - m_contactAmount = 0; - - m_attachedAnglesPlayerSpace = TransformAnglesToPlayerSpace( angles, pPlayer ); - if ( m_angleAlignment != 0 ) - { - m_attachedAnglesPlayerSpace = AlignAngles( m_attachedAnglesPlayerSpace, m_angleAlignment ); - } - - // Ragdolls don't offset this way - if ( dynamic_cast(pEntity) ) - { - m_attachedPositionObjectSpace.Init(); - } - else - { - VectorITransform( pEntity->WorldSpaceCenter(), pEntity->EntityToWorldTransform(), m_attachedPositionObjectSpace ); - } - - // If it's a prop, see if it has desired carry angles - CPhysicsProp *pProp = dynamic_cast(pEntity); - if ( pProp ) - { - m_bHasPreferredCarryAngles = pProp->GetPropDataAngles( "preferred_carryangles", m_vecPreferredCarryAngles ); - m_flDistanceOffset = pProp->GetCarryDistanceOffset(); - } - else - { - m_bHasPreferredCarryAngles = false; - m_flDistanceOffset = 0; - } - - m_bAllowObjectOverhead = IsObjectAllowedOverhead( pEntity ); -} - -static void ClampPhysicsVelocity( IPhysicsObject *pPhys, float linearLimit, float angularLimit ) -{ - Vector vel; - AngularImpulse angVel; - pPhys->GetVelocity( &vel, &angVel ); - float speed = VectorNormalize(vel) - linearLimit; - float angSpeed = VectorNormalize(angVel) - angularLimit; - speed = speed < 0 ? 0 : -speed; - angSpeed = angSpeed < 0 ? 0 : -angSpeed; - vel *= speed; - angVel *= angSpeed; - pPhys->AddVelocity( &vel, &angVel ); -} - -void CGrabController::DetachEntity( bool bClearVelocity ) -{ - Assert(!PhysIsInCallback()); - CBaseEntity *pEntity = GetAttached(); - if ( pEntity ) - { - // Restore the LS blocking state - pEntity->SetBlocksLOS( m_bCarriedEntityBlocksLOS ); - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int count = pEntity->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - for ( int i = 0; i < count; i++ ) - { - IPhysicsObject *pPhys = pList[i]; - if ( !pPhys ) - continue; - - // on the odd chance that it's gone to sleep while under anti-gravity - pPhys->EnableDrag( true ); - pPhys->Wake(); - pPhys->SetMass( m_savedMass[i] ); - pPhys->SetDamping( NULL, &m_savedRotDamping[i] ); - PhysClearGameFlags( pPhys, FVPHYSICS_PLAYER_HELD ); - if ( bClearVelocity ) - { - PhysForceClearVelocity( pPhys ); - } - else - { - ClampPhysicsVelocity( pPhys, hl2_normspeed.GetFloat() * 1.5f, 2.0f * 360.0f ); - } - - } - } - - m_attachedEntity = NULL; - physenv->DestroyMotionController( m_controller ); - m_controller = NULL; -} - -static bool InContactWithHeavyObject( IPhysicsObject *pObject, float heavyMass ) -{ - bool contact = false; - IPhysicsFrictionSnapshot *pSnapshot = pObject->CreateFrictionSnapshot(); - while ( pSnapshot->IsValid() ) - { - IPhysicsObject *pOther = pSnapshot->GetObject( 1 ); - if ( !pOther->IsMoveable() || pOther->GetMass() > heavyMass ) - { - contact = true; - break; - } - pSnapshot->NextFrictionData(); - } - pObject->DestroyFrictionSnapshot( pSnapshot ); - return contact; -} - -IMotionEvent::simresult_e CGrabController::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) -{ - game_shadowcontrol_params_t shadowParams = m_shadow; - if ( InContactWithHeavyObject( pObject, GetLoadWeight() ) ) - { - m_contactAmount = Approach( 0.1f, m_contactAmount, deltaTime*2.0f ); - } - else - { - m_contactAmount = Approach( 1.0f, m_contactAmount, deltaTime*2.0f ); - } - shadowParams.maxAngular = m_shadow.maxAngular * m_contactAmount * m_contactAmount * m_contactAmount; - m_timeToArrive = pObject->ComputeShadowControl( shadowParams, m_timeToArrive, deltaTime ); - - // Slide along the current contact points to fix bouncing problems - Vector velocity; - AngularImpulse angVel; - pObject->GetVelocity( &velocity, &angVel ); - PhysComputeSlideDirection( pObject, velocity, angVel, &velocity, &angVel, GetLoadWeight() ); - pObject->SetVelocityInstantaneous( &velocity, NULL ); - - linear.Init(); - angular.Init(); - m_errorTime += deltaTime; - - return SIM_LOCAL_ACCELERATION; -} - -float CGrabController::GetSavedMass( IPhysicsObject *pObject ) -{ - CBaseEntity *pHeld = m_attachedEntity; - if ( pHeld ) - { - if ( pObject->GetGameData() == (void*)pHeld ) - { - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int count = pHeld->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - for ( int i = 0; i < count; i++ ) - { - if ( pList[i] == pObject ) - return m_savedMass[i]; - } - } - } - return 0.0f; -} - -//----------------------------------------------------------------------------- -// Is this an object that the player is allowed to lift to a position -// directly overhead? The default behavior prevents lifting objects directly -// overhead, but there are exceptions for gameplay purposes. -//----------------------------------------------------------------------------- -bool CGrabController::IsObjectAllowedOverhead( CBaseEntity *pEntity ) -{ - // Allow combine balls overhead - if( UTIL_IsCombineBallDefinite(pEntity) ) - return true; - - // Allow props that are specifically flagged as such - CPhysicsProp *pPhysProp = dynamic_cast(pEntity); - if ( pPhysProp != NULL && pPhysProp->HasInteraction( PROPINTER_PHYSGUN_ALLOW_OVERHEAD ) ) - return true; - - // String checks are fine here, we only run this code one time- when the object is picked up. - if( pEntity->ClassMatches("grenade_helicopter") ) - return true; - - if( pEntity->ClassMatches("weapon_striderbuster") ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Player pickup controller -//----------------------------------------------------------------------------- -class CPlayerPickupController : public CBaseEntity -{ - DECLARE_DATADESC(); - DECLARE_CLASS( CPlayerPickupController, CBaseEntity ); -public: - void Init( CBasePlayer *pPlayer, CBaseEntity *pObject ); - void Shutdown( bool bThrown = false ); - bool OnControls( CBaseEntity *pControls ) { return true; } - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - void OnRestore() - { - m_grabController.OnRestore(); - } - void VPhysicsUpdate( IPhysicsObject *pPhysics ){} - void VPhysicsShadowUpdate( IPhysicsObject *pPhysics ) {} - - bool IsHoldingEntity( CBaseEntity *pEnt ); - CGrabController &GetGrabController() { return m_grabController; } - -private: - CGrabController m_grabController; - CBasePlayer *m_pPlayer; -}; - -LINK_ENTITY_TO_CLASS( player_pickup, CPlayerPickupController ); - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CPlayerPickupController ) - - DEFINE_EMBEDDED( m_grabController ), - - // Physptrs can't be inside embedded classes - DEFINE_PHYSPTR( m_grabController.m_controller ), - - DEFINE_FIELD( m_pPlayer, FIELD_CLASSPTR ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -// *pObject - -//----------------------------------------------------------------------------- -void CPlayerPickupController::Init( CBasePlayer *pPlayer, CBaseEntity *pObject ) -{ - // Holster player's weapon - if ( pPlayer->GetActiveWeapon() ) - { - if ( !pPlayer->GetActiveWeapon()->CanHolster() || !pPlayer->GetActiveWeapon()->Holster() ) - { - Shutdown(); - return; - } - } - - CHL2_Player *pOwner = (CHL2_Player *)ToBasePlayer( pPlayer ); - if ( pOwner ) - { - pOwner->EnableSprint( false ); - } - - // If the target is debris, convert it to non-debris - if ( pObject->GetCollisionGroup() == COLLISION_GROUP_DEBRIS ) - { - // Interactive debris converts back to debris when it comes to rest - pObject->SetCollisionGroup( COLLISION_GROUP_INTERACTIVE_DEBRIS ); - } - - // done so I'll go across level transitions with the player - SetParent( pPlayer ); - m_grabController.SetIgnorePitch( true ); - m_grabController.SetAngleAlignment( DOT_30DEGREE ); - m_pPlayer = pPlayer; - IPhysicsObject *pPhysics = pObject->VPhysicsGetObject(); - - Pickup_OnPhysGunPickup( pObject, m_pPlayer, PICKED_UP_BY_PLAYER ); - - m_grabController.AttachEntity( pPlayer, pObject, pPhysics, false, vec3_origin, false ); - - m_pPlayer->m_Local.m_iHideHUD |= HIDEHUD_WEAPONSELECTION; - m_pPlayer->SetUseEntity( this ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : bool - -//----------------------------------------------------------------------------- -void CPlayerPickupController::Shutdown( bool bThrown ) -{ - CBaseEntity *pObject = m_grabController.GetAttached(); - - bool bClearVelocity = false; - if ( !bThrown && pObject && pObject->VPhysicsGetObject() && pObject->VPhysicsGetObject()->GetContactPoint(NULL,NULL) ) - { - bClearVelocity = true; - } - - m_grabController.DetachEntity( bClearVelocity ); - - if ( pObject != NULL ) - { - Pickup_OnPhysGunDrop( pObject, m_pPlayer, bThrown ? THROWN_BY_PLAYER : DROPPED_BY_PLAYER ); - } - - if ( m_pPlayer ) - { - CHL2_Player *pOwner = (CHL2_Player *)ToBasePlayer( m_pPlayer ); - if ( pOwner ) - { - pOwner->EnableSprint( true ); - } - - m_pPlayer->SetUseEntity( NULL ); - if ( m_pPlayer->GetActiveWeapon() ) - { - if ( !m_pPlayer->GetActiveWeapon()->Deploy() ) - { - // We tried to restore the player's weapon, but we couldn't. - // This usually happens when they're holding an empty weapon that doesn't - // autoswitch away when out of ammo. Switch to next best weapon. - m_pPlayer->SwitchToNextBestWeapon( NULL ); - } - } - - m_pPlayer->m_Local.m_iHideHUD &= ~HIDEHUD_WEAPONSELECTION; - } - Remove(); -} - - -void CPlayerPickupController::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - if ( ToBasePlayer(pActivator) == m_pPlayer ) - { - CBaseEntity *pAttached = m_grabController.GetAttached(); - - // UNDONE: Use vphysics stress to decide to drop objects - // UNDONE: Must fix case of forcing objects into the ground you're standing on (causes stress) before that will work - if ( !pAttached || useType == USE_OFF || (m_pPlayer->m_nButtons & IN_ATTACK2) || m_grabController.ComputeError() > 12 ) - { - Shutdown(); - return; - } - - //Adrian: Oops, our object became motion disabled, let go! - IPhysicsObject *pPhys = pAttached->VPhysicsGetObject(); - if ( pPhys && pPhys->IsMoveable() == false ) - { - Shutdown(); - return; - } - -#if STRESS_TEST - vphysics_objectstress_t stress; - CalculateObjectStress( pPhys, pAttached, &stress ); - if ( stress.exertedStress > 250 ) - { - Shutdown(); - return; - } -#endif - // +ATTACK will throw phys objects - if ( m_pPlayer->m_nButtons & IN_ATTACK ) - { - Shutdown( true ); - Vector vecLaunch; - m_pPlayer->EyeVectors( &vecLaunch ); - // JAY: Scale this with mass because some small objects really go flying - float massFactor = clamp( pPhys->GetMass(), 0.5, 15 ); - massFactor = RemapVal( massFactor, 0.5, 15, 0.5, 4 ); - vecLaunch *= player_throwforce.GetFloat() * massFactor; - - pPhys->ApplyForceCenter( vecLaunch ); - AngularImpulse aVel = RandomAngularImpulse( -10, 10 ) * massFactor; - pPhys->ApplyTorqueCenter( aVel ); - return; - } - - if ( useType == USE_SET ) - { - // update position - m_grabController.UpdateObject( m_pPlayer, 12 ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEnt - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CPlayerPickupController::IsHoldingEntity( CBaseEntity *pEnt ) -{ - return ( m_grabController.GetAttached() == pEnt ); -} - -void PlayerPickupObject( CBasePlayer *pPlayer, CBaseEntity *pObject ) -{ - //Don't pick up if we don't have a phys object. - if ( pObject->VPhysicsGetObject() == NULL ) - return; - - CPlayerPickupController *pController = (CPlayerPickupController *)CBaseEntity::Create( "player_pickup", pObject->GetAbsOrigin(), vec3_angle, pPlayer ); - - if ( !pController ) - return; - - pController->Init( pPlayer, pObject ); -} - -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// Physcannon -//----------------------------------------------------------------------------- - -#define NUM_BEAMS 4 -#define NUM_SPRITES 6 - -struct thrown_objects_t -{ - float fTimeThrown; - EHANDLE hEntity; - - DECLARE_SIMPLE_DATADESC(); -}; - -BEGIN_SIMPLE_DATADESC( thrown_objects_t ) - DEFINE_FIELD( fTimeThrown, FIELD_TIME ), - DEFINE_FIELD( hEntity, FIELD_EHANDLE ), -END_DATADESC() - -class CWeaponPhysCannon : public CBaseHLCombatWeapon -{ -public: - DECLARE_CLASS( CWeaponPhysCannon, CBaseHLCombatWeapon ); - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - CWeaponPhysCannon( void ); - - void Drop( const Vector &vecVelocity ); - void Precache(); - virtual void Spawn(); - virtual void OnRestore(); - virtual void StopLoopingSounds(); - virtual void UpdateOnRemove(void); - void PrimaryAttack(); - void SecondaryAttack(); - void WeaponIdle(); - void ItemPreFrame(); - void ItemPostFrame(); - void ItemBusyFrame(); - - virtual float GetMaxAutoAimDeflection() { return 0.90f; } - - void ForceDrop( void ); - bool DropIfEntityHeld( CBaseEntity *pTarget ); // Drops its held entity if it matches the entity passed in - CGrabController &GetGrabController() { return m_grabController; } - - bool CanHolster( void ); - bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); - bool Deploy( void ); - - bool HasAnyAmmo( void ) { return true; } - - void InputBecomeMegaCannon( inputdata_t &inputdata ); - - void BeginUpgrade(); - - virtual void SetViewModel( void ); - virtual const char *GetShootSound( int iIndex ) const; - - void RecordThrownObject( CBaseEntity *pObject ); - void PurgeThrownObjects(); - bool IsAccountableForObject( CBaseEntity *pObject ); - - bool ShouldDisplayHUDHint() { return true; } - - - -protected: - enum FindObjectResult_t - { - OBJECT_FOUND = 0, - OBJECT_NOT_FOUND, - OBJECT_BEING_DETACHED, - }; - - void DoMegaEffect( int effectType, Vector *pos = NULL ); - void DoEffect( int effectType, Vector *pos = NULL ); - - void OpenElements( void ); - void CloseElements( void ); - - // Pickup and throw objects. - bool CanPickupObject( CBaseEntity *pTarget ); - void CheckForTarget( void ); - FindObjectResult_t FindObject( void ); - void FindObjectTrace( CBasePlayer *pPlayer, trace_t *pTraceResult ); - CBaseEntity *MegaPhysCannonFindObjectInCone( const Vector &vecOrigin, const Vector &vecDir, float flCone, float flCombineBallCone, bool bOnlyCombineBalls ); - CBaseEntity *FindObjectInCone( const Vector &vecOrigin, const Vector &vecDir, float flCone ); - bool AttachObject( CBaseEntity *pObject, const Vector &vPosition ); - void UpdateObject( void ); - void DetachObject( bool playSound = true, bool wasLaunched = false ); - void LaunchObject( const Vector &vecDir, float flForce ); - void StartEffects( void ); // Initialize all sprites and beams - void StopEffects( bool stopSound = true ); // Hide all effects temporarily - void DestroyEffects( void ); // Destroy all sprites and beams - - // Punt objects - this is pointing at an object in the world and applying a force to it. - void PuntNonVPhysics( CBaseEntity *pEntity, const Vector &forward, trace_t &tr ); - void PuntVPhysics( CBaseEntity *pEntity, const Vector &forward, trace_t &tr ); - void PuntRagdoll( CBaseEntity *pEntity, const Vector &forward, trace_t &tr ); - - // Velocity-based throw common to punt and launch code. - void ApplyVelocityBasedForce( CBaseEntity *pEntity, const Vector &forward, const Vector &vecHitPos, PhysGunForce_t reason ); - - // Physgun effects - void DoEffectClosed( void ); - void DoMegaEffectClosed( void ); - - void DoEffectReady( void ); - void DoMegaEffectReady( void ); - - void DoMegaEffectHolding( void ); - void DoEffectHolding( void ); - - void DoMegaEffectLaunch( Vector *pos ); - void DoEffectLaunch( Vector *pos ); - - void DoEffectNone( void ); - void DoEffectIdle( void ); - - // Trace length - float TraceLength(); - - // Do we have the super-phys gun? - inline bool IsMegaPhysCannon() - { - return PlayerHasMegaPhysCannon(); - } - - // Sprite scale factor - float SpriteScaleFactor(); - - float GetLoadPercentage(); - CSoundPatch *GetMotorSound( void ); - - void DryFire( void ); - void PrimaryFireEffect( void ); - - // What happens when the physgun picks up something - void Physgun_OnPhysGunPickup( CBaseEntity *pEntity, CBasePlayer *pOwner, PhysGunPickup_t reason ); - - // Wait until we're done upgrading - void WaitForUpgradeThink(); - - bool EntityAllowsPunts( CBaseEntity *pEntity ); - - bool m_bOpen; - bool m_bActive; - int m_nChangeState; //For delayed state change of elements - float m_flCheckSuppressTime; //Amount of time to suppress the checking for targets - bool m_flLastDenySoundPlayed; //Debounce for deny sound - int m_nAttack2Debounce; - - CNetworkVar( bool, m_bIsCurrentlyUpgrading ); - CNetworkVar( float, m_flTimeForceView ); - - float m_flElementDebounce; - float m_flElementPosition; - float m_flElementDestination; - - CHandle m_hBeams[NUM_BEAMS]; - CHandle m_hGlowSprites[NUM_SPRITES]; - CHandle m_hEndSprites[2]; - float m_flEndSpritesOverride[2]; - CHandle m_hCenterSprite; - CHandle m_hBlastSprite; - - CSoundPatch *m_sndMotor; // Whirring sound for the gun - - CGrabController m_grabController; - - int m_EffectState; // Current state of the effects on the gun - - bool m_bPhyscannonState; - - // A list of the objects thrown or punted recently, and the time done so. - CUtlVector< thrown_objects_t > m_ThrownEntities; - - float m_flTimeNextObjectPurge; - -protected: - // Because the physcannon is a leaf class, we can use - // static variables to store this information, and save some memory. - // Should the physcannon end up having inheritors, their activate may - // stomp these numbers, in which case you should make these ordinary members - // again. - // - // The physcannon also caches some pose parameters in SetupGlobalModelData(). - static int m_poseActive; - static bool m_sbStaticPoseParamsLoaded; -}; - -bool CWeaponPhysCannon::m_sbStaticPoseParamsLoaded = false; -int CWeaponPhysCannon::m_poseActive = 0; - -IMPLEMENT_SERVERCLASS_ST(CWeaponPhysCannon, DT_WeaponPhysCannon) - SendPropBool( SENDINFO( m_bIsCurrentlyUpgrading ) ), - SendPropFloat( SENDINFO( m_flTimeForceView ) ), -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_physcannon, CWeaponPhysCannon ); -PRECACHE_WEAPON_REGISTER( weapon_physcannon ); - -BEGIN_DATADESC( CWeaponPhysCannon ) - - DEFINE_FIELD( m_bOpen, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bActive, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_nChangeState, FIELD_INTEGER ), - DEFINE_FIELD( m_flCheckSuppressTime, FIELD_TIME ), - DEFINE_FIELD( m_flElementDebounce, FIELD_TIME ), - DEFINE_FIELD( m_flElementPosition, FIELD_FLOAT ), - DEFINE_FIELD( m_flElementDestination, FIELD_FLOAT ), - DEFINE_FIELD( m_nAttack2Debounce, FIELD_INTEGER ), - DEFINE_FIELD( m_bIsCurrentlyUpgrading, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flTimeForceView, FIELD_TIME ), - DEFINE_FIELD( m_EffectState, FIELD_INTEGER ), - - DEFINE_AUTO_ARRAY( m_hBeams, FIELD_EHANDLE ), - DEFINE_AUTO_ARRAY( m_hGlowSprites, FIELD_EHANDLE ), - DEFINE_AUTO_ARRAY( m_hEndSprites, FIELD_EHANDLE ), - DEFINE_AUTO_ARRAY( m_flEndSpritesOverride, FIELD_TIME ), - DEFINE_FIELD( m_hCenterSprite, FIELD_EHANDLE ), - DEFINE_FIELD( m_hBlastSprite, FIELD_EHANDLE ), - DEFINE_FIELD( m_flLastDenySoundPlayed, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bPhyscannonState, FIELD_BOOLEAN ), - DEFINE_SOUNDPATCH( m_sndMotor ), - - DEFINE_EMBEDDED( m_grabController ), - - // Physptrs can't be inside embedded classes - DEFINE_PHYSPTR( m_grabController.m_controller ), - - DEFINE_THINKFUNC( WaitForUpgradeThink ), - - DEFINE_UTLVECTOR( m_ThrownEntities, FIELD_EMBEDDED ), - - DEFINE_FIELD( m_flTimeNextObjectPurge, FIELD_TIME ), - -END_DATADESC() - - -enum -{ - ELEMENT_STATE_NONE = -1, - ELEMENT_STATE_OPEN, - ELEMENT_STATE_CLOSED, -}; - -enum -{ - EFFECT_NONE, - EFFECT_CLOSED, - EFFECT_READY, - EFFECT_HOLDING, - EFFECT_LAUNCH, -}; - - -//----------------------------------------------------------------------------- -// Do we have the super-phys gun? -//----------------------------------------------------------------------------- -bool PlayerHasMegaPhysCannon() -{ - return ( HL2GameRules()->MegaPhyscannonActive() == true ); -} - - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CWeaponPhysCannon::CWeaponPhysCannon( void ) -{ - m_flElementPosition = 0.0f; - m_flElementDestination = 0.0f; - m_bOpen = false; - m_nChangeState = ELEMENT_STATE_NONE; - m_flCheckSuppressTime = 0.0f; - m_EffectState = EFFECT_NONE; - m_flLastDenySoundPlayed = false; - - m_flEndSpritesOverride[0] = 0.0f; - m_flEndSpritesOverride[1] = 0.0f; - - m_bPhyscannonState = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Precache -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::Precache( void ) -{ - PrecacheModel( PHYSCANNON_BEAM_SPRITE ); - PrecacheModel( PHYSCANNON_GLOW_SPRITE ); - PrecacheModel( PHYSCANNON_ENDCAP_SPRITE ); - PrecacheModel( PHYSCANNON_CENTER_GLOW ); - PrecacheModel( PHYSCANNON_BLAST_SPRITE ); - - PrecacheModel( MEGACANNON_BEAM_SPRITE ); - PrecacheModel( MEGACANNON_GLOW_SPRITE ); - PrecacheModel( MEGACANNON_ENDCAP_SPRITE ); - PrecacheModel( MEGACANNON_CENTER_GLOW ); - PrecacheModel( MEGACANNON_BLAST_SPRITE ); - - PrecacheModel( MEGACANNON_RAGDOLL_BOOGIE_SPRITE ); - - // Precache our alternate model - PrecacheModel( MEGACANNON_MODEL ); - - PrecacheScriptSound( "Weapon_PhysCannon.HoldSound" ); - PrecacheScriptSound( "Weapon_Physgun.Off" ); - - PrecacheScriptSound( "Weapon_MegaPhysCannon.DryFire" ); - PrecacheScriptSound( "Weapon_MegaPhysCannon.Launch" ); - PrecacheScriptSound( "Weapon_MegaPhysCannon.Pickup"); - PrecacheScriptSound( "Weapon_MegaPhysCannon.Drop"); - PrecacheScriptSound( "Weapon_MegaPhysCannon.HoldSound"); - PrecacheScriptSound( "Weapon_MegaPhysCannon.ChargeZap"); - - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::Spawn( void ) -{ - BaseClass::Spawn(); - - // Need to get close to pick it up - CollisionProp()->UseTriggerBounds( false ); - - m_bPhyscannonState = IsMegaPhysCannon(); - - // The megacannon uses a different skin - if ( IsMegaPhysCannon() ) - { - m_nSkin = MEGACANNON_SKIN; - } - - m_flTimeForceView = -1; -} - - -//----------------------------------------------------------------------------- -// Purpose: Restore -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::OnRestore() -{ - BaseClass::OnRestore(); - m_grabController.OnRestore(); - - m_bPhyscannonState = IsMegaPhysCannon(); - - // Tracker 8106: Physcannon effects disappear through level transition, so - // just recreate any effects here - if ( m_EffectState != EFFECT_NONE ) - { - DoEffect( m_EffectState, NULL ); - } -} - -//----------------------------------------------------------------------------- -// On Remove -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::UpdateOnRemove(void) -{ - DestroyEffects( ); - BaseClass::UpdateOnRemove(); -} - - -//----------------------------------------------------------------------------- -// Sprite scale factor -//----------------------------------------------------------------------------- -inline float CWeaponPhysCannon::SpriteScaleFactor() -{ - return IsMegaPhysCannon() ? 1.5f : 1.0f; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponPhysCannon::Deploy( void ) -{ - CloseElements(); - DoEffect( EFFECT_READY ); - - // Unbloat our bounds - if ( IsMegaPhysCannon() ) - { - CollisionProp()->UseTriggerBounds( false ); - } - - m_flTimeNextObjectPurge = gpGlobals->curtime; - - return BaseClass::Deploy(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::SetViewModel( void ) -{ - if ( !IsMegaPhysCannon() ) - { - BaseClass::SetViewModel(); - return; - } - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( pOwner == NULL ) - return; - - CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex ); - if ( vm == NULL ) - return; - - vm->SetWeaponModel( MEGACANNON_MODEL, this ); -} - -//----------------------------------------------------------------------------- -// Purpose: Force the cannon to drop anything it's carrying -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::ForceDrop( void ) -{ - CloseElements(); - DetachObject(); - StopEffects(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Drops its held entity if it matches the entity passed in -// Input : *pTarget - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponPhysCannon::DropIfEntityHeld( CBaseEntity *pTarget ) -{ - if ( pTarget == NULL ) - return false; - - CBaseEntity *pHeld = m_grabController.GetAttached(); - - if ( pHeld == NULL ) - return false; - - if ( pHeld == pTarget ) - { - ForceDrop(); - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::Drop( const Vector &vecVelocity ) -{ - ForceDrop(); - BaseClass::Drop( vecVelocity ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CWeaponPhysCannon::CanHolster( void ) -{ - //Don't holster this weapon if we're holding onto something - if ( m_bActive ) - return false; - - return BaseClass::CanHolster(); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponPhysCannon::Holster( CBaseCombatWeapon *pSwitchingTo ) -{ - //Don't holster this weapon if we're holding onto something - if ( m_bActive ) - { - if ( !pSwitchingTo || - ( m_grabController.GetAttached() == pSwitchingTo && - GetOwner()->Weapon_OwnsThisType( pSwitchingTo->GetClassname(), pSwitchingTo->GetSubType()) ) ) - { - - } - else - { - return false; - } - } - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( pOwner ) - { - pOwner->RumbleEffect( RUMBLE_PHYSCANNON_OPEN, 0, RUMBLE_FLAG_STOP ); - } - - ForceDrop(); - - return BaseClass::Holster( pSwitchingTo ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DryFire( void ) -{ - SendWeaponAnim( ACT_VM_PRIMARYATTACK ); - WeaponSound( EMPTY ); - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( pOwner ) - { - pOwner->RumbleEffect( RUMBLE_PISTOL, 0, RUMBLE_FLAG_RESTART ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::PrimaryFireEffect( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - pOwner->ViewPunch( QAngle(-6, random->RandomInt(-2,2) ,0) ); - - color32 white = { 245, 245, 255, 32 }; - UTIL_ScreenFade( pOwner, white, 0.1f, 0.0f, FFADE_IN ); - - WeaponSound( SINGLE ); -} - -#define MAX_KNOCKBACK_FORCE 128 - -//----------------------------------------------------------------------------- -// Punt non-physics -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::PuntNonVPhysics( CBaseEntity *pEntity, const Vector &forward, trace_t &tr ) -{ - float flDamage = 1.0f; - if ( FClassnameIs( pEntity, "func_breakable" ) ) - { - CBreakable *pBreak = dynamic_cast (pEntity); - if ( pBreak && ( pBreak->GetMaterialType() == matGlass ) ) - { - flDamage = physcannon_dmg_glass.GetFloat(); - } - } - - CTakeDamageInfo info; - - info.SetAttacker( GetOwner() ); - info.SetInflictor( this ); - info.SetDamage( flDamage ); - info.SetDamageType( DMG_CRUSH | DMG_PHYSGUN ); - info.SetDamageForce( forward ); // Scale? - info.SetDamagePosition( tr.endpos ); - - pEntity->DispatchTraceAttack( info, forward, &tr ); - - ApplyMultiDamage(); - - //Explosion effect - DoEffect( EFFECT_LAUNCH, &tr.endpos ); - - PrimaryFireEffect(); - SendWeaponAnim( ACT_VM_SECONDARYATTACK ); - - m_nChangeState = ELEMENT_STATE_CLOSED; - m_flElementDebounce = gpGlobals->curtime + 0.5f; - m_flCheckSuppressTime = gpGlobals->curtime + 0.25f; -} - - -//----------------------------------------------------------------------------- -// What happens when the physgun picks up something -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::Physgun_OnPhysGunPickup( CBaseEntity *pEntity, CBasePlayer *pOwner, PhysGunPickup_t reason ) -{ - // If the target is debris, convert it to non-debris - if ( pEntity->GetCollisionGroup() == COLLISION_GROUP_DEBRIS ) - { - // Interactive debris converts back to debris when it comes to rest - pEntity->SetCollisionGroup( COLLISION_GROUP_INTERACTIVE_DEBRIS ); - } - - float mass = 0.0f; - if( pEntity->VPhysicsGetObject() ) - { - mass = pEntity->VPhysicsGetObject()->GetMass(); - } - - if( reason == PUNTED_BY_CANNON ) - { - pOwner->RumbleEffect( RUMBLE_357, 0, RUMBLE_FLAGS_NONE ); - RecordThrownObject( pEntity ); - } - - // Warn Alyx if the player is punting a car around. - if( hl2_episodic.GetBool() && mass > 250.0f ) - { - CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); - int nAIs = g_AI_Manager.NumAIs(); - - for ( int i = 0; i < nAIs; i++ ) - { - if( ppAIs[ i ]->Classify() == CLASS_PLAYER_ALLY_VITAL ) - { - ppAIs[ i ]->DispatchInteraction( g_interactionPlayerPuntedHeavyObject, pEntity, pOwner ); - } - } - } - - Pickup_OnPhysGunPickup( pEntity, pOwner, reason ); -} - - -//----------------------------------------------------------------------------- -// Punt vphysics -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::PuntVPhysics( CBaseEntity *pEntity, const Vector &vecForward, trace_t &tr ) -{ - CTakeDamageInfo info; - - Vector forward = vecForward; - - info.SetAttacker( GetOwner() ); - info.SetInflictor( this ); - info.SetDamage( 0.0f ); - info.SetDamageType( DMG_PHYSGUN ); - pEntity->DispatchTraceAttack( info, forward, &tr ); - ApplyMultiDamage(); - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( Pickup_OnAttemptPhysGunPickup( pEntity, pOwner, PUNTED_BY_CANNON ) ) - { - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int listCount = pEntity->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - if ( !listCount ) - { - //FIXME: Do we want to do this if there's no physics object? - Physgun_OnPhysGunPickup( pEntity, pOwner, PUNTED_BY_CANNON ); - DryFire(); - return; - } - - if( forward.z < 0 ) - { - //reflect, but flatten the trajectory out a bit so it's easier to hit standing targets - forward.z *= -0.65f; - } - - // NOTE: Do this first to enable motion (if disabled) - so forces will work - // Tell the object it's been punted - Physgun_OnPhysGunPickup( pEntity, pOwner, PUNTED_BY_CANNON ); - - // don't push vehicles that are attached to the world via fixed constraints - // they will just wiggle... - if ( (pList[0]->GetGameFlags() & FVPHYSICS_CONSTRAINT_STATIC) && pEntity->GetServerVehicle() ) - { - forward.Init(); - } - - if ( !IsMegaPhysCannon() && !Pickup_ShouldPuntUseLaunchForces( pEntity, PHYSGUN_FORCE_PUNTED ) ) - { - int i; - - // limit mass to avoid punting REALLY huge things - float totalMass = 0; - for ( i = 0; i < listCount; i++ ) - { - totalMass += pList[i]->GetMass(); - } - float maxMass = 250; - IServerVehicle *pVehicle = pEntity->GetServerVehicle(); - if ( pVehicle ) - { - maxMass *= 2.5; // 625 for vehicles - } - float mass = MIN(totalMass, maxMass); // max 250kg of additional force - - // Put some spin on the object - for ( i = 0; i < listCount; i++ ) - { - const float hitObjectFactor = 0.5f; - const float otherObjectFactor = 1.0f - hitObjectFactor; - // Must be light enough - float ratio = pList[i]->GetMass() / totalMass; - if ( pList[i] == pEntity->VPhysicsGetObject() ) - { - ratio += hitObjectFactor; - ratio = MIN(ratio,1.0f); - } - else - { - ratio *= otherObjectFactor; - } - pList[i]->ApplyForceCenter( forward * 15000.0f * ratio ); - pList[i]->ApplyForceOffset( forward * mass * 600.0f * ratio, tr.endpos ); - } - } - else - { - ApplyVelocityBasedForce( pEntity, vecForward, tr.endpos, PHYSGUN_FORCE_PUNTED ); - } - } - - // Add recoil - QAngle recoil = QAngle( random->RandomFloat( 1.0f, 2.0f ), random->RandomFloat( -1.0f, 1.0f ), 0 ); - pOwner->ViewPunch( recoil ); - - //Explosion effect - DoEffect( EFFECT_LAUNCH, &tr.endpos ); - - PrimaryFireEffect(); - SendWeaponAnim( ACT_VM_SECONDARYATTACK ); - - m_nChangeState = ELEMENT_STATE_CLOSED; - m_flElementDebounce = gpGlobals->curtime + 0.5f; - m_flCheckSuppressTime = gpGlobals->curtime + 0.25f; - - // Don't allow the gun to regrab a thrown object!! - m_flNextSecondaryAttack = m_flNextPrimaryAttack = gpGlobals->curtime + 0.5f; -} - -//----------------------------------------------------------------------------- -// Purpose: Applies velocity-based forces to throw the entity. This code is -// called from both punt and launch carried code. -// ASSUMES: that pEntity is a vphysics entity. -// Input : - -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::ApplyVelocityBasedForce( CBaseEntity *pEntity, const Vector &forward, const Vector &vecHitPos, PhysGunForce_t reason ) -{ - // Get the launch velocity - Vector vVel = Pickup_PhysGunLaunchVelocity( pEntity, forward, reason ); - - // Get the launch angular impulse - AngularImpulse aVel = Pickup_PhysGunLaunchAngularImpulse( pEntity, reason ); - - // Get the physics object (MUST have one) - IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject(); - if ( pPhysicsObject == NULL ) - { - Assert( 0 ); - return; - } - - // Affect the object - CRagdollProp *pRagdoll = dynamic_cast( pEntity ); - if ( pRagdoll == NULL ) - { -#ifdef HL2_EPISODIC - // The jeep being punted needs special force overrides - if ( reason == PHYSGUN_FORCE_PUNTED && pEntity->GetServerVehicle() ) - { - // We want the point to emanate low on the vehicle to move it along the ground, not to twist it - Vector vecFinalPos = vecHitPos; - vecFinalPos.z = pEntity->GetAbsOrigin().z; - pPhysicsObject->ApplyForceOffset( vVel, vecFinalPos ); - } - else - { - pPhysicsObject->AddVelocity( &vVel, &aVel ); - } -#else - - pPhysicsObject->AddVelocity( &vVel, &aVel ); - -#endif // HL2_EPISODIC - } - else - { - Vector vTempVel; - AngularImpulse vTempAVel; - - ragdoll_t *pRagdollPhys = pRagdoll->GetRagdoll( ); - for ( int j = 0; j < pRagdollPhys->listCount; ++j ) - { - pRagdollPhys->list[j].pObject->AddVelocity( &vVel, &aVel ); - } - } -} - - -//----------------------------------------------------------------------------- -// Punt non-physics -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::PuntRagdoll( CBaseEntity *pEntity, const Vector &vecForward, trace_t &tr ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - Pickup_OnPhysGunDrop( pEntity, pOwner, LAUNCHED_BY_CANNON ); - - CTakeDamageInfo info; - - Vector forward = vecForward; - info.SetAttacker( GetOwner() ); - info.SetInflictor( this ); - info.SetDamage( 0.0f ); - info.SetDamageType( DMG_PHYSGUN ); - pEntity->DispatchTraceAttack( info, forward, &tr ); - ApplyMultiDamage(); - - if ( Pickup_OnAttemptPhysGunPickup( pEntity, pOwner, PUNTED_BY_CANNON ) ) - { - Physgun_OnPhysGunPickup( pEntity, pOwner, PUNTED_BY_CANNON ); - - if( forward.z < 0 ) - { - //reflect, but flatten the trajectory out a bit so it's easier to hit standing targets - forward.z *= -0.65f; - } - - Vector vVel = forward * 1500; - AngularImpulse aVel = Pickup_PhysGunLaunchAngularImpulse( pEntity, PHYSGUN_FORCE_PUNTED ); - - CRagdollProp *pRagdoll = dynamic_cast( pEntity ); - ragdoll_t *pRagdollPhys = pRagdoll->GetRagdoll( ); - - int j; - for ( j = 0; j < pRagdollPhys->listCount; ++j ) - { - pRagdollPhys->list[j].pObject->AddVelocity( &vVel, NULL ); - } - } - - // Add recoil - QAngle recoil = QAngle( random->RandomFloat( 1.0f, 2.0f ), random->RandomFloat( -1.0f, 1.0f ), 0 ); - pOwner->ViewPunch( recoil ); - - //Explosion effect - DoEffect( EFFECT_LAUNCH, &tr.endpos ); - - PrimaryFireEffect(); - SendWeaponAnim( ACT_VM_SECONDARYATTACK ); - - m_nChangeState = ELEMENT_STATE_CLOSED; - m_flElementDebounce = gpGlobals->curtime + 0.5f; - m_flCheckSuppressTime = gpGlobals->curtime + 0.25f; - - // Don't allow the gun to regrab a thrown object!! - m_flNextSecondaryAttack = m_flNextPrimaryAttack = gpGlobals->curtime + 0.5f; -} - - -//----------------------------------------------------------------------------- -// Trace length -//----------------------------------------------------------------------------- -float CWeaponPhysCannon::TraceLength() -{ - if ( !IsMegaPhysCannon() ) - { - return physcannon_tracelength.GetFloat(); - } - - return physcannon_mega_tracelength.GetFloat(); -} - -//----------------------------------------------------------------------------- -// If there's any special rejection code you need to do per entity then do it here -// This is kinda nasty but I'd hate to move more physcannon related stuff into CBaseEntity -//----------------------------------------------------------------------------- -bool CWeaponPhysCannon::EntityAllowsPunts( CBaseEntity *pEntity ) -{ - if ( pEntity->HasSpawnFlags( SF_PHYSBOX_NEVER_PUNT ) ) - { - CPhysBox *pPhysBox = dynamic_cast(pEntity); - - if ( pPhysBox != NULL ) - { - if ( pPhysBox->HasSpawnFlags( SF_PHYSBOX_NEVER_PUNT ) ) - { - return false; - } - } - } - - if ( pEntity->HasSpawnFlags( SF_WEAPON_NO_PHYSCANNON_PUNT ) ) - { - CBaseCombatWeapon *pWeapon = dynamic_cast(pEntity); - - if ( pWeapon != NULL ) - { - if ( pWeapon->HasSpawnFlags( SF_WEAPON_NO_PHYSCANNON_PUNT ) ) - { - return false; - } - } - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -// This mode is a toggle. Primary fire one time to pick up a physics object. -// With an object held, click primary fire again to drop object. -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::PrimaryAttack( void ) -{ - if( m_flNextPrimaryAttack > gpGlobals->curtime ) - return; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - if( m_bActive ) - { - // Punch the object being held!! - Vector forward; - pOwner->EyeVectors( &forward ); - - // Validate the item is within punt range - CBaseEntity *pHeld = m_grabController.GetAttached(); - Assert( pHeld != NULL ); - - if ( pHeld != NULL ) - { - float heldDist = pHeld->CollisionProp()->CalcDistanceFromPoint(pOwner->WorldSpaceCenter() ); - - if ( heldDist > physcannon_tracelength.GetFloat() ) - { - // We can't punt this yet - DryFire(); - return; - } - } - - LaunchObject( forward, physcannon_maxforce.GetFloat() ); - - PrimaryFireEffect(); - SendWeaponAnim( ACT_VM_SECONDARYATTACK ); - return; - } - - // If not active, just issue a physics punch in the world. - m_flNextPrimaryAttack = gpGlobals->curtime + 0.5f; - - Vector forward; - pOwner->EyeVectors( &forward ); - - // NOTE: Notice we're *not* using the mega tracelength here - // when you have the mega cannon. Punting has shorter range. - Vector start, end; - start = pOwner->Weapon_ShootPosition(); - float flPuntDistance = physcannon_tracelength.GetFloat(); - VectorMA( start, flPuntDistance, forward, end ); - - trace_t tr; - UTIL_PhyscannonTraceHull( start, end, -Vector(8,8,8), Vector(8,8,8), pOwner, &tr ); - bool bValid = true; - CBaseEntity *pEntity = tr.m_pEnt; - if ( tr.fraction == 1 || !tr.m_pEnt || tr.m_pEnt->IsEFlagSet( EFL_NO_PHYSCANNON_INTERACTION ) ) - { - bValid = false; - } - else if ( (pEntity->GetMoveType() != MOVETYPE_VPHYSICS) && ( pEntity->m_takedamage == DAMAGE_NO ) ) - { - bValid = false; - } - - // If the entity we've hit is invalid, try a traceline instead - if ( !bValid ) - { - UTIL_PhyscannonTraceLine( start, end, pOwner, &tr ); - if ( tr.fraction == 1 || !tr.m_pEnt || tr.m_pEnt->IsEFlagSet( EFL_NO_PHYSCANNON_INTERACTION ) ) - { - if( hl2_episodic.GetBool() ) - { - // Try to find something in a very small cone. - CBaseEntity *pObject = FindObjectInCone( start, forward, physcannon_punt_cone.GetFloat() ); - - if( pObject ) - { - // Trace to the object. - UTIL_PhyscannonTraceLine( start, pObject->WorldSpaceCenter(), pOwner, &tr ); - - if( tr.m_pEnt && tr.m_pEnt == pObject && !(pObject->IsEFlagSet(EFL_NO_PHYSCANNON_INTERACTION)) ) - { - bValid = true; - pEntity = pObject; - } - } - } - } - else - { - bValid = true; - pEntity = tr.m_pEnt; - } - } - - if( !bValid ) - { - DryFire(); - return; - } - - // See if we hit something - if ( pEntity->GetMoveType() != MOVETYPE_VPHYSICS ) - { - if ( pEntity->m_takedamage == DAMAGE_NO ) - { - DryFire(); - return; - } - - if( GetOwner()->IsPlayer() && !IsMegaPhysCannon() ) - { - // Don't let the player zap any NPC's except regular antlions and headcrabs. - if( pEntity->IsNPC() && pEntity->Classify() != CLASS_HEADCRAB && !FClassnameIs(pEntity, "npc_antlion") ) - { - DryFire(); - return; - } - } - - if ( IsMegaPhysCannon() ) - { - if ( pEntity->IsNPC() && !pEntity->IsEFlagSet( EFL_NO_MEGAPHYSCANNON_RAGDOLL ) && pEntity->MyNPCPointer()->CanBecomeRagdoll() ) - { - CTakeDamageInfo info( pOwner, pOwner, 1.0f, DMG_GENERIC ); - CBaseEntity *pRagdoll = CreateServerRagdoll( pEntity->MyNPCPointer(), 0, info, COLLISION_GROUP_INTERACTIVE_DEBRIS, true ); - PhysSetEntityGameFlags( pRagdoll, FVPHYSICS_NO_SELF_COLLISIONS ); - pRagdoll->SetCollisionBounds( pEntity->CollisionProp()->OBBMins(), pEntity->CollisionProp()->OBBMaxs() ); - - // Necessary to cause it to do the appropriate death cleanup - CTakeDamageInfo ragdollInfo( pOwner, pOwner, 10000.0, DMG_PHYSGUN | DMG_REMOVENORAGDOLL ); - pEntity->TakeDamage( ragdollInfo ); - - PuntRagdoll( pRagdoll, forward, tr ); - return; - } - } - - PuntNonVPhysics( pEntity, forward, tr ); - } - else - { - if ( EntityAllowsPunts( pEntity) == false ) - { - DryFire(); - return; - } - - if ( !IsMegaPhysCannon() ) - { - if ( pEntity->VPhysicsIsFlesh( ) ) - { - DryFire(); - return; - } - PuntVPhysics( pEntity, forward, tr ); - } - else - { - if ( dynamic_cast(pEntity) ) - { - PuntRagdoll( pEntity, forward, tr ); - } - else - { - PuntVPhysics( pEntity, forward, tr ); - } - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Click secondary attack whilst holding an object to hurl it. -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::SecondaryAttack( void ) -{ - if ( m_flNextSecondaryAttack > gpGlobals->curtime ) - return; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - // See if we should drop a held item - if ( ( m_bActive ) && ( pOwner->m_afButtonPressed & IN_ATTACK2 ) ) - { - // Drop the held object - m_flNextPrimaryAttack = gpGlobals->curtime + 0.5; - m_flNextSecondaryAttack = gpGlobals->curtime + 0.5; - - DetachObject(); - - DoEffect( EFFECT_READY ); - - SendWeaponAnim( ACT_VM_PRIMARYATTACK ); - } - else - { - // Otherwise pick it up - FindObjectResult_t result = FindObject(); - switch ( result ) - { - case OBJECT_FOUND: - WeaponSound( SPECIAL1 ); - SendWeaponAnim( ACT_VM_PRIMARYATTACK ); - m_flNextSecondaryAttack = gpGlobals->curtime + 0.5f; - - // We found an object. Debounce the button - m_nAttack2Debounce |= pOwner->m_nButtons; - break; - - case OBJECT_NOT_FOUND: - m_flNextSecondaryAttack = gpGlobals->curtime + 0.1f; - CloseElements(); - break; - - case OBJECT_BEING_DETACHED: - m_flNextSecondaryAttack = gpGlobals->curtime + 0.01f; - break; - } - - DoEffect( EFFECT_HOLDING ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::WeaponIdle( void ) -{ - if ( HasWeaponIdleTimeElapsed() ) - { - if ( m_bActive ) - { - //Shake when holding an item - SendWeaponAnim( ACT_VM_RELOAD ); - } - else - { - //Otherwise idle simply - SendWeaponAnim( ACT_VM_IDLE ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pObject - -//----------------------------------------------------------------------------- -bool CWeaponPhysCannon::AttachObject( CBaseEntity *pObject, const Vector &vPosition ) -{ - if ( m_bActive ) - return false; - - if ( CanPickupObject( pObject ) == false ) - return false; - - m_grabController.SetIgnorePitch( false ); - m_grabController.SetAngleAlignment( 0 ); - - bool bKilledByGrab = false; - - bool bIsMegaPhysCannon = IsMegaPhysCannon(); - if ( bIsMegaPhysCannon ) - { - if ( pObject->IsNPC() && !pObject->IsEFlagSet( EFL_NO_MEGAPHYSCANNON_RAGDOLL ) ) - { - Assert( pObject->MyNPCPointer()->CanBecomeRagdoll() ); - CTakeDamageInfo info( GetOwner(), GetOwner(), 1.0f, DMG_GENERIC ); - CBaseEntity *pRagdoll = CreateServerRagdoll( pObject->MyNPCPointer(), 0, info, COLLISION_GROUP_INTERACTIVE_DEBRIS, true ); - PhysSetEntityGameFlags( pRagdoll, FVPHYSICS_NO_SELF_COLLISIONS ); - - pRagdoll->SetCollisionBounds( pObject->CollisionProp()->OBBMins(), pObject->CollisionProp()->OBBMaxs() ); - - // Necessary to cause it to do the appropriate death cleanup - CTakeDamageInfo ragdollInfo( GetOwner(), GetOwner(), 10000.0, DMG_PHYSGUN | DMG_REMOVENORAGDOLL ); - pObject->TakeDamage( ragdollInfo ); - - // Now we act on the ragdoll for the remainder of the time - pObject = pRagdoll; - bKilledByGrab = true; - } - } - - IPhysicsObject *pPhysics = pObject->VPhysicsGetObject(); - - // Must be valid - if ( !pPhysics ) - return false; - - CHL2_Player *pOwner = (CHL2_Player *)ToBasePlayer( GetOwner() ); - - m_bActive = true; - if( pOwner ) - { -#ifdef HL2_EPISODIC - CBreakableProp *pProp = dynamic_cast< CBreakableProp * >( pObject ); - - if ( pProp && pProp->HasInteraction( PROPINTER_PHYSGUN_CREATE_FLARE ) ) - { - pOwner->FlashlightTurnOff(); - } -#endif - - // NOTE: This can change the mass; so it must be done before max speed setting - Physgun_OnPhysGunPickup( pObject, pOwner, PICKED_UP_BY_CANNON ); - } - - // NOTE :This must happen after OnPhysGunPickup because that can change the mass - m_grabController.AttachEntity( pOwner, pObject, pPhysics, bIsMegaPhysCannon, vPosition, (!bKilledByGrab) ); - - if( pOwner ) - { - pOwner->EnableSprint( false ); - - float loadWeight = ( 1.0f - GetLoadPercentage() ); - float maxSpeed = hl2_walkspeed.GetFloat() + ( ( hl2_normspeed.GetFloat() - hl2_walkspeed.GetFloat() ) * loadWeight ); - - //Msg( "Load perc: %f -- Movement speed: %f/%f\n", loadWeight, maxSpeed, hl2_normspeed.GetFloat() ); - pOwner->SetMaxSpeed( maxSpeed ); - } - - // Don't drop again for a slight delay, in case they were pulling objects near them - m_flNextSecondaryAttack = gpGlobals->curtime + 0.4f; - - DoEffect( EFFECT_HOLDING ); - OpenElements(); - - if ( GetMotorSound() ) - { - (CSoundEnvelopeController::GetController()).Play( GetMotorSound(), 0.0f, 50 ); - (CSoundEnvelopeController::GetController()).SoundChangePitch( GetMotorSound(), 100, 0.5f ); - (CSoundEnvelopeController::GetController()).SoundChangeVolume( GetMotorSound(), 0.8f, 0.5f ); - } - -#if defined(HL2_DLL) - if( physcannon_right_turrets.GetBool() && pObject->ClassMatches("npc_turret_floor") ) - { - // We just picked up a turret. Is it already upright? - Vector vecUp; - Vector vecTrueUp(0,0,1); - pObject->GetVectors( NULL, NULL, &vecUp ); - float flDot = DotProduct( vecUp, vecTrueUp ); - - if( flDot < 0.5f ) - { - // The turret is NOT upright, so have the client help us by raising up the player's view. - m_flTimeForceView = gpGlobals->curtime + 1.0f; - } - } -#endif - - return true; -} - -void CWeaponPhysCannon::FindObjectTrace( CBasePlayer *pPlayer, trace_t *pTraceResult ) -{ - Vector forward; - pPlayer->EyeVectors( &forward ); - - // Setup our positions - Vector start = pPlayer->Weapon_ShootPosition(); - float testLength = TraceLength() * 4.0f; - Vector end = start + forward * testLength; - - if( IsMegaPhysCannon() && hl2_episodic.GetBool() ) - { - Vector vecAutoAimDir = pPlayer->GetAutoaimVector( 1.0f, testLength ); - end = start + vecAutoAimDir * testLength; - } - - // Try to find an object by looking straight ahead - UTIL_PhyscannonTraceLine( start, end, pPlayer, pTraceResult ); - - // Try again with a hull trace - if ( !pTraceResult->DidHitNonWorldEntity() ) - { - UTIL_PhyscannonTraceHull( start, end, -Vector(4,4,4), Vector(4,4,4), pPlayer, pTraceResult ); - } -} - - -CWeaponPhysCannon::FindObjectResult_t CWeaponPhysCannon::FindObject( void ) -{ - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - Assert( pPlayer ); - if ( pPlayer == NULL ) - return OBJECT_NOT_FOUND; - - trace_t tr; - FindObjectTrace( pPlayer, &tr ); - CBaseEntity *pEntity = tr.m_pEnt ? tr.m_pEnt->GetRootMoveParent() : NULL; - bool bAttach = false; - bool bPull = false; - - // If we hit something, pick it up or pull it - if ( ( tr.fraction != 1.0f ) && ( tr.m_pEnt ) && ( tr.m_pEnt->IsWorld() == false ) ) - { - // Attempt to attach if within range - if ( tr.fraction <= 0.25f ) - { - bAttach = true; - } - else if ( tr.fraction > 0.25f ) - { - bPull = true; - } - } - - Vector forward; - pPlayer->EyeVectors( &forward ); - - // Setup our positions - Vector start = pPlayer->Weapon_ShootPosition(); - float testLength = TraceLength() * 4.0f; - - // Find anything within a general cone in front - CBaseEntity *pConeEntity = NULL; - if ( !IsMegaPhysCannon() ) - { - if (!bAttach && !bPull) - { - pConeEntity = FindObjectInCone( start, forward, physcannon_cone.GetFloat() ); - } - } - else - { - pConeEntity = MegaPhysCannonFindObjectInCone( start, forward, - physcannon_cone.GetFloat(), physcannon_ball_cone.GetFloat(), bAttach || bPull ); - } - - if ( pConeEntity ) - { - pEntity = pConeEntity; - - // If the object is near, grab it. Else, pull it a bit. - if ( pEntity->WorldSpaceCenter().DistToSqr( start ) <= (testLength * testLength) ) - { - bAttach = true; - } - else - { - bPull = true; - } - } - - if ( CanPickupObject( pEntity ) == false ) - { - CBaseEntity *pNewObject = Pickup_OnFailedPhysGunPickup( pEntity, start ); - - if ( pNewObject && CanPickupObject( pNewObject ) ) - { - pEntity = pNewObject; - } - else - { - // Make a noise to signify we can't pick this up - if ( !m_flLastDenySoundPlayed ) - { - m_flLastDenySoundPlayed = true; - WeaponSound( SPECIAL3 ); - } - - return OBJECT_NOT_FOUND; - } - } - - // Check to see if the object is constrained + needs to be ripped off... - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( !Pickup_OnAttemptPhysGunPickup( pEntity, pOwner, PICKED_UP_BY_CANNON ) ) - return OBJECT_BEING_DETACHED; - - if ( bAttach ) - { - return AttachObject( pEntity, tr.endpos ) ? OBJECT_FOUND : OBJECT_NOT_FOUND; - } - - if ( !bPull ) - return OBJECT_NOT_FOUND; - - // FIXME: This needs to be run through the CanPickupObject logic - IPhysicsObject *pObj = pEntity->VPhysicsGetObject(); - if ( !pObj ) - return OBJECT_NOT_FOUND; - - // If we're too far, simply start to pull the object towards us - Vector pullDir = start - pEntity->WorldSpaceCenter(); - VectorNormalize( pullDir ); - pullDir *= IsMegaPhysCannon() ? physcannon_mega_pullforce.GetFloat() : physcannon_pullforce.GetFloat(); - - float mass = PhysGetEntityMass( pEntity ); - if ( mass < 50.0f ) - { - pullDir *= (mass + 0.5) * (1/50.0f); - } - - // Nudge it towards us - pObj->ApplyForceCenter( pullDir ); - return OBJECT_NOT_FOUND; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CBaseEntity *CWeaponPhysCannon::MegaPhysCannonFindObjectInCone( const Vector &vecOrigin, - const Vector &vecDir, float flCone, float flCombineBallCone, bool bOnlyCombineBalls ) -{ - // Find the nearest physics-based item in a cone in front of me. - CBaseEntity *list[1024]; - float flMaxDist = TraceLength() + 1.0; - float flNearestDist = flMaxDist; - bool bNearestIsCombineBall = bOnlyCombineBalls ? true : false; - Vector mins = vecOrigin - Vector( flNearestDist, flNearestDist, flNearestDist ); - Vector maxs = vecOrigin + Vector( flNearestDist, flNearestDist, flNearestDist ); - - CBaseEntity *pNearest = NULL; - - int count = UTIL_EntitiesInBox( list, 1024, mins, maxs, 0 ); - for( int i = 0 ; i < count ; i++ ) - { - if ( !list[ i ]->VPhysicsGetObject() ) - continue; - - bool bIsCombineBall = FClassnameIs( list[ i ], "prop_combine_ball" ); - if ( !bIsCombineBall && bNearestIsCombineBall ) - continue; - - // Closer than other objects - Vector los; - VectorSubtract( list[ i ]->WorldSpaceCenter(), vecOrigin, los ); - float flDist = VectorNormalize( los ); - - if ( !bIsCombineBall || bNearestIsCombineBall ) - { - // Closer than other objects - if( flDist >= flNearestDist ) - continue; - - // Cull to the cone - if ( DotProduct( los, vecDir ) <= flCone ) - continue; - } - else - { - // Close enough? - if ( flDist >= flMaxDist ) - continue; - - // Cull to the cone - if ( DotProduct( los, vecDir ) <= flCone ) - continue; - - // NOW: If it's either closer than nearest dist or within the ball cone, use it! - if ( (flDist > flNearestDist) && (DotProduct( los, vecDir ) <= flCombineBallCone) ) - continue; - } - - // Make sure it isn't occluded! - trace_t tr; - UTIL_PhyscannonTraceLine( vecOrigin, list[ i ]->WorldSpaceCenter(), GetOwner(), &tr ); - if( tr.m_pEnt == list[ i ] ) - { - flNearestDist = flDist; - pNearest = list[ i ]; - bNearestIsCombineBall = bIsCombineBall; - } - } - - return pNearest; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CBaseEntity *CWeaponPhysCannon::FindObjectInCone( const Vector &vecOrigin, const Vector &vecDir, float flCone ) -{ - // Find the nearest physics-based item in a cone in front of me. - CBaseEntity *list[256]; - float flNearestDist = physcannon_tracelength.GetFloat() + 1.0; //Use regular distance. - Vector mins = vecOrigin - Vector( flNearestDist, flNearestDist, flNearestDist ); - Vector maxs = vecOrigin + Vector( flNearestDist, flNearestDist, flNearestDist ); - - CBaseEntity *pNearest = NULL; - - int count = UTIL_EntitiesInBox( list, 256, mins, maxs, 0 ); - for( int i = 0 ; i < count ; i++ ) - { - if ( !list[ i ]->VPhysicsGetObject() ) - continue; - - // Closer than other objects - Vector los = ( list[ i ]->WorldSpaceCenter() - vecOrigin ); - float flDist = VectorNormalize( los ); - if( flDist >= flNearestDist ) - continue; - - // Cull to the cone - if ( DotProduct( los, vecDir ) <= flCone ) - continue; - - // Make sure it isn't occluded! - trace_t tr; - UTIL_PhyscannonTraceLine( vecOrigin, list[ i ]->WorldSpaceCenter(), GetOwner(), &tr ); - if( tr.m_pEnt == list[ i ] ) - { - flNearestDist = flDist; - pNearest = list[ i ]; - } - } - - return pNearest; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CGrabController::UpdateObject( CBasePlayer *pPlayer, float flError ) -{ - CBaseEntity *pEntity = GetAttached(); - if ( !pEntity || ComputeError() > flError || pPlayer->GetGroundEntity() == pEntity || !pEntity->VPhysicsGetObject() ) - { - return false; - } - - //Adrian: Oops, our object became motion disabled, let go! - IPhysicsObject *pPhys = pEntity->VPhysicsGetObject(); - if ( pPhys && pPhys->IsMoveable() == false ) - { - return false; - } - - Vector forward, right, up; - QAngle playerAngles = pPlayer->EyeAngles(); - AngleVectors( playerAngles, &forward, &right, &up ); - - if ( HL2GameRules()->MegaPhyscannonActive() ) - { - Vector los = ( pEntity->WorldSpaceCenter() - pPlayer->Weapon_ShootPosition() ); - VectorNormalize( los ); - - float flDot = DotProduct( los, forward ); - - //Let go of the item if we turn around too fast. - if ( flDot <= 0.35f ) - return false; - } - - float pitch = AngleDistance(playerAngles.x,0); - - if( !m_bAllowObjectOverhead ) - { - playerAngles.x = clamp( pitch, -75, 75 ); - } - else - { - playerAngles.x = clamp( pitch, -90, 75 ); - } - - - - // Now clamp a sphere of object radius at end to the player's bbox - Vector radial = physcollision->CollideGetExtent( pPhys->GetCollide(), vec3_origin, pEntity->GetAbsAngles(), -forward ); - Vector player2d = pPlayer->CollisionProp()->OBBMaxs(); - float playerRadius = player2d.Length2D(); - float radius = playerRadius + fabs(DotProduct( forward, radial )); - - float distance = 24 + ( radius * 2.0f ); - - // Add the prop's distance offset - distance += m_flDistanceOffset; - - Vector start = pPlayer->Weapon_ShootPosition(); - Vector end = start + ( forward * distance ); - - trace_t tr; - CTraceFilterSkipTwoEntities traceFilter( pPlayer, pEntity, COLLISION_GROUP_NONE ); - Ray_t ray; - ray.Init( start, end ); - enginetrace->TraceRay( ray, MASK_SOLID_BRUSHONLY, &traceFilter, &tr ); - - if ( tr.fraction < 0.5 ) - { - end = start + forward * (radius*0.5f); - } - else if ( tr.fraction <= 1.0f ) - { - end = start + forward * ( distance - radius ); - } - Vector playerMins, playerMaxs, nearest; - pPlayer->CollisionProp()->WorldSpaceAABB( &playerMins, &playerMaxs ); - Vector playerLine = pPlayer->CollisionProp()->WorldSpaceCenter(); - CalcClosestPointOnLine( end, playerLine+Vector(0,0,playerMins.z), playerLine+Vector(0,0,playerMaxs.z), nearest, NULL ); - - if( !m_bAllowObjectOverhead ) - { - Vector delta = end - nearest; - float len = VectorNormalize(delta); - if ( len < radius ) - { - end = nearest + radius * delta; - } - } - - //Show overlays of radius - if ( g_debug_physcannon.GetBool() ) - { - NDebugOverlay::Box( end, -Vector( 2,2,2 ), Vector(2,2,2), 0, 255, 0, true, 0 ); - - NDebugOverlay::Box( GetAttached()->WorldSpaceCenter(), - -Vector( radius, radius, radius), - Vector( radius, radius, radius ), - 255, 0, 0, - true, - 0.0f ); - } - - QAngle angles = TransformAnglesFromPlayerSpace( m_attachedAnglesPlayerSpace, pPlayer ); - - // If it has a preferred orientation, update to ensure we're still oriented correctly. - Pickup_GetPreferredCarryAngles( pEntity, pPlayer, pPlayer->EntityToWorldTransform(), angles ); - - // We may be holding a prop that has preferred carry angles - if ( m_bHasPreferredCarryAngles ) - { - matrix3x4_t tmp; - ComputePlayerMatrix( pPlayer, tmp ); - angles = TransformAnglesToWorldSpace( m_vecPreferredCarryAngles, tmp ); - } - - matrix3x4_t attachedToWorld; - Vector offset; - AngleMatrix( angles, attachedToWorld ); - VectorRotate( m_attachedPositionObjectSpace, attachedToWorld, offset ); - - SetTargetPosition( end - offset, angles ); - - return true; -} - -void CWeaponPhysCannon::UpdateObject( void ) -{ - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - Assert( pPlayer ); - - float flError = IsMegaPhysCannon() ? 18 : 12; - if ( !m_grabController.UpdateObject( pPlayer, flError ) ) - { - DetachObject(); - return; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DetachObject( bool playSound, bool wasLaunched ) -{ - if ( m_bActive == false ) - return; - - CHL2_Player *pOwner = (CHL2_Player *)ToBasePlayer( GetOwner() ); - if( pOwner != NULL ) - { - pOwner->EnableSprint( true ); - pOwner->SetMaxSpeed( hl2_normspeed.GetFloat() ); - - if( wasLaunched ) - { - pOwner->RumbleEffect( RUMBLE_357, 0, RUMBLE_FLAG_RESTART ); - } - } - - CBaseEntity *pObject = m_grabController.GetAttached(); - - m_grabController.DetachEntity( wasLaunched ); - - if ( pObject != NULL ) - { - Pickup_OnPhysGunDrop( pObject, pOwner, wasLaunched ? LAUNCHED_BY_CANNON : DROPPED_BY_CANNON ); - } - - // Stop our looping sound - if ( GetMotorSound() ) - { - (CSoundEnvelopeController::GetController()).SoundChangeVolume( GetMotorSound(), 0.0f, 1.0f ); - (CSoundEnvelopeController::GetController()).SoundChangePitch( GetMotorSound(), 50, 1.0f ); - } - - m_bActive = false; - - if ( playSound ) - { - //Play the detach sound - WeaponSound( MELEE_MISS ); - } - - RecordThrownObject( pObject ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::ItemPreFrame() -{ - BaseClass::ItemPreFrame(); - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - m_flElementPosition = UTIL_Approach( m_flElementDestination, m_flElementPosition, 0.1f ); - - CBaseViewModel *vm = pOwner->GetViewModel(); - - if ( vm != NULL ) - { - // This has to happen here because of how the SetModel interacts with the caching at startup - if ( m_sbStaticPoseParamsLoaded == false ) - { - m_poseActive = LookupPoseParameter( "active" ); - m_sbStaticPoseParamsLoaded = true; - } - - vm->SetPoseParameter( m_poseActive, m_flElementPosition ); - } - - // Update the object if the weapon is switched on. - if( m_bActive ) - { - UpdateObject(); - } - - if( gpGlobals->curtime >= m_flTimeNextObjectPurge ) - { - PurgeThrownObjects(); - m_flTimeNextObjectPurge = gpGlobals->curtime + 0.5f; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::CheckForTarget( void ) -{ - //See if we're suppressing this - if ( m_flCheckSuppressTime > gpGlobals->curtime ) - return; - - // holstered - if ( IsEffectActive( EF_NODRAW ) ) - return; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - if ( m_bActive ) - return; - - trace_t tr; - FindObjectTrace( pOwner, &tr ); - - if ( ( tr.fraction != 1.0f ) && ( tr.m_pEnt != NULL ) ) - { - float dist = (tr.endpos - tr.startpos).Length(); - if ( dist <= TraceLength() ) - { - // FIXME: Try just having the elements always open when pointed at a physics object - if ( CanPickupObject( tr.m_pEnt ) || Pickup_ForcePhysGunOpen( tr.m_pEnt, pOwner ) ) - // if ( ( tr.m_pEnt->VPhysicsGetObject() != NULL ) && ( tr.m_pEnt->GetMoveType() == MOVETYPE_VPHYSICS ) ) - { - m_nChangeState = ELEMENT_STATE_NONE; - OpenElements(); - return; - } - } - } - - // Close the elements after a delay to prevent overact state switching - if ( ( m_flElementDebounce < gpGlobals->curtime ) && ( m_nChangeState == ELEMENT_STATE_NONE ) ) - { - m_nChangeState = ELEMENT_STATE_CLOSED; - m_flElementDebounce = gpGlobals->curtime + 0.5f; - } -} - - -//----------------------------------------------------------------------------- -// Begin upgrading! -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::BeginUpgrade() -{ - if ( IsMegaPhysCannon() ) - return; - - if ( m_bIsCurrentlyUpgrading ) - return; - - SetSequence( SelectWeightedSequence( ACT_PHYSCANNON_UPGRADE ) ); - ResetSequenceInfo(); - - m_bIsCurrentlyUpgrading = true; - - SetContextThink( &CWeaponPhysCannon::WaitForUpgradeThink, gpGlobals->curtime + 6.0f, s_pWaitForUpgradeContext ); - - EmitSound( "WeaponDissolve.Charge" ); - - // Bloat our bounds - CollisionProp()->UseTriggerBounds( true, 32.0f ); - - // Turn on the new skin - m_nSkin = MEGACANNON_SKIN; -} - - -//----------------------------------------------------------------------------- -// Wait until we're done upgrading -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::WaitForUpgradeThink() -{ - Assert( m_bIsCurrentlyUpgrading ); - - StudioFrameAdvance(); - if ( !IsActivityFinished() ) - { - SetContextThink( &CWeaponPhysCannon::WaitForUpgradeThink, gpGlobals->curtime + 0.1f, s_pWaitForUpgradeContext ); - return; - } - - if ( !GlobalEntity_IsInTable( "super_phys_gun" ) ) - { - GlobalEntity_Add( MAKE_STRING("super_phys_gun"), gpGlobals->mapname, GLOBAL_ON ); - } - else - { - GlobalEntity_SetState( MAKE_STRING("super_phys_gun"), GLOBAL_ON ); - } - m_bIsCurrentlyUpgrading = false; - - // This is necessary to get the effects to look different - DestroyEffects(); - - // HACK: Hacky notification back to the level that we've finish upgrading - CBaseEntity *pEnt = gEntList.FindEntityByName( NULL, "script_physcannon_upgrade" ); - if ( pEnt ) - { - variant_t emptyVariant; - pEnt->AcceptInput( "Trigger", this, this, emptyVariant, 0 ); - } - - StopSound( "WeaponDissolve.Charge" ); - - // Re-enable weapon pickup - AddSolidFlags( FSOLID_TRIGGER ); - - SetContextThink( NULL, gpGlobals->curtime, s_pWaitForUpgradeContext ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DoEffectIdle( void ) -{ - if ( IsEffectActive( EF_NODRAW ) ) - { - StopEffects(); - return; - } - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - if ( m_bPhyscannonState != IsMegaPhysCannon() ) - { - DestroyEffects(); - StartEffects(); - - m_bPhyscannonState = IsMegaPhysCannon(); - - //This means we just switched to regular physcannon this frame. - if ( m_bPhyscannonState == false ) - { - EmitSound( "Weapon_Physgun.Off" ); - -#ifdef HL2_EPISODIC - ForceDrop(); - - CHL2_Player *pPlayer = dynamic_cast( pOwner ); - - if ( pPlayer ) - { - pPlayer->StartArmorReduction(); - } -#endif - - CCitadelEnergyCore *pCore = static_cast( CreateEntityByName( "env_citadel_energy_core" ) ); - - if ( pCore == NULL ) - return; - - CBaseAnimating *pBeamEnt = pOwner->GetViewModel(); - - if ( pBeamEnt ) - { - int iAttachment = pBeamEnt->LookupAttachment( "muzzle" ); - - Vector vOrigin; - QAngle vAngle; - - pBeamEnt->GetAttachment( iAttachment, vOrigin, vAngle ); - - pCore->SetAbsOrigin( vOrigin ); - pCore->SetAbsAngles( vAngle ); - - DispatchSpawn( pCore ); - pCore->Activate(); - - pCore->SetParent( pBeamEnt, iAttachment ); - pCore->SetScale( 2.5f ); - - variant_t variant; - variant.SetFloat( 1.0f ); - - g_EventQueue.AddEvent( pCore, "StartDischarge", 0, pOwner, pOwner ); - g_EventQueue.AddEvent( pCore, "Stop", variant, 1, pOwner, pOwner ); - - pCore->SetThink ( &CCitadelEnergyCore::SUB_Remove ); - pCore->SetNextThink( gpGlobals->curtime + 10.0f ); - - m_nSkin = 0; - } - } - } - - float flScaleFactor = SpriteScaleFactor(); - - // Flicker the end sprites - if ( ( m_hEndSprites[0] != NULL ) && ( m_hEndSprites[1] != NULL ) ) - { - //Make the end points flicker as fast as possible - //FIXME: Make this a property of the CSprite class! - for ( int i = 0; i < 2; i++ ) - { - m_hEndSprites[i]->SetBrightness( random->RandomInt( 200, 255 ) ); - m_hEndSprites[i]->SetScale( random->RandomFloat( 0.1, 0.15 ) * flScaleFactor ); - } - } - - // Flicker the glow sprites - for ( int i = 0; i < NUM_SPRITES; i++ ) - { - if ( m_hGlowSprites[i] == NULL ) - continue; - - if ( IsMegaPhysCannon() ) - { - m_hGlowSprites[i]->SetBrightness( random->RandomInt( 32, 48 ) ); - m_hGlowSprites[i]->SetScale( random->RandomFloat( 0.15, 0.2 ) * flScaleFactor ); - } - else - { - m_hGlowSprites[i]->SetBrightness( random->RandomInt( 16, 24 ) ); - m_hGlowSprites[i]->SetScale( random->RandomFloat( 0.3, 0.35 ) * flScaleFactor ); - } - } - - // Only do these effects on the mega-cannon - if ( IsMegaPhysCannon() ) - { - // Randomly arc between the elements and core - if ( random->RandomInt( 0, 100 ) == 0 && !engine->IsPaused() ) - { - CBeam *pBeam = CBeam::BeamCreate( MEGACANNON_BEAM_SPRITE, 1 ); - - CBaseEntity *pBeamEnt = pOwner->GetViewModel(); - pBeam->EntsInit( pBeamEnt, pBeamEnt ); - - int startAttachment; - int sprite; - - if ( random->RandomInt( 0, 1 ) ) - { - startAttachment = LookupAttachment( "fork1t" ); - sprite = 0; - } - else - { - startAttachment = LookupAttachment( "fork2t" ); - sprite = 1; - } - - int endAttachment = 1; - - pBeam->SetStartAttachment( startAttachment ); - pBeam->SetEndAttachment( endAttachment ); - pBeam->SetNoise( random->RandomFloat( 8.0f, 16.0f ) ); - pBeam->SetColor( 255, 255, 255 ); - pBeam->SetScrollRate( 25 ); - pBeam->SetBrightness( 128 ); - pBeam->SetWidth( 1 ); - pBeam->SetEndWidth( random->RandomFloat( 2, 8 ) ); - - float lifetime = random->RandomFloat( 0.2f, 0.4f ); - - pBeam->LiveForTime( lifetime ); - - if ( m_hEndSprites[sprite] != NULL ) - { - // Turn on the sprite for awhile - m_hEndSprites[sprite]->TurnOn(); - m_flEndSpritesOverride[sprite] = gpGlobals->curtime + lifetime; - EmitSound( "Weapon_MegaPhysCannon.ChargeZap" ); - } - } - - if ( m_hCenterSprite != NULL ) - { - if ( m_EffectState == EFFECT_HOLDING ) - { - m_hCenterSprite->SetBrightness( random->RandomInt( 32, 64 ) ); - m_hCenterSprite->SetScale( random->RandomFloat( 0.2, 0.25 ) * flScaleFactor ); - } - else - { - m_hCenterSprite->SetBrightness( random->RandomInt( 32, 64 ) ); - m_hCenterSprite->SetScale( random->RandomFloat( 0.125, 0.15 ) * flScaleFactor ); - } - } - - if ( m_hBlastSprite != NULL ) - { - if ( m_EffectState == EFFECT_HOLDING ) - { - m_hBlastSprite->SetBrightness( random->RandomInt( 125, 150 ) ); - m_hBlastSprite->SetScale( random->RandomFloat( 0.125, 0.15 ) * flScaleFactor ); - } - else - { - m_hBlastSprite->SetBrightness( random->RandomInt( 32, 64 ) ); - m_hBlastSprite->SetScale( random->RandomFloat( 0.075, 0.15 ) * flScaleFactor ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Update our idle effects even when deploying -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::ItemBusyFrame( void ) -{ - DoEffectIdle(); - - BaseClass::ItemBusyFrame(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::ItemPostFrame() -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( pOwner == NULL ) - { - // We found an object. Debounce the button - m_nAttack2Debounce = 0; - return; - } - - //Check for object in pickup range - if ( m_bActive == false ) - { - CheckForTarget(); - - if ( ( m_flElementDebounce < gpGlobals->curtime ) && ( m_nChangeState != ELEMENT_STATE_NONE ) ) - { - if ( m_nChangeState == ELEMENT_STATE_OPEN ) - { - OpenElements(); - } - else if ( m_nChangeState == ELEMENT_STATE_CLOSED ) - { - CloseElements(); - } - - m_nChangeState = ELEMENT_STATE_NONE; - } - } - - // NOTE: Attack2 will be considered to be pressed until the first item is picked up. - int nAttack2Mask = pOwner->m_nButtons & (~m_nAttack2Debounce); - if ( nAttack2Mask & IN_ATTACK2 ) - { - SecondaryAttack(); - } - else - { - // Reset our debouncer - m_flLastDenySoundPlayed = false; - - if ( m_bActive == false ) - { - DoEffect( EFFECT_READY ); - } - } - - if (( pOwner->m_nButtons & IN_ATTACK2 ) == 0 ) - { - m_nAttack2Debounce = 0; - } - - if ( pOwner->m_nButtons & IN_ATTACK ) - { - PrimaryAttack(); - } - else - { - WeaponIdle(); - } - - if ( hl2_episodic.GetBool() == true ) - { - if ( IsMegaPhysCannon() ) - { - if ( !( pOwner->m_nButtons & IN_ATTACK ) ) - { - m_flNextPrimaryAttack = gpGlobals->curtime; - } - } - } - - // Update our idle effects (flickers, etc) - DoEffectIdle(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -#define PHYSCANNON_DANGER_SOUND_RADIUS 128 - -void CWeaponPhysCannon::LaunchObject( const Vector &vecDir, float flForce ) -{ - // FIRE!!! - if( m_grabController.GetAttached() ) - { - CBaseEntity *pObject = m_grabController.GetAttached(); - - gamestats->Event_Punted( pObject ); - - DetachObject( false, true ); - - // Trace ahead a bit and make a chain of danger sounds ahead of the phys object - // to scare potential targets - trace_t tr; - Vector vecStart = pObject->GetAbsOrigin(); - Vector vecSpot; - int iLength; - int i; - - UTIL_TraceLine( vecStart, vecStart + vecDir * flForce, MASK_SHOT, pObject, COLLISION_GROUP_NONE, &tr ); - iLength = (int)((tr.startpos - tr.endpos).Length()); - vecSpot = vecStart + vecDir * PHYSCANNON_DANGER_SOUND_RADIUS; - - for( i = PHYSCANNON_DANGER_SOUND_RADIUS ; i < iLength ; i += PHYSCANNON_DANGER_SOUND_RADIUS ) - { - CSoundEnt::InsertSound( SOUND_PHYSICS_DANGER, vecSpot, PHYSCANNON_DANGER_SOUND_RADIUS, 0.5, pObject ); - vecSpot = vecSpot + ( vecDir * PHYSCANNON_DANGER_SOUND_RADIUS ); - } - - // Launch - ApplyVelocityBasedForce( pObject, vecDir, tr.endpos, PHYSGUN_FORCE_LAUNCHED ); - - // Don't allow the gun to regrab a thrown object!! - m_flNextSecondaryAttack = m_flNextPrimaryAttack = gpGlobals->curtime + 0.5; - - Vector center = pObject->WorldSpaceCenter(); - - //Do repulse effect - DoEffect( EFFECT_LAUNCH, ¢er ); - } - - // Stop our looping sound - if ( GetMotorSound() ) - { - (CSoundEnvelopeController::GetController()).SoundChangeVolume( GetMotorSound(), 0.0f, 1.0f ); - (CSoundEnvelopeController::GetController()).SoundChangePitch( GetMotorSound(), 50, 1.0f ); - } - - //Close the elements and suppress checking for a bit - m_nChangeState = ELEMENT_STATE_CLOSED; - m_flElementDebounce = gpGlobals->curtime + 0.1f; - m_flCheckSuppressTime = gpGlobals->curtime + 0.25f; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTarget - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponPhysCannon::CanPickupObject( CBaseEntity *pTarget ) -{ - if ( pTarget == NULL ) - return false; - - if ( pTarget->GetBaseAnimating() && pTarget->GetBaseAnimating()->IsDissolving() ) - return false; - - if ( pTarget->HasSpawnFlags( SF_PHYSBOX_ALWAYS_PICK_UP ) || pTarget->HasSpawnFlags( SF_PHYSBOX_NEVER_PICK_UP ) ) - { - // It may seem strange to check this spawnflag before we know the class of this object, since the - // spawnflag only applies to func_physbox, but it can act as a filter of sorts to reduce the number - // of irrelevant entities that fall through to this next casting check, which is slower. - CPhysBox *pPhysBox = dynamic_cast(pTarget); - - if ( pPhysBox != NULL ) - { - if ( pTarget->HasSpawnFlags( SF_PHYSBOX_NEVER_PICK_UP ) ) - return false; - else - return true; - } - } - - if ( pTarget->HasSpawnFlags(SF_PHYSPROP_ALWAYS_PICK_UP) ) - { - // It may seem strange to check this spawnflag before we know the class of this object, since the - // spawnflag only applies to func_physbox, but it can act as a filter of sorts to reduce the number - // of irrelevant entities that fall through to this next casting check, which is slower. - CPhysicsProp *pPhysProp = dynamic_cast(pTarget); - if ( pPhysProp != NULL ) - return true; - } - - if ( pTarget->IsEFlagSet( EFL_NO_PHYSCANNON_INTERACTION ) ) - return false; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( pOwner && pOwner->GetGroundEntity() == pTarget ) - return false; - - if ( !IsMegaPhysCannon() ) - { - if ( pTarget->VPhysicsIsFlesh( ) ) - return false; - return CBasePlayer::CanPickupObject( pTarget, physcannon_maxmass.GetFloat(), 0 ); - } - - if ( pTarget->IsNPC() && pTarget->MyNPCPointer()->CanBecomeRagdoll() ) - return true; - - if ( dynamic_cast(pTarget) ) - return true; - - return CBasePlayer::CanPickupObject( pTarget, 0, 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::OpenElements( void ) -{ - if ( m_bOpen ) - return; - - WeaponSound( SPECIAL2 ); - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - if( !IsMegaPhysCannon() ) - { - pOwner->RumbleEffect( RUMBLE_PHYSCANNON_OPEN, 0, RUMBLE_FLAG_RESTART ); - } - - if ( m_flElementPosition < 0.0f ) - m_flElementPosition = 0.0f; - - m_flElementDestination = 1.0f; - - SendWeaponAnim( ACT_VM_IDLE ); - - m_bOpen = true; - - DoEffect( EFFECT_READY ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::CloseElements( void ) -{ - // The mega cannon cannot be closed! - if ( IsMegaPhysCannon() ) - { - OpenElements(); - return; - } - - if ( m_bOpen == false ) - return; - - WeaponSound( MELEE_HIT ); - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - pOwner->RumbleEffect(RUMBLE_PHYSCANNON_OPEN, 0, RUMBLE_FLAG_STOP); - - if ( m_flElementPosition > 1.0f ) - m_flElementPosition = 1.0f; - - m_flElementDestination = 0.0f; - - SendWeaponAnim( ACT_VM_IDLE ); - - m_bOpen = false; - - if ( GetMotorSound() ) - { - (CSoundEnvelopeController::GetController()).SoundChangeVolume( GetMotorSound(), 0.0f, 1.0f ); - (CSoundEnvelopeController::GetController()).SoundChangePitch( GetMotorSound(), 50, 1.0f ); - } - - DoEffect( EFFECT_CLOSED ); -} - -#define PHYSCANNON_MAX_MASS 500 - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CWeaponPhysCannon::GetLoadPercentage( void ) -{ - float loadWeight = m_grabController.GetLoadWeight(); - loadWeight /= physcannon_maxmass.GetFloat(); - loadWeight = clamp( loadWeight, 0.0f, 1.0f ); - return loadWeight; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CSoundPatch -//----------------------------------------------------------------------------- -CSoundPatch *CWeaponPhysCannon::GetMotorSound( void ) -{ - if ( m_sndMotor == NULL ) - { - CPASAttenuationFilter filter( this ); - - if ( IsMegaPhysCannon() ) - { - m_sndMotor = (CSoundEnvelopeController::GetController()).SoundCreate( filter, entindex(), CHAN_STATIC, "Weapon_MegaPhysCannon.HoldSound", ATTN_NORM ); - } - else - { - m_sndMotor = (CSoundEnvelopeController::GetController()).SoundCreate( filter, entindex(), CHAN_STATIC, "Weapon_PhysCannon.HoldSound", ATTN_NORM ); - } - } - - return m_sndMotor; -} - - -//----------------------------------------------------------------------------- -// Shuts down sounds -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::StopLoopingSounds() -{ - if ( m_sndMotor != NULL ) - { - (CSoundEnvelopeController::GetController()).SoundDestroy( m_sndMotor ); - m_sndMotor = NULL; - } - - BaseClass::StopLoopingSounds(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DestroyEffects( void ) -{ - //Turn off main glow - if ( m_hCenterSprite != NULL ) - { - UTIL_Remove( m_hCenterSprite ); - m_hCenterSprite = NULL; - } - - if ( m_hBlastSprite != NULL ) - { - UTIL_Remove( m_hBlastSprite ); - m_hBlastSprite = NULL; - } - - // Turn off beams - for ( int i = 0; i < NUM_BEAMS; i++ ) - { - if ( m_hBeams[i] != NULL ) - { - UTIL_Remove( m_hBeams[i] ); - m_hBeams[i] = NULL; - } - } - - // Turn off sprites - for ( int i = 0; i < NUM_SPRITES; i++ ) - { - if ( m_hGlowSprites[i] != NULL ) - { - UTIL_Remove( m_hGlowSprites[i] ); - m_hGlowSprites[i] = NULL; - } - } - - for ( int i = 0; i < 2; i++ ) - { - if ( m_hEndSprites[i] != NULL ) - { - UTIL_Remove( m_hEndSprites[i] ); - m_hEndSprites[i] = NULL; - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::StopEffects( bool stopSound ) -{ - // Turn off our effect state - DoEffect( EFFECT_NONE ); - - //Turn off main glow - if ( m_hCenterSprite != NULL ) - { - m_hCenterSprite->TurnOff(); - } - - if ( m_hBlastSprite != NULL ) - { - m_hBlastSprite->TurnOff(); - } - - //Turn off beams - for ( int i = 0; i < NUM_BEAMS; i++ ) - { - if ( m_hBeams[i] != NULL ) - { - m_hBeams[i]->SetBrightness( 0 ); - } - } - - //Turn off sprites - for ( int i = 0; i < NUM_SPRITES; i++ ) - { - if ( m_hGlowSprites[i] != NULL ) - { - m_hGlowSprites[i]->TurnOff(); - } - } - - for ( int i = 0; i < 2; i++ ) - { - if ( m_hEndSprites[i] != NULL ) - { - m_hEndSprites[i]->TurnOff(); - } - } - - //Shut off sounds - if ( stopSound && GetMotorSound() != NULL ) - { - (CSoundEnvelopeController::GetController()).SoundFadeOut( GetMotorSound(), 0.1f ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::StartEffects( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( pOwner == NULL ) - return; - - bool bIsMegaCannon = IsMegaPhysCannon(); - - int i; - float flScaleFactor = SpriteScaleFactor(); - CBaseEntity *pBeamEnt = pOwner->GetViewModel(); - - // Create the beams - for ( i = 0; i < NUM_BEAMS; i++ ) - { - if ( m_hBeams[i] ) - continue; - - const char *beamAttachNames[] = - { - "fork1t", - "fork2t", - "fork1t", - "fork2t", - "fork1t", - "fork2t", - }; - - m_hBeams[i] = CBeam::BeamCreate( - bIsMegaCannon ? MEGACANNON_BEAM_SPRITE : PHYSCANNON_BEAM_SPRITE, 1.0f ); - m_hBeams[i]->EntsInit( pBeamEnt, pBeamEnt ); - - int startAttachment = LookupAttachment( beamAttachNames[i] ); - int endAttachment = 1; - - m_hBeams[i]->FollowEntity( pBeamEnt ); - - m_hBeams[i]->AddSpawnFlags( SF_BEAM_TEMPORARY ); - m_hBeams[i]->SetStartAttachment( startAttachment ); - m_hBeams[i]->SetEndAttachment( endAttachment ); - m_hBeams[i]->SetNoise( random->RandomFloat( 8.0f, 16.0f ) ); - m_hBeams[i]->SetColor( 255, 255, 255 ); - m_hBeams[i]->SetScrollRate( 25 ); - m_hBeams[i]->SetBrightness( 128 ); - m_hBeams[i]->SetWidth( 0 ); - m_hBeams[i]->SetEndWidth( random->RandomFloat( 2, 4 ) ); - } - - //Create the glow sprites - for ( i = 0; i < NUM_SPRITES; i++ ) - { - if ( m_hGlowSprites[i] ) - continue; - - const char *attachNames[] = - { - "fork1b", - "fork1m", - "fork1t", - "fork2b", - "fork2m", - "fork2t" - }; - - m_hGlowSprites[i] = CSprite::SpriteCreate( - bIsMegaCannon ? MEGACANNON_GLOW_SPRITE : PHYSCANNON_GLOW_SPRITE, - GetAbsOrigin(), false ); - - m_hGlowSprites[i]->SetAsTemporary(); - - m_hGlowSprites[i]->SetAttachment( pOwner->GetViewModel(), LookupAttachment( attachNames[i] ) ); - - if ( bIsMegaCannon ) - { - m_hGlowSprites[i]->SetTransparency( kRenderTransAdd, 255, 255, 255, 128, kRenderFxNone ); - } - else - { - m_hGlowSprites[i]->SetTransparency( kRenderTransAdd, 255, 128, 0, 64, kRenderFxNoDissipation ); - } - - m_hGlowSprites[i]->SetBrightness( 255, 0.2f ); - m_hGlowSprites[i]->SetScale( 0.25f * flScaleFactor, 0.2f ); - } - - //Create the endcap sprites - for ( i = 0; i < 2; i++ ) - { - if ( m_hEndSprites[i] == NULL ) - { - const char *attachNames[] = - { - "fork1t", - "fork2t" - }; - - m_hEndSprites[i] = CSprite::SpriteCreate( - bIsMegaCannon ? MEGACANNON_ENDCAP_SPRITE : PHYSCANNON_ENDCAP_SPRITE, - GetAbsOrigin(), false ); - - m_hEndSprites[i]->SetAsTemporary(); - m_hEndSprites[i]->SetAttachment( pOwner->GetViewModel(), LookupAttachment( attachNames[i] ) ); - m_hEndSprites[i]->SetTransparency( kRenderTransAdd, 255, 255, 255, 255, kRenderFxNoDissipation ); - m_hEndSprites[i]->SetBrightness( 255, 0.2f ); - m_hEndSprites[i]->SetScale( 0.25f * flScaleFactor, 0.2f ); - m_hEndSprites[i]->TurnOff(); - } - } - - //Create the center glow - if ( m_hCenterSprite == NULL ) - { - m_hCenterSprite = CSprite::SpriteCreate( - bIsMegaCannon ? MEGACANNON_CENTER_GLOW : PHYSCANNON_CENTER_GLOW, - GetAbsOrigin(), false ); - - m_hCenterSprite->SetAsTemporary(); - m_hCenterSprite->SetAttachment( pOwner->GetViewModel(), 1 ); - m_hCenterSprite->SetTransparency( kRenderTransAdd, 255, 255, 255, 255, kRenderFxNone ); - m_hCenterSprite->SetBrightness( 255, 0.2f ); - m_hCenterSprite->SetScale( 0.1f, 0.2f ); - } - - //Create the blast sprite - if ( m_hBlastSprite == NULL ) - { - m_hBlastSprite = CSprite::SpriteCreate( - bIsMegaCannon ? MEGACANNON_BLAST_SPRITE : PHYSCANNON_BLAST_SPRITE, - GetAbsOrigin(), false ); - - m_hBlastSprite->SetAsTemporary(); - m_hBlastSprite->SetAttachment( pOwner->GetViewModel(), 1 ); - m_hBlastSprite->SetTransparency( kRenderTransAdd, 255, 255, 255, 255, kRenderFxNone ); - m_hBlastSprite->SetBrightness( 255, 0.2f ); - m_hBlastSprite->SetScale( 0.1f, 0.2f ); - m_hBlastSprite->TurnOff(); - } -} - -//----------------------------------------------------------------------------- -// Closing effects -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DoEffectClosed( void ) -{ - float flScaleFactor = SpriteScaleFactor(); - - // Turn off the center sprite - if ( m_hCenterSprite != NULL ) - { - m_hCenterSprite->SetBrightness( 0, 0.1f ); - m_hCenterSprite->SetScale( 0.0f, 0.1f ); - m_hCenterSprite->TurnOff(); - } - - // Turn off the end-caps - for ( int i = 0; i < 2; i++ ) - { - if ( m_hEndSprites[i] != NULL ) - { - m_hEndSprites[i]->TurnOff(); - } - } - - // Turn off the lightning - for ( int i = 0; i < NUM_BEAMS; i++ ) - { - if ( m_hBeams[i] != NULL ) - { - m_hBeams[i]->SetBrightness( 0 ); - } - } - - // Turn on the glow sprites - for ( int i = 0; i < NUM_SPRITES; i++ ) - { - if ( m_hGlowSprites[i] != NULL ) - { - m_hGlowSprites[i]->TurnOn(); - m_hGlowSprites[i]->SetBrightness( 16, 0.2f ); - m_hGlowSprites[i]->SetScale( 0.3f * flScaleFactor, 0.2f ); - } - } - - // Prepare for scale down - if ( m_hBlastSprite != NULL ) - { - m_hBlastSprite->TurnOn(); - m_hBlastSprite->SetScale( 1.0f, 0.0f ); - m_hBlastSprite->SetBrightness( 0, 0.0f ); - } -} - -//----------------------------------------------------------------------------- -// Closing effects -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DoMegaEffectClosed( void ) -{ - float flScaleFactor = SpriteScaleFactor(); - - // Turn off the center sprite - if ( m_hCenterSprite != NULL ) - { - m_hCenterSprite->SetBrightness( 0, 0.1f ); - m_hCenterSprite->SetScale( 0.0f, 0.1f ); - m_hCenterSprite->TurnOff(); - } - - // Turn off the end-caps - for ( int i = 0; i < 2; i++ ) - { - if ( m_hEndSprites[i] != NULL ) - { - m_hEndSprites[i]->TurnOff(); - } - } - - // Turn off the lightning - for ( int i = 0; i < NUM_BEAMS; i++ ) - { - if ( m_hBeams[i] != NULL ) - { - m_hBeams[i]->SetBrightness( 0 ); - } - } - - // Turn on the glow sprites - for ( int i = 0; i < NUM_SPRITES; i++ ) - { - if ( m_hGlowSprites[i] != NULL ) - { - m_hGlowSprites[i]->TurnOn(); - m_hGlowSprites[i]->SetBrightness( 16, 0.2f ); - m_hGlowSprites[i]->SetScale( 0.3f * flScaleFactor, 0.2f ); - } - } - - // Prepare for scale down - if ( m_hBlastSprite != NULL ) - { - m_hBlastSprite->TurnOn(); - m_hBlastSprite->SetScale( 1.0f, 0.0f ); - m_hBlastSprite->SetBrightness( 0, 0.0f ); - } -} - -//----------------------------------------------------------------------------- -// Ready effects -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DoEffectReady( ) -{ - float flScaleFactor = SpriteScaleFactor(); - - //Turn on the center sprite - if ( m_hCenterSprite != NULL ) - { - m_hCenterSprite->SetBrightness( 128, 0.2f ); - m_hCenterSprite->SetScale( 0.15f, 0.2f ); - m_hCenterSprite->TurnOn(); - } - - //Turn off the end-caps - for ( int i = 0; i < 2; i++ ) - { - if ( m_hEndSprites[i] != NULL ) - { - m_hEndSprites[i]->TurnOff(); - } - } - - //Turn off the lightning - for ( int i = 0; i < NUM_BEAMS; i++ ) - { - if ( m_hBeams[i] != NULL ) - { - m_hBeams[i]->SetBrightness( 0 ); - } - } - - //Turn on the glow sprites - for ( int i = 0; i < NUM_SPRITES; i++ ) - { - if ( m_hGlowSprites[i] != NULL ) - { - m_hGlowSprites[i]->TurnOn(); - m_hGlowSprites[i]->SetBrightness( 32, 0.2f ); - m_hGlowSprites[i]->SetScale( 0.4f * flScaleFactor, 0.2f ); - } - } - - //Scale down - if ( m_hBlastSprite != NULL ) - { - m_hBlastSprite->TurnOn(); - m_hBlastSprite->SetScale( 0.1f, 0.2f ); - m_hBlastSprite->SetBrightness( 255, 0.1f ); - } -} - - -//----------------------------------------------------------------------------- -// Holding effects -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DoEffectHolding( ) -{ - float flScaleFactor = SpriteScaleFactor(); - - // Turn off the center sprite - if ( m_hCenterSprite != NULL ) - { - m_hCenterSprite->SetBrightness( 255, 0.1f ); - m_hCenterSprite->SetScale( 0.2f, 0.2f ); - m_hCenterSprite->TurnOn(); - } - - // Turn off the end-caps - for ( int i = 0; i < 2; i++ ) - { - if ( m_hEndSprites[i] != NULL ) - { - m_hEndSprites[i]->TurnOn(); - } - } - - // Turn off the lightning - for ( int i = 0; i < NUM_BEAMS; i++ ) - { - if ( m_hBeams[i] != NULL ) - { - m_hBeams[i]->SetBrightness( 128 ); - } - } - - // Turn on the glow sprites - for ( int i = 0; i < NUM_SPRITES; i++ ) - { - if ( m_hGlowSprites[i] != NULL ) - { - m_hGlowSprites[i]->TurnOn(); - m_hGlowSprites[i]->SetBrightness( 64, 0.2f ); - m_hGlowSprites[i]->SetScale( 0.5f * flScaleFactor, 0.2f ); - } - } - - // Prepare for scale up - if ( m_hBlastSprite != NULL ) - { - m_hBlastSprite->TurnOff(); - m_hBlastSprite->SetScale( 0.1f, 0.0f ); - m_hBlastSprite->SetBrightness( 0, 0.0f ); - } -} - - -//----------------------------------------------------------------------------- -// Launch effects -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DoEffectLaunch( Vector *pos ) -{ - Assert( pos ); - if ( pos == NULL ) - return; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( pOwner == NULL ) - return; - - Vector endpos = *pos; - - // Check to store off our view model index - CBeam *pBeam = CBeam::BeamCreate( IsMegaPhysCannon() ? MEGACANNON_BEAM_SPRITE : PHYSCANNON_BEAM_SPRITE, 8 ); - - if ( pBeam != NULL ) - { - pBeam->PointEntInit( endpos, this ); - pBeam->SetEndAttachment( 1 ); - pBeam->SetWidth( 6.4 ); - pBeam->SetEndWidth( 12.8 ); - pBeam->SetBrightness( 255 ); - pBeam->SetColor( 255, 255, 255 ); - pBeam->LiveForTime( 0.1f ); - pBeam->RelinkBeam(); - pBeam->SetNoise( 2 ); - } - - Vector shotDir = ( endpos - pOwner->Weapon_ShootPosition() ); - VectorNormalize( shotDir ); - - //End hit - //FIXME: Probably too big - CPVSFilter filter( endpos ); - te->GaussExplosion( filter, 0.0f, endpos - ( shotDir * 4.0f ), RandomVector(-1.0f, 1.0f), 0 ); - - if ( m_hBlastSprite != NULL ) - { - m_hBlastSprite->TurnOn(); - m_hBlastSprite->SetScale( 2.0f, 0.1f ); - m_hBlastSprite->SetBrightness( 0, 0.1f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pos - -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DoMegaEffectLaunch( Vector *pos ) -{ - Assert( pos ); - if ( pos == NULL ) - return; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( pOwner == NULL ) - return; - - Vector endpos = *pos; - - // Check to store off our view model index - CBaseViewModel *vm = pOwner->GetViewModel(); - - int numBeams = random->RandomInt( 1, 2 ); - - CBeam *pBeam = CBeam::BeamCreate( IsMegaPhysCannon() ? MEGACANNON_BEAM_SPRITE : PHYSCANNON_BEAM_SPRITE, 0.8 ); - - if ( pBeam != NULL ) - { - pBeam->PointEntInit( endpos, vm ); - pBeam->SetEndAttachment( 1 ); - pBeam->SetWidth( 2 ); - pBeam->SetEndWidth( 12 ); - pBeam->SetBrightness( 255 ); - pBeam->SetColor( 255, 255, 255 ); - pBeam->LiveForTime( 0.1f ); - pBeam->RelinkBeam(); - pBeam->SetNoise( 0 ); - } - - for ( int i = 0; i < numBeams; i++ ) - { - pBeam = CBeam::BeamCreate( IsMegaPhysCannon() ? MEGACANNON_BEAM_SPRITE : PHYSCANNON_BEAM_SPRITE, 0.8 ); - - if ( pBeam != NULL ) - { - pBeam->PointEntInit( endpos, vm ); - pBeam->SetEndAttachment( 1 ); - pBeam->SetWidth( 2 ); - pBeam->SetEndWidth( random->RandomInt( 1, 2 ) ); - pBeam->SetBrightness( 255 ); - pBeam->SetColor( 255, 255, 255 ); - pBeam->LiveForTime( 0.1f ); - pBeam->RelinkBeam(); - pBeam->SetNoise( random->RandomInt( 8, 12 ) ); - } - } - - Vector shotDir = ( endpos - pOwner->Weapon_ShootPosition() ); - VectorNormalize( shotDir ); - - //End hit - //FIXME: Probably too big - CPVSFilter filter( endpos ); - te->GaussExplosion( filter, 0.0f, endpos - ( shotDir * 4.0f ), RandomVector(-1.0f, 1.0f), 0 ); -} - -//----------------------------------------------------------------------------- -// Holding effects -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DoMegaEffectHolding( void ) -{ - float flScaleFactor = SpriteScaleFactor(); - - // Turn off the center sprite - if ( m_hCenterSprite != NULL ) - { - m_hCenterSprite->SetBrightness( 255, 0.1f ); - m_hCenterSprite->SetScale( 0.2f, 0.2f ); - m_hCenterSprite->TurnOn(); - } - - // Turn off the end-caps - for ( int i = 0; i < 2; i++ ) - { - if ( m_hEndSprites[i] != NULL ) - { - m_hEndSprites[i]->TurnOn(); - } - } - - // Turn off the lightning - for ( int i = 0; i < NUM_BEAMS; i++ ) - { - if ( m_hBeams[i] != NULL ) - { - m_hBeams[i]->SetBrightness( 128 ); - } - } - - // Turn on the glow sprites - for ( int i = 0; i < NUM_SPRITES; i++ ) - { - if ( m_hGlowSprites[i] != NULL ) - { - m_hGlowSprites[i]->TurnOn(); - m_hGlowSprites[i]->SetBrightness( 32, 0.2f ); - m_hGlowSprites[i]->SetScale( 0.25f * flScaleFactor, 0.2f ); - } - } -} - -//----------------------------------------------------------------------------- -// Ready effects -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DoMegaEffectReady( void ) -{ - float flScaleFactor = SpriteScaleFactor(); - - //Turn on the center sprite - if ( m_hCenterSprite != NULL ) - { - m_hCenterSprite->SetBrightness( 128, 0.2f ); - m_hCenterSprite->SetScale( 0.15f, 0.2f ); - m_hCenterSprite->TurnOn(); - } - - //Turn off the end-caps - for ( int i = 0; i < 2; i++ ) - { - if ( m_hEndSprites[i] != NULL ) - { - if ( m_flEndSpritesOverride[i] < gpGlobals->curtime ) - { - m_hEndSprites[i]->TurnOff(); - } - } - } - - //Turn off the lightning - for ( int i = 0; i < NUM_BEAMS; i++ ) - { - if ( m_hBeams[i] != NULL ) - { - m_hBeams[i]->SetBrightness( 0 ); - } - } - - //Turn on the glow sprites - for ( int i = 0; i < NUM_SPRITES; i++ ) - { - if ( m_hGlowSprites[i] != NULL ) - { - m_hGlowSprites[i]->TurnOn(); - m_hGlowSprites[i]->SetBrightness( 24, 0.2f ); - m_hGlowSprites[i]->SetScale( 0.2f * flScaleFactor, 0.2f ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Shutdown for the weapon when it's holstered -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DoEffectNone( void ) -{ - if ( m_hBlastSprite != NULL ) - { - // Become small - m_hBlastSprite->SetScale( 0.001f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : effectType - -// *pos - -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DoMegaEffect( int effectType, Vector *pos ) -{ - switch( effectType ) - { - case EFFECT_CLOSED: - DoMegaEffectClosed(); - break; - - case EFFECT_READY: - DoMegaEffectReady(); - break; - - case EFFECT_HOLDING: - DoMegaEffectHolding(); - break; - - case EFFECT_LAUNCH: - DoMegaEffectLaunch( pos ); - break; - - default: - case EFFECT_NONE: - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : effectType - -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DoEffect( int effectType, Vector *pos ) -{ - // Make sure we're active - StartEffects(); - - m_EffectState = effectType; - - // Do different effects when upgraded - if ( IsMegaPhysCannon() ) - { - DoMegaEffect( effectType, pos ); - return; - } - - switch( effectType ) - { - case EFFECT_CLOSED: - DoEffectClosed( ); - break; - - case EFFECT_READY: - DoEffectReady( ); - break; - - case EFFECT_HOLDING: - DoEffectHolding(); - break; - - case EFFECT_LAUNCH: - DoEffectLaunch( pos ); - break; - - default: - case EFFECT_NONE: - DoEffectNone(); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iIndex - -// Output : const char -//----------------------------------------------------------------------------- -const char *CWeaponPhysCannon::GetShootSound( int iIndex ) const -{ - // Just do this normally if we're a normal physcannon - if ( PlayerHasMegaPhysCannon() == false ) - return BaseClass::GetShootSound( iIndex ); - - // We override this if we're the charged up version - switch( iIndex ) - { - case EMPTY: - return "Weapon_MegaPhysCannon.DryFire"; - break; - - case SINGLE: - return "Weapon_MegaPhysCannon.Launch"; - break; - - case SPECIAL1: - return "Weapon_MegaPhysCannon.Pickup"; - break; - - case MELEE_MISS: - return "Weapon_MegaPhysCannon.Drop"; - break; - - default: - break; - } - - return BaseClass::GetShootSound( iIndex ); -} - -//----------------------------------------------------------------------------- -// Purpose: Adds the specified object to the list of objects that have been -// propelled by this physgun, along with a timestamp of when the -// object was added to the list. This list is checked when a physics -// object strikes another entity, to resolve whether the player is -// accountable for the impact. -// -// Input : pObject - pointer to the object being thrown by the physcannon. -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::RecordThrownObject( CBaseEntity *pObject ) -{ - thrown_objects_t thrown; - thrown.hEntity = pObject; - thrown.fTimeThrown = gpGlobals->curtime; - - // Get rid of stale and dead objects in the list. - PurgeThrownObjects(); - - // See if this object is already in the list. - int count = m_ThrownEntities.Count(); - - for( int i = 0 ; i < count ; i++ ) - { - if( m_ThrownEntities[i].hEntity == pObject ) - { - // Just update the time. - //Msg("++UPDATING: %s (%d)\n", m_ThrownEntities[i].hEntity->GetClassname(), m_ThrownEntities[i].hEntity->entindex() ); - m_ThrownEntities[i] = thrown; - return; - } - } - - //Msg("++ADDING: %s (%d)\n", pObject->GetClassname(), pObject->entindex() ); - - m_ThrownEntities.AddToTail(thrown); -} - -//----------------------------------------------------------------------------- -// Purpose: Go through the objects in the thrown objects list and discard any -// objects that have gone 'stale'. (Were thrown several seconds ago), or -// have been destroyed or removed. -// -//----------------------------------------------------------------------------- -#define PHYSCANNON_THROWN_LIST_TIMEOUT 10.0f -void CWeaponPhysCannon::PurgeThrownObjects() -{ - bool bListChanged; - - // This is bubble-sorty, but the list is also very short. - do - { - bListChanged = false; - - int count = m_ThrownEntities.Count(); - for( int i = 0 ; i < count ; i++ ) - { - bool bRemove = false; - - if( !m_ThrownEntities[i].hEntity.Get() ) - { - bRemove = true; - } - else if( gpGlobals->curtime > (m_ThrownEntities[i].fTimeThrown + PHYSCANNON_THROWN_LIST_TIMEOUT) ) - { - bRemove = true; - } - else - { - IPhysicsObject *pObject = m_ThrownEntities[i].hEntity->VPhysicsGetObject(); - - if( pObject && pObject->IsAsleep() ) - { - bRemove = true; - } - } - - if( bRemove ) - { - //Msg("--REMOVING: %s (%d)\n", m_ThrownEntities[i].hEntity->GetClassname(), m_ThrownEntities[i].hEntity->entindex() ); - m_ThrownEntities.Remove(i); - bListChanged = true; - break; - } - } - } while( bListChanged ); -} - -bool CWeaponPhysCannon::IsAccountableForObject( CBaseEntity *pObject ) -{ - // Clean out the stale and dead items. - PurgeThrownObjects(); - - // Now if this object is in the list, the player is accountable for it striking something. - int count = m_ThrownEntities.Count(); - - for( int i = 0 ; i < count ; i++ ) - { - if( m_ThrownEntities[i].hEntity == pObject ) - { - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// EXTERNAL API -//----------------------------------------------------------------------------- -void PhysCannonForceDrop( CBaseCombatWeapon *pActiveWeapon, CBaseEntity *pOnlyIfHoldingThis ) -{ - CWeaponPhysCannon *pCannon = dynamic_cast(pActiveWeapon); - if ( pCannon ) - { - if ( pOnlyIfHoldingThis ) - { - pCannon->DropIfEntityHeld( pOnlyIfHoldingThis ); - } - else - { - pCannon->ForceDrop(); - } - } -} - -void PhysCannonBeginUpgrade( CBaseAnimating *pAnim ) -{ - CWeaponPhysCannon *pWeaponPhyscannon = assert_cast< CWeaponPhysCannon* >( pAnim ); - pWeaponPhyscannon->BeginUpgrade(); -} - - -bool PlayerPickupControllerIsHoldingEntity( CBaseEntity *pPickupControllerEntity, CBaseEntity *pHeldEntity ) -{ - CPlayerPickupController *pController = dynamic_cast(pPickupControllerEntity); - - return pController ? pController->IsHoldingEntity( pHeldEntity ) : false; -} - - -float PhysCannonGetHeldObjectMass( CBaseCombatWeapon *pActiveWeapon, IPhysicsObject *pHeldObject ) -{ - float mass = 0.0f; - CWeaponPhysCannon *pCannon = dynamic_cast(pActiveWeapon); - if ( pCannon ) - { - CGrabController &grab = pCannon->GetGrabController(); - mass = grab.GetSavedMass( pHeldObject ); - } - - return mass; -} - -CBaseEntity *PhysCannonGetHeldEntity( CBaseCombatWeapon *pActiveWeapon ) -{ - CWeaponPhysCannon *pCannon = dynamic_cast(pActiveWeapon); - if ( pCannon ) - { - CGrabController &grab = pCannon->GetGrabController(); - return grab.GetAttached(); - } - - return NULL; -} - -CBaseEntity *GetPlayerHeldEntity( CBasePlayer *pPlayer ) -{ - CBaseEntity *pObject = NULL; - CPlayerPickupController *pPlayerPickupController = (CPlayerPickupController *)(pPlayer->GetUseEntity()); - - if ( pPlayerPickupController ) - { - pObject = pPlayerPickupController->GetGrabController().GetAttached(); - } - - return pObject; -} - -bool PhysCannonAccountableForObject( CBaseCombatWeapon *pPhysCannon, CBaseEntity *pObject ) -{ - CWeaponPhysCannon *pCannon = dynamic_cast(pPhysCannon); - if ( pCannon ) - { - return pCannon->IsAccountableForObject(pObject); - } - - return false; -} - -float PlayerPickupGetHeldObjectMass( CBaseEntity *pPickupControllerEntity, IPhysicsObject *pHeldObject ) -{ - float mass = 0.0f; - CPlayerPickupController *pController = dynamic_cast(pPickupControllerEntity); - if ( pController ) - { - CGrabController &grab = pController->GetGrabController(); - mass = grab.GetSavedMass( pHeldObject ); - } - return mass; -} diff --git a/game/server/hl2/weapon_physcannon.h b/game/server/hl2/weapon_physcannon.h deleted file mode 100644 index ceaa18b38..000000000 --- a/game/server/hl2/weapon_physcannon.h +++ /dev/null @@ -1,33 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef WEAPON_PHYSCANNON_H -#define WEAPON_PHYSCANNON_H -#ifdef _WIN32 -#pragma once -#endif - - - -//----------------------------------------------------------------------------- -// Do we have the super-phys gun? -//----------------------------------------------------------------------------- -bool PlayerHasMegaPhysCannon(); - -// force the physcannon to drop an object (if carried) -void PhysCannonForceDrop( CBaseCombatWeapon *pActiveWeapon, CBaseEntity *pOnlyIfHoldingThis ); -void PhysCannonBeginUpgrade( CBaseAnimating *pAnim ); - -bool PlayerPickupControllerIsHoldingEntity( CBaseEntity *pPickupController, CBaseEntity *pHeldEntity ); -float PlayerPickupGetHeldObjectMass( CBaseEntity *pPickupControllerEntity, IPhysicsObject *pHeldObject ); -float PhysCannonGetHeldObjectMass( CBaseCombatWeapon *pActiveWeapon, IPhysicsObject *pHeldObject ); - -CBaseEntity *PhysCannonGetHeldEntity( CBaseCombatWeapon *pActiveWeapon ); -CBaseEntity *GetPlayerHeldEntity( CBasePlayer *pPlayer ); - -bool PhysCannonAccountableForObject( CBaseCombatWeapon *pPhysCannon, CBaseEntity *pObject ); - -#endif // WEAPON_PHYSCANNON_H diff --git a/game/server/hl2/weapon_pistol.cpp b/game/server/hl2/weapon_pistol.cpp deleted file mode 100644 index 00ae79852..000000000 --- a/game/server/hl2/weapon_pistol.cpp +++ /dev/null @@ -1,373 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Pistol - hand gun -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" -#include "basehlcombatweapon.h" -#include "basecombatcharacter.h" -#include "ai_basenpc.h" -#include "player.h" -#include "gamerules.h" -#include "in_buttons.h" -#include "soundent.h" -#include "game.h" -#include "vstdlib/random.h" -#include "GameStats.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define PISTOL_FASTEST_REFIRE_TIME 0.1f -#define PISTOL_FASTEST_DRY_REFIRE_TIME 0.2f - -#define PISTOL_ACCURACY_SHOT_PENALTY_TIME 0.2f // Applied amount of time each shot adds to the time we must recover from -#define PISTOL_ACCURACY_MAXIMUM_PENALTY_TIME 1.5f // Maximum penalty to deal out - -ConVar pistol_use_new_accuracy( "pistol_use_new_accuracy", "1" ); - -//----------------------------------------------------------------------------- -// CWeaponPistol -//----------------------------------------------------------------------------- - -class CWeaponPistol : public CBaseHLCombatWeapon -{ - DECLARE_DATADESC(); - -public: - DECLARE_CLASS( CWeaponPistol, CBaseHLCombatWeapon ); - - CWeaponPistol(void); - - DECLARE_SERVERCLASS(); - - void Precache( void ); - void ItemPostFrame( void ); - void ItemPreFrame( void ); - void ItemBusyFrame( void ); - void PrimaryAttack( void ); - void AddViewKick( void ); - void DryFire( void ); - void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); - - void UpdatePenaltyTime( void ); - - int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } - Activity GetPrimaryAttackActivity( void ); - - virtual bool Reload( void ); - - virtual const Vector& GetBulletSpread( void ) - { - // Handle NPCs first - static Vector npcCone = VECTOR_CONE_5DEGREES; - if ( GetOwner() && GetOwner()->IsNPC() ) - return npcCone; - - static Vector cone; - - if ( pistol_use_new_accuracy.GetBool() ) - { - float ramp = RemapValClamped( m_flAccuracyPenalty, - 0.0f, - PISTOL_ACCURACY_MAXIMUM_PENALTY_TIME, - 0.0f, - 1.0f ); - - // We lerp from very accurate to inaccurate over time - VectorLerp( VECTOR_CONE_1DEGREES, VECTOR_CONE_6DEGREES, ramp, cone ); - } - else - { - // Old value - cone = VECTOR_CONE_4DEGREES; - } - - return cone; - } - - virtual int GetMinBurst() - { - return 1; - } - - virtual int GetMaxBurst() - { - return 3; - } - - virtual float GetFireRate( void ) - { - return 0.5f; - } - - DECLARE_ACTTABLE(); - -private: - float m_flSoonestPrimaryAttack; - float m_flLastAttackTime; - float m_flAccuracyPenalty; - int m_nNumShotsFired; -}; - - -IMPLEMENT_SERVERCLASS_ST(CWeaponPistol, DT_WeaponPistol) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_pistol, CWeaponPistol ); -PRECACHE_WEAPON_REGISTER( weapon_pistol ); - -BEGIN_DATADESC( CWeaponPistol ) - - DEFINE_FIELD( m_flSoonestPrimaryAttack, FIELD_TIME ), - DEFINE_FIELD( m_flLastAttackTime, FIELD_TIME ), - DEFINE_FIELD( m_flAccuracyPenalty, FIELD_FLOAT ), //NOTENOTE: This is NOT tracking game time - DEFINE_FIELD( m_nNumShotsFired, FIELD_INTEGER ), - -END_DATADESC() - -acttable_t CWeaponPistol::m_acttable[] = -{ - { ACT_IDLE, ACT_IDLE_PISTOL, true }, - { ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_PISTOL, true }, - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_PISTOL, true }, - { ACT_RELOAD, ACT_RELOAD_PISTOL, true }, - { ACT_WALK_AIM, ACT_WALK_AIM_PISTOL, true }, - { ACT_RUN_AIM, ACT_RUN_AIM_PISTOL, true }, - { ACT_GESTURE_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK_PISTOL,true }, - { ACT_RELOAD_LOW, ACT_RELOAD_PISTOL_LOW, false }, - { ACT_RANGE_ATTACK1_LOW, ACT_RANGE_ATTACK_PISTOL_LOW, false }, - { ACT_COVER_LOW, ACT_COVER_PISTOL_LOW, false }, - { ACT_RANGE_AIM_LOW, ACT_RANGE_AIM_PISTOL_LOW, false }, - { ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_PISTOL, false }, - { ACT_WALK, ACT_WALK_PISTOL, false }, - { ACT_RUN, ACT_RUN_PISTOL, false }, -}; - - -IMPLEMENT_ACTTABLE( CWeaponPistol ); - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -CWeaponPistol::CWeaponPistol( void ) -{ - m_flSoonestPrimaryAttack = gpGlobals->curtime; - m_flAccuracyPenalty = 0.0f; - - m_fMinRange1 = 24; - m_fMaxRange1 = 1500; - m_fMinRange2 = 24; - m_fMaxRange2 = 200; - - m_bFiresUnderwater = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPistol::Precache( void ) -{ - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeaponPistol::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - switch( pEvent->event ) - { - case EVENT_WEAPON_PISTOL_FIRE: - { - Vector vecShootOrigin, vecShootDir; - vecShootOrigin = pOperator->Weapon_ShootPosition(); - - CAI_BaseNPC *npc = pOperator->MyNPCPointer(); - ASSERT( npc != NULL ); - - vecShootDir = npc->GetActualShootTrajectory( vecShootOrigin ); - - CSoundEnt::InsertSound( SOUND_COMBAT|SOUND_CONTEXT_GUNFIRE, pOperator->GetAbsOrigin(), SOUNDENT_VOLUME_PISTOL, 0.2, pOperator, SOUNDENT_CHANNEL_WEAPON, pOperator->GetEnemy() ); - - WeaponSound( SINGLE_NPC ); - pOperator->FireBullets( 1, vecShootOrigin, vecShootDir, VECTOR_CONE_PRECALCULATED, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 2 ); - pOperator->DoMuzzleFlash(); - m_iClip1 = m_iClip1 - 1; - } - break; - default: - BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPistol::DryFire( void ) -{ - WeaponSound( EMPTY ); - SendWeaponAnim( ACT_VM_DRYFIRE ); - - m_flSoonestPrimaryAttack = gpGlobals->curtime + PISTOL_FASTEST_DRY_REFIRE_TIME; - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPistol::PrimaryAttack( void ) -{ - if ( ( gpGlobals->curtime - m_flLastAttackTime ) > 0.5f ) - { - m_nNumShotsFired = 0; - } - else - { - m_nNumShotsFired++; - } - - m_flLastAttackTime = gpGlobals->curtime; - m_flSoonestPrimaryAttack = gpGlobals->curtime + PISTOL_FASTEST_REFIRE_TIME; - CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), SOUNDENT_VOLUME_PISTOL, 0.2, GetOwner() ); - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if( pOwner ) - { - // Each time the player fires the pistol, reset the view punch. This prevents - // the aim from 'drifting off' when the player fires very quickly. This may - // not be the ideal way to achieve this, but it's cheap and it works, which is - // great for a feature we're evaluating. (sjb) - pOwner->ViewPunchReset(); - } - - BaseClass::PrimaryAttack(); - - // Add an accuracy penalty which can move past our maximum penalty time if we're really spastic - m_flAccuracyPenalty += PISTOL_ACCURACY_SHOT_PENALTY_TIME; - - m_iPrimaryAttacks++; - gamestats->Event_WeaponFired( pOwner, true, GetClassname() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPistol::UpdatePenaltyTime( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - // Check our penalty time decay - if ( ( ( pOwner->m_nButtons & IN_ATTACK ) == false ) && ( m_flSoonestPrimaryAttack < gpGlobals->curtime ) ) - { - m_flAccuracyPenalty -= gpGlobals->frametime; - m_flAccuracyPenalty = clamp( m_flAccuracyPenalty, 0.0f, PISTOL_ACCURACY_MAXIMUM_PENALTY_TIME ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPistol::ItemPreFrame( void ) -{ - UpdatePenaltyTime(); - - BaseClass::ItemPreFrame(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPistol::ItemBusyFrame( void ) -{ - UpdatePenaltyTime(); - - BaseClass::ItemBusyFrame(); -} - -//----------------------------------------------------------------------------- -// Purpose: Allows firing as fast as button is pressed -//----------------------------------------------------------------------------- -void CWeaponPistol::ItemPostFrame( void ) -{ - BaseClass::ItemPostFrame(); - - if ( m_bInReload ) - return; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - //Allow a refire as fast as the player can click - if ( ( ( pOwner->m_nButtons & IN_ATTACK ) == false ) && ( m_flSoonestPrimaryAttack < gpGlobals->curtime ) ) - { - m_flNextPrimaryAttack = gpGlobals->curtime - 0.1f; - } - else if ( ( pOwner->m_nButtons & IN_ATTACK ) && ( m_flNextPrimaryAttack < gpGlobals->curtime ) && ( m_iClip1 <= 0 ) ) - { - DryFire(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -Activity CWeaponPistol::GetPrimaryAttackActivity( void ) -{ - if ( m_nNumShotsFired < 1 ) - return ACT_VM_PRIMARYATTACK; - - if ( m_nNumShotsFired < 2 ) - return ACT_VM_RECOIL1; - - if ( m_nNumShotsFired < 3 ) - return ACT_VM_RECOIL2; - - return ACT_VM_RECOIL3; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CWeaponPistol::Reload( void ) -{ - bool fRet = DefaultReload( GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD ); - if ( fRet ) - { - WeaponSound( RELOAD ); - m_flAccuracyPenalty = 0.0f; - } - return fRet; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPistol::AddViewKick( void ) -{ - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if ( pPlayer == NULL ) - return; - - QAngle viewPunch; - - viewPunch.x = random->RandomFloat( 0.25f, 0.5f ); - viewPunch.y = random->RandomFloat( -.6f, .6f ); - viewPunch.z = 0.0f; - - //Add it to the view punch - pPlayer->ViewPunch( viewPunch ); -} diff --git a/game/server/hl2/weapon_rpg.cpp b/game/server/hl2/weapon_rpg.cpp deleted file mode 100644 index efbc753cf..000000000 --- a/game/server/hl2/weapon_rpg.cpp +++ /dev/null @@ -1,2376 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "basehlcombatweapon.h" -#include "basecombatcharacter.h" -#include "movie_explosion.h" -#include "soundent.h" -#include "player.h" -#include "rope.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "explode.h" -#include "util.h" -#include "in_buttons.h" -#include "weapon_rpg.h" -#include "shake.h" -#include "ai_basenpc.h" -#include "ai_squad.h" -#include "te_effect_dispatch.h" -#include "triggers.h" -#include "smoke_trail.h" -#include "collisionutils.h" -#include "hl2_shareddefs.h" -#include "rumble_shared.h" -#include "GameStats.h" - -#ifdef PORTAL - #include "portal_util_shared.h" -#endif - -#ifdef HL2_DLL - extern int g_interactionPlayerLaunchedRPG; -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define RPG_SPEED 1500 - -static ConVar sk_apc_missile_damage("sk_apc_missile_damage", "15"); -ConVar rpg_missle_use_custom_detonators( "rpg_missle_use_custom_detonators", "1" ); - -#define APC_MISSILE_DAMAGE sk_apc_missile_damage.GetInt() - -const char *g_pLaserDotThink = "LaserThinkContext"; - -//----------------------------------------------------------------------------- -// Laser Dot -//----------------------------------------------------------------------------- -class CLaserDot : public CSprite -{ - DECLARE_CLASS( CLaserDot, CSprite ); -public: - - CLaserDot( void ); - ~CLaserDot( void ); - - static CLaserDot *Create( const Vector &origin, CBaseEntity *pOwner = NULL, bool bVisibleDot = true ); - - void SetTargetEntity( CBaseEntity *pTarget ) { m_hTargetEnt = pTarget; } - CBaseEntity *GetTargetEntity( void ) { return m_hTargetEnt; } - - void SetLaserPosition( const Vector &origin, const Vector &normal ); - Vector GetChasePosition(); - void TurnOn( void ); - void TurnOff( void ); - bool IsOn() const { return m_bIsOn; } - - void Toggle( void ); - - void LaserThink( void ); - - int ObjectCaps() { return (BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | FCAP_DONT_SAVE; } - - void MakeInvisible( void ); - -protected: - Vector m_vecSurfaceNormal; - EHANDLE m_hTargetEnt; - bool m_bVisibleLaserDot; - bool m_bIsOn; - - DECLARE_DATADESC(); -public: - CLaserDot *m_pNext; -}; - -// a list of laser dots to search quickly -CEntityClassList g_LaserDotList; -template <> CLaserDot *CEntityClassList::m_pClassList = NULL; -CLaserDot *GetLaserDotList() -{ - return g_LaserDotList.m_pClassList; -} - -BEGIN_DATADESC( CMissile ) - - DEFINE_FIELD( m_hOwner, FIELD_EHANDLE ), - DEFINE_FIELD( m_hRocketTrail, FIELD_EHANDLE ), - DEFINE_FIELD( m_flAugerTime, FIELD_TIME ), - DEFINE_FIELD( m_flMarkDeadTime, FIELD_TIME ), - DEFINE_FIELD( m_flGracePeriodEndsAt, FIELD_TIME ), - DEFINE_FIELD( m_flDamage, FIELD_FLOAT ), - DEFINE_FIELD( m_bCreateDangerSounds, FIELD_BOOLEAN ), - - // Function Pointers - DEFINE_FUNCTION( MissileTouch ), - DEFINE_FUNCTION( AccelerateThink ), - DEFINE_FUNCTION( AugerThink ), - DEFINE_FUNCTION( IgniteThink ), - DEFINE_FUNCTION( SeekThink ), - -END_DATADESC() -LINK_ENTITY_TO_CLASS( rpg_missile, CMissile ); - -class CWeaponRPG; - - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CMissile::CMissile() -{ - m_hRocketTrail = NULL; - m_bCreateDangerSounds = false; -} - -CMissile::~CMissile() -{ -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CMissile::Precache( void ) -{ - PrecacheModel( "models/weapons/w_missile.mdl" ); - PrecacheModel( "models/weapons/w_missile_launch.mdl" ); - PrecacheModel( "models/weapons/w_missile_closed.mdl" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CMissile::Spawn( void ) -{ - Precache(); - - SetSolid( SOLID_BBOX ); - SetModel("models/weapons/w_missile_launch.mdl"); - UTIL_SetSize( this, -Vector(4,4,4), Vector(4,4,4) ); - - SetTouch( &CMissile::MissileTouch ); - - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); - SetThink( &CMissile::IgniteThink ); - - SetNextThink( gpGlobals->curtime + 0.3f ); - SetDamage( 200.0f ); - - m_takedamage = DAMAGE_YES; - m_iHealth = m_iMaxHealth = 100; - m_bloodColor = DONT_BLEED; - m_flGracePeriodEndsAt = 0; - - AddFlag( FL_OBJECT ); -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CMissile::Event_Killed( const CTakeDamageInfo &info ) -{ - m_takedamage = DAMAGE_NO; - - ShotDown(); -} - -unsigned int CMissile::PhysicsSolidMaskForEntity( void ) const -{ - return BaseClass::PhysicsSolidMaskForEntity() | CONTENTS_HITBOX; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CMissile::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - if ( ( info.GetDamageType() & (DMG_MISSILEDEFENSE | DMG_AIRBOAT) ) == false ) - return 0; - - bool bIsDamaged; - if( m_iHealth <= AugerHealth() ) - { - // This missile is already damaged (i.e., already running AugerThink) - bIsDamaged = true; - } - else - { - // This missile isn't damaged enough to wobble in flight yet - bIsDamaged = false; - } - - int nRetVal = BaseClass::OnTakeDamage_Alive( info ); - - if( !bIsDamaged ) - { - if ( m_iHealth <= AugerHealth() ) - { - ShotDown(); - } - } - - return nRetVal; -} - - -//----------------------------------------------------------------------------- -// Purpose: Stops any kind of tracking and shoots dumb -//----------------------------------------------------------------------------- -void CMissile::DumbFire( void ) -{ - SetThink( NULL ); - SetMoveType( MOVETYPE_FLY ); - - SetModel("models/weapons/w_missile.mdl"); - UTIL_SetSize( this, vec3_origin, vec3_origin ); - - EmitSound( "Missile.Ignite" ); - - // Smoke trail. - CreateSmokeTrail(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMissile::SetGracePeriod( float flGracePeriod ) -{ - m_flGracePeriodEndsAt = gpGlobals->curtime + flGracePeriod; - - // Go non-solid until the grace period ends - AddSolidFlags( FSOLID_NOT_SOLID ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CMissile::AccelerateThink( void ) -{ - Vector vecForward; - - // !!!UNDONE - make this work exactly the same as HL1 RPG, lest we have looping sound bugs again! - EmitSound( "Missile.Accelerate" ); - - // SetEffects( EF_LIGHT ); - - AngleVectors( GetLocalAngles(), &vecForward ); - SetAbsVelocity( vecForward * RPG_SPEED ); - - SetThink( &CMissile::SeekThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -#define AUGER_YDEVIANCE 20.0f -#define AUGER_XDEVIANCEUP 8.0f -#define AUGER_XDEVIANCEDOWN 1.0f - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CMissile::AugerThink( void ) -{ - // If we've augered long enough, then just explode - if ( m_flAugerTime < gpGlobals->curtime ) - { - Explode(); - return; - } - - if ( m_flMarkDeadTime < gpGlobals->curtime ) - { - m_lifeState = LIFE_DYING; - } - - QAngle angles = GetLocalAngles(); - - angles.y += random->RandomFloat( -AUGER_YDEVIANCE, AUGER_YDEVIANCE ); - angles.x += random->RandomFloat( -AUGER_XDEVIANCEDOWN, AUGER_XDEVIANCEUP ); - - SetLocalAngles( angles ); - - Vector vecForward; - - AngleVectors( GetLocalAngles(), &vecForward ); - - SetAbsVelocity( vecForward * 1000.0f ); - - SetNextThink( gpGlobals->curtime + 0.05f ); -} - -//----------------------------------------------------------------------------- -// Purpose: Causes the missile to spiral to the ground and explode, due to damage -//----------------------------------------------------------------------------- -void CMissile::ShotDown( void ) -{ - CEffectData data; - data.m_vOrigin = GetAbsOrigin(); - - DispatchEffect( "RPGShotDown", data ); - - if ( m_hRocketTrail != NULL ) - { - m_hRocketTrail->m_bDamaged = true; - } - - SetThink( &CMissile::AugerThink ); - SetNextThink( gpGlobals->curtime ); - m_flAugerTime = gpGlobals->curtime + 1.5f; - m_flMarkDeadTime = gpGlobals->curtime + 0.75; - - // Let the RPG start reloading immediately - if ( m_hOwner != NULL ) - { - m_hOwner->NotifyRocketDied(); - m_hOwner = NULL; - } -} - - -//----------------------------------------------------------------------------- -// The actual explosion -//----------------------------------------------------------------------------- -void CMissile::DoExplosion( void ) -{ - // Explode - ExplosionCreate( GetAbsOrigin(), GetAbsAngles(), GetOwnerEntity(), (int)GetDamage(), CMissile::EXPLOSION_RADIUS, - SF_ENVEXPLOSION_NOSPARKS | SF_ENVEXPLOSION_NODLIGHTS | SF_ENVEXPLOSION_NOSMOKE, 0.0f, this); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMissile::Explode( void ) -{ - // Don't explode against the skybox. Just pretend that - // the missile flies off into the distance. - Vector forward; - - GetVectors( &forward, NULL, NULL ); - - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + forward * 16, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - m_takedamage = DAMAGE_NO; - SetSolid( SOLID_NONE ); - if( tr.fraction == 1.0 || !(tr.surface.flags & SURF_SKY) ) - { - DoExplosion(); - } - - if( m_hRocketTrail ) - { - m_hRocketTrail->SetLifetime(0.1f); - m_hRocketTrail = NULL; - } - - if ( m_hOwner != NULL ) - { - m_hOwner->NotifyRocketDied(); - m_hOwner = NULL; - } - - StopSound( "Missile.Ignite" ); - UTIL_Remove( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOther - -//----------------------------------------------------------------------------- -void CMissile::MissileTouch( CBaseEntity *pOther ) -{ - Assert( pOther ); - - // Don't touch triggers (but DO hit weapons) - if ( pOther->IsSolidFlagSet(FSOLID_TRIGGER|FSOLID_VOLUME_CONTENTS) && pOther->GetCollisionGroup() != COLLISION_GROUP_WEAPON ) - { - // Some NPCs are triggers that can take damage (like antlion grubs). We should hit them. - if ( ( pOther->m_takedamage == DAMAGE_NO ) || ( pOther->m_takedamage == DAMAGE_EVENTS_ONLY ) ) - return; - } - - Explode(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMissile::CreateSmokeTrail( void ) -{ - if ( m_hRocketTrail ) - return; - - // Smoke trail. - if ( (m_hRocketTrail = RocketTrail::CreateRocketTrail()) != NULL ) - { - m_hRocketTrail->m_Opacity = 0.2f; - m_hRocketTrail->m_SpawnRate = 100; - m_hRocketTrail->m_ParticleLifetime = 0.5f; - m_hRocketTrail->m_StartColor.Init( 0.65f, 0.65f , 0.65f ); - m_hRocketTrail->m_EndColor.Init( 0.0, 0.0, 0.0 ); - m_hRocketTrail->m_StartSize = 8; - m_hRocketTrail->m_EndSize = 32; - m_hRocketTrail->m_SpawnRadius = 4; - m_hRocketTrail->m_MinSpeed = 2; - m_hRocketTrail->m_MaxSpeed = 16; - - m_hRocketTrail->SetLifetime( 999 ); - m_hRocketTrail->FollowEntity( this, "0" ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMissile::IgniteThink( void ) -{ - SetMoveType( MOVETYPE_FLY ); - SetModel("models/weapons/w_missile.mdl"); - UTIL_SetSize( this, vec3_origin, vec3_origin ); - RemoveSolidFlags( FSOLID_NOT_SOLID ); - - //TODO: Play opening sound - - Vector vecForward; - - EmitSound( "Missile.Ignite" ); - - AngleVectors( GetLocalAngles(), &vecForward ); - SetAbsVelocity( vecForward * RPG_SPEED ); - - SetThink( &CMissile::SeekThink ); - SetNextThink( gpGlobals->curtime ); - - if ( m_hOwner && m_hOwner->GetOwner() ) - { - CBasePlayer *pPlayer = ToBasePlayer( m_hOwner->GetOwner() ); - - if ( pPlayer ) - { - color32 white = { 255,225,205,64 }; - UTIL_ScreenFade( pPlayer, white, 0.1f, 0.0f, FFADE_IN ); - - pPlayer->RumbleEffect( RUMBLE_RPG_MISSILE, 0, RUMBLE_FLAG_RESTART ); - } - } - - CreateSmokeTrail(); -} - - -//----------------------------------------------------------------------------- -// Gets the shooting position -//----------------------------------------------------------------------------- -void CMissile::GetShootPosition( CLaserDot *pLaserDot, Vector *pShootPosition ) -{ - if ( pLaserDot->GetOwnerEntity() != NULL ) - { - //FIXME: Do we care this isn't exactly the muzzle position? - *pShootPosition = pLaserDot->GetOwnerEntity()->WorldSpaceCenter(); - } - else - { - *pShootPosition = pLaserDot->GetChasePosition(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -#define RPG_HOMING_SPEED 0.125f - -void CMissile::ComputeActualDotPosition( CLaserDot *pLaserDot, Vector *pActualDotPosition, float *pHomingSpeed ) -{ - *pHomingSpeed = RPG_HOMING_SPEED; - if ( pLaserDot->GetTargetEntity() ) - { - *pActualDotPosition = pLaserDot->GetChasePosition(); - return; - } - - Vector vLaserStart; - GetShootPosition( pLaserDot, &vLaserStart ); - - //Get the laser's vector - Vector vLaserDir; - VectorSubtract( pLaserDot->GetChasePosition(), vLaserStart, vLaserDir ); - - //Find the length of the current laser - float flLaserLength = VectorNormalize( vLaserDir ); - - //Find the length from the missile to the laser's owner - float flMissileLength = GetAbsOrigin().DistTo( vLaserStart ); - - //Find the length from the missile to the laser's position - Vector vecTargetToMissile; - VectorSubtract( GetAbsOrigin(), pLaserDot->GetChasePosition(), vecTargetToMissile ); - float flTargetLength = VectorNormalize( vecTargetToMissile ); - - // See if we should chase the line segment nearest us - if ( ( flMissileLength < flLaserLength ) || ( flTargetLength <= 512.0f ) ) - { - *pActualDotPosition = UTIL_PointOnLineNearestPoint( vLaserStart, pLaserDot->GetChasePosition(), GetAbsOrigin() ); - *pActualDotPosition += ( vLaserDir * 256.0f ); - } - else - { - // Otherwise chase the dot - *pActualDotPosition = pLaserDot->GetChasePosition(); - } - -// NDebugOverlay::Line( pLaserDot->GetChasePosition(), vLaserStart, 0, 255, 0, true, 0.05f ); -// NDebugOverlay::Line( GetAbsOrigin(), *pActualDotPosition, 255, 0, 0, true, 0.05f ); -// NDebugOverlay::Cross3D( *pActualDotPosition, -Vector(4,4,4), Vector(4,4,4), 255, 0, 0, true, 0.05f ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMissile::SeekThink( void ) -{ - CBaseEntity *pBestDot = NULL; - float flBestDist = MAX_TRACE_LENGTH; - float dotDist; - - // If we have a grace period, go solid when it ends - if ( m_flGracePeriodEndsAt ) - { - if ( m_flGracePeriodEndsAt < gpGlobals->curtime ) - { - RemoveSolidFlags( FSOLID_NOT_SOLID ); - m_flGracePeriodEndsAt = 0; - } - } - - //Search for all dots relevant to us - for( CLaserDot *pEnt = GetLaserDotList(); pEnt != NULL; pEnt = pEnt->m_pNext ) - { - if ( !pEnt->IsOn() ) - continue; - - if ( pEnt->GetOwnerEntity() != GetOwnerEntity() ) - continue; - - dotDist = (GetAbsOrigin() - pEnt->GetAbsOrigin()).Length(); - - //Find closest - if ( dotDist < flBestDist ) - { - pBestDot = pEnt; - flBestDist = dotDist; - } - } - - if( hl2_episodic.GetBool() ) - { - if( flBestDist <= ( GetAbsVelocity().Length() * 2.5f ) && FVisible( pBestDot->GetAbsOrigin() ) ) - { - // Scare targets - CSoundEnt::InsertSound( SOUND_DANGER, pBestDot->GetAbsOrigin(), CMissile::EXPLOSION_RADIUS, 0.2f, pBestDot, SOUNDENT_CHANNEL_REPEATED_DANGER, NULL ); - } - } - - if ( rpg_missle_use_custom_detonators.GetBool() ) - { - for ( int i = gm_CustomDetonators.Count() - 1; i >=0; --i ) - { - CustomDetonator_t &detonator = gm_CustomDetonators[i]; - if ( !detonator.hEntity ) - { - gm_CustomDetonators.FastRemove( i ); - } - else - { - const Vector &vPos = detonator.hEntity->CollisionProp()->WorldSpaceCenter(); - if ( detonator.halfHeight > 0 ) - { - if ( fabsf( vPos.z - GetAbsOrigin().z ) < detonator.halfHeight ) - { - if ( ( GetAbsOrigin().AsVector2D() - vPos.AsVector2D() ).LengthSqr() < detonator.radiusSq ) - { - Explode(); - return; - } - } - } - else - { - if ( ( GetAbsOrigin() - vPos ).LengthSqr() < detonator.radiusSq ) - { - Explode(); - return; - } - } - } - } - } - - //If we have a dot target - if ( pBestDot == NULL ) - { - //Think as soon as possible - SetNextThink( gpGlobals->curtime ); - return; - } - - CLaserDot *pLaserDot = (CLaserDot *)pBestDot; - Vector targetPos; - - float flHomingSpeed; - Vector vecLaserDotPosition; - ComputeActualDotPosition( pLaserDot, &targetPos, &flHomingSpeed ); - - if ( IsSimulatingOnAlternateTicks() ) - flHomingSpeed *= 2; - - Vector vTargetDir; - VectorSubtract( targetPos, GetAbsOrigin(), vTargetDir ); - float flDist = VectorNormalize( vTargetDir ); - - if( pLaserDot->GetTargetEntity() != NULL && flDist <= 240.0f && hl2_episodic.GetBool() ) - { - // Prevent the missile circling the Strider like a Halo in ep1_c17_06. If the missile gets within 20 - // feet of a Strider, tighten up the turn speed of the missile so it can break the halo and strike. (sjb 4/27/2006) - if( pLaserDot->GetTargetEntity()->ClassMatches( "npc_strider" ) ) - { - flHomingSpeed *= 1.75f; - } - } - - Vector vDir = GetAbsVelocity(); - float flSpeed = VectorNormalize( vDir ); - Vector vNewVelocity = vDir; - if ( gpGlobals->frametime > 0.0f ) - { - if ( flSpeed != 0 ) - { - vNewVelocity = ( flHomingSpeed * vTargetDir ) + ( ( 1 - flHomingSpeed ) * vDir ); - - // This computation may happen to cancel itself out exactly. If so, slam to targetdir. - if ( VectorNormalize( vNewVelocity ) < 1e-3 ) - { - vNewVelocity = (flDist != 0) ? vTargetDir : vDir; - } - } - else - { - vNewVelocity = vTargetDir; - } - } - - QAngle finalAngles; - VectorAngles( vNewVelocity, finalAngles ); - SetAbsAngles( finalAngles ); - - vNewVelocity *= flSpeed; - SetAbsVelocity( vNewVelocity ); - - if( GetAbsVelocity() == vec3_origin ) - { - // Strange circumstances have brought this missile to halt. Just blow it up. - Explode(); - return; - } - - // Think as soon as possible - SetNextThink( gpGlobals->curtime ); - -#ifdef HL2_EPISODIC - - if ( m_bCreateDangerSounds == true ) - { - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + GetAbsVelocity() * 0.5, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - - CSoundEnt::InsertSound( SOUND_DANGER, tr.endpos, 100, 0.2, this, SOUNDENT_CHANNEL_REPEATED_DANGER ); - } -#endif -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -// Input : &vecOrigin - -// &vecAngles - -// NULL - -// -// Output : CMissile -//----------------------------------------------------------------------------- -CMissile *CMissile::Create( const Vector &vecOrigin, const QAngle &vecAngles, edict_t *pentOwner = NULL ) -{ - //CMissile *pMissile = (CMissile *)CreateEntityByName("rpg_missile" ); - CMissile *pMissile = (CMissile *) CBaseEntity::Create( "rpg_missile", vecOrigin, vecAngles, CBaseEntity::Instance( pentOwner ) ); - pMissile->SetOwnerEntity( Instance( pentOwner ) ); - pMissile->Spawn(); - pMissile->AddEffects( EF_NOSHADOW ); - - Vector vecForward; - AngleVectors( vecAngles, &vecForward ); - - pMissile->SetAbsVelocity( vecForward * 300 + Vector( 0,0, 128 ) ); - - return pMissile; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CUtlVector CMissile::gm_CustomDetonators; - -void CMissile::AddCustomDetonator( CBaseEntity *pEntity, float radius, float height ) -{ - int i = gm_CustomDetonators.AddToTail(); - gm_CustomDetonators[i].hEntity = pEntity; - gm_CustomDetonators[i].radiusSq = Square( radius ); - gm_CustomDetonators[i].halfHeight = height * 0.5f; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CMissile::RemoveCustomDetonator( CBaseEntity *pEntity ) -{ - for ( int i = 0; i < gm_CustomDetonators.Count(); i++ ) - { - if ( gm_CustomDetonators[i].hEntity == pEntity ) - { - gm_CustomDetonators.FastRemove( i ); - break; - } - } -} - - -//----------------------------------------------------------------------------- -// This entity is used to create little force boxes that the helicopter -// should avoid. -//----------------------------------------------------------------------------- -class CInfoAPCMissileHint : public CBaseEntity -{ - DECLARE_DATADESC(); - -public: - DECLARE_CLASS( CInfoAPCMissileHint, CBaseEntity ); - - virtual void Spawn( ); - virtual void Activate(); - virtual void UpdateOnRemove(); - - static CBaseEntity *FindAimTarget( CBaseEntity *pMissile, const char *pTargetName, - const Vector &vecCurrentTargetPos, const Vector &vecCurrentTargetVel ); - -private: - EHANDLE m_hTarget; - - typedef CHandle APCMissileHintHandle_t; - static CUtlVector< APCMissileHintHandle_t > s_APCMissileHints; -}; - - -//----------------------------------------------------------------------------- -// -// This entity is used to create little force boxes that the helicopters should avoid. -// -//----------------------------------------------------------------------------- -CUtlVector< CInfoAPCMissileHint::APCMissileHintHandle_t > CInfoAPCMissileHint::s_APCMissileHints; - -LINK_ENTITY_TO_CLASS( info_apc_missile_hint, CInfoAPCMissileHint ); - -BEGIN_DATADESC( CInfoAPCMissileHint ) - DEFINE_FIELD( m_hTarget, FIELD_EHANDLE ), -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Spawn, remove -//----------------------------------------------------------------------------- -void CInfoAPCMissileHint::Spawn( ) -{ - SetModel( STRING( GetModelName() ) ); - SetSolid( SOLID_BSP ); - AddSolidFlags( FSOLID_NOT_SOLID ); - AddEffects( EF_NODRAW ); -} - -void CInfoAPCMissileHint::Activate( ) -{ - BaseClass::Activate(); - - m_hTarget = gEntList.FindEntityByName( NULL, m_target ); - if ( m_hTarget == NULL ) - { - DevWarning( "%s: Could not find target '%s'!\n", GetClassname(), STRING( m_target ) ); - } - else - { - s_APCMissileHints.AddToTail( this ); - } -} - -void CInfoAPCMissileHint::UpdateOnRemove( ) -{ - s_APCMissileHints.FindAndRemove( this ); - BaseClass::UpdateOnRemove(); -} - - -//----------------------------------------------------------------------------- -// Where are how should we avoid? -//----------------------------------------------------------------------------- -#define HINT_PREDICTION_TIME 3.0f - -CBaseEntity *CInfoAPCMissileHint::FindAimTarget( CBaseEntity *pMissile, const char *pTargetName, - const Vector &vecCurrentEnemyPos, const Vector &vecCurrentEnemyVel ) -{ - if ( !pTargetName ) - return NULL; - - float flOOSpeed = pMissile->GetAbsVelocity().Length(); - if ( flOOSpeed != 0.0f ) - { - flOOSpeed = 1.0f / flOOSpeed; - } - - for ( int i = s_APCMissileHints.Count(); --i >= 0; ) - { - CInfoAPCMissileHint *pHint = s_APCMissileHints[i]; - if ( !pHint->NameMatches( pTargetName ) ) - continue; - - if ( !pHint->m_hTarget ) - continue; - - Vector vecMissileToHint, vecMissileToEnemy; - VectorSubtract( pHint->m_hTarget->WorldSpaceCenter(), pMissile->GetAbsOrigin(), vecMissileToHint ); - VectorSubtract( vecCurrentEnemyPos, pMissile->GetAbsOrigin(), vecMissileToEnemy ); - float flDistMissileToHint = VectorNormalize( vecMissileToHint ); - VectorNormalize( vecMissileToEnemy ); - if ( DotProduct( vecMissileToHint, vecMissileToEnemy ) < 0.866f ) - continue; - - // Determine when the target will be inside the volume. - // Project at most 3 seconds in advance - Vector vecRayDelta; - VectorMultiply( vecCurrentEnemyVel, HINT_PREDICTION_TIME, vecRayDelta ); - - BoxTraceInfo_t trace; - if ( !IntersectRayWithOBB( vecCurrentEnemyPos, vecRayDelta, pHint->CollisionProp()->CollisionToWorldTransform(), - pHint->CollisionProp()->OBBMins(), pHint->CollisionProp()->OBBMaxs(), 0.0f, &trace )) - { - continue; - } - - // Determine the amount of time it would take the missile to reach the target - // If we can reach the target within the time it takes for the enemy to reach the - float tSqr = flDistMissileToHint * flOOSpeed / HINT_PREDICTION_TIME; - if ( (tSqr < (trace.t1 * trace.t1)) || (tSqr > (trace.t2 * trace.t2)) ) - continue; - - return pHint->m_hTarget; - } - - return NULL; -} - - -//----------------------------------------------------------------------------- -// a list of missiles to search quickly -//----------------------------------------------------------------------------- -CEntityClassList g_APCMissileList; -template <> CAPCMissile *CEntityClassList::m_pClassList = NULL; -CAPCMissile *GetAPCMissileList() -{ - return g_APCMissileList.m_pClassList; -} - -//----------------------------------------------------------------------------- -// Finds apc missiles in cone -//----------------------------------------------------------------------------- -CAPCMissile *FindAPCMissileInCone( const Vector &vecOrigin, const Vector &vecDirection, float flAngle ) -{ - float flCosAngle = cos( DEG2RAD( flAngle ) ); - for( CAPCMissile *pEnt = GetAPCMissileList(); pEnt != NULL; pEnt = pEnt->m_pNext ) - { - if ( !pEnt->IsSolid() ) - continue; - - Vector vecDelta; - VectorSubtract( pEnt->GetAbsOrigin(), vecOrigin, vecDelta ); - VectorNormalize( vecDelta ); - float flDot = DotProduct( vecDelta, vecDirection ); - if ( flDot > flCosAngle ) - return pEnt; - } - - return NULL; -} - - -//----------------------------------------------------------------------------- -// -// Specialized version of the missile -// -//----------------------------------------------------------------------------- -#define MAX_HOMING_DISTANCE 2250.0f -#define MIN_HOMING_DISTANCE 1250.0f -#define MAX_NEAR_HOMING_DISTANCE 1750.0f -#define MIN_NEAR_HOMING_DISTANCE 1000.0f -#define DOWNWARD_BLEND_TIME_START 0.2f -#define MIN_HEIGHT_DIFFERENCE 250.0f -#define MAX_HEIGHT_DIFFERENCE 550.0f -#define CORRECTION_TIME 0.2f -#define APC_LAUNCH_HOMING_SPEED 0.1f -#define APC_HOMING_SPEED 0.025f -#define HOMING_SPEED_ACCEL 0.01f - -BEGIN_DATADESC( CAPCMissile ) - - DEFINE_FIELD( m_flReachedTargetTime, FIELD_TIME ), - DEFINE_FIELD( m_flIgnitionTime, FIELD_TIME ), - DEFINE_FIELD( m_bGuidingDisabled, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hSpecificTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_strHint, FIELD_STRING ), - DEFINE_FIELD( m_flLastHomingSpeed, FIELD_FLOAT ), -// DEFINE_FIELD( m_pNext, FIELD_CLASSPTR ), - - DEFINE_THINKFUNC( BeginSeekThink ), - DEFINE_THINKFUNC( AugerStartThink ), - DEFINE_THINKFUNC( ExplodeThink ), - DEFINE_THINKFUNC( APCSeekThink ), - - DEFINE_FUNCTION( APCMissileTouch ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( apc_missile, CAPCMissile ); - -CAPCMissile *CAPCMissile::Create( const Vector &vecOrigin, const QAngle &vecAngles, const Vector &vecVelocity, CBaseEntity *pOwner ) -{ - CAPCMissile *pMissile = (CAPCMissile *)CBaseEntity::Create( "apc_missile", vecOrigin, vecAngles, pOwner ); - pMissile->SetOwnerEntity( pOwner ); - pMissile->Spawn(); - pMissile->SetAbsVelocity( vecVelocity ); - pMissile->AddFlag( FL_NOTARGET ); - pMissile->AddEffects( EF_NOSHADOW ); - return pMissile; -} - - -//----------------------------------------------------------------------------- -// Constructor, destructor -//----------------------------------------------------------------------------- -CAPCMissile::CAPCMissile() -{ - g_APCMissileList.Insert( this ); -} - -CAPCMissile::~CAPCMissile() -{ - g_APCMissileList.Remove( this ); -} - - -//----------------------------------------------------------------------------- -// Shared initialization code -//----------------------------------------------------------------------------- -void CAPCMissile::Init() -{ - SetMoveType( MOVETYPE_FLY ); - SetModel("models/weapons/w_missile.mdl"); - UTIL_SetSize( this, vec3_origin, vec3_origin ); - CreateSmokeTrail(); - SetTouch( &CAPCMissile::APCMissileTouch ); - m_flLastHomingSpeed = APC_HOMING_SPEED; - CreateDangerSounds( true ); - - - if( g_pGameRules->GetAutoAimMode() == AUTOAIM_ON_CONSOLE ) - { - AddFlag( FL_AIMTARGET ); - } -} - - -//----------------------------------------------------------------------------- -// For hitting a specific target -//----------------------------------------------------------------------------- -void CAPCMissile::AimAtSpecificTarget( CBaseEntity *pTarget ) -{ - m_hSpecificTarget = pTarget; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOther - -//----------------------------------------------------------------------------- -void CAPCMissile::APCMissileTouch( CBaseEntity *pOther ) -{ - Assert( pOther ); - if ( !pOther->IsSolid() && !pOther->IsSolidFlagSet(FSOLID_VOLUME_CONTENTS) ) - return; - - Explode(); -} - - -//----------------------------------------------------------------------------- -// Specialized version of the missile -//----------------------------------------------------------------------------- -void CAPCMissile::IgniteDelay( void ) -{ - m_flIgnitionTime = gpGlobals->curtime + 0.3f; - - SetThink( &CAPCMissile::BeginSeekThink ); - SetNextThink( m_flIgnitionTime ); - Init(); - AddSolidFlags( FSOLID_NOT_SOLID ); -} - -void CAPCMissile::AugerDelay( float flDelay ) -{ - m_flIgnitionTime = gpGlobals->curtime; - SetThink( &CAPCMissile::AugerStartThink ); - SetNextThink( gpGlobals->curtime + flDelay ); - Init(); - DisableGuiding(); -} - -void CAPCMissile::AugerStartThink() -{ - if ( m_hRocketTrail != NULL ) - { - m_hRocketTrail->m_bDamaged = true; - } - m_flAugerTime = gpGlobals->curtime + random->RandomFloat( 1.0f, 2.0f ); - SetThink( &CAPCMissile::AugerThink ); - SetNextThink( gpGlobals->curtime ); -} - -void CAPCMissile::ExplodeDelay( float flDelay ) -{ - m_flIgnitionTime = gpGlobals->curtime; - SetThink( &CAPCMissile::ExplodeThink ); - SetNextThink( gpGlobals->curtime + flDelay ); - Init(); - DisableGuiding(); -} - - -void CAPCMissile::BeginSeekThink( void ) -{ - RemoveSolidFlags( FSOLID_NOT_SOLID ); - SetThink( &CAPCMissile::APCSeekThink ); - SetNextThink( gpGlobals->curtime ); -} - -void CAPCMissile::APCSeekThink( void ) -{ - BaseClass::SeekThink(); - - bool bFoundDot = false; - - //If we can't find a dot to follow around then just send me wherever I'm facing so I can blow up in peace. - for( CLaserDot *pEnt = GetLaserDotList(); pEnt != NULL; pEnt = pEnt->m_pNext ) - { - if ( !pEnt->IsOn() ) - continue; - - if ( pEnt->GetOwnerEntity() != GetOwnerEntity() ) - continue; - - bFoundDot = true; - } - - if ( bFoundDot == false ) - { - Vector vDir = GetAbsVelocity(); - VectorNormalize ( vDir ); - - SetAbsVelocity( vDir * 800 ); - - SetThink( NULL ); - } -} - -void CAPCMissile::ExplodeThink() -{ - DoExplosion(); -} - -//----------------------------------------------------------------------------- -// Health lost at which augering starts -//----------------------------------------------------------------------------- -int CAPCMissile::AugerHealth() -{ - return m_iMaxHealth - 25; -} - - -//----------------------------------------------------------------------------- -// Health lost at which augering starts -//----------------------------------------------------------------------------- -void CAPCMissile::DisableGuiding() -{ - m_bGuidingDisabled = true; -} - - -//----------------------------------------------------------------------------- -// Guidance hints -//----------------------------------------------------------------------------- -void CAPCMissile::SetGuidanceHint( const char *pHintName ) -{ - m_strHint = MAKE_STRING( pHintName ); -} - - -//----------------------------------------------------------------------------- -// The actual explosion -//----------------------------------------------------------------------------- -void CAPCMissile::DoExplosion( void ) -{ - if ( GetWaterLevel() != 0 ) - { - CEffectData data; - data.m_vOrigin = WorldSpaceCenter(); - data.m_flMagnitude = 128; - data.m_flScale = 128; - data.m_fFlags = 0; - DispatchEffect( "WaterSurfaceExplosion", data ); - } - else - { -#ifdef HL2_EPISODIC - ExplosionCreate( GetAbsOrigin(), GetAbsAngles(), this, APC_MISSILE_DAMAGE, 100, true, 20000 ); -#else - ExplosionCreate( GetAbsOrigin(), GetAbsAngles(), GetOwnerEntity(), APC_MISSILE_DAMAGE, 100, true, 20000 ); -#endif - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAPCMissile::ComputeLeadingPosition( const Vector &vecShootPosition, CBaseEntity *pTarget, Vector *pLeadPosition ) -{ - Vector vecTarget = pTarget->BodyTarget( vecShootPosition, false ); - float flShotSpeed = GetAbsVelocity().Length(); - if ( flShotSpeed == 0 ) - { - *pLeadPosition = vecTarget; - return; - } - - Vector vecVelocity = pTarget->GetSmoothedVelocity(); - vecVelocity.z = 0.0f; - float flTargetSpeed = VectorNormalize( vecVelocity ); - Vector vecDelta; - VectorSubtract( vecShootPosition, vecTarget, vecDelta ); - float flTargetToShooter = VectorNormalize( vecDelta ); - float flCosTheta = DotProduct( vecDelta, vecVelocity ); - - // Law of cosines... z^2 = x^2 + y^2 - 2xy cos Theta - // where z = flShooterToPredictedTargetPosition = flShotSpeed * predicted time - // x = flTargetSpeed * predicted time - // y = flTargetToShooter - // solve for predicted time using at^2 + bt + c = 0, t = (-b +/- sqrt( b^2 - 4ac )) / 2a - float a = flTargetSpeed * flTargetSpeed - flShotSpeed * flShotSpeed; - float b = -2.0f * flTargetToShooter * flCosTheta * flTargetSpeed; - float c = flTargetToShooter * flTargetToShooter; - - float flDiscrim = b*b - 4*a*c; - if (flDiscrim < 0) - { - *pLeadPosition = vecTarget; - return; - } - - flDiscrim = sqrt(flDiscrim); - float t = (-b + flDiscrim) / (2.0f * a); - float t2 = (-b - flDiscrim) / (2.0f * a); - if ( t < t2 ) - { - t = t2; - } - - if ( t <= 0.0f ) - { - *pLeadPosition = vecTarget; - return; - } - - VectorMA( vecTarget, flTargetSpeed * t, vecVelocity, *pLeadPosition ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAPCMissile::ComputeActualDotPosition( CLaserDot *pLaserDot, Vector *pActualDotPosition, float *pHomingSpeed ) -{ - if ( m_bGuidingDisabled ) - { - *pActualDotPosition = GetAbsOrigin(); - *pHomingSpeed = 0.0f; - m_flLastHomingSpeed = *pHomingSpeed; - return; - } - - if ( ( m_strHint != NULL_STRING ) && (!m_hSpecificTarget) ) - { - Vector vecOrigin, vecVelocity; - CBaseEntity *pTarget = pLaserDot->GetTargetEntity(); - if ( pTarget ) - { - vecOrigin = pTarget->BodyTarget( GetAbsOrigin(), false ); - vecVelocity = pTarget->GetSmoothedVelocity(); - } - else - { - vecOrigin = pLaserDot->GetChasePosition(); - vecVelocity = vec3_origin; - } - - m_hSpecificTarget = CInfoAPCMissileHint::FindAimTarget( this, STRING( m_strHint ), vecOrigin, vecVelocity ); - } - - CBaseEntity *pLaserTarget = m_hSpecificTarget ? m_hSpecificTarget.Get() : pLaserDot->GetTargetEntity(); - if ( !pLaserTarget ) - { - BaseClass::ComputeActualDotPosition( pLaserDot, pActualDotPosition, pHomingSpeed ); - m_flLastHomingSpeed = *pHomingSpeed; - return; - } - - if ( pLaserTarget->ClassMatches( "npc_bullseye" ) ) - { - if ( m_flLastHomingSpeed != RPG_HOMING_SPEED ) - { - if (m_flLastHomingSpeed > RPG_HOMING_SPEED) - { - m_flLastHomingSpeed -= HOMING_SPEED_ACCEL * UTIL_GetSimulationInterval(); - if ( m_flLastHomingSpeed < RPG_HOMING_SPEED ) - { - m_flLastHomingSpeed = RPG_HOMING_SPEED; - } - } - else - { - m_flLastHomingSpeed += HOMING_SPEED_ACCEL * UTIL_GetSimulationInterval(); - if ( m_flLastHomingSpeed > RPG_HOMING_SPEED ) - { - m_flLastHomingSpeed = RPG_HOMING_SPEED; - } - } - } - *pHomingSpeed = m_flLastHomingSpeed; - *pActualDotPosition = pLaserTarget->WorldSpaceCenter(); - return; - } - - Vector vLaserStart; - GetShootPosition( pLaserDot, &vLaserStart ); - *pHomingSpeed = APC_LAUNCH_HOMING_SPEED; - - //Get the laser's vector - Vector vecTargetPosition = pLaserTarget->BodyTarget( GetAbsOrigin(), false ); - - // Compute leading position - Vector vecLeadPosition; - ComputeLeadingPosition( GetAbsOrigin(), pLaserTarget, &vecLeadPosition ); - - Vector vecTargetToMissile, vecTargetToShooter; - VectorSubtract( GetAbsOrigin(), vecTargetPosition, vecTargetToMissile ); - VectorSubtract( vLaserStart, vecTargetPosition, vecTargetToShooter ); - - *pActualDotPosition = vecLeadPosition; - - float flMinHomingDistance = MIN_HOMING_DISTANCE; - float flMaxHomingDistance = MAX_HOMING_DISTANCE; - float flBlendTime = gpGlobals->curtime - m_flIgnitionTime; - if ( flBlendTime > DOWNWARD_BLEND_TIME_START ) - { - if ( m_flReachedTargetTime != 0.0f ) - { - *pHomingSpeed = APC_HOMING_SPEED; - float flDeltaTime = clamp( gpGlobals->curtime - m_flReachedTargetTime, 0.0f, CORRECTION_TIME ); - *pHomingSpeed = SimpleSplineRemapVal( flDeltaTime, 0.0f, CORRECTION_TIME, 0.2f, *pHomingSpeed ); - flMinHomingDistance = SimpleSplineRemapVal( flDeltaTime, 0.0f, CORRECTION_TIME, MIN_NEAR_HOMING_DISTANCE, flMinHomingDistance ); - flMaxHomingDistance = SimpleSplineRemapVal( flDeltaTime, 0.0f, CORRECTION_TIME, MAX_NEAR_HOMING_DISTANCE, flMaxHomingDistance ); - } - else - { - flMinHomingDistance = MIN_NEAR_HOMING_DISTANCE; - flMaxHomingDistance = MAX_NEAR_HOMING_DISTANCE; - Vector vecDelta; - VectorSubtract( GetAbsOrigin(), *pActualDotPosition, vecDelta ); - if ( vecDelta.z > MIN_HEIGHT_DIFFERENCE ) - { - float flClampedHeight = clamp( vecDelta.z, MIN_HEIGHT_DIFFERENCE, MAX_HEIGHT_DIFFERENCE ); - float flHeightAdjustFactor = SimpleSplineRemapVal( flClampedHeight, MIN_HEIGHT_DIFFERENCE, MAX_HEIGHT_DIFFERENCE, 0.0f, 1.0f ); - - vecDelta.z = 0.0f; - float flDist = VectorNormalize( vecDelta ); - - float flForwardOffset = 2000.0f; - if ( flDist > flForwardOffset ) - { - Vector vecNewPosition; - VectorMA( GetAbsOrigin(), -flForwardOffset, vecDelta, vecNewPosition ); - vecNewPosition.z = pActualDotPosition->z; - - VectorLerp( *pActualDotPosition, vecNewPosition, flHeightAdjustFactor, *pActualDotPosition ); - } - } - else - { - m_flReachedTargetTime = gpGlobals->curtime; - } - } - - // Allows for players right at the edge of rocket range to be threatened - if ( flBlendTime > 0.6f ) - { - float flTargetLength = GetAbsOrigin().DistTo( pLaserTarget->WorldSpaceCenter() ); - flTargetLength = clamp( flTargetLength, flMinHomingDistance, flMaxHomingDistance ); - *pHomingSpeed = SimpleSplineRemapVal( flTargetLength, flMaxHomingDistance, flMinHomingDistance, *pHomingSpeed, 0.01f ); - } - } - - float flDot = DotProduct2D( vecTargetToShooter.AsVector2D(), vecTargetToMissile.AsVector2D() ); - if ( ( flDot < 0 ) || m_bGuidingDisabled ) - { - *pHomingSpeed = 0.0f; - } - - m_flLastHomingSpeed = *pHomingSpeed; - -// NDebugOverlay::Line( vecLeadPosition, GetAbsOrigin(), 0, 255, 0, true, 0.05f ); -// NDebugOverlay::Line( GetAbsOrigin(), *pActualDotPosition, 255, 0, 0, true, 0.05f ); -// NDebugOverlay::Cross3D( *pActualDotPosition, -Vector(4,4,4), Vector(4,4,4), 255, 0, 0, true, 0.05f ); -} - -#define RPG_BEAM_SPRITE "effects/laser1_noz.vmt" -#define RPG_LASER_SPRITE "sprites/redglow1.vmt" - -//============================================================================= -// RPG -//============================================================================= - -BEGIN_DATADESC( CWeaponRPG ) - - DEFINE_FIELD( m_bInitialStateUpdate,FIELD_BOOLEAN ), - DEFINE_FIELD( m_bGuiding, FIELD_BOOLEAN ), - DEFINE_FIELD( m_vecNPCLaserDot, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_hLaserDot, FIELD_EHANDLE ), - DEFINE_FIELD( m_hMissile, FIELD_EHANDLE ), - DEFINE_FIELD( m_hLaserMuzzleSprite, FIELD_EHANDLE ), - DEFINE_FIELD( m_hLaserBeam, FIELD_EHANDLE ), - DEFINE_FIELD( m_bHideGuiding, FIELD_BOOLEAN ), - -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST(CWeaponRPG, DT_WeaponRPG) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_rpg, CWeaponRPG ); -PRECACHE_WEAPON_REGISTER(weapon_rpg); - -acttable_t CWeaponRPG::m_acttable[] = -{ - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_RPG, true }, - - { ACT_IDLE_RELAXED, ACT_IDLE_RPG_RELAXED, true }, - { ACT_IDLE_STIMULATED, ACT_IDLE_ANGRY_RPG, true }, - { ACT_IDLE_AGITATED, ACT_IDLE_ANGRY_RPG, true }, - - { ACT_IDLE, ACT_IDLE_RPG, true }, - { ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_RPG, true }, - { ACT_WALK, ACT_WALK_RPG, true }, - { ACT_WALK_CROUCH, ACT_WALK_CROUCH_RPG, true }, - { ACT_RUN, ACT_RUN_RPG, true }, - { ACT_RUN_CROUCH, ACT_RUN_CROUCH_RPG, true }, - { ACT_COVER_LOW, ACT_COVER_LOW_RPG, true }, -}; - -IMPLEMENT_ACTTABLE(CWeaponRPG); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CWeaponRPG::CWeaponRPG() -{ - m_bReloadsSingly = true; - m_bInitialStateUpdate= false; - m_bHideGuiding = false; - m_bGuiding = false; - - m_fMinRange1 = m_fMinRange2 = 40*12; - m_fMaxRange1 = m_fMaxRange2 = 500*12; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CWeaponRPG::~CWeaponRPG() -{ - if ( m_hLaserDot != NULL ) - { - UTIL_Remove( m_hLaserDot ); - m_hLaserDot = NULL; - } - - if ( m_hLaserMuzzleSprite ) - { - UTIL_Remove( m_hLaserMuzzleSprite ); - } - - if ( m_hLaserBeam ) - { - UTIL_Remove( m_hLaserBeam ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponRPG::Precache( void ) -{ - BaseClass::Precache(); - - PrecacheScriptSound( "Missile.Ignite" ); - PrecacheScriptSound( "Missile.Accelerate" ); - - // Laser dot... - PrecacheModel( "sprites/redglow1.vmt" ); - PrecacheModel( RPG_LASER_SPRITE ); - PrecacheModel( RPG_BEAM_SPRITE ); - - UTIL_PrecacheOther( "rpg_missile" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponRPG::Activate( void ) -{ - BaseClass::Activate(); - - // Restore the laser pointer after transition - if ( m_bGuiding ) - { - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - if ( pOwner->GetActiveWeapon() == this ) - { - StartGuiding(); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEvent - -// *pOperator - -//----------------------------------------------------------------------------- -void CWeaponRPG::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - switch( pEvent->event ) - { - case EVENT_WEAPON_SMG1: - { - if ( m_hMissile != NULL ) - return; - - Vector muzzlePoint; - QAngle vecAngles; - - muzzlePoint = GetOwner()->Weapon_ShootPosition(); - - CAI_BaseNPC *npc = pOperator->MyNPCPointer(); - ASSERT( npc != NULL ); - - Vector vecShootDir = npc->GetActualShootTrajectory( muzzlePoint ); - - // look for a better launch location - Vector altLaunchPoint; - if (GetAttachment( "missile", altLaunchPoint )) - { - // check to see if it's relativly free - trace_t tr; - AI_TraceHull( altLaunchPoint, altLaunchPoint + vecShootDir * (10.0f*12.0f), Vector( -24, -24, -24 ), Vector( 24, 24, 24 ), MASK_NPCSOLID, NULL, &tr ); - - if( tr.fraction == 1.0) - { - muzzlePoint = altLaunchPoint; - } - } - - VectorAngles( vecShootDir, vecAngles ); - - m_hMissile = CMissile::Create( muzzlePoint, vecAngles, GetOwner()->edict() ); - m_hMissile->m_hOwner = this; - - // NPCs always get a grace period - m_hMissile->SetGracePeriod( 0.5 ); - - pOperator->DoMuzzleFlash(); - - WeaponSound( SINGLE_NPC ); - - // Make sure our laserdot is off - m_bGuiding = false; - - if ( m_hLaserDot ) - { - m_hLaserDot->TurnOff(); - } - } - break; - - default: - BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CWeaponRPG::HasAnyAmmo( void ) -{ - if ( m_hMissile != NULL ) - return true; - - return BaseClass::HasAnyAmmo(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponRPG::WeaponShouldBeLowered( void ) -{ - // Lower us if we're out of ammo - if ( !HasAnyAmmo() ) - return true; - - return BaseClass::WeaponShouldBeLowered(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponRPG::PrimaryAttack( void ) -{ - // Can't have an active missile out - if ( m_hMissile != NULL ) - return; - - // Can't be reloading - if ( GetActivity() == ACT_VM_RELOAD ) - return; - - Vector vecOrigin; - Vector vecForward; - - m_flNextPrimaryAttack = gpGlobals->curtime + 0.5f; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - Vector vForward, vRight, vUp; - - pOwner->EyeVectors( &vForward, &vRight, &vUp ); - - Vector muzzlePoint = pOwner->Weapon_ShootPosition() + vForward * 12.0f + vRight * 6.0f + vUp * -3.0f; - - QAngle vecAngles; - VectorAngles( vForward, vecAngles ); - m_hMissile = CMissile::Create( muzzlePoint, vecAngles, GetOwner()->edict() ); - - m_hMissile->m_hOwner = this; - - // If the shot is clear to the player, give the missile a grace period - trace_t tr; - Vector vecEye = pOwner->EyePosition(); - UTIL_TraceLine( vecEye, vecEye + vForward * 128, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction == 1.0 ) - { - m_hMissile->SetGracePeriod( 0.3 ); - } - - DecrementAmmo( GetOwner() ); - - // Register a muzzleflash for the AI - pOwner->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 ); - - SendWeaponAnim( ACT_VM_PRIMARYATTACK ); - WeaponSound( SINGLE ); - - pOwner->RumbleEffect( RUMBLE_SHOTGUN_SINGLE, 0, RUMBLE_FLAG_RESTART ); - - m_iPrimaryAttacks++; - gamestats->Event_WeaponFired( pOwner, true, GetClassname() ); - - CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 1000, 0.2, GetOwner(), SOUNDENT_CHANNEL_WEAPON ); - - // Check to see if we should trigger any RPG firing triggers - int iCount = g_hWeaponFireTriggers.Count(); - for ( int i = 0; i < iCount; i++ ) - { - if ( g_hWeaponFireTriggers[i]->IsTouching( pOwner ) ) - { - if ( FClassnameIs( g_hWeaponFireTriggers[i], "trigger_rpgfire" ) ) - { - g_hWeaponFireTriggers[i]->ActivateMultiTrigger( pOwner ); - } - } - } - - if( hl2_episodic.GetBool() ) - { - CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); - int nAIs = g_AI_Manager.NumAIs(); - - string_t iszStriderClassname = AllocPooledString( "npc_strider" ); - - for ( int i = 0; i < nAIs; i++ ) - { - if( ppAIs[ i ]->m_iClassname == iszStriderClassname ) - { - ppAIs[ i ]->DispatchInteraction( g_interactionPlayerLaunchedRPG, NULL, m_hMissile ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOwner - -//----------------------------------------------------------------------------- -void CWeaponRPG::DecrementAmmo( CBaseCombatCharacter *pOwner ) -{ - // Take away our primary ammo type - pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : state - -//----------------------------------------------------------------------------- -void CWeaponRPG::SuppressGuiding( bool state ) -{ - m_bHideGuiding = state; - - if ( m_hLaserDot == NULL ) - { - StartGuiding(); - - //STILL!? - if ( m_hLaserDot == NULL ) - return; - } - - if ( state ) - { - m_hLaserDot->TurnOff(); - } - else - { - m_hLaserDot->TurnOn(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Override this if we're guiding a missile currently -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponRPG::Lower( void ) -{ - if ( m_hMissile != NULL ) - return false; - - return BaseClass::Lower(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponRPG::ItemPostFrame( void ) -{ - BaseClass::ItemPostFrame(); - - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if ( pPlayer == NULL ) - return; - - //If we're pulling the weapon out for the first time, wait to draw the laser - if ( ( m_bInitialStateUpdate ) && ( GetActivity() != ACT_VM_DRAW ) ) - { - StartGuiding(); - m_bInitialStateUpdate = false; - } - - // Supress our guiding effects if we're lowered - if ( GetIdealActivity() == ACT_VM_IDLE_LOWERED || GetIdealActivity() == ACT_VM_RELOAD ) - { - SuppressGuiding(); - } - else - { - SuppressGuiding( false ); - } - - //Player has toggled guidance state - //Adrian: Players are not allowed to remove the laser guide in single player anymore, bye! - if ( g_pGameRules->IsMultiplayer() == true ) - { - if ( pPlayer->m_afButtonPressed & IN_ATTACK2 ) - { - ToggleGuiding(); - } - } - - //Move the laser - UpdateLaserPosition(); - UpdateLaserEffects(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Vector -//----------------------------------------------------------------------------- -Vector CWeaponRPG::GetLaserPosition( void ) -{ - CreateLaserPointer(); - - if ( m_hLaserDot != NULL ) - return m_hLaserDot->GetAbsOrigin(); - - //FIXME: The laser dot sprite is not active, this code should not be allowed! - assert(0); - return vec3_origin; -} - -//----------------------------------------------------------------------------- -// Purpose: NPC RPG users cheat and directly set the laser pointer's origin -// Input : &vecTarget - -//----------------------------------------------------------------------------- -void CWeaponRPG::UpdateNPCLaserPosition( const Vector &vecTarget ) -{ - CreateLaserPointer(); - // Turn the laserdot on - m_bGuiding = true; - m_hLaserDot->TurnOn(); - - Vector muzzlePoint = GetOwner()->Weapon_ShootPosition(); - Vector vecDir = (vecTarget - muzzlePoint); - VectorNormalize( vecDir ); - vecDir = muzzlePoint + ( vecDir * MAX_TRACE_LENGTH ); - UpdateLaserPosition( muzzlePoint, vecDir ); - - SetNPCLaserPosition( vecTarget ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponRPG::SetNPCLaserPosition( const Vector &vecTarget ) -{ - m_vecNPCLaserDot = vecTarget; - //NDebugOverlay::Box( m_vecNPCLaserDot, -Vector(10,10,10), Vector(10,10,10), 255,0,0, 8, 3 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const Vector &CWeaponRPG::GetNPCLaserPosition( void ) -{ - return m_vecNPCLaserDot; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true if the rocket is being guided, false if it's dumb -//----------------------------------------------------------------------------- -bool CWeaponRPG::IsGuiding( void ) -{ - return m_bGuiding; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponRPG::Deploy( void ) -{ - m_bInitialStateUpdate = true; - - return BaseClass::Deploy(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CWeaponRPG::Holster( CBaseCombatWeapon *pSwitchingTo ) -{ - //Can't have an active missile out - if ( m_hMissile != NULL ) - return false; - - StopGuiding(); - return BaseClass::Holster( pSwitchingTo ); -} - -//----------------------------------------------------------------------------- -// Purpose: Turn on the guiding laser -//----------------------------------------------------------------------------- -void CWeaponRPG::StartGuiding( void ) -{ - // Don't start back up if we're overriding this - if ( m_bHideGuiding ) - return; - - m_bGuiding = true; - - WeaponSound(SPECIAL1); - - CreateLaserPointer(); - StartLaserEffects(); -} - -//----------------------------------------------------------------------------- -// Purpose: Turn off the guiding laser -//----------------------------------------------------------------------------- -void CWeaponRPG::StopGuiding( void ) -{ - m_bGuiding = false; - - WeaponSound( SPECIAL2 ); - - StopLaserEffects(); - - // Kill the dot completely - if ( m_hLaserDot != NULL ) - { - m_hLaserDot->TurnOff(); - UTIL_Remove( m_hLaserDot ); - m_hLaserDot = NULL; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Toggle the guiding laser -//----------------------------------------------------------------------------- -void CWeaponRPG::ToggleGuiding( void ) -{ - if ( IsGuiding() ) - { - StopGuiding(); - } - else - { - StartGuiding(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponRPG::Drop( const Vector &vecVelocity ) -{ - StopGuiding(); - - BaseClass::Drop( vecVelocity ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponRPG::UpdateLaserPosition( Vector vecMuzzlePos, Vector vecEndPos ) -{ - if ( vecMuzzlePos == vec3_origin || vecEndPos == vec3_origin ) - { - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - if ( !pPlayer ) - return; - - vecMuzzlePos = pPlayer->Weapon_ShootPosition(); - Vector forward; - - if( g_pGameRules->GetAutoAimMode() == AUTOAIM_ON_CONSOLE ) - { - forward = pPlayer->GetAutoaimVector( AUTOAIM_SCALE_DEFAULT ); - } - else - { - pPlayer->EyeVectors( &forward ); - } - - vecEndPos = vecMuzzlePos + ( forward * MAX_TRACE_LENGTH ); - } - - //Move the laser dot, if active - trace_t tr; - - // Trace out for the endpoint -#ifdef PORTAL - g_bBulletPortalTrace = true; - Ray_t rayLaser; - rayLaser.Init( vecMuzzlePos, vecEndPos ); - UTIL_Portal_TraceRay( rayLaser, (MASK_SHOT & ~CONTENTS_WINDOW), this, COLLISION_GROUP_NONE, &tr ); - g_bBulletPortalTrace = false; -#else - UTIL_TraceLine( vecMuzzlePos, vecEndPos, (MASK_SHOT & ~CONTENTS_WINDOW), this, COLLISION_GROUP_NONE, &tr ); -#endif - - // Move the laser sprite - if ( m_hLaserDot != NULL ) - { - Vector laserPos = tr.endpos; - m_hLaserDot->SetLaserPosition( laserPos, tr.plane.normal ); - - if ( tr.DidHitNonWorldEntity() ) - { - CBaseEntity *pHit = tr.m_pEnt; - - if ( ( pHit != NULL ) && ( pHit->m_takedamage ) ) - { - m_hLaserDot->SetTargetEntity( pHit ); - } - else - { - m_hLaserDot->SetTargetEntity( NULL ); - } - } - else - { - m_hLaserDot->SetTargetEntity( NULL ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponRPG::CreateLaserPointer( void ) -{ - if ( m_hLaserDot != NULL ) - return; - - m_hLaserDot = CLaserDot::Create( GetAbsOrigin(), GetOwnerEntity() ); - m_hLaserDot->TurnOff(); - - UpdateLaserPosition(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponRPG::NotifyRocketDied( void ) -{ - m_hMissile = NULL; - - Reload(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CWeaponRPG::Reload( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - return false; - - if ( pOwner->GetAmmoCount(m_iPrimaryAmmoType) <= 0 ) - return false; - - WeaponSound( RELOAD ); - - SendWeaponAnim( ACT_VM_RELOAD ); - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CWeaponRPG::WeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions ) -{ - bool bResult = BaseClass::WeaponLOSCondition( ownerPos, targetPos, bSetConditions ); - - if( bResult ) - { - CAI_BaseNPC* npcOwner = GetOwner()->MyNPCPointer(); - - if( npcOwner ) - { - trace_t tr; - - Vector vecRelativeShootPosition; - VectorSubtract( npcOwner->Weapon_ShootPosition(), npcOwner->GetAbsOrigin(), vecRelativeShootPosition ); - Vector vecMuzzle = ownerPos + vecRelativeShootPosition; - Vector vecShootDir = npcOwner->GetActualShootTrajectory( vecMuzzle ); - - // Make sure I have a good 10 feet of wide clearance in front, or I'll blow my teeth out. - AI_TraceHull( vecMuzzle, vecMuzzle + vecShootDir * (10.0f*12.0f), Vector( -24, -24, -24 ), Vector( 24, 24, 24 ), MASK_NPCSOLID, NULL, &tr ); - - if( tr.fraction != 1.0f ) - bResult = false; - } - } - - return bResult; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flDot - -// flDist - -// Output : int -//----------------------------------------------------------------------------- -int CWeaponRPG::WeaponRangeAttack1Condition( float flDot, float flDist ) -{ - if ( m_hMissile != NULL ) - return 0; - - // Ignore vertical distance when doing our RPG distance calculations - CAI_BaseNPC *pNPC = GetOwner()->MyNPCPointer(); - if ( pNPC ) - { - CBaseEntity *pEnemy = pNPC->GetEnemy(); - Vector vecToTarget = (pEnemy->GetAbsOrigin() - pNPC->GetAbsOrigin()); - vecToTarget.z = 0; - flDist = vecToTarget.Length(); - } - - if ( flDist < MIN( m_fMinRange1, m_fMinRange2 ) ) - return COND_TOO_CLOSE_TO_ATTACK; - - if ( m_flNextPrimaryAttack > gpGlobals->curtime ) - return 0; - - // See if there's anyone in the way! - CAI_BaseNPC *pOwner = GetOwner()->MyNPCPointer(); - ASSERT( pOwner != NULL ); - - if( pOwner ) - { - // Make sure I don't shoot the world! - trace_t tr; - - Vector vecMuzzle = pOwner->Weapon_ShootPosition(); - Vector vecShootDir = pOwner->GetActualShootTrajectory( vecMuzzle ); - - // Make sure I have a good 10 feet of wide clearance in front, or I'll blow my teeth out. - AI_TraceHull( vecMuzzle, vecMuzzle + vecShootDir * (10.0f*12.0f), Vector( -24, -24, -24 ), Vector( 24, 24, 24 ), MASK_NPCSOLID, NULL, &tr ); - - if( tr.fraction != 1.0 ) - { - return COND_WEAPON_SIGHT_OCCLUDED; - } - } - - return COND_CAN_RANGE_ATTACK1; -} - -//----------------------------------------------------------------------------- -// Purpose: Start the effects on the viewmodel of the RPG -//----------------------------------------------------------------------------- -void CWeaponRPG::StartLaserEffects( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( pOwner == NULL ) - return; - - CBaseViewModel *pBeamEnt = static_cast(pOwner->GetViewModel()); - - if ( m_hLaserBeam == NULL ) - { - m_hLaserBeam = CBeam::BeamCreate( RPG_BEAM_SPRITE, 1.0f ); - - if ( m_hLaserBeam == NULL ) - { - // We were unable to create the beam - Assert(0); - return; - } - - m_hLaserBeam->EntsInit( pBeamEnt, pBeamEnt ); - - int startAttachment = LookupAttachment( "laser" ); - int endAttachment = LookupAttachment( "laser_end" ); - - m_hLaserBeam->FollowEntity( pBeamEnt ); - m_hLaserBeam->SetStartAttachment( startAttachment ); - m_hLaserBeam->SetEndAttachment( endAttachment ); - m_hLaserBeam->SetNoise( 0 ); - m_hLaserBeam->SetColor( 255, 0, 0 ); - m_hLaserBeam->SetScrollRate( 0 ); - m_hLaserBeam->SetWidth( 0.5f ); - m_hLaserBeam->SetEndWidth( 0.5f ); - m_hLaserBeam->SetBrightness( 128 ); - m_hLaserBeam->SetBeamFlags( SF_BEAM_SHADEIN ); -#ifdef PORTAL - m_hLaserBeam->m_bDrawInMainRender = true; - m_hLaserBeam->m_bDrawInPortalRender = false; -#endif - } - else - { - m_hLaserBeam->SetBrightness( 128 ); - } - - if ( m_hLaserMuzzleSprite == NULL ) - { - m_hLaserMuzzleSprite = CSprite::SpriteCreate( RPG_LASER_SPRITE, GetAbsOrigin(), false ); - - if ( m_hLaserMuzzleSprite == NULL ) - { - // We were unable to create the sprite - Assert(0); - return; - } - -#ifdef PORTAL - m_hLaserMuzzleSprite->m_bDrawInMainRender = true; - m_hLaserMuzzleSprite->m_bDrawInPortalRender = false; -#endif - - m_hLaserMuzzleSprite->SetAttachment( pOwner->GetViewModel(), LookupAttachment( "laser" ) ); - m_hLaserMuzzleSprite->SetTransparency( kRenderTransAdd, 255, 255, 255, 255, kRenderFxNoDissipation ); - m_hLaserMuzzleSprite->SetBrightness( 255, 0.5f ); - m_hLaserMuzzleSprite->SetScale( 0.25f, 0.5f ); - m_hLaserMuzzleSprite->TurnOn(); - } - else - { - m_hLaserMuzzleSprite->TurnOn(); - m_hLaserMuzzleSprite->SetScale( 0.25f, 0.25f ); - m_hLaserMuzzleSprite->SetBrightness( 255 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Stop the effects on the viewmodel of the RPG -//----------------------------------------------------------------------------- -void CWeaponRPG::StopLaserEffects( void ) -{ - if ( m_hLaserBeam != NULL ) - { - m_hLaserBeam->SetBrightness( 0 ); - } - - if ( m_hLaserMuzzleSprite != NULL ) - { - m_hLaserMuzzleSprite->SetScale( 0.01f ); - m_hLaserMuzzleSprite->SetBrightness( 0, 0.5f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Pulse all the effects to make them more... well, laser-like -//----------------------------------------------------------------------------- -void CWeaponRPG::UpdateLaserEffects( void ) -{ - if ( !m_bGuiding ) - return; - - if ( m_hLaserBeam != NULL ) - { - m_hLaserBeam->SetBrightness( 128 + random->RandomInt( -8, 8 ) ); - } - - if ( m_hLaserMuzzleSprite != NULL ) - { - m_hLaserMuzzleSprite->SetScale( 0.1f + random->RandomFloat( -0.025f, 0.025f ) ); - } -} - -//============================================================================= -// Laser Dot -//============================================================================= - -LINK_ENTITY_TO_CLASS( env_laserdot, CLaserDot ); - -BEGIN_DATADESC( CLaserDot ) - DEFINE_FIELD( m_vecSurfaceNormal, FIELD_VECTOR ), - DEFINE_FIELD( m_hTargetEnt, FIELD_EHANDLE ), - DEFINE_FIELD( m_bVisibleLaserDot, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bIsOn, FIELD_BOOLEAN ), - - //DEFINE_FIELD( m_pNext, FIELD_CLASSPTR ), // don't save - regenerated by constructor - DEFINE_THINKFUNC( LaserThink ), -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Finds missiles in cone -//----------------------------------------------------------------------------- -CBaseEntity *CreateLaserDot( const Vector &origin, CBaseEntity *pOwner, bool bVisibleDot ) -{ - return CLaserDot::Create( origin, pOwner, bVisibleDot ); -} - -void SetLaserDotTarget( CBaseEntity *pLaserDot, CBaseEntity *pTarget ) -{ - CLaserDot *pDot = assert_cast< CLaserDot* >(pLaserDot ); - pDot->SetTargetEntity( pTarget ); -} - -void EnableLaserDot( CBaseEntity *pLaserDot, bool bEnable ) -{ - CLaserDot *pDot = assert_cast< CLaserDot* >(pLaserDot ); - if ( bEnable ) - { - pDot->TurnOn(); - } - else - { - pDot->TurnOff(); - } -} - -CLaserDot::CLaserDot( void ) -{ - m_hTargetEnt = NULL; - m_bIsOn = true; - g_LaserDotList.Insert( this ); -} - -CLaserDot::~CLaserDot( void ) -{ - g_LaserDotList.Remove( this ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &origin - -// Output : CLaserDot -//----------------------------------------------------------------------------- -CLaserDot *CLaserDot::Create( const Vector &origin, CBaseEntity *pOwner, bool bVisibleDot ) -{ - CLaserDot *pLaserDot = (CLaserDot *) CBaseEntity::Create( "env_laserdot", origin, QAngle(0,0,0) ); - - if ( pLaserDot == NULL ) - return NULL; - - pLaserDot->m_bVisibleLaserDot = bVisibleDot; - pLaserDot->SetMoveType( MOVETYPE_NONE ); - pLaserDot->AddSolidFlags( FSOLID_NOT_SOLID ); - pLaserDot->AddEffects( EF_NOSHADOW ); - UTIL_SetSize( pLaserDot, vec3_origin, vec3_origin ); - - //Create the graphic - pLaserDot->SpriteInit( "sprites/redglow1.vmt", origin ); - - pLaserDot->SetName( AllocPooledString("TEST") ); - - pLaserDot->SetTransparency( kRenderGlow, 255, 255, 255, 255, kRenderFxNoDissipation ); - pLaserDot->SetScale( 0.5f ); - - pLaserDot->SetOwnerEntity( pOwner ); - - pLaserDot->SetContextThink( &CLaserDot::LaserThink, gpGlobals->curtime + 0.1f, g_pLaserDotThink ); - pLaserDot->SetSimulatedEveryTick( true ); - - if ( !bVisibleDot ) - { - pLaserDot->MakeInvisible(); - } - - return pLaserDot; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CLaserDot::LaserThink( void ) -{ - SetNextThink( gpGlobals->curtime + 0.05f, g_pLaserDotThink ); - - if ( GetOwnerEntity() == NULL ) - return; - - Vector viewDir = GetAbsOrigin() - GetOwnerEntity()->GetAbsOrigin(); - float dist = VectorNormalize( viewDir ); - - float scale = RemapVal( dist, 32, 1024, 0.01f, 0.5f ); - float scaleOffs = random->RandomFloat( -scale * 0.25f, scale * 0.25f ); - - scale = clamp( scale + scaleOffs, 0.1f, 32.0f ); - - SetScale( scale ); -} - -void CLaserDot::SetLaserPosition( const Vector &origin, const Vector &normal ) -{ - SetAbsOrigin( origin ); - m_vecSurfaceNormal = normal; -} - -Vector CLaserDot::GetChasePosition() -{ - return GetAbsOrigin() - m_vecSurfaceNormal * 10; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CLaserDot::TurnOn( void ) -{ - m_bIsOn = true; - if ( m_bVisibleLaserDot ) - { - BaseClass::TurnOn(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CLaserDot::TurnOff( void ) -{ - m_bIsOn = false; - if ( m_bVisibleLaserDot ) - { - BaseClass::TurnOff(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CLaserDot::MakeInvisible( void ) -{ - BaseClass::TurnOff(); -} diff --git a/game/server/hl2/weapon_rpg.h b/game/server/hl2/weapon_rpg.h deleted file mode 100644 index 7e5364767..000000000 --- a/game/server/hl2/weapon_rpg.h +++ /dev/null @@ -1,256 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef WEAPON_RPG_H -#define WEAPON_RPG_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "basehlcombatweapon.h" -#include "Sprite.h" -#include "npcevent.h" -#include "beam_shared.h" - -class CWeaponRPG; -class CLaserDot; -class RocketTrail; - -//########################################################################### -// >> CMissile (missile launcher class is below this one!) -//########################################################################### -class CMissile : public CBaseCombatCharacter -{ - DECLARE_CLASS( CMissile, CBaseCombatCharacter ); - -public: - static const int EXPLOSION_RADIUS = 200; - - CMissile(); - ~CMissile(); - -#ifdef HL1_DLL - Class_T Classify( void ) { return CLASS_NONE; } -#else - Class_T Classify( void ) { return CLASS_MISSILE; } -#endif - - void Spawn( void ); - void Precache( void ); - void MissileTouch( CBaseEntity *pOther ); - void Explode( void ); - void ShotDown( void ); - void AccelerateThink( void ); - void AugerThink( void ); - void IgniteThink( void ); - void SeekThink( void ); - void DumbFire( void ); - void SetGracePeriod( float flGracePeriod ); - - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - void Event_Killed( const CTakeDamageInfo &info ); - - virtual float GetDamage() { return m_flDamage; } - virtual void SetDamage(float flDamage) { m_flDamage = flDamage; } - - unsigned int PhysicsSolidMaskForEntity( void ) const; - - CHandle m_hOwner; - - static CMissile *Create( const Vector &vecOrigin, const QAngle &vecAngles, edict_t *pentOwner ); - - void CreateDangerSounds( bool bState ){ m_bCreateDangerSounds = bState; } - - static void AddCustomDetonator( CBaseEntity *pEntity, float radius, float height = -1 ); - static void RemoveCustomDetonator( CBaseEntity *pEntity ); - -protected: - virtual void DoExplosion(); - virtual void ComputeActualDotPosition( CLaserDot *pLaserDot, Vector *pActualDotPosition, float *pHomingSpeed ); - virtual int AugerHealth() { return m_iMaxHealth - 20; } - - // Creates the smoke trail - void CreateSmokeTrail( void ); - - // Gets the shooting position - void GetShootPosition( CLaserDot *pLaserDot, Vector *pShootPosition ); - - CHandle m_hRocketTrail; - float m_flAugerTime; // Amount of time to auger before blowing up anyway - float m_flMarkDeadTime; - float m_flDamage; - - struct CustomDetonator_t - { - EHANDLE hEntity; - float radiusSq; - float halfHeight; - }; - - static CUtlVector gm_CustomDetonators; - -private: - float m_flGracePeriodEndsAt; - bool m_bCreateDangerSounds; - - DECLARE_DATADESC(); -}; - - -//----------------------------------------------------------------------------- -// Laser dot control -//----------------------------------------------------------------------------- -CBaseEntity *CreateLaserDot( const Vector &origin, CBaseEntity *pOwner, bool bVisibleDot ); -void SetLaserDotTarget( CBaseEntity *pLaserDot, CBaseEntity *pTarget ); -void EnableLaserDot( CBaseEntity *pLaserDot, bool bEnable ); - - -//----------------------------------------------------------------------------- -// Specialized mizzizzile -//----------------------------------------------------------------------------- -class CAPCMissile : public CMissile -{ - DECLARE_CLASS( CMissile, CMissile ); - DECLARE_DATADESC(); - -public: - static CAPCMissile *Create( const Vector &vecOrigin, const QAngle &vecAngles, const Vector &vecVelocity, CBaseEntity *pOwner ); - - CAPCMissile(); - ~CAPCMissile(); - void IgniteDelay( void ); - void AugerDelay( float flDelayTime ); - void ExplodeDelay( float flDelayTime ); - void DisableGuiding(); -#if defined( HL2_DLL ) - virtual Class_T Classify ( void ) { return CLASS_COMBINE; } -#endif - - void AimAtSpecificTarget( CBaseEntity *pTarget ); - void SetGuidanceHint( const char *pHintName ); - - void APCSeekThink( void ); - - CAPCMissile *m_pNext; - -protected: - virtual void DoExplosion(); - virtual void ComputeActualDotPosition( CLaserDot *pLaserDot, Vector *pActualDotPosition, float *pHomingSpeed ); - virtual int AugerHealth(); - -private: - void Init(); - void ComputeLeadingPosition( const Vector &vecShootPosition, CBaseEntity *pTarget, Vector *pLeadPosition ); - void BeginSeekThink(); - void AugerStartThink(); - void ExplodeThink(); - void APCMissileTouch( CBaseEntity *pOther ); - - float m_flReachedTargetTime; - float m_flIgnitionTime; - bool m_bGuidingDisabled; - float m_flLastHomingSpeed; - EHANDLE m_hSpecificTarget; - string_t m_strHint; -}; - - -//----------------------------------------------------------------------------- -// Finds apc missiles in cone -//----------------------------------------------------------------------------- -CAPCMissile *FindAPCMissileInCone( const Vector &vecOrigin, const Vector &vecDirection, float flAngle ); - - -//----------------------------------------------------------------------------- -// RPG -//----------------------------------------------------------------------------- -class CWeaponRPG : public CBaseHLCombatWeapon -{ - DECLARE_CLASS( CWeaponRPG, CBaseHLCombatWeapon ); -public: - - CWeaponRPG(); - ~CWeaponRPG(); - - DECLARE_SERVERCLASS(); - - void Precache( void ); - - void PrimaryAttack( void ); - virtual float GetFireRate( void ) { return 1; }; - void ItemPostFrame( void ); - - void Activate( void ); - void DecrementAmmo( CBaseCombatCharacter *pOwner ); - - bool Deploy( void ); - bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); - bool Reload( void ); - bool WeaponShouldBeLowered( void ); - bool Lower( void ); - - virtual void Drop( const Vector &vecVelocity ); - - int GetMinBurst() { return 1; } - int GetMaxBurst() { return 1; } - float GetMinRestTime() { return 4.0; } - float GetMaxRestTime() { return 4.0; } - - bool WeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions ); - int WeaponRangeAttack1Condition( float flDot, float flDist ); - - void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); - void StartGuiding( void ); - void StopGuiding( void ); - void ToggleGuiding( void ); - bool IsGuiding( void ); - - void NotifyRocketDied( void ); - - bool HasAnyAmmo( void ); - - void SuppressGuiding( bool state = true ); - - void CreateLaserPointer( void ); - void UpdateLaserPosition( Vector vecMuzzlePos = vec3_origin, Vector vecEndPos = vec3_origin ); - Vector GetLaserPosition( void ); - void StartLaserEffects( void ); - void StopLaserEffects( void ); - void UpdateLaserEffects( void ); - - // NPC RPG users cheat and directly set the laser pointer's origin - void UpdateNPCLaserPosition( const Vector &vecTarget ); - void SetNPCLaserPosition( const Vector &vecTarget ); - const Vector &GetNPCLaserPosition( void ); - - int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } - - virtual const Vector& GetBulletSpread( void ) - { - static Vector cone = VECTOR_CONE_3DEGREES; - return cone; - } - - CBaseEntity *GetMissile( void ) { return m_hMissile; } - - DECLARE_ACTTABLE(); - DECLARE_DATADESC(); - -protected: - - bool m_bInitialStateUpdate; - bool m_bGuiding; - bool m_bHideGuiding; //User to override the player's wish to guide under certain circumstances - Vector m_vecNPCLaserDot; - CHandle m_hLaserDot; - CHandle m_hMissile; - CHandle m_hLaserMuzzleSprite; - CHandle m_hLaserBeam; -}; - -#endif // WEAPON_RPG_H diff --git a/game/server/hl2/weapon_shotgun.cpp b/game/server/hl2/weapon_shotgun.cpp deleted file mode 100644 index a28bbb4ea..000000000 --- a/game/server/hl2/weapon_shotgun.cpp +++ /dev/null @@ -1,793 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: A shotgun. -// -// Primary attack: single barrel shot. -// Secondary attack: double barrel shot. -// -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" -#include "basehlcombatweapon_shared.h" -#include "basecombatcharacter.h" -#include "ai_basenpc.h" -#include "player.h" -#include "gamerules.h" // For g_pGameRules -#include "in_buttons.h" -#include "soundent.h" -#include "vstdlib/random.h" -#include "GameStats.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern ConVar sk_auto_reload_time; -extern ConVar sk_plr_num_shotgun_pellets; - -class CWeaponShotgun : public CBaseHLCombatWeapon -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( CWeaponShotgun, CBaseHLCombatWeapon ); - - DECLARE_SERVERCLASS(); - -private: - bool m_bNeedPump; // When emptied completely - bool m_bDelayedFire1; // Fire primary when finished reloading - bool m_bDelayedFire2; // Fire secondary when finished reloading - -public: - void Precache( void ); - - int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } - - virtual const Vector& GetBulletSpread( void ) - { - static Vector vitalAllyCone = VECTOR_CONE_3DEGREES; - static Vector cone = VECTOR_CONE_10DEGREES; - - if( GetOwner() && (GetOwner()->Classify() == CLASS_PLAYER_ALLY_VITAL) ) - { - // Give Alyx's shotgun blasts more a more directed punch. She needs - // to be at least as deadly as she would be with her pistol to stay interesting (sjb) - return vitalAllyCone; - } - - return cone; - } - - virtual int GetMinBurst() { return 1; } - virtual int GetMaxBurst() { return 3; } - - virtual float GetMinRestTime(); - virtual float GetMaxRestTime(); - - virtual float GetFireRate( void ); - - bool StartReload( void ); - bool Reload( void ); - void FillClip( void ); - void FinishReload( void ); - void CheckHolsterReload( void ); - void Pump( void ); -// void WeaponIdle( void ); - void ItemHolsterFrame( void ); - void ItemPostFrame( void ); - void PrimaryAttack( void ); - void SecondaryAttack( void ); - void DryFire( void ); - - void FireNPCPrimaryAttack( CBaseCombatCharacter *pOperator, bool bUseWeaponAngles ); - void Operator_ForceNPCFire( CBaseCombatCharacter *pOperator, bool bSecondary ); - void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); - - DECLARE_ACTTABLE(); - - CWeaponShotgun(void); -}; - -IMPLEMENT_SERVERCLASS_ST(CWeaponShotgun, DT_WeaponShotgun) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_shotgun, CWeaponShotgun ); -PRECACHE_WEAPON_REGISTER(weapon_shotgun); - -BEGIN_DATADESC( CWeaponShotgun ) - - DEFINE_FIELD( m_bNeedPump, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bDelayedFire1, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bDelayedFire2, FIELD_BOOLEAN ), - -END_DATADESC() - -acttable_t CWeaponShotgun::m_acttable[] = -{ - { ACT_IDLE, ACT_IDLE_SMG1, true }, // FIXME: hook to shotgun unique - - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SHOTGUN, true }, - { ACT_RELOAD, ACT_RELOAD_SHOTGUN, false }, - { ACT_WALK, ACT_WALK_RIFLE, true }, - { ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_SHOTGUN, true }, - -// Readiness activities (not aiming) - { ACT_IDLE_RELAXED, ACT_IDLE_SHOTGUN_RELAXED, false },//never aims - { ACT_IDLE_STIMULATED, ACT_IDLE_SHOTGUN_STIMULATED, false }, - { ACT_IDLE_AGITATED, ACT_IDLE_SHOTGUN_AGITATED, false },//always aims - - { ACT_WALK_RELAXED, ACT_WALK_RIFLE_RELAXED, false },//never aims - { ACT_WALK_STIMULATED, ACT_WALK_RIFLE_STIMULATED, false }, - { ACT_WALK_AGITATED, ACT_WALK_AIM_RIFLE, false },//always aims - - { ACT_RUN_RELAXED, ACT_RUN_RIFLE_RELAXED, false },//never aims - { ACT_RUN_STIMULATED, ACT_RUN_RIFLE_STIMULATED, false }, - { ACT_RUN_AGITATED, ACT_RUN_AIM_RIFLE, false },//always aims - -// Readiness activities (aiming) - { ACT_IDLE_AIM_RELAXED, ACT_IDLE_SMG1_RELAXED, false },//never aims - { ACT_IDLE_AIM_STIMULATED, ACT_IDLE_AIM_RIFLE_STIMULATED, false }, - { ACT_IDLE_AIM_AGITATED, ACT_IDLE_ANGRY_SMG1, false },//always aims - - { ACT_WALK_AIM_RELAXED, ACT_WALK_RIFLE_RELAXED, false },//never aims - { ACT_WALK_AIM_STIMULATED, ACT_WALK_AIM_RIFLE_STIMULATED, false }, - { ACT_WALK_AIM_AGITATED, ACT_WALK_AIM_RIFLE, false },//always aims - - { ACT_RUN_AIM_RELAXED, ACT_RUN_RIFLE_RELAXED, false },//never aims - { ACT_RUN_AIM_STIMULATED, ACT_RUN_AIM_RIFLE_STIMULATED, false }, - { ACT_RUN_AIM_AGITATED, ACT_RUN_AIM_RIFLE, false },//always aims -//End readiness activities - - { ACT_WALK_AIM, ACT_WALK_AIM_SHOTGUN, true }, - { ACT_WALK_CROUCH, ACT_WALK_CROUCH_RIFLE, true }, - { ACT_WALK_CROUCH_AIM, ACT_WALK_CROUCH_AIM_RIFLE, true }, - { ACT_RUN, ACT_RUN_RIFLE, true }, - { ACT_RUN_AIM, ACT_RUN_AIM_SHOTGUN, true }, - { ACT_RUN_CROUCH, ACT_RUN_CROUCH_RIFLE, true }, - { ACT_RUN_CROUCH_AIM, ACT_RUN_CROUCH_AIM_RIFLE, true }, - { ACT_GESTURE_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK_SHOTGUN, true }, - { ACT_RANGE_ATTACK1_LOW, ACT_RANGE_ATTACK_SHOTGUN_LOW, true }, - { ACT_RELOAD_LOW, ACT_RELOAD_SHOTGUN_LOW, false }, - { ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SHOTGUN, false }, -}; - -IMPLEMENT_ACTTABLE(CWeaponShotgun); - -void CWeaponShotgun::Precache( void ) -{ - CBaseCombatWeapon::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOperator - -//----------------------------------------------------------------------------- -void CWeaponShotgun::FireNPCPrimaryAttack( CBaseCombatCharacter *pOperator, bool bUseWeaponAngles ) -{ - Vector vecShootOrigin, vecShootDir; - CAI_BaseNPC *npc = pOperator->MyNPCPointer(); - ASSERT( npc != NULL ); - WeaponSound( SINGLE_NPC ); - pOperator->DoMuzzleFlash(); - m_iClip1 = m_iClip1 - 1; - - if ( bUseWeaponAngles ) - { - QAngle angShootDir; - GetAttachment( LookupAttachment( "muzzle" ), vecShootOrigin, angShootDir ); - AngleVectors( angShootDir, &vecShootDir ); - } - else - { - vecShootOrigin = pOperator->Weapon_ShootPosition(); - vecShootDir = npc->GetActualShootTrajectory( vecShootOrigin ); - } - - pOperator->FireBullets( 8, vecShootOrigin, vecShootDir, GetBulletSpread(), MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponShotgun::Operator_ForceNPCFire( CBaseCombatCharacter *pOperator, bool bSecondary ) -{ - // Ensure we have enough rounds in the clip - m_iClip1++; - - FireNPCPrimaryAttack( pOperator, true ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeaponShotgun::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - switch( pEvent->event ) - { - case EVENT_WEAPON_SHOTGUN_FIRE: - { - FireNPCPrimaryAttack( pOperator, false ); - } - break; - - default: - CBaseCombatWeapon::Operator_HandleAnimEvent( pEvent, pOperator ); - break; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: When we shipped HL2, the shotgun weapon did not override the -// BaseCombatWeapon default rest time of 0.3 to 0.6 seconds. When -// NPC's fight from a stationary position, their animation events -// govern when they fire so the rate of fire is specified by the -// animation. When NPC's move-and-shoot, the rate of fire is -// specifically controlled by the shot regulator, so it's imporant -// that GetMinRestTime and GetMaxRestTime are implemented and provide -// reasonable defaults for the weapon. To address difficulty concerns, -// we are going to fix the combine's rate of shotgun fire in episodic. -// This change will not affect Alyx using a shotgun in EP1. (sjb) -//----------------------------------------------------------------------------- -float CWeaponShotgun::GetMinRestTime() -{ - if( hl2_episodic.GetBool() && GetOwner() && GetOwner()->Classify() == CLASS_COMBINE ) - { - return 1.2f; - } - - return BaseClass::GetMinRestTime(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -float CWeaponShotgun::GetMaxRestTime() -{ - if( hl2_episodic.GetBool() && GetOwner() && GetOwner()->Classify() == CLASS_COMBINE ) - { - return 1.5f; - } - - return BaseClass::GetMaxRestTime(); -} - -//----------------------------------------------------------------------------- -// Purpose: Time between successive shots in a burst. Also returned for EP2 -// with an eye to not messing up Alyx in EP1. -//----------------------------------------------------------------------------- -float CWeaponShotgun::GetFireRate() -{ - if( hl2_episodic.GetBool() && GetOwner() && GetOwner()->Classify() == CLASS_COMBINE ) - { - return 0.8f; - } - - return 0.7; -} - -//----------------------------------------------------------------------------- -// Purpose: Override so only reload one shell at a time -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CWeaponShotgun::StartReload( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - return false; - - if (pOwner->GetAmmoCount(m_iPrimaryAmmoType) <= 0) - return false; - - if (m_iClip1 >= GetMaxClip1()) - return false; - - // If shotgun totally emptied then a pump animation is needed - - //NOTENOTE: This is kinda lame because the player doesn't get strong feedback on when the reload has finished, - // without the pump. Technically, it's incorrect, but it's good for feedback... - - if (m_iClip1 <= 0) - { - m_bNeedPump = true; - } - - int j = MIN(1, pOwner->GetAmmoCount(m_iPrimaryAmmoType)); - - if (j <= 0) - return false; - - SendWeaponAnim( ACT_SHOTGUN_RELOAD_START ); - - // Make shotgun shell visible - SetBodygroup(1,0); - - pOwner->m_flNextAttack = gpGlobals->curtime; - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - - m_bInReload = true; - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Override so only reload one shell at a time -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CWeaponShotgun::Reload( void ) -{ - // Check that StartReload was called first - if (!m_bInReload) - { - Warning("ERROR: Shotgun Reload called incorrectly!\n"); - } - - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - return false; - - if (pOwner->GetAmmoCount(m_iPrimaryAmmoType) <= 0) - return false; - - if (m_iClip1 >= GetMaxClip1()) - return false; - - int j = MIN(1, pOwner->GetAmmoCount(m_iPrimaryAmmoType)); - - if (j <= 0) - return false; - - FillClip(); - // Play reload on different channel as otherwise steals channel away from fire sound - WeaponSound(RELOAD); - SendWeaponAnim( ACT_VM_RELOAD ); - - pOwner->m_flNextAttack = gpGlobals->curtime; - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Play finish reload anim and fill clip -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeaponShotgun::FinishReload( void ) -{ - // Make shotgun shell invisible - SetBodygroup(1,1); - - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - return; - - m_bInReload = false; - - // Finish reload animation - SendWeaponAnim( ACT_SHOTGUN_RELOAD_FINISH ); - - pOwner->m_flNextAttack = gpGlobals->curtime; - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); -} - -//----------------------------------------------------------------------------- -// Purpose: Play finish reload anim and fill clip -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeaponShotgun::FillClip( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - return; - - // Add them to the clip - if ( pOwner->GetAmmoCount( m_iPrimaryAmmoType ) > 0 ) - { - if ( Clip1() < GetMaxClip1() ) - { - m_iClip1++; - pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Play weapon pump anim -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeaponShotgun::Pump( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - return; - - m_bNeedPump = false; - - WeaponSound( SPECIAL1 ); - - // Finish reload animation - SendWeaponAnim( ACT_SHOTGUN_PUMP ); - - pOwner->m_flNextAttack = gpGlobals->curtime + SequenceDuration(); - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CWeaponShotgun::DryFire( void ) -{ - WeaponSound(EMPTY); - SendWeaponAnim( ACT_VM_DRYFIRE ); - - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CWeaponShotgun::PrimaryAttack( void ) -{ - // Only the player fires this way so we can cast - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if (!pPlayer) - { - return; - } - - // MUST call sound before removing a round from the clip of a CMachineGun - WeaponSound(SINGLE); - - pPlayer->DoMuzzleFlash(); - - SendWeaponAnim( ACT_VM_PRIMARYATTACK ); - - // player "shoot" animation - pPlayer->SetAnimation( PLAYER_ATTACK1 ); - - // Don't fire again until fire animation has completed - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - m_iClip1 -= 1; - - Vector vecSrc = pPlayer->Weapon_ShootPosition( ); - Vector vecAiming = pPlayer->GetAutoaimVector( AUTOAIM_SCALE_DEFAULT ); - - pPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 1.0 ); - - // Fire the bullets, and force the first shot to be perfectly accuracy - pPlayer->FireBullets( sk_plr_num_shotgun_pellets.GetInt(), vecSrc, vecAiming, GetBulletSpread(), MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 0, -1, -1, 0, NULL, true, true ); - - pPlayer->ViewPunch( QAngle( random->RandomFloat( -2, -1 ), random->RandomFloat( -2, 2 ), 0 ) ); - - CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), SOUNDENT_VOLUME_SHOTGUN, 0.2, GetOwner() ); - - if (!m_iClip1 && pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0) - { - // HEV suit - indicate out of ammo condition - pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); - } - - if( m_iClip1 ) - { - // pump so long as some rounds are left. - m_bNeedPump = true; - } - - m_iPrimaryAttacks++; - gamestats->Event_WeaponFired( pPlayer, true, GetClassname() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CWeaponShotgun::SecondaryAttack( void ) -{ - // Only the player fires this way so we can cast - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if (!pPlayer) - { - return; - } - - pPlayer->m_nButtons &= ~IN_ATTACK2; - // MUST call sound before removing a round from the clip of a CMachineGun - WeaponSound(WPN_DOUBLE); - - pPlayer->DoMuzzleFlash(); - - SendWeaponAnim( ACT_VM_SECONDARYATTACK ); - - // player "shoot" animation - pPlayer->SetAnimation( PLAYER_ATTACK1 ); - - // Don't fire again until fire animation has completed - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - m_iClip1 -= 2; // Shotgun uses same clip for primary and secondary attacks - - Vector vecSrc = pPlayer->Weapon_ShootPosition(); - Vector vecAiming = pPlayer->GetAutoaimVector( AUTOAIM_SCALE_DEFAULT ); - - // Fire the bullets - pPlayer->FireBullets( 12, vecSrc, vecAiming, GetBulletSpread(), MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 0, -1, -1, 0, NULL, false, false ); - pPlayer->ViewPunch( QAngle(random->RandomFloat( -5, 5 ),0,0) ); - - pPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 1.0 ); - - CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), SOUNDENT_VOLUME_SHOTGUN, 0.2 ); - - if (!m_iClip1 && pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0) - { - // HEV suit - indicate out of ammo condition - pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); - } - - if( m_iClip1 ) - { - // pump so long as some rounds are left. - m_bNeedPump = true; - } - - m_iSecondaryAttacks++; - gamestats->Event_WeaponFired( pPlayer, false, GetClassname() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Override so shotgun can do mulitple reloads in a row -//----------------------------------------------------------------------------- -void CWeaponShotgun::ItemPostFrame( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if (!pOwner) - { - return; - } - - if (m_bInReload) - { - // If I'm primary firing and have one round stop reloading and fire - if ((pOwner->m_nButtons & IN_ATTACK ) && (m_iClip1 >=1)) - { - m_bInReload = false; - m_bNeedPump = false; - m_bDelayedFire1 = true; - } - // If I'm secondary firing and have one round stop reloading and fire - else if ((pOwner->m_nButtons & IN_ATTACK2 ) && (m_iClip1 >=2)) - { - m_bInReload = false; - m_bNeedPump = false; - m_bDelayedFire2 = true; - } - else if (m_flNextPrimaryAttack <= gpGlobals->curtime) - { - // If out of ammo end reload - if (pOwner->GetAmmoCount(m_iPrimaryAmmoType) <=0) - { - FinishReload(); - return; - } - // If clip not full reload again - if (m_iClip1 < GetMaxClip1()) - { - Reload(); - return; - } - // Clip full, stop reloading - else - { - FinishReload(); - return; - } - } - } - else - { - // Make shotgun shell invisible - SetBodygroup(1,1); - } - - if ((m_bNeedPump) && (m_flNextPrimaryAttack <= gpGlobals->curtime)) - { - Pump(); - return; - } - - // Shotgun uses same timing and ammo for secondary attack - if ((m_bDelayedFire2 || pOwner->m_nButtons & IN_ATTACK2)&&(m_flNextPrimaryAttack <= gpGlobals->curtime)) - { - m_bDelayedFire2 = false; - - if ( (m_iClip1 <= 1 && UsesClipsForAmmo1())) - { - // If only one shell is left, do a single shot instead - if ( m_iClip1 == 1 ) - { - PrimaryAttack(); - } - else if (!pOwner->GetAmmoCount(m_iPrimaryAmmoType)) - { - DryFire(); - } - else - { - StartReload(); - } - } - - // Fire underwater? - else if (GetOwner()->GetWaterLevel() == 3 && m_bFiresUnderwater == false) - { - WeaponSound(EMPTY); - m_flNextPrimaryAttack = gpGlobals->curtime + 0.2; - return; - } - else - { - // If the firing button was just pressed, reset the firing time - if ( pOwner->m_afButtonPressed & IN_ATTACK ) - { - m_flNextPrimaryAttack = gpGlobals->curtime; - } - SecondaryAttack(); - } - } - else if ( (m_bDelayedFire1 || pOwner->m_nButtons & IN_ATTACK) && m_flNextPrimaryAttack <= gpGlobals->curtime) - { - m_bDelayedFire1 = false; - if ( (m_iClip1 <= 0 && UsesClipsForAmmo1()) || ( !UsesClipsForAmmo1() && !pOwner->GetAmmoCount(m_iPrimaryAmmoType) ) ) - { - if (!pOwner->GetAmmoCount(m_iPrimaryAmmoType)) - { - DryFire(); - } - else - { - StartReload(); - } - } - // Fire underwater? - else if (pOwner->GetWaterLevel() == 3 && m_bFiresUnderwater == false) - { - WeaponSound(EMPTY); - m_flNextPrimaryAttack = gpGlobals->curtime + 0.2; - return; - } - else - { - // If the firing button was just pressed, reset the firing time - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - if ( pPlayer && pPlayer->m_afButtonPressed & IN_ATTACK ) - { - m_flNextPrimaryAttack = gpGlobals->curtime; - } - PrimaryAttack(); - } - } - - if ( pOwner->m_nButtons & IN_RELOAD && UsesClipsForAmmo1() && !m_bInReload ) - { - // reload when reload is pressed, or if no buttons are down and weapon is empty. - StartReload(); - } - else - { - // no fire buttons down - m_bFireOnEmpty = false; - - if ( !HasAnyAmmo() && m_flNextPrimaryAttack < gpGlobals->curtime ) - { - // weapon isn't useable, switch. - if ( !(GetWeaponFlags() & ITEM_FLAG_NOAUTOSWITCHEMPTY) && pOwner->SwitchToNextBestWeapon( this ) ) - { - m_flNextPrimaryAttack = gpGlobals->curtime + 0.3; - return; - } - } - else - { - // weapon is useable. Reload if empty and weapon has waited as long as it has to after firing - if ( m_iClip1 <= 0 && !(GetWeaponFlags() & ITEM_FLAG_NOAUTORELOAD) && m_flNextPrimaryAttack < gpGlobals->curtime ) - { - if (StartReload()) - { - // if we've successfully started to reload, we're done - return; - } - } - } - - WeaponIdle( ); - return; - } - -} - - - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -CWeaponShotgun::CWeaponShotgun( void ) -{ - m_bReloadsSingly = true; - - m_bNeedPump = false; - m_bDelayedFire1 = false; - m_bDelayedFire2 = false; - - m_fMinRange1 = 0.0; - m_fMaxRange1 = 500; - m_fMinRange2 = 0.0; - m_fMaxRange2 = 200; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponShotgun::ItemHolsterFrame( void ) -{ - // Must be player held - if ( GetOwner() && GetOwner()->IsPlayer() == false ) - return; - - // We can't be active - if ( GetOwner()->GetActiveWeapon() == this ) - return; - - // If it's been longer than three seconds, reload - if ( ( gpGlobals->curtime - m_flHolsterTime ) > sk_auto_reload_time.GetFloat() ) - { - // Reset the timer - m_flHolsterTime = gpGlobals->curtime; - - if ( GetOwner() == NULL ) - return; - - if ( m_iClip1 == GetMaxClip1() ) - return; - - // Just load the clip with no animations - int ammoFill = MIN( (GetMaxClip1() - m_iClip1), GetOwner()->GetAmmoCount( GetPrimaryAmmoType() ) ); - - GetOwner()->RemoveAmmo( ammoFill, GetPrimaryAmmoType() ); - m_iClip1 += ammoFill; - } -} - -//================================================== -// Purpose: -//================================================== -/* -void CWeaponShotgun::WeaponIdle( void ) -{ - //Only the player fires this way so we can cast - CBasePlayer *pPlayer = GetOwner() - - if ( pPlayer == NULL ) - return; - - //If we're on a target, play the new anim - if ( pPlayer->IsOnTarget() ) - { - SendWeaponAnim( ACT_VM_IDLE_ACTIVE ); - } -} -*/ diff --git a/game/server/hl2/weapon_slam.cpp b/game/server/hl2/weapon_slam.cpp deleted file mode 100644 index 0e1734007..000000000 --- a/game/server/hl2/weapon_slam.cpp +++ /dev/null @@ -1,996 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "basehlcombatweapon.h" -#include "player.h" -#include "gamerules.h" -#include "grenade_tripmine.h" -#include "grenade_satchel.h" -#include "entitylist.h" -#include "weapon_slam.h" -#include "npcevent.h" -#include "in_buttons.h" -#include "engine/IEngineSound.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SLAM_PRIMARY_VOLUME 450 - -BEGIN_DATADESC( CWeapon_SLAM ) - - DEFINE_FIELD( m_tSlamState, FIELD_INTEGER ), - DEFINE_FIELD( m_bDetonatorArmed, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bNeedDetonatorDraw, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bNeedDetonatorHolster, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bNeedReload, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bClearReload, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bThrowSatchel, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bAttachSatchel, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bAttachTripmine, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flWallSwitchTime, FIELD_TIME ), - - // Function Pointers - DEFINE_FUNCTION( SLAMThink ), - DEFINE_FUNCTION( SlamTouch ), - -END_DATADESC() - - -IMPLEMENT_SERVERCLASS_ST(CWeapon_SLAM, DT_Weapon_SLAM) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_slam, CWeapon_SLAM ); -PRECACHE_WEAPON_REGISTER(weapon_slam); - -acttable_t CWeapon_SLAM::m_acttable[] = -{ - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SLAM, true }, -}; - -IMPLEMENT_ACTTABLE(CWeapon_SLAM); - - -void CWeapon_SLAM::Spawn( ) -{ - BaseClass::Spawn(); - - Precache( ); - - UTIL_SetSize(this, Vector(-4,-4,-2),Vector(4,4,2)); - - FallInit();// get ready to fall down - - SetThink( NULL ); - - m_tSlamState = SLAM_TRIPMINE_READY; - m_flWallSwitchTime = 0; - - // Give 1 piece of default ammo when first picked up - m_iClip2 = 1; -} - -void CWeapon_SLAM::Precache( void ) -{ - BaseClass::Precache(); - - UTIL_PrecacheOther( "npc_tripmine" ); - UTIL_PrecacheOther( "npc_satchel" ); - - PrecacheScriptSound( "Weapon_SLAM.ThrowMode" ); - PrecacheScriptSound( "Weapon_SLAM.TripMineMode" ); - PrecacheScriptSound( "Weapon_SLAM.SatchelDetonate" ); - PrecacheScriptSound( "Weapon_SLAM.TripMineAttach" ); - PrecacheScriptSound( "Weapon_SLAM.SatchelThrow" ); - PrecacheScriptSound( "Weapon_SLAM.SatchelAttach" ); - -} - -//------------------------------------------------------------------------------ -// Purpose : Override to use slam's pickup touch function -// Input : -// Output : -//------------------------------------------------------------------------------ -void CWeapon_SLAM::SetPickupTouch( void ) -{ - SetTouch(&CWeapon_SLAM::SlamTouch); -} - -//----------------------------------------------------------------------------- -// Purpose: Override so give correct ammo -// Input : pOther - the entity that touched me -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::SlamTouch( CBaseEntity *pOther ) -{ - CBaseCombatCharacter* pBCC = ToBaseCombatCharacter( pOther ); - - // Can I even pick stuff up? - if ( pBCC && !pBCC->IsAllowedToPickupWeapons() ) - return; - - // --------------------------------------------------- - // First give weapon to touching entity if allowed - // --------------------------------------------------- - BaseClass::DefaultTouch(pOther); - - // ---------------------------------------------------- - // Give slam ammo if touching client - // ---------------------------------------------------- - if (pOther->GetFlags() & FL_CLIENT) - { - // ------------------------------------------------ - // If already owned weapon of this type remove me - // ------------------------------------------------ - CWeapon_SLAM* oldWeapon = (CWeapon_SLAM*)pBCC->Weapon_OwnsThisType( GetClassname() ); - if (oldWeapon != this) - { - UTIL_Remove( this ); - } - else - { - pBCC->GiveAmmo( 1, m_iSecondaryAmmoType ); - SetThink(NULL); - } - } -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -bool CWeapon_SLAM::Holster( CBaseCombatWeapon *pSwitchingTo ) -{ - SetThink(NULL); - return BaseClass::Holster(pSwitchingTo); -} - -//----------------------------------------------------------------------------- -// Purpose: SLAM has no reload, but must call weapon idle to update state -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CWeapon_SLAM::Reload( void ) -{ - WeaponIdle( ); - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::PrimaryAttack( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - if (!pOwner) - { - return; - } - - if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0) - { - return; - } - - switch (m_tSlamState) - { - case SLAM_TRIPMINE_READY: - if (CanAttachSLAM()) - { - StartTripmineAttach(); - } - break; - case SLAM_SATCHEL_THROW: - StartSatchelThrow(); - break; - case SLAM_SATCHEL_ATTACH: - StartSatchelAttach(); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Secondary attack switches between satchel charge and tripmine mode -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::SecondaryAttack( void ) -{ - return; // Nothin for now. SLAM's just a tripmine. - - CBaseCombatCharacter *pOwner = GetOwner(); - if (!pOwner) - { - return; - } - - if (m_bDetonatorArmed) - { - StartSatchelDetonate(); - } - else if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) > 0) - { - if (m_tSlamState == SLAM_TRIPMINE_READY) - { - // Play sound for going to throw mode - EmitSound( "Weapon_SLAM.ThrowMode" ); - - if (CanAttachSLAM()) - { - SetSlamState(SLAM_SATCHEL_ATTACH); - SendWeaponAnim( ACT_SLAM_TRIPMINE_TO_STICKWALL_ND ); - } - else - { - SetSlamState(SLAM_SATCHEL_THROW); - SendWeaponAnim( ACT_SLAM_TRIPMINE_TO_THROW_ND ); - } - } - else - { - // Play sound for going to tripmine mode - EmitSound( "Weapon_SLAM.TripMineMode" ); - - if (m_tSlamState == SLAM_SATCHEL_ATTACH) - { - SetSlamState(SLAM_TRIPMINE_READY); - SendWeaponAnim( ACT_SLAM_STICKWALL_TO_TRIPMINE_ND ); - } - else - { - SetSlamState(SLAM_TRIPMINE_READY); - SendWeaponAnim( ACT_SLAM_THROW_TO_TRIPMINE_ND ); - } - } - m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::SatchelDetonate() -{ - CBaseEntity *pEntity = NULL; - - while ((pEntity = gEntList.FindEntityByClassname( pEntity, "npc_satchel" )) != NULL) - { - CSatchelCharge *pSatchel = dynamic_cast(pEntity); - if (pSatchel->m_bIsLive && pSatchel->GetThrower() && GetOwner() && pSatchel->GetThrower() == GetOwner()) - { - pSatchel->Use( GetOwner(), GetOwner(), USE_ON, 0 ); - } - } - // Play sound for pressing the detonator - EmitSound( "Weapon_SLAM.SatchelDetonate" ); - - m_bDetonatorArmed = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true if there are any undetonated charges in the world -// that belong to this player -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CWeapon_SLAM::AnyUndetonatedCharges(void) -{ - CBaseEntity *pEntity = NULL; - - while ((pEntity = gEntList.FindEntityByClassname( pEntity, "npc_satchel" )) != NULL) - { - CSatchelCharge* pSatchel = dynamic_cast(pEntity); - if (pSatchel->m_bIsLive && pSatchel->GetThrower() && pSatchel->GetThrower() == GetOwner()) - { - return true; - } - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::StartSatchelDetonate() -{ - // ----------------------------------------- - // Play detonate animation - // ----------------------------------------- - if (m_bNeedReload) - { - SendWeaponAnim(ACT_SLAM_DETONATOR_DETONATE); - } - else if (m_tSlamState == SLAM_SATCHEL_ATTACH) - { - SendWeaponAnim(ACT_SLAM_STICKWALL_DETONATE); - } - else if (m_tSlamState == SLAM_SATCHEL_THROW) - { - SendWeaponAnim(ACT_SLAM_THROW_DETONATE); - } - else - { - return; - } - SatchelDetonate(); - - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::TripmineAttach( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - if (!pOwner) - { - return; - } - - m_bAttachTripmine = false; - - Vector vecSrc = pOwner->Weapon_ShootPosition(); - Vector vecAiming = pOwner->EyeDirection3D(); - - trace_t tr; - - UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); - - if (tr.fraction < 1.0) - { - CBaseEntity *pEntity = tr.m_pEnt; - if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR)) - { - QAngle angles; - VectorAngles(tr.plane.normal, angles); - angles.x += 90; - - CBaseEntity *pEnt = CBaseEntity::Create( "npc_tripmine", tr.endpos + tr.plane.normal * 3, angles, NULL ); - - CTripmineGrenade *pMine = (CTripmineGrenade *)pEnt; - pMine->m_hOwner = GetOwner(); - - pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType ); - - EmitSound( "Weapon_SLAM.TripMineAttach" ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::StartTripmineAttach( void ) -{ - // Only the player fires this way so we can cast - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - if (!pPlayer) - { - return; - } - - Vector vecSrc = pPlayer->Weapon_ShootPosition(); - Vector vecAiming = pPlayer->BodyDirection3D( ); - - trace_t tr; - - UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &tr ); - - if (tr.fraction < 1.0) - { - // ALERT( at_console, "hit %f\n", tr.flFraction ); - - CBaseEntity *pEntity = tr.m_pEnt; - if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR)) - { - // player "shoot" animation - pPlayer->SetAnimation( PLAYER_ATTACK1 ); - - // ----------------------------------------- - // Play attach animation - // ----------------------------------------- - SendWeaponAnim(ACT_SLAM_TRIPMINE_ATTACH); - - m_bNeedReload = true; - m_bAttachTripmine = true; - } - else - { - // ALERT( at_console, "no deploy\n" ); - } - } - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration(); -// SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::SatchelThrow( void ) -{ - - m_bThrowSatchel = false; - - // Only the player fires this way so we can cast - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - Vector vecSrc = pPlayer->WorldSpaceCenter(); - Vector vecFacing = pPlayer->BodyDirection3D( ); - vecSrc = vecSrc + vecFacing * 18.0; - // BUGBUG: is this because vecSrc is not from Weapon_ShootPosition()??? - vecSrc.z += 24.0f; - - Vector vecThrow; - GetOwner()->GetVelocity( &vecThrow, NULL ); - vecThrow += vecFacing * 500; - - // Player may have turned to face a wall during the throw anim in which case - // we don't want to throw the SLAM into the wall - if (CanAttachSLAM()) - { - vecThrow = vecFacing; - vecSrc = pPlayer->WorldSpaceCenter() + vecFacing * 5.0; - } - - CSatchelCharge *pSatchel = (CSatchelCharge*)Create( "npc_satchel", vecSrc, vec3_angle, GetOwner() ); - pSatchel->SetThrower( GetOwner() ); - pSatchel->ApplyAbsVelocityImpulse( vecThrow ); - pSatchel->SetLocalAngularVelocity( QAngle( 0, 400, 0 ) ); - pSatchel->m_bIsLive = true; - pSatchel->m_pMyWeaponSLAM = this; - - pPlayer->RemoveAmmo( 1, m_iSecondaryAmmoType ); - - // Play throw sound - EmitSound( "Weapon_SLAM.SatchelThrow" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::StartSatchelThrow( void ) -{ - // ----------------------------------------- - // Play throw animation - // ----------------------------------------- - if (m_bDetonatorArmed) - { - SendWeaponAnim(ACT_SLAM_THROW_THROW); - } - else - { - SendWeaponAnim(ACT_SLAM_THROW_THROW_ND); - if (!m_bDetonatorArmed) - { - m_bDetonatorArmed = true; - m_bNeedDetonatorDraw = true; - } - } - - m_bNeedReload = true; - m_bThrowSatchel = true; - - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::SatchelAttach( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - if (!pOwner) - { - return; - } - - m_bAttachSatchel = false; - - Vector vecSrc = pOwner->Weapon_ShootPosition( ); - Vector vecAiming = pOwner->BodyDirection2D( ); - - trace_t tr; - - UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); - - if (tr.fraction < 1.0) - { - CBaseEntity *pEntity = tr.m_pEnt; - if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR)) - { - QAngle angles; - VectorAngles(tr.plane.normal, angles); - angles.y -= 90; - angles.z -= 90; - tr.endpos.z -= 6.0f; - - EmitSound( "Weapon_SLAM.SatchelAttach" ); - - CSatchelCharge *pSatchel = (CSatchelCharge*)CBaseEntity::Create( "npc_satchel", tr.endpos + tr.plane.normal * 3, angles, NULL ); - pSatchel->SetMoveType( MOVETYPE_FLY ); // no gravity - pSatchel->m_bIsAttached = true; - pSatchel->m_bIsLive = true; - pSatchel->SetThrower( GetOwner() ); - pSatchel->SetOwnerEntity( ((CBaseEntity*)GetOwner()) ); - pSatchel->m_pMyWeaponSLAM = this; - - pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::StartSatchelAttach( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - if (!pOwner) - { - return; - } - - Vector vecSrc = pOwner->Weapon_ShootPosition( ); - Vector vecAiming = pOwner->BodyDirection2D( ); - - trace_t tr; - - UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); - - if (tr.fraction < 1.0) - { - CBaseEntity *pEntity = tr.m_pEnt; - if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR)) - { - // Only the player fires this way so we can cast - CBasePlayer *pPlayer = ToBasePlayer( pOwner ); - - // player "shoot" animation - pPlayer->SetAnimation( PLAYER_ATTACK1 ); - - // ----------------------------------------- - // Play attach animation - // ----------------------------------------- - if (m_bDetonatorArmed) - { - SendWeaponAnim(ACT_SLAM_STICKWALL_ATTACH); - } - else - { - SendWeaponAnim(ACT_SLAM_STICKWALL_ND_ATTACH); - if (!m_bDetonatorArmed) - { - m_bDetonatorArmed = true; - m_bNeedDetonatorDraw = true; - } - } - - m_bNeedReload = true; - m_bAttachSatchel = true; - - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::SetSlamState( SlamState_t newState ) -{ - // Set set and set idle time so animation gets updated with state change - m_tSlamState = newState; - SetWeaponIdleTime( gpGlobals->curtime ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::SLAMThink( void ) -{ - if (m_flWallSwitchTime <= gpGlobals->curtime) - { - // If not in tripmine mode we need to check to see if we are close to - // a wall. If we are we go into satchel_attach mode - CBaseCombatCharacter *pOwner = GetOwner(); - - if ((m_tSlamState != SLAM_TRIPMINE_READY) && (pOwner && pOwner->GetAmmoCount(m_iSecondaryAmmoType) > 0)) - { - if (CanAttachSLAM()) - { - if (m_tSlamState == SLAM_SATCHEL_THROW) - { - SetSlamState(SLAM_SATCHEL_ATTACH); - int iAnim = m_bDetonatorArmed ? ACT_SLAM_THROW_TO_STICKWALL : ACT_SLAM_THROW_TO_STICKWALL_ND; - SendWeaponAnim( iAnim ); - m_flWallSwitchTime = gpGlobals->curtime + SequenceDuration(); - } - } - else - { - if (m_tSlamState == SLAM_SATCHEL_ATTACH) - { - SetSlamState(SLAM_SATCHEL_THROW); - int iAnim = m_bDetonatorArmed ? ACT_SLAM_STICKWALL_TO_THROW : ACT_SLAM_STICKWALL_TO_THROW_ND; - SendWeaponAnim( iAnim ); - m_flWallSwitchTime = gpGlobals->curtime + SequenceDuration(); - } - } - } - } - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CWeapon_SLAM::CanAttachSLAM( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - if (!pOwner) - { - return false; - } - - Vector vecSrc = pOwner->Weapon_ShootPosition( ); - Vector vecAiming = pOwner->BodyDirection2D( ); - - trace_t tr; - - Vector vecEnd = vecSrc + (vecAiming * 42); - UTIL_TraceLine( vecSrc, vecEnd, MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); - - if (tr.fraction < 1.0) - { - // Don't attach to a living creature - if (tr.m_pEnt) - { - CBaseEntity *pEntity = tr.m_pEnt; - CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pEntity ); - if (pBCC) - { - return false; - } - } - return true; - } - else - { - return false; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Override so SLAM to so secondary attack when no secondary ammo -// but satchel is in the world -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::ItemPostFrame( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if (!pOwner) - { - return; - } - - if ((pOwner->m_nButtons & IN_ATTACK2) && (m_flNextSecondaryAttack <= gpGlobals->curtime)) - { - SecondaryAttack(); - } - else if (!m_bNeedReload && (pOwner->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime)) - { - PrimaryAttack(); - } - - // ----------------------- - // No buttons down - // ----------------------- - else - { - WeaponIdle( ); - return; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Switch to next best weapon -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::WeaponSwitch( void ) -{ - // Note that we may pick the SLAM again, when we switch - // weapons, in which case we have to save and restore the - // detonator armed state. - // The SLAMs may be about to blow up, but haven't done so yet - // and the deploy function will find the undetonated charges - // and we are armed - bool saveState = m_bDetonatorArmed; - CBaseCombatCharacter *pOwner = GetOwner(); - pOwner->SwitchToNextBestWeapon( pOwner->GetActiveWeapon() ); - if (pOwner->GetActiveWeapon() == this) - { - m_bDetonatorArmed = saveState; - } - - // If not armed and have no ammo - if (!m_bDetonatorArmed && pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0) - { - pOwner->ClearActiveWeapon(); - } - -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::WeaponIdle( void ) -{ - // Ready to switch animations? - if ( HasWeaponIdleTimeElapsed() ) - { - // Don't allow throw to attach switch unless in idle - m_flWallSwitchTime = gpGlobals->curtime + 50; - - if (m_bClearReload) - { - m_bNeedReload = false; - m_bClearReload = false; - } - CBaseCombatCharacter *pOwner = GetOwner(); - if (!pOwner) - { - return; - } - - int iAnim = 0; - - if (m_bThrowSatchel) - { - SatchelThrow(); - if (m_bDetonatorArmed && !m_bNeedDetonatorDraw) - { - iAnim = ACT_SLAM_THROW_THROW2; - } - else - { - iAnim = ACT_SLAM_THROW_THROW_ND2; - } - } - else if (m_bAttachSatchel) - { - SatchelAttach(); - if (m_bDetonatorArmed && !m_bNeedDetonatorDraw) - { - iAnim = ACT_SLAM_STICKWALL_ATTACH2; - } - else - { - iAnim = ACT_SLAM_STICKWALL_ND_ATTACH2; - } - } - else if (m_bAttachTripmine) - { - TripmineAttach(); - iAnim = ACT_SLAM_TRIPMINE_ATTACH2; - } - else if (m_bNeedReload) - { - // If owner had ammo draw the correct SLAM type - if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) > 0) - { - switch( m_tSlamState) - { - case SLAM_TRIPMINE_READY: - { - iAnim = ACT_SLAM_TRIPMINE_DRAW; - } - break; - case SLAM_SATCHEL_ATTACH: - { - if (m_bNeedDetonatorHolster) - { - iAnim = ACT_SLAM_STICKWALL_DETONATOR_HOLSTER; - m_bNeedDetonatorHolster = false; - } - else if (m_bDetonatorArmed) - { - iAnim = m_bNeedDetonatorDraw ? ACT_SLAM_DETONATOR_STICKWALL_DRAW : ACT_SLAM_STICKWALL_DRAW; - m_bNeedDetonatorDraw = false; - } - else - { - iAnim = ACT_SLAM_STICKWALL_ND_DRAW; - } - } - break; - case SLAM_SATCHEL_THROW: - { - if (m_bNeedDetonatorHolster) - { - iAnim = ACT_SLAM_THROW_DETONATOR_HOLSTER; - m_bNeedDetonatorHolster = false; - } - else if (m_bDetonatorArmed) - { - iAnim = m_bNeedDetonatorDraw ? ACT_SLAM_DETONATOR_THROW_DRAW : ACT_SLAM_THROW_DRAW; - m_bNeedDetonatorDraw = false; - } - else - { - iAnim = ACT_SLAM_THROW_ND_DRAW; - } - } - break; - } - m_bClearReload = true; - } - // If no ammo and armed, idle with only the detonator - else if (m_bDetonatorArmed) - { - iAnim = m_bNeedDetonatorDraw ? ACT_SLAM_DETONATOR_DRAW : ACT_SLAM_DETONATOR_IDLE; - m_bNeedDetonatorDraw = false; - } - else - { - pOwner->Weapon_Drop( this ); - UTIL_Remove(this); - } - } - else if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0) - { - pOwner->Weapon_Drop( this ); - UTIL_Remove(this); - } - - // If I don't need to reload just do the appropriate idle - else - { - switch( m_tSlamState) - { - case SLAM_TRIPMINE_READY: - { - iAnim = ACT_SLAM_TRIPMINE_IDLE; - } - break; - case SLAM_SATCHEL_THROW: - { - if (m_bNeedDetonatorHolster) - { - iAnim = ACT_SLAM_THROW_DETONATOR_HOLSTER; - m_bNeedDetonatorHolster = false; - } - else - { - iAnim = m_bDetonatorArmed ? ACT_SLAM_THROW_IDLE : ACT_SLAM_THROW_ND_IDLE; - m_flWallSwitchTime = 0; - } - } - break; - case SLAM_SATCHEL_ATTACH: - { - if (m_bNeedDetonatorHolster) - { - iAnim = ACT_SLAM_STICKWALL_DETONATOR_HOLSTER; - m_bNeedDetonatorHolster = false; - } - else - { - iAnim = m_bDetonatorArmed ? ACT_SLAM_STICKWALL_IDLE : ACT_SLAM_STICKWALL_ND_IDLE; - m_flWallSwitchTime = 0; - } - } - break; - } - } - SendWeaponAnim( iAnim ); - } -} - -bool CWeapon_SLAM::Deploy( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - if (!pOwner) - { - return false; - } - - m_bDetonatorArmed = AnyUndetonatedCharges(); - - - SetThink( &CWeapon_SLAM::SLAMThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - SetModel( GetViewModel() ); - - // ------------------------------ - // Pick the right draw animation - // ------------------------------ - int iActivity; - - // If detonator is already armed - m_bNeedReload = false; - if (m_bDetonatorArmed) - { - if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0) - { - iActivity = ACT_SLAM_DETONATOR_DRAW; - m_bNeedReload = true; - } - else if (CanAttachSLAM()) - { - iActivity = ACT_SLAM_DETONATOR_STICKWALL_DRAW; - } - else - { - iActivity = ACT_SLAM_DETONATOR_THROW_DRAW; - } - } - else - { - if (CanAttachSLAM()) - { - iActivity = ACT_SLAM_STICKWALL_ND_DRAW; - } - else - { - iActivity = ACT_SLAM_THROW_ND_DRAW; - } - } - - return DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), iActivity, (char*)GetAnimPrefix() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Constructor -// Input : -// Output : -//----------------------------------------------------------------------------- -CWeapon_SLAM::CWeapon_SLAM(void) -{ - m_tSlamState = SLAM_SATCHEL_THROW; - m_bDetonatorArmed = false; - m_bNeedReload = true; - m_bClearReload = false; - m_bThrowSatchel = false; - m_bAttachSatchel = false; - m_bAttachTripmine = false; - m_bNeedDetonatorDraw = false; - m_bNeedDetonatorHolster = false; -} diff --git a/game/server/hl2/weapon_slam.h b/game/server/hl2/weapon_slam.h deleted file mode 100644 index 8171501c3..000000000 --- a/game/server/hl2/weapon_slam.h +++ /dev/null @@ -1,83 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: SLAM -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef WEAPONSLAM_H -#define WEAPONSLAM_H -#ifndef HL2MP - -#include "basegrenade_shared.h" -#include "basehlcombatweapon.h" - -enum SlamState_t -{ - SLAM_TRIPMINE_READY, - SLAM_SATCHEL_THROW, - SLAM_SATCHEL_ATTACH, -}; - -class CWeapon_SLAM : public CBaseHLCombatWeapon -{ -public: - DECLARE_CLASS( CWeapon_SLAM, CBaseHLCombatWeapon ); - - DECLARE_SERVERCLASS(); - - SlamState_t m_tSlamState; - bool m_bDetonatorArmed; - bool m_bNeedDetonatorDraw; - bool m_bNeedDetonatorHolster; - bool m_bNeedReload; - bool m_bClearReload; - bool m_bThrowSatchel; - bool m_bAttachSatchel; - bool m_bAttachTripmine; - float m_flWallSwitchTime; - - void Spawn( void ); - void Precache( void ); - - int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } - void PrimaryAttack( void ); - void SecondaryAttack( void ); - void WeaponIdle( void ); - void WeaponSwitch( void ); - void SLAMThink( void ); - - void SetPickupTouch( void ); - void SlamTouch( CBaseEntity *pOther ); // default weapon touch - void ItemPostFrame( void ); - bool Reload( void ); - void SetSlamState( SlamState_t newState ); - bool CanAttachSLAM(void); // In position where can attach SLAM? - bool AnyUndetonatedCharges(void); - void StartTripmineAttach( void ); - void TripmineAttach( void ); - - void StartSatchelDetonate( void ); - void SatchelDetonate( void ); - void StartSatchelThrow( void ); - void StartSatchelAttach( void ); - void SatchelThrow( void ); - void SatchelAttach( void ); - bool Deploy( void ); - bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); - - - CWeapon_SLAM(); - - DECLARE_ACTTABLE(); - DECLARE_DATADESC(); -}; - -#endif //HL2MP -#endif //WEAPONSLAM_H diff --git a/game/server/hl2/weapon_smg1.cpp b/game/server/hl2/weapon_smg1.cpp deleted file mode 100644 index 1615d14e4..000000000 --- a/game/server/hl2/weapon_smg1.cpp +++ /dev/null @@ -1,512 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "basehlcombatweapon.h" -#include "npcevent.h" -#include "basecombatcharacter.h" -#include "ai_basenpc.h" -#include "player.h" -#include "game.h" -#include "in_buttons.h" -#include "grenade_ar2.h" -#include "ai_memory.h" -#include "soundent.h" -#include "rumble_shared.h" -#include "GameStats.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern ConVar sk_plr_dmg_smg1_grenade; - -class CWeaponSMG1 : public CHLSelectFireMachineGun -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( CWeaponSMG1, CHLSelectFireMachineGun ); - - CWeaponSMG1(); - - DECLARE_SERVERCLASS(); - - void Precache( void ); - void AddViewKick( void ); - void SecondaryAttack( void ); - - int GetMinBurst() { return 2; } - int GetMaxBurst() { return 5; } - - virtual void Equip( CBaseCombatCharacter *pOwner ); - bool Reload( void ); - - float GetFireRate( void ) { return 0.075f; } // 13.3hz - int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } - int WeaponRangeAttack2Condition( float flDot, float flDist ); - Activity GetPrimaryAttackActivity( void ); - - virtual const Vector& GetBulletSpread( void ) - { - static const Vector cone = VECTOR_CONE_5DEGREES; - return cone; - } - - const WeaponProficiencyInfo_t *GetProficiencyValues(); - - void FireNPCPrimaryAttack( CBaseCombatCharacter *pOperator, Vector &vecShootOrigin, Vector &vecShootDir ); - void Operator_ForceNPCFire( CBaseCombatCharacter *pOperator, bool bSecondary ); - void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); - - DECLARE_ACTTABLE(); - -protected: - - Vector m_vecTossVelocity; - float m_flNextGrenadeCheck; -}; - -IMPLEMENT_SERVERCLASS_ST(CWeaponSMG1, DT_WeaponSMG1) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_smg1, CWeaponSMG1 ); -PRECACHE_WEAPON_REGISTER(weapon_smg1); - -BEGIN_DATADESC( CWeaponSMG1 ) - - DEFINE_FIELD( m_vecTossVelocity, FIELD_VECTOR ), - DEFINE_FIELD( m_flNextGrenadeCheck, FIELD_TIME ), - -END_DATADESC() - -acttable_t CWeaponSMG1::m_acttable[] = -{ - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SMG1, true }, - { ACT_RELOAD, ACT_RELOAD_SMG1, true }, - { ACT_IDLE, ACT_IDLE_SMG1, true }, - { ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_SMG1, true }, - - { ACT_WALK, ACT_WALK_RIFLE, true }, - { ACT_WALK_AIM, ACT_WALK_AIM_RIFLE, true }, - -// Readiness activities (not aiming) - { ACT_IDLE_RELAXED, ACT_IDLE_SMG1_RELAXED, false },//never aims - { ACT_IDLE_STIMULATED, ACT_IDLE_SMG1_STIMULATED, false }, - { ACT_IDLE_AGITATED, ACT_IDLE_ANGRY_SMG1, false },//always aims - - { ACT_WALK_RELAXED, ACT_WALK_RIFLE_RELAXED, false },//never aims - { ACT_WALK_STIMULATED, ACT_WALK_RIFLE_STIMULATED, false }, - { ACT_WALK_AGITATED, ACT_WALK_AIM_RIFLE, false },//always aims - - { ACT_RUN_RELAXED, ACT_RUN_RIFLE_RELAXED, false },//never aims - { ACT_RUN_STIMULATED, ACT_RUN_RIFLE_STIMULATED, false }, - { ACT_RUN_AGITATED, ACT_RUN_AIM_RIFLE, false },//always aims - -// Readiness activities (aiming) - { ACT_IDLE_AIM_RELAXED, ACT_IDLE_SMG1_RELAXED, false },//never aims - { ACT_IDLE_AIM_STIMULATED, ACT_IDLE_AIM_RIFLE_STIMULATED, false }, - { ACT_IDLE_AIM_AGITATED, ACT_IDLE_ANGRY_SMG1, false },//always aims - - { ACT_WALK_AIM_RELAXED, ACT_WALK_RIFLE_RELAXED, false },//never aims - { ACT_WALK_AIM_STIMULATED, ACT_WALK_AIM_RIFLE_STIMULATED, false }, - { ACT_WALK_AIM_AGITATED, ACT_WALK_AIM_RIFLE, false },//always aims - - { ACT_RUN_AIM_RELAXED, ACT_RUN_RIFLE_RELAXED, false },//never aims - { ACT_RUN_AIM_STIMULATED, ACT_RUN_AIM_RIFLE_STIMULATED, false }, - { ACT_RUN_AIM_AGITATED, ACT_RUN_AIM_RIFLE, false },//always aims -//End readiness activities - - { ACT_WALK_AIM, ACT_WALK_AIM_RIFLE, true }, - { ACT_WALK_CROUCH, ACT_WALK_CROUCH_RIFLE, true }, - { ACT_WALK_CROUCH_AIM, ACT_WALK_CROUCH_AIM_RIFLE, true }, - { ACT_RUN, ACT_RUN_RIFLE, true }, - { ACT_RUN_AIM, ACT_RUN_AIM_RIFLE, true }, - { ACT_RUN_CROUCH, ACT_RUN_CROUCH_RIFLE, true }, - { ACT_RUN_CROUCH_AIM, ACT_RUN_CROUCH_AIM_RIFLE, true }, - { ACT_GESTURE_RANGE_ATTACK1, ACT_GESTURE_RANGE_ATTACK_SMG1, true }, - { ACT_RANGE_ATTACK1_LOW, ACT_RANGE_ATTACK_SMG1_LOW, true }, - { ACT_COVER_LOW, ACT_COVER_SMG1_LOW, false }, - { ACT_RANGE_AIM_LOW, ACT_RANGE_AIM_SMG1_LOW, false }, - { ACT_RELOAD_LOW, ACT_RELOAD_SMG1_LOW, false }, - { ACT_GESTURE_RELOAD, ACT_GESTURE_RELOAD_SMG1, true }, -}; - -IMPLEMENT_ACTTABLE(CWeaponSMG1); - -//========================================================= -CWeaponSMG1::CWeaponSMG1( ) -{ - m_fMinRange1 = 0;// No minimum range. - m_fMaxRange1 = 1400; - - m_bAltFiresUnderwater = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponSMG1::Precache( void ) -{ - UTIL_PrecacheOther("grenade_ar2"); - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: Give this weapon longer range when wielded by an ally NPC. -//----------------------------------------------------------------------------- -void CWeaponSMG1::Equip( CBaseCombatCharacter *pOwner ) -{ - if( pOwner->Classify() == CLASS_PLAYER_ALLY ) - { - m_fMaxRange1 = 3000; - } - else - { - m_fMaxRange1 = 1400; - } - - BaseClass::Equip( pOwner ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponSMG1::FireNPCPrimaryAttack( CBaseCombatCharacter *pOperator, Vector &vecShootOrigin, Vector &vecShootDir ) -{ - // FIXME: use the returned number of bullets to account for >10hz firerate - WeaponSoundRealtime( SINGLE_NPC ); - - CSoundEnt::InsertSound( SOUND_COMBAT|SOUND_CONTEXT_GUNFIRE, pOperator->GetAbsOrigin(), SOUNDENT_VOLUME_MACHINEGUN, 0.2, pOperator, SOUNDENT_CHANNEL_WEAPON, pOperator->GetEnemy() ); - pOperator->FireBullets( 1, vecShootOrigin, vecShootDir, VECTOR_CONE_PRECALCULATED, - MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 2, entindex(), 0 ); - - pOperator->DoMuzzleFlash(); - m_iClip1 = m_iClip1 - 1; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponSMG1::Operator_ForceNPCFire( CBaseCombatCharacter *pOperator, bool bSecondary ) -{ - // Ensure we have enough rounds in the clip - m_iClip1++; - - Vector vecShootOrigin, vecShootDir; - QAngle angShootDir; - GetAttachment( LookupAttachment( "muzzle" ), vecShootOrigin, angShootDir ); - AngleVectors( angShootDir, &vecShootDir ); - FireNPCPrimaryAttack( pOperator, vecShootOrigin, vecShootDir ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponSMG1::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - switch( pEvent->event ) - { - case EVENT_WEAPON_SMG1: - { - Vector vecShootOrigin, vecShootDir; - QAngle angDiscard; - - // Support old style attachment point firing - if ((pEvent->options == NULL) || (pEvent->options[0] == '\0') || (!pOperator->GetAttachment(pEvent->options, vecShootOrigin, angDiscard))) - { - vecShootOrigin = pOperator->Weapon_ShootPosition(); - } - - CAI_BaseNPC *npc = pOperator->MyNPCPointer(); - ASSERT( npc != NULL ); - vecShootDir = npc->GetActualShootTrajectory( vecShootOrigin ); - - FireNPCPrimaryAttack( pOperator, vecShootOrigin, vecShootDir ); - } - break; - - /*//FIXME: Re-enable - case EVENT_WEAPON_AR2_GRENADE: - { - CAI_BaseNPC *npc = pOperator->MyNPCPointer(); - - Vector vecShootOrigin, vecShootDir; - vecShootOrigin = pOperator->Weapon_ShootPosition(); - vecShootDir = npc->GetShootEnemyDir( vecShootOrigin ); - - Vector vecThrow = m_vecTossVelocity; - - CGrenadeAR2 *pGrenade = (CGrenadeAR2*)Create( "grenade_ar2", vecShootOrigin, vec3_angle, npc ); - pGrenade->SetAbsVelocity( vecThrow ); - pGrenade->SetLocalAngularVelocity( QAngle( 0, 400, 0 ) ); - pGrenade->SetMoveType( MOVETYPE_FLYGRAVITY ); - pGrenade->m_hOwner = npc; - pGrenade->m_pMyWeaponAR2 = this; - pGrenade->SetDamage(sk_npc_dmg_ar2_grenade.GetFloat()); - - // FIXME: arrgg ,this is hard coded into the weapon??? - m_flNextGrenadeCheck = gpGlobals->curtime + 6;// wait six seconds before even looking again to see if a grenade can be thrown. - - m_iClip2--; - } - break; - */ - - default: - BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Activity -//----------------------------------------------------------------------------- -Activity CWeaponSMG1::GetPrimaryAttackActivity( void ) -{ - if ( m_nShotsFired < 2 ) - return ACT_VM_PRIMARYATTACK; - - if ( m_nShotsFired < 3 ) - return ACT_VM_RECOIL1; - - if ( m_nShotsFired < 4 ) - return ACT_VM_RECOIL2; - - return ACT_VM_RECOIL3; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CWeaponSMG1::Reload( void ) -{ - bool fRet; - float fCacheTime = m_flNextSecondaryAttack; - - fRet = DefaultReload( GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD ); - if ( fRet ) - { - // Undo whatever the reload process has done to our secondary - // attack timer. We allow you to interrupt reloading to fire - // a grenade. - m_flNextSecondaryAttack = GetOwner()->m_flNextAttack = fCacheTime; - - WeaponSound( RELOAD ); - } - - return fRet; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponSMG1::AddViewKick( void ) -{ - #define EASY_DAMPEN 0.5f - #define MAX_VERTICAL_KICK 1.0f //Degrees - #define SLIDE_LIMIT 2.0f //Seconds - - //Get the view kick - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if ( pPlayer == NULL ) - return; - - DoMachineGunKick( pPlayer, EASY_DAMPEN, MAX_VERTICAL_KICK, m_fFireDuration, SLIDE_LIMIT ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponSMG1::SecondaryAttack( void ) -{ - // Only the player fires this way so we can cast - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if ( pPlayer == NULL ) - return; - - //Must have ammo - if ( ( pPlayer->GetAmmoCount( m_iSecondaryAmmoType ) <= 0 ) || ( pPlayer->GetWaterLevel() == 3 ) ) - { - SendWeaponAnim( ACT_VM_DRYFIRE ); - BaseClass::WeaponSound( EMPTY ); - m_flNextSecondaryAttack = gpGlobals->curtime + 0.5f; - return; - } - - if( m_bInReload ) - m_bInReload = false; - - // MUST call sound before removing a round from the clip of a CMachineGun - BaseClass::WeaponSound( WPN_DOUBLE ); - - pPlayer->RumbleEffect( RUMBLE_357, 0, RUMBLE_FLAGS_NONE ); - - Vector vecSrc = pPlayer->Weapon_ShootPosition(); - Vector vecThrow; - // Don't autoaim on grenade tosses - AngleVectors( pPlayer->EyeAngles() + pPlayer->GetPunchAngle(), &vecThrow ); - VectorScale( vecThrow, 1000.0f, vecThrow ); - - //Create the grenade - QAngle angles; - VectorAngles( vecThrow, angles ); - CGrenadeAR2 *pGrenade = (CGrenadeAR2*)Create( "grenade_ar2", vecSrc, angles, pPlayer ); - pGrenade->SetAbsVelocity( vecThrow ); - - pGrenade->SetLocalAngularVelocity( RandomAngle( -400, 400 ) ); - pGrenade->SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); - pGrenade->SetThrower( GetOwner() ); - pGrenade->SetDamage( sk_plr_dmg_smg1_grenade.GetFloat() ); - - SendWeaponAnim( ACT_VM_SECONDARYATTACK ); - - CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 1000, 0.2, GetOwner(), SOUNDENT_CHANNEL_WEAPON ); - - // player "shoot" animation - pPlayer->SetAnimation( PLAYER_ATTACK1 ); - - // Decrease ammo - pPlayer->RemoveAmmo( 1, m_iSecondaryAmmoType ); - - // Can shoot again immediately - m_flNextPrimaryAttack = gpGlobals->curtime + 0.5f; - - // Can blow up after a short delay (so have time to release mouse button) - m_flNextSecondaryAttack = gpGlobals->curtime + 1.0f; - - // Register a muzzleflash for the AI. - pPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 ); - - m_iSecondaryAttacks++; - gamestats->Event_WeaponFired( pPlayer, false, GetClassname() ); -} - -#define COMBINE_MIN_GRENADE_CLEAR_DIST 256 - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flDot - -// flDist - -// Output : int -//----------------------------------------------------------------------------- -int CWeaponSMG1::WeaponRangeAttack2Condition( float flDot, float flDist ) -{ - CAI_BaseNPC *npcOwner = GetOwner()->MyNPCPointer(); - - return COND_NONE; - -/* - // -------------------------------------------------------- - // Assume things haven't changed too much since last time - // -------------------------------------------------------- - if (gpGlobals->curtime < m_flNextGrenadeCheck ) - return m_lastGrenadeCondition; -*/ - - // ----------------------- - // If moving, don't check. - // ----------------------- - if ( npcOwner->IsMoving()) - return COND_NONE; - - CBaseEntity *pEnemy = npcOwner->GetEnemy(); - - if (!pEnemy) - return COND_NONE; - - Vector vecEnemyLKP = npcOwner->GetEnemyLKP(); - if ( !( pEnemy->GetFlags() & FL_ONGROUND ) && pEnemy->GetWaterLevel() == 0 && vecEnemyLKP.z > (GetAbsOrigin().z + WorldAlignMaxs().z) ) - { - //!!!BUGBUG - we should make this check movetype and make sure it isn't FLY? Players who jump a lot are unlikely to - // be grenaded. - // don't throw grenades at anything that isn't on the ground! - return COND_NONE; - } - - // -------------------------------------- - // Get target vector - // -------------------------------------- - Vector vecTarget; - if (random->RandomInt(0,1)) - { - // magically know where they are - vecTarget = pEnemy->WorldSpaceCenter(); - } - else - { - // toss it to where you last saw them - vecTarget = vecEnemyLKP; - } - // vecTarget = m_vecEnemyLKP + (pEnemy->BodyTarget( GetLocalOrigin() ) - pEnemy->GetLocalOrigin()); - // estimate position - // vecTarget = vecTarget + pEnemy->m_vecVelocity * 2; - - - if ( ( vecTarget - npcOwner->GetLocalOrigin() ).Length2D() <= COMBINE_MIN_GRENADE_CLEAR_DIST ) - { - // crap, I don't want to blow myself up - m_flNextGrenadeCheck = gpGlobals->curtime + 1; // one full second. - return (COND_NONE); - } - - // --------------------------------------------------------------------- - // Are any friendlies near the intended grenade impact area? - // --------------------------------------------------------------------- - CBaseEntity *pTarget = NULL; - - while ( ( pTarget = gEntList.FindEntityInSphere( pTarget, vecTarget, COMBINE_MIN_GRENADE_CLEAR_DIST ) ) != NULL ) - { - //Check to see if the default relationship is hatred, and if so intensify that - if ( npcOwner->IRelationType( pTarget ) == D_LI ) - { - // crap, I might blow my own guy up. Don't throw a grenade and don't check again for a while. - m_flNextGrenadeCheck = gpGlobals->curtime + 1; // one full second. - return (COND_WEAPON_BLOCKED_BY_FRIEND); - } - } - - // --------------------------------------------------------------------- - // Check that throw is legal and clear - // --------------------------------------------------------------------- - // FIXME: speed is based on difficulty... - - Vector vecToss = VecCheckThrow( this, npcOwner->GetLocalOrigin() + Vector(0,0,60), vecTarget, 600.0, 0.5 ); - if ( vecToss != vec3_origin ) - { - m_vecTossVelocity = vecToss; - - // don't check again for a while. - // JAY: HL1 keeps checking - test? - //m_flNextGrenadeCheck = gpGlobals->curtime; - m_flNextGrenadeCheck = gpGlobals->curtime + 0.3; // 1/3 second. - return COND_CAN_RANGE_ATTACK2; - } - else - { - // don't check again for a while. - m_flNextGrenadeCheck = gpGlobals->curtime + 1; // one full second. - return COND_WEAPON_SIGHT_OCCLUDED; - } -} - -//----------------------------------------------------------------------------- -const WeaponProficiencyInfo_t *CWeaponSMG1::GetProficiencyValues() -{ - static WeaponProficiencyInfo_t proficiencyTable[] = - { - { 7.0, 0.75 }, - { 5.00, 0.75 }, - { 10.0/3.0, 0.75 }, - { 5.0/3.0, 0.75 }, - { 1.00, 1.0 }, - }; - - COMPILE_TIME_ASSERT( ARRAYSIZE(proficiencyTable) == WEAPON_PROFICIENCY_PERFECT + 1); - - return proficiencyTable; -} diff --git a/game/server/hl2/weapon_smg2.cpp b/game/server/hl2/weapon_smg2.cpp deleted file mode 100644 index 65876f662..000000000 --- a/game/server/hl2/weapon_smg2.cpp +++ /dev/null @@ -1,123 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "basehlcombatweapon.h" -#include "npcevent.h" -#include "basecombatcharacter.h" -#include "ai_basenpc.h" -#include "player.h" -#include "game.h" -#include "in_buttons.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CWeaponSMG2 : public CHLSelectFireMachineGun -{ -public: - DECLARE_CLASS( CWeaponSMG2, CHLSelectFireMachineGun ); - - CWeaponSMG2(); - - DECLARE_SERVERCLASS(); - - const Vector &GetBulletSpread( void ); - - void Precache( void ); - void AddViewKick( void ); - void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); - - float GetFireRate( void ) { return 0.1f; } - int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } - - DECLARE_ACTTABLE(); -}; - -IMPLEMENT_SERVERCLASS_ST(CWeaponSMG2, DT_WeaponSMG2) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_smg2, CWeaponSMG2 ); -PRECACHE_WEAPON_REGISTER(weapon_smg2); - -acttable_t CWeaponSMG2::m_acttable[] = -{ - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SMG2, true }, -}; - -IMPLEMENT_ACTTABLE(CWeaponSMG2); - -//========================================================= -CWeaponSMG2::CWeaponSMG2( ) -{ - m_fMaxRange1 = 2000; - m_fMinRange1 = 32; - - m_iFireMode = FIREMODE_3RNDBURST; -} - -void CWeaponSMG2::Precache( void ) -{ - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const Vector -//----------------------------------------------------------------------------- -const Vector &CWeaponSMG2::GetBulletSpread( void ) -{ - static const Vector cone = VECTOR_CONE_10DEGREES; - return cone; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEvent - -// *pOperator - -//----------------------------------------------------------------------------- -void CWeaponSMG2::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - switch( pEvent->event ) - { - case EVENT_WEAPON_SMG2: - { - Vector vecShootOrigin, vecShootDir; - vecShootOrigin = pOperator->Weapon_ShootPosition( ); - - CAI_BaseNPC *npc = pOperator->MyNPCPointer(); - ASSERT( npc != NULL ); - vecShootDir = npc->GetActualShootTrajectory( vecShootOrigin ); - - WeaponSound(SINGLE_NPC); - pOperator->FireBullets( 1, vecShootOrigin, vecShootDir, VECTOR_CONE_PRECALCULATED, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, 2 ); - pOperator->DoMuzzleFlash(); - m_iClip1 = m_iClip1 - 1; - } - break; - default: - BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponSMG2::AddViewKick( void ) -{ - #define EASY_DAMPEN 0.5f - #define MAX_VERTICAL_KICK 2.0f //Degrees - #define SLIDE_LIMIT 1.0f //Seconds - - //Get the view kick - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if (!pPlayer) - return; - - DoMachineGunKick( pPlayer, EASY_DAMPEN, MAX_VERTICAL_KICK, m_fFireDuration, SLIDE_LIMIT ); -} diff --git a/game/server/hl2/weapon_sniperrifle.cpp b/game/server/hl2/weapon_sniperrifle.cpp deleted file mode 100644 index e721438d9..000000000 --- a/game/server/hl2/weapon_sniperrifle.cpp +++ /dev/null @@ -1,447 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements a sniper rifle weapon. -// -// Primary attack: fires a single high-powered shot, then reloads. -// Secondary attack: cycles sniper scope through zoom levels. -// -// TODO: Circular mask around crosshairs when zoomed in. -// TODO: Shell ejection. -// TODO: Finalize kickback. -// TODO: Animated zoom effect? -// -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" -#include "basehlcombatweapon.h" -#include "basecombatcharacter.h" -#include "ai_basenpc.h" -#include "player.h" -#include "gamerules.h" // For g_pGameRules -#include "in_buttons.h" -#include "soundent.h" -#include "vstdlib/random.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SNIPER_CONE_PLAYER vec3_origin // Spread cone when fired by the player. -#define SNIPER_CONE_NPC vec3_origin // Spread cone when fired by NPCs. -#define SNIPER_BULLET_COUNT_PLAYER 1 // Fire n bullets per shot fired by the player. -#define SNIPER_BULLET_COUNT_NPC 1 // Fire n bullets per shot fired by NPCs. -#define SNIPER_TRACER_FREQUENCY_PLAYER 0 // Draw a tracer every nth shot fired by the player. -#define SNIPER_TRACER_FREQUENCY_NPC 0 // Draw a tracer every nth shot fired by NPCs. -#define SNIPER_KICKBACK 3 // Range for punchangle when firing. - -#define SNIPER_ZOOM_RATE 0.2 // Interval between zoom levels in seconds. - - -//----------------------------------------------------------------------------- -// Discrete zoom levels for the scope. -//----------------------------------------------------------------------------- -static int g_nZoomFOV[] = -{ - 20, - 5 -}; - - -class CWeaponSniperRifle : public CBaseHLCombatWeapon -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( CWeaponSniperRifle, CBaseHLCombatWeapon ); - - CWeaponSniperRifle(void); - - DECLARE_SERVERCLASS(); - - void Precache( void ); - - int CapabilitiesGet( void ) const; - - const Vector &GetBulletSpread( void ); - - bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); - void ItemPostFrame( void ); - void PrimaryAttack( void ); - bool Reload( void ); - void Zoom( void ); - virtual float GetFireRate( void ) { return 1; }; - - void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); - - DECLARE_ACTTABLE(); - -protected: - - float m_fNextZoom; - int m_nZoomLevel; -}; - -IMPLEMENT_SERVERCLASS_ST(CWeaponSniperRifle, DT_WeaponSniperRifle) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_sniperrifle, CWeaponSniperRifle ); -PRECACHE_WEAPON_REGISTER(weapon_sniperrifle); - -BEGIN_DATADESC( CWeaponSniperRifle ) - - DEFINE_FIELD( m_fNextZoom, FIELD_FLOAT ), - DEFINE_FIELD( m_nZoomLevel, FIELD_INTEGER ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Maps base activities to weapons-specific ones so our characters do the right things. -//----------------------------------------------------------------------------- -acttable_t CWeaponSniperRifle::m_acttable[] = -{ - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SNIPER_RIFLE, true } -}; - -IMPLEMENT_ACTTABLE(CWeaponSniperRifle); - - -//----------------------------------------------------------------------------- -// Purpose: Constructor. -//----------------------------------------------------------------------------- -CWeaponSniperRifle::CWeaponSniperRifle( void ) -{ - m_fNextZoom = gpGlobals->curtime; - m_nZoomLevel = 0; - - m_bReloadsSingly = true; - - m_fMinRange1 = 65; - m_fMinRange2 = 65; - m_fMaxRange1 = 2048; - m_fMaxRange2 = 2048; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CWeaponSniperRifle::CapabilitiesGet( void ) const -{ - return bits_CAP_WEAPON_RANGE_ATTACK1; -} - - - -//----------------------------------------------------------------------------- -// Purpose: Turns off the zoom when the rifle is holstered. -//----------------------------------------------------------------------------- -bool CWeaponSniperRifle::Holster( CBaseCombatWeapon *pSwitchingTo ) -{ - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - if (pPlayer != NULL) - { - if ( m_nZoomLevel != 0 ) - { - if ( pPlayer->SetFOV( this, 0 ) ) - { - pPlayer->ShowViewModel(true); - m_nZoomLevel = 0; - } - } - } - - return BaseClass::Holster(pSwitchingTo); -} - - -//----------------------------------------------------------------------------- -// Purpose: Overloaded to handle the zoom functionality. -//----------------------------------------------------------------------------- -void CWeaponSniperRifle::ItemPostFrame( void ) -{ - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - if (pPlayer == NULL) - { - return; - } - - if ((m_bInReload) && (m_flNextPrimaryAttack <= gpGlobals->curtime)) - { - FinishReload(); - m_bInReload = false; - } - - if (pPlayer->m_nButtons & IN_ATTACK2) - { - if (m_fNextZoom <= gpGlobals->curtime) - { - Zoom(); - pPlayer->m_nButtons &= ~IN_ATTACK2; - } - } - else if ((pPlayer->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime)) - { - if ( (m_iClip1 == 0 && UsesClipsForAmmo1()) || ( !UsesClipsForAmmo1() && !pPlayer->GetAmmoCount(m_iPrimaryAmmoType) ) ) - { - m_bFireOnEmpty = true; - } - - // Fire underwater? - if (pPlayer->GetWaterLevel() == 3 && m_bFiresUnderwater == false) - { - WeaponSound(EMPTY); - m_flNextPrimaryAttack = gpGlobals->curtime + 0.2; - return; - } - else - { - // If the firing button was just pressed, reset the firing time - if ( pPlayer && pPlayer->m_afButtonPressed & IN_ATTACK ) - { - m_flNextPrimaryAttack = gpGlobals->curtime; - } - - PrimaryAttack(); - } - } - - // ----------------------- - // Reload pressed / Clip Empty - // ----------------------- - if ( pPlayer->m_nButtons & IN_RELOAD && UsesClipsForAmmo1() && !m_bInReload ) - { - // reload when reload is pressed, or if no buttons are down and weapon is empty. - Reload(); - } - - // ----------------------- - // No buttons down - // ----------------------- - if (!((pPlayer->m_nButtons & IN_ATTACK) || (pPlayer->m_nButtons & IN_ATTACK2) || (pPlayer->m_nButtons & IN_RELOAD))) - { - // no fire buttons down - m_bFireOnEmpty = false; - - if ( !HasAnyAmmo() && m_flNextPrimaryAttack < gpGlobals->curtime ) - { - // weapon isn't useable, switch. - if ( !(GetWeaponFlags() & ITEM_FLAG_NOAUTOSWITCHEMPTY) && pPlayer->SwitchToNextBestWeapon( this ) ) - { - m_flNextPrimaryAttack = gpGlobals->curtime + 0.3; - return; - } - } - else - { - // weapon is useable. Reload if empty and weapon has waited as long as it has to after firing - if ( m_iClip1 == 0 && !(GetWeaponFlags() & ITEM_FLAG_NOAUTORELOAD) && m_flNextPrimaryAttack < gpGlobals->curtime ) - { - Reload(); - return; - } - } - - WeaponIdle( ); - return; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponSniperRifle::Precache( void ) -{ - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Same as base reload but doesn't change the owner's next attack time. This -// lets us zoom out while reloading. This hack is necessary because our -// ItemPostFrame is only called when the owner's next attack time has -// expired. -// Output : Returns true if the weapon was reloaded, false if no more ammo. -//----------------------------------------------------------------------------- -bool CWeaponSniperRifle::Reload( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - if (!pOwner) - { - return false; - } - - if (pOwner->GetAmmoCount(m_iPrimaryAmmoType) > 0) - { - int primary = MIN(GetMaxClip1() - m_iClip1, pOwner->GetAmmoCount(m_iPrimaryAmmoType)); - int secondary = MIN(GetMaxClip2() - m_iClip2, pOwner->GetAmmoCount(m_iSecondaryAmmoType)); - - if (primary > 0 || secondary > 0) - { - // Play reload on different channel as it happens after every fire - // and otherwise steals channel away from fire sound - WeaponSound(RELOAD); - SendWeaponAnim( ACT_VM_RELOAD ); - - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - - m_bInReload = true; - } - - return true; - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponSniperRifle::PrimaryAttack( void ) -{ - // Only the player fires this way so we can cast safely. - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - if (!pPlayer) - { - return; - } - - if ( gpGlobals->curtime >= m_flNextPrimaryAttack ) - { - // If my clip is empty (and I use clips) start reload - if ( !m_iClip1 ) - { - Reload(); - return; - } - - // MUST call sound before removing a round from the clip of a CMachineGun dvs: does this apply to the sniper rifle? I don't know. - WeaponSound(SINGLE); - - pPlayer->DoMuzzleFlash(); - - SendWeaponAnim( ACT_VM_PRIMARYATTACK ); - - // player "shoot" animation - pPlayer->SetAnimation( PLAYER_ATTACK1 ); - - // Don't fire again until fire animation has completed - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - m_iClip1 = m_iClip1 - 1; - - Vector vecSrc = pPlayer->Weapon_ShootPosition(); - Vector vecAiming = pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES ); - - // Fire the bullets - pPlayer->FireBullets( SNIPER_BULLET_COUNT_PLAYER, vecSrc, vecAiming, GetBulletSpread(), MAX_TRACE_LENGTH, m_iPrimaryAmmoType, SNIPER_TRACER_FREQUENCY_PLAYER ); - - CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 600, 0.2 ); - - QAngle vecPunch(random->RandomFloat( -SNIPER_KICKBACK, SNIPER_KICKBACK ), 0, 0); - pPlayer->ViewPunch(vecPunch); - - // Indicate out of ammo condition if we run out of ammo. - if (!m_iClip1 && pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0) - { - pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); - } - } - - // Register a muzzleflash for the AI. - pPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Zooms in using the sniper rifle scope. -//----------------------------------------------------------------------------- -void CWeaponSniperRifle::Zoom( void ) -{ - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - if (!pPlayer) - { - return; - } - - if (m_nZoomLevel >= (int)(sizeof(g_nZoomFOV) / sizeof(g_nZoomFOV[0]))) - { - if ( pPlayer->SetFOV( this, 0 ) ) - { - pPlayer->ShowViewModel(true); - - // Zoom out to the default zoom level - WeaponSound(SPECIAL2); - m_nZoomLevel = 0; - } - } - else - { - if ( pPlayer->SetFOV( this, g_nZoomFOV[m_nZoomLevel] ) ) - { - if (m_nZoomLevel == 0) - { - pPlayer->ShowViewModel(false); - } - - WeaponSound(SPECIAL1); - - m_nZoomLevel++; - } - } - - m_fNextZoom = gpGlobals->curtime + SNIPER_ZOOM_RATE; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : virtual const Vector& -//----------------------------------------------------------------------------- -const Vector &CWeaponSniperRifle::GetBulletSpread( void ) -{ - static Vector cone = SNIPER_CONE_PLAYER; - return cone; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEvent - -// *pOperator - -//----------------------------------------------------------------------------- -void CWeaponSniperRifle::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - switch ( pEvent->event ) - { - case EVENT_WEAPON_SNIPER_RIFLE_FIRE: - { - Vector vecShootOrigin, vecShootDir; - vecShootOrigin = pOperator->Weapon_ShootPosition(); - - CAI_BaseNPC *npc = pOperator->MyNPCPointer(); - Vector vecSpread; - if (npc) - { - vecShootDir = npc->GetActualShootTrajectory( vecShootOrigin ); - vecSpread = VECTOR_CONE_PRECALCULATED; - } - else - { - AngleVectors( pOperator->GetLocalAngles(), &vecShootDir ); - vecSpread = GetBulletSpread(); - } - WeaponSound( SINGLE_NPC ); - pOperator->FireBullets( SNIPER_BULLET_COUNT_NPC, vecShootOrigin, vecShootDir, vecSpread, MAX_TRACE_LENGTH, m_iPrimaryAmmoType, SNIPER_TRACER_FREQUENCY_NPC ); - pOperator->DoMuzzleFlash(); - break; - } - - default: - { - BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); - break; - } - } -} - diff --git a/game/server/hl2/weapon_stunstick.cpp b/game/server/hl2/weapon_stunstick.cpp deleted file mode 100644 index 4eb765abf..000000000 --- a/game/server/hl2/weapon_stunstick.cpp +++ /dev/null @@ -1,372 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Stun Stick- beating stick with a zappy end -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" -#include "npc_metropolice.h" -#include "weapon_stunstick.h" -#include "IEffects.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar sk_plr_dmg_stunstick ( "sk_plr_dmg_stunstick","0"); -ConVar sk_npc_dmg_stunstick ( "sk_npc_dmg_stunstick","0"); - -extern ConVar metropolice_move_and_melee; - -//----------------------------------------------------------------------------- -// CWeaponStunStick -//----------------------------------------------------------------------------- - -IMPLEMENT_SERVERCLASS_ST(CWeaponStunStick, DT_WeaponStunStick) - SendPropInt( SENDINFO( m_bActive ), 1, SPROP_UNSIGNED ), -END_SEND_TABLE() - -#ifndef HL2MP -LINK_ENTITY_TO_CLASS( weapon_stunstick, CWeaponStunStick ); -PRECACHE_WEAPON_REGISTER( weapon_stunstick ); -#endif - -acttable_t CWeaponStunStick::m_acttable[] = -{ - { ACT_MELEE_ATTACK1, ACT_MELEE_ATTACK_SWING, true }, - { ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_MELEE, true }, -}; - -IMPLEMENT_ACTTABLE(CWeaponStunStick); - - -BEGIN_DATADESC( CWeaponStunStick ) - - DEFINE_FIELD( m_bActive, FIELD_BOOLEAN ), - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CWeaponStunStick::CWeaponStunStick( void ) -{ - // HACK: Don't call SetStunState because this tried to Emit a sound before - // any players are connected which is a bug - m_bActive = false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CWeaponStunStick::Spawn() -{ - Precache(); - - - BaseClass::Spawn(); - AddSolidFlags( FSOLID_NOT_STANDABLE ); -} - -void CWeaponStunStick::Precache() -{ - BaseClass::Precache(); - - PrecacheScriptSound( "Weapon_StunStick.Activate" ); - PrecacheScriptSound( "Weapon_StunStick.Deactivate" ); - -} - -//----------------------------------------------------------------------------- -// Purpose: Get the damage amount for the animation we're doing -// Input : hitActivity - currently played activity -// Output : Damage amount -//----------------------------------------------------------------------------- -float CWeaponStunStick::GetDamageForActivity( Activity hitActivity ) -{ - if ( ( GetOwner() != NULL ) && ( GetOwner()->IsPlayer() ) ) - return sk_plr_dmg_stunstick.GetFloat(); - - return sk_npc_dmg_stunstick.GetFloat(); -} - -//----------------------------------------------------------------------------- -// Attempt to lead the target (needed because citizens can't hit manhacks with the crowbar!) -//----------------------------------------------------------------------------- -extern ConVar sk_crowbar_lead_time; - -int CWeaponStunStick::WeaponMeleeAttack1Condition( float flDot, float flDist ) -{ - // Attempt to lead the target (needed because citizens can't hit manhacks with the crowbar!) - CAI_BaseNPC *pNPC = GetOwner()->MyNPCPointer(); - CBaseEntity *pEnemy = pNPC->GetEnemy(); - if (!pEnemy) - return COND_NONE; - - Vector vecVelocity; - AngularImpulse angVelocity; - pEnemy->GetVelocity( &vecVelocity, &angVelocity ); - - // Project where the enemy will be in a little while, add some randomness so he doesn't always hit - float dt = sk_crowbar_lead_time.GetFloat(); - dt += random->RandomFloat( -0.3f, 0.2f ); - if ( dt < 0.0f ) - dt = 0.0f; - - Vector vecExtrapolatedPos; - VectorMA( pEnemy->WorldSpaceCenter(), dt, vecVelocity, vecExtrapolatedPos ); - - Vector vecDelta; - VectorSubtract( vecExtrapolatedPos, pNPC->WorldSpaceCenter(), vecDelta ); - - if ( fabs( vecDelta.z ) > 70 ) - { - return COND_TOO_FAR_TO_ATTACK; - } - - Vector vecForward = pNPC->BodyDirection2D( ); - vecDelta.z = 0.0f; - float flExtrapolatedDot = DotProduct2D( vecDelta.AsVector2D(), vecForward.AsVector2D() ); - if ((flDot < 0.7) && (flExtrapolatedDot < 0.7)) - { - return COND_NOT_FACING_ATTACK; - } - - float flExtrapolatedDist = Vector2DNormalize( vecDelta.AsVector2D() ); - - if( pEnemy->IsPlayer() ) - { - //Vector vecDir = pEnemy->GetSmoothedVelocity(); - //float flSpeed = VectorNormalize( vecDir ); - - // If player will be in front of me in one-half second, clock his arse. - Vector vecProjectEnemy = pEnemy->GetAbsOrigin() + (pEnemy->GetAbsVelocity() * 0.35); - Vector vecProjectMe = GetAbsOrigin(); - - if( (vecProjectMe - vecProjectEnemy).Length2D() <= 48.0f ) - { - return COND_CAN_MELEE_ATTACK1; - } - } -/* - if( metropolice_move_and_melee.GetBool() ) - { - if( pNPC->IsMoving() ) - { - flTargetDist *= 1.5f; - } - } -*/ - float flTargetDist = 48.0f; - if ((flDist > flTargetDist) && (flExtrapolatedDist > flTargetDist)) - { - return COND_TOO_FAR_TO_ATTACK; - } - - return COND_CAN_MELEE_ATTACK1; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponStunStick::ImpactEffect( trace_t &traceHit ) -{ - //Glowing spark effect for hit - //UTIL_DecalTrace( &m_trLineHit, "PlasmaGlowFade" ); - - //FIXME: need new decals - UTIL_ImpactTrace( &traceHit, DMG_CLUB ); -} - -void CWeaponStunStick::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - switch( pEvent->event ) - { - case EVENT_WEAPON_MELEE_HIT: - { - // Trace up or down based on where the enemy is... - // But only if we're basically facing that direction - Vector vecDirection; - AngleVectors( GetAbsAngles(), &vecDirection ); - - CBaseEntity *pEnemy = pOperator->MyNPCPointer() ? pOperator->MyNPCPointer()->GetEnemy() : NULL; - if ( pEnemy ) - { - Vector vecDelta; - VectorSubtract( pEnemy->WorldSpaceCenter(), pOperator->Weapon_ShootPosition(), vecDelta ); - VectorNormalize( vecDelta ); - - Vector2D vecDelta2D = vecDelta.AsVector2D(); - Vector2DNormalize( vecDelta2D ); - if ( DotProduct2D( vecDelta2D, vecDirection.AsVector2D() ) > 0.8f ) - { - vecDirection = vecDelta; - } - } - - Vector vecEnd; - VectorMA( pOperator->Weapon_ShootPosition(), 32, vecDirection, vecEnd ); - // Stretch the swing box down to catch low level physics objects - CBaseEntity *pHurt = pOperator->CheckTraceHullAttack( pOperator->Weapon_ShootPosition(), vecEnd, - Vector(-16,-16,-40), Vector(16,16,16), (int)GetDamageForActivity( GetActivity() ), DMG_CLUB, 0.5f, false ); - - // did I hit someone? - if ( pHurt ) - { - // play sound - WeaponSound( MELEE_HIT ); - - CBasePlayer *pPlayer = ToBasePlayer( pHurt ); - - CNPC_MetroPolice *pCop = dynamic_cast(pOperator); - bool bFlashed = false; - - if ( pCop != NULL && pPlayer != NULL ) - { - // See if we need to knock out this target - if ( pCop->ShouldKnockOutTarget( pHurt ) ) - { - float yawKick = random->RandomFloat( -48, -24 ); - - //Kick the player angles - pPlayer->ViewPunch( QAngle( -16, yawKick, 2 ) ); - - color32 white = {255,255,255,255}; - UTIL_ScreenFade( pPlayer, white, 0.2f, 1.0f, FFADE_OUT|FFADE_PURGE|FFADE_STAYOUT ); - bFlashed = true; - - pCop->KnockOutTarget( pHurt ); - - break; - } - else - { - // Notify that we've stunned a target - pCop->StunnedTarget( pHurt ); - } - } - - // Punch angles - if ( pPlayer != NULL && !(pPlayer->GetFlags() & FL_GODMODE) ) - { - float yawKick = random->RandomFloat( -48, -24 ); - - //Kick the player angles - pPlayer->ViewPunch( QAngle( -16, yawKick, 2 ) ); - - Vector dir = pHurt->GetAbsOrigin() - GetAbsOrigin(); - - // If the player's on my head, don't knock him up - if ( pPlayer->GetGroundEntity() == pOperator ) - { - dir = vecDirection; - dir.z = 0; - } - - VectorNormalize(dir); - - dir *= 500.0f; - - //If not on ground, then don't make them fly! - if ( !(pPlayer->GetFlags() & FL_ONGROUND ) ) - dir.z = 0.0f; - - //Push the target back - pHurt->ApplyAbsVelocityImpulse( dir ); - - if ( !bFlashed ) - { - color32 red = {128,0,0,128}; - UTIL_ScreenFade( pPlayer, red, 0.5f, 0.1f, FFADE_IN ); - } - - // Force the player to drop anyting they were holding - pPlayer->ForceDropOfCarriedPhysObjects(); - } - - // do effect? - } - else - { - WeaponSound( MELEE_MISS ); - } - } - break; - default: - BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Sets the state of the stun stick -//----------------------------------------------------------------------------- -void CWeaponStunStick::SetStunState( bool state ) -{ - m_bActive = state; - - if ( m_bActive ) - { - //FIXME: START - Move to client-side - - Vector vecAttachment; - - GetAttachment( 1, vecAttachment ); - g_pEffects->Sparks( vecAttachment ); - - //FIXME: END - Move to client-side - - EmitSound( "Weapon_StunStick.Activate" ); - } - else - { - EmitSound( "Weapon_StunStick.Deactivate" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponStunStick::Deploy( void ) -{ - SetStunState( true ); - - return BaseClass::Deploy(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CWeaponStunStick::Holster( CBaseCombatWeapon *pSwitchingTo ) -{ - if ( BaseClass::Holster( pSwitchingTo ) == false ) - return false; - - SetStunState( false ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &vecVelocity - -//----------------------------------------------------------------------------- -void CWeaponStunStick::Drop( const Vector &vecVelocity ) -{ - SetStunState( false ); - - BaseClass::Drop( vecVelocity ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponStunStick::GetStunState( void ) -{ - return m_bActive; -} diff --git a/game/server/hl2/weapon_stunstick.h b/game/server/hl2/weapon_stunstick.h deleted file mode 100644 index aa4a1721e..000000000 --- a/game/server/hl2/weapon_stunstick.h +++ /dev/null @@ -1,58 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef WEAPON_STUNSTICK_H -#define WEAPON_STUNSTICK_H -#ifdef _WIN32 -#pragma once -#endif - -#include "basebludgeonweapon.h" - -#define STUNSTICK_RANGE 75.0f -#define STUNSTICK_REFIRE 0.6f - -class CWeaponStunStick : public CBaseHLBludgeonWeapon -{ - DECLARE_CLASS( CWeaponStunStick, CBaseHLBludgeonWeapon ); - DECLARE_DATADESC(); - -public: - - CWeaponStunStick(); - - DECLARE_SERVERCLASS(); - DECLARE_ACTTABLE(); - - virtual void Precache(); - - void Spawn(); - - float GetRange( void ) { return STUNSTICK_RANGE; } - float GetFireRate( void ) { return STUNSTICK_REFIRE; } - - int WeaponMeleeAttack1Condition( float flDot, float flDist ); - - bool Deploy( void ); - bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); - - void Drop( const Vector &vecVelocity ); - void ImpactEffect( trace_t &traceHit ); - void SecondaryAttack( void ) {} - void SetStunState( bool state ); - bool GetStunState( void ); - void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); - - float GetDamageForActivity( Activity hitActivity ); - - bool CanBePickedUpByNPCs( void ) { return false; } - -private: - - CNetworkVar( bool, m_bActive ); -}; - -#endif // WEAPON_STUNSTICK_H diff --git a/game/server/hl2/weapon_thumper.cpp b/game/server/hl2/weapon_thumper.cpp deleted file mode 100644 index 6aa6273a4..000000000 --- a/game/server/hl2/weapon_thumper.cpp +++ /dev/null @@ -1,295 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: 'weapon' what lets the player controll the rollerbuddy. -// -// $Revision: $ -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "basehlcombatweapon.h" -#include "npcevent.h" -#include "basecombatcharacter.h" -#include "ai_basenpc.h" -#include "player.h" -#include "entitylist.h" -#include "ndebugoverlay.h" -#include "soundent.h" -#include "engine/IEngineSound.h" -#include "rotorwash.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar thumpFrequency( "thumpfrequency", "2" ); -ConVar thumpRadius( "thumpradius", "512" ); - - -//========================================================= -//========================================================= -class CPortableThumper : public CBaseAnimating -{ - DECLARE_CLASS( CPortableThumper, CBaseAnimating ); -private: - - void ThumpThink( void ); - void ThumperUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - void Precache( void ); - void Spawn( void ); - - int ObjectCaps( void ) { return FCAP_IMPULSE_USE; } - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( portable_thumper, CPortableThumper ); - - - -void CPortableThumper::Precache( void ) -{ - PrecacheModel( "models/fire_equipment/w_firehydrant.mdl" ); -} - -void CPortableThumper::Spawn( void ) -{ - m_takedamage = DAMAGE_NO; - - SetModel( "models/fire_equipment/w_firehydrant.mdl" ); - - Vector vecBBMin, vecBBMax; - - vecBBMin.z = 0; - vecBBMin.x = -16; - vecBBMin.y = -16; - - vecBBMax.z = 32; - vecBBMax.x = 16; - vecBBMax.y = 16; - - SetSolid( SOLID_BBOX ); - UTIL_SetSize( this, vecBBMin, vecBBMax ); - - SetThink( &CPortableThumper::ThumpThink ); - SetUse( &CPortableThumper::ThumperUse ); - SetNextThink( gpGlobals->curtime + thumpFrequency.GetFloat() ); -} - -void CPortableThumper::ThumperUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - if( !pActivator->IsPlayer() ) - { - return; - } - - CBasePlayer *pPlayer; - - pPlayer = (CBasePlayer *)pActivator; - pPlayer->GiveNamedItem( "weapon_thumper" ); - - UTIL_Remove( this ); -} - -void CPortableThumper::ThumpThink( void ) -{ - EmitSound( "PortableThumper.ThumpSound" ); - - UTIL_RotorWash( GetAbsOrigin() + Vector( 0, 0, 32 ), Vector( 0, 0, -1 ), 512 ); - - SetNextThink( gpGlobals->curtime + thumpFrequency.GetFloat() ); - - CSoundEnt::InsertSound( SOUND_THUMPER, GetAbsOrigin(), thumpRadius.GetInt(), 0.2, this ); -} - -BEGIN_DATADESC( CPortableThumper ) - - DEFINE_FUNCTION( ThumpThink ), - DEFINE_FUNCTION( ThumperUse ), - -END_DATADESC() - - - - - - -class CWeaponThumper: public CBaseHLCombatWeapon -{ - DECLARE_CLASS( CWeaponThumper, CBaseHLCombatWeapon ); -public: - DECLARE_SERVERCLASS(); - void Spawn( void ); - void Precache( void ); - - int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } - void PrimaryAttack( void ); - bool Reload( void ); - void DecrementAmmo( CBaseCombatCharacter *pOwner ); -}; - -IMPLEMENT_SERVERCLASS_ST(CWeaponThumper, DT_WeaponThumper) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_thumper, CWeaponThumper ); -PRECACHE_WEAPON_REGISTER(weapon_thumper); - -void CWeaponThumper::Spawn( ) -{ - BaseClass::Spawn(); - - Precache( ); - - UTIL_SetSize(this, Vector(-4,-4,-2),Vector(4,4,2)); - - FallInit();// get ready to fall down -} - -void CWeaponThumper::Precache( void ) -{ - BaseClass::Precache(); - UTIL_PrecacheOther( "portable_thumper" ); - - PrecacheScriptSound( "PortableThumper.ThumpSound" ); - -} - -bool CWeaponThumper::Reload( void ) -{ - WeaponIdle(); - return true; -} - -void CWeaponThumper::PrimaryAttack( void ) -{ - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - if ( !pPlayer ) - return; - - DecrementAmmo( pPlayer ); - - trace_t tr; - - Vector vecStart, vecDir; - - Vector vecForward; - Vector vecSpot; - - pPlayer->GetVectors( &vecForward, NULL, NULL ); - - vecForward.z = 0.0; - - vecStart = pPlayer->WorldSpaceCenter() + vecForward * 64; - - UTIL_TraceLine( vecStart, vecStart - Vector( 0, 0, 128 ), MASK_SHOT, pPlayer, COLLISION_GROUP_NONE, &tr ); - - if( tr.fraction != 1.0 ) - { - Create( "portable_thumper", tr.endpos, vec3_angle, NULL ); - m_flNextPrimaryAttack = gpGlobals->curtime + 0.5; - } - - m_flNextPrimaryAttack = gpGlobals->curtime + 0.5; -} - - -void CWeaponThumper::DecrementAmmo( CBaseCombatCharacter *pOwner ) -{ - pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType ); - - if (pOwner->GetAmmoCount(m_iPrimaryAmmoType) <= 0) - { - pOwner->Weapon_Drop( this ); - UTIL_Remove(this); - } -} - -/* -//========================================================= -//========================================================= -class CWeaponThumper : public CBaseHLCombatWeapon -{ -public: - DECLARE_CLASS( CWeaponThumper, CBaseHLCombatWeapon ); - - CWeaponThumper(); - - DECLARE_SERVERCLASS(); - - void Precache( void ); - bool Deploy( void ); - - int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } - - void PrimaryAttack( void ); - void SecondaryAttack( void ); - - DECLARE_ACTTABLE(); -}; - -IMPLEMENT_SERVERCLASS_ST(CWeaponThumper, DT_WeaponThumper) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_thumper, CWeaponThumper ); -PRECACHE_WEAPON_REGISTER(weapon_thumper); - -acttable_t CWeaponThumper::m_acttable[] = -{ - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_AR1, true }, -}; - -IMPLEMENT_ACTTABLE(CWeaponThumper); - -CWeaponThumper::CWeaponThumper( ) -{ -} - -void CWeaponThumper::Precache( void ) -{ - UTIL_PrecacheOther( "portable_thumper" ); - BaseClass::Precache(); -} - -bool CWeaponThumper::Deploy( void ) -{ - bool fReturn; - - fReturn = BaseClass::Deploy(); - - m_flNextPrimaryAttack = gpGlobals->curtime; - m_flNextSecondaryAttack = gpGlobals->curtime; - m_hOwner->m_flNextAttack = gpGlobals->curtime + 0.0; - - return fReturn; -} - -void CWeaponThumper::PrimaryAttack( void ) -{ - trace_t tr; - - Vector vecStart, vecDir; - - Vector vecForward; - Vector vecSpot; - - m_hOwner->GetVectors( &vecForward, NULL, NULL ); - - vecForward.z = 0.0; - - vecStart = m_hOwner->Center() + vecForward * 64; - - UTIL_TraceLine( vecStart, vecStart - Vector( 0, 0, 128 ), MASK_SHOT, m_hOwner, COLLISION_GROUP_NONE, &tr ); - - if( tr.fraction != 1.0 ) - { - Create( "portable_thumper", tr.endpos, vec3_origin, NULL ); - m_flNextPrimaryAttack = gpGlobals->curtime + 0.5; - } - - m_hOwner->m_iAmmo[m_iPrimaryAmmoType]++; -} - -void CWeaponThumper::SecondaryAttack( void ) -{ - m_flNextSecondaryAttack = gpGlobals->curtime + 0.5; -} -*/ diff --git a/game/server/hl2/weapon_tripwire.cpp b/game/server/hl2/weapon_tripwire.cpp deleted file mode 100644 index b36ff82ee..000000000 --- a/game/server/hl2/weapon_tripwire.cpp +++ /dev/null @@ -1,434 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "util.h" -#include "basehlcombatweapon.h" -#include "player.h" -#include "gamerules.h" -#include "grenade_tripwire.h" -#include "grenade_satchel.h" -#include "entitylist.h" -#include "weapon_tripwire.h" -#include "npcevent.h" -#include "in_buttons.h" -#include "engine/IEngineSound.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -BEGIN_DATADESC( CWeapon_Tripwire ) - - DEFINE_FIELD( m_bNeedReload, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bClearReload, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bAttachTripwire, FIELD_BOOLEAN ), - - // Function Pointers - DEFINE_FUNCTION( TripwireTouch ), - -END_DATADESC() - - -IMPLEMENT_SERVERCLASS_ST(CWeapon_Tripwire, DT_Weapon_Tripwire) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_tripwire, CWeapon_Tripwire ); - -// BUGBUG: Enable this when the script & resources are checked in. -//PRECACHE_WEAPON_REGISTER(weapon_tripwire); - -acttable_t CWeapon_Tripwire::m_acttable[] = -{ - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_TRIPWIRE, true }, -}; - -IMPLEMENT_ACTTABLE(CWeapon_Tripwire); - - -void CWeapon_Tripwire::Spawn( ) -{ - UTIL_Remove(this); - return; - - BaseClass::Spawn(); - - Precache( ); - - UTIL_SetSize(this, Vector(-4,-4,-2),Vector(4,4,2)); - - - FallInit();// get ready to fall down - - SetThink( NULL ); - - // Give one piece of default ammo when first picked up - m_iClip2 = 1; -} - -void CWeapon_Tripwire::Precache( void ) -{ - BaseClass::Precache(); - - PrecacheScriptSound( "Weapon_Tripwire.Attach" ); - - UTIL_PrecacheOther( "npc_tripwire" ); -} - -//------------------------------------------------------------------------------ -// Purpose : Override to use tripwire's pickup touch function -// Input : -// Output : -//------------------------------------------------------------------------------ -void CWeapon_Tripwire::SetPickupTouch( void ) -{ - SetTouch(&CWeapon_Tripwire::TripwireTouch); -} - -//----------------------------------------------------------------------------- -// Purpose: Override so give correct ammo -// Input : pOther - the entity that touched me -// Output : -//----------------------------------------------------------------------------- -void CWeapon_Tripwire::TripwireTouch( CBaseEntity *pOther ) -{ - // --------------------------------------------------- - // First give weapon to touching entity if allowed - // --------------------------------------------------- - BaseClass::DefaultTouch(pOther); - - // ---------------------------------------------------- - // Give ammo if touching client - // ---------------------------------------------------- - if (pOther->GetFlags() & FL_CLIENT) - { - // ------------------------------------------------ - // If already owned weapon of this type remove me - // ------------------------------------------------ - CBaseCombatCharacter* pBCC = ToBaseCombatCharacter( pOther ); - CWeapon_Tripwire* oldWeapon = (CWeapon_Tripwire*)pBCC->Weapon_OwnsThisType( GetClassname() ); - if (oldWeapon != this) - { - UTIL_Remove( this ); - } - else - { - pBCC->GiveAmmo( 1, m_iSecondaryAmmoType ); - SetThink(NULL); - } - } -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -bool CWeapon_Tripwire::Holster( CBaseCombatWeapon *pSwitchingTo ) -{ - SetThink(NULL); - return BaseClass::Holster(pSwitchingTo); -} - -//----------------------------------------------------------------------------- -// Purpose: Tripwire has no reload, but must call weapon idle to update state -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CWeapon_Tripwire::Reload( void ) -{ - WeaponIdle( ); - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_Tripwire::PrimaryAttack( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - if (!pOwner) - { - return; - } - - if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0) - { - return; - } - - if (CanAttachTripwire()) - { - StartTripwireAttach(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Secondary attack does nothing -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_Tripwire::SecondaryAttack( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_Tripwire::TripwireAttach( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - if (!pOwner) - { - return; - } - - m_bAttachTripwire = false; - - Vector vecSrc = pOwner->Weapon_ShootPosition(); - Vector vecAiming = pOwner->BodyDirection2D( ); - - trace_t tr; - - UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); - - if (tr.fraction < 1.0) - { - CBaseEntity *pEntity = tr.m_pEnt; - if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR)) - { - QAngle angles; - VectorAngles(tr.plane.normal, angles); - angles.x += 90; - - CBaseEntity *pEnt = CBaseEntity::Create( "npc_tripwire", tr.endpos + tr.plane.normal * 3, angles, NULL ); - - CTripwireGrenade *pMine = (CTripwireGrenade *)pEnt; - pMine->SetThrower( GetOwner() ); - - pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType ); - - EmitSound( "Weapon_Tripwire.Attach" ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_Tripwire::StartTripwireAttach( void ) -{ - // Only the player fires this way so we can cast - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - if (!pPlayer) - { - return; - } - - Vector vecSrc = pPlayer->Weapon_ShootPosition(); - Vector vecAiming = pPlayer->BodyDirection3D( ); - - trace_t tr; - - UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &tr ); - - if (tr.fraction < 1.0) - { - // ALERT( at_console, "hit %f\n", tr.flFraction ); - - CBaseEntity *pEntity = tr.m_pEnt; - if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR)) - { - // player "shoot" animation - pPlayer->SetAnimation( PLAYER_ATTACK1 ); - - // ----------------------------------------- - // Play attach animation - // ----------------------------------------- - SendWeaponAnim(ACT_SLAM_TRIPMINE_ATTACH); - - m_bNeedReload = true; - m_bAttachTripwire = true; - } - else - { - // ALERT( at_console, "no deploy\n" ); - } - } - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration(); -// SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CWeapon_Tripwire::CanAttachTripwire( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - if (!pOwner) - { - return false; - } - - Vector vecSrc = pOwner->Weapon_ShootPosition(); - Vector vecAiming = pOwner->BodyDirection2D( ); - - trace_t tr; - - Vector vecEnd = vecSrc + (vecAiming * 42); - UTIL_TraceLine( vecSrc, vecEnd, MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); - - if (tr.fraction < 1.0) - { - // Don't attach to a living creature - if (tr.m_pEnt) - { - CBaseEntity *pEntity = tr.m_pEnt; - CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pEntity ); - if (pBCC) - { - return false; - } - } - return true; - } - else - { - return false; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_Tripwire::ItemPostFrame( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if (!pOwner) - { - return; - } - - if ((pOwner->m_nButtons & IN_ATTACK2) && (m_flNextSecondaryAttack <= gpGlobals->curtime)) - { - SecondaryAttack(); - } - else if (!m_bNeedReload && (pOwner->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime)) - { - PrimaryAttack(); - } - - // ----------------------- - // No buttons down - // ----------------------- - else - { - WeaponIdle( ); - return; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_Tripwire::WeaponIdle( void ) -{ - // Ready to switch animations? - if ( HasWeaponIdleTimeElapsed() ) - { - if (m_bClearReload) - { - m_bNeedReload = false; - m_bClearReload = false; - } - CBaseCombatCharacter *pOwner = GetOwner(); - if (!pOwner) - { - return; - } - - int iAnim = 0; - - if (m_bAttachTripwire) - { - TripwireAttach(); - iAnim = ACT_SLAM_TRIPMINE_ATTACH2; - } - else if (m_bNeedReload) - { - // If owner had ammo draw the correct tripwire type - if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) > 0) - { - iAnim = ACT_SLAM_TRIPMINE_DRAW; - m_bClearReload = true; - } - else - { - pOwner->Weapon_Drop( this ); - UTIL_Remove(this); - } - } - else if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0) - { - pOwner->Weapon_Drop( this ); - UTIL_Remove(this); - } - - // If I don't need to reload just do the appropriate idle - else - { - iAnim = ACT_SLAM_TRIPMINE_IDLE; - } - SendWeaponAnim( iAnim ); - } -} - -bool CWeapon_Tripwire::Deploy( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - if (!pOwner) - { - return false; - } - - SetModel( GetViewModel() ); - - // ------------------------------ - // Pick the right draw animation - // ------------------------------ - int iActivity; - - // If detonator is already armed - m_bNeedReload = false; - iActivity = ACT_SLAM_STICKWALL_ND_DRAW; - return DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), iActivity, (char*)GetAnimPrefix() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Constructor -// Input : -// Output : -//----------------------------------------------------------------------------- -CWeapon_Tripwire::CWeapon_Tripwire(void) -{ - m_bNeedReload = true; - m_bClearReload = false; - m_bAttachTripwire = false; -} diff --git a/game/server/hl2/weapon_tripwire.h b/game/server/hl2/weapon_tripwire.h deleted file mode 100644 index 8f962dbf6..000000000 --- a/game/server/hl2/weapon_tripwire.h +++ /dev/null @@ -1,66 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: TRIPWIRE -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef WEAPONTRIPWIRE_H -#define WEAPONTRIPWIRE_H - -#include "basegrenade_shared.h" -#include "basehlcombatweapon.h" - -enum TripwireState_t -{ - TRIPWIRE_TRIPMINE_READY, - TRIPWIRE_SATCHEL_THROW, - TRIPWIRE_SATCHEL_ATTACH, -}; - -class CWeapon_Tripwire : public CBaseHLCombatWeapon -{ -public: - DECLARE_CLASS( CWeapon_Tripwire, CBaseHLCombatWeapon ); - - DECLARE_SERVERCLASS(); - - bool m_bNeedReload; - bool m_bClearReload; - bool m_bAttachTripwire; - - void Spawn( void ); - void Precache( void ); - - int CapabilitiesGet( void ) { return bits_CAP_WEAPON_RANGE_ATTACK1; } - void PrimaryAttack( void ); - void SecondaryAttack( void ); - void WeaponIdle( void ); - void WeaponSwitch( void ); - - void SetPickupTouch( void ); - void TripwireTouch( CBaseEntity *pOther ); // default weapon touch - void ItemPostFrame( void ); - bool Reload( void ); - bool CanAttachTripwire(void); // In position where can attach TRIPWIRE? - void StartTripwireAttach( void ); - void TripwireAttach( void ); - - bool Deploy( void ); - bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); - - - CWeapon_Tripwire(); - - DECLARE_ACTTABLE(); - DECLARE_DATADESC(); -}; - - -#endif //WEAPONTRIPWIRE_H diff --git a/game/server/hl2mp/grenade_satchel.cpp b/game/server/hl2mp/grenade_satchel.cpp deleted file mode 100644 index 9c91cdbe1..000000000 --- a/game/server/hl2mp/grenade_satchel.cpp +++ /dev/null @@ -1,217 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include "cbase.h" -#include "player.h" -#include "soundenvelope.h" -#include "engine/IEngineSound.h" -#include "explode.h" -#include "Sprite.h" -#include "grenade_satchel.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SLAM_SPRITE "sprites/redglow1.vmt" - -ConVar sk_plr_dmg_satchel ( "sk_plr_dmg_satchel","0"); -ConVar sk_npc_dmg_satchel ( "sk_npc_dmg_satchel","0"); -ConVar sk_satchel_radius ( "sk_satchel_radius","0"); - -BEGIN_DATADESC( CSatchelCharge ) - - DEFINE_FIELD( m_flNextBounceSoundTime, FIELD_TIME ), - DEFINE_FIELD( m_bInAir, FIELD_BOOLEAN ), - DEFINE_FIELD( m_vLastPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_pMyWeaponSLAM, FIELD_CLASSPTR ), - DEFINE_FIELD( m_bIsAttached, FIELD_BOOLEAN ), - - // Function Pointers - DEFINE_THINKFUNC( SatchelThink ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Explode", InputExplode), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( npc_satchel, CSatchelCharge ); - -//========================================================= -// Deactivate - do whatever it is we do to an orphaned -// satchel when we don't want it in the world anymore. -//========================================================= -void CSatchelCharge::Deactivate( void ) -{ - AddSolidFlags( FSOLID_NOT_SOLID ); - UTIL_Remove( this ); - - if ( m_hGlowSprite != NULL ) - { - UTIL_Remove( m_hGlowSprite ); - m_hGlowSprite = NULL; - } -} - - -void CSatchelCharge::Spawn( void ) -{ - Precache( ); - SetModel( "models/Weapons/w_slam.mdl" ); - - VPhysicsInitNormal( SOLID_BBOX, GetSolidFlags() | FSOLID_TRIGGER, false ); - SetMoveType( MOVETYPE_VPHYSICS ); - - SetCollisionGroup( COLLISION_GROUP_WEAPON ); - - UTIL_SetSize(this, Vector( -6, -6, -2), Vector(6, 6, 2)); - - SetThink( &CSatchelCharge::SatchelThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - m_flDamage = sk_plr_dmg_satchel.GetFloat(); - m_DmgRadius = sk_satchel_radius.GetFloat(); - m_takedamage = DAMAGE_YES; - m_iHealth = 1; - - SetGravity( UTIL_ScaleForGravity( 560 ) ); // slightly lower gravity - SetFriction( 1.0 ); - SetSequence( 1 ); - SetDamage( 150 ); - - m_bIsAttached = false; - m_bInAir = true; - m_flNextBounceSoundTime = 0; - - m_vLastPosition = vec3_origin; - - m_hGlowSprite = NULL; - CreateEffects(); -} - -//----------------------------------------------------------------------------- -// Purpose: Start up any effects for us -//----------------------------------------------------------------------------- -void CSatchelCharge::CreateEffects( void ) -{ - // Only do this once - if ( m_hGlowSprite != NULL ) - return; - - // Create a blinking light to show we're an active SLAM - m_hGlowSprite = CSprite::SpriteCreate( SLAM_SPRITE, GetAbsOrigin(), false ); - m_hGlowSprite->SetAttachment( this, 0 ); - m_hGlowSprite->SetTransparency( kRenderTransAdd, 255, 255, 255, 255, kRenderFxStrobeFast ); - m_hGlowSprite->SetBrightness( 255, 1.0f ); - m_hGlowSprite->SetScale( 0.2f, 0.5f ); - m_hGlowSprite->TurnOn(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CSatchelCharge::InputExplode( inputdata_t &inputdata ) -{ - ExplosionCreate( GetAbsOrigin() + Vector( 0, 0, 16 ), GetAbsAngles(), GetThrower(), (int)GetDamage(), 200, - SF_ENVEXPLOSION_NOSPARKS | SF_ENVEXPLOSION_NODLIGHTS | SF_ENVEXPLOSION_NOSMOKE, 0.0f, this); - - UTIL_Remove( this ); -} - - -void CSatchelCharge::SatchelThink( void ) -{ - // If attached resize so player can pick up off wall - if (m_bIsAttached) - { - UTIL_SetSize(this, Vector( -2, -2, -6), Vector(2, 2, 6)); - } - - // See if I can lose my owner (has dropper moved out of way?) - // Want do this so owner can shoot the satchel charge - if (GetOwnerEntity()) - { - trace_t tr; - Vector vUpABit = GetAbsOrigin(); - vUpABit.z += 5.0; - - CBaseEntity* saveOwner = GetOwnerEntity(); - SetOwnerEntity( NULL ); - UTIL_TraceEntity( this, GetAbsOrigin(), vUpABit, MASK_SOLID, &tr ); - if ( tr.startsolid || tr.fraction != 1.0 ) - { - SetOwnerEntity( saveOwner ); - } - } - - // Bounce movement code gets this think stuck occasionally so check if I've - // succeeded in moving, otherwise kill my motions. - else if ((GetAbsOrigin() - m_vLastPosition).LengthSqr()<1) - { - SetAbsVelocity( vec3_origin ); - - QAngle angVel = GetLocalAngularVelocity(); - angVel.y = 0; - SetLocalAngularVelocity( angVel ); - - // Clear think function - SetThink(NULL); - return; - } - m_vLastPosition= GetAbsOrigin(); - - StudioFrameAdvance( ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - if (!IsInWorld()) - { - UTIL_Remove( this ); - return; - } - - // Is it attached to a wall? - if (m_bIsAttached) - { - return; - } -} - -void CSatchelCharge::Precache( void ) -{ - PrecacheModel("models/Weapons/w_slam.mdl"); - PrecacheModel(SLAM_SPRITE); -} - -void CSatchelCharge::BounceSound( void ) -{ - if (gpGlobals->curtime > m_flNextBounceSoundTime) - { - m_flNextBounceSoundTime = gpGlobals->curtime + 0.1; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Constructor -// Input : -// Output : -//----------------------------------------------------------------------------- -CSatchelCharge::CSatchelCharge(void) -{ - m_vLastPosition.Init(); - m_pMyWeaponSLAM = NULL; -} - -CSatchelCharge::~CSatchelCharge(void) -{ - if ( m_hGlowSprite != NULL ) - { - UTIL_Remove( m_hGlowSprite ); - m_hGlowSprite = NULL; - } -} diff --git a/game/server/hl2mp/grenade_satchel.h b/game/server/hl2mp/grenade_satchel.h deleted file mode 100644 index 98cb5c843..000000000 --- a/game/server/hl2mp/grenade_satchel.h +++ /dev/null @@ -1,56 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Satchel Charge -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef SATCHEL_H -#define SATCHEL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "basegrenade_shared.h" -#include "hl2mp/weapon_slam.h" - -class CSoundPatch; -class CSprite; - -class CSatchelCharge : public CBaseGrenade -{ -public: - DECLARE_CLASS( CSatchelCharge, CBaseGrenade ); - - void Spawn( void ); - void Precache( void ); - void BounceSound( void ); - void SatchelTouch( CBaseEntity *pOther ); - void SatchelThink( void ); - - // Input handlers - void InputExplode( inputdata_t &inputdata ); - - float m_flNextBounceSoundTime; - bool m_bInAir; - Vector m_vLastPosition; - -public: - CWeapon_SLAM* m_pMyWeaponSLAM; // Who shot me.. - bool m_bIsAttached; - void Deactivate( void ); - - CSatchelCharge(); - ~CSatchelCharge(); - - DECLARE_DATADESC(); - -private: - void CreateEffects( void ); - CHandle m_hGlowSprite; -}; - -#endif //SATCHEL_H diff --git a/game/server/hl2mp/grenade_tripmine.cpp b/game/server/hl2mp/grenade_tripmine.cpp deleted file mode 100644 index ac729d82e..000000000 --- a/game/server/hl2mp/grenade_tripmine.cpp +++ /dev/null @@ -1,274 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements the tripmine grenade. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "beam_shared.h" -#include "shake.h" -#include "grenade_tripmine.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "explode.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern const char* g_pModelNameLaser; - -ConVar sk_plr_dmg_tripmine ( "sk_plr_dmg_tripmine","0"); -ConVar sk_npc_dmg_tripmine ( "sk_npc_dmg_tripmine","0"); -ConVar sk_tripmine_radius ( "sk_tripmine_radius","0"); - -LINK_ENTITY_TO_CLASS( npc_tripmine, CTripmineGrenade ); - -BEGIN_DATADESC( CTripmineGrenade ) - - DEFINE_FIELD( m_hOwner, FIELD_EHANDLE ), - DEFINE_FIELD( m_flPowerUp, FIELD_TIME ), - DEFINE_FIELD( m_vecDir, FIELD_VECTOR ), - DEFINE_FIELD( m_vecEnd, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_flBeamLength, FIELD_FLOAT ), - DEFINE_FIELD( m_pBeam, FIELD_CLASSPTR ), - DEFINE_FIELD( m_posOwner, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_angleOwner, FIELD_VECTOR ), - - // Function Pointers - DEFINE_THINKFUNC( WarningThink ), - DEFINE_THINKFUNC( PowerupThink ), - DEFINE_THINKFUNC( BeamBreakThink ), - DEFINE_THINKFUNC( DelayDeathThink ), - -END_DATADESC() - -CTripmineGrenade::CTripmineGrenade() -{ - m_vecDir.Init(); - m_vecEnd.Init(); - m_posOwner.Init(); - m_angleOwner.Init(); -} - -void CTripmineGrenade::Spawn( void ) -{ - Precache( ); - // motor - SetMoveType( MOVETYPE_FLY ); - SetSolid( SOLID_BBOX ); - SetModel( "models/Weapons/w_slam.mdl" ); - - IPhysicsObject *pObject = VPhysicsInitNormal( SOLID_BBOX, GetSolidFlags() | FSOLID_TRIGGER, true ); - pObject->EnableMotion( false ); - SetCollisionGroup( COLLISION_GROUP_WEAPON ); - - SetCycle( 0.0f ); - m_nBody = 3; - m_flDamage = sk_plr_dmg_tripmine.GetFloat(); - m_DmgRadius = sk_tripmine_radius.GetFloat(); - - ResetSequenceInfo( ); - m_flPlaybackRate = 0; - - UTIL_SetSize(this, Vector( -4, -4, -2), Vector(4, 4, 2)); - - m_flPowerUp = gpGlobals->curtime + 2.0; - - SetThink( &CTripmineGrenade::PowerupThink ); - SetNextThink( gpGlobals->curtime + 0.2 ); - - m_takedamage = DAMAGE_YES; - - m_iHealth = 1; - - EmitSound( "TripmineGrenade.Place" ); - SetDamage ( 200 ); - - // Tripmine sits at 90 on wall so rotate back to get m_vecDir - QAngle angles = GetAbsAngles(); - angles.x -= 90; - - AngleVectors( angles, &m_vecDir ); - m_vecEnd = GetAbsOrigin() + m_vecDir * 2048; - - AddEffects( EF_NOSHADOW ); -} - - -void CTripmineGrenade::Precache( void ) -{ - PrecacheModel("models/Weapons/w_slam.mdl"); - - PrecacheScriptSound( "TripmineGrenade.Place" ); - PrecacheScriptSound( "TripmineGrenade.Activate" ); -} - - -void CTripmineGrenade::WarningThink( void ) -{ - // set to power up - SetThink( &CTripmineGrenade::PowerupThink ); - SetNextThink( gpGlobals->curtime + 1.0f ); -} - - -void CTripmineGrenade::PowerupThink( void ) -{ - if (gpGlobals->curtime > m_flPowerUp) - { - MakeBeam( ); - RemoveSolidFlags( FSOLID_NOT_SOLID ); - m_bIsLive = true; - - // play enabled sound - EmitSound( "TripmineGrenade.Activate" ); - } - SetNextThink( gpGlobals->curtime + 0.1f ); -} - - -void CTripmineGrenade::KillBeam( void ) -{ - if ( m_pBeam ) - { - UTIL_Remove( m_pBeam ); - m_pBeam = NULL; - } -} - - -void CTripmineGrenade::MakeBeam( void ) -{ - trace_t tr; - - UTIL_TraceLine( GetAbsOrigin(), m_vecEnd, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - m_flBeamLength = tr.fraction; - - - - // If I hit a living thing, send the beam through me so it turns on briefly - // and then blows the living thing up - CBaseEntity *pEntity = tr.m_pEnt; - CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pEntity ); - - // Draw length is not the beam length if entity is in the way - float drawLength = tr.fraction; - if (pBCC) - { - SetOwnerEntity( pBCC ); - UTIL_TraceLine( GetAbsOrigin(), m_vecEnd, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - m_flBeamLength = tr.fraction; - SetOwnerEntity( NULL ); - - } - - // set to follow laser spot - SetThink( &CTripmineGrenade::BeamBreakThink ); - - // Delay first think slightly so beam has time - // to appear if person right in front of it - SetNextThink( gpGlobals->curtime + 1.0f ); - - Vector vecTmpEnd = GetLocalOrigin() + m_vecDir * 2048 * drawLength; - - m_pBeam = CBeam::BeamCreate( g_pModelNameLaser, 0.35 ); - m_pBeam->PointEntInit( vecTmpEnd, this ); - m_pBeam->SetColor( 255, 55, 52 ); - m_pBeam->SetScrollRate( (int)25.6 ); - m_pBeam->SetBrightness( 64 ); - - int beamAttach = LookupAttachment("beam_attach"); - m_pBeam->SetEndAttachment( beamAttach ); -} - - -void CTripmineGrenade::BeamBreakThink( void ) -{ - // See if I can go solid yet (has dropper moved out of way?) - if (IsSolidFlagSet( FSOLID_NOT_SOLID )) - { - trace_t tr; - Vector vUpBit = GetAbsOrigin(); - vUpBit.z += 5.0; - - UTIL_TraceEntity( this, GetAbsOrigin(), vUpBit, MASK_SHOT, &tr ); - if ( !tr.startsolid && (tr.fraction == 1.0) ) - { - RemoveSolidFlags( FSOLID_NOT_SOLID ); - } - } - - trace_t tr; - - // NOT MASK_SHOT because we want only simple hit boxes - UTIL_TraceLine( GetAbsOrigin(), m_vecEnd, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - - // ALERT( at_console, "%f : %f\n", tr.flFraction, m_flBeamLength ); - - // respawn detect. - if ( !m_pBeam ) - { - MakeBeam( ); - if ( tr.m_pEnt ) - m_hOwner = tr.m_pEnt; // reset owner too - } - - - CBaseEntity *pEntity = tr.m_pEnt; - CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pEntity ); - - if (pBCC || fabs( m_flBeamLength - tr.fraction ) > 0.001) - { - m_iHealth = 0; - Event_Killed( CTakeDamageInfo( (CBaseEntity*)m_hOwner, this, 100, GIB_NORMAL ) ); - return; - } - - SetNextThink( gpGlobals->curtime + 0.05f ); -} - -int CTripmineGrenade::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - if (gpGlobals->curtime < m_flPowerUp && info.GetDamage() < m_iHealth) - { - // disable - // Create( "weapon_tripmine", GetLocalOrigin() + m_vecDir * 24, GetAngles() ); - SetThink( &CTripmineGrenade::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 0.1f ); - KillBeam(); - return FALSE; - } - return BaseClass::OnTakeDamage_Alive( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CTripmineGrenade::Event_Killed( const CTakeDamageInfo &info ) -{ - m_takedamage = DAMAGE_NO; - - SetThink( &CTripmineGrenade::DelayDeathThink ); - SetNextThink( gpGlobals->curtime + 0.25 ); - - EmitSound( "TripmineGrenade.StopSound" ); -} - - -void CTripmineGrenade::DelayDeathThink( void ) -{ - KillBeam(); - trace_t tr; - UTIL_TraceLine ( GetAbsOrigin() + m_vecDir * 8, GetAbsOrigin() - m_vecDir * 64, MASK_SOLID, this, COLLISION_GROUP_NONE, & tr); - UTIL_ScreenShake( GetAbsOrigin(), 25.0, 150.0, 1.0, 750, SHAKE_START ); - - ExplosionCreate( GetAbsOrigin() + m_vecDir * 8, GetAbsAngles(), m_hOwner, (int)GetDamage(), 200, - SF_ENVEXPLOSION_NOSPARKS | SF_ENVEXPLOSION_NODLIGHTS | SF_ENVEXPLOSION_NOSMOKE, 0.0f, this); - - UTIL_Remove( this ); -} - diff --git a/game/server/hl2mp/grenade_tripmine.h b/game/server/hl2mp/grenade_tripmine.h deleted file mode 100644 index 1e51cec8b..000000000 --- a/game/server/hl2mp/grenade_tripmine.h +++ /dev/null @@ -1,55 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef GRENADE_TRIPMINE_H -#define GRENADE_TRIPMINE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "basegrenade_shared.h" - -class CBeam; - - -class CTripmineGrenade : public CBaseGrenade -{ -public: - DECLARE_CLASS( CTripmineGrenade, CBaseGrenade ); - - CTripmineGrenade(); - void Spawn( void ); - void Precache( void ); - - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - - void WarningThink( void ); - void PowerupThink( void ); - void BeamBreakThink( void ); - void DelayDeathThink( void ); - void Event_Killed( const CTakeDamageInfo &info ); - - void MakeBeam( void ); - void KillBeam( void ); - -public: - EHANDLE m_hOwner; - -private: - float m_flPowerUp; - Vector m_vecDir; - Vector m_vecEnd; - float m_flBeamLength; - - CBeam *m_pBeam; - Vector m_posOwner; - Vector m_angleOwner; - - DECLARE_DATADESC(); -}; - -#endif // GRENADE_TRIPMINE_H diff --git a/game/server/hl2mp/hl2mp_bot_temp.cpp b/game/server/hl2mp/hl2mp_bot_temp.cpp deleted file mode 100644 index 7e6db976c..000000000 --- a/game/server/hl2mp/hl2mp_bot_temp.cpp +++ /dev/null @@ -1,430 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Basic BOT handling. -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - - -#include "cbase.h" -#include "player.h" -#include "hl2mp_player.h" -#include "in_buttons.h" -#include "movehelper_server.h" - -void ClientPutInServer( edict_t *pEdict, const char *playername ); -void Bot_Think( CHL2MP_Player *pBot ); - -#ifdef DEBUG - -ConVar bot_forcefireweapon( "bot_forcefireweapon", "", 0, "Force bots with the specified weapon to fire." ); -ConVar bot_forceattack2( "bot_forceattack2", "0", 0, "When firing, use attack2." ); -ConVar bot_forceattackon( "bot_forceattackon", "0", 0, "When firing, don't tap fire, hold it down." ); -ConVar bot_flipout( "bot_flipout", "0", 0, "When on, all bots fire their guns." ); -ConVar bot_defend( "bot_defend", "0", 0, "Set to a team number, and that team will all keep their combat shields raised." ); -ConVar bot_changeclass( "bot_changeclass", "0", 0, "Force all bots to change to the specified class." ); -ConVar bot_zombie( "bot_zombie", "0", 0, "Brraaaaaiiiins." ); -static ConVar bot_mimic( "bot_mimic", "0", 0, "Bot uses usercmd of player by index." ); -static ConVar bot_mimic_yaw_offset( "bot_mimic_yaw_offset", "0", 0, "Offsets the bot yaw." ); -ConVar bot_attack( "bot_attack", "1", 0, "Shoot!" ); - -ConVar bot_sendcmd( "bot_sendcmd", "", 0, "Forces bots to send the specified command." ); - -ConVar bot_crouch( "bot_crouch", "0", 0, "Bot crouches" ); - -static int BotNumber = 1; -static int g_iNextBotTeam = -1; -//static int g_iNextBotClass = -1; - -typedef struct -{ - bool backwards; - - float nextturntime; - bool lastturntoright; - - float nextstrafetime; - float sidemove; - - QAngle forwardAngle; - QAngle lastAngles; - - float m_flJoinTeamTime; - int m_WantedTeam; - int m_WantedClass; -} botdata_t; - -static botdata_t g_BotData[ MAX_PLAYERS ]; - - -//----------------------------------------------------------------------------- -// Purpose: Create a new Bot and put it in the game. -// Output : Pointer to the new Bot, or NULL if there's no free clients. -//----------------------------------------------------------------------------- -CBasePlayer *BotPutInServer( bool bFrozen, int iTeam ) -{ - g_iNextBotTeam = iTeam; - - char botname[ 64 ]; - Q_snprintf( botname, sizeof( botname ), "Bot%02i", BotNumber ); - - // This is an evil hack, but we use it to prevent sv_autojointeam from kicking in. - - edict_t *pEdict = engine->CreateFakeClient( botname ); - - if (!pEdict) - { - Msg( "Failed to create Bot.\n"); - return NULL; - } - - // Allocate a CBasePlayer for the bot, and call spawn - //ClientPutInServer( pEdict, botname ); - CHL2MP_Player *pPlayer = ((CHL2MP_Player *)CBaseEntity::Instance( pEdict )); - pPlayer->ClearFlags(); - pPlayer->AddFlag( FL_CLIENT | FL_FAKECLIENT ); - - if ( bFrozen ) - pPlayer->AddEFlags( EFL_BOT_FROZEN ); - - BotNumber++; - - g_BotData[pPlayer->entindex()-1].m_WantedTeam = iTeam; - g_BotData[pPlayer->entindex()-1].m_flJoinTeamTime = gpGlobals->curtime + 0.3; - - return pPlayer; -} - -//----------------------------------------------------------------------------- -// Purpose: Run through all the Bots in the game and let them think. -//----------------------------------------------------------------------------- -void Bot_RunAll( void ) -{ - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CHL2MP_Player *pPlayer = ToHL2MPPlayer( UTIL_PlayerByIndex( i ) ); - - if ( pPlayer && (pPlayer->GetFlags() & FL_FAKECLIENT) ) - { - Bot_Think( pPlayer ); - } - } -} - -bool RunMimicCommand( CUserCmd& cmd ) -{ - if ( bot_mimic.GetInt() <= 0 ) - return false; - - if ( bot_mimic.GetInt() > gpGlobals->maxClients ) - return false; - - - CBasePlayer *pPlayer = UTIL_PlayerByIndex( bot_mimic.GetInt() ); - if ( !pPlayer ) - return false; - - if ( !pPlayer->GetLastUserCommand() ) - return false; - - cmd = *pPlayer->GetLastUserCommand(); - cmd.viewangles[YAW] += bot_mimic_yaw_offset.GetFloat(); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Simulates a single frame of movement for a player -// Input : *fakeclient - -// *viewangles - -// forwardmove - -// sidemove - -// upmove - -// buttons - -// impulse - -// msec - -// Output : virtual void -//----------------------------------------------------------------------------- -static void RunPlayerMove( CHL2MP_Player *fakeclient, const QAngle& viewangles, float forwardmove, float sidemove, float upmove, unsigned short buttons, byte impulse, float frametime ) -{ - if ( !fakeclient ) - return; - - CUserCmd cmd; - - // Store off the globals.. they're gonna get whacked - float flOldFrametime = gpGlobals->frametime; - float flOldCurtime = gpGlobals->curtime; - - float flTimeBase = gpGlobals->curtime + gpGlobals->frametime - frametime; - fakeclient->SetTimeBase( flTimeBase ); - - Q_memset( &cmd, 0, sizeof( cmd ) ); - - if ( !RunMimicCommand( cmd ) && !bot_zombie.GetBool() ) - { - VectorCopy( viewangles, cmd.viewangles ); - cmd.forwardmove = forwardmove; - cmd.sidemove = sidemove; - cmd.upmove = upmove; - cmd.buttons = buttons; - cmd.impulse = impulse; - cmd.random_seed = random->RandomInt( 0, 0x7fffffff ); - } - - if( bot_crouch.GetInt() ) - cmd.buttons |= IN_DUCK; - - if ( bot_attack.GetBool() ) - cmd.buttons |= IN_ATTACK; - - MoveHelperServer()->SetHost( fakeclient ); - fakeclient->PlayerRunCommand( &cmd, MoveHelperServer() ); - - // save off the last good usercmd - fakeclient->SetLastUserCommand( cmd ); - - // Clear out any fixangle that has been set - fakeclient->pl.fixangle = FIXANGLE_NONE; - - // Restore the globals.. - gpGlobals->frametime = flOldFrametime; - gpGlobals->curtime = flOldCurtime; -} - -//----------------------------------------------------------------------------- -// Purpose: Run this Bot's AI for one frame. -//----------------------------------------------------------------------------- -void Bot_Think( CHL2MP_Player *pBot ) -{ - // Make sure we stay being a bot - pBot->AddFlag( FL_FAKECLIENT ); - - botdata_t *botdata = &g_BotData[ ENTINDEX( pBot->edict() ) - 1 ]; - - QAngle vecViewAngles; - float forwardmove = 0.0; - float sidemove = botdata->sidemove; - float upmove = 0.0; - unsigned short buttons = 0; - byte impulse = 0; - float frametime = gpGlobals->frametime; - - vecViewAngles = pBot->GetLocalAngles(); - - - // Create some random values - if ( pBot->IsAlive() && (pBot->GetSolid() == SOLID_BBOX) ) - { - trace_t trace; - - // Stop when shot - if ( !pBot->IsEFlagSet(EFL_BOT_FROZEN) ) - { - if ( pBot->m_iHealth == 100 ) - { - forwardmove = 600 * ( botdata->backwards ? -1 : 1 ); - if ( botdata->sidemove != 0.0f ) - { - forwardmove *= random->RandomFloat( 0.1, 1.0f ); - } - } - else - { - forwardmove = 0; - } - } - - // Only turn if I haven't been hurt - if ( !pBot->IsEFlagSet(EFL_BOT_FROZEN) && pBot->m_iHealth == 100 ) - { - Vector vecEnd; - Vector forward; - - QAngle angle; - float angledelta = 15.0; - - int maxtries = (int)(360.0 / angledelta); - - if ( botdata->lastturntoright ) - { - angledelta = -angledelta; - } - - angle = pBot->GetLocalAngles(); - - Vector vecSrc; - while ( --maxtries >= 0 ) - { - AngleVectors( angle, &forward ); - - vecSrc = pBot->GetLocalOrigin() + Vector( 0, 0, 36 ); - - vecEnd = vecSrc + forward * 10; - - UTIL_TraceHull( vecSrc, vecEnd, VEC_HULL_MIN, VEC_HULL_MAX, - MASK_PLAYERSOLID, pBot, COLLISION_GROUP_NONE, &trace ); - - if ( trace.fraction == 1.0 ) - { - if ( gpGlobals->curtime < botdata->nextturntime ) - { - break; - } - } - - angle.y += angledelta; - - if ( angle.y > 180 ) - angle.y -= 360; - else if ( angle.y < -180 ) - angle.y += 360; - - botdata->nextturntime = gpGlobals->curtime + 2.0; - botdata->lastturntoright = random->RandomInt( 0, 1 ) == 0 ? true : false; - - botdata->forwardAngle = angle; - botdata->lastAngles = angle; - - } - - - if ( gpGlobals->curtime >= botdata->nextstrafetime ) - { - botdata->nextstrafetime = gpGlobals->curtime + 1.0f; - - if ( random->RandomInt( 0, 5 ) == 0 ) - { - botdata->sidemove = -600.0f + 1200.0f * random->RandomFloat( 0, 2 ); - } - else - { - botdata->sidemove = 0; - } - sidemove = botdata->sidemove; - - if ( random->RandomInt( 0, 20 ) == 0 ) - { - botdata->backwards = true; - } - else - { - botdata->backwards = false; - } - } - - pBot->SetLocalAngles( angle ); - vecViewAngles = angle; - } - - // Is my team being forced to defend? - if ( bot_defend.GetInt() == pBot->GetTeamNumber() ) - { - buttons |= IN_ATTACK2; - } - // If bots are being forced to fire a weapon, see if I have it - else if ( bot_forcefireweapon.GetString() ) - { - CBaseCombatWeapon *pWeapon = pBot->Weapon_OwnsThisType( bot_forcefireweapon.GetString() ); - if ( pWeapon ) - { - // Switch to it if we don't have it out - CBaseCombatWeapon *pActiveWeapon = pBot->GetActiveWeapon(); - - // Switch? - if ( pActiveWeapon != pWeapon ) - { - pBot->Weapon_Switch( pWeapon ); - } - else - { - // Start firing - // Some weapons require releases, so randomise firing - if ( bot_forceattackon.GetBool() || (RandomFloat(0.0,1.0) > 0.5) ) - { - buttons |= bot_forceattack2.GetBool() ? IN_ATTACK2 : IN_ATTACK; - } - } - } - } - - if ( bot_flipout.GetInt() ) - { - if ( bot_forceattackon.GetBool() || (RandomFloat(0.0,1.0) > 0.5) ) - { - buttons |= bot_forceattack2.GetBool() ? IN_ATTACK2 : IN_ATTACK; - } - } - - if ( strlen( bot_sendcmd.GetString() ) > 0 ) - { - //send the cmd from this bot - CCommand args; - args.Tokenize( bot_sendcmd.GetString() ); - pBot->ClientCommand( args ); - - bot_sendcmd.SetValue(""); - } - } - else - { - // Wait for Reinforcement wave - if ( !pBot->IsAlive() ) - { - // Try hitting my buttons occasionally - if ( random->RandomInt( 0, 100 ) > 80 ) - { - // Respawn the bot - if ( random->RandomInt( 0, 1 ) == 0 ) - { - buttons |= IN_JUMP; - } - else - { - buttons = 0; - } - } - } - } - - if ( bot_flipout.GetInt() >= 2 ) - { - - QAngle angOffset = RandomAngle( -1, 1 ); - - botdata->lastAngles += angOffset; - - for ( int i = 0 ; i < 2; i++ ) - { - if ( fabs( botdata->lastAngles[ i ] - botdata->forwardAngle[ i ] ) > 15.0f ) - { - if ( botdata->lastAngles[ i ] > botdata->forwardAngle[ i ] ) - { - botdata->lastAngles[ i ] = botdata->forwardAngle[ i ] + 15; - } - else - { - botdata->lastAngles[ i ] = botdata->forwardAngle[ i ] - 15; - } - } - } - - botdata->lastAngles[ 2 ] = 0; - - pBot->SetLocalAngles( botdata->lastAngles ); - } - - // Fix up the m_fEffects flags - pBot->PostClientMessagesSent(); - - RunPlayerMove( pBot, pBot->GetLocalAngles(), forwardmove, sidemove, upmove, buttons, impulse, frametime ); -} - -#endif - diff --git a/game/server/hl2mp/hl2mp_bot_temp.h b/game/server/hl2mp/hl2mp_bot_temp.h deleted file mode 100644 index 280b48c2d..000000000 --- a/game/server/hl2mp/hl2mp_bot_temp.h +++ /dev/null @@ -1,19 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#ifndef BOT_BASE_H -#define BOT_BASE_H -#ifdef _WIN32 -#pragma once -#endif - - -// If iTeam or iClass is -1, then a team or class is randomly chosen. -CBasePlayer *BotPutInServer( bool bFrozen, int iTeam ); - - -#endif // BOT_BASE_H - diff --git a/game/server/hl2mp/hl2mp_client.cpp b/game/server/hl2mp/hl2mp_client.cpp deleted file mode 100644 index a3490dfa3..000000000 --- a/game/server/hl2mp/hl2mp_client.cpp +++ /dev/null @@ -1,198 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -/* - -===== tf_client.cpp ======================================================== - - HL2 client/server game specific stuff - -*/ - -#include "cbase.h" -#include "hl2mp_player.h" -#include "hl2mp_gamerules.h" -#include "gamerules.h" -#include "teamplay_gamerules.h" -#include "entitylist.h" -#include "physics.h" -#include "game.h" -#include "player_resource.h" -#include "engine/IEngineSound.h" -#include "team.h" -#include "viewport_panel_names.h" - -#include "tier0/vprof.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -void Host_Say( edict_t *pEdict, bool teamonly ); - -extern CBaseEntity* FindPickerEntityClass( CBasePlayer *pPlayer, char *classname ); -extern bool g_fGameOver; - -void FinishClientPutInServer( CHL2MP_Player *pPlayer ) -{ - pPlayer->InitialSpawn(); - pPlayer->Spawn(); - - - char sName[128]; - Q_strncpy( sName, pPlayer->GetPlayerName(), sizeof( sName ) ); - - // First parse the name and remove any %'s - for ( char *pApersand = sName; pApersand != NULL && *pApersand != 0; pApersand++ ) - { - // Replace it with a space - if ( *pApersand == '%' ) - *pApersand = ' '; - } - - // notify other clients of player joining the game - UTIL_ClientPrintAll( HUD_PRINTNOTIFY, "#Game_connected", sName[0] != 0 ? sName : "" ); - - if ( HL2MPRules()->IsTeamplay() == true ) - { - ClientPrint( pPlayer, HUD_PRINTTALK, "You are on team %s1\n", pPlayer->GetTeam()->GetName() ); - } - - const ConVar *hostname = cvar->FindVar( "hostname" ); - const char *title = (hostname) ? hostname->GetString() : "MESSAGE OF THE DAY"; - - KeyValues *data = new KeyValues("data"); - data->SetString( "title", title ); // info panel title - data->SetString( "type", "1" ); // show userdata from stringtable entry - data->SetString( "msg", "motd" ); // use this stringtable entry - - pPlayer->ShowViewPortPanel( PANEL_INFO, true, data ); - - data->deleteThis(); -} - -/* -=========== -ClientPutInServer - -called each time a player is spawned into the game -============ -*/ -void ClientPutInServer( edict_t *pEdict, const char *playername ) -{ - // Allocate a CBaseTFPlayer for pev, and call spawn - CHL2MP_Player *pPlayer = CHL2MP_Player::CreatePlayer( "player", pEdict ); - pPlayer->SetPlayerName( playername ); -} - - -void ClientActive( edict_t *pEdict, bool bLoadGame ) -{ - // Can't load games in CS! - Assert( !bLoadGame ); - - CHL2MP_Player *pPlayer = ToHL2MPPlayer( CBaseEntity::Instance( pEdict ) ); - FinishClientPutInServer( pPlayer ); -} - - -/* -=============== -const char *GetGameDescription() - -Returns the descriptive name of this .dll. E.g., Half-Life, or Team Fortress 2 -=============== -*/ -const char *GetGameDescription() -{ - if ( g_pGameRules ) // this function may be called before the world has spawned, and the game rules initialized - return g_pGameRules->GetGameDescription(); - else - return "Half-Life 2 Deathmatch"; -} - -//----------------------------------------------------------------------------- -// Purpose: Given a player and optional name returns the entity of that -// classname that the player is nearest facing -// -// Input : -// Output : -//----------------------------------------------------------------------------- -CBaseEntity* FindEntity( edict_t *pEdict, char *classname) -{ - // If no name was given set bits based on the picked - if (FStrEq(classname,"")) - { - return (FindPickerEntityClass( static_cast(GetContainingEntity(pEdict)), classname )); - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Precache game-specific models & sounds -//----------------------------------------------------------------------------- -void ClientGamePrecache( void ) -{ - CBaseEntity::PrecacheModel("models/player.mdl"); - CBaseEntity::PrecacheModel( "models/gibs/agibs.mdl" ); - CBaseEntity::PrecacheModel ("models/weapons/v_hands.mdl"); - - CBaseEntity::PrecacheScriptSound( "HUDQuickInfo.LowAmmo" ); - CBaseEntity::PrecacheScriptSound( "HUDQuickInfo.LowHealth" ); - - CBaseEntity::PrecacheScriptSound( "FX_AntlionImpact.ShellImpact" ); - CBaseEntity::PrecacheScriptSound( "Missile.ShotDown" ); - CBaseEntity::PrecacheScriptSound( "Bullets.DefaultNearmiss" ); - CBaseEntity::PrecacheScriptSound( "Bullets.GunshipNearmiss" ); - CBaseEntity::PrecacheScriptSound( "Bullets.StriderNearmiss" ); - - CBaseEntity::PrecacheScriptSound( "Geiger.BeepHigh" ); - CBaseEntity::PrecacheScriptSound( "Geiger.BeepLow" ); -} - - -// called by ClientKill and DeadThink -void respawn( CBaseEntity *pEdict, bool fCopyCorpse ) -{ - CHL2MP_Player *pPlayer = ToHL2MPPlayer( pEdict ); - - if ( pPlayer ) - { - if ( gpGlobals->curtime > pPlayer->GetDeathTime() + DEATH_ANIMATION_TIME ) - { - // respawn player - pPlayer->Spawn(); - } - else - { - pPlayer->SetNextThink( gpGlobals->curtime + 0.1f ); - } - } -} - -void GameStartFrame( void ) -{ - VPROF("GameStartFrame()"); - if ( g_fGameOver ) - return; - - gpGlobals->teamplay = (teamplay.GetInt() != 0); - -#ifdef DEBUG - extern void Bot_RunAll(); - Bot_RunAll(); -#endif -} - -//========================================================= -// instantiate the proper game rules object -//========================================================= -void InstallGameRules() -{ - // vanilla deathmatch - CreateGameRulesObject( "CHL2MPRules" ); -} - diff --git a/game/server/hl2mp/hl2mp_cvars.cpp b/game/server/hl2mp/hl2mp_cvars.cpp deleted file mode 100644 index c237200b2..000000000 --- a/game/server/hl2mp/hl2mp_cvars.cpp +++ /dev/null @@ -1,25 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "hl2mp_cvars.h" - - - -// Ready restart -ConVar mp_readyrestart( - "mp_readyrestart", - "0", - FCVAR_GAMEDLL, - "If non-zero, game will restart once each player gives the ready signal" ); - -// Ready signal -ConVar mp_ready_signal( - "mp_ready_signal", - "ready", - FCVAR_GAMEDLL, - "Text that each player must speak for the match to begin" ); diff --git a/game/server/hl2mp/hl2mp_cvars.h b/game/server/hl2mp/hl2mp_cvars.h deleted file mode 100644 index 64d725d8c..000000000 --- a/game/server/hl2mp/hl2mp_cvars.h +++ /dev/null @@ -1,20 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef HL2MP_CVARS_H -#define HL2MP_CVARS_H -#ifdef _WIN32 -#pragma once -#endif - -#define MAX_INTERMISSION_TIME 120 - -extern ConVar mp_restartround; -extern ConVar mp_readyrestart; -extern ConVar mp_ready_signal; - -#endif //HL2MP_CVARS_H diff --git a/game/server/hl2mp/hl2mp_gameinterface.cpp b/game/server/hl2mp/hl2mp_gameinterface.cpp deleted file mode 100644 index d79b2e516..000000000 --- a/game/server/hl2mp/hl2mp_gameinterface.cpp +++ /dev/null @@ -1,32 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "gameinterface.h" -#include "mapentities.h" -#include "hl2mp_gameinterface.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// -------------------------------------------------------------------------------------------- // -// Mod-specific CServerGameClients implementation. -// -------------------------------------------------------------------------------------------- // - -void CServerGameClients::GetPlayerLimits( int& minplayers, int& maxplayers, int &defaultMaxPlayers ) const -{ - minplayers = defaultMaxPlayers = 2; - maxplayers = 16; -} - -// -------------------------------------------------------------------------------------------- // -// Mod-specific CServerGameDLL implementation. -// -------------------------------------------------------------------------------------------- // - -void CServerGameDLL::LevelInit_ParseAllEntities( const char *pMapEntities ) -{ -} - diff --git a/game/server/hl2mp/hl2mp_gameinterface.h b/game/server/hl2mp/hl2mp_gameinterface.h deleted file mode 100644 index 31e234031..000000000 --- a/game/server/hl2mp/hl2mp_gameinterface.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef HL2MP_GAMEINTERFACE_H -#define HL2MP_GAMEINTERFACE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "gameinterface.h" - -#endif diff --git a/game/server/hl2mp/hl2mp_player.cpp b/game/server/hl2mp/hl2mp_player.cpp deleted file mode 100644 index 1b8fd32e6..000000000 --- a/game/server/hl2mp/hl2mp_player.cpp +++ /dev/null @@ -1,1634 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Player for HL2. -// -//=============================================================================// - -#include "weapon_hl2mpbasehlmpcombatweapon.h" - -#include "cbase.h" -#include "hl2mp_player.h" -#include "globalstate.h" -#include "game.h" -#include "gamerules.h" -#include "hl2mp_player_shared.h" -#include "predicted_viewmodel.h" -#include "in_buttons.h" -#include "hl2mp_gamerules.h" -#include "KeyValues.h" -#include "team.h" -#include "weapon_hl2mpbase.h" -#include "grenade_satchel.h" -#include "eventqueue.h" -#include "GameStats.h" - -#include "engine/IEngineSound.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" - -#include "ilagcompensationmanager.h" - -int g_iLastCitizenModel = 0; -int g_iLastCombineModel = 0; - -CBaseEntity *g_pLastCombineSpawn = NULL; -CBaseEntity *g_pLastRebelSpawn = NULL; -extern CBaseEntity *g_pLastSpawn; - -#define HL2MP_COMMAND_MAX_RATE 0.3 - -void DropPrimedFragGrenade( CHL2MP_Player *pPlayer, CBaseCombatWeapon *pGrenade ); - -LINK_ENTITY_TO_CLASS( player, CHL2MP_Player ); - -LINK_ENTITY_TO_CLASS( info_player_combine, CPointEntity ); -LINK_ENTITY_TO_CLASS( info_player_rebel, CPointEntity ); - -IMPLEMENT_SERVERCLASS_ST(CHL2MP_Player, DT_HL2MP_Player) - SendPropAngle( SENDINFO_VECTORELEM2(m_angEyeAngles, 0, x), 11, SPROP_CHANGES_OFTEN ), - SendPropAngle( SENDINFO_VECTORELEM2(m_angEyeAngles, 1, y), 11, SPROP_CHANGES_OFTEN ), - SendPropEHandle( SENDINFO( m_hRagdoll ) ), - SendPropInt( SENDINFO( m_iSpawnInterpCounter), 4 ), - SendPropInt( SENDINFO( m_iPlayerSoundType), 3 ), - - SendPropExclude( "DT_BaseAnimating", "m_flPoseParameter" ), - SendPropExclude( "DT_BaseFlex", "m_viewtarget" ), - -// SendPropExclude( "DT_ServerAnimationData" , "m_flCycle" ), -// SendPropExclude( "DT_AnimTimeMustBeFirst" , "m_flAnimTime" ), - -END_SEND_TABLE() - -BEGIN_DATADESC( CHL2MP_Player ) -END_DATADESC() - -const char *g_ppszRandomCitizenModels[] = -{ - "models/humans/group03/male_01.mdl", - "models/humans/group03/male_02.mdl", - "models/humans/group03/female_01.mdl", - "models/humans/group03/male_03.mdl", - "models/humans/group03/female_02.mdl", - "models/humans/group03/male_04.mdl", - "models/humans/group03/female_03.mdl", - "models/humans/group03/male_05.mdl", - "models/humans/group03/female_04.mdl", - "models/humans/group03/male_06.mdl", - "models/humans/group03/female_06.mdl", - "models/humans/group03/male_07.mdl", - "models/humans/group03/female_07.mdl", - "models/humans/group03/male_08.mdl", - "models/humans/group03/male_09.mdl", -}; - -const char *g_ppszRandomCombineModels[] = -{ - "models/combine_soldier.mdl", - "models/combine_soldier_prisonguard.mdl", - "models/combine_super_soldier.mdl", - "models/police.mdl", -}; - - -#define MAX_COMBINE_MODELS 4 -#define MODEL_CHANGE_INTERVAL 5.0f -#define TEAM_CHANGE_INTERVAL 5.0f - -#define HL2MPPLAYER_PHYSDAMAGE_SCALE 4.0f - -#ifdef _MSC_VER -#pragma warning( disable : 4355 ) -#endif - -CHL2MP_Player::CHL2MP_Player() : m_PlayerAnimState( this ) -{ - m_angEyeAngles.Init(); - - m_iLastWeaponFireUsercmd = 0; - - m_flNextModelChangeTime = 0.0f; - m_flNextTeamChangeTime = 0.0f; - - m_iSpawnInterpCounter = 0; - - m_bEnterObserver = false; - m_bReady = false; - - BaseClass::ChangeTeam( 0 ); - -// UseClientSideAnimation(); -} - -CHL2MP_Player::~CHL2MP_Player( void ) -{ - -} - -void CHL2MP_Player::UpdateOnRemove( void ) -{ - if ( m_hRagdoll ) - { - UTIL_RemoveImmediate( m_hRagdoll ); - m_hRagdoll = NULL; - } - - BaseClass::UpdateOnRemove(); -} - -void CHL2MP_Player::Precache( void ) -{ - BaseClass::Precache(); - - PrecacheModel ( "sprites/glow01.vmt" ); - - //Precache Citizen models - int nHeads = ARRAYSIZE( g_ppszRandomCitizenModels ); - int i; - - for ( i = 0; i < nHeads; ++i ) - PrecacheModel( g_ppszRandomCitizenModels[i] ); - - //Precache Combine Models - nHeads = ARRAYSIZE( g_ppszRandomCombineModels ); - - for ( i = 0; i < nHeads; ++i ) - PrecacheModel( g_ppszRandomCombineModels[i] ); - - PrecacheFootStepSounds(); - - PrecacheScriptSound( "NPC_MetroPolice.Die" ); - PrecacheScriptSound( "NPC_CombineS.Die" ); - PrecacheScriptSound( "NPC_Citizen.die" ); -} - -void CHL2MP_Player::GiveAllItems( void ) -{ - EquipSuit(); - - CBasePlayer::GiveAmmo( 255, "Pistol"); - CBasePlayer::GiveAmmo( 255, "AR2" ); - CBasePlayer::GiveAmmo( 5, "AR2AltFire" ); - CBasePlayer::GiveAmmo( 255, "SMG1"); - CBasePlayer::GiveAmmo( 1, "smg1_grenade"); - CBasePlayer::GiveAmmo( 255, "Buckshot"); - CBasePlayer::GiveAmmo( 32, "357" ); - CBasePlayer::GiveAmmo( 3, "rpg_round"); - - CBasePlayer::GiveAmmo( 1, "grenade" ); - CBasePlayer::GiveAmmo( 2, "slam" ); - - GiveNamedItem( "weapon_crowbar" ); - GiveNamedItem( "weapon_stunstick" ); - GiveNamedItem( "weapon_pistol" ); - GiveNamedItem( "weapon_357" ); - - GiveNamedItem( "weapon_smg1" ); - GiveNamedItem( "weapon_ar2" ); - - GiveNamedItem( "weapon_shotgun" ); - GiveNamedItem( "weapon_frag" ); - - GiveNamedItem( "weapon_crossbow" ); - - GiveNamedItem( "weapon_rpg" ); - - GiveNamedItem( "weapon_slam" ); - - GiveNamedItem( "weapon_physcannon" ); - -} - -void CHL2MP_Player::GiveDefaultItems( void ) -{ - EquipSuit(); - - CBasePlayer::GiveAmmo( 255, "Pistol"); - CBasePlayer::GiveAmmo( 45, "SMG1"); - CBasePlayer::GiveAmmo( 1, "grenade" ); - CBasePlayer::GiveAmmo( 6, "Buckshot"); - CBasePlayer::GiveAmmo( 6, "357" ); - - if ( GetPlayerModelType() == PLAYER_SOUNDS_METROPOLICE || GetPlayerModelType() == PLAYER_SOUNDS_COMBINESOLDIER ) - { - GiveNamedItem( "weapon_stunstick" ); - } - else if ( GetPlayerModelType() == PLAYER_SOUNDS_CITIZEN ) - { - GiveNamedItem( "weapon_crowbar" ); - } - - GiveNamedItem( "weapon_pistol" ); - GiveNamedItem( "weapon_smg1" ); - GiveNamedItem( "weapon_frag" ); - GiveNamedItem( "weapon_physcannon" ); - - const char *szDefaultWeaponName = engine->GetClientConVarValue( engine->IndexOfEdict( edict() ), "cl_defaultweapon" ); - - CBaseCombatWeapon *pDefaultWeapon = Weapon_OwnsThisType( szDefaultWeaponName ); - - if ( pDefaultWeapon ) - { - Weapon_Switch( pDefaultWeapon ); - } - else - { - Weapon_Switch( Weapon_OwnsThisType( "weapon_physcannon" ) ); - } -} - -void CHL2MP_Player::PickDefaultSpawnTeam( void ) -{ - if ( GetTeamNumber() == 0 ) - { - if ( HL2MPRules()->IsTeamplay() == false ) - { - if ( GetModelPtr() == NULL ) - { - const char *szModelName = NULL; - szModelName = engine->GetClientConVarValue( engine->IndexOfEdict( edict() ), "cl_playermodel" ); - - if ( ValidatePlayerModel( szModelName ) == false ) - { - char szReturnString[512]; - - Q_snprintf( szReturnString, sizeof (szReturnString ), "cl_playermodel models/combine_soldier.mdl\n" ); - engine->ClientCommand ( edict(), szReturnString ); - } - - ChangeTeam( TEAM_UNASSIGNED ); - } - } - else - { - CTeam *pCombine = g_Teams[TEAM_COMBINE]; - CTeam *pRebels = g_Teams[TEAM_REBELS]; - - if ( pCombine == NULL || pRebels == NULL ) - { - ChangeTeam( random->RandomInt( TEAM_COMBINE, TEAM_REBELS ) ); - } - else - { - if ( pCombine->GetNumPlayers() > pRebels->GetNumPlayers() ) - { - ChangeTeam( TEAM_REBELS ); - } - else if ( pCombine->GetNumPlayers() < pRebels->GetNumPlayers() ) - { - ChangeTeam( TEAM_COMBINE ); - } - else - { - ChangeTeam( random->RandomInt( TEAM_COMBINE, TEAM_REBELS ) ); - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Sets HL2 specific defaults. -//----------------------------------------------------------------------------- -void CHL2MP_Player::Spawn(void) -{ - m_flNextModelChangeTime = 0.0f; - m_flNextTeamChangeTime = 0.0f; - - PickDefaultSpawnTeam(); - - BaseClass::Spawn(); - - if ( !IsObserver() ) - { - pl.deadflag = false; - RemoveSolidFlags( FSOLID_NOT_SOLID ); - - RemoveEffects( EF_NODRAW ); - - GiveDefaultItems(); - } - - RemoveEffects( EF_NOINTERP ); - - SetNumAnimOverlays( 3 ); - ResetAnimation(); - - m_nRenderFX = kRenderNormal; - - m_Local.m_iHideHUD = 0; - - AddFlag(FL_ONGROUND); // set the player on the ground at the start of the round. - - m_impactEnergyScale = HL2MPPLAYER_PHYSDAMAGE_SCALE; - - if ( HL2MPRules()->IsIntermission() ) - { - AddFlag( FL_FROZEN ); - } - else - { - RemoveFlag( FL_FROZEN ); - } - - m_iSpawnInterpCounter = (m_iSpawnInterpCounter + 1) % 8; - - m_Local.m_bDucked = false; - - SetPlayerUnderwater(false); - - m_bReady = false; -} - -void CHL2MP_Player::PickupObject( CBaseEntity *pObject, bool bLimitMassAndSize ) -{ - -} - -bool CHL2MP_Player::ValidatePlayerModel( const char *pModel ) -{ - int iModels = ARRAYSIZE( g_ppszRandomCitizenModels ); - int i; - - for ( i = 0; i < iModels; ++i ) - { - if ( !Q_stricmp( g_ppszRandomCitizenModels[i], pModel ) ) - { - return true; - } - } - - iModels = ARRAYSIZE( g_ppszRandomCombineModels ); - - for ( i = 0; i < iModels; ++i ) - { - if ( !Q_stricmp( g_ppszRandomCombineModels[i], pModel ) ) - { - return true; - } - } - - return false; -} - -void CHL2MP_Player::SetPlayerTeamModel( void ) -{ - const char *szModelName = NULL; - szModelName = engine->GetClientConVarValue( engine->IndexOfEdict( edict() ), "cl_playermodel" ); - - int modelIndex = modelinfo->GetModelIndex( szModelName ); - - if ( modelIndex == -1 || ValidatePlayerModel( szModelName ) == false ) - { - szModelName = "models/Combine_Soldier.mdl"; - m_iModelType = TEAM_COMBINE; - - char szReturnString[512]; - - Q_snprintf( szReturnString, sizeof (szReturnString ), "cl_playermodel %s\n", szModelName ); - engine->ClientCommand ( edict(), szReturnString ); - } - - if ( GetTeamNumber() == TEAM_COMBINE ) - { - if ( Q_stristr( szModelName, "models/human") ) - { - int nHeads = ARRAYSIZE( g_ppszRandomCombineModels ); - - g_iLastCombineModel = ( g_iLastCombineModel + 1 ) % nHeads; - szModelName = g_ppszRandomCombineModels[g_iLastCombineModel]; - } - - m_iModelType = TEAM_COMBINE; - } - else if ( GetTeamNumber() == TEAM_REBELS ) - { - if ( !Q_stristr( szModelName, "models/human") ) - { - int nHeads = ARRAYSIZE( g_ppszRandomCitizenModels ); - - g_iLastCitizenModel = ( g_iLastCitizenModel + 1 ) % nHeads; - szModelName = g_ppszRandomCitizenModels[g_iLastCitizenModel]; - } - - m_iModelType = TEAM_REBELS; - } - - SetModel( szModelName ); - SetupPlayerSoundsByModel( szModelName ); - - m_flNextModelChangeTime = gpGlobals->curtime + MODEL_CHANGE_INTERVAL; -} - -void CHL2MP_Player::SetPlayerModel( void ) -{ - const char *szModelName = NULL; - const char *pszCurrentModelName = modelinfo->GetModelName( GetModel()); - - szModelName = engine->GetClientConVarValue( engine->IndexOfEdict( edict() ), "cl_playermodel" ); - - if ( ValidatePlayerModel( szModelName ) == false ) - { - char szReturnString[512]; - - if ( ValidatePlayerModel( pszCurrentModelName ) == false ) - { - pszCurrentModelName = "models/Combine_Soldier.mdl"; - } - - Q_snprintf( szReturnString, sizeof (szReturnString ), "cl_playermodel %s\n", pszCurrentModelName ); - engine->ClientCommand ( edict(), szReturnString ); - - szModelName = pszCurrentModelName; - } - - if ( GetTeamNumber() == TEAM_COMBINE ) - { - int nHeads = ARRAYSIZE( g_ppszRandomCombineModels ); - - g_iLastCombineModel = ( g_iLastCombineModel + 1 ) % nHeads; - szModelName = g_ppszRandomCombineModels[g_iLastCombineModel]; - - m_iModelType = TEAM_COMBINE; - } - else if ( GetTeamNumber() == TEAM_REBELS ) - { - int nHeads = ARRAYSIZE( g_ppszRandomCitizenModels ); - - g_iLastCitizenModel = ( g_iLastCitizenModel + 1 ) % nHeads; - szModelName = g_ppszRandomCitizenModels[g_iLastCitizenModel]; - - m_iModelType = TEAM_REBELS; - } - else - { - if ( Q_strlen( szModelName ) == 0 ) - { - szModelName = g_ppszRandomCitizenModels[0]; - } - - if ( Q_stristr( szModelName, "models/human") ) - { - m_iModelType = TEAM_REBELS; - } - else - { - m_iModelType = TEAM_COMBINE; - } - } - - int modelIndex = modelinfo->GetModelIndex( szModelName ); - - if ( modelIndex == -1 ) - { - szModelName = "models/Combine_Soldier.mdl"; - m_iModelType = TEAM_COMBINE; - - char szReturnString[512]; - - Q_snprintf( szReturnString, sizeof (szReturnString ), "cl_playermodel %s\n", szModelName ); - engine->ClientCommand ( edict(), szReturnString ); - } - - SetModel( szModelName ); - SetupPlayerSoundsByModel( szModelName ); - - m_flNextModelChangeTime = gpGlobals->curtime + MODEL_CHANGE_INTERVAL; -} - -void CHL2MP_Player::SetupPlayerSoundsByModel( const char *pModelName ) -{ - if ( Q_stristr( pModelName, "models/human") ) - { - m_iPlayerSoundType = (int)PLAYER_SOUNDS_CITIZEN; - } - else if ( Q_stristr(pModelName, "police" ) ) - { - m_iPlayerSoundType = (int)PLAYER_SOUNDS_METROPOLICE; - } - else if ( Q_stristr(pModelName, "combine" ) ) - { - m_iPlayerSoundType = (int)PLAYER_SOUNDS_COMBINESOLDIER; - } -} - -void CHL2MP_Player::ResetAnimation( void ) -{ - if ( IsAlive() ) - { - SetSequence ( -1 ); - SetActivity( ACT_INVALID ); - - if (!GetAbsVelocity().x && !GetAbsVelocity().y) - SetAnimation( PLAYER_IDLE ); - else if ((GetAbsVelocity().x || GetAbsVelocity().y) && ( GetFlags() & FL_ONGROUND )) - SetAnimation( PLAYER_WALK ); - else if (GetWaterLevel() > 1) - SetAnimation( PLAYER_WALK ); - } -} - - -bool CHL2MP_Player::Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmodelindex ) -{ - bool bRet = BaseClass::Weapon_Switch( pWeapon, viewmodelindex ); - - if ( bRet == true ) - { - ResetAnimation(); - } - - return bRet; -} - -void CHL2MP_Player::PreThink( void ) -{ - QAngle vOldAngles = GetLocalAngles(); - QAngle vTempAngles = GetLocalAngles(); - - vTempAngles = EyeAngles(); - - if ( vTempAngles[PITCH] > 180.0f ) - { - vTempAngles[PITCH] -= 360.0f; - } - - SetLocalAngles( vTempAngles ); - - BaseClass::PreThink(); - State_PreThink(); - - //Reset bullet force accumulator, only lasts one frame - m_vecTotalBulletForce = vec3_origin; - SetLocalAngles( vOldAngles ); -} - -void CHL2MP_Player::PostThink( void ) -{ - BaseClass::PostThink(); - - if ( GetFlags() & FL_DUCKING ) - { - SetCollisionBounds( VEC_CROUCH_TRACE_MIN, VEC_CROUCH_TRACE_MAX ); - } - - m_PlayerAnimState.Update(); - - // Store the eye angles pitch so the client can compute its animation state correctly. - m_angEyeAngles = EyeAngles(); - - QAngle angles = GetLocalAngles(); - angles[PITCH] = 0; - SetLocalAngles( angles ); -} - -void CHL2MP_Player::PlayerDeathThink() -{ - if( !IsObserver() ) - { - BaseClass::PlayerDeathThink(); - } -} - -void CHL2MP_Player::FireBullets ( const FireBulletsInfo_t &info ) -{ - // Move other players back to history positions based on local player's lag - lagcompensation->StartLagCompensation( this, this->GetCurrentCommand() ); - - FireBulletsInfo_t modinfo = info; - - CWeaponHL2MPBase *pWeapon = dynamic_cast( GetActiveWeapon() ); - - if ( pWeapon ) - { - modinfo.m_iPlayerDamage = modinfo.m_iDamage = pWeapon->GetHL2MPWpnData().m_iPlayerDamage; - } - - NoteWeaponFired(); - - BaseClass::FireBullets( modinfo ); - - // Move other players back to history positions based on local player's lag - lagcompensation->FinishLagCompensation( this ); -} - -void CHL2MP_Player::NoteWeaponFired( void ) -{ - Assert( m_pCurrentCommand ); - if( m_pCurrentCommand ) - { - m_iLastWeaponFireUsercmd = m_pCurrentCommand->command_number; - } -} - -extern ConVar sv_maxunlag; - -bool CHL2MP_Player::WantsLagCompensationOnEntity( const CBasePlayer *pPlayer, const CUserCmd *pCmd, const CBitVec *pEntityTransmitBits ) const -{ - // No need to lag compensate at all if we're not attacking in this command and - // we haven't attacked recently. - if ( !( pCmd->buttons & IN_ATTACK ) && (pCmd->command_number - m_iLastWeaponFireUsercmd > 5) ) - return false; - - // If this entity hasn't been transmitted to us and acked, then don't bother lag compensating it. - if ( pEntityTransmitBits && !pEntityTransmitBits->Get( pPlayer->entindex() ) ) - return false; - - const Vector &vMyOrigin = GetAbsOrigin(); - const Vector &vHisOrigin = pPlayer->GetAbsOrigin(); - - // get max distance player could have moved within max lag compensation time, - // multiply by 1.5 to to avoid "dead zones" (sqrt(2) would be the exact value) - float maxDistance = 1.5 * pPlayer->MaxSpeed() * sv_maxunlag.GetFloat(); - - // If the player is within this distance, lag compensate them in case they're running past us. - if ( vHisOrigin.DistTo( vMyOrigin ) < maxDistance ) - return true; - - // If their origin is not within a 45 degree cone in front of us, no need to lag compensate. - Vector vForward; - AngleVectors( pCmd->viewangles, &vForward ); - - Vector vDiff = vHisOrigin - vMyOrigin; - VectorNormalize( vDiff ); - - float flCosAngle = 0.707107f; // 45 degree angle - if ( vForward.Dot( vDiff ) < flCosAngle ) - return false; - - return true; -} - -Activity CHL2MP_Player::TranslateTeamActivity( Activity ActToTranslate ) -{ - if ( m_iModelType == TEAM_COMBINE ) - return ActToTranslate; - - if ( ActToTranslate == ACT_RUN ) - return ACT_RUN_AIM_AGITATED; - - if ( ActToTranslate == ACT_IDLE ) - return ACT_IDLE_AIM_AGITATED; - - if ( ActToTranslate == ACT_WALK ) - return ACT_WALK_AIM_AGITATED; - - return ActToTranslate; -} - -extern ConVar hl2_normspeed; - -// Set the activity based on an event or current state -void CHL2MP_Player::SetAnimation( PLAYER_ANIM playerAnim ) -{ - int animDesired; - - float speed; - - speed = GetAbsVelocity().Length2D(); - - - // bool bRunning = true; - - //Revisit! -/* if ( ( m_nButtons & ( IN_FORWARD | IN_BACK | IN_MOVELEFT | IN_MOVERIGHT ) ) ) - { - if ( speed > 1.0f && speed < hl2_normspeed.GetFloat() - 20.0f ) - { - bRunning = false; - } - }*/ - - if ( GetFlags() & ( FL_FROZEN | FL_ATCONTROLS ) ) - { - speed = 0; - playerAnim = PLAYER_IDLE; - } - - Activity idealActivity = ACT_HL2MP_RUN; - - // This could stand to be redone. Why is playerAnim abstracted from activity? (sjb) - if ( playerAnim == PLAYER_JUMP ) - { - idealActivity = ACT_HL2MP_JUMP; - } - else if ( playerAnim == PLAYER_DIE ) - { - if ( m_lifeState == LIFE_ALIVE ) - { - return; - } - } - else if ( playerAnim == PLAYER_ATTACK1 ) - { - if ( GetActivity( ) == ACT_HOVER || - GetActivity( ) == ACT_SWIM || - GetActivity( ) == ACT_HOP || - GetActivity( ) == ACT_LEAP || - GetActivity( ) == ACT_DIESIMPLE ) - { - idealActivity = GetActivity( ); - } - else - { - idealActivity = ACT_HL2MP_GESTURE_RANGE_ATTACK; - } - } - else if ( playerAnim == PLAYER_RELOAD ) - { - idealActivity = ACT_HL2MP_GESTURE_RELOAD; - } - else if ( playerAnim == PLAYER_IDLE || playerAnim == PLAYER_WALK ) - { - if ( !( GetFlags() & FL_ONGROUND ) && GetActivity( ) == ACT_HL2MP_JUMP ) // Still jumping - { - idealActivity = GetActivity( ); - } - /* - else if ( GetWaterLevel() > 1 ) - { - if ( speed == 0 ) - idealActivity = ACT_HOVER; - else - idealActivity = ACT_SWIM; - } - */ - else - { - if ( GetFlags() & FL_DUCKING ) - { - if ( speed > 0 ) - { - idealActivity = ACT_HL2MP_WALK_CROUCH; - } - else - { - idealActivity = ACT_HL2MP_IDLE_CROUCH; - } - } - else - { - if ( speed > 0 ) - { - /* - if ( bRunning == false ) - { - idealActivity = ACT_WALK; - } - else - */ - { - idealActivity = ACT_HL2MP_RUN; - } - } - else - { - idealActivity = ACT_HL2MP_IDLE; - } - } - } - - idealActivity = TranslateTeamActivity( idealActivity ); - } - - if ( idealActivity == ACT_HL2MP_GESTURE_RANGE_ATTACK ) - { - RestartGesture( Weapon_TranslateActivity( idealActivity ) ); - - // FIXME: this seems a bit wacked - Weapon_SetActivity( Weapon_TranslateActivity( ACT_RANGE_ATTACK1 ), 0 ); - - return; - } - else if ( idealActivity == ACT_HL2MP_GESTURE_RELOAD ) - { - RestartGesture( Weapon_TranslateActivity( idealActivity ) ); - return; - } - else - { - SetActivity( idealActivity ); - - animDesired = SelectWeightedSequence( Weapon_TranslateActivity ( idealActivity ) ); - - if (animDesired == -1) - { - animDesired = SelectWeightedSequence( idealActivity ); - - if ( animDesired == -1 ) - { - animDesired = 0; - } - } - - // Already using the desired animation? - if ( GetSequence() == animDesired ) - return; - - m_flPlaybackRate = 1.0; - ResetSequence( animDesired ); - SetCycle( 0 ); - return; - } - - // Already using the desired animation? - if ( GetSequence() == animDesired ) - return; - - //Msg( "Set animation to %d\n", animDesired ); - // Reset to first frame of desired animation - ResetSequence( animDesired ); - SetCycle( 0 ); -} - - -extern int gEvilImpulse101; -//----------------------------------------------------------------------------- -// Purpose: Player reacts to bumping a weapon. -// Input : pWeapon - the weapon that the player bumped into. -// Output : Returns true if player picked up the weapon -//----------------------------------------------------------------------------- -bool CHL2MP_Player::BumpWeapon( CBaseCombatWeapon *pWeapon ) -{ - CBaseCombatCharacter *pOwner = pWeapon->GetOwner(); - - // Can I have this weapon type? - if ( !IsAllowedToPickupWeapons() ) - return false; - - if ( pOwner || !Weapon_CanUse( pWeapon ) || !g_pGameRules->CanHavePlayerItem( this, pWeapon ) ) - { - if ( gEvilImpulse101 ) - { - UTIL_Remove( pWeapon ); - } - return false; - } - - // Don't let the player fetch weapons through walls (use MASK_SOLID so that you can't pickup through windows) - if( !pWeapon->FVisible( this, MASK_SOLID ) && !(GetFlags() & FL_NOTARGET) ) - { - return false; - } - - bool bOwnsWeaponAlready = !!Weapon_OwnsThisType( pWeapon->GetClassname(), pWeapon->GetSubType()); - - if ( bOwnsWeaponAlready == true ) - { - //If we have room for the ammo, then "take" the weapon too. - if ( Weapon_EquipAmmoOnly( pWeapon ) ) - { - pWeapon->CheckRespawn(); - - UTIL_Remove( pWeapon ); - return true; - } - else - { - return false; - } - } - - pWeapon->CheckRespawn(); - Weapon_Equip( pWeapon ); - - return true; -} - -void CHL2MP_Player::ChangeTeam( int iTeam ) -{ -/* if ( GetNextTeamChangeTime() >= gpGlobals->curtime ) - { - char szReturnString[128]; - Q_snprintf( szReturnString, sizeof( szReturnString ), "Please wait %d more seconds before trying to switch teams again.\n", (int)(GetNextTeamChangeTime() - gpGlobals->curtime) ); - - ClientPrint( this, HUD_PRINTTALK, szReturnString ); - return; - }*/ - - bool bKill = false; - - if ( HL2MPRules()->IsTeamplay() != true && iTeam != TEAM_SPECTATOR ) - { - //don't let them try to join combine or rebels during deathmatch. - iTeam = TEAM_UNASSIGNED; - } - - if ( HL2MPRules()->IsTeamplay() == true ) - { - if ( iTeam != GetTeamNumber() && GetTeamNumber() != TEAM_UNASSIGNED ) - { - bKill = true; - } - } - - BaseClass::ChangeTeam( iTeam ); - - m_flNextTeamChangeTime = gpGlobals->curtime + TEAM_CHANGE_INTERVAL; - - if ( HL2MPRules()->IsTeamplay() == true ) - { - SetPlayerTeamModel(); - } - else - { - SetPlayerModel(); - } - - if ( iTeam == TEAM_SPECTATOR ) - { - RemoveAllItems( true ); - - State_Transition( STATE_OBSERVER_MODE ); - } - - if ( bKill == true ) - { - CommitSuicide(); - } -} - -bool CHL2MP_Player::HandleCommand_JoinTeam( int team ) -{ - if ( !GetGlobalTeam( team ) || team == 0 ) - { - Warning( "HandleCommand_JoinTeam( %d ) - invalid team index.\n", team ); - return false; - } - - if ( team == TEAM_SPECTATOR ) - { - // Prevent this is the cvar is set - if ( !mp_allowspectators.GetInt() ) - { - ClientPrint( this, HUD_PRINTCENTER, "#Cannot_Be_Spectator" ); - return false; - } - - if ( GetTeamNumber() != TEAM_UNASSIGNED && !IsDead() ) - { - m_fNextSuicideTime = gpGlobals->curtime; // allow the suicide to work - - CommitSuicide(); - - // add 1 to frags to balance out the 1 subtracted for killing yourself - IncrementFragCount( 1 ); - } - - ChangeTeam( TEAM_SPECTATOR ); - - return true; - } - else - { - StopObserverMode(); - State_Transition(STATE_ACTIVE); - } - - // Switch their actual team... - ChangeTeam( team ); - - return true; -} - -bool CHL2MP_Player::ClientCommand( const CCommand &args ) -{ - if ( FStrEq( args[0], "spectate" ) ) - { - if ( ShouldRunRateLimitedCommand( args ) ) - { - // instantly join spectators - HandleCommand_JoinTeam( TEAM_SPECTATOR ); - } - return true; - } - else if ( FStrEq( args[0], "jointeam" ) ) - { - if ( args.ArgC() < 2 ) - { - Warning( "Player sent bad jointeam syntax\n" ); - } - - if ( ShouldRunRateLimitedCommand( args ) ) - { - int iTeam = atoi( args[1] ); - HandleCommand_JoinTeam( iTeam ); - } - return true; - } - else if ( FStrEq( args[0], "joingame" ) ) - { - return true; - } - - return BaseClass::ClientCommand( args ); -} - -void CHL2MP_Player::CheatImpulseCommands( int iImpulse ) -{ - switch ( iImpulse ) - { - case 101: - { - if( sv_cheats->GetBool() ) - { - GiveAllItems(); - } - } - break; - - default: - BaseClass::CheatImpulseCommands( iImpulse ); - } -} - -bool CHL2MP_Player::ShouldRunRateLimitedCommand( const CCommand &args ) -{ - int i = m_RateLimitLastCommandTimes.Find( args[0] ); - if ( i == m_RateLimitLastCommandTimes.InvalidIndex() ) - { - m_RateLimitLastCommandTimes.Insert( args[0], gpGlobals->curtime ); - return true; - } - else if ( (gpGlobals->curtime - m_RateLimitLastCommandTimes[i]) < HL2MP_COMMAND_MAX_RATE ) - { - // Too fast. - return false; - } - else - { - m_RateLimitLastCommandTimes[i] = gpGlobals->curtime; - return true; - } -} - -void CHL2MP_Player::CreateViewModel( int index /*=0*/ ) -{ - Assert( index >= 0 && index < MAX_VIEWMODELS ); - - if ( GetViewModel( index ) ) - return; - - CPredictedViewModel *vm = ( CPredictedViewModel * )CreateEntityByName( "predicted_viewmodel" ); - if ( vm ) - { - vm->SetAbsOrigin( GetAbsOrigin() ); - vm->SetOwner( this ); - vm->SetIndex( index ); - DispatchSpawn( vm ); - vm->FollowEntity( this, false ); - m_hViewModel.Set( index, vm ); - } -} - -bool CHL2MP_Player::BecomeRagdollOnClient( const Vector &force ) -{ - return true; -} - -// -------------------------------------------------------------------------------- // -// Ragdoll entities. -// -------------------------------------------------------------------------------- // - -class CHL2MPRagdoll : public CBaseAnimatingOverlay -{ -public: - DECLARE_CLASS( CHL2MPRagdoll, CBaseAnimatingOverlay ); - DECLARE_SERVERCLASS(); - - // Transmit ragdolls to everyone. - virtual int UpdateTransmitState() - { - return SetTransmitState( FL_EDICT_ALWAYS ); - } - -public: - // In case the client has the player entity, we transmit the player index. - // In case the client doesn't have it, we transmit the player's model index, origin, and angles - // so they can create a ragdoll in the right place. - CNetworkHandle( CBaseEntity, m_hPlayer ); // networked entity handle - CNetworkVector( m_vecRagdollVelocity ); - CNetworkVector( m_vecRagdollOrigin ); -}; - -LINK_ENTITY_TO_CLASS( hl2mp_ragdoll, CHL2MPRagdoll ); - -IMPLEMENT_SERVERCLASS_ST_NOBASE( CHL2MPRagdoll, DT_HL2MPRagdoll ) - SendPropVector( SENDINFO(m_vecRagdollOrigin), -1, SPROP_COORD ), - SendPropEHandle( SENDINFO( m_hPlayer ) ), - SendPropModelIndex( SENDINFO( m_nModelIndex ) ), - SendPropInt ( SENDINFO(m_nForceBone), 8, 0 ), - SendPropVector ( SENDINFO(m_vecForce), -1, SPROP_NOSCALE ), - SendPropVector( SENDINFO( m_vecRagdollVelocity ) ) -END_SEND_TABLE() - - -void CHL2MP_Player::CreateRagdollEntity( void ) -{ - if ( m_hRagdoll ) - { - UTIL_RemoveImmediate( m_hRagdoll ); - m_hRagdoll = NULL; - } - - // If we already have a ragdoll, don't make another one. - CHL2MPRagdoll *pRagdoll = dynamic_cast< CHL2MPRagdoll* >( m_hRagdoll.Get() ); - - if ( !pRagdoll ) - { - // create a new one - pRagdoll = dynamic_cast< CHL2MPRagdoll* >( CreateEntityByName( "hl2mp_ragdoll" ) ); - } - - if ( pRagdoll ) - { - pRagdoll->m_hPlayer = this; - pRagdoll->m_vecRagdollOrigin = GetAbsOrigin(); - pRagdoll->m_vecRagdollVelocity = GetAbsVelocity(); - pRagdoll->m_nModelIndex = m_nModelIndex; - pRagdoll->m_nForceBone = m_nForceBone; - pRagdoll->m_vecForce = m_vecTotalBulletForce; - pRagdoll->SetAbsOrigin( GetAbsOrigin() ); - } - - // ragdolls will be removed on round restart automatically - m_hRagdoll = pRagdoll; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CHL2MP_Player::FlashlightIsOn( void ) -{ - return IsEffectActive( EF_DIMLIGHT ); -} - -extern ConVar flashlight; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHL2MP_Player::FlashlightTurnOn( void ) -{ - if( flashlight.GetInt() > 0 && IsAlive() ) - { - AddEffects( EF_DIMLIGHT ); - EmitSound( "HL2Player.FlashlightOn" ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CHL2MP_Player::FlashlightTurnOff( void ) -{ - RemoveEffects( EF_DIMLIGHT ); - - if( IsAlive() ) - { - EmitSound( "HL2Player.FlashlightOff" ); - } -} - -void CHL2MP_Player::Weapon_Drop( CBaseCombatWeapon *pWeapon, const Vector *pvecTarget, const Vector *pVelocity ) -{ - //Drop a grenade if it's primed. - if ( GetActiveWeapon() ) - { - CBaseCombatWeapon *pGrenade = Weapon_OwnsThisType("weapon_frag"); - - if ( GetActiveWeapon() == pGrenade ) - { - if ( ( m_nButtons & IN_ATTACK ) || (m_nButtons & IN_ATTACK2) ) - { - DropPrimedFragGrenade( this, pGrenade ); - return; - } - } - } - - BaseClass::Weapon_Drop( pWeapon, pvecTarget, pVelocity ); -} - - -void CHL2MP_Player::DetonateTripmines( void ) -{ - CBaseEntity *pEntity = NULL; - - while ((pEntity = gEntList.FindEntityByClassname( pEntity, "npc_satchel" )) != NULL) - { - CSatchelCharge *pSatchel = dynamic_cast(pEntity); - if (pSatchel->m_bIsLive && pSatchel->GetThrower() == this ) - { - g_EventQueue.AddEvent( pSatchel, "Explode", 0.20, this, this ); - } - } - - // Play sound for pressing the detonator - EmitSound( "Weapon_SLAM.SatchelDetonate" ); -} - -void CHL2MP_Player::Event_Killed( const CTakeDamageInfo &info ) -{ - //update damage info with our accumulated physics force - CTakeDamageInfo subinfo = info; - subinfo.SetDamageForce( m_vecTotalBulletForce ); - - SetNumAnimOverlays( 0 ); - - // Note: since we're dead, it won't draw us on the client, but we don't set EF_NODRAW - // because we still want to transmit to the clients in our PVS. - CreateRagdollEntity(); - - DetonateTripmines(); - - BaseClass::Event_Killed( subinfo ); - - if ( info.GetDamageType() & DMG_DISSOLVE ) - { - if ( m_hRagdoll ) - { - m_hRagdoll->GetBaseAnimating()->Dissolve( NULL, gpGlobals->curtime, false, ENTITY_DISSOLVE_NORMAL ); - } - } - - CBaseEntity *pAttacker = info.GetAttacker(); - - if ( pAttacker ) - { - int iScoreToAdd = 1; - - if ( pAttacker == this ) - { - iScoreToAdd = -1; - } - - GetGlobalTeam( pAttacker->GetTeamNumber() )->AddScore( iScoreToAdd ); - } - - FlashlightTurnOff(); - - m_lifeState = LIFE_DEAD; - - RemoveEffects( EF_NODRAW ); // still draw player body - StopZooming(); -} - -int CHL2MP_Player::OnTakeDamage( const CTakeDamageInfo &inputInfo ) -{ - //return here if the player is in the respawn grace period vs. slams. - if ( gpGlobals->curtime < m_flSlamProtectTime && (inputInfo.GetDamageType() == DMG_BLAST ) ) - return 0; - - m_vecTotalBulletForce += inputInfo.GetDamageForce(); - - gamestats->Event_PlayerDamage( this, inputInfo ); - - return BaseClass::OnTakeDamage( inputInfo ); -} - -void CHL2MP_Player::DeathSound( const CTakeDamageInfo &info ) -{ - if ( m_hRagdoll && m_hRagdoll->GetBaseAnimating()->IsDissolving() ) - return; - - char szStepSound[128]; - - Q_snprintf( szStepSound, sizeof( szStepSound ), "%s.Die", GetPlayerModelSoundPrefix() ); - - const char *pModelName = STRING( GetModelName() ); - - CSoundParameters params; - if ( GetParametersForSound( szStepSound, params, pModelName ) == false ) - return; - - Vector vecOrigin = GetAbsOrigin(); - - CRecipientFilter filter; - filter.AddRecipientsByPAS( vecOrigin ); - - EmitSound_t ep; - ep.m_nChannel = params.channel; - ep.m_pSoundName = params.soundname; - ep.m_flVolume = params.volume; - ep.m_SoundLevel = params.soundlevel; - ep.m_nFlags = 0; - ep.m_nPitch = params.pitch; - ep.m_pOrigin = &vecOrigin; - - EmitSound( filter, entindex(), ep ); -} - -CBaseEntity* CHL2MP_Player::EntSelectSpawnPoint( void ) -{ - CBaseEntity *pSpot = NULL; - CBaseEntity *pLastSpawnPoint = g_pLastSpawn; - edict_t *player = edict(); - const char *pSpawnpointName = "info_player_deathmatch"; - - if ( HL2MPRules()->IsTeamplay() == true ) - { - if ( GetTeamNumber() == TEAM_COMBINE ) - { - pSpawnpointName = "info_player_combine"; - pLastSpawnPoint = g_pLastCombineSpawn; - } - else if ( GetTeamNumber() == TEAM_REBELS ) - { - pSpawnpointName = "info_player_rebel"; - pLastSpawnPoint = g_pLastRebelSpawn; - } - - if ( gEntList.FindEntityByClassname( NULL, pSpawnpointName ) == NULL ) - { - pSpawnpointName = "info_player_deathmatch"; - pLastSpawnPoint = g_pLastSpawn; - } - } - - pSpot = pLastSpawnPoint; - // Randomize the start spot - for ( int i = random->RandomInt(1,5); i > 0; i-- ) - pSpot = gEntList.FindEntityByClassname( pSpot, pSpawnpointName ); - if ( !pSpot ) // skip over the null point - pSpot = gEntList.FindEntityByClassname( pSpot, pSpawnpointName ); - - CBaseEntity *pFirstSpot = pSpot; - - do - { - if ( pSpot ) - { - // check if pSpot is valid - if ( g_pGameRules->IsSpawnPointValid( pSpot, this ) ) - { - if ( pSpot->GetLocalOrigin() == vec3_origin ) - { - pSpot = gEntList.FindEntityByClassname( pSpot, pSpawnpointName ); - continue; - } - - // if so, go to pSpot - goto ReturnSpot; - } - } - // increment pSpot - pSpot = gEntList.FindEntityByClassname( pSpot, pSpawnpointName ); - } while ( pSpot != pFirstSpot ); // loop if we're not back to the start - - // we haven't found a place to spawn yet, so kill any guy at the first spawn point and spawn there - if ( pSpot ) - { - CBaseEntity *ent = NULL; - for ( CEntitySphereQuery sphere( pSpot->GetAbsOrigin(), 128 ); (ent = sphere.GetCurrentEntity()) != NULL; sphere.NextEntity() ) - { - // if ent is a client, kill em (unless they are ourselves) - if ( ent->IsPlayer() && !(ent->edict() == player) ) - ent->TakeDamage( CTakeDamageInfo( GetContainingEntity(INDEXENT(0)), GetContainingEntity(INDEXENT(0)), 300, DMG_GENERIC ) ); - } - goto ReturnSpot; - } - - if ( !pSpot ) - { - pSpot = gEntList.FindEntityByClassname( pSpot, "info_player_start" ); - - if ( pSpot ) - goto ReturnSpot; - } - -ReturnSpot: - - if ( HL2MPRules()->IsTeamplay() == true ) - { - if ( GetTeamNumber() == TEAM_COMBINE ) - { - g_pLastCombineSpawn = pSpot; - } - else if ( GetTeamNumber() == TEAM_REBELS ) - { - g_pLastRebelSpawn = pSpot; - } - } - - g_pLastSpawn = pSpot; - - m_flSlamProtectTime = gpGlobals->curtime + 0.5; - - return pSpot; -} - - -CON_COMMAND( timeleft, "prints the time remaining in the match" ) -{ - CHL2MP_Player *pPlayer = ToHL2MPPlayer( UTIL_GetCommandClient() ); - - int iTimeRemaining = (int)HL2MPRules()->GetMapRemainingTime(); - - if ( iTimeRemaining == 0 ) - { - if ( pPlayer ) - { - ClientPrint( pPlayer, HUD_PRINTTALK, "This game has no timelimit." ); - } - else - { - Msg( "* No Time Limit *\n" ); - } - } - else - { - int iMinutes, iSeconds; - iMinutes = iTimeRemaining / 60; - iSeconds = iTimeRemaining % 60; - - char minutes[8]; - char seconds[8]; - - Q_snprintf( minutes, sizeof(minutes), "%d", iMinutes ); - Q_snprintf( seconds, sizeof(seconds), "%2.2d", iSeconds ); - - if ( pPlayer ) - { - ClientPrint( pPlayer, HUD_PRINTTALK, "Time left in map: %s1:%s2", minutes, seconds ); - } - else - { - Msg( "Time Remaining: %s:%s\n", minutes, seconds ); - } - } -} - - -void CHL2MP_Player::Reset() -{ - ResetDeathCount(); - ResetFragCount(); -} - -bool CHL2MP_Player::IsReady() -{ - return m_bReady; -} - -void CHL2MP_Player::SetReady( bool bReady ) -{ - m_bReady = bReady; -} - -void CHL2MP_Player::CheckChatText( char *p, int bufsize ) -{ - //Look for escape sequences and replace - - char *buf = new char[bufsize]; - int pos = 0; - - // Parse say text for escape sequences - for ( char *pSrc = p; pSrc != NULL && *pSrc != 0 && pos < bufsize-1; pSrc++ ) - { - // copy each char across - buf[pos] = *pSrc; - pos++; - } - - buf[pos] = '\0'; - - // copy buf back into p - Q_strncpy( p, buf, bufsize ); - - delete[] buf; - - const char *pReadyCheck = p; - - HL2MPRules()->CheckChatForReadySignal( this, pReadyCheck ); -} - -void CHL2MP_Player::State_Transition( HL2MPPlayerState newState ) -{ - State_Leave(); - State_Enter( newState ); -} - - -void CHL2MP_Player::State_Enter( HL2MPPlayerState newState ) -{ - m_iPlayerState = newState; - m_pCurStateInfo = State_LookupInfo( newState ); - - // Initialize the new state. - if ( m_pCurStateInfo && m_pCurStateInfo->pfnEnterState ) - (this->*m_pCurStateInfo->pfnEnterState)(); -} - - -void CHL2MP_Player::State_Leave() -{ - if ( m_pCurStateInfo && m_pCurStateInfo->pfnLeaveState ) - { - (this->*m_pCurStateInfo->pfnLeaveState)(); - } -} - - -void CHL2MP_Player::State_PreThink() -{ - if ( m_pCurStateInfo && m_pCurStateInfo->pfnPreThink ) - { - (this->*m_pCurStateInfo->pfnPreThink)(); - } -} - - -CHL2MPPlayerStateInfo *CHL2MP_Player::State_LookupInfo( HL2MPPlayerState state ) -{ - // This table MUST match the - static CHL2MPPlayerStateInfo playerStateInfos[] = - { - { STATE_ACTIVE, "STATE_ACTIVE", &CHL2MP_Player::State_Enter_ACTIVE, NULL, &CHL2MP_Player::State_PreThink_ACTIVE }, - { STATE_OBSERVER_MODE, "STATE_OBSERVER_MODE", &CHL2MP_Player::State_Enter_OBSERVER_MODE, NULL, &CHL2MP_Player::State_PreThink_OBSERVER_MODE } - }; - - for ( size_t i=0; i < ARRAYSIZE( playerStateInfos ); i++ ) - { - if ( playerStateInfos[i].m_iPlayerState == state ) - return &playerStateInfos[i]; - } - - return NULL; -} - -bool CHL2MP_Player::StartObserverMode(int mode) -{ - //we only want to go into observer mode if the player asked to, not on a death timeout - if ( m_bEnterObserver == true ) - { - VPhysicsDestroyObject(); - return BaseClass::StartObserverMode( mode ); - } - return false; -} - -void CHL2MP_Player::StopObserverMode() -{ - m_bEnterObserver = false; - BaseClass::StopObserverMode(); -} - -void CHL2MP_Player::State_Enter_OBSERVER_MODE() -{ - int observerMode = m_iObserverLastMode; - if ( IsNetClient() ) - { - const char *pIdealMode = engine->GetClientConVarValue( engine->IndexOfEdict( edict() ), "cl_spec_mode" ); - if ( pIdealMode ) - { - observerMode = atoi( pIdealMode ); - if ( observerMode <= OBS_MODE_FIXED || observerMode > OBS_MODE_ROAMING ) - { - observerMode = m_iObserverLastMode; - } - } - } - m_bEnterObserver = true; - StartObserverMode( observerMode ); -} - -void CHL2MP_Player::State_PreThink_OBSERVER_MODE() -{ - // Make sure nobody has changed any of our state. - // Assert( GetMoveType() == MOVETYPE_FLY ); - Assert( m_takedamage == DAMAGE_NO ); - Assert( IsSolidFlagSet( FSOLID_NOT_SOLID ) ); - // Assert( IsEffectActive( EF_NODRAW ) ); - - // Must be dead. - Assert( m_lifeState == LIFE_DEAD ); - Assert( pl.deadflag ); -} - - -void CHL2MP_Player::State_Enter_ACTIVE() -{ - SetMoveType( MOVETYPE_WALK ); - - // md 8/15/07 - They'll get set back to solid when they actually respawn. If we set them solid now and mp_forcerespawn - // is false, then they'll be spectating but blocking live players from moving. - // RemoveSolidFlags( FSOLID_NOT_SOLID ); - - m_Local.m_iHideHUD = 0; -} - - -void CHL2MP_Player::State_PreThink_ACTIVE() -{ - //we don't really need to do anything here. - //This state_prethink structure came over from CS:S and was doing an assert check that fails the way hl2dm handles death -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CHL2MP_Player::CanHearAndReadChatFrom( CBasePlayer *pPlayer ) -{ - // can always hear the console unless we're ignoring all chat - if ( !pPlayer ) - return false; - - return true; -} diff --git a/game/server/hl2mp/hl2mp_player.h b/game/server/hl2mp/hl2mp_player.h deleted file mode 100644 index 45fa81633..000000000 --- a/game/server/hl2mp/hl2mp_player.h +++ /dev/null @@ -1,176 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef HL2MP_PLAYER_H -#define HL2MP_PLAYER_H -#pragma once - -class CHL2MP_Player; - -#include "basemultiplayerplayer.h" -#include "hl2_playerlocaldata.h" -#include "hl2_player.h" -#include "simtimer.h" -#include "soundenvelope.h" -#include "hl2mp_player_shared.h" -#include "hl2mp_gamerules.h" -#include "utldict.h" - -//============================================================================= -// >> HL2MP_Player -//============================================================================= -class CHL2MPPlayerStateInfo -{ -public: - HL2MPPlayerState m_iPlayerState; - const char *m_pStateName; - - void (CHL2MP_Player::*pfnEnterState)(); // Init and deinit the state. - void (CHL2MP_Player::*pfnLeaveState)(); - - void (CHL2MP_Player::*pfnPreThink)(); // Do a PreThink() in this state. -}; - -class CHL2MP_Player : public CHL2_Player -{ -public: - DECLARE_CLASS( CHL2MP_Player, CHL2_Player ); - - CHL2MP_Player(); - ~CHL2MP_Player( void ); - - static CHL2MP_Player *CreatePlayer( const char *className, edict_t *ed ) - { - CHL2MP_Player::s_PlayerEdict = ed; - return (CHL2MP_Player*)CreateEntityByName( className ); - } - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - virtual void Precache( void ); - virtual void Spawn( void ); - virtual void PostThink( void ); - virtual void PreThink( void ); - virtual void PlayerDeathThink( void ); - virtual void SetAnimation( PLAYER_ANIM playerAnim ); - virtual bool HandleCommand_JoinTeam( int team ); - virtual bool ClientCommand( const CCommand &args ); - virtual void CreateViewModel( int viewmodelindex = 0 ); - virtual bool BecomeRagdollOnClient( const Vector &force ); - virtual void Event_Killed( const CTakeDamageInfo &info ); - virtual int OnTakeDamage( const CTakeDamageInfo &inputInfo ); - virtual bool WantsLagCompensationOnEntity( const CBasePlayer *pPlayer, const CUserCmd *pCmd, const CBitVec *pEntityTransmitBits ) const; - virtual void FireBullets ( const FireBulletsInfo_t &info ); - virtual bool Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmodelindex = 0); - virtual bool BumpWeapon( CBaseCombatWeapon *pWeapon ); - virtual void ChangeTeam( int iTeam ); - virtual void PickupObject ( CBaseEntity *pObject, bool bLimitMassAndSize ); - virtual void PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, float fvol, bool force ); - virtual void Weapon_Drop( CBaseCombatWeapon *pWeapon, const Vector *pvecTarget = NULL, const Vector *pVelocity = NULL ); - virtual void UpdateOnRemove( void ); - virtual void DeathSound( const CTakeDamageInfo &info ); - virtual CBaseEntity* EntSelectSpawnPoint( void ); - - int FlashlightIsOn( void ); - void FlashlightTurnOn( void ); - void FlashlightTurnOff( void ); - void PrecacheFootStepSounds( void ); - bool ValidatePlayerModel( const char *pModel ); - - QAngle GetAnimEyeAngles( void ) { return m_angEyeAngles.Get(); } - - Vector GetAttackSpread( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget = NULL ); - - void CheatImpulseCommands( int iImpulse ); - void CreateRagdollEntity( void ); - void GiveAllItems( void ); - void GiveDefaultItems( void ); - - void NoteWeaponFired( void ); - - void ResetAnimation( void ); - void SetPlayerModel( void ); - void SetPlayerTeamModel( void ); - Activity TranslateTeamActivity( Activity ActToTranslate ); - - float GetNextModelChangeTime( void ) { return m_flNextModelChangeTime; } - float GetNextTeamChangeTime( void ) { return m_flNextTeamChangeTime; } - void PickDefaultSpawnTeam( void ); - void SetupPlayerSoundsByModel( const char *pModelName ); - const char *GetPlayerModelSoundPrefix( void ); - int GetPlayerModelType( void ) { return m_iPlayerSoundType; } - - void DetonateTripmines( void ); - - void Reset(); - - bool IsReady(); - void SetReady( bool bReady ); - - void CheckChatText( char *p, int bufsize ); - - void State_Transition( HL2MPPlayerState newState ); - void State_Enter( HL2MPPlayerState newState ); - void State_Leave(); - void State_PreThink(); - CHL2MPPlayerStateInfo *State_LookupInfo( HL2MPPlayerState state ); - - void State_Enter_ACTIVE(); - void State_PreThink_ACTIVE(); - void State_Enter_OBSERVER_MODE(); - void State_PreThink_OBSERVER_MODE(); - - - virtual bool StartObserverMode( int mode ); - virtual void StopObserverMode( void ); - - - Vector m_vecTotalBulletForce; //Accumulator for bullet force in a single frame - - // Tracks our ragdoll entity. - CNetworkHandle( CBaseEntity, m_hRagdoll ); // networked entity handle - - virtual bool CanHearAndReadChatFrom( CBasePlayer *pPlayer ); - - -private: - - CNetworkQAngle( m_angEyeAngles ); - CPlayerAnimState m_PlayerAnimState; - - int m_iLastWeaponFireUsercmd; - int m_iModelType; - CNetworkVar( int, m_iSpawnInterpCounter ); - CNetworkVar( int, m_iPlayerSoundType ); - - float m_flNextModelChangeTime; - float m_flNextTeamChangeTime; - - float m_flSlamProtectTime; - - HL2MPPlayerState m_iPlayerState; - CHL2MPPlayerStateInfo *m_pCurStateInfo; - - bool ShouldRunRateLimitedCommand( const CCommand &args ); - - // This lets us rate limit the commands the players can execute so they don't overflow things like reliable buffers. - CUtlDict m_RateLimitLastCommandTimes; - - bool m_bEnterObserver; - bool m_bReady; -}; - -inline CHL2MP_Player *ToHL2MPPlayer( CBaseEntity *pEntity ) -{ - if ( !pEntity || !pEntity->IsPlayer() ) - return NULL; - - return dynamic_cast( pEntity ); -} - -#endif //HL2MP_PLAYER_H diff --git a/game/server/hl2mp/te_hl2mp_shotgun_shot.cpp b/game/server/hl2mp/te_hl2mp_shotgun_shot.cpp deleted file mode 100644 index 9097a8686..000000000 --- a/game/server/hl2mp/te_hl2mp_shotgun_shot.cpp +++ /dev/null @@ -1,104 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" - - -#define NUM_BULLET_SEED_BITS 8 - - -//----------------------------------------------------------------------------- -// Purpose: Display's a blood sprite -//----------------------------------------------------------------------------- -class CTEHL2MPFireBullets : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEHL2MPFireBullets, CBaseTempEntity ); - DECLARE_SERVERCLASS(); - - CTEHL2MPFireBullets( const char *name ); - virtual ~CTEHL2MPFireBullets( void ); - -public: - CNetworkVar( int, m_iPlayer ); - CNetworkVector( m_vecOrigin ); - CNetworkVector( m_vecDir ); - CNetworkVar( int, m_iAmmoID ); - CNetworkVar( int, m_iSeed ); - CNetworkVar( int, m_iShots ); - CNetworkVar( float, m_flSpread ); - CNetworkVar( bool, m_bDoImpacts ); - CNetworkVar( bool, m_bDoTracers ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEHL2MPFireBullets::CTEHL2MPFireBullets( const char *name ) : - CBaseTempEntity( name ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEHL2MPFireBullets::~CTEHL2MPFireBullets( void ) -{ -} - -IMPLEMENT_SERVERCLASS_ST_NOBASE(CTEHL2MPFireBullets, DT_TEHL2MPFireBullets) - SendPropVector( SENDINFO(m_vecOrigin), -1, SPROP_COORD ), - SendPropVector( SENDINFO(m_vecDir), -1 ), - SendPropInt( SENDINFO( m_iAmmoID ), 5, SPROP_UNSIGNED ), - SendPropInt( SENDINFO( m_iSeed ), NUM_BULLET_SEED_BITS, SPROP_UNSIGNED ), - SendPropInt( SENDINFO( m_iShots ), 5, SPROP_UNSIGNED ), - SendPropInt( SENDINFO( m_iPlayer ), 6, SPROP_UNSIGNED ), // max 64 players, see MAX_PLAYERS - SendPropFloat( SENDINFO( m_flSpread ), 10, 0, 0, 1 ), - SendPropBool( SENDINFO( m_bDoImpacts ) ), - SendPropBool( SENDINFO( m_bDoTracers ) ), -END_SEND_TABLE() - - -// Singleton -static CTEHL2MPFireBullets g_TEHL2MPFireBullets( "Shotgun Shot" ); - - -void TE_HL2MPFireBullets( - int iPlayerIndex, - const Vector &vOrigin, - const Vector &vDir, - int iAmmoID, - int iSeed, - int iShots, - float flSpread, - bool bDoTracers, - bool bDoImpacts ) -{ - CPASFilter filter( vOrigin ); - filter.UsePredictionRules(); - - g_TEHL2MPFireBullets.m_iPlayer = iPlayerIndex; - g_TEHL2MPFireBullets.m_vecOrigin = vOrigin; - g_TEHL2MPFireBullets.m_vecDir = vDir; - g_TEHL2MPFireBullets.m_iSeed = iSeed; - g_TEHL2MPFireBullets.m_iShots = iShots; - g_TEHL2MPFireBullets.m_flSpread = flSpread; - g_TEHL2MPFireBullets.m_iAmmoID = iAmmoID; - g_TEHL2MPFireBullets.m_bDoTracers = bDoTracers; - g_TEHL2MPFireBullets.m_bDoImpacts = bDoImpacts; - - Assert( iSeed < (1 << NUM_BULLET_SEED_BITS) ); - - g_TEHL2MPFireBullets.Create( filter, 0 ); -} diff --git a/game/server/hl2mp/te_hl2mp_shotgun_shot.h b/game/server/hl2mp/te_hl2mp_shotgun_shot.h deleted file mode 100644 index 1bd172ba3..000000000 --- a/game/server/hl2mp/te_hl2mp_shotgun_shot.h +++ /dev/null @@ -1,26 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef TE_HL2MP_SHOTGUN_SHOT_H -#define TE_HL2MP_SHOTGUN_SHOT_H -#ifdef _WIN32 -#pragma once -#endif - - -void TE_HL2MPFireBullets( - int iPlayerIndex, - const Vector &vOrigin, - const Vector &vDir, - int iAmmoID, - int iSeed, - int iShots, - float flSpread, - bool bDoTracers, - bool bDoImpacts ); - - -#endif // TE_HL2MP_SHOTGUN_SHOT_H diff --git a/game/server/hltvdirector.cpp b/game/server/hltvdirector.cpp deleted file mode 100644 index 9387aa2bf..000000000 --- a/game/server/hltvdirector.cpp +++ /dev/null @@ -1,1184 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -// hltvdirector.cpp: implementation of the CHLTVDirector class. -// -////////////////////////////////////////////////////////////////////// - -#include "cbase.h" -#include "hltvdirector.h" -#include "KeyValues.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - - -static ConVar tv_delay( "tv_delay", "30", 0, "SourceTV broadcast delay in seconds", true, 0, true, HLTV_MAX_DELAY ); -static ConVar tv_allow_static_shots( "tv_allow_static_shots", "1", 0, "Auto director uses fixed level cameras for shots" ); -static ConVar tv_allow_camera_man( "tv_allow_camera_man", "1", 0, "Auto director allows spectators to become camera man" ); - -static bool GameEventLessFunc( CGameEvent const &e1, CGameEvent const &e2 ) -{ - return e1.m_Tick < e2.m_Tick; -} - -#define RANDOM_MAX_ELEMENTS 256 -static int s_RndOrder[RANDOM_MAX_ELEMENTS]; -static void InitRandomOrder(int nFields) -{ - if ( nFields > RANDOM_MAX_ELEMENTS ) - { - Assert( nFields > RANDOM_MAX_ELEMENTS ); - nFields = RANDOM_MAX_ELEMENTS; - } - - for ( int i=0; i= 0 ); - - return a*a; // vectors are facing opposite direction -} - -#if !defined( CSTRIKE_DLL ) && !defined( DOD_DLL ) && !defined( TF_DLL )// add your mod here if you use your own director - -static CHLTVDirector s_HLTVDirector; // singleton - -EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CHLTVDirector, IHLTVDirector, INTERFACEVERSION_HLTVDIRECTOR, s_HLTVDirector ); - -CHLTVDirector* HLTVDirector() -{ - return &s_HLTVDirector; -} - -IGameSystem* HLTVDirectorSystem() -{ - return &s_HLTVDirector; -} - -#endif // MODs - - - -CHLTVDirector::CHLTVDirector() -{ - m_iPVSEntity = 0; - m_fDelay = 30.0; - m_iLastPlayer = 1; - m_pHLTVServer = NULL; - m_pHLTVClient = NULL; - m_iCameraMan = 0; - m_nNumFixedCameras = 0; - m_EventHistory.SetLessFunc( GameEventLessFunc ); - m_nNextAnalyzeTick = 0; - m_iCameraManIndex = 0; -} - -CHLTVDirector::~CHLTVDirector() -{ - -} - -bool CHLTVDirector::Init() -{ - return gameeventmanager->LoadEventsFromFile( "resource/hltvevents.res" ) > 0; -} - -void CHLTVDirector::Shutdown() -{ - RemoveEventsFromHistory(-1); // all -} - -void CHLTVDirector::FireGameEvent( IGameEvent * event ) -{ - if ( !m_pHLTVServer ) - return; // don't do anything - - CGameEvent gameevent; - - gameevent.m_Event = gameeventmanager->DuplicateEvent( event ); - gameevent.m_Priority = event->GetInt( "priority", -1 ); // priorities are leveled between 0..10, -1 means ignore - gameevent.m_Tick = gpGlobals->tickcount; - - m_EventHistory.Insert( gameevent ); -} - -IHLTVServer* CHLTVDirector::GetHLTVServer( void ) -{ - return m_pHLTVServer; -} - -void CHLTVDirector::SetHLTVServer( IHLTVServer *hltv ) -{ - RemoveEventsFromHistory(-1); // all - - if ( hltv ) - { - m_pHLTVClient = UTIL_PlayerByIndex( hltv->GetHLTVSlot() + 1 ); - - if ( m_pHLTVClient && m_pHLTVClient->IsHLTV() ) - { - m_pHLTVServer = hltv; - } - else - { - m_pHLTVServer = NULL; - Error( "Couldn't find HLTV client player." ); - } - - // register for events the director needs to know - ListenForGameEvent( "player_hurt" ); - ListenForGameEvent( "player_death" ); - ListenForGameEvent( "round_end" ); - ListenForGameEvent( "round_start" ); - ListenForGameEvent( "hltv_cameraman" ); - ListenForGameEvent( "hltv_rank_entity" ); - ListenForGameEvent( "hltv_rank_camera" ); - } - else - { - // deactivate HLTV director - m_pHLTVServer = NULL; - } -} - -bool CHLTVDirector::IsActive( void ) -{ - return (m_pHLTVServer != NULL ); -} - -float CHLTVDirector::GetDelay( void ) -{ - return m_fDelay; -} - -int CHLTVDirector::GetDirectorTick( void ) -{ - // just simple delay it - return m_nBroadcastTick; -} - -int CHLTVDirector::GetPVSEntity( void ) -{ - return m_iPVSEntity; -} - -Vector CHLTVDirector::GetPVSOrigin( void ) -{ - return m_vPVSOrigin; -} - -void CHLTVDirector::UpdateSettings() -{ - // set delay - m_fDelay = tv_delay.GetFloat(); - - int newBroadcastTick = gpGlobals->tickcount; - - if ( m_fDelay < HLTV_MIN_DIRECTOR_DELAY ) - { - // instant broadcast, no delay - m_fDelay = 0.0; - } - else - { - // broadcast time is current time - delay time - newBroadcastTick -= TIME_TO_TICKS( m_fDelay ); - } - - if( (m_nBroadcastTick == 0) && (newBroadcastTick > 0) ) - { - // we start broadcasting right now, reset NextShotTimer - m_nNextShotTick = 0; - } - - // check if camera man is still valid - if ( m_iCameraManIndex > 0 ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( m_iCameraManIndex ); - if ( !pPlayer || pPlayer->GetTeamNumber() != TEAM_SPECTATOR ) - { - SetCameraMan( 0 ); - } - } - - m_nBroadcastTick = MAX( 0, newBroadcastTick ); -} - -const char** CHLTVDirector::GetModEvents() -{ - static const char *s_modevents[] = - { - "hltv_status", - "hltv_chat", - "player_connect", - "player_disconnect", - "player_team", - "player_info", - "server_cvar", - "player_death", - "player_chat", - "round_start", - "round_end", - NULL - }; - - return s_modevents; -} - - -void CHLTVDirector::BuildCameraList( void ) -{ - m_nNumFixedCameras = 0; - memset( m_pFixedCameras, 0, sizeof ( m_pFixedCameras ) ); - - CBaseEntity *pCamera = gEntList.FindEntityByClassname( NULL, GetFixedCameraEntityName() ); - - while ( pCamera && m_nNumFixedCameras < MAX_NUM_CAMERAS) - { - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, STRING(pCamera->m_target) ); - - if ( pTarget ) - { - // look at target if any given - QAngle angles; - VectorAngles( pTarget->GetAbsOrigin() - pCamera->GetAbsOrigin(), angles ); - pCamera->SetAbsAngles( angles ); - } - - m_pFixedCameras[m_nNumFixedCameras] = pCamera; - - m_nNumFixedCameras++; - pCamera = gEntList.FindEntityByClassname( pCamera, GetFixedCameraEntityName() ); - } -} - -// this is called with every new map -void CHLTVDirector::LevelInitPostEntity( void ) -{ - BuildCameraList(); - - m_vPVSOrigin.Init(); - m_iPVSEntity = 0; - m_nNextShotTick = 0; - m_nNextAnalyzeTick = 0; - m_iCameraManIndex = 0; - - RemoveEventsFromHistory(-1); // all - - // DevMsg("HLTV Director: found %i fixed cameras.\n", m_nNumFixedCameras ); -} - -void CHLTVDirector::FrameUpdatePostEntityThink( void ) -{ - if ( !m_pHLTVServer ) - return; // don't do anything - - // This function is called each tick - UpdateSettings(); // update settings from cvars - - if ( (m_nNextAnalyzeTick < gpGlobals->tickcount) && - (m_fDelay >= HLTV_MIN_DIRECTOR_DELAY) ) - { - m_nNextAnalyzeTick = gpGlobals->tickcount + TIME_TO_TICKS( 0.5f ); - - AnalyzePlayers(); - - AnalyzeCameras(); - } - - if ( m_nBroadcastTick <= 0 ) - { - // game start is still in delay loop - StartDelayMessage(); - } - else if ( m_nNextShotTick <= m_nBroadcastTick ) - { - // game is being broadcasted, generate camera shots - StartNewShot(); - } -} - -void CHLTVDirector::StartDelayMessage() -{ - if ( m_nNextShotTick > gpGlobals->tickcount ) - return; - - // check the next 8 seconds for interrupts/important events - m_nNextShotTick = gpGlobals->tickcount + TIME_TO_TICKS( DEF_SHOT_LENGTH ); - - // game hasn't started yet, we are still in the broadcast delay hole - IGameEvent *msg = gameeventmanager->CreateEvent( "hltv_message", true ); - - if ( msg ) - { - msg->SetString("text", "Please wait for broadcast to start ..." ); - - // send spectators the HLTV director command as a game event - m_pHLTVServer->BroadcastEvent( msg ); - gameeventmanager->FreeEvent( msg ); - } - - StartBestFixedCameraShot( true ); -} - -void CHLTVDirector::StartBestPlayerCameraShot() -{ - float flPlayerRanking[MAX_PLAYERS]; - - memset( flPlayerRanking, 0, sizeof(flPlayerRanking) ); - - int firstIndex = FindFirstEvent( m_nBroadcastTick ); - - int index = firstIndex; - - float flBestRank = -1.0f; - int iBestCamera = -1; - int iBestTarget = -1; - - // sum all ranking values for the cameras - - while( index != m_EventHistory.InvalidIndex() ) - { - CGameEvent &dc = m_EventHistory[index]; - - if ( dc.m_Tick >= m_nNextShotTick ) - break; - - // search for camera ranking events - if ( Q_strcmp( dc.m_Event->GetName(), "hltv_rank_entity") == 0 ) - { - int index = dc.m_Event->GetInt("index"); - - if ( index < MAX_PLAYERS ) - { - flPlayerRanking[index] += dc.m_Event->GetFloat("rank" ); - - // find best camera - if ( flPlayerRanking[index] > flBestRank ) - { - iBestCamera = index; - flBestRank = flPlayerRanking[index]; - iBestTarget = dc.m_Event->GetInt("target"); - } - } - } - - index = m_EventHistory.NextInorder( index ); - } - - if ( iBestCamera != -1 ) - { - // view over shoulder, randomly left or right - StartChaseCameraShot( iBestCamera, iBestTarget, 112, 20, (RandomFloat()>0.5)?20:-20, false ); - } - else - { - StartBestFixedCameraShot( true ); - } -} - -void CHLTVDirector::StartFixedCameraShot(int iCamera, int iTarget) -{ - CBaseEntity *pCamera = m_pFixedCameras[iCamera]; - - - Vector vCamPos = pCamera->GetAbsOrigin(); - QAngle aViewAngle = pCamera->GetAbsAngles(); - - m_iPVSEntity = 0; // don't use camera entity, since it may not been transmitted - m_vPVSOrigin = vCamPos; - - IGameEvent *shot = gameeventmanager->CreateEvent( "hltv_fixed", true ); - - if ( shot ) - { - shot->SetInt("posx", (int)vCamPos.x ); - shot->SetInt("posy", (int)vCamPos.y ); - shot->SetInt("posz", (int)vCamPos.z ); - shot->SetInt("theta", (int)aViewAngle.x ); - shot->SetInt("phi", (int)aViewAngle.y ); - shot->SetInt("target", iTarget ); - shot->SetFloat("fov", RandomFloat(50,110) ); - - // send spectators the HLTV director command as a game event - m_pHLTVServer->BroadcastEvent( shot ); - gameeventmanager->FreeEvent( shot ); - } -} - -void CHLTVDirector::StartChaseCameraShot(int iTarget1, int iTarget2, int distance, int phi, int theta, bool bInEye) -{ - IGameEvent *shot = gameeventmanager->CreateEvent( "hltv_chase", true ); - - if ( !shot ) - return; - - shot->SetInt("target1", iTarget1 ); - shot->SetInt("target2", iTarget2 ); - shot->SetInt("distance", distance ); - shot->SetInt("phi", phi ); // hi/low - shot->SetInt( "theta", theta ); // left/right - shot->SetInt( "ineye", bInEye?1:0 ); - - m_iPVSEntity = iTarget1; - - // send spectators the HLTV director command as a game event - m_pHLTVServer->BroadcastEvent( shot ); - gameeventmanager->FreeEvent( shot ); -} - -void CHLTVDirector::StartBestFixedCameraShot( bool bForce ) -{ - float flCameraRanking[MAX_NUM_CAMERAS]; - - if ( m_nNumFixedCameras <= 0 ) - return; - - memset( flCameraRanking, 0, sizeof(flCameraRanking) ); - - int firstIndex = FindFirstEvent( m_nBroadcastTick ); - - int index = firstIndex; - - float flBestRank = -1.0f; - int iBestCamera = -1; - int iBestTarget = -1; - - // sum all ranking values for the cameras - - while( index != m_EventHistory.InvalidIndex() ) - { - CGameEvent &dc = m_EventHistory[index]; - - if ( dc.m_Tick >= m_nNextShotTick ) - break; - - // search for camera ranking events - if ( Q_strcmp( dc.m_Event->GetName(), "hltv_rank_camera") == 0 ) - { - int index = dc.m_Event->GetInt("index"); - flCameraRanking[index] += dc.m_Event->GetFloat("rank" ); - - // find best camera - if ( flCameraRanking[index] > flBestRank ) - { - iBestCamera = index; - flBestRank = flCameraRanking[index]; - iBestTarget = dc.m_Event->GetInt("target"); - } - } - - index = m_EventHistory.NextInorder( index ); - } - - if ( !bForce && flBestRank == 0 ) - { - // if we are not forcing a fixed camera shot, switch to player chase came - // if no camera shows any players - StartBestPlayerCameraShot(); - } - else if ( iBestCamera != -1 ) - { - StartFixedCameraShot( iBestCamera, iBestTarget ); - } -} - -void CHLTVDirector::StartRandomShot() -{ - int toTick = m_nBroadcastTick + TIME_TO_TICKS ( DEF_SHOT_LENGTH ); - m_nNextShotTick = MIN( m_nNextShotTick, toTick ); - - if ( RandomFloat(0,1) < 0.25 && tv_allow_static_shots.GetBool() ) - { - // create a static shot from a level camera - StartBestFixedCameraShot( false ); - } - else - { - // follow a player - StartBestPlayerCameraShot(); - } -} - -void CHLTVDirector::CreateShotFromEvent( CGameEvent *event ) -{ - // show event at least for 2 more seconds after it occured - const char *name = event->m_Event->GetName(); - - bool bPlayerHurt = Q_strcmp( "player_hurt", name ) == 0; - bool bPlayerKilled = Q_strcmp( "player_death", name ) == 0; - bool bRoundStart = Q_strcmp( "round_start", name ) == 0; - bool bRoundEnd = Q_strcmp( "round_end", name ) == 0; - - if ( bPlayerHurt || bPlayerKilled ) - { - CBaseEntity *victim = UTIL_PlayerByUserId( event->m_Event->GetInt("userid") ); - CBaseEntity *attacker = UTIL_PlayerByUserId( event->m_Event->GetInt("attacker") ); - - if ( !victim ) - return; - - if ( attacker == victim || attacker == NULL ) - { - // player killed self or by WORLD - StartChaseCameraShot( victim->entindex(), 0, 96, 20, 0, false ); - } - else // attacker != NULL - { - // check if we would show it from ineye view - bool bInEye = (bPlayerKilled && RandomFloat(0,1) > 0.33) || (bPlayerHurt && RandomFloat(0,1) > 0.66); - - // if we show ineye view, show it more likely from killer - if ( RandomFloat(0,1) > (bInEye?0.3f:0.7f) ) - { - swap( attacker, victim ); - } - - // hurting a victim is shown as chase more often - // view from behind over head - // lower view point, dramatic - // view over shoulder, randomly left or right - StartChaseCameraShot( victim->entindex(), attacker->entindex(), 96, -20, (RandomFloat()>0.5)?30:-30, bInEye ); - } - - // shot 2 seconds after death/hurt - m_nNextShotTick = MIN( m_nNextShotTick, (event->m_Tick+TIME_TO_TICKS(2.0)) ); - } - else if ( bRoundStart || bRoundEnd ) - { - StartBestFixedCameraShot( false ); - } - else - { - DevMsg( "No known TV shot for event %s\n", name ); - } -} - -void CHLTVDirector::CheckHistory() -{ - int index = m_EventHistory.FirstInorder(); - int lastTick = -1; - - while ( index != m_EventHistory.InvalidIndex() ) - { - CGameEvent &dc = m_EventHistory[index]; - - Assert( lastTick <= dc.m_Tick ); - lastTick = dc.m_Tick; - - index = m_EventHistory.NextInorder( index ); - } -} - -void CHLTVDirector::RemoveEventsFromHistory(int tick) -{ - int index = m_EventHistory.FirstInorder(); - - while ( index != m_EventHistory.InvalidIndex() ) - { - CGameEvent &dc = m_EventHistory[index]; - - if ( (dc.m_Tick < tick) || (tick == -1) ) - { - gameeventmanager->FreeEvent( dc.m_Event ); - dc.m_Event = NULL; - m_EventHistory.RemoveAt( index ); - index = m_EventHistory.FirstInorder(); // start again - } - else - { - index = m_EventHistory.NextInorder( index ); - } - } - -#ifdef _DEBUG - CheckHistory(); -#endif -} - -int CHLTVDirector::FindFirstEvent( int tick ) -{ - // TODO cache last queried ticks - - int index = m_EventHistory.FirstInorder(); - - if ( index == m_EventHistory.InvalidIndex() ) - return index; // no commands in list - - CGameEvent *event = &m_EventHistory[index]; - - while ( event->m_Tick < tick ) - { - index = m_EventHistory.NextInorder( index ); - - if ( index == m_EventHistory.InvalidIndex() ) - break; - - event = &m_EventHistory[index]; - } - - return index; -} - -bool CHLTVDirector::SetCameraMan( int iPlayerIndex ) -{ - if ( !tv_allow_camera_man.GetBool() ) - return false; - - if ( m_iCameraManIndex == iPlayerIndex ) - return true; - - // check if somebody else is already the camera man - if ( m_iCameraManIndex != 0 && iPlayerIndex != 0 ) - return false; - - CBasePlayer *pPlayer = NULL; - - if ( iPlayerIndex > 0 ) - { - pPlayer = UTIL_PlayerByIndex( iPlayerIndex ); - if ( !pPlayer || pPlayer->GetTeamNumber() != TEAM_SPECTATOR ) - return false; - } - - m_iCameraManIndex = iPlayerIndex; - - // create event for director event history - IGameEvent *event = gameeventmanager->CreateEvent( "hltv_cameraman" ); - if ( event ) - { - event->SetInt("index", iPlayerIndex ); - gameeventmanager->FireEvent( event ); - } - - CRecipientFilter filter; - - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - - if ( pPlayer && pPlayer->GetTeamNumber() == TEAM_SPECTATOR && !pPlayer->IsFakeClient() ) - { - filter.AddRecipient( pPlayer ); - } - } - - filter.MakeReliable(); - - if ( iPlayerIndex > 0 ) - { - // tell all spectators that the camera is in use. - char szText[200]; - Q_snprintf( szText, sizeof(szText), "SourceTV camera is now controlled by %s.", pPlayer->GetPlayerName() ); - UTIL_ClientPrintFilter( filter, HUD_PRINTTALK, szText ); - } - else - { - // tell all spectators that the camera is available again. - UTIL_ClientPrintFilter( filter, HUD_PRINTTALK, "SourceTV camera switched to auto-director mode." ); - } - - return true; -} - -void CHLTVDirector::FinishCameraManShot() -{ - Assert( m_iCameraMan == m_iPVSEntity ); - - int index = FindFirstEvent( m_nBroadcastTick ); - - if ( index == m_EventHistory.InvalidIndex() ) - { - // check next frame again if event history is empty - m_nNextShotTick = m_nBroadcastTick+1; - return; - } - - m_nNextShotTick = m_nBroadcastTick + TIME_TO_TICKS( MIN_SHOT_LENGTH ); - - //check if camera turns camera off within broadcast time and game time - while( index != m_EventHistory.InvalidIndex() ) - { - CGameEvent &dc = m_EventHistory[index]; - - if ( dc.m_Tick >= m_nNextShotTick ) - break; - - if ( Q_strcmp( dc.m_Event->GetName(), "hltv_cameraman") == 0 ) - { - int iNewCameraMan = dc.m_Event->GetInt("index"); - - if ( iNewCameraMan == 0 ) - { - // camera man switched camera off - m_nNextShotTick = dc.m_Tick+1; - m_iCameraMan = 0; - return; - } - } - - index = m_EventHistory.NextInorder( index ); - } - - // camera man is still recording and live, resend camera man message - IGameEvent *msg = gameeventmanager->CreateEvent( "hltv_cameraman", true ); - if ( msg ) - { - msg->SetInt("index", m_iCameraMan ); - m_pHLTVServer->BroadcastEvent( msg ); - gameeventmanager->FreeEvent( msg ); - } - -} - -bool CHLTVDirector::StartCameraManShot() -{ - Assert( m_nNextShotTick <= m_nBroadcastTick ); - - int index = FindFirstEvent( m_nNextShotTick ); - - // check for cameraman mode - while( index != m_EventHistory.InvalidIndex() ) - { - CGameEvent &dc = m_EventHistory[index]; - - // only check if this is the current tick - if ( dc.m_Tick > m_nBroadcastTick ) - break; - - if ( Q_strcmp( dc.m_Event->GetName(), "hltv_cameraman") == 0 ) - { - if ( dc.m_Event->GetInt("index") > 0 ) - { - // ok, this guy is now the active camera man - m_iCameraMan = dc.m_Event->GetInt("index"); - - m_iPVSEntity = m_iCameraMan; - m_nNextShotTick = m_nBroadcastTick+1; // check setting right on next frame - - // send camera man command to client - m_pHLTVServer->BroadcastEvent( dc.m_Event ); - return true; - } - } - - index = m_EventHistory.NextInorder( index ); - } - - return false; // no camera man found -} - -void CHLTVDirector::StartInstantBroadcastShot() -{ - m_nNextShotTick = m_nBroadcastTick + TIME_TO_TICKS( MAX_SHOT_LENGTH ); - - if ( m_iCameraManIndex > 0 ) - { - // camera man is still recording and live, resend camera man message - IGameEvent *msg = gameeventmanager->CreateEvent( "hltv_cameraman", true ); - if ( msg ) - { - msg->SetInt("index", m_iCameraManIndex ); - m_pHLTVServer->BroadcastEvent( msg ); - gameeventmanager->FreeEvent( msg ); - - m_iPVSEntity = m_iCameraManIndex; - m_nNextShotTick = m_nBroadcastTick+TIME_TO_TICKS( MIN_SHOT_LENGTH ); - } - } - else - { - RemoveEventsFromHistory(-1); // all - - AnalyzePlayers(); - - AnalyzeCameras(); - - StartRandomShot(); - } -} - -void CHLTVDirector::StartNewShot() -{ - // we can remove all events the - int smallestTick = MAX(0, gpGlobals->tickcount - TIME_TO_TICKS(HLTV_MAX_DELAY) ); - RemoveEventsFromHistory( smallestTick ); - - // if the delay time is to short for autodirector, just show next best thing - if ( m_fDelay < HLTV_MIN_DIRECTOR_DELAY ) - { - StartInstantBroadcastShot(); - return; - } - - if ( m_iCameraMan > 0 ) - { - // we already have an active camera man, - // wait until he releases the "record" lock - FinishCameraManShot(); - return; - } - - if ( StartCameraManShot() ) - { - // now we have an active camera man - return; - } - - // ok, no camera man active, now check how much time - // we have for the next shot, if the time diff to the next - // important event we have to switch to is too short (<2sec) - // just extent the current shot and don't start a new one - - // check the next 8 seconds for interrupts/important events - m_nNextShotTick = m_nBroadcastTick + TIME_TO_TICKS( MAX_SHOT_LENGTH ); - - if ( m_nBroadcastTick <= 0 ) - { - // game hasn't started yet, we are still in the broadcast delay hole - IGameEvent *msg = gameeventmanager->CreateEvent( "hltv_message", true ); - - if ( msg ) - { - msg->SetString("text", "Please wait for broadcast to start ..." ); - - // send spectators the HLTV director command as a game event - m_pHLTVServer->BroadcastEvent( msg ); - gameeventmanager->FreeEvent( msg ); - } - - StartBestFixedCameraShot( true ); - return; - } - - int index = FindFirstEvent( m_nBroadcastTick ); - - while( index != m_EventHistory.InvalidIndex() ) - { - CGameEvent &dc = m_EventHistory[index]; - - if ( dc.m_Tick >= m_nNextShotTick ) - break; // we have searched enough - - // a camera man is always interrupting auto director - if ( Q_strcmp( dc.m_Event->GetName(), "hltv_cameraman") == 0 ) - { - if ( dc.m_Event->GetInt("index") > 0 ) - { - // stop the next cut when this cameraman starts recording - m_nNextShotTick = dc.m_Tick; - break; - } - } - - index = m_EventHistory.NextInorder( index ); - } - - float flDuration = TICKS_TO_TIME(m_nNextShotTick - m_nBroadcastTick); - - if ( flDuration < MIN_SHOT_LENGTH ) - return; // not enough time for a new shot - - // find the most interesting game event for next shot - CGameEvent *dc = FindBestGameEvent(); - - if ( dc ) - { - // show the game event - CreateShotFromEvent( dc ); - } - else - { - // no interesting events found, start random shot - StartRandomShot(); - } -} - -CGameEvent *CHLTVDirector::FindBestGameEvent() -{ - int bestEvent[4]; - int bestEventPrio[4]; - - Q_memset( bestEvent, 0, sizeof(bestEvent) ); - Q_memset( bestEventPrio, 0, sizeof(bestEventPrio) ); - - int index = FindFirstEvent( m_nBroadcastTick ); - - // search for next 4 best events within next 8 seconds - for (int i = 0; i<4; i ++) - { - bestEventPrio[i] = 0; - bestEvent[i] = 0; - - int tillTick = m_nBroadcastTick + TIME_TO_TICKS( 2.0f*(1.0f+i) ); - - if ( tillTick > m_nNextShotTick ) - break; - - // sum all action for the next time - while ( index != m_EventHistory.InvalidIndex() ) - { - CGameEvent &event = m_EventHistory[index]; - - if ( event.m_Tick > tillTick ) - break; - - int priority = event.m_Priority; - - if ( priority > bestEventPrio[i] ) - { - bestEvent[i] = index; - bestEventPrio[i] = priority; - } - - index = m_EventHistory.NextInorder( index ); - } - } - - if ( !( bestEventPrio[0] || bestEventPrio[1] || bestEventPrio[2] ) ) - return NULL; // no event found at all, give generic algorithm a chance - - // camera cut rules : - - if ( bestEventPrio[1] >= bestEventPrio[0] && - bestEventPrio[1] >= bestEventPrio[2] && - bestEventPrio[1] >= bestEventPrio[3] ) - { - return &m_EventHistory[ bestEvent[1] ]; // best case - } - else if ( bestEventPrio[0] > bestEventPrio[1] && - bestEventPrio[0] > bestEventPrio[2] ) - { - return &m_EventHistory[ bestEvent[0] ]; // event 0 is very important - } - else if ( bestEventPrio[2] > bestEventPrio[3] ) - { - return &m_EventHistory[ bestEvent[2] ]; - } - else - { - // event 4 is the best but too far away, so show event 1 - if ( bestEvent[0] ) - return &m_EventHistory[ bestEvent[0] ]; - else - return NULL; - } -} - -void CHLTVDirector::AnalyzeCameras() -{ - InitRandomOrder( m_nNumFixedCameras ); - - for ( int i = 0; iGetAbsOrigin(); - - for ( int j=0; jGetAbsOrigin(); - - float dist = VectorLength( vPlayerPos - vCamPos ); - - if ( dist > 1024.0f || dist < 4.0f ) - continue; // too colse or far away - - // check visibility - trace_t tr; - UTIL_TraceLine( vCamPos, pPlayer->GetAbsOrigin(), MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction < 1.0 ) - continue; // not visible for camera - - nCount++; - - // remember closest player - if ( dist < flClosestPlayerDist ) - { - iClosestPlayer = pPlayer->entindex(); - flClosestPlayerDist = dist; - } - - Vector v1; AngleVectors( pPlayer->EyeAngles(), &v1 ); - - // check players orientation towards camera - Vector v2 = vCamPos - vPlayerPos; - VectorNormalize( v2 ); - - // player/camera cost function: - flRank += ( 1.0f/sqrt(dist) ) * WeightedAngle( v1, v2 ); - - vDistribution += v2; - } - - if ( nCount > 0 ) - { - // normalize distribution - flRank *= VectorLength( vDistribution ) / nCount; - } - - IGameEvent *event = gameeventmanager->CreateEvent("hltv_rank_camera"); - - if ( event ) - { - event->SetFloat("rank", flRank ); - event->SetInt("index", iCameraIndex ); // index in m_pFixedCameras - event->SetInt("target", iClosestPlayer ); // ent index - gameeventmanager->FireEvent( event ); - } - } -} - -void CHLTVDirector::BuildActivePlayerList() -{ - // first build list of all active players - - m_nNumActivePlayers = 0; - - for ( int i =1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - - if ( !pPlayer ) - continue; - - if ( !pPlayer->IsAlive() ) - continue; - - if ( pPlayer->IsObserver() ) - continue; - - if ( pPlayer->GetTeamNumber() <= TEAM_SPECTATOR ) - continue; - - m_pActivePlayers[m_nNumActivePlayers] = pPlayer; - m_nNumActivePlayers++; - } -} - -void CHLTVDirector::AnalyzePlayers() -{ - // build list of current active players - BuildActivePlayerList(); - - // analyzes every active player - - InitRandomOrder( m_nNumActivePlayers ); - - for ( int i = 0; iGetAbsOrigin(); - - Vector v1; AngleVectors( pPlayer->EyeAngles(), &v1 ); - - v1 *= -1; // inverted - - for ( int j=0; jGetAbsOrigin(); - - float dist = VectorLength( vPlayerPos - vCamPos ); - - if ( dist > 1024.0f || dist < 4.0f ) - continue; // too close or far away - - // check visibility - trace_t tr; - UTIL_TraceLine( vCamPos, pOtherPlayer->GetAbsOrigin(), MASK_SOLID, pOtherPlayer, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction < 1.0 ) - continue; // not visible for camera - - nCount++; - - // check players orientation towards camera - Vector v2; AngleVectors( pOtherPlayer->EyeAngles(), &v2 ); - - float facing = WeightedAngle( v1, v2 ); - - // remember closest player - if ( facing > flBestFacingPlayer ) - { - iBestFacingPlayer = pOtherPlayer->entindex(); - flBestFacingPlayer = facing; - } - - // player/camera cost function: - flRank += ( 1.0f/sqrt(dist) ) * facing; - - vDistribution += v2; - } - - if ( nCount > 0 ) - { - float flDistribution = VectorLength( vDistribution ) / nCount; // normalize distribution - flRank *= flDistribution; - } - - IGameEvent *event = gameeventmanager->CreateEvent("hltv_rank_entity"); - if ( event ) - { - event->SetInt("index", pPlayer->entindex() ); - event->SetFloat("rank", flRank ); - event->SetInt("target", iBestFacingPlayer ); // ent index - gameeventmanager->FireEvent( event ); - } - } -} - diff --git a/game/server/hltvdirector.h b/game/server/hltvdirector.h deleted file mode 100644 index 946456eb9..000000000 --- a/game/server/hltvdirector.h +++ /dev/null @@ -1,124 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef HLTVDIRECTOR_H -#define HLTVDIRECTOR_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "GameEventListener.h" -#include -#include -#include -#include - -#define HLTV_MIN_DIRECTOR_DELAY 10 // minimum delay if director is enabled -#define HLTV_MAX_DELAY 120 // maximum delay - - -#define MAX_NUM_CAMERAS 64 // support up to 64 fixed cameras per level - -#define MIN_SHOT_LENGTH 4.0f // minimum time of a cut (seconds) -#define MAX_SHOT_LENGTH 8.0f // maximum time of a cut (seconds) -#define DEF_SHOT_LENGTH 6.0f // average time of a cut (seconds) - -class CGameEvent -{ -public: - int m_Tick; // tick of this command - int m_Priority; // game event priority - IGameEvent *m_Event; // IGameEvent -}; - -class CHLTVDirector : public CGameEventListener, public CBaseGameSystemPerFrame, public IHLTVDirector -{ -public: - DECLARE_CLASS_NOBASE( CHLTVDirector ); - - virtual char const *Name() { return "CHLTVDirector"; } - - CHLTVDirector(); - virtual ~CHLTVDirector(); - - virtual void SetHLTVServer( IHLTVServer *hltv ); // give the director an HLTV interface - IHLTVServer* GetHLTVServer( void ); - int GetDirectorTick( void ); // get current broadcast tick from director - int GetPVSEntity( void ); // get current view entity (PVS) - Vector GetPVSOrigin( void ); // get current PVS origin, if PVS entity is 0 - float GetDelay( void ); // returns current delay in seconds - bool IsActive( void ); - - virtual const char** GetModEvents(); // returns list of event names forwarded to HLTV clients - - void BuildCameraList( void ); - - -public: // IGameEventListener Interface - virtual void FireGameEvent( IGameEvent * event ); - -public: // CBaseGameSystem overrides - - virtual bool Init(); - virtual void Shutdown(); - virtual void FrameUpdatePostEntityThink(); - virtual void LevelInitPostEntity(); - virtual const char* GetFixedCameraEntityName( void ) { return "point_viewcontrol"; } - - bool SetCameraMan( int iPlayerIndex ); - int GetCameraMan() { return m_iCameraManIndex; } - - -protected: - - virtual void StartNewShot(); - virtual void StartRandomShot(); - virtual void StartDelayMessage(); - virtual void StartBestFixedCameraShot(bool bForce); - virtual void StartBestPlayerCameraShot(); - virtual void StartFixedCameraShot(int iCamera, int iTarget); - virtual void StartChaseCameraShot(int iTarget1, int iTarget2, int distance, int phi, int theta, bool bInEye); - virtual void UpdateSettings(); - virtual void AnalyzePlayers(); - virtual void AnalyzeCameras(); - virtual bool StartCameraManShot(); - virtual void StartInstantBroadcastShot(); - virtual void FinishCameraManShot(); - virtual void BuildActivePlayerList(); - virtual CGameEvent *FindBestGameEvent(); - virtual void CreateShotFromEvent( CGameEvent *ge ); - - int FindFirstEvent( int tick ); // finds first event >= tick - void CheckHistory(); - void RemoveEventsFromHistory(int tick); // removes all commands < tick, or all if tick -1 - - IHLTVServer *m_pHLTVServer; // interface to servers HLTV object - float m_fDelay; // hltv delay in seconds - int m_nBroadcastTick; // world time that is currently "on the air" - int m_iPVSEntity; // entity for PVS center - Vector m_vPVSOrigin; // PVS origin if PVS entity is 0 - int m_iCameraMan; // >0 if current view entity is a cameraman - CBasePlayer *m_pHLTVClient; // the HLTV fake client - int m_nNextShotTick; // time for the next scene cut - int m_iLastPlayer; // last player in random rotation - - int m_nNextAnalyzeTick; - - int m_nNumFixedCameras; //number of cameras in current map - CBaseEntity *m_pFixedCameras[MAX_NUM_CAMERAS]; // fixed cameras (point_viewcontrol) - - int m_nNumActivePlayers; //number of cameras in current map - CBasePlayer *m_pActivePlayers[MAX_PLAYERS]; // fixed cameras (point_viewcontrol) - int m_iCameraManIndex; // entity index of current camera man or 0 - - CUtlRBTree m_EventHistory; -}; - -extern IGameSystem* HLTVDirectorSystem(); -extern CHLTVDirector* HLTVDirector(); - -#endif // HLTVDIRECTOR_H diff --git a/game/server/ilagcompensationmanager.h b/game/server/ilagcompensationmanager.h deleted file mode 100644 index b42e46f37..000000000 --- a/game/server/ilagcompensationmanager.h +++ /dev/null @@ -1,30 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ILAGCOMPENSATIONMANAGER_H -#define ILAGCOMPENSATIONMANAGER_H -#ifdef _WIN32 -#pragma once -#endif - -class CBasePlayer; -class CUserCmd; - -//----------------------------------------------------------------------------- -// Purpose: This is also an IServerSystem -//----------------------------------------------------------------------------- -abstract_class ILagCompensationManager -{ -public: - // Called during player movement to set up/restore after lag compensation - virtual void StartLagCompensation( CBasePlayer *player, CUserCmd *cmd ) = 0; - virtual void FinishLagCompensation( CBasePlayer *player ) = 0; -}; - -extern ILagCompensationManager *lagcompensation; - -#endif // ILAGCOMPENSATIONMANAGER_H diff --git a/game/server/info_camera_link.cpp b/game/server/info_camera_link.cpp deleted file mode 100644 index d9f63d4b5..000000000 --- a/game/server/info_camera_link.cpp +++ /dev/null @@ -1,183 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" - -#include "info_camera_link.h" -#include "point_camera.h" -#include "utllinkedlist.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -//----------------------------------------------------------------------------- -// Link between entities and cameras -//----------------------------------------------------------------------------- -class CInfoCameraLink : public CLogicalEntity -{ - DECLARE_CLASS( CInfoCameraLink, CLogicalEntity ); - DECLARE_DATADESC(); - -public: - CInfoCameraLink(); - ~CInfoCameraLink(); - - virtual void Activate(); - -private: - void InputSetCamera(inputdata_t &inputdata); - void InputSetTargetEntity(inputdata_t &inputdata); - void SetCameraByName(const char *szName); - - CHandle m_hCamera; - EHANDLE m_hTargetEntity; - string_t m_strPointCamera; - - friend CBaseEntity *CreateInfoCameraLink( CBaseEntity *pTarget, CPointCamera *pCamera ); - friend void PointCameraSetupVisibility( CBaseEntity *pPlayer, int area, unsigned char *pvs, int pvssize ); -}; - - -//----------------------------------------------------------------------------- -// List of all info camera links -//----------------------------------------------------------------------------- -CUtlFixedLinkedList g_InfoCameraLinkList; - - -//----------------------------------------------------------------------------- -// Save/load -//----------------------------------------------------------------------------- -BEGIN_DATADESC( CInfoCameraLink ) - - DEFINE_KEYFIELD( m_strPointCamera, FIELD_STRING, "PointCamera" ), - - DEFINE_FIELD( m_hCamera, FIELD_EHANDLE ), - DEFINE_FIELD( m_hTargetEntity, FIELD_EHANDLE ), - - // Outputs - DEFINE_INPUTFUNC( FIELD_STRING, "SetCamera", InputSetCamera ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( info_camera_link, CInfoCameraLink ); - - -//----------------------------------------------------------------------------- -// Constructor, destructor -//----------------------------------------------------------------------------- -CInfoCameraLink::CInfoCameraLink() -{ - g_InfoCameraLinkList.AddToTail( this ); -} - -CInfoCameraLink::~CInfoCameraLink() -{ - g_InfoCameraLinkList.FindAndRemove( this ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Called after all entities have spawned and after a load game. -//----------------------------------------------------------------------------- -void CInfoCameraLink::Activate() -{ - BaseClass::Activate(); - - // Checks necessary to prevent interference with CreateInfoCameraLink - if ( !m_hCamera ) - { - SetCameraByName( STRING(m_strPointCamera) ); - } - - if ( !m_hTargetEntity ) - { - m_hTargetEntity = gEntList.FindEntityByName( NULL, STRING(m_target) ); - } -} - -void CInfoCameraLink::SetCameraByName(const char *szName) -{ - CBaseEntity *pBaseEnt = gEntList.FindEntityByName( NULL, szName ); - if( pBaseEnt ) - { - m_hCamera = dynamic_cast( pBaseEnt ); - if ( m_hCamera ) - { - // Keep the camera name consistent for save/load - m_strPointCamera = MAKE_STRING( szName ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CInfoCameraLink::InputSetCamera(inputdata_t &inputdata) -{ - SetCameraByName( inputdata.value.String() ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseEntity *CreateInfoCameraLink( CBaseEntity *pTarget, CPointCamera *pCamera ) -{ - CInfoCameraLink *pInfoCameraLink = (CInfoCameraLink*)CreateEntityByName( "info_camera_link" ); - if ( !pInfoCameraLink ) - return NULL; - - pInfoCameraLink->m_hCamera = pCamera; - pInfoCameraLink->m_hTargetEntity = pTarget; - pInfoCameraLink->Spawn(); - return pInfoCameraLink; -} - - -//----------------------------------------------------------------------------- -// Sets up visibility -//----------------------------------------------------------------------------- -void PointCameraSetupVisibility( CBaseEntity *pPlayer, int area, unsigned char *pvs, int pvssize ) -{ - for ( CPointCamera *pCameraEnt = GetPointCameraList(); pCameraEnt != NULL; pCameraEnt = pCameraEnt->m_pNext ) - { - pCameraEnt->SetActive( false ); - } - - int nNext; - for ( int i = g_InfoCameraLinkList.Head(); i != g_InfoCameraLinkList.InvalidIndex(); i = nNext ) - { - nNext = g_InfoCameraLinkList.Next( i ); - - CBaseEntity *pTargetEnt = g_InfoCameraLinkList[i]->m_hTargetEntity; - if ( !pTargetEnt ) - { - UTIL_Remove( g_InfoCameraLinkList[i] ); - continue; - } - - // Don't bother if it's not visible - if ( pTargetEnt->IsEffectActive( EF_NODRAW ) ) - continue; - - if ( !pTargetEnt->NetworkProp()->IsInPVS( pPlayer->edict(), pvs, pvssize ) ) - continue; - - if ( engine->CheckAreasConnected( area, pTargetEnt->NetworkProp()->AreaNum() ) ) - { - CPointCamera *pCameraEnt = g_InfoCameraLinkList[i]->m_hCamera; - if ( pCameraEnt ) - { - engine->AddOriginToPVS( pCameraEnt->GetAbsOrigin() ); - pCameraEnt->SetActive( true ); - } - } - } -} - diff --git a/game/server/info_camera_link.h b/game/server/info_camera_link.h deleted file mode 100644 index 605188286..000000000 --- a/game/server/info_camera_link.h +++ /dev/null @@ -1,32 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef INFO_CAMERA_LINK_H -#define INFO_CAMERA_LINK_H - -#include "baseentity.h" - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class CPointCamera; - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseEntity *CreateInfoCameraLink( CBaseEntity *pTarget, CPointCamera *pCamera ); - - -//----------------------------------------------------------------------------- -// Sets up visibility -//----------------------------------------------------------------------------- -void PointCameraSetupVisibility( CBaseEntity *pPlayer, int area, unsigned char *pvs, int pvssize ); - - - -#endif // INFO_CAMERA_LINK_H - diff --git a/game/server/info_overlay_accessor.cpp b/game/server/info_overlay_accessor.cpp deleted file mode 100644 index 61294e36a..000000000 --- a/game/server/info_overlay_accessor.cpp +++ /dev/null @@ -1,50 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// -------------------------------------------------------------------------------- // -// An entity used to access overlays (and change their texture) -// -------------------------------------------------------------------------------- // - -class CInfoOverlayAccessor : public CPointEntity -{ -public: - - DECLARE_CLASS( CInfoOverlayAccessor, CPointEntity ); - - int UpdateTransmitState(); - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - -private: - - CNetworkVar( int, m_iOverlayID ); -}; - - -// This table encodes the CBaseEntity data. -IMPLEMENT_SERVERCLASS_ST_NOBASE(CInfoOverlayAccessor, DT_InfoOverlayAccessor) - SendPropInt ( SENDINFO(m_iTextureFrameIndex), 8, SPROP_UNSIGNED ), - SendPropInt ( SENDINFO(m_iOverlayID), 32, SPROP_UNSIGNED ), -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( info_overlay_accessor, CInfoOverlayAccessor ); - -BEGIN_DATADESC( CInfoOverlayAccessor ) - DEFINE_KEYFIELD( m_iOverlayID, FIELD_INTEGER, "OverlayID" ), -END_DATADESC() - - -int CInfoOverlayAccessor::UpdateTransmitState() -{ - return SetTransmitState( FL_EDICT_ALWAYS ); -} diff --git a/game/server/init_factory.cpp b/game/server/init_factory.cpp deleted file mode 100644 index 0029dc1f3..000000000 --- a/game/server/init_factory.cpp +++ /dev/null @@ -1,25 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "init_factory.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -static factorylist_t s_factories; - -// Store off the factories -void FactoryList_Store( const factorylist_t &sourceData ) -{ - s_factories = sourceData; -} - -// retrieve the stored factories -void FactoryList_Retrieve( factorylist_t &destData ) -{ - destData = s_factories; -} diff --git a/game/server/init_factory.h b/game/server/init_factory.h deleted file mode 100644 index d751b4959..000000000 --- a/game/server/init_factory.h +++ /dev/null @@ -1,30 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef INIT_FACTORY_H -#define INIT_FACTORY_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "interface.h" - -struct factorylist_t -{ - CreateInterfaceFn engineFactory; - CreateInterfaceFn physicsFactory; - CreateInterfaceFn fileSystemFactory; -}; - -// Store off the factories -void FactoryList_Store( const factorylist_t &sourceData ); - -// retrieve the stored factories -void FactoryList_Retrieve( factorylist_t &destData ); - -#endif // INIT_FACTORY_H diff --git a/game/server/intermission.cpp b/game/server/intermission.cpp deleted file mode 100644 index 166898d4b..000000000 --- a/game/server/intermission.cpp +++ /dev/null @@ -1,52 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "entitylist.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//========================================================= -// Multiplayer intermission spots. -//========================================================= -class CInfoIntermission:public CPointEntity -{ -public: - DECLARE_CLASS( CInfoIntermission, CPointEntity ); - - void Spawn( void ); - void Think( void ); -}; - -void CInfoIntermission::Spawn( void ) -{ - SetSolid( SOLID_NONE ); - AddEffects( EF_NODRAW ); - SetLocalAngles( vec3_angle ); - SetNextThink( gpGlobals->curtime + 2 );// let targets spawn ! -} - -void CInfoIntermission::Think ( void ) -{ - CBaseEntity *pTarget; - - // find my target - pTarget = gEntList.FindEntityByName( NULL, m_target ); - - if ( pTarget ) - { - Vector dir = pTarget->GetLocalOrigin() - GetLocalOrigin(); - VectorNormalize( dir ); - QAngle angles; - VectorAngles( dir, angles ); - SetLocalAngles( angles ); - } -} - -LINK_ENTITY_TO_CLASS( info_intermission, CInfoIntermission ); diff --git a/game/server/iscorer.h b/game/server/iscorer.h deleted file mode 100644 index 54e134255..000000000 --- a/game/server/iscorer.h +++ /dev/null @@ -1,29 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Interface that entities can use to redirect scoring to other entities. -// i.e. A rocket redirects scoring to the player that fired it. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ISCORER_H -#define ISCORER_H -#ifdef _WIN32 -#pragma once -#endif - -//----------------------------------------------------------------------------- -// Purpose: Interface that entities can use to redirect scoring to other entities. -// i.e. A rocket redirects scoring to the player that fired it. -//----------------------------------------------------------------------------- -abstract_class IScorer -{ -public: - // Return the entity that should receive the score - virtual CBasePlayer *GetScorer( void ) = 0; - // Return the entity that should get assistance credit - virtual CBasePlayer *GetAssistant( void ) = 0; -}; - - -#endif // ISCORER_H diff --git a/game/server/iservervehicle.h b/game/server/iservervehicle.h deleted file mode 100644 index 80cadc8ab..000000000 --- a/game/server/iservervehicle.h +++ /dev/null @@ -1,139 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ISERVERVEHICLE_H -#define ISERVERVEHICLE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "IVehicle.h" -#include "vphysics/vehicles.h" - -class CBaseEntity; -class CBasePlayer; -class CBaseCombatCharacter; -class CNPC_VehicleDriver; -enum VehicleSeatQuery_e; - -// This is used by the player to access vehicles. It's an interface so the -// vehicles are not restricted in what they can derive from. -abstract_class IServerVehicle : public IVehicle -{ -public: - // Get the entity associated with the vehicle. - virtual CBaseEntity* GetVehicleEnt() = 0; - - // Get and set the current driver. Use PassengerRole_t enum in shareddefs.h for adding passengers - virtual void SetPassenger( int nRole, CBaseCombatCharacter *pPassenger ) = 0; - - // Is the player visible while in the vehicle? (this is a constant the vehicle) - virtual bool IsPassengerVisible( int nRole = VEHICLE_ROLE_DRIVER ) = 0; - - // Can a given passenger take damage? - virtual bool IsPassengerDamagable( int nRole = VEHICLE_ROLE_DRIVER ) = 0; - virtual bool PassengerShouldReceiveDamage( CTakeDamageInfo &info ) = 0; - - // Is the vehicle upright? - virtual bool IsVehicleUpright( void ) = 0; - - // Whether or not we're in a transitional phase - virtual bool IsPassengerEntering( void ) = 0; - virtual bool IsPassengerExiting( void ) = 0; - - // Get a position in *world space* inside the vehicle for the player to start at - virtual void GetPassengerSeatPoint( int nRole, Vector *pPoint, QAngle *pAngles ) = 0; - - virtual void HandlePassengerEntry( CBaseCombatCharacter *pPassenger, bool bAllowEntryOutsideZone = false ) = 0; - virtual bool HandlePassengerExit( CBaseCombatCharacter *pPassenger ) = 0; - - // Get a point in *world space* to leave the vehicle from (may be in solid) - virtual bool GetPassengerExitPoint( int nRole, Vector *pPoint, QAngle *pAngles ) = 0; - virtual int GetEntryAnimForPoint( const Vector &vecPoint ) = 0; - virtual int GetExitAnimToUse( Vector &vecEyeExitEndpoint, bool &bAllPointsBlocked ) = 0; - virtual void HandleEntryExitFinish( bool bExitAnimOn, bool bResetAnim ) = 0; - - virtual Class_T ClassifyPassenger( CBaseCombatCharacter *pPassenger, Class_T defaultClassification ) = 0; - virtual float PassengerDamageModifier( const CTakeDamageInfo &info ) = 0; - - // Get me the parameters for this vehicle - virtual const vehicleparams_t *GetVehicleParams( void ) = 0; - // If I'm a physics vehicle, get the controller - virtual IPhysicsVehicleController *GetVehicleController() = 0; - - virtual int NPC_GetAvailableSeat( CBaseCombatCharacter *pPassenger, string_t strRoleName, VehicleSeatQuery_e nQueryType ) = 0; - virtual bool NPC_AddPassenger( CBaseCombatCharacter *pPassenger, string_t strRoleName, int nSeat ) = 0; - virtual bool NPC_RemovePassenger( CBaseCombatCharacter *pPassenger ) = 0; - virtual bool NPC_GetPassengerSeatPosition( CBaseCombatCharacter *pPassenger, Vector *vecResultPos, QAngle *vecResultAngle ) = 0; - virtual bool NPC_GetPassengerSeatPositionLocal( CBaseCombatCharacter *pPassenger, Vector *vecResultPos, QAngle *vecResultAngle ) = 0; - virtual int NPC_GetPassengerSeatAttachment( CBaseCombatCharacter *pPassenger ) = 0; - virtual bool NPC_HasAvailableSeat( string_t strRoleName ) = 0; - - virtual const PassengerSeatAnims_t *NPC_GetPassengerSeatAnims( CBaseCombatCharacter *pPassenger, PassengerSeatAnimType_t nType ) = 0; - virtual CBaseCombatCharacter *NPC_GetPassengerInSeat( int nRoleID, int nSeatID ) = 0; - - virtual void RestorePassengerInfo( void ) = 0; - - // NPC Driving - virtual bool NPC_CanDrive( void ) = 0; - virtual void NPC_SetDriver( CNPC_VehicleDriver *pDriver ) = 0; - virtual void NPC_DriveVehicle( void ) = 0; - virtual void NPC_ThrottleCenter( void ) = 0; - virtual void NPC_ThrottleReverse( void ) = 0; - virtual void NPC_ThrottleForward( void ) = 0; - virtual void NPC_Brake( void ) = 0; - virtual void NPC_TurnLeft( float flDegrees ) = 0; - virtual void NPC_TurnRight( float flDegrees ) = 0; - virtual void NPC_TurnCenter( void ) = 0; - virtual void NPC_PrimaryFire( void ) = 0; - virtual void NPC_SecondaryFire( void ) = 0; - virtual bool NPC_HasPrimaryWeapon( void ) = 0; - virtual bool NPC_HasSecondaryWeapon( void ) = 0; - virtual void NPC_AimPrimaryWeapon( Vector vecTarget ) = 0; - virtual void NPC_AimSecondaryWeapon( Vector vecTarget ) = 0; - - // Weapon handling - virtual void Weapon_PrimaryRanges( float *flMinRange, float *flMaxRange ) = 0; - virtual void Weapon_SecondaryRanges( float *flMinRange, float *flMaxRange ) = 0; - virtual float Weapon_PrimaryCanFireAt( void ) = 0; // Return the time at which this vehicle's primary weapon can fire again - virtual float Weapon_SecondaryCanFireAt( void ) = 0; // Return the time at which this vehicle's secondary weapon can fire again - - // debugging, script file flushed - virtual void ReloadScript() = 0; -}; - -// This is an interface to derive from if your class contains an IServerVehicle -// handler (i.e. something derived CBaseServerVehicle. -abstract_class IDrivableVehicle -{ -public: - virtual CBaseEntity *GetDriver( void ) = 0; - - // Process movement - virtual void ItemPostFrame( CBasePlayer *pPlayer ) = 0; - virtual void SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) = 0; - virtual void ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ) = 0; - virtual void FinishMove( CBasePlayer *player, CUserCmd *ucmd, CMoveData *move ) = 0; - - // Entering / Exiting - virtual bool CanEnterVehicle( CBaseEntity *pEntity ) = 0; - virtual bool CanExitVehicle( CBaseEntity *pEntity ) = 0; - virtual void SetVehicleEntryAnim( bool bOn ) = 0; - virtual void SetVehicleExitAnim( bool bOn, Vector vecEyeExitEndpoint ) = 0; - virtual void EnterVehicle( CBaseCombatCharacter *pPassenger ) = 0; - - virtual void PreExitVehicle( CBaseCombatCharacter *pPassenger, int nRole ) = 0; - virtual void ExitVehicle( int nRole ) = 0; - virtual bool AllowBlockedExit( CBaseCombatCharacter *pPassenger, int nRole ) = 0; - virtual bool AllowMidairExit( CBaseCombatCharacter *pPassenger, int nRole ) = 0; - virtual string_t GetVehicleScriptName() = 0; - - virtual bool PassengerShouldReceiveDamage( CTakeDamageInfo &info ) = 0; -}; - -#endif // IVEHICLE_H diff --git a/game/server/item_world.cpp b/game/server/item_world.cpp deleted file mode 100644 index 970544370..000000000 --- a/game/server/item_world.cpp +++ /dev/null @@ -1,519 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: Handling for the base world item. Most of this was moved from items.cpp. -// -// $NoKeywords: $ -//===========================================================================// - -#include "cbase.h" -#include "player.h" -#include "items.h" -#include "gamerules.h" -#include "engine/IEngineSound.h" -#include "iservervehicle.h" -#include "physics_saverestore.h" - -#ifdef HL2MP -#include "hl2mp_gamerules.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define ITEM_PICKUP_BOX_BLOAT 24 - -class CWorldItem : public CBaseAnimating -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( CWorldItem, CBaseAnimating ); - - bool KeyValue( const char *szKeyName, const char *szValue ); - void Spawn( void ); - - int m_iType; -}; - -LINK_ENTITY_TO_CLASS(world_items, CWorldItem); - -BEGIN_DATADESC( CWorldItem ) - -DEFINE_FIELD( m_iType, FIELD_INTEGER ), - -END_DATADESC() - - -bool CWorldItem::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "type")) - { - m_iType = atoi(szValue); - } - else - return BaseClass::KeyValue( szKeyName, szValue ); - - return true; -} - -void CWorldItem::Spawn( void ) -{ - CBaseEntity *pEntity = NULL; - - switch (m_iType) - { - case 44: // ITEM_BATTERY: - pEntity = CBaseEntity::Create( "item_battery", GetLocalOrigin(), GetLocalAngles() ); - break; - case 45: // ITEM_SUIT: - pEntity = CBaseEntity::Create( "item_suit", GetLocalOrigin(), GetLocalAngles() ); - break; - } - - if (!pEntity) - { - Warning("unable to create world_item %d\n", m_iType ); - } - else - { - pEntity->m_target = m_target; - pEntity->SetName( GetEntityName() ); - pEntity->ClearSpawnFlags(); - pEntity->AddSpawnFlags( m_spawnflags ); - } - - UTIL_RemoveImmediate( this ); -} - - -BEGIN_DATADESC( CItem ) - - DEFINE_FIELD( m_bActivateWhenAtRest, FIELD_BOOLEAN ), - DEFINE_FIELD( m_vOriginalSpawnOrigin, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vOriginalSpawnAngles, FIELD_VECTOR ), - DEFINE_PHYSPTR( m_pConstraint ), - - // Function Pointers - DEFINE_ENTITYFUNC( ItemTouch ), - DEFINE_THINKFUNC( Materialize ), - DEFINE_THINKFUNC( ComeToRest ), - -#if defined( HL2MP ) - DEFINE_FIELD( m_flNextResetCheckTime, FIELD_TIME ), - DEFINE_THINKFUNC( FallThink ), -#endif - - // Outputs - DEFINE_OUTPUT( m_OnPlayerTouch, "OnPlayerTouch" ), - DEFINE_OUTPUT( m_OnCacheInteraction, "OnCacheInteraction" ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CItem::CItem() -{ - m_bActivateWhenAtRest = false; -} - -bool CItem::CreateItemVPhysicsObject( void ) -{ - // Create the object in the physics system - int nSolidFlags = GetSolidFlags() | FSOLID_NOT_STANDABLE; - if ( !m_bActivateWhenAtRest ) - { - nSolidFlags |= FSOLID_TRIGGER; - } - - if ( VPhysicsInitNormal( SOLID_VPHYSICS, nSolidFlags, false ) == NULL ) - { - SetSolid( SOLID_BBOX ); - AddSolidFlags( nSolidFlags ); - - // If it's not physical, drop it to the floor - if (UTIL_DropToFloor(this, MASK_SOLID) == 0) - { - Warning( "Item %s fell out of level at %f,%f,%f\n", GetClassname(), GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z); - UTIL_Remove( this ); - return false; - } - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CItem::Spawn( void ) -{ - if ( g_pGameRules->IsAllowedToSpawn( this ) == false ) - { - UTIL_Remove( this ); - return; - } - - SetMoveType( MOVETYPE_FLYGRAVITY ); - SetSolid( SOLID_BBOX ); - SetBlocksLOS( false ); - AddEFlags( EFL_NO_ROTORWASH_PUSH ); - - if( IsX360() ) - { - AddEffects( EF_ITEM_BLINK ); - } - - // This will make them not collide with the player, but will collide - // against other items + weapons - SetCollisionGroup( COLLISION_GROUP_WEAPON ); - CollisionProp()->UseTriggerBounds( true, ITEM_PICKUP_BOX_BLOAT ); - SetTouch(&CItem::ItemTouch); - - if ( CreateItemVPhysicsObject() == false ) - return; - - m_takedamage = DAMAGE_EVENTS_ONLY; - -#if !defined( CLIENT_DLL ) - // Constrained start? - if ( HasSpawnFlags( SF_ITEM_START_CONSTRAINED ) ) - { - //Constrain the weapon in place - IPhysicsObject *pReferenceObject, *pAttachedObject; - - pReferenceObject = g_PhysWorldObject; - pAttachedObject = VPhysicsGetObject(); - - if ( pReferenceObject && pAttachedObject ) - { - constraint_fixedparams_t fixed; - fixed.Defaults(); - fixed.InitWithCurrentObjectState( pReferenceObject, pAttachedObject ); - - fixed.constraint.forceLimit = lbs2kg( 10000 ); - fixed.constraint.torqueLimit = lbs2kg( 10000 ); - - m_pConstraint = physenv->CreateFixedConstraint( pReferenceObject, pAttachedObject, NULL, fixed ); - - m_pConstraint->SetGameData( (void *) this ); - } - } -#endif //CLIENT_DLL - -#if defined( HL2MP ) - SetThink( &CItem::FallThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); -#endif -} - -void CItem::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - CBasePlayer *pPlayer = ToBasePlayer( pActivator ); - - if ( pPlayer ) - { - pPlayer->PickupObject( this ); - } -} - -extern int gEvilImpulse101; - - -//----------------------------------------------------------------------------- -// Activate when at rest, but don't allow pickup until then -//----------------------------------------------------------------------------- -void CItem::ActivateWhenAtRest() -{ - RemoveSolidFlags( FSOLID_TRIGGER ); - m_bActivateWhenAtRest = true; - SetThink( &CItem::ComeToRest ); - SetNextThink( gpGlobals->curtime + 0.5f ); -} - - -//----------------------------------------------------------------------------- -// Become touchable when we are at rest -//----------------------------------------------------------------------------- -void CItem::OnEntityEvent( EntityEvent_t event, void *pEventData ) -{ - BaseClass::OnEntityEvent( event, pEventData ); - - switch( event ) - { - case ENTITY_EVENT_WATER_TOUCH: - { - // Delay rest for a sec, to avoid changing collision - // properties inside a collision callback. - SetThink( &CItem::ComeToRest ); - SetNextThink( gpGlobals->curtime + 0.1f ); - } - break; - default: - break; - } -} - - -//----------------------------------------------------------------------------- -// Become touchable when we are at rest -//----------------------------------------------------------------------------- -void CItem::ComeToRest( void ) -{ - if ( m_bActivateWhenAtRest ) - { - m_bActivateWhenAtRest = false; - AddSolidFlags( FSOLID_TRIGGER ); - SetThink( NULL ); - } -} - -#if defined( HL2MP ) - -//----------------------------------------------------------------------------- -// Purpose: Items that have just spawned run this think to catch them when -// they hit the ground. Once we're sure that the object is grounded, -// we change its solid type to trigger and set it in a large box that -// helps the player get it. -//----------------------------------------------------------------------------- -void CItem::FallThink ( void ) -{ - SetNextThink( gpGlobals->curtime + 0.1f ); - - bool shouldMaterialize = false; - IPhysicsObject *pPhysics = VPhysicsGetObject(); - if ( pPhysics ) - { - shouldMaterialize = pPhysics->IsAsleep(); - } - else - { - shouldMaterialize = (GetFlags() & FL_ONGROUND) ? true : false; - } - - if ( shouldMaterialize ) - { - SetThink ( NULL ); - - m_vOriginalSpawnOrigin = GetAbsOrigin(); - m_vOriginalSpawnAngles = GetAbsAngles(); - - HL2MPRules()->AddLevelDesignerPlacedObject( this ); - } -} - -#endif - -//----------------------------------------------------------------------------- -// Purpose: Used to tell whether an item may be picked up by the player. This -// accounts for solid obstructions being in the way. -// Input : *pItem - item in question -// *pPlayer - player attempting the pickup -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool UTIL_ItemCanBeTouchedByPlayer( CBaseEntity *pItem, CBasePlayer *pPlayer ) -{ - if ( pItem == NULL || pPlayer == NULL ) - return false; - - // For now, always allow a vehicle riding player to pick up things they're driving over - if ( pPlayer->IsInAVehicle() ) - return true; - - // Get our test positions - Vector vecStartPos; - IPhysicsObject *pPhysObj = pItem->VPhysicsGetObject(); - if ( pPhysObj != NULL ) - { - // Use the physics hull's center - QAngle vecAngles; - pPhysObj->GetPosition( &vecStartPos, &vecAngles ); - } - else - { - // Use the generic bbox center - vecStartPos = pItem->CollisionProp()->WorldSpaceCenter(); - } - - Vector vecEndPos = pPlayer->EyePosition(); - - // FIXME: This is the simple first try solution towards the problem. We need to take edges and shape more into account - // for this to be fully robust. - - // Trace between to see if we're occluded - trace_t tr; - CTraceFilterSkipTwoEntities filter( pPlayer, pItem, COLLISION_GROUP_PLAYER_MOVEMENT ); - UTIL_TraceLine( vecStartPos, vecEndPos, MASK_SOLID, &filter, &tr ); - - // Occluded - // FIXME: For now, we exclude starting in solid because there are cases where this doesn't matter - if ( tr.fraction < 1.0f ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Whether or not the item can be touched and picked up by the player, taking -// into account obstructions and other hinderances -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CItem::ItemCanBeTouchedByPlayer( CBasePlayer *pPlayer ) -{ - return UTIL_ItemCanBeTouchedByPlayer( this, pPlayer ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pOther - -//----------------------------------------------------------------------------- -void CItem::ItemTouch( CBaseEntity *pOther ) -{ - // Vehicles can touch items + pick them up - if ( pOther->GetServerVehicle() ) - { - pOther = pOther->GetServerVehicle()->GetPassenger(); - if ( !pOther ) - return; - } - - // if it's not a player, ignore - if ( !pOther->IsPlayer() ) - return; - - CBasePlayer *pPlayer = (CBasePlayer *)pOther; - - // Must be a valid pickup scenario (no blocking). Though this is a more expensive - // check than some that follow, this has to be first Obecause it's the only one - // that inhibits firing the output OnCacheInteraction. - if ( ItemCanBeTouchedByPlayer( pPlayer ) == false ) - return; - - m_OnCacheInteraction.FireOutput(pOther, this); - - // Can I even pick stuff up? - if ( !pPlayer->IsAllowedToPickupWeapons() ) - return; - - // ok, a player is touching this item, but can he have it? - if ( !g_pGameRules->CanHaveItem( pPlayer, this ) ) - { - // no? Ignore the touch. - return; - } - - if ( MyTouch( pPlayer ) ) - { - m_OnPlayerTouch.FireOutput(pOther, this); - - SetTouch( NULL ); - SetThink( NULL ); - - // player grabbed the item. - g_pGameRules->PlayerGotItem( pPlayer, this ); - if ( g_pGameRules->ItemShouldRespawn( this ) == GR_ITEM_RESPAWN_YES ) - { - Respawn(); - } - else - { - UTIL_Remove( this ); - -#ifdef HL2MP - HL2MPRules()->RemoveLevelDesignerPlacedObject( this ); -#endif - } - } - else if (gEvilImpulse101) - { - UTIL_Remove( this ); - } -} - -CBaseEntity* CItem::Respawn( void ) -{ - SetTouch( NULL ); - AddEffects( EF_NODRAW ); - - VPhysicsDestroyObject(); - - SetMoveType( MOVETYPE_NONE ); - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_TRIGGER ); - - UTIL_SetOrigin( this, g_pGameRules->VecItemRespawnSpot( this ) );// blip to whereever you should respawn. - SetAbsAngles( g_pGameRules->VecItemRespawnAngles( this ) );// set the angles. - -#if !defined( TF_DLL ) - UTIL_DropToFloor( this, MASK_SOLID ); -#endif - - RemoveAllDecals(); //remove any decals - - SetThink ( &CItem::Materialize ); - SetNextThink( gpGlobals->curtime + g_pGameRules->FlItemRespawnTime( this ) ); - return this; -} - -void CItem::Materialize( void ) -{ - CreateItemVPhysicsObject(); - - if ( IsEffectActive( EF_NODRAW ) ) - { - // changing from invisible state to visible. - -#ifdef HL2MP - EmitSound( "AlyxEmp.Charge" ); -#else - EmitSound( "Item.Materialize" ); -#endif - RemoveEffects( EF_NODRAW ); - DoMuzzleFlash(); - } - - SetTouch( &CItem::ItemTouch ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CItem::Precache() -{ - BaseClass::Precache(); - - PrecacheScriptSound( "Item.Materialize" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPhysGunUser - -// PICKED_UP_BY_CANNON - -//----------------------------------------------------------------------------- -void CItem::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) -{ - m_OnCacheInteraction.FireOutput(pPhysGunUser, this); - - if ( reason == PICKED_UP_BY_CANNON ) - { - // Expand the pickup box - CollisionProp()->UseTriggerBounds( true, ITEM_PICKUP_BOX_BLOAT * 2 ); - - if( m_pConstraint != NULL ) - { - physenv->DestroyConstraint( m_pConstraint ); - m_pConstraint = NULL; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPhysGunUser - -// reason - -//----------------------------------------------------------------------------- -void CItem::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t reason ) -{ - // Restore the pickup box to the original - CollisionProp()->UseTriggerBounds( true, ITEM_PICKUP_BOX_BLOAT ); -} diff --git a/game/server/items.h b/game/server/items.h deleted file mode 100644 index 40a018065..000000000 --- a/game/server/items.h +++ /dev/null @@ -1,95 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ITEMS_H -#define ITEMS_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "entityoutput.h" -#include "player_pickup.h" -#include "vphysics/constraints.h" - - -// Armor given by a battery -#define MAX_NORMAL_BATTERY 100 - -// Ammo counts given by ammo items -#define SIZE_AMMO_PISTOL 20 -#define SIZE_AMMO_PISTOL_LARGE 100 -#define SIZE_AMMO_SMG1 45 -#define SIZE_AMMO_SMG1_LARGE 225 -#define SIZE_AMMO_AR2 20 -#define SIZE_AMMO_AR2_LARGE 100 -#define SIZE_AMMO_RPG_ROUND 1 -#define SIZE_AMMO_SMG1_GRENADE 1 -#define SIZE_AMMO_BUCKSHOT 20 -#define SIZE_AMMO_357 6 -#define SIZE_AMMO_357_LARGE 20 -#define SIZE_AMMO_CROSSBOW 6 -#define SIZE_AMMO_AR2_ALTFIRE 1 - -#define SF_ITEM_START_CONSTRAINED 0x00000001 - - -class CItem : public CBaseAnimating, public CDefaultPlayerPickupVPhysics -{ -public: - DECLARE_CLASS( CItem, CBaseAnimating ); - - CItem(); - - virtual void Spawn( void ); - virtual void Precache(); - - virtual CBaseEntity* Respawn( void ); - void ItemTouch( CBaseEntity *pOther ); - virtual void Materialize( void ); - virtual bool MyTouch( CBasePlayer *pPlayer ) { return false; }; - - // Become touchable when we are at rest - virtual void OnEntityEvent( EntityEvent_t event, void *pEventData ); - - // Activate when at rest, but don't allow pickup until then - void ActivateWhenAtRest(); - - // IPlayerPickupVPhysics - virtual void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason = PICKED_UP_BY_CANNON ); - virtual void OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t reason ); - - virtual int ObjectCaps() { return BaseClass::ObjectCaps() | FCAP_IMPULSE_USE | FCAP_WCEDIT_POSITION; }; - virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - Vector GetOriginalSpawnOrigin( void ) { return m_vOriginalSpawnOrigin; } - QAngle GetOriginalSpawnAngles( void ) { return m_vOriginalSpawnAngles; } - void SetOriginalSpawnOrigin( const Vector& origin ) { m_vOriginalSpawnOrigin = origin; } - void SetOriginalSpawnAngles( const QAngle& angles ) { m_vOriginalSpawnAngles = angles; } - bool CreateItemVPhysicsObject( void ); - bool ItemCanBeTouchedByPlayer( CBasePlayer *pPlayer ); - -#if defined( HL2MP ) - void FallThink( void ); - float m_flNextResetCheckTime; -#endif - - DECLARE_DATADESC(); -private: - void ComeToRest( void ); - -private: - bool m_bActivateWhenAtRest; - COutputEvent m_OnPlayerTouch; - COutputEvent m_OnCacheInteraction; - - Vector m_vOriginalSpawnOrigin; - QAngle m_vOriginalSpawnAngles; - - IPhysicsConstraint *m_pConstraint; -}; - -#endif // ITEMS_H diff --git a/game/server/lightglow.cpp b/game/server/lightglow.cpp deleted file mode 100644 index fb6afb4c4..000000000 --- a/game/server/lightglow.cpp +++ /dev/null @@ -1,136 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "baseentity.h" -#include "sendproxy.h" -#include "sun_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define LIGHTGLOW_MAXDIST_BITS 16 -#define LIGHTGLOW_MAXDIST_MAX_VALUE ((1 << LIGHTGLOW_MAXDIST_BITS)-1) - -#define LIGHTGLOW_OUTERMAXDIST_BITS 16 -#define LIGHTGLOW_OUTERMAXDIST_MAX_VALUE ((1 << LIGHTGLOW_OUTERMAXDIST_BITS)-1) - -class CLightGlow : public CBaseEntity -{ -public: - DECLARE_CLASS( CLightGlow, CBaseEntity ); - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - CLightGlow(); - - virtual void Spawn( void ); - virtual void Activate( void ); - virtual int UpdateTransmitState( void ); - - void InputColor(inputdata_t &data); - -public: - CNetworkVar( int, m_nHorizontalSize ); - CNetworkVar( int, m_nVerticalSize ); - CNetworkVar( int, m_nMinDist ); - CNetworkVar( int, m_nMaxDist ); - CNetworkVar( int, m_nOuterMaxDist ); - - CNetworkVar( float, m_flGlowProxySize ); - CNetworkVar( float, m_flHDRColorScale ); -}; - -extern void SendProxy_Angles( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); - -IMPLEMENT_SERVERCLASS_ST_NOBASE( CLightGlow, DT_LightGlow ) - SendPropInt( SENDINFO(m_clrRender), 32, SPROP_UNSIGNED, SendProxy_Color32ToInt ), - SendPropInt( SENDINFO(m_nHorizontalSize), 16, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nVerticalSize), 16, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nMinDist), 16, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nMaxDist), LIGHTGLOW_MAXDIST_BITS, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nOuterMaxDist), LIGHTGLOW_OUTERMAXDIST_BITS, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_spawnflags), 8, SPROP_UNSIGNED ), - SendPropVector(SENDINFO(m_vecOrigin), -1, SPROP_COORD ), - SendPropQAngles (SENDINFO(m_angRotation), 13, 0, SendProxy_Angles ), - SendPropEHandle (SENDINFO_NAME(m_hMoveParent, moveparent)), - SendPropFloat( SENDINFO(m_flGlowProxySize ), 6, SPROP_ROUNDUP, 0.0f, 64.0f ), - SendPropFloat( SENDINFO_NAME( m_flHDRColorScale, HDRColorScale ), 0, SPROP_NOSCALE, 0.0f, 100.0f ), -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( env_lightglow, CLightGlow ); - -BEGIN_DATADESC( CLightGlow ) - - DEFINE_KEYFIELD( m_nVerticalSize, FIELD_INTEGER, "VerticalGlowSize" ), - DEFINE_KEYFIELD( m_nHorizontalSize, FIELD_INTEGER, "HorizontalGlowSize" ), - DEFINE_KEYFIELD( m_nMinDist, FIELD_INTEGER, "MinDist" ), - DEFINE_KEYFIELD( m_nMaxDist, FIELD_INTEGER, "MaxDist" ), - DEFINE_KEYFIELD( m_nOuterMaxDist, FIELD_INTEGER, "OuterMaxDist" ), - DEFINE_KEYFIELD( m_flGlowProxySize, FIELD_FLOAT, "GlowProxySize" ), - DEFINE_KEYFIELD( m_flHDRColorScale, FIELD_FLOAT, "HDRColorScale" ), - DEFINE_INPUTFUNC( FIELD_COLOR32, "Color", InputColor ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CLightGlow::CLightGlow( void ) -{ - m_nHorizontalSize = 0.0f; - m_nVerticalSize = 0.0f; - m_nMinDist = 0.0f; - m_nMaxDist = 0.0f; - - m_flGlowProxySize = 2.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CLightGlow::Spawn( void ) -{ - BaseClass::Spawn(); - - // No model but we still need to force this! - AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); -} - -//----------------------------------------------------------------------------- -// Purpose: Always transmit light glows to clients to avoid spikes as we enter -// or leave PVS. Done because we often have many glows in an area. -//----------------------------------------------------------------------------- -int CLightGlow::UpdateTransmitState( void ) -{ - return SetTransmitState( FL_EDICT_ALWAYS ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CLightGlow::Activate() -{ - BaseClass::Activate(); - - if ( m_nMaxDist > LIGHTGLOW_MAXDIST_MAX_VALUE ) - { - Warning( "env_lightglow maxdist too large (%d should be %d).\n", m_nMaxDist, LIGHTGLOW_MAXDIST_MAX_VALUE ); - m_nMaxDist = LIGHTGLOW_MAXDIST_MAX_VALUE; - } - - if ( m_nOuterMaxDist > LIGHTGLOW_OUTERMAXDIST_MAX_VALUE ) - { - Warning( "env_lightglow outermaxdist too large (%d should be %d).\n", m_nOuterMaxDist, LIGHTGLOW_OUTERMAXDIST_MAX_VALUE ); - m_nOuterMaxDist = LIGHTGLOW_OUTERMAXDIST_MAX_VALUE; - } -} - -void CLightGlow::InputColor(inputdata_t &inputdata) -{ - m_clrRender = inputdata.value.Color32(); -} diff --git a/game/server/lights.cpp b/game/server/lights.cpp deleted file mode 100644 index 99a8f0dba..000000000 --- a/game/server/lights.cpp +++ /dev/null @@ -1,265 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: spawn and think functions for editor-placed lights -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "lights.h" -#include "world.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -LINK_ENTITY_TO_CLASS( light, CLight ); - -BEGIN_DATADESC( CLight ) - - DEFINE_FIELD( m_iCurrentFade, FIELD_CHARACTER), - DEFINE_FIELD( m_iTargetFade, FIELD_CHARACTER), - - DEFINE_KEYFIELD( m_iStyle, FIELD_INTEGER, "style" ), - DEFINE_KEYFIELD( m_iDefaultStyle, FIELD_INTEGER, "defaultstyle" ), - DEFINE_KEYFIELD( m_iszPattern, FIELD_STRING, "pattern" ), - - // Fuctions - DEFINE_FUNCTION( FadeThink ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_STRING, "SetPattern", InputSetPattern ), - DEFINE_INPUTFUNC( FIELD_STRING, "FadeToPattern", InputFadeToPattern ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - -END_DATADESC() - - - -// -// Cache user-entity-field values until spawn is called. -// -bool CLight::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "pitch")) - { - QAngle angles = GetAbsAngles(); - angles.x = atof(szValue); - SetAbsAngles( angles ); - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } - - return true; -} - -// Light entity -// If targeted, it will toggle between on or off. -void CLight::Spawn( void ) -{ - if (!GetEntityName()) - { // inert light - UTIL_Remove( this ); - return; - } - - if (m_iStyle >= 32) - { - if ( m_iszPattern == NULL_STRING && m_iDefaultStyle > 0 ) - { - m_iszPattern = MAKE_STRING(GetDefaultLightstyleString(m_iDefaultStyle)); - } - - if (FBitSet(m_spawnflags, SF_LIGHT_START_OFF)) - engine->LightStyle(m_iStyle, "a"); - else if (m_iszPattern != NULL_STRING) - engine->LightStyle(m_iStyle, (char *)STRING( m_iszPattern )); - else - engine->LightStyle(m_iStyle, "m"); - } -} - - -void CLight::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - if (m_iStyle >= 32) - { - if ( !ShouldToggle( useType, !FBitSet(m_spawnflags, SF_LIGHT_START_OFF) ) ) - return; - - Toggle(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Turn the light on -//----------------------------------------------------------------------------- -void CLight::TurnOn( void ) -{ - if ( m_iszPattern != NULL_STRING ) - { - engine->LightStyle( m_iStyle, (char *) STRING( m_iszPattern ) ); - } - else - { - engine->LightStyle( m_iStyle, "m" ); - } - - CLEARBITS( m_spawnflags, SF_LIGHT_START_OFF ); -} - -//----------------------------------------------------------------------------- -// Purpose: Turn the light off -//----------------------------------------------------------------------------- -void CLight::TurnOff( void ) -{ - engine->LightStyle( m_iStyle, "a" ); - SETBITS( m_spawnflags, SF_LIGHT_START_OFF ); -} - -//----------------------------------------------------------------------------- -// Purpose: Toggle the light on/off -//----------------------------------------------------------------------------- -void CLight::Toggle( void ) -{ - //Toggle it - if ( FBitSet( m_spawnflags, SF_LIGHT_START_OFF ) ) - { - TurnOn(); - } - else - { - TurnOff(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Handle the "turnon" input handler -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CLight::InputTurnOn( inputdata_t &inputdata ) -{ - TurnOn(); -} - -//----------------------------------------------------------------------------- -// Purpose: Handle the "turnoff" input handler -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CLight::InputTurnOff( inputdata_t &inputdata ) -{ - TurnOff(); -} - -//----------------------------------------------------------------------------- -// Purpose: Handle the "toggle" input handler -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CLight::InputToggle( inputdata_t &inputdata ) -{ - Toggle(); -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for setting a light pattern -//----------------------------------------------------------------------------- -void CLight::InputSetPattern( inputdata_t &inputdata ) -{ - m_iszPattern = inputdata.value.StringID(); - engine->LightStyle(m_iStyle, (char *)STRING( m_iszPattern )); - - // Light is on if pattern is set - CLEARBITS(m_spawnflags, SF_LIGHT_START_OFF); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for fading from first value in old pattern to -// first value in new pattern -//----------------------------------------------------------------------------- -void CLight::InputFadeToPattern( inputdata_t &inputdata ) -{ - m_iCurrentFade = (STRING(m_iszPattern))[0]; - m_iTargetFade = inputdata.value.String()[0]; - m_iszPattern = inputdata.value.StringID(); - SetThink(&CLight::FadeThink); - SetNextThink( gpGlobals->curtime ); - - // Light is on if pattern is set - CLEARBITS(m_spawnflags, SF_LIGHT_START_OFF); -} - - -//------------------------------------------------------------------------------ -// Purpose : Fade light to new starting pattern value then stop thinking -//------------------------------------------------------------------------------ -void CLight::FadeThink(void) -{ - if (m_iCurrentFade < m_iTargetFade) - { - m_iCurrentFade++; - } - else if (m_iCurrentFade > m_iTargetFade) - { - m_iCurrentFade--; - } - - // If we're done fading instantiate our light pattern and stop thinking - if (m_iCurrentFade == m_iTargetFade) - { - engine->LightStyle(m_iStyle, (char *)STRING( m_iszPattern )); - SetNextThink( TICK_NEVER_THINK ); - } - // Otherwise instantiate our current fade value and keep thinking - else - { - char sCurString[2]; - sCurString[0] = m_iCurrentFade; - sCurString[1] = '\0'; - engine->LightStyle(m_iStyle, sCurString); - - // UNDONE: Consider making this settable war to control fade speed - SetNextThink( gpGlobals->curtime + 0.1f ); - } -} - -// -// shut up spawn functions for new spotlights -// -LINK_ENTITY_TO_CLASS( light_spot, CLight ); -LINK_ENTITY_TO_CLASS( light_glspot, CLight ); - - -class CEnvLight : public CLight -{ -public: - DECLARE_CLASS( CEnvLight, CLight ); - - bool KeyValue( const char *szKeyName, const char *szValue ); - void Spawn( void ); -}; - -LINK_ENTITY_TO_CLASS( light_environment, CEnvLight ); - -bool CEnvLight::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "_light")) - { - // nothing - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } - - return true; -} - - -void CEnvLight::Spawn( void ) -{ - BaseClass::Spawn( ); -} diff --git a/game/server/lights.h b/game/server/lights.h deleted file mode 100644 index d16684786..000000000 --- a/game/server/lights.h +++ /dev/null @@ -1,48 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef LIGHTS_H -#define LIGHTS_H -#ifdef _WIN32 -#pragma once -#endif - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CLight : public CPointEntity -{ -public: - DECLARE_CLASS( CLight, CPointEntity ); - - bool KeyValue( const char *szKeyName, const char *szValue ); - void Spawn( void ); - void FadeThink( void ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - void TurnOn( void ); - void TurnOff( void ); - void Toggle( void ); - - // Input handlers - void InputSetPattern( inputdata_t &inputdata ); - void InputFadeToPattern( inputdata_t &inputdata ); - - void InputToggle( inputdata_t &inputdata ); - void InputTurnOn( inputdata_t &inputdata ); - void InputTurnOff( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - -private: - int m_iStyle; - int m_iDefaultStyle; - string_t m_iszPattern; - char m_iCurrentFade; - char m_iTargetFade; -}; - -#endif // LIGHTS_H diff --git a/game/server/locksounds.h b/game/server/locksounds.h deleted file mode 100644 index c4fb242aa..000000000 --- a/game/server/locksounds.h +++ /dev/null @@ -1,37 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Defines a structure common to buttons and doors for playing locked -// and unlocked sounds. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef LOCKSOUNDS_H -#define LOCKSOUNDS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "datamap.h" - - -struct locksound_t // sounds that doors and buttons make when locked/unlocked -{ - DECLARE_DATADESC(); - - string_t sLockedSound; // sound a door makes when it's locked - string_t sLockedSentence; // sentence group played when door is locked - string_t sUnlockedSound; // sound a door makes when it's unlocked - string_t sUnlockedSentence; // sentence group played when door is unlocked - - int iLockedSentence; // which sentence in sentence group to play next - int iUnlockedSentence; // which sentence in sentence group to play next - - float flwaitSound; // time delay between playing consecutive 'locked/unlocked' sounds - float flwaitSentence; // time delay between playing consecutive sentences - byte bEOFLocked; // true if hit end of list of locked sentences - byte bEOFUnlocked; // true if hit end of list of unlocked sentences -}; - - -#endif // LOCKSOUNDS_H diff --git a/game/server/logic_achievement.cpp b/game/server/logic_achievement.cpp deleted file mode 100644 index 52eb605c0..000000000 --- a/game/server/logic_achievement.cpp +++ /dev/null @@ -1,182 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ==== -// -// Defines a logical entity which passes achievement related events to the gamerules system. - -#include "cbase.h" -#include "gamerules.h" -#include "entityinput.h" -#include "entityoutput.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -/* - These are the string choices in the FGD: - - ACHIEVEMENT_EVENT_HL2_HIT_CANCOP_WITHCAN - ACHIEVEMENT_EVENT_HL2_ESCAPE_APARTMENTRAID - ACHIEVEMENT_EVENT_HL2_FIND_ONEGMAN - ACHIEVEMENT_EVENT_HL2_BREAK_MINITELEPORTER - ACHIEVEMENT_EVENT_HL2_GET_PISTOL - ACHIEVEMENT_EVENT_HL2_GET_AIRBOAT - ACHIEVEMENT_EVENT_HL2_GET_AIRBOATGUN - ACHIEVEMENT_EVENT_HL2_FIND_VORTIGAUNTCAVE - ACHIEVEMENT_EVENT_HL2_KILL_CHOPPER - ACHIEVEMENT_EVENT_HL2_FIND_HEVFACEPLATE - ACHIEVEMENT_EVENT_HL2_GET_GRAVITYGUN - ACHIEVEMENT_EVENT_HL2_MAKEABASKET - ACHIEVEMENT_EVENT_HL2_BEAT_RAVENHOLM_NOWEAPONS_START - ACHIEVEMENT_EVENT_HL2_BEAT_RAVENHOLM_NOWEAPONS_END - ACHIEVEMENT_EVENT_HL2_BEAT_CEMETERY - ACHIEVEMENT_EVENT_HL2_KILL_ENEMIES_WITHCRANE - ACHIEVEMENT_EVENT_HL2_PIN_SOLDIER_TOBILLBOARD - ACHIEVEMENT_EVENT_HL2_KILL_ODESSAGUNSHIP - ACHIEVEMENT_EVENT_HL2_BEAT_DONTTOUCHSAND - ACHIEVEMENT_EVENT_HL2_ENTER_NOVAPROSPEKT, - ACHIEVEMENT_EVENT_HL2_BEAT_TURRETSTANDOFF2 - ACHIEVEMENT_EVENT_HL2_BEAT_NOVAPROSPEKT - ACHIEVEMENT_EVENT_HL2_BEAT_TOXICTUNNEL - ACHIEVEMENT_EVENT_HL2_BEAT_PLAZASTANDOFF - ACHIEVEMENT_EVENT_HL2_KILL_ALLC17SNIPERS - ACHIEVEMENT_EVENT_HL2_BEAT_SUPRESSIONDEVICE - ACHIEVEMENT_EVENT_HL2_BEAT_C17STRIDERSTANDOFF - ACHIEVEMENT_EVENT_HL2_REACH_BREENSOFFICE - ACHIEVEMENT_EVENT_HL2_FIND_LAMDACACHE - - // EP1 - ACHIEVEMENT_EVENT_EP1_BEAT_MAINELEVATOR - ACHIEVEMENT_EVENT_EP1_BEAT_CITADELCORE - ACHIEVEMENT_EVENT_EP1_BEAT_CITADELCORE_NOSTALKERKILLS - ACHIEVEMENT_EVENT_EP1_BEAT_GARAGEELEVATORSTANDOFF - ACHIEVEMENT_EVENT_EP1_KILL_ENEMIES_WITHSNIPERALYX - ACHIEVEMENT_EVENT_EP1_BEAT_HOSPITALATTICGUNSHIP - ACHIEVEMENT_EVENT_EP1_BEAT_CITIZENESCORT_NOCITIZENDEATHS - - // EP2 - ACHIEVEMENT_EVENT_EP2_BREAK_ALLWEBS - ACHIEVEMENT_EVENT_EP2_BEAT_ANTLIONINVASION - ACHIEVEMENT_EVENT_EP2_BEAT_ANTLIONGUARDS - ACHIEVEMENT_EVENT_EP2_BEAT_HUNTERAMBUSH - ACHIEVEMENT_EVENT_EP2_KILL_COMBINECANNON - ACHIEVEMENT_EVENT_EP2_FIND_RADAR_CACHE - ACHIEVEMENT_EVENT_EP2_BEAT_RACEWITHDOG - ACHIEVEMENT_EVENT_EP2_BEAT_ROCKETCACHEPUZZLE - ACHIEVEMENT_EVENT_EP2_BEAT_WHITEFORESTINN - ACHIEVEMENT_EVENT_EP2_PUT_ITEMINROCKET - ACHIEVEMENT_EVENT_EP2_BEAT_MISSILESILO2 - ACHIEVEMENT_EVENT_EP2_BEAT_OUTLAND12_NOBUILDINGSDESTROYED - - // PORTAL - ACHIEVEMENT_EVENT_PORTAL_GET_PORTALGUNS - ACHIEVEMENT_EVENT_PORTAL_KILL_COMPANIONCUBE - ACHIEVEMENT_EVENT_PORTAL_ESCAPE_TESTCHAMBERS - ACHIEVEMENT_EVENT_PORTAL_BEAT_GAME -*/ - - -// Allows map logic to send achievement related events to the achievement system. -class CLogicAchievement : public CLogicalEntity -{ -public: - DECLARE_CLASS( CLogicAchievement, CLogicalEntity ); - - CLogicAchievement(); - -protected: - - // Inputs - void InputFireEvent( inputdata_t &inputdata ); - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - void InputToggle( inputdata_t &inputdata ); - - bool m_bDisabled; - string_t m_iszAchievementEventID; // Which achievement event this entity marks - - COutputEvent m_OnFired; - - DECLARE_DATADESC(); -}; - - -LINK_ENTITY_TO_CLASS( logic_achievement, CLogicAchievement ); - - -BEGIN_DATADESC( CLogicAchievement ) - - DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ), - DEFINE_KEYFIELD( m_iszAchievementEventID, FIELD_STRING, "AchievementEvent" ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "FireEvent", InputFireEvent ), - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - - // Outputs - DEFINE_OUTPUT( m_OnFired, "OnFired" ), - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Purpose: Constructor. -//----------------------------------------------------------------------------- -CLogicAchievement::CLogicAchievement(void) -{ - m_iszAchievementEventID = NULL_STRING; -} - -#define ACHIEVEMENT_PREFIX "ACHIEVEMENT_EVENT_" - -//----------------------------------------------------------------------------- -// Purpose: Sends the achievement event to the achievement marking system. -//----------------------------------------------------------------------------- -void CLogicAchievement::InputFireEvent( inputdata_t &inputdata ) -{ - // If we're active, and our string matched a valid achievement ID - if ( !m_bDisabled && m_iszAchievementEventID != NULL_STRING) - { - m_OnFired.FireOutput( inputdata.pActivator, this ); - - char const *pchName = STRING( m_iszAchievementEventID ); - - int nPrefixLen = Q_strlen( ACHIEVEMENT_PREFIX ); - if ( !Q_strnicmp( pchName, ACHIEVEMENT_PREFIX, nPrefixLen ) ) - { - // Skip the prefix - pchName += nPrefixLen; - if ( pchName && *pchName ) - { - CBroadcastRecipientFilter filter; - g_pGameRules->MarkAchievement( filter, pchName ); - } - } - } -} - -//------------------------------------------------------------------------------ -// Purpose: Turns on the relay, allowing it to fire outputs. -//------------------------------------------------------------------------------ -void CLogicAchievement::InputEnable( inputdata_t &inputdata ) -{ - m_bDisabled = false; -} - -//------------------------------------------------------------------------------ -// Purpose: Turns off the relay, preventing it from firing outputs. -//------------------------------------------------------------------------------ -void CLogicAchievement::InputDisable( inputdata_t &inputdata ) -{ - m_bDisabled = true; -} - - -//------------------------------------------------------------------------------ -// Purpose: Toggles the enabled/disabled state of the relay. -//------------------------------------------------------------------------------ -void CLogicAchievement::InputToggle( inputdata_t &inputdata ) -{ - m_bDisabled = !m_bDisabled; -} diff --git a/game/server/logic_measure_movement.cpp b/game/server/logic_measure_movement.cpp deleted file mode 100644 index 4c66c5221..000000000 --- a/game/server/logic_measure_movement.cpp +++ /dev/null @@ -1,257 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: This will measure the movement of a target entity and move -// another entity to match the movement of the first. -// -//=============================================================================// - -#include "cbase.h" -#include "baseentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// This will measure the movement of a target entity and move -// another entity to match the movement of the first. -//----------------------------------------------------------------------------- -class CLogicMeasureMovement : public CLogicalEntity -{ - DECLARE_DATADESC(); - DECLARE_CLASS( CLogicMeasureMovement, CLogicalEntity ); - -public: - virtual void Activate(); - -private: - void SetMeasureTarget( const char *pName ); - void SetMeasureReference( const char *pName ); - void SetTarget( const char *pName ); - void SetTargetReference( const char *pName ); - - void InputSetMeasureTarget( inputdata_t &inputdata ); - void InputSetMeasureReference( inputdata_t &inputdata ); - void InputSetTarget( inputdata_t &inputdata ); - void InputSetTargetReference( inputdata_t &inputdata ); - void InputSetTargetScale( inputdata_t &inputdata ); - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - - void MeasureThink(); - -private: - enum - { - MEASURE_POSITION = 0, - MEASURE_EYE_POSITION, - }; - - string_t m_strMeasureTarget; - string_t m_strMeasureReference; - string_t m_strTargetReference; - - EHANDLE m_hMeasureTarget; - EHANDLE m_hMeasureReference; - EHANDLE m_hTarget; - EHANDLE m_hTargetReference; - - float m_flScale; - int m_nMeasureType; -}; - - -LINK_ENTITY_TO_CLASS( logic_measure_movement, CLogicMeasureMovement ); - - -BEGIN_DATADESC( CLogicMeasureMovement ) - - DEFINE_KEYFIELD( m_strMeasureTarget, FIELD_STRING, "MeasureTarget" ), - DEFINE_KEYFIELD( m_strMeasureReference, FIELD_STRING, "MeasureReference" ), - DEFINE_KEYFIELD( m_strTargetReference, FIELD_STRING, "TargetReference" ), - DEFINE_KEYFIELD( m_flScale, FIELD_FLOAT, "TargetScale" ), - DEFINE_KEYFIELD( m_nMeasureType, FIELD_INTEGER, "MeasureType" ), - - DEFINE_FIELD( m_hMeasureTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_hMeasureReference, FIELD_EHANDLE ), - DEFINE_FIELD( m_hTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_hTargetReference, FIELD_EHANDLE ), - - DEFINE_INPUTFUNC( FIELD_STRING, "SetMeasureTarget", InputSetMeasureTarget ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetMeasureReference", InputSetMeasureReference ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetTarget", InputSetTarget ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetTargetReference", InputSetTargetReference ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetTargetScale", InputSetTargetScale ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - - DEFINE_THINKFUNC( MeasureThink ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Methods to change various targets -//----------------------------------------------------------------------------- -void CLogicMeasureMovement::Activate() -{ - BaseClass::Activate(); - - SetMeasureTarget( STRING(m_strMeasureTarget) ); - SetMeasureReference( STRING(m_strMeasureReference) ); - SetTarget( STRING(m_target) ); - SetTargetReference( STRING(m_strTargetReference) ); - - SetThink( &CLogicMeasureMovement::MeasureThink ); - SetNextThink( gpGlobals->curtime + TICK_INTERVAL ); -} - - -//----------------------------------------------------------------------------- -// Sets the name -//----------------------------------------------------------------------------- -void CLogicMeasureMovement::SetMeasureTarget( const char *pName ) -{ - m_hMeasureTarget = gEntList.FindEntityByName( NULL, pName ); - if ( !m_hMeasureTarget ) - { - if ( Q_strnicmp( STRING(m_strMeasureTarget), "!player", 8 ) ) - { - Warning("logic_measure_movement: Unable to find measure target entity %s\n", pName ); - } - } -} - -void CLogicMeasureMovement::SetMeasureReference( const char *pName ) -{ - m_hMeasureReference = gEntList.FindEntityByName( NULL, pName ); - if ( !m_hMeasureReference ) - { - Warning("logic_measure_movement: Unable to find measure reference entity %s\n", pName ); - } -} - -void CLogicMeasureMovement::SetTarget( const char *pName ) -{ - m_hTarget = gEntList.FindEntityByName( NULL, pName ); - if ( !m_hTarget ) - { - Warning("logic_measure_movement: Unable to find movement target entity %s\n", pName ); - } -} - -void CLogicMeasureMovement::SetTargetReference( const char *pName ) -{ - m_hTargetReference = gEntList.FindEntityByName( NULL, pName ); - if ( !m_hTargetReference ) - { - Warning("logic_measure_movement: Unable to find movement reference entity %s\n", pName ); - } -} - - -//----------------------------------------------------------------------------- -// Apply movement -//----------------------------------------------------------------------------- -void CLogicMeasureMovement::MeasureThink( ) -{ - // FIXME: This is a hack to make measuring !player simpler. The player isn't - // created at Activate time, so m_hMeasureTarget may be NULL because of that. - if ( !m_hMeasureTarget.Get() && !Q_strnicmp( STRING(m_strMeasureTarget), "!player", 8 ) ) - { - SetMeasureTarget( STRING(m_strMeasureTarget) ); - } - - // Make sure all entities are valid - if ( m_hMeasureTarget.Get() && m_hMeasureReference.Get() && m_hTarget.Get() && m_hTargetReference.Get() ) - { - matrix3x4_t matRefToMeasure, matWorldToMeasure; - switch( m_nMeasureType ) - { - case MEASURE_POSITION: - MatrixInvert( m_hMeasureTarget->EntityToWorldTransform(), matWorldToMeasure ); - break; - - case MEASURE_EYE_POSITION: - AngleIMatrix( m_hMeasureTarget->EyeAngles(), m_hMeasureTarget->EyePosition(), matWorldToMeasure ); - break; - - // FIXME: Could add attachment point measurement here easily - } - - ConcatTransforms( matWorldToMeasure, m_hMeasureReference->EntityToWorldTransform(), matRefToMeasure ); - - // Apply the scale factor - if ( ( m_flScale != 0.0f ) && ( m_flScale != 1.0f ) ) - { - Vector vecTranslation; - MatrixGetColumn( matRefToMeasure, 3, vecTranslation ); - vecTranslation /= m_flScale; - MatrixSetColumn( vecTranslation, 3, matRefToMeasure ); - } - - // Now apply the new matrix to the new reference point - matrix3x4_t matMeasureToRef, matNewTargetToWorld; - MatrixInvert( matRefToMeasure, matMeasureToRef ); - - ConcatTransforms( m_hTargetReference->EntityToWorldTransform(), matMeasureToRef, matNewTargetToWorld ); - - Vector vecNewOrigin; - QAngle vecNewAngles; - MatrixAngles( matNewTargetToWorld, vecNewAngles, vecNewOrigin ); - m_hTarget->SetAbsOrigin( vecNewOrigin ); - m_hTarget->SetAbsAngles( vecNewAngles ); - } - - SetNextThink( gpGlobals->curtime + TICK_INTERVAL ); -} - - -//----------------------------------------------------------------------------- -// Enable, disable -//----------------------------------------------------------------------------- -void CLogicMeasureMovement::InputEnable( inputdata_t &inputdata ) -{ - SetThink( &CLogicMeasureMovement::MeasureThink ); - SetNextThink( gpGlobals->curtime + TICK_INTERVAL ); -} - -void CLogicMeasureMovement::InputDisable( inputdata_t &inputdata ) -{ - SetThink( NULL ); -} - - -//----------------------------------------------------------------------------- -// Methods to change various targets -//----------------------------------------------------------------------------- -void CLogicMeasureMovement::InputSetMeasureTarget( inputdata_t &inputdata ) -{ - m_strMeasureTarget = MAKE_STRING( inputdata.value.String() ); - SetMeasureTarget( inputdata.value.String() ); - SetTarget( STRING(m_target) ); - SetTargetReference( STRING(m_strTargetReference) ); -} - -void CLogicMeasureMovement::InputSetMeasureReference( inputdata_t &inputdata ) -{ - m_strMeasureReference = MAKE_STRING( inputdata.value.String() ); - SetMeasureReference( inputdata.value.String() ); -} - -void CLogicMeasureMovement::InputSetTarget( inputdata_t &inputdata ) -{ - m_target = MAKE_STRING( inputdata.value.String() ); - SetTarget( inputdata.value.String() ); -} - -void CLogicMeasureMovement::InputSetTargetReference( inputdata_t &inputdata ) -{ - m_strTargetReference = MAKE_STRING( inputdata.value.String() ); - SetTargetReference( inputdata.value.String() ); -} - -void CLogicMeasureMovement::InputSetTargetScale( inputdata_t &inputdata ) -{ - m_flScale = inputdata.value.Float(); -} diff --git a/game/server/logic_mirror_movement.cpp b/game/server/logic_mirror_movement.cpp deleted file mode 100644 index 5de4d645c..000000000 --- a/game/server/logic_mirror_movement.cpp +++ /dev/null @@ -1,198 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Mirrors the movement of a camera about a given point. -// -//=============================================================================// - -#include "cbase.h" -#include "baseentity.h" -#include "modelentities.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -////////////////////////////////////////////////////////////////////////// -// CLogicMirrorMovement -// This will record the vector offset of an entity's center from a given reference point -// (most likely the center of a mirror or portal) and place an entity (most likely a point camera) -// at a the same offset, mirrored about the reference point and orientation. -////////////////////////////////////////////////////////////////////////// -class CLogicMirrorMovement : public CLogicalEntity -{ - DECLARE_DATADESC(); - DECLARE_CLASS( CLogicMirrorMovement, CLogicalEntity ); - -private: - void SetMirrorTarget( const char *pName ); // Set entity to watch and mirror (ex. the player) - void SetTarget( const char *pName ); // Set entity to move based on the Mirror Target entity (ex. a point_camera) - void SetMirrorRelative( const char* pName ); // Set the point about which to measure an offset to orient based upon (ex. portal 1) - void SetRemoteTarget ( const char *pName ); // Entity's orientation/location from which to offset the movement target (ex. portal 2) - void SetDrawingSurface ( const char *pName ); - - void InputSetMirrorTarget( inputdata_t &inputdata ); - void InputSetTarget( inputdata_t &inputdata ); - void InputSetRemoteTarget ( inputdata_t &inputdata ); - void InputSetMirrorRelative ( inputdata_t &inputdata ); - - void Think(); - virtual void Activate(); - - string_t m_strMirrorTarget; - string_t m_strRemoteTarget; - string_t m_strMirrorRelative; - - EHANDLE m_hRemoteTarget; - EHANDLE m_hMirrorTarget; - EHANDLE m_hMovementTarget; - EHANDLE m_hMirrorRelative; - -}; - -LINK_ENTITY_TO_CLASS( logic_mirror_movement, CLogicMirrorMovement ); - - -BEGIN_DATADESC( CLogicMirrorMovement ) - -DEFINE_KEYFIELD( m_strMirrorTarget, FIELD_STRING, "MirrorTarget" ), -DEFINE_KEYFIELD( m_strRemoteTarget, FIELD_STRING, "RemoteTarget" ), -DEFINE_KEYFIELD( m_strMirrorRelative, FIELD_STRING, "MirrorRelative" ), - -DEFINE_FIELD( m_hMirrorTarget, FIELD_EHANDLE ), -DEFINE_FIELD( m_hMovementTarget, FIELD_EHANDLE ), -DEFINE_FIELD( m_hRemoteTarget, FIELD_EHANDLE ), -DEFINE_FIELD( m_hMirrorRelative, FIELD_EHANDLE ), - -DEFINE_INPUTFUNC( FIELD_STRING, "SetMirrorTarget", InputSetMirrorTarget ), -DEFINE_INPUTFUNC( FIELD_STRING, "SetTarget", InputSetTarget ), -DEFINE_INPUTFUNC( FIELD_STRING, "SetRemoteTarget", InputSetRemoteTarget ), -DEFINE_INPUTFUNC( FIELD_STRING, "SetMirrorRelative", InputSetMirrorRelative ), - -DEFINE_THINKFUNC( Think ), - -END_DATADESC() - - -void CLogicMirrorMovement::Activate() -{ - BaseClass::Activate(); - - SetMirrorTarget( STRING(m_strMirrorTarget) ); - SetTarget( STRING(m_target) ); - SetRemoteTarget( STRING(m_strRemoteTarget ) ); - SetMirrorRelative( STRING( m_strMirrorRelative) ); - - SetThink( &CLogicMirrorMovement::Think ); - SetNextThink( gpGlobals->curtime + TICK_INTERVAL ); -} - - -void CLogicMirrorMovement::SetMirrorTarget( const char *pName ) -{ - m_hMirrorTarget = gEntList.FindEntityByName( NULL, pName ); - if ( !m_hMirrorTarget ) - { - if ( Q_strnicmp( STRING(m_strMirrorTarget), "!player", 8 ) ) - { - Warning("logic_mirror_movement: Unable to find mirror target entity %s\n", pName ); - } - } -} - -void CLogicMirrorMovement::SetTarget( const char *pName ) -{ - m_hMovementTarget = gEntList.FindEntityByName( NULL, pName ); - if ( !m_hMovementTarget ) - { - Warning("logic_mirror_movement: Unable to find movement target entity %s\n", pName ); - } -} - -void CLogicMirrorMovement::SetRemoteTarget(const char *pName ) -{ - m_hRemoteTarget = gEntList.FindEntityByName( NULL, pName ); - if ( !m_hRemoteTarget ) - { - Warning("logic_mirror_movement: Unable to find remote target entity %s\n", pName ); - } -} - -void CLogicMirrorMovement::SetMirrorRelative(const char* pName ) -{ - m_hMirrorRelative = gEntList.FindEntityByName( NULL, pName ); - if ( !m_hMirrorRelative ) - { - Warning("logic_mirror_movement: Unable to find mirror relative entity %s\n", pName ); - } -} - -void CLogicMirrorMovement::InputSetMirrorTarget( inputdata_t &inputdata ) -{ - m_strMirrorTarget = AllocPooledString( inputdata.value.String() ); - SetMirrorTarget( inputdata.value.String() ); -} - -void CLogicMirrorMovement::InputSetTarget( inputdata_t &inputdata ) -{ - m_target = AllocPooledString( inputdata.value.String() ); - SetTarget( inputdata.value.String() ); -} - -void CLogicMirrorMovement::InputSetRemoteTarget(inputdata_t &inputdata ) -{ - m_strRemoteTarget = AllocPooledString( inputdata.value.String() ); - SetRemoteTarget( inputdata.value.String() ); -} - -void CLogicMirrorMovement::InputSetMirrorRelative(inputdata_t &inputdata ) -{ - m_strMirrorRelative = AllocPooledString ( inputdata.value.String() ); - SetMirrorRelative( inputdata.value.String() ); -} - - -void CLogicMirrorMovement::Think() -{ - // Attempt to get the player's handle because it didn't exist at Activate time - if ( !m_hMirrorTarget.Get() ) - { - // If we will never find a target, we don't have a use... shutdown - if ( m_strMirrorTarget == NULL_STRING ) - SetNextThink ( 0.0f ); - - //BUGBUG: If m_strSetMirrorTarget doesn't exist in ent list, we get per-think searches with no results ever... - SetMirrorTarget ( STRING(m_strMirrorTarget) ); - } - - // Make sure all entities are valid - if ( m_hMirrorTarget.Get() && m_hMovementTarget.Get() && m_hRemoteTarget.Get() && m_hMirrorRelative.Get() ) - { - // Get our two portal's world transforms transforms - VMatrix matPortal1ToWorldInv, matPortal2ToWorld; - MatrixInverseGeneral( m_hMirrorRelative->EntityToWorldTransform(), matPortal1ToWorldInv ); - matPortal2ToWorld = m_hRemoteTarget->EntityToWorldTransform(); - - VMatrix matTransformToRemotePortal = matPortal1ToWorldInv * matPortal2ToWorld; - - // Get our scene camera's current orientation - Vector ptCameraPosition, vCameraLook, vCameraRight, vCameraUp; - ptCameraPosition = m_hMirrorTarget->EyePosition(); - m_hMirrorTarget->GetVectors ( &vCameraLook, &vCameraRight, &vCameraUp ); - - // map this position and orientation to the remote portal, mirrored (invert the result) - Vector ptNewPosition, vNewLook; - ptNewPosition = matPortal1ToWorldInv * ptCameraPosition; - ptNewPosition = matPortal2ToWorld*( Vector( -ptNewPosition.x, -ptNewPosition.y, ptNewPosition.z ) ); - - vNewLook = matPortal1ToWorldInv.ApplyRotation( vCameraLook ); - vNewLook = matPortal2ToWorld.ApplyRotation( Vector( -vNewLook.x, -vNewLook.y, vNewLook.z) ); - - // Set the point camera to the new location/orientation - QAngle qNewAngles; - VectorAngles( vNewLook, qNewAngles ); - m_hMovementTarget->Teleport( &ptNewPosition, &qNewAngles, NULL ); - } - - SetNextThink( gpGlobals->curtime + TICK_INTERVAL ); -} - - diff --git a/game/server/logic_navigation.cpp b/game/server/logic_navigation.cpp deleted file mode 100644 index 4bed6a5f0..000000000 --- a/game/server/logic_navigation.cpp +++ /dev/null @@ -1,183 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SF_NAV_START_ON 0x0001 - -enum navproperties_t -{ - NAV_IGNORE = 1<<0, -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CLogicNavigation : public CLogicalEntity, - public IEntityListener -{ - DECLARE_CLASS( CLogicNavigation, CLogicalEntity ); - - bool KeyValue( const char *szKeyName, const char *szValue ); - void Activate( void ); - -private: - void UpdateOnRemove(); - - void OnEntitySpawned( CBaseEntity *pEntity ); - - // Inputs - void InputTurnOn( inputdata_t &inputdata ) { TurnOn(); } - void InputTurnOff( inputdata_t &inputdata ) { TurnOff(); } - void InputToggle( inputdata_t &inputdata ) - { - if ( m_isOn ) - TurnOff(); - else - TurnOn(); - } - - void TurnOn(); - void TurnOff(); - void UpdateProperty(); - - DECLARE_DATADESC(); - - bool m_isOn; - navproperties_t m_navProperty; -}; - -LINK_ENTITY_TO_CLASS(logic_navigation, CLogicNavigation); - - -BEGIN_DATADESC( CLogicNavigation ) - - DEFINE_FIELD( m_isOn, FIELD_BOOLEAN ), - DEFINE_FIELD( m_navProperty, FIELD_INTEGER ), - - // Inputs - DEFINE_INPUTFUNC(FIELD_VOID, "TurnOn", InputTurnOn), - DEFINE_INPUTFUNC(FIELD_VOID, "TurnOff", InputTurnOff), - DEFINE_INPUTFUNC(FIELD_VOID, "Toggle", InputToggle), - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *szKeyName - -// *szValue - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CLogicNavigation::KeyValue( const char *szKeyName, const char *szValue ) -{ - if ( FStrEq(szKeyName, "navprop") ) - { - if ( FStrEq( szValue, "Ignore" ) ) - { - m_navProperty = NAV_IGNORE; - } - else - { - DevMsg( 1, "Unknown nav property %s\n", szValue ); - } - return true; - } - - return BaseClass::KeyValue( szKeyName, szValue ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CLogicNavigation::Activate() -{ - BaseClass::Activate(); - - if ( HasSpawnFlags( SF_NAV_START_ON ) ) - { - TurnOn(); - RemoveSpawnFlags( SF_NAV_START_ON ); - } - else if ( m_isOn ) - { - gEntList.AddListenerEntity( this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CLogicNavigation::UpdateOnRemove() -{ - if ( m_isOn ) - { - gEntList.RemoveListenerEntity( this ); - } - - BaseClass::UpdateOnRemove(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CLogicNavigation::OnEntitySpawned( CBaseEntity *pEntity ) -{ - if ( m_isOn && ( m_navProperty & NAV_IGNORE ) && pEntity->NameMatches( m_target ) ) - { - pEntity->SetNavIgnore(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CLogicNavigation::TurnOn() -{ - if ( m_isOn ) - return; - m_isOn = true; - gEntList.AddListenerEntity( this ); - UpdateProperty(); -} - -void CLogicNavigation::UpdateProperty() -{ - CBaseEntity *pEntity = NULL; - while ( ( pEntity = gEntList.FindEntityByName( pEntity, STRING(m_target) ) ) != NULL ) - { - if ( m_isOn ) - { - if ( m_navProperty & NAV_IGNORE ) - pEntity->SetNavIgnore(); - } - else - { - if ( m_navProperty & NAV_IGNORE ) - pEntity->ClearNavIgnore(); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CLogicNavigation::TurnOff() -{ - if ( !m_isOn ) - return; - - m_isOn = false; - gEntList.RemoveListenerEntity( this ); - UpdateProperty(); -} - diff --git a/game/server/logicauto.cpp b/game/server/logicauto.cpp deleted file mode 100644 index a76984e6b..000000000 --- a/game/server/logicauto.cpp +++ /dev/null @@ -1,127 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Fires an output when the map spawns (or respawns if not set to -// only fire once). It can be set to check a global state before firing. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "entityinput.h" -#include "entityoutput.h" -#include "eventqueue.h" -#include "mathlib/mathlib.h" -#include "globalstate.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -const int SF_AUTO_FIREONCE = 0x01; -const int SF_AUTO_FIREONRELOAD = 0x02; - - -class CLogicAuto : public CBaseEntity -{ -public: - DECLARE_CLASS( CLogicAuto, CBaseEntity ); - - void Activate(void); - void Think(void); - - int ObjectCaps(void) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } - - DECLARE_DATADESC(); - -private: - - // fired no matter why the map loaded - COutputEvent m_OnMapSpawn; - - // fired for specified types of map loads - COutputEvent m_OnNewGame; - COutputEvent m_OnLoadGame; - COutputEvent m_OnMapTransition; - COutputEvent m_OnBackgroundMap; - COutputEvent m_OnMultiNewMap; - COutputEvent m_OnMultiNewRound; - - string_t m_globalstate; -}; - -LINK_ENTITY_TO_CLASS(logic_auto, CLogicAuto); - - -BEGIN_DATADESC( CLogicAuto ) - - DEFINE_KEYFIELD(m_globalstate, FIELD_STRING, "globalstate"), - - // Outputs - DEFINE_OUTPUT(m_OnMapSpawn, "OnMapSpawn"), - DEFINE_OUTPUT(m_OnNewGame, "OnNewGame"), - DEFINE_OUTPUT(m_OnLoadGame, "OnLoadGame"), - DEFINE_OUTPUT(m_OnMapTransition, "OnMapTransition"), - DEFINE_OUTPUT(m_OnBackgroundMap, "OnBackgroundMap"), - DEFINE_OUTPUT(m_OnMultiNewMap, "OnMultiNewMap" ), - DEFINE_OUTPUT(m_OnMultiNewRound, "OnMultiNewRound" ), - -END_DATADESC() - - -//------------------------------------------------------------------------------ -// Purpose : Fire my outputs here if I fire on map reload -//------------------------------------------------------------------------------ -void CLogicAuto::Activate(void) -{ - BaseClass::Activate(); - SetNextThink( gpGlobals->curtime + 0.2 ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Called shortly after level spawn. Checks the global state and fires -// targets if the global state is set or if there is not global state -// to check. -//----------------------------------------------------------------------------- -void CLogicAuto::Think(void) -{ - if (!m_globalstate || GlobalEntity_GetState(m_globalstate) == GLOBAL_ON) - { - if (gpGlobals->eLoadType == MapLoad_Transition) - { - m_OnMapTransition.FireOutput(NULL, this); - } - else if (gpGlobals->eLoadType == MapLoad_NewGame) - { - m_OnNewGame.FireOutput(NULL, this); - } - else if (gpGlobals->eLoadType == MapLoad_LoadGame) - { - m_OnLoadGame.FireOutput(NULL, this); - } - else if (gpGlobals->eLoadType == MapLoad_Background) - { - m_OnBackgroundMap.FireOutput(NULL, this); - } - - m_OnMapSpawn.FireOutput(NULL, this); - - if ( g_pGameRules->IsMultiplayer() ) - { - // In multiplayer, fire the new map / round events. - if ( g_pGameRules->InRoundRestart() ) - { - m_OnMultiNewRound.FireOutput(NULL, this); - } - else - { - m_OnMultiNewMap.FireOutput(NULL, this); - } - } - - if (m_spawnflags & SF_AUTO_FIREONCE) - { - UTIL_Remove(this); - } - } -} - diff --git a/game/server/logicentities.cpp b/game/server/logicentities.cpp deleted file mode 100644 index 105d1dae9..000000000 --- a/game/server/logicentities.cpp +++ /dev/null @@ -1,2748 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ==== -// -// Purpose: Implements many of the entities that control logic flow within a map. -// -//============================================================================= - -#include "cbase.h" -#include "entityinput.h" -#include "entityoutput.h" -#include "eventqueue.h" -#include "mathlib/mathlib.h" -#include "globalstate.h" -#include "ndebugoverlay.h" -#include "saverestore_utlvector.h" -#include "vstdlib/random.h" -#include "gameinterface.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -extern CServerGameDLL g_ServerGameDLL; - - -//----------------------------------------------------------------------------- -// Purpose: Compares a set of integer inputs to the one main input -// Outputs true if they are all equivalant, false otherwise -//----------------------------------------------------------------------------- -class CLogicCompareInteger : public CLogicalEntity -{ -public: - DECLARE_CLASS( CLogicCompareInteger, CLogicalEntity ); - - // outputs - COutputEvent m_OnEqual; - COutputEvent m_OnNotEqual; - - // data - int m_iIntegerValue; - int m_iShouldCompareToValue; - - DECLARE_DATADESC(); - - CMultiInputVar m_AllIntCompares; - - // Input handlers - void InputValue( inputdata_t &inputdata ); - void InputCompareValues( inputdata_t &inputdata ); -}; - - -LINK_ENTITY_TO_CLASS( logic_multicompare, CLogicCompareInteger ); - - -BEGIN_DATADESC( CLogicCompareInteger ) - - DEFINE_OUTPUT( m_OnEqual, "OnEqual" ), - DEFINE_OUTPUT( m_OnNotEqual, "OnNotEqual" ), - - DEFINE_KEYFIELD( m_iIntegerValue, FIELD_INTEGER, "IntegerValue" ), - DEFINE_KEYFIELD( m_iShouldCompareToValue, FIELD_INTEGER, "ShouldComparetoValue" ), - - DEFINE_FIELD( m_AllIntCompares, FIELD_INPUT ), - - DEFINE_INPUTFUNC( FIELD_INPUT, "InputValue", InputValue ), - DEFINE_INPUTFUNC( FIELD_INPUT, "CompareValues", InputCompareValues ), - -END_DATADESC() - - - - -//----------------------------------------------------------------------------- -// Purpose: Adds to the list of compared values -//----------------------------------------------------------------------------- -void CLogicCompareInteger::InputValue( inputdata_t &inputdata ) -{ - // make sure it's an int, if it can't be converted just throw it away - if ( !inputdata.value.Convert(FIELD_INTEGER) ) - return; - - // update the value list with the new value - m_AllIntCompares.AddValue( inputdata.value, inputdata.nOutputID ); - - // if we haven't already this frame, send a message to ourself to update and fire - if ( !m_AllIntCompares.m_bUpdatedThisFrame ) - { - // TODO: need to add this event with a lower priority, so it gets called after all inputs have arrived - g_EventQueue.AddEvent( this, "CompareValues", 0, inputdata.pActivator, this, inputdata.nOutputID ); - m_AllIntCompares.m_bUpdatedThisFrame = TRUE; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Forces a recompare -//----------------------------------------------------------------------------- -void CLogicCompareInteger::InputCompareValues( inputdata_t &inputdata ) -{ - m_AllIntCompares.m_bUpdatedThisFrame = FALSE; - - // loop through all the values comparing them - int value = m_iIntegerValue; - CMultiInputVar::inputitem_t *input = m_AllIntCompares.m_InputList; - - if ( !m_iShouldCompareToValue && input ) - { - value = input->value.Int(); - } - - while ( input ) - { - if ( input->value.Int() != value ) - { - // false - m_OnNotEqual.FireOutput( inputdata.pActivator, this ); - return; - } - - input = input->next; - } - - // true! all values equal - m_OnEqual.FireOutput( inputdata.pActivator, this ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Timer entity. Fires an output at regular or random intervals. -//----------------------------------------------------------------------------- -// -// Spawnflags and others constants. -// -const int SF_TIMER_UPDOWN = 1; -const float LOGIC_TIMER_MIN_INTERVAL = 0.01; - - -class CTimerEntity : public CLogicalEntity -{ -public: - DECLARE_CLASS( CTimerEntity, CLogicalEntity ); - - void Spawn( void ); - void Think( void ); - - void Toggle( void ); - void Enable( void ); - void Disable( void ); - void FireTimer( void ); - - int DrawDebugTextOverlays(void); - - // outputs - COutputEvent m_OnTimer; - COutputEvent m_OnTimerHigh; - COutputEvent m_OnTimerLow; - - // inputs - void InputToggle( inputdata_t &inputdata ); - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - void InputFireTimer( inputdata_t &inputdata ); - void InputRefireTime( inputdata_t &inputdata ); - void InputResetTimer( inputdata_t &inputdata ); - void InputAddToTimer( inputdata_t &inputdata ); - void InputSubtractFromTimer( inputdata_t &inputdata ); - - int m_iDisabled; - float m_flRefireTime; - bool m_bUpDownState; - int m_iUseRandomTime; - float m_flLowerRandomBound; - float m_flUpperRandomBound; - - // methods - void ResetTimer( void ); - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( logic_timer, CTimerEntity ); - - -BEGIN_DATADESC( CTimerEntity ) - - // Keys - DEFINE_KEYFIELD( m_iDisabled, FIELD_INTEGER, "StartDisabled" ), - DEFINE_KEYFIELD( m_flRefireTime, FIELD_FLOAT, "RefireTime" ), - - DEFINE_FIELD( m_bUpDownState, FIELD_BOOLEAN ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_FLOAT, "RefireTime", InputRefireTime ), - DEFINE_INPUTFUNC( FIELD_VOID, "FireTimer", InputFireTimer ), - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "AddToTimer", InputAddToTimer ), - DEFINE_INPUTFUNC( FIELD_VOID, "ResetTimer", InputResetTimer ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SubtractFromTimer", InputSubtractFromTimer ), - - DEFINE_INPUT( m_iUseRandomTime, FIELD_INTEGER, "UseRandomTime" ), - DEFINE_INPUT( m_flLowerRandomBound, FIELD_FLOAT, "LowerRandomBound" ), - DEFINE_INPUT( m_flUpperRandomBound, FIELD_FLOAT, "UpperRandomBound" ), - - - // Outputs - DEFINE_OUTPUT( m_OnTimer, "OnTimer" ), - DEFINE_OUTPUT( m_OnTimerHigh, "OnTimerHigh" ), - DEFINE_OUTPUT( m_OnTimerLow, "OnTimerLow" ), - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTimerEntity::Spawn( void ) -{ - if (!m_iUseRandomTime && (m_flRefireTime < LOGIC_TIMER_MIN_INTERVAL)) - { - m_flRefireTime = LOGIC_TIMER_MIN_INTERVAL; - } - - if ( !m_iDisabled && (m_flRefireTime > 0 || m_iUseRandomTime) ) - { - Enable(); - } - else - { - Disable(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTimerEntity::Think( void ) -{ - FireTimer(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Sets the time the timerentity will next fire -//----------------------------------------------------------------------------- -void CTimerEntity::ResetTimer( void ) -{ - if ( m_iDisabled ) - return; - - if ( m_iUseRandomTime ) - { - m_flRefireTime = random->RandomFloat( m_flLowerRandomBound, m_flUpperRandomBound ); - } - - SetNextThink( gpGlobals->curtime + m_flRefireTime ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTimerEntity::Enable( void ) -{ - m_iDisabled = FALSE; - ResetTimer(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTimerEntity::Disable( void ) -{ - m_iDisabled = TRUE; - SetNextThink( TICK_NEVER_THINK ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTimerEntity::Toggle( void ) -{ - if ( m_iDisabled ) - { - Enable(); - } - else - { - Disable(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTimerEntity::FireTimer( void ) -{ - if ( !m_iDisabled ) - { - // - // Up/down timers alternate between two outputs. - // - if (m_spawnflags & SF_TIMER_UPDOWN) - { - if (m_bUpDownState) - { - m_OnTimerHigh.FireOutput( this, this ); - } - else - { - m_OnTimerLow.FireOutput( this, this ); - } - - m_bUpDownState = !m_bUpDownState; - } - // - // Regular timers only fire a single output. - // - else - { - m_OnTimer.FireOutput( this, this ); - } - - ResetTimer(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTimerEntity::InputEnable( inputdata_t &inputdata ) -{ - Enable(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTimerEntity::InputDisable( inputdata_t &inputdata ) -{ - Disable(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTimerEntity::InputToggle( inputdata_t &inputdata ) -{ - Toggle(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTimerEntity::InputFireTimer( inputdata_t &inputdata ) -{ - FireTimer(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Changes the time interval between timer fires -// Resets the next firing to be time + newRefireTime -// Input : Float refire frequency in seconds. -//----------------------------------------------------------------------------- -void CTimerEntity::InputRefireTime( inputdata_t &inputdata ) -{ - float flRefireInterval = inputdata.value.Float(); - - if ( flRefireInterval < LOGIC_TIMER_MIN_INTERVAL) - { - flRefireInterval = LOGIC_TIMER_MIN_INTERVAL; - } - - if (m_flRefireTime != flRefireInterval ) - { - m_flRefireTime = flRefireInterval; - ResetTimer(); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CTimerEntity::InputResetTimer( inputdata_t &inputdata ) -{ - // don't reset the timer if it isn't enabled - if ( m_iDisabled ) - return; - - ResetTimer(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Adds to the time interval if the timer is enabled -// Input : Float time to add in seconds -//----------------------------------------------------------------------------- -void CTimerEntity::InputAddToTimer( inputdata_t &inputdata ) -{ - // don't add time if the timer isn't enabled - if ( m_iDisabled ) - return; - - // Add time to timer - float flNextThink = GetNextThink(); - SetNextThink( flNextThink += inputdata.value.Float() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Subtract from the time interval if the timer is enabled -// Input : Float time to subtract in seconds -//----------------------------------------------------------------------------- -void CTimerEntity::InputSubtractFromTimer( inputdata_t &inputdata ) -{ - // don't add time if the timer isn't enabled - if ( m_iDisabled ) - return; - - // Subtract time from the timer but don't let the timer go negative - float flNextThink = GetNextThink(); - if ( ( flNextThink - gpGlobals->curtime ) <= inputdata.value.Float() ) - { - SetNextThink( gpGlobals->curtime ); - } - else - { - SetNextThink( flNextThink -= inputdata.value.Float() ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CTimerEntity::DrawDebugTextOverlays( void ) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - - // print refire time - Q_snprintf(tempstr,sizeof(tempstr),"refire interval: %.2f sec", m_flRefireTime); - EntityText(text_offset,tempstr,0); - text_offset++; - - // print seconds to next fire - if ( !m_iDisabled ) - { - float flNextThink = GetNextThink(); - Q_snprintf( tempstr, sizeof( tempstr ), " firing in: %.2f sec", flNextThink - gpGlobals->curtime ); - EntityText( text_offset, tempstr, 0); - text_offset++; - } - } - return text_offset; -} - - -//----------------------------------------------------------------------------- -// Purpose: Computes a line between two entities -//----------------------------------------------------------------------------- -class CLogicLineToEntity : public CLogicalEntity -{ -public: - DECLARE_CLASS( CLogicLineToEntity, CLogicalEntity ); - - void Activate(void); - void Spawn( void ); - void Think( void ); - - // outputs - COutputVector m_Line; - - DECLARE_DATADESC(); - -private: - string_t m_SourceName; - EHANDLE m_StartEntity; - EHANDLE m_EndEntity; -}; - -LINK_ENTITY_TO_CLASS( logic_lineto, CLogicLineToEntity ); - - -BEGIN_DATADESC( CLogicLineToEntity ) - - // Keys - // target is handled in the base class, stored in field m_target - DEFINE_KEYFIELD( m_SourceName, FIELD_STRING, "source" ), - DEFINE_FIELD( m_StartEntity, FIELD_EHANDLE ), - DEFINE_FIELD( m_EndEntity, FIELD_EHANDLE ), - - // Outputs - DEFINE_OUTPUT( m_Line, "Line" ), - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Find the entities -//----------------------------------------------------------------------------- -void CLogicLineToEntity::Activate(void) -{ - BaseClass::Activate(); - - if (m_target != NULL_STRING) - { - m_EndEntity = gEntList.FindEntityByName( NULL, m_target ); - - // - // If we were given a bad measure target, just measure sound where we are. - // - if ((m_EndEntity == NULL) || (m_EndEntity->edict() == NULL)) - { - Warning( "logic_lineto - Target not found or target with no origin!\n"); - m_EndEntity = this; - } - } - else - { - m_EndEntity = this; - } - - if (m_SourceName != NULL_STRING) - { - m_StartEntity = gEntList.FindEntityByName( NULL, m_SourceName ); - - // - // If we were given a bad measure target, just measure sound where we are. - // - if ((m_StartEntity == NULL) || (m_StartEntity->edict() == NULL)) - { - Warning( "logic_lineto - Source not found or source with no origin!\n"); - m_StartEntity = this; - } - } - else - { - m_StartEntity = this; - } -} - - -//----------------------------------------------------------------------------- -// Find the entities -//----------------------------------------------------------------------------- -void CLogicLineToEntity::Spawn(void) -{ - SetNextThink( gpGlobals->curtime + 0.01f ); -} - - -//----------------------------------------------------------------------------- -// Find the entities -//----------------------------------------------------------------------------- -void CLogicLineToEntity::Think(void) -{ - CBaseEntity* pDest = m_EndEntity.Get(); - CBaseEntity* pSrc = m_StartEntity.Get(); - if (!pDest || !pSrc || !pDest->edict() || !pSrc->edict()) - { - // Can sleep for a long time, no more lines. - m_Line.Set( vec3_origin, this, this ); - SetNextThink( gpGlobals->curtime + 10 ); - return; - } - - Vector delta; - VectorSubtract( pDest->GetAbsOrigin(), pSrc->GetAbsOrigin(), delta ); - m_Line.Set(delta, this, this); - - SetNextThink( gpGlobals->curtime + 0.01f ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Remaps a given input range to an output range. -//----------------------------------------------------------------------------- -const int SF_MATH_REMAP_IGNORE_OUT_OF_RANGE = 1; -const int SF_MATH_REMAP_CLAMP_OUTPUT_TO_RANGE = 2; - -class CMathRemap : public CLogicalEntity -{ -public: - - DECLARE_CLASS( CMathRemap, CLogicalEntity ); - - void Spawn(void); - - // Keys - float m_flInMin; - float m_flInMax; - float m_flOut1; // Output value when input is m_fInMin - float m_flOut2; // Output value when input is m_fInMax - - bool m_bEnabled; - - // Inputs - void InputValue( inputdata_t &inputdata ); - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - - // Outputs - COutputFloat m_OutValue; - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS(math_remap, CMathRemap); - - -BEGIN_DATADESC( CMathRemap ) - - DEFINE_INPUTFUNC(FIELD_FLOAT, "InValue", InputValue ), - - DEFINE_OUTPUT(m_OutValue, "OutValue"), - - DEFINE_KEYFIELD(m_flInMin, FIELD_FLOAT, "in1"), - DEFINE_KEYFIELD(m_flInMax, FIELD_FLOAT, "in2"), - DEFINE_KEYFIELD(m_flOut1, FIELD_FLOAT, "out1"), - DEFINE_KEYFIELD(m_flOut2, FIELD_FLOAT, "out2"), - - DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - -END_DATADESC() - - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMathRemap::Spawn(void) -{ - // - // Avoid a divide by zero in ValueChanged. - // - if (m_flInMin == m_flInMax) - { - m_flInMin = 0; - m_flInMax = 1; - } - - // - // Make sure min and max are set properly relative to one another. - // - if (m_flInMin > m_flInMax) - { - float flTemp = m_flInMin; - m_flInMin = m_flInMax; - m_flInMax = flTemp; - } - - m_bEnabled = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMathRemap::InputEnable( inputdata_t &inputdata ) -{ - m_bEnabled = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMathRemap::InputDisable( inputdata_t &inputdata ) -{ - m_bEnabled = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler that is called when the input value changes. -//----------------------------------------------------------------------------- -void CMathRemap::InputValue( inputdata_t &inputdata ) -{ - float flValue = inputdata.value.Float(); - - // - // Disallow out-of-range input values to avoid out-of-range output values. - // - float flClampValue = clamp(flValue, m_flInMin, m_flInMax); - - if ((flClampValue == flValue) || !FBitSet(m_spawnflags, SF_MATH_REMAP_IGNORE_OUT_OF_RANGE)) - { - // - // Remap the input value to the desired output range and update the output. - // - float flRemappedValue = m_flOut1 + (((flValue - m_flInMin) * (m_flOut2 - m_flOut1)) / (m_flInMax - m_flInMin)); - - if ( FBitSet( m_spawnflags, SF_MATH_REMAP_CLAMP_OUTPUT_TO_RANGE ) ) - { - flRemappedValue = clamp( flRemappedValue, m_flOut1, m_flOut2 ); - } - - if ( m_bEnabled == true ) - { - m_OutValue.Set(flRemappedValue, inputdata.pActivator, this); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Remaps a given input range to an output range. -//----------------------------------------------------------------------------- -const int SF_COLOR_BLEND_IGNORE_OUT_OF_RANGE = 1; - -class CMathColorBlend : public CLogicalEntity -{ -public: - - DECLARE_CLASS( CMathColorBlend, CLogicalEntity ); - - void Spawn(void); - - // Keys - float m_flInMin; - float m_flInMax; - color32 m_OutColor1; // Output color when input is m_fInMin - color32 m_OutColor2; // Output color when input is m_fInMax - - // Inputs - void InputValue( inputdata_t &inputdata ); - - // Outputs - COutputColor32 m_OutValue; - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS(math_colorblend, CMathColorBlend); - - -BEGIN_DATADESC( CMathColorBlend ) - - DEFINE_INPUTFUNC(FIELD_FLOAT, "InValue", InputValue ), - - DEFINE_OUTPUT(m_OutValue, "OutColor"), - - DEFINE_KEYFIELD(m_flInMin, FIELD_FLOAT, "inmin"), - DEFINE_KEYFIELD(m_flInMax, FIELD_FLOAT, "inmax"), - DEFINE_KEYFIELD(m_OutColor1, FIELD_COLOR32, "colormin"), - DEFINE_KEYFIELD(m_OutColor2, FIELD_COLOR32, "colormax"), - -END_DATADESC() - - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMathColorBlend::Spawn(void) -{ - // - // Avoid a divide by zero in ValueChanged. - // - if (m_flInMin == m_flInMax) - { - m_flInMin = 0; - m_flInMax = 1; - } - - // - // Make sure min and max are set properly relative to one another. - // - if (m_flInMin > m_flInMax) - { - float flTemp = m_flInMin; - m_flInMin = m_flInMax; - m_flInMax = flTemp; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that is called when the input value changes. -//----------------------------------------------------------------------------- -void CMathColorBlend::InputValue( inputdata_t &inputdata ) -{ - float flValue = inputdata.value.Float(); - - // - // Disallow out-of-range input values to avoid out-of-range output values. - // - float flClampValue = clamp(flValue, m_flInMin, m_flInMax); - if ((flClampValue == flValue) || !FBitSet(m_spawnflags, SF_COLOR_BLEND_IGNORE_OUT_OF_RANGE)) - { - // - // Remap the input value to the desired output color and update the output. - // - color32 Color; - Color.r = (byte)(m_OutColor1.r + (((flClampValue - m_flInMin) * (m_OutColor2.r - m_OutColor1.r)) / (m_flInMax - m_flInMin))); - Color.g = (byte)(m_OutColor1.g + (((flClampValue - m_flInMin) * (m_OutColor2.g - m_OutColor1.g)) / (m_flInMax - m_flInMin))); - Color.b = (byte)(m_OutColor1.b + (((flClampValue - m_flInMin) * (m_OutColor2.b - m_OutColor1.b)) / (m_flInMax - m_flInMin))); - Color.a = (byte)(m_OutColor1.a + (((flClampValue - m_flInMin) * (m_OutColor2.a - m_OutColor1.a)) / (m_flInMax - m_flInMin))); - - m_OutValue.Set(Color, inputdata.pActivator, this); - } -} - - -//----------------------------------------------------------------------------- -// Console command to set the state of a global -//----------------------------------------------------------------------------- -void CC_Global_Set( const CCommand &args ) -{ - const char *szGlobal = args[1]; - const char *szState = args[2]; - - if ( szGlobal == NULL || szState == NULL ) - { - Msg( "Usage: global_set : Sets the state of the given env_global (0 = OFF, 1 = ON, 2 = DEAD).\n" ); - return; - } - - int nState = atoi( szState ); - - int nIndex = GlobalEntity_GetIndex( szGlobal ); - - if ( nIndex >= 0 ) - { - GlobalEntity_SetState( nIndex, ( GLOBALESTATE )nState ); - } - else - { - GlobalEntity_Add( szGlobal, STRING( gpGlobals->mapname ), ( GLOBALESTATE )nState ); - } -} - -static ConCommand global_set( "global_set", CC_Global_Set, "global_set : Sets the state of the given env_global (0 = OFF, 1 = ON, 2 = DEAD).", FCVAR_CHEAT ); - - -//----------------------------------------------------------------------------- -// Purpose: Holds a global state that can be queried by other entities to change -// their behavior, such as "predistaster". -//----------------------------------------------------------------------------- -const int SF_GLOBAL_SET = 1; // Set global state to initial state on spawn - -class CEnvGlobal : public CLogicalEntity -{ -public: - DECLARE_CLASS( CEnvGlobal, CLogicalEntity ); - - void Spawn( void ); - - // Input handlers - void InputTurnOn( inputdata_t &inputdata ); - void InputTurnOff( inputdata_t &inputdata ); - void InputRemove( inputdata_t &inputdata ); - void InputToggle( inputdata_t &inputdata ); - void InputSetCounter( inputdata_t &inputdata ); - void InputAddToCounter( inputdata_t &inputdata ); - void InputGetCounter( inputdata_t &inputdata ); - - int DrawDebugTextOverlays(void); - - DECLARE_DATADESC(); - - COutputInt m_outCounter; - - string_t m_globalstate; - int m_triggermode; - int m_initialstate; - int m_counter; // A counter value associated with this global. -}; - - -BEGIN_DATADESC( CEnvGlobal ) - - DEFINE_KEYFIELD( m_globalstate, FIELD_STRING, "globalstate" ), - DEFINE_FIELD( m_triggermode, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_initialstate, FIELD_INTEGER, "initialstate" ), - DEFINE_KEYFIELD( m_counter, FIELD_INTEGER, "counter" ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - DEFINE_INPUTFUNC( FIELD_VOID, "Remove", InputRemove ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetCounter", InputSetCounter ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "AddToCounter", InputAddToCounter ), - DEFINE_INPUTFUNC( FIELD_VOID, "GetCounter", InputGetCounter ), - - DEFINE_OUTPUT( m_outCounter, "Counter" ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( env_global, CEnvGlobal ); - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvGlobal::Spawn( void ) -{ - if ( !m_globalstate ) - { - UTIL_Remove( this ); - return; - } - -#ifdef HL2_EPISODIC - // if we modify the state of the physics cannon, make sure we precache the ragdoll boogie zap sound - if ( ( m_globalstate != NULL_STRING ) && ( stricmp( STRING( m_globalstate ), "super_phys_gun" ) == 0 ) ) - { - PrecacheScriptSound( "RagdollBoogie.Zap" ); - } -#endif - - if ( FBitSet( m_spawnflags, SF_GLOBAL_SET ) ) - { - if ( !GlobalEntity_IsInTable( m_globalstate ) ) - { - GlobalEntity_Add( m_globalstate, gpGlobals->mapname, (GLOBALESTATE)m_initialstate ); - } - - if ( m_counter != 0 ) - { - GlobalEntity_SetCounter( m_globalstate, m_counter ); - } - } -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CEnvGlobal::InputTurnOn( inputdata_t &inputdata ) -{ - if ( GlobalEntity_IsInTable( m_globalstate ) ) - { - GlobalEntity_SetState( m_globalstate, GLOBAL_ON ); - } - else - { - GlobalEntity_Add( m_globalstate, gpGlobals->mapname, GLOBAL_ON ); - } -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CEnvGlobal::InputTurnOff( inputdata_t &inputdata ) -{ - if ( GlobalEntity_IsInTable( m_globalstate ) ) - { - GlobalEntity_SetState( m_globalstate, GLOBAL_OFF ); - } - else - { - GlobalEntity_Add( m_globalstate, gpGlobals->mapname, GLOBAL_OFF ); - } -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CEnvGlobal::InputRemove( inputdata_t &inputdata ) -{ - if ( GlobalEntity_IsInTable( m_globalstate ) ) - { - GlobalEntity_SetState( m_globalstate, GLOBAL_DEAD ); - } - else - { - GlobalEntity_Add( m_globalstate, gpGlobals->mapname, GLOBAL_DEAD ); - } -} - - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CEnvGlobal::InputSetCounter( inputdata_t &inputdata ) -{ - if ( !GlobalEntity_IsInTable( m_globalstate ) ) - { - GlobalEntity_Add( m_globalstate, gpGlobals->mapname, GLOBAL_ON ); - } - - GlobalEntity_SetCounter( m_globalstate, inputdata.value.Int() ); -} - - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CEnvGlobal::InputAddToCounter( inputdata_t &inputdata ) -{ - if ( !GlobalEntity_IsInTable( m_globalstate ) ) - { - GlobalEntity_Add( m_globalstate, gpGlobals->mapname, GLOBAL_ON ); - } - - GlobalEntity_AddToCounter( m_globalstate, inputdata.value.Int() ); -} - - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CEnvGlobal::InputGetCounter( inputdata_t &inputdata ) -{ - if ( !GlobalEntity_IsInTable( m_globalstate ) ) - { - GlobalEntity_Add( m_globalstate, gpGlobals->mapname, GLOBAL_ON ); - } - - m_outCounter.Set( GlobalEntity_GetCounter( m_globalstate ), inputdata.pActivator, this ); -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CEnvGlobal::InputToggle( inputdata_t &inputdata ) -{ - GLOBALESTATE oldState = GlobalEntity_GetState( m_globalstate ); - GLOBALESTATE newState; - - if ( oldState == GLOBAL_ON ) - { - newState = GLOBAL_OFF; - } - else if ( oldState == GLOBAL_OFF ) - { - newState = GLOBAL_ON; - } - else - { - return; - } - - if ( GlobalEntity_IsInTable( m_globalstate ) ) - { - GlobalEntity_SetState( m_globalstate, newState ); - } - else - { - GlobalEntity_Add( m_globalstate, gpGlobals->mapname, newState ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Input : -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CEnvGlobal::DrawDebugTextOverlays(void) -{ - // Skip AIClass debug overlays - int text_offset = CBaseEntity::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - Q_snprintf(tempstr,sizeof(tempstr),"State: %s",STRING(m_globalstate)); - EntityText(text_offset,tempstr,0); - text_offset++; - - GLOBALESTATE nState = GlobalEntity_GetState( m_globalstate ); - - switch( nState ) - { - case GLOBAL_OFF: - Q_strncpy(tempstr,"Value: OFF",sizeof(tempstr)); - break; - - case GLOBAL_ON: - Q_strncpy(tempstr,"Value: ON",sizeof(tempstr)); - break; - - case GLOBAL_DEAD: - Q_strncpy(tempstr,"Value: DEAD",sizeof(tempstr)); - break; - } - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -#define MS_MAX_TARGETS 32 - -const int SF_MULTI_INIT = 1; - -class CMultiSource : public CLogicalEntity -{ -public: - DECLARE_CLASS( CMultiSource, CLogicalEntity ); - - void Spawn( ); - bool KeyValue( const char *szKeyName, const char *szValue ); - void Use( ::CBaseEntity *pActivator, ::CBaseEntity *pCaller, USE_TYPE useType, float value ); - int ObjectCaps( void ) { return(BaseClass::ObjectCaps() | FCAP_MASTER); } - bool IsTriggered( ::CBaseEntity *pActivator ); - void Register( void ); - - DECLARE_DATADESC(); - - EHANDLE m_rgEntities[MS_MAX_TARGETS]; - int m_rgTriggered[MS_MAX_TARGETS]; - - COutputEvent m_OnTrigger; // Fired when all connections are triggered. - - int m_iTotal; - string_t m_globalstate; -}; - -BEGIN_DATADESC( CMultiSource ) - - //!!!BUGBUG FIX - DEFINE_ARRAY( m_rgEntities, FIELD_EHANDLE, MS_MAX_TARGETS ), - DEFINE_ARRAY( m_rgTriggered, FIELD_INTEGER, MS_MAX_TARGETS ), - DEFINE_FIELD( m_iTotal, FIELD_INTEGER ), - - DEFINE_KEYFIELD( m_globalstate, FIELD_STRING, "globalstate" ), - - // Function pointers - DEFINE_FUNCTION( Register ), - - // Outputs - DEFINE_OUTPUT(m_OnTrigger, "OnTrigger"), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( multisource, CMultiSource ); - - -//----------------------------------------------------------------------------- -// Purpose: Cache user entity field values until spawn is called. -// Input : szKeyName - Key to handle. -// szValue - Value for key. -// Output : Returns true if the key was handled, false if not. -//----------------------------------------------------------------------------- -bool CMultiSource::KeyValue( const char *szKeyName, const char *szValue ) -{ - if ( FStrEq(szKeyName, "style") || - FStrEq(szKeyName, "height") || - FStrEq(szKeyName, "killtarget") || - FStrEq(szKeyName, "value1") || - FStrEq(szKeyName, "value2") || - FStrEq(szKeyName, "value3")) - { - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMultiSource::Spawn() -{ - SetNextThink( gpGlobals->curtime + 0.1f ); - m_spawnflags |= SF_MULTI_INIT; // Until it's initialized - SetThink(&CMultiSource::Register); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pActivator - -// pCaller - -// useType - -// value - -//----------------------------------------------------------------------------- -void CMultiSource::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - int i = 0; - - // Find the entity in our list - while (i < m_iTotal) - if ( m_rgEntities[i++] == pCaller ) - break; - - // if we didn't find it, report error and leave - if (i > m_iTotal) - { - Warning("MultiSrc: Used by non member %s.\n", pCaller->edict() ? pCaller->GetClassname() : ""); - return; - } - - // CONSIDER: a Use input to the multisource always toggles. Could check useType for ON/OFF/TOGGLE - - m_rgTriggered[i-1] ^= 1; - - // - if ( IsTriggered( pActivator ) ) - { - DevMsg( 2, "Multisource %s enabled (%d inputs)\n", GetDebugName(), m_iTotal ); - USE_TYPE useType = USE_TOGGLE; - if ( m_globalstate != NULL_STRING ) - useType = USE_ON; - - m_OnTrigger.FireOutput(pActivator, this); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CMultiSource::IsTriggered( CBaseEntity * ) -{ - // Is everything triggered? - int i = 0; - - // Still initializing? - if ( m_spawnflags & SF_MULTI_INIT ) - return 0; - - while (i < m_iTotal) - { - if (m_rgTriggered[i] == 0) - break; - i++; - } - - if (i == m_iTotal) - { - if ( !m_globalstate || GlobalEntity_GetState( m_globalstate ) == GLOBAL_ON ) - return 1; - } - - return 0; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMultiSource::Register(void) -{ - CBaseEntity *pTarget = NULL; - - m_iTotal = 0; - memset( m_rgEntities, 0, MS_MAX_TARGETS * sizeof(EHANDLE) ); - - SetThink(&CMultiSource::SUB_DoNothing); - - // search for all entities which target this multisource (m_iName) - // dvsents2: port multisource to entity I/O! - - pTarget = gEntList.FindEntityByTarget( NULL, STRING(GetEntityName()) ); - - while ( pTarget && (m_iTotal < MS_MAX_TARGETS) ) - { - if ( pTarget ) - m_rgEntities[m_iTotal++] = pTarget; - - pTarget = gEntList.FindEntityByTarget( pTarget, STRING(GetEntityName()) ); - } - - pTarget = gEntList.FindEntityByClassname( NULL, "multi_manager" ); - while (pTarget && (m_iTotal < MS_MAX_TARGETS)) - { - if ( pTarget && pTarget->HasTarget(GetEntityName()) ) - m_rgEntities[m_iTotal++] = pTarget; - - pTarget = gEntList.FindEntityByClassname( pTarget, "multi_manager" ); - } - - m_spawnflags &= ~SF_MULTI_INIT; -} - - -//----------------------------------------------------------------------------- -// Purpose: Holds a value that can be added to and subtracted from. -//----------------------------------------------------------------------------- -class CMathCounter : public CLogicalEntity -{ - DECLARE_CLASS( CMathCounter, CLogicalEntity ); -private: - float m_flMin; // Minimum clamp value. If min and max are BOTH zero, no clamping is done. - float m_flMax; // Maximum clamp value. - bool m_bHitMin; // Set when we reach or go below our minimum value, cleared if we go above it again. - bool m_bHitMax; // Set when we reach or exceed our maximum value, cleared if we fall below it again. - - bool m_bDisabled; - - bool KeyValue(const char *szKeyName, const char *szValue); - void Spawn(void); - - int DrawDebugTextOverlays(void); - - void UpdateOutValue(CBaseEntity *pActivator, float fNewValue); - - // Inputs - void InputAdd( inputdata_t &inputdata ); - void InputDivide( inputdata_t &inputdata ); - void InputMultiply( inputdata_t &inputdata ); - void InputSetValue( inputdata_t &inputdata ); - void InputSetValueNoFire( inputdata_t &inputdata ); - void InputSubtract( inputdata_t &inputdata ); - void InputSetHitMax( inputdata_t &inputdata ); - void InputSetHitMin( inputdata_t &inputdata ); - void InputGetValue( inputdata_t &inputdata ); - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - - // Outputs - COutputFloat m_OutValue; - COutputFloat m_OnGetValue; // Used for polling the counter value. - COutputEvent m_OnHitMin; - COutputEvent m_OnHitMax; - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS(math_counter, CMathCounter); - - -BEGIN_DATADESC( CMathCounter ) - - DEFINE_FIELD(m_bHitMax, FIELD_BOOLEAN), - DEFINE_FIELD(m_bHitMin, FIELD_BOOLEAN), - - // Keys - DEFINE_KEYFIELD(m_flMin, FIELD_FLOAT, "min"), - DEFINE_KEYFIELD(m_flMax, FIELD_FLOAT, "max"), - - DEFINE_KEYFIELD(m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ), - - // Inputs - DEFINE_INPUTFUNC(FIELD_FLOAT, "Add", InputAdd), - DEFINE_INPUTFUNC(FIELD_FLOAT, "Divide", InputDivide), - DEFINE_INPUTFUNC(FIELD_FLOAT, "Multiply", InputMultiply), - DEFINE_INPUTFUNC(FIELD_FLOAT, "SetValue", InputSetValue), - DEFINE_INPUTFUNC(FIELD_FLOAT, "SetValueNoFire", InputSetValueNoFire), - DEFINE_INPUTFUNC(FIELD_FLOAT, "Subtract", InputSubtract), - DEFINE_INPUTFUNC(FIELD_FLOAT, "SetHitMax", InputSetHitMax), - DEFINE_INPUTFUNC(FIELD_FLOAT, "SetHitMin", InputSetHitMin), - DEFINE_INPUTFUNC(FIELD_VOID, "GetValue", InputGetValue), - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - - // Outputs - DEFINE_OUTPUT(m_OutValue, "OutValue"), - DEFINE_OUTPUT(m_OnHitMin, "OnHitMin"), - DEFINE_OUTPUT(m_OnHitMax, "OnHitMax"), - DEFINE_OUTPUT(m_OnGetValue, "OnGetValue"), - -END_DATADESC() - - - - -//----------------------------------------------------------------------------- -// Purpose: Handles key values from the BSP before spawn is called. -//----------------------------------------------------------------------------- -bool CMathCounter::KeyValue(const char *szKeyName, const char *szValue) -{ - // - // Set the initial value of the counter. - // - if (!stricmp(szKeyName, "startvalue")) - { - m_OutValue.Init(atoi(szValue)); - return(true); - } - - return(BaseClass::KeyValue(szKeyName, szValue)); -} - - -//----------------------------------------------------------------------------- -// Purpose: Called before spawning, after key values have been set. -//----------------------------------------------------------------------------- -void CMathCounter::Spawn( void ) -{ - // - // Make sure max and min are ordered properly or clamp won't work. - // - if (m_flMin > m_flMax) - { - float flTemp = m_flMax; - m_flMax = m_flMin; - m_flMin = flTemp; - } - - // - // Clamp initial value to within the valid range. - // - if ((m_flMin != 0) || (m_flMax != 0)) - { - float flStartValue = clamp(m_OutValue.Get(), m_flMin, m_flMax); - m_OutValue.Init(flStartValue); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Input : -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CMathCounter::DrawDebugTextOverlays( void ) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - - Q_snprintf(tempstr,sizeof(tempstr)," min value: %f", m_flMin); - EntityText(text_offset,tempstr,0); - text_offset++; - - Q_snprintf(tempstr,sizeof(tempstr)," max value: %f", m_flMax); - EntityText(text_offset,tempstr,0); - text_offset++; - - Q_snprintf(tempstr,sizeof(tempstr),"current value: %f", m_OutValue.Get()); - EntityText(text_offset,tempstr,0); - text_offset++; - - if( m_bDisabled ) - { - Q_snprintf(tempstr,sizeof(tempstr),"*DISABLED*"); - } - else - { - Q_snprintf(tempstr,sizeof(tempstr),"Enabled."); - } - EntityText(text_offset,tempstr,0); - text_offset++; - - } - return text_offset; -} - -//----------------------------------------------------------------------------- -// Change min/max -//----------------------------------------------------------------------------- -void CMathCounter::InputSetHitMax( inputdata_t &inputdata ) -{ - m_flMax = inputdata.value.Float(); - if ( m_flMax < m_flMin ) - { - m_flMin = m_flMax; - } - UpdateOutValue( inputdata.pActivator, m_OutValue.Get() ); -} - -void CMathCounter::InputSetHitMin( inputdata_t &inputdata ) -{ - m_flMin = inputdata.value.Float(); - if ( m_flMax < m_flMin ) - { - m_flMax = m_flMin; - } - UpdateOutValue( inputdata.pActivator, m_OutValue.Get() ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for adding to the accumulator value. -// Input : Float value to add. -//----------------------------------------------------------------------------- -void CMathCounter::InputAdd( inputdata_t &inputdata ) -{ - if( m_bDisabled ) - { - DevMsg("Math Counter %s ignoring ADD because it is disabled\n", GetDebugName() ); - return; - } - - float fNewValue = m_OutValue.Get() + inputdata.value.Float(); - UpdateOutValue( inputdata.pActivator, fNewValue ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for multiplying the current value. -// Input : Float value to multiply the value by. -//----------------------------------------------------------------------------- -void CMathCounter::InputDivide( inputdata_t &inputdata ) -{ - if( m_bDisabled ) - { - DevMsg("Math Counter %s ignoring DIVIDE because it is disabled\n", GetDebugName() ); - return; - } - - if (inputdata.value.Float() != 0) - { - float fNewValue = m_OutValue.Get() / inputdata.value.Float(); - UpdateOutValue( inputdata.pActivator, fNewValue ); - } - else - { - DevMsg( 1, "LEVEL DESIGN ERROR: Divide by zero in math_value\n" ); - UpdateOutValue( inputdata.pActivator, m_OutValue.Get() ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for multiplying the current value. -// Input : Float value to multiply the value by. -//----------------------------------------------------------------------------- -void CMathCounter::InputMultiply( inputdata_t &inputdata ) -{ - if( m_bDisabled ) - { - DevMsg("Math Counter %s ignoring MULTIPLY because it is disabled\n", GetDebugName() ); - return; - } - - float fNewValue = m_OutValue.Get() * inputdata.value.Float(); - UpdateOutValue( inputdata.pActivator, fNewValue ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for updating the value. -// Input : Float value to set. -//----------------------------------------------------------------------------- -void CMathCounter::InputSetValue( inputdata_t &inputdata ) -{ - if( m_bDisabled ) - { - DevMsg("Math Counter %s ignoring SETVALUE because it is disabled\n", GetDebugName() ); - return; - } - - UpdateOutValue( inputdata.pActivator, inputdata.value.Float() ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for updating the value. -// Input : Float value to set. -//----------------------------------------------------------------------------- -void CMathCounter::InputSetValueNoFire( inputdata_t &inputdata ) -{ - if( m_bDisabled ) - { - DevMsg("Math Counter %s ignoring SETVALUENOFIRE because it is disabled\n", GetDebugName() ); - return; - } - - float flNewValue = inputdata.value.Float(); - if (( m_flMin != 0 ) || (m_flMax != 0 )) - { - flNewValue = clamp(flNewValue, m_flMin, m_flMax); - } - - m_OutValue.Init( flNewValue ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for subtracting from the current value. -// Input : Float value to subtract. -//----------------------------------------------------------------------------- -void CMathCounter::InputSubtract( inputdata_t &inputdata ) -{ - if( m_bDisabled ) - { - DevMsg("Math Counter %s ignoring SUBTRACT because it is disabled\n", GetDebugName() ); - return; - } - - float fNewValue = m_OutValue.Get() - inputdata.value.Float(); - UpdateOutValue( inputdata.pActivator, fNewValue ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CMathCounter::InputGetValue( inputdata_t &inputdata ) -{ - float flOutValue = m_OutValue.Get(); - m_OnGetValue.Set( flOutValue, inputdata.pActivator, inputdata.pCaller ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CMathCounter::InputEnable( inputdata_t &inputdata ) -{ - m_bDisabled = false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CMathCounter::InputDisable( inputdata_t &inputdata ) -{ - m_bDisabled = true; -} - -//----------------------------------------------------------------------------- -// Purpose: Sets the value to the new value, clamping and firing the output value. -// Input : fNewValue - Value to set. -//----------------------------------------------------------------------------- -void CMathCounter::UpdateOutValue(CBaseEntity *pActivator, float fNewValue) -{ - if ((m_flMin != 0) || (m_flMax != 0)) - { - // - // Fire an output any time we reach or exceed our maximum value. - // - if ( fNewValue >= m_flMax ) - { - if ( !m_bHitMax ) - { - m_bHitMax = true; - m_OnHitMax.FireOutput( pActivator, this ); - } - } - else - { - m_bHitMax = false; - } - - // - // Fire an output any time we reach or go below our minimum value. - // - if ( fNewValue <= m_flMin ) - { - if ( !m_bHitMin ) - { - m_bHitMin = true; - m_OnHitMin.FireOutput( pActivator, this ); - } - } - else - { - m_bHitMin = false; - } - - fNewValue = clamp(fNewValue, m_flMin, m_flMax); - } - - m_OutValue.Set(fNewValue, pActivator, this); -} - - - -//----------------------------------------------------------------------------- -// Purpose: Compares a single string input to up to 16 case values, firing an -// output corresponding to the case value that matched, or a default -// output if the input value didn't match any of the case values. -// -// This can also be used to fire a random output from a set of outputs. -//----------------------------------------------------------------------------- -#define MAX_LOGIC_CASES 16 - -class CLogicCase : public CLogicalEntity -{ - DECLARE_CLASS( CLogicCase, CLogicalEntity ); -private: - string_t m_nCase[MAX_LOGIC_CASES]; - - int m_nShuffleCases; - int m_nLastShuffleCase; - unsigned char m_uchShuffleCaseMap[MAX_LOGIC_CASES]; - - void Spawn(void); - - int BuildCaseMap(unsigned char *puchMap); - - // Inputs - void InputValue( inputdata_t &inputdata ); - void InputPickRandom( inputdata_t &inputdata ); - void InputPickRandomShuffle( inputdata_t &inputdata ); - - // Outputs - COutputEvent m_OnCase[MAX_LOGIC_CASES]; // Fired when the input value matches one of the case values. - COutputVariant m_OnDefault; // Fired when no match was found. - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS(logic_case, CLogicCase); - - -BEGIN_DATADESC( CLogicCase ) - -// Silence, Classcheck! -// DEFINE_ARRAY( m_nCase, FIELD_STRING, MAX_LOGIC_CASES ), - - // Keys - DEFINE_KEYFIELD(m_nCase[0], FIELD_STRING, "Case01"), - DEFINE_KEYFIELD(m_nCase[1], FIELD_STRING, "Case02"), - DEFINE_KEYFIELD(m_nCase[2], FIELD_STRING, "Case03"), - DEFINE_KEYFIELD(m_nCase[3], FIELD_STRING, "Case04"), - DEFINE_KEYFIELD(m_nCase[4], FIELD_STRING, "Case05"), - DEFINE_KEYFIELD(m_nCase[5], FIELD_STRING, "Case06"), - DEFINE_KEYFIELD(m_nCase[6], FIELD_STRING, "Case07"), - DEFINE_KEYFIELD(m_nCase[7], FIELD_STRING, "Case08"), - DEFINE_KEYFIELD(m_nCase[8], FIELD_STRING, "Case09"), - DEFINE_KEYFIELD(m_nCase[9], FIELD_STRING, "Case10"), - DEFINE_KEYFIELD(m_nCase[10], FIELD_STRING, "Case11"), - DEFINE_KEYFIELD(m_nCase[11], FIELD_STRING, "Case12"), - DEFINE_KEYFIELD(m_nCase[12], FIELD_STRING, "Case13"), - DEFINE_KEYFIELD(m_nCase[13], FIELD_STRING, "Case14"), - DEFINE_KEYFIELD(m_nCase[14], FIELD_STRING, "Case15"), - DEFINE_KEYFIELD(m_nCase[15], FIELD_STRING, "Case16"), - - DEFINE_FIELD( m_nShuffleCases, FIELD_INTEGER ), - DEFINE_FIELD( m_nLastShuffleCase, FIELD_INTEGER ), - DEFINE_ARRAY( m_uchShuffleCaseMap, FIELD_CHARACTER, MAX_LOGIC_CASES ), - - // Inputs - DEFINE_INPUTFUNC(FIELD_INPUT, "InValue", InputValue), - DEFINE_INPUTFUNC(FIELD_VOID, "PickRandom", InputPickRandom), - DEFINE_INPUTFUNC(FIELD_VOID, "PickRandomShuffle", InputPickRandomShuffle), - - // Outputs - DEFINE_OUTPUT(m_OnCase[0], "OnCase01"), - DEFINE_OUTPUT(m_OnCase[1], "OnCase02"), - DEFINE_OUTPUT(m_OnCase[2], "OnCase03"), - DEFINE_OUTPUT(m_OnCase[3], "OnCase04"), - DEFINE_OUTPUT(m_OnCase[4], "OnCase05"), - DEFINE_OUTPUT(m_OnCase[5], "OnCase06"), - DEFINE_OUTPUT(m_OnCase[6], "OnCase07"), - DEFINE_OUTPUT(m_OnCase[7], "OnCase08"), - DEFINE_OUTPUT(m_OnCase[8], "OnCase09"), - DEFINE_OUTPUT(m_OnCase[9], "OnCase10"), - DEFINE_OUTPUT(m_OnCase[10], "OnCase11"), - DEFINE_OUTPUT(m_OnCase[11], "OnCase12"), - DEFINE_OUTPUT(m_OnCase[12], "OnCase13"), - DEFINE_OUTPUT(m_OnCase[13], "OnCase14"), - DEFINE_OUTPUT(m_OnCase[14], "OnCase15"), - DEFINE_OUTPUT(m_OnCase[15], "OnCase16"), - - DEFINE_OUTPUT(m_OnDefault, "OnDefault"), - -END_DATADESC() - - - - -//----------------------------------------------------------------------------- -// Purpose: Called before spawning, after key values have been set. -//----------------------------------------------------------------------------- -void CLogicCase::Spawn( void ) -{ - m_nLastShuffleCase = -1; -} - - -//----------------------------------------------------------------------------- -// Purpose: Evaluates the new input value, firing the appropriate OnCaseX output -// if the input value matches one of the "CaseX" keys. -// Input : Value - Variant value to compare against the values of the case fields. -// We use a variant so that we can convert any input type to a string. -//----------------------------------------------------------------------------- -void CLogicCase::InputValue( inputdata_t &inputdata ) -{ - const char *pszValue = inputdata.value.String(); - for (int i = 0; i < MAX_LOGIC_CASES; i++) - { - if ((m_nCase[i] != NULL_STRING) && !stricmp(STRING(m_nCase[i]), pszValue)) - { - m_OnCase[i].FireOutput( inputdata.pActivator, this ); - return; - } - } - - m_OnDefault.Set( inputdata.value, inputdata.pActivator, this ); -} - - -//----------------------------------------------------------------------------- -// Count the number of valid cases, building a packed array -// that maps 0..NumCases to the actual CaseX values. -// -// This allows our zany mappers to set up cases sparsely if they desire. -// NOTE: assumes pnMap points to an array of MAX_LOGIC_CASES -//----------------------------------------------------------------------------- -int CLogicCase::BuildCaseMap(unsigned char *puchCaseMap) -{ - memset(puchCaseMap, 0, sizeof(unsigned char) * MAX_LOGIC_CASES); - - int nNumCases = 0; - for (int i = 0; i < MAX_LOGIC_CASES; i++) - { - if (m_OnCase[i].NumberOfElements() > 0) - { - puchCaseMap[nNumCases] = (unsigned char)i; - nNumCases++; - } - } - - return nNumCases; -} - - -//----------------------------------------------------------------------------- -// Purpose: Makes the case statement choose a case at random. -//----------------------------------------------------------------------------- -void CLogicCase::InputPickRandom( inputdata_t &inputdata ) -{ - unsigned char uchCaseMap[MAX_LOGIC_CASES]; - int nNumCases = BuildCaseMap( uchCaseMap ); - - // - // Choose a random case from the ones that were set up by the level designer. - // - if ( nNumCases > 0 ) - { - int nRandom = random->RandomInt(0, nNumCases - 1); - int nCase = (unsigned char)uchCaseMap[nRandom]; - - Assert(nCase < MAX_LOGIC_CASES); - - if (nCase < MAX_LOGIC_CASES) - { - m_OnCase[nCase].FireOutput( inputdata.pActivator, this ); - } - } - else - { - DevMsg( 1, "Firing PickRandom input on logic_case %s with no cases set up\n", GetDebugName() ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Makes the case statement choose a case at random. -//----------------------------------------------------------------------------- -void CLogicCase::InputPickRandomShuffle( inputdata_t &inputdata ) -{ - int nAvoidCase = -1; - int nCaseCount = m_nShuffleCases; - - if ( nCaseCount == 0 ) - { - // Starting a new shuffle batch. - nCaseCount = m_nShuffleCases = BuildCaseMap( m_uchShuffleCaseMap ); - - if ( ( m_nShuffleCases > 1 ) && ( m_nLastShuffleCase != -1 ) ) - { - // Remove the previously picked case from the case map for this pick only. - // This avoids repeats across shuffle batch boundaries. - nAvoidCase = m_nLastShuffleCase; - - for (int i = 0; i < m_nShuffleCases; i++ ) - { - if ( m_uchShuffleCaseMap[i] == nAvoidCase ) - { - unsigned char uchSwap = m_uchShuffleCaseMap[i]; - m_uchShuffleCaseMap[i] = m_uchShuffleCaseMap[nCaseCount - 1]; - m_uchShuffleCaseMap[nCaseCount - 1] = uchSwap; - nCaseCount--; - break; - } - } - } - } - - // - // Choose a random case from the ones that were set up by the level designer. - // Never repeat a case within a shuffle batch, nor consecutively across batches. - // - if ( nCaseCount > 0 ) - { - int nRandom = random->RandomInt( 0, nCaseCount - 1 ); - - int nCase = m_uchShuffleCaseMap[nRandom]; - Assert(nCase < MAX_LOGIC_CASES); - - if (nCase < MAX_LOGIC_CASES) - { - m_OnCase[nCase].FireOutput( inputdata.pActivator, this ); - } - - m_uchShuffleCaseMap[nRandom] = m_uchShuffleCaseMap[m_nShuffleCases - 1]; - m_nShuffleCases--; - - m_nLastShuffleCase = nCase; - } - else - { - DevMsg( 1, "Firing PickRandom input on logic_case %s with no cases set up\n", GetDebugName() ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Compares a floating point input to a predefined value, firing an -// output to indicate the result of the comparison. -//----------------------------------------------------------------------------- -class CLogicCompare : public CLogicalEntity -{ - DECLARE_CLASS( CLogicCompare, CLogicalEntity ); - -public: - int DrawDebugTextOverlays(void); - -private: - // Inputs - void InputSetValue( inputdata_t &inputdata ); - void InputSetValueCompare( inputdata_t &inputdata ); - void InputSetCompareValue( inputdata_t &inputdata ); - void InputCompare( inputdata_t &inputdata ); - - void DoCompare(CBaseEntity *pActivator, float flInValue); - - float m_flInValue; // Place to hold the last input value for a recomparison. - float m_flCompareValue; // The value to compare the input value against. - - // Outputs - COutputFloat m_OnLessThan; // Fired when the input value is less than the compare value. - COutputFloat m_OnEqualTo; // Fired when the input value is equal to the compare value. - COutputFloat m_OnNotEqualTo; // Fired when the input value is not equal to the compare value. - COutputFloat m_OnGreaterThan; // Fired when the input value is greater than the compare value. - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS(logic_compare, CLogicCompare); - - -BEGIN_DATADESC( CLogicCompare ) - - // Keys - DEFINE_KEYFIELD(m_flCompareValue, FIELD_FLOAT, "CompareValue"), - DEFINE_KEYFIELD(m_flInValue, FIELD_FLOAT, "InitialValue"), - - // Inputs - DEFINE_INPUTFUNC(FIELD_FLOAT, "SetValue", InputSetValue), - DEFINE_INPUTFUNC(FIELD_FLOAT, "SetValueCompare", InputSetValueCompare), - DEFINE_INPUTFUNC(FIELD_FLOAT, "SetCompareValue", InputSetCompareValue), - DEFINE_INPUTFUNC(FIELD_VOID, "Compare", InputCompare), - - // Outputs - DEFINE_OUTPUT(m_OnEqualTo, "OnEqualTo"), - DEFINE_OUTPUT(m_OnNotEqualTo, "OnNotEqualTo"), - DEFINE_OUTPUT(m_OnGreaterThan, "OnGreaterThan"), - DEFINE_OUTPUT(m_OnLessThan, "OnLessThan"), - -END_DATADESC() - - - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for a new input value without performing a comparison. -//----------------------------------------------------------------------------- -void CLogicCompare::InputSetValue( inputdata_t &inputdata ) -{ - m_flInValue = inputdata.value.Float(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for a setting a new value and doing the comparison. -//----------------------------------------------------------------------------- -void CLogicCompare::InputSetValueCompare( inputdata_t &inputdata ) -{ - m_flInValue = inputdata.value.Float(); - DoCompare( inputdata.pActivator, m_flInValue ); -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for a new input value without performing a comparison. -//----------------------------------------------------------------------------- -void CLogicCompare::InputSetCompareValue( inputdata_t &inputdata ) -{ - m_flCompareValue = inputdata.value.Float(); -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for forcing a recompare of the last input value. -//----------------------------------------------------------------------------- -void CLogicCompare::InputCompare( inputdata_t &inputdata ) -{ - DoCompare( inputdata.pActivator, m_flInValue ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Compares the input value to the compare value, firing the appropriate -// output(s) based on the comparison result. -// Input : flInValue - Value to compare against the comparison value. -//----------------------------------------------------------------------------- -void CLogicCompare::DoCompare(CBaseEntity *pActivator, float flInValue) -{ - if (flInValue == m_flCompareValue) - { - m_OnEqualTo.Set(flInValue, pActivator, this); - } - else - { - m_OnNotEqualTo.Set(flInValue, pActivator, this); - - if (flInValue > m_flCompareValue) - { - m_OnGreaterThan.Set(flInValue, pActivator, this); - } - else - { - m_OnLessThan.Set(flInValue, pActivator, this); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CLogicCompare::DrawDebugTextOverlays( void ) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - - // print duration - Q_snprintf(tempstr,sizeof(tempstr)," Initial Value: %f", m_flInValue); - EntityText(text_offset,tempstr,0); - text_offset++; - - // print hold time - Q_snprintf(tempstr,sizeof(tempstr)," Compare Value: %f", m_flCompareValue); - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} - -//----------------------------------------------------------------------------- -// Purpose: Tests a boolean value, firing an output to indicate whether the -// value was true or false. -//----------------------------------------------------------------------------- -class CLogicBranch : public CLogicalEntity -{ - DECLARE_CLASS( CLogicBranch, CLogicalEntity ); - -public: - - void UpdateOnRemove(); - - void AddLogicBranchListener( CBaseEntity *pEntity ); - inline bool GetLogicBranchState(); - virtual int DrawDebugTextOverlays( void ); - -private: - - enum LogicBranchFire_t - { - LOGIC_BRANCH_FIRE, - LOGIC_BRANCH_NO_FIRE, - }; - - // Inputs - void InputSetValue( inputdata_t &inputdata ); - void InputSetValueTest( inputdata_t &inputdata ); - void InputToggle( inputdata_t &inputdata ); - void InputToggleTest( inputdata_t &inputdata ); - void InputTest( inputdata_t &inputdata ); - - void UpdateValue(bool bNewValue, CBaseEntity *pActivator, LogicBranchFire_t eFire); - - bool m_bInValue; // Place to hold the last input value for a future test. - - CUtlVector m_Listeners; // A list of logic_branch_listeners that are monitoring us. - - // Outputs - COutputEvent m_OnTrue; // Fired when the value is true. - COutputEvent m_OnFalse; // Fired when the value is false. - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS(logic_branch, CLogicBranch); - - -BEGIN_DATADESC( CLogicBranch ) - - // Keys - DEFINE_KEYFIELD(m_bInValue, FIELD_BOOLEAN, "InitialValue"), - - DEFINE_UTLVECTOR( m_Listeners, FIELD_EHANDLE ), - - // Inputs - DEFINE_INPUTFUNC(FIELD_BOOLEAN, "SetValue", InputSetValue), - DEFINE_INPUTFUNC(FIELD_BOOLEAN, "SetValueTest", InputSetValueTest), - DEFINE_INPUTFUNC(FIELD_VOID, "Toggle", InputToggle), - DEFINE_INPUTFUNC(FIELD_VOID, "ToggleTest", InputToggleTest), - DEFINE_INPUTFUNC(FIELD_VOID, "Test", InputTest), - - // Outputs - DEFINE_OUTPUT(m_OnTrue, "OnTrue"), - DEFINE_OUTPUT(m_OnFalse, "OnFalse"), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CLogicBranch::UpdateOnRemove() -{ - for ( int i = 0; i < m_Listeners.Count(); i++ ) - { - CBaseEntity *pEntity = m_Listeners.Element( i ).Get(); - if ( pEntity ) - { - g_EventQueue.AddEvent( this, "_OnLogicBranchRemoved", 0, this, this ); - } - } - - BaseClass::UpdateOnRemove(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler to set a new input value without firing outputs. -// Input : Boolean value to set. -//----------------------------------------------------------------------------- -void CLogicBranch::InputSetValue( inputdata_t &inputdata ) -{ - UpdateValue( inputdata.value.Bool(), inputdata.pActivator, LOGIC_BRANCH_NO_FIRE ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler to set a new input value and fire appropriate outputs. -// Input : Boolean value to set. -//----------------------------------------------------------------------------- -void CLogicBranch::InputSetValueTest( inputdata_t &inputdata ) -{ - UpdateValue( inputdata.value.Bool(), inputdata.pActivator, LOGIC_BRANCH_FIRE ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for toggling the boolean value without firing outputs. -//----------------------------------------------------------------------------- -void CLogicBranch::InputToggle( inputdata_t &inputdata ) -{ - UpdateValue( !m_bInValue, inputdata.pActivator, LOGIC_BRANCH_NO_FIRE ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for toggling the boolean value and then firing the -// appropriate output based on the new value. -//----------------------------------------------------------------------------- -void CLogicBranch::InputToggleTest( inputdata_t &inputdata ) -{ - UpdateValue( !m_bInValue, inputdata.pActivator, LOGIC_BRANCH_FIRE ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for forcing a test of the last input value. -//----------------------------------------------------------------------------- -void CLogicBranch::InputTest( inputdata_t &inputdata ) -{ - UpdateValue( m_bInValue, inputdata.pActivator, LOGIC_BRANCH_FIRE ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Tests the last input value, firing the appropriate output based on -// the test result. -// Input : bInValue - -//----------------------------------------------------------------------------- -void CLogicBranch::UpdateValue( bool bNewValue, CBaseEntity *pActivator, LogicBranchFire_t eFire ) -{ - if ( m_bInValue != bNewValue ) - { - m_bInValue = bNewValue; - - for ( int i = 0; i < m_Listeners.Count(); i++ ) - { - CBaseEntity *pEntity = m_Listeners.Element( i ).Get(); - if ( pEntity ) - { - g_EventQueue.AddEvent( pEntity, "_OnLogicBranchChanged", 0, this, this ); - } - } - } - - if ( eFire == LOGIC_BRANCH_FIRE ) - { - if ( m_bInValue ) - { - m_OnTrue.FireOutput( pActivator, this ); - } - else - { - m_OnFalse.FireOutput( pActivator, this ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Accessor for logic_branchlist to test the value of the branch on demand. -//----------------------------------------------------------------------------- -bool CLogicBranch::GetLogicBranchState() -{ - return m_bInValue; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CLogicBranch::AddLogicBranchListener( CBaseEntity *pEntity ) -{ - if ( m_Listeners.Find( pEntity ) == -1 ) - { - m_Listeners.AddToTail( pEntity ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CLogicBranch::DrawDebugTextOverlays( void ) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - - // print refire time - Q_snprintf( tempstr, sizeof(tempstr), "Branch value: %s", (m_bInValue) ? "TRUE" : "FALSE" ); - EntityText( text_offset, tempstr, 0 ); - text_offset++; - } - - return text_offset; -} - -//----------------------------------------------------------------------------- -// Purpose: Autosaves when triggered -//----------------------------------------------------------------------------- -class CLogicAutosave : public CLogicalEntity -{ - DECLARE_CLASS( CLogicAutosave, CLogicalEntity ); - -protected: - // Inputs - void InputSave( inputdata_t &inputdata ); - void InputSaveDangerous( inputdata_t &inputdata ); - void InputSetMinHitpointsThreshold( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - bool m_bForceNewLevelUnit; - int m_minHitPoints; - int m_minHitPointsToCommit; -}; - -LINK_ENTITY_TO_CLASS(logic_autosave, CLogicAutosave); - -BEGIN_DATADESC( CLogicAutosave ) - DEFINE_KEYFIELD( m_bForceNewLevelUnit, FIELD_BOOLEAN, "NewLevelUnit" ), - DEFINE_KEYFIELD( m_minHitPoints, FIELD_INTEGER, "MinimumHitPoints" ), - DEFINE_KEYFIELD( m_minHitPointsToCommit, FIELD_INTEGER, "MinHitPointsToCommit" ), - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Save", InputSave ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SaveDangerous", InputSaveDangerous ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetMinHitpointsThreshold", InputSetMinHitpointsThreshold ), -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: Save! -//----------------------------------------------------------------------------- -void CLogicAutosave::InputSave( inputdata_t &inputdata ) -{ - if ( m_bForceNewLevelUnit ) - { - engine->ClearSaveDir(); - } - - engine->ServerCommand( "autosave\n" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Save safely! -//----------------------------------------------------------------------------- -void CLogicAutosave::InputSaveDangerous( inputdata_t &inputdata ) -{ - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); - - if ( g_ServerGameDLL.m_fAutoSaveDangerousTime != 0.0f && g_ServerGameDLL.m_fAutoSaveDangerousTime >= gpGlobals->curtime ) - { - // A previous dangerous auto save was waiting to become safe - - if ( pPlayer->GetDeathTime() == 0.0f || pPlayer->GetDeathTime() > gpGlobals->curtime ) - { - // The player isn't dead, so make the dangerous auto save safe - engine->ServerCommand( "autosavedangerousissafe\n" ); - } - } - - if ( m_bForceNewLevelUnit ) - { - engine->ClearSaveDir(); - } - - if ( pPlayer->GetHealth() >= m_minHitPoints ) - { - engine->ServerCommand( "autosavedangerous\n" ); - g_ServerGameDLL.m_fAutoSaveDangerousTime = gpGlobals->curtime + inputdata.value.Float(); - - // Player must have this much health when we go to commit, or we don't commit. - g_ServerGameDLL.m_fAutoSaveDangerousMinHealthToCommit = m_minHitPointsToCommit; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Autosaves when triggered -//----------------------------------------------------------------------------- -class CLogicActiveAutosave : public CLogicAutosave -{ - DECLARE_CLASS( CLogicActiveAutosave, CLogicAutosave ); - - void InputEnable( inputdata_t &inputdata ) - { - m_flStartTime = -1; - SetThink( &CLogicActiveAutosave::SaveThink ); - SetNextThink( gpGlobals->curtime ); - } - - void InputDisable( inputdata_t &inputdata ) - { - SetThink( NULL ); - } - - void SaveThink() - { - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - if ( pPlayer ) - { - if ( m_flStartTime < 0 ) - { - if ( pPlayer->GetHealth() <= m_minHitPoints ) - { - m_flStartTime = gpGlobals->curtime; - } - } - else - { - if ( pPlayer->GetHealth() >= m_TriggerHitPoints ) - { - inputdata_t inputdata; - DevMsg( 2, "logic_active_autosave (%s, %d) triggered\n", STRING( GetEntityName() ), entindex() ); - if ( !m_flDangerousTime ) - { - InputSave( inputdata ); - } - else - { - inputdata.value.SetFloat( m_flDangerousTime ); - InputSaveDangerous( inputdata ); - } - m_flStartTime = -1; - } - else if ( m_flTimeToTrigger > 0 && gpGlobals->curtime - m_flStartTime > m_flTimeToTrigger ) - { - m_flStartTime = -1; - } - } - } - - float thinkInterval = ( m_flStartTime < 0 ) ? 1.0 : 0.5; - SetNextThink( gpGlobals->curtime + thinkInterval ); - } - - DECLARE_DATADESC(); - - int m_TriggerHitPoints; - float m_flTimeToTrigger; - float m_flStartTime; - float m_flDangerousTime; -}; - -LINK_ENTITY_TO_CLASS(logic_active_autosave, CLogicActiveAutosave); - -BEGIN_DATADESC( CLogicActiveAutosave ) - DEFINE_KEYFIELD( m_TriggerHitPoints, FIELD_INTEGER, "TriggerHitPoints" ), - DEFINE_KEYFIELD( m_flTimeToTrigger, FIELD_FLOAT, "TimeToTrigger" ), - DEFINE_KEYFIELD( m_flDangerousTime, FIELD_FLOAT, "DangerousTime" ), - DEFINE_FIELD( m_flStartTime, FIELD_TIME ), - DEFINE_THINKFUNC( SaveThink ), - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: Keyfield set func -//----------------------------------------------------------------------------- -void CLogicAutosave::InputSetMinHitpointsThreshold( inputdata_t &inputdata ) -{ - int setTo = inputdata.value.Int(); - AssertMsg1(setTo >= 0 && setTo <= 100, "Tried to set autosave MinHitpointsThreshold to %d!\n", setTo); - m_minHitPoints = setTo; -} - -// Finds the named physics object. If no name, returns the world -// If a name is specified and an object not found - errors are reported -IPhysicsObject *FindPhysicsObjectByNameOrWorld( string_t name, CBaseEntity *pErrorEntity ) -{ - if ( !name ) - return g_PhysWorldObject; - - IPhysicsObject *pPhysics = FindPhysicsObjectByName( name.ToCStr(), pErrorEntity ); - if ( !pPhysics ) - { - DevWarning("%s: can't find %s\n", pErrorEntity->GetClassname(), name.ToCStr()); - } - return pPhysics; -} - -class CLogicCollisionPair : public CLogicalEntity -{ - DECLARE_CLASS( CLogicCollisionPair, CLogicalEntity ); -public: - - void EnableCollisions( bool bEnable ) - { - IPhysicsObject *pPhysics0 = FindPhysicsObjectByNameOrWorld( m_nameAttach1, this ); - IPhysicsObject *pPhysics1 = FindPhysicsObjectByNameOrWorld( m_nameAttach2, this ); - - // need two different objects to do anything - if ( pPhysics0 && pPhysics1 && pPhysics0 != pPhysics1 ) - { - m_disabled = !bEnable; - m_succeeded = true; - if ( bEnable ) - { - PhysEnableEntityCollisions( pPhysics0, pPhysics1 ); - } - else - { - PhysDisableEntityCollisions( pPhysics0, pPhysics1 ); - } - } - else - { - m_succeeded = false; - } - } - - void Activate( void ) - { - if ( m_disabled ) - { - EnableCollisions( false ); - } - BaseClass::Activate(); - } - - void InputDisableCollisions( inputdata_t &inputdata ) - { - if ( m_succeeded && m_disabled ) - return; - EnableCollisions( false ); - } - - void InputEnableCollisions( inputdata_t &inputdata ) - { - if ( m_succeeded && !m_disabled ) - return; - EnableCollisions( true ); - } - // If Activate() becomes PostSpawn() - //void OnRestore() { Activate(); } - - DECLARE_DATADESC(); - -private: - string_t m_nameAttach1; - string_t m_nameAttach2; - bool m_disabled; - bool m_succeeded; -}; - -BEGIN_DATADESC( CLogicCollisionPair ) - DEFINE_KEYFIELD( m_nameAttach1, FIELD_STRING, "attach1" ), - DEFINE_KEYFIELD( m_nameAttach2, FIELD_STRING, "attach2" ), - DEFINE_KEYFIELD( m_disabled, FIELD_BOOLEAN, "startdisabled" ), - DEFINE_FIELD( m_succeeded, FIELD_BOOLEAN ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "DisableCollisions", InputDisableCollisions ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableCollisions", InputEnableCollisions ), -END_DATADESC() - -LINK_ENTITY_TO_CLASS( logic_collision_pair, CLogicCollisionPair ); - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -#define MAX_LOGIC_BRANCH_NAMES 16 - -class CLogicBranchList : public CLogicalEntity -{ - DECLARE_CLASS( CLogicBranchList, CLogicalEntity ); - - virtual void Spawn(); - virtual void Activate(); - virtual int DrawDebugTextOverlays( void ); - -private: - - enum LogicBranchListenerLastState_t - { - LOGIC_BRANCH_LISTENER_NOT_INIT = 0, - LOGIC_BRANCH_LISTENER_ALL_TRUE, - LOGIC_BRANCH_LISTENER_ALL_FALSE, - LOGIC_BRANCH_LISTENER_MIXED, - }; - - void DoTest( CBaseEntity *pActivator ); - - string_t m_nLogicBranchNames[MAX_LOGIC_BRANCH_NAMES]; - CUtlVector m_LogicBranchList; - LogicBranchListenerLastState_t m_eLastState; - - // Inputs - void Input_OnLogicBranchRemoved( inputdata_t &inputdata ); - void Input_OnLogicBranchChanged( inputdata_t &inputdata ); - void InputTest( inputdata_t &inputdata ); - - // Outputs - COutputEvent m_OnAllTrue; // Fired when all the registered logic_branches become true. - COutputEvent m_OnAllFalse; // Fired when all the registered logic_branches become false. - COutputEvent m_OnMixed; // Fired when one of the registered logic branches changes, but not all are true or false. - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS(logic_branch_listener, CLogicBranchList); - - -BEGIN_DATADESC( CLogicBranchList ) - - // Silence, classcheck! - //DEFINE_ARRAY( m_nLogicBranchNames, FIELD_STRING, MAX_LOGIC_BRANCH_NAMES ), - - // Keys - DEFINE_KEYFIELD( m_nLogicBranchNames[0], FIELD_STRING, "Branch01" ), - DEFINE_KEYFIELD( m_nLogicBranchNames[1], FIELD_STRING, "Branch02" ), - DEFINE_KEYFIELD( m_nLogicBranchNames[2], FIELD_STRING, "Branch03" ), - DEFINE_KEYFIELD( m_nLogicBranchNames[3], FIELD_STRING, "Branch04" ), - DEFINE_KEYFIELD( m_nLogicBranchNames[4], FIELD_STRING, "Branch05" ), - DEFINE_KEYFIELD( m_nLogicBranchNames[5], FIELD_STRING, "Branch06" ), - DEFINE_KEYFIELD( m_nLogicBranchNames[6], FIELD_STRING, "Branch07" ), - DEFINE_KEYFIELD( m_nLogicBranchNames[7], FIELD_STRING, "Branch08" ), - DEFINE_KEYFIELD( m_nLogicBranchNames[8], FIELD_STRING, "Branch09" ), - DEFINE_KEYFIELD( m_nLogicBranchNames[9], FIELD_STRING, "Branch10" ), - DEFINE_KEYFIELD( m_nLogicBranchNames[10], FIELD_STRING, "Branch11" ), - DEFINE_KEYFIELD( m_nLogicBranchNames[11], FIELD_STRING, "Branch12" ), - DEFINE_KEYFIELD( m_nLogicBranchNames[12], FIELD_STRING, "Branch13" ), - DEFINE_KEYFIELD( m_nLogicBranchNames[13], FIELD_STRING, "Branch14" ), - DEFINE_KEYFIELD( m_nLogicBranchNames[14], FIELD_STRING, "Branch15" ), - DEFINE_KEYFIELD( m_nLogicBranchNames[15], FIELD_STRING, "Branch16" ), - - DEFINE_UTLVECTOR( m_LogicBranchList, FIELD_EHANDLE ), - - DEFINE_FIELD( m_eLastState, FIELD_INTEGER ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_INPUT, "Test", InputTest ), - DEFINE_INPUTFUNC( FIELD_INPUT, "_OnLogicBranchChanged", Input_OnLogicBranchChanged ), - DEFINE_INPUTFUNC( FIELD_INPUT, "_OnLogicBranchRemoved", Input_OnLogicBranchRemoved ), - - // Outputs - DEFINE_OUTPUT( m_OnAllTrue, "OnAllTrue" ), - DEFINE_OUTPUT( m_OnAllFalse, "OnAllFalse" ), - DEFINE_OUTPUT( m_OnMixed, "OnMixed" ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: Called before spawning, after key values have been set. -//----------------------------------------------------------------------------- -void CLogicBranchList::Spawn( void ) -{ -} - - -//----------------------------------------------------------------------------- -// Finds all the logic_branches that we are monitoring and register ourselves with them. -//----------------------------------------------------------------------------- -void CLogicBranchList::Activate( void ) -{ - for ( int i = 0; i < MAX_LOGIC_BRANCH_NAMES; i++ ) - { - CBaseEntity *pEntity = NULL; - while ( ( pEntity = gEntList.FindEntityGeneric( pEntity, STRING( m_nLogicBranchNames[i] ), this ) ) != NULL ) - { - if ( FClassnameIs( pEntity, "logic_branch" ) ) - { - CLogicBranch *pBranch = (CLogicBranch *)pEntity; - pBranch->AddLogicBranchListener( this ); - m_LogicBranchList.AddToTail( pBranch ); - } - else - { - DevWarning( "logic_branchlist %s refers to entity %s, which is not a logic_branch\n", GetDebugName(), pEntity->GetDebugName() ); - } - } - } - - BaseClass::Activate(); -} - - -//----------------------------------------------------------------------------- -// Called when a monitored logic branch is deleted from the world, since that -// might affect our final result. -//----------------------------------------------------------------------------- -void CLogicBranchList::Input_OnLogicBranchRemoved( inputdata_t &inputdata ) -{ - int nIndex = m_LogicBranchList.Find( inputdata.pActivator ); - if ( nIndex != -1 ) - { - m_LogicBranchList.FastRemove( nIndex ); - } - - // See if this logic_branch's deletion affects the final result. - DoTest( inputdata.pActivator ); -} - - -//----------------------------------------------------------------------------- -// Called when the value of a monitored logic branch changes. -//----------------------------------------------------------------------------- -void CLogicBranchList::Input_OnLogicBranchChanged( inputdata_t &inputdata ) -{ - DoTest( inputdata.pActivator ); -} - - -//----------------------------------------------------------------------------- -// Input handler to manually test the monitored logic branches and fire the -// appropriate output. -//----------------------------------------------------------------------------- -void CLogicBranchList::InputTest( inputdata_t &inputdata ) -{ - // Force an output. - m_eLastState = LOGIC_BRANCH_LISTENER_NOT_INIT; - - DoTest( inputdata.pActivator ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CLogicBranchList::DoTest( CBaseEntity *pActivator ) -{ - bool bOneTrue = false; - bool bOneFalse = false; - - for ( int i = 0; i < m_LogicBranchList.Count(); i++ ) - { - CLogicBranch *pBranch = (CLogicBranch *)m_LogicBranchList.Element( i ).Get(); - if ( pBranch && pBranch->GetLogicBranchState() ) - { - bOneTrue = true; - } - else - { - bOneFalse = true; - } - } - - // Only fire the output if the new result differs from the last result. - if ( bOneTrue && !bOneFalse ) - { - if ( m_eLastState != LOGIC_BRANCH_LISTENER_ALL_TRUE ) - { - m_OnAllTrue.FireOutput( pActivator, this ); - m_eLastState = LOGIC_BRANCH_LISTENER_ALL_TRUE; - } - } - else if ( bOneFalse && !bOneTrue ) - { - if ( m_eLastState != LOGIC_BRANCH_LISTENER_ALL_FALSE ) - { - m_OnAllFalse.FireOutput( pActivator, this ); - m_eLastState = LOGIC_BRANCH_LISTENER_ALL_FALSE; - } - } - else - { - if ( m_eLastState != LOGIC_BRANCH_LISTENER_MIXED ) - { - m_OnMixed.FireOutput( pActivator, this ); - m_eLastState = LOGIC_BRANCH_LISTENER_MIXED; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CLogicBranchList::DrawDebugTextOverlays( void ) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - - for ( int i = 0; i < m_LogicBranchList.Count(); i++ ) - { - CLogicBranch *pBranch = (CLogicBranch *)m_LogicBranchList.Element( i ).Get(); - if ( pBranch ) - { - Q_snprintf( tempstr, sizeof(tempstr), "Branch (%s): %s", STRING(pBranch->GetEntityName()), (pBranch->GetLogicBranchState()) ? "TRUE" : "FALSE" ); - EntityText( text_offset, tempstr, 0 ); - text_offset++; - } - } - } - - return text_offset; -} diff --git a/game/server/logicrelay.cpp b/game/server/logicrelay.cpp deleted file mode 100644 index 124b86a42..000000000 --- a/game/server/logicrelay.cpp +++ /dev/null @@ -1,162 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ==== -// -// A message forwarder. Fires an OnTrigger output when triggered, and can be -// disabled to prevent forwarding outputs. -// -// Useful as an intermediary between one entity and another for turning on or -// off an I/O connection, or as a container for holding a set of outputs that -// can be triggered from multiple places. -// -//============================================================================= - -#include "cbase.h" -#include "entityinput.h" -#include "entityoutput.h" -#include "eventqueue.h" -#include "soundent.h" -#include "logicrelay.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -const int SF_REMOVE_ON_FIRE = 0x001; // Relay will remove itself after being triggered. -const int SF_ALLOW_FAST_RETRIGGER = 0x002; // Unless set, relay will disable itself until the last output is sent. - -LINK_ENTITY_TO_CLASS(logic_relay, CLogicRelay); - - -BEGIN_DATADESC( CLogicRelay ) - - DEFINE_FIELD(m_bWaitForRefire, FIELD_BOOLEAN), - DEFINE_KEYFIELD(m_bDisabled, FIELD_BOOLEAN, "StartDisabled"), - - // Inputs - DEFINE_INPUTFUNC(FIELD_VOID, "Enable", InputEnable), - DEFINE_INPUTFUNC(FIELD_VOID, "EnableRefire", InputEnableRefire), - DEFINE_INPUTFUNC(FIELD_VOID, "Disable", InputDisable), - DEFINE_INPUTFUNC(FIELD_VOID, "Toggle", InputToggle), - DEFINE_INPUTFUNC(FIELD_VOID, "Trigger", InputTrigger), - DEFINE_INPUTFUNC(FIELD_VOID, "CancelPending", InputCancelPending), - - // Outputs - DEFINE_OUTPUT(m_OnTrigger, "OnTrigger"), - DEFINE_OUTPUT(m_OnSpawn, "OnSpawn"), - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Purpose: Constructor. -//----------------------------------------------------------------------------- -CLogicRelay::CLogicRelay(void) -{ -} - - -//------------------------------------------------------------------------------ -// Kickstarts a think if we have OnSpawn connections. -//------------------------------------------------------------------------------ -void CLogicRelay::Activate() -{ - BaseClass::Activate(); - - if ( m_OnSpawn.NumberOfElements() > 0) - { - SetNextThink( gpGlobals->curtime + 0.01 ); - } -} - - -//----------------------------------------------------------------------------- -// If we have OnSpawn connections, this is called shortly after spawning to -// fire the OnSpawn output. -//----------------------------------------------------------------------------- -void CLogicRelay::Think() -{ - // Fire an output when we spawn. This is used for self-starting an entity - // template -- since the logic_relay is inside the template, it gets all the - // name and I/O connection fixup, so can target other entities in the template. - m_OnSpawn.FireOutput( this, this ); - - // We only get here if we had OnSpawn connections, so this is safe. - if ( m_spawnflags & SF_REMOVE_ON_FIRE ) - { - UTIL_Remove(this); - } -} - - -//------------------------------------------------------------------------------ -// Purpose: Turns on the relay, allowing it to fire outputs. -//------------------------------------------------------------------------------ -void CLogicRelay::InputEnable( inputdata_t &inputdata ) -{ - m_bDisabled = false; -} - -//------------------------------------------------------------------------------ -// Purpose: Enables us to fire again. This input is only posted from our Trigger -// function to prevent rapid refire. -//------------------------------------------------------------------------------ -void CLogicRelay::InputEnableRefire( inputdata_t &inputdata ) -{ - m_bWaitForRefire = false; -} - - -//------------------------------------------------------------------------------ -// Purpose: Cancels any I/O events in the queue that were fired by us. -//------------------------------------------------------------------------------ -void CLogicRelay::InputCancelPending( inputdata_t &inputdata ) -{ - g_EventQueue.CancelEvents( this ); - - // Stop waiting; allow another Trigger. - m_bWaitForRefire = false; -} - - -//------------------------------------------------------------------------------ -// Purpose: Turns off the relay, preventing it from firing outputs. -//------------------------------------------------------------------------------ -void CLogicRelay::InputDisable( inputdata_t &inputdata ) -{ - m_bDisabled = true; -} - - -//------------------------------------------------------------------------------ -// Purpose: Toggles the enabled/disabled state of the relay. -//------------------------------------------------------------------------------ -void CLogicRelay::InputToggle( inputdata_t &inputdata ) -{ - m_bDisabled = !m_bDisabled; -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that triggers the relay. -//----------------------------------------------------------------------------- -void CLogicRelay::InputTrigger( inputdata_t &inputdata ) -{ - if ((!m_bDisabled) && (!m_bWaitForRefire)) - { - m_OnTrigger.FireOutput( inputdata.pActivator, this ); - - if (m_spawnflags & SF_REMOVE_ON_FIRE) - { - UTIL_Remove(this); - } - else if (!(m_spawnflags & SF_ALLOW_FAST_RETRIGGER)) - { - // - // Disable the relay so that it cannot be refired until after the last output - // has been fired and post an input to re-enable ourselves. - // - m_bWaitForRefire = true; - g_EventQueue.AddEvent(this, "EnableRefire", m_OnTrigger.GetMaxDelay() + 0.001, this, this); - } - } -} - diff --git a/game/server/logicrelay.h b/game/server/logicrelay.h deleted file mode 100644 index 427d3c316..000000000 --- a/game/server/logicrelay.h +++ /dev/null @@ -1,46 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef LOGICRELAY_H -#define LOGICRELAY_H - -#include "cbase.h" -#include "entityinput.h" -#include "entityoutput.h" -#include "eventqueue.h" - -class CLogicRelay : public CLogicalEntity -{ -public: - DECLARE_CLASS( CLogicRelay, CLogicalEntity ); - - CLogicRelay(); - - void Activate(); - void Think(); - - // Input handlers - void InputEnable( inputdata_t &inputdata ); - void InputEnableRefire( inputdata_t &inputdata ); // Private input handler, not in FGD - void InputDisable( inputdata_t &inputdata ); - void InputToggle( inputdata_t &inputdata ); - void InputTrigger( inputdata_t &inputdata ); - void InputCancelPending( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - - // Outputs - COutputEvent m_OnTrigger; - COutputEvent m_OnSpawn; - -private: - - bool m_bDisabled; - bool m_bWaitForRefire; // Set to disallow a refire while we are waiting for our outputs to finish firing. -}; - -#endif //LOGICRELAY_H diff --git a/game/server/mapentities.cpp b/game/server/mapentities.cpp deleted file mode 100644 index 70d41a69f..000000000 --- a/game/server/mapentities.cpp +++ /dev/null @@ -1,601 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Controls the loading, parsing and creation of the entities from the BSP. -// -//=============================================================================// - -#include "cbase.h" -#include "entitylist.h" -#include "mapentities_shared.h" -#include "soundent.h" -#include "TemplateEntities.h" -#include "point_template.h" -#include "ai_initutils.h" -#include "lights.h" -#include "mapentities.h" -#include "wcedit.h" -#include "stringregistry.h" -#include "datacache/imdlcache.h" -#include "world.h" -#include "toolframework/iserverenginetools.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -struct HierarchicalSpawnMapData_t -{ - const char *m_pMapData; - int m_iMapDataLength; -}; - -static CStringRegistry *g_pClassnameSpawnPriority = NULL; -extern edict_t *g_pForceAttachEdict; - -// creates an entity by string name, but does not spawn it -CBaseEntity *CreateEntityByName( const char *className, int iForceEdictIndex ) -{ - if ( iForceEdictIndex != -1 ) - { - g_pForceAttachEdict = engine->CreateEdict( iForceEdictIndex ); - if ( !g_pForceAttachEdict ) - Error( "CreateEntityByName( %s, %d ) - CreateEdict failed.", className, iForceEdictIndex ); - } - - IServerNetworkable *pNetwork = EntityFactoryDictionary()->Create( className ); - g_pForceAttachEdict = NULL; - - if ( !pNetwork ) - return NULL; - - CBaseEntity *pEntity = pNetwork->GetBaseEntity(); - Assert( pEntity ); - return pEntity; -} - -CBaseNetworkable *CreateNetworkableByName( const char *className ) -{ - IServerNetworkable *pNetwork = EntityFactoryDictionary()->Create( className ); - if ( !pNetwork ) - return NULL; - - CBaseNetworkable *pNetworkable = pNetwork->GetBaseNetworkable(); - Assert( pNetworkable ); - return pNetworkable; -} - -void FreeContainingEntity( edict_t *ed ) -{ - if ( ed ) - { - CBaseEntity *ent = GetContainingEntity( ed ); - if ( ent ) - { - ed->SetEdict( NULL, false ); - CBaseEntity::PhysicsRemoveTouchedList( ent ); - CBaseEntity::PhysicsRemoveGroundList( ent ); - UTIL_RemoveImmediate( ent ); - } - } -} - -// parent name may have a , in it to include an attachment point -string_t ExtractParentName(string_t parentName) -{ - if ( !strchr(STRING(parentName), ',') ) - return parentName; - - char szToken[256]; - nexttoken(szToken, STRING(parentName), ','); - return AllocPooledString(szToken); -} - -//----------------------------------------------------------------------------- -// Purpose: Callback function for qsort, used to sort entities by their depth -// in the movement hierarchy. -// Input : pEnt1 - -// pEnt2 - -// Output : Returns -1, 0, or 1 per qsort spec. -//----------------------------------------------------------------------------- -static int __cdecl CompareSpawnOrder(HierarchicalSpawn_t *pEnt1, HierarchicalSpawn_t *pEnt2) -{ - if (pEnt1->m_nDepth == pEnt2->m_nDepth) - { - if ( g_pClassnameSpawnPriority ) - { - int o1 = pEnt1->m_pEntity ? g_pClassnameSpawnPriority->GetStringID( pEnt1->m_pEntity->GetClassname() ) : -1; - int o2 = pEnt2->m_pEntity ? g_pClassnameSpawnPriority->GetStringID( pEnt2->m_pEntity->GetClassname() ) : -1; - if ( o1 < o2 ) - return 1; - if ( o2 < o1 ) - return -1; - } - return 0; - } - - if (pEnt1->m_nDepth > pEnt2->m_nDepth) - return 1; - - return -1; -} - - -//----------------------------------------------------------------------------- -// Computes the hierarchical depth of the entities to spawn.. -//----------------------------------------------------------------------------- -static int ComputeSpawnHierarchyDepth_r( CBaseEntity *pEntity ) -{ - if ( !pEntity ) - return 1; - - if (pEntity->m_iParent == NULL_STRING) - return 1; - - CBaseEntity *pParent = gEntList.FindEntityByName( NULL, ExtractParentName(pEntity->m_iParent) ); - if (!pParent) - return 1; - - if (pParent == pEntity) - { - Warning( "LEVEL DESIGN ERROR: Entity %s is parented to itself!\n", pEntity->GetDebugName() ); - return 1; - } - - return 1 + ComputeSpawnHierarchyDepth_r( pParent ); -} - -static void ComputeSpawnHierarchyDepth( int nEntities, HierarchicalSpawn_t *pSpawnList ) -{ - // NOTE: This isn't particularly efficient, but so what? It's at the beginning of time - // I did it this way because it simplified the parent setting in hierarchy (basically - // eliminated questions about whether you should transform origin from global to local or not) - int nEntity; - for (nEntity = 0; nEntity < nEntities; nEntity++) - { - CBaseEntity *pEntity = pSpawnList[nEntity].m_pEntity; - if (pEntity && !pEntity->IsDormant()) - { - pSpawnList[nEntity].m_nDepth = ComputeSpawnHierarchyDepth_r( pEntity ); - } - else - { - pSpawnList[nEntity].m_nDepth = 1; - } - } -} - -static void SortSpawnListByHierarchy( int nEntities, HierarchicalSpawn_t *pSpawnList ) -{ - MEM_ALLOC_CREDIT(); - g_pClassnameSpawnPriority = new CStringRegistry; - // this will cause the entities to be spawned in the indicated order - // Highest string ID spawns first. String ID is spawn priority. - // by default, anything not in this list has priority -1 - g_pClassnameSpawnPriority->AddString( "func_wall", 10 ); - g_pClassnameSpawnPriority->AddString( "scripted_sequence", 9 ); - g_pClassnameSpawnPriority->AddString( "phys_hinge", 8 ); - g_pClassnameSpawnPriority->AddString( "phys_ballsocket", 8 ); - g_pClassnameSpawnPriority->AddString( "phys_slideconstraint", 8 ); - g_pClassnameSpawnPriority->AddString( "phys_constraint", 8 ); - g_pClassnameSpawnPriority->AddString( "phys_pulleyconstraint", 8 ); - g_pClassnameSpawnPriority->AddString( "phys_lengthconstraint", 8 ); - g_pClassnameSpawnPriority->AddString( "phys_ragdollconstraint", 8 ); - g_pClassnameSpawnPriority->AddString( "info_mass_center", 8 ); // spawn these before physbox/prop_physics - g_pClassnameSpawnPriority->AddString( "trigger_vphysics_motion", 8 ); // spawn these before physbox/prop_physics - - g_pClassnameSpawnPriority->AddString( "prop_physics", 7 ); - g_pClassnameSpawnPriority->AddString( "prop_ragdoll", 7 ); - // Sort the entities (other than the world) by hierarchy depth, in order to spawn them in - // that order. This insures that each entity's parent spawns before it does so that - // it can properly set up anything that relies on hierarchy. -#ifdef _WIN32 - qsort(&pSpawnList[0], nEntities, sizeof(pSpawnList[0]), (int (__cdecl *)(const void *, const void *))CompareSpawnOrder); -#elif _LINUX - qsort(&pSpawnList[0], nEntities, sizeof(pSpawnList[0]), (int (*)(const void *, const void *))CompareSpawnOrder); -#endif - delete g_pClassnameSpawnPriority; - g_pClassnameSpawnPriority = NULL; -} - -void SetupParentsForSpawnList( int nEntities, HierarchicalSpawn_t *pSpawnList ) -{ - int nEntity; - for (nEntity = nEntities - 1; nEntity >= 0; nEntity--) - { - CBaseEntity *pEntity = pSpawnList[nEntity].m_pEntity; - if ( pEntity ) - { - if ( strchr(STRING(pEntity->m_iParent), ',') ) - { - char szToken[256]; - const char *pAttachmentName = nexttoken(szToken, STRING(pEntity->m_iParent), ','); - pEntity->m_iParent = AllocPooledString(szToken); - CBaseEntity *pParent = gEntList.FindEntityByName( NULL, pEntity->m_iParent ); - - // setparent in the spawn pass instead - so the model will have been set & loaded - pSpawnList[nEntity].m_pDeferredParent = pParent; - pSpawnList[nEntity].m_pDeferredParentAttachment = pAttachmentName; - } - else - { - CBaseEntity *pParent = gEntList.FindEntityByName( NULL, pEntity->m_iParent ); - - if ((pParent != NULL) && (pParent->edict() != NULL)) - { - pEntity->SetParent( pParent ); - } - } - } - } -} - -// this is a hook for edit mode -void RememberInitialEntityPositions( int nEntities, HierarchicalSpawn_t *pSpawnList ) -{ - for (int nEntity = 0; nEntity < nEntities; nEntity++) - { - CBaseEntity *pEntity = pSpawnList[nEntity].m_pEntity; - - if ( pEntity ) - { - NWCEdit::RememberEntityPosition( pEntity ); - } - } -} - - -void SpawnAllEntities( int nEntities, HierarchicalSpawn_t *pSpawnList, bool bActivateEntities ) -{ - int nEntity; - for (nEntity = 0; nEntity < nEntities; nEntity++) - { - VPROF( "MapEntity_ParseAllEntities_Spawn"); - CBaseEntity *pEntity = pSpawnList[nEntity].m_pEntity; - - if ( pSpawnList[nEntity].m_pDeferredParent ) - { - // UNDONE: Promote this up to the root of this function? - MDLCACHE_CRITICAL_SECTION(); - CBaseEntity *pParent = pSpawnList[nEntity].m_pDeferredParent; - int iAttachment = -1; - CBaseAnimating *pAnim = pParent->GetBaseAnimating(); - if ( pAnim ) - { - iAttachment = pAnim->LookupAttachment(pSpawnList[nEntity].m_pDeferredParentAttachment); - } - pEntity->SetParent( pParent, iAttachment ); - } - if ( pEntity ) - { - if (DispatchSpawn(pEntity) < 0) - { - for ( int i = nEntity+1; i < nEntities; i++ ) - { - // this is a child object that will be deleted now - if ( pSpawnList[i].m_pEntity && pSpawnList[i].m_pEntity->IsMarkedForDeletion() ) - { - pSpawnList[i].m_pEntity = NULL; - } - } - // Spawn failed. - gEntList.CleanupDeleteList(); - // Remove the entity from the spawn list - pSpawnList[nEntity].m_pEntity = NULL; - } - } - } - - if ( bActivateEntities ) - { - VPROF( "MapEntity_ParseAllEntities_Activate"); - bool bAsyncAnims = mdlcache->SetAsyncLoad( MDLCACHE_ANIMBLOCK, false ); - for (nEntity = 0; nEntity < nEntities; nEntity++) - { - CBaseEntity *pEntity = pSpawnList[nEntity].m_pEntity; - - if ( pEntity ) - { - MDLCACHE_CRITICAL_SECTION(); - pEntity->Activate(); - } - } - mdlcache->SetAsyncLoad( MDLCACHE_ANIMBLOCK, bAsyncAnims ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Only called on BSP load. Parses and spawns all the entities in the BSP. -// Input : pMapData - Pointer to the entity data block to parse. -//----------------------------------------------------------------------------- -void MapEntity_ParseAllEntities(const char *pMapData, IMapEntityFilter *pFilter, bool bActivateEntities) -{ - VPROF("MapEntity_ParseAllEntities"); - - HierarchicalSpawnMapData_t *pSpawnMapData = new HierarchicalSpawnMapData_t[NUM_ENT_ENTRIES]; - HierarchicalSpawn_t *pSpawnList = new HierarchicalSpawn_t[NUM_ENT_ENTRIES]; - - CUtlVector< CPointTemplate* > pPointTemplates; - int nEntities = 0; - - char szTokenBuffer[MAPKEY_MAXLENGTH]; - - // Allow the tools to spawn different things - if ( serverenginetools ) - { - pMapData = serverenginetools->GetEntityData( pMapData ); - } - - // Loop through all entities in the map data, creating each. - for ( ; true; pMapData = MapEntity_SkipToNextEntity(pMapData, szTokenBuffer) ) - { - // - // Parse the opening brace. - // - char token[MAPKEY_MAXLENGTH]; - pMapData = MapEntity_ParseToken( pMapData, token ); - - // - // Check to see if we've finished or not. - // - if (!pMapData) - break; - - if (token[0] != '{') - { - Error( "MapEntity_ParseAllEntities: found %s when expecting {", token); - continue; - } - - // - // Parse the entity and add it to the spawn list. - // - CBaseEntity *pEntity; - const char *pCurMapData = pMapData; - pMapData = MapEntity_ParseEntity(pEntity, pMapData, pFilter); - if (pEntity == NULL) - continue; - - if (pEntity->IsTemplate()) - { - // It's a template entity. Squirrel away its keyvalue text so that we can - // recreate the entity later via a spawner. pMapData points at the '}' - // so we must add one to include it in the string. - Templates_Add(pEntity, pCurMapData, (pMapData - pCurMapData) + 2); - - // Remove the template entity so that it does not show up in FindEntityXXX searches. - UTIL_Remove(pEntity); - gEntList.CleanupDeleteList(); - continue; - } - - // To - if ( dynamic_cast( pEntity ) ) - { - VPROF( "MapEntity_ParseAllEntities_SpawnWorld"); - - pEntity->m_iParent = NULL_STRING; // don't allow a parent on the first entity (worldspawn) - - DispatchSpawn(pEntity); - continue; - } - - CNodeEnt *pNode = dynamic_cast(pEntity); - if ( pNode ) - { - VPROF( "MapEntity_ParseAllEntities_SpawnTransients"); - - // We overflow the max edicts on large maps that have lots of entities. - // Nodes & Lights remove themselves immediately on Spawn(), so dispatch their - // spawn now, to free up the slot inside this loop. - // NOTE: This solution prevents nodes & lights from being used inside point_templates. - // - // NOTE: Nodes spawn other entities (ai_hint) if they need to have a persistent presence. - // To ensure keys are copied over into the new entity, we pass the mapdata into the - // node spawn function. - if ( pNode->Spawn( pCurMapData ) < 0 ) - { - gEntList.CleanupDeleteList(); - } - continue; - } - - if ( dynamic_cast(pEntity) ) - { - VPROF( "MapEntity_ParseAllEntities_SpawnTransients"); - - // We overflow the max edicts on large maps that have lots of entities. - // Nodes & Lights remove themselves immediately on Spawn(), so dispatch their - // spawn now, to free up the slot inside this loop. - // NOTE: This solution prevents nodes & lights from being used inside point_templates. - if (DispatchSpawn(pEntity) < 0) - { - gEntList.CleanupDeleteList(); - } - continue; - } - - // Build a list of all point_template's so we can spawn them before everything else - CPointTemplate *pTemplate = dynamic_cast< CPointTemplate* >(pEntity); - if ( pTemplate ) - { - pPointTemplates.AddToTail( pTemplate ); - } - else - { - // Queue up this entity for spawning - pSpawnList[nEntities].m_pEntity = pEntity; - pSpawnList[nEntities].m_nDepth = 0; - pSpawnList[nEntities].m_pDeferredParentAttachment = NULL; - pSpawnList[nEntities].m_pDeferredParent = NULL; - - pSpawnMapData[nEntities].m_pMapData = pCurMapData; - pSpawnMapData[nEntities].m_iMapDataLength = (pMapData - pCurMapData) + 2; - nEntities++; - } - } - - // Now loop through all our point_template entities and tell them to make templates of everything they're pointing to - int iTemplates = pPointTemplates.Count(); - for ( int i = 0; i < iTemplates; i++ ) - { - VPROF( "MapEntity_ParseAllEntities_SpawnTemplates"); - CPointTemplate *pPointTemplate = pPointTemplates[i]; - - // First, tell the Point template to Spawn - if ( DispatchSpawn(pPointTemplate) < 0 ) - { - UTIL_Remove(pPointTemplate); - gEntList.CleanupDeleteList(); - continue; - } - - pPointTemplate->StartBuildingTemplates(); - - // Now go through all it's templates and turn the entities into templates - int iNumTemplates = pPointTemplate->GetNumTemplateEntities(); - for ( int iTemplateNum = 0; iTemplateNum < iNumTemplates; iTemplateNum++ ) - { - // Find it in the spawn list - CBaseEntity *pEntity = pPointTemplate->GetTemplateEntity( iTemplateNum ); - for ( int iEntNum = 0; iEntNum < nEntities; iEntNum++ ) - { - if ( pSpawnList[iEntNum].m_pEntity == pEntity ) - { - // Give the point_template the mapdata - pPointTemplate->AddTemplate( pEntity, pSpawnMapData[iEntNum].m_pMapData, pSpawnMapData[iEntNum].m_iMapDataLength ); - - if ( pPointTemplate->ShouldRemoveTemplateEntities() ) - { - // Remove the template entity so that it does not show up in FindEntityXXX searches. - UTIL_Remove(pEntity); - gEntList.CleanupDeleteList(); - - // Remove the entity from the spawn list - pSpawnList[iEntNum].m_pEntity = NULL; - } - break; - } - } - } - - pPointTemplate->FinishBuildingTemplates(); - } - - SpawnHierarchicalList( nEntities, pSpawnList, bActivateEntities ); - - delete [] pSpawnMapData; - delete [] pSpawnList; -} - -void SpawnHierarchicalList( int nEntities, HierarchicalSpawn_t *pSpawnList, bool bActivateEntities ) -{ - // Compute the hierarchical depth of all entities hierarchically attached - ComputeSpawnHierarchyDepth( nEntities, pSpawnList ); - - // Sort the entities (other than the world) by hierarchy depth, in order to spawn them in - // that order. This insures that each entity's parent spawns before it does so that - // it can properly set up anything that relies on hierarchy. - SortSpawnListByHierarchy( nEntities, pSpawnList ); - - // save off entity positions if in edit mode - if ( engine->IsInEditMode() ) - { - RememberInitialEntityPositions( nEntities, pSpawnList ); - } - // Set up entity movement hierarchy in reverse hierarchy depth order. This allows each entity - // to use its parent's world spawn origin to calculate its local origin. - SetupParentsForSpawnList( nEntities, pSpawnList ); - - // Spawn all the entities in hierarchy depth order so that parents spawn before their children. - SpawnAllEntities( nEntities, pSpawnList, bActivateEntities ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEntData - -//----------------------------------------------------------------------------- -void MapEntity_PrecacheEntity( const char *pEntData, int &nStringSize ) -{ - CEntityMapData entData( (char*)pEntData, nStringSize ); - char className[MAPKEY_MAXLENGTH]; - - if (!entData.ExtractValue("classname", className)) - { - Error( "classname missing from entity!\n" ); - } - - // Construct via the LINK_ENTITY_TO_CLASS factory. - CBaseEntity *pEntity = CreateEntityByName(className); - - // - // Set up keyvalues, which can set the model name, which is why we don't just do UTIL_PrecacheOther here... - // - if ( pEntity != NULL ) - { - pEntity->ParseMapData(&entData); - pEntity->Precache(); - UTIL_RemoveImmediate( pEntity ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Takes a block of character data as the input -// Input : pEntity - Receives the newly constructed entity, NULL on failure. -// pEntData - Data block to parse to extract entity keys. -// Output : Returns the current position in the entity data block. -//----------------------------------------------------------------------------- -const char *MapEntity_ParseEntity(CBaseEntity *&pEntity, const char *pEntData, IMapEntityFilter *pFilter) -{ - CEntityMapData entData( (char*)pEntData ); - char className[MAPKEY_MAXLENGTH]; - - if (!entData.ExtractValue("classname", className)) - { - Error( "classname missing from entity!\n" ); - } - - pEntity = NULL; - if ( !pFilter || pFilter->ShouldCreateEntity( className ) ) - { - // - // Construct via the LINK_ENTITY_TO_CLASS factory. - // - if ( pFilter ) - pEntity = pFilter->CreateNextEntity( className ); - else - pEntity = CreateEntityByName(className); - - // - // Set up keyvalues. - // - if (pEntity != NULL) - { - pEntity->ParseMapData(&entData); - } - else - { - Warning("Can't init %s\n", className); - } - } - else - { - // Just skip past all the keys. - char keyName[MAPKEY_MAXLENGTH]; - char value[MAPKEY_MAXLENGTH]; - if ( entData.GetFirstKey(keyName, value) ) - { - do - { - } - while ( entData.GetNextKey(keyName, value) ); - } - } - - // - // Return the current parser position in the data block - // - return entData.CurrentBufferPosition(); -} - - diff --git a/game/server/mapentities.h b/game/server/mapentities.h deleted file mode 100644 index c0a8eb73b..000000000 --- a/game/server/mapentities.h +++ /dev/null @@ -1,47 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef MAPENTITIES_H -#define MAPENTITIES_H -#ifdef _WIN32 -#pragma once -#endif - -#include "mapentities_shared.h" - -// This class provides hooks into the map-entity loading process that allows CS to do some tricks -// when restarting the round. The main trick it tries to do is recreate all -abstract_class IMapEntityFilter -{ -public: - virtual bool ShouldCreateEntity( const char *pClassname ) = 0; - virtual CBaseEntity* CreateNextEntity( const char *pClassname ) = 0; -}; - -// Use the filter so you can prevent certain entities from being created out of the map. -// CSPort does this when restarting rounds. It wants to reload most entities from the map, but certain -// entities like the world entity need to be left intact. -void MapEntity_ParseAllEntities( const char *pMapData, IMapEntityFilter *pFilter=NULL, bool bActivateEntities=false ); - -const char *MapEntity_ParseEntity( CBaseEntity *&pEntity, const char *pEntData, IMapEntityFilter *pFilter ); -void MapEntity_PrecacheEntity( const char *pEntData, int &nStringSize ); - - -//----------------------------------------------------------------------------- -// Hierarchical spawn -//----------------------------------------------------------------------------- -struct HierarchicalSpawn_t -{ - CBaseEntity *m_pEntity; - int m_nDepth; - CBaseEntity *m_pDeferredParent; // attachment parents can't be set until the parents are spawned - const char *m_pDeferredParentAttachment; // so defer setting them up until the second pass -}; - -void SpawnHierarchicalList( int nEntities, HierarchicalSpawn_t *pSpawnList, bool bActivateEntities ); - -#endif // MAPENTITIES_H diff --git a/game/server/maprules.cpp b/game/server/maprules.cpp deleted file mode 100644 index bcb73017f..000000000 --- a/game/server/maprules.cpp +++ /dev/null @@ -1,742 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Contains entities for implementing/changing game rules dynamically within each BSP. -// -//=============================================================================// - -#include "cbase.h" -#include "datamap.h" -#include "gamerules.h" -#include "maprules.h" -#include "player.h" -#include "entitylist.h" -#include "ai_hull.h" -#include "entityoutput.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CRuleEntity : public CBaseEntity -{ -public: - DECLARE_CLASS( CRuleEntity, CBaseEntity ); - - void Spawn( void ); - - DECLARE_DATADESC(); - - void SetMaster( string_t iszMaster ) { m_iszMaster = iszMaster; } - -protected: - bool CanFireForActivator( CBaseEntity *pActivator ); - -private: - string_t m_iszMaster; -}; - -BEGIN_DATADESC( CRuleEntity ) - - DEFINE_KEYFIELD( m_iszMaster, FIELD_STRING, "master" ), - -END_DATADESC() - - - -void CRuleEntity::Spawn( void ) -{ - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NONE ); - AddEffects( EF_NODRAW ); -} - - -bool CRuleEntity::CanFireForActivator( CBaseEntity *pActivator ) -{ - if ( m_iszMaster != NULL_STRING ) - { - if ( UTIL_IsMasterTriggered( m_iszMaster, pActivator ) ) - return true; - else - return false; - } - - return true; -} - -// -// CRulePointEntity -- base class for all rule "point" entities (not brushes) -// -class CRulePointEntity : public CRuleEntity -{ -public: - DECLARE_DATADESC(); - DECLARE_CLASS( CRulePointEntity, CRuleEntity ); - - int m_Score; - void Spawn( void ); -}; - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CRulePointEntity ) - - DEFINE_FIELD( m_Score, FIELD_INTEGER ), - -END_DATADESC() - - -void CRulePointEntity::Spawn( void ) -{ - BaseClass::Spawn(); - SetModelName( NULL_STRING ); - m_Score = 0; -} - -// -// CRuleBrushEntity -- base class for all rule "brush" entities (not brushes) -// Default behavior is to set up like a trigger, invisible, but keep the model for volume testing -// -class CRuleBrushEntity : public CRuleEntity -{ -public: - DECLARE_CLASS( CRuleBrushEntity, CRuleEntity ); - - void Spawn( void ); - -private: -}; - -void CRuleBrushEntity::Spawn( void ) -{ - SetModel( STRING( GetModelName() ) ); - BaseClass::Spawn(); -} - - -// CGameScore / game_score -- award points to player / team -// Points +/- total -// Flag: Allow negative scores SF_SCORE_NEGATIVE -// Flag: Award points to team in teamplay SF_SCORE_TEAM - -#define SF_SCORE_NEGATIVE 0x0001 -#define SF_SCORE_TEAM 0x0002 - -class CGameScore : public CRulePointEntity -{ -public: - DECLARE_CLASS( CGameScore, CRulePointEntity ); - DECLARE_DATADESC(); - - void Spawn( void ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - bool KeyValue( const char *szKeyName, const char *szValue ); - - inline int Points( void ) { return m_Score; } - inline bool AllowNegativeScore( void ) { return m_spawnflags & SF_SCORE_NEGATIVE; } - inline int AwardToTeam( void ) { return (m_spawnflags & SF_SCORE_TEAM); } - - inline void SetPoints( int points ) { m_Score = points; } - - void InputApplyScore( inputdata_t &inputdata ); - -private: -}; - -LINK_ENTITY_TO_CLASS( game_score, CGameScore ); - -BEGIN_DATADESC( CGameScore ) - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "ApplyScore", InputApplyScore ), -END_DATADESC() - -void CGameScore::Spawn( void ) -{ - int iScore = Points(); - BaseClass::Spawn(); - SetPoints( iScore ); -} - - -bool CGameScore::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "points")) - { - SetPoints( atoi(szValue) ); - } - else - return BaseClass::KeyValue( szKeyName, szValue ); - - return true; -} - -void CGameScore::InputApplyScore( inputdata_t &inputdata ) -{ - CBaseEntity *pActivator = inputdata.pActivator; - - if ( pActivator == NULL ) - return; - - if ( CanFireForActivator( pActivator ) == false ) - return; - - // Only players can use this - if ( pActivator->IsPlayer() ) - { - if ( AwardToTeam() ) - { - pActivator->AddPointsToTeam( Points(), AllowNegativeScore() ); - } - else - { - pActivator->AddPoints( Points(), AllowNegativeScore() ); - } - } -} - -void CGameScore::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - if ( !CanFireForActivator( pActivator ) ) - return; - - // Only players can use this - if ( pActivator->IsPlayer() ) - { - if ( AwardToTeam() ) - { - pActivator->AddPointsToTeam( Points(), AllowNegativeScore() ); - } - else - { - pActivator->AddPoints( Points(), AllowNegativeScore() ); - } - } -} - - -// CGameEnd / game_end -- Ends the game in MP - -class CGameEnd : public CRulePointEntity -{ - DECLARE_CLASS( CGameEnd, CRulePointEntity ); - -public: - DECLARE_DATADESC(); - - void InputGameEnd( inputdata_t &inputdata ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); -private: -}; - -BEGIN_DATADESC( CGameEnd ) - - // inputs - DEFINE_INPUTFUNC( FIELD_VOID, "EndGame", InputGameEnd ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( game_end, CGameEnd ); - - -void CGameEnd::InputGameEnd( inputdata_t &inputdata ) -{ - g_pGameRules->EndMultiplayerGame(); -} - -void CGameEnd::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - if ( !CanFireForActivator( pActivator ) ) - return; - - g_pGameRules->EndMultiplayerGame(); -} - - -// -// CGameText / game_text -- NON-Localized HUD Message (use env_message to display a titles.txt message) -// Flag: All players SF_ENVTEXT_ALLPLAYERS -// -#define SF_ENVTEXT_ALLPLAYERS 0x0001 - - -class CGameText : public CRulePointEntity -{ -public: - DECLARE_CLASS( CGameText, CRulePointEntity ); - - bool KeyValue( const char *szKeyName, const char *szValue ); - - DECLARE_DATADESC(); - - inline bool MessageToAll( void ) { return (m_spawnflags & SF_ENVTEXT_ALLPLAYERS); } - inline void MessageSet( const char *pMessage ) { m_iszMessage = AllocPooledString(pMessage); } - inline const char *MessageGet( void ) { return STRING( m_iszMessage ); } - - void InputDisplay( inputdata_t &inputdata ); - void Display( CBaseEntity *pActivator ); - - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) - { - Display( pActivator ); - } - -private: - - string_t m_iszMessage; - hudtextparms_t m_textParms; -}; - -LINK_ENTITY_TO_CLASS( game_text, CGameText ); - -// Save parms as a block. Will break save/restore if the structure changes, but this entity didn't ship with Half-Life, so -// it can't impact saved Half-Life games. -BEGIN_DATADESC( CGameText ) - - DEFINE_KEYFIELD( m_iszMessage, FIELD_STRING, "message" ), - - DEFINE_KEYFIELD( m_textParms.channel, FIELD_INTEGER, "channel" ), - DEFINE_KEYFIELD( m_textParms.x, FIELD_FLOAT, "x" ), - DEFINE_KEYFIELD( m_textParms.y, FIELD_FLOAT, "y" ), - DEFINE_KEYFIELD( m_textParms.effect, FIELD_INTEGER, "effect" ), - DEFINE_KEYFIELD( m_textParms.fadeinTime, FIELD_FLOAT, "fadein" ), - DEFINE_KEYFIELD( m_textParms.fadeoutTime, FIELD_FLOAT, "fadeout" ), - DEFINE_KEYFIELD( m_textParms.holdTime, FIELD_FLOAT, "holdtime" ), - DEFINE_KEYFIELD( m_textParms.fxTime, FIELD_FLOAT, "fxtime" ), - - DEFINE_ARRAY( m_textParms, FIELD_CHARACTER, sizeof(hudtextparms_t) ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Display", InputDisplay ), - -END_DATADESC() - - - -bool CGameText::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "color")) - { - int color[4]; - UTIL_StringToIntArray( color, 4, szValue ); - m_textParms.r1 = color[0]; - m_textParms.g1 = color[1]; - m_textParms.b1 = color[2]; - m_textParms.a1 = color[3]; - } - else if (FStrEq(szKeyName, "color2")) - { - int color[4]; - UTIL_StringToIntArray( color, 4, szValue ); - m_textParms.r2 = color[0]; - m_textParms.g2 = color[1]; - m_textParms.b2 = color[2]; - m_textParms.a2 = color[3]; - } - else - return BaseClass::KeyValue( szKeyName, szValue ); - - return true; -} - - -void CGameText::InputDisplay( inputdata_t &inputdata ) -{ - Display( inputdata.pActivator ); -} - -void CGameText::Display( CBaseEntity *pActivator ) -{ - if ( !CanFireForActivator( pActivator ) ) - return; - - if ( MessageToAll() ) - { - UTIL_HudMessageAll( m_textParms, MessageGet() ); - } - else - { - // If we're in singleplayer, show the message to the player. - if ( gpGlobals->maxClients == 1 ) - { - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - UTIL_HudMessage( pPlayer, m_textParms, MessageGet() ); - } - // Otherwise show the message to the player that triggered us. - else if ( pActivator && pActivator->IsNetClient() ) - { - UTIL_HudMessage( ToBasePlayer( pActivator ), m_textParms, MessageGet() ); - } - } -} - - -/* TODO: Replace with an entity I/O version -// -// CGameTeamSet / game_team_set -- Changes the team of the entity it targets to the activator's team -// Flag: Fire once -// Flag: Clear team -- Sets the team to "NONE" instead of activator - -#define SF_TEAMSET_FIREONCE 0x0001 -#define SF_TEAMSET_CLEARTEAM 0x0002 - -class CGameTeamSet : public CRulePointEntity -{ -public: - DECLARE_CLASS( CGameTeamSet, CRulePointEntity ); - - inline bool RemoveOnFire( void ) { return (m_spawnflags & SF_TEAMSET_FIREONCE) ? true : false; } - inline bool ShouldClearTeam( void ) { return (m_spawnflags & SF_TEAMSET_CLEARTEAM) ? true : false; } - void InputTrigger( inputdata_t &inputdata ); - -private: - COutputEvent m_OnTrigger; -}; - -LINK_ENTITY_TO_CLASS( game_team_set, CGameTeamSet ); - - -void CGameTeamSet::InputTrigger( inputdata_t &inputdata ) -{ - if ( !CanFireForActivator( inputdata.pActivator ) ) - return; - - if ( ShouldClearTeam() ) - { - // clear the team of our target - } - else - { - // set the team of our target to our activator's team - } - - m_OnTrigger.FireOutput(pActivator, this); - - if ( RemoveOnFire() ) - { - UTIL_Remove( this ); - } -} -*/ - - -// -// CGamePlayerZone / game_player_zone -- players in the zone fire my target when I'm fired -// -// Needs master? -class CGamePlayerZone : public CRuleBrushEntity -{ -public: - DECLARE_CLASS( CGamePlayerZone, CRuleBrushEntity ); - void InputCountPlayersInZone( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - -private: - - COutputEvent m_OnPlayerInZone; - COutputEvent m_OnPlayerOutZone; - - COutputInt m_PlayersInCount; - COutputInt m_PlayersOutCount; -}; - -LINK_ENTITY_TO_CLASS( game_zone_player, CGamePlayerZone ); -BEGIN_DATADESC( CGamePlayerZone ) - - // Inputs - DEFINE_INPUTFUNC(FIELD_VOID, "CountPlayersInZone", InputCountPlayersInZone), - - // Outputs - DEFINE_OUTPUT(m_OnPlayerInZone, "OnPlayerInZone"), - DEFINE_OUTPUT(m_OnPlayerOutZone, "OnPlayerOutZone"), - DEFINE_OUTPUT(m_PlayersInCount, "PlayersInCount"), - DEFINE_OUTPUT(m_PlayersOutCount, "PlayersOutCount"), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: Counts all the players in the zone. Fires one output per player -// in the zone, one output per player out of the zone, and outputs -// with the total counts of players in and out of the zone. -//----------------------------------------------------------------------------- -void CGamePlayerZone::InputCountPlayersInZone( inputdata_t &inputdata ) -{ - int playersInCount = 0; - int playersOutCount = 0; - - if ( !CanFireForActivator( inputdata.pActivator ) ) - return; - - CBaseEntity *pPlayer = NULL; - - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - pPlayer = UTIL_PlayerByIndex( i ); - if ( pPlayer ) - { - trace_t trace; - Hull_t hullType; - - hullType = HULL_HUMAN; - if ( pPlayer->GetFlags() & FL_DUCKING ) - { - hullType = HULL_SMALL_CENTERED; - } - - UTIL_TraceModel( pPlayer->GetAbsOrigin(), pPlayer->GetAbsOrigin(), NAI_Hull::Mins(hullType), - NAI_Hull::Maxs(hullType), this, COLLISION_GROUP_NONE, &trace ); - - if ( trace.startsolid ) - { - playersInCount++; - m_OnPlayerInZone.FireOutput(pPlayer, this); - } - else - { - playersOutCount++; - m_OnPlayerOutZone.FireOutput(pPlayer, this); - } - } - } - - m_PlayersInCount.Set(playersInCount, inputdata.pActivator, this); - m_PlayersOutCount.Set(playersOutCount, inputdata.pActivator, this); -} - - -/* -// Disable. Eventually will be replace by new activator filter entities. (LHL) -// -// CGamePlayerHurt / game_player_hurt -- Damages the player who fires it -// Flag: Fire once - -#define SF_PKILL_FIREONCE 0x0001 -class CGamePlayerHurt : public CRulePointEntity -{ -public: - DECLARE_CLASS( CGamePlayerHurt, CRulePointEntity ); - - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - inline bool RemoveOnFire( void ) { return (m_spawnflags & SF_PKILL_FIREONCE) ? true : false; } - - DECLARE_DATADESC(); - -private: - - float m_flDamage; // Damage to inflict, negative values give health. - - COutputEvent m_OnUse; -}; - -LINK_ENTITY_TO_CLASS( game_player_hurt, CGamePlayerHurt ); - - -BEGIN_DATADESC( CGamePlayerHurt ) - - DEFINE_KEYFIELD( m_flDamage, FIELD_FLOAT, "dmg" ), - -END_DATADESC() - - - -void CGamePlayerHurt::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - if ( !CanFireForActivator( pActivator ) ) - return; - - if ( pActivator->IsPlayer() ) - { - if ( m_flDamage < 0 ) - { - pActivator->TakeHealth( -m_flDamage, DMG_GENERIC ); - } - else - { - pActivator->TakeDamage( this, this, m_flDamage, DMG_GENERIC ); - } - } - - SUB_UseTargets( pActivator, useType, value ); - m_OnUse.FireOutput(pActivator, this); // dvsents2: handle useType and value here - they are passed through - - if ( RemoveOnFire() ) - { - UTIL_Remove( this ); - } -} -*/ - -// -// CGamePlayerEquip / game_playerequip -- Sets the default player equipment -// Flag: USE Only - -#define SF_PLAYEREQUIP_USEONLY 0x0001 -#define MAX_EQUIP 32 - -class CGamePlayerEquip : public CRulePointEntity -{ - DECLARE_DATADESC(); - -public: - DECLARE_CLASS( CGamePlayerEquip, CRulePointEntity ); - - bool KeyValue( const char *szKeyName, const char *szValue ); - void Touch( CBaseEntity *pOther ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - inline bool UseOnly( void ) { return (m_spawnflags & SF_PLAYEREQUIP_USEONLY) ? true : false; } - -private: - - void EquipPlayer( CBaseEntity *pPlayer ); - - string_t m_weaponNames[MAX_EQUIP]; - int m_weaponCount[MAX_EQUIP]; -}; - -LINK_ENTITY_TO_CLASS( game_player_equip, CGamePlayerEquip ); - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CGamePlayerEquip ) - - DEFINE_AUTO_ARRAY( m_weaponNames, FIELD_STRING ), - DEFINE_AUTO_ARRAY( m_weaponCount, FIELD_INTEGER ), - -END_DATADESC() - - - - -bool CGamePlayerEquip::KeyValue( const char *szKeyName, const char *szValue ) -{ - if ( !BaseClass::KeyValue( szKeyName, szValue ) ) - { - for ( int i = 0; i < MAX_EQUIP; i++ ) - { - if ( !m_weaponNames[i] ) - { - char tmp[128]; - - UTIL_StripToken( szKeyName, tmp ); - - m_weaponNames[i] = AllocPooledString(tmp); - m_weaponCount[i] = atoi(szValue); - m_weaponCount[i] = MAX(1,m_weaponCount[i]); - return true; - } - } - } - - return false; -} - - -void CGamePlayerEquip::Touch( CBaseEntity *pOther ) -{ - if ( !CanFireForActivator( pOther ) ) - return; - - if ( UseOnly() ) - return; - - EquipPlayer( pOther ); -} - -void CGamePlayerEquip::EquipPlayer( CBaseEntity *pEntity ) -{ - CBasePlayer *pPlayer = NULL; - - if ( pEntity->IsPlayer() ) - { - pPlayer = (CBasePlayer *)pEntity; - } - - if ( !pPlayer ) - return; - - for ( int i = 0; i < MAX_EQUIP; i++ ) - { - if ( !m_weaponNames[i] ) - break; - for ( int j = 0; j < m_weaponCount[i]; j++ ) - { - pPlayer->GiveNamedItem( STRING(m_weaponNames[i]) ); - } - } -} - - -void CGamePlayerEquip::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - EquipPlayer( pActivator ); -} - - -// -// CGamePlayerTeam / game_player_team -- Changes the team of the player who fired it -// Flag: Fire once -// Flag: Kill Player -// Flag: Gib Player - -#define SF_PTEAM_FIREONCE 0x0001 -#define SF_PTEAM_KILL 0x0002 -#define SF_PTEAM_GIB 0x0004 - -class CGamePlayerTeam : public CRulePointEntity -{ -public: - DECLARE_CLASS( CGamePlayerTeam, CRulePointEntity ); - - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - -private: - - inline bool RemoveOnFire( void ) { return (m_spawnflags & SF_PTEAM_FIREONCE) ? true : false; } - inline bool ShouldKillPlayer( void ) { return (m_spawnflags & SF_PTEAM_KILL) ? true : false; } - inline bool ShouldGibPlayer( void ) { return (m_spawnflags & SF_PTEAM_GIB) ? true : false; } - - const char *TargetTeamName( const char *pszTargetName, CBaseEntity *pActivator ); -}; - -LINK_ENTITY_TO_CLASS( game_player_team, CGamePlayerTeam ); - - -const char *CGamePlayerTeam::TargetTeamName( const char *pszTargetName, CBaseEntity *pActivator ) -{ - CBaseEntity *pTeamEntity = NULL; - - while ((pTeamEntity = gEntList.FindEntityByName( pTeamEntity, pszTargetName, NULL, pActivator )) != NULL) - { - if ( FClassnameIs( pTeamEntity, "game_team_master" ) ) - return pTeamEntity->TeamID(); - } - - return NULL; -} - - -void CGamePlayerTeam::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - if ( !CanFireForActivator( pActivator ) ) - return; - - if ( pActivator->IsPlayer() ) - { - const char *pszTargetTeam = TargetTeamName( STRING(m_target), pActivator ); - if ( pszTargetTeam ) - { - CBasePlayer *pPlayer = (CBasePlayer *)pActivator; - g_pGameRules->ChangePlayerTeam( pPlayer, pszTargetTeam, ShouldKillPlayer(), ShouldGibPlayer() ); - } - } - - if ( RemoveOnFire() ) - { - UTIL_Remove( this ); - } -} - - diff --git a/game/server/maprules.h b/game/server/maprules.h deleted file mode 100644 index ab86d93a3..000000000 --- a/game/server/maprules.h +++ /dev/null @@ -1,15 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef MAPRULES_H -#define MAPRULES_H - - - -#endif // MAPRULES_H - diff --git a/game/server/message_entity.cpp b/game/server/message_entity.cpp deleted file mode 100644 index 63369ef26..000000000 --- a/game/server/message_entity.cpp +++ /dev/null @@ -1,191 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "basecombatweapon.h" -#include "explode.h" -#include "eventqueue.h" -#include "gamerules.h" -#include "ammodef.h" -#include "in_buttons.h" -#include "soundent.h" -#include "ndebugoverlay.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "game.h" - -#include "player.h" -#include "entitylist.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// Spawnflags -#define SF_MESSAGE_DISABLED 1 - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CMessageEntity : public CPointEntity -{ - DECLARE_CLASS( CMessageEntity, CPointEntity ); - -public: - void Spawn( void ); - void Activate( void ); - void Think( void ); - void DrawOverlays(void); - - virtual void UpdateOnRemove(); - - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - -protected: - int m_radius; - string_t m_messageText; - bool m_drawText; - bool m_bDeveloperOnly; - bool m_bEnabled; -}; - -LINK_ENTITY_TO_CLASS( point_message, CMessageEntity ); - -BEGIN_DATADESC( CMessageEntity ) - - DEFINE_KEYFIELD( m_radius, FIELD_INTEGER, "radius" ), - DEFINE_KEYFIELD( m_messageText, FIELD_STRING, "message" ), - DEFINE_KEYFIELD( m_bDeveloperOnly, FIELD_BOOLEAN, "developeronly" ), - DEFINE_FIELD( m_drawText, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - -END_DATADESC() - -static CUtlVector< CHandle< CMessageEntity > > g_MessageEntities; - -//----------------------------------------- -// Spawn -//----------------------------------------- -void CMessageEntity::Spawn( void ) -{ - SetNextThink( gpGlobals->curtime + 0.1f ); - m_drawText = false; - m_bDeveloperOnly = false; - m_bEnabled = !HasSpawnFlags( SF_MESSAGE_DISABLED ); - //m_debugOverlays |= OVERLAY_TEXT_BIT; // make sure we always show the text -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMessageEntity::Activate( void ) -{ - BaseClass::Activate(); - - CHandle< CMessageEntity > h; - h = this; - g_MessageEntities.AddToTail( h ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMessageEntity::UpdateOnRemove() -{ - BaseClass::UpdateOnRemove(); - - CHandle< CMessageEntity > h; - h = this; - g_MessageEntities.FindAndRemove( h ); - - BaseClass::UpdateOnRemove(); -} - -//----------------------------------------- -// Think -//----------------------------------------- -void CMessageEntity::Think( void ) -{ - SetNextThink( gpGlobals->curtime + 0.1f ); - - // check for player distance - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - - if ( !pPlayer || ( pPlayer->GetFlags() & FL_NOTARGET ) ) - return; - - Vector worldTargetPosition = pPlayer->EyePosition(); - - // bail if player is too far away - if ( (worldTargetPosition - GetAbsOrigin()).Length() > m_radius ) - { - m_drawText = false; - return; - } - - // turn on text - m_drawText = true; -} - -//------------------------------------------- -//------------------------------------------- -void CMessageEntity::DrawOverlays(void) -{ - if ( !m_drawText ) - return; - - if ( m_bDeveloperOnly && !g_pDeveloper->GetInt() ) - return; - - if ( !m_bEnabled ) - return; - - // display text if they are within range - char tempstr[512]; - Q_snprintf( tempstr, sizeof(tempstr), "%s", STRING(m_messageText) ); - EntityText( 0, tempstr, 0); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMessageEntity::InputEnable( inputdata_t &inputdata ) -{ - m_bEnabled = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMessageEntity::InputDisable( inputdata_t &inputdata ) -{ - m_bEnabled = false; -} - -// This is a hack to make point_message stuff appear in developer 0 release builds -// for now -void DrawMessageEntities() -{ - int c = g_MessageEntities.Count(); - for ( int i = c - 1; i >= 0; i-- ) - { - CMessageEntity *me = g_MessageEntities[ i ]; - if ( !me ) - { - g_MessageEntities.Remove( i ); - continue; - } - - me->DrawOverlays(); - } -} diff --git a/game/server/modelentities.cpp b/game/server/modelentities.cpp deleted file mode 100644 index 4e3da044f..000000000 --- a/game/server/modelentities.cpp +++ /dev/null @@ -1,364 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "entityoutput.h" -#include "ndebugoverlay.h" -#include "modelentities.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern ConVar ent_debugkeys; -extern ConVar showtriggers; - - - -LINK_ENTITY_TO_CLASS( func_brush, CFuncBrush ); - -BEGIN_DATADESC( CFuncBrush ) - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputTurnOff ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - DEFINE_KEYFIELD( m_iDisabled, FIELD_INTEGER, "StartDisabled" ), - DEFINE_KEYFIELD( m_iSolidity, FIELD_INTEGER, "Solidity" ), - DEFINE_KEYFIELD( m_bSolidBsp, FIELD_BOOLEAN, "solidbsp" ), - DEFINE_KEYFIELD( m_iszExcludedClass, FIELD_STRING, "excludednpc" ), - DEFINE_KEYFIELD( m_bInvertExclusion, FIELD_BOOLEAN, "invert_exclusion" ), - - DEFINE_INPUTFUNC( FIELD_STRING, "SetExcluded", InputSetExcluded ), - DEFINE_INPUTFUNC( FIELD_BOOLEAN, "SetInvert", InputSetInvert ), - -END_DATADESC() - - -void CFuncBrush::Spawn( void ) -{ - SetMoveType( MOVETYPE_PUSH ); // so it doesn't get pushed by anything - - SetSolid( SOLID_VPHYSICS ); - AddEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID ); - - if ( m_iSolidity == BRUSHSOLID_NEVER ) - { - AddSolidFlags( FSOLID_NOT_SOLID ); - } - - SetModel( STRING( GetModelName() ) ); - - if ( m_iDisabled ) - TurnOff(); - - // If it can't move/go away, it's really part of the world - if ( !GetEntityName() || !m_iParent ) - AddFlag( FL_WORLDBRUSH ); - - CreateVPhysics(); - - // Slam the object back to solid - if we really want it to be solid. - if ( m_bSolidBsp ) - { - SetSolid( SOLID_BSP ); - } -} - -//----------------------------------------------------------------------------- - -bool CFuncBrush::CreateVPhysics( void ) -{ - // NOTE: Don't init this static. It's pretty common for these to be constrained - // and dynamically parented. Initing shadow avoids having to destroy the physics - // object later and lose the constraints. - IPhysicsObject *pPhys = VPhysicsInitShadow(false, false); - if ( pPhys ) - { - int contents = modelinfo->GetModelContents( GetModelIndex() ); - if ( ! (contents & (MASK_SOLID|MASK_PLAYERSOLID|MASK_NPCSOLID)) ) - { - // leave the physics shadow there in case it has crap constrained to it - // but disable collisions with it - pPhys->EnableCollisions( false ); - } - } - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CFuncBrush::DrawDebugTextOverlays( void ) -{ - int nOffset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - Q_snprintf( tempstr,sizeof(tempstr), "angles: %g %g %g", (double)GetLocalAngles()[PITCH], (double)GetLocalAngles()[YAW], (double)GetLocalAngles()[ROLL] ); - EntityText( nOffset, tempstr, 0 ); - nOffset++; - } - - return nOffset; -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for toggling the hidden/shown state of the brush. -//----------------------------------------------------------------------------- -void CFuncBrush::InputToggle( inputdata_t &inputdata ) -{ - if ( IsOn() ) - { - TurnOff(); - return; - } - - TurnOn(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for hiding the brush. -//----------------------------------------------------------------------------- -void CFuncBrush::InputTurnOff( inputdata_t &inputdata ) -{ - TurnOff(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for showing the brush. -//----------------------------------------------------------------------------- -void CFuncBrush::InputTurnOn( inputdata_t &inputdata ) -{ - TurnOn(); -} - - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -void CFuncBrush::InputSetExcluded( inputdata_t &inputdata ) -{ - m_iszExcludedClass = inputdata.value.StringID(); -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -void CFuncBrush::InputSetInvert( inputdata_t &inputdata ) -{ - m_bInvertExclusion = inputdata.value.Bool(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Hides the brush. -//----------------------------------------------------------------------------- -void CFuncBrush::TurnOff( void ) -{ - if ( !IsOn() ) - return; - - if ( m_iSolidity != BRUSHSOLID_ALWAYS ) - { - AddSolidFlags( FSOLID_NOT_SOLID ); - } - - AddEffects( EF_NODRAW ); - m_iDisabled = TRUE; -} - - -//----------------------------------------------------------------------------- -// Purpose: Shows the brush. -//----------------------------------------------------------------------------- -void CFuncBrush::TurnOn( void ) -{ - if ( IsOn() ) - return; - - if ( m_iSolidity != BRUSHSOLID_NEVER ) - { - RemoveSolidFlags( FSOLID_NOT_SOLID ); - } - - RemoveEffects( EF_NODRAW ); -} - - -bool CFuncBrush::IsOn( void ) -{ - return !IsEffectActive( EF_NODRAW ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Invisible field that activates when touched -// All inputs are passed up to the main entity, unless filtered out -//----------------------------------------------------------------------------- -// DVS TODO: obsolete, remove -class CTriggerBrush : public CBaseEntity -{ - // - // Filters controlling what this trigger responds to. - // - enum TriggerFilters_e - { - TRIGGER_IGNOREPLAYERS = 0x01, - TRIGGER_IGNORENPCS = 0x02, - TRIGGER_IGNOREPUSHABLES = 0x04, - TRIGGER_IGNORETOUCH = 0x08, - TRIGGER_IGNOREUSE = 0x10, - TRIGGER_IGNOREALL = 0x20, - }; - -public: - DECLARE_CLASS( CTriggerBrush, CBaseEntity ); - - // engine inputs - void Spawn( void ); - void StartTouch( CBaseEntity *pOther ); - void EndTouch( CBaseEntity *pOther ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - // input filtering (use/touch/blocked) - bool PassesInputFilter( CBaseEntity *pOther, int filter ); - - // input functions - void InputEnable( inputdata_t &inputdata ) - { - RemoveFlag( FL_DONTTOUCH ); - } - - void InputDisable( inputdata_t &inputdata ) - { - // this ensures that all the remaining EndTouch() calls still get passed through - AddFlag( FL_DONTTOUCH ); - } - - // outputs - COutputEvent m_OnStartTouch; - COutputEvent m_OnEndTouch; - COutputEvent m_OnUse; - - // data - int m_iInputFilter; - int m_iDontMessageParent; - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( trigger_brush, CTriggerBrush ); - -BEGIN_DATADESC( CTriggerBrush ) - - DEFINE_KEYFIELD( m_iInputFilter, FIELD_INTEGER, "InputFilter" ), - DEFINE_KEYFIELD( m_iDontMessageParent, FIELD_INTEGER, "DontMessageParent" ), - - DEFINE_OUTPUT( m_OnStartTouch, "OnStartTouch" ), - DEFINE_OUTPUT( m_OnEndTouch, "OnEndTouch" ), - DEFINE_OUTPUT( m_OnUse, "OnUse" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - -END_DATADESC() - - -void CTriggerBrush::Spawn( void ) -{ - SetSolid( SOLID_BSP ); - AddSolidFlags( FSOLID_TRIGGER ); - SetMoveType( MOVETYPE_NONE ); - - SetModel( STRING( GetModelName() ) ); // set size and link into world - - if ( !showtriggers.GetInt() ) - { - AddEffects( EF_NODRAW ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Called when an entity starts touching us. -// Input : pOther - the entity that is now touching us. -//----------------------------------------------------------------------------- -void CTriggerBrush::StartTouch( CBaseEntity *pOther ) -{ - if ( PassesInputFilter(pOther, m_iInputFilter) && !(m_iInputFilter & TRIGGER_IGNORETOUCH) ) - { - m_OnStartTouch.FireOutput( pOther, this ); - if ( !m_iDontMessageParent ) - BaseClass::StartTouch( pOther ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Called when an entity stops touching us. -// Input : pOther - the entity that was touching us. -//----------------------------------------------------------------------------- -void CTriggerBrush::EndTouch( CBaseEntity *pOther ) -{ - if ( PassesInputFilter(pOther, m_iInputFilter) && !(m_iInputFilter & TRIGGER_IGNORETOUCH) ) - { - m_OnEndTouch.FireOutput( pOther, this ); - - if ( !m_iDontMessageParent ) - BaseClass::EndTouch( pOther ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Called when we are triggered by another entity or used by the player. -// Input : pActivator - -// pCaller - -// useType - -// value - -//----------------------------------------------------------------------------- -void CTriggerBrush::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - if ( PassesInputFilter(pActivator, m_iInputFilter) && !(m_iInputFilter & TRIGGER_IGNOREUSE) ) - { - m_OnUse.FireOutput( pActivator, this ); - if ( !m_iDontMessageParent ) - { - BaseClass::Use( pActivator, pCaller, useType, value ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Checks an entity input, against a filter and the current entity -// Input : *pOther - the entity that is part of the input (touch/untouch/block/use) -// filter - a field of standard filters (TriggerFilters_e) -// Output : Returns true if the input passes, false if it should be ignored -//----------------------------------------------------------------------------- -bool CTriggerBrush::PassesInputFilter( CBaseEntity *pOther, int filter ) -{ - if ( !filter ) - return true; - - // check for players - if ( (filter & TRIGGER_IGNOREPLAYERS) && pOther->IsPlayer() ) - return false; - - // NPCs - if ( (filter & TRIGGER_IGNORENPCS) && pOther->edict() && (pOther->GetFlags() & FL_NPC) ) - return false; - - // pushables - if ( (filter & TRIGGER_IGNOREPUSHABLES) && FStrEq(STRING(pOther->m_iClassname), "func_pushable") ) - return false; - - return true; -} - diff --git a/game/server/modelentities.h b/game/server/modelentities.h deleted file mode 100644 index 10e9054b2..000000000 --- a/game/server/modelentities.h +++ /dev/null @@ -1,63 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef MODELENTITIES_H -#define MODELENTITIES_H -#ifdef _WIN32 -#pragma once -#endif - -//!! replace this with generic start enabled/disabled -#define SF_WALL_START_OFF 0x0001 -#define SF_IGNORE_PLAYERUSE 0x0002 - -//----------------------------------------------------------------------------- -// Purpose: basic solid geometry -// enabled state: brush is visible -// disabled staute: brush not visible -//----------------------------------------------------------------------------- -class CFuncBrush : public CBaseEntity -{ -public: - DECLARE_CLASS( CFuncBrush, CBaseEntity ); - - virtual void Spawn( void ); - bool CreateVPhysics( void ); - - virtual int ObjectCaps( void ) { return HasSpawnFlags(SF_IGNORE_PLAYERUSE) ? BaseClass::ObjectCaps() : BaseClass::ObjectCaps() | FCAP_IMPULSE_USE; } - - virtual int DrawDebugTextOverlays( void ); - - void TurnOff( void ); - void TurnOn( void ); - - // Input handlers - void InputTurnOff( inputdata_t &inputdata ); - void InputTurnOn( inputdata_t &inputdata ); - void InputToggle( inputdata_t &inputdata ); - void InputSetExcluded( inputdata_t &inputdata ); - void InputSetInvert( inputdata_t &inputdata ); - - enum BrushSolidities_e { - BRUSHSOLID_TOGGLE = 0, - BRUSHSOLID_NEVER = 1, - BRUSHSOLID_ALWAYS = 2, - }; - - BrushSolidities_e m_iSolidity; - int m_iDisabled; - bool m_bSolidBsp; - string_t m_iszExcludedClass; - bool m_bInvertExclusion; - - DECLARE_DATADESC(); - - virtual bool IsOn( void ); -}; - - -#endif // MODELENTITIES_H diff --git a/game/server/monstermaker.cpp b/game/server/monstermaker.cpp deleted file mode 100644 index dc8b4403b..000000000 --- a/game/server/monstermaker.cpp +++ /dev/null @@ -1,1083 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: An entity that creates NPCs in the game. There are two types of NPC -// makers -- one which creates NPCs using a template NPC, and one which -// creates an NPC via a classname. -// -//=============================================================================// - -#include "cbase.h" -#include "datacache/imdlcache.h" -#include "entityapi.h" -#include "entityoutput.h" -#include "ai_basenpc.h" -#include "monstermaker.h" -#include "TemplateEntities.h" -#include "ndebugoverlay.h" -#include "mapentities.h" -#include "IEffects.h" -#include "props.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -static void DispatchActivate( CBaseEntity *pEntity ) -{ - bool bAsyncAnims = mdlcache->SetAsyncLoad( MDLCACHE_ANIMBLOCK, false ); - pEntity->Activate(); - mdlcache->SetAsyncLoad( MDLCACHE_ANIMBLOCK, bAsyncAnims ); -} - -ConVar ai_inhibit_spawners( "ai_inhibit_spawners", "0", FCVAR_CHEAT ); - - -LINK_ENTITY_TO_CLASS( info_npc_spawn_destination, CNPCSpawnDestination ); - -BEGIN_DATADESC( CNPCSpawnDestination ) - DEFINE_KEYFIELD( m_ReuseDelay, FIELD_FLOAT, "ReuseDelay" ), - DEFINE_KEYFIELD( m_RenameNPC,FIELD_STRING, "RenameNPC" ), - DEFINE_FIELD( m_TimeNextAvailable, FIELD_TIME ), - - DEFINE_OUTPUT( m_OnSpawnNPC, "OnSpawnNPC" ), -END_DATADESC() - -//--------------------------------------------------------- -//--------------------------------------------------------- -CNPCSpawnDestination::CNPCSpawnDestination() -{ - // Available right away, the first time. - m_TimeNextAvailable = gpGlobals->curtime; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CNPCSpawnDestination::IsAvailable() -{ - if( m_TimeNextAvailable > gpGlobals->curtime ) - { - return false; - } - - return true; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CNPCSpawnDestination::OnSpawnedNPC( CAI_BaseNPC *pNPC ) -{ - // Rename the NPC - if( m_RenameNPC != NULL_STRING ) - { - pNPC->SetName( m_RenameNPC ); - } - - m_OnSpawnNPC.FireOutput( pNPC, this ); - m_TimeNextAvailable = gpGlobals->curtime + m_ReuseDelay; -} - -//------------------------------------- -BEGIN_DATADESC( CBaseNPCMaker ) - - DEFINE_KEYFIELD( m_nMaxNumNPCs, FIELD_INTEGER, "MaxNPCCount" ), - DEFINE_KEYFIELD( m_nMaxLiveChildren, FIELD_INTEGER, "MaxLiveChildren" ), - DEFINE_KEYFIELD( m_flSpawnFrequency, FIELD_FLOAT, "SpawnFrequency" ), - DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ), - - DEFINE_FIELD( m_nLiveChildren, FIELD_INTEGER ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Spawn", InputSpawnNPC ), - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetMaxChildren", InputSetMaxChildren ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "AddMaxChildren", InputAddMaxChildren ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetMaxLiveChildren", InputSetMaxLiveChildren ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetSpawnFrequency", InputSetSpawnFrequency ), - - // Outputs - DEFINE_OUTPUT( m_OnAllSpawned, "OnAllSpawned" ), - DEFINE_OUTPUT( m_OnAllSpawnedDead, "OnAllSpawnedDead" ), - DEFINE_OUTPUT( m_OnAllLiveChildrenDead, "OnAllLiveChildrenDead" ), - DEFINE_OUTPUT( m_OnSpawnNPC, "OnSpawnNPC" ), - - // Function Pointers - DEFINE_THINKFUNC( MakerThink ), - - DEFINE_FIELD( m_hIgnoreEntity, FIELD_EHANDLE ), - DEFINE_KEYFIELD( m_iszIngoreEnt, FIELD_STRING, "IgnoreEntity" ), -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: Spawn -//----------------------------------------------------------------------------- -void CBaseNPCMaker::Spawn( void ) -{ - SetSolid( SOLID_NONE ); - m_nLiveChildren = 0; - Precache(); - - // If I can make an infinite number of NPC, force them to fade - if ( m_spawnflags & SF_NPCMAKER_INF_CHILD ) - { - m_spawnflags |= SF_NPCMAKER_FADE; - } - - //Start on? - if ( m_bDisabled == false ) - { - SetThink ( &CBaseNPCMaker::MakerThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); - } - else - { - //wait to be activated. - SetThink ( &CBaseNPCMaker::SUB_DoNothing ); - } -} - -//----------------------------------------------------------------------------- -// A not-very-robust check to see if a human hull could fit at this location. -// used to validate spawn destinations. -//----------------------------------------------------------------------------- -bool CBaseNPCMaker::HumanHullFits( const Vector &vecLocation ) -{ - trace_t tr; - UTIL_TraceHull( vecLocation, - vecLocation + Vector( 0, 0, 1 ), - NAI_Hull::Mins(HULL_HUMAN), - NAI_Hull::Maxs(HULL_HUMAN), - MASK_NPCSOLID, - m_hIgnoreEntity, - COLLISION_GROUP_NONE, - &tr ); - - if( tr.fraction == 1.0 ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns whether or not it is OK to make an NPC at this instant. -//----------------------------------------------------------------------------- -bool CBaseNPCMaker::CanMakeNPC( bool bIgnoreSolidEntities ) -{ - if( ai_inhibit_spawners.GetBool() ) - return false; - - if ( m_nMaxLiveChildren > 0 && m_nLiveChildren >= m_nMaxLiveChildren ) - {// not allowed to make a new one yet. Too many live ones out right now. - return false; - } - - if ( m_iszIngoreEnt != NULL_STRING ) - { - m_hIgnoreEntity = gEntList.FindEntityByName( NULL, m_iszIngoreEnt ); - } - - Vector mins = GetAbsOrigin() - Vector( 34, 34, 0 ); - Vector maxs = GetAbsOrigin() + Vector( 34, 34, 0 ); - maxs.z = GetAbsOrigin().z; - - // If we care about not hitting solid entities, look for 'em - if ( !bIgnoreSolidEntities ) - { - CBaseEntity *pList[128]; - - int count = UTIL_EntitiesInBox( pList, 128, mins, maxs, FL_CLIENT|FL_NPC ); - if ( count ) - { - //Iterate through the list and check the results - for ( int i = 0; i < count; i++ ) - { - //Don't build on top of another entity - if ( pList[i] == NULL ) - continue; - - //If one of the entities is solid, then we may not be able to spawn now - if ( ( pList[i]->GetSolidFlags() & FSOLID_NOT_SOLID ) == false ) - { - // Since the outer method doesn't work well around striders on account of their huge bounding box. - // Find the ground under me and see if a human hull would fit there. - trace_t tr; - UTIL_TraceHull( GetAbsOrigin() + Vector( 0, 0, 2 ), - GetAbsOrigin() - Vector( 0, 0, 8192 ), - NAI_Hull::Mins(HULL_HUMAN), - NAI_Hull::Maxs(HULL_HUMAN), - MASK_NPCSOLID, - m_hIgnoreEntity, - COLLISION_GROUP_NONE, - &tr ); - - if( !HumanHullFits( tr.endpos + Vector( 0, 0, 1 ) ) ) - { - return false; - } - } - } - } - } - - // Do we need to check to see if the player's looking? - if ( HasSpawnFlags( SF_NPCMAKER_HIDEFROMPLAYER ) ) - { - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex(i); - if ( pPlayer ) - { - // Only spawn if the player's looking away from me - if( pPlayer->FInViewCone( GetAbsOrigin() ) && pPlayer->FVisible( GetAbsOrigin() ) ) - { - if ( !(pPlayer->GetFlags() & FL_NOTARGET) ) - return false; - DevMsg( 2, "Spawner %s spawning even though seen due to notarget\n", STRING( GetEntityName() ) ); - } - } - } - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: If this had a finite number of children, return true if they've all -// been created. -//----------------------------------------------------------------------------- -bool CBaseNPCMaker::IsDepleted() -{ - if ( (m_spawnflags & SF_NPCMAKER_INF_CHILD) || m_nMaxNumNPCs > 0 ) - return false; - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Toggle the spawner's state -//----------------------------------------------------------------------------- -void CBaseNPCMaker::Toggle( void ) -{ - if ( m_bDisabled ) - { - Enable(); - } - else - { - Disable(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Start the spawner -//----------------------------------------------------------------------------- -void CBaseNPCMaker::Enable( void ) -{ - // can't be enabled once depleted - if ( IsDepleted() ) - return; - - m_bDisabled = false; - SetThink ( &CBaseNPCMaker::MakerThink ); - SetNextThink( gpGlobals->curtime ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Stop the spawner -//----------------------------------------------------------------------------- -void CBaseNPCMaker::Disable( void ) -{ - m_bDisabled = true; - SetThink ( NULL ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that spawns an NPC. -//----------------------------------------------------------------------------- -void CBaseNPCMaker::InputSpawnNPC( inputdata_t &inputdata ) -{ - if( !IsDepleted() ) - { - MakeNPC(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input hander that starts the spawner -//----------------------------------------------------------------------------- -void CBaseNPCMaker::InputEnable( inputdata_t &inputdata ) -{ - Enable(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input hander that stops the spawner -//----------------------------------------------------------------------------- -void CBaseNPCMaker::InputDisable( inputdata_t &inputdata ) -{ - Disable(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input hander that toggles the spawner -//----------------------------------------------------------------------------- -void CBaseNPCMaker::InputToggle( inputdata_t &inputdata ) -{ - Toggle(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseNPCMaker::InputSetMaxChildren( inputdata_t &inputdata ) -{ - m_nMaxNumNPCs = inputdata.value.Int(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseNPCMaker::InputAddMaxChildren( inputdata_t &inputdata ) -{ - m_nMaxNumNPCs += inputdata.value.Int(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseNPCMaker::InputSetMaxLiveChildren( inputdata_t &inputdata ) -{ - m_nMaxLiveChildren = inputdata.value.Int(); -} - -void CBaseNPCMaker::InputSetSpawnFrequency( inputdata_t &inputdata ) -{ - m_flSpawnFrequency = inputdata.value.Float(); -} - -LINK_ENTITY_TO_CLASS( npc_maker, CNPCMaker ); - -BEGIN_DATADESC( CNPCMaker ) - - DEFINE_KEYFIELD( m_iszNPCClassname, FIELD_STRING, "NPCType" ), - DEFINE_KEYFIELD( m_ChildTargetName, FIELD_STRING, "NPCTargetname" ), - DEFINE_KEYFIELD( m_SquadName, FIELD_STRING, "NPCSquadName" ), - DEFINE_KEYFIELD( m_spawnEquipment, FIELD_STRING, "additionalequipment" ), - DEFINE_KEYFIELD( m_strHintGroup, FIELD_STRING, "NPCHintGroup" ), - DEFINE_KEYFIELD( m_RelationshipString, FIELD_STRING, "Relationship" ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CNPCMaker::CNPCMaker( void ) -{ - m_spawnEquipment = NULL_STRING; -} - - -//----------------------------------------------------------------------------- -// Purpose: Precache the target NPC -//----------------------------------------------------------------------------- -void CNPCMaker::Precache( void ) -{ - BaseClass::Precache(); - - const char *pszNPCName = STRING( m_iszNPCClassname ); - if ( !pszNPCName || !pszNPCName[0] ) - { - Warning("npc_maker %s has no specified NPC-to-spawn classname.\n", STRING(GetEntityName()) ); - } - else - { - UTIL_PrecacheOther( pszNPCName ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Creates the NPC. -//----------------------------------------------------------------------------- -void CNPCMaker::MakeNPC( void ) -{ - if (!CanMakeNPC()) - return; - - CAI_BaseNPC *pent = (CAI_BaseNPC*)CreateEntityByName( STRING(m_iszNPCClassname) ); - - if ( !pent ) - { - Warning("NULL Ent in NPCMaker!\n" ); - return; - } - - // ------------------------------------------------ - // Intialize spawned NPC's relationships - // ------------------------------------------------ - pent->SetRelationshipString( m_RelationshipString ); - - m_OnSpawnNPC.Set( pent, pent, this ); - - pent->SetAbsOrigin( GetAbsOrigin() ); - - // Strip pitch and roll from the spawner's angles. Pass only yaw to the spawned NPC. - QAngle angles = GetAbsAngles(); - angles.x = 0.0; - angles.z = 0.0; - pent->SetAbsAngles( angles ); - - pent->AddSpawnFlags( SF_NPC_FALL_TO_GROUND ); - - if ( m_spawnflags & SF_NPCMAKER_FADE ) - { - pent->AddSpawnFlags( SF_NPC_FADE_CORPSE ); - } - - pent->m_spawnEquipment = m_spawnEquipment; - pent->SetSquadName( m_SquadName ); - pent->SetHintGroup( m_strHintGroup ); - - ChildPreSpawn( pent ); - - DispatchSpawn( pent ); - pent->SetOwnerEntity( this ); - DispatchActivate( pent ); - - if ( m_ChildTargetName != NULL_STRING ) - { - // if I have a netname (overloaded), give the child NPC that name as a targetname - pent->SetName( m_ChildTargetName ); - } - - ChildPostSpawn( pent ); - - m_nLiveChildren++;// count this NPC - - if (!(m_spawnflags & SF_NPCMAKER_INF_CHILD)) - { - m_nMaxNumNPCs--; - - if ( IsDepleted() ) - { - m_OnAllSpawned.FireOutput( this, this ); - - // Disable this forever. Don't kill it because it still gets death notices - SetThink( NULL ); - SetUse( NULL ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pChild - -//----------------------------------------------------------------------------- -void CBaseNPCMaker::ChildPostSpawn( CAI_BaseNPC *pChild ) -{ - // If I'm stuck inside any props, remove them - bool bFound = true; - while ( bFound ) - { - trace_t tr; - UTIL_TraceHull( pChild->GetAbsOrigin(), pChild->GetAbsOrigin(), pChild->WorldAlignMins(), pChild->WorldAlignMaxs(), MASK_NPCSOLID, pChild, COLLISION_GROUP_NONE, &tr ); - //NDebugOverlay::Box( pChild->GetAbsOrigin(), pChild->WorldAlignMins(), pChild->WorldAlignMaxs(), 0, 255, 0, 32, 5.0 ); - if ( tr.fraction != 1.0 && tr.m_pEnt ) - { - if ( FClassnameIs( tr.m_pEnt, "prop_physics" ) ) - { - // Set to non-solid so this loop doesn't keep finding it - tr.m_pEnt->AddSolidFlags( FSOLID_NOT_SOLID ); - UTIL_RemoveImmediate( tr.m_pEnt ); - continue; - } - } - - bFound = false; - } - if ( m_hIgnoreEntity != NULL ) - { - pChild->SetOwnerEntity( m_hIgnoreEntity ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Creates a new NPC every so often. -//----------------------------------------------------------------------------- -void CBaseNPCMaker::MakerThink ( void ) -{ - SetNextThink( gpGlobals->curtime + m_flSpawnFrequency ); - - MakeNPC(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pVictim - -//----------------------------------------------------------------------------- -void CBaseNPCMaker::DeathNotice( CBaseEntity *pVictim ) -{ - // ok, we've gotten the deathnotice from our child, now clear out its owner if we don't want it to fade. - m_nLiveChildren--; - - // If we're here, we're getting erroneous death messages from children we haven't created - AssertMsg( m_nLiveChildren >= 0, "npc_maker receiving child death notice but thinks has no children\n" ); - - if ( m_nLiveChildren <= 0 ) - { - m_OnAllLiveChildrenDead.FireOutput( this, this ); - - // See if we've exhausted our supply of NPCs - if ( ( (m_spawnflags & SF_NPCMAKER_INF_CHILD) == false ) && IsDepleted() ) - { - // Signal that all our children have been spawned and are now dead - m_OnAllSpawnedDead.FireOutput( this, this ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Creates new NPCs from a template NPC. The template NPC must be marked -// as a template (spawnflag) and does not spawn. -//----------------------------------------------------------------------------- - -LINK_ENTITY_TO_CLASS( npc_template_maker, CTemplateNPCMaker ); - -BEGIN_DATADESC( CTemplateNPCMaker ) - - DEFINE_KEYFIELD( m_iszTemplateName, FIELD_STRING, "TemplateName" ), - DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "radius" ), - DEFINE_FIELD( m_iszTemplateData, FIELD_STRING ), - DEFINE_KEYFIELD( m_iszDestinationGroup, FIELD_STRING, "DestinationGroup" ), - DEFINE_KEYFIELD( m_CriterionVisibility, FIELD_INTEGER, "CriterionVisibility" ), - DEFINE_KEYFIELD( m_CriterionDistance, FIELD_INTEGER, "CriterionDistance" ), - DEFINE_KEYFIELD( m_iMinSpawnDistance, FIELD_INTEGER, "MinSpawnDistance" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "SpawnNPCInRadius", InputSpawnInRadius ), - DEFINE_INPUTFUNC( FIELD_VOID, "SpawnNPCInLine", InputSpawnInLine ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SpawnMultiple", InputSpawnMultiple ), - DEFINE_INPUTFUNC( FIELD_STRING, "ChangeDestinationGroup", InputChangeDestinationGroup ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetMinimumSpawnDistance", InputSetMinimumSpawnDistance ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// A hook that lets derived NPC makers do special stuff when precaching. -//----------------------------------------------------------------------------- -void CTemplateNPCMaker::PrecacheTemplateEntity( CBaseEntity *pEntity ) -{ - pEntity->Precache(); -} - - -void CTemplateNPCMaker::Precache() -{ - BaseClass::Precache(); - - if ( !m_iszTemplateData ) - { - // - // This must be the first time we're activated, not a load from save game. - // Look up the template in the template database. - // - if (!m_iszTemplateName) - { - Warning( "npc_template_maker %s has no template NPC!\n", STRING(GetEntityName()) ); - UTIL_Remove( this ); - return; - } - else - { - m_iszTemplateData = Templates_FindByTargetName(STRING(m_iszTemplateName)); - if ( m_iszTemplateData == NULL_STRING ) - { - DevWarning( "npc_template_maker %s: template NPC %s not found!\n", STRING(GetEntityName()), STRING(m_iszTemplateName) ); - UTIL_Remove( this ); - return; - } - } - } - - Assert( m_iszTemplateData != NULL_STRING ); - - // If the mapper marked this as "preload", then instance the entity preache stuff and delete the entity - //if ( !HasSpawnFlags(SF_NPCMAKER_NOPRELOADMODELS) ) - if ( m_iszTemplateData != NULL_STRING ) - { - CBaseEntity *pEntity = NULL; - MapEntity_ParseEntity( pEntity, STRING(m_iszTemplateData), NULL ); - if ( pEntity != NULL ) - { - PrecacheTemplateEntity( pEntity ); - UTIL_RemoveImmediate( pEntity ); - } - } -} - -#define MAX_DESTINATION_ENTS 100 -CNPCSpawnDestination *CTemplateNPCMaker::FindSpawnDestination() -{ - CNPCSpawnDestination *pDestinations[ MAX_DESTINATION_ENTS ]; - CBaseEntity *pEnt = NULL; - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - int count = 0; - - if( !pPlayer ) - { - return NULL; - } - - // Collect all the qualifiying destination ents - pEnt = gEntList.FindEntityByName( NULL, m_iszDestinationGroup ); - - if( !pEnt ) - { - DevWarning("Template NPC Spawner (%s) doesn't have any spawn destinations!\n", GetDebugName() ); - return NULL; - } - - while( pEnt ) - { - CNPCSpawnDestination *pDestination; - - pDestination = dynamic_cast (pEnt); - - if( pDestination && pDestination->IsAvailable() ) - { - bool fValid = true; - Vector vecTest = pDestination->GetAbsOrigin(); - - if( m_CriterionVisibility != TS_YN_DONT_CARE ) - { - // Right now View Cone check is omitted intentionally. - Vector vecTopOfHull = NAI_Hull::Maxs( HULL_HUMAN ); - vecTopOfHull.x = 0; - vecTopOfHull.y = 0; - bool fVisible = (pPlayer->FVisible( vecTest ) || pPlayer->FVisible( vecTest + vecTopOfHull ) ); - - if( m_CriterionVisibility == TS_YN_YES ) - { - if( !fVisible ) - fValid = false; - } - else - { - if( fVisible ) - { - if ( !(pPlayer->GetFlags() & FL_NOTARGET) ) - fValid = false; - else - DevMsg( 2, "Spawner %s spawning even though seen due to notarget\n", STRING( GetEntityName() ) ); - } - } - } - - if( fValid ) - { - pDestinations[ count ] = pDestination; - count++; - } - } - - pEnt = gEntList.FindEntityByName( pEnt, m_iszDestinationGroup ); - } - - if( count < 1 ) - return NULL; - - // Now find the nearest/farthest based on distance criterion - if( m_CriterionDistance == TS_DIST_DONT_CARE ) - { - // Pretty lame way to pick randomly. Try a few times to find a random - // location where a hull can fit. Don't try too many times due to performance - // concerns. - for( int i = 0 ; i < 5 ; i++ ) - { - CNPCSpawnDestination *pRandomDest = pDestinations[ rand() % count ]; - - if( HumanHullFits( pRandomDest->GetAbsOrigin() ) ) - { - return pRandomDest; - } - } - - return NULL; - } - else - { - if( m_CriterionDistance == TS_DIST_NEAREST ) - { - float flNearest = FLT_MAX; - CNPCSpawnDestination *pNearest = NULL; - - for( int i = 0 ; i < count ; i++ ) - { - Vector vecTest = pDestinations[ i ]->GetAbsOrigin(); - float flDist = ( vecTest - pPlayer->GetAbsOrigin() ).Length(); - - if ( m_iMinSpawnDistance != 0 && m_iMinSpawnDistance > flDist ) - continue; - - if( flDist < flNearest && HumanHullFits( vecTest ) ) - { - flNearest = flDist; - pNearest = pDestinations[ i ]; - } - } - - return pNearest; - } - else - { - float flFarthest = 0; - CNPCSpawnDestination *pFarthest = NULL; - - for( int i = 0 ; i < count ; i++ ) - { - Vector vecTest = pDestinations[ i ]->GetAbsOrigin(); - float flDist = ( vecTest - pPlayer->GetAbsOrigin() ).Length(); - - if ( m_iMinSpawnDistance != 0 && m_iMinSpawnDistance > flDist ) - continue; - - if( flDist > flFarthest && HumanHullFits( vecTest ) ) - { - flFarthest = flDist; - pFarthest = pDestinations[ i ]; - } - } - - return pFarthest; - } - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTemplateNPCMaker::MakeNPC( void ) -{ - // If we should be using the radius spawn method instead, do so - if ( m_flRadius && HasSpawnFlags(SF_NPCMAKER_ALWAYSUSERADIUS) ) - { - MakeNPCInRadius(); - return; - } - - if (!CanMakeNPC( ( m_iszDestinationGroup != NULL_STRING ) )) - return; - - CNPCSpawnDestination *pDestination = NULL; - if ( m_iszDestinationGroup != NULL_STRING ) - { - pDestination = FindSpawnDestination(); - if ( !pDestination ) - { - DevMsg( 2, "%s '%s' failed to find a valid spawnpoint in destination group: '%s'\n", GetClassname(), STRING(GetEntityName()), STRING(m_iszDestinationGroup) ); - return; - } - } - - CAI_BaseNPC *pent = NULL; - CBaseEntity *pEntity = NULL; - MapEntity_ParseEntity( pEntity, STRING(m_iszTemplateData), NULL ); - if ( pEntity != NULL ) - { - pent = (CAI_BaseNPC *)pEntity; - } - - if ( !pent ) - { - Warning("NULL Ent in NPCMaker!\n" ); - return; - } - - if ( pDestination ) - { - pent->SetAbsOrigin( pDestination->GetAbsOrigin() ); - - // Strip pitch and roll from the spawner's angles. Pass only yaw to the spawned NPC. - QAngle angles = pDestination->GetAbsAngles(); - angles.x = 0.0; - angles.z = 0.0; - pent->SetAbsAngles( angles ); - - pDestination->OnSpawnedNPC( pent ); - } - else - { - pent->SetAbsOrigin( GetAbsOrigin() ); - - // Strip pitch and roll from the spawner's angles. Pass only yaw to the spawned NPC. - QAngle angles = GetAbsAngles(); - angles.x = 0.0; - angles.z = 0.0; - pent->SetAbsAngles( angles ); - } - - m_OnSpawnNPC.Set( pEntity, pEntity, this ); - - if ( m_spawnflags & SF_NPCMAKER_FADE ) - { - pent->AddSpawnFlags( SF_NPC_FADE_CORPSE ); - } - - pent->RemoveSpawnFlags( SF_NPC_TEMPLATE ); - - if ( ( m_spawnflags & SF_NPCMAKER_NO_DROP ) == false ) - { - pent->RemoveSpawnFlags( SF_NPC_FALL_TO_GROUND ); // don't fall, slam - } - - ChildPreSpawn( pent ); - - DispatchSpawn( pent ); - pent->SetOwnerEntity( this ); - DispatchActivate( pent ); - - ChildPostSpawn( pent ); - - m_nLiveChildren++;// count this NPC - - if (!(m_spawnflags & SF_NPCMAKER_INF_CHILD)) - { - m_nMaxNumNPCs--; - - if ( IsDepleted() ) - { - m_OnAllSpawned.FireOutput( this, this ); - - // Disable this forever. Don't kill it because it still gets death notices - SetThink( NULL ); - SetUse( NULL ); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CTemplateNPCMaker::MakeNPCInLine( void ) -{ - if (!CanMakeNPC(true)) - return; - - CAI_BaseNPC *pent = NULL; - CBaseEntity *pEntity = NULL; - MapEntity_ParseEntity( pEntity, STRING(m_iszTemplateData), NULL ); - if ( pEntity != NULL ) - { - pent = (CAI_BaseNPC *)pEntity; - } - - if ( !pent ) - { - Warning("NULL Ent in NPCMaker!\n" ); - return; - } - - m_OnSpawnNPC.Set( pEntity, pEntity, this ); - - PlaceNPCInLine( pent ); - - pent->AddSpawnFlags( SF_NPC_FALL_TO_GROUND ); - - pent->RemoveSpawnFlags( SF_NPC_TEMPLATE ); - ChildPreSpawn( pent ); - - DispatchSpawn( pent ); - pent->SetOwnerEntity( this ); - DispatchActivate( pent ); - - ChildPostSpawn( pent ); - - m_nLiveChildren++;// count this NPC - - if (!(m_spawnflags & SF_NPCMAKER_INF_CHILD)) - { - m_nMaxNumNPCs--; - - if ( IsDepleted() ) - { - m_OnAllSpawned.FireOutput( this, this ); - - // Disable this forever. Don't kill it because it still gets death notices - SetThink( NULL ); - SetUse( NULL ); - } - } -} - -//----------------------------------------------------------------------------- -bool CTemplateNPCMaker::PlaceNPCInLine( CAI_BaseNPC *pNPC ) -{ - Vector vecPlace; - Vector vecLine; - - GetVectors( &vecLine, NULL, NULL ); - - // invert this, line up NPC's BEHIND the maker. - vecLine *= -1; - - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector( 0, 0, 8192 ), MASK_SHOT, pNPC, COLLISION_GROUP_NONE, &tr ); - vecPlace = tr.endpos; - float flStepSize = pNPC->GetHullWidth(); - - // Try 10 times to place this npc. - for( int i = 0 ; i < 10 ; i++ ) - { - UTIL_TraceHull( vecPlace, - vecPlace + Vector( 0, 0, 10 ), - pNPC->GetHullMins(), - pNPC->GetHullMaxs(), - MASK_SHOT, - pNPC, - COLLISION_GROUP_NONE, - &tr ); - - if( tr.fraction == 1.0 ) - { - pNPC->SetAbsOrigin( tr.endpos ); - return true; - } - - vecPlace += vecLine * flStepSize; - } - - DevMsg("**Failed to place NPC in line!\n"); - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Place NPC somewhere on the perimeter of my radius. -//----------------------------------------------------------------------------- -void CTemplateNPCMaker::MakeNPCInRadius( void ) -{ - if ( !CanMakeNPC(true)) - return; - - CAI_BaseNPC *pent = NULL; - CBaseEntity *pEntity = NULL; - MapEntity_ParseEntity( pEntity, STRING(m_iszTemplateData), NULL ); - if ( pEntity != NULL ) - { - pent = (CAI_BaseNPC *)pEntity; - } - - if ( !pent ) - { - Warning("NULL Ent in NPCMaker!\n" ); - return; - } - - if ( !PlaceNPCInRadius( pent ) ) - { - // Failed to place the NPC. Abort - UTIL_RemoveImmediate( pent ); - return; - } - - m_OnSpawnNPC.Set( pEntity, pEntity, this ); - - pent->AddSpawnFlags( SF_NPC_FALL_TO_GROUND ); - - pent->RemoveSpawnFlags( SF_NPC_TEMPLATE ); - ChildPreSpawn( pent ); - - DispatchSpawn( pent ); - - pent->SetOwnerEntity( this ); - DispatchActivate( pent ); - - ChildPostSpawn( pent ); - - m_nLiveChildren++;// count this NPC - - if (!(m_spawnflags & SF_NPCMAKER_INF_CHILD)) - { - m_nMaxNumNPCs--; - - if ( IsDepleted() ) - { - m_OnAllSpawned.FireOutput( this, this ); - - // Disable this forever. Don't kill it because it still gets death notices - SetThink( NULL ); - SetUse( NULL ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Find a place to spawn an npc within my radius. -// Right now this function tries to place them on the perimeter of radius. -// Output : false if we couldn't find a spot! -//----------------------------------------------------------------------------- -bool CTemplateNPCMaker::PlaceNPCInRadius( CAI_BaseNPC *pNPC ) -{ - Vector vPos; - - if ( CAI_BaseNPC::FindSpotForNPCInRadius( &vPos, GetAbsOrigin(), pNPC, m_flRadius ) ) - { - pNPC->SetAbsOrigin( vPos ); - return true; - } - - DevMsg("**Failed to place NPC in radius!\n"); - return false; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CTemplateNPCMaker::MakeMultipleNPCS( int nNPCs ) -{ - bool bInRadius = ( m_iszDestinationGroup == NULL_STRING && m_flRadius > 0.1 ); - while ( nNPCs-- ) - { - if ( !bInRadius ) - { - MakeNPC(); - } - else - { - MakeNPCInRadius(); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CTemplateNPCMaker::InputSpawnMultiple( inputdata_t &inputdata ) -{ - MakeMultipleNPCS( inputdata.value.Int() ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CTemplateNPCMaker::InputChangeDestinationGroup( inputdata_t &inputdata ) -{ - m_iszDestinationGroup = inputdata.value.StringID(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CTemplateNPCMaker::InputSetMinimumSpawnDistance( inputdata_t &inputdata ) -{ - m_iMinSpawnDistance = inputdata.value.Int(); -} diff --git a/game/server/monstermaker.h b/game/server/monstermaker.h deleted file mode 100644 index e4a448935..000000000 --- a/game/server/monstermaker.h +++ /dev/null @@ -1,184 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef MONSTERMAKER_H -#define MONSTERMAKER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "cbase.h" - - -//----------------------------------------------------------------------------- -// Spawnflags -//----------------------------------------------------------------------------- -#define SF_NPCMAKER_START_ON 1 // start active ( if has targetname ) -#define SF_NPCMAKER_NPCCLIP 8 // Children are blocked by NPCclip -#define SF_NPCMAKER_FADE 16 // Children's corpses fade -#define SF_NPCMAKER_INF_CHILD 32 // Infinite number of children -#define SF_NPCMAKER_NO_DROP 64 // Do not adjust for the ground's position when checking for spawn -#define SF_NPCMAKER_HIDEFROMPLAYER 128 // Don't spawn if the player's looking at me -#define SF_NPCMAKER_ALWAYSUSERADIUS 256 // Use radius spawn whenever spawning -#define SF_NPCMAKER_NOPRELOADMODELS 512 // Suppress preloading into the cache of all referenced .mdl files - -//========================================================= -//========================================================= -class CNPCSpawnDestination : public CPointEntity -{ - DECLARE_CLASS( CNPCSpawnDestination, CPointEntity ); - -public: - CNPCSpawnDestination(); - bool IsAvailable(); // Is this spawn destination available for selection? - void OnSpawnedNPC( CAI_BaseNPC *pNPC ); // Notify this spawn destination that an NPC has spawned here. - - float m_ReuseDelay; // How long to be unavailable after being selected - string_t m_RenameNPC; // If not NULL, rename the NPC that spawns here to this. - float m_TimeNextAvailable;// The time at which this destination will be available again. - - COutputEvent m_OnSpawnNPC; - - DECLARE_DATADESC(); -}; - -abstract_class CBaseNPCMaker : public CBaseEntity -{ -public: - DECLARE_CLASS( CBaseNPCMaker, CBaseEntity ); - - void Spawn( void ); - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } - void MakerThink( void ); - bool HumanHullFits( const Vector &vecLocation ); - bool CanMakeNPC( bool bIgnoreSolidEntities = false ); - - virtual void DeathNotice( CBaseEntity *pChild );// NPC maker children use this to tell the NPC maker that they have died. - virtual void MakeNPC( void ) = 0; - - virtual void ChildPreSpawn( CAI_BaseNPC *pChild ) {}; - virtual void ChildPostSpawn( CAI_BaseNPC *pChild ); - - CBaseNPCMaker(void) {} - - // Input handlers - void InputSpawnNPC( inputdata_t &inputdata ); - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - void InputToggle( inputdata_t &inputdata ); - void InputSetMaxChildren( inputdata_t &inputdata ); - void InputAddMaxChildren( inputdata_t &inputdata ); - void InputSetMaxLiveChildren( inputdata_t &inputdata ); - void InputSetSpawnFrequency( inputdata_t &inputdata ); - - // State changers - void Toggle( void ); - virtual void Enable( void ); - virtual void Disable( void ); - - virtual bool IsDepleted( void ); - - DECLARE_DATADESC(); - - int m_nMaxNumNPCs; // max number of NPCs this ent can create - float m_flSpawnFrequency; // delay (in secs) between spawns - - COutputEHANDLE m_OnSpawnNPC; - COutputEvent m_OnAllSpawned; - COutputEvent m_OnAllSpawnedDead; - COutputEvent m_OnAllLiveChildrenDead; - - int m_nLiveChildren; // how many NPCs made by this NPC maker that are currently alive - int m_nMaxLiveChildren; // max number of NPCs that this maker may have out at one time. - - bool m_bDisabled; - - EHANDLE m_hIgnoreEntity; - string_t m_iszIngoreEnt; -}; - - -class CNPCMaker : public CBaseNPCMaker -{ -public: - DECLARE_CLASS( CNPCMaker, CBaseNPCMaker ); - - CNPCMaker( void ); - - void Precache( void ); - - virtual void MakeNPC( void ); - - DECLARE_DATADESC(); - - string_t m_iszNPCClassname; // classname of the NPC(s) that will be created. - string_t m_SquadName; - string_t m_strHintGroup; - string_t m_spawnEquipment; - string_t m_RelationshipString; // Used to load up relationship keyvalues - string_t m_ChildTargetName; -}; - -class CTemplateNPCMaker : public CBaseNPCMaker -{ -public: - DECLARE_CLASS( CTemplateNPCMaker, CBaseNPCMaker ); - - CTemplateNPCMaker( void ) - { - m_iMinSpawnDistance = 0; - } - - virtual void Precache(); - - virtual CNPCSpawnDestination *FindSpawnDestination(); - virtual void MakeNPC( void ); - void MakeNPCInRadius( void ); - void MakeNPCInLine( void ); - virtual void MakeMultipleNPCS( int nNPCs ); - -protected: - virtual void PrecacheTemplateEntity( CBaseEntity *pEntity ); - - bool PlaceNPCInRadius( CAI_BaseNPC *pNPC ); - bool PlaceNPCInLine( CAI_BaseNPC *pNPC ); - - // Inputs - void InputSpawnInRadius( inputdata_t &inputdata ) { MakeNPCInRadius(); } - void InputSpawnInLine( inputdata_t &inputdata ) { MakeNPCInLine(); } - void InputSpawnMultiple( inputdata_t &inputdata ); - void InputChangeDestinationGroup( inputdata_t &inputdata ); - void InputSetMinimumSpawnDistance( inputdata_t &inputdata ); - - float m_flRadius; - - DECLARE_DATADESC(); - - string_t m_iszTemplateName; // The name of the NPC that will be used as the template. - string_t m_iszTemplateData; // The keyvalue data blob from the template NPC that will be used to spawn new ones. - string_t m_iszDestinationGroup; - - int m_iMinSpawnDistance; - - enum ThreeStateYesNo_t - { - TS_YN_YES = 0, - TS_YN_NO, - TS_YN_DONT_CARE, - }; - - enum ThreeStateDist_t - { - TS_DIST_NEAREST = 0, - TS_DIST_FARTHEST, - TS_DIST_DONT_CARE, - }; - - ThreeStateYesNo_t m_CriterionVisibility; - ThreeStateDist_t m_CriterionDistance; -}; - -#endif // MONSTERMAKER_H diff --git a/game/server/movehelper_server.cpp b/game/server/movehelper_server.cpp deleted file mode 100644 index 99bbeba5d..000000000 --- a/game/server/movehelper_server.cpp +++ /dev/null @@ -1,381 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include -#include "gamerules.h" -#include "player.h" -#include "model_types.h" -#include "movehelper_server.h" -#include "shake.h" // For screen fade constants -#include "engine/IEngineSound.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern IPhysicsCollision *physcollision; - - -//----------------------------------------------------------------------------- -// Implementation of the movehelper on the server -//----------------------------------------------------------------------------- - -class CMoveHelperServer : public IMoveHelperServer -{ -public: - CMoveHelperServer( void ); - virtual ~CMoveHelperServer(); - - // Methods associated with a particular entity - virtual char const* GetName( EntityHandle_t handle ) const; - - // Touch list... - virtual void ResetTouchList( void ); - virtual bool AddToTouched( const trace_t &tr, const Vector& impactvelocity ); - virtual void ProcessImpacts( void ); - - virtual bool PlayerFallingDamage( void ); - virtual void PlayerSetAnimation( PLAYER_ANIM eAnim ); - - // Numbered line printf - virtual void Con_NPrintf( int idx, char const* fmt, ... ); - - // These have separate server vs client impementations - virtual void StartSound( const Vector& origin, int channel, char const* sample, float volume, soundlevel_t soundlevel, int fFlags, int pitch ); - virtual void StartSound( const Vector& origin, const char *soundname ); - - virtual void PlaybackEventFull( int flags, int clientindex, unsigned short eventindex, float delay, Vector& origin, Vector& angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 ); - virtual IPhysicsSurfaceProps *GetSurfaceProps( void ); - - void SetHost( CBasePlayer *host ); - - virtual bool IsWorldEntity( const CBaseHandle &handle ); - -private: - CBasePlayer* m_pHostPlayer; - - // results, tallied on client and server, but only used by server to run SV_Impact. - // we store off our velocity in the trace_t structure so that we can determine results - // of shoving boxes etc. around. - struct touchlist_t - { - Vector deltavelocity; - trace_t trace; - }; - - CUtlVector m_TouchList; -}; - - -//----------------------------------------------------------------------------- -// Singleton -//----------------------------------------------------------------------------- - -IMPLEMENT_MOVEHELPER(); - -IMoveHelperServer* MoveHelperServer() -{ - static CMoveHelperServer s_MoveHelperServer; - return &s_MoveHelperServer; -} - - -//----------------------------------------------------------------------------- -// Converts the entity handle into a edict_t -//----------------------------------------------------------------------------- - -static inline edict_t* GetEdict( EntityHandle_t handle ) -{ - return gEntList.GetEdict( handle ); -} - - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- - -CMoveHelperServer::CMoveHelperServer( void ) : m_TouchList( 0, 128 ) -{ - m_pHostPlayer = 0; - SetSingleton( this ); -} - -CMoveHelperServer::~CMoveHelperServer( void ) -{ - SetSingleton( 0 ); -} - -//----------------------------------------------------------------------------- -// Indicates which player we're going to move -//----------------------------------------------------------------------------- - -void CMoveHelperServer::SetHost( CBasePlayer *host ) -{ - m_pHostPlayer = host; - - // In case any stuff is ever left over, sigh... - ResetTouchList(); -} - - -//----------------------------------------------------------------------------- -// Returns the name for debugging purposes -//----------------------------------------------------------------------------- -char const* CMoveHelperServer::GetName( EntityHandle_t handle ) const -{ - // This ain't pertickulerly fast, but it's for debugging anyways - edict_t* pEdict = GetEdict(handle); - CBaseEntity *ent = CBaseEntity::Instance( pEdict ); - - // Is it the world? - if (ENTINDEX(pEdict) == 0) - return STRING(gpGlobals->mapname); - - // Is it a model? - if ( ent && ent->GetModelName() != NULL_STRING ) - return STRING( ent->GetModelName() ); - - if ( ent->GetClassname() != NULL ) - { - return ent->GetClassname(); - } - - return "?"; -} - -//----------------------------------------------------------------------------- -// When we do a collision test, we report everything we hit.. -//----------------------------------------------------------------------------- - -void CMoveHelperServer::ResetTouchList( void ) -{ - m_TouchList.RemoveAll(); -} - - -//----------------------------------------------------------------------------- -// When a collision occurs, we add it to the touched list -//----------------------------------------------------------------------------- - -bool CMoveHelperServer::AddToTouched( const trace_t &tr, const Vector& impactvelocity ) -{ - Assert( m_pHostPlayer ); - - // Trace missed - if ( !tr.m_pEnt ) - return false; - - if ( tr.m_pEnt == m_pHostPlayer ) - { - Assert( !"CMoveHelperServer::AddToTouched: Tried to add self to touchlist!!!" ); - return false; - } - - // Check for duplicate entities - for ( int j = m_TouchList.Size(); --j >= 0; ) - { - if ( m_TouchList[j].trace.m_pEnt == tr.m_pEnt ) - { - return false; - } - } - - int i = m_TouchList.AddToTail(); - m_TouchList[i].trace = tr; - VectorCopy( impactvelocity, m_TouchList[i].deltavelocity ); - - return true; -} - - -//----------------------------------------------------------------------------- -// After we built the touch list, deal with all the impacts... -//----------------------------------------------------------------------------- -void CMoveHelperServer::ProcessImpacts( void ) -{ - Assert( m_pHostPlayer ); - - // Relink in order to build absorigin and absmin/max to reflect any changes - // from prediction. Relink will early out on SOLID_NOT - m_pHostPlayer->PhysicsTouchTriggers(); - - // Don't bother if the player ain't solid - if ( m_pHostPlayer->IsSolidFlagSet( FSOLID_NOT_SOLID ) ) - return; - - // Save off the velocity, cause we need to temporarily reset it - Vector vel = m_pHostPlayer->GetAbsVelocity(); - - // Touch other objects that were intersected during the movement. - for (int i = 0 ; i < m_TouchList.Size(); i++) - { - CBaseHandle entindex = m_TouchList[i].trace.m_pEnt->GetRefEHandle(); - - // We should have culled negative indices by now - Assert( entindex.IsValid() ); - - edict_t* ent = GetEdict( entindex ); - if (!ent) - continue; - - // Run the impact function as if we had run it during movement. - CBaseEntity *entity = GetContainingEntity( ent ); - if ( !entity ) - continue; - - Assert( entity != m_pHostPlayer ); - // Don't ever collide with self!!!! - if ( entity == m_pHostPlayer ) - continue; - - // Reconstruct trace results. - m_TouchList[i].trace.m_pEnt = CBaseEntity::Instance( ent ); - - // Use the velocity we had when we collided, so boxes will move, etc. - m_pHostPlayer->SetAbsVelocity( m_TouchList[i].deltavelocity ); - - entity->PhysicsImpact( m_pHostPlayer, m_TouchList[i].trace ); - } - - // Restore the velocity - m_pHostPlayer->SetAbsVelocity( vel ); - - // So no stuff is ever left over, sigh... - ResetTouchList(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : origin - -// *soundname - -//----------------------------------------------------------------------------- -void CMoveHelperServer::StartSound( const Vector& origin, const char *soundname ) -{ - //MDB - Changing this to send to PAS, as the overloaded function below has done. - //Also removed the UsePredictionRules, client does not yet play the equivalent sound - - CRecipientFilter filter; - filter.AddRecipientsByPAS( origin ); - - CBaseEntity::EmitSound( filter, m_pHostPlayer->entindex(), soundname ); -} - -//----------------------------------------------------------------------------- -// plays a sound -//----------------------------------------------------------------------------- -void CMoveHelperServer::StartSound( const Vector& origin, int channel, char const* sample, - float volume, soundlevel_t soundlevel, int fFlags, int pitch ) -{ - - CRecipientFilter filter; - filter.AddRecipientsByPAS( origin ); - // FIXME, these sounds should not go to the host entity ( SND_NOTHOST ) - if ( gpGlobals->maxClients == 1 ) - { - // Always send sounds down in SP - - EmitSound_t ep; - ep.m_nChannel = channel; - ep.m_pSoundName = sample; - ep.m_flVolume = volume; - ep.m_SoundLevel = soundlevel; - ep.m_nFlags = fFlags; - ep.m_nPitch = pitch; - ep.m_pOrigin = &origin; - - CBaseEntity::EmitSound( filter, m_pHostPlayer->entindex(), ep ); - } - else - { - filter.UsePredictionRules(); - - EmitSound_t ep; - ep.m_nChannel = channel; - ep.m_pSoundName = sample; - ep.m_flVolume = volume; - ep.m_SoundLevel = soundlevel; - ep.m_nFlags = fFlags; - ep.m_nPitch = pitch; - ep.m_pOrigin = &origin; - - CBaseEntity::EmitSound( filter, m_pHostPlayer->entindex(), ep ); - } -} - - -//----------------------------------------------------------------------------- -// Umm... -//----------------------------------------------------------------------------- -void CMoveHelperServer::PlaybackEventFull( int flags, int clientindex, unsigned short eventindex, float delay, Vector& origin, Vector& angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 ) -{ - // FIXME, Redo with new event system parameter stuff -} - -IPhysicsSurfaceProps *CMoveHelperServer::GetSurfaceProps( void ) -{ - extern IPhysicsSurfaceProps *physprops; - return physprops; -} - -//----------------------------------------------------------------------------- -// Purpose: Note that this only works on a listen server (since it requires graphical output) -// *pFormat - -// ... - -//----------------------------------------------------------------------------- -void CMoveHelperServer::Con_NPrintf( int idx, char const* pFormat, ...) -{ - va_list marker; - char msg[8192]; - - va_start(marker, pFormat); - Q_vsnprintf(msg, sizeof( msg ), pFormat, marker); - va_end(marker); - - engine->Con_NPrintf( idx, msg ); -} - -//----------------------------------------------------------------------------- -// Purpose: Called when the player falls onto a surface fast enough to take -// damage, according to the rules in CGameMovement::CheckFalling. -// Output : Returns true if the player survived the fall, false if they died. -//----------------------------------------------------------------------------- -bool CMoveHelperServer::PlayerFallingDamage( void ) -{ - float flFallDamage = g_pGameRules->FlPlayerFallDamage( m_pHostPlayer ); - if ( flFallDamage > 0 ) - { - m_pHostPlayer->TakeDamage( CTakeDamageInfo( GetContainingEntity(INDEXENT(0)), GetContainingEntity(INDEXENT(0)), flFallDamage, DMG_FALL ) ); - StartSound( m_pHostPlayer->GetAbsOrigin(), "Player.FallDamage" ); - } - - if ( m_pHostPlayer->m_iHealth <= 0 ) - { - if ( g_pGameRules->FlPlayerFallDeathDoesScreenFade( m_pHostPlayer ) ) - { - color32 black = {0, 0, 0, 255}; - UTIL_ScreenFade( m_pHostPlayer, black, 0, 9999, FFADE_OUT | FFADE_STAYOUT ); - } - return(false); - } - - return(true); -} - - -//----------------------------------------------------------------------------- -// Purpose: Sets an animation in the player. -// Input : eAnim - Animation to set. -//----------------------------------------------------------------------------- -void CMoveHelperServer::PlayerSetAnimation( PLAYER_ANIM eAnim ) -{ - m_pHostPlayer->SetAnimation( eAnim ); -} - -bool CMoveHelperServer::IsWorldEntity( const CBaseHandle &handle ) -{ - return handle == CBaseEntity::Instance( 0 ); -} diff --git a/game/server/movehelper_server.h b/game/server/movehelper_server.h deleted file mode 100644 index f5555b3a1..000000000 --- a/game/server/movehelper_server.h +++ /dev/null @@ -1,43 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef MOVEHELPER_SERVER_H -#define MOVEHELPER_SERVER_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "imovehelper.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- - -class CBasePlayer; -class CBaseEntity; - - -//----------------------------------------------------------------------------- -// Implementation of the movehelper on the server -//----------------------------------------------------------------------------- - -abstract_class IMoveHelperServer : public IMoveHelper -{ -public: - virtual void SetHost( CBasePlayer *host ) = 0; -}; - -//----------------------------------------------------------------------------- -// Singleton access -//----------------------------------------------------------------------------- - -IMoveHelperServer* MoveHelperServer(); - - -#endif // MOVEHELPER_SERVER_H diff --git a/game/server/movement.cpp b/game/server/movement.cpp deleted file mode 100644 index 3224b4692..000000000 --- a/game/server/movement.cpp +++ /dev/null @@ -1,658 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: MOVEMENT ENTITIES TEST -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "entitylist.h" -#include "entityoutput.h" -#include "keyframe/keyframe.h" // BUG: this needs to move if keyframe is a standard thing - -#include "mathlib/mathlib.h" // FIXME: why do we still need this? - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// Hack, sort of. These interpolators don't get to hold state, but the ones -// that need state (like the rope simulator) should NOT be used as paths here. -IPositionInterpolator *g_pPositionInterpolators[8] = {0,0,0,0,0,0,0,0}; - -IPositionInterpolator* GetPositionInterpolator( int iInterp ) -{ - if( !g_pPositionInterpolators[iInterp] ) - g_pPositionInterpolators[iInterp] = Motion_GetPositionInterpolator( iInterp ); - - return g_pPositionInterpolators[iInterp]; -} - - -static float Fix( float angle ) -{ - while ( angle < 0 ) - angle += 360; - while ( angle > 360 ) - angle -= 360; - - return angle; -} - -void FixupAngles( QAngle &v ) -{ - v.x = Fix( v.x ); - v.y = Fix( v.y ); - v.z = Fix( v.z ); -} - - -//----------------------------------------------------------------------------- -// -// Purpose: Contains a description of a keyframe -// has no networked representation, so has to store origin, etc. itself -// -//----------------------------------------------------------------------------- -class CPathKeyFrame : public CLogicalEntity -{ -public: - DECLARE_CLASS( CPathKeyFrame, CLogicalEntity ); - - void Spawn( void ); - void Activate( void ); - void Link( void ); - - Vector m_Origin; - QAngle m_Angles; // euler angles PITCH YAW ROLL (Y Z X) - Quaternion m_qAngle; // quaternion angle (generated from m_Angles) - - string_t m_iNextKey; - float m_flNextTime; - - CPathKeyFrame *NextKey( int direction ); - CPathKeyFrame *PrevKey( int direction ); - - float Speed( void ) { return m_flSpeed; } - void SetKeyAngles( QAngle angles ); - - CPathKeyFrame *InsertNewKey( Vector newPos, QAngle newAngles ); - void CalculateFrameDuration( void ); - -protected: - CPathKeyFrame *m_pNextKey; - CPathKeyFrame *m_pPrevKey; - - float m_flSpeed; - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( keyframe_track, CPathKeyFrame ); - -BEGIN_DATADESC( CPathKeyFrame ) - - DEFINE_FIELD( m_Origin, FIELD_VECTOR ), - DEFINE_FIELD( m_Angles, FIELD_VECTOR ), - DEFINE_FIELD( m_qAngle, FIELD_QUATERNION ), - - DEFINE_KEYFIELD( m_iNextKey, FIELD_STRING, "NextKey" ), - DEFINE_FIELD( m_flNextTime, FIELD_FLOAT ), // derived from speed - DEFINE_KEYFIELD( m_flSpeed, FIELD_FLOAT, "MoveSpeed" ), - DEFINE_FIELD( m_pNextKey, FIELD_CLASSPTR ), - DEFINE_FIELD( m_pPrevKey, FIELD_CLASSPTR ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: Converts inputed euler angles to internal angle format (quaternions) -//----------------------------------------------------------------------------- -void CPathKeyFrame::Spawn( void ) -{ - m_Origin = GetLocalOrigin(); - m_Angles = GetLocalAngles(); - - SetKeyAngles( m_Angles ); -} - -//----------------------------------------------------------------------------- -// Purpose: Adds the keyframe into the path after all the other keys have spawned -//----------------------------------------------------------------------------- -void CPathKeyFrame::Activate( void ) -{ - BaseClass::Activate(); - - Link(); - - CalculateFrameDuration(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPathKeyFrame::CalculateFrameDuration( void ) -{ - // calculate time from speed - if ( m_pNextKey && m_flSpeed > 0 ) - { - m_flNextTime = (m_Origin - m_pNextKey->m_Origin).Length() / m_flSpeed; - - // couldn't get time from distance, get it from rotation instead - if ( !m_flNextTime ) - { - // speed is in degrees per second - // find the largest rotation component and use that - QAngle ang = m_Angles - m_pNextKey->m_Angles; - FixupAngles( ang ); - float x = 0; - for ( int i = 0; i < 3; i++ ) - { - if ( fabs(ang[i]) > x ) - { - x = fabs(ang[i]); - } - } - - m_flNextTime = x / m_flSpeed; - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Links the key frame into the key frame list -//----------------------------------------------------------------------------- -void CPathKeyFrame::Link( void ) -{ - m_pNextKey = dynamic_cast( gEntList.FindEntityByName(NULL, m_iNextKey ) ); - - if ( m_pNextKey ) - { - m_pNextKey->m_pPrevKey = this; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : angles - -//----------------------------------------------------------------------------- -void CPathKeyFrame::SetKeyAngles( QAngle angles ) -{ - m_Angles = angles; - AngleQuaternion( m_Angles, m_qAngle ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : direction - -// Output : CPathKeyFrame -//----------------------------------------------------------------------------- -CPathKeyFrame* CPathKeyFrame::NextKey( int direction ) -{ - if ( direction == 1 ) - { - return m_pNextKey; - } - else if ( direction == -1 ) - { - return m_pPrevKey; - } - - return this; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : direction - -// Output : CPathKeyFrame -//----------------------------------------------------------------------------- -CPathKeyFrame *CPathKeyFrame::PrevKey( int direction ) -{ - if ( direction == 1 ) - { - return m_pPrevKey; - } - else if ( direction == -1 ) - { - return m_pNextKey; - } - - return this; -} - -//----------------------------------------------------------------------------- -// Purpose: Creates and insterts a new keyframe into the sequence -// Input : newPos - -// newAngles - -// Output : CPathKeyFrame -//----------------------------------------------------------------------------- -CPathKeyFrame *CPathKeyFrame::InsertNewKey( Vector newPos, QAngle newAngles ) -{ - CPathKeyFrame *newKey = CREATE_ENTITY( CPathKeyFrame, "keyframe_track" ); - - // copy data across - newKey->SetKeyAngles( newAngles ); - newKey->m_Origin = newPos; - newKey->m_flSpeed = m_flSpeed; - newKey->SetEFlags( GetEFlags() ); - if ( m_iParent != NULL_STRING ) - { - newKey->SetParent( m_iParent, NULL ); - } - - // link forward - newKey->m_pNextKey = m_pNextKey; - m_pNextKey->m_pPrevKey = newKey; - - // link back - m_pNextKey = newKey; - newKey->m_pPrevKey = this; - - // calculate new times - CalculateFrameDuration(); - newKey->CalculateFrameDuration(); - - return newKey; -} - - -//----------------------------------------------------------------------------- -// -// Purpose: Basic keyframed movement behavior -// -//----------------------------------------------------------------------------- -class CBaseMoveBehavior : public CPathKeyFrame -{ -public: - DECLARE_CLASS( CBaseMoveBehavior, CPathKeyFrame ); - - void Spawn( void ); - void Activate( void ); - void MoveDone( void ); - float SetObjectPhysicsVelocity( float moveTime ); - - // methods - virtual bool StartMoving( int direction ); - virtual void StopMoving( void ); - virtual bool IsMoving( void ); - - // derived classes should override this to get notification of arriving at new keyframes -// virtual void ArrivedAtKeyFrame( CPathKeyFrame * ) {} - - bool IsAtSequenceStart( void ); - bool IsAtSequenceEnd( void ); - - // interpolation functions -// int m_iTimeModifier; - int m_iPositionInterpolator; - int m_iRotationInterpolator; - - // animation vars - float m_flAnimStartTime; - float m_flAnimEndTime; - float m_flAverageSpeedAcrossFrame; // for advancing time with speed (not the normal visa-versa) - CPathKeyFrame *m_pCurrentKeyFrame; // keyframe currently moving from - CPathKeyFrame *m_pTargetKeyFrame; // keyframe being moved to - CPathKeyFrame *m_pPreKeyFrame, *m_pPostKeyFrame; // pre- and post-keyframe's for spline interpolation - float m_flTimeIntoFrame; - - int m_iDirection; // 1 for forward, -1 for backward, and 0 for at rest - - float CalculateTimeAdvancementForSpeed( float moveTime, float speed ); - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( move_keyframed, CBaseMoveBehavior ); - -BEGIN_DATADESC( CBaseMoveBehavior ) - -// DEFINE_KEYFIELD( m_iTimeModifier, FIELD_INTEGER, "TimeModifier" ), - DEFINE_KEYFIELD( m_iPositionInterpolator, FIELD_INTEGER, "PositionInterpolator" ), - DEFINE_KEYFIELD( m_iRotationInterpolator, FIELD_INTEGER, "RotationInterpolator" ), - - DEFINE_FIELD( m_pCurrentKeyFrame, FIELD_CLASSPTR ), - DEFINE_FIELD( m_pTargetKeyFrame, FIELD_CLASSPTR ), - DEFINE_FIELD( m_pPreKeyFrame, FIELD_CLASSPTR ), - DEFINE_FIELD( m_pPostKeyFrame, FIELD_CLASSPTR ), - - DEFINE_FIELD( m_flAnimStartTime, FIELD_FLOAT ), - DEFINE_FIELD( m_flAnimEndTime, FIELD_FLOAT ), - DEFINE_FIELD( m_flAverageSpeedAcrossFrame, FIELD_FLOAT ), - DEFINE_FIELD( m_flTimeIntoFrame, FIELD_FLOAT ), - DEFINE_FIELD( m_iDirection, FIELD_INTEGER ), - -END_DATADESC() - - -void CBaseMoveBehavior::Spawn( void ) -{ - m_pCurrentKeyFrame = this; - m_flTimeIntoFrame = 0; - SetMoveType( MOVETYPE_PUSH ); - - // a move behavior is also it's first keyframe - m_Origin = GetLocalOrigin(); - m_Angles = GetLocalAngles(); - - BaseClass::Spawn(); -} - -void CBaseMoveBehavior::Activate( void ) -{ - BaseClass::Activate(); - - SetMoveDoneTime( 0.5 ); // start moving in 0.2 seconds time - - // if we are just the basic keyframed entity, cycle our animation - if ( !stricmp(GetClassname(), "move_keyframed") ) - { - StartMoving( 1 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Checks to see if the we're at the start of the keyframe sequence -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseMoveBehavior::IsAtSequenceStart( void ) -{ - if ( !m_pCurrentKeyFrame ) - return true; - - if ( m_flAnimStartTime && m_flAnimStartTime >= GetLocalTime() ) - { - if ( !m_pCurrentKeyFrame->PrevKey(1) && !m_pTargetKeyFrame ) - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Checks to see if we're at the end of the keyframe sequence -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseMoveBehavior::IsAtSequenceEnd( void ) -{ - if ( !m_pCurrentKeyFrame ) - return false; - - if ( !m_pCurrentKeyFrame->NextKey(1) && !m_pTargetKeyFrame ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseMoveBehavior::IsMoving( void ) -{ - if ( m_iDirection != 0 ) - return true; - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Starts the object moving from it's current position, in the direction indicated -// Input : direction - 1 is forward through the sequence, -1 is backwards, and 0 is stop -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseMoveBehavior::StartMoving( int direction ) -{ - // 0 direction is to stop moving - if ( direction == 0 ) - { - StopMoving(); - return false; - } - - // check to see if we should keep moving in the current direction - if ( m_iDirection == direction ) - { - // if we're at the end of the current anim key, move to the next one - if ( GetLocalTime() >= m_flAnimEndTime ) - { - m_pCurrentKeyFrame = m_pTargetKeyFrame; - m_flTimeIntoFrame = 0; - - if ( !m_pTargetKeyFrame->NextKey(direction) ) - { - // we've hit the end of the sequence - m_flAnimEndTime = 0; - m_flAnimStartTime = 0; - StopMoving(); - return false; - } - - // advance the target keyframe - m_pTargetKeyFrame = m_pTargetKeyFrame->NextKey(direction); - } - } - else - { - // we're changing direction - - // need to calculate current position in the frame - // stop first, then start again - if ( m_iDirection != 0 ) - { - StopMoving(); - } - - m_iDirection = direction; - - // if we're going in reverse, swap the currentkey and targetkey (since we're going opposite dir) - if ( direction == 1 ) - { - m_pTargetKeyFrame = m_pCurrentKeyFrame->NextKey( direction ); - } - else if ( direction == -1 ) - { - if ( m_flTimeIntoFrame > 0 ) - { - m_pTargetKeyFrame = m_pCurrentKeyFrame; - m_pCurrentKeyFrame = m_pCurrentKeyFrame->NextKey( 1 ); - } - else - { - m_pTargetKeyFrame = m_pCurrentKeyFrame->PrevKey( 1 ); - } - } - - // recalculate our movement from the stored data - if ( !m_pTargetKeyFrame ) - { - StopMoving(); - return false; - } - - // calculate the keyframes before and after the keyframes we're interpolating between - m_pPostKeyFrame = m_pTargetKeyFrame->NextKey( direction ); - if ( !m_pPostKeyFrame ) - { - m_pPostKeyFrame = m_pTargetKeyFrame; - } - m_pPreKeyFrame = m_pCurrentKeyFrame->PrevKey( direction ); - if ( !m_pPreKeyFrame ) - { - m_pPreKeyFrame = m_pCurrentKeyFrame; - } - } - - // no target, can't move - if ( !m_pTargetKeyFrame ) - return false; - - // calculate start/end time - // ->m_flNextTime is the time to traverse to the NEXT key, so we need the opposite if travelling backwards - if ( m_iDirection == 1 ) - { - m_flAnimStartTime = GetLocalTime() - m_flTimeIntoFrame; - m_flAnimEndTime = GetLocalTime() + m_pCurrentKeyFrame->m_flNextTime - m_flTimeIntoFrame; - } - else - { - // flip the timing, since we're in reverse - if ( m_flTimeIntoFrame ) - m_flTimeIntoFrame = m_pTargetKeyFrame->m_flNextTime - m_flTimeIntoFrame; - - m_flAnimStartTime = GetLocalTime() - m_flTimeIntoFrame; - m_flAnimEndTime = GetLocalTime() + m_pTargetKeyFrame->m_flNextTime - m_flTimeIntoFrame; - } - - // calculate the average speed at which we cross - float animDuration = (m_flAnimEndTime - m_flAnimStartTime); - float dist = (m_pCurrentKeyFrame->m_Origin - m_pTargetKeyFrame->m_Origin).Length(); - m_flAverageSpeedAcrossFrame = animDuration / dist; - - SetMoveDoneTime( m_flAnimEndTime - GetLocalTime() ); - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: stops the object from moving -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -void CBaseMoveBehavior::StopMoving( void ) -{ - // remember exactly where we are in the frame - m_flTimeIntoFrame = 0; - - if ( m_iDirection == 1 ) - { - // record the time if we're not at the end of the frame - if ( GetLocalTime() < m_flAnimEndTime ) - { - m_flTimeIntoFrame = GetLocalTime() - m_flAnimStartTime; - } - else - { - // we're actually at the end - if ( m_pTargetKeyFrame ) - { - m_pCurrentKeyFrame = m_pTargetKeyFrame; - } - } - } - else if ( m_iDirection == -1 ) - { - // store it only as a forward movement - m_pCurrentKeyFrame = m_pTargetKeyFrame; - - if ( GetLocalTime() < m_flAnimEndTime ) - { - m_flTimeIntoFrame = m_flAnimEndTime - GetLocalTime(); - } - } - - // stop moving totally - SetMoveDoneTime( -1 ); - m_iDirection = 0; - m_flAnimStartTime = 0; - m_flAnimEndTime = 0; - m_pTargetKeyFrame = NULL; - SetAbsVelocity(vec3_origin); - SetLocalAngularVelocity( vec3_angle ); -} - - -//----------------------------------------------------------------------------- -// Purpose: We have just arrived at a key, move onto the next keyframe -//----------------------------------------------------------------------------- -void CBaseMoveBehavior::MoveDone( void ) -{ - // if we're just a base then keep playing the anim - if ( !stricmp(STRING(m_iClassname), "move_keyframed") ) - { - int direction = m_iDirection; - // start moving from the keyframe we've just reached - if ( !StartMoving(direction) ) - { - // try moving in the other direction - StartMoving( -direction ); - } - } - - BaseClass::MoveDone(); -} - -//----------------------------------------------------------------------------- -// Purpose: Calculates a new moveTime based on the speed and the current point -// in the animation. -// used to advance keyframed objects that have dynamic speeds. -// Input : moveTime - -// Output : float - the new time in the keyframing sequence -//----------------------------------------------------------------------------- -float CBaseMoveBehavior::CalculateTimeAdvancementForSpeed( float moveTime, float speed ) -{ - return (moveTime * speed * m_flAverageSpeedAcrossFrame); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// GetLocalTime() is the objects local current time -// Input : destTime - new time that is being moved to -// moveTime - amount of time to be advanced this frame -// Output : float - the actual amount of time to move (usually moveTime) -//----------------------------------------------------------------------------- -float CBaseMoveBehavior::SetObjectPhysicsVelocity( float moveTime ) -{ - // make sure we have a valid set up - if ( !m_pCurrentKeyFrame || !m_pTargetKeyFrame ) - return moveTime; - - // if we're not moving, we're not moving - if ( !IsMoving() ) - return moveTime; - - float destTime = moveTime + GetLocalTime(); - - // work out where we want to be, using destTime - m_flTimeIntoFrame = destTime - m_flAnimStartTime; - float newTime = (destTime - m_flAnimStartTime) / (m_flAnimEndTime - m_flAnimStartTime); - Vector newPos; - QAngle newAngles; - - IPositionInterpolator *pInterp = GetPositionInterpolator( m_iPositionInterpolator ); - if( pInterp ) - { - // setup key frames - pInterp->SetKeyPosition( -1, m_pPreKeyFrame->m_Origin ); - Motion_SetKeyAngles( -1, m_pPreKeyFrame->m_qAngle ); - - pInterp->SetKeyPosition( 0, m_pCurrentKeyFrame->m_Origin ); - Motion_SetKeyAngles( 0, m_pCurrentKeyFrame->m_qAngle ); - - pInterp->SetKeyPosition( 1, m_pTargetKeyFrame->m_Origin ); - Motion_SetKeyAngles( 1, m_pTargetKeyFrame->m_qAngle ); - - pInterp->SetKeyPosition( 2, m_pPostKeyFrame->m_Origin ); - Motion_SetKeyAngles( 2, m_pPostKeyFrame->m_qAngle ); - - // find new interpolated position & rotation - pInterp->InterpolatePosition( newTime, newPos ); - } - else - { - newPos.Init(); - } - - Quaternion qRot; - Motion_InterpolateRotation( newTime, m_iRotationInterpolator, qRot ); - QuaternionAngles( qRot, newAngles ); - - // find our velocity vector (newPos - currentPos) and scale velocity vector according to the movetime - float oneOnMoveTime = 1 / moveTime; - SetAbsVelocity( (newPos - GetLocalOrigin()) * oneOnMoveTime ); - SetLocalAngularVelocity( (newAngles - GetLocalAngles()) * oneOnMoveTime ); - - return moveTime; -} - diff --git a/game/server/movie_explosion.cpp b/game/server/movie_explosion.cpp deleted file mode 100644 index 776f63fee..000000000 --- a/game/server/movie_explosion.cpp +++ /dev/null @@ -1,44 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "movie_explosion.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define MOVIEEXPLOSION_ENTITYNAME "env_movieexplosion" - - -IMPLEMENT_SERVERCLASS_ST(MovieExplosion, DT_MovieExplosion) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS(env_movieexplosion, MovieExplosion); - - -MovieExplosion* MovieExplosion::CreateMovieExplosion(const Vector &pos) -{ - CBaseEntity *pEnt = CreateEntityByName(MOVIEEXPLOSION_ENTITYNAME); - if(pEnt) - { - MovieExplosion *pEffect = dynamic_cast(pEnt); - if(pEffect && pEffect->edict()) - { - pEffect->SetLocalOrigin( pos ); - pEffect->Activate(); - return pEffect; - } - else - { - UTIL_Remove(pEnt); - } - } - - return NULL; -} - - diff --git a/game/server/movie_explosion.h b/game/server/movie_explosion.h deleted file mode 100644 index e57841911..000000000 --- a/game/server/movie_explosion.h +++ /dev/null @@ -1,28 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef MOVIE_EXPLOSION_H -#define MOVIE_EXPLOSION_H - - -#include "baseparticleentity.h" - - -class MovieExplosion : public CBaseParticleEntity -{ -public: - DECLARE_CLASS( MovieExplosion, CBaseParticleEntity ); - DECLARE_SERVERCLASS(); - - static MovieExplosion* CreateMovieExplosion(const Vector &pos); -}; - - -#endif - - diff --git a/game/server/nav.h b/game/server/nav.h deleted file mode 100644 index aa2f83548..000000000 --- a/game/server/nav.h +++ /dev/null @@ -1,367 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -// nav.h -// Data structures and constants for the Navigation Mesh system -// Author: Michael S. Booth (mike@turtlerockstudios.com), January 2003 - -#ifndef _NAV_H_ -#define _NAV_H_ - -#include "modelentities.h" // for CFuncBrush - -/** - * Below are several constants used by the navigation system. - * @todo Move these into TheNavMesh singleton. - */ -const float GenerationStepSize = 25.0f; ///< (30) was 20, but bots can't fit always fit -const float StepHeight = 18.0f; ///< if delta Z is greater than this, we have to jump to get up -const float JumpHeight = 41.8f; ///< if delta Z is less than this, we can jump up on it -const float JumpCrouchHeight = 58.0f; ///< (48) if delta Z is less than or equal to this, we can jumpcrouch up on it - -const float BotRadius = 10.0f; ///< circular extent that contains bot -const float DeathDrop = 200.0f; ///< (300) distance at which we will die if we fall - should be about 600, and pay attention to fall damage during pathfind - -const float HalfHumanWidth = 16.0f; -const float HalfHumanHeight = 36.0f; -const float HumanHeight = 72.0f; - - -#define NAV_MAGIC_NUMBER 0xFEEDFACE ///< to help identify nav files - -/** - * A place is a named group of navigation areas - */ -typedef unsigned int Place; -#define UNDEFINED_PLACE 0 // ie: "no place" -#define ANY_PLACE 0xFFFF - -enum NavErrorType -{ - NAV_OK, - NAV_CANT_ACCESS_FILE, - NAV_INVALID_FILE, - NAV_BAD_FILE_VERSION, - NAV_FILE_OUT_OF_DATE, - NAV_CORRUPT_DATA, -}; - -enum NavAttributeType -{ - NAV_MESH_CROUCH = 0x0001, ///< must crouch to use this node/area - NAV_MESH_JUMP = 0x0002, ///< must jump to traverse this area - NAV_MESH_PRECISE = 0x0004, ///< do not adjust for obstacles, just move along area - NAV_MESH_NO_JUMP = 0x0008, ///< inhibit discontinuity jumping - NAV_MESH_STOP = 0x0010, ///< must stop when entering this area - NAV_MESH_RUN = 0x0020, ///< must run to traverse this area - NAV_MESH_WALK = 0x0040, ///< must walk to traverse this area - NAV_MESH_AVOID = 0x0080, ///< avoid this area unless alternatives are too dangerous - NAV_MESH_TRANSIENT = 0x0100, ///< area may become blocked, and should be periodically checked - NAV_MESH_DONT_HIDE = 0x0200, ///< area should not be considered for hiding spot generation - NAV_MESH_STAND = 0x0400, ///< bots hiding in this area should stand - NAV_MESH_NO_HOSTAGES = 0x0800, ///< hostages shouldn't use this area -}; - -enum NavDirType -{ - NORTH = 0, - EAST = 1, - SOUTH = 2, - WEST = 3, - - NUM_DIRECTIONS -}; - -/** - * Defines possible ways to move from one area to another - */ -enum NavTraverseType -{ - // NOTE: First 4 directions MUST match NavDirType - GO_NORTH = 0, - GO_EAST, - GO_SOUTH, - GO_WEST, - GO_LADDER_UP, - GO_LADDER_DOWN, - GO_JUMP, - - NUM_TRAVERSE_TYPES -}; - -enum NavCornerType -{ - NORTH_WEST = 0, - NORTH_EAST = 1, - SOUTH_EAST = 2, - SOUTH_WEST = 3, - - NUM_CORNERS -}; - -enum NavRelativeDirType -{ - FORWARD = 0, - RIGHT, - BACKWARD, - LEFT, - UP, - DOWN, - - NUM_RELATIVE_DIRECTIONS -}; - -struct Extent -{ - Vector lo, hi; - - void Init( void ) - { - lo.Init(); - hi.Init(); - } - - float SizeX( void ) const { return hi.x - lo.x; } - float SizeY( void ) const { return hi.y - lo.y; } - float SizeZ( void ) const { return hi.z - lo.z; } - float Area( void ) const { return SizeX() * SizeY(); } - - // Increase bounds to contain the given point - void Encompass( const Vector &pos ) - { - for ( int i=0; i<3; ++i ) - { - if ( pos[i] < lo[i] ) - { - lo[i] = pos[i]; - } - else if ( pos[i] > hi[i] ) - { - hi[i] = pos[i]; - } - } - } - - /// return true if 'pos' is inside of this extent - bool Contains( const Vector &pos ) const - { - return (pos.x >= lo.x && pos.x <= hi.x && - pos.y >= lo.y && pos.y <= hi.y && - pos.z >= lo.z && pos.z <= hi.z); - } -}; - -struct Ray -{ - Vector from, to; -}; - - -class CNavArea; -class CNavNode; - - -//-------------------------------------------------------------------------------------------------------------- -inline NavDirType OppositeDirection( NavDirType dir ) -{ - switch( dir ) - { - case NORTH: return SOUTH; - case SOUTH: return NORTH; - case EAST: return WEST; - case WEST: return EAST; - default: break; - } - - return NORTH; -} - -//-------------------------------------------------------------------------------------------------------------- -inline NavDirType DirectionLeft( NavDirType dir ) -{ - switch( dir ) - { - case NORTH: return WEST; - case SOUTH: return EAST; - case EAST: return NORTH; - case WEST: return SOUTH; - default: break; - } - - return NORTH; -} - -//-------------------------------------------------------------------------------------------------------------- -inline NavDirType DirectionRight( NavDirType dir ) -{ - switch( dir ) - { - case NORTH: return EAST; - case SOUTH: return WEST; - case EAST: return SOUTH; - case WEST: return NORTH; - default: break; - } - - return NORTH; -} - -//-------------------------------------------------------------------------------------------------------------- -inline void AddDirectionVector( Vector *v, NavDirType dir, float amount ) -{ - switch( dir ) - { - case NORTH: v->y -= amount; return; - case SOUTH: v->y += amount; return; - case EAST: v->x += amount; return; - case WEST: v->x -= amount; return; - default: break; - } -} - -//-------------------------------------------------------------------------------------------------------------- -inline float DirectionToAngle( NavDirType dir ) -{ - switch( dir ) - { - case NORTH: return 270.0f; - case SOUTH: return 90.0f; - case EAST: return 0.0f; - case WEST: return 180.0f; - default: break; - } - - return 0.0f; -} - -//-------------------------------------------------------------------------------------------------------------- -inline NavDirType AngleToDirection( float angle ) -{ - while( angle < 0.0f ) - angle += 360.0f; - - while( angle > 360.0f ) - angle -= 360.0f; - - if (angle < 45 || angle > 315) - return EAST; - - if (angle >= 45 && angle < 135) - return SOUTH; - - if (angle >= 135 && angle < 225) - return WEST; - - return NORTH; -} - -//-------------------------------------------------------------------------------------------------------------- -inline void DirectionToVector2D( NavDirType dir, Vector2D *v ) -{ - switch( dir ) - { - case NORTH: v->x = 0.0f; v->y = -1.0f; break; - case SOUTH: v->x = 0.0f; v->y = 1.0f; break; - case EAST: v->x = 1.0f; v->y = 0.0f; break; - case WEST: v->x = -1.0f; v->y = 0.0f; break; - default: break; - } -} - - -//-------------------------------------------------------------------------------------------------------------- -inline void CornerToVector2D( NavCornerType dir, Vector2D *v ) -{ - switch( dir ) - { - case NORTH_WEST: v->x = -1.0f; v->y = -1.0f; break; - case NORTH_EAST: v->x = 1.0f; v->y = -1.0f; break; - case SOUTH_EAST: v->x = 1.0f; v->y = 1.0f; break; - case SOUTH_WEST: v->x = -1.0f; v->y = 1.0f; break; - default: break; - } - - v->NormalizeInPlace(); -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return true if given entity can be ignored when moving - */ -#define WALK_THRU_DOORS 0x01 -#define WALK_THRU_BREAKABLES 0x02 -#define WALK_THRU_TOGGLE_BRUSHES 0x04 -#define WALK_THRU_EVERYTHING (WALK_THRU_DOORS | WALK_THRU_BREAKABLES | WALK_THRU_TOGGLE_BRUSHES) -inline bool IsEntityWalkable( CBaseEntity *entity, unsigned int flags ) -{ - if (FClassnameIs( entity, "worldspawn" )) - return false; - - if (FClassnameIs( entity, "player" )) - return false; - - // if we hit a door, assume its walkable because it will open when we touch it - if (FClassnameIs( entity, "prop_door*" ) || FClassnameIs( entity, "func_door*" )) - return (flags & WALK_THRU_DOORS) ? true : false; - - // if we hit a clip brush, ignore it if it is not BRUSHSOLID_ALWAYS - if (FClassnameIs( entity, "func_brush" )) - { - CFuncBrush *brush = (CFuncBrush *)entity; - switch ( brush->m_iSolidity ) - { - case CFuncBrush::BRUSHSOLID_ALWAYS: - return false; - case CFuncBrush::BRUSHSOLID_NEVER: - return true; - case CFuncBrush::BRUSHSOLID_TOGGLE: - return (flags & WALK_THRU_TOGGLE_BRUSHES) ? true : false; - } - } - - // if we hit a breakable object, assume its walkable because we will shoot it when we touch it - if (FClassnameIs( entity, "func_breakable" ) && entity->GetHealth() && entity->m_takedamage == DAMAGE_YES) - return (flags & WALK_THRU_BREAKABLES) ? true : false; - - if (FClassnameIs( entity, "func_breakable_surf" ) && entity->m_takedamage == DAMAGE_YES) - return (flags & WALK_THRU_BREAKABLES) ? true : false; - - return false; -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Trace filter that ignores players, NPCs, and objects that can be walked through - */ -class CTraceFilterWalkableEntities : public CTraceFilterNoNPCsOrPlayer -{ -public: - CTraceFilterWalkableEntities( const IHandleEntity *passentity, int collisionGroup, unsigned int flags ) - : CTraceFilterNoNPCsOrPlayer( passentity, collisionGroup ), m_flags( flags ) - { - } - - virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ) - { - if ( CTraceFilterNoNPCsOrPlayer::ShouldHitEntity(pServerEntity, contentsMask) ) - { - CBaseEntity *pEntity = EntityFromEntityHandle( pServerEntity ); - return ( !IsEntityWalkable( pEntity, m_flags ) ); - } - return false; - } - -private: - unsigned int m_flags; -}; - - -extern bool IsWalkableTraceLineClear( Vector &from, Vector &to, unsigned int flags = 0 ); - -#endif // _NAV_H_ diff --git a/game/server/nav_area.cpp b/game/server/nav_area.cpp deleted file mode 100644 index 8602f469f..000000000 --- a/game/server/nav_area.cpp +++ /dev/null @@ -1,3554 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -// nav_area.cpp -// AI Navigation areas -// Author: Michael S. Booth (mike@turtlerockstudios.com), January 2003 - -#include "cbase.h" - -#include "nav_mesh.h" -#include "nav_node.h" -#include "nav_pathfind.h" -#include "nav_colors.h" -#include "fmtstr.h" -#include "props_shared.h" -#include "func_breakablesurf.h" -#include "Color.h" -#include "collisionutils.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include - -#ifdef _WIN32 -#pragma warning (disable:4701) // disable warning that variable *may* not be initialized -#endif - -extern void HintMessageToAllPlayers( const char *message ); - -unsigned int CNavArea::m_nextID = 1; -NavAreaList TheNavAreaList; - -unsigned int CNavArea::m_masterMarker = 1; -CNavArea *CNavArea::m_openList = NULL; - -bool CNavArea::m_isReset = false; - -ConVar nav_coplanar_slope_limit( "nav_coplanar_slope_limit", "0.99", FCVAR_GAMEDLL ); -ConVar nav_split_place_on_ground( "nav_split_place_on_ground", "0", FCVAR_GAMEDLL, "If true, nav areas will be placed flush with the ground when split." ); -ConVar nav_area_bgcolor( "nav_area_bgcolor", "0 0 0 30", FCVAR_GAMEDLL, "RGBA color to draw as the background color for nav areas while editing." ); -ConVar nav_corner_adjust_adjacent( "nav_corner_adjust_adjacent", "18", FCVAR_GAMEDLL, "radius used to raise/lower corners in nearby areas when raising/lowering corners." ); - -//-------------------------------------------------------------------------------------------------------------- -void CNavArea::CompressIDs( void ) -{ - m_nextID = 1; - - FOR_EACH_LL( TheNavAreaList, id ) - { - CNavArea *area = TheNavAreaList[id]; - area->m_id = m_nextID++; - - // remove and re-add the area from the nav mesh to update the hashed ID - TheNavMesh->RemoveNavArea( area ); - TheNavMesh->AddNavArea( area ); - } -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * To keep constructors consistent - */ -void CNavArea::Initialize( void ) -{ - m_marker = 0; - m_parent = NULL; - m_parentHow = GO_NORTH; - m_attributeFlags = 0; - m_place = TheNavMesh->GetNavPlace(); - m_isBlocked = false; - m_isUnderwater = false; - - ResetNodes(); - - int i; - for ( i=0; iGetPosition(); - m_extent.hi = *seNode->GetPosition(); - - m_center.x = (m_extent.lo.x + m_extent.hi.x)/2.0f; - m_center.y = (m_extent.lo.y + m_extent.hi.y)/2.0f; - m_center.z = (m_extent.lo.z + m_extent.hi.z)/2.0f; - - m_neZ = neNode->GetPosition()->z; - m_swZ = swNode->GetPosition()->z; - - m_node[ NORTH_WEST ] = nwNode; - m_node[ NORTH_EAST ] = neNode; - m_node[ SOUTH_EAST ] = seNode; - m_node[ SOUTH_WEST ] = swNode; - - // mark internal nodes as part of this area - AssignNodes( this ); -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Destructor - */ -CNavArea::~CNavArea() -{ - m_spotEncounterList.PurgeAndDeleteElements(); - - // if we are resetting the system, don't bother cleaning up - all areas are being destroyed - if (m_isReset) - return; - - // tell the other areas we are going away - FOR_EACH_LL( TheNavAreaList, it ) - { - CNavArea *area = TheNavAreaList[ it ]; - - if (area == this) - continue; - - area->OnDestroyNotify( this ); - } - - // unhook from ladders - { - FOR_EACH_LL( TheNavMesh->GetLadders(), it ) - { - CNavLadder *ladder = TheNavMesh->GetLadders()[ it ]; - - ladder->OnDestroyNotify( this ); - } - } - - // remove the area from the grid - TheNavMesh->RemoveNavArea( this ); -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * This is invoked at the start of an incremental nav generation on pre-existing areas. - */ -void CNavArea::ResetNodes( void ) -{ - for ( int i=0; im_id, dirName[ dir ] ); -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Connect this area to given ladder - */ -void CNavArea::ConnectTo( CNavLadder *ladder ) -{ - float center = (ladder->m_top.z + ladder->m_bottom.z) * 0.5f; - - Disconnect( ladder ); // just in case - - if ( GetCenter().z > center ) - { - AddLadderDown( ladder ); - } - else - { - AddLadderUp( ladder ); - } -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Disconnect this area from given area - */ -void CNavArea::Disconnect( CNavArea *area ) -{ - NavConnect connect; - connect.area = area; - - for( int dir = 0; dirGetPosition(); - m_extent.hi = *m_node[ SOUTH_EAST ]->GetPosition(); - - m_center.x = (m_extent.lo.x + m_extent.hi.x)/2.0f; - m_center.y = (m_extent.lo.y + m_extent.hi.y)/2.0f; - m_center.z = (m_extent.lo.z + m_extent.hi.z)/2.0f; - - m_neZ = m_node[ NORTH_EAST ]->GetPosition()->z; - m_swZ = m_node[ SOUTH_WEST ]->GetPosition()->z; - - // reassign the adjacent area's internal nodes to the final area - adjArea->AssignNodes( this ); - - // merge adjacency links - we gain all the connections that adjArea had - MergeAdjacentConnections( adjArea ); - - // remove subsumed adjacent area - TheNavAreaList.FindAndRemove( adjArea ); - delete adjArea; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * For merging with "adjArea" - pick up all of "adjArea"s connections - */ -void CNavArea::MergeAdjacentConnections( CNavArea *adjArea ) -{ - // merge adjacency links - we gain all the connections that adjArea had - int dir; - for( dir = 0; dirm_connect[ dir ], it ) - { - NavConnect connect = adjArea->m_connect[ dir ][ it ]; - - if (connect.area != adjArea && connect.area != this) - ConnectTo( connect.area, (NavDirType)dir ); - } - } - - // remove any references from this area to the adjacent area, since it is now part of us - for( dir = 0; dirm_connect[ dir ], cit ) - { - NavConnect connect = area->m_connect[ dir ][ cit ]; - - if (connect.area == adjArea) - { - connected = true; - break; - } - } - - if (connected) - { - // remove all references to adjArea - NavConnect connect; - connect.area = adjArea; - area->m_connect[dir].FindAndRemove( connect ); - - // remove all references to the new area - connect.area = this; - area->m_connect[dir].FindAndRemove( connect ); - - // add a single connection to the new area - connect.area = this; - area->m_connect[dir].AddToTail( connect ); - } - } - } - - // We gain all ladder connections adjArea had - for( dir=0; dirm_ladder[ dir ], it ) - { - ConnectTo( adjArea->m_ladder[ dir ][ it ].ladder ); - } - } - - // All ladders that point to adjArea should point to us now - FOR_EACH_LL( TheNavMesh->GetLadders(), lit ) - { - CNavLadder *ladder = TheNavMesh->GetLadders()[lit]; - - if ( ladder->m_topForwardArea == adjArea ) - ladder->m_topForwardArea = this; - - if ( ladder->m_topRightArea == adjArea ) - ladder->m_topRightArea = this; - - if ( ladder->m_topLeftArea == adjArea ) - ladder->m_topLeftArea = this; - - if ( ladder->m_topBehindArea == adjArea ) - ladder->m_topBehindArea = this; - - if ( ladder->m_bottomArea == adjArea ) - ladder->m_bottomArea = this; - } -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Assign internal nodes to the given area - * NOTE: "internal" nodes do not include the east or south border nodes - */ -void CNavArea::AssignNodes( CNavArea *area ) -{ - CNavNode *horizLast = m_node[ NORTH_EAST ]; - - for( CNavNode *vertNode = m_node[ NORTH_WEST ]; vertNode != m_node[ SOUTH_WEST ]; vertNode = vertNode->GetConnectedNode( SOUTH ) ) - { - for( CNavNode *horizNode = vertNode; horizNode != horizLast; horizNode = horizNode->GetConnectedNode( EAST ) ) - { - horizNode->AssignArea( area ); - } - - horizLast = horizLast->GetConnectedNode( SOUTH ); - } -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Split this area into two areas at the given edge. - * Preserve all adjacency connections. - * NOTE: This does not update node connections, only areas. - */ -bool CNavArea::SplitEdit( bool splitAlongX, float splitEdge, CNavArea **outAlpha, CNavArea **outBeta ) -{ - CNavArea *alpha = NULL; - CNavArea *beta = NULL; - - if (splitAlongX) - { - // +-----+->X - // | A | - // +-----+ - // | B | - // +-----+ - // | - // Y - - // don't do split if at edge of area - if (splitEdge <= m_extent.lo.y + 1.0f) - return false; - - if (splitEdge >= m_extent.hi.y - 1.0f) - return false; - - alpha = new CNavArea; - alpha->m_extent.lo = m_extent.lo; - - alpha->m_extent.hi.x = m_extent.hi.x; - alpha->m_extent.hi.y = splitEdge; - alpha->m_extent.hi.z = GetZ( alpha->m_extent.hi ); - - beta = new CNavArea; - beta->m_extent.lo.x = m_extent.lo.x; - beta->m_extent.lo.y = splitEdge; - beta->m_extent.lo.z = GetZ( beta->m_extent.lo ); - - beta->m_extent.hi = m_extent.hi; - - alpha->ConnectTo( beta, SOUTH ); - beta->ConnectTo( alpha, NORTH ); - - FinishSplitEdit( alpha, SOUTH ); - FinishSplitEdit( beta, NORTH ); - } - else - { - // +--+--+->X - // | | | - // | A|B | - // | | | - // +--+--+ - // | - // Y - - // don't do split if at edge of area - if (splitEdge <= m_extent.lo.x + 1.0f) - return false; - - if (splitEdge >= m_extent.hi.x - 1.0f) - return false; - - alpha = new CNavArea; - alpha->m_extent.lo = m_extent.lo; - - alpha->m_extent.hi.x = splitEdge; - alpha->m_extent.hi.y = m_extent.hi.y; - alpha->m_extent.hi.z = GetZ( alpha->m_extent.hi ); - - beta = new CNavArea; - beta->m_extent.lo.x = splitEdge; - beta->m_extent.lo.y = m_extent.lo.y; - beta->m_extent.lo.z = GetZ( beta->m_extent.lo ); - - beta->m_extent.hi = m_extent.hi; - - alpha->ConnectTo( beta, EAST ); - beta->ConnectTo( alpha, WEST ); - - FinishSplitEdit( alpha, EAST ); - FinishSplitEdit( beta, WEST ); - } - - if ( !TheNavMesh->IsGenerating() && nav_split_place_on_ground.GetBool() ) - { - alpha->PlaceOnGround( NUM_CORNERS ); - beta->PlaceOnGround( NUM_CORNERS ); - } - - // For every ladder we pointed to, alpha or beta should point to it, based on - // their distance to the ladder - int dir; - for( dir=0; dirm_top; // doesn't matter if we choose top or bottom - - float alphaDistance = alpha->GetDistanceSquaredToPoint( ladderPos ); - float betaDistance = beta->GetDistanceSquaredToPoint( ladderPos ); - - if ( alphaDistance < betaDistance ) - { - alpha->ConnectTo( ladder ); - } - else - { - beta->ConnectTo( ladder ); - } - } - } - - // For every ladder that pointed to us, connect that ladder to the closer of alpha and beta - FOR_EACH_LL( TheNavMesh->GetLadders(), lit ) - { - CNavLadder *ladder = TheNavMesh->GetLadders()[lit]; - ladder->OnSplit( this, alpha, beta ); - } - - // new areas inherit attributes from original area - alpha->SetAttributes( GetAttributes() ); - beta->SetAttributes( GetAttributes() ); - - // new areas inherit place from original area - alpha->SetPlace( GetPlace() ); - beta->SetPlace( GetPlace() ); - - // return new areas - if (outAlpha) - *outAlpha = alpha; - - if (outBeta) - *outBeta = beta; - - // remove original area - TheNavAreaList.FindAndRemove( this ); - delete this; - - return true; -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return true if given ladder is connected in given direction - * @todo Formalize "asymmetric" flag on connections - */ -bool CNavArea::IsConnected( const CNavLadder *ladder, CNavLadder::LadderDirectionType dir ) const -{ - FOR_EACH_LL( m_ladder[ dir ], it ) - { - if ( ladder == m_ladder[ dir ][ it ].ladder ) - { - return true; - } - } - - return false; -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return true if given area is connected in given direction - * if dir == NUM_DIRECTIONS, check all directions (direction is unknown) - * @todo Formalize "asymmetric" flag on connections - */ -bool CNavArea::IsConnected( const CNavArea *area, NavDirType dir ) const -{ - // we are connected to ourself - if (area == this) - return true; - - if (dir == NUM_DIRECTIONS) - { - // search all directions - for( int d=0; dm_topBehindArea == area || - ladder->m_topForwardArea == area || - ladder->m_topLeftArea == area || - ladder->m_topRightArea == area) - return true; - } - - FOR_EACH_LL( m_ladder[ CNavLadder::LADDER_DOWN ], dit ) - { - CNavLadder *ladder = m_ladder[ CNavLadder::LADDER_DOWN ][ dit ].ladder; - - if (ladder->m_bottomArea == area) - return true; - } - } - else - { - // check specific direction - FOR_EACH_LL( m_connect[ dir ], it ) - { - if (area == m_connect[ dir ][ it ].area) - return true; - } - } - - return false; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Compute change in height from this area to given area - * @todo This is approximate for now - */ -float CNavArea::ComputeHeightChange( const CNavArea *area ) -{ - float ourZ = GetZ( GetCenter() ); - float areaZ = area->GetZ( area->GetCenter() ); - - return areaZ - ourZ; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Given the portion of the original area, update its internal data - * The "ignoreEdge" direction defines the side of the original area that the new area does not include - */ -void CNavArea::FinishSplitEdit( CNavArea *newArea, NavDirType ignoreEdge ) -{ - newArea->m_center.x = (newArea->m_extent.lo.x + newArea->m_extent.hi.x)/2.0f; - newArea->m_center.y = (newArea->m_extent.lo.y + newArea->m_extent.hi.y)/2.0f; - newArea->m_center.z = (newArea->m_extent.lo.z + newArea->m_extent.hi.z)/2.0f; - - newArea->m_neZ = GetZ( newArea->m_extent.hi.x, newArea->m_extent.lo.y ); - newArea->m_swZ = GetZ( newArea->m_extent.lo.x, newArea->m_extent.hi.y ); - - // connect to adjacent areas - for( int d=0; dIsOverlappingX( adj )) - { - newArea->ConnectTo( adj, (NavDirType)d ); - - // add reciprocal connection if needed - if (adj->IsConnected( this, OppositeDirection( (NavDirType)d ))) - adj->ConnectTo( newArea, OppositeDirection( (NavDirType)d ) ); - } - break; - - case EAST: - case WEST: - if (newArea->IsOverlappingY( adj )) - { - newArea->ConnectTo( adj, (NavDirType)d ); - - // add reciprocal connection if needed - if (adj->IsConnected( this, OppositeDirection( (NavDirType)d ))) - adj->ConnectTo( newArea, OppositeDirection( (NavDirType)d ) ); - } - break; - } - } - } - - TheNavAreaList.AddToTail( newArea ); - TheNavMesh->AddNavArea( newArea ); - - // Assign nodes - if ( HasNodes() ) - { - // first give it all our nodes... - newArea->m_node[ NORTH_WEST ] = m_node[ NORTH_WEST ]; - newArea->m_node[ NORTH_EAST ] = m_node[ NORTH_EAST ]; - newArea->m_node[ SOUTH_EAST ] = m_node[ SOUTH_EAST ]; - newArea->m_node[ SOUTH_WEST ] = m_node[ SOUTH_WEST ]; - - // ... then pull in one edge... - NavDirType dir = NUM_DIRECTIONS; - NavCornerType corner[2] = { NUM_CORNERS, NUM_CORNERS }; - - switch ( ignoreEdge ) - { - case NORTH: - dir = SOUTH; - corner[0] = NORTH_WEST; - corner[1] = NORTH_EAST; - break; - case SOUTH: - dir = NORTH; - corner[0] = SOUTH_WEST; - corner[1] = SOUTH_EAST; - break; - case EAST: - dir = WEST; - corner[0] = NORTH_EAST; - corner[1] = SOUTH_EAST; - break; - case WEST: - dir = EAST; - corner[0] = NORTH_WEST; - corner[1] = SOUTH_WEST; - break; - default: - break; - } - - while ( !newArea->IsOverlapping( *newArea->m_node[ corner[0] ]->GetPosition(), GenerationStepSize/2 ) ) - { - for ( int i=0; i<2; ++i ) - { - Assert( newArea->m_node[ corner[i] ] ); - Assert( newArea->m_node[ corner[i] ]->GetConnectedNode( dir ) ); - newArea->m_node[ corner[i] ] = newArea->m_node[ corner[i] ]->GetConnectedNode( dir ); - } - } - - // assign internal nodes... - newArea->AssignNodes( newArea ); - - // ... and grab the node heights for our corner heights. - newArea->m_neZ = newArea->m_node[ NORTH_EAST ]->GetPosition()->z; - newArea->m_extent.lo.z = newArea->m_node[ NORTH_WEST ]->GetPosition()->z; - newArea->m_swZ = newArea->m_node[ SOUTH_WEST ]->GetPosition()->z; - newArea->m_extent.hi.z = newArea->m_node[ SOUTH_EAST ]->GetPosition()->z; - } -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Create a new area between this area and given area - */ -bool CNavArea::SpliceEdit( CNavArea *other ) -{ - CNavArea *newArea = NULL; - Vector nw, ne, se, sw; - - if (m_extent.lo.x > other->m_extent.hi.x) - { - // 'this' is east of 'other' - float top = MAX( m_extent.lo.y, other->m_extent.lo.y ); - float bottom = MIN( m_extent.hi.y, other->m_extent.hi.y ); - - nw.x = other->m_extent.hi.x; - nw.y = top; - nw.z = other->GetZ( nw ); - - se.x = m_extent.lo.x; - se.y = bottom; - se.z = GetZ( se ); - - ne.x = se.x; - ne.y = nw.y; - ne.z = GetZ( ne ); - - sw.x = nw.x; - sw.y = se.y; - sw.z = other->GetZ( sw ); - - newArea = new CNavArea( nw, ne, se, sw ); - - this->ConnectTo( newArea, WEST ); - newArea->ConnectTo( this, EAST ); - - other->ConnectTo( newArea, EAST ); - newArea->ConnectTo( other, WEST ); - } - else if (m_extent.hi.x < other->m_extent.lo.x) - { - // 'this' is west of 'other' - float top = MAX( m_extent.lo.y, other->m_extent.lo.y ); - float bottom = MIN( m_extent.hi.y, other->m_extent.hi.y ); - - nw.x = m_extent.hi.x; - nw.y = top; - nw.z = GetZ( nw ); - - se.x = other->m_extent.lo.x; - se.y = bottom; - se.z = other->GetZ( se ); - - ne.x = se.x; - ne.y = nw.y; - ne.z = other->GetZ( ne ); - - sw.x = nw.x; - sw.y = se.y; - sw.z = GetZ( sw ); - - newArea = new CNavArea( nw, ne, se, sw ); - - this->ConnectTo( newArea, EAST ); - newArea->ConnectTo( this, WEST ); - - other->ConnectTo( newArea, WEST ); - newArea->ConnectTo( other, EAST ); - } - else // 'this' overlaps in X - { - if (m_extent.lo.y > other->m_extent.hi.y) - { - // 'this' is south of 'other' - float left = MAX( m_extent.lo.x, other->m_extent.lo.x ); - float right = MIN( m_extent.hi.x, other->m_extent.hi.x ); - - nw.x = left; - nw.y = other->m_extent.hi.y; - nw.z = other->GetZ( nw ); - - se.x = right; - se.y = m_extent.lo.y; - se.z = GetZ( se ); - - ne.x = se.x; - ne.y = nw.y; - ne.z = other->GetZ( ne ); - - sw.x = nw.x; - sw.y = se.y; - sw.z = GetZ( sw ); - - newArea = new CNavArea( nw, ne, se, sw ); - - this->ConnectTo( newArea, NORTH ); - newArea->ConnectTo( this, SOUTH ); - - other->ConnectTo( newArea, SOUTH ); - newArea->ConnectTo( other, NORTH ); - } - else if (m_extent.hi.y < other->m_extent.lo.y) - { - // 'this' is north of 'other' - float left = MAX( m_extent.lo.x, other->m_extent.lo.x ); - float right = MIN( m_extent.hi.x, other->m_extent.hi.x ); - - nw.x = left; - nw.y = m_extent.hi.y; - nw.z = GetZ( nw ); - - se.x = right; - se.y = other->m_extent.lo.y; - se.z = other->GetZ( se ); - - ne.x = se.x; - ne.y = nw.y; - ne.z = GetZ( ne ); - - sw.x = nw.x; - sw.y = se.y; - sw.z = other->GetZ( sw ); - - newArea = new CNavArea( nw, ne, se, sw ); - - this->ConnectTo( newArea, SOUTH ); - newArea->ConnectTo( this, NORTH ); - - other->ConnectTo( newArea, NORTH ); - newArea->ConnectTo( other, SOUTH ); - } - else - { - // areas overlap - return false; - } - } - - // if both areas have the same place, the new area inherits it - if (GetPlace() == other->GetPlace()) - { - newArea->SetPlace( GetPlace() ); - } - else if (GetPlace() == UNDEFINED_PLACE) - { - newArea->SetPlace( other->GetPlace() ); - } - else if (other->GetPlace() == UNDEFINED_PLACE) - { - newArea->SetPlace( GetPlace() ); - } - else - { - // both have valid, but different places - pick on at random - if (RandomInt( 0, 100 ) < 50) - newArea->SetPlace( GetPlace() ); - else - newArea->SetPlace( other->GetPlace() ); - } - - TheNavAreaList.AddToTail( newArea ); - TheNavMesh->AddNavArea( newArea ); - - return true; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Merge this area and given adjacent area - */ -bool CNavArea::MergeEdit( CNavArea *adj ) -{ - // can only merge if attributes of both areas match - - - // check that these areas can be merged - const float tolerance = 1.0f; - bool merge = false; - if (fabs( m_extent.lo.x - adj->m_extent.lo.x ) < tolerance && - fabs( m_extent.hi.x - adj->m_extent.hi.x ) < tolerance) - merge = true; - - if (fabs( m_extent.lo.y - adj->m_extent.lo.y ) < tolerance && - fabs( m_extent.hi.y - adj->m_extent.hi.y ) < tolerance) - merge = true; - - if (merge == false) - return false; - - Extent origExtent = m_extent; - - // update extent - if (m_extent.lo.x > adj->m_extent.lo.x || m_extent.lo.y > adj->m_extent.lo.y) - m_extent.lo = adj->m_extent.lo; - - if (m_extent.hi.x < adj->m_extent.hi.x || m_extent.hi.y < adj->m_extent.hi.y) - m_extent.hi = adj->m_extent.hi; - - m_center.x = (m_extent.lo.x + m_extent.hi.x)/2.0f; - m_center.y = (m_extent.lo.y + m_extent.hi.y)/2.0f; - m_center.z = (m_extent.lo.z + m_extent.hi.z)/2.0f; - - if (m_extent.hi.x > origExtent.hi.x || m_extent.lo.y < origExtent.lo.y) - m_neZ = adj->GetZ( m_extent.hi.x, m_extent.lo.y ); - else - m_neZ = GetZ( m_extent.hi.x, m_extent.lo.y ); - - if (m_extent.lo.x < origExtent.lo.x || m_extent.hi.y > origExtent.hi.y) - m_swZ = adj->GetZ( m_extent.lo.x, m_extent.hi.y ); - else - m_swZ = GetZ( m_extent.lo.x, m_extent.hi.y ); - - // merge adjacency links - we gain all the connections that adjArea had - MergeAdjacentConnections( adj ); - - // remove subsumed adjacent area - TheNavAreaList.FindAndRemove( adj ); - delete adj; - - return true; -} - -//-------------------------------------------------------------------------------------------------------------- -void ApproachAreaAnalysisPrep( void ) -{ -} - -//-------------------------------------------------------------------------------------------------------------- -void CleanupApproachAreaAnalysisPrep( void ) -{ -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Remove "analyzed" data from nav area - */ -void CNavArea::Strip( void ) -{ - m_approachCount = 0; - m_spotEncounterList.PurgeAndDeleteElements(); // this calls delete on each element -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return true if area is more or less square. - * This is used when merging to prevent long, thin, areas being created. - */ -bool CNavArea::IsRoughlySquare( void ) const -{ - float aspect = GetSizeX() / GetSizeY(); - - const float maxAspect = 3.01; - const float minAspect = 1.0f / maxAspect; - if (aspect < minAspect || aspect > maxAspect) - return false; - - return true; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return true if 'pos' is within 2D extents of area. - */ -bool CNavArea::IsOverlapping( const Vector &pos, float tolerance ) const -{ - if (pos.x + tolerance >= m_extent.lo.x && pos.x - tolerance <= m_extent.hi.x && - pos.y + tolerance >= m_extent.lo.y && pos.y - tolerance <= m_extent.hi.y) - return true; - - return false; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return true if 'area' overlaps our 2D extents - */ -bool CNavArea::IsOverlapping( const CNavArea *area ) const -{ - if (area->m_extent.lo.x < m_extent.hi.x && area->m_extent.hi.x > m_extent.lo.x && - area->m_extent.lo.y < m_extent.hi.y && area->m_extent.hi.y > m_extent.lo.y) - return true; - - return false; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return true if 'area' overlaps our X extent - */ -bool CNavArea::IsOverlappingX( const CNavArea *area ) const -{ - if (area->m_extent.lo.x < m_extent.hi.x && area->m_extent.hi.x > m_extent.lo.x) - return true; - - return false; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return true if 'area' overlaps our Y extent - */ -bool CNavArea::IsOverlappingY( const CNavArea *area ) const -{ - if (area->m_extent.lo.y < m_extent.hi.y && area->m_extent.hi.y > m_extent.lo.y) - return true; - - return false; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return true if given point is on or above this area, but no others - */ -bool CNavArea::Contains( const Vector &pos ) const -{ - // check 2D overlap - if (!IsOverlapping( pos )) - return false; - - // the point overlaps us, check that it is above us, but not above any areas that overlap us - float myZ = GetZ( pos ); - - // if the nav area is above the given position, fail - if (myZ > pos.z) - return false; - - FOR_EACH_LL( m_overlapList, it ) - { - const CNavArea *area = m_overlapList[ it ]; - - // skip self - if (area == this) - continue; - - // check 2D overlap - if (!area->IsOverlapping( pos )) - continue; - - float theirZ = area->GetZ( pos ); - if (theirZ > pos.z) - { - // they are above the point - continue; - } - - if (theirZ > myZ) - { - // we are below an area that is beneath the given position - return false; - } - } - - return true; -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavArea::ComputeNormal( Vector *normal, bool alternate ) const -{ - if ( !normal ) - return; - - Vector u, v; - - if ( !alternate ) - { - u.x = m_extent.hi.x - m_extent.lo.x; - u.y = 0.0f; - u.z = m_neZ - m_extent.lo.z; - - v.x = 0.0f; - v.y = m_extent.hi.y - m_extent.lo.y; - v.z = m_swZ - m_extent.lo.z; - } - else - { - u.x = m_extent.lo.x - m_extent.hi.x; - u.y = 0.0f; - u.z = m_swZ - m_extent.hi.z; - - v.x = 0.0f; - v.y = m_extent.lo.y - m_extent.hi.y; - v.z = m_neZ - m_extent.hi.z; - } - - *normal = CrossProduct( u, v ); - normal->NormalizeInPlace(); -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return true if the area is approximately flat, using normals computed from opposite corners - */ -bool CNavArea::IsFlat( void ) const -{ - Vector normal, otherNormal; - ComputeNormal( &normal ); - ComputeNormal( &otherNormal, true ); - - const float tolerance = nav_coplanar_slope_limit.GetFloat(); - if (DotProduct( normal, otherNormal ) > tolerance) - return true; - - return false; -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return true if this area and given area are approximately co-planar - */ -bool CNavArea::IsCoplanar( const CNavArea *area ) const -{ - Vector u, v; - - if ( !IsFlat() ) - return false; - - if ( !area->IsFlat() ) - return false; - - // compute our unit surface normal - Vector normal, otherNormal; - ComputeNormal( &normal ); - area->ComputeNormal( &otherNormal ); - - // can only merge areas that are nearly planar, to ensure areas do not differ from underlying geometry much - const float tolerance = nav_coplanar_slope_limit.GetFloat(); //0.99f; // 0.7071f; // 0.9 - if (DotProduct( normal, otherNormal ) > tolerance) - return true; - - return false; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return Z of area at (x,y) of 'pos' - * Trilinear interpolation of Z values at quad edges. - * NOTE: pos->z is not used. - */ -float CNavArea::GetZ( const Vector &pos ) const -{ - float dx = m_extent.hi.x - m_extent.lo.x; - float dy = m_extent.hi.y - m_extent.lo.y; - - // guard against division by zero due to degenerate areas - if (dx == 0.0f || dy == 0.0f) - return m_neZ; - - float u = (pos.x - m_extent.lo.x) / dx; - float v = (pos.y - m_extent.lo.y) / dy; - - // clamp Z values to (x,y) volume - if (u < 0.0f) - u = 0.0f; - else if (u > 1.0f) - u = 1.0f; - - if (v < 0.0f) - v = 0.0f; - else if (v > 1.0f) - v = 1.0f; - - float northZ = m_extent.lo.z + u * (m_neZ - m_extent.lo.z); - float southZ = m_swZ + u * (m_extent.hi.z - m_swZ); - - return northZ + v * (southZ - northZ); -} - -float CNavArea::GetZ( float x, float y ) const -{ - Vector pos( x, y, 0.0f ); - return GetZ( pos ); -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return closest point to 'pos' on 'area'. - * Returned point is in 'close'. - */ -void CNavArea::GetClosestPointOnArea( const Vector &pos, Vector *close ) const -{ - const Extent &extent = GetExtent(); - - if (pos.x < extent.lo.x) - { - if (pos.y < extent.lo.y) - { - // position is north-west of area - *close = extent.lo; - } - else if (pos.y > extent.hi.y) - { - // position is south-west of area - close->x = extent.lo.x; - close->y = extent.hi.y; - } - else - { - // position is west of area - close->x = extent.lo.x; - close->y = pos.y; - } - } - else if (pos.x > extent.hi.x) - { - if (pos.y < extent.lo.y) - { - // position is north-east of area - close->x = extent.hi.x; - close->y = extent.lo.y; - } - else if (pos.y > extent.hi.y) - { - // position is south-east of area - *close = extent.hi; - } - else - { - // position is east of area - close->x = extent.hi.x; - close->y = pos.y; - } - } - else if (pos.y < extent.lo.y) - { - // position is north of area - close->x = pos.x; - close->y = extent.lo.y; - } - else if (pos.y > extent.hi.y) - { - // position is south of area - close->x = pos.x; - close->y = extent.hi.y; - } - else - { - // position is inside of area - it is the 'closest point' to itself - *close = pos; - } - - close->z = GetZ( *close ); -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return shortest distance squared between point and this area - */ -float CNavArea::GetDistanceSquaredToPoint( const Vector &pos ) const -{ - const Extent &extent = GetExtent(); - - if (pos.x < extent.lo.x) - { - if (pos.y < extent.lo.y) - { - // position is north-west of area - return (extent.lo - pos).LengthSqr(); - } - else if (pos.y > extent.hi.y) - { - // position is south-west of area - Vector d; - d.x = extent.lo.x - pos.x; - d.y = extent.hi.y - pos.y; - d.z = m_swZ - pos.z; - return d.LengthSqr(); - } - else - { - // position is west of area - float d = extent.lo.x - pos.x; - return d * d; - } - } - else if (pos.x > extent.hi.x) - { - if (pos.y < extent.lo.y) - { - // position is north-east of area - Vector d; - d.x = extent.hi.x - pos.x; - d.y = extent.lo.y - pos.y; - d.z = m_neZ - pos.z; - return d.LengthSqr(); - } - else if (pos.y > extent.hi.y) - { - // position is south-east of area - return (extent.hi - pos).LengthSqr(); - } - else - { - // position is east of area - float d = pos.z - extent.hi.x; - return d * d; - } - } - else if (pos.y < extent.lo.y) - { - // position is north of area - float d = extent.lo.y - pos.y; - return d * d; - } - else if (pos.y > extent.hi.y) - { - // position is south of area - float d = pos.y - extent.hi.y; - return d * d; - } - else - { - // position is inside of 2D extent of area - find delta Z - float z = GetZ( pos ); - float d = z - pos.z; - return d * d; - } -} - - - -//-------------------------------------------------------------------------------------------------------------- -CNavArea *CNavArea::GetRandomAdjacentArea( NavDirType dir ) const -{ - int count = m_connect[ dir ].Count(); - int which = RandomInt( 0, count-1 ); - - int i = 0; - FOR_EACH_LL( m_connect[ dir ], it ) - { - if (i == which) - return m_connect[ dir ][ it ].area; - - ++i; - } - - return NULL; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Compute "portal" between to adjacent areas. - * Return center of portal opening, and half-width defining sides of portal from center. - * NOTE: center->z is unset. - */ -void CNavArea::ComputePortal( const CNavArea *to, NavDirType dir, Vector *center, float *halfWidth ) const -{ - if (dir == NORTH || dir == SOUTH) - { - if (dir == NORTH) - center->y = m_extent.lo.y; - else - center->y = m_extent.hi.y; - - float left = MAX( m_extent.lo.x, to->m_extent.lo.x ); - float right = MIN( m_extent.hi.x, to->m_extent.hi.x ); - - // clamp to our extent in case areas are disjoint - if (left < m_extent.lo.x) - left = m_extent.lo.x; - else if (left > m_extent.hi.x) - left = m_extent.hi.x; - - if (right < m_extent.lo.x) - right = m_extent.lo.x; - else if (right > m_extent.hi.x) - right = m_extent.hi.x; - - center->x = (left + right)/2.0f; - *halfWidth = (right - left)/2.0f; - } - else // EAST or WEST - { - if (dir == WEST) - center->x = m_extent.lo.x; - else - center->x = m_extent.hi.x; - - float top = MAX( m_extent.lo.y, to->m_extent.lo.y ); - float bottom = MIN( m_extent.hi.y, to->m_extent.hi.y ); - - // clamp to our extent in case areas are disjoint - if (top < m_extent.lo.y) - top = m_extent.lo.y; - else if (top > m_extent.hi.y) - top = m_extent.hi.y; - - if (bottom < m_extent.lo.y) - bottom = m_extent.lo.y; - else if (bottom > m_extent.hi.y) - bottom = m_extent.hi.y; - - center->y = (top + bottom)/2.0f; - *halfWidth = (bottom - top)/2.0f; - } -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Compute closest point within the "portal" between to adjacent areas. - */ -void CNavArea::ComputeClosestPointInPortal( const CNavArea *to, NavDirType dir, const Vector &fromPos, Vector *closePos ) const -{ - const float margin = GenerationStepSize/2.0f; - - if (dir == NORTH || dir == SOUTH) - { - if (dir == NORTH) - closePos->y = m_extent.lo.y; - else - closePos->y = m_extent.hi.y; - - float left = MAX( m_extent.lo.x, to->m_extent.lo.x ); - float right = MIN( m_extent.hi.x, to->m_extent.hi.x ); - - // clamp to our extent in case areas are disjoint - if (left < m_extent.lo.x) - left = m_extent.lo.x; - else if (left > m_extent.hi.x) - left = m_extent.hi.x; - - if (right < m_extent.lo.x) - right = m_extent.lo.x; - else if (right > m_extent.hi.x) - right = m_extent.hi.x; - - // keep margin if against edge - const float leftMargin = (to->IsEdge( WEST )) ? (left + margin) : left; - const float rightMargin = (to->IsEdge( EAST )) ? (right - margin) : right; - - // limit x to within portal - if (fromPos.x < leftMargin) - closePos->x = leftMargin; - else if (fromPos.x > rightMargin) - closePos->x = rightMargin; - else - closePos->x = fromPos.x; - - } - else // EAST or WEST - { - if (dir == WEST) - closePos->x = m_extent.lo.x; - else - closePos->x = m_extent.hi.x; - - float top = MAX( m_extent.lo.y, to->m_extent.lo.y ); - float bottom = MIN( m_extent.hi.y, to->m_extent.hi.y ); - - // clamp to our extent in case areas are disjoint - if (top < m_extent.lo.y) - top = m_extent.lo.y; - else if (top > m_extent.hi.y) - top = m_extent.hi.y; - - if (bottom < m_extent.lo.y) - bottom = m_extent.lo.y; - else if (bottom > m_extent.hi.y) - bottom = m_extent.hi.y; - - // keep margin if against edge - const float topMargin = (to->IsEdge( NORTH )) ? (top + margin) : top; - const float bottomMargin = (to->IsEdge( SOUTH )) ? (bottom - margin) : bottom; - - // limit y to within portal - if (fromPos.y < topMargin) - closePos->y = topMargin; - else if (fromPos.y > bottomMargin) - closePos->y = bottomMargin; - else - closePos->y = fromPos.y; - } -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return true if there are no bi-directional links on the given side - */ -bool CNavArea::IsEdge( NavDirType dir ) const -{ - FOR_EACH_LL( m_connect[ dir ], it ) - { - const NavConnect connect = m_connect[ dir ][ it ]; - - if (connect.area->IsConnected( this, OppositeDirection( dir ) )) - return false; - } - - return true; -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return direction from this area to the given point - */ -NavDirType CNavArea::ComputeDirection( Vector *point ) const -{ - if (point->x >= m_extent.lo.x && point->x <= m_extent.hi.x) - { - if (point->y < m_extent.lo.y) - return NORTH; - else if (point->y > m_extent.hi.y) - return SOUTH; - } - else if (point->y >= m_extent.lo.y && point->y <= m_extent.hi.y) - { - if (point->x < m_extent.lo.x) - return WEST; - else if (point->x > m_extent.hi.x) - return EAST; - } - - // find closest direction - Vector to = *point - m_center; - - if (fabs(to.x) > fabs(to.y)) - { - if (to.x > 0.0f) - return EAST; - return WEST; - } - else - { - if (to.y > 0.0f) - return SOUTH; - return NORTH; - } - - return NUM_DIRECTIONS; -} - - -//-------------------------------------------------------------------------------------------------------------- -bool CNavArea::GetCornerHotspot( NavCornerType corner, Vector hotspot[NUM_CORNERS] ) const -{ - Vector nw = GetCorner( NORTH_WEST ); - Vector ne = GetCorner( NORTH_EAST ); - Vector sw = GetCorner( SOUTH_WEST ); - Vector se = GetCorner( SOUTH_EAST ); - - float size = 9.0f; - size = MIN( size, GetSizeX()/3 ); // make sure the hotspot doesn't extend outside small areas - size = MIN( size, GetSizeY()/3 ); - - switch ( corner ) - { - case NORTH_WEST: - hotspot[0] = nw; - hotspot[1] = hotspot[0] + Vector( size, 0, 0 ); - hotspot[2] = hotspot[0] + Vector( size, size, 0 ); - hotspot[3] = hotspot[0] + Vector( 0, size, 0 ); - break; - case NORTH_EAST: - hotspot[0] = ne; - hotspot[1] = hotspot[0] + Vector( -size, 0, 0 ); - hotspot[2] = hotspot[0] + Vector( -size, size, 0 ); - hotspot[3] = hotspot[0] + Vector( 0, size, 0 ); - break; - case SOUTH_WEST: - hotspot[0] = sw; - hotspot[1] = hotspot[0] + Vector( size, 0, 0 ); - hotspot[2] = hotspot[0] + Vector( size, -size, 0 ); - hotspot[3] = hotspot[0] + Vector( 0, -size, 0 ); - break; - case SOUTH_EAST: - hotspot[0] = se; - hotspot[1] = hotspot[0] + Vector( -size, 0, 0 ); - hotspot[2] = hotspot[0] + Vector( -size, -size, 0 ); - hotspot[3] = hotspot[0] + Vector( 0, -size, 0 ); - break; - default: - return false; - } - - for ( int i=1; iGetEditVectors( &eyePos, &eyeForward ); - - Ray_t ray; - ray.Init( eyePos, eyePos + 10000.0f * eyeForward, vec3_origin, vec3_origin ); - - float dist = IntersectRayWithTriangle( ray, hotspot[0], hotspot[1], hotspot[2], false ); - if ( dist > 0 ) - { - return true; - } - - dist = IntersectRayWithTriangle( ray, hotspot[2], hotspot[3], hotspot[0], false ); - if ( dist > 0 ) - { - return true; - } - - return false; -} - - -//-------------------------------------------------------------------------------------------------------------- -NavCornerType CNavArea::GetCornerUnderCursor( void ) const -{ - Vector eyePos, eyeForward; - TheNavMesh->GetEditVectors( &eyePos, &eyeForward ); - - for ( int i=0; iIsPlaceMode() ) - { - useAttributeColors = false; - - if ( m_place == UNDEFINED_PLACE ) - { - color = NavNoPlaceColor; - } - else if ( TheNavMesh->GetNavPlace() == m_place ) - { - color = NavSamePlaceColor; - } - else - { - color = NavDifferentPlaceColor; - } - } - else - { - // normal edit mode - if ( this == TheNavMesh->GetMarkedArea() ) - { - useAttributeColors = false; - color = NavMarkedColor; - } - else if ( this == TheNavMesh->GetSelectedArea() ) - { - color = NavSelectedColor; - } - else if ( m_isBlocked ) - { - color = NavBlockedColor; - } - else - { - color = NavNormalColor; - } - } - - if ( IsDegenerate() ) - { - static IntervalTimer blink; - static bool blinkOn = false; - - if (blink.GetElapsedTime() > 1.0f) - { - blink.Reset(); - blinkOn = !blinkOn; - } - - useAttributeColors = false; - - if (blinkOn) - color = NavDegenerateFirstColor; - else - color = NavDegenerateSecondColor; - - NDebugOverlay::Text( GetCenter(), UTIL_VarArgs( "Degenerate area %d", GetID() ), true, 0.1f ); - } - - Vector nw, ne, sw, se; - - nw = m_extent.lo; - se = m_extent.hi; - ne.x = se.x; - ne.y = nw.y; - ne.z = m_neZ; - sw.x = nw.x; - sw.y = se.y; - sw.z = m_swZ; - - int bgcolor[4]; - if ( 4 == sscanf( nav_area_bgcolor.GetString(), "%d %d %d %d", &(bgcolor[0]), &(bgcolor[1]), &(bgcolor[2]), &(bgcolor[3]) ) ) - { - for ( int i=0; i<4; ++i ) - bgcolor[i] = clamp( bgcolor[i], 0, 255 ); - - if ( bgcolor[3] > 0 ) - { - const Vector offset( 0, 0, 0.8f ); - NDebugOverlay::Triangle( nw+offset, se+offset, ne+offset, bgcolor[0], bgcolor[1], bgcolor[2], bgcolor[3], true, 0.15f ); - NDebugOverlay::Triangle( se+offset, nw+offset, sw+offset, bgcolor[0], bgcolor[1], bgcolor[2], bgcolor[3], true, 0.15f ); - } - } - - const float inset = 0.2f; - nw.x += inset; - nw.y += inset; - ne.x -= inset; - ne.y += inset; - sw.x += inset; - sw.y -= inset; - se.x -= inset; - se.y -= inset; - - if ( GetAttributes() & NAV_MESH_TRANSIENT ) - { - NavDrawDashedLine( nw, ne, color ); - NavDrawDashedLine( ne, se, color ); - NavDrawDashedLine( se, sw, color ); - NavDrawDashedLine( sw, nw, color ); - } - else - { - NavDrawLine( nw, ne, color ); - NavDrawLine( ne, se, color ); - NavDrawLine( se, sw, color ); - NavDrawLine( sw, nw, color ); - } - - if ( this == TheNavMesh->GetMarkedArea() && TheNavMesh->m_markedCorner != NUM_CORNERS ) - { - Vector p[NUM_CORNERS]; - GetCornerHotspot( TheNavMesh->m_markedCorner, p ); - - NavDrawLine( p[1], p[2], NavMarkedColor ); - NavDrawLine( p[2], p[3], NavMarkedColor ); - } - if ( this != TheNavMesh->GetMarkedArea() && this == TheNavMesh->GetSelectedArea() && TheNavMesh->m_navEditMode == CNavMesh::NAV_EDIT_NORMAL ) - { - NavCornerType bestCorner = GetCornerUnderCursor(); - - Vector p[NUM_CORNERS]; - GetCornerHotspot( bestCorner, p ); - - NavDrawLine( p[1], p[2], NavSelectedColor ); - NavDrawLine( p[2], p[3], NavSelectedColor ); - } - - if (GetAttributes() & NAV_MESH_CROUCH) - { - if ( useAttributeColors ) - color = NavAttributeCrouchColor; - - NavDrawLine( nw, se, color ); - } - - if (GetAttributes() & NAV_MESH_JUMP) - { - if ( useAttributeColors ) - color = NavAttributeJumpColor; - - if ( !(GetAttributes() & NAV_MESH_CROUCH) ) - { - NavDrawLine( nw, se, color ); - } - NavDrawLine( ne, sw, color ); - } - - if (GetAttributes() & NAV_MESH_PRECISE) - { - if ( useAttributeColors ) - color = NavAttributePreciseColor; - - float size = 8.0f; - Vector up( m_center.x, m_center.y - size, m_center.z ); - Vector down( m_center.x, m_center.y + size, m_center.z ); - NavDrawLine( up, down, color ); - - Vector left( m_center.x - size, m_center.y, m_center.z ); - Vector right( m_center.x + size, m_center.y, m_center.z ); - NavDrawLine( left, right, color ); - } - - if (GetAttributes() & NAV_MESH_NO_JUMP) - { - if ( useAttributeColors ) - color = NavAttributeNoJumpColor; - - float size = 8.0f; - Vector up( m_center.x, m_center.y - size, m_center.z ); - Vector down( m_center.x, m_center.y + size, m_center.z ); - Vector left( m_center.x - size, m_center.y, m_center.z ); - Vector right( m_center.x + size, m_center.y, m_center.z ); - NavDrawLine( up, right, color ); - NavDrawLine( right, down, color ); - NavDrawLine( down, left, color ); - NavDrawLine( left, up, color ); - } - - // Stop is represented by an octogon - if (GetAttributes() & NAV_MESH_STOP) - { - if ( useAttributeColors ) - color = NavAttributeStopColor; - - float dist = 8.0f; - float length = dist/2.5f; - Vector start, end; - - start = m_center + Vector( dist, -length, 0 ); - end = m_center + Vector( dist, length, 0 ); - NavDrawLine( start, end, color ); - - start = m_center + Vector( dist, length, 0 ); - end = m_center + Vector( length, dist, 0 ); - NavDrawLine( start, end, color ); - - start = m_center + Vector( -dist, -length, 0 ); - end = m_center + Vector( -dist, length, 0 ); - NavDrawLine( start, end, color ); - - start = m_center + Vector( -dist, length, 0 ); - end = m_center + Vector( -length, dist, 0 ); - NavDrawLine( start, end, color ); - - start = m_center + Vector( -length, dist, 0 ); - end = m_center + Vector( length, dist, 0 ); - NavDrawLine( start, end, color ); - - start = m_center + Vector( -dist, -length, 0 ); - end = m_center + Vector( -length, -dist, 0 ); - NavDrawLine( start, end, color ); - - start = m_center + Vector( -length, -dist, 0 ); - end = m_center + Vector( length, -dist, 0 ); - NavDrawLine( start, end, color ); - - start = m_center + Vector( length, -dist, 0 ); - end = m_center + Vector( dist, -length, 0 ); - NavDrawLine( start, end, color ); - } - - // Walk is represented by an arrow - if (GetAttributes() & NAV_MESH_WALK) - { - if ( useAttributeColors ) - color = NavAttributeWalkColor; - - float size = 8.0f; - NavDrawHorizontalArrow( m_center + Vector( -size, 0, 0 ), m_center + Vector( size, 0, 0 ), 4, color ); - } - - // Walk is represented by a double arrow - if (GetAttributes() & NAV_MESH_RUN) - { - if ( useAttributeColors ) - color = NavAttributeRunColor; - - float size = 8.0f; - float dist = 4.0f; - NavDrawHorizontalArrow( m_center + Vector( -size, dist, 0 ), m_center + Vector( size, dist, 0 ), 4, color ); - NavDrawHorizontalArrow( m_center + Vector( -size, -dist, 0 ), m_center + Vector( size, -dist, 0 ), 4, color ); - } - - // Avoid is represented by an exclamation point - if (GetAttributes() & NAV_MESH_AVOID) - { - if ( useAttributeColors ) - color = NavAttributeAvoidColor; - - float topHeight = 8.0f; - float topWidth = 3.0f; - float bottomHeight = 3.0f; - float bottomWidth = 2.0f; - NavDrawTriangle( m_center, m_center + Vector( -topWidth, topHeight, 0 ), m_center + Vector( +topWidth, topHeight, 0 ), color ); - NavDrawTriangle( m_center + Vector( 0, -bottomHeight, 0 ), m_center + Vector( -bottomWidth, -bottomHeight*2, 0 ), m_center + Vector( bottomWidth, -bottomHeight*2, 0 ), color ); - } -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Draw navigation areas and edit them - */ -void CNavArea::DrawHidingSpots( void ) const -{ - const HidingSpotList *list = GetHidingSpotList(); - - FOR_EACH_LL( (*list), it ) - { - const HidingSpot *spot = (*list)[ it ]; - - NavEditColor color; - - if (spot->IsIdealSniperSpot()) - { - color = NavIdealSniperColor; - } - else if (spot->IsGoodSniperSpot()) - { - color = NavGoodSniperColor; - } - else if (spot->HasGoodCover()) - { - color = NavGoodCoverColor; - } - else - { - color = NavExposedColor; - } - - NavDrawLine( spot->GetPosition(), spot->GetPosition() + Vector( 0, 0, 50 ), color ); - } -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Draw ourselves and adjacent areas - */ -void CNavArea::DrawConnectedAreas( void ) const -{ - int i; - - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - // draw self - if (TheNavMesh->IsPlaceMode()) - { - Draw(); - } - else - { - Draw(); - DrawHidingSpots(); - } - - // draw connected ladders - { - FOR_EACH_LL( m_ladder[ CNavLadder::LADDER_UP ], it ) - { - CNavLadder *ladder = m_ladder[ CNavLadder::LADDER_UP ][ it ].ladder; - - ladder->DrawLadder(); - - if ( !ladder->IsConnected( this, CNavLadder::LADDER_DOWN ) ) - { - NavDrawLine( m_center, ladder->m_bottom + Vector( 0, 0, GenerationStepSize ), NavConnectedOneWayColor ); - } - } - } - { - FOR_EACH_LL( m_ladder[ CNavLadder::LADDER_DOWN ], it ) - { - CNavLadder *ladder = m_ladder[ CNavLadder::LADDER_DOWN ][ it ].ladder; - - ladder->DrawLadder(); - - if ( !ladder->IsConnected( this, CNavLadder::LADDER_UP ) ) - { - NavDrawLine( m_center, ladder->m_top, NavConnectedOneWayColor ); - } - } - } - - // draw connected areas - for( i=0; iDraw(); - - if ( !TheNavMesh->IsPlaceMode() ) - { - adj->DrawHidingSpots(); - - Vector from = Vector(0.0f, 0.0f, 0.0f), to = Vector(0.0f, 0.0f, 0.0f); - Vector hookPos = Vector(0.0f, 0.0f, 0.0f); - float halfWidth; - float size = 5.0f; - ComputePortal( adj, dir, &hookPos, &halfWidth ); - - switch( dir ) - { - case NORTH: - from = hookPos + Vector( 0.0f, size, 0.0f ); - to = hookPos + Vector( 0.0f, -size, 0.0f ); - break; - case SOUTH: - from = hookPos + Vector( 0.0f, -size, 0.0f ); - to = hookPos + Vector( 0.0f, size, 0.0f ); - break; - case EAST: - from = hookPos + Vector( -size, 0.0f, 0.0f ); - to = hookPos + Vector( +size, 0.0f, 0.0f ); - break; - case WEST: - from = hookPos + Vector( size, 0.0f, 0.0f ); - to = hookPos + Vector( -size, 0.0f, 0.0f ); - break; - default: - break; - } - - from.z = GetZ( from ); - to.z = adj->GetZ( to ); - - Vector drawTo; - adj->GetClosestPointOnArea( to, &drawTo ); - - if (adj->IsConnected( this, OppositeDirection( dir ) ) ) - NavDrawLine( from, drawTo, NavConnectedTwoWaysColor ); - else - NavDrawLine( from, drawTo, NavConnectedOneWayColor ); - } - } - } -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Add to open list in decreasing value order - */ -void CNavArea::AddToOpenList( void ) -{ - // mark as being on open list for quick check - m_openMarker = m_masterMarker; - - // if list is empty, add and return - if (m_openList == NULL) - { - m_openList = this; - this->m_prevOpen = NULL; - this->m_nextOpen = NULL; - return; - } - - // insert self in ascending cost order - CNavArea *area, *last = NULL; - for( area = m_openList; area; area = area->m_nextOpen ) - { - if (this->GetTotalCost() < area->GetTotalCost()) - break; - - last = area; - } - - if (area) - { - // insert before this area - this->m_prevOpen = area->m_prevOpen; - if (this->m_prevOpen) - this->m_prevOpen->m_nextOpen = this; - else - m_openList = this; - - this->m_nextOpen = area; - area->m_prevOpen = this; - } - else - { - // append to end of list - last->m_nextOpen = this; - - this->m_prevOpen = last; - this->m_nextOpen = NULL; - } -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * A smaller value has been found, update this area on the open list - * @todo "bubbling" does unnecessary work, since the order of all other nodes will be unchanged - only this node is altered - */ -void CNavArea::UpdateOnOpenList( void ) -{ - // since value can only decrease, bubble this area up from current spot - while( m_prevOpen && - this->GetTotalCost() < m_prevOpen->GetTotalCost() ) - { - // swap position with predecessor - CNavArea *other = m_prevOpen; - CNavArea *before = other->m_prevOpen; - CNavArea *after = this->m_nextOpen; - - this->m_nextOpen = other; - this->m_prevOpen = before; - - other->m_prevOpen = this; - other->m_nextOpen = after; - - if (before) - before->m_nextOpen = this; - else - m_openList = this; - - if (after) - after->m_prevOpen = other; - } -} - -//-------------------------------------------------------------------------------------------------------------- -void CNavArea::RemoveFromOpenList( void ) -{ - if (m_prevOpen) - m_prevOpen->m_nextOpen = m_nextOpen; - else - m_openList = m_nextOpen; - - if (m_nextOpen) - m_nextOpen->m_prevOpen = m_prevOpen; - - // zero is an invalid marker - m_openMarker = 0; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Clears the open and closed lists for a new search - */ -void CNavArea::ClearSearchLists( void ) -{ - // effectively clears all open list pointers and closed flags - CNavArea::MakeNewMarker(); - - m_openList = NULL; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return the coordinates of the area's corner. - * NOTE: Do not retain the returned pointer - it is temporary. - */ -const Vector &CNavArea::GetCorner( NavCornerType corner ) const -{ - static Vector pos; - - switch( corner ) - { - default: - Assert( false && "GetCorner: Invalid type" ); - case NORTH_WEST: - return m_extent.lo; - - case NORTH_EAST: - pos.x = m_extent.hi.x; - pos.y = m_extent.lo.y; - pos.z = m_neZ; - return pos; - - case SOUTH_WEST: - pos.x = m_extent.lo.x; - pos.y = m_extent.hi.y; - pos.z = m_swZ; - return pos; - - case SOUTH_EAST: - return m_extent.hi; - } -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavArea::SetCorner( NavCornerType corner, const Vector& newPosition ) -{ - switch( corner ) - { - case NORTH_WEST: - m_extent.lo = newPosition; - break; - - case NORTH_EAST: - m_extent.hi.x = newPosition.x; - m_extent.lo.y = newPosition.y; - m_neZ = newPosition.z; - break; - - case SOUTH_WEST: - m_extent.lo.x = newPosition.x; - m_extent.hi.y = newPosition.y; - m_swZ = newPosition.z; - break; - - case SOUTH_EAST: - m_extent.hi = newPosition; - break; - - default: - { - Vector oldPosition = GetCenter(); - Vector delta = newPosition - oldPosition; - m_extent.lo += delta; - m_extent.hi += delta; - m_neZ += delta.z; - m_swZ += delta.z; - } - } - - m_center.x = (m_extent.lo.x + m_extent.hi.x)/2.0f; - m_center.y = (m_extent.lo.y + m_extent.hi.y)/2.0f; - m_center.z = (m_extent.lo.z + m_extent.hi.z)/2.0f; -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Returns true if an existing hiding spot is too close to given position - */ -bool CNavArea::IsHidingSpotCollision( const Vector &pos ) const -{ - const float collisionRange = 30.0f; - - FOR_EACH_LL( m_hidingSpotList, it ) - { - const HidingSpot *spot = m_hidingSpotList[ it ]; - - if ((spot->GetPosition() - pos).IsLengthLessThan( collisionRange )) - return true; - } - - return false; -} - -//-------------------------------------------------------------------------------------------------------------- -bool IsHidingSpotInCover( const Vector &spot ) -{ - int coverCount = 0; - trace_t result; - - Vector from = spot; - from.z += HalfHumanHeight; - - Vector to; - - // if we are crouched underneath something, that counts as good cover - to = from + Vector( 0, 0, 20.0f ); - UTIL_TraceLine( from, to, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &result ); - if (result.fraction != 1.0f) - return true; - - const float coverRange = 100.0f; - const float inc = M_PI / 8.0f; - - for( float angle = 0.0f; angle < 2.0f * M_PI; angle += inc ) - { - to = from + Vector( coverRange * (float)cos(angle), coverRange * (float)sin(angle), HalfHumanHeight ); - - UTIL_TraceLine( from, to, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &result ); - - // if traceline hit something, it hit "cover" - if (result.fraction != 1.0f) - ++coverCount; - } - - // if more than half of the circle has no cover, the spot is not "in cover" - const int halfCover = 8; - if (coverCount < halfCover) - return false; - - return true; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Finds the hiding spot position in a corner's area. If the typical inset is off the nav area (small - * hand-constructed areas), it tries to fit the position inside the area. - */ -static Vector FindPositionInArea( CNavArea *area, NavCornerType corner ) -{ - int multX = 1, multY = 1; - switch ( corner ) - { - case NORTH_WEST: - break; - case NORTH_EAST: - multX = -1; - break; - case SOUTH_WEST: - multY = -1; - break; - case SOUTH_EAST: - multX = -1; - multY = -1; - break; - default: - break; - } - - const float offset = 12.5f; - Vector cornerPos = area->GetCorner( corner ); - - // Try the basic inset - Vector pos = cornerPos + Vector( offset*multX, offset*multY, 0.0f ); - if ( !area->IsOverlapping( pos ) ) - { - // Try pulling the Y offset to the area's center - pos = cornerPos + Vector( offset*multX, area->GetSizeY()*0.5f*multY, 0.0f ); - if ( !area->IsOverlapping( pos ) ) - { - // Try pulling the X offset to the area's center - pos = cornerPos + Vector( area->GetSizeX()*0.5f*multX, offset*multY, 0.0f ); - if ( !area->IsOverlapping( pos ) ) - { - // Try pulling the X and Y offsets to the area's center - pos = cornerPos + Vector( area->GetSizeX()*0.5f*multX, area->GetSizeY()*0.5f*multY, 0.0f ); - if ( !area->IsOverlapping( pos ) ) - { - AssertMsg( false, UTIL_VarArgs( "A Hiding Spot can't be placed on its area at (%.0f %.0f %.0f)", cornerPos.x, cornerPos.y, cornerPos.z) ); - - // Just pull the position to a small offset - pos = cornerPos + Vector( 1.0f*multX, 1.0f*multY, 0.0f ); - if ( !area->IsOverlapping( pos ) ) - { - // Nothing is working (degenerate area?), so just put it directly on the corner - pos = cornerPos; - } - } - } - } - } - - return pos; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Analyze local area neighborhood to find "hiding spots" for this area - */ -void CNavArea::ComputeHidingSpots( void ) -{ - struct - { - float lo, hi; - } - extent; - - m_hidingSpotList.PurgeAndDeleteElements(); - - - // "jump areas" cannot have hiding spots - if ( GetAttributes() & NAV_MESH_JUMP ) - return; - - // "don't hide areas" cannot have hiding spots - if ( GetAttributes() & NAV_MESH_DONT_HIDE ) - return; - - int cornerCount[NUM_CORNERS]; - for( int i=0; iIsConnected( this, OppositeDirection( static_cast( d ) ) ) == false) - continue; - - // ignore jump areas - if (connect.area->GetAttributes() & NAV_MESH_JUMP) - continue; - - if (isHoriz) - { - if (connect.area->m_extent.lo.x < extent.lo) - extent.lo = connect.area->m_extent.lo.x; - - if (connect.area->m_extent.hi.x > extent.hi) - extent.hi = connect.area->m_extent.hi.x; - } - else - { - if (connect.area->m_extent.lo.y < extent.lo) - extent.lo = connect.area->m_extent.lo.y; - - if (connect.area->m_extent.hi.y > extent.hi) - extent.hi = connect.area->m_extent.hi.y; - } - } - - switch( d ) - { - case NORTH: - if (extent.lo - m_extent.lo.x >= cornerSize) - ++cornerCount[ NORTH_WEST ]; - - if (m_extent.hi.x - extent.hi >= cornerSize) - ++cornerCount[ NORTH_EAST ]; - break; - - case SOUTH: - if (extent.lo - m_extent.lo.x >= cornerSize) - ++cornerCount[ SOUTH_WEST ]; - - if (m_extent.hi.x - extent.hi >= cornerSize) - ++cornerCount[ SOUTH_EAST ]; - break; - - case EAST: - if (extent.lo - m_extent.lo.y >= cornerSize) - ++cornerCount[ NORTH_EAST ]; - - if (m_extent.hi.y - extent.hi >= cornerSize) - ++cornerCount[ SOUTH_EAST ]; - break; - - case WEST: - if (extent.lo - m_extent.lo.y >= cornerSize) - ++cornerCount[ NORTH_WEST ]; - - if (m_extent.hi.y - extent.hi >= cornerSize) - ++cornerCount[ SOUTH_WEST ]; - break; - } - } - - for ( int c=0; cCreateHidingSpot(); - spot->SetPosition( pos ); - spot->SetFlags( IsHidingSpotInCover( pos ) ? HidingSpot::IN_COVER : HidingSpot::EXPOSED ); - m_hidingSpotList.AddToTail( spot ); - } - } - } -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Determine how much walkable area we can see from the spot, and how far away we can see. - */ -void ClassifySniperSpot( HidingSpot *spot ) -{ - Vector eye = spot->GetPosition(); - - CNavArea *hidingArea = TheNavMesh->GetNavArea( spot->GetPosition() ); - if (hidingArea && (hidingArea->GetAttributes() & NAV_MESH_STAND)) - { - // we will be standing at this hiding spot - eye += Vector( 0, 0, 0.8f * HumanHeight ); - } - else - { - // we are crouching when at this hiding spot - eye += Vector( 0, 0, HalfHumanHeight ); - } - - Vector walkable; - trace_t result; - - Extent sniperExtent; - float farthestRangeSq = 0.0f; - const float minSniperRangeSq = 1000.0f * 1000.0f; - bool found = false; - - // to make compiler stop warning me - sniperExtent.lo = Vector( 0.0f, 0.0f, 0.0f ); - sniperExtent.hi = Vector( 0.0f, 0.0f, 0.0f ); - - FOR_EACH_LL( TheNavAreaList, it ) - { - CNavArea *area = TheNavAreaList[ it ]; - - const Extent &extent = area->GetExtent(); - - // scan this area - for( walkable.y = extent.lo.y + GenerationStepSize/2.0f; walkable.y < extent.hi.y; walkable.y += GenerationStepSize ) - { - for( walkable.x = extent.lo.x + GenerationStepSize/2.0f; walkable.x < extent.hi.x; walkable.x += GenerationStepSize ) - { - walkable.z = area->GetZ( walkable ) + HalfHumanHeight; - - // check line of sight - UTIL_TraceLine( eye, walkable, CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_PLAYERCLIP, NULL, COLLISION_GROUP_NONE, &result ); - - if (result.fraction == 1.0f && !result.startsolid) - { - // can see this spot - - // keep track of how far we can see - float rangeSq = (eye - walkable).LengthSqr(); - if (rangeSq > farthestRangeSq) - { - farthestRangeSq = rangeSq; - - if (rangeSq >= minSniperRangeSq) - { - // this is a sniper spot - // determine how good of a sniper spot it is by keeping track of the snipable area - if (found) - { - if (walkable.x < sniperExtent.lo.x) - sniperExtent.lo.x = walkable.x; - if (walkable.x > sniperExtent.hi.x) - sniperExtent.hi.x = walkable.x; - - if (walkable.y < sniperExtent.lo.y) - sniperExtent.lo.y = walkable.y; - if (walkable.y > sniperExtent.hi.y) - sniperExtent.hi.y = walkable.y; - } - else - { - sniperExtent.lo = walkable; - sniperExtent.hi = walkable; - found = true; - } - } - } - } - } - } - } - - if (found) - { - // if we can see a large snipable area, it is an "ideal" spot - float snipableArea = sniperExtent.Area(); - - const float minIdealSniperArea = 200.0f * 200.0f; - const float longSniperRangeSq = 1500.0f * 1500.0f; - - if (snipableArea >= minIdealSniperArea || farthestRangeSq >= longSniperRangeSq) - spot->m_flags |= HidingSpot::IDEAL_SNIPER_SPOT; - else - spot->m_flags |= HidingSpot::GOOD_SNIPER_SPOT; - } -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Analyze local area neighborhood to find "sniper spots" for this area - */ -void CNavArea::ComputeSniperSpots( void ) -{ - if (nav_quicksave.GetBool()) - return; - - FOR_EACH_LL( m_hidingSpotList, it ) - { - HidingSpot *spot = m_hidingSpotList[ it ]; - - ClassifySniperSpot( spot ); - } -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Given the areas we are moving between, return the spots we will encounter - */ -SpotEncounter *CNavArea::GetSpotEncounter( const CNavArea *from, const CNavArea *to ) -{ - if (from && to) - { - SpotEncounter *e; - - FOR_EACH_LL( m_spotEncounterList, it ) - { - e = m_spotEncounterList[ it ]; - - if (e->from.area == from && e->to.area == to) - return e; - } - } - - return NULL; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Add spot encounter data when moving from area to area - */ -void CNavArea::AddSpotEncounters( const CNavArea *from, NavDirType fromDir, const CNavArea *to, NavDirType toDir ) -{ - SpotEncounter *e = new SpotEncounter; - - e->from.area = const_cast( from ); - e->fromDir = fromDir; - - e->to.area = const_cast( to ); - e->toDir = toDir; - - float halfWidth; - ComputePortal( to, toDir, &e->path.to, &halfWidth ); - ComputePortal( from, fromDir, &e->path.from, &halfWidth ); - - const float eyeHeight = HalfHumanHeight; - e->path.from.z = from->GetZ( e->path.from ) + eyeHeight; - e->path.to.z = to->GetZ( e->path.to ) + eyeHeight; - - // step along ray and track which spots can be seen - Vector dir = e->path.to - e->path.from; - float length = dir.NormalizeInPlace(); - - // create unique marker to flag used spots - HidingSpot::ChangeMasterMarker(); - - const float stepSize = 25.0f; // 50 - const float seeSpotRange = 2000.0f; // 3000 - trace_t result; - - Vector eye, delta; - HidingSpot *spot; - SpotOrder spotOrder; - - // step along path thru this area - bool done = false; - for( float along = 0.0f; !done; along += stepSize ) - { - // make sure we check the endpoint of the path segment - if (along >= length) - { - along = length; - done = true; - } - - // move the eyepoint along the path segment - eye = e->path.from + along * dir; - - // check each hiding spot for visibility - FOR_EACH_LL( TheHidingSpotList, it ) - { - spot = TheHidingSpotList[ it ]; - - // only look at spots with cover (others are out in the open and easily seen) - if (!spot->HasGoodCover()) - continue; - - if (spot->IsMarked()) - continue; - - const Vector &spotPos = spot->GetPosition(); - - delta.x = spotPos.x - eye.x; - delta.y = spotPos.y - eye.y; - delta.z = (spotPos.z + eyeHeight) - eye.z; - - // check if in range - if (delta.IsLengthGreaterThan( seeSpotRange )) - continue; - - // check if we have LOS - // BOTPORT: ignore glass here - UTIL_TraceLine( eye, Vector( spotPos.x, spotPos.y, spotPos.z + HalfHumanHeight ), MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &result ); - if (result.fraction != 1.0f) - continue; - - // if spot is in front of us along our path, ignore it - delta.NormalizeInPlace(); - float dot = DotProduct( dir, delta ); - if (dot < 0.7071f && dot > -0.7071f) - { - // we only want to keep spots that BECOME visible as we walk past them - // therefore, skip ALL visible spots at the start of the path segment - if (along > 0.0f) - { - // add spot to encounter - spotOrder.spot = spot; - spotOrder.t = along/length; - e->spotList.AddToTail( spotOrder ); - } - } - - // mark spot as encountered - spot->Mark(); - } - } - - // add encounter to list - m_spotEncounterList.AddToTail( e ); -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Compute "spot encounter" data. This is an ordered list of spots to look at - * for each possible path thru a nav area. - */ -void CNavArea::ComputeSpotEncounters( void ) -{ - m_spotEncounterList.RemoveAll(); - - if (nav_quicksave.GetBool()) - return; - - // for each adjacent area - for( int fromDir=0; fromDirarea, (NavDirType)fromDir, toCon->area, (NavDirType)toDir ); - } - } - } - } -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Decay the danger values - */ -void CNavArea::DecayDanger( void ) -{ - // one kill == 1.0, which we will forget about in two minutes - const float decayRate = 1.0f / 120.0f; - - for( int i=0; icurtime - m_dangerTimestamp[i]; - float decayAmount = decayRate * deltaT; - - m_danger[i] -= decayAmount; - if (m_danger[i] < 0.0f) - m_danger[i] = 0.0f; - - // update timestamp - m_dangerTimestamp[i] = gpGlobals->curtime; - } -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Increase the danger of this area for the given team - */ -void CNavArea::IncreaseDanger( int teamID, float amount ) -{ - // before we add the new value, decay what's there - DecayDanger(); - - int teamIdx = teamID % MAX_NAV_TEAMS; - - m_danger[ teamIdx ] += amount; - m_dangerTimestamp[ teamIdx ] = gpGlobals->curtime; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return the danger of this area (decays over time) - */ -float CNavArea::GetDanger( int teamID ) -{ - DecayDanger(); - - int teamIdx = teamID % MAX_NAV_TEAMS; - return m_danger[ teamIdx ]; -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Raise/lower a corner - */ -void CNavArea::RaiseCorner( NavCornerType corner, int amount, bool raiseAdjacentCorners ) -{ - if ( corner == NUM_CORNERS ) - { - RaiseCorner( NORTH_WEST, amount, raiseAdjacentCorners ); - RaiseCorner( NORTH_EAST, amount, raiseAdjacentCorners ); - RaiseCorner( SOUTH_WEST, amount, raiseAdjacentCorners ); - RaiseCorner( SOUTH_EAST, amount, raiseAdjacentCorners ); - return; - } - - // Move the corner - switch (corner) - { - case NORTH_WEST: - m_extent.lo.z += amount; - break; - case NORTH_EAST: - m_neZ += amount; - break; - case SOUTH_WEST: - m_swZ += amount; - break; - case SOUTH_EAST: - m_extent.hi.z += amount; - break; - default: - break; - } - - // Recompute the center - m_center.x = (m_extent.lo.x + m_extent.hi.x)/2.0f; - m_center.y = (m_extent.lo.y + m_extent.hi.y)/2.0f; - m_center.z = (m_extent.lo.z + m_extent.hi.z)/2.0f; - - if ( !raiseAdjacentCorners || nav_corner_adjust_adjacent.GetFloat() <= 0.0f ) - { - return; - } - - // Find nearby areas that share the corner - CNavArea::MakeNewMarker(); - Mark(); - - const float tolerance = nav_corner_adjust_adjacent.GetFloat(); - - Vector cornerPos = GetCorner( corner ); - cornerPos.z -= amount; // use the pre-adjustment corner for adjacency checks - - int gridX = TheNavMesh->WorldToGridX( cornerPos.x ); - int gridY = TheNavMesh->WorldToGridY( cornerPos.y ); - - const int shift = 1; // try a 3x3 set of grids in case we're on the edge - - for( int x = gridX - shift; x <= gridX + shift; ++x ) - { - if (x < 0 || x >= TheNavMesh->m_gridSizeX) - continue; - - for( int y = gridY - shift; y <= gridY + shift; ++y ) - { - if (y < 0 || y >= TheNavMesh->m_gridSizeY) - continue; - - NavAreaList *list = &TheNavMesh->m_grid[ x + y*TheNavMesh->m_gridSizeX ]; - - // find closest area in this cell - FOR_EACH_LL( (*list), it ) - { - CNavArea *area = (*list)[ it ]; - - // skip if we've already visited this area - if (area->IsMarked()) - continue; - - area->Mark(); - - Vector areaPos; - for ( int i=0; iGetCorner( NavCornerType(i) ); - if ( areaPos.DistTo( cornerPos ) < tolerance ) - { - float heightDiff = (cornerPos.z + amount ) - areaPos.z; - area->RaiseCorner( NavCornerType(i), (int)heightDiff, false ); - } - } - } - } - } -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * FindGroundZFromPoint walks from the start position to the end position in GenerationStepSize increments, - * checking the ground height along the way. - */ -float FindGroundZFromPoint( const Vector& end, const Vector& start ) -{ - Vector step( 0, 0, StepHeight ); - if ( fabs( end.x - start.x ) > fabs( end.y - start.y ) ) - { - step.x = GenerationStepSize; - if ( end.x < start.x ) - { - step.x = -step.x; - } - } - else - { - step.y = GenerationStepSize; - if ( end.y < start.y ) - { - step.y = -step.y; - } - } - - // step towards our end point - Vector point = start; - float z; - while ( point.AsVector2D().DistTo( end.AsVector2D() ) > GenerationStepSize ) - { - point = point + step; - z = point.z; - if ( TheNavMesh->GetGroundHeight( point, &z ) ) - { - point.z = z; - } - else - { - point.z -= step.z; - } - } - - // now do the exact one once we're within GenerationStepSize of it - z = point.z + step.z; - point = end; - point.z = z; - if ( TheNavMesh->GetGroundHeight( point, &z ) ) - { - point.z = z; - } - else - { - point.z -= step.z; - } - - return point.z; -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Finds the Z value for a corner given two other corner points. This walks along the edges of the nav area - * in GenerationStepSize increments, to increase accuracy. - */ -float FindGroundZ( const Vector& original, const Vector& corner1, const Vector& corner2 ) -{ - float first = FindGroundZFromPoint( original, corner1 ); - float second = FindGroundZFromPoint( original, corner2 ); - - if ( fabs( first - second ) > StepHeight ) - { - // approaching the point from the two directions didn't agree. Take the one closest to the original z. - if ( fabs( original.z - first ) > fabs( original.z - second ) ) - { - return second; - } - else - { - return first; - } - } - - return first; -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Places a corner (or all corners if corner == NUM_CORNERS) on the ground - */ -void CNavArea::PlaceOnGround( NavCornerType corner, float inset ) -{ - trace_t result; - Vector from, to; - - Vector nw = m_extent.lo + Vector ( inset, inset, 0 ); - Vector se = m_extent.hi + Vector ( -inset, -inset, 0 ); - Vector ne, sw; - ne.x = se.x; - ne.y = nw.y; - ne.z = m_neZ; - sw.x = nw.x; - sw.y = se.y; - sw.z = m_swZ; - - if ( corner == NORTH_WEST || corner == NUM_CORNERS ) - { - float newZ = FindGroundZ( nw, ne, sw ); - RaiseCorner( NORTH_WEST, static_cast(newZ - nw.z) ); - } - - if ( corner == NORTH_EAST || corner == NUM_CORNERS ) - { - float newZ = FindGroundZ( ne, nw, se ); - RaiseCorner( NORTH_EAST, static_cast(newZ - ne.z) ); - } - - if ( corner == SOUTH_WEST || corner == NUM_CORNERS ) - { - float newZ = FindGroundZ( sw, nw, se ); - RaiseCorner( SOUTH_WEST, static_cast(newZ - sw.z) ); - } - - if ( corner == SOUTH_EAST || corner == NUM_CORNERS ) - { - float newZ = FindGroundZ( se, ne, sw ); - RaiseCorner( SOUTH_EAST, static_cast(newZ - se.z) ); - } -} - - -//-------------------------------------------------------------------------------------------------------------- -static void CommandNavUpdateBlocked( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - if ( TheNavMesh->GetMarkedArea() ) - { - CNavArea *area = TheNavMesh->GetMarkedArea(); - area->UpdateBlocked(); - if ( area->IsBlocked() ) - { - DevMsg( "Area #%d %s is blocked\n", area->GetID(), VecToString( area->GetCenter() + Vector( 0, 0, HalfHumanHeight ) ) ); - } - } - else - { - float start = engine->Time(); - CNavArea *blockedArea = NULL; - FOR_EACH_LL( TheNavAreaList, nit ) - { - CNavArea *area = TheNavAreaList[ nit ]; - area->UpdateBlocked(); - if ( area->IsBlocked() ) - { - DevMsg( "Area #%d %s is blocked\n", area->GetID(), VecToString( area->GetCenter() + Vector( 0, 0, HalfHumanHeight ) ) ); - if ( !blockedArea ) - { - blockedArea = area; - } - } - } - - float end = engine->Time(); - float time = (end - start) * 1000.0f; - DevMsg( "nav_update_blocked took %2.2f ms\n", time ); - - if ( blockedArea ) - { - CBasePlayer *player = UTIL_GetListenServerHost(); - if ( player ) - { - if ( ( player->IsDead() || player->IsObserver() ) && player->GetObserverMode() == OBS_MODE_ROAMING ) - { - Vector origin = blockedArea->GetCenter() + Vector( 0, 0, 0.75f * HumanHeight ); - UTIL_SetOrigin( player, origin ); - } - } - } - } -} -static ConCommand nav_update_blocked( "nav_update_blocked", CommandNavUpdateBlocked, "Updates the blocked/unblocked status for every nav area.", FCVAR_GAMEDLL ); - - -//----------------------------------------------------------------------------------------------------- -class CNavBlockerEnumerator : public IPartitionEnumerator -{ -public: - // Forced constructor - CNavBlockerEnumerator(CBaseEntity **ents, int nMaxEnts) - { - m_nAlreadyHit = 0; - m_AlreadyHit = ents; - m_nMaxHits = nMaxEnts; - } - - // Actual work code - virtual IterationRetval_t EnumElement( IHandleEntity *pHandleEntity ) - { - CBaseEntity *pEnt = gEntList.GetBaseEntity( pHandleEntity->GetRefEHandle() ); - - if ( pEnt == NULL ) - return ITERATION_CONTINUE; - - if ( pEnt->GetCollisionGroup() != COLLISION_GROUP_PUSHAWAY && pEnt->GetCollisionGroup() != COLLISION_GROUP_BREAKABLE_GLASS && pEnt->GetCollisionGroup() != COLLISION_GROUP_PLAYER && pEnt->GetCollisionGroup() != COLLISION_GROUP_NONE ) - return ITERATION_CONTINUE; - - IMultiplayerPhysics *pInterface = dynamic_cast( pEnt ); - if ( pInterface ) - { - if ( pInterface->GetMultiplayerPhysicsMode() != PHYSICS_MULTIPLAYER_SOLID ) - return ITERATION_CONTINUE; - } - else - { - if ((FClassnameIs( pEnt, "func_breakable" ) || FClassnameIs( pEnt, "func_breakable_surf" ))) - { - bool isBreakable = true; - - // If we won't be able to break it, don't try - if ( pEnt->m_takedamage != DAMAGE_YES ) - { - isBreakable = false; - } - - if ( !isBreakable ) - return ITERATION_CONTINUE; - } - else if ( FClassnameIs( pEnt, "func_door*" ) ) // doors - { - } - else if ( FClassnameIs( pEnt, "prop_door*" ) ) // doors - { - } - else - { - return ITERATION_CONTINUE; - } - } - - if ( m_nAlreadyHit < m_nMaxHits ) - { - m_AlreadyHit[m_nAlreadyHit] = pEnt; - m_nAlreadyHit++; - } - - return ITERATION_CONTINUE; - } - -public: - - CBaseEntity **m_AlreadyHit; - int m_nAlreadyHit; - int m_nMaxHits; -}; - - -//----------------------------------------------------------------------------------------------------- -/*static int GetPushawayEntsInVolume( const Vector& origin, const Vector& mins, const Vector& maxs, CBaseEntity **ents, int nMaxEnts, int PartitionMask, CNavBlockerEnumerator *enumerator ) -{ - Ray_t ray; - ray.Init( origin, origin, mins, maxs ); - - CNavBlockerEnumerator *physPropEnum = NULL; - if ( !enumerator ) - { - physPropEnum = new CNavBlockerEnumerator( ents, nMaxEnts ); - enumerator = physPropEnum; - } - - partition->EnumerateElementsAlongRay( PartitionMask, ray, false, enumerator ); - - int numHit = enumerator->m_nAlreadyHit; - - if ( physPropEnum ) - delete physPropEnum; - - return numHit; -}*/ - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Updates the (un)blocked status of the nav area - */ -void CNavArea::UpdateBlocked( void ) -{ - Vector origin = GetCenter(); - origin.z += HalfHumanHeight; - - const float sizeX = MAX( 1, MIN( GetSizeX()/2 - 5, HalfHumanWidth ) ); - const float sizeY = MAX( 1, MIN( GetSizeY()/2 - 5, HalfHumanWidth ) ); - Vector mins( -sizeX, -sizeY, 0 ); - Vector maxs( sizeX, sizeY, VEC_DUCK_HULL_MAX.z ); - - maxs.z -= HalfHumanHeight; - - bool wasBlocked = m_isBlocked; - - // See if spot is valid - CTraceFilterWalkableEntities filter( NULL, COLLISION_GROUP_PLAYER_MOVEMENT, WALK_THRU_DOORS | WALK_THRU_BREAKABLES ); - trace_t tr; - UTIL_TraceHull( - origin, - origin, - mins, - maxs, - MASK_PLAYERSOLID_BRUSHONLY, - &filter, - &tr ); - - m_isBlocked = tr.startsolid; - - if ( wasBlocked != m_isBlocked ) - { - IGameEvent * event = gameeventmanager->CreateEvent( "nav_blocked" ); - if ( event ) - { - event->SetInt( "area", m_id ); - event->SetInt( "blocked", m_isBlocked ); - gameeventmanager->FireEvent( event ); - } - } - - /* - if ( m_isBlocked ) - { - NDebugOverlay::Box( origin, mins, maxs, 255, 0, 0, 64, 3.0f ); - } - else - { - NDebugOverlay::Box( origin, mins, maxs, 0, 255, 0, 64, 3.0f ); - } - */ -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Checks if there is a floor under the nav area, in case a breakable floor is gone - */ -void CNavArea::CheckFloor( CBaseEntity *ignore ) -{ - if ( m_isBlocked ) - return; - - Vector origin = GetCenter(); - origin.z -= JumpCrouchHeight; - - const float size = GenerationStepSize * 0.5f; - Vector mins = Vector( -size, -size, 0 ); - Vector maxs = Vector( size, size, JumpCrouchHeight + 10.0f ); - - bool wasBlocked = m_isBlocked; - - // See if spot is valid - trace_t tr; - UTIL_TraceHull( - origin, - origin, - mins, - maxs, - MASK_PLAYERSOLID_BRUSHONLY, - ignore, - COLLISION_GROUP_PLAYER_MOVEMENT, - &tr ); - - // If the center is open space, we're effectively blocked - m_isBlocked = !tr.startsolid; - - if ( wasBlocked != m_isBlocked ) - { - IGameEvent * event = gameeventmanager->CreateEvent( "nav_blocked" ); - if ( event ) - { - event->SetInt( "area", m_id ); - event->SetInt( "blocked", m_isBlocked ); - gameeventmanager->FireEvent( event ); - } - } - - /* - if ( m_isBlocked ) - { - NDebugOverlay::Box( origin, mins, maxs, 255, 0, 0, 64, 3.0f ); - } - else - { - NDebugOverlay::Box( origin, mins, maxs, 0, 255, 0, 64, 3.0f ); - } - */ -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavArea::CheckWaterLevel( void ) -{ - Vector pos( GetCenter() ); - if ( !TheNavMesh->GetGroundHeight( pos, &pos.z ) ) - { - m_isUnderwater = false; - return; - } - - pos.z += 1; - m_isUnderwater = (enginetrace->GetPointContents( pos ) & MASK_WATER) != 0; -} - - -//-------------------------------------------------------------------------------------------------------------- -static void CommandNavCheckFloor( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - if ( TheNavMesh->GetMarkedArea() ) - { - CNavArea *area = TheNavMesh->GetMarkedArea(); - area->CheckFloor( NULL ); - if ( area->IsBlocked() ) - { - DevMsg( "Area #%d %s is blocked\n", area->GetID(), VecToString( area->GetCenter() + Vector( 0, 0, HalfHumanHeight ) ) ); - } - } - else - { - float start = engine->Time(); - FOR_EACH_LL( TheNavAreaList, nit ) - { - CNavArea *area = TheNavAreaList[ nit ]; - area->CheckFloor( NULL ); - if ( area->IsBlocked() ) - { - DevMsg( "Area #%d %s is blocked\n", area->GetID(), VecToString( area->GetCenter() + Vector( 0, 0, HalfHumanHeight ) ) ); - } - } - - float end = engine->Time(); - float time = (end - start) * 1000.0f; - DevMsg( "nav_check_floor took %2.2f ms\n", time ); - } -} -static ConCommand nav_check_floor( "nav_check_floor", CommandNavCheckFloor, "Updates the blocked/unblocked status for every nav area.", FCVAR_GAMEDLL ); - - -//-------------------------------------------------------------------------------------------------------------- diff --git a/game/server/nav_area.h b/game/server/nav_area.h deleted file mode 100644 index 17332ed0b..000000000 --- a/game/server/nav_area.h +++ /dev/null @@ -1,586 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -// nav_area.h -// Navigation areas -// Author: Michael S. Booth (mike@turtlerockstudios.com), January 2003 - -#ifndef _NAV_AREA_H_ -#define _NAV_AREA_H_ - -#include "nav_ladder.h" - -// BOTPORT: Clean up relationship between team index and danger storage in nav areas -enum { MAX_NAV_TEAMS = 2 }; - - - -//------------------------------------------------------------------------------------------------------------------- -/** - * The NavConnect union is used to refer to connections to areas - */ -union NavConnect -{ - unsigned int id; - CNavArea *area; - - bool operator==( const NavConnect &other ) const - { - return (area == other.area) ? true : false; - } -}; -typedef CUtlLinkedList NavConnectList; - - -//------------------------------------------------------------------------------------------------------------------- -/** - * The NavLadderConnect union is used to refer to connections to ladders - */ -union NavLadderConnect -{ - unsigned int id; - CNavLadder *ladder; - - bool operator==( const NavLadderConnect &other ) const - { - return (ladder == other.ladder) ? true : false; - } -}; -typedef CUtlLinkedList NavLadderConnectList; - - -//-------------------------------------------------------------------------------------------------------------- -/** - * A HidingSpot is a good place for a bot to crouch and wait for enemies - */ -class HidingSpot -{ -public: - virtual ~HidingSpot() { } - - enum - { - IN_COVER = 0x01, ///< in a corner with good hard cover nearby - GOOD_SNIPER_SPOT = 0x02, ///< had at least one decent sniping corridor - IDEAL_SNIPER_SPOT = 0x04, ///< can see either very far, or a large area, or both - EXPOSED = 0x08 ///< spot in the open, usually on a ledge or cliff - }; - - bool HasGoodCover( void ) const { return (m_flags & IN_COVER) ? true : false; } ///< return true if hiding spot in in cover - bool IsGoodSniperSpot( void ) const { return (m_flags & GOOD_SNIPER_SPOT) ? true : false; } - bool IsIdealSniperSpot( void ) const { return (m_flags & IDEAL_SNIPER_SPOT) ? true : false; } - bool IsExposed( void ) const { return (m_flags & EXPOSED) ? true : false; } - - int GetFlags( void ) const { return m_flags; } - - void Save( FileHandle_t file, unsigned int version ) const; - void Load( FileHandle_t file, unsigned int version ); - NavErrorType PostLoad( void ); - - const Vector &GetPosition( void ) const { return m_pos; } ///< get the position of the hiding spot - unsigned int GetID( void ) const { return m_id; } - const CNavArea *GetArea( void ) const { return m_area; } ///< return nav area this hiding spot is within - - void Mark( void ) { m_marker = m_masterMarker; } - bool IsMarked( void ) const { return (m_marker == m_masterMarker) ? true : false; } - static void ChangeMasterMarker( void ) { ++m_masterMarker; } - - -public: - void SetFlags( int flags ) { m_flags |= flags; } ///< FOR INTERNAL USE ONLY - void SetPosition( const Vector &pos ) { m_pos = pos; } ///< FOR INTERNAL USE ONLY - -private: - friend class CNavMesh; - friend void ClassifySniperSpot( HidingSpot *spot ); - - HidingSpot( void ); ///< must use factory to create - - Vector m_pos; ///< world coordinates of the spot - unsigned int m_id; ///< this spot's unique ID - unsigned int m_marker; ///< this spot's unique marker - CNavArea *m_area; ///< the nav area containing this hiding spot - - unsigned char m_flags; ///< bit flags - - static unsigned int m_nextID; ///< used when allocating spot ID's - static unsigned int m_masterMarker; ///< used to mark spots -}; -typedef CUtlLinkedList< HidingSpot *, int > HidingSpotList; -extern HidingSpotList TheHidingSpotList; - -extern HidingSpot *GetHidingSpotByID( unsigned int id ); - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Stores a pointer to an interesting "spot", and a parametric distance along a path - */ -struct SpotOrder -{ - float t; ///< parametric distance along ray where this spot first has LOS to our path - union - { - HidingSpot *spot; ///< the spot to look at - unsigned int id; ///< spot ID for save/load - }; -}; -typedef CUtlLinkedList< SpotOrder, int > SpotOrderList; - -/** - * This struct stores possible path segments thru a CNavArea, and the dangerous spots - * to look at as we traverse that path segment. - */ -struct SpotEncounter -{ - NavConnect from; - NavDirType fromDir; - NavConnect to; - NavDirType toDir; - Ray path; ///< the path segment - SpotOrderList spotList; ///< list of spots to look at, in order of occurrence -}; -typedef CUtlLinkedList< SpotEncounter *, int > SpotEncounterList; - - -//------------------------------------------------------------------------------------------------------------------- -/** - * A CNavArea is a rectangular region defining a walkable area in the environment - */ -class CNavArea -{ -public: - CNavArea( CNavNode *nwNode, CNavNode *neNode, CNavNode *seNode, CNavNode *swNode ); - CNavArea( void ); - CNavArea( const Vector &corner, const Vector &otherCorner ); - CNavArea( const Vector &nwCorner, const Vector &neCorner, const Vector &seCorner, const Vector &swCorner ); - - ~CNavArea(); - - void ConnectTo( CNavArea *area, NavDirType dir ); ///< connect this area to given area in given direction - void Disconnect( CNavArea *area ); ///< disconnect this area from given area - - void ConnectTo( CNavLadder *ladder ); ///< connect this area to given ladder - void Disconnect( CNavLadder *ladder ); ///< disconnect this area from given ladder - - void Save( FileHandle_t file, unsigned int version ) const; - void Load( FileHandle_t file, unsigned int version ); - NavErrorType PostLoad( void ); - - unsigned int GetID( void ) const { return m_id; } ///< return this area's unique ID - static void CompressIDs( void ); ///< re-orders area ID's so they are continuous - - void SetAttributes( int bits ) { m_attributeFlags = (unsigned short)bits; } - int GetAttributes( void ) const { return m_attributeFlags; } - - void SetPlace( Place place ) { m_place = place; } ///< set place descriptor - Place GetPlace( void ) const { return m_place; } ///< get place descriptor - - void UpdateBlocked( void ); ///< Updates the (un)blocked status of the nav area - void CheckFloor( CBaseEntity *ignore ); ///< Checks if there is a floor under the nav area, in case a breakable floor is gone - bool IsBlocked( void ) const { return m_isBlocked; } - void CheckWaterLevel( void ); - bool IsUnderwater( void ) const { return m_isUnderwater; } - - bool IsOverlapping( const Vector &pos, float tolerance = 0.0f ) const; ///< return true if 'pos' is within 2D extents of area. - bool IsOverlapping( const CNavArea *area ) const; ///< return true if 'area' overlaps our 2D extents - bool IsOverlappingX( const CNavArea *area ) const; ///< return true if 'area' overlaps our X extent - bool IsOverlappingY( const CNavArea *area ) const; ///< return true if 'area' overlaps our Y extent - float GetZ( const Vector &pos ) const; ///< return Z of area at (x,y) of 'pos' - float GetZ( float x, float y ) const; ///< return Z of area at (x,y) of 'pos' - bool Contains( const Vector &pos ) const; ///< return true if given point is on or above this area, but no others - bool IsCoplanar( const CNavArea *area ) const; ///< return true if this area and given area are approximately co-planar - void GetClosestPointOnArea( const Vector &pos, Vector *close ) const; ///< return closest point to 'pos' on this area - returned point in 'close' - float GetDistanceSquaredToPoint( const Vector &pos ) const; ///< return shortest distance between point and this area - bool IsDegenerate( void ) const; ///< return true if this area is badly formed - bool IsRoughlySquare( void ) const; ///< return true if this area is approximately square - bool IsFlat( void ) const; ///< return true if this area is approximately flat - - bool IsEdge( NavDirType dir ) const; ///< return true if there are no bi-directional links on the given side - - bool IsVisible( const Vector &eye, Vector *visSpot = NULL ) const; ///< return true if area is visible from the given eyepoint, return visible spot - - int GetAdjacentCount( NavDirType dir ) const { return m_connect[ dir ].Count(); } ///< return number of connected areas in given direction - CNavArea *GetAdjacentArea( NavDirType dir, int i ) const; /// return the i'th adjacent area in the given direction - CNavArea *GetRandomAdjacentArea( NavDirType dir ) const; - - const NavConnectList *GetAdjacentList( NavDirType dir ) const { return &m_connect[dir]; } - bool IsConnected( const CNavArea *area, NavDirType dir ) const; ///< return true if given area is connected in given direction - bool IsConnected( const CNavLadder *ladder, CNavLadder::LadderDirectionType dir ) const; ///< return true if given ladder is connected in given direction - float ComputeHeightChange( const CNavArea *area ); ///< compute change in height from this area to given area - - const NavLadderConnectList *GetLadderList( CNavLadder::LadderDirectionType dir ) const { return &m_ladder[dir]; } - - void ComputePortal( const CNavArea *to, NavDirType dir, Vector *center, float *halfWidth ) const; ///< compute portal to adjacent area - void ComputeClosestPointInPortal( const CNavArea *to, NavDirType dir, const Vector &fromPos, Vector *closePos ) const; ///< compute closest point within the "portal" between to adjacent areas - NavDirType ComputeDirection( Vector *point ) const; ///< return direction from this area to the given point - - //- for hunting algorithm --------------------------------------------------------------------------- - void SetClearedTimestamp( int teamID ); ///< set this area's "clear" timestamp to now - float GetClearedTimestamp( int teamID ) const; ///< get time this area was marked "clear" - - //- hiding spots ------------------------------------------------------------------------------------ - const HidingSpotList *GetHidingSpotList( void ) const { return &m_hidingSpotList; } - void ComputeHidingSpots( void ); ///< analyze local area neighborhood to find "hiding spots" in this area - for map learning - void ComputeSniperSpots( void ); ///< analyze local area neighborhood to find "sniper spots" in this area - for map learning - - SpotEncounter *GetSpotEncounter( const CNavArea *from, const CNavArea *to ); ///< given the areas we are moving between, return the spots we will encounter - void ComputeSpotEncounters( void ); ///< compute spot encounter data - for map learning - int GetSpotEncounterCount( void ) const { return m_spotEncounterList.Count(); } - - //- "danger" ---------------------------------------------------------------------------------------- - void IncreaseDanger( int teamID, float amount ); ///< increase the danger of this area for the given team - float GetDanger( int teamID ); ///< return the danger of this area (decays over time) - - //- extents ----------------------------------------------------------------------------------------- - float GetSizeX( void ) const { return m_extent.hi.x - m_extent.lo.x; } - float GetSizeY( void ) const { return m_extent.hi.y - m_extent.lo.y; } - const Extent &GetExtent( void ) const { return m_extent; } - const Vector &GetCenter( void ) const { return m_center; } - const Vector &GetCorner( NavCornerType corner ) const; - void SetCorner( NavCornerType corner, const Vector& newPosition ); - void ComputeNormal( Vector *normal, bool alternate = false ) const; ///< Computes the area's normal based on m_extent.lo. If 'alternate' is specified, m_extent.hi is used instead. - - //- approach areas ---------------------------------------------------------------------------------- - struct ApproachInfo - { - NavConnect here; ///< the approach area - NavConnect prev; ///< the area just before the approach area on the path - NavTraverseType prevToHereHow; - NavConnect next; ///< the area just after the approach area on the path - NavTraverseType hereToNextHow; - }; - const ApproachInfo *GetApproachInfo( int i ) const { return &m_approach[i]; } - int GetApproachInfoCount( void ) const { return m_approachCount; } - void ComputeApproachAreas( void ); ///< determine the set of "approach areas" - for map learning - - //- occupy time ------------------------------------------------------------------------------------ - float GetEarliestOccupyTime( int teamID ) const; ///< returns the minimum time for someone of the given team to reach this spot from their spawn - bool IsBattlefront( void ) const { return m_isBattlefront; } ///< true if this area is a "battlefront" - where rushing teams initially meet - - //- player counting -------------------------------------------------------------------------------- - void IncrementPlayerCount( int teamID ); ///< add one player to this area's count - void DecrementPlayerCount( int teamID ); ///< subtract one player from this area's count - void ClearPlayerCount( void ); ///< set the player count to zero - unsigned char GetPlayerCount( int teamID = 0 ) const; ///< return number of players of given team currently within this area (team of zero means any/all) - - //- A* pathfinding algorithm ------------------------------------------------------------------------ - static void MakeNewMarker( void ) { ++m_masterMarker; if (m_masterMarker == 0) m_masterMarker = 1; } - void Mark( void ) { m_marker = m_masterMarker; } - BOOL IsMarked( void ) const { return (m_marker == m_masterMarker) ? true : false; } - - void SetParent( CNavArea *parent, NavTraverseType how = NUM_TRAVERSE_TYPES ) { m_parent = parent; m_parentHow = how; } - CNavArea *GetParent( void ) const { return m_parent; } - NavTraverseType GetParentHow( void ) const { return m_parentHow; } - - bool IsOpen( void ) const; ///< true if on "open list" - void AddToOpenList( void ); ///< add to open list in decreasing value order - void UpdateOnOpenList( void ); ///< a smaller value has been found, update this area on the open list - void RemoveFromOpenList( void ); - static bool IsOpenListEmpty( void ); - static CNavArea *PopOpenList( void ); ///< remove and return the first element of the open list - - bool IsClosed( void ) const; ///< true if on "closed list" - void AddToClosedList( void ); ///< add to the closed list - void RemoveFromClosedList( void ); - - static void ClearSearchLists( void ); ///< clears the open and closed lists for a new search - - void SetTotalCost( float value ) { m_totalCost = value; } - float GetTotalCost( void ) const { return m_totalCost; } - - void SetCostSoFar( float value ) { m_costSoFar = value; } - float GetCostSoFar( void ) const { return m_costSoFar; } - - //- editing ----------------------------------------------------------------------------------------- - void Draw( void ) const; ///< draw area for debugging & editing - void DrawConnectedAreas( void ) const; - void DrawHidingSpots( void ) const; - bool SplitEdit( bool splitAlongX, float splitEdge, CNavArea **outAlpha = NULL, CNavArea **outBeta = NULL ); ///< split this area into two areas at the given edge - bool MergeEdit( CNavArea *adj ); ///< merge this area and given adjacent area - bool SpliceEdit( CNavArea *other ); ///< create a new area between this area and given area - void RaiseCorner( NavCornerType corner, int amount, bool raiseAdjacentCorners = true ); ///< raise/lower a corner (or all corners if corner == NUM_CORNERS) - void PlaceOnGround( NavCornerType corner, float inset = 0.0f ); ///< places a corner (or all corners if corner == NUM_CORNERS) on the ground - NavCornerType GetCornerUnderCursor( void ) const; - bool GetCornerHotspot( NavCornerType corner, Vector hotspot[NUM_CORNERS] ) const; ///< returns true if the corner is under the cursor - - //- ladders ----------------------------------------------------------------------------------------- - void AddLadderUp( CNavLadder *ladder ); - void AddLadderDown( CNavLadder *ladder ); - -private: - friend class CNavMesh; - friend class CNavLadder; - - void Initialize( void ); ///< to keep constructors consistent - static bool m_isReset; ///< if true, don't bother cleaning up in destructor since everything is going away - - /* - extent.lo - nw ne - +-----------+ - | +-->x | - | | | - | v | - | y | - | | - +-----------+ - sw se - extent.hi - */ - - static unsigned int m_nextID; ///< used to allocate unique IDs - unsigned int m_id; ///< unique area ID - Extent m_extent; ///< extents of area in world coords (NOTE: lo.z is not necessarily the minimum Z, but corresponds to Z at point (lo.x, lo.y), etc - Vector m_center; ///< centroid of area - unsigned short m_attributeFlags; ///< set of attribute bit flags (see NavAttributeType) - Place m_place; ///< place descriptor - bool m_isBlocked; ///< if true, some part of the world is preventing movement through this nav area - bool m_isUnderwater; ///< true if the center of the area is underwater - - /// height of the implicit corners - float m_neZ; - float m_swZ; - - //- for hunting ------------------------------------------------------------------------------------- - float m_clearedTimestamp[ MAX_NAV_TEAMS ]; ///< time this area was last "cleared" of enemies - - //- "danger" ---------------------------------------------------------------------------------------- - float m_danger[ MAX_NAV_TEAMS ]; ///< danger of this area, allowing bots to avoid areas where they died in the past - zero is no danger - float m_dangerTimestamp[ MAX_NAV_TEAMS ]; ///< time when danger value was set - used for decaying - void DecayDanger( void ); - - //- hiding spots ------------------------------------------------------------------------------------ - HidingSpotList m_hidingSpotList; - bool IsHidingSpotCollision( const Vector &pos ) const; ///< returns true if an existing hiding spot is too close to given position - - //- encounter spots --------------------------------------------------------------------------------- - SpotEncounterList m_spotEncounterList; ///< list of possible ways to move thru this area, and the spots to look at as we do - void AddSpotEncounters( const CNavArea *from, NavDirType fromDir, const CNavArea *to, NavDirType toDir ); ///< add spot encounter data when moving from area to area - - //- approach areas ---------------------------------------------------------------------------------- - enum { MAX_APPROACH_AREAS = 16 }; - ApproachInfo m_approach[ MAX_APPROACH_AREAS ]; - unsigned char m_approachCount; - - float m_earliestOccupyTime[ MAX_NAV_TEAMS ]; ///< min time to reach this spot from spawn - void ComputeEarliestOccupyTimes( void ); - bool m_isBattlefront; - - unsigned char m_playerCount[ MAX_NAV_TEAMS ]; ///< the number of players currently in this area - - void Strip( void ); ///< remove "analyzed" data from nav area - - //- A* pathfinding algorithm ------------------------------------------------------------------------ - static unsigned int m_masterMarker; - unsigned int m_marker; ///< used to flag the area as visited - CNavArea *m_parent; ///< the area just prior to this on in the search path - NavTraverseType m_parentHow; ///< how we get from parent to us - float m_totalCost; ///< the distance so far plus an estimate of the distance left - float m_costSoFar; ///< distance travelled so far - - static CNavArea *m_openList; - CNavArea *m_nextOpen, *m_prevOpen; ///< only valid if m_openMarker == m_masterMarker - unsigned int m_openMarker; ///< if this equals the current marker value, we are on the open list - - //- connections to adjacent areas ------------------------------------------------------------------- - NavConnectList m_connect[ NUM_DIRECTIONS ]; ///< a list of adjacent areas for each direction - NavLadderConnectList m_ladder[ CNavLadder::NUM_LADDER_DIRECTIONS ]; ///< list of ladders leading up and down from this area - - //--------------------------------------------------------------------------------------------------- - CNavNode *m_node[ NUM_CORNERS ]; ///< nav nodes at each corner of the area - - void ResetNodes( void ); ///< nodes are going away as part of an incremental nav generation - bool HasNodes( void ) const; - - void FinishMerge( CNavArea *adjArea ); ///< recompute internal data once nodes have been adjusted during merge - void MergeAdjacentConnections( CNavArea *adjArea ); ///< for merging with "adjArea" - pick up all of "adjArea"s connections - void AssignNodes( CNavArea *area ); ///< assign internal nodes to the given area - - void FinishSplitEdit( CNavArea *newArea, NavDirType ignoreEdge ); ///< given the portion of the original area, update its internal data - - CUtlLinkedList m_overlapList; ///< list of areas that overlap this area - - void OnDestroyNotify( CNavArea *dead ); ///< invoked when given area is going away - void OnDestroyNotify( CNavLadder *dead ); ///< invoked when given ladder is going away - - CNavArea *m_prevHash, *m_nextHash; ///< for hash table in CNavMesh -}; - -typedef CUtlLinkedList< CNavArea *, int > NavAreaList; -extern NavAreaList TheNavAreaList; - - -//-------------------------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------------------------- -// -// Inlines -// - -//-------------------------------------------------------------------------------------------------------------- -inline bool CNavArea::IsDegenerate( void ) const -{ - return (m_extent.lo.x >= m_extent.hi.x || m_extent.lo.y >= m_extent.hi.y); -} - -//-------------------------------------------------------------------------------------------------------------- -inline CNavArea *CNavArea::GetAdjacentArea( NavDirType dir, int i ) const -{ - int iter; - for( iter = m_connect[dir].Head(); iter != m_connect[dir].InvalidIndex(); iter=m_connect[dir].Next( iter ) ) - { - if (i == 0) - return m_connect[dir][iter].area; - --i; - } - - return NULL; -} - -//-------------------------------------------------------------------------------------------------------------- -inline bool CNavArea::IsOpen( void ) const -{ - return (m_openMarker == m_masterMarker) ? true : false; -} - -//-------------------------------------------------------------------------------------------------------------- -inline bool CNavArea::IsOpenListEmpty( void ) -{ - return (m_openList) ? false : true; -} - -//-------------------------------------------------------------------------------------------------------------- -inline CNavArea *CNavArea::PopOpenList( void ) -{ - if (m_openList) - { - CNavArea *area = m_openList; - - // disconnect from list - area->RemoveFromOpenList(); - - return area; - } - - return NULL; -} - -//-------------------------------------------------------------------------------------------------------------- -inline bool CNavArea::IsClosed( void ) const -{ - if (IsMarked() && !IsOpen()) - return true; - - return false; -} - -//-------------------------------------------------------------------------------------------------------------- -inline void CNavArea::AddToClosedList( void ) -{ - Mark(); -} - -//-------------------------------------------------------------------------------------------------------------- -inline void CNavArea::RemoveFromClosedList( void ) -{ - // since "closed" is defined as visited (marked) and not on open list, do nothing -} - -//-------------------------------------------------------------------------------------------------------------- -inline void CNavArea::SetClearedTimestamp( int teamID ) -{ - m_clearedTimestamp[ teamID % MAX_NAV_TEAMS ] = gpGlobals->curtime; -} - -//-------------------------------------------------------------------------------------------------------------- -inline float CNavArea::GetClearedTimestamp( int teamID ) const -{ - return m_clearedTimestamp[ teamID % MAX_NAV_TEAMS ]; -} - -//-------------------------------------------------------------------------------------------------------------- -inline float CNavArea::GetEarliestOccupyTime( int teamID ) const -{ - return m_earliestOccupyTime[ teamID % MAX_NAV_TEAMS ]; -} - - -//-------------------------------------------------------------------------------------------------------------- -inline bool CNavArea::IsVisible( const Vector &eye, Vector *visSpot ) const -{ - Vector corner; - trace_t result; - CTraceFilterNoNPCsOrPlayer traceFilter( NULL, COLLISION_GROUP_NONE ); - const float offset = 0.75f * HumanHeight; - - // check center first - UTIL_TraceLine( eye, GetCenter() + Vector( 0, 0, offset ), MASK_BLOCKLOS_AND_NPCS, &traceFilter, &result ); - if (result.fraction == 1.0f) - { - // we can see this area - if (visSpot) - { - *visSpot = GetCenter(); - } - return true; - } - - for( int c=0; cIsGenerating() ) - { - return (int)GenerationStepSize; - } - - int snapVal = nav_snap_to_grid.GetInt(); - if ( forceGrid && !snapVal ) - { - snapVal = 1; - } - - if ( snapVal == 0 ) - { - return 0; - } - - int scale = (int)GenerationStepSize; - switch ( snapVal ) - { - case 3: - scale = 1; - break; - case 2: - scale = 5; - break; - case 1: - default: - break; - } - - return scale; -} - - -//-------------------------------------------------------------------------------------------------------------- -Vector CNavMesh::SnapToGrid( const Vector& in, bool snapX, bool snapY, bool forceGrid ) const -{ - int scale = GetGridSize( forceGrid ); - if ( !scale ) - { - return in; - } - - Vector out( in ); - - if ( snapX ) - { - out.x = round( in.x, scale ); - } - - if ( snapY ) - { - out.y = round( in.y, scale ); - } - - return out; -} - - -//-------------------------------------------------------------------------------------------------------------- -float CNavMesh::SnapToGrid( float x, bool forceGrid ) const -{ - int scale = GetGridSize( forceGrid ); - if ( !scale ) - { - return x; - } - - x = round( x, scale ); - return x; -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::GetEditVectors( Vector *pos, Vector *forward ) -{ - if ( !pos || !forward ) - { - return; - } - - CBasePlayer *player = UTIL_GetListenServerHost(); - if ( !player ) - { - return; - } - - Vector dir; - AngleVectors( player->EyeAngles() + player->GetPunchAngle(), forward ); - - *pos = player->EyePosition(); -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Convenience function to find the nav area a player is looking at, for editing commands - */ -bool CNavMesh::GetActiveNavArea( void ) -{ - VPROF( "CNavMesh::GetActiveNavArea" ); - - m_splitAlongX = false; - m_splitEdge = 0.0f; - m_selectedArea = NULL; - m_climbableSurface = false; - m_selectedLadder = NULL; - - CBasePlayer *player = UTIL_GetListenServerHost(); - if ( player == NULL ) - return false; - - const float maxRange = 1000.0f; // 500 - - Vector from, dir; - GetEditVectors( &from, &dir ); - - Vector to = from + maxRange * dir; - - trace_t result; - UTIL_TraceLine( from, to, MASK_PLAYERSOLID_BRUSHONLY, player, COLLISION_GROUP_NONE, &result ); - - if (result.fraction != 1.0f) - { - if ( m_navEditMode != NAV_EDIT_CREATE ) - { - m_climbableSurface = physprops->GetSurfaceData( result.surface.surfaceProps )->game.climbable != 0; - if ( !m_climbableSurface ) - { - m_climbableSurface = (result.contents & CONTENTS_LADDER) != 0; - } - m_surfaceNormal = result.plane.normal; - - if ( m_climbableSurface ) - { - // check if we're on the same plane as the original point when we're building a ladder - if ( m_isCreatingLadder ) - { - if ( m_surfaceNormal != m_ladderNormal ) - { - m_climbableSurface = false; - } - } - - if ( m_surfaceNormal.z > 0.9f ) - { - m_climbableSurface = false; // don't try to build ladders on flat ground - } - } - } - - if ( ( m_climbableSurface && !m_isCreatingLadder ) || m_navEditMode != NAV_EDIT_CREATE ) - { - float closestDistSqr = 200.0f * 200.0f; - - FOR_EACH_LL( m_ladderList, it ) - { - CNavLadder *ladder = m_ladderList[ it ]; - - Vector absMin = ladder->m_bottom; - Vector absMax = ladder->m_top; - - Vector left( 0, 0, 0), right(0, 0, 0), up( 0, 0, 0); - VectorVectors( ladder->GetNormal(), right, up ); - right *= ladder->m_width * 0.5f; - left = -right; - - absMin.x += MIN( left.x, right.x ); - absMin.y += MIN( left.y, right.y ); - - absMax.x += MAX( left.x, right.x ); - absMax.y += MAX( left.y, right.y ); - - Extent e; - e.lo = absMin + Vector( -5, -5, -5 ); - e.hi = absMax + Vector( 5, 5, 5 ); - - if ( e.Contains( m_editCursorPos ) ) - { - m_selectedLadder = ladder; - break; - } - - if ( !m_climbableSurface ) - continue; - - Vector p1 = (ladder->m_bottom + ladder->m_top)/2; - Vector p2 = m_editCursorPos; - float distSqr = p1.DistToSqr( p2 ); - - if ( distSqr < closestDistSqr ) - { - m_selectedLadder = ladder; - closestDistSqr = distSqr; - } - } - } - - m_editCursorPos = result.endpos; - - // find the area the player is pointing at - if ( !m_climbableSurface && !m_selectedLadder ) - { - // Try to clip our trace to nav areas - if ( m_grid ) - { - Vector start = result.startpos; - Vector end = result.endpos + 10.0f * dir; // extend a few units into the ground - Ray_t ray; - ray.Init( start, end, vec3_origin, vec3_origin ); - - float bestDist = 1.0f; - - Extent extent; - extent.lo = extent.hi = start; - extent.Encompass( end ); - - int loX = WorldToGridX( extent.lo.x ); - int loY = WorldToGridY( extent.lo.y ); - int hiX = WorldToGridX( extent.hi.x ); - int hiY = WorldToGridY( extent.hi.y ); - - //int navAreasTouched = 0; - //int gridBucketsTouched = 0; - for( int y = loY; y <= hiY; ++y ) - { - for( int x = loX; x <= hiX; ++x ) - { - NavAreaList &areaGrid = m_grid[ x + y*m_gridSizeX ]; - //++gridBucketsTouched; - - FOR_EACH_LL( areaGrid, it ) - { - //++navAreasTouched; - - CNavArea *area = areaGrid[ it ]; - - Vector nw = area->m_extent.lo; - Vector se = area->m_extent.hi; - Vector ne, sw; - ne.x = se.x; - ne.y = nw.y; - ne.z = area->m_neZ; - sw.x = nw.x; - sw.y = se.y; - sw.z = area->m_swZ; - - float dist = IntersectRayWithTriangle( ray, nw, ne, se, false ); - if ( dist > 0 && dist < bestDist ) - { - m_selectedArea = area; - bestDist = dist; - } - - dist = IntersectRayWithTriangle( ray, se, sw, nw, false ); - if ( dist > 0 && dist < bestDist ) - { - m_selectedArea = area; - bestDist = dist; - } - } - } - } - } - - //engine->Con_NPrintf( 20, "%d areas queried in %d grid buckets, instead of %d areas", navAreasTouched, gridBucketsTouched, TheNavAreaList.Count() ); - - // Failing that, get the closest area to the endpoint - if ( !m_selectedArea ) - { - m_selectedArea = TheNavMesh->GetNearestNavArea( result.endpos, false, 500.0f ); - } - } - - if ( m_selectedArea ) - { - float yaw = player->EyeAngles().y; - while( yaw > 360.0f ) - yaw -= 360.0f; - - while( yaw < 0.0f ) - yaw += 360.0f; - - if ((yaw < 45.0f || yaw > 315.0f) || (yaw > 135.0f && yaw < 225.0f)) - { - m_splitEdge = SnapToGrid( result.endpos.y, true ); - m_splitAlongX = true; - } - else - { - m_splitEdge = SnapToGrid( result.endpos.x, true ); - m_splitAlongX = false; - } - } - - if ( !m_climbableSurface && !m_isCreatingLadder ) - { - m_editCursorPos = SnapToGrid( m_editCursorPos ); - } - - return true; - } - - return false; -} - - -//-------------------------------------------------------------------------------------------------------------- -bool CheckForClimbableSurface( const Vector &start, const Vector &end ) -{ - trace_t result; - UTIL_TraceLine( start, end, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &result ); - - bool climbableSurface = false; - if (result.fraction != 1.0f) - { - climbableSurface = physprops->GetSurfaceData( result.surface.surfaceProps )->game.climbable != 0; - if ( !climbableSurface ) - { - climbableSurface = (result.contents & CONTENTS_LADDER) != 0; - } - } - - return climbableSurface; -} - - -//-------------------------------------------------------------------------------------------------------------- -void StepAlongClimbableSurface( Vector &pos, const Vector &increment, const Vector &probe ) -{ - while ( CheckForClimbableSurface( pos + increment - probe, pos + increment + probe ) ) - { - pos += increment; - } -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavBuildLadder( void ) -{ - if ( m_navEditMode == NAV_EDIT_CREATE || m_isCreatingLadder || !m_climbableSurface ) - { - return; - } - - // We've got a ladder at m_editCursorPos, with a normal of m_surfaceNormal - Vector right, up; - VectorVectors( -m_surfaceNormal, right, up ); - - Vector startPos = m_editCursorPos; - - Vector leftEdge = startPos; - Vector rightEdge = startPos; - Vector topEdge = startPos; - Vector bottomEdge = startPos; - - // trace to the sides to find the width - Vector probe = m_surfaceNormal * -HalfHumanWidth; - const float StepSize = 1.0f; - StepAlongClimbableSurface( leftEdge, right * -StepSize, probe ); - StepAlongClimbableSurface( rightEdge, right * StepSize, probe ); - StepAlongClimbableSurface( topEdge, up * StepSize, probe ); - StepAlongClimbableSurface( bottomEdge, up * -StepSize, probe ); - - Vector2D ladderDir = m_surfaceNormal.AsVector2D(); - - trace_t result; - CNavLadder *ladder = new CNavLadder; - - // compute top & bottom of ladder - ladder->m_top = topEdge; - ladder->m_bottom = bottomEdge; - ladder->m_width = leftEdge.DistTo( rightEdge ); - if ( fabs( ladderDir.x ) > fabs( ladderDir.y ) ) - { - if ( ladderDir.x > 0.0f ) - { - ladder->SetDir( EAST ); - } - else - { - ladder->SetDir( WEST ); - } - } - else - { - if ( ladderDir.y > 0.0f ) - { - ladder->SetDir( SOUTH ); - } - else - { - ladder->SetDir( NORTH ); - } - } - - // adjust top and bottom of ladder to make sure they are reachable - // (cs_office has a crate right in front of the base of a ladder) - Vector along = ladder->m_top - ladder->m_bottom; - float length = along.NormalizeInPlace(); - Vector on, out; - const float minLadderClearance = 32.0f; - - // adjust bottom to bypass blockages - const float inc = 10.0f; - float t; - for( t = 0.0f; t <= length; t += inc ) - { - on = ladder->m_bottom + t * along; - - out = on + ladder->GetNormal() * minLadderClearance; - - UTIL_TraceLine( on, out, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &result ); - - if (result.fraction == 1.0f && !result.startsolid) - { - // found viable ladder bottom - ladder->m_bottom = on; - break; - } - } - - // adjust top to bypass blockages - for( t = 0.0f; t <= length; t += inc ) - { - on = ladder->m_top - t * along; - - out = on + ladder->GetNormal() * minLadderClearance; - - UTIL_TraceLine( on, out, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &result ); - - if (result.fraction == 1.0f && !result.startsolid) - { - // found viable ladder top - ladder->m_top = on; - break; - } - } - - ladder->m_length = (ladder->m_top - ladder->m_bottom).Length(); - - ladder->SetDir( ladder->GetDir() ); // now that we've adjusted the top and bottom, re-check the normal - - ladder->m_bottomArea = NULL; - ladder->m_topForwardArea = NULL; - ladder->m_topLeftArea = NULL; - ladder->m_topRightArea = NULL; - ladder->m_topBehindArea = NULL; - ladder->ConnectGeneratedLadder(); - - // add ladder to global list - m_ladderList.AddToTail( ladder ); -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Flood fills all areas with current place - */ -class PlaceFloodFillFunctor -{ -public: - PlaceFloodFillFunctor( CNavArea *area ) - { - m_initialPlace = area->GetPlace(); - } - - bool operator() ( CNavArea *area ) - { - if (area->GetPlace() != m_initialPlace) - return false; - - area->SetPlace( TheNavMesh->GetNavPlace() ); - - return true; - } - -private: - unsigned int m_initialPlace; -}; - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Called when edit mode has just been enabled - */ -void CNavMesh::OnEditModeStart( void ) -{ -/* - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - const Vector &eye = player->EyePosition(); - Vector forward, right, up; - AngleVectors( player->EyeAngles(), &forward, &right, &up ); - - // darken the world so the edit lines show up clearly - const float screenHalfSize = 1000.0f; - const float screenRange = 50.0f; - Vector upLeft = eye + screenRange * forward + screenHalfSize * (up - right); - Vector upRight = eye + screenRange * forward + screenHalfSize * (up + right); - Vector downLeft = eye + screenRange * forward - screenHalfSize * (up + right); - Vector downRight = eye + screenRange * forward + screenHalfSize * (right - up); - - const int alpha = 200; - NDebugOverlay::Triangle( downLeft, upLeft, upRight, 0, 0, 0, alpha, true, 999999.9f ); - NDebugOverlay::Triangle( downLeft, upRight, downRight, 0, 0, 0, alpha, true, 999999.9f ); -*/ -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Called when edit mode has just been disabled - */ -void CNavMesh::OnEditModeEnd( void ) -{ -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Draw navigation areas and edit them - * @todo Clean the whole edit system up - its structure is legacy from peculiarities in GoldSrc. - */ -void CNavMesh::DrawEditMode( void ) -{ - VPROF( "CNavMesh::DrawEditMode" ); - - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - const float maxRange = 1000.0f; // 500 - -#if DEBUG_NAV_NODES - if ( nav_show_nodes.GetBool() ) - { - for ( CNavNode *node = CNavNode::GetFirst(); node != NULL; node = node->GetNext() ) - { - if ( m_editCursorPos.DistToSqr( *node->GetPosition() ) < 150*150 ) - { - node->Draw(); - } - } - } -#endif // DEBUG_NAV_NODES - - // draw approach points for marked area - if (nav_show_approach_points.GetBool() && GetMarkedArea()) - { - Vector ap; - float halfWidth; - for( int i=0; iGetApproachInfoCount(); ++i ) - { - const CNavArea::ApproachInfo *info = GetMarkedArea()->GetApproachInfo( i ); - - // compute approach point - if (info->hereToNextHow <= GO_WEST) - { - info->here.area->ComputePortal( info->next.area, (NavDirType)info->hereToNextHow, &ap, &halfWidth ); - ap.z = info->next.area->GetZ( ap ); - } - else - { - // use the area's center as an approach point - ap = info->here.area->GetCenter(); - } - - NavDrawLine( ap + Vector( 0, 0, 50 ), ap + Vector( 10, 0, 0 ), NavApproachPointColor ); - NavDrawLine( ap + Vector( 0, 0, 50 ), ap + Vector( -10, 0, 0 ), NavApproachPointColor ); - NavDrawLine( ap + Vector( 0, 0, 50 ), ap + Vector( 0, 10, 0 ), NavApproachPointColor ); - NavDrawLine( ap + Vector( 0, 0, 50 ), ap + Vector( 0, -10, 0 ), NavApproachPointColor ); - } - } - - Vector from, dir; - GetEditVectors( &from, &dir ); - - Vector to = from + maxRange * dir; - - /* IN_PROGRESS: - if ( m_navEditMode != NAV_EDIT_PLACE && nav_snap_to_grid.GetBool() ) - { - Vector center = SnapToGrid( m_editCursorPos ); - - const int GridCount = 3; - const int GridArraySize = GridCount * 2 + 1; - const int GridSize = GetGridSize(); - - // fill in an array of heights for the grid - Vector pos[GridArraySize][GridArraySize]; - int x, y; - for ( x=0; xGetID() ); - NDebugOverlay::ScreenText( 0.5, 0.53, buffer, 255, 255, 0, 128, nav_show_area_info.GetBool() ? 0.1 : 0.5 ); - } - - // draw the ladder we are pointing at and all connected areas - m_selectedLadder->DrawLadder(); - m_selectedLadder->DrawConnectedAreas(); - } - - if ( m_markedLadder && m_navEditMode != NAV_EDIT_PLACE ) - { - // draw the "marked" ladder - m_markedLadder->DrawLadder(); - } - - if ( m_markedArea && m_navEditMode != NAV_EDIT_PLACE ) - { - // draw the "marked" area - m_markedArea->Draw(); - } - - // find the area the player is pointing at - if (m_selectedArea) - { - m_lastSelectedLadder = NULL; - - // if area changed, print its ID - if ( m_selectedArea != m_lastSelectedArea ) - { - m_showAreaInfoTimer.Start( nav_show_area_info.GetFloat() ); - m_lastSelectedArea = m_selectedArea; - } - - if (m_showAreaInfoTimer.HasStarted() && !m_showAreaInfoTimer.IsElapsed() ) - { - char buffer[80]; - char attrib[80]; - char locName[80]; - - if (m_selectedArea->GetPlace()) - { - const char *name = TheNavMesh->PlaceToName( m_selectedArea->GetPlace() ); - if (name) - strcpy( locName, name ); - else - strcpy( locName, "ERROR" ); - } - else - { - locName[0] = '\000'; - } - - if (m_navEditMode == NAV_EDIT_PLACE) - { - attrib[0] = '\000'; - } - else - { - attrib[0] = 0; - int attributes = m_selectedArea->GetAttributes(); - if ( attributes & NAV_MESH_CROUCH ) Q_strncat( attrib, "CROUCH ", sizeof( attrib ), -1 ); - if ( attributes & NAV_MESH_JUMP ) Q_strncat( attrib, "JUMP ", sizeof( attrib ), -1 ); - if ( attributes & NAV_MESH_PRECISE ) Q_strncat( attrib, "PRECISE ", sizeof( attrib ), -1 ); - if ( attributes & NAV_MESH_NO_JUMP ) Q_strncat( attrib, "NO_JUMP ", sizeof( attrib ), -1 ); - if ( attributes & NAV_MESH_STOP ) Q_strncat( attrib, "STOP ", sizeof( attrib ), -1 ); - if ( attributes & NAV_MESH_RUN ) Q_strncat( attrib, "RUN ", sizeof( attrib ), -1 ); - if ( attributes & NAV_MESH_WALK ) Q_strncat( attrib, "WALK ", sizeof( attrib ), -1 ); - if ( attributes & NAV_MESH_AVOID ) Q_strncat( attrib, "AVOID ", sizeof( attrib ), -1 ); - if ( attributes & NAV_MESH_TRANSIENT ) Q_strncat( attrib, "TRANSIENT ", sizeof( attrib ), -1 ); - if ( attributes & NAV_MESH_DONT_HIDE ) Q_strncat( attrib, "DONT_HIDE ", sizeof( attrib ), -1 ); - if ( attributes & NAV_MESH_STAND ) Q_strncat( attrib, "STAND ", sizeof( attrib ), -1 ); - if ( attributes & NAV_MESH_NO_HOSTAGES )Q_strncat( attrib, "NO HOSTAGES ", sizeof( attrib ), -1 ); - if ( m_selectedArea->IsBlocked() ) Q_strncat( attrib, "BLOCKED ", sizeof( attrib ), -1 ); - if ( m_selectedArea->IsUnderwater() ) Q_strncat( attrib, "UNDERWATER ", sizeof( attrib ), -1 ); - } - - Q_snprintf( buffer, sizeof( buffer ), "Area #%d %s %s\n", m_selectedArea->GetID(), locName, attrib ); - NDebugOverlay::ScreenText( 0.5, 0.53, buffer, 255, 255, 0, 128, 0.1 ); - - // do "place painting" - if (m_isPlacePainting) - { - if (m_selectedArea->GetPlace() != TheNavMesh->GetNavPlace()) - { - m_selectedArea->SetPlace( TheNavMesh->GetNavPlace() ); - player->EmitSound( "Bot.EditSwitchOn" ); - } - } - } - - if (m_navEditMode == NAV_EDIT_PLACE) - { - m_selectedArea->DrawConnectedAreas(); - - } - else // normal editing mode - { - // draw split line - const Extent &extent = m_selectedArea->GetExtent(); - - float yaw = player->EyeAngles().y; - while( yaw > 360.0f ) - yaw -= 360.0f; - - while( yaw < 0.0f ) - yaw += 360.0f; - - if (m_splitAlongX) - { - from.x = extent.lo.x; - from.y = m_splitEdge; - from.z = m_selectedArea->GetZ( from ); - - to.x = extent.hi.x; - to.y = m_splitEdge; - to.z = m_selectedArea->GetZ( to ); - } - else - { - from.x = m_splitEdge; - from.y = extent.lo.y; - from.z = m_selectedArea->GetZ( from ); - - to.x = m_splitEdge; - to.y = extent.hi.y; - to.z = m_selectedArea->GetZ( to ); - } - - NavDrawLine( from, to, NavSplitLineColor ); - - // draw the area we are pointing at and all connected areas - m_selectedArea->DrawConnectedAreas(); - } - } - } -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::SetEditMode( bool isPlaceMode ) -{ - if ( isPlaceMode ) - { - m_markedLadder = NULL; - m_markedArea = NULL; - m_markedCorner = NUM_CORNERS; - } - - m_navEditMode = (isPlaceMode)?NAV_EDIT_PLACE:NAV_EDIT_NORMAL; -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::SetPlacePaintingMode( bool painting ) -{ - if ( m_navEditMode == NAV_EDIT_PLACE ) - { - m_markedLadder = NULL; - m_markedArea = NULL; - m_markedCorner = NUM_CORNERS; - - m_isPlacePainting = painting; - } -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::SetMarkedLadder( CNavLadder *ladder ) -{ - m_markedLadder = ladder; - m_markedArea = NULL; - m_markedCorner = NUM_CORNERS; -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::SetMarkedArea( CNavArea *area ) -{ - m_markedLadder = NULL; - m_markedArea = area; - m_markedCorner = NUM_CORNERS; -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavDelete( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode == NAV_EDIT_CREATE || m_isCreatingLadder || m_navEditMode == NAV_EDIT_PLACE ) - return; - - GetActiveNavArea(); - - if ( m_selectedArea ) - { - player->EmitSound( "EDIT_DELETE" ); - TheNavAreaList.FindAndRemove( m_selectedArea ); - delete m_selectedArea; - } - else if ( m_selectedLadder ) - { - player->EmitSound( "EDIT_DELETE" ); - m_ladderList.FindAndRemove( m_selectedLadder ); - delete m_selectedLadder; - } - - StripNavigationAreas(); - - SetMarkedArea( NULL ); // unmark the mark area - m_markedCorner = NUM_CORNERS; // clear the corner selection -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavDeleteMarked( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode == NAV_EDIT_CREATE || m_isCreatingLadder || m_navEditMode == NAV_EDIT_PLACE ) - return; - - CNavArea *markedArea = GetMarkedArea(); - if( markedArea ) - { - player->EmitSound( "EDIT_DELETE" ); - TheNavAreaList.FindAndRemove( markedArea ); - delete markedArea; - } - - StripNavigationAreas(); - - SetMarkedArea( NULL ); // unmark the mark area - m_markedCorner = NUM_CORNERS; // clear the corner selection -} - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavSplit( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode == NAV_EDIT_CREATE || m_isCreatingLadder || m_navEditMode == NAV_EDIT_PLACE ) - return; - - GetActiveNavArea(); - - if ( m_selectedArea ) - { - if (m_selectedArea->SplitEdit( m_splitAlongX, m_splitEdge )) - player->EmitSound( "EDIT_SPLIT.MarkedArea" ); - else - player->EmitSound( "EDIT_SPLIT.NoMarkedArea" ); - } - - StripNavigationAreas(); - - SetMarkedArea( NULL ); // unmark the mark area - m_markedCorner = NUM_CORNERS; // clear the corner selection -} - - -//-------------------------------------------------------------------------------------------------------------- -bool MakeSniperSpots( CNavArea *area ) -{ - if ( !area ) - return false; - - bool splitAlongX; - float splitEdge; - - const float minSplitSize = 2.0f; // ensure the first split is larger than this - - float sizeX = area->GetSizeX(); - float sizeY = area->GetSizeY(); - - if ( sizeX > GenerationStepSize && sizeX > sizeY ) - { - splitEdge = round( area->GetExtent().lo.x, GenerationStepSize ); - if ( splitEdge < area->GetExtent().lo.x + minSplitSize ) - splitEdge += GenerationStepSize; - splitAlongX = false; - } - else if ( sizeY > GenerationStepSize && sizeY > sizeX ) - { - splitEdge = round( area->GetExtent().lo.y, GenerationStepSize ); - if ( splitEdge < area->GetExtent().lo.y + minSplitSize ) - splitEdge += GenerationStepSize; - splitAlongX = true; - } - else - { - return false; - } - - CNavArea *first, *second; - if ( !area->SplitEdit( splitAlongX, splitEdge, &first, &second ) ) - { - return false; - } - - first->Disconnect( second ); - second->Disconnect( first ); - - MakeSniperSpots( first ); - MakeSniperSpots( second ); - - return true; -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavMakeSniperSpots( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode == NAV_EDIT_CREATE || m_isCreatingLadder || m_navEditMode == NAV_EDIT_PLACE ) - return; - - GetActiveNavArea(); - - if ( m_selectedArea ) - { - // recursively split the area - if ( MakeSniperSpots( m_selectedArea ) ) - { - player->EmitSound( "EDIT_SPLIT.MarkedArea" ); - } - else - { - player->EmitSound( "EDIT_SPLIT.NoMarkedArea" ); - } - } - else - { - player->EmitSound( "EDIT_SPLIT.NoMarkedArea" ); - } - - StripNavigationAreas(); - - SetMarkedArea( NULL ); // unmark the mark area - m_markedCorner = NUM_CORNERS; // clear the corner selection -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavMerge( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode == NAV_EDIT_CREATE || m_isCreatingLadder || m_navEditMode == NAV_EDIT_PLACE ) - return; - - GetActiveNavArea(); - - if ( m_selectedArea ) - { - if ( m_markedArea && m_markedArea != m_selectedArea ) - { - if ( m_selectedArea->MergeEdit( GetMarkedArea() ) ) - player->EmitSound( "EDIT_MERGE.Enable" ); - else - player->EmitSound( "EDIT_MERGE.Disable" ); - } - else - { - Msg( "To merge, mark an area, highlight a second area, then invoke the merge command" ); - player->EmitSound( "EDIT_MERGE.Disable" ); - } - } - - StripNavigationAreas(); - - SetMarkedArea( NULL ); // unmark the mark area - m_markedCorner = NUM_CORNERS; // clear the corner selection -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavMark( const CCommand &args ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode == NAV_EDIT_CREATE || m_isCreatingLadder || m_navEditMode == NAV_EDIT_PLACE ) - return; - - GetActiveNavArea(); - - if ( m_markedArea || m_markedLadder ) - { - // Unmark area or ladder - player->EmitSound( "EDIT_MARK.Enable" ); - Msg("Area unmarked.\n"); - SetMarkedArea( NULL ); - } - else if ( args.ArgC() > 1 ) - { - const char *areaIDNameToMark = args[1]; - if( areaIDNameToMark != NULL ) - { - unsigned int areaIDToMark = atoi(areaIDNameToMark); - if( areaIDToMark != 0 ) - { - CNavArea *areaToMark = NULL; - FOR_EACH_LL( TheNavAreaList, nit ) - { - if( TheNavAreaList[nit]->GetID() == areaIDToMark ) - { - areaToMark = TheNavAreaList[nit]; - break; - } - } - if( areaToMark ) - { - SetMarkedArea( areaToMark ); - - int connected = 0; - connected += GetMarkedArea()->GetAdjacentCount( NORTH ); - connected += GetMarkedArea()->GetAdjacentCount( SOUTH ); - connected += GetMarkedArea()->GetAdjacentCount( EAST ); - connected += GetMarkedArea()->GetAdjacentCount( WEST ); - - Msg( "Marked Area is connected to %d other Areas\n", connected ); - } - } - } - } - else if ( m_selectedArea ) - { - // Mark an area - player->EmitSound( "EDIT_MARK.Disable" ); - SetMarkedArea( m_selectedArea ); - - int connected = 0; - connected += GetMarkedArea()->GetAdjacentCount( NORTH ); - connected += GetMarkedArea()->GetAdjacentCount( SOUTH ); - connected += GetMarkedArea()->GetAdjacentCount( EAST ); - connected += GetMarkedArea()->GetAdjacentCount( WEST ); - - Msg( "Marked Area is connected to %d other Areas\n", connected ); - } - else if ( m_selectedLadder ) - { - // Mark a ladder - player->EmitSound( "EDIT_MARK.Disable" ); - SetMarkedLadder( m_selectedLadder ); - - int connected = 0; - connected += m_markedLadder->m_topForwardArea != NULL; - connected += m_markedLadder->m_topLeftArea != NULL; - connected += m_markedLadder->m_topRightArea != NULL; - connected += m_markedLadder->m_topBehindArea != NULL; - connected += m_markedLadder->m_bottomArea != NULL; - - Msg( "Marked Ladder is connected to %d Areas\n", connected ); - } - - m_markedCorner = NUM_CORNERS; // clear the corner selection -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavUnmark( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode == NAV_EDIT_CREATE || m_isCreatingLadder || m_navEditMode == NAV_EDIT_PLACE ) - return; - - player->EmitSound( "EDIT_MARK.Enable" ); - SetMarkedArea( NULL ); // unmark the mark area - m_markedCorner = NUM_CORNERS; // clear the corner selection -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavBeginArea( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode == NAV_EDIT_PLACE ) - { - player->EmitSound( "EDIT_END_AREA.NotCreating" ); - return; - } - - GetActiveNavArea(); - - if (m_navEditMode == NAV_EDIT_CREATE) - { - m_navEditMode = NAV_EDIT_NORMAL; - player->EmitSound( "EDIT_BEGIN_AREA.Creating" ); - } - else if ( m_isCreatingLadder ) - { - m_isCreatingLadder = false; - player->EmitSound( "EDIT_BEGIN_AREA.Creating" ); - } - else if ( m_climbableSurface ) - { - player->EmitSound( "EDIT_BEGIN_AREA.NotCreating" ); - m_isCreatingLadder = true; - - // m_ladderAnchor starting corner - m_ladderAnchor = m_editCursorPos; - m_ladderNormal = m_surfaceNormal; - } - else - { - player->EmitSound( "EDIT_BEGIN_AREA.NotCreating" ); - m_navEditMode = NAV_EDIT_CREATE; - - // m_anchor starting corner - m_anchor = m_editCursorPos; - } - - SetMarkedArea( NULL ); // unmark the mark area - m_markedCorner = NUM_CORNERS; // clear the corner selection -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavEndArea( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode == NAV_EDIT_PLACE ) - { - player->EmitSound( "EDIT_END_AREA.NotCreating" ); - return; - } - - if ( m_navEditMode == NAV_EDIT_CREATE ) - { - // create the new nav area - Vector endPos = m_editCursorPos; - endPos.z = m_anchor.z; - CNavArea *newArea = new CNavArea( m_anchor, endPos ); - TheNavAreaList.AddToTail( newArea ); - TheNavMesh->AddNavArea( newArea ); - player->EmitSound( "EDIT_END_AREA.Creating" ); - - if ( nav_create_place_on_ground.GetBool() ) - { - newArea->PlaceOnGround( NUM_CORNERS ); - } - - // if we have a marked area, inter-connect the two - if (GetMarkedArea()) - { - const Extent &extent = GetMarkedArea()->GetExtent(); - - if (m_anchor.x > extent.hi.x && m_editCursorPos.x > extent.hi.x) - { - GetMarkedArea()->ConnectTo( newArea, EAST ); - newArea->ConnectTo( GetMarkedArea(), WEST ); - } - else if (m_anchor.x < extent.lo.x && m_editCursorPos.x < extent.lo.x) - { - GetMarkedArea()->ConnectTo( newArea, WEST ); - newArea->ConnectTo( GetMarkedArea(), EAST ); - } - else if (m_anchor.y > extent.hi.y && m_editCursorPos.y > extent.hi.y) - { - GetMarkedArea()->ConnectTo( newArea, SOUTH ); - newArea->ConnectTo( GetMarkedArea(), NORTH ); - } - else if (m_anchor.y < extent.lo.y && m_editCursorPos.y < extent.lo.y) - { - GetMarkedArea()->ConnectTo( newArea, NORTH ); - newArea->ConnectTo( GetMarkedArea(), SOUTH ); - } - - // propogate marked area to new area - SetMarkedArea( newArea ); - } - - m_navEditMode = NAV_EDIT_NORMAL; - } - else if ( m_isCreatingLadder ) - { - player->EmitSound( "EDIT_END_AREA.Creating" ); - - // the two points defining the ladder are m_ladderAnchor and m_editCursorPos. The normal is m_ladderNormal. - Vector mins, maxs; - - mins.x = MIN( m_ladderAnchor.x, m_editCursorPos.x ); - mins.y = MIN( m_ladderAnchor.y, m_editCursorPos.y ); - mins.z = MIN( m_ladderAnchor.z, m_editCursorPos.z ); - - maxs.x = MAX( m_ladderAnchor.x, m_editCursorPos.x ); - maxs.y = MAX( m_ladderAnchor.y, m_editCursorPos.y ); - maxs.z = MAX( m_ladderAnchor.z, m_editCursorPos.z ); - - Vector2D ladderDir = m_ladderNormal.AsVector2D(); - CreateLadder( mins, maxs, &ladderDir ); - - m_isCreatingLadder = false; - } - else - { - player->EmitSound( "EDIT_END_AREA.NotCreating" ); - } - - m_markedCorner = NUM_CORNERS; // clear the corner selection -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavConnect( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode == NAV_EDIT_CREATE || m_isCreatingLadder || m_navEditMode == NAV_EDIT_PLACE ) - return; - - GetActiveNavArea(); - - if ( m_selectedArea ) - { - if ( m_markedLadder ) - { - m_markedLadder->ConnectTo( m_selectedArea ); - player->EmitSound( "EDIT_CONNECT.Added" ); - } - else if ( m_markedArea ) - { - NavDirType dir = GetMarkedArea()->ComputeDirection( &m_editCursorPos ); - if (dir == NUM_DIRECTIONS) - { - player->EmitSound( "EDIT_CONNECT.AllDirections" ); - } - else - { - m_markedArea->ConnectTo( m_selectedArea, dir ); - player->EmitSound( "EDIT_CONNECT.Added" ); - } - } - else - { - Msg( "To connect areas, mark an area, highlight a second area, then invoke the connect command. Make sure the cursor is directly north, south, east, or west of the marked area." ); - player->EmitSound( "EDIT_CONNECT.AllDirections" ); - } - } - else if ( m_selectedLadder ) - { - if ( m_markedArea ) - { - m_markedArea->ConnectTo( m_selectedLadder ); - player->EmitSound( "EDIT_CONNECT.Added" ); - } - else - { - Msg( "To connect areas, mark an area, highlight a second area, then invoke the connect command. Make sure the cursor is directly north, south, east, or west of the marked area." ); - player->EmitSound( "EDIT_CONNECT.AllDirections" ); - } - } - - SetMarkedArea( NULL ); // unmark the mark area - m_markedCorner = NUM_CORNERS; // clear the corner selection -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavDisconnect( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode == NAV_EDIT_CREATE || m_isCreatingLadder || m_navEditMode == NAV_EDIT_PLACE ) - return; - - GetActiveNavArea(); - - if ( m_selectedArea ) - { - if ( m_markedArea ) - { - m_markedArea->Disconnect( m_selectedArea ); - m_selectedArea->Disconnect( m_markedArea ); - player->EmitSound( "EDIT_DISCONNECT.MarkedArea" ); - } - else - { - if ( m_markedLadder ) - { - m_markedLadder->Disconnect( m_selectedArea ); - m_selectedArea->Disconnect( m_markedLadder ); - player->EmitSound( "EDIT_DISCONNECT.MarkedArea" ); - } - else - { - Msg( "To disconnect areas, mark an area, highlight a second area, then invoke the disconnect command. This will remove all connections between the two areas." ); - player->EmitSound( "EDIT_DISCONNECT.NoMarkedArea" ); - } - } - } - else if ( m_selectedLadder ) - { - if ( m_markedArea ) - { - m_markedArea->Disconnect( m_selectedLadder ); - m_selectedLadder->Disconnect( m_markedArea ); - player->EmitSound( "EDIT_DISCONNECT.MarkedArea" ); - } - else - { - Msg( "To disconnect areas, mark an area, highlight a second area, then invoke the disconnect command. This will remove all connections between the two areas." ); - player->EmitSound( "EDIT_DISCONNECT.NoMarkedArea" ); - } - } - - SetMarkedArea( NULL ); // unmark the mark area - m_markedCorner = NUM_CORNERS; // clear the corner selection -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavSplice( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode == NAV_EDIT_CREATE || m_isCreatingLadder || m_navEditMode == NAV_EDIT_PLACE ) - return; - - GetActiveNavArea(); - - if ( m_selectedArea ) - { - if (GetMarkedArea()) - { - if (m_selectedArea->SpliceEdit( GetMarkedArea() )) - player->EmitSound( "EDIT_SPLICE.MarkedArea" ); - else - player->EmitSound( "EDIT_SPLICE.NoMarkedArea" ); - } - else - { - Msg( "To splice, mark an area, highlight a second area, then invoke the splice command to create an area between them" ); - player->EmitSound( "EDIT_SPLICE.NoMarkedArea" ); - } - } - - SetMarkedArea( NULL ); // unmark the mark area - m_markedCorner = NUM_CORNERS; // clear the corner selection -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavToggleAttribute( NavAttributeType attribute ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode == NAV_EDIT_CREATE || m_isCreatingLadder || m_navEditMode == NAV_EDIT_PLACE ) - return; - - GetActiveNavArea(); - - if ( m_selectedArea ) - { - player->EmitSound( "EDIT.ToggleAttribute" ); - m_selectedArea->SetAttributes( m_selectedArea->GetAttributes() ^ attribute ); - - if ( attribute == NAV_MESH_TRANSIENT ) - { - if ( m_selectedArea->GetAttributes() & NAV_MESH_TRANSIENT ) - { - m_transientAreas.AddToTail( m_selectedArea ); - } - else - { - m_transientAreas.FindAndRemove( m_selectedArea ); - } - } - } - - SetMarkedArea( NULL ); // unmark the mark area - m_markedCorner = NUM_CORNERS; // clear the corner selection -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavTogglePlaceMode( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode == NAV_EDIT_CREATE || m_isCreatingLadder ) - return; - - player->EmitSound( "EDIT_TOGGLE_PLACE_MODE" ); - m_navEditMode = (m_navEditMode == NAV_EDIT_PLACE) ? NAV_EDIT_NORMAL : NAV_EDIT_PLACE; - - SetMarkedArea( NULL ); // unmark the mark area - m_markedCorner = NUM_CORNERS; // clear the corner selection -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavPlaceFloodFill( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode != NAV_EDIT_PLACE ) - return; - - GetActiveNavArea(); - - if ( m_selectedArea ) - { - PlaceFloodFillFunctor pff( m_selectedArea ); - SearchSurroundingAreas( m_selectedArea, m_selectedArea->GetCenter(), pff ); - } - - SetMarkedArea( NULL ); // unmark the mark area - m_markedCorner = NUM_CORNERS; // clear the corner selection -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavPlacePick( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode != NAV_EDIT_PLACE ) - return; - - GetActiveNavArea(); - - if ( m_selectedArea ) - { - player->EmitSound( "EDIT_PLACE_PICK" ); - TheNavMesh->SetNavPlace( m_selectedArea->GetPlace() ); - } - - SetMarkedArea( NULL ); // unmark the mark area - m_markedCorner = NUM_CORNERS; // clear the corner selection -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavTogglePlacePainting( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode != NAV_EDIT_PLACE ) - return; - - GetActiveNavArea(); - - if ( m_selectedArea ) - { - if (m_isPlacePainting) - { - m_isPlacePainting = false; - player->EmitSound( "Bot.EditSwitchOff" ); - } - else - { - m_isPlacePainting = true; - - player->EmitSound( "Bot.EditSwitchOn" ); - - // paint the initial area - m_selectedArea->SetPlace( TheNavMesh->GetNavPlace() ); - } - } - - SetMarkedArea( NULL ); // unmark the mark area - m_markedCorner = NUM_CORNERS; // clear the corner selection -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavMarkUnnamed( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode == NAV_EDIT_CREATE || m_isCreatingLadder || m_navEditMode == NAV_EDIT_PLACE ) - return; - - GetActiveNavArea(); - - if ( m_selectedArea ) - { - if (GetMarkedArea()) - { - player->EmitSound( "EDIT_MARK_UNNAMED.Enable" ); - SetMarkedArea( NULL ); - } - else - { - SetMarkedArea( NULL ); - FOR_EACH_LL( TheNavAreaList, it ) - { - CNavArea *area = TheNavAreaList[ it ]; - - if ( area->GetPlace() == 0 ) - { - SetMarkedArea( area ); - break; - } - } - if ( !GetMarkedArea() ) - { - player->EmitSound( "EDIT_MARK_UNNAMED.NoMarkedArea" ); - } - else - { - player->EmitSound( "EDIT_MARK_UNNAMED.MarkedArea" ); - - int connected = 0; - connected += GetMarkedArea()->GetAdjacentCount( NORTH ); - connected += GetMarkedArea()->GetAdjacentCount( SOUTH ); - connected += GetMarkedArea()->GetAdjacentCount( EAST ); - connected += GetMarkedArea()->GetAdjacentCount( WEST ); - - int totalUnnamedAreas = 0; - FOR_EACH_LL( TheNavAreaList, it ) - { - CNavArea *area = TheNavAreaList[ it ]; - if ( area->GetPlace() == 0 ) - { - ++totalUnnamedAreas; - } - } - - Msg( "Marked Area is connected to %d other Areas - there are %d total unnamed areas\n", connected, totalUnnamedAreas ); - } - } - } - - m_markedCorner = NUM_CORNERS; // clear the corner selection -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavPickArea( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode == NAV_EDIT_CREATE || m_isCreatingLadder || m_navEditMode == NAV_EDIT_PLACE ) - return; - - if ( m_markedLadder ) - { - // Unmark ladder - player->EmitSound( "EDIT_MARK.Enable" ); - Msg("Ladder unmarked.\n"); - SetMarkedArea( NULL ); - m_markedCorner = NUM_CORNERS; // clear the corner selection - return; - } - else if ( m_selectedArea ) - { - NavCornerType bestCorner = m_selectedArea->GetCornerUnderCursor(); - - if ( m_markedCorner == bestCorner && m_selectedArea == m_markedArea ) - { - // Unmark area - player->EmitSound( "EDIT_MARK.Enable" ); - Msg("Area unmarked.\n"); - SetMarkedArea( NULL ); - m_markedCorner = NUM_CORNERS; // clear the corner selection - return; - } - - - // Mark an area - SetMarkedArea( m_selectedArea ); - m_markedCorner = bestCorner; - - int connected = 0; - connected += GetMarkedArea()->GetAdjacentCount( NORTH ); - connected += GetMarkedArea()->GetAdjacentCount( SOUTH ); - connected += GetMarkedArea()->GetAdjacentCount( EAST ); - connected += GetMarkedArea()->GetAdjacentCount( WEST ); - - player->EmitSound( "EDIT_MARK.Disable" ); - Msg( "Marked Area is connected to %d other Areas\n", connected ); - } - else if ( m_selectedLadder ) - { - // Mark a ladder - player->EmitSound( "EDIT_MARK.Disable" ); - SetMarkedLadder( m_selectedLadder ); - - int connected = 0; - connected += m_markedLadder->m_topForwardArea != NULL; - connected += m_markedLadder->m_topLeftArea != NULL; - connected += m_markedLadder->m_topRightArea != NULL; - connected += m_markedLadder->m_topBehindArea != NULL; - connected += m_markedLadder->m_bottomArea != NULL; - - Msg( "Marked Ladder is connected to %d Areas\n", connected ); - m_markedCorner = NUM_CORNERS; // clear the corner selection - } -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavResizeHorizontal( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( !m_markedArea ) - { - CommandNavPickArea(); // try to grab an area first - } - - if ( !m_markedArea ) - { - player->EmitSound( "EDIT_END_AREA.Creating" ); - return; - } - - if ( m_navEditMode == NAV_EDIT_RESIZE_HORIZONTAL ) - { - m_navEditMode = NAV_EDIT_NORMAL; - player->EmitSound( "EDIT_BEGIN_AREA.Creating" ); - return; - } - - if ( m_navEditMode != NAV_EDIT_NORMAL ) - { - return; - } - - m_navEditMode = NAV_EDIT_RESIZE_HORIZONTAL; - player->EmitSound( "EDIT_BEGIN_AREA.NotCreating" ); - m_anchor = m_editCursorPos; - if ( nav_snap_to_grid.GetBool() ) - { - m_anchor = SnapToGrid( m_anchor ); - } -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavResizeVertical( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( !m_markedArea ) - { - player->EmitSound( "EDIT_END_AREA.Creating" ); - return; - } - - if ( m_navEditMode == NAV_EDIT_RESIZE_VERTICAL ) - { - m_navEditMode = NAV_EDIT_NORMAL; - player->EmitSound( "EDIT_BEGIN_AREA.Creating" ); - return; - } - - if ( m_navEditMode != NAV_EDIT_NORMAL ) - { - return; - } - - m_navEditMode = NAV_EDIT_RESIZE_VERTICAL; - player->EmitSound( "EDIT_BEGIN_AREA.NotCreating" ); - m_anchor = m_editCursorPos; - if ( nav_snap_to_grid.GetBool() ) - { - m_anchor = SnapToGrid( m_anchor ); - } -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavResizeEnd( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode != NAV_EDIT_RESIZE_HORIZONTAL && m_navEditMode != NAV_EDIT_RESIZE_VERTICAL ) - { - player->EmitSound( "EDIT_END_AREA.Creating" ); - return; - } - - if ( !m_markedArea ) - { - player->EmitSound( "EDIT_END_AREA.Creating" ); - m_navEditMode = NAV_EDIT_NORMAL; - return; - } - - Vector cornerPos = ( m_markedCorner == NUM_CORNERS ) ? m_markedArea->GetCenter() : m_markedArea->GetCorner( m_markedCorner ); - - if ( m_navEditMode == NAV_EDIT_RESIZE_HORIZONTAL ) - { - // find the new pos - Vector from, dir; - GetEditVectors( &from, &dir ); - - const float dist = 10000.0f; - float t = IntersectRayWithAAPlane( from, from + dir * dist, 2, 1.0f, cornerPos.z ); - - if ( t > 0 && t < 1 ) - { - Vector newPos = from + dir * dist * t; - if ( nav_snap_to_grid.GetBool() ) - { - newPos = SnapToGrid( newPos ); - } - m_markedArea->SetCorner( m_markedCorner, newPos ); - } - } - player->EmitSound( "EDIT_END_AREA.NotCreating" ); - m_navEditMode = NAV_EDIT_NORMAL; -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavCornerSelect( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode == NAV_EDIT_CREATE || m_isCreatingLadder || m_navEditMode == NAV_EDIT_PLACE ) - return; - - GetActiveNavArea(); - - if ( m_selectedArea ) - { - if (GetMarkedArea()) - { - int corner = (m_markedCorner + 1) % (NUM_CORNERS + 1); - m_markedCorner = (NavCornerType)corner; - player->EmitSound( "EDIT_SELECT_CORNER.MarkedArea" ); - } - else - { - player->EmitSound( "EDIT_SELECT_CORNER.NoMarkedArea" ); - } - } -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavCornerRaise( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode == NAV_EDIT_CREATE || m_isCreatingLadder || m_navEditMode == NAV_EDIT_PLACE ) - return; - - GetActiveNavArea(); - - if ( m_selectedArea ) - { - if (GetMarkedArea()) - { - GetMarkedArea()->RaiseCorner( m_markedCorner, 1 ); - player->EmitSound( "EDIT_MOVE_CORNER.MarkedArea" ); - } - else - { - player->EmitSound( "EDIT_MOVE_CORNER.NoMarkedArea" ); - } - } -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavCornerLower( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode == NAV_EDIT_CREATE || m_isCreatingLadder || m_navEditMode == NAV_EDIT_PLACE ) - return; - - GetActiveNavArea(); - - if ( m_selectedArea ) - { - if (GetMarkedArea()) - { - GetMarkedArea()->RaiseCorner( m_markedCorner, -1 ); - player->EmitSound( "EDIT_MOVE_CORNER.MarkedArea" ); - } - else - { - player->EmitSound( "EDIT_MOVE_CORNER.NoMarkedArea" ); - } - } -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavCornerPlaceOnGround( const CCommand &args ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode == NAV_EDIT_CREATE || m_isCreatingLadder || m_navEditMode == NAV_EDIT_PLACE ) - return; - - GetActiveNavArea(); - - if ( m_selectedArea ) - { - float inset = 0.0f; - if ( args.ArgC() == 2 ) - inset = atof( args[1] ); - if ( m_markedArea ) - { - m_markedArea->PlaceOnGround( m_markedCorner, inset ); - } - else - { - m_selectedArea->PlaceOnGround( NUM_CORNERS, inset ); - } - player->EmitSound( "EDIT_MOVE_CORNER.MarkedArea" ); - } - else - { - player->EmitSound( "EDIT_MOVE_CORNER.NoMarkedArea" ); - } -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavWarpToMark( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode == NAV_EDIT_CREATE || m_isCreatingLadder || m_navEditMode == NAV_EDIT_PLACE ) - return; - - if (GetMarkedArea()) - { - if ( ( player->IsDead() || player->IsObserver() ) && player->GetObserverMode() == OBS_MODE_ROAMING ) - { - Vector origin = GetMarkedArea()->GetCenter() + Vector( 0, 0, 0.75f * HumanHeight ); - UTIL_SetOrigin( player, origin ); - } - else - { - player->EmitSound( "EDIT_WARP_TO_MARK" ); - } - } - else if (GetMarkedLadder()) - { - CNavLadder *ladder = GetMarkedLadder(); - if ( ( player->IsDead() || player->IsObserver() ) && player->GetObserverMode() == OBS_MODE_ROAMING ) - { - Vector origin = (ladder->m_top + ladder->m_bottom)/2; - origin.x += ladder->GetNormal().x * GenerationStepSize; - origin.y += ladder->GetNormal().y * GenerationStepSize; - UTIL_SetOrigin( player, origin ); - } - else - { - player->EmitSound( "EDIT_WARP_TO_MARK" ); - } - } - else - { - player->EmitSound( "EDIT_WARP_TO_MARK" ); - } -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavLadderFlip( void ) -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - if ( m_navEditMode == NAV_EDIT_CREATE || m_isCreatingLadder || m_navEditMode == NAV_EDIT_PLACE ) - return; - - GetActiveNavArea(); - - if ( m_selectedLadder ) - { - CNavArea *area; - - // flip direction - player->EmitSound( "EDIT_MOVE_CORNER.MarkedArea" ); - m_selectedLadder->SetDir( OppositeDirection( m_selectedLadder->GetDir() ) ); - - // and reverse ladder's area pointers - area = m_selectedLadder->m_topBehindArea; - m_selectedLadder->m_topBehindArea = m_selectedLadder->m_topForwardArea; - m_selectedLadder->m_topForwardArea = area; - - area = m_selectedLadder->m_topRightArea; - m_selectedLadder->m_topRightArea = m_selectedLadder->m_topLeftArea; - m_selectedLadder->m_topLeftArea = area; - } - - SetMarkedArea( NULL ); // unmark the mark area - m_markedCorner = NUM_CORNERS; // clear the corner selection -} - - -//-------------------------------------------------------------------------------------------------------------- diff --git a/game/server/nav_file.cpp b/game/server/nav_file.cpp deleted file mode 100644 index 776a04cf3..000000000 --- a/game/server/nav_file.cpp +++ /dev/null @@ -1,1365 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -// nav_file.cpp -// Reading and writing nav files -// Author: Michael S. Booth (mike@turtlerockstudios.com), January-September 2003 - -#include "cbase.h" -#include "nav_mesh.h" - -#ifdef CSTRIKE_DLL -#include "cs_shareddefs.h" -#include "nav_pathfind.h" -#endif - - -//-------------------------------------------------------------------------------------------------------------- -/// The current version of the nav file format -const unsigned int NavCurrentVersion = 9; - -//-------------------------------------------------------------------------------------------------------------- -// -// The 'place directory' is used to save and load places from -// nav files in a size-efficient manner that also allows for the -// order of the place ID's to change without invalidating the -// nav files. -// -// The place directory is stored in the nav file as a list of -// place name strings. Each nav area then contains an index -// into that directory, or zero if no place has been assigned to -// that area. -// -class PlaceDirectory -{ -public: - - typedef unsigned short IndexType; - - void Reset( void ) - { - m_directory.RemoveAll(); - } - - /// return true if this place is already in the directory - bool IsKnown( Place place ) const - { - return m_directory.HasElement( place ); - } - - /// return the directory index corresponding to this Place (0 = no entry) - IndexType GetIndex( Place place ) const - { - if (place == UNDEFINED_PLACE) - return 0; - - int i = m_directory.Find( place ); - - if (i < 0) - { - Assert( false && "PlaceDirectory::GetIndex failure" ); - return 0; - } - - return (IndexType)(i+1); - } - - /// add the place to the directory if not already known - void AddPlace( Place place ) - { - if (place == UNDEFINED_PLACE) - return; - - Assert( place < 1000 ); - - if (IsKnown( place )) - return; - - m_directory.AddToTail( place ); - } - - /// given an index, return the Place - Place IndexToPlace( IndexType entry ) const - { - if (entry == 0) - return UNDEFINED_PLACE; - - int i = entry-1; - - if (i >= m_directory.Count()) - { - Assert( false && "PlaceDirectory::IndexToPlace: Invalid entry" ); - return UNDEFINED_PLACE; - } - - return m_directory[ i ]; - } - - /// store the directory - void Save( FileHandle_t file ) - { - // store number of entries in directory - IndexType count = (IndexType)m_directory.Count(); - filesystem->Write( &count, sizeof(IndexType), file ); - - // store entries - for( int i=0; iPlaceToName( m_directory[i] ); - - // store string length followed by string itself - unsigned short len = (unsigned short)(strlen( placeName ) + 1); - filesystem->Write( &len, sizeof(unsigned short), file ); - filesystem->Write( placeName, len, file ); - } - } - - /// load the directory - void Load( FileHandle_t file ) - { - // read number of entries - IndexType count; - filesystem->Read( &count, sizeof(IndexType), file ); - - m_directory.RemoveAll(); - - // read each entry - char placeName[256]; - unsigned short len; - for( int i=0; iRead( &len, sizeof(unsigned short), file ); - filesystem->Read( placeName, len, file ); - - AddPlace( TheNavMesh->NameToPlace( placeName ) ); - } - } - -private: - CUtlVector< Place > m_directory; -}; - -static PlaceDirectory placeDirectory; - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Replace extension with "bsp" - */ -char *GetBspFilename( const char *navFilename ) -{ - static char bspFilename[256]; - - Q_snprintf( bspFilename, sizeof( bspFilename ), "maps\\%s.bsp", STRING( gpGlobals->mapname ) ); - - int len = strlen( bspFilename ); - if (len < 3) - return NULL; - - bspFilename[ len-3 ] = 'b'; - bspFilename[ len-2 ] = 's'; - bspFilename[ len-1 ] = 'p'; - - return bspFilename; -} - -//-------------------------------------------------------------------------------------------------------------- -/* -void CNavArea::Save( FILE *fp ) const -{ - fprintf( fp, "v %f %f %f\n", m_extent.lo.x, m_extent.lo.y, m_extent.lo.z ); - fprintf( fp, "v %f %f %f\n", m_extent.hi.x, m_extent.lo.y, m_neZ ); - fprintf( fp, "v %f %f %f\n", m_extent.hi.x, m_extent.hi.y, m_extent.hi.z ); - fprintf( fp, "v %f %f %f\n", m_extent.lo.x, m_extent.hi.y, m_swZ ); - - static int base = 1; - fprintf( fp, "\n\ng %04dArea%s%s%s%s\n", m_id, - (GetAttributes() & BOT_NAV_CROUCH) ? "CROUCH" : "", - (GetAttributes() & BOT_NAV_JUMP) ? "JUMP" : "", - (GetAttributes() & BOT_NAV_PRECISE) ? "PRECISE" : "", - (GetAttributes() & BOT_NAV_NO_JUMP) ? "NO_JUMP" : "" ); - fprintf( fp, "f %d %d %d %d\n\n", base, base+1, base+2, base+3 ); - base += 4; -} -*/ - -//-------------------------------------------------------------------------------------------------------------- -/** - * Save a navigation area to the opened binary stream - */ -void CNavArea::Save( FileHandle_t file, unsigned int version ) const -{ - // save ID - filesystem->Write( &m_id, sizeof(unsigned int), file ); - - // save attribute flags - filesystem->Write( &m_attributeFlags, sizeof(unsigned short), file ); - - // save extent of area - filesystem->Write( &m_extent, 6*sizeof(float), file ); - - // save heights of implicit corners - filesystem->Write( &m_neZ, sizeof(float), file ); - filesystem->Write( &m_swZ, sizeof(float), file ); - - // save connections to adjacent areas - // in the enum order NORTH, EAST, SOUTH, WEST - for( int d=0; dWrite( &count, sizeof(unsigned int), file ); - - FOR_EACH_LL( m_connect[d], it ) - { - NavConnect connect = m_connect[d][ it ]; - filesystem->Write( &connect.area->m_id, sizeof(unsigned int), file ); - } - } - - // - // Store hiding spots for this area - // - unsigned char count; - if (m_hidingSpotList.Count() > 255) - { - count = 255; - Warning( "Warning: NavArea #%d: Truncated hiding spot list to 255\n", m_id ); - } - else - { - count = (unsigned char)m_hidingSpotList.Count(); - } - filesystem->Write( &count, sizeof(unsigned char), file ); - - // store HidingSpot objects - unsigned int saveCount = 0; - FOR_EACH_LL( m_hidingSpotList, hit ) - { - HidingSpot *spot = m_hidingSpotList[ hit ]; - - spot->Save( file, version ); - - // overflow check - if (++saveCount == count) - break; - } - - // - // Save the approach areas for this area - // - - // save number of approach areas - filesystem->Write( &m_approachCount, sizeof(unsigned char), file ); - - // save approach area info - unsigned char type; - unsigned int zero = 0; - for( int a=0; aWrite( &m_approach[a].here.area->m_id, sizeof(unsigned int), file ); - else - filesystem->Write( &zero, sizeof(unsigned int), file ); - - if (m_approach[a].prev.area) - filesystem->Write( &m_approach[a].prev.area->m_id, sizeof(unsigned int), file ); - else - filesystem->Write( &zero, sizeof(unsigned int), file ); - type = (unsigned char)m_approach[a].prevToHereHow; - filesystem->Write( &type, sizeof(unsigned char), file ); - - if (m_approach[a].next.area) - filesystem->Write( &m_approach[a].next.area->m_id, sizeof(unsigned int), file ); - else - filesystem->Write( &zero, sizeof(unsigned int), file ); - type = (unsigned char)m_approach[a].hereToNextHow; - filesystem->Write( &type, sizeof(unsigned char), file ); - } - - // - // Save encounter spots for this area - // - { - // save number of encounter paths for this area - unsigned int count = m_spotEncounterList.Count(); - filesystem->Write( &count, sizeof(unsigned int), file ); - - SpotEncounter *e; - FOR_EACH_LL( m_spotEncounterList, it ) - { - e = m_spotEncounterList[ it ]; - - if (e->from.area) - filesystem->Write( &e->from.area->m_id, sizeof(unsigned int), file ); - else - filesystem->Write( &zero, sizeof(unsigned int), file ); - - unsigned char dir = (unsigned char)e->fromDir; - filesystem->Write( &dir, sizeof(unsigned char), file ); - - if (e->to.area) - filesystem->Write( &e->to.area->m_id, sizeof(unsigned int), file ); - else - filesystem->Write( &zero, sizeof(unsigned int), file ); - - dir = (unsigned char)e->toDir; - filesystem->Write( &dir, sizeof(unsigned char), file ); - - // write list of spots along this path - unsigned char spotCount; - if (e->spotList.Count() > 255) - { - spotCount = 255; - Warning( "Warning: NavArea #%d: Truncated encounter spot list to 255\n", m_id ); - } - else - { - spotCount = (unsigned char)e->spotList.Count(); - } - filesystem->Write( &spotCount, sizeof(unsigned char), file ); - - saveCount = 0; - FOR_EACH_LL( e->spotList, sit ) - { - SpotOrder *order = &e->spotList[ sit ]; - - // order->spot may be NULL if we've loaded a nav mesh that has been edited but not re-analyzed - unsigned int id = (order->spot) ? order->spot->GetID() : 0; - filesystem->Write( &id, sizeof(unsigned int), file ); - - unsigned char t = (unsigned char)(255 * order->t); - filesystem->Write( &t, sizeof(unsigned char), file ); - - // overflow check - if (++saveCount == spotCount) - break; - } - } - } - - // store place dictionary entry - PlaceDirectory::IndexType entry = placeDirectory.GetIndex( GetPlace() ); - filesystem->Write( &entry, sizeof(entry), file ); - - // write out ladder info - int i; - for ( i=0; iWrite( &count, sizeof(unsigned int), file ); - - NavLadderConnect ladder; - FOR_EACH_LL( m_ladder[i], it ) - { - ladder = m_ladder[i][it]; - - unsigned int id = ladder.ladder->GetID(); - filesystem->Write( &id, sizeof( id ), file ); - } - } - - // save earliest occupy times - for( i=0; iWrite( &m_earliestOccupyTime[i], sizeof(m_earliestOccupyTime[i]), file ); - } -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Load a navigation area from the file - */ -void CNavArea::Load( FileHandle_t file, unsigned int version ) -{ - // load ID - filesystem->Read( &m_id, sizeof(unsigned int), file ); - - // update nextID to avoid collisions - if (m_id >= m_nextID) - m_nextID = m_id+1; - - // load attribute flags - if ( version <= 8 ) - { - unsigned char flags = 0; - filesystem->Read( &flags, sizeof(unsigned char), file ); - m_attributeFlags = flags; - } - else - { - filesystem->Read( &m_attributeFlags, sizeof(unsigned short), file ); - } - - // load extent of area - filesystem->Read( &m_extent, 6*sizeof(float), file ); - - m_center.x = (m_extent.lo.x + m_extent.hi.x)/2.0f; - m_center.y = (m_extent.lo.y + m_extent.hi.y)/2.0f; - m_center.z = (m_extent.lo.z + m_extent.hi.z)/2.0f; - - // load heights of implicit corners - filesystem->Read( &m_neZ, sizeof(float), file ); - filesystem->Read( &m_swZ, sizeof(float), file ); - - CheckWaterLevel(); - - // load connections (IDs) to adjacent areas - // in the enum order NORTH, EAST, SOUTH, WEST - for( int d=0; dRead( &count, sizeof(unsigned int), file ); - Assert( result == sizeof(unsigned int) ); - - for( unsigned int i=0; iRead( &connect.id, sizeof(unsigned int), file ); - Assert( result == sizeof(unsigned int) ); - - // don't allow self-referential connections - if ( connect.id != m_id ) - { - m_connect[d].AddToTail( connect ); - } - } - } - - // - // Load hiding spots - // - - // load number of hiding spots - unsigned char hidingSpotCount; - filesystem->Read( &hidingSpotCount, sizeof(unsigned char), file ); - - if (version == 1) - { - // load simple vector array - Vector pos; - for( int h=0; hRead( &pos, 3 * sizeof(float), file ); - - // create new hiding spot and put on master list - HidingSpot *spot = TheNavMesh->CreateHidingSpot(); - spot->SetPosition( pos ); - spot->SetFlags( HidingSpot::IN_COVER ); - m_hidingSpotList.AddToTail( spot ); - } - } - else - { - // load HidingSpot objects for this area - for( int h=0; hCreateHidingSpot(); - - spot->Load( file, version ); - - m_hidingSpotList.AddToTail( spot ); - } - } - - // - // Load number of approach areas - // - filesystem->Read( &m_approachCount, sizeof(unsigned char), file ); - - // load approach area info (IDs) - unsigned char type; - for( int a=0; aRead( &m_approach[a].here.id, sizeof(unsigned int), file ); - - filesystem->Read( &m_approach[a].prev.id, sizeof(unsigned int), file ); - filesystem->Read( &type, sizeof(unsigned char), file ); - m_approach[a].prevToHereHow = (NavTraverseType)type; - - filesystem->Read( &m_approach[a].next.id, sizeof(unsigned int), file ); - filesystem->Read( &type, sizeof(unsigned char), file ); - m_approach[a].hereToNextHow = (NavTraverseType)type; - } - - - // - // Load encounter paths for this area - // - unsigned int count; - filesystem->Read( &count, sizeof(unsigned int), file ); - - if (version < 3) - { - // old data, read and discard - for( unsigned int e=0; eRead( &encounter.from.id, sizeof(unsigned int), file ); - filesystem->Read( &encounter.to.id, sizeof(unsigned int), file ); - - filesystem->Read( &encounter.path.from.x, 3 * sizeof(float), file ); - filesystem->Read( &encounter.path.to.x, 3 * sizeof(float), file ); - - // read list of spots along this path - unsigned char spotCount; - filesystem->Read( &spotCount, sizeof(unsigned char), file ); - - for( int s=0; sRead( &pos, 3*sizeof(float), file ); - filesystem->Read( &pos, sizeof(float), file ); - } - } - return; - } - - for( unsigned int e=0; eRead( &encounter->from.id, sizeof(unsigned int), file ); - - unsigned char dir; - filesystem->Read( &dir, sizeof(unsigned char), file ); - encounter->fromDir = static_cast( dir ); - - filesystem->Read( &encounter->to.id, sizeof(unsigned int), file ); - - filesystem->Read( &dir, sizeof(unsigned char), file ); - encounter->toDir = static_cast( dir ); - - // read list of spots along this path - unsigned char spotCount; - filesystem->Read( &spotCount, sizeof(unsigned char), file ); - - SpotOrder order; - for( int s=0; sRead( &order.id, sizeof(unsigned int), file ); - - unsigned char t; - filesystem->Read( &t, sizeof(unsigned char), file ); - - order.t = (float)t/255.0f; - - encounter->spotList.AddToTail( order ); - } - - m_spotEncounterList.AddToTail( encounter ); - } - - if (version < 5) - return; - - // - // Load Place data - // - PlaceDirectory::IndexType entry; - filesystem->Read( &entry, sizeof(entry), file ); - - // convert entry to actual Place - SetPlace( placeDirectory.IndexToPlace( entry ) ); - - if ( version < 7 ) - return; - - // load ladder data - for ( int dir=0; dirRead( &count, sizeof(unsigned int), file ); - { - for( unsigned int i=0; iRead( &connect.id, sizeof(unsigned int), file ); - - bool alreadyConnected = false; - FOR_EACH_LL( m_ladder[dir], j ) - { - if ( m_ladder[dir][j].id == connect.id ) - { - alreadyConnected = true; - break; - } - } - - if ( !alreadyConnected ) - { - m_ladder[dir].AddToTail( connect ); - } - } - } - } - - if ( version < 8 ) - return; - - // load earliest occupy times - for( int i=0; iRead( &m_earliestOccupyTime[i], sizeof(m_earliestOccupyTime[i]), file ); - } -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Convert loaded IDs to pointers - * Make sure all IDs are converted, even if corrupt data is encountered. - */ -NavErrorType CNavArea::PostLoad( void ) -{ - NavErrorType error = NAV_OK; - - for ( int dir=0; dirGetLadders().Find( connect.ladder ) == TheNavMesh->GetLadders().InvalidIndex() ) - { - connect.ladder = TheNavMesh->GetLadderByID( id ); - } - - if (id && connect.ladder == NULL) - { - Msg( "CNavArea::PostLoad: Corrupt navigation ladder data. Cannot connect Navigation Areas.\n" ); - error = NAV_CORRUPT_DATA; - } - } - } - - // connect areas together - for( int d=0; did; - connect->area = TheNavMesh->GetNavAreaByID( id ); - if (id && connect->area == NULL) - { - Msg( "CNavArea::PostLoad: Corrupt navigation data. Cannot connect Navigation Areas.\n" ); - error = NAV_CORRUPT_DATA; - } - } - } - - // resolve approach area IDs - for( int a=0; aGetNavAreaByID( m_approach[a].here.id ); - if (m_approach[a].here.id && m_approach[a].here.area == NULL) - { - Msg( "CNavArea::PostLoad: Corrupt navigation data. Missing Approach Area (here).\n" ); - error = NAV_CORRUPT_DATA; - } - - m_approach[a].prev.area = TheNavMesh->GetNavAreaByID( m_approach[a].prev.id ); - if (m_approach[a].prev.id && m_approach[a].prev.area == NULL) - { - Msg( "CNavArea::PostLoad: Corrupt navigation data. Missing Approach Area (prev).\n" ); - error = NAV_CORRUPT_DATA; - } - - m_approach[a].next.area = TheNavMesh->GetNavAreaByID( m_approach[a].next.id ); - if (m_approach[a].next.id && m_approach[a].next.area == NULL) - { - Msg( "CNavArea::PostLoad: Corrupt navigation data. Missing Approach Area (next).\n" ); - error = NAV_CORRUPT_DATA; - } - } - - // resolve spot encounter IDs - SpotEncounter *e; - FOR_EACH_LL( m_spotEncounterList, it ) - { - e = m_spotEncounterList[ it ]; - - e->from.area = TheNavMesh->GetNavAreaByID( e->from.id ); - if (e->from.area == NULL) - { - Msg( "CNavArea::PostLoad: Corrupt navigation data. Missing \"from\" Navigation Area for Encounter Spot.\n" ); - error = NAV_CORRUPT_DATA; - } - - e->to.area = TheNavMesh->GetNavAreaByID( e->to.id ); - if (e->to.area == NULL) - { - Msg( "CNavArea::PostLoad: Corrupt navigation data. Missing \"to\" Navigation Area for Encounter Spot.\n" ); - error = NAV_CORRUPT_DATA; - } - - if (e->from.area && e->to.area) - { - // compute path - float halfWidth; - ComputePortal( e->to.area, e->toDir, &e->path.to, &halfWidth ); - ComputePortal( e->from.area, e->fromDir, &e->path.from, &halfWidth ); - - const float eyeHeight = HalfHumanHeight; - e->path.from.z = e->from.area->GetZ( e->path.from ) + eyeHeight; - e->path.to.z = e->to.area->GetZ( e->path.to ) + eyeHeight; - } - - // resolve HidingSpot IDs - FOR_EACH_LL( e->spotList, sit ) - { - SpotOrder *order = &e->spotList[ sit ]; - - order->spot = GetHidingSpotByID( order->id ); - if (order->spot == NULL) - { - Msg( "CNavArea::PostLoad: Corrupt navigation data. Missing Hiding Spot\n" ); - error = NAV_CORRUPT_DATA; - } - } - } - - // build overlap list - /// @todo Optimize this - FOR_EACH_LL( TheNavAreaList, nit ) - { - CNavArea *area = TheNavAreaList[ nit ]; - - if (area == this) - continue; - - if (IsOverlapping( area )) - m_overlapList.AddToTail( area ); - } - - return error; -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Determine the earliest time this hiding spot can be reached by either team - */ -void CNavArea::ComputeEarliestOccupyTimes( void ) -{ -#ifdef CSTRIKE_DLL - /// @todo Derive cstrike-specific navigation classes - - for( int i=0; iGetAbsOrigin(), m_center, cost ); - if (travelDistance < 0.0f) - continue; - - float travelTime = travelDistance / playerSpeed; - if (travelTime < m_earliestOccupyTime[ team ]) - { - m_earliestOccupyTime[ team ] = travelTime; - } - } - - - // determine the shortest time it will take a CT to reach this area - team = TEAM_CT % MAX_NAV_TEAMS; - for( spot = gEntList.FindEntityByClassname( NULL, "info_player_counterterrorist" ); - spot; - spot = gEntList.FindEntityByClassname( spot, "info_player_counterterrorist" ) ) - { - float travelDistance = NavAreaTravelDistance( spot->GetAbsOrigin(), m_center, cost ); - if (travelDistance < 0.0f) - continue; - - float travelTime = travelDistance / playerSpeed; - if (travelTime < m_earliestOccupyTime[ team ]) - { - m_earliestOccupyTime[ team ] = travelTime; - } - } - -#else - for( int i=0; iGetNavArea( tSpawn->GetAbsOrigin() ); - if (tArea == NULL) - continue; - - for( ctSpawn = gEntList.FindEntityByClassname( NULL, "info_player_counterterrorist" ); - ctSpawn; - ctSpawn = gEntList.FindEntityByClassname( ctSpawn, "info_player_counterterrorist" ) ) - { - CNavArea *ctArea = TheNavMesh->GetNavArea( ctSpawn->GetAbsOrigin() ); - - if (ctArea == NULL) - continue; - - if (tArea == ctArea) - { - m_isBattlefront = true; - return; - } - - // build path between these two spawn points - assume if path fails, it at least got close - // (ie: imagine spawn points that you jump down from - can't path to) - CNavArea *goalArea = NULL; - NavAreaBuildPath( tArea, ctArea, NULL, cost, &goalArea ); - - if (goalArea == NULL) - continue; - - -/** - * @todo Need to enumerate ALL paths between all pairs of spawn points to find all battlefront areas - */ - - // find the area with the earliest overlapping occupy times - CNavArea *battlefront = NULL; - float earliestTime = 999999.9f; - - const float epsilon = 1.0f; - CNavArea *area; - for( area = goalArea; area; area = area->GetParent() ) - { - if (fabs(area->GetEarliestOccupyTime( TEAM_TERRORIST ) - area->GetEarliestOccupyTime( TEAM_CT )) < epsilon) - { - } - - } - } - } -#endif -#endif -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return the filename for this map's "nav map" file - */ -const char *CNavMesh::GetFilename( void ) const -{ - // filename is local to game dir for Steam, so we need to prepend game dir for regular file save - char gamePath[256]; - engine->GetGameDir( gamePath, 256 ); - - static char filename[256]; - Q_snprintf( filename, sizeof( filename ), "%s\\maps\\%s.nav", gamePath, STRING( gpGlobals->mapname ) ); - - return filename; -} - -//-------------------------------------------------------------------------------------------------------------- -/* -============ -COM_FixSlashes - -Changes all '/' characters into '\' characters, in place. -============ -*/ -inline void COM_FixSlashes( char *pname ) -{ -#ifdef _WIN32 - while ( *pname ) - { - if ( *pname == '/' ) - *pname = '\\'; - pname++; - } -#else - while ( *pname ) - { - if ( *pname == '\\' ) - *pname = '/'; - pname++; - } -#endif -} - -static void WarnIfMeshNeedsAnalysis( void ) -{ - // Quick check to warn about needing to analyze: nav_strip, nav_delete, etc set - // every CNavArea's m_approachCount to 0, and delete their m_spotEncounterList. - // So, if no area has either, odds are good we need an analyze. - { - bool hasApproachAreas = false; - bool hasSpotEncounters = false; - - FOR_EACH_LL( TheNavAreaList, it ) - { - CNavArea *area = TheNavAreaList[ it ]; - if ( area->GetApproachInfoCount() ) - { - hasApproachAreas = true; - } - - if ( area->GetSpotEncounterCount() ) - { - hasSpotEncounters = true; - } - } - - if ( !hasApproachAreas || !hasSpotEncounters ) - { - Warning( "The nav mesh needs a full nav_analyze\n" ); - } - } -} - -/** - * Store Navigation Mesh to a file - */ -bool CNavMesh::Save( void ) const -{ - WarnIfMeshNeedsAnalysis(); - - const char *filename = GetFilename(); - if (filename == NULL) - return false; - - // - // Store the NAV file - // - COM_FixSlashes( const_cast(filename) ); - - // get size of source bsp file for later (before we open the nav file for writing, in - // case of failure) - char *bspFilename = GetBspFilename( filename ); - if (bspFilename == NULL) - { - return false; - } - - FileHandle_t file = filesystem->Open( filename, "wb" ); - - if (!file) - { - return false; - } - - // store "magic number" to help identify this kind of file - unsigned int magic = NAV_MAGIC_NUMBER; - filesystem->Write( &magic, sizeof(unsigned int), file ); - - // store version number of file - // 1 = hiding spots as plain vector array - // 2 = hiding spots as HidingSpot objects - // 3 = Encounter spots use HidingSpot ID's instead of storing vector again - // 4 = Includes size of source bsp file to verify nav data correlation - // ---- Beta Release at V4 ----- - // 5 = Added Place info - // ---- Conversion to Src ------ - // 6 = Added Ladder info - // 7 = Areas store ladder ID's so ladders can have one-way connections - // 8 = Added earliest occupy times (2 floats) to each area - // 9 = Promoted CNavArea's attribute flags to a short - unsigned int version = NavCurrentVersion; - filesystem->Write( &version, sizeof(unsigned int), file ); - - // store the size of source bsp file in the nav file - // so we can test if the bsp changed since the nav file was made - unsigned int bspSize = filesystem->Size( bspFilename ); - DevMsg( "Size of bsp file '%s' is %u bytes.\n", bspFilename, bspSize ); - - filesystem->Write( &bspSize, sizeof(unsigned int), file ); - - - // - // Build a directory of the Places in this map - // - placeDirectory.Reset(); - - FOR_EACH_LL( TheNavAreaList, nit ) - { - CNavArea *area = TheNavAreaList[ nit ]; - - Place place = area->GetPlace(); - - if (place) - { - placeDirectory.AddPlace( place ); - } - } - - placeDirectory.Save( file ); - - - // - // Store navigation areas - // - { - // store number of areas - unsigned int count = TheNavAreaList.Count(); - filesystem->Write( &count, sizeof(unsigned int), file ); - - // store each area - FOR_EACH_LL( TheNavAreaList, it ) - { - CNavArea *area = TheNavAreaList[ it ]; - - area->Save( file, version ); - } - } - - // - // Store ladders - // - { - // store number of ladders - unsigned int count = m_ladderList.Count(); - filesystem->Write( &count, sizeof(unsigned int), file ); - - // store each ladder - FOR_EACH_LL( m_ladderList, it ) - { - CNavLadder *ladder = m_ladderList[ it ]; - - ladder->Save( file, version ); - } - } - - filesystem->Flush( file ); - filesystem->Close( file ); - - unsigned int navSize = filesystem->Size( filename ); - DevMsg( "Size of nav file '%s' is %u bytes.\n", filename, navSize ); - - return true; -} - - -//-------------------------------------------------------------------------------------------------------------- -static NavErrorType CheckNavFile( const char *bspFilename ) -{ - if ( !bspFilename ) - return NAV_CANT_ACCESS_FILE; - - char bspPathname[256]; - char filename[256]; - Q_strncpy( bspPathname, "maps/", sizeof( bspPathname ) ); - Q_strncat( bspPathname, bspFilename, sizeof( bspPathname ), COPY_ALL_CHARACTERS ); - Q_strncpy( filename, bspPathname, sizeof( filename ) ); - Q_SetExtension( filename, ".nav", sizeof( filename ) ); - - bool navIsInBsp = false; - FileHandle_t file = filesystem->Open( filename, "rb", "MOD" ); // this ignores .nav files embedded in the .bsp ... - if ( !file ) - { - navIsInBsp = true; - file = filesystem->Open( filename, "rb", "GAME" ); // ... and this looks for one if it's the only one around. - } - - if (!file) - { - return NAV_CANT_ACCESS_FILE; - } - - // check magic number - int result; - unsigned int magic; - result = filesystem->Read( &magic, sizeof(unsigned int), file ); - if (!result || magic != NAV_MAGIC_NUMBER) - { - filesystem->Close( file ); - return NAV_INVALID_FILE; - } - - // read file version number - unsigned int version; - result = filesystem->Read( &version, sizeof(unsigned int), file ); - if (!result || version > NavCurrentVersion || version < 4) - { - filesystem->Close( file ); - return NAV_BAD_FILE_VERSION; - } - - // get size of source bsp file and verify that the bsp hasn't changed - unsigned int saveBspSize; - filesystem->Read( &saveBspSize, sizeof(unsigned int), file ); - - // verify size - unsigned int bspSize = filesystem->Size( bspPathname ); - - if (bspSize != saveBspSize && !navIsInBsp) - { - return NAV_FILE_OUT_OF_DATE; - } - - return NAV_OK; -} - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavCheckFileConsistency( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - FileFindHandle_t findHandle; - const char *bspFilename = filesystem->FindFirstEx( "maps/*.bsp", "MOD", &findHandle ); - while ( bspFilename ) - { - switch ( CheckNavFile( bspFilename ) ) - { - case NAV_CANT_ACCESS_FILE: - Warning( "Missing nav file for %s\n", bspFilename ); - break; - case NAV_INVALID_FILE: - Warning( "Invalid nav file for %s\n", bspFilename ); - break; - case NAV_BAD_FILE_VERSION: - Warning( "Old nav file for %s\n", bspFilename ); - break; - case NAV_FILE_OUT_OF_DATE: - Warning( "The nav file for %s is built from an old version of the map\n", bspFilename ); - break; - case NAV_OK: - Msg( "The nav file for %s is up-to-date\n", bspFilename ); - break; - default: - break; - } - - bspFilename = filesystem->FindNext( findHandle ); - } - filesystem->FindClose( findHandle ); -} -static ConCommand nav_check_file_consistency( "nav_check_file_consistency", CommandNavCheckFileConsistency, "Scans the maps directory and reports any missing/out-of-date navigation files.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Load AI navigation data from a file - */ -NavErrorType CNavMesh::Load( void ) -{ - // free previous navigation mesh data - Reset(); - placeDirectory.Reset(); - - CNavArea::m_nextID = 1; - - // nav filename is derived from map filename - char filename[256]; - Q_snprintf( filename, sizeof( filename ), "maps\\%s.nav", STRING( gpGlobals->mapname ) ); - - bool navIsInBsp = false; - FileHandle_t file = filesystem->Open( filename, "rb", "MOD" ); // this ignores .nav files embedded in the .bsp ... - if ( !file ) - { - navIsInBsp = true; - file = filesystem->Open( filename, "rb", "GAME" ); // ... and this looks for one if it's the only one around. - } - - if (!file) - { - return NAV_CANT_ACCESS_FILE; - } - - // check magic number - int result; - unsigned int magic; - result = filesystem->Read( &magic, sizeof(unsigned int), file ); - if (!result || magic != NAV_MAGIC_NUMBER) - { - Msg( "Invalid navigation file '%s'.\n", filename ); - filesystem->Close( file ); - return NAV_INVALID_FILE; - } - - // read file version number - unsigned int version; - result = filesystem->Read( &version, sizeof(unsigned int), file ); - if (!result || version > NavCurrentVersion) - { - Msg( "Unknown navigation file version.\n" ); - filesystem->Close( file ); - return NAV_BAD_FILE_VERSION; - } - - if (version >= 4) - { - // get size of source bsp file and verify that the bsp hasn't changed - unsigned int saveBspSize; - filesystem->Read( &saveBspSize, sizeof(unsigned int), file ); - - // verify size - char *bspFilename = GetBspFilename( filename ); - if ( bspFilename == NULL ) - { - filesystem->Close( file ); - return NAV_INVALID_FILE; - } - - unsigned int bspSize = filesystem->Size( bspFilename ); - - if (bspSize != saveBspSize && !navIsInBsp) - { - if ( engine->IsDedicatedServer() ) - { - // Warning doesn't print to the dedicated server console, so we'll use Msg instead - Msg( "The Navigation Mesh was built using a different version of this map.\n" ); - } - else - { - Warning( "The Navigation Mesh was built using a different version of this map.\n" ); - } - m_isFromCurrentMap = false; - } - } - - // load Place directory - if (version >= 5) - { - placeDirectory.Load( file ); - } - - // get number of areas - unsigned int count; - unsigned int i; - result = filesystem->Read( &count, sizeof(unsigned int), file ); - - Extent extent; - extent.lo.x = 9999999999.9f; - extent.lo.y = 9999999999.9f; - extent.hi.x = -9999999999.9f; - extent.hi.y = -9999999999.9f; - - // load the areas and compute total extent - for( i=0; iLoad( file, version ); - TheNavAreaList.AddToTail( area ); - - const Extent &areaExtent = area->GetExtent(); - - // check validity of nav area - if (areaExtent.lo.x >= areaExtent.hi.x || areaExtent.lo.y >= areaExtent.hi.y) - Warning( "WARNING: Degenerate Navigation Area #%d at ( %g, %g, %g )\n", - area->GetID(), area->m_center.x, area->m_center.y, area->m_center.z ); - - if (areaExtent.lo.x < extent.lo.x) - extent.lo.x = areaExtent.lo.x; - if (areaExtent.lo.y < extent.lo.y) - extent.lo.y = areaExtent.lo.y; - if (areaExtent.hi.x > extent.hi.x) - extent.hi.x = areaExtent.hi.x; - if (areaExtent.hi.y > extent.hi.y) - extent.hi.y = areaExtent.hi.y; - } - - // add the areas to the grid - AllocateGrid( extent.lo.x, extent.hi.x, extent.lo.y, extent.hi.y ); - - FOR_EACH_LL( TheNavAreaList, it ) - { - AddNavArea( TheNavAreaList[ it ] ); - } - - - // - // Set up all the ladders - // - if (version >= 6) - { - result = filesystem->Read( &count, sizeof(unsigned int), file ); - - // load the ladders - for( i=0; iLoad( file, version ); - m_ladderList.AddToTail( ladder ); - } - } - else - { - BuildLadders(); - } - - // allow areas to connect to each other, etc - FOR_EACH_LL( TheNavAreaList, pit ) - { - CNavArea *area = TheNavAreaList[ pit ]; - area->PostLoad(); - } - - // allow hiding spots to compute information - FOR_EACH_LL( TheHidingSpotList, hit ) - { - HidingSpot *spot = TheHidingSpotList[ hit ]; - spot->PostLoad(); - } - - if ( version < 8 ) - { - // Old nav meshes need to compute earliest occupy times - FOR_EACH_LL( TheNavAreaList, nit ) - { - CNavArea *area = TheNavAreaList[ nit ]; - area->ComputeEarliestOccupyTimes(); - } - } - - ComputeBattlefrontAreas(); - - // the Navigation Mesh has been successfully loaded - m_isLoaded = true; - - filesystem->Close( file ); - - WarnIfMeshNeedsAnalysis(); - - return NAV_OK; -} diff --git a/game/server/nav_generate.cpp b/game/server/nav_generate.cpp deleted file mode 100644 index 80da8a85a..000000000 --- a/game/server/nav_generate.cpp +++ /dev/null @@ -1,2288 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -// nav_generate.cpp -// Auto-generate a Navigation Mesh by sampling the current map -// Author: Michael S. Booth (mike@turtlerockstudios.com), 2003 - -#include "cbase.h" -#include "util_shared.h" -#include "nav_mesh.h" -#include "nav_node.h" -#include "nav_pathfind.h" -#include "viewport_panel_names.h" - -enum { MAX_BLOCKED_AREAS = 256 }; -static unsigned int blockedID[ MAX_BLOCKED_AREAS ]; -static int blockedIDCount = 0; -static float lastMsgTime = 0.0f; - - -ConVar nav_slope_limit( "nav_slope_limit", "0.7", FCVAR_GAMEDLL, "The ground unit normal's Z component must be greater than this for nav areas to be generated." ); -ConVar nav_restart_after_analysis( "nav_restart_after_analysis", "1", FCVAR_GAMEDLL, "When nav nav_restart_after_analysis finishes, restart the server. Turning this off can cause crashes, but is useful for incremental generation." ); - - -//-------------------------------------------------------------------------------------------------------------- -inline float round( float val, float unit ) -{ - val = val + ((val < 0.0f) ? -unit*0.5f : unit*0.5f); - return (float)( ((int)val) / (int)unit ); -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Shortest path cost, paying attention to "blocked" areas - */ -class ApproachAreaCost -{ -public: - float operator() ( CNavArea *area, CNavArea *fromArea, const CNavLadder *ladder ) - { - // check if this area is "blocked" - for( int i=0; iGetID() == blockedID[i]) - { - return -1.0f; - } - } - - if (fromArea == NULL) - { - // first area in path, no cost - return 0.0f; - } - else - { - // compute distance traveled along path so far - float dist; - - if (ladder) - { - dist = ladder->m_length; - } - else - { - dist = (area->GetCenter() - fromArea->GetCenter()).Length(); - } - - float cost = dist + fromArea->GetCostSoFar(); - - return cost; - } - } -}; - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Determine the set of "approach areas". - * An approach area is an area representing a place where players - * move into/out of our local neighborhood of areas. - * @todo Optimize by search from eye outward and modifying pathfinder to treat all links as bi-directional - */ -void CNavArea::ComputeApproachAreas( void ) -{ - m_approachCount = 0; - - if (nav_quicksave.GetBool()) - return; - - // use the center of the nav area as the "view" point - Vector eye = m_center; - if (TheNavMesh->GetGroundHeight( eye, &eye.z ) == false) - return; - - // approximate eye position - if (GetAttributes() & NAV_MESH_CROUCH) - eye.z += 0.9f * HalfHumanHeight; - else - eye.z += 0.9f * HumanHeight; - - enum { MAX_PATH_LENGTH = 256 }; - CNavArea *path[ MAX_PATH_LENGTH ]; - ApproachAreaCost cost; - - enum SearchType - { - FROM_EYE, ///< start search from our eyepoint outward to farArea - TO_EYE, ///< start search from farArea beack towards our eye - SEARCH_FINISHED - }; - - // - // In order to *completely* enumerate all of the approach areas, we - // need to search from our eyepoint outward, as well as from outwards - // towards our eyepoint - // - for( int searchType = FROM_EYE; searchType != SEARCH_FINISHED; ++searchType ) - { - // - // In order to enumerate all of the approach areas, we need to - // run the algorithm many times, once for each "far away" area - // and keep the union of the approach area sets - // - int it; - for( it = TheNavAreaList.Head(); it != TheNavAreaList.InvalidIndex(); it = TheNavAreaList.Next( it ) ) - { - CNavArea *farArea = TheNavAreaList[ it ]; - - blockedIDCount = 0; - - // skip the small areas - const float minSize = 200.0f; // 150 - const Extent &extent = farArea->GetExtent(); - if (extent.SizeX() < minSize || extent.SizeY() < minSize) - { - continue; - } - - // if we can see 'farArea', try again - the whole point is to go "around the bend", so to speak - if (farArea->IsVisible( eye )) - { - continue; - } - - // - // Keep building paths to farArea and blocking them off until we - // cant path there any more. - // As areas are blocked off, all exits will be enumerated. - // - while( m_approachCount < MAX_APPROACH_AREAS ) - { - CNavArea *from, *to; - - if (searchType == FROM_EYE) - { - // find another path *to* 'farArea' - // we must pathfind from us in order to pick up one-way paths OUT OF our area - from = this; - to = farArea; - } - else // TO_EYE - { - // find another path *from* 'farArea' - // we must pathfind to us in order to pick up one-way paths INTO our area - from = farArea; - to = this; - } - - // build the actual path - if (NavAreaBuildPath( from, to, NULL, cost ) == false) - { - break; - } - - // find number of areas on path - int count = 0; - CNavArea *area; - for( area = to; area; area = area->GetParent() ) - { - ++count; - } - - if (count > MAX_PATH_LENGTH) - { - count = MAX_PATH_LENGTH; - } - - // if the path is only two areas long, there can be no approach points - if (count <= 2) - { - break; - } - - // build path starting from eye - int i = 0; - - if (searchType == FROM_EYE) - { - for( area = to; i < count && area; area = area->GetParent() ) - { - path[ count-i-1 ] = area; - ++i; - } - } - else // TO_EYE - { - for( area = to; i < count && area; area = area->GetParent() ) - { - path[ i++ ] = area; - } - } - - // traverse path to find first area we cannot see (skip the first area) - for( i=1; iIsVisible( eye )) - { - continue; - } - - // we can't see this area - mark this area as "blocked" and unusable by subsequent approach paths - if (blockedIDCount == MAX_BLOCKED_AREAS) - { - Msg( "Overflow computing approach areas for area #%d.\n", m_id ); - return; - } - - // if the area to be blocked is actually farArea, block the one just prior - // (blocking farArea will cause all subsequent pathfinds to fail) - int block = (path[i] == farArea) ? i-1 : i; - - // dont block the start area, or all subsequence pathfinds will fail - if (block == 0) - { - continue; - } - - blockedID[ blockedIDCount++ ] = path[ block ]->GetID(); - - // store new approach area if not already in set - int a; - for( a=0; a= 2) ? path[block-2] : NULL; - - m_approach[ m_approachCount ].here.area = path[block-1]; - m_approach[ m_approachCount ].prevToHereHow = path[block-1]->GetParentHow(); - - m_approach[ m_approachCount ].next.area = path[block]; - m_approach[ m_approachCount ].hereToNextHow = path[block]->GetParentHow(); - - ++m_approachCount; - } - - // we are done with this path - break; - } - } - } - } -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Start at given position and find first area in given direction - */ -inline CNavArea *findFirstAreaInDirection( const Vector *start, NavDirType dir, float range, float beneathLimit, CBaseEntity *traceIgnore = NULL, Vector *closePos = NULL ) -{ - CNavArea *area = NULL; - - Vector pos = *start; - - int end = (int)((range / GenerationStepSize) + 0.5f); - - for( int i=1; i<=end; i++ ) - { - AddDirectionVector( &pos, dir, GenerationStepSize ); - - // make sure we dont look thru the wall - trace_t result; - - UTIL_TraceLine( *start, pos, MASK_PLAYERSOLID_BRUSHONLY, traceIgnore, COLLISION_GROUP_NONE, &result ); - - if (result.fraction < 1.0f) - break; - - area = TheNavMesh->GetNavArea( pos, beneathLimit ); - if (area) - { - if (closePos) - { - closePos->x = pos.x; - closePos->y = pos.y; - closePos->z = area->GetZ( pos.x, pos.y ); - } - - break; - } - } - - return area; -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * For each ladder in the map, create a navigation representation of it. - */ -void CNavMesh::BuildLadders( void ) -{ - // remove any left-over ladders - DestroyLadders(); - - trace_t result; - - CInfoLadder *entity = NULL; - while( (entity = dynamic_cast< CInfoLadder * >(gEntList.FindEntityByClassname( entity, "info_ladder" ))) != NULL ) - { - CreateLadder( entity->WorldAlignMins(), entity->WorldAlignMaxs(), NULL ); - } -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Create a navigation representation of a ladder. - */ -void CNavMesh::CreateLadder( const Vector& absMin, const Vector& absMax, const Vector2D *ladderDir ) -{ - CNavLadder *ladder = new CNavLadder; - - // compute top & bottom of ladder - ladder->m_top.x = (absMin.x + absMax.x) / 2.0f; - ladder->m_top.y = (absMin.y + absMax.y) / 2.0f; - ladder->m_top.z = absMax.z; - - ladder->m_bottom.x = ladder->m_top.x; - ladder->m_bottom.y = ladder->m_top.y; - ladder->m_bottom.z = absMin.z; - - // determine facing - assumes "normal" runged ladder - float xSize = absMax.x - absMin.x; - float ySize = absMax.y - absMin.y; - trace_t result; - if (xSize > ySize) - { - // ladder is facing north or south - determine which way - // "pull in" traceline from bottom and top in case ladder abuts floor and/or ceiling - Vector from = ladder->m_bottom + Vector( 0.0f, GenerationStepSize, GenerationStepSize/2 ); - Vector to = ladder->m_top + Vector( 0.0f, GenerationStepSize, -GenerationStepSize/2 ); - - UTIL_TraceLine( from, to, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &result ); - - if (result.fraction != 1.0f || result.startsolid) - ladder->SetDir( NORTH ); - else - ladder->SetDir( SOUTH ); - - ladder->m_width = xSize; - } - else - { - // ladder is facing east or west - determine which way - Vector from = ladder->m_bottom + Vector( GenerationStepSize, 0.0f, GenerationStepSize/2 ); - Vector to = ladder->m_top + Vector( GenerationStepSize, 0.0f, -GenerationStepSize/2 ); - - UTIL_TraceLine( from, to, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &result ); - - if (result.fraction != 1.0f || result.startsolid) - ladder->SetDir( WEST ); - else - ladder->SetDir( EAST ); - - ladder->m_width = ySize; - } - - // adjust top and bottom of ladder to make sure they are reachable - // (cs_office has a crate right in front of the base of a ladder) - Vector along = ladder->m_top - ladder->m_bottom; - float length = along.NormalizeInPlace(); - Vector on, out; - const float minLadderClearance = 32.0f; - - // adjust bottom to bypass blockages - const float inc = 10.0f; - float t; - for( t = 0.0f; t <= length; t += inc ) - { - on = ladder->m_bottom + t * along; - - out = on + ladder->GetNormal() * minLadderClearance; - - UTIL_TraceLine( on, out, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &result ); - - if (result.fraction == 1.0f && !result.startsolid) - { - // found viable ladder bottom - ladder->m_bottom = on; - break; - } - } - - // adjust top to bypass blockages - for( t = 0.0f; t <= length; t += inc ) - { - on = ladder->m_top - t * along; - - out = on + ladder->GetNormal() * minLadderClearance; - - UTIL_TraceLine( on, out, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &result ); - - if (result.fraction == 1.0f && !result.startsolid) - { - // found viable ladder top - ladder->m_top = on; - break; - } - } - - ladder->m_length = (ladder->m_top - ladder->m_bottom).Length(); - - ladder->SetDir( ladder->GetDir() ); // now that we've adjusted the top and bottom, re-check the normal - - ladder->m_bottomArea = NULL; - ladder->m_topForwardArea = NULL; - ladder->m_topLeftArea = NULL; - ladder->m_topRightArea = NULL; - ladder->m_topBehindArea = NULL; - ladder->ConnectGeneratedLadder(); - - // add ladder to global list - m_ladderList.AddToTail( ladder ); -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavLadder::ConnectGeneratedLadder( void ) -{ - const float nearLadderRange = 75.0f; // 50 - - // - // Find naviagtion area at bottom of ladder - // - - // get approximate postion of player on ladder - Vector center = m_bottom + Vector( 0, 0, GenerationStepSize ); - AddDirectionVector( ¢er, m_dir, HalfHumanWidth ); - - m_bottomArea = TheNavMesh->GetNearestNavArea( center, true ); - if (!m_bottomArea) - { - DevMsg( "ERROR: Unconnected ladder bottom at ( %g, %g, %g )\n", m_bottom.x, m_bottom.y, m_bottom.z ); - } - else - { - // store reference to ladder in the area - m_bottomArea->AddLadderUp( this ); - } - - // - // Find adjacent navigation areas at the top of the ladder - // - - // get approximate postion of player on ladder - center = m_top + Vector( 0, 0, GenerationStepSize ); - AddDirectionVector( ¢er, m_dir, HalfHumanWidth ); - - float beneathLimit = MIN( 120.0f, m_top.z - m_bottom.z + HalfHumanWidth ); - - // find "ahead" area - m_topForwardArea = findFirstAreaInDirection( ¢er, OppositeDirection( m_dir ), nearLadderRange, beneathLimit, NULL ); - if (m_topForwardArea == m_bottomArea) - m_topForwardArea = NULL; - - // find "left" area - m_topLeftArea = findFirstAreaInDirection( ¢er, DirectionLeft( m_dir ), nearLadderRange, beneathLimit, NULL ); - if (m_topLeftArea == m_bottomArea) - m_topLeftArea = NULL; - - // find "right" area - m_topRightArea = findFirstAreaInDirection( ¢er, DirectionRight( m_dir ), nearLadderRange, beneathLimit, NULL ); - if (m_topRightArea == m_bottomArea) - m_topRightArea = NULL; - - // find "behind" area - must look farther, since ladder is against the wall away from this area - m_topBehindArea = findFirstAreaInDirection( ¢er, m_dir, 2.0f*nearLadderRange, beneathLimit, NULL ); - if (m_topBehindArea == m_bottomArea) - m_topBehindArea = NULL; - - // can't include behind area, since it is not used when going up a ladder - if (!m_topForwardArea && !m_topLeftArea && !m_topRightArea) - DevMsg( "ERROR: Unconnected ladder top at ( %g, %g, %g )\n", m_top.x, m_top.y, m_top.z ); - - // store reference to ladder in the area(s) - if (m_topForwardArea) - m_topForwardArea->AddLadderDown( this ); - - if (m_topLeftArea) - m_topLeftArea->AddLadderDown( this ); - - if (m_topRightArea) - m_topRightArea->AddLadderDown( this ); - - if (m_topBehindArea) - { - m_topBehindArea->AddLadderDown( this ); - Disconnect( m_topBehindArea ); - } - - // adjust top of ladder to highest connected area - float topZ = m_bottom.z + 5.0f; - bool topAdjusted = false; - CNavArea *topAreaList[4]; - topAreaList[0] = m_topForwardArea; - topAreaList[1] = m_topLeftArea; - topAreaList[2] = m_topRightArea; - topAreaList[3] = m_topBehindArea; - - for( int a=0; a<4; ++a ) - { - CNavArea *topArea = topAreaList[a]; - if (topArea == NULL) - continue; - - Vector close; - topArea->GetClosestPointOnArea( m_top, &close ); - if (topZ < close.z) - { - topZ = close.z; - topAdjusted = true; - } - } - - if (topAdjusted) - { - m_top.z = topZ; - } - - // - // Determine whether this ladder is "dangling" or not - // "Dangling" ladders are too high to go up - // - if (m_bottomArea) - { - Vector bottomSpot; - m_bottomArea->GetClosestPointOnArea( m_bottom, &bottomSpot ); - if (m_bottom.z - bottomSpot.z > HumanHeight) - { - m_bottomArea->Disconnect( this ); - } - } -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Mark all areas that require a jump to get through them. - * This currently relies on jump areas having extreme slope. - */ -void CNavMesh::MarkJumpAreas( void ) -{ - FOR_EACH_LL( TheNavAreaList, it ) - { - CNavArea *area = TheNavAreaList[ it ]; - if ( !area->HasNodes() ) - continue; - - Vector normal, otherNormal; - area->ComputeNormal( &normal ); - area->ComputeNormal( &otherNormal, true ); - - if (normal.z < nav_slope_limit.GetFloat() || - otherNormal.z < nav_slope_limit.GetFloat()) - { - area->SetAttributes( area->GetAttributes() | NAV_MESH_JUMP ); - } - } -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Jump areas that are connected to only one non-jump area won't be used. Delete them. - */ -void CNavMesh::RemoveUnusedJumpAreas( void ) -{ - CUtlLinkedList< CNavArea *, int > unusedAreas; - - FOR_EACH_LL( TheNavAreaList, it ) - { - CNavArea *testArea = TheNavAreaList[ it ]; - if ( !(testArea->GetAttributes() & NAV_MESH_JUMP) ) - { - continue; - } - - NavConnect connectedArea; - NavLadderConnect connectedLadder; - connectedArea.area = NULL; - connectedLadder.ladder = NULL; - - bool doubleConnected = false; - - // Look at testArea->ladder connections - int i; - for ( i=0; iGetLadderList( (CNavLadder::LadderDirectionType)i ); - if ( !ladderList ) - { - continue; - } - - if ( ladderList->Count() == 0 ) - { - continue; - } - - if ( ladderList->Count() > 1 ) - { - doubleConnected = true; - break; - } - - NavLadderConnect ladderConnect = (*ladderList)[ ladderList->Head() ]; - if ( connectedArea.area || (connectedLadder.ladder && connectedLadder.ladder != ladderConnect.ladder) ) - { - doubleConnected = true; - break; - } - - connectedLadder = ladderConnect; - } - - if ( doubleConnected ) - { - continue; - } - - // Look at testArea->area connections - for ( i=0; iGetAdjacentList( (NavDirType)i ); - if ( !areaList ) - { - continue; - } - - if ( areaList->Count() == 0 ) - { - continue; - } - - FOR_EACH_LL ( (*areaList), ait ) - { - NavConnect areaConnect = (*areaList)[ ait ]; - if ( areaConnect.area->GetAttributes() & NAV_MESH_JUMP ) - { - continue; - } - - if ( connectedLadder.ladder || (connectedArea.area && connectedArea.area != areaConnect.area) ) - { - doubleConnected = true; - break; - } - - connectedArea = areaConnect; - } - } - - if ( doubleConnected ) - { - continue; - } - - // Look at ladder->testArea connections - FOR_EACH_LL( m_ladderList, lit ) - { - CNavLadder *ladder = m_ladderList[lit]; - if ( !ladder ) - { - continue; - } - - if ( !ladder->IsConnected( testArea, CNavLadder::NUM_LADDER_DIRECTIONS ) ) - { - continue; - } - - if ( connectedArea.area ) - { - doubleConnected = true; - break; - } - - if ( ladder == connectedLadder.ladder ) - { - continue; - } - - if ( connectedLadder.ladder ) - { - doubleConnected = true; - break; - } - - connectedLadder.ladder = ladder; - } - - if ( doubleConnected ) - { - continue; - } - - // Look at area->testArea connections - FOR_EACH_LL( TheNavAreaList, ait ) - { - CNavArea *area = TheNavAreaList[ait]; - if ( !area ) - { - continue; - } - - if ( area->GetAttributes() & NAV_MESH_JUMP ) - { - continue; - } - - if ( !area->IsConnected( testArea, NUM_DIRECTIONS ) ) - { - continue; - } - - if ( connectedLadder.ladder ) - { - doubleConnected = true; - break; - } - - if ( area == connectedArea.area ) - { - continue; - } - - if ( connectedArea.area ) - { - doubleConnected = true; - break; - } - - connectedArea.area = area; - } - - if ( doubleConnected ) - { - continue; - } - - // Since we got here, at most one ladder or non-jump area is connected to us, so we can be deleted. - unusedAreas.AddToTail( testArea ); - } - - FOR_EACH_LL( unusedAreas, uit ) - { - CNavArea *areaToDelete = unusedAreas[ uit ]; - TheNavAreaList.FindAndRemove( areaToDelete ); - delete areaToDelete; - } - - StripNavigationAreas(); - - SetMarkedArea( NULL ); // unmark the mark area - m_markedCorner = NUM_CORNERS; // clear the corner selection -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::CommandNavRemoveUnusedJumpAreas( void ) -{ - RemoveUnusedJumpAreas(); -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Recursively chop area in half along X until child areas are roughly square - */ -static void splitX( CNavArea *area ) -{ - if (area->IsRoughlySquare()) - return; - - float split = area->GetSizeX(); - split /= 2.0f; - split += area->GetExtent().lo.x; - - split = TheNavMesh->SnapToGrid( split ); - - const float epsilon = 0.1f; - if (fabs(split - area->GetExtent().lo.x) < epsilon || - fabs(split - area->GetExtent().hi.x) < epsilon) - { - // too small to subdivide - return; - } - - CNavArea *alpha, *beta; - if (area->SplitEdit( false, split, &alpha, &beta )) - { - // split each new area until square - splitX( alpha ); - splitX( beta ); - } -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Recursively chop area in half along Y until child areas are roughly square - */ -static void splitY( CNavArea *area ) -{ - if (area->IsRoughlySquare()) - return; - - float split = area->GetSizeY(); - split /= 2.0f; - split += area->GetExtent().lo.y; - - split = TheNavMesh->SnapToGrid( split ); - - const float epsilon = 0.1f; - if (fabs(split - area->GetExtent().lo.y) < epsilon || - fabs(split - area->GetExtent().hi.y) < epsilon) - { - // too small to subdivide - return; - } - - CNavArea *alpha, *beta; - if (area->SplitEdit( true, split, &alpha, &beta )) - { - // split each new area until square - splitY( alpha ); - splitY( beta ); - } -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Split any long, thin, areas into roughly square chunks. - */ -void CNavMesh::SquareUpAreas( void ) -{ - int it = TheNavAreaList.Head(); - - while( it != TheNavAreaList.InvalidIndex() ) - { - CNavArea *area = TheNavAreaList[ it ]; - - // move the iterator in case the current area is split and deleted - it = TheNavAreaList.Next( it ); - - if (area->HasNodes() && !area->IsRoughlySquare()) - { - // chop this area into square pieces - if (area->GetSizeX() > area->GetSizeY()) - splitX( area ); - else - splitY( area ); - } - } -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Determine if we can "jump down" from given point - */ -inline bool testJumpDown( const Vector *fromPos, const Vector *toPos ) -{ - float dz = fromPos->z - toPos->z; - - // drop can't be too far, or too short (or nonexistant) - if (dz <= JumpCrouchHeight || dz >= DeathDrop) - return false; - - // - // Check LOS out and down - // - // ------+ - // | - // F | - // | - // T - // - - Vector from( fromPos->x, fromPos->y, fromPos->z + HumanHeight ); - Vector to( toPos->x, toPos->y, from.z ); - - trace_t result; - UTIL_TraceLine( from, to, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &result ); - if (result.fraction != 1.0f || result.startsolid) - return false; - - from = to; - to.z = toPos->z + 2.0f; - UTIL_TraceLine( from, to, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &result ); - if (result.fraction != 1.0f || result.startsolid) - return false; - - return true; -} - - -//-------------------------------------------------------------------------------------------------------------- -inline CNavArea *findJumpDownArea( const Vector *fromPos, NavDirType dir ) -{ - Vector start( fromPos->x, fromPos->y, fromPos->z + HalfHumanHeight ); - AddDirectionVector( &start, dir, GenerationStepSize/2.0f ); - - Vector toPos; - CNavArea *downArea = findFirstAreaInDirection( &start, dir, 4.0f * GenerationStepSize, DeathDrop, NULL, &toPos ); - - if (downArea && testJumpDown( fromPos, &toPos )) - return downArea; - - return NULL; -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Define connections between adjacent generated areas - */ -void CNavMesh::ConnectGeneratedAreas( void ) -{ - Msg( "Connecting navigation areas...\n" ); - - FOR_EACH_LL( TheNavAreaList, it ) - { - CNavArea *area = TheNavAreaList[ it ]; - - // scan along edge nodes, stepping one node over into the next area - // for now, only use bi-directional connections - - // north edge - CNavNode *node; - for( node = area->m_node[ NORTH_WEST ]; node != area->m_node[ NORTH_EAST ]; node = node->GetConnectedNode( EAST ) ) - { - CNavNode *adj = node->GetConnectedNode( NORTH ); - - if (adj && adj->GetArea() && adj->GetConnectedNode( SOUTH ) == node) - { - area->ConnectTo( adj->GetArea(), NORTH ); - } - else - { - CNavArea *downArea = findJumpDownArea( node->GetPosition(), NORTH ); - if (downArea && downArea != area) - area->ConnectTo( downArea, NORTH ); - } - } - - // west edge - for( node = area->m_node[ NORTH_WEST ]; node != area->m_node[ SOUTH_WEST ]; node = node->GetConnectedNode( SOUTH ) ) - { - CNavNode *adj = node->GetConnectedNode( WEST ); - - if (adj && adj->GetArea() && adj->GetConnectedNode( EAST ) == node) - { - area->ConnectTo( adj->GetArea(), WEST ); - } - else - { - CNavArea *downArea = findJumpDownArea( node->GetPosition(), WEST ); - if (downArea && downArea != area) - area->ConnectTo( downArea, WEST ); - } - } - - // south edge - this edge's nodes are actually part of adjacent areas - // move one node north, and scan west to east - /// @todo This allows one-node-wide areas - do we want this? - node = area->m_node[ SOUTH_WEST ]; - if ( node ) // pre-existing areas in incremental generates won't have nodes - { - node = node->GetConnectedNode( NORTH ); - } - if (node) - { - CNavNode *end = area->m_node[ SOUTH_EAST ]->GetConnectedNode( NORTH ); - /// @todo Figure out why cs_backalley gets a NULL node in here... - for( ; node && node != end; node = node->GetConnectedNode( EAST ) ) - { - CNavNode *adj = node->GetConnectedNode( SOUTH ); - - if (adj && adj->GetArea() && adj->GetConnectedNode( NORTH ) == node) - { - area->ConnectTo( adj->GetArea(), SOUTH ); - } - else - { - CNavArea *downArea = findJumpDownArea( node->GetPosition(), SOUTH ); - if (downArea && downArea != area) - area->ConnectTo( downArea, SOUTH ); - } - } - } - - // east edge - this edge's nodes are actually part of adjacent areas - node = area->m_node[ NORTH_EAST ]; - if ( node ) // pre-existing areas in incremental generates won't have nodes - { - node = node->GetConnectedNode( WEST ); - } - if (node) - { - CNavNode *end = area->m_node[ SOUTH_EAST ]->GetConnectedNode( WEST ); - for( ; node && node != end; node = node->GetConnectedNode( SOUTH ) ) - { - CNavNode *adj = node->GetConnectedNode( EAST ); - - if (adj && adj->GetArea() && adj->GetConnectedNode( WEST ) == node) - { - area->ConnectTo( adj->GetArea(), EAST ); - } - else - { - CNavArea *downArea = findJumpDownArea( node->GetPosition(), EAST ); - if (downArea && downArea != area) - area->ConnectTo( downArea, EAST ); - } - } - } - } -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Merge areas together to make larger ones (must remain rectangular - convex). - * Areas can only be merged if their attributes match. - */ -void CNavMesh::MergeGeneratedAreas( void ) -{ - Msg( "Merging navigation areas...\n" ); - - bool merged; - - do - { - merged = false; - - FOR_EACH_LL( TheNavAreaList, it ) - { - CNavArea *area = TheNavAreaList[ it ]; - if ( !area->HasNodes() ) - continue; - - // north edge - FOR_EACH_LL( area->m_connect[ NORTH ], nit ) - { - CNavArea *adjArea = area->m_connect[ NORTH ][ nit ].area; - if ( !adjArea->HasNodes() ) // pre-existing areas in incremental generates won't have nodes - continue; - - if (area->m_node[ NORTH_WEST ] == adjArea->m_node[ SOUTH_WEST ] && - area->m_node[ NORTH_EAST ] == adjArea->m_node[ SOUTH_EAST ] && - area->GetAttributes() == adjArea->GetAttributes() && - area->IsCoplanar( adjArea )) - { - // merge vertical - area->m_node[ NORTH_WEST ] = adjArea->m_node[ NORTH_WEST ]; - area->m_node[ NORTH_EAST ] = adjArea->m_node[ NORTH_EAST ]; - - merged = true; - //CONSOLE_ECHO( " Merged (north) areas #%d and #%d\n", area->m_id, adjArea->m_id ); - - area->FinishMerge( adjArea ); - - // restart scan - iterator is invalidated - break; - } - } - - if (merged) - break; - - // south edge - FOR_EACH_LL( area->m_connect[ SOUTH ], sit ) - { - CNavArea *adjArea = area->m_connect[ SOUTH ][ sit ].area; - if ( !adjArea->HasNodes() ) // pre-existing areas in incremental generates won't have nodes - continue; - - if (adjArea->m_node[ NORTH_WEST ] == area->m_node[ SOUTH_WEST ] && - adjArea->m_node[ NORTH_EAST ] == area->m_node[ SOUTH_EAST ] && - area->GetAttributes() == adjArea->GetAttributes() && - area->IsCoplanar( adjArea )) - { - // merge vertical - area->m_node[ SOUTH_WEST ] = adjArea->m_node[ SOUTH_WEST ]; - area->m_node[ SOUTH_EAST ] = adjArea->m_node[ SOUTH_EAST ]; - - merged = true; - //CONSOLE_ECHO( " Merged (south) areas #%d and #%d\n", area->m_id, adjArea->m_id ); - - area->FinishMerge( adjArea ); - - // restart scan - iterator is invalidated - break; - } - - } - - if (merged) - break; - - - // west edge - FOR_EACH_LL( area->m_connect[ WEST ], wit ) - { - CNavArea *adjArea = area->m_connect[ WEST ][ wit ].area; - if ( !adjArea->HasNodes() ) // pre-existing areas in incremental generates won't have nodes - continue; - - if (area->m_node[ NORTH_WEST ] == adjArea->m_node[ NORTH_EAST ] && - area->m_node[ SOUTH_WEST ] == adjArea->m_node[ SOUTH_EAST ] && - area->GetAttributes() == adjArea->GetAttributes() && - area->IsCoplanar( adjArea )) - { - // merge horizontal - area->m_node[ NORTH_WEST ] = adjArea->m_node[ NORTH_WEST ]; - area->m_node[ SOUTH_WEST ] = adjArea->m_node[ SOUTH_WEST ]; - - merged = true; - //CONSOLE_ECHO( " Merged (west) areas #%d and #%d\n", area->m_id, adjArea->m_id ); - - area->FinishMerge( adjArea ); - - // restart scan - iterator is invalidated - break; - } - - } - - if (merged) - break; - - // east edge - FOR_EACH_LL( area->m_connect[ EAST ], eit ) - { - CNavArea *adjArea = area->m_connect[ EAST ][ eit ].area; - if ( !adjArea->HasNodes() ) // pre-existing areas in incremental generates won't have nodes - continue; - - if (adjArea->m_node[ NORTH_WEST ] == area->m_node[ NORTH_EAST ] && - adjArea->m_node[ SOUTH_WEST ] == area->m_node[ SOUTH_EAST ] && - area->GetAttributes() == adjArea->GetAttributes() && - area->IsCoplanar( adjArea )) - { - // merge horizontal - area->m_node[ NORTH_EAST ] = adjArea->m_node[ NORTH_EAST ]; - area->m_node[ SOUTH_EAST ] = adjArea->m_node[ SOUTH_EAST ]; - - merged = true; - //CONSOLE_ECHO( " Merged (east) areas #%d and #%d\n", area->m_id, adjArea->m_id ); - - area->FinishMerge( adjArea ); - - // restart scan - iterator is invalidated - break; - } - } - - if (merged) - break; - } - } - while( merged ); -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Check if an rectangular area of the given size can be - * made starting from the given node as the NW corner. - * Only consider fully connected nodes for this check. - * All of the nodes within the test area must have the same attributes. - * All of the nodes must be approximately co-planar w.r.t the NW node's normal, with the - * exception of 1x1 areas which can be any angle. - */ -bool CNavMesh::TestArea( CNavNode *node, int width, int height ) -{ - Vector normal = *node->GetNormal(); - float d = -DotProduct( normal, *node->GetPosition() ); - - bool nodeCrouch = node->m_crouch[ SOUTH_EAST ]; - unsigned char nodeAttributes = node->GetAttributes() & ~NAV_MESH_CROUCH; - - const float offPlaneTolerance = 5.0f; - - CNavNode *vertNode, *horizNode; - - vertNode = node; - for( int y=0; ym_crouch[ SOUTH_EAST ]; - } - else if ( northEdge && eastEdge ) - { - horizNodeCrouch = horizNode->m_crouch[ SOUTH_EAST ] || horizNode->m_crouch[ SOUTH_WEST ]; - } - else if ( southEdge && westEdge ) - { - horizNodeCrouch = horizNode->m_crouch[ SOUTH_EAST ] || horizNode->m_crouch[ NORTH_EAST ]; - } - else if ( southEdge && eastEdge ) - { - horizNodeCrouch = (horizNode->GetAttributes() & NAV_MESH_CROUCH) != 0; - } - // check sides next - else if ( northEdge ) - { - horizNodeCrouch = horizNode->m_crouch[ SOUTH_EAST ] || horizNode->m_crouch[ SOUTH_WEST ]; - } - else if ( southEdge ) - { - horizNodeCrouch = (horizNode->GetAttributes() & NAV_MESH_CROUCH) != 0; - } - else if ( eastEdge ) - { - horizNodeCrouch = (horizNode->GetAttributes() & NAV_MESH_CROUCH) != 0; - } - else if ( westEdge ) - { - horizNodeCrouch = horizNode->m_crouch[ SOUTH_EAST ] || horizNode->m_crouch[ NORTH_EAST ]; - } - // finally, we have a center node - else - { - horizNodeCrouch = (horizNode->GetAttributes() & NAV_MESH_CROUCH) != 0; - } - - // all nodes must be crouch/non-crouch - if ( nodeCrouch != horizNodeCrouch ) - return false; - - // all nodes must have the same non-crouch attributes - unsigned char horizNodeAttributes = horizNode->GetAttributes() & ~NAV_MESH_CROUCH; - if (horizNodeAttributes != nodeAttributes) - return false; - - if (horizNode->IsCovered()) - return false; - - if (!horizNode->IsClosedCell()) - return false; - - horizNode = horizNode->GetConnectedNode( EAST ); - if (horizNode == NULL) - return false; - - // nodes must lie on/near the plane - if (width > 1 || height > 1) - { - float dist = (float)fabs( DotProduct( *horizNode->GetPosition(), normal ) + d ); - if (dist > offPlaneTolerance) - return false; - } - } - - vertNode = vertNode->GetConnectedNode( SOUTH ); - if (vertNode == NULL) - return false; - - // nodes must lie on/near the plane - if (width > 1 || height > 1) - { - float dist = (float)fabs( DotProduct( *vertNode->GetPosition(), normal ) + d ); - if (dist > offPlaneTolerance) - return false; - } - } - - // check planarity of southern edge - if (width > 1 || height > 1) - { - horizNode = vertNode; - - for( int x=0; xGetConnectedNode( EAST ); - if (horizNode == NULL) - return false; - - // nodes must lie on/near the plane - float dist = (float)fabs( DotProduct( *horizNode->GetPosition(), normal ) + d ); - if (dist > offPlaneTolerance) - return false; - } - } - - return true; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Create a nav area, and mark all nodes it overlaps as "covered" - * NOTE: Nodes on the east and south edges are not included. - * Returns number of nodes covered by this area, or -1 for error; - */ -int CNavMesh::BuildArea( CNavNode *node, int width, int height ) -{ - CNavNode *nwNode = node; - CNavNode *neNode = NULL; - CNavNode *swNode = NULL; - CNavNode *seNode = NULL; - - CNavNode *vertNode = node; - CNavNode *horizNode; - - int coveredNodes = 0; - - for( int y=0; yCover(); - ++coveredNodes; - - horizNode = horizNode->GetConnectedNode( EAST ); - } - - if (y == 0) - neNode = horizNode; - - vertNode = vertNode->GetConnectedNode( SOUTH ); - } - - swNode = vertNode; - - horizNode = vertNode; - for( int x=0; xGetConnectedNode( EAST ); - } - seNode = horizNode; - - if (!nwNode || !neNode || !seNode || !swNode) - { - Error( "BuildArea - NULL node.\n" ); - return -1; - } - - CNavArea *area = new CNavArea( nwNode, neNode, seNode, swNode ); - TheNavAreaList.AddToTail( area ); - - // since all internal nodes have the same attributes, set this area's attributes - area->SetAttributes( node->GetAttributes() ); - - // Check that the node was crouch in the right direction - bool nodeCrouch = node->m_crouch[ SOUTH_EAST ]; - if ( (area->GetAttributes() & NAV_MESH_CROUCH) && !nodeCrouch ) - { - area->SetAttributes( area->GetAttributes() & ~NAV_MESH_CROUCH ); - } - - return coveredNodes; -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * This function uses the CNavNodes that have been sampled from the map to - * generate CNavAreas - rectangular areas of "walkable" space. These areas - * are connected to each other, proving information on know how to move from - * area to area. - * - * This is a "greedy" algorithm that attempts to cover the walkable area - * with the fewest, largest, rectangles. - */ -void CNavMesh::CreateNavAreasFromNodes( void ) -{ - // haven't yet seen a map use larger than 30... - int tryWidth = 50; - int tryHeight = 50; - int uncoveredNodes = CNavNode::GetListLength(); - - while( uncoveredNodes > 0 ) - { - for( CNavNode *node = CNavNode::GetFirst(); node; node = node->GetNext() ) - { - if (node->IsCovered()) - continue; - - if (TestArea( node, tryWidth, tryHeight )) - { - int covered = BuildArea( node, tryWidth, tryHeight ); - if (covered < 0) - { - Error( "Generate: Error - Data corrupt.\n" ); - return; - } - - uncoveredNodes -= covered; - } - } - - if (tryWidth >= tryHeight) - --tryWidth; - else - --tryHeight; - - if (tryWidth <= 0 || tryHeight <= 0) - break; - } - - if ( !TheNavAreaList.Count() ) - { - // If we somehow have no areas, don't try to create an impossibly-large grid - AllocateGrid( 0, 0, 0, 0 ); - return; - } - - Extent extent; - extent.lo.x = 9999999999.9f; - extent.lo.y = 9999999999.9f; - extent.hi.x = -9999999999.9f; - extent.hi.y = -9999999999.9f; - - // compute total extent - FOR_EACH_LL( TheNavAreaList, it ) - { - CNavArea *area = TheNavAreaList[ it ]; - const Extent &areaExtent = area->GetExtent(); - - if (areaExtent.lo.x < extent.lo.x) - extent.lo.x = areaExtent.lo.x; - if (areaExtent.lo.y < extent.lo.y) - extent.lo.y = areaExtent.lo.y; - if (areaExtent.hi.x > extent.hi.x) - extent.hi.x = areaExtent.hi.x; - if (areaExtent.hi.y > extent.hi.y) - extent.hi.y = areaExtent.hi.y; - } - - // add the areas to the grid - AllocateGrid( extent.lo.x, extent.hi.x, extent.lo.y, extent.hi.y ); - - FOR_EACH_LL( TheNavAreaList, git ) - { - AddNavArea( TheNavAreaList[ git ] ); - } - - - ConnectGeneratedAreas(); - MergeGeneratedAreas(); - SquareUpAreas(); - MarkJumpAreas(); - - /// @TODO: incremental generation doesn't create ladders yet - if ( m_generationMode != GENERATE_INCREMENTAL ) - { - FOR_EACH_LL( m_ladderList, lit ) - { - m_ladderList[lit]->ConnectGeneratedLadder(); - } - } -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Initiate the generation process - */ -void CNavMesh::BeginGeneration( bool incremental ) -{ - IGameEvent *event = gameeventmanager->CreateEvent( "nav_generate" ); - if ( event ) - { - gameeventmanager->FireEvent( event ); - } - - engine->ServerCommand( "bot_kick\n" ); - - // Right now, incrementally-generated areas won't connect to existing areas automatically. - // Since this means hand-editing will be necessary, don't do a full analyze. - if ( incremental ) - { - nav_quicksave.SetValue( 1 ); - } - - m_generationState = SAMPLE_WALKABLE_SPACE; - m_sampleTick = 0; - m_generationMode = (incremental) ? GENERATE_INCREMENTAL : GENERATE_FULL; - lastMsgTime = 0.0f; - - // clear any previous mesh - DestroyNavigationMesh( incremental ); - - SetNavPlace( UNDEFINED_PLACE ); - - // build internal representations of ladders, which are used to find new walkable areas - if ( !incremental ) ///< @incremental update doesn't build ladders to avoid overlapping existing ones - { - BuildLadders(); - } - - // start sampling from a spawn point - CBaseEntity *spawn = gEntList.FindEntityByClassname( NULL, GetPlayerSpawnName() ); - - if (spawn && !incremental) - { - // snap it to the sampling grid - Vector pos = spawn->GetAbsOrigin(); - pos.x = TheNavMesh->SnapToGrid( pos.x ); - pos.y = TheNavMesh->SnapToGrid( pos.y ); - - Vector normal; - if (GetGroundHeight( pos, &pos.z, &normal )) - { - m_currentNode = new CNavNode( pos, normal, NULL ); - } - } - else - { - // the system will see this NULL and select the next walkable seed - m_currentNode = NULL; - } - - // if there are no seed points, we can't generate - if (m_walkableSeedList.Count() == 0 && m_currentNode == NULL) - { - m_generationMode = GENERATE_NONE; - Msg( "No valid walkable seed positions. Cannot generate Navigation Mesh.\n" ); - return; - } - - // initialize seed list index - m_seedIdx = m_walkableSeedList.Head(); - - Msg( "Generating Navigation Mesh...\n" ); -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Re-analyze an existing Mesh. Determine Hiding Spots, Encounter Spots, etc. - */ -void CNavMesh::BeginAnalysis( void ) -{ - // Remove and re-add elements in TheNavAreaList, to ensure indices are useful for progress feedback - NavAreaList tmpList; - { - FOR_EACH_LL( TheNavAreaList, it ) - { - tmpList.AddToTail( TheNavAreaList[it] ); - } - } - TheNavAreaList.RemoveAll(); - { - FOR_EACH_LL( tmpList, it ) - { - TheNavAreaList.AddToTail( tmpList[it] ); - } - } - - DestroyHidingSpots(); - m_generationState = FIND_HIDING_SPOTS; - m_generationIndex = TheNavAreaList.Head(); - m_generationMode = GENERATE_ANALYSIS_ONLY; - lastMsgTime = 0.0f; -} - - -//-------------------------------------------------------------------------------------------------------------- -void ShowViewPortPanelToAll( const char * name, bool bShow, KeyValues *data ) -{ - CRecipientFilter filter; - filter.AddAllPlayers(); - filter.MakeReliable(); - - int count = 0; - KeyValues *subkey = NULL; - - if ( data ) - { - subkey = data->GetFirstSubKey(); - while ( subkey ) - { - count++; subkey = subkey->GetNextKey(); - } - - subkey = data->GetFirstSubKey(); // reset - } - - UserMessageBegin( filter, "VGUIMenu" ); - WRITE_STRING( name ); // menu name - WRITE_BYTE( bShow?1:0 ); - WRITE_BYTE( count ); - - // write additional data (be carefull not more than 192 bytes!) - while ( subkey ) - { - WRITE_STRING( subkey->GetName() ); - WRITE_STRING( subkey->GetString() ); - subkey = subkey->GetNextKey(); - } - MessageEnd(); -} - - -//-------------------------------------------------------------------------------------------------------------- -static void AnalysisProgress( const char *msg, int ticks, int current, bool showPercent = true ) -{ - const float MsgInterval = 10.0f; - float now = Plat_FloatTime(); - if ( now > lastMsgTime + MsgInterval ) - { - if ( showPercent && ticks ) - { - Msg( "%s %.0f%%\n", msg, current*100.0f/ticks ); - } - else - { - Msg( "%s\n", msg ); - } - - lastMsgTime = now; - } - - KeyValues *data = new KeyValues("data"); - data->SetString( "msg", msg ); - data->SetInt( "total", ticks ); - data->SetInt( "current", current ); - - ShowViewPortPanelToAll( PANEL_NAV_PROGRESS, true, data ); - - data->deleteThis(); -} - - -//-------------------------------------------------------------------------------------------------------------- -static void HideAnalysisProgress( void ) -{ - KeyValues *data = new KeyValues("data"); - ShowViewPortPanelToAll( PANEL_NAV_PROGRESS, false, data ); - data->deleteThis(); -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Process the auto-generation for 'maxTime' seconds. return false if generation is complete. - */ -bool CNavMesh::UpdateGeneration( float maxTime ) -{ - double startTime = Plat_FloatTime(); - - switch( m_generationState ) - { - //--------------------------------------------------------------------------- - case SAMPLE_WALKABLE_SPACE: - { - AnalysisProgress( "Sampling walkable space...", 100, m_sampleTick / 10, false ); - m_sampleTick = ( m_sampleTick + 1 ) % 1000; - - while ( SampleStep() ) - { - if ( Plat_FloatTime() - startTime > maxTime ) - { - return true; - } - } - - // sampling is complete, now build nav areas - m_generationState = CREATE_AREAS_FROM_SAMPLES; - - return true; - } - - //--------------------------------------------------------------------------- - case CREATE_AREAS_FROM_SAMPLES: - { - Msg( "Creating navigation areas from sampled data...\n" ); - - CreateNavAreasFromNodes(); - DestroyHidingSpots(); - - // Remove and re-add elements in TheNavAreaList, to ensure indices are useful for progress feedback - NavAreaList tmpList; - { - FOR_EACH_LL( TheNavAreaList, it ) - { - tmpList.AddToTail( TheNavAreaList[it] ); - } - } - TheNavAreaList.RemoveAll(); - { - FOR_EACH_LL( tmpList, it ) - { - TheNavAreaList.AddToTail( tmpList[it] ); - } - } - - m_generationState = FIND_HIDING_SPOTS; - m_generationIndex = TheNavAreaList.Head(); - return true; - } - - //--------------------------------------------------------------------------- - case FIND_HIDING_SPOTS: - { - while( m_generationIndex != TheNavAreaList.InvalidIndex() ) - { - CNavArea *area = TheNavAreaList[ m_generationIndex ]; - m_generationIndex = TheNavAreaList.Next( m_generationIndex ); - - area->ComputeHidingSpots(); - - // don't go over our time allotment - if( Plat_FloatTime() - startTime > maxTime ) - { - AnalysisProgress( "Finding hiding spots...", 100, 100 * m_generationIndex / TheNavAreaList.Count() ); - return true; - } - } - - Msg( "Finding hiding spots...DONE\n" ); - - m_generationState = FIND_APPROACH_AREAS; - m_generationIndex = TheNavAreaList.Head(); - return true; - } - - //--------------------------------------------------------------------------- - case FIND_APPROACH_AREAS: - { - while( m_generationIndex != TheNavAreaList.InvalidIndex() ) - { - CNavArea *area = TheNavAreaList[ m_generationIndex ]; - m_generationIndex = TheNavAreaList.Next( m_generationIndex ); - - area->ComputeApproachAreas(); - - // don't go over our time allotment - if( Plat_FloatTime() - startTime > maxTime ) - { - AnalysisProgress( "Finding approach areas...", 100, 100 * m_generationIndex / TheNavAreaList.Count() ); - return true; - } - } - - Msg( "Finding approach areas...DONE\n" ); - - m_generationState = FIND_ENCOUNTER_SPOTS; - m_generationIndex = TheNavAreaList.Head(); - return true; - } - - //--------------------------------------------------------------------------- - case FIND_ENCOUNTER_SPOTS: - { - while( m_generationIndex != TheNavAreaList.InvalidIndex() ) - { - CNavArea *area = TheNavAreaList[ m_generationIndex ]; - m_generationIndex = TheNavAreaList.Next( m_generationIndex ); - - area->ComputeSpotEncounters(); - - // don't go over our time allotment - if( Plat_FloatTime() - startTime > maxTime ) - { - AnalysisProgress( "Finding encounter spots...", 100, 100 * m_generationIndex / TheNavAreaList.Count() ); - return true; - } - } - - Msg( "Finding encounter spots...DONE\n" ); - - m_generationState = FIND_SNIPER_SPOTS; - m_generationIndex = TheNavAreaList.Head(); - return true; - } - - //--------------------------------------------------------------------------- - case FIND_SNIPER_SPOTS: - { - while( m_generationIndex != TheNavAreaList.InvalidIndex() ) - { - CNavArea *area = TheNavAreaList[ m_generationIndex ]; - m_generationIndex = TheNavAreaList.Next( m_generationIndex ); - - area->ComputeSniperSpots(); - - // don't go over our time allotment - if( Plat_FloatTime() - startTime > maxTime ) - { - AnalysisProgress( "Finding sniper spots...", 100, 100 * m_generationIndex / TheNavAreaList.Count() ); - return true; - } - } - - Msg( "Finding sniper spots...DONE\n" ); - - m_generationState = FIND_EARLIEST_OCCUPY_TIMES; - m_generationIndex = TheNavAreaList.Head(); - return true; - } - - //--------------------------------------------------------------------------- - case FIND_EARLIEST_OCCUPY_TIMES: - { - while( m_generationIndex != TheNavAreaList.InvalidIndex() ) - { - CNavArea *area = TheNavAreaList[ m_generationIndex ]; - m_generationIndex = TheNavAreaList.Next( m_generationIndex ); - - area->ComputeEarliestOccupyTimes(); - - // don't go over our time allotment - if( Plat_FloatTime() - startTime > maxTime ) - { - AnalysisProgress( "Finding earliest occupy times...", 100, 100 * m_generationIndex / TheNavAreaList.Count() ); - return true; - } - } - - Msg( "Finding earliest occupy times...DONE\n" ); - - m_generationState = SAVE_NAV_MESH; - m_generationIndex = TheNavAreaList.Head(); - return true; - } - - //--------------------------------------------------------------------------- - case SAVE_NAV_MESH: - { - // generation complete! - Msg( "Generation complete!\n" ); - m_generationMode = GENERATE_NONE; - m_isLoaded = true; - - HideAnalysisProgress(); - - if ( nav_restart_after_analysis.GetBool() ) - { - // save the mesh - if (Save()) - { - Msg( "Navigation map '%s' saved.\n", GetFilename() ); - } - else - { - const char *filename = GetFilename(); - Msg( "ERROR: Cannot save navigation map '%s'.\n", (filename) ? filename : "(null)" ); - } - - engine->ChangeLevel( STRING( gpGlobals->mapname ), NULL ); - } - - return false; - } - - default: - break; - } - - return false; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Define the name of player spawn entities - */ -void CNavMesh::SetPlayerSpawnName( const char *name ) -{ - if (m_spawnName) - { - delete [] m_spawnName; - } - - m_spawnName = new char [ strlen(name) + 1 ]; - strcpy( m_spawnName, name ); -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return name of player spawn entity - */ -const char *CNavMesh::GetPlayerSpawnName( void ) const -{ - if (m_spawnName) - return m_spawnName; - - // default value - return "info_player_start"; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Add a nav node and connect it. - * Node Z positions are ground level. - */ -CNavNode *CNavMesh::AddNode( const Vector &destPos, const Vector &normal, NavDirType dir, CNavNode *source ) -{ - // check if a node exists at this location - CNavNode *node = CNavNode::GetNode( destPos ); - - // if no node exists, create one - bool useNew = false; - if (node == NULL) - { - node = new CNavNode( destPos, normal, source ); - useNew = true; - } - - // connect source node to new node - source->ConnectTo( node, dir ); - - // optimization: if deltaZ changes very little, assume connection is commutative - const float zTolerance = 50.0f; - if (fabs( source->GetPosition()->z - destPos.z ) < zTolerance) - { - node->ConnectTo( source, OppositeDirection( dir ) ); - node->MarkAsVisited( OppositeDirection( dir ) ); - } - - if (useNew) - { - // new node becomes current node - m_currentNode = node; - } - - node->CheckCrouch(); - - return node; -} - -//-------------------------------------------------------------------------------------------------------------- -inline CNavNode *LadderEndSearch( const Vector *pos, NavDirType mountDir ) -{ - Vector center = *pos; - AddDirectionVector( ¢er, mountDir, HalfHumanWidth ); - - // - // Test the ladder dismount point first, then each cardinal direction one and two steps away - // - for( int d=(-1); d<2*NUM_DIRECTIONS; ++d ) - { - Vector tryPos = center; - - if (d >= NUM_DIRECTIONS) - AddDirectionVector( &tryPos, (NavDirType)(d - NUM_DIRECTIONS), 2.0f*GenerationStepSize ); - else if (d >= 0) - AddDirectionVector( &tryPos, (NavDirType)d, GenerationStepSize ); - - // step up a rung, to ensure adjacent floors are below us - tryPos.z += GenerationStepSize; - - tryPos.x = TheNavMesh->SnapToGrid( tryPos.x ); - tryPos.y = TheNavMesh->SnapToGrid( tryPos.y ); - - // adjust height to account for sloping areas - Vector tryNormal; - if (TheNavMesh->GetGroundHeight( tryPos, &tryPos.z, &tryNormal ) == false) - continue; - - // make sure this point is not on the other side of a wall - const float fudge = 2.0f; - trace_t result; - UTIL_TraceLine( center + Vector( 0, 0, fudge ), tryPos + Vector( 0, 0, fudge ), MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &result ); - if (result.fraction != 1.0f || result.startsolid) - continue; - - // if no node exists here, create one and continue the search - if (CNavNode::GetNode( tryPos ) == NULL) - { - return new CNavNode( tryPos, tryNormal, NULL ); - } - } - - return NULL; -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Search the world and build a map of possible movements. - * The algorithm begins at the bot's current location, and does a recursive search - * outwards, tracking all valid steps and generating a directed graph of CNavNodes. - * - * Sample the map one "step" in a cardinal direction to learn the map. - * - * Returns true if sampling needs to continue, or false if done. - */ -bool CNavMesh::SampleStep( void ) -{ - // take a step - while( true ) - { - if (m_currentNode == NULL) - { - // sampling is complete from current seed, try next one - m_currentNode = GetNextWalkableSeedNode(); - - if (m_currentNode == NULL) - { - // search is exhausted - continue search from ends of ladders - FOR_EACH_LL( m_ladderList, it ) - { - CNavLadder *ladder = m_ladderList[ it ]; - - // check ladder bottom - if ((m_currentNode = LadderEndSearch( &ladder->m_bottom, ladder->GetDir() )) != 0) - break; - - // check ladder top - if ((m_currentNode = LadderEndSearch( &ladder->m_top, ladder->GetDir() )) != 0) - break; - } - - if (m_currentNode == NULL) - { - // all seeds exhausted, sampling complete - return false; - } - } - } - - // - // Take a step from this node - // - for( int dir = NORTH; dir < NUM_DIRECTIONS; dir++ ) - { - if (!m_currentNode->HasVisited( (NavDirType)dir )) - { - // have not searched in this direction yet - - // start at current node position - Vector pos = *m_currentNode->GetPosition(); - - // snap to grid - int cx = (int)SnapToGrid( pos.x ); - int cy = (int)SnapToGrid( pos.y ); - - // attempt to move to adjacent node - switch( dir ) - { - case NORTH: cy = (int)(cy - GenerationStepSize); break; - case SOUTH: cy = (int)(cy + GenerationStepSize); break; - case EAST: cx = (int)(cx + GenerationStepSize); break; - case WEST: cx = (int)(cx - GenerationStepSize); break; - } - - pos.x = cx; - pos.y = cy; - - m_generationDir = (NavDirType)dir; - - // mark direction as visited - m_currentNode->MarkAsVisited( m_generationDir ); - - // test if we can move to new position - trace_t result; - Vector from, to; - - // modify position to account for change in ground level during step - to.x = pos.x; - to.y = pos.y; - Vector toNormal; - if (GetGroundHeight( pos, &to.z, &toNormal ) == false) - { - return true; - } - - from = *m_currentNode->GetPosition(); - - Vector fromOrigin = from + Vector( 0, 0, HalfHumanHeight ); - Vector toOrigin = to + Vector( 0, 0, HalfHumanHeight ); - - CTraceFilterWalkableEntities filter( NULL, COLLISION_GROUP_NONE, WALK_THRU_EVERYTHING ); - UTIL_TraceLine( fromOrigin, toOrigin, MASK_PLAYERSOLID_BRUSHONLY, &filter, &result ); - - bool walkable; - - if (result.fraction == 1.0f && !result.startsolid) - { - // the trace didnt hit anything - clear - - float toGround = to.z; - float fromGround = from.z; - - float epsilon = 0.1f; - - // check if ledge is too high to reach or will cause us to fall to our death - if (toGround - fromGround > JumpCrouchHeight + epsilon || fromGround - toGround > DeathDrop) - { - walkable = false; - } - else - { - // check surface normals along this step to see if we would cross any impassable slopes - Vector delta = to - from; - const float inc = 2.0f; - float along = inc; - bool done = false; - float ground; - Vector normal; - - walkable = true; - - while( !done ) - { - Vector p; - - // need to guarantee that we test the exact edges - if (along >= GenerationStepSize) - { - p = to; - done = true; - } - else - { - p = from + delta * (along/GenerationStepSize); - } - - if (GetGroundHeight( p, &ground, &normal ) == false) - { - walkable = false; - break; - } - - // check for maximum allowed slope - if (normal.z < nav_slope_limit.GetFloat()) - { - walkable = false; - break; - } - - along += inc; - } - } - } - else // TraceLine hit something... - { - if (IsEntityWalkable( result.m_pEnt, WALK_THRU_EVERYTHING )) - { - walkable = true; - } - else - { - walkable = false; - } - } - - // if we're incrementally generating, don't overlap existing nav areas - CNavArea *overlap = GetNavArea( to, HumanHeight ); - if ( overlap ) - { - walkable = false; - } - - if (walkable) - { - // we can move here - // create a new navigation node, and update current node pointer - AddNode( to, toNormal, m_generationDir, m_currentNode ); - } - - return true; - } - } - - // all directions have been searched from this node - pop back to its parent and continue - m_currentNode = m_currentNode->GetParent(); - } -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Add given walkable position to list of seed positions for map sampling - */ -void CNavMesh::AddWalkableSeed( const Vector &pos, const Vector &normal ) -{ - WalkableSeedSpot seed; - - seed.pos = pos; - seed.normal = normal; - - m_walkableSeedList.AddToTail( seed ); -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return the next walkable seed as a node - */ -CNavNode *CNavMesh::GetNextWalkableSeedNode( void ) -{ - if (!m_walkableSeedList.IsValidIndex( m_seedIdx )) - return NULL; - - WalkableSeedSpot spot = m_walkableSeedList.Element( m_seedIdx ); - - m_seedIdx = m_walkableSeedList.Next( m_seedIdx ); - - return new CNavNode( spot.pos, spot.normal, NULL ); -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Check LOS, ignoring any entities that we can walk through - */ -bool IsWalkableTraceLineClear( Vector &from, Vector &to, unsigned int flags ) -{ - trace_t result; - CBaseEntity *ignore = NULL; - Vector useFrom = from; - - CTraceFilterWalkableEntities traceFilter( NULL, COLLISION_GROUP_NONE, flags ); - - result.fraction = 0.0f; - - const int maxTries = 50; - for( int t=0; tGetLadders(), id ) - { - CNavLadder *ladder = TheNavMesh->GetLadders()[id]; - ladder->m_id = m_nextID++; - } - } -} - - -//-------------------------------------------------------------------------------------------------------------- -CNavArea ** CNavLadder::GetConnection( LadderConnectionType dir ) -{ - switch ( dir ) - { - case LADDER_TOP_FORWARD: - return &m_topForwardArea; - case LADDER_TOP_LEFT: - return &m_topLeftArea; - case LADDER_TOP_RIGHT: - return &m_topRightArea; - case LADDER_TOP_BEHIND: - return &m_topBehindArea; - case LADDER_BOTTOM: - return &m_bottomArea; - default: - break; - } - - return NULL; -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavLadder::OnSplit( CNavArea *original, CNavArea *alpha, CNavArea *beta ) -{ - for ( int con=0; conGetDistanceSquaredToPoint( m_top ); - float betaDistance = beta->GetDistanceSquaredToPoint( m_top ); - - if ( alphaDistance < betaDistance ) - { - *areaConnection = alpha; - } - else - { - *areaConnection = beta; - } - } - } -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Connect this ladder to given area - */ -void CNavLadder::ConnectTo( CNavArea *area ) -{ - float center = (m_top.z + m_bottom.z) * 0.5f; - - if (area->GetCenter().z > center) - { - // connect to top - NavDirType dir; - - Vector dirVector = area->GetCenter() - m_top; - if ( fabs( dirVector.x ) > fabs( dirVector.y ) ) - { - if ( dirVector.x > 0.0f ) // east - { - dir = EAST; - } - else // west - { - dir = WEST; - } - } - else - { - if ( dirVector.y > 0.0f ) // south - { - dir = SOUTH; - } - else // north - { - dir = NORTH; - } - } - - if ( m_dir == dir ) - { - m_topBehindArea = area; - } - else if ( OppositeDirection( m_dir ) == dir ) - { - m_topForwardArea = area; - } - else if ( DirectionLeft( m_dir ) == dir ) - { - m_topLeftArea = area; - } - else - { - m_topRightArea = area; - } - } - else - { - // connect to bottom - m_bottomArea = area; - } -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Destructor - */ -CNavLadder::~CNavLadder() -{ - // tell the other areas we are going away - FOR_EACH_LL( TheNavAreaList, it ) - { - CNavArea *area = TheNavAreaList[ it ]; - - area->OnDestroyNotify( this ); - } -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * invoked when given area is going away - */ -void CNavLadder::OnDestroyNotify( CNavArea *dead ) -{ - Disconnect( dead ); -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Disconnect this ladder from given area - */ -void CNavLadder::Disconnect( CNavArea *area ) -{ - if ( m_topForwardArea == area ) - { - m_topForwardArea = NULL; - } - else if ( m_topLeftArea == area ) - { - m_topLeftArea = NULL; - } - else if ( m_topRightArea == area ) - { - m_topRightArea = NULL; - } - else if ( m_topBehindArea == area ) - { - m_topBehindArea = NULL; - } - else if ( m_bottomArea == area ) - { - m_bottomArea = NULL; - } -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * returns true if given area is connected in given direction - */ -bool CNavLadder::IsConnected( const CNavArea *area, LadderDirectionType dir ) const -{ - if ( dir == LADDER_DOWN ) - { - return area == m_bottomArea; - } - else if ( dir == LADDER_UP ) - { - return ( area == m_topForwardArea || - area == m_topLeftArea || - area == m_topRightArea || - area == m_topBehindArea ); - } - else - { - return ( area == m_bottomArea || - area == m_topForwardArea || - area == m_topLeftArea || - area == m_topRightArea || - area == m_topBehindArea ); - } -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavLadder::SetDir( NavDirType dir ) -{ - m_dir = dir; - - m_normal.Init(); - AddDirectionVector( &m_normal, m_dir, 1.0f ); // worst-case, we have the NavDirType as a normal - - Vector from = (m_top + m_bottom) * 0.5f + m_normal * 5.0f; - Vector to = from - m_normal * 32.0f; - - trace_t result; - UTIL_TraceLine( from, to, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &result ); - - if (result.fraction != 1.0f) - { - bool climbableSurface = physprops->GetSurfaceData( result.surface.surfaceProps )->game.climbable != 0; - if ( !climbableSurface ) - { - climbableSurface = (result.contents & CONTENTS_LADDER) != 0; - } - if ( climbableSurface ) - { - m_normal = result.plane.normal; - } - } -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavLadder::DrawLadder( void ) const -{ - CBasePlayer *player = UTIL_GetListenServerHost(); - if (player == NULL) - return; - - Vector dir; - const Vector &eye = player->EyePosition(); - AngleVectors( player->EyeAngles() + player->GetPunchAngle(), &dir ); - - float dx = eye.x - m_bottom.x; - float dy = eye.y - m_bottom.y; - - Vector2D eyeDir( dx, dy ); - eyeDir.NormalizeInPlace(); - bool isSelected = ( this == TheNavMesh->GetSelectedLadder() ); - bool isMarked = ( this == TheNavMesh->GetMarkedLadder() ); - bool isFront = DotProduct2D( eyeDir, GetNormal().AsVector2D() ) > 0; - - if ( TheNavMesh->IsPlaceMode() ) - { - isSelected = isMarked = false; - isFront = true; - } - - // Draw 'ladder' lines ---------------------------------------------------- - NavEditColor ladderColor = NavNormalColor; - if ( isFront ) - { - if ( isMarked ) - { - ladderColor = NavMarkedColor; - } - else if ( isSelected ) - { - ladderColor = NavSelectedColor; - } - else - { - ladderColor = NavSamePlaceColor; - } - } - else if ( isMarked ) - { - ladderColor = NavMarkedColor; - } - else if ( isSelected ) - { - ladderColor = NavSelectedColor; - } - - Vector right(0, 0, 0), up( 0, 0, 0 ); - VectorVectors( GetNormal(), right, up ); - right *= m_width * 0.5f; - - Vector bottomLeft = m_bottom - right; - Vector bottomRight = m_bottom + right; - Vector topLeft = m_top - right; - Vector topRight = m_top + right; - - int bgcolor[4]; - if ( 4 == sscanf( nav_area_bgcolor.GetString(), "%d %d %d %d", &(bgcolor[0]), &(bgcolor[1]), &(bgcolor[2]), &(bgcolor[3]) ) ) - { - for ( int i=0; i<4; ++i ) - bgcolor[i] = clamp( bgcolor[i], 0, 255 ); - - if ( bgcolor[3] > 0 ) - { - Vector offset( 0, 0, 0 ); - AddDirectionVector( &offset, OppositeDirection( m_dir ), 1 ); - NDebugOverlay::Triangle( topLeft+offset, topRight+offset, bottomRight+offset, bgcolor[0], bgcolor[1], bgcolor[2], bgcolor[3], true, 0.15f ); - NDebugOverlay::Triangle( bottomRight+offset, bottomLeft+offset, topLeft+offset, bgcolor[0], bgcolor[1], bgcolor[2], bgcolor[3], true, 0.15f ); - } - } - - NavDrawLine( topLeft, bottomLeft, ladderColor ); - NavDrawLine( topRight, bottomRight, ladderColor ); - - while ( bottomRight.z < topRight.z ) - { - NavDrawLine( bottomRight, bottomLeft, ladderColor ); - bottomRight += up * (GenerationStepSize/2); - bottomLeft += up * (GenerationStepSize/2); - } - - // Draw connector lines --------------------------------------------------- - if ( !TheNavMesh->IsPlaceMode() ) - { - Vector bottom = m_bottom; - Vector top = m_top; - - NavDrawLine( top, bottom, NavConnectedTwoWaysColor ); - - if (m_bottomArea) - { - float offset = GenerationStepSize; - const Vector& areaBottom = m_bottomArea->GetCenter(); - - // don't draw the bottom connection too high if the ladder is very short - if ( top.z - bottom.z < GenerationStepSize * 1.5f ) - offset = 0.0f; - - // don't draw the bottom connection too high if the ladder is high above the area - if ( bottom.z - areaBottom.z > GenerationStepSize * 1.5f ) - offset = 0.0f; - - NavDrawLine( bottom + Vector( 0, 0, offset ), areaBottom, ((m_bottomArea->IsConnected( this, LADDER_UP ))?NavConnectedTwoWaysColor:NavConnectedOneWayColor) ); - } - - if (m_topForwardArea) - NavDrawLine( top, m_topForwardArea->GetCenter(), ((m_topForwardArea->IsConnected( this, LADDER_DOWN ))?NavConnectedTwoWaysColor:NavConnectedOneWayColor) ); - - if (m_topLeftArea) - NavDrawLine( top, m_topLeftArea->GetCenter(), ((m_topLeftArea->IsConnected( this, LADDER_DOWN ))?NavConnectedTwoWaysColor:NavConnectedOneWayColor) ); - - if (m_topRightArea) - NavDrawLine( top, m_topRightArea->GetCenter(), ((m_topRightArea->IsConnected( this, LADDER_DOWN ))?NavConnectedTwoWaysColor:NavConnectedOneWayColor) ); - - if (m_topBehindArea) - NavDrawLine( top, m_topBehindArea->GetCenter(), ((m_topBehindArea->IsConnected( this, LADDER_DOWN ))?NavConnectedTwoWaysColor:NavConnectedOneWayColor) ); - } -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavLadder::DrawConnectedAreas( void ) -{ - CUtlVector< CNavArea * > areas; - if ( m_topForwardArea ) - areas.AddToTail( m_topForwardArea ); - if ( m_topLeftArea ) - areas.AddToTail( m_topLeftArea ); - if ( m_topRightArea ) - areas.AddToTail( m_topRightArea ); - if ( m_topBehindArea ) - areas.AddToTail( m_topBehindArea ); - if ( m_bottomArea ) - areas.AddToTail( m_bottomArea ); - - for ( int i=0; iDraw(); - - if ( ! TheNavMesh->IsPlaceMode() ) - { - adj->DrawHidingSpots(); - } - } -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Save a navigation ladder to the opened binary stream - */ -void CNavLadder::Save( FileHandle_t file, unsigned int version ) const -{ - // save ID - filesystem->Write( &m_id, sizeof(unsigned int), file ); - - // save extent of ladder - filesystem->Write( &m_width, sizeof(float), file ); - - // save top endpoint of ladder - filesystem->Write( &m_top, 3*sizeof(float), file ); - - // save bottom endpoint of ladder - filesystem->Write( &m_bottom, 3*sizeof(float), file ); - - // save ladder length - filesystem->Write( &m_length, sizeof(float), file ); - - // save direction - filesystem->Write( &m_dir, sizeof(m_dir), file ); - - // save IDs of connecting areas - unsigned int id; - id = ( m_topForwardArea ) ? m_topForwardArea->GetID() : 0; - filesystem->Write( &id, sizeof(id), file ); - - id = ( m_topLeftArea ) ? m_topLeftArea->GetID() : 0; - filesystem->Write( &id, sizeof(id), file ); - - id = ( m_topRightArea ) ? m_topRightArea->GetID() : 0; - filesystem->Write( &id, sizeof(id), file ); - - id = ( m_topBehindArea ) ? m_topBehindArea->GetID() : 0; - filesystem->Write( &id, sizeof(id), file ); - - id = ( m_bottomArea ) ? m_bottomArea->GetID() : 0; - filesystem->Write( &id, sizeof(id), file ); -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Load a navigation ladder from the opened binary stream - */ -void CNavLadder::Load( FileHandle_t file, unsigned int version ) -{ - // load ID - filesystem->Read( &m_id, sizeof(unsigned int), file ); - - // update nextID to avoid collisions - if (m_id >= m_nextID) - m_nextID = m_id+1; - - // load extent of ladder - filesystem->Read( &m_width, sizeof(float), file ); - - // load top endpoint of ladder - filesystem->Read( &m_top, 3*sizeof(float), file ); - - // load bottom endpoint of ladder - filesystem->Read( &m_bottom, 3*sizeof(float), file ); - - // load ladder length - filesystem->Read( &m_length, sizeof(float), file ); - - // load direction - filesystem->Read( &m_dir, sizeof(m_dir), file ); - SetDir( m_dir ); // regenerate the surface normal - - // load dangling status - if ( version == 6 ) - { - bool m_isDangling; - filesystem->Read( &m_isDangling, sizeof(m_isDangling), file ); - } - - // load IDs of connecting areas - unsigned int id; - filesystem->Read( &id, sizeof(id), file ); - m_topForwardArea = TheNavMesh->GetNavAreaByID( id ); - - filesystem->Read( &id, sizeof(id), file ); - m_topLeftArea = TheNavMesh->GetNavAreaByID( id ); - - filesystem->Read( &id, sizeof(id), file ); - m_topRightArea = TheNavMesh->GetNavAreaByID( id ); - - filesystem->Read( &id, sizeof(id), file ); - m_topBehindArea = TheNavMesh->GetNavAreaByID( id ); - - filesystem->Read( &id, sizeof(id), file ); - m_bottomArea = TheNavMesh->GetNavAreaByID( id ); - if ( !m_bottomArea ) - { - DevMsg( "ERROR: Unconnected ladder #%d bottom at ( %g, %g, %g )\n", m_id, m_bottom.x, m_bottom.y, m_bottom.z ); - } - - // can't include behind area, since it is not used when going up a ladder - if (!m_topForwardArea && !m_topLeftArea && !m_topRightArea) - DevMsg( "ERROR: Unconnected ladder #%d top at ( %g, %g, %g )\n", m_id, m_top.x, m_top.y, m_top.z ); -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Functor returns true if ladder is free, or false if someone is on the ladder - */ -class IsLadderFreeFunctor -{ -public: - IsLadderFreeFunctor( const CNavLadder *ladder, const CBasePlayer *ignore ) - { - m_ladder = ladder; - m_ignore = ignore; - } - - bool operator() ( CBasePlayer *player ) - { - if (player == m_ignore) - return true; - - if (!player->IsOnLadder()) - return true; - - // player is on a ladder - is it this one? - const Vector &feet = player->GetAbsOrigin(); - - if (feet.z > m_ladder->m_top.z + HalfHumanHeight) - return true; - - if (feet.z + HumanHeight < m_ladder->m_bottom.z - HalfHumanHeight) - return true; - - Vector2D away( m_ladder->m_bottom.x - feet.x, m_ladder->m_bottom.y - feet.y ); - const float onLadderRange = 50.0f; - return away.IsLengthGreaterThan( onLadderRange ); - } - - const CNavLadder *m_ladder; - const CBasePlayer *m_ignore; -}; - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return true if someone is on this ladder - */ -bool CNavLadder::IsInUse( const CBasePlayer *ignore ) const -{ - IsLadderFreeFunctor isLadderFree( this, ignore ); - return !ForEachPlayer( isLadderFree ); -} - -//-------------------------------------------------------------------------------------------------------------- -Vector CNavLadder::GetPosAtHeight( float height ) const -{ - if ( height < m_bottom.z ) - { - return m_bottom; - } - - if ( height > m_top.z ) - { - return m_top; - } - - if ( m_top.z == m_bottom.z ) - { - return m_top; - } - - float percent = ( height - m_bottom.z ) / ( m_top.z - m_bottom.z ); - - return m_top * percent + m_bottom * ( 1.0f - percent ); -} - -//-------------------------------------------------------------------------------------------------------------- diff --git a/game/server/nav_ladder.h b/game/server/nav_ladder.h deleted file mode 100644 index af1f1f2b9..000000000 --- a/game/server/nav_ladder.h +++ /dev/null @@ -1,141 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -// Navigation ladders -// Author: Michael S. Booth (mike@turtlerockstudios.com), January 2003 - -#ifndef _NAV_LADDER_H_ -#define _NAV_LADDER_H_ - -class CNavArea; - -//-------------------------------------------------------------------------------------------------------------- -/** - * Placeholder ladder class that holds the mins and maxs for a ladder, since its brushes - * are merged into the world during the compile. - */ -class CInfoLadder : public CBaseEntity -{ -public: - DECLARE_CLASS( CInfoLadder, CBaseEntity ); - DECLARE_DATADESC(); - - bool KeyValue( const char *szKeyName, const char *szValue ); - - Vector mins; - Vector maxs; -}; - - -//-------------------------------------------------------------------------------------------------------------- -/** - * The NavLadder represents ladders in the Navigation Mesh, and their connections to adjacent NavAreas - * @todo Deal with ladders that allow jumping off to areas in the middle - */ -class CNavLadder -{ -public: - CNavLadder( void ) - { - m_topForwardArea = NULL; - m_topRightArea = NULL; - m_topLeftArea = NULL; - m_topBehindArea = NULL; - m_bottomArea = NULL; - - // set an ID for interactive editing - loads will overwrite this - m_id = m_nextID++; - } - - ~CNavLadder(); - - void Save( FileHandle_t file, unsigned int version ) const; - void Load( FileHandle_t file, unsigned int version ); - - unsigned int GetID( void ) const { return m_id; } ///< return this ladder's unique ID - static void CompressIDs( void ); /// NavLadderList; - - -//-------------------------------------------------------------------------------------------------------------- -inline NavDirType CNavLadder::GetDir( void ) const -{ - return m_dir; -} - - -//-------------------------------------------------------------------------------------------------------------- -inline const Vector &CNavLadder::GetNormal( void ) const -{ - return m_normal; -} - - -#endif // _NAV_LADDER_H_ diff --git a/game/server/nav_mesh.cpp b/game/server/nav_mesh.cpp deleted file mode 100644 index 804a98287..000000000 --- a/game/server/nav_mesh.cpp +++ /dev/null @@ -1,1959 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -// NavMesh.cpp -// Implementation of Navigation Mesh interface -// Author: Michael S. Booth, 2003-2004 - -#include "cbase.h" -#include "filesystem.h" -#include "nav_mesh.h" -#include "nav_node.h" -#include "fmtstr.h" -#include "utlbuffer.h" -#include "tier0/vprof.h" - -#define DrawLine( from, to, duration, red, green, blue ) NDebugOverlay::Line( from, to, red, green, blue, true, 0.1f ) - - -/** - * The singleton for accessing the navigation mesh - */ -CNavMesh *TheNavMesh = NULL; - -ConVar nav_edit( "nav_edit", "0", FCVAR_GAMEDLL | FCVAR_CHEAT, "Set to one to interactively edit the Navigation Mesh. Set to zero to leave edit mode." ); -ConVar nav_quicksave( "nav_quicksave", "0", FCVAR_GAMEDLL | FCVAR_CHEAT, "Set to one to skip the time consuming phases of the analysis. Useful for data collection and testing." ); -ConVar nav_show_approach_points( "nav_show_approach_points", "0", FCVAR_GAMEDLL | FCVAR_CHEAT, "Show Approach Points in the Navigation Mesh." ); -ConVar nav_show_danger( "nav_show_danger", "0", FCVAR_GAMEDLL | FCVAR_CHEAT, "Show current 'danger' levels." ); -ConVar nav_show_player_counts( "nav_show_player_counts", "0", FCVAR_GAMEDLL | FCVAR_CHEAT, "Show current player counts in each area." ); - - -//-------------------------------------------------------------------------------------------------------------- -CNavMesh::CNavMesh( void ) -{ - m_grid = NULL; - m_spawnName = NULL; - m_gridCellSize = 300.0f; - - m_placeCount = 0; - m_placeName = NULL; - - LoadPlaceDatabase(); - - Reset(); -} - -//-------------------------------------------------------------------------------------------------------------- -CNavMesh::~CNavMesh() -{ - delete [] m_grid; - m_grid = NULL; - - if (m_spawnName) - delete [] m_spawnName; - - // !!!!bug!!! why does this crash in linux on server exit - for( unsigned int i=0; iResetNodes(); - } - } - - // destroy all hiding spots - DestroyHidingSpots(); - - // destroy navigation nodes created during map generation - CNavNode *node, *next; - for( node = CNavNode::m_list; node; node = next ) - { - next = node->m_next; - delete node; - } - CNavNode::m_list = NULL; - CNavNode::m_listLength = 0; - CNavNode::m_nextID = 1; - - if ( !incremental ) - { - // destroy the grid - if (m_grid) - delete [] m_grid; - - m_grid = NULL; - m_gridSizeX = 0; - m_gridSizeY = 0; - } - - // clear the hash table - for( int i=0; iGetExtent(); - - int loX = WorldToGridX( extent.lo.x ); - int loY = WorldToGridY( extent.lo.y ); - int hiX = WorldToGridX( extent.hi.x ); - int hiY = WorldToGridY( extent.hi.y ); - - for( int y = loY; y <= hiY; ++y ) - { - for( int x = loX; x <= hiX; ++x ) - { - m_grid[ x + y*m_gridSizeX ].AddToTail( const_cast( area ) ); - } - } - - // add to hash table - int key = ComputeHashKey( area->GetID() ); - - if (m_hashTable[key]) - { - // add to head of list in this slot - area->m_prevHash = NULL; - area->m_nextHash = m_hashTable[key]; - m_hashTable[key]->m_prevHash = area; - m_hashTable[key] = area; - } - else - { - // first entry in this slot - m_hashTable[key] = area; - area->m_nextHash = NULL; - area->m_prevHash = NULL; - } - - if ( area->GetAttributes() & NAV_MESH_TRANSIENT ) - { - m_transientAreas.AddToTail( area ); - } - - ++m_areaCount; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Remove an area from the mesh - */ -void CNavMesh::RemoveNavArea( CNavArea *area ) -{ - // add to grid - const Extent &extent = area->GetExtent(); - - int loX = WorldToGridX( extent.lo.x ); - int loY = WorldToGridY( extent.lo.y ); - int hiX = WorldToGridX( extent.hi.x ); - int hiY = WorldToGridY( extent.hi.y ); - - for( int y = loY; y <= hiY; ++y ) - { - for( int x = loX; x <= hiX; ++x ) - { - m_grid[ x + y*m_gridSizeX ].FindAndRemove( area ); - } - } - - // remove from hash table - int key = ComputeHashKey( area->GetID() ); - - if (area->m_prevHash) - { - area->m_prevHash->m_nextHash = area->m_nextHash; - } - else - { - // area was at start of list - m_hashTable[key] = area->m_nextHash; - - if (m_hashTable[key]) - { - m_hashTable[key]->m_prevHash = NULL; - } - } - - if (area->m_nextHash) - { - area->m_nextHash->m_prevHash = area->m_prevHash; - } - - if ( area->GetAttributes() & NAV_MESH_TRANSIENT ) - { - BuildTransientAreaList(); - } - - --m_areaCount; -} - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::BuildTransientAreaList( void ) -{ - m_transientAreas.RemoveAll(); - - FOR_EACH_LL( TheNavAreaList, it ) - { - CNavArea *area = TheNavAreaList[ it ]; - - if ( area->GetAttributes() & NAV_MESH_TRANSIENT ) - { - m_transientAreas.AddToTail( area ); - } - } -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Given a position, return the nav area that IsOverlapping and is *immediately* beneath it - */ -CNavArea *CNavMesh::GetNavArea( const Vector &pos, float beneathLimit ) const -{ - VPROF( "CNavMesh::GetNavArea" ); - - if (m_grid == NULL) - return NULL; - - // get list in cell that contains position - int x = WorldToGridX( pos.x ); - int y = WorldToGridY( pos.y ); - NavAreaList *list = &m_grid[ x + y*m_gridSizeX ]; - - - // search cell list to find correct area - CNavArea *use = NULL; - float useZ = -99999999.9f; - Vector testPos = pos + Vector( 0, 0, 5 ); - - FOR_EACH_LL( (*list), it ) - { - CNavArea *area = (*list)[ it ]; - - // check if position is within 2D boundaries of this area - if (area->IsOverlapping( testPos )) - { - // project position onto area to get Z - float z = area->GetZ( testPos ); - - // if area is above us, skip it - if (z > testPos.z) - continue; - - // if area is too far below us, skip it - if (z < pos.z - beneathLimit) - continue; - - // if area is higher than the one we have, use this instead - if (z > useZ) - { - use = area; - useZ = z; - } - } - } - - return use; -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::GridToWorld( int gridX, int gridY, Vector *pos ) const -{ - gridX = clamp( gridX, 0, m_gridSizeX-1 ); - gridY = clamp( gridY, 0, m_gridSizeY-1 ); - - pos->x = m_minX + gridX * m_gridCellSize; - pos->y = m_minY + gridY * m_gridCellSize; -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Given a position in the world, return the nav area that is closest - * and at the same height, or beneath it. - * Used to find initial area if we start off of the mesh. - */ -CNavArea *CNavMesh::GetNearestNavArea( const Vector &pos, bool anyZ, float maxDist, bool checkLOS ) const -{ - VPROF( "CNavMesh::GetNearestNavArea" ); - - if (m_grid == NULL) - return NULL; - - CNavArea *close = NULL; - float closeDistSq = maxDist * maxDist; - - // quick check - close = GetNavArea( pos ); - if (close) - { - return close; - } - - // ensure source position is well behaved - Vector source; - source.x = pos.x; - source.y = pos.y; - if (GetGroundHeight( pos, &source.z ) == false) - { - return NULL; - } - - source.z += HalfHumanHeight; - - - // find closest nav area - CNavArea::MakeNewMarker(); - - - // get list in cell that contains position - int originX = WorldToGridX( pos.x ); - int originY = WorldToGridY( pos.y ); - - int shiftLimit = static_cast(maxDist / m_gridCellSize); - - // - // Search in increasing rings out from origin, starting with cell - // that contains the given position. - // Once we find a close area, we must check one more step out in - // case our position is just against the edge of the cell boundary - // and an area in an adjacent cell is actually closer. - // - for( int shift=0; shift <= shiftLimit; ++shift ) - { - for( int x = originX - shift; x <= originX + shift; ++x ) - { - if (x < 0 || x >= m_gridSizeX) - continue; - - for( int y = originY - shift; y <= originY + shift; ++y ) - { - if (y < 0 || y >= m_gridSizeY) - continue; - - // only check these areas if we're on the outer edge of our spiral - if ( x > originX - shift && - x < originX + shift && - y > originY - shift && - y < originY + shift ) - continue; - - NavAreaList *list = &m_grid[ x + y*m_gridSizeX ]; - - // find closest area in this cell - FOR_EACH_LL( (*list), it ) - { - CNavArea *area = (*list)[ it ]; - - // skip if we've already visited this area - if (area->IsMarked()) - continue; - - area->Mark(); - - Vector areaPos; - area->GetClosestPointOnArea( source, &areaPos ); - - float distSq = (areaPos - source).LengthSqr(); - - // keep the closest area - if (distSq < closeDistSq) - { - // check LOS to area - // REMOVED: If we do this for !anyZ, it's likely we wont have LOS and will enumerate every area in the mesh - // It is still good to do this in some isolated cases, however - if ( checkLOS ) - { - trace_t result; - UTIL_TraceLine( source, areaPos + Vector( 0, 0, HalfHumanHeight ), MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &result ); - if (result.fraction != 1.0f) - { - continue; - } - } - - closeDistSq = distSq; - close = area; - - // look one more step outwards - shiftLimit = shift+1; - } - } - } - } - } - - return close; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Given an ID, return the associated area - */ -CNavArea *CNavMesh::GetNavAreaByID( unsigned int id ) const -{ - if (id == 0) - return NULL; - - int key = ComputeHashKey( id ); - - for( CNavArea *area = m_hashTable[key]; area; area = area->m_nextHash ) - { - if (area->GetID() == id) - { - return area; - } - } - - return NULL; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Given an ID, return the associated ladder - */ -CNavLadder *CNavMesh::GetLadderByID( unsigned int id ) const -{ - if (id == 0) - return NULL; - - FOR_EACH_LL( m_ladderList, it ) - { - CNavLadder *ladder = m_ladderList[it]; - if ( ladder->GetID() == id ) - { - return ladder; - } - } - - return NULL; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return radio chatter place for given coordinate - */ -unsigned int CNavMesh::GetPlace( const Vector &pos ) const -{ - CNavArea *area = GetNearestNavArea( pos, true ); - - if (area) - { - return area->GetPlace(); - } - - return UNDEFINED_PLACE; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Load the place names from a file - */ -void CNavMesh::LoadPlaceDatabase( void ) -{ - m_placeCount = 0; - - CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); - filesystem->ReadFile("NavPlace.db", "GAME", buf); - - if (!buf.Size()) - return; - - const int maxNameLength = 128; - char buffer[ maxNameLength ]; - - CUtlVector placeNames; - - // count the number of places - while( true ) - { - buf.GetLine( buffer, maxNameLength ); - - if ( !buf.IsValid() ) - break; - - int len = V_strlen( buffer ); - if ( len >= 2 ) - { - if ( buffer[len-1] == '\n' ) - buffer[len-1] = 0; - - if ( buffer[len-2] == '\r' ) - buffer[len-2] = 0; - - char *pName = new char[ len + 1 ]; - V_strncpy( pName, buffer, len+1 ); - placeNames.AddToTail( pName ); - } - } - - // allocate place name array - m_placeCount = placeNames.Count(); - m_placeName = new char * [ m_placeCount ]; - - for ( unsigned int i=0; i < m_placeCount; i++ ) - { - m_placeName[i] = placeNames[i]; - } -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Given a place, return its name. - * Reserve zero as invalid. - */ -const char *CNavMesh::PlaceToName( Place place ) const -{ - if (place >= 1 && place <= m_placeCount) - return m_placeName[ (int)place - 1 ]; - - return NULL; -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Given a place name, return a place ID or zero if no place is defined - * Reserve zero as invalid. - */ -Place CNavMesh::NameToPlace( const char *name ) const -{ - for( unsigned int i=0; i placeNames; - for ( i=0; i %-26s", placeNames[i] ); - else - Msg( "%-30s", placeNames[i] ); - - if ((i+1) % 3 == 0) - Msg( "\n" ); - } - - Msg( "\n" ); -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return the ground height below this point in "height". - * Return false if position is invalid (outside of map, in a solid area, etc). - */ -bool CNavMesh::GetGroundHeight( const Vector &pos, float *height, Vector *normal ) const -{ - VPROF( "CNavMesh::GetGroundHeight" ); - - Vector to; - to.x = pos.x; - to.y = pos.y; - to.z = pos.z - 9999.9f; - - float offset; - Vector from; - trace_t result; - CBaseEntity *ignore = NULL; - - const float maxOffset = 100.0f; - const float inc = 10.0f; - - #define MAX_GROUND_LAYERS 16 - struct GroundLayerInfo - { - float ground; - Vector normal; - } - layer[ MAX_GROUND_LAYERS ]; - int layerCount = 0; - - for( offset = 1.0f; offset < maxOffset; offset += inc ) - { - from = pos + Vector( 0, 0, offset ); - - CTraceFilterWalkableEntities filter( ignore, COLLISION_GROUP_NONE, WALK_THRU_EVERYTHING ); - UTIL_TraceLine( from, to, MASK_PLAYERSOLID_BRUSHONLY, &filter, &result ); - - // if the trace came down thru a door, ignore the door and try again - // also ignore breakable floors - if (result.DidHitNonWorldEntity() && result.m_pEnt) - { - if (FClassnameIs( result.m_pEnt, "prop_door" ) || - FClassnameIs( result.m_pEnt, "prop_door_rotating" ) || - FClassnameIs( result.m_pEnt, "func_breakable" ))// && VARS( result.pHit )->takedamage == DAMAGE_YES)) - { - ignore = result.m_pEnt; - // keep incrementing to avoid infinite loop if more than one entity is along the traceline... - /// @todo Deal with multiple ignore entities in a single TraceLine() - //offset -= inc; - continue; - } - } - - if (result.startsolid == false) - { - // if we didnt start inside a solid area, the trace hit a ground layer - - // if this is a new ground layer, add it to the set - if (layerCount == 0 || result.endpos.z > layer[ layerCount-1 ].ground) - { - layer[ layerCount ].ground = result.endpos.z; - if (result.plane.normal.IsZero()) - layer[ layerCount ].normal = Vector( 0, 0, 1 ); - else - layer[ layerCount ].normal = result.plane.normal; - - ++layerCount; - - if (layerCount == MAX_GROUND_LAYERS) - break; - } - } - } - - if (layerCount == 0) - return false; - - // find the lowest layer that allows a player to stand or crouch upon it - int i; - for( i=0; i= HalfHumanHeight) - break; - } - - *height = layer[ i ].ground; - - if (normal) - *normal = layer[ i ].normal; - - return true; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return the "simple" ground height below this point in "height". - * This function is much faster, but less tolerant. Make sure the give position is "well behaved". - * Return false if position is invalid (outside of map, in a solid area, etc). - */ -bool CNavMesh::GetSimpleGroundHeight( const Vector &pos, float *height, Vector *normal ) const -{ - Vector to; - to.x = pos.x; - to.y = pos.y; - to.z = pos.z - 9999.9f; - - trace_t result; - - UTIL_TraceLine( pos, to, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &result ); - - if (result.startsolid) - return false; - - *height = result.endpos.z; - - if (normal) - *normal = result.plane.normal; - - return true; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Show danger levels for debugging - */ -void CNavMesh::DrawDanger( void ) const -{ - FOR_EACH_LL( TheNavAreaList, it ) - { - CNavArea *area = TheNavAreaList[ it ]; - - Vector center = area->GetCenter(); - Vector top; - center.z = area->GetZ( center ); - - float danger = area->GetDanger( 0 ); - if (danger > 0.1f) - { - top.x = center.x; - top.y = center.y; - top.z = center.z + 10.0f * danger; - DrawLine( center, top, 3, 255, 0, 0 ); - } - - danger = area->GetDanger( 1 ); - if (danger > 0.1f) - { - top.x = center.x; - top.y = center.y; - top.z = center.z + 10.0f * danger; - DrawLine( center, top, 3, 0, 0, 255 ); - } - } -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Zero player counts in all areas - */ -void CNavMesh::ClearPlayerCounts( void ) -{ - FOR_EACH_LL( TheNavAreaList, it ) - { - CNavArea *area = TheNavAreaList[ it ]; - - area->ClearPlayerCount(); - } -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Show current player counts for debugging. - * NOTE: Assumes two teams. - */ -void CNavMesh::DrawPlayerCounts( void ) const -{ - CFmtStr msg; - - FOR_EACH_LL( TheNavAreaList, it ) - { - CNavArea *area = TheNavAreaList[ it ]; - - if (area->GetPlayerCount() > 0) - { - NDebugOverlay::Text( area->GetCenter(), msg.sprintf( "%d (%d/%d)", area->GetPlayerCount(), area->GetPlayerCount(1), area->GetPlayerCount(2) ), false, 0.1f ); - } - } -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Increase the danger of nav areas containing and near the given position - */ -void CNavMesh::IncreaseDangerNearby( int teamID, float amount, CNavArea *startArea, const Vector &pos, float maxRadius ) -{ - if (startArea == NULL) - return; - - CNavArea::MakeNewMarker(); - CNavArea::ClearSearchLists(); - - startArea->AddToOpenList(); - startArea->SetTotalCost( 0.0f ); - startArea->Mark(); - startArea->IncreaseDanger( teamID, amount ); - - while( !CNavArea::IsOpenListEmpty() ) - { - // get next area to check - CNavArea *area = CNavArea::PopOpenList(); - - // explore adjacent areas - for( int dir=0; dirGetAdjacentCount( (NavDirType)dir ); - for( int i=0; iGetAdjacentArea( (NavDirType)dir, i ); - - if (!adjArea->IsMarked()) - { - // compute distance from danger source - float cost = (adjArea->GetCenter() - pos).Length(); - if (cost <= maxRadius) - { - adjArea->AddToOpenList(); - adjArea->SetTotalCost( cost ); - adjArea->Mark(); - adjArea->IncreaseDanger( teamID, amount * cost/maxRadius ); - } - } - } - } - } -} - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavRemoveUnusedJumpAreas( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavRemoveUnusedJumpAreas(); -} -static ConCommand nav_remove_unused_jump_areas( "nav_remove_unused_jump_areas", CommandNavRemoveUnusedJumpAreas, "Removes jump areas with at most 1 connection to a ladder or non-jump area.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavDelete( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavDelete(); -} -static ConCommand nav_delete( "nav_delete", CommandNavDelete, "Deletes the currently highlighted Area.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavDeleteMarked( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavDeleteMarked(); -} -static ConCommand nav_delete_marked( "nav_delete_marked", CommandNavDeleteMarked, "Deletes the currently marked Area (if any).", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavSplit( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavSplit(); -} -static ConCommand nav_split( "nav_split", CommandNavSplit, "To split an Area into two, align the split line using your cursor and invoke the split command.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavMakeSniperSpots( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavMakeSniperSpots(); -} -static ConCommand nav_make_sniper_spots( "nav_make_sniper_spots", CommandNavMakeSniperSpots, "Chops the marked area into disconnected sub-areas suitable for sniper spots.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavMerge( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavMerge(); -} -static ConCommand nav_merge( "nav_merge", CommandNavMerge, "To merge two Areas into one, mark the first Area, highlight the second by pointing your cursor at it, and invoke the merge command.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavMark( const CCommand &args ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavMark( args ); -} -static ConCommand nav_mark( "nav_mark", CommandNavMark, "Marks the Area or Ladder under the cursor for manipulation by subsequent editing commands.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavUnmark( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavUnmark(); -} -static ConCommand nav_unmark( "nav_unmark", CommandNavUnmark, "Clears the marked Area or Ladder.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavBeginArea( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavBeginArea(); -} -static ConCommand nav_begin_area( "nav_begin_area", CommandNavBeginArea, "Defines a corner of a new Area or Ladder. To complete the Area or Ladder, drag the opposite corner to the desired location and issue a 'nav_end_area' command.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavEndArea( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavEndArea(); -} -static ConCommand nav_end_area( "nav_end_area", CommandNavEndArea, "Defines the second corner of a new Area or Ladder and creates it.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavConnect( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavConnect(); -} -static ConCommand nav_connect( "nav_connect", CommandNavConnect, "To connect two Areas, mark the first Area, highlight the second Area, then invoke the connect command. Note that this creates a ONE-WAY connection from the first to the second Area. To make a two-way connection, also connect the second area to the first.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavDisconnect( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavDisconnect(); -} -static ConCommand nav_disconnect( "nav_disconnect", CommandNavDisconnect, "To disconnect two Areas, mark an Area, highlight a second Area, then invoke the disconnect command. This will remove all connections between the two Areas.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavSplice( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavSplice(); -} -static ConCommand nav_splice( "nav_splice", CommandNavSplice, "To splice, mark an area, highlight a second area, then invoke the splice command to create a new, connected area between them.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavCrouch( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavToggleAttribute( NAV_MESH_CROUCH ); -} -static ConCommand nav_crouch( "nav_crouch", CommandNavCrouch, "Toggles the 'must crouch in this area' flag used by the AI system.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavPrecise( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavToggleAttribute( NAV_MESH_PRECISE ); -} -static ConCommand nav_precise( "nav_precise", CommandNavPrecise, "Toggles the 'dont avoid obstacles' flag used by the AI system.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavJump( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavToggleAttribute( NAV_MESH_JUMP ); -} -static ConCommand nav_jump( "nav_jump", CommandNavJump, "Toggles the 'traverse this area by jumping' flag used by the AI system.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavNoJump( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavToggleAttribute( NAV_MESH_NO_JUMP ); -} -static ConCommand nav_no_jump( "nav_no_jump", CommandNavNoJump, "Toggles the 'dont jump in this area' flag used by the AI system.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavStop( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavToggleAttribute( NAV_MESH_STOP ); -} -static ConCommand nav_stop( "nav_stop", CommandNavStop, "Toggles the 'must stop when entering this area' flag used by the AI system.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavWalk( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavToggleAttribute( NAV_MESH_WALK ); -} -static ConCommand nav_walk( "nav_walk", CommandNavWalk, "Toggles the 'traverse this area by walking' flag used by the AI system.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavRun( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavToggleAttribute( NAV_MESH_RUN ); -} -static ConCommand nav_run( "nav_run", CommandNavRun, "Toggles the 'traverse this area by running' flag used by the AI system.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavAvoid( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavToggleAttribute( NAV_MESH_AVOID ); -} -static ConCommand nav_avoid( "nav_avoid", CommandNavAvoid, "Toggles the 'avoid this area when possible' flag used by the AI system.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavTransient( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavToggleAttribute( NAV_MESH_TRANSIENT ); -} -static ConCommand nav_transient( "nav_transient", CommandNavTransient, "Toggles the 'area is transient and may become blocked' flag used by the AI system.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavDontHide( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavToggleAttribute( NAV_MESH_DONT_HIDE ); -} -static ConCommand nav_dont_hide( "nav_dont_hide", CommandNavDontHide, "Toggles the 'area is not suitable for hiding spots' flag used by the AI system.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavStand( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavToggleAttribute( NAV_MESH_STAND ); -} -static ConCommand nav_stand( "nav_stand", CommandNavStand, "Toggles the 'stand while hiding' flag used by the AI system.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavNoHostages( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavToggleAttribute( NAV_MESH_NO_HOSTAGES ); -} -static ConCommand nav_no_hostages( "nav_no_hostages", CommandNavNoHostages, "Toggles the 'hostages cannot use this area' flag used by the AI system.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavStrip( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->StripNavigationAreas(); -} -static ConCommand nav_strip( "nav_strip", CommandNavStrip, "Strips all Hiding Spots, Approach Points, and Encounter Spots from the current Area.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavSave( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - if (TheNavMesh->Save()) - { - Msg( "Navigation map '%s' saved.\n", TheNavMesh->GetFilename() ); - } - else - { - const char *filename = TheNavMesh->GetFilename(); - Msg( "ERROR: Cannot save navigation map '%s'.\n", (filename) ? filename : "(null)" ); - } -} -static ConCommand nav_save( "nav_save", CommandNavSave, "Saves the current Navigation Mesh to disk.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavLoad( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - if (TheNavMesh->Load() != NAV_OK) - { - Msg( "ERROR: Navigation Mesh load failed.\n" ); - } -} -static ConCommand nav_load( "nav_load", CommandNavLoad, "Loads the Navigation Mesh for the current map.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -static int PlaceNameAutocompleteCallback( char const *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] ) -{ - return TheNavMesh->PlaceNameAutocomplete( partial, commands ); -} - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavUsePlace( const CCommand &args ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - if (args.ArgC() == 1) - { - // no arguments = list all available places - TheNavMesh->PrintAllPlaces(); - } - else - { - // single argument = set current place - Place place = TheNavMesh->PartialNameToPlace( args[ 1 ] ); - - if (place == UNDEFINED_PLACE) - { - Msg( "Ambiguous\n" ); - } - else - { - Msg( "Current place set to '%s'\n", TheNavMesh->PlaceToName( place ) ); - TheNavMesh->SetNavPlace( place ); - } - } -} -static ConCommand nav_use_place( "nav_use_place", CommandNavUsePlace, "If used without arguments, all available Places will be listed. If a Place argument is given, the current Place is set.", FCVAR_GAMEDLL | FCVAR_CHEAT, PlaceNameAutocompleteCallback ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavPlaceReplace( const CCommand &args ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - if (args.ArgC() != 3) - { - // no arguments - Msg( "Usage: nav_place_replace \n" ); - } - else - { - // two arguments - replace the first place with the second - Place oldPlace = TheNavMesh->PartialNameToPlace( args[ 1 ] ); - Place newPlace = TheNavMesh->PartialNameToPlace( args[ 2 ] ); - - if ( oldPlace == UNDEFINED_PLACE || newPlace == UNDEFINED_PLACE ) - { - Msg( "Ambiguous\n" ); - } - else - { - FOR_EACH_LL( TheNavAreaList, it ) - { - CNavArea *area = TheNavAreaList[it]; - if ( area->GetPlace() == oldPlace ) - { - area->SetPlace( newPlace ); - } - } - } - } -} -static ConCommand nav_place_replace( "nav_place_replace", CommandNavPlaceReplace, "Replaces all instances of the first place with the second place.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavPlaceList( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - CUtlVector< Place > placeDirectory; - - FOR_EACH_LL( TheNavAreaList, nit ) - { - CNavArea *area = TheNavAreaList[ nit ]; - - Place place = area->GetPlace(); - - if ( place ) - { - if ( !placeDirectory.HasElement( place ) ) - { - placeDirectory.AddToTail( place ); - } - } - } - - Msg( "Map uses %d place names:\n", placeDirectory.Count() ); - for ( int i=0; iPlaceToName( placeDirectory[i] ) ); - } -} -static ConCommand nav_place_list( "nav_place_list", CommandNavPlaceList, "Lists all place names used in the map.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavTogglePlaceMode( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavTogglePlaceMode(); -} -static ConCommand nav_toggle_place_mode( "nav_toggle_place_mode", CommandNavTogglePlaceMode, "Toggle the editor into and out of Place mode. Place mode allows labelling of Area with Place names.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavSetPlaceMode( const CCommand &args ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - bool on = true; - if ( args.ArgC() == 2 ) - { - on = (atoi( args[ 1 ] ) != 0); - } - - if ( on != TheNavMesh->IsPlaceMode() ) - { - TheNavMesh->CommandNavTogglePlaceMode(); - } -} -static ConCommand nav_set_place_mode( "nav_set_place_mode", CommandNavSetPlaceMode, "Sets the editor into or out of Place mode. Place mode allows labelling of Area with Place names.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavPlaceFloodFill( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavPlaceFloodFill(); -} -static ConCommand nav_place_floodfill( "nav_place_floodfill", CommandNavPlaceFloodFill, "Sets the Place of the Area under the cursor to the curent Place, and 'flood-fills' the Place to all adjacent Areas. Flood-filling stops when it hits an Area with the same Place, or a different Place than that of the initial Area.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavPlacePick( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavPlacePick(); -} -static ConCommand nav_place_pick( "nav_place_pick", CommandNavPlacePick, "Sets the current Place to the Place of the Area under the cursor.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavTogglePlacePainting( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavTogglePlacePainting(); -} -static ConCommand nav_toggle_place_painting( "nav_toggle_place_painting", CommandNavTogglePlacePainting, "Toggles Place Painting mode. When Place Painting, pointing at an Area will 'paint' it with the current Place.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavMarkUnnamed( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavMarkUnnamed(); -} -static ConCommand nav_mark_unnamed( "nav_mark_unnamed", CommandNavMarkUnnamed, "Mark an Area with no Place name. Useful for finding stray areas missed when Place Painting.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavCornerSelect( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavCornerSelect(); -} -static ConCommand nav_corner_select( "nav_corner_select", CommandNavCornerSelect, "Select a corner of the currently marked Area. Use multiple times to access all four corners.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavCornerRaise( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavCornerRaise(); -} -static ConCommand nav_corner_raise( "nav_corner_raise", CommandNavCornerRaise, "Raise the selected corner of the currently marked Area.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavCornerLower( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavCornerLower(); -} -static ConCommand nav_corner_lower( "nav_corner_lower", CommandNavCornerLower, "Lower the selected corner of the currently marked Area.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavCornerPlaceOnGround( const CCommand &args ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavCornerPlaceOnGround( args ); -} -static ConCommand nav_corner_place_on_ground( "nav_corner_place_on_ground", CommandNavCornerPlaceOnGround, "Places the selected corner of the currently marked Area on the ground.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavWarpToMark( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavWarpToMark(); -} -static ConCommand nav_warp_to_mark( "nav_warp_to_mark", CommandNavWarpToMark, "Warps the player to the marked area.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavLadderFlip( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavLadderFlip(); -} -static ConCommand nav_ladder_flip( "nav_ladder_flip", CommandNavLadderFlip, "Flips the selected ladder's direction.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavGenerate( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->BeginGeneration(); -} -static ConCommand nav_generate( "nav_generate", CommandNavGenerate, "Generate a Navigation Mesh for the current map and save it to disk.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavGenerateIncremental( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->BeginGeneration( true ); -} -static ConCommand nav_generate_incremental( "nav_generate_incremental", CommandNavGenerateIncremental, "Generate a Navigation Mesh for the current map and save it to disk.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavAnalyze( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->BeginAnalysis(); -} -static ConCommand nav_analyze( "nav_analyze", CommandNavAnalyze, "Re-analyze the current Navigation Mesh and save it to disk.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavMarkWalkable( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - Vector pos; - - if (nav_edit.GetBool()) - { - // we are in edit mode, use the edit cursor's location - pos = TheNavMesh->GetEditCursorPosition(); - } - else - { - // we are not in edit mode, use the position of the local player - CBasePlayer *player = UTIL_GetListenServerHost(); - - if (player == NULL) - { - Msg( "ERROR: No local player!\n" ); - return; - } - - pos = player->GetAbsOrigin(); - } - - // snap position to the sampling grid - pos.x = TheNavMesh->SnapToGrid( pos.x, true ); - pos.y = TheNavMesh->SnapToGrid( pos.y, true ); - - Vector normal; - if (TheNavMesh->GetGroundHeight( pos, &pos.z, &normal ) == false) - { - Msg( "ERROR: Invalid ground position.\n" ); - return; - } - - TheNavMesh->AddWalkableSeed( pos, normal ); - - Msg( "Walkable position marked.\n" ); -} -static ConCommand nav_mark_walkable( "nav_mark_walkable", CommandNavMarkWalkable, "Mark the current location as a walkable position. These positions are used as seed locations when sampling the map to generate a Navigation Mesh.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavClearWalkableMarks( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->ClearWalkableSeeds(); -} -static ConCommand nav_clear_walkable_marks( "nav_clear_walkable_marks", CommandNavClearWalkableMarks, "Erase any previously placed walkable positions.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavCompressID( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - CNavArea::CompressIDs(); - CNavLadder::CompressIDs(); -} -static ConCommand nav_compress_id( "nav_compress_id", CommandNavCompressID, "Re-orders area and ladder ID's so they are continuous.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavShowLadderBounds( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - CInfoLadder *ladder = NULL; - while( (ladder = dynamic_cast< CInfoLadder * >(gEntList.FindEntityByClassname( ladder, "info_ladder" ))) != NULL ) - { - NDebugOverlay::Box( vec3_origin, ladder->mins, ladder->maxs, 0, 255, 0, 0, 600 ); - NDebugOverlay::Box( ladder->GetAbsOrigin(), ladder->mins, ladder->maxs, 0, 0, 255, 0, 600 ); - } -} -static ConCommand nav_show_ladder_bounds( "nav_show_ladder_bounds", CommandNavShowLadderBounds, "Draws the bounding boxes of all func_ladders in the map.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavBuildLadder( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavBuildLadder(); -} -static ConCommand nav_build_ladder( "nav_build_ladder", CommandNavBuildLadder, "Attempts to build a nav ladder on the climbable surface under the cursor.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -/* IN PROGRESS: -//-------------------------------------------------------------------------------------------------------------- -void CommandNavPickArea( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavPickArea(); -} -static ConCommand nav_pick_area( "nav_pick_area", CommandNavPickArea, "Marks an area (and corner) based on the surface under the cursor.", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavResizeHorizontal( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavResizeHorizontal(); -} -static ConCommand nav_resize_horizontal( "nav_resize_horizontal", CommandNavResizeHorizontal, "TODO", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavResizeVertical( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavResizeVertical(); -} -static ConCommand nav_resize_vertical( "nav_resize_vertical", CommandNavResizeVertical, "TODO", FCVAR_GAMEDLL | FCVAR_CHEAT ); - - -//-------------------------------------------------------------------------------------------------------------- -void CommandNavResizeEnd( void ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - TheNavMesh->CommandNavResizeEnd(); -} -static ConCommand nav_resize_end( "nav_resize_end", CommandNavResizeEnd, "TODO", FCVAR_GAMEDLL | FCVAR_CHEAT ); -*/ - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Destroy ladder representations - */ -void CNavMesh::DestroyLadders( void ) -{ - FOR_EACH_LL( m_ladderList, it ) - { - delete m_ladderList[ it ]; - } - - m_ladderList.RemoveAll(); - - m_markedLadder = NULL; - m_selectedLadder = NULL; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Strip the "analyzed" data out of all navigation areas - */ -void CNavMesh::StripNavigationAreas( void ) -{ - FOR_EACH_LL( TheNavAreaList, it ) - { - CNavArea *area = TheNavAreaList[ it ]; - - area->Strip(); - } -} - -//-------------------------------------------------------------------------------------------------------------- - -HidingSpotList TheHidingSpotList; -unsigned int HidingSpot::m_nextID = 1; -unsigned int HidingSpot::m_masterMarker = 0; - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Hiding Spot factory - */ -HidingSpot *CNavMesh::CreateHidingSpot( void ) const -{ - return new HidingSpot; -} - - -//-------------------------------------------------------------------------------------------------------------- -void CNavMesh::DestroyHidingSpots( void ) -{ - // remove all hiding spot references from the nav areas - FOR_EACH_LL( TheNavAreaList, it ) - { - CNavArea *area = TheNavAreaList[ it ]; - - area->m_hidingSpotList.RemoveAll(); - } - - HidingSpot::m_nextID = 0; - - // free all the HidingSpots - FOR_EACH_LL( TheHidingSpotList, hit ) - { - delete TheHidingSpotList[ hit ]; - } - - TheHidingSpotList.RemoveAll(); -} - -//-------------------------------------------------------------------------------------------------------------- -//-------------------------------------------------------------------------------------------------------------- -/** - * Construct a Hiding Spot. Assign a unique ID which may be overwritten if loaded. - */ -HidingSpot::HidingSpot( void ) -{ - m_pos = Vector( 0, 0, 0 ); - m_id = m_nextID++; - m_flags = 0; - m_area = NULL; - - TheHidingSpotList.AddToTail( this ); -} - - -//-------------------------------------------------------------------------------------------------------------- -void HidingSpot::Save( FileHandle_t file, unsigned int version ) const -{ - filesystem->Write( &m_id, sizeof(unsigned int), file ); - filesystem->Write( &m_pos, 3 * sizeof(float), file ); - filesystem->Write( &m_flags, sizeof(unsigned char), file ); -} - - -//-------------------------------------------------------------------------------------------------------------- -void HidingSpot::Load( FileHandle_t file, unsigned int version ) -{ - filesystem->Read( &m_id, sizeof(unsigned int), file ); - filesystem->Read( &m_pos, 3 * sizeof(float), file ); - filesystem->Read( &m_flags, sizeof(unsigned char), file ); - - // update next ID to avoid ID collisions by later spots - if (m_id >= m_nextID) - m_nextID = m_id+1; -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Hiding Spot post-load processing - */ -NavErrorType HidingSpot::PostLoad( void ) -{ - // set our area - m_area = TheNavMesh->GetNavArea( m_pos + Vector( 0, 0, HalfHumanHeight ) ); - - AssertMsg( m_area, UTIL_VarArgs("A Hiding Spot is off of the Nav Mesh at (%.0f %.0f %.0f)", m_pos.x, m_pos.y, m_pos.z) ); - - return NAV_OK; -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Given a HidingSpot ID, return the associated HidingSpot - */ -HidingSpot *GetHidingSpotByID( unsigned int id ) -{ - FOR_EACH_LL( TheHidingSpotList, it ) - { - HidingSpot *spot = TheHidingSpotList[ it ]; - - if (spot->GetID() == id) - return spot; - } - - return NULL; -} - - diff --git a/game/server/nav_mesh.h b/game/server/nav_mesh.h deleted file mode 100644 index 3116fbfac..000000000 --- a/game/server/nav_mesh.h +++ /dev/null @@ -1,376 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -// nav_mesh.h -// The Navigation Mesh interface -// Author: Michael S. Booth (mike@turtlerockstudios.com), January 2003 - -// -// Author: Michael S. Booth (mike@turtlerockstudios.com), 2003 -// -// NOTE: The Navigation code uses Doxygen-style comments. If you run Doxygen over this code, it will -// auto-generate documentation. Visit www.doxygen.org to download the system for free. -// - -#ifndef _NAV_MESH_H_ -#define _NAV_MESH_H_ - -#include "filesystem.h" - -#include "nav.h" -#include "nav_area.h" -#include "nav_colors.h" - - -class CNavArea; -class CBaseEntity; - -extern ConVar nav_edit; -extern ConVar nav_quicksave; -extern ConVar nav_show_approach_points; -extern ConVar nav_show_danger; - -//-------------------------------------------------------------------------------------------------------- -/** - * The CNavMesh is the global interface to the Navigation Mesh. - * @todo Make this an abstract base class interface, and derive mod-specific implementations. - */ -class CNavMesh -{ -public: - CNavMesh( void ); - virtual ~CNavMesh(); - - virtual HidingSpot *CreateHidingSpot( void ) const; ///< Hiding Spot factory - - virtual void Reset( void ); ///< destroy Navigation Mesh data and revert to initial state - virtual void Update( void ); ///< invoked on each game frame - - virtual NavErrorType Load( void ); ///< load navigation data from a file - bool IsLoaded( void ) const { return m_isLoaded; } ///< return true if a Navigation Mesh has been loaded - virtual bool Save( void ) const; ///< store Navigation Mesh to a file - bool IsFromCurrentMap( void ) const { return m_isFromCurrentMap; } ///< return true if the Navigation Mesh was last edited with the current map version - - unsigned int GetNavAreaCount( void ) const { return m_areaCount; } ///< return total number of nav areas - - CNavArea *GetNavArea( const Vector &pos, float beneathLimt = 120.0f ) const; ///< given a position, return the nav area that IsOverlapping and is *immediately* beneath it - CNavArea *GetNavAreaByID( unsigned int id ) const; - CNavArea *GetNearestNavArea( const Vector &pos, bool anyZ = false, float maxDist = 10000.0f, bool checkLOS = false ) const; - - Place GetPlace( const Vector &pos ) const; ///< return Place at given coordinate - const char *PlaceToName( Place place ) const; ///< given a place, return its name - Place NameToPlace( const char *name ) const; ///< given a place name, return a place ID or zero if no place is defined - Place PartialNameToPlace( const char *name ) const; ///< given the first part of a place name, return a place ID or zero if no place is defined, or the partial match is ambiguous - void PrintAllPlaces( void ) const; ///< output a list of names to the console - int PlaceNameAutocomplete( char const *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] ); ///< Given a partial place name, fill in possible place names for ConCommand autocomplete - - bool GetGroundHeight( const Vector &pos, float *height, Vector *normal = NULL ) const; ///< get the Z coordinate of the topmost ground level below the given point - bool GetSimpleGroundHeight( const Vector &pos, float *height, Vector *normal = NULL ) const;///< get the Z coordinate of the ground level directly below the given point - - - /// increase "danger" weights in the given nav area and nearby ones - void IncreaseDangerNearby( int teamID, float amount, CNavArea *area, const Vector &pos, float maxRadius ); - void DrawDanger( void ) const; ///< draw the current danger levels - - void ClearPlayerCounts( void ); ///< zero player counts in all areas - void DrawPlayerCounts( void ) const; ///< draw the current player counts for each area - - //------------------------------------------------------------------------------------- - // Auto-generation - // - void BeginGeneration( bool incremental = false ); ///< initiate the generation process - void BeginAnalysis( void ); ///< re-analyze an existing Mesh. Determine Hiding Spots, Encounter Spots, etc. - - bool IsGenerating( void ) const { return m_generationMode != GENERATE_NONE; } ///< return true while a Navigation Mesh is being generated - const char *GetPlayerSpawnName( void ) const; ///< return name of player spawn entity - void SetPlayerSpawnName( const char *name ); ///< define the name of player spawn entities - void AddWalkableSeed( const Vector &pos, const Vector &normal ); ///< add given walkable position to list of seed positions for map sampling - void ClearWalkableSeeds( void ) { m_walkableSeedList.RemoveAll(); } ///< erase all walkable seed positions - - //------------------------------------------------------------------------------------- - // Edit mode - // - unsigned int GetNavPlace( void ) const { return m_navPlace; } - void SetNavPlace( unsigned int place ) { m_navPlace = place; } - - // Edit callbacks from ConCommands - void CommandNavDelete( void ); ///< delete current area - void CommandNavDeleteMarked( void ); ///< delete current marked area - void CommandNavSplit( void ); ///< split current area - void CommandNavMerge( void ); ///< merge adjacent areas - void CommandNavMark( const CCommand &args ); ///< mark an area for further operations - void CommandNavUnmark( void ); ///< removes the mark - void CommandNavBeginArea( void ); ///< begin creating a new nav area - void CommandNavEndArea( void ); ///< end creation of the new nav area - void CommandNavConnect( void ); ///< connect marked area to selected area - void CommandNavDisconnect( void ); ///< disconnect marked area from selected area - void CommandNavSplice( void ); ///< create new area in between marked and selected areas - void CommandNavCrouch( void ); ///< toggle crouch attribute on current area - void CommandNavTogglePlaceMode( void ); ///< switch between normal and place editing - void CommandNavSetPlaceMode( void ); ///< switch between normal and place editing - void CommandNavPlaceFloodFill( void ); ///< floodfill areas out from current area - void CommandNavPlacePick( void ); ///< "pick up" the place at the current area - void CommandNavTogglePlacePainting( void ); ///< switch between "painting" places onto areas - void CommandNavMarkUnnamed( void ); ///< mark an unnamed area for further operations - void CommandNavCornerSelect( void ); ///< select a corner on the current area - void CommandNavCornerRaise( void ); ///< raise a corner on the current area - void CommandNavCornerLower( void ); ///< lower a corner on the current area - void CommandNavCornerPlaceOnGround( const CCommand &args ); ///< position a corner on the current area at ground height - void CommandNavWarpToMark( void ); ///< warp a spectating local player to the selected mark - void CommandNavLadderFlip( void ); ///< Flips the direction a ladder faces - void CommandNavToggleAttribute( NavAttributeType attribute ); ///< toggle an attribute on current area - void CommandNavMakeSniperSpots( void ); ///< cuts up the marked area into individual areas suitable for sniper spots - void CommandNavBuildLadder( void ); ///< builds a nav ladder on the climbable surface under the cursor - void CommandNavRemoveUnusedJumpAreas( void ); ///< removes jump areas with at most 1 connection to a ladder or non-jump area - - // IN-PROGRESS COMMANDS FOR MANIPULATING EXISTING AREAS - void CommandNavPickArea( void ); - void CommandNavResizeHorizontal( void ); - void CommandNavResizeVertical( void ); - void CommandNavResizeEnd( void ); - - bool IsPlaceMode( void ) const { return m_navEditMode == NAV_EDIT_PLACE; } - - void GetEditVectors( Vector *pos, Vector *forward ); ///< Gets the eye position and view direction of the editing player - - CNavArea *GetMarkedArea( void ) const { return m_markedArea; } ///< return area marked by user in edit mode - CNavLadder *GetMarkedLadder( void ) const { return m_markedLadder; } ///< return ladder marked by user in edit mode - - CNavArea *GetSelectedArea( void ) const { return m_selectedArea; } ///< return area selected by user in edit mode - CNavLadder *GetSelectedLadder( void ) const { return m_selectedLadder; } ///< return ladder selected by user in edit mode - - void CreateLadder( const Vector& mins, const Vector& maxs, const Vector2D *ladderDir ); - - float SnapToGrid( float x, bool forceGrid = false ) const; ///< snap given coordinate to generation grid boundary - Vector SnapToGrid( const Vector& in, bool snapX = true, bool snapY = true, bool forceGrid = false ) const; ///< snap given vector's X & Y coordinates to generation grid boundary - - const Vector &GetEditCursorPosition( void ) const { return m_editCursorPos; } ///< return position of edit cursor - void StripNavigationAreas( void ); - const char *GetFilename( void ) const; ///< return the filename for this map's "nav" file - - - //------------------------------------------------------------------------------------- - /** - * Apply the functor to all navigation areas. - * If functor returns false, stop processing and return false. - */ - template < typename Functor > - bool ForAllAreas( Functor &func ) - { - FOR_EACH_LL( TheNavAreaList, it ) - { - CNavArea *area = TheNavAreaList[ it ]; - - if (func( area ) == false) - return false; - } - - return true; - } - - NavLadderList& GetLadders( void ) { return m_ladderList; } ///< Returns the list of ladders - CNavLadder *GetLadderByID( unsigned int id ) const; - - CUtlVector< CNavArea * >& GetTransientAreas( void ) { return m_transientAreas; } - -private: - friend class CNavArea; - friend class CNavNode; - - NavAreaList *m_grid; - float m_gridCellSize; ///< the width/height of a grid cell for spatially partitioning nav areas for fast access - int m_gridSizeX; - int m_gridSizeY; - float m_minX; - float m_minY; - unsigned int m_areaCount; ///< total number of nav areas - - bool m_isLoaded; ///< true if a Navigation Mesh has been loaded - bool m_isFromCurrentMap; ///< true if the Navigation Mesh was last saved with the current map - - enum { HASH_TABLE_SIZE = 256 }; - CNavArea *m_hashTable[ HASH_TABLE_SIZE ]; ///< hash table to optimize lookup by ID - int ComputeHashKey( unsigned int id ) const; ///< returns a hash key for the given nav area ID - - int WorldToGridX( float wx ) const; ///< given X component, return grid index - int WorldToGridY( float wy ) const; ///< given Y component, return grid index - void AllocateGrid( float minX, float maxX, float minY, float maxY ); ///< clear and reset the grid to the given extents - void GridToWorld( int gridX, int gridY, Vector *pos ) const; - - void AddNavArea( CNavArea *area ); ///< add an area to the grid - void RemoveNavArea( CNavArea *area ); ///< remove an area from the grid - - void DestroyNavigationMesh( bool incremental = false ); ///< free all resources of the mesh and reset it to empty state - void DestroyHidingSpots( void ); - - void ComputeBattlefrontAreas( void ); ///< determine areas where rushing teams will first meet - - //---------------------------------------------------------------------------------- - // Place directory - // - char **m_placeName; ///< master directory of place names (ie: "places") - unsigned int m_placeCount; ///< number of "places" defined in placeName[] - void LoadPlaceDatabase( void ); ///< load the place names from a file - - //---------------------------------------------------------------------------------- - // Edit mode - // - unsigned int m_navPlace; ///< current navigation place for editing - void OnEditModeStart( void ); ///< called when edit mode has just been enabled - void DrawEditMode( void ); ///< draw navigation areas - void OnEditModeEnd( void ); ///< called when edit mode has just been disabled - bool m_isEditing; ///< true if in edit mode - Vector m_editCursorPos; ///< current position of the cursor - CNavArea *m_markedArea; ///< currently marked area for edit operations - CNavArea *m_selectedArea; ///< area that is selected this frame - CNavArea *m_lastSelectedArea; ///< area that was selected last frame - NavCornerType m_markedCorner; ///< currently marked corner for edit operations - Vector m_anchor; ///< first corner of an area being created - bool m_isPlacePainting; ///< if true, we set an area's place by pointing at it - bool m_splitAlongX; ///< direction the selected nav area would be split - float m_splitEdge; ///< location of the possible split - - enum NavEditMode { - NAV_EDIT_NORMAL = 0, - NAV_EDIT_CREATE, ///< manually creating a new nav area - NAV_EDIT_RESIZE_HORIZONTAL, - NAV_EDIT_RESIZE_VERTICAL, - NAV_EDIT_PLACE ///< place-editing mode - }; - NavEditMode m_navEditMode; - - bool m_climbableSurface; ///< if true, the cursor is pointing at a climable surface - Vector m_surfaceNormal; ///< Normal of the surface the cursor is pointing at - Vector m_ladderAnchor; ///< first corner of a ladder being created - Vector m_ladderNormal; ///< Normal of the surface of the ladder being created - bool m_isCreatingLadder; ///< if true, we are manually creating a ladder - CNavLadder *m_selectedLadder; ///< ladder that is selected this frame - CNavLadder *m_lastSelectedLadder; ///< ladder that was selected last frame - CNavLadder *m_markedLadder; ///< currently marked ladder for edit operations - - bool GetActiveNavArea( void ); ///< Finds the area or ladder the local player is currently pointing at. Returns true if a surface was hit by the traceline. - - void SetEditMode( bool isPlaceMode ); ///< sets/clears place mode - void SetPlacePaintingMode( bool painting ); ///< Sets place-painting, if we're in place mode - void SetMarkedLadder( CNavLadder *ladder ); ///< mark ladder for further edit operations - void SetMarkedArea( CNavArea *area ); ///< mark area for further edit operations - - CountdownTimer m_showAreaInfoTimer; ///< Timer that controls how long area info is displayed - - //---------------------------------------------------------------------------------- - // Auto-generation - // - bool UpdateGeneration( float maxTime = 0.25f ); ///< process the auto-generation for 'maxTime' seconds. return false if generation is complete. - - CNavNode *m_currentNode; ///< the current node we are sampling from - NavDirType m_generationDir; - CNavNode *AddNode( const Vector &destPos, const Vector &destNormal, NavDirType dir, CNavNode *source ); ///< add a nav node and connect it, update current node - - NavLadderList m_ladderList; ///< list of ladder navigation representations - void BuildLadders( void ); - void DestroyLadders( void ); - - bool SampleStep( void ); ///< sample the walkable areas of the map - void CreateNavAreasFromNodes( void ); ///< cover all of the sampled nodes with nav areas - - bool TestArea( CNavNode *node, int width, int height ); ///< check if an area of size (width, height) can fit, starting from node as upper left corner - int BuildArea( CNavNode *node, int width, int height ); ///< create a CNavArea of size (width, height) starting fom node at upper left corner - - void RemoveUnusedJumpAreas( void ); - void MarkJumpAreas( void ); - void SquareUpAreas( void ); - void MergeGeneratedAreas( void ); - void ConnectGeneratedAreas( void ); - - enum GenerationStateType - { - SAMPLE_WALKABLE_SPACE, - CREATE_AREAS_FROM_SAMPLES, - FIND_HIDING_SPOTS, - FIND_APPROACH_AREAS, - FIND_ENCOUNTER_SPOTS, - FIND_SNIPER_SPOTS, - FIND_EARLIEST_OCCUPY_TIMES, - SAVE_NAV_MESH, - - NUM_GENERATION_STATES - } - m_generationState; ///< the state of the generation process - enum GenerationModeType - { - GENERATE_NONE, - GENERATE_FULL, - GENERATE_INCREMENTAL, - GENERATE_ANALYSIS_ONLY, - } - m_generationMode; ///< true while a Navigation Mesh is being generated - int m_generationIndex; ///< used for iterating nav areas during generation process - int m_sampleTick; ///< counter for displaying pseudo-progress while sampling walkable space - - char *m_spawnName; ///< name of player spawn entity, used to initiate sampling - - struct WalkableSeedSpot - { - Vector pos; - Vector normal; - }; - CUtlLinkedList< WalkableSeedSpot, int > m_walkableSeedList; ///< list of walkable seed spots for sampling - - CNavNode *GetNextWalkableSeedNode( void ); ///< return the next walkable seed as a node - int m_seedIdx; - - void BuildTransientAreaList( void ); - CUtlVector< CNavArea * > m_transientAreas; -}; - -// the global singleton interface -extern CNavMesh *TheNavMesh; - - - -//-------------------------------------------------------------------------------------------------------------- -inline int CNavMesh::ComputeHashKey( unsigned int id ) const -{ - return id & 0xFF; -} - -//-------------------------------------------------------------------------------------------------------------- -inline int CNavMesh::WorldToGridX( float wx ) const -{ - int x = (int)( (wx - m_minX) / m_gridCellSize ); - - if (x < 0) - x = 0; - else if (x >= m_gridSizeX) - x = m_gridSizeX-1; - - return x; -} - -//-------------------------------------------------------------------------------------------------------------- -inline int CNavMesh::WorldToGridY( float wy ) const -{ - int y = (int)( (wy - m_minY) / m_gridCellSize ); - - if (y < 0) - y = 0; - else if (y >= m_gridSizeY) - y = m_gridSizeY-1; - - return y; -} - - -//-------------------------------------------------------------------------------------------------------------- -// -// Function prototypes -// - -extern void ApproachAreaAnalysisPrep( void ); -extern void CleanupApproachAreaAnalysisPrep( void ); - -#endif // _NAV_MESH_H_ diff --git a/game/server/nav_node.cpp b/game/server/nav_node.cpp deleted file mode 100644 index 291190ac8..000000000 --- a/game/server/nav_node.cpp +++ /dev/null @@ -1,383 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -// nav_node.cpp -// AI Navigation Nodes -// Author: Michael S. Booth (mike@turtlerockstudios.com), January 2003 - -#include "cbase.h" -#include "nav_node.h" -#include "nav_colors.h" -#include "nav_mesh.h" - -NavDirType Opposite[ NUM_DIRECTIONS ] = { SOUTH, WEST, NORTH, EAST }; - -CNavNode *CNavNode::m_list = NULL; -unsigned int CNavNode::m_listLength = 0; -unsigned int CNavNode::m_nextID = 1; - -ConVar nav_show_nodes( "nav_show_nodes", "0" ); - - -//-------------------------------------------------------------------------------------------------------------- -class LookAtTarget -{ -public: - LookAtTarget( const Vector &target ) - { - m_target = target; - } - - bool operator()( CBasePlayer *player ) - { - QAngle angles; - Vector to = m_target - player->GetAbsOrigin(); - VectorAngles( to, angles ); - - player->SetLocalAngles( angles ); - player->SnapEyeAngles( angles ); - return true; - } - -private: - Vector m_target; -}; - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Constructor - */ -CNavNode::CNavNode( const Vector &pos, const Vector &normal, CNavNode *parent ) -{ - m_pos = pos; - m_normal = normal; - - m_id = m_nextID++; - - int i; - for( i=0; iTestArea( this, 1, 1 ); - nav_test_node.SetValue( 0 ); - } - - if ( (unsigned int)(nav_test_node_crouch.GetInt()) == m_id ) - { - CheckCrouch(); - nav_test_node_crouch.SetValue( 0 ); - } - - if ( GetAttributes() & NAV_MESH_CROUCH ) - { - int i; - for( i=0; iGetGroundHeight( m_pos, &floorZ ) ) - { - maxFloorZ = MAX( maxFloorZ, floorZ + 0.1f ); - } - } - } - - groundPos.Init( m_pos.x, m_pos.y, maxFloorZ ); - } - - // For each direction, trace upwards from our best ground height to VEC_HULL_MAX.z to see if we have standing room. - for ( int i=0; i maxs[j] ) - { - float tmp = mins[j]; - mins[j] = maxs[j]; - maxs[j] = tmp; - } - } - - UTIL_TraceHull( - actualGroundPos + Vector( 0, 0, 0.1f ), - actualGroundPos + Vector( 0, 0, VEC_HULL_MAX.z - 0.2f ), - mins, - maxs, - MASK_PLAYERSOLID_BRUSHONLY, - &filter, - &tr ); - actualGroundPos.z += tr.fractionleftsolid * VEC_HULL_MAX.z; - float maxHeight = actualGroundPos.z + VEC_DUCK_HULL_MAX.z; - for ( ; tr.startsolid && actualGroundPos.z <= maxHeight; actualGroundPos.z += 1.0f ) - { - // In case we didn't find a good ground pos above, we could start in the ground. Move us up some. - UTIL_TraceHull( - actualGroundPos + Vector( 0, 0, 0.1f ), - actualGroundPos + Vector( 0, 0, VEC_HULL_MAX.z - 0.2f ), - mins, - maxs, - MASK_PLAYERSOLID_BRUSHONLY, - &filter, - &tr ); - } - if (tr.startsolid || tr.fraction != 1.0f) - { - SetAttributes( NAV_MESH_CROUCH ); - m_crouch[corner] = true; - } - -#if DEBUG_NAV_NODES - if ( nav_show_nodes.GetBool() ) - { - if ( nav_test_node_crouch_dir.GetInt() == i || nav_test_node_crouch_dir.GetInt() == NUM_CORNERS ) - { - if ( tr.startsolid ) - { - NDebugOverlay::Box( actualGroundPos, mins, maxs+Vector( 0, 0, VEC_HULL_MAX.z), 255, 0, 0, 10, 20.0f ); - } - else if ( m_crouch[corner] ) - { - NDebugOverlay::Box( actualGroundPos, mins, maxs+Vector( 0, 0, VEC_HULL_MAX.z), 0, 0, 255, 10, 20.0f ); - } - else - { - NDebugOverlay::Box( actualGroundPos, mins, maxs+Vector( 0, 0, VEC_HULL_MAX.z), 0, 255, 0, 10, 10.0f ); - } - } - } -#endif // DEBUG_NAV_NODES - } -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Create a connection FROM this node TO the given node, in the given direction - */ -void CNavNode::ConnectTo( CNavNode *node, NavDirType dir ) -{ - m_to[ dir ] = node; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return node at given position. - * @todo Need a hash table to make this lookup fast - */ -CNavNode *CNavNode::GetNode( const Vector &pos ) -{ - const float tolerance = 0.45f * GenerationStepSize; // 1.0f - - for( CNavNode *node = m_list; node; node = node->m_next ) - { - float dx = fabs( node->m_pos.x - pos.x ); - float dy = fabs( node->m_pos.y - pos.y ); - float dz = fabs( node->m_pos.z - pos.z ); - - if (dx < tolerance && dy < tolerance && dz < tolerance) - return node; - } - - return NULL; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return true if this node is bidirectionally linked to - * another node in the given direction - */ -BOOL CNavNode::IsBiLinked( NavDirType dir ) const -{ - if (m_to[ dir ] && m_to[ dir ]->m_to[ Opposite[dir] ] == this) - { - return true; - } - - return false; -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Return true if this node is the NW corner of a quad of nodes - * that are all bidirectionally linked. - */ -BOOL CNavNode::IsClosedCell( void ) const -{ - if (IsBiLinked( SOUTH ) && - IsBiLinked( EAST ) && - m_to[ EAST ]->IsBiLinked( SOUTH ) && - m_to[ SOUTH ]->IsBiLinked( EAST ) && - m_to[ EAST ]->m_to[ SOUTH ] == m_to[ SOUTH ]->m_to[ EAST ]) - { - return true; - } - - return false; -} - diff --git a/game/server/nav_node.h b/game/server/nav_node.h deleted file mode 100644 index 6f46cf3b8..000000000 --- a/game/server/nav_node.h +++ /dev/null @@ -1,135 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -// nav_node.h -// Navigation Nodes are used when generating a Navigation Mesh by point sampling the map -// Author: Michael S. Booth (mike@turtlerockstudios.com), January 2003 - -#ifndef _NAV_NODE_H_ -#define _NAV_NODE_H_ - -#include "nav.h" - -// If DEBUG_NAV_NODES is true, nav_show_nodes controls drawing node positions, and -// nav_show_node_id allows you to show the IDs of nodes that didn't get used to create areas. -#ifdef _DEBUG -#define DEBUG_NAV_NODES 1 -#else -#define DEBUG_NAV_NODES 0 -#endif - -//-------------------------------------------------------------------------------------------------------------- -/** - * Navigation Nodes. - * These Nodes encapsulate world locations, and ways to get from one location to an adjacent one. - * Note that these links are not necessarily commutative (falling off of a ledge, for example). - */ -class CNavNode -{ -public: - CNavNode( const Vector &pos, const Vector &normal, CNavNode *parent = NULL ); - - static CNavNode *GetNode( const Vector &pos ); ///< return navigation node at the position, or NULL if none exists - - CNavNode *GetConnectedNode( NavDirType dir ) const; ///< get navigation node connected in given direction, or NULL if cant go that way - const Vector *GetPosition( void ) const; - const Vector *GetNormal( void ) const { return &m_normal; } - unsigned int GetID( void ) const { return m_id; } - - static CNavNode *GetFirst( void ) { return m_list; } - static unsigned int GetListLength( void ) { return m_listLength; } - CNavNode *GetNext( void ) { return m_next; } - - void Draw( void ); - - void ConnectTo( CNavNode *node, NavDirType dir ); ///< create a connection FROM this node TO the given node, in the given direction - CNavNode *GetParent( void ) const; - - void MarkAsVisited( NavDirType dir ); ///< mark the given direction as having been visited - BOOL HasVisited( NavDirType dir ); ///< return TRUE if the given direction has already been searched - BOOL IsBiLinked( NavDirType dir ) const; ///< node is bidirectionally linked to another node in the given direction - BOOL IsClosedCell( void ) const; ///< node is the NW corner of a bi-linked quad of nodes - - void Cover( void ) { m_isCovered = true; } ///< @todo Should pass in area that is covering - BOOL IsCovered( void ) const { return m_isCovered; } ///< return true if this node has been covered by an area - - void AssignArea( CNavArea *area ); ///< assign the given area to this node - CNavArea *GetArea( void ) const; ///< return associated area - - void SetAttributes( unsigned char bits ) { m_attributeFlags = bits; } - unsigned char GetAttributes( void ) const { return m_attributeFlags; } - -private: - friend class CNavMesh; - - void CheckCrouch( void ); - - Vector m_pos; ///< position of this node in the world - Vector m_normal; ///< surface normal at this location - CNavNode *m_to[ NUM_DIRECTIONS ]; ///< links to north, south, east, and west. NULL if no link - unsigned int m_id; ///< unique ID of this node - unsigned char m_attributeFlags; ///< set of attribute bit flags (see NavAttributeType) - - static CNavNode *m_list; ///< the master list of all nodes for this map - static unsigned int m_listLength; - static unsigned int m_nextID; - CNavNode *m_next; ///< next link in master list - - // below are only needed when generating - unsigned char m_visited; ///< flags for automatic node generation. If direction bit is clear, that direction hasn't been explored yet. - CNavNode *m_parent; ///< the node prior to this in the search, which we pop back to when this node's search is done (a stack) - bool m_isCovered; ///< true when this node is "covered" by a CNavArea - CNavArea *m_area; ///< the area this node is contained within - - bool m_crouch[ NUM_CORNERS ]; -}; - -//-------------------------------------------------------------------------------------------------------------- -// -// Inlines -// - -inline CNavNode *CNavNode::GetConnectedNode( NavDirType dir ) const -{ - return m_to[ dir ]; -} - -inline const Vector *CNavNode::GetPosition( void ) const -{ - return &m_pos; -} - -inline CNavNode *CNavNode::GetParent( void ) const -{ - return m_parent; -} - -inline void CNavNode::MarkAsVisited( NavDirType dir ) -{ - m_visited |= (1 << dir); -} - -inline BOOL CNavNode::HasVisited( NavDirType dir ) -{ - if (m_visited & (1 << dir)) - return true; - - return false; -} - -inline void CNavNode::AssignArea( CNavArea *area ) -{ - m_area = area; -} - -inline CNavArea *CNavNode::GetArea( void ) const -{ - return m_area; -} - - -#endif // _NAV_NODE_H_ diff --git a/game/server/nav_pathfind.h b/game/server/nav_pathfind.h deleted file mode 100644 index a48248d8a..000000000 --- a/game/server/nav_pathfind.h +++ /dev/null @@ -1,621 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -// nav_pathfind.h -// Path-finding mechanisms using the Navigation Mesh -// Author: Michael S. Booth (mike@turtlerockstudios.com), January 2003 - -#ifndef _NAV_PATHFIND_H_ -#define _NAV_PATHFIND_H_ - -//------------------------------------------------------------------------------------------------------------------- -/** - * Used when building a path to determine the kind of path to build - */ -enum RouteType -{ - FASTEST_ROUTE, - SAFEST_ROUTE, -}; - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Functor used with NavAreaBuildPath() - */ -class ShortestPathCost -{ -public: - float operator() ( CNavArea *area, CNavArea *fromArea, const CNavLadder *ladder ) - { - if (fromArea == NULL) - { - // first area in path, no cost - return 0.0f; - } - else - { - // compute distance travelled along path so far - float dist; - - if (ladder) - dist = ladder->m_length; - else - dist = (area->GetCenter() - fromArea->GetCenter()).Length(); - - float cost = dist + fromArea->GetCostSoFar(); - - // if this is a "crouch" area, add penalty - if (area->GetAttributes() & NAV_MESH_CROUCH) - { - const float crouchPenalty = 20.0f; // 10 - cost += crouchPenalty * dist; - } - - // if this is a "jump" area, add penalty - if (area->GetAttributes() & NAV_MESH_JUMP) - { - const float jumpPenalty = 5.0f; - cost += jumpPenalty * dist; - } - - return cost; - } - } -}; - -//-------------------------------------------------------------------------------------------------------------- -/** - * Find path from startArea to goalArea via an A* search, using supplied cost heuristic. - * If cost functor returns -1 for an area, that area is considered a dead end. - * This doesn't actually build a path, but the path is defined by following parent - * pointers back from goalArea to startArea. - * If 'closestArea' is non-NULL, the closest area to the goal is returned (useful if the path fails). - * If 'goalArea' is NULL, will compute a path as close as possible to 'goalPos'. - * If 'goalPos' is NULL, will use the center of 'goalArea' as the goal position. - * Returns true if a path exists. - */ -template< typename CostFunctor > -bool NavAreaBuildPath( CNavArea *startArea, CNavArea *goalArea, const Vector *goalPos, CostFunctor &costFunc, CNavArea **closestArea = NULL ) -{ - if (startArea == NULL) - return false; - - if (goalArea != NULL && goalArea->IsBlocked()) - goalArea = NULL; - - if (goalArea == NULL && goalPos == NULL) - return false; - - startArea->SetParent( NULL ); - - // if we are already in the goal area, build trivial path - if (startArea == goalArea) - { - goalArea->SetParent( NULL ); - return true; - } - - // determine actual goal position - Vector actualGoalPos = (goalPos) ? *goalPos : goalArea->GetCenter(); - - // start search - CNavArea::ClearSearchLists(); - - // compute estimate of path length - /// @todo Cost might work as "manhattan distance" - startArea->SetTotalCost( (startArea->GetCenter() - actualGoalPos).Length() ); - - float initCost = costFunc( startArea, NULL, NULL ); - if (initCost < 0.0f) - return false; - startArea->SetCostSoFar( initCost ); - - startArea->AddToOpenList(); - - // keep track of the area we visit that is closest to the goal - if (closestArea) - *closestArea = startArea; - float closestAreaDist = startArea->GetTotalCost(); - - // do A* search - while( !CNavArea::IsOpenListEmpty() ) - { - // get next area to check - CNavArea *area = CNavArea::PopOpenList(); - - // don't consider blocked areas - if ( area->IsBlocked() ) - continue; - - // check if we have found the goal area or position - if (area == goalArea || (goalArea == NULL && goalPos && area->Contains( *goalPos ))) - { - if (closestArea) - { - *closestArea = area; - } - - return true; - } - - // search adjacent areas - bool searchFloor = true; - int dir = NORTH; - const NavConnectList *floorList = area->GetAdjacentList( NORTH ); - int floorIter = floorList->Head(); - - bool ladderUp = true; - const NavLadderConnectList *ladderList = NULL; - int ladderIter = NavLadderConnectList::InvalidIndex(); - enum { AHEAD = 0, LEFT, RIGHT, BEHIND, NUM_TOP_DIRECTIONS }; - int ladderTopDir = AHEAD; - - while(true) - { - CNavArea *newArea; - NavTraverseType how; - const CNavLadder *ladder = NULL; - - // - // Get next adjacent area - either on floor or via ladder - // - if (searchFloor) - { - // if exhausted adjacent connections in current direction, begin checking next direction - if (floorIter == floorList->InvalidIndex()) - { - ++dir; - - if (dir == NUM_DIRECTIONS) - { - // checked all directions on floor - check ladders next - searchFloor = false; - - ladderList = area->GetLadderList( CNavLadder::LADDER_UP ); - ladderIter = ladderList->Head(); - ladderTopDir = AHEAD; - } - else - { - // start next direction - floorList = area->GetAdjacentList( (NavDirType)dir ); - floorIter = floorList->Head(); - } - - continue; - } - - newArea = floorList->Element(floorIter).area; - how = (NavTraverseType)dir; - floorIter = floorList->Next( floorIter ); - } - else // search ladders - { - if (ladderIter == ladderList->InvalidIndex()) - { - if (!ladderUp) - { - // checked both ladder directions - done - break; - } - else - { - // check down ladders - ladderUp = false; - ladderList = area->GetLadderList( CNavLadder::LADDER_DOWN ); - ladderIter = ladderList->Head(); - } - continue; - } - - if (ladderUp) - { - ladder = ladderList->Element( ladderIter ).ladder; - - // do not use BEHIND connection, as its very hard to get to when going up a ladder - if (ladderTopDir == AHEAD) - newArea = ladder->m_topForwardArea; - else if (ladderTopDir == LEFT) - newArea = ladder->m_topLeftArea; - else if (ladderTopDir == RIGHT) - newArea = ladder->m_topRightArea; - else - { - ladderIter = ladderList->Next( ladderIter ); - ladderTopDir = AHEAD; - continue; - } - - how = GO_LADDER_UP; - ++ladderTopDir; - } - else - { - newArea = ladderList->Element(ladderIter).ladder->m_bottomArea; - how = GO_LADDER_DOWN; - ladder = ladderList->Element(ladderIter).ladder; - ladderIter = ladderList->Next( ladderIter ); - } - - if (newArea == NULL) - continue; - } - - // don't backtrack - if (newArea == area) - continue; - - // don't consider blocked areas - if ( newArea->IsBlocked() ) - continue; - - float newCostSoFar = costFunc( newArea, area, ladder ); - - // check if cost functor says this area is a dead-end - if (newCostSoFar < 0.0f) - continue; - - if ((newArea->IsOpen() || newArea->IsClosed()) && newArea->GetCostSoFar() <= newCostSoFar) - { - // this is a worse path - skip it - continue; - } - else - { - // compute estimate of distance left to go - float newCostRemaining = (newArea->GetCenter() - actualGoalPos).Length(); - - // track closest area to goal in case path fails - if (closestArea && newCostRemaining < closestAreaDist) - { - *closestArea = newArea; - closestAreaDist = newCostRemaining; - } - - newArea->SetParent( area, how ); - newArea->SetCostSoFar( newCostSoFar ); - newArea->SetTotalCost( newCostSoFar + newCostRemaining ); - - if (newArea->IsClosed()) - newArea->RemoveFromClosedList(); - - if (newArea->IsOpen()) - { - // area already on open list, update the list order to keep costs sorted - newArea->UpdateOnOpenList(); - } - else - { - newArea->AddToOpenList(); - } - } - } - - // we have searched this area - area->AddToClosedList(); - } - - return false; -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Compute distance between two areas. Return -1 if can't reach 'endArea' from 'startArea'. - */ -template< typename CostFunctor > -float NavAreaTravelDistance( CNavArea *startArea, CNavArea *endArea, CostFunctor &costFunc ) -{ - if (startArea == NULL) - return -1.0f; - - if (endArea == NULL) - return -1.0f; - - if (startArea == endArea) - return 0.0f; - - // compute path between areas using given cost heuristic - if (NavAreaBuildPath( startArea, endArea, NULL, costFunc ) == false) - return -1.0f; - - // compute distance along path - float distance = 0.0f; - for( CNavArea *area = endArea; area->GetParent(); area = area->GetParent() ) - { - distance += (area->GetCenter() - area->GetParent()->GetCenter()).Length(); - } - - return distance; -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Compute travel distance along shortest path from startPos to goalPos. - * Return -1 if can't reach endPos from goalPos. - */ -template< typename CostFunctor > -float NavAreaTravelDistance( const Vector &startPos, const Vector &goalPos, CostFunctor &costFunc ) -{ - CNavArea *startArea = TheNavMesh->GetNearestNavArea( startPos ); - if (startArea == NULL) - { - return -1.0f; - } - - // compute path between areas using given cost heuristic - CNavArea *goalArea = NULL; - if (NavAreaBuildPath( startArea, NULL, &goalPos, costFunc, &goalArea ) == false) - { - return -1.0f; - } - - // compute distance along path - if (goalArea->GetParent() == NULL) - { - // both points are in the same area - return euclidean distance - return (goalPos - startPos).Length(); - } - else - { - CNavArea *area; - float distance; - - // goalPos is assumed to be inside goalArea (or very close to it) - skip to next area - area = goalArea->GetParent(); - distance = (goalPos - area->GetCenter()).Length(); - - for( ; area->GetParent(); area = area->GetParent() ) - { - distance += (area->GetCenter() - area->GetParent()->GetCenter()).Length(); - } - - // add in distance to startPos - distance += (startPos - area->GetCenter()).Length(); - - return distance; - } -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Do a breadth-first search, invoking functor on each area. - * If functor returns 'true', continue searching from this area. - * If functor returns 'false', the area's adjacent areas are not explored (dead end). - * If 'maxRange' is 0 or less, no range check is done (all areas will be examined). - * - * NOTE: Returns all areas that overlap range, even partially - * - * @todo Use ladder connections - */ - -// helper function -inline void AddAreaToOpenList( CNavArea *area, CNavArea *parent, const Vector &startPos, float maxRange ) -{ - if (area == NULL) - return; - - if (!area->IsMarked()) - { - area->Mark(); - area->SetTotalCost( 0.0f ); - area->SetParent( parent ); - - if (maxRange > 0.0f) - { - // make sure this area overlaps range - Vector closePos; - area->GetClosestPointOnArea( startPos, &closePos ); - if ((closePos - startPos).AsVector2D().IsLengthLessThan( maxRange )) - { - // compute approximate distance along path to limit travel range, too - float distAlong = parent->GetCostSoFar(); - distAlong += (area->GetCenter() - parent->GetCenter()).Length(); - area->SetCostSoFar( distAlong ); - - // allow for some fudge due to large size areas - if (distAlong <= 1.5f * maxRange) - area->AddToOpenList(); - } - } - else - { - // infinite range - area->AddToOpenList(); - } - } -} - - -template < typename Functor > -void SearchSurroundingAreas( CNavArea *startArea, const Vector &startPos, Functor &func, float maxRange = -1.0f ) -{ - if (startArea == NULL) - return; - - CNavArea::MakeNewMarker(); - CNavArea::ClearSearchLists(); - - startArea->AddToOpenList(); - startArea->SetTotalCost( 0.0f ); - startArea->SetCostSoFar( 0.0f ); - startArea->SetParent( NULL ); - startArea->Mark(); - - while( !CNavArea::IsOpenListEmpty() ) - { - // get next area to check - CNavArea *area = CNavArea::PopOpenList(); - - // don't use blocked areas - if ( area->IsBlocked() ) - continue; - - // invoke functor on area - if (func( area )) - { - // explore adjacent floor areas - for( int dir=0; dirGetAdjacentCount( (NavDirType)dir ); - for( int i=0; iGetAdjacentArea( (NavDirType)dir, i ); - - AddAreaToOpenList( adjArea, area, startPos, maxRange ); - } - } - - - // explore adjacent areas connected by ladders - - // check up ladders - const NavLadderConnectList *ladderList = area->GetLadderList( CNavLadder::LADDER_UP ); - if (ladderList) - { - FOR_EACH_LL( (*ladderList), it ) - { - const CNavLadder *ladder = (*ladderList)[ it ].ladder; - - // do not use BEHIND connection, as its very hard to get to when going up a ladder - AddAreaToOpenList( ladder->m_topForwardArea, area, startPos, maxRange ); - AddAreaToOpenList( ladder->m_topLeftArea, area, startPos, maxRange ); - AddAreaToOpenList( ladder->m_topRightArea, area, startPos, maxRange ); - } - } - - // check down ladders - ladderList = area->GetLadderList( CNavLadder::LADDER_DOWN ); - if (ladderList) - { - FOR_EACH_LL( (*ladderList), it ) - { - const CNavLadder *ladder = (*ladderList)[ it ].ladder; - - AddAreaToOpenList( ladder->m_bottomArea, area, startPos, maxRange ); - } - } - } - } -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Fuctor that returns lowest cost for farthest away areas - * For use with FindMinimumCostArea() - */ -class FarAwayFunctor -{ -public: - float operator() ( CNavArea *area, CNavArea *fromArea, const CNavLadder *ladder ) - { - if (area == fromArea) - return 9999999.9f; - - return 1.0f/(fromArea->GetCenter() - area->GetCenter()).Length(); - } -}; - -/** - * Fuctor that returns lowest cost for areas farthest from given position - * For use with FindMinimumCostArea() - */ -class FarAwayFromPositionFunctor -{ -public: - FarAwayFromPositionFunctor( const Vector &pos ) : m_pos( pos ) - { - } - - float operator() ( CNavArea *area, CNavArea *fromArea, const CNavLadder *ladder ) - { - return 1.0f/(m_pos - area->GetCenter()).Length(); - } - -private: - const Vector &m_pos; -}; - - -/** - * Pick a low-cost area of "decent" size - */ -template< typename CostFunctor > -CNavArea *FindMinimumCostArea( CNavArea *startArea, CostFunctor &costFunc ) -{ - const float minSize = 150.0f; - - // collect N low-cost areas of a decent size - enum { NUM_CHEAP_AREAS = 32 }; - struct - { - CNavArea *area; - float cost; - } - cheapAreaSet[ NUM_CHEAP_AREAS ]; - int cheapAreaSetCount = 0; - - FOR_EACH_LL( TheNavAreaList, iter ) - { - CNavArea *area = TheNavAreaList[iter]; - - // skip the small areas - const Extent &extent = area->GetExtent(); - if (extent.hi.x - extent.lo.x < minSize || extent.hi.y - extent.lo.y < minSize) - continue; - - // compute cost of this area - float cost = costFunc( area, startArea, NULL ); - - if (cheapAreaSetCount < NUM_CHEAP_AREAS) - { - cheapAreaSet[ cheapAreaSetCount ].area = area; - cheapAreaSet[ cheapAreaSetCount++ ].cost = cost; - } - else - { - // replace most expensive cost if this is cheaper - int expensive = 0; - for( int i=1; i cheapAreaSet[expensive].cost) - expensive = i; - - if (cheapAreaSet[expensive].cost > cost) - { - cheapAreaSet[expensive].area = area; - cheapAreaSet[expensive].cost = cost; - } - } - } - - if (cheapAreaSetCount) - { - // pick one of the areas at random - return cheapAreaSet[ RandomInt( 0, cheapAreaSetCount-1 ) ].area; - } - else - { - // degenerate case - no decent sized areas - pick a random area - int numAreas = TheNavAreaList.Count(); - int which = RandomInt( 0, numAreas-1 ); - - FOR_EACH_LL( TheNavAreaList, iter ) - { - if (which-- == 0) - return TheNavAreaList[iter]; - } - - } - return cheapAreaSet[ RandomInt( 0, cheapAreaSetCount-1 ) ].area; -} - - -#endif // _NAV_PATHFIND_H_ diff --git a/game/server/ndebugoverlay.cpp b/game/server/ndebugoverlay.cpp deleted file mode 100644 index 2a92c19e6..000000000 --- a/game/server/ndebugoverlay.cpp +++ /dev/null @@ -1,266 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Namespace for functions dealing with Debug Overlays -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "mathlib/mathlib.h" -#include "player.h" -#include "ndebugoverlay.h" -#include "wcedit.h" - -#ifdef _LINUX -#include "ai_basenpc.h" -#include "ai_network.h" -#include "ai_networkmanager.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -#define NUM_DEBUG_OVERLAY_LINES 20 - -int m_nDebugOverlayIndex = -1; -OverlayLine_t* m_debugOverlayLine[NUM_DEBUG_OVERLAY_LINES]; - -//----------------------------------------------------------------------------- -// Purpose: Return the old overlay line from the overlay pool -//----------------------------------------------------------------------------- -OverlayLine_t* GetDebugOverlayLine(void) -{ - // Make casing pool if not initialized - if (m_nDebugOverlayIndex == -1) - { - for (int i=0;inoDepthTest = true; - m_debugOverlayLine[i]->draw = false; - } - m_nDebugOverlayIndex = 0; - } - - int id; - - m_nDebugOverlayIndex++; - if (m_nDebugOverlayIndex == NUM_DEBUG_OVERLAY_LINES) - { - m_nDebugOverlayIndex = 0; - id = NUM_DEBUG_OVERLAY_LINES-1; - - } - else - { - id = m_nDebugOverlayIndex-1; - } - return m_debugOverlayLine[id]; -} - -//----------------------------------------------------------------------------- -// Purpose: Adds a debug line to be drawn on the screen -// Input : If testLOS is true, color is based on line of sight test -// Output : -//----------------------------------------------------------------------------- -void UTIL_AddDebugLine(const Vector &startPos, const Vector &endPos, bool noDepthTest, bool testLOS) -{ - OverlayLine_t* debugLine = GetDebugOverlayLine(); - - debugLine->origin = startPos; - debugLine->dest = endPos; - debugLine->noDepthTest = noDepthTest; - debugLine->draw = true; - - if (testLOS) - { - trace_t tr; - UTIL_TraceLine ( debugLine->origin, debugLine->dest, MASK_BLOCKLOS, NULL, COLLISION_GROUP_NONE, &tr ); - if (tr.startsolid || tr.fraction < 1.0) - { - debugLine->r = 255; - debugLine->g = 0; - debugLine->b = 0; - return; - } - } - - debugLine->r = 255; - debugLine->g = 255; - debugLine->b = 255; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns z value of floor below given point (up to 384 inches below) -//----------------------------------------------------------------------------- -float GetLongFloorZ(const Vector &origin) -{ - // trace to the ground, then pop up 8 units and place node there to make it - // easier for them to connect (think stairs, chairs, and bumps in the floor). - // After the routing is done, push them back down. - // - trace_t tr; - UTIL_TraceLine ( origin, - origin - Vector ( 0, 0, 2048 ), - MASK_NPCSOLID_BRUSHONLY, - NULL, - COLLISION_GROUP_NONE, - &tr ); - - // This trace is ONLY used if we hit an entity flagged with FL_WORLDBRUSH - trace_t trEnt; - UTIL_TraceLine ( origin, - origin - Vector ( 0, 0, 2048 ), - MASK_NPCSOLID, - NULL, - COLLISION_GROUP_NONE, - &trEnt ); - - - // Did we hit something closer than the floor? - if ( trEnt.fraction < tr.fraction ) - { - // If it was a world brush entity, copy the node location - if ( trEnt.m_pEnt ) - { - CBaseEntity *e = trEnt.m_pEnt; - if ( e && (e->GetFlags() & FL_WORLDBRUSH) ) - { - tr.endpos = trEnt.endpos; - } - } - } - - return tr.endpos.z; -} - -//------------------------------------------------------------------------------ -// Purpose : Draws a large crosshair at flCrossDistance from the debug player -// with tick marks -//------------------------------------------------------------------------------ -void UTIL_DrawPositioningOverlay( float flCrossDistance ) -{ - CBasePlayer* pPlayer = UTIL_PlayerByIndex(CBaseEntity::m_nDebugPlayer); - - if (!pPlayer) - { - return; - } - - Vector pRight; - pPlayer->EyeVectors( NULL, &pRight, NULL ); - -#ifdef _WIN32 - Vector topPos = NWCEdit::AirNodePlacementPosition(); -#else - Vector pForward; - pPlayer->EyeVectors( &pForward ); - - Vector floorVec = pForward; - floorVec.z = 0; - VectorNormalize( floorVec ); - VectorNormalize( pForward ); - - float cosAngle = DotProduct(floorVec,pForward); - - float lookDist = g_pAINetworkManager->GetEditOps()->m_flAirEditDistance/cosAngle; - Vector topPos = pPlayer->EyePosition()+pForward * lookDist; -#endif - - Vector bottomPos = topPos; - bottomPos.z = GetLongFloorZ(bottomPos); - - // Make sure we can see the target pos - trace_t tr; - Vector endPos; - UTIL_TraceLine(pPlayer->EyePosition(), topPos, MASK_NPCSOLID_BRUSHONLY, pPlayer, COLLISION_GROUP_NONE, &tr); - if (tr.fraction == 1.0) - { - Vector rightTrace = topPos + pRight*400; - float traceLen = (topPos - rightTrace).Length(); - UTIL_TraceLine(topPos, rightTrace, MASK_NPCSOLID_BRUSHONLY, pPlayer, COLLISION_GROUP_NONE, &tr); - endPos = topPos+(pRight*traceLen*tr.fraction); - NDebugOverlay::DrawTickMarkedLine(topPos, endPos, 24.0, 5, 255,0,0,false,0); - - Vector leftTrace = topPos - pRight*400; - traceLen = (topPos - leftTrace).Length(); - UTIL_TraceLine(topPos, leftTrace, MASK_NPCSOLID_BRUSHONLY, pPlayer, COLLISION_GROUP_NONE, &tr); - endPos = topPos-(pRight*traceLen*tr.fraction); - NDebugOverlay::DrawTickMarkedLine(topPos, endPos, 24.0, 5, 255,0,0,false,0); - - Vector upTrace = topPos + Vector(0,0,1)*400; - traceLen = (topPos - upTrace).Length(); - UTIL_TraceLine(topPos, upTrace, MASK_NPCSOLID_BRUSHONLY, pPlayer, COLLISION_GROUP_NONE, &tr); - endPos = topPos+(Vector(0,0,1)*traceLen*tr.fraction); - NDebugOverlay::DrawTickMarkedLine(bottomPos, endPos, 24.0, 5, 255,0,0,false,0); - - // Draw white cross at center - NDebugOverlay::Cross3D(topPos, Vector(-2,-2,-2), Vector(2,2,2), 255,255,255, true, 0); - } - else - { - // Draw warning cross at center - NDebugOverlay::Cross3D(topPos, Vector(-2,-2,-2), Vector(2,2,2), 255,100,100, true, 0 ); - } - /* Don't show distance for now. - char text[25]; - Q_snprintf(text,sizeof(text),"%3.0f",flCrossDistance/12.0); - Vector textPos = topPos - pRight*16 + Vector(0,0,10); - NDebugOverlay::Text( textPos, text, true, 0 ); - */ -} - -//------------------------------------------------------------------------------ -// Purpose : Draw all overlay lines in the list -//------------------------------------------------------------------------------ -void UTIL_DrawOverlayLines(void) -{ - if (m_nDebugOverlayIndex != -1) - { - for (int i=0;idraw) - { - NDebugOverlay::Line(m_debugOverlayLine[i]->origin, - m_debugOverlayLine[i]->dest, - m_debugOverlayLine[i]->r, - m_debugOverlayLine[i]->g, - m_debugOverlayLine[i]->b, - m_debugOverlayLine[i]->noDepthTest,0); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Add an overlay line with padding on the start and end -//----------------------------------------------------------------------------- -void DebugDrawLine( const Vector& vecAbsStart, const Vector& vecAbsEnd, int r, int g, int b, bool test, float duration ) -{ - NDebugOverlay::Line( vecAbsStart + Vector( 0,0,0.1), vecAbsEnd + Vector( 0,0,0.1), r,g,b, test, duration ); -} - -//----------------------------------------------------------------------------- -// Purpose: Allow all debug overlays to be cleared at once -//----------------------------------------------------------------------------- -CON_COMMAND( clear_debug_overlays, "clears debug overlays" ) -{ - CBaseEntity *pEntity = gEntList.FirstEnt(); - - // Clear all entities of their debug overlays - while ( pEntity ) - { - pEntity->m_debugOverlays = 0; - // UNDONE: Clear out / expire timed overlays? - pEntity = gEntList.NextEnt( pEntity ); - } - - // Clear all engine overlays - if ( debugoverlay ) - { - debugoverlay->ClearAllOverlays(); - } -} diff --git a/game/server/ndebugoverlay.h b/game/server/ndebugoverlay.h deleted file mode 100644 index 0f66ff82f..000000000 --- a/game/server/ndebugoverlay.h +++ /dev/null @@ -1,34 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Namespace for functions dealing with Debug Overlays -// -// $NoKeywords: $ -//=============================================================================// -#ifndef NDEBUGOVERLAY_H -#define NDEBUGOVERLAY_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "debugoverlay_shared.h" - -// An overlay line -struct OverlayLine_t -{ - Vector origin; - Vector dest; - int r; - int g; - int b; - bool noDepthTest; - bool draw; -}; - -extern void UTIL_AddDebugLine( const Vector &startPos, const Vector &endPos, bool noDepthTest, bool testLOS ); -extern void UTIL_DrawPositioningOverlay( float flCrossDistance ); -extern void UTIL_DrawOverlayLines( void ); - -extern void DebugDrawLine( const Vector& vecAbsStart, const Vector& vecAbsEnd, int r, int g, int b, bool test, float duration ); - -#endif // NDEBUGOVERLAY_H diff --git a/game/server/networkstringtable_gamedll.h b/game/server/networkstringtable_gamedll.h deleted file mode 100644 index db857deef..000000000 --- a/game/server/networkstringtable_gamedll.h +++ /dev/null @@ -1,46 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef NETWORKSTRINGTABLE_GAMEDLL_H -#define NETWORKSTRINGTABLE_GAMEDLL_H -#ifdef _WIN32 -#pragma once -#endif - -#include "networkstringtabledefs.h" - -class CStringTableSaveRestoreOps; - -// String tables used by the game DLL -#define MAX_VGUI_SCREEN_STRING_BITS 8 -#define MAX_VGUI_SCREEN_STRINGS ( 1 << MAX_VGUI_SCREEN_STRING_BITS ) -#define VGUI_SCREEN_INVALID_STRING ( MAX_VGUI_SCREEN_STRINGS - 1 ) - -#define MAX_MATERIAL_STRING_BITS 10 -#define MAX_MATERIAL_STRINGS ( 1 << MAX_MATERIAL_STRING_BITS ) -#define OVERLAY_MATERIAL_INVALID_STRING ( MAX_MATERIAL_STRINGS - 1 ) - -#define MAX_CHOREO_SCENES_STRING_BITS 12 -#define MAX_CHOREO_SCENES_STRINGS ( 1 << MAX_CHOREO_SCENES_STRING_BITS ) -#define CHOREO_SCENES_INVALID_STRING ( MAX_CHOREO_SCENES_STRINGS - 1 ) - -#define MAX_PARTICLESYSTEMS_STRING_BITS 10 -#define MAX_PARTICLESYSTEMS_STRINGS ( 1 << MAX_PARTICLESYSTEMS_STRING_BITS ) -#define PARTICLESYSTEMS_INVALID_STRING ( MAX_PARTICLESYSTEMS_STRINGS - 1 ) - -extern INetworkStringTableContainer *networkstringtable; -extern INetworkStringTable *g_pStringTableVguiScreen; -extern INetworkStringTable *g_pStringTableEffectDispatch; -extern INetworkStringTable *g_pStringTableClientSideChoreoScenes; - -#define MAX_INFOPANEL_STRINGS 128 - -// save/load -extern CStringTableSaveRestoreOps g_VguiScreenStringOps; - - -#endif // NETWORKSTRINGTABLE_GAMEDLL_H diff --git a/game/server/npc_talker.cpp b/game/server/npc_talker.cpp deleted file mode 100644 index 728f7338b..000000000 --- a/game/server/npc_talker.cpp +++ /dev/null @@ -1,1354 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include "cbase.h" - -#include "npc_talker.h" -#include "npcevent.h" -#include "scriptevent.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - - -BEGIN_SIMPLE_DATADESC( CNPCSimpleTalkerExpresser ) - // m_pSink (reconnected on load) - DEFINE_AUTO_ARRAY( m_szMonologSentence, FIELD_CHARACTER ), - DEFINE_FIELD( m_iMonologIndex, FIELD_INTEGER ), - DEFINE_FIELD( m_fMonologSuspended, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hMonologTalkTarget, FIELD_EHANDLE ), -END_DATADESC() - -BEGIN_DATADESC( CNPCSimpleTalker ) - DEFINE_FIELD( m_useTime, FIELD_TIME ), - DEFINE_FIELD( m_flNextIdleSpeechTime, FIELD_TIME ), - DEFINE_FIELD( m_nSpeak, FIELD_INTEGER ), - DEFINE_FIELD( m_iszUse, FIELD_STRING ), - DEFINE_FIELD( m_iszUnUse, FIELD_STRING ), - // m_FollowBehavior (auto saved by AI) - // Function Pointers - DEFINE_USEFUNC( FollowerUse ), - -END_DATADESC() - -// array of friend names -const char *CNPCSimpleTalker::m_szFriends[TLK_CFRIENDS] = -{ - "NPC_barney", - "NPC_scientist", - "NPC_sitting_scientist", - NULL, -}; - -bool CNPCSimpleTalker::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "UseSentence")) - { - m_iszUse = AllocPooledString(szValue); - } - else if (FStrEq(szKeyName, "UnUseSentence")) - { - m_iszUnUse = AllocPooledString(szValue); - } - else - return BaseClass::KeyValue( szKeyName, szValue ); - - return true; -} - -void CNPCSimpleTalker::Precache( void ) -{ - /* - // FIXME: Need to figure out how to hook these... - if ( m_iszUse != NULL_STRING ) - GetExpresser()->ModifyConcept( TLK_STARTFOLLOW, STRING( m_iszUse ) ); - if ( m_iszUnUse != NULL_STRING ) - GetExpresser()->ModifyConcept( TLK_STOPFOLLOW, STRING( m_iszUnUse ) ); - - */ - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: Allows for modification of the interrupt mask for the current schedule. -// In the most cases the base implementation should be called first. -//----------------------------------------------------------------------------- -void CNPCSimpleTalker::BuildScheduleTestBits( void ) -{ - BaseClass::BuildScheduleTestBits(); - - // Assume that if I move from the player, I can respond to a question - if ( ConditionInterruptsCurSchedule( COND_PLAYER_PUSHING ) || ConditionInterruptsCurSchedule( COND_PROVOKED ) ) - { - SetCustomInterruptCondition( COND_TALKER_RESPOND_TO_QUESTION ); - } -} - -void CNPCSimpleTalker::PrescheduleThink( void ) -{ - BaseClass::PrescheduleThink(); - - (assert_cast(GetExpresser()))->SpeakMonolog(); -} - -bool CNPCSimpleTalker::ShouldSuspendMonolog( void ) -{ - float flDist; - - flDist = ((assert_cast(GetExpresser()))->GetMonologueTarget()->GetAbsOrigin() - GetAbsOrigin()).Length(); - - if( flDist >= 384 ) - { - return true; - } - - return false; -} - -bool CNPCSimpleTalker::ShouldResumeMonolog( void ) -{ - float flDist; - - if( HasCondition( COND_SEE_PLAYER ) ) - { - flDist = ((assert_cast(GetExpresser()))->GetMonologueTarget()->GetAbsOrigin() - GetAbsOrigin()).Length(); - - if( flDist <= 256 ) - { - return true; - } - } - - return false; -} - -int CNPCSimpleTalker::SelectSchedule( void ) -{ - if ( !HasCondition(COND_RECEIVED_ORDERS) ) - { - if ( GetState() == NPC_STATE_IDLE ) - { - // if never seen player, try to greet him - // Filter might be preventing us from ever greeting the player - if ( HasCondition( COND_SEE_PLAYER ) && CanSayHello()) - { - return SCHED_TALKER_IDLE_HELLO; - } - } - } - - return BaseClass::SelectSchedule(); -} - -void CNPCSimpleTalker::StartTask( const Task_t *pTask ) -{ - switch ( pTask->iTask ) - { - case TASK_TALKER_WAIT_FOR_SEMAPHORE: - if ( GetExpresser()->SemaphoreIsAvailable( this ) ) - TaskComplete(); - break; - - case TASK_TALKER_SPEAK: - // ask question or make statement - FIdleSpeak(); - TaskComplete(); - break; - - case TASK_TALKER_RESPOND: - // respond to question - IdleRespond(); - TaskComplete(); - break; - - case TASK_TALKER_HELLO: - // greet player - FIdleHello(); - TaskComplete(); - break; - - case TASK_TALKER_STARE: - // let the player know I know he's staring at me. - FIdleStare(); - TaskComplete(); - break; - - case TASK_TALKER_LOOK_AT_CLIENT: - case TASK_TALKER_CLIENT_STARE: - // track head to the client for a while. - SetWait( pTask->flTaskData ); - break; - - case TASK_TALKER_EYECONTACT: - break; - - case TASK_TALKER_IDEALYAW: - if (GetSpeechTarget() != NULL) - { - GetMotor()->SetIdealYawToTarget( GetSpeechTarget()->GetAbsOrigin() ); - } - TaskComplete(); - break; - - case TASK_TALKER_HEADRESET: - // reset head position after looking at something - SetSpeechTarget( NULL ); - TaskComplete(); - break; - - case TASK_TALKER_BETRAYED: - Speak( TLK_BETRAYED ); - TaskComplete(); - break; - - case TASK_TALKER_STOPSHOOTING: - // tell player to stop shooting - Speak( TLK_NOSHOOT ); - TaskComplete(); - break; - default: - BaseClass::StartTask( pTask ); - } -} - -void CNPCSimpleTalker::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_TALKER_WAIT_FOR_SEMAPHORE: - if ( GetExpresser()->SemaphoreIsAvailable( this ) ) - TaskComplete(); - break; - - case TASK_TALKER_CLIENT_STARE: - case TASK_TALKER_LOOK_AT_CLIENT: - - if ( pTask->iTask == TASK_TALKER_CLIENT_STARE && AI_IsSinglePlayer() ) - { - // Get edict for one player - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - Assert( pPlayer ); - - // fail out if the player looks away or moves away. - if ( ( pPlayer->GetAbsOrigin() - GetAbsOrigin() ).Length2D() > TALKER_STARE_DIST ) - { - // player moved away. - TaskFail("Player moved away"); - } - - Vector forward; - AngleVectors( pPlayer->GetLocalAngles(), &forward ); - if ( UTIL_DotPoints( pPlayer->GetAbsOrigin(), GetAbsOrigin(), forward ) < m_flFieldOfView ) - { - // player looked away - TaskFail("Player looked away"); - } - } - - if ( IsWaitFinished() ) - { - TaskComplete(); - } - break; - - case TASK_TALKER_EYECONTACT: - if (IsMoving() || !GetExpresser()->IsSpeaking() || GetSpeechTarget() == NULL) - { - TaskComplete(); - } - break; - - case TASK_WAIT_FOR_MOVEMENT: - FIdleSpeakWhileMoving(); - BaseClass::RunTask( pTask ); - break; - - default: - BaseClass::RunTask( pTask ); - } -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ - -Activity CNPCSimpleTalker::NPC_TranslateActivity( Activity eNewActivity ) -{ - if ((eNewActivity == ACT_IDLE) && - (GetExpresser()->IsSpeaking()) && - (SelectWeightedSequence ( ACT_SIGNAL3 ) != ACTIVITY_NOT_AVAILABLE) ) - { - return ACT_SIGNAL3; - } - else if ((eNewActivity == ACT_SIGNAL3) && - (SelectWeightedSequence ( ACT_SIGNAL3 ) == ACTIVITY_NOT_AVAILABLE) ) - { - return ACT_IDLE; - } - return BaseClass::NPC_TranslateActivity( eNewActivity ); -} - - -void CNPCSimpleTalker::Event_Killed( const CTakeDamageInfo &info ) -{ - AlertFriends( info.GetAttacker() ); - if ( info.GetAttacker()->GetFlags() & FL_CLIENT ) - { - LimitFollowers( info.GetAttacker(), 0 ); - } - BaseClass::Event_Killed( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseEntity *CNPCSimpleTalker::EnumFriends( CBaseEntity *pPrevious, int listNumber, bool bTrace ) -{ - CBaseEntity *pFriend = pPrevious; - const char *pszFriend; - trace_t tr; - Vector vecCheck; - - pszFriend = m_szFriends[ FriendNumber(listNumber) ]; - while ( pszFriend != NULL && ((pFriend = gEntList.FindEntityByClassname( pFriend, pszFriend )) != NULL) ) - { - if (pFriend == this || !pFriend->IsAlive()) - // don't talk to self or dead people - continue; - - if ( bTrace ) - { - Vector vecCheck; - pFriend->CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 1.0f ), &vecCheck ); - UTIL_TraceLine( GetAbsOrigin(), vecCheck, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr); - } - else - { - tr.fraction = 1.0; - } - - if (tr.fraction == 1.0) - { - return pFriend; - } - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pKiller - -//----------------------------------------------------------------------------- -void CNPCSimpleTalker::AlertFriends( CBaseEntity *pKiller ) -{ - CBaseEntity *pFriend = NULL; - int i; - - // for each friend in this bsp... - for ( i = 0; i < TLK_CFRIENDS; i++ ) - { - while ((pFriend = EnumFriends( pFriend, i, true )) != NULL ) - { - CAI_BaseNPC *pNPC = pFriend->MyNPCPointer(); - if ( pNPC->IsAlive() ) - { - // If a client killed me, make everyone else mad/afraid of him - if ( pKiller->GetFlags() & FL_CLIENT ) - { - CNPCSimpleTalker*pTalkNPC = (CNPCSimpleTalker *)pFriend; - - if (pTalkNPC && pTalkNPC->IsOkToCombatSpeak()) - { - // FIXME: need to check CanSpeakConcept? - pTalkNPC->Speak( TLK_BETRAYED ); - } - } - else - { - if( IRelationType(pKiller) == D_HT) - { - // Killed by an enemy!!! - CNPCSimpleTalker *pAlly = (CNPCSimpleTalker *)pNPC; - - if( pAlly && pAlly->GetExpresser()->CanSpeakConcept( TLK_ALLY_KILLED ) ) - { - pAlly->Speak( TLK_ALLY_KILLED ); - } - } - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPCSimpleTalker::ShutUpFriends( void ) -{ - CBaseEntity *pFriend = NULL; - int i; - - // for each friend in this bsp... - for ( i = 0; i < TLK_CFRIENDS; i++ ) - { - while ((pFriend = EnumFriends( pFriend, i, true )) != NULL) - { - CAI_BaseNPC *pNPC = pFriend->MyNPCPointer(); - if ( pNPC ) - { - pNPC->SentenceStop(); - } - } - } -} - - -// UNDONE: Keep a follow time in each follower, make a list of followers in this function and do LRU -// UNDONE: Check this in Restore to keep restored NPCs from joining a full list of followers -void CNPCSimpleTalker::LimitFollowers( CBaseEntity *pPlayer, int maxFollowers ) -{ - CBaseEntity *pFriend = NULL; - int i, count; - - count = 0; - // for each friend in this bsp... - for ( i = 0; i < TLK_CFRIENDS; i++ ) - { - while ((pFriend = EnumFriends( pFriend, i, false )) != NULL) - { - CAI_BaseNPC *pNPC = pFriend->MyNPCPointer(); - CNPCSimpleTalker *pTalker; - if ( pNPC ) - { - if ( pNPC->GetTarget() == pPlayer ) - { - count++; - if ( count > maxFollowers && (pTalker = dynamic_cast( pNPC ) ) != NULL ) - pTalker->StopFollowing(); - } - } - } - } -} - -//========================================================= -// HandleAnimEvent - catches the NPC-specific messages -// that occur when tagged animation frames are played. -//========================================================= -void CNPCSimpleTalker::HandleAnimEvent( animevent_t *pEvent ) -{ - switch( pEvent->event ) - { - case SCRIPT_EVENT_SENTENCE_RND1: // Play a named sentence group 25% of the time - if (random->RandomInt(0,99) < 75) - break; - // fall through... - case SCRIPT_EVENT_SENTENCE: // Play a named sentence group - ShutUpFriends(); - PlaySentence( pEvent->options, random->RandomFloat(2.8, 3.4) ); - //Msg( "script event speak\n"); - break; - - default: - BaseClass::HandleAnimEvent( pEvent ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Scan for nearest, visible friend. If fPlayer is true, look for nearest player -//----------------------------------------------------------------------------- -bool CNPCSimpleTalker::IsValidSpeechTarget( int flags, CBaseEntity *pEntity ) -{ - return BaseClass::IsValidSpeechTarget( flags, pEntity ); -} - -CBaseEntity *CNPCSimpleTalker::FindNearestFriend(bool fPlayer) -{ - return FindSpeechTarget( (fPlayer) ? AIST_PLAYERS : AIST_NPCS ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// Purpose: Respond to a previous question -//----------------------------------------------------------------------------- -void CNPCSimpleTalker::IdleRespond( void ) -{ - if (!IsOkToSpeak()) - return; - - // play response - SpeakAnswerFriend( GetSpeechTarget() ); - - DeferAllIdleSpeech( random->RandomFloat( TALKER_DEFER_IDLE_SPEAK_MIN, TALKER_DEFER_IDLE_SPEAK_MAX ) ); -} - -bool CNPCSimpleTalker::IsOkToSpeak( void ) -{ - if ( m_flNextIdleSpeechTime > gpGlobals->curtime ) - return false; - - return BaseClass::IsOkToSpeak(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Find a nearby friend to stare at -//----------------------------------------------------------------------------- -int CNPCSimpleTalker::FIdleStare( void ) -{ - // Don't idly speak if our speech filter is preventing us - if ( GetSpeechFilter() && GetSpeechFilter()->GetIdleModifier() == 0 ) - return true; - - SpeakIfAllowed( TLK_STARE ); - - SetSpeechTarget( FindNearestFriend( true ) ); - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Try to greet player first time he's seen -// Output : int -//----------------------------------------------------------------------------- -int CNPCSimpleTalker::FIdleHello( void ) -{ - // Filter might be preventing us from ever greeting the player - if ( !CanSayHello() ) - return false; - - // get a player - CBaseEntity *pPlayer = FindNearestFriend(true); - - if (pPlayer) - { - if (FInViewCone(pPlayer) && FVisible(pPlayer)) - { - SayHelloToPlayer( pPlayer ); - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Say hello to the specified player -//----------------------------------------------------------------------------- -void CNPCSimpleTalker::SayHelloToPlayer( CBaseEntity *pPlayer ) -{ - Assert( !GetExpresser()->SpokeConcept(TLK_HELLO) ); - - SetSpeechTarget( pPlayer ); - - Speak( TLK_HELLO ); - DeferAllIdleSpeech( random->RandomFloat( 5, 10 ) ); - - CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); - CAI_PlayerAlly *pTalker; - for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - pTalker = dynamic_cast(ppAIs[i]); - - if( pTalker && FVisible( pTalker ) ) - { - // Tell this guy he's already said hello to the player, too. - pTalker->GetExpresser()->SetSpokeConcept( TLK_HELLO, NULL ); - } - } -} - - -//--------------------------------------------------------- -// Stop all allies from idle speech for a fixed amount -// of time. Mostly filthy hack to hold us over until -// acting comes online. -//--------------------------------------------------------- -void CNPCSimpleTalker::DeferAllIdleSpeech( float flDelay, CAI_BaseNPC *pIgnore ) -{ - // Brute force. Just plow through NPC list looking for talkers. - CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); - CNPCSimpleTalker *pTalker; - - float flTime = gpGlobals->curtime + flDelay; - - for ( int i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - if( ppAIs[i] != pIgnore ) - { - pTalker = dynamic_cast(ppAIs[i]); - - if( pTalker ) - { - pTalker->m_flNextIdleSpeechTime = flTime; - } - } - } - - BaseClass::DeferAllIdleSpeech( flDelay, pIgnore ); -} - -//========================================================= -// FIdleSpeak -// ask question of nearby friend, or make statement -//========================================================= -int CNPCSimpleTalker::FIdleSpeak( void ) -{ - // try to start a conversation, or make statement - int pitch; - - if (!IsOkToSpeak()) - return false; - - Assert( GetExpresser()->SemaphoreIsAvailable( this ) ); - - pitch = GetExpresser()->GetVoicePitch(); - - // player using this entity is alive and wounded? - CBaseEntity *pTarget = GetTarget(); - - if ( pTarget != NULL ) - { - if ( pTarget->IsPlayer() ) - { - if ( pTarget->IsAlive() ) - { - SetSpeechTarget( GetTarget() ); - if (GetExpresser()->CanSpeakConcept( TLK_PLHURT3) && - (GetTarget()->m_iHealth <= GetTarget()->m_iMaxHealth / 8)) - { - Speak( TLK_PLHURT3 ); - return true; - } - else if (GetExpresser()->CanSpeakConcept( TLK_PLHURT2) && - (GetTarget()->m_iHealth <= GetTarget()->m_iMaxHealth / 4)) - { - Speak( TLK_PLHURT2 ); - return true; - } - else if (GetExpresser()->CanSpeakConcept( TLK_PLHURT1) && - (GetTarget()->m_iHealth <= GetTarget()->m_iMaxHealth / 2)) - { - Speak( TLK_PLHURT1 ); - return true; - } - } - else - { - //!!!KELLY - here's a cool spot to have the talkNPC talk about the dead player if we want. - // "Oh dear, Gordon Freeman is dead!" -Scientist - // "Damn, I can't do this without you." -Barney - } - } - } - - // ROBIN: Disabled idle question & answer for now - /* - // if there is a friend nearby to speak to, play sentence, set friend's response time, return - CBaseEntity *pFriend = FindNearestFriend(false); - - // 75% chance of talking to another citizen if one is available. - if (pFriend && !(pFriend->IsMoving()) && random->RandomInt( 0, 3 ) != 0 ) - { - if ( SpeakQuestionFriend( pFriend ) ) - { - // force friend to answer - CAI_PlayerAlly *pTalkNPC = dynamic_cast(pFriend); - if (pTalkNPC && !pTalkNPC->HasSpawnFlags(SF_NPC_GAG) && !pTalkNPC->IsInAScript() ) - { - SetSpeechTarget( pFriend ); - pTalkNPC->SetAnswerQuestion( this ); - pTalkNPC->GetExpresser()->BlockSpeechUntil( GetExpresser()->GetTimeSpeechComplete() ); - - m_nSpeak++; - } - - // Don't let anyone else butt in. - DeferAllIdleSpeech( random->RandomFloat( TALKER_DEFER_IDLE_SPEAK_MIN, TALKER_DEFER_IDLE_SPEAK_MAX ), pTalkNPC ); - return true; - } - } - */ - - // Otherwise, play an idle statement, try to face client when making a statement. - CBaseEntity *pFriend = FindNearestFriend(true); - if ( pFriend ) - { - SetSpeechTarget( pFriend ); - - // If we're about to talk to the player, and we've never said hello, say hello first - if ( !GetSpeechFilter() || !GetSpeechFilter()->NeverSayHello() ) - { - if ( GetExpresser()->CanSpeakConcept( TLK_HELLO ) && !GetExpresser()->SpokeConcept( TLK_HELLO ) ) - { - SayHelloToPlayer( pFriend ); - return true; - } - } - - if ( Speak( TLK_IDLE ) ) - { - DeferAllIdleSpeech( random->RandomFloat( TALKER_DEFER_IDLE_SPEAK_MIN, TALKER_DEFER_IDLE_SPEAK_MAX ) ); - m_nSpeak++; - } - else - { - // We failed to speak. Don't try again for a bit. - m_flNextIdleSpeechTime = gpGlobals->curtime + 3; - } - - return true; - } - - // didn't speak - m_flNextIdleSpeechTime = gpGlobals->curtime + 3; - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Speak the right question based upon who we're asking -//----------------------------------------------------------------------------- -bool CNPCSimpleTalker::SpeakQuestionFriend( CBaseEntity *pFriend ) -{ - return Speak( TLK_QUESTION ); -} - -//----------------------------------------------------------------------------- -// Purpose: Speak the right answer based upon who we're answering -//----------------------------------------------------------------------------- -bool CNPCSimpleTalker::SpeakAnswerFriend( CBaseEntity *pFriend ) -{ - return Speak( TLK_ANSWER ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPCSimpleTalker::FIdleSpeakWhileMoving( void ) -{ - if ( GetExpresser()->CanSpeak() ) - { - if (!GetExpresser()->IsSpeaking() || GetSpeechTarget() == NULL) - { - // override so that during walk, a scientist may talk and greet player - FIdleHello(); - - if ( ShouldSpeakRandom( m_nSpeak * 20, GetSpeechFilter() ? GetSpeechFilter()->GetIdleModifier() : 1.0 ) ) - { - FIdleSpeak(); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPCSimpleTalker::PlayScriptedSentence( const char *pszSentence, float delay, float volume, soundlevel_t soundlevel, bool bConcurrent, CBaseEntity *pListener ) -{ - if ( !bConcurrent ) - ShutUpFriends(); - - int sentenceIndex = BaseClass::PlayScriptedSentence( pszSentence, delay, volume, soundlevel, bConcurrent, pListener ); - delay += engine->SentenceLength( sentenceIndex ); - if ( delay < 0 ) - delay = 0; - m_useTime = gpGlobals->curtime + delay; - - // Stop all idle speech until after the sentence has completed - DeferAllIdleSpeech( delay + random->RandomFloat( 3.0f, 5.0f ) ); - - return sentenceIndex; -} - -//----------------------------------------------------------------------------- -// Purpose: Tell this NPC to answer a question from another NPC -//----------------------------------------------------------------------------- -void CNPCSimpleTalker::SetAnswerQuestion( CNPCSimpleTalker *pSpeaker ) -{ - if ( !m_hCine ) - { - SetCondition( COND_TALKER_RESPOND_TO_QUESTION ); - } - - SetSpeechTarget( (CAI_BaseNPC *)pSpeaker ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPCSimpleTalker::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - CTakeDamageInfo subInfo = info; - - // if player damaged this entity, have other friends talk about it. - if (subInfo.GetAttacker() && (subInfo.GetAttacker()->GetFlags() & FL_CLIENT) && subInfo.GetDamage() < GetHealth() ) - { - CBaseEntity *pFriend = FindNearestFriend(false); - - if (pFriend && pFriend->IsAlive()) - { - // only if not dead or dying! - CNPCSimpleTalker *pTalkNPC = (CNPCSimpleTalker *)pFriend; - - if (pTalkNPC && pTalkNPC->IsOkToCombatSpeak()) - { - pTalkNPC->Speak( TLK_NOSHOOT ); - } - } - } - return BaseClass::OnTakeDamage_Alive( subInfo ); -} - -int CNPCSimpleTalker::SelectNonCombatSpeechSchedule() -{ - if ( !IsOkToSpeak() ) - return SCHED_NONE; - - // talk about world - if ( ShouldSpeakRandom( m_nSpeak * 2, GetSpeechFilter() ? GetSpeechFilter()->GetIdleModifier() : 1.0 ) ) - { - //Msg("standing idle speak\n" ); - return SCHED_TALKER_IDLE_SPEAK; - } - - // failed to speak, so look at the player if he's around - if ( AI_IsSinglePlayer() && GetExpresser()->CanSpeak() && HasCondition ( COND_SEE_PLAYER ) && random->RandomInt( 0, 6 ) == 0 ) - { - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - Assert( pPlayer ); - - if ( pPlayer ) - { - // watch the client. - Vector forward; - AngleVectors( pPlayer->GetLocalAngles(), &forward ); - if ( ( pPlayer->GetAbsOrigin() - GetAbsOrigin() ).Length2D() < TALKER_STARE_DIST && - UTIL_DotPoints( pPlayer->GetAbsOrigin(), GetAbsOrigin(), forward ) >= m_flFieldOfView ) - { - // go into the special STARE schedule if the player is close, and looking at me too. - return SCHED_TALKER_IDLE_WATCH_CLIENT_STARE; - } - - return SCHED_TALKER_IDLE_WATCH_CLIENT; - } - } - else - { - // look at who we're talking to - if ( GetSpeechTarget() && GetExpresser()->IsSpeaking() ) - return SCHED_TALKER_IDLE_EYE_CONTACT; - } - return SCHED_NONE; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CNPCSimpleTalker::CanSayHello( void ) -{ -#ifndef HL1_DLL - if ( Classify() == CLASS_PLAYER_ALLY_VITAL ) - return false; -#endif - - if ( GetSpeechFilter() && GetSpeechFilter()->NeverSayHello() ) - return false; - - if ( !GetExpresser()->CanSpeakConcept(TLK_HELLO) || GetExpresser()->SpokeConcept(TLK_HELLO) ) - return false; - - if ( !IsOkToSpeak() ) - return false; - - return true; -} - -void CNPCSimpleTalker::OnStartingFollow( CBaseEntity *pTarget ) -{ - GetExpresser()->SetSpokeConcept( TLK_HELLO, NULL ); // Don't say hi after you've started following - if ( IsOkToSpeak() ) // don't speak if idle talk is blocked. player commanded/use follow will always speak - Speak( TLK_STARTFOLLOW ); - SetSpeechTarget( GetTarget() ); - ClearCondition( COND_PLAYER_PUSHING ); -} - -void CNPCSimpleTalker::OnStoppingFollow( CBaseEntity *pTarget ) -{ - if ( !(m_afMemory & bits_MEMORY_PROVOKED) ) - { - if ( IsOkToCombatSpeak() ) - { - if ( pTarget == NULL ) - Speak( TLK_STOPFOLLOW ); - else - Speak( TLK_STOP ); - } - SetSpeechTarget( FindNearestFriend(true) ); - } -} - -void CNPCSimpleTalker::FollowerUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - // Don't allow use during a scripted_sentence - if ( m_useTime > gpGlobals->curtime ) - return; - - if ( pCaller != NULL && pCaller->IsPlayer() ) - { - if ( !m_FollowBehavior.GetFollowTarget() && IsInterruptable() ) - { -#if TOML_TODO - LimitFollowers( pCaller , 1 ); -#endif - - if ( m_afMemory & bits_MEMORY_PROVOKED ) - Msg( "I'm not following you, you evil person!\n" ); - else - { - StartFollowing( pCaller ); - } - } - else - { - StopFollowing(); - } - } -} - -//----------------------------------------------------------------------------- -void CNPCSimpleTalker::InputIdleRespond( inputdata_t &inputdata ) -{ - // We've been told to respond. Check combat speak, not isoktospeak, because - // we don't want to check the idle speech time. - if (!IsOkToCombatSpeak()) - return; - - IdleRespond(); -} - -int CNPCSimpleTalkerExpresser::SpeakRawSentence( const char *pszSentence, float delay, float volume, soundlevel_t soundlevel, CBaseEntity *pListener ) -{ - char szSpecificSentence[1024]; - int sentenceIndex = -1; - - if ( !pszSentence ) - return sentenceIndex; - - if ( pszSentence[0] == AI_SP_START_MONOLOG ) - { - // this sentence command will start this NPC speaking - // lengthy monolog from smaller sentences. - BeginMonolog( (char *)pszSentence, pListener ); - return -1; - } - else if ( pszSentence[0] == AI_SP_MONOLOG_LINE ) - { - Q_strncpy(szSpecificSentence, pszSentence, sizeof(szSpecificSentence) ); - szSpecificSentence[0] = AI_SP_SPECIFIC_SENTENCE; - pszSentence = szSpecificSentence; - } - else - { - // this bit of speech is interrupting my monolog! - SuspendMonolog( 0 ); - } - - return CAI_Expresser::SpeakRawSentence( pszSentence, delay, volume, soundlevel, pListener ); -} - -//------------------------------------- - -void CNPCSimpleTalkerExpresser::BeginMonolog( char *pszSentenceName, CBaseEntity *pListener ) -{ - if( pListener ) - { - m_hMonologTalkTarget = pListener; - } - else - { - Warning( "NULL Listener in BeginMonolog()!\n" ); - Assert(0); - EndMonolog(); - return; - } - - Q_strncpy( m_szMonologSentence, pszSentenceName ,sizeof(m_szMonologSentence)); - - // change the "AI_SP_START_MONOLOG" to an "AI_SP_MONOLOG_LINE". m_sMonologSentence is now the - // string we'll tack numbers onto to play sentences from this group in - // sequential order. - m_szMonologSentence[0] = AI_SP_MONOLOG_LINE; - - m_fMonologSuspended = false; - - m_iMonologIndex = 0; -} - -//------------------------------------- - -void CNPCSimpleTalkerExpresser::EndMonolog( void ) -{ - m_szMonologSentence[0] = 0; - m_iMonologIndex = -1; - m_fMonologSuspended = false; - m_hMonologTalkTarget = NULL; -} - -//------------------------------------- - -void CNPCSimpleTalkerExpresser::SpeakMonolog( void ) -{ - int i; - char szSentence[ MONOLOGNAME_LEN ]; - - if( !HasMonolog() ) - { - return; - } - - if( CanSpeak() ) - { - if( m_fMonologSuspended ) - { - if ( GetOuter()->ShouldResumeMonolog() ) - { - ResumeMonolog(); - } - - return; - } - - Q_snprintf( szSentence,sizeof(szSentence), "%s%d", m_szMonologSentence, m_iMonologIndex ); - m_iMonologIndex++; - - i = SpeakRawSentence( szSentence, 0, VOL_NORM ); - - if ( i == -1 ) - { - EndMonolog(); - } - } - else - { - if( GetOuter()->ShouldSuspendMonolog() ) - { - SuspendMonolog( 0 ); - } - } -} - -//------------------------------------- - -void CNPCSimpleTalkerExpresser::SuspendMonolog( float flInterval ) -{ - if( HasMonolog() ) - { - m_fMonologSuspended = true; - } - - // free up other characters to speak. - if ( GetSink()->UseSemaphore() ) - { - GetSpeechSemaphore( GetOuter() )->Release(); - } -} - -//------------------------------------- - -void CNPCSimpleTalkerExpresser::ResumeMonolog( void ) -{ - if( m_iMonologIndex > 0 ) - { - // back up and repeat what I was saying - // when interrupted. - m_iMonologIndex--; - } - - GetOuter()->OnResumeMonolog(); - m_fMonologSuspended = false; -} - -// try to smell something -void CNPCSimpleTalker::TrySmellTalk( void ) -{ - if ( !IsOkToSpeak() ) - return; - - if ( HasCondition( COND_SMELL ) && GetExpresser()->CanSpeakConcept( TLK_SMELL ) ) - Speak( TLK_SMELL ); -} - -void CNPCSimpleTalker::OnChangeRunningBehavior( CAI_BehaviorBase *pOldBehavior, CAI_BehaviorBase *pNewBehavior ) -{ - BaseClass::OnChangeRunningBehavior( pOldBehavior, pNewBehavior ); - - CAI_FollowBehavior *pFollowBehavior; - if ( ( pFollowBehavior = dynamic_cast(pNewBehavior) ) != NULL ) - { - OnStartingFollow( pFollowBehavior->GetFollowTarget() ); - } - else if ( ( pFollowBehavior = dynamic_cast(pOldBehavior) ) != NULL ) - { - OnStoppingFollow( pFollowBehavior->GetFollowTarget() ); - } -} - - -bool CNPCSimpleTalker::OnBehaviorChangeStatus( CAI_BehaviorBase *pBehavior, bool fCanFinishSchedule ) -{ - bool interrupt = BaseClass::OnBehaviorChangeStatus( pBehavior, fCanFinishSchedule ); - if ( !interrupt ) - { - interrupt = ( dynamic_cast(pBehavior) != NULL && ( m_NPCState == NPC_STATE_IDLE || m_NPCState == NPC_STATE_ALERT ) ); - } - return interrupt; - -} -//----------------------------------------------------------------------------- -// Purpose: Return true if I should speak based on the chance & the speech filter's modifier -//----------------------------------------------------------------------------- -bool CNPCSimpleTalker::ShouldSpeakRandom( int iChance, float flModifier ) -{ - if ( flModifier != 1.0 ) - { - // Avoid divide by zero - if ( !flModifier ) - return false; - - iChance = (int)floor( (float)iChance / flModifier ); - } - - return (random->RandomInt(0,iChance) == 0); -} - - -AI_BEGIN_CUSTOM_NPC(talk_monster,CNPCSimpleTalker) - DECLARE_USES_SCHEDULE_PROVIDER( CAI_FollowBehavior ) - - DECLARE_TASK(TASK_TALKER_RESPOND) - DECLARE_TASK(TASK_TALKER_SPEAK) - DECLARE_TASK(TASK_TALKER_HELLO) - DECLARE_TASK(TASK_TALKER_BETRAYED) - DECLARE_TASK(TASK_TALKER_HEADRESET) - DECLARE_TASK(TASK_TALKER_STOPSHOOTING) - DECLARE_TASK(TASK_TALKER_STARE) - DECLARE_TASK(TASK_TALKER_LOOK_AT_CLIENT) - DECLARE_TASK(TASK_TALKER_CLIENT_STARE) - DECLARE_TASK(TASK_TALKER_EYECONTACT) - DECLARE_TASK(TASK_TALKER_IDEALYAW) - DECLARE_TASK(TASK_TALKER_WAIT_FOR_SEMAPHORE) - - //========================================================= - // > SCHED_TALKER_IDLE_RESPONSE - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_TALKER_IDLE_RESPONSE, - - " Tasks" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" // Stop and listen - " TASK_WAIT 0.5" // Wait until sure it's me they are talking to - " TASK_TALKER_IDEALYAW 0" // look at who I'm talking to - " TASK_FACE_IDEAL 0" - " TASK_TALKER_EYECONTACT 0" // Wait until speaker is done - " TASK_TALKER_WAIT_FOR_SEMAPHORE 0" - " TASK_TALKER_EYECONTACT 0" // Wait until speaker is done - " TASK_TALKER_RESPOND 0" // Wait and then say my response - " TASK_TALKER_IDEALYAW 0" // look at who I'm talking to - " TASK_FACE_IDEAL 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_SIGNAL3" - " TASK_TALKER_EYECONTACT 0" // Wait until speaker is done - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_HEAR_COMBAT" - " COND_PLAYER_PUSHING" - " COND_GIVE_WAY" - ) - - //========================================================= - // > SCHED_TALKER_IDLE_SPEAK - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_TALKER_IDLE_SPEAK, - - " Tasks" - " TASK_TALKER_SPEAK 0" // question or remark - " TASK_TALKER_IDEALYAW 0" // look at who I'm talking to - " TASK_FACE_IDEAL 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_SIGNAL3" - " TASK_TALKER_EYECONTACT 0" - " TASK_WAIT_RANDOM 0.5" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_HEAR_COMBAT" - " COND_PLAYER_PUSHING" - " COND_GIVE_WAY" - ) - - //========================================================= - // > SCHED_TALKER_IDLE_HELLO - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_TALKER_IDLE_HELLO, - - " Tasks" - " TASK_SET_ACTIVITY ACTIVITY:ACT_SIGNAL3" // Stop and talk - " TASK_TALKER_HELLO 0" // Try to say hello to player - " TASK_TALKER_EYECONTACT 0" - " TASK_WAIT 0.5" // wait a bit - " TASK_TALKER_HELLO 0" // Try to say hello to player - " TASK_TALKER_EYECONTACT 0" - " TASK_WAIT 0.5" // wait a bit - " TASK_TALKER_HELLO 0" // Try to say hello to player - " TASK_TALKER_EYECONTACT 0" - " TASK_WAIT 0.5" // wait a bit - " TASK_TALKER_HELLO 0" // Try to say hello to player - " TASK_TALKER_EYECONTACT 0" - " TASK_WAIT 0.5 " // wait a bit - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_PROVOKED" - " COND_HEAR_COMBAT" - " COND_HEAR_DANGER" - " COND_PLAYER_PUSHING" - " COND_GIVE_WAY" - ) - - //========================================================= - // > SCHED_TALKER_IDLE_STOP_SHOOTING - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_TALKER_IDLE_STOP_SHOOTING, - - " Tasks" - " TASK_TALKER_STOPSHOOTING 0" // tell player to stop shooting friend - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - ) - - //========================================================= - // Scold the player before attacking. - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_TALKER_BETRAYED, - - " Tasks" - " TASK_TALKER_BETRAYED 0" - " TASK_WAIT 0.5" - "" - " Interrupts" - " COND_HEAR_DANGER" - ) - - //========================================================= - // > SCHED_TALKER_IDLE_WATCH_CLIENT - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_TALKER_IDLE_WATCH_CLIENT, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_TALKER_LOOK_AT_CLIENT 6" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_PROVOKED" - " COND_HEAR_COMBAT" // sound flags - change these and you'll break the talking code. - " COND_HEAR_DANGER" - " COND_SMELL" - " COND_PLAYER_PUSHING" - " COND_TALKER_CLIENTUNSEEN" - " COND_GIVE_WAY" - " COND_IDLE_INTERRUPT" - ) - - //========================================================= - // > SCHED_TALKER_IDLE_WATCH_CLIENT_STARE - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_TALKER_IDLE_WATCH_CLIENT_STARE, - - " Tasks" - " TASK_STOP_MOVING 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_IDLE" - " TASK_TALKER_CLIENT_STARE 6" - " TASK_TALKER_STARE 0" - " TASK_TALKER_IDEALYAW 0" // look at who I'm talking to - " TASK_FACE_IDEAL 0 " - " TASK_SET_ACTIVITY ACTIVITY:ACT_SIGNAL3" - " TASK_TALKER_EYECONTACT 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_PROVOKED" - " COND_HEAR_COMBAT" // sound flags - change these and you'll break the talking code. - " COND_HEAR_DANGER" - " COND_SMELL" - " COND_PLAYER_PUSHING" - " COND_TALKER_CLIENTUNSEEN" - " COND_GIVE_WAY" - " COND_IDLE_INTERRUPT" - ) - - //========================================================= - // > SCHED_TALKER_IDLE_EYE_CONTACT - //========================================================= - DEFINE_SCHEDULE - ( - SCHED_TALKER_IDLE_EYE_CONTACT, - - " Tasks" - " TASK_TALKER_IDEALYAW 0" // look at who I'm talking to - " TASK_FACE_IDEAL 0" - " TASK_SET_ACTIVITY ACTIVITY:ACT_SIGNAL3" - " TASK_TALKER_EYECONTACT 0" // Wait until speaker is done - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_HEAR_DANGER" - " COND_HEAR_COMBAT" - " COND_PLAYER_PUSHING" - " COND_GIVE_WAY" - " COND_IDLE_INTERRUPT" - ) - -AI_END_CUSTOM_NPC() diff --git a/game/server/npc_talker.h b/game/server/npc_talker.h deleted file mode 100644 index ee86078d5..000000000 --- a/game/server/npc_talker.h +++ /dev/null @@ -1,248 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef TALKNPC_H -#define TALKNPC_H - -#ifdef _LINUX -#undef time -#include -#endif - -#if !defined _XBOX && defined _MSC_VER -#pragma warning(push) -#include -#pragma warning(pop) -#endif - -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_playerally.h" - -#include "soundflags.h" - -#include "ai_task.h" -#include "ai_schedule.h" -#include "ai_default.h" -#include "ai_speech.h" -#include "ai_basenpc.h" -#include "ai_behavior.h" -#include "ai_behavior_follow.h" - -#include "tier0/memdbgon.h" - -//========================================================= -// Talking NPC base class -// Used for scientists and barneys -//========================================================= - -#define TLK_CFRIENDS 4 - -//============================================================================= -// >> CNPCSimpleTalker -//============================================================================= - -#define MONOLOGNAME_LEN 16 // sentence names passed as monolog may be no longer than this. -#define AI_SP_START_MONOLOG '~' -#define AI_SP_MONOLOG_LINE '@' - -class CNPCSimpleTalker; - -class CNPCSimpleTalkerExpresser : public CAI_ComponentWithOuter -{ -public: - CNPCSimpleTalkerExpresser( CNPCSimpleTalker *pOuter ) - : CAI_ComponentWithOuter( pOuter ) - { - EndMonolog(); - } - - virtual int SpeakRawSentence( const char *pszSentence, float delay, float volume = VOL_NORM, soundlevel_t soundlevel = SNDLVL_TALKING, CBaseEntity *pListener = NULL ); - - // -------------------------------- - // - // Monologue operations - // - - bool HasMonolog( void ) { return m_iMonologIndex != -1; }; - void BeginMonolog( char *pszSentenceName, CBaseEntity *pListener ); - void EndMonolog( void ); - void SpeakMonolog( void ); - - void SuspendMonolog( float flInterval ); - void ResumeMonolog( void ); - - CBaseEntity *GetMonologueTarget() { return m_hMonologTalkTarget.Get(); } - - // -------------------------------- - // - // Monologue data - // - char m_szMonologSentence[MONOLOGNAME_LEN]; // The name of the sentence group for the monolog I'm speaking. - int m_iMonologIndex; // Which sentence from the group I should be speaking. - bool m_fMonologSuspended; - EHANDLE m_hMonologTalkTarget; // Who I'm trying to deliver my monolog to. - - DECLARE_SIMPLE_DATADESC(); -}; - -//------------------------------------- - -class CNPCSimpleTalker : public CAI_PlayerAlly -{ - DECLARE_CLASS( CNPCSimpleTalker, CAI_PlayerAlly ); -public: - void Precache( void ); - virtual bool KeyValue( const char *szKeyName, const char *szValue ); - - virtual CAI_Expresser *CreateExpresser() { return new CNPCSimpleTalkerExpresser(this); } - - virtual void StartFollowing( CBaseEntity *pLeader ) { m_FollowBehavior.SetFollowTarget( pLeader ); DeferSchedulingToBehavior( &m_FollowBehavior ); } - virtual void StopFollowing( ) { m_FollowBehavior.SetFollowTarget( NULL ); DeferSchedulingToBehavior( NULL ); } - CBaseEntity *GetFollowTarget( void ) { return m_FollowBehavior.GetFollowTarget(); } - - virtual void OnChangeRunningBehavior( CAI_BehaviorBase *pOldBehavior, CAI_BehaviorBase *pNewBehavior ); - bool OnBehaviorChangeStatus( CAI_BehaviorBase *pBehavior, bool fCanFinishSchedule ); - - int PlayScriptedSentence( const char *pszSentence, float delay, float volume, soundlevel_t soundlevel, bool bConcurrent, CBaseEntity *pListener ); - virtual void FollowerUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - void Event_Killed( const CTakeDamageInfo &info ); - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - - bool CreateBehaviors() - { - AddBehavior( &m_FollowBehavior ); - return BaseClass::CreateBehaviors(); - } - - void BuildScheduleTestBits( void ); - void PrescheduleThink( void ); - virtual int SelectSchedule( void ); - virtual int SelectNonCombatSpeechSchedule(); - void StartTask( const Task_t *pTask ); - void RunTask( const Task_t *pTask ); - void HandleAnimEvent( animevent_t *pEvent ); - Activity NPC_TranslateActivity( Activity newActivity ); - - virtual void OnStartingFollow( CBaseEntity *pTarget ); - virtual void OnStoppingFollow( CBaseEntity *pTarget ); - - virtual void DeferAllIdleSpeech( float flDelay, CAI_BaseNPC *pIgnore = NULL ); - bool ShouldSpeakRandom( int iChance, float flModifier ); - - // For following - virtual void DeclineFollowing( void ) {} - void LimitFollowers( CBaseEntity *pPlayer, int maxFollowers ); - - float GetUseTime() const { return m_useTime; } - - //========================================================= - // TalkNPC schedules - //========================================================= - enum - { - SCHED_TALKER_IDLE_RESPONSE = BaseClass::NEXT_SCHEDULE, - SCHED_TALKER_IDLE_SPEAK, - SCHED_TALKER_IDLE_HELLO, - SCHED_TALKER_IDLE_STOP_SHOOTING, - SCHED_TALKER_IDLE_WATCH_CLIENT, - SCHED_TALKER_IDLE_WATCH_CLIENT_STARE, - SCHED_TALKER_IDLE_EYE_CONTACT, - SCHED_TALKER_BETRAYED, - - // !ALWAYS LAST! - NEXT_SCHEDULE, - }; - - //========================================================= - // TalkNPC tasks - //========================================================= - enum - { - TASK_TALKER_RESPOND = BaseClass::NEXT_TASK, // say my response - TASK_TALKER_SPEAK, // question or remark - TASK_TALKER_HELLO, // Try to say hello to player - TASK_TALKER_BETRAYED, // Player killed an ally - TASK_TALKER_HEADRESET, // reset head position - TASK_TALKER_STOPSHOOTING, // tell player to stop shooting friend - TASK_TALKER_STARE, // let the player know I know he's staring at me. - TASK_TALKER_LOOK_AT_CLIENT,// faces player if not moving and not talking and in idle. - TASK_TALKER_CLIENT_STARE, // same as look at client, but says something if the player stares. - TASK_TALKER_EYECONTACT, // maintain eyecontact with person who I'm talking to - TASK_TALKER_IDEALYAW, // set ideal yaw to face who I'm talking to - TASK_FIND_LOCK_HINTNODE_HEALTH, // Find & lock a nearby healthkit hintnode to heal myself at - TASK_TALKER_WAIT_FOR_SEMAPHORE, - - // !ALWAYS LAST! - NEXT_TASK, - }; - -//private: - virtual bool IsValidSpeechTarget( int flags, CBaseEntity *pEntity ); - - CBaseEntity *FindNearestFriend(bool fPlayer); - - bool IsOkToSpeak( void ); - - void SayHelloToPlayer( CBaseEntity *pPlayer ); - virtual bool CanSayHello( void ); - virtual int FIdleHello( void ); - - // Inputs - void InputIdleRespond( inputdata_t &inputdata ); - - // Conversations / communication - void IdleRespond( void ); - int FIdleSpeak( void ); - void FIdleSpeakWhileMoving( void ); - int FIdleStare( void ); - bool SpeakQuestionFriend( CBaseEntity *pFriend ); - bool SpeakAnswerFriend( CBaseEntity *pFriend ); - void TrySmellTalk( void ); - - virtual void SetAnswerQuestion( CNPCSimpleTalker *pSpeaker ); - - bool ShouldSuspendMonolog( void ); - bool ShouldResumeMonolog( void ); - void OnResumeMonolog() { Speak( TLK_RESUME ); } - - int m_nSpeak; // number of times initiated talking - float m_flNextIdleSpeechTime; - - static const char *m_szFriends[TLK_CFRIENDS]; // array of friend names - CBaseEntity *EnumFriends( CBaseEntity *pentPrevious, int listNumber, bool bTrace ); - - virtual int FriendNumber( int arrayNumber ) { return arrayNumber; } - void ShutUpFriends( void ); - void AlertFriends( CBaseEntity *pKiller ); - - string_t m_iszUse; // Custom +USE sentence group (follow) - string_t m_iszUnUse; // Custom +USE sentence group (stop following) - -protected: - CAI_FollowBehavior m_FollowBehavior; - float m_useTime; // Don't allow +USE until this time - - //--------------------------------- - - DECLARE_DATADESC(); -#ifndef _XBOX - DEFINE_CUSTOM_AI; -#else -public: - DEFINE_CUSTOM_AI; -private: -#endif -}; - -#include "tier0/memdbgoff.h" - -#endif //TALKNPC_H diff --git a/game/server/npc_vehicledriver.cpp b/game/server/npc_vehicledriver.cpp deleted file mode 100644 index 730d11e60..000000000 --- a/game/server/npc_vehicledriver.cpp +++ /dev/null @@ -1,1193 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "ai_network.h" -#include "ai_default.h" -#include "ai_schedule.h" -#include "ai_hull.h" -#include "ai_node.h" -#include "ai_task.h" -#include "ai_senses.h" -#include "ai_navigator.h" -#include "ai_route.h" -#include "entitylist.h" -#include "soundenvelope.h" -#include "gamerules.h" -#include "ndebugoverlay.h" -#include "soundflags.h" -#include "trains.h" -#include "globalstate.h" -#include "vehicle_base.h" -#include "npc_vehicledriver.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define DRIVER_DEBUG_PATH 1 -#define DRIVER_DEBUG_PATH_SPLINE 2 - -//------------------------------------ -// -//------------------------------------ -ConVar g_debug_vehicledriver( "g_debug_vehicledriver", "0", FCVAR_CHEAT ); - -BEGIN_DATADESC( CNPC_VehicleDriver ) - DEFINE_KEYFIELD( m_iszVehicleName, FIELD_STRING, "vehicle" ), -// DEFINE_FIELD( m_hVehicle, FIELD_EHANDLE ), - // DEFINE_FIELD( m_pVehicleInterface, FIELD_POINTER ), - DEFINE_FIELD( m_hVehicleEntity, FIELD_EHANDLE ), - // DEFINE_FIELD( m_Waypoints, FIELD_???? ), - // DEFINE_FIELD( m_pCurrentWaypoint, FIELD_POINTER ), - // DEFINE_FIELD( m_pNextWaypoint, FIELD_POINTER ), - DEFINE_FIELD( m_vecDesiredVelocity, FIELD_VECTOR ), - DEFINE_FIELD( m_vecDesiredPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecPrevPoint, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecPrevPrevPoint, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecPostPoint, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecPostPostPoint, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_flDistanceAlongSpline, FIELD_FLOAT ), - DEFINE_KEYFIELD( m_flDriversMaxSpeed, FIELD_FLOAT, "drivermaxspeed" ), - DEFINE_KEYFIELD( m_flDriversMinSpeed, FIELD_FLOAT, "driverminspeed" ), - DEFINE_FIELD( m_flMaxSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_flGoalSpeed, FIELD_FLOAT ), - //DEFINE_KEYFIELD( m_flInitialSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_flSteering, FIELD_FLOAT ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetDriversMaxSpeed", InputSetDriversMaxSpeed ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetDriversMinSpeed", InputSetDriversMinSpeed ), - - DEFINE_INPUTFUNC( FIELD_VOID, "StartForward", InputStartForward ), - DEFINE_INPUTFUNC( FIELD_VOID, "Stop", InputStop ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartFiring", InputStartFiring ), - DEFINE_INPUTFUNC( FIELD_VOID, "StopFiring", InputStopFiring ), - DEFINE_INPUTFUNC( FIELD_STRING, "GotoPathCorner", InputGotoPathCorner ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( npc_vehicledriver, CNPC_VehicleDriver ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CNPC_VehicleDriver::CNPC_VehicleDriver( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CNPC_VehicleDriver::~CNPC_VehicleDriver( void ) -{ - ClearWaypoints(); -} - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CNPC_VehicleDriver::Spawn( void ) -{ - Precache( ); - - BaseClass::Spawn(); - - CapabilitiesClear(); - CapabilitiesAdd( bits_CAP_MOVE_GROUND ); - CapabilitiesAdd( bits_CAP_MOVE_SHOOT ); - - SetModel( "models/roller_vehicledriver.mdl" ); - SetHullType(HULL_LARGE); - SetHullSizeNormal(); - m_iMaxHealth = m_iHealth = 1; - m_flFieldOfView = VIEW_FIELD_FULL; - - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_SOLID ); - SetMoveType( MOVETYPE_NONE ); - AddEffects( EF_NODRAW ); - - m_lifeState = LIFE_ALIVE; - SetCycle( 0 ); - ResetSequenceInfo(); - - AddFlag( FL_NPC ); - - m_flMaxSpeed = 0; - m_flGoalSpeed = m_flInitialSpeed; - - m_vecDesiredVelocity = vec3_origin; - m_vecPrevPoint = vec3_origin; - m_vecPrevPrevPoint = vec3_origin; - m_vecPostPoint = vec3_origin; - m_vecPostPostPoint = vec3_origin; - m_vecDesiredPosition = vec3_origin; - m_flSteering = 45; - m_flDistanceAlongSpline = 0.2; - m_pCurrentWaypoint = m_pNextWaypoint = NULL; - - GetNavigator()->SetPathcornerPathfinding( false ); - - NPCInit(); - - m_takedamage = DAMAGE_NO; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_VehicleDriver::Precache( void ) -{ - PrecacheModel( "models/roller_vehicledriver.mdl" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_VehicleDriver::Activate( void ) -{ - BaseClass::Activate(); - - // Restore doesn't need to do this - if ( m_hVehicleEntity ) - return; - - // Make sure we've got a vehicle - if ( m_iszVehicleName == NULL_STRING ) - { - Warning( "npc_vehicledriver %s has no vehicle to drive.\n", STRING(GetEntityName()) ); - UTIL_Remove( this ); - return; - } - - m_hVehicleEntity = (gEntList.FindEntityByName( NULL, STRING(m_iszVehicleName) )); - if ( !m_hVehicleEntity ) - { - Warning( "npc_vehicledriver %s couldn't find his vehicle named %s.\n", STRING(GetEntityName()), STRING(m_iszVehicleName) ); - UTIL_Remove( this ); - return; - } - - m_pVehicleInterface = m_hVehicleEntity->GetServerVehicle(); - Assert( m_pVehicleInterface ); - if ( !m_pVehicleInterface->NPC_CanDrive() ) - { - Warning( "npc_vehicledriver %s doesn't know how to drive vehicle %s.\n", STRING(GetEntityName()), STRING(m_hVehicleEntity->GetEntityName()) ); - UTIL_Remove( this ); - return; - } - - // We've found our vehicle. Move to it and start following it. - SetAbsOrigin( m_hVehicleEntity->WorldSpaceCenter() ); - m_pVehicleInterface->NPC_SetDriver( this ); - - RecalculateSpeeds(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_VehicleDriver::OnRestore( void ) -{ - BaseClass::OnRestore(); - if ( m_hVehicleEntity ) - { - m_pVehicleInterface = m_hVehicleEntity->GetServerVehicle(); - Assert( m_pVehicleInterface ); - } -} -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_VehicleDriver::UpdateOnRemove( void ) -{ - // Leave our vehicle - if ( m_pVehicleInterface ) - { - m_pVehicleInterface->NPC_SetDriver( NULL ); - } - - BaseClass::UpdateOnRemove(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_VehicleDriver::PrescheduleThink( void ) -{ - if ( !m_hVehicleEntity ) - { - m_pVehicleInterface = NULL; - UTIL_Remove( this ); - return; - } - - // Keep up with my vehicle - SetAbsOrigin( m_hVehicleEntity->WorldSpaceCenter() ); - SetAbsAngles( m_hVehicleEntity->GetAbsAngles() ); - - BaseClass::PrescheduleThink(); - - if ( m_NPCState == NPC_STATE_IDLE ) - { - m_pVehicleInterface->NPC_Brake(); - return; - } - - // If we've been picked up by something (dropship probably), abort. - if ( m_hVehicleEntity->GetParent() ) - { - SetState( NPC_STATE_IDLE ); - ClearWaypoints(); - SetGoalEnt( NULL ); - return; - } - - DriveVehicle(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_VehicleDriver::SelectSchedule( void ) -{ - // Vehicle driver hangs in the air inside the vehicle, so we never need to fall to ground - ClearCondition( COND_FLOATING_OFF_GROUND ); - - if ( HasSpawnFlags(SF_VEHICLEDRIVER_INACTIVE) ) - { - SetState( NPC_STATE_IDLE ); - return SCHED_VEHICLEDRIVER_INACTIVE; - } - - if ( GetGoalEnt() ) - return SCHED_VEHICLEDRIVER_DRIVE_PATH; - - switch ( m_NPCState ) - { - case NPC_STATE_IDLE: - break; - - case NPC_STATE_ALERT: - break; - - case NPC_STATE_COMBAT: - { - if ( HasCondition(COND_NEW_ENEMY) || HasCondition( COND_ENEMY_DEAD ) ) - return BaseClass::SelectSchedule(); - - if ( HasCondition(COND_SEE_ENEMY) ) - { - // we can see the enemy - if ( HasCondition(COND_CAN_RANGE_ATTACK2) ) - return SCHED_RANGE_ATTACK2; - if ( HasCondition(COND_CAN_RANGE_ATTACK1) ) - return SCHED_RANGE_ATTACK1; - - // What to do here? Not necessarily easy to face enemy. - //if ( HasCondition(COND_NOT_FACING_ATTACK) ) - //return SCHED_COMBAT_FACE; - } - - // We can see him, but can't shoot him. Just wait and hope he comes closer. - return SCHED_VEHICLEDRIVER_COMBAT_WAIT; - } - break; - - default: - break; - } - - return BaseClass::SelectSchedule(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_VehicleDriver::RangeAttack1Conditions( float flDot, float flDist ) -{ - // Vehicle not ready to fire again yet? - if ( m_pVehicleInterface->Weapon_PrimaryCanFireAt() > gpGlobals->curtime ) - return 0; - - // Check weapon range - float flMinRange, flMaxRange; - m_pVehicleInterface->Weapon_PrimaryRanges( &flMinRange, &flMaxRange ); - if ( flDist < flMinRange ) - return COND_TOO_CLOSE_TO_ATTACK; - if ( flDist > flMaxRange ) - return COND_TOO_FAR_TO_ATTACK; - - // Don't shoot backwards - Vector vecForward; - Vector vecToTarget = (GetEnemy()->GetAbsOrigin() - GetAbsOrigin()); - VectorNormalize(vecToTarget); - m_hVehicleEntity->GetVectors( &vecForward, NULL, NULL ); - float flForwardDot = DotProduct( vecForward, vecToTarget ); - if ( flForwardDot < 0 && fabs(flDot) < 0.5 ) - return COND_NOT_FACING_ATTACK; - - return COND_CAN_RANGE_ATTACK1; -} - -//========================================================= -// RangeAttack2Conditions -//========================================================= -int CNPC_VehicleDriver::RangeAttack2Conditions( float flDot, float flDist ) -{ - // Vehicle not ready to fire again yet? - if ( m_pVehicleInterface->Weapon_SecondaryCanFireAt() > gpGlobals->curtime ) - return 0; - - // Check weapon range - float flMinRange, flMaxRange; - m_pVehicleInterface->Weapon_SecondaryRanges( &flMinRange, &flMaxRange ); - if ( flDist < flMinRange ) - return COND_TOO_CLOSE_TO_ATTACK; - if ( flDist > flMaxRange ) - return COND_TOO_FAR_TO_ATTACK; - - return COND_CAN_RANGE_ATTACK2; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CNPC_VehicleDriver::TranslateSchedule( int scheduleType ) -{ - switch ( scheduleType ) - { - case SCHED_COMBAT_FACE: - { - // Vehicles can't rotate, so don't try and face - return TranslateSchedule( SCHED_CHASE_ENEMY ); - } - break; - - case SCHED_ALERT_FACE: - { - // Vehicles can't rotate, so don't try and face - return SCHED_ALERT_STAND; - } - break; - - case SCHED_CHASE_ENEMY_FAILED: - case SCHED_FAIL: - { - return SCHED_FAIL; - } - break; - } - - return BaseClass::TranslateSchedule(scheduleType); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTask - -//----------------------------------------------------------------------------- -void CNPC_VehicleDriver::StartTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_RUN_PATH: - case TASK_WALK_PATH: - TaskComplete(); - break; - - case TASK_FACE_IDEAL: - case TASK_FACE_ENEMY: - { - // Vehicle ignores face commands, since it can't rotate on the spot. - TaskComplete(); - } - break; - - case TASK_VEHICLEDRIVER_GET_PATH: - { - if ( !GetGoalEnt() ) - { - TaskFail( FAIL_NO_TARGET ); - return; - } - - CheckForTeleport(); - - if ( g_debug_vehicledriver.GetInt() & DRIVER_DEBUG_PATH ) - { - NDebugOverlay::Box( GetGoalEnt()->GetAbsOrigin(), -Vector(50,50,50), Vector(50,50,50), 255,255,255, true, 5); - } - - AI_NavGoal_t goal( GOALTYPE_PATHCORNER, GetGoalEnt()->GetLocalOrigin(), ACT_WALK, AIN_DEF_TOLERANCE, AIN_YAW_TO_DEST); - if ( !GetNavigator()->SetGoal( goal ) ) - { - TaskFail( FAIL_NO_ROUTE ); - return; - } - - TaskComplete(); - } - break; - - case TASK_WAIT_FOR_MOVEMENT: - { - if (GetNavigator()->GetGoalType() == GOALTYPE_NONE) - { - TaskComplete(); - GetNavigator()->StopMoving(); // Stop moving - } - else if (!GetNavigator()->IsGoalActive()) - { - SetIdealActivity( GetStoppedActivity() ); - } - else - { - // Check validity of goal type - ValidateNavGoal(); - } - } - break; - - default: - BaseClass::StartTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_VehicleDriver::RunTask( const Task_t *pTask ) -{ - switch( pTask->iTask ) - { - case TASK_RANGE_ATTACK1: - { - // Vehicle driver has no animations, so fire a burst at the target - CBaseEntity *pEnemy = GetEnemy(); - if ( pEnemy ) - { - // TODO: Get a bodytarget from the firing point of the gun in the vehicle - Vector vecTarget = GetEnemy()->BodyTarget( GetAbsOrigin(), false ); - m_pVehicleInterface->NPC_AimPrimaryWeapon( vecTarget ); - m_pVehicleInterface->NPC_PrimaryFire(); - TaskComplete(); - } - else - { - TaskFail(FAIL_NO_ENEMY); - return; - } - } - break; - - case TASK_RANGE_ATTACK2: - { - // Vehicle driver has no animations, so fire a burst at the target - CBaseEntity *pEnemy = GetEnemy(); - if ( pEnemy ) - { - // TODO: Get a bodytarget from the firing point of the gun in the vehicle - Vector vecTarget = GetEnemy()->BodyTarget( GetAbsOrigin(), false ); - m_pVehicleInterface->NPC_AimSecondaryWeapon( vecTarget ); - m_pVehicleInterface->NPC_SecondaryFire(); - TaskComplete(); - } - else - { - TaskFail(FAIL_NO_ENEMY); - return; - } - } - break; - - case TASK_WAIT_FOR_MOVEMENT: - { - BaseClass::RunTask( pTask ); - - if ( HasCondition(COND_SEE_ENEMY) ) - { - // we can see the enemy - if ( HasCondition(COND_CAN_RANGE_ATTACK2) ) - { - ChainRunTask( TASK_RANGE_ATTACK2, pTask->flTaskData ); - } - if ( HasCondition(COND_CAN_RANGE_ATTACK1) ) - { - ChainRunTask( TASK_RANGE_ATTACK1, pTask->flTaskData ); - } - } - } - break; - - default: - BaseClass::RunTask( pTask ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_VehicleDriver::GatherEnemyConditions( CBaseEntity *pEnemy ) -{ - BaseClass::GatherEnemyConditions(pEnemy); -} - -//----------------------------------------------------------------------------- -// Purpose: Overridden because if the player is a criminal, we hate them. -//----------------------------------------------------------------------------- -Disposition_t CNPC_VehicleDriver::IRelationType(CBaseEntity *pTarget) -{ - // If it's the player and they are a criminal, we hate them. - if (pTarget->Classify() == CLASS_PLAYER) - { - if (GlobalEntity_GetState("gordon_precriminal") == GLOBAL_ON) - { - return(D_NU); - } - } - - return(BaseClass::IRelationType(pTarget)); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_VehicleDriver::OverrideMove( float flInterval ) -{ - if ( !m_hVehicleEntity ) - return true; - - // If we don't have a maxspeed, we've been stopped, so abort early - // Or we've been picked up by something (dropship probably). - if ( !m_flMaxSpeed || m_hVehicleEntity->GetParent() ) - { - m_pVehicleInterface->NPC_Brake(); - return true; - } - - // ----------------------------------------------------------------- - // If I have a route, keep it updated and move toward target - // ------------------------------------------------------------------ - if (GetNavigator()->IsGoalActive()) - { - if ( OverridePathMove( flInterval ) ) - return true; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_VehicleDriver::CalculatePostPoints( void ) -{ - m_vecPostPoint = m_vecDesiredPosition; - m_vecPostPostPoint = m_vecDesiredPosition; - - // If we have a waypoint beyond our current, use it instead. - if ( !GetNavigator()->CurWaypointIsGoal() ) - { - AI_Waypoint_t *pCurWaypoint = GetNavigator()->GetPath()->GetCurWaypoint(); - m_vecPostPoint = pCurWaypoint->GetNext()->GetPos(); - if ( pCurWaypoint->GetNext()->GetNext() ) - { - m_vecPostPostPoint = pCurWaypoint->GetNext()->GetNext()->GetPos(); - } - else - { - m_vecPostPostPoint = m_vecPostPoint; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Destroy our current waypoints -//----------------------------------------------------------------------------- -void CNPC_VehicleDriver::ClearWaypoints( void ) -{ - m_vecDesiredPosition = vec3_origin; - if ( m_pCurrentWaypoint ) - { - delete m_pCurrentWaypoint; - m_pCurrentWaypoint = NULL; - } - if ( m_pNextWaypoint ) - { - delete m_pNextWaypoint; - m_pNextWaypoint = NULL; - } -} - -//----------------------------------------------------------------------------- -// Purpose: We've hit a waypoint. Handle it, and return true if this is the -// end of the path. -//----------------------------------------------------------------------------- -bool CNPC_VehicleDriver::WaypointReached( void ) -{ - // We reached our current waypoint. - m_vecPrevPrevPoint = m_vecPrevPoint; - m_vecPrevPoint = GetAbsOrigin(); - - // If we've got to our goal, we're done here. - if ( GetNavigator()->CurWaypointIsGoal() ) - { - // Necessary for InPass outputs to be fired, is a no-op otherwise - GetNavigator()->AdvancePath(); - - // Stop pathing - ClearWaypoints(); - TaskComplete(); - SetGoalEnt( NULL ); - return true; - } - - AI_Waypoint_t *pCurWaypoint = GetNavigator()->GetPath()->GetCurWaypoint(); - if ( !pCurWaypoint ) - return false; - - // Check to see if the waypoint wants us to change speed - if ( pCurWaypoint->Flags() & bits_WP_TO_PATHCORNER ) - { - CBaseEntity *pEntity = pCurWaypoint->hPathCorner; - if ( pEntity ) - { - if ( pEntity->m_flSpeed > 0 ) - { - if ( pEntity->m_flSpeed <= 1.0 ) - { - m_flDriversMaxSpeed = pEntity->m_flSpeed; - RecalculateSpeeds(); - } - else - { - Warning("path_track %s tried to tell the npc_vehicledriver to set speed to %.3f. npc_vehicledriver only accepts values between 0 and 1.\n", STRING(pEntity->GetEntityName()), pEntity->m_flSpeed ); - } - } - } - } - - // Get the waypoints for the next part of the path - GetNavigator()->AdvancePath(); - if ( !GetNavigator()->GetPath()->GetCurWaypoint() ) - { - ClearWaypoints(); - TaskComplete(); - SetGoalEnt( NULL ); - return true; - } - - m_vecDesiredPosition = GetNavigator()->GetCurWaypointPos(); - CalculatePostPoints(); - - // Move to the next waypoint - delete m_pCurrentWaypoint; - m_pCurrentWaypoint = m_pNextWaypoint; - m_Waypoints[1] = new CVehicleWaypoint( m_vecPrevPoint, m_vecDesiredPosition, m_vecPostPoint, m_vecPostPostPoint ); - m_pNextWaypoint = m_Waypoints[1]; - - // Drop the spline marker back - m_flDistanceAlongSpline = MAX( 0, m_flDistanceAlongSpline - 1.0 ); - - CheckForTeleport(); - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CNPC_VehicleDriver::OverridePathMove( float flInterval ) -{ - // Setup our initial path data if we've just started running a path - if ( !m_pCurrentWaypoint ) - { - m_vecPrevPoint = GetAbsOrigin(); - m_vecPrevPrevPoint = GetAbsOrigin(); - m_vecDesiredPosition = GetNavigator()->GetCurWaypointPos(); - CalculatePostPoints(); - - // Init our two waypoints - m_Waypoints[0] = new CVehicleWaypoint( m_vecPrevPrevPoint, m_vecPrevPoint, m_vecDesiredPosition, m_vecPostPoint ); - m_Waypoints[1] = new CVehicleWaypoint( m_vecPrevPoint, m_vecDesiredPosition, m_vecPostPoint, m_vecPostPostPoint ); - m_pCurrentWaypoint = m_Waypoints[0]; - m_pNextWaypoint = m_Waypoints[1]; - - m_flDistanceAlongSpline = 0.2; - } - - // Have we reached our target? See if we've passed the current waypoint's plane. - Vector vecAbsMins, vecAbsMaxs; - CollisionProp()->WorldSpaceAABB( &vecAbsMins, &vecAbsMaxs ); - if ( BoxOnPlaneSide( vecAbsMins, vecAbsMaxs, &m_pCurrentWaypoint->planeWaypoint ) == 3 ) - { - if ( WaypointReached() ) - return true; - } - - // Did we bypass it and reach the next one already? - if ( m_pNextWaypoint && BoxOnPlaneSide( vecAbsMins, vecAbsMaxs, &m_pNextWaypoint->planeWaypoint ) == 3 ) - { - if ( WaypointReached() ) - return true; - } - - // We may have just teleported, so check to make sure we have a waypoint - if ( !m_pCurrentWaypoint || !m_pNextWaypoint ) - return false; - - // Figure out which spline we're trucking along - CVehicleWaypoint *pCurrentSplineBeingTraversed = m_pCurrentWaypoint; - if ( m_flDistanceAlongSpline > 1 ) - { - pCurrentSplineBeingTraversed = m_pNextWaypoint; - } - - // Get our current speed, and check it against the length of the spline to know how far to advance our marker - AngularImpulse angVel; - Vector vecVelocity; - IPhysicsObject *pVehiclePhysics = m_hVehicleEntity->VPhysicsGetObject(); - - if( !pVehiclePhysics ) - { - // I think my vehicle has been destroyed. - return false; - } - - pVehiclePhysics->GetVelocity( &vecVelocity, &angVel ); - float flSpeed = vecVelocity.Length(); - float flIncTime = gpGlobals->curtime - GetLastThink(); - float flIncrement = flIncTime * (flSpeed / pCurrentSplineBeingTraversed->GetLength()); - - // Now advance our point along the spline - m_flDistanceAlongSpline = clamp( m_flDistanceAlongSpline + flIncrement, 0, 2); - if ( m_flDistanceAlongSpline > 1 ) - { - // We crossed the spline boundary - pCurrentSplineBeingTraversed = m_pNextWaypoint; - } - - Vector vSplinePoint = pCurrentSplineBeingTraversed->GetPointAt( m_flDistanceAlongSpline > 1 ? m_flDistanceAlongSpline-1 : m_flDistanceAlongSpline ); - Vector vSplineTangent = pCurrentSplineBeingTraversed->GetTangentAt( m_flDistanceAlongSpline > 1 ? m_flDistanceAlongSpline-1 : m_flDistanceAlongSpline ); - - // Now that we've got the target spline point & tangent, use it to decide what our desired velocity is. - // If we're close to the tangent, just use the tangent. Otherwise, Lerp towards it. - Vector vecToDesired = (vSplinePoint - GetAbsOrigin()); - float flDistToDesired = VectorNormalize( vecToDesired ); - float flTangentLength = VectorNormalize( vSplineTangent ); - - if ( flDistToDesired > (flTangentLength * 0.75) ) - { - m_vecDesiredVelocity = vecToDesired * flTangentLength; - } - else - { - VectorLerp( vSplineTangent, vecToDesired * flTangentLength, (flDistToDesired / (flTangentLength * 0.5)), m_vecDesiredVelocity ); - } - - // Decrease speed according to the turn we're trying to make - Vector vecRight; - m_hVehicleEntity->GetVectors( NULL, &vecRight, NULL ); - Vector vecNormVel = m_vecDesiredVelocity; - VectorNormalize( vecNormVel ); - float flDotRight = DotProduct( vecRight, vecNormVel ); - flSpeed = (1.0 - fabs(flDotRight)); - // Don't go slower than we've been told to go - if ( flSpeed < m_flDriversMinSpeed ) - { - flSpeed = m_flDriversMinSpeed; - } - m_vecDesiredVelocity = vecNormVel * (flSpeed * m_flMaxSpeed); - - // Bunch o'debug - if ( g_debug_vehicledriver.GetInt() & DRIVER_DEBUG_PATH ) - { - NDebugOverlay::Box( m_vecPrevPrevPoint, -Vector(15,15,15), Vector(15,15,15), 192,0,0, true, 0.1); - NDebugOverlay::Box( m_vecPrevPoint, -Vector(20,20,20), Vector(20,20,20), 255,0,0, true, 0.1); - NDebugOverlay::Box( m_vecPostPoint, -Vector(20,20,20), Vector(20,20,20), 0,192,0, true, 0.1); - NDebugOverlay::Box( m_vecPostPostPoint, -Vector(20,20,20), Vector(20,20,20), 0,128,0, true, 0.1); - NDebugOverlay::Box( vSplinePoint, -Vector(10,10,10), Vector(10,10,10), 0,0,255, true, 0.1); - NDebugOverlay::Line( vSplinePoint, vSplinePoint + (vSplineTangent * 40), 0,0,255, true, 0.1); - - //NDebugOverlay::HorzArrow( pCurrentSplineBeingTraversed->splinePoints[0], pCurrentSplineBeingTraversed->splinePoints[1], 30, 255,255,255,0, false, 0.1f ); - //NDebugOverlay::HorzArrow( pCurrentSplineBeingTraversed->splinePoints[1], pCurrentSplineBeingTraversed->splinePoints[2], 20, 255,255,255,0, false, 0.1f ); - //NDebugOverlay::HorzArrow( pCurrentSplineBeingTraversed->splinePoints[2], pCurrentSplineBeingTraversed->splinePoints[3], 10, 255,255,255,0, false, 0.1f ); - - // Draw the plane we're checking against for waypoint passing - Vector vecPlaneRight; - CrossProduct( m_pCurrentWaypoint->planeWaypoint.normal, Vector(0,0,1), vecPlaneRight ); - Vector vecPlane = m_pCurrentWaypoint->splinePoints[2]; - NDebugOverlay::Line( vecPlane + (vecPlaneRight * -100), vecPlane + (vecPlaneRight * 100), 255,0,0, true, 0.1); - - // Draw the next plane too - CrossProduct( m_pNextWaypoint->planeWaypoint.normal, Vector(0,0,1), vecPlaneRight ); - vecPlane = m_pNextWaypoint->splinePoints[2]; - NDebugOverlay::Line( vecPlane + (vecPlaneRight * -100), vecPlane + (vecPlaneRight * 100), 192,0,0, true, 0.1); - } - - if ( g_debug_vehicledriver.GetInt() & DRIVER_DEBUG_PATH_SPLINE ) - { - for ( int i = 0; i < 10; i++ ) - { - Vector vecTarget = m_pCurrentWaypoint->GetPointAt( 0.1 * i ); - Vector vecTangent = m_pCurrentWaypoint->GetTangentAt( 0.1 * i ); - VectorNormalize(vecTangent); - NDebugOverlay::Box( vecTarget, -Vector(10,10,10), Vector(10,10,10), 255,0,0, true, 0.1 ); - NDebugOverlay::Line( vecTarget, vecTarget + (vecTangent * 10), 255,255,0, true, 0.1); - } - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: This takes the current place the NPC's trying to get to, figures out -// what keys to press to get the vehicle to go there, and then sends -// them to the vehicle. -//----------------------------------------------------------------------------- -void CNPC_VehicleDriver::DriveVehicle( void ) -{ - AngularImpulse angVel; - Vector vecVelocity; - IPhysicsObject *pVehiclePhysics = m_hVehicleEntity->VPhysicsGetObject(); - if ( !pVehiclePhysics ) - return; - pVehiclePhysics->GetVelocity( &vecVelocity, &angVel ); - float flSpeed = VectorNormalize( vecVelocity ); - - // If we have no target position to drive to, brake to a halt - if ( !m_flMaxSpeed || m_vecDesiredPosition == vec3_origin ) - { - if ( flSpeed > 1 ) - { - m_pVehicleInterface->NPC_Brake(); - } - return; - } - - if ( g_debug_vehicledriver.GetInt() & DRIVER_DEBUG_PATH ) - { - NDebugOverlay::Box(m_vecDesiredPosition, -Vector(20,20,20), Vector(20,20,20), 0,255,0, true, 0.1); - NDebugOverlay::Line(GetAbsOrigin(), GetAbsOrigin() + m_vecDesiredVelocity, 0,255,0, true, 0.1); - } - - m_flGoalSpeed = VectorNormalize(m_vecDesiredVelocity); - - // Is our target in front or behind us? - Vector vecForward, vecRight; - m_hVehicleEntity->GetVectors( &vecForward, &vecRight, NULL ); - float flDot = DotProduct( vecForward, m_vecDesiredVelocity ); - bool bBehind = ( flDot < 0 ); - float flVelDot = DotProduct( vecVelocity, m_vecDesiredVelocity ); - bool bGoingWrongWay = ( flVelDot < 0 ); - - // Figure out whether we should accelerate / decelerate - if ( bGoingWrongWay || (flSpeed < m_flGoalSpeed) ) - { - // If it's behind us, go backwards not forwards - if ( bBehind ) - { - m_pVehicleInterface->NPC_ThrottleReverse(); - } - else - { - m_pVehicleInterface->NPC_ThrottleForward(); - } - } - else - { - // Brake if we're go significantly too fast - if ( (flSpeed - 200) > m_flGoalSpeed ) - { - m_pVehicleInterface->NPC_Brake(); - } - else - { - m_pVehicleInterface->NPC_ThrottleCenter(); - } - } - - // Do we need to turn? - float flDotRight = DotProduct( vecRight, m_vecDesiredVelocity ); - if ( bBehind ) - { - // If we're driving backwards, flip our turning - flDotRight *= -1; - } - // Map it to the vehicle's steering - flDotRight *= (m_flSteering / 90); - - if ( flDotRight < 0 ) - { - // Turn left - m_pVehicleInterface->NPC_TurnLeft( -flDotRight ); - } - else if ( flDotRight > 0 ) - { - // Turn right - m_pVehicleInterface->NPC_TurnRight( flDotRight ); - } - else - { - m_pVehicleInterface->NPC_TurnCenter(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Check to see if we should teleport to the current path corner -//----------------------------------------------------------------------------- -void CNPC_VehicleDriver::CheckForTeleport( void ) -{ - if ( !GetGoalEnt() ) - return; - - CPathTrack *pTrack = dynamic_cast( GetGoalEnt() ); - if ( !pTrack ) - return; - - // Does it have the teleport flag set? - if ( pTrack->HasSpawnFlags( SF_PATH_TELEPORT ) ) - { - AddEffects( EF_NOINTERP ); - - // Teleport the vehicle to the pathcorner - Vector vecMins, vecMaxs; - vecMins = m_hVehicleEntity->CollisionProp()->OBBMins(); - vecMaxs = m_hVehicleEntity->CollisionProp()->OBBMaxs(); - Vector vecTarget = pTrack->GetAbsOrigin() - (vecMins + vecMaxs) * 0.5; - vecTarget.z += ((vecMaxs.z - vecMins.z) * 0.5) + 8; // Safety buffer - - // Orient it to face the next point - QAngle vecAngles = pTrack->GetAbsAngles(); - Vector vecToTarget = vec3_origin; - if ( pTrack->GetNext() ) - { - vecToTarget = (pTrack->GetNext()->GetAbsOrigin() - pTrack->GetAbsOrigin()); - VectorNormalize( vecToTarget ); - - // Vehicles are rotated 90 degrees - VectorAngles( vecToTarget, vecAngles ); - vecAngles[YAW] -= 90; - } - m_hVehicleEntity->Teleport( &vecTarget, &vecAngles, &vec3_origin ); - - // Teleport the driver - SetAbsOrigin( m_hVehicleEntity->WorldSpaceCenter() ); - SetAbsAngles( m_hVehicleEntity->GetAbsAngles() ); - - m_vecPrevPoint = pTrack->GetAbsOrigin(); - - // Move to the next waypoint, we've reached this one - if ( GetNavigator()->GetPath() ) - { - WaypointReached(); - } - - // Clear our waypoints, because the next waypoint is certainly invalid now. - ClearWaypoints(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CNPC_VehicleDriver::GetDefaultNavGoalTolerance() -{ - return 48; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_VehicleDriver::RecalculateSpeeds( void ) -{ - // Get data from the vehicle - const vehicleparams_t *pParams = m_pVehicleInterface->GetVehicleParams(); - if ( pParams ) - { - m_flMaxSpeed = pParams->engine.maxSpeed * m_flDriversMaxSpeed; - m_flSteering = pParams->steering.degreesSlow; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_VehicleDriver::InputSetDriversMaxSpeed( inputdata_t &inputdata ) -{ - m_flDriversMaxSpeed = inputdata.value.Float(); - - RecalculateSpeeds(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_VehicleDriver::InputSetDriversMinSpeed( inputdata_t &inputdata ) -{ - m_flDriversMinSpeed = inputdata.value.Float(); - - RecalculateSpeeds(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_VehicleDriver::InputStartForward( inputdata_t &inputdata ) -{ - CLEARBITS( m_spawnflags, SF_VEHICLEDRIVER_INACTIVE ); - if ( m_NPCState == NPC_STATE_IDLE ) - { - SetState( NPC_STATE_ALERT ); - } - SetCondition( COND_PROVOKED ); - - RecalculateSpeeds(); -} - -//----------------------------------------------------------------------------- -// Purpose: Tell the driver to stop moving -//----------------------------------------------------------------------------- -void CNPC_VehicleDriver::InputStop( inputdata_t &inputdata ) -{ - m_flMaxSpeed = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: Tell the driver to start firing at targets -//----------------------------------------------------------------------------- -void CNPC_VehicleDriver::InputStartFiring( inputdata_t &inputdata ) -{ - CLEARBITS( m_spawnflags, SF_VEHICLEDRIVER_INACTIVE ); - SetCondition( COND_PROVOKED ); - - float flMinRange, flMaxRange; - // If the vehicle has a weapon, set our capability - if ( m_pVehicleInterface->NPC_HasPrimaryWeapon() ) - { - CapabilitiesAdd( bits_CAP_INNATE_RANGE_ATTACK1 ); - m_pVehicleInterface->Weapon_PrimaryRanges( &flMinRange, &flMaxRange ); - - // Ensure the look distances is long enough - if ( m_flDistTooFar < flMaxRange || GetSenses()->GetDistLook() < flMaxRange ) - { - m_flDistTooFar = flMaxRange; - SetDistLook( flMaxRange ); - } - } - - if ( m_pVehicleInterface->NPC_HasSecondaryWeapon() ) - { - CapabilitiesAdd( bits_CAP_INNATE_RANGE_ATTACK2 ); - m_pVehicleInterface->Weapon_SecondaryRanges( &flMinRange, &flMaxRange ); - - // Ensure the look distances is long enough - if ( m_flDistTooFar < flMaxRange || GetSenses()->GetDistLook() < flMaxRange ) - { - m_flDistTooFar = flMaxRange; - SetDistLook( flMaxRange ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Tell the driver to stop firing at targets -//----------------------------------------------------------------------------- -void CNPC_VehicleDriver::InputStopFiring( inputdata_t &inputdata ) -{ - // If the vehicle has a weapon, set our capability - CapabilitiesRemove( bits_CAP_INNATE_RANGE_ATTACK1 ); - CapabilitiesRemove( bits_CAP_INNATE_RANGE_ATTACK2 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CNPC_VehicleDriver::InputGotoPathCorner( inputdata_t &inputdata ) -{ - string_t iszPathName = inputdata.value.StringID(); - if ( iszPathName != NULL_STRING ) - { - CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, iszPathName ); - if ( !pEntity ) - { - Warning("npc_vehicledriver %s couldn't find entity named %s\n", STRING(GetEntityName()), STRING(iszPathName) ); - return; - } - - ClearWaypoints(); - - // Drive to the point - SetGoalEnt( pEntity ); - if ( m_NPCState == NPC_STATE_IDLE ) - { - SetState( NPC_STATE_ALERT ); - } - SetCondition( COND_PROVOKED ); - - // Force him to start forward - InputStartForward( inputdata ); - } -} - -//----------------------------------------------------------------------------- -// -// Schedules -// -//----------------------------------------------------------------------------- - -AI_BEGIN_CUSTOM_NPC( npc_vehicledriver, CNPC_VehicleDriver ) - - //Tasks - DECLARE_TASK( TASK_VEHICLEDRIVER_GET_PATH ) - - // Schedules - DEFINE_SCHEDULE - ( - SCHED_VEHICLEDRIVER_INACTIVE, - - " Tasks" - " TASK_WAIT_INDEFINITE 0" - "" - " Interrupts" - " COND_PROVOKED" - ) - - DEFINE_SCHEDULE - ( - SCHED_VEHICLEDRIVER_COMBAT_WAIT, - - " Tasks" - " TASK_WAIT 5" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_LIGHT_DAMAGE" - " COND_HEAVY_DAMAGE" - " COND_PROVOKED" - " COND_CAN_RANGE_ATTACK1" - " COND_CAN_RANGE_ATTACK2" - ) - - DEFINE_SCHEDULE - ( - SCHED_VEHICLEDRIVER_DRIVE_PATH, - - " Tasks" - " TASK_VEHICLEDRIVER_GET_PATH 0" - " TASK_WALK_PATH 9999" - " TASK_WAIT_FOR_MOVEMENT 0" - " TASK_WAIT_PVS 0" - "" - " Interrupts" - " COND_NEW_ENEMY" - " COND_PROVOKED" - ) - -AI_END_CUSTOM_NPC() diff --git a/game/server/npc_vehicledriver.h b/game/server/npc_vehicledriver.h deleted file mode 100644 index 47ab52d74..000000000 --- a/game/server/npc_vehicledriver.h +++ /dev/null @@ -1,197 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: NPC that drives vehicles -// -//=============================================================================// - -#ifndef NPC_VEHICLEDRIVER_H -#define NPC_VEHICLEDRIVER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_basenpc.h" - -class CPropVehicleDriveable; - -//------------------------------------ -// Spawnflags -//------------------------------------ -#define SF_VEHICLEDRIVER_INACTIVE (1 << 16) - -//========================================================= -// Custom schedules -//========================================================= -enum -{ - SCHED_VEHICLEDRIVER_INACTIVE = LAST_SHARED_SCHEDULE, - SCHED_VEHICLEDRIVER_COMBAT_WAIT, - SCHED_VEHICLEDRIVER_DRIVE_PATH, - - LAST_VEHICLEDRIVER_SCHED, -}; - -//========================================================= -// Custom tasks -//========================================================= -enum -{ - TASK_VEHICLEDRIVER_GET_PATH = LAST_SHARED_TASK, - - LAST_VEHICLEDRIVER_TASK, -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CVehicleWaypoint -{ -public: - CVehicleWaypoint( Vector &pPrevPoint, Vector &pCurPoint, Vector &pNextPoint, Vector &pNextNextPoint ) - { - splinePoints[0] = pPrevPoint; - splinePoints[1] = pCurPoint; - splinePoints[2] = pNextPoint; - splinePoints[3] = pNextNextPoint; - - RecalculateSpline(); - } - - void RecalculateSpline( void ) - { - planeWaypoint.normal = (splinePoints[2] - splinePoints[1]); - VectorNormalize( planeWaypoint.normal ); - planeWaypoint.type = PLANE_ANYZ; - planeWaypoint.dist = DotProduct( planeWaypoint.normal, splinePoints[2] ); - planeWaypoint.signbits = SignbitsForPlane(&planeWaypoint); - // TODO: Use the vehicle's absbox - iInitialPlaneSide = BoxOnPlaneSide( -Vector(32,32,32), Vector(32,32,32), &planeWaypoint ); - - // Hackily calculate a length for the spline. Subdivide & measure. - flSplineLength = 0; - Vector vecPrev = splinePoints[1]; - const int iDivs = 10; - for ( int i = 1; i <= iDivs; i++ ) - { - Vector vecCurr; - float flT = (float)i / (float)iDivs; - Catmull_Rom_Spline( splinePoints[0], splinePoints[1], splinePoints[2], splinePoints[3], flT, vecCurr ); - flSplineLength += (vecCurr - vecPrev).Length(); - vecPrev = vecCurr; - } - } - - Vector GetPointAt( float flT ) - { - Vector vecCurr(0,0,0); - Catmull_Rom_Spline( splinePoints[0], splinePoints[1], splinePoints[2], splinePoints[3], flT, vecCurr ); - return vecCurr; - } - - Vector GetTangentAt( float flT ) - { - Vector vecCurr(0,0,0); - Catmull_Rom_Spline_Tangent( splinePoints[0], splinePoints[1], splinePoints[2], splinePoints[3], flT, vecCurr ); - return vecCurr; - } - - float GetLength( void ) - { - return flSplineLength; - } - -public: - int iInitialPlaneSide; - float flSplineLength; - Vector splinePoints[4]; - cplane_t planeWaypoint; -}; - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CNPC_VehicleDriver : public CAI_BaseNPC -{ - DECLARE_CLASS( CNPC_VehicleDriver, CAI_BaseNPC ); -public: - DECLARE_DATADESC(); - DEFINE_CUSTOM_AI; - - CNPC_VehicleDriver( void ); - ~CNPC_VehicleDriver( void ); - - virtual void Spawn( void ); - virtual void Precache( void ); - virtual void Activate( void ); - virtual void OnRestore(); - virtual void UpdateOnRemove( void ); - - // AI - void UpdateEfficiency( bool bInPVS ) { SetEfficiency( ( GetSleepState() != AISS_AWAKE ) ? AIE_DORMANT : AIE_NORMAL ); SetMoveEfficiency( AIME_NORMAL ); } - virtual void PrescheduleThink( void ); - virtual int TranslateSchedule( int scheduleType ); - virtual int SelectSchedule( void ); - virtual void StartTask( const Task_t *pTask ); - virtual void RunTask( const Task_t *pTask ); - virtual void GatherEnemyConditions( CBaseEntity *pEnemy ); - virtual int RangeAttack1Conditions( float flDot, float flDist ); - virtual int RangeAttack2Conditions( float flDot, float flDist ); - - // Driving - virtual void DriveVehicle( void ); - virtual bool OverrideMove( float flInterval ); - bool OverridePathMove( float flInterval ); - void CalculatePostPoints( void ); - bool WaypointReached( void ); - float GetDefaultNavGoalTolerance(); - void RecalculateSpeeds( void ); - void ClearWaypoints( void ); - void CheckForTeleport( void ); - - int BloodColor( void ) { return DONT_BLEED; } - -#ifdef HL2_DLL - Class_T Classify( void ) { return CLASS_METROPOLICE; } -#else - Class_T Classify( void ) { return CLASS_NONE; } -#endif - - Disposition_t IRelationType( CBaseEntity *pTarget ); - - // Inputs - void InputSetDriversMaxSpeed( inputdata_t &inputdata ); - void InputSetDriversMinSpeed( inputdata_t &inputdata ); - void InputStartForward( inputdata_t &inputdata ); - void InputStop( inputdata_t &inputdata ); - void InputStartFiring( inputdata_t &inputdata ); - void InputStopFiring( inputdata_t &inputdata ); - void InputGotoPathCorner( inputdata_t &inputdata ); - -public: - string_t m_iszVehicleName; - IServerVehicle *m_pVehicleInterface; - EHANDLE m_hVehicleEntity; - - // Path driving - CVehicleWaypoint *m_Waypoints[2]; - CVehicleWaypoint *m_pCurrentWaypoint; - CVehicleWaypoint *m_pNextWaypoint; - Vector m_vecDesiredVelocity; - Vector m_vecDesiredPosition; - Vector m_vecPrevPoint; - Vector m_vecPrevPrevPoint; - Vector m_vecPostPoint; - Vector m_vecPostPostPoint; - float m_flDistanceAlongSpline; - float m_flDriversMaxSpeed; - float m_flDriversMinSpeed; - - // Speed - float m_flMaxSpeed; // Maximum speed this driver will go - float m_flGoalSpeed; // Desired speed - float m_flInitialSpeed; - float m_flSteering; -}; - -#endif // NPC_VEHICLEDRIVER_H diff --git a/game/server/particle_fire.cpp b/game/server/particle_fire.cpp deleted file mode 100644 index 313769e93..000000000 --- a/game/server/particle_fire.cpp +++ /dev/null @@ -1,43 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" - -#include "particle_fire.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -IMPLEMENT_SERVERCLASS_ST_NOBASE(CParticleFire, DT_ParticleFire) - SendPropVector(SENDINFO(m_vOrigin), 0, SPROP_COORD), - SendPropVector(SENDINFO(m_vDirection), 0, SPROP_NOSCALE) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( env_particlefire, CParticleFire ); - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CParticleFire ) - - DEFINE_FIELD( m_vOrigin, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vDirection, FIELD_VECTOR ), - -END_DATADESC() - - -CParticleFire::CParticleFire() -{ -#ifdef _DEBUG - m_vOrigin.Init(); - m_vDirection.Init(); -#endif -} - - - diff --git a/game/server/particle_fire.h b/game/server/particle_fire.h deleted file mode 100644 index 424c15ac2..000000000 --- a/game/server/particle_fire.h +++ /dev/null @@ -1,36 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef PARTICLE_FIRE_H -#define PARTICLE_FIRE_H - - -#include "baseparticleentity.h" - - -class CParticleFire : public CBaseParticleEntity -{ - DECLARE_DATADESC(); - -public: - CParticleFire(); - - DECLARE_CLASS( CParticleFire, CBaseParticleEntity ); - - DECLARE_SERVERCLASS(); - - // The client shoots a ray out and starts creating fire where it hits. - CNetworkVector( m_vOrigin ); - CNetworkVector( m_vDirection ); -}; - - -#endif - - - diff --git a/game/server/particle_light.cpp b/game/server/particle_light.cpp deleted file mode 100644 index e9b1c14e0..000000000 --- a/game/server/particle_light.cpp +++ /dev/null @@ -1,41 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "particle_light.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -LINK_ENTITY_TO_CLASS( env_particlelight, CParticleLight ); - - -//Save/restore -BEGIN_DATADESC( CParticleLight ) - - //Keyvalue fields - DEFINE_KEYFIELD( m_flIntensity, FIELD_FLOAT, "Intensity" ), - DEFINE_KEYFIELD( m_vColor, FIELD_VECTOR, "Color" ), - DEFINE_KEYFIELD( m_PSName, FIELD_STRING, "PSName" ), - DEFINE_KEYFIELD( m_bDirectional, FIELD_BOOLEAN, "Directional" ) - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Purpose: Called before spawning, after key values have been set. -//----------------------------------------------------------------------------- -CParticleLight::CParticleLight() -{ - m_flIntensity = 5000; - m_vColor.Init( 1, 0, 0 ); - m_PSName = NULL_STRING; - m_bDirectional = false; -} - - diff --git a/game/server/particle_light.h b/game/server/particle_light.h deleted file mode 100644 index 7d4fdd359..000000000 --- a/game/server/particle_light.h +++ /dev/null @@ -1,41 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PARTICLE_LIGHT_H -#define PARTICLE_LIGHT_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "baseentity.h" - - -//================================================== -// CParticleLight. These are tied to -//================================================== - -#define PARTICLELIGHT_ENTNAME "env_particlelight" - -class CParticleLight : public CServerOnlyPointEntity -{ -public: - DECLARE_CLASS( CParticleLight, CServerOnlyPointEntity ); - DECLARE_DATADESC(); - - CParticleLight(); - - -public: - float m_flIntensity; - Vector m_vColor; // 0-255 - string_t m_PSName; // Name of the particle system entity this light affects. - bool m_bDirectional; -}; - - -#endif // PARTICLE_LIGHT_H diff --git a/game/server/particle_smokegrenade.cpp b/game/server/particle_smokegrenade.cpp deleted file mode 100644 index e8b9252f6..000000000 --- a/game/server/particle_smokegrenade.cpp +++ /dev/null @@ -1,75 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include "cbase.h" -#include "particle_smokegrenade.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -IMPLEMENT_SERVERCLASS_ST(ParticleSmokeGrenade, DT_ParticleSmokeGrenade) - SendPropTime(SENDINFO(m_flSpawnTime) ), - SendPropFloat(SENDINFO(m_FadeStartTime), 0, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_FadeEndTime), 0, SPROP_NOSCALE), - SendPropInt(SENDINFO(m_CurrentStage), 1, SPROP_UNSIGNED), -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( env_particlesmokegrenade, ParticleSmokeGrenade ); - -BEGIN_DATADESC( ParticleSmokeGrenade ) - - DEFINE_FIELD( m_CurrentStage, FIELD_CHARACTER ), - DEFINE_FIELD( m_FadeStartTime, FIELD_TIME ), - DEFINE_FIELD( m_FadeEndTime, FIELD_TIME ), - DEFINE_FIELD( m_flSpawnTime, FIELD_TIME ), - -END_DATADESC() - - -ParticleSmokeGrenade::ParticleSmokeGrenade() -{ - m_CurrentStage = 0; - m_FadeStartTime = 17; - m_FadeEndTime = 22; - - m_flSpawnTime = gpGlobals->curtime; -} - - -// Smoke grenade particles should always transmitted to clients. If not, a client who -// enters the PVS late will see the smoke start billowing from then, allowing better vision. -int ParticleSmokeGrenade::UpdateTransmitState( void ) -{ - if ( IsEffectActive( EF_NODRAW ) ) - return SetTransmitState( FL_EDICT_DONTSEND ); - - return SetTransmitState( FL_EDICT_ALWAYS ); -} - - -void ParticleSmokeGrenade::FillVolume() -{ - m_CurrentStage = 1; - CollisionProp()->SetCollisionBounds( Vector( -50, -50, -50 ), Vector( 50, 50, 50 ) ); -} - - -void ParticleSmokeGrenade::SetFadeTime(float startTime, float endTime) -{ - m_FadeStartTime = startTime; - m_FadeEndTime = endTime; -} - -// Fade start and end are relative to current time -void ParticleSmokeGrenade::SetRelativeFadeTime(float startTime, float endTime) -{ - float flCurrentTime = gpGlobals->curtime - m_flSpawnTime; - - m_FadeStartTime = flCurrentTime + startTime; - m_FadeEndTime = flCurrentTime + endTime; -} diff --git a/game/server/particle_smokegrenade.h b/game/server/particle_smokegrenade.h deleted file mode 100644 index 07781b6db..000000000 --- a/game/server/particle_smokegrenade.h +++ /dev/null @@ -1,58 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef PARTICLE_SMOKEGRENADE_H -#define PARTICLE_SMOKEGRENADE_H - - -#include "baseparticleentity.h" - - -#define PARTICLESMOKEGRENADE_ENTITYNAME "env_particlesmokegrenade" - - -class ParticleSmokeGrenade : public CBaseParticleEntity -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( ParticleSmokeGrenade, CBaseParticleEntity ); - DECLARE_SERVERCLASS(); - - ParticleSmokeGrenade(); - - virtual int UpdateTransmitState( void ); - -public: - - // Tell the client entity to start filling the volume. - void FillVolume(); - - // Set the times it fades out at. - void SetFadeTime(float startTime, float endTime); - - // Set time to fade out relative to current time - void SetRelativeFadeTime(float startTime, float endTime); - - -public: - - // Stage 0 (default): make a smoke trail that follows the entity it's following. - // Stage 1 : fill a volume with smoke. - CNetworkVar( unsigned char, m_CurrentStage ); - - CNetworkVar( float, m_flSpawnTime ); - - // When to fade in and out. - CNetworkVar( float, m_FadeStartTime ); - CNetworkVar( float, m_FadeEndTime ); -}; - - -#endif - - diff --git a/game/server/particle_system.cpp b/game/server/particle_system.cpp deleted file mode 100644 index 2e86e2529..000000000 --- a/game/server/particle_system.cpp +++ /dev/null @@ -1,254 +0,0 @@ -//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: An entity that spawns and controls a particle system -// -//============================================================================= - -#include "cbase.h" -#include "particles/particles.h" -#include "networkstringtable_gamedll.h" -#include "particle_system.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern void SendProxy_Origin( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); -extern void SendProxy_Angles( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); - -// Stripped down CBaseEntity send table -IMPLEMENT_SERVERCLASS_ST_NOBASE(CParticleSystem, DT_ParticleSystem) - SendPropVector (SENDINFO(m_vecOrigin), -1, SPROP_COORD|SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_Origin ), - SendPropEHandle (SENDINFO(m_hOwnerEntity)), - SendPropEHandle (SENDINFO_NAME(m_hMoveParent, moveparent)), - SendPropInt (SENDINFO(m_iParentAttachment), NUM_PARENTATTACHMENT_BITS, SPROP_UNSIGNED), - SendPropQAngles (SENDINFO(m_angRotation), 13, SPROP_CHANGES_OFTEN, SendProxy_Angles ), - - SendPropInt( SENDINFO(m_iEffectIndex), MAX_PARTICLESYSTEMS_STRING_BITS, SPROP_UNSIGNED ), - SendPropBool( SENDINFO(m_bActive) ), - SendPropFloat( SENDINFO(m_flStartTime) ), - - SendPropArray3( SENDINFO_ARRAY3(m_hControlPointEnts), SendPropEHandle( SENDINFO_ARRAY(m_hControlPointEnts) ) ), - SendPropArray3( SENDINFO_ARRAY3(m_iControlPointParents), SendPropInt( SENDINFO_ARRAY(m_iControlPointParents), 3, SPROP_UNSIGNED ) ), -END_SEND_TABLE() - -BEGIN_DATADESC( CParticleSystem ) - DEFINE_KEYFIELD( m_bStartActive, FIELD_BOOLEAN, "start_active" ), - DEFINE_FIELD( m_bActive, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flStartTime, FIELD_TIME ), - DEFINE_KEYFIELD( m_iszEffectName, FIELD_STRING, "effect_name" ), - //DEFINE_FIELD( m_iEffectIndex, FIELD_INTEGER ), // Don't save. Refind after loading. - - DEFINE_KEYFIELD( m_iszControlPointNames[0], FIELD_STRING, "cpoint1" ), - DEFINE_KEYFIELD( m_iszControlPointNames[1], FIELD_STRING, "cpoint2" ), - DEFINE_KEYFIELD( m_iszControlPointNames[2], FIELD_STRING, "cpoint3" ), - DEFINE_KEYFIELD( m_iszControlPointNames[3], FIELD_STRING, "cpoint4" ), - DEFINE_KEYFIELD( m_iszControlPointNames[4], FIELD_STRING, "cpoint5" ), - DEFINE_KEYFIELD( m_iszControlPointNames[5], FIELD_STRING, "cpoint6" ), - DEFINE_KEYFIELD( m_iszControlPointNames[6], FIELD_STRING, "cpoint7" ), - DEFINE_KEYFIELD( m_iszControlPointNames[7], FIELD_STRING, "cpoint8" ), - DEFINE_KEYFIELD( m_iszControlPointNames[8], FIELD_STRING, "cpoint9" ), - DEFINE_KEYFIELD( m_iszControlPointNames[9], FIELD_STRING, "cpoint10" ), - DEFINE_KEYFIELD( m_iszControlPointNames[10], FIELD_STRING, "cpoint11" ), - DEFINE_KEYFIELD( m_iszControlPointNames[11], FIELD_STRING, "cpoint12" ), - DEFINE_KEYFIELD( m_iszControlPointNames[12], FIELD_STRING, "cpoint13" ), - DEFINE_KEYFIELD( m_iszControlPointNames[13], FIELD_STRING, "cpoint14" ), - DEFINE_KEYFIELD( m_iszControlPointNames[14], FIELD_STRING, "cpoint15" ), - DEFINE_KEYFIELD( m_iszControlPointNames[15], FIELD_STRING, "cpoint16" ), - DEFINE_KEYFIELD( m_iszControlPointNames[16], FIELD_STRING, "cpoint17" ), - DEFINE_KEYFIELD( m_iszControlPointNames[17], FIELD_STRING, "cpoint18" ), - DEFINE_KEYFIELD( m_iszControlPointNames[18], FIELD_STRING, "cpoint19" ), - DEFINE_KEYFIELD( m_iszControlPointNames[19], FIELD_STRING, "cpoint20" ), - DEFINE_KEYFIELD( m_iszControlPointNames[20], FIELD_STRING, "cpoint21" ), - DEFINE_KEYFIELD( m_iszControlPointNames[21], FIELD_STRING, "cpoint22" ), - DEFINE_KEYFIELD( m_iszControlPointNames[22], FIELD_STRING, "cpoint23" ), - DEFINE_KEYFIELD( m_iszControlPointNames[23], FIELD_STRING, "cpoint24" ), - DEFINE_KEYFIELD( m_iszControlPointNames[24], FIELD_STRING, "cpoint25" ), - DEFINE_KEYFIELD( m_iszControlPointNames[25], FIELD_STRING, "cpoint26" ), - DEFINE_KEYFIELD( m_iszControlPointNames[26], FIELD_STRING, "cpoint27" ), - DEFINE_KEYFIELD( m_iszControlPointNames[27], FIELD_STRING, "cpoint28" ), - DEFINE_KEYFIELD( m_iszControlPointNames[28], FIELD_STRING, "cpoint29" ), - DEFINE_KEYFIELD( m_iszControlPointNames[29], FIELD_STRING, "cpoint30" ), - DEFINE_KEYFIELD( m_iszControlPointNames[30], FIELD_STRING, "cpoint31" ), - DEFINE_KEYFIELD( m_iszControlPointNames[31], FIELD_STRING, "cpoint32" ), - DEFINE_KEYFIELD( m_iszControlPointNames[32], FIELD_STRING, "cpoint33" ), - DEFINE_KEYFIELD( m_iszControlPointNames[33], FIELD_STRING, "cpoint34" ), - DEFINE_KEYFIELD( m_iszControlPointNames[34], FIELD_STRING, "cpoint35" ), - DEFINE_KEYFIELD( m_iszControlPointNames[35], FIELD_STRING, "cpoint36" ), - DEFINE_KEYFIELD( m_iszControlPointNames[36], FIELD_STRING, "cpoint37" ), - DEFINE_KEYFIELD( m_iszControlPointNames[37], FIELD_STRING, "cpoint38" ), - DEFINE_KEYFIELD( m_iszControlPointNames[38], FIELD_STRING, "cpoint39" ), - DEFINE_KEYFIELD( m_iszControlPointNames[39], FIELD_STRING, "cpoint40" ), - DEFINE_KEYFIELD( m_iszControlPointNames[40], FIELD_STRING, "cpoint41" ), - DEFINE_KEYFIELD( m_iszControlPointNames[41], FIELD_STRING, "cpoint42" ), - DEFINE_KEYFIELD( m_iszControlPointNames[42], FIELD_STRING, "cpoint43" ), - DEFINE_KEYFIELD( m_iszControlPointNames[43], FIELD_STRING, "cpoint44" ), - DEFINE_KEYFIELD( m_iszControlPointNames[44], FIELD_STRING, "cpoint45" ), - DEFINE_KEYFIELD( m_iszControlPointNames[45], FIELD_STRING, "cpoint46" ), - DEFINE_KEYFIELD( m_iszControlPointNames[46], FIELD_STRING, "cpoint47" ), - DEFINE_KEYFIELD( m_iszControlPointNames[47], FIELD_STRING, "cpoint48" ), - DEFINE_KEYFIELD( m_iszControlPointNames[48], FIELD_STRING, "cpoint49" ), - DEFINE_KEYFIELD( m_iszControlPointNames[49], FIELD_STRING, "cpoint50" ), - DEFINE_KEYFIELD( m_iszControlPointNames[50], FIELD_STRING, "cpoint51" ), - DEFINE_KEYFIELD( m_iszControlPointNames[51], FIELD_STRING, "cpoint52" ), - DEFINE_KEYFIELD( m_iszControlPointNames[52], FIELD_STRING, "cpoint53" ), - DEFINE_KEYFIELD( m_iszControlPointNames[53], FIELD_STRING, "cpoint54" ), - DEFINE_KEYFIELD( m_iszControlPointNames[54], FIELD_STRING, "cpoint55" ), - DEFINE_KEYFIELD( m_iszControlPointNames[55], FIELD_STRING, "cpoint56" ), - DEFINE_KEYFIELD( m_iszControlPointNames[56], FIELD_STRING, "cpoint57" ), - DEFINE_KEYFIELD( m_iszControlPointNames[57], FIELD_STRING, "cpoint58" ), - DEFINE_KEYFIELD( m_iszControlPointNames[58], FIELD_STRING, "cpoint59" ), - DEFINE_KEYFIELD( m_iszControlPointNames[59], FIELD_STRING, "cpoint60" ), - DEFINE_KEYFIELD( m_iszControlPointNames[60], FIELD_STRING, "cpoint61" ), - DEFINE_KEYFIELD( m_iszControlPointNames[61], FIELD_STRING, "cpoint62" ), - DEFINE_KEYFIELD( m_iszControlPointNames[62], FIELD_STRING, "cpoint63" ), - - /* This causes a cannot apply offsetof when operator[] is overloaded error in GCC 4.2 - DEFINE_KEYFIELD( m_iControlPointParents[0], FIELD_CHARACTER, "cpoint1_parent" ), - DEFINE_KEYFIELD( m_iControlPointParents[1], FIELD_CHARACTER, "cpoint2_parent" ), - DEFINE_KEYFIELD( m_iControlPointParents[2], FIELD_CHARACTER, "cpoint3_parent" ), - DEFINE_KEYFIELD( m_iControlPointParents[3], FIELD_CHARACTER, "cpoint4_parent" ), - DEFINE_KEYFIELD( m_iControlPointParents[4], FIELD_CHARACTER, "cpoint5_parent" ), - DEFINE_KEYFIELD( m_iControlPointParents[5], FIELD_CHARACTER, "cpoint6_parent" ), - DEFINE_KEYFIELD( m_iControlPointParents[6], FIELD_CHARACTER, "cpoint7_parent" ), - */ - - DEFINE_KEYFIELD_NETARRAY( m_iControlPointParents, 0, FIELD_CHARACTER, "cpoint1_parent" ), - DEFINE_KEYFIELD_NETARRAY( m_iControlPointParents, 1, FIELD_CHARACTER, "cpoint2_parent" ), - DEFINE_KEYFIELD_NETARRAY( m_iControlPointParents, 2, FIELD_CHARACTER, "cpoint3_parent" ), - DEFINE_KEYFIELD_NETARRAY( m_iControlPointParents, 3, FIELD_CHARACTER, "cpoint4_parent" ), - DEFINE_KEYFIELD_NETARRAY( m_iControlPointParents, 4, FIELD_CHARACTER, "cpoint5_parent" ), - DEFINE_KEYFIELD_NETARRAY( m_iControlPointParents, 5, FIELD_CHARACTER, "cpoint6_parent" ), - DEFINE_KEYFIELD_NETARRAY( m_iControlPointParents, 6, FIELD_CHARACTER, "cpoint7_parent" ), - - DEFINE_AUTO_ARRAY( m_hControlPointEnts, FIELD_EHANDLE ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Start", InputStart ), - DEFINE_INPUTFUNC( FIELD_VOID, "Stop", InputStop ), - - DEFINE_THINKFUNC( StartParticleSystemThink ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( info_particle_system, CParticleSystem ); - - -//----------------------------------------------------------------------------- -// Precache -//----------------------------------------------------------------------------- -void CParticleSystem::Precache( void ) -{ - const char *pParticleSystemName = STRING( m_iszEffectName ); - if ( pParticleSystemName == NULL || pParticleSystemName[0] == 0 ) - { - Warning( "info_particle_system (%s) has no particle system name specified!\n", GetEntityName().ToCStr() ); - } - - PrecacheParticleSystem( pParticleSystemName ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CParticleSystem::Spawn( void ) -{ - BaseClass::Spawn(); - - Precache(); - m_iEffectIndex = -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CParticleSystem::Activate( void ) -{ - BaseClass::Activate(); - - // Find our particle effect index - m_iEffectIndex = GetParticleSystemIndex( STRING(m_iszEffectName) ); - - if ( m_bStartActive ) - { - m_bStartActive = false; - StartParticleSystem(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CParticleSystem::StartParticleSystemThink( void ) -{ - StartParticleSystem(); -} - -//----------------------------------------------------------------------------- -// Purpose: Always transmitted to clients -//----------------------------------------------------------------------------- -int CParticleSystem::UpdateTransmitState() -{ - return SetTransmitState( FL_EDICT_ALWAYS ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CParticleSystem::StartParticleSystem( void ) -{ - if ( m_bActive == false ) - { - m_flStartTime = gpGlobals->curtime; - m_bActive = true; - - // Setup our control points at this time (in case our targets weren't around at spawn time) - ReadControlPointEnts(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CParticleSystem::StopParticleSystem( void ) -{ - m_bActive = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CParticleSystem::InputStart( inputdata_t &inputdata ) -{ - StartParticleSystem(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CParticleSystem::InputStop( inputdata_t &inputdata ) -{ - StopParticleSystem(); -} - -//----------------------------------------------------------------------------- -// Purpose: Find each entity referred to by m_iszControlPointNames and -// resolve it into the corresponding slot in m_hControlPointEnts -//----------------------------------------------------------------------------- -void CParticleSystem::ReadControlPointEnts( void ) -{ - for ( int i = 0 ; i < kMAXCONTROLPOINTS; ++i ) - { - if ( m_iszControlPointNames[i] == NULL_STRING ) - continue; - - CBaseEntity *pPointEnt = gEntList.FindEntityGeneric( NULL, STRING( m_iszControlPointNames[i] ), this ); - Assert( pPointEnt != NULL ); - if ( pPointEnt == NULL ) - { - Warning("Particle system %s could not find control point entity (%s)\n", GetEntityName().ToCStr(), m_iszControlPointNames[i].ToCStr() ); - continue; - } - - m_hControlPointEnts.Set( i, pPointEnt ); - } -} diff --git a/game/server/particle_system.h b/game/server/particle_system.h deleted file mode 100644 index 9f23dcd20..000000000 --- a/game/server/particle_system.h +++ /dev/null @@ -1,56 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef PARTICLE_SYSTEM_H -#define PARTICLE_SYSTEM_H -#ifdef _WIN32 -#pragma once -#endif - -#include "cbase.h" - -//----------------------------------------------------------------------------- -// Purpose: An entity that spawns and controls a particle system -//----------------------------------------------------------------------------- -class CParticleSystem : public CBaseEntity -{ - DECLARE_CLASS( CParticleSystem, CBaseEntity ); -public: - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - virtual void Precache( void ); - virtual void Spawn( void ); - virtual void Activate( void ); - virtual int UpdateTransmitState(void); - - void StartParticleSystem( void ); - void StopParticleSystem( void ); - - void InputStart( inputdata_t &inputdata ); - void InputStop( inputdata_t &inputdata ); - void StartParticleSystemThink( void ); - - enum { kMAXCONTROLPOINTS = 63 }; ///< actually one less than the total number of cpoints since 0 is assumed to be me - -protected: - - /// Load up and resolve the entities that are supposed to be the control points - void ReadControlPointEnts( void ); - - bool m_bStartActive; - string_t m_iszEffectName; - - CNetworkVar( bool, m_bActive ); - CNetworkVar( int, m_iEffectIndex ) - CNetworkVar( float, m_flStartTime ); // Time at which this effect was started. This is used after restoring an active effect. - - string_t m_iszControlPointNames[kMAXCONTROLPOINTS]; - CNetworkArray( EHANDLE, m_hControlPointEnts, kMAXCONTROLPOINTS ); - CNetworkArray( unsigned char, m_iControlPointParents, kMAXCONTROLPOINTS ); -}; - -#endif // PARTICLE_SYSTEM_H diff --git a/game/server/pathcorner.cpp b/game/server/pathcorner.cpp deleted file mode 100644 index eae71d904..000000000 --- a/game/server/pathcorner.cpp +++ /dev/null @@ -1,142 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Used to create a path that can be followed by NPCs and trains. -// -//=============================================================================// - -#include "cbase.h" -#include "trains.h" -#include "entitylist.h" -#include "ndebugoverlay.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CPathCorner : public CPointEntity -{ - DECLARE_CLASS( CPathCorner, CPointEntity ); -public: - - void Spawn( ); - float GetDelay( void ) { return m_flWait; } - int DrawDebugTextOverlays(void); - void DrawDebugGeometryOverlays(void); - - // Input handlers - void InputSetNextPathCorner( inputdata_t &inputdata ); - void InputInPass( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - -private: - float m_flWait; - COutputEvent m_OnPass; -}; - -LINK_ENTITY_TO_CLASS( path_corner, CPathCorner ); - - -class CPathCornerCrash : public CPathCorner -{ - DECLARE_CLASS( CPathCornerCrash, CPathCorner ); -}; - -LINK_ENTITY_TO_CLASS( path_corner_crash, CPathCornerCrash ); - - -BEGIN_DATADESC( CPathCorner ) - - DEFINE_KEYFIELD( m_flWait, FIELD_FLOAT, "wait" ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_STRING, "SetNextPathCorner", InputSetNextPathCorner), - - // Internal inputs - not exposed in the FGD - DEFINE_INPUTFUNC( FIELD_VOID, "InPass", InputInPass ), - - // Outputs - DEFINE_OUTPUT( m_OnPass, "OnPass"), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPathCorner::Spawn( void ) -{ - ASSERTSZ(GetEntityName() != NULL_STRING, "path_corner without a targetname"); -} - - -//------------------------------------------------------------------------------ -// Purpose: Sets the next path corner by name. -// Input : String ID name of next path corner. -//----------------------------------------------------------------------------- -void CPathCorner::InputSetNextPathCorner( inputdata_t &inputdata ) -{ - m_target = inputdata.value.StringID(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Fired by path followers as they pass the path corner. -//----------------------------------------------------------------------------- -void CPathCorner::InputInPass( inputdata_t &inputdata ) -{ - m_OnPass.FireOutput( inputdata.pActivator, inputdata.pCaller, 0); -} - - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CPathCorner::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - // -------------- - // Print Target - // -------------- - char tempstr[255]; - if (m_target!=NULL_STRING) - { - Q_snprintf(tempstr,sizeof(tempstr),"Target: %s",STRING(m_target)); - } - else - { - Q_strncpy(tempstr,"Target: - ",sizeof(tempstr)); - } - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} - - -//----------------------------------------------------------------------------- -// Purpose: Override base class to add display of paths -//----------------------------------------------------------------------------- -void CPathCorner::DrawDebugGeometryOverlays(void) -{ - // ---------------------------------------------- - // Draw line to next target is bbox is selected - // ---------------------------------------------- - if (m_debugOverlays & (OVERLAY_BBOX_BIT|OVERLAY_ABSBOX_BIT)) - { - NDebugOverlay::Box(GetAbsOrigin(), Vector(-10,-10,-10), Vector(10,10,10), 255, 100, 100, 0 ,0); - - if (m_target != NULL_STRING) - { - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, m_target ); - if (pTarget) - { - NDebugOverlay::Line(GetAbsOrigin(),pTarget->GetAbsOrigin(),255,100,100,true,0.0); - } - } - } - BaseClass::DrawDebugGeometryOverlays(); -} diff --git a/game/server/pathtrack.cpp b/game/server/pathtrack.cpp deleted file mode 100644 index 187a542eb..000000000 --- a/game/server/pathtrack.cpp +++ /dev/null @@ -1,561 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Used to create a path that can be followed by NPCs and trains. -// -//=============================================================================// - -#include "cbase.h" -#include "pathtrack.h" -#include "entitylist.h" -#include "ndebugoverlay.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Save/load -//----------------------------------------------------------------------------- -BEGIN_DATADESC( CPathTrack ) - - DEFINE_FIELD( m_pnext, FIELD_CLASSPTR ), - DEFINE_FIELD( m_pprevious, FIELD_CLASSPTR ), - DEFINE_FIELD( m_paltpath, FIELD_CLASSPTR ), - - DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "radius" ), - DEFINE_FIELD( m_length, FIELD_FLOAT ), - DEFINE_KEYFIELD( m_altName, FIELD_STRING, "altpath" ), - DEFINE_KEYFIELD( m_eOrientationType, FIELD_INTEGER, "orientationtype" ), -// DEFINE_FIELD( m_nIterVal, FIELD_INTEGER ), - - DEFINE_INPUTFUNC( FIELD_VOID, "InPass", InputPass ), - - DEFINE_INPUTFUNC( FIELD_VOID, "EnableAlternatePath", InputEnableAlternatePath ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableAlternatePath", InputDisableAlternatePath ), - DEFINE_INPUTFUNC( FIELD_VOID, "ToggleAlternatePath", InputToggleAlternatePath ), - - DEFINE_INPUTFUNC( FIELD_VOID, "EnablePath", InputEnablePath ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisablePath", InputDisablePath ), - DEFINE_INPUTFUNC( FIELD_VOID, "TogglePath", InputTogglePath ), - - // Outputs - DEFINE_OUTPUT(m_OnPass, "OnPass"), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( path_track, CPathTrack ); - - -//----------------------------------------------------------------------------- -// Finds circular paths -//----------------------------------------------------------------------------- -int CPathTrack::s_nCurrIterVal = 0; -bool CPathTrack::s_bIsIterating = false; - - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CPathTrack::CPathTrack() -{ - m_nIterVal = -1; - m_eOrientationType = TrackOrientation_FacePath; -} - - -//----------------------------------------------------------------------------- -// Spawn! -//----------------------------------------------------------------------------- -void CPathTrack::Spawn( void ) -{ - SetSolid( SOLID_NONE ); - UTIL_SetSize(this, Vector(-8, -8, -8), Vector(8, 8, 8)); - - m_pnext = NULL; - m_pprevious = NULL; -} - - -//----------------------------------------------------------------------------- -// Activate! -//----------------------------------------------------------------------------- -void CPathTrack::Activate( void ) -{ - BaseClass::Activate(); - - if ( GetEntityName() != NULL_STRING ) // Link to next, and back-link - { - Link(); - } -} - - -//----------------------------------------------------------------------------- -// Connects up the previons + next pointers -//----------------------------------------------------------------------------- -void CPathTrack::Link( void ) -{ - CBaseEntity *pTarget; - - if ( m_target != NULL_STRING ) - { - pTarget = gEntList.FindEntityByName( NULL, m_target ); - - if ( pTarget == this) - { - Warning("ERROR: path_track (%s) refers to itself as a target!\n", GetDebugName()); - - //FIXME: Why were we removing this? If it was already connected to, we weren't updating the other linked - // end, causing problems with walking through bogus memory links! -- jdw - - //UTIL_Remove(this); - //return; - } - else if ( pTarget ) - { - m_pnext = dynamic_cast( pTarget ); - - if ( m_pnext ) // If no next pointer, this is the end of a path - { - m_pnext->SetPrevious( this ); - } - } - else - { - Warning("Dead end link: %s\n", STRING( m_target ) ); - } - } - - // Find "alternate" path - if ( m_altName != NULL_STRING ) - { - pTarget = gEntList.FindEntityByName( NULL, m_altName ); - if ( pTarget ) - { - m_paltpath = dynamic_cast( pTarget ); - m_paltpath->SetPrevious( this ); - } - } -} - - -//----------------------------------------------------------------------------- -// Circular path checking -//----------------------------------------------------------------------------- -void CPathTrack::BeginIteration() -{ - Assert( !s_bIsIterating ); - ++s_nCurrIterVal; - s_bIsIterating = true; -} - -void CPathTrack::EndIteration() -{ - Assert( s_bIsIterating ); - s_bIsIterating = false; -} - -void CPathTrack::Visit() -{ - m_nIterVal = s_nCurrIterVal; -} - -bool CPathTrack::HasBeenVisited() const -{ - return ( m_nIterVal == s_nCurrIterVal ); -} - - -//----------------------------------------------------------------------------- -// Do we have an alternate path? -//----------------------------------------------------------------------------- -bool CPathTrack::HasAlternathPath() const -{ - return ( m_paltpath != NULL ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Toggles the track to or from its alternate path -//----------------------------------------------------------------------------- -void CPathTrack::ToggleAlternatePath( void ) -{ - // Use toggles between two paths - if ( m_paltpath != NULL ) - { - if ( FBitSet( m_spawnflags, SF_PATH_ALTERNATE ) == false ) - { - EnableAlternatePath(); - } - else - { - DisableAlternatePath(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPathTrack::EnableAlternatePath( void ) -{ - if ( m_paltpath != NULL ) - { - SETBITS( m_spawnflags, SF_PATH_ALTERNATE ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPathTrack::DisableAlternatePath( void ) -{ - if ( m_paltpath != NULL ) - { - CLEARBITS( m_spawnflags, SF_PATH_ALTERNATE ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CPathTrack::InputEnableAlternatePath( inputdata_t &inputdata ) -{ - EnableAlternatePath(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CPathTrack::InputDisableAlternatePath( inputdata_t &inputdata ) -{ - DisableAlternatePath(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CPathTrack::InputToggleAlternatePath( inputdata_t &inputdata ) -{ - ToggleAlternatePath(); -} - -//----------------------------------------------------------------------------- -// Purpose: Toggles the track to or from its alternate path -//----------------------------------------------------------------------------- -void CPathTrack::TogglePath( void ) -{ - // Use toggles between two paths - if ( FBitSet( m_spawnflags, SF_PATH_DISABLED ) ) - { - EnablePath(); - } - else - { - DisablePath(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPathTrack::EnablePath( void ) -{ - CLEARBITS( m_spawnflags, SF_PATH_DISABLED ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPathTrack::DisablePath( void ) -{ - SETBITS( m_spawnflags, SF_PATH_DISABLED ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CPathTrack::InputEnablePath( inputdata_t &inputdata ) -{ - EnablePath(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CPathTrack::InputDisablePath( inputdata_t &inputdata ) -{ - DisablePath(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CPathTrack::InputTogglePath( inputdata_t &inputdata ) -{ - TogglePath(); -} - - -void CPathTrack::DrawDebugGeometryOverlays() -{ - // ---------------------------------------------- - // Draw line to next target is bbox is selected - // ---------------------------------------------- - if (m_debugOverlays & (OVERLAY_BBOX_BIT|OVERLAY_ABSBOX_BIT)) - { - if (m_pnext) - { - NDebugOverlay::Line(GetAbsOrigin(),m_pnext->GetAbsOrigin(),255,100,100,true,0.0); - } - } - BaseClass::DrawDebugGeometryOverlays(); -} - -CPathTrack *CPathTrack::ValidPath( CPathTrack *ppath, int testFlag ) -{ - if ( !ppath ) - return NULL; - - if ( testFlag && FBitSet( ppath->m_spawnflags, SF_PATH_DISABLED ) ) - return NULL; - - return ppath; -} - - -void CPathTrack::Project( CPathTrack *pstart, CPathTrack *pend, Vector &origin, float dist ) -{ - if ( pstart && pend ) - { - Vector dir = (pend->GetLocalOrigin() - pstart->GetLocalOrigin()); - VectorNormalize( dir ); - origin = pend->GetLocalOrigin() + dir * dist; - } -} - -CPathTrack *CPathTrack::GetNext( void ) -{ - if ( m_paltpath && FBitSet( m_spawnflags, SF_PATH_ALTERNATE ) && !FBitSet( m_spawnflags, SF_PATH_ALTREVERSE ) ) - return m_paltpath; - - return m_pnext; -} - - - -CPathTrack *CPathTrack::GetPrevious( void ) -{ - if ( m_paltpath && FBitSet( m_spawnflags, SF_PATH_ALTERNATE ) && FBitSet( m_spawnflags, SF_PATH_ALTREVERSE ) ) - return m_paltpath; - - return m_pprevious; -} - - - -void CPathTrack::SetPrevious( CPathTrack *pprev ) -{ - // Only set previous if this isn't my alternate path - if ( pprev && !FStrEq( STRING(pprev->GetEntityName()), STRING(m_altName) ) ) - m_pprevious = pprev; -} - - -CPathTrack *CPathTrack::GetNextInDir( bool bForward ) -{ - if ( bForward ) - return GetNext(); - - return GetPrevious(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Assumes this is ALWAYS enabled -// Input : origin - position along path to look ahead from -// dist - distance to look ahead, negative values look backward -// move - -// Output : Returns the track that we will be PAST in 'dist' units. -//----------------------------------------------------------------------------- -CPathTrack *CPathTrack::LookAhead( Vector &origin, float dist, int move, CPathTrack **pNextNext ) -{ - CPathTrack *pcurrent = this; - float originalDist = dist; - Vector currentPos = origin; - - bool bForward = true; - if ( dist < 0 ) - { - // Travelling backwards along the path. - dist = -dist; - bForward = false; - } - - // Move along the path, until we've gone 'dist' units or run out of path. - while ( dist > 0 ) - { - // If there is no next path track, or it's disabled, we're done. - if ( !ValidPath( pcurrent->GetNextInDir( bForward ), move ) ) - { - if ( !move ) - { - Project( pcurrent->GetNextInDir( !bForward ), pcurrent, origin, dist ); - } - - return NULL; - } - - // The next path track is valid. How far are we from it? - Vector dir = pcurrent->GetNextInDir( bForward )->GetLocalOrigin() - currentPos; - float length = dir.Length(); - - // If we are at the next node and there isn't one beyond it, return the next node. - if ( !length && !ValidPath( pcurrent->GetNextInDir( bForward )->GetNextInDir( bForward ), move ) ) - { - if ( pNextNext ) - { - *pNextNext = NULL; - } - - if ( dist == originalDist ) - { - // Didn't move at all, must be in a dead end. - return NULL; - } - - return pcurrent->GetNextInDir( bForward ); - } - - // If we don't hit the next path track within the distance remaining, we're done. - if ( length > dist ) - { - origin = currentPos + ( dir * ( dist / length ) ); - if ( pNextNext ) - { - *pNextNext = pcurrent->GetNextInDir( bForward ); - } - - return pcurrent; - } - - // We hit the next path track, advance to it. - dist -= length; - currentPos = pcurrent->GetNextInDir( bForward )->GetLocalOrigin(); - pcurrent = pcurrent->GetNextInDir( bForward ); - origin = currentPos; - } - - // We consumed all of the distance, and exactly landed on a path track. - if ( pNextNext ) - { - *pNextNext = pcurrent->GetNextInDir( bForward ); - } - - return pcurrent; -} - - -// Assumes this is ALWAYS enabled -CPathTrack *CPathTrack::Nearest( const Vector &origin ) -{ - int deadCount; - float minDist, dist; - Vector delta; - CPathTrack *ppath, *pnearest; - - - delta = origin - GetLocalOrigin(); - delta.z = 0; - minDist = delta.Length(); - pnearest = this; - ppath = GetNext(); - - // Hey, I could use the old 2 racing pointers solution to this, but I'm lazy :) - deadCount = 0; - while ( ppath && ppath != this ) - { - deadCount++; - if ( deadCount > 9999 ) - { - Warning( "Bad sequence of path_tracks from %s\n", GetDebugName() ); - Assert(0); - return NULL; - } - delta = origin - ppath->GetLocalOrigin(); - delta.z = 0; - dist = delta.Length(); - if ( dist < minDist ) - { - minDist = dist; - pnearest = ppath; - } - ppath = ppath->GetNext(); - } - return pnearest; -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns how the path follower should orient itself when moving -// through this path track. -//----------------------------------------------------------------------------- -TrackOrientationType_t CPathTrack::GetOrientationType() -{ - return m_eOrientationType; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -QAngle CPathTrack::GetOrientation( bool bForwardDir ) -{ - TrackOrientationType_t eOrient = GetOrientationType(); - if ( eOrient == TrackOrientation_FacePathAngles ) - { - return GetLocalAngles(); - } - - CPathTrack *pPrev = this; - CPathTrack *pNext = GetNextInDir( bForwardDir ); - - if ( !pNext ) - { pPrev = GetNextInDir( !bForwardDir ); - pNext = this; - } - - Vector vecDir = pNext->GetLocalOrigin() - pPrev->GetLocalOrigin(); - - QAngle angDir; - VectorAngles( vecDir, angDir ); - return angDir; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pent - -// Output : CPathTrack -//----------------------------------------------------------------------------- -CPathTrack *CPathTrack::Instance( edict_t *pent ) -{ - CBaseEntity *pEntity = CBaseEntity::Instance( pent ); - if ( FClassnameIs( pEntity, "path_track" ) ) - return (CPathTrack *)pEntity; - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPathTrack::InputPass( inputdata_t &inputdata ) -{ - m_OnPass.FireOutput( inputdata.pActivator, this ); -} diff --git a/game/server/pathtrack.h b/game/server/pathtrack.h deleted file mode 100644 index 8ab6b7f4a..000000000 --- a/game/server/pathtrack.h +++ /dev/null @@ -1,134 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef PATHTRACK_H -#define PATHTRACK_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "entityoutput.h" - - -//----------------------------------------------------------------------------- -// Spawnflag for CPathTrack -//----------------------------------------------------------------------------- -#define SF_PATH_DISABLED 0x00000001 -//#define SF_PATH_FIREONCE 0x00000002 -#define SF_PATH_ALTREVERSE 0x00000004 -#define SF_PATH_DISABLE_TRAIN 0x00000008 -#define SF_PATH_TELEPORT 0x00000010 -#define SF_PATH_ALTERNATE 0x00008000 - - -enum TrackOrientationType_t -{ - TrackOrientation_Fixed = 0, - TrackOrientation_FacePath, - TrackOrientation_FacePathAngles, -}; - - -//----------------------------------------------------------------------------- -// Paths! -//----------------------------------------------------------------------------- -class CPathTrack : public CPointEntity -{ - DECLARE_CLASS( CPathTrack, CPointEntity ); - -public: - CPathTrack(); - - void Spawn( void ); - void Activate( void ); - void DrawDebugGeometryOverlays(); - - void ToggleAlternatePath( void ); - void EnableAlternatePath( void ); - void DisableAlternatePath( void ); - bool HasAlternathPath() const; - - void TogglePath( void ); - void EnablePath( void ); - void DisablePath( void ); - - static CPathTrack *ValidPath( CPathTrack *ppath, int testFlag = true ); // Returns ppath if enabled, NULL otherwise - - CPathTrack *GetNextInDir( bool bForward ); - CPathTrack *GetNext( void ); - CPathTrack *GetPrevious( void ); - - CPathTrack *Nearest( const Vector &origin ); - //CPathTrack *LookAhead( Vector &origin, float dist, int move ); - CPathTrack *LookAhead( Vector &origin, float dist, int move, CPathTrack **pNextNext = NULL ); - - TrackOrientationType_t GetOrientationType(); - QAngle GetOrientation( bool bForwardDir ); - - CPathTrack *m_pnext; - CPathTrack *m_pprevious; - CPathTrack *m_paltpath; - - float GetRadius() const { return m_flRadius; } - - // These four methods help for circular path checking. Call BeginIteration - // before iterating, EndInteration afterwards. Call Visit on each path in the - // list. Then you can use HasBeenVisited to see if you've visited the node - // already, which means you've got a circular or lasso path. You can use the - // macro BEGIN_PATH_TRACK_ITERATION below to simplify the calls to - // BeginInteration + EndIteration. - static void BeginIteration(); - static void EndIteration(); - void Visit(); - bool HasBeenVisited() const; - -private: - void Project( CPathTrack *pstart, CPathTrack *pend, Vector &origin, float dist ); - void SetPrevious( CPathTrack *pprevious ); - void Link( void ); - - static CPathTrack *Instance( edict_t *pent ); - - void InputPass( inputdata_t &inputdata ); - - void InputToggleAlternatePath( inputdata_t &inputdata ); - void InputEnableAlternatePath( inputdata_t &inputdata ); - void InputDisableAlternatePath( inputdata_t &inputdata ); - - void InputTogglePath( inputdata_t &inputdata ); - void InputEnablePath( inputdata_t &inputdata ); - void InputDisablePath( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - - float m_flRadius; - float m_length; - string_t m_altName; - int m_nIterVal; - TrackOrientationType_t m_eOrientationType; - - COutputEvent m_OnPass; - - static int s_nCurrIterVal; - static bool s_bIsIterating; -}; - -//----------------------------------------------------------------------------- -// Used to make sure circular iteration works all nice -//----------------------------------------------------------------------------- -#define BEGIN_PATH_TRACK_ITERATION() CPathTrackVisitor _visit - -class CPathTrackVisitor -{ -public: - CPathTrackVisitor() { CPathTrack::BeginIteration(); } - ~CPathTrackVisitor() { CPathTrack::EndIteration(); } -}; - - - -#endif // PATHTRACK_H diff --git a/game/server/phys_controller.cpp b/game/server/phys_controller.cpp deleted file mode 100644 index bbdafa077..000000000 --- a/game/server/phys_controller.cpp +++ /dev/null @@ -1,1078 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "entitylist.h" -#include "physics.h" -#include "vphysics/constraints.h" -#include "physics_saverestore.h" -#include "phys_controller.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SF_THRUST_STARTACTIVE 0x0001 -#define SF_THRUST_FORCE 0x0002 -#define SF_THRUST_TORQUE 0x0004 -#define SF_THRUST_LOCAL_ORIENTATION 0x0008 -#define SF_THRUST_MASS_INDEPENDENT 0x0010 -#define SF_THRUST_IGNORE_POS 0x0020 - -class CPhysThruster; - -//----------------------------------------------------------------------------- -// Purpose: This class only implements the IMotionEvent-specific behavior -// It keeps track of the forces so they can be integrated -//----------------------------------------------------------------------------- -class CConstantForceController : public IMotionEvent -{ - DECLARE_SIMPLE_DATADESC(); - -public: - void Init( IMotionEvent::simresult_e controlType ) - { - m_controlType = controlType; - } - - void SetConstantForce( const Vector &linear, const AngularImpulse &angular ); - void ScaleConstantForce( float scale ); - - IMotionEvent::simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ); - IMotionEvent::simresult_e m_controlType; - Vector m_linear; - AngularImpulse m_angular; - Vector m_linearSave; - AngularImpulse m_angularSave; -}; - -BEGIN_SIMPLE_DATADESC( CConstantForceController ) - DEFINE_FIELD( m_controlType, FIELD_INTEGER ), - DEFINE_FIELD( m_linear, FIELD_VECTOR ), - DEFINE_FIELD( m_angular, FIELD_VECTOR ), - DEFINE_FIELD( m_linearSave, FIELD_VECTOR ), - DEFINE_FIELD( m_angularSave, FIELD_VECTOR ), -END_DATADESC() - - -void CConstantForceController::SetConstantForce( const Vector &linear, const AngularImpulse &angular ) -{ - m_linear = linear; - m_angular = angular; - // cache these for scaling later - m_linearSave = linear; - m_angularSave = angular; -} - -void CConstantForceController::ScaleConstantForce( float scale ) -{ - m_linear = m_linearSave * scale; - m_angular = m_angularSave * scale; -} - - -IMotionEvent::simresult_e CConstantForceController::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) -{ - linear = m_linear; - angular = m_angular; - - return m_controlType; -} - -// UNDONE: Make these logical entities -//----------------------------------------------------------------------------- -// Purpose: This is a general entity that has a force/motion controller that -// simply integrates a constant linear/angular acceleration -//----------------------------------------------------------------------------- -abstract_class CPhysForce : public CPointEntity -{ -public: - DECLARE_CLASS( CPhysForce, CPointEntity ); - - CPhysForce(); - ~CPhysForce(); - - DECLARE_DATADESC(); - - virtual void OnRestore( ); - void Spawn( void ); - void Activate( void ); - - void ForceOn( void ); - void ForceOff( void ); - void ActivateForce( void ); - - // Input handlers - void InputActivate( inputdata_t &inputdata ); - void InputDeactivate( inputdata_t &inputdata ); - void InputForceScale( inputdata_t &inputdata ); - - void SaveForce( void ); - void ScaleForce( float scale ); - - // MUST IMPLEMENT THIS IN DERIVED CLASS - virtual void SetupForces( IPhysicsObject *pPhys, Vector &linear, AngularImpulse &angular ) = 0; - - // optional - virtual void OnActivate( void ) {} - -protected: - IPhysicsMotionController *m_pController; - - string_t m_nameAttach; - float m_force; - float m_forceTime; - EHANDLE m_attachedObject; - bool m_wasRestored; - - CConstantForceController m_integrator; -}; - -BEGIN_DATADESC( CPhysForce ) - - DEFINE_PHYSPTR( m_pController ), - DEFINE_KEYFIELD( m_nameAttach, FIELD_STRING, "attach1" ), - DEFINE_KEYFIELD( m_force, FIELD_FLOAT, "force" ), - DEFINE_KEYFIELD( m_forceTime, FIELD_FLOAT, "forcetime" ), - - DEFINE_FIELD( m_attachedObject, FIELD_EHANDLE ), - //DEFINE_FIELD( m_wasRestored, FIELD_BOOLEAN ), // NOTE: DO NOT save/load this - it's used to detect loads - DEFINE_EMBEDDED( m_integrator ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ), - DEFINE_INPUTFUNC( FIELD_VOID, "Deactivate", InputDeactivate ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "scale", InputForceScale ), - - // Function Pointers - DEFINE_FUNCTION( ForceOff ), - -END_DATADESC() - - -CPhysForce::CPhysForce( void ) -{ - m_pController = NULL; - m_wasRestored = false; -} - -CPhysForce::~CPhysForce() -{ - if ( m_pController ) - { - physenv->DestroyMotionController( m_pController ); - } -} - -void CPhysForce::Spawn( void ) -{ - if ( m_spawnflags & SF_THRUST_LOCAL_ORIENTATION ) - { - m_integrator.Init( IMotionEvent::SIM_LOCAL_ACCELERATION ); - } - else - { - m_integrator.Init( IMotionEvent::SIM_GLOBAL_ACCELERATION ); - } -} - -void CPhysForce::OnRestore( ) -{ - BaseClass::OnRestore(); - - if ( m_pController ) - { - m_pController->SetEventHandler( &m_integrator ); - } - m_wasRestored = true; -} - -void CPhysForce::Activate( void ) -{ - BaseClass::Activate(); - - if ( m_pController ) - { - m_pController->WakeObjects(); - } - if ( m_wasRestored ) - return; - - if ( m_attachedObject == NULL ) - { - m_attachedObject = gEntList.FindEntityByName( NULL, m_nameAttach ); - } - - // Let the derived class set up before we throw the switch - OnActivate(); - - if ( m_spawnflags & SF_THRUST_STARTACTIVE ) - { - ForceOn(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysForce::InputActivate( inputdata_t &inputdata ) -{ - ForceOn(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysForce::InputDeactivate( inputdata_t &inputdata ) -{ - ForceOff(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysForce::InputForceScale( inputdata_t &inputdata ) -{ - ScaleForce( inputdata.value.Float() ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysForce::ForceOn( void ) -{ - if ( m_pController ) - return; - - ActivateForce(); - if ( m_forceTime ) - { - SetNextThink( gpGlobals->curtime + m_forceTime ); - SetThink( &CPhysForce::ForceOff ); - } -} - - -void CPhysForce::ActivateForce( void ) -{ - IPhysicsObject *pPhys = NULL; - if ( m_attachedObject ) - { - pPhys = m_attachedObject->VPhysicsGetObject(); - } - - if ( !pPhys ) - return; - - Vector linear; - AngularImpulse angular; - - SetupForces( pPhys, linear, angular ); - - m_integrator.SetConstantForce( linear, angular ); - m_pController = physenv->CreateMotionController( &m_integrator ); - m_pController->AttachObject( pPhys, true ); - // Make sure the object is simulated - pPhys->Wake(); -} - - -void CPhysForce::ForceOff( void ) -{ - if ( !m_pController ) - return; - - physenv->DestroyMotionController( m_pController ); - m_pController = NULL; - SetThink( NULL ); - SetNextThink( TICK_NEVER_THINK ); - IPhysicsObject *pPhys = NULL; - if ( m_attachedObject ) - { - pPhys = m_attachedObject->VPhysicsGetObject(); - if ( pPhys ) - { - pPhys->Wake(); - } - } -} - - -void CPhysForce::ScaleForce( float scale ) -{ - if ( !m_pController ) - ForceOn(); - - m_integrator.ScaleConstantForce( scale ); - m_pController->WakeObjects(); -} - - -//----------------------------------------------------------------------------- -// Purpose: A rocket-engine/thruster based on the force controller above -// Calculate the force (and optional torque) that the engine would create -//----------------------------------------------------------------------------- -class CPhysThruster : public CPhysForce -{ - DECLARE_CLASS( CPhysThruster, CPhysForce ); -public: - DECLARE_DATADESC(); - - virtual void OnActivate( void ); - virtual void SetupForces( IPhysicsObject *pPhys, Vector &linear, AngularImpulse &angular ); - -private: - Vector m_localOrigin; -}; - -LINK_ENTITY_TO_CLASS( phys_thruster, CPhysThruster ); - -BEGIN_DATADESC( CPhysThruster ) - - DEFINE_FIELD( m_localOrigin, FIELD_VECTOR ), - -END_DATADESC() - - - -void CPhysThruster::OnActivate( void ) -{ - if ( m_attachedObject != NULL ) - { - matrix3x4_t worldToAttached, thrusterToAttached; - MatrixInvert( m_attachedObject->EntityToWorldTransform(), worldToAttached ); - ConcatTransforms( worldToAttached, EntityToWorldTransform(), thrusterToAttached ); - MatrixGetColumn( thrusterToAttached, 3, m_localOrigin ); - - if ( HasSpawnFlags( SF_THRUST_LOCAL_ORIENTATION ) ) - { - QAngle angles; - MatrixAngles( thrusterToAttached, angles ); - SetLocalAngles( angles ); - } - // maintain the local relationship with this entity - // it may move before the thruster is activated - if ( HasSpawnFlags( SF_THRUST_IGNORE_POS ) ) - { - m_localOrigin.Init(); - } - } -} - -// utility function to duplicate this call in local space -void CalculateVelocityOffsetLocal( IPhysicsObject *pPhys, const Vector &forceLocal, const Vector &positionLocal, Vector &outVelLocal, AngularImpulse &outAngular ) -{ - Vector posWorld, forceWorld; - pPhys->LocalToWorld( &posWorld, positionLocal ); - pPhys->LocalToWorldVector( &forceWorld, forceLocal ); - Vector velWorld; - pPhys->CalculateVelocityOffset( forceWorld, posWorld, &velWorld, &outAngular ); - pPhys->WorldToLocalVector( &outVelLocal, velWorld ); -} - -void CPhysThruster::SetupForces( IPhysicsObject *pPhys, Vector &linear, AngularImpulse &angular ) -{ - Vector thrustVector; - AngleVectors( GetLocalAngles(), &thrustVector ); - thrustVector *= m_force; - - // multiply the force by mass (it's actually just an acceleration) - if ( m_spawnflags & SF_THRUST_MASS_INDEPENDENT ) - { - thrustVector *= pPhys->GetMass(); - } - if ( m_spawnflags & SF_THRUST_LOCAL_ORIENTATION ) - { - CalculateVelocityOffsetLocal( pPhys, thrustVector, m_localOrigin, linear, angular ); - } - else - { - Vector position; - VectorTransform( m_localOrigin, m_attachedObject->EntityToWorldTransform(), position ); - pPhys->CalculateVelocityOffset( thrustVector, position, &linear, &angular ); - } - - if ( !(m_spawnflags & SF_THRUST_FORCE) ) - { - // clear out force - linear.Init(); - } - - if ( !(m_spawnflags & SF_THRUST_TORQUE) ) - { - // clear out torque - angular.Init(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: A controllable motor - exerts torque -//----------------------------------------------------------------------------- -class CPhysTorque : public CPhysForce -{ - DECLARE_CLASS( CPhysTorque, CPhysForce ); -public: - DECLARE_DATADESC(); - void Spawn( void ); - virtual void SetupForces( IPhysicsObject *pPhys, Vector &linear, AngularImpulse &angular ); -private: - Vector m_axis; -}; - -BEGIN_DATADESC( CPhysTorque ) - - DEFINE_KEYFIELD( m_axis, FIELD_VECTOR, "axis" ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( phys_torque, CPhysTorque ); - -void CPhysTorque::Spawn( void ) -{ - // force spawnflags to agree with implementation of this class - m_spawnflags |= SF_THRUST_TORQUE | SF_THRUST_MASS_INDEPENDENT; - m_spawnflags &= ~SF_THRUST_FORCE; - - m_axis -= GetAbsOrigin(); - VectorNormalize(m_axis); - UTIL_SnapDirectionToAxis( m_axis ); - BaseClass::Spawn(); -} - -void CPhysTorque::SetupForces( IPhysicsObject *pPhys, Vector &linear, AngularImpulse &angular ) -{ - // clear out force - linear.Init(); - - matrix3x4_t matrix; - pPhys->GetPositionMatrix( &matrix ); - - // transform motor axis to local space - Vector axis_ls; - VectorIRotate( m_axis, matrix, axis_ls ); - - // Set torque to be around selected axis - angular = axis_ls * m_force; -} - - - -//----------------------------------------------------------------------------- -// Purpose: This class only implements the IMotionEvent-specific behavior -// It keeps track of the forces so they can be integrated -//----------------------------------------------------------------------------- -class CMotorController : public IMotionEvent -{ - DECLARE_SIMPLE_DATADESC(); - -public: - IMotionEvent::simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ); - float m_speed; - float m_maxTorque; - Vector m_axis; - float m_inertiaFactor; - - float m_lastSpeed; - float m_lastAcceleration; - float m_lastForce; - float m_restistanceDamping; -}; - -BEGIN_SIMPLE_DATADESC( CMotorController ) - - DEFINE_FIELD( m_speed, FIELD_FLOAT ), - DEFINE_FIELD( m_maxTorque, FIELD_FLOAT ), - DEFINE_KEYFIELD( m_axis, FIELD_VECTOR, "axis" ), - DEFINE_KEYFIELD( m_inertiaFactor, FIELD_FLOAT, "inertiafactor" ), - DEFINE_FIELD( m_lastSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_lastAcceleration, FIELD_FLOAT ), - DEFINE_FIELD( m_lastForce, FIELD_FLOAT ), - DEFINE_FIELD( m_restistanceDamping, FIELD_FLOAT ), - -END_DATADESC() - - -IMotionEvent::simresult_e CMotorController::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) -{ - linear = vec3_origin; - angular = vec3_origin; - - if ( m_speed == 0 ) - return SIM_NOTHING; - - matrix3x4_t matrix; - pObject->GetPositionMatrix( &matrix ); - AngularImpulse currentRotAxis; - - // currentRotAxis is in local space - pObject->GetVelocity( NULL, ¤tRotAxis ); - // transform motor axis to local space - Vector motorAxis_ls; - VectorIRotate( m_axis, matrix, motorAxis_ls ); - float currentSpeed = DotProduct( currentRotAxis, motorAxis_ls ); - - float inertia = DotProductAbs( pObject->GetInertia(), motorAxis_ls ); - - // compute absolute acceleration, don't integrate over the timestep - float accel = m_speed - currentSpeed; - float rotForce = accel * inertia * m_inertiaFactor; - - // BUGBUG: This heuristic is a little flaky - // UNDONE: Make a better heuristic for speed control - if ( fabsf(m_lastAcceleration) > 0 ) - { - float deltaSpeed = currentSpeed - m_lastSpeed; - // make sure they are going the same way - if ( deltaSpeed * accel > 0 ) - { - float factor = deltaSpeed / m_lastAcceleration; - factor = 1 - clamp( factor, 0, 1 ); - rotForce += m_lastForce * factor * m_restistanceDamping; - } - else - { - if ( currentSpeed != 0 ) - { - // have we reached a steady state that isn't our target? - float increase = deltaSpeed / m_lastAcceleration; - if ( fabsf(increase) < 0.05 ) - { - rotForce += m_lastForce * m_restistanceDamping; - } - } - } - } - // ------------------------------------------------------- - - - if ( m_maxTorque != 0 ) - { - if ( rotForce > m_maxTorque ) - { - rotForce = m_maxTorque; - } - else if ( rotForce < -m_maxTorque ) - { - rotForce = -m_maxTorque; - } - } - - m_lastForce = rotForce; - m_lastAcceleration = (rotForce / inertia); - m_lastSpeed = currentSpeed; - - // this is in local space - angular = motorAxis_ls * rotForce; - - return SIM_LOCAL_FORCE; -} - -#define SF_MOTOR_START_ON 0x0001 // starts on by default -#define SF_MOTOR_NOCOLLIDE 0x0002 // don't collide with world geometry -#define SF_MOTOR_HINGE 0x0004 // motor also acts as a hinge constraining the object to this axis -// NOTE: THIS DOESN'T WORK YET -#define SF_MOTOR_LOCAL 0x0008 // Maintain local relationship with the attached object - -class CPhysMotor : public CLogicalEntity -{ - DECLARE_CLASS( CPhysMotor, CLogicalEntity ); -public: - ~CPhysMotor(); - DECLARE_DATADESC(); - void Spawn( void ); - void Activate( void ); - void Think( void ); - - void TurnOn( void ); - void TargetSpeedChanged( void ); - void OnRestore(); - - void InputSetTargetSpeed( inputdata_t &inputdata ); - void InputTurnOn( inputdata_t &inputdata ); - void InputTurnOff( inputdata_t &inputdata ); - void CalculateAcceleration(); - - string_t m_nameAttach; - EHANDLE m_attachedObject; - float m_spinUp; - float m_additionalAcceleration; - float m_angularAcceleration; - float m_lastTime; - // FIXME: can we remove m_flSpeed from CBaseEntity? - //float m_flSpeed; - - IPhysicsConstraint *m_pHinge; - IPhysicsMotionController *m_pController; - CMotorController m_motor; -}; - - -BEGIN_DATADESC( CPhysMotor ) - - DEFINE_KEYFIELD( m_nameAttach, FIELD_STRING, "attach1" ), - DEFINE_FIELD( m_attachedObject, FIELD_EHANDLE ), - DEFINE_KEYFIELD( m_spinUp, FIELD_FLOAT, "spinup" ), - DEFINE_KEYFIELD( m_additionalAcceleration, FIELD_FLOAT, "addangaccel" ), - DEFINE_FIELD( m_angularAcceleration, FIELD_FLOAT ), - DEFINE_FIELD( m_lastTime, FIELD_TIME ), - DEFINE_PHYSPTR( m_pHinge ), - DEFINE_PHYSPTR( m_pController ), - - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetSpeed", InputSetTargetSpeed ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - - DEFINE_EMBEDDED( m_motor ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( phys_motor, CPhysMotor ); - - -void CPhysMotor::CalculateAcceleration() -{ - if ( m_spinUp ) - { - m_angularAcceleration = fabsf(m_flSpeed / m_spinUp); - } - else - { - m_angularAcceleration = fabsf(m_flSpeed); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler that sets a speed to spin up or down to. -//----------------------------------------------------------------------------- -void CPhysMotor::InputSetTargetSpeed( inputdata_t &inputdata ) -{ - if ( m_flSpeed == inputdata.value.Float() ) - return; - - m_flSpeed = inputdata.value.Float(); - TargetSpeedChanged(); - CalculateAcceleration(); -} - - -void CPhysMotor::TargetSpeedChanged( void ) -{ - SetNextThink( gpGlobals->curtime ); - m_lastTime = gpGlobals->curtime; - m_pController->WakeObjects(); -} - - -//------------------------------------------------------------------------------ -// Purpose: Input handler that turns the motor on. -//------------------------------------------------------------------------------ -void CPhysMotor::InputTurnOn( inputdata_t &inputdata ) -{ - TurnOn(); -} - - -//------------------------------------------------------------------------------ -// Purpose: Input handler that turns the motor off. -//------------------------------------------------------------------------------ -void CPhysMotor::InputTurnOff( inputdata_t &inputdata ) -{ - m_motor.m_speed = 0; - SetNextThink( TICK_NEVER_THINK ); -} - - -CPhysMotor::~CPhysMotor() -{ - if ( m_attachedObject && m_pHinge ) - { - IPhysicsObject *pPhys = m_attachedObject->VPhysicsGetObject(); - if ( pPhys ) - { - PhysClearGameFlags(pPhys, FVPHYSICS_NO_PLAYER_PICKUP); - } - } - - physenv->DestroyConstraint( m_pHinge ); - physenv->DestroyMotionController( m_pController ); -} - - -void CPhysMotor::Spawn( void ) -{ - m_motor.m_axis -= GetLocalOrigin(); - float axisLength = VectorNormalize(m_motor.m_axis); - // double check that the axis is at least a unit long. If not, warn and self-destruct. - if ( axisLength > 1.0f ) - { - UTIL_SnapDirectionToAxis( m_motor.m_axis ); - } - else - { - Warning("phys_motor %s does not have a valid axis helper, and self-destructed!\n", GetDebugName()); - - m_motor.m_speed = 0; - SetNextThink( TICK_NEVER_THINK ); - - UTIL_Remove(this); - } -} - - -void CPhysMotor::TurnOn( void ) -{ - CBaseEntity *pAttached = m_attachedObject; - if ( !pAttached ) - return; - - IPhysicsObject *pPhys = pAttached->VPhysicsGetObject(); - if ( pPhys ) - { - m_pController->WakeObjects(); - // If the current speed is zero, the objects can run a tick without getting torque'd and go back to sleep - // so force a think now and have some acceleration happen before the controller gets called. - m_lastTime = gpGlobals->curtime - TICK_INTERVAL; - Think(); - } -} - - -void CPhysMotor::Activate( void ) -{ - BaseClass::Activate(); - - // This gets called after all objects spawn and after all objects restore - if ( m_attachedObject == NULL ) - { - CBaseEntity *pAttach = gEntList.FindEntityByName( NULL, m_nameAttach ); - if ( pAttach && pAttach->GetMoveType() == MOVETYPE_VPHYSICS ) - { - m_attachedObject = pAttach; - IPhysicsObject *pPhys = m_attachedObject->VPhysicsGetObject(); - CalculateAcceleration(); - matrix3x4_t matrix; - pPhys->GetPositionMatrix( &matrix ); - Vector motorAxis_ls; - VectorIRotate( m_motor.m_axis, matrix, motorAxis_ls ); - float inertia = DotProductAbs( pPhys->GetInertia(), motorAxis_ls ); - m_motor.m_maxTorque = inertia * m_motor.m_inertiaFactor * (m_angularAcceleration + m_additionalAcceleration); - m_motor.m_restistanceDamping = 1.0f; - } - } - - if ( m_attachedObject ) - { - IPhysicsObject *pPhys = m_attachedObject->VPhysicsGetObject(); - - // create a hinge constraint for this object? - if ( m_spawnflags & SF_MOTOR_HINGE ) - { - // UNDONE: Don't do this on restore? - if ( !m_pHinge ) - { - constraint_hingeparams_t hingeParams; - hingeParams.Defaults(); - hingeParams.worldAxisDirection = m_motor.m_axis; - hingeParams.worldPosition = GetLocalOrigin(); - - m_pHinge = physenv->CreateHingeConstraint( g_PhysWorldObject, pPhys, NULL, hingeParams ); - m_pHinge->SetGameData( (void *)this ); - // can't grab this object - PhysSetGameFlags(pPhys, FVPHYSICS_NO_PLAYER_PICKUP); - } - - if ( m_spawnflags & SF_MOTOR_NOCOLLIDE ) - { - PhysDisableEntityCollisions( g_PhysWorldObject, pPhys ); - } - } - else - { - m_pHinge = NULL; - } - - // NOTE: On restore, this path isn't run because m_pController will not be NULL - if ( !m_pController ) - { - m_pController = physenv->CreateMotionController( &m_motor ); - m_pController->AttachObject( m_attachedObject->VPhysicsGetObject(), false ); - - if ( m_spawnflags & SF_MOTOR_START_ON ) - { - TurnOn(); - } - } - } -} - -void CPhysMotor::OnRestore() -{ - BaseClass::OnRestore(); - // Need to do this on restore since there's no good way to save this - if ( m_pController ) - { - m_pController->SetEventHandler( &m_motor ); - } -} - -void CPhysMotor::Think( void ) -{ - // angular acceleration is always positive - it should be treated as a magnitude - the controller - // will apply it in the proper direction - Assert(m_angularAcceleration>=0); - - m_motor.m_speed = UTIL_Approach( m_flSpeed, m_motor.m_speed, m_angularAcceleration*(gpGlobals->curtime-m_lastTime) ); - m_lastTime = gpGlobals->curtime; - if ( m_motor.m_speed != m_flSpeed ) - { - SetNextThink( gpGlobals->curtime ); - } -} - -//====================================================================================== -// KEEPUPRIGHT CONTROLLER -//====================================================================================== - -class CKeepUpright : public CPointEntity, public IMotionEvent -{ - DECLARE_CLASS( CKeepUpright, CPointEntity ); -public: - DECLARE_DATADESC(); - - CKeepUpright(); - ~CKeepUpright(); - void Spawn(); - void Activate(); - - // IMotionEvent - virtual simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ); - - // Inputs - void InputTurnOn( inputdata_t &inputdata ) - { - m_bActive = true; - } - void InputTurnOff( inputdata_t &inputdata ) - { - m_bActive = false; - } - - void InputSetAngularLimit( inputdata_t &inputdata ) - { - m_angularLimit = inputdata.value.Float(); - } - -private: - friend CBaseEntity *CreateKeepUpright( const Vector &vecOrigin, const QAngle &vecAngles, CBaseEntity *pOwner, float flAngularLimit, bool bActive ); - - Vector m_worldGoalAxis; - Vector m_localTestAxis; - IPhysicsMotionController *m_pController; - string_t m_nameAttach; - EHANDLE m_attachedObject; - float m_angularLimit; - bool m_bActive; - bool m_bDampAllRotation; -}; - -#define SF_KEEPUPRIGHT_START_INACTIVE 0x0001 - -LINK_ENTITY_TO_CLASS( phys_keepupright, CKeepUpright ); - -BEGIN_DATADESC( CKeepUpright ) - - DEFINE_FIELD( m_worldGoalAxis, FIELD_VECTOR ), - DEFINE_FIELD( m_localTestAxis, FIELD_VECTOR ), - DEFINE_PHYSPTR( m_pController ), - DEFINE_KEYFIELD( m_nameAttach, FIELD_STRING, "attach1" ), - DEFINE_FIELD( m_attachedObject, FIELD_EHANDLE ), - DEFINE_KEYFIELD( m_angularLimit, FIELD_FLOAT, "angularlimit" ), - DEFINE_FIELD( m_bActive, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bDampAllRotation, FIELD_BOOLEAN ), - - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetAngularLimit", InputSetAngularLimit ), - -END_DATADESC() - -CKeepUpright::CKeepUpright() -{ - // by default, recover from up to 15 degrees / sec angular velocity - m_angularLimit = 15; - m_attachedObject = NULL; - m_bDampAllRotation = false; -} - -CKeepUpright::~CKeepUpright() -{ - if ( m_pController ) - { - physenv->DestroyMotionController( m_pController ); - m_pController = NULL; - } -} - -void CKeepUpright::Spawn() -{ - // align the object's local Z axis - m_localTestAxis.Init( 0, 0, 1 ); - // Use our Up axis so mapmakers can orient us arbitrarily - GetVectors( NULL, NULL, &m_worldGoalAxis ); - - SetMoveType( MOVETYPE_NONE ); - - if ( m_spawnflags & SF_KEEPUPRIGHT_START_INACTIVE ) - { - m_bActive = false; - } - else - { - m_bActive = true; - } -} - -void CKeepUpright::Activate() -{ - BaseClass::Activate(); - - if ( !m_pController ) - { - // This case occurs when spawning - IPhysicsObject *pPhys; - if ( m_attachedObject ) - { - pPhys = m_attachedObject->VPhysicsGetObject(); - } - else - { - pPhys = FindPhysicsObjectByName( STRING(m_nameAttach), this ); - } - - if ( !pPhys ) - { - UTIL_Remove(this); - return; - } - // HACKHACK: Due to changes in the vehicle simulator the keepupright controller used in coast_01 is unstable - // force it to have perfect damping to compensate. - // detect it using the hack of angular limit == 150, attached to a vehicle - // Fixing it in the code is the simplest course of action presently -#ifdef HL2_DLL - if ( m_angularLimit == 150.0f ) - { - CBaseEntity *pEntity = static_cast(pPhys->GetGameData()); - if ( pEntity && pEntity->GetServerVehicle() && Q_stristr( gpGlobals->mapname.ToCStr(), "d2_coast_01" ) ) - { - m_bDampAllRotation = true; - } - } -#endif - - m_pController = physenv->CreateMotionController( (IMotionEvent *)this ); - m_pController->AttachObject( pPhys, false ); - } - else - { - // This case occurs when restoring - m_pController->SetEventHandler( this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Use this to spawn a keepupright controller via code instead of map-placed -//----------------------------------------------------------------------------- -CBaseEntity *CreateKeepUpright( const Vector &vecOrigin, const QAngle &vecAngles, CBaseEntity *pOwner, float flAngularLimit, bool bActive ) -{ - CKeepUpright *pKeepUpright = (CKeepUpright*)CBaseEntity::Create( "phys_keepupright", vecOrigin, vecAngles, pOwner ); - if ( pKeepUpright ) - { - pKeepUpright->m_attachedObject = pOwner; - pKeepUpright->m_angularLimit = flAngularLimit; - if ( !bActive ) - { - pKeepUpright->AddSpawnFlags( SF_KEEPUPRIGHT_START_INACTIVE ); - } - pKeepUpright->Spawn(); - pKeepUpright->Activate(); - } - - return pKeepUpright; -} - -IMotionEvent::simresult_e CKeepUpright::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) -{ - if ( !m_bActive ) - return SIM_NOTHING; - - linear.Init(); - - AngularImpulse angVel; - pObject->GetVelocity( NULL, &angVel ); - - matrix3x4_t matrix; - // get the object's local to world transform - pObject->GetPositionMatrix( &matrix ); - - // Get the alignment axis in object space - Vector currentLocalTargetAxis; - VectorIRotate( m_worldGoalAxis, matrix, currentLocalTargetAxis ); - - float invDeltaTime = (1/deltaTime); - - if ( m_bDampAllRotation ) - { - angular = ComputeRotSpeedToAlignAxes( m_localTestAxis, currentLocalTargetAxis, angVel, 0, invDeltaTime, m_angularLimit ); - angular -= angVel; - angular *= invDeltaTime; - return SIM_LOCAL_ACCELERATION; - } - - angular = ComputeRotSpeedToAlignAxes( m_localTestAxis, currentLocalTargetAxis, angVel, 1.0, invDeltaTime, m_angularLimit ); - angular *= invDeltaTime; - -#if 0 - Vector position, out, worldAxis; - MatrixGetColumn( matrix, 3, position ); - out = angular * 0.1; - VectorRotate( m_localTestAxis, matrix, worldAxis ); - NDebugOverlay::Line( position, position + worldAxis * 100, 255, 0, 0, 0, 0 ); - NDebugOverlay::Line( position, position + m_worldGoalAxis * 100, 255, 0, 0, 0, 0 ); - NDebugOverlay::Line( position, position + out, 255, 255, 0, 0, 0 ); -#endif - - return SIM_LOCAL_ACCELERATION; -} - - -// computes the torque necessary to align testAxis with alignAxis -AngularImpulse ComputeRotSpeedToAlignAxes( const Vector &testAxis, const Vector &alignAxis, const AngularImpulse ¤tSpeed, float damping, float scale, float maxSpeed ) -{ - Vector rotationAxis = CrossProduct( testAxis, alignAxis ); - - // atan2() is well defined, so do a Dot & Cross instead of asin(Cross) - float cosine = DotProduct( testAxis, alignAxis ); - float sine = VectorNormalize( rotationAxis ); - float angle = atan2( sine, cosine ); - - angle = RAD2DEG(angle); - AngularImpulse angular = rotationAxis * scale * angle; - angular -= rotationAxis * damping * DotProduct( currentSpeed, rotationAxis ); - - float len = VectorNormalize( angular ); - - if ( len > maxSpeed ) - { - len = maxSpeed; - } - - return angular * len; -} - diff --git a/game/server/phys_controller.h b/game/server/phys_controller.h deleted file mode 100644 index c1314a574..000000000 --- a/game/server/phys_controller.h +++ /dev/null @@ -1,19 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef PHYS_CONTROLLER_H -#define PHYS_CONTROLLER_H -#ifdef _WIN32 -#pragma once -#endif - - -CBaseEntity *CreateKeepUpright( const Vector &vecOrigin, const QAngle &vecAngles, CBaseEntity *pOwner, float flAngularLimit, bool bActive ); - -AngularImpulse ComputeRotSpeedToAlignAxes( const Vector &testAxis, const Vector &alignAxis, const AngularImpulse ¤tSpeed, - float damping, float scale, float maxSpeed ); - -#endif // PHYS_CONTROLLER_H diff --git a/game/server/physconstraint.cpp b/game/server/physconstraint.cpp deleted file mode 100644 index e7bfb509b..000000000 --- a/game/server/physconstraint.cpp +++ /dev/null @@ -1,1999 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: Physics constraint entities -// -// $NoKeywords: $ -//===========================================================================// - -#include "cbase.h" -#include "physics.h" -#include "entityoutput.h" -#include "engine/IEngineSound.h" -#include "vphysics/constraints.h" -#include "igamesystem.h" -#include "physics_saverestore.h" -#include "vcollide_parse.h" -#include "positionwatcher.h" -#include "fmtstr.h" -#include "physics_prop_ragdoll.h" - -#define HINGE_NOTIFY HL2_EPISODIC -#if HINGE_NOTIFY -#include "physconstraint_sounds.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SF_CONSTRAINT_DISABLE_COLLISION 0x0001 -#define SF_SLIDE_LIMIT_ENDS 0x0002 -#define SF_PULLEY_RIGID 0x0002 -#define SF_LENGTH_RIGID 0x0002 -#define SF_RAGDOLL_FREEMOVEMENT 0x0002 -#define SF_CONSTRAINT_START_INACTIVE 0x0004 -#define SF_CONSTRAINT_ASSUME_WORLD_GEOMETRY 0x0008 -#define SF_CONSTRAINT_NO_CONNECT_UNTIL_ACTIVATED 0x0010 // Will only check the two attached entities at activation - - -ConVar g_debug_constraint_sounds ( "g_debug_constraint_sounds", "0", FCVAR_CHEAT, "Enable debug printing about constraint sounds."); - -struct hl_constraint_info_t -{ - hl_constraint_info_t() - { - pObjects[0] = pObjects[1] = NULL; - pGroup = NULL; - anchorPosition[0].Init(); - anchorPosition[1].Init(); - swapped = false; - massScale[0] = massScale[1] = 1.0f; - } - Vector anchorPosition[2]; - IPhysicsObject *pObjects[2]; - IPhysicsConstraintGroup *pGroup; - float massScale[2]; - bool swapped; -}; - -struct constraint_anchor_t -{ - Vector localOrigin; - EHANDLE hEntity; - int parentAttachment; - string_t name; - float massScale; -}; - -class CAnchorList : public CAutoGameSystem -{ -public: - CAnchorList( char const *name ) : CAutoGameSystem( name ) - { - } - void LevelShutdownPostEntity() - { - m_list.Purge(); - } - - void AddToList( CBaseEntity *pEntity, float massScale ) - { - int index = m_list.AddToTail(); - constraint_anchor_t *pAnchor = &m_list[index]; - - pAnchor->hEntity = pEntity->GetParent(); - pAnchor->parentAttachment = pEntity->GetParentAttachment(); - pAnchor->name = pEntity->GetEntityName(); - pAnchor->localOrigin = pEntity->GetLocalOrigin(); - pAnchor->massScale = massScale; - } - - constraint_anchor_t *Find( string_t name ) - { - for ( int i = m_list.Count()-1; i >=0; i-- ) - { - if ( FStrEq( STRING(m_list[i].name), STRING(name) ) ) - { - return &m_list[i]; - } - } - return NULL; - } - -private: - CUtlVector m_list; -}; - -static CAnchorList g_AnchorList( "CAnchorList" ); - -class CConstraintAnchor : public CPointEntity -{ - DECLARE_CLASS( CConstraintAnchor, CPointEntity ); -public: - CConstraintAnchor() - { - m_massScale = 1.0f; - } - void Spawn( void ) - { - if ( GetParent() ) - { - g_AnchorList.AddToList( this, m_massScale ); - UTIL_Remove( this ); - } - } - DECLARE_DATADESC(); - - float m_massScale; -}; - -BEGIN_DATADESC( CConstraintAnchor ) - DEFINE_KEYFIELD( m_massScale, FIELD_FLOAT, "massScale" ), -END_DATADESC() - -LINK_ENTITY_TO_CLASS( info_constraint_anchor, CConstraintAnchor ); - -class CPhysConstraintSystem : public CLogicalEntity -{ - DECLARE_CLASS( CPhysConstraintSystem, CLogicalEntity ); -public: - - void Spawn(); - IPhysicsConstraintGroup *GetVPhysicsGroup() { return m_pMachine; } - - DECLARE_DATADESC(); -private: - IPhysicsConstraintGroup *m_pMachine; - int m_additionalIterations; -}; - -BEGIN_DATADESC( CPhysConstraintSystem ) - DEFINE_PHYSPTR( m_pMachine ), - DEFINE_KEYFIELD( m_additionalIterations, FIELD_INTEGER, "additionaliterations" ), - -END_DATADESC() - - -void CPhysConstraintSystem::Spawn() -{ - constraint_groupparams_t group; - group.Defaults(); - group.additionalIterations = m_additionalIterations; - m_pMachine = physenv->CreateConstraintGroup( group ); -} - -LINK_ENTITY_TO_CLASS( phys_constraintsystem, CPhysConstraintSystem ); - -void PhysTeleportConstrainedEntity( CBaseEntity *pTeleportSource, IPhysicsObject *pObject0, IPhysicsObject *pObject1, const Vector &prevPosition, const QAngle &prevAngles, bool physicsRotate ) -{ - // teleport the other object - CBaseEntity *pEntity0 = static_cast (pObject0->GetGameData()); - CBaseEntity *pEntity1 = static_cast (pObject1->GetGameData()); - if ( !pEntity0 || !pEntity1 ) - return; - - // figure out which entity needs to be fixed up (the one that isn't pTeleportSource) - CBaseEntity *pFixup = pEntity1; - // teleport the other object - if ( pTeleportSource != pEntity0 ) - { - if ( pTeleportSource != pEntity1 ) - { - Msg("Bogus teleport notification!!\n"); - return; - } - pFixup = pEntity0; - } - - // constraint doesn't move this entity - if ( pFixup->GetMoveType() != MOVETYPE_VPHYSICS ) - return; - - if ( !pFixup->VPhysicsGetObject() || !pFixup->VPhysicsGetObject()->IsMoveable() ) - return; - - QAngle oldAngles = prevAngles; - - if ( !physicsRotate ) - { - oldAngles = pTeleportSource->GetAbsAngles(); - } - - matrix3x4_t startCoord, startInv, endCoord, xform; - AngleMatrix( oldAngles, prevPosition, startCoord ); - MatrixInvert( startCoord, startInv ); - ConcatTransforms( pTeleportSource->EntityToWorldTransform(), startInv, xform ); - QAngle fixupAngles; - Vector fixupPos; - - ConcatTransforms( xform, pFixup->EntityToWorldTransform(), endCoord ); - MatrixAngles( endCoord, fixupAngles, fixupPos ); - pFixup->Teleport( &fixupPos, &fixupAngles, NULL ); -} - -static void DrawPhysicsBounds( IPhysicsObject *pObject, int r, int g, int b, int a ) -{ - const CPhysCollide *pCollide = pObject->GetCollide(); - Vector pos; - QAngle angles; - pObject->GetPosition( &pos, &angles ); - Vector mins, maxs; - physcollision->CollideGetAABB( &mins, &maxs, pCollide, vec3_origin, vec3_angle ); - // don't fight the z-buffer - mins -= Vector(1,1,1); - maxs += Vector(1,1,1); - NDebugOverlay::BoxAngles( pos, mins, maxs, angles, r, g, b, a, 0 ); -} - -static void DrawConstraintObjectsAxes(CBaseEntity *pConstraintEntity, IPhysicsConstraint *pConstraint) -{ - if ( !pConstraint || !pConstraintEntity ) - return; - matrix3x4_t xformRef, xformAtt; - bool bXform = pConstraint->GetConstraintTransform( &xformRef, &xformAtt ); - IPhysicsObject *pRef = pConstraint->GetReferenceObject(); - - if ( pRef && !pRef->IsStatic() ) - { - if ( bXform ) - { - Vector pos, posWorld; - QAngle angles; - MatrixAngles( xformRef, angles, pos ); - pRef->LocalToWorld( &posWorld, pos ); - NDebugOverlay::Axis( posWorld, vec3_angle, 12, false, 0 ); - } - DrawPhysicsBounds( pRef, 0, 255, 0, 12 ); - } - IPhysicsObject *pAttach = pConstraint->GetAttachedObject(); - if ( pAttach && !pAttach->IsStatic() ) - { - if ( bXform ) - { - Vector pos, posWorld; - QAngle angles; - MatrixAngles( xformAtt, angles, pos ); - pAttach->LocalToWorld( &posWorld, pos ); - NDebugOverlay::Axis( posWorld, vec3_angle, 12, false, 0 ); - } - DrawPhysicsBounds( pAttach, 255, 0, 0, 12 ); - } -} - -abstract_class CPhysConstraint : public CLogicalEntity -{ - DECLARE_CLASS( CPhysConstraint, CLogicalEntity ); -public: - - CPhysConstraint(); - ~CPhysConstraint(); - - DECLARE_DATADESC(); - - void Spawn( void ); - void Precache( void ); - void Activate( void ); - - void ClearStaticFlag( IPhysicsObject *pObj ) - { - if ( !pObj ) - return; - PhysClearGameFlags( pObj, FVPHYSICS_CONSTRAINT_STATIC ); - } - - virtual void Deactivate() - { - if ( !m_pConstraint ) - return; - m_pConstraint->Deactivate(); - ClearStaticFlag( m_pConstraint->GetReferenceObject() ); - ClearStaticFlag( m_pConstraint->GetAttachedObject() ); - if ( m_spawnflags & SF_CONSTRAINT_DISABLE_COLLISION ) - { - // constraint may be getting deactivated because an object got deleted, so check them here. - IPhysicsObject *pRef = m_pConstraint->GetReferenceObject(); - IPhysicsObject *pAtt = m_pConstraint->GetAttachedObject(); - if ( pRef && pAtt ) - { - PhysEnableEntityCollisions( pRef, pAtt ); - } - } - } - - void OnBreak( void ) - { - Deactivate(); - if ( m_breakSound != NULL_STRING ) - { - CPASAttenuationFilter filter( this, ATTN_STATIC ); - - Vector origin = GetAbsOrigin(); - Vector refPos = origin, attachPos = origin; - - IPhysicsObject *pRef = m_pConstraint->GetReferenceObject(); - if ( pRef && (pRef != g_PhysWorldObject) ) - { - pRef->GetPosition( &refPos, NULL ); - attachPos = refPos; - } - IPhysicsObject *pAttach = m_pConstraint->GetAttachedObject(); - if ( pAttach && (pAttach != g_PhysWorldObject) ) - { - pAttach->GetPosition( &attachPos, NULL ); - if ( !pRef || (pRef == g_PhysWorldObject) ) - { - refPos = attachPos; - } - } - - VectorAdd( refPos, attachPos, origin ); - origin *= 0.5f; - - EmitSound_t ep; - ep.m_nChannel = CHAN_STATIC; - ep.m_pSoundName = STRING(m_breakSound); - ep.m_flVolume = VOL_NORM; - ep.m_SoundLevel = ATTN_TO_SNDLVL( ATTN_STATIC ); - ep.m_pOrigin = &origin; - - EmitSound( filter, entindex(), ep ); - } - m_OnBreak.FireOutput( this, this ); - // queue this up to be deleted at the end of physics - // The Deactivate() call should make sure we don't get more of these callbacks. - PhysCallbackRemove( this->NetworkProp() ); - } - - void InputBreak( inputdata_t &inputdata ) - { - if ( m_pConstraint ) - m_pConstraint->Deactivate(); - - OnBreak(); - } - - void InputOnBreak( inputdata_t &inputdata ) - { - OnBreak(); - } - - void InputTurnOn( inputdata_t &inputdata ) - { - if ( HasSpawnFlags( SF_CONSTRAINT_NO_CONNECT_UNTIL_ACTIVATED ) ) - { - ActivateConstraint(); - } - - if ( !m_pConstraint || !m_pConstraint->GetReferenceObject() || !m_pConstraint->GetAttachedObject() ) - return; - - m_pConstraint->Activate(); - m_pConstraint->GetReferenceObject()->Wake(); - m_pConstraint->GetAttachedObject()->Wake(); - } - - void InputTurnOff( inputdata_t &inputdata ) - { - Deactivate(); - } - - int DrawDebugTextOverlays() - { - int pos = BaseClass::DrawDebugTextOverlays(); - if ( m_pConstraint && (m_debugOverlays & OVERLAY_TEXT_BIT) ) - { - constraint_breakableparams_t params; - Q_memset(¶ms,0,sizeof(params)); - m_pConstraint->GetConstraintParams( ¶ms ); - - if ( (params.bodyMassScale[0] != 1.0f && params.bodyMassScale[0] != 0.0f) || (params.bodyMassScale[1] != 1.0f && params.bodyMassScale[1] != 0.0f) ) - { - CFmtStr str("mass ratio %.4f:%.4f\n", params.bodyMassScale[0], params.bodyMassScale[1] ); - NDebugOverlay::EntityTextAtPosition( GetAbsOrigin(), pos, str.Access(), 0, 255, 255, 0, 255 ); - } - pos++; - } - return pos; - } - - void DrawDebugGeometryOverlays() - { - if ( m_debugOverlays & (OVERLAY_BBOX_BIT|OVERLAY_PIVOT_BIT|OVERLAY_ABSBOX_BIT) ) - { - DrawConstraintObjectsAxes(this, m_pConstraint); - } - BaseClass::DrawDebugGeometryOverlays(); - } - - void GetBreakParams( constraint_breakableparams_t ¶ms, const hl_constraint_info_t &info ) - { - params.Defaults(); - params.forceLimit = lbs2kg(m_forceLimit); - params.torqueLimit = lbs2kg(m_torqueLimit); - params.isActive = HasSpawnFlags( SF_CONSTRAINT_START_INACTIVE ) ? false : true; - params.bodyMassScale[0] = info.massScale[0]; - params.bodyMassScale[1] = info.massScale[1]; - } - - // the notify system calls this on the constrained entities - used to detect & follow teleports - void NotifySystemEvent( CBaseEntity *pNotify, notify_system_event_t eventType, const notify_system_event_params_t ¶ms ); - - // gets called at setup time on first init and restore - virtual void OnConstraintSetup( hl_constraint_info_t &info ); - - // return the internal constraint object (used by sound gadgets) - inline IPhysicsConstraint *GetPhysConstraint() { return m_pConstraint; } - -protected: - void GetConstraintObjects( hl_constraint_info_t &info ); - void SetupTeleportationHandling( hl_constraint_info_t &info ); - bool ActivateConstraint( void ); - virtual IPhysicsConstraint *CreateConstraint( IPhysicsConstraintGroup *pGroup, const hl_constraint_info_t &info ) = 0; - - IPhysicsConstraint *m_pConstraint; - - // These are "template" values used to construct the hinge - string_t m_nameAttach1; - string_t m_nameAttach2; - string_t m_breakSound; - string_t m_nameSystem; - float m_forceLimit; - float m_torqueLimit; - unsigned int m_teleportTick; - float m_minTeleportDistance; - - COutputEvent m_OnBreak; -}; - -BEGIN_DATADESC( CPhysConstraint ) - - DEFINE_PHYSPTR( m_pConstraint ), - - DEFINE_KEYFIELD( m_nameSystem, FIELD_STRING, "constraintsystem" ), - DEFINE_KEYFIELD( m_nameAttach1, FIELD_STRING, "attach1" ), - DEFINE_KEYFIELD( m_nameAttach2, FIELD_STRING, "attach2" ), - DEFINE_KEYFIELD( m_breakSound, FIELD_SOUNDNAME, "breaksound" ), - DEFINE_KEYFIELD( m_forceLimit, FIELD_FLOAT, "forcelimit" ), - DEFINE_KEYFIELD( m_torqueLimit, FIELD_FLOAT, "torquelimit" ), - DEFINE_KEYFIELD( m_minTeleportDistance, FIELD_FLOAT, "teleportfollowdistance" ), -// DEFINE_FIELD( m_teleportTick, FIELD_INTEGER ), - - DEFINE_OUTPUT( m_OnBreak, "OnBreak" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Break", InputBreak ), - DEFINE_INPUTFUNC( FIELD_VOID, "ConstraintBroken", InputOnBreak ), - - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - -END_DATADESC() - - -CPhysConstraint::CPhysConstraint( void ) -{ - m_pConstraint = NULL; - m_nameAttach1 = NULL_STRING; - m_nameAttach2 = NULL_STRING; - m_forceLimit = 0; - m_torqueLimit = 0; - m_teleportTick = 0xFFFFFFFF; - m_minTeleportDistance = 0.0f; -} - -CPhysConstraint::~CPhysConstraint() -{ - Deactivate(); - physenv->DestroyConstraint( m_pConstraint ); -} - -void CPhysConstraint::Precache( void ) -{ - if ( m_breakSound != NULL_STRING ) - { - PrecacheScriptSound( STRING(m_breakSound) ); - } -} - -void CPhysConstraint::Spawn( void ) -{ - BaseClass::Spawn(); - - Precache(); -} - -// debug function - slow, uses dynamic_cast<> - use this to query the attached objects -// physics_debug_entity toggles the constraint system for an object using this -bool GetConstraintAttachments( CBaseEntity *pEntity, CBaseEntity *pAttachOut[2], IPhysicsObject *pAttachVPhysics[2] ) -{ - CPhysConstraint *pConstraintEntity = dynamic_cast(pEntity); - if ( pConstraintEntity ) - { - IPhysicsConstraint *pConstraint = pConstraintEntity->GetPhysConstraint(); - if ( pConstraint ) - { - IPhysicsObject *pRef = pConstraint->GetReferenceObject(); - pAttachVPhysics[0] = pRef; - pAttachOut[0] = pRef ? static_cast(pRef->GetGameData()) : NULL; - IPhysicsObject *pAttach = pConstraint->GetAttachedObject(); - pAttachVPhysics[1] = pAttach; - pAttachOut[1] = pAttach ? static_cast(pAttach->GetGameData()) : NULL; - return true; - } - } - return false; -} - -void DebugConstraint(CBaseEntity *pEntity) -{ - CPhysConstraint *pConstraintEntity = dynamic_cast(pEntity); - if ( pConstraintEntity ) - { - IPhysicsConstraint *pConstraint = pConstraintEntity->GetPhysConstraint(); - if ( pConstraint ) - { - pConstraint->OutputDebugInfo(); - } - } -} - - -void FindPhysicsAnchor( string_t name, hl_constraint_info_t &info, int index, CBaseEntity *pErrorEntity ) -{ - constraint_anchor_t *pAnchor = g_AnchorList.Find( name ); - if ( pAnchor ) - { - CBaseEntity *pEntity = pAnchor->hEntity; - if ( pEntity ) - { - info.massScale[index] = pAnchor->massScale; - bool bWroteAttachment = false; - if ( pAnchor->parentAttachment > 0 ) - { - CBaseAnimating *pAnim = pAnchor->hEntity->GetBaseAnimating(); - if ( pAnim ) - { - IPhysicsObject *list[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int listCount = pAnchor->hEntity->VPhysicsGetObjectList( list, ARRAYSIZE(list) ); - int iPhysicsBone = pAnim->GetPhysicsBone( pAnim->GetAttachmentBone( pAnchor->parentAttachment ) ); - if ( iPhysicsBone < listCount ) - { - Vector pos; - info.pObjects[index] = list[iPhysicsBone]; - pAnim->GetAttachment( pAnchor->parentAttachment, pos ); - list[iPhysicsBone]->WorldToLocal( &info.anchorPosition[index], pos ); - bWroteAttachment = true; - } - } - } - if ( !bWroteAttachment ) - { - info.anchorPosition[index] = pAnchor->localOrigin; - info.pObjects[index] = pAnchor->hEntity->VPhysicsGetObject(); - } - } - else - { - pAnchor = NULL; - } - } - if ( !pAnchor ) - { - info.anchorPosition[index] = vec3_origin; - info.pObjects[index] = FindPhysicsObjectByName( STRING(name), pErrorEntity ); - info.massScale[index] = 1.0f; - } -} - -void CPhysConstraint::OnConstraintSetup( hl_constraint_info_t &info ) -{ - if ( info.pObjects[0] && info.pObjects[1] ) - { - SetupTeleportationHandling( info ); - } - if ( m_spawnflags & SF_CONSTRAINT_DISABLE_COLLISION ) - { - PhysDisableEntityCollisions( info.pObjects[0], info.pObjects[1] ); - } -} - -void CPhysConstraint::SetupTeleportationHandling( hl_constraint_info_t &info ) -{ - CBaseEntity *pEntity0 = (CBaseEntity *)info.pObjects[0]->GetGameData(); - if ( pEntity0 ) - { - g_pNotify->AddEntity( this, pEntity0 ); - } - - CBaseEntity *pEntity1 = (CBaseEntity *)info.pObjects[1]->GetGameData(); - if ( pEntity1 ) - { - g_pNotify->AddEntity( this, pEntity1 ); - } -} - -static IPhysicsConstraintGroup *GetRagdollConstraintGroup( IPhysicsObject *pObj ) -{ - if ( pObj ) - { - CBaseEntity *pEntity = static_cast(pObj->GetGameData()); - ragdoll_t *pRagdoll = Ragdoll_GetRagdoll(pEntity); - if ( pRagdoll ) - return pRagdoll->pGroup; - } - return NULL; -} - -void CPhysConstraint::GetConstraintObjects( hl_constraint_info_t &info ) -{ - FindPhysicsAnchor( m_nameAttach1, info, 0, this ); - FindPhysicsAnchor( m_nameAttach2, info, 1, this ); - - // Missing one object, assume the world instead - if ( info.pObjects[0] == NULL && info.pObjects[1] ) - { - if ( Q_strlen(STRING(m_nameAttach1)) ) - { - Warning("Bogus constraint %s (attaches ENTITY NOT FOUND:%s to %s)\n", GetDebugName(), STRING(m_nameAttach1), STRING(m_nameAttach2)); -#ifdef HL2_EPISODIC - info.pObjects[0] = info.pObjects[1] = NULL; - return; -#endif // HL2_EPISODIC - } - info.pObjects[0] = g_PhysWorldObject; - info.massScale[0] = info.massScale[1] = 1.0f; // no mass scale on world constraint - } - else if ( info.pObjects[0] && !info.pObjects[1] ) - { - if ( Q_strlen(STRING(m_nameAttach2)) ) - { - Warning("Bogus constraint %s (attaches %s to ENTITY NOT FOUND:%s)\n", GetDebugName(), STRING(m_nameAttach1), STRING(m_nameAttach2)); -#ifdef HL2_EPISODIC - info.pObjects[0] = info.pObjects[1] = NULL; - return; -#endif // HL2_EPISODIC - } - info.pObjects[1] = info.pObjects[0]; - info.pObjects[0] = g_PhysWorldObject; // Try to make the world object consistently object0 for ease of implementation - info.massScale[0] = info.massScale[1] = 1.0f; // no mass scale on world constraint - info.swapped = true; - } - - info.pGroup = GetRagdollConstraintGroup(info.pObjects[0]); - if ( !info.pGroup ) - { - info.pGroup = GetRagdollConstraintGroup(info.pObjects[1]); - } -} - -void CPhysConstraint::Activate( void ) -{ - BaseClass::Activate(); - - if ( HasSpawnFlags( SF_CONSTRAINT_NO_CONNECT_UNTIL_ACTIVATED ) == false ) - { - if ( !ActivateConstraint() ) - { - UTIL_Remove(this); - } - } -} - -IPhysicsConstraintGroup *GetConstraintGroup( string_t systemName ) -{ - CBaseEntity *pMachine = gEntList.FindEntityByName( NULL, systemName ); - - if ( pMachine ) - { - CPhysConstraintSystem *pGroup = dynamic_cast(pMachine); - if ( pGroup ) - { - return pGroup->GetVPhysicsGroup(); - } - } - return NULL; -} - -bool CPhysConstraint::ActivateConstraint( void ) -{ - // A constraint attaches two objects to each other. - // The constraint is specified in the coordinate frame of the "reference" object - // and constrains the "attached" object - hl_constraint_info_t info; - if ( m_pConstraint ) - { - // already have a constraint, don't make a new one - info.pObjects[0] = m_pConstraint->GetReferenceObject(); - info.pObjects[1] = m_pConstraint->GetAttachedObject(); - OnConstraintSetup(info); - return true; - } - - GetConstraintObjects( info ); - if ( !info.pObjects[0] && !info.pObjects[1] ) - return false; - - if ( info.pObjects[0]->IsStatic() && info.pObjects[1]->IsStatic() ) - { - Warning("Constraint (%s) attached to two static objects (%s and %s)!!!\n", STRING(GetEntityName()), STRING(m_nameAttach1), m_nameAttach2 == NULL_STRING ? "world" : STRING(m_nameAttach2) ); - return false; - } - - if ( info.pObjects[0]->GetShadowController() && info.pObjects[1]->GetShadowController() ) - { - Warning("Constraint (%s) attached to two shadow objects (%s and %s)!!!\n", STRING(GetEntityName()), STRING(m_nameAttach1), m_nameAttach2 == NULL_STRING ? "world" : STRING(m_nameAttach2) ); - return false; - } - IPhysicsConstraintGroup *pGroup = GetConstraintGroup( m_nameSystem ); - if ( !pGroup ) - { - pGroup = info.pGroup; - } - m_pConstraint = CreateConstraint( pGroup, info ); - if ( !m_pConstraint ) - return false; - - m_pConstraint->SetGameData( (void *)this ); - - if ( pGroup ) - { - pGroup->Activate(); - } - - OnConstraintSetup(info); - - return true; -} - -void CPhysConstraint::NotifySystemEvent( CBaseEntity *pNotify, notify_system_event_t eventType, const notify_system_event_params_t ¶ms ) -{ - // don't recurse - if ( eventType != NOTIFY_EVENT_TELEPORT || (unsigned int)gpGlobals->tickcount == m_teleportTick ) - return; - - float distance = (params.pTeleport->prevOrigin - pNotify->GetAbsOrigin()).Length(); - - // no need to follow a small teleport - if ( distance <= m_minTeleportDistance ) - return; - - m_teleportTick = gpGlobals->tickcount; - - PhysTeleportConstrainedEntity( pNotify, m_pConstraint->GetReferenceObject(), m_pConstraint->GetAttachedObject(), params.pTeleport->prevOrigin, params.pTeleport->prevAngles, params.pTeleport->physicsRotate ); -} - -class CPhysHinge : public CPhysConstraint, public IVPhysicsWatcher -{ - DECLARE_CLASS( CPhysHinge, CPhysConstraint ); - -public: - void Spawn( void ); - IPhysicsConstraint *CreateConstraint( IPhysicsConstraintGroup *pGroup, const hl_constraint_info_t &info ) - { - if ( m_hinge.worldAxisDirection == vec3_origin ) - { - DevMsg("ERROR: Hinge with bad data!!!\n" ); - return NULL; - } - GetBreakParams( m_hinge.constraint, info ); - m_hinge.constraint.strength = 1.0; - // BUGBUG: These numbers are very hard to edit - // Scale by 1000 to make things easier - // CONSIDER: Unify the units of torque around something other - // than HL units (kg * in^2 / s ^2) - m_hinge.hingeAxis.SetAxisFriction( 0, 0, m_hingeFriction * 1000 ); - - int hingeAxis; - if ( IsWorldHinge( info, &hingeAxis ) ) - { - info.pObjects[1]->BecomeHinged( hingeAxis ); - } - else - { - RemoveSpawnFlags( SF_CONSTRAINT_ASSUME_WORLD_GEOMETRY ); - } - - return physenv->CreateHingeConstraint( info.pObjects[0], info.pObjects[1], pGroup, m_hinge ); - } - - void DrawDebugGeometryOverlays() - { - if ( m_debugOverlays & (OVERLAY_BBOX_BIT|OVERLAY_PIVOT_BIT|OVERLAY_ABSBOX_BIT) ) - { - NDebugOverlay::Line(m_hinge.worldPosition, m_hinge.worldPosition + 48 * m_hinge.worldAxisDirection, 0, 255, 0, false, 0 ); - } - BaseClass::DrawDebugGeometryOverlays(); - } - - void InputSetVelocity( inputdata_t &inputdata ) - { - if ( !m_pConstraint || !m_pConstraint->GetReferenceObject() || !m_pConstraint->GetAttachedObject() ) - return; - - float speed = inputdata.value.Float(); - float massLoad = 1; - int numMasses = 0; - if ( m_pConstraint->GetReferenceObject()->IsMoveable() ) - { - massLoad = m_pConstraint->GetReferenceObject()->GetInertia().Length(); - numMasses++; - m_pConstraint->GetReferenceObject()->Wake(); - } - if ( m_pConstraint->GetAttachedObject()->IsMoveable() ) - { - massLoad += m_pConstraint->GetAttachedObject()->GetInertia().Length(); - numMasses++; - m_pConstraint->GetAttachedObject()->Wake(); - } - if ( numMasses > 0 ) - { - massLoad /= (float)numMasses; - } - - float loadscale = m_systemLoadScale != 0 ? m_systemLoadScale : 1; - m_pConstraint->SetAngularMotor( speed, speed * loadscale * massLoad * loadscale * (1.0/TICK_INTERVAL) ); - } - - void InputSetHingeFriction( inputdata_t &inputdata ) - { - m_hingeFriction = inputdata.value.Float(); - Msg("Setting hinge friction to %f\n", m_hingeFriction ); - m_hinge.hingeAxis.SetAxisFriction( 0, 0, m_hingeFriction * 1000 ); - } - - virtual void Deactivate() - { - if ( HasSpawnFlags( SF_CONSTRAINT_ASSUME_WORLD_GEOMETRY ) ) - { - if ( m_pConstraint && m_pConstraint->GetAttachedObject() ) - { - // NOTE: RemoveHinged() is always safe - m_pConstraint->GetAttachedObject()->RemoveHinged(); - } - } - - BaseClass::Deactivate(); - } - - void NotifyVPhysicsStateChanged( IPhysicsObject *pPhysics, CBaseEntity *pEntity, bool bAwake ) - { -#if HINGE_NOTIFY - Assert(m_pConstraint); - if (!m_pConstraint) - return; - - // if something woke up, start thinking. If everything is asleep, stop thinking. - if ( bAwake ) - { - // Did something wake up when I was not thinking? - if ( GetNextThink() == TICK_NEVER_THINK ) - { - m_soundInfo.StartThinking(this, - VelocitySampler::GetRelativeAngularVelocity(m_pConstraint->GetAttachedObject(), m_pConstraint->GetReferenceObject()) , - m_hinge.worldAxisDirection - ); - - SetThink(&CPhysHinge::SoundThink); - SetNextThink(gpGlobals->curtime + m_soundInfo.getThinkRate()); - } - } - else - { - // Is everything asleep? If so, stop thinking. - if ( GetNextThink() != TICK_NEVER_THINK && - m_pConstraint->GetAttachedObject()->IsAsleep() && - m_pConstraint->GetReferenceObject()->IsAsleep() ) - { - m_soundInfo.StopThinking(this); - SetNextThink(TICK_NEVER_THINK); - } - } -#endif - } - - -#if HINGE_NOTIFY - virtual void OnConstraintSetup( hl_constraint_info_t &info ) - { - CBaseEntity *pEntity0 = info.pObjects[0] ? static_cast(info.pObjects[0]->GetGameData()) : NULL; - if ( pEntity0 && !info.pObjects[0]->IsStatic() ) - { - WatchVPhysicsStateChanges( this, pEntity0 ); - } - CBaseEntity *pEntity1 = info.pObjects[1] ? static_cast(info.pObjects[1]->GetGameData()) : NULL; - if ( pEntity1 && !info.pObjects[1]->IsStatic() ) - { - WatchVPhysicsStateChanges( this, pEntity1 ); - } - BaseClass::OnConstraintSetup(info); - } - - void SoundThink( void ); - // void Spawn( void ); - void Activate( void ); - void Precache( void ); -#endif - - DECLARE_DATADESC(); - - -#if HINGE_NOTIFY -protected: - ConstraintSoundInfo m_soundInfo; -#endif - -private: - constraint_hingeparams_t m_hinge; - float m_hingeFriction; - float m_systemLoadScale; - bool IsWorldHinge( const hl_constraint_info_t &info, int *pAxisOut ); -}; - -BEGIN_DATADESC( CPhysHinge ) - -// Quiet down classcheck -// DEFINE_FIELD( m_hinge, FIELD_??? ), - - DEFINE_KEYFIELD( m_hingeFriction, FIELD_FLOAT, "hingefriction" ), - DEFINE_FIELD( m_hinge.worldPosition, FIELD_POSITION_VECTOR ), - DEFINE_KEYFIELD( m_hinge.worldAxisDirection, FIELD_VECTOR, "hingeaxis" ), - DEFINE_KEYFIELD( m_systemLoadScale, FIELD_FLOAT, "systemloadscale" ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetAngularVelocity", InputSetVelocity ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetHingeFriction", InputSetHingeFriction ), - -#if HINGE_NOTIFY - DEFINE_KEYFIELD( m_soundInfo.m_soundProfile.m_keyPoints[SimpleConstraintSoundProfile::kMIN_THRESHOLD] , FIELD_FLOAT, "minSoundThreshold" ), - DEFINE_KEYFIELD( m_soundInfo.m_soundProfile.m_keyPoints[SimpleConstraintSoundProfile::kMIN_FULL] , FIELD_FLOAT, "maxSoundThreshold" ), - DEFINE_KEYFIELD( m_soundInfo.m_iszTravelSoundFwd, FIELD_SOUNDNAME, "slidesoundfwd" ), - DEFINE_KEYFIELD( m_soundInfo.m_iszTravelSoundBack, FIELD_SOUNDNAME, "slidesoundback" ), - - DEFINE_KEYFIELD( m_soundInfo.m_iszReversalSounds[0], FIELD_SOUNDNAME, "reversalsoundSmall" ), - DEFINE_KEYFIELD( m_soundInfo.m_iszReversalSounds[1], FIELD_SOUNDNAME, "reversalsoundMedium" ), - DEFINE_KEYFIELD( m_soundInfo.m_iszReversalSounds[2], FIELD_SOUNDNAME, "reversalsoundLarge" ), - - DEFINE_KEYFIELD( m_soundInfo.m_soundProfile.m_reversalSoundThresholds[0] , FIELD_FLOAT, "reversalsoundthresholdSmall" ), - DEFINE_KEYFIELD( m_soundInfo.m_soundProfile.m_reversalSoundThresholds[1], FIELD_FLOAT, "reversalsoundthresholdMedium" ), - DEFINE_KEYFIELD( m_soundInfo.m_soundProfile.m_reversalSoundThresholds[2] , FIELD_FLOAT, "reversalsoundthresholdLarge" ), - - DEFINE_THINKFUNC( SoundThink ), -#endif - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( phys_hinge, CPhysHinge ); - - -void CPhysHinge::Spawn( void ) -{ - m_hinge.worldPosition = GetLocalOrigin(); - m_hinge.worldAxisDirection -= GetLocalOrigin(); - VectorNormalize(m_hinge.worldAxisDirection); - UTIL_SnapDirectionToAxis( m_hinge.worldAxisDirection ); - - m_hinge.hingeAxis.SetAxisFriction( 0, 0, 0 ); - - if ( HasSpawnFlags( SF_CONSTRAINT_ASSUME_WORLD_GEOMETRY ) ) - { - masscenteroverride_t params; - if ( m_nameAttach1 == NULL_STRING ) - { - params.SnapToAxis( m_nameAttach2, m_hinge.worldPosition, m_hinge.worldAxisDirection ); - PhysSetMassCenterOverride( params ); - } - else if ( m_nameAttach2 == NULL_STRING ) - { - params.SnapToAxis( m_nameAttach1, m_hinge.worldPosition, m_hinge.worldAxisDirection ); - PhysSetMassCenterOverride( params ); - } - else - { - RemoveSpawnFlags( SF_CONSTRAINT_ASSUME_WORLD_GEOMETRY ); - } - } - - Precache(); -} - -#if HINGE_NOTIFY -void CPhysHinge::Activate( void ) -{ - BaseClass::Activate(); - - m_soundInfo.OnActivate(this); - if (m_pConstraint) - { - m_soundInfo.StartThinking(this, - VelocitySampler::GetRelativeAngularVelocity(m_pConstraint->GetAttachedObject(), m_pConstraint->GetReferenceObject()) , - m_hinge.worldAxisDirection - ); - - SetThink(&CPhysHinge::SoundThink); - SetNextThink( gpGlobals->curtime + m_soundInfo.getThinkRate() ); - } -} - -void CPhysHinge::Precache( void ) -{ - BaseClass::Precache(); - return m_soundInfo.OnPrecache(this); -} - -#endif - - -static int GetUnitAxisIndex( const Vector &axis ) -{ - bool valid = false; - int index = -1; - - for ( int i = 0; i < 3; i++ ) - { - if ( axis[i] != 0 ) - { - if ( fabs(axis[i]) == 1 ) - { - if ( index < 0 ) - { - index = i; - valid = true; - continue; - } - } - valid = false; - } - } - return valid ? index : -1; -} - -bool CPhysHinge::IsWorldHinge( const hl_constraint_info_t &info, int *pAxisOut ) -{ - if ( HasSpawnFlags( SF_CONSTRAINT_ASSUME_WORLD_GEOMETRY ) && info.pObjects[0] == g_PhysWorldObject ) - { - Vector localHinge; - info.pObjects[1]->WorldToLocalVector( &localHinge, m_hinge.worldAxisDirection ); - UTIL_SnapDirectionToAxis( localHinge ); - int hingeAxis = GetUnitAxisIndex( localHinge ); - if ( hingeAxis >= 0 ) - { - *pAxisOut = hingeAxis; - return true; - } - } - return false; -} - - -#if HINGE_NOTIFY -void CPhysHinge::SoundThink( void ) -{ - Assert(m_pConstraint); - if (!m_pConstraint) - return; - - IPhysicsObject * pAttached = m_pConstraint->GetAttachedObject(), *pReference = m_pConstraint->GetReferenceObject(); - Assert( pAttached && pReference ); - if (pAttached && pReference) - { - Vector relativeVel = VelocitySampler::GetRelativeAngularVelocity(pAttached,pReference); - if (g_debug_constraint_sounds.GetBool()) - { - NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() + (relativeVel), 255, 255, 0, true, 0.1f ); - } - m_soundInfo.OnThink( this, relativeVel ); - - SetNextThink(gpGlobals->curtime + m_soundInfo.getThinkRate()); - } -} -#endif - -class CPhysBallSocket : public CPhysConstraint -{ -public: - DECLARE_CLASS( CPhysBallSocket, CPhysConstraint ); - - IPhysicsConstraint *CreateConstraint( IPhysicsConstraintGroup *pGroup, const hl_constraint_info_t &info ) - { - constraint_ballsocketparams_t ballsocket; - - ballsocket.Defaults(); - - for ( int i = 0; i < 2; i++ ) - { - info.pObjects[i]->WorldToLocal( &ballsocket.constraintPosition[i], GetAbsOrigin() ); - } - GetBreakParams( ballsocket.constraint, info ); - ballsocket.constraint.torqueLimit = 0; - - return physenv->CreateBallsocketConstraint( info.pObjects[0], info.pObjects[1], pGroup, ballsocket ); - } -}; - -LINK_ENTITY_TO_CLASS( phys_ballsocket, CPhysBallSocket ); - -class CPhysSlideConstraint : public CPhysConstraint, public IVPhysicsWatcher -{ -public: - DECLARE_CLASS( CPhysSlideConstraint, CPhysConstraint ); - - DECLARE_DATADESC(); - IPhysicsConstraint *CreateConstraint( IPhysicsConstraintGroup *pGroup, const hl_constraint_info_t &info ); - void InputSetVelocity( inputdata_t &inputdata ) - { - if ( !m_pConstraint || !m_pConstraint->GetReferenceObject() || !m_pConstraint->GetAttachedObject() ) - return; - - float speed = inputdata.value.Float(); - float massLoad = 1; - int numMasses = 0; - if ( m_pConstraint->GetReferenceObject()->IsMoveable() ) - { - massLoad = m_pConstraint->GetReferenceObject()->GetMass(); - numMasses++; - m_pConstraint->GetReferenceObject()->Wake(); - } - if ( m_pConstraint->GetAttachedObject()->IsMoveable() ) - { - massLoad += m_pConstraint->GetAttachedObject()->GetMass(); - numMasses++; - m_pConstraint->GetAttachedObject()->Wake(); - } - if ( numMasses > 0 ) - { - massLoad /= (float)numMasses; - } - float loadscale = m_systemLoadScale != 0 ? m_systemLoadScale : 1; - m_pConstraint->SetLinearMotor( speed, speed * loadscale * massLoad * (1.0/TICK_INTERVAL) ); - } - - void DrawDebugGeometryOverlays() - { - if ( m_debugOverlays & (OVERLAY_BBOX_BIT|OVERLAY_PIVOT_BIT|OVERLAY_ABSBOX_BIT) ) - { - NDebugOverlay::Box( GetAbsOrigin(), -Vector(8,8,8), Vector(8,8,8), 0, 255, 0, 0, 0 ); - NDebugOverlay::Box( m_axisEnd, -Vector(4,4,4), Vector(4,4,4), 0, 0, 255, 0, 0 ); - NDebugOverlay::Line( GetAbsOrigin(), m_axisEnd, 255, 255, 0, false, 0 ); - } - BaseClass::DrawDebugGeometryOverlays(); - } - - void NotifyVPhysicsStateChanged( IPhysicsObject *pPhysics, CBaseEntity *pEntity, bool bAwake ) - { -#if HINGE_NOTIFY - Assert(m_pConstraint); - if (!m_pConstraint) - return; - - // if something woke up, start thinking. If everything is asleep, stop thinking. - if ( bAwake ) - { - // Did something wake up when I was not thinking? - if ( GetNextThink() == TICK_NEVER_THINK ) - { - Vector axisDirection = m_axisEnd - GetAbsOrigin(); - VectorNormalize( axisDirection ); - UTIL_SnapDirectionToAxis( axisDirection ); - - m_soundInfo.StartThinking(this, - VelocitySampler::GetRelativeVelocity(m_pConstraint->GetAttachedObject(), m_pConstraint->GetReferenceObject()), - axisDirection - ); - SetThink(&CPhysSlideConstraint::SoundThink); - SetNextThink(gpGlobals->curtime + m_soundInfo.getThinkRate()); - } - } - else - { - // Is everything asleep? If so, stop thinking. - if ( GetNextThink() != TICK_NEVER_THINK && - m_pConstraint->GetAttachedObject()->IsAsleep() && - m_pConstraint->GetReferenceObject()->IsAsleep() ) - { - m_soundInfo.StopThinking(this); - SetNextThink(TICK_NEVER_THINK); - } - } -#endif - } - - -#if HINGE_NOTIFY - virtual void OnConstraintSetup( hl_constraint_info_t &info ) - { - CBaseEntity *pEntity0 = info.pObjects[0] ? static_cast(info.pObjects[0]->GetGameData()) : NULL; - if ( pEntity0 && !info.pObjects[0]->IsStatic() ) - { - WatchVPhysicsStateChanges( this, pEntity0 ); - } - CBaseEntity *pEntity1 = info.pObjects[1] ? static_cast(info.pObjects[1]->GetGameData()) : NULL; - if ( pEntity1 && !info.pObjects[1]->IsStatic() ) - { - WatchVPhysicsStateChanges( this, pEntity1 ); - } - BaseClass::OnConstraintSetup(info); - } - - - void SoundThink( void ); - // void Spawn( void ); - void Activate( void ); - void Precache( void ); -#endif - - Vector m_axisEnd; - float m_slideFriction; - float m_systemLoadScale; - -#if HINGE_NOTIFY -protected: - ConstraintSoundInfo m_soundInfo; -#endif -}; - -LINK_ENTITY_TO_CLASS( phys_slideconstraint, CPhysSlideConstraint ); - -BEGIN_DATADESC( CPhysSlideConstraint ) - - DEFINE_KEYFIELD( m_axisEnd, FIELD_POSITION_VECTOR, "slideaxis" ), - DEFINE_KEYFIELD( m_slideFriction, FIELD_FLOAT, "slidefriction" ), - DEFINE_KEYFIELD( m_systemLoadScale, FIELD_FLOAT, "systemloadscale" ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetVelocity", InputSetVelocity ), -#if HINGE_NOTIFY - DEFINE_KEYFIELD( m_soundInfo.m_soundProfile.m_keyPoints[SimpleConstraintSoundProfile::kMIN_THRESHOLD] , FIELD_FLOAT, "minSoundThreshold" ), - DEFINE_KEYFIELD( m_soundInfo.m_soundProfile.m_keyPoints[SimpleConstraintSoundProfile::kMIN_FULL] , FIELD_FLOAT, "maxSoundThreshold" ), - DEFINE_KEYFIELD( m_soundInfo.m_iszTravelSoundFwd, FIELD_SOUNDNAME, "slidesoundfwd" ), - DEFINE_KEYFIELD( m_soundInfo.m_iszTravelSoundBack, FIELD_SOUNDNAME, "slidesoundback" ), - - DEFINE_KEYFIELD( m_soundInfo.m_iszReversalSounds[0], FIELD_SOUNDNAME, "reversalsoundSmall" ), - DEFINE_KEYFIELD( m_soundInfo.m_iszReversalSounds[1], FIELD_SOUNDNAME, "reversalsoundMedium" ), - DEFINE_KEYFIELD( m_soundInfo.m_iszReversalSounds[2], FIELD_SOUNDNAME, "reversalsoundLarge" ), - - DEFINE_KEYFIELD( m_soundInfo.m_soundProfile.m_reversalSoundThresholds[0] , FIELD_FLOAT, "reversalsoundthresholdSmall" ), - DEFINE_KEYFIELD( m_soundInfo.m_soundProfile.m_reversalSoundThresholds[1], FIELD_FLOAT, "reversalsoundthresholdMedium" ), - DEFINE_KEYFIELD( m_soundInfo.m_soundProfile.m_reversalSoundThresholds[2] , FIELD_FLOAT, "reversalsoundthresholdLarge" ), - - - DEFINE_THINKFUNC( SoundThink ), -#endif - -END_DATADESC() - - - -IPhysicsConstraint *CPhysSlideConstraint::CreateConstraint( IPhysicsConstraintGroup *pGroup, const hl_constraint_info_t &info ) -{ - constraint_slidingparams_t sliding; - sliding.Defaults(); - GetBreakParams( sliding.constraint, info ); - sliding.constraint.strength = 1.0; - - Vector axisDirection = m_axisEnd - GetAbsOrigin(); - VectorNormalize( axisDirection ); - UTIL_SnapDirectionToAxis( axisDirection ); - - sliding.InitWithCurrentObjectState( info.pObjects[0], info.pObjects[1], axisDirection ); - sliding.friction = m_slideFriction; - if ( m_spawnflags & SF_SLIDE_LIMIT_ENDS ) - { - Vector position; - info.pObjects[1]->GetPosition( &position, NULL ); - - sliding.limitMin = DotProduct( axisDirection, GetAbsOrigin() ); - sliding.limitMax = DotProduct( axisDirection, m_axisEnd ); - if ( sliding.limitMax < sliding.limitMin ) - { - swap( sliding.limitMin, sliding.limitMax ); - } - - // expand limits to make initial position of the attached object valid - float limit = DotProduct( position, axisDirection ); - if ( limit < sliding.limitMin ) - { - sliding.limitMin = limit; - } - else if ( limit > sliding.limitMax ) - { - sliding.limitMax = limit; - } - // offset so that the current position is 0 - sliding.limitMin -= limit; - sliding.limitMax -= limit; - } - - return physenv->CreateSlidingConstraint( info.pObjects[0], info.pObjects[1], pGroup, sliding ); -} - - -#if HINGE_NOTIFY -void CPhysSlideConstraint::SoundThink( void ) -{ - Assert(m_pConstraint); - if (!m_pConstraint) - return; - - IPhysicsObject * pAttached = m_pConstraint->GetAttachedObject(), *pReference = m_pConstraint->GetReferenceObject(); - Assert( pAttached && pReference ); - if (pAttached && pReference) - { - Vector relativeVel = VelocitySampler::GetRelativeVelocity(pAttached,pReference); - // project velocity onto my primary axis.: - - Vector axisDirection = m_axisEnd - GetAbsOrigin(); - relativeVel = m_axisEnd * relativeVel.Dot(m_axisEnd)/m_axisEnd.Dot(m_axisEnd); - - m_soundInfo.OnThink( this, relativeVel ); - - SetNextThink(gpGlobals->curtime + m_soundInfo.getThinkRate()); - } - -} - -void CPhysSlideConstraint::Activate( void ) -{ - BaseClass::Activate(); - - m_soundInfo.OnActivate(this); - - Vector axisDirection = m_axisEnd - GetAbsOrigin(); - VectorNormalize( axisDirection ); - UTIL_SnapDirectionToAxis( axisDirection ); - m_soundInfo.StartThinking(this, - VelocitySampler::GetRelativeVelocity(m_pConstraint->GetAttachedObject(), m_pConstraint->GetReferenceObject()), - axisDirection - ); - - SetThink(&CPhysSlideConstraint::SoundThink); - SetNextThink(gpGlobals->curtime + m_soundInfo.getThinkRate()); -} - -void CPhysSlideConstraint::Precache() -{ - m_soundInfo.OnPrecache(this); -} - -#endif - - -//----------------------------------------------------------------------------- -// Purpose: Fixed breakable constraint -//----------------------------------------------------------------------------- -class CPhysFixed : public CPhysConstraint -{ - DECLARE_CLASS( CPhysFixed, CPhysConstraint ); -public: - IPhysicsConstraint *CreateConstraint( IPhysicsConstraintGroup *pGroup, const hl_constraint_info_t &info ); - - // just for debugging - move to the position of the reference entity - void MoveToRefPosition() - { - if ( m_pConstraint ) - { - matrix3x4_t xformRef; - m_pConstraint->GetConstraintTransform( &xformRef, NULL ); - IPhysicsObject *pObj = m_pConstraint->GetReferenceObject(); - if ( pObj && pObj->IsMoveable() ) - { - Vector pos, posWorld; - MatrixPosition( xformRef, pos ); - pObj->LocalToWorld(&posWorld, pos); - SetAbsOrigin(posWorld); - } - } - } - int DrawDebugTextOverlays() - { - if ( m_debugOverlays & OVERLAY_TEXT_BIT ) - { - MoveToRefPosition(); - } - return BaseClass::DrawDebugTextOverlays(); - } - void DrawDebugGeometryOverlays() - { - if ( m_debugOverlays & (OVERLAY_BBOX_BIT|OVERLAY_PIVOT_BIT|OVERLAY_ABSBOX_BIT) ) - { - MoveToRefPosition(); - } - BaseClass::DrawDebugGeometryOverlays(); - } -}; - -LINK_ENTITY_TO_CLASS( phys_constraint, CPhysFixed ); - -//----------------------------------------------------------------------------- -// Purpose: Activate/create the constraint -//----------------------------------------------------------------------------- -IPhysicsConstraint *CPhysFixed::CreateConstraint( IPhysicsConstraintGroup *pGroup, const hl_constraint_info_t &info ) -{ - constraint_fixedparams_t fixed; - fixed.Defaults(); - fixed.InitWithCurrentObjectState( info.pObjects[0], info.pObjects[1] ); - GetBreakParams( fixed.constraint, info ); - - // constraining to the world means object 1 is fixed - if ( info.pObjects[0] == g_PhysWorldObject ) - { - PhysSetGameFlags( info.pObjects[1], FVPHYSICS_CONSTRAINT_STATIC ); - } - - return physenv->CreateFixedConstraint( info.pObjects[0], info.pObjects[1], pGroup, fixed ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Breakable pulley w/ropes constraint -//----------------------------------------------------------------------------- -class CPhysPulley : public CPhysConstraint -{ - DECLARE_CLASS( CPhysPulley, CPhysConstraint ); -public: - DECLARE_DATADESC(); - - void DrawDebugGeometryOverlays() - { - if ( m_debugOverlays & (OVERLAY_BBOX_BIT|OVERLAY_PIVOT_BIT|OVERLAY_ABSBOX_BIT) ) - { - Vector origin = GetAbsOrigin(); - Vector refPos = origin, attachPos = origin; - IPhysicsObject *pRef = m_pConstraint->GetReferenceObject(); - if ( pRef ) - { - matrix3x4_t matrix; - pRef->GetPositionMatrix( &matrix ); - VectorTransform( m_offset[0], matrix, refPos ); - } - IPhysicsObject *pAttach = m_pConstraint->GetAttachedObject(); - if ( pAttach ) - { - matrix3x4_t matrix; - pAttach->GetPositionMatrix( &matrix ); - VectorTransform( m_offset[1], matrix, attachPos ); - } - NDebugOverlay::Line( refPos, origin, 0, 255, 0, false, 0 ); - NDebugOverlay::Line( origin, m_position2, 128, 128, 128, false, 0 ); - NDebugOverlay::Line( m_position2, attachPos, 0, 255, 0, false, 0 ); - NDebugOverlay::Box( origin, -Vector(8,8,8), Vector(8,8,8), 128, 255, 128, 32, 0 ); - NDebugOverlay::Box( m_position2, -Vector(8,8,8), Vector(8,8,8), 255, 128, 128, 32, 0 ); - } - BaseClass::DrawDebugGeometryOverlays(); - } - - IPhysicsConstraint *CreateConstraint( IPhysicsConstraintGroup *pGroup, const hl_constraint_info_t &info ); - -private: - Vector m_position2; - Vector m_offset[2]; - float m_addLength; - float m_gearRatio; -}; - -BEGIN_DATADESC( CPhysPulley ) - - DEFINE_KEYFIELD( m_position2, FIELD_POSITION_VECTOR, "position2" ), - DEFINE_AUTO_ARRAY( m_offset, FIELD_VECTOR ), - DEFINE_KEYFIELD( m_addLength, FIELD_FLOAT, "addlength" ), - DEFINE_KEYFIELD( m_gearRatio, FIELD_FLOAT, "gearratio" ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( phys_pulleyconstraint, CPhysPulley ); - - -//----------------------------------------------------------------------------- -// Purpose: Activate/create the constraint -//----------------------------------------------------------------------------- -IPhysicsConstraint *CPhysPulley::CreateConstraint( IPhysicsConstraintGroup *pGroup, const hl_constraint_info_t &info ) -{ - constraint_pulleyparams_t pulley; - pulley.Defaults(); - pulley.pulleyPosition[0] = GetAbsOrigin(); - pulley.pulleyPosition[1] = m_position2; - - matrix3x4_t matrix; - Vector world[2]; - - info.pObjects[0]->GetPositionMatrix( &matrix ); - VectorTransform( info.anchorPosition[0], matrix, world[0] ); - info.pObjects[1]->GetPositionMatrix( &matrix ); - VectorTransform( info.anchorPosition[1], matrix, world[1] ); - - for ( int i = 0; i < 2; i++ ) - { - pulley.objectPosition[i] = info.anchorPosition[i]; - m_offset[i] = info.anchorPosition[i]; - } - - pulley.totalLength = m_addLength + - (world[0] - pulley.pulleyPosition[0]).Length() + - ((world[1] - pulley.pulleyPosition[1]).Length() * m_gearRatio); - - if ( m_gearRatio != 0 ) - { - pulley.gearRatio = m_gearRatio; - } - GetBreakParams( pulley.constraint, info ); - if ( m_spawnflags & SF_PULLEY_RIGID ) - { - pulley.isRigid = true; - } - - return physenv->CreatePulleyConstraint( info.pObjects[0], info.pObjects[1], pGroup, pulley ); -} - -//----------------------------------------------------------------------------- -// Purpose: Breakable rope/length constraint -//----------------------------------------------------------------------------- -class CPhysLength : public CPhysConstraint -{ - DECLARE_CLASS( CPhysLength, CPhysConstraint ); -public: - DECLARE_DATADESC(); - - void DrawDebugGeometryOverlays() - { - if ( m_debugOverlays & (OVERLAY_BBOX_BIT|OVERLAY_PIVOT_BIT|OVERLAY_ABSBOX_BIT) ) - { - Vector origin = GetAbsOrigin(); - Vector refPos = origin, attachPos = origin; - IPhysicsObject *pRef = m_pConstraint->GetReferenceObject(); - if ( pRef ) - { - matrix3x4_t matrix; - pRef->GetPositionMatrix( &matrix ); - VectorTransform( m_offset[0], matrix, refPos ); - } - IPhysicsObject *pAttach = m_pConstraint->GetAttachedObject(); - if ( pAttach ) - { - matrix3x4_t matrix; - pAttach->GetPositionMatrix( &matrix ); - VectorTransform( m_offset[1], matrix, attachPos ); - } - Vector dir = attachPos - refPos; - - float len = VectorNormalize(dir); - if ( len > m_totalLength ) - { - Vector mid = refPos + dir * m_totalLength; - NDebugOverlay::Line( refPos, mid, 0, 255, 0, false, 0 ); - NDebugOverlay::Line( mid, attachPos, 255, 0, 0, false, 0 ); - } - else - { - NDebugOverlay::Line( refPos, attachPos, 0, 255, 0, false, 0 ); - } - } - BaseClass::DrawDebugGeometryOverlays(); - } - - IPhysicsConstraint *CreateConstraint( IPhysicsConstraintGroup *pGroup, const hl_constraint_info_t &info ); - -private: - Vector m_offset[2]; - Vector m_vecAttach; - float m_addLength; - float m_minLength; - float m_totalLength; -}; - -BEGIN_DATADESC( CPhysLength ) - - DEFINE_AUTO_ARRAY( m_offset, FIELD_VECTOR ), - DEFINE_KEYFIELD( m_addLength, FIELD_FLOAT, "addlength" ), - DEFINE_KEYFIELD( m_minLength, FIELD_FLOAT, "minlength" ), - DEFINE_KEYFIELD( m_vecAttach, FIELD_POSITION_VECTOR, "attachpoint" ), - DEFINE_FIELD( m_totalLength, FIELD_FLOAT ), -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( phys_lengthconstraint, CPhysLength ); - - -//----------------------------------------------------------------------------- -// Purpose: Activate/create the constraint -//----------------------------------------------------------------------------- -IPhysicsConstraint *CPhysLength::CreateConstraint( IPhysicsConstraintGroup *pGroup, const hl_constraint_info_t &info ) -{ - constraint_lengthparams_t length; - length.Defaults(); - Vector position[2]; - position[0] = GetAbsOrigin(); - position[1] = m_vecAttach; - int index = info.swapped ? 1 : 0; - length.InitWorldspace( info.pObjects[0], info.pObjects[1], position[index], position[!index] ); - length.totalLength += m_addLength; - length.minLength = m_minLength; - m_totalLength = length.totalLength; - if ( HasSpawnFlags(SF_LENGTH_RIGID) ) - { - length.minLength = length.totalLength; - } - - for ( int i = 0; i < 2; i++ ) - { - m_offset[i] = length.objectPosition[i]; - } - GetBreakParams( length.constraint, info ); - - return physenv->CreateLengthConstraint( info.pObjects[0], info.pObjects[1], pGroup, length ); -} - -//----------------------------------------------------------------------------- -// Purpose: Limited ballsocket constraint with toggle-able translation constraints -//----------------------------------------------------------------------------- -class CRagdollConstraint : public CPhysConstraint -{ - DECLARE_CLASS( CRagdollConstraint, CPhysConstraint ); -public: - DECLARE_DATADESC(); -#if 0 - void DrawDebugGeometryOverlays() - { - if ( m_debugOverlays & (OVERLAY_BBOX_BIT|OVERLAY_PIVOT_BIT|OVERLAY_ABSBOX_BIT) ) - { - NDebugOverlay::Line( refPos, attachPos, 0, 255, 0, false, 0 ); - } - BaseClass::DrawDebugGeometryOverlays(); - } -#endif - - IPhysicsConstraint *CreateConstraint( IPhysicsConstraintGroup *pGroup, const hl_constraint_info_t &info ); - -private: - float m_xmin; // constraint limits in degrees - float m_xmax; - float m_ymin; - float m_ymax; - float m_zmin; - float m_zmax; - - float m_xfriction; - float m_yfriction; - float m_zfriction; -}; - -BEGIN_DATADESC( CRagdollConstraint ) - - DEFINE_KEYFIELD( m_xmin, FIELD_FLOAT, "xmin" ), - DEFINE_KEYFIELD( m_xmax, FIELD_FLOAT, "xmax" ), - DEFINE_KEYFIELD( m_ymin, FIELD_FLOAT, "ymin" ), - DEFINE_KEYFIELD( m_ymax, FIELD_FLOAT, "ymax" ), - DEFINE_KEYFIELD( m_zmin, FIELD_FLOAT, "zmin" ), - DEFINE_KEYFIELD( m_zmax, FIELD_FLOAT, "zmax" ), - DEFINE_KEYFIELD( m_xfriction, FIELD_FLOAT, "xfriction" ), - DEFINE_KEYFIELD( m_yfriction, FIELD_FLOAT, "yfriction" ), - DEFINE_KEYFIELD( m_zfriction, FIELD_FLOAT, "zfriction" ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( phys_ragdollconstraint, CRagdollConstraint ); - -//----------------------------------------------------------------------------- -// Purpose: Activate/create the constraint -//----------------------------------------------------------------------------- -IPhysicsConstraint *CRagdollConstraint::CreateConstraint( IPhysicsConstraintGroup *pGroup, const hl_constraint_info_t &info ) -{ - constraint_ragdollparams_t ragdoll; - ragdoll.Defaults(); - - matrix3x4_t entityToWorld, worldToEntity; - info.pObjects[0]->GetPositionMatrix( &entityToWorld ); - MatrixInvert( entityToWorld, worldToEntity ); - ConcatTransforms( worldToEntity, EntityToWorldTransform(), ragdoll.constraintToReference ); - - info.pObjects[1]->GetPositionMatrix( &entityToWorld ); - MatrixInvert( entityToWorld, worldToEntity ); - ConcatTransforms( worldToEntity, EntityToWorldTransform(), ragdoll.constraintToAttached ); - - ragdoll.onlyAngularLimits = HasSpawnFlags( SF_RAGDOLL_FREEMOVEMENT ) ? true : false; - - // FIXME: Why are these friction numbers in different units from what the hinge uses? - ragdoll.axes[0].SetAxisFriction( m_xmin, m_xmax, m_xfriction ); - ragdoll.axes[1].SetAxisFriction( m_ymin, m_ymax, m_yfriction ); - ragdoll.axes[2].SetAxisFriction( m_zmin, m_zmax, m_zfriction ); - - if ( HasSpawnFlags( SF_CONSTRAINT_START_INACTIVE ) ) - { - ragdoll.isActive = false; - } - return physenv->CreateRagdollConstraint( info.pObjects[0], info.pObjects[1], pGroup, ragdoll ); -} - - - -class CPhysConstraintEvents : public IPhysicsConstraintEvent -{ - void ConstraintBroken( IPhysicsConstraint *pConstraint ) - { - CBaseEntity *pEntity = (CBaseEntity *)pConstraint->GetGameData(); - if ( pEntity ) - { - IPhysicsConstraintEvent *pConstraintEvent = dynamic_cast( pEntity ); - //Msg("Constraint broken %s\n", pEntity->GetDebugName() ); - if ( pConstraintEvent ) - { - pConstraintEvent->ConstraintBroken( pConstraint ); - } - else - { - variant_t emptyVariant; - pEntity->AcceptInput( "ConstraintBroken", NULL, NULL, emptyVariant, 0 ); - } - } - } -}; - -static CPhysConstraintEvents constraintevents; -// registered in physics.cpp -IPhysicsConstraintEvent *g_pConstraintEvents = &constraintevents; - - - - - -#if HINGE_NOTIFY -//----------------------------------------------------------------------------- -// Code for sampler -//----------------------------------------------------------------------------- - - -/// Call this in spawn(). (Not a constructor because those are difficult to use in entities.) -void VelocitySampler::Initialize(float samplerate) -{ - m_fIdealSampleRate = samplerate; -} - -// This is an old style approach to reversal sounds, from when there was only one. -#if 0 -bool VelocitySampler::HasReversed(const Vector &relativeVelocity, float thresholdAcceleration) -{ - // first, make sure the velocity has reversed (is more than 90deg off) from last time, or is zero now. - // float rVsq = relativeVelocity.LengthSqr(); - float vDot = relativeVelocity.Dot(m_prevSample); - if (vDot <= 0) // there is a reversal in direction. compute the magnitude of acceleration. - { - // find the scalar projection of the relative acceleration this fame onto the previous frame's - // velocity, and compare that to the threshold. - Vector accel = relativeVelocity - m_prevSample; - - float prevSampleLength = m_prevSample.Length(); - float projection = 0; - // divide through by dt to get the accel per sec - if (prevSampleLength) - { - projection = -(accel.Dot(m_prevSample) / prevSampleLength) / (gpGlobals->curtime - m_fPrevSampleTime); - } - else - { - projection = accel.Length() / (gpGlobals->curtime - m_fPrevSampleTime); - } - - if (g_debug_constraint_sounds.GetBool()) - { - Msg("Reversal accel is %f/%f\n",projection,thresholdAcceleration); - } - return ((projection) > thresholdAcceleration); // the scalar projection is negative because the acceleration is against vel - } - else - { - return false; - } -} -#endif - -/// Looks at the force of reversal and compares it to a ladder of thresholds. -/// Returns the index of the highest threshold exceeded by the reversal velocity. -int VelocitySampler::HasReversed(const Vector &relativeVelocity, const float thresholdAcceleration[], const unsigned short numThresholds) -{ - // first, make sure the velocity has reversed (is more than 90deg off) from last time, or is zero now. - // float rVsq = relativeVelocity.LengthSqr(); - float vDot = relativeVelocity.Dot(m_prevSample); - if (vDot <= 0) // there is a reversal in direction. compute the magnitude of acceleration. - { - // find the scalar projection of the relative acceleration this fame onto the previous frame's - // velocity, and compare that to the threshold. - Vector accel = relativeVelocity - m_prevSample; - - float prevSampleLength = m_prevSample.Length(); - float projection = 0; - // divide through by dt to get the accel per sec - if (prevSampleLength) - { - // the scalar projection is negative because the acceleration is against vel - projection = -(accel.Dot(m_prevSample) / prevSampleLength) / (gpGlobals->curtime - m_fPrevSampleTime); - } - else - { - projection = accel.Length() / (gpGlobals->curtime - m_fPrevSampleTime); - } - - if (g_debug_constraint_sounds.GetBool()) - { - Msg("Reversal accel is %f/%f\n", projection, thresholdAcceleration[0]); - } - - - // now find the threshold crossed. - int retval; - for (retval = numThresholds - 1; retval >= 0 ; --retval) - { - if (projection > thresholdAcceleration[retval]) - break; - } - - return retval; - } - else - { - return -1; - } -} - -/// small helper function used just below (technique copy-pasted from sound.cpp) -inline static bool IsEmpty (const string_t &str) -{ - return (!str || strlen(str.ToCStr()) < 1 ); -} - -void ConstraintSoundInfo::OnActivate( CPhysConstraint *pOuter ) -{ - m_pTravelSound = NULL; - m_vSampler.Initialize( getThinkRate() ); - - - ValidateInternals( pOuter ); - - // make sure sound filenames are not empty - m_bPlayTravelSound = !IsEmpty(m_iszTravelSoundFwd) || !IsEmpty(m_iszTravelSoundBack); - m_bPlayReversalSound = false; - for (int i = 0; i < SimpleConstraintSoundProfile::kREVERSAL_SOUND_ARRAY_SIZE ; ++i) - { - if ( !IsEmpty(m_iszReversalSounds[i]) ) - { - // if there is at least one filled sound field, we should try - // to play reversals - m_bPlayReversalSound = true; - break; - } - } - - - /* - SetThink(&CPhysSlideConstraint::SoundThink); - SetNextThink(gpGlobals->curtime + m_vSampler.getSampleRate()); - */ -} - -/// Maintain consistency of internal datastructures on start -void ConstraintSoundInfo::ValidateInternals( CPhysConstraint *pOuter ) -{ - // Make sure the reversal sound thresholds are strictly increasing. - for (int i = 1 ; i < SimpleConstraintSoundProfile::kREVERSAL_SOUND_ARRAY_SIZE ; ++i) - { - // if decreases from small to medium, promote small to medium and warn. - if (m_soundProfile.m_reversalSoundThresholds[i] < m_soundProfile.m_reversalSoundThresholds[i-1]) - { - Warning("Constraint reversal sounds for %s are out of order!", pOuter->GetDebugName() ); - m_soundProfile.m_reversalSoundThresholds[i] = m_soundProfile.m_reversalSoundThresholds[i-1]; - m_iszReversalSounds[i] = m_iszReversalSounds[i-1]; - } - } -} - -void ConstraintSoundInfo::OnPrecache( CPhysConstraint *pOuter ) -{ - pOuter->PrecacheScriptSound( m_iszTravelSoundFwd.ToCStr() ); - pOuter->PrecacheScriptSound( m_iszTravelSoundBack.ToCStr() ); - for (int i = 0 ; i < SimpleConstraintSoundProfile::kREVERSAL_SOUND_ARRAY_SIZE; ++i ) - { - pOuter->PrecacheScriptSound( m_iszReversalSounds[i].ToCStr() ); - } -} - -void ConstraintSoundInfo::OnThink( CPhysConstraint *pOuter, const Vector &relativeVelocity ) -{ - // have we had a hard reversal? - int playReversal = m_vSampler.HasReversed( relativeVelocity, m_soundProfile.m_reversalSoundThresholds, SimpleConstraintSoundProfile::kREVERSAL_SOUND_ARRAY_SIZE ); - float relativeVelMag = relativeVelocity.Length(); //< magnitude of relative velocity - - CBaseEntity *pChildEntity = static_cast(pOuter->GetPhysConstraint()->GetAttachedObject()->GetGameData()); - - // compute sound level - float soundVol = this->m_soundProfile.GetVolume(relativeVelMag); - - if (g_debug_constraint_sounds.GetBool()) - { - char tempstr[512]; - Q_snprintf(tempstr,sizeof(tempstr),"Velocity: %.3f", relativeVelMag ); - pChildEntity->EntityText( 0, tempstr, m_vSampler.getSampleRate() ); - - Q_snprintf(tempstr,sizeof(tempstr),"Sound volume: %.3f", soundVol ); - pChildEntity->EntityText( 1, tempstr, m_vSampler.getSampleRate() ); - - if (playReversal >= 0) - { - Q_snprintf(tempstr,sizeof(tempstr),"Reversal [%d]", playReversal ); - pChildEntity->EntityText(2,tempstr,m_vSampler.getSampleRate()); - } - } - - // if we loaded a travel sound - if (m_bPlayTravelSound) - { - if (soundVol > 0) - { - // if we want to play a sound... - if ( m_pTravelSound ) - { // if a sound exists, modify it - CSoundEnvelopeController::GetController().SoundChangeVolume( m_pTravelSound, soundVol, 0.1f ); - } - else - { // if a sound does not exist, create it - bool travellingForward = relativeVelocity.Dot(m_forwardAxis) > 0; - - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - CPASAttenuationFilter filter( pChildEntity ); - m_pTravelSound = controller.SoundCreate( filter, pChildEntity->entindex(), - (travellingForward ? m_iszTravelSoundFwd : m_iszTravelSoundBack).ToCStr() ); - controller.Play( m_pTravelSound, soundVol, 100 ); - } - } - else - { - // if we want to not play sound - if ( m_pTravelSound ) - { // and it exists, kill it - CSoundEnvelopeController::GetController().SoundDestroy( m_pTravelSound ); - m_pTravelSound = NULL; - } - } - } - - if (m_bPlayReversalSound && (playReversal >= 0)) - { - pChildEntity->EmitSound(m_iszReversalSounds[playReversal].ToCStr()); - } - - m_vSampler.AddSample( relativeVelocity ); - -} - - -void ConstraintSoundInfo::StartThinking( CPhysConstraint *pOuter, const Vector &relativeVelocity, const Vector &forwardVector ) -{ - m_forwardAxis = forwardVector; - m_vSampler.BeginSampling( relativeVelocity ); - - /* - IPhysicsConstraint *pConstraint = pOuter->GetPhysConstraint(); - Assert(pConstraint); - if (pConstraint) - { - IPhysicsObject * pAttached = pConstraint->GetAttachedObject(), *pReference = pConstraint->GetReferenceObject(); - m_vSampler.BeginSampling( VelocitySampler::GetRelativeVelocity(pAttached,pReference) ); - } - */ -} - -void ConstraintSoundInfo::StopThinking( CPhysConstraint *pOuter ) -{ - DeleteAllSounds(); -} - - -ConstraintSoundInfo::~ConstraintSoundInfo() -{ - DeleteAllSounds(); -} - -// Any sounds envelopes that are active, kill. -void ConstraintSoundInfo::DeleteAllSounds() -{ - if ( m_pTravelSound ) - { - CSoundEnvelopeController::GetController().SoundDestroy( m_pTravelSound ); - m_pTravelSound = NULL; - } -} - -#endif diff --git a/game/server/physconstraint_sounds.h b/game/server/physconstraint_sounds.h deleted file mode 100644 index 138352096..000000000 --- a/game/server/physconstraint_sounds.h +++ /dev/null @@ -1,291 +0,0 @@ -//========= Copyright 1996-2007, Valve Corporation, All rights reserved. ============// -// -// Purpose: Data types used inside constraints for the purpose of playing sounds -// during movement. -// -//=============================================================================// - -#ifndef PHYSCONSTRAINT_SOUNDS_H -#define PHYSCONSTRAINT_SOUNDS_H -#ifdef _WIN32 -#pragma once -#endif - - -#include -#include "soundenvelope.h" - - -/** \brief Class to store a sampled history of velocity for an object -- used for certain sound calculations - -Although this contains only one sample for now, it exists as an interface -so as to make simpler the possibility of moving to a ring buffer -implementation in the future. - -The "sample rate" variable is not nominal: it should be used to specify -the ClientThink() interval. - -Be sure to use the beginSampling() function for the first sample, and -addSample() thereafter: this will be relevant and necessary for a ring -buffer implementation (which will have to perform certain initialization). -*/ -class VelocitySampler -{ -public: - /* - enum - { - HISTORY_DEPTH_LOG = 3, // < log-base-2 of the sampler's array depth - HISTORY_DEPTH = (1 << VELOCITY_SAMPLER_HISTORY_DEPTH_LOG), - }; - */ - - /// Return the internally stored sample rate. - inline float getSampleRate() - { - return m_fIdealSampleRate; - } - - - /// Store off the first recorded sample for the given object. - inline void BeginSampling(const Vector &relativeVelocity); - - /// Record a sample. Do this LAST, after calling hasReversed() et al. - inline void AddSample(const Vector &relativeVelocity); - - /// Using the sample history, determine if the object has reversed direction - /// with at least the given acceleration (in units/sec^2). - int HasReversed(const Vector &relativeVelocity, const float thresholdAcceleration[], const unsigned short numThresholds); - - /// Call this in spawn(). (Not a constructor because those are difficult to use in entities.) - void Initialize(float samplerate); - - - /// A convenience function for extracting the linear velocity of one object relative to another. - inline static Vector GetRelativeVelocity(IPhysicsObject *pObj, IPhysicsObject *pReferenceFrame); - - /// A convenience function for extracting the angular velocity of one object relative to another. - inline static Vector GetRelativeAngularVelocity(IPhysicsObject *pObj, IPhysicsObject *pReferenceFrame); - - -protected: - Vector m_prevSample; - float m_fPrevSampleTime; - - float m_fIdealSampleRate; - -}; - -struct SimpleConstraintSoundProfile -{ - // define the indices of the sound points: - enum - { - kMIN_THRESHOLD, ///< below this no sound is played - kMIN_FULL, ///< at this velocity sound is at its loudest - - kHIGHWATER, ///< high water mark for this enum - } eKeypoints; - - float m_keyPoints[kHIGHWATER]; - - /// Number of entries in the reversal sound array - enum { kREVERSAL_SOUND_ARRAY_SIZE = 3 }; - - /// Acceleration threshold for playing the hard-reverse sound. Divided into sections. - /// Below the 0th threshold no sound will play. - float m_reversalSoundThresholds[kREVERSAL_SOUND_ARRAY_SIZE]; - - /// Get volume for given velocity [0..1] - float GetVolume(float inVel); -}; - -float SimpleConstraintSoundProfile::GetVolume(float inVel) -{ - // clamped lerp on 0-1 - if (inVel <= m_keyPoints[kMIN_THRESHOLD]) - { - return 0; - } - else if (inVel >= m_keyPoints[kMIN_FULL]) - { - return 1; - } - else // lerp... - { - return (inVel - m_keyPoints[kMIN_THRESHOLD])/(m_keyPoints[kMIN_FULL] - m_keyPoints[kMIN_THRESHOLD]); - } -} - -class CPhysConstraint; -/** This class encapsulates the data and behavior necessary for a constraint to play sounds. - - For the moment I have no easy means of populating this from an entity's datadesc. - You should explicitly fill out the fields with eg - - DEFINE_KEYFIELD( m_soundInfo.m_soundProfile.m_keyPoints[SimpleConstraintSoundProfile::kMIN_THRESHOLD] , FIELD_FLOAT, "minSoundThreshold" ), - DEFINE_KEYFIELD( m_soundInfo.m_soundProfile.m_keyPoints[SimpleConstraintSoundProfile::kMIN_FULL] , FIELD_FLOAT, "maxSoundThreshold" ), - DEFINE_KEYFIELD( m_soundInfo.m_iszTravelSoundFwd, FIELD_SOUNDNAME, "slidesoundfwd" ), - DEFINE_KEYFIELD( m_soundInfo.m_iszTravelSoundBack, FIELD_SOUNDNAME, "slidesoundback" ), - DEFINE_KEYFIELD( m_soundInfo.m_iszReversalSound, FIELD_SOUNDNAME, "reversalsound" ), - DEFINE_KEYFIELD( m_soundInfo.m_soundProfile.m_reversalSoundThreshold , FIELD_FLOAT, "reversalsoundthreshold" ), - - */ -class ConstraintSoundInfo -{ -public: - // no ctor. - // dtor - ~ConstraintSoundInfo(); - - /// Call from the constraint's Activate() - void OnActivate( CPhysConstraint *pOuter ); - - /// Constraint should have a think function that calls this. It should pass in relative velocity - /// between child and parent. (This need not be linear velocity; it may be angular.) - void OnThink( CPhysConstraint *pOuter, const Vector &relativeVelocity ); - - /// This is how often the think function should be run: - inline float getThinkRate() const { return 0.09f; } - - /// Call this before the first call to OnThink() - void StartThinking( CPhysConstraint *pOuter, const Vector &relativeVelocity, const Vector &forwardVector ); - - /// Call this if you intend to stop calling OnThink(): - void StopThinking( CPhysConstraint *pOuter ); - - /// Call from owner's Precache(). - void OnPrecache( CPhysConstraint *pOuter ); - - - VelocitySampler m_vSampler; - SimpleConstraintSoundProfile m_soundProfile; - - Vector m_forwardAxis; ///< velocity in this direction is forward. The opposite direction is backward. - - string_t m_iszTravelSoundFwd,m_iszTravelSoundBack; // Path/filename of WAV file to play. - CSoundPatch *m_pTravelSound; - bool m_bPlayTravelSound; - - string_t m_iszReversalSounds[SimpleConstraintSoundProfile::kREVERSAL_SOUND_ARRAY_SIZE]; // Path/filename of WAV files to play -- one per entry in threshold. - // CSoundPatch *m_pReversalSound; - bool m_bPlayReversalSound; - -protected: - /// Maintain consistency of internal datastructures on start - void ValidateInternals( CPhysConstraint *pOuter ); - - /// Stop playing any active sounds. - void DeleteAllSounds(); -}; - - -/////////////// INLINE FUNCTIONS - - -/// compute the relative velocity between an object and its parent. Just a convenience. -Vector VelocitySampler::GetRelativeVelocity( IPhysicsObject *pObj, IPhysicsObject *pReferenceFrame ) -{ - Vector childVelocity, parentVelocity; - pObj->GetImplicitVelocity( &childVelocity, NULL ); - pReferenceFrame->GetImplicitVelocity(&parentVelocity, NULL); - - return (childVelocity - parentVelocity); -} - - -Vector VelocitySampler::GetRelativeAngularVelocity( IPhysicsObject *pObj, IPhysicsObject *pReferenceFrame ) -{ - Assert(pObj); - - if ( pReferenceFrame ) - { - Vector childVelocityLocal, parentVelocityLocal, childVelocityWorld, parentVelocityWorld; - pObj->GetImplicitVelocity( NULL, &childVelocityLocal ); - pObj->LocalToWorldVector( &childVelocityWorld, childVelocityLocal ); - pReferenceFrame->GetImplicitVelocity( NULL, &parentVelocityLocal ); - pObj->LocalToWorldVector( &parentVelocityWorld, parentVelocityLocal ); - - return (childVelocityWorld - parentVelocityWorld); - } - else - { - Vector childVelocityLocal, childVelocityWorld; - pObj->GetImplicitVelocity( NULL, &childVelocityLocal ); - pObj->LocalToWorldVector( &childVelocityWorld, childVelocityLocal ); - - return (childVelocityWorld); - } -} - -/************************************************************************/ -// This function is nominal -- it's here as an interface because in the -// future there will need to be special initialization for the first entry -// in a ring buffer. (I made a test implementation of this, then reverted it -// later; this is not an arbitrary assumption.) -/************************************************************************/ -/// Store off the first recorded sample for the given object. -void VelocitySampler::BeginSampling(const Vector &relativeVelocity) -{ - return AddSample(relativeVelocity); -} - -// Record a sample for the given object -void VelocitySampler::AddSample(const Vector &relativeVelocity) -{ - m_prevSample = relativeVelocity; - m_fPrevSampleTime = gpGlobals->curtime; -} - - - -/* // abandoned -- too complicated, no way to set from keyfields -#pragma warning(push) -#pragma warning( disable:4201 ) // C4201: nonstandard extension used: nameless struct/union -/// Stores information used for playing sounds based on -/// constraint movement -class ConstraintSoundProfile -{ -public: -/// Defines a point in the sound profile: volume and pitch for the sound to play. -/// Implicit crossfading between two sounds. Used to map velocity to a sound profile. -struct SoundInfoTuple -{ -float minVelocity; -union { -struct{ -float volume1,pitch1; //< volume and pitch of sound 1 -float volume2,pitch2; //< volume and pitch of sound 2 -}; -fltx4 m_as4; -}; - -inline SoundInfoTuple(float _minVelocity, float _volume1, float _pitch1, float _volume2, float _pitch2) : -minVelocity(_minVelocity), volume1(_volume1), pitch1(_pitch1), volume2(_volume2), pitch2(_pitch2) -{} -}; - -ConstraintSoundProfile(const SoundInfoTuple *soundTable, unsigned int tableSize) -: m_pSoundInfos(soundTable), m_numSoundInfos(tableSize) -{} - - -protected: - -/// A table of sound info structs -const SoundInfoTuple * const m_pSoundInfos; -/// Size of the table -const unsigned int m_numSoundInfos; -}; - -static ConstraintSoundProfile::SoundInfoTuple CSDebugProfileTable[] = -{ -ConstraintSoundProfile::SoundInfoTuple(12,0,0,0,0), -ConstraintSoundProfile::SoundInfoTuple(24,0,0,0,0), - -}; -#pragma warning(pop) -*/ - - -#endif diff --git a/game/server/physgun.cpp b/game/server/physgun.cpp deleted file mode 100644 index 4af5a59d0..000000000 --- a/game/server/physgun.cpp +++ /dev/null @@ -1,1524 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "beam_shared.h" -#include "player.h" -#include "gamerules.h" -#include "basecombatweapon.h" -#include "baseviewmodel.h" -#include "vphysics/constraints.h" -#include "physics.h" -#include "in_buttons.h" -#include "IEffects.h" -#include "engine/IEngineSound.h" -#include "ndebugoverlay.h" -#include "physics_saverestore.h" -#include "player_pickup.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar phys_gunmass("phys_gunmass", "200"); -ConVar phys_gunvel("phys_gunvel", "400"); -ConVar phys_gunforce("phys_gunforce", "5e5" ); -ConVar phys_guntorque("phys_guntorque", "100" ); -ConVar phys_gunglueradius("phys_gunglueradius", "128" ); - -static int g_physgunBeam; -#define PHYSGUN_BEAM_SPRITE "sprites/physbeam.vmt" - -#define MAX_PELLETS 16 - -class CWeaponGravityGun; - -class CGravityPellet : public CBaseAnimating -{ - DECLARE_CLASS( CGravityPellet, CBaseAnimating ); -public: - DECLARE_DATADESC(); - - ~CGravityPellet(); - void Precache() - { - SetModelName( MAKE_STRING( "models/weapons/glueblob.mdl" ) ); - PrecacheModel( STRING( GetModelName() ) ); - BaseClass::Precache(); - } - void Spawn() - { - Precache(); - SetModel( STRING( GetModelName() ) ); - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NONE ); - AddEffects( EF_NOSHADOW ); - SetRenderColor( 255, 0, 0 ); - m_isInert = false; - } - - bool IsInert() - { - return m_isInert; - } - - bool MakeConstraint( CBaseEntity *pObject ) - { - IPhysicsObject *pReference = g_PhysWorldObject; - if ( GetMoveParent() ) - { - pReference = GetMoveParent()->VPhysicsGetObject(); - } - IPhysicsObject *pAttached = pObject->VPhysicsGetObject(); - if ( !pReference || !pAttached ) - { - return false; - } - - constraint_fixedparams_t fixed; - fixed.Defaults(); - fixed.InitWithCurrentObjectState( pReference, pAttached ); - - m_pConstraint = physenv->CreateFixedConstraint( pReference, pAttached, NULL, fixed ); - m_pConstraint->SetGameData( (void *)this ); - - MakeInert(); - return true; - } - - void MakeInert() - { - SetRenderColor( 64, 64, 128 ); - m_isInert = true; - } - - void InputOnBreak( inputdata_t &inputdata ) - { - UTIL_Remove(this); - } - - IPhysicsConstraint *m_pConstraint; - bool m_isInert; -}; - -LINK_ENTITY_TO_CLASS(gravity_pellet, CGravityPellet); -PRECACHE_REGISTER(gravity_pellet); - -BEGIN_DATADESC( CGravityPellet ) - - DEFINE_PHYSPTR( m_pConstraint ), - DEFINE_FIELD( m_isInert, FIELD_BOOLEAN ), - // physics system will fire this input if the constraint breaks due to physics - DEFINE_INPUTFUNC( FIELD_VOID, "ConstraintBroken", InputOnBreak ), - -END_DATADESC() - - -CGravityPellet::~CGravityPellet() -{ - if ( m_pConstraint ) - { - physenv->DestroyConstraint( m_pConstraint ); - } -} - -class CGravControllerPoint : public IMotionEvent -{ - DECLARE_SIMPLE_DATADESC(); - -public: - CGravControllerPoint( void ); - ~CGravControllerPoint( void ); - void AttachEntity( CBaseEntity *pEntity, IPhysicsObject *pPhys, const Vector &position ); - void DetachEntity( void ); - void SetMaxVelocity( float maxVel ) - { - m_maxVel = maxVel; - } - void SetTargetPosition( const Vector &target ) - { - m_targetPosition = target; - if ( m_attachedEntity == NULL ) - { - m_worldPosition = target; - } - m_timeToArrive = gpGlobals->frametime; - } - - void SetAutoAlign( const Vector &localDir, const Vector &localPos, const Vector &worldAlignDir, const Vector &worldAlignPos ) - { - m_align = true; - m_localAlignNormal = -localDir; - m_localAlignPosition = localPos; - m_targetAlignNormal = worldAlignDir; - m_targetAlignPosition = worldAlignPos; - } - - void ClearAutoAlign() - { - m_align = false; - } - - IMotionEvent::simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ); - Vector m_localPosition; - Vector m_targetPosition; - Vector m_worldPosition; - Vector m_localAlignNormal; - Vector m_localAlignPosition; - Vector m_targetAlignNormal; - Vector m_targetAlignPosition; - bool m_align; - float m_saveDamping; - float m_maxVel; - float m_maxAcceleration; - Vector m_maxAngularAcceleration; - EHANDLE m_attachedEntity; - QAngle m_targetRotation; - float m_timeToArrive; - - IPhysicsMotionController *m_controller; -}; - - -BEGIN_SIMPLE_DATADESC( CGravControllerPoint ) - - DEFINE_FIELD( m_localPosition, FIELD_VECTOR ), - DEFINE_FIELD( m_targetPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_worldPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_localAlignNormal, FIELD_VECTOR ), - DEFINE_FIELD( m_localAlignPosition, FIELD_VECTOR ), - DEFINE_FIELD( m_targetAlignNormal, FIELD_VECTOR ), - DEFINE_FIELD( m_targetAlignPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_align, FIELD_BOOLEAN ), - DEFINE_FIELD( m_saveDamping, FIELD_FLOAT ), - DEFINE_FIELD( m_maxVel, FIELD_FLOAT ), - DEFINE_FIELD( m_maxAcceleration, FIELD_FLOAT ), - DEFINE_FIELD( m_maxAngularAcceleration, FIELD_VECTOR ), - DEFINE_FIELD( m_attachedEntity, FIELD_EHANDLE ), - DEFINE_FIELD( m_targetRotation, FIELD_VECTOR ), - DEFINE_FIELD( m_timeToArrive, FIELD_FLOAT ), - - // Physptrs can't be saved in embedded classes... this is to silence classcheck - // DEFINE_PHYSPTR( m_controller ), - -END_DATADESC() - - -CGravControllerPoint::CGravControllerPoint( void ) -{ - m_attachedEntity = NULL; -} - -CGravControllerPoint::~CGravControllerPoint( void ) -{ - DetachEntity(); -} - - -void CGravControllerPoint::AttachEntity( CBaseEntity *pEntity, IPhysicsObject *pPhys, const Vector &position ) -{ - m_attachedEntity = pEntity; - pPhys->WorldToLocal( &m_localPosition, position ); - m_worldPosition = position; - pPhys->GetDamping( NULL, &m_saveDamping ); - float damping = 2; - pPhys->SetDamping( NULL, &damping ); - m_controller = physenv->CreateMotionController( this ); - m_controller->AttachObject( pPhys, true ); - m_controller->SetPriority( IPhysicsMotionController::HIGH_PRIORITY ); - SetTargetPosition( position ); - m_maxAcceleration = phys_gunforce.GetFloat() * pPhys->GetInvMass(); - m_targetRotation = pEntity->GetAbsAngles(); - float torque = phys_guntorque.GetFloat(); - m_maxAngularAcceleration = torque * pPhys->GetInvInertia(); -} - -void CGravControllerPoint::DetachEntity( void ) -{ - CBaseEntity *pEntity = m_attachedEntity; - if ( pEntity ) - { - IPhysicsObject *pPhys = pEntity->VPhysicsGetObject(); - if ( pPhys ) - { - // on the odd chance that it's gone to sleep while under anti-gravity - pPhys->Wake(); - pPhys->SetDamping( NULL, &m_saveDamping ); - } - } - m_attachedEntity = NULL; - physenv->DestroyMotionController( m_controller ); - m_controller = NULL; - - // UNDONE: Does this help the networking? - m_targetPosition = vec3_origin; - m_worldPosition = vec3_origin; -} - -void AxisAngleQAngle( const Vector &axis, float angle, QAngle &outAngles ) -{ - // map back to HL rotation axes - outAngles.z = axis.x * angle; - outAngles.x = axis.y * angle; - outAngles.y = axis.z * angle; -} - -IMotionEvent::simresult_e CGravControllerPoint::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) -{ - Vector vel; - AngularImpulse angVel; - - float fracRemainingSimTime = 1.0; - if ( m_timeToArrive > 0 ) - { - fracRemainingSimTime *= deltaTime / m_timeToArrive; - if ( fracRemainingSimTime > 1 ) - { - fracRemainingSimTime = 1; - } - } - - m_timeToArrive -= deltaTime; - if ( m_timeToArrive < 0 ) - { - m_timeToArrive = 0; - } - - float invDeltaTime = (1.0f / deltaTime); - Vector world; - pObject->LocalToWorld( &world, m_localPosition ); - m_worldPosition = world; - pObject->GetVelocity( &vel, &angVel ); - //pObject->GetVelocityAtPoint( world, &vel ); - float damping = 1.0; - world += vel * deltaTime * damping; - Vector delta = (m_targetPosition - world) * fracRemainingSimTime * invDeltaTime; - Vector alignDir; - linear = vec3_origin; - angular = vec3_origin; - - if ( m_align ) - { - QAngle angles; - Vector origin; - Vector axis; - AngularImpulse torque; - - pObject->GetShadowPosition( &origin, &angles ); - // align local normal to target normal - VMatrix tmp = SetupMatrixOrgAngles( origin, angles ); - Vector worldNormal = tmp.VMul3x3( m_localAlignNormal ); - axis = CrossProduct( worldNormal, m_targetAlignNormal ); - float trig = VectorNormalize(axis); - float alignRotation = RAD2DEG(asin(trig)); - axis *= alignRotation; - if ( alignRotation < 10 ) - { - float dot = DotProduct( worldNormal, m_targetAlignNormal ); - // probably 180 degrees off - if ( dot < 0 ) - { - if ( worldNormal.x < 0.5 ) - { - axis.Init(10,0,0); - } - else - { - axis.Init(0,0,10); - } - alignRotation = 10; - } - } - - // Solve for the rotation around the target normal (at the local align pos) that will - // move the grabbed spot to the destination. - Vector worldRotCenter = tmp.VMul4x3( m_localAlignPosition ); - Vector rotSrc = world - worldRotCenter; - Vector rotDest = m_targetPosition - worldRotCenter; - - // Get a basis in the plane perpendicular to m_targetAlignNormal - Vector srcN = rotSrc; - VectorNormalize( srcN ); - Vector tangent = CrossProduct( srcN, m_targetAlignNormal ); - float len = VectorNormalize( tangent ); - - // needs at least ~5 degrees, or forget rotation (0.08 ~= sin(5)) - if ( len > 0.08 ) - { - Vector binormal = CrossProduct( m_targetAlignNormal, tangent ); - - // Now project the src & dest positions into that plane - Vector planeSrc( DotProduct( rotSrc, tangent ), DotProduct( rotSrc, binormal ), 0 ); - Vector planeDest( DotProduct( rotDest, tangent ), DotProduct( rotDest, binormal ), 0 ); - - float rotRadius = VectorNormalize( planeSrc ); - float destRadius = VectorNormalize( planeDest ); - if ( rotRadius > 0.1 ) - { - if ( destRadius < rotRadius ) - { - destRadius = rotRadius; - } - //float ratio = rotRadius / destRadius; - float angleSrc = atan2( planeSrc.y, planeSrc.x ); - float angleDest = atan2( planeDest.y, planeDest.x ); - float angleDiff = angleDest - angleSrc; - angleDiff = RAD2DEG(angleDiff); - axis += m_targetAlignNormal * angleDiff; - //world = m_targetPosition;// + rotDest * (1-ratio); -// NDebugOverlay::Line( worldRotCenter, worldRotCenter-m_targetAlignNormal*50, 255, 0, 0, false, 0.1 ); -// NDebugOverlay::Line( worldRotCenter, worldRotCenter+tangent*50, 0, 255, 0, false, 0.1 ); -// NDebugOverlay::Line( worldRotCenter, worldRotCenter+binormal*50, 0, 0, 255, false, 0.1 ); - } - } - - torque = WorldToLocalRotation( tmp, axis, 1 ); - torque *= fracRemainingSimTime * invDeltaTime; - torque -= angVel * 1.0; // damping - for ( int i = 0; i < 3; i++ ) - { - if ( torque[i] > 0 ) - { - if ( torque[i] > m_maxAngularAcceleration[i] ) - torque[i] = m_maxAngularAcceleration[i]; - } - else - { - if ( torque[i] < -m_maxAngularAcceleration[i] ) - torque[i] = -m_maxAngularAcceleration[i]; - } - } - torque *= invDeltaTime; - angular += torque; - // Calculate an acceleration that pulls the object toward the constraint - // When you're out of alignment, don't pull very hard - float factor = fabsf(alignRotation); - if ( factor < 5 ) - { - factor = clamp( factor, 0, 5 ) * (1/5); - alignDir = m_targetAlignPosition - worldRotCenter; - // Limit movement to the part along m_targetAlignNormal if worldRotCenter is on the backside of - // of the target plane (one inch epsilon)! - float planeForward = DotProduct( alignDir, m_targetAlignNormal ); - if ( planeForward > 1 ) - { - alignDir = m_targetAlignNormal * planeForward; - } - Vector accel = alignDir * invDeltaTime * fracRemainingSimTime * (1-factor) * 0.20 * invDeltaTime; - float mag = accel.Length(); - if ( mag > m_maxAcceleration ) - { - accel *= (m_maxAcceleration/mag); - } - linear += accel; - } - linear -= vel*damping*invDeltaTime; - // UNDONE: Factor in the change in worldRotCenter due to applied torque! - } - else - { - // clamp future velocity to max speed - Vector nextVel = delta + vel; - float nextSpeed = nextVel.Length(); - if ( nextSpeed > m_maxVel ) - { - nextVel *= (m_maxVel / nextSpeed); - delta = nextVel - vel; - } - - delta *= invDeltaTime; - - float linearAccel = delta.Length(); - if ( linearAccel > m_maxAcceleration ) - { - delta *= m_maxAcceleration / linearAccel; - } - - Vector accel; - AngularImpulse angAccel; - pObject->CalculateForceOffset( delta, world, &accel, &angAccel ); - - linear += accel; - angular += angAccel; - } - - return SIM_GLOBAL_ACCELERATION; -} - - -struct pelletlist_t -{ - DECLARE_SIMPLE_DATADESC(); - - Vector localNormal; // normal in parent space - CHandle pellet; - EHANDLE parent; -}; - -class CWeaponGravityGun : public CBaseCombatWeapon -{ - DECLARE_DATADESC(); - -public: - DECLARE_CLASS( CWeaponGravityGun, CBaseCombatWeapon ); - - CWeaponGravityGun(); - void Spawn( void ); - void OnRestore( void ); - void Precache( void ); - - void PrimaryAttack( void ); - void SecondaryAttack( void ); - void WeaponIdle( void ); - void ItemPostFrame( void ); - virtual bool Holster( CBaseCombatWeapon *pSwitchingTo ) - { - EffectDestroy(); - return BaseClass::Holster(); - } - - bool Reload( void ); - void Equip( CBaseCombatCharacter *pOwner ) - { - // add constraint ammo - pOwner->SetAmmoCount( MAX_PELLETS, m_iSecondaryAmmoType ); - BaseClass::Equip( pOwner ); - } - void Drop(const Vector &vecVelocity) - { - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - pOwner->SetAmmoCount( 0, m_iSecondaryAmmoType ); - // destroy all constraints - BaseClass::Drop(vecVelocity); - } - - bool HasAnyAmmo( void ); - - void AttachObject( CBaseEntity *pEdict, const Vector& start, const Vector &end, float distance ); - void DetachObject( void ); - - void EffectCreate( void ); - void EffectUpdate( void ); - void EffectDestroy( void ); - - void SoundCreate( void ); - void SoundDestroy( void ); - void SoundStop( void ); - void SoundStart( void ); - void SoundUpdate( void ); - void AddPellet( CGravityPellet *pPellet, CBaseEntity *pParent, const Vector &surfaceNormal ); - void DeleteActivePellets(); - void SortPelletsForObject( CBaseEntity *pObject ); - void SetObjectPelletsColor( int r, int g, int b ); - void CreatePelletAttraction( float radius, CBaseEntity *pObject ); - IPhysicsObject *GetPelletPhysObject( int pelletIndex ); - void GetPelletWorldCoords( int pelletIndex, Vector *worldPos, Vector *worldNormal ) - { - if ( worldPos ) - { - *worldPos = m_activePellets[pelletIndex].pellet->GetAbsOrigin(); - } - if ( worldNormal ) - { - if ( m_activePellets[pelletIndex].parent ) - { - EntityMatrix tmp; - tmp.InitFromEntity( m_activePellets[pelletIndex].parent ); - *worldNormal = tmp.LocalToWorldRotation( m_activePellets[pelletIndex].localNormal ); - } - else - { - *worldNormal = m_activePellets[pelletIndex].localNormal; - } - } - } - - int ObjectCaps( void ) - { - int caps = BaseClass::ObjectCaps(); - if ( m_active ) - { - caps |= FCAP_DIRECTIONAL_USE; - } - return caps; - } - - CBaseEntity *GetBeamEntity(); - - DECLARE_SERVERCLASS(); - -private: - CNetworkVar( int, m_active ); - bool m_useDown; - EHANDLE m_hObject; - float m_distance; - float m_movementLength; - float m_lastYaw; - int m_soundState; - CNetworkVar( int, m_viewModelIndex ); - Vector m_originalObjectPosition; - - CGravControllerPoint m_gravCallback; - pelletlist_t m_activePellets[MAX_PELLETS]; - int m_pelletCount; - int m_objectPelletCount; - - int m_pelletHeld; - int m_pelletAttract; - float m_glueTime; - CNetworkVar( bool, m_glueTouching ); -}; - -IMPLEMENT_SERVERCLASS_ST( CWeaponGravityGun, DT_WeaponGravityGun ) - SendPropVector( SENDINFO_NAME(m_gravCallback.m_targetPosition, m_targetPosition), -1, SPROP_COORD ), - SendPropVector( SENDINFO_NAME(m_gravCallback.m_worldPosition, m_worldPosition), -1, SPROP_COORD ), - SendPropInt( SENDINFO(m_active), 1, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_glueTouching), 1, SPROP_UNSIGNED ), - SendPropModelIndex( SENDINFO(m_viewModelIndex) ), -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( weapon_physgun, CWeaponGravityGun ); -PRECACHE_WEAPON_REGISTER(weapon_physgun); - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_SIMPLE_DATADESC( pelletlist_t ) - - DEFINE_FIELD( localNormal, FIELD_VECTOR ), - DEFINE_FIELD( pellet, FIELD_EHANDLE ), - DEFINE_FIELD( parent, FIELD_EHANDLE ), - -END_DATADESC() - -BEGIN_DATADESC( CWeaponGravityGun ) - - DEFINE_FIELD( m_active, FIELD_INTEGER ), - DEFINE_FIELD( m_useDown, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hObject, FIELD_EHANDLE ), - DEFINE_FIELD( m_distance, FIELD_FLOAT ), - DEFINE_FIELD( m_movementLength, FIELD_FLOAT ), - DEFINE_FIELD( m_lastYaw, FIELD_FLOAT ), - DEFINE_FIELD( m_soundState, FIELD_INTEGER ), - DEFINE_FIELD( m_viewModelIndex, FIELD_INTEGER ), - DEFINE_FIELD( m_originalObjectPosition, FIELD_POSITION_VECTOR ), - DEFINE_EMBEDDED( m_gravCallback ), - // Physptrs can't be saved in embedded classes.. - DEFINE_PHYSPTR( m_gravCallback.m_controller ), - DEFINE_EMBEDDED_AUTO_ARRAY( m_activePellets ), - DEFINE_FIELD( m_pelletCount, FIELD_INTEGER ), - DEFINE_FIELD( m_objectPelletCount, FIELD_INTEGER ), - DEFINE_FIELD( m_pelletHeld, FIELD_INTEGER ), - DEFINE_FIELD( m_pelletAttract, FIELD_INTEGER ), - DEFINE_FIELD( m_glueTime, FIELD_TIME ), - DEFINE_FIELD( m_glueTouching, FIELD_BOOLEAN ), - -END_DATADESC() - - -enum physgun_soundstate { SS_SCANNING, SS_LOCKEDON }; -enum physgun_soundIndex { SI_LOCKEDON = 0, SI_SCANNING = 1, SI_LIGHTOBJECT = 2, SI_HEAVYOBJECT = 3, SI_ON, SI_OFF }; - - -//========================================================= -//========================================================= - -CWeaponGravityGun::CWeaponGravityGun() -{ - m_active = false; - m_bFiresUnderwater = true; - m_pelletAttract = -1; - m_pelletHeld = -1; -} - -//========================================================= -//========================================================= -void CWeaponGravityGun::Spawn( ) -{ - BaseClass::Spawn(); -// SetModel( GetWorldModel() ); - - FallInit(); -} - -void CWeaponGravityGun::OnRestore( void ) -{ - BaseClass::OnRestore(); - - if ( m_gravCallback.m_controller ) - { - m_gravCallback.m_controller->SetEventHandler( &m_gravCallback ); - } -} - - -//========================================================= -//========================================================= -void CWeaponGravityGun::Precache( void ) -{ - BaseClass::Precache(); - - g_physgunBeam = PrecacheModel(PHYSGUN_BEAM_SPRITE); - - PrecacheScriptSound( "Weapon_Physgun.Scanning" ); - PrecacheScriptSound( "Weapon_Physgun.LockedOn" ); - PrecacheScriptSound( "Weapon_Physgun.Scanning" ); - PrecacheScriptSound( "Weapon_Physgun.LightObject" ); - PrecacheScriptSound( "Weapon_Physgun.HeavyObject" ); -} - -void CWeaponGravityGun::EffectCreate( void ) -{ - EffectUpdate(); - m_active = true; -} - - -void CWeaponGravityGun::EffectUpdate( void ) -{ - Vector start, angles, forward, right; - trace_t tr; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( !pOwner ) - return; - - m_viewModelIndex = pOwner->entindex(); - // Make sure I've got a view model - CBaseViewModel *vm = pOwner->GetViewModel(); - if ( vm ) - { - m_viewModelIndex = vm->entindex(); - } - - pOwner->EyeVectors( &forward, &right, NULL ); - - start = pOwner->Weapon_ShootPosition(); - Vector end = start + forward * 4096; - - UTIL_TraceLine( start, end, MASK_SHOT, pOwner, COLLISION_GROUP_NONE, &tr ); - end = tr.endpos; - float distance = tr.fraction * 4096; - if ( tr.fraction != 1 ) - { - // too close to the player, drop the object - if ( distance < 36 ) - { - DetachObject(); - return; - } - } - - if ( m_hObject == NULL && tr.DidHitNonWorldEntity() ) - { - CBaseEntity *pEntity = tr.m_pEnt; - // inform the object what was hit - ClearMultiDamage(); - pEntity->DispatchTraceAttack( CTakeDamageInfo( pOwner, pOwner, 0, DMG_PHYSGUN ), forward, &tr ); - ApplyMultiDamage(); - AttachObject( pEntity, start, tr.endpos, distance ); - m_lastYaw = pOwner->EyeAngles().y; - } - - // Add the incremental player yaw to the target transform - matrix3x4_t curMatrix, incMatrix, nextMatrix; - QAngle ang(0.0f, pOwner->EyeAngles().y - m_lastYaw, 0.0f); - AngleMatrix( m_gravCallback.m_targetRotation, curMatrix ); - AngleMatrix( ang, incMatrix ); - ConcatTransforms( incMatrix, curMatrix, nextMatrix ); - MatrixAngles( nextMatrix, m_gravCallback.m_targetRotation ); - m_lastYaw = pOwner->EyeAngles().y; - - CBaseEntity *pObject = m_hObject; - if ( pObject ) - { - if ( m_useDown ) - { - if ( pOwner->m_afButtonPressed & IN_USE ) - { - m_useDown = false; - } - } - else - { - if ( pOwner->m_afButtonPressed & IN_USE ) - { - m_useDown = true; - } - } - - if ( m_useDown ) - { - pOwner->SetPhysicsFlag( PFLAG_DIROVERRIDE, true ); - if ( pOwner->m_nButtons & IN_FORWARD ) - { - m_distance = UTIL_Approach( 1024, m_distance, gpGlobals->frametime * 100 ); - } - if ( pOwner->m_nButtons & IN_BACK ) - { - m_distance = UTIL_Approach( 40, m_distance, gpGlobals->frametime * 100 ); - } - } - - if ( pOwner->m_nButtons & IN_WEAPON1 ) - { - m_distance = UTIL_Approach( 1024, m_distance, m_distance * 0.1 ); - } - if ( pOwner->m_nButtons & IN_WEAPON2 ) - { - m_distance = UTIL_Approach( 40, m_distance, m_distance * 0.1 ); - } - - // Send the object a physics damage message (0 damage). Some objects interpret this - // as something else being in control of their physics temporarily. - pObject->TakeDamage( CTakeDamageInfo( this, pOwner, 0, DMG_PHYSGUN ) ); - - Vector newPosition = start + forward * m_distance; - // 24 is a little larger than 16 * sqrt(2) (extent of player bbox) - // HACKHACK: We do this so we can "ignore" the player and the object we're manipulating - // If we had a filter for tracelines, we could simply filter both ents and start from "start" - Vector awayfromPlayer = start + forward * 24; - - UTIL_TraceLine( start, awayfromPlayer, MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction == 1 ) - { - UTIL_TraceLine( awayfromPlayer, newPosition, MASK_SOLID, pObject, COLLISION_GROUP_NONE, &tr ); - Vector dir = tr.endpos - newPosition; - float distance = VectorNormalize(dir); - float maxDist = m_gravCallback.m_maxVel * gpGlobals->frametime; - if ( distance > maxDist ) - { - newPosition += dir * maxDist; - } - else - { - newPosition = tr.endpos; - } - } - else - { - newPosition = tr.endpos; - } - - CreatePelletAttraction( phys_gunglueradius.GetFloat(), pObject ); - - // If I'm looking more than 20 degrees away from the glue point, then give up - // This lets the player "gesture" for the glue to let go. - Vector pelletDir = m_gravCallback.m_worldPosition - start; - VectorNormalize(pelletDir); - if ( DotProduct( pelletDir, forward ) < 0.939 ) // 0.939 ~= cos(20deg) - { - // lose attach for 2 seconds if you're too far away - m_glueTime = gpGlobals->curtime + 1; - } - - if ( m_pelletHeld >= 0 && gpGlobals->curtime > m_glueTime ) - { - CGravityPellet *pPelletAttract = m_activePellets[m_pelletAttract].pellet; - - g_pEffects->Sparks( pPelletAttract->GetAbsOrigin() ); - } - - m_gravCallback.SetTargetPosition( newPosition ); - Vector dir = (newPosition - pObject->GetLocalOrigin()); - m_movementLength = dir.Length(); - } - else - { - m_gravCallback.SetTargetPosition( end ); - } - if ( m_pelletHeld >= 0 && gpGlobals->curtime > m_glueTime ) - { - Vector worldNormal, worldPos; - GetPelletWorldCoords( m_pelletAttract, &worldPos, &worldNormal ); - - m_gravCallback.SetAutoAlign( m_activePellets[m_pelletHeld].localNormal, m_activePellets[m_pelletHeld].pellet->GetLocalOrigin(), worldNormal, worldPos ); - } - else - { - m_gravCallback.ClearAutoAlign(); - } -} - -void CWeaponGravityGun::SoundCreate( void ) -{ - m_soundState = SS_SCANNING; - SoundStart(); -} - - -void CWeaponGravityGun::SoundDestroy( void ) -{ - SoundStop(); -} - - -void CWeaponGravityGun::SoundStop( void ) -{ - switch( m_soundState ) - { - case SS_SCANNING: - GetOwner()->StopSound( "Weapon_Physgun.Scanning" ); - break; - case SS_LOCKEDON: - GetOwner()->StopSound( "Weapon_Physgun.Scanning" ); - GetOwner()->StopSound( "Weapon_Physgun.LockedOn" ); - GetOwner()->StopSound( "Weapon_Physgun.LightObject" ); - GetOwner()->StopSound( "Weapon_Physgun.HeavyObject" ); - break; - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: returns the linear fraction of value between low & high (0.0 - 1.0) * scale -// e.g. UTIL_LineFraction( 1.5, 1, 2, 1 ); will return 0.5 since 1.5 is -// halfway between 1 and 2 -// Input : value - a value between low & high (clamped) -// low - the value that maps to zero -// high - the value that maps to "scale" -// scale - the output scale -// Output : parametric fraction between low & high -//----------------------------------------------------------------------------- -static float UTIL_LineFraction( float value, float low, float high, float scale ) -{ - if ( value < low ) - value = low; - if ( value > high ) - value = high; - - float delta = high - low; - if ( delta == 0 ) - return 0; - - return scale * (value-low) / delta; -} - -void CWeaponGravityGun::SoundStart( void ) -{ - CPASAttenuationFilter filter( GetOwner() ); - filter.MakeReliable(); - - switch( m_soundState ) - { - case SS_SCANNING: - { - EmitSound( filter, GetOwner()->entindex(), "Weapon_Physgun.Scanning" ); - } - break; - case SS_LOCKEDON: - { - // BUGBUG - If you start a sound with a pitch of 100, the pitch shift doesn't work! - - EmitSound( filter, GetOwner()->entindex(), "Weapon_Physgun.LockedOn" ); - EmitSound( filter, GetOwner()->entindex(), "Weapon_Physgun.Scanning" ); - EmitSound( filter, GetOwner()->entindex(), "Weapon_Physgun.LightObject" ); - EmitSound( filter, GetOwner()->entindex(), "Weapon_Physgun.HeavyObject" ); - } - break; - } - // volume, att, flags, pitch -} - -void CWeaponGravityGun::SoundUpdate( void ) -{ - int newState; - - if ( m_hObject ) - newState = SS_LOCKEDON; - else - newState = SS_SCANNING; - - if ( newState != m_soundState ) - { - SoundStop(); - m_soundState = newState; - SoundStart(); - } - - switch( m_soundState ) - { - case SS_SCANNING: - break; - case SS_LOCKEDON: - { - CPASAttenuationFilter filter( GetOwner() ); - filter.MakeReliable(); - - float height = m_hObject->GetAbsOrigin().z - m_originalObjectPosition.z; - - // go from pitch 90 to 150 over a height of 500 - int pitch = 90 + (int)UTIL_LineFraction( height, 0, 500, 60 ); - - CSoundParameters params; - if ( GetParametersForSound( "Weapon_Physgun.LockedOn", params, NULL ) ) - { - EmitSound_t ep( params ); - ep.m_nFlags = SND_CHANGE_VOL | SND_CHANGE_PITCH; - ep.m_nPitch = pitch; - - EmitSound( filter, GetOwner()->entindex(), ep ); - } - - // attenutate the movement sounds over 200 units of movement - float distance = UTIL_LineFraction( m_movementLength, 0, 200, 1.0 ); - - // blend the "mass" sounds between 50 and 500 kg - IPhysicsObject *pPhys = m_hObject->VPhysicsGetObject(); - - float fade = UTIL_LineFraction( pPhys->GetMass(), 50, 500, 1.0 ); - - if ( GetParametersForSound( "Weapon_Physgun.LightObject", params, NULL ) ) - { - EmitSound_t ep( params ); - ep.m_nFlags = SND_CHANGE_VOL; - ep.m_flVolume = fade * distance; - - EmitSound( filter, GetOwner()->entindex(), ep ); - } - - if ( GetParametersForSound( "Weapon_Physgun.HeavyObject", params, NULL ) ) - { - EmitSound_t ep( params ); - ep.m_nFlags = SND_CHANGE_VOL; - ep.m_flVolume = (1.0 - fade) * distance; - - EmitSound( filter, GetOwner()->entindex(), ep ); - } - } - break; - } -} - - -void CWeaponGravityGun::AddPellet( CGravityPellet *pPellet, CBaseEntity *pAttach, const Vector &surfaceNormal ) -{ - Assert(m_pelletCountIsInert() ) - { - if ( i != 0 ) - { - pelletlist_t tmp = m_activePellets[m_objectPelletCount]; - m_activePellets[m_objectPelletCount] = m_activePellets[i]; - m_activePellets[i] = tmp; - } - m_objectPelletCount++; - } - } - - SetObjectPelletsColor( 192, 255, 192 ); -} - -void CWeaponGravityGun::SetObjectPelletsColor( int r, int g, int b ) -{ - color32 color; - color.r = r; - color.g = g; - color.b = b; - color.a = 255; - - for ( int i = 0; i < m_objectPelletCount; i++ ) - { - CGravityPellet *pPellet = m_activePellets[i].pellet; - if ( !pPellet || pPellet->IsInert() ) - continue; - - pPellet->m_clrRender = color; - } -} - -CBaseEntity *CWeaponGravityGun::GetBeamEntity() -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( !pOwner ) - return NULL; - - // Make sure I've got a view model - CBaseViewModel *vm = pOwner->GetViewModel(); - if ( vm ) - return vm; - - return pOwner; -} - -void CWeaponGravityGun::DeleteActivePellets() -{ - CBaseEntity *pEnt = GetBeamEntity(); - - for ( int i = 0; i < m_pelletCount; i++ ) - { - CGravityPellet *pPellet = m_activePellets[i].pellet; - if ( !pPellet ) - continue; - - Vector forward; - AngleVectors( pPellet->GetAbsAngles(), &forward ); - g_pEffects->Dust( pPellet->GetAbsOrigin(), forward, 32, 30 ); - - // UNDONE: Probably should just do this client side - CBeam *pBeam = CBeam::BeamCreate( PHYSGUN_BEAM_SPRITE, 1.5 ); - pBeam->PointEntInit( pPellet->GetAbsOrigin(), pEnt ); - pBeam->SetEndAttachment( 1 ); - pBeam->SetBrightness( 255 ); - pBeam->SetColor( 255, 0, 0 ); - pBeam->RelinkBeam(); - pBeam->LiveForTime( 0.1 ); - - UTIL_Remove( pPellet ); - } - m_pelletCount = 0; -} - -void CWeaponGravityGun::CreatePelletAttraction( float radius, CBaseEntity *pObject ) -{ - int nearPellet = -1; - int objectPellet = -1; - float best = radius*radius; - // already have a pellet, check for in range - if ( m_pelletAttract >= 0 ) - { - Vector attract, held; - GetPelletWorldCoords( m_pelletAttract, &attract, NULL ); - GetPelletWorldCoords( m_pelletHeld, &held, NULL ); - float dist = (attract - held).Length(); - if ( dist < radius * 2 ) - { - nearPellet = m_pelletAttract; - objectPellet = m_pelletHeld; - best = dist * dist; - } - } - - if ( nearPellet < 0 ) - { - - for ( int i = 0; i < m_objectPelletCount; i++ ) - { - CGravityPellet *pPellet = m_activePellets[i].pellet; - if ( !pPellet ) - continue; - for ( int j = m_objectPelletCount; j < m_pelletCount; j++ ) - { - CGravityPellet *pTest = m_activePellets[j].pellet; - if ( !pTest ) - continue; - - if ( pTest->IsInert() ) - continue; - float distSqr = (pTest->GetAbsOrigin() - pPellet->GetAbsOrigin()).LengthSqr(); - if ( distSqr < best ) - { - Vector worldPos, worldNormal; - GetPelletWorldCoords( j, &worldPos, &worldNormal ); - // don't attract backside pellets (unless current pellet - prevent oscillation) - float dist = DotProduct( worldPos, worldNormal ); - if ( m_pelletAttract == j || DotProduct( pPellet->GetAbsOrigin(), worldNormal ) - dist >= 0 ) - { - best = distSqr; - nearPellet = j; - objectPellet = i; - } - } - } - } - } - - m_glueTouching = false; - if ( nearPellet < 0 || objectPellet < 0 ) - { - m_pelletAttract = -1; - m_pelletHeld = -1; - return; - } - - if ( nearPellet != m_pelletAttract || objectPellet != m_pelletHeld ) - { - m_glueTime = gpGlobals->curtime; - - m_pelletAttract = nearPellet; - m_pelletHeld = objectPellet; - } - - // check for bonding - if ( best < 3*3 ) - { - // This makes the pull towards the pellet stop getting stronger since some part of - // the object is touching - m_glueTouching = true; - } - } - - -IPhysicsObject *CWeaponGravityGun::GetPelletPhysObject( int pelletIndex ) -{ - if ( pelletIndex < 0 ) - return NULL; - - CBaseEntity *pEntity = m_activePellets[pelletIndex].parent; - if ( pEntity ) - return pEntity->VPhysicsGetObject(); - - return g_PhysWorldObject; -} - -void CWeaponGravityGun::EffectDestroy( void ) -{ - m_active = false; - SoundStop(); - - DetachObject(); -} - -void CWeaponGravityGun::DetachObject( void ) -{ - m_pelletHeld = -1; - m_pelletAttract = -1; - m_glueTouching = false; - SetObjectPelletsColor( 255, 0, 0 ); - m_objectPelletCount = 0; - - if ( m_hObject ) - { - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - Pickup_OnPhysGunDrop( m_hObject, pOwner, DROPPED_BY_CANNON ); - - m_gravCallback.DetachEntity(); - m_hObject = NULL; - } -} - -void CWeaponGravityGun::AttachObject( CBaseEntity *pObject, const Vector& start, const Vector &end, float distance ) -{ - m_hObject = pObject; - m_useDown = false; - IPhysicsObject *pPhysics = pObject ? (pObject->VPhysicsGetObject()) : NULL; - if ( pPhysics && pObject->GetMoveType() == MOVETYPE_VPHYSICS ) - { - m_distance = distance; - - m_gravCallback.AttachEntity( pObject, pPhysics, end ); - float mass = pPhysics->GetMass(); - Msg( "Object mass: %.2f lbs (%.2f kg)\n", kg2lbs(mass), mass ); - float vel = phys_gunvel.GetFloat(); - if ( mass > phys_gunmass.GetFloat() ) - { - vel = (vel*phys_gunmass.GetFloat())/mass; - } - m_gravCallback.SetMaxVelocity( vel ); -// Msg( "Object mass: %.2f lbs (%.2f kg) %f %f %f\n", kg2lbs(mass), mass, pObject->GetAbsOrigin().x, pObject->GetAbsOrigin().y, pObject->GetAbsOrigin().z ); -// Msg( "ANG: %f %f %f\n", pObject->GetAbsAngles().x, pObject->GetAbsAngles().y, pObject->GetAbsAngles().z ); - - m_originalObjectPosition = pObject->GetAbsOrigin(); - - m_pelletAttract = -1; - m_pelletHeld = -1; - - pPhysics->Wake(); - SortPelletsForObject( pObject ); - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if( pOwner ) - { - Pickup_OnPhysGunPickup( pObject, pOwner ); - } - } - else - { - m_hObject = NULL; - } -} - -//========================================================= -//========================================================= -void CWeaponGravityGun::PrimaryAttack( void ) -{ - if ( !m_active ) - { - SendWeaponAnim( ACT_VM_PRIMARYATTACK ); - EffectCreate(); - SoundCreate(); - } - else - { - EffectUpdate(); - SoundUpdate(); - } -} - -void CWeaponGravityGun::SecondaryAttack( void ) -{ - m_flNextSecondaryAttack = gpGlobals->curtime + 0.1; - if ( m_active ) - { - EffectDestroy(); - SoundDestroy(); - return; - } - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - Assert( pOwner ); - - if ( pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0 ) - return; - - m_viewModelIndex = pOwner->entindex(); - // Make sure I've got a view model - CBaseViewModel *vm = pOwner->GetViewModel(); - if ( vm ) - { - m_viewModelIndex = vm->entindex(); - } - - Vector forward; - pOwner->EyeVectors( &forward ); - - Vector start = pOwner->Weapon_ShootPosition(); - Vector end = start + forward * 4096; - - trace_t tr; - UTIL_TraceLine( start, end, MASK_SHOT, pOwner, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction == 1.0 || (tr.surface.flags & SURF_SKY) ) - return; - - CBaseEntity *pHit = tr.m_pEnt; - - if ( pHit->entindex() == 0 ) - { - pHit = NULL; - } - else - { - // if the object has no physics object, or isn't a physprop or brush entity, then don't glue - if ( !pHit->VPhysicsGetObject() || pHit->GetMoveType() != MOVETYPE_VPHYSICS ) - return; - } - - QAngle angles; - WeaponSound( SINGLE ); - pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType ); - - VectorAngles( tr.plane.normal, angles ); - Vector endPoint = tr.endpos + tr.plane.normal; - CGravityPellet *pPellet = (CGravityPellet *)CBaseEntity::Create( "gravity_pellet", endPoint, angles, this ); - if ( pHit ) - { - pPellet->SetParent( pHit ); - } - AddPellet( pPellet, pHit, tr.plane.normal ); - - // UNDONE: Probably should just do this client side - CBaseEntity *pEnt = GetBeamEntity(); - CBeam *pBeam = CBeam::BeamCreate( PHYSGUN_BEAM_SPRITE, 1.5 ); - pBeam->PointEntInit( endPoint, pEnt ); - pBeam->SetEndAttachment( 1 ); - pBeam->SetBrightness( 255 ); - pBeam->SetColor( 255, 0, 0 ); - pBeam->RelinkBeam(); - pBeam->LiveForTime( 0.1 ); - -} - -void CWeaponGravityGun::WeaponIdle( void ) -{ - if ( HasWeaponIdleTimeElapsed() ) - { - SendWeaponAnim( ACT_VM_IDLE ); - if ( m_active ) - { - CBaseEntity *pObject = m_hObject; - // pellet is touching object, so glue it - if ( pObject && m_glueTouching ) - { - CGravityPellet *pPellet = m_activePellets[m_pelletAttract].pellet; - if ( pPellet->MakeConstraint( pObject ) ) - { - WeaponSound( SPECIAL1 ); - m_flNextPrimaryAttack = gpGlobals->curtime + 0.75; - m_activePellets[m_pelletHeld].pellet->MakeInert(); - } - } - - EffectDestroy(); - SoundDestroy(); - } - } -} - -void CWeaponGravityGun::ItemPostFrame( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if (!pOwner) - return; - - if ( pOwner->m_afButtonPressed & IN_ATTACK2 ) - { - SecondaryAttack(); - } - else if ( pOwner->m_nButtons & IN_ATTACK ) - { - PrimaryAttack(); - } - else if ( pOwner->m_afButtonPressed & IN_RELOAD ) - { - Reload(); - } - // ----------------------- - // No buttons down - // ----------------------- - else - { - WeaponIdle( ); - return; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponGravityGun::HasAnyAmmo( void ) -{ - //Always report that we have ammo - return true; -} - -//========================================================= -//========================================================= -bool CWeaponGravityGun::Reload( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner->GetAmmoCount(m_iSecondaryAmmoType) != MAX_PELLETS ) - { - pOwner->SetAmmoCount( MAX_PELLETS, m_iSecondaryAmmoType ); - DeleteActivePellets(); - WeaponSound( RELOAD ); - return true; - } - - return false; -} - -#define NUM_COLLISION_TESTS 2500 -void CC_CollisionTest( const CCommand &args ) -{ - if ( !physenv ) - return; - - Msg( "Testing collision system\n" ); - int i; - CBaseEntity *pSpot = gEntList.FindEntityByClassname( NULL, "info_player_start"); - Vector start = pSpot->GetAbsOrigin(); - static Vector *targets = NULL; - static bool first = true; - static float test[2] = {1,1}; - if ( first ) - { - targets = new Vector[NUM_COLLISION_TESTS]; - float radius = 0; - float theta = 0; - float phi = 0; - for ( i = 0; i < NUM_COLLISION_TESTS; i++ ) - { - radius += NUM_COLLISION_TESTS * 123.123; - radius = fabs(fmod(radius, 128)); - theta += NUM_COLLISION_TESTS * 76.76; - theta = fabs(fmod(theta, DEG2RAD(360))); - phi += NUM_COLLISION_TESTS * 1997.99; - phi = fabs(fmod(phi, DEG2RAD(180))); - - float st, ct, sp, cp; - SinCos( theta, &st, &ct ); - SinCos( phi, &sp, &cp ); - - targets[i].x = radius * ct * sp; - targets[i].y = radius * st * sp; - targets[i].z = radius * cp; - - // make the trace 1024 units long - Vector dir = targets[i] - start; - VectorNormalize(dir); - targets[i] = start + dir * 1024; - } - first = false; - } - - //Vector results[NUM_COLLISION_TESTS]; - - int testType = 0; - if ( args.ArgC() >= 2 ) - { - testType = atoi( args[1] ); - } - float duration = 0; - Vector size[2]; - size[0].Init(0,0,0); - size[1].Init(16,16,16); - unsigned int dots = 0; - - for ( int j = 0; j < 2; j++ ) - { - float startTime = engine->Time(); - if ( testType == 1 ) - { - const CPhysCollide *pCollide = g_PhysWorldObject->GetCollide(); - trace_t tr; - - for ( i = 0; i < NUM_COLLISION_TESTS; i++ ) - { - physcollision->TraceBox( start, targets[i], -size[j], size[j], pCollide, vec3_origin, vec3_angle, &tr ); - dots += physcollision->ReadStat(0); - //results[i] = tr.endpos; - } - } - else - { - testType = 0; - CBaseEntity *pWorld = GetContainingEntity( INDEXENT(0) ); - trace_t tr; - - for ( i = 0; i < NUM_COLLISION_TESTS; i++ ) - { - UTIL_TraceModel( start, targets[i], -size[j], size[j], pWorld, COLLISION_GROUP_NONE, &tr ); - //results[i] = tr.endpos; - } - } - - duration += engine->Time() - startTime; - } - test[testType] = duration; - Msg("%d collisions in %.2f ms (%u dots)\n", NUM_COLLISION_TESTS, duration*1000, dots ); - Msg("Current speed ratio: %.2fX BSP:JGJK\n", test[1] / test[0] ); -#if 0 - int red = 255, green = 0, blue = 0; - for ( i = 0; i < NUM_COLLISION_TESTS; i++ ) - { - NDebugOverlay::Line( start, results[i], red, green, blue, false, 2 ); - } -#endif -} -static ConCommand collision_test("collision_test", CC_CollisionTest, "Tests collision system", FCVAR_CHEAT ); diff --git a/game/server/physics.cpp b/game/server/physics.cpp deleted file mode 100644 index 941ba8c8e..000000000 --- a/game/server/physics.cpp +++ /dev/null @@ -1,2912 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: Interface layer for ipion IVP physics. -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//===========================================================================// - - -#include "cbase.h" -#include "coordsize.h" -#include "entitylist.h" -#include "vcollide_parse.h" -#include "soundenvelope.h" -#include "game.h" -#include "utlvector.h" -#include "init_factory.h" -#include "igamesystem.h" -#include "hierarchy.h" -#include "IEffects.h" -#include "engine/IEngineSound.h" -#include "world.h" -#include "decals.h" -#include "physics_fx.h" -#include "vphysics_sound.h" -#include "vphysics/vehicles.h" -#include "vehicle_sounds.h" -#include "movevars_shared.h" -#include "physics_saverestore.h" -#include "solidsetdefaults.h" -#include "tier0/vprof.h" -#include "engine/IStaticPropMgr.h" -#include "physics_prop_ragdoll.h" -#if HL2_EPISODIC -#include "particle_parse.h" -#endif -#include "vphysics/object_hash.h" -#include "vphysics/collision_set.h" -#include "vphysics/friction.h" -#include "fmtstr.h" -#include "physics_npc_solver.h" -#include "physics_collisionevent.h" -#include "vphysics/performance.h" -#include "positionwatcher.h" -#include "tier1/callqueue.h" -#include "vphysics/constraints.h" - -#ifdef PORTAL -#include "portal_physics_collisionevent.h" -#include "physicsshadowclone.h" -#include "PortalSimulation.h" -void PortalPhysFrame( float deltaTime ); //small wrapper for PhysFrame that simulates all 3 environments at once -#endif - -void PrecachePhysicsSounds( void ); - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar phys_speeds( "phys_speeds", "0" ); - -// defined in phys_constraint -extern IPhysicsConstraintEvent *g_pConstraintEvents; - - -CEntityList *g_pShadowEntities = NULL; -#ifdef PORTAL -CEntityList *g_pShadowEntities_Main = NULL; -#endif - -// local variables -static float g_PhysAverageSimTime; -CCallQueue g_PostSimulationQueue; - - -// local routines -static IPhysicsObject *PhysCreateWorld( CBaseEntity *pWorld ); -static void PhysFrame( float deltaTime ); -static bool IsDebris( int collisionGroup ); - -void TimescaleChanged( IConVar *var, const char *pOldString, float flOldValue ) -{ - if ( physenv ) - { - physenv->ResetSimulationClock(); - } -} - -ConVar phys_timescale( "phys_timescale", "1", 0, "Scale time for physics", TimescaleChanged ); - -#if _DEBUG -ConVar phys_dontprintint( "phys_dontprintint", "1", FCVAR_NONE, "Don't print inter-penetration warnings." ); -#endif - -#ifdef PORTAL - CPortal_CollisionEvent g_Collisions; -#else - CCollisionEvent g_Collisions; -#endif - - -IPhysicsCollisionSolver * const g_pCollisionSolver = &g_Collisions; -IPhysicsCollisionEvent * const g_pCollisionEventHandler = &g_Collisions; -IPhysicsObjectEvent * const g_pObjectEventHandler = &g_Collisions; - - -struct vehiclescript_t -{ - string_t scriptName; - vehicleparams_t params; - vehiclesounds_t sounds; -}; - -class CPhysicsHook : public CBaseGameSystemPerFrame -{ -public: - virtual const char *Name() { return "CPhysicsHook"; } - - virtual bool Init(); - virtual void LevelInitPreEntity(); - virtual void LevelInitPostEntity(); - virtual void LevelShutdownPreEntity(); - virtual void LevelShutdownPostEntity(); - virtual void FrameUpdatePostEntityThink(); - virtual void PreClientUpdate(); - - bool FindOrAddVehicleScript( const char *pScriptName, vehicleparams_t *pVehicle, vehiclesounds_t *pSounds ); - void FlushVehicleScripts() - { - m_vehicleScripts.RemoveAll(); - } - - bool ShouldSimulate() - { - return (physenv && !m_bPaused) ? true : false; - } - - physicssound::soundlist_t m_impactSounds; - CUtlVector m_breakSounds; - - CUtlVector m_massCenterOverrides; - CUtlVector m_vehicleScripts; - - float m_impactSoundTime; - bool m_bPaused; - bool m_isFinalTick; -}; - - -CPhysicsHook g_PhysicsHook; - -//----------------------------------------------------------------------------- -// Singleton access -//----------------------------------------------------------------------------- -IGameSystem* PhysicsGameSystem() -{ - return &g_PhysicsHook; -} - - -//----------------------------------------------------------------------------- -// Purpose: The physics hook callback implementations -//----------------------------------------------------------------------------- -bool CPhysicsHook::Init( void ) -{ - factorylist_t factories; - - // Get the list of interface factories to extract the physics DLL's factory - FactoryList_Retrieve( factories ); - - if ( !factories.physicsFactory ) - return false; - - if ((physics = (IPhysics *)factories.physicsFactory( VPHYSICS_INTERFACE_VERSION, NULL )) == NULL || - (physcollision = (IPhysicsCollision *)factories.physicsFactory( VPHYSICS_COLLISION_INTERFACE_VERSION, NULL )) == NULL || - (physprops = (IPhysicsSurfaceProps *)factories.physicsFactory( VPHYSICS_SURFACEPROPS_INTERFACE_VERSION, NULL )) == NULL - ) - return false; - - PhysParseSurfaceData( physprops, filesystem ); - - m_isFinalTick = true; - m_impactSoundTime = 0; - m_vehicleScripts.EnsureCapacity(4); - return true; -} - - -// a little debug wrapper to help fix bugs when entity pointers get trashed -#if 0 -struct physcheck_t -{ - IPhysicsObject *pPhys; - char string[512]; -}; - -CUtlVector< physcheck_t > physCheck; - -void PhysCheckAdd( IPhysicsObject *pPhys, const char *pString ) -{ - physcheck_t tmp; - tmp.pPhys = pPhys; - Q_strncpy( tmp.string, pString ,sizeof(tmp.string)); - physCheck.AddToTail( tmp ); -} - -const char *PhysCheck( IPhysicsObject *pPhys ) -{ - for ( int i = 0; i < physCheck.Size(); i++ ) - { - if ( physCheck[i].pPhys == pPhys ) - return physCheck[i].string; - } - - return "unknown"; -} -#endif - -void CPhysicsHook::LevelInitPreEntity() -{ - physenv = physics->CreateEnvironment(); - physics_performanceparams_t params; - params.Defaults(); - params.maxCollisionsPerObjectPerTimestep = 10; - physenv->SetPerformanceSettings( ¶ms ); - -#ifdef PORTAL - physenv_main = physenv; -#endif - { - g_EntityCollisionHash = physics->CreateObjectPairHash(); - } - factorylist_t factories; - FactoryList_Retrieve( factories ); - physenv->SetDebugOverlay( factories.engineFactory ); - physenv->EnableDeleteQueue( true ); - - physenv->SetCollisionSolver( &g_Collisions ); - physenv->SetCollisionEventHandler( &g_Collisions ); - physenv->SetConstraintEventHandler( g_pConstraintEvents ); - physenv->EnableConstraintNotify( true ); // callback when an object gets deleted that is attached to a constraint - - physenv->SetObjectEventHandler( &g_Collisions ); - - physenv->SetSimulationTimestep( DEFAULT_TICK_INTERVAL ); // 15 ms per tick - // HL Game gravity, not real-world gravity - physenv->SetGravity( Vector( 0, 0, -sv_gravity.GetFloat() ) ); - g_PhysAverageSimTime = 0; - - g_PhysWorldObject = PhysCreateWorld( GetWorldEntity() ); - - g_pShadowEntities = new CEntityList; -#ifdef PORTAL - g_pShadowEntities_Main = g_pShadowEntities; -#endif - - PrecachePhysicsSounds(); - - m_bPaused = true; -} - - - -void CPhysicsHook::LevelInitPostEntity() -{ - m_bPaused = false; -} - -void CPhysicsHook::LevelShutdownPreEntity() -{ - if ( !physenv ) - return; - physenv->SetQuickDelete( true ); -} - -void CPhysicsHook::LevelShutdownPostEntity() -{ - if ( !physenv ) - return; - - g_pPhysSaveRestoreManager->ForgetAllModels(); - - g_Collisions.LevelShutdown(); - - physics->DestroyEnvironment( physenv ); - physenv = NULL; - - physics->DestroyObjectPairHash( g_EntityCollisionHash ); - g_EntityCollisionHash = NULL; - - physics->DestroyAllCollisionSets(); - - g_PhysWorldObject = NULL; - - delete g_pShadowEntities; - g_pShadowEntities = NULL; - m_impactSounds.RemoveAll(); - m_breakSounds.RemoveAll(); - m_massCenterOverrides.Purge(); - FlushVehicleScripts(); -} - - -bool CPhysicsHook::FindOrAddVehicleScript( const char *pScriptName, vehicleparams_t *pVehicle, vehiclesounds_t *pSounds ) -{ - bool bLoadedSounds = false; - int index = -1; - for ( int i = 0; i < m_vehicleScripts.Count(); i++ ) - { - if ( !Q_stricmp(m_vehicleScripts[i].scriptName.ToCStr(), pScriptName) ) - { - index = i; - bLoadedSounds = true; - break; - } - } - - if ( index < 0 ) - { - byte *pFile = UTIL_LoadFileForMe( pScriptName, NULL ); - if ( pFile ) - { - // new script, parse it and write to the table - index = m_vehicleScripts.AddToTail(); - m_vehicleScripts[index].scriptName = AllocPooledString(pScriptName); - m_vehicleScripts[index].sounds.Init(); - - IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( (char *)pFile ); - while ( !pParse->Finished() ) - { - const char *pBlock = pParse->GetCurrentBlockName(); - if ( !strcmpi( pBlock, "vehicle" ) ) - { - pParse->ParseVehicle( &m_vehicleScripts[index].params, NULL ); - } - else if ( !Q_stricmp( pBlock, "vehicle_sounds" ) ) - { - bLoadedSounds = true; - CVehicleSoundsParser soundParser; - pParse->ParseCustom( &m_vehicleScripts[index].sounds, &soundParser ); - } - else - { - pParse->SkipBlock(); - } - } - physcollision->VPhysicsKeyParserDestroy( pParse ); - UTIL_FreeFile( pFile ); - } - } - - if ( index >= 0 ) - { - if ( pVehicle ) - { - *pVehicle = m_vehicleScripts[index].params; - } - if ( pSounds ) - { - // We must pass back valid data here! - if ( bLoadedSounds == false ) - return false; - - *pSounds = m_vehicleScripts[index].sounds; - } - return true; - } - - return false; -} - -// called after entities think -void CPhysicsHook::FrameUpdatePostEntityThink( ) -{ - VPROF_BUDGET( "CPhysicsHook::FrameUpdatePostEntityThink", VPROF_BUDGETGROUP_PHYSICS ); - - // Tracker 24846: If game is paused, don't simulate vphysics - float interval = ( gpGlobals->frametime > 0.0f ) ? TICK_INTERVAL : 0.0f; - - // update the physics simulation, not we don't use gpGlobals->frametime, since that can be 30 msec or 15 msec - // depending on whether IsSimulatingOnAlternateTicks is true or not - if ( CBaseEntity::IsSimulatingOnAlternateTicks() ) - { - m_isFinalTick = false; - -#ifdef PORTAL //slight detour if we're the portal mod - PortalPhysFrame( interval ); -#else - PhysFrame( interval ); -#endif - - } - m_isFinalTick = true; - -#ifdef PORTAL //slight detour if we're the portal mod - PortalPhysFrame( interval ); -#else - PhysFrame( interval ); -#endif - -} - -void CPhysicsHook::PreClientUpdate() -{ - m_impactSoundTime += gpGlobals->frametime; - if ( m_impactSoundTime > 0.05f ) - { - physicssound::PlayImpactSounds( m_impactSounds ); - m_impactSoundTime = 0.0f; - physicssound::PlayBreakSounds( m_breakSounds ); - } -} - -bool PhysIsFinalTick() -{ - return g_PhysicsHook.m_isFinalTick; -} - -IPhysicsObject *PhysCreateWorld( CBaseEntity *pWorld ) -{ - staticpropmgr->CreateVPhysicsRepresentations( physenv, &g_SolidSetup, pWorld ); - return PhysCreateWorld_Shared( pWorld, modelinfo->GetVCollide(1), g_PhysDefaultObjectParams ); -} - - -// vehicle wheels can only collide with things that can't get stuck in them during game physics -// because they aren't in the game physics world at present -static bool WheelCollidesWith( IPhysicsObject *pObj, CBaseEntity *pEntity ) -{ -#if defined( INVASION_DLL ) - if ( pEntity->GetCollisionGroup() == TFCOLLISION_GROUP_OBJECT ) - return false; -#endif - - // Cull against interactive debris - if ( pEntity->GetCollisionGroup() == COLLISION_GROUP_INTERACTIVE_DEBRIS ) - return false; - - // Hit physics ents - if ( pEntity->GetMoveType() == MOVETYPE_PUSH || pEntity->GetMoveType() == MOVETYPE_VPHYSICS || pObj->IsStatic() ) - return true; - - return false; -} - -CCollisionEvent::CCollisionEvent() -{ - m_inCallback = 0; - m_bBufferTouchEvents = false; - m_lastTickFrictionError = 0; -} - -int CCollisionEvent::ShouldCollide( IPhysicsObject *pObj0, IPhysicsObject *pObj1, void *pGameData0, void *pGameData1 ) -#if _DEBUG -{ - int x0 = ShouldCollide_2(pObj0, pObj1, pGameData0, pGameData1); - int x1 = ShouldCollide_2(pObj1, pObj0, pGameData1, pGameData0); - Assert(x0==x1); - return x0; -} -int CCollisionEvent::ShouldCollide_2( IPhysicsObject *pObj0, IPhysicsObject *pObj1, void *pGameData0, void *pGameData1 ) -#endif -{ - CallbackContext check(this); - - CBaseEntity *pEntity0 = static_cast(pGameData0); - CBaseEntity *pEntity1 = static_cast(pGameData1); - - if ( !pEntity0 || !pEntity1 ) - return 1; - - unsigned short gameFlags0 = pObj0->GetGameFlags(); - unsigned short gameFlags1 = pObj1->GetGameFlags(); - - if ( pEntity0 == pEntity1 ) - { - // allow all-or-nothing per-entity disable - if ( (gameFlags0 | gameFlags1) & FVPHYSICS_NO_SELF_COLLISIONS ) - return 0; - - IPhysicsCollisionSet *pSet = physics->FindCollisionSet( pEntity0->GetModelIndex() ); - if ( pSet ) - return pSet->ShouldCollide( pObj0->GetGameIndex(), pObj1->GetGameIndex() ); - - return 1; - } - - // objects that are both constrained to the world don't collide with each other - if ( (gameFlags0 & gameFlags1) & FVPHYSICS_CONSTRAINT_STATIC ) - { - return 0; - } - - // Special collision rules for vehicle wheels - // Their entity collides with stuff using the normal rules, but they - // have different rules than the vehicle body for various reasons. - // sort of a hack because we don't have spheres to represent them in the game - // world for speculative collisions. - if ( pObj0->GetCallbackFlags() & CALLBACK_IS_VEHICLE_WHEEL ) - { - if ( !WheelCollidesWith( pObj1, pEntity1 ) ) - return false; - } - if ( pObj1->GetCallbackFlags() & CALLBACK_IS_VEHICLE_WHEEL ) - { - if ( !WheelCollidesWith( pObj0, pEntity0 ) ) - return false; - } - - if ( pEntity0->ForceVPhysicsCollide( pEntity1 ) || pEntity1->ForceVPhysicsCollide( pEntity0 ) ) - return 1; - - if ( pEntity0->edict() && pEntity1->edict() ) - { - // don't collide with your owner - if ( pEntity0->GetOwnerEntity() == pEntity1 || pEntity1->GetOwnerEntity() == pEntity0 ) - return 0; - } - - if ( pEntity0->GetMoveParent() || pEntity1->GetMoveParent() ) - { - CBaseEntity *pParent0 = pEntity0->GetRootMoveParent(); - CBaseEntity *pParent1 = pEntity1->GetRootMoveParent(); - - // NOTE: Don't let siblings/parents collide. If you want this behavior, do it - // with constraints, not hierarchy! - if ( pParent0 == pParent1 ) - return 0; - - if ( g_EntityCollisionHash->IsObjectPairInHash( pParent0, pParent1 ) ) - return 0; - - IPhysicsObject *p0 = pParent0->VPhysicsGetObject(); - IPhysicsObject *p1 = pParent1->VPhysicsGetObject(); - if ( p0 && p1 ) - { - if ( g_EntityCollisionHash->IsObjectPairInHash( p0, p1 ) ) - return 0; - } - } - - int solid0 = pEntity0->GetSolid(); - int solid1 = pEntity1->GetSolid(); - int nSolidFlags0 = pEntity0->GetSolidFlags(); - int nSolidFlags1 = pEntity1->GetSolidFlags(); - - int movetype0 = pEntity0->GetMoveType(); - int movetype1 = pEntity1->GetMoveType(); - - // entities with non-physical move parents or entities with MOVETYPE_PUSH - // are considered as "AI movers". They are unchanged by collision; they exert - // physics forces on the rest of the system. - bool aiMove0 = (movetype0==MOVETYPE_PUSH) ? true : false; - bool aiMove1 = (movetype1==MOVETYPE_PUSH) ? true : false; - - if ( pEntity0->GetMoveParent() ) - { - // if the object & its parent are both MOVETYPE_VPHYSICS, then this must be a special case - // like a prop_ragdoll_attached - if ( !(movetype0 == MOVETYPE_VPHYSICS && pEntity0->GetRootMoveParent()->GetMoveType() == MOVETYPE_VPHYSICS) ) - { - aiMove0 = true; - } - } - if ( pEntity1->GetMoveParent() ) - { - // if the object & its parent are both MOVETYPE_VPHYSICS, then this must be a special case. - if ( !(movetype1 == MOVETYPE_VPHYSICS && pEntity1->GetRootMoveParent()->GetMoveType() == MOVETYPE_VPHYSICS) ) - { - aiMove1 = true; - } - } - - // AI movers don't collide with the world/static/pinned objects or other AI movers - if ( (aiMove0 && !pObj1->IsMoveable()) || - (aiMove1 && !pObj0->IsMoveable()) || - (aiMove0 && aiMove1) ) - return 0; - - // two objects under shadow control should not collide. The AI will figure it out - if ( pObj0->GetShadowController() && pObj1->GetShadowController() ) - return 0; - - // BRJ 1/24/03 - // You can remove the assert if it's problematic; I *believe* this condition - // should be met, but I'm not sure. - //Assert ( (solid0 != SOLID_NONE) && (solid1 != SOLID_NONE) ); - if ( (solid0 == SOLID_NONE) || (solid1 == SOLID_NONE) ) - return 0; - - // not solid doesn't collide with anything - if ( (nSolidFlags0|nSolidFlags1) & FSOLID_NOT_SOLID ) - { - // might be a vphysics trigger, collide with everything but "not solid" - if ( pObj0->IsTrigger() && !(nSolidFlags1 & FSOLID_NOT_SOLID) ) - return 1; - if ( pObj1->IsTrigger() && !(nSolidFlags0 & FSOLID_NOT_SOLID) ) - return 1; - - return 0; - } - - if ( (nSolidFlags0 & FSOLID_TRIGGER) && - !(solid1 == SOLID_VPHYSICS || solid1 == SOLID_BSP || movetype1 == MOVETYPE_VPHYSICS) ) - return 0; - - if ( (nSolidFlags1 & FSOLID_TRIGGER) && - !(solid0 == SOLID_VPHYSICS || solid0 == SOLID_BSP || movetype0 == MOVETYPE_VPHYSICS) ) - return 0; - - if ( !g_pGameRules->ShouldCollide( pEntity0->GetCollisionGroup(), pEntity1->GetCollisionGroup() ) ) - return 0; - - // check contents - if ( !(pObj0->GetContents() & pEntity1->PhysicsSolidMaskForEntity()) || !(pObj1->GetContents() & pEntity0->PhysicsSolidMaskForEntity()) ) - return 0; - - if ( g_EntityCollisionHash->IsObjectPairInHash( pGameData0, pGameData1 ) ) - return 0; - - if ( g_EntityCollisionHash->IsObjectPairInHash( pObj0, pObj1 ) ) - return 0; - - return 1; -} - -bool FindMaxContact( IPhysicsObject *pObject, float minForce, IPhysicsObject **pOtherObject, Vector *contactPos, Vector *pForce ) -{ - float mass = pObject->GetMass(); - float maxForce = minForce; - *pOtherObject = NULL; - IPhysicsFrictionSnapshot *pSnapshot = pObject->CreateFrictionSnapshot(); - while ( pSnapshot->IsValid() ) - { - IPhysicsObject *pOther = pSnapshot->GetObject(1); - if ( pOther->IsMoveable() && pOther->GetMass() > mass ) - { - float force = pSnapshot->GetNormalForce(); - if ( force > maxForce ) - { - *pOtherObject = pOther; - pSnapshot->GetContactPoint( *contactPos ); - pSnapshot->GetSurfaceNormal( *pForce ); - *pForce *= force; - } - } - pSnapshot->NextFrictionData(); - } - pObject->DestroyFrictionSnapshot( pSnapshot ); - if ( *pOtherObject ) - return true; - - return false; -} - -bool CCollisionEvent::ShouldFreezeObject( IPhysicsObject *pObject ) -{ - extern bool PropIsGib(CBaseEntity *pEntity); - // for now, don't apply a per-object limit to ai MOVETYPE_PUSH objects - // NOTE: If this becomes a problem (too many collision checks this tick) we should add a path - // to inform the logic in VPhysicsUpdatePusher() about the limit being applied so - // that it doesn't falsely block the object when it's simply been temporarily frozen - // for performance reasons - CBaseEntity *pEntity = static_cast(pObject->GetGameData()); - if ( pEntity ) - { - if (pEntity->GetMoveType() == MOVETYPE_PUSH ) - return false; - - // don't limit vehicle collisions either, limit can make breaking through a pile of breakable - // props very hitchy - if (pEntity->GetServerVehicle() && !(pObject->GetCallbackFlags() & CALLBACK_IS_VEHICLE_WHEEL)) - return false; - } - - // if we're freezing a debris object, then it's probably due to some kind of solver issue - // usually this is a large object resting on the debris object in question which is not - // very stable. - // After doing the experiment of constraining the dynamic range of mass while solving friction - // contacts, I like the results of this tradeoff better. So damage or remove the debris object - // wherever possible once we hit this case: - if ( IsDebris( pEntity->GetCollisionGroup()) && !pEntity->IsNPC() ) - { - IPhysicsObject *pOtherObject = NULL; - Vector contactPos; - Vector force; - // find the contact with the moveable object applying the most contact force - if ( FindMaxContact( pObject, pObject->GetMass() * 10, &pOtherObject, &contactPos, &force ) ) - { - CBaseEntity *pOther = static_cast(pOtherObject->GetGameData()); - // this object can take damage, crush it - if ( pEntity->m_takedamage > DAMAGE_EVENTS_ONLY ) - { - CTakeDamageInfo dmgInfo( pOther, pOther, force, contactPos, force.Length() * 0.1f, DMG_CRUSH ); - PhysCallbackDamage( pEntity, dmgInfo ); - } - else - { - // can't be damaged, so do something else: - if ( PropIsGib(pEntity) ) - { - // it's always safe to delete gibs, so kill this one to avoid simulation problems - PhysCallbackRemove( pEntity->NetworkProp() ); - } - else - { - // not a gib, create a solver: - // UNDONE: Add a property to override this in gameplay critical scenarios? - g_PostSimulationQueue.QueueCall( EntityPhysics_CreateSolver, pOther, pEntity, true, 1.0f ); - } - } - } - } - return true; -} - -bool CCollisionEvent::ShouldFreezeContacts( IPhysicsObject **pObjectList, int objectCount ) -{ - if ( m_lastTickFrictionError > gpGlobals->tickcount || m_lastTickFrictionError < (gpGlobals->tickcount-1) ) - { - DevWarning("Performance Warning: large friction system (%d objects)!!!\n", objectCount ); -#if _DEBUG - for ( int i = 0; i < objectCount; i++ ) - { - CBaseEntity *pEntity = static_cast(pObjectList[i]->GetGameData()); - pEntity->m_debugOverlays |= OVERLAY_ABSBOX_BIT | OVERLAY_PIVOT_BIT; - } -#endif - } - m_lastTickFrictionError = gpGlobals->tickcount; - return false; -} - -// NOTE: these are fully edge triggered events -// called when an object wakes up (starts simulating) -void CCollisionEvent::ObjectWake( IPhysicsObject *pObject ) -{ - CBaseEntity *pEntity = static_cast(pObject->GetGameData()); - if ( pEntity && pEntity->HasDataObjectType( VPHYSICSWATCHER ) ) - { - ReportVPhysicsStateChanged( pObject, pEntity, true ); - } -} -// called when an object goes to sleep (no longer simulating) -void CCollisionEvent::ObjectSleep( IPhysicsObject *pObject ) -{ - CBaseEntity *pEntity = static_cast(pObject->GetGameData()); - if ( pEntity && pEntity->HasDataObjectType( VPHYSICSWATCHER ) ) - { - ReportVPhysicsStateChanged( pObject, pEntity, false ); - } -} - -bool PhysShouldCollide( IPhysicsObject *pObj0, IPhysicsObject *pObj1 ) -{ - void *pGameData0 = pObj0->GetGameData(); - void *pGameData1 = pObj1->GetGameData(); - if ( !pGameData0 || !pGameData1 ) - return false; - return g_Collisions.ShouldCollide( pObj0, pObj1, pGameData0, pGameData1 ) ? true : false; -} - -bool PhysIsInCallback() -{ - if ( (physenv && physenv->IsInSimulation()) || g_Collisions.IsInCallback() ) - return true; - - return false; -} - - -static void ReportPenetration( CBaseEntity *pEntity, float duration ) -{ - if ( pEntity->GetMoveType() == MOVETYPE_VPHYSICS ) - { - if ( g_pDeveloper->GetInt() > 1 ) - { - pEntity->m_debugOverlays |= OVERLAY_ABSBOX_BIT; - } - - pEntity->AddTimedOverlay( UTIL_VarArgs("VPhysics Penetration Error (%s)!", pEntity->GetDebugName()), (int)duration ); - } -} - -static bool IsDebris( int collisionGroup ) -{ - switch ( collisionGroup ) - { - case COLLISION_GROUP_DEBRIS: - case COLLISION_GROUP_INTERACTIVE_DEBRIS: - case COLLISION_GROUP_DEBRIS_TRIGGER: - return true; - default: - break; - } - return false; -} - -static void UpdateEntityPenetrationFlag( CBaseEntity *pEntity, bool isPenetrating ) -{ - if ( !pEntity ) - return; - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int count = pEntity->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - for ( int i = 0; i < count; i++ ) - { - if ( !pList[i]->IsStatic() ) - { - if ( isPenetrating ) - { - PhysSetGameFlags( pList[i], FVPHYSICS_PENETRATING ); - } - else - { - PhysClearGameFlags( pList[i], FVPHYSICS_PENETRATING ); - } - } - } -} - -void CCollisionEvent::GetListOfPenetratingEntities( CBaseEntity *pSearch, CUtlVector &list ) -{ - for ( int i = m_penetrateEvents.Count()-1; i >= 0; --i ) - { - if ( m_penetrateEvents[i].hEntity0 == pSearch && m_penetrateEvents[i].hEntity1.Get() != NULL ) - { - list.AddToTail( m_penetrateEvents[i].hEntity1 ); - } - else if ( m_penetrateEvents[i].hEntity1 == pSearch && m_penetrateEvents[i].hEntity0.Get() != NULL ) - { - list.AddToTail( m_penetrateEvents[i].hEntity0 ); - } - } -} - -void CCollisionEvent::UpdatePenetrateEvents( void ) -{ - for ( int i = m_penetrateEvents.Count()-1; i >= 0; --i ) - { - CBaseEntity *pEntity0 = m_penetrateEvents[i].hEntity0; - CBaseEntity *pEntity1 = m_penetrateEvents[i].hEntity1; - - if ( m_penetrateEvents[i].collisionState == COLLSTATE_TRYDISABLE ) - { - if ( pEntity0 && pEntity1 ) - { - IPhysicsObject *pObj0 = pEntity0->VPhysicsGetObject(); - if ( pObj0 ) - { - PhysForceEntityToSleep( pEntity0, pObj0 ); - } - IPhysicsObject *pObj1 = pEntity1->VPhysicsGetObject(); - if ( pObj1 ) - { - PhysForceEntityToSleep( pEntity1, pObj1 ); - } - m_penetrateEvents[i].collisionState = COLLSTATE_DISABLED; - continue; - } - // missing entity or object, clear event - } - else if ( m_penetrateEvents[i].collisionState == COLLSTATE_TRYNPCSOLVER ) - { - if ( pEntity0 && pEntity1 ) - { - CAI_BaseNPC *pNPC = pEntity0->MyNPCPointer(); - CBaseEntity *pBlocker = pEntity1; - if ( !pNPC ) - { - pNPC = pEntity1->MyNPCPointer(); - Assert(pNPC); - pBlocker = pEntity0; - } - NPCPhysics_CreateSolver( pNPC, pBlocker, true, 1.0f ); - } - // transferred to solver, clear event - } - else if ( m_penetrateEvents[i].collisionState == COLLSTATE_TRYENTITYSOLVER ) - { - if ( pEntity0 && pEntity1 ) - { - if ( !IsDebris(pEntity1->GetCollisionGroup()) || pEntity1->GetMoveType() != MOVETYPE_VPHYSICS ) - { - CBaseEntity *pTmp = pEntity0; - pEntity0 = pEntity1; - pEntity1 = pTmp; - } - EntityPhysics_CreateSolver( pEntity0, pEntity1, true, 1.0f ); - } - // transferred to solver, clear event - } - else if ( gpGlobals->curtime - m_penetrateEvents[i].timeStamp > 1.0 ) - { - if ( m_penetrateEvents[i].collisionState == COLLSTATE_DISABLED ) - { - if ( pEntity0 && pEntity1 ) - { - IPhysicsObject *pObj0 = pEntity0->VPhysicsGetObject(); - IPhysicsObject *pObj1 = pEntity1->VPhysicsGetObject(); - if ( pObj0 && pObj1 ) - { - m_penetrateEvents[i].collisionState = COLLSTATE_ENABLED; - continue; - } - } - } - // haven't penetrated for 1 second, so remove - } - else - { - // recent timestamp, don't remove the event yet - continue; - } - // done, clear event - m_penetrateEvents.FastRemove(i); - UpdateEntityPenetrationFlag( pEntity0, false ); - UpdateEntityPenetrationFlag( pEntity1, false ); - } -} - -penetrateevent_t &CCollisionEvent::FindOrAddPenetrateEvent( CBaseEntity *pEntity0, CBaseEntity *pEntity1 ) -{ - int index = -1; - for ( int i = m_penetrateEvents.Count()-1; i >= 0; --i ) - { - if ( m_penetrateEvents[i].hEntity0.Get() == pEntity0 && m_penetrateEvents[i].hEntity1.Get() == pEntity1 ) - { - index = i; - break; - } - } - if ( index < 0 ) - { - index = m_penetrateEvents.AddToTail(); - penetrateevent_t &event = m_penetrateEvents[index]; - event.hEntity0 = pEntity0; - event.hEntity1 = pEntity1; - event.startTime = gpGlobals->curtime; - event.collisionState = COLLSTATE_ENABLED; - UpdateEntityPenetrationFlag( pEntity0, true ); - UpdateEntityPenetrationFlag( pEntity1, true ); - } - penetrateevent_t &event = m_penetrateEvents[index]; - event.timeStamp = gpGlobals->curtime; - return event; -} - - - -static ConVar phys_penetration_error_time( "phys_penetration_error_time", "10", 0, "Controls the duration of vphysics penetration error boxes." ); - -static bool CanResolvePenetrationWithNPC( CBaseEntity *pEntity, IPhysicsObject *pObject ) -{ - if ( pEntity->GetMoveType() == MOVETYPE_VPHYSICS ) - { - // hinged objects won't be able to be pushed out anyway, so don't try the npc solver - if ( !pObject->IsHinged() && !pObject->IsAttachedToConstraint(true) ) - { - if ( pObject->IsMoveable() || pEntity->GetServerVehicle() ) - return true; - } - } - return false; -} - -int CCollisionEvent::ShouldSolvePenetration( IPhysicsObject *pObj0, IPhysicsObject *pObj1, void *pGameData0, void *pGameData1, float dt ) -{ - CallbackContext check(this); - - // Pointers to the entity for each physics object - CBaseEntity *pEntity0 = static_cast(pGameData0); - CBaseEntity *pEntity1 = static_cast(pGameData1); - - // this can get called as entities are being constructed on the other side of a game load or level transition - // Some entities may not be fully constructed, so don't call into their code until the level is running - if ( g_PhysicsHook.m_bPaused ) - return true; - - // solve it yourself here and return 0, or have the default implementation do it - if ( pEntity0 > pEntity1 ) - { - // swap sort - CBaseEntity *pTmp = pEntity0; - pEntity0 = pEntity1; - pEntity1 = pTmp; - IPhysicsObject *pTmpObj = pObj0; - pObj0 = pObj1; - pObj1 = pTmpObj; - } - if ( pEntity0 == pEntity1 ) - { - if ( pObj0->GetGameFlags() & FVPHYSICS_PART_OF_RAGDOLL ) - { - DevMsg(2, "Solving ragdoll self penetration! %s (%s) (%d v %d)\n", pObj0->GetName(), pEntity0->GetDebugName(), pObj0->GetGameIndex(), pObj1->GetGameIndex() ); - ragdoll_t *pRagdoll = Ragdoll_GetRagdoll( pEntity0 ); - pRagdoll->pGroup->SolvePenetration( pObj0, pObj1 ); - return false; - } - } - penetrateevent_t &event = FindOrAddPenetrateEvent( pEntity0, pEntity1 ); - float eventTime = gpGlobals->curtime - event.startTime; - - // NPC vs. physics object. Create a game DLL solver and remove this event - if ( (pEntity0->MyNPCPointer() && CanResolvePenetrationWithNPC(pEntity1, pObj1)) || - (pEntity1->MyNPCPointer() && CanResolvePenetrationWithNPC(pEntity0, pObj0)) ) - { - event.collisionState = COLLSTATE_TRYNPCSOLVER; - } - - if ( (IsDebris( pEntity0->GetCollisionGroup() ) && !pObj1->IsStatic()) || (IsDebris( pEntity1->GetCollisionGroup() ) && !pObj0->IsStatic()) ) - { - if ( eventTime > 0.5f ) - { - //Msg("Debris stuck in non-static!\n"); - event.collisionState = COLLSTATE_TRYENTITYSOLVER; - } - } -#if _DEBUG - if ( phys_dontprintint.GetBool() == false ) - { - const char *pName1 = STRING(pEntity0->GetModelName()); - const char *pName2 = STRING(pEntity1->GetModelName()); - if ( pEntity0 == pEntity1 ) - { - int index0 = physcollision->CollideIndex( pObj0->GetCollide() ); - int index1 = physcollision->CollideIndex( pObj1->GetCollide() ); - DevMsg(1, "***Inter-penetration on %s (%d & %d) (%.0f, %.0f)\n", pName1?pName1:"(null)", index0, index1, gpGlobals->curtime, eventTime ); - } - else - { - DevMsg(1, "***Inter-penetration between %s(%s) AND %s(%s) (%.0f, %.0f)\n", pName1?pName1:"(null)", pEntity0->GetDebugName(), pName2?pName2:"(null)", pEntity1->GetDebugName(), gpGlobals->curtime, eventTime ); - } - } -#endif - - if ( eventTime > 3 ) - { - // don't report penetrations on ragdolls with themselves, or outside of developer mode - if ( g_pDeveloper->GetInt() && pEntity0 != pEntity1 ) - { - ReportPenetration( pEntity0, phys_penetration_error_time.GetFloat() ); - ReportPenetration( pEntity1, phys_penetration_error_time.GetFloat() ); - } - event.startTime = gpGlobals->curtime; - // don't put players or game physics controlled objects to sleep - if ( !pEntity0->IsPlayer() && !pEntity1->IsPlayer() && !pObj0->GetShadowController() && !pObj1->GetShadowController() ) - { - // two objects have been stuck for more than 3 seconds, try disabling simulation - event.collisionState = COLLSTATE_TRYDISABLE; - return false; - } - } - - - return true; -} - - -void CCollisionEvent::FluidStartTouch( IPhysicsObject *pObject, IPhysicsFluidController *pFluid ) -{ - CallbackContext check(this); - if ( ( pObject == NULL ) || ( pFluid == NULL ) ) - return; - - CBaseEntity *pEntity = static_cast(pObject->GetGameData()); - if ( !pEntity ) - return; - - pEntity->AddEFlags( EFL_TOUCHING_FLUID ); - pEntity->OnEntityEvent( ENTITY_EVENT_WATER_TOUCH, (void*)pFluid->GetContents() ); - - float timeSinceLastCollision = DeltaTimeSinceLastFluid( pEntity ); - if ( timeSinceLastCollision < 0.5f ) - return; - - // UNDONE: Use this for splash logic instead? - // UNDONE: Use angular term too - push splashes in rotAxs cross normal direction? - Vector normal; - float dist; - pFluid->GetSurfacePlane( &normal, &dist ); - Vector vel; - AngularImpulse angVel; - pObject->GetVelocity( &vel, &angVel ); - Vector unitVel = vel; - VectorNormalize( unitVel ); - - // normal points out of the surface, we want the direction that points in - float dragScale = pFluid->GetDensity() * physenv->GetSimulationTimestep(); - normal = -normal; - float linearScale = 0.5f * DotProduct( unitVel, normal ) * pObject->CalculateLinearDrag( normal ) * dragScale; - linearScale = clamp( linearScale, 0.0f, 1.0f ); - vel *= -linearScale; - - // UNDONE: Figure out how much of the surface area has crossed the water surface and scale angScale by that - // For now assume 25% - Vector rotAxis = angVel; - VectorNormalize(rotAxis); - float angScale = 0.25f * pObject->CalculateAngularDrag( angVel ) * dragScale; - angScale = clamp( angScale, 0.0f, 1.0f ); - angVel *= -angScale; - - // compute the splash before we modify the velocity - PhysicsSplash( pFluid, pObject, pEntity ); - - // now damp out some motion toward the surface - pObject->AddVelocity( &vel, &angVel ); -} - -void CCollisionEvent::FluidEndTouch( IPhysicsObject *pObject, IPhysicsFluidController *pFluid ) -{ - CallbackContext check(this); - if ( ( pObject == NULL ) || ( pFluid == NULL ) ) - return; - - CBaseEntity *pEntity = static_cast(pObject->GetGameData()); - if ( !pEntity ) - return; - - float timeSinceLastCollision = DeltaTimeSinceLastFluid( pEntity ); - if ( timeSinceLastCollision >= 0.5f ) - { - PhysicsSplash( pFluid, pObject, pEntity ); - } - - pEntity->RemoveEFlags( EFL_TOUCHING_FLUID ); - pEntity->OnEntityEvent( ENTITY_EVENT_WATER_UNTOUCH, (void*)pFluid->GetContents() ); -} - -class CSkipKeys : public IVPhysicsKeyHandler -{ -public: - virtual void ParseKeyValue( void *pData, const char *pKey, const char *pValue ) {} - virtual void SetDefaults( void *pData ) {} -}; - -void PhysSolidOverride( solid_t &solid, string_t overrideScript ) -{ - if ( overrideScript != NULL_STRING) - { - // parser destroys this data - bool collisions = solid.params.enableCollisions; - - char pTmpString[4096]; - - // write a header for a solid_t - Q_strncpy( pTmpString, "solid { ", sizeof(pTmpString) ); - - // suck out the comma delimited tokens and turn them into quoted key/values - char szToken[256]; - const char *pStr = nexttoken(szToken, STRING(overrideScript), ','); - while ( szToken[0] != 0 ) - { - Q_strncat( pTmpString, "\"", sizeof(pTmpString), COPY_ALL_CHARACTERS ); - Q_strncat( pTmpString, szToken, sizeof(pTmpString), COPY_ALL_CHARACTERS ); - Q_strncat( pTmpString, "\" ", sizeof(pTmpString), COPY_ALL_CHARACTERS ); - pStr = nexttoken(szToken, pStr, ','); - } - // terminate the script - Q_strncat( pTmpString, "}", sizeof(pTmpString), COPY_ALL_CHARACTERS ); - - // parse that sucker - IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pTmpString ); - CSkipKeys tmp; - pParse->ParseSolid( &solid, &tmp ); - physcollision->VPhysicsKeyParserDestroy( pParse ); - - // parser destroys this data - solid.params.enableCollisions = collisions; - } -} - -void PhysSetMassCenterOverride( masscenteroverride_t &override ) -{ - if ( override.entityName != NULL_STRING ) - { - g_PhysicsHook.m_massCenterOverrides.AddToTail( override ); - } -} - -// NOTE: This will remove the entry from the list as well -int PhysGetMassCenterOverrideIndex( string_t name ) -{ - if ( name != NULL_STRING && g_PhysicsHook.m_massCenterOverrides.Count() ) - { - for ( int i = 0; i < g_PhysicsHook.m_massCenterOverrides.Count(); i++ ) - { - if ( g_PhysicsHook.m_massCenterOverrides[i].entityName == name ) - { - return i; - } - } - } - return -1; -} - -void PhysGetMassCenterOverride( CBaseEntity *pEntity, vcollide_t *pCollide, solid_t &solidOut ) -{ - int index = PhysGetMassCenterOverrideIndex( pEntity->GetEntityName() ); - - if ( index >= 0 ) - { - masscenteroverride_t &override = g_PhysicsHook.m_massCenterOverrides[index]; - Vector massCenterWS = override.center; - switch ( override.alignType ) - { - case masscenteroverride_t::ALIGN_POINT: - VectorITransform( massCenterWS, pEntity->EntityToWorldTransform(), solidOut.massCenterOverride ); - break; - case masscenteroverride_t::ALIGN_AXIS: - { - Vector massCenterLocal, defaultMassCenterWS; - physcollision->CollideGetMassCenter( pCollide->solids[solidOut.index], &massCenterLocal ); - VectorTransform( massCenterLocal, pEntity->EntityToWorldTransform(), defaultMassCenterWS ); - massCenterWS += override.axis * - ( DotProduct(defaultMassCenterWS,override.axis) - DotProduct( override.axis, override.center ) ); - VectorITransform( massCenterWS, pEntity->EntityToWorldTransform(), solidOut.massCenterOverride ); - } - break; - } - g_PhysicsHook.m_massCenterOverrides.FastRemove( index ); - - if ( solidOut.massCenterOverride.Length() > DIST_EPSILON ) - { - solidOut.params.massCenterOverride = &solidOut.massCenterOverride; - } - } -} - -float PhysGetEntityMass( CBaseEntity *pEntity ) -{ - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int physCount = pEntity->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - float otherMass = 0; - for ( int i = 0; i < physCount; i++ ) - { - otherMass += pList[i]->GetMass(); - } - - return otherMass; -} - - -typedef void (*EntityCallbackFunction) ( CBaseEntity *pEntity ); - -void IterateActivePhysicsEntities( EntityCallbackFunction func ) -{ - int activeCount = physenv->GetActiveObjectCount(); - IPhysicsObject **pActiveList = NULL; - if ( activeCount ) - { - pActiveList = (IPhysicsObject **)stackalloc( sizeof(IPhysicsObject *)*activeCount ); - physenv->GetActiveObjects( pActiveList ); - for ( int i = 0; i < activeCount; i++ ) - { - CBaseEntity *pEntity = reinterpret_cast(pActiveList[i]->GetGameData()); - if ( pEntity ) - { - func( pEntity ); - } - } - } -} - - -static void CallbackHighlight( CBaseEntity *pEntity ) -{ - pEntity->m_debugOverlays |= OVERLAY_ABSBOX_BIT | OVERLAY_PIVOT_BIT; -} - -static void CallbackReport( CBaseEntity *pEntity ) -{ - const char *pName = STRING(pEntity->GetEntityName()); - if ( !Q_strlen(pName) ) - { - pName = STRING(pEntity->GetModelName()); - } - Msg( "%s - %s\n", pEntity->GetClassname(), pName ); -} - -CON_COMMAND(physics_highlight_active, "Turns on the absbox for all active physics objects") -{ - IterateActivePhysicsEntities( CallbackHighlight ); -} - -CON_COMMAND(physics_report_active, "Lists all active physics objects") -{ - IterateActivePhysicsEntities( CallbackReport ); -} - -CON_COMMAND_F(surfaceprop, "Reports the surface properties at the cursor", FCVAR_CHEAT ) -{ - CBasePlayer *pPlayer = UTIL_GetCommandClient(); - - trace_t tr; - Vector forward; - pPlayer->EyeVectors( &forward ); - UTIL_TraceLine(pPlayer->EyePosition(), pPlayer->EyePosition() + forward * MAX_COORD_RANGE, - MASK_SHOT_HULL|CONTENTS_GRATE|CONTENTS_DEBRIS, pPlayer, COLLISION_GROUP_NONE, &tr ); - - if ( tr.DidHit() ) - { - const model_t *pModel = modelinfo->GetModel( tr.m_pEnt->GetModelIndex() ); - const char *pModelName = STRING(tr.m_pEnt->GetModelName()); - if ( tr.DidHitWorld() && tr.hitbox > 0 ) - { - ICollideable *pCollide = staticpropmgr->GetStaticPropByIndex( tr.hitbox-1 ); - pModel = pCollide->GetCollisionModel(); - pModelName = modelinfo->GetModelName( pModel ); - } - CFmtStr modelStuff; - if ( pModel ) - { - modelStuff.sprintf("%s.%s ", modelinfo->IsTranslucent( pModel ) ? "Translucent" : "Opaque", - modelinfo->IsTranslucentTwoPass( pModel ) ? " Two-pass." : "" ); - } - - // Calculate distance to surface that was hit - Vector vecVelocity = tr.startpos - tr.endpos; - int length = (int)vecVelocity.Length(); - - Msg("Hit surface \"%s\" (entity %s, model \"%s\" %s), texture \"%s\"\n", physprops->GetPropName( tr.surface.surfaceProps ), tr.m_pEnt->GetClassname(), pModelName, modelStuff.Access(), tr.surface.name); - Msg("Distance to surface: %d\n", length ); - } -} - -static void OutputVPhysicsDebugInfo( CBaseEntity *pEntity ) -{ - if ( pEntity ) - { - Msg("Entity %s (%s) %s Collision Group %d\n", pEntity->GetClassname(), pEntity->GetDebugName(), pEntity->IsNavIgnored() ? "NAV IGNORE" : "", pEntity->GetCollisionGroup() ); - CUtlVector list; - g_Collisions.GetListOfPenetratingEntities( pEntity, list ); - for ( int i = 0; i < list.Count(); i++ ) - { - Msg(" penetration with entity %s (%s)\n", list[i]->GetDebugName(), STRING(list[i]->GetModelName()) ); - } - - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int physCount = pEntity->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - if ( physCount ) - { - if ( physCount > 1 ) - { - for ( int i = 0; i < physCount; i++ ) - { - Msg("Object %d (of %d) =========================\n", i+1, physCount ); - pList[i]->OutputDebugInfo(); - } - } - else - { - pList[0]->OutputDebugInfo(); - } - } - } -} - -class CConstraintFloodEntry -{ -public: - CConstraintFloodEntry() : isMarked(false), isConstraint(false) {} - - CUtlVector linkList; - bool isMarked; - bool isConstraint; -}; - -class CConstraintFloodList -{ -public: - CConstraintFloodList() - { - SetDefLessFunc( m_list ); - m_list.EnsureCapacity(64); - m_entryList.EnsureCapacity(64); - } - - bool IsWorldEntity( CBaseEntity *pEnt ) - { - if ( pEnt->edict() ) - return pEnt->IsWorld(); - return false; - } - - void AddLink( CBaseEntity *pEntity, CBaseEntity *pLink, bool bIsConstraint ) - { - if ( !pEntity || !pLink || IsWorldEntity(pEntity) || IsWorldEntity(pLink) ) - return; - int listIndex = m_list.Find(pEntity); - if ( listIndex == m_list.InvalidIndex() ) - { - int entryIndex = m_entryList.AddToTail(); - m_entryList[entryIndex].isConstraint = bIsConstraint; - listIndex = m_list.Insert( pEntity, entryIndex ); - } - int entryIndex = m_list.Element(listIndex); - CConstraintFloodEntry &entry = m_entryList.Element(entryIndex); - Assert( entry.isConstraint == bIsConstraint ); - if ( entry.linkList.Find(pLink) < 0 ) - { - entry.linkList.AddToTail( pLink ); - } - } - - void BuildGraphFromEntity( CBaseEntity *pEntity, CUtlVector &constraintList ) - { - int listIndex = m_list.Find(pEntity); - if ( listIndex != m_list.InvalidIndex() ) - { - int entryIndex = m_list.Element(listIndex); - CConstraintFloodEntry &entry = m_entryList.Element(entryIndex); - if ( !entry.isMarked ) - { - if ( entry.isConstraint ) - { - Assert( constraintList.Find(pEntity) < 0); - constraintList.AddToTail( pEntity ); - } - entry.isMarked = true; - for ( int i = 0; i < entry.linkList.Count(); i++ ) - { - // now recursively traverse the graph from here - BuildGraphFromEntity( entry.linkList[i], constraintList ); - } - } - } - } - CUtlMap m_list; - CUtlVector m_entryList; -}; - -// traverses the graph of attachments (currently supports springs & constraints) starting at an entity -// Then turns on debug info for each link in the graph (springs/constraints are links) -static void DebugConstraints( CBaseEntity *pEntity ) -{ - extern bool GetSpringAttachments( CBaseEntity *pEntity, CBaseEntity *pAttach[2], IPhysicsObject *pAttachVPhysics[2] ); - extern bool GetConstraintAttachments( CBaseEntity *pEntity, CBaseEntity *pAttach[2], IPhysicsObject *pAttachVPhysics[2] ); - extern void DebugConstraint(CBaseEntity *pEntity); - - if ( !pEntity ) - return; - - CBaseEntity *pAttach[2]; - IPhysicsObject *pAttachVPhysics[2]; - CConstraintFloodList list; - - for ( CBaseEntity *pList = gEntList.FirstEnt(); pList != NULL; pList = gEntList.NextEnt(pList) ) - { - if ( GetConstraintAttachments(pList, pAttach, pAttachVPhysics) || GetSpringAttachments(pList, pAttach, pAttachVPhysics) ) - { - list.AddLink( pList, pAttach[0], true ); - list.AddLink( pList, pAttach[1], true ); - list.AddLink( pAttach[0], pList, false ); - list.AddLink( pAttach[1], pList, false ); - } - } - - CUtlVector constraints; - list.BuildGraphFromEntity( pEntity, constraints ); - for ( int i = 0; i < constraints.Count(); i++ ) - { - if ( !GetConstraintAttachments(constraints[i], pAttach, pAttachVPhysics) ) - { - GetSpringAttachments(constraints[i], pAttach, pAttachVPhysics); - } - const char *pName0 = "world"; - const char *pName1 = "world"; - const char *pModel0 = ""; - const char *pModel1 = ""; - int index0 = 0; - int index1 = 0; - if ( pAttach[0] ) - { - pName0 = pAttach[0]->GetClassname(); - pModel0 = STRING(pAttach[0]->GetModelName()); - index0 = pAttachVPhysics[0]->GetGameIndex(); - } - if ( pAttach[1] ) - { - pName1 = pAttach[1]->GetClassname(); - pModel1 = STRING(pAttach[1]->GetModelName()); - index1 = pAttachVPhysics[1]->GetGameIndex(); - } - Msg("**********************\n%s connects %s(%s:%d) to %s(%s:%d)\n", constraints[i]->GetClassname(), pName0, pModel0, index0, pName1, pModel1, index1 ); - DebugConstraint(constraints[i]); - constraints[i]->m_debugOverlays |= OVERLAY_BBOX_BIT | OVERLAY_TEXT_BIT; - } -} - -static void MarkVPhysicsDebug( CBaseEntity *pEntity ) -{ - if ( pEntity ) - { - IPhysicsObject *pPhysics = pEntity->VPhysicsGetObject(); - if ( pPhysics ) - { - unsigned short callbacks = pPhysics->GetCallbackFlags(); - callbacks ^= CALLBACK_MARKED_FOR_TEST; - pPhysics->SetCallbackFlags( callbacks ); - } - } -} - -void PhysicsCommand( const CCommand &args, void (*func)( CBaseEntity *pEntity ) ) -{ - if ( args.ArgC() < 2 ) - { - CBasePlayer *pPlayer = UTIL_GetCommandClient(); - - trace_t tr; - Vector forward; - pPlayer->EyeVectors( &forward ); - UTIL_TraceLine(pPlayer->EyePosition(), pPlayer->EyePosition() + forward * MAX_COORD_RANGE, - MASK_SHOT_HULL|CONTENTS_GRATE|CONTENTS_DEBRIS, pPlayer, COLLISION_GROUP_NONE, &tr ); - - if ( tr.DidHit() ) - { - func( tr.m_pEnt ); - } - } - else - { - CBaseEntity *pEnt = NULL; - while ( ( pEnt = gEntList.FindEntityGeneric( pEnt, args[1] ) ) != NULL ) - { - func( pEnt ); - } - } -} - -CON_COMMAND(physics_constraints, "Highlights constraint system graph for an entity") -{ - PhysicsCommand( args, DebugConstraints ); -} - -CON_COMMAND(physics_debug_entity, "Dumps debug info for an entity") -{ - PhysicsCommand( args, OutputVPhysicsDebugInfo ); -} - -CON_COMMAND(physics_select, "Dumps debug info for an entity") -{ - PhysicsCommand( args, MarkVPhysicsDebug ); -} - -CON_COMMAND( physics_budget, "Times the cost of each active object" ) -{ - int activeCount = physenv->GetActiveObjectCount(); - - IPhysicsObject **pActiveList = NULL; - CUtlVector ents; - if ( activeCount ) - { - int i; - - pActiveList = (IPhysicsObject **)stackalloc( sizeof(IPhysicsObject *)*activeCount ); - physenv->GetActiveObjects( pActiveList ); - for ( i = 0; i < activeCount; i++ ) - { - CBaseEntity *pEntity = reinterpret_cast(pActiveList[i]->GetGameData()); - if ( pEntity ) - { - int index = -1; - for ( int j = 0; j < ents.Count(); j++ ) - { - if ( pEntity == ents[j] ) - { - index = j; - break; - } - } - if ( index >= 0 ) - continue; - - ents.AddToTail( pEntity ); - } - } - stackfree( pActiveList ); - - if ( !ents.Count() ) - return; - - CUtlVector times; - float totalTime = 0.f; - g_Collisions.BufferTouchEvents( true ); - float full = engine->Time(); - physenv->Simulate( DEFAULT_TICK_INTERVAL ); - full = engine->Time() - full; - float lastTime = full; - - times.SetSize( ents.Count() ); - - - // NOTE: This is just a heuristic. Attempt to estimate cost by putting each object to sleep in turn. - // note that simulation may wake the objects again and some costs scale with sets of objects/constraints/etc - // so these are only generally useful for broad questions, not real metrics! - for ( i = 0; i < ents.Count(); i++ ) - { - for ( int j = 0; j < i; j++ ) - { - PhysForceEntityToSleep( ents[j], ents[j]->VPhysicsGetObject() ); - } - float start = engine->Time(); - physenv->Simulate( DEFAULT_TICK_INTERVAL ); - float end = engine->Time(); - - float elapsed = end - start; - float avgTime = lastTime - elapsed; - times[i] = clamp( avgTime, 0.00001f, 1.0f ); - totalTime += times[i]; - lastTime = elapsed; - } - - totalTime = MAX( totalTime, 0.001 ); - for ( i = 0; i < ents.Count(); i++ ) - { - float fraction = times[i] / totalTime; - Msg( "%s (%s): %.3fms (%.3f%%) @ %s\n", ents[i]->GetClassname(), ents[i]->GetDebugName(), fraction * totalTime * 1000.0f, fraction * 100.0f, VecToString(ents[i]->GetAbsOrigin()) ); - } - g_Collisions.BufferTouchEvents( false ); - } - -} - - -#ifdef PORTAL -ConVar sv_fullsyncclones("sv_fullsyncclones", "1", FCVAR_CHEAT ); -void PortalPhysFrame( float deltaTime ) //small wrapper for PhysFrame that simulates all environments at once -{ - CPortalSimulator::PrePhysFrame(); - - if( sv_fullsyncclones.GetBool() ) - CPhysicsShadowClone::FullSyncAllClones(); - - g_Collisions.BufferTouchEvents( true ); - - PhysFrame( deltaTime ); - - g_Collisions.PortalPostSimulationFrame(); - - g_Collisions.BufferTouchEvents( false ); - g_Collisions.FrameUpdate(); - - CPortalSimulator::PostPhysFrame(); -} -#endif - -// Advance physics by time (in seconds) -void PhysFrame( float deltaTime ) -{ - static int lastObjectCount = 0; - entitem_t *pItem; - - if ( !g_PhysicsHook.ShouldSimulate() ) - return; - - // Trap interrupts and clock changes - if ( deltaTime > 1.0f || deltaTime < 0.0f ) - { - deltaTime = 0; - Msg( "Reset physics clock\n" ); - } - else if ( deltaTime > 0.1f ) // limit incoming time to 100ms - { - deltaTime = 0.1f; - } - float simRealTime = 0; - - deltaTime *= phys_timescale.GetFloat(); - // !!!HACKHACK -- hard limit scaled time to avoid spending too much time in here - // Limit to 100 ms - if ( deltaTime > 0.100f ) - deltaTime = 0.100f; - - bool bProfile = phys_speeds.GetBool(); - - if ( bProfile ) - { - simRealTime = engine->Time(); - } - -#ifdef _DEBUG - physenv->DebugCheckContacts(); -#endif - -#ifndef PORTAL //instead of wrapping 1 simulation with this, portal needs to wrap 3 - g_Collisions.BufferTouchEvents( true ); -#endif - - physenv->Simulate( deltaTime ); - - int activeCount = physenv->GetActiveObjectCount(); - IPhysicsObject **pActiveList = NULL; - if ( activeCount ) - { - pActiveList = (IPhysicsObject **)stackalloc( sizeof(IPhysicsObject *)*activeCount ); - physenv->GetActiveObjects( pActiveList ); - - for ( int i = 0; i < activeCount; i++ ) - { - CBaseEntity *pEntity = reinterpret_cast(pActiveList[i]->GetGameData()); - if ( pEntity ) - { - if ( pEntity->CollisionProp()->DoesVPhysicsInvalidateSurroundingBox() ) - { - pEntity->CollisionProp()->MarkSurroundingBoundsDirty(); - } - pEntity->VPhysicsUpdate( pActiveList[i] ); - } - } - stackfree( pActiveList ); - } - - for ( pItem = g_pShadowEntities->m_pItemList; pItem; pItem = pItem->pNext ) - { - CBaseEntity *pEntity = pItem->hEnt.Get(); - if ( !pEntity ) - { - Msg( "Dangling pointer to physics entity!!!\n" ); - continue; - } - - IPhysicsObject *pPhysics = pEntity->VPhysicsGetObject(); - // apply updates - if ( pPhysics && !pPhysics->IsAsleep() ) - { - pEntity->VPhysicsShadowUpdate( pPhysics ); - } - } - - if ( bProfile ) - { - simRealTime = engine->Time() - simRealTime; - - if ( simRealTime < 0 ) - simRealTime = 0; - g_PhysAverageSimTime *= 0.8; - g_PhysAverageSimTime += (simRealTime * 0.2); - if ( lastObjectCount != 0 || activeCount != 0 ) - { - Msg( "Physics: %3d objects, %4.1fms / AVG: %4.1fms\n", activeCount, simRealTime * 1000, g_PhysAverageSimTime * 1000 ); - } - - lastObjectCount = activeCount; - } - -#ifndef PORTAL //instead of wrapping 1 simulation with this, portal needs to wrap 3 - g_Collisions.BufferTouchEvents( false ); - g_Collisions.FrameUpdate(); -#endif -} - - -void PhysAddShadow( CBaseEntity *pEntity ) -{ - g_pShadowEntities->AddEntity( pEntity ); -} - -void PhysRemoveShadow( CBaseEntity *pEntity ) -{ - g_pShadowEntities->DeleteEntity( pEntity ); -} - -bool PhysHasShadow( CBaseEntity *pEntity ) -{ - EHANDLE hTestEnt = pEntity; - entitem_t *pCurrent = g_pShadowEntities->m_pItemList; - while( pCurrent ) - { - if( pCurrent->hEnt == hTestEnt ) - { - return true; - } - pCurrent = pCurrent->pNext; - } - return false; -} - -void PhysEnableFloating( IPhysicsObject *pObject, bool bEnable ) -{ - if ( pObject != NULL ) - { - unsigned short flags = pObject->GetCallbackFlags(); - if ( bEnable ) - { - flags |= CALLBACK_DO_FLUID_SIMULATION; - } - else - { - flags &= ~CALLBACK_DO_FLUID_SIMULATION; - } - pObject->SetCallbackFlags( flags ); - } -} - - -//----------------------------------------------------------------------------- -// CollisionEvent system -//----------------------------------------------------------------------------- -// NOTE: PreCollision/PostCollision ALWAYS come in matched pairs!!! -void CCollisionEvent::PreCollision( vcollisionevent_t *pEvent ) -{ - CallbackContext check(this); - m_gameEvent.Init( pEvent ); - - // gather the pre-collision data that the game needs to track - for ( int i = 0; i < 2; i++ ) - { - IPhysicsObject *pObject = pEvent->pObjects[i]; - if ( pObject ) - { - if ( pObject->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - { - CBaseEntity *pOtherEntity = reinterpret_cast(pEvent->pObjects[!i]->GetGameData()); - if ( pOtherEntity && !pOtherEntity->IsPlayer() ) - { - Vector velocity; - AngularImpulse angVel; - // HACKHACK: If we totally clear this out, then Havok will think the objects - // are penetrating and generate forces to separate them - // so make it fairly small and have a tiny collision instead. - pObject->GetVelocity( &velocity, &angVel ); - float len = VectorNormalize(velocity); - len = MAX( len, 10 ); - velocity *= len; - len = VectorNormalize(angVel); - len = MAX( len, 1 ); - angVel *= len; - pObject->SetVelocity( &velocity, &angVel ); - } - } - pObject->GetVelocity( &m_gameEvent.preVelocity[i], &m_gameEvent.preAngularVelocity[i] ); - } - } -} - -void CCollisionEvent::PostCollision( vcollisionevent_t *pEvent ) -{ - CallbackContext check(this); - bool isShadow[2] = {false,false}; - int i; - - for ( i = 0; i < 2; i++ ) - { - IPhysicsObject *pObject = pEvent->pObjects[i]; - if ( pObject ) - { - CBaseEntity *pEntity = reinterpret_cast(pObject->GetGameData()); - if ( !pEntity ) - return; - - // UNDONE: This is here to trap crashes due to NULLing out the game data on delete - m_gameEvent.pEntities[i] = pEntity; - unsigned int flags = pObject->GetCallbackFlags(); - pObject->GetVelocity( &m_gameEvent.postVelocity[i], NULL ); - if ( flags & CALLBACK_SHADOW_COLLISION ) - { - isShadow[i] = true; - } - - // Shouldn't get impacts with triggers - Assert( !pObject->IsTrigger() ); - } - } - - // copy off the post-collision variable data - m_gameEvent.collisionSpeed = pEvent->collisionSpeed; - m_gameEvent.pInternalData = pEvent->pInternalData; - - // special case for hitting self, only make one non-shadow call - if ( m_gameEvent.pEntities[0] == m_gameEvent.pEntities[1] ) - { - if ( pEvent->isCollision && m_gameEvent.pEntities[0] ) - { - m_gameEvent.pEntities[0]->VPhysicsCollision( 0, &m_gameEvent ); - } - return; - } - - if ( isShadow[0] && isShadow[1] ) - { - pEvent->isCollision = false; - } - - for ( i = 0; i < 2; i++ ) - { - if ( pEvent->isCollision ) - { - m_gameEvent.pEntities[i]->VPhysicsCollision( i, &m_gameEvent ); - } - if ( pEvent->isShadowCollision && isShadow[i] ) - { - m_gameEvent.pEntities[i]->VPhysicsShadowCollision( i, &m_gameEvent ); - } - } -} - -void PhysForceEntityToSleep( CBaseEntity *pEntity, IPhysicsObject *pObject ) -{ - // UNDONE: Check to see if the object is touching the player first? - // Might get the player stuck? - if ( !pObject || !pObject->IsMoveable() ) - return; - - DevMsg(2, "Putting entity to sleep: %s\n", pEntity->GetClassname() ); - MEM_ALLOC_CREDIT(); - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int physCount = pEntity->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - for ( int i = 0; i < physCount; i++ ) - { - PhysForceClearVelocity( pList[i] ); - pList[i]->Sleep(); - } -} - -void CCollisionEvent::Friction( IPhysicsObject *pObject, float energy, int surfaceProps, int surfacePropsHit, IPhysicsCollisionData *pData ) -{ - CallbackContext check(this); - //Get our friction information - Vector vecPos, vecVel; - pData->GetContactPoint( vecPos ); - pObject->GetVelocityAtPoint( vecPos, &vecVel ); - - CBaseEntity *pEntity = reinterpret_cast(pObject->GetGameData()); - - if ( pEntity ) - { - friction_t *pFriction = g_Collisions.FindFriction( pEntity ); - - if ( pFriction && pFriction->pObject) - { - // in MP mode play sound and effects once every 500 msecs, - // no ongoing updates, takes too much bandwidth - if ( (pFriction->flLastEffectTime + 0.5f) > gpGlobals->curtime) - { - pFriction->flLastUpdateTime = gpGlobals->curtime; - return; - } - } - - pEntity->VPhysicsFriction( pObject, energy, surfaceProps, surfacePropsHit ); - } - - PhysFrictionEffect( vecPos, vecVel, energy, surfaceProps, surfacePropsHit ); -} - - -friction_t *CCollisionEvent::FindFriction( CBaseEntity *pObject ) -{ - friction_t *pFree = NULL; - - for ( size_t i = 0; i < ARRAYSIZE(m_current); i++ ) - { - if ( !m_current[i].pObject && !pFree ) - pFree = &m_current[i]; - - if ( m_current[i].pObject == pObject ) - return &m_current[i]; - } - - return pFree; -} - -void CCollisionEvent::ShutdownFriction( friction_t &friction ) -{ -// Msg( "Scrape Stop %s \n", STRING(friction.pObject->m_iClassname) ); - CSoundEnvelopeController::GetController().SoundDestroy( friction.patch ); - friction.patch = NULL; - friction.pObject = NULL; -} - -void CCollisionEvent::UpdateRemoveObjects() -{ - Assert(!PhysIsInCallback()); - for ( int i = 0 ; i < m_removeObjects.Count(); i++ ) - { - UTIL_Remove(m_removeObjects[i]); - } - m_removeObjects.RemoveAll(); -} - -void CCollisionEvent::PostSimulationFrame() -{ - UpdateDamageEvents(); - g_PostSimulationQueue.CallQueued(); - UpdateRemoveObjects(); -} - -void CCollisionEvent::FlushQueuedOperations() -{ - int loopCount = 0; - while ( loopCount < 20 ) - { - int count = m_triggerEvents.Count() + m_touchEvents.Count() + m_damageEvents.Count() + m_removeObjects.Count() + g_PostSimulationQueue.Count(); - if ( !count ) - break; - // testing, if this assert fires it proves we've fixed the crash - // after that the assert + warning can safely be removed - Assert(0); - Warning("Physics queue not empty, error!\n"); - loopCount++; - UpdateTouchEvents(); - UpdateDamageEvents(); - g_PostSimulationQueue.CallQueued(); - UpdateRemoveObjects(); - } -} - -void CCollisionEvent::FrameUpdate( void ) -{ - UpdateFrictionSounds(); - UpdateTouchEvents(); - UpdatePenetrateEvents(); - UpdateFluidEvents(); - UpdateDamageEvents(); // if there was no PSI in physics, we'll still need to do some of these because collisions are solved in between PSIs - g_PostSimulationQueue.CallQueued(); - UpdateRemoveObjects(); - - // There are some queued operations that must complete each frame, iterate until these are done - FlushQueuedOperations(); -} - -// the delete list is getting flushed, clean up ours -void PhysOnCleanupDeleteList() -{ - g_Collisions.FlushQueuedOperations(); - if ( physenv ) - { - physenv->CleanupDeleteList(); - } -} - -void CCollisionEvent::UpdateFluidEvents( void ) -{ - for ( int i = m_fluidEvents.Count()-1; i >= 0; --i ) - { - if ( (gpGlobals->curtime - m_fluidEvents[i].impactTime) > FLUID_TIME_MAX ) - { - m_fluidEvents.FastRemove(i); - } - } -} - - -float CCollisionEvent::DeltaTimeSinceLastFluid( CBaseEntity *pEntity ) -{ - for ( int i = m_fluidEvents.Count()-1; i >= 0; --i ) - { - if ( m_fluidEvents[i].hEntity.Get() == pEntity ) - { - return gpGlobals->curtime - m_fluidEvents[i].impactTime; - } - } - - int index = m_fluidEvents.AddToTail(); - m_fluidEvents[index].hEntity = pEntity; - m_fluidEvents[index].impactTime = gpGlobals->curtime; - return FLUID_TIME_MAX; -} - -void CCollisionEvent::UpdateFrictionSounds( void ) -{ - for ( size_t i = 0; i < ARRAYSIZE(m_current); i++ ) - { - if ( m_current[i].patch ) - { - if ( m_current[i].flLastUpdateTime < (gpGlobals->curtime-0.1f) ) - { - // friction wasn't updated the last 100msec, assume fiction finished - ShutdownFriction( m_current[i] ); - } - } - } -} - - -void CCollisionEvent::DispatchStartTouch( CBaseEntity *pEntity0, CBaseEntity *pEntity1, const Vector &point, const Vector &normal ) -{ - trace_t trace; - memset( &trace, 0, sizeof(trace) ); - trace.endpos = point; - trace.plane.dist = DotProduct( point, normal ); - trace.plane.normal = normal; - - // NOTE: This sets up the touch list for both entities, no call to pEntity1 is needed - pEntity0->PhysicsMarkEntitiesAsTouchingEventDriven( pEntity1, trace ); -} - -void CCollisionEvent::DispatchEndTouch( CBaseEntity *pEntity0, CBaseEntity *pEntity1 ) -{ - // frees the event-driven touchlinks - pEntity0->PhysicsNotifyOtherOfUntouch( pEntity0, pEntity1 ); - pEntity1->PhysicsNotifyOtherOfUntouch( pEntity1, pEntity0 ); -} - -void CCollisionEvent::UpdateTouchEvents( void ) -{ - int i; - // Turn on buffering in case new touch events occur during processing - bool bOldTouchEvents = m_bBufferTouchEvents; - m_bBufferTouchEvents = true; - for ( i = 0; i < m_touchEvents.Count(); i++ ) - { - const touchevent_t &event = m_touchEvents[i]; - if ( event.touchType == TOUCH_START ) - { - DispatchStartTouch( event.pEntity0, event.pEntity1, event.endPoint, event.normal ); - } - else - { - // TOUCH_END - DispatchEndTouch( event.pEntity0, event.pEntity1 ); - } - } - m_touchEvents.RemoveAll(); - - for ( i = 0; i < m_triggerEvents.Count(); i++ ) - { - m_currentTriggerEvent = m_triggerEvents[i]; - if ( m_currentTriggerEvent.bStart ) - { - m_currentTriggerEvent.pTriggerEntity->StartTouch( m_currentTriggerEvent.pEntity ); - } - else - { - m_currentTriggerEvent.pTriggerEntity->EndTouch( m_currentTriggerEvent.pEntity ); - } - } - m_triggerEvents.RemoveAll(); - m_currentTriggerEvent.Clear(); - m_bBufferTouchEvents = bOldTouchEvents; -} - -void CCollisionEvent::UpdateDamageEvents( void ) -{ - for ( int i = 0; i < m_damageEvents.Count(); i++ ) - { - damageevent_t &event = m_damageEvents[i]; - - // Track changes in the entity's life state - int iEntBits = event.pEntity->IsAlive() ? 0x0001 : 0; - iEntBits |= event.pEntity->IsMarkedForDeletion() ? 0x0002 : 0; - iEntBits |= (event.pEntity->GetSolidFlags() & FSOLID_NOT_SOLID) ? 0x0004 : 0; -#if 0 - // Go ahead and compute the current static stress when hit by a large object (with a force high enough to do damage). - // That way you die from the impact rather than the stress of the object resting on you whenever possible. - // This makes the damage effects cleaner. - if ( event.pInflictorPhysics && event.pInflictorPhysics->GetMass() > VPHYSICS_LARGE_OBJECT_MASS ) - { - CBaseCombatCharacter *pCombat = event.pEntity->MyCombatCharacterPointer(); - if ( pCombat ) - { - vphysics_objectstress_t stressOut; - event.info.AddDamage( pCombat->CalculatePhysicsStressDamage( &stressOut, pCombat->VPhysicsGetObject() ) ); - } - } -#endif - - event.pEntity->TakeDamage( event.info ); - int iEntBits2 = event.pEntity->IsAlive() ? 0x0001 : 0; - iEntBits2 |= event.pEntity->IsMarkedForDeletion() ? 0x0002 : 0; - iEntBits2 |= (event.pEntity->GetSolidFlags() & FSOLID_NOT_SOLID) ? 0x0004 : 0; - - if ( event.bRestoreVelocity && iEntBits != iEntBits2 ) - { - // UNDONE: Use ratio of masses to blend in a little of the collision response? - // UNDONE: Damage for future events is already computed - it would be nice to - // go back and recompute it now that the values have - // been adjusted - RestoreDamageInflictorState( event.pInflictorPhysics ); - } - } - m_damageEvents.RemoveAll(); - m_damageInflictors.RemoveAll(); -} - -void CCollisionEvent::RestoreDamageInflictorState( int inflictorStateIndex, float velocityBlend ) -{ - inflictorstate_t &state = m_damageInflictors[inflictorStateIndex]; - if ( state.restored ) - return; - - // so we only restore this guy once - state.restored = true; - - if ( velocityBlend > 0 ) - { - Vector velocity; - AngularImpulse angVel; - state.pInflictorPhysics->GetVelocity( &velocity, &angVel ); - state.savedVelocity = state.savedVelocity*velocityBlend + velocity*(1-velocityBlend); - state.savedAngularVelocity = state.savedAngularVelocity*velocityBlend + angVel*(1-velocityBlend); - state.pInflictorPhysics->SetVelocity( &state.savedVelocity, &state.savedAngularVelocity ); - } - - if ( state.nextIndex >= 0 ) - { - RestoreDamageInflictorState( state.nextIndex, velocityBlend ); - } -} - -void CCollisionEvent::RestoreDamageInflictorState( IPhysicsObject *pInflictor ) -{ - if ( !pInflictor ) - return; - - int index = FindDamageInflictor( pInflictor ); - if ( index >= 0 ) - { - inflictorstate_t &state = m_damageInflictors[index]; - if ( !state.restored ) - { - float velocityBlend = 1.0; - float inflictorMass = state.pInflictorPhysics->GetMass(); - if ( inflictorMass < VPHYSICS_LARGE_OBJECT_MASS && !(state.pInflictorPhysics->GetGameFlags() & FVPHYSICS_DMG_SLICE) ) - { - float otherMass = state.otherMassMax > 0 ? state.otherMassMax : 1; - float massRatio = inflictorMass / otherMass; - massRatio = clamp( massRatio, 0.1f, 10.0f ); - if ( massRatio < 1 ) - { - velocityBlend = RemapVal( massRatio, 0.1, 1, 0, 0.5 ); - } - else - { - velocityBlend = RemapVal( massRatio, 1.0, 10, 0.5, 1 ); - } - } - RestoreDamageInflictorState( index, velocityBlend ); - } - } -} - -bool CCollisionEvent::GetInflictorVelocity( IPhysicsObject *pInflictor, Vector &velocity, AngularImpulse &angVelocity ) -{ - int index = FindDamageInflictor( pInflictor ); - if ( index >= 0 ) - { - inflictorstate_t &state = m_damageInflictors[index]; - velocity = state.savedVelocity; - angVelocity = state.savedAngularVelocity; - return true; - } - - return false; -} - -bool PhysGetDamageInflictorVelocityStartOfFrame( IPhysicsObject *pInflictor, Vector &velocity, AngularImpulse &angVelocity ) -{ - return g_Collisions.GetInflictorVelocity( pInflictor, velocity, angVelocity ); -} - -void CCollisionEvent::AddTouchEvent( CBaseEntity *pEntity0, CBaseEntity *pEntity1, int touchType, const Vector &point, const Vector &normal ) -{ - if ( !pEntity0 || !pEntity1 ) - return; - - int index = m_touchEvents.AddToTail(); - touchevent_t &event = m_touchEvents[index]; - event.pEntity0 = pEntity0; - event.pEntity1 = pEntity1; - event.touchType = touchType; - event.endPoint = point; - event.normal = normal; -} - -void CCollisionEvent::AddDamageEvent( CBaseEntity *pEntity, const CTakeDamageInfo &info, IPhysicsObject *pInflictorPhysics, bool bRestoreVelocity, const Vector &savedVel, const AngularImpulse &savedAngVel ) -{ - if ( pEntity->IsMarkedForDeletion() ) - return; - - int iTimeBasedDamage = g_pGameRules->Damage_GetTimeBased(); - if ( !( info.GetDamageType() & (DMG_BURN | DMG_DROWN | iTimeBasedDamage | DMG_PREVENT_PHYSICS_FORCE) ) ) - { - Assert( info.GetDamageForce() != vec3_origin && info.GetDamagePosition() != vec3_origin ); - } - - int index = m_damageEvents.AddToTail(); - damageevent_t &event = m_damageEvents[index]; - event.pEntity = pEntity; - event.info = info; - event.pInflictorPhysics = pInflictorPhysics; - event.bRestoreVelocity = bRestoreVelocity; - if ( !pInflictorPhysics || !pInflictorPhysics->IsMoveable() ) - { - event.bRestoreVelocity = false; - } - - if ( event.bRestoreVelocity ) - { - float otherMass = pEntity->VPhysicsGetObject()->GetMass(); - int inflictorIndex = FindDamageInflictor(pInflictorPhysics); - if ( inflictorIndex >= 0 ) - { - // if this is a bigger mass, save that info - inflictorstate_t &state = m_damageInflictors[inflictorIndex]; - if ( otherMass > state.otherMassMax ) - { - state.otherMassMax = otherMass; - } - - } - else - { - AddDamageInflictor( pInflictorPhysics, otherMass, savedVel, savedAngVel, true ); - } - } - -} - -//----------------------------------------------------------------------------- -// Impulse events -//----------------------------------------------------------------------------- -static void PostSimulation_ImpulseEvent( IPhysicsObject *pObject, const Vector ¢erForce, const AngularImpulse ¢erTorque ) -{ - pObject->ApplyForceCenter( centerForce ); - pObject->ApplyTorqueCenter( centerTorque ); -} - -void PostSimulation_SetVelocityEvent( IPhysicsObject *pPhysicsObject, const Vector &vecVelocity ) -{ - pPhysicsObject->SetVelocity( &vecVelocity, NULL ); -} - -void CCollisionEvent::AddRemoveObject(IServerNetworkable *pRemove) -{ - if ( pRemove && m_removeObjects.Find(pRemove) == -1 ) - { - m_removeObjects.AddToTail(pRemove); - } -} -int CCollisionEvent::FindDamageInflictor( IPhysicsObject *pInflictorPhysics ) -{ - // UNDONE: Linear search? Probably ok with a low count here - for ( int i = m_damageInflictors.Count()-1; i >= 0; --i ) - { - const inflictorstate_t &state = m_damageInflictors[i]; - if ( state.pInflictorPhysics == pInflictorPhysics ) - return i; - } - - return -1; -} - - -int CCollisionEvent::AddDamageInflictor( IPhysicsObject *pInflictorPhysics, float otherMass, const Vector &savedVel, const AngularImpulse &savedAngVel, bool addList ) -{ - // NOTE: Save off the state of the object before collision - // restore if the impact is a kill - // UNDONE: Should we absorb some energy here? - // NOTE: we can't save a delta because there could be subsequent post-fatal collisions - - int addIndex = m_damageInflictors.AddToTail(); - { - inflictorstate_t &state = m_damageInflictors[addIndex]; - state.pInflictorPhysics = pInflictorPhysics; - state.savedVelocity = savedVel; - state.savedAngularVelocity = savedAngVel; - state.otherMassMax = otherMass; - state.restored = false; - state.nextIndex = -1; - } - - if ( addList ) - { - CBaseEntity *pEntity = static_cast(pInflictorPhysics->GetGameData()); - if ( pEntity ) - { - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int physCount = pEntity->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - if ( physCount > 1 ) - { - int currentIndex = addIndex; - for ( int i = 0; i < physCount; i++ ) - { - if ( pList[i] != pInflictorPhysics ) - { - Vector vel; - AngularImpulse angVel; - pList[i]->GetVelocity( &vel, &angVel ); - int next = AddDamageInflictor( pList[i], otherMass, vel, angVel, false ); - m_damageInflictors[currentIndex].nextIndex = next; - currentIndex = next; - } - } - } - } - } - return addIndex; -} - - -void CCollisionEvent::LevelShutdown( void ) -{ - for ( size_t i = 0; i < ARRAYSIZE(m_current); i++ ) - { - if ( m_current[i].patch ) - { - ShutdownFriction( m_current[i] ); - } - } -} - - -void CCollisionEvent::StartTouch( IPhysicsObject *pObject1, IPhysicsObject *pObject2, IPhysicsCollisionData *pTouchData ) -{ - CallbackContext check(this); - CBaseEntity *pEntity1 = static_cast(pObject1->GetGameData()); - CBaseEntity *pEntity2 = static_cast(pObject2->GetGameData()); - - if ( !pEntity1 || !pEntity2 ) - return; - - Vector endPoint, normal; - pTouchData->GetContactPoint( endPoint ); - pTouchData->GetSurfaceNormal( normal ); - if ( !m_bBufferTouchEvents ) - { - DispatchStartTouch( pEntity1, pEntity2, endPoint, normal ); - } - else - { - AddTouchEvent( pEntity1, pEntity2, TOUCH_START, endPoint, normal ); - } -} - -static int CountPhysicsObjectEntityContacts( IPhysicsObject *pObject, CBaseEntity *pEntity ) -{ - IPhysicsFrictionSnapshot *pSnapshot = pObject->CreateFrictionSnapshot(); - int count = 0; - while ( pSnapshot->IsValid() ) - { - IPhysicsObject *pOther = pSnapshot->GetObject(1); - CBaseEntity *pOtherEntity = static_cast(pOther->GetGameData()); - if ( pOtherEntity == pEntity ) - count++; - pSnapshot->NextFrictionData(); - } - pObject->DestroyFrictionSnapshot( pSnapshot ); - return count; -} - -void CCollisionEvent::EndTouch( IPhysicsObject *pObject1, IPhysicsObject *pObject2, IPhysicsCollisionData *pTouchData ) -{ - CallbackContext check(this); - CBaseEntity *pEntity1 = static_cast(pObject1->GetGameData()); - CBaseEntity *pEntity2 = static_cast(pObject2->GetGameData()); - - if ( !pEntity1 || !pEntity2 ) - return; - - // contact point deleted, but entities are still touching? - IPhysicsObject *list[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int count = pEntity1->VPhysicsGetObjectList( list, ARRAYSIZE(list) ); - - int contactCount = 0; - for ( int i = 0; i < count; i++ ) - { - contactCount += CountPhysicsObjectEntityContacts( list[i], pEntity2 ); - - // still touching - if ( contactCount > 1 ) - return; - } - - // should have exactly one contact point (the one getting deleted here) - //Assert( contactCount == 1 ); - - Vector endPoint, normal; - pTouchData->GetContactPoint( endPoint ); - pTouchData->GetSurfaceNormal( normal ); - - if ( !m_bBufferTouchEvents ) - { - DispatchEndTouch( pEntity1, pEntity2 ); - } - else - { - AddTouchEvent( pEntity1, pEntity2, TOUCH_END, vec3_origin, vec3_origin ); - } -} - -// UNDONE: This is functional, but minimally. -void CCollisionEvent::ObjectEnterTrigger( IPhysicsObject *pTrigger, IPhysicsObject *pObject ) -{ - CBaseEntity *pTriggerEntity = static_cast(pTrigger->GetGameData()); - CBaseEntity *pEntity = static_cast(pObject->GetGameData()); - if ( pTriggerEntity && pEntity ) - { - // UNDONE: Don't buffer these until we can solve generating touches at object creation time - if ( 0 && m_bBufferTouchEvents ) - { - int index = m_triggerEvents.AddToTail(); - m_triggerEvents[index].Init( pTriggerEntity, pTrigger, pEntity, pObject, true ); - } - else - { - CallbackContext check(this); - m_currentTriggerEvent.Init( pTriggerEntity, pTrigger, pEntity, pObject, true ); - pTriggerEntity->StartTouch( pEntity ); - m_currentTriggerEvent.Clear(); - } - } -} - -void CCollisionEvent::ObjectLeaveTrigger( IPhysicsObject *pTrigger, IPhysicsObject *pObject ) -{ - CBaseEntity *pTriggerEntity = static_cast(pTrigger->GetGameData()); - CBaseEntity *pEntity = static_cast(pObject->GetGameData()); - if ( pTriggerEntity && pEntity ) - { - // UNDONE: Don't buffer these until we can solve generating touches at object creation time - if ( 0 && m_bBufferTouchEvents ) - { - int index = m_triggerEvents.AddToTail(); - m_triggerEvents[index].Init( pTriggerEntity, pTrigger, pEntity, pObject, false ); - } - else - { - CallbackContext check(this); - m_currentTriggerEvent.Init( pTriggerEntity, pTrigger, pEntity, pObject, false ); - pTriggerEntity->EndTouch( pEntity ); - m_currentTriggerEvent.Clear(); - } - } -} - -bool CCollisionEvent::GetTriggerEvent( triggerevent_t *pEvent, CBaseEntity *pTriggerEntity ) -{ - if ( pEvent && pTriggerEntity == m_currentTriggerEvent.pTriggerEntity ) - { - *pEvent = m_currentTriggerEvent; - return true; - } - - return false; -} - -void PhysGetListOfPenetratingEntities( CBaseEntity *pSearch, CUtlVector &list ) -{ - g_Collisions.GetListOfPenetratingEntities( pSearch, list ); -} - -bool PhysGetTriggerEvent( triggerevent_t *pEvent, CBaseEntity *pTriggerEntity ) -{ - return g_Collisions.GetTriggerEvent( pEvent, pTriggerEntity ); -} -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -// External interface to collision sounds -//----------------------------------------------------------------------------- - -void PhysicsImpactSound( CBaseEntity *pEntity, IPhysicsObject *pPhysObject, int channel, int surfaceProps, int surfacePropsHit, float volume, float impactSpeed ) -{ - physicssound::AddImpactSound( g_PhysicsHook.m_impactSounds, pEntity, pEntity->entindex(), channel, pPhysObject, surfaceProps, surfacePropsHit, volume, impactSpeed ); -} - -void PhysCollisionSound( CBaseEntity *pEntity, IPhysicsObject *pPhysObject, int channel, int surfaceProps, int surfacePropsHit, float deltaTime, float speed ) -{ - if ( deltaTime < 0.05f || speed < 70.0f ) - return; - - float volume = speed * speed * (1.0f/(320.0f*320.0f)); // max volume at 320 in/s - if ( volume > 1.0f ) - volume = 1.0f; - - PhysicsImpactSound( pEntity, pPhysObject, channel, surfaceProps, surfacePropsHit, volume, speed ); -} - -void PhysBreakSound( CBaseEntity *pEntity, IPhysicsObject *pPhysObject, Vector vecOrigin ) -{ - if ( !pPhysObject) - return; - - physicssound::AddBreakSound( g_PhysicsHook.m_breakSounds, vecOrigin, pPhysObject->GetMaterialIndex() ); -} - -ConVar collision_shake_amp("collision_shake_amp", "0.2"); -ConVar collision_shake_freq("collision_shake_freq", "0.5"); -ConVar collision_shake_time("collision_shake_time", "0.5"); - -void PhysCollisionScreenShake( gamevcollisionevent_t *pEvent, int index ) -{ - int otherIndex = !index; - float mass = pEvent->pObjects[index]->GetMass(); - if ( mass >= VPHYSICS_LARGE_OBJECT_MASS && pEvent->pObjects[otherIndex]->IsStatic() && - !(pEvent->pObjects[index]->GetGameFlags() & FVPHYSICS_PENETRATING) ) - { - mass = clamp(mass, VPHYSICS_LARGE_OBJECT_MASS, 2000); - if ( pEvent->collisionSpeed > 30 && pEvent->deltaCollisionTime > 0.25f ) - { - Vector vecPos; - pEvent->pInternalData->GetContactPoint( vecPos ); - float impulse = pEvent->collisionSpeed * mass; - float amplitude = impulse * (collision_shake_amp.GetFloat() / (30.0f * VPHYSICS_LARGE_OBJECT_MASS)); - UTIL_ScreenShake( vecPos, amplitude, collision_shake_freq.GetFloat(), collision_shake_time.GetFloat(), amplitude * 60, SHAKE_START ); - } - } -} - -#if HL2_EPISODIC -// Uses DispatchParticleEffect because, so far as I know, that is the new means of kicking -// off flinders for this kind of collision. Should this be in g_pEffects instead? -void PhysCollisionWarpEffect( gamevcollisionevent_t *pEvent, surfacedata_t *phit ) -{ - Vector vecPos; - QAngle vecAngles; - - pEvent->pInternalData->GetContactPoint( vecPos ); - { - Vector vecNormal; - pEvent->pInternalData->GetSurfaceNormal(vecNormal); - VectorAngles( vecNormal, vecAngles ); - } - - DispatchParticleEffect( "warp_shield_impact", vecPos, vecAngles ); -} -#endif - -void PhysCollisionDust( gamevcollisionevent_t *pEvent, surfacedata_t *phit ) -{ - - switch ( phit->game.material ) - { - case CHAR_TEX_SAND: - case CHAR_TEX_DIRT: - - if ( pEvent->collisionSpeed < 200.0f ) - return; - - break; - - case CHAR_TEX_CONCRETE: - - if ( pEvent->collisionSpeed < 340.0f ) - return; - - break; - -#if HL2_EPISODIC - // this is probably redundant because BaseEntity::VHandleCollision should have already dispatched us elsewhere - case CHAR_TEX_WARPSHIELD: - PhysCollisionWarpEffect(pEvent,phit); - return; - - break; -#endif - - default: - return; - } - - //Kick up dust - Vector vecPos, vecVel; - - pEvent->pInternalData->GetContactPoint( vecPos ); - - vecVel.Random( -1.0f, 1.0f ); - vecVel.z = random->RandomFloat( 0.3f, 1.0f ); - VectorNormalize( vecVel ); - g_pEffects->Dust( vecPos, vecVel, 8.0f, pEvent->collisionSpeed ); -} - -void PhysFrictionSound( CBaseEntity *pEntity, IPhysicsObject *pObject, const char *pSoundName, HSOUNDSCRIPTHANDLE& handle, float flVolume ) -{ - if ( !pEntity ) - return; - - // cut out the quiet sounds - // UNDONE: Separate threshold for starting a sound vs. continuing? - flVolume = clamp( flVolume, 0.0f, 1.0f ); - if ( flVolume > (1.0f/128.0f) ) - { - friction_t *pFriction = g_Collisions.FindFriction( pEntity ); - if ( !pFriction ) - return; - - CSoundParameters params; - if ( !CBaseEntity::GetParametersForSound( pSoundName, handle, params, NULL ) ) - return; - - if ( !pFriction->pObject ) - { - // don't create really quiet scrapes - if ( params.volume * flVolume <= 0.1f ) - return; - - pFriction->pObject = pEntity; - CPASAttenuationFilter filter( pEntity, params.soundlevel ); - pFriction->patch = CSoundEnvelopeController::GetController().SoundCreate( - filter, pEntity->entindex(), CHAN_BODY, pSoundName, params.soundlevel ); - CSoundEnvelopeController::GetController().Play( pFriction->patch, params.volume * flVolume, params.pitch ); - } - else - { - float pitch = (flVolume * (params.pitchhigh - params.pitchlow)) + params.pitchlow; - CSoundEnvelopeController::GetController().SoundChangeVolume( pFriction->patch, params.volume * flVolume, 0.1f ); - CSoundEnvelopeController::GetController().SoundChangePitch( pFriction->patch, pitch, 0.1f ); - } - - pFriction->flLastUpdateTime = gpGlobals->curtime; - pFriction->flLastEffectTime = gpGlobals->curtime; - } -} - -void PhysCleanupFrictionSounds( CBaseEntity *pEntity ) -{ - friction_t *pFriction = g_Collisions.FindFriction( pEntity ); - if ( pFriction && pFriction->patch ) - { - g_Collisions.ShutdownFriction( *pFriction ); - } -} - - -//----------------------------------------------------------------------------- -// Applies force impulses at a later time -//----------------------------------------------------------------------------- -void PhysCallbackImpulse( IPhysicsObject *pPhysicsObject, const Vector &vecCenterForce, const AngularImpulse &vecCenterTorque ) -{ - Assert( physenv->IsInSimulation() ); - g_PostSimulationQueue.QueueCall( PostSimulation_ImpulseEvent, pPhysicsObject, RefToVal(vecCenterForce), RefToVal(vecCenterTorque) ); -} - -void PhysCallbackSetVelocity( IPhysicsObject *pPhysicsObject, const Vector &vecVelocity ) -{ - Assert( physenv->IsInSimulation() ); - g_PostSimulationQueue.QueueCall( PostSimulation_SetVelocityEvent, pPhysicsObject, RefToVal(vecVelocity) ); -} - -void PhysCallbackDamage( CBaseEntity *pEntity, const CTakeDamageInfo &info, gamevcollisionevent_t &event, int hurtIndex ) -{ - Assert( physenv->IsInSimulation() ); - int otherIndex = !hurtIndex; - g_Collisions.AddDamageEvent( pEntity, info, event.pObjects[otherIndex], true, event.preVelocity[otherIndex], event.preAngularVelocity[otherIndex] ); -} - -void PhysCallbackDamage( CBaseEntity *pEntity, const CTakeDamageInfo &info ) -{ - if ( PhysIsInCallback() ) - { - CBaseEntity *pInflictor = info.GetInflictor(); - IPhysicsObject *pInflictorPhysics = (pInflictor) ? pInflictor->VPhysicsGetObject() : NULL; - g_Collisions.AddDamageEvent( pEntity, info, pInflictorPhysics, false, vec3_origin, vec3_origin ); - if ( pEntity && info.GetInflictor() ) - { - DevMsg( 2, "Warning: Physics damage event with no recovery info!\nObjects: %s, %s\n", pEntity->GetClassname(), info.GetInflictor()->GetClassname() ); - } - } - else - { - pEntity->TakeDamage( info ); - } -} - -void PhysCallbackRemove(IServerNetworkable *pRemove) -{ - if ( PhysIsInCallback() ) - { - g_Collisions.AddRemoveObject(pRemove); - } - else - { - UTIL_Remove(pRemove); - } -} - -void PhysSetEntityGameFlags( CBaseEntity *pEntity, unsigned short flags ) -{ - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int count = pEntity->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - for ( int i = 0; i < count; i++ ) - { - PhysSetGameFlags( pList[i], flags ); - } -} - -bool PhysFindOrAddVehicleScript( const char *pScriptName, vehicleparams_t *pParams, vehiclesounds_t *pSounds ) -{ - return g_PhysicsHook.FindOrAddVehicleScript(pScriptName, pParams, pSounds); -} - -void PhysFlushVehicleScripts() -{ - g_PhysicsHook.FlushVehicleScripts(); -} - -IPhysicsObject *FindPhysicsObjectByName( const char *pName, CBaseEntity *pErrorEntity ) -{ - if ( !pName || !strlen(pName) ) - return NULL; - - CBaseEntity *pEntity = NULL; - IPhysicsObject *pBestObject = NULL; - while (1) - { - pEntity = gEntList.FindEntityByName( pEntity, pName ); - if ( !pEntity ) - break; - if ( pEntity->VPhysicsGetObject() ) - { - if ( pBestObject ) - { - const char *pErrorName = pErrorEntity ? pErrorEntity->GetClassname() : "Unknown"; - Vector origin = pErrorEntity ? pErrorEntity->GetAbsOrigin() : vec3_origin; - DevWarning("entity %s at %s has physics attachment to more than one entity with the name %s!!!\n", pErrorName, VecToString(origin), pName ); - while ( ( pEntity = gEntList.FindEntityByName( pEntity, pName ) ) != NULL ) - { - DevWarning("Found %s\n", pEntity->GetClassname() ); - } - break; - - } - pBestObject = pEntity->VPhysicsGetObject(); - } - } - return pBestObject; -} - -void CC_AirDensity( const CCommand &args ) -{ - if ( !physenv ) - return; - - if ( args.ArgC() < 2 ) - { - Msg( "air_density \nCurrent air density is %.2f\n", physenv->GetAirDensity() ); - } - else - { - float density = atof( args[1] ); - physenv->SetAirDensity( density ); - } -} -static ConCommand air_density("air_density", CC_AirDensity, "Changes the density of air for drag computations.", FCVAR_CHEAT); - -void DebugDrawContactPoints(IPhysicsObject *pPhysics) -{ - IPhysicsFrictionSnapshot *pSnapshot = pPhysics->CreateFrictionSnapshot(); - - while ( pSnapshot->IsValid() ) - { - Vector pt, normal; - pSnapshot->GetContactPoint( pt ); - pSnapshot->GetSurfaceNormal( normal ); - NDebugOverlay::Box( pt, -Vector(1,1,1), Vector(1,1,1), 0, 255, 0, 32, 0 ); - NDebugOverlay::Line( pt, pt - normal * 20, 0, 255, 0, false, 0 ); - IPhysicsObject *pOther = pSnapshot->GetObject(1); - CBaseEntity *pEntity0 = static_cast(pOther->GetGameData()); - CFmtStr str("%s (%s): %s [%0.2f]", pEntity0->GetClassname(), STRING(pEntity0->GetModelName()), pEntity0->GetDebugName(), pSnapshot->GetFrictionCoefficient() ); - NDebugOverlay::Text( pt, str.Access(), false, 0 ); - pSnapshot->NextFrictionData(); - } - pSnapshot->DeleteAllMarkedContacts( true ); - pPhysics->DestroyFrictionSnapshot( pSnapshot ); -} - - - -#if 0 - -#include "filesystem.h" -//----------------------------------------------------------------------------- -// Purpose: This will append a collide to a glview file. Then you can view the -// collisionmodels with glview. -// Input : *pCollide - collision model -// &origin - position of the instance of this model -// &angles - orientation of instance -// *pFilename - output text file -//----------------------------------------------------------------------------- -// examples: -// world: -// DumpCollideToGlView( pWorldCollide->solids[0], vec3_origin, vec3_origin, "jaycollide.txt" ); -// static_prop: -// DumpCollideToGlView( info.m_pCollide->solids[0], info.m_Origin, info.m_Angles, "jaycollide.txt" ); -// -//----------------------------------------------------------------------------- -void DumpCollideToGlView( CPhysCollide *pCollide, const Vector &origin, const QAngle &angles, const char *pFilename ) -{ - if ( !pCollide ) - return; - - printf("Writing %s...\n", pFilename ); - Vector *outVerts; - int vertCount = physcollision->CreateDebugMesh( pCollide, &outVerts ); - FileHandle_t fp = filesystem->Open( pFilename, "ab" ); - int triCount = vertCount / 3; - int vert = 0; - VMatrix tmp = SetupMatrixOrgAngles( origin, angles ); - int i; - for ( i = 0; i < vertCount; i++ ) - { - outVerts[i] = tmp.VMul4x3( outVerts[i] ); - } - for ( i = 0; i < triCount; i++ ) - { - filesystem->FPrintf( fp, "3\n" ); - filesystem->FPrintf( fp, "%6.3f %6.3f %6.3f 1 0 0\n", outVerts[vert].x, outVerts[vert].y, outVerts[vert].z ); - vert++; - filesystem->FPrintf( fp, "%6.3f %6.3f %6.3f 0 1 0\n", outVerts[vert].x, outVerts[vert].y, outVerts[vert].z ); - vert++; - filesystem->FPrintf( fp, "%6.3f %6.3f %6.3f 0 0 1\n", outVerts[vert].x, outVerts[vert].y, outVerts[vert].z ); - vert++; - } - filesystem->Close( fp ); - physcollision->DestroyDebugMesh( vertCount, outVerts ); -} -#endif - diff --git a/game/server/physics.h b/game/server/physics.h deleted file mode 100644 index 466192aa5..000000000 --- a/game/server/physics.h +++ /dev/null @@ -1,189 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: This is the abstraction layer for the physics simulation system -// Any calls to the external physics library (ipion) should be made through this -// layer. Eventually, the physics system will probably become a DLL and made -// accessible to the client & server side code. -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef PHYSICS_H -#define PHYSICS_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "physics_shared.h" - -class CBaseEntity; -class IPhysicsMaterial; -class IPhysicsConstraint; -class IPhysicsSpring; -class IPhysicsSurfaceProps; -class CTakeDamageInfo; -class ConVar; - -extern IPhysicsMaterial *g_Material; -extern ConVar phys_pushscale; -extern ConVar phys_timescale; - -struct objectparams_t; -extern IPhysicsGameTrace *physgametrace; - -class IPhysicsCollisionSolver; -class IPhysicsCollisionEvent; -class IPhysicsObjectEvent; -extern IPhysicsCollisionSolver * const g_pCollisionSolver; -extern IPhysicsCollisionEvent * const g_pCollisionEventHandler; -extern IPhysicsObjectEvent * const g_pObjectEventHandler; - -// HACKHACK: We treat anything >= 500kg as a special "large mass" that does more impact damage -// and has special recovery on crushing/killing other objects -// also causes screen shakes on impact with static/world objects -const float VPHYSICS_LARGE_OBJECT_MASS = 500.0f; - -struct gamevcollisionevent_t : public vcollisionevent_t -{ - Vector preVelocity[2]; - Vector postVelocity[2]; - AngularImpulse preAngularVelocity[2]; - CBaseEntity *pEntities[2]; - - void Init( vcollisionevent_t *pEvent ) - { - *((vcollisionevent_t *)this) = *pEvent; - pEntities[0] = NULL; - pEntities[1] = NULL; - } -}; - -struct triggerevent_t -{ - CBaseEntity *pTriggerEntity; - IPhysicsObject *pTriggerPhysics; - CBaseEntity *pEntity; - IPhysicsObject *pObject; - bool bStart; - - inline void Init( CBaseEntity *triggerEntity, IPhysicsObject *triggerPhysics, CBaseEntity *entity, IPhysicsObject *object, bool startTouch ) - { - pTriggerEntity = triggerEntity; - pTriggerPhysics= triggerPhysics; - pEntity = entity; - pObject = object; - bStart = startTouch; - } - inline void Clear() - { - memset( this, 0, sizeof(*this) ); - } -}; - -// parse solid parameter overrides out of a string -void PhysSolidOverride( solid_t &solid, string_t overrideScript ); - -extern CEntityList *g_pShadowEntities; -#ifdef PORTAL -extern CEntityList *g_pShadowEntities_Main; -#endif -void PhysAddShadow( CBaseEntity *pEntity ); -void PhysRemoveShadow( CBaseEntity *pEntity ); -bool PhysHasShadow( CBaseEntity *pEntity ); - -void PhysEnableFloating( IPhysicsObject *pObject, bool bEnable ); - -void PhysCollisionSound( CBaseEntity *pEntity, IPhysicsObject *pPhysObject, int channel, int surfaceProps, int surfacePropsHit, float deltaTime, float speed ); -void PhysCollisionScreenShake( gamevcollisionevent_t *pEvent, int index ); -void PhysCollisionDust( gamevcollisionevent_t *pEvent, surfacedata_t *phit ); -#if HL2_EPISODIC -void PhysCollisionWarpEffect( gamevcollisionevent_t *pEvent, surfacedata_t *phit ); -#endif -void PhysBreakSound( CBaseEntity *pEntity, IPhysicsObject *pPhysObject, Vector vecOrigin ); - -// plays the impact sound for a particular material -void PhysicsImpactSound( CBaseEntity *pEntity, IPhysicsObject *pPhysObject, int channel, int surfaceProps, int surfacePropsHit, float volume, float impactSpeed ); - -void PhysCallbackDamage( CBaseEntity *pEntity, const CTakeDamageInfo &info ); -void PhysCallbackDamage( CBaseEntity *pEntity, const CTakeDamageInfo &info, gamevcollisionevent_t &event, int hurtIndex ); - -// Applies force impulses at a later time -void PhysCallbackImpulse( IPhysicsObject *pPhysicsObject, const Vector &vecCenterForce, const AngularImpulse &vecCenterTorque ); - -// Sets the velocity at a later time -void PhysCallbackSetVelocity( IPhysicsObject *pPhysicsObject, const Vector &vecVelocity ); - -// queue up a delete on this object -void PhysCallbackRemove(IServerNetworkable *pRemove); - -bool PhysGetDamageInflictorVelocityStartOfFrame( IPhysicsObject *pInflictor, Vector &velocity, AngularImpulse &angVelocity ); - -// force a physics entity to sleep immediately -void PhysForceEntityToSleep( CBaseEntity *pEntity, IPhysicsObject *pObject ); - -// teleport an entity to it's position relative to an object it's constrained to -void PhysTeleportConstrainedEntity( CBaseEntity *pTeleportSource, IPhysicsObject *pObject0, IPhysicsObject *pObject1, const Vector &prevPosition, const QAngle &prevAngles, bool physicsRotate ); - -void PhysGetListOfPenetratingEntities( CBaseEntity *pSearch, CUtlVector &list ); -bool PhysShouldCollide( IPhysicsObject *pObj0, IPhysicsObject *pObj1 ); - -// returns true when processing a callback - so we can defer things that can't be done inside a callback -bool PhysIsInCallback(); -bool PhysIsFinalTick(); - -bool PhysGetTriggerEvent( triggerevent_t *pEvent, CBaseEntity *pTrigger ); -// note: pErrorEntity is used to report errors (object not found, more than one found). It can be NULL -IPhysicsObject *FindPhysicsObjectByName( const char *pName, CBaseEntity *pErrorEntity ); -bool PhysFindOrAddVehicleScript( const char *pScriptName, struct vehicleparams_t *pParams, struct vehiclesounds_t *pSounds ); -void PhysFlushVehicleScripts(); - -// this is called to flush all queues when the delete list is cleared -void PhysOnCleanupDeleteList(); - -struct masscenteroverride_t -{ - enum align_type - { - ALIGN_POINT = 0, - ALIGN_AXIS = 1, - }; - - void Defaults() - { - entityName = NULL_STRING; - } - - void SnapToPoint( string_t name, const Vector &pointWS ) - { - entityName = name; - center = pointWS; - axis.Init(); - alignType = ALIGN_POINT; - } - - void SnapToAxis( string_t name, const Vector &axisStartWS, const Vector &unitAxisDirWS ) - { - entityName = name; - center = axisStartWS; - axis = unitAxisDirWS; - alignType = ALIGN_AXIS; - } - - Vector center; - Vector axis; - int alignType; - string_t entityName; -}; - -void PhysSetMassCenterOverride( masscenteroverride_t &override ); -// NOTE: this removes the entry from the table as well as retrieving it -void PhysGetMassCenterOverride( CBaseEntity *pEntity, vcollide_t *pCollide, solid_t &solidOut ); -float PhysGetEntityMass( CBaseEntity *pEntity ); -void PhysSetEntityGameFlags( CBaseEntity *pEntity, unsigned short flags ); - -void DebugDrawContactPoints(IPhysicsObject *pPhysics); - -#endif // PHYSICS_H diff --git a/game/server/physics_bone_follower.cpp b/game/server/physics_bone_follower.cpp deleted file mode 100644 index b985fbbbc..000000000 --- a/game/server/physics_bone_follower.cpp +++ /dev/null @@ -1,485 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "bone_setup.h" -#include "physics_bone_follower.h" -#include "vcollide_parse.h" -#include "saverestore_utlvector.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -BEGIN_SIMPLE_DATADESC( physfollower_t ) -DEFINE_FIELD( boneIndex, FIELD_INTEGER ), -DEFINE_FIELD( hFollower, FIELD_EHANDLE ), -END_DATADESC() - -BEGIN_SIMPLE_DATADESC( CBoneFollowerManager ) -DEFINE_GLOBAL_FIELD( m_iNumBones, FIELD_INTEGER ), -DEFINE_GLOBAL_UTLVECTOR( m_physBones, FIELD_EMBEDDED ), -END_DATADESC() - -//================================================================================================================ -// BONE FOLLOWER MANAGER -//================================================================================================================ -CBoneFollowerManager::CBoneFollowerManager() -{ - m_iNumBones = 0; -} - -CBoneFollowerManager::~CBoneFollowerManager() -{ - // if this fires then someone isn't destroying their bonefollowers in UpdateOnRemove - Assert(m_iNumBones==0); - DestroyBoneFollowers(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEntity - -// iNumBones - -// **pFollowerBoneNames - -//----------------------------------------------------------------------------- -void CBoneFollowerManager::InitBoneFollowers( CBaseAnimating *pParentEntity, int iNumBones, const char **pFollowerBoneNames ) -{ - m_iNumBones = iNumBones; - m_physBones.EnsureCount( iNumBones ); - - // Now init all the bones - for ( int i = 0; i < iNumBones; i++ ) - { - CreatePhysicsFollower( pParentEntity, m_physBones[i], pFollowerBoneNames[i], NULL ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBoneFollowerManager::AddBoneFollower( CBaseAnimating *pParentEntity, const char *pFollowerBoneName, solid_t *pSolid ) -{ - m_iNumBones++; - - int iIndex = m_physBones.AddToTail(); - CreatePhysicsFollower( pParentEntity, m_physBones[iIndex], pFollowerBoneName, pSolid ); -} - -// walk the hitboxes and find the first one that is attached to the physics bone in question -// return the hitgroup of that box -static int HitGroupFromPhysicsBone( CBaseAnimating *pAnim, int physicsBone ) -{ - CStudioHdr *pStudioHdr = pAnim->GetModelPtr( ); - mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( pAnim->m_nHitboxSet ); - for ( int i = 0; i < set->numhitboxes; i++ ) - { - if ( pStudioHdr->pBone( set->pHitbox(i)->bone )->physicsbone == physicsBone ) - { - return set->pHitbox(i)->group; - } - } - - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &follow - -// *pBoneName - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBoneFollowerManager::CreatePhysicsFollower( CBaseAnimating *pParentEntity, physfollower_t &follow, const char *pBoneName, solid_t *pSolid ) -{ - CStudioHdr *pStudioHdr = pParentEntity->GetModelPtr(); - matrix3x4_t boneToWorld; - solid_t solidTmp; - - Vector bonePosition; - QAngle boneAngles; - - int boneIndex = Studio_BoneIndexByName( pStudioHdr, pBoneName ); - - if ( boneIndex >= 0 ) - { - mstudiobone_t *pBone = pStudioHdr->pBone( boneIndex ); - - int physicsBone = pBone->physicsbone; - if ( !pSolid ) - { - if ( !PhysModelParseSolidByIndex( solidTmp, pParentEntity, pParentEntity->GetModelIndex(), physicsBone ) ) - return false; - pSolid = &solidTmp; - } - - // fixup in case ragdoll is assigned to a parent of the requested follower bone - follow.boneIndex = Studio_BoneIndexByName( pStudioHdr, pSolid->name ); - if ( follow.boneIndex < 0 ) - { - follow.boneIndex = boneIndex; - } - - pParentEntity->GetBoneTransform( follow.boneIndex, boneToWorld ); - MatrixAngles( boneToWorld, boneAngles, bonePosition ); - - follow.hFollower = CBoneFollower::Create( pParentEntity, STRING(pParentEntity->GetModelName()), *pSolid, bonePosition, boneAngles ); - follow.hFollower->SetTraceData( physicsBone, HitGroupFromPhysicsBone( pParentEntity, physicsBone ) ); - follow.hFollower->SetBlocksLOS( pParentEntity->BlocksLOS() ); - return true; - } - else - { - Warning( "ERROR: Tried to create bone follower on invalid bone %s\n", pBoneName ); - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBoneFollowerManager::UpdateBoneFollowers( CBaseAnimating *pParentEntity ) -{ - if ( m_iNumBones ) - { - matrix3x4_t boneToWorld; - Vector bonePosition; - QAngle boneAngles; - for ( int i = 0; i < m_iNumBones; i++ ) - { - if ( !m_physBones[i].hFollower ) - continue; - - pParentEntity->GetBoneTransform( m_physBones[i].boneIndex, boneToWorld ); - MatrixAngles( boneToWorld, boneAngles, bonePosition ); - m_physBones[i].hFollower->UpdateFollower( bonePosition, boneAngles, 0.1 ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBoneFollowerManager::DestroyBoneFollowers( void ) -{ - for ( int i = 0; i < m_iNumBones; i++ ) - { - if ( !m_physBones[i].hFollower ) - continue; - - UTIL_Remove( m_physBones[i].hFollower ); - m_physBones[i].hFollower = NULL; - } - - m_physBones.Purge(); - m_iNumBones = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -physfollower_t *CBoneFollowerManager::GetBoneFollower( int iFollowerIndex ) -{ - Assert( iFollowerIndex >= 0 && iFollowerIndex < m_iNumBones ); - if ( iFollowerIndex >= 0 && iFollowerIndex < m_iNumBones ) - return &m_physBones[iFollowerIndex]; - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Retrieve the index for a supplied bone follower -// Input : *pFollower - Bone follower to look up -// Output : -1 if not found, otherwise the index of the bone follower -//----------------------------------------------------------------------------- -int CBoneFollowerManager::GetBoneFollowerIndex( CBoneFollower *pFollower ) -{ - if ( pFollower == NULL ) - return -1; - - for ( int i = 0; i < m_iNumBones; i++ ) - { - if ( !m_physBones[i].hFollower ) - continue; - - if ( m_physBones[i].hFollower == pFollower ) - return i; - } - - return -1; -} - -//================================================================================================================ -// BONE FOLLOWER -//================================================================================================================ - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CBoneFollower ) - - DEFINE_FIELD( m_modelIndex, FIELD_MODELINDEX ), - DEFINE_FIELD( m_solidIndex, FIELD_INTEGER ), - DEFINE_FIELD( m_physicsBone, FIELD_INTEGER ), - DEFINE_FIELD( m_hitGroup, FIELD_INTEGER ), - -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CBoneFollower, DT_BoneFollower ) - SendPropModelIndex(SENDINFO(m_modelIndex)), - SendPropInt(SENDINFO(m_solidIndex), 6, SPROP_UNSIGNED ), -END_SEND_TABLE() - - -bool CBoneFollower::Init( CBaseEntity *pOwner, const char *pModelName, solid_t &solid, const Vector &position, const QAngle &orientation ) -{ - SetOwnerEntity( pOwner ); - UTIL_SetModel( this, pModelName ); - - AddEffects( EF_NODRAW ); // invisible - - m_modelIndex = modelinfo->GetModelIndex( pModelName ); - m_solidIndex = solid.index; - SetAbsOrigin( position ); - SetAbsAngles( orientation ); - SetMoveType( MOVETYPE_PUSH ); - SetSolid( SOLID_VPHYSICS ); - SetCollisionGroup( pOwner->GetCollisionGroup() ); - AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST ); - solid.params.pGameData = (void *)this; - IPhysicsObject *pPhysics = VPhysicsInitShadow( false, false, &solid ); - if ( !pPhysics ) - return false; - - // we can't use the default model bounds because each entity is only one bone of the model - // so compute the OBB of the physics model and use that. - Vector mins, maxs; - physcollision->CollideGetAABB( &mins, &maxs, pPhysics->GetCollide(), vec3_origin, vec3_angle ); - SetCollisionBounds( mins, maxs ); - - pPhysics->SetCallbackFlags( pPhysics->GetCallbackFlags() | CALLBACK_GLOBAL_TOUCH ); - pPhysics->EnableGravity( false ); - // This is not a normal shadow controller that is trying to go to a space occupied by an entity in the game physics - // This entity is not running PhysicsPusher(), so Vphysics is supposed to move it - // This line of code informs vphysics of that fact - if ( pOwner->IsNPC() ) - { - pPhysics->GetShadowController()->SetPhysicallyControlled( true ); - } - - return true; -} - -int CBoneFollower::UpdateTransmitState() -{ - // Send to the client for client-side collisions and visualization - return SetTransmitState( FL_EDICT_PVSCHECK ); -} - -void CBoneFollower::VPhysicsUpdate( IPhysicsObject *pPhysics ) -{ - Vector origin; - QAngle angles; - - pPhysics->GetPosition( &origin, &angles ); - - SetAbsOrigin( origin ); - SetAbsAngles( angles ); -} - -// a little helper class to temporarily change the physics object -// for an entity - and change it back when it goes out of scope. -class CPhysicsSwapTemp -{ -public: - CPhysicsSwapTemp( CBaseEntity *pEntity, IPhysicsObject *pTmpPhysics ) - { - Assert(pEntity); - Assert(pTmpPhysics); - m_pEntity = pEntity; - m_pPhysics = m_pEntity->VPhysicsGetObject(); - if ( m_pPhysics ) - { - m_pEntity->VPhysicsSwapObject( pTmpPhysics ); - } - else - { - m_pEntity->VPhysicsSetObject( pTmpPhysics ); - } - } - ~CPhysicsSwapTemp() - { - m_pEntity->VPhysicsSwapObject( m_pPhysics ); - } - -private: - CBaseEntity *m_pEntity; - IPhysicsObject *m_pPhysics; -}; - - -void CBoneFollower::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) -{ - CBaseEntity *pOwner = GetOwnerEntity(); - if ( pOwner ) - { - CPhysicsSwapTemp tmp(pOwner, pEvent->pObjects[index] ); - pOwner->VPhysicsCollision( index, pEvent ); - } -} - -void CBoneFollower::VPhysicsShadowCollision( int index, gamevcollisionevent_t *pEvent ) -{ - CBaseEntity *pOwner = GetOwnerEntity(); - if ( pOwner ) - { - CPhysicsSwapTemp tmp(pOwner, pEvent->pObjects[index] ); - pOwner->VPhysicsShadowCollision( index, pEvent ); - } -} - -void CBoneFollower::VPhysicsFriction( IPhysicsObject *pObject, float energy, int surfaceProps, int surfacePropsHit ) -{ - CBaseEntity *pOwner = GetOwnerEntity(); - if ( pOwner ) - { - CPhysicsSwapTemp tmp(pOwner, pObject ); - pOwner->VPhysicsFriction( pObject, energy, surfaceProps, surfacePropsHit ); - } -} - -bool CBoneFollower::TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ) -{ - vcollide_t *pCollide = modelinfo->GetVCollide( GetModelIndex() ); - Assert( pCollide && pCollide->solidCount > m_solidIndex ); - - UTIL_ClearTrace( trace ); - - physcollision->TraceBox( ray, pCollide->solids[m_solidIndex], GetAbsOrigin(), GetAbsAngles(), &trace ); - - if ( trace.fraction >= 1 ) - return false; - - // return owner as trace hit - trace.m_pEnt = GetOwnerEntity(); - trace.hitgroup = m_hitGroup; - trace.physicsbone = m_physicsBone; - return true; -} - -void CBoneFollower::UpdateFollower( const Vector &position, const QAngle &orientation, float flInterval ) -{ - // UNDONE: Shadow update needs timing info? - VPhysicsGetObject()->UpdateShadow( position, orientation, false, flInterval ); -} - -void CBoneFollower::SetTraceData( int physicsBone, int hitGroup ) -{ - m_hitGroup = hitGroup; - m_physicsBone = physicsBone; -} - -CBoneFollower *CBoneFollower::Create( CBaseEntity *pOwner, const char *pModelName, solid_t &solid, const Vector &position, const QAngle &orientation ) -{ - CBoneFollower *pFollower = (CBoneFollower *)CreateEntityByName( "phys_bone_follower" ); - if ( pFollower ) - { - pFollower->Init( pOwner, pModelName, solid, position, orientation ); - } - return pFollower; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBoneFollower::ObjectCaps() -{ - CBaseEntity *pOwner = GetOwnerEntity(); - if ( pOwner ) - { - if( pOwner->m_iGlobalname != NULL_STRING ) - { - int caps = BaseClass::ObjectCaps() | pOwner->ObjectCaps(); - caps &= ~FCAP_ACROSS_TRANSITION; - return caps; - } - } - - return BaseClass::ObjectCaps(); -} -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBoneFollower::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - CBaseEntity *pOwner = GetOwnerEntity(); - if ( pOwner ) - { - pOwner->Use( pActivator, pCaller, useType, value ); - return; - } - - BaseClass::Use( pActivator, pCaller, useType, value ); -} - -//----------------------------------------------------------------------------- -// Purpose: Pass on Touch calls to the entity we're following -//----------------------------------------------------------------------------- -void CBoneFollower::Touch( CBaseEntity *pOther ) -{ - CBaseEntity *pOwner = GetOwnerEntity(); - if ( pOwner ) - { - //TODO: fill in the touch trace with the hitbox number associated with this bone - pOwner->Touch( pOther ); - return; - } - - BaseClass::Touch( pOther ); -} - -//----------------------------------------------------------------------------- -// Purpose: Pass on trace attack calls to the entity we're following -//----------------------------------------------------------------------------- -void CBoneFollower::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - CBaseEntity *pOwner = GetOwnerEntity(); - if ( pOwner ) - { - pOwner->DispatchTraceAttack( info, vecDir, ptr ); - return; - } - - BaseClass::TraceAttack( info, vecDir, ptr ); -} - -LINK_ENTITY_TO_CLASS( phys_bone_follower, CBoneFollower ); - - - -// create a manager and a list of followers directly from a ragdoll -void CreateBoneFollowersFromRagdoll( CBaseAnimating *pEntity, CBoneFollowerManager *pManager, vcollide_t *pCollide ) -{ - IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pCollide->pKeyValues ); - while ( !pParse->Finished() ) - { - const char *pBlock = pParse->GetCurrentBlockName(); - if ( !strcmpi( pBlock, "solid" ) ) - { - solid_t solid; - - pParse->ParseSolid( &solid, NULL ); - // collisions are off by default, turn them on - solid.params.enableCollisions = true; - solid.params.pName = STRING(pEntity->GetModelName()); - - pManager->AddBoneFollower( pEntity, solid.name, &solid ); - } - else - { - pParse->SkipBlock(); - } - } -} diff --git a/game/server/physics_bone_follower.h b/game/server/physics_bone_follower.h deleted file mode 100644 index facb25b9f..000000000 --- a/game/server/physics_bone_follower.h +++ /dev/null @@ -1,104 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef PHYSICS_BONE_FOLLOWER_H -#define PHYSICS_BONE_FOLLOWER_H -#ifdef _WIN32 -#pragma once -#endif - -class CBoneFollower; - -// -// To use bone followers in an entity, contain a CBoneFollowerManager in it. Then: -// - Call InitBoneFollowers() in the entity's CreateVPhysics(). -// - Call UpdateBoneFollowers() after you move your bones. -// - Call DestroyBoneFollowers() when your entity's removed - -struct physfollower_t -{ - DECLARE_SIMPLE_DATADESC(); - int boneIndex; - CHandle hFollower; -}; - -struct vcollide_t; - -// create a manager and a list of followers directly from a ragdoll -void CreateBoneFollowersFromRagdoll( CBaseAnimating *pEntity, class CBoneFollowerManager *pManager, vcollide_t *pCollide ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CBoneFollowerManager -{ - DECLARE_SIMPLE_DATADESC(); -public: - CBoneFollowerManager(); - ~CBoneFollowerManager(); - - // Use either of these to create the bone followers in your entity's CreateVPhysics() - void InitBoneFollowers( CBaseAnimating *pParentEntity, int iNumBones, const char **pFollowerBoneNames ); - void AddBoneFollower( CBaseAnimating *pParentEntity, const char *pFollowerBoneName, solid_t *pSolid = NULL ); // Adds a single bone follower - - // Call this after you move your bones - void UpdateBoneFollowers( CBaseAnimating *pParentEntity ); - - // Call this when your entity's removed - void DestroyBoneFollowers( void ); - - physfollower_t *GetBoneFollower( int iFollowerIndex ); - int GetBoneFollowerIndex( CBoneFollower *pFollower ); - int GetNumBoneFollowers( void ) const { return m_iNumBones; } - -private: - bool CreatePhysicsFollower( CBaseAnimating *pParentEntity, physfollower_t &follow, const char *pBoneName, solid_t *pSolid ); - -private: - int m_iNumBones; - CUtlVector m_physBones; -}; - - -class CBoneFollower : public CBaseEntity -{ - DECLARE_CLASS( CBoneFollower, CBaseEntity ); - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); -public: - // CBaseEntity - void VPhysicsUpdate( IPhysicsObject *pPhysics ); - int UpdateTransmitState(void); - - // NOTE: These are forwarded to the parent object! - void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); - void VPhysicsFriction( IPhysicsObject *pObject, float energy, int surfaceProps, int surfacePropsHit ); - void VPhysicsShadowCollision( int index, gamevcollisionevent_t *pEvent ); - - bool TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ); - int ObjectCaps( void ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - void Touch( CBaseEntity *pOther ); - - void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - - // locals - bool Init( CBaseEntity *pOwner, const char *pModelName, solid_t &solid, const Vector &position, const QAngle &orientation ); - void UpdateFollower( const Vector &position, const QAngle &orientation, float flInterval ); - void SetTraceData( int physicsBone, int hitGroup ); - - // factory - static CBoneFollower *Create( CBaseEntity *pOwner, const char *pModelName, solid_t &solid, const Vector &position, const QAngle &orientation ); - -private: - CNetworkVar( int, m_modelIndex ); - CNetworkVar( int, m_solidIndex ); - int m_physicsBone; - int m_hitGroup; -}; - -#endif // PHYSICS_BONE_FOLLOWER_H diff --git a/game/server/physics_cannister.cpp b/game/server/physics_cannister.cpp deleted file mode 100644 index d9101d9b2..000000000 --- a/game/server/physics_cannister.cpp +++ /dev/null @@ -1,483 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include "cbase.h" -#include "basecombatcharacter.h" -#include "entityoutput.h" -#include "physics.h" -#include "explode.h" -#include "vphysics_interface.h" -#include "collisionutils.h" -#include "steamjet.h" -#include "eventqueue.h" -#include "soundflags.h" -#include "engine/IEngineSound.h" -#include "props.h" -#include "physics_cannister.h" -#include "globals.h" -#include "physics_saverestore.h" -#include "shareddefs.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SF_CANNISTER_ASLEEP 0x0001 -#define SF_CANNISTER_EXPLODE 0x0002 - -BEGIN_SIMPLE_DATADESC( CThrustController ) - - DEFINE_FIELD( m_thrustVector, FIELD_VECTOR ), - DEFINE_FIELD( m_torqueVector, FIELD_VECTOR ), - DEFINE_KEYFIELD( m_thrust, FIELD_FLOAT, "thrust" ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( physics_cannister, CPhysicsCannister ); - -BEGIN_DATADESC( CPhysicsCannister ) - - DEFINE_OUTPUT( m_onActivate, "OnActivate" ), - DEFINE_OUTPUT( m_OnAwakened, "OnAwakened" ), - DEFINE_FIELD( m_thrustOrigin, FIELD_VECTOR ), // this is a position, but in local space - DEFINE_EMBEDDED( m_thruster ), - DEFINE_PHYSPTR( m_pController ), - DEFINE_FIELD( m_pJet, FIELD_CLASSPTR ), - DEFINE_FIELD( m_active, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_thrustTime, FIELD_FLOAT, "fuel" ), - DEFINE_KEYFIELD( m_damage, FIELD_FLOAT, "expdamage" ), - DEFINE_KEYFIELD( m_damageRadius, FIELD_FLOAT, "expradius" ), - DEFINE_FIELD( m_activateTime, FIELD_TIME ), - DEFINE_KEYFIELD( m_gasSound, FIELD_SOUNDNAME, "gassound" ), - DEFINE_FIELD( m_bFired, FIELD_BOOLEAN ), - - // Physics Influence - DEFINE_FIELD( m_hPhysicsAttacker, FIELD_EHANDLE ), - DEFINE_FIELD( m_flLastPhysicsInfluenceTime, FIELD_TIME ), - DEFINE_FIELD( m_hLauncher, FIELD_EHANDLE ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ), - DEFINE_INPUTFUNC( FIELD_VOID, "Deactivate", InputDeactivate ), - DEFINE_INPUTFUNC( FIELD_VOID, "Explode", InputExplode ), - DEFINE_INPUTFUNC( FIELD_VOID, "Wake", InputWake ), - - DEFINE_THINKFUNC( BeginShutdownThink ), - DEFINE_ENTITYFUNC( ExplodeTouch ), - -END_DATADESC() - -void CPhysicsCannister::Spawn( void ) -{ - Precache(); - SetModel( STRING(GetModelName()) ); - SetBloodColor( DONT_BLEED ); - - AddSolidFlags( FSOLID_CUSTOMRAYTEST ); - m_takedamage = DAMAGE_YES; - SetNextThink( TICK_NEVER_THINK ); - - if ( m_iHealth <= 0 ) - m_iHealth = 25; - - m_flAnimTime = gpGlobals->curtime; - m_flPlaybackRate = 0.0; - SetCycle( 0 ); - m_bFired = false; - - // not thrusting - m_active = false; - - CreateVPhysics(); - if ( !VPhysicsGetObject() ) - { - // must have a physics object or code will crash later - UTIL_Remove(this); - } -} - -void CPhysicsCannister::OnRestore() -{ - BaseClass::OnRestore(); - if ( m_pController ) - { - m_pController->SetEventHandler( &m_thruster ); - } -} - -bool CPhysicsCannister::CreateVPhysics() -{ - bool asleep = HasSpawnFlags(SF_CANNISTER_ASLEEP); - - VPhysicsInitNormal( SOLID_VPHYSICS, 0, asleep ); - return true; -} - -bool CPhysicsCannister::TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ) -{ - Vector vecAbsMins, vecAbsMaxs; - CollisionProp()->WorldSpaceAABB( &vecAbsMins, &vecAbsMaxs ); - - if ( !IsBoxIntersectingRay( vecAbsMins, vecAbsMaxs, ray.m_Start, ray.m_Delta ) ) - return false; - - return BaseClass::TestCollision( ray, mask, trace ); -} - -Vector CPhysicsCannister::CalcLocalThrust( const Vector &offset ) -{ - matrix3x4_t nozzleMatrix; - Vector thrustDirection; - - GetAttachment( LookupAttachment("nozzle"), nozzleMatrix ); - MatrixGetColumn( nozzleMatrix, 2, thrustDirection ); - MatrixGetColumn( nozzleMatrix, 3, m_thrustOrigin ); - thrustDirection = -5*thrustDirection + offset; - VectorNormalize( thrustDirection ); - return thrustDirection; -} - - -CPhysicsCannister::~CPhysicsCannister( void ) -{ -} - -void CPhysicsCannister::Precache( void ) -{ - PropBreakablePrecacheAll( GetModelName() ); - if ( m_gasSound != NULL_STRING ) - { - PrecacheScriptSound( STRING(m_gasSound) ); - } - BaseClass::Precache(); -} - -int CPhysicsCannister::OnTakeDamage( const CTakeDamageInfo &info ) -{ - // HACKHACK: Shouldn't g_vecAttackDir be a parameter to this function? - if ( !m_takedamage ) - return 0; - - if ( !m_active ) - { - m_iHealth -= info.GetDamage(); - if ( m_iHealth < 0 ) - { - Explode( info.GetAttacker() ); - } - else - { - // explosions that don't destroy will activate - // 50% of the time blunt damage will activate as well - if ( (info.GetDamageType() & DMG_BLAST) || - ( (info.GetDamageType() & (DMG_CLUB|DMG_SLASH|DMG_CRUSH) ) && random->RandomInt(1,100) < 50 ) ) - { - CannisterActivate( info.GetAttacker(), g_vecAttackDir ); - } - } - return 1; - } - - if ( (gpGlobals->curtime - m_activateTime) <= 0.1 ) - return 0; - - if ( info.GetDamageType() & (DMG_BULLET|DMG_BUCKSHOT|DMG_BURN|DMG_BLAST) ) - { - Explode( info.GetAttacker() ); - } - - return 0; -} - - -void CPhysicsCannister::TraceAttack( const CTakeDamageInfo &info, const Vector &dir, trace_t *ptr ) -{ - if ( !m_active && ptr->hitgroup != 0 ) - { - Vector direction = -dir; - direction.z -= 5; - VectorNormalize( direction ); - CannisterActivate( info.GetAttacker(), direction ); - } - BaseClass::TraceAttack( info, dir, ptr ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysicsCannister::CannisterActivate( CBaseEntity *pActivator, const Vector &thrustOffset ) -{ - // already active or spent - if ( m_active || !m_thrustTime ) - { - return; - } - - m_hLauncher = pActivator; - - Vector thrustDirection = CalcLocalThrust( thrustOffset ); - m_onActivate.FireOutput( pActivator, this, 0 ); - m_thruster.CalcThrust( m_thrustOrigin, thrustDirection, VPhysicsGetObject() ); - m_pController = physenv->CreateMotionController( &m_thruster ); - IPhysicsObject *pPhys = VPhysicsGetObject(); - m_pController->AttachObject( pPhys, true ); - // Make sure the object is simulated - pPhys->Wake(); - - m_active = true; - m_activateTime = gpGlobals->curtime; - SetNextThink( gpGlobals->curtime + m_thrustTime ); - SetThink( &CPhysicsCannister::BeginShutdownThink ); - - QAngle angles; - VectorAngles( -thrustDirection, angles ); - m_pJet = dynamic_cast( CBaseEntity::Create( "env_steam", m_thrustOrigin, angles, this ) ); - m_pJet->SetParent( this ); - - float extra = m_thruster.m_thrust * (1/5000.f); - extra = clamp( extra, 0, 1 ); - - m_pJet->m_SpreadSpeed = 15 * m_thruster.m_thrust * 0.001; - m_pJet->m_Speed = 128 + 100 * extra; - m_pJet->m_StartSize = 10; - m_pJet->m_EndSize = 25; - - m_pJet->m_Rate = 52 + (int)extra*20; - m_pJet->m_JetLength = 64; - m_pJet->m_clrRender = m_clrRender; - - m_pJet->Use( this, this, USE_ON, 1 ); - if ( m_gasSound != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_ITEM; - ep.m_pSoundName = STRING(m_gasSound); - ep.m_flVolume = 1.0f; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: The cannister's been fired by a weapon, so it should stay pretty accurate -//----------------------------------------------------------------------------- -void CPhysicsCannister::CannisterFire( CBaseEntity *pActivator ) -{ - m_bFired = true; - - // Increase thrust - m_thruster.m_thrust *= 4; - - // Only last a short time - m_thrustTime = 10.0; - - // Explode on contact - SetTouch( &CPhysicsCannister::ExplodeTouch ); - - CannisterActivate( pActivator, vec3_origin ); -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for activating the cannister. -//----------------------------------------------------------------------------- -void CPhysicsCannister::InputActivate( inputdata_t &data ) -{ - CannisterActivate( data.pActivator, Vector(0,0.1,-0.25) ); -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for deactivating the cannister. -//----------------------------------------------------------------------------- -void CPhysicsCannister::InputDeactivate(inputdata_t &data) -{ - Deactivate(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for making the cannister go boom. -//----------------------------------------------------------------------------- -void CPhysicsCannister::InputExplode(inputdata_t &data) -{ - Explode( data.pActivator ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for waking up the cannister if it is sleeping. -//----------------------------------------------------------------------------- -void CPhysicsCannister::InputWake( inputdata_t &data ) -{ - IPhysicsObject *pPhys = VPhysicsGetObject(); - if ( pPhys != NULL ) - { - pPhys->Wake(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysicsCannister::Deactivate(void) -{ - if ( !m_pController ) - return; - - m_pController->DetachObject( VPhysicsGetObject() ); - physenv->DestroyMotionController( m_pController ); - m_pController = NULL; - SetNextThink( TICK_NEVER_THINK ); - m_thrustTime = 0; - m_active = false; - if ( m_pJet ) - { - ShutdownJet(); - } - if ( m_gasSound != NULL_STRING ) - { - StopSound( entindex(), CHAN_ITEM, STRING(m_gasSound) ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysicsCannister::Explode( CBaseEntity *pAttacker ) -{ - // don't recurse - m_takedamage = 0; - Deactivate(); - - Vector velocity; - AngularImpulse angVelocity; - IPhysicsObject *pPhysics = VPhysicsGetObject(); - - pPhysics->GetVelocity( &velocity, &angVelocity ); - PropBreakableCreateAll( GetModelIndex(), pPhysics, GetAbsOrigin(), GetAbsAngles(), velocity, angVelocity, 1.0, 20, COLLISION_GROUP_DEBRIS ); - ExplosionCreate( GetAbsOrigin(), GetAbsAngles(), pAttacker, (int)m_damage, 0, true ); - UTIL_Remove( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: Explode when I next hit a damageable entity -//----------------------------------------------------------------------------- -void CPhysicsCannister::ExplodeTouch( CBaseEntity *pOther ) -{ - if ( !pOther->m_takedamage ) - return; - - Explode( m_hLauncher ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysicsCannister::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) -{ - if ( m_bFired && m_active ) - { - int otherIndex = !index; - CBaseEntity *pHitEntity = pEvent->pEntities[otherIndex]; - if ( pEvent->deltaCollisionTime < 0.5 && (pHitEntity == this) ) - return; - - // If we hit hard enough. explode - if ( pEvent->collisionSpeed > 1000 ) - { - Explode( m_hLauncher ); - return; - } - } - - BaseClass::VPhysicsCollision( index, pEvent ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysicsCannister::ShutdownJet( void ) -{ - g_EventQueue.AddEvent( m_pJet, "kill", 5, NULL, NULL ); - - m_pJet->m_bEmit = false; - m_pJet->m_Rate = 0; - m_pJet = NULL; - SetNextThink( TICK_NEVER_THINK ); -} - -//----------------------------------------------------------------------------- -// Purpose: The think just shuts the cannister down -//----------------------------------------------------------------------------- -void CPhysicsCannister::BeginShutdownThink( void ) -{ - Deactivate(); -} - -//----------------------------------------------------------------------------- -// Physics Attacker -//----------------------------------------------------------------------------- -void CPhysicsCannister::SetPhysicsAttacker( CBasePlayer *pEntity, float flTime ) -{ - m_hPhysicsAttacker = pEntity; - m_flLastPhysicsInfluenceTime = flTime; -} - - -//----------------------------------------------------------------------------- -// Purpose: Keep track of physgun influence -//----------------------------------------------------------------------------- -void CPhysicsCannister::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) -{ - SetPhysicsAttacker( pPhysGunUser, gpGlobals->curtime ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysicsCannister::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ) -{ - SetPhysicsAttacker( pPhysGunUser, gpGlobals->curtime ); - if ( Reason == LAUNCHED_BY_CANNON ) - { - CannisterActivate( pPhysGunUser, vec3_origin ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBasePlayer *CPhysicsCannister::HasPhysicsAttacker( float dt ) -{ - if (gpGlobals->curtime - dt <= m_flLastPhysicsInfluenceTime) - { - return m_hPhysicsAttacker; - } - return NULL; -} -//----------------------------------------------------------------------------- -// Purpose: Update the visible representation of the physic system's representation of this object -//----------------------------------------------------------------------------- -void CPhysicsCannister::VPhysicsUpdate( IPhysicsObject *pPhysics ) -{ - BaseClass::VPhysicsUpdate( pPhysics ); - - // if this is the first time we have moved, fire our target - if ( HasSpawnFlags( SF_CANNISTER_ASLEEP ) ) - { - if ( !pPhysics->IsAsleep() ) - { - m_OnAwakened.FireOutput(this, this); - RemoveSpawnFlags( SF_CANNISTER_ASLEEP ); - } - } -} diff --git a/game/server/physics_cannister.h b/game/server/physics_cannister.h deleted file mode 100644 index d04b5abb2..000000000 --- a/game/server/physics_cannister.h +++ /dev/null @@ -1,145 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef PHYSICS_CANNISTER_H -#define PHYSICS_CANNISTER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "player_pickup.h" - -class CSteamJet; - -class CThrustController : public IMotionEvent -{ - DECLARE_SIMPLE_DATADESC(); - -public: - IMotionEvent::simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) - { - angular = m_torqueVector; - linear = m_thrustVector; - return SIM_LOCAL_ACCELERATION; - } - - void CalcThrust( const Vector &position, const Vector &direction, IPhysicsObject *pPhys ) - { - Vector force = direction * m_thrust * pPhys->GetMass(); - - // Adjust for the position of the thruster -- apply proper torque) - pPhys->CalculateVelocityOffset( force, position, &m_thrustVector, &m_torqueVector ); - pPhys->WorldToLocalVector( &m_thrustVector, m_thrustVector ); - } - - Vector m_thrustVector; - AngularImpulse m_torqueVector; - float m_thrust; -}; - -class CPhysicsCannister : public CBaseCombatCharacter, public CDefaultPlayerPickupVPhysics -{ - DECLARE_CLASS( CPhysicsCannister, CBaseCombatCharacter ); -public: - ~CPhysicsCannister( void ); - - void Spawn( void ); - void Precache( void ); - virtual void OnRestore(); - bool CreateVPhysics(); - - DECLARE_DATADESC(); - virtual void VPhysicsUpdate( IPhysicsObject *pPhysics ); - - virtual QAngle PreferredCarryAngles( void ) { return QAngle( -90, 0, 0 ); } - virtual bool HasPreferredCarryAnglesForPlayer( CBasePlayer *pPlayer ) { return true; } - - // - // Input handlers. - // - void InputActivate(inputdata_t &data); - void InputDeactivate(inputdata_t &data); - void InputExplode(inputdata_t &data); - void InputWake( inputdata_t &data ); - - bool TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ); - - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - - int ObjectCaps() - { - return (BaseClass::ObjectCaps() | FCAP_IMPULSE_USE); - } - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) - { - CBasePlayer *pPlayer = ToBasePlayer( pActivator ); - if ( pPlayer ) - { - pPlayer->PickupObject( this ); - } - } - - void CannisterActivate( CBaseEntity *pActivator, const Vector &thrustOffset ); - void CannisterFire( CBaseEntity *pActivator ); - void Deactivate( void ); - void Explode( CBaseEntity *pAttacker ); - void ExplodeTouch( CBaseEntity *pOther ); - void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); - - // Don't treat as a live target - virtual bool IsAlive( void ) { return false; } - - virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &dir, trace_t *ptr ); - - void ShutdownJet( void ); - void BeginShutdownThink( void ); - -public: - virtual bool OnAttemptPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) { return true; } - virtual void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ); - virtual void OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t reason ); - virtual CBasePlayer *HasPhysicsAttacker( float dt ); - virtual bool ShouldPuntUseLaunchForces( PhysGunForce_t reason ) - { - if ( reason == PHYSGUN_FORCE_LAUNCHED ) - return (m_thrustTime!=0); - - return false; - } - virtual AngularImpulse PhysGunLaunchAngularImpulse( void ) { return vec3_origin; } - virtual Vector PhysGunLaunchVelocity( const Vector &forward, float flMass ) { return vec3_origin; } - -protected: - void SetPhysicsAttacker( CBasePlayer *pEntity, float flTime ); - - -public: - Vector m_thrustOrigin; - CThrustController m_thruster; - IPhysicsMotionController *m_pController; - CSteamJet *m_pJet; - bool m_active; - float m_thrustTime; - float m_damage; - float m_damageRadius; - - float m_activateTime; - string_t m_gasSound; - - bool m_bFired; // True if this cannister was fire by a weapon - - COutputEvent m_onActivate; - COutputEvent m_OnAwakened; - - CHandle m_hPhysicsAttacker; - float m_flLastPhysicsInfluenceTime; - EHANDLE m_hLauncher; // Entity that caused this cannister to launch - -private: - Vector CalcLocalThrust( const Vector &offset ); -}; - -#endif // PHYSICS_CANNISTER_H diff --git a/game/server/physics_collisionevent.h b/game/server/physics_collisionevent.h deleted file mode 100644 index 972f7274f..000000000 --- a/game/server/physics_collisionevent.h +++ /dev/null @@ -1,176 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Pulling CCollisionEvent's definition out of physics.cpp so it can be abstracted upon (for the portal mod) -// -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef PHYSICS_COLLISIONEVENT_H -#define PHYSICS_COLLISIONEVENT_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "physics.h" -#include "tier1/callqueue.h" - -extern CCallQueue g_PostSimulationQueue; - -struct damageevent_t -{ - CBaseEntity *pEntity; - IPhysicsObject *pInflictorPhysics; - CTakeDamageInfo info; - bool bRestoreVelocity; -}; - -struct inflictorstate_t -{ - Vector savedVelocity; - AngularImpulse savedAngularVelocity; - IPhysicsObject *pInflictorPhysics; - float otherMassMax; - short nextIndex; - short restored; -}; - -enum -{ - COLLSTATE_ENABLED = 0, - COLLSTATE_TRYDISABLE = 1, - COLLSTATE_TRYNPCSOLVER = 2, - COLLSTATE_TRYENTITYSOLVER = 3, - COLLSTATE_DISABLED = 4 -}; - -struct penetrateevent_t -{ - EHANDLE hEntity0; - EHANDLE hEntity1; - float startTime; - float timeStamp; - int collisionState; -}; - -class CCollisionEvent : public IPhysicsCollisionEvent, public IPhysicsCollisionSolver, public IPhysicsObjectEvent -{ -public: - CCollisionEvent(); - friction_t *FindFriction( CBaseEntity *pObject ); - void ShutdownFriction( friction_t &friction ); - void FrameUpdate(); - void LevelShutdown( void ); - - // IPhysicsCollisionEvent - void PreCollision( vcollisionevent_t *pEvent ); - void PostCollision( vcollisionevent_t *pEvent ); - void Friction( IPhysicsObject *pObject, float energy, int surfaceProps, int surfacePropsHit, IPhysicsCollisionData *pData ); - void StartTouch( IPhysicsObject *pObject1, IPhysicsObject *pObject2, IPhysicsCollisionData *pTouchData ); - void EndTouch( IPhysicsObject *pObject1, IPhysicsObject *pObject2, IPhysicsCollisionData *pTouchData ); - void FluidStartTouch( IPhysicsObject *pObject, IPhysicsFluidController *pFluid ); - void FluidEndTouch( IPhysicsObject *pObject, IPhysicsFluidController *pFluid ); - void PostSimulationFrame(); - void ObjectEnterTrigger( IPhysicsObject *pTrigger, IPhysicsObject *pObject ); - void ObjectLeaveTrigger( IPhysicsObject *pTrigger, IPhysicsObject *pObject ); - - bool GetTriggerEvent( triggerevent_t *pEvent, CBaseEntity *pTriggerEntity ); - void BufferTouchEvents( bool enable ) { m_bBufferTouchEvents = enable; } - virtual void AddDamageEvent( CBaseEntity *pEntity, const CTakeDamageInfo &info, IPhysicsObject *pInflictorPhysics, bool bRestoreVelocity, const Vector &savedVel, const AngularImpulse &savedAngVel ); - void AddImpulseEvent( IPhysicsObject *pPhysicsObject, const Vector &vecCenterForce, const AngularImpulse &vecCenterTorque ); - void AddSetVelocityEvent( IPhysicsObject *pPhysicsObject, const Vector &vecVelocity ); - void AddRemoveObject(IServerNetworkable *pRemove); - void FlushQueuedOperations(); - - // IPhysicsCollisionSolver - int ShouldCollide( IPhysicsObject *pObj0, IPhysicsObject *pObj1, void *pGameData0, void *pGameData1 ); - int ShouldSolvePenetration( IPhysicsObject *pObj0, IPhysicsObject *pObj1, void *pGameData0, void *pGameData1, float dt ); - bool ShouldFreezeObject( IPhysicsObject *pObject ); - static const char *ModuleName() { return CBaseEntity::IsServer() ? "SERVER" : "CLIENT"; } - int AdditionalCollisionChecksThisTick( int currentChecksDone ) - { - //CallbackContext check(this); - if ( currentChecksDone < 1200 ) - { - DevMsg(1,"%s: VPhysics Collision detection getting expensive, check for too many convex pieces!\n", ModuleName()); - return 1200 - currentChecksDone; - } - DevMsg(1,"%s: VPhysics exceeded collision check limit (%d)!!!\nInterpenetration may result!\n", ModuleName(), currentChecksDone ); - return 0; - } - bool ShouldFreezeContacts( IPhysicsObject **pObjectList, int objectCount ); - - // IPhysicsObjectEvent - // these can be used to optimize out queries on sleeping objects - // Called when an object is woken after sleeping - virtual void ObjectWake( IPhysicsObject *pObject ); - // called when an object goes to sleep (no longer simulating) - virtual void ObjectSleep( IPhysicsObject *pObject ); - - - // locals - bool GetInflictorVelocity( IPhysicsObject *pInflictor, Vector &velocity, AngularImpulse &angVelocity ); - - void GetListOfPenetratingEntities( CBaseEntity *pSearch, CUtlVector &list ); - bool IsInCallback() { return m_inCallback > 0 ? true : false; } - -private: -#if _DEBUG - int ShouldCollide_2( IPhysicsObject *pObj0, IPhysicsObject *pObj1, void *pGameData0, void *pGameData1 ); -#endif - - void UpdateFrictionSounds(); - void UpdateTouchEvents(); - void UpdateDamageEvents(); - void UpdatePenetrateEvents( void ); - void UpdateFluidEvents(); - void UpdateRemoveObjects(); - void AddTouchEvent( CBaseEntity *pEntity0, CBaseEntity *pEntity1, int touchType, const Vector &point, const Vector &normal ); - penetrateevent_t &FindOrAddPenetrateEvent( CBaseEntity *pEntity0, CBaseEntity *pEntity1 ); - float DeltaTimeSinceLastFluid( CBaseEntity *pEntity ); - - void RestoreDamageInflictorState( IPhysicsObject *pInflictor ); - void RestoreDamageInflictorState( int inflictorStateIndex, float velocityBlend ); - int AddDamageInflictor( IPhysicsObject *pInflictorPhysics, float otherMass, const Vector &savedVel, const AngularImpulse &savedAngVel, bool addList ); - int FindDamageInflictor( IPhysicsObject *pInflictorPhysics ); - - // make the call into the entity system - void DispatchStartTouch( CBaseEntity *pEntity0, CBaseEntity *pEntity1, const Vector &point, const Vector &normal ); - void DispatchEndTouch( CBaseEntity *pEntity0, CBaseEntity *pEntity1 ); - - class CallbackContext - { - public: - CallbackContext(CCollisionEvent *pOuter) - { - m_pOuter = pOuter; - m_pOuter->m_inCallback++; - } - ~CallbackContext() - { - m_pOuter->m_inCallback--; - } - private: - CCollisionEvent *m_pOuter; - }; - friend class CallbackContext; - - friction_t m_current[4]; - gamevcollisionevent_t m_gameEvent; - CUtlVector m_triggerEvents; - triggerevent_t m_currentTriggerEvent; - CUtlVector m_touchEvents; - CUtlVector m_damageEvents; - CUtlVector m_damageInflictors; - CUtlVector m_penetrateEvents; - CUtlVector m_fluidEvents; - CUtlVector m_removeObjects; - int m_inCallback; - int m_lastTickFrictionError; // counter to control printing of the dev warning for large contact systems - bool m_bBufferTouchEvents; -}; - -#endif //#ifndef PHYSICS_COLLISIONEVENT_H diff --git a/game/server/physics_fx.cpp b/game/server/physics_fx.cpp deleted file mode 100644 index e1532466f..000000000 --- a/game/server/physics_fx.cpp +++ /dev/null @@ -1,238 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "physics.h" -#include "te_effect_dispatch.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -static int BestAxisMatchingNormal( matrix3x4_t &matrix, const Vector &normal ) -{ - float bestDot = -1; - int best = 0; - for ( int i = 0; i < 3; i++ ) - { - Vector tmp; - MatrixGetColumn( matrix, i, tmp ); - float dot = fabs(DotProduct( tmp, normal )); - if ( dot > bestDot ) - { - bestDot = dot; - best = i; - } - } - - return best; -} - -void PhysicsSplash( IPhysicsFluidController *pFluid, IPhysicsObject *pObject, CBaseEntity *pEntity ) -{ - Vector normal; - float dist; - pFluid->GetSurfacePlane( &normal, &dist ); - - matrix3x4_t &matrix = pEntity->EntityToWorldTransform(); - - // Find the local axis that best matches the water surface normal - int bestAxis = BestAxisMatchingNormal( matrix, normal ); - - Vector tangent, binormal; - MatrixGetColumn( matrix, (bestAxis+1)%3, tangent ); - binormal = CrossProduct( normal, tangent ); - VectorNormalize( binormal ); - tangent = CrossProduct( binormal, normal ); - VectorNormalize( tangent ); - - // Now we have a basis tangent to the surface that matches the object's local orientation as well as possible - // compute an OBB using this basis - - // Get object extents in basis - Vector tanPts[2], binPts[2]; - tanPts[0] = physcollision->CollideGetExtent( pObject->GetCollide(), pEntity->GetAbsOrigin(), pEntity->GetAbsAngles(), -tangent ); - tanPts[1] = physcollision->CollideGetExtent( pObject->GetCollide(), pEntity->GetAbsOrigin(), pEntity->GetAbsAngles(), tangent ); - binPts[0] = physcollision->CollideGetExtent( pObject->GetCollide(), pEntity->GetAbsOrigin(), pEntity->GetAbsAngles(), -binormal ); - binPts[1] = physcollision->CollideGetExtent( pObject->GetCollide(), pEntity->GetAbsOrigin(), pEntity->GetAbsAngles(), binormal ); - - // now compute the centered bbox - float mins[2], maxs[2], center[2], extents[2]; - mins[0] = DotProduct( tanPts[0], tangent ); - maxs[0] = DotProduct( tanPts[1], tangent ); - - mins[1] = DotProduct( binPts[0], binormal ); - maxs[1] = DotProduct( binPts[1], binormal ); - - center[0] = 0.5 * (mins[0] + maxs[0]); - center[1] = 0.5 * (mins[1] + maxs[1]); - - extents[0] = maxs[0] - center[0]; - extents[1] = maxs[1] - center[1]; - - Vector centerPoint = center[0] * tangent + center[1] * binormal + dist * normal; - - Vector axes[2]; - axes[0] = (maxs[0] - center[0]) * tangent; - axes[1] = (maxs[1] - center[1]) * binormal; - - // visualize OBB hit - /* - Vector corner1 = centerPoint - axes[0] - axes[1]; - Vector corner2 = centerPoint + axes[0] - axes[1]; - Vector corner3 = centerPoint + axes[0] + axes[1]; - Vector corner4 = centerPoint - axes[0] + axes[1]; - NDebugOverlay::Line( corner1, corner2, 0, 0, 255, false, 10 ); - NDebugOverlay::Line( corner2, corner3, 0, 0, 255, false, 10 ); - NDebugOverlay::Line( corner3, corner4, 0, 0, 255, false, 10 ); - NDebugOverlay::Line( corner4, corner1, 0, 0, 255, false, 10 ); - */ - - Vector corner[4]; - - corner[0] = centerPoint - axes[0] - axes[1]; - corner[1] = centerPoint + axes[0] - axes[1]; - corner[2] = centerPoint + axes[0] + axes[1]; - corner[3] = centerPoint - axes[0] + axes[1]; - - CEffectData data; - - if ( pObject->GetGameFlags() & FVPHYSICS_PART_OF_RAGDOLL ) - { - /* - data.m_vOrigin = centerPoint; - data.m_vNormal = normal; - VectorAngles( normal, data.m_vAngles ); - data.m_flScale = random->RandomFloat( 8, 10 ); - - DispatchEffect( "watersplash", data ); - - int splashes = 4; - Vector point; - - for ( int i = 0; i < splashes; i++ ) - { - point = RandomVector( -32.0f, 32.0f ); - point[2] = 0.0f; - - point += corner[i]; - - data.m_vOrigin = point; - data.m_vNormal = normal; - VectorAngles( normal, data.m_vAngles ); - data.m_flScale = random->RandomFloat( 4, 6 ); - - DispatchEffect( "watersplash", data ); - } - */ - - //FIXME: This code will not work correctly given how the ragdoll/fluid collision is acting currently - return; - } - - Vector vel; - pObject->GetVelocity( &vel, NULL ); - float rawSpeed = -DotProduct( normal, vel ); - - // proportional to cross-sectional area times velocity squared (fluid pressure) - float speed = rawSpeed * rawSpeed * extents[0] * extents[1] * (1.0f / 2500000.0f) * pObject->GetMass() * (0.01f); - - speed = clamp( speed, 0, 50 ); - - bool bRippleOnly = false; - - // allow the entity to perform a custom splash effect - if ( pEntity->PhysicsSplash( centerPoint, normal, rawSpeed, speed ) ) - return; - - //Deny really weak hits - //FIXME: We still need to ripple the surface in this case - if ( speed <= 0.35f ) - { - if ( speed <= 0.1f ) - return; - - bRippleOnly = true; - } - - float size = RemapVal( speed, 0.35, 50, 8, 18 ); - - //Find the surface area - float radius = extents[0] * extents[1]; - //int splashes = clamp ( radius / 128.0f, 1, 2 ); //One splash for every three square feet of area - - //Msg( "Speed: %.2f, Size: %.2f\n, Radius: %.2f, Splashes: %d", speed, size, radius, splashes ); - - Vector point; - - data.m_fFlags = 0; - data.m_vOrigin = centerPoint; - data.m_vNormal = normal; - VectorAngles( normal, data.m_vAngles ); - data.m_flScale = size + random->RandomFloat( 0, 2 ); - if ( pEntity->GetWaterType() & CONTENTS_SLIME ) - { - data.m_fFlags |= FX_WATER_IN_SLIME; - } - - if ( bRippleOnly ) - { - DispatchEffect( "waterripple", data ); - } - else - { - DispatchEffect( "watersplash", data ); - } - - if ( radius > 500.0f ) - { - int splashes = random->RandomInt( 1, 4 ); - - for ( int i = 0; i < splashes; i++ ) - { - point = RandomVector( -4.0f, 4.0f ); - point[2] = 0.0f; - - point += corner[i]; - - data.m_fFlags = 0; - data.m_vOrigin = point; - data.m_vNormal = normal; - VectorAngles( normal, data.m_vAngles ); - data.m_flScale = size + random->RandomFloat( -3, 1 ); - if ( pEntity->GetWaterType() & CONTENTS_SLIME ) - { - data.m_fFlags |= FX_WATER_IN_SLIME; - } - - if ( bRippleOnly ) - { - DispatchEffect( "waterripple", data ); - } - else - { - DispatchEffect( "watersplash", data ); - } - } - } - - /* - for ( i = 0; i < splashes; i++ ) - { - point = RandomVector( -8.0f, 8.0f ); - point[2] = 0.0f; - - point += centerPoint + axes[0] * random->RandomFloat( -1, 1 ) + axes[1] * random->RandomFloat( -1, 1 ); - - data.m_vOrigin = point; - data.m_vNormal = normal; - VectorAngles( normal, data.m_vAngles ); - data.m_flScale = size + random->RandomFloat( -2, 4 ); - - DispatchEffect( "watersplash", data ); - } - */ -} diff --git a/game/server/physics_fx.h b/game/server/physics_fx.h deleted file mode 100644 index 7fbe9aef6..000000000 --- a/game/server/physics_fx.h +++ /dev/null @@ -1,19 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef PHYSICS_FX_H -#define PHYSICS_FX_H -#ifdef _WIN32 -#pragma once -#endif - - -class CBaseEntity; -class IPhysicsFluidController; - -void PhysicsSplash( IPhysicsFluidController *pFluid, IPhysicsObject *pObject, CBaseEntity *pEntity ); - -#endif // PHYSICS_FX_H diff --git a/game/server/physics_impact_damage.cpp b/game/server/physics_impact_damage.cpp deleted file mode 100644 index 73be849f0..000000000 --- a/game/server/physics_impact_damage.cpp +++ /dev/null @@ -1,777 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "physics_impact_damage.h" -#include "shareddefs.h" -#include "vphysics/friction.h" -#include "vphysics/player_controller.h" -#include "world.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//============================================================================================== -// PLAYER PHYSICS DAMAGE TABLE -//============================================================================================== -static impactentry_t playerLinearTable[] = -{ - { 150*150, 5 }, - { 250*250, 10 }, - { 450*450, 20 }, - { 550*550, 50 }, - { 700*700, 100 }, - { 1000*1000, 500 }, -}; - -static impactentry_t playerAngularTable[] = -{ - { 100*100, 10 }, - { 150*150, 20 }, - { 200*200, 50 }, - { 300*300, 500 }, -}; - -impactdamagetable_t gDefaultPlayerImpactDamageTable = -{ - playerLinearTable, - playerAngularTable, - - ARRAYSIZE(playerLinearTable), - ARRAYSIZE(playerAngularTable), - - 24*24.0f, // minimum linear speed - 360*360.0f, // minimum angular speed - 2.0f, // can't take damage from anything under 2kg - - 5.0f, // anything less than 5kg is "small" - 5.0f, // never take more than 5 pts of damage from anything under 5kg - 36*36.0f, // <5kg objects must go faster than 36 in/s to do damage - - 0.0f, // large mass in kg (no large mass effects) - 1.0f, // large mass scale - 2.0f, // large mass falling scale - 320.0f, // min velocity for player speed to cause damage - -}; - -//============================================================================================== -// PLAYER-IN-VEHICLE PHYSICS DAMAGE TABLE -//============================================================================================== -static impactentry_t playerVehicleLinearTable[] = -{ - { 450*450, 5 }, - { 600*600, 10 }, - { 700*700, 25 }, - { 1000*1000, 50 }, - { 1500*1500, 100 }, - { 2000*2000, 500 }, -}; - -static impactentry_t playerVehicleAngularTable[] = -{ - { 100*100, 10 }, - { 150*150, 20 }, - { 200*200, 50 }, - { 300*300, 500 }, -}; - -impactdamagetable_t gDefaultPlayerVehicleImpactDamageTable = -{ - playerVehicleLinearTable, - playerVehicleAngularTable, - - ARRAYSIZE(playerVehicleLinearTable), - ARRAYSIZE(playerVehicleAngularTable), - - 24*24, // minimum linear speed - 360*360, // minimum angular speed - 80, // can't take damage from anything under 80 kg - - 150, // anything less than 150kg is "small" - 5, // never take more than 5 pts of damage from anything under 150kg - 36*36, // <150kg objects must go faster than 36 in/s to do damage - - 0, // large mass in kg (no large mass effects) - 1.0f, // large mass scale - 1.0f, // large mass falling scale - 0.0f, // min vel -}; - - -//============================================================================================== -// NPC PHYSICS DAMAGE TABLE -//============================================================================================== -static impactentry_t npcLinearTable[] = -{ - { 150*150, 5 }, - { 250*250, 10 }, - { 350*350, 50 }, - { 500*500, 100 }, - { 1000*1000, 500 }, -}; - -static impactentry_t npcAngularTable[] = -{ - { 100*100, 10 }, - { 150*150, 25 }, - { 200*200, 50 }, - { 250*250, 500 }, -}; - -impactdamagetable_t gDefaultNPCImpactDamageTable = -{ - npcLinearTable, - npcAngularTable, - - ARRAYSIZE(npcLinearTable), - ARRAYSIZE(npcAngularTable), - - 24*24, // minimum linear speed squared - 360*360, // minimum angular speed squared (360 deg/s to cause spin/slice damage) - 2, // can't take damage from anything under 2kg - - 5, // anything less than 5kg is "small" - 5, // never take more than 5 pts of damage from anything under 5kg - 36*36, // <5kg objects must go faster than 36 in/s to do damage - - VPHYSICS_LARGE_OBJECT_MASS, // large mass in kg - 4, // large mass scale (anything over 500kg does 4X as much energy to read from damage table) - 5, // large mass falling scale (emphasize falling/crushing damage over sideways impacts since the stress will kill you anyway) - 0.0f, // min vel -}; - -//============================================================================================== -// GLASS DAMAGE TABLE -//============================================================================================== -static impactentry_t glassLinearTable[] = -{ - { 25*25, 10 }, - { 50*50, 20 }, - { 100*100, 50 }, - { 200*200, 75 }, - { 500*500, 100 }, - { 250*250, 500 }, -}; - -static impactentry_t glassAngularTable[] = -{ - { 50*50, 25 }, - { 100*100, 50 }, - { 200*200, 100 }, - { 250*250, 500 }, -}; - -impactdamagetable_t gGlassImpactDamageTable = -{ - glassLinearTable, - glassAngularTable, - - ARRAYSIZE(glassLinearTable), - ARRAYSIZE(glassAngularTable), - - 8*8, // minimum linear speed squared - 360*360, // minimum angular speed squared (360 deg/s to cause spin/slice damage) - 2, // can't take damage from anything under 2kg - - 1, // anything less than 1kg is "small" - 10, // never take more than 10 pts of damage from anything under 1kg - 8*8, // <1kg objects must go faster than 8 in/s to do damage - - 50, // large mass in kg - 4, // large mass scale (anything over 50kg does 4X as much energy to read from damage table) - 0.0f, // min vel -}; - -//============================================================================================== -// PHYSICS TABLE NAMES -//============================================================================================== -struct damagetable_t -{ - const char *pszTableName; - impactdamagetable_t *pTable; -}; - -static damagetable_t gDamageTableRegistry[] = -{ - { - "player", - &gDefaultPlayerImpactDamageTable, - }, - { - "player_vehicle", - &gDefaultPlayerVehicleImpactDamageTable, - }, - { - "npc", - &gDefaultNPCImpactDamageTable, - }, - { - "glass", - &gGlassImpactDamageTable, - }, -}; - -//============================================================================================== -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float ReadDamageTable( impactentry_t *pTable, int tableCount, float impulse, bool bDebug ) -{ - if ( pTable ) - { - int i; - for ( i = 0; i < tableCount; i++ ) - { - if ( impulse < pTable[i].impulse ) - break; - } - if ( i > 0 ) - { - i--; - if ( bDebug ) - { - Msg("Damage %.0f, energy %.0f\n", pTable[i].damage, FastSqrt(impulse) ); - } - return pTable[i].damage; - } - } - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CalculatePhysicsImpactDamage( int index, gamevcollisionevent_t *pEvent, const impactdamagetable_t &table, float energyScale, bool allowStaticDamage, int &damageType, bool bDamageFromHeldObjects ) -{ - damageType = DMG_CRUSH; - int otherIndex = !index; - - // UNDONE: Expose a flag for self-inflicted damage? Can't think of a valid case so far. - if ( pEvent->pEntities[0] == pEvent->pEntities[1] ) - return 0; - - if ( pEvent->pObjects[otherIndex]->GetGameFlags() & FVPHYSICS_NO_NPC_IMPACT_DMG ) - { - if( pEvent->pEntities[index]->IsNPC() || pEvent->pEntities[index]->IsPlayer() ) - { - return 0; - } - } - - // use implicit velocities on ragdolls since they may have high constraint velocities that aren't actually executed, just pushed through contacts - if (( pEvent->pObjects[otherIndex]->GetGameFlags() & FVPHYSICS_PART_OF_RAGDOLL) && pEvent->pEntities[index]->IsPlayer() ) - { - pEvent->pObjects[otherIndex]->GetImplicitVelocity( &pEvent->preVelocity[otherIndex], &pEvent->preAngularVelocity[otherIndex] ); - } - - // Dissolving impact damage results in death always. - if ( ( pEvent->pObjects[otherIndex]->GetGameFlags() & FVPHYSICS_DMG_DISSOLVE ) && - !pEvent->pEntities[index]->IsEFlagSet(EFL_NO_DISSOLVE) ) - { - damageType |= DMG_DISSOLVE; - return 1000; - } - - if ( energyScale <= 0.0f ) - return 0; - - const int gameFlagsNoDamage = FVPHYSICS_CONSTRAINT_STATIC | FVPHYSICS_NO_IMPACT_DMG; - - // NOTE: Crushing damage is handled by stress calcs in vphysics update functions, this is ONLY impact damage - // this is a non-moving object due to a constraint - no damage - if ( pEvent->pObjects[otherIndex]->GetGameFlags() & gameFlagsNoDamage ) - return 0; - - // If it doesn't take damage from held objects and the object is being held - no damage - if ( !bDamageFromHeldObjects && ( pEvent->pObjects[otherIndex]->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) ) - { - // If it doesn't take damage from held objects - no damage - if ( !bDamageFromHeldObjects ) - return 0; - } - - if ( pEvent->pObjects[otherIndex]->GetGameFlags() & FVPHYSICS_MULTIOBJECT_ENTITY ) - { - // UNDONE: Add up mass here for car wheels and prop_ragdoll pieces? - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int count = pEvent->pEntities[otherIndex]->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - for ( int i = 0; i < count; i++ ) - { - if ( pList[i]->GetGameFlags() & gameFlagsNoDamage ) - return 0; - } - } - - if ( pEvent->pObjects[index]->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - { - // players can't damage held objects - if ( pEvent->pEntities[otherIndex]->IsPlayer() ) - return 0; - - allowStaticDamage = false; - } - -#if 0 - { - PhysGetDamageInflictorVelocityStartOfFrame( pEvent->pObjects[otherIndex], pEvent->preVelocity[otherIndex], pEvent->preAngularVelocity[otherIndex] ); - } -#endif - - float otherSpeedSqr = pEvent->preVelocity[otherIndex].LengthSqr(); - float otherAngSqr = 0; - - // factor in angular for sharp objects - if ( pEvent->pObjects[otherIndex]->GetGameFlags() & FVPHYSICS_DMG_SLICE ) - { - otherAngSqr = pEvent->preAngularVelocity[otherIndex].LengthSqr(); - } - - float otherMass = pEvent->pObjects[otherIndex]->GetMass(); - - if ( pEvent->pObjects[otherIndex]->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - { - // if the player is holding the object, use its real mass (player holding reduced the mass) - - CBasePlayer *pPlayer = NULL; - - if ( 1 == gpGlobals->maxClients ) - { - pPlayer = UTIL_GetLocalPlayer(); - } - else - { - // See which MP player is holding the physics object and then use that player to get the real mass of the object. - // This is ugly but better than having linkage between an object and its "holding" player. - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *tempPlayer = UTIL_PlayerByIndex( i ); - if ( tempPlayer && pEvent->pEntities[index] == tempPlayer->GetHeldObject() ) - { - pPlayer = tempPlayer; - break; - } - } - } - - if ( pPlayer ) - { - otherMass = pPlayer->GetHeldObjectMass( pEvent->pObjects[otherIndex] ); - } - } - - // NOTE: sum the mass of each object in this system for the purpose of damage - if ( pEvent->pEntities[otherIndex] && (pEvent->pObjects[otherIndex]->GetGameFlags() & FVPHYSICS_MULTIOBJECT_ENTITY) ) - { - otherMass = PhysGetEntityMass( pEvent->pEntities[otherIndex] ); - } - - if ( pEvent->pObjects[otherIndex]->GetGameFlags() & FVPHYSICS_HEAVY_OBJECT ) - { - otherMass = table.largeMassMin; - if ( energyScale < 2.0f ) - { - energyScale = 2.0f; - } - } - - // UNDONE: allowStaticDamage is a hack - work out some method for - // breakable props to impact the world and break!! - if ( !allowStaticDamage ) - { - if ( otherMass < table.minMass ) - return 0; - // check to see if the object is small - if ( otherMass < table.smallMassMax && otherSpeedSqr < table.smallMassMinSpeedSqr ) - return 0; - - if ( otherSpeedSqr < table.minSpeedSqr && otherAngSqr < table.minRotSpeedSqr ) - return 0; - } - - // Add extra oomph for floating objects - if ( pEvent->pEntities[index]->IsFloating() && !pEvent->pEntities[otherIndex]->IsWorld() ) - { - if ( energyScale < 3.0f ) - { - energyScale = 3.0f; - } - } - - float damage = 0; - bool bDebug = false;//(&table == &gDefaultPlayerImpactDamageTable); - - // don't ever take spin damage from slowly spinning objects - if ( otherAngSqr > table.minRotSpeedSqr ) - { - Vector otherInertia = pEvent->pObjects[otherIndex]->GetInertia(); - float angularMom = DotProductAbs( otherInertia, pEvent->preAngularVelocity[otherIndex] ); - damage = ReadDamageTable( table.angularTable, table.angularCount, angularMom * energyScale, bDebug ); - if ( damage > 0 ) - { -// Msg("Spin : %.1f, Damage %.0f\n", FastSqrt(angularMom), damage ); - damageType |= DMG_SLASH; - } - } - - float deltaV = pEvent->preVelocity[index].Length() - pEvent->postVelocity[index].Length(); - float mass = pEvent->pObjects[index]->GetMass(); - - // If I lost speed, and I lost less than min velocity, then filter out this energy - if ( deltaV > 0 && deltaV < table.myMinVelocity ) - { - deltaV = 0; - } - float eliminatedEnergy = deltaV * deltaV * mass; - - deltaV = pEvent->preVelocity[otherIndex].Length() - pEvent->postVelocity[otherIndex].Length(); - float otherEliminatedEnergy = deltaV * deltaV * otherMass; - - // exaggerate the effects of really large objects - if ( otherMass >= table.largeMassMin ) - { - otherEliminatedEnergy *= table.largeMassScale; - float dz = pEvent->preVelocity[otherIndex].z - pEvent->postVelocity[otherIndex].z; - - if ( deltaV > 0 && dz < 0 && pEvent->preVelocity[otherIndex].z < 0 ) - { - float factor = fabs(dz / deltaV); - otherEliminatedEnergy *= (1 + factor * (table.largeMassFallingScale - 1.0f)); - } - } - - eliminatedEnergy += otherEliminatedEnergy; - - // now in units of this character's speed squared - float invMass = pEvent->pObjects[index]->GetInvMass(); - if ( !pEvent->pObjects[index]->IsMoveable() ) - { - // inv mass is zero, but impact damage is enabled on this - // prop, so recompute: - invMass = 1.0f / pEvent->pObjects[index]->GetMass(); - } - else if ( pEvent->pObjects[index]->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - { - // if the player is holding the object, use it's real mass (player holding reduced the mass) - - CBasePlayer *pPlayer = NULL; - if ( 1 == gpGlobals->maxClients ) - { - pPlayer = UTIL_GetLocalPlayer(); - } - else - { - // See which MP player is holding the physics object and then use that player to get the real mass of the object. - // This is ugly but better than having linkage between an object and its "holding" player. - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *tempPlayer = UTIL_PlayerByIndex( i ); - if ( tempPlayer && pEvent->pEntities[index] == tempPlayer->GetHeldObject() ) - { - pPlayer = tempPlayer; - break; - } - } - } - - if ( pPlayer ) - { - float mass = pPlayer->GetHeldObjectMass( pEvent->pObjects[index] ); - if ( mass > 0 ) - { - invMass = 1.0f / mass; - } - } - } - - eliminatedEnergy *= invMass * energyScale; - - damage += ReadDamageTable( table.linearTable, table.linearCount, eliminatedEnergy, bDebug ); - - if ( !pEvent->pObjects[otherIndex]->IsStatic() && otherMass < table.smallMassMax && table.smallMassCap > 0 ) - { - damage = clamp( damage, 0, table.smallMassCap ); - } - - return damage; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CalculateDefaultPhysicsDamage( int index, gamevcollisionevent_t *pEvent, float energyScale, bool allowStaticDamage, int &damageType, string_t iszDamageTableName, bool bDamageFromHeldObjects ) -{ - // If we have a specified damage table, find it and use it instead - if ( iszDamageTableName != NULL_STRING ) - { - for ( size_t i = 0; i < ARRAYSIZE(gDamageTableRegistry); i++ ) - { - if ( !Q_strcmp( gDamageTableRegistry[i].pszTableName, STRING(iszDamageTableName) ) ) - return CalculatePhysicsImpactDamage( index, pEvent, *(gDamageTableRegistry[i].pTable), energyScale, allowStaticDamage, damageType, bDamageFromHeldObjects ); - } - - Warning("Failed to find custom physics damage table name: %s\n", STRING(iszDamageTableName) ); - } - - return CalculatePhysicsImpactDamage( index, pEvent, gDefaultNPCImpactDamageTable, energyScale, allowStaticDamage, damageType, bDamageFromHeldObjects ); -} - -static bool IsPhysicallyControlled( CBaseEntity *pEntity, IPhysicsObject *pPhysics ) -{ - bool isPhysical = false; - if ( pEntity->GetMoveType() == MOVETYPE_VPHYSICS ) - { - isPhysical = true; - } - else - { - if ( pPhysics->GetShadowController() ) - { - isPhysical = pPhysics->GetShadowController()->IsPhysicallyControlled(); - } - } - return isPhysical; -} -float CalculateObjectStress( IPhysicsObject *pObject, CBaseEntity *pInputOwnerEntity, vphysics_objectstress_t *pOutput ) -{ - CUtlVector< CBaseEntity * > pObjectList; - CUtlVector< Vector > objectForce; - bool hasLargeObject = false; - - // add a slot for static objects - pObjectList.AddToTail( NULL ); - objectForce.AddToTail( vec3_origin ); - // add a slot for friendly objects - pObjectList.AddToTail( NULL ); - objectForce.AddToTail( vec3_origin ); - - CBaseCombatCharacter *pBCC = pInputOwnerEntity->MyCombatCharacterPointer(); - - IPhysicsFrictionSnapshot *pSnapshot = pObject->CreateFrictionSnapshot(); - float objMass = pObject->GetMass(); - while ( pSnapshot->IsValid() ) - { - float force = pSnapshot->GetNormalForce(); - if ( force > 0.0f ) - { - IPhysicsObject *pOther = pSnapshot->GetObject(1); - CBaseEntity *pOtherEntity = static_cast(pOther->GetGameData()); - if ( !pOtherEntity ) - { - // object was just deleted, but we still have a contact point this frame... - // just assume it came from the world. - pOtherEntity = GetWorldEntity(); - } - CBaseEntity *pOtherOwner = pOtherEntity; - if ( pOtherEntity->GetOwnerEntity() ) - { - pOtherOwner = pOtherEntity->GetOwnerEntity(); - } - - int outIndex = 0; - if ( !pOther->IsMoveable() ) - { - outIndex = 0; - } - // NavIgnored objects are often being pushed by a friendly - else if ( pBCC && (pBCC->IRelationType( pOtherOwner ) == D_LI || pOtherEntity->IsNavIgnored()) ) - { - outIndex = 1; - } - // player held objects do no stress - else if ( pOther->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - { - outIndex = 1; - } - else - { - if ( pOther->GetMass() >= VPHYSICS_LARGE_OBJECT_MASS ) - { - if ( pInputOwnerEntity->GetGroundEntity() != pOtherEntity) - { - hasLargeObject = true; - } - } - // moveable, non-friendly - - // aggregate contacts over each object to avoid greater stress in multiple contact cases - // NOTE: Contacts should be in order, so this shouldn't ever search, but just in case - outIndex = pObjectList.Count(); - for ( int i = pObjectList.Count()-1; i >= 2; --i ) - { - if ( pObjectList[i] == pOtherOwner ) - { - outIndex = i; - break; - } - } - if ( outIndex == pObjectList.Count() ) - { - pObjectList.AddToTail( pOtherOwner ); - objectForce.AddToTail( vec3_origin ); - } - } - - if ( outIndex != 0 && pInputOwnerEntity->GetMoveType() != MOVETYPE_VPHYSICS && !IsPhysicallyControlled(pOtherEntity, pOther) ) - { - // UNDONE: Test this! This is to remove any shadow/shadow stress. The game should handle this with blocked/damage - force = 0.0f; - } - - Vector normal; - pSnapshot->GetSurfaceNormal( normal ); - objectForce[outIndex] += normal * force; - } - pSnapshot->NextFrictionData(); - } - pObject->DestroyFrictionSnapshot( pSnapshot ); - pSnapshot = NULL; - - // clear out all friendly force - objectForce[1].Init(); - - float sum = 0; - Vector negativeForce = vec3_origin; - Vector positiveForce = vec3_origin; - - Assert( pObjectList.Count() == objectForce.Count() ); - for ( int objectIndex = pObjectList.Count()-1; objectIndex >= 0; --objectIndex ) - { - sum += objectForce[objectIndex].Length(); - for ( int i = 0; i < 3; i++ ) - { - if ( objectForce[objectIndex][i] < 0 ) - { - negativeForce[i] -= objectForce[objectIndex][i]; - } - else - { - positiveForce[i] += objectForce[objectIndex][i]; - } - } - } - - // "external" stress is two way (something pushes on the object and something else pushes back) - // so the set of minimum values per component are the projections of the two-way force - // "internal" stress is one way (the object is pushing against something OR something pushing back) - // the momentum must have come from inside the object (gravity, controller, etc) - Vector internalForce = vec3_origin; - Vector externalForce = vec3_origin; - - for ( int i = 0; i < 3; i++ ) - { - if ( negativeForce[i] < positiveForce[i] ) - { - internalForce[i] = positiveForce[i] - negativeForce[i]; - externalForce[i] = negativeForce[i]; - } - else - { - internalForce[i] = negativeForce[i] - positiveForce[i]; - externalForce[i] = positiveForce[i]; - } - } - - // sum is kg in / s - Vector gravVector; - physenv->GetGravity( &gravVector ); - float gravity = gravVector.Length(); - if ( pInputOwnerEntity->GetMoveType() != MOVETYPE_VPHYSICS && pObject->IsMoveable() ) - { - Vector lastVel; - lastVel.Init(); - if ( pObject->GetShadowController() ) - { - pObject->GetShadowController()->GetLastImpulse( &lastVel ); - } - else - { - if ( ( pObject->GetCallbackFlags() & CALLBACK_IS_PLAYER_CONTROLLER ) ) - { - CBasePlayer *pPlayer = ToBasePlayer( pInputOwnerEntity ); - IPhysicsPlayerController *pController = pPlayer ? pPlayer->GetPhysicsController() : NULL; - if ( pController ) - { - pController->GetLastImpulse( &lastVel ); - } - } - } - - // Work in progress... - - // Peek into the controller for this object. Look at the input velocity and make sure it's all - // accounted for in the computed stress. If not, redistribute external to internal as it's - // probably being reflected in a way we can't measure here. - float inputLen = lastVel.Length() * (1.0f / physenv->GetSimulationTimestep()) * objMass; - if ( inputLen > 0.0f ) - { - float internalLen = internalForce.Length(); - if ( internalLen < inputLen ) - { - float ratio = internalLen / inputLen; - Vector delta = internalForce * (1.0f - ratio); - internalForce += delta; - float deltaLen = delta.Length(); - sum -= deltaLen; - float extLen = VectorNormalize(externalForce) - deltaLen; - if ( extLen < 0 ) - { - extLen = 0; - } - externalForce *= extLen; - } - } - } - - float invGravity = gravity; - if ( invGravity <= 0 ) - { - invGravity = 1.0f; - } - else - { - invGravity = 1.0f / invGravity; - } - sum *= invGravity; - internalForce *= invGravity; - externalForce *= invGravity; - if ( !pObject->IsMoveable() ) - { - // the above algorithm will see almost all force as internal if the object is not moveable - // (it doesn't push on anything else, so nothing is reciprocated) - // exceptions for friction of a single other object with multiple contact points on this object - - // But the game wants to see it all as external because obviously the object can't move, so it can't have - // internal stress - externalForce = internalForce; - internalForce.Init(); - - if ( !pObject->IsStatic() ) - { - sum += objMass; - } - } - else - { - // assume object is at rest - if ( sum > objMass ) - { - sum = objMass + (sum-objMass) * 0.5; - } - } - - if ( pOutput ) - { - pOutput->exertedStress = internalForce.Length(); - pOutput->receivedStress = externalForce.Length(); - pOutput->hasNonStaticStress = pObjectList.Count() > 2 ? true : false; - pOutput->hasLargeObjectContact = hasLargeObject; - } - - // sum is now kg - return sum; -} diff --git a/game/server/physics_impact_damage.h b/game/server/physics_impact_damage.h deleted file mode 100644 index 389a31c86..000000000 --- a/game/server/physics_impact_damage.h +++ /dev/null @@ -1,66 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef PHYSICS_IMPACT_DAMAGE_H -#define PHYSICS_IMPACT_DAMAGE_H -#ifdef _WIN32 -#pragma once -#endif - - -struct impactentry_t -{ - float impulse; - float damage; -}; - -// UNDONE: Add a flag to turn off aggregation of mass in object systems (e.g. ragdolls, vehicles)? -struct impactdamagetable_t -{ - impactentry_t *linearTable; - impactentry_t *angularTable; - int linearCount; // array size of linearTable - int angularCount; // array size of angularTable - - float minSpeedSqr; // minimum squared impact speed for damage - float minRotSpeedSqr; - float minMass; // minimum mass to do damage - - // filter out reall small objects, set all to zero to disable - float smallMassMax; - float smallMassCap; - float smallMassMinSpeedSqr; - - // exaggerate the effects of really large objects, set all to 1 to disable - float largeMassMin; - float largeMassScale; - float largeMassFallingScale; // emphasize downward impacts so that this will kill instead of stress (we have more information here than there) - float myMinVelocity; // filter out any energy lost by me unless my velocity is greater than this -}; - - - -extern impactdamagetable_t gDefaultNPCImpactDamageTable; -extern impactdamagetable_t gDefaultPlayerImpactDamageTable; -extern impactdamagetable_t gDefaultPlayerVehicleImpactDamageTable; - -// NOTE Default uses default NPC table -float CalculateDefaultPhysicsDamage( int index, gamevcollisionevent_t *pEvent, float energyScale, bool allowStaticDamage, int &damageTypeOut, string_t iszDamageTableName = NULL_STRING, bool bDamageFromHeldObjects = false ); - -// use passes in the table -float CalculatePhysicsImpactDamage( int index, gamevcollisionevent_t *pEvent, const impactdamagetable_t &table, float energyScale, bool allowStaticDamage, int &damageTypeOut, bool bDamageFromHeldObjects = false ); - -struct vphysics_objectstress_t -{ - float exertedStress; - float receivedStress; - bool hasNonStaticStress; - bool hasLargeObjectContact; -}; - -float CalculateObjectStress( IPhysicsObject *pObject, CBaseEntity *pOwnerEntity, vphysics_objectstress_t *pOutput ); - -#endif // PHYSICS_IMPACT_DAMAGE_H diff --git a/game/server/physics_main.cpp b/game/server/physics_main.cpp deleted file mode 100644 index 16712e91e..000000000 --- a/game/server/physics_main.cpp +++ /dev/null @@ -1,2069 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Physics simulation for non-havok/ipion objects -// -// $NoKeywords: $ -//=============================================================================// - - -#include "cbase.h" -#ifdef _WIN32 -#include "typeinfo.h" -// BUGBUG: typeinfo stomps some of the warning settings (in yvals.h) -#pragma warning(disable:4244) -#elif _LINUX -#include -#else -#error "need typeinfo defined" -#endif - -#include "player.h" -#include "ai_basenpc.h" -#include "gamerules.h" -#include "vphysics_interface.h" -#include "mempool.h" -#include "entitylist.h" -#include "engine/IEngineSound.h" -#include "datacache/imdlcache.h" -#include "ispatialpartition.h" -#include "tier0/vprof.h" -#include "movevars_shared.h" -#include "hierarchy.h" -#include "trains.h" -#include "vphysicsupdateai.h" -#include "tier0/vcrmode.h" -#include "pushentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern ConVar think_limit; -#ifdef _XBOX -ConVar vprof_think_limit( "vprof_think_limit", "0" ); -#endif - -ConVar vprof_scope_entity_thinks( "vprof_scope_entity_thinks", "0" ); -ConVar vprof_scope_entity_gamephys( "vprof_scope_entity_gamephys", "0" ); - -ConVar npc_vphysics ( "npc_vphysics","0"); -//----------------------------------------------------------------------------- -// helper method for trace hull as used by physics... -//----------------------------------------------------------------------------- -static void Physics_TraceEntity( CBaseEntity* pBaseEntity, const Vector &vecAbsStart, - const Vector &vecAbsEnd, unsigned int mask, trace_t *ptr ) -{ - // FIXME: I really am not sure the best way of doing this - // The TraceHull code below for shots will make sure the object passes - // through shields which do not block that damage type. It will also - // send messages to the shields that they've been hit. - if (pBaseEntity->GetDamageType() != DMG_GENERIC) - { - GameRules()->WeaponTraceEntity( pBaseEntity, vecAbsStart, vecAbsEnd, mask, ptr ); - } - else - { - UTIL_TraceEntity( pBaseEntity, vecAbsStart, vecAbsEnd, mask, ptr ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Does not change the entities velocity at all -// Input : push - -// Output : trace_t -//----------------------------------------------------------------------------- -static void PhysicsCheckSweep( CBaseEntity *pEntity, const Vector& vecAbsStart, const Vector &vecAbsDelta, trace_t *pTrace ) -{ - unsigned int mask = pEntity->PhysicsSolidMaskForEntity(); - - Vector vecAbsEnd; - VectorAdd( vecAbsStart, vecAbsDelta, vecAbsEnd ); - - // Set collision type - if ( !pEntity->IsSolid() || pEntity->IsSolidFlagSet( FSOLID_VOLUME_CONTENTS) ) - { - if ( pEntity->GetMoveParent() ) - { - UTIL_ClearTrace( *pTrace ); - return; - } - - // don't collide with monsters - mask &= ~CONTENTS_MONSTER; - } - - Physics_TraceEntity( pEntity, vecAbsStart, vecAbsEnd, mask, pTrace ); -} - -CPhysicsPushedEntities s_PushedEntities; -#ifndef TF_DLL -CPhysicsPushedEntities *g_pPushedEntities = &s_PushedEntities; -#endif - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CPhysicsPushedEntities::CPhysicsPushedEntities( void ) : m_rgPusher(8, 8), m_rgMoved(32, 32) -{ - m_flMoveTime = -1.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: Store off entity and copy original origin to temporary array -//----------------------------------------------------------------------------- -void CPhysicsPushedEntities::AddEntity( CBaseEntity *ent ) -{ - int i = m_rgMoved.AddToTail(); - m_rgMoved[i].m_pEntity = ent; - m_rgMoved[i].m_vecStartAbsOrigin = ent->GetAbsOrigin(); -} - - -//----------------------------------------------------------------------------- -// Unlink + relink the pusher list so we can actually do the push -//----------------------------------------------------------------------------- -void CPhysicsPushedEntities::UnlinkPusherList( int *pPusherHandles ) -{ - for ( int i = m_rgPusher.Count(); --i >= 0; ) - { - pPusherHandles[i] = partition->HideElement( m_rgPusher[i].m_pEntity->CollisionProp()->GetPartitionHandle() ); - } -} - -void CPhysicsPushedEntities::RelinkPusherList( int *pPusherHandles ) -{ - for ( int i = m_rgPusher.Count(); --i >= 0; ) - { - partition->UnhideElement( m_rgPusher[i].m_pEntity->CollisionProp()->GetPartitionHandle(), pPusherHandles[i] ); - } -} - - -//----------------------------------------------------------------------------- -// Compute the direction to move the rotation blocker -//----------------------------------------------------------------------------- -void CPhysicsPushedEntities::ComputeRotationalPushDirection( CBaseEntity *pBlocker, const RotatingPushMove_t &rotPushMove, Vector *pMove, CBaseEntity *pRoot ) -{ - // calculate destination position - // "start" is relative to the *root* pusher, world orientation - Vector start = pBlocker->CollisionProp()->GetCollisionOrigin(); - if ( pRoot->GetSolid() == SOLID_VPHYSICS ) - { - // HACKHACK: Use move dir to guess which corner of the box determines contact and rotate the box so - // that corner remains in the same local position. - // BUGBUG: This will break, but not as badly as the previous solution!!! - Vector vecAbsMins, vecAbsMaxs; - pBlocker->CollisionProp()->WorldSpaceAABB( &vecAbsMins, &vecAbsMaxs ); - start.x = (pMove->x < 0) ? vecAbsMaxs.x : vecAbsMins.x; - start.y = (pMove->y < 0) ? vecAbsMaxs.y : vecAbsMins.y; - start.z = (pMove->z < 0) ? vecAbsMaxs.z : vecAbsMins.z; - - CBasePlayer *pPlayer = ToBasePlayer(pBlocker); - if ( pPlayer ) - { - // notify the player physics code so it can use vphysics to keep players from getting stuck - pPlayer->SetPhysicsFlag( PFLAG_GAMEPHYSICS_ROTPUSH, true ); - } - } - - // org is pusher local coordinate of start - Vector local; - // transform starting point into local space - VectorITransform( start, rotPushMove.startLocalToWorld, local ); - // rotate local org into world space at end of rotation - Vector end; - VectorTransform( local, rotPushMove.endLocalToWorld, end ); - - // move is the difference (in world space) that the move will push this object - VectorSubtract( end, start, *pMove ); -} - -class CTraceFilterPushFinal : public CTraceFilterSimple -{ - DECLARE_CLASS( CTraceFilterPushFinal, CTraceFilterSimple ); - -public: - CTraceFilterPushFinal( CBaseEntity *pEntity, int nCollisionGroup ) - : CTraceFilterSimple( pEntity, nCollisionGroup ) - { - - } - - bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) - { - Assert( dynamic_cast(pHandleEntity) ); - CBaseEntity *pTestEntity = static_cast(pHandleEntity); - - // UNDONE: This should really filter to just the pushing entities - if ( pTestEntity->GetMoveType() == MOVETYPE_VPHYSICS && - pTestEntity->VPhysicsGetObject() && pTestEntity->VPhysicsGetObject()->IsMoveable() ) - return false; - - return BaseClass::ShouldHitEntity( pHandleEntity, contentsMask ); - } - -}; - -bool CPhysicsPushedEntities::IsPushedPositionValid( CBaseEntity *pBlocker ) -{ - CTraceFilterPushFinal pushFilter(pBlocker, pBlocker->GetCollisionGroup() ); - - trace_t trace; - UTIL_TraceEntity( pBlocker, pBlocker->GetAbsOrigin(), pBlocker->GetAbsOrigin(), pBlocker->PhysicsSolidMaskForEntity(), &pushFilter, &trace ); - - return !trace.startsolid; -} - -//----------------------------------------------------------------------------- -// Speculatively checks to see if all entities in this list can be pushed -//----------------------------------------------------------------------------- -bool CPhysicsPushedEntities::SpeculativelyCheckPush( PhysicsPushedInfo_t &info, const Vector &vecAbsPush, bool bRotationalPush ) -{ - CBaseEntity *pBlocker = info.m_pEntity; - - // See if it's possible to move the entity, but disable all pushers in the hierarchy first - int *pPusherHandles = (int*)stackalloc( m_rgPusher.Count() * sizeof(int) ); - UnlinkPusherList( pPusherHandles ); - CTraceFilterPushMove pushFilter(pBlocker, pBlocker->GetCollisionGroup() ); - - Vector pushDestPosition = pBlocker->GetAbsOrigin() + vecAbsPush; - UTIL_TraceEntity( pBlocker, pBlocker->GetAbsOrigin(), pushDestPosition, - pBlocker->PhysicsSolidMaskForEntity(), &pushFilter, &info.m_Trace ); - - RelinkPusherList(pPusherHandles); - info.m_bPusherIsGround = false; - if ( pBlocker->GetGroundEntity() && pBlocker->GetGroundEntity()->GetRootMoveParent() == m_rgPusher[0].m_pEntity ) - { - info.m_bPusherIsGround = true; - } - - bool bIsUnblockable = (m_bIsUnblockableByPlayer && (pBlocker->IsPlayer() || pBlocker->MyNPCPointer())) ? true : false; - if ( bIsUnblockable ) - { - pBlocker->SetAbsOrigin( pushDestPosition ); - } - else - { - // Move the blocker into its new position - if ( info.m_Trace.fraction ) - { - pBlocker->SetAbsOrigin( info.m_Trace.endpos ); - } - - // We're not blocked if the blocker is point-sized or non-solid - if ( pBlocker->IsPointSized() || !pBlocker->IsSolid() || - pBlocker->IsSolidFlagSet( FSOLID_VOLUME_CONTENTS ) ) - { - return true; - } - - if ( (!bRotationalPush) && (info.m_Trace.fraction == 1.0) ) - { - //Assert( pBlocker->PhysicsTestEntityPosition() == false ); - if ( !IsPushedPositionValid(pBlocker) ) - { - Warning("Interpenetrating entities! (%s and %s)\n", - pBlocker->GetClassname(), m_rgPusher[0].m_pEntity->GetClassname() ); - } - - return true; - } - } - - // Check to see if we're still blocked by the pushers - // FIXME: If the trace fraction == 0 can we early out also? - info.m_bBlocked = !IsPushedPositionValid(pBlocker); - - if ( !info.m_bBlocked ) - return true; - - // if the player is blocking the train try nudging him around to fix accumulated error - if ( bIsUnblockable ) - { - Vector org = pBlocker->GetAbsOrigin(); - for ( int checkCount = 0; checkCount < 4; checkCount++ ) - { - Vector move; - MatrixGetColumn( m_rgPusher[0].m_pEntity->EntityToWorldTransform(), checkCount>>1, move ); - - // alternate movements 1/2" in each direction - float factor = ( checkCount & 1 ) ? -0.5f : 0.5f; - pBlocker->SetAbsOrigin( org + move * factor ); - info.m_bBlocked = !IsPushedPositionValid(pBlocker); - if ( !info.m_bBlocked ) - return true; - } - pBlocker->SetAbsOrigin( pushDestPosition ); - DevMsg(1, "Ignoring player blocking train!\n"); - return true; - } - return false; -} - - -//----------------------------------------------------------------------------- -// Speculatively checks to see if all entities in this list can be pushed -//----------------------------------------------------------------------------- -bool CPhysicsPushedEntities::SpeculativelyCheckRotPush( const RotatingPushMove_t &rotPushMove, CBaseEntity *pRoot ) -{ - Vector vecAbsPush; - m_nBlocker = -1; - for (int i = m_rgMoved.Count(); --i >= 0; ) - { - ComputeRotationalPushDirection( m_rgMoved[i].m_pEntity, rotPushMove, &vecAbsPush, pRoot ); - if (!SpeculativelyCheckPush( m_rgMoved[i], vecAbsPush, true )) - { - m_nBlocker = i; - return false; - } - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Speculatively checks to see if all entities in this list can be pushed -//----------------------------------------------------------------------------- -bool CPhysicsPushedEntities::SpeculativelyCheckLinearPush( const Vector &vecAbsPush ) -{ - m_nBlocker = -1; - for (int i = m_rgMoved.Count(); --i >= 0; ) - { - if (!SpeculativelyCheckPush( m_rgMoved[i], vecAbsPush, false )) - { - m_nBlocker = i; - return false; - } - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Causes all entities in the list to touch triggers from their prev position -//----------------------------------------------------------------------------- -void CPhysicsPushedEntities::FinishPushers() -{ - // We succeeded! Now that we know the final location of all entities, - // touch triggers + update physics objects + do other fixup - for ( int i = m_rgPusher.Count(); --i >= 0; ) - { - PhysicsPusherInfo_t &info = m_rgPusher[i]; - - // Cause touch functions to be called - // FIXME: Need to make moved entities not touch triggers until we know we're ok - // FIXME: it'd be better for the engine to just have a touch method - info.m_pEntity->PhysicsTouchTriggers( &info.m_vecStartAbsOrigin ); - - info.m_pEntity->UpdatePhysicsShadowToCurrentPosition( gpGlobals->frametime ); - } -} - - -//----------------------------------------------------------------------------- -// Causes all entities in the list to touch triggers from their prev position -//----------------------------------------------------------------------------- -void CPhysicsPushedEntities::FinishRotPushedEntity( CBaseEntity *pPushedEntity, const RotatingPushMove_t &rotPushMove ) -{ - // Impart angular velocity of push onto pushed objects - if ( pPushedEntity->IsPlayer() ) - { - QAngle angVel = pPushedEntity->GetLocalAngularVelocity(); - angVel[1] = rotPushMove.amove[1]; - pPushedEntity->SetLocalAngularVelocity(angVel); - - // Look up associated client - CBasePlayer *player = ( CBasePlayer * )pPushedEntity; - player->pl.fixangle = FIXANGLE_RELATIVE; - // Because we can run multiple ticks per server frame, accumulate a total offset here instead of straight - // setting it. The engine will reset anglechange to 0 when the message is actually sent to the client - player->pl.anglechange += rotPushMove.amove; - } - else - { - QAngle angles = pPushedEntity->GetAbsAngles(); - - // only rotate YAW with pushing. Freely rotateable entities should either use VPHYSICS - // or be set up as children - angles.y += rotPushMove.amove.y; - pPushedEntity->SetAbsAngles( angles ); - } -} - - -//----------------------------------------------------------------------------- -// Causes all entities in the list to touch triggers from their prev position -//----------------------------------------------------------------------------- -void CPhysicsPushedEntities::FinishPush( bool bIsRotPush, const RotatingPushMove_t *pRotPushMove ) -{ - FinishPushers(); - - for ( int i = m_rgMoved.Count(); --i >= 0; ) - { - PhysicsPushedInfo_t &info = m_rgMoved[i]; - CBaseEntity *pPushedEntity = info.m_pEntity; - - // Cause touch functions to be called - // FIXME: it'd be better for the engine to just have a touch method - info.m_pEntity->PhysicsTouchTriggers( &info.m_vecStartAbsOrigin ); - info.m_pEntity->UpdatePhysicsShadowToCurrentPosition( gpGlobals->frametime ); - CAI_BaseNPC *pNPC = info.m_pEntity->MyNPCPointer(); - if ( info.m_bPusherIsGround && pNPC ) - { - pNPC->NotifyPushMove(); - } - - - // Register physics impacts... - if (info.m_Trace.m_pEnt) - { - pPushedEntity->PhysicsImpact( info.m_Trace.m_pEnt, info.m_Trace ); - } - - if (bIsRotPush) - { - FinishRotPushedEntity( pPushedEntity, *pRotPushMove ); - } - } -} - -// save initial state when beginning a push sequence -void CPhysicsPushedEntities::BeginPush( CBaseEntity *pRoot ) -{ - m_rgMoved.RemoveAll(); - m_rgPusher.RemoveAll(); - - m_rootPusherStartLocalOrigin = pRoot->GetLocalOrigin(); - m_rootPusherStartLocalAngles = pRoot->GetLocalAngles(); - m_rootPusherStartLocaltime = pRoot->GetLocalTime(); -} - -// store off a list of what has changed - so vphysicsUpdate can undo this if the object gets blocked -void CPhysicsPushedEntities::StoreMovedEntities( physicspushlist_t &list ) -{ - list.localMoveTime = m_rootPusherStartLocaltime; - list.localOrigin = m_rootPusherStartLocalOrigin; - list.localAngles = m_rootPusherStartLocalAngles; - list.pushedCount = CountMovedEntities(); - Assert(list.pushedCount < (int)ARRAYSIZE(list.pushedEnts)); - if ( list.pushedCount > (int)ARRAYSIZE(list.pushedEnts) ) - { - list.pushedCount = ARRAYSIZE(list.pushedEnts); - } - for ( int i = 0; i < list.pushedCount; i++ ) - { - list.pushedEnts[i] = m_rgMoved[i].m_pEntity; - list.pushVec[i] = m_rgMoved[i].m_pEntity->GetAbsOrigin() - m_rgMoved[i].m_vecStartAbsOrigin; - } -} - -//----------------------------------------------------------------------------- -// Registers a blockage -//----------------------------------------------------------------------------- -CBaseEntity *CPhysicsPushedEntities::RegisterBlockage() -{ - Assert( m_nBlocker >= 0 ); - - // Generate a PhysicsImpact against the blocker... - PhysicsPushedInfo_t &info = m_rgMoved[m_nBlocker]; - if ( info.m_Trace.m_pEnt ) - { - info.m_pEntity->PhysicsImpact( info.m_Trace.m_pEnt, info.m_Trace ); - } - - // This is the dude - return info.m_pEntity; -} - - -//----------------------------------------------------------------------------- -// Purpose: Restore entities that might have been moved -// Input : fromrotation - if the move is from a rotation, then angular move must also be reverted -// *amove - -//----------------------------------------------------------------------------- -void CPhysicsPushedEntities::RestoreEntities( ) -{ - // Reset all of the pushed entities to get them back into place also - for ( int i = m_rgMoved.Count(); --i >= 0; ) - { - m_rgMoved[ i ].m_pEntity->SetAbsOrigin( m_rgMoved[ i ].m_vecStartAbsOrigin ); - } -} - - - - -//----------------------------------------------------------------------------- -// Purpose: This is a trace filter that only hits an exclusive list of entities -//----------------------------------------------------------------------------- -class CTraceFilterAgainstEntityList : public ITraceFilter -{ -public: - virtual bool ShouldHitEntity( IHandleEntity *pEntity, int contentsMask ) - { - for ( int i = m_entityList.Count()-1; i >= 0; --i ) - { - if ( m_entityList[i] == pEntity ) - return true; - } - - return false; - } - - virtual TraceType_t GetTraceType() const - { - return TRACE_ENTITIES_ONLY; - } - - void AddEntityToHit( IHandleEntity *pEntity ) - { - m_entityList.AddToTail(pEntity); - } - - CUtlVector m_entityList; -}; - -//----------------------------------------------------------------------------- -// Generates a list of potential blocking entities -//----------------------------------------------------------------------------- -class CPushBlockerEnum : public IPartitionEnumerator -{ -public: - CPushBlockerEnum( CPhysicsPushedEntities *pPushedEntities ) : m_pPushedEntities(pPushedEntities) - { - // All elements are part of the same hierarchy, so they all have - // the same root, so it doesn't matter which one we grab - m_pRootHighestParent = m_pPushedEntities->m_rgPusher[0].m_pEntity->GetRootMoveParent(); - ++s_nEnumCount; - - m_collisionGroupCount = 0; - for ( int i = m_pPushedEntities->m_rgPusher.Count(); --i >= 0; ) - { - if ( !m_pPushedEntities->m_rgPusher[i].m_pEntity->IsSolid() ) - continue; - - m_pushersOnly.AddEntityToHit( m_pPushedEntities->m_rgPusher[i].m_pEntity ); - int collisionGroup = m_pPushedEntities->m_rgPusher[i].m_pEntity->GetCollisionGroup(); - AddCollisionGroup(collisionGroup); - } - - } - - virtual IterationRetval_t EnumElement( IHandleEntity *pHandleEntity ) - { - CBaseEntity *pCheck = GetPushableEntity( pHandleEntity ); - if ( !pCheck ) - return ITERATION_CONTINUE; - - // Mark it as seen - pCheck->m_nPushEnumCount = s_nEnumCount; - m_pPushedEntities->AddEntity( pCheck ); - - return ITERATION_CONTINUE; - } - -private: - - inline void AddCollisionGroup(int collisionGroup) - { - for ( int i = 0; i < m_collisionGroupCount; i++ ) - { - if ( m_collisionGroups[i] == collisionGroup ) - return; - } - if ( m_collisionGroupCount < (int)ARRAYSIZE(m_collisionGroups) ) - { - m_collisionGroups[m_collisionGroupCount] = collisionGroup; - m_collisionGroupCount++; - } - } - - bool IsStandingOnPusher( CBaseEntity *pCheck ) - { - CBaseEntity *pGroundEnt = pCheck->GetGroundEntity(); - if ( pCheck->GetFlags() & FL_ONGROUND || pGroundEnt ) - { - for ( int i = m_pPushedEntities->m_rgPusher.Count(); --i >= 0; ) - { - if (m_pPushedEntities->m_rgPusher[i].m_pEntity == pGroundEnt) - { - return true; - } - } - } - return false; - } - - bool IntersectsPushers( CBaseEntity *pTest ) - { - trace_t tr; - - ICollideable *pCollision = pTest->GetCollideable(); - enginetrace->SweepCollideable( pCollision, pTest->GetAbsOrigin(), pTest->GetAbsOrigin(), pCollision->GetCollisionAngles(), - pTest->PhysicsSolidMaskForEntity(), &m_pushersOnly, &tr ); - - return tr.startsolid; - } - - CBaseEntity *GetPushableEntity( IHandleEntity *pHandleEntity ) - { - CBaseEntity *pCheck = gEntList.GetBaseEntity( pHandleEntity->GetRefEHandle() ); - if ( !pCheck ) - return NULL; - - // Don't bother if we've already seen this one... - if (pCheck->m_nPushEnumCount == s_nEnumCount) - return NULL; - - if ( !pCheck->IsSolid() ) - return NULL; - - if ( pCheck->GetMoveType() == MOVETYPE_PUSH || - pCheck->GetMoveType() == MOVETYPE_NONE || - pCheck->GetMoveType() == MOVETYPE_VPHYSICS || - pCheck->GetMoveType() == MOVETYPE_NOCLIP ) - { - return NULL; - } - - bool bCollide = false; - for ( int i = 0; i < m_collisionGroupCount; i++ ) - { - if ( g_pGameRules->ShouldCollide( pCheck->GetCollisionGroup(), m_collisionGroups[i] ) ) - { - bCollide = true; - break; - } - } - if ( !bCollide ) - return NULL; - // We're not pushing stuff we're hierarchically attached to - CBaseEntity *pCheckHighestParent = pCheck->GetRootMoveParent(); - if (pCheckHighestParent == m_pRootHighestParent) - return NULL; - - // If we're standing on the pusher or any rigidly attached child - // of the pusher, we don't need to bother checking for interpenetration - if ( !IsStandingOnPusher(pCheck) ) - { - // Our surrounding boxes are touching. But we may well not be colliding.... - // see if the ent's bbox is inside the pusher's final position - if ( !IntersectsPushers( pCheck ) ) - return NULL; - } - - // NOTE: This is pretty tricky here. If a rigidly attached child comes into - // contact with a pusher, we *cannot* push the child. Instead, we must push - // the highest parent of that child. - return pCheckHighestParent; - } - -private: - static int s_nEnumCount; - CPhysicsPushedEntities *m_pPushedEntities; - CBaseEntity *m_pRootHighestParent; - CTraceFilterAgainstEntityList m_pushersOnly; - int m_collisionGroups[8]; - int m_collisionGroupCount; -}; - -int CPushBlockerEnum::s_nEnumCount = 0; - -//----------------------------------------------------------------------------- -// Generates a list of potential blocking entities -//----------------------------------------------------------------------------- -void CPhysicsPushedEntities::GenerateBlockingEntityList() -{ - VPROF("CPhysicsPushedEntities::GenerateBlockingEntityList"); - - m_rgMoved.RemoveAll(); - CPushBlockerEnum blockerEnum( this ); - - for ( int i = m_rgPusher.Count(); --i >= 0; ) - { - CBaseEntity *pPusher = m_rgPusher[i].m_pEntity; - - // Don't bother if the pusher isn't solid - if ( !pPusher->IsSolid() || pPusher->IsSolidFlagSet( FSOLID_VOLUME_CONTENTS ) ) - { - continue; - } - - Vector vecAbsMins, vecAbsMaxs; - pPusher->CollisionProp()->WorldSpaceAABB( &vecAbsMins, &vecAbsMaxs ); - partition->EnumerateElementsInBox( PARTITION_ENGINE_NON_STATIC_EDICTS, vecAbsMins, vecAbsMaxs, false, &blockerEnum ); - - //Go back throught the generated list. - } -} - -//----------------------------------------------------------------------------- -// Generates a list of potential blocking entities -//----------------------------------------------------------------------------- -void CPhysicsPushedEntities::GenerateBlockingEntityListAddBox( const Vector &vecMoved ) -{ - VPROF("CPhysicsPushedEntities::GenerateBlockingEntityListAddBox"); - - m_rgMoved.RemoveAll(); - CPushBlockerEnum blockerEnum( this ); - - for ( int i = m_rgPusher.Count(); --i >= 0; ) - { - CBaseEntity *pPusher = m_rgPusher[i].m_pEntity; - - // Don't bother if the pusher isn't solid - if ( !pPusher->IsSolid() || pPusher->IsSolidFlagSet( FSOLID_VOLUME_CONTENTS ) ) - { - continue; - } - - Vector vecAbsMins, vecAbsMaxs; - pPusher->CollisionProp()->WorldSpaceAABB( &vecAbsMins, &vecAbsMaxs ); - for ( int iAxis = 0; iAxis < 3; ++iAxis ) - { - if ( vecMoved[iAxis] >= 0.0f ) - { - vecAbsMins[iAxis] -= vecMoved[iAxis]; - } - else - { - vecAbsMaxs[iAxis] -= vecMoved[iAxis]; - } - } - - partition->EnumerateElementsInBox( PARTITION_ENGINE_NON_STATIC_EDICTS, vecAbsMins, vecAbsMaxs, false, &blockerEnum ); - - //Go back throught the generated list. - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Gets a list of all entities hierarchically attached to the root -//----------------------------------------------------------------------------- -void CPhysicsPushedEntities::SetupAllInHierarchy( CBaseEntity *pParent ) -{ - if (!pParent) - return; - - VPROF("CPhysicsPushedEntities::SetupAllInHierarchy"); - - // Make sure to snack the position +before+ relink because applying the - // rotation (which occurs in relink) will put it at the final location - // NOTE: The root object at this point is actually at its final position. - // We'll fix that up later - int i = m_rgPusher.AddToTail(); - m_rgPusher[i].m_pEntity = pParent; - m_rgPusher[i].m_vecStartAbsOrigin = pParent->GetAbsOrigin(); - - CBaseEntity *pChild; - for ( pChild = pParent->FirstMoveChild(); pChild != NULL; pChild = pChild->NextMovePeer() ) - { - SetupAllInHierarchy( pChild ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Rotates the root entity, fills in the pushmove structure -//----------------------------------------------------------------------------- -void CPhysicsPushedEntities::RotateRootEntity( CBaseEntity *pRoot, float movetime, RotatingPushMove_t &rotation ) -{ - VPROF("CPhysicsPushedEntities::RotateRootEntity"); - - rotation.amove = pRoot->GetLocalAngularVelocity() * movetime; - rotation.origin = pRoot->GetAbsOrigin(); - - // Knowing the initial + ending basis is needed for determining - // which corner we're pushing - MatrixCopy( pRoot->EntityToWorldTransform(), rotation.startLocalToWorld ); - - // rotate the pusher to it's final position - QAngle angles = pRoot->GetLocalAngles(); - angles += pRoot->GetLocalAngularVelocity() * movetime; - pRoot->SetLocalAngles( angles ); - - // Compute the change in absangles - MatrixCopy( pRoot->EntityToWorldTransform(), rotation.endLocalToWorld ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Tries to rotate an entity hierarchy, returns the blocker if any -//----------------------------------------------------------------------------- -CBaseEntity *CPhysicsPushedEntities::PerformRotatePush( CBaseEntity *pRoot, float movetime ) -{ - VPROF("CPhysicsPushedEntities::PerformRotatePush"); - - m_bIsUnblockableByPlayer = (pRoot->GetFlags() & FL_UNBLOCKABLE_BY_PLAYER) ? true : false; - // Build a list of this entity + all its children because we're going to try to move them all - // This will also make sure each entity is linked in the appropriate place - // with correct absboxes - m_rgPusher.RemoveAll(); - SetupAllInHierarchy( pRoot ); - - // save where we rotated from, in case we're blocked - QAngle angPrevAngles = pRoot->GetLocalAngles(); - - // Apply the rotation - RotatingPushMove_t rotPushMove; - RotateRootEntity( pRoot, movetime, rotPushMove ); - - // Next generate a list of all entities that could potentially be intersecting with - // any of the children in their new locations... - GenerateBlockingEntityList( ); - - // Now we have a unique list of things that could potentially block our push - // and need to be pushed out of the way. Lets try to push them all out of the way. - // If we fail, undo it all - if (!SpeculativelyCheckRotPush( rotPushMove, pRoot )) - { - CBaseEntity *pBlocker = RegisterBlockage(); - pRoot->SetLocalAngles( angPrevAngles ); - RestoreEntities( ); - return pBlocker; - } - - FinishPush( true, &rotPushMove ); - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Linearly moves the root entity -//----------------------------------------------------------------------------- -void CPhysicsPushedEntities::LinearlyMoveRootEntity( CBaseEntity *pRoot, float movetime, Vector *pAbsPushVector ) -{ - VPROF("CPhysicsPushedEntities::LinearlyMoveRootEntity"); - - // move the pusher to it's final position - Vector move = pRoot->GetLocalVelocity() * movetime; - Vector origin = pRoot->GetLocalOrigin(); - origin += move; - pRoot->SetLocalOrigin( origin ); - - // Store off the abs push vector - *pAbsPushVector = pRoot->GetAbsVelocity() * movetime; -} - - -//----------------------------------------------------------------------------- -// Purpose: Tries to linearly push an entity hierarchy, returns the blocker if any -//----------------------------------------------------------------------------- -CBaseEntity *CPhysicsPushedEntities::PerformLinearPush( CBaseEntity *pRoot, float movetime ) -{ - VPROF("CPhysicsPushedEntities::PerformLinearPush"); - - m_flMoveTime = movetime; - - m_bIsUnblockableByPlayer = (pRoot->GetFlags() & FL_UNBLOCKABLE_BY_PLAYER) ? true : false; - // Build a list of this entity + all its children because we're going to try to move them all - // This will also make sure each entity is linked in the appropriate place - // with correct absboxes - m_rgPusher.RemoveAll(); - SetupAllInHierarchy( pRoot ); - - // save where we started from, in case we're blocked - Vector vecPrevOrigin = pRoot->GetLocalOrigin(); - - // Move the root (and all children) into its new position - Vector vecAbsPush; - LinearlyMoveRootEntity( pRoot, movetime, &vecAbsPush ); - - // Next generate a list of all entities that could potentially be intersecting with - // any of the children in their new locations... - GenerateBlockingEntityListAddBox( vecAbsPush ); - - // Now we have a unique list of things that could potentially block our push - // and need to be pushed out of the way. Lets try to push them all out of the way. - // If we fail, undo it all - if (!SpeculativelyCheckLinearPush( vecAbsPush )) - { - CBaseEntity *pBlocker = RegisterBlockage(); - pRoot->SetLocalOrigin( vecPrevOrigin ); - RestoreEntities(); - return pBlocker; - } - - FinishPush( ); - return NULL; -} - - - -//----------------------------------------------------------------------------- -// -// CBaseEntity methods -// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// Purpose: Called when it's time for a physically moved objects (plats, doors, etc) -// to run it's game code. -// All other entity thinking is done during worldspawn's think -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsDispatchThink( BASEPTR thinkFunc ) -{ - VPROF_ENTER_SCOPE( ( !vprof_scope_entity_thinks.GetBool() ) ? - "CBaseEntity::PhysicsDispatchThink" : - EntityFactoryDictionary()->GetCannonicalName( GetClassname() ) ); - - float thinkLimit = think_limit.GetFloat(); - - // The thinkLimit stuff makes a LOT of calls to Sys_FloatTime, which winds up calling into - // VCR mode so much that the framerate becomes unusable. - if ( VCRGetMode() != VCR_Disabled ) - thinkLimit = 0; - - float startTime = 0.0; - - if ( IsDormant() ) - { - Warning( "Dormant entity %s (%s) is thinking!!\n", GetClassname(), GetDebugName() ); - Assert(0); - } - - if ( thinkLimit ) - { - startTime = engine->Time(); - } - - if ( thinkFunc ) - { - MDLCACHE_CRITICAL_SECTION(); - (this->*thinkFunc)(); - } - - if ( thinkLimit ) - { - // calculate running time of the AI in milliseconds - float time = ( engine->Time() - startTime ) * 1000.0f; - if ( time > thinkLimit ) - { -#if defined( _XBOX ) && !defined( _RETAIL ) - if ( vprof_think_limit.GetBool() ) - { - extern bool g_VProfSignalSpike; - g_VProfSignalSpike = true; - } -#endif - // If its an NPC print out the shedule/task that took so long - CAI_BaseNPC *pNPC = MyNPCPointer(); - if (pNPC && pNPC->GetCurSchedule()) - { - pNPC->ReportOverThinkLimit( time ); - } - else - { -#ifdef _WIN32 - Msg( "%s(%s) thinking for %.02f ms!!!\n", GetClassname(), typeid(this).raw_name(), time ); -#elif _LINUX - Msg( "%s(%s) thinking for %.02f ms!!!\n", GetClassname(), typeid(this).name(), time ); -#else -#error "typeinfo" -#endif - } - } - } - - VPROF_EXIT_SCOPE(); -} - -//----------------------------------------------------------------------------- -// Purpose: Does not change the entities velocity at all -// Input : push - -// Output : trace_t -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsCheckSweep( const Vector& vecAbsStart, const Vector &vecAbsDelta, trace_t *pTrace ) -{ - ::PhysicsCheckSweep( this, vecAbsStart, vecAbsDelta, pTrace ); -} - - - -#define MAX_CLIP_PLANES 5 -//----------------------------------------------------------------------------- -// Purpose: The basic solid body movement attempt/clip that slides along multiple planes -// Input : time - Amount of time to try moving for -// *steptrace - if not NULL, the trace results of any vertical wall hit will be stored -// Output : int - the clipflags if the velocity was modified (hit something solid) -// 1 = floor -// 2 = wall / step -// 4 = dead stop -//----------------------------------------------------------------------------- -int CBaseEntity::PhysicsTryMove( float flTime, trace_t *steptrace ) -{ - VPROF("CBaseEntity::PhysicsTryMove"); - - int bumpcount, numbumps; - Vector dir; - float d; - int numplanes; - Vector planes[MAX_CLIP_PLANES]; - Vector primal_velocity, original_velocity, new_velocity; - int i, j; - trace_t trace; - Vector end; - float time_left; - int blocked; - - unsigned int mask = PhysicsSolidMaskForEntity(); - - new_velocity.Init(); - - numbumps = 4; - - Vector vecAbsVelocity = GetAbsVelocity(); - - blocked = 0; - VectorCopy (vecAbsVelocity, original_velocity); - VectorCopy (vecAbsVelocity, primal_velocity); - numplanes = 0; - - time_left = flTime; - - for (bumpcount=0 ; bumpcount 0) - { // actually covered some distance - SetAbsOrigin( trace.endpos ); - VectorCopy (vecAbsVelocity, original_velocity); - numplanes = 0; - } - - if (trace.fraction == 1) - break; // moved the entire distance - - if (!trace.m_pEnt) - { - SetAbsVelocity( vecAbsVelocity ); - Warning( "PhysicsTryMove: !trace.u.ent" ); - Assert(0); - return 4; - } - - if (trace.plane.normal[2] > 0.7) - { - blocked |= 1; // floor - if (CanStandOn( trace.m_pEnt )) - { - // keep track of time when changing ground entity - if (GetGroundEntity() != trace.m_pEnt) - { - SetGroundChangeTime( gpGlobals->curtime + (flTime - (1 - trace.fraction) * time_left) ); - } - - SetGroundEntity( trace.m_pEnt ); - } - } - if (!trace.plane.normal[2]) - { - blocked |= 2; // step - if (steptrace) - *steptrace = trace; // save for player extrafriction - } - - // run the impact function - PhysicsImpact( trace.m_pEnt, trace ); - // Removed by the impact function - if ( IsMarkedForDeletion() || IsEdictFree() ) - break; - - time_left -= time_left * trace.fraction; - - // clipped to another plane - if (numplanes >= MAX_CLIP_PLANES) - { // this shouldn't really happen - SetAbsVelocity(vec3_origin); - return blocked; - } - - VectorCopy (trace.plane.normal, planes[numplanes]); - numplanes++; - - // modify original_velocity so it parallels all of the clip planes - if ( GetMoveType() == MOVETYPE_WALK && (!(GetFlags() & FL_ONGROUND) || GetFriction()!=1) ) // relfect player velocity - { - for ( i = 0; i < numplanes; i++ ) - { - if ( planes[i][2] > 0.7 ) - {// floor or slope - PhysicsClipVelocity( original_velocity, planes[i], new_velocity, 1 ); - VectorCopy( new_velocity, original_velocity ); - } - else - { - PhysicsClipVelocity( original_velocity, planes[i], new_velocity, 1.0 + sv_bounce.GetFloat() * (1-GetFriction()) ); - } - } - - VectorCopy( new_velocity, vecAbsVelocity ); - VectorCopy( new_velocity, original_velocity ); - } - else - { - for (i=0 ; iframetime; - SetAbsVelocity( vecAbsVelocity ); - - Vector vecNewBaseVelocity = GetBaseVelocity(); - vecNewBaseVelocity[2] = 0; - SetBaseVelocity( vecNewBaseVelocity ); - - // Bound velocity - PhysicsCheckVelocity(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Does not change the entities velocity at all -// Input : push - -// Output : trace_t -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsPushEntity( const Vector& push, trace_t *pTrace ) -{ - VPROF("CBaseEntity::PhysicsPushEntity"); - - if ( GetMoveParent() ) - { - Warning( "pushing entity (%s) that has parent (%s)!\n", GetDebugName(), GetMoveParent()->GetDebugName() ); - Assert(0); - } - - // NOTE: absorigin and origin must be equal because there is no moveparent - Vector prevOrigin; - VectorCopy( GetAbsOrigin(), prevOrigin ); - - ::PhysicsCheckSweep( this, prevOrigin, push, pTrace ); - - if ( pTrace->fraction ) - { - SetAbsOrigin( pTrace->endpos ); - - // FIXME(ywb): Should we try to enable this here - // WakeRestingObjects(); - } - - // Passing in the previous abs origin here will cause the relinker - // to test the swept ray from previous to current location for trigger intersections - PhysicsTouchTriggers( &prevOrigin ); - - if ( pTrace->m_pEnt ) - { - PhysicsImpact( pTrace->m_pEnt, *pTrace ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: See if entity is inside another entity, if so, returns true if so, fills in *ppEntity if ppEntity is not NULL -// Input : **ppEntity - optional return pointer to entity we are inside of -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseEntity::PhysicsTestEntityPosition( CBaseEntity **ppEntity /*=NULL*/ ) -{ - VPROF("CBaseEntity::PhysicsTestEntityPosition"); - - trace_t trace; - - unsigned int mask = PhysicsSolidMaskForEntity(); - - Physics_TraceEntity( this, GetAbsOrigin(), GetAbsOrigin(), mask, &trace ); - - if ( trace.startsolid ) - { - if ( ppEntity ) - { - *ppEntity = trace.m_pEnt; - } - return true; - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseEntity *CBaseEntity::PhysicsPushMove( float movetime ) -{ - VPROF("CBaseEntity::PhysicsPushMove"); - - // If this entity isn't moving, just update the time. - IncrementLocalTime( movetime ); - - if ( GetLocalVelocity() == vec3_origin ) - { - return NULL; - } - - // Now check that the entire hierarchy can rotate into the new location - CBaseEntity *pBlocker = g_pPushedEntities->PerformLinearPush( this, movetime ); - if ( pBlocker ) - { - IncrementLocalTime( -movetime ); - } - return pBlocker; -} - - -//----------------------------------------------------------------------------- -// Purpose: Tries to rotate, returns success or failure -// Input : movetime - -// Output : bool -//----------------------------------------------------------------------------- -CBaseEntity *CBaseEntity::PhysicsPushRotate( float movetime ) -{ - VPROF("CBaseEntity::PhysicsPushRotate"); - - IncrementLocalTime( movetime ); - - // Not rotating - if ( GetLocalAngularVelocity() == vec3_angle ) - { - return NULL; - } - - // Now check that the entire hierarchy can rotate into the new location - CBaseEntity *pBlocker = g_pPushedEntities->PerformRotatePush( this, movetime ); - if ( pBlocker ) - { - IncrementLocalTime( -movetime ); - } - - return pBlocker; -} - - -//----------------------------------------------------------------------------- -// Block of icky shared code from PhysicsParent + PhysicsPusher -//----------------------------------------------------------------------------- -void CBaseEntity::PerformPush( float movetime ) -{ - VPROF("CBaseEntity::PerformPush"); - // NOTE: Use handle index because the previous blocker could have been deleted - int hPrevBlocker = m_pBlocker.ToInt(); - CBaseEntity *pBlocker; - g_pPushedEntities->BeginPush( this ); - if (movetime > 0) - { - if ( GetLocalAngularVelocity() != vec3_angle ) - { - if ( GetLocalVelocity() != vec3_origin ) - { - // NOTE: Both PhysicsPushRotate + PhysicsPushMove - // will attempt to advance local time. Choose the one that's - // the greater of the two from push + move - - // FIXME: Should we really be doing them both simultaneously?? - // FIXME: Choose the *greater* of the two?!? That's strange... - float flInitialLocalTime = m_flLocalTime; - - // moving and rotating, so rotate first, then move - pBlocker = PhysicsPushRotate( movetime ); - if ( !pBlocker ) - { - float flRotateLocalTime = m_flLocalTime; - - // Reset the local time to what it was before we rotated - m_flLocalTime = flInitialLocalTime; - pBlocker = PhysicsPushMove( movetime ); - if ( m_flLocalTime < flRotateLocalTime ) - { - m_flLocalTime = flRotateLocalTime; - } - } - } - else - { - // only rotating - pBlocker = PhysicsPushRotate( movetime ); - } - } - else - { - // only moving - pBlocker = PhysicsPushMove( movetime ); - } - - m_pBlocker = pBlocker; - if (m_pBlocker.ToInt() != hPrevBlocker) - { - if (hPrevBlocker != (int)INVALID_EHANDLE_INDEX) - { - EndBlocked(); - } - if (m_pBlocker) - { - StartBlocked( pBlocker ); - } - } - if (m_pBlocker) - { - Blocked( m_pBlocker ); - } - - // NOTE NOTE: This is here for brutal reasons. - // For MOVETYPE_PUSH objects with VPhysics shadow objects, the move done time - // is handled by CBaseEntity::VPhyicsUpdatePusher, which only gets called if - // the physics system thinks the entity is awake. That will happen if the - // shadow gets updated, but the push code above doesn't update unless the - // move is successful or non-zero. So we must make sure it's awake - if ( VPhysicsGetObject() ) - { - VPhysicsGetObject()->Wake(); - } - } - - // move done is handled by physics if it has any - if ( VPhysicsGetObject() ) - { - // store the list of moved entities for later - // if you actually did an unblocked push that moved entities, and you're using physics (which may block later) - if ( movetime > 0 && !m_pBlocker && GetSolid() == SOLID_VPHYSICS && g_pPushedEntities->CountMovedEntities() > 0 ) - { - // UNDONE: Any reason to want to call this twice before physics runs? - // If so, maybe just append to the list? - Assert( !GetDataObject( PHYSICSPUSHLIST ) ); - physicspushlist_t *pList = (physicspushlist_t *)CreateDataObject( PHYSICSPUSHLIST ); - if ( pList ) - { - g_pPushedEntities->StoreMovedEntities( *pList ); - } - } - } - else - { - if ( m_flMoveDoneTime <= m_flLocalTime && m_flMoveDoneTime > 0 ) - { - SetMoveDoneTime( -1 ); - MoveDone(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: UNDONE: This is only different from PhysicsParent because of the callback to PhysicsVelocity() -// Can we support that callback in push objects as well? -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsPusher( void ) -{ - VPROF("CBaseEntity::PhysicsPusher"); - - // regular thinking - if ( !PhysicsRunThink() ) - return; - - m_flVPhysicsUpdateLocalTime = m_flLocalTime; - - float movetime = GetMoveDoneTime(); - if (movetime > gpGlobals->frametime) - { - movetime = gpGlobals->frametime; - } - - PerformPush( movetime ); -} - - - -//----------------------------------------------------------------------------- -// Purpose: Non moving objects can only think -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsNone( void ) -{ - VPROF("CBaseEntity::PhysicsNone"); - - // regular thinking - PhysicsRunThink(); -} - - -//----------------------------------------------------------------------------- -// Purpose: A moving object that doesn't obey physics -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsNoclip( void ) -{ - VPROF("CBaseEntity::PhysicsNoclip"); - - // regular thinking - if ( !PhysicsRunThink() ) - { - return; - } - - // Apply angular velocity - SimulateAngles( gpGlobals->frametime ); - - Vector origin; - VectorMA( GetLocalOrigin(), gpGlobals->frametime, GetLocalVelocity(), origin ); - SetLocalOrigin( origin ); -} - - -void CBaseEntity::PerformCustomPhysics( Vector *pNewPosition, Vector *pNewVelocity, QAngle *pNewAngles, QAngle *pNewAngVelocity ) -{ - // If you're going to use custom physics, you need to implement this! - Assert(0); -} - - -//----------------------------------------------------------------------------- -// Allows entities to describe their own physics -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsCustom() -{ - VPROF("CBaseEntity::PhysicsCustom"); - PhysicsCheckWater(); - - // regular thinking - if ( !PhysicsRunThink() ) - return; - - // Moving upward, off the ground, or resting on a client/monster, remove FL_ONGROUND - if ( m_vecVelocity[2] > 0 || !GetGroundEntity() || !GetGroundEntity()->IsStandable() ) - { - SetGroundEntity( NULL ); - } - - // NOTE: The entity must set the position, angles, velocity in its custom movement - Vector vecNewPosition = GetAbsOrigin(); - Vector vecNewVelocity = GetAbsVelocity(); - QAngle angNewAngles = GetAbsAngles(); - QAngle angNewAngVelocity = GetLocalAngularVelocity(); - - PerformCustomPhysics( &vecNewPosition, &vecNewVelocity, &angNewAngles, &angNewAngVelocity ); - - // Store off all of the new state information... - SetAbsVelocity( vecNewVelocity ); - SetAbsAngles( angNewAngles ); - SetLocalAngularVelocity( angNewAngVelocity ); - - Vector move; - VectorSubtract( vecNewPosition, GetAbsOrigin(), move ); - - // move origin - trace_t trace; - PhysicsPushEntity( move, &trace ); - - PhysicsCheckVelocity(); - - if (trace.allsolid) - { - // entity is trapped in another solid - // UNDONE: does this entity needs to be removed? - SetAbsVelocity(vec3_origin); - SetLocalAngularVelocity(vec3_angle); - return; - } - - if (IsEdictFree()) - return; - - // check for in water - PhysicsCheckWaterTransition(); -} - -bool g_bTestMoveTypeStepSimulation = true; -ConVar sv_teststepsimulation( "sv_teststepsimulation", "1", 0 ); - -//----------------------------------------------------------------------------- -// Purpose: Until we remove the above cvar, we need to have the entities able -// to dynamically deal with changing their simulation stuff here. -//----------------------------------------------------------------------------- -void CBaseEntity::CheckStepSimulationChanged() -{ - if ( g_bTestMoveTypeStepSimulation != IsSimulatedEveryTick() ) - { - SetSimulatedEveryTick( g_bTestMoveTypeStepSimulation ); - } - - bool hadobject = HasDataObjectType( STEPSIMULATION ); - - if ( g_bTestMoveTypeStepSimulation ) - { - if ( !hadobject ) - { - CreateDataObject( STEPSIMULATION ); - } - } - else - { - if ( hadobject ) - { - DestroyDataObject( STEPSIMULATION ); - } - } -} - - -#define STEP_TELPORTATION_VEL_SQ ( 4096.0f * 4096.0f ) -//----------------------------------------------------------------------------- -// Purpose: Run regular think and latch off angle/origin changes so we can interpolate them on the server to fake simulation -// Input : *step - -//----------------------------------------------------------------------------- -void CBaseEntity::StepSimulationThink( float dt ) -{ - // See if we need to allocate, deallocate step simulation object - CheckStepSimulationChanged(); - - StepSimulationData *step = ( StepSimulationData * )GetDataObject( STEPSIMULATION ); - if ( !step ) - { - PhysicsStepRunTimestep( dt ); - - // Just call the think function directly - PhysicsRunThink( THINK_FIRE_BASE_ONLY ); - } - else - { - // Assume that it's in use - step->m_bOriginActive = true; - step->m_bAnglesActive = true; - - // Reset networked versions of origin and angles - step->m_nLastProcessTickCount = -1; - step->m_vecNetworkOrigin.Init(); - step->m_angNetworkAngles.Init(); - - // Remember old old values - step->m_Previous2 = step->m_Previous; - - // Remember old values - step->m_Previous.nTickCount = gpGlobals->tickcount; - step->m_Previous.vecOrigin = GetStepOrigin(); - QAngle stepAngles = GetStepAngles(); - AngleQuaternion( stepAngles, step->m_Previous.qRotation ); - - // Run simulation - PhysicsStepRunTimestep( dt ); - - // Call the actual think function... - PhysicsRunThink( THINK_FIRE_BASE_ONLY ); - - // do any local processing that's needed - if (GetBaseAnimating() != NULL) - { - GetBaseAnimating()->UpdateStepOrigin(); - } - - // Latch new values to see if external code modifies our position/orientation - step->m_Next.vecOrigin = GetStepOrigin(); - stepAngles = GetStepAngles(); - AngleQuaternion( stepAngles, step->m_Next.qRotation ); - // Also store of non-Quaternion version for simple comparisons - step->m_angNextRotation = GetStepAngles(); - step->m_Next.nTickCount = GetNextThinkTick(); - - // Hack: Add a tick if we are simulating every other tick - if ( CBaseEntity::IsSimulatingOnAlternateTicks() ) - { - ++step->m_Next.nTickCount; - } - - // Check for teleportation/snapping of the origin - if ( dt > 0.0f ) - { - Vector deltaorigin = step->m_Next.vecOrigin - step->m_Previous.vecOrigin; - float velSq = deltaorigin.LengthSqr() / ( dt * dt ); - if ( velSq >= STEP_TELPORTATION_VEL_SQ ) - { - // Deactivate it due to large origin change - step->m_bOriginActive = false; - step->m_bAnglesActive = false; - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Monsters freefall when they don't have a ground entity, otherwise -// all movement is done with discrete steps. -// This is also used for objects that have become still on the ground, but -// will fall if the floor is pulled out from under them. -// JAY: Extended this to synchronize movement and thinking wherever possible. -// This allows the client-side interpolation to interpolate animation and simulation -// data at the same time. -// UNDONE: Remove all other cases from this loop - only use MOVETYPE_STEP to simulate -// entities that are currently animating/thinking. -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsStep() -{ - // EVIL HACK: Force these to appear as if they've changed!!! - // The underlying values don't actually change, but we need the network sendproxy on origin/angles - // to get triggered, and that only happens if NetworkStateChanged() appears to have occured. - // Getting them for modify marks them as changed automagically. - m_vecOrigin.GetForModify(); - m_angRotation.GetForModify(); - - // HACK: Make sure that the client latches the networked origin/orientation changes with the current server tick count - // so that we don't get jittery interpolation. All of this is necessary to mimic actual continuous simulation of the underlying - // variables. - SetSimulationTime( gpGlobals->curtime ); - - // Run all but the base think function - PhysicsRunThink( THINK_FIRE_ALL_BUT_BASE ); - - int thinktick = GetNextThinkTick(); - float thinktime = thinktick * TICK_INTERVAL; - - // Is the next think too far out, or non-existent? - // BUGBUG: Interpolation is going to look bad in here. But it should only - // be for dead things - and those should be ragdolls (client-side sim) anyway. - // UNDONE: Remove this and assert? Force MOVETYPE_STEP objs to become MOVETYPE_TOSS when - // they aren't thinking? - // UNDONE: this happens as the first frame for a bunch of things like dynamically created ents. - // can't remove until initial conditions are resolved - float deltaThink = thinktime - gpGlobals->curtime; - if ( thinktime <= 0 || deltaThink > 0.5 ) - { - PhysicsStepRunTimestep( gpGlobals->frametime ); - PhysicsCheckWaterTransition(); - SetLastThink( -1, gpGlobals->curtime ); - UpdatePhysicsShadowToCurrentPosition(gpGlobals->frametime); - PhysicsRelinkChildren(gpGlobals->frametime); - return; - } - - Vector oldOrigin = GetAbsOrigin(); - - // Feed the position delta back from vphysics if enabled - bool updateFromVPhysics = npc_vphysics.GetBool(); - if ( HasDataObjectType(VPHYSICSUPDATEAI) ) - { - vphysicsupdateai_t *pUpdate = static_cast(GetDataObject( VPHYSICSUPDATEAI )); - if ( pUpdate->stopUpdateTime > gpGlobals->curtime ) - { - updateFromVPhysics = true; - } - else - { - float maxAngular; - VPhysicsGetObject()->GetShadowController()->GetMaxSpeed( NULL, &maxAngular ); - VPhysicsGetObject()->GetShadowController()->MaxSpeed( pUpdate->savedShadowControllerMaxSpeed, maxAngular ); - DestroyDataObject(VPHYSICSUPDATEAI); - } - } - - if ( updateFromVPhysics && VPhysicsGetObject() && !GetParent() ) - { - Vector position; - VPhysicsGetObject()->GetShadowPosition( &position, NULL ); - float delta = (GetAbsOrigin() - position).LengthSqr(); - // for now, use a tolerance of 1 inch for these tests - if ( delta < 1 ) - { - // physics is really close, check to see if my current position is valid. - // If so, ignore the physics result. - trace_t tr; - Physics_TraceEntity( this, GetAbsOrigin(), GetAbsOrigin(), PhysicsSolidMaskForEntity(), &tr ); - updateFromVPhysics = tr.startsolid; - } - if ( updateFromVPhysics ) - { - SetAbsOrigin( position ); - PhysicsTouchTriggers(); - } - //NDebugOverlay::Box( position, WorldAlignMins(), WorldAlignMaxs(), 255, 255, 0, 0, 0.0 ); - } - - // not going to think, don't run game physics either - if ( thinktick > gpGlobals->tickcount ) - return; - - // Don't let things stay in the past. - // it is possible to start that way - // by a trigger with a local time. - if ( thinktime < gpGlobals->curtime ) - { - thinktime = gpGlobals->curtime; - } - - // simulate over the timestep - float dt = thinktime - GetLastThink(); - - // Now run step simulator - StepSimulationThink( dt ); - - PhysicsCheckWaterTransition(); - - if ( VPhysicsGetObject() ) - { - if ( !VectorCompare( oldOrigin, GetAbsOrigin() ) ) - { - VPhysicsGetObject()->UpdateShadow( GetAbsOrigin(), vec3_angle, (GetFlags() & FL_FLY) ? true : false, dt ); - } - } - PhysicsRelinkChildren(dt); -} - - -void UTIL_TraceLineFilterEntity( CBaseEntity *pEntity, const Vector &vecAbsStart, const Vector &vecAbsEnd, - unsigned int mask, const int nCollisionGroup, trace_t *ptr ); - -// Check to see what (if anything) this MOVETYPE_STEP entity is standing on -void CBaseEntity::PhysicsStepRecheckGround() -{ - unsigned int mask = PhysicsSolidMaskForEntity(); - // determine if it's on solid ground at all - Vector mins, maxs, point; - int x, y; - trace_t trace; - - VectorAdd (GetAbsOrigin(), WorldAlignMins(), mins); - VectorAdd (GetAbsOrigin(), WorldAlignMaxs(), maxs); - point[2] = mins[2] - 1; - for (x=0 ; x<=1 ; x++) - { - for (y=0 ; y<=1 ; y++) - { - point[0] = x ? maxs[0] : mins[0]; - point[1] = y ? maxs[1] : mins[1]; - - ICollideable *pCollision = GetCollideable(); - - if ( pCollision && IsNPC() ) - { - UTIL_TraceLineFilterEntity( this, point, point, mask, COLLISION_GROUP_NONE, &trace ); - } - else - { - UTIL_TraceLine( point, point, mask, this, COLLISION_GROUP_NONE, &trace ); - } - - if ( trace.startsolid ) - { - SetGroundEntity( trace.m_pEnt ); - return; - } - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : timestep - -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsStepRunTimestep( float timestep ) -{ - bool wasonground; - bool inwater; - bool hitsound = false; - float speed, newspeed, control; - float friction; - - PhysicsCheckVelocity(); - - wasonground = ( GetFlags() & FL_ONGROUND ) ? true : false; - - // add gravity except: - // flying monsters - // swimming monsters who are in the water - inwater = PhysicsCheckWater(); - - bool isfalling = false; - - if ( !wasonground ) - { - if ( !( GetFlags() & FL_FLY ) ) - { - if ( !( ( GetFlags() & FL_SWIM ) && ( GetWaterLevel() > 0 ) ) ) - { - if ( GetAbsVelocity()[2] < ( sv_gravity.GetFloat() * -0.1 ) ) - { - hitsound = true; - } - - if ( !inwater ) - { - PhysicsAddHalfGravity( timestep ); - isfalling = true; - } - } - } - } - - if ( !(GetFlags() & FL_STEPMOVEMENT) && - (!VectorCompare(GetAbsVelocity(), vec3_origin) || - !VectorCompare(GetBaseVelocity(), vec3_origin))) - { - Vector vecAbsVelocity = GetAbsVelocity(); - - SetGroundEntity( NULL ); - // apply friction - // let dead monsters who aren't completely onground slide - if ( wasonground ) - { - speed = VectorLength( vecAbsVelocity ); - if (speed) - { - friction = sv_friction.GetFloat() * GetFriction(); - - control = speed < sv_stopspeed.GetFloat() ? sv_stopspeed.GetFloat() : speed; - newspeed = speed - timestep*control*friction; - - if (newspeed < 0) - newspeed = 0; - newspeed /= speed; - - vecAbsVelocity[0] *= newspeed; - vecAbsVelocity[1] *= newspeed; - } - } - - vecAbsVelocity += GetBaseVelocity(); - SetAbsVelocity( vecAbsVelocity ); - - // Apply angular velocity - SimulateAngles( timestep ); - - PhysicsCheckVelocity(); - - PhysicsTryMove( timestep, NULL ); - - PhysicsCheckVelocity(); - - vecAbsVelocity = GetAbsVelocity(); - vecAbsVelocity -= GetBaseVelocity(); - SetAbsVelocity( vecAbsVelocity ); - - PhysicsCheckVelocity(); - - if ( !(GetFlags() & FL_ONGROUND) ) - { - PhysicsStepRecheckGround(); - } - - PhysicsTouchTriggers(); - } - - if (!( GetFlags() & FL_ONGROUND ) && isfalling) - { - PhysicsAddHalfGravity( timestep ); - } -} - -// After this long, if a player isn't updating, then return it's projectiles to server control -#define PLAYER_PACKETS_STOPPED_SO_RETURN_TO_PHYSICS_TIME 1.0f - -void Physics_SimulateEntity( CBaseEntity *pEntity ) -{ - VPROF( ( !vprof_scope_entity_gamephys.GetBool() ) ? - "Physics_SimulateEntity" : - EntityFactoryDictionary()->GetCannonicalName( pEntity->GetClassname() ) ); - - if ( pEntity->edict() ) - { -#if !defined( NO_ENTITY_PREDICTION ) - // Player drives simulation of this entity - if ( pEntity->IsPlayerSimulated() ) - { - // If the player is gone, dropped, crashed, then return - // control to the game code. - CBasePlayer *simulatingPlayer = pEntity->GetSimulatingPlayer(); - if ( simulatingPlayer && - ( simulatingPlayer->GetTimeBase() > gpGlobals->curtime - PLAYER_PACKETS_STOPPED_SO_RETURN_TO_PHYSICS_TIME ) ) - { - // Okay, the guy is still around - return; - } - - pEntity->UnsetPlayerSimulated(); - } -#endif - - MDLCACHE_CRITICAL_SECTION(); - -#if !defined( NO_ENTITY_PREDICTION ) - // If an object was at one point player simulated, but had that status revoked (as just - // above when no packets have arrived in a while ), then we still will assume that the - // owner/player will be predicting the entity locally (even if the game is playing like butt) - // and so we won't spam that player with additional network data such as effects/sounds - // that are theoretically being predicted by the player anyway. - if ( pEntity->m_PredictableID->IsActive() ) - { - CBasePlayer *playerowner = ToBasePlayer( pEntity->GetOwnerEntity() ); - if ( playerowner ) - { - CBasePlayer *pl = ToBasePlayer( UTIL_PlayerByIndex( pEntity->m_PredictableID->GetPlayer() + 1 ) ); - // Is the player who created it still the owner? - if ( pl == playerowner ) - { - // Set up to suppress sending events to owner player - if ( pl->IsPredictingWeapons() ) - { - IPredictionSystem::SuppressHostEvents( playerowner ); - } - } - } - { - VPROF( ( !vprof_scope_entity_gamephys.GetBool() ) ? - "pEntity->PhysicsSimulate" : - EntityFactoryDictionary()->GetCannonicalName( pEntity->GetClassname() ) ); - - // Run entity physics - pEntity->PhysicsSimulate(); - } - - // Restore suppression filter - IPredictionSystem::SuppressHostEvents( NULL ); - } - else -#endif - { - // Run entity physics - pEntity->PhysicsSimulate(); - } - } - else - { - pEntity->PhysicsRunThink(); - } -} -//----------------------------------------------------------------------------- -// Purpose: Runs the main physics simulation loop against all entities ( except players ) -//----------------------------------------------------------------------------- -void Physics_RunThinkFunctions( bool simulating ) -{ - VPROF( "Physics_RunThinkFunctions"); - - g_bTestMoveTypeStepSimulation = sv_teststepsimulation.GetBool(); - - float starttime = gpGlobals->curtime; - // clear all entites freed outside of this loop - gEntList.CleanupDeleteList(); - - if ( !simulating ) - { - // only simulate players - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - if ( pPlayer ) - { - // Always reset clock to real sv.time - gpGlobals->curtime = starttime; - // Force usercmd processing even though gpGlobals->tickcount isn't incrementing - pPlayer->ForceSimulation(); - Physics_SimulateEntity( pPlayer ); - } - } - } - else - { - UTIL_DisableRemoveImmediate(); - int listMax = SimThink_ListCount(); - listMax = MAX(listMax,1); - CBaseEntity **list = (CBaseEntity **)stackalloc( sizeof(CBaseEntity *) * listMax ); - // iterate through all entities and have them think or simulate - - // UNDONE: This has problems with UTIL_RemoveImmediate() (now disabled during this loop). - // Do we really need UTIL_RemoveImmediate()? - int count = SimThink_ListCopy( list, listMax ); - - //DevMsg(1, "Count: %d\n", count ); - for ( int i = 0; i < count; i++ ) - { - if ( !list[i] ) - continue; - // Always reset clock to real sv.time - gpGlobals->curtime = starttime; - Physics_SimulateEntity( list[i] ); - } - - stackfree( list ); - UTIL_EnableRemoveImmediate(); - } - - gpGlobals->curtime = starttime; -} - diff --git a/game/server/physics_npc_solver.cpp b/game/server/physics_npc_solver.cpp deleted file mode 100644 index 16e15e919..000000000 --- a/game/server/physics_npc_solver.cpp +++ /dev/null @@ -1,468 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "physics_saverestore.h" -#include "vphysics/friction.h" -#include "ai_basenpc.h" -#include "movevars_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -class CPhysicsNPCSolver : public CLogicalEntity, public IMotionEvent -{ - DECLARE_CLASS( CPhysicsNPCSolver, CLogicalEntity ); -public: - CPhysicsNPCSolver(); - ~CPhysicsNPCSolver(); - DECLARE_DATADESC(); - void Init( CAI_BaseNPC *pNPC, CBaseEntity *pPhysicsObject, bool disableCollisions, float separationTime ); - static CPhysicsNPCSolver *Create( CAI_BaseNPC *pNPC, CBaseEntity *pPhysicsObject, bool disableCollisions, float separationTime ); - - // CBaseEntity - virtual void Spawn(); - virtual void UpdateOnRemove(); - virtual void Think(); - virtual void OnRestore() - { - BaseClass::OnRestore(); - if ( m_allowIntersection ) - { - PhysDisableEntityCollisions( m_hNPC, m_hEntity ); - } - } - - // IMotionEvent - virtual simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ); - -public: - CPhysicsNPCSolver *m_pNext; -private: - // locals - void ResetCancelTime(); - void BecomePenetrationSolver(); - bool IsIntersecting(); - bool IsContactOnNPCHead( IPhysicsFrictionSnapshot *pSnapshot, IPhysicsObject *pPhysics, CAI_BaseNPC *pNPC ); - bool CheckTouching(); - friend bool NPCPhysics_SolverExists( CAI_BaseNPC *pNPC, CBaseEntity *pPhysicsObject ); - - CHandle m_hNPC; - EHANDLE m_hEntity; - IPhysicsMotionController *m_pController; - float m_separationDuration; - float m_cancelTime; - bool m_allowIntersection; -}; - -LINK_ENTITY_TO_CLASS( physics_npc_solver, CPhysicsNPCSolver ); - -BEGIN_DATADESC( CPhysicsNPCSolver ) - - DEFINE_FIELD( m_hNPC, FIELD_EHANDLE ), - DEFINE_FIELD( m_hEntity, FIELD_EHANDLE ), - DEFINE_FIELD( m_separationDuration, FIELD_FLOAT ), - DEFINE_FIELD( m_cancelTime, FIELD_TIME ), - DEFINE_FIELD( m_allowIntersection, FIELD_BOOLEAN ), - DEFINE_PHYSPTR( m_pController ), - //DEFINE_FIELD( m_pNext, FIELD_CLASSPTR ), - -END_DATADESC() - -CEntityClassList g_SolverList; -template <> CPhysicsNPCSolver *CEntityClassList::m_pClassList = NULL; - -bool NPCPhysics_SolverExists( CAI_BaseNPC *pNPC, CBaseEntity *pPhysicsObject ) -{ - CPhysicsNPCSolver *pSolver = g_SolverList.m_pClassList; - while ( pSolver ) - { - if ( pSolver->m_hEntity == pPhysicsObject && pSolver->m_hNPC == pNPC ) - return true; - pSolver = pSolver->m_pNext; - } - - return false; -} - -CPhysicsNPCSolver *CPhysicsNPCSolver::Create( CAI_BaseNPC *pNPC, CBaseEntity *pPhysicsObject, bool disableCollisions, float separationTime ) -{ - CPhysicsNPCSolver *pSolver = (CPhysicsNPCSolver *)CBaseEntity::CreateNoSpawn( "physics_npc_solver", vec3_origin, vec3_angle, NULL ); - pSolver->Init( pNPC, pPhysicsObject, disableCollisions, separationTime ); - pSolver->Spawn(); - //NDebugOverlay::EntityBounds(pNPC, 255, 255, 0, 64, 0.5f ); - return pSolver; -} - -CPhysicsNPCSolver::CPhysicsNPCSolver() -{ - g_SolverList.Insert( this ); -} - -CPhysicsNPCSolver::~CPhysicsNPCSolver() -{ - g_SolverList.Remove( this ); -} - -void CPhysicsNPCSolver::Init( CAI_BaseNPC *pNPC, CBaseEntity *pPhysicsObject, bool disableCollisions, float separationTime ) -{ - m_hNPC = pNPC; - m_hEntity = pPhysicsObject; - m_pController = NULL; - m_separationDuration = separationTime; - m_allowIntersection = disableCollisions; - -} - -void CPhysicsNPCSolver::ResetCancelTime() -{ - m_cancelTime = gpGlobals->curtime + m_separationDuration; - SetNextThink( m_cancelTime ); -} - -void CPhysicsNPCSolver::BecomePenetrationSolver() -{ - CBaseEntity *pEntity = m_hEntity.Get(); - if ( pEntity ) - { - m_allowIntersection = true; - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int listCount = pEntity->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - PhysDisableEntityCollisions( m_hNPC, pEntity ); - m_pController = physenv->CreateMotionController( this ); - for ( int i = 0; i < listCount; i++ ) - { - m_pController->AttachObject( pList[i], false ); - pList[i]->Wake(); - } - m_pController->SetPriority( IPhysicsMotionController::HIGH_PRIORITY ); - } -} - -void CPhysicsNPCSolver::Spawn() -{ - if ( m_allowIntersection ) - { - BecomePenetrationSolver(); - } - else - { - m_hEntity->SetNavIgnore(); - } - ResetCancelTime(); -} - -void CPhysicsNPCSolver::UpdateOnRemove() -{ - if ( m_allowIntersection ) - { - physenv->DestroyMotionController( m_pController ); - m_pController = NULL; - PhysEnableEntityCollisions( m_hNPC, m_hEntity ); - } - else - { - if ( m_hEntity.Get() ) - { - m_hEntity->ClearNavIgnore(); - } - } - //NDebugOverlay::EntityBounds(m_hNPC, 0, 255, 0, 64, 0.5f ); - BaseClass::UpdateOnRemove(); -} - -bool CPhysicsNPCSolver::IsIntersecting() -{ - CAI_BaseNPC *pNPC = m_hNPC.Get(); - CBaseEntity *pPhysics = m_hEntity.Get(); - if ( pNPC && pPhysics ) - { - Ray_t ray; - // bloated bounds to force slight separation - Vector mins = pNPC->WorldAlignMins() - Vector(1,1,1); - Vector maxs = pNPC->WorldAlignMaxs() + Vector(1,1,1); - - ray.Init( pNPC->GetAbsOrigin(), pNPC->GetAbsOrigin(), mins, maxs ); - trace_t tr; - enginetrace->ClipRayToEntity( ray, pNPC->PhysicsSolidMaskForEntity(), pPhysics, &tr ); - if ( tr.startsolid ) - return true; - } - return false; -} - -bool CPhysicsNPCSolver::IsContactOnNPCHead( IPhysicsFrictionSnapshot *pSnapshot, IPhysicsObject *pPhysics, CAI_BaseNPC *pNPC ) -{ - float heightCheck = pNPC->GetAbsOrigin().z + pNPC->GetHullMaxs().z; - Vector vel, point; - pPhysics->GetVelocity( &vel, NULL ); - pSnapshot->GetContactPoint( point ); - // don't care if the object is already moving away - if ( vel.LengthSqr() < 10.0f*10.0f ) - { - float topdist = fabs(point.z-heightCheck); - if ( topdist < 2.0f ) - { - return true; - } - } - return false; -} - -bool CPhysicsNPCSolver::CheckTouching() -{ - CAI_BaseNPC *pNPC = m_hNPC.Get(); - if ( !pNPC ) - return false; - - CBaseEntity *pPhysicsEnt = m_hEntity.Get(); - if ( !pPhysicsEnt ) - return false; - - IPhysicsObject *pPhysics = pPhysicsEnt->VPhysicsGetObject(); - IPhysicsObject *pNPCPhysics = pNPC->VPhysicsGetObject(); - if ( !pNPCPhysics || !pPhysics ) - return false; - - IPhysicsFrictionSnapshot *pSnapshot = pPhysics->CreateFrictionSnapshot(); - bool found = false; - bool penetrate = false; - - while ( pSnapshot->IsValid() ) - { - IPhysicsObject *pOther = pSnapshot->GetObject(1); - if ( pOther == pNPCPhysics ) - { - found = true; - if ( IsContactOnNPCHead(pSnapshot, pPhysics, pNPC ) ) - { - penetrate = true; - pSnapshot->MarkContactForDelete(); - } - break; - } - pSnapshot->NextFrictionData(); - } - pSnapshot->DeleteAllMarkedContacts( true ); - pPhysics->DestroyFrictionSnapshot( pSnapshot ); - - // if the object is penetrating something, check to see if it's intersecting this NPC - // if so, go ahead and switch over to penetration solver mode - if ( !penetrate && (pPhysics->GetGameFlags() & FVPHYSICS_PENETRATING) ) - { - penetrate = IsIntersecting(); - } - - if ( penetrate ) - { - pPhysicsEnt->ClearNavIgnore(); - BecomePenetrationSolver(); - } - - return found; -} - -void CPhysicsNPCSolver::Think() -{ - bool finished = m_allowIntersection ? !IsIntersecting() : !CheckTouching(); - - if ( finished ) - { - UTIL_Remove(this); - return; - } - if ( m_allowIntersection ) - { - IPhysicsObject *pObject = m_hEntity->VPhysicsGetObject(); - if ( !pObject ) - { - UTIL_Remove(this); - return; - } - pObject->Wake(); - } - ResetCancelTime(); -} - -IMotionEvent::simresult_e CPhysicsNPCSolver::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, - float deltaTime, Vector &linear, AngularImpulse &angular ) -{ - if ( IsIntersecting() ) - { - const float PUSH_SPEED = 150.0f; - - if ( pObject->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - { - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - if ( pPlayer ) - { - pPlayer->ForceDropOfCarriedPhysObjects( m_hEntity ); - } - } - - ResetCancelTime(); - angular.Init(); - linear.Init(); - - // Don't push on vehicles because they won't move - if ( pObject->GetGameFlags() & FVPHYSICS_MULTIOBJECT_ENTITY ) - { - if ( m_hEntity->GetServerVehicle() ) - return SIM_NOTHING; - } - - Vector origin, vel; - pObject->GetPosition( &origin, NULL ); - pObject->GetVelocity( &vel, NULL ); - Vector dir = origin - m_hNPC->GetAbsOrigin(); - dir.z = dir.z > 0 ? 0.1f : -0.1f; - VectorNormalize(dir); - AngularImpulse angVel; - angVel.Init(); - - // NOTE: Iterate this object's contact points - // if it can't move in this direction, try sliding along the plane/crease - Vector pushImpulse; - PhysComputeSlideDirection( pObject, dir * PUSH_SPEED, angVel, &pushImpulse, NULL, 0 ); - - dir = pushImpulse; - VectorNormalize(dir); - - if ( DotProduct( vel, dir ) < PUSH_SPEED * 0.5f ) - { - linear = pushImpulse; - if ( pObject->GetContactPoint(NULL,NULL) ) - { - linear.z += sv_gravity.GetFloat(); - } - } - return SIM_GLOBAL_ACCELERATION; - } - return SIM_NOTHING; -} - - -CBaseEntity *NPCPhysics_CreateSolver( CAI_BaseNPC *pNPC, CBaseEntity *pPhysicsObject, bool disableCollisions, float separationDuration ) -{ - if ( disableCollisions ) - { - if ( PhysEntityCollisionsAreDisabled( pNPC, pPhysicsObject ) ) - return NULL; - } - else - { - if ( pPhysicsObject->IsNavIgnored() ) - return NULL; - } - return CPhysicsNPCSolver::Create( pNPC, pPhysicsObject, disableCollisions, separationDuration ); -} - - -class CPhysicsEntitySolver : public CLogicalEntity//, public IMotionEvent -{ - DECLARE_CLASS( CPhysicsEntitySolver, CLogicalEntity ); -public: - DECLARE_DATADESC(); - void Init( CBaseEntity *pMovingEntity, CBaseEntity *pPhysicsBlocker, float separationTime ); - static CPhysicsEntitySolver *Create( CBaseEntity *pMovingEntity, CBaseEntity *pPhysicsBlocker, float separationTime ); - - // CBaseEntity - virtual void Spawn(); - virtual void UpdateOnRemove(); - virtual void Think(); - - // IMotionEvent - //virtual simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ); - -private: - // locals - void ResetCancelTime(); - void BecomePenetrationSolver(); - //bool IsIntersecting(); - //bool IsTouching(); - - EHANDLE m_hMovingEntity; - EHANDLE m_hPhysicsBlocker; - //IPhysicsMotionController *m_pController; - float m_separationDuration; - float m_cancelTime; - int m_savedCollisionGroup; -}; - -LINK_ENTITY_TO_CLASS( physics_entity_solver, CPhysicsEntitySolver ); - -BEGIN_DATADESC( CPhysicsEntitySolver ) - - DEFINE_FIELD( m_hMovingEntity, FIELD_EHANDLE ), - DEFINE_FIELD( m_hPhysicsBlocker, FIELD_EHANDLE ), - DEFINE_FIELD( m_separationDuration, FIELD_FLOAT ), - DEFINE_FIELD( m_cancelTime, FIELD_TIME ), - DEFINE_FIELD( m_savedCollisionGroup, FIELD_INTEGER ), - //DEFINE_PHYSPTR( m_pController ), - -END_DATADESC() - -CPhysicsEntitySolver *CPhysicsEntitySolver::Create( CBaseEntity *pMovingEntity, CBaseEntity *pPhysicsBlocker, float separationTime ) -{ - CPhysicsEntitySolver *pSolver = (CPhysicsEntitySolver *)CBaseEntity::CreateNoSpawn( "physics_entity_solver", vec3_origin, vec3_angle, NULL ); - pSolver->Init( pMovingEntity, pPhysicsBlocker, separationTime ); - pSolver->Spawn(); - //NDebugOverlay::EntityBounds(pNPC, 255, 255, 0, 64, 0.5f ); - return pSolver; -} - -void CPhysicsEntitySolver::Init( CBaseEntity *pMovingEntity, CBaseEntity *pPhysicsBlocker, float separationTime ) -{ - m_hMovingEntity = pMovingEntity; - m_hPhysicsBlocker = pPhysicsBlocker; - //m_pController = NULL; - m_separationDuration = separationTime; -} - -void CPhysicsEntitySolver::Spawn() -{ - SetNextThink( gpGlobals->curtime + m_separationDuration ); - PhysDisableEntityCollisions( m_hMovingEntity, m_hPhysicsBlocker ); - m_savedCollisionGroup = m_hPhysicsBlocker->GetCollisionGroup(); - m_hPhysicsBlocker->SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - if ( m_hPhysicsBlocker->VPhysicsGetObject() ) - { - m_hPhysicsBlocker->VPhysicsGetObject()->RecheckContactPoints(); - } -} - -void CPhysicsEntitySolver::Think() -{ - UTIL_Remove(this); -} - -void CPhysicsEntitySolver::UpdateOnRemove() -{ - //physenv->DestroyMotionController( m_pController ); - //m_pController = NULL; - CBaseEntity *pEntity = m_hMovingEntity.Get(); - CBaseEntity *pPhysics = m_hPhysicsBlocker.Get(); - if ( pEntity && pPhysics ) - { - PhysEnableEntityCollisions( pEntity, pPhysics ); - } - if ( pPhysics ) - { - pPhysics->SetCollisionGroup( m_savedCollisionGroup ); - } - BaseClass::UpdateOnRemove(); -} - - -CBaseEntity *EntityPhysics_CreateSolver( CBaseEntity *pMovingEntity, CBaseEntity *pPhysicsObject, bool disableCollisions, float separationDuration ) -{ - if ( PhysEntityCollisionsAreDisabled( pMovingEntity, pPhysicsObject ) ) - return NULL; - - return CPhysicsEntitySolver::Create( pMovingEntity, pPhysicsObject, separationDuration ); -} - diff --git a/game/server/physics_npc_solver.h b/game/server/physics_npc_solver.h deleted file mode 100644 index 275781db2..000000000 --- a/game/server/physics_npc_solver.h +++ /dev/null @@ -1,19 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef PHYSICS_NPC_SOLVER_H -#define PHYSICS_NPC_SOLVER_H -#ifdef _WIN32 -#pragma once -#endif - - -extern CBaseEntity *NPCPhysics_CreateSolver( CAI_BaseNPC *pNPC, CBaseEntity *pPhysicsObject, bool disableCollisions, float separationDuration ); -extern CBaseEntity *EntityPhysics_CreateSolver( CBaseEntity *pMovingEntity, CBaseEntity *pPhysicsBlocker, bool disableCollisions, float separationDuration ); -bool NPCPhysics_SolverExists( CAI_BaseNPC *pNPC, CBaseEntity *pPhysicsObject ); - - -#endif // PHYSICS_NPC_SOLVER_H diff --git a/game/server/physics_prop_ragdoll.cpp b/game/server/physics_prop_ragdoll.cpp deleted file mode 100644 index 05b620bd6..000000000 --- a/game/server/physics_prop_ragdoll.cpp +++ /dev/null @@ -1,1712 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "baseanimating.h" -#include "studio.h" -#include "physics.h" -#include "physics_saverestore.h" -#include "ai_basenpc.h" -#include "vphysics/constraints.h" -#include "datacache/imdlcache.h" -#include "bone_setup.h" -#include "physics_prop_ragdoll.h" -#include "KeyValues.h" -#include "props.h" -#include "RagdollBoogie.h" -#include "AI_Criteria.h" -#include "ragdoll_shared.h" -#include "hierarchy.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -const char *GetMassEquivalent(float flMass); - -#define RAGDOLL_VISUALIZE 0 - -//----------------------------------------------------------------------------- -// ThinkContext -//----------------------------------------------------------------------------- -const char *s_pFadeOutContext = "RagdollFadeOutContext"; -const char *s_pDebrisContext = "DebrisContext"; - -const float ATTACHED_DAMPING_SCALE = 50.0f; - -//----------------------------------------------------------------------------- -// Spawnflags -//----------------------------------------------------------------------------- -#define SF_RAGDOLLPROP_DEBRIS 0x0004 -#define SF_RAGDOLLPROP_USE_LRU_RETIREMENT 0x1000 -#define SF_RAGDOLLPROP_ALLOW_DISSOLVE 0x2000 // Allow this prop to be dissolved -#define SF_RAGDOLLPROP_MOTIONDISABLED 0x4000 -#define SF_RAGDOLLPROP_ALLOW_STRETCH 0x8000 -#define SF_RAGDOLLPROP_STARTASLEEP 0x10000 - -//----------------------------------------------------------------------------- -// Networking -//----------------------------------------------------------------------------- -LINK_ENTITY_TO_CLASS( physics_prop_ragdoll, CRagdollProp ); -LINK_ENTITY_TO_CLASS( prop_ragdoll, CRagdollProp ); -EXTERN_SEND_TABLE(DT_Ragdoll) - -IMPLEMENT_SERVERCLASS_ST(CRagdollProp, DT_Ragdoll) - SendPropArray (SendPropQAngles(SENDINFO_ARRAY(m_ragAngles), 13, 0 ), m_ragAngles), - SendPropArray (SendPropVector(SENDINFO_ARRAY(m_ragPos), -1, SPROP_COORD ), m_ragPos), - SendPropEHandle(SENDINFO( m_hUnragdoll ) ), - SendPropFloat(SENDINFO(m_flBlendWeight), 8, SPROP_ROUNDDOWN, 0.0f, 1.0f ), - SendPropInt(SENDINFO(m_nOverlaySequence), 11), -END_SEND_TABLE() - -#define DEFINE_RAGDOLL_ELEMENT( i ) \ - DEFINE_FIELD( m_ragdoll.list[i].originParentSpace, FIELD_VECTOR ), \ - DEFINE_PHYSPTR( m_ragdoll.list[i].pObject ), \ - DEFINE_PHYSPTR( m_ragdoll.list[i].pConstraint ), \ - DEFINE_FIELD( m_ragdoll.list[i].parentIndex, FIELD_INTEGER ) - -BEGIN_DATADESC(CRagdollProp) -// m_ragdoll (custom handling) - DEFINE_AUTO_ARRAY ( m_ragdoll.boneIndex, FIELD_INTEGER ), - DEFINE_AUTO_ARRAY ( m_ragPos, FIELD_POSITION_VECTOR ), - DEFINE_AUTO_ARRAY ( m_ragAngles, FIELD_VECTOR ), - DEFINE_KEYFIELD(m_anglesOverrideString, FIELD_STRING, "angleOverride" ), - DEFINE_FIELD( m_lastUpdateTickCount, FIELD_INTEGER ), - DEFINE_FIELD( m_allAsleep, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hDamageEntity, FIELD_EHANDLE ), - DEFINE_FIELD( m_hKiller, FIELD_EHANDLE ), - - DEFINE_KEYFIELD( m_bStartDisabled, FIELD_BOOLEAN, "StartDisabled" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "StartRagdollBoogie", InputStartRadgollBoogie ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableMotion", InputEnableMotion ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableMotion", InputDisableMotion ), - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputTurnOff ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "FadeAndRemove", InputFadeAndRemove ), - - DEFINE_FIELD( m_hUnragdoll, FIELD_EHANDLE ), - DEFINE_FIELD( m_bFirstCollisionAfterLaunch, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_flBlendWeight, FIELD_FLOAT ), - DEFINE_FIELD( m_nOverlaySequence, FIELD_INTEGER ), - DEFINE_AUTO_ARRAY( m_ragdollMins, FIELD_VECTOR ), - DEFINE_AUTO_ARRAY( m_ragdollMaxs, FIELD_VECTOR ), - - // Physics Influence - DEFINE_FIELD( m_hPhysicsAttacker, FIELD_EHANDLE ), - DEFINE_FIELD( m_flLastPhysicsInfluenceTime, FIELD_TIME ), - DEFINE_FIELD( m_flFadeOutStartTime, FIELD_TIME ), - DEFINE_FIELD( m_flFadeTime, FIELD_FLOAT), - DEFINE_FIELD( m_strSourceClassName, FIELD_STRING ), - DEFINE_FIELD( m_bHasBeenPhysgunned, FIELD_BOOLEAN ), - - // think functions - DEFINE_THINKFUNC( SetDebrisThink ), - DEFINE_THINKFUNC( ClearFlagsThink ), - DEFINE_THINKFUNC( FadeOutThink ), - - DEFINE_FIELD( m_ragdoll.listCount, FIELD_INTEGER ), - DEFINE_FIELD( m_ragdoll.allowStretch, FIELD_BOOLEAN ), - DEFINE_PHYSPTR( m_ragdoll.pGroup ), - DEFINE_FIELD( m_flDefaultFadeScale, FIELD_FLOAT ), - - //DEFINE_RAGDOLL_ELEMENT( 0 ), - DEFINE_RAGDOLL_ELEMENT( 1 ), - DEFINE_RAGDOLL_ELEMENT( 2 ), - DEFINE_RAGDOLL_ELEMENT( 3 ), - DEFINE_RAGDOLL_ELEMENT( 4 ), - DEFINE_RAGDOLL_ELEMENT( 5 ), - DEFINE_RAGDOLL_ELEMENT( 6 ), - DEFINE_RAGDOLL_ELEMENT( 7 ), - DEFINE_RAGDOLL_ELEMENT( 8 ), - DEFINE_RAGDOLL_ELEMENT( 9 ), - DEFINE_RAGDOLL_ELEMENT( 10 ), - DEFINE_RAGDOLL_ELEMENT( 11 ), - DEFINE_RAGDOLL_ELEMENT( 12 ), - DEFINE_RAGDOLL_ELEMENT( 13 ), - DEFINE_RAGDOLL_ELEMENT( 14 ), - DEFINE_RAGDOLL_ELEMENT( 15 ), - DEFINE_RAGDOLL_ELEMENT( 16 ), - DEFINE_RAGDOLL_ELEMENT( 17 ), - DEFINE_RAGDOLL_ELEMENT( 18 ), - DEFINE_RAGDOLL_ELEMENT( 19 ), - DEFINE_RAGDOLL_ELEMENT( 20 ), - DEFINE_RAGDOLL_ELEMENT( 21 ), - DEFINE_RAGDOLL_ELEMENT( 22 ), - DEFINE_RAGDOLL_ELEMENT( 23 ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Disable auto fading under dx7 or when level fades are specified -//----------------------------------------------------------------------------- -void CRagdollProp::DisableAutoFade() -{ - m_flFadeScale = 0; - m_flDefaultFadeScale = 0; -} - - -void CRagdollProp::Spawn( void ) -{ - // Starts out as the default fade scale value - m_flDefaultFadeScale = m_flFadeScale; - - // NOTE: If this fires, then the assert or the datadesc is wrong! (see DEFINE_RAGDOLL_ELEMENT above) - Assert( RAGDOLL_MAX_ELEMENTS == 24 ); - Precache(); - SetModel( STRING( GetModelName() ) ); - - CStudioHdr *pStudioHdr = GetModelPtr( ); - if ( pStudioHdr->flags() & STUDIOHDR_FLAGS_NO_FORCED_FADE ) - { - DisableAutoFade(); - } - else - { - m_flFadeScale = m_flDefaultFadeScale; - } - - matrix3x4_t pBoneToWorld[MAXSTUDIOBONES]; - BaseClass::SetupBones( pBoneToWorld, BONE_USED_BY_ANYTHING ); // FIXME: shouldn't this be a subset of the bones - // this is useless info after the initial conditions are set - SetAbsAngles( vec3_angle ); - int collisionGroup = (m_spawnflags & SF_RAGDOLLPROP_DEBRIS) ? COLLISION_GROUP_DEBRIS : COLLISION_GROUP_NONE; - bool bWake = (m_spawnflags & SF_RAGDOLLPROP_STARTASLEEP) ? false : true; - InitRagdoll( vec3_origin, 0, vec3_origin, pBoneToWorld, pBoneToWorld, 0, collisionGroup, true, bWake ); - m_lastUpdateTickCount = 0; - m_flBlendWeight = 0.0f; - m_nOverlaySequence = -1; - - // Unless specified, do not allow this to be dissolved - if ( HasSpawnFlags( SF_RAGDOLLPROP_ALLOW_DISSOLVE ) == false ) - { - AddEFlags( EFL_NO_DISSOLVE ); - } - - if ( HasSpawnFlags(SF_RAGDOLLPROP_MOTIONDISABLED) ) - { - DisableMotion(); - } - - if( m_bStartDisabled ) - { - AddEffects( EF_NODRAW ); - } -} - -void CRagdollProp::SetSourceClassName( const char *pClassname ) -{ - m_strSourceClassName = MAKE_STRING( pClassname ); -} - - -void CRagdollProp::OnSave( IEntitySaveUtils *pUtils ) -{ - if ( !m_ragdoll.listCount ) - return; - - // Don't save ragdoll element 0, base class saves the pointer in - // m_pPhysicsObject - Assert( m_ragdoll.list[0].parentIndex == -1 ); - Assert( m_ragdoll.list[0].pConstraint == NULL ); - Assert( m_ragdoll.list[0].originParentSpace == vec3_origin ); - Assert( m_ragdoll.list[0].pObject != NULL ); - VPhysicsSetObject( NULL ); // squelch a warning message - VPhysicsSetObject( m_ragdoll.list[0].pObject ); // make sure object zero is saved by CBaseEntity - BaseClass::OnSave( pUtils ); -} - -void CRagdollProp::OnRestore() -{ - // rebuild element 0 since it isn't saved - // NOTE: This breaks the rules - the pointer needs to get fixed in Restore() - m_ragdoll.list[0].pObject = VPhysicsGetObject(); - m_ragdoll.list[0].parentIndex = -1; - m_ragdoll.list[0].originParentSpace.Init(); - - BaseClass::OnRestore(); - if ( !m_ragdoll.listCount ) - return; - - // JAY: Reset collision relationships - RagdollSetupCollisions( m_ragdoll, modelinfo->GetVCollide( GetModelIndex() ), GetModelIndex() ); - VPhysicsUpdate( VPhysicsGetObject() ); -} - -void CRagdollProp::CalcRagdollSize( void ) -{ - CollisionProp()->SetSurroundingBoundsType( USE_HITBOXES ); - CollisionProp()->RemoveSolidFlags( FSOLID_FORCE_WORLD_ALIGNED ); -} - -void CRagdollProp::UpdateOnRemove( void ) -{ - for ( int i = 0; i < m_ragdoll.listCount; i++ ) - { - if ( m_ragdoll.list[i].pObject ) - { - g_pPhysSaveRestoreManager->ForgetModel( m_ragdoll.list[i].pObject ); - } - } - - // Set to null so that the destructor's call to DestroyObject won't destroy - // m_pObjects[ 0 ] twice since that's the physics object for the prop - VPhysicsSetObject( NULL ); - - RagdollDestroy( m_ragdoll ); - // Chain to base after doing our own cleanup to mimic - // destructor unwind order - BaseClass::UpdateOnRemove(); -} - -CRagdollProp::CRagdollProp( void ) -{ - m_strSourceClassName = NULL_STRING; - m_anglesOverrideString = NULL_STRING; - m_ragdoll.listCount = 0; - Assert( (1<=RAGDOLL_MAX_ELEMENTS ); - m_allAsleep = false; - m_flFadeScale = 1; - m_flDefaultFadeScale = 1; -} - -CRagdollProp::~CRagdollProp( void ) -{ -} - -void CRagdollProp::Precache( void ) -{ - PrecacheModel( STRING( GetModelName() ) ); - BaseClass::Precache(); -} - -int CRagdollProp::ObjectCaps() -{ - return BaseClass::ObjectCaps() | FCAP_WCEDIT_POSITION; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CRagdollProp::InitRagdollAnimation() -{ - m_flAnimTime = gpGlobals->curtime; - m_flPlaybackRate = 0.0; - SetCycle( 0 ); - - // put into ACT_DIERAGDOLL if it exists, otherwise use sequence 0 - int nSequence = SelectWeightedSequence( ACT_DIERAGDOLL ); - if ( nSequence < 0 ) - { - ResetSequence( 0 ); - } - else - { - ResetSequence( nSequence ); - } -} - - -//----------------------------------------------------------------------------- -// Response system stuff -//----------------------------------------------------------------------------- -IResponseSystem *CRagdollProp::GetResponseSystem() -{ - extern IResponseSystem *g_pResponseSystem; - - // Just use the general NPC response system; we often come from NPCs after all - return g_pResponseSystem; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CRagdollProp::ModifyOrAppendCriteria( AI_CriteriaSet& set ) -{ - BaseClass::ModifyOrAppendCriteria( set ); - - if ( m_strSourceClassName != NULL_STRING ) - { - set.RemoveCriteria( "classname" ); - set.AppendCriteria( "classname", STRING(m_strSourceClassName) ); - set.AppendCriteria( "ragdoll", "1" ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CRagdollProp::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) -{ - m_hPhysicsAttacker = pPhysGunUser; - m_flLastPhysicsInfluenceTime = gpGlobals->curtime; - - // Clear out the classname if we've been physgunned before - // so that the screams, etc. don't happen. Simulate that the first - // major punt or throw has been enough to kill him. - if ( m_bHasBeenPhysgunned ) - { - m_strSourceClassName = NULL_STRING; - } - m_bHasBeenPhysgunned = true; - - if( HasPhysgunInteraction( "onpickup", "boogie" ) ) - { - if ( reason == PUNTED_BY_CANNON ) - { - CRagdollBoogie::Create( this, 150, gpGlobals->curtime, 3.0f, SF_RAGDOLL_BOOGIE_ELECTRICAL ); - } - else - { - CRagdollBoogie::Create( this, 150, gpGlobals->curtime, 2.0f, 0 ); - } - } - - if ( HasSpawnFlags( SF_RAGDOLLPROP_USE_LRU_RETIREMENT ) ) - { - s_RagdollLRU.MoveToTopOfLRU( this ); - } - - if ( !HasSpawnFlags( SF_PHYSPROP_ENABLE_ON_PHYSCANNON ) ) - return; - - ragdoll_t *pRagdollPhys = GetRagdoll( ); - for ( int j = 0; j < pRagdollPhys->listCount; ++j ) - { - pRagdollPhys->list[j].pObject->Wake(); - pRagdollPhys->list[j].pObject->EnableMotion( true ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CRagdollProp::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ) -{ - CDefaultPlayerPickupVPhysics::OnPhysGunDrop( pPhysGunUser, Reason ); - m_hPhysicsAttacker = pPhysGunUser; - m_flLastPhysicsInfluenceTime = gpGlobals->curtime; - - if( HasPhysgunInteraction( "onpickup", "boogie" ) ) - { - CRagdollBoogie::Create( this, 150, gpGlobals->curtime, 3.0f, SF_RAGDOLL_BOOGIE_ELECTRICAL ); - } - - if ( HasSpawnFlags( SF_RAGDOLLPROP_USE_LRU_RETIREMENT ) ) - { - s_RagdollLRU.MoveToTopOfLRU( this ); - } - - // Make sure it's interactive debris for at most 5 seconds - if ( GetCollisionGroup() == COLLISION_GROUP_INTERACTIVE_DEBRIS ) - { - SetContextThink( &CRagdollProp::SetDebrisThink, gpGlobals->curtime + 5, s_pDebrisContext ); - } - - if ( Reason != LAUNCHED_BY_CANNON ) - return; - - if( HasPhysgunInteraction( "onlaunch", "spin_zaxis" ) ) - { - Vector vecAverageCenter( 0, 0, 0 ); - - // Get the average position, apply forces to produce a spin - int j; - ragdoll_t *pRagdollPhys = GetRagdoll( ); - for ( j = 0; j < pRagdollPhys->listCount; ++j ) - { - Vector vecCenter; - pRagdollPhys->list[j].pObject->GetPosition( &vecCenter, NULL ); - vecAverageCenter += vecCenter; - } - - vecAverageCenter /= pRagdollPhys->listCount; - - Vector vecZAxis( 0, 0, 1 ); - for ( j = 0; j < pRagdollPhys->listCount; ++j ) - { - Vector vecDelta; - pRagdollPhys->list[j].pObject->GetPosition( &vecDelta, NULL ); - vecDelta -= vecAverageCenter; - - Vector vecDir; - CrossProduct( vecZAxis, vecDelta, vecDir ); - vecDir *= 100; - pRagdollPhys->list[j].pObject->AddVelocity( &vecDir, NULL ); - } - } - - PhysSetGameFlags( VPhysicsGetObject(), FVPHYSICS_WAS_THROWN ); - m_bFirstCollisionAfterLaunch = true; -} - - -//----------------------------------------------------------------------------- -// Physics attacker -//----------------------------------------------------------------------------- -CBasePlayer *CRagdollProp::HasPhysicsAttacker( float dt ) -{ - if (gpGlobals->curtime - dt <= m_flLastPhysicsInfluenceTime) - { - return m_hPhysicsAttacker; - } - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CRagdollProp::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) -{ - BaseClass::VPhysicsCollision( index, pEvent ); - - CBaseEntity *pHitEntity = pEvent->pEntities[!index]; - if ( pHitEntity == this ) - return; - - // Don't take physics damage from whoever's holding him with the physcannon. - if ( VPhysicsGetObject() && (VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD) ) - { - if ( pHitEntity && (pHitEntity == HasPhysicsAttacker( FLT_MAX )) ) - return; - } - - // Don't bother taking damage from the physics attacker - if ( pHitEntity && HasPhysicsAttacker( 0.5f ) == pHitEntity ) - return; - - if( m_bFirstCollisionAfterLaunch ) - { - HandleFirstCollisionInteractions( index, pEvent ); - } - - if ( m_takedamage != DAMAGE_NO ) - { - int damageType = 0; - float damage = CalculateDefaultPhysicsDamage( index, pEvent, 1.0f, true, damageType ); - if ( damage > 0 ) - { - // Take extra damage after we're punted by the physcannon - if ( m_bFirstCollisionAfterLaunch ) - { - damage *= 10; - } - - CBaseEntity *pHitEntity = pEvent->pEntities[!index]; - if ( !pHitEntity ) - { - // hit world - pHitEntity = GetContainingEntity( INDEXENT(0) ); - } - Vector damagePos; - pEvent->pInternalData->GetContactPoint( damagePos ); - Vector damageForce = pEvent->postVelocity[index] * pEvent->pObjects[index]->GetMass(); - if ( damageForce == vec3_origin ) - { - // This can happen if this entity is motion disabled, and can't move. - // Use the velocity of the entity that hit us instead. - damageForce = pEvent->postVelocity[!index] * pEvent->pObjects[!index]->GetMass(); - } - - // FIXME: this doesn't pass in who is responsible if some other entity "caused" this collision - PhysCallbackDamage( this, CTakeDamageInfo( pHitEntity, pHitEntity, damageForce, damagePos, damage, damageType ), *pEvent, index ); - } - } - - if ( m_bFirstCollisionAfterLaunch ) - { - // Setup the think function to remove the flags - SetThink( &CRagdollProp::ClearFlagsThink ); - SetNextThink( gpGlobals->curtime ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CRagdollProp::HasPhysgunInteraction( const char *pszKeyName, const char *pszValue ) -{ - KeyValues *modelKeyValues = new KeyValues(""); - if ( modelKeyValues->LoadFromBuffer( modelinfo->GetModelName( GetModel() ), modelinfo->GetModelKeyValueText( GetModel() ) ) ) - { - KeyValues *pkvPropData = modelKeyValues->FindKey("physgun_interactions"); - if ( pkvPropData ) - { - char const *pszBase = pkvPropData->GetString( pszKeyName ); - - if ( pszBase && pszBase[0] && !stricmp( pszBase, pszValue ) ) - { - modelKeyValues->deleteThis(); - return true; - } - } - } - - modelKeyValues->deleteThis(); - return false; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CRagdollProp::HandleFirstCollisionInteractions( int index, gamevcollisionevent_t *pEvent ) -{ - IPhysicsObject *pObj = VPhysicsGetObject(); - if ( !pObj) - return; - - if( HasPhysgunInteraction( "onfirstimpact", "break" ) ) - { - // Looks like it's best to break by having the object damage itself. - CTakeDamageInfo info; - - info.SetDamage( m_iHealth ); - info.SetAttacker( this ); - info.SetInflictor( this ); - info.SetDamageType( DMG_GENERIC ); - - Vector vecPosition; - Vector vecVelocity; - - VPhysicsGetObject()->GetVelocity( &vecVelocity, NULL ); - VPhysicsGetObject()->GetPosition( &vecPosition, NULL ); - - info.SetDamageForce( vecVelocity ); - info.SetDamagePosition( vecPosition ); - - TakeDamage( info ); - return; - } - - if( HasPhysgunInteraction( "onfirstimpact", "paintsplat" ) ) - { - IPhysicsObject *pObj = VPhysicsGetObject(); - - Vector vecPos; - pObj->GetPosition( &vecPos, NULL ); - - trace_t tr; - UTIL_TraceLine( vecPos, vecPos + pEvent->preVelocity[0] * 1.5, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - switch( random->RandomInt( 1, 3 ) ) - { - case 1: - UTIL_DecalTrace( &tr, "PaintSplatBlue" ); - break; - - case 2: - UTIL_DecalTrace( &tr, "PaintSplatGreen" ); - break; - - case 3: - UTIL_DecalTrace( &tr, "PaintSplatPink" ); - break; - } - } - - bool bAlienBloodSplat = HasPhysgunInteraction( "onfirstimpact", "alienbloodsplat" ); - if( bAlienBloodSplat || HasPhysgunInteraction( "onfirstimpact", "bloodsplat" ) ) - { - IPhysicsObject *pObj = VPhysicsGetObject(); - - Vector vecPos; - pObj->GetPosition( &vecPos, NULL ); - - trace_t tr; - UTIL_TraceLine( vecPos, vecPos + pEvent->preVelocity[0] * 1.5, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - UTIL_BloodDecalTrace( &tr, bAlienBloodSplat ? BLOOD_COLOR_GREEN : BLOOD_COLOR_RED ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CRagdollProp::ClearFlagsThink( void ) -{ - PhysClearGameFlags( VPhysicsGetObject(), FVPHYSICS_WAS_THROWN ); - m_bFirstCollisionAfterLaunch = false; - SetThink( NULL ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -AngularImpulse CRagdollProp::PhysGunLaunchAngularImpulse() -{ - if( HasPhysgunInteraction( "onlaunch", "spin_zaxis" ) ) - { - // Don't add in random angular impulse if this object is supposed to spin in a specific way. - AngularImpulse ang( 0, 0, 0 ); - return ang; - } - - return CDefaultPlayerPickupVPhysics::PhysGunLaunchAngularImpulse(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : activity - -//----------------------------------------------------------------------------- -void CRagdollProp::SetOverlaySequence( Activity activity ) -{ - int seq = SelectWeightedSequence( activity ); - if ( seq < 0 ) - { - m_nOverlaySequence = -1; - } - else - { - m_nOverlaySequence = seq; - } -} - -void CRagdollProp::InitRagdoll( const Vector &forceVector, int forceBone, const Vector &forcePos, matrix3x4_t *pPrevBones, matrix3x4_t *pBoneToWorld, float dt, int collisionGroup, bool activateRagdoll, bool bWakeRagdoll ) -{ - SetCollisionGroup( collisionGroup ); - - // Make sure it's interactive debris for at most 5 seconds - if ( collisionGroup == COLLISION_GROUP_INTERACTIVE_DEBRIS ) - { - SetContextThink( &CRagdollProp::SetDebrisThink, gpGlobals->curtime + 5, s_pDebrisContext ); - } - - SetMoveType( MOVETYPE_VPHYSICS ); - SetSolid( SOLID_VPHYSICS ); - AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST ); - m_takedamage = DAMAGE_EVENTS_ONLY; - - ragdollparams_t params; - params.pGameData = static_cast( static_cast(this) ); - params.modelIndex = GetModelIndex(); - params.pCollide = modelinfo->GetVCollide( params.modelIndex ); - params.pStudioHdr = GetModelPtr(); - params.forceVector = forceVector; - params.forceBoneIndex = forceBone; - params.forcePosition = forcePos; - params.pCurrentBones = pBoneToWorld; - params.jointFrictionScale = 1.0; - params.allowStretch = HasSpawnFlags(SF_RAGDOLLPROP_ALLOW_STRETCH); - RagdollCreate( m_ragdoll, params, physenv ); - RagdollApplyAnimationAsVelocity( m_ragdoll, pPrevBones, pBoneToWorld, dt ); - if ( m_anglesOverrideString != NULL_STRING && Q_strlen(m_anglesOverrideString.ToCStr()) > 0 ) - { - char szToken[2048]; - const char *pStr = nexttoken(szToken, STRING(m_anglesOverrideString), ','); - // anglesOverride is index,angles,index,angles (e.g. "1, 22.5 123.0 0.0, 2, 0 0 0, 3, 0 0 180.0") - while ( szToken[0] != 0 ) - { - int objectIndex = atoi(szToken); - // sanity check to make sure this token is an integer - Assert( atof(szToken) == ((float)objectIndex) ); - pStr = nexttoken(szToken, pStr, ','); - Assert( szToken[0] ); - if ( objectIndex >= m_ragdoll.listCount ) - { - Warning("Bad ragdoll pose in entity %s, model (%s) at %s, model changed?\n", GetDebugName(), GetModelName().ToCStr(), VecToString(GetAbsOrigin()) ); - } - else if ( szToken[0] != 0 ) - { - QAngle angles; - Assert( objectIndex >= 0 && objectIndex < RAGDOLL_MAX_ELEMENTS ); - UTIL_StringToVector( angles.Base(), szToken ); - int boneIndex = m_ragdoll.boneIndex[objectIndex]; - AngleMatrix( angles, pBoneToWorld[boneIndex] ); - const ragdollelement_t &element = m_ragdoll.list[objectIndex]; - Vector out; - if ( element.parentIndex >= 0 ) - { - int parentBoneIndex = m_ragdoll.boneIndex[element.parentIndex]; - VectorTransform( element.originParentSpace, pBoneToWorld[parentBoneIndex], out ); - } - else - { - out = GetAbsOrigin(); - } - MatrixSetColumn( out, 3, pBoneToWorld[boneIndex] ); - element.pObject->SetPositionMatrix( pBoneToWorld[boneIndex], true ); - } - pStr = nexttoken(szToken, pStr, ','); - } - } - - if ( activateRagdoll ) - { - MEM_ALLOC_CREDIT(); - RagdollActivate( m_ragdoll, params.pCollide, GetModelIndex(), bWakeRagdoll ); - } - - for ( int i = 0; i < m_ragdoll.listCount; i++ ) - { - UpdateNetworkDataFromVPhysics( m_ragdoll.list[i].pObject, i ); - g_pPhysSaveRestoreManager->AssociateModel( m_ragdoll.list[i].pObject, GetModelIndex() ); - physcollision->CollideGetAABB( &m_ragdollMins[i], &m_ragdollMaxs[i], m_ragdoll.list[i].pObject->GetCollide(), vec3_origin, vec3_angle ); - } - VPhysicsSetObject( m_ragdoll.list[0].pObject ); - - CalcRagdollSize(); -} - -void CRagdollProp::SetDebrisThink() -{ - SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - RecheckCollisionFilter(); -} - -void CRagdollProp::SetDamageEntity( CBaseEntity *pEntity ) -{ - // Damage passing - m_hDamageEntity = pEntity; - - // Set our takedamage to match it - if ( pEntity ) - { - m_takedamage = pEntity->m_takedamage; - } - else - { - m_takedamage = DAMAGE_EVENTS_ONLY; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CRagdollProp::OnTakeDamage( const CTakeDamageInfo &info ) -{ - // If we have a damage entity, we want to pass damage to it. Add the - // Never Ragdoll flag, on the assumption that if the entity dies, we'll - // actually be taking the role of its ragdoll. - if ( m_hDamageEntity.Get() ) - { - CTakeDamageInfo subInfo = info; - subInfo.AddDamageType( DMG_REMOVENORAGDOLL ); - return m_hDamageEntity->OnTakeDamage( subInfo ); - } - - return BaseClass::OnTakeDamage( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: Force all the ragdoll's bone's physics objects to recheck their collision filters -//----------------------------------------------------------------------------- -void CRagdollProp::RecheckCollisionFilter( void ) -{ - for ( int i = 0; i < m_ragdoll.listCount; i++ ) - { - m_ragdoll.list[i].pObject->RecheckCollisionFilter(); - } -} - - -void CRagdollProp::TraceAttack( const CTakeDamageInfo &info, const Vector &dir, trace_t *ptr ) -{ - if ( ptr->physicsbone >= 0 && ptr->physicsbone < m_ragdoll.listCount ) - { - VPhysicsSwapObject( m_ragdoll.list[ptr->physicsbone].pObject ); - } - BaseClass::TraceAttack( info, dir, ptr ); -} - -void CRagdollProp::SetupBones( matrix3x4_t *pBoneToWorld, int boneMask ) -{ - // no ragdoll, fall through to base class - if ( !m_ragdoll.listCount ) - { - BaseClass::SetupBones( pBoneToWorld, boneMask ); - return; - } - - // Not really ideal, but it'll work for now - UpdateModelWidthScale(); - - MDLCACHE_CRITICAL_SECTION(); - CStudioHdr *pStudioHdr = GetModelPtr( ); - bool sim[MAXSTUDIOBONES]; - memset( sim, 0, pStudioHdr->numbones() ); - - int i; - - CBoneAccessor boneaccessor( pBoneToWorld ); - for ( i = 0; i < m_ragdoll.listCount; i++ ) - { - // during restore this may be NULL - if ( !m_ragdoll.list[i].pObject ) - continue; - - if ( RagdollGetBoneMatrix( m_ragdoll, boneaccessor, i ) ) - { - sim[m_ragdoll.boneIndex[i]] = true; - } - } - - mstudiobone_t *pbones = pStudioHdr->pBone( 0 ); - for ( i = 0; i < pStudioHdr->numbones(); i++ ) - { - if ( sim[i] ) - continue; - - if ( !(pStudioHdr->boneFlags(i) & boneMask) ) - continue; - - matrix3x4_t matBoneLocal; - AngleMatrix( pbones[i].rot, pbones[i].pos, matBoneLocal ); - ConcatTransforms( pBoneToWorld[pbones[i].parent], matBoneLocal, pBoneToWorld[i]); - } -} - -bool CRagdollProp::TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ) -{ -#if 0 - // PERFORMANCE: Use hitboxes for rays instead of vcollides if this is a performance problem - if ( ray.m_IsRay ) - { - return BaseClass::TestCollision( ray, mask, trace ); - } -#endif - - CStudioHdr *pStudioHdr = GetModelPtr( ); - if (!pStudioHdr) - return false; - - // Just iterate all of the elements and trace the box against each one. - // NOTE: This is pretty expensive for small/dense characters - trace_t tr; - for ( int i = 0; i < m_ragdoll.listCount; i++ ) - { - Vector position; - QAngle angles; - - if( m_ragdoll.list[i].pObject ) - { - m_ragdoll.list[i].pObject->GetPosition( &position, &angles ); - physcollision->TraceBox( ray, m_ragdoll.list[i].pObject->GetCollide(), position, angles, &tr ); - - if ( tr.fraction < trace.fraction ) - { - tr.physicsbone = i; - tr.surface.surfaceProps = m_ragdoll.list[i].pObject->GetMaterialIndex(); - trace = tr; - } - } - else - { - DevWarning("Bogus object in Ragdoll Prop's ragdoll list!\n"); - } - } - - if ( trace.fraction >= 1 ) - { - return false; - } - - return true; -} - - -void CRagdollProp::Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ) -{ - // newAngles is a relative transform for the entity - // But a ragdoll entity has identity orientation by design - // so we compute a relative transform here based on the previous transform - matrix3x4_t startMatrixInv; - MatrixInvert( EntityToWorldTransform(), startMatrixInv ); - matrix3x4_t endMatrix; - MatrixCopy( EntityToWorldTransform(), endMatrix ); - if ( newAngles ) - { - AngleMatrix( *newAngles, endMatrix ); - } - if ( newPosition ) - { - PositionMatrix( *newPosition, endMatrix ); - } - // now endMatrix is the refernce matrix for the entity at the target position - matrix3x4_t xform; - ConcatTransforms( endMatrix, startMatrixInv, xform ); - // now xform is the relative transform the entity must undergo - - // we need to call the base class and it will teleport our vphysics object, - // so set object 0 up and compute the origin/angles for its new position (base implementation has side effects) - VPhysicsSwapObject( m_ragdoll.list[0].pObject ); - matrix3x4_t obj0source, obj0Target; - m_ragdoll.list[0].pObject->GetPositionMatrix( &obj0source ); - ConcatTransforms( xform, obj0source, obj0Target ); - Vector obj0Pos; - QAngle obj0Angles; - MatrixAngles( obj0Target, obj0Angles, obj0Pos ); - BaseClass::Teleport( &obj0Pos, &obj0Angles, newVelocity ); - - for ( int i = 1; i < m_ragdoll.listCount; i++ ) - { - matrix3x4_t matrix, newMatrix; - m_ragdoll.list[i].pObject->GetPositionMatrix( &matrix ); - ConcatTransforms( xform, matrix, newMatrix ); - m_ragdoll.list[i].pObject->SetPositionMatrix( newMatrix, true ); - UpdateNetworkDataFromVPhysics( m_ragdoll.list[i].pObject, i ); - } - // fixup/relink object 0 - UpdateNetworkDataFromVPhysics( m_ragdoll.list[0].pObject, 0 ); -} - -void CRagdollProp::VPhysicsUpdate( IPhysicsObject *pPhysics ) -{ - if ( m_lastUpdateTickCount == (unsigned int)gpGlobals->tickcount ) - return; - - m_lastUpdateTickCount = gpGlobals->tickcount; - //NetworkStateChanged(); - - matrix3x4_t boneToWorld[MAXSTUDIOBONES]; - QAngle angles; - Vector surroundingMins, surroundingMaxs; - - int i; - for ( i = 0; i < m_ragdoll.listCount; i++ ) - { - CBoneAccessor boneaccessor( boneToWorld ); - if ( RagdollGetBoneMatrix( m_ragdoll, boneaccessor, i ) ) - { - Vector vNewPos; - MatrixAngles( boneToWorld[m_ragdoll.boneIndex[i]], angles, vNewPos ); - m_ragPos.Set( i, vNewPos ); - m_ragAngles.Set( i, angles ); - } - else - { - m_ragPos.GetForModify(i).Init(); - m_ragAngles.GetForModify(i).Init(); - } - } - - // BUGBUG: Use the ragdollmins/maxs to do this instead of the collides - m_allAsleep = RagdollIsAsleep( m_ragdoll ); - - // Don't scream after you've come to rest - if ( m_allAsleep ) - { - m_strSourceClassName = NULL_STRING; - } - else - { - if ( m_ragdoll.pGroup->IsInErrorState() ) - { - RagdollSolveSeparation( m_ragdoll, this ); - } - } - - // Interactive debris converts back to debris when it comes to rest - if ( m_allAsleep && GetCollisionGroup() == COLLISION_GROUP_INTERACTIVE_DEBRIS ) - { - SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - RecheckCollisionFilter(); - SetContextThink( NULL, gpGlobals->curtime, s_pDebrisContext ); - } - - Vector vecFullMins, vecFullMaxs; - vecFullMins = m_ragPos[0]; - vecFullMaxs = m_ragPos[0]; - for ( i = 0; i < m_ragdoll.listCount; i++ ) - { - Vector mins, maxs; - matrix3x4_t update; - if ( !m_ragdoll.list[i].pObject ) - { - m_ragdollMins[i].Init(); - m_ragdollMaxs[i].Init(); - continue; - } - m_ragdoll.list[i].pObject->GetPositionMatrix( &update ); - TransformAABB( update, m_ragdollMins[i], m_ragdollMaxs[i], mins, maxs ); - for ( int j = 0; j < 3; j++ ) - { - if ( mins[j] < vecFullMins[j] ) - { - vecFullMins[j] = mins[j]; - } - if ( maxs[j] > vecFullMaxs[j] ) - { - vecFullMaxs[j] = maxs[j]; - } - } - } - - SetAbsOrigin( m_ragPos[0] ); - SetAbsAngles( vec3_angle ); - const Vector &vecOrigin = CollisionProp()->GetCollisionOrigin(); - CollisionProp()->AddSolidFlags( FSOLID_FORCE_WORLD_ALIGNED ); - CollisionProp()->SetSurroundingBoundsType( USE_COLLISION_BOUNDS_NEVER_VPHYSICS ); - SetCollisionBounds( vecFullMins - vecOrigin, vecFullMaxs - vecOrigin ); - CollisionProp()->MarkSurroundingBoundsDirty(); - - PhysicsTouchTriggers(); -} - -int CRagdollProp::VPhysicsGetObjectList( IPhysicsObject **pList, int listMax ) -{ - for ( int i = 0; i < m_ragdoll.listCount; i++ ) - { - if ( i < listMax ) - { - pList[i] = m_ragdoll.list[i].pObject; - } - } - - return m_ragdoll.listCount; -} - -void CRagdollProp::UpdateNetworkDataFromVPhysics( IPhysicsObject *pPhysics, int index ) -{ - Assert(index < m_ragdoll.listCount); - - QAngle angles; - Vector vPos; - m_ragdoll.list[index].pObject->GetPosition( &vPos, &angles ); - m_ragPos.Set( index, vPos ); - m_ragAngles.Set( index, angles ); - - // move/relink if root moved - if ( index == 0 ) - { - SetAbsOrigin( m_ragPos[0] ); - PhysicsTouchTriggers(); - } -} - - -//----------------------------------------------------------------------------- -// Fade out due to the LRU telling it do -//----------------------------------------------------------------------------- -#define FADE_OUT_LENGTH 0.5f - -void CRagdollProp::FadeOut( float flDelay, float fadeTime ) -{ - if ( IsFading() ) - return; - - m_flFadeTime = ( fadeTime == -1 ) ? FADE_OUT_LENGTH : fadeTime; - - m_flFadeOutStartTime = gpGlobals->curtime + flDelay; - m_flFadeScale = 0; - SetContextThink( &CRagdollProp::FadeOutThink, gpGlobals->curtime + flDelay + 0.01f, s_pFadeOutContext ); -} - -bool CRagdollProp::IsFading() -{ - return ( GetNextThink( s_pFadeOutContext ) >= gpGlobals->curtime ); -} - -void CRagdollProp::FadeOutThink(void) -{ - float dt = gpGlobals->curtime - m_flFadeOutStartTime; - if ( dt < 0 ) - { - SetContextThink( &CRagdollProp::FadeOutThink, gpGlobals->curtime + 0.1, s_pFadeOutContext ); - } - else if ( dt < m_flFadeTime ) - { - float alpha = 1.0f - dt / m_flFadeTime; - int nFade = (int)(alpha * 255.0f); - m_nRenderMode = kRenderTransTexture; - SetRenderColorA( nFade ); - NetworkStateChanged(); - SetContextThink( &CRagdollProp::FadeOutThink, gpGlobals->curtime + TICK_INTERVAL, s_pFadeOutContext ); - } - else - { - // Necessary to cause it to do the appropriate death cleanup - // Yeah, the player may have nothing to do with it, but - // passing NULL to TakeDamage causes bad things to happen - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - CTakeDamageInfo info( pPlayer, pPlayer, 10000.0, DMG_GENERIC ); - TakeDamage( info ); - UTIL_Remove( this ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CRagdollProp::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - if (m_ragdoll.listCount) - { - float mass = 0; - for ( int i = 0; i < m_ragdoll.listCount; i++ ) - { - if ( m_ragdoll.list[i].pObject != NULL ) - { - mass += m_ragdoll.list[i].pObject->GetMass(); - } - } - - char tempstr[512]; - Q_snprintf(tempstr, sizeof(tempstr),"Mass: %.2f kg / %.2f lb (%s)", mass, kg2lbs(mass), GetMassEquivalent(mass) ); - EntityText( text_offset, tempstr, 0); - text_offset++; - } - } - - return text_offset; -} - -void CRagdollProp::DrawDebugGeometryOverlays() -{ - if (m_debugOverlays & OVERLAY_BBOX_BIT) - { - DrawServerHitboxes(); - } - if (m_debugOverlays & OVERLAY_PIVOT_BIT) - { - for ( int i = 0; i < m_ragdoll.listCount; i++ ) - { - if ( m_ragdoll.list[i].pObject ) - { - float mass = m_ragdoll.list[i].pObject->GetMass(); - Vector pos; - m_ragdoll.list[i].pObject->GetPosition( &pos, NULL ); - CFmtStr str("mass %.1f", mass ); - NDebugOverlay::EntityTextAtPosition( pos, 0, str.Access(), 0, 0, 255, 0, 255 ); - } - } - } - BaseClass::DrawDebugGeometryOverlays(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOther - -//----------------------------------------------------------------------------- -void CRagdollProp::SetUnragdoll( CBaseAnimating *pOther ) -{ - m_hUnragdoll = pOther; -} - -//=============================================================================================================== -// RagdollPropAttached -//=============================================================================================================== -class CRagdollPropAttached : public CRagdollProp -{ - DECLARE_CLASS( CRagdollPropAttached, CRagdollProp ); -public: - - CRagdollPropAttached() - { - m_bShouldDetach = false; - } - - ~CRagdollPropAttached() - { - physenv->DestroyConstraint( m_pAttachConstraint ); - m_pAttachConstraint = NULL; - } - - void InitRagdollAttached( IPhysicsObject *pAttached, const Vector &forceVector, int forceBone, matrix3x4_t *pPrevBones, matrix3x4_t *pBoneToWorld, float dt, int collisionGroup, CBaseAnimating *pFollow, int boneIndexRoot, const Vector &boneLocalOrigin, int parentBoneAttach, const Vector &worldAttachOrigin ); - void DetachOnNextUpdate(); - void VPhysicsUpdate( IPhysicsObject *pPhysics ); - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - -private: - void Detach(); - CNetworkVar( int, m_boneIndexAttached ); - CNetworkVar( int, m_ragdollAttachedObjectIndex ); - CNetworkVector( m_attachmentPointBoneSpace ); - CNetworkVector( m_attachmentPointRagdollSpace ); - bool m_bShouldDetach; - IPhysicsConstraint *m_pAttachConstraint; -}; - -LINK_ENTITY_TO_CLASS( prop_ragdoll_attached, CRagdollPropAttached ); -EXTERN_SEND_TABLE(DT_Ragdoll_Attached) - -IMPLEMENT_SERVERCLASS_ST(CRagdollPropAttached, DT_Ragdoll_Attached) - SendPropInt( SENDINFO( m_boneIndexAttached ), MAXSTUDIOBONEBITS, SPROP_UNSIGNED ), - SendPropInt( SENDINFO( m_ragdollAttachedObjectIndex ), RAGDOLL_INDEX_BITS, SPROP_UNSIGNED ), - SendPropVector(SENDINFO(m_attachmentPointBoneSpace), -1, SPROP_COORD ), - SendPropVector(SENDINFO(m_attachmentPointRagdollSpace), -1, SPROP_COORD ), -END_SEND_TABLE() - -BEGIN_DATADESC(CRagdollPropAttached) - DEFINE_FIELD( m_boneIndexAttached, FIELD_INTEGER ), - DEFINE_FIELD( m_ragdollAttachedObjectIndex, FIELD_INTEGER ), - DEFINE_FIELD( m_attachmentPointBoneSpace, FIELD_VECTOR ), - DEFINE_FIELD( m_attachmentPointRagdollSpace, FIELD_VECTOR ), - DEFINE_FIELD( m_bShouldDetach, FIELD_BOOLEAN ), - DEFINE_PHYSPTR( m_pAttachConstraint ), -END_DATADESC() - - -static void SyncAnimatingWithPhysics( CBaseAnimating *pAnimating ) -{ - IPhysicsObject *pPhysics = pAnimating->VPhysicsGetObject(); - if ( pPhysics ) - { - Vector pos; - pPhysics->GetShadowPosition( &pos, NULL ); - pAnimating->SetAbsOrigin( pos ); - } -} - - -CBaseAnimating *CreateServerRagdollSubmodel( CBaseAnimating *pOwner, const char *pModelName, const Vector &position, const QAngle &angles, int collisionGroup ) -{ - CRagdollProp *pRagdoll = (CRagdollProp *)CBaseEntity::CreateNoSpawn( "prop_ragdoll", position, angles, pOwner ); - pRagdoll->SetModelName( AllocPooledString( pModelName ) ); - pRagdoll->SetModel( STRING(pRagdoll->GetModelName()) ); - matrix3x4_t pBoneToWorld[MAXSTUDIOBONES], pBoneToWorldNext[MAXSTUDIOBONES]; - pRagdoll->ResetSequence( 0 ); - - // let bone merging do the work of copying everything over for us - pRagdoll->SetParent( pOwner ); - pRagdoll->SetupBones( pBoneToWorld, BONE_USED_BY_ANYTHING ); - // HACKHACK: don't want this parent anymore - pRagdoll->SetParent( NULL ); - - memcpy( pBoneToWorldNext, pBoneToWorld, sizeof(pBoneToWorld) ); - - pRagdoll->InitRagdoll( vec3_origin, -1, vec3_origin, pBoneToWorld, pBoneToWorldNext, 0.1, collisionGroup, true ); - return pRagdoll; -} - - -CBaseEntity *CreateServerRagdoll( CBaseAnimating *pAnimating, int forceBone, const CTakeDamageInfo &info, int collisionGroup, bool bUseLRURetirement ) -{ - if ( info.GetDamageType() & (DMG_VEHICLE|DMG_CRUSH) ) - { - // if the entity was killed by physics or a vehicle, move to the vphysics shadow position before creating the ragdoll. - SyncAnimatingWithPhysics( pAnimating ); - } - CRagdollProp *pRagdoll = (CRagdollProp *)CBaseEntity::CreateNoSpawn( "prop_ragdoll", pAnimating->GetAbsOrigin(), vec3_angle, NULL ); - pRagdoll->CopyAnimationDataFrom( pAnimating ); - pRagdoll->SetOwnerEntity( pAnimating ); - - pRagdoll->InitRagdollAnimation(); - matrix3x4_t pBoneToWorld[MAXSTUDIOBONES], pBoneToWorldNext[MAXSTUDIOBONES]; - - float dt = 0.1f; - - // Copy over dissolve state... - if ( pAnimating->IsEFlagSet( EFL_NO_DISSOLVE ) ) - { - pRagdoll->AddEFlags( EFL_NO_DISSOLVE ); - } - - // NOTE: This currently is only necessary to prevent manhacks from - // colliding with server ragdolls they kill - pRagdoll->SetKiller( info.GetInflictor() ); - pRagdoll->SetSourceClassName( pAnimating->GetClassname() ); - - // NPC_STATE_DEAD npc's will have their COND_IN_PVS cleared, so this needs to force SetupBones to happen - unsigned short fPrevFlags = pAnimating->GetBoneCacheFlags(); - pAnimating->SetBoneCacheFlags( BCF_NO_ANIMATION_SKIP ); - - // UNDONE: Extract velocity from bones via animation (like we do on the client) - // UNDONE: For now, just move each bone by the total entity velocity if set. - // Get Bones positions before - // Store current cycle - float fSequenceDuration = pAnimating->SequenceDuration( pAnimating->GetSequence() ); - float fSequenceTime = pAnimating->GetCycle() * fSequenceDuration; - - if( fSequenceTime <= dt && fSequenceTime > 0.0f ) - { - // Avoid having negative cycle - dt = fSequenceTime; - } - - float fPreviousCycle = clamp(pAnimating->GetCycle()-( dt * ( 1 / fSequenceDuration ) ),0.f,1.f); - float fCurCycle = pAnimating->GetCycle(); - // Get current bones positions - pAnimating->SetupBones( pBoneToWorldNext, BONE_USED_BY_ANYTHING ); - // Get previous bones positions - pAnimating->SetCycle( fPreviousCycle ); - pAnimating->SetupBones( pBoneToWorld, BONE_USED_BY_ANYTHING ); - // Restore current cycle - pAnimating->SetCycle( fCurCycle ); - - // Reset previous bone flags - pAnimating->ClearBoneCacheFlags( BCF_NO_ANIMATION_SKIP ); - pAnimating->SetBoneCacheFlags( fPrevFlags ); - - Vector vel = pAnimating->GetAbsVelocity(); - if( ( vel.Length() == 0 ) && ( dt > 0 ) ) - { - // Compute animation velocity - CStudioHdr *pstudiohdr = pAnimating->GetModelPtr(); - if ( pstudiohdr ) - { - Vector deltaPos; - QAngle deltaAngles; - if (Studio_SeqMovement( pstudiohdr, - pAnimating->GetSequence(), - fPreviousCycle, - pAnimating->GetCycle(), - pAnimating->GetPoseParameterArray(), - deltaPos, - deltaAngles )) - { - VectorRotate( deltaPos, pAnimating->EntityToWorldTransform(), vel ); - vel /= dt; - } - } - } - - if ( vel.LengthSqr() > 0 ) - { - int numbones = pAnimating->GetModelPtr()->numbones(); - vel *= dt; - for ( int i = 0; i < numbones; i++ ) - { - Vector pos; - MatrixGetColumn( pBoneToWorld[i], 3, pos ); - pos -= vel; - MatrixSetColumn( pos, 3, pBoneToWorld[i] ); - } - } - -#if RAGDOLL_VISUALIZE - pAnimating->DrawRawSkeleton( pBoneToWorld, BONE_USED_BY_ANYTHING, true, 20, false ); - pAnimating->DrawRawSkeleton( pBoneToWorldNext, BONE_USED_BY_ANYTHING, true, 20, true ); -#endif - // Is this a vehicle / NPC collision? - if ( (info.GetDamageType() & DMG_VEHICLE) && pAnimating->MyNPCPointer() ) - { - // init the ragdoll with no forces - pRagdoll->InitRagdoll( vec3_origin, -1, vec3_origin, pBoneToWorld, pBoneToWorldNext, dt, collisionGroup, true ); - - // apply vehicle forces - // Get a list of bones with hitboxes below the plane of impact - int boxList[128]; - Vector normal(0,0,-1); - int count = pAnimating->GetHitboxesFrontside( boxList, ARRAYSIZE(boxList), normal, DotProduct( normal, info.GetDamagePosition() ) ); - - // distribute force over mass of entire character - float massScale = Studio_GetMass(pAnimating->GetModelPtr()); - massScale = clamp( massScale, 1, 1e4 ); - massScale = 1 / massScale; - - // distribute the force - // BUGBUG: This will hit the same bone twice if it has two hitboxes!!!! - ragdoll_t *pRagInfo = pRagdoll->GetRagdoll(); - for ( int i = 0; i < count; i++ ) - { - int physBone = pAnimating->GetPhysicsBone( pAnimating->GetHitboxBone( boxList[i] ) ); - IPhysicsObject *pPhysics = pRagInfo->list[physBone].pObject; - pPhysics->ApplyForceCenter( info.GetDamageForce() * pPhysics->GetMass() * massScale ); - } - } - else - { - pRagdoll->InitRagdoll( info.GetDamageForce(), forceBone, info.GetDamagePosition(), pBoneToWorld, pBoneToWorldNext, dt, collisionGroup, true ); - } - - // Are we dissolving? - if ( pAnimating->IsDissolving() ) - { - pRagdoll->TransferDissolveFrom( pAnimating ); - } - else if ( bUseLRURetirement ) - { - pRagdoll->AddSpawnFlags( SF_RAGDOLLPROP_USE_LRU_RETIREMENT ); - s_RagdollLRU.MoveToTopOfLRU( pRagdoll ); - } - - // Tracker 22598: If we don't set the OBB mins/maxs to something valid here, then the client will have a zero sized hull - // for the ragdoll for one frame until Vphysics updates the real obb bounds after the first simulation frame. Having - // a zero sized hull makes the ragdoll think it should be faded/alpha'd to zero for a frame, so you get a blink where - // the ragdoll doesn't draw initially. - Vector mins, maxs; - mins = pAnimating->CollisionProp()->OBBMins(); - maxs = pAnimating->CollisionProp()->OBBMaxs(); - pRagdoll->CollisionProp()->SetCollisionBounds( mins, maxs ); - - return pRagdoll; -} - -void CRagdollPropAttached::DetachOnNextUpdate() -{ - m_bShouldDetach = true; -} - -void CRagdollPropAttached::VPhysicsUpdate( IPhysicsObject *pPhysics ) -{ - if ( m_bShouldDetach ) - { - Detach(); - m_bShouldDetach = false; - } - BaseClass::VPhysicsUpdate( pPhysics ); -} - -void CRagdollPropAttached::Detach() -{ - SetParent(NULL); - SetOwnerEntity( NULL ); - SetAbsAngles( vec3_angle ); - SetMoveType( MOVETYPE_VPHYSICS ); - RemoveSolidFlags( FSOLID_NOT_SOLID ); - physenv->DestroyConstraint( m_pAttachConstraint ); - m_pAttachConstraint = NULL; - const float dampingScale = 1.0f / ATTACHED_DAMPING_SCALE; - for ( int i = 0; i < m_ragdoll.listCount; i++ ) - { - float damping, rotdamping; - m_ragdoll.list[i].pObject->GetDamping( &damping, &rotdamping ); - damping *= dampingScale; - rotdamping *= dampingScale; - m_ragdoll.list[i].pObject->SetDamping( &damping, &damping ); - } - - // Go non-solid - SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - RecheckCollisionFilter(); -} - -void CRagdollPropAttached::InitRagdollAttached( - IPhysicsObject *pAttached, - const Vector &forceVector, - int forceBone, - matrix3x4_t *pPrevBones, - matrix3x4_t *pBoneToWorld, - float dt, - int collisionGroup, - CBaseAnimating *pFollow, - int boneIndexRoot, - const Vector &boneLocalOrigin, - int parentBoneAttach, - const Vector &worldAttachOrigin ) -{ - int ragdollAttachedIndex = 0; - if ( parentBoneAttach > 0 ) - { - CStudioHdr *pStudioHdr = GetModelPtr(); - mstudiobone_t *pBone = pStudioHdr->pBone( parentBoneAttach ); - ragdollAttachedIndex = pBone->physicsbone; - } - - InitRagdoll( forceVector, forceBone, vec3_origin, pPrevBones, pBoneToWorld, dt, collisionGroup, false ); - - IPhysicsObject *pRefObject = m_ragdoll.list[ragdollAttachedIndex].pObject; - - Vector attachmentPointRagdollSpace; - pRefObject->WorldToLocal( &attachmentPointRagdollSpace, worldAttachOrigin ); - - constraint_ragdollparams_t constraint; - constraint.Defaults(); - matrix3x4_t tmp, worldToAttached, worldToReference, constraintToWorld; - - Vector offsetWS; - pAttached->LocalToWorld( &offsetWS, boneLocalOrigin ); - - QAngle followAng = QAngle(0, pFollow->GetAbsAngles().y, 0 ); - AngleMatrix( followAng, offsetWS, constraintToWorld ); - - constraint.axes[0].SetAxisFriction( -2, 2, 20 ); - constraint.axes[1].SetAxisFriction( 0, 0, 0 ); - constraint.axes[2].SetAxisFriction( -15, 15, 20 ); - - // Exaggerate the bone's ability to pull the mass of the ragdoll around - constraint.constraint.bodyMassScale[1] = 50.0f; - - pAttached->GetPositionMatrix( &tmp ); - MatrixInvert( tmp, worldToAttached ); - - pRefObject->GetPositionMatrix( &tmp ); - MatrixInvert( tmp, worldToReference ); - - ConcatTransforms( worldToReference, constraintToWorld, constraint.constraintToReference ); - ConcatTransforms( worldToAttached, constraintToWorld, constraint.constraintToAttached ); - - // for now, just slam this to be the passed in value - MatrixSetColumn( attachmentPointRagdollSpace, 3, constraint.constraintToReference ); - - PhysDisableEntityCollisions( pAttached, m_ragdoll.list[0].pObject ); - m_pAttachConstraint = physenv->CreateRagdollConstraint( pRefObject, pAttached, m_ragdoll.pGroup, constraint ); - - SetParent( pFollow ); - SetOwnerEntity( pFollow ); - - RagdollActivate( m_ragdoll, modelinfo->GetVCollide( GetModelIndex() ), GetModelIndex() ); - - // add a bunch of dampening to the ragdoll - for ( int i = 0; i < m_ragdoll.listCount; i++ ) - { - float damping, rotdamping; - m_ragdoll.list[i].pObject->GetDamping( &damping, &rotdamping ); - damping *= ATTACHED_DAMPING_SCALE; - rotdamping *= ATTACHED_DAMPING_SCALE; - m_ragdoll.list[i].pObject->SetDamping( &damping, &rotdamping ); - } - - m_boneIndexAttached = boneIndexRoot; - m_ragdollAttachedObjectIndex = ragdollAttachedIndex; - m_attachmentPointBoneSpace = boneLocalOrigin; - - Vector vTemp; - MatrixGetColumn( constraint.constraintToReference, 3, vTemp ); - m_attachmentPointRagdollSpace = vTemp; -} - -CRagdollProp *CreateServerRagdollAttached( CBaseAnimating *pAnimating, const Vector &vecForce, int forceBone, int collisionGroup, IPhysicsObject *pAttached, CBaseAnimating *pParentEntity, int boneAttach, const Vector &originAttached, int parentBoneAttach, const Vector &boneOrigin ) -{ - // Return immediately if the model doesn't have a vcollide - if ( modelinfo->GetVCollide( pAnimating->GetModelIndex() ) == NULL ) - return NULL; - - CRagdollPropAttached *pRagdoll = (CRagdollPropAttached *)CBaseEntity::CreateNoSpawn( "prop_ragdoll_attached", pAnimating->GetAbsOrigin(), vec3_angle, NULL ); - pRagdoll->CopyAnimationDataFrom( pAnimating ); - - pRagdoll->InitRagdollAnimation(); - matrix3x4_t pBoneToWorld[MAXSTUDIOBONES]; - pAnimating->SetupBones( pBoneToWorld, BONE_USED_BY_ANYTHING ); - pRagdoll->InitRagdollAttached( pAttached, vecForce, forceBone, pBoneToWorld, pBoneToWorld, 0.1, collisionGroup, pParentEntity, boneAttach, boneOrigin, parentBoneAttach, originAttached ); - - return pRagdoll; -} - -void DetachAttachedRagdoll( CBaseEntity *pRagdollIn ) -{ - CRagdollPropAttached *pRagdoll = dynamic_cast(pRagdollIn); - - if ( pRagdoll ) - { - pRagdoll->DetachOnNextUpdate(); - } -} - -void DetachAttachedRagdollsForEntity( CBaseEntity *pRagdollParent ) -{ - CUtlVector list; - GetAllChildren( pRagdollParent, list ); - for ( int i = list.Count()-1; i >= 0; --i ) - { - DetachAttachedRagdoll( list[i] ); - } -} - -bool Ragdoll_IsPropRagdoll( CBaseEntity *pEntity ) -{ - if ( dynamic_cast(pEntity) != NULL ) - return true; - return false; -} - -ragdoll_t *Ragdoll_GetRagdoll( CBaseEntity *pEntity ) -{ - CRagdollProp *pProp = dynamic_cast(pEntity); - if ( pProp ) - return pProp->GetRagdoll(); - return NULL; -} - -void CRagdollProp::GetAngleOverrideFromCurrentState( char *pOut, int size ) -{ - pOut[0] = 0; - for ( int i = 0; i < m_ragdoll.listCount; i++ ) - { - if ( i != 0 ) - { - Q_strncat( pOut, ",", size, COPY_ALL_CHARACTERS ); - - } - CFmtStr str("%d,%.2f %.2f %.2f", i, m_ragAngles[i].x, m_ragAngles[i].y, m_ragAngles[i].z ); - Q_strncat( pOut, str, size, COPY_ALL_CHARACTERS ); - } -} - -void CRagdollProp::DisableMotion( void ) -{ - for ( int iRagdoll = 0; iRagdoll < m_ragdoll.listCount; ++iRagdoll ) - { - IPhysicsObject *pPhysicsObject = m_ragdoll.list[ iRagdoll ].pObject; - if ( pPhysicsObject != NULL ) - { - pPhysicsObject->EnableMotion( false ); - } - } -} - -void CRagdollProp::InputStartRadgollBoogie( inputdata_t &inputdata ) -{ - float duration = inputdata.value.Float(); - - if( duration <= 0.0f ) - { - duration = 5.0f; - } - - CRagdollBoogie::Create( this, 100, gpGlobals->curtime, duration, 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: Enable physics motion and collision response (on by default) -//----------------------------------------------------------------------------- -void CRagdollProp::InputEnableMotion( inputdata_t &inputdata ) -{ - for ( int iRagdoll = 0; iRagdoll < m_ragdoll.listCount; ++iRagdoll ) - { - IPhysicsObject *pPhysicsObject = m_ragdoll.list[ iRagdoll ].pObject; - if ( pPhysicsObject != NULL ) - { - pPhysicsObject->EnableMotion( true ); - pPhysicsObject->Wake(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Disable any physics motion or collision response -//----------------------------------------------------------------------------- -void CRagdollProp::InputDisableMotion( inputdata_t &inputdata ) -{ - DisableMotion(); -} - -void CRagdollProp::InputTurnOn( inputdata_t &inputdata ) -{ - RemoveEffects( EF_NODRAW ); -} - -void CRagdollProp::InputTurnOff( inputdata_t &inputdata ) -{ - AddEffects( EF_NODRAW ); -} - -void CRagdollProp::InputFadeAndRemove( inputdata_t &inputdata ) -{ - float flFadeDuration = inputdata.value.Float(); - - if( flFadeDuration == 0.0f ) - flFadeDuration = 1.0f; - - FadeOut( 0.0f, flFadeDuration ); -} - -void Ragdoll_GetAngleOverrideString( char *pOut, int size, CBaseEntity *pEntity ) -{ - CRagdollProp *pRagdoll = dynamic_cast(pEntity); - if ( pRagdoll ) - { - pRagdoll->GetAngleOverrideFromCurrentState( pOut, size ); - } -} diff --git a/game/server/physics_prop_ragdoll.h b/game/server/physics_prop_ragdoll.h deleted file mode 100644 index f083d82b0..000000000 --- a/game/server/physics_prop_ragdoll.h +++ /dev/null @@ -1,162 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef PHYSICS_PROP_RAGDOLL_H -#define PHYSICS_PROP_RAGDOLL_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ragdoll_shared.h" -#include "player_pickup.h" - - -//----------------------------------------------------------------------------- -// Purpose: entity class for simple ragdoll physics -//----------------------------------------------------------------------------- - -// UNDONE: Move this to a private header -class CRagdollProp : public CBaseAnimating, public CDefaultPlayerPickupVPhysics -{ - DECLARE_CLASS( CRagdollProp, CBaseAnimating ); - -public: - CRagdollProp( void ); - ~CRagdollProp( void ); - - virtual void UpdateOnRemove( void ); - - void DrawDebugGeometryOverlays(); - - void Spawn( void ); - void Precache( void ); - - // Disable auto fading under dx7 or when level fades are specified - void DisableAutoFade(); - - int ObjectCaps(); - - DECLARE_SERVERCLASS(); - // Don't treat as a live target - virtual bool IsAlive( void ) { return false; } - - virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &dir, trace_t *ptr ); - virtual bool TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ); - virtual void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ); - virtual void SetupBones( matrix3x4_t *pBoneToWorld, int boneMask ); - virtual void VPhysicsUpdate( IPhysicsObject *pPhysics ); - virtual int VPhysicsGetObjectList( IPhysicsObject **pList, int listMax ); - - virtual int DrawDebugTextOverlays(void); - - // Response system stuff - virtual IResponseSystem *GetResponseSystem(); - virtual void ModifyOrAppendCriteria( AI_CriteriaSet& set ); - void SetSourceClassName( const char *pClassname ); - - // Physics attacker - virtual CBasePlayer *HasPhysicsAttacker( float dt ); - - // locals - void InitRagdollAnimation( void ); - void InitRagdoll( const Vector &forceVector, int forceBone, const Vector &forcePos, matrix3x4_t *pPrevBones, matrix3x4_t *pBoneToWorld, float dt, int collisionGroup, bool activateRagdoll, bool bWakeRagdoll = true ); - - void RecheckCollisionFilter( void ); - void SetDebrisThink(); - void ClearFlagsThink( void ); - inline ragdoll_t *GetRagdoll( void ) { return &m_ragdoll; } - - virtual bool IsRagdoll() { return true; } - - // Damage passing - virtual void SetDamageEntity( CBaseEntity *pEntity ); - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - virtual void OnSave( IEntitySaveUtils *pUtils ); - virtual void OnRestore(); - - // Purpose: CDefaultPlayerPickupVPhysics - virtual void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); - virtual void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ); - virtual void OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ); - virtual AngularImpulse PhysGunLaunchAngularImpulse(); - bool HasPhysgunInteraction( const char *pszKeyName, const char *pszValue ); - void HandleFirstCollisionInteractions( int index, gamevcollisionevent_t *pEvent ); - - void SetUnragdoll( CBaseAnimating *pOther ); - - void SetBlendWeight( float weight ) { m_flBlendWeight = weight; } - void SetOverlaySequence( Activity activity ); - void FadeOut( float flDelay = 0, float fadeTime = -1 ); - bool IsFading(); - CBaseEntity* GetKiller() { return m_hKiller; } - void SetKiller( CBaseEntity *pKiller ) { m_hKiller = pKiller; } - void GetAngleOverrideFromCurrentState( char *pOut, int size ); - - void DisableMotion( void ); - - // Input/Output - void InputStartRadgollBoogie( inputdata_t &inputdata ); - void InputEnableMotion( inputdata_t &inputdata ); - void InputDisableMotion( inputdata_t &inputdata ); - void InputTurnOn( inputdata_t &inputdata ); - void InputTurnOff( inputdata_t &inputdata ); - void InputFadeAndRemove( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - -protected: - void CalcRagdollSize( void ); - ragdoll_t m_ragdoll; - -private: - void UpdateNetworkDataFromVPhysics( IPhysicsObject *pPhysics, int index ); - void FadeOutThink(); - - bool m_bStartDisabled; - - CNetworkArray( Vector, m_ragPos, RAGDOLL_MAX_ELEMENTS ); - CNetworkArray( QAngle, m_ragAngles, RAGDOLL_MAX_ELEMENTS ); - - string_t m_anglesOverrideString; - - typedef CHandle CBaseAnimatingHandle; - CNetworkVar( CBaseAnimatingHandle, m_hUnragdoll ); - - - unsigned int m_lastUpdateTickCount; - bool m_allAsleep; - bool m_bFirstCollisionAfterLaunch; - EHANDLE m_hDamageEntity; - EHANDLE m_hKiller; // Who killed me? - CHandle m_hPhysicsAttacker; - float m_flLastPhysicsInfluenceTime; - float m_flFadeOutStartTime; - float m_flFadeTime; - - - string_t m_strSourceClassName; - bool m_bHasBeenPhysgunned; - - // If not 1, then allow underlying sequence to blend in with simulated bone positions - CNetworkVar( float, m_flBlendWeight ); - CNetworkVar( int, m_nOverlaySequence ); - float m_flDefaultFadeScale; - - Vector m_ragdollMins[RAGDOLL_MAX_ELEMENTS]; - Vector m_ragdollMaxs[RAGDOLL_MAX_ELEMENTS]; -}; - -CBaseEntity *CreateServerRagdoll( CBaseAnimating *pAnimating, int forceBone, const CTakeDamageInfo &info, int collisionGroup, bool bUseLRURetirement = false ); -CRagdollProp *CreateServerRagdollAttached( CBaseAnimating *pAnimating, const Vector &vecForce, int forceBone, int collisionGroup, IPhysicsObject *pAttached, CBaseAnimating *pParentEntity, int boneAttach, const Vector &originAttached, int parentBoneAttach, const Vector &boneOrigin ); -void DetachAttachedRagdoll( CBaseEntity *pRagdollIn ); -void DetachAttachedRagdollsForEntity( CBaseEntity *pRagdollParent ); -CBaseAnimating *CreateServerRagdollSubmodel( CBaseAnimating *pOwner, const char *pModelName, const Vector &position, const QAngle &angles, int collisionGroup ); - -bool Ragdoll_IsPropRagdoll( CBaseEntity *pEntity ); -void Ragdoll_GetAngleOverrideString( char *pOut, int size, CBaseEntity *pEntity ); -ragdoll_t *Ragdoll_GetRagdoll( CBaseEntity *pEntity ); - -#endif // PHYSICS_PROP_RAGDOLL_H diff --git a/game/server/physobj.cpp b/game/server/physobj.cpp deleted file mode 100644 index fd829cf55..000000000 --- a/game/server/physobj.cpp +++ /dev/null @@ -1,2136 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "player.h" -#include "vphysics_interface.h" -#include "physics.h" -#include "vcollide_parse.h" -#include "entitylist.h" -#include "physobj.h" -#include "hierarchy.h" -#include "game.h" -#include "ndebugoverlay.h" -#include "engine/IEngineSound.h" -#include "model_types.h" -#include "props.h" -#include "physics_saverestore.h" -#include "saverestore_utlvector.h" -#include "vphysics/constraints.h" -#include "collisionutils.h" -#include "decals.h" -#include "bone_setup.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar debug_physimpact("debug_physimpact", "0" ); - -const char *GetMassEquivalent(float flMass); - -// This is a physically simulated spring, used to join objects together and create spring forces -// -// NOTE: Springs are not physical in the sense that they only create force, they do not collide with -// anything or have any REAL constraints. They can be stretched infinitely (though this will create -// and infinite force), they can penetrate any other object (or spring). They do not occupy any space. -// - -#define SF_SPRING_ONLYSTRETCH 0x0001 - -class CPhysicsSpring : public CBaseEntity -{ - DECLARE_CLASS( CPhysicsSpring, CBaseEntity ); -public: - CPhysicsSpring(); - ~CPhysicsSpring(); - - void Spawn( void ); - void Activate( void ); - - // Inputs - void InputSetSpringConstant( inputdata_t &inputdata ); - void InputSetSpringDamping( inputdata_t &inputdata ); - void InputSetSpringLength( inputdata_t &inputdata ); - - // Debug - int DrawDebugTextOverlays(void); - void DrawDebugGeometryOverlays(void); - - void GetSpringObjectConnections( string_t nameStart, string_t nameEnd, IPhysicsObject **pStart, IPhysicsObject **pEnd ); - void NotifySystemEvent( CBaseEntity *pNotify, notify_system_event_t eventType, const notify_system_event_params_t ¶ms ); - IPhysicsObject *GetStartObject() { return m_pSpring ? m_pSpring->GetStartObject() : NULL; } - IPhysicsObject *GetEndObject() { return m_pSpring ? m_pSpring->GetEndObject() : NULL; } - - DECLARE_DATADESC(); - -private: - IPhysicsSpring *m_pSpring; - bool m_isLocal; - - // These are "template" values used to construct the spring. After creation, they are not needed - float m_tempConstant; - float m_tempLength; // This is the "ideal" length of the spring, not the length it is currently stretched to. - float m_tempDamping; - float m_tempRelativeDamping; - - string_t m_nameAttachStart; - string_t m_nameAttachEnd; - Vector m_start; - Vector m_end; - unsigned int m_teleportTick; -}; - -LINK_ENTITY_TO_CLASS( phys_spring, CPhysicsSpring ); - -BEGIN_DATADESC( CPhysicsSpring ) - - DEFINE_PHYSPTR( m_pSpring ), - - DEFINE_KEYFIELD( m_tempConstant, FIELD_FLOAT, "constant" ), - DEFINE_KEYFIELD( m_tempLength, FIELD_FLOAT, "length" ), - DEFINE_KEYFIELD( m_tempDamping, FIELD_FLOAT, "damping" ), - DEFINE_KEYFIELD( m_tempRelativeDamping, FIELD_FLOAT, "relativedamping" ), - - DEFINE_KEYFIELD( m_nameAttachStart, FIELD_STRING, "attach1" ), - DEFINE_KEYFIELD( m_nameAttachEnd, FIELD_STRING, "attach2" ), - - DEFINE_FIELD( m_start, FIELD_POSITION_VECTOR ), - DEFINE_KEYFIELD( m_end, FIELD_POSITION_VECTOR, "springaxis" ), - DEFINE_FIELD( m_isLocal, FIELD_BOOLEAN ), - - // Not necessary to save... it's only there to make sure -// DEFINE_FIELD( m_teleportTick, FIELD_INTEGER ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetSpringConstant", InputSetSpringConstant ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetSpringLength", InputSetSpringLength ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetSpringDamping", InputSetSpringDamping ), - -END_DATADESC() - -// debug function - slow, uses dynamic_cast<> - use this to query the attached objects -// physics_debug_entity toggles the constraint system for an object using this -bool GetSpringAttachments( CBaseEntity *pEntity, CBaseEntity *pAttachOut[2], IPhysicsObject *pAttachVPhysics[2] ) -{ - CPhysicsSpring *pSpringEntity = dynamic_cast(pEntity); - if ( pSpringEntity ) - { - IPhysicsObject *pRef = pSpringEntity->GetStartObject(); - pAttachOut[0] = pRef ? static_cast(pRef->GetGameData()) : NULL; - pAttachVPhysics[0] = pRef; - IPhysicsObject *pAttach = pSpringEntity->GetEndObject(); - pAttachOut[1] = pAttach ? static_cast(pAttach->GetGameData()) : NULL; - pAttachVPhysics[1] = pAttach; - return true; - } - return false; -} - - -CPhysicsSpring::CPhysicsSpring( void ) -{ -#ifdef _DEBUG - m_start.Init(); - m_end.Init(); -#endif - m_pSpring = NULL; - m_tempConstant = 150; - m_tempLength = 0; - m_tempDamping = 2.0; - m_tempRelativeDamping = 0.01; - m_isLocal = false; - m_teleportTick = 0xFFFFFFFF; -} - -CPhysicsSpring::~CPhysicsSpring( void ) -{ - if ( m_pSpring ) - { - physenv->DestroySpring( m_pSpring ); - } -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CPhysicsSpring::InputSetSpringConstant( inputdata_t &inputdata ) -{ - m_tempConstant = inputdata.value.Float(); - m_pSpring->SetSpringConstant(inputdata.value.Float()); -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CPhysicsSpring::InputSetSpringDamping( inputdata_t &inputdata ) -{ - m_tempDamping = inputdata.value.Float(); - m_pSpring->SetSpringDamping(inputdata.value.Float()); -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CPhysicsSpring::InputSetSpringLength( inputdata_t &inputdata ) -{ - m_tempLength = inputdata.value.Float(); - m_pSpring->SetSpringLength(inputdata.value.Float()); -} - - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CPhysicsSpring::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - Q_snprintf(tempstr,sizeof(tempstr),"Constant: %3.2f",m_tempConstant); - EntityText(text_offset,tempstr,0); - text_offset++; - - Q_snprintf(tempstr,sizeof(tempstr),"Length: %3.2f",m_tempLength); - EntityText(text_offset,tempstr,0); - text_offset++; - - Q_snprintf(tempstr,sizeof(tempstr),"Damping: %3.2f",m_tempDamping); - EntityText(text_offset,tempstr,0); - text_offset++; - - } - return text_offset; -} - -//----------------------------------------------------------------------------- -// Purpose: Override base class to add display of fly direction -// Input : -// Output : -//----------------------------------------------------------------------------- -void CPhysicsSpring::DrawDebugGeometryOverlays(void) -{ - if ( !m_pSpring ) - return; - - // ------------------------------ - // Draw if BBOX is on - // ------------------------------ - if (m_debugOverlays & OVERLAY_BBOX_BIT) - { - Vector vStartPos; - Vector vEndPos; - m_pSpring->GetEndpoints( &vStartPos, &vEndPos ); - - Vector vSpringDir = vEndPos - vStartPos; - VectorNormalize(vSpringDir); - - Vector vLength = vStartPos + (vSpringDir*m_tempLength); - - NDebugOverlay::Line(vStartPos, vLength, 0,0,255, false, 0); - NDebugOverlay::Line(vLength, vEndPos, 255,0,0, false, 0); - } - BaseClass::DrawDebugGeometryOverlays(); -} - -bool PointIsNearer( IPhysicsObject *pObject1, const Vector &point1, const Vector &point2 ) -{ - Vector center; - - pObject1->GetPosition( ¢er, 0 ); - - float dist1 = (center - point1).LengthSqr(); - float dist2 = (center - point2).LengthSqr(); - - if ( dist1 < dist2 ) - return true; - - return false; -} - -void CPhysicsSpring::GetSpringObjectConnections( string_t nameStart, string_t nameEnd, IPhysicsObject **pStart, IPhysicsObject **pEnd ) -{ - IPhysicsObject *pStartObject = FindPhysicsObjectByName( STRING(nameStart), this ); - IPhysicsObject *pEndObject = FindPhysicsObjectByName( STRING(nameEnd), this ); - - // Assume the world for missing objects - if ( !pStartObject ) - { - pStartObject = g_PhysWorldObject; - } - else if ( !pEndObject ) - { - // try to sort so that the world is always the start object - pEndObject = pStartObject; - pStartObject = g_PhysWorldObject; - } - else - { - CBaseEntity *pEntity0 = (CBaseEntity *) (pStartObject->GetGameData()); - if ( pEntity0 ) - { - g_pNotify->AddEntity( this, pEntity0 ); - } - - CBaseEntity *pEntity1 = (CBaseEntity *) pEndObject->GetGameData(); - if ( pEntity1 ) - { - g_pNotify->AddEntity( this, pEntity1 ); - } - } - - *pStart = pStartObject; - *pEnd = pEndObject; -} - - -void CPhysicsSpring::Activate( void ) -{ - BaseClass::Activate(); - - // UNDONE: save/restore all data, and only create the spring here - - if ( !m_pSpring ) - { - IPhysicsObject *pStart, *pEnd; - - GetSpringObjectConnections( m_nameAttachStart, m_nameAttachEnd, &pStart, &pEnd ); - - // Needs to connect to real, different objects - if ( (!pStart || !pEnd) || (pStart == pEnd) ) - { - DevMsg("ERROR: Can't init spring %s from \"%s\" to \"%s\"\n", GetDebugName(), STRING(m_nameAttachStart), STRING(m_nameAttachEnd) ); - UTIL_Remove( this ); - return; - } - - // if m_end is not closer to pEnd than m_start, swap - if ( !PointIsNearer( pEnd, m_end, m_start ) ) - { - Vector tmpVec = m_start; - m_start = m_end; - m_end = tmpVec; - } - - // create the spring - springparams_t spring; - spring.constant = m_tempConstant; - spring.damping = m_tempDamping; - spring.naturalLength = m_tempLength; - spring.relativeDamping = m_tempRelativeDamping; - spring.startPosition = m_start; - spring.endPosition = m_end; - spring.useLocalPositions = false; - spring.onlyStretch = HasSpawnFlags( SF_SPRING_ONLYSTRETCH ); - m_pSpring = physenv->CreateSpring( pStart, pEnd, &spring ); - } -} - - -void CPhysicsSpring::Spawn( void ) -{ - SetSolid( SOLID_NONE ); - m_start = GetAbsOrigin(); - if ( m_tempLength <= 0 ) - { - m_tempLength = (m_end - m_start).Length(); - } -} - -void CPhysicsSpring::NotifySystemEvent( CBaseEntity *pNotify, notify_system_event_t eventType, const notify_system_event_params_t ¶ms ) -{ - // don't recurse - if ( eventType != NOTIFY_EVENT_TELEPORT || (unsigned int)gpGlobals->tickcount == m_teleportTick ) - return; - - m_teleportTick = gpGlobals->tickcount; - PhysTeleportConstrainedEntity( pNotify, m_pSpring->GetStartObject(), m_pSpring->GetEndObject(), params.pTeleport->prevOrigin, params.pTeleport->prevAngles, params.pTeleport->physicsRotate ); -} - - -// --------------------------------------------------------------------- -// -// CPhysBox -- physically simulated brush -// -// --------------------------------------------------------------------- - -// SendTable stuff. -IMPLEMENT_SERVERCLASS_ST(CPhysBox, DT_PhysBox) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( func_physbox, CPhysBox ); - -BEGIN_DATADESC( CPhysBox ) - - DEFINE_FIELD( m_hCarryingPlayer, FIELD_EHANDLE ), - - DEFINE_KEYFIELD( m_massScale, FIELD_FLOAT, "massScale" ), - DEFINE_KEYFIELD( m_damageType, FIELD_INTEGER, "Damagetype" ), - DEFINE_KEYFIELD( m_iszOverrideScript, FIELD_STRING, "overridescript" ), - DEFINE_KEYFIELD( m_damageToEnableMotion, FIELD_INTEGER, "damagetoenablemotion" ), - DEFINE_KEYFIELD( m_flForceToEnableMotion, FIELD_FLOAT, "forcetoenablemotion" ), - DEFINE_KEYFIELD( m_angPreferredCarryAngles, FIELD_VECTOR, "preferredcarryangles" ), - DEFINE_KEYFIELD( m_bNotSolidToWorld, FIELD_BOOLEAN, "notsolid" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Wake", InputWake ), - DEFINE_INPUTFUNC( FIELD_VOID, "Sleep", InputSleep ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableMotion", InputEnableMotion ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableMotion", InputDisableMotion ), - DEFINE_INPUTFUNC( FIELD_VOID, "ForceDrop", InputForceDrop ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableFloating", InputDisableFloating ), - - // Function pointers - DEFINE_ENTITYFUNC( BreakTouch ), - - // Outputs - DEFINE_OUTPUT( m_OnDamaged, "OnDamaged" ), - DEFINE_OUTPUT( m_OnAwakened, "OnAwakened" ), - DEFINE_OUTPUT( m_OnMotionEnabled, "OnMotionEnabled" ), - DEFINE_OUTPUT( m_OnPhysGunPickup, "OnPhysGunPickup" ), - DEFINE_OUTPUT( m_OnPhysGunPunt, "OnPhysGunPunt" ), - DEFINE_OUTPUT( m_OnPhysGunOnlyPickup, "OnPhysGunOnlyPickup" ), - DEFINE_OUTPUT( m_OnPhysGunDrop, "OnPhysGunDrop" ), - DEFINE_OUTPUT( m_OnPlayerUse, "OnPlayerUse" ), - -END_DATADESC() - -// UNDONE: Save/Restore needs to take the physics object's properties into account -// UNDONE: Acceleration, velocity, angular velocity, etc. must be preserved -// UNDONE: Many of these quantities are relative to a coordinate frame -// UNDONE: Translate when going across transitions? -// UNDONE: Build transition transformation, and transform data in save/restore for IPhysicsObject -// UNDONE: Angles are saved in the entity, but not propagated back to the IPhysicsObject on restore - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysBox::Spawn( void ) -{ - // Initialize damage modifiers. Must be done before baseclass spawn. - m_flDmgModBullet = func_breakdmg_bullet.GetFloat(); - m_flDmgModClub = func_breakdmg_club.GetFloat(); - m_flDmgModExplosive = func_breakdmg_explosive.GetFloat(); - - ParsePropData(); - - Precache(); - - m_iMaxHealth = ( m_iHealth > 0 ) ? m_iHealth : 1; - - if ( HasSpawnFlags( SF_BREAK_TRIGGER_ONLY ) ) - { - m_takedamage = DAMAGE_EVENTS_ONLY; - AddSpawnFlags( SF_BREAK_DONT_TAKE_PHYSICS_DAMAGE ); - } - else if ( m_iHealth == 0 ) - { - m_takedamage = DAMAGE_EVENTS_ONLY; - AddSpawnFlags( SF_BREAK_DONT_TAKE_PHYSICS_DAMAGE ); - } - else - { - m_takedamage = DAMAGE_YES; - } - - SetMoveType( MOVETYPE_NONE ); - SetAbsVelocity( vec3_origin ); - SetModel( STRING( GetModelName() ) ); - SetSolid( SOLID_VPHYSICS ); - if ( HasSpawnFlags( SF_PHYSBOX_DEBRIS ) ) - { - SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - } - - if ( HasSpawnFlags( SF_PHYSBOX_NO_ROTORWASH_PUSH ) ) - { - AddEFlags( EFL_NO_ROTORWASH_PUSH ); - } - - if ( m_bNotSolidToWorld ) - { - AddSolidFlags( FSOLID_NOT_SOLID ); - } - CreateVPhysics(); - - m_hCarryingPlayer = NULL; - - SetTouch( &CPhysBox::BreakTouch ); - if ( HasSpawnFlags( SF_BREAK_TRIGGER_ONLY ) ) // Only break on trigger - { - SetTouch( NULL ); - } - - if ( m_impactEnergyScale == 0 ) - { - m_impactEnergyScale = 1.0; - } -} - -// shared from studiomdl, checks for long, thin objects and adds some damping -// to prevent endless rolling due to low inertia -static bool ShouldDampRotation( const CPhysCollide *pCollide ) -{ - Vector mins, maxs; - physcollision->CollideGetAABB( &mins, &maxs, pCollide, vec3_origin, vec3_angle ); - Vector size = maxs-mins; - int largest = 0; - float largeSize = size[0]; - for ( int i = 1; i < 3; i++ ) - { - if ( size[i] > largeSize ) - { - largeSize = size[i]; - largest = i; - } - } - size[largest] = 0; - float len = size.Length(); - if ( len > 0 ) - { - float sizeRatio = largeSize / len; - // HACKHACK: Hardcoded size ratio to induce damping - // This prevents long skinny objects from rolling endlessly - if ( sizeRatio > 9 ) - return true; - } - return false; -} - - -bool CPhysBox::CreateVPhysics() -{ - solid_t tmpSolid; - PhysModelParseSolid( tmpSolid, this, GetModelIndex() ); - if ( m_massScale > 0 ) - { - tmpSolid.params.mass *= m_massScale; - } - - vcollide_t *pVCollide = modelinfo->GetVCollide( GetModelIndex() ); - PhysGetMassCenterOverride( this, pVCollide, tmpSolid ); - PhysSolidOverride( tmpSolid, m_iszOverrideScript ); - if ( tmpSolid.params.rotdamping < 1.0f && ShouldDampRotation(pVCollide->solids[0]) ) - { - tmpSolid.params.rotdamping = 1.0f; - } - IPhysicsObject *pPhysics = VPhysicsInitNormal( GetSolid(), GetSolidFlags(), true, &tmpSolid ); - - if ( m_damageType == 1 ) - { - PhysSetGameFlags( pPhysics, FVPHYSICS_DMG_SLICE ); - } - - // Wake it up if not asleep - if ( !HasSpawnFlags(SF_PHYSBOX_ASLEEP) ) - { - pPhysics->Wake(); - } - - if ( HasSpawnFlags(SF_PHYSBOX_MOTIONDISABLED) || m_damageToEnableMotion > 0 || m_flForceToEnableMotion > 0 ) - { - pPhysics->EnableMotion( false ); - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CPhysBox::ObjectCaps() -{ - int caps = BaseClass::ObjectCaps() | FCAP_WCEDIT_POSITION; - if ( HasSpawnFlags( SF_PHYSBOX_ENABLE_PICKUP_OUTPUT ) ) - { - caps |= FCAP_IMPULSE_USE; - } - else if ( !HasSpawnFlags( SF_PHYSBOX_IGNOREUSE ) ) - { - if ( CBasePlayer::CanPickupObject( this, 35, 128 ) ) - { - caps |= FCAP_IMPULSE_USE; - } - } - - return caps; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysBox::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - CBasePlayer *pPlayer = ToBasePlayer( pActivator ); - if ( pPlayer ) - { - if ( HasSpawnFlags( SF_PHYSBOX_ENABLE_PICKUP_OUTPUT ) ) - { - m_OnPlayerUse.FireOutput( this, this ); - } - - if ( !HasSpawnFlags( SF_PHYSBOX_IGNOREUSE ) ) - { - pPlayer->PickupObject( this ); - } - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CPhysBox::CanBePickedUpByPhyscannon() -{ - if ( HasSpawnFlags( SF_PHYSBOX_NEVER_PICK_UP ) ) - return false; - - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - if ( !pPhysicsObject ) - return false; - - if ( !pPhysicsObject->IsMotionEnabled() && !HasSpawnFlags( SF_PHYSBOX_ENABLE_ON_PHYSCANNON ) ) - return false; - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CPhysBox::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - if (VPhysicsGetObject()) - { - char tempstr[512]; - Q_snprintf(tempstr, sizeof(tempstr),"Mass: %.2f kg / %.2f lb (%s)", VPhysicsGetObject()->GetMass(), kg2lbs(VPhysicsGetObject()->GetMass()), GetMassEquivalent(VPhysicsGetObject()->GetMass())); - EntityText( text_offset, tempstr, 0); - text_offset++; - } - } - - return text_offset; -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that breaks the physics object away from its parent -// and starts it simulating. -//----------------------------------------------------------------------------- -void CPhysBox::InputWake( inputdata_t &inputdata ) -{ - VPhysicsGetObject()->Wake(); -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler that breaks the physics object away from its parent -// and stops it simulating. -//----------------------------------------------------------------------------- -void CPhysBox::InputSleep( inputdata_t &inputdata ) -{ - VPhysicsGetObject()->Sleep(); -} - -//----------------------------------------------------------------------------- -// Purpose: Enable physics motion and collision response (on by default) -//----------------------------------------------------------------------------- -void CPhysBox::InputEnableMotion( inputdata_t &inputdata ) -{ - EnableMotion(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysBox::EnableMotion( void ) -{ - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - if ( pPhysicsObject != NULL ) - { - pPhysicsObject->EnableMotion( true ); - pPhysicsObject->Wake(); - } - - m_damageToEnableMotion = 0; - m_flForceToEnableMotion = 0; - - m_OnMotionEnabled.FireOutput( this, this, 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: Disable any physics motion or collision response -//----------------------------------------------------------------------------- -void CPhysBox::InputDisableMotion( inputdata_t &inputdata ) -{ - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - if ( pPhysicsObject != NULL ) - { - pPhysicsObject->EnableMotion( false ); - } -} - -// Turn off floating simulation (and cost) -void CPhysBox::InputDisableFloating( inputdata_t &inputdata ) -{ - PhysEnableFloating( VPhysicsGetObject(), false ); -} - -//----------------------------------------------------------------------------- -// Purpose: If we're being held by the player's hand/physgun, force it to drop us -//----------------------------------------------------------------------------- -void CPhysBox::InputForceDrop( inputdata_t &inputdata ) -{ - if ( m_hCarryingPlayer ) - { - m_hCarryingPlayer->ForceDropOfCarriedPhysObjects(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysBox::Move( const Vector &direction ) -{ - VPhysicsGetObject()->ApplyForceCenter( direction ); -} - -// Update the visible representation of the physic system's representation of this object -void CPhysBox::VPhysicsUpdate( IPhysicsObject *pPhysics ) -{ - BaseClass::VPhysicsUpdate( pPhysics ); - - // if this is the first time we have moved, fire our target - if ( HasSpawnFlags( SF_PHYSBOX_ASLEEP ) ) - { - if ( !pPhysics->IsAsleep() ) - { - m_OnAwakened.FireOutput(this, this); - FireTargets( STRING(m_target), this, this, USE_TOGGLE, 0 ); - RemoveSpawnFlags( SF_PHYSBOX_ASLEEP ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysBox::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) -{ - if ( reason == PUNTED_BY_CANNON ) - { - m_OnPhysGunPunt.FireOutput( pPhysGunUser, this ); - } - - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - if ( pPhysicsObject && !pPhysicsObject->IsMoveable() ) - { - if ( !HasSpawnFlags( SF_PHYSBOX_ENABLE_ON_PHYSCANNON ) ) - return; - EnableMotion(); - } - - m_OnPhysGunPickup.FireOutput( pPhysGunUser, this ); - - // Are we just being punted? - if ( reason == PUNTED_BY_CANNON ) - return; - - if( reason == PICKED_UP_BY_CANNON ) - { - m_OnPhysGunOnlyPickup.FireOutput( pPhysGunUser, this ); - } - - m_hCarryingPlayer = pPhysGunUser; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysBox::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ) -{ - BaseClass::OnPhysGunDrop( pPhysGunUser, Reason ); - - m_hCarryingPlayer = NULL; - m_OnPhysGunDrop.FireOutput( pPhysGunUser, this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysBox::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) -{ - BaseClass::VPhysicsCollision( index, pEvent ); - - IPhysicsObject *pPhysObj = pEvent->pObjects[!index]; - - // If we have a force to enable motion, and we're still disabled, check to see if this should enable us - if ( m_flForceToEnableMotion ) - { - CBaseEntity *pOther = static_cast(pPhysObj->GetGameData()); - - // Don't allow the player to bump an object active if we've requested not to - if ( ( pOther && pOther->IsPlayer() && HasSpawnFlags( SF_PHYSBOX_PREVENT_PLAYER_TOUCH_ENABLE ) ) == false ) - { - // Large enough to enable motion? - float flForce = pEvent->collisionSpeed * pEvent->pObjects[!index]->GetMass(); - if ( flForce >= m_flForceToEnableMotion ) - { - EnableMotion(); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CPhysBox::OnTakeDamage( const CTakeDamageInfo &info ) -{ - if ( IsMarkedForDeletion() ) - return 0; - - // note: if motion is disabled, OnTakeDamage can't apply physics force - int ret = BaseClass::OnTakeDamage( info ); - - if ( info.GetInflictor() ) - { - m_OnDamaged.FireOutput( info.GetAttacker(), this ); - } - - // Have we been broken? If so, abort - if ( GetHealth() <= 0 ) - return ret; - - // If we have a force to enable motion, and we're still disabled, check to see if this should enable us - if ( m_flForceToEnableMotion ) - { - // Large enough to enable motion? - float flForce = info.GetDamageForce().Length(); - if ( flForce >= m_flForceToEnableMotion ) - { - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - if ( pPhysicsObject ) - { - EnableMotion(); - } - } - } - - // Check our health against the threshold: - if( m_damageToEnableMotion > 0 && GetHealth() < m_damageToEnableMotion ) - { - EnableMotion(); - VPhysicsTakeDamage( info ); - } - - return ret; -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if this physbox has preferred carry angles -//----------------------------------------------------------------------------- -bool CPhysBox::HasPreferredCarryAnglesForPlayer( CBasePlayer *pPlayer ) -{ - return HasSpawnFlags( SF_PHYSBOX_USEPREFERRED ); -} - - -// --------------------------------------------------------------------- -// -// CPhysExplosion -- physically simulated explosion -// -// --------------------------------------------------------------------- -#define SF_PHYSEXPLOSION_NODAMAGE 0x0001 -#define SF_PHYSEXPLOSION_PUSH_PLAYER 0x0002 -#define SF_PHYSEXPLOSION_RADIAL 0x0004 -#define SF_PHYSEXPLOSION_TEST_LOS 0x0008 -#define SF_PHYSEXPLOSION_DISORIENT_PLAYER 0x0010 - -LINK_ENTITY_TO_CLASS( env_physexplosion, CPhysExplosion ); - -BEGIN_DATADESC( CPhysExplosion ) - - DEFINE_KEYFIELD( m_damage, FIELD_FLOAT, "magnitude" ), - DEFINE_KEYFIELD( m_radius, FIELD_FLOAT, "radius" ), - DEFINE_KEYFIELD( m_targetEntityName, FIELD_STRING, "targetentityname" ), - DEFINE_KEYFIELD( m_flInnerRadius, FIELD_FLOAT, "inner_radius" ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Explode", InputExplode ), - - // Outputs - DEFINE_OUTPUT( m_OnPushedPlayer, "OnPushedPlayer" ), - -END_DATADESC() - - -void CPhysExplosion::Spawn( void ) -{ - SetMoveType( MOVETYPE_NONE ); - SetSolid( SOLID_NONE ); - SetModelName( NULL_STRING ); -} - -float CPhysExplosion::GetRadius( void ) -{ - float radius = m_radius; - if ( radius <= 0 ) - { - // Use the same radius as combat - radius = m_damage * 2.5; - } - - return radius; -} - -CBaseEntity *CPhysExplosion::FindEntity( CBaseEntity *pEntity, CBaseEntity *pActivator, CBaseEntity *pCaller ) -{ - // Filter by name or classname - if ( m_targetEntityName != NULL_STRING ) - { - // Try an explicit name first - CBaseEntity *pTarget = gEntList.FindEntityByName( pEntity, m_targetEntityName, NULL, pActivator, pCaller ); - if ( pTarget != NULL ) - return pTarget; - - // Failing that, try a classname - return gEntList.FindEntityByClassnameWithin( pEntity, STRING(m_targetEntityName), GetAbsOrigin(), GetRadius() ); - } - - // Just find anything in the radius - return gEntList.FindEntityInSphere( pEntity, GetAbsOrigin(), GetRadius() ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysExplosion::InputExplode( inputdata_t &inputdata ) -{ - Explode( inputdata.pActivator, inputdata.pCaller ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysExplosion::Explode( CBaseEntity *pActivator, CBaseEntity *pCaller ) -{ - CBaseEntity *pEntity = NULL; - float adjustedDamage, falloff, flDist; - Vector vecSpot, vecOrigin; - - falloff = 1.0 / 2.5; - - // iterate on all entities in the vicinity. - // I've removed the traceline heuristic from phys explosions. SO right now they will - // affect entities through walls. (sjb) - // UNDONE: Try tracing world-only? - while ((pEntity = FindEntity( pEntity, pActivator, pCaller )) != NULL) - { - // UNDONE: Ask the object if it should get force if it's not MOVETYPE_VPHYSICS? - if ( pEntity->m_takedamage != DAMAGE_NO && (pEntity->GetMoveType() == MOVETYPE_VPHYSICS || (pEntity->VPhysicsGetObject() /*&& !pEntity->IsPlayer()*/)) ) - { - vecOrigin = GetAbsOrigin(); - - vecSpot = pEntity->BodyTarget( vecOrigin ); - // Squash this down to a circle - if ( HasSpawnFlags( SF_PHYSEXPLOSION_RADIAL ) ) - { - vecOrigin[2] = vecSpot[2]; - } - - // decrease damage for an ent that's farther from the bomb. - flDist = ( vecOrigin - vecSpot ).Length(); - - if( m_radius == 0 || flDist <= m_radius ) - { - if ( HasSpawnFlags( SF_PHYSEXPLOSION_TEST_LOS ) ) - { - Vector vecStartPos = GetAbsOrigin(); - Vector vecEndPos = pEntity->BodyTarget( vecStartPos, false ); - - if ( m_flInnerRadius != 0.0f ) - { - // Find a point on our inner radius sphere to begin from - Vector vecDirToTarget = ( vecEndPos - vecStartPos ); - VectorNormalize( vecDirToTarget ); - vecStartPos = GetAbsOrigin() + ( vecDirToTarget * m_flInnerRadius ); - } - - trace_t tr; - UTIL_TraceLine( vecStartPos, - pEntity->BodyTarget( vecStartPos, false ), - MASK_SOLID_BRUSHONLY, - this, - COLLISION_GROUP_NONE, - &tr ); - - // Shielded - if ( tr.fraction < 1.0f && tr.m_pEnt != pEntity ) - continue; - } - - adjustedDamage = flDist * falloff; - adjustedDamage = m_damage - adjustedDamage; - - if ( adjustedDamage < 1 ) - { - adjustedDamage = 1; - } - - CTakeDamageInfo info( this, this, adjustedDamage, DMG_BLAST ); - CalculateExplosiveDamageForce( &info, (vecSpot - vecOrigin), vecOrigin ); - - if ( HasSpawnFlags( SF_PHYSEXPLOSION_PUSH_PLAYER ) ) - { - if ( pEntity->IsPlayer() ) - { - Vector vecPushDir = ( pEntity->BodyTarget( GetAbsOrigin(), false ) - GetAbsOrigin() ); - float dist = VectorNormalize( vecPushDir ); - - float flFalloff = RemapValClamped( dist, m_radius, m_radius*0.75f, 0.0f, 1.0f ); - - if ( HasSpawnFlags( SF_PHYSEXPLOSION_DISORIENT_PLAYER ) ) - { - //Disorient the player - QAngle vecDeltaAngles; - - vecDeltaAngles.x = random->RandomInt( -30, 30 ); - vecDeltaAngles.y = random->RandomInt( -30, 30 ); - vecDeltaAngles.z = 0.0f; - - CBasePlayer *pPlayer = ToBasePlayer( pEntity ); - pPlayer->SnapEyeAngles( GetLocalAngles() + vecDeltaAngles ); - pEntity->ViewPunch( vecDeltaAngles ); - } - - Vector vecPush = (vecPushDir*m_damage*flFalloff*2.0f); - if ( pEntity->GetFlags() & FL_BASEVELOCITY ) - { - vecPush = vecPush + pEntity->GetBaseVelocity(); - } - if ( vecPush.z > 0 && (pEntity->GetFlags() & FL_ONGROUND) ) - { - pEntity->SetGroundEntity( NULL ); - Vector origin = pEntity->GetAbsOrigin(); - origin.z += 1.0f; - pEntity->SetAbsOrigin( origin ); - } - - pEntity->SetBaseVelocity( vecPush ); - pEntity->AddFlag( FL_BASEVELOCITY ); - - // Fire an output that the player has been pushed - m_OnPushedPlayer.FireOutput( this, this ); - continue; - } - } - - if ( HasSpawnFlags( SF_PHYSEXPLOSION_NODAMAGE ) ) - { - pEntity->VPhysicsTakeDamage( info ); - } - else - { - pEntity->TakeDamage( info ); - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CPhysExplosion::DrawDebugTextOverlays( void ) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - - // print magnitude - Q_snprintf(tempstr,sizeof(tempstr)," magnitude: %f", m_damage); - EntityText(text_offset,tempstr,0); - text_offset++; - - // print target entity - Q_snprintf(tempstr,sizeof(tempstr)," limit to: %s", STRING(m_targetEntityName)); - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} - - -//================================================== -// CPhysImpact -//================================================== - -#define bitsPHYSIMPACT_NOFALLOFF 0x00000001 -#define bitsPHYSIMPACT_INFINITE_LENGTH 0x00000002 -#define bitsPHYSIMPACT_IGNORE_MASS 0x00000004 -#define bitsPHYSIMPACT_IGNORE_NORMAL 0x00000008 - -#define DEFAULT_EXPLODE_DISTANCE 256 -LINK_ENTITY_TO_CLASS( env_physimpact, CPhysImpact ); - -BEGIN_DATADESC( CPhysImpact ) - - DEFINE_KEYFIELD( m_damage, FIELD_FLOAT, "magnitude" ), - DEFINE_KEYFIELD( m_distance, FIELD_FLOAT, "distance" ), - DEFINE_KEYFIELD( m_directionEntityName,FIELD_STRING, "directionentityname" ), - - // Function pointers - DEFINE_FUNCTION( PointAtEntity ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Impact", InputImpact ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysImpact::Activate( void ) -{ - BaseClass::Activate(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysImpact::Spawn( void ) -{ - SetMoveType( MOVETYPE_NONE ); - SetSolid( SOLID_NONE ); - SetModelName( NULL_STRING ); - - //If not targetted, and no distance is set, give it a default value - if ( m_distance == 0 ) - { - m_distance = DEFAULT_EXPLODE_DISTANCE; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysImpact::PointAtEntity( void ) -{ - //If we're not targetted at anything, don't bother - if ( m_directionEntityName == NULL_STRING ) - return; - - UTIL_PointAtNamedEntity( this, m_directionEntityName ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pActivator - -// *pCaller - -// useType - -// value - -//----------------------------------------------------------------------------- -void CPhysImpact::InputImpact( inputdata_t &inputdata ) -{ - Vector dir; - trace_t trace; - - //If we have a direction target, setup to point at it - if ( m_directionEntityName != NULL_STRING ) - { - PointAtEntity(); - } - - AngleVectors( GetAbsAngles(), &dir ); - - //Setup our trace information - float dist = HasSpawnFlags( bitsPHYSIMPACT_INFINITE_LENGTH ) ? MAX_TRACE_LENGTH : m_distance; - Vector start = GetAbsOrigin(); - Vector end = start + ( dir * dist ); - - //Trace out - UTIL_TraceLine( start, end, MASK_SHOT, this, 0, &trace ); - - if( debug_physimpact.GetBool() ) - { - NDebugOverlay::Cross3D( start, 24, 255, 255, 255, false, 30 ); - NDebugOverlay::Line( trace.startpos, trace.endpos, 0, 255, 0, false, 30 ); - } - - if ( trace.fraction != 1.0 ) - { - // if inside the object, just go opposite the direction - if ( trace.startsolid ) - { - trace.plane.normal = -dir; - } - CBaseEntity *pEnt = trace.m_pEnt; - - IPhysicsObject *pPhysics = pEnt->VPhysicsGetObject(); - //If the entity is valid, hit it - if ( ( pEnt != NULL ) && ( pPhysics != NULL ) ) - { - CTakeDamageInfo info; - info.SetAttacker( this); - info.SetInflictor( this ); - info.SetDamage( 0 ); - info.SetDamageForce( vec3_origin ); - info.SetDamageType( DMG_GENERIC ); - - pEnt->DispatchTraceAttack( info, dir, &trace ); - ApplyMultiDamage(); - - //Damage falls off unless specified or the ray's length is infinite - float damage = HasSpawnFlags( bitsPHYSIMPACT_NOFALLOFF | bitsPHYSIMPACT_INFINITE_LENGTH ) ? - m_damage : (m_damage * (1.0f-trace.fraction)); - - if ( HasSpawnFlags( bitsPHYSIMPACT_IGNORE_MASS ) ) - { - damage *= pPhysics->GetMass(); - } - - if( debug_physimpact.GetBool() ) - { - NDebugOverlay::Line( trace.endpos, trace.endpos + trace.plane.normal * -128, 255, 0, 0, false, 30 ); - } - - // Legacy entities applied the force along the impact normal, which yielded unpredictable results. - if ( !HasSpawnFlags( bitsPHYSIMPACT_IGNORE_NORMAL ) ) - { - dir = -trace.plane.normal; - } - - pPhysics->ApplyForceOffset( damage * dir * phys_pushscale.GetFloat(), trace.endpos ); - } - } -} - - -class CSimplePhysicsBrush : public CBaseEntity -{ - DECLARE_CLASS( CSimplePhysicsBrush, CBaseEntity ); -public: - void Spawn() - { - SetModel( STRING( GetModelName() ) ); - SetMoveType( MOVETYPE_VPHYSICS ); - SetSolid( SOLID_VPHYSICS ); - m_takedamage = DAMAGE_EVENTS_ONLY; - } -}; - -LINK_ENTITY_TO_CLASS( simple_physics_brush, CSimplePhysicsBrush ); - -class CSimplePhysicsProp : public CBaseProp -{ - DECLARE_CLASS( CSimplePhysicsProp, CBaseProp ); - -public: - void Spawn() - { - BaseClass::Spawn(); - SetMoveType( MOVETYPE_VPHYSICS ); - SetSolid( SOLID_VPHYSICS ); - m_takedamage = DAMAGE_EVENTS_ONLY; - } - - int ObjectCaps() - { - int caps = BaseClass::ObjectCaps() | FCAP_WCEDIT_POSITION; - - if ( CBasePlayer::CanPickupObject( this, 35, 128 ) ) - { - caps |= FCAP_IMPULSE_USE; - } - - return caps; - } - - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) - { - CBasePlayer *pPlayer = ToBasePlayer( pActivator ); - if ( pPlayer ) - { - pPlayer->PickupObject( this ); - } - } -}; - -LINK_ENTITY_TO_CLASS( simple_physics_prop, CSimplePhysicsProp ); - -// UNDONE: Is this worth it?, just recreate the object instead? (that happens when this returns false anyway) -// recreating works, but is more expensive and won't inherit properties (velocity, constraints, etc) -bool TransferPhysicsObject( CBaseEntity *pFrom, CBaseEntity *pTo, bool wakeUp ) -{ - IPhysicsObject *pVPhysics = pFrom->VPhysicsGetObject(); - if ( !pVPhysics || pVPhysics->IsStatic() ) - return false; - - // clear out the pointer so it won't get deleted - pFrom->VPhysicsSwapObject( NULL ); - // remove any AI behavior bound to it - pVPhysics->RemoveShadowController(); - // transfer to the new owner - pTo->VPhysicsSetObject( pVPhysics ); - pVPhysics->SetGameData( (void *)pTo ); - pTo->VPhysicsUpdate( pVPhysics ); - - // may have been temporarily disabled by the old object - pVPhysics->EnableMotion( true ); - pVPhysics->EnableGravity( true ); - - // Update for the new entity solid type - pVPhysics->RecheckCollisionFilter(); - if ( wakeUp ) - { - pVPhysics->Wake(); - } - - return true; -} - -// UNDONE: Move/rename this function -static CBaseEntity *CreateSimplePhysicsObject( CBaseEntity *pEntity, bool createAsleep, bool createAsDebris ) -{ - CBaseEntity *pPhysEntity = NULL; - int modelindex = pEntity->GetModelIndex(); - const model_t *model = modelinfo->GetModel( modelindex ); - if ( model && modelinfo->GetModelType(model) == mod_brush ) - { - pPhysEntity = CreateEntityByName( "simple_physics_brush" ); - } - else - { - pPhysEntity = CreateEntityByName( "simple_physics_prop" ); - } - - pPhysEntity->KeyValue( "model", STRING(pEntity->GetModelName()) ); - pPhysEntity->SetAbsOrigin( pEntity->GetAbsOrigin() ); - pPhysEntity->SetAbsAngles( pEntity->GetAbsAngles() ); - pPhysEntity->Spawn(); - if ( !TransferPhysicsObject( pEntity, pPhysEntity, !createAsleep ) ) - { - pPhysEntity->VPhysicsInitNormal( SOLID_VPHYSICS, 0, createAsleep ); - if ( createAsDebris ) - pPhysEntity->SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - } - return pPhysEntity; -} - -#define SF_CONVERT_ASLEEP 0x0001 -#define SF_CONVERT_AS_DEBRIS 0x0002 - -class CPhysConvert : public CLogicalEntity -{ - DECLARE_CLASS( CPhysConvert, CLogicalEntity ); - -public: - CPhysConvert( void ) : m_flMassOverride( 0.0f ) {}; - COutputEvent m_OnConvert; - - // Input handlers - void InputConvertTarget( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - -private: - string_t m_swapModel; - float m_flMassOverride; -}; - -LINK_ENTITY_TO_CLASS( phys_convert, CPhysConvert ); - -BEGIN_DATADESC( CPhysConvert ) - - DEFINE_KEYFIELD( m_swapModel, FIELD_STRING, "swapmodel" ), - DEFINE_KEYFIELD( m_flMassOverride, FIELD_FLOAT, "massoverride" ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "ConvertTarget", InputConvertTarget ), - - // Outputs - DEFINE_OUTPUT( m_OnConvert, "OnConvert"), - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that converts our target to a physics object. -//----------------------------------------------------------------------------- -void CPhysConvert::InputConvertTarget( inputdata_t &inputdata ) -{ - bool createAsleep = HasSpawnFlags(SF_CONVERT_ASLEEP); - bool createAsDebris = HasSpawnFlags(SF_CONVERT_AS_DEBRIS); - // Fire output - m_OnConvert.FireOutput( inputdata.pActivator, this ); - - CBaseEntity *entlist[512]; - CBaseEntity *pSwap = gEntList.FindEntityByName( NULL, m_swapModel, NULL, inputdata.pActivator, inputdata.pCaller ); - CBaseEntity *pEntity = NULL; - - int count = 0; - while ( (pEntity = gEntList.FindEntityByName( pEntity, m_target, NULL, inputdata.pActivator, inputdata.pCaller )) != NULL ) - { - entlist[count++] = pEntity; - if ( count >= (int)ARRAYSIZE(entlist) ) - break; - } - - // if we're swapping to model out, don't loop over more than one object - // multiple objects with the same brush model will render, but the dynamic lights - // and decals will be shared between the two instances... - if ( pSwap && count > 0 ) - { - count = 1; - } - - for ( int i = 0; i < count; i++ ) - { - pEntity = entlist[i]; - - // don't convert something that is already physics based - if ( pEntity->GetMoveType() == MOVETYPE_VPHYSICS ) - { - Msg( "ERROR phys_convert %s ! Already MOVETYPE_VPHYSICS\n", STRING(pEntity->m_iClassname) ); - continue; - } - - UnlinkFromParent( pEntity ); - - if ( pSwap ) - { - // we can't reuse this physics object, so kill it - pEntity->VPhysicsDestroyObject(); - pEntity->SetModel( STRING(pSwap->GetModelName()) ); - } - - // created phys object, now move hierarchy over - CBaseEntity *pPhys = CreateSimplePhysicsObject( pEntity, createAsleep, createAsDebris ); - if ( pPhys ) - { - // Override the mass if specified - if ( m_flMassOverride > 0 ) - { - IPhysicsObject *pPhysObj = pPhys->VPhysicsGetObject(); - if ( pPhysObj ) - { - pPhysObj->SetMass( m_flMassOverride ); - } - } - - pPhys->SetName( pEntity->GetEntityName() ); - UTIL_TransferPoseParameters( pEntity, pPhys ); - TransferChildren( pEntity, pPhys ); - pEntity->AddSolidFlags( FSOLID_NOT_SOLID ); - pEntity->AddEffects( EF_NODRAW ); - UTIL_Remove( pEntity ); - } - } -} - -//============================================================================================================ -// PHYS MAGNET -//============================================================================================================ -#define SF_MAGNET_ASLEEP 0x0001 -#define SF_MAGNET_MOTIONDISABLED 0x0002 -#define SF_MAGNET_SUCK 0x0004 -#define SF_MAGNET_ALLOWROTATION 0x0008 -#define SF_MAGNET_COAST_HACK 0x0010 - -LINK_ENTITY_TO_CLASS( phys_magnet, CPhysMagnet ); - -// BUGBUG: This won't work! Right now you can't save physics pointers inside an embedded type! -BEGIN_SIMPLE_DATADESC( magnetted_objects_t ) - - DEFINE_PHYSPTR( pConstraint ), - DEFINE_FIELD( hEntity, FIELD_EHANDLE ), - -END_DATADESC() - -BEGIN_DATADESC( CPhysMagnet ) - // Outputs - DEFINE_OUTPUT( m_OnMagnetAttach, "OnAttach" ), - DEFINE_OUTPUT( m_OnMagnetDetach, "OnDetach" ), - - // Keys - DEFINE_KEYFIELD( m_massScale, FIELD_FLOAT, "massScale" ), - DEFINE_KEYFIELD( m_iszOverrideScript, FIELD_STRING, "overridescript" ), - DEFINE_KEYFIELD( m_iMaxObjectsAttached, FIELD_INTEGER, "maxobjects" ), - DEFINE_KEYFIELD( m_forceLimit, FIELD_FLOAT, "forcelimit" ), - DEFINE_KEYFIELD( m_torqueLimit, FIELD_FLOAT, "torquelimit" ), - - DEFINE_UTLVECTOR( m_MagnettedEntities, FIELD_EMBEDDED ), - DEFINE_PHYSPTR( m_pConstraintGroup ), - - DEFINE_FIELD( m_bActive, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bHasHitSomething, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flTotalMass, FIELD_FLOAT ), - DEFINE_FIELD( m_flRadius, FIELD_FLOAT ), - DEFINE_FIELD( m_flNextSuckTime, FIELD_FLOAT ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: SendProxy that converts the magnet's attached object UtlVector to entindexes -//----------------------------------------------------------------------------- -void SendProxy_MagnetAttachedObjectList( const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ) -{ - CPhysMagnet *pMagnet = (CPhysMagnet*)pData; - - // If this assertion fails, then SendProxyArrayLength_MagnetAttachedArray must have failed. - Assert( iElement < pMagnet->GetNumAttachedObjects() ); - - pOut->m_Int = pMagnet->GetAttachedObject(iElement)->entindex(); -} - - -int SendProxyArrayLength_MagnetAttachedArray( const void *pStruct, int objectID ) -{ - CPhysMagnet *pMagnet = (CPhysMagnet*)pStruct; - return pMagnet->GetNumAttachedObjects(); -} - -IMPLEMENT_SERVERCLASS_ST( CPhysMagnet, DT_PhysMagnet ) - - // ROBIN: Disabled because we don't need it anymore - /* - SendPropArray2( - SendProxyArrayLength_MagnetAttachedArray, - SendPropInt("magnetattached_array_element", 0, 4, 10, SPROP_UNSIGNED, SendProxy_MagnetAttachedObjectList), - 128, - 0, - "magnetattached_array" - ) - */ - -END_SEND_TABLE() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CPhysMagnet::CPhysMagnet( void ) -{ - m_forceLimit = 0; - m_torqueLimit = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CPhysMagnet::~CPhysMagnet( void ) -{ - DetachAll(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysMagnet::Spawn( void ) -{ - Precache(); - - SetMoveType( MOVETYPE_NONE ); - SetSolid( SOLID_VPHYSICS ); - SetModel( STRING( GetModelName() ) ); - - m_takedamage = DAMAGE_EVENTS_ONLY; - - solid_t tmpSolid; - PhysModelParseSolid( tmpSolid, this, GetModelIndex() ); - if ( m_massScale > 0 ) - { - tmpSolid.params.mass *= m_massScale; - } - PhysSolidOverride( tmpSolid, m_iszOverrideScript ); - VPhysicsInitNormal( GetSolid(), GetSolidFlags(), true, &tmpSolid ); - - // Wake it up if not asleep - if ( !HasSpawnFlags(SF_MAGNET_ASLEEP) ) - { - VPhysicsGetObject()->Wake(); - } - - if ( HasSpawnFlags(SF_MAGNET_MOTIONDISABLED) ) - { - VPhysicsGetObject()->EnableMotion( false ); - } - - m_bActive = true; - m_pConstraintGroup = NULL; - m_flTotalMass = 0; - m_flNextSuckTime = 0; - - BaseClass::Spawn(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysMagnet::Precache( void ) -{ - PrecacheModel( STRING( GetModelName() ) ); - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysMagnet::Touch( CBaseEntity *pOther ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysMagnet::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) -{ - int otherIndex = !index; - CBaseEntity *pOther = pEvent->pEntities[otherIndex]; - - // Ignore triggers - if ( pOther->IsSolidFlagSet( FSOLID_NOT_SOLID ) ) - return; - - m_bHasHitSomething = true; - DoMagnetSuck( pEvent->pEntities[!index] ); - - // Don't pickup if we're not active - if ( !m_bActive ) - return; - - // Hit our maximum? - if ( m_iMaxObjectsAttached && m_iMaxObjectsAttached <= GetNumAttachedObjects() ) - return; - - // This is a hack to solve players (Erik) stacking stuff on their jeeps in coast_01 - // and being screwed when the crane can't pick them up. We need to get rid of the object. - if ( HasSpawnFlags( SF_MAGNET_COAST_HACK ) ) - { - // If the other isn't the jeep, we need to get rid of it - if ( !FClassnameIs( pOther, "prop_vehicle_jeep" ) ) - { - // If it takes damage, destroy it - if ( pOther->m_takedamage != DAMAGE_NO && pOther->m_takedamage != DAMAGE_EVENTS_ONLY ) - { - CTakeDamageInfo info( this, this, pOther->GetHealth(), DMG_GENERIC | DMG_PREVENT_PHYSICS_FORCE ); - pOther->TakeDamage( info ); - } - else if ( pEvent->pObjects[ otherIndex ]->IsMoveable() ) - { - // Otherwise, we're screwed, so just remove it - UTIL_Remove( pOther ); - } - else - { - Warning( "CPhysMagnet %s:%d blocking magnet\n", - pOther->GetClassname(), pOther->entindex() ); - } - return; - } - } - - // Make sure it's made of metal - const surfacedata_t *phit = physprops->GetSurfaceData( pEvent->surfaceProps[otherIndex] ); - char cTexType = phit->game.material; - if ( cTexType != CHAR_TEX_METAL && cTexType != CHAR_TEX_COMPUTER ) - { - // If we don't have a model, we're done. The texture we hit wasn't metal. - if ( !pOther->GetBaseAnimating() ) - return; - - // If we have a model that wants to be metal, even though we hit a non-metal texture, we'll stick to it - if ( Q_strncmp( Studio_GetDefaultSurfaceProps( pOther->GetBaseAnimating()->GetModelPtr() ), "metal", 5 ) ) - return; - } - - IPhysicsObject *pPhysics = pOther->VPhysicsGetObject(); - if ( pPhysics && pOther->GetMoveType() == MOVETYPE_VPHYSICS && pPhysics->IsMoveable() ) - { - // Make sure we haven't already got this sucker on the magnet - int iCount = m_MagnettedEntities.Count(); - for ( int i = 0; i < iCount; i++ ) - { - if ( m_MagnettedEntities[i].hEntity == pOther ) - return; - } - - // We want to cast a long way to ensure our shadow shows up - pOther->SetShadowCastDistance( 2048 ); - - // Create a constraint between the magnet and this sucker - IPhysicsObject *pMagnetPhysObject = VPhysicsGetObject(); - Assert( pMagnetPhysObject ); - - magnetted_objects_t newEntityOnMagnet; - newEntityOnMagnet.hEntity = pOther; - - // Use the right constraint - if ( HasSpawnFlags( SF_MAGNET_ALLOWROTATION ) ) - { - constraint_ballsocketparams_t ballsocket; - ballsocket.Defaults(); - ballsocket.constraint.Defaults(); - ballsocket.constraint.forceLimit = lbs2kg(m_forceLimit); - ballsocket.constraint.torqueLimit = lbs2kg(m_torqueLimit); - - Vector vecCollisionPoint; - pEvent->pInternalData->GetContactPoint( vecCollisionPoint ); - - pMagnetPhysObject->WorldToLocal( &ballsocket.constraintPosition[0], vecCollisionPoint ); - pPhysics->WorldToLocal( &ballsocket.constraintPosition[1], vecCollisionPoint ); - - //newEntityOnMagnet.pConstraint = physenv->CreateBallsocketConstraint( pMagnetPhysObject, pPhysics, m_pConstraintGroup, ballsocket ); - newEntityOnMagnet.pConstraint = physenv->CreateBallsocketConstraint( pMagnetPhysObject, pPhysics, NULL, ballsocket ); - } - else - { - constraint_fixedparams_t fixed; - fixed.Defaults(); - fixed.InitWithCurrentObjectState( pMagnetPhysObject, pPhysics ); - fixed.constraint.Defaults(); - fixed.constraint.forceLimit = lbs2kg(m_forceLimit); - fixed.constraint.torqueLimit = lbs2kg(m_torqueLimit); - - // FIXME: Use the magnet's constraint group. - //newEntityOnMagnet.pConstraint = physenv->CreateFixedConstraint( pMagnetPhysObject, pPhysics, m_pConstraintGroup, fixed ); - newEntityOnMagnet.pConstraint = physenv->CreateFixedConstraint( pMagnetPhysObject, pPhysics, NULL, fixed ); - } - - newEntityOnMagnet.pConstraint->SetGameData( (void *) this ); - m_MagnettedEntities.AddToTail( newEntityOnMagnet ); - - m_flTotalMass += pPhysics->GetMass(); - } - - DoMagnetSuck( pOther ); - - m_OnMagnetAttach.FireOutput( this, this ); - - BaseClass::VPhysicsCollision( index, pEvent ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysMagnet::DoMagnetSuck( CBaseEntity *pOther ) -{ - if ( !HasSpawnFlags( SF_MAGNET_SUCK ) ) - return; - - if ( !m_bActive ) - return; - - // Don't repeatedly suck - if ( m_flNextSuckTime > gpGlobals->curtime ) - return; - - // Look for physics objects underneath the magnet and suck them onto it - Vector vecCheckPos, vecSuckPoint; - VectorTransform( Vector(0,0,-96), EntityToWorldTransform(), vecCheckPos ); - VectorTransform( Vector(0,0,-64), EntityToWorldTransform(), vecSuckPoint ); - - CBaseEntity *pEntities[20]; - int iNumEntities = UTIL_EntitiesInSphere( pEntities, 20, vecCheckPos, 80.0, 0 ); - for ( int i = 0; i < iNumEntities; i++ ) - { - CBaseEntity *pEntity = pEntities[i]; - if ( !pEntity || pEntity == pOther ) - continue; - - IPhysicsObject *pPhys = pEntity->VPhysicsGetObject(); - if ( pPhys && pEntity->GetMoveType() == MOVETYPE_VPHYSICS && pPhys->GetMass() < 5000 ) - { - // Do we have line of sight to it? - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), pEntity->GetAbsOrigin(), MASK_SHOT, this, 0, &tr ); - if ( tr.fraction == 1.0 || tr.m_pEnt == pEntity ) - { - // Pull it towards the magnet - Vector vecVelocity = (vecSuckPoint - pEntity->GetAbsOrigin()); - VectorNormalize(vecVelocity); - vecVelocity *= 5 * pPhys->GetMass(); - pPhys->AddVelocity( &vecVelocity, NULL ); - } - } - } - - m_flNextSuckTime = gpGlobals->curtime + 2.0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysMagnet::SetConstraintGroup( IPhysicsConstraintGroup *pGroup ) -{ - m_pConstraintGroup = pGroup; -} - -//----------------------------------------------------------------------------- -// Purpose: Make the magnet active -//----------------------------------------------------------------------------- -void CPhysMagnet::InputTurnOn( inputdata_t &inputdata ) -{ - m_bActive = true; -} - -//----------------------------------------------------------------------------- -// Purpose: Make the magnet inactive. Drop everything it's got hooked on. -//----------------------------------------------------------------------------- -void CPhysMagnet::InputTurnOff( inputdata_t &inputdata ) -{ - m_bActive = false; - DetachAll(); -} - -//----------------------------------------------------------------------------- -// Purpose: Toggle the magnet's active state -//----------------------------------------------------------------------------- -void CPhysMagnet::InputToggle( inputdata_t &inputdata ) -{ - if ( m_bActive ) - { - InputTurnOff( inputdata ); - } - else - { - InputTurnOn( inputdata ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: One of our magnet constraints broke -//----------------------------------------------------------------------------- -void CPhysMagnet::ConstraintBroken( IPhysicsConstraint *pConstraint ) -{ - // Find the entity that was constrained and release it - int iCount = m_MagnettedEntities.Count(); - for ( int i = 0; i < iCount; i++ ) - { - if ( m_MagnettedEntities[i].hEntity.Get() != NULL && m_MagnettedEntities[i].pConstraint == pConstraint ) - { - IPhysicsObject *pPhysObject = m_MagnettedEntities[i].hEntity->VPhysicsGetObject(); - - if( pPhysObject != NULL ) - { - m_flTotalMass -= pPhysObject->GetMass(); - } - - m_MagnettedEntities.Remove(i); - break; - } - } - - m_OnMagnetDetach.FireOutput( this, this ); - - physenv->DestroyConstraint( pConstraint ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysMagnet::DetachAll( void ) -{ - // Make sure we haven't already got this sucker on the magnet - int iCount = m_MagnettedEntities.Count(); - for ( int i = 0; i < iCount; i++ ) - { - // Delay a couple seconds to reset to the default shadow cast behavior - if ( m_MagnettedEntities[i].hEntity ) - { - m_MagnettedEntities[i].hEntity->SetShadowCastDistance( 0, 2.0f ); - } - - physenv->DestroyConstraint( m_MagnettedEntities[i].pConstraint ); - } - - m_MagnettedEntities.Purge(); - m_flTotalMass = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CPhysMagnet::GetNumAttachedObjects( void ) -{ - return m_MagnettedEntities.Count(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CPhysMagnet::GetTotalMassAttachedObjects( void ) -{ - return m_flTotalMass; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseEntity *CPhysMagnet::GetAttachedObject( int iIndex ) -{ - Assert( iIndex < GetNumAttachedObjects() ); - - return m_MagnettedEntities[iIndex].hEntity; -} - -class CInfoMassCenter : public CPointEntity -{ - DECLARE_CLASS( CInfoMassCenter, CPointEntity ); -public: - void Spawn( void ) - { - if ( m_target != NULL_STRING ) - { - masscenteroverride_t params; - params.SnapToPoint( m_target, GetAbsOrigin() ); - PhysSetMassCenterOverride( params ); - UTIL_Remove( this ); - } - } -}; -LINK_ENTITY_TO_CLASS( info_mass_center, CInfoMassCenter ); - -// ============================================================= -// point_push -// ============================================================= - -class CPointPush : public CPointEntity -{ -public: - DECLARE_CLASS( CPointPush, CPointEntity ); - - virtual void Activate( void ); - void PushThink( void ); - - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - -private: - inline void PushEntity( CBaseEntity *pTarget ); - - bool m_bEnabled; - float m_flMagnitude; - float m_flRadius; - float m_flInnerRadius; // Inner radius where the push eminates from (on a sphere) -}; - -LINK_ENTITY_TO_CLASS( point_push, CPointPush ); - -BEGIN_DATADESC( CPointPush ) - - DEFINE_THINKFUNC( PushThink ), - - DEFINE_KEYFIELD( m_bEnabled, FIELD_BOOLEAN, "enabled" ), - DEFINE_KEYFIELD( m_flMagnitude, FIELD_FLOAT, "magnitude" ), - DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "radius" ), - DEFINE_KEYFIELD( m_flInnerRadius,FIELD_FLOAT, "inner_radius" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - -END_DATADESC(); - -// Spawnflags -#define SF_PUSH_TEST_LOS 0x0001 -#define SF_PUSH_DIRECTIONAL 0x0002 -#define SF_PUSH_NO_FALLOFF 0x0004 -#define SF_PUSH_PLAYER 0x0008 -#define SF_PUSH_PHYSICS 0x0010 - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointPush::Activate( void ) -{ - if ( m_bEnabled ) - { - SetThink( &CPointPush::PushThink ); - SetNextThink( gpGlobals->curtime + 0.05f ); - } - - BaseClass::Activate(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTarget - -//----------------------------------------------------------------------------- -void CPointPush::PushEntity( CBaseEntity *pTarget ) -{ - Vector vecPushDir; - - if ( HasSpawnFlags( SF_PUSH_DIRECTIONAL ) ) - { - GetVectors( &vecPushDir, NULL, NULL ); - } - else - { - vecPushDir = ( pTarget->BodyTarget( GetAbsOrigin(), false ) - GetAbsOrigin() ); - } - - float dist = VectorNormalize( vecPushDir ); - - float flFalloff = ( HasSpawnFlags( SF_PUSH_NO_FALLOFF ) ) ? 1.0f : RemapValClamped( dist, m_flRadius, m_flRadius*0.25f, 0.0f, 1.0f ); - - switch( pTarget->GetMoveType() ) - { - case MOVETYPE_NONE: - case MOVETYPE_PUSH: - case MOVETYPE_NOCLIP: - break; - - case MOVETYPE_VPHYSICS: - { - IPhysicsObject *pPhys = pTarget->VPhysicsGetObject(); - if ( pPhys ) - { - // UNDONE: Assume the velocity is for a 100kg object, scale with mass - pPhys->ApplyForceCenter( m_flMagnitude * flFalloff * 100.0f * vecPushDir * pPhys->GetMass() * gpGlobals->frametime ); - return; - } - } - break; - - case MOVETYPE_STEP: - { - // NPCs cannot be lifted up properly, they need to move in 2D - vecPushDir.z = 0.0f; - - // NOTE: Falls through! - } - - default: - { - Vector vecPush = (m_flMagnitude * vecPushDir * flFalloff); - if ( pTarget->GetFlags() & FL_BASEVELOCITY ) - { - vecPush = vecPush + pTarget->GetBaseVelocity(); - } - if ( vecPush.z > 0 && (pTarget->GetFlags() & FL_ONGROUND) ) - { - pTarget->SetGroundEntity( NULL ); - Vector origin = pTarget->GetAbsOrigin(); - origin.z += 1.0f; - pTarget->SetAbsOrigin( origin ); - } - - pTarget->SetBaseVelocity( vecPush ); - pTarget->AddFlag( FL_BASEVELOCITY ); - } - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointPush::PushThink( void ) -{ - // Get a collection of entities in a radius around us - CBaseEntity *pEnts[256]; - int numEnts = UTIL_EntitiesInSphere( pEnts, 256, GetAbsOrigin(), m_flRadius, 0 ); - for ( int i = 0; i < numEnts; i++ ) - { - // Must be solid - if ( pEnts[i]->IsSolid() == false ) - continue; - - // Cannot be parented (only push parents) - if ( pEnts[i]->GetMoveParent() != NULL ) - continue; - - // Must be moveable - if ( pEnts[i]->GetMoveType() != MOVETYPE_VPHYSICS && - pEnts[i]->GetMoveType() != MOVETYPE_WALK && - pEnts[i]->GetMoveType() != MOVETYPE_STEP ) - continue; - - // If we don't want to push players, don't - if ( pEnts[i]->IsPlayer() && HasSpawnFlags( SF_PUSH_PLAYER ) == false ) - continue; - - // If we don't want to push physics, don't - if ( pEnts[i]->GetMoveType() == MOVETYPE_VPHYSICS && HasSpawnFlags( SF_PUSH_PHYSICS ) == false ) - continue; - - // Test for LOS if asked to - if ( HasSpawnFlags( SF_PUSH_TEST_LOS ) ) - { - Vector vecStartPos = GetAbsOrigin(); - Vector vecEndPos = pEnts[i]->BodyTarget( vecStartPos, false ); - - if ( m_flInnerRadius != 0.0f ) - { - // Find a point on our inner radius sphere to begin from - Vector vecDirToTarget = ( vecEndPos - vecStartPos ); - VectorNormalize( vecDirToTarget ); - vecStartPos = GetAbsOrigin() + ( vecDirToTarget * m_flInnerRadius ); - } - - trace_t tr; - UTIL_TraceLine( vecStartPos, - pEnts[i]->BodyTarget( vecStartPos, false ), - MASK_SOLID_BRUSHONLY, - this, - COLLISION_GROUP_NONE, - &tr ); - - // Shielded - if ( tr.fraction < 1.0f && tr.m_pEnt != pEnts[i] ) - continue; - } - - // Push it along - PushEntity( pEnts[i] ); - } - - // Set us up for the next think - SetNextThink( gpGlobals->curtime + 0.05f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointPush::InputEnable( inputdata_t &inputdata ) -{ - m_bEnabled = true; - SetThink( &CPointPush::PushThink ); - SetNextThink( gpGlobals->curtime + 0.05f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointPush::InputDisable( inputdata_t &inputdata ) -{ - m_bEnabled = false; - SetThink( NULL ); - SetNextThink( gpGlobals->curtime ); -} diff --git a/game/server/physobj.h b/game/server/physobj.h deleted file mode 100644 index 42c19c195..000000000 --- a/game/server/physobj.h +++ /dev/null @@ -1,237 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PHYSOBJ_H -#define PHYSOBJ_H -#ifdef _WIN32 -#pragma once -#endif - -#ifndef PHYSICS_H -#include "physics.h" -#endif - -#include "entityoutput.h" -#include "func_break.h" -#include "player_pickup.h" - -// --------------------------------------------------------------------- -// -// CPhysBox -- physically simulated brush rectangular solid -// -// --------------------------------------------------------------------- -// Physbox Spawnflags. Start at 0x01000 to avoid collision with CBreakable's -#define SF_PHYSBOX_ASLEEP 0x01000 -#define SF_PHYSBOX_IGNOREUSE 0x02000 -#define SF_PHYSBOX_DEBRIS 0x04000 -#define SF_PHYSBOX_MOTIONDISABLED 0x08000 -#define SF_PHYSBOX_USEPREFERRED 0x10000 -#define SF_PHYSBOX_ENABLE_ON_PHYSCANNON 0x20000 -#define SF_PHYSBOX_NO_ROTORWASH_PUSH 0x40000 // The rotorwash doesn't push these -#define SF_PHYSBOX_ENABLE_PICKUP_OUTPUT 0x80000 -#define SF_PHYSBOX_ALWAYS_PICK_UP 0x100000 // Physcannon can always pick this up, no matter what mass or constraints may apply. -#define SF_PHYSBOX_NEVER_PICK_UP 0x200000 // Physcannon will never be able to pick this up. -#define SF_PHYSBOX_NEVER_PUNT 0x400000 // Physcannon will never be able to punt this object. -#define SF_PHYSBOX_PREVENT_PLAYER_TOUCH_ENABLE 0x800000 // If set, the player will not cause the object to enable its motion when bumped into - -// UNDONE: Hook collisions into the physics system to generate touch functions and take damage on falls -// UNDONE: Base class PhysBrush -class CPhysBox : public CBreakable -{ -DECLARE_CLASS( CPhysBox, CBreakable ); - -public: - DECLARE_SERVERCLASS(); - - void Spawn ( void ); - bool CreateVPhysics(); - void Move( const Vector &force ); - virtual int ObjectCaps(); - virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - virtual int DrawDebugTextOverlays(void); - - virtual void VPhysicsUpdate( IPhysicsObject *pPhysics ); - virtual void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); - int OnTakeDamage( const CTakeDamageInfo &info ); - void EnableMotion( void ); - - bool CanBePickedUpByPhyscannon(); - - // IPlayerPickupVPhysics - virtual void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ); - virtual void OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ); - - bool HasPreferredCarryAnglesForPlayer( CBasePlayer *pPlayer ); - virtual QAngle PreferredCarryAngles( void ) { return m_angPreferredCarryAngles; } - - // inputs - void InputWake( inputdata_t &inputdata ); - void InputSleep( inputdata_t &inputdata ); - void InputEnableMotion( inputdata_t &inputdata ); - void InputDisableMotion( inputdata_t &inputdata ); - void InputForceDrop( inputdata_t &inputdata ); - void InputDisableFloating( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - -protected: - int m_damageType; - float m_massScale; - string_t m_iszOverrideScript; - int m_damageToEnableMotion; - float m_flForceToEnableMotion; - QAngle m_angPreferredCarryAngles; - bool m_bNotSolidToWorld; - - // Outputs - COutputEvent m_OnDamaged; - COutputEvent m_OnAwakened; - COutputEvent m_OnMotionEnabled; - COutputEvent m_OnPhysGunPickup; - COutputEvent m_OnPhysGunPunt; - COutputEvent m_OnPhysGunOnlyPickup; - COutputEvent m_OnPhysGunDrop; - COutputEvent m_OnPlayerUse; - - CHandle m_hCarryingPlayer; // Player who's carrying us -}; - -// --------------------------------------------------------------------- -// -// CPhysExplosion -- physically simulated explosion -// -// --------------------------------------------------------------------- -class CPhysExplosion : public CPointEntity -{ -public: - DECLARE_CLASS( CPhysExplosion, CPointEntity ); - - void Spawn ( void ); - void Explode( CBaseEntity *pActivator, CBaseEntity *pCaller ); - - CBaseEntity *FindEntity( CBaseEntity *pEntity, CBaseEntity *pActivator, CBaseEntity *pCaller ); - - int DrawDebugTextOverlays(void); - - // Input handlers - void InputExplode( inputdata_t &inputdata ); - - DECLARE_DATADESC(); -private: - - float GetRadius( void ); - - float m_damage; - float m_radius; - string_t m_targetEntityName; - float m_flInnerRadius; - - COutputEvent m_OnPushedPlayer; -}; - - -//================================================== -// CPhysImpact -//================================================== - -class CPhysImpact : public CPointEntity -{ -public: - DECLARE_CLASS( CPhysImpact, CPointEntity ); - - void Spawn( void ); - //void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - void Activate( void ); - - void InputImpact( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - -private: - - void PointAtEntity( void ); - - float m_damage; - float m_distance; - string_t m_directionEntityName; -}; - -//----------------------------------------------------------------------------- -// Purpose: A magnet that creates constraints between itself and anything it touches -//----------------------------------------------------------------------------- - -struct magnetted_objects_t -{ - IPhysicsConstraint *pConstraint; - EHANDLE hEntity; - - DECLARE_SIMPLE_DATADESC(); -}; - -class CPhysMagnet : public CBaseAnimating, public IPhysicsConstraintEvent -{ - DECLARE_CLASS( CPhysMagnet, CBaseAnimating ); -public: - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - CPhysMagnet(); - ~CPhysMagnet(); - - void Spawn( void ); - void Precache( void ); - void Touch( CBaseEntity *pOther ); - void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); - void DoMagnetSuck( CBaseEntity *pOther ); - void SetConstraintGroup( IPhysicsConstraintGroup *pGroup ); - - bool IsOn( void ) { return m_bActive; } - int GetNumAttachedObjects( void ); - float GetTotalMassAttachedObjects( void ); - CBaseEntity *GetAttachedObject( int iIndex ); - - // Checking for hitting something - void ResetHasHitSomething( void ) { m_bHasHitSomething = false; } - bool HasHitSomething( void ) { return m_bHasHitSomething; } - - // Inputs - void InputToggle( inputdata_t &inputdata ); - void InputTurnOn( inputdata_t &inputdata ); - void InputTurnOff( inputdata_t &inputdata ); - - void InputConstraintBroken( inputdata_t &inputdata ); - - void DetachAll( void ); - -// IPhysicsConstraintEvent -public: - void ConstraintBroken( IPhysicsConstraint *pConstraint ); - -protected: - // Outputs - COutputEvent m_OnMagnetAttach; - COutputEvent m_OnMagnetDetach; - - // Keys - float m_massScale; - string_t m_iszOverrideScript; - float m_forceLimit; - float m_torqueLimit; - - CUtlVector< magnetted_objects_t > m_MagnettedEntities; - IPhysicsConstraintGroup *m_pConstraintGroup; - - bool m_bActive; - bool m_bHasHitSomething; - float m_flTotalMass; - float m_flRadius; - float m_flNextSuckTime; - int m_iMaxObjectsAttached; -}; - -#endif // PHYSOBJ_H diff --git a/game/server/plasma.cpp b/game/server/plasma.cpp deleted file mode 100644 index 7db192a00..000000000 --- a/game/server/plasma.cpp +++ /dev/null @@ -1,93 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "plasma.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//================================================== -// CPlasma -//================================================== - -//Link the entity -LINK_ENTITY_TO_CLASS( _plasma, CPlasma ); - -//Send datatable -IMPLEMENT_SERVERCLASS_ST( CPlasma, DT_Plasma ) - SendPropFloat( SENDINFO( m_flScale ), 0, SPROP_NOSCALE), - SendPropFloat( SENDINFO( m_flScaleTime ), 0, SPROP_NOSCALE), - SendPropInt( SENDINFO( m_nFlags ), 8, SPROP_UNSIGNED ), - SendPropModelIndex( SENDINFO( m_nPlasmaModelIndex )), - SendPropModelIndex( SENDINFO( m_nPlasmaModelIndex2 )), - SendPropModelIndex( SENDINFO( m_nGlowModelIndex )), -END_SEND_TABLE() - -//Data description -BEGIN_DATADESC( CPlasma ) - - //Client-side - DEFINE_FIELD( m_flScale, FIELD_FLOAT ), - DEFINE_FIELD( m_flScaleTime, FIELD_FLOAT ), - DEFINE_FIELD( m_nFlags, FIELD_INTEGER ), - -// DEFINE_FIELD( m_nPlasmaModelIndex, FIELD_INTEGER ), -// DEFINE_FIELD( m_nPlasmaModelIndex2, FIELD_INTEGER ), -// DEFINE_FIELD( m_nGlowModelIndex, FIELD_INTEGER ), - - //Server-side - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CPlasma::CPlasma( void ) -{ - //Client-side - m_flScale = 0.0f; - m_flScaleTime = 0.0f; - m_nFlags = bitsFIRE_NONE; - m_nPlasmaModelIndex = PrecacheModel( "sprites/plasma1.vmt" ); - m_nPlasmaModelIndex2 = PrecacheModel( "sprites/plasma1.vmt" );//<> - m_nGlowModelIndex = PrecacheModel( "sprites/fire_floor.vmt" ); - //Server-side -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CPlasma::~CPlasma( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : state - -//----------------------------------------------------------------------------- -void CPlasma::EnableSmoke( int state ) -{ - if ( state ) - { - m_nFlags |= bitsFIRESMOKE_SMOKE; - } - else - { - m_nFlags &= ~bitsFIRESMOKE_SMOKE; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPlasma::Precache( void ) -{ - PrecacheModel( "sprites/plasma1.vmt" ); - PrecacheModel( "sprites/fire_floor.vmt" ); -} diff --git a/game/server/plasma.h b/game/server/plasma.h deleted file mode 100644 index b93ddc697..000000000 --- a/game/server/plasma.h +++ /dev/null @@ -1,45 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef __PLASMA__ -#define __PLASMA__ -#pragma once - -#include "fire_smoke.h" - -//================================================== -// CPlasma -//================================================== - -//NOTENOTE: Mirrored in cl_dll/c_plasma.cpp -#define bitsPLASMA_FREE 0x00000002 - -class CPlasma : public CBaseFire -{ -public: - DECLARE_CLASS( CPlasma, CBaseFire ); - - CPlasma( void ); - virtual ~CPlasma( void ); - void EnableSmoke( int state ); - - void Precache( void ); - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - -public: - - //Client-side - CNetworkVar( int, m_nPlasmaModelIndex ); - CNetworkVar( int, m_nPlasmaModelIndex2 ); - CNetworkVar( int, m_nGlowModelIndex ); - - //Server-side -}; - -#endif //__PLASMA__ diff --git a/game/server/player.cpp b/game/server/player.cpp deleted file mode 100644 index e4b03f481..000000000 --- a/game/server/player.cpp +++ /dev/null @@ -1,8972 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: Functions dealing with the player. -// -//===========================================================================// - -#include "cbase.h" -#include "const.h" -#include "baseplayer_shared.h" -#include "trains.h" -#include "soundent.h" -#include "gib.h" -#include "shake.h" -#include "decals.h" -#include "gamerules.h" -#include "game.h" -#include "entityapi.h" -#include "entitylist.h" -#include "eventqueue.h" -#include "worldsize.h" -#include "isaverestore.h" -#include "globalstate.h" -#include "basecombatweapon.h" -#include "ai_basenpc.h" -#include "ai_network.h" -#include "ai_node.h" -#include "ai_networkmanager.h" -#include "ammodef.h" -#include "mathlib/mathlib.h" -#include "ndebugoverlay.h" -#include "baseviewmodel.h" -#include "in_buttons.h" -#include "client.h" -#include "team.h" -#include "particle_smokegrenade.h" -#include "IEffects.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "movehelper_server.h" -#include "igamemovement.h" -#include "saverestoretypes.h" -#include "iservervehicle.h" -#include "movevars_shared.h" -#include "vcollide_parse.h" -#include "player_command.h" -#include "vehicle_base.h" -#include "AI_Criteria.h" -#include "globals.h" -#include "usermessages.h" -#include "gamevars_shared.h" -#include "world.h" -#include "physobj.h" -#include "KeyValues.h" -#include "coordsize.h" -#include "vphysics/player_controller.h" -#include "saverestore_utlvector.h" -#include "hltvdirector.h" -#include "nav_mesh.h" -#include "env_zoom.h" -#include "rumble_shared.h" -#include "GameStats.h" -#include "npcevent.h" -#include "datacache/imdlcache.h" -#include "hintsystem.h" -#include "env_debughistory.h" -#include "fogcontroller.h" -#include "gameinterface.h" -#include "hl2orange.spa.h" - -#ifdef HL2_DLL -#include "combine_mine.h" -#include "weapon_physcannon.h" -#endif - -ConVar autoaim_max_dist( "autoaim_max_dist", "2160" ); // 2160 = 180 feet -ConVar autoaim_max_deflect( "autoaim_max_deflect", "0.99" ); - -ConVar spec_freeze_time( "spec_freeze_time", "4.0", FCVAR_CHEAT | FCVAR_REPLICATED, "Time spend frozen in observer freeze cam." ); -ConVar spec_freeze_traveltime( "spec_freeze_traveltime", "0.4", FCVAR_CHEAT | FCVAR_REPLICATED, "Time taken to zoom in to frame a target in observer freeze cam.", true, 0.01, false, 0 ); - -ConVar sv_bonus_challenge( "sv_bonus_challenge", "0", FCVAR_REPLICATED, "Set to values other than 0 to select a bonus map challenge type." ); - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -static ConVar old_armor( "player_old_armor", "0" ); - -static ConVar physicsshadowupdate_render( "physicsshadowupdate_render", "0" ); -bool IsInCommentaryMode( void ); -bool IsListeningToCommentary( void ); - -// This is declared in the engine, too -ConVar sv_noclipduringpause( "sv_noclipduringpause", "0", FCVAR_REPLICATED | FCVAR_CHEAT, "If cheats are enabled, then you can noclip with the game paused (for doing screenshots, etc.)." ); - -extern ConVar sv_maxunlag; -extern ConVar sv_turbophysics; -extern ConVar *sv_maxreplay; - -extern CServerGameDLL g_ServerGameDLL; - -// TIME BASED DAMAGE AMOUNT -// tweak these values based on gameplay feedback: -#define PARALYZE_DURATION 2 // number of 2 second intervals to take damage -#define PARALYZE_DAMAGE 1.0 // damage to take each 2 second interval - -#define NERVEGAS_DURATION 2 -#define NERVEGAS_DAMAGE 5.0 - -#define POISON_DURATION 5 -#define POISON_DAMAGE 2.0 - -#define RADIATION_DURATION 2 -#define RADIATION_DAMAGE 1.0 - -#define ACID_DURATION 2 -#define ACID_DAMAGE 5.0 - -#define SLOWBURN_DURATION 2 -#define SLOWBURN_DAMAGE 1.0 - -#define SLOWFREEZE_DURATION 2 -#define SLOWFREEZE_DAMAGE 1.0 - -//---------------------------------------------------- -// Player Physics Shadow -//---------------------------------------------------- -#define VPHYS_MAX_DISTANCE 2.0 -#define VPHYS_MAX_VEL 10 -#define VPHYS_MAX_DISTSQR (VPHYS_MAX_DISTANCE*VPHYS_MAX_DISTANCE) -#define VPHYS_MAX_VELSQR (VPHYS_MAX_VEL*VPHYS_MAX_VEL) - - -extern bool g_fDrawLines; -int gEvilImpulse101; - -bool gInitHUD = true; - -extern void respawn(CBaseEntity *pEdict, bool fCopyCorpse); -int MapTextureTypeStepType(char chTextureType); -extern void SpawnBlood(Vector vecSpot, const Vector &vecDir, int bloodColor, float flDamage); -extern void AddMultiDamage( const CTakeDamageInfo &info, CBaseEntity *pEntity ); - - -#define CMD_MOSTRECENT 0 - -//#define FLASH_DRAIN_TIME 1.2 //100 units/3 minutes -//#define FLASH_CHARGE_TIME 0.2 // 100 units/20 seconds (seconds per unit) - - -//#define PLAYER_MAX_SAFE_FALL_DIST 20// falling any farther than this many feet will inflict damage -//#define PLAYER_FATAL_FALL_DIST 60// 100% damage inflicted if player falls this many feet -//#define DAMAGE_PER_UNIT_FALLEN (float)( 100 ) / ( ( PLAYER_FATAL_FALL_DIST - PLAYER_MAX_SAFE_FALL_DIST ) * 12 ) -//#define MAX_SAFE_FALL_UNITS ( PLAYER_MAX_SAFE_FALL_DIST * 12 ) - -// player damage adjusters -ConVar sk_player_head( "sk_player_head","2" ); -ConVar sk_player_chest( "sk_player_chest","1" ); -ConVar sk_player_stomach( "sk_player_stomach","1" ); -ConVar sk_player_arm( "sk_player_arm","1" ); -ConVar sk_player_leg( "sk_player_leg","1" ); - -ConVar player_debug_print_damage( "player_debug_print_damage", "0", FCVAR_CHEAT, "When true, print amount and type of all damage received by player to console." ); - - -void CC_GiveCurrentAmmo( void ) -{ - CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); - - if( pPlayer ) - { - CBaseCombatWeapon *pWeapon = pPlayer->GetActiveWeapon(); - - if( pWeapon ) - { - if( pWeapon->UsesPrimaryAmmo() ) - { - int ammoIndex = pWeapon->GetPrimaryAmmoType(); - - if( ammoIndex != -1 ) - { - int giveAmount; - giveAmount = GetAmmoDef()->MaxCarry(ammoIndex); - pPlayer->GiveAmmo( giveAmount, GetAmmoDef()->GetAmmoOfIndex(ammoIndex)->pName ); - } - } - if( pWeapon->UsesSecondaryAmmo() && pWeapon->HasSecondaryAmmo() ) - { - // Give secondary ammo out, as long as the player already has some - // from a presumeably natural source. This prevents players on XBox - // having Combine Balls and so forth in areas of the game that - // were not tested with these items. - int ammoIndex = pWeapon->GetSecondaryAmmoType(); - - if( ammoIndex != -1 ) - { - int giveAmount; - giveAmount = GetAmmoDef()->MaxCarry(ammoIndex); - pPlayer->GiveAmmo( giveAmount, GetAmmoDef()->GetAmmoOfIndex(ammoIndex)->pName ); - } - } - } - } -} -static ConCommand givecurrentammo("givecurrentammo", CC_GiveCurrentAmmo, "Give a supply of ammo for current weapon..\n", FCVAR_CHEAT ); - - -// pl -BEGIN_SIMPLE_DATADESC( CPlayerState ) - // DEFINE_FIELD( netname, FIELD_STRING ), // Don't stomp player name with what's in save/restore - DEFINE_FIELD( v_angle, FIELD_VECTOR ), - DEFINE_FIELD( deadflag, FIELD_BOOLEAN ), - - // this is always set to true on restore, don't bother saving it. - // DEFINE_FIELD( fixangle, FIELD_INTEGER ), - // DEFINE_FIELD( anglechange, FIELD_FLOAT ), - // DEFINE_FIELD( hltv, FIELD_BOOLEAN ), - // DEFINE_FIELD( frags, FIELD_INTEGER ), - // DEFINE_FIELD( deaths, FIELD_INTEGER ), -END_DATADESC() - -// Global Savedata for player -BEGIN_DATADESC( CBasePlayer ) - - DEFINE_EMBEDDED( m_Local ), - DEFINE_UTLVECTOR( m_hTriggerSoundscapeList, FIELD_EHANDLE ), - DEFINE_EMBEDDED( pl ), - - DEFINE_FIELD( m_StuckLast, FIELD_INTEGER ), - - DEFINE_FIELD( m_nButtons, FIELD_INTEGER ), - DEFINE_FIELD( m_afButtonLast, FIELD_INTEGER ), - DEFINE_FIELD( m_afButtonPressed, FIELD_INTEGER ), - DEFINE_FIELD( m_afButtonReleased, FIELD_INTEGER ), - DEFINE_FIELD( m_afButtonDisabled, FIELD_INTEGER ), - DEFINE_FIELD( m_afButtonForced, FIELD_INTEGER ), - - DEFINE_FIELD( m_iFOV, FIELD_INTEGER ), - DEFINE_FIELD( m_iFOVStart, FIELD_INTEGER ), - DEFINE_FIELD( m_flFOVTime, FIELD_TIME ), - DEFINE_FIELD( m_iDefaultFOV,FIELD_INTEGER ), - DEFINE_FIELD( m_flVehicleViewFOV, FIELD_FLOAT ), - - //DEFINE_FIELD( m_fOnTarget, FIELD_BOOLEAN ), // Don't need to restore - DEFINE_FIELD( m_iObserverMode, FIELD_INTEGER ), - DEFINE_FIELD( m_iObserverLastMode, FIELD_INTEGER ), - DEFINE_FIELD( m_hObserverTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_bForcedObserverMode, FIELD_BOOLEAN ), - DEFINE_AUTO_ARRAY( m_szAnimExtension, FIELD_CHARACTER ), -// DEFINE_CUSTOM_FIELD( m_Activity, ActivityDataOps() ), - - DEFINE_FIELD( m_nUpdateRate, FIELD_INTEGER ), - DEFINE_FIELD( m_fLerpTime, FIELD_FLOAT ), - DEFINE_FIELD( m_bLagCompensation, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bPredictWeapons, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_vecAdditionalPVSOrigin, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecCameraPVSOrigin, FIELD_POSITION_VECTOR ), - - DEFINE_FIELD( m_hUseEntity, FIELD_EHANDLE ), - DEFINE_FIELD( m_iTrain, FIELD_INTEGER ), - DEFINE_FIELD( m_iRespawnFrames, FIELD_FLOAT ), - DEFINE_FIELD( m_afPhysicsFlags, FIELD_INTEGER ), - DEFINE_FIELD( m_hVehicle, FIELD_EHANDLE ), - - // recreate, don't restore - // DEFINE_FIELD( m_CommandContext, CUtlVector < CCommandContext > ), - //DEFINE_FIELD( m_pPhysicsController, FIELD_POINTER ), - //DEFINE_FIELD( m_pShadowStand, FIELD_POINTER ), - //DEFINE_FIELD( m_pShadowCrouch, FIELD_POINTER ), - //DEFINE_FIELD( m_vphysicsCollisionState, FIELD_INTEGER ), - // DEFINE_FIELD( m_lastNavArea, CNavArea ), - DEFINE_ARRAY( m_szNetworkIDString, FIELD_CHARACTER, MAX_NETWORKID_LENGTH ), - DEFINE_FIELD( m_oldOrigin, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecSmoothedVelocity, FIELD_VECTOR ), - //DEFINE_FIELD( m_touchedPhysObject, FIELD_BOOLEAN ), - //DEFINE_FIELD( m_bPhysicsWasFrozen, FIELD_BOOLEAN ), - //DEFINE_FIELD( m_iPlayerSound, FIELD_INTEGER ), // Don't restore, set in Precache() - DEFINE_FIELD( m_iTargetVolume, FIELD_INTEGER ), - DEFINE_AUTO_ARRAY( m_rgItems, FIELD_INTEGER ), - //DEFINE_FIELD( m_fNextSuicideTime, FIELD_TIME ), - // DEFINE_FIELD( m_PlayerInfo, CPlayerInfo ), - - DEFINE_FIELD( m_flSwimTime, FIELD_TIME ), - DEFINE_FIELD( m_flDuckTime, FIELD_TIME ), - DEFINE_FIELD( m_flDuckJumpTime, FIELD_TIME ), - - DEFINE_FIELD( m_flSuitUpdate, FIELD_TIME ), - DEFINE_AUTO_ARRAY( m_rgSuitPlayList, FIELD_INTEGER ), - DEFINE_FIELD( m_iSuitPlayNext, FIELD_INTEGER ), - DEFINE_AUTO_ARRAY( m_rgiSuitNoRepeat, FIELD_INTEGER ), - DEFINE_AUTO_ARRAY( m_rgflSuitNoRepeatTime, FIELD_TIME ), - DEFINE_FIELD( m_bPauseBonusProgress, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iBonusProgress, FIELD_INTEGER ), - DEFINE_FIELD( m_iBonusChallenge, FIELD_INTEGER ), - DEFINE_FIELD( m_lastDamageAmount, FIELD_INTEGER ), - DEFINE_FIELD( m_tbdPrev, FIELD_TIME ), - DEFINE_FIELD( m_flStepSoundTime, FIELD_FLOAT ), - DEFINE_ARRAY( m_szNetname, FIELD_CHARACTER, MAX_PLAYER_NAME_LENGTH ), - - //DEFINE_FIELD( m_flgeigerRange, FIELD_FLOAT ), // Don't restore, reset in Precache() - //DEFINE_FIELD( m_flgeigerDelay, FIELD_FLOAT ), // Don't restore, reset in Precache() - //DEFINE_FIELD( m_igeigerRangePrev, FIELD_FLOAT ), // Don't restore, reset in Precache() - //DEFINE_FIELD( m_iStepLeft, FIELD_INTEGER ), // Don't need to restore - //DEFINE_FIELD( m_chTextureType, FIELD_CHARACTER ), // Don't need to restore - //DEFINE_FIELD( m_surfaceProps, FIELD_INTEGER ), // don't need to restore, reset by gamemovement - // DEFINE_FIELD( m_pSurfaceData, surfacedata_t* ), - //DEFINE_FIELD( m_surfaceFriction, FIELD_FLOAT ), - //DEFINE_FIELD( m_chPreviousTextureType, FIELD_CHARACTER ), - - DEFINE_FIELD( m_idrowndmg, FIELD_INTEGER ), - DEFINE_FIELD( m_idrownrestored, FIELD_INTEGER ), - - DEFINE_FIELD( m_nPoisonDmg, FIELD_INTEGER ), - DEFINE_FIELD( m_nPoisonRestored, FIELD_INTEGER ), - - DEFINE_FIELD( m_bitsHUDDamage, FIELD_INTEGER ), - DEFINE_FIELD( m_fInitHUD, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flDeathTime, FIELD_TIME ), - DEFINE_FIELD( m_flDeathAnimTime, FIELD_TIME ), - - //DEFINE_FIELD( m_fGameHUDInitialized, FIELD_BOOLEAN ), // only used in multiplayer games - //DEFINE_FIELD( m_fWeapon, FIELD_BOOLEAN ), // Don't restore, client needs reset - //DEFINE_FIELD( m_iUpdateTime, FIELD_INTEGER ), // Don't need to restore - //DEFINE_FIELD( m_iClientBattery, FIELD_INTEGER ), // Don't restore, client needs reset - //DEFINE_FIELD( m_iClientHideHUD, FIELD_INTEGER ), // Don't restore, client needs reset - //DEFINE_FIELD( m_vecAutoAim, FIELD_VECTOR ), // Don't save/restore - this is recomputed - //DEFINE_FIELD( m_lastx, FIELD_INTEGER ), - //DEFINE_FIELD( m_lasty, FIELD_INTEGER ), - - DEFINE_FIELD( m_iFrags, FIELD_INTEGER ), - DEFINE_FIELD( m_iDeaths, FIELD_INTEGER ), - DEFINE_FIELD( m_bAllowInstantSpawn, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flNextDecalTime, FIELD_TIME ), - //DEFINE_AUTO_ARRAY( m_szTeamName, FIELD_STRING ), // mp - - //DEFINE_FIELD( m_iConnected, FIELD_INTEGER ), - // from edict_t - DEFINE_FIELD( m_ArmorValue, FIELD_INTEGER ), - DEFINE_FIELD( m_DmgOrigin, FIELD_VECTOR ), - DEFINE_FIELD( m_DmgTake, FIELD_FLOAT ), - DEFINE_FIELD( m_DmgSave, FIELD_FLOAT ), - DEFINE_FIELD( m_AirFinished, FIELD_TIME ), - DEFINE_FIELD( m_PainFinished, FIELD_TIME ), - - DEFINE_FIELD( m_iPlayerLocked, FIELD_INTEGER ), - - DEFINE_AUTO_ARRAY( m_hViewModel, FIELD_EHANDLE ), - - DEFINE_FIELD( m_flMaxspeed, FIELD_FLOAT ), - DEFINE_FIELD( m_flWaterJumpTime, FIELD_TIME ), - DEFINE_FIELD( m_vecWaterJumpVel, FIELD_VECTOR ), - DEFINE_FIELD( m_nImpulse, FIELD_INTEGER ), - DEFINE_FIELD( m_flSwimSoundTime, FIELD_TIME ), - DEFINE_FIELD( m_vecLadderNormal, FIELD_VECTOR ), - - DEFINE_FIELD( m_flFlashTime, FIELD_TIME ), - DEFINE_FIELD( m_nDrownDmgRate, FIELD_INTEGER ), - DEFINE_FIELD( m_iSuicideCustomKillFlags, FIELD_INTEGER ), - - // NOT SAVED - //DEFINE_FIELD( m_vForcedOrigin, FIELD_VECTOR ), - //DEFINE_FIELD( m_bForceOrigin, FIELD_BOOLEAN ), - //DEFINE_FIELD( m_nTickBase, FIELD_INTEGER ), - //DEFINE_FIELD( m_LastCmd, FIELD_ ), - // DEFINE_FIELD( m_pCurrentCommand, CUserCmd ), - //DEFINE_FIELD( m_bGamePaused, FIELD_BOOLEAN ), - // DEFINE_FIELD( m_iVehicleAnalogBias, FIELD_INTEGER ), - - // m_flVehicleViewFOV - // m_vecVehicleViewOrigin - // m_vecVehicleViewAngles - // m_nVehicleViewSavedFrame - - DEFINE_FIELD( m_bitsDamageType, FIELD_INTEGER ), - DEFINE_AUTO_ARRAY( m_rgbTimeBasedDamage, FIELD_CHARACTER ), - DEFINE_FIELD( m_fLastPlayerTalkTime, FIELD_FLOAT ), - DEFINE_FIELD( m_hLastWeapon, FIELD_EHANDLE ), - -#if !defined( NO_ENTITY_PREDICTION ) - // DEFINE_FIELD( m_SimulatedByThisPlayer, CUtlVector < CHandle < CBaseEntity > > ), -#endif - - DEFINE_FIELD( m_flOldPlayerZ, FIELD_FLOAT ), - DEFINE_FIELD( m_flOldPlayerViewOffsetZ, FIELD_FLOAT ), - DEFINE_FIELD( m_bPlayerUnderwater, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hViewEntity, FIELD_EHANDLE ), - - DEFINE_FIELD( m_hConstraintEntity, FIELD_EHANDLE ), - DEFINE_FIELD( m_vecConstraintCenter, FIELD_VECTOR ), - DEFINE_FIELD( m_flConstraintRadius, FIELD_FLOAT ), - DEFINE_FIELD( m_flConstraintWidth, FIELD_FLOAT ), - DEFINE_FIELD( m_flConstraintSpeedFactor, FIELD_FLOAT ), - DEFINE_FIELD( m_hZoomOwner, FIELD_EHANDLE ), - - DEFINE_FIELD( m_flLaggedMovementValue, FIELD_FLOAT ), - - DEFINE_FIELD( m_vNewVPhysicsPosition, FIELD_VECTOR ), - DEFINE_FIELD( m_vNewVPhysicsVelocity, FIELD_VECTOR ), - - DEFINE_FIELD( m_bSinglePlayerGameEnding, FIELD_BOOLEAN ), - DEFINE_ARRAY( m_szLastPlaceName, FIELD_CHARACTER, MAX_PLACE_NAME_LENGTH ), - - DEFINE_FIELD( m_autoKickDisabled, FIELD_BOOLEAN ), - - // Function Pointers - DEFINE_FUNCTION( PlayerDeathThink ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetHealth", InputSetHealth ), - DEFINE_INPUTFUNC( FIELD_BOOLEAN, "SetHUDVisibility", InputSetHUDVisibility ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetFogController", InputSetFogController ), - - DEFINE_FIELD( m_nNumCrouches, FIELD_INTEGER ), - DEFINE_FIELD( m_bDuckToggled, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flForwardMove, FIELD_FLOAT ), - DEFINE_FIELD( m_flSideMove, FIELD_FLOAT ), - DEFINE_FIELD( m_vecPreviouslyPredictedOrigin, FIELD_POSITION_VECTOR ), - - DEFINE_FIELD( m_nNumCrateHudHints, FIELD_INTEGER ), - - // DEFINE_FIELD( m_nBodyPitchPoseParam, FIELD_INTEGER ), - // DEFINE_ARRAY( m_StepSoundCache, StepSoundCache_t, 2 ), - - // DEFINE_UTLVECTOR( m_vecPlayerCmdInfo ), - // DEFINE_UTLVECTOR( m_vecPlayerSimInfo ), -END_DATADESC() - -int giPrecacheGrunt = 0; - -edict_t *CBasePlayer::s_PlayerEdict = NULL; - - -inline bool ShouldRunCommandsInContext( const CCommandContext *ctx ) -{ - // TODO: This should be enabled at some point. If usercmds can run while paused, then - // they can create entities which will never die and it will fill up the entity list. -#ifdef NO_USERCMDS_DURING_PAUSE - return !ctx->paused || sv_noclipduringpause.GetInt(); -#else - return true; -#endif -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CBaseViewModel -//----------------------------------------------------------------------------- -CBaseViewModel *CBasePlayer::GetViewModel( int index /*= 0*/ ) -{ - Assert( index >= 0 && index < MAX_VIEWMODELS ); - return m_hViewModel[ index ].Get(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::CreateViewModel( int index /*=0*/ ) -{ - Assert( index >= 0 && index < MAX_VIEWMODELS ); - - if ( GetViewModel( index ) ) - return; - - CBaseViewModel *vm = ( CBaseViewModel * )CreateEntityByName( "viewmodel" ); - if ( vm ) - { - vm->SetAbsOrigin( GetAbsOrigin() ); - vm->SetOwner( this ); - vm->SetIndex( index ); - DispatchSpawn( vm ); - vm->FollowEntity( this ); - m_hViewModel.Set( index, vm ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::DestroyViewModels( void ) -{ - int i; - for ( i = MAX_VIEWMODELS - 1; i >= 0; i-- ) - { - CBaseViewModel *vm = GetViewModel( i ); - if ( !vm ) - continue; - - UTIL_Remove( vm ); - m_hViewModel.Set( i, NULL ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Static member function to create a player of the specified class -// Input : *className - -// *ed - -// Output : CBasePlayer -//----------------------------------------------------------------------------- -CBasePlayer *CBasePlayer::CreatePlayer( const char *className, edict_t *ed ) -{ - CBasePlayer *player; - CBasePlayer::s_PlayerEdict = ed; - player = ( CBasePlayer * )CreateEntityByName( className ); - return player; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -CBasePlayer::CBasePlayer( ) -{ - AddEFlags( EFL_NO_AUTO_EDICT_ATTACH ); - -#ifdef _DEBUG - m_vecAutoAim.Init(); - m_vecAdditionalPVSOrigin.Init(); - m_vecCameraPVSOrigin.Init(); - m_DmgOrigin.Init(); - m_vecLadderNormal.Init(); - - m_oldOrigin.Init(); - m_vecSmoothedVelocity.Init(); -#endif - - if ( s_PlayerEdict ) - { - // take the assigned edict_t and attach it - Assert( s_PlayerEdict != NULL ); - NetworkProp()->AttachEdict( s_PlayerEdict ); - s_PlayerEdict = NULL; - } - - m_flFlashTime = -1; - pl.fixangle = FIXANGLE_ABSOLUTE; - pl.hltv = false; - pl.frags = 0; - pl.deaths = 0; - - m_szNetname[0] = '\0'; - - m_iHealth = 0; - Weapon_SetLast( NULL ); - m_bitsDamageType = 0; - - m_bForceOrigin = false; - m_hVehicle = NULL; - m_pCurrentCommand = NULL; - - // Setup our default FOV - m_iDefaultFOV = g_pGameRules->DefaultFOV(); - - m_hZoomOwner = NULL; - - m_nUpdateRate = 20; // cl_updaterate defualt - m_fLerpTime = 0.1f; // cl_interp default - m_bPredictWeapons = true; - m_bLagCompensation = false; - m_flLaggedMovementValue = 1.0f; - m_StuckLast = 0; - m_impactEnergyScale = 1.0f; - m_fLastPlayerTalkTime = 0.0f; - m_PlayerInfo.SetParent( this ); - - ResetObserverMode(); - - m_surfaceProps = 0; - m_pSurfaceData = NULL; - m_surfaceFriction = 1.0f; - m_chTextureType = 0; - m_chPreviousTextureType = 0; - - m_iSuicideCustomKillFlags = 0; - m_fDelay = 0.0f; - m_fReplayEnd = -1; - m_iReplayEntity = 0; - - m_autoKickDisabled = false; - - m_nNumCrouches = 0; - m_bDuckToggled = false; - m_bPhysicsWasFrozen = false; - - // Used to mask off buttons - m_afButtonDisabled = 0; - m_afButtonForced = 0; - - m_nBodyPitchPoseParam = -1; - m_flForwardMove = 0; - m_flSideMove = 0; -} - -CBasePlayer::~CBasePlayer( ) -{ - VPhysicsDestroyObject(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CBasePlayer::UpdateOnRemove( void ) -{ - VPhysicsDestroyObject(); - - // Remove him from his current team - if ( GetTeam() ) - { - GetTeam()->RemovePlayer( this ); - } - - // Chain at end to mimic destructor unwind order - BaseClass::UpdateOnRemove(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : **pvs - -// **pas - -//----------------------------------------------------------------------------- -void CBasePlayer::SetupVisibility( CBaseEntity *pViewEntity, unsigned char *pvs, int pvssize ) -{ - // If we have a viewentity, we don't add the player's origin. - if ( pViewEntity ) - return; - - Vector org; - org = EyePosition(); - - engine->AddOriginToPVS( org ); -} - -int CBasePlayer::UpdateTransmitState() -{ - // always call ShouldTransmit() for players - return SetTransmitState( FL_EDICT_FULLCHECK ); -} - -int CBasePlayer::ShouldTransmit( const CCheckTransmitInfo *pInfo ) -{ - // Allow me to introduce myself to, err, myself. - // I.e., always update the recipient player data even if it's nodraw (first person mode) - if ( pInfo->m_pClientEnt == edict() ) - { - return FL_EDICT_ALWAYS; - } - - // when HLTV is connected and spectators press +USE, they - // signal that they are recording a interesting scene - // so transmit these 'cameramans' to the HLTV client - if ( HLTVDirector()->GetCameraMan() == entindex() ) - { - CBaseEntity *pRecipientEntity = CBaseEntity::Instance( pInfo->m_pClientEnt ); - - Assert( pRecipientEntity->IsPlayer() ); - - CBasePlayer *pRecipientPlayer = static_cast( pRecipientEntity ); - if ( pRecipientPlayer->IsHLTV() ) - { - // HACK force calling RecomputePVSInformation to update PVS data - NetworkProp()->AreaNum(); - return FL_EDICT_ALWAYS; - } - } - - // Transmit for a short time after death and our death anim finishes so ragdolls can access reliable player data. - // Note that if m_flDeathAnimTime is never set, as long as m_lifeState is set to LIFE_DEAD after dying, this - // test will act as if the death anim is finished. - if ( IsEffectActive( EF_NODRAW ) || ( IsObserver() && ( gpGlobals->curtime - m_flDeathTime > 0.5 ) && - ( m_lifeState == LIFE_DEAD ) && ( gpGlobals->curtime - m_flDeathAnimTime > 0.5 ) ) ) - { - return FL_EDICT_DONTSEND; - } - - return BaseClass::ShouldTransmit( pInfo ); -} - - -bool CBasePlayer::WantsLagCompensationOnEntity( const CBasePlayer *pPlayer, const CUserCmd *pCmd, const CBitVec *pEntityTransmitBits ) const -{ - // Team members shouldn't be adjusted unless friendly fire is on. - if ( !friendlyfire.GetInt() && pPlayer->GetTeamNumber() == GetTeamNumber() ) - return false; - - // If this entity hasn't been transmitted to us and acked, then don't bother lag compensating it. - if ( pEntityTransmitBits && !pEntityTransmitBits->Get( pPlayer->entindex() ) ) - return false; - - const Vector &vMyOrigin = GetAbsOrigin(); - const Vector &vHisOrigin = pPlayer->GetAbsOrigin(); - - // get max distance player could have moved within max lag compensation time, - // multiply by 1.5 to to avoid "dead zones" (sqrt(2) would be the exact value) - float maxDistance = 1.5 * pPlayer->MaxSpeed() * sv_maxunlag.GetFloat(); - - // If the player is within this distance, lag compensate them in case they're running past us. - if ( vHisOrigin.DistTo( vMyOrigin ) < maxDistance ) - return true; - - // If their origin is not within a 45 degree cone in front of us, no need to lag compensate. - Vector vForward; - AngleVectors( pCmd->viewangles, &vForward ); - - Vector vDiff = vHisOrigin - vMyOrigin; - VectorNormalize( vDiff ); - - float flCosAngle = 0.707107f; // 45 degree angle - if ( vForward.Dot( vDiff ) < flCosAngle ) - return false; - - return true; -} - -void CBasePlayer::PauseBonusProgress( bool bPause ) -{ - m_bPauseBonusProgress = bPause; -} - -void CBasePlayer::SetBonusProgress( int iBonusProgress ) -{ - if ( !m_bPauseBonusProgress ) - m_iBonusProgress = iBonusProgress; -} - -void CBasePlayer::SetBonusChallenge( int iBonusChallenge ) -{ - m_iBonusChallenge = iBonusChallenge; -} - - -//----------------------------------------------------------------------------- -// Sets the view angles -//----------------------------------------------------------------------------- -void CBasePlayer::SnapEyeAngles( const QAngle &viewAngles ) -{ - pl.v_angle = viewAngles; - pl.fixangle = FIXANGLE_ABSOLUTE; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iSpeed - -// iMax - -// Output : int -//----------------------------------------------------------------------------- -int TrainSpeed(int iSpeed, int iMax) -{ - float fSpeed, fMax; - int iRet = 0; - - fMax = (float)iMax; - fSpeed = iSpeed; - - fSpeed = fSpeed/fMax; - - if (iSpeed < 0) - iRet = TRAIN_BACK; - else if (iSpeed == 0) - iRet = TRAIN_NEUTRAL; - else if (fSpeed < 0.33) - iRet = TRAIN_SLOW; - else if (fSpeed < 0.66) - iRet = TRAIN_MEDIUM; - else - iRet = TRAIN_FAST; - - return iRet; -} - -void CBasePlayer::DeathSound( const CTakeDamageInfo &info ) -{ - // temporarily using pain sounds for death sounds - - // Did we die from falling? - if ( m_bitsDamageType & DMG_FALL ) - { - // They died in the fall. Play a splat sound. - EmitSound( "Player.FallGib" ); - } - else - { - EmitSound( "Player.Death" ); - } - - // play one of the suit death alarms - if ( IsSuitEquipped() ) - { - UTIL_EmitGroupnameSuit(edict(), "HEV_DEAD"); - } -} - -// override takehealth -// bitsDamageType indicates type of damage healed. - -int CBasePlayer::TakeHealth( float flHealth, int bitsDamageType ) -{ - // clear out any damage types we healed. - // UNDONE: generic health should not heal any - // UNDONE: time-based damage - if (m_takedamage) - { - int bitsDmgTimeBased = g_pGameRules->Damage_GetTimeBased(); - m_bitsDamageType &= ~( bitsDamageType & ~bitsDmgTimeBased ); - } - - // I disabled reporting history into the dbghist because it was super spammy. - // But, if you need to reenable it, the code is below in the "else" clause. -#if 1 // #ifdef DISABLE_DEBUG_HISTORY - return BaseClass::TakeHealth (flHealth, bitsDamageType); -#else - const int healingTaken = BaseClass::TakeHealth(flHealth,bitsDamageType); - char buf[256]; - Q_snprintf(buf, 256, "[%f] Player %s healed for %d with damagetype %X\n", gpGlobals->curtime, GetDebugName(), healingTaken, bitsDamageType); - ADD_DEBUG_HISTORY( HISTORY_PLAYER_DAMAGE, buf ); - - return healingTaken; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Draw all overlays (should be implemented in cascade by subclass to add -// any additional non-text overlays) -// Input : -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -void CBasePlayer::DrawDebugGeometryOverlays(void) -{ - // -------------------------------------------------------- - // If in buddha mode and dead draw lines to indicate death - // -------------------------------------------------------- - if ((m_debugOverlays & OVERLAY_BUDDHA_MODE) && m_iHealth == 1) - { - Vector vBodyDir = BodyDirection2D( ); - Vector eyePos = EyePosition() + vBodyDir*10.0; - Vector vUp = Vector(0,0,8); - Vector vSide; - CrossProduct( vBodyDir, vUp, vSide); - NDebugOverlay::Line(eyePos+vSide+vUp, eyePos-vSide-vUp, 255,0,0, false, 0); - NDebugOverlay::Line(eyePos+vSide-vUp, eyePos-vSide+vUp, 255,0,0, false, 0); - } - BaseClass::DrawDebugGeometryOverlays(); -} - -//========================================================= -// TraceAttack -//========================================================= -void CBasePlayer::TraceAttack( const CTakeDamageInfo &inputInfo, const Vector &vecDir, trace_t *ptr ) -{ - if ( m_takedamage ) - { - CTakeDamageInfo info = inputInfo; - - if ( info.GetAttacker() ) - { - // -------------------------------------------------- - // If an NPC check if friendly fire is disallowed - // -------------------------------------------------- - CAI_BaseNPC *pNPC = info.GetAttacker()->MyNPCPointer(); - if ( pNPC && (pNPC->CapabilitiesGet() & bits_CAP_NO_HIT_PLAYER) && pNPC->IRelationType( this ) != D_HT ) - return; - - // Prevent team damage here so blood doesn't appear - if ( info.GetAttacker()->IsPlayer() ) - { - if ( !g_pGameRules->FPlayerCanTakeDamage( this, info.GetAttacker() ) ) - return; - } - } - - SetLastHitGroup( ptr->hitgroup ); - - - switch ( ptr->hitgroup ) - { - case HITGROUP_GENERIC: - break; - case HITGROUP_HEAD: - info.ScaleDamage( sk_player_head.GetFloat() ); - break; - case HITGROUP_CHEST: - info.ScaleDamage( sk_player_chest.GetFloat() ); - break; - case HITGROUP_STOMACH: - info.ScaleDamage( sk_player_stomach.GetFloat() ); - break; - case HITGROUP_LEFTARM: - case HITGROUP_RIGHTARM: - info.ScaleDamage( sk_player_arm.GetFloat() ); - break; - case HITGROUP_LEFTLEG: - case HITGROUP_RIGHTLEG: - info.ScaleDamage( sk_player_leg.GetFloat() ); - break; - default: - break; - } - -#ifdef HL2_EPISODIC - // If this damage type makes us bleed, then do so - bool bShouldBleed = !g_pGameRules->Damage_ShouldNotBleed( info.GetDamageType() ); - if ( bShouldBleed ) -#endif - { - SpawnBlood(ptr->endpos, vecDir, BloodColor(), info.GetDamage());// a little surface blood. - TraceBleed( info.GetDamage(), vecDir, ptr, info.GetDamageType() ); - } - - AddMultiDamage( info, this ); - } -} - -//------------------------------------------------------------------------------ -// Purpose : Do some kind of damage effect for the type of damage -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBasePlayer::DamageEffect(float flDamage, int fDamageType) -{ - if (fDamageType & DMG_CRUSH) - { - //Red damage indicator - color32 red = {128,0,0,128}; - UTIL_ScreenFade( this, red, 1.0f, 0.1f, FFADE_IN ); - } - else if (fDamageType & DMG_DROWN) - { - //Red damage indicator - color32 blue = {0,0,128,128}; - UTIL_ScreenFade( this, blue, 1.0f, 0.1f, FFADE_IN ); - } - else if (fDamageType & DMG_SLASH) - { - // If slash damage shoot some blood - SpawnBlood(EyePosition(), g_vecAttackDir, BloodColor(), flDamage); - } - else if (fDamageType & DMG_PLASMA) - { - // Blue screen fade - color32 blue = {0,0,255,100}; - UTIL_ScreenFade( this, blue, 0.2, 0.4, FFADE_MODULATE ); - - // Very small screen shake - ViewPunch(QAngle(random->RandomFloat(-0.1f,0.1f), random->RandomFloat(-0.1f,0.1f), random->RandomFloat(-0.1f,0.1f))); - - // Burn sound - EmitSound( "Player.PlasmaDamage" ); - } - else if (fDamageType & DMG_SONIC) - { - // Sonic damage sound - EmitSound( "Player.SonicDamage" ); - } - else if ( fDamageType & DMG_BULLET ) - { - EmitSound( "Flesh.BulletImpact" ); - } -} - -/* - Take some damage. - NOTE: each call to OnTakeDamage with bitsDamageType set to a time-based damage - type will cause the damage time countdown to be reset. Thus the ongoing effects of poison, radiation - etc are implemented with subsequent calls to OnTakeDamage using DMG_GENERIC. -*/ - -// Old values -#define OLD_ARMOR_RATIO 0.2 // Armor Takes 80% of the damage -#define OLD_ARMOR_BONUS 0.5 // Each Point of Armor is work 1/x points of health - -// New values -#define ARMOR_RATIO 0.2 -#define ARMOR_BONUS 1.0 - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CBasePlayer::ShouldTakeDamageInCommentaryMode( const CTakeDamageInfo &inputInfo ) -{ - // Only ignore damage when we're listening to a commentary node - if ( !IsListeningToCommentary() ) - return true; - - // Allow SetHealth inputs to kill player. - if ( inputInfo.GetInflictor() == this && inputInfo.GetAttacker() == this ) - return true; - -#ifdef PORTAL - if ( inputInfo.GetDamageType() & DMG_ACID ) - return true; -#endif - - // In commentary, ignore all damage except for falling and leeches - if ( !(inputInfo.GetDamageType() & (DMG_BURN | DMG_PLASMA | DMG_FALL | DMG_CRUSH)) && inputInfo.GetDamageType() != DMG_GENERIC ) - return false; - - // We let DMG_CRUSH pass the check above so that we can check here for stress damage. Deny the CRUSH damage if there is no attacker, - // or if the attacker isn't a BSP model. Therefore, we're allowing any CRUSH damage done by a BSP model. - if ( (inputInfo.GetDamageType() & DMG_CRUSH) && ( inputInfo.GetAttacker() == NULL || !inputInfo.GetAttacker()->IsBSPModel() ) ) - return false; - - return true; -} - -int CBasePlayer::OnTakeDamage( const CTakeDamageInfo &inputInfo ) -{ - // have suit diagnose the problem - ie: report damage type - int bitsDamage = inputInfo.GetDamageType(); - int ffound = true; - int fmajor; - int fcritical; - int fTookDamage; - int ftrivial; - float flRatio; - float flBonus; - float flHealthPrev = m_iHealth; - - CTakeDamageInfo info = inputInfo; - - IServerVehicle *pVehicle = GetVehicle(); - if ( pVehicle ) - { - // Let the vehicle decide if we should take this damage or not - if ( pVehicle->PassengerShouldReceiveDamage( info ) == false ) - return 0; - } - - if ( IsInCommentaryMode() ) - { - if( !ShouldTakeDamageInCommentaryMode( info ) ) - return 0; - } - - if ( GetFlags() & FL_GODMODE ) - return 0; - - if ( m_debugOverlays & OVERLAY_BUDDHA_MODE ) - { - if ((m_iHealth - info.GetDamage()) <= 0) - { - m_iHealth = 1; - return 0; - } - } - - // Early out if there's no damage - if ( !info.GetDamage() ) - return 0; - - if( old_armor.GetBool() ) - { - flBonus = OLD_ARMOR_BONUS; - flRatio = OLD_ARMOR_RATIO; - } - else - { - flBonus = ARMOR_BONUS; - flRatio = ARMOR_RATIO; - } - - if ( ( info.GetDamageType() & DMG_BLAST ) && g_pGameRules->IsMultiplayer() ) - { - // blasts damage armor more. - flBonus *= 2; - } - - // Already dead - if ( !IsAlive() ) - return 0; - // go take the damage first - - - if ( !g_pGameRules->FPlayerCanTakeDamage( this, info.GetAttacker() ) ) - { - // Refuse the damage - return 0; - } - - // print to console if the appropriate cvar is set -#ifdef DISABLE_DEBUG_HISTORY - if (player_debug_print_damage.GetBool() && info.GetDamage() > 0) -#endif - { - char dmgtype[64]; - CTakeDamageInfo::DebugGetDamageTypeString( info.GetDamageType(), dmgtype, 512 ); - char outputString[256]; - Q_snprintf( outputString, 256, "%f: Player %s at [%0.2f %0.2f %0.2f] took %f damage from %s, type %s\n", gpGlobals->curtime, GetDebugName(), - GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z, info.GetDamage(), info.GetInflictor()->GetDebugName(), dmgtype ); - - //Msg( "%f: Player %s at [%0.2f %0.2f %0.2f] took %f damage from %s, type %s\n", gpGlobals->curtime, GetDebugName(), - // GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z, info.GetDamage(), info.GetInflictor()->GetDebugName(), dmgtype ); - - ADD_DEBUG_HISTORY( HISTORY_PLAYER_DAMAGE, outputString ); -#ifndef DISABLE_DEBUG_HISTORY - if ( player_debug_print_damage.GetBool() ) // if we're not in here just for the debug history -#endif - { - Msg(outputString); - } - } - - // keep track of amount of damage last sustained - m_lastDamageAmount = (int)info.GetDamage(); - - // Armor. - if (m_ArmorValue && !(info.GetDamageType() & (DMG_FALL | DMG_DROWN | DMG_POISON | DMG_RADIATION)) )// armor doesn't protect against fall or drown damage! - { - float flNew = info.GetDamage() * flRatio; - - float flArmor; - - flArmor = (info.GetDamage() - flNew) * flBonus; - - if( !old_armor.GetBool() ) - { - if( flArmor < 1.0 ) - { - flArmor = 1.0; - } - } - - // Does this use more armor than we have? - if (flArmor > m_ArmorValue) - { - flArmor = m_ArmorValue; - flArmor *= (1/flBonus); - flNew = info.GetDamage() - flArmor; - m_DmgSave = m_ArmorValue; - m_ArmorValue = 0; - } - else - { - m_DmgSave = flArmor; - m_ArmorValue -= flArmor; - } - - info.SetDamage( flNew ); - } - - // this cast to INT is critical!!! If a player ends up with 0.5 health, the engine will get that - // as an int (zero) and think the player is dead! (this will incite a clientside screentilt, etc) - - // NOTENOTE: jdw - We are now capable of retaining the mantissa of this damage value and deferring its application - - // info.SetDamage( (int)info.GetDamage() ); - - // Call up to the base class - fTookDamage = BaseClass::OnTakeDamage( info ); - - // Early out if the base class took no damage - if ( !fTookDamage ) - return 0; - - // add to the damage total for clients, which will be sent as a single - // message at the end of the frame - // todo: remove after combining shotgun blasts? - if ( info.GetInflictor() && info.GetInflictor()->edict() ) - m_DmgOrigin = info.GetInflictor()->GetAbsOrigin(); - - m_DmgTake += (int)info.GetDamage(); - - // Reset damage time countdown for each type of time based damage player just sustained - for (int i = 0; i < CDMG_TIMEBASED; i++) - { - // Make sure the damage type is really time-based. - // This is kind of hacky but necessary until we setup DamageType as an enum. - int iDamage = ( DMG_PARALYZE << i ); - if ( ( info.GetDamageType() & iDamage ) && g_pGameRules->Damage_IsTimeBased( iDamage ) ) - { - m_rgbTimeBasedDamage[i] = 0; - } - } - - // Display any effect associate with this damage type - DamageEffect(info.GetDamage(),bitsDamage); - - // how bad is it, doc? - ftrivial = (m_iHealth > 75 || m_lastDamageAmount < 5); - fmajor = (m_lastDamageAmount > 25); - fcritical = (m_iHealth < 30); - - // handle all bits set in this damage message, - // let the suit give player the diagnosis - - // UNDONE: add sounds for types of damage sustained (ie: burn, shock, slash ) - - // UNDONE: still need to record damage and heal messages for the following types - - // DMG_BURN - // DMG_FREEZE - // DMG_BLAST - // DMG_SHOCK - - m_bitsDamageType |= bitsDamage; // Save this so we can report it to the client - m_bitsHUDDamage = -1; // make sure the damage bits get resent - - while (fTookDamage && (!ftrivial || g_pGameRules->Damage_IsTimeBased( bitsDamage ) ) && ffound && bitsDamage) - { - ffound = false; - - if (bitsDamage & DMG_CLUB) - { - if (fmajor) - SetSuitUpdate("!HEV_DMG4", false, SUIT_NEXT_IN_30SEC); // minor fracture - bitsDamage &= ~DMG_CLUB; - ffound = true; - } - if (bitsDamage & (DMG_FALL | DMG_CRUSH)) - { - if (fmajor) - SetSuitUpdate("!HEV_DMG5", false, SUIT_NEXT_IN_30SEC); // major fracture - else - SetSuitUpdate("!HEV_DMG4", false, SUIT_NEXT_IN_30SEC); // minor fracture - - bitsDamage &= ~(DMG_FALL | DMG_CRUSH); - ffound = true; - } - - if (bitsDamage & DMG_BULLET) - { - if (m_lastDamageAmount > 5) - SetSuitUpdate("!HEV_DMG6", false, SUIT_NEXT_IN_30SEC); // blood loss detected - //else - // SetSuitUpdate("!HEV_DMG0", false, SUIT_NEXT_IN_30SEC); // minor laceration - - bitsDamage &= ~DMG_BULLET; - ffound = true; - } - - if (bitsDamage & DMG_SLASH) - { - if (fmajor) - SetSuitUpdate("!HEV_DMG1", false, SUIT_NEXT_IN_30SEC); // major laceration - else - SetSuitUpdate("!HEV_DMG0", false, SUIT_NEXT_IN_30SEC); // minor laceration - - bitsDamage &= ~DMG_SLASH; - ffound = true; - } - - if (bitsDamage & DMG_SONIC) - { - if (fmajor) - SetSuitUpdate("!HEV_DMG2", false, SUIT_NEXT_IN_1MIN); // internal bleeding - bitsDamage &= ~DMG_SONIC; - ffound = true; - } - - if (bitsDamage & (DMG_POISON | DMG_PARALYZE)) - { - if (bitsDamage & DMG_POISON) - { - m_nPoisonDmg += (int)info.GetDamage(); - m_tbdPrev = gpGlobals->curtime; - m_rgbTimeBasedDamage[itbd_PoisonRecover] = 0; - } - - SetSuitUpdate("!HEV_DMG3", false, SUIT_NEXT_IN_1MIN); // blood toxins detected - bitsDamage &= ~( DMG_POISON | DMG_PARALYZE ); - ffound = true; - } - - if (bitsDamage & DMG_ACID) - { - SetSuitUpdate("!HEV_DET1", false, SUIT_NEXT_IN_1MIN); // hazardous chemicals detected - bitsDamage &= ~DMG_ACID; - ffound = true; - } - - if (bitsDamage & DMG_NERVEGAS) - { - SetSuitUpdate("!HEV_DET0", false, SUIT_NEXT_IN_1MIN); // biohazard detected - bitsDamage &= ~DMG_NERVEGAS; - ffound = true; - } - - if (bitsDamage & DMG_RADIATION) - { - SetSuitUpdate("!HEV_DET2", false, SUIT_NEXT_IN_1MIN); // radiation detected - bitsDamage &= ~DMG_RADIATION; - ffound = true; - } - if (bitsDamage & DMG_SHOCK) - { - bitsDamage &= ~DMG_SHOCK; - ffound = true; - } - } - - float flPunch = -2; - - if( hl2_episodic.GetBool() && info.GetAttacker() && !FInViewCone( info.GetAttacker() ) ) - { - if( info.GetDamage() > 10.0f ) - flPunch = -10; - else - flPunch = RandomFloat( -5, -7 ); - } - - m_Local.m_vecPunchAngle.SetX( flPunch ); - - if (fTookDamage && !ftrivial && fmajor && flHealthPrev >= 75) - { - // first time we take major damage... - // turn automedic on if not on - SetSuitUpdate("!HEV_MED1", false, SUIT_NEXT_IN_30MIN); // automedic on - - // give morphine shot if not given recently - SetSuitUpdate("!HEV_HEAL7", false, SUIT_NEXT_IN_30MIN); // morphine shot - } - - if (fTookDamage && !ftrivial && fcritical && flHealthPrev < 75) - { - - // already took major damage, now it's critical... - if (m_iHealth < 6) - SetSuitUpdate("!HEV_HLTH3", false, SUIT_NEXT_IN_10MIN); // near death - else if (m_iHealth < 20) - SetSuitUpdate("!HEV_HLTH2", false, SUIT_NEXT_IN_10MIN); // health critical - - // give critical health warnings - if (!random->RandomInt(0,3) && flHealthPrev < 50) - SetSuitUpdate("!HEV_DMG7", false, SUIT_NEXT_IN_5MIN); //seek medical attention - } - - // if we're taking time based damage, warn about its continuing effects - if (fTookDamage && g_pGameRules->Damage_IsTimeBased( info.GetDamageType() ) && flHealthPrev < 75) - { - if (flHealthPrev < 50) - { - if (!random->RandomInt(0,3)) - SetSuitUpdate("!HEV_DMG7", false, SUIT_NEXT_IN_5MIN); //seek medical attention - } - else - SetSuitUpdate("!HEV_HLTH1", false, SUIT_NEXT_IN_10MIN); // health dropping - } - - // Do special explosion damage effect - if ( bitsDamage & DMG_BLAST ) - { - OnDamagedByExplosion( info ); - } - - return fTookDamage; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -// damageAmount - -//----------------------------------------------------------------------------- -#define MIN_SHOCK_AND_CONFUSION_DAMAGE 30.0f -#define MIN_EAR_RINGING_DISTANCE 240.0f // 20 feet - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -//----------------------------------------------------------------------------- -void CBasePlayer::OnDamagedByExplosion( const CTakeDamageInfo &info ) -{ - float lastDamage = info.GetDamage(); - - float distanceFromPlayer = 9999.0f; - - CBaseEntity *inflictor = info.GetInflictor(); - if ( inflictor ) - { - Vector delta = GetAbsOrigin() - inflictor->GetAbsOrigin(); - distanceFromPlayer = delta.Length(); - } - - bool ear_ringing = distanceFromPlayer < MIN_EAR_RINGING_DISTANCE ? true : false; - bool shock = lastDamage >= MIN_SHOCK_AND_CONFUSION_DAMAGE; - - if ( !shock && !ear_ringing ) - return; - - int effect = shock ? - random->RandomInt( 35, 37 ) : - random->RandomInt( 32, 34 ); - - CSingleUserRecipientFilter user( this ); - enginesound->SetPlayerDSP( user, effect, false ); -} - -//========================================================= -// PackDeadPlayerItems - call this when a player dies to -// pack up the appropriate weapons and ammo items, and to -// destroy anything that shouldn't be packed. -// -// This is pretty brute force :( -//========================================================= -void CBasePlayer::PackDeadPlayerItems( void ) -{ - int iWeaponRules; - int iAmmoRules; - int i; - CBaseCombatWeapon *rgpPackWeapons[ 20 ];// 20 hardcoded for now. How to determine exactly how many weapons we have? - int iPackAmmo[ MAX_AMMO_SLOTS + 1]; - int iPW = 0;// index into packweapons array - int iPA = 0;// index into packammo array - - memset(rgpPackWeapons, 0, sizeof(rgpPackWeapons) ); - memset(iPackAmmo, -1, sizeof(iPackAmmo) ); - - // get the game rules - iWeaponRules = g_pGameRules->DeadPlayerWeapons( this ); - iAmmoRules = g_pGameRules->DeadPlayerAmmo( this ); - - if ( iWeaponRules == GR_PLR_DROP_GUN_NO && iAmmoRules == GR_PLR_DROP_AMMO_NO ) - { - // nothing to pack. Remove the weapons and return. Don't call create on the box! - RemoveAllItems( true ); - return; - } - -// go through all of the weapons and make a list of the ones to pack - for ( i = 0 ; i < WeaponCount() ; i++ ) - { - // there's a weapon here. Should I pack it? - CBaseCombatWeapon *pPlayerItem = GetWeapon( i ); - if ( pPlayerItem ) - { - switch( iWeaponRules ) - { - case GR_PLR_DROP_GUN_ACTIVE: - if ( GetActiveWeapon() && pPlayerItem == GetActiveWeapon() ) - { - // this is the active item. Pack it. - rgpPackWeapons[ iPW++ ] = pPlayerItem; - } - break; - - case GR_PLR_DROP_GUN_ALL: - rgpPackWeapons[ iPW++ ] = pPlayerItem; - break; - - default: - break; - } - } - } - -// now go through ammo and make a list of which types to pack. - if ( iAmmoRules != GR_PLR_DROP_AMMO_NO ) - { - for ( i = 0 ; i < MAX_AMMO_SLOTS ; i++ ) - { - if ( GetAmmoCount( i ) > 0 ) - { - // player has some ammo of this type. - switch ( iAmmoRules ) - { - case GR_PLR_DROP_AMMO_ALL: - iPackAmmo[ iPA++ ] = i; - break; - - case GR_PLR_DROP_AMMO_ACTIVE: - // WEAPONTODO: Make this work - /* - if ( GetActiveWeapon() && i == GetActiveWeapon()->m_iPrimaryAmmoType ) - { - // this is the primary ammo type for the active weapon - iPackAmmo[ iPA++ ] = i; - } - else if ( GetActiveWeapon() && i == GetActiveWeapon()->m_iSecondaryAmmoType ) - { - // this is the secondary ammo type for the active weapon - iPackAmmo[ iPA++ ] = i; - } - */ - break; - - default: - break; - } - } - } - } - - RemoveAllItems( true );// now strip off everything that wasn't handled by the code above. -} - -void CBasePlayer::RemoveAllItems( bool removeSuit ) -{ - if (GetActiveWeapon()) - { - ResetAutoaim( ); - GetActiveWeapon()->Holster( ); - } - - Weapon_SetLast( NULL ); - RemoveAllWeapons(); - RemoveAllAmmo(); - - if ( removeSuit ) - { - RemoveSuit(); - } - - UpdateClientData(); -} - -bool CBasePlayer::IsDead() const -{ - return m_lifeState == LIFE_DEAD; -} - -static float DamageForce( const Vector &size, float damage ) -{ - float force = damage * ((32 * 32 * 72.0) / (size.x * size.y * size.z)) * 5; - - if ( force > 1000.0) - { - force = 1000.0; - } - - return force; -} - - -const impactdamagetable_t &CBasePlayer::GetPhysicsImpactDamageTable() -{ - return gDefaultPlayerImpactDamageTable; -} - - -int CBasePlayer::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - // set damage type sustained - m_bitsDamageType |= info.GetDamageType(); - - if ( !BaseClass::OnTakeDamage_Alive( info ) ) - return 0; - - CBaseEntity * attacker = info.GetAttacker(); - - if ( !attacker ) - return 0; - - Vector vecDir = vec3_origin; - if ( info.GetInflictor() ) - { - vecDir = info.GetInflictor()->WorldSpaceCenter() - Vector ( 0, 0, 10 ) - WorldSpaceCenter(); - VectorNormalize( vecDir ); - } - - if ( info.GetInflictor() && (GetMoveType() == MOVETYPE_WALK) && - ( !attacker->IsSolidFlagSet(FSOLID_TRIGGER)) ) - { - Vector force = vecDir * -DamageForce( WorldAlignSize(), info.GetBaseDamage() ); - if ( force.z > 250.0f ) - { - force.z = 250.0f; - } - ApplyAbsVelocityImpulse( force ); - } - - // fire global game event - - IGameEvent * event = gameeventmanager->CreateEvent( "player_hurt" ); - if ( event ) - { - event->SetInt("userid", GetUserID() ); - event->SetInt("health", MAX(0, m_iHealth) ); - event->SetInt("priority", 5 ); // HLTV event priority, not transmitted - - if ( attacker->IsPlayer() ) - { - CBasePlayer *player = ToBasePlayer( attacker ); - event->SetInt("attacker", player->GetUserID() ); // hurt by other player - } - else - { - event->SetInt("attacker", 0 ); // hurt by "world" - } - - gameeventmanager->FireEvent( event ); - } - - // Insert a combat sound so that nearby NPCs hear battle - if ( attacker->IsNPC() ) - { - CSoundEnt::InsertSound( SOUND_COMBAT, GetAbsOrigin(), 512, 0.5, this );//<>//magic number - } - - return 1; -} - - -void CBasePlayer::Event_Killed( const CTakeDamageInfo &info ) -{ - CSound *pSound; - - if ( Hints() ) - { - Hints()->ResetHintTimers(); - } - - g_pGameRules->PlayerKilled( this, info ); - - gamestats->Event_PlayerKilled( this, info ); - - RumbleEffect( RUMBLE_STOP_ALL, 0, RUMBLE_FLAGS_NONE ); - - ClearUseEntity(); - - // this client isn't going to be thinking for a while, so reset the sound until they respawn - pSound = CSoundEnt::SoundPointerForIndex( CSoundEnt::ClientSoundIndex( edict() ) ); - { - if ( pSound ) - { - pSound->Reset(); - } - } - - // don't let the status bar glitch for players with <0 health. - if (m_iHealth < -99) - { - m_iHealth = 0; - } - - // holster the current weapon - if ( GetActiveWeapon() ) - { - GetActiveWeapon()->Holster(); - } - - SetAnimation( PLAYER_DIE ); - - SetViewOffset( VEC_DEAD_VIEWHEIGHT ); - m_lifeState = LIFE_DYING; - - pl.deadflag = true; - AddSolidFlags( FSOLID_NOT_SOLID ); - // force contact points to get flushed if no longer valid - // UNDONE: Always do this on RecheckCollisionFilter() ? - IPhysicsObject *pObject = VPhysicsGetObject(); - if ( pObject ) - { - pObject->RecheckContactPoints(); - } - - SetMoveType( MOVETYPE_FLYGRAVITY ); - SetGroundEntity( NULL ); - - // clear out the suit message cache so we don't keep chattering - SetSuitUpdate(NULL, false, 0); - - // reset FOV - SetFOV( this, 0 ); - - if ( FlashlightIsOn() ) - { - FlashlightTurnOff(); - } - - m_flDeathTime = gpGlobals->curtime; - - // only count alive players - if (m_lastNavArea) - { - m_lastNavArea->DecrementPlayerCount( GetTeamNumber() ); - m_lastNavArea = NULL; - } - - BaseClass::Event_Killed( info ); -} - -void CBasePlayer::Event_Dying() -{ - // NOT GIBBED, RUN THIS CODE - - CTakeDamageInfo info; - DeathSound( info ); - - // The dead body rolls out of the vehicle. - if ( IsInAVehicle() ) - { - LeaveVehicle(); - } - - QAngle angles = GetLocalAngles(); - - angles.x = 0; - angles.z = 0; - - SetLocalAngles( angles ); - - SetThink(&CBasePlayer::PlayerDeathThink); - SetNextThink( gpGlobals->curtime + 0.1f ); - BaseClass::Event_Dying(); -} - - -// Set the activity based on an event or current state -void CBasePlayer::SetAnimation( PLAYER_ANIM playerAnim ) -{ - int animDesired; - char szAnim[64]; - - float speed; - - speed = GetAbsVelocity().Length2D(); - - if (GetFlags() & (FL_FROZEN|FL_ATCONTROLS)) - { - speed = 0; - playerAnim = PLAYER_IDLE; - } - - Activity idealActivity = ACT_WALK;// TEMP!!!!! - - // This could stand to be redone. Why is playerAnim abstracted from activity? (sjb) - if (playerAnim == PLAYER_JUMP) - { - idealActivity = ACT_HOP; - } - else if (playerAnim == PLAYER_SUPERJUMP) - { - idealActivity = ACT_LEAP; - } - else if (playerAnim == PLAYER_DIE) - { - if ( m_lifeState == LIFE_ALIVE ) - { - idealActivity = GetDeathActivity(); - } - } - else if (playerAnim == PLAYER_ATTACK1) - { - if ( m_Activity == ACT_HOVER || - m_Activity == ACT_SWIM || - m_Activity == ACT_HOP || - m_Activity == ACT_LEAP || - m_Activity == ACT_DIESIMPLE ) - { - idealActivity = m_Activity; - } - else - { - idealActivity = ACT_RANGE_ATTACK1; - } - } - else if (playerAnim == PLAYER_IDLE || playerAnim == PLAYER_WALK) - { - if ( !( GetFlags() & FL_ONGROUND ) && (m_Activity == ACT_HOP || m_Activity == ACT_LEAP) ) // Still jumping - { - idealActivity = m_Activity; - } - else if ( GetWaterLevel() > 1 ) - { - if ( speed == 0 ) - idealActivity = ACT_HOVER; - else - idealActivity = ACT_SWIM; - } - else - { - idealActivity = ACT_WALK; - } - } - - - if (idealActivity == ACT_RANGE_ATTACK1) - { - if ( GetFlags() & FL_DUCKING ) // crouching - { - Q_strncpy( szAnim, "crouch_shoot_" ,sizeof(szAnim)); - } - else - { - Q_strncpy( szAnim, "ref_shoot_" ,sizeof(szAnim)); - } - Q_strncat( szAnim, m_szAnimExtension ,sizeof(szAnim), COPY_ALL_CHARACTERS ); - animDesired = LookupSequence( szAnim ); - if (animDesired == -1) - animDesired = 0; - - if ( GetSequence() != animDesired || !SequenceLoops() ) - { - SetCycle( 0 ); - } - - // Tracker 24588: In single player when firing own weapon this causes eye and punchangle to jitter - //if (!SequenceLoops()) - //{ - // AddEffects( EF_NOINTERP ); - //} - - SetActivity( idealActivity ); - ResetSequence( animDesired ); - } - else if (idealActivity == ACT_WALK) - { - if (GetActivity() != ACT_RANGE_ATTACK1 || IsActivityFinished()) - { - if ( GetFlags() & FL_DUCKING ) // crouching - { - Q_strncpy( szAnim, "crouch_aim_" ,sizeof(szAnim)); - } - else - { - Q_strncpy( szAnim, "ref_aim_" ,sizeof(szAnim)); - } - Q_strncat( szAnim, m_szAnimExtension,sizeof(szAnim), COPY_ALL_CHARACTERS ); - animDesired = LookupSequence( szAnim ); - if (animDesired == -1) - animDesired = 0; - SetActivity( ACT_WALK ); - } - else - { - animDesired = GetSequence(); - } - } - else - { - if ( GetActivity() == idealActivity) - return; - - SetActivity( idealActivity ); - - animDesired = SelectWeightedSequence( m_Activity ); - - // Already using the desired animation? - if (GetSequence() == animDesired) - return; - - ResetSequence( animDesired ); - SetCycle( 0 ); - return; - } - - // Already using the desired animation? - if (GetSequence() == animDesired) - return; - - //Msg( "Set animation to %d\n", animDesired ); - // Reset to first frame of desired animation - ResetSequence( animDesired ); - SetCycle( 0 ); -} - -/* -=========== -WaterMove -============ -*/ -#ifdef HL2_DLL - -// test for HL2 drowning damage increase (aux power used instead) -#define AIRTIME 7 // lung full of air lasts this many seconds -#define DROWNING_DAMAGE_INITIAL 10 -#define DROWNING_DAMAGE_MAX 10 - -#else - -#define AIRTIME 12 // lung full of air lasts this many seconds -#define DROWNING_DAMAGE_INITIAL 2 -#define DROWNING_DAMAGE_MAX 5 - -#endif - -void CBasePlayer::WaterMove() -{ - if ( ( GetMoveType() == MOVETYPE_NOCLIP ) && !GetMoveParent() ) - { - m_AirFinished = gpGlobals->curtime + AIRTIME; - return; - } - - if ( m_iHealth < 0 || !IsAlive() ) - { - UpdateUnderwaterState(); - return; - } - - // waterlevel 0 - not in water (WL_NotInWater) - // waterlevel 1 - feet in water (WL_Feet) - // waterlevel 2 - waist in water (WL_Waist) - // waterlevel 3 - head in water (WL_Eyes) - - if (GetWaterLevel() != WL_Eyes || CanBreatheUnderwater()) - { - // not underwater - - // play 'up for air' sound - - if (m_AirFinished < gpGlobals->curtime) - { - EmitSound( "Player.DrownStart" ); - } - - m_AirFinished = gpGlobals->curtime + AIRTIME; - m_nDrownDmgRate = DROWNING_DAMAGE_INITIAL; - - // if we took drowning damage, give it back slowly - if (m_idrowndmg > m_idrownrestored) - { - // set drowning damage bit. hack - dmg_drownrecover actually - // makes the time based damage code 'give back' health over time. - // make sure counter is cleared so we start count correctly. - - // NOTE: this actually causes the count to continue restarting - // until all drowning damage is healed. - - m_bitsDamageType |= DMG_DROWNRECOVER; - m_bitsDamageType &= ~DMG_DROWN; - m_rgbTimeBasedDamage[itbd_DrownRecover] = 0; - } - - } - else - { // fully under water - // stop restoring damage while underwater - m_bitsDamageType &= ~DMG_DROWNRECOVER; - m_rgbTimeBasedDamage[itbd_DrownRecover] = 0; - - if (m_AirFinished < gpGlobals->curtime && !(GetFlags() & FL_GODMODE) ) // drown! - { - if (m_PainFinished < gpGlobals->curtime) - { - // take drowning damage - m_nDrownDmgRate += 1; - if (m_nDrownDmgRate > DROWNING_DAMAGE_MAX) - { - m_nDrownDmgRate = DROWNING_DAMAGE_MAX; - } - - OnTakeDamage( CTakeDamageInfo( GetContainingEntity(INDEXENT(0)), GetContainingEntity(INDEXENT(0)), m_nDrownDmgRate, DMG_DROWN ) ); - m_PainFinished = gpGlobals->curtime + 1; - - // track drowning damage, give it back when - // player finally takes a breath - m_idrowndmg += m_nDrownDmgRate; - } - } - else - { - m_bitsDamageType &= ~DMG_DROWN; - } - } - - UpdateUnderwaterState(); -} - - -// true if the player is attached to a ladder -bool CBasePlayer::IsOnLadder( void ) -{ - return (GetMoveType() == MOVETYPE_LADDER); -} - - -float CBasePlayer::GetWaterJumpTime() const -{ - return m_flWaterJumpTime; -} - -void CBasePlayer::SetWaterJumpTime( float flWaterJumpTime ) -{ - m_flWaterJumpTime = flWaterJumpTime; -} - -float CBasePlayer::GetSwimSoundTime( void ) const -{ - return m_flSwimSoundTime; -} - -void CBasePlayer::SetSwimSoundTime( float flSwimSoundTime ) -{ - m_flSwimSoundTime = flSwimSoundTime; -} - -void CBasePlayer::ShowViewPortPanel( const char * name, bool bShow, KeyValues *data ) -{ - CSingleUserRecipientFilter filter( this ); - filter.MakeReliable(); - - int count = 0; - KeyValues *subkey = NULL; - - if ( data ) - { - subkey = data->GetFirstSubKey(); - while ( subkey ) - { - count++; subkey = subkey->GetNextKey(); - } - - subkey = data->GetFirstSubKey(); // reset - } - - UserMessageBegin( filter, "VGUIMenu" ); - WRITE_STRING( name ); // menu name - WRITE_BYTE( bShow?1:0 ); - WRITE_BYTE( count ); - - // write additional data (be careful not more than 192 bytes!) - while ( subkey ) - { - WRITE_STRING( subkey->GetName() ); - WRITE_STRING( subkey->GetString() ); - subkey = subkey->GetNextKey(); - } - MessageEnd(); -} - - -void CBasePlayer::PlayerDeathThink(void) -{ - float flForward; - - SetNextThink( gpGlobals->curtime + 0.1f ); - - if (GetFlags() & FL_ONGROUND) - { - flForward = GetAbsVelocity().Length() - 20; - if (flForward <= 0) - { - SetAbsVelocity( vec3_origin ); - } - else - { - Vector vecNewVelocity = GetAbsVelocity(); - VectorNormalize( vecNewVelocity ); - vecNewVelocity *= flForward; - SetAbsVelocity( vecNewVelocity ); - } - } - - if ( HasWeapons() ) - { - // we drop the guns here because weapons that have an area effect and can kill their user - // will sometimes crash coming back from CBasePlayer::Killed() if they kill their owner because the - // player class sometimes is freed. It's safer to manipulate the weapons once we know - // we aren't calling into any of their code anymore through the player pointer. - PackDeadPlayerItems(); - } - - if (GetModelIndex() && (!IsSequenceFinished()) && (m_lifeState == LIFE_DYING)) - { - StudioFrameAdvance( ); - - m_iRespawnFrames++; - if ( m_iRespawnFrames < 60 ) // animations should be no longer than this - return; - } - - if (m_lifeState == LIFE_DYING) - { - m_lifeState = LIFE_DEAD; - m_flDeathAnimTime = gpGlobals->curtime; - } - - StopAnimation(); - - AddEffects( EF_NOINTERP ); - m_flPlaybackRate = 0.0; - - int fAnyButtonDown = (m_nButtons & ~IN_SCORE); - - // Strip out the duck key from this check if it's toggled - if ( (fAnyButtonDown & IN_DUCK) && GetToggledDuckState()) - { - fAnyButtonDown &= ~IN_DUCK; - } - - // wait for all buttons released - if (m_lifeState == LIFE_DEAD) - { - if (fAnyButtonDown) - return; - - if ( g_pGameRules->FPlayerCanRespawn( this ) ) - { - m_lifeState = LIFE_RESPAWNABLE; - } - - return; - } - -// if the player has been dead for one second longer than allowed by forcerespawn, -// forcerespawn isn't on. Send the player off to an intermission camera until they -// choose to respawn. - if ( g_pGameRules->IsMultiplayer() && ( gpGlobals->curtime > (m_flDeathTime + DEATH_ANIMATION_TIME) ) && !IsObserver() ) - { - // go to dead camera. - StartObserverMode( m_iObserverLastMode ); - } - -// wait for any button down, or mp_forcerespawn is set and the respawn time is up - if (!fAnyButtonDown - && !( g_pGameRules->IsMultiplayer() && forcerespawn.GetInt() > 0 && (gpGlobals->curtime > (m_flDeathTime + 5))) ) - return; - - m_nButtons = 0; - m_iRespawnFrames = 0; - - //Msg( "Respawn\n"); - - respawn( this, !IsObserver() );// don't copy a corpse if we're in deathcam. - SetNextThink( TICK_NEVER_THINK ); -} - -/* - -//========================================================= -// StartDeathCam - find an intermission spot and send the -// player off into observer mode -//========================================================= -void CBasePlayer::StartDeathCam( void ) -{ - CBaseEntity *pSpot, *pNewSpot; - int iRand; - - if ( GetViewOffset() == vec3_origin ) - { - // don't accept subsequent attempts to StartDeathCam() - return; - } - - pSpot = gEntList.FindEntityByClassname( NULL, "info_intermission"); - - if ( pSpot ) - { - // at least one intermission spot in the world. - iRand = random->RandomInt( 0, 3 ); - - while ( iRand > 0 ) - { - pNewSpot = gEntList.FindEntityByClassname( pSpot, "info_intermission"); - - if ( pNewSpot ) - { - pSpot = pNewSpot; - } - - iRand--; - } - - CreateCorpse(); - StartObserverMode( pSpot->GetAbsOrigin(), pSpot->GetAbsAngles() ); - } - else - { - // no intermission spot. Push them up in the air, looking down at their corpse - trace_t tr; - - CreateCorpse(); - - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, 128 ), - MASK_PLAYERSOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - QAngle angles; - VectorAngles( GetAbsOrigin() - tr.endpos, angles ); - StartObserverMode( tr.endpos, angles ); - return; - } -} */ - -void CBasePlayer::StopObserverMode() -{ - m_bForcedObserverMode = false; - m_afPhysicsFlags &= ~PFLAG_OBSERVER; - - if ( m_iObserverMode == OBS_MODE_NONE ) - return; - - if ( m_iObserverMode > OBS_MODE_DEATHCAM ) - { - m_iObserverLastMode = m_iObserverMode; - } - - m_iObserverMode.Set( OBS_MODE_NONE ); - - ShowViewPortPanel( "specmenu", false ); - ShowViewPortPanel( "specgui", false ); - ShowViewPortPanel( "overview", false ); -} - -bool CBasePlayer::StartObserverMode(int mode) -{ - if ( !IsObserver() ) - { - // set position to last view offset - SetAbsOrigin( GetAbsOrigin() + GetViewOffset() ); - SetViewOffset( vec3_origin ); - } - - Assert( mode > OBS_MODE_NONE ); - - m_afPhysicsFlags |= PFLAG_OBSERVER; - - // Holster weapon immediately, to allow it to cleanup - if ( GetActiveWeapon() ) - GetActiveWeapon()->Holster(); - - // clear out the suit message cache so we don't keep chattering - SetSuitUpdate(NULL, FALSE, 0); - - SetGroundEntity( (CBaseEntity *)NULL ); - - RemoveFlag( FL_DUCKING ); - - AddSolidFlags( FSOLID_NOT_SOLID ); - - SetObserverMode( mode ); - - if ( gpGlobals->eLoadType != MapLoad_Background ) - { - ShowViewPortPanel( "specgui" , ModeWantsSpectatorGUI(mode) ); - } - - // Setup flags - m_Local.m_iHideHUD = HIDEHUD_HEALTH; - m_takedamage = DAMAGE_NO; - - // Become invisible - AddEffects( EF_NODRAW ); - - m_iHealth = 1; - m_lifeState = LIFE_DEAD; // Can't be dead, otherwise movement doesn't work right. - m_flDeathAnimTime = gpGlobals->curtime; - pl.deadflag = true; - - return true; -} - -bool CBasePlayer::SetObserverMode(int mode ) -{ - if ( mode < OBS_MODE_NONE || mode >= NUM_OBSERVER_MODES ) - return false; - - - // check mp_forcecamera settings for dead players - if ( mode > OBS_MODE_FIXED && GetTeamNumber() > TEAM_SPECTATOR ) - { - switch ( mp_forcecamera.GetInt() ) - { - case OBS_ALLOW_ALL : break; // no restrictions - case OBS_ALLOW_TEAM : mode = OBS_MODE_IN_EYE; break; - case OBS_ALLOW_NONE : mode = OBS_MODE_FIXED; break; // don't allow anything - } - } - - if ( m_iObserverMode > OBS_MODE_DEATHCAM ) - { - // remember mode if we were really spectating before - m_iObserverLastMode = m_iObserverMode; - } - - m_iObserverMode = mode; - - switch ( mode ) - { - case OBS_MODE_NONE: - case OBS_MODE_FIXED : - case OBS_MODE_DEATHCAM : - SetFOV( this, 0 ); // Reset FOV - SetViewOffset( vec3_origin ); - SetMoveType( MOVETYPE_NONE ); - break; - - case OBS_MODE_CHASE : - case OBS_MODE_IN_EYE : - // udpate FOV and viewmodels - SetObserverTarget( m_hObserverTarget ); - SetMoveType( MOVETYPE_OBSERVER ); - break; - - case OBS_MODE_ROAMING : - SetFOV( this, 0 ); // Reset FOV - SetObserverTarget( m_hObserverTarget ); - SetViewOffset( vec3_origin ); - SetMoveType( MOVETYPE_OBSERVER ); - break; - - } - - CheckObserverSettings(); - - return true; -} - -int CBasePlayer::GetObserverMode() -{ - return m_iObserverMode; -} - -void CBasePlayer::ForceObserverMode(int mode) -{ - int tempMode = OBS_MODE_ROAMING; - - if ( m_iObserverMode == mode ) - return; - - // don't change last mode if already in forced mode - - if ( m_bForcedObserverMode ) - { - tempMode = m_iObserverLastMode; - } - - SetObserverMode( mode ); - - if ( m_bForcedObserverMode ) - { - m_iObserverLastMode = tempMode; - } - - m_bForcedObserverMode = true; -} - -void CBasePlayer::CheckObserverSettings() -{ - // check if we are in forced mode and may go back to old mode - if ( m_bForcedObserverMode ) - { - CBaseEntity * target = m_hObserverTarget; - - if ( !IsValidObserverTarget(target) ) - { - // if old target is still invalid, try to find valid one - target = FindNextObserverTarget( false ); - } - - if ( target ) - { - // we found a valid target - m_bForcedObserverMode = false; // disable force mode - SetObserverMode( m_iObserverLastMode ); // switch to last mode - SetObserverTarget( target ); // goto target - - // TODO check for HUD icons - return; - } - else - { - // else stay in forced mode, no changes - return; - } - } - - // make sure our last mode is valid - if ( m_iObserverLastMode < OBS_MODE_FIXED ) - { - m_iObserverLastMode = OBS_MODE_ROAMING; - } - - // check if our spectating target is still a valid one - - if ( m_iObserverMode == OBS_MODE_IN_EYE || m_iObserverMode == OBS_MODE_CHASE ) - { - ValidateCurrentObserverTarget(); - - CBasePlayer *target = ToBasePlayer( m_hObserverTarget.Get() ); - - // for ineye mode we have to copy several data to see exactly the same - - if ( target && m_iObserverMode == OBS_MODE_IN_EYE ) - { - int flagMask = FL_ONGROUND | FL_DUCKING ; - - int flags = target->GetFlags() & flagMask; - - if ( (GetFlags() & flagMask) != flags ) - { - flags |= GetFlags() & (~flagMask); // keep other flags - ClearFlags(); - AddFlag( flags ); - } - - if ( target->GetViewOffset() != GetViewOffset() ) - { - SetViewOffset( target->GetViewOffset() ); - } - } - - // Update the fog. - if ( target ) - { - if ( target->m_Local.m_PlayerFog.m_hCtrl.Get() != m_Local.m_PlayerFog.m_hCtrl.Get() ) - { - m_Local.m_PlayerFog.m_hCtrl.Set( target->m_Local.m_PlayerFog.m_hCtrl.Get() ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::ValidateCurrentObserverTarget( void ) -{ - if ( !IsValidObserverTarget( m_hObserverTarget.Get() ) ) - { - // our target is not valid, try to find new target - CBaseEntity * target = FindNextObserverTarget( false ); - if ( target ) - { - // switch to new valid target - SetObserverTarget( target ); - } - else - { - // couldn't find new target, switch to temporary mode - if ( mp_forcecamera.GetInt() == OBS_ALLOW_ALL ) - { - // let player roam around - ForceObserverMode( OBS_MODE_ROAMING ); - } - else - { - // fix player view right where it is - ForceObserverMode( OBS_MODE_FIXED ); - m_hObserverTarget.Set( NULL ); // no traget to follow - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::AttemptToExitFreezeCam( void ) -{ - StartObserverMode( OBS_MODE_DEATHCAM ); -} - -bool CBasePlayer::StartReplayMode( float fDelay, float fDuration, int iEntity ) -{ - if ( ( sv_maxreplay == NULL ) || ( sv_maxreplay->GetFloat() <= 0 ) ) - return false; - - m_fDelay = fDelay; - m_fReplayEnd = gpGlobals->curtime + fDuration; - m_iReplayEntity = iEntity; - - return true; -} - -void CBasePlayer::StopReplayMode() -{ - m_fDelay = 0.0f; - m_fReplayEnd = -1; - m_iReplayEntity = 0; -} - -int CBasePlayer::GetDelayTicks() -{ - if ( m_fReplayEnd > gpGlobals->curtime ) - { - return TIME_TO_TICKS( m_fDelay ); - } - else - { - if ( m_fDelay > 0.0f ) - StopReplayMode(); - - return 0; - } -} - -int CBasePlayer::GetReplayEntity() -{ - return m_iReplayEntity; -} - -CBaseEntity * CBasePlayer::GetObserverTarget() -{ - return m_hObserverTarget.Get(); -} - -void CBasePlayer::ObserverUse( bool bIsPressed ) -{ -#ifndef _XBOX - if ( !HLTVDirector()->IsActive() ) - return; - - if ( GetTeamNumber() != TEAM_SPECTATOR ) - return; // only pure spectators can play cameraman - - if ( !bIsPressed ) - return; - - int iCameraManIndex = HLTVDirector()->GetCameraMan(); - - if ( iCameraManIndex == 0 ) - { - // turn camera on - HLTVDirector()->SetCameraMan( entindex() ); - } - else if ( iCameraManIndex == entindex() ) - { - // turn camera off - HLTVDirector()->SetCameraMan( 0 ); - } - else - { - ClientPrint( this, HUD_PRINTTALK, "Camera in use by other player." ); - } - - /* UTIL_SayText( "Spectator can not USE anything", this ); - - Vector dir,end; - Vector start = GetAbsOrigin(); - - AngleVectors( GetAbsAngles(), &dir ); - VectorNormalize( dir ); - - VectorMA( start, 32.0f, dir, end ); - - trace_t tr; - UTIL_TraceLine( start, end, MASK_PLAYERSOLID, this, COLLISION_GROUP_PLAYER_MOVEMENT, &tr ); - - if ( tr.fraction == 1.0f ) - return; // no obstacles in spectators way - - VectorMA( start, 128.0f, dir, end ); - - Ray_t ray; - ray.Init( end, start, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX ); - - UTIL_TraceRay( ray, MASK_PLAYERSOLID, this, COLLISION_GROUP_PLAYER_MOVEMENT, &tr ); - - if ( tr.startsolid || tr.allsolid ) - return; - - SetAbsOrigin( tr.endpos ); */ -#endif -} - -void CBasePlayer::JumptoPosition(const Vector &origin, const QAngle &angles) -{ - SetAbsOrigin( origin ); - SetAbsVelocity( vec3_origin ); // stop movement - SetLocalAngles( angles ); - SnapEyeAngles( angles ); -} - -bool CBasePlayer::SetObserverTarget(CBaseEntity *target) -{ - if ( !IsValidObserverTarget( target ) ) - return false; - - // set new target - m_hObserverTarget.Set( target ); - - // reset fov to default - SetFOV( this, 0 ); - - if ( m_iObserverMode == OBS_MODE_ROAMING ) - { - Vector dir, end; - Vector start = target->EyePosition(); - - AngleVectors( target->EyeAngles(), &dir ); - VectorNormalize( dir ); - VectorMA( start, -64.0f, dir, end ); - - Ray_t ray; - ray.Init( start, end, VEC_DUCK_HULL_MIN , VEC_DUCK_HULL_MAX ); - - trace_t tr; - UTIL_TraceRay( ray, MASK_PLAYERSOLID, target, COLLISION_GROUP_PLAYER_MOVEMENT, &tr ); - - JumptoPosition( tr.endpos, target->EyeAngles() ); - } - - return true; -} - -bool CBasePlayer::IsValidObserverTarget(CBaseEntity * target) -{ - if ( target == NULL ) - return false; - - // MOD AUTHORS: Add checks on target here or in derived method - - if ( !target->IsPlayer() ) // only track players - return false; - - CBasePlayer * player = ToBasePlayer( target ); - - /* Don't spec observers or players who haven't picked a class yet - if ( player->IsObserver() ) - return false; */ - - if( player == this ) - return false; // We can't observe ourselves. - - if ( player->IsEffectActive( EF_NODRAW ) ) // don't watch invisible players - return false; - - if ( player->m_lifeState == LIFE_RESPAWNABLE ) // target is dead, waiting for respawn - return false; - - if ( player->m_lifeState == LIFE_DEAD || player->m_lifeState == LIFE_DYING ) - { - if ( (player->m_flDeathTime + DEATH_ANIMATION_TIME ) < gpGlobals->curtime ) - { - return false; // allow watching until 3 seconds after death to see death animation - } - } - - // check forcecamera settings for active players - if ( GetTeamNumber() != TEAM_SPECTATOR ) - { - switch ( mp_forcecamera.GetInt() ) - { - case OBS_ALLOW_ALL : break; - case OBS_ALLOW_TEAM : if ( GetTeamNumber() != target->GetTeamNumber() ) - return false; - break; - case OBS_ALLOW_NONE : return false; - } - } - - return true; // passed all test -} - -int CBasePlayer::GetNextObserverSearchStartPoint( bool bReverse ) -{ - int iDir = bReverse ? -1 : 1; - - int startIndex; - - if ( m_hObserverTarget ) - { - // start using last followed player - startIndex = m_hObserverTarget->entindex(); - } - else - { - // start using own player index - startIndex = this->entindex(); - } - - startIndex += iDir; - if (startIndex > gpGlobals->maxClients) - startIndex = 1; - else if (startIndex < 1) - startIndex = gpGlobals->maxClients; - - return startIndex; -} - -CBaseEntity * CBasePlayer::FindNextObserverTarget(bool bReverse) -{ - // MOD AUTHORS: Modify the logic of this function if you want to restrict the observer to watching - // only a subset of the players. e.g. Make it check the target's team. - -/* if ( m_flNextFollowTime && m_flNextFollowTime > gpGlobals->time ) - { - return; - } - - m_flNextFollowTime = gpGlobals->time + 0.25; - */ // TODO move outside this function - - int startIndex = GetNextObserverSearchStartPoint( bReverse ); - - int currentIndex = startIndex; - int iDir = bReverse ? -1 : 1; - - do - { - CBaseEntity * nextTarget = UTIL_PlayerByIndex( currentIndex ); - - if ( IsValidObserverTarget( nextTarget ) ) - { - return nextTarget; // found next valid player - } - - currentIndex += iDir; - - // Loop through the clients - if (currentIndex > gpGlobals->maxClients) - currentIndex = 1; - else if (currentIndex < 1) - currentIndex = gpGlobals->maxClients; - - } while ( currentIndex != startIndex ); - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if this object can be +used by the player -//----------------------------------------------------------------------------- -bool CBasePlayer::IsUseableEntity( CBaseEntity *pEntity, unsigned int requiredCaps ) -{ - if ( pEntity ) - { - int caps = pEntity->ObjectCaps(); - if ( caps & (FCAP_IMPULSE_USE|FCAP_CONTINUOUS_USE|FCAP_ONOFF_USE|FCAP_DIRECTIONAL_USE) ) - { - if ( (caps & requiredCaps) == requiredCaps ) - { - return true; - } - } - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBasePlayer::CanPickupObject( CBaseEntity *pObject, float massLimit, float sizeLimit ) -{ - // UNDONE: Make this virtual and move to HL2 player -#ifdef HL2_DLL - //Must be valid - if ( pObject == NULL ) - return false; - - //Must move with physics - if ( pObject->GetMoveType() != MOVETYPE_VPHYSICS ) - return false; - - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int count = pObject->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - - //Must have a physics object - if (!count) - return false; - - float objectMass = 0; - bool checkEnable = false; - for ( int i = 0; i < count; i++ ) - { - objectMass += pList[i]->GetMass(); - if ( !pList[i]->IsMoveable() ) - { - checkEnable = true; - } - if ( pList[i]->GetGameFlags() & FVPHYSICS_NO_PLAYER_PICKUP ) - return false; - if ( pList[i]->IsHinged() ) - return false; - } - - - //Msg( "Target mass: %f\n", pPhys->GetMass() ); - - //Must be under our threshold weight - if ( massLimit > 0 && objectMass > massLimit ) - return false; - - if ( checkEnable ) - { - // Allowing picking up of bouncebombs. - CBounceBomb *pBomb = dynamic_cast(pObject); - if( pBomb ) - return true; - - // Allow pickup of phys props that are motion enabled on player pickup - CPhysicsProp *pProp = dynamic_cast(pObject); - CPhysBox *pBox = dynamic_cast(pObject); - if ( !pProp && !pBox ) - return false; - - if ( pProp && !(pProp->HasSpawnFlags( SF_PHYSPROP_ENABLE_ON_PHYSCANNON )) ) - return false; - - if ( pBox && !(pBox->HasSpawnFlags( SF_PHYSBOX_ENABLE_ON_PHYSCANNON )) ) - return false; - } - - if ( sizeLimit > 0 ) - { - const Vector &size = pObject->CollisionProp()->OBBSize(); - if ( size.x > sizeLimit || size.y > sizeLimit || size.z > sizeLimit ) - return false; - } - - return true; -#else - return false; -#endif -} - -float CBasePlayer::GetHeldObjectMass( IPhysicsObject *pHeldObject ) -{ - return 0; -} - -CBaseEntity *CBasePlayer::GetHeldObject( void ) -{ - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Server side of jumping rules. Most jumping logic is already -// handled in shared gamemovement code. Put stuff here that should -// only be done server side. -//----------------------------------------------------------------------------- -void CBasePlayer::Jump() -{ -} - -void CBasePlayer::Duck( ) -{ - if (m_nButtons & IN_DUCK) - { - if ( m_Activity != ACT_LEAP ) - { - SetAnimation( PLAYER_WALK ); - } - } -} - -// -// ID's player as such. -// -Class_T CBasePlayer::Classify ( void ) -{ - return CLASS_PLAYER; -} - - -void CBasePlayer::ResetFragCount() -{ - m_iFrags = 0; - pl.frags = m_iFrags; -} - -void CBasePlayer::IncrementFragCount( int nCount ) -{ - m_iFrags += nCount; - pl.frags = m_iFrags; -} - -void CBasePlayer::ResetDeathCount() -{ - m_iDeaths = 0; - pl.deaths = m_iDeaths; -} - -void CBasePlayer::IncrementDeathCount( int nCount ) -{ - m_iDeaths += nCount; - pl.deaths = m_iDeaths; -} - -void CBasePlayer::AddPoints( int score, bool bAllowNegativeScore ) -{ - // Positive score always adds - if ( score < 0 ) - { - if ( !bAllowNegativeScore ) - { - if ( m_iFrags < 0 ) // Can't go more negative - return; - - if ( -score > m_iFrags ) // Will this go negative? - { - score = -m_iFrags; // Sum will be 0 - } - } - } - - m_iFrags += score; - pl.frags = m_iFrags; -} - -void CBasePlayer::AddPointsToTeam( int score, bool bAllowNegativeScore ) -{ - if ( GetTeam() ) - { - GetTeam()->AddScore( score ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CBasePlayer::GetCommandContextCount( void ) const -{ - return m_CommandContext.Count(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -// Output : CCommandContext -//----------------------------------------------------------------------------- -CCommandContext *CBasePlayer::GetCommandContext( int index ) -{ - if ( index < 0 || index >= m_CommandContext.Count() ) - return NULL; - - return &m_CommandContext[ index ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CCommandContext *CBasePlayer::AllocCommandContext( void ) -{ - int idx = m_CommandContext.AddToTail(); - if ( m_CommandContext.Count() > 1000 ) - { - Assert( 0 ); - } - return &m_CommandContext[ idx ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -//----------------------------------------------------------------------------- -void CBasePlayer::RemoveCommandContext( int index ) -{ - m_CommandContext.Remove( index ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::RemoveAllCommandContexts() -{ - m_CommandContext.RemoveAll(); -} - -//----------------------------------------------------------------------------- -// Purpose: Removes all existing contexts, but leaves the last one around ( or creates it if it doesn't exist -- which would be a bug ) -//----------------------------------------------------------------------------- -CCommandContext *CBasePlayer::RemoveAllCommandContextsExceptNewest( void ) -{ - int count = m_CommandContext.Count(); - int toRemove = count - 1; - if ( toRemove > 0 ) - { - m_CommandContext.RemoveMultiple( 0, toRemove ); - } - - if ( !m_CommandContext.Count() ) - { - Assert( 0 ); - CCommandContext *ctx = AllocCommandContext(); - Q_memset( ctx, 0, sizeof( *ctx ) ); - } - - return &m_CommandContext[ 0 ]; -} - -//----------------------------------------------------------------------------- -// Purpose: Replaces the first nCommands CUserCmds in the context with the ones passed in -- this is used to help meter out CUserCmds over the number of simulation ticks on the server -//----------------------------------------------------------------------------- -void CBasePlayer::ReplaceContextCommands( CCommandContext *ctx, CUserCmd *pCommands, int nCommands ) -{ - // Blow away all of the commands - ctx->cmds.RemoveAll(); - - ctx->numcmds = nCommands; - ctx->totalcmds = nCommands; - ctx->dropped_packets = 0; // meaningless in this context - - // Add them in so the most recent is at slot 0 - for ( int i = nCommands - 1; i >= 0; --i ) - { - ctx->cmds.AddToTail( pCommands[ i ] ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Determine how much time we will be running this frame -// Output : float -//----------------------------------------------------------------------------- -int CBasePlayer::DetermineSimulationTicks( void ) -{ - int command_context_count = GetCommandContextCount(); - - int context_number; - - int simulation_ticks = 0; - - // Determine how much time we will be running this frame and fixup player clock as needed - for ( context_number = 0; context_number < command_context_count; context_number++ ) - { - CCommandContext const *ctx = GetCommandContext( context_number ); - Assert( ctx ); - Assert( ctx->numcmds > 0 ); - Assert( ctx->dropped_packets >= 0 ); - - // Determine how long it will take to run those packets - simulation_ticks += ctx->numcmds + ctx->dropped_packets; - } - - return simulation_ticks; -} - -// 2 ticks ahead or behind current clock means we need to fix clock on client -static ConVar sv_clockcorrection_msecs( "sv_clockcorrection_msecs", "60", 0, "The server tries to keep each player's m_nTickBase withing this many msecs of the server absolute tickcount" ); -static ConVar sv_playerperfhistorycount( "sv_playerperfhistorycount", "20", 0, "Number of samples to maintain in player perf history", true, 1.0f, true, 128.0 ); - -//----------------------------------------------------------------------------- -// Purpose: Based upon amount of time in simulation time, adjust m_nTickBase so that -// we just end at the end of the current frame (so the player is basically on clock -// with the server) -// Input : simulation_ticks - -//----------------------------------------------------------------------------- -void CBasePlayer::AdjustPlayerTimeBase( int simulation_ticks ) -{ - Assert( simulation_ticks >= 0 ); - if ( simulation_ticks < 0 ) - return; - - CPlayerSimInfo *pi = NULL; - if ( sv_playerperfhistorycount.GetInt() > 0 ) - { - while ( m_vecPlayerSimInfo.Count() > sv_playerperfhistorycount.GetInt() ) - { - m_vecPlayerSimInfo.Remove( m_vecPlayerSimInfo.Head() ); - } - - pi = &m_vecPlayerSimInfo[ m_vecPlayerSimInfo.AddToTail() ]; - } - - // Start in the past so that we get to the sv.time that we'll hit at the end of the - // frame, just as we process the final command - - if ( gpGlobals->maxClients == 1 ) - { - // set TickBase so that player simulation tick matches gpGlobals->tickcount after - // all commands have been executed - m_nTickBase = gpGlobals->tickcount - simulation_ticks + gpGlobals->simTicksThisFrame; - } - else // multiplayer - { - float flCorrectionSeconds = clamp( sv_clockcorrection_msecs.GetFloat() / 1000.0f, 0.0f, 1.0f ); - int nCorrectionTicks = TIME_TO_TICKS( flCorrectionSeconds ); - - // Set the target tick flCorrectionSeconds (rounded to ticks) ahead in the future. this way the client can - // alternate around this target tick without getting smaller than gpGlobals->tickcount. - // After running the commands simulation time should be equal or after current gpGlobals->tickcount, - // otherwise the simulation time drops out of the client side interpolated var history window. - - int nIdealFinalTick = gpGlobals->tickcount + nCorrectionTicks; - - int nEstimatedFinalTick = m_nTickBase + simulation_ticks; - - // If client gets ahead of this, we'll need to correct - int too_fast_limit = nIdealFinalTick + nCorrectionTicks; - // If client falls behind this, we'll also need to correct - int too_slow_limit = nIdealFinalTick - nCorrectionTicks; - - // See if we are too fast - if ( nEstimatedFinalTick > too_fast_limit || - nEstimatedFinalTick < too_slow_limit ) - { - int nCorrectedTick = nIdealFinalTick - simulation_ticks + gpGlobals->simTicksThisFrame; - - if ( pi ) - { - pi->m_nTicksCorrected = nCorrectionTicks; - } - - m_nTickBase = nCorrectedTick; - } - } - - if ( pi ) - { - pi->m_flFinalSimulationTime = TICKS_TO_TIME( m_nTickBase + simulation_ticks + gpGlobals->simTicksThisFrame ); - } -} - -void CBasePlayer::RunNullCommand( void ) -{ - CUserCmd cmd; // NULL command - - // Store off the globals.. they're gonna get whacked - float flOldFrametime = gpGlobals->frametime; - float flOldCurtime = gpGlobals->curtime; - - pl.fixangle = FIXANGLE_NONE; - cmd.viewangles = EyeAngles(); - - float flTimeBase = gpGlobals->curtime; - SetTimeBase( flTimeBase ); - - MoveHelperServer()->SetHost( this ); - PlayerRunCommand( &cmd, MoveHelperServer() ); - - // save off the last good usercmd - SetLastUserCommand( cmd ); - - // Restore the globals.. - gpGlobals->frametime = flOldFrametime; - gpGlobals->curtime = flOldCurtime; - - MoveHelperServer()->SetHost( NULL ); -} - -//----------------------------------------------------------------------------- -// Purpose: Note, don't chain to BaseClass::PhysicsSimulate -//----------------------------------------------------------------------------- -void CBasePlayer::PhysicsSimulate( void ) -{ - VPROF_BUDGET( "CBasePlayer::PhysicsSimulate", VPROF_BUDGETGROUP_PLAYER ); - - // If we've got a moveparent, we must simulate that first. - CBaseEntity *pMoveParent = GetMoveParent(); - if (pMoveParent) - { - pMoveParent->PhysicsSimulate(); - } - - // Make sure not to simulate this guy twice per frame - if ( m_nSimulationTick == gpGlobals->tickcount ) - { - return; - } - - m_nSimulationTick = gpGlobals->tickcount; - - // See how many CUserCmds are queued up for running - int simulation_ticks = DetermineSimulationTicks(); - - // If some time will elapse, make sure our clock (m_nTickBase) starts at the correct time - if ( simulation_ticks > 0 ) - { - AdjustPlayerTimeBase( simulation_ticks ); - } - - if ( IsHLTV() ) - { - // just run a single, empty command to make sure - // all PreThink/PostThink functions are called as usual - Assert ( GetCommandContextCount() == 0 ); - RunNullCommand(); - RemoveAllCommandContexts(); - return; - } - - // Store off true server timestamps - float savetime = gpGlobals->curtime; - float saveframetime = gpGlobals->frametime; - - int command_context_count = GetCommandContextCount(); - - - // Build a list of all available commands - CUtlVector< CUserCmd > vecAvailCommands; - - // Contexts go from oldest to newest - for ( int context_number = 0; context_number < command_context_count; context_number++ ) - { - // Get oldest ( newer are added to tail ) - CCommandContext *ctx = GetCommandContext( context_number ); - if ( !ShouldRunCommandsInContext( ctx ) ) - continue; - - if ( !ctx->cmds.Count() ) - continue; - - int numbackup = ctx->totalcmds - ctx->numcmds; - - // If we haven't dropped too many packets, then run some commands - if ( ctx->dropped_packets < 24 ) - { - int droppedcmds = ctx->dropped_packets; - - // run the last known cmd for each dropped cmd we don't have a backup for - while ( droppedcmds > numbackup ) - { - m_LastCmd.tick_count++; - vecAvailCommands.AddToTail( m_LastCmd ); - droppedcmds--; - } - - // Now run the "history" commands if we still have dropped packets - while ( droppedcmds > 0 ) - { - int cmdnum = ctx->numcmds + droppedcmds - 1; - vecAvailCommands.AddToTail( ctx->cmds[cmdnum] ); - droppedcmds--; - } - } - - // Now run any new command(s). Go backward because the most recent command is at index 0. - for ( int i = ctx->numcmds - 1; i >= 0; i-- ) - { - vecAvailCommands.AddToTail( ctx->cmds[i] ); - } - - // Save off the last good command in case we drop > numbackup packets and need to rerun them - // we'll use this to "guess" at what was in the missing packets - m_LastCmd = ctx->cmds[ CMD_MOSTRECENT ]; - } - - // gpGlobals->simTicksThisFrame == number of ticks remaining to be run, so we should take the last N CUserCmds and postpone them until the next frame - - // If we're running multiple ticks this frame, don't peel off all of the commands, spread them out over - // the server ticks. Use blocks of two in alternate ticks - int commandLimit = CBaseEntity::IsSimulatingOnAlternateTicks() ? 2 : 1; - int commandsToRun = vecAvailCommands.Count(); - if ( gpGlobals->simTicksThisFrame >= commandLimit && vecAvailCommands.Count() > commandLimit ) - { - int commandsToRollOver = MIN( vecAvailCommands.Count(), ( gpGlobals->simTicksThisFrame - 1 ) ); - commandsToRun = vecAvailCommands.Count() - commandsToRollOver; - Assert( commandsToRun >= 0 ); - // Clear all contexts except the last one - if ( commandsToRollOver > 0 ) - { - CCommandContext *ctx = RemoveAllCommandContextsExceptNewest(); - ReplaceContextCommands( ctx, &vecAvailCommands[ commandsToRun ], commandsToRollOver ); - } - else - { - // Clear all contexts - RemoveAllCommandContexts(); - } - } - else - { - // Clear all contexts - RemoveAllCommandContexts(); - } - - float vphysicsArrivalTime = TICK_INTERVAL; - - // Now run the commands - if ( commandsToRun > 0 ) - { - MoveHelperServer()->SetHost( this ); - - // Suppress predicted events, etc. - if ( IsPredictingWeapons() ) - { - IPredictionSystem::SuppressHostEvents( this ); - } - - for ( int i = 0; i < commandsToRun; ++i ) - { - PlayerRunCommand( &vecAvailCommands[ i ], MoveHelperServer() ); - - // Update our vphysics object. - if ( m_pPhysicsController ) - { - VPROF( "CBasePlayer::PhysicsSimulate-UpdateVPhysicsPosition" ); - // If simulating at 2 * TICK_INTERVAL, add an extra TICK_INTERVAL to position arrival computation - UpdateVPhysicsPosition( m_vNewVPhysicsPosition, m_vNewVPhysicsVelocity, vphysicsArrivalTime ); - vphysicsArrivalTime += TICK_INTERVAL; - } - } - - // Always reset after running commands - IPredictionSystem::SuppressHostEvents( NULL ); - - MoveHelperServer()->SetHost( NULL ); - - // Copy in final origin from simulation - CPlayerSimInfo *pi = NULL; - if ( m_vecPlayerSimInfo.Count() > 0 ) - { - pi = &m_vecPlayerSimInfo[ m_vecPlayerSimInfo.Tail() ]; - pi->m_flTime = gpGlobals->realtime; - pi->m_vecAbsOrigin = GetAbsOrigin(); - pi->m_flGameSimulationTime = gpGlobals->curtime; - pi->m_nNumCmds = commandsToRun; - } - } - - // Restore the true server clock - // FIXME: Should this occur after simulation of children so - // that they are in the timespace of the player? - gpGlobals->curtime = savetime; - gpGlobals->frametime = saveframetime; -} - -unsigned int CBasePlayer::PhysicsSolidMaskForEntity() const -{ - return MASK_PLAYERSOLID; -} - -//----------------------------------------------------------------------------- -// Purpose: This will force usercmd processing to actually consume commands even if the global tick counter isn't incrementing -//----------------------------------------------------------------------------- -void CBasePlayer::ForceSimulation() -{ - m_nSimulationTick = -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *buf - -// totalcmds - -// dropped_packets - -// ignore - -// paused - -// Output : float -- Time in seconds of last movement command -//----------------------------------------------------------------------------- -void CBasePlayer::ProcessUsercmds( CUserCmd *cmds, int numcmds, int totalcmds, - int dropped_packets, bool paused ) -{ - CCommandContext *ctx = AllocCommandContext(); - Assert( ctx ); - - int i; - for ( i = totalcmds - 1; i >= 0; i-- ) - { - ctx->cmds.AddToTail( cmds[ totalcmds - 1 - i ] ); - } - ctx->numcmds = numcmds; - ctx->totalcmds = totalcmds, - ctx->dropped_packets = dropped_packets; - ctx->paused = paused; - - // If the server is paused, zero out motion,buttons,view changes - if ( ctx->paused ) - { - bool clear_angles = true; - - // If no clipping and cheats enabled and sv_noclipduringpause enabled, then don't zero out movement part of CUserCmd - if ( GetMoveType() == MOVETYPE_NOCLIP && - sv_cheats->GetBool() && - sv_noclipduringpause.GetBool() ) - { - clear_angles = false; - } - - for ( i = 0; i < ctx->numcmds; i++ ) - { - ctx->cmds[ i ].buttons = 0; - if ( clear_angles ) - { - ctx->cmds[ i ].forwardmove = 0; - ctx->cmds[ i ].sidemove = 0; - ctx->cmds[ i ].upmove = 0; - VectorCopy ( pl.v_angle, ctx->cmds[ i ].viewangles ); - } - } - - ctx->dropped_packets = 0; - } - - // Set global pause state for this player - m_bGamePaused = paused; - - if ( paused ) - { - ForceSimulation(); - // Just run the commands right away if paused - PhysicsSimulate(); - } - - if ( sv_playerperfhistorycount.GetInt() > 0 ) - { - CPlayerCmdInfo pi; - pi.m_flTime = gpGlobals->realtime; - pi.m_nDroppedPackets = dropped_packets; - pi.m_nNumCmds = numcmds; - - while ( m_vecPlayerCmdInfo.Count() >= sv_playerperfhistorycount.GetInt() ) - { - m_vecPlayerCmdInfo.Remove( m_vecPlayerCmdInfo.Head() ); - } - - m_vecPlayerCmdInfo.AddToTail( pi ); - } -} - -void CBasePlayer::DumpPerfToRecipient( CBasePlayer *pRecipient, int nMaxRecords ) -{ - if ( !pRecipient ) - return; - - char buf[ 256 ] = { 0 }; - int curpos = 0; - - int nDumped = 0; - Vector prevo( 0, 0, 0 ); - float prevt = 0.0f; - - for ( int i = m_vecPlayerSimInfo.Tail(); i != m_vecPlayerSimInfo.InvalidIndex() ; i = m_vecPlayerSimInfo.Previous( i ) ) - { - const CPlayerSimInfo *pi = &m_vecPlayerSimInfo[ i ]; - - float vel = 0.0f; - - // Note we're walking from newest backward - float dt = prevt - pi->m_flFinalSimulationTime; - if ( nDumped > 0 && dt > 0.0f ) - { - Vector d = pi->m_vecAbsOrigin - prevo; - vel = d.Length() / dt; - } - - char line[ 128 ]; - int len = Q_snprintf( line, sizeof( line ), "%.3f %d %d %.3f %.3f %.3f [vel %.2f]\n", - pi->m_flTime, - pi->m_nNumCmds, - pi->m_nTicksCorrected, - pi->m_flFinalSimulationTime, - pi->m_flGameSimulationTime, - pi->m_flServerFrameTime, - vel ); - - if ( curpos + len > 200 ) - { - ClientPrint( pRecipient, HUD_PRINTCONSOLE, (char const *)buf ); - buf[ 0 ] = 0; - curpos = 0; - } - - Q_strncpy( &buf[ curpos ], line, sizeof( buf ) - curpos ); - curpos += len; - - ++nDumped; - if ( nMaxRecords != -1 && nDumped >= nMaxRecords ) - break; - - prevo = pi->m_vecAbsOrigin; - prevt = pi->m_flFinalSimulationTime; - } - - if ( curpos > 0 ) - { - ClientPrint( pRecipient, HUD_PRINTCONSOLE, buf ); - } - - nDumped = 0; - curpos = 0; - - for ( int i = m_vecPlayerCmdInfo.Tail(); i != m_vecPlayerCmdInfo.InvalidIndex() ; i = m_vecPlayerCmdInfo.Previous( i ) ) - { - const CPlayerCmdInfo *pi = &m_vecPlayerCmdInfo[ i ]; - - char line[ 128 ]; - int len = Q_snprintf( line, sizeof( line ), "%.3f %d %d\n", - pi->m_flTime, - pi->m_nNumCmds, - pi->m_nDroppedPackets ); - - if ( curpos + len > 200 ) - { - ClientPrint( pRecipient, HUD_PRINTCONSOLE, (char const *)buf ); - buf[ 0 ] = 0; - curpos = 0; - } - - Q_strncpy( &buf[ curpos ], line, sizeof( buf ) - curpos ); - curpos += len; - - ++nDumped; - if ( nMaxRecords != -1 && nDumped >= nMaxRecords ) - break; - } - - if ( curpos > 0 ) - { - ClientPrint( pRecipient, HUD_PRINTCONSOLE, buf ); - } -} - -// Duck debouncing code to stop menu changes from disallowing crouch/uncrouch -ConVar xc_crouch_debounce( "xc_crouch_debounce", "0", FCVAR_NONE ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *ucmd - -// *moveHelper - -//----------------------------------------------------------------------------- -void CBasePlayer::PlayerRunCommand(CUserCmd *ucmd, IMoveHelper *moveHelper) -{ - m_touchedPhysObject = false; - - if ( pl.fixangle == FIXANGLE_NONE) - { - VectorCopy ( ucmd->viewangles, pl.v_angle ); - } - - // Handle FL_FROZEN. - // Prevent player moving for some seconds after New Game, so that they pick up everything - if( GetFlags() & FL_FROZEN || - (developer.GetInt() == 0 && gpGlobals->eLoadType == MapLoad_NewGame && gpGlobals->curtime < 3.0 ) ) - { - ucmd->forwardmove = 0; - ucmd->sidemove = 0; - ucmd->upmove = 0; - ucmd->buttons = 0; - ucmd->impulse = 0; - VectorCopy ( pl.v_angle, ucmd->viewangles ); - } - else - { - // Force a duck if we're toggled - if ( GetToggledDuckState() ) - { - // If this is set, we've altered our menu options and need to debounce the duck - if ( xc_crouch_debounce.GetBool() ) - { - ToggleDuck(); - - // Mark it as handled - xc_crouch_debounce.SetValue( 0 ); - } - else - { - ucmd->buttons |= IN_DUCK; - } - } - } - - PlayerMove()->RunCommand(this, ucmd, moveHelper); -} - -//----------------------------------------------------------------------------- -// Purpose: Strips off IN_xxx flags from the player's input -//----------------------------------------------------------------------------- -void CBasePlayer::DisableButtons( int nButtons ) -{ - m_afButtonDisabled |= nButtons; -} - -//----------------------------------------------------------------------------- -// Purpose: Re-enables stripped IN_xxx flags to the player's input -//----------------------------------------------------------------------------- -void CBasePlayer::EnableButtons( int nButtons ) -{ - m_afButtonDisabled &= ~nButtons; -} - -//----------------------------------------------------------------------------- -// Purpose: Strips off IN_xxx flags from the player's input -//----------------------------------------------------------------------------- -void CBasePlayer::ForceButtons( int nButtons ) -{ - m_afButtonForced |= nButtons; -} - -//----------------------------------------------------------------------------- -// Purpose: Re-enables stripped IN_xxx flags to the player's input -//----------------------------------------------------------------------------- -void CBasePlayer::UnforceButtons( int nButtons ) -{ - m_afButtonForced &= ~nButtons; -} - -void CBasePlayer::HandleFuncTrain(void) -{ - if ( m_afPhysicsFlags & PFLAG_DIROVERRIDE ) - AddFlag( FL_ONTRAIN ); - else - RemoveFlag( FL_ONTRAIN ); - - // Train speed control - if (( m_afPhysicsFlags & PFLAG_DIROVERRIDE ) == 0) - { - if (m_iTrain & TRAIN_ACTIVE) - { - m_iTrain = TRAIN_NEW; // turn off train - } - return; - } - - CBaseEntity *pTrain = GetGroundEntity(); - float vel; - - if ( pTrain ) - { - if ( !(pTrain->ObjectCaps() & FCAP_DIRECTIONAL_USE) ) - pTrain = NULL; - } - - if ( !pTrain ) - { - if ( GetActiveWeapon()->ObjectCaps() & FCAP_DIRECTIONAL_USE ) - { - m_iTrain = TRAIN_ACTIVE | TRAIN_NEW; - - if ( m_nButtons & IN_FORWARD ) - { - m_iTrain |= TRAIN_FAST; - } - else if ( m_nButtons & IN_BACK ) - { - m_iTrain |= TRAIN_BACK; - } - else - { - m_iTrain |= TRAIN_NEUTRAL; - } - return; - } - else - { - trace_t trainTrace; - // Maybe this is on the other side of a level transition - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + Vector(0,0,-38), - MASK_PLAYERSOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trainTrace ); - - if ( trainTrace.fraction != 1.0 && trainTrace.m_pEnt ) - pTrain = trainTrace.m_pEnt; - - - if ( !pTrain || !(pTrain->ObjectCaps() & FCAP_DIRECTIONAL_USE) || !pTrain->OnControls(this) ) - { - m_afPhysicsFlags &= ~PFLAG_DIROVERRIDE; - m_iTrain = TRAIN_NEW|TRAIN_OFF; - return; - } - } - } - else if ( !( GetFlags() & FL_ONGROUND ) || pTrain->HasSpawnFlags( SF_TRACKTRAIN_NOCONTROL ) || (m_nButtons & (IN_MOVELEFT|IN_MOVERIGHT) ) ) - { - // Turn off the train if you jump, strafe, or the train controls go dead - m_afPhysicsFlags &= ~PFLAG_DIROVERRIDE; - m_iTrain = TRAIN_NEW|TRAIN_OFF; - return; - } - - SetAbsVelocity( vec3_origin ); - vel = 0; - if ( m_afButtonPressed & IN_FORWARD ) - { - vel = 1; - pTrain->Use( this, this, USE_SET, (float)vel ); - } - else if ( m_afButtonPressed & IN_BACK ) - { - vel = -1; - pTrain->Use( this, this, USE_SET, (float)vel ); - } - - if (vel) - { - m_iTrain = TrainSpeed((int)pTrain->m_flSpeed, (int)((CFuncTrackTrain*)pTrain)->GetMaxSpeed()); - m_iTrain |= TRAIN_ACTIVE|TRAIN_NEW; - } -} - - -void CBasePlayer::PreThink(void) -{ - if ( g_fGameOver || m_iPlayerLocked ) - return; // intermission or finale - - if ( Hints() ) - { - Hints()->Update(); - } - - ItemPreFrame( ); - WaterMove(); - - if ( g_pGameRules && g_pGameRules->FAllowFlashlight() ) - m_Local.m_iHideHUD &= ~HIDEHUD_FLASHLIGHT; - else - m_Local.m_iHideHUD |= HIDEHUD_FLASHLIGHT; - - // checks if new client data (for HUD and view control) needs to be sent to the client - UpdateClientData(); - - CheckTimeBasedDamage(); - - CheckSuitUpdate(); - - if ( GetObserverMode() > OBS_MODE_FIXED ) - { - CheckObserverSettings(); // do this each frame - } - - if (m_lifeState >= LIFE_DYING) - return; - - HandleFuncTrain(); - - if (m_nButtons & IN_JUMP) - { - // If on a ladder, jump off the ladder - // else Jump - Jump(); - } - - // If trying to duck, already ducked, or in the process of ducking - if ((m_nButtons & IN_DUCK) || (GetFlags() & FL_DUCKING) || (m_afPhysicsFlags & PFLAG_DUCKING) ) - Duck(); - - // - // If we're not on the ground, we're falling. Update our falling velocity. - // - if ( !( GetFlags() & FL_ONGROUND ) ) - { - m_Local.m_flFallVelocity = -GetAbsVelocity().z; - } - -#ifndef _XBOX - CNavArea *area = TheNavMesh->GetNavArea( GetAbsOrigin() ); - if (area && area != m_lastNavArea) - { - // player entered a new nav area - if (m_lastNavArea) - { - m_lastNavArea->DecrementPlayerCount( GetTeamNumber() ); - } - - area->IncrementPlayerCount( GetTeamNumber() ); - - m_lastNavArea = area; - if ( area->GetPlace() != UNDEFINED_PLACE ) - { - const char *placeName = TheNavMesh->PlaceToName( area->GetPlace() ); - if ( placeName && *placeName ) - { - Q_strncpy( m_szLastPlaceName.GetForModify(), placeName, MAX_PLACE_NAME_LENGTH ); - } - } - - // generate event - //KeyValues *event = new KeyValues( "player_entered_area" ); - //event->SetInt( "userid", GetUserID() ); - //event->SetInt( "areaid", area->GetID() ); - //gameeventmanager->FireEvent( event ); - } -#endif - - // StudioFrameAdvance( );//!!!HACKHACK!!! Can't be hit by traceline when not animating? -} - - -/* Time based Damage works as follows: - 1) There are several types of timebased damage: - - #define DMG_PARALYZE (1 << 14) // slows affected creature down - #define DMG_NERVEGAS (1 << 15) // nerve toxins, very bad - #define DMG_POISON (1 << 16) // blood poisioning - #define DMG_RADIATION (1 << 17) // radiation exposure - #define DMG_DROWNRECOVER (1 << 18) // drown recovery - #define DMG_ACID (1 << 19) // toxic chemicals or acid burns - #define DMG_SLOWBURN (1 << 20) // in an oven - - 2) A new hit inflicting tbd restarts the tbd counter - each NPC has an 8bit counter, - per damage type. The counter is decremented every second, so the maximum time - an effect will last is 255/60 = 4.25 minutes. Of course, staying within the radius - of a damaging effect like fire, nervegas, radiation will continually reset the counter to max. - - 3) Every second that a tbd counter is running, the player takes damage. The damage - is determined by the type of tdb. - Paralyze - 1/2 movement rate, 30 second duration. - Nervegas - 5 points per second, 16 second duration = 80 points max dose. - Poison - 2 points per second, 25 second duration = 50 points max dose. - Radiation - 1 point per second, 50 second duration = 50 points max dose. - Drown - 5 points per second, 2 second duration. - Acid/Chemical - 5 points per second, 10 second duration = 50 points max. - Burn - 10 points per second, 2 second duration. - Freeze - 3 points per second, 10 second duration = 30 points max. - - 4) Certain actions or countermeasures counteract the damaging effects of tbds: - - Armor/Heater/Cooler - Chemical(acid),burn, freeze all do damage to armor power, then to body - - recharged by suit recharger - Air In Lungs - drowning damage is done to air in lungs first, then to body - - recharged by poking head out of water - - 10 seconds if swiming fast - Air In SCUBA - drowning damage is done to air in tanks first, then to body - - 2 minutes in tanks. Need new tank once empty. - Radiation Syringe - Each syringe full provides protection vs one radiation dosage - Antitoxin Syringe - Each syringe full provides protection vs one poisoning (nervegas or poison). - Health kit - Immediate stop to acid/chemical, fire or freeze damage. - Radiation Shower - Immediate stop to radiation damage, acid/chemical or fire damage. - - -*/ - -// If player is taking time based damage, continue doing damage to player - -// this simulates the effect of being poisoned, gassed, dosed with radiation etc - -// anything that continues to do damage even after the initial contact stops. -// Update all time based damage counters, and shut off any that are done. - -// The m_bitsDamageType bit MUST be set if any damage is to be taken. -// This routine will detect the initial on value of the m_bitsDamageType -// and init the appropriate counter. Only processes damage every second. - -//#define PARALYZE_DURATION 30 // number of 2 second intervals to take damage -//#define PARALYZE_DAMAGE 0.0 // damage to take each 2 second interval - -//#define NERVEGAS_DURATION 16 -//#define NERVEGAS_DAMAGE 5.0 - -//#define POISON_DURATION 25 -//#define POISON_DAMAGE 2.0 - -//#define RADIATION_DURATION 50 -//#define RADIATION_DAMAGE 1.0 - -//#define ACID_DURATION 10 -//#define ACID_DAMAGE 5.0 - -//#define SLOWBURN_DURATION 2 -//#define SLOWBURN_DAMAGE 1.0 - -//#define SLOWFREEZE_DURATION 1.0 -//#define SLOWFREEZE_DAMAGE 3.0 - -/* */ - - -void CBasePlayer::CheckTimeBasedDamage() -{ - int i; - byte bDuration = 0; - - // If we don't have any time based damage return. - if ( !g_pGameRules->Damage_IsTimeBased( m_bitsDamageType ) ) - return; - - // only check for time based damage approx. every 2 seconds - if ( fabs( gpGlobals->curtime - m_tbdPrev ) < 2.0f ) - return; - - m_tbdPrev = gpGlobals->curtime; - - for (i = 0; i < CDMG_TIMEBASED; i++) - { - // Make sure the damage type is really time-based. - // This is kind of hacky but necessary until we setup DamageType as an enum. - int iDamage = ( DMG_PARALYZE << i ); - if ( !g_pGameRules->Damage_IsTimeBased( iDamage ) ) - continue; - - - // make sure bit is set for damage type - if ( m_bitsDamageType & iDamage ) - { - switch (i) - { - case itbd_Paralyze: - // UNDONE - flag movement as half-speed - bDuration = PARALYZE_DURATION; - break; - case itbd_NerveGas: -// OnTakeDamage(pev, pev, NERVEGAS_DAMAGE, DMG_GENERIC); - bDuration = NERVEGAS_DURATION; - break; -// case itbd_Poison: -// OnTakeDamage( CTakeDamageInfo( this, this, POISON_DAMAGE, DMG_GENERIC ) ); -// bDuration = POISON_DURATION; -// break; - case itbd_Radiation: -// OnTakeDamage(pev, pev, RADIATION_DAMAGE, DMG_GENERIC); - bDuration = RADIATION_DURATION; - break; - case itbd_DrownRecover: - // NOTE: this hack is actually used to RESTORE health - // after the player has been drowning and finally takes a breath - if (m_idrowndmg > m_idrownrestored) - { - int idif = MIN(m_idrowndmg - m_idrownrestored, 10); - - TakeHealth(idif, DMG_GENERIC); - m_idrownrestored += idif; - } - bDuration = 4; // get up to 5*10 = 50 points back - break; - - case itbd_PoisonRecover: - { - // NOTE: this hack is actually used to RESTORE health - // after the player has been poisoned. - if (m_nPoisonDmg > m_nPoisonRestored) - { - int nDif = MIN(m_nPoisonDmg - m_nPoisonRestored, 10); - TakeHealth(nDif, DMG_GENERIC); - m_nPoisonRestored += nDif; - } - bDuration = 9; // get up to 10*10 = 100 points back - break; - } - - case itbd_Acid: -// OnTakeDamage(pev, pev, ACID_DAMAGE, DMG_GENERIC); - bDuration = ACID_DURATION; - break; - case itbd_SlowBurn: -// OnTakeDamage(pev, pev, SLOWBURN_DAMAGE, DMG_GENERIC); - bDuration = SLOWBURN_DURATION; - break; - case itbd_SlowFreeze: -// OnTakeDamage(pev, pev, SLOWFREEZE_DAMAGE, DMG_GENERIC); - bDuration = SLOWFREEZE_DURATION; - break; - default: - bDuration = 0; - } - - if (m_rgbTimeBasedDamage[i]) - { - // decrement damage duration, detect when done. - if (!m_rgbTimeBasedDamage[i] || --m_rgbTimeBasedDamage[i] == 0) - { - m_rgbTimeBasedDamage[i] = 0; - // if we're done, clear damage bits - m_bitsDamageType &= ~(DMG_PARALYZE << i); - } - } - else - // first time taking this damage type - init damage duration - m_rgbTimeBasedDamage[i] = bDuration; - } - } -} - -/* -THE POWER SUIT - -The Suit provides 3 main functions: Protection, Notification and Augmentation. -Some functions are automatic, some require power. -The player gets the suit shortly after getting off the train in C1A0 and it stays -with him for the entire game. - -Protection - - Heat/Cold - When the player enters a hot/cold area, the heating/cooling indicator on the suit - will come on and the battery will drain while the player stays in the area. - After the battery is dead, the player starts to take damage. - This feature is built into the suit and is automatically engaged. - Radiation Syringe - This will cause the player to be immune from the effects of radiation for N seconds. Single use item. - Anti-Toxin Syringe - This will cure the player from being poisoned. Single use item. - Health - Small (1st aid kits, food, etc.) - Large (boxes on walls) - Armor - The armor works using energy to create a protective field that deflects a - percentage of damage projectile and explosive attacks. After the armor has been deployed, - it will attempt to recharge itself to full capacity with the energy reserves from the battery. - It takes the armor N seconds to fully charge. - -Notification (via the HUD) - -x Health -x Ammo -x Automatic Health Care - Notifies the player when automatic healing has been engaged. -x Geiger counter - Classic Geiger counter sound and status bar at top of HUD - alerts player to dangerous levels of radiation. This is not visible when radiation levels are normal. -x Poison - Armor - Displays the current level of armor. - -Augmentation - - Reanimation (w/adrenaline) - Causes the player to come back to life after he has been dead for 3 seconds. - Will not work if player was gibbed. Single use. - Long Jump - Used by hitting the ??? key(s). Caused the player to further than normal. - SCUBA - Used automatically after picked up and after player enters the water. - Works for N seconds. Single use. - -Things powered by the battery - - Armor - Uses N watts for every M units of damage. - Heat/Cool - Uses N watts for every second in hot/cold area. - Long Jump - Uses N watts for every jump. - Alien Cloak - Uses N watts for each use. Each use lasts M seconds. - Alien Shield - Augments armor. Reduces Armor drain by one half - -*/ - -// if in range of radiation source, ping geiger counter - -#define GEIGERDELAY 0.25 - -void CBasePlayer::UpdateGeigerCounter( void ) -{ - byte range; - - // delay per update ie: don't flood net with these msgs - if (gpGlobals->curtime < m_flgeigerDelay) - return; - - m_flgeigerDelay = gpGlobals->curtime + GEIGERDELAY; - - // send range to radition source to client - range = (byte) clamp(m_flgeigerRange / 4, 0, 255); - - // This is to make sure you aren't driven crazy by geiger while in the airboat - if ( IsInAVehicle() ) - { - range = clamp( (int)range * 4, 0, 255 ); - } - - if (range != m_igeigerRangePrev) - { - m_igeigerRangePrev = range; - - CSingleUserRecipientFilter user( this ); - user.MakeReliable(); - UserMessageBegin( user, "Geiger" ); - WRITE_BYTE( range ); - MessageEnd(); - } - - // reset counter and semaphore - if (!random->RandomInt(0,3)) - { - m_flgeigerRange = 1000; - } -} - -/* -================ -CheckSuitUpdate - -Play suit update if it's time -================ -*/ - -#define SUITUPDATETIME 3.5 -#define SUITFIRSTUPDATETIME 0.1 - -void CBasePlayer::CheckSuitUpdate() -{ - int i; - int isentence = 0; - int isearch = m_iSuitPlayNext; - - // Ignore suit updates if no suit - if ( !IsSuitEquipped() ) - return; - - // if in range of radiation source, ping geiger counter - UpdateGeigerCounter(); - - if ( g_pGameRules->IsMultiplayer() ) - { - // don't bother updating HEV voice in multiplayer. - return; - } - - if ( gpGlobals->curtime >= m_flSuitUpdate && m_flSuitUpdate > 0) - { - // play a sentence off of the end of the queue - for (i = 0; i < CSUITPLAYLIST; i++) - { - if ((isentence = m_rgSuitPlayList[isearch]) != 0) - break; - - if (++isearch == CSUITPLAYLIST) - isearch = 0; - } - - if (isentence) - { - m_rgSuitPlayList[isearch] = 0; - if (isentence > 0) - { - // play sentence number - - char sentence[512]; - Q_snprintf( sentence, sizeof( sentence ), "!%s", engine->SentenceNameFromIndex( isentence ) ); - UTIL_EmitSoundSuit( edict(), sentence ); - } - else - { - // play sentence group - UTIL_EmitGroupIDSuit(edict(), -isentence); - } - m_flSuitUpdate = gpGlobals->curtime + SUITUPDATETIME; - } - else - // queue is empty, don't check - m_flSuitUpdate = 0; - } -} - -// add sentence to suit playlist queue. if fgroup is true, then -// name is a sentence group (HEV_AA), otherwise name is a specific -// sentence name ie: !HEV_AA0. If iNoRepeat is specified in -// seconds, then we won't repeat playback of this word or sentence -// for at least that number of seconds. - -void CBasePlayer::SetSuitUpdate(const char *name, int fgroup, int iNoRepeatTime) -{ - int i; - int isentence; - int iempty = -1; - - - // Ignore suit updates if no suit - if ( !IsSuitEquipped() ) - return; - - if ( g_pGameRules->IsMultiplayer() ) - { - // due to static channel design, etc. We don't play HEV sounds in multiplayer right now. - return; - } - - // if name == NULL, then clear out the queue - - if (!name) - { - for (i = 0; i < CSUITPLAYLIST; i++) - m_rgSuitPlayList[i] = 0; - return; - } - // get sentence or group number - if (!fgroup) - { - isentence = SENTENCEG_Lookup(name); // Lookup sentence index (not group) by name - if (isentence < 0) - return; - } - else - // mark group number as negative - isentence = -SENTENCEG_GetIndex(name); // Lookup group index by name - - // check norepeat list - this list lets us cancel - // the playback of words or sentences that have already - // been played within a certain time. - - for (i = 0; i < CSUITNOREPEAT; i++) - { - if (isentence == m_rgiSuitNoRepeat[i]) - { - // this sentence or group is already in - // the norepeat list - - if (m_rgflSuitNoRepeatTime[i] < gpGlobals->curtime) - { - // norepeat time has expired, clear it out - m_rgiSuitNoRepeat[i] = 0; - m_rgflSuitNoRepeatTime[i] = 0.0; - iempty = i; - break; - } - else - { - // don't play, still marked as norepeat - return; - } - } - // keep track of empty slot - if (!m_rgiSuitNoRepeat[i]) - iempty = i; - } - - // sentence is not in norepeat list, save if norepeat time was given - - if (iNoRepeatTime) - { - if (iempty < 0) - iempty = random->RandomInt(0, CSUITNOREPEAT-1); // pick random slot to take over - m_rgiSuitNoRepeat[iempty] = isentence; - m_rgflSuitNoRepeatTime[iempty] = iNoRepeatTime + gpGlobals->curtime; - } - - // find empty spot in queue, or overwrite last spot - - m_rgSuitPlayList[m_iSuitPlayNext++] = isentence; - if (m_iSuitPlayNext == CSUITPLAYLIST) - m_iSuitPlayNext = 0; - - if (m_flSuitUpdate <= gpGlobals->curtime) - { - if (m_flSuitUpdate == 0) - // play queue is empty, don't delay too long before playback - m_flSuitUpdate = gpGlobals->curtime + SUITFIRSTUPDATETIME; - else - m_flSuitUpdate = gpGlobals->curtime + SUITUPDATETIME; - } - -} - -//========================================================= -// UpdatePlayerSound - updates the position of the player's -// reserved sound slot in the sound list. -//========================================================= -void CBasePlayer::UpdatePlayerSound ( void ) -{ - int iBodyVolume; - int iVolume; - CSound *pSound; - - pSound = CSoundEnt::SoundPointerForIndex( CSoundEnt::ClientSoundIndex( edict() ) ); - - if ( !pSound ) - { - Msg( "Client lost reserved sound!\n" ); - return; - } - - if (GetFlags() & FL_NOTARGET) - { - pSound->m_iVolume = 0; - return; - } - - // now figure out how loud the player's movement is. - if ( GetFlags() & FL_ONGROUND ) - { - iBodyVolume = (int)GetAbsVelocity().Length(); - - // clamp the noise that can be made by the body, in case a push trigger, - // weapon recoil, or anything shoves the player abnormally fast. - // NOTE: 512 units is a pretty large radius for a sound made by the player's body. - // then again, I think some materials are pretty loud. - if ( iBodyVolume > 512 ) - { - iBodyVolume = 512; - } - } - else - { - iBodyVolume = 0; - } - - if ( m_nButtons & IN_JUMP ) - { - // Jumping is a little louder. - iBodyVolume += 100; - } - - m_iTargetVolume = iBodyVolume; - - // if target volume is greater than the player sound's current volume, we paste the new volume in - // immediately. If target is less than the current volume, current volume is not set immediately to the - // lower volume, rather works itself towards target volume over time. This gives NPCs a much better chance - // to hear a sound, especially if they don't listen every frame. - iVolume = pSound->Volume(); - - if ( m_iTargetVolume > iVolume ) - { - iVolume = m_iTargetVolume; - } - else if ( iVolume > m_iTargetVolume ) - { - iVolume = static_cast(iVolume - 250 * gpGlobals->frametime); - - if ( iVolume < m_iTargetVolume ) - { - iVolume = 0; - } - } - - if ( pSound ) - { - pSound->SetSoundOrigin( GetAbsOrigin() ); - pSound->m_iType = SOUND_PLAYER; - pSound->m_iVolume = iVolume; - } - - // Below are a couple of useful little bits that make it easier to visualize just how much noise the - // player is making. - //Vector forward = UTIL_YawToVector( pl.v_angle.y ); - //UTIL_Sparks( GetAbsOrigin() + forward * iVolume ); - //Msg( "%d/%d\n", iVolume, m_iTargetVolume ); -} - -// This is a glorious hack to find free space when you've crouched into some solid space -// Our crouching collisions do not work correctly for some reason and this is easier -// than fixing the problem :( -void FixPlayerCrouchStuck( CBasePlayer *pPlayer ) -{ - trace_t trace; - - // Move up as many as 18 pixels if the player is stuck. - int i; - Vector org = pPlayer->GetAbsOrigin();; - for ( i = 0; i < 18; i++ ) - { - UTIL_TraceHull( pPlayer->GetAbsOrigin(), pPlayer->GetAbsOrigin(), - VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, MASK_PLAYERSOLID, pPlayer, COLLISION_GROUP_PLAYER_MOVEMENT, &trace ); - if ( trace.startsolid ) - { - Vector origin = pPlayer->GetAbsOrigin(); - origin.z += 1.0f; - pPlayer->SetLocalOrigin( origin ); - } - else - return; - } - - pPlayer->SetAbsOrigin( org ); - - for ( i = 0; i < 18; i++ ) - { - UTIL_TraceHull( pPlayer->GetAbsOrigin(), pPlayer->GetAbsOrigin(), - VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, MASK_PLAYERSOLID, pPlayer, COLLISION_GROUP_PLAYER_MOVEMENT, &trace ); - if ( trace.startsolid ) - { - Vector origin = pPlayer->GetAbsOrigin(); - origin.z -= 1.0f; - pPlayer->SetLocalOrigin( origin ); - } - else - return; - } -} -#define SMOOTHING_FACTOR 0.9 -extern CMoveData *g_pMoveData; - -// UNDONE: Look and see if the ground entity is in hierarchy with a MOVETYPE_VPHYSICS? -// Behavior in that case is not as good currently when the parent is rideable -bool CBasePlayer::IsRideablePhysics( IPhysicsObject *pPhysics ) -{ - if ( pPhysics ) - { - if ( pPhysics->GetMass() > (VPhysicsGetObject()->GetMass()*2) ) - return true; - } - - return false; -} - -IPhysicsObject *CBasePlayer::GetGroundVPhysics() -{ - CBaseEntity *pGroundEntity = GetGroundEntity(); - if ( pGroundEntity && pGroundEntity->GetMoveType() == MOVETYPE_VPHYSICS ) - { - IPhysicsObject *pPhysGround = pGroundEntity->VPhysicsGetObject(); - if ( pPhysGround && pPhysGround->IsMoveable() ) - return pPhysGround; - } - return NULL; -} - - -//----------------------------------------------------------------------------- -// For debugging... -//----------------------------------------------------------------------------- -void CBasePlayer::ForceOrigin( const Vector &vecOrigin ) -{ - m_bForceOrigin = true; - m_vForcedOrigin = vecOrigin; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::PostThink() -{ - m_vecSmoothedVelocity = m_vecSmoothedVelocity * SMOOTHING_FACTOR + GetAbsVelocity() * ( 1 - SMOOTHING_FACTOR ); - - if ( !g_fGameOver && !m_iPlayerLocked ) - { - if ( IsAlive() ) - { - // set correct collision bounds (may have changed in player movement code) - VPROF_SCOPE_BEGIN( "CBasePlayer::PostThink-Bounds" ); - if ( GetFlags() & FL_DUCKING ) - { - SetCollisionBounds( VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX ); - } - else - { - SetCollisionBounds( VEC_HULL_MIN, VEC_HULL_MAX ); - } - VPROF_SCOPE_END(); - - VPROF_SCOPE_BEGIN( "CBasePlayer::PostThink-Use" ); - // Handle controlling an entity - if ( m_hUseEntity != NULL ) - { - // if they've moved too far from the gun, or deployed another weapon, unuse the gun - if ( m_hUseEntity->OnControls( this ) && - ( !GetActiveWeapon() || GetActiveWeapon()->IsEffectActive( EF_NODRAW ) || - ( GetActiveWeapon()->GetActivity() == ACT_VM_HOLSTER ) - #ifdef PORTAL // Portalgun view model stays up when holding an object -Jeep - || FClassnameIs( GetActiveWeapon(), "weapon_portalgun" ) - #endif //#ifdef PORTAL - ) ) - { - m_hUseEntity->Use( this, this, USE_SET, 2 ); // try fire the gun - } - else - { - // they've moved off the controls - ClearUseEntity(); - } - } - VPROF_SCOPE_END(); - - // do weapon stuff - VPROF_SCOPE_BEGIN( "CBasePlayer::PostThink-ItemPostFrame" ); - ItemPostFrame(); - VPROF_SCOPE_END(); - - if ( GetFlags() & FL_ONGROUND ) - { - if (m_Local.m_flFallVelocity > 64 && !g_pGameRules->IsMultiplayer()) - { - CSoundEnt::InsertSound ( SOUND_PLAYER, GetAbsOrigin(), m_Local.m_flFallVelocity, 0.2, this ); - // Msg( "fall %f\n", m_Local.m_flFallVelocity ); - } - m_Local.m_flFallVelocity = 0; - } - - // select the proper animation for the player character - VPROF( "CBasePlayer::PostThink-Animation" ); - // If he's in a vehicle, sit down - if ( IsInAVehicle() ) - SetAnimation( PLAYER_IN_VEHICLE ); - else if (!GetAbsVelocity().x && !GetAbsVelocity().y) - SetAnimation( PLAYER_IDLE ); - else if ((GetAbsVelocity().x || GetAbsVelocity().y) && ( GetFlags() & FL_ONGROUND )) - SetAnimation( PLAYER_WALK ); - else if (GetWaterLevel() > 1) - SetAnimation( PLAYER_WALK ); - } - - // Don't allow bogus sequence on player - if ( GetSequence() == -1 ) - { - SetSequence( 0 ); - } - - VPROF_SCOPE_BEGIN( "CBasePlayer::PostThink-StudioFrameAdvance" ); - StudioFrameAdvance(); - VPROF_SCOPE_END(); - - VPROF_SCOPE_BEGIN( "CBasePlayer::PostThink-DispatchAnimEvents" ); - DispatchAnimEvents( this ); - VPROF_SCOPE_END(); - - SetSimulationTime( gpGlobals->curtime ); - - //Let the weapon update as well - VPROF_SCOPE_BEGIN( "CBasePlayer::PostThink-Weapon_FrameUpdate" ); - Weapon_FrameUpdate(); - VPROF_SCOPE_END(); - - VPROF_SCOPE_BEGIN( "CBasePlayer::PostThink-UpdatePlayerSound" ); - UpdatePlayerSound(); - VPROF_SCOPE_END(); - - if ( m_bForceOrigin ) - { - SetLocalOrigin( m_vForcedOrigin ); - SetLocalAngles( m_Local.m_vecPunchAngle ); - m_Local.m_vecPunchAngle = RandomAngle( -25, 25 ); - m_Local.m_vecPunchAngleVel.Init(); - } - - VPROF_SCOPE_BEGIN( "CBasePlayer::PostThink-PostThinkVPhysics" ); - PostThinkVPhysics(); - VPROF_SCOPE_END(); - } - -#if !defined( NO_ENTITY_PREDICTION ) - // Even if dead simulate entities - SimulatePlayerSimulatedEntities(); -#endif - -} - -// handles touching physics objects -void CBasePlayer::Touch( CBaseEntity *pOther ) -{ - if ( pOther == GetGroundEntity() ) - return; - - if ( pOther->GetMoveType() != MOVETYPE_VPHYSICS || pOther->GetSolid() != SOLID_VPHYSICS || (pOther->GetSolidFlags() & FSOLID_TRIGGER) ) - return; - - IPhysicsObject *pPhys = pOther->VPhysicsGetObject(); - if ( !pPhys || !pPhys->IsMoveable() ) - return; - - SetTouchedPhysics( true ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::PostThinkVPhysics( void ) -{ - // Check to see if things are initialized! - if ( !m_pPhysicsController ) - return; - - Vector newPosition = GetAbsOrigin(); - float frametime = gpGlobals->frametime; - if ( frametime <= 0 || frametime > 0.1f ) - frametime = 0.1f; - - IPhysicsObject *pPhysGround = GetGroundVPhysics(); - - if ( !pPhysGround && m_touchedPhysObject && g_pMoveData->m_outStepHeight <= 0.f && (GetFlags() & FL_ONGROUND) ) - { - newPosition = m_oldOrigin + frametime * g_pMoveData->m_outWishVel; - newPosition = (GetAbsOrigin() * 0.5f) + (newPosition * 0.5f); - } - - int collisionState = VPHYS_WALK; - if ( GetMoveType() == MOVETYPE_NOCLIP || GetMoveType() == MOVETYPE_OBSERVER ) - { - collisionState = VPHYS_NOCLIP; - } - else if ( GetFlags() & FL_DUCKING ) - { - collisionState = VPHYS_CROUCH; - } - - if ( collisionState != m_vphysicsCollisionState ) - { - SetVCollisionState( GetAbsOrigin(), GetAbsVelocity(), collisionState ); - } - - if ( !(TouchedPhysics() || pPhysGround) ) - { - float maxSpeed = m_flMaxspeed > 0.0f ? m_flMaxspeed : sv_maxspeed.GetFloat(); - g_pMoveData->m_outWishVel.Init( maxSpeed, maxSpeed, maxSpeed ); - } - - // teleport the physics object up by stepheight (game code does this - reflect in the physics) - if ( g_pMoveData->m_outStepHeight > 0.1f ) - { - if ( g_pMoveData->m_outStepHeight > 4.0f ) - { - VPhysicsGetObject()->SetPosition( GetAbsOrigin(), vec3_angle, true ); - } - else - { - // don't ever teleport into solid - Vector position, end; - VPhysicsGetObject()->GetPosition( &position, NULL ); - end = position; - end.z += g_pMoveData->m_outStepHeight; - trace_t trace; - UTIL_TraceEntity( this, position, end, MASK_PLAYERSOLID, this, COLLISION_GROUP_PLAYER_MOVEMENT, &trace ); - if ( trace.DidHit() ) - { - g_pMoveData->m_outStepHeight = trace.endpos.z - position.z; - } - m_pPhysicsController->StepUp( g_pMoveData->m_outStepHeight ); - } - m_pPhysicsController->Jump(); - } - g_pMoveData->m_outStepHeight = 0.0f; - - // Store these off because after running the usercmds, it'll pass them - // to UpdateVPhysicsPosition. - m_vNewVPhysicsPosition = newPosition; - m_vNewVPhysicsVelocity = g_pMoveData->m_outWishVel; - - m_oldOrigin = GetAbsOrigin(); -} - -void CBasePlayer::UpdateVPhysicsPosition( const Vector &position, const Vector &velocity, float secondsToArrival ) -{ - bool onground = (GetFlags() & FL_ONGROUND) ? true : false; - IPhysicsObject *pPhysGround = GetGroundVPhysics(); - - // if the object is much heavier than the player, treat it as a local coordinate system - // the player controller will solve movement differently in this case. - if ( !IsRideablePhysics(pPhysGround) ) - { - pPhysGround = NULL; - } - - m_pPhysicsController->Update( position, velocity, secondsToArrival, onground, pPhysGround ); -} - -void CBasePlayer::UpdatePhysicsShadowToCurrentPosition() -{ - UpdateVPhysicsPosition( GetAbsOrigin(), vec3_origin, gpGlobals->frametime ); -} - -void CBasePlayer::UpdatePhysicsShadowToPosition( const Vector &vecAbsOrigin ) -{ - UpdateVPhysicsPosition( vecAbsOrigin, vec3_origin, gpGlobals->frametime ); -} - -Vector CBasePlayer::GetSmoothedVelocity( void ) -{ - if ( IsInAVehicle() ) - { - return GetVehicle()->GetVehicleEnt()->GetSmoothedVelocity(); - } - return m_vecSmoothedVelocity; -} - - -CBaseEntity *g_pLastSpawn = NULL; - - -//----------------------------------------------------------------------------- -// Purpose: Finds a player start entity of the given classname. If any entity of -// of the given classname has the SF_PLAYER_START_MASTER flag set, that -// is the entity that will be returned. Otherwise, the first entity of -// the given classname is returned. -// Input : pszClassName - should be "info_player_start", "info_player_coop", or -// "info_player_deathmatch" -//----------------------------------------------------------------------------- -CBaseEntity *FindPlayerStart(const char *pszClassName) -{ - #define SF_PLAYER_START_MASTER 1 - - CBaseEntity *pStart = gEntList.FindEntityByClassname(NULL, pszClassName); - CBaseEntity *pStartFirst = pStart; - while (pStart != NULL) - { - if (pStart->HasSpawnFlags(SF_PLAYER_START_MASTER)) - { - return pStart; - } - - pStart = gEntList.FindEntityByClassname(pStart, pszClassName); - } - - return pStartFirst; -} - -/* -============ -EntSelectSpawnPoint - -Returns the entity to spawn at - -USES AND SETS GLOBAL g_pLastSpawn -============ -*/ -CBaseEntity *CBasePlayer::EntSelectSpawnPoint() -{ - CBaseEntity *pSpot; - edict_t *player; - - player = edict(); - -// choose a info_player_deathmatch point - if (g_pGameRules->IsCoOp()) - { - pSpot = gEntList.FindEntityByClassname( g_pLastSpawn, "info_player_coop"); - if ( pSpot ) - goto ReturnSpot; - pSpot = gEntList.FindEntityByClassname( g_pLastSpawn, "info_player_start"); - if ( pSpot ) - goto ReturnSpot; - } - else if ( g_pGameRules->IsDeathmatch() ) - { - pSpot = g_pLastSpawn; - // Randomize the start spot - for ( int i = random->RandomInt(1,5); i > 0; i-- ) - pSpot = gEntList.FindEntityByClassname( pSpot, "info_player_deathmatch" ); - if ( !pSpot ) // skip over the null point - pSpot = gEntList.FindEntityByClassname( pSpot, "info_player_deathmatch" ); - - CBaseEntity *pFirstSpot = pSpot; - - do - { - if ( pSpot ) - { - // check if pSpot is valid - if ( g_pGameRules->IsSpawnPointValid( pSpot, this ) ) - { - if ( pSpot->GetLocalOrigin() == vec3_origin ) - { - pSpot = gEntList.FindEntityByClassname( pSpot, "info_player_deathmatch" ); - continue; - } - - // if so, go to pSpot - goto ReturnSpot; - } - } - // increment pSpot - pSpot = gEntList.FindEntityByClassname( pSpot, "info_player_deathmatch" ); - } while ( pSpot != pFirstSpot ); // loop if we're not back to the start - - // we haven't found a place to spawn yet, so kill any guy at the first spawn point and spawn there - if ( pSpot ) - { - CBaseEntity *ent = NULL; - for ( CEntitySphereQuery sphere( pSpot->GetAbsOrigin(), 128 ); (ent = sphere.GetCurrentEntity()) != NULL; sphere.NextEntity() ) - { - // if ent is a client, kill em (unless they are ourselves) - if ( ent->IsPlayer() && !(ent->edict() == player) ) - ent->TakeDamage( CTakeDamageInfo( GetContainingEntity(INDEXENT(0)), GetContainingEntity(INDEXENT(0)), 300, DMG_GENERIC ) ); - } - goto ReturnSpot; - } - } - - // If startspot is set, (re)spawn there. - if ( !gpGlobals->startspot || !strlen(STRING(gpGlobals->startspot))) - { - pSpot = FindPlayerStart( "info_player_start" ); - if ( pSpot ) - goto ReturnSpot; - } - else - { - pSpot = gEntList.FindEntityByName( NULL, gpGlobals->startspot ); - if ( pSpot ) - goto ReturnSpot; - } - -ReturnSpot: - if ( !pSpot ) - { - Warning( "PutClientInServer: no info_player_start on level\n"); - return CBaseEntity::Instance( INDEXENT( 0 ) ); - } - - g_pLastSpawn = pSpot; - return pSpot; -} - -//----------------------------------------------------------------------------- -// Purpose: Called the first time the player's created -//----------------------------------------------------------------------------- -void CBasePlayer::InitialSpawn( void ) -{ - m_iConnected = PlayerConnected; - gamestats->Event_PlayerConnected( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: Called everytime the player respawns -//----------------------------------------------------------------------------- -void CBasePlayer::Spawn( void ) -{ - // Needs to be done before weapons are given - if ( Hints() ) - { - Hints()->ResetHints(); - } - - SetClassname( "player" ); - - // Shared spawning code.. - SharedSpawn(); - - SetSimulatedEveryTick( true ); - SetAnimatedEveryTick( true ); - - m_ArmorValue = SpawnArmorValue(); - SetBlocksLOS( false ); - m_iMaxHealth = m_iHealth; - - // Clear all flags except for FL_FULLEDICT - if ( GetFlags() & FL_FAKECLIENT ) - { - ClearFlags(); - AddFlag( FL_CLIENT | FL_FAKECLIENT ); - } - else - { - ClearFlags(); - AddFlag( FL_CLIENT ); - } - - AddFlag( FL_AIMTARGET ); - - m_AirFinished = gpGlobals->curtime + AIRTIME; - m_nDrownDmgRate = DROWNING_DAMAGE_INITIAL; - - // only preserve the shadow flag - int effects = GetEffects() & EF_NOSHADOW; - SetEffects( effects | EF_NOINTERP ); - - // Initialize the fog controller. - InitFogController(); - - m_DmgTake = 0; - m_DmgSave = 0; - m_bitsHUDDamage = -1; - m_bitsDamageType = 0; - m_afPhysicsFlags = 0; - - m_idrownrestored = m_idrowndmg; - - SetFOV( this, 0 ); - - m_flNextDecalTime = 0;// let this player decal as soon as he spawns. - - m_flgeigerDelay = gpGlobals->curtime + 2.0; // wait a few seconds until user-defined message registrations - // are recieved by all clients - - m_flFieldOfView = 0.766;// some NPCs use this to determine whether or not the player is looking at them. - - m_vecAdditionalPVSOrigin = vec3_origin; - m_vecCameraPVSOrigin = vec3_origin; - - if ( !m_fGameHUDInitialized ) - g_pGameRules->SetDefaultPlayerTeam( this ); - - g_pGameRules->GetPlayerSpawnSpot( this ); - - m_Local.m_bDucked = false;// This will persist over round restart if you hold duck otherwise. - m_Local.m_bDucking = false; - SetViewOffset( VEC_VIEW ); - Precache(); - - m_bitsDamageType = 0; - m_bitsHUDDamage = -1; - SetPlayerUnderwater( false ); - - m_iTrain = TRAIN_NEW; - - m_HackedGunPos = Vector( 0, 32, 0 ); - - m_iBonusChallenge = sv_bonus_challenge.GetInt(); - sv_bonus_challenge.SetValue( 0 ); - - if ( m_iPlayerSound == SOUNDLIST_EMPTY ) - { - Msg( "Couldn't alloc player sound slot!\n" ); - } - - SetThink(NULL); - m_fInitHUD = true; - m_fWeapon = false; - m_iClientBattery = -1; - - m_lastx = m_lasty = 0; - - m_lastNavArea = NULL; - -#ifndef _XBOX - /// @todo Do this once per round instead of once per player - if (TheNavMesh) - { - TheNavMesh->ClearPlayerCounts(); - } -#endif - - Q_strncpy( m_szLastPlaceName.GetForModify(), "", MAX_PLACE_NAME_LENGTH ); - - CSingleUserRecipientFilter user( this ); - enginesound->SetPlayerDSP( user, 0, false ); - - CreateViewModel(); - - SetCollisionGroup( COLLISION_GROUP_PLAYER ); - - // if the player is locked, make sure he stays locked - if ( m_iPlayerLocked ) - { - m_iPlayerLocked = false; - LockPlayerInPlace(); - } - - if ( GetTeamNumber() != TEAM_SPECTATOR ) - { - StopObserverMode(); - } - else - { - StartObserverMode( m_iObserverLastMode ); - } - - StopReplayMode(); - - // Clear any screenfade - color32 nothing = {0,0,0,255}; - UTIL_ScreenFade( this, nothing, 0, 0, FFADE_IN | FFADE_PURGE ); - - g_pGameRules->PlayerSpawn( this ); - - m_flLaggedMovementValue = 1.0f; - m_vecSmoothedVelocity = vec3_origin; - InitVCollision( GetAbsOrigin(), GetAbsVelocity() ); - - IGameEvent *event = gameeventmanager->CreateEvent( "player_spawn" ); - - if ( event ) - { - event->SetInt("userid", GetUserID() ); - gameeventmanager->FireEvent( event ); - } - - RumbleEffect( RUMBLE_STOP_ALL, 0, RUMBLE_FLAGS_NONE ); - - // Calculate this immediately - m_nVehicleViewSavedFrame = 0; -} - -void CBasePlayer::Activate( void ) -{ - BaseClass::Activate(); - - AimTarget_ForceRepopulateList(); - - RumbleEffect( RUMBLE_STOP_ALL, 0, RUMBLE_FLAGS_NONE ); - - // Reset the analog bias. If the player is in a vehicle when the game - // reloads, it will autosense and apply the correct bias. - m_iVehicleAnalogBias = VEHICLE_ANALOG_BIAS_NONE; -} - -void CBasePlayer::Precache( void ) -{ - BaseClass::Precache(); - - - PrecacheScriptSound( "Player.FallGib" ); - PrecacheScriptSound( "Player.Death" ); - PrecacheScriptSound( "Player.PlasmaDamage" ); - PrecacheScriptSound( "Player.SonicDamage" ); - PrecacheScriptSound( "Player.DrownStart" ); - PrecacheScriptSound( "Player.DrownContinue" ); - PrecacheScriptSound( "Player.Wade" ); - PrecacheScriptSound( "Player.AmbientUnderWater" ); - enginesound->PrecacheSentenceGroup( "HEV" ); - - // These are always needed -#ifndef TF_DLL - PrecacheParticleSystem( "slime_splash_01" ); - PrecacheParticleSystem( "slime_splash_02" ); - PrecacheParticleSystem( "slime_splash_03" ); -#endif - - // in the event that the player JUST spawned, and the level node graph - // was loaded, fix all of the node graph pointers before the game starts. - - // !!!BUGBUG - now that we have multiplayer, this needs to be moved! - /* todo - put in better spot and use new ainetowrk stuff - if ( WorldGraph.m_fGraphPresent && !WorldGraph.m_fGraphPointersSet ) - { - if ( !WorldGraph.FSetGraphPointers() ) - { - Msg( "**Graph pointers were not set!\n"); - } - else - { - Msg( "**Graph Pointers Set!\n" ); - } - } - */ - - // SOUNDS / MODELS ARE PRECACHED in ClientPrecache() (game specific) - // because they need to precache before any clients have connected - - // init geiger counter vars during spawn and each time - // we cross a level transition - m_flgeigerRange = 1000; - m_igeigerRangePrev = 1000; - -#if 0 - // @Note (toml 04-19-04): These are saved, used to be slammed here - m_bitsDamageType = 0; - m_bitsHUDDamage = -1; - SetPlayerUnderwter( false ); - - m_iTrain = TRAIN_NEW; -#endif - - m_iClientBattery = -1; - - m_iUpdateTime = 5; // won't update for 1/2 a second - - if ( gInitHUD ) - m_fInitHUD = true; - -} - -//----------------------------------------------------------------------------- -// Purpose: Force this player to immediately respawn -//----------------------------------------------------------------------------- -void CBasePlayer::ForceRespawn( void ) -{ - RemoveAllItems( true ); - - // Reset ground state for airwalk animations - SetGroundEntity( NULL ); - - // Stop any firing that was taking place before respawn. - m_nButtons = 0; - - Spawn(); -} - -int CBasePlayer::Save( ISave &save ) -{ - if ( !BaseClass::Save(save) ) - return 0; - - return 1; -} - - -// Friend class of CBaseEntity to access private member data. -class CPlayerRestoreHelper -{ -public: - - const Vector &GetAbsOrigin( CBaseEntity *pent ) - { - return pent->m_vecAbsOrigin; - } - - const Vector &GetAbsVelocity( CBaseEntity *pent ) - { - return pent->m_vecAbsVelocity; - } -}; - - -int CBasePlayer::Restore( IRestore &restore ) -{ - int status = BaseClass::Restore(restore); - if ( !status ) - return 0; - - CSaveRestoreData *pSaveData = gpGlobals->pSaveData; - // landmark isn't present. - if ( !pSaveData->levelInfo.fUseLandmark ) - { - Msg( "No Landmark:%s\n", pSaveData->levelInfo.szLandmarkName ); - - // default to normal spawn - CBaseEntity *pSpawnSpot = EntSelectSpawnPoint(); - SetLocalOrigin( pSpawnSpot->GetLocalOrigin() + Vector(0,0,1) ); - SetLocalAngles( pSpawnSpot->GetLocalAngles() ); - } - - QAngle newViewAngles = pl.v_angle; - newViewAngles.z = 0; // Clear out roll - SetLocalAngles( newViewAngles ); - SnapEyeAngles( newViewAngles ); - - // Copied from spawn() for now - SetBloodColor( BLOOD_COLOR_RED ); - - // clear this - it will get reset by touching the trigger again - m_afPhysicsFlags &= ~PFLAG_VPHYSICS_MOTIONCONTROLLER; - - if ( GetFlags() & FL_DUCKING ) - { - // Use the crouch HACK - FixPlayerCrouchStuck( this ); - UTIL_SetSize(this, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX); - m_Local.m_bDucked = true; - } - else - { - m_Local.m_bDucked = false; - UTIL_SetSize(this, VEC_HULL_MIN, VEC_HULL_MAX); - } - - // We need to get at m_vecAbsOrigin as it was restored but can't let it be - // recalculated by a call to GetAbsOrigin because hierarchy isn't fully restored yet, - // so we use this backdoor to get at the private data in CBaseEntity. - CPlayerRestoreHelper helper; - InitVCollision( helper.GetAbsOrigin( this ), helper.GetAbsVelocity( this ) ); - - // success - return 1; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::OnRestore( void ) -{ - BaseClass::OnRestore(); - - SetViewEntity( m_hViewEntity ); - SetDefaultFOV(m_iDefaultFOV); // force this to reset if zero - - // Calculate this immediately - m_nVehicleViewSavedFrame = 0; - - m_nBodyPitchPoseParam = LookupPoseParameter( "body_pitch" ); -} - -/* void CBasePlayer::SetTeamName( const char *pTeamName ) -{ - Q_strncpy( m_szTeamName, pTeamName, TEAM_NAME_LENGTH ); -} */ - -void CBasePlayer::SetArmorValue( int value ) -{ - m_ArmorValue = value; -} - -void CBasePlayer::IncrementArmorValue( int nCount, int nMaxValue ) -{ - m_ArmorValue += nCount; - if (nMaxValue > 0) - { - if (m_ArmorValue > nMaxValue) - m_ArmorValue = nMaxValue; - } -} - -// used by the physics gun and game physics... is there a better interface? -void CBasePlayer::SetPhysicsFlag( int nFlag, bool bSet ) -{ - if (bSet) - m_afPhysicsFlags |= nFlag; - else - m_afPhysicsFlags &= ~nFlag; -} - - -void CBasePlayer::NotifyNearbyRadiationSource( float flRange ) -{ - // if player's current geiger counter range is larger - // than range to this trigger hurt, reset player's - // geiger counter range - - if (m_flgeigerRange >= flRange) - m_flgeigerRange = flRange; -} - -void CBasePlayer::AllowImmediateDecalPainting() -{ - m_flNextDecalTime = gpGlobals->curtime; -} - -// Suicide... -void CBasePlayer::CommitSuicide( bool bExplode /*= false*/, bool bForce /*= false*/ ) -{ - MDLCACHE_CRITICAL_SECTION(); - - if( !IsAlive() ) - return; - - // prevent suiciding too often - if ( m_fNextSuicideTime > gpGlobals->curtime && !bForce ) - return; - - // don't let them suicide for 5 seconds after suiciding - m_fNextSuicideTime = gpGlobals->curtime + 5; - - int fDamage = DMG_PREVENT_PHYSICS_FORCE | ( bExplode ? ( DMG_BLAST | DMG_ALWAYSGIB ) : DMG_NEVERGIB ); - - // have the player kill themself - m_iHealth = 0; - Event_Killed( CTakeDamageInfo( this, this, 0, fDamage, m_iSuicideCustomKillFlags ) ); - Event_Dying(); - m_iSuicideCustomKillFlags = 0; -} - -// Suicide with style... -void CBasePlayer::CommitSuicide( const Vector &vecForce, bool bExplode /*= false*/, bool bForce /*= false*/ ) -{ - MDLCACHE_CRITICAL_SECTION(); - - // Already dead. - if( !IsAlive() ) - return; - - // Prevent suicides for a time. - if ( m_fNextSuicideTime > gpGlobals->curtime && !bForce ) - return; - - m_fNextSuicideTime = gpGlobals->curtime + 5; - - // Apply the force. - int nHealth = GetHealth(); - - // Kill the player. - CTakeDamageInfo info; - info.SetDamage( nHealth + 10 ); - info.SetAttacker( this ); - info.SetDamageType( bExplode ? DMG_ALWAYSGIB : DMG_GENERIC ); - info.SetDamageForce( vecForce ); - info.SetDamagePosition( WorldSpaceCenter() ); - TakeDamage( info ); -} - -//============================================== -// HasWeapons - do I have any weapons at all? -//============================================== -bool CBasePlayer::HasWeapons( void ) -{ - int i; - - for ( i = 0 ; i < WeaponCount() ; i++ ) - { - if ( GetWeapon(i) ) - { - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &vecForce - -//----------------------------------------------------------------------------- -void CBasePlayer::VelocityPunch( const Vector &vecForce ) -{ - // Clear onground and add velocity. - SetGroundEntity( NULL ); - ApplyAbsVelocityImpulse(vecForce ); -} - - -//-------------------------------------------------------------------------------------------------------------- -// VEHICLES -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// Purpose: Whether or not the player is currently able to enter the vehicle -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBasePlayer::CanEnterVehicle( IServerVehicle *pVehicle, int nRole ) -{ - // Must not have a passenger there already - if ( pVehicle->GetPassenger( nRole ) ) - return false; - - // Must be able to holster our current weapon (ie. grav gun!) - if ( pVehicle->IsPassengerUsingStandardWeapons( nRole ) == false ) - { - //Must be able to stow our weapon - CBaseCombatWeapon *pWeapon = GetActiveWeapon(); - if ( ( pWeapon != NULL ) && ( pWeapon->CanHolster() == false ) ) - return false; - } - - // Must be alive - if ( IsAlive() == false ) - return false; - - // Can't be pulled by a barnacle - if ( IsEFlagSet( EFL_IS_BEING_LIFTED_BY_BARNACLE ) ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Put this player in a vehicle -//----------------------------------------------------------------------------- -bool CBasePlayer::GetInVehicle( IServerVehicle *pVehicle, int nRole ) -{ - Assert( NULL == m_hVehicle.Get() ); - Assert( nRole >= 0 ); - - // Make sure we can enter the vehicle - if ( CanEnterVehicle( pVehicle, nRole ) == false ) - return false; - - CBaseEntity *pEnt = pVehicle->GetVehicleEnt(); - Assert( pEnt ); - - // Try to stow weapons - if ( pVehicle->IsPassengerUsingStandardWeapons( nRole ) == false ) - { - CBaseCombatWeapon *pWeapon = GetActiveWeapon(); - if ( pWeapon != NULL ) - { - pWeapon->Holster( NULL ); - } - -#ifndef HL2_DLL - m_Local.m_iHideHUD |= HIDEHUD_WEAPONSELECTION; -#endif - m_Local.m_iHideHUD |= HIDEHUD_INVEHICLE; - } - - if ( !pVehicle->IsPassengerVisible( nRole ) ) - { - AddEffects( EF_NODRAW ); - } - - // Put us in the vehicle - pVehicle->SetPassenger( nRole, this ); - - ViewPunchReset(); - - // Setting the velocity to 0 will cause the IDLE animation to play - SetAbsVelocity( vec3_origin ); - SetMoveType( MOVETYPE_NOCLIP ); - - // This is a hack to fixup the player's stats since they really didn't "cheat" and enter noclip from the console - gamestats->Event_DecrementPlayerEnteredNoClip( this ); - - // Get the seat position we'll be at in this vehicle - Vector vSeatOrigin; - QAngle qSeatAngles; - pVehicle->GetPassengerSeatPoint( nRole, &vSeatOrigin, &qSeatAngles ); - - // Set us to that position - SetAbsOrigin( vSeatOrigin ); - SetAbsAngles( qSeatAngles ); - - // Parent to the vehicle - SetParent( pEnt ); - - SetCollisionGroup( COLLISION_GROUP_IN_VEHICLE ); - - // We cannot be ducking -- do all this before SetPassenger because it - // saves our view offset for restoration when we exit the vehicle. - RemoveFlag( FL_DUCKING ); - SetViewOffset( VEC_VIEW ); - m_Local.m_bDucked = false; - m_Local.m_bDucking = false; - m_Local.m_flDucktime = 0.0f; - m_Local.m_flDuckJumpTime = 0.0f; - m_Local.m_flJumpTime = 0.0f; - - // Turn our toggled duck off - if ( GetToggledDuckState() ) - { - ToggleDuck(); - } - - m_hVehicle = pEnt; - - // Throw an event indicating that the player entered the vehicle. - g_pNotify->ReportNamedEvent( this, "PlayerEnteredVehicle" ); - - m_iVehicleAnalogBias = VEHICLE_ANALOG_BIAS_NONE; - - OnVehicleStart(); - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Remove this player from a vehicle -//----------------------------------------------------------------------------- -void CBasePlayer::LeaveVehicle( const Vector &vecExitPoint, const QAngle &vecExitAngles ) -{ - if ( NULL == m_hVehicle.Get() ) - return; - - IServerVehicle *pVehicle = GetVehicle(); - Assert( pVehicle ); - - int nRole = pVehicle->GetPassengerRole( this ); - Assert( nRole >= 0 ); - - SetParent( NULL ); - - // Find the first non-blocked exit point: - Vector vNewPos = GetAbsOrigin(); - QAngle qAngles = GetAbsAngles(); - if ( vecExitPoint == vec3_origin ) - { - // FIXME: this might fail to find a safe exit point!! - pVehicle->GetPassengerExitPoint( nRole, &vNewPos, &qAngles ); - } - else - { - vNewPos = vecExitPoint; - qAngles = vecExitAngles; - } - OnVehicleEnd( vNewPos ); - SetAbsOrigin( vNewPos ); - SetAbsAngles( qAngles ); - // Clear out any leftover velocity - SetAbsVelocity( vec3_origin ); - - qAngles[ROLL] = 0; - SnapEyeAngles( qAngles ); - -#ifndef HL2_DLL - m_Local.m_iHideHUD &= ~HIDEHUD_WEAPONSELECTION; -#endif - - m_Local.m_iHideHUD &= ~HIDEHUD_INVEHICLE; - - RemoveEffects( EF_NODRAW ); - - SetMoveType( MOVETYPE_WALK ); - SetCollisionGroup( COLLISION_GROUP_PLAYER ); - - if ( VPhysicsGetObject() ) - { - VPhysicsGetObject()->SetPosition( vNewPos, vec3_angle, true ); - } - - m_hVehicle = NULL; - pVehicle->SetPassenger(nRole, NULL); - - // Re-deploy our weapon - if ( IsAlive() ) - { - if ( GetActiveWeapon() && GetActiveWeapon()->IsWeaponVisible() == false ) - { - GetActiveWeapon()->Deploy(); - ShowCrosshair( true ); - } - } - - // Just cut all of the rumble effects. - RumbleEffect( RUMBLE_STOP_ALL, 0, RUMBLE_FLAGS_NONE ); -} - - -//============================================== -// !!!UNDONE:ultra temporary SprayCan entity to apply -// decal frame at a time. For PreAlpha CD -//============================================== -class CSprayCan : public CPointEntity -{ -public: - DECLARE_CLASS( CSprayCan, CPointEntity ); - - void Spawn ( CBasePlayer *pOwner ); - void Think( void ); - - virtual void Precache(); - - virtual int ObjectCaps( void ) { return FCAP_DONT_SAVE; } -}; - -LINK_ENTITY_TO_CLASS( spraycan, CSprayCan ); -PRECACHE_REGISTER( spraycan ); - -void CSprayCan::Spawn ( CBasePlayer *pOwner ) -{ - SetLocalOrigin( pOwner->WorldSpaceCenter() + Vector ( 0 , 0 , 32 ) ); - SetLocalAngles( pOwner->EyeAngles() ); - SetOwnerEntity( pOwner ); - SetNextThink( gpGlobals->curtime ); - EmitSound( "SprayCan.Paint" ); -} - -void CSprayCan::Precache() -{ - BaseClass::Precache(); - - PrecacheScriptSound( "SprayCan.Paint" ); -} - -void CSprayCan::Think( void ) -{ - CBasePlayer *pPlayer = ToBasePlayer( GetOwnerEntity() ); - if ( pPlayer ) - { - int playernum = pPlayer->entindex(); - - Vector forward; - trace_t tr; - - AngleVectors( GetAbsAngles(), &forward ); - UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + forward * 128, - MASK_SOLID_BRUSHONLY, pPlayer, COLLISION_GROUP_NONE, & tr); - - UTIL_PlayerDecalTrace( &tr, playernum ); - } - - // Just painted last custom frame. - UTIL_Remove( this ); -} - -class CBloodSplat : public CPointEntity -{ -public: - DECLARE_CLASS( CBloodSplat, CPointEntity ); - - void Spawn ( CBaseEntity *pOwner ); - void Think ( void ); -}; - -void CBloodSplat::Spawn ( CBaseEntity *pOwner ) -{ - SetLocalOrigin( pOwner->WorldSpaceCenter() + Vector ( 0 , 0 , 32 ) ); - SetLocalAngles( pOwner->GetLocalAngles() ); - SetOwnerEntity( pOwner ); - - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -void CBloodSplat::Think( void ) -{ - trace_t tr; - - if ( g_Language.GetInt() != LANGUAGE_GERMAN ) - { - CBasePlayer *pPlayer; - pPlayer = ToBasePlayer( GetOwnerEntity() ); - - Vector forward; - AngleVectors( GetAbsAngles(), &forward ); - UTIL_TraceLine ( GetAbsOrigin(), GetAbsOrigin() + forward * 128, - MASK_SOLID_BRUSHONLY, pPlayer, COLLISION_GROUP_NONE, & tr); - - UTIL_BloodDecalTrace( &tr, BLOOD_COLOR_RED ); - } - UTIL_Remove( this ); -} - -//============================================== - -//----------------------------------------------------------------------------- -// Purpose: Create and give the named item to the player. Then return it. -//----------------------------------------------------------------------------- -CBaseEntity *CBasePlayer::GiveNamedItem( const char *pszName, int iSubType ) -{ - // If I already own this type don't create one - if ( Weapon_OwnsThisType(pszName, iSubType) ) - return NULL; - - // Msg( "giving %s\n", pszName ); - - EHANDLE pent; - - pent = CreateEntityByName(pszName); - if ( pent == NULL ) - { - Msg( "NULL Ent in GiveNamedItem!\n" ); - return NULL; - } - - pent->SetLocalOrigin( GetLocalOrigin() ); - pent->AddSpawnFlags( SF_NORESPAWN ); - - CBaseCombatWeapon *pWeapon = dynamic_cast( (CBaseEntity*)pent ); - if ( pWeapon ) - { - pWeapon->SetSubType( iSubType ); - } - - DispatchSpawn( pent ); - - if ( pent != NULL && !(pent->IsMarkedForDeletion()) ) - { - pent->Touch( this ); - } - - return pent; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the nearest COLLIBALE entity in front of the player -// that has a clear line of sight with the given classname -// Input : -// Output : -//----------------------------------------------------------------------------- -CBaseEntity *FindEntityClassForward( CBasePlayer *pMe, char *classname ) -{ - trace_t tr; - - Vector forward; - pMe->EyeVectors( &forward ); - UTIL_TraceLine(pMe->EyePosition(), - pMe->EyePosition() + forward * MAX_COORD_RANGE, - MASK_SOLID, pMe, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction != 1.0 && tr.DidHitNonWorldEntity() ) - { - CBaseEntity *pHit = tr.m_pEnt; - if (FClassnameIs( pHit,classname ) ) - { - return pHit; - } - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the nearest COLLIBALE entity in front of the player -// that has a clear line of sight. If HULL is true, the trace will -// hit the collision hull of entities. Otherwise, the trace will hit -// hitboxes. -// Input : -// Output : -//----------------------------------------------------------------------------- -CBaseEntity *FindEntityForward( CBasePlayer *pMe, bool fHull ) -{ - if ( pMe ) - { - trace_t tr; - Vector forward; - int mask; - - if( fHull ) - { - mask = MASK_SOLID; - } - else - { - mask = MASK_SHOT; - } - - pMe->EyeVectors( &forward ); - UTIL_TraceLine(pMe->EyePosition(), - pMe->EyePosition() + forward * MAX_COORD_RANGE, - mask, pMe, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction != 1.0 && tr.DidHitNonWorldEntity() ) - { - return tr.m_pEnt; - } - } - return NULL; - -} - -//----------------------------------------------------------------------------- -// Purpose: Finds the nearest entity in front of the player of the given -// classname, preferring collidable entities, but allows selection of -// enities that are on the other side of walls or objects -// -// Input : -// Output : -//----------------------------------------------------------------------------- -CBaseEntity *FindPickerEntityClass( CBasePlayer *pPlayer, char *classname ) -{ - // First try to trace a hull to an entity - CBaseEntity *pEntity = FindEntityClassForward( pPlayer, classname ); - - // If that fails just look for the nearest facing entity - if (!pEntity) - { - Vector forward; - Vector origin; - pPlayer->EyeVectors( &forward ); - origin = pPlayer->WorldSpaceCenter(); - pEntity = gEntList.FindEntityClassNearestFacing( origin, forward,0.95,classname); - } - return pEntity; -} - -//----------------------------------------------------------------------------- -// Purpose: Finds the nearest entity in front of the player, preferring -// collidable entities, but allows selection of enities that are -// on the other side of walls or objects -// Input : -// Output : -//----------------------------------------------------------------------------- -CBaseEntity *FindPickerEntity( CBasePlayer *pPlayer ) -{ - MDLCACHE_CRITICAL_SECTION(); - - // First try to trace a hull to an entity - CBaseEntity *pEntity = FindEntityForward( pPlayer, true ); - - // If that fails just look for the nearest facing entity - if (!pEntity) - { - Vector forward; - Vector origin; - pPlayer->EyeVectors( &forward ); - origin = pPlayer->WorldSpaceCenter(); - pEntity = gEntList.FindEntityNearestFacing( origin, forward,0.95); - } - return pEntity; -} - -//----------------------------------------------------------------------------- -// Purpose: Finds the nearest node in front of the player -// Input : -// Output : -//----------------------------------------------------------------------------- -CAI_Node *FindPickerAINode( CBasePlayer *pPlayer, NodeType_e nNodeType ) -{ - Vector forward; - Vector origin; - - pPlayer->EyeVectors( &forward ); - origin = pPlayer->EyePosition(); - return g_pAINetworkManager->GetEditOps()->FindAINodeNearestFacing( origin, forward,0.90, nNodeType); -} - -//----------------------------------------------------------------------------- -// Purpose: Finds the nearest link in front of the player -// Input : -// Output : -//----------------------------------------------------------------------------- -CAI_Link *FindPickerAILink( CBasePlayer* pPlayer ) -{ - Vector forward; - Vector origin; - - pPlayer->EyeVectors( &forward ); - origin = pPlayer->EyePosition(); - return g_pAINetworkManager->GetEditOps()->FindAILinkNearestFacing( origin, forward,0.90); -} - -/* -=============== -ForceClientDllUpdate - -When recording a demo, we need to have the server tell us the entire client state -so that the client side .dll can behave correctly. -Reset stuff so that the state is transmitted. -=============== -*/ -void CBasePlayer::ForceClientDllUpdate( void ) -{ - m_iClientBattery = -1; - m_iTrain |= TRAIN_NEW; // Force new train message. - m_fWeapon = false; // Force weapon send - - // Force all HUD data to be resent to client - m_fInitHUD = true; - - // Now force all the necessary messages - // to be sent. - UpdateClientData(); - - UTIL_RestartAmbientSounds(); // MOTODO that updates the sounds for everybody -} - -/* -============ -ImpulseCommands -============ -*/ - -void CBasePlayer::ImpulseCommands( ) -{ - trace_t tr; - - int iImpulse = (int)m_nImpulse; - switch (iImpulse) - { - case 100: - // temporary flashlight for level designers - if ( FlashlightIsOn() ) - { - FlashlightTurnOff(); - } - else - { - FlashlightTurnOn(); - } - break; - - case 200: - if ( sv_cheats->GetBool() ) - { - CBaseCombatWeapon *pWeapon; - - pWeapon = GetActiveWeapon(); - - if( pWeapon->IsEffectActive( EF_NODRAW ) ) - { - pWeapon->Deploy(); - } - else - { - pWeapon->Holster(); - } - } - break; - - case 201:// paint decal - - if ( gpGlobals->curtime < m_flNextDecalTime ) - { - // too early! - break; - } - - { - Vector forward; - EyeVectors( &forward ); - UTIL_TraceLine ( EyePosition(), - EyePosition() + forward * 128, - MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, & tr); - } - - if ( tr.fraction != 1.0 ) - {// line hit something, so paint a decal - m_flNextDecalTime = gpGlobals->curtime + decalfrequency.GetFloat(); - CSprayCan *pCan = CREATE_UNSAVED_ENTITY( CSprayCan, "spraycan" ); - pCan->Spawn( this ); - } - - break; - - case 202:// player jungle sound - if ( gpGlobals->curtime < m_flNextDecalTime ) - { - // too early! - break; - - } - - EntityMessageBegin( this ); - WRITE_BYTE( PLAY_PLAYER_JINGLE ); - MessageEnd(); - - m_flNextDecalTime = gpGlobals->curtime + decalfrequency.GetFloat(); - break; - - default: - // check all of the cheat impulse commands now - CheatImpulseCommands( iImpulse ); - break; - } - - m_nImpulse = 0; -} - -#ifdef HL2_EPISODIC - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -static void CreateJalopy( CBasePlayer *pPlayer ) -{ - // Cheat to create a jeep in front of the player - Vector vecForward; - AngleVectors( pPlayer->EyeAngles(), &vecForward ); - CBaseEntity *pJeep = (CBaseEntity *)CreateEntityByName( "prop_vehicle_jeep" ); - if ( pJeep ) - { - Vector vecOrigin = pPlayer->GetAbsOrigin() + vecForward * 256 + Vector(0,0,64); - QAngle vecAngles( 0, pPlayer->GetAbsAngles().y - 90, 0 ); - pJeep->SetAbsOrigin( vecOrigin ); - pJeep->SetAbsAngles( vecAngles ); - pJeep->KeyValue( "model", "models/vehicle.mdl" ); - pJeep->KeyValue( "solid", "6" ); - pJeep->KeyValue( "targetname", "jeep" ); - pJeep->KeyValue( "vehiclescript", "scripts/vehicles/jalopy.txt" ); - DispatchSpawn( pJeep ); - pJeep->Activate(); - pJeep->Teleport( &vecOrigin, &vecAngles, NULL ); - } -} - -void CC_CH_CreateJalopy( void ) -{ - CBasePlayer *pPlayer = UTIL_GetCommandClient(); - if ( !pPlayer ) - return; - CreateJalopy( pPlayer ); -} - -static ConCommand ch_createjalopy("ch_createjalopy", CC_CH_CreateJalopy, "Spawn jalopy in front of the player.", FCVAR_CHEAT); - -#endif // HL2_EPISODIC - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -static void CreateJeep( CBasePlayer *pPlayer ) -{ - // Cheat to create a jeep in front of the player - Vector vecForward; - AngleVectors( pPlayer->EyeAngles(), &vecForward ); - CBaseEntity *pJeep = (CBaseEntity *)CreateEntityByName( "prop_vehicle_jeep" ); - if ( pJeep ) - { - Vector vecOrigin = pPlayer->GetAbsOrigin() + vecForward * 256 + Vector(0,0,64); - QAngle vecAngles( 0, pPlayer->GetAbsAngles().y - 90, 0 ); - pJeep->SetAbsOrigin( vecOrigin ); - pJeep->SetAbsAngles( vecAngles ); - pJeep->KeyValue( "model", "models/buggy.mdl" ); - pJeep->KeyValue( "solid", "6" ); - pJeep->KeyValue( "targetname", "jeep" ); - pJeep->KeyValue( "vehiclescript", "scripts/vehicles/jeep_test.txt" ); - DispatchSpawn( pJeep ); - pJeep->Activate(); - pJeep->Teleport( &vecOrigin, &vecAngles, NULL ); - } -} - - -void CC_CH_CreateJeep( void ) -{ - CBasePlayer *pPlayer = UTIL_GetCommandClient(); - if ( !pPlayer ) - return; - CreateJeep( pPlayer ); -} - -static ConCommand ch_createjeep("ch_createjeep", CC_CH_CreateJeep, "Spawn jeep in front of the player.", FCVAR_CHEAT); - - -//----------------------------------------------------------------------------- -// Create an airboat in front of the specified player -//----------------------------------------------------------------------------- -static void CreateAirboat( CBasePlayer *pPlayer ) -{ - // Cheat to create a jeep in front of the player - Vector vecForward; - AngleVectors( pPlayer->EyeAngles(), &vecForward ); - CBaseEntity *pJeep = ( CBaseEntity* )CreateEntityByName( "prop_vehicle_airboat" ); - if ( pJeep ) - { - Vector vecOrigin = pPlayer->GetAbsOrigin() + vecForward * 256 + Vector( 0,0,64 ); - QAngle vecAngles( 0, pPlayer->GetAbsAngles().y - 90, 0 ); - pJeep->SetAbsOrigin( vecOrigin ); - pJeep->SetAbsAngles( vecAngles ); - pJeep->KeyValue( "model", "models/airboat.mdl" ); - pJeep->KeyValue( "solid", "6" ); - pJeep->KeyValue( "targetname", "airboat" ); - pJeep->KeyValue( "vehiclescript", "scripts/vehicles/airboat.txt" ); - DispatchSpawn( pJeep ); - pJeep->Activate(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CC_CH_CreateAirboat( void ) -{ - CBasePlayer *pPlayer = UTIL_GetCommandClient(); - if ( !pPlayer ) - return; - - CreateAirboat( pPlayer ); - -} - -static ConCommand ch_createairboat( "ch_createairboat", CC_CH_CreateAirboat, "Spawn airboat in front of the player.", FCVAR_CHEAT ); - - -//========================================================= -//========================================================= -void CBasePlayer::CheatImpulseCommands( int iImpulse ) -{ -#if !defined( HLDEMO_BUILD ) - if ( !sv_cheats->GetBool() ) - { - return; - } - - CBaseEntity *pEntity; - trace_t tr; - - switch ( iImpulse ) - { - case 76: - { - if (!giPrecacheGrunt) - { - giPrecacheGrunt = 1; - Msg( "You must now restart to use Grunt-o-matic.\n"); - } - else - { - Vector forward = UTIL_YawToVector( EyeAngles().y ); - Create("NPC_human_grunt", GetLocalOrigin() + forward * 128, GetLocalAngles()); - } - break; - } - - case 81: - - GiveNamedItem( "weapon_cubemap" ); - break; - - case 82: - // Cheat to create a jeep in front of the player - CreateJeep( this ); - break; - - case 83: - // Cheat to create a airboat in front of the player - CreateAirboat( this ); - break; - - case 101: - gEvilImpulse101 = true; - - EquipSuit(); - - // Give the player everything! - GiveAmmo( 255, "Pistol"); - GiveAmmo( 255, "AR2"); - GiveAmmo( 5, "AR2AltFire"); - GiveAmmo( 255, "SMG1"); - GiveAmmo( 255, "Buckshot"); - GiveAmmo( 3, "smg1_grenade"); - GiveAmmo( 3, "rpg_round"); - GiveAmmo( 5, "grenade"); - GiveAmmo( 32, "357" ); - GiveAmmo( 16, "XBowBolt" ); -#ifdef HL2_EPISODIC - GiveAmmo( 5, "Hopwire" ); -#endif - GiveNamedItem( "weapon_smg1" ); - GiveNamedItem( "weapon_frag" ); - GiveNamedItem( "weapon_crowbar" ); - GiveNamedItem( "weapon_pistol" ); - GiveNamedItem( "weapon_ar2" ); - GiveNamedItem( "weapon_shotgun" ); - GiveNamedItem( "weapon_physcannon" ); - GiveNamedItem( "weapon_bugbait" ); - GiveNamedItem( "weapon_rpg" ); - GiveNamedItem( "weapon_357" ); - GiveNamedItem( "weapon_crossbow" ); -#ifdef HL2_EPISODIC - // GiveNamedItem( "weapon_magnade" ); -#endif - if ( GetHealth() < 100 ) - { - TakeHealth( 25, DMG_GENERIC ); - } - - gEvilImpulse101 = false; - - break; - - case 102: - // Gibbage!!! - CGib::SpawnRandomGibs( this, 1, GIB_HUMAN ); - break; - - case 103: - // What the hell are you doing? - pEntity = FindEntityForward( this, true ); - if ( pEntity ) - { - CAI_BaseNPC *pNPC = pEntity->MyNPCPointer(); - if ( pNPC ) - pNPC->ReportAIState(); - } - break; - - case 106: - // Give me the classname and targetname of this entity. - pEntity = FindEntityForward( this, true ); - if ( pEntity ) - { - Msg( "Classname: %s", pEntity->GetClassname() ); - - if ( pEntity->GetEntityName() != NULL_STRING ) - { - Msg( " - Name: %s\n", STRING( pEntity->GetEntityName() ) ); - } - else - { - Msg( " - Name: No Targetname\n" ); - } - - if ( pEntity->m_iParent != NULL_STRING ) - Msg( "Parent: %s\n", STRING(pEntity->m_iParent) ); - - Msg( "Model: %s\n", STRING( pEntity->GetModelName() ) ); - if ( pEntity->m_iGlobalname != NULL_STRING ) - Msg( "Globalname: %s\n", STRING(pEntity->m_iGlobalname) ); - } - break; - - case 107: - { - trace_t tr; - - edict_t *pWorld = engine->PEntityOfEntIndex( 0 ); - - Vector start = EyePosition(); - Vector forward; - EyeVectors( &forward ); - Vector end = start + forward * 1024; - UTIL_TraceLine( start, end, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - if ( tr.m_pEnt ) - pWorld = tr.m_pEnt->edict(); - - const char *pTextureName = tr.surface.name; - - if ( pTextureName ) - Msg( "Texture: %s\n", pTextureName ); - } - break; - - // - // Sets the debug NPC to be the NPC under the crosshair. - // - case 108: - { - pEntity = FindEntityForward( this, true ); - if ( pEntity ) - { - CAI_BaseNPC *pNPC = pEntity->MyNPCPointer(); - if ( pNPC != NULL ) - { - Msg( "Debugging %s (0x%x)\n", pNPC->GetClassname(), pNPC ); - CAI_BaseNPC::SetDebugNPC( pNPC ); - } - } - break; - } - - case 195:// show shortest paths for entire level to nearest node - { - Create("node_viewer_fly", GetLocalOrigin(), GetLocalAngles()); - } - break; - case 196:// show shortest paths for entire level to nearest node - { - Create("node_viewer_large", GetLocalOrigin(), GetLocalAngles()); - } - break; - case 197:// show shortest paths for entire level to nearest node - { - Create("node_viewer_human", GetLocalOrigin(), GetLocalAngles()); - } - break; - case 202:// Random blood splatter - { - Vector forward; - EyeVectors( &forward ); - UTIL_TraceLine ( EyePosition(), - EyePosition() + forward * 128, - MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, & tr); - - if ( tr.fraction != 1.0 ) - {// line hit something, so paint a decal - CBloodSplat *pBlood = CREATE_UNSAVED_ENTITY( CBloodSplat, "bloodsplat" ); - pBlood->Spawn( this ); - } - } - break; - case 203:// remove creature. - pEntity = FindEntityForward( this, true ); - if ( pEntity ) - { - UTIL_Remove( pEntity ); -// if ( pEntity->m_takedamage ) -// pEntity->SetThink(SUB_Remove); - } - break; - } -#endif // HLDEMO_BUILD -} - - -bool CBasePlayer::ClientCommand( const CCommand &args ) -{ - const char *cmd = args[0]; -#ifdef _DEBUG - if( stricmp( cmd, "test_SmokeGrenade" ) == 0 ) - { - if ( sv_cheats && sv_cheats->GetBool() ) - { - ParticleSmokeGrenade *pSmoke = dynamic_cast( CreateEntityByName(PARTICLESMOKEGRENADE_ENTITYNAME) ); - if ( pSmoke ) - { - Vector vForward; - AngleVectors( GetLocalAngles(), &vForward ); - vForward.z = 0; - VectorNormalize( vForward ); - - pSmoke->SetLocalOrigin( GetLocalOrigin() + vForward * 100 ); - pSmoke->SetFadeTime(25, 30); // Fade out between 25 seconds and 30 seconds. - pSmoke->Activate(); - pSmoke->SetLifetime(30); - pSmoke->FillVolume(); - - return true; - } - } - } - else -#endif // _DEBUG - if( stricmp( cmd, "vehicleRole" ) == 0 ) - { - // Get the vehicle role value. - if ( args.ArgC() == 2 ) - { - // Check to see if a player is in a vehicle. - if ( IsInAVehicle() ) - { - int nRole = atoi( args[1] ); - IServerVehicle *pVehicle = GetVehicle(); - if ( pVehicle ) - { - // Only switch roles if role is empty! - if ( !pVehicle->GetPassenger( nRole ) ) - { - LeaveVehicle(); - GetInVehicle( pVehicle, nRole ); - } - } - } - - return true; - } - } - else if ( stricmp( cmd, "spectate" ) == 0 ) // join spectator team & start observer mode - { - if ( GetTeamNumber() == TEAM_SPECTATOR ) - return true; - - ConVarRef mp_allowspectators( "mp_allowspectators" ); - if ( mp_allowspectators.IsValid() ) - { - if ( ( mp_allowspectators.GetBool() == false ) && !IsHLTV() ) - { - ClientPrint( this, HUD_PRINTCENTER, "#Cannot_Be_Spectator" ); - return true; - } - } - - if ( !IsDead() ) - { - CommitSuicide(); // kill player - } - - RemoveAllItems( true ); - - ChangeTeam( TEAM_SPECTATOR ); - - StartObserverMode( OBS_MODE_ROAMING ); - return true; - } - else if ( stricmp( cmd, "spec_mode" ) == 0 ) // new observer mode - { - int mode; - - if ( GetObserverMode() == OBS_MODE_FREEZECAM ) - { - AttemptToExitFreezeCam(); - return true; - } - - // not allowed to change spectator modes when mp_fadetoblack is being used - if ( mp_fadetoblack.GetBool() ) - { - if ( GetTeamNumber() > TEAM_SPECTATOR ) - return true; - } - - // check for parameters. - if ( args.ArgC() >= 2 ) - { - mode = atoi( args[1] ); - - if ( mode < OBS_MODE_IN_EYE || mode > LAST_PLAYER_OBSERVERMODE ) - mode = OBS_MODE_IN_EYE; - } - else - { - // switch to next spec mode if no parameter given - mode = GetObserverMode() + 1; - - if ( mode > LAST_PLAYER_OBSERVERMODE ) - { - mode = OBS_MODE_IN_EYE; - } - else if ( mode < OBS_MODE_IN_EYE ) - { - mode = OBS_MODE_ROAMING; - } - - } - - // don't allow input while player or death cam animation - if ( GetObserverMode() > OBS_MODE_DEATHCAM ) - { - // set new spectator mode, don't allow OBS_MODE_NONE - if ( !SetObserverMode( mode ) ) - ClientPrint( this, HUD_PRINTCONSOLE, "#Spectator_Mode_Unkown"); - else - engine->ClientCommand( edict(), "cl_spec_mode %d", mode ); - } - else - { - // remember spectator mode for later use - m_iObserverLastMode = mode; - engine->ClientCommand( edict(), "cl_spec_mode %d", mode ); - } - - return true; - } - else if ( stricmp( cmd, "spec_next" ) == 0 ) // chase next player - { - if ( GetObserverMode() > OBS_MODE_FIXED ) - { - // set new spectator mode - CBaseEntity * target = FindNextObserverTarget( false ); - if ( target ) - { - SetObserverTarget( target ); - } - } - else if ( GetObserverMode() == OBS_MODE_FREEZECAM ) - { - AttemptToExitFreezeCam(); - } - - return true; - } - else if ( stricmp( cmd, "spec_prev" ) == 0 ) // chase prevoius player - { - if ( GetObserverMode() > OBS_MODE_FIXED ) - { - // set new spectator mode - CBaseEntity * target = FindNextObserverTarget( true ); - if ( target ) - { - SetObserverTarget( target ); - } - } - else if ( GetObserverMode() == OBS_MODE_FREEZECAM ) - { - AttemptToExitFreezeCam(); - } - - return true; - } - - else if ( stricmp( cmd, "spec_player" ) == 0 ) // chase next player - { - if ( GetObserverMode() > OBS_MODE_FIXED && args.ArgC() == 2 ) - { - int index = atoi( args[1] ); - - CBasePlayer * target; - - if ( index == 0 ) - { - target = UTIL_PlayerByName( args[1] ); - } - else - { - target = UTIL_PlayerByIndex( index ); - } - - if ( IsValidObserverTarget( target ) ) - { - SetObserverTarget( target ); - } - } - - return true; - } - - else if ( stricmp( cmd, "spec_goto" ) == 0 ) // chase next player - { - if ( ( GetObserverMode() == OBS_MODE_FIXED || - GetObserverMode() == OBS_MODE_ROAMING ) && - args.ArgC() == 6 ) - { - Vector origin; - origin.x = atof( args[1] ); - origin.y = atof( args[2] ); - origin.z = atof( args[3] ); - - QAngle angle; - angle.x = atof( args[4] ); - angle.y = atof( args[5] ); - angle.z = 0.0f; - - JumptoPosition( origin, angle ); - } - - return true; - } - else if ( stricmp( cmd, "playerperf" ) == 0 ) - { - int nRecip = entindex(); - if ( args.ArgC() >= 2 ) - { - nRecip = clamp( Q_atoi( args.Arg( 1 ) ), 1, gpGlobals->maxClients ); - } - int nRecords = -1; // all - if ( args.ArgC() >= 3 ) - { - nRecords = MAX( Q_atoi( args.Arg( 2 ) ), 1 ); - } - - CBasePlayer *pl = UTIL_PlayerByIndex( nRecip ); - if ( pl ) - { - pl->DumpPerfToRecipient( this, nRecords ); - } - return true; - } - - return false; -} - -extern bool UTIL_ItemCanBeTouchedByPlayer( CBaseEntity *pItem, CBasePlayer *pPlayer ); - -//----------------------------------------------------------------------------- -// Purpose: Player reacts to bumping a weapon. -// Input : pWeapon - the weapon that the player bumped into. -// Output : Returns true if player picked up the weapon -//----------------------------------------------------------------------------- -bool CBasePlayer::BumpWeapon( CBaseCombatWeapon *pWeapon ) -{ - CBaseCombatCharacter *pOwner = pWeapon->GetOwner(); - - // Can I have this weapon type? - if ( !IsAllowedToPickupWeapons() ) - return false; - - if ( pOwner || !Weapon_CanUse( pWeapon ) || !g_pGameRules->CanHavePlayerItem( this, pWeapon ) ) - { - if ( gEvilImpulse101 ) - { - UTIL_Remove( pWeapon ); - } - return false; - } - - // Act differently in the episodes - if ( hl2_episodic.GetBool() ) - { - // Don't let the player touch the item unless unobstructed - if ( !UTIL_ItemCanBeTouchedByPlayer( pWeapon, this ) && !gEvilImpulse101 ) - return false; - } - else - { - // Don't let the player fetch weapons through walls (use MASK_SOLID so that you can't pickup through windows) - if( pWeapon->FVisible( this, MASK_SOLID ) == false && !(GetFlags() & FL_NOTARGET) ) - return false; - } - - // ---------------------------------------- - // If I already have it just take the ammo - // ---------------------------------------- - if (Weapon_OwnsThisType( pWeapon->GetClassname(), pWeapon->GetSubType())) - { - if( Weapon_EquipAmmoOnly( pWeapon ) ) - { - // Only remove me if I have no ammo left - if ( pWeapon->HasPrimaryAmmo() ) - return false; - - UTIL_Remove( pWeapon ); - return true; - } - else - { - return false; - } - } - // ------------------------- - // Otherwise take the weapon - // ------------------------- - else - { - pWeapon->CheckRespawn(); - - pWeapon->AddSolidFlags( FSOLID_NOT_SOLID ); - pWeapon->AddEffects( EF_NODRAW ); - - Weapon_Equip( pWeapon ); - if ( IsInAVehicle() ) - { - pWeapon->Holster(); - } - else - { -#ifdef HL2_DLL - - if ( IsX360() ) - { - CFmtStr hint; - hint.sprintf( "#valve_hint_select_%s", pWeapon->GetClassname() ); - UTIL_HudHintText( this, hint.Access() ); - } - - // Always switch to a newly-picked up weapon - if ( !PlayerHasMegaPhysCannon() ) - { - // If it uses clips, load it full. (this is the first time you've picked up this type of weapon) - if ( pWeapon->UsesClipsForAmmo1() ) - { - pWeapon->m_iClip1 = pWeapon->GetMaxClip1(); - } - - Weapon_Switch( pWeapon ); - } -#endif - } - return true; - } -} - - -bool CBasePlayer::RemovePlayerItem( CBaseCombatWeapon *pItem ) -{ - if (GetActiveWeapon() == pItem) - { - ResetAutoaim( ); - pItem->Holster( ); - pItem->SetNextThink( TICK_NEVER_THINK );; // crowbar may be trying to swing again, etc - pItem->SetThink( NULL ); - } - - if ( m_hLastWeapon.Get() == pItem ) - { - Weapon_SetLast( NULL ); - } - - return Weapon_Detach( pItem ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Hides or shows the player's view model. The "r_drawviewmodel" cvar -// can still hide the viewmodel even if this is set to true. -// Input : bShow - true to show, false to hide the view model. -//----------------------------------------------------------------------------- -void CBasePlayer::ShowViewModel(bool bShow) -{ - m_Local.m_bDrawViewmodel = bShow; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : bDraw - -//----------------------------------------------------------------------------- -void CBasePlayer::ShowCrosshair( bool bShow ) -{ - if ( bShow ) - { - m_Local.m_iHideHUD &= ~HIDEHUD_CROSSHAIR; - } - else - { - m_Local.m_iHideHUD |= HIDEHUD_CROSSHAIR; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -QAngle CBasePlayer::BodyAngles() -{ - return EyeAngles(); -} - -//------------------------------------------------------------------------------ -// Purpose : Add noise to BodyTarget() to give enemy a better chance of -// getting a clear shot when the player is peeking above a hole -// or behind a ladder (eventually the randomly-picked point -// along the spine will be one that is exposed above the hole or -// between rungs of a ladder.) -// Input : -// Output : -//------------------------------------------------------------------------------ -Vector CBasePlayer::BodyTarget( const Vector &posSrc, bool bNoisy ) -{ - if ( IsInAVehicle() ) - { - return GetVehicle()->GetVehicleEnt()->BodyTarget( posSrc, bNoisy ); - } - if (bNoisy) - { - return GetAbsOrigin() + (GetViewOffset() * random->RandomFloat( 0.7, 1.0 )); - } - else - { - return EyePosition(); - } -}; - -/* -========================================================= - UpdateClientData - -resends any changed player HUD info to the client. -Called every frame by PlayerPreThink -Also called at start of demo recording and playback by -ForceClientDllUpdate to ensure the demo gets messages -reflecting all of the HUD state info. -========================================================= -*/ -void CBasePlayer::UpdateClientData( void ) -{ - CSingleUserRecipientFilter user( this ); - user.MakeReliable(); - - if (m_fInitHUD) - { - m_fInitHUD = false; - gInitHUD = false; - - UserMessageBegin( user, "ResetHUD" ); - WRITE_BYTE( 0 ); - MessageEnd(); - - if ( !m_fGameHUDInitialized ) - { - g_pGameRules->InitHUD( this ); - InitHUD(); - m_fGameHUDInitialized = true; - if ( g_pGameRules->IsMultiplayer() ) - { - variant_t value; - g_EventQueue.AddEvent( "game_player_manager", "OnPlayerJoin", value, 0, this, this ); - } - } - - variant_t value; - g_EventQueue.AddEvent( "game_player_manager", "OnPlayerSpawn", value, 0, this, this ); - } - - // HACKHACK -- send the message to display the game title - CWorld *world = GetWorldEntity(); - if ( world && world->GetDisplayTitle() ) - { - UserMessageBegin( user, "GameTitle" ); - MessageEnd(); - world->SetDisplayTitle( false ); - } - - if (m_ArmorValue != m_iClientBattery) - { - m_iClientBattery = m_ArmorValue; - - // send "battery" update message - if ( usermessages->LookupUserMessage( "Battery" ) != -1 ) - { - UserMessageBegin( user, "Battery" ); - WRITE_SHORT( (int)m_ArmorValue); - MessageEnd(); - } - } - -#if 0 // BYE BYE!! - // Update Flashlight - if ((m_flFlashLightTime) && (m_flFlashLightTime <= gpGlobals->curtime)) - { - if (FlashlightIsOn()) - { - if (m_iFlashBattery) - { - m_flFlashLightTime = FLASH_DRAIN_TIME + gpGlobals->curtime; - m_iFlashBattery--; - - if (!m_iFlashBattery) - FlashlightTurnOff(); - } - } - else - { - if (m_iFlashBattery < 100) - { - m_flFlashLightTime = FLASH_CHARGE_TIME + gpGlobals->curtime; - m_iFlashBattery++; - } - else - m_flFlashLightTime = 0; - } - } -#endif - - CheckTrainUpdate(); - - // Update all the items - for ( int i = 0; i < WeaponCount(); i++ ) - { - if ( GetWeapon(i) ) // each item updates it's successors - GetWeapon(i)->UpdateClientData( this ); - } - - // update the client with our poison state - m_Local.m_bPoisoned = ( m_bitsDamageType & DMG_POISON ) - && ( m_nPoisonDmg > m_nPoisonRestored ) - && ( m_iHealth < 100 ); - - // Check if the bonus progress HUD element should be displayed - if ( m_iBonusChallenge == 0 && m_iBonusProgress == 0 && !( m_Local.m_iHideHUD & HIDEHUD_BONUS_PROGRESS ) ) - m_Local.m_iHideHUD |= HIDEHUD_BONUS_PROGRESS; - if ( ( m_iBonusChallenge != 0 )&& ( m_Local.m_iHideHUD & HIDEHUD_BONUS_PROGRESS ) ) - m_Local.m_iHideHUD &= ~HIDEHUD_BONUS_PROGRESS; - - // Let any global rules update the HUD, too - g_pGameRules->UpdateClientData( this ); -} - -void CBasePlayer::RumbleEffect( unsigned char index, unsigned char rumbleData, unsigned char rumbleFlags ) -{ - if( !IsAlive() ) - return; - - CSingleUserRecipientFilter filter( this ); - filter.MakeReliable(); - - UserMessageBegin( filter, "Rumble" ); - WRITE_BYTE( index ); - WRITE_BYTE( rumbleData ); - WRITE_BYTE( rumbleFlags ); - MessageEnd(); -} - -void CBasePlayer::EnableControl(bool fControl) -{ - if (!fControl) - AddFlag( FL_FROZEN ); - else - RemoveFlag( FL_FROZEN ); - -} - -void CBasePlayer::CheckTrainUpdate( void ) -{ - if ( ( m_iTrain & TRAIN_NEW ) ) - { - CSingleUserRecipientFilter user( this ); - user.MakeReliable(); - - // send "Train" update message - UserMessageBegin( user, "Train" ); - WRITE_BYTE(m_iTrain & 0xF); - MessageEnd(); - - m_iTrain &= ~TRAIN_NEW; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Returns whether the player should autoaim or not -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBasePlayer::ShouldAutoaim( void ) -{ - // cannot be in multiplayer - if ( gpGlobals->maxClients > 1 ) - return false; - - // autoaiming is only for easy and medium skill - return ( IsX360() || !g_pGameRules->IsSkillLevel(SKILL_HARD) ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Vector CBasePlayer::GetAutoaimVector( float flScale ) -{ - autoaim_params_t params; - - params.m_fScale = flScale; - params.m_fMaxDist = autoaim_max_dist.GetFloat(); - - GetAutoaimVector( params ); - return params.m_vecAutoAimDir; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Vector CBasePlayer::GetAutoaimVector( float flScale, float flMaxDist ) -{ - autoaim_params_t params; - - params.m_fScale = flScale; - params.m_fMaxDist = flMaxDist; - - GetAutoaimVector( params ); - return params.m_vecAutoAimDir; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CBasePlayer::GetAutoaimVector( autoaim_params_t ¶ms ) -{ - // Assume autoaim will not be assisting. - params.m_bAutoAimAssisting = false; - - if ( ( ShouldAutoaim() == false ) || ( params.m_fScale == AUTOAIM_SCALE_DIRECT_ONLY ) ) - { - Vector forward; - AngleVectors( EyeAngles() + m_Local.m_vecPunchAngle, &forward ); - - params.m_vecAutoAimDir = forward; - params.m_hAutoAimEntity.Set(NULL); - params.m_vecAutoAimPoint = vec3_invalid; - params.m_bAutoAimAssisting = false; - return; - } - - Vector vecSrc = Weapon_ShootPosition( ); - - m_vecAutoAim.Init( 0.0f, 0.0f, 0.0f ); - - QAngle angles = AutoaimDeflection( vecSrc, params ); - - // update ontarget if changed - if ( !g_pGameRules->AllowAutoTargetCrosshair() ) - m_fOnTarget = false; - - if (angles.x > 180) - angles.x -= 360; - if (angles.x < -180) - angles.x += 360; - if (angles.y > 180) - angles.y -= 360; - if (angles.y < -180) - angles.y += 360; - - if (angles.x > 25) - angles.x = 25; - if (angles.x < -25) - angles.x = -25; - if (angles.y > 12) - angles.y = 12; - if (angles.y < -12) - angles.y = -12; - - Vector forward; - - if( IsInAVehicle() && g_pGameRules->GetAutoAimMode() == AUTOAIM_ON_CONSOLE ) - { - m_vecAutoAim = angles; - AngleVectors( EyeAngles() + m_vecAutoAim, &forward ); - } - else - { - // always use non-sticky autoaim - m_vecAutoAim = angles * 0.9f; - AngleVectors( EyeAngles() + m_Local.m_vecPunchAngle + m_vecAutoAim, &forward ); - } - - params.m_vecAutoAimDir = forward; -} - -//----------------------------------------------------------------------------- -// Targets represent themselves to autoaim as a viewplane-parallel disc with -// a radius specified by the target. The player then modifies this radius -// to achieve more or less aggressive aiming assistance -//----------------------------------------------------------------------------- -float CBasePlayer::GetAutoaimScore( const Vector &eyePosition, const Vector &viewDir, const Vector &vecTarget, CBaseEntity *pTarget, float fScale, CBaseCombatWeapon *pActiveWeapon ) -{ - float radiusSqr; - float targetRadius = pTarget->GetAutoAimRadius() * fScale; - - if( pActiveWeapon != NULL ) - targetRadius *= pActiveWeapon->WeaponAutoAimScale(); - - float targetRadiusSqr = Square( targetRadius ); - - Vector vecNearestPoint = PointOnLineNearestPoint( eyePosition, eyePosition + viewDir * 8192, vecTarget ); - Vector vecDiff = vecTarget - vecNearestPoint; - - radiusSqr = vecDiff.LengthSqr(); - - if( radiusSqr <= targetRadiusSqr ) - { - float score; - - score = 1.0f - (radiusSqr / targetRadiusSqr); - - Assert( score >= 0.0f && score <= 1.0f ); - return score; - } - - // 0 means no score- doesn't qualify for autoaim. - return 0.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &vecSrc - -// flDist - -// flDelta - -// Output : Vector -//----------------------------------------------------------------------------- -QAngle CBasePlayer::AutoaimDeflection( Vector &vecSrc, autoaim_params_t ¶ms ) -{ - float bestscore; - float score; - QAngle eyeAngles; - Vector bestdir; - CBaseEntity *bestent; - trace_t tr; - Vector v_forward, v_right, v_up; - - if ( ShouldAutoaim() == false ) - { - m_fOnTarget = false; - return vec3_angle; - } - - eyeAngles = EyeAngles(); - AngleVectors( eyeAngles + m_Local.m_vecPunchAngle + m_vecAutoAim, &v_forward, &v_right, &v_up ); - - // try all possible entities - bestdir = v_forward; - bestscore = 0.0f; - bestent = NULL; - - //Reset this data - m_fOnTarget = false; - params.m_bOnTargetNatural = false; - - CBaseEntity *pIgnore = NULL; - - if( IsInAVehicle() ) - { - pIgnore = GetVehicleEntity(); - } - - CTraceFilterSkipTwoEntities traceFilter( this, pIgnore, COLLISION_GROUP_NONE ); - - UTIL_TraceLine( vecSrc, vecSrc + bestdir * MAX_COORD_FLOAT, MASK_SHOT, &traceFilter, &tr ); - - CBaseEntity *pEntHit = tr.m_pEnt; - - if ( pEntHit && pEntHit->m_takedamage != DAMAGE_NO && pEntHit->GetHealth() > 0 ) - { - // don't look through water - if (!((GetWaterLevel() != 3 && pEntHit->GetWaterLevel() == 3) || (GetWaterLevel() == 3 && pEntHit->GetWaterLevel() == 0))) - { - if( pEntHit->ShouldAttractAutoAim(this) ) - { - bool bAimAtThis = true; - - if( pEntHit->IsNPC() && g_pGameRules->GetAutoAimMode() > AUTOAIM_NONE ) - { - int iRelationType = GetDefaultRelationshipDisposition( pEntHit->Classify() ); - - if( iRelationType != D_HT ) - { - bAimAtThis = false; - } - } - - if( bAimAtThis ) - { - if ( pEntHit->GetFlags() & FL_AIMTARGET ) - { - m_fOnTarget = true; - } - - // Player is already on target naturally, don't autoaim. - // Fill out the autoaim_params_t struct, though. - params.m_hAutoAimEntity.Set(pEntHit); - params.m_vecAutoAimDir = bestdir; - params.m_vecAutoAimPoint = tr.endpos; - params.m_bAutoAimAssisting = false; - params.m_bOnTargetNatural = true; - return vec3_angle; - } - } - - //Fall through and look for an autoaim ent. - } - } - - int count = AimTarget_ListCount(); - if ( count ) - { - CBaseEntity **pList = (CBaseEntity **)stackalloc( sizeof(CBaseEntity *) * count ); - AimTarget_ListCopy( pList, count ); - - for ( int i = 0; i < count; i++ ) - { - Vector center; - Vector dir; - CBaseEntity *pEntity = pList[i]; - - // Don't autoaim at anything that doesn't want to be. - if( !pEntity->ShouldAttractAutoAim(this) ) - continue; - - // Don't shoot yourself - if ( pEntity == this ) - continue; - - if ( (pEntity->IsNPC() && !pEntity->IsAlive()) || !pEntity->edict() ) - continue; - - if ( !g_pGameRules->ShouldAutoAim( this, pEntity->edict() ) ) - continue; - - // don't look through water - if ((GetWaterLevel() != 3 && pEntity->GetWaterLevel() == 3) || (GetWaterLevel() == 3 && pEntity->GetWaterLevel() == 0)) - continue; - - if( pEntity->MyNPCPointer() ) - { - // If this entity is an NPC, only aim if it is an enemy. - if ( IRelationType( pEntity ) != D_HT ) - { - if ( !pEntity->IsPlayer() && !g_pGameRules->IsDeathmatch()) - // Msg( "friend\n"); - continue; - } - } - - // Don't autoaim at the noisy bodytarget, this makes the autoaim crosshair wobble. - //center = pEntity->BodyTarget( vecSrc, false ); - center = pEntity->WorldSpaceCenter(); - - dir = (center - vecSrc); - - float dist = dir.Length2D(); - VectorNormalize( dir ); - - // Skip if out of range. - if( dist > params.m_fMaxDist ) - continue; - - float dot = DotProduct (dir, v_forward ); - - // make sure it's in front of the player - if( dot < 0 ) - continue; - - if( !(pEntity->GetFlags() & FL_FLY) ) - { - // Refuse to take wild shots at targets far from reticle. - if( GetActiveWeapon() != NULL && dot < GetActiveWeapon()->GetMaxAutoAimDeflection() ) - { - // Be lenient if the player is looking down, though. 30 degrees through 90 degrees of pitch. - // (90 degrees is looking down at player's own 'feet'. Looking straight ahead is 0 degrees pitch. - // This was done for XBox to make it easier to fight headcrabs around the player's feet. - if( eyeAngles.x < 30.0f || eyeAngles.x > 90.0f || g_pGameRules->GetAutoAimMode() != AUTOAIM_ON_CONSOLE ) - { - continue; - } - } - } - - score = GetAutoaimScore(vecSrc, v_forward, pEntity->GetAutoAimCenter(), pEntity, params.m_fScale, GetActiveWeapon() ); - - if( score <= bestscore ) - { - continue; - } - - UTIL_TraceLine( vecSrc, center, MASK_SHOT, &traceFilter, &tr ); - - if (tr.fraction != 1.0 && tr.m_pEnt != pEntity ) - { - // Msg( "hit %s, can't see %s\n", STRING( tr.u.ent->classname ), STRING( pEdict->classname ) ); - continue; - } - - // This is the best candidate so far. - bestscore = score; - bestent = pEntity; - bestdir = dir; - } - if ( bestent ) - { - QAngle bestang; - - VectorAngles( bestdir, bestang ); - - if( IsInAVehicle() ) - { - bestang -= EyeAngles(); - } - else - { - bestang -= EyeAngles() - m_Local.m_vecPunchAngle; - } - - m_fOnTarget = true; - - // Autoaim detected a target for us. Aim automatically at its bodytarget. - params.m_hAutoAimEntity.Set(bestent); - params.m_vecAutoAimDir = bestdir; - params.m_vecAutoAimPoint = bestent->BodyTarget( vecSrc, false ); - params.m_bAutoAimAssisting = true; - - return bestang; - } - } - - return vec3_angle; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::ResetAutoaim( void ) -{ - if (m_vecAutoAim.x != 0 || m_vecAutoAim.y != 0) - { - m_vecAutoAim = QAngle( 0, 0, 0 ); - engine->CrosshairAngle( edict(), 0, 0 ); - } - m_fOnTarget = false; -} - -// ========================================================================== -// > Weapon stuff -// ========================================================================== - -//----------------------------------------------------------------------------- -// Purpose: Override base class, player can always use weapon -// Input : A weapon -// Output : true or false -//----------------------------------------------------------------------------- -bool CBasePlayer::Weapon_CanUse( CBaseCombatWeapon *pWeapon ) -{ - return true; -} - - - -//----------------------------------------------------------------------------- -// Purpose: Override to clear dropped weapon from the hud -//----------------------------------------------------------------------------- -void CBasePlayer::Weapon_Drop( CBaseCombatWeapon *pWeapon, const Vector *pvecTarget /* = NULL */, const Vector *pVelocity /* = NULL */ ) -{ - bool bWasActiveWeapon = false; - if ( pWeapon == GetActiveWeapon() ) - { - bWasActiveWeapon = true; - } - - if ( pWeapon ) - { - if ( bWasActiveWeapon ) - { - pWeapon->SendWeaponAnim( ACT_VM_IDLE ); - } - } - - BaseClass::Weapon_Drop( pWeapon, pvecTarget, pVelocity ); - - if ( bWasActiveWeapon ) - { - if (!SwitchToNextBestWeapon( NULL )) - { - CBaseViewModel *vm = GetViewModel(); - if ( vm ) - { - vm->AddEffects( EF_NODRAW ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : weaponSlot - -//----------------------------------------------------------------------------- -void CBasePlayer::Weapon_DropSlot( int weaponSlot ) -{ - CBaseCombatWeapon *pWeapon; - - // Check for that slot being occupied already - for ( int i=0; i < MAX_WEAPONS; i++ ) - { - pWeapon = GetWeapon( i ); - - if ( pWeapon != NULL ) - { - // If the slots match, it's already occupied - if ( pWeapon->GetSlot() == weaponSlot ) - { - Weapon_Drop( pWeapon, NULL, NULL ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Override to add weapon to the hud -//----------------------------------------------------------------------------- -void CBasePlayer::Weapon_Equip( CBaseCombatWeapon *pWeapon ) -{ - BaseClass::Weapon_Equip( pWeapon ); - - bool bShouldSwitch = g_pGameRules->FShouldSwitchWeapon( this, pWeapon ); - -#ifdef HL2_DLL - if ( bShouldSwitch == false && PhysCannonGetHeldEntity( GetActiveWeapon() ) == pWeapon && - Weapon_OwnsThisType( pWeapon->GetClassname(), pWeapon->GetSubType()) ) - { - bShouldSwitch = true; - } -#endif//HL2_DLL - - // should we switch to this item? - if ( bShouldSwitch ) - { - Weapon_Switch( pWeapon ); - } -} - - -//========================================================= -// HasNamedPlayerItem Does the player already have this item? -//========================================================= -CBaseEntity *CBasePlayer::HasNamedPlayerItem( const char *pszItemName ) -{ - for ( int i = 0 ; i < WeaponCount() ; i++ ) - { - if ( !GetWeapon(i) ) - continue; - - if ( FStrEq( pszItemName, GetWeapon(i)->GetClassname() ) ) - { - return GetWeapon(i); - } - } - - return NULL; -} - - - -//================================================================================ -// TEAM HANDLING -//================================================================================ -//----------------------------------------------------------------------------- -// Purpose: Put the player in the specified team -//----------------------------------------------------------------------------- - -void CBasePlayer::ChangeTeam( int iTeamNum ) -{ - if ( !GetGlobalTeam( iTeamNum ) ) - { - Warning( "CBasePlayer::ChangeTeam( %d ) - invalid team index.\n", iTeamNum ); - return; - } - - // if this is our current team, just abort - if ( iTeamNum == GetTeamNumber() ) - { - return; - } - - // Immediately tell all clients that he's changing team. This has to be done - // first, so that all user messages that follow as a result of the team change - // come after this one, allowing the client to be prepared for them. - IGameEvent * event = gameeventmanager->CreateEvent( "player_team" ); - if ( event ) - { - event->SetInt("userid", GetUserID() ); - event->SetInt("team", iTeamNum ); - event->SetInt("oldteam", GetTeamNumber() ); - event->SetInt("disconnect", IsDisconnecting()); - - gameeventmanager->FireEvent( event ); - } - - // Remove him from his current team - if ( GetTeam() ) - { - GetTeam()->RemovePlayer( this ); - } - - // Are we being added to a team? - if ( iTeamNum ) - { - GetGlobalTeam( iTeamNum )->AddPlayer( this ); - } - - BaseClass::ChangeTeam( iTeamNum ); -} - - - -//----------------------------------------------------------------------------- -// Purpose: Locks a player to the spot; they can't move, shoot, or be hurt -//----------------------------------------------------------------------------- -void CBasePlayer::LockPlayerInPlace( void ) -{ - if ( m_iPlayerLocked ) - return; - - AddFlag( FL_GODMODE | FL_FROZEN ); - SetMoveType( MOVETYPE_NONE ); - m_iPlayerLocked = true; - - // force a client data update, so that anything that has been done to - // this player previously this frame won't get delayed in being sent - UpdateClientData(); -} - -//----------------------------------------------------------------------------- -// Purpose: Unlocks a previously locked player -//----------------------------------------------------------------------------- -void CBasePlayer::UnlockPlayer( void ) -{ - if ( !m_iPlayerLocked ) - return; - - RemoveFlag( FL_GODMODE | FL_FROZEN ); - SetMoveType( MOVETYPE_WALK ); - m_iPlayerLocked = false; -} - -bool CBasePlayer::ClearUseEntity() -{ - if ( m_hUseEntity != NULL ) - { - // Stop controlling the train/object - // TODO: Send HUD Update - m_hUseEntity->Use( this, this, USE_OFF, 0 ); - m_hUseEntity = NULL; - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::HideViewModels( void ) -{ - for ( int i = 0 ; i < MAX_VIEWMODELS; i++ ) - { - CBaseViewModel *vm = GetViewModel( i ); - if ( !vm ) - continue; - - vm->SetWeaponModel( NULL, NULL ); - } -} - -class CStripWeapons : public CPointEntity -{ - DECLARE_CLASS( CStripWeapons, CPointEntity ); -public: - void InputStripWeapons(inputdata_t &data); - void InputStripWeaponsAndSuit(inputdata_t &data); - - void StripWeapons(inputdata_t &data, bool stripSuit); - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( player_weaponstrip, CStripWeapons ); - -BEGIN_DATADESC( CStripWeapons ) - DEFINE_INPUTFUNC( FIELD_VOID, "Strip", InputStripWeapons ), - DEFINE_INPUTFUNC( FIELD_VOID, "StripWeaponsAndSuit", InputStripWeaponsAndSuit ), -END_DATADESC() - - -void CStripWeapons::InputStripWeapons(inputdata_t &data) -{ - StripWeapons(data, false); -} - -void CStripWeapons::InputStripWeaponsAndSuit(inputdata_t &data) -{ - StripWeapons(data, true); -} - -void CStripWeapons::StripWeapons(inputdata_t &data, bool stripSuit) -{ - CBasePlayer *pPlayer = NULL; - - if ( data.pActivator && data.pActivator->IsPlayer() ) - { - pPlayer = (CBasePlayer *)data.pActivator; - } - else if ( !g_pGameRules->IsDeathmatch() ) - { - pPlayer = UTIL_GetLocalPlayer(); - } - - if ( pPlayer ) - { - pPlayer->RemoveAllItems( stripSuit ); - } -} - - -class CRevertSaved : public CPointEntity -{ - DECLARE_CLASS( CRevertSaved, CPointEntity ); -public: - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - void LoadThink( void ); - - DECLARE_DATADESC(); - - inline float Duration( void ) { return m_Duration; } - inline float HoldTime( void ) { return m_HoldTime; } - inline float LoadTime( void ) { return m_loadTime; } - - inline void SetDuration( float duration ) { m_Duration = duration; } - inline void SetHoldTime( float hold ) { m_HoldTime = hold; } - inline void SetLoadTime( float time ) { m_loadTime = time; } - - //Inputs - void InputReload(inputdata_t &data); - -#ifdef HL1_DLL - void MessageThink( void ); - inline float MessageTime( void ) { return m_messageTime; } - inline void SetMessageTime( float time ) { m_messageTime = time; } -#endif - -private: - - float m_loadTime; - float m_Duration; - float m_HoldTime; - -#ifdef HL1_DLL - string_t m_iszMessage; - float m_messageTime; -#endif -}; - -LINK_ENTITY_TO_CLASS( player_loadsaved, CRevertSaved ); - -BEGIN_DATADESC( CRevertSaved ) - -#ifdef HL1_DLL - DEFINE_KEYFIELD( m_iszMessage, FIELD_STRING, "message" ), - DEFINE_KEYFIELD( m_messageTime, FIELD_FLOAT, "messagetime" ), // These are not actual times, but durations, so save as floats - - DEFINE_FUNCTION( MessageThink ), -#endif - - DEFINE_KEYFIELD( m_loadTime, FIELD_FLOAT, "loadtime" ), - DEFINE_KEYFIELD( m_Duration, FIELD_FLOAT, "duration" ), - DEFINE_KEYFIELD( m_HoldTime, FIELD_FLOAT, "holdtime" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Reload", InputReload ), - - - // Function Pointers - DEFINE_FUNCTION( LoadThink ), - -END_DATADESC() - -CBaseEntity *CreatePlayerLoadSave( Vector vOrigin, float flDuration, float flHoldTime, float flLoadTime ) -{ - CRevertSaved *pRevertSaved = (CRevertSaved *) CreateEntityByName( "player_loadsaved" ); - - if ( pRevertSaved == NULL ) - return NULL; - - UTIL_SetOrigin( pRevertSaved, vOrigin ); - - pRevertSaved->Spawn(); - pRevertSaved->SetDuration( flDuration ); - pRevertSaved->SetHoldTime( flHoldTime ); - pRevertSaved->SetLoadTime( flLoadTime ); - - return pRevertSaved; -} - - - -void CRevertSaved::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - UTIL_ScreenFadeAll( m_clrRender, Duration(), HoldTime(), FFADE_OUT ); - SetNextThink( gpGlobals->curtime + LoadTime() ); - SetThink( &CRevertSaved::LoadThink ); - - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - - if ( pPlayer ) - { - //Adrian: Setting this flag so we can't move or save a game. - pPlayer->pl.deadflag = true; - pPlayer->AddFlag( (FL_NOTARGET|FL_FROZEN) ); - - // clear any pending autosavedangerous - g_ServerGameDLL.m_fAutoSaveDangerousTime = 0.0f; - g_ServerGameDLL.m_fAutoSaveDangerousMinHealthToCommit = 0.0f; - } -} - -void CRevertSaved::InputReload( inputdata_t &inputdata ) -{ - UTIL_ScreenFadeAll( m_clrRender, Duration(), HoldTime(), FFADE_OUT ); - -#ifdef HL1_DLL - SetNextThink( gpGlobals->curtime + MessageTime() ); - SetThink( &CRevertSaved::MessageThink ); -#else - SetNextThink( gpGlobals->curtime + LoadTime() ); - SetThink( &CRevertSaved::LoadThink ); -#endif - - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - - if ( pPlayer ) - { - //Adrian: Setting this flag so we can't move or save a game. - pPlayer->pl.deadflag = true; - pPlayer->AddFlag( (FL_NOTARGET|FL_FROZEN) ); - - // clear any pending autosavedangerous - g_ServerGameDLL.m_fAutoSaveDangerousTime = 0.0f; - g_ServerGameDLL.m_fAutoSaveDangerousMinHealthToCommit = 0.0f; - } -} - -#ifdef HL1_DLL -void CRevertSaved::MessageThink( void ) -{ - UTIL_ShowMessageAll( STRING( m_iszMessage ) ); - float nextThink = LoadTime() - MessageTime(); - if ( nextThink > 0 ) - { - SetNextThink( gpGlobals->curtime + nextThink ); - SetThink( &CRevertSaved::LoadThink ); - } - else - LoadThink(); -} -#endif - - -void CRevertSaved::LoadThink( void ) -{ - if ( !gpGlobals->deathmatch ) - { - engine->ServerCommand("reload\n"); - } -} - -#define SF_SPEED_MOD_SUPPRESS_WEAPONS (1<<0) // Take away weapons -#define SF_SPEED_MOD_SUPPRESS_HUD (1<<1) // Take away the HUD -#define SF_SPEED_MOD_SUPPRESS_JUMP (1<<2) -#define SF_SPEED_MOD_SUPPRESS_DUCK (1<<3) -#define SF_SPEED_MOD_SUPPRESS_USE (1<<4) -#define SF_SPEED_MOD_SUPPRESS_SPEED (1<<5) -#define SF_SPEED_MOD_SUPPRESS_ATTACK (1<<6) -#define SF_SPEED_MOD_SUPPRESS_ZOOM (1<<7) - -class CMovementSpeedMod : public CPointEntity -{ - DECLARE_CLASS( CMovementSpeedMod, CPointEntity ); -public: - void InputSpeedMod(inputdata_t &data); - -private: - int GetDisabledButtonMask( void ); - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( player_speedmod, CMovementSpeedMod ); - -BEGIN_DATADESC( CMovementSpeedMod ) - DEFINE_INPUTFUNC( FIELD_FLOAT, "ModifySpeed", InputSpeedMod ), -END_DATADESC() - -int CMovementSpeedMod::GetDisabledButtonMask( void ) -{ - int nMask = 0; - - if ( HasSpawnFlags( SF_SPEED_MOD_SUPPRESS_JUMP ) ) - { - nMask |= IN_JUMP; - } - - if ( HasSpawnFlags( SF_SPEED_MOD_SUPPRESS_DUCK ) ) - { - nMask |= IN_DUCK; - } - - if ( HasSpawnFlags( SF_SPEED_MOD_SUPPRESS_USE ) ) - { - nMask |= IN_USE; - } - - if ( HasSpawnFlags( SF_SPEED_MOD_SUPPRESS_SPEED ) ) - { - nMask |= IN_SPEED; - } - - if ( HasSpawnFlags( SF_SPEED_MOD_SUPPRESS_ATTACK ) ) - { - nMask |= (IN_ATTACK|IN_ATTACK2); - } - - if ( HasSpawnFlags( SF_SPEED_MOD_SUPPRESS_ZOOM ) ) - { - nMask |= IN_ZOOM; - } - - return nMask; -} - -void CMovementSpeedMod::InputSpeedMod(inputdata_t &data) -{ - CBasePlayer *pPlayer = NULL; - - if ( data.pActivator && data.pActivator->IsPlayer() ) - { - pPlayer = (CBasePlayer *)data.pActivator; - } - else if ( !g_pGameRules->IsDeathmatch() ) - { - pPlayer = UTIL_GetLocalPlayer(); - } - - if ( pPlayer ) - { - if ( data.value.Float() != 1.0f ) - { - // Holster weapon immediately, to allow it to cleanup - if ( HasSpawnFlags( SF_SPEED_MOD_SUPPRESS_WEAPONS ) ) - { - if ( pPlayer->GetActiveWeapon() ) - { - pPlayer->Weapon_SetLast( pPlayer->GetActiveWeapon() ); - pPlayer->GetActiveWeapon()->Holster(); - pPlayer->ClearActiveWeapon(); - } - - pPlayer->HideViewModels(); - } - - // Turn off the flashlight - if ( pPlayer->FlashlightIsOn() ) - { - pPlayer->FlashlightTurnOff(); - } - - // Disable the flashlight's further use - pPlayer->SetFlashlightEnabled( false ); - pPlayer->DisableButtons( GetDisabledButtonMask() ); - - // Hide the HUD - if ( HasSpawnFlags( SF_SPEED_MOD_SUPPRESS_HUD ) ) - { - pPlayer->m_Local.m_iHideHUD |= HIDEHUD_ALL; - } - } - else - { - // Bring the weapon back - if ( HasSpawnFlags( SF_SPEED_MOD_SUPPRESS_WEAPONS ) && pPlayer->GetActiveWeapon() == NULL ) - { - pPlayer->SetActiveWeapon( pPlayer->Weapon_GetLast() ); - if ( pPlayer->GetActiveWeapon() ) - { - pPlayer->GetActiveWeapon()->Deploy(); - } - } - - // Allow the flashlight again - pPlayer->SetFlashlightEnabled( true ); - pPlayer->EnableButtons( GetDisabledButtonMask() ); - - // Restore the HUD - if ( HasSpawnFlags( SF_SPEED_MOD_SUPPRESS_HUD ) ) - { - pPlayer->m_Local.m_iHideHUD &= ~HIDEHUD_ALL; - } - } - - pPlayer->SetLaggedMovementValue( data.value.Float() ); - } -} - - -void SendProxy_CropFlagsToPlayerFlagBitsLength( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID) -{ - int mask = (1<m_Int = ( data & mask ); -} -// -------------------------------------------------------------------------------- // -// SendTable for CPlayerState. -// -------------------------------------------------------------------------------- // - - BEGIN_SEND_TABLE_NOBASE(CPlayerState, DT_PlayerState) - SendPropInt (SENDINFO(deadflag), 1, SPROP_UNSIGNED ), - END_SEND_TABLE() - -// -------------------------------------------------------------------------------- // -// This data only gets sent to clients that ARE this player entity. -// -------------------------------------------------------------------------------- // - - BEGIN_SEND_TABLE_NOBASE( CBasePlayer, DT_LocalPlayerExclusive ) - - SendPropDataTable ( SENDINFO_DT(m_Local), &REFERENCE_SEND_TABLE(DT_Local) ), - -// If HL2_DLL is defined, then baseflex.cpp already sends these. -#ifndef HL2_DLL - SendPropFloat ( SENDINFO_VECTORELEM2(m_vecViewOffset, 0, x), 8, SPROP_ROUNDDOWN, -32.0, 32.0f), - SendPropFloat ( SENDINFO_VECTORELEM2(m_vecViewOffset, 1, y), 8, SPROP_ROUNDDOWN, -32.0, 32.0f), - SendPropFloat ( SENDINFO_VECTORELEM2(m_vecViewOffset, 2, z), 10, SPROP_CHANGES_OFTEN, 0.0f, 128.0f), -#endif - - SendPropFloat ( SENDINFO(m_flFriction), 8, SPROP_ROUNDDOWN, 0.0f, 4.0f), - - SendPropArray3 ( SENDINFO_ARRAY3(m_iAmmo), SendPropInt( SENDINFO_ARRAY(m_iAmmo), 10, SPROP_UNSIGNED ) ), - - SendPropInt ( SENDINFO( m_fOnTarget ), 2, SPROP_UNSIGNED ), - - SendPropInt ( SENDINFO( m_nTickBase ), -1, SPROP_CHANGES_OFTEN ), - SendPropInt ( SENDINFO( m_nNextThinkTick ) ), - - SendPropEHandle ( SENDINFO( m_hLastWeapon ) ), - SendPropEHandle ( SENDINFO( m_hGroundEntity ), SPROP_CHANGES_OFTEN ), - - SendPropFloat ( SENDINFO_VECTORELEM2(m_vecVelocity, 0, x), 32, SPROP_NOSCALE|SPROP_CHANGES_OFTEN ), - SendPropFloat ( SENDINFO_VECTORELEM2(m_vecVelocity, 1, y), 32, SPROP_NOSCALE|SPROP_CHANGES_OFTEN ), - SendPropFloat ( SENDINFO_VECTORELEM2(m_vecVelocity, 2, z), 32, SPROP_NOSCALE|SPROP_CHANGES_OFTEN ), - -#if PREDICTION_ERROR_CHECK_LEVEL > 1 - SendPropVector ( SENDINFO( m_vecBaseVelocity ), -1, SPROP_COORD ), -#else - SendPropVector ( SENDINFO( m_vecBaseVelocity ), 20, 0, -1000, 1000 ), -#endif - - SendPropEHandle ( SENDINFO( m_hConstraintEntity)), - SendPropVector ( SENDINFO( m_vecConstraintCenter), 0, SPROP_NOSCALE ), - SendPropFloat ( SENDINFO( m_flConstraintRadius ), 0, SPROP_NOSCALE ), - SendPropFloat ( SENDINFO( m_flConstraintWidth ), 0, SPROP_NOSCALE ), - SendPropFloat ( SENDINFO( m_flConstraintSpeedFactor ), 0, SPROP_NOSCALE ), - - SendPropFloat ( SENDINFO( m_flDeathTime ), 0, SPROP_NOSCALE ), - - SendPropInt ( SENDINFO( m_nWaterLevel ), 2, SPROP_UNSIGNED ), - SendPropFloat ( SENDINFO( m_flLaggedMovementValue ), 0, SPROP_NOSCALE ), - - END_SEND_TABLE() - - -// -------------------------------------------------------------------------------- // -// DT_BasePlayer sendtable. -// -------------------------------------------------------------------------------- // - - IMPLEMENT_SERVERCLASS_ST( CBasePlayer, DT_BasePlayer ) - - SendPropDataTable(SENDINFO_DT(pl), &REFERENCE_SEND_TABLE(DT_PlayerState), SendProxy_DataTableToDataTable), - - SendPropEHandle(SENDINFO(m_hVehicle)), - SendPropEHandle(SENDINFO(m_hUseEntity)), - SendPropInt (SENDINFO(m_iHealth), 10 ), - SendPropInt (SENDINFO(m_lifeState), 3, SPROP_UNSIGNED ), - SendPropInt (SENDINFO(m_iBonusProgress), 15 ), - SendPropInt (SENDINFO(m_iBonusChallenge), 4 ), - SendPropFloat (SENDINFO(m_flMaxspeed), 12, SPROP_ROUNDDOWN, 0.0f, 2048.0f ), // CL - SendPropInt (SENDINFO(m_fFlags), PLAYER_FLAG_BITS, SPROP_UNSIGNED|SPROP_CHANGES_OFTEN, SendProxy_CropFlagsToPlayerFlagBitsLength ), - SendPropInt (SENDINFO(m_iObserverMode), 3, SPROP_UNSIGNED ), - SendPropEHandle (SENDINFO(m_hObserverTarget) ), - SendPropInt (SENDINFO(m_iFOV), 8, SPROP_UNSIGNED ), - SendPropInt (SENDINFO(m_iFOVStart), 8, SPROP_UNSIGNED ), - SendPropFloat (SENDINFO(m_flFOVTime) ), - SendPropInt (SENDINFO(m_iDefaultFOV), 8, SPROP_UNSIGNED ), - SendPropEHandle (SENDINFO(m_hZoomOwner) ), - SendPropArray ( SendPropEHandle( SENDINFO_ARRAY( m_hViewModel ) ), m_hViewModel ), - SendPropString (SENDINFO(m_szLastPlaceName) ), - SendPropInt ( SENDINFO( m_ubEFNoInterpParity ), NOINTERP_PARITY_MAX_BITS, SPROP_UNSIGNED ), - - // Data that only gets sent to the local player. - SendPropDataTable( "localdata", 0, &REFERENCE_SEND_TABLE(DT_LocalPlayerExclusive), SendProxy_SendLocalDataTable ), - - END_SEND_TABLE() - -//============================================================================= -// -// Player Physics Shadow Code -// - -void CBasePlayer::SetupVPhysicsShadow( const Vector &vecAbsOrigin, const Vector &vecAbsVelocity, CPhysCollide *pStandModel, const char *pStandHullName, CPhysCollide *pCrouchModel, const char *pCrouchHullName ) -{ - solid_t solid; - Q_strncpy( solid.surfaceprop, "player", sizeof(solid.surfaceprop) ); - solid.params = g_PhysDefaultObjectParams; - solid.params.mass = 85.0f; - solid.params.inertia = 1e24f; - solid.params.enableCollisions = false; - //disable drag - solid.params.dragCoefficient = 0; - // create standing hull - m_pShadowStand = PhysModelCreateCustom( this, pStandModel, GetLocalOrigin(), GetLocalAngles(), pStandHullName, false, &solid ); - m_pShadowStand->SetCallbackFlags( CALLBACK_GLOBAL_COLLISION | CALLBACK_SHADOW_COLLISION ); - - // create crouchig hull - m_pShadowCrouch = PhysModelCreateCustom( this, pCrouchModel, GetLocalOrigin(), GetLocalAngles(), pCrouchHullName, false, &solid ); - m_pShadowCrouch->SetCallbackFlags( CALLBACK_GLOBAL_COLLISION | CALLBACK_SHADOW_COLLISION ); - - // default to stand - VPhysicsSetObject( m_pShadowStand ); - - // tell physics lists I'm a shadow controller object - PhysAddShadow( this ); - m_pPhysicsController = physenv->CreatePlayerController( m_pShadowStand ); - m_pPhysicsController->SetPushMassLimit( 350.0f ); - m_pPhysicsController->SetPushSpeedLimit( 50.0f ); - - // Give the controller a valid position so it doesn't do anything rash. - UpdatePhysicsShadowToPosition( vecAbsOrigin ); - - // init state - if ( GetFlags() & FL_DUCKING ) - { - SetVCollisionState( vecAbsOrigin, vecAbsVelocity, VPHYS_CROUCH ); - } - else - { - SetVCollisionState( vecAbsOrigin, vecAbsVelocity, VPHYS_WALK ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Empty, just want to keep the baseentity version from being called -// current so we don't kick up dust, etc. -//----------------------------------------------------------------------------- -void CBasePlayer::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::VPhysicsUpdate( IPhysicsObject *pPhysics ) -{ - float savedImpact = m_impactEnergyScale; - - // HACKHACK: Reduce player's stress by 1/8th - m_impactEnergyScale *= 0.125f; - ApplyStressDamage( pPhysics, true ); - m_impactEnergyScale = savedImpact; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::VPhysicsShadowUpdate( IPhysicsObject *pPhysics ) -{ - if ( sv_turbophysics.GetBool() ) - return; - - Vector newPosition; - - bool physicsUpdated = m_pPhysicsController->GetShadowPosition( &newPosition, NULL ) > 0 ? true : false; - - // UNDONE: If the player is penetrating, but the player's game collisions are not stuck, teleport the physics shadow to the game position - if ( pPhysics->GetGameFlags() & FVPHYSICS_PENETRATING ) - { - CUtlVector list; - PhysGetListOfPenetratingEntities( this, list ); - for ( int i = list.Count()-1; i >= 0; --i ) - { - // filter out anything that isn't simulated by vphysics - // UNDONE: Filter out motion disabled objects? - if ( list[i]->GetMoveType() == MOVETYPE_VPHYSICS ) - { - // I'm currently stuck inside a moving object, so allow vphysics to - // apply velocity to the player in order to separate these objects - m_touchedPhysObject = true; - } - - // if it's an NPC, tell them that the player is intersecting them - CAI_BaseNPC *pNPC = list[i]->MyNPCPointer(); - if ( pNPC ) - { - pNPC->PlayerPenetratingVPhysics(); - } - } - } - - bool bCheckStuck = false; - if ( m_afPhysicsFlags & PFLAG_GAMEPHYSICS_ROTPUSH ) - { - bCheckStuck = true; - m_afPhysicsFlags &= ~PFLAG_GAMEPHYSICS_ROTPUSH; - } - if ( m_pPhysicsController->IsInContact() || (m_afPhysicsFlags & PFLAG_VPHYSICS_MOTIONCONTROLLER) ) - { - m_touchedPhysObject = true; - } - - if ( IsFollowingPhysics() ) - { - m_touchedPhysObject = true; - } - - if ( GetMoveType() == MOVETYPE_NOCLIP || pl.deadflag ) - { - m_oldOrigin = GetAbsOrigin(); - return; - } - - if ( phys_timescale.GetFloat() == 0.0f ) - { - physicsUpdated = false; - } - - if ( !physicsUpdated ) - return; - - IPhysicsObject *pPhysGround = GetGroundVPhysics(); - - Vector newVelocity; - pPhysics->GetPosition( &newPosition, 0 ); - m_pPhysicsController->GetShadowVelocity( &newVelocity ); - // assume vphysics gave us back a position without penetration - Vector lastValidPosition = newPosition; - - if ( physicsshadowupdate_render.GetBool() ) - { - NDebugOverlay::Box( GetAbsOrigin(), WorldAlignMins(), WorldAlignMaxs(), 255, 0, 0, 24, 15.0f ); - NDebugOverlay::Box( newPosition, WorldAlignMins(), WorldAlignMaxs(), 0,0,255, 24, 15.0f); - // NDebugOverlay::Box( newPosition, WorldAlignMins(), WorldAlignMaxs(), 0,0,255, 24, .01f); - } - - Vector tmp = GetAbsOrigin() - newPosition; - if ( !m_touchedPhysObject && !(GetFlags() & FL_ONGROUND) ) - { - tmp.z *= 0.5f; // don't care about z delta as much - } - - float dist = tmp.LengthSqr(); - float deltaV = (newVelocity - GetAbsVelocity()).LengthSqr(); - - float maxDistErrorSqr = VPHYS_MAX_DISTSQR; - float maxVelErrorSqr = VPHYS_MAX_VELSQR; - if ( IsRideablePhysics(pPhysGround) ) - { - maxDistErrorSqr *= 0.25; - maxVelErrorSqr *= 0.25; - } - - // player's physics was frozen, try moving to the game's simulated position if possible - if ( m_pPhysicsController->WasFrozen() ) - { - m_bPhysicsWasFrozen = true; - // check my position (physics object could have simulated into my position - // physics is not very far away, check my position - trace_t trace; - UTIL_TraceEntity( this, GetAbsOrigin(), GetAbsOrigin(), MASK_PLAYERSOLID, this, COLLISION_GROUP_PLAYER_MOVEMENT, &trace ); - if ( !trace.startsolid ) - return; - - // The physics shadow position is probably not in solid, try to move from there to the desired position - UTIL_TraceEntity( this, newPosition, GetAbsOrigin(), MASK_PLAYERSOLID, this, COLLISION_GROUP_PLAYER_MOVEMENT, &trace ); - if ( !trace.startsolid ) - { - // found a valid position between the two? take it. - SetAbsOrigin( trace.endpos ); - UpdateVPhysicsPosition(trace.endpos, vec3_origin, 0); - return; - } - - } - if ( dist >= maxDistErrorSqr || deltaV >= maxVelErrorSqr || (pPhysGround && !m_touchedPhysObject) ) - { - if ( m_touchedPhysObject || pPhysGround ) - { - // BUGBUG: Rewrite this code using fixed timestep - if ( deltaV >= maxVelErrorSqr && !m_bPhysicsWasFrozen ) - { - Vector dir = GetAbsVelocity(); - float len = VectorNormalize(dir); - float dot = DotProduct( newVelocity, dir ); - if ( dot > len ) - { - dot = len; - } - else if ( dot < -len ) - { - dot = -len; - } - - VectorMA( newVelocity, -dot, dir, newVelocity ); - - if ( m_afPhysicsFlags & PFLAG_VPHYSICS_MOTIONCONTROLLER ) - { - float val = Lerp( 0.1f, len, dot ); - VectorMA( newVelocity, val - len, dir, newVelocity ); - } - - if ( !IsRideablePhysics(pPhysGround) ) - { - if ( !(m_afPhysicsFlags & PFLAG_VPHYSICS_MOTIONCONTROLLER ) && IsSimulatingOnAlternateTicks() ) - { - newVelocity *= 0.5f; - } - ApplyAbsVelocityImpulse( newVelocity ); - } - } - - trace_t trace; - UTIL_TraceEntity( this, newPosition, newPosition, MASK_PLAYERSOLID, this, COLLISION_GROUP_PLAYER_MOVEMENT, &trace ); - if ( !trace.allsolid && !trace.startsolid ) - { - SetAbsOrigin( newPosition ); - } - } - else - { - bCheckStuck = true; - } - } - else - { - if ( m_touchedPhysObject ) - { - // check my position (physics object could have simulated into my position - // physics is not very far away, check my position - trace_t trace; - UTIL_TraceEntity( this, GetAbsOrigin(), GetAbsOrigin(), - MASK_PLAYERSOLID, this, COLLISION_GROUP_PLAYER_MOVEMENT, &trace ); - - // is current position ok? - if ( trace.allsolid || trace.startsolid ) - { - // no use the final stuck check to move back to old if this stuck fix didn't work - bCheckStuck = true; - lastValidPosition = m_oldOrigin; - SetAbsOrigin( newPosition ); - } - } - } - - if ( bCheckStuck ) - { - trace_t trace; - UTIL_TraceEntity( this, GetAbsOrigin(), GetAbsOrigin(), MASK_PLAYERSOLID, this, COLLISION_GROUP_PLAYER_MOVEMENT, &trace ); - - // current position is not ok, fixup - if ( trace.allsolid || trace.startsolid ) - { - // STUCK!?!?! - //Warning( "Checkstuck failed. Stuck on %s!!\n", trace.m_pEnt->GetClassname() ); - SetAbsOrigin( lastValidPosition ); - } - } - m_oldOrigin = GetAbsOrigin(); - m_bPhysicsWasFrozen = false; -} - -// recreate physics on save/load, don't try to save the state! -bool CBasePlayer::ShouldSavePhysics() -{ - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::InitVCollision( const Vector &vecAbsOrigin, const Vector &vecAbsVelocity ) -{ - // Cleanup any old vphysics stuff. - VPhysicsDestroyObject(); - - // in turbo physics players dont have a physics shadow - if ( sv_turbophysics.GetBool() ) - return; - - CPhysCollide *pModel = PhysCreateBbox( VEC_HULL_MIN, VEC_HULL_MAX ); - CPhysCollide *pCrouchModel = PhysCreateBbox( VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX ); - - SetupVPhysicsShadow( vecAbsOrigin, vecAbsVelocity, pModel, "player_stand", pCrouchModel, "player_crouch" ); -} - - -void CBasePlayer::VPhysicsDestroyObject() -{ - // Since CBasePlayer aliases its pointer to the physics object, tell CBaseEntity to - // clear out its physics object pointer so we don't wind up deleting one of - // the aliased objects twice. - VPhysicsSetObject( NULL ); - - PhysRemoveShadow( this ); - - if ( m_pPhysicsController ) - { - physenv->DestroyPlayerController( m_pPhysicsController ); - m_pPhysicsController = NULL; - } - - if ( m_pShadowStand ) - { - m_pShadowStand->EnableCollisions( false ); - PhysDestroyObject( m_pShadowStand ); - m_pShadowStand = NULL; - } - if ( m_pShadowCrouch ) - { - m_pShadowCrouch->EnableCollisions( false ); - PhysDestroyObject( m_pShadowCrouch ); - m_pShadowCrouch = NULL; - } - - BaseClass::VPhysicsDestroyObject(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::SetVCollisionState( const Vector &vecAbsOrigin, const Vector &vecAbsVelocity, int collisionState ) -{ - m_vphysicsCollisionState = collisionState; - switch( collisionState ) - { - case VPHYS_WALK: - m_pShadowStand->SetPosition( vecAbsOrigin, vec3_angle, true ); - m_pShadowStand->SetVelocity( &vecAbsVelocity, NULL ); - m_pShadowCrouch->EnableCollisions( false ); - m_pPhysicsController->SetObject( m_pShadowStand ); - VPhysicsSwapObject( m_pShadowStand ); - m_pShadowStand->EnableCollisions( true ); - break; - - case VPHYS_CROUCH: - m_pShadowCrouch->SetPosition( vecAbsOrigin, vec3_angle, true ); - m_pShadowCrouch->SetVelocity( &vecAbsVelocity, NULL ); - m_pShadowStand->EnableCollisions( false ); - m_pPhysicsController->SetObject( m_pShadowCrouch ); - VPhysicsSwapObject( m_pShadowCrouch ); - m_pShadowCrouch->EnableCollisions( true ); - break; - - case VPHYS_NOCLIP: - m_pShadowCrouch->EnableCollisions( false ); - m_pShadowStand->EnableCollisions( false ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBasePlayer::GetFOV( void ) -{ - int nDefaultFOV; - - // The vehicle's FOV wins if we're asking for a default value - if ( GetVehicle() ) - { - CacheVehicleView(); - nDefaultFOV = ( m_flVehicleViewFOV == 0 ) ? GetDefaultFOV() : (int) m_flVehicleViewFOV; - } - else - { - nDefaultFOV = GetDefaultFOV(); - } - - int fFOV = ( m_iFOV == 0 ) ? nDefaultFOV : m_iFOV; - - // If it's immediate, just do it - if ( m_Local.m_flFOVRate == 0.0f ) - return fFOV; - - float deltaTime = (float)( gpGlobals->curtime - m_flFOVTime ) / m_Local.m_flFOVRate; - - if ( deltaTime >= 1.0f ) - { - //If we're past the zoom time, just take the new value and stop lerping - m_iFOVStart = fFOV; - } - else - { - fFOV = (int)SimpleSplineRemapValClamped( deltaTime, 0.0f, 1.0f, m_iFOVStart, fFOV ); - } - - return fFOV; -} - - -//----------------------------------------------------------------------------- -// Get the current FOV used for network computations -// Choose the smallest FOV, as it will open the largest number of portals -//----------------------------------------------------------------------------- -int CBasePlayer::GetFOVForNetworking( void ) -{ - int nDefaultFOV; - - // The vehicle's FOV wins if we're asking for a default value - if ( GetVehicle() ) - { - CacheVehicleView(); - nDefaultFOV = ( m_flVehicleViewFOV == 0 ) ? GetDefaultFOV() : (int) m_flVehicleViewFOV; - } - else - { - nDefaultFOV = GetDefaultFOV(); - } - - int fFOV = ( m_iFOV == 0 ) ? nDefaultFOV : m_iFOV; - - // If it's immediate, just do it - if ( m_Local.m_flFOVRate == 0.0f ) - return fFOV; - - if ( gpGlobals->curtime - m_flFOVTime < m_Local.m_flFOVRate ) - { - fFOV = MIN( fFOV, m_iFOVStart ); - } - return fFOV; -} - - -float CBasePlayer::GetFOVDistanceAdjustFactorForNetworking() -{ - float defaultFOV = (float)GetDefaultFOV(); - float localFOV = (float)GetFOVForNetworking(); - - if ( localFOV == defaultFOV || defaultFOV < 0.001f ) - return 1.0f; - - // If FOV is lower, then we're "zoomed" in and this will give a factor < 1 so apparent LOD distances can be - // shorted accordingly - return localFOV / defaultFOV; -} - - -//----------------------------------------------------------------------------- -// Purpose: Sets the default FOV for the player if nothing else is going on -// Input : FOV - the new base FOV for this player -//----------------------------------------------------------------------------- -void CBasePlayer::SetDefaultFOV( int FOV ) -{ - m_iDefaultFOV = ( FOV == 0 ) ? g_pGameRules->DefaultFOV() : FOV; -} - -//----------------------------------------------------------------------------- -// Purpose: // static func -// Input : set - -//----------------------------------------------------------------------------- -void CBasePlayer::ModifyOrAppendPlayerCriteria( AI_CriteriaSet& set ) -{ - // Append our health - set.AppendCriteria( "playerhealth", UTIL_VarArgs( "%i", GetHealth() ) ); - float healthfrac = 0.0f; - if ( GetMaxHealth() > 0 ) - { - healthfrac = (float)GetHealth() / (float)GetMaxHealth(); - } - - set.AppendCriteria( "playerhealthfrac", UTIL_VarArgs( "%.3f", healthfrac ) ); - - CBaseCombatWeapon *weapon = GetActiveWeapon(); - if ( weapon ) - { - set.AppendCriteria( "playerweapon", weapon->GetClassname() ); - } - else - { - set.AppendCriteria( "playerweapon", "none" ); - } - - // Append current activity name - set.AppendCriteria( "playeractivity", CAI_BaseNPC::GetActivityName( GetActivity() ) ); - - set.AppendCriteria( "playerspeed", UTIL_VarArgs( "%.3f", GetAbsVelocity().Length() ) ); - - AppendContextToCriteria( set, "player" ); -} - - -const QAngle& CBasePlayer::GetPunchAngle() -{ - return m_Local.m_vecPunchAngle.Get(); -} - - -void CBasePlayer::SetPunchAngle( const QAngle &punchAngle ) -{ - m_Local.m_vecPunchAngle = punchAngle; - - if ( IsAlive() ) - { - int index = entindex(); - - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - - if ( pPlayer && i != index && pPlayer->GetObserverTarget() == this && pPlayer->GetObserverMode() == OBS_MODE_IN_EYE ) - { - pPlayer->SetPunchAngle( punchAngle ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Apply a movement constraint to the player -//----------------------------------------------------------------------------- -void CBasePlayer::ActivateMovementConstraint( CBaseEntity *pEntity, const Vector &vecCenter, float flRadius, float flConstraintWidth, float flSpeedFactor ) -{ - m_hConstraintEntity = pEntity; - m_vecConstraintCenter = vecCenter; - m_flConstraintRadius = flRadius; - m_flConstraintWidth = flConstraintWidth; - m_flConstraintSpeedFactor = flSpeedFactor; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::DeactivateMovementConstraint( ) -{ - m_hConstraintEntity = NULL; - m_flConstraintRadius = 0.0f; - m_vecConstraintCenter = vec3_origin; -} - -//----------------------------------------------------------------------------- -// Perhaps a poorly-named function. This function traces against the supplied -// NPC's hitboxes (instead of hull). If the trace hits a different NPC, the -// new NPC is selected. Otherwise, the supplied NPC is determined to be the -// one the citizen wants. This function allows the selection of a citizen over -// another citizen's shoulder, which is impossible without tracing against -// hitboxes instead of the hull (sjb) -//----------------------------------------------------------------------------- -CBaseEntity *CBasePlayer::DoubleCheckUseNPC( CBaseEntity *pNPC, const Vector &vecSrc, const Vector &vecDir ) -{ - trace_t tr; - - UTIL_TraceLine( vecSrc, vecSrc + vecDir * 1024, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - if( tr.m_pEnt != NULL && tr.m_pEnt->MyNPCPointer() && tr.m_pEnt != pNPC ) - { - // Player is selecting a different NPC through some negative space - // in the first NPC's hitboxes (between legs, over shoulder, etc). - return tr.m_pEnt; - } - - return pNPC; -} - - -bool CBasePlayer::IsBot() const -{ - return (GetFlags() & FL_FAKECLIENT) != 0; -} - -bool CBasePlayer::IsFakeClient() const -{ - return (GetFlags() & FL_FAKECLIENT) != 0; -} - -void CBasePlayer::EquipSuit( bool bPlayEffects ) -{ - m_Local.m_bWearingSuit = true; -} - -void CBasePlayer::RemoveSuit( void ) -{ - m_Local.m_bWearingSuit = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &tr - -// nDamageType - -//----------------------------------------------------------------------------- -void CBasePlayer::DoImpactEffect( trace_t &tr, int nDamageType ) -{ - if ( GetActiveWeapon() ) - { - GetActiveWeapon()->DoImpactEffect( tr, nDamageType ); - return; - } - - BaseClass::DoImpactEffect( tr, nDamageType ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::InputSetHealth( inputdata_t &inputdata ) -{ - int iNewHealth = inputdata.value.Int(); - int iDelta = abs(GetHealth() - iNewHealth); - if ( iNewHealth > GetHealth() ) - { - TakeHealth( iDelta, DMG_GENERIC ); - } - else if ( iNewHealth < GetHealth() ) - { - // Strip off and restore armor so that it doesn't absorb any of this damage. - int armor = m_ArmorValue; - m_ArmorValue = 0; - TakeDamage( CTakeDamageInfo( this, this, iDelta, DMG_GENERIC ) ); - m_ArmorValue = armor; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Hides or displays the HUD -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CBasePlayer::InputSetHUDVisibility( inputdata_t &inputdata ) -{ - bool bEnable = inputdata.value.Bool(); - - if ( bEnable ) - { - m_Local.m_iHideHUD &= ~HIDEHUD_ALL; - } - else - { - m_Local.m_iHideHUD |= HIDEHUD_ALL; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Set the fog controller data per player. -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CBasePlayer::InputSetFogController( inputdata_t &inputdata ) -{ - // Find the fog controller with the given name. - CFogController *pFogController = dynamic_cast( gEntList.FindEntityByName( NULL, inputdata.value.String() ) ); - if ( pFogController ) - { - m_Local.m_PlayerFog.m_hCtrl.Set( pFogController ); - } -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -void CBasePlayer::InitFogController( void ) -{ - // Setup with the default master controller. - m_Local.m_PlayerFog.m_hCtrl = FogSystem()->GetMasterFogController(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEntity - -//----------------------------------------------------------------------------- -void CBasePlayer::SetViewEntity( CBaseEntity *pEntity ) -{ - m_hViewEntity = pEntity; - - if ( m_hViewEntity ) - { - engine->SetView( edict(), m_hViewEntity->edict() ); - } - else - { - engine->SetView( edict(), edict() ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Looks at the player's reserve ammo and also all his weapons for any ammo -// of the specified type -// Input : nAmmoIndex - ammo to look for -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBasePlayer::HasAnyAmmoOfType( int nAmmoIndex ) -{ - // Must be a valid index - if ( nAmmoIndex < 0 ) - return false; - - // If we have some in reserve, we're already done - if ( GetAmmoCount( nAmmoIndex ) ) - return true; - - CBaseCombatWeapon *pWeapon; - - // Check all held weapons - for ( int i=0; i < MAX_WEAPONS; i++ ) - { - pWeapon = GetWeapon( i ); - - if ( !pWeapon ) - continue; - - // We must use clips and use this sort of ammo - if ( pWeapon->UsesClipsForAmmo1() && pWeapon->GetPrimaryAmmoType() == nAmmoIndex ) - { - // If we have any ammo, we're done - if ( pWeapon->HasPrimaryAmmo() ) - return true; - } - - // We'll check both clips for the same ammo type, just in case - if ( pWeapon->UsesClipsForAmmo2() && pWeapon->GetSecondaryAmmoType() == nAmmoIndex ) - { - if ( pWeapon->HasSecondaryAmmo() ) - return true; - } - } - - // We're completely without this type of ammo - return false; -} - -//----------------------------------------------------------------------------- -// return a string version of the players network (i.e steam) ID. -// -//----------------------------------------------------------------------------- -const char *CBasePlayer::GetNetworkIDString() -{ - Q_strncpy( m_szNetworkIDString, engine->GetPlayerNetworkIDString( edict() ), sizeof(m_szNetworkIDString) ); - return m_szNetworkIDString; -} - -//----------------------------------------------------------------------------- -// Assign the player a name -//----------------------------------------------------------------------------- -void CBasePlayer::SetPlayerName( const char *name ) -{ - Assert( name ); - - if ( name ) - { - Assert( strlen(name) > 0 ); - - Q_strncpy( m_szNetname, name, sizeof(m_szNetname) ); - } -} - -//----------------------------------------------------------------------------- -// sets the "don't autokick me" flag on a player -//----------------------------------------------------------------------------- -class DisableAutokick -{ -public: - DisableAutokick( int userID ) - { - m_userID = userID; - } - - bool operator()( CBasePlayer *player ) - { - if ( player->GetUserID() == m_userID ) - { - Msg( "autokick is disabled for %s\n", player->GetPlayerName() ); - player->DisableAutoKick( true ); - return false; // don't need to check other players - } - - return true; // keep looking at other players - } - -private: - int m_userID; -}; - -//----------------------------------------------------------------------------- -// sets the "don't autokick me" flag on a player -//----------------------------------------------------------------------------- -CON_COMMAND( mp_disable_autokick, "Prevents a userid from being auto-kicked" ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - { - Msg( "You must be a server admin to use mp_disable_autokick\n" ); - return; - } - - if ( args.ArgC() != 2 ) - { - Msg( "Usage: mp_disable_autokick \n" ); - return; - } - - int userID = atoi( args[1] ); - DisableAutokick disable( userID ); - ForEachPlayer( disable ); -} - -//----------------------------------------------------------------------------- -// Purpose: Toggle between the duck being on and off -//----------------------------------------------------------------------------- -void CBasePlayer::ToggleDuck( void ) -{ - // Toggle the state - m_bDuckToggled = !m_bDuckToggled; -} - -//----------------------------------------------------------------------------- -// Just tells us how far the stick is from the center. No directional info -//----------------------------------------------------------------------------- -float CBasePlayer::GetStickDist() -{ - Vector2D controlStick; - - controlStick.x = m_flForwardMove; - controlStick.y = m_flSideMove; - - return controlStick.Length(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::HandleAnimEvent( animevent_t *pEvent ) -{ - if ((pEvent->type & AE_TYPE_NEWEVENTSYSTEM) && (pEvent->type & AE_TYPE_SERVER)) - { - if ( pEvent->event == AE_RAGDOLL ) - { - // Convert to ragdoll immediately - CreateRagdollEntity(); - BecomeRagdollOnClient( vec3_origin ); - - // Force the player to start death thinking - SetThink(&CBasePlayer::PlayerDeathThink); - SetNextThink( gpGlobals->curtime + 0.1f ); - return; - } - } - - BaseClass::HandleAnimEvent( pEvent ); -} - -//----------------------------------------------------------------------------- -// CPlayerInfo functions (simple passthroughts to get around the CBasePlayer multiple inheritence limitation) -//----------------------------------------------------------------------------- -const char *CPlayerInfo::GetName() -{ - Assert( m_pParent ); - return m_pParent->GetPlayerName(); -} - -int CPlayerInfo::GetUserID() -{ - Assert( m_pParent ); - return engine->GetPlayerUserId( m_pParent->edict() ); -} - -const char *CPlayerInfo::GetNetworkIDString() -{ - Assert( m_pParent ); - return m_pParent->GetNetworkIDString(); -} - -int CPlayerInfo::GetTeamIndex() -{ - Assert( m_pParent ); - return m_pParent->GetTeamNumber(); -} - -void CPlayerInfo::ChangeTeam( int iTeamNum ) -{ - Assert( m_pParent ); - m_pParent->ChangeTeam(iTeamNum); -} - -int CPlayerInfo::GetFragCount() -{ - Assert( m_pParent ); - return m_pParent->FragCount(); -} - -int CPlayerInfo::GetDeathCount() -{ - Assert( m_pParent ); - return m_pParent->DeathCount(); -} - -bool CPlayerInfo::IsConnected() -{ - Assert( m_pParent ); - return m_pParent->IsConnected(); -} - -int CPlayerInfo::GetArmorValue() -{ - Assert( m_pParent ); - return m_pParent->ArmorValue(); -} - -bool CPlayerInfo::IsHLTV() -{ - Assert( m_pParent ); - return m_pParent->IsHLTV(); -} - -bool CPlayerInfo::IsPlayer() -{ - Assert( m_pParent ); - return m_pParent->IsPlayer(); -} - -bool CPlayerInfo::IsFakeClient() -{ - Assert( m_pParent ); - return m_pParent->IsFakeClient(); -} - -bool CPlayerInfo::IsDead() -{ - Assert( m_pParent ); - return m_pParent->IsDead(); -} - -bool CPlayerInfo::IsInAVehicle() -{ - Assert( m_pParent ); - return m_pParent->IsInAVehicle(); -} - -bool CPlayerInfo::IsObserver() -{ - Assert( m_pParent ); - return m_pParent->IsObserver(); -} - -const Vector CPlayerInfo::GetAbsOrigin() -{ - Assert( m_pParent ); - return m_pParent->GetAbsOrigin(); -} - -const QAngle CPlayerInfo::GetAbsAngles() -{ - Assert( m_pParent ); - return m_pParent->GetAbsAngles(); -} - -const Vector CPlayerInfo::GetPlayerMins() -{ - Assert( m_pParent ); - return m_pParent->GetPlayerMins(); -} - -const Vector CPlayerInfo::GetPlayerMaxs() -{ - Assert( m_pParent ); - return m_pParent->GetPlayerMaxs(); -} - -const char *CPlayerInfo::GetWeaponName() -{ - Assert( m_pParent ); - CBaseCombatWeapon *weap = m_pParent->GetActiveWeapon(); - if ( !weap ) - { - return NULL; - } - return weap->GetName(); -} - -const char *CPlayerInfo::GetModelName() -{ - Assert( m_pParent ); - return m_pParent->GetModelName().ToCStr(); -} - -const int CPlayerInfo::GetHealth() -{ - Assert( m_pParent ); - return m_pParent->GetHealth(); -} - -const int CPlayerInfo::GetMaxHealth() -{ - Assert( m_pParent ); - return m_pParent->GetMaxHealth(); -} - - - - - -void CPlayerInfo::SetAbsOrigin( Vector & vec ) -{ - Assert( m_pParent ); - if ( m_pParent->IsBot() ) - { - m_pParent->SetAbsOrigin(vec); - } -} - -void CPlayerInfo::SetAbsAngles( QAngle & ang ) -{ - Assert( m_pParent ); - if ( m_pParent->IsBot() ) - { - m_pParent->SetAbsAngles(ang); - } -} - -void CPlayerInfo::RemoveAllItems( bool removeSuit ) -{ - Assert( m_pParent ); - if ( m_pParent->IsBot() ) - { - m_pParent->RemoveAllItems(removeSuit); - } -} - -void CPlayerInfo::SetActiveWeapon( const char *WeaponName ) -{ - Assert( m_pParent ); - if ( m_pParent->IsBot() ) - { - CBaseCombatWeapon *weap = m_pParent->Weapon_Create( WeaponName ); - if ( weap ) - { - m_pParent->Weapon_Equip(weap); - m_pParent->Weapon_Switch(weap); - } - } -} - -void CPlayerInfo::SetLocalOrigin( const Vector& origin ) -{ - Assert( m_pParent ); - if ( m_pParent->IsBot() ) - { - m_pParent->SetLocalOrigin(origin); - } -} - -const Vector CPlayerInfo::GetLocalOrigin( void ) -{ - Assert( m_pParent ); - if ( m_pParent->IsBot() ) - { - Vector origin = m_pParent->GetLocalOrigin(); - return origin; - } - else - { - return Vector( 0, 0, 0 ); - } -} - -void CPlayerInfo::SetLocalAngles( const QAngle& angles ) -{ - Assert( m_pParent ); - if ( m_pParent->IsBot() ) - { - m_pParent->SetLocalAngles( angles ); - } -} - -const QAngle CPlayerInfo::GetLocalAngles( void ) -{ - Assert( m_pParent ); - if ( m_pParent->IsBot() ) - { - return m_pParent->GetLocalAngles(); - } - else - { - return QAngle(); - } -} - -void CPlayerInfo::PostClientMessagesSent( void ) -{ - Assert( m_pParent ); - if ( m_pParent->IsBot() ) - { - m_pParent->PostClientMessagesSent(); - } -} - -bool CPlayerInfo::IsEFlagSet( int nEFlagMask ) -{ - Assert( m_pParent ); - if ( m_pParent->IsBot() ) - { - return m_pParent->IsEFlagSet(nEFlagMask); - } - return false; -} - -void CPlayerInfo::RunPlayerMove( CBotCmd *ucmd ) -{ - if ( m_pParent->IsBot() ) - { - Assert( m_pParent ); - CUserCmd cmd; - cmd.buttons = ucmd->buttons; - cmd.command_number = ucmd->command_number; - cmd.forwardmove = ucmd->forwardmove; - cmd.hasbeenpredicted = ucmd->hasbeenpredicted; - cmd.impulse = ucmd->impulse; - cmd.mousedx = ucmd->mousedx; - cmd.mousedy = ucmd->mousedy; - cmd.random_seed = ucmd->random_seed; - cmd.sidemove = ucmd->sidemove; - cmd.tick_count = ucmd->tick_count; - cmd.upmove = ucmd->upmove; - cmd.viewangles = ucmd->viewangles; - cmd.weaponselect = ucmd->weaponselect; - cmd.weaponsubtype = ucmd->weaponsubtype; - - // Store off the globals.. they're gonna get whacked - float flOldFrametime = gpGlobals->frametime; - float flOldCurtime = gpGlobals->curtime; - - m_pParent->SetTimeBase( gpGlobals->curtime ); - - MoveHelperServer()->SetHost( m_pParent ); - m_pParent->PlayerRunCommand( &cmd, MoveHelperServer() ); - - // save off the last good usercmd - m_pParent->SetLastUserCommand( cmd ); - - // Clear out any fixangle that has been set - m_pParent->pl.fixangle = FIXANGLE_NONE; - - // Restore the globals.. - gpGlobals->frametime = flOldFrametime; - gpGlobals->curtime = flOldCurtime; - MoveHelperServer()->SetHost( NULL ); - } -} - -void CPlayerInfo::SetLastUserCommand( const CBotCmd &ucmd ) -{ - if ( m_pParent->IsBot() ) - { - Assert( m_pParent ); - CUserCmd cmd; - cmd.buttons = ucmd.buttons; - cmd.command_number = ucmd.command_number; - cmd.forwardmove = ucmd.forwardmove; - cmd.hasbeenpredicted = ucmd.hasbeenpredicted; - cmd.impulse = ucmd.impulse; - cmd.mousedx = ucmd.mousedx; - cmd.mousedy = ucmd.mousedy; - cmd.random_seed = ucmd.random_seed; - cmd.sidemove = ucmd.sidemove; - cmd.tick_count = ucmd.tick_count; - cmd.upmove = ucmd.upmove; - cmd.viewangles = ucmd.viewangles; - cmd.weaponselect = ucmd.weaponselect; - cmd.weaponsubtype = ucmd.weaponsubtype; - - m_pParent->SetLastUserCommand(cmd); - } -} - - -CBotCmd CPlayerInfo::GetLastUserCommand() -{ - CBotCmd cmd; - const CUserCmd *ucmd = m_pParent->GetLastUserCommand(); - if ( ucmd ) - { - cmd.buttons = ucmd->buttons; - cmd.command_number = ucmd->command_number; - cmd.forwardmove = ucmd->forwardmove; - cmd.hasbeenpredicted = ucmd->hasbeenpredicted; - cmd.impulse = ucmd->impulse; - cmd.mousedx = ucmd->mousedx; - cmd.mousedy = ucmd->mousedy; - cmd.random_seed = ucmd->random_seed; - cmd.sidemove = ucmd->sidemove; - cmd.tick_count = ucmd->tick_count; - cmd.upmove = ucmd->upmove; - cmd.viewangles = ucmd->viewangles; - cmd.weaponselect = ucmd->weaponselect; - cmd.weaponsubtype = ucmd->weaponsubtype; - } - return cmd; -} - -// Notify that I've killed some other entity. (called from Victim's Event_Killed). -void CBasePlayer::Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info ) -{ - BaseClass::Event_KilledOther( pVictim, info ); - if ( pVictim != this ) - { - gamestats->Event_PlayerKilledOther( this, pVictim, info ); - } -} - -void CBasePlayer::SetModel( const char *szModelName ) -{ - BaseClass::SetModel( szModelName ); - m_nBodyPitchPoseParam = LookupPoseParameter( "body_pitch" ); -} - -void CBasePlayer::SetBodyPitch( float flPitch ) -{ - if ( m_nBodyPitchPoseParam >= 0 ) - { - SetPoseParameter( m_nBodyPitchPoseParam, flPitch ); - } -} - -void CBasePlayer::AdjustDrownDmg( int nAmount ) -{ - m_idrowndmg += nAmount; - if ( m_idrowndmg < m_idrownrestored ) - { - m_idrowndmg = m_idrownrestored; - } -} diff --git a/game/server/player.h b/game/server/player.h deleted file mode 100644 index 4f8338252..000000000 --- a/game/server/player.h +++ /dev/null @@ -1,1277 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#ifndef PLAYER_H -#define PLAYER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "basecombatcharacter.h" -#include "usercmd.h" -#include "playerlocaldata.h" -#include "PlayerState.h" -#include "game/server/iplayerinfo.h" -#include "hintsystem.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" - -// For queuing and processing usercmds -class CCommandContext -{ -public: - CUtlVector< CUserCmd > cmds; - - int numcmds; - int totalcmds; - int dropped_packets; - bool paused; -}; - -// Info about last 20 or so updates to the -class CPlayerCmdInfo -{ -public: - CPlayerCmdInfo() : - m_flTime( 0.0f ), m_nNumCmds( 0 ), m_nDroppedPackets( 0 ) - { - } - - // realtime of sample - float m_flTime; - // # of CUserCmds in this update - int m_nNumCmds; - // # of dropped packets on the link - int m_nDroppedPackets; -}; - -class CPlayerSimInfo -{ -public: - CPlayerSimInfo() : - m_flTime( 0.0f ), m_nNumCmds( 0 ), m_nTicksCorrected( 0 ), m_flFinalSimulationTime( 0.0f ), m_flGameSimulationTime( 0.0f ), m_flServerFrameTime( 0.0f ), m_vecAbsOrigin( 0, 0, 0 ) - { - } - - // realtime of sample - float m_flTime; - // # of CUserCmds in this update - int m_nNumCmds; - // If clock needed correction, # of ticks added/removed - int m_nTicksCorrected; // +ve or -ve - // player's m_flSimulationTime at end of frame - float m_flFinalSimulationTime; - float m_flGameSimulationTime; - // estimate of server perf - float m_flServerFrameTime; - Vector m_vecAbsOrigin; -}; -//----------------------------------------------------------------------------- -// Forward declarations: -//----------------------------------------------------------------------------- -class CBaseCombatWeapon; -class CBaseViewModel; -class CTeam; -class IPhysicsPlayerController; -class IServerVehicle; -class CUserCmd; -class CFuncLadder; -class CNavArea; -class CHintSystem; -class CAI_Expresser; - -// for step sounds -struct surfacedata_t; - -// !!!set this bit on guns and stuff that should never respawn. -#define SF_NORESPAWN ( 1 << 30 ) - -// -// Player PHYSICS FLAGS bits -// -enum PlayerPhysFlag_e -{ - PFLAG_DIROVERRIDE = ( 1<<0 ), // override the player's directional control (trains, physics gun, etc.) - PFLAG_DUCKING = ( 1<<1 ), // In the process of ducking, but totally squatted yet - PFLAG_USING = ( 1<<2 ), // Using a continuous entity - PFLAG_OBSERVER = ( 1<<3 ), // player is locked in stationary cam mode. Spectators can move, observers can't. - PFLAG_VPHYSICS_MOTIONCONTROLLER = ( 1<<4 ), // player is physically attached to a motion controller - PFLAG_GAMEPHYSICS_ROTPUSH = (1<<5), // game physics did a rotating push that we may want to override with vphysics - - // If you add another flag here check that you aren't - // overwriting phys flags in the HL2 of TF2 player classes -}; - -// -// generic player -// -//----------------------------------------------------- -//This is Half-Life player entity -//----------------------------------------------------- -#define CSUITPLAYLIST 4 // max of 4 suit sentences queued up at any time -#define SUIT_REPEAT_OK 0 - -#define SUIT_NEXT_IN_30SEC 30 -#define SUIT_NEXT_IN_1MIN 60 -#define SUIT_NEXT_IN_5MIN 300 -#define SUIT_NEXT_IN_10MIN 600 -#define SUIT_NEXT_IN_30MIN 1800 -#define SUIT_NEXT_IN_1HOUR 3600 - -#define CSUITNOREPEAT 32 - -#define TEAM_NAME_LENGTH 16 - -// constant items -#define ITEM_HEALTHKIT 1 -#define ITEM_BATTERY 4 - -#define AUTOAIM_2DEGREES 0.0348994967025 -#define AUTOAIM_5DEGREES 0.08715574274766 -#define AUTOAIM_8DEGREES 0.1391731009601 -#define AUTOAIM_10DEGREES 0.1736481776669 -#define AUTOAIM_20DEGREES 0.3490658503989 - -// useful cosines -#define DOT_1DEGREE 0.9998476951564 -#define DOT_2DEGREE 0.9993908270191 -#define DOT_3DEGREE 0.9986295347546 -#define DOT_4DEGREE 0.9975640502598 -#define DOT_5DEGREE 0.9961946980917 -#define DOT_6DEGREE 0.9945218953683 -#define DOT_7DEGREE 0.9925461516413 -#define DOT_8DEGREE 0.9902680687416 -#define DOT_9DEGREE 0.9876883405951 -#define DOT_10DEGREE 0.9848077530122 -#define DOT_15DEGREE 0.9659258262891 -#define DOT_20DEGREE 0.9396926207859 -#define DOT_25DEGREE 0.9063077870367 -#define DOT_30DEGREE 0.866025403784 -#define DOT_45DEGREE 0.707106781187 -enum -{ - VPHYS_WALK = 0, - VPHYS_CROUCH, - VPHYS_NOCLIP, -}; - - -enum PlayerConnectedState -{ - PlayerConnected, - PlayerDisconnecting, - PlayerDisconnected, -}; - -extern bool gInitHUD; -extern ConVar *sv_cheats; - -class CBasePlayer; -class CPlayerInfo : public IBotController, public IPlayerInfo -{ -public: - CPlayerInfo () { m_pParent = NULL; } - ~CPlayerInfo () {} - void SetParent( CBasePlayer *parent ) { m_pParent = parent; } - - // IPlayerInfo interface - virtual const char *GetName(); - virtual int GetUserID(); - virtual const char *GetNetworkIDString(); - virtual int GetTeamIndex(); - virtual void ChangeTeam( int iTeamNum ); - virtual int GetFragCount(); - virtual int GetDeathCount(); - virtual bool IsConnected(); - virtual int GetArmorValue(); - - virtual bool IsHLTV(); - virtual bool IsPlayer(); - virtual bool IsFakeClient(); - virtual bool IsDead(); - virtual bool IsInAVehicle(); - virtual bool IsObserver(); - virtual const Vector GetAbsOrigin(); - virtual const QAngle GetAbsAngles(); - virtual const Vector GetPlayerMins(); - virtual const Vector GetPlayerMaxs(); - virtual const char *GetWeaponName(); - virtual const char *GetModelName(); - virtual const int GetHealth(); - virtual const int GetMaxHealth(); - - // bot specific functions - virtual void SetAbsOrigin( Vector & vec ); - virtual void SetAbsAngles( QAngle & ang ); - virtual void RemoveAllItems( bool removeSuit ); - virtual void SetActiveWeapon( const char *WeaponName ); - virtual void SetLocalOrigin( const Vector& origin ); - virtual const Vector GetLocalOrigin( void ); - virtual void SetLocalAngles( const QAngle& angles ); - virtual const QAngle GetLocalAngles( void ); - virtual void PostClientMessagesSent( void ); - virtual bool IsEFlagSet( int nEFlagMask ); - - virtual void RunPlayerMove( CBotCmd *ucmd ); - virtual void SetLastUserCommand( const CBotCmd &cmd ); - - virtual CBotCmd GetLastUserCommand(); - virtual bool IsReplay(); - -private: - CBasePlayer *m_pParent; -}; - - -class CBasePlayer : public CBaseCombatCharacter -{ -public: - DECLARE_CLASS( CBasePlayer, CBaseCombatCharacter ); -protected: - // HACK FOR BOTS - friend class CBotManager; - static edict_t *s_PlayerEdict; // must be set before calling constructor -public: - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - CBasePlayer(); - ~CBasePlayer(); - - // IPlayerInfo passthrough (because we can't do multiple inheritance) - IPlayerInfo *GetPlayerInfo() { return &m_PlayerInfo; } - IBotController *GetBotController() { return &m_PlayerInfo; } - - virtual void SetModel( const char *szModelName ); - void SetBodyPitch( float flPitch ); - - virtual void UpdateOnRemove( void ); - - static CBasePlayer *CreatePlayer( const char *className, edict_t *ed ); - - virtual void CreateViewModel( int viewmodelindex = 0 ); - CBaseViewModel *GetViewModel( int viewmodelindex = 0 ); - void HideViewModels( void ); - void DestroyViewModels( void ); - - CPlayerState *PlayerData( void ) { return &pl; } - - int RequiredEdictIndex( void ) { return ENTINDEX(edict()); } - - void LockPlayerInPlace( void ); - void UnlockPlayer( void ); - - virtual void DrawDebugGeometryOverlays(void); - - // Networking is about to update this entity, let it override and specify it's own pvs - virtual void SetupVisibility( CBaseEntity *pViewEntity, unsigned char *pvs, int pvssize ); - virtual int UpdateTransmitState(); - virtual int ShouldTransmit( const CCheckTransmitInfo *pInfo ); - - // Returns true if this player wants pPlayer to be moved back in time when this player runs usercmds. - // Saves a lot of overhead on the server if we can cull out entities that don't need to lag compensate - // (like team members, entities out of our PVS, etc). - virtual bool WantsLagCompensationOnEntity( const CBasePlayer *pPlayer, const CUserCmd *pCmd, const CBitVec *pEntityTransmitBits ) const; - - virtual void Spawn( void ); - virtual void Activate( void ); - virtual void SharedSpawn(); // Shared between client and server. - virtual void ForceRespawn( void ); - - virtual void InitialSpawn( void ); - virtual void InitHUD( void ) {} - virtual void ShowViewPortPanel( const char * name, bool bShow = true, KeyValues *data = NULL ); - - virtual void PlayerDeathThink( void ); - - virtual void Jump( void ); - virtual void Duck( void ); - - const char *GetTracerType( void ); - void MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ); - void DoImpactEffect( trace_t &tr, int nDamageType ); - -#if !defined( NO_ENTITY_PREDICTION ) - void AddToPlayerSimulationList( CBaseEntity *other ); - void RemoveFromPlayerSimulationList( CBaseEntity *other ); - void SimulatePlayerSimulatedEntities( void ); - void ClearPlayerSimulationList( void ); -#endif - - // Physics simulation (player executes it's usercmd's here) - virtual void PhysicsSimulate( void ); - - // Forces processing of usercmds (e.g., even if game is paused, etc.) - void ForceSimulation(); - - virtual unsigned int PhysicsSolidMaskForEntity( void ) const; - - virtual void PreThink( void ); - virtual void PostThink( void ); - virtual int TakeHealth( float flHealth, int bitsDamageType ); - virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - bool ShouldTakeDamageInCommentaryMode( const CTakeDamageInfo &inputInfo ); - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - virtual void DamageEffect(float flDamage, int fDamageType); - - virtual void OnDamagedByExplosion( const CTakeDamageInfo &info ); - - void PauseBonusProgress( bool bPause = true ); - void SetBonusProgress( int iBonusProgress ); - void SetBonusChallenge( int iBonusChallenge ); - - int GetBonusProgress() const { return m_iBonusProgress; } - int GetBonusChallenge() const { return m_iBonusChallenge; } - - virtual Vector EyePosition( ); // position of eyes - const QAngle &EyeAngles( ); - void EyePositionAndVectors( Vector *pPosition, Vector *pForward, Vector *pRight, Vector *pUp ); - virtual const QAngle &LocalEyeAngles(); // Direction of eyes - void EyeVectors( Vector *pForward, Vector *pRight = NULL, Vector *pUp = NULL ); - void CacheVehicleView( void ); // Calculate and cache the position of the player in the vehicle - - // Sets the view angles - void SnapEyeAngles( const QAngle &viewAngles ); - - virtual QAngle BodyAngles(); - virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy); - virtual bool ShouldFadeOnDeath( void ) { return FALSE; } - - virtual const impactdamagetable_t &GetPhysicsImpactDamageTable(); - virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - virtual void Event_Killed( const CTakeDamageInfo &info ); - // Notifier that I've killed some other entity. (called from Victim's Event_Killed). - virtual void Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info ); - - void Event_Dying( void ); - - bool IsHLTV( void ) const { return pl.hltv; } - virtual bool IsPlayer( void ) const { return true; } // Spectators return TRUE for this, use IsObserver to seperate cases - virtual bool IsNetClient( void ) const { return true; } // Bots should return FALSE for this, they can't receive NET messages - // Spectators should return TRUE for this - - virtual bool IsFakeClient( void ) const; - - // Get the client index (entindex-1). - int GetClientIndex() { return ENTINDEX( edict() ) - 1; } - - // returns the player name - const char * GetPlayerName() { return m_szNetname; } - void SetPlayerName( const char *name ); - - int GetUserID() { return engine->GetPlayerUserId( edict() ); } - const char * GetNetworkIDString(); - virtual const Vector GetPlayerMins( void ) const; // uses local player - virtual const Vector GetPlayerMaxs( void ) const; // uses local player - - - void VelocityPunch( const Vector &vecForce ); - void ViewPunch( const QAngle &angleOffset ); - void ViewPunchReset( float tolerance = 0 ); - void ShowViewModel( bool bShow ); - void ShowCrosshair( bool bShow ); - - // View model prediction setup - void CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear, float &zFar, float &fov ); - - // Handle view smoothing when going up stairs - void SmoothViewOnStairs( Vector& eyeOrigin ); - virtual float CalcRoll (const QAngle& angles, const Vector& velocity, float rollangle, float rollspeed); - void CalcViewRoll( QAngle& eyeAngles ); - - virtual int Save( ISave &save ); - virtual int Restore( IRestore &restore ); - virtual bool ShouldSavePhysics(); - virtual void OnRestore( void ); - - virtual void PackDeadPlayerItems( void ); - virtual void RemoveAllItems( bool removeSuit ); - bool IsDead() const; -#ifdef CSTRIKE_DLL - virtual bool IsRunning( void ) const { return false; } // bot support under cstrike (AR) -#endif - - bool HasPhysicsFlag( unsigned int flag ) { return (m_afPhysicsFlags & flag) != 0; } - - // Weapon stuff - virtual Vector Weapon_ShootPosition( ); - virtual bool Weapon_CanUse( CBaseCombatWeapon *pWeapon ); - virtual void Weapon_Equip( CBaseCombatWeapon *pWeapon ); - virtual void Weapon_Drop( CBaseCombatWeapon *pWeapon, const Vector *pvecTarget /* = NULL */, const Vector *pVelocity /* = NULL */ ); - virtual bool Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmodelindex = 0 ); // Switch to given weapon if has ammo (false if failed) - virtual void Weapon_SetLast( CBaseCombatWeapon *pWeapon ); - virtual bool Weapon_ShouldSetLast( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ) { return true; } - virtual bool Weapon_ShouldSelectItem( CBaseCombatWeapon *pWeapon ); - void Weapon_DropSlot( int weaponSlot ); - CBaseCombatWeapon *Weapon_GetLast( void ) { return m_hLastWeapon.Get(); } - - bool HasAnyAmmoOfType( int nAmmoIndex ); - - // JOHN: sends custom messages if player HUD data has changed (eg health, ammo) - virtual void UpdateClientData( void ); - void RumbleEffect( unsigned char index, unsigned char rumbleData, unsigned char rumbleFlags ); - - // Player is moved across the transition by other means - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } - virtual void Precache( void ); - bool IsOnLadder( void ); - virtual void ExitLadder() {} - virtual surfacedata_t *GetLadderSurface( const Vector &origin ); - - virtual void SetFlashlightEnabled( bool bState ) { }; - virtual int FlashlightIsOn( void ) { return false; } - virtual void FlashlightTurnOn( void ) { }; - virtual void FlashlightTurnOff( void ) { }; - virtual bool IsIlluminatedByFlashlight( CBaseEntity *pEntity, float *flReturnDot ) {return false; } - - void UpdatePlayerSound ( void ); - virtual void UpdateStepSound( surfacedata_t *psurface, const Vector &vecOrigin, const Vector &vecVelocity ); - virtual void PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, float fvol, bool force ); - virtual void GetStepSoundVelocities( float *velwalk, float *velrun ); - virtual void SetStepSoundTime( stepsoundtimes_t iStepSoundTime, bool bWalking ); - virtual void DeathSound( const CTakeDamageInfo &info ); - - Class_T Classify ( void ); - virtual void SetAnimation( PLAYER_ANIM playerAnim ); - void SetWeaponAnimType( const char *szExtention ); - - // custom player functions - virtual void ImpulseCommands( void ); - virtual void CheatImpulseCommands( int iImpulse ); - virtual bool ClientCommand( const CCommand &args ); - - void NotifySinglePlayerGameEnding() { m_bSinglePlayerGameEnding = true; } - bool IsSinglePlayerGameEnding() { return m_bSinglePlayerGameEnding == true; } - - // Observer functions - virtual bool StartObserverMode(int mode); // true, if successful - virtual void StopObserverMode( void ); // stop spectator mode - virtual bool ModeWantsSpectatorGUI( int iMode ) { return true; } - virtual bool SetObserverMode(int mode); // sets new observer mode, returns true if successful - virtual int GetObserverMode( void ); // returns observer mode or OBS_NONE - virtual bool SetObserverTarget(CBaseEntity * target); - virtual void ObserverUse( bool bIsPressed ); // observer pressed use - virtual CBaseEntity *GetObserverTarget( void ); // returns players targer or NULL - virtual CBaseEntity *FindNextObserverTarget( bool bReverse ); // returns next/prev player to follow or NULL - virtual int GetNextObserverSearchStartPoint( bool bReverse ); // Where we should start looping the player list in a FindNextObserverTarget call - virtual bool IsValidObserverTarget(CBaseEntity * target); // true, if player is allowed to see this target - virtual void CheckObserverSettings(); // checks, if target still valid (didn't die etc) - virtual void JumptoPosition(const Vector &origin, const QAngle &angles); - virtual void ForceObserverMode(int mode); // sets a temporary mode, force because of invalid targets - virtual void ResetObserverMode(); // resets all observer related settings - virtual void ValidateCurrentObserverTarget( void ); // Checks the current observer target, and moves on if it's not valid anymore - virtual void AttemptToExitFreezeCam( void ); - - virtual bool StartReplayMode( float fDelay, float fDuration, int iEntity ); - virtual void StopReplayMode(); - virtual int GetDelayTicks(); - virtual int GetReplayEntity(); - - virtual void CreateCorpse( void ) { } - virtual CBaseEntity *EntSelectSpawnPoint( void ); - - // Vehicles - virtual bool IsInAVehicle( void ) const; - bool CanEnterVehicle( IServerVehicle *pVehicle, int nRole ); - virtual bool GetInVehicle( IServerVehicle *pVehicle, int nRole ); - virtual void LeaveVehicle( const Vector &vecExitPoint = vec3_origin, const QAngle &vecExitAngles = vec3_angle ); - int GetVehicleAnalogControlBias() { return m_iVehicleAnalogBias; } - void SetVehicleAnalogControlBias( int bias ) { m_iVehicleAnalogBias = bias; } - - // override these for - virtual void OnVehicleStart() {} - virtual void OnVehicleEnd( Vector &playerDestPosition ) {} - IServerVehicle *GetVehicle(); - CBaseEntity *GetVehicleEntity( void ); - bool UsingStandardWeaponsInVehicle( void ); - - void AddPoints( int score, bool bAllowNegativeScore ); - void AddPointsToTeam( int score, bool bAllowNegativeScore ); - virtual bool BumpWeapon( CBaseCombatWeapon *pWeapon ); - bool RemovePlayerItem( CBaseCombatWeapon *pItem ); - CBaseEntity *HasNamedPlayerItem( const char *pszItemName ); - bool HasWeapons( void );// do I have ANY weapons? - virtual void SelectLastItem(void); - virtual void SelectItem( const char *pstr, int iSubType = 0 ); - void ItemPreFrame( void ); - virtual void ItemPostFrame( void ); - virtual CBaseEntity *GiveNamedItem( const char *szName, int iSubType = 0 ); - void EnableControl(bool fControl); - virtual void CheckTrainUpdate( void ); - void AbortReload( void ); - - void SendAmmoUpdate(void); - - void WaterMove( void ); - float GetWaterJumpTime() const; - void SetWaterJumpTime( float flWaterJumpTime ); - float GetSwimSoundTime( void ) const; - void SetSwimSoundTime( float flSwimSoundTime ); - - virtual void SetPlayerUnderwater( bool state ); - void UpdateUnderwaterState( void ); - bool IsPlayerUnderwater( void ) { return m_bPlayerUnderwater; } - - virtual bool CanBreatheUnderwater() const { return false; } - virtual void PlayerUse( void ); - virtual void PlayUseDenySound() {} - - virtual CBaseEntity *FindUseEntity( void ); - virtual bool IsUseableEntity( CBaseEntity *pEntity, unsigned int requiredCaps ); - bool ClearUseEntity(); - CBaseEntity *DoubleCheckUseNPC( CBaseEntity *pNPC, const Vector &vecSrc, const Vector &vecDir ); - - - // physics interactions - // mass/size limit set to zero for none - static bool CanPickupObject( CBaseEntity *pObject, float massLimit, float sizeLimit ); - virtual void PickupObject( CBaseEntity *pObject, bool bLimitMassAndSize = true ) {} - virtual void ForceDropOfCarriedPhysObjects( CBaseEntity *pOnlyIfHoldindThis = NULL ) {} - virtual float GetHeldObjectMass( IPhysicsObject *pHeldObject ); - virtual CBaseEntity *GetHeldObject( void ); - - void CheckSuitUpdate(); - void SetSuitUpdate(const char *name, int fgroup, int iNoRepeat); - virtual void UpdateGeigerCounter( void ); - void CheckTimeBasedDamage( void ); - - void ResetAutoaim( void ); - - virtual Vector GetAutoaimVector( float flScale ); - virtual Vector GetAutoaimVector( float flScale, float flMaxDist ); - virtual void GetAutoaimVector( autoaim_params_t ¶ms ); - - float GetAutoaimScore( const Vector &eyePosition, const Vector &viewDir, const Vector &vecTarget, CBaseEntity *pTarget, float fScale, CBaseCombatWeapon *pActiveWeapon ); - QAngle AutoaimDeflection( Vector &vecSrc, autoaim_params_t ¶ms ); - virtual bool ShouldAutoaim( void ); - void SetTargetInfo( Vector &vecSrc, float flDist ); - - void SetViewEntity( CBaseEntity *pEntity ); - CBaseEntity *GetViewEntity( void ) { return m_hViewEntity; } - - virtual void ForceClientDllUpdate( void ); // Forces all client .dll specific data to be resent to client. - - void DeathMessage( CBaseEntity *pKiller ); - - virtual void ProcessUsercmds( CUserCmd *cmds, int numcmds, int totalcmds, - int dropped_packets, bool paused ); - - void AvoidPhysicsProps( CUserCmd *pCmd ); - - // Run a user command. The default implementation calls ::PlayerRunCommand. In TF, this controls a vehicle if - // the player is in one. - virtual void PlayerRunCommand(CUserCmd *ucmd, IMoveHelper *moveHelper); - void RunNullCommand(); - CUserCmd * GetCurrentCommand( void ) { return m_pCurrentCommand; } - - // Team Handling - virtual void ChangeTeam( int iTeamNum ); - - // say/sayteam allowed? - virtual bool CanHearAndReadChatFrom( CBasePlayer *pPlayer ) { return true; } - virtual bool CanSpeak( void ) { return true; } - - audioparams_t &GetAudioParams() { return m_Local.m_audio; } - - virtual void ModifyOrAppendPlayerCriteria( AI_CriteriaSet& set ); - - const QAngle& GetPunchAngle(); - void SetPunchAngle( const QAngle &punchAngle ); - - virtual void DoMuzzleFlash(); - - CNavArea *GetLastKnownArea( void ) const { return m_lastNavArea; } // return the last nav area the player occupied - NULL if unknown - const char *GetLastKnownPlaceName( void ) const { return m_szLastPlaceName; } // return the last nav place name the player occupied - - virtual void CheckChatText( char *p, int bufsize ) {} - - virtual void CreateRagdollEntity( void ) { return; } - - virtual void HandleAnimEvent( animevent_t *pEvent ); - - virtual bool ShouldAnnounceAchievement( void ){ return true; } - -public: - // Player Physics Shadow - void SetupVPhysicsShadow( const Vector &vecAbsOrigin, const Vector &vecAbsVelocity, CPhysCollide *pStandModel, const char *pStandHullName, CPhysCollide *pCrouchModel, const char *pCrouchHullName ); - IPhysicsPlayerController* GetPhysicsController() { return m_pPhysicsController; } - virtual void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); - void VPhysicsUpdate( IPhysicsObject *pPhysics ); - virtual void VPhysicsShadowUpdate( IPhysicsObject *pPhysics ); - virtual bool IsFollowingPhysics( void ) { return false; } - bool IsRideablePhysics( IPhysicsObject *pPhysics ); - IPhysicsObject *GetGroundVPhysics(); - - virtual void Touch( CBaseEntity *pOther ); - void SetTouchedPhysics( bool bTouch ); - bool TouchedPhysics( void ); - Vector GetSmoothedVelocity( void ); - - virtual void InitVCollision( const Vector &vecAbsOrigin, const Vector &vecAbsVelocity ); - virtual void VPhysicsDestroyObject(); - void SetVCollisionState( const Vector &vecAbsOrigin, const Vector &vecAbsVelocity, int collisionState ); - void PostThinkVPhysics( void ); - virtual void UpdatePhysicsShadowToCurrentPosition(); - void UpdatePhysicsShadowToPosition( const Vector &vecAbsOrigin ); - void UpdateVPhysicsPosition( const Vector &position, const Vector &velocity, float secondsToArrival ); - - // Hint system - virtual CHintSystem *Hints( void ) { return NULL; } - bool ShouldShowHints( void ) { return Hints() ? Hints()->ShouldShowHints() : false; } - void SetShowHints( bool bShowHints ) { if (Hints()) Hints()->SetShowHints( bShowHints ); } - bool HintMessage( int hint, bool bForce = false ) { return Hints() ? Hints()->HintMessage( hint, bForce ) : false; } - void HintMessage( const char *pMessage ) { if (Hints()) Hints()->HintMessage( pMessage ); } - void StartHintTimer( int iHintID ) { if (Hints()) Hints()->StartHintTimer( iHintID ); } - void StopHintTimer( int iHintID ) { if (Hints()) Hints()->StopHintTimer( iHintID ); } - void RemoveHintTimer( int iHintID ) { if (Hints()) Hints()->RemoveHintTimer( iHintID ); } - - // Accessor methods - int FragCount() const { return m_iFrags; } - int DeathCount() const { return m_iDeaths;} - bool IsConnected() const { return m_iConnected != PlayerDisconnected; } - bool IsDisconnecting() const { return m_iConnected == PlayerDisconnecting; } - bool IsSuitEquipped() const { return m_Local.m_bWearingSuit; } - int ArmorValue() const { return m_ArmorValue; } - bool HUDNeedsRestart() const { return m_fInitHUD; } - float MaxSpeed() const { return m_flMaxspeed; } - Activity GetActivity( ) const { return m_Activity; } - inline void SetActivity( Activity eActivity ) { m_Activity = eActivity; } - bool IsPlayerLockedInPlace() const { return m_iPlayerLocked != 0; } - bool IsObserver() const { return (m_afPhysicsFlags & PFLAG_OBSERVER) != 0; } - bool IsOnTarget() const { return m_fOnTarget; } - float MuzzleFlashTime() const { return m_flFlashTime; } - float PlayerDrownTime() const { return m_AirFinished; } - - int GetObserverMode() const { return m_iObserverMode; } - CBaseEntity *GetObserverTarget() const { return m_hObserverTarget; } - - // Round gamerules - virtual bool IsReadyToPlay( void ) { return true; } - virtual bool IsReadyToSpawn( void ) { return true; } - virtual bool ShouldGainInstantSpawn( void ) { return false; } - virtual void ResetPerRoundStats( void ) { return; } - void AllowInstantSpawn( void ) { m_bAllowInstantSpawn = true; } - - virtual void ResetScores( void ) { ResetFragCount(); ResetDeathCount(); } - void ResetFragCount(); - void IncrementFragCount( int nCount ); - - void ResetDeathCount(); - void IncrementDeathCount( int nCount ); - - void SetArmorValue( int value ); - void IncrementArmorValue( int nCount, int nMaxValue = -1 ); - - void SetConnected( PlayerConnectedState iConnected ) { m_iConnected = iConnected; } - virtual void EquipSuit( bool bPlayEffects = true ); - virtual void RemoveSuit( void ); - void SetMaxSpeed( float flMaxSpeed ) { m_flMaxspeed = flMaxSpeed; } - - void NotifyNearbyRadiationSource( float flRange ); - - void SetAnimationExtension( const char *pExtension ); - - void SetAdditionalPVSOrigin( const Vector &vecOrigin ); - void SetCameraPVSOrigin( const Vector &vecOrigin ); - void SetMuzzleFlashTime( float flTime ); - void SetUseEntity( CBaseEntity *pUseEntity ); - CBaseEntity *GetUseEntity(); - - // Used to set private physics flags PFLAG_* - void SetPhysicsFlag( int nFlag, bool bSet ); - - void AllowImmediateDecalPainting(); - - // Suicide... - virtual void CommitSuicide( bool bExplode = false, bool bForce = false ); - virtual void CommitSuicide( const Vector &vecForce, bool bExplode = false, bool bForce = false ); - - // For debugging... - void ForceOrigin( const Vector &vecOrigin ); - - // Bot accessors... - void SetTimeBase( float flTimeBase ); - float GetTimeBase() const; - void SetLastUserCommand( const CUserCmd &cmd ); - const CUserCmd *GetLastUserCommand( void ); - virtual bool IsBot() const; - - bool IsPredictingWeapons( void ) const; - int CurrentCommandNumber() const; - const CUserCmd *GetCurrentUserCommand() const; - - int GetFOV( void ); // Get the current FOV value - int GetDefaultFOV( void ) const; // Default FOV if not specified otherwise - int GetFOVForNetworking( void ); // Get the current FOV used for network computations - bool SetFOV( CBaseEntity *pRequester, int FOV, float zoomRate = 0.0f, int iZoomStart = 0 ); // Alters the base FOV of the player (must have a valid requester) - void SetDefaultFOV( int FOV ); // Sets the base FOV if nothing else is affecting it by zooming - CBaseEntity *GetFOVOwner( void ) { return m_hZoomOwner; } - float GetFOVDistanceAdjustFactor(); // shared between client and server - float GetFOVDistanceAdjustFactorForNetworking(); - - int GetImpulse( void ) const { return m_nImpulse; } - - // Movement constraints - void ActivateMovementConstraint( CBaseEntity *pEntity, const Vector &vecCenter, float flRadius, float flConstraintWidth, float flSpeedFactor ); - void DeactivateMovementConstraint( ); - - // talk control - void NotePlayerTalked() { m_fLastPlayerTalkTime = gpGlobals->curtime; } - float LastTimePlayerTalked() { return m_fLastPlayerTalkTime; } - - void DisableButtons( int nButtons ); - void EnableButtons( int nButtons ); - void ForceButtons( int nButtons ); - void UnforceButtons( int nButtons ); - - //--------------------------------- - // Inputs - //--------------------------------- - void InputSetHealth( inputdata_t &inputdata ); - void InputSetHUDVisibility( inputdata_t &inputdata ); - - surfacedata_t *GetSurfaceData( void ) { return m_pSurfaceData; } - void SetLadderNormal( Vector vecLadderNormal ) { m_vecLadderNormal = vecLadderNormal; } - - // Here so that derived classes can use the expresser - virtual CAI_Expresser *GetExpresser() { return NULL; }; - - void IncrementEFNoInterpParity(); - int GetEFNoInterpParity() const; - -private: - - // For queueing up CUserCmds and running them from PhysicsSimulate - int GetCommandContextCount( void ) const; - CCommandContext *GetCommandContext( int index ); - CCommandContext *AllocCommandContext( void ); - void RemoveCommandContext( int index ); - void RemoveAllCommandContexts( void ); - CCommandContext *RemoveAllCommandContextsExceptNewest( void ); - void ReplaceContextCommands( CCommandContext *ctx, CUserCmd *pCommands, int nCommands ); - - int DetermineSimulationTicks( void ); - void AdjustPlayerTimeBase( int simulation_ticks ); - -public: - - // Used by gamemovement to check if the entity is stuck. - int m_StuckLast; - - // FIXME: Make these protected or private! - - // This player's data that should only be replicated to - // the player and not to other players. - CNetworkVarEmbedded( CPlayerLocalData, m_Local ); - void InitFogController( void ); - void InputSetFogController( inputdata_t &inputdata ); - - // Used by env_soundscape_triggerable to manage when the player is touching multiple - // soundscape triggers simultaneously. - // The one at the HEAD of the list is always the current soundscape for the player. - CUtlVector m_hTriggerSoundscapeList; - - // Player data that's sometimes needed by the engine - CNetworkVarEmbedded( CPlayerState, pl ); - - IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_fFlags ); - - IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_vecViewOffset ); - IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_flFriction ); - IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_iAmmo ); - - IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_hGroundEntity ); - - IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_lifeState ); - IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_iHealth ); - IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_vecBaseVelocity ); - IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_nNextThinkTick ); - IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_vecVelocity ); - IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_nWaterLevel ); - - int m_nButtons; - int m_afButtonPressed; - int m_afButtonReleased; - int m_afButtonLast; - int m_afButtonDisabled; // A mask of input flags that are cleared automatically - int m_afButtonForced; // These are forced onto the player's inputs - - CNetworkVar( bool, m_fOnTarget ); //Is the crosshair on a target? - - char m_szAnimExtension[32]; - - int m_nUpdateRate; // user snapshot rate cl_updaterate - float m_fLerpTime; // users cl_interp - bool m_bLagCompensation; // user wants lag compenstation - bool m_bPredictWeapons; // user has client side predicted weapons - - float GetDeathTime( void ) { return m_flDeathTime; } - - void ClearZoomOwner( void ); - - void SetPreviouslyPredictedOrigin( const Vector &vecAbsOrigin ); - const Vector &GetPreviouslyPredictedOrigin() const; - float GetFOVTime( void ){ return m_flFOVTime; } - - void AdjustDrownDmg( int nAmount ); - -private: - - Activity m_Activity; - -protected: - - void CalcPlayerView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov ); - void CalcVehicleView( IServerVehicle *pVehicle, Vector& eyeOrigin, QAngle& eyeAngles, - float& zNear, float& zFar, float& fov ); - void CalcObserverView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov ); - void CalcViewModelView( const Vector& eyeOrigin, const QAngle& eyeAngles); - - // FIXME: Make these private! (tf_player uses them) - - // Secondary point to derive PVS from when zoomed in with binoculars/sniper rifle. The PVS is - // a merge of the standing origin and this additional origin - Vector m_vecAdditionalPVSOrigin; - // Extra PVS origin if we are using a camera object - Vector m_vecCameraPVSOrigin; - - CNetworkHandle( CBaseEntity, m_hUseEntity ); // the player is currently controlling this entity because of +USE latched, NULL if no entity - - int m_iTrain; // Train control position - - float m_iRespawnFrames; // used in PlayerDeathThink() to make sure players can always respawn - unsigned int m_afPhysicsFlags; // physics flags - set when 'normal' physics should be revisited or overriden - - // Vehicles - CNetworkHandle( CBaseEntity, m_hVehicle ); - - int m_iVehicleAnalogBias; - - void UpdateButtonState( int nUserCmdButtonMask ); - - bool m_bPauseBonusProgress; - CNetworkVar( int, m_iBonusProgress ); - CNetworkVar( int, m_iBonusChallenge ); - - int m_lastDamageAmount; // Last damage taken - - Vector m_DmgOrigin; - float m_DmgTake; - float m_DmgSave; - int m_bitsDamageType; // what types of damage has player taken - int m_bitsHUDDamage; // Damage bits for the current fame. These get sent to the hud via gmsgDamage - - CNetworkVar( float, m_flDeathTime ); // the time at which the player died (used in PlayerDeathThink()) - float m_flDeathAnimTime; // the time at which the player finished their death anim (used in PlayerDeathThink() and ShouldTransmit()) - - CNetworkVar( int, m_iObserverMode ); // if in spectator mode != 0 - CNetworkVar( int, m_iFOV ); // field of view - CNetworkVar( int, m_iDefaultFOV ); // default field of view - CNetworkVar( int, m_iFOVStart ); // What our FOV started at - CNetworkVar( float, m_flFOVTime ); // Time our FOV change started - - int m_iObserverLastMode; // last used observer mode - CNetworkHandle( CBaseEntity, m_hObserverTarget ); // entity handle to m_iObserverTarget - bool m_bForcedObserverMode; // true, player was forced by invalid targets to switch mode - - CNetworkHandle( CBaseEntity, m_hZoomOwner ); //This is a pointer to the entity currently controlling the player's zoom - //Only this entity can change the zoom state once it has ownership - - float m_tbdPrev; // Time-based damage timer - int m_idrowndmg; // track drowning damage taken - int m_idrownrestored; // track drowning damage restored - int m_nPoisonDmg; // track recoverable poison damage taken - int m_nPoisonRestored; // track poison damage restored - // NOTE: bits damage type appears to only be used for time-based damage - BYTE m_rgbTimeBasedDamage[CDMG_TIMEBASED]; - - // Player Physics Shadow - int m_vphysicsCollisionState; - - virtual int SpawnArmorValue( void ) const { return 0; } - - float m_fNextSuicideTime; // the time after which the player can next use the suicide command - int m_iSuicideCustomKillFlags; - - // Replay mode - float m_fDelay; // replay delay in seconds - float m_fReplayEnd; // time to stop replay mode - int m_iReplayEntity; // follow this entity in replay - -private: - void HandleFuncTrain(); - -// DATA -private: - CUtlVector< CCommandContext > m_CommandContext; - // Player Physics Shadow - -protected: //used to be private, but need access for portal mod (Dave Kircher) - IPhysicsPlayerController *m_pPhysicsController; - IPhysicsObject *m_pShadowStand; - IPhysicsObject *m_pShadowCrouch; - Vector m_oldOrigin; - Vector m_vecSmoothedVelocity; - bool m_touchedPhysObject; - bool m_bPhysicsWasFrozen; - -private: - - int m_iPlayerSound;// the index of the sound list slot reserved for this player - int m_iTargetVolume;// ideal sound volume. - - int m_rgItems[MAX_ITEMS]; - - // these are time-sensitive things that we keep track of - float m_flSwimTime; // how long player has been underwater - float m_flDuckTime; // how long we've been ducking - float m_flDuckJumpTime; - - float m_flSuitUpdate; // when to play next suit update - int m_rgSuitPlayList[CSUITPLAYLIST];// next sentencenum to play for suit update - int m_iSuitPlayNext; // next sentence slot for queue storage; - int m_rgiSuitNoRepeat[CSUITNOREPEAT]; // suit sentence no repeat list - float m_rgflSuitNoRepeatTime[CSUITNOREPEAT]; // how long to wait before allowing repeat - - float m_flgeigerRange; // range to nearest radiation source - float m_flgeigerDelay; // delay per update of range msg to client - int m_igeigerRangePrev; - - bool m_fInitHUD; // True when deferred HUD restart msg needs to be sent - bool m_fGameHUDInitialized; - bool m_fWeapon; // Set this to FALSE to force a reset of the current weapon HUD info - - int m_iUpdateTime; // stores the number of frame ticks before sending HUD update messages - int m_iClientBattery; // the Battery currently known by the client. If this changes, send a new - - // Autoaim data - QAngle m_vecAutoAim; - int m_lastx, m_lasty; // These are the previous update's crosshair angles, DON"T SAVE/RESTORE - - int m_iFrags; - int m_iDeaths; - - float m_flNextDecalTime;// next time this player can spray a decal - - // Team Handling - // char m_szTeamName[TEAM_NAME_LENGTH]; - - // Multiplayer handling - PlayerConnectedState m_iConnected; - - // from edict_t - // CBasePlayer doesn't send this but CCSPlayer does. - CNetworkVarForDerived( int, m_ArmorValue ); - float m_AirFinished; - float m_PainFinished; - - // player locking - int m_iPlayerLocked; - - -protected: - // the player's personal view model - typedef CHandle CBaseViewModelHandle; - CNetworkArray( CBaseViewModelHandle, m_hViewModel, MAX_VIEWMODELS ); - - // Last received usercmd (in case we drop a lot of packets ) - CUserCmd m_LastCmd; - CUserCmd *m_pCurrentCommand; - - float m_flStepSoundTime; // time to check for next footstep sound - - bool m_bAllowInstantSpawn; - -private: - -// Replicated to all clients - CNetworkVar( float, m_flMaxspeed ); - -// Not transmitted - float m_flWaterJumpTime; // used to be called teleport_time - Vector m_vecWaterJumpVel; - int m_nImpulse; - float m_flSwimSoundTime; - Vector m_vecLadderNormal; - - float m_flFlashTime; - int m_nDrownDmgRate; // Drowning damage in points per second without air. - - int m_nNumCrouches; // Number of times we've crouched (for hinting) - bool m_bDuckToggled; // If true, the player is crouching via a toggle - -public: - bool GetToggledDuckState( void ) { return m_bDuckToggled; } - void ToggleDuck( void ); - float GetStickDist( void ); - - float m_flForwardMove; - float m_flSideMove; - int m_nNumCrateHudHints; - -private: - - // Used in test code to teleport the player to random locations in the map. - Vector m_vForcedOrigin; - bool m_bForceOrigin; - - // Clients try to run on their own realtime clock, this is this client's clock - CNetworkVar( int, m_nTickBase ); - - bool m_bGamePaused; - float m_fLastPlayerTalkTime; - - CNetworkVar( CBaseCombatWeaponHandle, m_hLastWeapon ); - -#if !defined( NO_ENTITY_PREDICTION ) - CUtlVector< CHandle< CBaseEntity > > m_SimulatedByThisPlayer; -#endif - - float m_flOldPlayerZ; - float m_flOldPlayerViewOffsetZ; - - bool m_bPlayerUnderwater; - - EHANDLE m_hViewEntity; - - // Movement constraints - CNetworkHandle( CBaseEntity, m_hConstraintEntity ); - CNetworkVector( m_vecConstraintCenter ); - CNetworkVar( float, m_flConstraintRadius ); - CNetworkVar( float, m_flConstraintWidth ); - CNetworkVar( float, m_flConstraintSpeedFactor ); - - friend class CPlayerMove; - friend class CPlayerClass; - - // Player name - char m_szNetname[MAX_PLAYER_NAME_LENGTH]; - -protected: - // HACK FOR TF2 Prediction - friend class CTFGameMovementRecon; - friend class CGameMovement; - friend class CTFGameMovement; - friend class CHL1GameMovement; - friend class CCSGameMovement; - friend class CHL2GameMovement; - friend class CDODGameMovement; - friend class CPortalGameMovement; - - // Accessors for gamemovement - bool IsDucked( void ) const { return m_Local.m_bDucked; } - bool IsDucking( void ) const { return m_Local.m_bDucking; } - float GetStepSize( void ) const { return m_Local.m_flStepSize; } - - CNetworkVar( float, m_flLaggedMovementValue ); - - // These are generated while running usercmds, then given to UpdateVPhysicsPosition after running all queued commands. - Vector m_vNewVPhysicsPosition; - Vector m_vNewVPhysicsVelocity; - - Vector m_vecVehicleViewOrigin; // Used to store the calculated view of the player while riding in a vehicle - QAngle m_vecVehicleViewAngles; // Vehicle angles - float m_flVehicleViewFOV; // FOV of the vehicle driver - int m_nVehicleViewSavedFrame; // Used to mark which frame was the last one the view was calculated for - - Vector m_vecPreviouslyPredictedOrigin; // Used to determine if non-gamemovement game code has teleported, or tweaked the player's origin - int m_nBodyPitchPoseParam; - - // last known navigation area of player - NULL if unknown - CNavArea *m_lastNavArea; - CNetworkString( m_szLastPlaceName, MAX_PLACE_NAME_LENGTH ); - - char m_szNetworkIDString[MAX_NETWORKID_LENGTH]; - CPlayerInfo m_PlayerInfo; - - // Texture names and surface data, used by CGameMovement - int m_surfaceProps; - surfacedata_t* m_pSurfaceData; - float m_surfaceFriction; - char m_chTextureType; - char m_chPreviousTextureType; // Separate from m_chTextureType. This is cleared if the player's not on the ground. - - bool m_bSinglePlayerGameEnding; - - CNetworkVar( int, m_ubEFNoInterpParity ); - -public: - - float GetLaggedMovementValue( void ){ return m_flLaggedMovementValue; } - void SetLaggedMovementValue( float flValue ) { m_flLaggedMovementValue = flValue; } - - inline bool IsAutoKickDisabled( void ) const; - inline void DisableAutoKick( bool disabled ); - - void DumpPerfToRecipient( CBasePlayer *pRecipient, int nMaxRecords ); -private: - bool m_autoKickDisabled; - - struct StepSoundCache_t - { - StepSoundCache_t() : m_usSoundNameIndex( 0 ) {} - CSoundParameters m_SoundParameters; - unsigned short m_usSoundNameIndex; - }; - // One for left and one for right side of step - StepSoundCache_t m_StepSoundCache[ 2 ]; - - CUtlLinkedList< CPlayerSimInfo > m_vecPlayerSimInfo; - CUtlLinkedList< CPlayerCmdInfo > m_vecPlayerCmdInfo; -}; - -typedef CHandle CBasePlayerHandle; - -EXTERN_SEND_TABLE(DT_BasePlayer) - - - -//----------------------------------------------------------------------------- -// Inline methods -//----------------------------------------------------------------------------- -inline bool CBasePlayer::IsAutoKickDisabled( void ) const -{ - return m_autoKickDisabled; -} - -inline void CBasePlayer::DisableAutoKick( bool disabled ) -{ - m_autoKickDisabled = disabled; -} - -inline void CBasePlayer::SetAdditionalPVSOrigin( const Vector &vecOrigin ) -{ - m_vecAdditionalPVSOrigin = vecOrigin; -} - -inline void CBasePlayer::SetCameraPVSOrigin( const Vector &vecOrigin ) -{ - m_vecCameraPVSOrigin = vecOrigin; -} - -inline void CBasePlayer::SetMuzzleFlashTime( float flTime ) -{ - m_flFlashTime = flTime; -} - -inline void CBasePlayer::SetUseEntity( CBaseEntity *pUseEntity ) -{ - m_hUseEntity = pUseEntity; -} - -inline CBaseEntity *CBasePlayer::GetUseEntity() -{ - return m_hUseEntity; -} - -// Bot accessors... -inline void CBasePlayer::SetTimeBase( float flTimeBase ) -{ - m_nTickBase = TIME_TO_TICKS( flTimeBase ); -} - -inline void CBasePlayer::SetLastUserCommand( const CUserCmd &cmd ) -{ - m_LastCmd = cmd; -} - -inline CUserCmd const *CBasePlayer::GetLastUserCommand( void ) -{ - return &m_LastCmd; -} - -inline bool CBasePlayer::IsPredictingWeapons( void ) const -{ - return m_bPredictWeapons; -} - -inline int CBasePlayer::CurrentCommandNumber() const -{ - Assert( m_pCurrentCommand ); - return m_pCurrentCommand->command_number; -} - -inline const CUserCmd *CBasePlayer::GetCurrentUserCommand() const -{ - Assert( m_pCurrentCommand ); - return m_pCurrentCommand; -} - -inline IServerVehicle *CBasePlayer::GetVehicle() -{ - CBaseEntity *pVehicleEnt = m_hVehicle.Get(); - return pVehicleEnt ? pVehicleEnt->GetServerVehicle() : NULL; -} - -inline CBaseEntity *CBasePlayer::GetVehicleEntity() -{ - return m_hVehicle.Get(); -} - -inline bool CBasePlayer::IsInAVehicle( void ) const -{ - return ( NULL != m_hVehicle.Get() ) ? true : false; -} - -inline void CBasePlayer::SetTouchedPhysics( bool bTouch ) -{ - m_touchedPhysObject = bTouch; -} - -inline bool CBasePlayer::TouchedPhysics( void ) -{ - return m_touchedPhysObject; -} - -//----------------------------------------------------------------------------- -// Converts an entity to a player -//----------------------------------------------------------------------------- -inline CBasePlayer *ToBasePlayer( CBaseEntity *pEntity ) -{ - if ( !pEntity || !pEntity->IsPlayer() ) - return NULL; -#if _DEBUG - return dynamic_cast( pEntity ); -#else - return static_cast( pEntity ); -#endif -} - -//-------------------------------------------------------------------------------------------------------------- -/** - * Iterate over all active players in the game, invoking functor on each. - * If functor returns false, stop iteration and return false. - */ -template < typename Functor > -bool ForEachPlayer( Functor &func ) -{ - for( int i=1; i<=gpGlobals->maxClients; ++i ) - { - CBasePlayer *player = static_cast( UTIL_PlayerByIndex( i ) ); - - if (player == NULL) - continue; - - if (FNullEnt( player->edict() )) - continue; - - if (!player->IsPlayer()) - continue; - - if (func( player ) == false) - return false; - } - - return true; -} - -enum -{ - VEHICLE_ANALOG_BIAS_NONE = 0, - VEHICLE_ANALOG_BIAS_FORWARD, - VEHICLE_ANALOG_BIAS_REVERSE, -}; - -#endif // PLAYER_H diff --git a/game/server/player_command.cpp b/game/server/player_command.cpp deleted file mode 100644 index c4ad80189..000000000 --- a/game/server/player_command.cpp +++ /dev/null @@ -1,433 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "player.h" -#include "usercmd.h" -#include "igamemovement.h" -#include "mathlib/mathlib.h" -#include "client.h" -#include "player_command.h" -#include "movehelper_server.h" -#include "iservervehicle.h" -#include "tier0/vprof.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern IGameMovement *g_pGameMovement; -extern CMoveData *g_pMoveData; // This is a global because it is subclassed by each game. -extern ConVar sv_noclipduringpause; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CPlayerMove::CPlayerMove( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: We're about to run this usercmd for the specified player. We can set up groupinfo and masking here, etc. -// This is the time to examine the usercmd for anything extra. This call happens even if think does not. -// Input : *player - -// *cmd - -//----------------------------------------------------------------------------- -void CPlayerMove::StartCommand( CBasePlayer *player, CUserCmd *cmd ) -{ - VPROF( "CPlayerMove::StartCommand" ); - -#if !defined( NO_ENTITY_PREDICTION ) - CPredictableId::ResetInstanceCounters(); -#endif - - player->m_pCurrentCommand = cmd; - CBaseEntity::SetPredictionRandomSeed( cmd ); - CBaseEntity::SetPredictionPlayer( player ); - -#if defined (HL2_DLL) - // pull out backchannel data and move this out - - // Let's not bother with IK data in MP games - if ( 1 == gpGlobals->maxClients ) - { - int i; - for (i = 0; i < cmd->entitygroundcontact.Count(); i++) - { - int entindex = cmd->entitygroundcontact[i].entindex; - CBaseEntity *pEntity = CBaseEntity::Instance( engine->PEntityOfEntIndex( entindex) ); - if (pEntity) - { - CBaseAnimating *pAnimating = pEntity->GetBaseAnimating(); - if (pAnimating) - { - pAnimating->SetIKGroundContactInfo( cmd->entitygroundcontact[i].minheight, cmd->entitygroundcontact[i].maxheight ); - } - } - } - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: We've finished running a user's command -// Input : *player - -//----------------------------------------------------------------------------- -void CPlayerMove::FinishCommand( CBasePlayer *player ) -{ - VPROF( "CPlayerMove::FinishCommand" ); - - player->m_pCurrentCommand = NULL; - CBaseEntity::SetPredictionRandomSeed( NULL ); - CBaseEntity::SetPredictionPlayer( NULL ); -} - -//----------------------------------------------------------------------------- -// Purpose: Checks if the player is standing on a moving entity and adjusts velocity and -// basevelocity appropriately -// Input : *player - -// frametime - -//----------------------------------------------------------------------------- -void CPlayerMove::CheckMovingGround( CBasePlayer *player, double frametime ) -{ - VPROF( "CPlayerMove::CheckMovingGround()" ); - - CBaseEntity *groundentity; - - if ( player->GetFlags() & FL_ONGROUND ) - { - groundentity = player->GetGroundEntity(); - if ( groundentity && ( groundentity->GetFlags() & FL_CONVEYOR) ) - { - Vector vecNewVelocity; - groundentity->GetGroundVelocityToApply( vecNewVelocity ); - if ( player->GetFlags() & FL_BASEVELOCITY ) - { - vecNewVelocity += player->GetBaseVelocity(); - } - player->SetBaseVelocity( vecNewVelocity ); - player->AddFlag( FL_BASEVELOCITY ); - } - } - - if ( !( player->GetFlags() & FL_BASEVELOCITY ) ) - { - // Apply momentum (add in half of the previous frame of velocity first) - player->ApplyAbsVelocityImpulse( (1.0 + ( frametime * 0.5 )) * player->GetBaseVelocity() ); - player->SetBaseVelocity( vec3_origin ); - } - - player->RemoveFlag( FL_BASEVELOCITY ); -} - -//----------------------------------------------------------------------------- -// Purpose: Prepares for running movement -// Input : *player - -// *ucmd - -// *pHelper - -// *move - -// time - -//----------------------------------------------------------------------------- -void CPlayerMove::SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) -{ - VPROF( "CPlayerMove::SetupMove" ); - - // Allow sound, etc. to be created by movement code - move->m_bFirstRunOfFunctions = true; - move->m_bGameCodeMovedPlayer = false; - if ( player->GetPreviouslyPredictedOrigin() != player->GetAbsOrigin() ) - { - move->m_bGameCodeMovedPlayer = true; - } - - // Prepare the usercmd fields - move->m_nImpulseCommand = ucmd->impulse; - move->m_vecViewAngles = ucmd->viewangles; - - CBaseEntity *pMoveParent = player->GetMoveParent(); - if (!pMoveParent) - { - move->m_vecAbsViewAngles = move->m_vecViewAngles; - } - else - { - matrix3x4_t viewToParent, viewToWorld; - AngleMatrix( move->m_vecViewAngles, viewToParent ); - ConcatTransforms( pMoveParent->EntityToWorldTransform(), viewToParent, viewToWorld ); - MatrixAngles( viewToWorld, move->m_vecAbsViewAngles ); - } - - move->m_nButtons = ucmd->buttons; - - // Ingore buttons for movement if at controls - if ( player->GetFlags() & FL_ATCONTROLS ) - { - move->m_flForwardMove = 0; - move->m_flSideMove = 0; - move->m_flUpMove = 0; - } - else - { - move->m_flForwardMove = ucmd->forwardmove; - move->m_flSideMove = ucmd->sidemove; - move->m_flUpMove = ucmd->upmove; - } - - // Prepare remaining fields - move->m_flClientMaxSpeed = player->m_flMaxspeed; - move->m_nOldButtons = player->m_Local.m_nOldButtons; - move->m_vecAngles = player->pl.v_angle; - - move->m_vecVelocity = player->GetAbsVelocity(); - - move->m_nPlayerHandle = player; - - move->SetAbsOrigin( player->GetAbsOrigin() ); - - // Copy constraint information - if ( player->m_hConstraintEntity.Get() ) - move->m_vecConstraintCenter = player->m_hConstraintEntity.Get()->GetAbsOrigin(); - else - move->m_vecConstraintCenter = player->m_vecConstraintCenter; - move->m_flConstraintRadius = player->m_flConstraintRadius; - move->m_flConstraintWidth = player->m_flConstraintWidth; - move->m_flConstraintSpeedFactor = player->m_flConstraintSpeedFactor; -} - -//----------------------------------------------------------------------------- -// Purpose: Finishes running movement -// Input : *player - -// *move - -// *ucmd - -// time - -//----------------------------------------------------------------------------- -void CPlayerMove::FinishMove( CBasePlayer *player, CUserCmd *ucmd, CMoveData *move ) -{ - VPROF( "CPlayerMove::FinishMove" ); - - player->m_flMaxspeed = move->m_flClientMaxSpeed; - player->SetAbsOrigin( move->GetAbsOrigin() ); - player->SetAbsVelocity( move->m_vecVelocity ); - player->SetPreviouslyPredictedOrigin( move->GetAbsOrigin() ); - - player->m_Local.m_nOldButtons = move->m_nButtons; - - // Convert final pitch to body pitch - float pitch = move->m_vecAngles[ PITCH ]; - if ( pitch > 180.0f ) - { - pitch -= 360.0f; - } - pitch = clamp( pitch, -90, 90 ); - - move->m_vecAngles[ PITCH ] = pitch; - - player->SetBodyPitch( pitch ); - - player->SetLocalAngles( move->m_vecAngles ); - - // The class had better not have changed during the move!! - if ( player->m_hConstraintEntity ) - Assert( move->m_vecConstraintCenter == player->m_hConstraintEntity.Get()->GetAbsOrigin() ); - else - Assert( move->m_vecConstraintCenter == player->m_vecConstraintCenter ); - Assert( move->m_flConstraintRadius == player->m_flConstraintRadius ); - Assert( move->m_flConstraintWidth == player->m_flConstraintWidth ); - Assert( move->m_flConstraintSpeedFactor == player->m_flConstraintSpeedFactor ); -} - -//----------------------------------------------------------------------------- -// Purpose: Called before player thinks -// Input : *player - -// thinktime - -//----------------------------------------------------------------------------- -void CPlayerMove::RunPreThink( CBasePlayer *player ) -{ - VPROF( "CPlayerMove::RunPreThink" ); - - // Run think functions on the player - VPROF_SCOPE_BEGIN( "player->PhysicsRunThink()" ); - if ( !player->PhysicsRunThink() ) - return; - VPROF_SCOPE_END(); - - VPROF_SCOPE_BEGIN( "g_pGameRules->PlayerThink( player )" ); - // Called every frame to let game rules do any specific think logic for the player - g_pGameRules->PlayerThink( player ); - VPROF_SCOPE_END(); - - VPROF_SCOPE_BEGIN( "player->PreThink()" ); - player->PreThink(); - VPROF_SCOPE_END(); -} - -//----------------------------------------------------------------------------- -// Purpose: Runs the PLAYER's thinking code if time. There is some play in the exact time the think -// function will be called, because it is called before any movement is done -// in a frame. Not used for pushmove objects, because they must be exact. -// Returns false if the entity removed itself. -// Input : *ent - -// frametime - -// clienttimebase - -// Output : void CPlayerMove::RunThink -//----------------------------------------------------------------------------- -void CPlayerMove::RunThink (CBasePlayer *player, double frametime ) -{ - VPROF( "CPlayerMove::RunThink" ); - int thinktick = player->GetNextThinkTick(); - - if ( thinktick <= 0 || thinktick > player->m_nTickBase ) - return; - - //gpGlobals->curtime = thinktime; - player->SetNextThink( TICK_NEVER_THINK ); - - // Think - player->Think(); -} - -//----------------------------------------------------------------------------- -// Purpose: Called after player movement -// Input : *player - -// thinktime - -// frametime - -//----------------------------------------------------------------------------- -void CPlayerMove::RunPostThink( CBasePlayer *player ) -{ - VPROF( "CPlayerMove::RunPostThink" ); - - // Run post-think - player->PostThink(); -} - -void CommentarySystem_PePlayerRunCommand( CBasePlayer *player, CUserCmd *ucmd ); - -//----------------------------------------------------------------------------- -// Purpose: Runs movement commands for the player -// Input : *player - -// *ucmd - -// *moveHelper - -// Output : void CPlayerMove::RunCommand -//----------------------------------------------------------------------------- -void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *moveHelper ) -{ - StartCommand( player, ucmd ); - - // Set globals appropriately - gpGlobals->curtime = player->m_nTickBase * TICK_INTERVAL; - gpGlobals->frametime = player->m_bGamePaused ? 0 : TICK_INTERVAL; - - // Add and subtract buttons we're forcing on the player - ucmd->buttons |= player->m_afButtonForced; - ucmd->buttons &= ~player->m_afButtonDisabled; - - if ( player->m_bGamePaused ) - { - // If no clipping and cheats enabled and noclipduring game enabled, then leave - // forwardmove and angles stuff in usercmd - if ( player->GetMoveType() == MOVETYPE_NOCLIP && - sv_cheats->GetBool() && - sv_noclipduringpause.GetBool() ) - { - gpGlobals->frametime = TICK_INTERVAL; - } - } - - /* - // TODO: We can check whether the player is sending more commands than elapsed real time - cmdtimeremaining -= ucmd->msec; - if ( cmdtimeremaining < 0 ) - { - // return; - } - */ - - g_pGameMovement->StartTrackPredictionErrors( player ); - - CommentarySystem_PePlayerRunCommand( player, ucmd ); - - // Do weapon selection - if ( ucmd->weaponselect != 0 ) - { - CBaseCombatWeapon *weapon = dynamic_cast< CBaseCombatWeapon * >( CBaseEntity::Instance( ucmd->weaponselect ) ); - if ( weapon ) - { - VPROF( "player->SelectItem()" ); - player->SelectItem( weapon->GetName(), ucmd->weaponsubtype ); - } - } - - IServerVehicle *pVehicle = player->GetVehicle(); - - // Latch in impulse. - if ( ucmd->impulse ) - { - // Discard impulse commands unless the vehicle allows them. - // FIXME: UsingStandardWeapons seems like a bad filter for this. The flashlight is an impulse command, for example. - if ( !pVehicle || player->UsingStandardWeaponsInVehicle() ) - { - player->m_nImpulse = ucmd->impulse; - } - } - - // Update player input button states - VPROF_SCOPE_BEGIN( "player->UpdateButtonState" ); - player->UpdateButtonState( ucmd->buttons ); - VPROF_SCOPE_END(); - - CheckMovingGround( player, TICK_INTERVAL ); - - g_pMoveData->m_vecOldAngles = player->pl.v_angle; - - // Copy from command to player unless game .dll has set angle using fixangle - if ( player->pl.fixangle == FIXANGLE_NONE ) - { - player->pl.v_angle = ucmd->viewangles; - } - else if( player->pl.fixangle == FIXANGLE_RELATIVE ) - { - player->pl.v_angle = ucmd->viewangles + player->pl.anglechange; - } - - // Call standard client pre-think - RunPreThink( player ); - - // Call Think if one is set - RunThink( player, TICK_INTERVAL ); - - // Setup input. - SetupMove( player, ucmd, moveHelper, g_pMoveData ); - - // Let the game do the movement. - if ( !pVehicle ) - { - VPROF( "g_pGameMovement->ProcessMovement()" ); - Assert( g_pGameMovement ); - g_pGameMovement->ProcessMovement( player, g_pMoveData ); - } - else - { - VPROF( "pVehicle->ProcessMovement()" ); - pVehicle->ProcessMovement( player, g_pMoveData ); - } - - // Copy output - FinishMove( player, ucmd, g_pMoveData ); - - // Let server invoke any needed impact functions - VPROF_SCOPE_BEGIN( "moveHelper->ProcessImpacts" ); - moveHelper->ProcessImpacts(); - VPROF_SCOPE_END(); - - RunPostThink( player ); - - g_pGameMovement->FinishTrackPredictionErrors( player ); - - FinishCommand( player ); - - // Let time pass - player->m_nTickBase++; -} - diff --git a/game/server/player_command.h b/game/server/player_command.h deleted file mode 100644 index b79434d6a..000000000 --- a/game/server/player_command.h +++ /dev/null @@ -1,64 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PLAYER_COMMAND_H -#define PLAYER_COMMAND_H -#pragma once - - -#include "edict.h" -#include "usercmd.h" - - -class IMoveHelper; -class CMoveData; -class CBasePlayer; - -//----------------------------------------------------------------------------- -// Purpose: Server side player movement -//----------------------------------------------------------------------------- -class CPlayerMove -{ -public: - DECLARE_CLASS_NOBASE( CPlayerMove ); - - // Construction/destruction - CPlayerMove( void ); - virtual ~CPlayerMove( void ) {} - - // Public interfaces: - // Run a movement command from the player - void RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *moveHelper ); - -protected: - // Prepare for running movement - virtual void SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ); - - // Finish movement - virtual void FinishMove( CBasePlayer *player, CUserCmd *ucmd, CMoveData *move ); - - // Called before and after any movement processing - virtual void StartCommand( CBasePlayer *player, CUserCmd *cmd ); - void FinishCommand( CBasePlayer *player ); - - // Helper to determine if the user is standing on ground - void CheckMovingGround( CBasePlayer *player, double frametime ); - - // Helpers to call pre and post think for player, and to call think if a think function is set - void RunPreThink( CBasePlayer *player ); - void RunThink (CBasePlayer *ent, double frametime ); - void RunPostThink( CBasePlayer *player ); -}; - - -//----------------------------------------------------------------------------- -// Singleton accessor -//----------------------------------------------------------------------------- -CPlayerMove *PlayerMove(); - - -#endif // PLAYER_COMMAND_H diff --git a/game/server/player_lagcompensation.cpp b/game/server/player_lagcompensation.cpp deleted file mode 100644 index 3229a77c8..000000000 --- a/game/server/player_lagcompensation.cpp +++ /dev/null @@ -1,800 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "usercmd.h" -#include "igamesystem.h" -#include "ilagcompensationmanager.h" -#include "inetchannelinfo.h" -#include "utllinkedlist.h" -#include "BaseAnimatingOverlay.h" -#include "tier0/vprof.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define LC_NONE 0 -#define LC_ALIVE (1<<0) - -#define LC_ORIGIN_CHANGED (1<<8) -#define LC_ANGLES_CHANGED (1<<9) -#define LC_SIZE_CHANGED (1<<10) -#define LC_ANIMATION_CHANGED (1<<11) - -#define LAG_COMPENSATION_TELEPORTED_DISTANCE_SQR ( 64.0f * 64.0f ) -#define LAG_COMPENSATION_EPS_SQR ( 0.1f * 0.1f ) -// Allow 4 units of error ( about 1 / 8 bbox width ) -#define LAG_COMPENSATION_ERROR_EPS_SQR ( 4.0f * 4.0f ) - -ConVar sv_unlag( "sv_unlag", "1", FCVAR_DEVELOPMENTONLY, "Enables player lag compensation" ); -ConVar sv_maxunlag( "sv_maxunlag", "1.0", FCVAR_DEVELOPMENTONLY, "Maximum lag compensation in seconds", true, 0.0f, true, 1.0f ); -ConVar sv_lagflushbonecache( "sv_lagflushbonecache", "1", FCVAR_DEVELOPMENTONLY, "Flushes entity bone cache on lag compensation" ); -ConVar sv_showlagcompensation( "sv_showlagcompensation", "0", FCVAR_CHEAT, "Show lag compensated hitboxes whenever a player is lag compensated." ); - -ConVar sv_unlag_fixstuck( "sv_unlag_fixstuck", "0", FCVAR_DEVELOPMENTONLY, "Disallow backtracking a player for lag compensation if it will cause them to become stuck" ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -#define MAX_LAYER_RECORDS (CBaseAnimatingOverlay::MAX_OVERLAYS) - -struct LayerRecord -{ - int m_sequence; - float m_cycle; - float m_weight; - int m_order; - - LayerRecord() - { - m_sequence = 0; - m_cycle = 0; - m_weight = 0; - m_order = 0; - } - - LayerRecord( const LayerRecord& src ) - { - m_sequence = src.m_sequence; - m_cycle = src.m_cycle; - m_weight = src.m_weight; - m_order = src.m_order; - } -}; - -struct LagRecord -{ -public: - LagRecord() - { - m_fFlags = 0; - m_vecOrigin.Init(); - m_vecAngles.Init(); - m_vecMins.Init(); - m_vecMaxs.Init(); - m_flSimulationTime = -1; - m_masterSequence = 0; - m_masterCycle = 0; - } - - LagRecord( const LagRecord& src ) - { - m_fFlags = src.m_fFlags; - m_vecOrigin = src.m_vecOrigin; - m_vecAngles = src.m_vecAngles; - m_vecMins = src.m_vecMins; - m_vecMaxs = src.m_vecMaxs; - m_flSimulationTime = src.m_flSimulationTime; - for( int layerIndex = 0; layerIndex < MAX_LAYER_RECORDS; ++layerIndex ) - { - m_layerRecords[layerIndex] = src.m_layerRecords[layerIndex]; - } - m_masterSequence = src.m_masterSequence; - m_masterCycle = src.m_masterCycle; - } - - // Did player die this frame - int m_fFlags; - - // Player position, orientation and bbox - Vector m_vecOrigin; - QAngle m_vecAngles; - Vector m_vecMins; - Vector m_vecMaxs; - - float m_flSimulationTime; - - // Player animation details, so we can get the legs in the right spot. - LayerRecord m_layerRecords[MAX_LAYER_RECORDS]; - int m_masterSequence; - float m_masterCycle; -}; - - -// -// Try to take the player from his current origin to vWantedPos. -// If it can't get there, leave the player where he is. -// - -ConVar sv_unlag_debug( "sv_unlag_debug", "0", FCVAR_GAMEDLL | FCVAR_DEVELOPMENTONLY ); - -float g_flFractionScale = 0.95; -static void RestorePlayerTo( CBasePlayer *pPlayer, const Vector &vWantedPos ) -{ - // Try to move to the wanted position from our current position. - trace_t tr; - VPROF_BUDGET( "RestorePlayerTo", "CLagCompensationManager" ); - UTIL_TraceEntity( pPlayer, vWantedPos, vWantedPos, MASK_PLAYERSOLID, pPlayer, COLLISION_GROUP_PLAYER_MOVEMENT, &tr ); - if ( tr.startsolid || tr.allsolid ) - { - if ( sv_unlag_debug.GetBool() ) - { - DevMsg( "RestorePlayerTo() could not restore player position for client \"%s\" ( %.1f %.1f %.1f )\n", - pPlayer->GetPlayerName(), vWantedPos.x, vWantedPos.y, vWantedPos.z ); - } - - UTIL_TraceEntity( pPlayer, pPlayer->GetLocalOrigin(), vWantedPos, MASK_PLAYERSOLID, pPlayer, COLLISION_GROUP_PLAYER_MOVEMENT, &tr ); - if ( tr.startsolid || tr.allsolid ) - { - // In this case, the guy got stuck back wherever we lag compensated him to. Nasty. - - if ( sv_unlag_debug.GetBool() ) - DevMsg( " restore failed entirely\n" ); - } - else - { - // We can get to a valid place, but not all the way back to where we were. - Vector vPos; - VectorLerp( pPlayer->GetLocalOrigin(), vWantedPos, tr.fraction * g_flFractionScale, vPos ); - UTIL_SetOrigin( pPlayer, vPos, true ); - - if ( sv_unlag_debug.GetBool() ) - DevMsg( " restore got most of the way\n" ); - } - } - else - { - // Cool, the player can go back to whence he came. - UTIL_SetOrigin( pPlayer, tr.endpos, true ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CLagCompensationManager : public CAutoGameSystemPerFrame, public ILagCompensationManager -{ -public: - CLagCompensationManager( char const *name ) : CAutoGameSystemPerFrame( name ) - { - } - - // IServerSystem stuff - virtual void Shutdown() - { - ClearHistory(); - } - - virtual void LevelShutdownPostEntity() - { - ClearHistory(); - } - - // called after entities think - virtual void FrameUpdatePostEntityThink(); - - // ILagCompensationManager stuff - - // Called during player movement to set up/restore after lag compensation - void StartLagCompensation( CBasePlayer *player, CUserCmd *cmd ); - void FinishLagCompensation( CBasePlayer *player ); - -private: - void BacktrackPlayer( CBasePlayer *player, float flTargetTime ); - - void ClearHistory() - { - for ( int i=0; i m_PlayerTrack[ MAX_PLAYERS ]; - - // Scratchpad for determining what needs to be restored - CBitVec m_RestorePlayer; - bool m_bNeedToRestore; - - LagRecord m_RestoreData[ MAX_PLAYERS ]; // player data before we moved him back - LagRecord m_ChangeData[ MAX_PLAYERS ]; // player data where we moved him back - - CBasePlayer *m_pCurrentPlayer; // The player we are doing lag compensation for -}; - -static CLagCompensationManager g_LagCompensationManager( "CLagCompensationManager" ); -ILagCompensationManager *lagcompensation = &g_LagCompensationManager; - - -//----------------------------------------------------------------------------- -// Purpose: Called once per frame after all entities have had a chance to think -//----------------------------------------------------------------------------- -void CLagCompensationManager::FrameUpdatePostEntityThink() -{ - if ( (gpGlobals->maxClients <= 1) || !sv_unlag.GetBool() ) - { - ClearHistory(); - return; - } - - VPROF_BUDGET( "FrameUpdatePostEntityThink", "CLagCompensationManager" ); - - // remove all records before that time: - int flDeadtime = static_cast(gpGlobals->curtime - sv_maxunlag.GetFloat()); - - // Iterate all active players - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - - CUtlFixedLinkedList< LagRecord > *track = &m_PlayerTrack[i-1]; - - if ( !pPlayer ) - { - track->RemoveAll(); - continue; - } - - Assert( track->Count() < 1000 ); // insanity check - - // remove tail records that are too old - int tailIndex = track->Tail(); - while ( track->IsValidIndex( tailIndex ) ) - { - LagRecord &tail = track->Element( tailIndex ); - - // if tail is within limits, stop - if ( tail.m_flSimulationTime >= flDeadtime ) - break; - - // remove tail, get new tail - track->Remove( tailIndex ); - tailIndex = track->Tail(); - } - - // check if head has same simulation time - if ( track->Count() > 0 ) - { - LagRecord &head = track->Element( track->Head() ); - - // check if player changed simulation time since last time updated - if ( head.m_flSimulationTime >= pPlayer->GetSimulationTime() ) - continue; // don't add new entry for same or older time - } - - // add new record to player track - LagRecord &record = track->Element( track->AddToHead() ); - - record.m_fFlags = 0; - if ( pPlayer->IsAlive() ) - { - record.m_fFlags |= LC_ALIVE; - } - - record.m_flSimulationTime = pPlayer->GetSimulationTime(); - record.m_vecAngles = pPlayer->GetLocalAngles(); - record.m_vecOrigin = pPlayer->GetLocalOrigin(); - record.m_vecMaxs = pPlayer->WorldAlignMaxs(); - record.m_vecMins = pPlayer->WorldAlignMins(); - - int layerCount = pPlayer->GetNumAnimOverlays(); - for( int layerIndex = 0; layerIndex < layerCount; ++layerIndex ) - { - CAnimationLayer *currentLayer = pPlayer->GetAnimOverlay(layerIndex); - if( currentLayer ) - { - record.m_layerRecords[layerIndex].m_cycle = currentLayer->m_flCycle; - record.m_layerRecords[layerIndex].m_order = currentLayer->m_nOrder; - record.m_layerRecords[layerIndex].m_sequence = currentLayer->m_nSequence; - record.m_layerRecords[layerIndex].m_weight = currentLayer->m_flWeight; - } - } - record.m_masterSequence = pPlayer->GetSequence(); - record.m_masterCycle = pPlayer->GetCycle(); - } -} - -// Called during player movement to set up/restore after lag compensation -void CLagCompensationManager::StartLagCompensation( CBasePlayer *player, CUserCmd *cmd ) -{ - // Assume no players need to be restored - m_RestorePlayer.ClearAll(); - m_bNeedToRestore = false; - - m_pCurrentPlayer = player; - - if ( !player->m_bLagCompensation // Player not wanting lag compensation - || (gpGlobals->maxClients <= 1) // no lag compensation in single player - || !sv_unlag.GetBool() // disabled by server admin - || player->IsBot() // not for bots - || player->IsObserver() // not for spectators - ) - return; - - // NOTE: Put this here so that it won't show up in single player mode. - VPROF_BUDGET( "StartLagCompensation", VPROF_BUDGETGROUP_OTHER_NETWORKING ); - Q_memset( m_RestoreData, 0, sizeof( m_RestoreData ) ); - Q_memset( m_ChangeData, 0, sizeof( m_ChangeData ) ); - - // Get true latency - - // correct is the amout of time we have to correct game time - float correct = 0.0f; - - INetChannelInfo *nci = engine->GetPlayerNetInfo( player->entindex() ); - - if ( nci ) - { - // add network latency - correct+= nci->GetLatency( FLOW_OUTGOING ); - } - - // calc number of view interpolation ticks - 1 - int lerpTicks = TIME_TO_TICKS( player->m_fLerpTime ); - - // add view interpolation latency see C_BaseEntity::GetInterpolationAmount() - correct += TICKS_TO_TIME( lerpTicks ); - - // check bouns [0,sv_maxunlag] - correct = clamp( correct, 0.0f, sv_maxunlag.GetFloat() ); - - // correct tick send by player - int targettick = cmd->tick_count - lerpTicks; - - // calc difference between tick send by player and our latency based tick - float deltaTime = correct - TICKS_TO_TIME(gpGlobals->tickcount - targettick); - - if ( fabs( deltaTime ) > 0.2f ) - { - // difference between cmd time and latency is too big > 200ms, use time correction based on latency - // DevMsg("StartLagCompensation: delta too big (%.3f)\n", deltaTime ); - targettick = gpGlobals->tickcount - TIME_TO_TICKS( correct ); - } - - // Iterate all active players - const CBitVec *pEntityTransmitBits = engine->GetEntityTransmitBitsForClient( player->entindex() - 1 ); - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - - if ( !pPlayer ) - { - continue; - } - - // Don't lag compensate yourself you loser... - if ( player == pPlayer ) - { - continue; - } - - // Custom checks for if things should lag compensate (based on things like what team the player is on). - if ( !player->WantsLagCompensationOnEntity( pPlayer, cmd, pEntityTransmitBits ) ) - continue; - - // Move other player back in time - BacktrackPlayer( pPlayer, TICKS_TO_TIME( targettick ) ); - } -} - -void CLagCompensationManager::BacktrackPlayer( CBasePlayer *pPlayer, float flTargetTime ) -{ - Vector org, mins, maxs; - QAngle ang; - - VPROF_BUDGET( "BacktrackPlayer", "CLagCompensationManager" ); - int pl_index = pPlayer->entindex() - 1; - - // get track history of this player - CUtlFixedLinkedList< LagRecord > *track = &m_PlayerTrack[ pl_index ]; - - // check if we have at leat one entry - if ( track->Count() <= 0 ) - return; - - int curr = track->Head(); - - LagRecord *prevRecord = NULL; - LagRecord *record = NULL; - - Vector prevOrg = pPlayer->GetLocalOrigin(); - - // Walk context looking for any invalidating event - while( track->IsValidIndex(curr) ) - { - // remember last record - prevRecord = record; - - // get next record - record = &track->Element( curr ); - - if ( !(record->m_fFlags & LC_ALIVE) ) - { - // player most be alive, lost track - return; - } - - Vector delta = record->m_vecOrigin - prevOrg; - if ( delta.LengthSqr() > LAG_COMPENSATION_TELEPORTED_DISTANCE_SQR ) - { - // lost track, too much difference - return; - } - - // did we find a context smaller than target time ? - if ( record->m_flSimulationTime <= flTargetTime ) - break; // hurra, stop - - prevOrg = record->m_vecOrigin; - - // go one step back - curr = track->Next( curr ); - } - - Assert( record ); - - if ( !record ) - { - if ( sv_unlag_debug.GetBool() ) - { - DevMsg( "No valid positions in history for BacktrackPlayer client ( %s )\n", pPlayer->GetPlayerName() ); - } - - return; // that should never happen - } - - float frac = 0.0f; - if ( prevRecord && - (record->m_flSimulationTime < flTargetTime) && - (record->m_flSimulationTime < prevRecord->m_flSimulationTime) ) - { - // we didn't find the exact time but have a valid previous record - // so interpolate between these two records; - - Assert( prevRecord->m_flSimulationTime > record->m_flSimulationTime ); - Assert( flTargetTime < prevRecord->m_flSimulationTime ); - - // calc fraction between both records - frac = ( flTargetTime - record->m_flSimulationTime ) / - ( prevRecord->m_flSimulationTime - record->m_flSimulationTime ); - - Assert( frac > 0 && frac < 1 ); // should never extrapolate - - ang = Lerp( frac, record->m_vecAngles, prevRecord->m_vecAngles ); - org = Lerp( frac, record->m_vecOrigin, prevRecord->m_vecOrigin ); - mins = Lerp( frac, record->m_vecMins, prevRecord->m_vecMins ); - maxs = Lerp( frac, record->m_vecMaxs, prevRecord->m_vecMaxs ); - } - else - { - // we found the exact record or no other record to interpolate with - // just copy these values since they are the best we have - ang = record->m_vecAngles; - org = record->m_vecOrigin; - mins = record->m_vecMins; - maxs = record->m_vecMaxs; - } - - // See if this is still a valid position for us to teleport to - if ( sv_unlag_fixstuck.GetBool() ) - { - // Try to move to the wanted position from our current position. - trace_t tr; - UTIL_TraceEntity( pPlayer, org, org, MASK_PLAYERSOLID, &tr ); - if ( tr.startsolid || tr.allsolid ) - { - if ( sv_unlag_debug.GetBool() ) - DevMsg( "WARNING: BackupPlayer trying to back player into a bad position - client %s\n", pPlayer->GetPlayerName() ); - - CBasePlayer *pHitPlayer = dynamic_cast( tr.m_pEnt ); - - // don't lag compensate the current player - if ( pHitPlayer && ( pHitPlayer != m_pCurrentPlayer ) ) - { - // If we haven't backtracked this player, do it now - // this deliberately ignores WantsLagCompensationOnEntity. - if ( !m_RestorePlayer.Get( pHitPlayer->entindex() - 1 ) ) - { - // prevent recursion - save a copy of m_RestorePlayer, - // pretend that this player is off-limits - int pl_index = pPlayer->entindex() - 1; - - // Temp turn this flag on - m_RestorePlayer.Set( pl_index ); - - BacktrackPlayer( pHitPlayer, flTargetTime ); - - // Remove the temp flag - m_RestorePlayer.Clear( pl_index ); - } - } - - // now trace us back as far as we can go - UTIL_TraceEntity( pPlayer, pPlayer->GetLocalOrigin(), org, MASK_PLAYERSOLID, &tr ); - - if ( tr.startsolid || tr.allsolid ) - { - // Our starting position is bogus - - if ( sv_unlag_debug.GetBool() ) - DevMsg( "Backtrack failed completely, bad starting position\n" ); - } - else - { - // We can get to a valid place, but not all the way to the target - Vector vPos; - VectorLerp( pPlayer->GetLocalOrigin(), org, tr.fraction * g_flFractionScale, vPos ); - - // This is as close as we're going to get - org = vPos; - - if ( sv_unlag_debug.GetBool() ) - DevMsg( "Backtrack got most of the way\n" ); - } - } - } - - // See if this represents a change for the player - int flags = 0; - LagRecord *restore = &m_RestoreData[ pl_index ]; - LagRecord *change = &m_ChangeData[ pl_index ]; - - QAngle angdiff = pPlayer->GetLocalAngles() - ang; - Vector orgdiff = pPlayer->GetLocalOrigin() - org; - - // Always remember the pristine simulation time in case we need to restore it. - restore->m_flSimulationTime = pPlayer->GetSimulationTime(); - - if ( angdiff.LengthSqr() > LAG_COMPENSATION_EPS_SQR ) - { - flags |= LC_ANGLES_CHANGED; - restore->m_vecAngles = pPlayer->GetLocalAngles(); - pPlayer->SetLocalAngles( ang ); - change->m_vecAngles = ang; - } - - // Use absolute equality here - if ( ( mins != pPlayer->WorldAlignMins() ) || - ( maxs != pPlayer->WorldAlignMaxs() ) ) - { - flags |= LC_SIZE_CHANGED; - restore->m_vecMins = pPlayer->WorldAlignMins() ; - restore->m_vecMaxs = pPlayer->WorldAlignMaxs(); - pPlayer->SetSize( mins, maxs ); - change->m_vecMins = mins; - change->m_vecMaxs = maxs; - } - - // Note, do origin at end since it causes a relink into the k/d tree - if ( orgdiff.LengthSqr() > LAG_COMPENSATION_EPS_SQR ) - { - flags |= LC_ORIGIN_CHANGED; - restore->m_vecOrigin = pPlayer->GetLocalOrigin(); - pPlayer->SetLocalOrigin( org ); - change->m_vecOrigin = org; - } - - // Sorry for the loss of the optimization for the case of people - // standing still, but you breathe even on the server. - // This is quicker than actually comparing all bazillion floats. - flags |= LC_ANIMATION_CHANGED; - restore->m_masterSequence = pPlayer->GetSequence(); - restore->m_masterCycle = pPlayer->GetCycle(); - - bool interpolationAllowed = false; - if( prevRecord && (record->m_masterSequence == prevRecord->m_masterSequence) ) - { - // If the master state changes, all layers will be invalid too, so don't interp (ya know, interp barely ever happens anyway) - interpolationAllowed = true; - } - - //////////////////////// - // First do the master settings - bool interpolatedMasters = false; - if( frac > 0.0f && interpolationAllowed ) - { - interpolatedMasters = true; - pPlayer->SetSequence( Lerp( frac, record->m_masterSequence, prevRecord->m_masterSequence ) ); - pPlayer->SetCycle( Lerp( frac, record->m_masterCycle, prevRecord->m_masterCycle ) ); - - if( record->m_masterCycle > prevRecord->m_masterCycle ) - { - // the older record is higher in frame than the newer, it must have wrapped around from 1 back to 0 - // add one to the newer so it is lerping from .9 to 1.1 instead of .9 to .1, for example. - float newCycle = Lerp( frac, record->m_masterCycle, prevRecord->m_masterCycle + 1 ); - pPlayer->SetCycle(newCycle < 1 ? newCycle : newCycle - 1 );// and make sure .9 to 1.2 does not end up 1.05 - } - else - { - pPlayer->SetCycle( Lerp( frac, record->m_masterCycle, prevRecord->m_masterCycle ) ); - } - } - if( !interpolatedMasters ) - { - pPlayer->SetSequence(record->m_masterSequence); - pPlayer->SetCycle(record->m_masterCycle); - } - - //////////////////////// - // Now do all the layers - int layerCount = pPlayer->GetNumAnimOverlays(); - for( int layerIndex = 0; layerIndex < layerCount; ++layerIndex ) - { - CAnimationLayer *currentLayer = pPlayer->GetAnimOverlay(layerIndex); - if( currentLayer ) - { - restore->m_layerRecords[layerIndex].m_cycle = currentLayer->m_flCycle; - restore->m_layerRecords[layerIndex].m_order = currentLayer->m_nOrder; - restore->m_layerRecords[layerIndex].m_sequence = currentLayer->m_nSequence; - restore->m_layerRecords[layerIndex].m_weight = currentLayer->m_flWeight; - - bool interpolated = false; - if( (frac > 0.0f) && interpolationAllowed ) - { - LayerRecord &recordsLayerRecord = record->m_layerRecords[layerIndex]; - LayerRecord &prevRecordsLayerRecord = prevRecord->m_layerRecords[layerIndex]; - if( (recordsLayerRecord.m_order == prevRecordsLayerRecord.m_order) - && (recordsLayerRecord.m_sequence == prevRecordsLayerRecord.m_sequence) - ) - { - // We can't interpolate across a sequence or order change - interpolated = true; - if( recordsLayerRecord.m_cycle > prevRecordsLayerRecord.m_cycle ) - { - // the older record is higher in frame than the newer, it must have wrapped around from 1 back to 0 - // add one to the newer so it is lerping from .9 to 1.1 instead of .9 to .1, for example. - float newCycle = Lerp( frac, recordsLayerRecord.m_cycle, prevRecordsLayerRecord.m_cycle + 1 ); - currentLayer->m_flCycle = newCycle < 1 ? newCycle : newCycle - 1;// and make sure .9 to 1.2 does not end up 1.05 - } - else - { - currentLayer->m_flCycle = Lerp( frac, recordsLayerRecord.m_cycle, prevRecordsLayerRecord.m_cycle ); - } - currentLayer->m_nOrder = recordsLayerRecord.m_order; - currentLayer->m_nSequence = recordsLayerRecord.m_sequence; - currentLayer->m_flWeight = Lerp( frac, recordsLayerRecord.m_weight, prevRecordsLayerRecord.m_weight ); - } - } - if( !interpolated ) - { - //Either no interp, or interp failed. Just use record. - currentLayer->m_flCycle = record->m_layerRecords[layerIndex].m_cycle; - currentLayer->m_nOrder = record->m_layerRecords[layerIndex].m_order; - currentLayer->m_nSequence = record->m_layerRecords[layerIndex].m_sequence; - currentLayer->m_flWeight = record->m_layerRecords[layerIndex].m_weight; - } - } - } - - if ( !flags ) - return; // we didn't change anything - - if ( sv_lagflushbonecache.GetBool() ) - pPlayer->InvalidateBoneCache(); - - /*char text[256]; Q_snprintf( text, sizeof(text), "time %.2f", flTargetTime ); - pPlayer->DrawServerHitboxes( 10 ); - NDebugOverlay::Text( org, text, false, 10 ); - NDebugOverlay::EntityBounds( pPlayer, 255, 0, 0, 32, 10 ); */ - - m_RestorePlayer.Set( pl_index ); //remember that we changed this player - m_bNeedToRestore = true; // we changed at least one player - restore->m_fFlags = flags; // we need to restore these flags - change->m_fFlags = flags; // we have changed these flags - - if( sv_showlagcompensation.GetInt() == 1 ) - { - pPlayer->DrawServerHitboxes(4, true); - } -} - - -void CLagCompensationManager::FinishLagCompensation( CBasePlayer *player ) -{ - VPROF_BUDGET_FLAGS( "FinishLagCompensation", VPROF_BUDGETGROUP_OTHER_NETWORKING, BUDGETFLAG_CLIENT|BUDGETFLAG_SERVER ); - if ( !m_bNeedToRestore ) - return; // no player was changed at all - - // Iterate all active players - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - int pl_index = i - 1; - - if ( !m_RestorePlayer.Get( pl_index ) ) - { - // player wasn't changed by lag compensation - continue; - } - - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - if ( !pPlayer ) - { - continue; - } - - LagRecord *restore = &m_RestoreData[ pl_index ]; - LagRecord *change = &m_ChangeData[ pl_index ]; - - bool restoreSimulationTime = false; - - if ( restore->m_fFlags & LC_SIZE_CHANGED ) - { - restoreSimulationTime = true; - - // see if simulation made any changes, if no, then do the restore, otherwise, - // leave new values in - if ( pPlayer->WorldAlignMins() == change->m_vecMins && - pPlayer->WorldAlignMaxs() == change->m_vecMaxs ) - { - // Restore it - pPlayer->SetSize( restore->m_vecMins, restore->m_vecMaxs ); - } - } - - if ( restore->m_fFlags & LC_ANGLES_CHANGED ) - { - restoreSimulationTime = true; - - if ( pPlayer->GetLocalAngles() == change->m_vecAngles ) - { - pPlayer->SetLocalAngles( restore->m_vecAngles ); - } - } - - if ( restore->m_fFlags & LC_ORIGIN_CHANGED ) - { - restoreSimulationTime = true; - - // Okay, let's see if we can do something reasonable with the change - Vector delta = pPlayer->GetLocalOrigin() - change->m_vecOrigin; - - // If it moved really far, just leave the player in the new spot!!! - if ( delta.LengthSqr() < LAG_COMPENSATION_TELEPORTED_DISTANCE_SQR ) - { - RestorePlayerTo( pPlayer, restore->m_vecOrigin + delta ); - } - } - - if( restore->m_fFlags & LC_ANIMATION_CHANGED ) - { - restoreSimulationTime = true; - - pPlayer->SetSequence(restore->m_masterSequence); - pPlayer->SetCycle(restore->m_masterCycle); - - int layerCount = pPlayer->GetNumAnimOverlays(); - for( int layerIndex = 0; layerIndex < layerCount; ++layerIndex ) - { - CAnimationLayer *currentLayer = pPlayer->GetAnimOverlay(layerIndex); - if( currentLayer ) - { - currentLayer->m_flCycle = restore->m_layerRecords[layerIndex].m_cycle; - currentLayer->m_nOrder = restore->m_layerRecords[layerIndex].m_order; - currentLayer->m_nSequence = restore->m_layerRecords[layerIndex].m_sequence; - currentLayer->m_flWeight = restore->m_layerRecords[layerIndex].m_weight; - } - } - } - - if ( restoreSimulationTime ) - { - pPlayer->SetSimulationTime( restore->m_flSimulationTime ); - } - } -} - - diff --git a/game/server/player_pickup.cpp b/game/server/player_pickup.cpp deleted file mode 100644 index 76ffd8820..000000000 --- a/game/server/player_pickup.cpp +++ /dev/null @@ -1,175 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "player_pickup.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// player pickup utility routine -void Pickup_ForcePlayerToDropThisObject( CBaseEntity *pTarget ) -{ - if ( pTarget == NULL ) - return; - - IPhysicsObject *pPhysics = pTarget->VPhysicsGetObject(); - - if ( pPhysics == NULL ) - return; - - if ( pPhysics->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - { - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - pPlayer->ForceDropOfCarriedPhysObjects( pTarget ); - } -} - - -void Pickup_OnPhysGunDrop( CBaseEntity *pDroppedObject, CBasePlayer *pPlayer, PhysGunDrop_t Reason ) -{ - IPlayerPickupVPhysics *pPickup = dynamic_cast(pDroppedObject); - if ( pPickup ) - { - pPickup->OnPhysGunDrop( pPlayer, Reason ); - } -} - - -void Pickup_OnPhysGunPickup( CBaseEntity *pPickedUpObject, CBasePlayer *pPlayer, PhysGunPickup_t reason ) -{ - IPlayerPickupVPhysics *pPickup = dynamic_cast(pPickedUpObject); - if ( pPickup ) - { - pPickup->OnPhysGunPickup( pPlayer, reason ); - } - - // send phys gun pickup item event, but only in single player - if ( !g_pGameRules->IsMultiplayer() ) - { - IGameEvent *event = gameeventmanager->CreateEvent( "physgun_pickup" ); - if ( event ) - { - event->SetInt( "entindex", pPickedUpObject->entindex() ); - gameeventmanager->FireEvent( event ); - } - } -} - -bool Pickup_OnAttemptPhysGunPickup( CBaseEntity *pPickedUpObject, CBasePlayer *pPlayer, PhysGunPickup_t reason ) -{ - IPlayerPickupVPhysics *pPickup = dynamic_cast(pPickedUpObject); - if ( pPickup ) - { - return pPickup->OnAttemptPhysGunPickup( pPlayer, reason ); - } - return true; -} - -CBaseEntity *Pickup_OnFailedPhysGunPickup( CBaseEntity *pPickedUpObject, Vector vPhysgunPos ) -{ - IPlayerPickupVPhysics *pPickup = dynamic_cast(pPickedUpObject); - if ( pPickup ) - { - return pPickup->OnFailedPhysGunPickup( vPhysgunPos ); - } - - return NULL; -} - -bool Pickup_GetPreferredCarryAngles( CBaseEntity *pObject, CBasePlayer *pPlayer, matrix3x4_t &localToWorld, QAngle &outputAnglesWorldSpace ) -{ - IPlayerPickupVPhysics *pPickup = dynamic_cast(pObject); - if ( pPickup ) - { - if ( pPickup->HasPreferredCarryAnglesForPlayer( pPlayer ) ) - { - outputAnglesWorldSpace = TransformAnglesToWorldSpace( pPickup->PreferredCarryAngles(), localToWorld ); - return true; - } - } - return false; -} - -bool Pickup_ForcePhysGunOpen( CBaseEntity *pObject, CBasePlayer *pPlayer ) -{ - IPlayerPickupVPhysics *pPickup = dynamic_cast(pObject); - if ( pPickup ) - { - return pPickup->ForcePhysgunOpen( pPlayer ); - } - return false; -} - -AngularImpulse Pickup_PhysGunLaunchAngularImpulse( CBaseEntity *pObject, PhysGunForce_t reason ) -{ - IPlayerPickupVPhysics *pPickup = dynamic_cast(pObject); - if ( pPickup != NULL && pPickup->ShouldPuntUseLaunchForces( reason ) ) - { - return pPickup->PhysGunLaunchAngularImpulse(); - } - return RandomAngularImpulse( -600, 600 ); -} - -Vector Pickup_DefaultPhysGunLaunchVelocity( const Vector &vecForward, float flMass ) -{ -#ifdef HL2_DLL - // Calculate the velocity based on physcannon rules - float flForceMax = physcannon_maxforce.GetFloat(); - float flForce = flForceMax; - - float mass = flMass; - if ( mass > 100 ) - { - mass = MIN( mass, 1000 ); - float flForceMin = physcannon_minforce.GetFloat(); - flForce = SimpleSplineRemapValClamped( mass, 100, 600, flForceMax, flForceMin ); - } - - return ( vecForward * flForce ); -#endif - - // Do the simple calculation - return ( vecForward * flMass ); -} - -Vector Pickup_PhysGunLaunchVelocity( CBaseEntity *pObject, const Vector &vecForward, PhysGunForce_t reason ) -{ - // The object must be valid - if ( pObject == NULL ) - { - Assert( 0 ); - return vec3_origin; - } - - // Shouldn't ever get here with a non-vphysics object. - IPhysicsObject *pPhysicsObject = pObject->VPhysicsGetObject(); - if ( pPhysicsObject == NULL ) - { - Assert( 0 ); - return vec3_origin; - } - - // Call the pickup entity's callback - IPlayerPickupVPhysics *pPickup = dynamic_cast(pObject); - if ( pPickup != NULL && pPickup->ShouldPuntUseLaunchForces( reason ) ) - return pPickup->PhysGunLaunchVelocity( vecForward, pPhysicsObject->GetMass() ); - - // Do our default behavior - return Pickup_DefaultPhysGunLaunchVelocity( vecForward, pPhysicsObject->GetMass() ); -} - -bool Pickup_ShouldPuntUseLaunchForces( CBaseEntity *pObject, PhysGunForce_t reason ) -{ - IPlayerPickupVPhysics *pPickup = dynamic_cast(pObject); - if ( pPickup ) - { - return pPickup->ShouldPuntUseLaunchForces( reason ); - } - return false; -} - diff --git a/game/server/player_pickup.h b/game/server/player_pickup.h deleted file mode 100644 index 6da09adba..000000000 --- a/game/server/player_pickup.h +++ /dev/null @@ -1,93 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: APIs for player pickup of physics objects -// -//=============================================================================// - -#ifndef PLAYER_PICKUP_H -#define PLAYER_PICKUP_H -#ifdef _WIN32 -#pragma once -#endif - -#ifdef HL2_DLL -// Needed for launch velocity -extern ConVar physcannon_minforce; -extern ConVar physcannon_maxforce; -#endif - -// Reasons behind a pickup -enum PhysGunPickup_t -{ - PICKED_UP_BY_CANNON, - PUNTED_BY_CANNON, - PICKED_UP_BY_PLAYER, // Picked up by +USE, not physgun. -}; - -// Reasons behind a drop -enum PhysGunDrop_t -{ - DROPPED_BY_PLAYER, - THROWN_BY_PLAYER, - DROPPED_BY_CANNON, - LAUNCHED_BY_CANNON, -}; - -enum PhysGunForce_t -{ - PHYSGUN_FORCE_DROPPED, // Dropped by +USE - PHYSGUN_FORCE_THROWN, // Thrown from +USE - PHYSGUN_FORCE_PUNTED, // Punted by cannon - PHYSGUN_FORCE_LAUNCHED, // Launched by cannon -}; - -void PlayerPickupObject( CBasePlayer *pPlayer, CBaseEntity *pObject ); -void Pickup_ForcePlayerToDropThisObject( CBaseEntity *pTarget ); - -void Pickup_OnPhysGunDrop( CBaseEntity *pDroppedObject, CBasePlayer *pPlayer, PhysGunDrop_t reason ); -void Pickup_OnPhysGunPickup( CBaseEntity *pPickedUpObject, CBasePlayer *pPlayer, PhysGunPickup_t reason = PICKED_UP_BY_CANNON ); -bool Pickup_OnAttemptPhysGunPickup( CBaseEntity *pPickedUpObject, CBasePlayer *pPlayer, PhysGunPickup_t reason = PICKED_UP_BY_CANNON ); -bool Pickup_GetPreferredCarryAngles( CBaseEntity *pObject, CBasePlayer *pPlayer, matrix3x4_t &localToWorld, QAngle &outputAnglesWorldSpace ); -bool Pickup_ForcePhysGunOpen( CBaseEntity *pObject, CBasePlayer *pPlayer ); -bool Pickup_ShouldPuntUseLaunchForces( CBaseEntity *pObject, PhysGunForce_t reason ); -AngularImpulse Pickup_PhysGunLaunchAngularImpulse( CBaseEntity *pObject, PhysGunForce_t reason ); -Vector Pickup_DefaultPhysGunLaunchVelocity( const Vector &vecForward, float flMass ); -Vector Pickup_PhysGunLaunchVelocity( CBaseEntity *pObject, const Vector &vecForward, PhysGunForce_t reason ); - -CBaseEntity *Pickup_OnFailedPhysGunPickup( CBaseEntity *pPickedUpObject, Vector vPhysgunPos ); - -abstract_class IPlayerPickupVPhysics -{ -public: - // Callbacks for the physgun/cannon picking up an entity - virtual bool OnAttemptPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason = PICKED_UP_BY_CANNON ) = 0; - virtual CBaseEntity *OnFailedPhysGunPickup( Vector vPhysgunPos ) = 0; - virtual void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason = PICKED_UP_BY_CANNON ) = 0; - virtual void OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ) = 0; - virtual bool HasPreferredCarryAnglesForPlayer( CBasePlayer *pPlayer = NULL ) = 0; - virtual QAngle PreferredCarryAngles( void ) = 0; - virtual bool ForcePhysgunOpen( CBasePlayer *pPlayer ) = 0; - virtual AngularImpulse PhysGunLaunchAngularImpulse() = 0; - virtual bool ShouldPuntUseLaunchForces( PhysGunForce_t reason ) = 0; - virtual Vector PhysGunLaunchVelocity( const Vector &vecForward, float flMass ) = 0; -}; - -class CDefaultPlayerPickupVPhysics : public IPlayerPickupVPhysics -{ -public: - virtual bool OnAttemptPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason = PICKED_UP_BY_CANNON ) { return true; } - virtual CBaseEntity *OnFailedPhysGunPickup( Vector vPhysgunPos ) { return NULL; } - virtual void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason = PICKED_UP_BY_CANNON ) {} - virtual void OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t reason ) {} - virtual bool HasPreferredCarryAnglesForPlayer( CBasePlayer *pPlayer ) { return false; } - virtual QAngle PreferredCarryAngles( void ) { return vec3_angle; } - virtual bool ForcePhysgunOpen( CBasePlayer *pPlayer ) { return false; } - virtual AngularImpulse PhysGunLaunchAngularImpulse() { return RandomAngularImpulse( -600, 600 ); } - virtual bool ShouldPuntUseLaunchForces( PhysGunForce_t reason ) { return false; } - virtual Vector PhysGunLaunchVelocity( const Vector &vecForward, float flMass ) - { - return Pickup_DefaultPhysGunLaunchVelocity( vecForward, flMass ); - } -}; - -#endif // PLAYER_PICKUP_H diff --git a/game/server/player_resource.cpp b/game/server/player_resource.cpp deleted file mode 100644 index 28b996b66..000000000 --- a/game/server/player_resource.cpp +++ /dev/null @@ -1,130 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Entity that propagates general data needed by clients for every player. -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "player.h" -#include "player_resource.h" -#include - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// Datatable -IMPLEMENT_SERVERCLASS_ST_NOBASE(CPlayerResource, DT_PlayerResource) -// SendPropArray( SendPropString( SENDINFO(m_szName[0]) ), SENDARRAYINFO(m_szName) ), - SendPropArray3( SENDINFO_ARRAY3(m_iPing), SendPropInt( SENDINFO_ARRAY(m_iPing), 10, SPROP_UNSIGNED ) ), -// SendPropArray( SendPropInt( SENDINFO_ARRAY(m_iPacketloss), 7, SPROP_UNSIGNED ), m_iPacketloss ), - SendPropArray3( SENDINFO_ARRAY3(m_iScore), SendPropInt( SENDINFO_ARRAY(m_iScore), 12 ) ), - SendPropArray3( SENDINFO_ARRAY3(m_iDeaths), SendPropInt( SENDINFO_ARRAY(m_iDeaths), 12 ) ), - SendPropArray3( SENDINFO_ARRAY3(m_bConnected), SendPropInt( SENDINFO_ARRAY(m_bConnected), 1, SPROP_UNSIGNED ) ), - SendPropArray3( SENDINFO_ARRAY3(m_iTeam), SendPropInt( SENDINFO_ARRAY(m_iTeam), 4 ) ), - SendPropArray3( SENDINFO_ARRAY3(m_bAlive), SendPropInt( SENDINFO_ARRAY(m_bAlive), 1, SPROP_UNSIGNED ) ), - SendPropArray3( SENDINFO_ARRAY3(m_iHealth), SendPropInt( SENDINFO_ARRAY(m_iHealth), 10, SPROP_UNSIGNED ) ), -END_SEND_TABLE() - -BEGIN_DATADESC( CPlayerResource ) - - // DEFINE_ARRAY( m_iPing, FIELD_INTEGER, MAX_PLAYERS+1 ), - // DEFINE_ARRAY( m_iPacketloss, FIELD_INTEGER, MAX_PLAYERS+1 ), - // DEFINE_ARRAY( m_iScore, FIELD_INTEGER, MAX_PLAYERS+1 ), - // DEFINE_ARRAY( m_iDeaths, FIELD_INTEGER, MAX_PLAYERS+1 ), - // DEFINE_ARRAY( m_bConnected, FIELD_INTEGER, MAX_PLAYERS+1 ), - // DEFINE_FIELD( m_flNextPingUpdate, FIELD_FLOAT ), - // DEFINE_ARRAY( m_iTeam, FIELD_INTEGER, MAX_PLAYERS+1 ), - // DEFINE_ARRAY( m_bAlive, FIELD_INTEGER, MAX_PLAYERS+1 ), - // DEFINE_ARRAY( m_iHealth, FIELD_INTEGER, MAX_PLAYERS+1 ), - // DEFINE_FIELD( m_nUpdateCounter, FIELD_INTEGER ), - - // Function Pointers - DEFINE_FUNCTION( ResourceThink ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( player_manager, CPlayerResource ); - -CPlayerResource *g_pPlayerResource; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPlayerResource::Spawn( void ) -{ - for ( int i=0; i < MAX_PLAYERS+1; i++ ) - { - m_iPing.Set( i, 0 ); - m_iScore.Set( i, 0 ); - m_iDeaths.Set( i, 0 ); - m_bConnected.Set( i, 0 ); - m_iTeam.Set( i, 0 ); - m_bAlive.Set( i, 0 ); - } - - SetThink( &CPlayerResource::ResourceThink ); - SetNextThink( gpGlobals->curtime ); - m_nUpdateCounter = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: The Player resource is always transmitted to clients -//----------------------------------------------------------------------------- -int CPlayerResource::UpdateTransmitState() -{ - // ALWAYS transmit to all clients. - return SetTransmitState( FL_EDICT_ALWAYS ); -} - -//----------------------------------------------------------------------------- -// Purpose: Wrapper for the virtual GrabPlayerData Think function -//----------------------------------------------------------------------------- -void CPlayerResource::ResourceThink( void ) -{ - m_nUpdateCounter++; - - UpdatePlayerData(); - - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPlayerResource::UpdatePlayerData( void ) -{ - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = (CBasePlayer*)UTIL_PlayerByIndex( i ); - - if ( pPlayer && pPlayer->IsConnected() ) - { - m_iScore.Set( i, pPlayer->FragCount() ); - m_iDeaths.Set( i, pPlayer->DeathCount() ); - m_bConnected.Set( i, 1 ); - m_iTeam.Set( i, pPlayer->GetTeamNumber() ); - m_bAlive.Set( i, pPlayer->IsAlive()?1:0 ); - m_iHealth.Set(i, MAX( 0, pPlayer->GetHealth() ) ); - - // Don't update ping / packetloss everytime - - if ( !(m_nUpdateCounter%20) ) - { - // update ping all 20 think ticks = (20*0.1=2seconds) - int ping, packetloss; - UTIL_GetPlayerConnectionInfo( i, ping, packetloss ); - - // calc avg for scoreboard so it's not so jittery - ping = (int)(0.8f * m_iPing.Get(i) + 0.2f * ping); - - - m_iPing.Set( i, ping ); - // m_iPacketloss.Set( i, packetloss ); - } - } - else - { - m_bConnected.Set( i, 0 ); - } - } -} diff --git a/game/server/player_resource.h b/game/server/player_resource.h deleted file mode 100644 index 1f2a210b7..000000000 --- a/game/server/player_resource.h +++ /dev/null @@ -1,45 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Entity that propagates general data needed by clients for every player. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PLAYER_RESOURCE_H -#define PLAYER_RESOURCE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "shareddefs.h" - -class CPlayerResource : public CBaseEntity -{ - DECLARE_CLASS( CPlayerResource, CBaseEntity ); -public: - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - virtual void Spawn( void ); - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() | FCAP_DONT_SAVE; } - virtual void ResourceThink( void ); - virtual void UpdatePlayerData( void ); - virtual int UpdateTransmitState(void); - -protected: - // Data for each player that's propagated to all clients - // Stored in individual arrays so they can be sent down via datatables - CNetworkArray( int, m_iPing, MAX_PLAYERS+1 ); - CNetworkArray( int, m_iScore, MAX_PLAYERS+1 ); - CNetworkArray( int, m_iDeaths, MAX_PLAYERS+1 ); - CNetworkArray( int, m_bConnected, MAX_PLAYERS+1 ); - CNetworkArray( int, m_iTeam, MAX_PLAYERS+1 ); - CNetworkArray( int, m_bAlive, MAX_PLAYERS+1 ); - CNetworkArray( int, m_iHealth, MAX_PLAYERS+1 ); - - int m_nUpdateCounter; -}; - -extern CPlayerResource *g_pPlayerResource; - -#endif // PLAYER_RESOURCE_H diff --git a/game/server/playerinfomanager.cpp b/game/server/playerinfomanager.cpp deleted file mode 100644 index f198914e9..000000000 --- a/game/server/playerinfomanager.cpp +++ /dev/null @@ -1,134 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: implementation of player info manager -// -//=============================================================================// - -#include "cbase.h" -#include "player.h" -#include "playerinfomanager.h" -#include "edict.h" - -extern CGlobalVars *gpGlobals; -static CPlayerInfoManager s_PlayerInfoManager; -static CPluginBotManager s_BotManager; - -namespace -{ - - // - // Old version support - // - abstract_class IPlayerInfo_V1 - { - public: - // returns the players name (UTF-8 encoded) - virtual const char *GetName() = 0; - // returns the userid (slot number) - virtual int GetUserID() = 0; - // returns the string of their network (i.e Steam) ID - virtual const char *GetNetworkIDString() = 0; - // returns the team the player is on - virtual int GetTeamIndex() = 0; - // changes the player to a new team (if the game dll logic allows it) - virtual void ChangeTeam( int iTeamNum ) = 0; - // returns the number of kills this player has (exact meaning is mod dependent) - virtual int GetFragCount() = 0; - // returns the number of deaths this player has (exact meaning is mod dependent) - virtual int GetDeathCount() = 0; - // returns if this player slot is actually valid - virtual bool IsConnected() = 0; - // returns the armor/health of the player (exact meaning is mod dependent) - virtual int GetArmorValue() = 0; - }; - - abstract_class IPlayerInfoManager_V1 - { - public: - virtual IPlayerInfo_V1 *GetPlayerInfo( edict_t *pEdict ) = 0; - }; - - - class CPlayerInfoManager_V1: public IPlayerInfoManager_V1 - { - public: - virtual IPlayerInfo_V1 *GetPlayerInfo( edict_t *pEdict ); - }; - - static CPlayerInfoManager_V1 s_PlayerInfoManager_V1; - - - IPlayerInfo_V1 *CPlayerInfoManager_V1::GetPlayerInfo( edict_t *pEdict ) - { - CBasePlayer *pPlayer = ( ( CBasePlayer * )CBaseEntity::Instance( pEdict )); - if ( pPlayer ) - { - return (IPlayerInfo_V1 *)pPlayer->GetPlayerInfo(); - } - else - { - return NULL; - } - } - - EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CPlayerInfoManager_V1, IPlayerInfoManager_V1, "PlayerInfoManager001", s_PlayerInfoManager_V1); -} - -IPlayerInfo *CPlayerInfoManager::GetPlayerInfo( edict_t *pEdict ) -{ - CBasePlayer *pPlayer = ( ( CBasePlayer * )CBaseEntity::Instance( pEdict )); - if ( pPlayer ) - { - return pPlayer->GetPlayerInfo(); - } - else - { - return NULL; - } -} - -CGlobalVars *CPlayerInfoManager::GetGlobalVars() -{ - return gpGlobals; -} - - - -IBotController *CPluginBotManager::GetBotController( edict_t *pEdict ) -{ - CBasePlayer *pPlayer = ( ( CBasePlayer * )CBaseEntity::Instance( pEdict )); - if ( pPlayer && pPlayer->IsBot() ) - { - return pPlayer->GetBotController(); - } - else - { - return NULL; - } -} - -edict_t *CPluginBotManager::CreateBot( const char *botname ) -{ - edict_t *pEdict = engine->CreateFakeClient( botname ); - if (!pEdict) - { - Msg( "Failed to create Bot.\n"); - return NULL; - } - - // Allocate a player entity for the bot, and call spawn - CBasePlayer *pPlayer = ((CBasePlayer*)CBaseEntity::Instance( pEdict )); - - pPlayer->ClearFlags(); - pPlayer->AddFlag( FL_CLIENT | FL_FAKECLIENT ); - - pPlayer->ChangeTeam( TEAM_UNASSIGNED ); - pPlayer->RemoveAllItems( true ); - pPlayer->Spawn(); - - return pEdict; -} - -EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CPlayerInfoManager, IPlayerInfoManager, INTERFACEVERSION_PLAYERINFOMANAGER, s_PlayerInfoManager); -EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CPluginBotManager, IBotManager, INTERFACEVERSION_PLAYERBOTMANAGER, s_BotManager); - diff --git a/game/server/playerinfomanager.h b/game/server/playerinfomanager.h deleted file mode 100644 index 2d69aeefa..000000000 --- a/game/server/playerinfomanager.h +++ /dev/null @@ -1,32 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: implementation of player info manager -// -//=============================================================================// -#ifndef PLAYERINFOMANAGER_H -#define PLAYERINFOMANAGER_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "game/server/iplayerinfo.h" - -//----------------------------------------------------------------------------- -// Purpose: interface for plugins to get player info -//----------------------------------------------------------------------------- -class CPlayerInfoManager: public IPlayerInfoManager -{ -public: - virtual IPlayerInfo *GetPlayerInfo( edict_t *pEdict ); - virtual CGlobalVars *GetGlobalVars(); -}; - -class CPluginBotManager: public IBotManager -{ -public: - virtual IBotController *GetBotController( edict_t *pEdict ); - virtual edict_t *CreateBot( const char *botname ); -}; - -#endif diff --git a/game/server/playerlocaldata.cpp b/game/server/playerlocaldata.cpp deleted file mode 100644 index 0378cf1c9..000000000 --- a/game/server/playerlocaldata.cpp +++ /dev/null @@ -1,256 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "playerlocaldata.h" -#include "player.h" -#include "mathlib/mathlib.h" -#include "entitylist.h" -#include "SkyCamera.h" -#include "playernet_vars.h" -#include "fogcontroller.h" -#include "tier0/vprof.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//============================================================================= - -BEGIN_SEND_TABLE_NOBASE( CPlayerLocalData, DT_Local ) - - SendPropArray3 (SENDINFO_ARRAY3(m_chAreaBits), SendPropInt(SENDINFO_ARRAY(m_chAreaBits), 8, SPROP_UNSIGNED)), - SendPropArray3 (SENDINFO_ARRAY3(m_chAreaPortalBits), SendPropInt(SENDINFO_ARRAY(m_chAreaPortalBits), 8, SPROP_UNSIGNED)), - - SendPropInt (SENDINFO(m_iHideHUD), HIDEHUD_BITCOUNT, SPROP_UNSIGNED), - SendPropFloat (SENDINFO(m_flFOVRate), 0, SPROP_NOSCALE ), - SendPropInt (SENDINFO(m_bDucked), 1, SPROP_UNSIGNED ), - SendPropInt (SENDINFO(m_bDucking), 1, SPROP_UNSIGNED ), - SendPropInt (SENDINFO(m_bInDuckJump), 1, SPROP_UNSIGNED ), - SendPropFloat (SENDINFO(m_flDucktime), 12, SPROP_ROUNDDOWN|SPROP_CHANGES_OFTEN, 0.0f, 2048.0f ), - SendPropFloat (SENDINFO(m_flDuckJumpTime), 12, SPROP_ROUNDDOWN, 0.0f, 2048.0f ), - SendPropFloat (SENDINFO(m_flJumpTime), 12, SPROP_ROUNDDOWN, 0.0f, 2048.0f ), -#if PREDICTION_ERROR_CHECK_LEVEL > 1 - SendPropFloat (SENDINFO(m_flFallVelocity), 32, SPROP_NOSCALE ), - - SendPropFloat ( SENDINFO_VECTORELEM(m_vecPunchAngle, 0), 32, SPROP_NOSCALE|SPROP_CHANGES_OFTEN ), - SendPropFloat ( SENDINFO_VECTORELEM(m_vecPunchAngle, 1), 32, SPROP_NOSCALE|SPROP_CHANGES_OFTEN ), - SendPropFloat ( SENDINFO_VECTORELEM(m_vecPunchAngle, 2), 32, SPROP_NOSCALE|SPROP_CHANGES_OFTEN ), - - SendPropFloat ( SENDINFO_VECTORELEM(m_vecPunchAngleVel, 0), 32, SPROP_NOSCALE|SPROP_CHANGES_OFTEN ), - SendPropFloat ( SENDINFO_VECTORELEM(m_vecPunchAngleVel, 1), 32, SPROP_NOSCALE|SPROP_CHANGES_OFTEN ), - SendPropFloat ( SENDINFO_VECTORELEM(m_vecPunchAngleVel, 2), 32, SPROP_NOSCALE|SPROP_CHANGES_OFTEN ), - -#else - SendPropFloat (SENDINFO(m_flFallVelocity), 17, SPROP_CHANGES_OFTEN, -4096.0f, 4096.0f ), - SendPropVector (SENDINFO(m_vecPunchAngle), -1, SPROP_COORD|SPROP_CHANGES_OFTEN), - SendPropVector (SENDINFO(m_vecPunchAngleVel), -1, SPROP_COORD), -#endif - SendPropInt (SENDINFO(m_bDrawViewmodel), 1, SPROP_UNSIGNED ), - SendPropInt (SENDINFO(m_bWearingSuit), 1, SPROP_UNSIGNED ), - SendPropBool (SENDINFO(m_bPoisoned)), - - SendPropFloat (SENDINFO(m_flStepSize), 16, SPROP_ROUNDUP, 0.0f, 128.0f ), - SendPropInt (SENDINFO(m_bAllowAutoMovement),1, SPROP_UNSIGNED ), - - // 3d skybox data - SendPropInt(SENDINFO_STRUCTELEM(m_skybox3d.scale), 12), - SendPropVector (SENDINFO_STRUCTELEM(m_skybox3d.origin), -1, SPROP_COORD), - SendPropInt (SENDINFO_STRUCTELEM(m_skybox3d.area), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO_STRUCTELEM( m_skybox3d.fog.enable ), 1, SPROP_UNSIGNED ), - SendPropInt( SENDINFO_STRUCTELEM( m_skybox3d.fog.blend ), 1, SPROP_UNSIGNED ), - SendPropVector( SENDINFO_STRUCTELEM(m_skybox3d.fog.dirPrimary), -1, SPROP_COORD), - SendPropInt( SENDINFO_STRUCTELEM( m_skybox3d.fog.colorPrimary ), 32, SPROP_UNSIGNED ), - SendPropInt( SENDINFO_STRUCTELEM( m_skybox3d.fog.colorSecondary ), 32, SPROP_UNSIGNED ), - SendPropFloat( SENDINFO_STRUCTELEM( m_skybox3d.fog.start ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO_STRUCTELEM( m_skybox3d.fog.end ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO_STRUCTELEM( m_skybox3d.fog.maxdensity ), 0, SPROP_NOSCALE ), - - SendPropEHandle( SENDINFO_STRUCTELEM( m_PlayerFog.m_hCtrl ) ), - - // audio data - SendPropVector( SENDINFO_STRUCTARRAYELEM( m_audio.localSound, 0 ), -1, SPROP_COORD), - SendPropVector( SENDINFO_STRUCTARRAYELEM( m_audio.localSound, 1 ), -1, SPROP_COORD), - SendPropVector( SENDINFO_STRUCTARRAYELEM( m_audio.localSound, 2 ), -1, SPROP_COORD), - SendPropVector( SENDINFO_STRUCTARRAYELEM( m_audio.localSound, 3 ), -1, SPROP_COORD), - SendPropVector( SENDINFO_STRUCTARRAYELEM( m_audio.localSound, 4 ), -1, SPROP_COORD), - SendPropVector( SENDINFO_STRUCTARRAYELEM( m_audio.localSound, 5 ), -1, SPROP_COORD), - SendPropVector( SENDINFO_STRUCTARRAYELEM( m_audio.localSound, 6 ), -1, SPROP_COORD), - SendPropVector( SENDINFO_STRUCTARRAYELEM( m_audio.localSound, 7 ), -1, SPROP_COORD), - SendPropInt( SENDINFO_STRUCTELEM( m_audio.soundscapeIndex ), 17, 0 ), - SendPropInt( SENDINFO_STRUCTELEM( m_audio.localBits ), NUM_AUDIO_LOCAL_SOUNDS, SPROP_UNSIGNED ), - SendPropEHandle( SENDINFO_STRUCTELEM( m_audio.ent ) ), -END_SEND_TABLE() - -BEGIN_SIMPLE_DATADESC( fogplayerparams_t ) - DEFINE_FIELD( m_hCtrl, FIELD_EHANDLE ), - DEFINE_FIELD( m_flTransitionTime, FIELD_FLOAT ), - DEFINE_FIELD( m_OldColor, FIELD_COLOR32 ), - DEFINE_FIELD( m_flOldStart, FIELD_FLOAT ), - DEFINE_FIELD( m_flOldEnd, FIELD_FLOAT ), - DEFINE_FIELD( m_NewColor, FIELD_COLOR32 ), - DEFINE_FIELD( m_flNewStart, FIELD_FLOAT ), - DEFINE_FIELD( m_flNewEnd, FIELD_FLOAT ), -END_DATADESC() - -BEGIN_SIMPLE_DATADESC( fogparams_t ) - - DEFINE_FIELD( enable, FIELD_BOOLEAN ), - DEFINE_FIELD( blend, FIELD_BOOLEAN ), - DEFINE_FIELD( dirPrimary, FIELD_VECTOR ), - DEFINE_FIELD( colorPrimary, FIELD_COLOR32 ), - DEFINE_FIELD( colorSecondary, FIELD_COLOR32 ), - DEFINE_FIELD( start, FIELD_FLOAT ), - DEFINE_FIELD( end, FIELD_FLOAT ), - DEFINE_FIELD( farz, FIELD_FLOAT ), - DEFINE_FIELD( maxdensity, FIELD_FLOAT ), - DEFINE_FIELD( colorPrimaryLerpTo, FIELD_COLOR32 ), - DEFINE_FIELD( colorSecondaryLerpTo, FIELD_COLOR32 ), - DEFINE_FIELD( startLerpTo, FIELD_FLOAT ), - DEFINE_FIELD( endLerpTo, FIELD_FLOAT ), - DEFINE_FIELD( lerptime, FIELD_TIME ), - DEFINE_FIELD( duration, FIELD_FLOAT ), -END_DATADESC() - -BEGIN_SIMPLE_DATADESC( sky3dparams_t ) - - DEFINE_FIELD( scale, FIELD_INTEGER ), - DEFINE_FIELD( origin, FIELD_VECTOR ), - DEFINE_FIELD( area, FIELD_INTEGER ), - DEFINE_EMBEDDED( fog ), - -END_DATADESC() - -BEGIN_SIMPLE_DATADESC( audioparams_t ) - - DEFINE_AUTO_ARRAY( localSound, FIELD_VECTOR ), - DEFINE_FIELD( soundscapeIndex, FIELD_INTEGER ), - DEFINE_FIELD( localBits, FIELD_INTEGER ), - DEFINE_FIELD( ent, FIELD_EHANDLE ), - -END_DATADESC() - -BEGIN_SIMPLE_DATADESC( CPlayerLocalData ) - DEFINE_AUTO_ARRAY( m_chAreaBits, FIELD_CHARACTER ), - DEFINE_AUTO_ARRAY( m_chAreaPortalBits, FIELD_CHARACTER ), - DEFINE_FIELD( m_iHideHUD, FIELD_INTEGER ), - DEFINE_FIELD( m_flFOVRate, FIELD_FLOAT ), - DEFINE_FIELD( m_vecOverViewpoint, FIELD_VECTOR ), - DEFINE_FIELD( m_bDucked, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bDucking, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bInDuckJump, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flDucktime, FIELD_TIME ), - DEFINE_FIELD( m_flDuckJumpTime, FIELD_TIME ), - DEFINE_FIELD( m_flJumpTime, FIELD_TIME ), - DEFINE_FIELD( m_nStepside, FIELD_INTEGER ), - DEFINE_FIELD( m_flFallVelocity, FIELD_FLOAT ), - DEFINE_FIELD( m_nOldButtons, FIELD_INTEGER ), - DEFINE_FIELD( m_vecPunchAngle, FIELD_VECTOR ), - DEFINE_FIELD( m_vecPunchAngleVel, FIELD_VECTOR ), - DEFINE_FIELD( m_bDrawViewmodel, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bWearingSuit, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bPoisoned, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flStepSize, FIELD_FLOAT ), - DEFINE_FIELD( m_bAllowAutoMovement, FIELD_BOOLEAN ), - DEFINE_EMBEDDED( m_skybox3d ), - DEFINE_EMBEDDED( m_PlayerFog ), - DEFINE_EMBEDDED( m_fog ), - DEFINE_EMBEDDED( m_audio ), - - // "Why don't we save this field, grandpa?" - // - // "You see Billy, trigger_vphysics_motion uses vPhysics to touch the player, - // so if the trigger is Disabled via an input while the player is inside it, - // the trigger won't get its EndTouch until the player moves. Since touchlinks - // aren't saved and restored, if the we save before EndTouch is called, it - // will never be called after we load." - //DEFINE_FIELD( m_bSlowMovement, FIELD_BOOLEAN ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: Constructor. -//----------------------------------------------------------------------------- -CPlayerLocalData::CPlayerLocalData() -{ -#ifdef _DEBUG - m_vecOverViewpoint.Init(); - m_vecPunchAngle.Init(); -#endif - m_audio.soundscapeIndex = 0; - m_audio.localBits = 0; - m_audio.ent.Set( NULL ); - m_pOldSkyCamera = NULL; - m_bDrawViewmodel = true; -} - - -void CPlayerLocalData::UpdateAreaBits( CBasePlayer *pl, unsigned char chAreaPortalBits[MAX_AREA_PORTAL_STATE_BYTES] ) -{ - Vector origin = pl->EyePosition(); - - unsigned char tempBits[32]; - COMPILE_TIME_ASSERT( sizeof( tempBits ) >= sizeof( ((CPlayerLocalData*)0)->m_chAreaBits ) ); - - int i; - int area = engine->GetArea( origin ); - engine->GetAreaBits( area, tempBits, sizeof( tempBits ) ); - for ( i=0; i < m_chAreaBits.Count(); i++ ) - { - if ( tempBits[i] != m_chAreaBits[ i ] ) - { - m_chAreaBits.Set( i, tempBits[i] ); - } - } - - for ( i=0; i < MAX_AREA_PORTAL_STATE_BYTES; i++ ) - { - if ( chAreaPortalBits[i] != m_chAreaPortalBits[i] ) - m_chAreaPortalBits.Set( i, chAreaPortalBits[i] ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Fills in CClientData values for local player just before sending over wire -// Input : player - -//----------------------------------------------------------------------------- - -void ClientData_Update( CBasePlayer *pl ) -{ - // HACKHACK: for 3d skybox - // UNDONE: Support multiple sky cameras? - CSkyCamera *pSkyCamera = GetCurrentSkyCamera(); - if ( pSkyCamera != pl->m_Local.m_pOldSkyCamera ) - { - pl->m_Local.m_pOldSkyCamera = pSkyCamera; - pl->m_Local.m_skybox3d.CopyFrom(pSkyCamera->m_skyboxData); - } - else if ( !pSkyCamera ) - { - pl->m_Local.m_skybox3d.area = 255; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void UpdateAllClientData( void ) -{ - VPROF( "UpdateAllClientData" ); - int i; - CBasePlayer *pl; - - for ( i = 1; i <= gpGlobals->maxClients; i++ ) - { - pl = ( CBasePlayer * )UTIL_PlayerByIndex( i ); - if ( !pl ) - continue; - - ClientData_Update( pl ); - } -} - diff --git a/game/server/playerlocaldata.h b/game/server/playerlocaldata.h deleted file mode 100644 index cbf0e7279..000000000 --- a/game/server/playerlocaldata.h +++ /dev/null @@ -1,92 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PLAYERLOCALDATA_H -#define PLAYERLOCALDATA_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "playernet_vars.h" -#include "networkvar.h" -#include "fogcontroller.h" - -//----------------------------------------------------------------------------- -// Purpose: Player specific data ( sent only to local player, too ) -//----------------------------------------------------------------------------- -class CPlayerLocalData -{ -public: - // Save/restore - DECLARE_SIMPLE_DATADESC(); - // Prediction data copying - DECLARE_CLASS_NOBASE( CPlayerLocalData ); - DECLARE_EMBEDDED_NETWORKVAR(); - - CPlayerLocalData(); - - void UpdateAreaBits( CBasePlayer *pl, unsigned char chAreaPortalBits[MAX_AREA_PORTAL_STATE_BYTES] ); - - -public: - - CNetworkArray( unsigned char, m_chAreaBits, MAX_AREA_STATE_BYTES ); // Which areas are potentially visible to the client? - CNetworkArray( unsigned char, m_chAreaPortalBits, MAX_AREA_PORTAL_STATE_BYTES ); // Which area portals are open? - - CNetworkVar( int, m_iHideHUD ); // bitfields containing sections of the HUD to hide - CNetworkVar( float, m_flFOVRate ); // rate at which the FOV changes (defaults to 0) - - Vector m_vecOverViewpoint; // Viewpoint overriding the real player's viewpoint - - // Fully ducked - CNetworkVar( bool, m_bDucked ); - // In process of ducking - CNetworkVar( bool, m_bDucking ); - // In process of duck-jumping - CNetworkVar( bool, m_bInDuckJump ); - // During ducking process, amount of time before full duc - CNetworkVar( float, m_flDucktime ); - CNetworkVar( float, m_flDuckJumpTime ); - // Jump time, time to auto unduck (since we auto crouch jump now). - CNetworkVar( float, m_flJumpTime ); - // Step sound side flip/flip - int m_nStepside;; - // Velocity at time when we hit ground - CNetworkVar( float, m_flFallVelocity ); - // Previous button state - int m_nOldButtons; - class CSkyCamera *m_pOldSkyCamera; - // Base velocity that was passed in to server physics so - // client can predict conveyors correctly. Server zeroes it, so we need to store here, too. - // auto-decaying view angle adjustment - CNetworkQAngle( m_vecPunchAngle ); - CNetworkQAngle( m_vecPunchAngleVel ); - // Draw view model for the player - CNetworkVar( bool, m_bDrawViewmodel ); - - // Is the player wearing the HEV suit - CNetworkVar( bool, m_bWearingSuit ); - CNetworkVar( bool, m_bPoisoned ); - CNetworkVar( float, m_flStepSize ); - CNetworkVar( bool, m_bAllowAutoMovement ); - - // 3d skybox - CNetworkVarEmbedded( sky3dparams_t, m_skybox3d ); - // world fog - CNetworkVarEmbedded( fogplayerparams_t, m_PlayerFog ); - fogparams_t m_fog; - // audio environment - CNetworkVarEmbedded( audioparams_t, m_audio ); - - CNetworkVar( bool, m_bSlowMovement ); -}; - -EXTERN_SEND_TABLE(DT_Local); - - -#endif // PLAYERLOCALDATA_H diff --git a/game/server/plugin_check.cpp b/game/server/plugin_check.cpp deleted file mode 100644 index 229578ed1..000000000 --- a/game/server/plugin_check.cpp +++ /dev/null @@ -1,30 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// This class allows the game dll to control what functions 3rd party plugins can -// call on clients. -// -//=============================================================================// - -#include "cbase.h" -#include "eiface.h" - -//----------------------------------------------------------------------------- -// Purpose: An implementation -//----------------------------------------------------------------------------- -class CPluginHelpersCheck : public IPluginHelpersCheck -{ -public: - virtual bool CreateMessage( const char *plugin, edict_t *pEntity, DIALOG_TYPE type, KeyValues *data ); -}; - -CPluginHelpersCheck s_PluginCheck; -EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CPluginHelpersCheck, IPluginHelpersCheck, INTERFACEVERSION_PLUGINHELPERSCHECK, s_PluginCheck); - -bool CPluginHelpersCheck::CreateMessage( const char *plugin, edict_t *pEntity, DIALOG_TYPE type, KeyValues *data ) -{ - // return false here to disallow a plugin from running this command on this client - return true; -} - diff --git a/game/server/point_camera.cpp b/game/server/point_camera.cpp deleted file mode 100644 index 176044ee9..000000000 --- a/game/server/point_camera.cpp +++ /dev/null @@ -1,253 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "igamesystem.h" -#include "point_camera.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define CAM_THINK_INTERVAL 0.05 - -// Spawnflags -#define SF_CAMERA_START_OFF 0x01 - -// UNDONE: Share properly with the client code!!! -#define POINT_CAMERA_MSG_SETACTIVE 1 - -CEntityClassList g_PointCameraList; -template <> CPointCamera *CEntityClassList::m_pClassList = NULL; - -CPointCamera* GetPointCameraList() -{ - return g_PointCameraList.m_pClassList; -} - -// These are already built into CBaseEntity -// DEFINE_KEYFIELD( m_iName, FIELD_STRING, "targetname" ), -// DEFINE_KEYFIELD( m_iParent, FIELD_STRING, "parentname" ), -// DEFINE_KEYFIELD( m_target, FIELD_STRING, "target" ), - -LINK_ENTITY_TO_CLASS( point_camera, CPointCamera ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CPointCamera::~CPointCamera() -{ - g_PointCameraList.Remove( this ); -} - -CPointCamera::CPointCamera() -{ - // Set these to opposites so that it'll be sent the first time around. - m_bActive = false; - m_bIsOn = false; - - m_bFogEnable = false; - - g_PointCameraList.Insert( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointCamera::Spawn( void ) -{ - BaseClass::Spawn(); - - if ( m_spawnflags & SF_CAMERA_START_OFF ) - { - m_bIsOn = false; - } - else - { - m_bIsOn = true; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Override ShouldTransmit since we want to be sent even though we don't have a model, etc. -// All that matters is if we are in the pvs. -//----------------------------------------------------------------------------- -int CPointCamera::UpdateTransmitState() -{ - if ( m_bActive ) - { - return SetTransmitState( FL_EDICT_ALWAYS ); - } - else - { - return SetTransmitState( FL_EDICT_DONTSEND ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointCamera::SetActive( bool bActive ) -{ - // If the mapmaker's told the camera it's off, it enforces inactive state - if ( !m_bIsOn ) - { - bActive = false; - } - - if ( m_bActive != bActive ) - { - m_bActive = bActive; - DispatchUpdateTransmitState(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointCamera::InputChangeFOV( inputdata_t &inputdata ) -{ - // Parse the keyvalue data - char parseString[255]; - - Q_strncpy(parseString, inputdata.value.String(), sizeof(parseString)); - - // Get FOV - char *pszParam = strtok(parseString," "); - if(pszParam) - { - m_TargetFOV = atof( pszParam ); - } - else - { - // Assume no change - m_TargetFOV = m_FOV; - } - - // Get Time - float flChangeTime; - pszParam = strtok(NULL," "); - if(pszParam) - { - flChangeTime = atof( pszParam ); - } - else - { - // Assume 1 second. - flChangeTime = 1.0; - } - - m_DegreesPerSecond = ( m_TargetFOV - m_FOV ) / flChangeTime; - - SetThink( &CPointCamera::ChangeFOVThink ); - SetNextThink( gpGlobals->curtime ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointCamera::ChangeFOVThink( void ) -{ - SetNextThink( gpGlobals->curtime + CAM_THINK_INTERVAL ); - - float newFOV = m_FOV; - - newFOV += m_DegreesPerSecond * CAM_THINK_INTERVAL; - - if( m_DegreesPerSecond < 0 ) - { - if( newFOV <= m_TargetFOV ) - { - newFOV = m_TargetFOV; - SetThink( NULL ); - } - } - else - { - if( newFOV >= m_TargetFOV ) - { - newFOV = m_TargetFOV; - SetThink( NULL ); - } - } - - m_FOV = newFOV; -} - -//----------------------------------------------------------------------------- -// Purpose: Turn this camera on, and turn all other cameras off -//----------------------------------------------------------------------------- -void CPointCamera::InputSetOnAndTurnOthersOff( inputdata_t &inputdata ) -{ - CBaseEntity *pEntity = NULL; - while ((pEntity = gEntList.FindEntityByClassname( pEntity, "point_camera" )) != NULL) - { - CPointCamera *pCamera = (CPointCamera*)pEntity; - pCamera->InputSetOff( inputdata ); - } - - // Now turn myself on - InputSetOn( inputdata ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointCamera::InputSetOn( inputdata_t &inputdata ) -{ - m_bIsOn = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointCamera::InputSetOff( inputdata_t &inputdata ) -{ - m_bIsOn = false; - SetActive( false ); -} - -BEGIN_DATADESC( CPointCamera ) - - // Save/restore Keyvalue fields - DEFINE_KEYFIELD( m_FOV, FIELD_FLOAT, "FOV" ), - DEFINE_KEYFIELD( m_Resolution, FIELD_FLOAT, "resolution" ), - DEFINE_KEYFIELD( m_bFogEnable, FIELD_BOOLEAN, "fogEnable" ), - DEFINE_KEYFIELD( m_FogColor, FIELD_COLOR32, "fogColor" ), - DEFINE_KEYFIELD( m_flFogStart, FIELD_FLOAT, "fogStart" ), - DEFINE_KEYFIELD( m_flFogEnd, FIELD_FLOAT, "fogEnd" ), - DEFINE_KEYFIELD( m_flFogMaxDensity, FIELD_FLOAT, "fogMaxDensity" ), - DEFINE_KEYFIELD( m_bUseScreenAspectRatio, FIELD_BOOLEAN, "UseScreenAspectRatio" ), - DEFINE_FIELD( m_bActive, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bIsOn, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_TargetFOV, FIELD_FLOAT ), - DEFINE_FIELD( m_DegreesPerSecond, FIELD_FLOAT ), - // This is re-set up in the constructor - //DEFINE_FIELD( m_pNext, FIELD_CLASSPTR ), - - DEFINE_FUNCTION( ChangeFOVThink ), - - // Input - DEFINE_INPUTFUNC( FIELD_STRING, "ChangeFOV", InputChangeFOV ), - DEFINE_INPUTFUNC( FIELD_VOID, "SetOnAndTurnOthersOff", InputSetOnAndTurnOthersOff ), - DEFINE_INPUTFUNC( FIELD_VOID, "SetOn", InputSetOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "SetOff", InputSetOff ), - -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CPointCamera, DT_PointCamera ) - SendPropFloat( SENDINFO( m_FOV ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO( m_Resolution ), 0, SPROP_NOSCALE ), - SendPropInt( SENDINFO( m_bFogEnable ), 1, SPROP_UNSIGNED ), - SendPropInt( SENDINFO_STRUCTELEM( m_FogColor ), 32, SPROP_UNSIGNED ), - SendPropFloat( SENDINFO( m_flFogStart ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO( m_flFogEnd ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO( m_flFogMaxDensity ), 0, SPROP_NOSCALE ), - SendPropInt( SENDINFO( m_bActive ), 1, SPROP_UNSIGNED ), - SendPropInt( SENDINFO( m_bUseScreenAspectRatio ), 1, SPROP_UNSIGNED ), -END_SEND_TABLE() diff --git a/game/server/point_camera.h b/game/server/point_camera.h deleted file mode 100644 index a818fe860..000000000 --- a/game/server/point_camera.h +++ /dev/null @@ -1,63 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef CAMERA_H -#define CAMERA_H -#ifdef _WIN32 -#pragma once -#endif - -#include "cbase.h" - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CPointCamera : public CBaseEntity -{ -public: - DECLARE_CLASS( CPointCamera, CBaseEntity ); - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - CPointCamera(); - ~CPointCamera(); - - void Spawn( void ); - - // Tell the client that this camera needs to be rendered - void SetActive( bool bActive ); - int UpdateTransmitState(void); - - void ChangeFOVThink( void ); - - void InputChangeFOV( inputdata_t &inputdata ); - void InputSetOnAndTurnOthersOff( inputdata_t &inputdata ); - void InputSetOn( inputdata_t &inputdata ); - void InputSetOff( inputdata_t &inputdata ); - -private: - float m_TargetFOV; - float m_DegreesPerSecond; - - CNetworkVar( float, m_FOV ); - CNetworkVar( float, m_Resolution ); - CNetworkVar( bool, m_bFogEnable ); - CNetworkColor32( m_FogColor ); - CNetworkVar( float, m_flFogStart ); - CNetworkVar( float, m_flFogEnd ); - CNetworkVar( float, m_flFogMaxDensity ); - CNetworkVar( bool, m_bActive ); - CNetworkVar( bool, m_bUseScreenAspectRatio ); - - // Allows the mapmaker to control whether a camera is active or not - bool m_bIsOn; - -public: - CPointCamera *m_pNext; -}; - -CPointCamera *GetPointCameraList(); -#endif // CAMERA_H diff --git a/game/server/point_devshot_camera.cpp b/game/server/point_devshot_camera.cpp deleted file mode 100644 index d32e65a27..000000000 --- a/game/server/point_devshot_camera.cpp +++ /dev/null @@ -1,268 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: A camera entity that's used by the -makedevshots system to take -// dev screenshots everytime the map is checked into source control. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "tier0/icommandline.h" -#include "igamesystem.h" -#include "filesystem.h" -#include - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -int g_iDevShotCameraCount = 0; -#define DEVSHOT_INITIAL_WAIT 5 // Time after the level spawn before the first devshot camera takes it's shot -#define DEVSHOT_INTERVAL 5 // Time between each devshot camera taking it's shot - -//----------------------------------------------------------------------------- -// Purpose: A camera entity that's used by the -makedevshots system to take -// dev screenshots everytime the map is checked into source control. -//----------------------------------------------------------------------------- -class CPointDevShotCamera : public CBaseEntity -{ - DECLARE_CLASS( CPointDevShotCamera, CBaseEntity ); -public: - DECLARE_DATADESC(); - - void Spawn( void ); - void DevShotThink_Setup( void ); - void DevShotThink_TakeShot( void ); - void DevShotThink_PostShot( void ); - - // Always transmit to clients so they know where to move the view to - virtual int UpdateTransmitState(); - -private: - string_t m_iszCameraName; - int m_iFOV; -}; - -BEGIN_DATADESC( CPointDevShotCamera ) - DEFINE_FUNCTION( DevShotThink_Setup ), - DEFINE_FUNCTION( DevShotThink_TakeShot ), - DEFINE_FUNCTION( DevShotThink_PostShot ), - - DEFINE_KEYFIELD( m_iszCameraName, FIELD_STRING, "cameraname" ), - DEFINE_KEYFIELD( m_iFOV, FIELD_INTEGER, "FOV" ), -END_DATADESC() - -LINK_ENTITY_TO_CLASS( point_devshot_camera, CPointDevShotCamera ); - -//----------------------------------------------------------------------------- -// Purpose: Convenience function so we don't have to make this check all over -//----------------------------------------------------------------------------- -static CBasePlayer * UTIL_GetLocalPlayerOrListenServerHost( void ) -{ - if ( gpGlobals->maxClients > 1 ) - { - if ( engine->IsDedicatedServer() ) - { - return NULL; - } - - return UTIL_GetListenServerHost(); - } - - return UTIL_GetLocalPlayer(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointDevShotCamera::Spawn( void ) -{ - BaseClass::Spawn(); - - // Remove this entity immediately if we're not making devshots - if ( !CommandLine()->FindParm("-makedevshots") ) - { - UTIL_Remove( this ); - return; - } - - // Take a screenshot when it's my turn - SetThink( &CPointDevShotCamera::DevShotThink_Setup ); - SetNextThink( gpGlobals->curtime + DEVSHOT_INITIAL_WAIT + (g_iDevShotCameraCount * DEVSHOT_INTERVAL) ); - - g_iDevShotCameraCount++; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CPointDevShotCamera::UpdateTransmitState() -{ - // always transmit if currently used by a monitor - return SetTransmitState( FL_EDICT_ALWAYS ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointDevShotCamera::DevShotThink_Setup( void ) -{ - // Move the player to the devshot camera - CBasePlayer *pPlayer = UTIL_GetLocalPlayerOrListenServerHost(); - if ( !pPlayer ) - return; - - // Hide stuff - engine->ClientCommand( pPlayer->edict(), "developer 0" ); - engine->ClientCommand( pPlayer->edict(), "cl_drawhud 0" ); - engine->ClientCommand( pPlayer->edict(), "sv_cheats 1" ); - engine->ClientCommand( pPlayer->edict(), "god" ); - engine->ClientCommand( pPlayer->edict(), "notarget" ); - - pPlayer->AddSolidFlags( FSOLID_NOT_SOLID ); - pPlayer->EnableControl(FALSE); - pPlayer->SetViewEntity( this ); - pPlayer->SetFOV( this, m_iFOV ); - - // Hide the player's viewmodel - if ( pPlayer->GetActiveWeapon() ) - { - pPlayer->GetActiveWeapon()->AddEffects( EF_NODRAW ); - } - - DispatchUpdateTransmitState(); - - // Now take the shot next frame - SetThink( &CPointDevShotCamera::DevShotThink_TakeShot ); - SetNextThink( gpGlobals->curtime ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointDevShotCamera::DevShotThink_TakeShot( void ) -{ - // Take the screenshot - CBasePlayer *pPlayer = UTIL_GetLocalPlayerOrListenServerHost(); - if ( !pPlayer ) - return; - - engine->ClientCommand( pPlayer->edict(), UTIL_VarArgs( "devshots_screenshot \"%s\"", STRING(m_iszCameraName) ) ); - - // Now take the shot next frame - SetThink( &CPointDevShotCamera::DevShotThink_PostShot ); - SetNextThink( gpGlobals->curtime + (DEVSHOT_INTERVAL - 1) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointDevShotCamera::DevShotThink_PostShot( void ) -{ - // Take the screenshot - CBasePlayer *pPlayer = UTIL_GetLocalPlayerOrListenServerHost(); - if ( !pPlayer ) - return; - - pPlayer->SetFOV( this, 0 ); - - // If all cameras have taken their shots, move to the next map - g_iDevShotCameraCount--; - if ( !g_iDevShotCameraCount ) - { - engine->ClientCommand( pPlayer->edict(), "devshots_nextmap" ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Game system to detect maps without cameras in them, and move on -//----------------------------------------------------------------------------- -class CDevShotSystem : public CAutoGameSystemPerFrame -{ -public: - - CDevShotSystem( char const *name ) : CAutoGameSystemPerFrame( name ) - { - } - - virtual void LevelInitPreEntity() - { - m_bIssuedNextMapCommand = false; - g_iDevShotCameraCount = 0; - m_bParsedMapFile = false; - } - - virtual void SafeRemoveIfDesired( void ) - { - // If we're not making devshots, remove this system immediately - if ( !CommandLine()->FindParm("-makedevshots") ) - { - Remove( this ); - return; - } - } - - virtual void FrameUpdatePostEntityThink( void ) - { - // Wait until we're all spawned in - if ( gpGlobals->curtime < 5 ) - return; - - if ( m_bIssuedNextMapCommand ) - return; - - if ( !m_bParsedMapFile ) - { - m_bParsedMapFile = true; - - // See if we've got a camera file to import cameras from - char szFullName[512]; - Q_snprintf(szFullName,sizeof(szFullName), "maps/%s.txt", STRING( gpGlobals->mapname )); - KeyValues *pkvMapCameras = new KeyValues( "MapCameras" ); - if ( pkvMapCameras->LoadFromFile( filesystem, szFullName, "MOD" ) ) - { - Warning( "Devshots: Loading point_devshot_camera positions from %s. \n", szFullName ); - - // Get each camera, and add it to our list - KeyValues *pkvCamera = pkvMapCameras->GetFirstSubKey(); - while ( pkvCamera ) - { - // Get camera name - const char *pCameraName = pkvCamera->GetName(); - - // Make a camera, and move it to the position specified - CPointDevShotCamera *pCamera = (CPointDevShotCamera*)CreateEntityByName( "point_devshot_camera" ); - Assert( pCamera ); - pCamera->KeyValue( "cameraname", pCameraName ); - pCamera->KeyValue( "origin", pkvCamera->GetString( "origin", "0 0 0" ) ); - pCamera->KeyValue( "angles", pkvCamera->GetString( "angles", "0 0 0" ) ); - pCamera->KeyValue( "FOV", pkvCamera->GetString( "FOV", "75" ) ); - DispatchSpawn( pCamera ); - pCamera->Activate(); - - // Move to next camera - pkvCamera = pkvCamera->GetNextKey(); - } - } - - if ( !g_iDevShotCameraCount ) - { - Warning( "Devshots: No point_devshot_camera in %s. Moving to next map.\n", STRING( gpGlobals->mapname ) ); - - CBasePlayer *pPlayer = UTIL_GetLocalPlayerOrListenServerHost(); - if ( pPlayer ) - { - engine->ClientCommand( pPlayer->edict(), "devshots_nextmap" ); - m_bIssuedNextMapCommand = true; - return; - } - } - } - } - -private: - bool m_bIssuedNextMapCommand; - bool m_bParsedMapFile; -}; - -CDevShotSystem DevShotSystem( "CDevShotSystem" ); diff --git a/game/server/point_playermoveconstraint.cpp b/game/server/point_playermoveconstraint.cpp deleted file mode 100644 index 6bd92d45a..000000000 --- a/game/server/point_playermoveconstraint.cpp +++ /dev/null @@ -1,161 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: An entity that can be used to constrain the player's movement around it -// -//=============================================================================// - -#include "cbase.h" -#include "saverestore_utlvector.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SF_TELEPORT_TO_SPAWN_POS 0x00000001 - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CPointPlayerMoveConstraint : public CBaseEntity -{ - DECLARE_CLASS( CPointPlayerMoveConstraint, CBaseEntity ); -public: - DECLARE_DATADESC(); - - int UpdateTransmitState( void ); - void Activate( void ); - void ConstraintThink( void ); - - void InputTurnOn( inputdata_t &inputdata ); - void InputTurnOff( inputdata_t &inputdata ); - -private: - float m_flRadius; - float m_flConstraintWidth; - float m_flSpeedFactor; - float m_flRadiusSquared; - CUtlVector m_hConstrainedPlayers; - COutputEvent m_OnConstraintBroken; -}; - -LINK_ENTITY_TO_CLASS( point_playermoveconstraint, CPointPlayerMoveConstraint ); - -BEGIN_DATADESC( CPointPlayerMoveConstraint ) - - DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "radius" ), - DEFINE_KEYFIELD( m_flConstraintWidth, FIELD_FLOAT, "width" ), - DEFINE_KEYFIELD( m_flSpeedFactor, FIELD_FLOAT, "speedfactor" ), - // DEFINE_FIELD( m_flRadiusSquared, FIELD_FLOAT ), // Don't Save - DEFINE_UTLVECTOR( m_hConstrainedPlayers, FIELD_EHANDLE ), - - DEFINE_THINKFUNC( ConstraintThink ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - - DEFINE_OUTPUT( m_OnConstraintBroken, "OnConstraintBroken" ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CPointPlayerMoveConstraint::UpdateTransmitState() -{ - // ALWAYS transmit to all clients. - return SetTransmitState( FL_EDICT_ALWAYS ); -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CPointPlayerMoveConstraint::Activate( void ) -{ - BaseClass::Activate(); - - m_flRadiusSquared = (m_flRadius * m_flRadius); -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CPointPlayerMoveConstraint::InputTurnOn( inputdata_t &inputdata ) -{ - // Find all players within our radius and constraint them - float flRadius = m_flRadius; - // If we're in singleplayer, blow the radius a bunch - if ( gpGlobals->maxClients == 1 ) - { - flRadius = MAX_COORD_RANGE; - } - CBaseEntity *pEntity = NULL; - while ( (pEntity = gEntList.FindEntityByClassnameWithin( pEntity, "player", GetLocalOrigin(), flRadius)) != NULL ) - { - CBasePlayer *pPlayer = ToBasePlayer( pEntity ); - Assert( pPlayer ); - - // Only add him if he's not already constrained - if ( m_hConstrainedPlayers.Find( pPlayer ) == m_hConstrainedPlayers.InvalidIndex() ) - { - m_hConstrainedPlayers.AddToTail( pPlayer ); - - pPlayer->ActivateMovementConstraint( this, GetAbsOrigin(), m_flRadius, m_flConstraintWidth, m_flSpeedFactor ); - } - } - - // Only think if we found any - if ( m_hConstrainedPlayers.Count() ) - { - SetThink( &CPointPlayerMoveConstraint::ConstraintThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); - } -} - -//------------------------------------------------------------------------------ -// Purpose: Release all players we've constrained -//------------------------------------------------------------------------------ -void CPointPlayerMoveConstraint::InputTurnOff( inputdata_t &inputdata ) -{ - int iCount = m_hConstrainedPlayers.Count(); - for ( int i = 0; i < iCount; i++ ) - { - CBasePlayer *pPlayer = ToBasePlayer( m_hConstrainedPlayers[i] ); - if ( pPlayer ) - { - pPlayer->DeactivateMovementConstraint(); - } - } - - m_hConstrainedPlayers.Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: Check to see if any of our constrained players have broken the constraint -//----------------------------------------------------------------------------- -void CPointPlayerMoveConstraint::ConstraintThink( void ) -{ - int iCount = m_hConstrainedPlayers.Count(); - - // Count backwards, because we might drop them if they've broken the constraint - for ( int i = (iCount-1); i >= 0; i-- ) - { - CBasePlayer *pPlayer = ToBasePlayer( m_hConstrainedPlayers[i] ); - if ( pPlayer ) - { - float flDistanceSqr = (pPlayer->GetAbsOrigin() - GetAbsOrigin()).LengthSqr(); - if ( flDistanceSqr > m_flRadiusSquared ) - { - // Break the constraint to this player - pPlayer->DeactivateMovementConstraint(); - m_hConstrainedPlayers.Remove(i); - - // Fire the broken output - m_OnConstraintBroken.FireOutput( this, pPlayer ); - } - } - } - - // Only keep thinking if we any left - if ( m_hConstrainedPlayers.Count() ) - { - SetNextThink( gpGlobals->curtime + 0.1f ); - } -} diff --git a/game/server/point_spotlight.cpp b/game/server/point_spotlight.cpp deleted file mode 100644 index 79dbea05e..000000000 --- a/game/server/point_spotlight.cpp +++ /dev/null @@ -1,511 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#include "cbase.h" -#include "beam_shared.h" -#include "spotlightend.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// Spawnflags -#define SF_SPOTLIGHT_START_LIGHT_ON 0x1 -#define SF_SPOTLIGHT_NO_DYNAMIC_LIGHT 0x2 - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CPointSpotlight : public CPointEntity -{ - DECLARE_CLASS( CPointSpotlight, CPointEntity ); -public: - DECLARE_DATADESC(); - - CPointSpotlight(); - - void Precache(void); - void Spawn(void); - virtual void Activate(); - - virtual void OnEntityEvent( EntityEvent_t event, void *pEventData ); - -private: - int UpdateTransmitState(); - void SpotlightThink(void); - void SpotlightUpdate(void); - Vector SpotlightCurrentPos(void); - void SpotlightCreate(void); - void SpotlightDestroy(void); - - // ------------------------------ - // Inputs - // ------------------------------ - void InputLightOn( inputdata_t &inputdata ); - void InputLightOff( inputdata_t &inputdata ); - - // Creates the efficient spotlight - void CreateEfficientSpotlight(); - - // Computes render info for a spotlight - void ComputeRenderInfo(); - -private: - bool m_bSpotlightOn; - bool m_bEfficientSpotlight; - Vector m_vSpotlightTargetPos; - Vector m_vSpotlightCurrentPos; - Vector m_vSpotlightDir; - int m_nHaloSprite; - CHandle m_hSpotlight; - CHandle m_hSpotlightTarget; - - float m_flSpotlightMaxLength; - float m_flSpotlightCurLength; - float m_flSpotlightGoalWidth; - float m_flHDRColorScale; - int m_nMinDXLevel; - -public: - COutputEvent m_OnOn, m_OnOff; ///< output fires when turned on, off -}; - -BEGIN_DATADESC( CPointSpotlight ) - DEFINE_FIELD( m_flSpotlightCurLength, FIELD_FLOAT ), - - DEFINE_FIELD( m_bSpotlightOn, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bEfficientSpotlight, FIELD_BOOLEAN ), - DEFINE_FIELD( m_vSpotlightTargetPos, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vSpotlightCurrentPos, FIELD_POSITION_VECTOR ), - - // Robin: Don't Save, recreated after restore/transition - //DEFINE_FIELD( m_hSpotlight, FIELD_EHANDLE ), - //DEFINE_FIELD( m_hSpotlightTarget, FIELD_EHANDLE ), - - DEFINE_FIELD( m_vSpotlightDir, FIELD_VECTOR ), - DEFINE_FIELD( m_nHaloSprite, FIELD_INTEGER ), - - DEFINE_KEYFIELD( m_flSpotlightMaxLength,FIELD_FLOAT, "SpotlightLength"), - DEFINE_KEYFIELD( m_flSpotlightGoalWidth,FIELD_FLOAT, "SpotlightWidth"), - DEFINE_KEYFIELD( m_flHDRColorScale, FIELD_FLOAT, "HDRColorScale" ), - DEFINE_KEYFIELD( m_nMinDXLevel, FIELD_INTEGER, "mindxlevel" ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "LightOn", InputLightOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "LightOff", InputLightOff ), - DEFINE_OUTPUT( m_OnOn, "OnLightOn" ), - DEFINE_OUTPUT( m_OnOff, "OnLightOff" ), - - DEFINE_THINKFUNC( SpotlightThink ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS(point_spotlight, CPointSpotlight); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CPointSpotlight::CPointSpotlight() -{ -#ifdef _DEBUG - m_vSpotlightTargetPos.Init(); - m_vSpotlightCurrentPos.Init(); - m_vSpotlightDir.Init(); -#endif - m_flHDRColorScale = 1.0f; - m_nMinDXLevel = 0; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointSpotlight::Precache(void) -{ - BaseClass::Precache(); - - // Sprites. - m_nHaloSprite = PrecacheModel("sprites/light_glow03.vmt"); - PrecacheModel( "sprites/glow_test02.vmt" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointSpotlight::Spawn(void) -{ - Precache(); - - UTIL_SetSize( this,vec3_origin,vec3_origin ); - AddSolidFlags( FSOLID_NOT_SOLID ); - SetMoveType( MOVETYPE_NONE ); - m_bEfficientSpotlight = true; - - // Check for user error - if (m_flSpotlightMaxLength <= 0) - { - DevMsg("%s (%s) has an invalid spotlight length <= 0, setting to 500\n", GetClassname(), GetDebugName() ); - m_flSpotlightMaxLength = 500; - } - if (m_flSpotlightGoalWidth <= 0) - { - DevMsg("%s (%s) has an invalid spotlight width <= 0, setting to 10\n", GetClassname(), GetDebugName() ); - m_flSpotlightGoalWidth = 10; - } - - if (m_flSpotlightGoalWidth > MAX_BEAM_WIDTH ) - { - DevMsg("%s (%s) has an invalid spotlight width %.1f (max %.1f).\n", GetClassname(), GetDebugName(), m_flSpotlightGoalWidth, MAX_BEAM_WIDTH ); - m_flSpotlightGoalWidth = MAX_BEAM_WIDTH; - } - - // ------------------------------------ - // Init all class vars - // ------------------------------------ - m_vSpotlightTargetPos = vec3_origin; - m_vSpotlightCurrentPos = vec3_origin; - m_hSpotlight = NULL; - m_hSpotlightTarget = NULL; - m_vSpotlightDir = vec3_origin; - m_flSpotlightCurLength = m_flSpotlightMaxLength; - - m_bSpotlightOn = HasSpawnFlags( SF_SPOTLIGHT_START_LIGHT_ON ); - - SetThink( &CPointSpotlight::SpotlightThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); -} - - -//----------------------------------------------------------------------------- -// Computes render info for a spotlight -//----------------------------------------------------------------------------- -void CPointSpotlight::ComputeRenderInfo() -{ - // Fade out spotlight end if past max length. - if ( m_flSpotlightCurLength > 2*m_flSpotlightMaxLength ) - { - m_hSpotlightTarget->SetRenderColorA( 0 ); - m_hSpotlight->SetFadeLength( m_flSpotlightMaxLength ); - } - else if ( m_flSpotlightCurLength > m_flSpotlightMaxLength ) - { - m_hSpotlightTarget->SetRenderColorA( (byte)(1-((m_flSpotlightCurLength-m_flSpotlightMaxLength)/m_flSpotlightMaxLength)) ); - m_hSpotlight->SetFadeLength( m_flSpotlightMaxLength ); - } - else - { - m_hSpotlightTarget->SetRenderColorA( 1 ); - m_hSpotlight->SetFadeLength( m_flSpotlightCurLength ); - } - - // Adjust end width to keep beam width constant - float flNewWidth = m_flSpotlightGoalWidth * (m_flSpotlightCurLength / m_flSpotlightMaxLength); - flNewWidth = clamp(flNewWidth, 0, MAX_BEAM_WIDTH ); - m_hSpotlight->SetEndWidth(flNewWidth); - - // Adjust width of light on the end. - if ( FBitSet (m_spawnflags, SF_SPOTLIGHT_NO_DYNAMIC_LIGHT) ) - { - m_hSpotlightTarget->m_flLightScale = 0.0; - } - else - { - // <> - magic number 1.8 depends on sprite size - m_hSpotlightTarget->m_flLightScale = 1.8*flNewWidth; - } -} - - -//----------------------------------------------------------------------------- -// Creates the efficient spotlight -//----------------------------------------------------------------------------- -void CPointSpotlight::CreateEfficientSpotlight() -{ - if ( m_hSpotlightTarget.Get() != NULL ) - return; - - SpotlightCreate(); - m_vSpotlightCurrentPos = SpotlightCurrentPos(); - m_hSpotlightTarget->SetAbsOrigin( m_vSpotlightCurrentPos ); - m_hSpotlightTarget->m_vSpotlightOrg = GetAbsOrigin(); - VectorSubtract( m_hSpotlightTarget->GetAbsOrigin(), m_hSpotlightTarget->m_vSpotlightOrg, m_hSpotlightTarget->m_vSpotlightDir ); - m_flSpotlightCurLength = VectorNormalize( m_hSpotlightTarget->m_vSpotlightDir ); - m_hSpotlightTarget->SetMoveType( MOVETYPE_NONE ); - ComputeRenderInfo(); - - m_OnOn.FireOutput( this, this ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointSpotlight::Activate(void) -{ - BaseClass::Activate(); - - if ( GetMoveParent() ) - { - m_bEfficientSpotlight = false; - } - - if ( m_bEfficientSpotlight ) - { - if ( m_bSpotlightOn ) - { - CreateEfficientSpotlight(); - } - - // Don't think - SetThink( NULL ); - } -} - - -//------------------------------------------------------------------------------------- -// Optimization to deal with spotlights -//------------------------------------------------------------------------------------- -void CPointSpotlight::OnEntityEvent( EntityEvent_t event, void *pEventData ) -{ - if ( event == ENTITY_EVENT_PARENT_CHANGED ) - { - if ( GetMoveParent() ) - { - m_bEfficientSpotlight = false; - if ( m_hSpotlightTarget ) - { - m_hSpotlightTarget->SetMoveType( MOVETYPE_FLY ); - } - SetThink( &CPointSpotlight::SpotlightThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); - } - } - - BaseClass::OnEntityEvent( event, pEventData ); -} - - -//------------------------------------------------------------------------------------- -// Purpose : Send even though we don't have a model so spotlight gets proper position -// Input : -// Output : -//------------------------------------------------------------------------------------- -int CPointSpotlight::UpdateTransmitState() -{ - if ( m_bEfficientSpotlight ) - return SetTransmitState( FL_EDICT_DONTSEND ); - - return SetTransmitState( FL_EDICT_PVSCHECK ); -} - -//----------------------------------------------------------------------------- -// Purpose: Plays the engine sound. -//----------------------------------------------------------------------------- -void CPointSpotlight::SpotlightThink( void ) -{ - if ( GetMoveParent() ) - { - SetNextThink( gpGlobals->curtime + TICK_INTERVAL ); - } - else - { - SetNextThink( gpGlobals->curtime + 0.1f ); - } - - SpotlightUpdate(); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CPointSpotlight::SpotlightCreate(void) -{ - if ( m_hSpotlightTarget.Get() != NULL ) - return; - - AngleVectors( GetAbsAngles(), &m_vSpotlightDir ); - - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + m_vSpotlightDir * m_flSpotlightMaxLength, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr); - - m_hSpotlightTarget = (CSpotlightEnd*)CreateEntityByName( "spotlight_end" ); - m_hSpotlightTarget->Spawn(); - m_hSpotlightTarget->SetAbsOrigin( tr.endpos ); - m_hSpotlightTarget->SetOwnerEntity( this ); - m_hSpotlightTarget->m_clrRender = m_clrRender; - m_hSpotlightTarget->m_Radius = m_flSpotlightMaxLength; - - if ( FBitSet (m_spawnflags, SF_SPOTLIGHT_NO_DYNAMIC_LIGHT) ) - { - m_hSpotlightTarget->m_flLightScale = 0.0; - } - - //m_hSpotlight = CBeam::BeamCreate( "sprites/spotlight.vmt", m_flSpotlightGoalWidth ); - m_hSpotlight = CBeam::BeamCreate( "sprites/glow_test02.vmt", m_flSpotlightGoalWidth ); - // Set the temporary spawnflag on the beam so it doesn't save (we'll recreate it on restore) - m_hSpotlight->SetHDRColorScale( m_flHDRColorScale ); - m_hSpotlight->AddSpawnFlags( SF_BEAM_TEMPORARY ); - m_hSpotlight->SetColor( m_clrRender->r, m_clrRender->g, m_clrRender->b ); - m_hSpotlight->SetHaloTexture(m_nHaloSprite); - m_hSpotlight->SetHaloScale(60); - m_hSpotlight->SetEndWidth(m_flSpotlightGoalWidth); - m_hSpotlight->SetBeamFlags( (FBEAM_SHADEOUT|FBEAM_NOTILE) ); - m_hSpotlight->SetBrightness( 64 ); - m_hSpotlight->SetNoise( 0 ); - m_hSpotlight->SetMinDXLevel( m_nMinDXLevel ); - - if ( m_bEfficientSpotlight ) - { - m_hSpotlight->PointsInit( GetAbsOrigin(), m_hSpotlightTarget->GetAbsOrigin() ); - } - else - { - m_hSpotlight->EntsInit( this, m_hSpotlightTarget ); - } -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -Vector CPointSpotlight::SpotlightCurrentPos(void) -{ - AngleVectors( GetAbsAngles(), &m_vSpotlightDir ); - - // Get beam end point. Only collide with solid objects, not npcs - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + (m_vSpotlightDir * 2 * m_flSpotlightMaxLength), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - return tr.endpos; -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CPointSpotlight::SpotlightDestroy(void) -{ - if ( m_hSpotlight ) - { - m_OnOff.FireOutput( this, this ); - - UTIL_Remove(m_hSpotlight); - UTIL_Remove(m_hSpotlightTarget); - } -} - -//------------------------------------------------------------------------------ -// Purpose : Update the direction and position of my spotlight -// Input : -// Output : -//------------------------------------------------------------------------------ -void CPointSpotlight::SpotlightUpdate(void) -{ - // --------------------------------------------------- - // If I don't have a spotlight attempt to create one - // --------------------------------------------------- - if ( !m_hSpotlight ) - { - if ( m_bSpotlightOn ) - { - // Make the spotlight - SpotlightCreate(); - } - else - { - return; - } - } - else if ( !m_bSpotlightOn ) - { - SpotlightDestroy(); - return; - } - - if ( !m_hSpotlightTarget ) - { - DevWarning( "**Attempting to update point_spotlight but target ent is NULL\n" ); - SpotlightDestroy(); - SpotlightCreate(); - if ( !m_hSpotlightTarget ) - return; - } - - m_vSpotlightCurrentPos = SpotlightCurrentPos(); - - // Update spotlight target velocity - Vector vTargetDir; - VectorSubtract( m_vSpotlightCurrentPos, m_hSpotlightTarget->GetAbsOrigin(), vTargetDir ); - float vTargetDist = vTargetDir.Length(); - - // If we haven't moved at all, don't recompute - if ( vTargetDist < 1 ) - { - m_hSpotlightTarget->SetAbsVelocity( vec3_origin ); - return; - } - - Vector vecNewVelocity = vTargetDir; - VectorNormalize(vecNewVelocity); - vecNewVelocity *= (10 * vTargetDist); - - // If a large move is requested, just jump to final spot as we probably hit a discontinuity - if (vecNewVelocity.Length() > 200) - { - VectorNormalize(vecNewVelocity); - vecNewVelocity *= 200; - VectorNormalize(vTargetDir); - m_hSpotlightTarget->SetAbsOrigin( m_vSpotlightCurrentPos ); - } - m_hSpotlightTarget->SetAbsVelocity( vecNewVelocity ); - m_hSpotlightTarget->m_vSpotlightOrg = GetAbsOrigin(); - - // Avoid sudden change in where beam fades out when cross disconinuities - VectorSubtract( m_hSpotlightTarget->GetAbsOrigin(), m_hSpotlightTarget->m_vSpotlightOrg, m_hSpotlightTarget->m_vSpotlightDir ); - float flBeamLength = VectorNormalize( m_hSpotlightTarget->m_vSpotlightDir ); - m_flSpotlightCurLength = (0.60*m_flSpotlightCurLength) + (0.4*flBeamLength); - - ComputeRenderInfo(); - - //NDebugOverlay::Cross3D(GetAbsOrigin(),Vector(-5,-5,-5),Vector(5,5,5),0,255,0,true,0.1); - //NDebugOverlay::Cross3D(m_vSpotlightCurrentPos,Vector(-5,-5,-5),Vector(5,5,5),0,255,0,true,0.1); - //NDebugOverlay::Cross3D(m_vSpotlightTargetPos,Vector(-5,-5,-5),Vector(5,5,5),255,0,0,true,0.1); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointSpotlight::InputLightOn( inputdata_t &inputdata ) -{ - if ( !m_bSpotlightOn ) - { - m_bSpotlightOn = true; - if ( m_bEfficientSpotlight ) - { - CreateEfficientSpotlight(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointSpotlight::InputLightOff( inputdata_t &inputdata ) -{ - if ( m_bSpotlightOn ) - { - m_bSpotlightOn = false; - if ( m_bEfficientSpotlight ) - { - SpotlightDestroy(); - } - } -} diff --git a/game/server/point_template.cpp b/game/server/point_template.cpp deleted file mode 100644 index a2144c153..000000000 --- a/game/server/point_template.cpp +++ /dev/null @@ -1,409 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Point entity used to create templates out of other entities or groups of entities -// -//=============================================================================// - -#include "cbase.h" -#include "entityinput.h" -#include "entityoutput.h" -#include "TemplateEntities.h" -#include "point_template.h" -#include "saverestore_utlvector.h" -#include "mapentities.h" -#include "tier0/icommandline.h" -#include "mapentities_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SF_POINTTEMPLATE_DONTREMOVETEMPLATEENTITIES 0x0001 - -// Level designers can suppress the uniquification of the spawned entity -// names with a spawnflag, provided they guarantee that only one instance -// of the entities will ever be spawned at a time. -#define SF_POINTTEMPLATE_PRESERVE_NAMES 0x0002 - - -LINK_ENTITY_TO_CLASS(point_template, CPointTemplate); - -BEGIN_SIMPLE_DATADESC( template_t ) - DEFINE_FIELD( iTemplateIndex, FIELD_INTEGER ), - DEFINE_FIELD( matEntityToTemplate, FIELD_VMATRIX ), -END_DATADESC() - -BEGIN_DATADESC( CPointTemplate ) - // Keys - - // Silence, Classcheck! - // DEFINE_ARRAY( m_iszTemplateEntityNames, FIELD_STRING, MAX_NUM_TEMPLATES ), - - DEFINE_KEYFIELD( m_iszTemplateEntityNames[0], FIELD_STRING, "Template01"), - DEFINE_KEYFIELD( m_iszTemplateEntityNames[1], FIELD_STRING, "Template02"), - DEFINE_KEYFIELD( m_iszTemplateEntityNames[2], FIELD_STRING, "Template03"), - DEFINE_KEYFIELD( m_iszTemplateEntityNames[3], FIELD_STRING, "Template04"), - DEFINE_KEYFIELD( m_iszTemplateEntityNames[4], FIELD_STRING, "Template05"), - DEFINE_KEYFIELD( m_iszTemplateEntityNames[5], FIELD_STRING, "Template06"), - DEFINE_KEYFIELD( m_iszTemplateEntityNames[6], FIELD_STRING, "Template07"), - DEFINE_KEYFIELD( m_iszTemplateEntityNames[7], FIELD_STRING, "Template08"), - DEFINE_KEYFIELD( m_iszTemplateEntityNames[8], FIELD_STRING, "Template09"), - DEFINE_KEYFIELD( m_iszTemplateEntityNames[9], FIELD_STRING, "Template10"), - DEFINE_KEYFIELD( m_iszTemplateEntityNames[10], FIELD_STRING, "Template11"), - DEFINE_KEYFIELD( m_iszTemplateEntityNames[11], FIELD_STRING, "Template12"), - DEFINE_KEYFIELD( m_iszTemplateEntityNames[12], FIELD_STRING, "Template13"), - DEFINE_KEYFIELD( m_iszTemplateEntityNames[13], FIELD_STRING, "Template14"), - DEFINE_KEYFIELD( m_iszTemplateEntityNames[14], FIELD_STRING, "Template15"), - DEFINE_KEYFIELD( m_iszTemplateEntityNames[15], FIELD_STRING, "Template16"), - DEFINE_UTLVECTOR( m_hTemplateEntities, FIELD_CLASSPTR ), - - DEFINE_UTLVECTOR( m_hTemplates, FIELD_EMBEDDED ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "ForceSpawn", InputForceSpawn ), - - // Outputs - DEFINE_OUTPUT( m_pOutputOnSpawned, "OnEntitySpawned" ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: A simple system to help precache point_template entities ... ywb -//----------------------------------------------------------------------------- -class CPointTemplatePrecacher : public CAutoGameSystem -{ -public: - - CPointTemplatePrecacher( char const *name ) : CAutoGameSystem( name ) - { - } - - void AddToPrecache( CBaseEntity *ent ) - { - m_Ents.AddToTail( EHANDLE( ent ) ); - } - - virtual void LevelInitPreEntity() - { - m_Ents.RemoveAll(); - } - - virtual void Shutdown() - { - m_Ents.RemoveAll(); - } - - void Precache() - { - int c = m_Ents.Count(); - for ( int i = 0 ; i < c; ++i ) - { - CPointTemplate *ent = m_Ents[ i ].Get(); - if ( ent ) - { - ent->PerformPrecache(); - } - } - - m_Ents.RemoveAll(); - } -private: - - CUtlVector< CHandle< CPointTemplate > > m_Ents; -}; - -CPointTemplatePrecacher g_PointTemplatePrecacher( "CPointTemplatePrecacher" ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void PrecachePointTemplates() -{ - g_PointTemplatePrecacher.Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointTemplate::Spawn( void ) -{ - Precache(); -} - -void CPointTemplate::Precache() -{ - // We can't call precache right when we instance the template, we need to defer it until after all map entities have - // been loaded, so add this template to a list which is cleared after map entity parsing is completed. - g_PointTemplatePrecacher.AddToPrecache( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: Level designers can suppress the uniquification of the spawned entity -// names with a spawnflag, provided they guarantee that only one instance -// of the entities will ever be spawned at a time. -//----------------------------------------------------------------------------- -bool CPointTemplate::AllowNameFixup() -{ - return !HasSpawnFlags( SF_POINTTEMPLATE_PRESERVE_NAMES ); -} - -//----------------------------------------------------------------------------- -// Purpose: Called at the start of template initialization for this point_template. -// Find all the entities referenced by this point_template, which will -// then be turned into templates by the map-parsing code. -//----------------------------------------------------------------------------- -void CPointTemplate::StartBuildingTemplates( void ) -{ - // Build our list of template entities - for ( int i = 0; i < MAX_NUM_TEMPLATES; i++ ) - { - if ( m_iszTemplateEntityNames[i] != NULL_STRING ) - { - CBaseEntity *pEntity = NULL; - int iOldNum = m_hTemplateEntities.Count(); - // Add all the entities with the matching targetname - while ( (pEntity = gEntList.FindEntityByName( pEntity, STRING(m_iszTemplateEntityNames[i]) )) != NULL ) - { - m_hTemplateEntities.AddToTail( pEntity ); - } - - // Useful mapmaker warning - if ( iOldNum == m_hTemplateEntities.Count() ) - { - Warning( "Couldn't find any entities named %s, which point_template %s is specifying.\n", STRING(m_iszTemplateEntityNames[i]), STRING(GetEntityName()) ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Called at the end of template initialization for this point_template. -// All of our referenced entities have now been destroyed. -//----------------------------------------------------------------------------- -void CPointTemplate::FinishBuildingTemplates( void ) -{ - // Our template entities are now gone, deleted by the server post turning them into templates. - m_hTemplateEntities.Purge(); - - // Now tell the template system to hook up all the Entity I/O connections within our set of templates. - Templates_ReconnectIOForGroup( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointTemplate::AddTemplate( CBaseEntity *pEntity, const char *pszMapData, int nLen ) -{ - // Add it to the template list - int iIndex = Templates_Add( pEntity, pszMapData, nLen ); - if ( iIndex == -1 ) - { - Warning( "point_template %s failed to add template.\n", STRING(GetEntityName()) ); - return; - } - - template_t newTemplate; - newTemplate.iTemplateIndex = iIndex; - - // Store the entity's origin & angles in a matrix in the template's local space - VMatrix matTemplateToWorld, matWorldToTemplate, matEntityToWorld, matEntityToTemplate; - matTemplateToWorld.SetupMatrixOrgAngles( GetAbsOrigin(), GetAbsAngles() ); - matTemplateToWorld.InverseTR( matWorldToTemplate ); - matEntityToWorld.SetupMatrixOrgAngles( pEntity->GetAbsOrigin(), pEntity->GetAbsAngles() ); - MatrixMultiply( matWorldToTemplate, matEntityToWorld, matEntityToTemplate ); - - newTemplate.matEntityToTemplate = matEntityToTemplate; - m_hTemplates.AddToTail( newTemplate ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CPointTemplate::ShouldRemoveTemplateEntities( void ) -{ - return ( !(m_spawnflags & SF_POINTTEMPLATE_DONTREMOVETEMPLATEENTITIES) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CPointTemplate::GetNumTemplates( void ) -{ - return m_hTemplates.Count(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CPointTemplate::GetTemplateIndexForTemplate( int iTemplate ) -{ - Assert( iTemplate < m_hTemplates.Count() ); - return m_hTemplates[iTemplate].iTemplateIndex; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CPointTemplate::GetNumTemplateEntities( void ) -{ - return m_hTemplateEntities.Count(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseEntity *CPointTemplate::GetTemplateEntity( int iTemplateNumber ) -{ - Assert( iTemplateNumber < m_hTemplateEntities.Count() ); - - return m_hTemplateEntities[iTemplateNumber]; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointTemplate::PerformPrecache() -{ - // Go through all our templated map data and precache all the entities in it - int iTemplates = m_hTemplates.Count(); - if ( !iTemplates ) - { - Msg("Precache called on a point_template that has no templates: %s\n", STRING(GetEntityName()) ); - return; - } - - // Tell the template system we're about to start a new template - Templates_StartUniqueInstance(); - - //HierarchicalSpawn_t *pSpawnList = (HierarchicalSpawn_t*)stackalloc( iTemplates * sizeof(HierarchicalSpawn_t) ); - - int i; - for ( i = 0; i < iTemplates; i++ ) - { - //CBaseEntity *pEntity = NULL; - char *pMapData; - int iTemplateIndex = m_hTemplates[i].iTemplateIndex; - - // Some templates have Entity I/O connecting the entities within the template. - // Unique versions of these templates need to be created whenever they're instanced. - int nStringSize; - if ( AllowNameFixup() && Templates_IndexRequiresEntityIOFixup( iTemplateIndex ) ) - { - // This template requires instancing. - // Create a new mapdata block and ask the template system to fill it in with - // a unique version (with fixed Entity I/O connections). - pMapData = Templates_GetEntityIOFixedMapData( iTemplateIndex ); - - } - else - { - // Use the unmodified mapdata - pMapData = (char*)STRING( Templates_FindByIndex( iTemplateIndex ) ); - } - - nStringSize = Templates_GetStringSize( iTemplateIndex ); - - // Create the entity from the mapdata - MapEntity_PrecacheEntity( pMapData, nStringSize ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Spawn the entities I contain -// Input : &vecOrigin - -// &vecAngles - -// pEntities - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CPointTemplate::CreateInstance( const Vector &vecOrigin, const QAngle &vecAngles, CUtlVector *pEntities ) -{ - // Go through all our templated map data and spawn all the entities in it - int iTemplates = m_hTemplates.Count(); - if ( !iTemplates ) - { - Msg("CreateInstance called on a point_template that has no templates: %s\n", STRING(GetEntityName()) ); - return false; - } - - // Tell the template system we're about to start a new template - Templates_StartUniqueInstance(); - - HierarchicalSpawn_t *pSpawnList = (HierarchicalSpawn_t*)stackalloc( iTemplates * sizeof(HierarchicalSpawn_t) ); - - int i; - for ( i = 0; i < iTemplates; i++ ) - { - CBaseEntity *pEntity = NULL; - char *pMapData; - int iTemplateIndex = m_hTemplates[i].iTemplateIndex; - - // Some templates have Entity I/O connecting the entities within the template. - // Unique versions of these templates need to be created whenever they're instanced. - if ( AllowNameFixup() && Templates_IndexRequiresEntityIOFixup( iTemplateIndex ) ) - { - // This template requires instancing. - // Create a new mapdata block and ask the template system to fill it in with - // a unique version (with fixed Entity I/O connections). - pMapData = Templates_GetEntityIOFixedMapData( iTemplateIndex ); - } - else - { - // Use the unmodified mapdata - pMapData = (char*)STRING( Templates_FindByIndex( iTemplateIndex ) ); - } - - // Create the entity from the mapdata - MapEntity_ParseEntity( pEntity, pMapData, NULL ); - if ( pEntity == NULL ) - { - Msg("Failed to initialize templated entity with mapdata: %s\n", pMapData ); - return false; - } - - // Get a matrix that'll convert from world to the new local space - VMatrix matNewTemplateToWorld, matStoredLocalToWorld; - matNewTemplateToWorld.SetupMatrixOrgAngles( vecOrigin, vecAngles ); - MatrixMultiply( matNewTemplateToWorld, m_hTemplates[i].matEntityToTemplate, matStoredLocalToWorld ); - - // Get the world origin & angles from the stored local coordinates - Vector vecNewOrigin; - QAngle vecNewAngles; - vecNewOrigin = matStoredLocalToWorld.GetTranslation(); - MatrixToAngles( matStoredLocalToWorld, vecNewAngles ); - - // Set its origin & angles - pEntity->SetAbsOrigin( vecNewOrigin ); - pEntity->SetAbsAngles( vecNewAngles ); - - pSpawnList[i].m_pEntity = pEntity; - pSpawnList[i].m_nDepth = 0; - pSpawnList[i].m_pDeferredParent = NULL; - } - - SpawnHierarchicalList( iTemplates, pSpawnList, true ); - - for ( i = 0; i < iTemplates; ++i ) - { - if ( pSpawnList[i].m_pEntity ) - { - pEntities->AddToTail( pSpawnList[i].m_pEntity ); - } - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CPointTemplate::InputForceSpawn( inputdata_t &inputdata ) -{ - // Spawn our template - CUtlVector hNewEntities; - if ( !CreateInstance( GetAbsOrigin(), GetAbsAngles(), &hNewEntities ) ) - return; - - // Fire our output - m_pOutputOnSpawned.FireOutput( this, this ); -} diff --git a/game/server/point_template.h b/game/server/point_template.h deleted file mode 100644 index 22af53f8a..000000000 --- a/game/server/point_template.h +++ /dev/null @@ -1,72 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Point entity used to create templates out of other entities or groups of entities -// -//=============================================================================// - -#ifndef POINT_TEMPLATE_H -#define POINT_TEMPLATE_H -#ifdef _WIN32 -#pragma once -#endif - -#define MAX_NUM_TEMPLATES 16 - -struct template_t -{ - int iTemplateIndex; - VMatrix matEntityToTemplate; - - DECLARE_SIMPLE_DATADESC(); -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CPointTemplate : public CLogicalEntity -{ - DECLARE_CLASS( CPointTemplate, CLogicalEntity ); -public: - DECLARE_DATADESC(); - - virtual void Spawn( void ); - virtual void Precache(); - - // Template initialization - void StartBuildingTemplates( void ); - void FinishBuildingTemplates( void ); - - // Template Entity accessors - int GetNumTemplateEntities( void ); - CBaseEntity *GetTemplateEntity( int iTemplateNumber ); - void AddTemplate( CBaseEntity *pEntity, const char *pszMapData, int nLen ); - bool ShouldRemoveTemplateEntities( void ); - bool AllowNameFixup(); - - // Templates accessors - int GetNumTemplates( void ); - int GetTemplateIndexForTemplate( int iTemplate ); - - // Template instancing - bool CreateInstance( const Vector &vecOrigin, const QAngle &vecAngles, CUtlVector *pEntities ); - - // Inputs - void InputForceSpawn( inputdata_t &inputdata ); - - virtual void PerformPrecache(); - -private: - string_t m_iszTemplateEntityNames[MAX_NUM_TEMPLATES]; - - // List of map entities this template targets. Built inside our Spawn(). - // It's only valid between Spawn() & Activate(), because the map entity parsing - // code removes all the entities in it once it finishes turning them into templates. - CUtlVector< CBaseEntity * > m_hTemplateEntities; - - // List of templates, generated from our template entities. - CUtlVector< template_t > m_hTemplates; - - COutputEvent m_pOutputOnSpawned; -}; - -#endif // POINT_TEMPLATE_H diff --git a/game/server/pointanglesensor.cpp b/game/server/pointanglesensor.cpp deleted file mode 100644 index 8a66761f9..000000000 --- a/game/server/pointanglesensor.cpp +++ /dev/null @@ -1,562 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Used to fire events based on the orientation of a given entity. -// -// Looks at its target's angles every frame and fires an output if its -// target's forward vector points at a specified lookat entity for more -// than a specified length of time. -// -// It also fires an output whenever the target's angles change. -// -//=============================================================================// - -#include "cbase.h" -#include "entityinput.h" -#include "entityoutput.h" -#include "eventqueue.h" -#include "mathlib/mathlib.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SF_USE_TARGET_FACING (1<<0) // Use the target entity's direction instead of position - -class CPointAngleSensor : public CPointEntity -{ - DECLARE_CLASS(CPointAngleSensor, CPointEntity); -public: - - bool KeyValue(const char *szKeyName, const char *szValue); - void Activate(void); - void Spawn(void); - void Think(void); - - int DrawDebugTextOverlays(void); - -protected: - - void Enable(); - void Disable(); - - // Input handlers - void InputEnable(inputdata_t &inputdata); - void InputDisable(inputdata_t &inputdata); - void InputToggle(inputdata_t &inputdata); - void InputTest(inputdata_t &inputdata); - void InputSetTargetEntity(inputdata_t &inputdata); - - bool IsFacingWithinTolerance(CBaseEntity *pEntity, CBaseEntity *pTarget, float flTolerance, float *pflDot = NULL); - - bool m_bDisabled; // When disabled, we do not think or fire outputs. - string_t m_nLookAtName; // Name of the entity that the target must point at to fire the OnTrue output. - - EHANDLE m_hTargetEntity; // Entity whose angles are being monitored. - EHANDLE m_hLookAtEntity; // Entity that the target must look at to fire the OnTrue output. - - float m_flDuration; // Time in seconds for which the entity must point at the target. - float m_flDotTolerance; // Degrees of error allowed to satisfy the condition, expressed as a dot product. - float m_flFacingTime; // The time at which the target entity pointed at the lookat entity. - bool m_bFired; // Latches the output so it only fires once per true. - - // Outputs - COutputEvent m_OnFacingLookat; // Fired when the target points at the lookat entity. - COutputEvent m_OnNotFacingLookat; // Fired in response to a Test input if the target is not looking at the lookat entity. - COutputVector m_TargetDir; - COutputFloat m_FacingPercentage; // Normalize value representing how close the entity is to facing directly at the target - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS(point_anglesensor, CPointAngleSensor); - - -BEGIN_DATADESC(CPointAngleSensor) - - // Keys - DEFINE_KEYFIELD(m_bDisabled, FIELD_BOOLEAN, "StartDisabled"), - DEFINE_KEYFIELD(m_nLookAtName, FIELD_STRING, "lookatname"), - DEFINE_FIELD(m_hTargetEntity, FIELD_EHANDLE), - DEFINE_FIELD(m_hLookAtEntity, FIELD_EHANDLE), - DEFINE_KEYFIELD(m_flDuration, FIELD_FLOAT, "duration"), - DEFINE_FIELD(m_flDotTolerance, FIELD_FLOAT), - DEFINE_FIELD(m_flFacingTime, FIELD_TIME), - DEFINE_FIELD(m_bFired, FIELD_BOOLEAN), - - // Outputs - DEFINE_OUTPUT(m_OnFacingLookat, "OnFacingLookat"), - DEFINE_OUTPUT(m_OnNotFacingLookat, "OnNotFacingLookat"), - DEFINE_OUTPUT(m_TargetDir, "TargetDir"), - DEFINE_OUTPUT(m_FacingPercentage, "FacingPercentage"), - - // Inputs - DEFINE_INPUTFUNC(FIELD_VOID, "Enable", InputEnable), - DEFINE_INPUTFUNC(FIELD_VOID, "Disable", InputDisable), - DEFINE_INPUTFUNC(FIELD_VOID, "Toggle", InputToggle), - DEFINE_INPUTFUNC(FIELD_VOID, "Test", InputTest), - DEFINE_INPUTFUNC(FIELD_STRING, "SetTargetEntity", InputSetTargetEntity), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: Handles keyvalues that require special processing. -// Output : Returns true if handled, false if not. -//----------------------------------------------------------------------------- -bool CPointAngleSensor::KeyValue(const char *szKeyName, const char *szValue) -{ - if (FStrEq(szKeyName, "tolerance")) - { - float flTolerance = atof(szValue); - m_flDotTolerance = cos(DEG2RAD(flTolerance)); - } - else - { - return(BaseClass::KeyValue(szKeyName, szValue)); - } - - return(true); -} - - -//----------------------------------------------------------------------------- -// Purpose: Called when spawning after parsing keyvalues. -//----------------------------------------------------------------------------- -void CPointAngleSensor::Spawn(void) -{ - BaseClass::Spawn(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Called after all entities have spawned on new map or savegame load. -//----------------------------------------------------------------------------- -void CPointAngleSensor::Activate(void) -{ - BaseClass::Activate(); - - if (!m_hTargetEntity) - { - m_hTargetEntity = gEntList.FindEntityByName( NULL, m_target ); - } - - if (!m_hLookAtEntity && (m_nLookAtName != NULL_STRING)) - { - m_hLookAtEntity = gEntList.FindEntityByName( NULL, m_nLookAtName ); - if (!m_hLookAtEntity) - { - DevMsg(1, "Angle sensor '%s' could not find look at entity '%s'.\n", GetDebugName(), STRING(m_nLookAtName)); - } - } - - // It's okay to not have a look at entity, it just means we measure and output the angles - // of the target entity without testing them against the look at entity. - if (!m_bDisabled && m_hTargetEntity) - { - SetNextThink( gpGlobals->curtime ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Determines if one entity is facing within a given tolerance of another -// Input : pEntity - -// pTarget - -// flTolerance - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CPointAngleSensor::IsFacingWithinTolerance(CBaseEntity *pEntity, CBaseEntity *pTarget, float flTolerance, float *pflDot) -{ - if (pflDot) - { - *pflDot = 0; - } - - if ((pEntity == NULL) || (pTarget == NULL)) - { - return(false); - } - - Vector forward; - pEntity->GetVectors(&forward, NULL, NULL); - - Vector dir; - // Use either our position relative to the target, or the target's raw facing - if ( HasSpawnFlags( SF_USE_TARGET_FACING ) ) - { - pTarget->GetVectors(&dir, NULL, NULL); - } - else - { - dir = pTarget->GetAbsOrigin() - pEntity->GetAbsOrigin(); - VectorNormalize(dir); - } - - // - // Larger dot product corresponds to a smaller angle. - // - float flDot = dir.Dot(forward); - if (pflDot) - { - *pflDot = flDot; - } - - if (flDot >= m_flDotTolerance) - { - return(true); - } - - return(false); -} - - -//----------------------------------------------------------------------------- -// Purpose: Called every frame. -//----------------------------------------------------------------------------- -void CPointAngleSensor::Think(void) -{ - if (m_hTargetEntity != NULL) - { - Vector forward; - m_hTargetEntity->GetVectors(&forward, NULL, NULL); - m_TargetDir.Set(forward, this, this); - - if (m_hLookAtEntity != NULL) - { - // - // Check to see if the measure entity's forward vector has been within - // given tolerance of the target entity for the given period of time. - // - float flDot; - if (IsFacingWithinTolerance(m_hTargetEntity, m_hLookAtEntity, m_flDotTolerance, &flDot )) - { - if (!m_bFired) - { - if (!m_flFacingTime) - { - m_flFacingTime = gpGlobals->curtime; - } - - if (gpGlobals->curtime >= m_flFacingTime + m_flDuration) - { - m_OnFacingLookat.FireOutput(this, this); - m_bFired = true; - } - } - } - else - { - // Reset the fired state - if ( m_bFired ) - { - m_bFired = false; - } - - // Always reset the time when we've lost our facing - m_flFacingTime = 0; - } - - // Output the angle range we're in - float flPerc = RemapValClamped( flDot, 1.0f, m_flDotTolerance, 1.0f, 0.0f ); - m_FacingPercentage.Set( flPerc, this, this ); - } - - SetNextThink( gpGlobals->curtime ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for forcing an instantaneous test of the condition. -//----------------------------------------------------------------------------- -void CPointAngleSensor::InputTest(inputdata_t &inputdata) -{ - if (IsFacingWithinTolerance(m_hTargetEntity, m_hLookAtEntity, m_flDotTolerance)) - { - m_OnFacingLookat.FireOutput(inputdata.pActivator, this); - } - else - { - m_OnNotFacingLookat.FireOutput(inputdata.pActivator, this); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointAngleSensor::InputSetTargetEntity(inputdata_t &inputdata) -{ - if ((inputdata.value.String() == NULL) || (inputdata.value.StringID() == NULL_STRING) || (inputdata.value.String()[0] == '\0')) - { - m_target = NULL_STRING; - m_hTargetEntity = NULL; - SetNextThink( TICK_NEVER_THINK ); - } - else - { - m_target = AllocPooledString(inputdata.value.String()); - m_hTargetEntity = gEntList.FindEntityByName( NULL, m_target, NULL, inputdata.pActivator, inputdata.pCaller ); - if (!m_bDisabled && m_hTargetEntity) - { - SetNextThink( gpGlobals->curtime ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointAngleSensor::InputEnable(inputdata_t &inputdata) -{ - Enable(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointAngleSensor::InputDisable(inputdata_t &inputdata) -{ - Disable(); -} - - -//----------------------------------------------------------------------------- -// Purpose: I like separators between my functions. -//----------------------------------------------------------------------------- -void CPointAngleSensor::InputToggle(inputdata_t &inputdata) -{ - if (m_bDisabled) - { - Enable(); - } - else - { - Disable(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointAngleSensor::Enable() -{ - m_bDisabled = false; - if (m_hTargetEntity) - { - SetNextThink(gpGlobals->curtime); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointAngleSensor::Disable() -{ - m_bDisabled = true; - SetNextThink(TICK_NEVER_THINK); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CPointAngleSensor::DrawDebugTextOverlays(void) -{ - int nOffset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - float flDot; - bool bFacing = IsFacingWithinTolerance(m_hTargetEntity, m_hLookAtEntity, m_flDotTolerance, &flDot); - - char tempstr[512]; - Q_snprintf(tempstr, sizeof(tempstr), "delta ang (dot) : %.2f (%f)", RAD2DEG(acos(flDot)), flDot); - EntityText( nOffset, tempstr, 0); - nOffset++; - - Q_snprintf(tempstr, sizeof(tempstr), "tolerance ang (dot): %.2f (%f)", RAD2DEG(acos(m_flDotTolerance)), m_flDotTolerance); - EntityText( nOffset, tempstr, 0); - nOffset++; - - Q_snprintf(tempstr, sizeof(tempstr), "facing: %s", bFacing ? "yes" : "no"); - EntityText( nOffset, tempstr, 0); - nOffset++; - } - - return nOffset; -} - -// ==================================================================== -// Proximity sensor -// ==================================================================== - -#define SF_PROXIMITY_TEST_AGAINST_AXIS (1<<0) - -class CPointProximitySensor : public CPointEntity -{ - DECLARE_CLASS( CPointProximitySensor, CPointEntity ); - -public: - - virtual void Activate( void ); - -protected: - - void Think( void ); - void Enable( void ); - void Disable( void ); - - // Input handlers - void InputEnable(inputdata_t &inputdata); - void InputDisable(inputdata_t &inputdata); - void InputToggle(inputdata_t &inputdata); - void InputSetTargetEntity(inputdata_t &inputdata); - -private: - - bool m_bDisabled; // When disabled, we do not think or fire outputs. - EHANDLE m_hTargetEntity; // Entity whose angles are being monitored. - - COutputFloat m_Distance; - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( point_proximity_sensor, CPointProximitySensor ); - -BEGIN_DATADESC( CPointProximitySensor ) - - // Keys - DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ), - DEFINE_FIELD( m_hTargetEntity, FIELD_EHANDLE ), - - // Outputs - DEFINE_OUTPUT( m_Distance, "Distance"), - - // Inputs - DEFINE_INPUTFUNC(FIELD_VOID, "Enable", InputEnable), - DEFINE_INPUTFUNC(FIELD_VOID, "Disable", InputDisable), - DEFINE_INPUTFUNC(FIELD_VOID, "Toggle", InputToggle), - DEFINE_INPUTFUNC(FIELD_STRING, "SetTargetEntity", InputSetTargetEntity), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: Called after all entities have spawned on new map or savegame load. -//----------------------------------------------------------------------------- -void CPointProximitySensor::Activate( void ) -{ - BaseClass::Activate(); - - if ( m_hTargetEntity == NULL ) - { - m_hTargetEntity = gEntList.FindEntityByName( NULL, m_target ); - } - - if ( m_bDisabled == false && m_hTargetEntity != NULL ) - { - SetNextThink( gpGlobals->curtime ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointProximitySensor::InputSetTargetEntity(inputdata_t &inputdata) -{ - if ((inputdata.value.String() == NULL) || (inputdata.value.StringID() == NULL_STRING) || (inputdata.value.String()[0] == '\0')) - { - m_target = NULL_STRING; - m_hTargetEntity = NULL; - SetNextThink( TICK_NEVER_THINK ); - } - else - { - m_target = AllocPooledString(inputdata.value.String()); - m_hTargetEntity = gEntList.FindEntityByName( NULL, m_target, NULL, inputdata.pActivator, inputdata.pCaller ); - if (!m_bDisabled && m_hTargetEntity) - { - SetNextThink( gpGlobals->curtime ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointProximitySensor::InputEnable( inputdata_t &inputdata ) -{ - Enable(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointProximitySensor::InputDisable( inputdata_t &inputdata ) -{ - Disable(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointProximitySensor::InputToggle( inputdata_t &inputdata ) -{ - if ( m_bDisabled ) - { - Enable(); - } - else - { - Disable(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointProximitySensor::Enable( void ) -{ - m_bDisabled = false; - if ( m_hTargetEntity ) - { - SetNextThink( gpGlobals->curtime ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointProximitySensor::Disable( void ) -{ - m_bDisabled = true; - SetNextThink( TICK_NEVER_THINK ); -} - -//----------------------------------------------------------------------------- -// Purpose: Called every frame -//----------------------------------------------------------------------------- -void CPointProximitySensor::Think( void ) -{ - if ( m_hTargetEntity != NULL ) - { - Vector vecTestDir = ( m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin() ); - float flDist = VectorNormalize( vecTestDir ); - - // If we're only interested in the distance along a vector, modify the length the accomodate that - if ( HasSpawnFlags( SF_PROXIMITY_TEST_AGAINST_AXIS ) ) - { - Vector vecDir; - GetVectors( &vecDir, NULL, NULL ); - - float flDot = DotProduct( vecTestDir, vecDir ); - flDist *= fabs( flDot ); - } - - m_Distance.Set( flDist, this, this ); - SetNextThink( gpGlobals->curtime ); - } -} diff --git a/game/server/pointhurt.cpp b/game/server/pointhurt.cpp deleted file mode 100644 index a5528367c..000000000 --- a/game/server/pointhurt.cpp +++ /dev/null @@ -1,182 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements hurting point entity -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "entitylist.h" -#include "gamerules.h" -#include "basecombatcharacter.h" -#include "ammodef.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -const int SF_PHURT_START_ON = 1; - -class CPointHurt : public CPointEntity -{ - DECLARE_CLASS( CPointHurt, CPointEntity ); - -public: - void Spawn( void ); - void Precache( void ); - void HurtThink( void ); - - // Input handlers - void InputTurnOn(inputdata_t &inputdata); - void InputTurnOff(inputdata_t &inputdata); - void InputToggle(inputdata_t &inputdata); - void InputHurt(inputdata_t &inputdata); - - DECLARE_DATADESC(); - - int m_nDamage; - int m_bitsDamageType; - float m_flRadius; - float m_flDelay; - string_t m_strTarget; - EHANDLE m_pActivator; -}; - -BEGIN_DATADESC( CPointHurt ) - - DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "DamageRadius" ), - DEFINE_KEYFIELD( m_nDamage, FIELD_INTEGER, "Damage" ), - DEFINE_KEYFIELD( m_flDelay, FIELD_FLOAT, "DamageDelay" ), - DEFINE_KEYFIELD( m_bitsDamageType, FIELD_INTEGER, "DamageType" ), - DEFINE_KEYFIELD( m_strTarget, FIELD_STRING, "DamageTarget" ), - - // Function Pointers - DEFINE_FUNCTION( HurtThink ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - DEFINE_INPUTFUNC( FIELD_VOID, "Hurt", InputHurt ), - - DEFINE_FIELD( m_pActivator, FIELD_EHANDLE ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( point_hurt, CPointHurt ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointHurt::Spawn(void) -{ - SetThink( NULL ); - SetUse( NULL ); - - m_pActivator = NULL; - - if ( HasSpawnFlags( SF_PHURT_START_ON ) ) - { - SetThink( &CPointHurt::HurtThink ); - } - - SetNextThink( gpGlobals->curtime + 0.1f ); - - if ( m_flRadius <= 0.0f ) - { - m_flRadius = 128.0f; - } - - if ( m_nDamage <= 0 ) - { - m_nDamage = 2; - } - - if ( m_flDelay <= 0 ) - { - m_flDelay = 0.1f; - } - - Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointHurt::Precache( void ) -{ - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPointHurt::HurtThink( void ) -{ - if ( m_strTarget != NULL_STRING ) - { - CBaseEntity *pEnt = NULL; - - CTakeDamageInfo info( this, m_pActivator, m_nDamage, m_bitsDamageType ); - while ( ( pEnt = gEntList.FindEntityByName( pEnt, m_strTarget, NULL, m_pActivator ) ) != NULL ) - { - GuessDamageForce( &info, (pEnt->GetAbsOrigin() - GetAbsOrigin()), pEnt->GetAbsOrigin() ); - pEnt->TakeDamage( info ); - } - } - else - { - RadiusDamage( CTakeDamageInfo( this, this, m_nDamage, m_bitsDamageType ), GetAbsOrigin(), m_flRadius, CLASS_NONE, NULL ); - } - - SetNextThink( gpGlobals->curtime + m_flDelay ); -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for turning on the point hurt. -//----------------------------------------------------------------------------- -void CPointHurt::InputTurnOn( inputdata_t &data ) -{ - SetThink( &CPointHurt::HurtThink ); - - SetNextThink( gpGlobals->curtime + 0.1f ); - - m_pActivator = data.pActivator; -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for turning off the point hurt. -//----------------------------------------------------------------------------- -void CPointHurt::InputTurnOff( inputdata_t &data ) -{ - SetThink( NULL ); - - m_pActivator = data.pActivator; -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for toggling the on/off state of the point hurt. -//----------------------------------------------------------------------------- -void CPointHurt::InputToggle( inputdata_t &data ) -{ - m_pActivator = data.pActivator; - - if ( m_pfnThink == (void (CBaseEntity::*)())&CPointHurt::HurtThink ) - { - SetThink( NULL ); - } - else - { - SetThink( &CPointHurt::HurtThink ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for instantaneously hurting whatever is near us. -//----------------------------------------------------------------------------- -void CPointHurt::InputHurt( inputdata_t &data ) -{ - m_pActivator = data.pActivator; - - HurtThink(); -} - diff --git a/game/server/pointteleport.cpp b/game/server/pointteleport.cpp deleted file mode 100644 index da04dbc6b..000000000 --- a/game/server/pointteleport.cpp +++ /dev/null @@ -1,147 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Teleports a named entity to a given position and restores -// it's physics state -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - - -#include "in_buttons.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SF_TELEPORT_TO_SPAWN_POS 0x00000001 -#define SF_TELEPORT_INTO_DUCK 0x00000002 ///< episodic only: player should be ducked after this teleport - -class CPointTeleport : public CBaseEntity -{ - DECLARE_CLASS( CPointTeleport, CBaseEntity ); -public: - void Activate( void ); - - void InputTeleport( inputdata_t &inputdata ); - -private: - - bool EntityMayTeleport( CBaseEntity *pTarget ); - - Vector m_vSaveOrigin; - QAngle m_vSaveAngles; - - DECLARE_DATADESC(); -}; - - -LINK_ENTITY_TO_CLASS( point_teleport, CPointTeleport ); - - -BEGIN_DATADESC( CPointTeleport ) - - DEFINE_FIELD( m_vSaveOrigin, FIELD_VECTOR ), - DEFINE_FIELD( m_vSaveAngles, FIELD_VECTOR ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Teleport", InputTeleport ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTarget - -// Output : Returns true if the entity may be teleported -//----------------------------------------------------------------------------- -bool CPointTeleport::EntityMayTeleport( CBaseEntity *pTarget ) -{ - if ( pTarget->GetMoveParent() != NULL ) - { - // Passengers in a vehicle are allowed to teleport; their behavior handles it - CBaseCombatCharacter *pBCC = pTarget->MyCombatCharacterPointer(); - if ( pBCC == NULL || ( pBCC != NULL && pBCC->IsInAVehicle() == false ) ) - return false; - } - - return true; -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CPointTeleport::Activate( void ) -{ - // Start with our origin point - m_vSaveOrigin = GetAbsOrigin(); - m_vSaveAngles = GetAbsAngles(); - - // Save off the spawn position of the target if instructed to do so - if ( m_spawnflags & SF_TELEPORT_TO_SPAWN_POS ) - { - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, m_target ); - if ( pTarget ) - { - // If teleport object is in a movement hierarchy, remove it first - if ( EntityMayTeleport( pTarget ) ) - { - // Save the points - m_vSaveOrigin = pTarget->GetAbsOrigin(); - m_vSaveAngles = pTarget->GetAbsAngles(); - } - else - { - Warning("ERROR: (%s) can't teleport object (%s) as it has a parent (%s)!\n",GetDebugName(),pTarget->GetDebugName(),pTarget->GetMoveParent()->GetDebugName()); - BaseClass::Activate(); - return; - } - } - else - { - Warning("ERROR: (%s) target '%s' not found. Deleting.\n", GetDebugName(), STRING(m_target)); - UTIL_Remove( this ); - return; - } - } - - BaseClass::Activate(); -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CPointTeleport::InputTeleport( inputdata_t &inputdata ) -{ - // Attempt to find the entity in question - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, m_target, this, inputdata.pActivator, inputdata.pCaller ); - if ( pTarget == NULL ) - return; - - // If teleport object is in a movement hierarchy, remove it first - if ( EntityMayTeleport( pTarget ) == false ) - { - Warning("ERROR: (%s) can't teleport object (%s) as it has a parent (%s)!\n",GetDebugName(),pTarget->GetDebugName(),pTarget->GetMoveParent()->GetDebugName()); - return; - } - - // in episodic, we have a special spawn flag that forces Gordon into a duck -#ifdef HL2_EPISODIC - if ( (m_spawnflags & SF_TELEPORT_INTO_DUCK) && pTarget->IsPlayer() ) - { - CBasePlayer *pPlayer = ToBasePlayer( pTarget ); - if ( pPlayer != NULL ) - { - pPlayer->m_nButtons |= IN_DUCK; - pPlayer->AddFlag( FL_DUCKING ); - pPlayer->m_Local.m_bDucked = true; - pPlayer->m_Local.m_bDucking = true; - pPlayer->m_Local.m_flDucktime = 0.0f; - pPlayer->SetViewOffset( VEC_DUCK_VIEW ); - pPlayer->SetCollisionBounds( VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX ); - } - } -#endif - - pTarget->Teleport( &m_vSaveOrigin, &m_vSaveAngles, NULL ); -} - diff --git a/game/server/props.cpp b/game/server/props.cpp deleted file mode 100644 index f51f00698..000000000 --- a/game/server/props.cpp +++ /dev/null @@ -1,5942 +0,0 @@ -//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: static_prop - don't move, don't animate, don't do anything. -// physics_prop - move, take damage, but don't animate -// -//===========================================================================// - - -#include "cbase.h" -#include "BasePropDoor.h" -#include "ai_basenpc.h" -#include "npcevent.h" -#include "engine/IEngineSound.h" -#include "locksounds.h" -#include "filters.h" -#include "physics.h" -#include "vphysics_interface.h" -#include "entityoutput.h" -#include "vcollide_parse.h" -#include "studio.h" -#include "explode.h" -#include "utlrbtree.h" -#include "tier1/strtools.h" -#include "physics_impact_damage.h" -#include "KeyValues.h" -#include "filesystem.h" -#include "scriptevent.h" -#include "entityblocker.h" -#include "soundent.h" -#include "EntityFlame.h" -#include "game.h" -#include "physics_prop_ragdoll.h" -#include "decals.h" -#include "hierarchy.h" -#include "shareddefs.h" -#include "physobj.h" -#include "physics_npc_solver.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" -#include "datacache/imdlcache.h" -#include "doors.h" -#include "physics_collisionevent.h" -#include "GameStats.h" -#include "vehicle_base.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define DOOR_HARDWARE_GROUP 1 - -// Any barrel farther away than this is ignited rather than exploded. -#define PROP_EXPLOSION_IGNITE_RADIUS 32.0f - -// How many times to remind the player that supply crates can be broken -// (displayed when the supply crate is picked up) -#define NUM_SUPPLY_CRATE_HUD_HINTS 3 - -extern CBaseEntity *FindPickerEntity( CBasePlayer *pPlayer ); - - -ConVar g_debug_doors( "g_debug_doors", "0" ); -ConVar breakable_disable_gib_limit( "breakable_disable_gib_limit", "0" ); -ConVar breakable_multiplayer( "breakable_multiplayer", "1" ); - -// AI Interaction for being hit by a physics object -int g_interactionHitByPlayerThrownPhysObj = 0; -int g_interactionPlayerPuntedHeavyObject = 0; - -int g_ActiveGibCount = 0; -ConVar prop_active_gib_limit( "prop_active_gib_limit", "999999" ); -ConVar prop_active_gib_max_fade_time( "prop_active_gib_max_fade_time", "999999" ); -#define ACTIVE_GIB_LIMIT prop_active_gib_limit.GetInt() -#define ACTIVE_GIB_FADE prop_active_gib_max_fade_time.GetInt() - - -// Damage type modifiers for breakable objects. -ConVar func_breakdmg_bullet( "func_breakdmg_bullet", "0.5" ); -ConVar func_breakdmg_club( "func_breakdmg_club", "1.5" ); -ConVar func_breakdmg_explosive( "func_breakdmg_explosive", "1.25" ); - -ConVar sv_turbophysics( "sv_turbophysics", "0", FCVAR_REPLICATED, "Turns on turbo physics" ); - -#ifdef HL2_EPISODIC - #define PROP_FLARE_LIFETIME 30.0f - #define PROP_FLARE_IGNITE_SUBSTRACT 5.0f - CBaseEntity *CreateFlare( Vector vOrigin, QAngle Angles, CBaseEntity *pOwner, float flDuration ); - void KillFlare( CBaseEntity *pOwnerEntity, CBaseEntity *pEntity, float flKillTime ); -#endif - - -//----------------------------------------------------------------------------- -// Purpose: Breakable objects take different levels of damage based upon the damage type. -// This isn't contained by CBaseProp, because func_breakables use it as well. -//----------------------------------------------------------------------------- -float GetBreakableDamage( const CTakeDamageInfo &inputInfo, IBreakableWithPropData *pProp ) -{ - float flDamage = inputInfo.GetDamage(); - int iDmgType = inputInfo.GetDamageType(); - - // Bullet damage? - if ( iDmgType & DMG_BULLET ) - { - // Buckshot does double damage to breakables - if ( iDmgType & DMG_BUCKSHOT ) - { - if ( pProp ) - { - flDamage *= (pProp->GetDmgModBullet() * 2); - } - else - { - // Bullets do little damage to breakables - flDamage *= (func_breakdmg_bullet.GetFloat() * 2); - } - } - else - { - if ( pProp ) - { - flDamage *= pProp->GetDmgModBullet(); - } - else - { - // Bullets do little damage to breakables - flDamage *= func_breakdmg_bullet.GetFloat(); - } - } - } - - // Club damage? - if ( iDmgType & DMG_CLUB ) - { - if ( pProp ) - { - flDamage *= pProp->GetDmgModClub(); - } - else - { - // Club does extra damage - flDamage *= func_breakdmg_club.GetFloat(); - } - } - - // Explosive damage? - if ( iDmgType & DMG_BLAST ) - { - if ( pProp ) - { - flDamage *= pProp->GetDmgModExplosive(); - } - else - { - // Explosions do extra damage - flDamage *= func_breakdmg_explosive.GetFloat(); - } - } - - if ( (iDmgType & DMG_SLASH) && (iDmgType & DMG_CRUSH) ) - { - // Cut by a Ravenholm propeller trap - flDamage *= 10.0f; - } - - // Poison & other timebased damage types do no damage - if ( g_pGameRules->Damage_IsTimeBased( iDmgType ) ) - { - flDamage = 0; - } - - return flDamage; -} - -//============================================================================================================= -// BASE PROP -//============================================================================================================= -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseProp::Spawn( void ) -{ - char *szModel = (char *)STRING( GetModelName() ); - if (!szModel || !*szModel) - { - Warning( "prop at %.0f %.0f %0.f missing modelname\n", GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z ); - UTIL_Remove( this ); - return; - } - - PrecacheModel( szModel ); - Precache(); - SetModel( szModel ); - - // Load this prop's data from the propdata file - int iResult = ParsePropData(); - if ( !OverridePropdata() ) - { - if ( iResult == PARSE_FAILED_BAD_DATA ) - { - DevWarning( "%s at %.0f %.0f %0.f uses model %s, which has an invalid prop_data type. DELETED.\n", GetClassname(), GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z, szModel ); - UTIL_Remove( this ); - return; - } - else if ( iResult == PARSE_FAILED_NO_DATA ) - { - // If we don't have data, but we're a prop_physics, fail - if ( FClassnameIs( this, "prop_physics" ) ) - { - DevWarning( "%s at %.0f %.0f %0.f uses model %s, which has no propdata which means it must be used on a prop_static. DELETED.\n", GetClassname(), GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z, szModel ); - UTIL_Remove( this ); - return; - } - } - else if ( iResult == PARSE_SUCCEEDED ) - { - // If we have data, and we're not a physics prop, fail - if ( !dynamic_cast(this) ) - { - DevWarning( "%s at %.0f %.0f %0.f uses model %s, which has propdata which means that it be used on a prop_physics. DELETED.\n", GetClassname(), GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z, szModel ); - UTIL_Remove( this ); - return; - } - } - } - - SetMoveType( MOVETYPE_PUSH ); - m_takedamage = DAMAGE_NO; - SetNextThink( TICK_NEVER_THINK ); - - m_flAnimTime = gpGlobals->curtime; - m_flPlaybackRate = 0.0; - SetCycle( 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseProp::Precache( void ) -{ - if ( GetModelName() == NULL_STRING ) - { - Msg( "%s at (%.3f, %.3f, %.3f) has no model name!\n", GetClassname(), GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z ); - SetModelName( AllocPooledString( "models/error.mdl" ) ); - } - - PrecacheModel( STRING( GetModelName() ) ); - - PrecacheScriptSound( "Metal.SawbladeStick" ); - PrecacheScriptSound( "PropaneTank.Burst" ); - -#ifdef HL2_EPISODIC - UTIL_PrecacheOther( "env_flare" ); -#endif - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseProp::Activate( void ) -{ - BaseClass::Activate(); - - // Make sure mapmakers haven't used the wrong prop type. - if ( m_takedamage == DAMAGE_NO && m_iHealth != 0 ) - { - Warning("%s has a health specified in model '%s'. Use prop_physics or prop_dynamic instead.\n", GetClassname(), STRING(GetModelName()) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Handles keyvalues from the BSP. Called before spawning. -//----------------------------------------------------------------------------- -bool CBaseProp::KeyValue( const char *szKeyName, const char *szValue ) -{ - if ( FStrEq(szKeyName, "health") ) - { - // Only override props are allowed to override health. - if ( FClassnameIs( this, "prop_physics_override" ) || FClassnameIs( this, "prop_dynamic_override" ) ) - return BaseClass::KeyValue( szKeyName, szValue ); - - return true; - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Calculate whether this prop should block LOS or not -//----------------------------------------------------------------------------- -void CBaseProp::CalculateBlockLOS( void ) -{ - // We block LOS if: - // - One of our dimensions is >40 - // - Our other 2 dimensions are >30 - // By default, entities block LOS, so we only need to detect non-blockage - bool bFoundLarge = false; - Vector vecSize = CollisionProp()->OBBMaxs() - CollisionProp()->OBBMins(); - for ( int i = 0; i < 3; i++ ) - { - if ( vecSize[i] > 40 ) - { - bFoundLarge = true; - } - if ( vecSize[i] > 30 ) - continue; - - // Dimension smaller than 30. - SetBlocksLOS( false ); - return; - } - - if ( !bFoundLarge ) - { - // No dimension larger than 40 - SetBlocksLOS( false ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Parse this prop's data from the model, if it has a keyvalues section. -// Returns true only if this prop is using a model that has a prop_data section that's invalid. -//----------------------------------------------------------------------------- -int CBaseProp::ParsePropData( void ) -{ - KeyValues *modelKeyValues = new KeyValues(""); - if ( !modelKeyValues->LoadFromBuffer( modelinfo->GetModelName( GetModel() ), modelinfo->GetModelKeyValueText( GetModel() ) ) ) - { - modelKeyValues->deleteThis(); - return PARSE_FAILED_NO_DATA; - } - - // Do we have a props section? - KeyValues *pkvPropData = modelKeyValues->FindKey("prop_data"); - if ( !pkvPropData ) - { - modelKeyValues->deleteThis(); - return PARSE_FAILED_NO_DATA; - } - - int iResult = g_PropDataSystem.ParsePropFromKV( this, pkvPropData, modelKeyValues ); - modelKeyValues->deleteThis(); - return iResult; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseProp::DrawDebugGeometryOverlays( void ) -{ - BaseClass::DrawDebugGeometryOverlays(); - - if ( m_debugOverlays & OVERLAY_PROP_DEBUG ) - { - if ( m_takedamage == DAMAGE_NO ) - { - NDebugOverlay::EntityBounds(this, 255, 0, 0, 0, 0 ); - } - else if ( m_takedamage == DAMAGE_EVENTS_ONLY ) - { - NDebugOverlay::EntityBounds(this, 255, 255, 255, 0, 0 ); - } - else - { - // Remap health to green brightness - float flG = RemapVal( m_iHealth, 0, 100, 64, 255 ); - flG = clamp( flG, 0, 255 ); - NDebugOverlay::EntityBounds(this, 0, (int)flG, 0, 0, 0 ); - } - } -} - - -class CEnableMotionFixup : public CBaseEntity -{ - DECLARE_CLASS( CEnableMotionFixup, CBaseEntity ); -}; - -LINK_ENTITY_TO_CLASS( point_enable_motion_fixup, CEnableMotionFixup ); - -static const char *s_pFadeScaleThink = "FadeScaleThink"; -static const char *s_pPropAnimateThink = "PropAnimateThink"; - -void CBreakableProp::SetEnableMotionPosition( const Vector &position, const QAngle &angles ) -{ - ClearEnableMotionPosition(); - CBaseEntity *pFixup = CBaseEntity::Create( "point_enable_motion_fixup", position, angles, this ); - if ( pFixup ) - { - pFixup->SetParent( this ); - } -} - -CBaseEntity *CBreakableProp::FindEnableMotionFixup() -{ - CUtlVector list; - GetAllChildren( this, list ); - for ( int i = list.Count()-1; i >= 0; --i ) - { - if ( FClassnameIs( list[i], "point_enable_motion_fixup" ) ) - return list[i]; - } - - return NULL; -} - -bool CBreakableProp::GetEnableMotionPosition( Vector *pPosition, QAngle *pAngles ) -{ - CBaseEntity *pFixup = FindEnableMotionFixup(); - if ( !pFixup ) - return false; - *pPosition = pFixup->GetAbsOrigin(); - *pAngles = pFixup->GetAbsAngles(); - return true; -} - -void CBreakableProp::ClearEnableMotionPosition() -{ - CBaseEntity *pFixup = FindEnableMotionFixup(); - if ( pFixup ) - { - UnlinkFromParent( pFixup ); - UTIL_Remove( pFixup ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CBreakableProp::Ignite( float flFlameLifetime, bool bNPCOnly, float flSize, bool bCalledByLevelDesigner ) -{ - if( IsOnFire() ) - return; - - if( !HasInteraction( PROPINTER_FIRE_FLAMMABLE ) ) - return; - - BaseClass::Ignite( flFlameLifetime, bNPCOnly, flSize, bCalledByLevelDesigner ); - - if ( g_pGameRules->ShouldBurningPropsEmitLight() ) - { - GetEffectEntity()->AddEffects( EF_DIMLIGHT ); - } - - // Frighten AIs, just in case this is an exploding thing. - CSoundEnt::InsertSound( SOUND_DANGER, GetAbsOrigin(), 128, 1.0f, this, SOUNDENT_CHANNEL_REPEATED_DANGER ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CBreakableProp::HandleFirstCollisionInteractions( int index, gamevcollisionevent_t *pEvent ) -{ - if ( pEvent->pEntities[ !index ]->IsWorld() ) - { - if ( HasInteraction( PROPINTER_PHYSGUN_WORLD_STICK ) ) - { - HandleInteractionStick( index, pEvent ); - } - } - - if( HasInteraction( PROPINTER_PHYSGUN_FIRST_BREAK ) ) - { - // Looks like it's best to break by having the object damage itself. - CTakeDamageInfo info; - - info.SetDamage( m_iHealth ); - info.SetAttacker( this ); - info.SetInflictor( this ); - info.SetDamageType( DMG_GENERIC ); - - Vector vecPosition; - Vector vecVelocity; - - VPhysicsGetObject()->GetVelocity( &vecVelocity, NULL ); - VPhysicsGetObject()->GetPosition( &vecPosition, NULL ); - - info.SetDamageForce( vecVelocity ); - info.SetDamagePosition( vecPosition ); - - TakeDamage( info ); - return; - } - - if( HasInteraction( PROPINTER_PHYSGUN_FIRST_PAINT ) ) - { - IPhysicsObject *pObj = VPhysicsGetObject(); - - Vector vecPos; - pObj->GetPosition( &vecPos, NULL ); - - Vector vecVelocity = pEvent->preVelocity[0]; - VectorNormalize(vecVelocity); - - trace_t tr; - UTIL_TraceLine( vecPos, vecPos + (vecVelocity * 64), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.m_pEnt ) - { -#ifdef HL2_DLL - // Don't paintsplat friendlies - int iClassify = tr.m_pEnt->Classify(); - if ( iClassify != CLASS_PLAYER_ALLY_VITAL && iClassify != CLASS_PLAYER_ALLY && - iClassify != CLASS_CITIZEN_PASSIVE && iClassify != CLASS_CITIZEN_REBEL ) -#endif - { - switch( entindex() % 3 ) - { - case 0: - UTIL_DecalTrace( &tr, "PaintSplatBlue" ); - break; - - case 1: - UTIL_DecalTrace( &tr, "PaintSplatGreen" ); - break; - - case 2: - UTIL_DecalTrace( &tr, "PaintSplatPink" ); - break; - } - } - } - } - - if ( HasInteraction( PROPINTER_PHYSGUN_NOTIFY_CHILDREN ) ) - { - CUtlVector children; - GetAllChildren( this, children ); - for (int i = 0; i < children.Count(); i++ ) - { - CBaseEntity *pent = children.Element( i ); - - IParentPropInteraction *pPropInter = dynamic_cast( pent ); - if ( pPropInter ) - { - pPropInter->OnParentCollisionInteraction( COLLISIONINTER_PARENT_FIRST_IMPACT, index, pEvent ); - } - } - } -} - - -void CBreakableProp::CheckRemoveRagdolls() -{ - if ( HasSpawnFlags( SF_PHYSPROP_HAS_ATTACHED_RAGDOLLS ) ) - { - DetachAttachedRagdollsForEntity( this ); - RemoveSpawnFlags( SF_PHYSPROP_HAS_ATTACHED_RAGDOLLS ); - } -} -//----------------------------------------------------------------------------- -// Purpose: Handle special physgun interactions -// Input : index - -// *pEvent - -//----------------------------------------------------------------------------- -void CPhysicsProp::HandleAnyCollisionInteractions( int index, gamevcollisionevent_t *pEvent ) -{ - // If we're supposed to impale, and we've hit an NPC, impale it - if ( HasInteraction( PROPINTER_PHYSGUN_FIRST_IMPALE ) ) - { - Vector vel = pEvent->preVelocity[index]; - - Vector forward; - QAngle angImpaleForward; - if ( GetPropDataAngles( "impale_forward", angImpaleForward ) ) - { - Vector vecImpaleForward; - AngleVectors( angImpaleForward, &vecImpaleForward ); - VectorRotate( vecImpaleForward, EntityToWorldTransform(), forward ); - } - else - { - GetVectors( &forward, NULL, NULL ); - } - - float speed = DotProduct( forward, vel ); - if ( speed < 1000.0f ) - { - // not going to stick, so remove any ragdolls we've got - CheckRemoveRagdolls(); - return; - } - CBaseEntity *pHitEntity = pEvent->pEntities[!index]; - if ( pHitEntity->IsWorld() ) - { - Vector normal; - float sign = index ? -1.0f : 1.0f; - pEvent->pInternalData->GetSurfaceNormal( normal ); - float dot = DotProduct( forward, normal ); - if ( (sign*dot) < DOT_45DEGREE ) - return; - // Impale sticks to the wall if we hit end on - HandleInteractionStick( index, pEvent ); - } - else if ( pHitEntity->MyNPCPointer() ) - { - CAI_BaseNPC *pNPC = pHitEntity->MyNPCPointer(); - IPhysicsObject *pObj = VPhysicsGetObject(); - - // do not impale NPCs if the impaler is friendly - CBasePlayer *pAttacker = HasPhysicsAttacker( 25.0f ); - if (pAttacker && pNPC->IRelationType( pAttacker ) == D_LI) - { - return; - } - - Vector vecPos; - pObj->GetPosition( &vecPos, NULL ); - - // Find the bone for the hitbox we hit - trace_t tr; - UTIL_TraceLine( vecPos, vecPos + pEvent->preVelocity[index] * 1.5, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - Vector vecImpalePos = tr.endpos; - int iBone = -1; - if ( tr.hitbox ) - { - Vector vecBonePos; - QAngle vecBoneAngles; - iBone = pNPC->GetHitboxBone( tr.hitbox ); - pNPC->GetBonePosition( iBone, vecBonePos, vecBoneAngles ); - - Teleport( &vecBonePos, NULL, NULL ); - vecImpalePos = vecBonePos; - } - - // Kill the NPC and make an attached ragdoll - pEvent->pInternalData->GetContactPoint( vecImpalePos ); - CBaseEntity *pRagdoll = CreateServerRagdollAttached( pNPC, vec3_origin, -1, COLLISION_GROUP_INTERACTIVE_DEBRIS, pObj, this, 0, vecImpalePos, iBone, vec3_origin ); - if ( pRagdoll ) - { - Vector vecVelocity = pEvent->preVelocity[index] * pObj->GetMass(); - PhysCallbackImpulse( pObj, vecVelocity, vec3_origin ); - UTIL_Remove( pNPC ); - AddSpawnFlags( SF_PHYSPROP_HAS_ATTACHED_RAGDOLLS ); - } - } - } -} - - -void CBreakableProp::StickAtPosition( const Vector &stickPosition, const Vector &savePosition, const QAngle &saveAngles ) -{ - if ( !VPhysicsGetObject()->IsMotionEnabled() ) - return; - - EmitSound("Metal.SawbladeStick"); - Teleport( &stickPosition, NULL, NULL ); - SetEnableMotionPosition( savePosition, saveAngles ); // this uses hierarchy, so it must be set after teleport - - VPhysicsGetObject()->EnableMotion( false ); - AddSpawnFlags( SF_PHYSPROP_ENABLE_ON_PHYSCANNON ); - SetCollisionGroup( COLLISION_GROUP_DEBRIS ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -// *pEvent - -//----------------------------------------------------------------------------- -void CBreakableProp::HandleInteractionStick( int index, gamevcollisionevent_t *pEvent ) -{ - Vector vecDir = pEvent->preVelocity[ index ]; - float speed = VectorNormalize( vecDir ); - - // Make sure the object is travelling fast enough to stick. - if( speed > 1000.0f ) - { - Vector position; - QAngle angles; - VPhysicsGetObject()->GetPosition( &position, &angles ); - - Vector vecNormal; - pEvent->pInternalData->GetSurfaceNormal( vecNormal ); - - // we want the normal that points away from this object - if ( index == 1 ) - { - vecNormal *= -1.0f; - } - float flDot = DotProduct( vecDir, vecNormal ); - - // Make sure the object isn't hitting the world at too sharp an angle. - if( flDot > 0.3 ) - { - // Finally, inhibit sticking in metal, grates, sky, or anything else that doesn't make a sound. - const surfacedata_t *psurf = physprops->GetSurfaceData( pEvent->surfaceProps[!index] ); - - if (psurf->game.material != CHAR_TEX_METAL && psurf->game.material != CHAR_TEX_GRATE && psurf->game.material != 'X' ) - { - Vector savePosition = position; - - Vector vecEmbed = pEvent->preVelocity[ index ]; - VectorNormalize( vecEmbed ); - vecEmbed *= 8; - - position += vecEmbed; - g_PostSimulationQueue.QueueCall( this, &CBreakableProp::StickAtPosition, position, savePosition, angles ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Turn on prop debugging mode -//----------------------------------------------------------------------------- -void CC_Prop_Debug( void ) -{ - // Toggle the prop debug bit on all props - for ( CBaseEntity *pEntity = gEntList.FirstEnt(); pEntity != NULL; pEntity = gEntList.NextEnt(pEntity) ) - { - CBaseProp *pProp = dynamic_cast(pEntity); - if ( pProp ) - { - if ( pProp->m_debugOverlays & OVERLAY_PROP_DEBUG ) - { - pProp->m_debugOverlays &= ~OVERLAY_PROP_DEBUG; - } - else - { - pProp->m_debugOverlays |= OVERLAY_PROP_DEBUG; - } - } - } -} -static ConCommand prop_debug("prop_debug", CC_Prop_Debug, "Toggle prop debug mode. If on, props will show colorcoded bounding boxes. Red means ignore all damage. White means respond physically to damage but never break. Green maps health in the range of 100 down to 1.", FCVAR_CHEAT); - -//============================================================================================================= -// BREAKABLE PROPS -//============================================================================================================= -IMPLEMENT_SERVERCLASS_ST(CBreakableProp, DT_BreakableProp) -END_SEND_TABLE() - -BEGIN_DATADESC( CBreakableProp ) - - DEFINE_KEYFIELD( m_explodeDamage, FIELD_FLOAT, "ExplodeDamage"), - DEFINE_KEYFIELD( m_explodeRadius, FIELD_FLOAT, "ExplodeRadius"), - DEFINE_KEYFIELD( m_iMinHealthDmg, FIELD_INTEGER, "minhealthdmg" ), - DEFINE_FIELD( m_createTick, FIELD_INTEGER ), - DEFINE_FIELD( m_hBreaker, FIELD_EHANDLE ), - DEFINE_KEYFIELD( m_PerformanceMode, FIELD_INTEGER, "PerformanceMode" ), - - DEFINE_FIELD( m_flDmgModBullet, FIELD_FLOAT ), - DEFINE_FIELD( m_flDmgModClub, FIELD_FLOAT ), - DEFINE_FIELD( m_flDmgModExplosive, FIELD_FLOAT ), - DEFINE_FIELD( m_iszPhysicsDamageTableName, FIELD_STRING ), - DEFINE_FIELD( m_iszBreakableModel, FIELD_STRING ), - DEFINE_FIELD( m_iBreakableSkin, FIELD_INTEGER ), - DEFINE_FIELD( m_iBreakableCount, FIELD_INTEGER ), - DEFINE_FIELD( m_iMaxBreakableSize, FIELD_INTEGER ), - DEFINE_FIELD( m_iszBasePropData, FIELD_STRING ), - DEFINE_FIELD( m_iInteractions, FIELD_INTEGER ), - DEFINE_FIELD( m_iNumBreakableChunks, FIELD_INTEGER ), - DEFINE_FIELD( m_nPhysgunState, FIELD_CHARACTER ), - DEFINE_KEYFIELD( m_iszPuntSound, FIELD_STRING, "puntsound" ), - - DEFINE_KEYFIELD( m_flPressureDelay, FIELD_FLOAT, "PressureDelay" ), - DEFINE_FIELD( m_preferredCarryAngles, FIELD_VECTOR ), - DEFINE_FIELD( m_flDefaultFadeScale, FIELD_FLOAT ), - DEFINE_FIELD( m_bUsePuntSound, FIELD_BOOLEAN ), - // DEFINE_FIELD( m_mpBreakMode, mp_break_t ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Break", InputBreak ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetHealth", InputSetHealth ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "AddHealth", InputAddHealth ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "RemoveHealth", InputRemoveHealth ), - DEFINE_INPUT( m_impactEnergyScale, FIELD_FLOAT, "physdamagescale" ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnablePhyscannonPickup", InputEnablePhyscannonPickup ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisablePhyscannonPickup", InputDisablePhyscannonPickup ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnablePuntSound", InputEnablePuntSound ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisablePuntSound", InputDisablePuntSound ), - - // Outputs - DEFINE_OUTPUT( m_OnBreak, "OnBreak" ), - DEFINE_OUTPUT( m_OnHealthChanged, "OnHealthChanged" ), - DEFINE_OUTPUT( m_OnTakeDamage, "OnTakeDamage" ), - DEFINE_OUTPUT( m_OnPhysCannonDetach, "OnPhysCannonDetach" ), - DEFINE_OUTPUT( m_OnPhysCannonAnimatePreStarted, "OnPhysCannonAnimatePreStarted" ), - DEFINE_OUTPUT( m_OnPhysCannonAnimatePullStarted, "OnPhysCannonAnimatePullStarted" ), - DEFINE_OUTPUT( m_OnPhysCannonAnimatePostStarted, "OnPhysCannonAnimatePostStarted" ), - DEFINE_OUTPUT( m_OnPhysCannonPullAnimFinished, "OnPhysCannonPullAnimFinished" ), - - // Function Pointers - DEFINE_THINKFUNC( BreakThink ), - DEFINE_THINKFUNC( AnimateThink ), - DEFINE_THINKFUNC( RampToDefaultFadeScale ), - DEFINE_ENTITYFUNC( BreakablePropTouch ), - - // Physics Influence - DEFINE_FIELD( m_hPhysicsAttacker, FIELD_EHANDLE ), - DEFINE_FIELD( m_flLastPhysicsInfluenceTime, FIELD_TIME ), - - DEFINE_FIELD( m_bOriginalBlockLOS, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bBlockLOSSetByPropData, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bIsWalkableSetByPropData, FIELD_BOOLEAN ), - - // Damage - DEFINE_FIELD( m_hLastAttacker, FIELD_EHANDLE ), - DEFINE_FIELD( m_hFlareEnt, FIELD_EHANDLE ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Constructor: -//----------------------------------------------------------------------------- -CBreakableProp::CBreakableProp() -{ - m_fadeMinDist = -1; - m_fadeMaxDist = 0; - m_flFadeScale = 1; - m_flDefaultFadeScale = 1; - m_mpBreakMode = MULTIPLAYER_BREAK_DEFAULT; - - // This defaults to on. Most times mapmakers won't specify a punt sound to play. - m_bUsePuntSound = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBreakableProp::Spawn() -{ - // Starts out as the default fade scale value - m_flDefaultFadeScale = m_flFadeScale; - - // Initialize damage modifiers. Must be done before baseclass spawn. - m_flDmgModBullet = 1.0; - m_flDmgModClub = 1.0; - m_flDmgModExplosive = 1.0; - - //jmd: I am guessing that the call to Spawn will set any flags that should be set anyway; this - //clears flags we don't want (specifically the FL_ONFIRE for explosive barrels in HL2MP)] -#ifdef HL2MP - ClearFlags(); -#endif - - BaseClass::Spawn(); - - if ( IsMarkedForDeletion() ) - return; - - CStudioHdr *pStudioHdr = GetModelPtr( ); - if ( pStudioHdr->flags() & STUDIOHDR_FLAGS_NO_FORCED_FADE ) - { - DisableAutoFade(); - } - else - { - m_flFadeScale = m_flDefaultFadeScale; - } - - // If we have no custom breakable chunks, see if we're breaking into generic ones - if ( !m_iNumBreakableChunks ) - { - IBreakableWithPropData *pBreakableInterface = assert_cast(this); - if ( pBreakableInterface->GetBreakableModel() != NULL_STRING && pBreakableInterface->GetBreakableCount() ) - { - m_iNumBreakableChunks = pBreakableInterface->GetBreakableCount(); - } - } - - // Setup takedamage based upon the health we parsed earlier, and our interactions - if ( ( m_iHealth == 0 ) || - ( !m_iNumBreakableChunks && - !HasInteraction( PROPINTER_PHYSGUN_BREAK_EXPLODE ) && - !HasInteraction( PROPINTER_PHYSGUN_FIRST_BREAK ) && - !HasInteraction( PROPINTER_FIRE_FLAMMABLE ) && - !HasInteraction( PROPINTER_FIRE_IGNITE_HALFHEALTH ) && - !HasInteraction( PROPINTER_FIRE_EXPLOSIVE_RESIST ) ) ) - { - m_iHealth = 0; - m_takedamage = DAMAGE_EVENTS_ONLY; - } - else - { - m_takedamage = DAMAGE_YES; - - if( g_pGameRules->GetAutoAimMode() == AUTOAIM_ON_CONSOLE ) - { - if ( HasInteraction( PROPINTER_PHYSGUN_BREAK_EXPLODE ) || - HasInteraction( PROPINTER_FIRE_IGNITE_HALFHEALTH ) ) - { - // Exploding barrels, exploding gas cans - AddFlag( FL_AIMTARGET ); - } - } - } - - m_iMaxHealth = ( m_iHealth > 0 ) ? m_iHealth : 1; - - m_createTick = gpGlobals->tickcount; - if ( m_impactEnergyScale == 0 ) - { - m_impactEnergyScale = 0.1f; - } - - m_preferredCarryAngles = QAngle( -5, 0, 0 ); - - // The presence of this activity causes us to have to detach it before it can be grabbed. - if ( SelectWeightedSequence( ACT_PHYSCANNON_ANIMATE ) != ACTIVITY_NOT_AVAILABLE ) - { - m_nPhysgunState = PHYSGUN_ANIMATE_ON_PULL; - } - else if ( SelectWeightedSequence( ACT_PHYSCANNON_DETACH ) != ACTIVITY_NOT_AVAILABLE ) - { - m_nPhysgunState = PHYSGUN_MUST_BE_DETACHED; - } - else - { - m_nPhysgunState = PHYSGUN_CAN_BE_GRABBED; - } - - m_hLastAttacker = NULL; - - m_hBreaker = NULL; - - SetTouch( &CBreakableProp::BreakablePropTouch ); -} - - -//----------------------------------------------------------------------------- -// Disable auto fading under dx7 or when level fades are specified -//----------------------------------------------------------------------------- -void CBreakableProp::DisableAutoFade() -{ - m_flFadeScale = 0; - m_flDefaultFadeScale = 0; -} - - -//----------------------------------------------------------------------------- -// Copy fade from another breakable. -//----------------------------------------------------------------------------- -void CBreakableProp::CopyFadeFrom( CBreakableProp *pSource ) -{ - m_flDefaultFadeScale = pSource->m_flDefaultFadeScale; - m_flFadeScale = pSource->m_flFadeScale; - if ( m_flFadeScale != m_flDefaultFadeScale ) - { - float flNextThink = pSource->GetNextThink( s_pFadeScaleThink ); - if ( flNextThink < gpGlobals->curtime + TICK_INTERVAL ) - { - flNextThink = gpGlobals->curtime + TICK_INTERVAL; - } - - SetContextThink( &CBreakableProp::RampToDefaultFadeScale, flNextThink, s_pFadeScaleThink ); - } -} - - -//----------------------------------------------------------------------------- -// Make physcannonable, or not -//----------------------------------------------------------------------------- -void CBreakableProp::InputEnablePhyscannonPickup( inputdata_t &inputdata ) -{ - RemoveEFlags( EFL_NO_PHYSCANNON_INTERACTION ); -} - -void CBreakableProp::InputDisablePhyscannonPickup( inputdata_t &inputdata ) -{ - AddEFlags( EFL_NO_PHYSCANNON_INTERACTION ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOther - -//----------------------------------------------------------------------------- -void CBreakableProp::BreakablePropTouch( CBaseEntity *pOther ) -{ - if ( HasSpawnFlags( SF_PHYSPROP_TOUCH ) ) - { - // can be broken when run into - float flDamage = pOther->GetSmoothedVelocity().Length() * 0.01; - - if ( flDamage >= m_iHealth ) - { - // Make sure we can take damage - m_takedamage = DAMAGE_YES; - OnTakeDamage( CTakeDamageInfo( pOther, pOther, flDamage, DMG_CRUSH ) ); - - // do a little damage to player if we broke glass or computer - CTakeDamageInfo info( pOther, pOther, flDamage/4, DMG_SLASH ); - CalculateMeleeDamageForce( &info, (pOther->GetAbsOrigin() - GetAbsOrigin()), GetAbsOrigin() ); - pOther->TakeDamage( info ); - } - } - - if ( HasSpawnFlags( SF_PHYSPROP_PRESSURE ) && pOther->GetGroundEntity() == this ) - { - // can be broken when stood upon - // play creaking sound here. - // DamageSound(); - - m_hBreaker = pOther; - - if ( m_pfnThink != (void (CBaseEntity::*)())&CBreakableProp::BreakThink ) - { - SetThink( &CBreakableProp::BreakThink ); - //SetTouch( NULL ); - - // Add optional delay - SetNextThink( gpGlobals->curtime + m_flPressureDelay ); - } - } - -#ifdef HL2_EPISODIC - if ( m_hFlareEnt ) - { - CAI_BaseNPC *pNPC = pOther->MyNPCPointer(); - - if ( pNPC && pNPC->AllowedToIgnite() && pNPC->IsOnFire() == false ) - { - pNPC->Ignite( 25.0f ); - KillFlare( this, m_hFlareEnt, PROP_FLARE_IGNITE_SUBSTRACT ); - IGameEvent *event = gameeventmanager->CreateEvent( "flare_ignite_npc" ); - if ( event ) - { - event->SetInt( "entindex", pNPC->entindex() ); - gameeventmanager->FireEvent( event ); - } - } - } -#endif -} - -//----------------------------------------------------------------------------- -// UNDONE: Time stamp the object's creation so that an explosion or something doesn't break the parent object -// and then break the children who spawn afterward ? -// Explosions should use entities in box before they start to do damage. Make sure nothing traverses the list -// in a way that would hose this. -int CBreakableProp::OnTakeDamage( const CTakeDamageInfo &inputInfo ) -{ - CTakeDamageInfo info = inputInfo; - - // If attacker can't do at least the min required damage to us, don't take any damage from them - if ( info.GetDamage() < m_iMinHealthDmg ) - return 0; - - if (!PassesDamageFilter( info )) - { - return 1; - } - - if( info.GetAttacker() && info.GetAttacker()->MyCombatCharacterPointer() ) - { - m_hLastAttacker.Set( info.GetAttacker() ); - } - - float flPropDamage = GetBreakableDamage( info, assert_cast(this) ); - info.SetDamage( flPropDamage ); - - // UNDONE: Do this? -#if 0 - // Make a shard noise each time func breakable is hit. - // Don't play shard noise if being burned. - // Don't play shard noise if cbreakable actually died. - if ( ( bitsDamageType & DMG_BURN ) == false ) - { - DamageSound(); - } -#endif - - // don't take damage on the same frame you were created - // (avoids a set of explosions progressively vaporizing a compound breakable) - if ( m_createTick == (unsigned int)gpGlobals->tickcount ) - { - int saveFlags = m_takedamage; - m_takedamage = DAMAGE_EVENTS_ONLY; - int ret = BaseClass::OnTakeDamage( info ); - m_takedamage = saveFlags; - - return ret; - } - - // Ignore fire damage from other flames if I'm already on fire. - // (i.e., only let the flames attached to me damage me) - if( IsOnFire() && (inputInfo.GetDamageType() & DMG_BURN) && !(inputInfo.GetDamageType() & DMG_DIRECT) ) - { - return 0; - } - - bool bDeadly = info.GetDamage() >= m_iHealth; - - if( bDeadly && (info.GetDamageType() & DMG_BLAST) && HasInteraction( PROPINTER_FIRE_EXPLOSIVE_RESIST ) && info.GetInflictor() ) - { - // This explosion would kill me, but I have a special interaction with explosions. - - float flDist = ( WorldSpaceCenter() - info.GetInflictor()->WorldSpaceCenter() ).Length(); - - // I'm going to burn for a bit instead of exploding right now. - float flBurnTime; - if( flDist >= PROP_EXPLOSION_IGNITE_RADIUS ) - { - // I'm far from the blast. Ignite and burn for several seconds. - const float MAX_BLAST_DIST = 256.0f; - - // Just clamp distance. - if( flDist > MAX_BLAST_DIST ) - flDist = MAX_BLAST_DIST; - - float flFactor; - flFactor = flDist / MAX_BLAST_DIST; - const float MAX_BURN_TIME = 5.0f; - flBurnTime = MAX( 0.5, MAX_BURN_TIME * flFactor ); - flBurnTime += random->RandomFloat( 0, 0.5 ); - } - else - { - // Very near the explosion. explode almost immediately. - flBurnTime = random->RandomFloat( 0.1, 0.2 ); - } - - // Change my health so that I burn for flBurnTime seconds. - float flIdealHealth = fpmin( m_iHealth, FLAME_DIRECT_DAMAGE_PER_SEC * flBurnTime ); - float flIdealDamage = m_iHealth - flIdealHealth; - - // Scale the damage to do ideal damage. - info.ScaleDamage( flIdealDamage / info.GetDamage() ); - - // Re-evaluate the deadly - bDeadly = info.GetDamage() >= m_iHealth; - } - - if( !bDeadly && (info.GetDamageType() & DMG_BLAST) ) - { - Ignite( random->RandomFloat( 10, 15 ), false ); - } - else if( !bDeadly && (info.GetDamageType() & DMG_BURN) ) - { - // Ignite if burned, and flammable (the Ignite() function takes care of all of this). - Ignite( random->RandomFloat( 10, 15 ), false ); - } - else if( !bDeadly && (info.GetDamageType() & DMG_BULLET) ) - { - if( HasInteraction( PROPINTER_FIRE_IGNITE_HALFHEALTH ) ) - { - if( (m_iHealth - info.GetDamage()) <= m_iMaxHealth / 2 && !IsOnFire() ) - { - // Bump back up to full health so it burns longer. Magically getting health back isn't - // a big problem because if this item takes damage again whilst burning, it will break. - m_iHealth = m_iMaxHealth; - Ignite( random->RandomFloat( 10, 15 ), false ); - } - else if( IsOnFire() ) - { - // Explode right now! - info.ScaleDamage( m_iHealth / info.GetDamage() ); - } - } - } - - int ret = BaseClass::OnTakeDamage( info ); - - // Output the new health as a percentage of max health [0..1] - float flRatio = clamp( (float)m_iHealth / (float)m_iMaxHealth, 0, 1 ); - m_OnHealthChanged.Set( flRatio, info.GetAttacker(), this ); - m_OnTakeDamage.FireOutput( info.GetAttacker(), this ); - - return ret; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBreakableProp::Event_Killed( const CTakeDamageInfo &info ) -{ - IPhysicsObject *pPhysics = VPhysicsGetObject(); - if ( pPhysics && !pPhysics->IsMoveable() ) - { - pPhysics->EnableMotion( true ); - VPhysicsTakeDamage( info ); - } - Break( info.GetInflictor(), info ); - BaseClass::Event_Killed( info ); -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for breaking the breakable immediately. -//----------------------------------------------------------------------------- -void CBreakableProp::InputBreak( inputdata_t &inputdata ) -{ - CTakeDamageInfo info; - info.SetAttacker( this ); - Break( inputdata.pActivator, info ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for adding to the breakable's health. -// Input : Integer health points to add. -//----------------------------------------------------------------------------- -void CBreakableProp::InputAddHealth( inputdata_t &inputdata ) -{ - UpdateHealth( m_iHealth + inputdata.value.Int(), inputdata.pActivator ); -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler for removing health from the breakable. -// Input : Integer health points to remove. -//----------------------------------------------------------------------------- -void CBreakableProp::InputRemoveHealth( inputdata_t &inputdata ) -{ - UpdateHealth( m_iHealth - inputdata.value.Int(), inputdata.pActivator ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for setting the breakable's health. -//----------------------------------------------------------------------------- -void CBreakableProp::InputSetHealth( inputdata_t &inputdata ) -{ - UpdateHealth( inputdata.value.Int(), inputdata.pActivator ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Choke point for changes to breakable health. Ensures outputs are fired. -// Input : iNewHealth - -// pActivator - -// Output : Returns true if the breakable survived, false if it died (broke). -//----------------------------------------------------------------------------- -bool CBreakableProp::UpdateHealth( int iNewHealth, CBaseEntity *pActivator ) -{ - if ( iNewHealth != m_iHealth ) - { - m_iHealth = iNewHealth; - - if ( m_iMaxHealth == 0 ) - { - Assert( false ); - m_iMaxHealth = 1; - } - - // Output the new health as a percentage of max health [0..1] - float flRatio = clamp( (float)m_iHealth / (float)m_iMaxHealth, 0, 1 ); - m_OnHealthChanged.Set( flRatio, pActivator, this ); - - if ( m_iHealth <= 0 ) - { - CTakeDamageInfo info; - info.SetAttacker( this ); - Break( pActivator, info ); - - return false; - } - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Advance a ripped-off-animation frame -//----------------------------------------------------------------------------- -bool CBreakableProp::OnAttemptPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) -{ - if ( m_nPhysgunState == PHYSGUN_CAN_BE_GRABBED ) - return true; - if ( m_nPhysgunState == PHYSGUN_ANIMATE_FINISHED ) - return false; - - if ( m_nPhysgunState == PHYSGUN_MUST_BE_DETACHED ) - { - // A punt advances - ResetSequence( SelectWeightedSequence( ACT_PHYSCANNON_DETACH ) ); - SetPlaybackRate( 0.0f ); - ResetClientsideFrame(); - m_nPhysgunState = PHYSGUN_IS_DETACHING; - return false; - } - - if ( m_nPhysgunState == PHYSGUN_ANIMATE_ON_PULL ) - { - // Animation-requiring detachments ignore punts - if ( reason == PUNTED_BY_CANNON ) - return false; - - // Do we have a pre sequence? - int iSequence = SelectWeightedSequence( ACT_PHYSCANNON_ANIMATE_PRE ); - if ( iSequence != ACTIVITY_NOT_AVAILABLE ) - { - m_nPhysgunState = PHYSGUN_ANIMATE_IS_PRE_ANIMATING; - SetContextThink( &CBreakableProp::AnimateThink, gpGlobals->curtime + 0.1, s_pPropAnimateThink ); - - m_OnPhysCannonAnimatePreStarted.FireOutput( NULL,this ); - } - else - { - // Go straight to the animate sequence - iSequence = SelectWeightedSequence( ACT_PHYSCANNON_ANIMATE ); - m_nPhysgunState = PHYSGUN_ANIMATE_IS_ANIMATING; - - m_OnPhysCannonAnimatePullStarted.FireOutput( NULL,this ); - } - - ResetSequence( iSequence ); - SetPlaybackRate( 1.0f ); - ResetClientsideFrame(); - } - - // If we're running PRE or POST ANIMATE sequences, wait for them to be done - if ( m_nPhysgunState == PHYSGUN_ANIMATE_IS_PRE_ANIMATING || - m_nPhysgunState == PHYSGUN_ANIMATE_IS_POST_ANIMATING ) - return false; - - if ( m_nPhysgunState == PHYSGUN_ANIMATE_IS_ANIMATING ) - { - // Animation-requiring detachments ignore punts - if ( reason == PUNTED_BY_CANNON ) - return false; - - StudioFrameAdvanceManual( gpGlobals->frametime ); - DispatchAnimEvents( this ); - - if ( IsActivityFinished() ) - { - int iSequence = SelectWeightedSequence( ACT_PHYSCANNON_ANIMATE_POST ); - if ( iSequence != ACTIVITY_NOT_AVAILABLE ) - { - m_nPhysgunState = PHYSGUN_ANIMATE_IS_POST_ANIMATING; - SetContextThink( &CBreakableProp::AnimateThink, gpGlobals->curtime + 0.1, s_pPropAnimateThink ); - ResetSequence( iSequence ); - SetPlaybackRate( 1.0f ); - ResetClientsideFrame(); - - m_OnPhysCannonAnimatePostStarted.FireOutput( NULL,this ); - } - else - { - m_nPhysgunState = PHYSGUN_ANIMATE_FINISHED; - m_OnPhysCannonPullAnimFinished.FireOutput( NULL,this ); - } - } - } - else - { - // Here, we're grabbing it. If we try to punt it, advance frames by quite a bit. - StudioFrameAdvanceManual( (reason == PICKED_UP_BY_CANNON) ? gpGlobals->frametime : 0.5f ); - ResetClientsideFrame(); - DispatchAnimEvents( this ); - - if ( IsActivityFinished() ) - { - // We're done, reset the playback rate. - SetPlaybackRate( 1.0f ); - m_nPhysgunState = PHYSGUN_CAN_BE_GRABBED; - m_OnPhysCannonDetach.FireOutput( NULL,this ); - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Physics Attacker -//----------------------------------------------------------------------------- -void CBreakableProp::AnimateThink( void ) -{ - if ( m_nPhysgunState == PHYSGUN_ANIMATE_IS_PRE_ANIMATING || m_nPhysgunState == PHYSGUN_ANIMATE_IS_POST_ANIMATING ) - { - StudioFrameAdvanceManual( 0.1 ); - DispatchAnimEvents( this ); - SetNextThink( gpGlobals->curtime + 0.1, s_pPropAnimateThink ); - - if ( IsActivityFinished() ) - { - if ( m_nPhysgunState == PHYSGUN_ANIMATE_IS_PRE_ANIMATING ) - { - // Start the animate sequence - m_nPhysgunState = PHYSGUN_ANIMATE_IS_ANIMATING; - - ResetSequence( SelectWeightedSequence( ACT_PHYSCANNON_ANIMATE ) ); - SetPlaybackRate( 1.0f ); - ResetClientsideFrame(); - - m_OnPhysCannonAnimatePullStarted.FireOutput( NULL,this ); - } - else - { - m_nPhysgunState = PHYSGUN_ANIMATE_FINISHED; - m_OnPhysCannonPullAnimFinished.FireOutput( NULL,this ); - } - - SetContextThink( NULL, 0, s_pPropAnimateThink ); - } - } -} - -//----------------------------------------------------------------------------- -// Physics Attacker -//----------------------------------------------------------------------------- -void CBreakableProp::SetPhysicsAttacker( CBasePlayer *pEntity, float flTime ) -{ - m_hPhysicsAttacker = pEntity; - m_flLastPhysicsInfluenceTime = flTime; -} - - -//----------------------------------------------------------------------------- -// Prevents fade scale from happening -//----------------------------------------------------------------------------- -void CBreakableProp::ForceFadeScaleToAlwaysVisible() -{ - m_flFadeScale = 0.0f; - SetContextThink( NULL, gpGlobals->curtime, s_pFadeScaleThink ); -} - - -void CBreakableProp::RampToDefaultFadeScale() -{ - m_flFadeScale += m_flDefaultFadeScale * TICK_INTERVAL / 2.0f; - if ( m_flFadeScale >= m_flDefaultFadeScale ) - { - m_flFadeScale = m_flDefaultFadeScale; - SetContextThink( NULL, gpGlobals->curtime, s_pFadeScaleThink ); - } - else - { - SetContextThink( &CBreakableProp::RampToDefaultFadeScale, gpGlobals->curtime + TICK_INTERVAL, s_pFadeScaleThink ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Keep track of physgun influence -//----------------------------------------------------------------------------- -void CBreakableProp::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) -{ - // Make sure held objects are always visible - if ( reason == PICKED_UP_BY_CANNON ) - { - ForceFadeScaleToAlwaysVisible(); - } - else - { - SetContextThink( &CBreakableProp::RampToDefaultFadeScale, gpGlobals->curtime + 2.0f, s_pFadeScaleThink ); - } - - if( reason == PUNTED_BY_CANNON ) - { - PlayPuntSound(); - } - - if ( IsX360() ) - { - if( reason != PUNTED_BY_CANNON && (pPhysGunUser->m_nNumCrateHudHints < NUM_SUPPLY_CRATE_HUD_HINTS) ) - { - if( FClassnameIs( this, "item_item_crate") ) - { - pPhysGunUser->m_nNumCrateHudHints++; - UTIL_HudHintText( pPhysGunUser, "#Valve_Hint_Hold_ItemCrate" ); - } - } - } - - SetPhysicsAttacker( pPhysGunUser, gpGlobals->curtime ); - - // Store original BlockLOS, and disable BlockLOS - m_bOriginalBlockLOS = BlocksLOS(); - SetBlocksLOS( false ); - -#ifdef HL2_EPISODIC - if ( HasInteraction( PROPINTER_PHYSGUN_CREATE_FLARE ) ) - { - CreateFlare( PROP_FLARE_LIFETIME ); - } -#endif -} - - -#ifdef HL2_EPISODIC -//----------------------------------------------------------------------------- -// Purpose: Create a flare at the attachment point -//----------------------------------------------------------------------------- -void CBreakableProp::CreateFlare( float flLifetime ) -{ - // Create the flare - CBaseEntity *pFlare = ::CreateFlare( GetAbsOrigin(), GetAbsAngles(), this, flLifetime ); - if ( pFlare ) - { - int iAttachment = LookupAttachment( "fuse" ); - - Vector vOrigin; - GetAttachment( iAttachment, vOrigin ); - - pFlare->SetMoveType( MOVETYPE_NONE ); - pFlare->SetSolid( SOLID_NONE ); - pFlare->SetRenderMode( kRenderTransAlpha ); - pFlare->SetRenderColorA( 1 ); - pFlare->SetLocalOrigin( vOrigin ); - pFlare->SetParent( this, iAttachment ); - RemoveInteraction( PROPINTER_PHYSGUN_CREATE_FLARE ); - m_hFlareEnt = pFlare; - - SetThink( &CBreakable::SUB_FadeOut ); - SetNextThink( gpGlobals->curtime + flLifetime + 5.0f ); - - m_nSkin = 1; - - AddEntityToDarknessCheck( pFlare ); - - AddEffects( EF_NOSHADOW ); - } -} -#endif // HL2_EPISODIC - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBreakableProp::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ) -{ - SetContextThink( &CBreakableProp::RampToDefaultFadeScale, gpGlobals->curtime + 2.0f, s_pFadeScaleThink ); - - SetPhysicsAttacker( pPhysGunUser, gpGlobals->curtime ); - - if( Reason == static_cast(PUNTED_BY_CANNON) ) - { - PlayPuntSound(); - } - - // Restore original BlockLOS - SetBlocksLOS( m_bOriginalBlockLOS ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -AngularImpulse CBreakableProp::PhysGunLaunchAngularImpulse() -{ - if( HasInteraction( PROPINTER_PHYSGUN_LAUNCH_SPIN_NONE ) || HasInteraction( PROPINTER_PHYSGUN_LAUNCH_SPIN_Z ) ) - { - // Don't add in random angular impulse if this object is supposed to spin in a specific way. - AngularImpulse ang( 0, 0, 0 ); - return ang; - } - - return CDefaultPlayerPickupVPhysics::PhysGunLaunchAngularImpulse(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CBasePlayer *CBreakableProp::HasPhysicsAttacker( float dt ) -{ - if (gpGlobals->curtime - dt <= m_flLastPhysicsInfluenceTime) - { - return m_hPhysicsAttacker; - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBreakableProp::BreakThink( void ) -{ - CTakeDamageInfo info; - info.SetAttacker( this ); - Break( m_hBreaker, info ); -} - -//----------------------------------------------------------------------------- -// Purpose: Play the sound (if any) that I'm supposed to play when punted. -//----------------------------------------------------------------------------- -void CBreakableProp::PlayPuntSound() -{ - if( !m_bUsePuntSound ) - return; - - if( m_iszPuntSound == NULL_STRING ) - return; - - EmitSound( STRING(m_iszPuntSound) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBreakableProp::Precache() -{ - m_iNumBreakableChunks = PropBreakablePrecacheAll( GetModelName() ); - - if( m_iszPuntSound != NULL_STRING ) - { - PrecacheScriptSound( STRING(m_iszPuntSound) ); - } - - BaseClass::Precache(); -} - -// Get the root physics object from which all broken pieces will -// derive their positions and velocities -IPhysicsObject *CBreakableProp::GetRootPhysicsObjectForBreak() -{ - return VPhysicsGetObject(); -} - -void CBreakableProp::Break( CBaseEntity *pBreaker, const CTakeDamageInfo &info ) -{ - const char *pModelName = STRING( GetModelName() ); - if ( pModelName && Q_stristr( pModelName, "crate" ) ) - { - bool bSmashed = false; - if ( pBreaker && pBreaker->IsPlayer() ) - { - bSmashed = true; - } - else if ( m_hPhysicsAttacker.Get() && m_hPhysicsAttacker->IsPlayer() ) - { - bSmashed = true; - } - else if ( pBreaker && dynamic_cast< CPropVehicleDriveable * >( pBreaker ) ) - { - CPropVehicleDriveable *veh = static_cast< CPropVehicleDriveable * >( pBreaker ); - CBaseEntity *driver = veh->GetDriver(); - if ( driver && driver->IsPlayer() ) - { - bSmashed = true; - } - } - if ( bSmashed ) - { - gamestats->Event_CrateSmashed(); - } - } - - IGameEvent * event = gameeventmanager->CreateEvent( "break_prop" ); - - if ( event ) - { - if ( pBreaker && pBreaker->IsPlayer() ) - { - event->SetInt( "userid", ToBasePlayer( pBreaker )->GetUserID() ); - } - else - { - event->SetInt( "userid", 0 ); - } - event->SetInt( "entindex", entindex() ); - gameeventmanager->FireEvent( event ); - } - - m_takedamage = DAMAGE_NO; - m_OnBreak.FireOutput( pBreaker, this ); - - Vector velocity; - AngularImpulse angVelocity; - IPhysicsObject *pPhysics = GetRootPhysicsObjectForBreak(); - - Vector origin; - QAngle angles; - AddSolidFlags( FSOLID_NOT_SOLID ); - if ( pPhysics ) - { - pPhysics->GetVelocity( &velocity, &angVelocity ); - pPhysics->GetPosition( &origin, &angles ); - pPhysics->RecheckCollisionFilter(); - } - else - { - velocity = GetAbsVelocity(); - QAngleToAngularImpulse( GetLocalAngularVelocity(), angVelocity ); - origin = GetAbsOrigin(); - angles = GetAbsAngles(); - } - - PhysBreakSound( this, VPhysicsGetObject(), GetAbsOrigin() ); - - bool bExploded = false; - - CBaseEntity *pAttacker = info.GetAttacker(); - if ( m_hLastAttacker ) - { - // Pass along the person who made this explosive breakable explode. - // This way the player allies can get immunity from barrels exploded by the player. - pAttacker = m_hLastAttacker; - } - else if( m_hPhysicsAttacker ) - { - // If I have a physics attacker and was influenced in the last 2 seconds, - // Make the attacker my physics attacker. This helps protect citizens from dying - // in the explosion of a physics object that was thrown by the player's physgun - // and exploded on impact. - if( gpGlobals->curtime - m_flLastPhysicsInfluenceTime <= 2.0f ) - { - pAttacker = m_hPhysicsAttacker; - } - } - - if ( m_explodeDamage > 0 || m_explodeRadius > 0 ) - { - if( HasInteraction( PROPINTER_PHYSGUN_BREAK_EXPLODE ) ) - { - ExplosionCreate( WorldSpaceCenter(), angles, pAttacker, (int)m_explodeDamage, (int)m_explodeRadius, - SF_ENVEXPLOSION_NOSPARKS | SF_ENVEXPLOSION_NODLIGHTS | SF_ENVEXPLOSION_NOSMOKE | SF_ENVEXPLOSION_SURFACEONLY | SF_ENVEXPLOSION_NOSOUND, - 0.0f, this ); - EmitSound("PropaneTank.Burst"); - } - else - { - ExplosionCreate( WorldSpaceCenter(), angles, pAttacker, (int)m_explodeDamage, (int)m_explodeRadius, - SF_ENVEXPLOSION_NOSPARKS | SF_ENVEXPLOSION_NODLIGHTS | SF_ENVEXPLOSION_NOSMOKE | SF_ENVEXPLOSION_SURFACEONLY, - 0.0f, this ); - } - - bExploded = true; - } - - // Allow derived classes to emit special things - OnBreak( velocity, angVelocity, pBreaker ); - - breakablepropparams_t params( origin, angles, velocity, angVelocity ); - params.impactEnergyScale = m_impactEnergyScale; - params.defCollisionGroup = GetCollisionGroup(); - if ( params.defCollisionGroup == COLLISION_GROUP_NONE ) - { - // don't automatically make anything COLLISION_GROUP_NONE or it will - // collide with debris being ejected by breaking - params.defCollisionGroup = COLLISION_GROUP_INTERACTIVE; - } - - params.defBurstScale = 100; - // in multiplayer spawn break models as clientside temp ents - if ( gpGlobals->maxClients > 1 && breakable_multiplayer.GetBool() ) - { - CPASFilter filter( WorldSpaceCenter() ); - - Vector velocity; velocity.Init(); - - if ( pPhysics ) - pPhysics->GetVelocity( &velocity, NULL ); - - switch ( GetMultiplayerBreakMode() ) - { - case MULTIPLAYER_BREAK_DEFAULT: // default is to break client-side - case MULTIPLAYER_BREAK_CLIENTSIDE: - te->PhysicsProp( filter, -1, GetModelIndex(), m_nSkin, GetAbsOrigin(), GetAbsAngles(), velocity, true, GetEffects() ); - break; - case MULTIPLAYER_BREAK_SERVERSIDE: // server-side break - if ( m_PerformanceMode != PM_NO_GIBS || breakable_disable_gib_limit.GetBool() ) - { - PropBreakableCreateAll( GetModelIndex(), pPhysics, params, this, -1, ( m_PerformanceMode == PM_FULL_GIBS ), false ); - } - break; - case MULTIPLAYER_BREAK_BOTH: // pieces break from both dlls - te->PhysicsProp( filter, -1, GetModelIndex(), m_nSkin, GetAbsOrigin(), GetAbsAngles(), velocity, true, GetEffects() ); - if ( m_PerformanceMode != PM_NO_GIBS || breakable_disable_gib_limit.GetBool() ) - { - PropBreakableCreateAll( GetModelIndex(), pPhysics, params, this, -1, ( m_PerformanceMode == PM_FULL_GIBS ), false ); - } - break; - } - } - // no damage/damage force? set a burst of 100 for some movement - else if ( m_PerformanceMode != PM_NO_GIBS || breakable_disable_gib_limit.GetBool() ) - { - PropBreakableCreateAll( GetModelIndex(), pPhysics, params, this, -1, ( m_PerformanceMode == PM_FULL_GIBS ) ); - } - - if( HasInteraction( PROPINTER_PHYSGUN_BREAK_EXPLODE ) ) - { - if ( bExploded == false ) - { - ExplosionCreate( origin, angles, pAttacker, 1, (int)m_explodeRadius, - SF_ENVEXPLOSION_NOSPARKS | SF_ENVEXPLOSION_NODLIGHTS | SF_ENVEXPLOSION_NOSMOKE, 0.0f, this ); - } - - // Find and ignite all NPC's within the radius - CBaseEntity *pEntity = NULL; - for ( CEntitySphereQuery sphere( origin, m_explodeRadius ); ( pEntity = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() ) - { - if( pEntity && pEntity->MyCombatCharacterPointer() ) - { - // Check damage filters so we don't ignite friendlies - if ( pEntity->PassesDamageFilter( info ) ) - { - pEntity->MyCombatCharacterPointer()->Ignite( 30 ); - } - } - } - } - -#ifndef HL2MP - UTIL_Remove( this ); -#endif -} - - -//============================================================================================================= -// DYNAMIC PROPS -//============================================================================================================= -LINK_ENTITY_TO_CLASS( dynamic_prop, CDynamicProp ); -LINK_ENTITY_TO_CLASS( prop_dynamic, CDynamicProp ); -LINK_ENTITY_TO_CLASS( prop_dynamic_override, CDynamicProp ); - -BEGIN_DATADESC( CDynamicProp ) - - // Fields - DEFINE_KEYFIELD( m_iszDefaultAnim, FIELD_STRING, "DefaultAnim"), - DEFINE_FIELD( m_iGoalSequence, FIELD_INTEGER ), - DEFINE_FIELD( m_iTransitionDirection, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_bRandomAnimator, FIELD_BOOLEAN, "RandomAnimation"), - DEFINE_FIELD( m_flNextRandAnim, FIELD_TIME ), - DEFINE_KEYFIELD( m_flMinRandAnimTime, FIELD_FLOAT, "MinAnimTime"), - DEFINE_KEYFIELD( m_flMaxRandAnimTime, FIELD_FLOAT, "MaxAnimTime"), - DEFINE_KEYFIELD( m_bStartDisabled, FIELD_BOOLEAN, "StartDisabled" ), - DEFINE_FIELD( m_bUseHitboxesForRenderBox, FIELD_BOOLEAN ), - DEFINE_FIELD( m_nPendingSequence, FIELD_SHORT ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_STRING, "SetAnimation", InputSetAnimation ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetDefaultAnimation", InputSetDefaultAnimation ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputTurnOff ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnableCollision", InputEnableCollision ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableCollision", InputDisableCollision ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetPlaybackRate", InputSetPlaybackRate ), - - // Outputs - DEFINE_OUTPUT( m_pOutputAnimBegun, "OnAnimationBegun" ), - DEFINE_OUTPUT( m_pOutputAnimOver, "OnAnimationDone" ), - - // Function Pointers - DEFINE_THINKFUNC( AnimThink ), - - DEFINE_EMBEDDED( m_BoneFollowerManager ), - -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST(CDynamicProp, DT_DynamicProp) - SendPropBool( SENDINFO( m_bUseHitboxesForRenderBox ) ), -END_SEND_TABLE() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CDynamicProp::CDynamicProp() -{ - m_nPendingSequence = -1; - if ( g_pGameRules->IsMultiplayer() ) - { - UseClientSideAnimation(); - } - m_iGoalSequence = -1; -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CDynamicProp::Spawn( ) -{ - // Condense classname's to one, except for "prop_dynamic_override" - if ( FClassnameIs( this, "dynamic_prop" ) ) - { - SetClassname( "prop_dynamic" ); - } - - // If the prop is not-solid, the bounding box needs to be - // OBB to correctly surround the prop as it rotates. - // Check the classname so we don't mess with doors & other derived classes. - if ( GetSolid() == SOLID_NONE && FClassnameIs( this, "prop_dynamic" ) ) - { - SetSolid( SOLID_OBB ); - AddSolidFlags( FSOLID_NOT_SOLID ); - } - - BaseClass::Spawn(); - - if ( IsMarkedForDeletion() ) - return; - - // Now condense all classnames to one - if ( FClassnameIs( this, "dynamic_prop" ) || FClassnameIs( this, "prop_dynamic_override" ) ) - { - SetClassname("prop_dynamic"); - } - - AddFlag( FL_STATICPROP ); - - if ( m_bRandomAnimator || ( m_iszDefaultAnim != NULL_STRING ) ) - { - RemoveFlag( FL_STATICPROP ); - - if ( m_bRandomAnimator ) - { - SetThink( &CDynamicProp::AnimThink ); - m_flNextRandAnim = gpGlobals->curtime + random->RandomFloat( m_flMinRandAnimTime, m_flMaxRandAnimTime ); - SetNextThink( gpGlobals->curtime + m_flNextRandAnim + 0.1 ); - } - else - { - PropSetAnim( STRING( m_iszDefaultAnim ) ); - } - } - - CreateVPhysics(); - - BoneFollowerHierarchyChanged(); - - if( m_bStartDisabled ) - { - AddEffects( EF_NODRAW ); - } - - if ( !PropDataOverrodeBlockLOS() ) - { - CalculateBlockLOS(); - } - - m_bUseHitboxesForRenderBox = HasSpawnFlags( SF_DYNAMICPROP_USEHITBOX_FOR_RENDERBOX ); - - if ( HasSpawnFlags( SF_DYNAMICPROP_DISABLE_COLLISION ) ) - { - AddSolidFlags( FSOLID_NOT_SOLID ); - } - - //m_debugOverlays |= OVERLAY_ABSBOX_BIT; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDynamicProp::OnRestore( void ) -{ - BaseClass::OnRestore(); - - BoneFollowerHierarchyChanged(); -} - -void CDynamicProp::SetParent( CBaseEntity *pNewParent, int iAttachment ) -{ - BaseClass::SetParent(pNewParent, iAttachment); - BoneFollowerHierarchyChanged(); -} - -// Call this when creating bone followers or changing hierarchy to make sure the bone followers get updated when hierarchy changes -void CDynamicProp::BoneFollowerHierarchyChanged() -{ - // If we have bone followers and we're parented to something, we need to constantly update our bone followers - if ( m_BoneFollowerManager.GetNumBoneFollowers() && GetParent() ) - { - WatchPositionChanges(this, this); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDynamicProp::OverridePropdata( void ) -{ - return ( FClassnameIs(this, "prop_dynamic_override" ) ); -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -bool CDynamicProp::CreateVPhysics( void ) -{ - if ( GetSolid() == SOLID_NONE || ((GetSolidFlags() & FSOLID_NOT_SOLID) && HasSpawnFlags(SF_DYNAMICPROP_NO_VPHYSICS))) - return true; - - CreateBoneFollowers(); - - if ( m_BoneFollowerManager.GetNumBoneFollowers() ) - { - if ( GetSolidFlags() & FSOLID_NOT_SOLID ) - { - // Already non-solid? Must need bone followers for some other reason - // like needing to attach constraints to this object - for ( int i = 0; i < m_BoneFollowerManager.GetNumBoneFollowers(); i++ ) - { - CBaseEntity *pFollower = m_BoneFollowerManager.GetBoneFollower(i)->hFollower; - if ( pFollower ) - { - pFollower->AddSolidFlags(FSOLID_NOT_SOLID); - } - } - - } - // If our collision is through bone followers, we want to be non-solid - AddSolidFlags( FSOLID_NOT_SOLID ); - // add these for the client, FSOLID_NOT_SOLID should keep it out of the testCollision code - // except in the case of TraceEntity() which the client does for impact effects - AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST ); - return true; - } - else - { - VPhysicsInitStatic(); - } - return true; -} - -void CDynamicProp::CreateBoneFollowers() -{ - // already created bone followers? Don't do so again. - if ( m_BoneFollowerManager.GetNumBoneFollowers() ) - return; - - KeyValues *modelKeyValues = new KeyValues(""); - if ( modelKeyValues->LoadFromBuffer( modelinfo->GetModelName( GetModel() ), modelinfo->GetModelKeyValueText( GetModel() ) ) ) - { - // Do we have a bone follower section? - KeyValues *pkvBoneFollowers = modelKeyValues->FindKey("bone_followers"); - if ( pkvBoneFollowers ) - { - // Loop through the list and create the bone followers - KeyValues *pBone = pkvBoneFollowers->GetFirstSubKey(); - while ( pBone ) - { - // Add it to the list - const char *pBoneName = pBone->GetString(); - m_BoneFollowerManager.AddBoneFollower( this, pBoneName ); - - pBone = pBone->GetNextKey(); - } - } - - modelKeyValues->deleteThis(); - } - - // if we got here, we don't have a bone follower section, but if we have a ragdoll - // go ahead and create default bone followers for it - if ( m_BoneFollowerManager.GetNumBoneFollowers() == 0 ) - { - vcollide_t *pCollide = modelinfo->GetVCollide( GetModelIndex() ); - if ( pCollide && pCollide->solidCount > 1 ) - { - CreateBoneFollowersFromRagdoll(this, &m_BoneFollowerManager, pCollide); - } - } -} - - -bool CDynamicProp::TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ) -{ - if ( IsSolidFlagSet(FSOLID_NOT_SOLID) ) - { - // if this entity is marked non-solid and custom test it must have bone followers - if ( IsSolidFlagSet( FSOLID_CUSTOMBOXTEST ) && IsSolidFlagSet( FSOLID_CUSTOMRAYTEST )) - { - for ( int i = 0; i < m_BoneFollowerManager.GetNumBoneFollowers(); i++ ) - { - CBaseEntity *pEntity = m_BoneFollowerManager.GetBoneFollower(i)->hFollower; - if ( pEntity && pEntity->TestCollision(ray, mask, trace) ) - return true; - } - } - } - return false; -} - - -IPhysicsObject *CDynamicProp::GetRootPhysicsObjectForBreak() -{ - if ( m_BoneFollowerManager.GetNumBoneFollowers() ) - { - physfollower_t *pFollower = m_BoneFollowerManager.GetBoneFollower(0); - CBaseEntity *pFollowerEntity = pFollower->hFollower; - if ( pFollowerEntity ) - { - return pFollowerEntity->VPhysicsGetObject(); - } - } - - return BaseClass::GetRootPhysicsObjectForBreak(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDynamicProp::UpdateOnRemove( void ) -{ - m_BoneFollowerManager.DestroyBoneFollowers(); - BaseClass::UpdateOnRemove(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CDynamicProp::HandleAnimEvent( animevent_t *pEvent ) -{ - switch( pEvent->event ) - { - case SCRIPT_EVENT_FIRE_INPUT: - { - variant_t emptyVariant; - this->AcceptInput( pEvent->options, this, this, emptyVariant, 0 ); - return; - } - - case SCRIPT_EVENT_SOUND: - { - EmitSound( pEvent->options ); - break; - } - - default: - { - break; - } - } - - BaseClass::HandleAnimEvent( pEvent ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDynamicProp::NotifyPositionChanged( CBaseEntity *pEntity ) -{ - Assert(pEntity==this); - m_BoneFollowerManager.UpdateBoneFollowers(this); -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CDynamicProp::AnimThink( void ) -{ - if ( m_nPendingSequence != -1 ) - { - FinishSetSequence( m_nPendingSequence ); - m_nPendingSequence = -1; - } - - if ( m_bRandomAnimator && m_flNextRandAnim < gpGlobals->curtime ) - { - ResetSequence( SelectWeightedSequence( ACT_IDLE ) ); - ResetClientsideFrame(); - - // Fire output - m_pOutputAnimBegun.FireOutput( NULL,this ); - - m_flNextRandAnim = gpGlobals->curtime + random->RandomFloat( m_flMinRandAnimTime, m_flMaxRandAnimTime ); - } - - if ( ((m_iTransitionDirection > 0 && GetCycle() >= 0.999f) || (m_iTransitionDirection < 0 && GetCycle() <= 0.0f)) && !SequenceLoops() ) - { - Assert( m_iGoalSequence >= 0 ); - if (GetSequence() != m_iGoalSequence) - { - PropSetSequence( m_iGoalSequence ); - } - else - { - // Fire output - m_pOutputAnimOver.FireOutput(NULL,this); - - // If I'm a random animator, think again when it's time to change sequence - if ( m_bRandomAnimator ) - { - SetNextThink( gpGlobals->curtime + m_flNextRandAnim + 0.1 ); - } - else - { - if (m_iszDefaultAnim != NULL_STRING) - { - PropSetAnim( STRING( m_iszDefaultAnim ) ); - } - } - } - } - else - { - SetNextThink( gpGlobals->curtime + 0.1f ); - } - - StudioFrameAdvance(); - DispatchAnimEvents(this); - m_BoneFollowerManager.UpdateBoneFollowers(this); -} - - -//------------------------------------------------------------------------------ -// Purpose: Sets an animation by sequence name or activity name. -//------------------------------------------------------------------------------ -void CDynamicProp::PropSetAnim( const char *szAnim ) -{ - if ( !szAnim ) - return; - - int nSequence = LookupSequence( szAnim ); - - // Set to the desired anim, or default anim if the desired is not present - if ( nSequence > ACTIVITY_NOT_AVAILABLE ) - { - PropSetSequence( nSequence ); - - // Fire output - m_pOutputAnimBegun.FireOutput( NULL,this ); - } - else - { - // Not available try to get default anim - Warning( "Dynamic prop %s: no sequence named:%s\n", GetDebugName(), szAnim ); - SetSequence( 0 ); - } -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CDynamicProp::InputSetAnimation( inputdata_t &inputdata ) -{ - PropSetAnim( inputdata.value.String() ); -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CDynamicProp::InputSetDefaultAnimation( inputdata_t &inputdata ) -{ - m_iszDefaultAnim = inputdata.value.StringID(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDynamicProp::InputSetPlaybackRate( inputdata_t &inputdata ) -{ - SetPlaybackRate( inputdata.value.Float() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Helper in case we have to async load the sequence -// Input : nSequence - -//----------------------------------------------------------------------------- -void CDynamicProp::FinishSetSequence( int nSequence ) -{ - // Msg("%.2f CDynamicProp::FinishSetSequence( %d )\n", gpGlobals->curtime, nSequence ); - SetCycle( 0 ); - m_flAnimTime = gpGlobals->curtime; - ResetSequence( nSequence ); - ResetClientsideFrame(); - RemoveFlag( FL_STATICPROP ); - SetPlaybackRate( m_iTransitionDirection > 0 ? 1.0f : -1.0f ); - SetCycle( m_iTransitionDirection > 0 ? 0.0f : 0.999f ); -} - -//----------------------------------------------------------------------------- -// Purpose: Sets the sequence and starts thinking. -// Input : nSequence - -//----------------------------------------------------------------------------- -void CDynamicProp::PropSetSequence( int nSequence ) -{ - m_iGoalSequence = nSequence; - - // Msg("%.2f CDynamicProp::PropSetSequence( %d (%d:%.1f:%.3f)\n", gpGlobals->curtime, nSequence, GetSequence(), GetPlaybackRate(), GetCycle() ); - - int nNextSequence; - float nextCycle; - float flInterval = 0.1f; - - if (GotoSequence( GetSequence(), GetCycle(), GetPlaybackRate(), m_iGoalSequence, nNextSequence, nextCycle, m_iTransitionDirection )) - { - FinishSetSequence( nNextSequence ); - } - - SetThink( &CDynamicProp::AnimThink ); - if ( GetNextThink() <= gpGlobals->curtime ) - SetNextThink( gpGlobals->curtime + flInterval ); -} - - -// NOTE: To avoid risk, currently these do nothing about collisions, only visually on/off -void CDynamicProp::InputTurnOn( inputdata_t &inputdata ) -{ - RemoveEffects( EF_NODRAW ); -} - -void CDynamicProp::InputTurnOff( inputdata_t &inputdata ) -{ - AddEffects( EF_NODRAW ); -} - -void CDynamicProp::InputDisableCollision( inputdata_t &inputdata ) -{ - AddSolidFlags( FSOLID_NOT_SOLID ); -} - -void CDynamicProp::InputEnableCollision( inputdata_t &inputdata ) -{ - RemoveSolidFlags( FSOLID_NOT_SOLID ); -} - -//----------------------------------------------------------------------------- -// Purpose: Ornamental prop that follows a studio -//----------------------------------------------------------------------------- -class COrnamentProp : public CDynamicProp -{ - DECLARE_CLASS( COrnamentProp, CDynamicProp ); -public: - DECLARE_DATADESC(); - - void Spawn(); - void Activate(); - void AttachTo( const char *pAttachEntity, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL ); - void DetachFromOwner(); - - // Input handlers - void InputSetAttached( inputdata_t &inputdata ); - void InputDetach( inputdata_t &inputdata ); - -private: - string_t m_initialOwner; -}; - -LINK_ENTITY_TO_CLASS( prop_dynamic_ornament, COrnamentProp ); - -BEGIN_DATADESC( COrnamentProp ) - - DEFINE_KEYFIELD( m_initialOwner, FIELD_STRING, "InitialOwner" ), - // Inputs - DEFINE_INPUTFUNC( FIELD_STRING, "SetAttached", InputSetAttached ), - DEFINE_INPUTFUNC( FIELD_VOID, "Detach", InputDetach ), - -END_DATADESC() - -void COrnamentProp::Spawn() -{ - BaseClass::Spawn(); - DetachFromOwner(); -} - -void COrnamentProp::DetachFromOwner() -{ - SetOwnerEntity( NULL ); - AddSolidFlags( FSOLID_NOT_SOLID ); - SetMoveType( MOVETYPE_NONE ); - AddEffects( EF_NODRAW ); -} - -void COrnamentProp::Activate() -{ - BaseClass::Activate(); - - if ( m_initialOwner != NULL_STRING ) - { - AttachTo( STRING(m_initialOwner) ); - } -} - -void COrnamentProp::InputSetAttached( inputdata_t &inputdata ) -{ - AttachTo( inputdata.value.String(), inputdata.pActivator, inputdata.pCaller ); -} - -void COrnamentProp::AttachTo( const char *pAttachName, CBaseEntity *pActivator, CBaseEntity *pCaller ) -{ - // find and notify the new parent - CBaseEntity *pAttach = gEntList.FindEntityByName( NULL, pAttachName, NULL, pActivator, pCaller ); - if ( pAttach ) - { - RemoveEffects( EF_NODRAW ); - FollowEntity( pAttach ); - } -} - -void COrnamentProp::InputDetach( inputdata_t &inputdata ) -{ - DetachFromOwner(); -} - - -//============================================================================= -// PHYSICS PROPS -//============================================================================= -LINK_ENTITY_TO_CLASS( physics_prop, CPhysicsProp ); -LINK_ENTITY_TO_CLASS( prop_physics, CPhysicsProp ); -LINK_ENTITY_TO_CLASS( prop_physics_override, CPhysicsProp ); - -BEGIN_DATADESC( CPhysicsProp ) - - DEFINE_INPUTFUNC( FIELD_VOID, "EnableMotion", InputEnableMotion ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableMotion", InputDisableMotion ), - DEFINE_INPUTFUNC( FIELD_VOID, "Wake", InputWake ), - DEFINE_INPUTFUNC( FIELD_VOID, "Sleep", InputSleep ), - DEFINE_INPUTFUNC( FIELD_VOID, "DisableFloating", InputDisableFloating ), - - DEFINE_FIELD( m_bAwake, FIELD_BOOLEAN ), - - DEFINE_KEYFIELD( m_massScale, FIELD_FLOAT, "massscale" ), - DEFINE_KEYFIELD( m_inertiaScale, FIELD_FLOAT, "inertiascale" ), - DEFINE_KEYFIELD( m_damageType, FIELD_INTEGER, "Damagetype" ), - DEFINE_KEYFIELD( m_iszOverrideScript, FIELD_STRING, "overridescript" ), - - DEFINE_KEYFIELD( m_damageToEnableMotion, FIELD_INTEGER, "damagetoenablemotion" ), - DEFINE_KEYFIELD( m_flForceToEnableMotion, FIELD_FLOAT, "forcetoenablemotion" ), - DEFINE_OUTPUT( m_OnAwakened, "OnAwakened" ), - DEFINE_OUTPUT( m_MotionEnabled, "OnMotionEnabled" ), - DEFINE_OUTPUT( m_OnPhysGunPickup, "OnPhysGunPickup" ), - DEFINE_OUTPUT( m_OnPhysGunOnlyPickup, "OnPhysGunOnlyPickup" ), - DEFINE_OUTPUT( m_OnPhysGunPunt, "OnPhysGunPunt" ), - DEFINE_OUTPUT( m_OnPhysGunDrop, "OnPhysGunDrop" ), - DEFINE_OUTPUT( m_OnPlayerUse, "OnPlayerUse" ), - DEFINE_OUTPUT( m_OnPlayerPickup, "OnPlayerPickup" ), - DEFINE_OUTPUT( m_OnOutOfWorld, "OnOutOfWorld" ), - - DEFINE_FIELD( m_bThrownByPlayer, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bFirstCollisionAfterLaunch, FIELD_BOOLEAN ), - - DEFINE_THINKFUNC( ClearFlagsThink ), - -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CPhysicsProp, DT_PhysicsProp ) - SendPropBool( SENDINFO( m_bAwake ) ), -END_SEND_TABLE() - -// external function to tell if this entity is a gib physics prop -bool PropIsGib( CBaseEntity *pEntity ) -{ - if ( FClassnameIs(pEntity, "prop_physics") ) - { - CPhysicsProp *pProp = static_cast(pEntity); - return pProp->IsGib(); - } - return false; -} - -CPhysicsProp::~CPhysicsProp() -{ - if (HasSpawnFlags(SF_PHYSPROP_IS_GIB)) - { - g_ActiveGibCount--; - } -} - -bool CPhysicsProp::IsGib() -{ - return (m_spawnflags & SF_PHYSPROP_IS_GIB) ? true : false; -} - -//----------------------------------------------------------------------------- -// Purpose: Create a physics object for this prop -//----------------------------------------------------------------------------- -void CPhysicsProp::Spawn( ) -{ - if (HasSpawnFlags(SF_PHYSPROP_IS_GIB)) - { - g_ActiveGibCount++; - } - // Condense classname's to one, except for "prop_physics_override" - if ( FClassnameIs( this, "physics_prop" ) ) - { - SetClassname( "prop_physics" ); - } - - BaseClass::Spawn(); - - if ( IsMarkedForDeletion() ) - return; - - // Now condense all classnames to one - if ( FClassnameIs( this, "prop_physics_override") ) - { - SetClassname( "prop_physics" ); - } - - if ( HasSpawnFlags( SF_PHYSPROP_DEBRIS ) || HasInteraction( PROPINTER_PHYSGUN_CREATE_FLARE ) ) - { - SetCollisionGroup( HasSpawnFlags( SF_PHYSPROP_FORCE_TOUCH_TRIGGERS ) ? COLLISION_GROUP_DEBRIS_TRIGGER : COLLISION_GROUP_DEBRIS ); - } - - if ( HasSpawnFlags( SF_PHYSPROP_NO_ROTORWASH_PUSH ) ) - { - AddEFlags( EFL_NO_ROTORWASH_PUSH ); - } - - CreateVPhysics(); - - if ( !PropDataOverrodeBlockLOS() ) - { - CalculateBlockLOS(); - } - - //Episode 1 change: - //Hi, since we're trying to ship this game we'll just go ahead and make all these doors not fade out instead of changing all the levels. - if ( Q_strcmp( STRING( GetModelName() ), "models/props_c17/door01_left.mdl" ) == 0 ) - { - SetFadeDistance( -1, 0 ); - DisableAutoFade(); - } - -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysicsProp::Precache( void ) -{ - if ( GetModelName() == NULL_STRING ) - { - Msg( "%s at (%.3f, %.3f, %.3f) has no model name!\n", GetClassname(), GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z ); - } - else - { - PrecacheModel( STRING( GetModelName() ) ); - BaseClass::Precache(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CPhysicsProp::CreateVPhysics() -{ - // Create the object in the physics system - bool asleep = HasSpawnFlags( SF_PHYSPROP_START_ASLEEP ) ? true : false; - - solid_t tmpSolid; - PhysModelParseSolid( tmpSolid, this, GetModelIndex() ); - - if ( m_massScale > 0 ) - { - tmpSolid.params.mass *= m_massScale; - } - - if ( m_inertiaScale > 0 ) - { - tmpSolid.params.inertia *= m_inertiaScale; - if ( tmpSolid.params.inertia < 0.5 ) - tmpSolid.params.inertia = 0.5; - } - - PhysGetMassCenterOverride( this, modelinfo->GetVCollide( GetModelIndex() ), tmpSolid ); - if ( HasSpawnFlags(SF_PHYSPROP_NO_COLLISIONS) ) - { - tmpSolid.params.enableCollisions = false; - } - PhysSolidOverride( tmpSolid, m_iszOverrideScript ); - - IPhysicsObject *pPhysicsObject = VPhysicsInitNormal( SOLID_VPHYSICS, 0, asleep, &tmpSolid ); - - if ( !pPhysicsObject ) - { - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NONE ); - Warning("ERROR!: Can't create physics object for %s\n", STRING( GetModelName() ) ); - } - else - { - if ( m_damageType == 1 ) - { - PhysSetGameFlags( pPhysicsObject, FVPHYSICS_DMG_SLICE ); - } - if ( HasSpawnFlags( SF_PHYSPROP_MOTIONDISABLED ) || m_damageToEnableMotion > 0 || m_flForceToEnableMotion > 0 ) - { - pPhysicsObject->EnableMotion( false ); - } - } - - // fix up any noncompliant blades. - if( HasInteraction( PROPINTER_PHYSGUN_LAUNCH_SPIN_Z ) ) - { - if( !(VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_DMG_SLICE) ) - { - PhysSetGameFlags( pPhysicsObject, FVPHYSICS_DMG_SLICE ); - -#if 0 - if( g_pDeveloper->GetInt() ) - { - // Highlight them in developer mode. - m_debugOverlays |= (OVERLAY_TEXT_BIT|OVERLAY_BBOX_BIT); - } -#endif - } - } - - if( HasInteraction( PROPINTER_PHYSGUN_DAMAGE_NONE ) ) - { - PhysSetGameFlags( pPhysicsObject, FVPHYSICS_NO_IMPACT_DMG ); - } - - if ( HasSpawnFlags(SF_PHYSPROP_PREVENT_PICKUP) ) - { - PhysSetGameFlags(pPhysicsObject, FVPHYSICS_NO_PLAYER_PICKUP); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CPhysicsProp::CanBePickedUpByPhyscannon( void ) -{ - if ( HasSpawnFlags( SF_PHYSPROP_PREVENT_PICKUP ) ) - return false; - - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - if ( pPhysicsObject && pPhysicsObject->IsMoveable() == false ) - { - if ( HasSpawnFlags( SF_PHYSPROP_ENABLE_ON_PHYSCANNON ) == false ) - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CPhysicsProp::OverridePropdata( void ) -{ - return ( FClassnameIs(this, "prop_physics_override" ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler to start the physics prop simulating. -//----------------------------------------------------------------------------- -void CPhysicsProp::InputWake( inputdata_t &inputdata ) -{ - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - if ( pPhysicsObject != NULL ) - { - pPhysicsObject->Wake(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler to stop the physics prop simulating. -//----------------------------------------------------------------------------- -void CPhysicsProp::InputSleep( inputdata_t &inputdata ) -{ - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - if ( pPhysicsObject != NULL ) - { - pPhysicsObject->Sleep(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Enable physics motion and collision response (on by default) -//----------------------------------------------------------------------------- -void CPhysicsProp::InputEnableMotion( inputdata_t &inputdata ) -{ - EnableMotion(); -} - -//----------------------------------------------------------------------------- -// Purpose: Disable any physics motion or collision response -//----------------------------------------------------------------------------- -void CPhysicsProp::InputDisableMotion( inputdata_t &inputdata ) -{ - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - if ( pPhysicsObject != NULL ) - { - pPhysicsObject->EnableMotion( false ); - } -} - -// Turn off floating simulation (and cost) -void CPhysicsProp::InputDisableFloating( inputdata_t &inputdata ) -{ - PhysEnableFloating( VPhysicsGetObject(), false ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysicsProp::EnableMotion( void ) -{ - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - if ( pPhysicsObject ) - { - Vector pos; - QAngle angles; - - if ( GetEnableMotionPosition( &pos, &angles ) ) - { - ClearEnableMotionPosition(); - //pPhysicsObject->SetPosition( pos, angles, true ); - Teleport( &pos, &angles, NULL ); - } - - pPhysicsObject->EnableMotion( true ); - pPhysicsObject->Wake(); - - m_MotionEnabled.FireOutput( this, this, 0 ); - } - CheckRemoveRagdolls(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysicsProp::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) -{ - BaseClass::OnPhysGunPickup( pPhysGunUser, reason ); - - IPhysicsObject *pPhysicsObject = VPhysicsGetObject(); - if ( pPhysicsObject && !pPhysicsObject->IsMoveable() ) - { - if ( !HasSpawnFlags( SF_PHYSPROP_ENABLE_ON_PHYSCANNON ) ) - return; - - EnableMotion(); - - if( HasInteraction( PROPINTER_PHYSGUN_WORLD_STICK ) ) - { - SetCollisionGroup( COLLISION_GROUP_INTERACTIVE_DEBRIS ); - } - } - - m_OnPhysGunPickup.FireOutput( pPhysGunUser, this ); - - if( reason == PICKED_UP_BY_CANNON ) - { - m_OnPhysGunOnlyPickup.FireOutput( pPhysGunUser, this ); - } - - if ( reason == PUNTED_BY_CANNON ) - { - m_OnPhysGunPunt.FireOutput( pPhysGunUser, this ); - } - - if ( reason == PICKED_UP_BY_CANNON || reason == PICKED_UP_BY_PLAYER ) - { - m_OnPlayerPickup.FireOutput( pPhysGunUser, this ); - } - - CheckRemoveRagdolls(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysicsProp::OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ) -{ - BaseClass::OnPhysGunDrop( pPhysGunUser, Reason ); - - if ( Reason == LAUNCHED_BY_CANNON ) - { - if ( HasInteraction( PROPINTER_PHYSGUN_LAUNCH_SPIN_Z ) ) - { - AngularImpulse angVel( 0, 0, 5000.0 ); - VPhysicsGetObject()->AddVelocity( NULL, &angVel ); - - // no angular drag on this object anymore - float angDrag = 0.0f; - VPhysicsGetObject()->SetDragCoefficient( NULL, &angDrag ); - } - - PhysSetGameFlags( VPhysicsGetObject(), FVPHYSICS_WAS_THROWN ); - m_bFirstCollisionAfterLaunch = true; - } - else if ( Reason == THROWN_BY_PLAYER ) - { - // Remember the player threw us for NPC response purposes - m_bThrownByPlayer = true; - } - - m_OnPhysGunDrop.FireOutput( pPhysGunUser, this ); - - if ( HasInteraction( PROPINTER_PHYSGUN_NOTIFY_CHILDREN ) ) - { - CUtlVector children; - GetAllChildren( this, children ); - for (int i = 0; i < children.Count(); i++ ) - { - CBaseEntity *pent = children.Element( i ); - - IParentPropInteraction *pPropInter = dynamic_cast( pent ); - if ( pPropInter ) - { - pPropInter->OnParentPhysGunDrop( pPhysGunUser, Reason ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Get the specified key's angles for this prop from the QC's physgun_interactions -//----------------------------------------------------------------------------- -bool CPhysicsProp::GetPropDataAngles( const char *pKeyName, QAngle &vecAngles ) -{ - KeyValues *modelKeyValues = new KeyValues(""); - if ( modelKeyValues->LoadFromBuffer( modelinfo->GetModelName( GetModel() ), modelinfo->GetModelKeyValueText( GetModel() ) ) ) - { - KeyValues *pkvPropData = modelKeyValues->FindKey( "physgun_interactions" ); - if ( pkvPropData ) - { - char const *pszBase = pkvPropData->GetString( pKeyName ); - if ( pszBase && pszBase[0] ) - { - UTIL_StringToVector( vecAngles.Base(), pszBase ); - modelKeyValues->deleteThis(); - return true; - } - } - } - - modelKeyValues->deleteThis(); - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CPhysicsProp::GetCarryDistanceOffset( void ) -{ - KeyValues *modelKeyValues = new KeyValues(""); - if ( modelKeyValues->LoadFromBuffer( modelinfo->GetModelName( GetModel() ), modelinfo->GetModelKeyValueText( GetModel() ) ) ) - { - KeyValues *pkvPropData = modelKeyValues->FindKey( "physgun_interactions" ); - if ( pkvPropData ) - { - float flDistance = pkvPropData->GetFloat( "carry_distance_offset", 0 ); - modelKeyValues->deleteThis(); - return flDistance; - } - } - - modelKeyValues->deleteThis(); - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CPhysicsProp::ObjectCaps() -{ - int caps = BaseClass::ObjectCaps() | FCAP_WCEDIT_POSITION; - - if ( HasSpawnFlags( SF_PHYSPROP_ENABLE_PICKUP_OUTPUT ) ) - { - caps |= FCAP_IMPULSE_USE; - } - else if ( CBasePlayer::CanPickupObject( this, 35, 128 ) ) - { - caps |= FCAP_IMPULSE_USE; - - if( hl2_episodic.GetBool() && HasInteraction( PROPINTER_PHYSGUN_CREATE_FLARE ) ) - { - caps |= FCAP_USE_IN_RADIUS; - } - } - - if( HasSpawnFlags( SF_PHYSPROP_RADIUS_PICKUP ) ) - { - caps |= FCAP_USE_IN_RADIUS; - } - - return caps; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pActivator - -// *pCaller - -// useType - -// value - -//----------------------------------------------------------------------------- -void CPhysicsProp::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - CBasePlayer *pPlayer = ToBasePlayer( pActivator ); - if ( pPlayer ) - { - if ( HasSpawnFlags( SF_PHYSPROP_ENABLE_PICKUP_OUTPUT ) ) - { - m_OnPlayerUse.FireOutput( this, this ); - } - - pPlayer->PickupObject( this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPhysics - -//----------------------------------------------------------------------------- -void CPhysicsProp::VPhysicsUpdate( IPhysicsObject *pPhysics ) -{ - BaseClass::VPhysicsUpdate( pPhysics ); - m_bAwake = !pPhysics->IsAsleep(); - NetworkStateChanged(); - if ( HasSpawnFlags( SF_PHYSPROP_START_ASLEEP ) ) - { - if ( m_bAwake ) - { - m_OnAwakened.FireOutput(this, this); - RemoveSpawnFlags( SF_PHYSPROP_START_ASLEEP ); - } - } - - // If we're asleep, clear the player thrown flag - if ( m_bThrownByPlayer && !m_bAwake ) - { - m_bThrownByPlayer = false; - } - - if ( !IsInWorld() ) - { - m_OnOutOfWorld.FireOutput( this, this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysicsProp::ClearFlagsThink( void ) -{ - // collision may have destroyed the physics object, recheck - if ( VPhysicsGetObject() ) - { - PhysClearGameFlags( VPhysicsGetObject(), FVPHYSICS_WAS_THROWN ); - } - SetContextThink( NULL, 0, "PROP_CLEARFLAGS" ); -} - - -//----------------------------------------------------------------------------- -// Compute impulse to apply to the enabled entity. -//----------------------------------------------------------------------------- -void CPhysicsProp::ComputeEnablingImpulse( int index, gamevcollisionevent_t *pEvent ) -{ - // Surface speed of the object that hit us = v + w x r - // NOTE: w is specified in local space - Vector vecContactPoint, vecLocalContactPoint; - pEvent->pInternalData->GetContactPoint( vecContactPoint ); - - // Compute the angular component of velocity - IPhysicsObject *pImpactObject = pEvent->pObjects[!index]; - pImpactObject->WorldToLocal( &vecLocalContactPoint, vecContactPoint ); - vecLocalContactPoint -= pImpactObject->GetMassCenterLocalSpace(); - - Vector vecLocalContactVelocity, vecContactVelocity; - - AngularImpulse vecAngularVelocity = pEvent->preAngularVelocity[!index]; - vecAngularVelocity *= M_PI / 180.0f; - CrossProduct( vecAngularVelocity, vecLocalContactPoint, vecLocalContactVelocity ); - pImpactObject->LocalToWorldVector( &vecContactVelocity, vecLocalContactVelocity ); - - // Add in the center-of-mass velocity - vecContactVelocity += pEvent->preVelocity[!index]; - - // Compute the force + torque to apply - vecContactVelocity *= pImpactObject->GetMass(); - - Vector vecForce; - AngularImpulse vecTorque; - pEvent->pObjects[index]->CalculateForceOffset( vecContactVelocity, vecContactPoint, &vecForce, &vecTorque ); - - PhysCallbackImpulse( pEvent->pObjects[index], vecForce, vecTorque ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPhysicsProp::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) -{ - BaseClass::VPhysicsCollision( index, pEvent ); - - IPhysicsObject *pPhysObj = pEvent->pObjects[!index]; - - if ( m_flForceToEnableMotion ) - { - CBaseEntity *pOther = static_cast(pPhysObj->GetGameData()); - - // Don't allow the player to bump an object active if we've requested not to - if ( ( pOther && pOther->IsPlayer() && HasSpawnFlags( SF_PHYSPROP_PREVENT_PLAYER_TOUCH_ENABLE ) ) == false ) - { - // Large enough to enable motion? - float flForce = pEvent->collisionSpeed * pPhysObj->GetMass(); - - if ( flForce >= m_flForceToEnableMotion ) - { - ComputeEnablingImpulse( index, pEvent ); - EnableMotion(); - m_flForceToEnableMotion = 0; - } - } - } - - if( m_bFirstCollisionAfterLaunch ) - { - HandleFirstCollisionInteractions( index, pEvent ); - } - - if ( HasPhysicsAttacker( 2.0f ) ) - { - HandleAnyCollisionInteractions( index, pEvent ); - } - - if ( !HasSpawnFlags( SF_PHYSPROP_DONT_TAKE_PHYSICS_DAMAGE ) ) - { - int damageType = 0; - - IBreakableWithPropData *pBreakableInterface = assert_cast(this); - float damage = CalculateDefaultPhysicsDamage( index, pEvent, m_impactEnergyScale, true, damageType, pBreakableInterface->GetPhysicsDamageTable() ); - if ( damage > 0 ) - { - // Take extra damage after we're punted by the physcannon - if ( m_bFirstCollisionAfterLaunch && !m_bThrownByPlayer ) - { - damage *= 10; - } - - CBaseEntity *pHitEntity = pEvent->pEntities[!index]; - if ( !pHitEntity ) - { - // hit world - pHitEntity = GetContainingEntity( INDEXENT(0) ); - } - Vector damagePos; - pEvent->pInternalData->GetContactPoint( damagePos ); - Vector damageForce = pEvent->postVelocity[index] * pEvent->pObjects[index]->GetMass(); - if ( damageForce == vec3_origin ) - { - // This can happen if this entity is motion disabled, and can't move. - // Use the velocity of the entity that hit us instead. - damageForce = pEvent->postVelocity[!index] * pEvent->pObjects[!index]->GetMass(); - } - - // FIXME: this doesn't pass in who is responsible if some other entity "caused" this collision - PhysCallbackDamage( this, CTakeDamageInfo( pHitEntity, pHitEntity, damageForce, damagePos, damage, damageType ), *pEvent, index ); - } - } - - if ( m_bThrownByPlayer || m_bFirstCollisionAfterLaunch ) - { - // If we were thrown by a player, and we've hit an NPC, let the NPC know - CBaseEntity *pHitEntity = pEvent->pEntities[!index]; - if ( pHitEntity && pHitEntity->MyNPCPointer() ) - { - pHitEntity->MyNPCPointer()->DispatchInteraction( g_interactionHitByPlayerThrownPhysObj, this, NULL ); - m_bThrownByPlayer = false; - } - } - - if ( m_bFirstCollisionAfterLaunch ) - { - m_bFirstCollisionAfterLaunch = false; - - // Setup the think function to remove the flags - RegisterThinkContext( "PROP_CLEARFLAGS" ); - SetContextThink( &CPhysicsProp::ClearFlagsThink, gpGlobals->curtime, "PROP_CLEARFLAGS" ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CPhysicsProp::OnTakeDamage( const CTakeDamageInfo &info ) -{ - // note: if motion is disabled, OnTakeDamage can't apply physics force - int ret = BaseClass::OnTakeDamage( info ); - - if( IsOnFire() ) - { - if( (info.GetDamageType() & DMG_BURN) && (info.GetDamageType() & DMG_DIRECT) ) - { - // Burning! scare things in my path if I'm moving. - Vector vel; - - if( VPhysicsGetObject() ) - { - VPhysicsGetObject()->GetVelocity( &vel, NULL ); - - int dangerRadius = 256; // generous radius to begin with - - if( hl2_episodic.GetBool() ) - { - // In Episodic, burning items (such as destroyed APCs) are making very large - // danger sounds which frighten NPCs. This danger sound was designed to frighten - // NPCs away from burning objects that are about to explode (barrels, etc). - // So if this item has no more health (ie, has died but hasn't exploded), - // make a smaller danger sound, just to keep NPCs away from the flames. - // I suspect this problem didn't appear in HL2 simply because we didn't have - // NPCs in such close proximity to destroyed NPCs. (sjb) - if( GetHealth() < 1 ) - { - // This item has no health, but still exists. That means that it may keep - // burning, but isn't likely to explode, so don't frighten over such a large radius. - dangerRadius = 120; - } - } - - trace_t tr; - UTIL_TraceLine( WorldSpaceCenter(), WorldSpaceCenter() + vel, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - CSoundEnt::InsertSound( SOUND_DANGER, tr.endpos, dangerRadius, 1.0, this, SOUNDENT_CHANNEL_REPEATED_DANGER ); - } - } - } - - // If we have a force to enable motion, and we're still disabled, check to see if this should enable us - if ( m_flForceToEnableMotion ) - { - // Large enough to enable motion? - float flForce = info.GetDamageForce().Length(); - if ( flForce >= m_flForceToEnableMotion ) - { - EnableMotion(); - m_flForceToEnableMotion = 0; - } - } - - // Check our health against the threshold: - if( m_damageToEnableMotion > 0 && GetHealth() < m_damageToEnableMotion ) - { - // only do this once - m_damageToEnableMotion = 0; - - // The damage that enables motion may have been enough damage to kill me if I'm breakable - // in which case my physics object is gone. - if ( VPhysicsGetObject() != NULL ) - { - EnableMotion(); - VPhysicsTakeDamage( info ); - } - } - - return ret; -} - - -//----------------------------------------------------------------------------- -// Mass / mass center -//----------------------------------------------------------------------------- -void CPhysicsProp::GetMassCenter( Vector *pMassCenter ) -{ - if ( !VPhysicsGetObject() ) - { - pMassCenter->Init(); - return; - } - - Vector vecLocal = VPhysicsGetObject()->GetMassCenterLocalSpace(); - VectorTransform( vecLocal, EntityToWorldTransform(), *pMassCenter ); -} - -float CPhysicsProp::GetMass() const -{ - return VPhysicsGetObject() ? VPhysicsGetObject()->GetMass() : 1.0f; -} - - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CPhysicsProp::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - if (VPhysicsGetObject()) - { - char tempstr[512]; - Q_snprintf(tempstr, sizeof(tempstr),"Mass: %.2f kg / %.2f lb (%s)", VPhysicsGetObject()->GetMass(), kg2lbs(VPhysicsGetObject()->GetMass()), GetMassEquivalent(VPhysicsGetObject()->GetMass())); - EntityText( text_offset, tempstr, 0); - text_offset++; - - { - vphysics_objectstress_t stressOut; - float stress = CalculateObjectStress( VPhysicsGetObject(), this, &stressOut ); - Q_snprintf(tempstr, sizeof(tempstr),"Stress: %.2f (%.2f / %.2f)", stress, stressOut.exertedStress, stressOut.receivedStress ); - EntityText( text_offset, tempstr, 0); - text_offset++; - } - - if ( !VPhysicsGetObject()->IsMoveable() ) - { - Q_snprintf(tempstr, sizeof(tempstr),"Motion Disabled" ); - EntityText( text_offset, tempstr, 0); - text_offset++; - } - - if ( m_iszBasePropData != NULL_STRING ) - { - Q_snprintf(tempstr, sizeof(tempstr),"Base PropData: %s", STRING(m_iszBasePropData) ); - EntityText( text_offset, tempstr, 0); - text_offset++; - } - - if ( m_iNumBreakableChunks != 0 ) - { - IBreakableWithPropData *pBreakableInterface = assert_cast(this); - Q_snprintf(tempstr, sizeof(tempstr),"Breakable Chunks: %d (Max Size %d)", m_iNumBreakableChunks, pBreakableInterface->GetMaxBreakableSize() ); - EntityText( text_offset, tempstr, 0); - text_offset++; - } - - Q_snprintf(tempstr, sizeof(tempstr),"Skin: %d", m_nSkin ); - EntityText( text_offset, tempstr, 0); - text_offset++; - - Q_snprintf(tempstr, sizeof(tempstr),"Health: %d, collision group %d", GetHealth(), GetCollisionGroup() ); - EntityText( text_offset, tempstr, 0); - text_offset++; - } - } - - return text_offset; -} - - -static CBreakableProp *BreakModelCreate_Prop( CBaseEntity *pOwner, breakmodel_t *pModel, const Vector &position, const QAngle &angles, const breakablepropparams_t ¶ms ) -{ - CBreakableProp *pEntity = (CBreakableProp *)CBaseEntity::CreateNoSpawn( "prop_physics", position, angles, pOwner ); - if ( pEntity ) - { - // UNDONE: Allow .qc to override spawnflags for child pieces - if ( pOwner ) - { - pEntity->AddSpawnFlags( pOwner->GetSpawnFlags() ); - - // We never want to be motion disabled - pEntity->RemoveSpawnFlags( SF_PHYSPROP_MOTIONDISABLED ); - } - pEntity->m_impactEnergyScale = params.impactEnergyScale; // assume the same material - // Inherit the base object's damage modifiers - CBreakableProp *pBreakableOwner = dynamic_cast(pOwner); - if ( pBreakableOwner ) - { - pEntity->SetDmgModBullet( pBreakableOwner->GetDmgModBullet() ); - pEntity->SetDmgModClub( pBreakableOwner->GetDmgModClub() ); - pEntity->SetDmgModExplosive( pBreakableOwner->GetDmgModExplosive() ); - - // Copy over the dx7 fade too - pEntity->CopyFadeFrom( pBreakableOwner ); - } - pEntity->SetModelName( AllocPooledString( pModel->modelName ) ); - pEntity->SetModel( STRING(pEntity->GetModelName()) ); - pEntity->SetCollisionGroup( pModel->collisionGroup ); - - if ( pModel->fadeMinDist > 0 && pModel->fadeMaxDist >= pModel->fadeMinDist ) - { - pEntity->SetFadeDistance( pModel->fadeMinDist, pModel->fadeMaxDist ); - } - - if ( pModel->fadeTime != 0 ) - { - pEntity->AddSpawnFlags( SF_PHYSPROP_IS_GIB ); - } - pEntity->Spawn(); - - // If we're burning, break into burning pieces - CBaseAnimating *pAnimating = dynamic_cast(pOwner); - if ( pAnimating && pAnimating->IsOnFire() ) - { - CEntityFlame *pOwnerFlame = dynamic_cast( pAnimating->GetEffectEntity() ); - - if ( pOwnerFlame ) - { - pEntity->Ignite( pOwnerFlame->GetRemainingLife(), false ); - pEntity->IgniteNumHitboxFires( pOwnerFlame->GetNumHitboxFires() ); - pEntity->IgniteHitboxFireScale( pOwnerFlame->GetHitboxFireScale() ); - } - else - { - // This should never happen - pEntity->Ignite( random->RandomFloat( 5, 10 ), false ); - } - } - } - - return pEntity; -} - -static CBaseAnimating *BreakModelCreate_Ragdoll( CBaseEntity *pOwner, breakmodel_t *pModel, const Vector &position, const QAngle &angles ) -{ - CBaseAnimating *pAnimating = CreateServerRagdollSubmodel( dynamic_cast(pOwner), pModel->modelName, position, angles, pModel->collisionGroup ); - return pAnimating; -} - -CBaseEntity *BreakModelCreateSingle( CBaseEntity *pOwner, breakmodel_t *pModel, const Vector &position, - const QAngle &angles, const Vector &velocity, const AngularImpulse &angVelocity, int nSkin, const breakablepropparams_t ¶ms ) -{ - CBaseAnimating *pEntity = NULL; - // stop creating gibs if too many - if ( g_ActiveGibCount >= ACTIVE_GIB_LIMIT ) - { - //DevMsg(1,"Gib limit on %s\n", pModel->modelName ); - return NULL; - } - - if ( !pModel->isRagdoll ) - { - pEntity = BreakModelCreate_Prop( pOwner, pModel, position, angles, params ); - } - else - { - pEntity = BreakModelCreate_Ragdoll( pOwner, pModel, position, angles ); - } - if ( pEntity ) - { - pEntity->m_nSkin = nSkin; - pEntity->m_iHealth = pModel->health; - if ( g_ActiveGibCount >= ACTIVE_GIB_FADE ) - { - pModel->fadeTime = MIN( 3, pModel->fadeTime ); - } - if ( pModel->fadeTime ) - { - pEntity->SUB_StartFadeOut( pModel->fadeTime, false ); - - CBreakableProp *pProp = dynamic_cast(pEntity); - if ( pProp && !pProp->GetNumBreakableChunks() && pProp->m_takedamage == DAMAGE_YES ) - { - pProp->m_takedamage = DAMAGE_EVENTS_ONLY; - } - } - - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int count = pEntity->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - if ( count ) - { - for ( int i = 0; i < count; i++ ) - { - pList[i]->SetVelocity( &velocity, &angVelocity ); - } - } - else - { - // failed to create a physics object - UTIL_Remove( pEntity ); - return NULL; - } - } - - return pEntity; -} - -class CBreakModelsPrecached : public CAutoGameSystem -{ -public: - CBreakModelsPrecached() : CAutoGameSystem( "CBreakModelsPrecached" ) - { - m_modelList.SetLessFunc( BreakLessFunc ); - } - - struct breakable_precache_t - { - string_t iszModelName; - int iBreakableCount; - }; - - static bool BreakLessFunc( breakable_precache_t const &lhs, breakable_precache_t const &rhs ) - { - return ( lhs.iszModelName.ToCStr() < rhs.iszModelName.ToCStr() ); - } - - bool IsInList( string_t modelName, int *iBreakableCount ) - { - breakable_precache_t sEntry; - sEntry.iszModelName = modelName; - int iEntry = m_modelList.Find(sEntry); - if ( iEntry != m_modelList.InvalidIndex() ) - { - *iBreakableCount = m_modelList[iEntry].iBreakableCount; - return true; - } - - return false; - } - - void AddToList( string_t modelName, int iBreakableCount ) - { - breakable_precache_t sEntry; - sEntry.iszModelName = modelName; - sEntry.iBreakableCount = iBreakableCount; - m_modelList.Insert( sEntry ); - } - - void LevelShutdownPostEntity() - { - m_modelList.RemoveAll(); - } - -private: - CUtlRBTree m_modelList; -}; - -static CBreakModelsPrecached g_BreakModelsPrecached; - -int PropBreakablePrecacheAll( string_t modelName ) -{ - int iBreakables = 0; - if ( g_BreakModelsPrecached.IsInList( modelName, &iBreakables ) ) - return iBreakables; - - if ( modelName == NULL_STRING ) - { - Msg("Trying to precache breakable prop, but has no model name\n"); - return iBreakables; - } - - int modelIndex = CBaseEntity::PrecacheModel( STRING(modelName) ); - - CUtlVector list; - - BreakModelList( list, modelIndex, COLLISION_GROUP_NONE, 0 ); - iBreakables = list.Count(); - - g_BreakModelsPrecached.AddToList( modelName, iBreakables ); - - for ( int i = 0; i < iBreakables; i++ ) - { - string_t breakModelName = AllocPooledString(list[i].modelName); - if ( modelIndex <= 0 ) - { - iBreakables--; - continue; - } - - PropBreakablePrecacheAll( breakModelName ); - } - - return iBreakables; -} - -bool PropBreakableCapEdictsOnCreateAll(int modelindex, IPhysicsObject *pPhysics, const breakablepropparams_t ¶ms, CBaseEntity *pEntity, int iPrecomputedBreakableCount = -1 ) -{ - // @Note (toml 10-07-03): this is stop-gap to prevent this function from crashing the engine - const int BREATHING_ROOM = 64; - - CUtlVector list; - BreakModelList( list, modelindex, params.defBurstScale, params.defCollisionGroup ); - - int numToCreate = 0; - - if ( iPrecomputedBreakableCount != -1 ) - { - numToCreate = iPrecomputedBreakableCount; - } - else - { - if ( list.Count() ) - { - for ( int i = 0; i < list.Count(); i++ ) - { - int modelIndex = modelinfo->GetModelIndex( list[i].modelName ); - if ( modelIndex <= 0 ) - continue; - numToCreate++; - } - } - // Then see if the propdata specifies any breakable pieces - else if ( pEntity ) - { - IBreakableWithPropData *pBreakableInterface = dynamic_cast(pEntity); - if ( pBreakableInterface && pBreakableInterface->GetBreakableModel() != NULL_STRING && pBreakableInterface->GetBreakableCount() ) - { - numToCreate += pBreakableInterface->GetBreakableCount(); - } - } - } - - return ( !numToCreate || ( engine->GetEntityCount() + numToCreate + BREATHING_ROOM < MAX_EDICTS ) ); -} - - -//============================================================================================================= -// BASE PROP DOOR -//============================================================================================================= -// -// Private activities. -// -static int ACT_DOOR_OPEN = 0; -static int ACT_DOOR_LOCKED = 0; - -// -// Anim events. -// -enum -{ - AE_DOOR_OPEN = 1, // The door should start opening. -}; - - -void PlayLockSounds(CBaseEntity *pEdict, locksound_t *pls, int flocked, int fbutton); - -BEGIN_DATADESC_NO_BASE(locksound_t) - - DEFINE_FIELD( sLockedSound, FIELD_STRING), - DEFINE_FIELD( sLockedSentence, FIELD_STRING ), - DEFINE_FIELD( sUnlockedSound, FIELD_STRING ), - DEFINE_FIELD( sUnlockedSentence, FIELD_STRING ), - DEFINE_FIELD( iLockedSentence, FIELD_INTEGER ), - DEFINE_FIELD( iUnlockedSentence, FIELD_INTEGER ), - DEFINE_FIELD( flwaitSound, FIELD_FLOAT ), - DEFINE_FIELD( flwaitSentence, FIELD_FLOAT ), - DEFINE_FIELD( bEOFLocked, FIELD_CHARACTER ), - DEFINE_FIELD( bEOFUnlocked, FIELD_CHARACTER ), - -END_DATADESC() - -BEGIN_DATADESC(CBasePropDoor) - //DEFINE_FIELD(m_bLockedSentence, FIELD_CHARACTER), - //DEFINE_FIELD(m_bUnlockedSentence, FIELD_CHARACTER), - DEFINE_KEYFIELD(m_nHardwareType, FIELD_INTEGER, "hardware"), - DEFINE_KEYFIELD(m_flAutoReturnDelay, FIELD_FLOAT, "returndelay"), - DEFINE_FIELD( m_hActivator, FIELD_EHANDLE ), - DEFINE_KEYFIELD(m_SoundMoving, FIELD_SOUNDNAME, "soundmoveoverride"), - DEFINE_KEYFIELD(m_SoundOpen, FIELD_SOUNDNAME, "soundopenoverride"), - DEFINE_KEYFIELD(m_SoundClose, FIELD_SOUNDNAME, "soundcloseoverride"), - DEFINE_KEYFIELD(m_ls.sLockedSound, FIELD_SOUNDNAME, "soundlockedoverride"), - DEFINE_KEYFIELD(m_ls.sUnlockedSound, FIELD_SOUNDNAME, "soundunlockedoverride"), - DEFINE_KEYFIELD(m_SlaveName, FIELD_STRING, "slavename" ), - DEFINE_FIELD(m_bLocked, FIELD_BOOLEAN), - //DEFINE_KEYFIELD(m_flBlockDamage, FIELD_FLOAT, "dmg"), - DEFINE_KEYFIELD( m_bForceClosed, FIELD_BOOLEAN, "forceclosed" ), - DEFINE_FIELD(m_eDoorState, FIELD_INTEGER), - DEFINE_FIELD( m_hMaster, FIELD_EHANDLE ), - DEFINE_FIELD( m_hBlocker, FIELD_EHANDLE ), - DEFINE_FIELD( m_bFirstBlocked, FIELD_BOOLEAN ), - //DEFINE_FIELD(m_hDoorList, FIELD_CLASSPTR), // Reconstructed - - DEFINE_INPUTFUNC(FIELD_VOID, "Open", InputOpen), - DEFINE_INPUTFUNC(FIELD_STRING, "OpenAwayFrom", InputOpenAwayFrom), - DEFINE_INPUTFUNC(FIELD_VOID, "Close", InputClose), - DEFINE_INPUTFUNC(FIELD_VOID, "Toggle", InputToggle), - DEFINE_INPUTFUNC(FIELD_VOID, "Lock", InputLock), - DEFINE_INPUTFUNC(FIELD_VOID, "Unlock", InputUnlock), - - DEFINE_OUTPUT(m_OnBlockedOpening, "OnBlockedOpening"), - DEFINE_OUTPUT(m_OnBlockedClosing, "OnBlockedClosing"), - DEFINE_OUTPUT(m_OnUnblockedOpening, "OnUnblockedOpening"), - DEFINE_OUTPUT(m_OnUnblockedClosing, "OnUnblockedClosing"), - DEFINE_OUTPUT(m_OnFullyClosed, "OnFullyClosed"), - DEFINE_OUTPUT(m_OnFullyOpen, "OnFullyOpen"), - DEFINE_OUTPUT(m_OnClose, "OnClose"), - DEFINE_OUTPUT(m_OnOpen, "OnOpen"), - DEFINE_OUTPUT(m_OnLockedUse, "OnLockedUse" ), - DEFINE_EMBEDDED( m_ls ), - - // Function Pointers - DEFINE_THINKFUNC(DoorOpenMoveDone), - DEFINE_THINKFUNC(DoorCloseMoveDone), - DEFINE_THINKFUNC(DoorAutoCloseThink), -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST(CBasePropDoor, DT_BasePropDoor) -END_SEND_TABLE() - -CBasePropDoor::CBasePropDoor( void ) -{ - m_hMaster = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePropDoor::Spawn() -{ - BaseClass::Spawn(); - - DisableAutoFade(); - Precache(); - - DoorTeleportToSpawnPosition(); - - if (HasSpawnFlags(SF_DOOR_LOCKED)) - { - m_bLocked = true; - } - - SetMoveType(MOVETYPE_PUSH); - - if (m_flSpeed == 0) - { - m_flSpeed = 100; - } - - RemoveFlag(FL_STATICPROP); - - SetSolid(SOLID_VPHYSICS); - VPhysicsInitShadow(false, false); - AddSolidFlags( FSOLID_CUSTOMRAYTEST | FSOLID_CUSTOMBOXTEST ); - - SetBodygroup( DOOR_HARDWARE_GROUP, m_nHardwareType ); - if ((m_nHardwareType == 0) && (!HasSpawnFlags(SF_DOOR_LOCKED))) - { - // Doors with no hardware must always be locked. - DevWarning(1, "Unlocked prop_door '%s' at (%.0f %.0f %.0f) has no hardware. All openable doors must have hardware!\n", GetDebugName(), GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z); - } - - if ( !PropDataOverrodeBlockLOS() ) - { - CalculateBlockLOS(); - } - - SetDoorBlocker( NULL ); - - // Fills out the m_Soundxxx members. - CalcDoorSounds(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns our capabilities mask. -//----------------------------------------------------------------------------- -int CBasePropDoor::ObjectCaps() -{ - return BaseClass::ObjectCaps() | ( HasSpawnFlags( SF_DOOR_IGNORE_USE ) ? 0 : (FCAP_IMPULSE_USE|FCAP_USE_IN_RADIUS) ); -}; - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePropDoor::Precache(void) -{ - BaseClass::Precache(); - - RegisterPrivateActivities(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePropDoor::RegisterPrivateActivities(void) -{ - static bool bRegistered = false; - - if (bRegistered) - return; - - REGISTER_PRIVATE_ACTIVITY( ACT_DOOR_OPEN ); - REGISTER_PRIVATE_ACTIVITY( ACT_DOOR_LOCKED ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePropDoor::Activate( void ) -{ - BaseClass::Activate(); - - UpdateAreaPortals( !IsDoorClosed() ); - - // If we have a name, we may be linked - if ( GetEntityName() != NULL_STRING ) - { - CBaseEntity *pTarget = NULL; - - // Find our slaves. - // If we have a specified slave name, then use that to find slaves. - // Otherwise, see if there are any other doors that match our name (Backwards compatability). - string_t iszSearchName = GetEntityName(); - if ( m_SlaveName != NULL_STRING ) - { - const char *pSlaveName = STRING(m_SlaveName); - if ( pSlaveName && pSlaveName[0] ) - { - iszSearchName = m_SlaveName; - } - } - - while ( ( pTarget = gEntList.FindEntityByName( pTarget, iszSearchName ) ) != NULL ) - { - if ( pTarget != this ) - { - CBasePropDoor *pDoor = dynamic_cast(pTarget); - - if ( pDoor != NULL && pDoor->HasSlaves() == false ) - { - m_hDoorList.AddToTail( pDoor ); - pDoor->SetMaster( this ); - pDoor->SetOwnerEntity( this ); - } - } - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePropDoor::HandleAnimEvent(animevent_t *pEvent) -{ - // Opening is called here via an animation event if the open sequence has one, - // otherwise it is called immediately when the open sequence is set. - if (pEvent->event == AE_DOOR_OPEN) - { - DoorActivate(); - } -} - - -// Only overwrite str1 if it's NULL_STRING. -#define ASSIGN_STRING_IF_NULL( str1, str2 ) \ - if ( ( str1 ) == NULL_STRING ) { ( str1 ) = ( str2 ); } - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePropDoor::CalcDoorSounds() -{ - ErrorIfNot( GetModel() != NULL, ( "prop_door with no model at %.2f %.2f %.2f\n", GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z ) ); - - string_t strSoundOpen = NULL_STRING; - string_t strSoundClose = NULL_STRING; - string_t strSoundMoving = NULL_STRING; - string_t strSoundLocked = NULL_STRING; - string_t strSoundUnlocked = NULL_STRING; - - bool bFoundSkin = false; - // Otherwise, use the sounds specified by the model keyvalues. These are looked up - // based on skin and hardware. - KeyValues *modelKeyValues = new KeyValues(""); - if ( modelKeyValues->LoadFromBuffer( modelinfo->GetModelName( GetModel() ), modelinfo->GetModelKeyValueText( GetModel() ) ) ) - { - KeyValues *pkvDoorSounds = modelKeyValues->FindKey("door_options"); - if ( pkvDoorSounds ) - { - // Open / close / move sounds are looked up by skin index. - char szSkin[80]; - int skin = m_nSkin; - Q_snprintf( szSkin, sizeof( szSkin ), "skin%d", skin ); - KeyValues *pkvSkinData = pkvDoorSounds->FindKey( szSkin ); - if ( pkvSkinData ) - { - strSoundOpen = AllocPooledString( pkvSkinData->GetString( "open" ) ); - strSoundClose = AllocPooledString( pkvSkinData->GetString( "close" ) ); - strSoundMoving = AllocPooledString( pkvSkinData->GetString( "move" ) ); - const char *pSurfaceprop = pkvSkinData->GetString( "surfaceprop" ); - if ( pSurfaceprop && VPhysicsGetObject() ) - { - bFoundSkin = true; - VPhysicsGetObject()->SetMaterialIndex( physprops->GetSurfaceIndex( pSurfaceprop ) ); - } - } - - // Locked / unlocked sounds are looked up by hardware index. - char szHardware[80]; - Q_snprintf( szHardware, sizeof( szHardware ), "hardware%d", m_nHardwareType ); - KeyValues *pkvHardwareData = pkvDoorSounds->FindKey( szHardware ); - if ( pkvHardwareData ) - { - strSoundLocked = AllocPooledString( pkvHardwareData->GetString( "locked" ) ); - strSoundUnlocked = AllocPooledString( pkvHardwareData->GetString( "unlocked" ) ); - } - - // If any sounds were missing, try the "defaults" block. - if ( ( strSoundOpen == NULL_STRING ) || ( strSoundClose == NULL_STRING ) || ( strSoundMoving == NULL_STRING ) || - ( strSoundLocked == NULL_STRING ) || ( strSoundUnlocked == NULL_STRING ) ) - { - KeyValues *pkvDefaults = pkvDoorSounds->FindKey( "defaults" ); - if ( pkvDefaults ) - { - ASSIGN_STRING_IF_NULL( strSoundOpen, AllocPooledString( pkvDefaults->GetString( "open" ) ) ); - ASSIGN_STRING_IF_NULL( strSoundClose, AllocPooledString( pkvDefaults->GetString( "close" ) ) ); - ASSIGN_STRING_IF_NULL( strSoundMoving, AllocPooledString( pkvDefaults->GetString( "move" ) ) ); - ASSIGN_STRING_IF_NULL( strSoundLocked, AllocPooledString( pkvDefaults->GetString( "locked" ) ) ); - ASSIGN_STRING_IF_NULL( strSoundUnlocked, AllocPooledString( pkvDefaults->GetString( "unlocked" ) ) ); - // NOTE: No default needed for surfaceprop, it's set by the model - } - } - } - } - modelKeyValues->deleteThis(); - modelKeyValues = NULL; - if ( !bFoundSkin && VPhysicsGetObject() ) - { - Warning( "%s has Door model (%s) with no door_options! Verify that SKIN is valid, and has a corresponding options block in the model QC file\n", GetDebugName(), modelinfo->GetModelName( GetModel() ) ); - VPhysicsGetObject()->SetMaterialIndex( physprops->GetSurfaceIndex("wood") ); - } - - // Any sound data members that are already filled out were specified as level designer overrides, - // so they should not be overwritten. - ASSIGN_STRING_IF_NULL( m_SoundOpen, strSoundOpen ); - ASSIGN_STRING_IF_NULL( m_SoundClose, strSoundClose ); - ASSIGN_STRING_IF_NULL( m_SoundMoving, strSoundMoving ); - ASSIGN_STRING_IF_NULL( m_ls.sLockedSound, strSoundLocked ); - ASSIGN_STRING_IF_NULL( m_ls.sUnlockedSound, strSoundUnlocked ); - - // Make sure we have real, precachable sound names in all cases. - UTIL_ValidateSoundName( m_SoundMoving, "DoorSound.Null" ); - UTIL_ValidateSoundName( m_SoundOpen, "DoorSound.Null" ); - UTIL_ValidateSoundName( m_SoundClose, "DoorSound.Null" ); - UTIL_ValidateSoundName( m_ls.sLockedSound, "DoorSound.Null" ); - UTIL_ValidateSoundName( m_ls.sUnlockedSound, "DoorSound.Null" ); - - PrecacheScriptSound( STRING( m_SoundMoving ) ); - PrecacheScriptSound( STRING( m_SoundOpen ) ); - PrecacheScriptSound( STRING( m_SoundClose ) ); - PrecacheScriptSound( STRING( m_ls.sLockedSound ) ); - PrecacheScriptSound( STRING( m_ls.sUnlockedSound ) ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : isOpen - -//----------------------------------------------------------------------------- -void CBasePropDoor::UpdateAreaPortals(bool isOpen) -{ - string_t name = GetEntityName(); - if (!name) - return; - - CBaseEntity *pPortal = NULL; - while ((pPortal = gEntList.FindEntityByClassname(pPortal, "func_areaportal")) != NULL) - { - if (pPortal->HasTarget(name)) - { - // USE_ON means open the portal, off means close it - pPortal->Use(this, this, isOpen?USE_ON:USE_OFF, 0); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : state - -//----------------------------------------------------------------------------- -void CBasePropDoor::SetDoorBlocker( CBaseEntity *pBlocker ) -{ - m_hBlocker = pBlocker; - - if ( m_hBlocker == NULL ) - { - m_bFirstBlocked = false; - } -} -//----------------------------------------------------------------------------- -// Purpose: Called when the player uses the door. -// Input : pActivator - -// pCaller - -// useType - -// value - -//----------------------------------------------------------------------------- -void CBasePropDoor::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) -{ - if ( GetMaster() != NULL ) - { - // Tell our owner we've been used - GetMaster()->Use( pActivator, pCaller, useType, value ); - } - else - { - // Just let it through - OnUse( pActivator, pCaller, useType, value ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pActivator - -// *pCaller - -// useType - -// value - -//----------------------------------------------------------------------------- -void CBasePropDoor::OnUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - // If we're blocked while closing, open away from our blocker. This will - // liberate whatever bit of detritus is stuck in us. - if ( IsDoorBlocked() && IsDoorClosing() ) - { - m_hActivator = pActivator; - DoorOpen( m_hBlocker ); - return; - } - - if (IsDoorClosed() || (IsDoorOpen() && HasSpawnFlags(SF_DOOR_USE_CLOSES))) - { - // Ready to be opened or closed. - if (m_bLocked) - { - PropSetSequence(SelectWeightedSequence((Activity)ACT_DOOR_LOCKED)); - PlayLockSounds(this, &m_ls, TRUE, FALSE); - m_OnLockedUse.FireOutput( pActivator, pCaller ); - } - else - { - m_hActivator = pActivator; - - PlayLockSounds(this, &m_ls, FALSE, FALSE); - int nSequence = SelectWeightedSequence((Activity)ACT_DOOR_OPEN); - PropSetSequence(nSequence); - - if ((nSequence == -1) || !HasAnimEvent(nSequence, AE_DOOR_OPEN)) - { - // No open anim event, we need to open the door here. - DoorActivate(); - } - } - } - else if ( IsDoorOpening() && HasSpawnFlags(SF_DOOR_USE_CLOSES) ) - { - // We've been used while opening, close. - m_hActivator = pActivator; - DoorClose(); - } - else if ( IsDoorClosing() || IsDoorAjar() ) - { - m_hActivator = pActivator; - DoorOpen( m_hActivator ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Closes the door if it is not already closed. -//----------------------------------------------------------------------------- -void CBasePropDoor::InputClose(inputdata_t &inputdata) -{ - if (!IsDoorClosed()) - { - m_OnClose.FireOutput(inputdata.pActivator, this); - DoorClose(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that locks the door. -//----------------------------------------------------------------------------- -void CBasePropDoor::InputLock(inputdata_t &inputdata) -{ - Lock(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Opens the door if it is not already open. -//----------------------------------------------------------------------------- -void CBasePropDoor::InputOpen(inputdata_t &inputdata) -{ - OpenIfUnlocked(inputdata.pActivator, NULL); -} - - -//----------------------------------------------------------------------------- -// Purpose: Opens the door away from a specified entity if it is not already open. -//----------------------------------------------------------------------------- -void CBasePropDoor::InputOpenAwayFrom(inputdata_t &inputdata) -{ - CBaseEntity *pOpenAwayFrom = gEntList.FindEntityByName( NULL, inputdata.value.String(), NULL, inputdata.pActivator, inputdata.pCaller ); - OpenIfUnlocked(inputdata.pActivator, pOpenAwayFrom); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -// FIXME: This function should be combined with DoorOpen, but doing that -// could break existing content. Fix after shipping! -// -// Input : *pOpenAwayFrom - -//----------------------------------------------------------------------------- -void CBasePropDoor::OpenIfUnlocked(CBaseEntity *pActivator, CBaseEntity *pOpenAwayFrom) -{ - // I'm locked, can't open - if (m_bLocked) - return; - - if (!IsDoorOpen() && !IsDoorOpening()) - { - // Play door unlock sounds. - PlayLockSounds(this, &m_ls, false, false); - m_OnOpen.FireOutput(pActivator, this); - DoorOpen(pOpenAwayFrom); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Opens the door if it is not already open. -//----------------------------------------------------------------------------- -void CBasePropDoor::InputToggle(inputdata_t &inputdata) -{ - if (IsDoorClosed()) - { - // I'm locked, can't open - if (m_bLocked) - return; - - DoorOpen(NULL); - } - else if (IsDoorOpen()) - { - DoorClose(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that unlocks the door. -//----------------------------------------------------------------------------- -void CBasePropDoor::InputUnlock(inputdata_t &inputdata) -{ - Unlock(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Locks the door so that it cannot be opened. -//----------------------------------------------------------------------------- -void CBasePropDoor::Lock(void) -{ - m_bLocked = true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Unlocks the door so that it can be opened. -//----------------------------------------------------------------------------- -void CBasePropDoor::Unlock(void) -{ - if (!m_nHardwareType) - { - // Doors with no hardware must always be locked. - DevWarning(1, "Unlocking prop_door '%s' at (%.0f %.0f %.0f) with no hardware. All openable doors must have hardware!\n", GetDebugName(), GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z); - } - - m_bLocked = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Causes the door to "do its thing", i.e. start moving, and cascade activation. -//----------------------------------------------------------------------------- -bool CBasePropDoor::DoorActivate( void ) -{ - if ( IsDoorOpen() && DoorCanClose( false ) ) - { - DoorClose(); - } - else - { - DoorOpen( m_hActivator ); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Starts the door opening. -//----------------------------------------------------------------------------- -void CBasePropDoor::DoorOpen(CBaseEntity *pOpenAwayFrom) -{ - // Don't bother if we're already doing this - if ( IsDoorOpen() || IsDoorOpening() ) - return; - - UpdateAreaPortals(true); - - // It could be going-down, if blocked. - ASSERT( IsDoorClosed() || IsDoorClosing() || IsDoorAjar() ); - - // Emit door moving and stop sounds on CHAN_STATIC so that the multicast doesn't - // filter them out and leave a client stuck with looping door sounds! - if (!HasSpawnFlags(SF_DOOR_SILENT)) - { - EmitSound( STRING( m_SoundMoving ) ); - - if ( m_hActivator && m_hActivator->IsPlayer() && !HasSpawnFlags( SF_DOOR_SILENT_TO_NPCS ) ) - { - CSoundEnt::InsertSound( SOUND_PLAYER, GetAbsOrigin(), 512, 0.5, this );//<>//magic number - } - } - - SetDoorState( DOOR_STATE_OPENING ); - - SetMoveDone(&CBasePropDoor::DoorOpenMoveDone); - - // Virtual function that starts the door moving for whatever type of door this is. - BeginOpening(pOpenAwayFrom); - - m_OnOpen.FireOutput(this, this); - - // Tell all the slaves - if ( HasSlaves() ) - { - int numDoors = m_hDoorList.Count(); - - CBasePropDoor *pLinkedDoor = NULL; - - // Open all linked doors - for ( int i = 0; i < numDoors; i++ ) - { - pLinkedDoor = m_hDoorList[i]; - - if ( pLinkedDoor != NULL ) - { - // If the door isn't already moving, get it moving - pLinkedDoor->m_hActivator = m_hActivator; - pLinkedDoor->DoorOpen( pOpenAwayFrom ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: The door has reached the open position. Either close automatically -// or wait for another activation. -//----------------------------------------------------------------------------- -void CBasePropDoor::DoorOpenMoveDone(void) -{ - SetDoorBlocker( NULL ); - - if (!HasSpawnFlags(SF_DOOR_SILENT)) - { - EmitSound( STRING( m_SoundOpen ) ); - } - - ASSERT(IsDoorOpening()); - SetDoorState( DOOR_STATE_OPEN ); - - if (WillAutoReturn()) - { - // In flWait seconds, DoorClose will fire, unless wait is -1, then door stays open - SetMoveDoneTime(m_flAutoReturnDelay + 0.1); - SetMoveDone(&CBasePropDoor::DoorAutoCloseThink); - - if (m_flAutoReturnDelay == -1) - { - SetNextThink( TICK_NEVER_THINK ); - } - } - - CAI_BaseNPC *pNPC = dynamic_cast(m_hActivator.Get()); - if (pNPC) - { - // Notify the NPC that opened us. - pNPC->OnDoorFullyOpen(this); - } - - m_OnFullyOpen.FireOutput(this, this); - - // Let the leaf class do its thing. - OnDoorOpened(); - - m_hActivator = NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Think function that tries to close the door. Used for autoreturn. -//----------------------------------------------------------------------------- -void CBasePropDoor::DoorAutoCloseThink(void) -{ - // When autoclosing, we check both sides so that we don't close in the player's - // face, or in an NPC's face for that matter, because they might be shooting - // through the doorway. - if ( !DoorCanClose( true ) ) - { - if (m_flAutoReturnDelay == -1) - { - SetNextThink( TICK_NEVER_THINK ); - } - else - { - // In flWait seconds, DoorClose will fire, unless wait is -1, then door stays open - SetMoveDoneTime(m_flAutoReturnDelay + 0.1); - SetMoveDone(&CBasePropDoor::DoorAutoCloseThink); - } - - return; - } - - DoorClose(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Starts the door closing. -//----------------------------------------------------------------------------- -void CBasePropDoor::DoorClose(void) -{ - // Don't bother if we're already doing this - if ( IsDoorClosed() || IsDoorClosing() ) - return; - - if (!HasSpawnFlags(SF_DOOR_SILENT)) - { - EmitSound( STRING( m_SoundMoving ) ); - - if ( m_hActivator && m_hActivator->IsPlayer() ) - { - CSoundEnt::InsertSound( SOUND_PLAYER, GetAbsOrigin(), 512, 0.5, this );//<>//magic number - } - } - - ASSERT(IsDoorOpen() || IsDoorOpening()); - SetDoorState( DOOR_STATE_CLOSING ); - - SetMoveDone(&CBasePropDoor::DoorCloseMoveDone); - - // This will set the movedone time. - BeginClosing(); - - m_OnClose.FireOutput(this, this); - - // Tell all the slaves - if ( HasSlaves() ) - { - int numDoors = m_hDoorList.Count(); - - CBasePropDoor *pLinkedDoor = NULL; - - // Open all linked doors - for ( int i = 0; i < numDoors; i++ ) - { - pLinkedDoor = m_hDoorList[i]; - - if ( pLinkedDoor != NULL ) - { - // If the door isn't already moving, get it moving - pLinkedDoor->DoorClose(); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: The door has reached the closed position. Return to quiescence. -//----------------------------------------------------------------------------- -void CBasePropDoor::DoorCloseMoveDone(void) -{ - SetDoorBlocker( NULL ); - - if (!HasSpawnFlags(SF_DOOR_SILENT)) - { - StopSound( STRING( m_SoundMoving ) ); - EmitSound( STRING( m_SoundClose ) ); - } - - ASSERT(IsDoorClosing()); - SetDoorState( DOOR_STATE_CLOSED ); - - m_OnFullyClosed.FireOutput(m_hActivator, this); - UpdateAreaPortals(false); - - // Let the leaf class do its thing. - OnDoorClosed(); - - m_hActivator = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOther - -//----------------------------------------------------------------------------- -void CBasePropDoor::MasterStartBlocked( CBaseEntity *pOther ) -{ - if ( HasSlaves() ) - { - int numDoors = m_hDoorList.Count(); - - CBasePropDoor *pLinkedDoor = NULL; - - // Open all linked doors - for ( int i = 0; i < numDoors; i++ ) - { - pLinkedDoor = m_hDoorList[i]; - - if ( pLinkedDoor != NULL ) - { - // If the door isn't already moving, get it moving - pLinkedDoor->OnStartBlocked( pOther ); - } - } - } - - // Start ourselves blocked - OnStartBlocked( pOther ); -} - -//----------------------------------------------------------------------------- -// Purpose: Called the first frame that the door is blocked while opening or closing. -// Input : pOther - The blocking entity. -//----------------------------------------------------------------------------- -void CBasePropDoor::StartBlocked( CBaseEntity *pOther ) -{ - m_bFirstBlocked = true; - - if ( GetMaster() != NULL ) - { - GetMaster()->MasterStartBlocked( pOther ); - return; - } - - // Start ourselves blocked - OnStartBlocked( pOther ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOther - -//----------------------------------------------------------------------------- -void CBasePropDoor::OnStartBlocked( CBaseEntity *pOther ) -{ - if ( m_bFirstBlocked == false ) - { - DoorStop(); - } - - SetDoorBlocker( pOther ); - - if (!HasSpawnFlags(SF_DOOR_SILENT)) - { - StopSound( STRING( m_SoundMoving ) ); - } - - // - // Fire whatever events we need to due to our blocked state. - // - if (IsDoorClosing()) - { - // Closed into an NPC, open. - if ( pOther->MyNPCPointer() ) - { - DoorOpen( pOther ); - } - m_OnBlockedClosing.FireOutput(pOther, this); - } - else - { - // Opened into an NPC, close. - if ( pOther->MyNPCPointer() ) - { - DoorClose(); - } - - CAI_BaseNPC *pNPC = dynamic_cast(m_hActivator.Get()); - - if ( pNPC != NULL ) - { - // Notify the NPC that tried to open us. - pNPC->OnDoorBlocked( this ); - } - - m_OnBlockedOpening.FireOutput( pOther, this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Called every frame when the door is blocked while opening or closing. -// Input : pOther - The blocking entity. -//----------------------------------------------------------------------------- -void CBasePropDoor::Blocked(CBaseEntity *pOther) -{ - // dvs: TODO: will prop_door apply any blocking damage? - // Hurt the blocker a little. - //if (m_flBlockDamage) - //{ - // pOther->TakeDamage(CTakeDamageInfo(this, this, m_flBlockDamage, DMG_CRUSH)); - //} - - if ( m_bForceClosed && ( pOther->GetMoveType() == MOVETYPE_VPHYSICS ) && - ( pOther->m_takedamage == DAMAGE_NO || pOther->m_takedamage == DAMAGE_EVENTS_ONLY ) ) - { - EntityPhysics_CreateSolver( this, pOther, true, 4.0f ); - } - else if ( m_bForceClosed && ( pOther->GetMoveType() == MOVETYPE_VPHYSICS ) && ( pOther->m_takedamage == DAMAGE_YES ) ) - { - pOther->TakeDamage( CTakeDamageInfo( this, this, pOther->GetHealth(), DMG_CRUSH ) ); - } - - // If we're set to force ourselves closed, keep going - if ( m_bForceClosed ) - return; - - // If a door has a negative wait, it would never come back if blocked, - // so let it just squash the object to death real fast. -// if (m_flAutoReturnDelay >= 0) -// { -// if (IsDoorClosing()) -// { -// DoorOpen(); -// } -// else -// { -// DoorClose(); -// } -// } - - // Block all door pieces with the same targetname here. -// if (GetEntityName() != NULL_STRING) -// { -// CBaseEntity pTarget = NULL; -// for (;;) -// { -// pTarget = gEntList.FindEntityByName(pTarget, GetEntityName() ); -// -// if (pTarget != this) -// { -// if (!pTarget) -// break; -// -// if (FClassnameIs(pTarget, "prop_door_rotating")) -// { -// CPropDoorRotating *pDoor = (CPropDoorRotating *)pTarget; -// -// if (pDoor->m_fAutoReturnDelay >= 0) -// { -// if (pDoor->GetAbsVelocity() == GetAbsVelocity() && pDoor->GetLocalAngularVelocity() == GetLocalAngularVelocity()) -// { -// // this is the most hacked, evil, bastardized thing I've ever seen. kjb -// if (FClassnameIs(pTarget, "prop_door_rotating")) -// { -// // set angles to realign rotating doors -// pDoor->SetLocalAngles(GetLocalAngles()); -// pDoor->SetLocalAngularVelocity(vec3_angle); -// } -// else -// //{ -// // // set origin to realign normal doors -// // pDoor->SetLocalOrigin(GetLocalOrigin()); -// // pDoor->SetAbsVelocity(vec3_origin);// stop! -// //} -// } -// -// if (IsDoorClosing()) -// { -// pDoor->DoorOpen(); -// } -// else -// { -// pDoor->DoorClose(); -// } -// } -// } -// } -// } -// } -} - - -//----------------------------------------------------------------------------- -// Purpose: Called the first frame that the door is unblocked while opening or closing. -//----------------------------------------------------------------------------- -void CBasePropDoor::EndBlocked( void ) -{ - if ( GetMaster() != NULL ) - { - GetMaster()->EndBlocked(); - return; - } - - if ( HasSlaves() ) - { - int numDoors = m_hDoorList.Count(); - - CBasePropDoor *pLinkedDoor = NULL; - - // Check all links as well - for ( int i = 0; i < numDoors; i++ ) - { - pLinkedDoor = m_hDoorList[i]; - - if ( pLinkedDoor != NULL ) - { - // Make sure they can close as well - pLinkedDoor->OnEndBlocked(); - } - } - } - - // Emit door moving and stop sounds on CHAN_STATIC so that the multicast doesn't - // filter them out and leave a client stuck with looping door sounds! - if (!HasSpawnFlags(SF_DOOR_SILENT)) - { - EmitSound( STRING( m_SoundMoving ) ); - } - - // - // Fire whatever events we need to due to our unblocked state. - // - if (IsDoorClosing()) - { - m_OnUnblockedClosing.FireOutput(this, this); - } - else - { - m_OnUnblockedOpening.FireOutput(this, this); - } - - OnEndBlocked(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePropDoor::OnEndBlocked( void ) -{ - if ( m_bFirstBlocked ) - return; - - // Restart us going - DoorResume(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pNPC - -//----------------------------------------------------------------------------- -bool CBasePropDoor::NPCOpenDoor( CAI_BaseNPC *pNPC ) -{ - // dvs: TODO: use activator filter here - // dvs: TODO: outboard entity containing rules for whether door is operable? - - if ( IsDoorClosed() ) - { - // Use the door - Use( pNPC, pNPC, USE_ON, 0 ); - } - - return true; -} - -bool CBasePropDoor::TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ) -{ - if ( !VPhysicsGetObject() ) - return false; - - CStudioHdr *pStudioHdr = GetModelPtr( ); - if (!pStudioHdr) - return false; - - if ( !( pStudioHdr->contents() & mask ) ) - return false; - - physcollision->TraceBox( ray, VPhysicsGetObject()->GetCollide(), GetAbsOrigin(), GetAbsAngles(), &trace ); - - if ( trace.DidHit() ) - { - trace.surface.surfaceProps = VPhysicsGetObject()->GetMaterialIndex(); - return true; - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Custom trace filter for doors -// Will only test against entities and rejects physics objects below a mass threshold -//----------------------------------------------------------------------------- - -class CTraceFilterDoor : public CTraceFilterEntitiesOnly -{ -public: - // It does have a base, but we'll never network anything below here.. - DECLARE_CLASS_NOBASE( CTraceFilterDoor ); - - CTraceFilterDoor( const IHandleEntity *pDoor, const IHandleEntity *passentity, int collisionGroup ) - : m_pDoor(pDoor), m_pPassEnt(passentity), m_collisionGroup(collisionGroup) - { - } - - virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) - { - if ( !StandardFilterRules( pHandleEntity, contentsMask ) ) - return false; - - if ( !PassServerEntityFilter( pHandleEntity, m_pDoor ) ) - return false; - - if ( !PassServerEntityFilter( pHandleEntity, m_pPassEnt ) ) - return false; - - // Don't test if the game code tells us we should ignore this collision... - CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); - - if ( pEntity ) - { - if ( !pEntity->ShouldCollide( m_collisionGroup, contentsMask ) ) - return false; - - if ( !g_pGameRules->ShouldCollide( m_collisionGroup, pEntity->GetCollisionGroup() ) ) - return false; - - // If objects are small enough and can move, close on them - if ( pEntity->GetMoveType() == MOVETYPE_VPHYSICS ) - { - IPhysicsObject *pPhysics = pEntity->VPhysicsGetObject(); - Assert(pPhysics); - - // Must either be squashable or very light - if ( pPhysics->IsMoveable() && pPhysics->GetMass() < 32 ) - return false; - } - } - - return true; - } - -private: - - const IHandleEntity *m_pDoor; - const IHandleEntity *m_pPassEnt; - int m_collisionGroup; -}; - -inline void TraceHull_Door( const CBasePropDoor *pDoor, const Vector &vecAbsStart, const Vector &vecAbsEnd, const Vector &hullMin, - const Vector &hullMax, unsigned int mask, const CBaseEntity *ignore, - int collisionGroup, trace_t *ptr ) -{ - Ray_t ray; - ray.Init( vecAbsStart, vecAbsEnd, hullMin, hullMax ); - CTraceFilterDoor traceFilter( pDoor, ignore, collisionGroup ); - enginetrace->TraceRay( ray, mask, &traceFilter, ptr ); -} - -// Check directions for door movement -enum doorCheck_e -{ - DOOR_CHECK_FORWARD, // Door's forward opening direction - DOOR_CHECK_BACKWARD, // Door's backward opening direction - DOOR_CHECK_FULL, // Door's complete movement volume -}; - - -enum PropDoorRotatingSpawnPos_t -{ - DOOR_SPAWN_CLOSED = 0, - DOOR_SPAWN_OPEN_FORWARD, - DOOR_SPAWN_OPEN_BACK, - DOOR_SPAWN_AJAR, -}; - -enum PropDoorRotatingOpenDirection_e -{ - DOOR_ROTATING_OPEN_BOTH_WAYS = 0, - DOOR_ROTATING_OPEN_FORWARD, - DOOR_ROTATING_OPEN_BACKWARD, -}; - -//=============================================== -// Rotating prop door -//=============================================== - -class CPropDoorRotating : public CBasePropDoor -{ - DECLARE_CLASS( CPropDoorRotating, CBasePropDoor ); - -public: - - ~CPropDoorRotating(); - - int DrawDebugTextOverlays(void); - - void Spawn( void ); - void MoveDone( void ); - void BeginOpening(CBaseEntity *pOpenAwayFrom); - void BeginClosing( void ); - void OnRestore( void ); - - void DoorTeleportToSpawnPosition(); - - void GetNPCOpenData(CAI_BaseNPC *pNPC, opendata_t &opendata); - - void DoorClose( void ); - bool DoorCanClose( bool bAutoClose ); - void DoorOpen( CBaseEntity *pOpenAwayFrom ); - - void OnDoorOpened(); - void OnDoorClosed(); - - void DoorResume( void ); - void DoorStop( void ); - - float GetOpenInterval(); - - bool OverridePropdata() { return true; } - - void InputSetSpeed(inputdata_t &inputdata); - - DECLARE_DATADESC(); - -private: - - bool IsHingeOnLeft(); - - void AngularMove(const QAngle &vecDestAngle, float flSpeed); - void CalculateDoorVolume( QAngle closedAngles, QAngle openAngles, Vector *destMins, Vector *destMaxs ); - - bool CheckDoorClear( doorCheck_e state ); - - doorCheck_e GetOpenState( void ); - - void InputSetRotationDistance ( inputdata_t &inputdata ); // Set the degree difference between open and closed - - void CalcOpenAngles ( void ); // Subroutine to setup the m_angRotation QAngles based on the m_flDistance variable - - Vector m_vecAxis; // The axis of rotation. - float m_flDistance; // How many degrees we rotate between open and closed. - - PropDoorRotatingSpawnPos_t m_eSpawnPosition; - PropDoorRotatingOpenDirection_e m_eOpenDirection; - - QAngle m_angRotationAjar; // Angles to spawn at if we are set to spawn ajar. - QAngle m_angRotationClosed; // Our angles when we are fully closed. - QAngle m_angRotationOpenForward; // Our angles when we are fully open towards our forward vector. - QAngle m_angRotationOpenBack; // Our angles when we are fully open away from our forward vector. - - QAngle m_angGoal; - - Vector m_vecForwardBoundsMin; - Vector m_vecForwardBoundsMax; - Vector m_vecBackBoundsMin; - Vector m_vecBackBoundsMax; - - CHandle m_hDoorBlocker; -}; - - -BEGIN_DATADESC(CPropDoorRotating) - DEFINE_KEYFIELD(m_eSpawnPosition, FIELD_INTEGER, "spawnpos"), - DEFINE_KEYFIELD(m_eOpenDirection, FIELD_INTEGER, "opendir" ), - DEFINE_KEYFIELD(m_vecAxis, FIELD_VECTOR, "axis"), - DEFINE_KEYFIELD(m_flDistance, FIELD_FLOAT, "distance"), - DEFINE_KEYFIELD( m_angRotationAjar, FIELD_VECTOR, "ajarangles" ), - DEFINE_FIELD( m_angRotationClosed, FIELD_VECTOR ), - DEFINE_FIELD( m_angRotationOpenForward, FIELD_VECTOR ), - DEFINE_FIELD( m_angRotationOpenBack, FIELD_VECTOR ), - DEFINE_FIELD( m_angGoal, FIELD_VECTOR ), - DEFINE_FIELD( m_hDoorBlocker, FIELD_EHANDLE ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetRotationDistance", InputSetRotationDistance ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetSpeed", InputSetSpeed ), - //m_vecForwardBoundsMin - //m_vecForwardBoundsMax - //m_vecBackBoundsMin - //m_vecBackBoundsMax -END_DATADESC() - -LINK_ENTITY_TO_CLASS(prop_door_rotating, CPropDoorRotating); - -//----------------------------------------------------------------------------- -// Destructor -//----------------------------------------------------------------------------- -CPropDoorRotating::~CPropDoorRotating( void ) -{ - // Remove our door blocker entity - if ( m_hDoorBlocker != NULL ) - { - UTIL_Remove( m_hDoorBlocker ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &mins1 - -// &maxs1 - -// &mins2 - -// &maxs2 - -// *destMins - -// *destMaxs - -//----------------------------------------------------------------------------- -void UTIL_ComputeAABBForBounds( const Vector &mins1, const Vector &maxs1, const Vector &mins2, const Vector &maxs2, Vector *destMins, Vector *destMaxs ) -{ - // Find the minimum extents - (*destMins)[0] = MIN( mins1[0], mins2[0] ); - (*destMins)[1] = MIN( mins1[1], mins2[1] ); - (*destMins)[2] = MIN( mins1[2], mins2[2] ); - - // Find the maximum extents - (*destMaxs)[0] = MAX( maxs1[0], maxs2[0] ); - (*destMaxs)[1] = MAX( maxs1[1], maxs2[1] ); - (*destMaxs)[2] = MAX( maxs1[2], maxs2[2] ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropDoorRotating::Spawn() -{ - // Doors are built closed, so save the current angles as the closed angles. - m_angRotationClosed = GetLocalAngles(); - - // The axis of rotation must be along the z axis for now. - // NOTE: If you change this, be sure to change IsHingeOnLeft to account for it! - m_vecAxis = Vector(0, 0, 1); - - CalcOpenAngles(); - - // Call this last! It relies on stuff we calculated above. - BaseClass::Spawn(); - - // We have to call this after we call the base Spawn because it requires - // that the model already be set. - if ( IsHingeOnLeft() ) - { - swap( m_angRotationOpenForward, m_angRotationOpenBack ); - } - - // Figure out our volumes of movement as this door opens - CalculateDoorVolume( GetLocalAngles(), m_angRotationOpenForward, &m_vecForwardBoundsMin, &m_vecForwardBoundsMax ); - CalculateDoorVolume( GetLocalAngles(), m_angRotationOpenBack, &m_vecBackBoundsMin, &m_vecBackBoundsMax ); -} - -//----------------------------------------------------------------------------- -// Purpose: Setup the m_angRotationOpenForward and m_angRotationOpenBack variables based on -// the m_flDistance variable. Also restricts m_flDistance > 0. -//----------------------------------------------------------------------------- -void CPropDoorRotating::CalcOpenAngles() -{ - // HACK: convert the axis of rotation to dPitch dYaw dRoll - Vector vecMoveDir(m_vecAxis.y, m_vecAxis.z, m_vecAxis.x); - - if (m_flDistance == 0) - { - m_flDistance = 90; - } - m_flDistance = fabs(m_flDistance); - - // Calculate our orientation when we are fully open. - m_angRotationOpenForward.x = m_angRotationClosed.x - (vecMoveDir.x * m_flDistance); - m_angRotationOpenForward.y = m_angRotationClosed.y - (vecMoveDir.y * m_flDistance); - m_angRotationOpenForward.z = m_angRotationClosed.z - (vecMoveDir.z * m_flDistance); - - m_angRotationOpenBack.x = m_angRotationClosed.x + (vecMoveDir.x * m_flDistance); - m_angRotationOpenBack.y = m_angRotationClosed.y + (vecMoveDir.y * m_flDistance); - m_angRotationOpenBack.z = m_angRotationClosed.z + (vecMoveDir.z * m_flDistance); -} - -//----------------------------------------------------------------------------- -// Figures out whether the door's hinge is on its left or its right. -// Assumes: -// - that the door is hinged through its origin. -// - that the origin is at one edge of the door (revolving doors will give -// a random answer) -// - that the hinge axis lies along the z axis -//----------------------------------------------------------------------------- -bool CPropDoorRotating::IsHingeOnLeft() -{ - // - // Find the point farthest from the hinge in 2D. - // - Vector vecMins; - Vector vecMaxs; - CollisionProp()->WorldSpaceAABB( &vecMins, &vecMaxs ); - - vecMins -= GetAbsOrigin(); - vecMaxs -= GetAbsOrigin(); - - // Throw out z -- we only care about 2D distance. - // NOTE: if we allow for arbitrary hinge axes, this needs to change - vecMins.z = vecMaxs.z = 0; - - Vector vecPointCheck; - if ( vecMins.LengthSqr() > vecMaxs.LengthSqr() ) - { - vecPointCheck = vecMins; - } - else - { - vecPointCheck = vecMaxs; - } - - // - // See if the projection of that point lies along our right vector. - // If it does, the door is hinged on its left. - // - Vector vecRight; - GetVectors( NULL, &vecRight, NULL ); - float flDot = DotProduct( vecPointCheck, vecRight ); - - return ( flDot > 0 ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -doorCheck_e CPropDoorRotating::GetOpenState( void ) -{ - return ( m_angGoal == m_angRotationOpenForward ) ? DOOR_CHECK_FORWARD : DOOR_CHECK_BACKWARD; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropDoorRotating::OnDoorOpened( void ) -{ - if ( m_hDoorBlocker != NULL ) - { - // Allow passage through this blocker while open - m_hDoorBlocker->AddSolidFlags( FSOLID_NOT_SOLID ); - - if ( g_debug_doors.GetBool() ) - { - NDebugOverlay::Box( GetAbsOrigin(), m_hDoorBlocker->CollisionProp()->OBBMins(), m_hDoorBlocker->CollisionProp()->OBBMaxs(), 0, 255, 0, true, 1.0f ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropDoorRotating::OnDoorClosed( void ) -{ - if ( m_hDoorBlocker != NULL ) - { - // Destroy the blocker that was preventing NPCs from getting in our way. - UTIL_Remove( m_hDoorBlocker ); - - if ( g_debug_doors.GetBool() ) - { - NDebugOverlay::Box( GetAbsOrigin(), m_hDoorBlocker->CollisionProp()->OBBMins(), m_hDoorBlocker->CollisionProp()->OBBMaxs(), 0, 255, 0, true, 1.0f ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns whether the way is clear for the door to close. -// Input : state - Which sides to check, forward, backward, or both. -// Output : Returns true if the door can close, false if the way is blocked. -//----------------------------------------------------------------------------- -bool CPropDoorRotating::DoorCanClose( bool bAutoClose ) -{ - if ( GetMaster() != NULL ) - return GetMaster()->DoorCanClose( bAutoClose ); - - // Check all slaves - if ( HasSlaves() ) - { - int numDoors = m_hDoorList.Count(); - - CPropDoorRotating *pLinkedDoor = NULL; - - // Check all links as well - for ( int i = 0; i < numDoors; i++ ) - { - pLinkedDoor = dynamic_cast((CBasePropDoor *)m_hDoorList[i]); - - if ( pLinkedDoor != NULL ) - { - if ( !pLinkedDoor->CheckDoorClear( bAutoClose ? DOOR_CHECK_FULL : pLinkedDoor->GetOpenState() ) ) - return false; - } - } - } - - // See if our path of movement is clear to allow us to shut - return CheckDoorClear( bAutoClose ? DOOR_CHECK_FULL : GetOpenState() ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : closedAngles - -// openAngles - -// *destMins - -// *destMaxs - -//----------------------------------------------------------------------------- -void CPropDoorRotating::CalculateDoorVolume( QAngle closedAngles, QAngle openAngles, Vector *destMins, Vector *destMaxs ) -{ - // Save our current angles and move to our start angles - QAngle saveAngles = GetLocalAngles(); - SetLocalAngles( closedAngles ); - - // Find our AABB at the closed state - Vector closedMins, closedMaxs; - CollisionProp()->WorldSpaceAABB( &closedMins, &closedMaxs ); - - SetLocalAngles( openAngles ); - - // Find our AABB at the open state - Vector openMins, openMaxs; - CollisionProp()->WorldSpaceAABB( &openMins, &openMaxs ); - - // Reset our angles to our starting angles - SetLocalAngles( saveAngles ); - - // Find the minimum extents - UTIL_ComputeAABBForBounds( closedMins, closedMaxs, openMins, openMaxs, destMins, destMaxs ); - - // Move this back into local space - *destMins -= GetAbsOrigin(); - *destMaxs -= GetAbsOrigin(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropDoorRotating::OnRestore( void ) -{ - BaseClass::OnRestore(); - - // Figure out our volumes of movement as this door opens - CalculateDoorVolume( GetLocalAngles(), m_angRotationOpenForward, &m_vecForwardBoundsMin, &m_vecForwardBoundsMax ); - CalculateDoorVolume( GetLocalAngles(), m_angRotationOpenBack, &m_vecBackBoundsMin, &m_vecBackBoundsMax ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : forward - -// mask - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CPropDoorRotating::CheckDoorClear( doorCheck_e state ) -{ - Vector moveMins; - Vector moveMaxs; - - switch ( state ) - { - case DOOR_CHECK_FORWARD: - moveMins = m_vecForwardBoundsMin; - moveMaxs = m_vecForwardBoundsMax; - break; - - case DOOR_CHECK_BACKWARD: - moveMins = m_vecBackBoundsMin; - moveMaxs = m_vecBackBoundsMax; - break; - - default: - case DOOR_CHECK_FULL: - UTIL_ComputeAABBForBounds( m_vecForwardBoundsMin, m_vecForwardBoundsMax, m_vecBackBoundsMin, m_vecBackBoundsMax, &moveMins, &moveMaxs ); - break; - } - - // Look for blocking entities, ignoring ourselves and the entity that opened us. - trace_t tr; - TraceHull_Door( this, GetAbsOrigin(), GetAbsOrigin(), moveMins, moveMaxs, MASK_SOLID, GetActivator(), COLLISION_GROUP_NONE, &tr ); - if ( tr.allsolid || tr.startsolid ) - { - if ( g_debug_doors.GetBool() ) - { - NDebugOverlay::Box( GetAbsOrigin(), moveMins, moveMaxs, 255, 0, 0, true, 10.0f ); - - if ( tr.m_pEnt ) - { - NDebugOverlay::Box( tr.m_pEnt->GetAbsOrigin(), tr.m_pEnt->CollisionProp()->OBBMins(), tr.m_pEnt->CollisionProp()->OBBMaxs(), 220, 220, 0, true, 10.0f ); - } - } - - return false; - } - - if ( g_debug_doors.GetBool() ) - { - NDebugOverlay::Box( GetAbsOrigin(), moveMins, moveMaxs, 0, 255, 0, true, 10.0f ); - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Puts the door in its appropriate position for spawning. -//----------------------------------------------------------------------------- -void CPropDoorRotating::DoorTeleportToSpawnPosition() -{ - QAngle angSpawn; - - // The Start Open spawnflag trumps the choices field - if ( ( HasSpawnFlags( SF_DOOR_START_OPEN_OBSOLETE ) ) || ( m_eSpawnPosition == DOOR_SPAWN_OPEN_FORWARD ) ) - { - angSpawn = m_angRotationOpenForward; - SetDoorState( DOOR_STATE_OPEN ); - } - else if ( m_eSpawnPosition == DOOR_SPAWN_OPEN_BACK ) - { - angSpawn = m_angRotationOpenBack; - SetDoorState( DOOR_STATE_OPEN ); - } - else if ( m_eSpawnPosition == DOOR_SPAWN_CLOSED ) - { - angSpawn = m_angRotationClosed; - SetDoorState( DOOR_STATE_CLOSED ); - } - else if ( m_eSpawnPosition == DOOR_SPAWN_AJAR ) - { - angSpawn = m_angRotationAjar; - SetDoorState( DOOR_STATE_AJAR ); - } - else - { - // Bogus spawn position setting! - Assert( false ); - angSpawn = m_angRotationClosed; - SetDoorState( DOOR_STATE_CLOSED ); - } - - SetLocalAngles( angSpawn ); - - // Doesn't relink; that's done in Spawn. -} - - -//----------------------------------------------------------------------------- -// Purpose: After rotating, set angle to exact final angle, call "move done" function. -//----------------------------------------------------------------------------- -void CPropDoorRotating::MoveDone() -{ - SetLocalAngles(m_angGoal); - SetLocalAngularVelocity(vec3_angle); - SetMoveDoneTime(-1); - BaseClass::MoveDone(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Calculate m_vecVelocity and m_flNextThink to reach vecDest from -// GetLocalOrigin() traveling at flSpeed. Just like LinearMove, but rotational. -// Input : vecDestAngle - -// flSpeed - -//----------------------------------------------------------------------------- -void CPropDoorRotating::AngularMove(const QAngle &vecDestAngle, float flSpeed) -{ - ASSERTSZ(flSpeed != 0, "AngularMove: no speed is defined!"); - - m_angGoal = vecDestAngle; - - // Already there? - if (vecDestAngle == GetLocalAngles()) - { - MoveDone(); - return; - } - - // Set destdelta to the vector needed to move. - QAngle vecDestDelta = vecDestAngle - GetLocalAngles(); - - // Divide by speed to get time to reach dest - float flTravelTime = vecDestDelta.Length() / flSpeed; - - // Call MoveDone when destination angles are reached. - SetMoveDoneTime(flTravelTime); - - // Scale the destdelta vector by the time spent traveling to get velocity. - SetLocalAngularVelocity(vecDestDelta * (1.0 / flTravelTime)); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropDoorRotating::BeginOpening(CBaseEntity *pOpenAwayFrom) -{ - // Determine the direction to open. - QAngle angOpen = m_angRotationOpenForward; - doorCheck_e eDirCheck = DOOR_CHECK_FORWARD; - - if ( m_eOpenDirection == DOOR_ROTATING_OPEN_FORWARD ) - { - eDirCheck = DOOR_CHECK_FORWARD; - angOpen = m_angRotationOpenForward; - } - else if ( m_eOpenDirection == DOOR_ROTATING_OPEN_BACKWARD ) - { - eDirCheck = DOOR_CHECK_BACKWARD; - angOpen = m_angRotationOpenBack; - } - else // Can open either direction, test to see which is appropriate - { - if (pOpenAwayFrom != NULL) - { - Vector vecForwardDoor; - GetVectors(&vecForwardDoor, NULL, NULL); - - if (vecForwardDoor.Dot(pOpenAwayFrom->GetAbsOrigin()) > vecForwardDoor.Dot(GetAbsOrigin())) - { - angOpen = m_angRotationOpenBack; - eDirCheck = DOOR_CHECK_BACKWARD; - } - } - - // If player is opening us and we're opening away from them, and we'll be - // blocked if we open away from them, open toward them. - if (IsPlayerOpening() && (pOpenAwayFrom && pOpenAwayFrom->IsPlayer()) && !CheckDoorClear(eDirCheck)) - { - if (eDirCheck == DOOR_CHECK_FORWARD) - { - angOpen = m_angRotationOpenBack; - eDirCheck = DOOR_CHECK_BACKWARD; - } - else - { - angOpen = m_angRotationOpenForward; - eDirCheck = DOOR_CHECK_FORWARD; - } - } - } - - // Create the door blocker - Vector mins, maxs; - if ( eDirCheck == DOOR_CHECK_FORWARD ) - { - mins = m_vecForwardBoundsMin; - maxs = m_vecForwardBoundsMax; - } - else - { - mins = m_vecBackBoundsMin; - maxs = m_vecBackBoundsMax; - } - - if ( m_hDoorBlocker != NULL ) - { - UTIL_Remove( m_hDoorBlocker ); - } - - // Create a blocking entity to keep random entities out of our movement path - m_hDoorBlocker = CEntityBlocker::Create( GetAbsOrigin(), mins, maxs, pOpenAwayFrom, false ); - - Vector volumeCenter = ((mins+maxs) * 0.5f) + GetAbsOrigin(); - - // Ignoring the Z - float volumeRadius = MAX( fabs(mins.x), maxs.x ); - volumeRadius = MAX( volumeRadius, MAX( fabs(mins.y), maxs.y ) ); - - // Debug - if ( g_debug_doors.GetBool() ) - { - NDebugOverlay::Cross3D( volumeCenter, -Vector(volumeRadius,volumeRadius,volumeRadius), Vector(volumeRadius,volumeRadius,volumeRadius), 255, 0, 0, true, 1.0f ); - } - - // Make respectful entities move away from our path - if( !HasSpawnFlags(SF_DOOR_SILENT_TO_NPCS) ) - { - CSoundEnt::InsertSound( SOUND_MOVE_AWAY, volumeCenter, (int)volumeRadius, 0.5f, pOpenAwayFrom ); - } - - // Do final setup - if ( m_hDoorBlocker != NULL ) - { - // Only block NPCs - m_hDoorBlocker->SetCollisionGroup( COLLISION_GROUP_DOOR_BLOCKER ); - - // If we hit something while opening, just stay unsolid until we try again - if ( CheckDoorClear( eDirCheck ) == false ) - { - m_hDoorBlocker->AddSolidFlags( FSOLID_NOT_SOLID ); - } - - if ( g_debug_doors.GetBool() ) - { - NDebugOverlay::Box( GetAbsOrigin(), m_hDoorBlocker->CollisionProp()->OBBMins(), m_hDoorBlocker->CollisionProp()->OBBMaxs(), 255, 0, 0, true, 1.0f ); - } - } - - AngularMove(angOpen, m_flSpeed); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropDoorRotating::BeginClosing( void ) -{ - if ( m_hDoorBlocker != NULL ) - { - // Become solid again unless we're already being blocked - if ( CheckDoorClear( GetOpenState() ) ) - { - m_hDoorBlocker->RemoveSolidFlags( FSOLID_NOT_SOLID ); - } - - if ( g_debug_doors.GetBool() ) - { - NDebugOverlay::Box( GetAbsOrigin(), m_hDoorBlocker->CollisionProp()->OBBMins(), m_hDoorBlocker->CollisionProp()->OBBMaxs(), 255, 0, 0, true, 1.0f ); - } - } - - AngularMove(m_angRotationClosed, m_flSpeed); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropDoorRotating::DoorStop( void ) -{ - SetLocalAngularVelocity( vec3_angle ); - SetMoveDoneTime( -1 ); -} - -//----------------------------------------------------------------------------- -// Purpose: Restart a door moving that was temporarily paused -//----------------------------------------------------------------------------- -void CPropDoorRotating::DoorResume( void ) -{ - // Restart our angular movement - AngularMove( m_angGoal, m_flSpeed ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : vecMoveDir - -// opendata - -//----------------------------------------------------------------------------- -void CPropDoorRotating::GetNPCOpenData(CAI_BaseNPC *pNPC, opendata_t &opendata) -{ - // dvs: TODO: finalize open position, direction, activity - Vector vecForward; - Vector vecRight; - AngleVectors(GetAbsAngles(), &vecForward, &vecRight, NULL); - - // - // Figure out where the NPC should stand to open this door, - // and what direction they should face. - // - opendata.vecStandPos = GetAbsOrigin() - (vecRight * 24); - opendata.vecStandPos.z -= 54; - - Vector vecNPCOrigin = pNPC->GetAbsOrigin(); - - if (pNPC->GetAbsOrigin().Dot(vecForward) > GetAbsOrigin().Dot(vecForward)) - { - // In front of the door relative to the door's forward vector. - opendata.vecStandPos += vecForward * 64; - opendata.vecFaceDir = -vecForward; - } - else - { - // Behind the door relative to the door's forward vector. - opendata.vecStandPos -= vecForward * 64; - opendata.vecFaceDir = vecForward; - } - - opendata.eActivity = ACT_OPEN_DOOR; -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns how long it will take this door to open. -//----------------------------------------------------------------------------- -float CPropDoorRotating::GetOpenInterval() -{ - // set destdelta to the vector needed to move - QAngle vecDestDelta = m_angRotationOpenForward - GetLocalAngles(); - - // divide by speed to get time to reach dest - return vecDestDelta.Length() / m_flSpeed; -} - - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CPropDoorRotating::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - Q_snprintf(tempstr, sizeof(tempstr),"Avelocity: %.2f %.2f %.2f", GetLocalAngularVelocity().x, GetLocalAngularVelocity().y, GetLocalAngularVelocity().z); - EntityText( text_offset, tempstr, 0); - text_offset++; - - if ( IsDoorOpen() ) - { - Q_strncpy(tempstr, "DOOR STATE: OPEN", sizeof(tempstr)); - } - else if ( IsDoorClosed() ) - { - Q_strncpy(tempstr, "DOOR STATE: CLOSED", sizeof(tempstr)); - } - else if ( IsDoorOpening() ) - { - Q_strncpy(tempstr, "DOOR STATE: OPENING", sizeof(tempstr)); - } - else if ( IsDoorClosing() ) - { - Q_strncpy(tempstr, "DOOR STATE: CLOSING", sizeof(tempstr)); - } - else if ( IsDoorAjar() ) - { - Q_strncpy(tempstr, "DOOR STATE: AJAR", sizeof(tempstr)); - } - EntityText( text_offset, tempstr, 0); - text_offset++; - } - - return text_offset; -} - -//----------------------------------------------------------------------------- -// Purpose: Change this door's distance (in degrees) between open and closed -//----------------------------------------------------------------------------- -void CPropDoorRotating::InputSetRotationDistance( inputdata_t &inputdata ) -{ - m_flDistance = inputdata.value.Float(); - - // Recalculate our open volume - CalcOpenAngles(); - CalculateDoorVolume( GetLocalAngles(), m_angRotationOpenForward, &m_vecForwardBoundsMin, &m_vecForwardBoundsMax ); - CalculateDoorVolume( GetLocalAngles(), m_angRotationOpenBack, &m_vecBackBoundsMin, &m_vecBackBoundsMax ); -} - -// Debug sphere -class CPhysSphere : public CPhysicsProp -{ - DECLARE_CLASS( CPhysSphere, CPhysicsProp ); -public: - virtual bool OverridePropdata() { return true; } - bool CreateVPhysics() - { - SetSolid( SOLID_BBOX ); - SetCollisionBounds( -Vector(12,12,12), Vector(12,12,12) ); - objectparams_t params = g_PhysDefaultObjectParams; - params.pGameData = static_cast(this); - IPhysicsObject *pPhysicsObject = physenv->CreateSphereObject( 12, 0, GetAbsOrigin(), GetAbsAngles(), ¶ms, false ); - if ( pPhysicsObject ) - { - VPhysicsSetObject( pPhysicsObject ); - SetMoveType( MOVETYPE_VPHYSICS ); - pPhysicsObject->Wake(); - } - - return true; - } -}; - -void CPropDoorRotating::InputSetSpeed(inputdata_t &inputdata) -{ - AssertMsg1(inputdata.value.Float() > 0.0f, "InputSetSpeed on %s called with negative parameter!", GetDebugName() ); - m_flSpeed = inputdata.value.Float(); - DoorResume(); -} - -LINK_ENTITY_TO_CLASS( prop_sphere, CPhysSphere ); - - -// ------------------------------------------------------------------------------------------ // -// Special version of func_physbox. -// ------------------------------------------------------------------------------------------ // -class CPhysBoxMultiplayer : public CPhysBox, public IMultiplayerPhysics -{ -public: - DECLARE_CLASS( CPhysBoxMultiplayer, CPhysBox ); - - virtual int GetMultiplayerPhysicsMode() - { - return m_iPhysicsMode; - } - - virtual float GetMass() - { - return m_fMass; - } - - virtual bool IsAsleep() - { - return VPhysicsGetObject()->IsAsleep(); - } - - CNetworkVar( int, m_iPhysicsMode ); // One of the PHYSICS_MULTIPLAYER_ defines. - CNetworkVar( float, m_fMass ); - - - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - virtual void Activate() - { - BaseClass::Activate(); - SetCollisionGroup( COLLISION_GROUP_PUSHAWAY ); - m_fMass = VPhysicsGetObject()->GetMass(); - } -}; - -LINK_ENTITY_TO_CLASS( func_physbox_multiplayer, CPhysBoxMultiplayer ); - -BEGIN_DATADESC( CPhysBoxMultiplayer ) -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CPhysBoxMultiplayer, DT_PhysBoxMultiplayer ) - SendPropInt( SENDINFO( m_iPhysicsMode ), 1, SPROP_UNSIGNED ), - SendPropFloat( SENDINFO( m_fMass ), 0, SPROP_NOSCALE ), -END_SEND_TABLE() - - - -class CPhysicsPropMultiplayer : public CPhysicsProp, public IMultiplayerPhysics -{ - DECLARE_CLASS( CPhysicsPropMultiplayer, CPhysicsProp ); - - CNetworkVar( int, m_iPhysicsMode ); // One of the PHYSICS_MULTIPLAYER_ defines. - CNetworkVar( float, m_fMass ); - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - CPhysicsPropMultiplayer() - { - m_iPhysicsMode = PHYSICS_MULTIPLAYER_AUTODETECT; - m_usingCustomCollisionBounds = false; - } - -// IBreakableWithPropData: - void SetPhysicsMode(int iMode) - { - m_iPhysicsMode = iMode; - } - - int GetPhysicsMode() { return m_iPhysicsMode; } - -// IMultiplayerPhysics: - int GetMultiplayerPhysicsMode() { return m_iPhysicsMode; } - float GetMass() { return m_fMass; } - bool IsAsleep() { return !m_bAwake; } - - bool IsDebris( void ) { return ( ( m_spawnflags & SF_PHYSPROP_DEBRIS ) != 0 ); } - - virtual void VPhysicsUpdate( IPhysicsObject *pPhysics ) - { - BaseClass::VPhysicsUpdate( pPhysics ); - - if ( sv_turbophysics.GetBool() ) - { - // If the object is set to debris, don't let turbo physics change it. - if ( IsDebris() ) - return; - - if ( m_bAwake ) - { - SetCollisionGroup( COLLISION_GROUP_PUSHAWAY ); - } - else if ( m_iPhysicsMode == PHYSICS_MULTIPLAYER_NON_SOLID ) - { - SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - } - else - { - SetCollisionGroup( COLLISION_GROUP_NONE ); - } - } - } - - virtual void Spawn( void ) - { - BaseClass::Spawn(); - - // if no physicsmode was defined by .QC or propdata.txt, - // use auto detect based on size & mass - if ( m_iPhysicsMode == PHYSICS_MULTIPLAYER_AUTODETECT ) - { - if ( VPhysicsGetObject() ) - { - m_iPhysicsMode = GetAutoMultiplayerPhysicsMode( - CollisionProp()->OBBSize(), VPhysicsGetObject()->GetMass() ); - } - else - { - UTIL_Remove( this ); - return; - } - } - - // check if map maker overrides physics mode to force a server-side entity - if ( GetSpawnFlags() & SF_PHYSPROP_FORCE_SERVER_SIDE ) - { - SetPhysicsMode( PHYSICS_MULTIPLAYER_NON_SOLID ); - } - - if ( m_iPhysicsMode == PHYSICS_MULTIPLAYER_CLIENTSIDE ) - { - if ( engine->IsInEditMode() ) - { - // in map edit mode always spawn as server phys prop - SetPhysicsMode( PHYSICS_MULTIPLAYER_NON_SOLID ); - } - else - { - // don't spawn clientside props on server - UTIL_Remove( this ); - return; - } - - } - - if ( GetCollisionGroup() == COLLISION_GROUP_NONE ) - SetCollisionGroup( COLLISION_GROUP_PUSHAWAY ); - - // Items marked as debris should be set as such. - if ( IsDebris() ) - { - SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - } - - m_fMass = VPhysicsGetObject()->GetMass(); - - // VPhysicsGetObject() is NULL on the client, which prevents the client from finding a decent - // AABB surrounding the collision bounds. If we've got a VPhysicsGetObject()->GetCollide(), we'll - // grab it's unrotated bounds and use it to calculate our collision surrounding bounds. This - // can end up larger than the CollisionProp() would have calculated on its own, but it'll be - // identical on the client and the server. - m_usingCustomCollisionBounds = false; - if ( ( GetSolid() == SOLID_VPHYSICS ) && ( GetMoveType() == MOVETYPE_VPHYSICS ) ) - { - IPhysicsObject *pPhysics = VPhysicsGetObject(); - if ( pPhysics && pPhysics->GetCollide() ) - { - physcollision->CollideGetAABB( &m_collisionMins.GetForModify(), &m_collisionMaxs.GetForModify(), pPhysics->GetCollide(), vec3_origin, vec3_angle ); - CollisionProp()->SetSurroundingBoundsType( USE_GAME_CODE ); - m_usingCustomCollisionBounds = true; - } - } - } - - virtual void ComputeWorldSpaceSurroundingBox( Vector *mins, Vector *maxs ) - { - Assert( m_usingCustomCollisionBounds ); - Assert( mins != NULL && maxs != NULL ); - if ( !mins || !maxs ) - return; - - // Take our saved collision bounds, and transform into world space - TransformAABB( EntityToWorldTransform(), m_collisionMins, m_collisionMaxs, *mins, *maxs ); - } - -private: - bool m_usingCustomCollisionBounds; - CNetworkVector( m_collisionMins ); - CNetworkVector( m_collisionMaxs ); -}; - -LINK_ENTITY_TO_CLASS( prop_physics_multiplayer, CPhysicsPropMultiplayer ); - -BEGIN_DATADESC( CPhysicsPropMultiplayer ) - DEFINE_KEYFIELD( m_iPhysicsMode, FIELD_INTEGER, "physicsmode" ), - DEFINE_FIELD( m_fMass, FIELD_FLOAT ), - DEFINE_FIELD( m_usingCustomCollisionBounds, FIELD_BOOLEAN ), - DEFINE_FIELD( m_collisionMins, FIELD_VECTOR ), - DEFINE_FIELD( m_collisionMaxs, FIELD_VECTOR ), -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CPhysicsPropMultiplayer, DT_PhysicsPropMultiplayer ) - SendPropInt( SENDINFO( m_iPhysicsMode ), 2, SPROP_UNSIGNED ), - SendPropFloat( SENDINFO( m_fMass ), 0, SPROP_NOSCALE ), - SendPropVector( SENDINFO( m_collisionMins ), 0, SPROP_NOSCALE ), - SendPropVector( SENDINFO( m_collisionMaxs ), 0, SPROP_NOSCALE ), -END_SEND_TABLE() - -#define RESPAWNABLE_PROP_DEFAULT_TIME 60.0f - -class CPhysicsPropRespawnable : public CPhysicsProp -{ - DECLARE_CLASS( CPhysicsPropRespawnable, CPhysicsProp ); - DECLARE_DATADESC(); - -public: - - CPhysicsPropRespawnable(); - - virtual void Spawn( void ); - virtual void Event_Killed( const CTakeDamageInfo &info ); - - void Materialize( void ); - -private: - - Vector m_vOriginalSpawnOrigin; - QAngle m_vOriginalSpawnAngles; - - Vector m_vOriginalMins; - Vector m_vOriginalMaxs; - - float m_flRespawnTime; -}; - -LINK_ENTITY_TO_CLASS( prop_physics_respawnable, CPhysicsPropRespawnable ); - -BEGIN_DATADESC( CPhysicsPropRespawnable ) - DEFINE_THINKFUNC( Materialize ), - DEFINE_KEYFIELD( m_flRespawnTime, FIELD_FLOAT, "RespawnTime" ), - DEFINE_FIELD( m_vOriginalSpawnOrigin, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vOriginalSpawnAngles, FIELD_VECTOR ), - DEFINE_FIELD( m_vOriginalMins, FIELD_VECTOR ), - DEFINE_FIELD( m_vOriginalMaxs, FIELD_VECTOR ), -END_DATADESC() - -CPhysicsPropRespawnable::CPhysicsPropRespawnable( void ) -{ - m_flRespawnTime = 0.0f; -} - -void CPhysicsPropRespawnable::Spawn( void ) -{ - BaseClass::Spawn(); - - m_vOriginalSpawnOrigin = GetAbsOrigin(); - m_vOriginalSpawnAngles = GetAbsAngles(); - - m_vOriginalMins = CollisionProp()->OBBMins(); - m_vOriginalMaxs = CollisionProp()->OBBMaxs(); - - if ( m_flRespawnTime == 0.0f ) - { - m_flRespawnTime = RESPAWNABLE_PROP_DEFAULT_TIME; - } - - SetOwnerEntity( NULL ); -} - -void CPhysicsPropRespawnable::Event_Killed( const CTakeDamageInfo &info ) -{ - IPhysicsObject *pPhysics = VPhysicsGetObject(); - if ( pPhysics && !pPhysics->IsMoveable() ) - { - pPhysics->EnableMotion( true ); - VPhysicsTakeDamage( info ); - } - - Break( info.GetInflictor(), info ); - - PhysCleanupFrictionSounds( this ); - - VPhysicsDestroyObject(); - - CBaseEntity::PhysicsRemoveTouchedList( this ); - CBaseEntity::PhysicsRemoveGroundList( this ); - DestroyAllDataObjects(); - - AddEffects( EF_NODRAW ); - - if ( IsOnFire() || IsDissolving() ) - { - UTIL_Remove( GetEffectEntity() ); - } - - Teleport( &m_vOriginalSpawnOrigin, &m_vOriginalSpawnAngles, NULL ); - - SetContextThink( NULL, 0, "PROP_CLEARFLAGS" ); - - SetThink( &CPhysicsPropRespawnable::Materialize ); - SetNextThink( gpGlobals->curtime + m_flRespawnTime ); -} - -void CPhysicsPropRespawnable::Materialize( void ) -{ - trace_t tr; - UTIL_TraceHull( m_vOriginalSpawnOrigin, m_vOriginalSpawnOrigin, m_vOriginalMins, m_vOriginalMaxs, MASK_SOLID, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.startsolid || tr.allsolid ) - { - //Try again in a second. - SetNextThink( gpGlobals->curtime + 1.0f ); - return; - } - - RemoveEffects( EF_NODRAW ); - Spawn(); -} - - -//------------------------------------------------------------------------------ -// Purpose: Create a prop of the given type -//------------------------------------------------------------------------------ -void CC_Prop_Dynamic_Create( const CCommand &args ) -{ - if ( args.ArgC() != 2 ) - return; - - // Figure out where to place it - CBasePlayer* pPlayer = UTIL_GetCommandClient(); - Vector forward; - pPlayer->EyeVectors( &forward ); - - trace_t tr; - UTIL_TraceLine( pPlayer->EyePosition(), - pPlayer->EyePosition() + forward * MAX_TRACE_LENGTH, MASK_NPCSOLID, - pPlayer, COLLISION_GROUP_NONE, &tr ); - - // No hit? We're done. - if ( tr.fraction == 1.0 ) - return; - - MDLCACHE_CRITICAL_SECTION(); - - char pModelName[512]; - Q_snprintf( pModelName, sizeof(pModelName), "models/%s", args[1] ); - Q_DefaultExtension( pModelName, ".mdl", sizeof(pModelName) ); - MDLHandle_t h = mdlcache->FindMDL( pModelName ); - if ( h == MDLHANDLE_INVALID ) - return; - - bool bAllowPrecache = CBaseEntity::IsPrecacheAllowed(); - CBaseEntity::SetAllowPrecache( true ); - - vcollide_t *pVCollide = mdlcache->GetVCollide( h ); - - Vector xaxis( 1.0f, 0.0f, 0.0f ); - Vector yaxis; - CrossProduct( tr.plane.normal, xaxis, yaxis ); - if ( VectorNormalize( yaxis ) < 1e-3 ) - { - xaxis.Init( 0.0f, 0.0f, 1.0f ); - CrossProduct( tr.plane.normal, xaxis, yaxis ); - VectorNormalize( yaxis ); - } - CrossProduct( yaxis, tr.plane.normal, xaxis ); - VectorNormalize( xaxis ); - - VMatrix entToWorld; - entToWorld.SetBasisVectors( xaxis, yaxis, tr.plane.normal ); - - QAngle angles; - MatrixToAngles( entToWorld, angles ); - - // Try to create entity - CDynamicProp *pProp = dynamic_cast< CDynamicProp * >( CreateEntityByName( "dynamic_prop" ) ); - if ( pProp ) - { - char buf[512]; - // Pass in standard key values - Q_snprintf( buf, sizeof(buf), "%.10f %.10f %.10f", tr.endpos.x, tr.endpos.y, tr.endpos.z ); - pProp->KeyValue( "origin", buf ); - Q_snprintf( buf, sizeof(buf), "%.10f %.10f %.10f", angles.x, angles.y, angles.z ); - pProp->KeyValue( "angles", buf ); - pProp->KeyValue( "model", pModelName ); - pProp->KeyValue( "solid", pVCollide ? "6" : "2" ); - pProp->KeyValue( "fademindist", "-1" ); - pProp->KeyValue( "fademaxdist", "0" ); - pProp->KeyValue( "fadescale", "1" ); - pProp->KeyValue( "MinAnimTime", "5" ); - pProp->KeyValue( "MaxAnimTime", "10" ); - pProp->Precache(); - DispatchSpawn( pProp ); - pProp->Activate(); - } - CBaseEntity::SetAllowPrecache( bAllowPrecache ); -} - -static ConCommand prop_dynamic_create("prop_dynamic_create", CC_Prop_Dynamic_Create, "Creates a dynamic prop with a specific .mdl aimed away from where the player is looking.\n\tArguments: {.mdl name}", FCVAR_CHEAT); - - - -//------------------------------------------------------------------------------ -// Purpose: Create a prop of the given type -//------------------------------------------------------------------------------ -void CC_Prop_Physics_Create( const CCommand &args ) -{ - if ( args.ArgC() != 2 ) - return; - - char pModelName[512]; - Q_snprintf( pModelName, sizeof(pModelName), "models/%s", args[1] ); - Q_DefaultExtension( pModelName, ".mdl", sizeof(pModelName) ); - - // Figure out where to place it - CBasePlayer* pPlayer = UTIL_GetCommandClient(); - Vector forward; - pPlayer->EyeVectors( &forward ); - - CreatePhysicsProp( pModelName, pPlayer->EyePosition(), pPlayer->EyePosition() + forward * MAX_TRACE_LENGTH, pPlayer, true ); -} - -static ConCommand prop_physics_create("prop_physics_create", CC_Prop_Physics_Create, "Creates a physics prop with a specific .mdl aimed away from where the player is looking.\n\tArguments: {.mdl name}", FCVAR_CHEAT); - - -CPhysicsProp* CreatePhysicsProp( const char *pModelName, const Vector &vTraceStart, const Vector &vTraceEnd, const IHandleEntity *pTraceIgnore, bool bRequireVCollide, const char *pClassName ) -{ - MDLCACHE_CRITICAL_SECTION(); - - MDLHandle_t h = mdlcache->FindMDL( pModelName ); - if ( h == MDLHANDLE_INVALID ) - return NULL; - - // Must have vphysics to place as a physics prop - studiohdr_t *pStudioHdr = mdlcache->GetStudioHdr( h ); - if ( !pStudioHdr ) - return NULL; - - // Must have vphysics to place as a physics prop - if ( bRequireVCollide && !mdlcache->GetVCollide( h ) ) - return NULL; - - QAngle angles( 0.0f, 0.0f, 0.0f ); - Vector vecSweepMins = pStudioHdr->hull_min; - Vector vecSweepMaxs = pStudioHdr->hull_max; - - trace_t tr; - UTIL_TraceHull( vTraceStart, vTraceEnd, - vecSweepMins, vecSweepMaxs, MASK_NPCSOLID, pTraceIgnore, COLLISION_GROUP_NONE, &tr ); - - // No hit? We're done. - if ( (tr.fraction == 1.0 && (vTraceEnd-vTraceStart).Length() > 0.01) || tr.allsolid ) - return NULL; - - VectorMA( tr.endpos, 1.0f, tr.plane.normal, tr.endpos ); - - bool bAllowPrecache = CBaseEntity::IsPrecacheAllowed(); - CBaseEntity::SetAllowPrecache( true ); - - // Try to create entity - CPhysicsProp *pProp = dynamic_cast< CPhysicsProp * >( CreateEntityByName( pClassName ) ); - if ( pProp ) - { - char buf[512]; - // Pass in standard key values - Q_snprintf( buf, sizeof(buf), "%.10f %.10f %.10f", tr.endpos.x, tr.endpos.y, tr.endpos.z ); - pProp->KeyValue( "origin", buf ); - Q_snprintf( buf, sizeof(buf), "%.10f %.10f %.10f", angles.x, angles.y, angles.z ); - pProp->KeyValue( "angles", buf ); - pProp->KeyValue( "model", pModelName ); - pProp->KeyValue( "fademindist", "-1" ); - pProp->KeyValue( "fademaxdist", "0" ); - pProp->KeyValue( "fadescale", "1" ); - pProp->KeyValue( "inertiaScale", "1.0" ); - pProp->KeyValue( "physdamagescale", "0.1" ); - pProp->Precache(); - DispatchSpawn( pProp ); - pProp->Activate(); - } - CBaseEntity::SetAllowPrecache( bAllowPrecache ); - - return pProp; -} - - -//------------------------------------------------------------------------------ -// Rotates an entity -//------------------------------------------------------------------------------ -void CC_Ent_Rotate( const CCommand &args ) -{ - CBasePlayer* pPlayer = UTIL_GetCommandClient(); - CBaseEntity* pEntity = FindPickerEntity( pPlayer ); - if ( !pEntity ) - return; - - QAngle angles = pEntity->GetLocalAngles(); - float flAngle = (args.ArgC() == 2) ? atof( args[1] ) : 7.5f; - - VMatrix entToWorld, rot, newEntToWorld; - MatrixBuildRotateZ( rot, flAngle ); - MatrixFromAngles( angles, entToWorld ); - MatrixMultiply( entToWorld, rot, newEntToWorld ); - MatrixToAngles( newEntToWorld, angles ); - pEntity->SetLocalAngles( angles ); -} - -static ConCommand ent_rotate("ent_rotate", CC_Ent_Rotate, "Rotates an entity by a specified # of degrees", FCVAR_CHEAT); - -// This is a dummy. The entity is entirely clientside. -LINK_ENTITY_TO_CLASS( func_proprrespawnzone, CBaseEntity ); diff --git a/game/server/props.h b/game/server/props.h deleted file mode 100644 index b712f5c55..000000000 --- a/game/server/props.h +++ /dev/null @@ -1,432 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#ifndef PROPS_H -#define PROPS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "props_shared.h" -#include "baseanimating.h" -#include "physics_bone_follower.h" -#include "player_pickup.h" -#include "positionwatcher.h" - -//============================================================================================================= -// PROP TYPES -//============================================================================================================= -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CBaseProp : public CBaseAnimating -{ - DECLARE_CLASS( CBaseProp, CBaseAnimating ); -public: - - void Spawn( void ); - void Precache( void ); - void Activate( void ); - bool KeyValue( const char *szKeyName, const char *szValue ); - void CalculateBlockLOS( void ); - int ParsePropData( void ); - - void DrawDebugGeometryOverlays( void ); - - // Don't treat as a live target - virtual bool IsAlive( void ) { return false; } - virtual bool OverridePropdata() { return true; } -}; - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CBreakableProp : public CBaseProp, public IBreakableWithPropData, public CDefaultPlayerPickupVPhysics -{ -public: - CBreakableProp(); - - DECLARE_CLASS( CBreakableProp, CBaseProp ); - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - virtual void Spawn(); - virtual void Precache(); - virtual float GetAutoAimRadius() { return 24.0f; } - - void BreakablePropTouch( CBaseEntity *pOther ); - - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - void Event_Killed( const CTakeDamageInfo &info ); - void Break( CBaseEntity *pBreaker, const CTakeDamageInfo &info ); - void BreakThink( void ); - void AnimateThink( void ); - - virtual void PlayPuntSound(); - - void InputBreak( inputdata_t &inputdata ); - void InputAddHealth( inputdata_t &inputdata ); - void InputRemoveHealth( inputdata_t &inputdata ); - void InputSetHealth( inputdata_t &inputdata ); - - int GetNumBreakableChunks( void ) { return m_iNumBreakableChunks; } - - virtual bool OverridePropdata() { return false; } - virtual IPhysicsObject *GetRootPhysicsObjectForBreak(); - - bool PropDataOverrodeBlockLOS( void ) { return m_bBlockLOSSetByPropData; } - bool PropDataOverrodeAIWalkable( void ) { return m_bIsWalkableSetByPropData; } - - virtual bool HasPreferredCarryAnglesForPlayer( CBasePlayer *pPlayer ) - { - if ( HasInteraction( PROPINTER_PHYSGUN_LAUNCH_SPIN_Z ) ) - return true; - - return false; - } - - virtual QAngle PreferredCarryAngles( void ) { return m_preferredCarryAngles; } - - virtual void Ignite( float flFlameLifetime, bool bNPCOnly, float flSize = 0.0f, bool bCalledByLevelDesigner = false ); - - // Specific interactions - void HandleFirstCollisionInteractions( int index, gamevcollisionevent_t *pEvent ); - void HandleInteractionStick( int index, gamevcollisionevent_t *pEvent ); - void StickAtPosition( const Vector &stickPosition, const Vector &savePosition, const QAngle &saveAngles ); - - // Disable auto fading under dx7 or when level fades are specified - void DisableAutoFade(); - -public: - COutputEvent m_OnBreak; - COutputFloat m_OnHealthChanged; - COutputEvent m_OnTakeDamage; - - float m_impactEnergyScale; - - int m_iMinHealthDmg; - - QAngle m_preferredCarryAngles; - -public: -// IBreakableWithPropData - void SetDmgModBullet( float flDmgMod ) { m_flDmgModBullet = flDmgMod; } - void SetDmgModClub( float flDmgMod ) { m_flDmgModClub = flDmgMod; } - void SetDmgModExplosive( float flDmgMod ) { m_flDmgModExplosive = flDmgMod; } - float GetDmgModBullet( void ) { return m_flDmgModBullet; } - float GetDmgModClub( void ) { return m_flDmgModClub; } - float GetDmgModExplosive( void ) { return m_flDmgModExplosive; } - void SetExplosiveRadius( float flRadius ) { m_explodeRadius = flRadius; } - void SetExplosiveDamage( float flDamage ) { m_explodeDamage = flDamage; } - float GetExplosiveRadius( void ) { return m_explodeRadius; } - float GetExplosiveDamage( void ) { return m_explodeDamage; } - void SetPhysicsDamageTable( string_t iszTableName ) { m_iszPhysicsDamageTableName = iszTableName; } - string_t GetPhysicsDamageTable( void ) { return m_iszPhysicsDamageTableName; } - void SetBreakableModel( string_t iszModel ) { m_iszBreakableModel = iszModel; } - string_t GetBreakableModel( void ) { return m_iszBreakableModel; } - void SetBreakableSkin( int iSkin ) { m_iBreakableSkin = iSkin; } - int GetBreakableSkin( void ) { return m_iBreakableSkin; } - void SetBreakableCount( int iCount ) { m_iBreakableCount = iCount; } - int GetBreakableCount( void ) { return m_iBreakableCount; } - void SetMaxBreakableSize( int iSize ) { m_iMaxBreakableSize = iSize; } - int GetMaxBreakableSize( void ) { return m_iMaxBreakableSize; } - void SetPropDataBlocksLOS( bool bBlocksLOS ) { m_bBlockLOSSetByPropData = true; SetBlocksLOS( bBlocksLOS ); } - void SetPropDataIsAIWalkable( bool b ) { m_bIsWalkableSetByPropData = true; SetAIWalkable( b ); } - void SetBasePropData( string_t iszBase ) { m_iszBasePropData = iszBase; } - string_t GetBasePropData( void ) { return m_iszBasePropData; } - void SetInteraction( propdata_interactions_t Interaction ) { m_iInteractions |= (1 << Interaction); } - void RemoveInteraction( propdata_interactions_t Interaction ) { m_iInteractions &= ~(1 << Interaction); } - bool HasInteraction( propdata_interactions_t Interaction ) { return ( m_iInteractions & (1 << Interaction) ) != 0; } - void SetMultiplayerBreakMode( mp_break_t mode ) { m_mpBreakMode = mode; } - mp_break_t GetMultiplayerBreakMode( void ) const { return m_mpBreakMode; } - -// derived by multiplayer phys props: - virtual void SetPhysicsMode(int iMode) {} - virtual int GetPhysicsMode() { return PHYSICS_MULTIPLAYER_SOLID; } - - // Copy fade from another breakable prop - void CopyFadeFrom( CBreakableProp *pSource ); - -protected: - - bool UpdateHealth( int iNewHealth, CBaseEntity *pActivator ); - virtual void OnBreak( const Vector &vecVelocity, const AngularImpulse &angVel, CBaseEntity *pBreaker ) {} - -protected: - - unsigned int m_createTick; - float m_flPressureDelay; - EHANDLE m_hBreaker; - - PerformanceMode_t m_PerformanceMode; - - // Prop data storage - float m_flDmgModBullet; - float m_flDmgModClub; - float m_flDmgModExplosive; - string_t m_iszPhysicsDamageTableName; - string_t m_iszBreakableModel; - int m_iBreakableSkin; - int m_iBreakableCount; - int m_iMaxBreakableSize; - string_t m_iszBasePropData; - int m_iInteractions; - float m_explodeDamage; - float m_explodeRadius; - - // Count of how many pieces we'll break into, custom or generic - int m_iNumBreakableChunks; - - void SetEnableMotionPosition( const Vector &position, const QAngle &angles ); - bool GetEnableMotionPosition( Vector *pPosition, QAngle *pAngles ); - void ClearEnableMotionPosition(); -private: - CBaseEntity *FindEnableMotionFixup(); - -public: - virtual bool OnAttemptPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ); - virtual void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ); - virtual void OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t reason ); - virtual AngularImpulse PhysGunLaunchAngularImpulse(); - virtual CBasePlayer *HasPhysicsAttacker( float dt ); - -#ifdef HL2_EPISODIC - void CreateFlare( float flLifetime ); -#endif //HL2_EPISODIC - -protected: - void SetPhysicsAttacker( CBasePlayer *pEntity, float flTime ); - void CheckRemoveRagdolls(); - -private: - void InputEnablePhyscannonPickup( inputdata_t &inputdata ); - void InputDisablePhyscannonPickup( inputdata_t &inputdata ); - - void InputEnablePuntSound( inputdata_t &inputdata ) { m_bUsePuntSound = true; } - void InputDisablePuntSound( inputdata_t &inputdata ) { m_bUsePuntSound = false; } - - // Prevents fade scale from happening - void ForceFadeScaleToAlwaysVisible(); - void RampToDefaultFadeScale(); - -private: - enum PhysgunState_t - { - PHYSGUN_MUST_BE_DETACHED = 0, - PHYSGUN_IS_DETACHING, - PHYSGUN_CAN_BE_GRABBED, - PHYSGUN_ANIMATE_ON_PULL, - PHYSGUN_ANIMATE_IS_ANIMATING, - PHYSGUN_ANIMATE_FINISHED, - PHYSGUN_ANIMATE_IS_PRE_ANIMATING, - PHYSGUN_ANIMATE_IS_POST_ANIMATING, - }; - - CHandle m_hPhysicsAttacker; - float m_flLastPhysicsInfluenceTime; - bool m_bBlockLOSSetByPropData; - bool m_bIsWalkableSetByPropData; - bool m_bOriginalBlockLOS; // BlockLOS state before physgun pickup - char m_nPhysgunState; // Ripped-off state - COutputEvent m_OnPhysCannonDetach; // We've ripped it off! - COutputEvent m_OnPhysCannonAnimatePreStarted; // Started playing the pre-pull animation - COutputEvent m_OnPhysCannonAnimatePullStarted; // Player started the pull anim - COutputEvent m_OnPhysCannonAnimatePostStarted; // Started playing the post-pull animation - COutputEvent m_OnPhysCannonPullAnimFinished; // We've had our pull anim finished, or the post-pull has finished if there is one - float m_flDefaultFadeScale; // Things may temporarily change the fade scale, but this is its steady-state condition - - mp_break_t m_mpBreakMode; - - EHANDLE m_hLastAttacker; // Last attacker that harmed me. - EHANDLE m_hFlareEnt; - string_t m_iszPuntSound; - bool m_bUsePuntSound; -}; - -// Spawnflags -#define SF_DYNAMICPROP_USEHITBOX_FOR_RENDERBOX 64 -#define SF_DYNAMICPROP_NO_VPHYSICS 128 -#define SF_DYNAMICPROP_DISABLE_COLLISION 256 - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CDynamicProp : public CBreakableProp, public IPositionWatcher -{ - DECLARE_CLASS( CDynamicProp, CBreakableProp ); - -public: - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - CDynamicProp(); - - void Spawn( void ); - bool CreateVPhysics( void ); - void CreateBoneFollowers(); - void UpdateOnRemove( void ); - void AnimThink( void ); - void PropSetSequence( int nSequence ); - void OnRestore( void ); - bool OverridePropdata( void ); - void HandleAnimEvent( animevent_t *pEvent ); - - // baseentity - watch dynamic hierarchy updates - virtual void SetParent( CBaseEntity* pNewParent, int iAttachment = -1 ); - bool TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace ); - - // breakable prop - virtual IPhysicsObject *GetRootPhysicsObjectForBreak(); - - // IPositionWatcher - virtual void NotifyPositionChanged( CBaseEntity *pEntity ); - - // Input handlers - void InputSetAnimation( inputdata_t &inputdata ); - void InputSetDefaultAnimation( inputdata_t &inputdata ); - void InputTurnOn( inputdata_t &inputdata ); - void InputTurnOff( inputdata_t &inputdata ); - void InputDisableCollision( inputdata_t &inputdata ); - void InputEnableCollision( inputdata_t &inputdata ); - void InputSetPlaybackRate( inputdata_t &inputdata ); - - COutputEvent m_pOutputAnimBegun; - COutputEvent m_pOutputAnimOver; - - string_t m_iszDefaultAnim; - - int m_iGoalSequence; - int m_iTransitionDirection; - - // Random animations - bool m_bRandomAnimator; - float m_flNextRandAnim; - float m_flMinRandAnimTime; - float m_flMaxRandAnimTime; - short m_nPendingSequence; - - bool m_bStartDisabled; - - CNetworkVar( bool, m_bUseHitboxesForRenderBox ); - -protected: - void FinishSetSequence( int nSequence ); - void PropSetAnim( const char *szAnim ); - void BoneFollowerHierarchyChanged(); - - // Contained Bone Follower manager - CBoneFollowerManager m_BoneFollowerManager; -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CPhysicsProp : public CBreakableProp -{ - DECLARE_CLASS( CPhysicsProp, CBreakableProp ); - DECLARE_SERVERCLASS(); - -public: - ~CPhysicsProp(); - CPhysicsProp( void ) - { - } - - void Spawn( void ); - void Precache(); - bool CreateVPhysics( void ); - bool OverridePropdata( void ); - - virtual void VPhysicsUpdate( IPhysicsObject *pPhysics ); - virtual void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); - - void InputWake( inputdata_t &inputdata ); - void InputSleep( inputdata_t &inputdata ); - void InputEnableMotion( inputdata_t &inputdata ); - void InputDisableMotion( inputdata_t &inputdata ); - void InputDisableFloating( inputdata_t &inputdata ); - - void EnableMotion( void ); - bool CanBePickedUpByPhyscannon( void ); - void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ); - void OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t reason ); - - bool GetPropDataAngles( const char *pKeyName, QAngle &vecAngles ); - float GetCarryDistanceOffset( void ); - - int ObjectCaps(); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - void GetMassCenter( Vector *pMassCenter ); - float GetMass() const; - - void ClearFlagsThink( void ); - - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - int DrawDebugTextOverlays(void); - bool IsGib(); - DECLARE_DATADESC(); - - // Specific interactions - void HandleAnyCollisionInteractions( int index, gamevcollisionevent_t *pEvent ); - -private: - // Compute impulse to apply to the enabled entity. - void ComputeEnablingImpulse( int index, gamevcollisionevent_t *pEvent ); - - COutputEvent m_MotionEnabled; - COutputEvent m_OnAwakened; - COutputEvent m_OnPhysGunPickup; - COutputEvent m_OnPhysGunPunt; - COutputEvent m_OnPhysGunOnlyPickup; - COutputEvent m_OnPhysGunDrop; - COutputEvent m_OnPlayerUse; - COutputEvent m_OnPlayerPickup; - COutputEvent m_OnOutOfWorld; - - float m_massScale; - float m_inertiaScale; - int m_damageType; - string_t m_iszOverrideScript; - int m_damageToEnableMotion; - float m_flForceToEnableMotion; - - bool m_bThrownByPlayer; - bool m_bFirstCollisionAfterLaunch; - -protected: - CNetworkVar( bool, m_bAwake ); -}; - - -// An interface so that objects parented to props can receive collision interaction events. -enum parentCollisionInteraction_t -{ - COLLISIONINTER_PARENT_FIRST_IMPACT = 1, -}; - - -abstract_class IParentPropInteraction -{ -public: - virtual void OnParentCollisionInteraction( parentCollisionInteraction_t eType, int index, gamevcollisionevent_t *pEvent ) = 0; - virtual void OnParentPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason ) = 0; -}; - - -// Used by prop_physics_create and the server benchmark. -// pModelName should not include the "models/" prefix. -CPhysicsProp* CreatePhysicsProp( const char *pModelName, const Vector &vTraceStart, const Vector &vTraceEnd, const IHandleEntity *pTraceIgnore, bool bRequireVCollide, const char *pClassName="physics_prop" ); - -float GetBreakableDamage( const CTakeDamageInfo &inputInfo, IBreakableWithPropData *pProp = NULL ); -int PropBreakablePrecacheAll( string_t modelName ); - -extern ConVar func_breakdmg_bullet; -extern ConVar func_breakdmg_club; -extern ConVar func_breakdmg_explosive; - -#endif // PROPS_H diff --git a/game/server/pushentity.h b/game/server/pushentity.h deleted file mode 100644 index 7302ab92e..000000000 --- a/game/server/pushentity.h +++ /dev/null @@ -1,160 +0,0 @@ -//====== Copyright 1996-2008, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= -#ifndef PUSHENTITY_H -#define PUSHENTITY_H -#ifdef _WIN32 -#pragma once -#endif - -#include "movetype_push.h" - -//----------------------------------------------------------------------------- -// Purpose: Keeps track of original positions of any entities that are being possibly pushed -// and handles restoring positions for those objects if the push is aborted -//----------------------------------------------------------------------------- -class CPhysicsPushedEntities -{ -public: - - DECLARE_CLASS_NOBASE( CPhysicsPushedEntities ); - - CPhysicsPushedEntities( void ); - - // Purpose: Tries to rotate an entity hierarchy, returns the blocker if any - CBaseEntity *PerformRotatePush( CBaseEntity *pRoot, float movetime ); - - // Purpose: Tries to linearly push an entity hierarchy, returns the blocker if any - CBaseEntity *PerformLinearPush( CBaseEntity *pRoot, float movetime ); - - int CountMovedEntities() { return m_rgMoved.Count(); } - void StoreMovedEntities( physicspushlist_t &list ); - void BeginPush( CBaseEntity *pRootEntity ); - -protected: - - // describes the per-frame incremental motion of a rotating MOVETYPE_PUSH - struct RotatingPushMove_t - { - Vector origin; - matrix3x4_t startLocalToWorld; - matrix3x4_t endLocalToWorld; - QAngle amove; // delta orientation - }; - - // Pushers + their original positions also (for touching triggers) - struct PhysicsPusherInfo_t - { - CBaseEntity *m_pEntity; - Vector m_vecStartAbsOrigin; - }; - - // Pushed entities + various state related to them being pushed - struct PhysicsPushedInfo_t - { - CBaseEntity *m_pEntity; - Vector m_vecStartAbsOrigin; - trace_t m_Trace; - bool m_bBlocked; - bool m_bPusherIsGround; - }; - - // Adds the specified entity to the list - void AddEntity( CBaseEntity *ent ); - - // If a move fails, restores all entities to their original positions - void RestoreEntities( ); - - // Compute the direction to move the rotation blocker - void ComputeRotationalPushDirection( CBaseEntity *pBlocker, const RotatingPushMove_t &rotPushMove, Vector *pMove, CBaseEntity *pRoot ); - - // Speculatively checks to see if all entities in this list can be pushed - bool SpeculativelyCheckPush( PhysicsPushedInfo_t &info, const Vector &vecAbsPush, bool bRotationalPush ); - - // Speculatively checks to see if all entities in this list can be pushed - virtual bool SpeculativelyCheckRotPush( const RotatingPushMove_t &rotPushMove, CBaseEntity *pRoot ); - - // Speculatively checks to see if all entities in this list can be pushed - virtual bool SpeculativelyCheckLinearPush( const Vector &vecAbsPush ); - - // Registers a blockage - CBaseEntity *RegisterBlockage(); - - // Some fixup for objects pushed by rotating objects - virtual void FinishRotPushedEntity( CBaseEntity *pPushedEntity, const RotatingPushMove_t &rotPushMove ); - - // Commits the speculative movement - void FinishPush( bool bIsRotPush = false, const RotatingPushMove_t *pRotPushMove = NULL ); - - // Generates a list of all entities potentially blocking all pushers - void GenerateBlockingEntityList(); - void GenerateBlockingEntityListAddBox( const Vector &vecMoved ); - - // Purpose: Gets a list of all entities hierarchically attached to the root - void SetupAllInHierarchy( CBaseEntity *pParent ); - - // Unlink + relink the pusher list so we can actually do the push - void UnlinkPusherList( int *pPusherHandles ); - void RelinkPusherList( int *pPusherHandles ); - - // Causes all entities in the list to touch triggers from their prev position - void FinishPushers(); - - // Purpose: Rotates the root entity, fills in the pushmove structure - void RotateRootEntity( CBaseEntity *pRoot, float movetime, RotatingPushMove_t &rotation ); - - // Purpose: Linearly moves the root entity - void LinearlyMoveRootEntity( CBaseEntity *pRoot, float movetime, Vector *pAbsPushVector ); - - bool IsPushedPositionValid( CBaseEntity *pBlocker ); - -protected: - - CUtlVector m_rgPusher; - CUtlVector m_rgMoved; - int m_nBlocker; - bool m_bIsUnblockableByPlayer; - Vector m_rootPusherStartLocalOrigin; - QAngle m_rootPusherStartLocalAngles; - float m_rootPusherStartLocaltime; - float m_flMoveTime; - - friend class CPushBlockerEnum; -}; - -class CTraceFilterPushMove : public CTraceFilterSimple -{ - DECLARE_CLASS( CTraceFilterPushMove, CTraceFilterSimple ); - -public: - CTraceFilterPushMove( CBaseEntity *pEntity, int nCollisionGroup ) - : CTraceFilterSimple( pEntity, nCollisionGroup ) - { - m_pRootParent = pEntity->GetRootMoveParent(); - } - - bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) - { - Assert( dynamic_cast(pHandleEntity) ); - CBaseEntity *pTestEntity = static_cast(pHandleEntity); - - if ( UTIL_EntityHasMatchingRootParent( m_pRootParent, pTestEntity ) ) - return false; - - if ( pTestEntity->GetMoveType() == MOVETYPE_VPHYSICS && - pTestEntity->VPhysicsGetObject() && pTestEntity->VPhysicsGetObject()->IsMoveable() ) - return false; - - return BaseClass::ShouldHitEntity( pHandleEntity, contentsMask ); - } - -private: - - CBaseEntity *m_pRootParent; -}; - -extern CPhysicsPushedEntities *g_pPushedEntities; - -#endif // PUSHENTITY_H diff --git a/game/server/ragdoll_manager.cpp b/game/server/ragdoll_manager.cpp deleted file mode 100644 index b46a48305..000000000 --- a/game/server/ragdoll_manager.cpp +++ /dev/null @@ -1,174 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "baseentity.h" -#include "sendproxy.h" -#include "ragdoll_shared.h" -#include "ai_basenpc.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CRagdollManager : public CBaseEntity -{ -public: - DECLARE_CLASS( CRagdollManager, CBaseEntity ); - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - CRagdollManager(); - - virtual void Activate(); - virtual int UpdateTransmitState(); - - void InputSetMaxRagdollCount(inputdata_t &data); - void InputSetMaxRagdollCountDX8(inputdata_t &data); - - int DrawDebugTextOverlays(void); - -public: - - void UpdateCurrentMaxRagDollCount(); - - CNetworkVar( int, m_iCurrentMaxRagdollCount ); - - int m_iDXLevel; - int m_iMaxRagdollCount; - int m_iMaxRagdollCountDX8; - - bool m_bSaveImportant; -}; - - -IMPLEMENT_SERVERCLASS_ST_NOBASE( CRagdollManager, DT_RagdollManager ) - SendPropInt( SENDINFO( m_iCurrentMaxRagdollCount ), 6 ), -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( game_ragdoll_manager, CRagdollManager ); - -BEGIN_DATADESC( CRagdollManager ) - - //DEFINE_FIELD( m_iDXLevel, FIELD_INTEGER ), - - DEFINE_FIELD( m_iCurrentMaxRagdollCount, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_iMaxRagdollCount, FIELD_INTEGER, "MaxRagdollCount" ), - DEFINE_KEYFIELD( m_iMaxRagdollCountDX8, FIELD_INTEGER, "MaxRagdollCountDX8" ), - - DEFINE_KEYFIELD( m_bSaveImportant, FIELD_BOOLEAN, "SaveImportant" ), - - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetMaxRagdollCount", InputSetMaxRagdollCount ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetMaxRagdollCountDX8", InputSetMaxRagdollCountDX8 ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CRagdollManager::CRagdollManager( void ) -{ - m_iMaxRagdollCount = -1; - m_iMaxRagdollCountDX8 = -1; - m_iCurrentMaxRagdollCount = -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pInfo - -// Output : int -//----------------------------------------------------------------------------- -int CRagdollManager::UpdateTransmitState() -{ - return SetTransmitState( FL_EDICT_ALWAYS ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CRagdollManager::Activate() -{ - BaseClass::Activate(); - - // Cache off the DX level for use later. - ConVarRef mat_dxlevel( "mat_dxlevel" ); - m_iDXLevel = mat_dxlevel.GetInt(); - - UpdateCurrentMaxRagDollCount(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CRagdollManager::UpdateCurrentMaxRagDollCount() -{ - if ( ( m_iDXLevel < 90 ) && ( m_iMaxRagdollCountDX8 >= 0 ) ) - { - m_iCurrentMaxRagdollCount = m_iMaxRagdollCountDX8; - } - else - { - m_iCurrentMaxRagdollCount = m_iMaxRagdollCount; - } - - s_RagdollLRU.SetMaxRagdollCount( m_iCurrentMaxRagdollCount ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CRagdollManager::InputSetMaxRagdollCount(inputdata_t &inputdata) -{ - m_iMaxRagdollCount = inputdata.value.Int(); - UpdateCurrentMaxRagDollCount(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CRagdollManager::InputSetMaxRagdollCountDX8(inputdata_t &inputdata) -{ - m_iMaxRagdollCountDX8 = inputdata.value.Int(); - UpdateCurrentMaxRagDollCount(); -} - -bool RagdollManager_SaveImportant( CAI_BaseNPC *pNPC ) -{ -#ifdef HL2_DLL - CRagdollManager *pEnt = (CRagdollManager *)gEntList.FindEntityByClassname( NULL, "game_ragdoll_manager" ); - - if ( pEnt == NULL ) - return false; - - if ( pEnt->m_bSaveImportant ) - { - if ( pNPC->Classify() == CLASS_PLAYER_ALLY || pNPC->Classify() == CLASS_PLAYER_ALLY_VITAL ) - { - return true; - } - } -#endif - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CRagdollManager::DrawDebugTextOverlays( void ) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - - // print max ragdoll count - Q_snprintf(tempstr,sizeof(tempstr),"max ragdoll count: %f", m_iCurrentMaxRagdollCount); - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} - diff --git a/game/server/recipientfilter.cpp b/game/server/recipientfilter.cpp deleted file mode 100644 index 09783ff6b..000000000 --- a/game/server/recipientfilter.cpp +++ /dev/null @@ -1,412 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "recipientfilter.h" -#include "team.h" -#include "ipredictionsystem.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -static IPredictionSystem g_RecipientFilterPredictionSystem; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CRecipientFilter::CRecipientFilter() -{ - Reset(); -} - -CRecipientFilter::~CRecipientFilter() -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : src - -//----------------------------------------------------------------------------- -void CRecipientFilter::CopyFrom( const CRecipientFilter& src ) -{ - m_bReliable = src.IsReliable(); - m_bInitMessage = src.IsInitMessage(); - - m_bUsingPredictionRules = src.IsUsingPredictionRules(); - m_bIgnorePredictionCull = src.IgnorePredictionCull(); - - int c = src.GetRecipientCount(); - for ( int i = 0; i < c; ++i ) - { - m_Recipients.AddToTail( src.GetRecipientIndex( i ) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CRecipientFilter::Reset( void ) -{ - m_bReliable = false; - m_bInitMessage = false; - m_Recipients.RemoveAll(); - m_bUsingPredictionRules = false; - m_bIgnorePredictionCull = false; -} - -void CRecipientFilter::MakeReliable( void ) -{ - m_bReliable = true; -} - -bool CRecipientFilter::IsReliable( void ) const -{ - return m_bReliable; -} - -int CRecipientFilter::GetRecipientCount( void ) const -{ - return m_Recipients.Size(); -} - -int CRecipientFilter::GetRecipientIndex( int slot ) const -{ - if ( slot < 0 || slot >= GetRecipientCount() ) - return -1; - - return m_Recipients[ slot ]; -} - -void CRecipientFilter::AddAllPlayers( void ) -{ - m_Recipients.RemoveAll(); - - int i; - for ( i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - if ( !pPlayer ) - { - continue; - } - - AddRecipient( pPlayer ); - } -} - -void CRecipientFilter::AddRecipient( CBasePlayer *player ) -{ - Assert( player ); - - int index = player->entindex(); - - // If we're predicting and this is not the first time we've predicted this sound - // then don't send it to the local player again. - if ( m_bUsingPredictionRules ) - { - // Only add local player if this is the first time doing prediction - if ( g_RecipientFilterPredictionSystem.GetSuppressHost() == player ) - { - return; - } - } - - // Already in list - if ( m_Recipients.Find( index ) != m_Recipients.InvalidIndex() ) - return; - - m_Recipients.AddToTail( index ); -} - -void CRecipientFilter::RemoveAllRecipients( void ) -{ - m_Recipients.RemoveAll(); -} - -void CRecipientFilter::RemoveRecipient( CBasePlayer *player ) -{ - Assert( player ); - if ( player ) - { - int index = player->entindex(); - - // Remove it if it's in the list - m_Recipients.FindAndRemove( index ); - } -} - -void CRecipientFilter::RemoveRecipientByPlayerIndex( int playerindex ) -{ - Assert( playerindex >= 1 && playerindex <= ABSOLUTE_PLAYER_LIMIT ); - - m_Recipients.FindAndRemove( playerindex ); -} - -void CRecipientFilter::AddRecipientsByTeam( CTeam *team ) -{ - Assert( team ); - - int i; - int c = team->GetNumPlayers(); - for ( i = 0 ; i < c ; i++ ) - { - CBasePlayer *player = team->GetPlayer( i ); - if ( !player ) - continue; - - AddRecipient( player ); - } -} - -void CRecipientFilter::RemoveRecipientsByTeam( CTeam *team ) -{ - Assert( team ); - - int i; - int c = team->GetNumPlayers(); - for ( i = 0 ; i < c ; i++ ) - { - CBasePlayer *player = team->GetPlayer( i ); - if ( !player ) - continue; - - RemoveRecipient( player ); - } -} - -void CRecipientFilter::RemoveRecipientsNotOnTeam( CTeam *team ) -{ - Assert( team ); - - int i; - for ( i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *player = UTIL_PlayerByIndex( i ); - if ( !player ) - continue; - - if ( player->GetTeam() != team ) - { - RemoveRecipient( player ); - } - } -} - -void CRecipientFilter::AddPlayersFromBitMask( CBitVec< ABSOLUTE_PLAYER_LIMIT >& playerbits ) -{ - int index = playerbits.FindNextSetBit( 0 ); - - while ( index > -1 ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( index + 1 ); - if ( pPlayer ) - { - AddRecipient( pPlayer ); - } - - index = playerbits.FindNextSetBit( index + 1 ); - } -} - -void CRecipientFilter::RemovePlayersFromBitMask( CBitVec< ABSOLUTE_PLAYER_LIMIT >& playerbits ) -{ - int index = playerbits.FindNextSetBit( 0 ); - - while ( index > -1 ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( index + 1 ); - if ( pPlayer ) - { - RemoveRecipient( pPlayer ); - } - - index = playerbits.FindNextSetBit( index + 1 ); - } -} - -void CRecipientFilter::AddRecipientsByPVS( const Vector& origin ) -{ - if ( gpGlobals->maxClients == 1 ) - { - AddAllPlayers(); - } - else - { - CBitVec< ABSOLUTE_PLAYER_LIMIT > playerbits; - engine->Message_DetermineMulticastRecipients( false, origin, playerbits ); - AddPlayersFromBitMask( playerbits ); - } -} - -void CRecipientFilter::RemoveRecipientsByPVS( const Vector& origin ) -{ - if ( gpGlobals->maxClients == 1 ) - { - m_Recipients.RemoveAll(); - } - else - { - CBitVec< ABSOLUTE_PLAYER_LIMIT > playerbits; - engine->Message_DetermineMulticastRecipients( false, origin, playerbits ); - RemovePlayersFromBitMask( playerbits ); - } -} - - - -void CRecipientFilter::AddRecipientsByPAS( const Vector& origin ) -{ - if ( gpGlobals->maxClients == 1 ) - { - AddAllPlayers(); - } - else - { - CBitVec< ABSOLUTE_PLAYER_LIMIT > playerbits; - engine->Message_DetermineMulticastRecipients( true, origin, playerbits ); - AddPlayersFromBitMask( playerbits ); - } -} - -bool CRecipientFilter::IsInitMessage( void ) const -{ - return m_bInitMessage; -} - -void CRecipientFilter::MakeInitMessage( void ) -{ - m_bInitMessage = true; -} - -void CRecipientFilter::UsePredictionRules( void ) -{ - if ( m_bUsingPredictionRules ) - return; - - m_bUsingPredictionRules = true; - - // Cull list now, if needed - if ( GetRecipientCount() == 0 ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( (CBaseEntity*)g_RecipientFilterPredictionSystem.GetSuppressHost() ); - - if ( pPlayer) - { - RemoveRecipient( pPlayer ); - } -} - -bool CRecipientFilter::IsUsingPredictionRules( void ) const -{ - return m_bUsingPredictionRules; -} - -bool CRecipientFilter:: IgnorePredictionCull( void ) const -{ - return m_bIgnorePredictionCull; -} - -void CRecipientFilter::SetIgnorePredictionCull( bool ignore ) -{ - m_bIgnorePredictionCull = ignore; -} - -//----------------------------------------------------------------------------- -// Purpose: Simple class to create a filter for all players on a given team -//----------------------------------------------------------------------------- -CTeamRecipientFilter::CTeamRecipientFilter( int team, bool isReliable ) -{ - if (isReliable) - MakeReliable(); - - RemoveAllRecipients(); - - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - - if ( !pPlayer ) - { - continue; - } - - if ( pPlayer->GetTeamNumber() != team ) - { - //If we're in the spectator team then we should be getting whatever messages the person I'm spectating gets. - if ( pPlayer->GetTeamNumber() == TEAM_SPECTATOR && (pPlayer->GetObserverMode() == OBS_MODE_IN_EYE || pPlayer->GetObserverMode() == OBS_MODE_CHASE) ) - { - if ( pPlayer->GetObserverTarget() ) - { - if ( pPlayer->GetObserverTarget()->GetTeamNumber() != team ) - continue; - } - } - else - { - continue; - } - } - - AddRecipient( pPlayer ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : origin - -// ATTN_NORM - -//----------------------------------------------------------------------------- -void CPASAttenuationFilter::Filter( const Vector& origin, float attenuation /*= ATTN_NORM*/ ) -{ - // Don't crop for attenuation in single player - if ( gpGlobals->maxClients == 1 ) - return; - - // CPASFilter adds them by pure PVS in constructor - if ( attenuation <= 0 ) - return; - - // Now remove recipients that are outside sound radius - float distance, maxAudible; - Vector vecRelative; - - int c = GetRecipientCount(); - - for ( int i = c - 1; i >= 0; i-- ) - { - int index = GetRecipientIndex( i ); - - CBaseEntity *ent = CBaseEntity::Instance( index ); - if ( !ent || !ent->IsPlayer() ) - { - Assert( 0 ); - continue; - } - - CBasePlayer *player = ToBasePlayer( ent ); - if ( !player ) - { - Assert( 0 ); - continue; - } - -#ifndef _XBOX - // never remove the HLTV bot - if ( player->IsHLTV() ) - continue; -#endif - - VectorSubtract( player->EarPosition(), origin, vecRelative ); - distance = VectorLength( vecRelative ); - maxAudible = ( 2 * SOUND_NORMAL_CLIP_DIST ) / attenuation; - if ( distance <= maxAudible ) - continue; - - RemoveRecipient( player ); - } -} diff --git a/game/server/recipientfilter.h b/game/server/recipientfilter.h deleted file mode 100644 index a12bed90d..000000000 --- a/game/server/recipientfilter.h +++ /dev/null @@ -1,228 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef RECIPIENTFILTER_H -#define RECIPIENTFILTER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "irecipientfilter.h" -#include "const.h" -#include "player.h" -#include "bitvec.h" - -//----------------------------------------------------------------------------- -// Purpose: A generic filter for determining whom to send message/sounds etc. to and -// providing a bit of additional state information -//----------------------------------------------------------------------------- -class CRecipientFilter : public IRecipientFilter -{ -public: - CRecipientFilter(); - virtual ~CRecipientFilter(); - - virtual bool IsReliable( void ) const; - virtual bool IsInitMessage( void ) const; - - virtual int GetRecipientCount( void ) const; - virtual int GetRecipientIndex( int slot ) const; - -public: - - void CopyFrom( const CRecipientFilter& src ); - - void Reset( void ); - - void MakeInitMessage( void ); - - void MakeReliable( void ); - - void AddAllPlayers( void ); - void AddRecipientsByPVS( const Vector& origin ); - void RemoveRecipientsByPVS( const Vector& origin ); - void AddRecipientsByPAS( const Vector& origin ); - void AddRecipient( CBasePlayer *player ); - void RemoveAllRecipients( void ); - void RemoveRecipient( CBasePlayer *player ); - void RemoveRecipientByPlayerIndex( int playerindex ); - void AddRecipientsByTeam( CTeam *team ); - void RemoveRecipientsByTeam( CTeam *team ); - void RemoveRecipientsNotOnTeam( CTeam *team ); - - void UsePredictionRules( void ); - bool IsUsingPredictionRules( void ) const; - - bool IgnorePredictionCull( void ) const; - void SetIgnorePredictionCull( bool ignore ); - - void AddPlayersFromBitMask( CBitVec< ABSOLUTE_PLAYER_LIMIT >& playerbits ); - void RemovePlayersFromBitMask( CBitVec< ABSOLUTE_PLAYER_LIMIT >& playerbits ); - -private: - - bool m_bReliable; - bool m_bInitMessage; - CUtlVector< int > m_Recipients; - - // If using prediction rules, the filter itself suppresses local player - bool m_bUsingPredictionRules; - // If ignoring prediction cull, then external systems can determine - // whether this is a special case where culling should not occur - bool m_bIgnorePredictionCull; -}; - -//----------------------------------------------------------------------------- -// Purpose: Simple class to create a filter for a single player ( unreliable ) -//----------------------------------------------------------------------------- -class CSingleUserRecipientFilter : public CRecipientFilter -{ -public: - CSingleUserRecipientFilter( CBasePlayer *player ) - { - AddRecipient( player ); - } -}; - -//----------------------------------------------------------------------------- -// Purpose: Simple class to create a filter for all players on a given team -//----------------------------------------------------------------------------- -class CTeamRecipientFilter : public CRecipientFilter -{ -public: - CTeamRecipientFilter( int team, bool isReliable = false ); -}; - -//----------------------------------------------------------------------------- -// Purpose: Simple class to create a filter for all players ( unreliable ) -//----------------------------------------------------------------------------- -class CBroadcastRecipientFilter : public CRecipientFilter -{ -public: - CBroadcastRecipientFilter( void ) - { - AddAllPlayers(); - } -}; - -//----------------------------------------------------------------------------- -// Purpose: Simple class to create a filter for all players ( reliable ) -//----------------------------------------------------------------------------- -class CReliableBroadcastRecipientFilter : public CBroadcastRecipientFilter -{ -public: - CReliableBroadcastRecipientFilter( void ) - { - MakeReliable(); - } -}; - -//----------------------------------------------------------------------------- -// Purpose: Add players in PAS to recipient list (unreliable) -//----------------------------------------------------------------------------- -class CPASFilter : public CRecipientFilter -{ -public: - CPASFilter( void ) - { - } - - CPASFilter( const Vector& origin ) - { - AddRecipientsByPAS( origin ); - } -}; - -//----------------------------------------------------------------------------- -// Purpose: Add players in PAS to list and if not in single player, use attenuation -// to remove those that are too far away from source origin -// Source origin can be stated as an entity or just a passed in origin -// (unreliable) -//----------------------------------------------------------------------------- -class CPASAttenuationFilter : public CPASFilter -{ -public: - CPASAttenuationFilter( void ) - { - } - - CPASAttenuationFilter( CBaseEntity *entity, soundlevel_t soundlevel ) : - CPASFilter( static_cast(entity->GetSoundEmissionOrigin()) ) - { - Filter( entity->GetSoundEmissionOrigin(), SNDLVL_TO_ATTN( soundlevel ) ); - } - - CPASAttenuationFilter( CBaseEntity *entity, float attenuation = ATTN_NORM ) : - CPASFilter( static_cast(entity->GetSoundEmissionOrigin()) ) - { - Filter( entity->GetSoundEmissionOrigin(), attenuation ); - } - - CPASAttenuationFilter( const Vector& origin, soundlevel_t soundlevel ) : - CPASFilter( origin ) - { - Filter( origin, SNDLVL_TO_ATTN( soundlevel ) ); - } - - CPASAttenuationFilter( const Vector& origin, float attenuation = ATTN_NORM ) : - CPASFilter( origin ) - { - Filter( origin, attenuation ); - } - - CPASAttenuationFilter( CBaseEntity *entity, const char *lookupSound ) : - CPASFilter( static_cast(entity->GetSoundEmissionOrigin()) ) - { - soundlevel_t level = CBaseEntity::LookupSoundLevel( lookupSound ); - float attenuation = SNDLVL_TO_ATTN( level ); - Filter( entity->GetSoundEmissionOrigin(), attenuation ); - } - - CPASAttenuationFilter( const Vector& origin, const char *lookupSound ) : - CPASFilter( origin ) - { - soundlevel_t level = CBaseEntity::LookupSoundLevel( lookupSound ); - float attenuation = SNDLVL_TO_ATTN( level ); - Filter( origin, attenuation ); - } - - CPASAttenuationFilter( CBaseEntity *entity, const char *lookupSound, HSOUNDSCRIPTHANDLE& handle ) : - CPASFilter( static_cast(entity->GetSoundEmissionOrigin()) ) - { - soundlevel_t level = CBaseEntity::LookupSoundLevel( lookupSound, handle ); - float attenuation = SNDLVL_TO_ATTN( level ); - Filter( entity->GetSoundEmissionOrigin(), attenuation ); - } - - CPASAttenuationFilter( const Vector& origin, const char *lookupSound, HSOUNDSCRIPTHANDLE& handle ) : - CPASFilter( origin ) - { - soundlevel_t level = CBaseEntity::LookupSoundLevel( lookupSound, handle ); - float attenuation = SNDLVL_TO_ATTN( level ); - Filter( origin, attenuation ); - } - - - - -public: - void Filter( const Vector& origin, float attenuation = ATTN_NORM ); -}; - -//----------------------------------------------------------------------------- -// Purpose: Simple PVS based filter ( unreliable ) -//----------------------------------------------------------------------------- -class CPVSFilter : public CRecipientFilter -{ -public: - CPVSFilter( const Vector& origin ) - { - AddRecipientsByPVS( origin ); - } -}; - -#endif // RECIPIENTFILTER_H diff --git a/game/server/rope.cpp b/game/server/rope.cpp deleted file mode 100644 index ed83fd4e2..000000000 --- a/game/server/rope.cpp +++ /dev/null @@ -1,759 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "rope.h" -#include "entitylist.h" -#include "rope_shared.h" -#include "sendproxy.h" -#include "rope_helpers.h" -#include "te_effect_dispatch.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//-------------------------------------------- -// Rope Spawn Flags -//-------------------------------------------- -#define SF_ROPE_RESIZE 1 // Automatically resize the rope - -// -------------------------------------------------------------------------------- // -// Fun With Tables. -// -------------------------------------------------------------------------------- // - -LINK_ENTITY_TO_CLASS( move_rope, CRopeKeyframe ); -LINK_ENTITY_TO_CLASS( keyframe_rope, CRopeKeyframe ); - -IMPLEMENT_SERVERCLASS_ST_NOBASE( CRopeKeyframe, DT_RopeKeyframe ) - SendPropEHandle(SENDINFO(m_hStartPoint)), - SendPropEHandle(SENDINFO(m_hEndPoint)), - SendPropInt( SENDINFO(m_iStartAttachment), 5, 0 ), - SendPropInt( SENDINFO(m_iEndAttachment), 5, 0 ), - - SendPropInt( SENDINFO(m_Slack), 12 ), - SendPropInt( SENDINFO(m_RopeLength), 15 ), - SendPropInt( SENDINFO(m_fLockedPoints), 4, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_RopeFlags), ROPE_NUMFLAGS, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nSegments), 4, SPROP_UNSIGNED ), - SendPropBool( SENDINFO(m_bConstrainBetweenEndpoints) ), - SendPropInt( SENDINFO(m_iRopeMaterialModelIndex), 16, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_Subdiv), 4, SPROP_UNSIGNED ), - - SendPropFloat( SENDINFO(m_TextureScale), 10, 0, 0.1f, 10.0f ), - SendPropFloat( SENDINFO(m_Width), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO(m_flScrollSpeed), 0, SPROP_NOSCALE ), - - SendPropVector(SENDINFO(m_vecOrigin), -1, SPROP_COORD ), - SendPropEHandle(SENDINFO_NAME(m_hMoveParent, moveparent) ), - - SendPropInt (SENDINFO(m_iParentAttachment), NUM_PARENTATTACHMENT_BITS, SPROP_UNSIGNED), -END_SEND_TABLE() - - -BEGIN_DATADESC( CRopeKeyframe ) - - DEFINE_FIELD( m_RopeFlags, FIELD_INTEGER ), - - DEFINE_KEYFIELD( m_iNextLinkName, FIELD_STRING, "NextKey" ), - DEFINE_KEYFIELD( m_Slack, FIELD_INTEGER, "Slack" ), - DEFINE_KEYFIELD( m_Width, FIELD_FLOAT, "Width" ), - DEFINE_KEYFIELD( m_TextureScale, FIELD_FLOAT, "TextureScale" ), - DEFINE_FIELD( m_nSegments, FIELD_INTEGER ), - DEFINE_FIELD( m_bConstrainBetweenEndpoints, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_strRopeMaterialModel, FIELD_STRING ), - DEFINE_FIELD( m_iRopeMaterialModelIndex, FIELD_MODELINDEX ), - DEFINE_KEYFIELD( m_Subdiv, FIELD_INTEGER, "Subdiv" ), - DEFINE_FIELD( m_RopeLength, FIELD_INTEGER ), - DEFINE_FIELD( m_fLockedPoints, FIELD_INTEGER ), - DEFINE_FIELD( m_bCreatedFromMapFile, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_flScrollSpeed, FIELD_FLOAT, "ScrollSpeed" ), - - DEFINE_FIELD( m_bStartPointValid, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bEndPointValid, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_hStartPoint, FIELD_EHANDLE ), - DEFINE_FIELD( m_hEndPoint, FIELD_EHANDLE ), - DEFINE_FIELD( m_iStartAttachment, FIELD_SHORT ), - DEFINE_FIELD( m_iEndAttachment, FIELD_SHORT ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetScrollSpeed", InputSetScrollSpeed ), - DEFINE_INPUTFUNC( FIELD_VECTOR, "SetForce", InputSetForce ), - DEFINE_INPUTFUNC( FIELD_VOID, "Break", InputBreak ), - -END_DATADESC() - - - -// -------------------------------------------------------------------------------- // -// CRopeKeyframe implementation. -// -------------------------------------------------------------------------------- // - -CRopeKeyframe::CRopeKeyframe() -{ - AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); - - m_takedamage = DAMAGE_YES; - - m_iStartAttachment = m_iEndAttachment = 0; - - m_Slack = 0; - m_Width = 2; - m_TextureScale = 4; // 4:1 - m_nSegments = 5; - m_RopeLength = 20; - m_fLockedPoints = (int) (ROPE_LOCK_START_POINT | ROPE_LOCK_END_POINT); // by default, both points are locked - m_flScrollSpeed = 0; - m_RopeFlags = ROPE_SIMULATE | ROPE_INITIAL_HANG; - m_iRopeMaterialModelIndex = -1; - m_Subdiv = 2; - - m_bCreatedFromMapFile = true; -} - - -CRopeKeyframe::~CRopeKeyframe() -{ - // Release transmit state ownership. - SetStartPoint( NULL, 0 ); - SetEndPoint( NULL, 0 ); - SetParent( NULL, 0 ); -} - - -void CRopeKeyframe::SetAttachmentPoint( CBaseHandle &hOutEnt, short &iOutAttachment, CBaseEntity *pEnt, int iAttachment ) -{ - // Unforce our previously attached entity from transmitting. - CBaseEntity *pCurEnt = gEntList.GetBaseEntity( hOutEnt ); - if ( pCurEnt && pCurEnt->edict() ) - { - pCurEnt->DecrementTransmitStateOwnedCounter(); - pCurEnt->DispatchUpdateTransmitState(); - } - - hOutEnt = pEnt; - iOutAttachment = iAttachment; - - // Force this entity to transmit. - if ( pEnt ) - { - pEnt->SetTransmitState( FL_EDICT_ALWAYS ); - pEnt->IncrementTransmitStateOwnedCounter(); - } - - EndpointsChanged(); -} - - -void CRopeKeyframe::SetStartPoint( CBaseEntity *pStartPoint, int attachment ) -{ - SetAttachmentPoint( m_hStartPoint.GetForModify(), m_iStartAttachment.GetForModify(), pStartPoint, attachment ); -} - -void CRopeKeyframe::SetEndPoint( CBaseEntity *pEndPoint, int attachment ) -{ - SetAttachmentPoint( m_hEndPoint.GetForModify(), m_iEndAttachment.GetForModify(), pEndPoint, attachment ); -} - -void CRopeKeyframe::SetParent( CBaseEntity *pNewParent, int iAttachment ) -{ - CBaseEntity *pCurParent = GetMoveParent(); - if ( pCurParent ) - { - pCurParent->DecrementTransmitStateOwnedCounter(); - pCurParent->DispatchUpdateTransmitState(); - } - - // Make sure our move parent always transmits or we get asserts on the client. - if ( pNewParent ) - { - pNewParent->IncrementTransmitStateOwnedCounter(); - pNewParent->SetTransmitState( FL_EDICT_ALWAYS ); - } - - BaseClass::SetParent( pNewParent, iAttachment ); -} - -void CRopeKeyframe::EnablePlayerWeaponAttach( bool bAttach ) -{ - int newFlags = m_RopeFlags; - if ( bAttach ) - newFlags |= ROPE_PLAYER_WPN_ATTACH; - else - newFlags &= ~ROPE_PLAYER_WPN_ATTACH; - - if ( newFlags != m_RopeFlags ) - { - m_RopeFlags = newFlags; - } -} - - -CRopeKeyframe* CRopeKeyframe::Create( - CBaseEntity *pStartEnt, - CBaseEntity *pEndEnt, - int iStartAttachment, - int iEndAttachment, - int ropeWidth, - const char *pMaterialName, - int numSegments - ) -{ - CRopeKeyframe *pRet = (CRopeKeyframe*)CreateEntityByName( "keyframe_rope" ); - if( !pRet ) - return NULL; - - pRet->SetStartPoint( pStartEnt, iStartAttachment ); - pRet->SetEndPoint( pEndEnt, iEndAttachment ); - pRet->m_bCreatedFromMapFile = false; - pRet->m_RopeFlags &= ~ROPE_INITIAL_HANG; - - pRet->Init(); - - pRet->SetMaterial( pMaterialName ); - pRet->m_Width = ropeWidth; - pRet->m_nSegments = clamp( numSegments, 2, ROPE_MAX_SEGMENTS ); - - return pRet; -} - - -CRopeKeyframe* CRopeKeyframe::CreateWithSecondPointDetached( - CBaseEntity *pStartEnt, - int iStartAttachment, - int ropeLength, - int ropeWidth, - const char *pMaterialName, - int numSegments, - bool bInitialHang - ) -{ - CRopeKeyframe *pRet = (CRopeKeyframe*)CreateEntityByName( "keyframe_rope" ); - if( !pRet ) - return NULL; - - pRet->SetStartPoint( pStartEnt, iStartAttachment ); - pRet->SetEndPoint( NULL, 0 ); - pRet->m_bCreatedFromMapFile = false; - pRet->m_fLockedPoints.Set( ROPE_LOCK_START_POINT ); // Only attach the first point. - - if( !bInitialHang ) - { - pRet->m_RopeFlags &= ~ROPE_INITIAL_HANG; - } - - pRet->Init(); - - pRet->SetMaterial( pMaterialName ); - pRet->m_RopeLength = ropeLength; - pRet->m_Width = ropeWidth; - pRet->m_nSegments = clamp( numSegments, 2, ROPE_MAX_SEGMENTS ); - - return pRet; -} - -void CRopeKeyframe::ActivateStartDirectionConstraints( bool bEnable ) -{ - if (bEnable) - { - m_fLockedPoints.Set( m_fLockedPoints | ROPE_LOCK_START_DIRECTION ); - } - else - { - m_fLockedPoints &= ~((int)ROPE_LOCK_START_DIRECTION); - } -} - - -void CRopeKeyframe::ActivateEndDirectionConstraints( bool bEnable ) -{ - if (bEnable) - { - m_fLockedPoints.Set( m_fLockedPoints | ROPE_LOCK_END_DIRECTION ); - } - else - { - m_fLockedPoints &= ~((int)ROPE_LOCK_END_DIRECTION); - } -} - - -void CRopeKeyframe::ShakeRopes( const Vector &vCenter, float flRadius, float flMagnitude ) -{ - CEffectData shakeData; - shakeData.m_vOrigin = vCenter; - shakeData.m_flRadius = flRadius; - shakeData.m_flMagnitude = flMagnitude; - DispatchEffect( "ShakeRopes", shakeData ); -} - - -bool CRopeKeyframe::SetupHangDistance( float flHangDist ) -{ - CBaseEntity *pEnt1 = m_hStartPoint.Get(); - CBaseEntity *pEnt2 = m_hEndPoint.Get(); - if ( !pEnt1 || !pEnt2 ) - return false; - - // Calculate starting conditions so we can force it to hang down N inches. - Vector v1 = pEnt1->GetAbsOrigin(); - if ( pEnt1->GetBaseAnimating() ) - pEnt1->GetBaseAnimating()->GetAttachment( m_iStartAttachment, v1 ); - - Vector v2 = pEnt2->GetAbsOrigin(); - if ( pEnt2->GetBaseAnimating() ) - pEnt2->GetBaseAnimating()->GetAttachment( m_iEndAttachment, v2 ); - - float flSlack, flLen; - CalcRopeStartingConditions( v1, v2, ROPE_MAX_SEGMENTS, flHangDist, &flLen, &flSlack ); - - m_RopeLength = (int)flLen; - m_Slack = (int)flSlack; - return true; -} - - -void CRopeKeyframe::Init() -{ - SetLocalAngles( vec3_angle ); - RecalculateLength(); - - m_nSegments = clamp( m_nSegments, 2, ROPE_MAX_SEGMENTS ); - - UpdateBBox( true ); - - m_bStartPointValid = (m_hStartPoint.Get() != NULL); - m_bEndPointValid = (m_hEndPoint.Get() != NULL); -} - - -void CRopeKeyframe::Activate() -{ - BaseClass::Activate(); - - if( !m_bCreatedFromMapFile ) - return; - - // Legacy support.. - if ( m_iRopeMaterialModelIndex == -1 ) - m_iRopeMaterialModelIndex = PrecacheModel( "cable/cable.vmt" ); - - // Find the next entity in our chain. - CBaseEntity *pEnt = gEntList.FindEntityByName( NULL, m_iNextLinkName ); - if( pEnt && pEnt->edict() ) - { - SetEndPoint( pEnt ); - - if( m_spawnflags & SF_ROPE_RESIZE ) - m_RopeFlags |= ROPE_RESIZE; - } - else - { - // If we're from the map file, and we don't have a target ent, and - // "Start Dangling" wasn't set, then this rope keyframe doesn't have - // any rope coming out of it. - if ( m_fLockedPoints & (int)ROPE_LOCK_END_POINT ) - { - m_RopeFlags &= ~ROPE_SIMULATE; - } - } - - // By default, our start point is our own entity. - SetStartPoint( this ); - - // If we don't do this here, then when we save/load, we won't "own" the transmit - // state of our parent, so the client might get our entity without our parent entity. - SetParent( GetParent(), GetParentAttachment() ); - - EndpointsChanged(); - - Init(); -} - -void CRopeKeyframe::EndpointsChanged() -{ - CBaseEntity *pStartEnt = m_hStartPoint.Get(); - if ( pStartEnt ) - { - if ( (pStartEnt != this) || GetMoveParent() ) - { - WatchPositionChanges( this, pStartEnt ); - } - } - CBaseEntity *pEndEnt = m_hEndPoint.Get(); - if ( pEndEnt ) - { - if ( (pEndEnt != this) || GetMoveParent() ) - { - WatchPositionChanges( this, pEndEnt ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Calculate the length of the rope -//----------------------------------------------------------------------------- -void CRopeKeyframe::RecalculateLength( void ) -{ - // Get my entities - if( m_hEndPoint.Get() ) - { - CBaseEntity *pStartEnt = m_hStartPoint.Get(); - CBaseEntity *pEndEnt = m_hEndPoint.Get(); - - // Set the length - m_RopeLength = (int)( pStartEnt->GetAbsOrigin() - pEndEnt->GetAbsOrigin() ).Length(); - } - else - { - m_RopeLength = 0; - } -} - -//----------------------------------------------------------------------------- -// Purpose: This should remove the rope next time it reaches a resting state. -// Right now only the client knows when it reaches a resting state, so -// for now it just removes itself after a short time. -//----------------------------------------------------------------------------- -void CRopeKeyframe::DieAtNextRest( void ) -{ - SetThink( &CBaseEntity::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 1.0f ); -} - - -void CRopeKeyframe::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ) -{ - if ( !pInfo->m_pTransmitEdict->Get( entindex() ) ) - { - BaseClass::SetTransmit( pInfo, bAlways ); - - // Make sure our target ents are sent too. - CBaseEntity *pEnt = m_hStartPoint; - if ( pEnt ) - pEnt->SetTransmit( pInfo, bAlways ); - - pEnt = m_hEndPoint; - if ( pEnt ) - pEnt->SetTransmit( pInfo, bAlways ); - } -} - - -bool CRopeKeyframe::GetEndPointPos2( CBaseEntity *pAttached, int iAttachment, Vector &vPos ) -{ - if( !pAttached ) - return false; - - if ( iAttachment > 0 ) - { - CBaseAnimating *pAnim = pAttached->GetBaseAnimating(); - if ( pAnim ) - { - if( !pAnim->GetAttachment( iAttachment, vPos ) ) - return false; - } - else - { - return false; - } - } - else - { - vPos = pAttached->GetAbsOrigin(); - } - - return true; -} - - -bool CRopeKeyframe::GetEndPointPos( int iPt, Vector &v ) -{ - if ( iPt == 0 ) - return GetEndPointPos2( m_hStartPoint, m_iStartAttachment, v ); - else - return GetEndPointPos2( m_hEndPoint, m_iEndAttachment, v ); -} - - -void CRopeKeyframe::UpdateBBox( bool bForceRelink ) -{ - Vector v1, v2; - Vector vMin, vMax; - if ( GetEndPointPos( 0, v1 ) ) - { - if ( GetEndPointPos( 1, v2 ) ) - { - VectorMin( v1, v2, vMin ); - VectorMax( v1, v2, vMax ); - - // Set our bounds to enclose both endpoints and relink. - vMin -= GetAbsOrigin(); - vMax -= GetAbsOrigin(); - } - else - { - vMin = vMax = v1 - GetAbsOrigin(); - } - } - else - { - vMin = vMax = Vector( 0, 0, 0 ); - } - - if ( WorldAlignMins() != vMin || WorldAlignMaxs() != vMax ) - { - UTIL_SetSize( this, vMin, vMax ); - } -} - -//------------------------------------------------------------------------------ -// Purpose : Propagate force to each link in the rope. Check for loops -// Input : -// Output : -//------------------------------------------------------------------------------ -void CRopeKeyframe::PropagateForce(CBaseEntity *pActivator, CBaseEntity *pCaller, CBaseEntity *pFirstLink, float x, float y, float z) -{ - EntityMessageBegin( this, true ); - WRITE_FLOAT( x ); - WRITE_FLOAT( y ); - WRITE_FLOAT( z ); - MessageEnd(); - - // UNDONE: Doesn't deal with intermediate loops - // Propagate to next segment - CRopeKeyframe *pNextLink = dynamic_cast((CBaseEntity *)m_hEndPoint); - if (pNextLink && pNextLink != pFirstLink) - { - pNextLink->PropagateForce(pActivator, pCaller, pFirstLink, x, y, z); - } -} - -//------------------------------------------------------------------------------ -// Purpose: Set an instaneous force on the rope. -// Input : Force vector. -//------------------------------------------------------------------------------ -void CRopeKeyframe::InputSetForce( inputdata_t &inputdata ) -{ - Vector vecForce; - inputdata.value.Vector3D(vecForce); - PropagateForce( inputdata.pActivator, inputdata.pCaller, this, vecForce.x, vecForce.y, vecForce.z ); -} - -//----------------------------------------------------------------------------- -// Purpose: Breaks the rope if able -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CRopeKeyframe::InputBreak( inputdata_t &inputdata ) -{ - //Route through the damage code - Break(); -} - -//----------------------------------------------------------------------------- -// Purpose: Breaks the rope -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CRopeKeyframe::Break( void ) -{ - DetachPoint( 0 ); - - // Find whoever references us and detach us from them. - // UNDONE: PERFORMANCE: This is very slow!!! - CRopeKeyframe *pTest = NULL; - pTest = gEntList.NextEntByClass( pTest ); - while ( pTest ) - { - if( stricmp( STRING(pTest->m_iNextLinkName), STRING(GetEntityName()) ) == 0 ) - { - pTest->DetachPoint( 1 ); - } - - pTest = gEntList.NextEntByClass( pTest ); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CRopeKeyframe::NotifyPositionChanged( CBaseEntity *pEntity ) -{ - // Update our bbox? - UpdateBBox( false ); - - CBaseEntity *ents[2] = { m_hStartPoint.Get(), m_hEndPoint.Get() }; - if ( (m_RopeFlags & ROPE_RESIZE) && ents[0] && ents[0]->edict() && ents[1] && ents[1]->edict() ) - { - int len = (int)( ents[0]->GetAbsOrigin() - ents[1]->GetAbsOrigin() ).Length() + m_Slack; - if ( len != m_RopeLength ) - { - m_RopeLength = len; - } - } - - // Figure out if our attachment points have gone away and make sure to update the client if they have. - bool *pValid[2] = { &m_bStartPointValid, &m_bEndPointValid }; - for ( int i=0; i < 2; i++ ) - { - bool bCurrentlyValid = ( ents[i] != NULL ); - if ( *pValid[i] != bCurrentlyValid ) - { - *pValid[i] = bCurrentlyValid; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Take damage will break the rope -//----------------------------------------------------------------------------- -int CRopeKeyframe::OnTakeDamage( const CTakeDamageInfo &info ) -{ - // Only allow this if it's been marked - if( !(m_RopeFlags & ROPE_BREAKABLE) ) - return false; - - Break(); - return 0; -} - - -void CRopeKeyframe::Precache() -{ - m_iRopeMaterialModelIndex = PrecacheModel( STRING( m_strRopeMaterialModel ) ); - BaseClass::Precache(); -} - - -void CRopeKeyframe::DetachPoint( int iPoint ) -{ - Assert( iPoint == 0 || iPoint == 1 ); - - m_fLockedPoints &= ~(1 << iPoint); -} - - -void CRopeKeyframe::EnableCollision() -{ - if( !( m_RopeFlags & ROPE_COLLIDE ) ) - { - m_RopeFlags |= ROPE_COLLIDE; - } -} - -void CRopeKeyframe::EnableWind( bool bEnable ) -{ - int flag = 0; - if ( !bEnable ) - flag |= ROPE_NO_WIND; - - if ( (m_RopeFlags & ROPE_NO_WIND) != flag ) - { - m_RopeFlags |= flag; - } -} - - -bool CRopeKeyframe::KeyValue( const char *szKeyName, const char *szValue ) -{ - if( stricmp( szKeyName, "Breakable" ) == 0 ) - { - if( atoi( szValue ) == 1 ) - m_RopeFlags |= ROPE_BREAKABLE; - } - else if( stricmp( szKeyName, "Collide" ) == 0 ) - { - if( atoi( szValue ) == 1 ) - m_RopeFlags |= ROPE_COLLIDE; - } - else if( stricmp( szKeyName, "Barbed" ) == 0 ) - { - if( atoi( szValue ) == 1 ) - m_RopeFlags |= ROPE_BARBED; - } - else if( stricmp( szKeyName, "Dangling" ) == 0 ) - { - if( atoi( szValue ) == 1 ) - m_fLockedPoints &= ~ROPE_LOCK_END_POINT; // detach our dest point - - return true; - } - else if( stricmp( szKeyName, "Type" ) == 0 ) - { - int iType = atoi( szValue ); - if( iType == 0 ) - m_nSegments = ROPE_MAX_SEGMENTS; - else if( iType == 1 ) - m_nSegments = ROPE_TYPE1_NUMSEGMENTS; - else - m_nSegments = ROPE_TYPE2_NUMSEGMENTS; - } - else if ( stricmp( szKeyName, "RopeShader" ) == 0 ) - { - // Legacy support for the RopeShader parameter. - int iShader = atoi( szValue ); - if ( iShader == 0 ) - { - m_iRopeMaterialModelIndex = PrecacheModel( "cable/cable.vmt" ); - } - else if ( iShader == 1 ) - { - m_iRopeMaterialModelIndex = PrecacheModel( "cable/rope.vmt" ); - } - else - { - m_iRopeMaterialModelIndex = PrecacheModel( "cable/chain.vmt" ); - } - } - else if ( stricmp( szKeyName, "RopeMaterial" ) == 0 ) - { - // Make sure we have a vmt extension. - if ( Q_stristr( szValue, ".vmt" ) ) - { - SetMaterial( szValue ); - } - else - { - char str[512]; - Q_snprintf( str, sizeof( str ), "%s.vmt", szValue ); - SetMaterial( str ); - } - } - - return BaseClass::KeyValue( szKeyName, szValue ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that sets the scroll speed. -//----------------------------------------------------------------------------- -void CRopeKeyframe::InputSetScrollSpeed( inputdata_t &inputdata ) -{ - m_flScrollSpeed = inputdata.value.Float(); -} - - -void CRopeKeyframe::SetMaterial( const char *pName ) -{ - m_strRopeMaterialModel = AllocPooledString( pName ); - m_iRopeMaterialModelIndex = PrecacheModel( STRING( m_strRopeMaterialModel ) ); -} - -int CRopeKeyframe::UpdateTransmitState() -{ - // Certain entities like sprites and ropes are strewn throughout the level and they rarely change. - // For these entities, it's more efficient to transmit them once and then always leave them on - // the client. Otherwise, the server will have to send big bursts of data with the entity states - // as they come in and out of the PVS. - return SetTransmitState( FL_EDICT_ALWAYS ); -} - - - - diff --git a/game/server/rope.h b/game/server/rope.h deleted file mode 100644 index 4c07fdf29..000000000 --- a/game/server/rope.h +++ /dev/null @@ -1,177 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ROPE_H -#define ROPE_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "baseentity.h" - -#include "positionwatcher.h" - -class CRopeKeyframe : public CBaseEntity, public IPositionWatcher -{ - DECLARE_CLASS( CRopeKeyframe, CBaseEntity ); -public: - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - CRopeKeyframe(); - virtual ~CRopeKeyframe(); - - // Create a rope and attach it to two entities. - // Attachment points on the entities are optional. - static CRopeKeyframe* Create( - CBaseEntity *pStartEnt, - CBaseEntity *pEndEnt, - int iStartAttachment=0, - int iEndAttachment=0, - int ropeWidth = 2, - const char *pMaterialName = "cable/cable.vmt", // Note: whoever creates the rope must - // use PrecacheModel for whatever material - // it specifies here. - int numSegments = 5 - ); - - static CRopeKeyframe* CreateWithSecondPointDetached( - CBaseEntity *pStartEnt, - int iStartAttachment = 0, // must be 0 if you don't want to use a specific model attachment. - int ropeLength = 20, - int ropeWidth = 2, - const char *pMaterialName = "cable/cable.vmt", // Note: whoever creates the rope - // use PrecacheModel for whatever material - // it specifies here. - int numSegments = 5, - bool bInitialHang = false - ); - - bool SetupHangDistance( float flHangDist ); - void ActivateStartDirectionConstraints( bool bEnable ); - void ActivateEndDirectionConstraints( bool bEnable ); - - - // Shakes all ropes near vCenter. The higher flMagnitude is, the larger the shake will be. - static void ShakeRopes( const Vector &vCenter, float flRadius, float flMagnitude ); - - -// CBaseEntity overrides. -public: - - // don't cross transitions - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } - virtual void Activate(); - virtual void Precache(); - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - virtual bool KeyValue( const char *szKeyName, const char *szValue ); - - void PropagateForce(CBaseEntity *pActivator, CBaseEntity *pCaller, CBaseEntity *pFirstLink, float x, float y, float z); - - // Once-off length recalculation - void RecalculateLength( void ); - - // Kill myself when I next come to rest - void DieAtNextRest( void ); - - virtual int UpdateTransmitState(void); - virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ); - virtual void SetParent( CBaseEntity *pParentEntity, int iAttachment ); - -// Input functions. -public: - - void InputSetScrollSpeed( inputdata_t &inputdata ); - void InputSetForce( inputdata_t &inputdata ); - void InputBreak( inputdata_t &inputdata ); - -public: - - bool Break( void ); - void DetachPoint( int iPoint ); - - void EndpointsChanged(); - - // By default, ropes don't collide with the world. Call this to enable it. - void EnableCollision(); - - // Toggle wind. - void EnableWind( bool bEnable ); - - // Unless this is called during initialization, the caller should have done - // PrecacheModel on whatever material they specify in here. - void SetMaterial( const char *pName ); - - CBaseEntity* GetEndPoint() { return m_hEndPoint.Get(); } - int GetEndAttachment() { return m_iStartAttachment; }; - - void SetStartPoint( CBaseEntity *pStartPoint, int attachment = 0 ); - void SetEndPoint( CBaseEntity *pEndPoint, int attachment = 0 ); - - // See ROPE_PLAYER_WPN_ATTACH for info. - void EnablePlayerWeaponAttach( bool bAttach ); - - - // IPositionWatcher - virtual void NotifyPositionChanged( CBaseEntity *pEntity ); - -private: - - void SetAttachmentPoint( CBaseHandle &hOutEnt, short &iOutAttachment, CBaseEntity *pEnt, int iAttachment ); - - // This is normally called by Activate but if you create the rope at runtime, - // you must call it after you have setup its variables. - void Init(); - - // These work just like the client-side versions. - bool GetEndPointPos2( CBaseEntity *pEnt, int iAttachment, Vector &v ); - bool GetEndPointPos( int iPt, Vector &v ); - - void UpdateBBox( bool bForceRelink ); - - -public: - - CNetworkVar( int, m_RopeFlags ); // Combination of ROPE_ defines in rope_shared.h - - string_t m_iNextLinkName; - CNetworkVar( int, m_Slack ); - CNetworkVar( float, m_Width ); - CNetworkVar( float, m_TextureScale ); - CNetworkVar( int, m_nSegments ); // Number of segments. - CNetworkVar( bool, m_bConstrainBetweenEndpoints ); - - string_t m_strRopeMaterialModel; - CNetworkVar( int, m_iRopeMaterialModelIndex ); // Index of sprite model with the rope's material. - - // Number of subdivisions in between segments. - CNetworkVar( int, m_Subdiv ); - - //EHANDLE m_hNextLink; - - CNetworkVar( int, m_RopeLength ); // Rope length at startup, used to calculate tension. - - CNetworkVar( int, m_fLockedPoints ); - - bool m_bCreatedFromMapFile; // set to false when creating at runtime - - CNetworkVar( float, m_flScrollSpeed ); - -private: - // Used to detect changes. - bool m_bStartPointValid; - bool m_bEndPointValid; - - CNetworkHandle( CBaseEntity, m_hStartPoint ); // StartPoint/EndPoint are entities - CNetworkHandle( CBaseEntity, m_hEndPoint ); - CNetworkVar( short, m_iStartAttachment ); // StartAttachment/EndAttachment are attachment points. - CNetworkVar( short, m_iEndAttachment ); -}; - - -#endif // ROPE_H diff --git a/game/server/saverestore_gamedll.cpp b/game/server/saverestore_gamedll.cpp deleted file mode 100644 index 399efcd0c..000000000 --- a/game/server/saverestore_gamedll.cpp +++ /dev/null @@ -1,241 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "isaverestore.h" -#include "saverestoretypes.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: iterates through a typedescript data block, so it can insert key/value data into the block -// Input : *pObject - pointer to the struct or class the data is to be insterted into -// *pFields - description of the data -// iNumFields - number of fields contained in pFields -// char *szKeyName - name of the variable to look for -// char *szValue - value to set the variable to -// Output : Returns true if the variable is found and set, false if the key is not found. -//----------------------------------------------------------------------------- -bool ParseKeyvalue( void *pObject, typedescription_t *pFields, int iNumFields, const char *szKeyName, const char *szValue ) -{ - int i; - typedescription_t *pField; - - for ( i = 0; i < iNumFields; i++ ) - { - pField = &pFields[i]; - - int fieldOffset = pField->fieldOffset[ TD_OFFSET_NORMAL ]; - - // Check the nested classes, but only if they aren't in array form. - if ((pField->fieldType == FIELD_EMBEDDED) && (pField->fieldSize == 1)) - { - for ( datamap_t *dmap = pField->td; dmap != NULL; dmap = dmap->baseMap ) - { - void *pEmbeddedObject = (void*)((char*)pObject + fieldOffset); - if ( ParseKeyvalue( pEmbeddedObject, dmap->dataDesc, dmap->dataNumFields, szKeyName, szValue) ) - return true; - } - } - - if ( (pField->flags & FTYPEDESC_KEY) && !stricmp(pField->externalName, szKeyName) ) - { - switch( pField->fieldType ) - { - case FIELD_MODELNAME: - case FIELD_SOUNDNAME: - case FIELD_STRING: - (*(string_t *)((char *)pObject + fieldOffset)) = AllocPooledString( szValue ); - return true; - - case FIELD_TIME: - case FIELD_FLOAT: - (*(float *)((char *)pObject + fieldOffset)) = atof( szValue ); - return true; - - case FIELD_BOOLEAN: - (*(bool *)((char *)pObject + fieldOffset)) = (bool)(atoi( szValue ) != 0); - return true; - - case FIELD_CHARACTER: - (*(char *)((char *)pObject + fieldOffset)) = (char)atoi( szValue ); - return true; - - case FIELD_SHORT: - (*(short *)((char *)pObject + fieldOffset)) = (short)atoi( szValue ); - return true; - - case FIELD_INTEGER: - case FIELD_TICK: - (*(int *)((char *)pObject + fieldOffset)) = atoi( szValue ); - return true; - - case FIELD_POSITION_VECTOR: - case FIELD_VECTOR: - UTIL_StringToVector( (float *)((char *)pObject + fieldOffset), szValue ); - return true; - - case FIELD_VMATRIX: - case FIELD_VMATRIX_WORLDSPACE: - UTIL_StringToFloatArray( (float *)((char *)pObject + fieldOffset), 16, szValue ); - return true; - - case FIELD_MATRIX3X4_WORLDSPACE: - UTIL_StringToFloatArray( (float *)((char *)pObject + fieldOffset), 12, szValue ); - return true; - - case FIELD_COLOR32: - UTIL_StringToColor32( (color32 *) ((char *)pObject + fieldOffset), szValue ); - return true; - - case FIELD_CUSTOM: - { - SaveRestoreFieldInfo_t fieldInfo = - { - (char *)pObject + fieldOffset, - pObject, - pField - }; - pField->pSaveRestoreOps->Parse( fieldInfo, szValue ); - return true; - } - - default: - case FIELD_INTERVAL: // Fixme, could write this if needed - case FIELD_CLASSPTR: - case FIELD_MODELINDEX: - case FIELD_MATERIALINDEX: - case FIELD_EDICT: - Warning( "Bad field in entity!!\n" ); - Assert(0); - break; - } - } - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: iterates through a typedescript data block, so it can insert key/value data into the block -// Input : *pObject - pointer to the struct or class the data is to be insterted into -// *pFields - description of the data -// iNumFields - number of fields contained in pFields -// char *szKeyName - name of the variable to look for -// char *szValue - value to set the variable to -// Output : Returns true if the variable is found and set, false if the key is not found. -//----------------------------------------------------------------------------- -bool ExtractKeyvalue( void *pObject, typedescription_t *pFields, int iNumFields, const char *szKeyName, char *szValue, int iMaxLen ) -{ - int i; - typedescription_t *pField; - - for ( i = 0; i < iNumFields; i++ ) - { - pField = &pFields[i]; - - int fieldOffset = pField->fieldOffset[ TD_OFFSET_NORMAL ]; - - // Check the nested classes, but only if they aren't in array form. - if ((pField->fieldType == FIELD_EMBEDDED) && (pField->fieldSize == 1)) - { - for ( datamap_t *dmap = pField->td; dmap != NULL; dmap = dmap->baseMap ) - { - void *pEmbeddedObject = (void*)((char*)pObject + fieldOffset); - if ( ExtractKeyvalue( pEmbeddedObject, dmap->dataDesc, dmap->dataNumFields, szKeyName, szValue, iMaxLen ) ) - return true; - } - } - - if ( (pField->flags & FTYPEDESC_KEY) && !stricmp(pField->externalName, szKeyName) ) - { - switch( pField->fieldType ) - { - case FIELD_MODELNAME: - case FIELD_SOUNDNAME: - case FIELD_STRING: - Q_strncpy( szValue, ((char *)pObject + fieldOffset), iMaxLen ); - return true; - - case FIELD_TIME: - case FIELD_FLOAT: - Q_snprintf( szValue, iMaxLen, "%f", (*(float *)((char *)pObject + fieldOffset)) ); - return true; - - case FIELD_BOOLEAN: - Q_snprintf( szValue, iMaxLen, "%d", (*(bool *)((char *)pObject + fieldOffset)) != 0); - return true; - - case FIELD_CHARACTER: - Q_snprintf( szValue, iMaxLen, "%d", (*(char *)((char *)pObject + fieldOffset)) ); - return true; - - case FIELD_SHORT: - Q_snprintf( szValue, iMaxLen, "%d", (*(short *)((char *)pObject + fieldOffset)) ); - return true; - - case FIELD_INTEGER: - case FIELD_TICK: - Q_snprintf( szValue, iMaxLen, "%d", (*(int *)((char *)pObject + fieldOffset)) ); - return true; - - case FIELD_POSITION_VECTOR: - case FIELD_VECTOR: - Q_snprintf( szValue, iMaxLen, "%f %f %f", - ((float *)((char *)pObject + fieldOffset))[0], - ((float *)((char *)pObject + fieldOffset))[1], - ((float *)((char *)pObject + fieldOffset))[2] ); - return true; - - case FIELD_VMATRIX: - case FIELD_VMATRIX_WORLDSPACE: - //UTIL_StringToFloatArray( (float *)((char *)pObject + fieldOffset), 16, szValue ); - return false; - - case FIELD_MATRIX3X4_WORLDSPACE: - //UTIL_StringToFloatArray( (float *)((char *)pObject + fieldOffset), 12, szValue ); - return false; - - case FIELD_COLOR32: - Q_snprintf( szValue, iMaxLen, "%d %d %d %d", - ((int *)((char *)pObject + fieldOffset))[0], - ((int *)((char *)pObject + fieldOffset))[1], - ((int *)((char *)pObject + fieldOffset))[2], - ((int *)((char *)pObject + fieldOffset))[3] ); - return true; - - case FIELD_CUSTOM: - { - /* - SaveRestoreFieldInfo_t fieldInfo = - { - (char *)pObject + fieldOffset, - pObject, - pField - }; - pField->pSaveRestoreOps->Parse( fieldInfo, szValue ); - */ - return false; - } - - default: - case FIELD_INTERVAL: // Fixme, could write this if needed - case FIELD_CLASSPTR: - case FIELD_MODELINDEX: - case FIELD_MATERIALINDEX: - case FIELD_EDICT: - Warning( "Bad field in entity!!\n" ); - Assert(0); - break; - } - } - } - - return false; -} diff --git a/game/server/sceneentity.cpp b/game/server/sceneentity.cpp deleted file mode 100644 index 36c2d0ac0..000000000 --- a/game/server/sceneentity.cpp +++ /dev/null @@ -1,5574 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include -#include "baseflex.h" -#include "entitylist.h" -#include "choreoevent.h" -#include "choreoactor.h" -#include "choreochannel.h" -#include "choreoscene.h" -#include "studio.h" -#include "networkstringtable_gamedll.h" -#include "ai_basenpc.h" -#include "engine/IEngineSound.h" -#include "ai_navigator.h" -#include "saverestore_utlvector.h" -#include "ai_baseactor.h" -#include "AI_Criteria.h" -#include "tier1/strtools.h" -#include "checksum_crc.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" -#include "utlbuffer.h" -#include "tier0/icommandline.h" -#include "sceneentity.h" -#include "datacache/idatacache.h" -#include "dt_utlvector_send.h" -#include "ichoreoeventcallback.h" -#include "scenefilecache/ISceneFileCache.h" -#include "SceneCache.h" -#include "scripted.h" -#include "env_debughistory.h" - -#ifdef HL2_EPISODIC -#include "npc_alyx_episodic.h" -#endif // HL2_EPISODIC - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern ISoundEmitterSystemBase *soundemitterbase; -extern ISceneFileCache *scenefilecache; - -class CSceneEntity; -class CBaseFlex; - -// VCDS are loaded from their compiled/binary format (much faster) -// Requies vcds be saved as compiled assets -//#define COMPILED_VCDS 1 - -static ConVar scene_forcecombined( "scene_forcecombined", "0", 0, "When playing back, force use of combined .wav files even in english." ); -static ConVar scene_maxcaptionradius( "scene_maxcaptionradius", "1200", 0, "Only show closed captions if recipient is within this many units of speaking actor (0==disabled)." ); - -// Assume sound system is 100 msec lagged (only used if we can't find snd_mixahead cvar!) -#define SOUND_SYSTEM_LATENCY_DEFAULT ( 0.1f ) - -// Think every 50 msec (FIXME: Try 10hz?) -#define SCENE_THINK_INTERVAL 0.001 // FIXME: make scene's think in concert with their npc's - -#define FINDNAMEDENTITY_MAX_ENTITIES 32 // max number of entities to be considered for random entity selection in FindNamedEntity - -// List of the last 5 lines of speech from NPCs for bug reports -static recentNPCSpeech_t speechListSounds[ SPEECH_LIST_MAX_SOUNDS ] = { { 0, "", "" }, { 0, "", "" }, { 0, "", "" }, { 0, "", "" }, { 0, "", "" } }; -static int speechListIndex = 0; - -// Only allow scenes to change their pitch within a range of values -#define SCENE_MIN_PITCH 0.25f -#define SCENE_MAX_PITCH 2.5f - -//=========================================================================================================== -// SCENE LIST MANAGER -//=========================================================================================================== -#define SCENE_LIST_MANAGER_MAX_SCENES 16 - -//----------------------------------------------------------------------------- -// Purpose: Entity that manages a list of scenes -//----------------------------------------------------------------------------- -class CSceneListManager : public CLogicalEntity -{ - DECLARE_CLASS( CSceneListManager, CLogicalEntity ); -public: - DECLARE_DATADESC(); - - virtual void Activate( void ); - - void ShutdownList( void ); - void SceneStarted( CBaseEntity *pSceneOrManager ); - void AddListManager( CSceneListManager *pManager ); - void RemoveScene( int iIndex ); - - // Inputs - void InputShutdown( inputdata_t &inputdata ); - -private: - CUtlVector< CHandle< CSceneListManager > > m_hListManagers; - string_t m_iszScenes[SCENE_LIST_MANAGER_MAX_SCENES]; - EHANDLE m_hScenes[SCENE_LIST_MANAGER_MAX_SCENES]; -}; - -//----------------------------------------------------------------------------- -// Purpose: This class exists solely to call think on all scene entities in a deterministic order -//----------------------------------------------------------------------------- -class CSceneManager : public CBaseEntity -{ - DECLARE_CLASS( CSceneManager, CBaseEntity ); - DECLARE_DATADESC(); - -public: - virtual void Spawn() - { - BaseClass::Spawn(); - SetNextThink( gpGlobals->curtime ); - } - - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() | FCAP_DONT_SAVE; } - - virtual void Think(); - - void ClearAllScenes(); - - void AddSceneEntity( CSceneEntity *scene ); - void RemoveSceneEntity( CSceneEntity *scene ); - - void QueueRestoredSound( CBaseFlex *actor, char const *soundname, soundlevel_t soundlevel, float time_in_past ); - - void OnClientActive( CBasePlayer *player ); - - void RemoveActorFromScenes( CBaseFlex *pActor, bool bInstancedOnly, bool bNonIdleOnly, const char *pszThisSceneOnly ); - void PauseActorsScenes( CBaseFlex *pActor, bool bInstancedOnly ); - bool IsInInterruptableScenes( CBaseFlex *pActor ); - void ResumeActorsScenes( CBaseFlex *pActor, bool bInstancedOnly ); - void QueueActorsScenesToResume( CBaseFlex *pActor, bool bInstancedOnly ); - bool IsRunningScriptedScene( CBaseFlex *pActor, bool bIgnoreInstancedScenes ); - bool IsRunningScriptedSceneAndNotPaused( CBaseFlex *pActor, bool bIgnoreInstancedScenes ); - bool IsRunningScriptedSceneWithSpeech( CBaseFlex *pActor, bool bIgnoreInstancedScenes ); - bool IsRunningScriptedSceneWithSpeechAndNotPaused( CBaseFlex *pActor, bool bIgnoreInstancedScenes ); - - -private: - - struct CRestoreSceneSound - { - CRestoreSceneSound() - { - actor = NULL; - soundname[0] = '\0'; - soundlevel = SNDLVL_NORM; - time_in_past = 0.0f; - } - - CHandle< CBaseFlex > actor; - char soundname[ 128 ]; - soundlevel_t soundlevel; - float time_in_past; - }; - - CUtlVector< CHandle< CSceneEntity > > m_ActiveScenes; - - CUtlVector< CRestoreSceneSound > m_QueuedSceneSounds; -}; - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CSceneManager ) - - DEFINE_UTLVECTOR( m_ActiveScenes, FIELD_EHANDLE ), - // DEFINE_FIELD( m_QueuedSceneSounds, CUtlVector < CRestoreSceneSound > ), // Don't save/restore this, it's created and used by OnRestore only - -END_DATADESC() - -#ifdef DISABLE_DEBUG_HISTORY -#define LocalScene_Printf Scene_Printf -#else -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pFormat - -// ... - -// Output : static void -//----------------------------------------------------------------------------- -void LocalScene_Printf( const char *pFormat, ... ) -{ - va_list marker; - char msg[8192]; - - va_start(marker, pFormat); - Q_vsnprintf(msg, sizeof(msg), pFormat, marker); - va_end(marker); - - Scene_Printf( "%s", msg ); - ADD_DEBUG_HISTORY( HISTORY_SCENE_PRINT, UTIL_VarArgs( "(%0.2f) %s", gpGlobals->curtime, msg ) ); -} -#endif - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *filename - -// **buffer - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CopySceneFileIntoMemory( char const *pFilename, void **pBuffer, int *pSize ) -{ - size_t bufSize = scenefilecache->GetSceneBufferSize( pFilename ); - if ( bufSize > 0 ) - { - *pBuffer = new byte[bufSize]; - *pSize = bufSize; - return scenefilecache->GetSceneData( pFilename, (byte *)(*pBuffer), bufSize ); - } - - *pBuffer = 0; - *pSize = 0; - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void FreeSceneFileMemory( void *buffer ) -{ - delete[] reinterpret_cast(buffer); -} - -//----------------------------------------------------------------------------- -// Binary compiled VCDs get their strings from a pool -//----------------------------------------------------------------------------- -class CChoreoStringPool : public IChoreoStringPool -{ -public: - short FindOrAddString( const char *pString ) - { - // huh?, no compilation at run time, only fetches - Assert( 0 ); - return -1; - } - - bool GetString( short stringId, char *buff, int buffSize ) - { - // fetch from compiled pool - const char *pString = scenefilecache->GetSceneString( stringId ); - if ( !pString ) - { - V_strncpy( buff, "", buffSize ); - return false; - } - V_strncpy( buff, pString, buffSize ); - return true; - } -}; -CChoreoStringPool g_ChoreoStringPool; - -//----------------------------------------------------------------------------- -// Purpose: Singleton scene manager. Created by first placed scene or recreated it it's deleted for some unknown reason -// Output : CSceneManager -//----------------------------------------------------------------------------- -CSceneManager *GetSceneManager() -{ - // Create it if it doesn't exist - static CHandle< CSceneManager > s_SceneManager; - if ( s_SceneManager == NULL ) - { - s_SceneManager = ( CSceneManager * )CreateEntityByName( "scene_manager" ); - Assert( s_SceneManager ); - if ( s_SceneManager ) - { - s_SceneManager->Spawn(); - } - } - - Assert( s_SceneManager ); - return s_SceneManager; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *player - -//----------------------------------------------------------------------------- -void SceneManager_ClientActive( CBasePlayer *player ) -{ - Assert( GetSceneManager() ); - - if ( GetSceneManager() ) - { - GetSceneManager()->OnClientActive( player ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: FIXME, need to deal with save/restore -//----------------------------------------------------------------------------- -class CSceneEntity : public CPointEntity, public IChoreoEventCallback -{ - friend class CInstancedSceneEntity; -public: - - enum - { - SCENE_ACTION_UNKNOWN = 0, - SCENE_ACTION_CANCEL, - SCENE_ACTION_RESUME, - }; - - enum - { - SCENE_BUSYACTOR_DEFAULT = 0, - SCENE_BUSYACTOR_WAIT, - SCENE_BUSYACTOR_INTERRUPT, - SCENE_BUSYACTOR_INTERRUPT_CANCEL, - }; - - - - - DECLARE_CLASS( CSceneEntity, CPointEntity ); - DECLARE_SERVERCLASS(); - - CSceneEntity( void ); - ~CSceneEntity( void ); - - // From IChoreoEventCallback - virtual void StartEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event ); - virtual void EndEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event ); - virtual void ProcessEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event ); - virtual bool CheckEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event ); - - - virtual int UpdateTransmitState(); - virtual int ShouldTransmit( const CCheckTransmitInfo *pInfo ); - - void SetRecipientFilter( IRecipientFilter *filter ); - - virtual void Activate(); - - virtual void Precache( void ); - virtual void Spawn( void ); - virtual void UpdateOnRemove( void ); - - virtual void OnRestore(); - virtual void OnLoaded(); - - DECLARE_DATADESC(); - - virtual void OnSceneFinished( bool canceled, bool fireoutput ); - - virtual void DoThink( float frametime ); - virtual void PauseThink( void ); - - bool IsPlayingBack() const { return m_bIsPlayingBack; } - bool IsPaused() const { return m_bPaused; } - bool IsMultiplayer() const { return m_bMultiplayer; } - - bool IsInterruptable(); - virtual void ClearInterrupt(); - virtual void CheckInterruptCompletion(); - - virtual bool InterruptThisScene( CSceneEntity *otherScene ); - void RequestCompletionNotification( CSceneEntity *otherScene ); - - virtual void NotifyOfCompletion( CSceneEntity *interruptor ); - - void AddListManager( CSceneListManager *pManager ); - - void ClearActivatorTargets( void ); - - void SetBreakOnNonIdle( bool bBreakOnNonIdle ) { m_bBreakOnNonIdle = bBreakOnNonIdle; } - bool ShouldBreakOnNonIdle( void ) { return m_bBreakOnNonIdle; } - - // Inputs - void InputStartPlayback( inputdata_t &inputdata ); - void InputPausePlayback( inputdata_t &inputdata ); - void InputResumePlayback( inputdata_t &inputdata ); - void InputCancelPlayback( inputdata_t &inputdata ); - void InputCancelAtNextInterrupt( inputdata_t &inputdata ); - void InputPitchShiftPlayback( inputdata_t &inputdata ); - void InputTriggerEvent( inputdata_t &inputdata ); - - // If the scene is playing, finds an actor in the scene who can respond to the specified concept token - void InputInterjectResponse( inputdata_t &inputdata ); - - // If this scene is waiting on an actor, give up and quit trying. - void InputStopWaitingForActor( inputdata_t &inputdata ); - - virtual void StartPlayback( void ); - virtual void PausePlayback( void ); - virtual void ResumePlayback( void ); - virtual void CancelPlayback( void ); - virtual void PitchShiftPlayback( float fPitch ); - virtual void QueueResumePlayback( void ); - - bool ValidScene() const; - - // Scene load/unload - static CChoreoScene *LoadScene( const char *filename, IChoreoEventCallback *pCallback ); - - void UnloadScene( void ); - - struct SpeakEventSound_t - { - CUtlSymbol m_Symbol; - float m_flStartTime; - }; - - static bool SpeakEventSoundLessFunc( const SpeakEventSound_t& lhs, const SpeakEventSound_t& rhs ); - - bool GetSoundNameForPlayer( CChoreoEvent *event, CBasePlayer *player, char *buf, size_t buflen ); - - void BuildSortedSpeakEventSoundsPrefetchList( - CChoreoScene *scene, - CUtlSymbolTable& table, - CUtlRBTree< SpeakEventSound_t >& soundnames, - float timeOffset ); - void PrefetchSpeakEventSounds( CUtlSymbolTable& table, CUtlRBTree< SpeakEventSound_t >& soundnames ); - - // Event handlers - virtual void DispatchStartExpression( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ); - virtual void DispatchEndExpression( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ); - virtual void DispatchStartFlexAnimation( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ); - virtual void DispatchEndFlexAnimation( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ); - virtual void DispatchStartGesture( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ); - virtual void DispatchEndGesture( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ); - virtual void DispatchStartLookAt( CChoreoScene *scene, CBaseFlex *actor, CBaseEntity *actor2, CChoreoEvent *event ); - virtual void DispatchEndLookAt( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ); - virtual void DispatchStartMoveTo( CChoreoScene *scene, CBaseFlex *actor, CBaseEntity *actor2, CChoreoEvent *event ); - virtual void DispatchEndMoveTo( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ); - virtual void DispatchStartSpeak( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event, soundlevel_t iSoundlevel ); - virtual void DispatchEndSpeak( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ); - virtual void DispatchStartFace( CChoreoScene *scene, CBaseFlex *actor, CBaseEntity *actor2, CChoreoEvent *event ); - virtual void DispatchEndFace( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ); - virtual void DispatchStartSequence( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ); - virtual void DispatchEndSequence( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ); - virtual void DispatchStartSubScene( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ); - virtual void DispatchStartInterrupt( CChoreoScene *scene, CChoreoEvent *event ); - virtual void DispatchEndInterrupt( CChoreoScene *scene, CChoreoEvent *event ); - virtual void DispatchStartGeneric( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ); - virtual void DispatchEndGeneric( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ); - - // NPC can play interstitial vcds (such as responding to the player doing something during a scene) - virtual void DispatchStartPermitResponses( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ); - virtual void DispatchEndPermitResponses( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ); - - - // Global events - virtual void DispatchProcessLoop( CChoreoScene *scene, CChoreoEvent *event ); - virtual void DispatchPauseScene( CChoreoScene *scene, const char *parameters ); - virtual void DispatchStopPoint( CChoreoScene *scene, const char *parameters ); - - virtual float EstimateLength( void ); - - void CancelIfSceneInvolvesActor( CBaseEntity *pActor ); - bool InvolvesActor( CBaseEntity *pActor ); // NOTE: returns false if scene hasn't loaded yet - - void GenerateSoundScene( CBaseFlex *pActor, const char *soundname ); - - virtual float GetPostSpeakDelay() { return 1.0; } - - bool HasUnplayedSpeech( void ); - bool HasFlexAnimation( void ); - - void SetCurrentTime( float t, bool forceClientSync ); - - void InputScriptPlayerDeath( inputdata_t &inputdata ); - -// Data -public: - string_t m_iszSceneFile; - - string_t m_iszResumeSceneFile; - EHANDLE m_hWaitingForThisResumeScene; - bool m_bWaitingForResumeScene; - - string_t m_iszTarget1; - string_t m_iszTarget2; - string_t m_iszTarget3; - string_t m_iszTarget4; - string_t m_iszTarget5; - string_t m_iszTarget6; - string_t m_iszTarget7; - string_t m_iszTarget8; - - EHANDLE m_hTarget1; - EHANDLE m_hTarget2; - EHANDLE m_hTarget3; - EHANDLE m_hTarget4; - EHANDLE m_hTarget5; - EHANDLE m_hTarget6; - EHANDLE m_hTarget7; - EHANDLE m_hTarget8; - - CNetworkVar( bool, m_bIsPlayingBack ); - CNetworkVar( bool, m_bPaused ); - CNetworkVar( bool, m_bMultiplayer ); - CNetworkVar( float, m_flForceClientTime ); - - float m_flCurrentTime; - float m_flFrameTime; - bool m_bCancelAtNextInterrupt; - - float m_fPitch; - - bool m_bAutomated; - int m_nAutomatedAction; - float m_flAutomationDelay; - float m_flAutomationTime; - - // A pause from an input requires another input to unpause (it's a hard pause) - bool m_bPausedViaInput; - - // Waiting for the actor to be able to speak. - bool m_bWaitingForActor; - - // Waiting for a point at which we can interrupt our actors - bool m_bWaitingForInterrupt; - bool m_bInterruptedActorsScenes; - - bool m_bBreakOnNonIdle; - -public: - virtual CBaseFlex *FindNamedActor( int index ); - virtual CBaseFlex *FindNamedActor( CChoreoActor *pChoreoActor ); - virtual CBaseFlex *FindNamedActor( const char *name ); - virtual CBaseEntity *FindNamedEntity( const char *name, CBaseEntity *pActor = NULL, bool bBaseFlexOnly = false, bool bUseClear = false ); - CBaseEntity *FindNamedTarget( string_t iszTarget, bool bBaseFlexOnly = false ); - virtual CBaseEntity *FindNamedEntityClosest( const char *name, CBaseEntity *pActor = NULL, bool bBaseFlexOnly = false, bool bUseClear = false, const char *pszSecondary = NULL ); - -private: - - CUtlVector< CHandle< CBaseFlex > > m_hActorList; - CUtlVector< CHandle< CBaseEntity > > m_hRemoveActorList; - -private: - - inline void SetRestoring( bool bRestoring ); - - // Prevent derived classed from using this! - virtual void Think( void ) {}; - - - void ClearSceneEvents( CChoreoScene *scene, bool canceled ); - void ClearSchedules( CChoreoScene *scene ); - - float GetSoundSystemLatency( void ); - void PrecacheScene( CChoreoScene *scene ); - - CChoreoScene *GenerateSceneForSound( CBaseFlex *pFlexActor, const char *soundname ); - - bool CheckActors(); - - void PrefetchAnimBlocks( CChoreoScene *scene ); - - bool ShouldNetwork() const; - // Set if we tried to async the scene but the FS returned that the data was not loadable - bool m_bSceneMissing; - - CChoreoScene *m_pScene; - CNetworkVar( int, m_nSceneStringIndex ); - - const ConVar *m_pcvSndMixahead; - - COutputEvent m_OnStart; - COutputEvent m_OnCompletion; - COutputEvent m_OnCanceled; - COutputEvent m_OnTrigger1; - COutputEvent m_OnTrigger2; - COutputEvent m_OnTrigger3; - COutputEvent m_OnTrigger4; - COutputEvent m_OnTrigger5; - COutputEvent m_OnTrigger6; - COutputEvent m_OnTrigger7; - COutputEvent m_OnTrigger8; - COutputEvent m_OnTrigger9; - COutputEvent m_OnTrigger10; - COutputEvent m_OnTrigger11; - COutputEvent m_OnTrigger12; - COutputEvent m_OnTrigger13; - COutputEvent m_OnTrigger14; - COutputEvent m_OnTrigger15; - COutputEvent m_OnTrigger16; - - int m_nInterruptCount; - bool m_bInterrupted; - CHandle< CSceneEntity > m_hInterruptScene; - - bool m_bCompletedEarly; - - bool m_bInterruptSceneFinished; - CUtlVector< CHandle< CSceneEntity > > m_hNotifySceneCompletion; - CUtlVector< CHandle< CSceneListManager > > m_hListManagers; - - bool m_bRestoring; - - bool m_bGenerated; - string_t m_iszSoundName; - CHandle< CBaseFlex > m_hActor; - - EHANDLE m_hActivator; - - int m_BusyActor; - - int m_iPlayerDeathBehavior; - - CRecipientFilter *m_pRecipientFilter; - -public: - void SetBackground( bool bIsBackground ); - bool IsBackground( void ); -}; - -LINK_ENTITY_TO_CLASS( logic_choreographed_scene, CSceneEntity ); -LINK_ENTITY_TO_CLASS( scripted_scene, CSceneEntity ); - -IMPLEMENT_SERVERCLASS_ST_NOBASE( CSceneEntity, DT_SceneEntity ) - SendPropInt(SENDINFO(m_nSceneStringIndex),MAX_CHOREO_SCENES_STRING_BITS,SPROP_UNSIGNED), - SendPropBool(SENDINFO(m_bIsPlayingBack)), - SendPropBool(SENDINFO(m_bPaused)), - SendPropBool(SENDINFO(m_bMultiplayer)), - SendPropFloat(SENDINFO(m_flForceClientTime)), - SendPropUtlVector( - SENDINFO_UTLVECTOR( m_hActorList ), - MAX_ACTORS_IN_SCENE, // max elements - SendPropEHandle( NULL, 0 ) ), -END_SEND_TABLE() - -BEGIN_DATADESC( CSceneEntity ) - - // Keys - DEFINE_KEYFIELD( m_iszSceneFile, FIELD_STRING, "SceneFile" ), - DEFINE_KEYFIELD( m_iszResumeSceneFile, FIELD_STRING, "ResumeSceneFile" ), - DEFINE_FIELD( m_hWaitingForThisResumeScene, FIELD_EHANDLE ), - DEFINE_FIELD( m_bWaitingForResumeScene, FIELD_BOOLEAN ), - - DEFINE_KEYFIELD( m_iszTarget1, FIELD_STRING, "target1" ), - DEFINE_KEYFIELD( m_iszTarget2, FIELD_STRING, "target2" ), - DEFINE_KEYFIELD( m_iszTarget3, FIELD_STRING, "target3" ), - DEFINE_KEYFIELD( m_iszTarget4, FIELD_STRING, "target4" ), - DEFINE_KEYFIELD( m_iszTarget5, FIELD_STRING, "target5" ), - DEFINE_KEYFIELD( m_iszTarget6, FIELD_STRING, "target6" ), - DEFINE_KEYFIELD( m_iszTarget7, FIELD_STRING, "target7" ), - DEFINE_KEYFIELD( m_iszTarget8, FIELD_STRING, "target8" ), - - DEFINE_KEYFIELD( m_BusyActor, FIELD_INTEGER, "busyactor" ), - - DEFINE_FIELD( m_hTarget1, FIELD_EHANDLE ), - DEFINE_FIELD( m_hTarget2, FIELD_EHANDLE ), - DEFINE_FIELD( m_hTarget3, FIELD_EHANDLE ), - DEFINE_FIELD( m_hTarget4, FIELD_EHANDLE ), - DEFINE_FIELD( m_hTarget5, FIELD_EHANDLE ), - DEFINE_FIELD( m_hTarget6, FIELD_EHANDLE ), - DEFINE_FIELD( m_hTarget7, FIELD_EHANDLE ), - DEFINE_FIELD( m_hTarget8, FIELD_EHANDLE ), - - DEFINE_FIELD( m_bIsPlayingBack, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bPaused, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flCurrentTime, FIELD_FLOAT ), // relative, not absolute time - DEFINE_FIELD( m_flForceClientTime, FIELD_FLOAT ), - DEFINE_FIELD( m_flFrameTime, FIELD_FLOAT ), // last frametime - DEFINE_FIELD( m_bCancelAtNextInterrupt, FIELD_BOOLEAN ), - DEFINE_FIELD( m_fPitch, FIELD_FLOAT ), - DEFINE_FIELD( m_bAutomated, FIELD_BOOLEAN ), - DEFINE_FIELD( m_nAutomatedAction, FIELD_INTEGER ), - DEFINE_FIELD( m_flAutomationDelay, FIELD_FLOAT ), - DEFINE_FIELD( m_flAutomationTime, FIELD_FLOAT ), // relative, not absolute time - - DEFINE_FIELD( m_bPausedViaInput, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bWaitingForActor, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bWaitingForInterrupt, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bInterruptedActorsScenes, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bBreakOnNonIdle, FIELD_BOOLEAN ), - - DEFINE_UTLVECTOR( m_hActorList, FIELD_EHANDLE ), - DEFINE_UTLVECTOR( m_hRemoveActorList, FIELD_EHANDLE ), - - // DEFINE_FIELD( m_pScene, FIELD_XXXX ) // Special processing used for this - - // These are set up in the constructor - // DEFINE_FIELD( m_pcvSndMixahead, FIELD_XXXXX ), - // DEFINE_FIELD( m_bRestoring, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_nInterruptCount, FIELD_INTEGER ), - DEFINE_FIELD( m_bInterrupted, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hInterruptScene, FIELD_EHANDLE ), - DEFINE_FIELD( m_bCompletedEarly, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bInterruptSceneFinished, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_bGenerated, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iszSoundName, FIELD_STRING ), - DEFINE_FIELD( m_hActor, FIELD_EHANDLE ), - DEFINE_FIELD( m_hActivator, FIELD_EHANDLE ), - - // DEFINE_FIELD( m_bSceneMissing, FIELD_BOOLEAN ), - DEFINE_UTLVECTOR( m_hNotifySceneCompletion, FIELD_EHANDLE ), - DEFINE_UTLVECTOR( m_hListManagers, FIELD_EHANDLE ), - - DEFINE_FIELD( m_bMultiplayer, FIELD_BOOLEAN ), -// DEFINE_FIELD( m_nSceneStringIndex, FIELD_INTEGER ), - - // DEFINE_FIELD( m_pRecipientFilter, IRecipientFilter* ), // Multiplayer only - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Start", InputStartPlayback ), - DEFINE_INPUTFUNC( FIELD_VOID, "Pause", InputPausePlayback ), - DEFINE_INPUTFUNC( FIELD_VOID, "Resume", InputResumePlayback ), - DEFINE_INPUTFUNC( FIELD_VOID, "Cancel", InputCancelPlayback ), - DEFINE_INPUTFUNC( FIELD_VOID, "CancelAtNextInterrupt", InputCancelAtNextInterrupt ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "PitchShift", InputPitchShiftPlayback ), - DEFINE_INPUTFUNC( FIELD_STRING, "InterjectResponse", InputInterjectResponse ), - DEFINE_INPUTFUNC( FIELD_VOID, "StopWaitingForActor", InputStopWaitingForActor ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "Trigger", InputTriggerEvent ), - - DEFINE_KEYFIELD( m_iPlayerDeathBehavior, FIELD_INTEGER, "onplayerdeath" ), - DEFINE_INPUTFUNC( FIELD_VOID, "ScriptPlayerDeath", InputScriptPlayerDeath ), - - // Outputs - DEFINE_OUTPUT( m_OnStart, "OnStart"), - DEFINE_OUTPUT( m_OnCompletion, "OnCompletion"), - DEFINE_OUTPUT( m_OnCanceled, "OnCanceled"), - DEFINE_OUTPUT( m_OnTrigger1, "OnTrigger1"), - DEFINE_OUTPUT( m_OnTrigger2, "OnTrigger2"), - DEFINE_OUTPUT( m_OnTrigger3, "OnTrigger3"), - DEFINE_OUTPUT( m_OnTrigger4, "OnTrigger4"), - DEFINE_OUTPUT( m_OnTrigger5, "OnTrigger5"), - DEFINE_OUTPUT( m_OnTrigger6, "OnTrigger6"), - DEFINE_OUTPUT( m_OnTrigger7, "OnTrigger7"), - DEFINE_OUTPUT( m_OnTrigger8, "OnTrigger8"), - DEFINE_OUTPUT( m_OnTrigger9, "OnTrigger9"), - DEFINE_OUTPUT( m_OnTrigger10, "OnTrigger10"), - DEFINE_OUTPUT( m_OnTrigger11, "OnTrigger11"), - DEFINE_OUTPUT( m_OnTrigger12, "OnTrigger12"), - DEFINE_OUTPUT( m_OnTrigger13, "OnTrigger13"), - DEFINE_OUTPUT( m_OnTrigger14, "OnTrigger14"), - DEFINE_OUTPUT( m_OnTrigger15, "OnTrigger15"), - DEFINE_OUTPUT( m_OnTrigger16, "OnTrigger16"), -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CSceneEntity::CSceneEntity( void ) -{ - m_bWaitingForActor = false; - m_bWaitingForInterrupt = false; - m_bInterruptedActorsScenes = false; - m_bIsPlayingBack = false; - m_bPaused = false; - m_bMultiplayer = false; - m_fPitch = 1.0f; - m_iszSceneFile = NULL_STRING; - m_iszResumeSceneFile = NULL_STRING; - m_hWaitingForThisResumeScene = NULL; - m_bWaitingForResumeScene = false; - SetCurrentTime( 0.0f, false ); - m_bCancelAtNextInterrupt = false; - - m_bAutomated = false; - m_nAutomatedAction = SCENE_ACTION_UNKNOWN; - m_flAutomationDelay = 0.0f; - m_flAutomationTime = 0.0f; - - m_bPausedViaInput = false; - ClearInterrupt(); - - m_pScene = NULL; - - m_bCompletedEarly = false; - - m_pcvSndMixahead = cvar->FindVar( "snd_mixahead" ); - - m_BusyActor = SCENE_BUSYACTOR_DEFAULT; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CSceneEntity::~CSceneEntity( void ) -{ - delete m_pRecipientFilter; - m_pRecipientFilter = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Resets time such that the client version of the .vcd is also updated, if appropriate -// Input : t - -// forceClientSync - forces new timestamp down to client .dll via networking -//----------------------------------------------------------------------------- -void CSceneEntity::SetCurrentTime( float t, bool bForceClientSync ) -{ - m_flCurrentTime = t; - if ( gpGlobals->maxClients == 1 || bForceClientSync ) - { - m_flForceClientTime = t; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSceneEntity::UpdateOnRemove( void ) -{ - UnloadScene(); - BaseClass::UpdateOnRemove(); - - if ( GetSceneManager() ) - { - GetSceneManager()->RemoveSceneEntity( this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -// *soundname - -// Output : CChoreoScene -//----------------------------------------------------------------------------- -CChoreoScene *CSceneEntity::GenerateSceneForSound( CBaseFlex *pFlexActor, const char *soundname ) -{ - float duration = CBaseEntity::GetSoundDuration( soundname, pFlexActor ? STRING( pFlexActor->GetModelName() ) : NULL ); - if( duration <= 0.0f ) - { - Warning( "CSceneEntity::GenerateSceneForSound: Couldn't determine duration of %s\n", soundname ); - return NULL; - } - - CChoreoScene *scene = new CChoreoScene( this ); - if ( !scene ) - { - Warning( "CSceneEntity::GenerateSceneForSound: Failed to allocated new scene!!!\n" ); - } - else - { - scene->SetPrintFunc( LocalScene_Printf ); - - - CChoreoActor *actor = scene->AllocActor(); - CChoreoChannel *channel = scene->AllocChannel(); - CChoreoEvent *event = scene->AllocEvent(); - - Assert( actor ); - Assert( channel ); - Assert( event ); - - if ( !actor || !channel || !event ) - { - Warning( "CSceneEntity::GenerateSceneForSound: Alloc of actor, channel, or event failed!!!\n" ); - delete scene; - return NULL; - } - - // Set us up the actorz - actor->SetName( "!self" ); // Could be pFlexActor->GetName()? - actor->SetActive( true ); - - // Set us up the channelz - channel->SetName( STRING( m_iszSceneFile ) ); - channel->SetActor( actor ); - - // Add to actor - actor->AddChannel( channel ); - - // Set us up the eventz - event->SetType( CChoreoEvent::SPEAK ); - event->SetName( soundname ); - event->SetParameters( soundname ); - event->SetStartTime( 0.0f ); - event->SetUsingRelativeTag( false ); - event->SetEndTime( duration ); - event->SnapTimes(); - - // Add to channel - channel->AddEvent( event ); - - // Point back to our owners - event->SetChannel( channel ); - event->SetActor( actor ); - - } - - return scene; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSceneEntity::Activate() -{ - if ( m_bGenerated && !m_pScene ) - { - m_pScene = GenerateSceneForSound( m_hActor, STRING( m_iszSoundName ) ); - } - - BaseClass::Activate(); - - if ( GetSceneManager() ) - { - GetSceneManager()->AddSceneEntity( this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CSceneEntity::GetSoundSystemLatency( void ) -{ - if ( m_pcvSndMixahead ) - { - return m_pcvSndMixahead->GetFloat(); - } - - // Assume 100 msec sound system latency - return SOUND_SYSTEM_LATENCY_DEFAULT; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *scene - -//----------------------------------------------------------------------------- -void CSceneEntity::PrecacheScene( CChoreoScene *scene ) -{ - Assert( scene ); - - // Iterate events and precache necessary resources - for ( int i = 0; i < scene->GetNumEvents(); i++ ) - { - CChoreoEvent *event = scene->GetEvent( i ); - if ( !event ) - continue; - - // load any necessary data - switch (event->GetType() ) - { - default: - break; - case CChoreoEvent::SPEAK: - { - // Defined in SoundEmitterSystem.cpp - // NOTE: The script entries associated with .vcds are forced to preload to avoid - // loading hitches during triggering - PrecacheScriptSound( event->GetParameters() ); - - if ( event->GetCloseCaptionType() == CChoreoEvent::CC_MASTER && - event->GetNumSlaves() > 0 ) - { - char tok[ CChoreoEvent::MAX_CCTOKEN_STRING ]; - if ( event->GetPlaybackCloseCaptionToken( tok, sizeof( tok ) ) ) - { - PrecacheScriptSound( tok ); - } - } - } - break; - case CChoreoEvent::SUBSCENE: - { - // Only allow a single level of subscenes for now - if ( !scene->IsSubScene() ) - { - CChoreoScene *subscene = event->GetSubScene(); - if ( !subscene ) - { - subscene = LoadScene( event->GetParameters(), this ); - subscene->SetSubScene( true ); - event->SetSubScene( subscene ); - - // Now precache it's resources, if any - PrecacheScene( subscene ); - } - } - } - break; - } - } -} -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSceneEntity::Precache( void ) -{ - if ( m_bGenerated ) - return; - - if ( m_iszSceneFile == NULL_STRING ) - return; - - if ( m_iszResumeSceneFile != NULL_STRING ) - { - PrecacheInstancedScene( STRING( m_iszResumeSceneFile ) ); - } - - PrecacheInstancedScene( STRING( m_iszSceneFile ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pActor - -// *soundname - -//----------------------------------------------------------------------------- -void CSceneEntity::GenerateSoundScene( CBaseFlex *pActor, const char *soundname ) -{ - m_bGenerated = true; - m_iszSoundName = MAKE_STRING( soundname ); - m_hActor = pActor; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CSceneEntity::HasUnplayedSpeech( void ) -{ - if ( m_pScene ) - return m_pScene->HasUnplayedSpeech(); - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CSceneEntity::HasFlexAnimation( void ) -{ - if ( m_pScene ) - return m_pScene->HasFlexAnimation(); - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : -//----------------------------------------------------------------------------- - -void CSceneEntity::SetBackground( bool bIsBackground ) -{ - if ( m_pScene ) - { - m_pScene->SetBackground( bIsBackground ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- - -bool CSceneEntity::IsBackground( void ) -{ - if ( m_pScene ) - return m_pScene->IsBackground( ); - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSceneEntity::OnRestore() -{ - BaseClass::OnRestore(); - - // Fix saved games that have their pitch set to zero - if ( m_fPitch < SCENE_MIN_PITCH || m_fPitch > SCENE_MAX_PITCH ) - m_fPitch = 1.0f; - - if ( !m_bIsPlayingBack ) - return; - - if ( !m_pScene ) - { - m_pScene = LoadScene( STRING( m_iszSceneFile ), this ); - if ( !m_pScene ) - { - m_bSceneMissing = true; - return; - } - - OnLoaded(); - - if ( ShouldNetwork() ) - { - m_nSceneStringIndex = g_pStringTableClientSideChoreoScenes->AddString( CBaseEntity::IsServer(), STRING( m_iszSceneFile ) ); - } - - UpdateTransmitState(); - } - - m_bSceneMissing = false; - - int i; - for ( i = 0 ; i < m_pScene->GetNumActors(); i++ ) - { - CBaseFlex *pTestActor = FindNamedActor( i ); - if ( !pTestActor ) - continue; - - if ( !pTestActor->MyCombatCharacterPointer() ) - continue; - - // Needed? - //if ( !pTestActor->MyCombatCharacterPointer()->IsAlive() ) - // return; - - pTestActor->StartChoreoScene( m_pScene ); - } - - float dt = SCENE_THINK_INTERVAL; - - bool paused = m_bPaused; - - m_bPaused = false; - - // roll back slightly so that pause events still trigger - m_pScene->ResetSimulation( true, m_flCurrentTime - SCENE_THINK_INTERVAL, m_flCurrentTime ); - m_pScene->SetTime( m_flCurrentTime - SCENE_THINK_INTERVAL ); - - SetCurrentTime( m_flCurrentTime, true ); - - // Robin: This causes a miscount of any interrupt events in the scene. - // All the variables are saved/restored properly, so we can safely leave them alone. - //ClearInterrupt(); - - SetRestoring( true ); - - DoThink( dt ); - - SetRestoring( false ); - - if ( paused ) - { - PausePlayback(); - } - - NetworkProp()->NetworkStateForceUpdate(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CSceneEntity::SetRestoring( bool bRestoring ) -{ - m_bRestoring = bRestoring; - if ( m_pScene ) - { - m_pScene->SetRestoring( bRestoring ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSceneEntity::Spawn( void ) -{ - Precache(); -} - -void CSceneEntity::PauseThink( void ) -{ - if ( !m_pScene ) - return; - - // Stay paused if pause occurred from interrupt - if ( m_bInterrupted ) - return; - - // If entity I/O paused the scene, then it'll have to resume/cancel the scene... - if ( m_bPausedViaInput ) - { - // If we're waiting for a resume scene to finish, continue when it's done - if ( m_bWaitingForResumeScene && !m_hWaitingForThisResumeScene ) - { - // Resume scene has finished, stop waiting for it - m_bWaitingForResumeScene = false; - } - else - { - return; - } - } - - if ( !m_bAutomated ) - { - // FIXME: Game code should check for AI waiting conditions being met, etc. - // - // - // - bool bAllFinished = m_pScene->CheckEventCompletion( ); - - if ( bAllFinished ) - { - // Perform action - switch ( m_nAutomatedAction ) - { - case SCENE_ACTION_RESUME: - ResumePlayback(); - break; - case SCENE_ACTION_CANCEL: - LocalScene_Printf( "%s : PauseThink canceling playback\n", STRING( m_iszSceneFile ) ); - CancelPlayback(); - break; - default: - ResumePlayback(); - break; - } - - // Reset - m_bAutomated = false; - m_nAutomatedAction = SCENE_ACTION_UNKNOWN; - m_flAutomationTime = 0.0f; - m_flAutomationDelay = 0.0f; - m_bPausedViaInput = false; - } - return; - } - - // Otherwise, see if resume/cancel is automatic and act accordingly if enough time - // has passed - m_flAutomationTime += (gpGlobals->frametime); - - if ( m_flAutomationDelay > 0.0f && - m_flAutomationTime < m_flAutomationDelay ) - return; - - // Perform action - switch ( m_nAutomatedAction ) - { - case SCENE_ACTION_RESUME: - LocalScene_Printf( "%s : Automatically resuming playback\n", STRING( m_iszSceneFile ) ); - ResumePlayback(); - break; - case SCENE_ACTION_CANCEL: - LocalScene_Printf( "%s : Automatically canceling playback\n", STRING( m_iszSceneFile ) ); - CancelPlayback(); - break; - default: - LocalScene_Printf( "%s : Unknown action %i, automatically resuming playback\n", STRING( m_iszSceneFile ), m_nAutomatedAction ); - ResumePlayback(); - break; - } - - // Reset - m_bAutomated = false; - m_nAutomatedAction = SCENE_ACTION_UNKNOWN; - m_flAutomationTime = 0.0f; - m_flAutomationDelay = 0.0f; - m_bPausedViaInput = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSceneEntity::DispatchPauseScene( CChoreoScene *scene, const char *parameters ) -{ - // Don't pause during restore, since we'll be restoring the pause state already - if ( m_bRestoring ) - return; - - // FIXME: Hook this up to AI, etc. somehow, perhaps poll each actor for conditions using - // scene resume condition iterator - PausePlayback(); - - char token[1024]; - - m_bPausedViaInput = false; - m_bAutomated = false; - m_nAutomatedAction = SCENE_ACTION_UNKNOWN; - m_flAutomationDelay = 0.0f; - m_flAutomationTime = 0.0f; - - // Check for auto resume/cancel - const char *buffer = parameters; - buffer = engine->ParseFile( buffer, token, sizeof( token ) ); - if ( !stricmp( token, "automate" ) ) - { - buffer = engine->ParseFile( buffer, token, sizeof( token ) ); - if ( !stricmp( token, "Cancel" ) ) - { - m_nAutomatedAction = SCENE_ACTION_CANCEL; - } - else if ( !stricmp( token, "Resume" ) ) - { - m_nAutomatedAction = SCENE_ACTION_RESUME; - } - - if ( m_nAutomatedAction != SCENE_ACTION_UNKNOWN ) - { - buffer = engine->ParseFile( buffer, token, sizeof( token ) ); - m_flAutomationDelay = (float)atof( token ); - - if ( m_flAutomationDelay > 0.0f ) - { - // Success - m_bAutomated = true; - m_flAutomationTime = 0.0f; - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *scene - -// *event - -//----------------------------------------------------------------------------- -void CSceneEntity::DispatchProcessLoop( CChoreoScene *scene, CChoreoEvent *event ) -{ - // Don't restore this event since it's implied in the current "state" of the scene timer, etc. - if ( m_bRestoring ) - return; - - Assert( scene ); - Assert( event->GetType() == CChoreoEvent::LOOP ); - - float backtime = (float)atof( event->GetParameters() ); - - bool process = true; - int counter = event->GetLoopCount(); - if ( counter != -1 ) - { - int remaining = event->GetNumLoopsRemaining(); - if ( remaining <= 0 ) - { - process = false; - } - else - { - event->SetNumLoopsRemaining( --remaining ); - } - } - - if ( !process ) - return; - - scene->LoopToTime( backtime ); - SetCurrentTime( backtime, true ); -} - -//----------------------------------------------------------------------------- -// Purpose: Flag the scene as already "completed" -// Input : *scene - -// *parameters - -//----------------------------------------------------------------------------- -void CSceneEntity::DispatchStopPoint( CChoreoScene *scene, const char *parameters ) -{ - if ( m_bCompletedEarly ) - { - Assert( 0 ); - Warning( "Scene '%s' with two stop point events!\n", STRING( m_iszSceneFile ) ); - return; - } - // Fire completion trigger early - m_bCompletedEarly = true; - m_OnCompletion.FireOutput( this, this, 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CSceneEntity::IsInterruptable() -{ - return ( m_nInterruptCount > 0 ) ? true : false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *scene - -// *actor - -// *event - -//----------------------------------------------------------------------------- -void CSceneEntity::DispatchStartInterrupt( CChoreoScene *scene, CChoreoEvent *event ) -{ - // Don't re-interrupt during restore - if ( m_bRestoring ) - return; - - // If we're supposed to cancel at our next interrupt point, cancel now - if ( m_bCancelAtNextInterrupt ) - { - m_bCancelAtNextInterrupt = false; - LocalScene_Printf( "%s : cancelled via interrupt\n", STRING( m_iszSceneFile ) ); - CancelPlayback(); - return; - } - - ++m_nInterruptCount; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *scene - -// *actor - -// *event - -//----------------------------------------------------------------------------- -void CSceneEntity::DispatchEndInterrupt( CChoreoScene *scene, CChoreoEvent *event ) -{ - // Don't re-interrupt during restore - if ( m_bRestoring ) - return; - - --m_nInterruptCount; - - if ( m_nInterruptCount < 0 ) - { - m_nInterruptCount = 0; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -// *event - -//----------------------------------------------------------------------------- -void CSceneEntity::DispatchStartExpression( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ) -{ - actor->AddSceneEvent( scene, event ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -// *event - -//----------------------------------------------------------------------------- -void CSceneEntity::DispatchEndExpression( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ) -{ - actor->RemoveSceneEvent( scene, event, false ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -// *event - -//----------------------------------------------------------------------------- -void CSceneEntity::DispatchStartFlexAnimation( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ) -{ - actor->AddSceneEvent( scene, event ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -// *event - -//----------------------------------------------------------------------------- -void CSceneEntity::DispatchEndFlexAnimation( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ) -{ - actor->RemoveSceneEvent( scene, event, false ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -// *parameters - -//----------------------------------------------------------------------------- -void CSceneEntity::DispatchStartGesture( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ) -{ - // Ingore null gestures - if ( !Q_stricmp( event->GetName(), "NULL" ) ) - return; - - actor->AddSceneEvent( scene, event); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -// *parameters - -//----------------------------------------------------------------------------- -void CSceneEntity::DispatchEndGesture( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ) -{ - // Ingore null gestures - if ( !Q_stricmp( event->GetName(), "NULL" ) ) - return; - - actor->RemoveSceneEvent( scene, event, m_bRestoring ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -// *parameters - -//----------------------------------------------------------------------------- -void CSceneEntity::DispatchStartGeneric( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ) -{ - CBaseEntity *pTarget = FindNamedEntity( event->GetParameters2( ) ); - actor->AddSceneEvent( scene, event, pTarget ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -// *parameters - -//----------------------------------------------------------------------------- -void CSceneEntity::DispatchEndGeneric( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ) -{ - actor->RemoveSceneEvent( scene, event, m_bRestoring ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -// *actor2 - -//----------------------------------------------------------------------------- -void CSceneEntity::DispatchStartLookAt( CChoreoScene *scene, CBaseFlex *actor, CBaseEntity *actor2, CChoreoEvent *event ) -{ - actor->AddSceneEvent( scene, event, actor2 ); -} - - -void CSceneEntity::DispatchEndLookAt( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ) -{ - actor->RemoveSceneEvent( scene, event, m_bRestoring ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Move to spot/actor -// FIXME: Need to allow this to take arbitrary amount of time and pause playback -// while waiting for actor to move into position -// Input : *actor - -// *parameters - -//----------------------------------------------------------------------------- -void CSceneEntity::DispatchStartMoveTo( CChoreoScene *scene, CBaseFlex *actor, CBaseEntity *actor2, CChoreoEvent *event ) -{ - actor->AddSceneEvent( scene, event, actor2 ); -} - - -void CSceneEntity::DispatchEndMoveTo( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ) -{ - actor->RemoveSceneEvent( scene, event, m_bRestoring ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *token - -// listener - -// soundorigins - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool AttenuateCaption( const char *token, const Vector& listener, CUtlVector< Vector >& soundorigins ) -{ - if ( scene_maxcaptionradius.GetFloat() <= 0.0f ) - { - return false; - } - - int c = soundorigins.Count(); - - if ( c <= 0 ) - { - return false; - } - - float maxdistSqr = scene_maxcaptionradius.GetFloat() * scene_maxcaptionradius.GetFloat(); - - for ( int i = 0; i < c; ++i ) - { - const Vector& org = soundorigins[ i ]; - - float distSqr = ( org - listener ).LengthSqr(); - if ( distSqr <= maxdistSqr ) - { - return false; - } - } - - // All sound sources too far, don't show caption... - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *event - which event -// player - which recipient -// buf, buflen: where to put the data -// Output : Returns true if the sound should be played/prefetched -//----------------------------------------------------------------------------- -bool CSceneEntity::GetSoundNameForPlayer( CChoreoEvent *event, CBasePlayer *player, char *buf, size_t buflen ) -{ - Assert( event ); - Assert( player ); - Assert( buf ); - Assert( buflen > 0 ); - - bool ismasterevent = true; - char tok[ CChoreoEvent::MAX_CCTOKEN_STRING ]; - bool validtoken = false; - - tok[ 0 ] = 0; - - if ( event->GetCloseCaptionType() == CChoreoEvent::CC_SLAVE || - event->GetCloseCaptionType() == CChoreoEvent::CC_DISABLED ) - { - ismasterevent = false; - } - else - { - validtoken = event->GetPlaybackCloseCaptionToken( tok, sizeof( tok ) ); - } - - // For english users, assume we emit the sound normally - Q_strncpy( buf, event->GetParameters(), buflen ); - - bool usingEnglish = true; - if ( !IsXbox() ) - { - char const *cvarvalue = engine->GetClientConVarValue( player->entindex(), "english" ); - if ( cvarvalue && *cvarvalue && Q_atoi( cvarvalue ) != 1 ) - { - usingEnglish = false; - } - - } - - // This makes it like they are running in another language - if ( scene_forcecombined.GetBool() ) - { - usingEnglish = false; - } - - if ( usingEnglish ) - { - // English sounds always play - return true; - } - - if ( ismasterevent ) - { - // Master event sounds always play too (master will be the combined .wav) - if ( validtoken ) - { - Q_strncpy( buf, tok, buflen ); - } - return true; - } - - // Slave events don't play any sound... - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Playback sound file that contains phonemes -// Input : *actor - -// *parameters - -//----------------------------------------------------------------------------- -void CSceneEntity::DispatchStartSpeak( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event, soundlevel_t iSoundlevel ) -{ - // Emit sound - if ( actor ) - { - CPASAttenuationFilter filter( actor ); - - if ( m_pRecipientFilter ) - { - int filterCount = filter.GetRecipientCount(); - int recipientPlayerCount = m_pRecipientFilter->GetRecipientCount(); - for ( int i = filterCount-1; i >= 0; --i ) - { - int playerindex = filter.GetRecipientIndex( i ); - - bool bFound = false; - - for ( int j = 0; j < recipientPlayerCount; ++j ) - { - if ( m_pRecipientFilter->GetRecipientIndex(j) == playerindex ) - { - bFound = true; - break; - } - } - - if ( !bFound ) - { - filter.RemoveRecipientByPlayerIndex( playerindex ); - } - } - } - - float time_in_past = m_flCurrentTime - event->GetStartTime() ; - - float soundtime = gpGlobals->curtime - time_in_past; - - if ( m_bRestoring ) - { - // Need to queue sounds on restore because the player has not yet connected - GetSceneManager()->QueueRestoredSound( actor, event->GetParameters(), iSoundlevel, time_in_past ); - - return; - } - - // Add padding to prevent any other talker talking right after I'm done, because I might - // be continuing speaking with another scene. - float flDuration = event->GetDuration() - time_in_past; - - CAI_BaseActor *pBaseActor = dynamic_cast(actor); - if ( pBaseActor ) - { - pBaseActor->NoteSpeaking( flDuration, GetPostSpeakDelay() ); - } - else if ( actor->IsNPC() ) - { - GetSpeechSemaphore( actor->MyNPCPointer() )->Acquire( flDuration + GetPostSpeakDelay(), actor ); - } - - EmitSound_t es; - es.m_nChannel = CHAN_VOICE; - es.m_flVolume = 1; - es.m_SoundLevel = iSoundlevel; - // Only specify exact delay in single player - es.m_flSoundTime = ( gpGlobals->maxClients == 1 ) ? soundtime : 0.0f; - if ( scene->ShouldIgnorePhonemes() ) - { - es.m_nFlags |= SND_IGNORE_PHONEMES; - } - - // No CC since we do it manually - // FIXME: This will change - es.m_bEmitCloseCaption = false; - - int c = filter.GetRecipientCount(); - for ( int i = 0; i < c; ++i ) - { - int playerindex = filter.GetRecipientIndex( i ); - CBasePlayer *player = UTIL_PlayerByIndex( playerindex ); - if ( !player ) - continue; - - CSingleUserRecipientFilter filter2( player ); - - char soundname[ 512 ]; - if ( !GetSoundNameForPlayer( event, player, soundname, sizeof( soundname ) ) ) - { - continue; - } - - es.m_pSoundName = soundname; - - // keep track of the last few sounds played for bug reports - speechListSounds[ speechListIndex ].time = gpGlobals->curtime; - Q_strncpy( speechListSounds[ speechListIndex ].name, soundname, sizeof( speechListSounds[ 0 ].name ) ); - Q_strncpy( speechListSounds[ speechListIndex ].sceneName, ( scene ) ? scene->GetFilename() : "", sizeof( speechListSounds[ 0 ].sceneName ) ); - - speechListIndex++; - if ( speechListIndex >= SPEECH_LIST_MAX_SOUNDS ) - { - speechListIndex = 0; - } - - // Warning( "Speak %s\n", soundname ); - - if ( m_fPitch != 1.0f ) - { - if ( es.m_nPitch ) - es.m_nPitch = static_cast(es.m_nPitch * m_fPitch); - else - es.m_nPitch = static_cast(100.0f * m_fPitch); - - es.m_nFlags |= SND_CHANGE_PITCH; - } - - EmitSound( filter2, actor->entindex(), es ); - actor->AddSceneEvent( scene, event ); - } - - // Close captioning only on master token no matter what... - if ( event->GetCloseCaptionType() == CChoreoEvent::CC_MASTER ) - { - char tok[ CChoreoEvent::MAX_CCTOKEN_STRING ]; - bool validtoken = event->GetPlaybackCloseCaptionToken( tok, sizeof( tok ) ); - if ( validtoken ) - { - char lowercase[ 256 ]; - Q_strncpy( lowercase, tok, sizeof( lowercase ) ); - Q_strlower( lowercase ); - - // Remove any players who don't want close captions - CBaseEntity::RemoveRecipientsIfNotCloseCaptioning( filter ); - - // Certain events are marked "don't attenuate", (breencast), skip those here - if ( !event->IsSuppressingCaptionAttenuation() && - ( filter.GetRecipientCount() > 0 ) ) - { - int c = filter.GetRecipientCount(); - for ( int i = c - 1 ; i >= 0; --i ) - { - CBasePlayer *player = UTIL_PlayerByIndex( filter.GetRecipientIndex( i ) ); - if ( !player ) - continue; - - Vector playerOrigin = player->GetAbsOrigin(); - - if ( AttenuateCaption( lowercase, playerOrigin, es.m_UtlVecSoundOrigin ) ) - { - // If the player has a view entity, measure the distance to that - if ( !player->GetViewEntity() || AttenuateCaption( lowercase, player->GetViewEntity()->GetAbsOrigin(), es.m_UtlVecSoundOrigin ) ) - { - filter.RemoveRecipient( player ); - } - } - } - } - - // Anyone left? - if ( filter.GetRecipientCount() > 0 ) - { - float endtime = event->GetLastSlaveEndTime(); - float durationShort = event->GetDuration(); - float durationLong = endtime - event->GetStartTime(); - - float duration = MAX( durationShort, durationLong ); - - - byte byteflags = CLOSE_CAPTION_WARNIFMISSING; // warnifmissing - /* - // Never for .vcds... - if ( fromplayer ) - { - byteflags |= CLOSE_CAPTION_FROMPLAYER; - } - */ - char const *pszActorModel = STRING( actor->GetModelName() ); - gender_t gender = soundemitterbase->GetActorGender( pszActorModel ); - - if ( gender == GENDER_MALE ) - { - byteflags |= CLOSE_CAPTION_GENDER_MALE; - } - else if ( gender == GENDER_FEMALE ) - { - byteflags |= CLOSE_CAPTION_GENDER_FEMALE; - } - - // Send caption and duration hint down to client - UserMessageBegin( filter, "CloseCaption" ); - WRITE_STRING( lowercase ); - WRITE_SHORT( MIN( 255, (int)( duration * 10.0f ) ) ); - WRITE_BYTE( byteflags ); // warn on missing - MessageEnd(); - } - } - } - } -} - -void CSceneEntity::DispatchEndSpeak( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ) -{ - actor->RemoveSceneEvent( scene, event, m_bRestoring ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -// *actor2 - -//----------------------------------------------------------------------------- -void CSceneEntity::DispatchStartFace( CChoreoScene *scene, CBaseFlex *actor, CBaseEntity *actor2, CChoreoEvent *event ) -{ - actor->AddSceneEvent( scene, event, actor2 ); -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -// *actor2 - -//----------------------------------------------------------------------------- -void CSceneEntity::DispatchEndFace( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ) -{ - actor->RemoveSceneEvent( scene, event, m_bRestoring ); -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -//----------------------------------------------------------------------------- -void CSceneEntity::DispatchStartSequence( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ) -{ - actor->AddSceneEvent( scene, event ); -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -//----------------------------------------------------------------------------- -void CSceneEntity::DispatchEndSequence( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ) -{ - actor->RemoveSceneEvent( scene, event, m_bRestoring ); -} - -//----------------------------------------------------------------------------- -// Purpose: NPC can play interstitial vcds (such as responding to the player doing something during a scene) -// Input : *scene - -// *actor - -// *event - -//----------------------------------------------------------------------------- -void CSceneEntity::DispatchStartPermitResponses( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ) -{ - actor->SetPermitResponse( gpGlobals->curtime + event->GetDuration() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *scene - -// *actor - -// *event - -//----------------------------------------------------------------------------- -void CSceneEntity::DispatchEndPermitResponses( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ) -{ - actor->SetPermitResponse( 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CSceneEntity::EstimateLength( void ) -{ - if ( !m_pScene ) - { - return GetSceneDuration( STRING( m_iszSceneFile ) ); - } - return m_pScene->FindStopTime(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// NOTE: returns false if scene hasn't loaded yet -//----------------------------------------------------------------------------- -void CSceneEntity::CancelIfSceneInvolvesActor( CBaseEntity *pActor ) -{ - if ( InvolvesActor( pActor ) ) - { - LocalScene_Printf( "%s : cancelled for '%s'\n", STRING( m_iszSceneFile ), pActor->GetDebugName() ); - CancelPlayback(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// NOTE: returns false if scene hasn't loaded yet -//----------------------------------------------------------------------------- -bool CSceneEntity::InvolvesActor( CBaseEntity *pActor ) -{ - if ( !m_pScene ) - return false; - - int i; - for ( i = 0 ; i < m_pScene->GetNumActors(); i++ ) - { - CBaseFlex *pTestActor = FindNamedActor( i ); - if ( !pTestActor ) - continue; - - if ( pTestActor == pActor ) - return true; - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSceneEntity::DoThink( float frametime ) -{ - CheckInterruptCompletion(); - - if ( m_bWaitingForActor || m_bWaitingForInterrupt ) - { - // Try to start playback. - StartPlayback(); - } - - if ( !m_pScene ) - return; - - if ( !m_bIsPlayingBack ) - return; - - // catch bad pitch shifting from old save games - Assert( m_fPitch >= SCENE_MIN_PITCH && m_fPitch <= SCENE_MAX_PITCH ); - m_fPitch = clamp( m_fPitch, SCENE_MIN_PITCH, SCENE_MAX_PITCH ); - - if ( m_bPaused ) - { - PauseThink(); - return; - } - - // Msg("%.2f %s\n", gpGlobals->curtime, STRING( m_iszSceneFile ) ); - - //Msg( "SV: %d, %f for %s\n", gpGlobals->tickcount, m_flCurrentTime, m_pScene->GetFilename() ); - - m_flFrameTime = frametime; - - m_pScene->SetSoundFileStartupLatency( GetSoundSystemLatency() ); - - // Tell scene to go - m_pScene->Think( m_flCurrentTime ); - - // Did we get to the end - if ( !m_bPaused ) - { - // Drive simulation time for scene - SetCurrentTime( m_flCurrentTime + m_flFrameTime * m_fPitch, false ); - - if ( m_pScene->SimulationFinished() ) - { - OnSceneFinished( false, true ); - - // Stop them from doing anything special - ClearSchedules( m_pScene ); - } - } - else - { - // Drive simulation time for scene - SetCurrentTime( m_pScene->GetTime(), true ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Input handlers -//----------------------------------------------------------------------------- -void CSceneEntity::InputStartPlayback( inputdata_t &inputdata ) -{ - // Already playing, ignore - if ( m_bIsPlayingBack ) - return; - - // Already waiting on someone. - if ( m_bWaitingForActor || m_bWaitingForInterrupt ) - return; - - ClearActivatorTargets(); - m_hActivator = inputdata.pActivator; - StartPlayback(); -} - -void CSceneEntity::InputPausePlayback( inputdata_t &inputdata ) -{ - PausePlayback(); - m_bPausedViaInput = true; -} - -void CSceneEntity::InputResumePlayback( inputdata_t &inputdata ) -{ - ResumePlayback(); -} - -void CSceneEntity::InputCancelPlayback( inputdata_t &inputdata ) -{ - LocalScene_Printf( "%s : cancelled via input\n", STRING( m_iszSceneFile ) ); - CancelPlayback(); -} - -void CSceneEntity::InputScriptPlayerDeath( inputdata_t &inputdata ) -{ - if ( m_iPlayerDeathBehavior == SCRIPT_CANCEL ) - { - LocalScene_Printf( "%s : cancelled via player death\n", STRING( m_iszSceneFile ) ); - CancelPlayback(); - } -} - - -void CSceneEntity::InputCancelAtNextInterrupt( inputdata_t &inputdata ) -{ - // If we're currently in an interruptable point, interrupt immediately - if ( IsInterruptable() ) - { - LocalScene_Printf( "%s : cancelled via input at interrupt point\n", STRING( m_iszSceneFile ) ); - CancelPlayback(); - return; - } - - // Otherwise, cancel when we next hit an interrupt point - m_bCancelAtNextInterrupt = true; -} - -void CSceneEntity::InputPitchShiftPlayback( inputdata_t &inputdata ) -{ - PitchShiftPlayback( inputdata.value.Float() ); -} - -void CSceneEntity::InputTriggerEvent( inputdata_t &inputdata ) -{ - CBaseEntity *pActivator = this; // at some point, find this from the inputdata - switch ( inputdata.value.Int() ) - { - case 1: - m_OnTrigger1.FireOutput( pActivator, this, 0 ); - break; - case 2: - m_OnTrigger2.FireOutput( pActivator, this, 0 ); - break; - case 3: - m_OnTrigger3.FireOutput( pActivator, this, 0 ); - break; - case 4: - m_OnTrigger4.FireOutput( pActivator, this, 0 ); - break; - case 5: - m_OnTrigger5.FireOutput( pActivator, this, 0 ); - break; - case 6: - m_OnTrigger6.FireOutput( pActivator, this, 0 ); - break; - case 7: - m_OnTrigger7.FireOutput( pActivator, this, 0 ); - break; - case 8: - m_OnTrigger8.FireOutput( pActivator, this, 0 ); - break; - case 9: - m_OnTrigger9.FireOutput( pActivator, this, 0 ); - break; - case 10: - m_OnTrigger10.FireOutput( pActivator, this, 0 ); - break; - case 11: - m_OnTrigger11.FireOutput( pActivator, this, 0 ); - break; - case 12: - m_OnTrigger12.FireOutput( pActivator, this, 0 ); - break; - case 13: - m_OnTrigger13.FireOutput( pActivator, this, 0 ); - break; - case 14: - m_OnTrigger14.FireOutput( pActivator, this, 0 ); - break; - case 15: - m_OnTrigger15.FireOutput( pActivator, this, 0 ); - break; - case 16: - m_OnTrigger16.FireOutput( pActivator, this, 0 ); - break; - } -} - -struct NPCInterjection -{ - AI_Response *response; - CAI_BaseActor *npc; -}; -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CSceneEntity::InputInterjectResponse( inputdata_t &inputdata ) -{ - // Not currently playing a scene - if ( !m_pScene ) - { - return; - } - - CUtlVector< CAI_BaseActor * > candidates; - int i; - for ( i = 0 ; i < m_pScene->GetNumActors(); i++ ) - { - CBaseFlex *pTestActor = FindNamedActor( i ); - if ( !pTestActor ) - continue; - - CAI_BaseActor *pBaseActor = dynamic_cast(pTestActor); - if ( !pBaseActor ) - continue; - - if ( !pBaseActor->IsAlive() ) - continue; - - candidates.AddToTail( pBaseActor ); - } - - int c = candidates.Count(); - - if ( !c ) - { - return; - } - - int useIndex = 0; - if ( !m_bIsPlayingBack ) - { - // Use any actor if not playing a scene - useIndex = RandomInt( 0, c - 1 ); - } - else - { - CUtlVector< NPCInterjection > validResponses; - - char modifiers[ 512 ]; - Q_snprintf( modifiers, sizeof( modifiers ), "scene:%s", STRING( GetEntityName() ) ); - - for ( int i = 0; i < c; i++ ) - { - CAI_BaseActor *npc = candidates[ i ]; - Assert( npc ); - - AI_Response *response = npc->SpeakFindResponse( inputdata.value.String(), modifiers ); - if ( !response ) - continue; - - float duration = npc->GetResponseDuration( response ); - // Couldn't look it up - if ( duration <= 0.0f ) - continue; - - if ( !npc->PermitResponse( duration ) ) - { - delete response; - continue; - } - - // - NPCInterjection inter; - inter.response = response; - inter.npc = npc; - - validResponses.AddToTail( inter ); - } - - int rcount = validResponses.Count(); - if ( rcount >= 1 ) - { - int slot = RandomInt( 0, rcount - 1 ); - - for ( int i = 0; i < rcount; i++ ) - { - NPCInterjection *pInterjection = &validResponses[ i ]; - if ( i == slot ) - { - pInterjection->npc->SpeakDispatchResponse( inputdata.value.String(), pInterjection->response ); - } - else - { - delete pInterjection->response; - } - } - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CSceneEntity::InputStopWaitingForActor( inputdata_t &inputdata ) -{ - if( m_bIsPlayingBack ) - { - // Already started. - return; - } - - m_bWaitingForActor = false; -} - -bool CSceneEntity::CheckActors() -{ - Assert( m_pScene ); - if ( !m_pScene ) - return false; - - int i; - for ( i = 0 ; i < m_pScene->GetNumActors(); i++ ) - { - CBaseFlex *pTestActor = FindNamedActor( i ); - if ( !pTestActor ) - continue; - - if ( !pTestActor->MyCombatCharacterPointer() ) - continue; - - if ( !pTestActor->MyCombatCharacterPointer()->IsAlive() ) - return false; - - if ( m_BusyActor == SCENE_BUSYACTOR_WAIT ) - { - CAI_BaseNPC *pActor = pTestActor->MyNPCPointer(); - - if ( pActor ) - { - bool bShouldWait = false; - if ( hl2_episodic.GetBool() ) - { - // Episodic waits until the NPC is fully finished with any .vcd with speech in it - if ( IsRunningScriptedSceneWithSpeech( pActor ) ) - { - bShouldWait = true; - } - -#ifdef HL2_EPISODIC - // HACK: Alyx cannot play scenes when she's in the middle of transitioning - if ( pActor->IsInAVehicle() ) - { - CNPC_Alyx *pAlyx = dynamic_cast(pActor); - if ( pAlyx != NULL && ( pAlyx->GetPassengerState() == PASSENGER_STATE_ENTERING || pAlyx->GetPassengerState() == PASSENGER_STATE_EXITING ) ) - { - bShouldWait = true; - } - } -#endif // HL2_EPISODIC - } - - if ( pActor->GetExpresser() && pActor->GetExpresser()->IsSpeaking() ) - { - bShouldWait = true; - } - - if ( bShouldWait ) - { - // One of the actors for this scene is talking already. - // Try again next think. - m_bWaitingForActor = true; - return false; - } - } - } - else if ( m_BusyActor == SCENE_BUSYACTOR_INTERRUPT || m_BusyActor == SCENE_BUSYACTOR_INTERRUPT_CANCEL ) - { - CBaseCombatCharacter *pActor = pTestActor->MyCombatCharacterPointer(); - if ( pActor && !IsInInterruptableScenes( pActor ) ) - { - // One of the actors is in a scene that's not at an interrupt point. - // Wait until the scene finishes or an interrupt point is reached. - m_bWaitingForInterrupt = true; - return false; - } - - if ( m_BusyActor == SCENE_BUSYACTOR_INTERRUPT_CANCEL ) - { - // Cancel existing scenes - RemoveActorFromScriptedScenes( pActor, false ); - } - else - { - // Pause existing scenes - PauseActorsScriptedScenes( pActor, false ); - m_bInterruptedActorsScenes = true; - } - } - - pTestActor->StartChoreoScene( m_pScene ); - } - - return true; -} - -#if !defined( _RETAIL ) -static ConVar scene_async_prefetch_spew( "scene_async_prefetch_spew", "0", 0, "Display async .ani file loading info." ); -#endif - -void CSceneEntity::PrefetchAnimBlocks( CChoreoScene *scene ) -{ - Assert( scene ); - - // Build a fast lookup, too - CUtlMap< CChoreoActor *, CBaseFlex *> actorMap( 0, 0, DefLessFunc( CChoreoActor * ) ); - - int spew = -#if !defined( _RETAIL ) - scene_async_prefetch_spew.GetInt(); -#else - 0; -#endif - - int resident = 0; - int checked = 0; - - // Iterate events and precache necessary resources - for ( int i = 0; i < scene->GetNumEvents(); i++ ) - { - CChoreoEvent *event = scene->GetEvent( i ); - if ( !event ) - continue; - - // load any necessary data - switch ( event->GetType() ) - { - default: - break; - case CChoreoEvent::SEQUENCE: - case CChoreoEvent::GESTURE: - { - CChoreoActor *actor = event->GetActor(); - if ( actor ) - { - CBaseFlex *pActor = NULL; - int idx = actorMap.Find( actor ); - if ( idx == actorMap.InvalidIndex() ) - { - pActor = FindNamedActor( actor ); - idx = actorMap.Insert( actor, pActor ); - } - else - { - pActor = actorMap[ idx ]; - } - - if ( pActor ) - { - int seq = pActor->LookupSequence( event->GetParameters() ); - if ( seq >= 0 ) - { - CStudioHdr *pStudioHdr = pActor->GetModelPtr(); - if ( pStudioHdr ) - { - // Now look up the animblock - mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( seq ); - for ( int i = 0 ; i < seqdesc.groupsize[ 0 ] ; ++i ) - { - for ( int j = 0; j < seqdesc.groupsize[ 1 ]; ++j ) - { - int animation = seqdesc.anim( i, j ); - int baseanimation = pStudioHdr->iRelativeAnim( seq, animation ); - mstudioanimdesc_t &animdesc = pStudioHdr->pAnimdesc( baseanimation ); - - ++checked; - - if ( spew != 0 ) - { - Msg( "%s checking block %d\n", pStudioHdr->pszName(), animdesc.animblock ); - } - - // Async load the animation - int iFrame = 0; - const mstudioanim_t *panim = animdesc.pAnim( &iFrame ); - if ( panim ) - { - ++resident; - if ( spew > 1 ) - { - Msg( "%s:%s[%i:%i] was resident\n", pStudioHdr->pszName(), animdesc.pszName(), i, j ); - } - } - else - { - if ( spew != 0 ) - { - Msg( "%s:%s[%i:%i] async load\n", pStudioHdr->pszName(), animdesc.pszName(), i, j ); - } - } - } - } - } - } - } - } - } - break; - } - } - - if ( !spew || checked <= 0 ) - return; - - Msg( "%d of %d animations resident\n", resident, checked ); -} - -void CSceneEntity::OnLoaded() -{ - // Nothing -} - -//----------------------------------------------------------------------------- -// Purpose: Initiate scene playback -//----------------------------------------------------------------------------- -void CSceneEntity::StartPlayback( void ) -{ - if ( !m_pScene ) - { - if ( m_bSceneMissing ) - return; - - m_pScene = LoadScene( STRING( m_iszSceneFile ), this ); - if ( !m_pScene ) - { - DevMsg( "%s missing from scenes.image\n", STRING( m_iszSceneFile ) ); - m_bSceneMissing = true; - return; - } - - OnLoaded(); - - if ( ShouldNetwork() ) - { - m_nSceneStringIndex = g_pStringTableClientSideChoreoScenes->AddString( CBaseEntity::IsServer(), STRING( m_iszSceneFile ) ); - } - - UpdateTransmitState(); - } - - if ( m_bIsPlayingBack ) - return; - - // Make sure actors are alive and able to handle this scene now, otherwise - // we'll wait for them to show up - if ( !CheckActors() ) - { - return; - } - - m_bCompletedEarly = false; - m_bWaitingForActor = false; - m_bWaitingForInterrupt = false; - m_bIsPlayingBack = true; - NetworkProp()->NetworkStateForceUpdate(); - m_bPaused = false; - SetCurrentTime( 0.0f, true ); - m_pScene->ResetSimulation(); - ClearInterrupt(); - - // Put face back in neutral pose - ClearSceneEvents( m_pScene, false ); - - m_OnStart.FireOutput( this, this, 0 ); - - // Aysnchronously load speak sounds - CUtlSymbolTable prefetchSoundSymbolTable; - CUtlRBTree< SpeakEventSound_t > soundnames( 0, 0, SpeakEventSoundLessFunc ); - - BuildSortedSpeakEventSoundsPrefetchList( m_pScene, prefetchSoundSymbolTable, soundnames, 0.0f ); - PrefetchSpeakEventSounds( prefetchSoundSymbolTable, soundnames ); - - // Tell any managers we're within that we've started - int c = m_hListManagers.Count(); - for ( int i = 0; i < c; i++ ) - { - if ( m_hListManagers[i] ) - { - m_hListManagers[i]->SceneStarted( this ); - } - } - - PrefetchAnimBlocks( m_pScene ); -} - -//----------------------------------------------------------------------------- -// Purpose: Static method used to sort by event start time -//----------------------------------------------------------------------------- -bool CSceneEntity::SpeakEventSoundLessFunc( const SpeakEventSound_t& lhs, const SpeakEventSound_t& rhs ) -{ - return lhs.m_flStartTime < rhs.m_flStartTime; -} - -//----------------------------------------------------------------------------- -// Purpose: Prefetches the list of sounds build by BuildSortedSpeakEventSoundsPrefetchList -//----------------------------------------------------------------------------- -void CSceneEntity::PrefetchSpeakEventSounds( CUtlSymbolTable& table, CUtlRBTree< SpeakEventSound_t >& soundnames ) -{ - for ( int i = soundnames.FirstInorder(); i != soundnames.InvalidIndex() ; i = soundnames.NextInorder( i ) ) - { - SpeakEventSound_t& sound = soundnames[ i ]; - // Look it up in the string table - char const *soundname = table.String( sound.m_Symbol ); - - // Warning( "Prefetch %s\n", soundname ); - - PrefetchScriptSound( soundname ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Builds list of sounds sorted by start time for prefetching -//----------------------------------------------------------------------------- -void CSceneEntity::BuildSortedSpeakEventSoundsPrefetchList( - CChoreoScene *scene, - CUtlSymbolTable& table, - CUtlRBTree< SpeakEventSound_t >& soundnames, - float timeOffset ) -{ - Assert( scene ); - - // Iterate events and precache necessary resources - for ( int i = 0; i < scene->GetNumEvents(); i++ ) - { - CChoreoEvent *event = scene->GetEvent( i ); - if ( !event ) - continue; - - // load any necessary data - switch (event->GetType() ) - { - default: - break; - case CChoreoEvent::SPEAK: - { - - // NOTE: The script entries associated with .vcds are forced to preload to avoid - // loading hitches during triggering - char soundname[ CChoreoEvent::MAX_CCTOKEN_STRING ]; - Q_strncpy( soundname, event->GetParameters(), sizeof( soundname ) ); - - if ( event->GetCloseCaptionType() == CChoreoEvent::CC_MASTER ) - { - event->GetPlaybackCloseCaptionToken( soundname, sizeof( soundname ) ); - } - - // In single player, try to use the combined or regular .wav files as needed - if ( gpGlobals->maxClients == 1 ) - { - CBasePlayer *player = UTIL_GetLocalPlayer(); - if ( player && !GetSoundNameForPlayer( event, player, soundname, sizeof( soundname ) ) ) - { - // Skip to next event - continue; - } - } - /* - else - { - // UNDONE: Probably need some other solution in multiplayer... (not sure how to "prefetch" on certain players - // with one sound, but not prefetch the same sound for others...) - } - */ - - SpeakEventSound_t ses; - ses.m_Symbol = table.AddString( soundname ); - ses.m_flStartTime = timeOffset + event->GetStartTime(); - - soundnames.Insert( ses ); - } - break; - case CChoreoEvent::SUBSCENE: - { - // Only allow a single level of subscenes for now - if ( !scene->IsSubScene() ) - { - CChoreoScene *subscene = event->GetSubScene(); - if ( !subscene ) - { - subscene = LoadScene( event->GetParameters(), this ); - subscene->SetSubScene( true ); - event->SetSubScene( subscene ); - - // Now precache it's resources, if any - BuildSortedSpeakEventSoundsPrefetchList( subscene, table, soundnames, event->GetStartTime() ); - } - } - } - break; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSceneEntity::PausePlayback( void ) -{ - if ( !m_bIsPlayingBack ) - return; - - if ( m_bPaused ) - return; - - m_bPaused = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSceneEntity::ResumePlayback( void ) -{ - if ( !m_bIsPlayingBack ) - return; - - if ( !m_bPaused ) - return; - - Assert( m_pScene ); - if ( !m_pScene ) - { - // This should never happen!!!! - return; - } - - // FIXME: Iterate using m_pScene->IterateResumeConditionEvents and - // only resume if the event conditions have all been satisfied - - // FIXME: Just resume for now - m_pScene->ResumeSimulation(); - - m_bPaused = false; - m_bPausedViaInput = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSceneEntity::CancelPlayback( void ) -{ - if ( !m_bIsPlayingBack ) - return; - - m_bIsPlayingBack = false; - m_bPaused = false; - - m_OnCanceled.FireOutput( this, this, 0 ); - - LocalScene_Printf( "%s : %8.2f: canceled\n", STRING( m_iszSceneFile ), m_flCurrentTime ); - - OnSceneFinished( true, false ); -} - -void CSceneEntity::PitchShiftPlayback( float fPitch ) -{ - fPitch = clamp( fPitch, SCENE_MIN_PITCH, SCENE_MAX_PITCH ); - - m_fPitch = fPitch; - - if ( !m_pScene ) - return; - - for ( int iActor = 0 ; iActor < m_pScene->GetNumActors(); ++iActor ) - { - CBaseFlex *pTestActor = FindNamedActor( iActor ); - - if ( !pTestActor ) - continue; - - char szBuff[ 256 ]; - - if ( m_pScene->GetPlayingSoundName( szBuff, sizeof( szBuff ) ) ) - { - CPASAttenuationFilter filter( pTestActor ); - EmitSound_t params; - params.m_pSoundName = szBuff; - params.m_nPitch = static_cast(100.0f * fPitch); - params.m_nFlags = SND_CHANGE_PITCH; - pTestActor->EmitSound( filter, pTestActor->entindex(), params ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Start a resume scene, if we have one, and resume playing when it finishes -//----------------------------------------------------------------------------- -void CSceneEntity::QueueResumePlayback( void ) -{ - // Do we have a resume scene? - if ( m_iszResumeSceneFile != NULL_STRING ) - { - bool bStartedScene = false; - - // If it has ".vcd" somewhere in the string, try using it as a scene file first - if ( Q_stristr( STRING(m_iszResumeSceneFile), ".vcd" ) ) - { - bStartedScene = InstancedScriptedScene( NULL, STRING(m_iszResumeSceneFile), &m_hWaitingForThisResumeScene, 0, false ) != 0; - } - - // HACKHACK: For now, get the first target, and see if we can find a response for him - if ( !bStartedScene ) - { - CBaseFlex *pActor = FindNamedActor( 0 ); - if ( pActor ) - { - CAI_BaseActor *pBaseActor = dynamic_cast(pActor); - if ( pBaseActor ) - { - AI_Response *result = pBaseActor->SpeakFindResponse( STRING(m_iszResumeSceneFile), NULL ); - if ( result ) - { - char response[ 256 ]; - result->GetResponse( response, sizeof( response ) ); - bStartedScene = InstancedScriptedScene( NULL, response, &m_hWaitingForThisResumeScene, 0, false ) != 0; - } - } - } - } - - // If we started a scene/response, wait for it to finish - if ( bStartedScene ) - { - m_bWaitingForResumeScene = true; - } - else - { - // Failed to create the scene. Resume immediately. - ResumePlayback(); - } - } - else - { - // No resume scene, so just resume immediately - ResumePlayback(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Query whether the scene actually loaded. Only meaninful after Spawn() -//----------------------------------------------------------------------------- -bool CSceneEntity::ValidScene() const -{ - return ( m_pScene != NULL ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pActor - -// *scene - -// *event - -//----------------------------------------------------------------------------- -void CSceneEntity::DispatchStartSubScene( CChoreoScene *scene, CBaseFlex *pActor, CChoreoEvent *event) -{ - if ( !scene->IsSubScene() ) - { - CChoreoScene *subscene = event->GetSubScene(); - if ( !subscene ) - { - Assert( 0 ); - /* - subscene = LoadScene( event->GetParameters() ); - subscene->SetSubScene( true ); - event->SetSubScene( subscene ); - */ - } - - if ( subscene ) - { - subscene->ResetSimulation(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: All events are leading edge triggered -// Input : currenttime - -// *event - -//----------------------------------------------------------------------------- -void CSceneEntity::StartEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event ) -{ - Assert( event ); - - if ( !Q_stricmp( event->GetName(), "NULL" ) ) - { - LocalScene_Printf( "%s : %8.2f: ignored %s\n", STRING( m_iszSceneFile ), currenttime, event->GetDescription() ); - return; - } - - - CBaseFlex *pActor = NULL; - CChoreoActor *actor = event->GetActor(); - if ( actor ) - { - pActor = FindNamedActor( actor ); - if (pActor == NULL) - { - Warning( "CSceneEntity %s unable to find actor named \"%s\"\n", STRING(GetEntityName()), actor->GetName() ); - return; - } - } - - LocalScene_Printf( "%s : %8.2f: start %s\n", STRING( m_iszSceneFile ), currenttime, event->GetDescription() ); - - switch ( event->GetType() ) - { - case CChoreoEvent::SUBSCENE: - { - if ( pActor && !IsMultiplayer() ) - { - DispatchStartSubScene( scene, pActor, event ); - } - } - break; - case CChoreoEvent::EXPRESSION: - { - if ( pActor && !IsMultiplayer() ) - { - DispatchStartExpression( scene, pActor, event ); - } - } - break; - case CChoreoEvent::FLEXANIMATION: - { - if ( pActor && !IsMultiplayer() ) - { - DispatchStartFlexAnimation( scene, pActor, event ); - } - } - break; - case CChoreoEvent::LOOKAT: - { - if ( pActor && !IsMultiplayer() ) - { - CBaseEntity *pActor2 = FindNamedEntity( event->GetParameters( ), pActor ); - if ( pActor2 ) - { - // Huh? - DispatchStartLookAt( scene, pActor, pActor2, event ); - } - else - { - Warning( "CSceneEntity %s unable to find actor named \"%s\"\n", STRING(GetEntityName()), event->GetParameters() ); - } - } - } - break; - case CChoreoEvent::SPEAK: - { - if ( pActor ) - { - // Speaking is edge triggered - - // FIXME: dB hack. soundlevel needs to be moved into inside of wav? - soundlevel_t iSoundlevel = SNDLVL_TALKING; - if (event->GetParameters2()) - { - iSoundlevel = (soundlevel_t)atoi( event->GetParameters2() ); - if (iSoundlevel == SNDLVL_NONE) - iSoundlevel = SNDLVL_TALKING; - } - - DispatchStartSpeak( scene, pActor, event, iSoundlevel ); - } - } - break; - case CChoreoEvent::MOVETO: - { - // FIXME: make sure moveto's aren't edge triggered - if ( !event->HasEndTime() ) - { - event->SetEndTime( event->GetStartTime() + 1.0 ); - } - - if ( pActor && !IsMultiplayer() ) - { - CBaseEntity *pActor2 = NULL; - if ( event->GetParameters3( ) && strlen( event->GetParameters3( ) ) > 0 ) - { - pActor2 = FindNamedEntityClosest( event->GetParameters( ), pActor, false, true, event->GetParameters3( ) ); - } - else - { - pActor2 = FindNamedEntity( event->GetParameters( ), pActor, false, true ); - } - if ( pActor2 ) - { - - DispatchStartMoveTo( scene, pActor, pActor2, event ); - } - else - { - Warning( "CSceneEntity %s unable to find actor named \"%s\"\n", STRING(GetEntityName()), event->GetParameters() ); - } - } - } - break; - case CChoreoEvent::FACE: - { - if ( pActor && !IsMultiplayer() ) - { - CBaseEntity *pActor2 = FindNamedEntity( event->GetParameters( ), pActor ); - if ( pActor2 ) - { - DispatchStartFace( scene, pActor, pActor2, event ); - } - else - { - Warning( "CSceneEntity %s unable to find actor named \"%s\"\n", STRING(GetEntityName()), event->GetParameters() ); - } - } - } - break; - case CChoreoEvent::GESTURE: - { - if ( pActor ) - { - DispatchStartGesture( scene, pActor, event ); - } - } - break; - case CChoreoEvent::GENERIC: - { - // If the first token in the parameters is "debugtext", print the rest of the text - if ( event->GetParameters() && !Q_strncmp( event->GetParameters(), "debugtext", 9 ) ) - { - const char *pszText = event->GetParameters() + 10; - - hudtextparms_s tTextParam; - tTextParam.x = -1; - tTextParam.y = 0.65; - tTextParam.effect = 0; - tTextParam.r1 = 255; - tTextParam.g1 = 170; - tTextParam.b1 = 0; - tTextParam.a1 = 255; - tTextParam.r2 = 255; - tTextParam.g2 = 170; - tTextParam.b2 = 0; - tTextParam.a2 = 255; - tTextParam.fadeinTime = 0; - tTextParam.fadeoutTime = 0; - tTextParam.holdTime = 3.1; - tTextParam.fxTime = 0; - tTextParam.channel = 1; - UTIL_HudMessageAll( tTextParam, pszText ); - break; - } - - if ( pActor ) - { - DispatchStartGeneric( scene, pActor, event ); - } - } - break; - case CChoreoEvent::FIRETRIGGER: - { - if ( IsMultiplayer() ) - break; - - // Don't re-fire triggers during restore, the entities should already reflect all such state... - if ( m_bRestoring ) - { - break; - } - - CBaseEntity *pActivator = pActor; - if (!pActivator) - { - pActivator = this; - } - - // FIXME: how do I decide who fired it?? - switch( atoi( event->GetParameters() ) ) - { - case 1: - m_OnTrigger1.FireOutput( pActivator, this, 0 ); - break; - case 2: - m_OnTrigger2.FireOutput( pActivator, this, 0 ); - break; - case 3: - m_OnTrigger3.FireOutput( pActivator, this, 0 ); - break; - case 4: - m_OnTrigger4.FireOutput( pActivator, this, 0 ); - break; - case 5: - m_OnTrigger5.FireOutput( pActivator, this, 0 ); - break; - case 6: - m_OnTrigger6.FireOutput( pActivator, this, 0 ); - break; - case 7: - m_OnTrigger7.FireOutput( pActivator, this, 0 ); - break; - case 8: - m_OnTrigger8.FireOutput( pActivator, this, 0 ); - break; - case 9: - m_OnTrigger9.FireOutput( pActivator, this, 0 ); - break; - case 10: - m_OnTrigger10.FireOutput( pActivator, this, 0 ); - break; - case 11: - m_OnTrigger11.FireOutput( pActivator, this, 0 ); - break; - case 12: - m_OnTrigger12.FireOutput( pActivator, this, 0 ); - break; - case 13: - m_OnTrigger13.FireOutput( pActivator, this, 0 ); - break; - case 14: - m_OnTrigger14.FireOutput( pActivator, this, 0 ); - break; - case 15: - m_OnTrigger15.FireOutput( pActivator, this, 0 ); - break; - case 16: - m_OnTrigger16.FireOutput( pActivator, this, 0 ); - break; - } - } - break; - case CChoreoEvent::SEQUENCE: - { - if ( pActor ) - { - DispatchStartSequence( scene, pActor, event ); - } - } - break; - case CChoreoEvent::SECTION: - { - if ( IsMultiplayer() ) - break; - - // Pauses scene playback - DispatchPauseScene( scene, event->GetParameters() ); - } - break; - case CChoreoEvent::LOOP: - { - DispatchProcessLoop( scene, event ); - } - break; - case CChoreoEvent::INTERRUPT: - { - if ( IsMultiplayer() ) - break; - - DispatchStartInterrupt( scene, event ); - } - break; - - case CChoreoEvent::STOPPOINT: - { - if ( IsMultiplayer() ) - break; - - DispatchStopPoint( scene, event->GetParameters() ); - } - break; - - case CChoreoEvent::PERMIT_RESPONSES: - { - if ( IsMultiplayer() ) - break; - - DispatchStartPermitResponses( scene, pActor, event ); - } - break; - default: - { - // FIXME: Unhandeled event - // Assert(0); - } - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : currenttime - -// *event - -//----------------------------------------------------------------------------- -void CSceneEntity::EndEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event ) -{ - Assert( event ); - - if ( !Q_stricmp( event->GetName(), "NULL" ) ) - { - return; - } - - CBaseFlex *pActor = NULL; - CChoreoActor *actor = event->GetActor(); - if ( actor ) - { - pActor = FindNamedActor( actor ); - } - - LocalScene_Printf( "%s : %8.2f: finish %s\n", STRING( m_iszSceneFile ), currenttime, event->GetDescription() ); - - switch ( event->GetType() ) - { - case CChoreoEvent::EXPRESSION: - { - if ( pActor && !IsMultiplayer() ) - { - DispatchEndExpression( scene, pActor, event ); - } - } - break; - case CChoreoEvent::SPEAK: - { - if ( pActor ) - { - DispatchEndSpeak( scene, pActor, event ); - } - } - break; - case CChoreoEvent::FLEXANIMATION: - { - if ( pActor && !IsMultiplayer() ) - { - DispatchEndFlexAnimation( scene, pActor, event ); - } - } - break; - - case CChoreoEvent::LOOKAT: - { - if ( pActor && !IsMultiplayer() ) - { - DispatchEndLookAt( scene, pActor, event ); - } - } - break; - - - case CChoreoEvent::GESTURE: - { - if ( pActor ) - { - DispatchEndGesture( scene, pActor, event ); - } - } - break; - case CChoreoEvent::GENERIC: - { - // If the first token in the parameters is "debugtext", we printed it and we're done - if ( event->GetParameters() && !Q_strncmp( event->GetParameters(), "debugtext", 9 ) ) - break; - - if ( pActor ) - { - DispatchEndGeneric( scene, pActor, event ); - } - } - break; - case CChoreoEvent::SEQUENCE: - { - if ( pActor ) - { - DispatchEndSequence( scene, pActor, event ); - } - } - break; - - case CChoreoEvent::FACE: - { - if ( pActor && !IsMultiplayer() ) - { - DispatchEndFace( scene, pActor, event ); - } - } - break; - - case CChoreoEvent::MOVETO: - { - if ( pActor && !IsMultiplayer() ) - { - DispatchEndMoveTo( scene, pActor, event ); - } - } - break; - - case CChoreoEvent::SUBSCENE: - { - if ( IsMultiplayer() ) - break; - - CChoreoScene *subscene = event->GetSubScene(); - if ( subscene ) - { - subscene->ResetSimulation(); - } - } - break; - case CChoreoEvent::INTERRUPT: - { - if ( IsMultiplayer() ) - break; - - DispatchEndInterrupt( scene, event ); - } - break; - - case CChoreoEvent::PERMIT_RESPONSES: - { - if ( IsMultiplayer() ) - break; - - DispatchEndPermitResponses( scene, pActor, event ); - } - break; - default: - break; - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: Only spew one time per missing scene!!! -// Input : *scenename - -//----------------------------------------------------------------------------- -void MissingSceneWarning( char const *scenename ) -{ - static CUtlSymbolTable missing; - - // Make sure we only show the message once - if ( UTL_INVAL_SYMBOL == missing.Find( scenename ) ) - { - missing.AddString( scenename ); - - Warning( "Scene '%s' missing!\n", scenename ); - } -} - -bool CSceneEntity::ShouldNetwork() const -{ - if ( m_bMultiplayer ) - { - if ( m_pScene && - ( m_pScene->HasEventsOfType( CChoreoEvent::FLEXANIMATION ) || - m_pScene->HasEventsOfType( CChoreoEvent::EXPRESSION )|| - m_pScene->HasEventsOfType( CChoreoEvent::GESTURE ) || - m_pScene->HasEventsOfType( CChoreoEvent::SEQUENCE ) ) ) - { - return true; - } - } - else - { - if ( m_pScene && - ( m_pScene->HasEventsOfType( CChoreoEvent::FLEXANIMATION ) || - m_pScene->HasEventsOfType( CChoreoEvent::EXPRESSION ) ) ) - { - return true; - } - } - - return false; -} - -CChoreoScene *CSceneEntity::LoadScene( const char *filename, IChoreoEventCallback *pCallback ) -{ - DevMsg( 2, "Blocking load of scene from '%s'\n", filename ); - - char loadfile[MAX_PATH]; - Q_strncpy( loadfile, filename, sizeof( loadfile ) ); - Q_SetExtension( loadfile, ".vcd", sizeof( loadfile ) ); - Q_FixSlashes( loadfile ); - - // binary compiled vcd - void *pBuffer; - int fileSize; - if ( !CopySceneFileIntoMemory( loadfile, &pBuffer, &fileSize ) ) - { - MissingSceneWarning( loadfile ); - return NULL; - } - - CChoreoScene *pScene = new CChoreoScene( NULL ); - CUtlBuffer buf( pBuffer, fileSize, CUtlBuffer::READ_ONLY ); - if ( !pScene->RestoreFromBinaryBuffer( buf, loadfile, &g_ChoreoStringPool ) ) - { - Warning( "CSceneEntity::LoadScene: Unable to load binary scene '%s'\n", loadfile ); - delete pScene; - pScene = NULL; - } - else - { - pScene->SetPrintFunc( LocalScene_Printf ); - pScene->SetEventCallbackInterface( pCallback ); - } - - FreeSceneFileMemory( pBuffer ); - return pScene; -} - -CChoreoScene *BlockingLoadScene( const char *filename ) -{ - return CSceneEntity::LoadScene( filename, NULL ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSceneEntity::UnloadScene( void ) -{ - if ( m_pScene ) - { - ClearSceneEvents( m_pScene, false ); - - for ( int i = 0 ; i < m_pScene->GetNumActors(); i++ ) - { - CBaseFlex *pTestActor = FindNamedActor( i ); - - if ( !pTestActor ) - continue; - - pTestActor->RemoveChoreoScene( m_pScene ); - } - } - delete m_pScene; - m_pScene = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Called every frame that an event is active (Start/EndEvent as also -// called) -// Input : *event - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -void CSceneEntity::ProcessEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event ) -{ - switch ( event->GetType() ) - { - case CChoreoEvent::SUBSCENE: - { - Assert( event->GetType() == CChoreoEvent::SUBSCENE ); - - CChoreoScene *subscene = event->GetSubScene(); - if ( !subscene ) - return; - - if ( subscene->SimulationFinished() ) - return; - - // Have subscenes think for appropriate time - subscene->Think( m_flFrameTime ); - } - break; - - default: - break; - } - - return; -} - - - -//----------------------------------------------------------------------------- -// Purpose: Called for events that are part of a pause condition -// Input : *event - -// Output : Returns true on event completed, false on non-completion. -//----------------------------------------------------------------------------- -bool CSceneEntity::CheckEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event ) -{ - switch ( event->GetType() ) - { - case CChoreoEvent::SUBSCENE: - { - } - break; - default: - { - CBaseFlex *pActor = NULL; - CChoreoActor *actor = event->GetActor(); - if ( actor ) - { - pActor = FindNamedActor( actor ); - if (pActor == NULL) - { - Warning( "CSceneEntity %s unable to find actor \"%s\"\n", STRING(GetEntityName()), actor->GetName() ); - return true; - } - } - if (pActor) - { - return pActor->CheckSceneEvent( currenttime, scene, event ); - } - } - break; - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Get a sticky version of a named actor -// Input : CChoreoActor -// Output : CBaseFlex -//----------------------------------------------------------------------------- - -CBaseFlex *CSceneEntity::FindNamedActor( int index ) -{ - if (m_hActorList.Count() == 0) - { - m_hActorList.SetCount( m_pScene->GetNumActors() ); - NetworkProp()->NetworkStateForceUpdate(); - } - - if ( !m_hActorList.IsValidIndex( index ) ) - { - DevWarning( "Scene %s has %d actors, but scene entity only has %d actors\n", m_pScene->GetFilename(), m_pScene->GetNumActors(), m_hActorList.Size() ); - return NULL; - } - - CBaseFlex *pActor = m_hActorList[ index ]; - - if (pActor == NULL || !pActor->IsAlive() ) - { - CChoreoActor *pChoreoActor = m_pScene->GetActor( index ); - if ( !pChoreoActor ) - return NULL; - - pActor = FindNamedActor( pChoreoActor->GetName() ); - - if (pActor) - { - // save who we found so we'll use them again - m_hActorList[ index ] = pActor; - NetworkProp()->NetworkStateForceUpdate(); - } - } - - return pActor; -} - -//----------------------------------------------------------------------------- -// Purpose: Get a sticky version of a named actor -// Input : CChoreoActor -// Output : CBaseFlex -//----------------------------------------------------------------------------- - -CBaseFlex *CSceneEntity::FindNamedActor( CChoreoActor *pChoreoActor ) -{ - int index = m_pScene->FindActorIndex( pChoreoActor ); - - if (index >= 0) - { - return FindNamedActor( index ); - } - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Search for an actor by name, make sure it can do face poses -// Input : *name - -// Output : CBaseFlex -//----------------------------------------------------------------------------- -CBaseFlex *CSceneEntity::FindNamedActor( const char *name ) -{ - CBaseEntity *entity = FindNamedEntity( name, NULL, true ); - - if ( !entity ) - { - // Couldn't find actor! - return NULL; - } - - // Make sure it can actually do facial animation, etc. - CBaseFlex *flexEntity = dynamic_cast< CBaseFlex * >( entity ); - if ( !flexEntity ) - { - // That actor was not a CBaseFlex! - return NULL; - } - - return flexEntity; -} - -//----------------------------------------------------------------------------- -// Purpose: Find an entity specified by a target name -// Input : *name - -// Output : CBaseEntity -//----------------------------------------------------------------------------- -CBaseEntity *CSceneEntity::FindNamedTarget( string_t iszTarget, bool bBaseFlexOnly ) -{ - if ( !stricmp( STRING(iszTarget), "!activator" ) ) - return m_hActivator; - - // If we don't have a wildcard in the target, just return the first entity found - if ( !strchr( STRING(iszTarget), '*' ) ) - return gEntList.FindEntityByName( NULL, iszTarget ); - - CBaseEntity *pTarget = NULL; - while ( (pTarget = gEntList.FindEntityByName( pTarget, iszTarget )) != NULL ) - { - if ( bBaseFlexOnly ) - { - // Make sure it can actually do facial animation, etc. - if ( dynamic_cast< CBaseFlex * >( pTarget ) ) - return pTarget; - } - else - { - return pTarget; - } - } - - // Failed to find one - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Filters entities only if they're clear -//----------------------------------------------------------------------------- -class CSceneFindMarkFilter : public IEntityFindFilter -{ -public: - void SetActor( CBaseEntity *pActor ) - { - m_hActor = pActor; - } - - bool ShouldFindEntity( CBaseEntity *pEntity ) - { - if ( !m_hActor ) - return true; - - // If we find no truly valid marks, we'll just use the first. - if ( !m_hEntityFound.Get() ) - { - m_hEntityFound = pEntity; - } - - // We only want marks that are clear - trace_t tr; - Vector vecOrigin = pEntity->GetAbsOrigin(); - AI_TraceHull( vecOrigin, vecOrigin, m_hActor->WorldAlignMins(), m_hActor->WorldAlignMaxs(), MASK_SOLID, m_hActor, COLLISION_GROUP_NONE, &tr ); - if ( tr.startsolid ) - { - return false; - } - m_hEntityFound = pEntity; - return true; - } - - CBaseEntity *GetFilterResult( void ) - { - return m_hEntityFound; - } - -private: - EHANDLE m_hActor; - - // To maintain backwards compatability, store off the first mark - // we find. If we find no truly valid marks, we'll just use the first. - EHANDLE m_hEntityFound; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Finds the entity nearest to both entities, and is clear -//----------------------------------------------------------------------------- -class CSceneFindNearestMarkFilter : public IEntityFindFilter -{ -public: - - CSceneFindNearestMarkFilter( const CBaseEntity *pActor, const Vector &vecPos2, float flMaxRadius = MAX_TRACE_LENGTH ) - { - m_vecPos2 = vecPos2; - - m_flMaxSegmentDistance = flMaxRadius; - - m_flNearestToTarget = flMaxRadius; - m_pNearestToTarget = NULL; - m_flNearestToActor = flMaxRadius; - m_pNearestToActor = NULL; - - m_hActor = pActor; - if (pActor) - { - m_vecPos1 = pActor->GetAbsOrigin(); - m_flMaxSegmentDistance = MIN( flMaxRadius, (m_vecPos1 - m_vecPos2).Length() + 1.0 ); - if (m_flMaxSegmentDistance <= 1.0) - { - // must be closest to self - m_flMaxSegmentDistance = MIN( flMaxRadius, MAX_TRACE_LENGTH ); - } - } - } - - bool ShouldFindEntity( CBaseEntity *pEntity ) - { - if ( !m_hActor ) - return true; - - // If we find no truly valid marks, we'll just use the first. - if ( m_pNearestToActor == NULL ) - { - m_pNearestToActor = pEntity; - } - - // We only want marks that are clear - trace_t tr; - Vector vecOrigin = pEntity->GetAbsOrigin(); - AI_TraceHull( vecOrigin, vecOrigin, m_hActor->WorldAlignMins(), m_hActor->WorldAlignMaxs(), MASK_SOLID, m_hActor, COLLISION_GROUP_NONE, &tr ); - if ( !tr.startsolid || tr.m_pEnt == m_hActor) - { - float dist1 = (m_vecPos1 - pEntity->GetAbsOrigin()).Length(); - float dist2 = (m_vecPos2 - pEntity->GetAbsOrigin()).Length(); - /* - char text[256]; - Q_snprintf( text, sizeof( text ), "%.0f : %.0f", dist1, dist2 ); - NDebugOverlay::Text( pEntity->GetAbsOrigin() + Vector( 0, 0, 8 ), text, false, 5.0f ); - */ - // find the point closest to the actor - if (dist1 <= m_flNearestToActor) - { - m_pNearestToActor = pEntity; - m_flNearestToActor = dist2; - } - // find that node that's closest to both, but the distance to it from the actor isn't farther than - // the distance to the second node. This should keep the actor from walking past their point of interest - if (dist1 <= m_flMaxSegmentDistance && dist2 <= m_flMaxSegmentDistance && dist2 < m_flNearestToTarget) - { - m_pNearestToTarget = pEntity; - m_flNearestToTarget = dist2; - } - } - - return false; - } - - CBaseEntity *GetFilterResult( void ) - { - if (m_pNearestToTarget) - return m_pNearestToTarget; - return m_pNearestToActor; - } - -private: - EHANDLE m_hActor; - Vector m_vecPos1; - Vector m_vecPos2; - float m_flMaxSegmentDistance; - float m_flNearestToTarget; - CBaseEntity *m_pNearestToTarget; - float m_flNearestToActor; - CBaseEntity *m_pNearestToActor; -}; - -//----------------------------------------------------------------------------- -// Purpose: Search for an actor by name, make sure it can do face poses -// Input : *name - -// Output : CBaseFlex -//----------------------------------------------------------------------------- -CBaseEntity *CSceneEntity::FindNamedEntity( const char *name, CBaseEntity *pActor, bool bBaseFlexOnly, bool bUseClear ) -{ - CBaseEntity *entity = NULL; - - if ( !stricmp( name, "Player" ) || !stricmp( name, "!player" )) - { - entity = ( gpGlobals->maxClients == 1 ) ? ( CBaseEntity * )UTIL_GetLocalPlayer() : NULL; - } - else if ( !stricmp( name, "!target1" ) ) - { - if (m_hTarget1 == NULL) - { - m_hTarget1 = FindNamedTarget( m_iszTarget1, bBaseFlexOnly ); - } - return m_hTarget1; - } - else if ( !stricmp( name, "!target2" ) ) - { - if (m_hTarget2 == NULL) - { - m_hTarget2 = FindNamedTarget( m_iszTarget2, bBaseFlexOnly ); - } - return m_hTarget2; - } - else if ( !stricmp( name, "!target3" ) ) - { - if (m_hTarget3 == NULL) - { - m_hTarget3 = FindNamedTarget( m_iszTarget3, bBaseFlexOnly ); - } - return m_hTarget3; - } - else if ( !stricmp( name, "!target4" ) ) - { - if (m_hTarget4 == NULL) - { - m_hTarget4 = FindNamedTarget( m_iszTarget4, bBaseFlexOnly ); - } - return m_hTarget4; - } - else if ( !stricmp( name, "!target5" ) ) - { - if (m_hTarget5 == NULL) - { - m_hTarget5 = FindNamedTarget( m_iszTarget5, bBaseFlexOnly ); - } - return m_hTarget5; - } - else if ( !stricmp( name, "!target6" ) ) - { - if (m_hTarget6 == NULL) - { - m_hTarget6 = FindNamedTarget( m_iszTarget6, bBaseFlexOnly ); - } - return m_hTarget6; - } - else if ( !stricmp( name, "!target7" ) ) - { - if (m_hTarget7 == NULL) - { - m_hTarget7 = FindNamedTarget( m_iszTarget7, bBaseFlexOnly ); - } - return m_hTarget7; - } - else if ( !stricmp( name, "!target8" ) ) - { - if (m_hTarget8 == NULL) - { - m_hTarget8 = FindNamedTarget( m_iszTarget8, bBaseFlexOnly ); - } - return m_hTarget8; - } - else if (pActor && pActor->MyNPCPointer()) - { - CSceneFindMarkFilter *pFilter = NULL; - if ( bUseClear ) - { - pFilter = new CSceneFindMarkFilter(); - pFilter->SetActor( pActor ); - } - - entity = pActor->MyNPCPointer()->FindNamedEntity( name, pFilter ); - if ( !entity && pFilter ) - { - entity = pFilter->GetFilterResult(); - } - } - else - { - // search for up to 32 entities with the same name and choose one randomly - CBaseEntity *entityList[ FINDNAMEDENTITY_MAX_ENTITIES ]; - int iCount; - - entity = NULL; - for( iCount = 0; iCount < FINDNAMEDENTITY_MAX_ENTITIES; iCount++ ) - { - entity = gEntList.FindEntityByName( entity, name, NULL, pActor ); - if ( !entity ) - { - break; - } - entityList[ iCount ] = entity; - } - - if ( iCount > 0 ) - { - entity = entityList[ RandomInt( 0, iCount - 1 ) ]; - } - else - { - entity = NULL; - } - } - - return entity; -} - - -//----------------------------------------------------------------------------- -// Purpose: Search for an actor by name, make sure it can do face poses -// Input : *name - -// Output : CBaseFlex -//----------------------------------------------------------------------------- -CBaseEntity *CSceneEntity::FindNamedEntityClosest( const char *name, CBaseEntity *pActor, bool bBaseFlexOnly, bool bUseClear, const char *pszSecondary ) -{ - CBaseEntity *entity = NULL; - - if ( !stricmp( name, "!activator" ) ) - { - return m_hActivator; - } - else if ( !stricmp( name, "Player" ) || !stricmp( name, "!player" )) - { - entity = ( gpGlobals->maxClients == 1 ) ? ( CBaseEntity * )UTIL_GetLocalPlayer() : NULL; - return entity; - } - else if ( !stricmp( name, "!target1" ) ) - { - name = STRING( m_iszTarget1 ); - } - else if ( !stricmp( name, "!target2" ) ) - { - name = STRING( m_iszTarget2 ); - } - else if ( !stricmp( name, "!target3" ) ) - { - name = STRING( m_iszTarget3 ); - } - else if ( !stricmp( name, "!target4" ) ) - { - name = STRING( m_iszTarget4 ); - } - else if ( !stricmp( name, "!target5" ) ) - { - name = STRING( m_iszTarget5 ); - } - else if ( !stricmp( name, "!target6" ) ) - { - name = STRING( m_iszTarget6 ); - } - else if ( !stricmp( name, "!target7" ) ) - { - name = STRING( m_iszTarget7 ); - } - - if (pActor && pActor->MyNPCPointer()) - { - if (pszSecondary && strlen( pszSecondary ) > 0) - { - CBaseEntity *pActor2 = FindNamedEntityClosest( pszSecondary, pActor, false, false, NULL ); - - if (pActor2) - { - CSceneFindNearestMarkFilter *pFilter = new CSceneFindNearestMarkFilter( pActor, pActor2->GetAbsOrigin() ); - - entity = pActor->MyNPCPointer()->FindNamedEntity( name, pFilter ); - if (!entity && pFilter) - { - entity = pFilter->GetFilterResult(); - } - } - } - if (!entity) - { - CSceneFindMarkFilter *pFilter = NULL; - if ( bUseClear ) - { - pFilter = new CSceneFindMarkFilter(); - pFilter->SetActor( pActor ); - } - - entity = pActor->MyNPCPointer()->FindNamedEntity( name, pFilter ); - if (!entity && pFilter) - { - entity = pFilter->GetFilterResult(); - } - } - } - else - { - // search for up to 32 entities with the same name and choose one randomly - int iCount; - entity = NULL; - CBaseEntity *current = NULL; - for( iCount = 0; iCount < FINDNAMEDENTITY_MAX_ENTITIES; iCount++ ) - { - current = gEntList.FindEntityByName( current, name, NULL, pActor ); - if ( current ) - { - if (RandomInt( 0, iCount ) == 0) - entity = current; - } - } - - entity = NULL; - } - - return entity; -} - - -//----------------------------------------------------------------------------- -// Purpose: Remove all "scene" expressions from all actors in this scene -//----------------------------------------------------------------------------- -void CSceneEntity::ClearSceneEvents( CChoreoScene *scene, bool canceled ) -{ - if ( !m_pScene ) - return; - - LocalScene_Printf( "%s : %8.2f: clearing events\n", STRING( m_iszSceneFile ), m_flCurrentTime ); - - int i; - for ( i = 0 ; i < m_pScene->GetNumActors(); i++ ) - { - CBaseFlex *pActor = FindNamedActor( i ); - if ( !pActor ) - continue; - - // Clear any existing expressions - pActor->ClearSceneEvents( scene, canceled ); - } - - // Iterate events and precache necessary resources - for ( i = 0; i < scene->GetNumEvents(); i++ ) - { - CChoreoEvent *event = scene->GetEvent( i ); - if ( !event ) - continue; - - // load any necessary data - switch (event->GetType() ) - { - default: - break; - case CChoreoEvent::SUBSCENE: - { - // Only allow a single level of subscenes for now - if ( !scene->IsSubScene() ) - { - CChoreoScene *subscene = event->GetSubScene(); - if ( subscene ) - { - ClearSceneEvents( subscene, canceled ); - } - } - } - break; - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Remove all imposed schedules from all actors in this scene -//----------------------------------------------------------------------------- -void CSceneEntity::ClearSchedules( CChoreoScene *scene ) -{ - if ( !m_pScene ) - return; - - int i; - for ( i = 0 ; i < m_pScene->GetNumActors(); i++ ) - { - CBaseFlex *pActor = FindNamedActor( i ); - if ( !pActor ) - continue; - - CAI_BaseNPC *pNPC = pActor->MyNPCPointer(); - - if ( pNPC ) - { - /* - if ( pNPC->IsCurSchedule( SCHED_SCENE_GENERIC ) ) - pNPC->ClearSchedule( "Scene entity clearing all actor schedules" ); - */ - } - else - { - pActor->ResetSequence( pActor->SelectWeightedSequence( ACT_IDLE ) ); - pActor->SetCycle( 0 ); - } - // Clear any existing expressions - } - - // Iterate events and precache necessary resources - for ( i = 0; i < scene->GetNumEvents(); i++ ) - { - CChoreoEvent *event = scene->GetEvent( i ); - if ( !event ) - continue; - - // load any necessary data - switch (event->GetType() ) - { - default: - break; - case CChoreoEvent::SUBSCENE: - { - // Only allow a single level of subscenes for now - if ( !scene->IsSubScene() ) - { - CChoreoScene *subscene = event->GetSubScene(); - if ( subscene ) - { - ClearSchedules( subscene ); - } - } - } - break; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: If we are currently interruptable, pause this scene and wait for the other -// scene to finish -// Input : *otherScene - -//----------------------------------------------------------------------------- -bool CSceneEntity::InterruptThisScene( CSceneEntity *otherScene ) -{ - Assert( otherScene ); - - if ( !IsInterruptable() ) - { - return false; - } - - // Already interrupted - if ( m_bInterrupted ) - { - return false; - } - - m_bInterrupted = true; - m_hInterruptScene = otherScene; - - // Ask other scene to tell us when it's finished or canceled - otherScene->RequestCompletionNotification( this ); - - PausePlayback(); - return true; -} - -/* -void scene_interrupt( const CCommand &args ) -{ - if ( args.ArgC() != 3 ) - return; - - const char *scene1 = args[1]; - const char *scene2 = args[2]; - - CSceneEntity *s1 = dynamic_cast< CSceneEntity * >( gEntList.FindEntityByName( NULL, scene1 ) ); - CSceneEntity *s2 = dynamic_cast< CSceneEntity * >( gEntList.FindEntityByName( NULL, scene2 ) ); - - if ( !s1 || !s2 ) - return; - - if ( s1->InterruptThisScene( s2 ) ) - { - s2->StartPlayback(); - } -} - -static ConCommand interruptscene( "int", scene_interrupt, "interrupt scene 1 with scene 2.", FCVAR_CHEAT ); -*/ - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSceneEntity::CheckInterruptCompletion() -{ - if ( !m_bInterrupted ) - return; - - // If the interruptor goes away it's the same as having that scene finish up... - if ( m_hInterruptScene != NULL && - !m_bInterruptSceneFinished ) - { - return; - } - - m_bInterrupted = false; - m_hInterruptScene = NULL; - - ResumePlayback(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSceneEntity::ClearInterrupt() -{ - m_nInterruptCount = 0; - m_bInterrupted = false; - m_hInterruptScene = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Another scene is asking us to notify upon completion -// Input : *notify - -//----------------------------------------------------------------------------- -void CSceneEntity::RequestCompletionNotification( CSceneEntity *notify ) -{ - CHandle< CSceneEntity > h; - h = notify; - // Only add it once - if ( m_hNotifySceneCompletion.Find( h ) == m_hNotifySceneCompletion.InvalidIndex() ) - { - m_hNotifySceneCompletion.AddToTail( h ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: An interrupt scene has finished or been canceled, we can resume once we pick up this state in CheckInterruptCompletion -// Input : *interruptor - -//----------------------------------------------------------------------------- -void CSceneEntity::NotifyOfCompletion( CSceneEntity *interruptor ) -{ - Assert( m_bInterrupted ); - Assert( m_hInterruptScene == interruptor ); - m_bInterruptSceneFinished = true; - - CheckInterruptCompletion(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSceneEntity::AddListManager( CSceneListManager *pManager ) -{ - CHandle< CSceneListManager > h; - h = pManager; - // Only add it once - if ( m_hListManagers.Find( h ) == m_hListManagers.InvalidIndex() ) - { - m_hListManagers.AddToTail( h ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Clear any targets that a referencing !activator -//----------------------------------------------------------------------------- -void CSceneEntity::ClearActivatorTargets( void ) -{ - if ( !stricmp( STRING(m_iszTarget1), "!activator" ) ) - { - // We need to clear out actors so they're re-evaluated - m_hActorList.Purge(); - NetworkProp()->NetworkStateForceUpdate(); - m_hTarget1 = NULL; - } - if ( !stricmp( STRING(m_iszTarget2), "!activator" ) ) - { - // We need to clear out actors so they're re-evaluated - m_hActorList.Purge(); - NetworkProp()->NetworkStateForceUpdate(); - m_hTarget2 = NULL; - } - if ( !stricmp( STRING(m_iszTarget3), "!activator" ) ) - { - // We need to clear out actors so they're re-evaluated - m_hActorList.Purge(); - NetworkProp()->NetworkStateForceUpdate(); - m_hTarget3 = NULL; - } - if ( !stricmp( STRING(m_iszTarget4), "!activator" ) ) - { - // We need to clear out actors so they're re-evaluated - m_hActorList.Purge(); - NetworkProp()->NetworkStateForceUpdate(); - m_hTarget4 = NULL; - } - if ( !stricmp( STRING(m_iszTarget5), "!activator" ) ) - { - // We need to clear out actors so they're re-evaluated - m_hActorList.Purge(); - NetworkProp()->NetworkStateForceUpdate(); - m_hTarget5 = NULL; - } - if ( !stricmp( STRING(m_iszTarget6), "!activator" ) ) - { - // We need to clear out actors so they're re-evaluated - m_hActorList.Purge(); - NetworkProp()->NetworkStateForceUpdate(); - m_hTarget6 = NULL; - } - if ( !stricmp( STRING(m_iszTarget7), "!activator" ) ) - { - // We need to clear out actors so they're re-evaluated - m_hActorList.Purge(); - NetworkProp()->NetworkStateForceUpdate(); - m_hTarget7 = NULL; - } - if ( !stricmp( STRING(m_iszTarget8), "!activator" ) ) - { - // We need to clear out actors so they're re-evaluated - m_hActorList.Purge(); - NetworkProp()->NetworkStateForceUpdate(); - m_hTarget8 = NULL; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Called when a scene is completed or canceled -//----------------------------------------------------------------------------- -void CSceneEntity::OnSceneFinished( bool canceled, bool fireoutput ) -{ - if ( !m_pScene ) - return; - - LocalScene_Printf( "%s : %8.2f: finished\n", STRING( m_iszSceneFile ), m_flCurrentTime ); - - // Notify any listeners - int c = m_hNotifySceneCompletion.Count(); - int i; - for ( i = 0; i < c; i++ ) - { - CSceneEntity *ent = m_hNotifySceneCompletion[ i ].Get(); - if ( !ent ) - continue; - - ent->NotifyOfCompletion( this ); - } - m_hNotifySceneCompletion.RemoveAll(); - - // Clear simulation - m_pScene->ResetSimulation(); - m_bIsPlayingBack = false; - m_bPaused = false; - SetCurrentTime( 0.0f, false ); - - // Clear interrupt state if we were interrupted for some reason - ClearInterrupt(); - - if ( fireoutput && !m_bCompletedEarly) - { - m_OnCompletion.FireOutput( this, this, 0 ); - } - - // Put face back in neutral pose - ClearSceneEvents( m_pScene, canceled ); - - for ( i = 0 ; i < m_pScene->GetNumActors(); i++ ) - { - CBaseFlex *pTestActor = FindNamedActor( i ); - - if ( !pTestActor ) - continue; - - pTestActor->RemoveChoreoScene( m_pScene, canceled ); - - // If we interrupted the actor's previous scenes, resume them - if ( m_bInterruptedActorsScenes ) - { - QueueActorsScriptedScenesToResume( pTestActor, false ); - } - } -} - -//----------------------------------------------------------------------------- -// Should we transmit it to the client? -//----------------------------------------------------------------------------- -int CSceneEntity::UpdateTransmitState() -{ - if ( !ShouldNetwork() ) - { - return SetTransmitState( FL_EDICT_DONTSEND ); - } - - if ( m_pRecipientFilter ) - { - return SetTransmitState( FL_EDICT_FULLCHECK ); - } - - return SetTransmitState( FL_EDICT_ALWAYS ); -} - -//----------------------------------------------------------------------------- -// Purpose: Which clients should we be transmitting to? -//----------------------------------------------------------------------------- -int CSceneEntity::ShouldTransmit( const CCheckTransmitInfo *pInfo ) -{ - int result = BaseClass::ShouldTransmit( pInfo ); - - // if we have excluded them via our recipient filter, don't send - if ( m_pRecipientFilter && result != FL_EDICT_DONTSEND ) - { - bool bFound = false; - - // If we can't find them in the recipient list, exclude - int i; - for ( i=0; iGetRecipientCount();i++ ) - { - int iRecipient = m_pRecipientFilter->GetRecipientIndex(i); - - CBasePlayer *player = static_cast< CBasePlayer * >( CBaseEntity::Instance( iRecipient ) ); - - if ( player && player->edict() == pInfo->m_pClientEnt ) - { - bFound = true; - break; - } - } - - if ( !bFound ) - { - result = FL_EDICT_DONTSEND; - } - } - - return result; -} - -void CSceneEntity::SetRecipientFilter( IRecipientFilter *filter ) -{ - // create a copy of this filter - if ( filter ) - { - m_pRecipientFilter = new CRecipientFilter(); - m_pRecipientFilter->CopyFrom( (CRecipientFilter &)( *filter ) ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -class CInstancedSceneEntity : public CSceneEntity -{ - DECLARE_DATADESC(); - DECLARE_CLASS( CInstancedSceneEntity, CSceneEntity ); -public: - EHANDLE m_hOwner; - bool m_bHadOwner; - float m_flPostSpeakDelay; - float m_flPreDelay; - char m_szInstanceFilename[ CChoreoScene::MAX_SCENE_FILENAME ]; - bool m_bIsBackground; - - virtual void StartPlayback( void ); - virtual void DoThink( float frametime ); - virtual CBaseFlex *FindNamedActor( const char *name ); - virtual CBaseEntity *FindNamedEntity( const char *name ); - virtual float GetPostSpeakDelay() { return m_flPostSpeakDelay; } - virtual void SetPostSpeakDelay( float flDelay ) { m_flPostSpeakDelay = flDelay; } - virtual float GetPreDelay() { return m_flPreDelay; } - virtual void SetPreDelay( float flDelay ) { m_flPreDelay = flDelay; } - - virtual void OnLoaded(); - - virtual void DispatchStartMoveTo( CChoreoScene *scene, CBaseFlex *actor, CBaseEntity *actor2, CChoreoEvent *event ) - { - if (PassThrough( actor )) BaseClass::DispatchStartMoveTo( scene, actor, actor2, event ); - }; - - virtual void DispatchEndMoveTo( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ) - { - if (PassThrough( actor )) BaseClass::DispatchEndMoveTo( scene, actor, event ); - }; - - virtual void DispatchStartFace( CChoreoScene *scene, CBaseFlex *actor, CBaseEntity *actor2, CChoreoEvent *event ) - { - if (PassThrough( actor )) BaseClass::DispatchStartFace( scene, actor, actor2, event ); - }; - - virtual void DispatchEndFace( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ) - { - if (PassThrough( actor )) BaseClass::DispatchEndFace( scene, actor, event ); - }; - - virtual void DispatchStartSequence( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ) { /* suppress */ }; - virtual void DispatchEndSequence( CChoreoScene *scene, CBaseFlex *actor, CChoreoEvent *event ) { /* suppress */ }; - virtual void DispatchPauseScene( CChoreoScene *scene, const char *parameters ) { /* suppress */ }; - - void OnRestore(); - - virtual float EstimateLength( void ); - -private: - bool PassThrough( CBaseFlex *actor ); -}; - -LINK_ENTITY_TO_CLASS( instanced_scripted_scene, CInstancedSceneEntity ); - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CInstancedSceneEntity ) - - DEFINE_FIELD( m_hOwner, FIELD_EHANDLE ), - DEFINE_FIELD( m_bHadOwner, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flPostSpeakDelay, FIELD_FLOAT ), - DEFINE_FIELD( m_flPreDelay, FIELD_FLOAT ), - DEFINE_AUTO_ARRAY( m_szInstanceFilename, FIELD_CHARACTER ), - DEFINE_FIELD( m_bIsBackground, FIELD_BOOLEAN ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: create a one-shot scene, no movement, sequences, etc. -// Input : -// Output : -//----------------------------------------------------------------------------- -float InstancedScriptedScene( CBaseFlex *pActor, const char *pszScene, EHANDLE *phSceneEnt, - float flPostDelay, bool bIsBackground, AI_Response *response, - bool bMultiplayer, IRecipientFilter *filter /* = NULL */ ) -{ - VPROF( "InstancedScriptedScene" ); - - CInstancedSceneEntity *pScene = (CInstancedSceneEntity *)CBaseEntity::CreateNoSpawn( "instanced_scripted_scene", vec3_origin, vec3_angle ); - - // This code expands any $gender tags into male or female tags based on the gender of the actor (based on his/her .mdl) - if ( pActor ) - { - pActor->GenderExpandString( pszScene, pScene->m_szInstanceFilename, sizeof( pScene->m_szInstanceFilename ) ); - } - else - { - Q_strncpy( pScene->m_szInstanceFilename, pszScene, sizeof( pScene->m_szInstanceFilename ) ); - } - pScene->m_iszSceneFile = MAKE_STRING( pScene->m_szInstanceFilename ); - - // FIXME: I should set my output to fire something that kills me.... - - // FIXME: add a proper initialization function - pScene->m_hOwner = pActor; - pScene->m_bHadOwner = pActor != NULL; - pScene->m_bMultiplayer = bMultiplayer; - pScene->SetPostSpeakDelay( flPostDelay ); - DispatchSpawn( pScene ); - pScene->Activate(); - pScene->m_bIsBackground = bIsBackground; - - pScene->SetBackground( bIsBackground ); - pScene->SetRecipientFilter( filter ); - - if ( response ) - { - float flPreDelay = response->GetPreDelay(); - if ( flPreDelay ) - { - pScene->SetPreDelay( flPreDelay ); - } - } - - pScene->StartPlayback(); - - if ( response ) - { - // If the response wants us to abort on NPC state switch, remember that - pScene->SetBreakOnNonIdle( response->ShouldBreakOnNonIdle() ); - } - - if ( phSceneEnt ) - { - *phSceneEnt = pScene; - } - - return pScene->EstimateLength(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pActor - -// *soundnmame - -// *phSceneEnt - -// Output : float -//----------------------------------------------------------------------------- -float InstancedAutoGeneratedSoundScene( CBaseFlex *pActor, char const *soundname, EHANDLE *phSceneEnt /*= NULL*/ ) -{ - if ( !pActor ) - { - Warning( "InstancedAutoGeneratedSoundScene: Expecting non-NULL pActor for sound %s\n", soundname ); - return 0; - } - - CInstancedSceneEntity *pScene = (CInstancedSceneEntity *)CBaseEntity::CreateNoSpawn( "instanced_scripted_scene", vec3_origin, vec3_angle ); - - Q_strncpy( pScene->m_szInstanceFilename, UTIL_VarArgs( "AutoGenerated(%s)", soundname ), sizeof( pScene->m_szInstanceFilename ) ); - pScene->m_iszSceneFile = MAKE_STRING( pScene->m_szInstanceFilename ); - - pScene->m_hOwner = pActor; - pScene->m_bHadOwner = pActor != NULL; - - pScene->GenerateSoundScene( pActor, soundname ); - - pScene->Spawn(); - pScene->Activate(); - pScene->StartPlayback(); - - if ( phSceneEnt ) - { - *phSceneEnt = pScene; - } - - return pScene->EstimateLength(); -} - -//----------------------------------------------------------------------------- - -void StopScriptedScene( CBaseFlex *pActor, EHANDLE hSceneEnt ) -{ - CBaseEntity *pEntity = hSceneEnt; - CSceneEntity *pScene = dynamic_cast(pEntity); - - if ( pScene ) - { - LocalScene_Printf( "%s : stop scripted scene\n", STRING( pScene->m_iszSceneFile ) ); - pScene->CancelPlayback(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pszScene - -// Output : float -//----------------------------------------------------------------------------- -float GetSceneDuration( char const *pszScene ) -{ - unsigned int msecs = 0; - - SceneCachedData_t cachedData; - if ( scenefilecache->GetSceneCachedData( pszScene, &cachedData ) ) - { - msecs = cachedData.msecs; - } - - return (float)msecs * 0.001f; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pszScene - -// Output : int -//----------------------------------------------------------------------------- -int GetSceneSpeechCount( char const *pszScene ) -{ - SceneCachedData_t cachedData; - if ( scenefilecache->GetSceneCachedData( pszScene, &cachedData ) ) - { - return cachedData.numSounds; - } - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: Used for precaching instanced scenes -// Input : *pszScene - -//----------------------------------------------------------------------------- -void PrecacheInstancedScene( char const *pszScene ) -{ - static int nMakingReslists = -1; - - if ( nMakingReslists == -1 ) - { - nMakingReslists = CommandLine()->FindParm( "-makereslists" ) > 0 ? 1 : 0; - } - - if ( nMakingReslists == 1 ) - { - // Just stat the file to add to reslist - g_pFullFileSystem->Size( pszScene ); - } - - // verify existence, cache is pre-populated, should be there - SceneCachedData_t sceneData; - if ( !scenefilecache->GetSceneCachedData( pszScene, &sceneData ) ) - { - // Scenes are sloppy and don't always exist. - // A scene that is not in the pre-built cache image, but on disk, is a true error. - if ( developer.GetInt() && ( IsX360() && ( g_pFullFileSystem->GetDVDMode() != DVDMODE_STRICT ) && g_pFullFileSystem->FileExists( pszScene, "GAME" ) ) ) - { - Warning( "PrecacheInstancedScene: Missing scene '%s' from scene image cache.\nRebuild scene image cache!\n", pszScene ); - } - } - else - { - for ( int i = 0; i < sceneData.numSounds; ++i ) - { - short stringId = scenefilecache->GetSceneCachedSound( sceneData.sceneId, i ); - CBaseEntity::PrecacheScriptSound( scenefilecache->GetSceneString( stringId ) ); - } - } - - g_pStringTableClientSideChoreoScenes->AddString( CBaseEntity::IsServer(), pszScene ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CInstancedSceneEntity::StartPlayback( void ) -{ - // Wait until our pre delay is over - if ( GetPreDelay() ) - return; - - BaseClass::StartPlayback(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CInstancedSceneEntity::DoThink( float frametime ) -{ - CheckInterruptCompletion(); - - if ( m_flPreDelay > 0 ) - { - m_flPreDelay = MAX( 0, m_flPreDelay - frametime ); - StartPlayback(); - if ( !m_bIsPlayingBack ) - return; - } - - if ( !m_pScene || !m_bIsPlayingBack || ( m_bHadOwner && m_hOwner == NULL ) ) - { - UTIL_Remove( this ); - return; - } - - // catch bad pitch shifting from old save games - Assert( m_fPitch >= SCENE_MIN_PITCH && m_fPitch <= SCENE_MAX_PITCH ); - m_fPitch = clamp( m_fPitch, SCENE_MIN_PITCH, SCENE_MAX_PITCH ); - - if ( m_bPaused ) - { - PauseThink(); - return; - } - - float dt = frametime; - - m_pScene->SetSoundFileStartupLatency( GetSoundSystemLatency() ); - - // Tell scene to go - m_pScene->Think( m_flCurrentTime ); - // Drive simulation time for scene - SetCurrentTime( m_flCurrentTime + dt * m_fPitch, false ); - - // Did we get to the end - if ( m_pScene->SimulationFinished() ) - { - OnSceneFinished( false, false ); - - UTIL_Remove( this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Search for an actor by name, make sure it can do face poses -// Input : *name - -// Output : CBaseFlex -//----------------------------------------------------------------------------- -CBaseFlex *CInstancedSceneEntity::FindNamedActor( const char *name ) -{ - if ( m_pScene->GetNumActors() == 1 || stricmp( name, "!self" ) == 0 ) - { - if ( m_hOwner != NULL ) - { - CBaseCombatCharacter *pCharacter = m_hOwner->MyCombatCharacterPointer(); - if ( pCharacter ) - { - return pCharacter; - } - } - } - return BaseClass::FindNamedActor( name ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Search for an actor by name, make sure it can do face poses -// Input : *name - -// Output : CBaseFlex -//----------------------------------------------------------------------------- -CBaseEntity *CInstancedSceneEntity::FindNamedEntity( const char *name ) -{ - CBaseEntity *pOther = NULL; - - if (m_hOwner != NULL) - { - CAI_BaseNPC *npc = m_hOwner->MyNPCPointer(); - - if (npc) - { - pOther = npc->FindNamedEntity( name ); - } - else if ( m_hOwner->MyCombatCharacterPointer() ) - { - pOther = m_hOwner; - } - } - - if (!pOther) - { - pOther = BaseClass::FindNamedEntity( name ); - } - return pOther; -} - - -//----------------------------------------------------------------------------- -// Purpose: Suppress certain events when it's instanced since they're can cause odd problems -// Input : actor -// Output : true - the event should happen, false - it shouldn't -//----------------------------------------------------------------------------- - -bool CInstancedSceneEntity::PassThrough( CBaseFlex *actor ) -{ - if (!actor) - return false; - - CAI_BaseNPC *myNpc = actor->MyNPCPointer( ); - - if (!myNpc) - return false; - - if (myNpc->IsCurSchedule( SCHED_SCENE_GENERIC )) - { - return true; - } - - if (myNpc->GetCurSchedule()) - { - CAI_ScheduleBits testBits; - myNpc->GetCurSchedule()->GetInterruptMask( &testBits ); - - if (testBits.IsBitSet( COND_IDLE_INTERRUPT )) - { - return true; - } - } - - LocalScene_Printf( "%s : event suppressed\n", STRING( m_iszSceneFile ) ); - - return false; -} - - -//----------------------------------------------------------------------------- -void CInstancedSceneEntity::OnRestore() -{ - if ( m_bHadOwner && !m_hOwner ) - { - // probably just came back from a level transition - UTIL_Remove( this ); - return; - } - // reset background state - if ( m_pScene ) - { - m_pScene->SetBackground( m_bIsBackground ); - } - BaseClass::OnRestore(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CInstancedSceneEntity::EstimateLength( void ) -{ - return (BaseClass::EstimateLength() + GetPreDelay()); -} - - -void CInstancedSceneEntity::OnLoaded() -{ - BaseClass::OnLoaded(); - SetBackground( m_bIsBackground ); -} - -bool g_bClientFlex = true; - -LINK_ENTITY_TO_CLASS( scene_manager, CSceneManager ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSceneManager::Think() -{ - // Latch this only once per frame... - g_bClientFlex = scene_clientflex.GetBool(); - - // The manager is always thinking at 20 hz - SetNextThink( gpGlobals->curtime + SCENE_THINK_INTERVAL ); - float frameTime = ( gpGlobals->curtime - GetLastThink() ); - frameTime = MIN( 0.1, frameTime ); - - // stop if AI is diabled - if (CAI_BaseNPC::m_nDebugBits & bits_debugDisableAI) - return; - - bool needCleanupPass = false; - int c = m_ActiveScenes.Count(); - for ( int i = 0; i < c; i++ ) - { - CSceneEntity *scene = m_ActiveScenes[ i ].Get(); - if ( !scene ) - { - needCleanupPass = true; - continue; - } - - scene->DoThink( frameTime ); - - if ( m_ActiveScenes.Count() < c ) - { - // Scene removed self while thinking. Adjust iteration. - c = m_ActiveScenes.Count(); - i--; - } - } - - // Now delete any invalid ones - if ( needCleanupPass ) - { - for ( int i = c - 1; i >= 0; i-- ) - { - CSceneEntity *scene = m_ActiveScenes[ i ].Get(); - if ( scene ) - continue; - - m_ActiveScenes.Remove( i ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSceneManager::ClearAllScenes() -{ - m_ActiveScenes.RemoveAll(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *scene - -//----------------------------------------------------------------------------- -void CSceneManager::AddSceneEntity( CSceneEntity *scene ) -{ - CHandle< CSceneEntity > h; - - h = scene; - - // Already added/activated - if ( m_ActiveScenes.Find( h ) != m_ActiveScenes.InvalidIndex() ) - { - return; - } - - m_ActiveScenes.AddToTail( h ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *scene - -//----------------------------------------------------------------------------- -void CSceneManager::RemoveSceneEntity( CSceneEntity *scene ) -{ - CHandle< CSceneEntity > h; - - h = scene; - - m_ActiveScenes.FindAndRemove( h ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *player - -//----------------------------------------------------------------------------- -void CSceneManager::OnClientActive( CBasePlayer *player ) -{ - int c = m_QueuedSceneSounds.Count(); - for ( int i = 0; i < c; i++ ) - { - CRestoreSceneSound *sound = &m_QueuedSceneSounds[ i ]; - - if ( sound->actor == NULL ) - continue; - - // Blow off sounds too far in past to encode over networking layer - if ( fabs( 1000.0f * sound->time_in_past ) > MAX_SOUND_DELAY_MSEC ) - continue; - - CPASAttenuationFilter filter( sound->actor ); - - EmitSound_t es; - es.m_nChannel = CHAN_VOICE; - es.m_flVolume = 1; - es.m_pSoundName = sound->soundname; - es.m_SoundLevel = sound->soundlevel; - es.m_flSoundTime = gpGlobals->curtime - sound->time_in_past; - - EmitSound( filter, sound->actor->entindex(), es ); - } - - m_QueuedSceneSounds.RemoveAll(); -} - -//----------------------------------------------------------------------------- -// Purpose: Stops scenes involving the specified actor -//----------------------------------------------------------------------------- -void CSceneManager::RemoveActorFromScenes( CBaseFlex *pActor, bool bInstancedOnly, bool bNonIdleOnly, const char *pszThisSceneOnly ) -{ - int c = m_ActiveScenes.Count(); - for ( int i = 0; i < c; i++ ) - { - CSceneEntity *pScene = m_ActiveScenes[ i ].Get(); - if ( !pScene ) - { - continue; - } - - // If only stopping instanced scenes, then skip it if it can't cast to an instanced scene - if ( bInstancedOnly && - ( dynamic_cast< CInstancedSceneEntity * >( pScene ) == NULL ) ) - { - continue; - } - - if ( bNonIdleOnly && !pScene->ShouldBreakOnNonIdle() ) - continue; - - if ( pScene->InvolvesActor( pActor ) ) - { - if ( pszThisSceneOnly && pszThisSceneOnly[0] ) - { - if ( Q_strcmp( pszThisSceneOnly, STRING(pScene->m_iszSceneFile) ) ) - continue; - } - - LocalScene_Printf( "%s : removed for '%s'\n", STRING( pScene->m_iszSceneFile ), pActor ? pActor->GetDebugName() : "NULL" ); - pScene->CancelPlayback(); - } - - } -} - -//----------------------------------------------------------------------------- -// Purpose: Pause scenes involving the specified actor -//----------------------------------------------------------------------------- -void CSceneManager::PauseActorsScenes( CBaseFlex *pActor, bool bInstancedOnly ) -{ - int c = m_ActiveScenes.Count(); - for ( int i = 0; i < c; i++ ) - { - CSceneEntity *pScene = m_ActiveScenes[ i ].Get(); - if ( !pScene ) - { - continue; - } - - // If only stopping instanced scenes, then skip it if it can't cast to an instanced scene - if ( bInstancedOnly && - ( dynamic_cast< CInstancedSceneEntity * >( pScene ) == NULL ) ) - { - continue; - } - - if ( pScene->InvolvesActor( pActor ) && pScene->IsPlayingBack() ) - { - LocalScene_Printf( "Pausing actor %s scripted scene: %s\n", pActor->GetDebugName(), STRING(pScene->m_iszSceneFile) ); - - variant_t emptyVariant; - pScene->AcceptInput( "Pause", pScene, pScene, emptyVariant, 0 ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if this Actor is only in scenes that are interruptable right now -//----------------------------------------------------------------------------- -bool CSceneManager::IsInInterruptableScenes( CBaseFlex *pActor ) -{ - int c = m_ActiveScenes.Count(); - for ( int i = 0; i < c; i++ ) - { - CSceneEntity *pScene = m_ActiveScenes[ i ].Get(); - if ( !pScene ) - continue; - - //Ignore background scenes since they're harmless. - if ( pScene->IsBackground() == true ) - continue; - - if ( pScene->InvolvesActor( pActor ) && pScene->IsPlayingBack() ) - { - if ( pScene->IsInterruptable() == false ) - return false; - } - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Resume any paused scenes involving the specified actor -//----------------------------------------------------------------------------- -void CSceneManager::ResumeActorsScenes( CBaseFlex *pActor, bool bInstancedOnly ) -{ - int c = m_ActiveScenes.Count(); - for ( int i = 0; i < c; i++ ) - { - CSceneEntity *pScene = m_ActiveScenes[ i ].Get(); - if ( !pScene ) - { - continue; - } - - // If only stopping instanced scenes, then skip it if it can't cast to an instanced scene - if ( bInstancedOnly && - ( dynamic_cast< CInstancedSceneEntity * >( pScene ) == NULL ) ) - { - continue; - } - - if ( pScene->InvolvesActor( pActor ) && pScene->IsPlayingBack() ) - { - LocalScene_Printf( "Resuming actor %s scripted scene: %s\n", pActor->GetDebugName(), STRING(pScene->m_iszSceneFile) ); - - variant_t emptyVariant; - pScene->AcceptInput( "Resume", pScene, pScene, emptyVariant, 0 ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Set all paused, in-playback scenes to resume when the actor is ready -//----------------------------------------------------------------------------- -void CSceneManager::QueueActorsScenesToResume( CBaseFlex *pActor, bool bInstancedOnly ) -{ - int c = m_ActiveScenes.Count(); - for ( int i = 0; i < c; i++ ) - { - CSceneEntity *pScene = m_ActiveScenes[ i ].Get(); - if ( !pScene ) - { - continue; - } - - // If only stopping instanced scenes, then skip it if it can't cast to an instanced scene - if ( bInstancedOnly && - ( dynamic_cast< CInstancedSceneEntity * >( pScene ) == NULL ) ) - { - continue; - } - - if ( pScene->InvolvesActor( pActor ) && pScene->IsPlayingBack() && pScene->IsPaused() ) - { - pScene->QueueResumePlayback(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: returns if there are scenes involving the specified actor -//----------------------------------------------------------------------------- -bool CSceneManager::IsRunningScriptedScene( CBaseFlex *pActor, bool bIgnoreInstancedScenes ) -{ - int c = m_ActiveScenes.Count(); - for ( int i = 0; i < c; i++ ) - { - CSceneEntity *pScene = m_ActiveScenes[ i ].Get(); - if ( !pScene || - !pScene->IsPlayingBack() || - ( bIgnoreInstancedScenes && dynamic_cast(pScene) != NULL ) - ) - { - continue; - } - - if ( pScene->InvolvesActor( pActor ) ) - { - return true; - } - } - return false; -} - -bool CSceneManager::IsRunningScriptedSceneAndNotPaused( CBaseFlex *pActor, bool bIgnoreInstancedScenes ) -{ - int c = m_ActiveScenes.Count(); - for ( int i = 0; i < c; i++ ) - { - CSceneEntity *pScene = m_ActiveScenes[ i ].Get(); - if ( !pScene || - !pScene->IsPlayingBack() || - pScene->IsPaused() || - ( bIgnoreInstancedScenes && dynamic_cast(pScene) != NULL ) - ) - { - continue; - } - - if ( pScene->InvolvesActor( pActor ) ) - { - return true; - } - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pActor - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CSceneManager::IsRunningScriptedSceneWithSpeech( CBaseFlex *pActor, bool bIgnoreInstancedScenes ) -{ - int c = m_ActiveScenes.Count(); - for ( int i = 0; i < c; i++ ) - { - CSceneEntity *pScene = m_ActiveScenes[ i ].Get(); - if ( !pScene || - !pScene->IsPlayingBack() || - ( bIgnoreInstancedScenes && dynamic_cast(pScene) != NULL ) - ) - { - continue; - } - - if ( pScene->InvolvesActor( pActor ) ) - { - if ( pScene->HasUnplayedSpeech() ) - return true; - } - } - return false; -} - - -bool CSceneManager::IsRunningScriptedSceneWithSpeechAndNotPaused( CBaseFlex *pActor, bool bIgnoreInstancedScenes ) -{ - int c = m_ActiveScenes.Count(); - for ( int i = 0; i < c; i++ ) - { - CSceneEntity *pScene = m_ActiveScenes[ i ].Get(); - if ( !pScene || - !pScene->IsPlayingBack() || - pScene->IsPaused() || - ( bIgnoreInstancedScenes && dynamic_cast(pScene) != NULL ) - ) - { - continue; - } - - if ( pScene->InvolvesActor( pActor ) ) - { - if ( pScene->HasUnplayedSpeech() ) - return true; - } - } - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -// *soundname - -// soundlevel - -// soundtime - -//----------------------------------------------------------------------------- -void CSceneManager::QueueRestoredSound( CBaseFlex *actor, char const *soundname, soundlevel_t soundlevel, float time_in_past ) -{ - CRestoreSceneSound e; - e.actor = actor; - Q_strncpy( e.soundname, soundname, sizeof( e.soundname ) ); - e.soundlevel = soundlevel; - e.time_in_past = time_in_past; - - m_QueuedSceneSounds.AddToTail( e ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void RemoveActorFromScriptedScenes( CBaseFlex *pActor, bool instancedscenesonly, bool nonidlescenesonly, const char *pszThisSceneOnly ) -{ - GetSceneManager()->RemoveActorFromScenes( pActor, instancedscenesonly, nonidlescenesonly, pszThisSceneOnly ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void PauseActorsScriptedScenes( CBaseFlex *pActor, bool instancedscenesonly ) -{ - GetSceneManager()->PauseActorsScenes( pActor, instancedscenesonly ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool IsInInterruptableScenes( CBaseFlex *pActor ) -{ - return GetSceneManager()->IsInInterruptableScenes( pActor ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void ResumeActorsScriptedScenes( CBaseFlex *pActor, bool instancedscenesonly ) -{ - GetSceneManager()->ResumeActorsScenes( pActor, instancedscenesonly ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void QueueActorsScriptedScenesToResume( CBaseFlex *pActor, bool instancedscenesonly ) -{ - GetSceneManager()->QueueActorsScenesToResume( pActor, instancedscenesonly ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool IsRunningScriptedScene( CBaseFlex *pActor, bool bIgnoreInstancedScenes ) -{ - return GetSceneManager()->IsRunningScriptedScene( pActor, bIgnoreInstancedScenes ); -} - -bool IsRunningScriptedSceneAndNotPaused( CBaseFlex *pActor, bool bIgnoreInstancedScenes ) -{ - return GetSceneManager()->IsRunningScriptedSceneAndNotPaused( pActor, bIgnoreInstancedScenes ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool IsRunningScriptedSceneWithSpeech( CBaseFlex *pActor, bool bIgnoreInstancedScenes ) -{ - return GetSceneManager()->IsRunningScriptedSceneWithSpeech( pActor, bIgnoreInstancedScenes ); -} - -bool IsRunningScriptedSceneWithSpeechAndNotPaused( CBaseFlex *pActor, bool bIgnoreInstancedScenes ) -{ - return GetSceneManager()->IsRunningScriptedSceneWithSpeechAndNotPaused( pActor, bIgnoreInstancedScenes ); -} - - -//=========================================================================================================== -// SCENE LIST MANAGER -//=========================================================================================================== -LINK_ENTITY_TO_CLASS( logic_scene_list_manager, CSceneListManager ); - -BEGIN_DATADESC( CSceneListManager ) - DEFINE_UTLVECTOR( m_hListManagers, FIELD_EHANDLE ), - - // Keys - DEFINE_KEYFIELD( m_iszScenes[0], FIELD_STRING, "scene0" ), - DEFINE_KEYFIELD( m_iszScenes[1], FIELD_STRING, "scene1" ), - DEFINE_KEYFIELD( m_iszScenes[2], FIELD_STRING, "scene2" ), - DEFINE_KEYFIELD( m_iszScenes[3], FIELD_STRING, "scene3" ), - DEFINE_KEYFIELD( m_iszScenes[4], FIELD_STRING, "scene4" ), - DEFINE_KEYFIELD( m_iszScenes[5], FIELD_STRING, "scene5" ), - DEFINE_KEYFIELD( m_iszScenes[6], FIELD_STRING, "scene6" ), - DEFINE_KEYFIELD( m_iszScenes[7], FIELD_STRING, "scene7" ), - DEFINE_KEYFIELD( m_iszScenes[8], FIELD_STRING, "scene8" ), - DEFINE_KEYFIELD( m_iszScenes[9], FIELD_STRING, "scene9" ), - DEFINE_KEYFIELD( m_iszScenes[10], FIELD_STRING, "scene10" ), - DEFINE_KEYFIELD( m_iszScenes[11], FIELD_STRING, "scene11" ), - DEFINE_KEYFIELD( m_iszScenes[12], FIELD_STRING, "scene12" ), - DEFINE_KEYFIELD( m_iszScenes[13], FIELD_STRING, "scene13" ), - DEFINE_KEYFIELD( m_iszScenes[14], FIELD_STRING, "scene14" ), - DEFINE_KEYFIELD( m_iszScenes[15], FIELD_STRING, "scene15" ), - - DEFINE_FIELD( m_hScenes[0], FIELD_EHANDLE ), - DEFINE_FIELD( m_hScenes[1], FIELD_EHANDLE ), - DEFINE_FIELD( m_hScenes[2], FIELD_EHANDLE ), - DEFINE_FIELD( m_hScenes[3], FIELD_EHANDLE ), - DEFINE_FIELD( m_hScenes[4], FIELD_EHANDLE ), - DEFINE_FIELD( m_hScenes[5], FIELD_EHANDLE ), - DEFINE_FIELD( m_hScenes[6], FIELD_EHANDLE ), - DEFINE_FIELD( m_hScenes[7], FIELD_EHANDLE ), - DEFINE_FIELD( m_hScenes[8], FIELD_EHANDLE ), - DEFINE_FIELD( m_hScenes[9], FIELD_EHANDLE ), - DEFINE_FIELD( m_hScenes[10], FIELD_EHANDLE ), - DEFINE_FIELD( m_hScenes[11], FIELD_EHANDLE ), - DEFINE_FIELD( m_hScenes[12], FIELD_EHANDLE ), - DEFINE_FIELD( m_hScenes[13], FIELD_EHANDLE ), - DEFINE_FIELD( m_hScenes[14], FIELD_EHANDLE ), - DEFINE_FIELD( m_hScenes[15], FIELD_EHANDLE ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Shutdown", InputShutdown ), -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSceneListManager::Activate( void ) -{ - BaseClass::Activate(); - - // Hook up scenes, but not after loading a game because they're saved. - if ( gpGlobals->eLoadType != MapLoad_LoadGame ) - { - for ( int i = 0; i < SCENE_LIST_MANAGER_MAX_SCENES; i++ ) - { - if ( m_iszScenes[i] != NULL_STRING ) - { - m_hScenes[i] = gEntList.FindEntityByName( NULL, STRING(m_iszScenes[i]) ); - if ( m_hScenes[i] ) - { - CSceneEntity *pScene = dynamic_cast(m_hScenes[i].Get()); - if ( pScene ) - { - pScene->AddListManager( this ); - } - else - { - CSceneListManager *pList = dynamic_cast(m_hScenes[i].Get()); - if ( pList ) - { - pList->AddListManager( this ); - } - else - { - Warning( "%s(%s) found an entity that wasn't a logic_choreographed_scene or logic_scene_list_manager in slot %d, named %s\n", GetDebugName(), GetClassname(), i, STRING(m_iszScenes[i]) ); - m_hScenes[i] = NULL; - } - } - } - else - { - Warning( "%s(%s) could not find scene %d, named %s\n", GetDebugName(), GetClassname(), i, STRING(m_iszScenes[i]) ); - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: A scene or manager in our list has started playing. -// Remove all scenes earlier in the list. -//----------------------------------------------------------------------------- -void CSceneListManager::SceneStarted( CBaseEntity *pSceneOrManager ) -{ - // Move backwards and call remove on all scenes / managers earlier in the list to the fired one - bool bFoundStart = false; - for ( int i = SCENE_LIST_MANAGER_MAX_SCENES-1; i >= 0; i-- ) - { - if ( !m_hScenes[i] ) - continue; - - if ( bFoundStart ) - { - RemoveScene( i ); - } - else if ( m_hScenes[i] == pSceneOrManager ) - { - bFoundStart = true; - } - } - - // Tell any managers we're within that we've started a scene - if ( bFoundStart ) - { - int c = m_hListManagers.Count(); - for ( int i = 0; i < c; i++ ) - { - if ( m_hListManagers[i] ) - { - m_hListManagers[i]->SceneStarted( this ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSceneListManager::AddListManager( CSceneListManager *pManager ) -{ - CHandle< CSceneListManager > h; - h = pManager; - // Only add it once - if ( m_hListManagers.Find( h ) == m_hListManagers.InvalidIndex() ) - { - m_hListManagers.AddToTail( h ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Shut down all scenes, and then remove this entity -//----------------------------------------------------------------------------- -void CSceneListManager::InputShutdown( inputdata_t &inputdata ) -{ - ShutdownList(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSceneListManager::ShutdownList( void ) -{ - for ( int i = 0; i < SCENE_LIST_MANAGER_MAX_SCENES; i++ ) - { - if ( m_hScenes[i] ) - { - RemoveScene(i); - } - } - - UTIL_Remove( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSceneListManager::RemoveScene( int iIndex ) -{ - CSceneEntity *pScene = dynamic_cast(m_hScenes[iIndex].Get()); - if ( pScene ) - { - // Remove the scene - UTIL_Remove( pScene ); - return; - } - - // Tell the list manager to shut down all scenes - CSceneListManager *pList = dynamic_cast(m_hScenes[iIndex].Get()); - if ( pList ) - { - pList->ShutdownList(); - } -} - -void ReloadSceneFromDisk( CBaseEntity *ent ) -{ - CSceneEntity *scene = dynamic_cast< CSceneEntity * >( ent ); - if ( !scene ) - return; - - Assert( 0 ); -} - -// Purpose: -// Input : *ent - -// Output : char const -//----------------------------------------------------------------------------- -char const *GetSceneFilename( CBaseEntity *ent ) -{ - CSceneEntity *scene = dynamic_cast< CSceneEntity * >( ent ); - if ( !scene ) - return ""; - - return STRING( scene->m_iszSceneFile ); -} - -//----------------------------------------------------------------------------- -// Purpose: Return a list of the last 5 lines of speech from NPCs for bug reports -// Input : -// Output : speech - last 5 sound files played as speech -// returns the number of sounds in the returned list -//----------------------------------------------------------------------------- - -int GetRecentNPCSpeech( recentNPCSpeech_t speech[ SPEECH_LIST_MAX_SOUNDS ] ) -{ - int i; - int num; - int index; - - // clear out the output list - for( i = 0; i < SPEECH_LIST_MAX_SOUNDS; i++ ) - { - speech[ i ].time = 0.0f; - speech[ i ].name[ 0 ] = 0; - speech[ i ].sceneName[ 0 ] = 0; - } - - // copy the sound names into the list in order they were played - num = 0; - index = speechListIndex; - for( i = 0; i < SPEECH_LIST_MAX_SOUNDS; i++ ) - { - if ( speechListSounds[ index ].name[ 0 ] ) - { - // only copy names that are not zero length - speech[ num ] = speechListSounds[ index ]; - num++; - } - - index++; - if ( index >= SPEECH_LIST_MAX_SOUNDS ) - { - index = 0; - } - } - - return num; -} - -//----------------------------------------------------------------------------- -// Purpose: Displays a list of the last 5 lines of speech from NPCs -// Input : -// Output : -//----------------------------------------------------------------------------- - -static void ListRecentNPCSpeech( void ) -{ - recentNPCSpeech_t speech[ SPEECH_LIST_MAX_SOUNDS ]; - int num; - int i; - - // get any sounds that were spoken by NPCs recently - num = GetRecentNPCSpeech( speech ); - Msg( "Recent NPC speech:\n" ); - for( i = 0; i < num; i++ ) - { - Msg( " time: %6.3f sound name: %s scene: %s\n", speech[ i ].time, speech[ i ].name, speech[ i ].sceneName ); - } - Msg( "Current time: %6.3f\n", gpGlobals->curtime ); -} - -static ConCommand ListRecentNPCSpeechCmd( "listRecentNPCSpeech", ListRecentNPCSpeech, "Displays a list of the last 5 lines of speech from NPCs.", FCVAR_DONTRECORD|FCVAR_GAMEDLL ); - -CON_COMMAND( scene_flush, "Flush all .vcds from the cache and reload from disk." ) -{ - Msg( "Reloading\n" ); - scenefilecache->Reload(); - Msg( " done\n" ); -} diff --git a/game/server/sceneentity.h b/game/server/sceneentity.h deleted file mode 100644 index 11168b55a..000000000 --- a/game/server/sceneentity.h +++ /dev/null @@ -1,47 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#ifndef SCENEENTITY_H -#define SCENEENTITY_H -#ifdef _WIN32 -#pragma once -#endif - -// List of the last 5 lines of speech from NPCs for bug reports -#define SPEECH_LIST_MAX_SOUNDS 5 - -class AI_Response; - -struct recentNPCSpeech_t -{ - float time; - char name[ 512 ]; - char sceneName[ 128 ]; -}; - -int GetRecentNPCSpeech( recentNPCSpeech_t speech[ SPEECH_LIST_MAX_SOUNDS ] ); -float InstancedScriptedScene( CBaseFlex *pActor, const char *pszScene, EHANDLE *phSceneEnt = NULL, float flPostDelay = 0.0f, bool bIsBackground = false, AI_Response *response = NULL, bool bMultiplayer = false, IRecipientFilter *filter = NULL ); -float InstancedAutoGeneratedSoundScene( CBaseFlex *pActor, char const *soundname, EHANDLE *phSceneEnt = NULL ); -void StopScriptedScene( CBaseFlex *pActor, EHANDLE hSceneEnt ); -void RemoveActorFromScriptedScenes( CBaseFlex *pActor, bool instancedscenesonly, bool nonidlescenesonly = false, const char *pszThisSceneOnly = NULL ); -void PauseActorsScriptedScenes( CBaseFlex *pActor, bool instancedscenesonly ); -void ResumeActorsScriptedScenes( CBaseFlex *pActor, bool instancedscenesonly ); -void QueueActorsScriptedScenesToResume( CBaseFlex *pActor, bool instancedscenesonly ); -bool IsRunningScriptedScene( CBaseFlex *pActor, bool bIgnoreInstancedScenes = true ); -bool IsRunningScriptedSceneAndNotPaused( CBaseFlex *pActor, bool bIgnoreInstancedScenes = true ); -bool IsRunningScriptedSceneWithSpeech( CBaseFlex *pActor, bool bIgnoreInstancedScenes = false ); -bool IsRunningScriptedSceneWithSpeechAndNotPaused( CBaseFlex *pActor, bool bIgnoreInstancedScenes = false ); -float GetSceneDuration( char const *pszScene ); -int GetSceneSpeechCount( char const *pszScene ); -bool IsInInterruptableScenes( CBaseFlex *pActor ); - -void PrecacheInstancedScene( char const *pszScene ); - -char const *GetSceneFilename( CBaseEntity *ent ); -void ReloadSceneFromDisk( CBaseEntity *ent ); - - -#endif // SCENEENTITY_H diff --git a/game/server/scratchpad_gamedll_helpers.cpp b/game/server/scratchpad_gamedll_helpers.cpp deleted file mode 100644 index feaf6ad78..000000000 --- a/game/server/scratchpad_gamedll_helpers.cpp +++ /dev/null @@ -1,95 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "scratchpad_gamedll_helpers.h" -#include "iscratchpad3d.h" -#include "player.h" -#include "collisionproperty.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -void ScratchPad_DrawWorldToScratchPad( - IScratchPad3D *pPad, - unsigned long flags ) -{ - pPad->SetRenderState( IScratchPad3D::RS_FillMode, IScratchPad3D::FillMode_Wireframe ); - - if ( flags & SPDRAWWORLD_DRAW_WORLD ) - { - engine->DrawMapToScratchPad( pPad, 0 ); - } - - if ( flags & (SPDRAWWORLD_DRAW_PLAYERS | SPDRAWWORLD_DRAW_ENTITIES) ) - { - CBaseEntity *pCur = gEntList.FirstEnt(); - while ( pCur ) - { - bool bPlayer = ( dynamic_cast< CBasePlayer* >( pCur ) != 0 ); - if ( (bPlayer && !( flags & SPDRAWWORLD_DRAW_PLAYERS )) || - (!bPlayer && !( flags & SPDRAWWORLD_DRAW_ENTITIES )) ) - { - pCur = gEntList.NextEnt( pCur ); - continue; - } - - ScratchPad_DrawEntityToScratchPad( - pPad, - flags, - pCur, - bPlayer ? Vector( 1.0, 0.5, 0 ) : Vector( 0.3, 0.3, 1.0 ) - ); - - pCur = gEntList.NextEnt( pCur ); - } - } -} - - -void ScratchPad_DrawEntityToScratchPad( - IScratchPad3D *pPad, - unsigned long flags, - CBaseEntity *pEnt, - const Vector &vColor ) -{ - // Draw the entity's bbox [todo: draw OBBs here too]. - Vector mins, maxs; - pEnt->CollisionProp()->WorldSpaceAABB( &mins, &maxs ); - - pPad->DrawWireframeBox( mins, maxs, vColor ); - - // Draw the edict's index or class? - char str[512]; - str[0] = 0; - if ( flags & SPDRAWWORLD_DRAW_EDICT_INDICES ) - { - char tempStr[512]; - Q_snprintf( tempStr, sizeof( tempStr ), "edict: %d", pEnt->entindex() ); - Q_strncat( str, tempStr, sizeof( str ), COPY_ALL_CHARACTERS ); - } - - if ( flags & SPDRAWWORLD_DRAW_ENTITY_CLASSNAMES ) - { - if ( str[0] != 0 ) - Q_strncat( str, ", ", sizeof( str ), COPY_ALL_CHARACTERS ); - - char tempStr[512]; - Q_snprintf( tempStr, sizeof( tempStr ), "class: %s", pEnt->GetClassname() ); - Q_strncat( str, tempStr, sizeof( str ), COPY_ALL_CHARACTERS ); - } - - if ( str[0] != 0 ) - { - CTextParams params; - params.m_vPos = (mins + maxs) * 0.5f; - params.m_bCentered = true; - params.m_flLetterWidth = 2; - pPad->DrawText( str, params ); - } -} - - diff --git a/game/server/scratchpad_gamedll_helpers.h b/game/server/scratchpad_gamedll_helpers.h deleted file mode 100644 index f29033750..000000000 --- a/game/server/scratchpad_gamedll_helpers.h +++ /dev/null @@ -1,40 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef SCRATCHPAD_GAMEDLL_HELPERS_H -#define SCRATCHPAD_GAMEDLL_HELPERS_H -#ifdef _WIN32 -#pragma once -#endif - - -class IScratchPad3D; - - -#define SPDRAWWORLD_DRAW_WORLD 0x001 -#define SPDRAWWORLD_DRAW_PLAYERS 0x002 // Draw player entities? -#define SPDRAWWORLD_DRAW_ENTITIES 0x004 // Draw entities other than players? -#define SPDRAWWORLD_DRAW_ENTITY_CLASSNAMES 0x008 -#define SPDRAWWORLD_DRAW_EDICT_INDICES 0x010 - -#define SPDRAWWORLD_DRAW_ALL 0xFFFFFFFF - - -// Draws the world and various things in it into the scratchpad. -// flags is a combination of the SPDRAWWORLD_ flags. -void ScratchPad_DrawWorldToScratchPad( - IScratchPad3D *pPad, - unsigned long flags ); - -// Draw a specific entity into the scratch pad. -void ScratchPad_DrawEntityToScratchPad( - IScratchPad3D *pPad, - unsigned long flags, - CBaseEntity *pEnt, - const Vector &vColor ); - - -#endif // SCRATCHPAD_GAMEDLL_HELPERS_H diff --git a/game/server/scripted.cpp b/game/server/scripted.cpp deleted file mode 100644 index 2ccace02a..000000000 --- a/game/server/scripted.cpp +++ /dev/null @@ -1,2248 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implementation of entities that cause NPCs to participate in -// scripted events. These entities find and temporarily possess NPCs -// within a given search radius. -// -// Multiple scripts with the same targetname will start frame-synchronized. -// -// Scripts will find available NPCs by name or class name and grab them -// to play the script. If the NPC is already playing a script, the -// new script may enqueue itself unless there is already a non critical -// script in the queue. -// -//=============================================================================// - -#include "cbase.h" -#include "ai_schedule.h" -#include "ai_default.h" -#include "ai_motor.h" -#include "ai_hint.h" -#include "ai_networkmanager.h" -#include "ai_network.h" -#include "engine/IEngineSound.h" -#include "animation.h" -#include "scripted.h" -#include "entitylist.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -ConVar ai_task_pre_script( "ai_task_pre_script", "0", FCVAR_NONE ); - - -// -// targetname "me" - there can be more than one with the same name, and they act in concert -// target "the_entity_I_want_to_start_playing" or "class entity_classname" will pick the closest inactive scientist -// play "name_of_sequence" -// idle "name of idle sequence to play before starting" -// moveto - if set the NPC first moves to this nodes position -// range # - only search this far to find the target -// spawnflags - (stop if blocked, stop if player seen) -// - -BEGIN_DATADESC( CAI_ScriptedSequence ) - - DEFINE_KEYFIELD( m_iszEntry, FIELD_STRING, "m_iszEntry" ), - DEFINE_KEYFIELD( m_iszPreIdle, FIELD_STRING, "m_iszIdle" ), - DEFINE_KEYFIELD( m_iszPlay, FIELD_STRING, "m_iszPlay" ), - DEFINE_KEYFIELD( m_iszPostIdle, FIELD_STRING, "m_iszPostIdle" ), - DEFINE_KEYFIELD( m_iszCustomMove, FIELD_STRING, "m_iszCustomMove" ), - DEFINE_KEYFIELD( m_iszNextScript, FIELD_STRING, "m_iszNextScript" ), - DEFINE_KEYFIELD( m_iszEntity, FIELD_STRING, "m_iszEntity" ), - DEFINE_KEYFIELD( m_fMoveTo, FIELD_INTEGER, "m_fMoveTo" ), - DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "m_flRadius" ), - DEFINE_KEYFIELD( m_flRepeat, FIELD_FLOAT, "m_flRepeat" ), - - DEFINE_FIELD( m_bIsPlayingEntry, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_bLoopActionSequence, FIELD_BOOLEAN, "m_bLoopActionSequence" ), - DEFINE_KEYFIELD( m_bSynchPostIdles, FIELD_BOOLEAN, "m_bSynchPostIdles" ), - DEFINE_KEYFIELD( m_bIgnoreGravity, FIELD_BOOLEAN, "m_bIgnoreGravity" ), - DEFINE_KEYFIELD( m_bDisableNPCCollisions, FIELD_BOOLEAN, "m_bDisableNPCCollisions" ), - - DEFINE_FIELD( m_iDelay, FIELD_INTEGER ), - DEFINE_FIELD( m_bDelayed, FIELD_BOOLEAN ), - DEFINE_FIELD( m_startTime, FIELD_TIME ), - DEFINE_FIELD( m_bWaitForBeginSequence, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_saved_effects, FIELD_INTEGER ), - DEFINE_FIELD( m_savedFlags, FIELD_INTEGER ), - DEFINE_FIELD( m_savedCollisionGroup, FIELD_INTEGER ), - - DEFINE_FIELD( m_interruptable, FIELD_BOOLEAN ), - DEFINE_FIELD( m_sequenceStarted, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hTargetEnt, FIELD_EHANDLE ), - DEFINE_FIELD( m_hNextCine, FIELD_EHANDLE ), - DEFINE_FIELD( m_hLastFoundEntity, FIELD_EHANDLE ), - DEFINE_FIELD( m_hForcedTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_bDontCancelOtherSequences, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bForceSynch, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_bThinking, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bInitiatedSelfDelete, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_bIsTeleportingDueToMoveTo, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_matInteractionPosition, FIELD_VMATRIX ), - DEFINE_FIELD( m_hInteractionRelativeEntity, FIELD_EHANDLE ), - - DEFINE_FIELD( m_bTargetWasAsleep, FIELD_BOOLEAN ), - - // Function Pointers - DEFINE_THINKFUNC( ScriptThink ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "MoveToPosition", InputMoveToPosition ), - DEFINE_INPUTFUNC( FIELD_VOID, "BeginSequence", InputBeginSequence ), - DEFINE_INPUTFUNC( FIELD_VOID, "CancelSequence", InputCancelSequence ), - - DEFINE_KEYFIELD( m_iPlayerDeathBehavior, FIELD_INTEGER, "onplayerdeath" ), - DEFINE_INPUTFUNC( FIELD_VOID, "ScriptPlayerDeath", InputScriptPlayerDeath ), - - // Outputs - DEFINE_OUTPUT(m_OnBeginSequence, "OnBeginSequence"), - DEFINE_OUTPUT(m_OnEndSequence, "OnEndSequence"), - DEFINE_OUTPUT(m_OnPostIdleEndSequence, "OnPostIdleEndSequence"), - DEFINE_OUTPUT(m_OnCancelSequence, "OnCancelSequence"), - DEFINE_OUTPUT(m_OnCancelFailedSequence, "OnCancelFailedSequence"), - DEFINE_OUTPUT(m_OnScriptEvent[0], "OnScriptEvent01"), - DEFINE_OUTPUT(m_OnScriptEvent[1], "OnScriptEvent02"), - DEFINE_OUTPUT(m_OnScriptEvent[2], "OnScriptEvent03"), - DEFINE_OUTPUT(m_OnScriptEvent[3], "OnScriptEvent04"), - DEFINE_OUTPUT(m_OnScriptEvent[4], "OnScriptEvent05"), - DEFINE_OUTPUT(m_OnScriptEvent[5], "OnScriptEvent06"), - DEFINE_OUTPUT(m_OnScriptEvent[6], "OnScriptEvent07"), - DEFINE_OUTPUT(m_OnScriptEvent[7], "OnScriptEvent08"), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( scripted_sequence, CAI_ScriptedSequence ); -#define CLASSNAME "scripted_sequence" - -//----------------------------------------------------------------------------- -// Purpose: Cancels the given scripted sequence. -// Input : pentCine - -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::ScriptEntityCancel( CBaseEntity *pentCine, bool bPretendSuccess ) -{ - // make sure they are a scripted_sequence - if ( FClassnameIs( pentCine, CLASSNAME ) ) - { - CAI_ScriptedSequence *pCineTarget = (CAI_ScriptedSequence *)pentCine; - - // make sure they have a NPC in mind for the script - CBaseEntity *pEntity = pCineTarget->GetTarget(); - CAI_BaseNPC *pTarget = NULL; - if ( pEntity ) - pTarget = pEntity->MyNPCPointer(); - - if (pTarget) - { - // make sure their NPC is actually playing a script - if ( pTarget->m_NPCState == NPC_STATE_SCRIPT ) - { - // tell them do die - pTarget->m_scriptState = CAI_BaseNPC::SCRIPT_CLEANUP; - - // We have to save off the flags here, because the NPC's m_hCine is cleared in CineCleanup() - int iSavedFlags = (pTarget->m_hCine ? pTarget->m_hCine->m_savedFlags : 0); - -#ifdef HL1_DLL - //if we didn't have FL_FLY before the script, remove it - // for some reason hl2 doesn't have to do this *before* - // restoring the position ( which checks FL_FLY ) in CineCleanup - // Let's not risk breaking anything at this stage and just remove it. - pCineTarget->FixFlyFlag( pTarget, iSavedFlags ); -#endif - // do it now - pTarget->CineCleanup( ); - pCineTarget->FixScriptNPCSchedule( pTarget, iSavedFlags ); - } - else - { - // Robin HACK: If a script is started and then cancelled before an NPC gets to - // think, we have to manually clear it out of scripted state, or it'll never recover. - pCineTarget->SetTarget( NULL ); - pTarget->SetEffects( pCineTarget->m_saved_effects ); - pTarget->m_hCine = NULL; - pTarget->SetTarget( NULL ); - pTarget->SetGoalEnt( NULL ); - pTarget->SetIdealState( NPC_STATE_IDLE ); - } - } - - // FIXME: this needs to be done in a cine cleanup function - pCineTarget->m_iDelay = 0; - - if ( bPretendSuccess ) - { - // We need to pretend that this sequence actually finished fully - pCineTarget->m_OnEndSequence.FireOutput(NULL, pCineTarget); - pCineTarget->m_OnPostIdleEndSequence.FireOutput(NULL, pCineTarget); - } - else - { - // Fire the cancel - pCineTarget->m_OnCancelSequence.FireOutput(NULL, pCineTarget); - - if ( pCineTarget->m_startTime == 0 ) - { - // If start time is 0, this sequence never actually ran. Fire the failed output. - pCineTarget->m_OnCancelFailedSequence.FireOutput(NULL, pCineTarget); - } - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Called before spawning, after keyvalues have been parsed. -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::Spawn( void ) -{ - SetSolid( SOLID_NONE ); - - // - // If we have no name or we are set to start immediately, find the NPC and - // have them move to their script position now. - // - if ( !GetEntityName() || ( m_spawnflags & SF_SCRIPT_START_ON_SPAWN ) ) - { - StartThink(); - SetNextThink( gpGlobals->curtime + 1.0f ); - - // - // If we have a name, wait for a BeginSequence input to play the - // action animation. Otherwise, we'll play the action animation - // as soon as the NPC reaches the script position. - // - if ( GetEntityName() != NULL_STRING ) - { - m_bWaitForBeginSequence = true; - } - } - - if ( m_spawnflags & SF_SCRIPT_NOINTERRUPT ) - { - m_interruptable = false; - } - else - { - m_interruptable = true; - } - - m_sequenceStarted = false; - m_startTime = 0; - m_hNextCine = NULL; - - m_hLastFoundEntity = NULL; -} - -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::UpdateOnRemove(void) -{ - ScriptEntityCancel( this ); - BaseClass::UpdateOnRemove(); -} - -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::StartThink() -{ - m_sequenceStarted = false; - m_bThinking = true; - SetThink( &CAI_ScriptedSequence::ScriptThink ); -} - -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::StopThink() -{ - if ( m_bThinking ) - { - Assert( !m_bInitiatedSelfDelete ); - SetThink( NULL); - m_bThinking = false; - } -} -//----------------------------------------------------------------------------- -// Purpose: Returns true if this scripted sequence can possess entities -// regardless of state. -//----------------------------------------------------------------------------- -bool CAI_ScriptedSequence::FCanOverrideState( void ) -{ - if ( m_spawnflags & SF_SCRIPT_OVERRIDESTATE ) - return true; - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Fires a script event by number. -// Input : nEvent - One based index of the script event from the , from 1 to 8. -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::FireScriptEvent( int nEvent ) -{ - if ( ( nEvent >= 1 ) && ( nEvent <= MAX_SCRIPT_EVENTS ) ) - { - m_OnScriptEvent[nEvent - 1].FireOutput( this, this ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that causes the NPC to move to the script position. -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::InputMoveToPosition( inputdata_t &inputdata ) -{ - if ( m_bInitiatedSelfDelete ) - return; - - // Have I already grabbed an NPC? - CBaseEntity *pEntity = GetTarget(); - CAI_BaseNPC *pTarget = NULL; - - if ( pEntity ) - { - pTarget = pEntity->MyNPCPointer(); - } - - if ( pTarget != NULL ) - { - // Yes, are they already playing this script? - if ( pTarget->m_scriptState == CAI_BaseNPC::SCRIPT_PLAYING || pTarget->m_scriptState == CAI_BaseNPC::SCRIPT_POST_IDLE ) - { - // Yes, see if we can enqueue ourselves. - if ( pTarget->CanPlaySequence( FCanOverrideState(), SS_INTERRUPT_BY_NAME ) ) - { - StartScript(); - m_bWaitForBeginSequence = true; - } - } - - // No, presumably they are moving to position or waiting for the BeginSequence input. - } - else - { - // No, grab the NPC but make them wait until BeginSequence is fired. They'll play - // their pre-action idle animation until BeginSequence is fired. - StartThink(); - SetNextThink( gpGlobals->curtime ); - m_bWaitForBeginSequence = true; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that activates the scripted sequence. -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::InputBeginSequence( inputdata_t &inputdata ) -{ - if ( m_bInitiatedSelfDelete ) - return; - - // Start the script as soon as possible. - m_bWaitForBeginSequence = false; - - // do I already know who I should use? - CBaseEntity *pEntity = GetTarget(); - CAI_BaseNPC *pTarget = NULL; - - if ( !pEntity && m_hForcedTarget ) - { - if ( FindEntity() ) - { - pEntity = GetTarget(); - } - } - - if ( pEntity ) - { - pTarget = pEntity->MyNPCPointer(); - } - - if ( pTarget ) - { - // Are they already playing a script? - if ( pTarget->m_scriptState == CAI_BaseNPC::SCRIPT_PLAYING || pTarget->m_scriptState == CAI_BaseNPC::SCRIPT_POST_IDLE ) - { - // See if we can enqueue ourselves after the current script. - if ( pTarget->CanPlaySequence( FCanOverrideState(), SS_INTERRUPT_BY_NAME ) ) - { - StartScript(); - } - } - } - else - { - // if not, try finding them - StartThink(); - - // Because we are directly calling the new "think" function ScriptThink, assume we're done - // This fixes the following bug (along with the WokeThisTick() code herein: - // A zombie is created in the asleep state and then, the mapper fires both Wake and BeginSequence - // messages to have it jump up out of the slime, e.g. What happens before this change is that - // the Wake code removed EF_NODRAW, but so the zombie is transmitted to the client, but the script - // hasn't started and won't start until the next Think time (2 ticks on xbox) at which time the - // actual sequence starts causing the zombie to quickly lie down. - // The changes here are to track what tick we "awoke" on and get rid of the lag between Wake and - // ScriptThink by actually calling ScriptThink directly on the same frame and checking for the - // zombie having woken up and been instructed to play a sequence in the same frame. - SetNextThink( TICK_NEVER_THINK ); - ScriptThink(); - } - -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that activates the scripted sequence. -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::InputCancelSequence( inputdata_t &inputdata ) -{ - if ( m_bInitiatedSelfDelete ) - return; - - // - // We don't call CancelScript because entity I/O will handle dispatching - // this input to all other scripts with our same name. - // - DevMsg( 2, "InputCancelScript: Cancelling script '%s'\n", STRING( m_iszPlay )); - StopThink(); - ScriptEntityCancel( this ); -} - -void CAI_ScriptedSequence::InputScriptPlayerDeath( inputdata_t &inputdata ) -{ - if ( m_iPlayerDeathBehavior == SCRIPT_CANCEL ) - { - if ( m_bInitiatedSelfDelete ) - return; - - // - // We don't call CancelScript because entity I/O will handle dispatching - // this input to all other scripts with our same name. - // - DevMsg( 2, "InputCancelScript: Cancelling script '%s'\n", STRING( m_iszPlay )); - StopThink(); - ScriptEntityCancel( this ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns true if it is time for this script to start, false if the -// NPC should continue waiting. -// -// Scripts wait for two reasons: -// -// 1. To frame-syncronize with other scripts of the same name. -// 2. To wait indefinitely for the BeginSequence input after the NPC -// moves to the script position. -//----------------------------------------------------------------------------- -bool CAI_ScriptedSequence::IsTimeToStart( void ) -{ - Assert( !m_bWaitForBeginSequence ); - - return ( m_iDelay == 0 ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns true if the script is still waiting to call StartScript() -//----------------------------------------------------------------------------- -bool CAI_ScriptedSequence::IsWaitingForBegin( void ) -{ - return m_bWaitForBeginSequence; -} - -//----------------------------------------------------------------------------- -// Purpose: This doesn't really make sense since only MOVETYPE_PUSH get 'Blocked' events -// Input : pOther - The entity blocking us. -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::Blocked( CBaseEntity *pOther ) -{ -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pOther - The entity touching us. -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::Touch( CBaseEntity *pOther ) -{ -/* - DevMsg( 2, "Cine Touch\n" ); - if (m_pentTarget && OFFSET(pOther->pev) == OFFSET(m_pentTarget)) - { - CAI_BaseNPC *pTarget = GetClassPtr((CAI_BaseNPC *)VARS(m_pentTarget)); - pTarget->m_NPCState == NPC_STATE_SCRIPT; - } -*/ -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::Die( void ) -{ - SetThink( &CAI_ScriptedSequence::SUB_Remove ); - m_bThinking = false; - m_bInitiatedSelfDelete = true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::Pain( void ) -{ -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : eMode - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -CAI_BaseNPC *CAI_ScriptedSequence::FindScriptEntity( ) -{ - CAI_BaseNPC *pEnqueueNPC = NULL; - - CBaseEntity *pEntity; - int interrupt; - if ( m_hForcedTarget ) - { - interrupt = SS_INTERRUPT_BY_NAME; - pEntity = m_hForcedTarget; - } - else - { - interrupt = SS_INTERRUPT_BY_NAME; - - pEntity = gEntList.FindEntityByNameWithin( m_hLastFoundEntity, STRING( m_iszEntity ), GetAbsOrigin(), m_flRadius ); - if (!pEntity) - { - pEntity = gEntList.FindEntityByClassnameWithin( m_hLastFoundEntity, STRING( m_iszEntity ), GetAbsOrigin(), m_flRadius ); - interrupt = SS_INTERRUPT_BY_CLASS; - } - } - - while ( pEntity != NULL ) - { - CAI_BaseNPC *pNPC = pEntity->MyNPCPointer( ); - if ( pNPC ) - { - // - // If they can play the sequence... - // - CanPlaySequence_t eCanPlay = pNPC->CanPlaySequence( FCanOverrideState(), interrupt ); - if ( eCanPlay == CAN_PLAY_NOW ) - { - // If they can play it now, we're done! - return pNPC; - } - else if ( eCanPlay == CAN_PLAY_ENQUEUED ) - { - // They can play it, but only enqueued. We'll use them as a last resort. - pEnqueueNPC = pNPC; - } - else if (!(m_spawnflags & SF_SCRIPT_NO_COMPLAINTS)) - { - // They cannot play the script. - DevMsg( "Found %s, but can't play!\n", STRING( m_iszEntity )); - } - } - - if ( m_hForcedTarget ) - { - Warning( "Code forced %s(%s), to be the target of scripted sequence %s, but it can't play it.\n", - pEntity->GetClassname(), pEntity->GetDebugName(), GetDebugName() ); - pEntity = NULL; - UTIL_Remove( this ); - return NULL; - } - else - { - if ( interrupt == SS_INTERRUPT_BY_NAME ) - pEntity = gEntList.FindEntityByNameWithin( pEntity, STRING( m_iszEntity ), GetAbsOrigin(), m_flRadius ); - else - pEntity = gEntList.FindEntityByClassnameWithin( pEntity, STRING( m_iszEntity ), GetAbsOrigin(), m_flRadius ); - } - } - - // - // If we found an NPC that will enqueue the script, use them. - // - if ( pEnqueueNPC != NULL ) - { - return pEnqueueNPC; - } - - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_ScriptedSequence::FindEntity( void ) -{ - CAI_BaseNPC *pTarget = FindScriptEntity( ); - - if ( (m_spawnflags & SF_SCRIPT_SEARCH_CYCLICALLY)) - { - // next time this is called, start searching from the one found last time - m_hLastFoundEntity = pTarget; - } - - SetTarget( pTarget ); - - return pTarget != NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Make the entity enter a scripted sequence. -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::StartScript( void ) -{ - CBaseEntity *pEntity = GetTarget(); - CAI_BaseNPC *pTarget = NULL; - if ( pEntity ) - pTarget = pEntity->MyNPCPointer(); - - if ( pTarget ) - { - pTarget->RemoveSpawnFlags( SF_NPC_WAIT_FOR_SCRIPT ); - - // - // If the NPC is in another script, just enqueue ourselves and bail out. - // We'll possess the NPC when the current script finishes with the NPC. - // Note that we only enqueue one deep currently, so if there is someone - // else in line we'll stomp them. - // - if ( pTarget->m_hCine != NULL ) - { - if ( pTarget->m_hCine->m_hNextCine != NULL ) - { - // - // Kicking another script out of the queue. - // - CAI_ScriptedSequence *pCine = ( CAI_ScriptedSequence * )pTarget->m_hCine->m_hNextCine.Get(); - - if (pTarget->m_hCine->m_hNextCine != pTarget->m_hCine) - { - // Don't clear the currently playing script's target! - pCine->SetTarget( NULL ); - } - DevMsg( 2, "script \"%s\" kicking script \"%s\" out of the queue\n", GetDebugName(), pCine->GetDebugName() ); - } - - pTarget->m_hCine->m_hNextCine = this; - return; - } - - // - // If no next script is specified, clear it out so other scripts can enqueue themselves - // after us. - // - if ( !m_iszNextScript ) - { - m_hNextCine = NULL; - } - - // UNDONE: Do this to sync up multi-entity scripts? - //pTarget->SetNextThink( gpGlobals->curtime ); - - pTarget->SetGoalEnt( this ); - pTarget->ForceDecisionThink(); - pTarget->m_hCine = this; - pTarget->SetTarget( this ); - - // Notify the NPC tat we're stomping them into a scene! - pTarget->OnStartScene(); - - { - m_bTargetWasAsleep = ( pTarget->GetSleepState() != AISS_AWAKE ) ? true : false; - bool justAwoke = pTarget->WokeThisTick(); - if ( m_bTargetWasAsleep || justAwoke ) - { - // Note, Wake() will remove the EF_NODRAW flag, but if we are starting a seq on a hidden entity - // we don't want it to draw on the client until the sequence actually starts to play - // Make sure it stays hidden!!! - if ( m_bTargetWasAsleep ) - { - pTarget->Wake(); - } - m_bTargetWasAsleep = true; - - // Even if awakened this frame, temporarily keep the entity hidden for now - pTarget->AddEffects( EF_NODRAW ); - } - } - - // If the entity was asleep at the start, make sure we don't make it invisible - // AFTER the script finishes (can't think of a case where you'd want that to happen) - m_saved_effects = pTarget->GetEffects() & ~EF_NODRAW; - pTarget->AddEffects( GetEffects() ); - m_savedFlags = pTarget->GetFlags(); - m_savedCollisionGroup = pTarget->GetCollisionGroup(); - - if ( m_bDisableNPCCollisions ) - { - pTarget->SetCollisionGroup( COLLISION_GROUP_NPC_SCRIPTED ); - } - - switch (m_fMoveTo) - { - case CINE_MOVETO_WAIT: - case CINE_MOVETO_WAIT_FACING: - pTarget->m_scriptState = CAI_BaseNPC::SCRIPT_WAIT; - - if ( m_bIgnoreGravity ) - { - pTarget->AddFlag( FL_FLY ); - pTarget->SetGroundEntity( NULL ); - } - - break; - - case CINE_MOVETO_WALK: - pTarget->m_scriptState = CAI_BaseNPC::SCRIPT_WALK_TO_MARK; - break; - - case CINE_MOVETO_RUN: - pTarget->m_scriptState = CAI_BaseNPC::SCRIPT_RUN_TO_MARK; - break; - - case CINE_MOVETO_CUSTOM: - pTarget->m_scriptState = CAI_BaseNPC::SCRIPT_CUSTOM_MOVE_TO_MARK; - break; - - case CINE_MOVETO_TELEPORT: - m_bIsTeleportingDueToMoveTo = true; - pTarget->Teleport( &GetAbsOrigin(), NULL, &vec3_origin ); - m_bIsTeleportingDueToMoveTo = false; - pTarget->GetMotor()->SetIdealYaw( GetLocalAngles().y ); - pTarget->SetLocalAngularVelocity( vec3_angle ); - pTarget->AddEffects( EF_NOINTERP ); - QAngle angles = pTarget->GetLocalAngles(); - angles.y = GetLocalAngles().y; - pTarget->SetLocalAngles( angles ); - pTarget->m_scriptState = CAI_BaseNPC::SCRIPT_WAIT; - - if ( m_bIgnoreGravity ) - { - pTarget->AddFlag( FL_FLY ); - pTarget->SetGroundEntity( NULL ); - } - - // UNDONE: Add a flag to do this so people can fixup physics after teleporting NPCs - //pTarget->SetGroundEntity( NULL ); - break; - } - //DevMsg( 2, "\"%s\" found and used (INT: %s)\n", STRING( pTarget->m_iName ), FBitSet(m_spawnflags, SF_SCRIPT_NOINTERRUPT)?"No":"Yes" ); - - - // Wait until all scripts of the same name are ready to play. - m_bDelayed = false; - DelayStart( true ); - - pTarget->SetIdealState(NPC_STATE_SCRIPT); - - // FIXME: not sure why this is happening, or what to do about truely dormant NPCs - if ( pTarget->IsEFlagSet( EFL_NO_THINK_FUNCTION ) && pTarget->GetNextThink() != TICK_NEVER_THINK ) - { - DevWarning( "scripted_sequence %d:%s - restarting dormant entity %d:%s : %.1f:%.1f\n", entindex(), GetDebugName(), pTarget->entindex(), pTarget->GetDebugName(), gpGlobals->curtime, pTarget->GetNextThink() ); - pTarget->SetNextThink( gpGlobals->curtime ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: First think after activation. Grabs an NPC and makes it do things. -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::ScriptThink( void ) -{ - if ( g_pAINetworkManager && !g_pAINetworkManager->IsInitialized() ) - { - SetNextThink( gpGlobals->curtime + 0.1f ); - } - else if (FindEntity()) - { - StartScript( ); - DevMsg( 2, "scripted_sequence %d:\"%s\" using NPC %d:\"%s\"(%s)\n", entindex(), GetDebugName(), GetTarget()->entindex(), GetTarget()->GetEntityName().ToCStr(), STRING( m_iszEntity ) ); - } - else - { - CancelScript( ); - DevMsg( 2, "scripted_sequence %d:\"%s\" can't find NPC \"%s\"\n", entindex(), GetDebugName(), STRING( m_iszEntity ) ); - // FIXME: just trying again is bad. This should fire an output instead. - // FIXME: Think about puting output triggers in both StartScript() and CancelScript(). - SetNextThink( gpGlobals->curtime + 1.0f ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Callback for firing the begin sequence output. Called by the NPC that -// is running the script as it starts the action seqeunce. -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::OnBeginSequence( void ) -{ - m_OnBeginSequence.FireOutput( this, this ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Look up a sequence name and setup the target NPC to play it. -// Input : pTarget - -// iszSeq - -// completeOnEmpty - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_ScriptedSequence::StartSequence( CAI_BaseNPC *pTarget, string_t iszSeq, bool completeOnEmpty ) -{ - Assert( pTarget ); - m_sequenceStarted = true; - m_bIsPlayingEntry = (iszSeq == m_iszEntry); - - if ( !iszSeq && completeOnEmpty ) - { - SequenceDone( pTarget ); - return false; - } - - int nSequence = pTarget->LookupSequence( STRING( iszSeq ) ); - if (nSequence == -1) - { - Warning( "%s: unknown scripted sequence \"%s\"\n", pTarget->GetDebugName(), STRING( iszSeq )); - nSequence = 0; - } - - // look for the activity that this represents - Activity act = pTarget->GetSequenceActivity( nSequence ); - if (act == ACT_INVALID) - act = ACT_IDLE; - - pTarget->SetActivityAndSequence( act, nSequence, act, act ); - - // If the target was hidden even though we woke it up, only make it drawable if we're not still on the preidle seq... - if ( m_bTargetWasAsleep && - iszSeq != m_iszPreIdle ) - { - m_bTargetWasAsleep = false; - // Show it - pTarget->RemoveEffects( EF_NODRAW ); - // Don't blend... - pTarget->AddEffects( EF_NOINTERP ); - } - //DevMsg( 2, "%s (%s): started \"%s\":INT:%s\n", STRING( pTarget->m_iName ), pTarget->GetClassname(), STRING( iszSeq), (m_spawnflags & SF_SCRIPT_NOINTERRUPT) ? "No" : "Yes" ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Called when a scripted sequence is ready to start playing the sequence -// Input : pNPC - Pointer to the NPC that the sequence possesses. -//----------------------------------------------------------------------------- - -void CAI_ScriptedSequence::SynchronizeSequence( CAI_BaseNPC *pNPC ) -{ - //Msg("%s (for %s) called SynchronizeSequence() at %0.2f\n", GetTarget()->GetDebugName(), GetDebugName(), gpGlobals->curtime); - - Assert( m_iDelay == 0 ); - Assert( m_bWaitForBeginSequence == false ); - m_bForceSynch = false; - - // Reset cycle position - float flCycleRate = pNPC->GetSequenceCycleRate( pNPC->GetSequence() ); - float flInterval = gpGlobals->curtime - m_startTime; - - // Msg("%.2f \"%s\" %s : %f (%f): interval %f\n", gpGlobals->curtime, GetEntityName().ToCStr(), pNPC->GetClassname(), pNPC->m_flAnimTime.Get(), m_startTime, flInterval ); - //Assert( flInterval >= 0.0 && flInterval <= 0.15 ); - flInterval = clamp( flInterval, 0, 0.15 ); - - if (flInterval == 0) - return; - - // do the movement for the missed portion of the sequence - pNPC->SetCycle( 0.0f ); - pNPC->AutoMovement( flInterval ); - - // reset the cycle to a common basis - pNPC->SetCycle( flInterval * flCycleRate ); -} - -//----------------------------------------------------------------------------- -// Purpose: Moves to the next action sequence if the scripted_sequence wants to, -// or returns true if it wants to leave the action sequence -//----------------------------------------------------------------------------- -bool CAI_ScriptedSequence::FinishedActionSequence( CAI_BaseNPC *pNPC ) -{ - // Restart the action sequence when the entry finishes, or when the action - // finishes and we're set to loop it. - if ( IsPlayingEntry() ) - { - if ( GetEntityName() != NULL_STRING ) - { - // Force all matching ss's to synchronize their action sequences - SynchNewSequence( CAI_BaseNPC::SCRIPT_PLAYING, m_iszPlay, true ); - } - else - { - StartSequence( pNPC, m_iszPlay, true ); - } - return false; - } - - // Let the core action sequence continue to loop - if ( ShouldLoopActionSequence() ) - { - // If the NPC has reached post idle state, we need to stop looping the action sequence - if ( pNPC->m_scriptState == CAI_BaseNPC::SCRIPT_POST_IDLE ) - return true; - - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Called when a scripted sequence animation sequence is done playing -// (or when an AI Scripted Sequence doesn't supply an animation sequence -// to play). -// Input : pNPC - Pointer to the NPC that the sequence possesses. -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::SequenceDone( CAI_BaseNPC *pNPC ) -{ - //DevMsg( 2, "Sequence %s finished\n", STRING( pNPC->m_hCine->m_iszPlay ) ); - - //Msg("%s SequenceDone() at %0.2f\n", pNPC->GetDebugName(), gpGlobals->curtime ); - - // If we're part of a synchronised post-idle sequence, we need to do things differently - if ( m_bSynchPostIdles && GetEntityName() != NULL_STRING ) - { - // If we're already in POST_IDLE state, then one of the other scripted - // sequences we're synching with has already kicked us into running - // the post idle sequence, so we do nothing. - if ( pNPC->m_scriptState != CAI_BaseNPC::SCRIPT_POST_IDLE ) - { - if ( ( m_iszPostIdle != NULL_STRING ) && ( m_hNextCine == NULL ) ) - { - SynchNewSequence( CAI_BaseNPC::SCRIPT_POST_IDLE, m_iszPostIdle, true ); - } - else - { - PostIdleDone( pNPC ); - } - } - } - else - { - // - // If we have a post idle set, and no other script is in the queue for this - // NPC, start playing the idle now. - // - if ( ( m_iszPostIdle != NULL_STRING ) && ( m_hNextCine == NULL ) ) - { - // - // First time we've gotten here for this script. Start playing the post idle - // if one is specified. - // - pNPC->m_scriptState = CAI_BaseNPC::SCRIPT_POST_IDLE; - StartSequence( pNPC, m_iszPostIdle, false ); // false to prevent recursion here! - } - else - { - PostIdleDone( pNPC ); - } - } - - m_OnEndSequence.FireOutput(NULL, this); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::SynchNewSequence( CAI_BaseNPC::SCRIPTSTATE newState, string_t iszSequence, bool bSynchOtherScenes ) -{ - // Do we need to synchronize all our matching scripted scenes? - if ( bSynchOtherScenes ) - { - //Msg("%s (for %s) forcing synch of %s at %0.2f\n", GetTarget()->GetDebugName(), GetDebugName(), iszSequence, gpGlobals->curtime); - - CBaseEntity *pentCine = gEntList.FindEntityByName( NULL, GetEntityName(), NULL ); - while ( pentCine ) - { - CAI_ScriptedSequence *pScene = dynamic_cast(pentCine); - if ( pScene && pScene != this ) - { - pScene->SynchNewSequence( newState, iszSequence, false ); - } - pentCine = gEntList.FindEntityByName( pentCine, GetEntityName(), NULL ); - } - } - - // Now force this one to start the post idle? - if ( !GetTarget() ) - return; - CAI_BaseNPC *pNPC = GetTarget()->MyNPCPointer(); - if ( !pNPC ) - return; - - //Msg("%s (for %s) starting %s seq at %0.2f\n", pNPC->GetDebugName(), GetDebugName(), iszSequence, gpGlobals->curtime); - - m_startTime = gpGlobals->curtime; - pNPC->m_scriptState = newState; - StartSequence( pNPC, iszSequence, false ); - - // Force the NPC to synchronize animations on their next think - m_bForceSynch = true; -} - -//----------------------------------------------------------------------------- -// Purpose: Called when a scripted sequence animation sequence is done playing -// (or when an AI Scripted Sequence doesn't supply an animation sequence -// to play). -// Input : pNPC - Pointer to the NPC that the sequence possesses. -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::PostIdleDone( CAI_BaseNPC *pNPC ) -{ - // - // If we're set to keep the NPC in a scripted idle, hack them back into the script, - // but allow another scripted sequence to take control of the NPC if it wants to, - // unless another script has stolen them from us. - // - if ( ( m_iszPostIdle != NULL_STRING ) && ( m_spawnflags & SF_SCRIPT_LOOP_IN_POST_IDLE ) && ( m_hNextCine == NULL ) ) - { - // - // First time we've gotten here for this script. Start playing the post idle - // if one is specified. - // Only do so if we're selected, to prevent spam - if ( pNPC->m_debugOverlays & OVERLAY_NPC_SELECTED_BIT ) - { - DevMsg( 2, "Post Idle %s finished for %s\n", STRING( pNPC->m_hCine->m_iszPostIdle ), pNPC->GetDebugName() ); - } - - pNPC->m_scriptState = CAI_BaseNPC::SCRIPT_POST_IDLE; - StartSequence( pNPC, m_iszPostIdle, false ); - } - else - { - if ( !( m_spawnflags & SF_SCRIPT_REPEATABLE ) ) - { - SetThink( &CAI_ScriptedSequence::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 0.1f ); - m_bThinking = false; - m_bInitiatedSelfDelete = true; - } - - // - // This is done so that another sequence can take over the NPC when triggered - // by the first. - // - pNPC->CineCleanup(); - - // We have to pass in the flags here, because the NPC's m_hCine was cleared in CineCleanup() - FixScriptNPCSchedule( pNPC, m_savedFlags ); - - // - // If another script is waiting to grab this NPC, start the next script - // immediately. - // - if ( m_hNextCine != NULL ) - { - CAI_ScriptedSequence *pNextCine = ( CAI_ScriptedSequence * )m_hNextCine.Get(); - - // - // Don't link ourselves in if we are going to be deleted. - // TODO: use EHANDLEs instead of pointers to scripts! - // - if ( ( pNextCine != this ) || ( m_spawnflags & SF_SCRIPT_REPEATABLE ) ) - { - pNextCine->SetTarget( pNPC ); - pNextCine->StartScript(); - } - } - } - - //Msg("%s finished post idle at %0.2f\n", pNPC->GetDebugName(), gpGlobals->curtime ); - m_OnPostIdleEndSequence.FireOutput(NULL, this); -} - - -//----------------------------------------------------------------------------- -// Purpose: When a NPC finishes a scripted sequence, we have to fix up its state -// and schedule for it to return to a normal AI NPC. -// Scripted sequences just dirty the Schedule and drop the NPC in Idle State. -// Input : *pNPC - -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::FixScriptNPCSchedule( CAI_BaseNPC *pNPC, int iSavedCineFlags ) -{ - if ( pNPC->GetIdealState() != NPC_STATE_DEAD ) - { - pNPC->SetIdealState( NPC_STATE_IDLE ); - } - - if ( pNPC == NULL ) - return; - - FixFlyFlag( pNPC, iSavedCineFlags ); - - pNPC->ClearSchedule( "Finished scripted sequence" ); -} - -void CAI_ScriptedSequence::FixFlyFlag( CAI_BaseNPC *pNPC, int iSavedCineFlags ) -{ - //Adrian: We NEED to clear this or the NPC's FL_FLY flag will never be removed cause of ClearSchedule! - if ( pNPC->GetTask() && ( pNPC->GetTask()->iTask == TASK_PLAY_SCRIPT || pNPC->GetTask()->iTask == TASK_PLAY_SCRIPT_POST_IDLE ) ) - { - if ( !(iSavedCineFlags & FL_FLY) ) - { - if ( pNPC->GetFlags() & FL_FLY ) - { - pNPC->RemoveFlag( FL_FLY ); - } - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : fAllow - -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::AllowInterrupt( bool fAllow ) -{ - if ( m_spawnflags & SF_SCRIPT_NOINTERRUPT ) - return; - m_interruptable = fAllow; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_ScriptedSequence::CanInterrupt( void ) -{ - if ( !m_interruptable ) - return false; - - CBaseEntity *pTarget = GetTarget(); - - if ( pTarget != NULL && pTarget->IsAlive() ) - return true; - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::RemoveIgnoredConditions( void ) -{ - if ( CanInterrupt() ) - { - return; - } - - CBaseEntity *pEntity = GetTarget(); - if ( pEntity == NULL ) - { - return; - } - - CAI_BaseNPC *pTarget = pEntity->MyNPCPointer(); - if ( pTarget == NULL ) - { - return; - } - - - if ( pTarget ) - { - pTarget->ClearCondition(COND_LIGHT_DAMAGE); - pTarget->ClearCondition(COND_HEAVY_DAMAGE); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns true if another script is allowed to enqueue itself after -// this script. The enqueued script will begin immediately after the -// current script without dropping the NPC into AI. -//----------------------------------------------------------------------------- -bool CAI_ScriptedSequence::CanEnqueueAfter( void ) -{ - if ( m_hNextCine == NULL ) - { - return true; - } - - if ( m_iszNextScript != NULL_STRING ) - { - DevMsg( 2, "%s is specified as the 'Next Script' and cannot be kicked out of the queue\n", m_hNextCine->GetDebugName() ); - return false; - } - - if ( !m_hNextCine->HasSpawnFlags( SF_SCRIPT_HIGH_PRIORITY ) ) - { - return true; - } - - DevMsg( 2, "%s is a priority script and cannot be kicked out of the queue\n", m_hNextCine->GetDebugName() ); - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::StopActionLoop( bool bStopSynchronizedScenes ) -{ - // Stop looping our action sequence. Next time the loop finishes, - // we'll move to the post idle sequence instead. - m_bLoopActionSequence = false; - - // If we have synchronized scenes, and we're supposed to stop them, do so - if ( !bStopSynchronizedScenes || GetEntityName() == NULL_STRING ) - return; - - CBaseEntity *pentCine = gEntList.FindEntityByName( NULL, GetEntityName(), NULL ); - while ( pentCine ) - { - CAI_ScriptedSequence *pScene = dynamic_cast(pentCine); - if ( pScene && pScene != this ) - { - pScene->StopActionLoop( false ); - } - - pentCine = gEntList.FindEntityByName( pentCine, GetEntityName(), NULL ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Code method of forcing a scripted sequence entity to use a particular NPC. -// Useful when you don't know if the NPC has a unique targetname. -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::ForceSetTargetEntity( CAI_BaseNPC *pTarget, bool bDontCancelOtherSequences ) -{ - m_hForcedTarget = pTarget; - m_iszEntity = m_hForcedTarget->GetEntityName(); // Not guaranteed to be unique - m_bDontCancelOtherSequences = bDontCancelOtherSequences; -} - -//----------------------------------------------------------------------------- -// Purpose: Setup this scripted sequence to maintain the desired position offset -// to the other NPC in the scripted interaction. -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::SetupInteractionPosition( CBaseEntity *pRelativeEntity, VMatrix &matDesiredLocalToWorld ) -{ - m_matInteractionPosition = matDesiredLocalToWorld; - m_hInteractionRelativeEntity = pRelativeEntity; -} - -extern ConVar ai_debug_dyninteractions; -//----------------------------------------------------------------------------- -// Purpose: Modify the target AutoMovement() position before the NPC moves. -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::ModifyScriptedAutoMovement( Vector *vecNewPos ) -{ - if ( m_hInteractionRelativeEntity ) - { - // If we have an entry animation, only do it on the entry - if ( m_iszEntry != NULL_STRING && !m_bIsPlayingEntry ) - return; - - Vector vecRelativeOrigin = m_hInteractionRelativeEntity->GetAbsOrigin(); - QAngle angRelativeAngles = m_hInteractionRelativeEntity->GetAbsAngles(); - - CAI_BaseNPC *pNPC = m_hInteractionRelativeEntity->MyNPCPointer(); - if ( pNPC ) - { - angRelativeAngles[YAW] = pNPC->GetInteractionYaw(); - } - - bool bDebug = ai_debug_dyninteractions.GetInt() == 2; - if ( bDebug ) - { - Msg("--\n%s current org: %f %f\n", m_hTargetEnt->GetDebugName(), m_hTargetEnt->GetAbsOrigin().x, m_hTargetEnt->GetAbsOrigin().y ); - Msg("%s current org: %f %f", m_hInteractionRelativeEntity->GetDebugName(), vecRelativeOrigin.x, vecRelativeOrigin.y ); - } - - CBaseAnimating *pAnimating = dynamic_cast(m_hInteractionRelativeEntity.Get()); - if ( pAnimating ) - { - Vector vecDeltaPos; - QAngle vecDeltaAngles; - pAnimating->GetSequenceMovement( pAnimating->GetSequence(), 0.0f, pAnimating->GetCycle(), vecDeltaPos, vecDeltaAngles ); - VectorYawRotate( vecDeltaPos, pAnimating->GetLocalAngles().y, vecDeltaPos ); - - if ( bDebug ) - { - NDebugOverlay::Box( vecRelativeOrigin, -Vector(2,2,2), Vector(2,2,2), 0,255,0, 8, 0.1 ); - } - vecRelativeOrigin -= vecDeltaPos; - if ( bDebug ) - { - Msg(", relative to sequence start: %f %f\n", vecRelativeOrigin.x, vecRelativeOrigin.y ); - NDebugOverlay::Box( vecRelativeOrigin, -Vector(3,3,3), Vector(3,3,3), 255,0,0, 8, 0.1 ); - } - } - - // We've been asked to maintain a specific position relative to the other NPC - // we're interacting with. Lerp towards the relative position. - VMatrix matMeToWorld, matLocalToWorld; - matMeToWorld.SetupMatrixOrgAngles( vecRelativeOrigin, angRelativeAngles ); - MatrixMultiply( matMeToWorld, m_matInteractionPosition, matLocalToWorld ); - - // Get the desired NPC position in worldspace - Vector vecOrigin; - QAngle angAngles; - vecOrigin = matLocalToWorld.GetTranslation(); - MatrixToAngles( matLocalToWorld, angAngles ); - - if ( bDebug ) - { - Msg("Desired Origin for %s: %f %f\n", m_hTargetEnt->GetDebugName(), vecOrigin.x, vecOrigin.y ); - NDebugOverlay::Axis( vecOrigin, angAngles, 5, true, 0.1 ); - } - - // Lerp to it over time - Vector vecToTarget = (vecOrigin - *vecNewPos); - if ( bDebug ) - { - Msg("Automovement's output origin: %f %f\n", (*vecNewPos).x, (*vecNewPos).y ); - Msg("Vector from automovement to desired: %f %f\n", vecToTarget.x, vecToTarget.y ); - } - *vecNewPos += (vecToTarget * pAnimating->GetCycle()); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Find all the cinematic entities with my targetname and stop them -// from playing. -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::CancelScript( void ) -{ - DevMsg( 2, "Cancelling script: %s\n", STRING( m_iszPlay )); - - // Don't cancel matching sequences if we're asked not to, unless we didn't actually - // succeed in starting, in which case we should always cancel. This fixes - // dynamic interactions where an NPC was killed the same frame another NPC - // started a dynamic interaction with him. - bool bDontCancelOther = ((m_bDontCancelOtherSequences || HasSpawnFlags( SF_SCRIPT_ALLOW_DEATH ) )&& (m_startTime != 0)); - if ( bDontCancelOther || !GetEntityName() ) - { - ScriptEntityCancel( this ); - return; - } - - CBaseEntity *pentCineTarget = gEntList.FindEntityByName( NULL, GetEntityName() ); - - while ( pentCineTarget ) - { - ScriptEntityCancel( pentCineTarget ); - pentCineTarget = gEntList.FindEntityByName( pentCineTarget, GetEntityName() ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Find all the cinematic entities with my targetname and tell them to -// wait before starting. This ensures that all scripted sequences with -// the same name are frame-synchronized. -// -// When triggered, scripts call this first with a state of 1 to indicate that -// they are not ready to play (while NPCs move to their cue positions, etc). -// Once they are ready to play, they call it with a state of 0. When all -// the scripts are ready, they all are told to start. -// -// Input : bDelay - true means this script is not ready, false means it is ready. -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::DelayStart( bool bDelay ) -{ - //Msg("SSEQ: %.2f \"%s\" (%d) DelayStart( %d ). Current m_iDelay is: %d\n", gpGlobals->curtime, GetDebugName(), entindex(), bDelay, m_iDelay ); - - if ( ai_task_pre_script.GetBool() ) - { - if ( bDelay == m_bDelayed ) - return; - - m_bDelayed = bDelay; - } - - // Without a name, we cannot synchronize with anything else - if ( GetEntityName() == NULL_STRING ) - { - m_iDelay = bDelay; - m_startTime = gpGlobals->curtime; - return; - } - - CBaseEntity *pentCine = gEntList.FindEntityByName( NULL, GetEntityName() ); - - while ( pentCine ) - { - if ( FClassnameIs( pentCine, "scripted_sequence" ) ) - { - CAI_ScriptedSequence *pTarget = (CAI_ScriptedSequence *)pentCine; - if (bDelay) - { - // if delaying, add up the number of other scripts in the group - m_iDelay++; - - //Msg("SSEQ: (%d) Found matching SS (%d). Incrementing MY m_iDelay to %d.\n", entindex(), pTarget->entindex(), m_iDelay ); - } - else - { - // if ready, decrement each of other scripts in the group - // members not yet delayed will decrement below zero. - pTarget->m_iDelay--; - - //Msg("SSEQ: (%d) Found matching SS (%d). Decrementing THEIR m_iDelay to %d.\n", entindex(), pTarget->entindex(), pTarget->m_iDelay ); - - // once everything is balanced, everyone will start. - if (pTarget->m_iDelay == 0) - { - pTarget->m_startTime = gpGlobals->curtime; - - //Msg("SSEQ: STARTING SEQUENCE for \"%s\" (%d) (m_iDelay reached 0).\n", pTarget->GetDebugName(), pTarget->entindex() ); - } - } - } - pentCine = gEntList.FindEntityByName( pentCine, GetEntityName() ); - } - - //Msg("SSEQ: Exited DelayStart() with m_iDelay of: %d.\n", m_iDelay ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Find an entity that I'm interested in and precache the sounds he'll -// need in the sequence. -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::Activate( void ) -{ - BaseClass::Activate(); - - // - // See if there is another script specified to run immediately after this one. - // - m_hNextCine = gEntList.FindEntityByName( NULL, m_iszNextScript ); - if ( m_hNextCine == NULL ) - { - m_iszNextScript = NULL_STRING; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ScriptedSequence::DrawDebugGeometryOverlays( void ) -{ - BaseClass::DrawDebugGeometryOverlays(); - - if ( m_debugOverlays & OVERLAY_TEXT_BIT ) - { - if ( GetTarget() ) - { - NDebugOverlay::HorzArrow( GetAbsOrigin(), GetTarget()->GetAbsOrigin(), 16, 0, 255, 0, 64, true, 0.0f ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Input : -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CAI_ScriptedSequence::DrawDebugTextOverlays( void ) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - - Q_snprintf(tempstr,sizeof(tempstr),"Target: %s", GetTarget() ? GetTarget()->GetDebugName() : "None" ) ; - EntityText(text_offset,tempstr,0); - text_offset++; - - switch (m_fMoveTo) - { - case CINE_MOVETO_WAIT: - Q_snprintf(tempstr,sizeof(tempstr),"Moveto: Wait" ); - break; - case CINE_MOVETO_WAIT_FACING: - Q_snprintf(tempstr,sizeof(tempstr),"Moveto: Wait Facing" ); - break; - case CINE_MOVETO_WALK: - Q_snprintf(tempstr,sizeof(tempstr),"Moveto: Walk to Mark" ); - break; - case CINE_MOVETO_RUN: - Q_snprintf(tempstr,sizeof(tempstr),"Moveto: Run to Mark" ); - break; - case CINE_MOVETO_CUSTOM: - Q_snprintf(tempstr,sizeof(tempstr),"Moveto: Custom move to Mark" ); - break; - case CINE_MOVETO_TELEPORT: - Q_snprintf(tempstr,sizeof(tempstr),"Moveto: Teleport to Mark" ); - break; - } - EntityText(text_offset,tempstr,0); - text_offset++; - - Q_snprintf(tempstr,sizeof(tempstr),"Thinking: %s", m_bThinking ? "Yes" : "No" ) ; - EntityText(text_offset,tempstr,0); - text_offset++; - - if ( GetEntityName() != NULL_STRING ) - { - Q_snprintf(tempstr,sizeof(tempstr),"Delay: %d", m_iDelay ) ; - EntityText(text_offset,tempstr,0); - text_offset++; - } - - Q_snprintf(tempstr,sizeof(tempstr),"Start Time: %f", m_startTime ) ; - EntityText(text_offset,tempstr,0); - text_offset++; - - Q_snprintf(tempstr,sizeof(tempstr),"Sequence has started: %s", m_sequenceStarted ? "Yes" : "No" ) ; - EntityText(text_offset,tempstr,0); - text_offset++; - - Q_snprintf(tempstr,sizeof(tempstr),"Cancel Other Sequences: %s", m_bDontCancelOtherSequences ? "No" : "Yes" ) ; - EntityText(text_offset,tempstr,0); - text_offset++; - - if ( m_bWaitForBeginSequence ) - { - Q_snprintf(tempstr,sizeof(tempstr),"Is waiting for BeingSequence" ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - - if ( m_bIsPlayingEntry ) - { - Q_snprintf(tempstr,sizeof(tempstr),"Is playing entry" ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - - if ( m_bLoopActionSequence ) - { - Q_snprintf(tempstr,sizeof(tempstr),"Will loop action sequence" ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - - if ( m_bSynchPostIdles ) - { - Q_snprintf(tempstr,sizeof(tempstr),"Will synch post idles" ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - } - - return text_offset; -} - - -//----------------------------------------------------------------------------- -// Purpose: Modifies an NPC's AI state without taking it out of its AI. -//----------------------------------------------------------------------------- - -class CAI_ScriptedSchedule : public CBaseEntity -{ - DECLARE_CLASS( CAI_ScriptedSchedule, CBaseEntity ); -public: - CAI_ScriptedSchedule( void ); - -private: - - void StartSchedule( CAI_BaseNPC *pTarget ); - void StopSchedule( CAI_BaseNPC *pTarget ); - void ScriptThink( void ); - - // Input handlers - void InputStartSchedule( inputdata_t &inputdata ); - void InputStopSchedule( inputdata_t &inputdata ); - - CAI_BaseNPC *FindScriptEntity( bool bCyclic ); - - //--------------------------------- - - enum Schedule_t - { - SCHED_SCRIPT_NONE = 0, - SCHED_SCRIPT_WALK_TO_GOAL, - SCHED_SCRIPT_RUN_TO_GOAL, - SCHED_SCRIPT_ENEMY_IS_GOAL, - SCHED_SCRIPT_WALK_PATH_GOAL, - SCHED_SCRIPT_RUN_PATH_GOAL, - SCHED_SCRIPT_ENEMY_IS_GOAL_AND_RUN_TO_GOAL, - }; - - //--------------------------------- - - EHANDLE m_hLastFoundEntity; - EHANDLE m_hActivator; // Held from the input to allow procedural calls - - string_t m_iszEntity; // Entity that is wanted for this script - float m_flRadius; // Range to search for an NPC to possess. - - string_t m_sGoalEnt; - Schedule_t m_nSchedule; - int m_nForceState; - - bool m_bGrabAll; - - Interruptability_t m_Interruptability; - - bool m_bDidFireOnce; - - //--------------------------------- - - DECLARE_DATADESC(); - -}; - -BEGIN_DATADESC( CAI_ScriptedSchedule ) - - DEFINE_FIELD( m_hLastFoundEntity, FIELD_EHANDLE ), - DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "m_flRadius" ), - - DEFINE_KEYFIELD( m_iszEntity, FIELD_STRING, "m_iszEntity" ), - DEFINE_KEYFIELD( m_nSchedule, FIELD_INTEGER, "schedule" ), - DEFINE_KEYFIELD( m_nForceState, FIELD_INTEGER, "forcestate" ), - DEFINE_KEYFIELD( m_sGoalEnt, FIELD_STRING, "goalent" ), - DEFINE_KEYFIELD( m_bGrabAll, FIELD_BOOLEAN, "graball" ), - DEFINE_KEYFIELD( m_Interruptability, FIELD_INTEGER, "interruptability"), - - DEFINE_FIELD( m_bDidFireOnce, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hActivator, FIELD_EHANDLE ), - - DEFINE_THINKFUNC( ScriptThink ), - - DEFINE_INPUTFUNC( FIELD_VOID, "StartSchedule", InputStartSchedule ), - DEFINE_INPUTFUNC( FIELD_VOID, "StopSchedule", InputStopSchedule ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( aiscripted_schedule, CAI_ScriptedSchedule ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CAI_ScriptedSchedule::CAI_ScriptedSchedule( void ) : m_hActivator( NULL ) -{ -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CAI_ScriptedSchedule::ScriptThink( void ) -{ - bool success = false; - CAI_BaseNPC *pTarget; - - if ( !m_bGrabAll ) - { - pTarget = FindScriptEntity( (m_spawnflags & SF_SCRIPT_SEARCH_CYCLICALLY) != 0 ); - if ( pTarget ) - { - DevMsg( 2, "scripted_schedule \"%s\" using NPC \"%s\"(%s)\n", GetDebugName(), STRING( m_iszEntity ), pTarget->GetEntityName().ToCStr() ); - StartSchedule( pTarget ); - success = true; - } - } - else - { - m_hLastFoundEntity = NULL; - while ( ( pTarget = FindScriptEntity( true ) ) != NULL ) - { - DevMsg( 2, "scripted_schedule \"%s\" using NPC \"%s\"(%s)\n", GetDebugName(), pTarget->GetEntityName().ToCStr(), STRING( m_iszEntity ) ); - StartSchedule( pTarget ); - success = true; - } - } - - if ( !success ) - { - DevMsg( 2, "scripted_schedule \"%s\" can't find NPC \"%s\"\n", GetDebugName(), STRING( m_iszEntity ) ); - // FIXME: just trying again is bad. This should fire an output instead. - // FIXME: Think about puting output triggers on success true and sucess false - // FIXME: also needs to check the result of StartSchedule(), which can fail and not complain - SetNextThink( gpGlobals->curtime + 1.0f ); - } - else - { - m_bDidFireOnce = true; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CAI_BaseNPC *CAI_ScriptedSchedule::FindScriptEntity( bool bCyclic ) -{ - CBaseEntity *pEntity = gEntList.FindEntityGenericWithin( m_hLastFoundEntity, STRING( m_iszEntity ), GetAbsOrigin(), m_flRadius, this, m_hActivator ); - - while ( pEntity != NULL ) - { - CAI_BaseNPC *pNPC = pEntity->MyNPCPointer(); - if ( pNPC && pNPC->IsAlive() && pNPC->IsInterruptable()) - { - if ( bCyclic ) - { - // next time this is called, start searching from the one found last time - m_hLastFoundEntity = pNPC; - } - - return pNPC; - } - - pEntity = gEntList.FindEntityGenericWithin( pEntity, STRING( m_iszEntity ), GetAbsOrigin(), m_flRadius, this, NULL ); - } - - m_hLastFoundEntity = NULL; - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Make the entity carry out the scripted instructions, but without -// destroying the NPC's state. -//----------------------------------------------------------------------------- -void CAI_ScriptedSchedule::StartSchedule( CAI_BaseNPC *pTarget ) -{ - if ( pTarget == NULL ) - return; - - CBaseEntity *pGoalEnt = gEntList.FindEntityGeneric( NULL, STRING( m_sGoalEnt ), this, NULL ); - - // NOTE: !!! all possible choices require a goal ent currently - if ( !pGoalEnt ) - { - CHintCriteria hintCriteria; - hintCriteria.SetGroup( m_sGoalEnt ); - hintCriteria.SetHintType( HINT_ANY ); - hintCriteria.AddIncludePosition( pTarget->GetAbsOrigin(), FLT_MAX ); - CAI_Hint *pHint = CAI_HintManager::FindHint( pTarget->GetAbsOrigin(), hintCriteria ); - if ( !pHint ) - { - DevMsg( 1, "Can't find goal entity %s\nCan't execute script %s\n", STRING(m_sGoalEnt), GetDebugName() ); - return; - } - pGoalEnt = pHint; - } - - static NPC_STATE forcedStatesMap[] = - { - NPC_STATE_NONE, - NPC_STATE_IDLE, - NPC_STATE_ALERT, - NPC_STATE_COMBAT - }; - - if ( pTarget->GetSleepState() > AISS_AWAKE ) - pTarget->Wake(); - - pTarget->ForceDecisionThink(); - - Assert( m_nForceState >= 0 && m_nForceState < (int)ARRAYSIZE(forcedStatesMap) ); - - NPC_STATE forcedState = forcedStatesMap[m_nForceState]; - - // trap if this isn't a legal thing to do - Assert( pTarget->IsInterruptable() ); - - if ( forcedState != NPC_STATE_NONE ) - pTarget->SetState( forcedState ); - - // - // Set enemy and make the NPC aware of the enemy's current position. - // - if ( m_nSchedule == SCHED_SCRIPT_ENEMY_IS_GOAL || m_nSchedule == SCHED_SCRIPT_ENEMY_IS_GOAL_AND_RUN_TO_GOAL ) - { - if ( pGoalEnt && pGoalEnt->MyCombatCharacterPointer() ) - { - pTarget->SetEnemy( pGoalEnt ); - pTarget->UpdateEnemyMemory( pGoalEnt, pGoalEnt->GetAbsOrigin() ); - pTarget->SetCondition( COND_SCHEDULE_DONE ); - } - else - DevMsg( "Scripted schedule %s specified an invalid enemy %s\n", STRING( GetEntityName() ), STRING( m_sGoalEnt ) ); - } - - bool bDidSetSchedule = false; - - switch ( m_nSchedule ) - { - // - // Walk or run to position. - // - case SCHED_SCRIPT_WALK_TO_GOAL: - case SCHED_SCRIPT_RUN_TO_GOAL: - case SCHED_SCRIPT_ENEMY_IS_GOAL_AND_RUN_TO_GOAL: - { - Activity movementActivity = ( m_nSchedule == SCHED_SCRIPT_WALK_TO_GOAL ) ? ACT_WALK : ACT_RUN; - bool bIsFlying = (pTarget->GetMoveType() == MOVETYPE_FLY) || (pTarget->GetMoveType() == MOVETYPE_FLYGRAVITY); - if ( bIsFlying ) - { - movementActivity = ACT_FLY; - } - - if (!pTarget->ScheduledMoveToGoalEntity( SCHED_IDLE_WALK, pGoalEnt, movementActivity )) - { - if (!(m_spawnflags & SF_SCRIPT_NO_COMPLAINTS)) - { - DevMsg( 1, "ScheduledMoveToGoalEntity to goal entity %s failed\nCan't execute script %s\n", STRING(m_sGoalEnt), GetDebugName() ); - } - return; - } - bDidSetSchedule = true; - - break; - } - - case SCHED_SCRIPT_WALK_PATH_GOAL: - case SCHED_SCRIPT_RUN_PATH_GOAL: - { - Activity movementActivity = ( m_nSchedule == SCHED_SCRIPT_WALK_PATH_GOAL ) ? ACT_WALK : ACT_RUN; - bool bIsFlying = (pTarget->GetMoveType() == MOVETYPE_FLY) || (pTarget->GetMoveType() == MOVETYPE_FLYGRAVITY); - if ( bIsFlying ) - { - movementActivity = ACT_FLY; - } - if (!pTarget->ScheduledFollowPath( SCHED_IDLE_WALK, pGoalEnt, movementActivity )) - { - if (!(m_spawnflags & SF_SCRIPT_NO_COMPLAINTS)) - { - DevMsg( 1, "ScheduledFollowPath to goal entity %s failed\nCan't execute script %s\n", STRING(m_sGoalEnt), GetDebugName() ); - } - return; - } - bDidSetSchedule = true; - break; - } - - default: - break; - } - - if ( bDidSetSchedule ) - { - // Chain this to the target so that it can add the base and any custom interrupts to this - pTarget->SetScriptedScheduleIgnoreConditions( m_Interruptability ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler to activate the scripted schedule. Finds the NPC to -// act on and sets a think for the near future to do the real work. -//----------------------------------------------------------------------------- -void CAI_ScriptedSchedule::InputStartSchedule( inputdata_t &inputdata ) -{ - if (( m_nForceState == 0 ) && ( m_nSchedule == 0 )) - { - DevMsg( 2, "aiscripted_schedule - no schedule or state has been set!\n" ); - } - - if ( !m_bDidFireOnce || ( m_spawnflags & SF_SCRIPT_REPEATABLE ) ) - { - // DVS TODO: Is the NPC already playing the script? - m_hActivator = inputdata.pActivator; - SetThink( &CAI_ScriptedSchedule::ScriptThink ); - SetNextThink( gpGlobals->curtime ); - } - else - { - DevMsg( 2, "aiscripted_schedule - not playing schedule again: not flagged to repeat\n" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler to stop a previously activated scripted schedule. -//----------------------------------------------------------------------------- -void CAI_ScriptedSchedule::InputStopSchedule( inputdata_t &inputdata ) -{ - if ( !m_bDidFireOnce ) - { - DevMsg( 2, "aiscripted_schedule - StopSchedule called, but schedule's never started.\n" ); - return; - } - - CAI_BaseNPC *pTarget; - if ( !m_bGrabAll ) - { - pTarget = FindScriptEntity( (m_spawnflags & SF_SCRIPT_SEARCH_CYCLICALLY) != 0 ); - if ( pTarget ) - { - StopSchedule( pTarget ); - } - } - else - { - m_hLastFoundEntity = NULL; - while ( ( pTarget = FindScriptEntity( true ) ) != NULL ) - { - StopSchedule( pTarget ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: If the target entity appears to be running this scripted schedule break it -//----------------------------------------------------------------------------- -void CAI_ScriptedSchedule::StopSchedule( CAI_BaseNPC *pTarget ) -{ - if ( pTarget->IsCurSchedule( SCHED_IDLE_WALK ) ) - { - DevMsg( 2, "%s (%s): StopSchedule called on NPC %s.\n", GetClassname(), GetDebugName(), pTarget->GetDebugName() ); - pTarget->ClearSchedule( "Stopping scripted schedule" ); - } -} - -class CAI_ScriptedSentence : public CPointEntity -{ -public: - DECLARE_CLASS( CAI_ScriptedSentence, CPointEntity ); - - void Spawn( void ); - bool KeyValue( const char *szKeyName, const char *szValue ); - void FindThink( void ); - void DelayThink( void ); - int ObjectCaps( void ) { return (BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION); } - - // Input handlers - void InputBeginSentence( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - - CAI_BaseNPC *FindEntity( void ); - bool AcceptableSpeaker( CAI_BaseNPC *pNPC ); - int StartSentence( CAI_BaseNPC *pTarget ); - -private: - string_t m_iszSentence; // string index for sentence name - string_t m_iszEntity; // entity that is wanted for this sentence - float m_flRadius; // range to search - float m_flDelay; // How long the sentence lasts - float m_flRepeat; // repeat rate - soundlevel_t m_iSoundLevel; - int m_TempAttenuation; - float m_flVolume; - bool m_active; - string_t m_iszListener; // name of entity to look at while talking - CBaseEntity *m_pActivator; - - COutputEvent m_OnBeginSentence; - COutputEvent m_OnEndSentence; -}; - - -#define SF_SENTENCE_ONCE 0x0001 -#define SF_SENTENCE_FOLLOWERS 0x0002 // only say if following player -#define SF_SENTENCE_INTERRUPT 0x0004 // force talking except when dead -#define SF_SENTENCE_CONCURRENT 0x0008 // allow other people to keep talking -#define SF_SENTENCE_SPEAKTOACTIVATOR 0x0010 - -BEGIN_DATADESC( CAI_ScriptedSentence ) - - DEFINE_KEYFIELD( m_iszSentence, FIELD_STRING, "sentence" ), - DEFINE_KEYFIELD( m_iszEntity, FIELD_STRING, "entity" ), - DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "radius" ), - DEFINE_KEYFIELD( m_flDelay, FIELD_FLOAT, "delay" ), - DEFINE_KEYFIELD( m_flRepeat, FIELD_FLOAT, "refire" ), - DEFINE_KEYFIELD( m_iszListener, FIELD_STRING, "listener" ), - - DEFINE_KEYFIELD( m_TempAttenuation, FIELD_INTEGER, "attenuation" ), - - DEFINE_FIELD( m_iSoundLevel, FIELD_INTEGER ), - DEFINE_FIELD( m_flVolume, FIELD_FLOAT ), - DEFINE_FIELD( m_active, FIELD_BOOLEAN ), - DEFINE_FIELD( m_pActivator, FIELD_EHANDLE ), - - // Function Pointers - DEFINE_FUNCTION( FindThink ), - DEFINE_FUNCTION( DelayThink ), - - // Inputs - DEFINE_INPUTFUNC(FIELD_VOID, "BeginSentence", InputBeginSentence), - - // Outputs - DEFINE_OUTPUT(m_OnBeginSentence, "OnBeginSentence"), - DEFINE_OUTPUT(m_OnEndSentence, "OnEndSentence"), - -END_DATADESC() - - - -LINK_ENTITY_TO_CLASS( scripted_sentence, CAI_ScriptedSentence ); - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : szKeyName - -// szValue - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_ScriptedSentence::KeyValue( const char *szKeyName, const char *szValue ) -{ - if(FStrEq(szKeyName, "volume")) - { - m_flVolume = atof( szValue ) * 0.1; - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for starting the scripted sentence. -//----------------------------------------------------------------------------- -void CAI_ScriptedSentence::InputBeginSentence( inputdata_t &inputdata ) -{ - if ( !m_active ) - return; - - m_pActivator = inputdata.pActivator; - - //Msg( "Firing sentence: %s\n", STRING( m_iszSentence )); - SetThink( &CAI_ScriptedSentence::FindThink ); - SetNextThink( gpGlobals->curtime ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ScriptedSentence::Spawn( void ) -{ - SetSolid( SOLID_NONE ); - - m_active = true; - // if no targetname, start now - if ( !GetEntityName() ) - { - SetThink( &CAI_ScriptedSentence::FindThink ); - SetNextThink( gpGlobals->curtime + 1.0f ); - } - - switch( m_TempAttenuation ) - { - case 1: // Medium radius - m_iSoundLevel = SNDLVL_80dB; - break; - - case 2: // Large radius - m_iSoundLevel = SNDLVL_85dB; - break; - - case 3: //EVERYWHERE - m_iSoundLevel = SNDLVL_NONE; - break; - - default: - case 0: // Small radius - m_iSoundLevel = SNDLVL_70dB; - break; - } - m_TempAttenuation = 0; - - // No volume, use normal - if ( m_flVolume <= 0 ) - m_flVolume = 1.0; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ScriptedSentence::FindThink( void ) -{ - CAI_BaseNPC *pNPC = FindEntity(); - if ( pNPC ) - { - int index = StartSentence( pNPC ); - float length = engine->SentenceLength(index); - - m_OnEndSentence.FireOutput(NULL, this, length + m_flRepeat); - - if ( m_spawnflags & SF_SENTENCE_ONCE ) - UTIL_Remove( this ); - - float delay = m_flDelay + length + 0.1; - if ( delay < 0 ) - delay = 0; - - SetThink( &CAI_ScriptedSentence::DelayThink ); - // calculate delay dynamically because this could play a sentence group - // rather than a single sentence. - // add 0.1 because the sound engine mixes ahead -- the sentence will actually start ~0.1 secs from now - SetNextThink( gpGlobals->curtime + delay + m_flRepeat ); - m_active = false; - //Msg( "%s: found NPC %s\n", STRING(m_iszSentence), STRING(m_iszEntity) ); - } - else - { - //Msg( "%s: can't find NPC %s\n", STRING(m_iszSentence), STRING(m_iszEntity) ); - SetNextThink( gpGlobals->curtime + m_flRepeat + 0.5 ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAI_ScriptedSentence::DelayThink( void ) -{ - m_active = true; - if ( !GetEntityName() ) - SetNextThink( gpGlobals->curtime + 0.1f ); - SetThink( &CAI_ScriptedSentence::FindThink ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pNPC - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CAI_ScriptedSentence::AcceptableSpeaker( CAI_BaseNPC *pNPC ) -{ - if ( pNPC ) - { - if ( m_spawnflags & SF_SENTENCE_FOLLOWERS ) - { - if ( pNPC->GetTarget() == NULL || !pNPC->GetTarget()->IsPlayer() ) - return false; - } - bool override; - if ( m_spawnflags & SF_SENTENCE_INTERRUPT ) - override = true; - else - override = false; - if ( pNPC->CanPlaySentence( override ) ) - return true; - } - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : -//----------------------------------------------------------------------------- -CAI_BaseNPC *CAI_ScriptedSentence::FindEntity( void ) -{ - CBaseEntity *pentTarget; - CAI_BaseNPC *pNPC; - - pentTarget = gEntList.FindEntityByName( NULL, m_iszEntity ); - pNPC = NULL; - - while (pentTarget) - { - pNPC = pentTarget->MyNPCPointer(); - if ( pNPC != NULL ) - { - if ( AcceptableSpeaker( pNPC ) ) - return pNPC; - //Msg( "%s (%s), not acceptable\n", pNPC->GetClassname(), pNPC->GetDebugName() ); - } - pentTarget = gEntList.FindEntityByName( pentTarget, m_iszEntity ); - } - - CBaseEntity *pEntity = NULL; - for ( CEntitySphereQuery sphere( GetAbsOrigin(), m_flRadius, FL_NPC ); ( pEntity = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() ) - { - if (FClassnameIs( pEntity, STRING(m_iszEntity))) - { - pNPC = pEntity->MyNPCPointer( ); - if ( AcceptableSpeaker( pNPC ) ) - return pNPC; - } - } - - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pTarget - -// Output : -//----------------------------------------------------------------------------- -int CAI_ScriptedSentence::StartSentence( CAI_BaseNPC *pTarget ) -{ - if ( !pTarget ) - { - DevMsg( 2, "Not Playing sentence %s\n", STRING(m_iszSentence) ); - return -1; - } - - bool bConcurrent = false; - if ( !(m_spawnflags & SF_SENTENCE_CONCURRENT) ) - bConcurrent = true; - - CBaseEntity *pListener = NULL; - - if ( m_spawnflags & SF_SENTENCE_SPEAKTOACTIVATOR ) - { - pListener = m_pActivator; - } - else if (m_iszListener != NULL_STRING) - { - float radius = m_flRadius; - - if ( FStrEq( STRING(m_iszListener ), "!player" ) ) - radius = MAX_TRACE_LENGTH; // Always find the player - - pListener = gEntList.FindEntityGenericNearest( STRING( m_iszListener ), pTarget->GetAbsOrigin(), radius, this, NULL ); - } - - int sentenceIndex = pTarget->PlayScriptedSentence( STRING(m_iszSentence), m_flDelay, m_flVolume, m_iSoundLevel, bConcurrent, pListener ); - DevMsg( 2, "Playing sentence %s\n", STRING(m_iszSentence) ); - - m_OnBeginSentence.FireOutput(NULL, this); - - return sentenceIndex; -} - - - -// HACKHACK: This is a little expensive with the dynamic_cast<> and all, but it lets us solve -// the problem of matching scripts back to entities without new state. -const char *CAI_ScriptedSequence::GetSpawnPreIdleSequenceForScript( CBaseEntity *pEntity ) -{ - CAI_ScriptedSequence *pScript = gEntList.NextEntByClass( (CAI_ScriptedSequence *)NULL ); - while ( pScript ) - { - if ( pScript->HasSpawnFlags( SF_SCRIPT_START_ON_SPAWN ) && pScript->m_iszEntity == pEntity->GetEntityName() ) - { - if ( pScript->m_iszPreIdle != NULL_STRING ) - { - return STRING(pScript->m_iszPreIdle); - } - return NULL; - } - pScript = gEntList.NextEntByClass( pScript ); - } - return NULL; -} - diff --git a/game/server/scripted.h b/game/server/scripted.h deleted file mode 100644 index 1ba1b0e7c..000000000 --- a/game/server/scripted.h +++ /dev/null @@ -1,229 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef SCRIPTED_H -#define SCRIPTED_H -#ifdef _WIN32 -#pragma once -#endif - -#ifndef SCRIPTEVENT_H -#include "scriptevent.h" -#endif - -#include "ai_basenpc.h" - - -// -// The number of unique outputs that a script can fire from animation events. -// These are fired via SCRIPT_EVENT_FIREEVENT in CAI_BaseNPC::HandleAnimEvent. -// -#define MAX_SCRIPT_EVENTS 8 - - -#define SF_SCRIPT_WAITTILLSEEN 1 -#define SF_SCRIPT_EXITAGITATED 2 -#define SF_SCRIPT_REPEATABLE 4 // Whether the script can be played more than once. -#define SF_SCRIPT_LEAVECORPSE 8 -#define SF_SCRIPT_START_ON_SPAWN 16 -#define SF_SCRIPT_NOINTERRUPT 32 -#define SF_SCRIPT_OVERRIDESTATE 64 -#define SF_SCRIPT_DONT_TELEPORT_AT_END 128 // Don't fixup end position with a teleport when the SS is finished -#define SF_SCRIPT_LOOP_IN_POST_IDLE 256 // Loop in the post idle animation after playing the action animation. -#define SF_SCRIPT_HIGH_PRIORITY 512 // If set, we don't allow other scripts to steal our spot in the queue. -#define SF_SCRIPT_SEARCH_CYCLICALLY 1024 // Start search from last entity found. -#define SF_SCRIPT_NO_COMPLAINTS 2048 // doesn't bitch if it can't find anything -#define SF_SCRIPT_ALLOW_DEATH 4096 // the actor using this scripted sequence may die without interrupting the scene (used for scripted deaths) - - -enum script_moveto_t -{ - CINE_MOVETO_WAIT = 0, - CINE_MOVETO_WALK = 1, - CINE_MOVETO_RUN = 2, - CINE_MOVETO_CUSTOM = 3, - CINE_MOVETO_TELEPORT = 4, - CINE_MOVETO_WAIT_FACING = 5, -}; - -enum SCRIPT_PLAYER_DEATH -{ - SCRIPT_DO_NOTHING = 0, - SCRIPT_CANCEL = 1, -}; - - -// -// Interrupt levels for grabbing NPCs to act out scripted events. These indicate -// how important it is to get a specific NPC, and can affect how they respond. -// -enum SS_INTERRUPT -{ - SS_INTERRUPT_BY_CLASS = 0, // Indicates that we are asking for this NPC by class - SS_INTERRUPT_BY_NAME, // Indicates that we are asking for this NPC by name -}; - - -// when a NPC finishes an AI scripted sequence, we can choose -// a schedule to place them in. These defines are the aliases to -// resolve worldcraft input to real schedules (sjb) -#define SCRIPT_FINISHSCHED_DEFAULT 0 -#define SCRIPT_FINISHSCHED_AMBUSH 1 - -class CAI_ScriptedSequence : public CBaseEntity -{ - DECLARE_CLASS( CAI_ScriptedSequence, CBaseEntity ); -public: - void Spawn( void ); - virtual void Blocked( CBaseEntity *pOther ); - virtual void Touch( CBaseEntity *pOther ); - virtual int ObjectCaps( void ) { return (BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION); } - virtual void Activate( void ); - virtual void UpdateOnRemove( void ); - void StartThink(); - void ScriptThink( void ); - void StopThink(); - - DECLARE_DATADESC(); - - void Pain( void ); - void Die( void ); - void DelayStart( bool bDelay ); - bool FindEntity( void ); - void StartScript( void ); - void FireScriptEvent( int nEvent ); - void OnBeginSequence( void ); - - void SetTarget( CBaseEntity *pTarget ) { m_hTargetEnt = pTarget; }; - CBaseEntity *GetTarget( void ) { return m_hTargetEnt; }; - - // Input handlers - void InputBeginSequence( inputdata_t &inputdata ); - void InputCancelSequence( inputdata_t &inputdata ); - void InputMoveToPosition( inputdata_t &inputdata ); - - bool IsTimeToStart( void ); - bool IsWaitingForBegin( void ); - void ReleaseEntity( CAI_BaseNPC *pEntity ); - void CancelScript( void ); - bool StartSequence( CAI_BaseNPC *pTarget, string_t iszSeq, bool completeOnEmpty ); - void SynchronizeSequence( CAI_BaseNPC *pNPC ); - bool FCanOverrideState ( void ); - void SequenceDone( CAI_BaseNPC *pNPC ); - void PostIdleDone( CAI_BaseNPC *pNPC ); - void FixScriptNPCSchedule( CAI_BaseNPC *pNPC, int iSavedCineFlags ); - void FixFlyFlag( CAI_BaseNPC *pNPC, int iSavedCineFlags ); - bool CanInterrupt( void ); - void AllowInterrupt( bool fAllow ); - void RemoveIgnoredConditions( void ); - bool PlayedSequence( void ) { return m_sequenceStarted; } - bool CanEnqueueAfter( void ); - - // Entry & Action loops - bool IsPlayingEntry( void ) { return m_bIsPlayingEntry; } - bool IsPlayingAction( void ) { return ( m_sequenceStarted && !m_bIsPlayingEntry ); } - bool FinishedActionSequence( CAI_BaseNPC *pNPC ); - void SetLoopActionSequence( bool bLoop ) { m_bLoopActionSequence = bLoop; } - bool ShouldLoopActionSequence( void ) { return m_bLoopActionSequence; } - void StopActionLoop( bool bStopSynchronizedScenes ); - void SetSynchPostIdles( bool bSynch ) { m_bSynchPostIdles = bSynch; } - void SynchNewSequence( CAI_BaseNPC::SCRIPTSTATE newState, string_t iszSequence, bool bSynchOtherScenes ); - - // Dynamic scripted sequence spawning - void ForceSetTargetEntity( CAI_BaseNPC *pTarget, bool bDontCancelOtherSequences ); - - // Dynamic interactions - void SetupInteractionPosition( CBaseEntity *pRelativeEntity, VMatrix &matDesiredLocalToWorld ); - void ModifyScriptedAutoMovement( Vector *vecNewPos ); - - bool IsTeleportingDueToMoveTo( void ) { return m_bIsTeleportingDueToMoveTo; } - - // Debug - virtual int DrawDebugTextOverlays( void ); - virtual void DrawDebugGeometryOverlays( void ); - - void InputScriptPlayerDeath( inputdata_t &inputdata ); - -private: - friend class CAI_BaseNPC; // should probably try to eliminate this relationship - - string_t m_iszEntry; // String index for animation that must be played before entering the main action anim - string_t m_iszPreIdle; // String index for idle animation to play before playing the action anim (only played while waiting for the script to begin) - string_t m_iszPlay; // String index for scripted action animation - string_t m_iszPostIdle; // String index for idle animation to play before playing the action anim - string_t m_iszCustomMove; // String index for custom movement animation - string_t m_iszNextScript; // Name of the script to run immediately after this one. - string_t m_iszEntity; // Entity that is wanted for this script - - int m_fMoveTo; - bool m_bIsPlayingEntry; - bool m_bLoopActionSequence; - bool m_bSynchPostIdles; - bool m_bIgnoreGravity; - bool m_bDisableNPCCollisions; // Used when characters must interpenetrate while riding on elevators, trains, etc. - - float m_flRadius; // Range to search for an NPC to possess. - float m_flRepeat; // Repeat rate - - int m_iDelay; // A counter indicating how many scripts are NOT ready to start. - - bool m_bDelayed; // This moderately hacky hack ensures that we don't calls to DelayStart(true) or DelayStart(false) - // twice in succession. This is necessary because we didn't want to remove the call to DelayStart(true) - // from StartScript, even though DelayStart(true) is called from TASK_PRE_SCRIPT. - // All of this is necessary in case the NPCs schedule gets cleared during the script and then they - // reselect the schedule to play the script. Without this you can get NPCs stuck with m_iDelay = -1 - - float m_startTime; // Time when script actually started, used for synchronization - bool m_bWaitForBeginSequence; // Set to true when we are told to MoveToPosition. Holds the actor in the pre-action idle until BeginSequence is called. - - int m_saved_effects; - int m_savedFlags; - int m_savedCollisionGroup; - - bool m_interruptable; - bool m_sequenceStarted; - - EHANDLE m_hTargetEnt; - - EHANDLE m_hNextCine; // The script to hand the NPC off to when we finish with them. - - bool m_bThinking; - bool m_bInitiatedSelfDelete; - - bool m_bIsTeleportingDueToMoveTo; - - CAI_BaseNPC *FindScriptEntity( void ); - EHANDLE m_hLastFoundEntity; - - // Code forced us to use a specific NPC - EHANDLE m_hForcedTarget; - bool m_bDontCancelOtherSequences; - bool m_bForceSynch; - - bool m_bTargetWasAsleep; - - COutputEvent m_OnBeginSequence; - COutputEvent m_OnEndSequence; - COutputEvent m_OnPostIdleEndSequence; - COutputEvent m_OnCancelSequence; - COutputEvent m_OnCancelFailedSequence; // Fired when a scene is cancelled before it's ever run - COutputEvent m_OnScriptEvent[MAX_SCRIPT_EVENTS]; - - static void ScriptEntityCancel( CBaseEntity *pentCine, bool bPretendSuccess = false ); - - static const char *GetSpawnPreIdleSequenceForScript( CBaseEntity *pTargetEntity ); - - // Dynamic interactions - // For now, store just a single one of these. To synchronize positions - // with multiple other NPCs, this needs to be an array of NPCs & desired position matrices. - VMatrix m_matInteractionPosition; - EHANDLE m_hInteractionRelativeEntity; - - int m_iPlayerDeathBehavior; -}; - - -#endif // SCRIPTED_H diff --git a/game/server/scriptedtarget.cpp b/game/server/scriptedtarget.cpp deleted file mode 100644 index ba06371fb..000000000 --- a/game/server/scriptedtarget.cpp +++ /dev/null @@ -1,362 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ai_default.h" -#include "scriptedtarget.h" -#include "entitylist.h" -#include "ndebugoverlay.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//========================================================= -// Interactions -//========================================================= -int g_interactionScriptedTarget = 0; - -LINK_ENTITY_TO_CLASS( scripted_target, CScriptedTarget ); - -BEGIN_DATADESC( CScriptedTarget ) - - DEFINE_FIELD( m_vLastPosition, FIELD_POSITION_VECTOR ), - - DEFINE_KEYFIELD( m_iDisabled, FIELD_INTEGER, "StartDisabled" ), - DEFINE_KEYFIELD( m_iszEntity, FIELD_STRING, "m_iszEntity" ), - DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "m_flRadius" ), - - DEFINE_KEYFIELD( m_nMoveSpeed, FIELD_INTEGER, "MoveSpeed" ), - DEFINE_KEYFIELD( m_flPauseDuration, FIELD_FLOAT, "PauseDuration" ), - DEFINE_FIELD( m_flPauseDoneTime, FIELD_TIME ), - DEFINE_KEYFIELD( m_flEffectDuration, FIELD_FLOAT, "EffectDuration" ), - - // Function Pointers - DEFINE_THINKFUNC( ScriptThink ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - - // Outputs - DEFINE_OUTPUT(m_AtTarget, "AtTarget" ), - DEFINE_OUTPUT(m_LeaveTarget, "LeaveTarget" ), - -END_DATADESC() - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CScriptedTarget::InputEnable( inputdata_t &inputdata ) -{ - TurnOn(); -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CScriptedTarget::InputDisable( inputdata_t &inputdata ) -{ - TurnOff(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CScriptedTarget::TurnOn( void ) -{ - m_vLastPosition = GetAbsOrigin(); - SetThink( &CScriptedTarget::ScriptThink ); - m_iDisabled = false; - SetNextThink( gpGlobals->curtime ); -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CScriptedTarget::TurnOff( void ) -{ - SetThink( NULL ); - m_iDisabled = true; - - // If I have a target entity, free him - if (GetTarget()) - { - CAI_BaseNPC* pNPC = GetTarget()->MyNPCPointer(); - pNPC->DispatchInteraction( g_interactionScriptedTarget, NULL, NULL ); - } -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CScriptedTarget::Spawn( void ) -{ - if (g_interactionScriptedTarget == 0) - { - g_interactionScriptedTarget = CBaseCombatCharacter::GetInteractionID(); - } - - SetSolid( SOLID_NONE ); - - m_vLastPosition = GetAbsOrigin(); - - if (!m_iDisabled ) - { - TurnOn(); - } -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -CScriptedTarget* CScriptedTarget::NextScriptedTarget(void) -{ - // ---------------------------------------------------------------------- - // If I just hit my target, set how long I'm supposed to pause here - // ---------------------------------------------------------------------- - if (m_flPauseDoneTime == 0) - { - m_flPauseDoneTime = gpGlobals->curtime + m_flPauseDuration; - m_AtTarget.FireOutput( GetTarget(), this ); - } - - // ------------------------------------------------------------- - // If I'm done pausing move on to next burn target - // ------------------------------------------------------------- - if (gpGlobals->curtime >= m_flPauseDoneTime) - { - m_flPauseDoneTime = 0; - - // ---------------------------------------------------------- - // Fire output that current Scripted target has been reached - // ---------------------------------------------------------- - m_LeaveTarget.FireOutput( GetTarget(), this ); - - // ------------------------------------------------------------ - // Get next target. - // ------------------------------------------------------------ - CScriptedTarget* pNextTarget = ((CScriptedTarget*)GetNextTarget()); - - // -------------------------------------------- - // Fire output if last one has been reached - // -------------------------------------------- - if (!pNextTarget) - { - TurnOff(); - SetTarget( NULL ); - } - // ------------------------------------------------ - // Otherwise, turn myself off, the next target on - // and pass on my target entity - // ------------------------------------------------ - else - { - // ---------------------------------------------------- - // Make sure there is a LOS between these two targets - // ---------------------------------------------------- - trace_t tr; - UTIL_TraceLine(GetAbsOrigin(), pNextTarget->GetAbsOrigin(), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr); - if (tr.fraction != 1.0) - { - Warning( "WARNING: Scripted Target from (%s) to (%s) is occluded!\n",GetDebugName(),pNextTarget->GetDebugName() ); - } - - pNextTarget->TurnOn(); - pNextTarget->SetTarget( GetTarget() ); - - SetTarget( NULL ); - TurnOff(); - } - // -------------------------------------------- - // Return new target - // -------------------------------------------- - return pNextTarget; - } - // ------------------------------------------------------------- - // Otherwise keep the same scripted target until pause is done - // ------------------------------------------------------------- - else - { - return this; - } -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -CBaseEntity* CScriptedTarget::FindEntity( void ) -{ - // --------------------------------------------------- - // First try to find the entity by name - // --------------------------------------------------- - CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, m_iszEntity ); - if (pEntity && pEntity->GetFlags() & FL_NPC) - { - CAI_BaseNPC* pNPC = pEntity->MyNPCPointer(); - if (pNPC->DispatchInteraction( g_interactionScriptedTarget, NULL, this )) - { - return pEntity; - } - } - - // --------------------------------------------------- - // If that fails, assume we were given a classname - // and find nearest entity in radius of that class - // --------------------------------------------------- - float flNearestDist = MAX_COORD_RANGE; - CBaseEntity* pNearestEnt = NULL; - CBaseEntity* pTestEnt = NULL; - - for ( CEntitySphereQuery sphere( GetAbsOrigin(), m_flRadius ); ( pTestEnt = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() ) - { - if (pTestEnt->GetFlags() & FL_NPC) - { - if (FClassnameIs( pTestEnt, STRING(m_iszEntity))) - { - float flTestDist = (pTestEnt->GetAbsOrigin() - GetAbsOrigin()).Length(); - if (flTestDist < flNearestDist) - { - flNearestDist = flTestDist; - pNearestEnt = pTestEnt; - } - } - } - } - - // UNDONE: If nearest fails, try next nearest - if (pNearestEnt) - { - CAI_BaseNPC* pNPC = pNearestEnt->MyNPCPointer(); - if (pNPC->DispatchInteraction( g_interactionScriptedTarget, NULL, this )) - { - return pNearestEnt; - } - } - - return NULL; -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CScriptedTarget::ScriptThink( void ) -{ - // -------------------------------------------- - // If I don't have target entity look for one - // -------------------------------------------- - if (GetTarget() == NULL) - { - m_flPauseDoneTime = 0; - SetTarget( FindEntity() ); - } - SetNextThink( gpGlobals->curtime + 0.1f ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CScriptedTarget::DrawDebugTextOverlays(void) -{ - // Skip AIClass debug overlays - int text_offset = CBaseEntity::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - // -------------- - // Print State - // -------------- - char tempstr[512]; - if (m_iDisabled) - { - Q_strncpy(tempstr,"State: Off",sizeof(tempstr)); - } - else - { - Q_strncpy(tempstr,"State: On",sizeof(tempstr)); - } - EntityText(text_offset,tempstr,0); - text_offset++; - - // ----------------- - // Print Next Entity - // ----------------- - CBaseEntity *pTarget = GetNextTarget(); - if (pTarget) - { - Q_snprintf(tempstr,sizeof(tempstr),"Next: %s",pTarget->GetDebugName() ); - } - else - { - Q_strncpy(tempstr,"Next: -NONE-",sizeof(tempstr)); - } - EntityText(text_offset,tempstr,0); - text_offset++; - - // -------------- - // Print Target - // -------------- - if (GetTarget()!=NULL) - { - Q_snprintf(tempstr,sizeof(tempstr),"User: %s",GetTarget()->GetDebugName() ); - } - else if (m_iDisabled) - { - Q_strncpy(tempstr,"User: -NONE-",sizeof(tempstr)); - } - else - { - Q_strncpy(tempstr,"User: -LOOKING-",sizeof(tempstr)); - } - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} - - -//----------------------------------------------------------------------------- -// Purpose: Override base class to add display of paths -//----------------------------------------------------------------------------- -void CScriptedTarget::DrawDebugGeometryOverlays(void) -{ - // ---------------------------------------------- - // Draw line to next target is bbox is selected - // ---------------------------------------------- - if (m_debugOverlays & (OVERLAY_BBOX_BIT|OVERLAY_ABSBOX_BIT)) - { - if (m_iDisabled) - { - NDebugOverlay::Box(GetAbsOrigin(), Vector(-5,-5,-5), Vector(5,5,5), 200,100,100, 0 ,0); - } - else - { - NDebugOverlay::Cross3D(m_vLastPosition, Vector(-8,-8,-8),Vector(8,8,8),255,0,0,true,0.1); - NDebugOverlay::Box(GetAbsOrigin(), Vector(-5,-5,-5), Vector(5,5,5), 255,0,0, 0 ,0); - NDebugOverlay::Line(GetAbsOrigin(),m_vLastPosition,255,0,0,true,0.0); - } - - CBaseEntity *pTarget = GetNextTarget(); - if (pTarget) - { - NDebugOverlay::Line(GetAbsOrigin(),pTarget->GetAbsOrigin(),200,100,100,true,0.0); - } - if (GetTarget() != NULL) - { - NDebugOverlay::Line(GetAbsOrigin(),GetTarget()->EyePosition(),0,255,0,true,0.0); - } - - } - CBaseEntity::DrawDebugGeometryOverlays(); -} - diff --git a/game/server/scriptedtarget.h b/game/server/scriptedtarget.h deleted file mode 100644 index 4e0a0ac10..000000000 --- a/game/server/scriptedtarget.h +++ /dev/null @@ -1,64 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SCRIPTEDTARGET_H -#define SCRIPTEDTARGET_H -#ifdef _WIN32 -#pragma once -#endif - -#ifndef SCRIPTEVENT_H -#include "scriptevent.h" -#endif - -#include "ai_basenpc.h" - -class CScriptedTarget : public CAI_BaseNPC -{ - DECLARE_CLASS( CScriptedTarget, CAI_BaseNPC ); -public: - DECLARE_DATADESC(); - - void Spawn( void ); - virtual int ObjectCaps( void ) { return (BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION); } - - - void ScriptThink( void ); - CBaseEntity* FindEntity( void ); - - void TurnOn(void); - void TurnOff(void); - - // Input handlers - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - - CScriptedTarget* NextScriptedTarget(void); - float MoveSpeed(void) { return m_nMoveSpeed; }; - float EffectDuration(void) { return m_flEffectDuration; }; - - int DrawDebugTextOverlays(void); - void DrawDebugGeometryOverlays(void); - float PercentComplete(void); - - Vector m_vLastPosition; // Last position that's been reached - -private: - int m_iDisabled; // Initial state - string_t m_iszEntity; // entity that is wanted for this script - float m_flRadius; // range to search - - int m_nMoveSpeed; // How fast do I burn from target to target - float m_flPauseDuration; // How long to pause at this target - float m_flPauseDoneTime; // When is pause over - float m_flEffectDuration; // How long should any associated effect last? - - COutputEvent m_AtTarget; // Fired when scripted target has been reached - COutputEvent m_LeaveTarget; // Fired when scripted target is left -}; - -#endif // SCRIPTEDTARGET_H diff --git a/game/server/sdk/sdk_bot_temp.cpp b/game/server/sdk/sdk_bot_temp.cpp deleted file mode 100644 index 44bacc1f2..000000000 --- a/game/server/sdk/sdk_bot_temp.cpp +++ /dev/null @@ -1,480 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Basic BOT handling. -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "player.h" -#include "sdk_player.h" -#include "in_buttons.h" -#include "movehelper_server.h" -#include "gameinterface.h" - - -class CSDKBot; -void Bot_Think( CSDKBot *pBot ); - - -ConVar bot_forcefireweapon( "bot_forcefireweapon", "", 0, "Force bots with the specified weapon to fire." ); -ConVar bot_forceattack2( "bot_forceattack2", "0", 0, "When firing, use attack2." ); -ConVar bot_forceattackon( "bot_forceattackon", "0", 0, "When firing, don't tap fire, hold it down." ); -ConVar bot_flipout( "bot_flipout", "0", 0, "When on, all bots fire their guns." ); -ConVar bot_changeclass( "bot_changeclass", "0", 0, "Force all bots to change to the specified class." ); -static ConVar bot_mimic( "bot_mimic", "0", 0, "Bot uses usercmd of player by index." ); -static ConVar bot_mimic_yaw_offset( "bot_mimic_yaw_offset", "0", 0, "Offsets the bot yaw." ); - -ConVar bot_sendcmd( "bot_sendcmd", "", 0, "Forces bots to send the specified command." ); - -ConVar bot_crouch( "bot_crouch", "0", 0, "Bot crouches" ); - -static int g_CurBotNumber = 1; - - -// This is our bot class. -class CSDKBot : public CSDKPlayer -{ -public: - bool m_bBackwards; - - float m_flNextTurnTime; - bool m_bLastTurnToRight; - - float m_flNextStrafeTime; - float m_flSideMove; - - QAngle m_ForwardAngle; - QAngle m_LastAngles; -}; - -LINK_ENTITY_TO_CLASS( sdk_bot, CSDKBot ); - -class CBotManager -{ -public: - static CBasePlayer* ClientPutInServerOverride_Bot( edict_t *pEdict, const char *playername ) - { - // This tells it which edict to use rather than creating a new one. - CBasePlayer::s_PlayerEdict = pEdict; - - CSDKBot *pPlayer = static_cast( CreateEntityByName( "sdk_bot" ) ); - if ( pPlayer ) - { - pPlayer->SetPlayerName( playername ); - } - - return pPlayer; - } -}; - - -//----------------------------------------------------------------------------- -// Purpose: Create a new Bot and put it in the game. -// Output : Pointer to the new Bot, or NULL if there's no free clients. -//----------------------------------------------------------------------------- -CBasePlayer *BotPutInServer( bool bFrozen ) -{ - char botname[ 64 ]; - Q_snprintf( botname, sizeof( botname ), "Bot%02i", g_CurBotNumber ); - - - // This trick lets us create a CSDKBot for this client instead of the CSDKPlayer - // that we would normally get when ClientPutInServer is called. - ClientPutInServerOverride( &CBotManager::ClientPutInServerOverride_Bot ); - edict_t *pEdict = engine->CreateFakeClient( botname ); - ClientPutInServerOverride( NULL ); - - if (!pEdict) - { - Msg( "Failed to create Bot.\n"); - return NULL; - } - - // Allocate a player entity for the bot, and call spawn - CSDKBot *pPlayer = ((CSDKBot*)CBaseEntity::Instance( pEdict )); - - pPlayer->ClearFlags(); - pPlayer->AddFlag( FL_CLIENT | FL_FAKECLIENT ); - - if ( bFrozen ) - pPlayer->AddEFlags( EFL_BOT_FROZEN ); - - pPlayer->ChangeTeam( TEAM_UNASSIGNED ); - pPlayer->RemoveAllItems( true ); - pPlayer->Spawn(); - - g_CurBotNumber++; - - return pPlayer; -} - -// Handler for the "bot" command. -CON_COMMAND_F( bot_add, "Add a bot.", FCVAR_CHEAT ) -{ - // Look at -count. - int count = args.FindArgInt( "-count", 1 ); - count = clamp( count, 1, 16 ); - - // Look at -frozen. - bool bFrozen = !!args.FindArg( "-frozen" ); - - // Ok, spawn all the bots. - while ( --count >= 0 ) - { - BotPutInServer( bFrozen ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Run through all the Bots in the game and let them think. -//----------------------------------------------------------------------------- -void Bot_RunAll( void ) -{ - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CSDKPlayer *pPlayer = ToSDKPlayer( UTIL_PlayerByIndex( i ) ); - - if ( pPlayer && (pPlayer->GetFlags() & FL_FAKECLIENT) ) - { - CSDKBot *pBot = dynamic_cast< CSDKBot* >( pPlayer ); - if ( pBot ) - Bot_Think( pBot ); - } - } -} - -bool Bot_RunMimicCommand( CUserCmd& cmd ) -{ - if ( bot_mimic.GetInt() <= 0 ) - return false; - - if ( bot_mimic.GetInt() > gpGlobals->maxClients ) - return false; - - - CBasePlayer *pPlayer = UTIL_PlayerByIndex( bot_mimic.GetInt() ); - if ( !pPlayer ) - return false; - - if ( !pPlayer->GetLastUserCommand() ) - return false; - - cmd = *pPlayer->GetLastUserCommand(); - cmd.viewangles[YAW] += bot_mimic_yaw_offset.GetFloat(); - - if( bot_crouch.GetInt() ) - cmd.buttons |= IN_DUCK; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Simulates a single frame of movement for a player -// Input : *fakeclient - -// *viewangles - -// forwardmove - -// m_flSideMove - -// upmove - -// buttons - -// impulse - -// msec - -// Output : virtual void -//----------------------------------------------------------------------------- -static void RunPlayerMove( CSDKPlayer *fakeclient, CUserCmd &cmd, float frametime ) -{ - if ( !fakeclient ) - return; - - // Store off the globals.. they're gonna get whacked - float flOldFrametime = gpGlobals->frametime; - float flOldCurtime = gpGlobals->curtime; - - float flTimeBase = gpGlobals->curtime + gpGlobals->frametime - frametime; - fakeclient->SetTimeBase( flTimeBase ); - - MoveHelperServer()->SetHost( fakeclient ); - fakeclient->PlayerRunCommand( &cmd, MoveHelperServer() ); - - // save off the last good usercmd - fakeclient->SetLastUserCommand( cmd ); - - // Clear out any fixangle that has been set - fakeclient->pl.fixangle = FIXANGLE_NONE; - - // Restore the globals.. - gpGlobals->frametime = flOldFrametime; - gpGlobals->curtime = flOldCurtime; -} - - - -void Bot_UpdateStrafing( CSDKBot *pBot, CUserCmd &cmd ) -{ - if ( gpGlobals->curtime >= pBot->m_flNextStrafeTime ) - { - pBot->m_flNextStrafeTime = gpGlobals->curtime + 1.0f; - - if ( random->RandomInt( 0, 5 ) == 0 ) - { - pBot->m_flSideMove = -600.0f + 1200.0f * random->RandomFloat( 0, 2 ); - } - else - { - pBot->m_flSideMove = 0; - } - cmd.sidemove = pBot->m_flSideMove; - - if ( random->RandomInt( 0, 20 ) == 0 ) - { - pBot->m_bBackwards = true; - } - else - { - pBot->m_bBackwards = false; - } - } -} - - -void Bot_UpdateDirection( CSDKBot *pBot ) -{ - float angledelta = 15.0; - QAngle angle; - - int maxtries = (int)(360.0 / angledelta); - - if ( pBot->m_bLastTurnToRight ) - { - angledelta = -angledelta; - } - - angle = pBot->GetLocalAngles(); - - trace_t trace; - Vector vecSrc, vecEnd, forward; - while ( --maxtries >= 0 ) - { - AngleVectors( angle, &forward ); - - vecSrc = pBot->GetLocalOrigin() + Vector( 0, 0, 36 ); - - vecEnd = vecSrc + forward * 10; - - UTIL_TraceHull( vecSrc, vecEnd, VEC_HULL_MIN, VEC_HULL_MAX, - MASK_PLAYERSOLID, pBot, COLLISION_GROUP_NONE, &trace ); - - if ( trace.fraction == 1.0 ) - { - if ( gpGlobals->curtime < pBot->m_flNextTurnTime ) - { - break; - } - } - - angle.y += angledelta; - - if ( angle.y > 180 ) - angle.y -= 360; - else if ( angle.y < -180 ) - angle.y += 360; - - pBot->m_flNextTurnTime = gpGlobals->curtime + 2.0; - pBot->m_bLastTurnToRight = random->RandomInt( 0, 1 ) == 0 ? true : false; - - pBot->m_ForwardAngle = angle; - pBot->m_LastAngles = angle; - } - - pBot->SetLocalAngles( angle ); -} - - -void Bot_FlipOut( CSDKBot *pBot, CUserCmd &cmd ) -{ - if ( bot_flipout.GetInt() > 0 && pBot->IsAlive() ) - { - if ( bot_forceattackon.GetBool() || (RandomFloat(0.0,1.0) > 0.5) ) - { - cmd.buttons |= bot_forceattack2.GetBool() ? IN_ATTACK2 : IN_ATTACK; - } - - if ( bot_flipout.GetInt() >= 2 ) - { - QAngle angOffset = RandomAngle( -1, 1 ); - - pBot->m_LastAngles += angOffset; - - for ( int i = 0 ; i < 2; i++ ) - { - if ( fabs( pBot->m_LastAngles[ i ] - pBot->m_ForwardAngle[ i ] ) > 15.0f ) - { - if ( pBot->m_LastAngles[ i ] > pBot->m_ForwardAngle[ i ] ) - { - pBot->m_LastAngles[ i ] = pBot->m_ForwardAngle[ i ] + 15; - } - else - { - pBot->m_LastAngles[ i ] = pBot->m_ForwardAngle[ i ] - 15; - } - } - } - - pBot->m_LastAngles[ 2 ] = 0; - - pBot->SetLocalAngles( pBot->m_LastAngles ); - } - } -} - - -void Bot_HandleSendCmd( CSDKBot *pBot ) -{ - if ( strlen( bot_sendcmd.GetString() ) > 0 ) - { - //send the cmd from this bot - CCommand args; - args.Tokenize( bot_sendcmd.GetString() ); - pBot->ClientCommand( args ); - - bot_sendcmd.SetValue(""); - } -} - - -// If bots are being forced to fire a weapon, see if I have it -void Bot_ForceFireWeapon( CSDKBot *pBot, CUserCmd &cmd ) -{ - if ( bot_forcefireweapon.GetString() ) - { - CBaseCombatWeapon *pWeapon = pBot->Weapon_OwnsThisType( bot_forcefireweapon.GetString() ); - if ( pWeapon ) - { - // Switch to it if we don't have it out - CBaseCombatWeapon *pActiveWeapon = pBot->GetActiveWeapon(); - - // Switch? - if ( pActiveWeapon != pWeapon ) - { - pBot->Weapon_Switch( pWeapon ); - } - else - { - // Start firing - // Some weapons require releases, so randomise firing - if ( bot_forceattackon.GetBool() || (RandomFloat(0.0,1.0) > 0.5) ) - { - cmd.buttons |= bot_forceattack2.GetBool() ? IN_ATTACK2 : IN_ATTACK; - } - } - } - } -} - - -void Bot_SetForwardMovement( CSDKBot *pBot, CUserCmd &cmd ) -{ - if ( !pBot->IsEFlagSet(EFL_BOT_FROZEN) ) - { - if ( pBot->m_iHealth == 100 ) - { - cmd.forwardmove = 600 * ( pBot->m_bBackwards ? -1 : 1 ); - if ( pBot->m_flSideMove != 0.0f ) - { - cmd.forwardmove *= random->RandomFloat( 0.1, 1.0f ); - } - } - else - { - // Stop when shot - cmd.forwardmove = 0; - } - } -} - - -void Bot_HandleRespawn( CSDKBot *pBot, CUserCmd &cmd ) -{ - // Wait for Reinforcement wave - if ( !pBot->IsAlive() ) - { - // Try hitting my buttons occasionally - if ( random->RandomInt( 0, 100 ) > 80 ) - { - // Respawn the bot - if ( random->RandomInt( 0, 1 ) == 0 ) - { - cmd.buttons |= IN_JUMP; - } - else - { - cmd.buttons = 0; - } - } - } -} - - -//----------------------------------------------------------------------------- -// Run this Bot's AI for one frame. -//----------------------------------------------------------------------------- -void Bot_Think( CSDKBot *pBot ) -{ - // Make sure we stay being a bot - pBot->AddFlag( FL_FAKECLIENT ); - - - CUserCmd cmd; - Q_memset( &cmd, 0, sizeof( cmd ) ); - - - // Finally, override all this stuff if the bot is being forced to mimic a player. - if ( !Bot_RunMimicCommand( cmd ) ) - { - cmd.sidemove = pBot->m_flSideMove; - - if ( pBot->IsAlive() && (pBot->GetSolid() == SOLID_BBOX) ) - { - Bot_SetForwardMovement( pBot, cmd ); - - // Only turn if I haven't been hurt - if ( !pBot->IsEFlagSet(EFL_BOT_FROZEN) && pBot->m_iHealth == 100 ) - { - Bot_UpdateDirection( pBot ); - Bot_UpdateStrafing( pBot, cmd ); - } - - // Handle console settings. - Bot_ForceFireWeapon( pBot, cmd ); - Bot_HandleSendCmd( pBot ); - } - else - { - Bot_HandleRespawn( pBot, cmd ); - } - - Bot_FlipOut( pBot, cmd ); - - // Fix up the m_fEffects flags - pBot->PostClientMessagesSent(); - - - - cmd.viewangles = pBot->GetLocalAngles(); - cmd.upmove = 0; - cmd.impulse = 0; - } - - - float frametime = gpGlobals->frametime; - RunPlayerMove( pBot, cmd, frametime ); -} - - diff --git a/game/server/sdk/sdk_bot_temp.h b/game/server/sdk/sdk_bot_temp.h deleted file mode 100644 index cf50eadbe..000000000 --- a/game/server/sdk/sdk_bot_temp.h +++ /dev/null @@ -1,21 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SDK_BOT_TEMP_H -#define SDK_BOT_TEMP_H -#ifdef _WIN32 -#pragma once -#endif - - -// If iTeam or iClass is -1, then a team or class is randomly chosen. -CBasePlayer *BotPutInServer( bool bFrozen, int iTeam, int iClass ); - -void Bot_RunAll(); - - -#endif // SDK_BOT_TEMP_H diff --git a/game/server/sdk/sdk_brushentity.cpp b/game/server/sdk/sdk_brushentity.cpp deleted file mode 100644 index 4683f9ffa..000000000 --- a/game/server/sdk/sdk_brushentity.cpp +++ /dev/null @@ -1,79 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Simple brush entity that moves when touched -// -//=============================================================================// - -#include "cbase.h" - -class CMyBrushEntity : public CBaseToggle -{ -public: - DECLARE_CLASS( CMyBrushEntity, CBaseToggle ); - DECLARE_DATADESC(); - - void Spawn( void ); - bool CreateVPhysics( void ); - - void BrushTouch( CBaseEntity *pOther ); -}; - -LINK_ENTITY_TO_CLASS( my_brush_entity, CMyBrushEntity ); - -// Start of our data description for the class -BEGIN_DATADESC( CMyBrushEntity ) - - // Declare this function as being a touch function - DEFINE_ENTITYFUNC( BrushTouch ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: Sets up the entity's initial state -//----------------------------------------------------------------------------- -void CMyBrushEntity::Spawn( void ) -{ - // We want to capture touches from other entities - SetTouch( &CMyBrushEntity::BrushTouch ); - - // We should collide with physics - SetSolid( SOLID_VPHYSICS ); - - // We push things out of our way - SetMoveType( MOVETYPE_PUSH ); - - // Use our brushmodel - SetModel( STRING( GetModelName() ) ); - - // Create our physics hull information - CreateVPhysics(); -} - -//----------------------------------------------------------------------------- -// Purpose: Setup our physics information so we collide properly -//----------------------------------------------------------------------------- -bool CMyBrushEntity::CreateVPhysics( void ) -{ - // For collisions with physics objects - VPhysicsInitShadow( false, false ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Move away from an entity that touched us -// Input : *pOther - the entity we touched -//----------------------------------------------------------------------------- -void CMyBrushEntity::BrushTouch( CBaseEntity *pOther ) -{ - // Get the collision information - const trace_t &tr = GetTouchTrace(); - - // We want to move away from the impact point along our surface - Vector vecPushDir = tr.plane.normal; - vecPushDir.Negate(); - vecPushDir.z = 0.0f; - - // Move slowly in that direction - LinearMove( GetAbsOrigin() + ( vecPushDir * 64.0f ), 32.0f ); -} diff --git a/game/server/sdk/sdk_client.cpp b/game/server/sdk/sdk_client.cpp deleted file mode 100644 index c95d03550..000000000 --- a/game/server/sdk/sdk_client.cpp +++ /dev/null @@ -1,164 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -/* - -===== tf_client.cpp ======================================================== - - HL2 client/server game specific stuff - -*/ - -#include "cbase.h" -#include "player.h" -#include "gamerules.h" -#include "entitylist.h" -#include "physics.h" -#include "game.h" -#include "ai_network.h" -#include "ai_node.h" -#include "ai_hull.h" -#include "shake.h" -#include "player_resource.h" -#include "engine/IEngineSound.h" -#include "sdk_player.h" -#include "sdk_gamerules.h" -#include "tier0/vprof.h" -#include "sdk_bot_temp.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -extern CBaseEntity *FindPickerEntity( CBasePlayer *pPlayer ); - -extern bool g_fGameOver; - - -void FinishClientPutInServer( CSDKPlayer *pPlayer ) -{ - pPlayer->InitialSpawn(); - pPlayer->Spawn(); - - if (!pPlayer->IsBot()) - { - // When the player first joins the server, they - pPlayer->m_takedamage = DAMAGE_YES; - pPlayer->pl.deadflag = false; - pPlayer->m_lifeState = LIFE_ALIVE; - pPlayer->RemoveEffects( EF_NODRAW ); - pPlayer->ChangeTeam( TEAM_UNASSIGNED ); - pPlayer->SetThink( NULL ); - } - - char sName[128]; - Q_strncpy( sName, pPlayer->GetPlayerName(), sizeof( sName ) ); - - // First parse the name and remove any %'s - for ( char *pApersand = sName; pApersand != NULL && *pApersand != 0; pApersand++ ) - { - // Replace it with a space - if ( *pApersand == '%' ) - *pApersand = ' '; - } - - // notify other clients of player joining the game - UTIL_ClientPrintAll( HUD_PRINTNOTIFY, "#Game_connected", sName[0] != 0 ? sName : "" ); -} - -/* -=========== -ClientPutInServer - -called each time a player is spawned into the game -============ -*/ -void ClientPutInServer( edict_t *pEdict, const char *playername ) -{ - // Allocate a CBaseTFPlayer for pev, and call spawn - CSDKPlayer *pPlayer = CSDKPlayer::CreatePlayer( "player", pEdict ); - pPlayer->SetPlayerName( playername ); -} - - -void ClientActive( edict_t *pEdict, bool bLoadGame ) -{ - // Can't load games in CS! - Assert( !bLoadGame ); - - CSDKPlayer *pPlayer = ToSDKPlayer( CBaseEntity::Instance( pEdict ) ); - FinishClientPutInServer( pPlayer ); -} - - -/* -=============== -const char *GetGameDescription() - -Returns the descriptive name of this .dll. E.g., Half-Life, or Team Fortress 2 -=============== -*/ -const char *GetGameDescription() -{ - if ( g_pGameRules ) // this function may be called before the world has spawned, and the game rules initialized - return g_pGameRules->GetGameDescription(); - else - return "CounterStrike"; -} - - -//----------------------------------------------------------------------------- -// Purpose: Precache game-specific models & sounds -//----------------------------------------------------------------------------- -void ClientGamePrecache( void ) -{ - // Materials used by the client effects - CBaseEntity::PrecacheModel( "sprites/white.vmt" ); - CBaseEntity::PrecacheModel( "sprites/physbeam.vmt" ); -} - - -// called by ClientKill and DeadThink -void respawn( CBaseEntity *pEdict, bool fCopyCorpse ) -{ - if (gpGlobals->coop || gpGlobals->deathmatch) - { - if ( fCopyCorpse ) - { - // make a copy of the dead body for appearances sake - dynamic_cast< CBasePlayer* >( pEdict )->CreateCorpse(); - } - - // respawn player - pEdict->Spawn(); - } - else - { // restart the entire server - engine->ServerCommand("reload\n"); - } -} - -void GameStartFrame( void ) -{ - VPROF( "GameStartFrame" ); - - if ( g_pGameRules ) - g_pGameRules->Think(); - - if ( g_fGameOver ) - return; - - gpGlobals->teamplay = teamplay.GetInt() ? true : false; -} - -//========================================================= -// instantiate the proper game rules object -//========================================================= -void InstallGameRules() -{ - CreateGameRulesObject( "CSDKGameRules" ); -} diff --git a/game/server/sdk/sdk_env_message.cpp b/game/server/sdk/sdk_env_message.cpp deleted file mode 100644 index f3619de35..000000000 --- a/game/server/sdk/sdk_env_message.cpp +++ /dev/null @@ -1,46 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Simple entity to transmit message to the client -// -//=============================================================================// - -#include "cbase.h" - -class CGameMessageEntity : public CLogicalEntity -{ -public: - DECLARE_CLASS( CGameMessageEntity, CLogicalEntity ); - DECLARE_DATADESC(); - - CGameMessageEntity( void ) {}; - - void InputDisplayMessage( inputdata_t &data ); - - string_t m_strText; -}; - -LINK_ENTITY_TO_CLASS( logic_game_message, CGameMessageEntity ); - -BEGIN_DATADESC( CGameMessageEntity ) - - DEFINE_KEYFIELD( m_strText, FIELD_STRING, "text" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "DisplayMessage", InputDisplayMessage ), - -END_DATADESC() - -void CGameMessageEntity::InputDisplayMessage( inputdata_t &data ) -{ - // Only send this message the local player - CSingleUserRecipientFilter user( UTIL_PlayerByIndex(1) ); - user.MakeReliable(); - - // Start the message block - UserMessageBegin( user, "GameMessage" ); - - // Send our text to the client - WRITE_STRING( STRING( m_strText ) ); - - // End the message block - MessageEnd(); -} diff --git a/game/server/sdk/sdk_env_sparkler.cpp b/game/server/sdk/sdk_env_sparkler.cpp deleted file mode 100644 index 5d8a303ad..000000000 --- a/game/server/sdk/sdk_env_sparkler.cpp +++ /dev/null @@ -1,104 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: A simple test entity for creating special effects -// -//=============================================================================// - -#include "cbase.h" -#include "te_effect_dispatch.h" - -// Declare the sparkler entity for the server-side -class CSparkler : public CBaseEntity -{ -public: - DECLARE_SERVERCLASS(); - DECLARE_CLASS( CSparkler, CBaseEntity ); - - void Spawn( void ); - - void InputToggle( inputdata_t &input ); // Input function for toggling our effect's state - void InputScale( inputdata_t &input ); - -private: - CNetworkVar( bool, m_bEmit ); // Marks whether the effect should be active or not - CNetworkVar( float, m_flScale ); // The size and speed of the effect - - DECLARE_DATADESC(); -}; - -// Link our class to the "env_sparkler" entity classname -LINK_ENTITY_TO_CLASS( env_sparkler, CSparkler ); - -// Declare our data description for this entity -BEGIN_DATADESC( CSparkler ) - DEFINE_FIELD( m_bEmit, FIELD_BOOLEAN ), - - DEFINE_KEYFIELD( m_flScale, FIELD_FLOAT, "scale" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), // Declare our toggle input function - DEFINE_INPUTFUNC( FIELD_FLOAT, "Scale", InputScale ), -END_DATADESC() - -// Declare the data-table for server/client communication -IMPLEMENT_SERVERCLASS_ST( CSparkler, DT_Sparkler ) - SendPropInt( SENDINFO( m_bEmit ), 1, SPROP_UNSIGNED ), // Declare our boolean state variable - SendPropFloat( SENDINFO( m_flScale ), 0, SPROP_NOSCALE ), -END_SEND_TABLE() - -//----------------------------------------------------------------------------- -// Purpose: Spawn function for this entity -//----------------------------------------------------------------------------- -void CSparkler::Spawn( void ) -{ - SetMoveType( MOVETYPE_NONE ); // Will not move on its own - SetSolid( SOLID_NONE ); // Will not collide with anything - - // Set a size for culling - UTIL_SetSize( this, -Vector(2,2,2), Vector(2,2,2) ); - - // We must add this flag to receive network transmitions - AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); -} - -//----------------------------------------------------------------------------- -// Purpose: Toggles the emission state of the effect -//----------------------------------------------------------------------------- -void CSparkler::InputToggle( inputdata_t &input ) -{ - // Toggle our state - m_bEmit = !m_bEmit; -} - -//----------------------------------------------------------------------------- -// Purpose: Change our scale via a float value -//----------------------------------------------------------------------------- -void CSparkler::InputScale( inputdata_t &input ) -{ - // Change our scale - m_flScale = input.value.Float(); -} - -// ============================================================================ -// -// Dispatch Effect version -// -// ============================================================================ - -//----------------------------------------------------------------------------- -// Purpose: Create a sparkle effect at the given location of the given size -// Input : &position - Where to emit from -// flSize - Size of the effect -//----------------------------------------------------------------------------- -void MakeSparkle( const Vector &origin, float flScale ) -{ - CEffectData data; - - // Send our origin - data.m_vOrigin = origin; - - // Send our scale - data.m_flScale = flScale; - - // Send the effect off to the client - DispatchEffect( "Sparkle", data ); -} diff --git a/game/server/sdk/sdk_eventlog.cpp b/game/server/sdk/sdk_eventlog.cpp deleted file mode 100644 index a5c208f44..000000000 --- a/game/server/sdk/sdk_eventlog.cpp +++ /dev/null @@ -1,55 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "../EventLog.h" -#include "KeyValues.h" - -class CSDKEventLog : public CEventLog -{ -private: - typedef CEventLog BaseClass; - -public: - virtual ~CSDKEventLog() {}; - -public: - bool PrintEvent( IGameEvent * event ) // override virtual function - { - if ( BaseClass::PrintEvent( event ) ) - { - return true; - } - - if ( Q_strcmp(event->GetName(), "sdk_") == 0 ) - { - return PrintSDKEvent( event ); - } - - return false; - } - -protected: - - bool PrintSDKEvent( IGameEvent * event ) // print Mod specific logs - { - //const char * name = event->GetName() + Q_strlen("sdk_"); // remove prefix - return false; - } - -}; - -CSDKEventLog g_SDKEventLog; - -//----------------------------------------------------------------------------- -// Singleton access -//----------------------------------------------------------------------------- -IGameSystem* GameLogSystem() -{ - return &g_SDKEventLog; -} - diff --git a/game/server/sdk/sdk_gameinterface.cpp b/game/server/sdk/sdk_gameinterface.cpp deleted file mode 100644 index 0c60f3d60..000000000 --- a/game/server/sdk/sdk_gameinterface.cpp +++ /dev/null @@ -1,29 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "gameinterface.h" -#include "mapentities.h" - - -// -------------------------------------------------------------------------------------------- // -// Mod-specific CServerGameClients implementation. -// -------------------------------------------------------------------------------------------- // - -void CServerGameClients::GetPlayerLimits( int& minplayers, int& maxplayers, int &defaultMaxPlayers ) const -{ - minplayers = 2; // Force multiplayer. - maxplayers = MAX_PLAYERS; - defaultMaxPlayers = 32; -} - -// -------------------------------------------------------------------------------------------- // -// Mod-specific CServerGameDLL implementation. -// -------------------------------------------------------------------------------------------- // - -void CServerGameDLL::LevelInit_ParseAllEntities( const char *pMapEntities ) -{ -} diff --git a/game/server/sdk/sdk_logicalentity.cpp b/game/server/sdk/sdk_logicalentity.cpp deleted file mode 100644 index 6d181fecd..000000000 --- a/game/server/sdk/sdk_logicalentity.cpp +++ /dev/null @@ -1,66 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Simple logical entity that counts up to a threshold value, then -// fires an output when reached. -// -//=============================================================================// - -#include "cbase.h" - -class CMyLogicalEntity : public CLogicalEntity -{ -public: - DECLARE_CLASS( CMyLogicalEntity , CLogicalEntity ); - DECLARE_DATADESC(); - - // Constructor - CMyLogicalEntity ( void ) : m_nCounter( 0 ) {} - - // Input function - void InputTick( inputdata_t &inputData ); - -private: - - int m_nThreshold; // Count at which to fire our output - int m_nCounter; // Internal counter - - COutputEvent m_OnThreshold; // Output even when the counter reaches the threshold -}; - -LINK_ENTITY_TO_CLASS( my_logical_entity, CMyLogicalEntity ); - -// Start of our data description for the class -BEGIN_DATADESC( CMyLogicalEntity ) - - // For save/load - DEFINE_FIELD( m_nCounter, FIELD_INTEGER ), - - // Links our member variable to our keyvalue from Hammer - DEFINE_KEYFIELD( m_nThreshold, FIELD_INTEGER, "threshold" ), - - // Links our input name from Hammer to our input member function - DEFINE_INPUTFUNC( FIELD_VOID, "Tick", InputTick ), - - // Links our output member to the output name used by Hammer - DEFINE_OUTPUT( m_OnThreshold, "OnThreshold" ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: Handle a tick input from another entity -//----------------------------------------------------------------------------- -void CMyLogicalEntity ::InputTick( inputdata_t &inputData ) -{ - // Increment our counter - m_nCounter++; - - // See if we've met or crossed our threshold value - if ( m_nCounter >= m_nThreshold ) - { - // Fire an output event - m_OnThreshold.FireOutput( inputData.pActivator, this ); - - // Reset our counter - m_nCounter = 0; - } -} diff --git a/game/server/sdk/sdk_modelentity.cpp b/game/server/sdk/sdk_modelentity.cpp deleted file mode 100644 index c78c6e555..000000000 --- a/game/server/sdk/sdk_modelentity.cpp +++ /dev/null @@ -1,128 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Simple model entity that randomly moves and changes direction -// when activated. -// -//=============================================================================// - -#include "cbase.h" - -class CMyModelEntity : public CBaseAnimating -{ -public: - DECLARE_CLASS( CMyModelEntity, CBaseAnimating ); - DECLARE_DATADESC(); - - void Spawn( void ); - void Precache( void ); - - void MoveThink( void ); - - // Input function - void InputToggle( inputdata_t &inputData ); - -private: - - bool m_bActive; - float m_flNextChangeTime; -}; - -LINK_ENTITY_TO_CLASS( my_model_entity, CMyModelEntity ); - -// Start of our data description for the class -BEGIN_DATADESC( CMyModelEntity ) - - // Save/restore our active state - DEFINE_FIELD( m_bActive, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flNextChangeTime, FIELD_TIME ), - - // Links our input name from Hammer to our input member function - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - - // Declare our think function - DEFINE_THINKFUNC( MoveThink ), - -END_DATADESC() - -// Name of our entity's model -#define ENTITY_MODEL "models/gibs/airboat_broken_engine.mdl" - -//----------------------------------------------------------------------------- -// Purpose: Precache assets used by the entity -//----------------------------------------------------------------------------- -void CMyModelEntity::Precache( void ) -{ - PrecacheModel( ENTITY_MODEL ); -} - -//----------------------------------------------------------------------------- -// Purpose: Sets up the entity's initial state -//----------------------------------------------------------------------------- -void CMyModelEntity::Spawn( void ) -{ - Precache(); - - SetModel( ENTITY_MODEL ); - SetSolid( SOLID_BBOX ); - UTIL_SetSize( this, -Vector(20,20,20), Vector(20,20,20) ); - - m_bActive = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Think function to randomly move the entity -//----------------------------------------------------------------------------- -void CMyModelEntity::MoveThink( void ) -{ - // See if we should change direction again - if ( m_flNextChangeTime < gpGlobals->curtime ) - { - // Randomly take a new direction and speed - Vector vecNewVelocity = RandomVector( -64.0f, 64.0f ); - SetAbsVelocity( vecNewVelocity ); - - // Randomly change it again within one to three seconds - m_flNextChangeTime = gpGlobals->curtime + random->RandomFloat( 1.0f, 3.0f ); - } - - // Snap our facing to where we're heading - Vector velFacing = GetAbsVelocity(); - QAngle angFacing; - VectorAngles( velFacing, angFacing ); - SetAbsAngles( angFacing ); - - // Think every 20Hz - SetNextThink( gpGlobals->curtime + 0.05f ); -} - -//----------------------------------------------------------------------------- -// Purpose: Toggle the movement of the entity -//----------------------------------------------------------------------------- -void CMyModelEntity::InputToggle( inputdata_t &inputData ) -{ - // Toggle our active state - if ( !m_bActive ) - { - // Start thinking - SetThink( &CMyModelEntity::MoveThink ); - SetNextThink( gpGlobals->curtime + 0.05f ); - - // Start flying - SetMoveType( MOVETYPE_FLY ); - - // Set our next time for changing our speed and direction - m_flNextChangeTime = gpGlobals->curtime; - m_bActive = true; - } - else - { - // Stop thinking - SetThink( NULL ); - - // Stop moving - SetAbsVelocity( vec3_origin ); - SetMoveType( MOVETYPE_NONE ); - - m_bActive = false; - } -} diff --git a/game/server/sdk/sdk_player.cpp b/game/server/sdk/sdk_player.cpp deleted file mode 100644 index 91e97a0a1..000000000 --- a/game/server/sdk/sdk_player.cpp +++ /dev/null @@ -1,390 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Player for HL1. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "sdk_player.h" -#include "sdk_gamerules.h" -#include "weapon_sdkbase.h" -#include "predicted_viewmodel.h" -#include "iservervehicle.h" -#include "viewport_panel_names.h" - -extern int gEvilImpulse101; - -// Linux compile needs this -extern void SendProxy_Origin( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); - -#define SDK_PLAYER_MODEL "models/player/terror.mdl" - - -// -------------------------------------------------------------------------------- // -// Player animation event. Sent to the client when a player fires, jumps, reloads, etc.. -// -------------------------------------------------------------------------------- // - -class CTEPlayerAnimEvent : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEPlayerAnimEvent, CBaseTempEntity ); - DECLARE_SERVERCLASS(); - - CTEPlayerAnimEvent( const char *name ) : CBaseTempEntity( name ) - { - } - - CNetworkHandle( CBasePlayer, m_hPlayer ); - CNetworkVar( int, m_iEvent ); - CNetworkVar( int, m_nData ); -}; - -#define THROWGRENADE_COUNTER_BITS 3 - -IMPLEMENT_SERVERCLASS_ST_NOBASE( CTEPlayerAnimEvent, DT_TEPlayerAnimEvent ) - SendPropEHandle( SENDINFO( m_hPlayer ) ), - SendPropInt( SENDINFO( m_iEvent ), Q_log2( PLAYERANIMEVENT_COUNT ) + 1, SPROP_UNSIGNED ), - SendPropInt( SENDINFO( m_nData ), 32 ) -END_SEND_TABLE() - -static CTEPlayerAnimEvent g_TEPlayerAnimEvent( "PlayerAnimEvent" ); - -void TE_PlayerAnimEvent( CBasePlayer *pPlayer, PlayerAnimEvent_t event, int nData ) -{ - CPVSFilter filter( (const Vector&)pPlayer->EyePosition() ); - - g_TEPlayerAnimEvent.m_hPlayer = pPlayer; - g_TEPlayerAnimEvent.m_iEvent = event; - g_TEPlayerAnimEvent.m_nData = nData; - g_TEPlayerAnimEvent.Create( filter, 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: Filters updates to a variable so that only non-local players see -// the changes. This is so we can send a low-res origin to non-local players -// while sending a hi-res one to the local player. -// Input : *pVarData - -// *pOut - -// objectID - -//----------------------------------------------------------------------------- - -void* SendProxy_SendNonLocalDataTable( const SendProp *pProp, const void *pStruct, const void *pVarData, CSendProxyRecipients *pRecipients, int objectID ) -{ - pRecipients->SetAllRecipients(); - pRecipients->ClearRecipient( objectID - 1 ); - return ( void * )pVarData; -} -REGISTER_SEND_PROXY_NON_MODIFIED_POINTER( SendProxy_SendNonLocalDataTable ); - -// -------------------------------------------------------------------------------- // -// Tables. -// -------------------------------------------------------------------------------- // - -LINK_ENTITY_TO_CLASS( player, CSDKPlayer ); -PRECACHE_REGISTER(player); - -BEGIN_SEND_TABLE_NOBASE( CSDKPlayer, DT_SDKLocalPlayerExclusive ) - SendPropInt( SENDINFO( m_iShotsFired ), 8, SPROP_UNSIGNED ), - // send a hi-res origin to the local player for use in prediction - SendPropVector (SENDINFO(m_vecOrigin), -1, SPROP_NOSCALE|SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_Origin ), -END_SEND_TABLE() - -BEGIN_SEND_TABLE_NOBASE( CSDKPlayer, DT_SDKNonLocalPlayerExclusive ) - // send a lo-res origin to other players - SendPropVector (SENDINFO(m_vecOrigin), -1, SPROP_COORD_MP_LOWPRECISION|SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_Origin ), -END_SEND_TABLE() - - -IMPLEMENT_SERVERCLASS_ST( CSDKPlayer, DT_SDKPlayer ) - SendPropExclude( "DT_BaseAnimating", "m_flPoseParameter" ), - SendPropExclude( "DT_BaseAnimating", "m_flPlaybackRate" ), - SendPropExclude( "DT_BaseAnimating", "m_nSequence" ), - SendPropExclude( "DT_BaseEntity", "m_angRotation" ), - SendPropExclude( "DT_BaseAnimatingOverlay", "overlay_vars" ), - SendPropExclude( "DT_BaseEntity", "m_vecOrigin" ), - - // playeranimstate and clientside animation takes care of these on the client - SendPropExclude( "DT_ServerAnimationData" , "m_flCycle" ), - SendPropExclude( "DT_AnimTimeMustBeFirst" , "m_flAnimTime" ), - - // Data that only gets sent to the local player. - SendPropDataTable( "sdklocaldata", 0, &REFERENCE_SEND_TABLE(DT_SDKLocalPlayerExclusive), SendProxy_SendLocalDataTable ), - SendPropDataTable( "sdknonlocaldata", 0, &REFERENCE_SEND_TABLE(DT_SDKNonLocalPlayerExclusive), SendProxy_SendNonLocalDataTable ), - - SendPropAngle( SENDINFO_VECTORELEM2(m_angEyeAngles, 0, x), 11 ), - SendPropAngle( SENDINFO_VECTORELEM2(m_angEyeAngles, 1, y), 11 ), - SendPropEHandle( SENDINFO( m_hRagdoll ) ), - - SendPropInt( SENDINFO( m_iThrowGrenadeCounter ), THROWGRENADE_COUNTER_BITS, SPROP_UNSIGNED ), -END_SEND_TABLE() - -class CSDKRagdoll : public CBaseAnimatingOverlay -{ -public: - DECLARE_CLASS( CSDKRagdoll, CBaseAnimatingOverlay ); - DECLARE_SERVERCLASS(); - - // Transmit ragdolls to everyone. - virtual int UpdateTransmitState() - { - return SetTransmitState( FL_EDICT_ALWAYS ); - } - -public: - // In case the client has the player entity, we transmit the player index. - // In case the client doesn't have it, we transmit the player's model index, origin, and angles - // so they can create a ragdoll in the right place. - CNetworkHandle( CBaseEntity, m_hPlayer ); // networked entity handle - CNetworkVector( m_vecRagdollVelocity ); - CNetworkVector( m_vecRagdollOrigin ); -}; - -LINK_ENTITY_TO_CLASS( sdk_ragdoll, CSDKRagdoll ); - -IMPLEMENT_SERVERCLASS_ST_NOBASE( CSDKRagdoll, DT_SDKRagdoll ) - SendPropVector( SENDINFO(m_vecRagdollOrigin), -1, SPROP_COORD ), - SendPropEHandle( SENDINFO( m_hPlayer ) ), - SendPropModelIndex( SENDINFO( m_nModelIndex ) ), - SendPropInt ( SENDINFO(m_nForceBone), 8, 0 ), - SendPropVector ( SENDINFO(m_vecForce), -1, SPROP_NOSCALE ), - SendPropVector( SENDINFO( m_vecRagdollVelocity ) ) -END_SEND_TABLE() - - -// -------------------------------------------------------------------------------- // - -void cc_CreatePredictionError_f() -{ - CBaseEntity *pEnt = CBaseEntity::Instance( 1 ); - pEnt->SetAbsOrigin( pEnt->GetAbsOrigin() + Vector( 63, 0, 0 ) ); -} - -ConCommand cc_CreatePredictionError( "CreatePredictionError", cc_CreatePredictionError_f, "Create a prediction error", FCVAR_CHEAT ); - - -CSDKPlayer::CSDKPlayer() -{ - m_PlayerAnimState = CreatePlayerAnimState( this, this, LEGANIM_9WAY, true ); - - UseClientSideAnimation(); - m_angEyeAngles.Init(); - - SetViewOffset( SDK_PLAYER_VIEW_OFFSET ); - - m_iThrowGrenadeCounter = 0; -} - - -CSDKPlayer::~CSDKPlayer() -{ - m_PlayerAnimState->Release(); -} - - -CSDKPlayer *CSDKPlayer::CreatePlayer( const char *className, edict_t *ed ) -{ - CSDKPlayer::s_PlayerEdict = ed; - return (CSDKPlayer*)CreateEntityByName( className ); -} - -void CSDKPlayer::LeaveVehicle( const Vector &vecExitPoint, const QAngle &vecExitAngles ) -{ - BaseClass::LeaveVehicle( vecExitPoint, vecExitAngles ); - - //teleport physics shadow too - // Vector newPos = GetAbsOrigin(); - // QAngle newAng = GetAbsAngles(); - - // Teleport( &newPos, &newAng, &vec3_origin ); -} - -void CSDKPlayer::PreThink(void) -{ - // Riding a vehicle? - if ( IsInAVehicle() ) - { - // make sure we update the client, check for timed damage and update suit even if we are in a vehicle - UpdateClientData(); - CheckTimeBasedDamage(); - - // Allow the suit to recharge when in the vehicle. - CheckSuitUpdate(); - - WaterMove(); - return; - } - - BaseClass::PreThink(); -} - - -void CSDKPlayer::PostThink() -{ - BaseClass::PostThink(); - - QAngle angles = GetLocalAngles(); - angles[PITCH] = 0; - SetLocalAngles( angles ); - - // Store the eye angles pitch so the client can compute its animation state correctly. - m_angEyeAngles = EyeAngles(); - - m_PlayerAnimState->Update( m_angEyeAngles[YAW], m_angEyeAngles[PITCH] ); -} - - -void CSDKPlayer::Precache() -{ - PrecacheModel( SDK_PLAYER_MODEL ); - - BaseClass::Precache(); -} - -void CSDKPlayer::Spawn() -{ - SetModel( SDK_PLAYER_MODEL ); - SetMoveType( MOVETYPE_WALK ); - RemoveSolidFlags( FSOLID_NOT_SOLID ); - - m_hRagdoll = NULL; - - BaseClass::Spawn(); -} - -void CSDKPlayer::InitialSpawn( void ) -{ - BaseClass::InitialSpawn(); - - const ConVar *hostname = cvar->FindVar( "hostname" ); - const char *title = (hostname) ? hostname->GetString() : "MESSAGE OF THE DAY"; - - // open info panel on client showing MOTD: - KeyValues *data = new KeyValues("data"); - data->SetString( "title", title ); // info panel title - data->SetString( "type", "1" ); // show userdata from stringtable entry - data->SetString( "msg", "motd" ); // use this stringtable entry - data->SetString( "cmd", "impulse 101" );// exec this command if panel closed - - ShowViewPortPanel( PANEL_INFO, true, data ); - - data->deleteThis(); -} - -void CSDKPlayer::Event_Killed( const CTakeDamageInfo &info ) -{ - // Note: since we're dead, it won't draw us on the client, but we don't set EF_NODRAW - // because we still want to transmit to the clients in our PVS. - - BaseClass::Event_Killed( info ); - - CreateRagdollEntity(); -} - -void CSDKPlayer::CreateRagdollEntity() -{ - // If we already have a ragdoll, don't make another one. - CSDKRagdoll *pRagdoll = dynamic_cast< CSDKRagdoll* >( m_hRagdoll.Get() ); - - if ( !pRagdoll ) - { - // create a new one - pRagdoll = dynamic_cast< CSDKRagdoll* >( CreateEntityByName( "sdk_ragdoll" ) ); - } - - if ( pRagdoll ) - { - pRagdoll->m_hPlayer = this; - pRagdoll->m_vecRagdollOrigin = GetAbsOrigin(); - pRagdoll->m_vecRagdollVelocity = GetAbsVelocity(); - pRagdoll->m_nModelIndex = m_nModelIndex; - pRagdoll->m_nForceBone = m_nForceBone; - pRagdoll->m_vecForce = Vector(0,0,0); - } - - // ragdolls will be removed on round restart automatically - m_hRagdoll = pRagdoll; -} - -void CSDKPlayer::DoAnimationEvent( PlayerAnimEvent_t event, int nData ) -{ - if ( event == PLAYERANIMEVENT_THROW_GRENADE ) - { - // Grenade throwing has to synchronize exactly with the player's grenade weapon going away, - // and events get delayed a bit, so we let CCSPlayerAnimState pickup the change to this - // variable. - m_iThrowGrenadeCounter = (m_iThrowGrenadeCounter+1) % (1<DoAnimationEvent( event, nData ); - TE_PlayerAnimEvent( this, event, nData ); // Send to any clients who can see this guy. - } -} - -CWeaponSDKBase* CSDKPlayer::GetActiveSDKWeapon() const -{ - return dynamic_cast< CWeaponSDKBase* >( GetActiveWeapon() ); -} - -void CSDKPlayer::CreateViewModel( int index /*=0*/ ) -{ - Assert( index >= 0 && index < MAX_VIEWMODELS ); - - if ( GetViewModel( index ) ) - return; - - CPredictedViewModel *vm = ( CPredictedViewModel * )CreateEntityByName( "predicted_viewmodel" ); - if ( vm ) - { - vm->SetAbsOrigin( GetAbsOrigin() ); - vm->SetOwner( this ); - vm->SetIndex( index ); - DispatchSpawn( vm ); - vm->FollowEntity( this, false ); - m_hViewModel.Set( index, vm ); - } -} - -void CSDKPlayer::CheatImpulseCommands( int iImpulse ) -{ - if ( iImpulse != 101 ) - { - BaseClass::CheatImpulseCommands( iImpulse ); - return ; - } - gEvilImpulse101 = true; - - EquipSuit(); - - GiveNamedItem( "weapon_mp5" ); - GiveNamedItem( "weapon_grenade" ); - GiveNamedItem( "weapon_shotgun" ); - - // Give the player everything! - GiveAmmo( 90, AMMO_BULLETS ); - GiveAmmo( 3, AMMO_GRENADE ); - - if ( GetHealth() < 100 ) - { - TakeHealth( 25, DMG_GENERIC ); - } - - gEvilImpulse101 = false; -} - - -void CSDKPlayer::FlashlightTurnOn( void ) -{ - AddEffects( EF_DIMLIGHT ); -} - -void CSDKPlayer::FlashlightTurnOff( void ) -{ - RemoveEffects( EF_DIMLIGHT ); -} - -int CSDKPlayer::FlashlightIsOn( void ) -{ - return IsEffectActive( EF_DIMLIGHT ); -} diff --git a/game/server/sdk/sdk_player.h b/game/server/sdk/sdk_player.h deleted file mode 100644 index ea76d1864..000000000 --- a/game/server/sdk/sdk_player.h +++ /dev/null @@ -1,99 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Player for SDK Game -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SDK_PLAYER_H -#define SDK_PLAYER_H -#pragma once - -#include "basemultiplayerplayer.h" -#include "server_class.h" -#include "sdk_playeranimstate.h" -#include "sdk_shareddefs.h" - - -//============================================================================= -// >> SDK Game player -//============================================================================= -class CSDKPlayer : public CBaseMultiplayerPlayer, public ISDKPlayerAnimStateHelpers -{ -public: - DECLARE_CLASS( CSDKPlayer, CBaseMultiplayerPlayer ); - DECLARE_SERVERCLASS(); - DECLARE_PREDICTABLE(); - - CSDKPlayer(); - ~CSDKPlayer(); - - static CSDKPlayer *CreatePlayer( const char *className, edict_t *ed ); - static CSDKPlayer* Instance( int iEnt ); - - // This passes the event to the client's and server's CPlayerAnimState. - void DoAnimationEvent( PlayerAnimEvent_t event, int nData = 0 ); - - virtual void FlashlightTurnOn( void ); - virtual void FlashlightTurnOff( void ); - virtual int FlashlightIsOn( void ); - - virtual void PreThink(); - virtual void PostThink(); - virtual void Spawn(); - virtual void InitialSpawn(); - virtual void Precache(); - virtual void Event_Killed( const CTakeDamageInfo &info ); - virtual void LeaveVehicle( const Vector &vecExitPoint, const QAngle &vecExitAngles ); - - CWeaponSDKBase* GetActiveSDKWeapon() const; - virtual void CreateViewModel( int viewmodelindex = 0 ); - - virtual void CheatImpulseCommands( int iImpulse ); - - CNetworkVar( int, m_iThrowGrenadeCounter ); // used to trigger grenade throw animations. - CNetworkQAngle( m_angEyeAngles ); // Copied from EyeAngles() so we can send it to the client. - CNetworkVar( int, m_iShotsFired ); // number of shots fired recently - - // Tracks our ragdoll entity. - CNetworkHandle( CBaseEntity, m_hRagdoll ); // networked entity handle - -// In shared code. -public: - // ISDKPlayerAnimState overrides. - virtual CWeaponSDKBase* SDKAnim_GetActiveWeapon(); - virtual bool SDKAnim_CanMove(); - - - void FireBullet( - Vector vecSrc, - const QAngle &shootAngles, - float vecSpread, - int iDamage, - int iBulletType, - CBaseEntity *pevAttacker, - bool bDoEffects, - float x, - float y ); - -private: - - void CreateRagdollEntity(); - - ISDKPlayerAnimState *m_PlayerAnimState; -}; - - -inline CSDKPlayer *ToSDKPlayer( CBaseEntity *pEntity ) -{ - if ( !pEntity || !pEntity->IsPlayer() ) - return NULL; - -#ifdef _DEBUG - Assert( dynamic_cast( pEntity ) != 0 ); -#endif - return static_cast< CSDKPlayer* >( pEntity ); -} - - -#endif // SDK_PLAYER_H diff --git a/game/server/sdk/sdk_playermove.cpp b/game/server/sdk/sdk_playermove.cpp deleted file mode 100644 index 1e8911d8e..000000000 --- a/game/server/sdk/sdk_playermove.cpp +++ /dev/null @@ -1,89 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "player_command.h" -#include "igamemovement.h" -#include "in_buttons.h" -#include "ipredictionsystem.h" -#include "sdk_player.h" -#include "iservervehicle.h" - - -static CMoveData g_MoveData; -CMoveData *g_pMoveData = &g_MoveData; - -IPredictionSystem *IPredictionSystem::g_pPredictionSystems = NULL; - - -//----------------------------------------------------------------------------- -// Sets up the move data for TF2 -//----------------------------------------------------------------------------- -class CSDKPlayerMove : public CPlayerMove -{ -DECLARE_CLASS( CSDKPlayerMove, CPlayerMove ); - -public: - virtual void StartCommand( CBasePlayer *player, CUserCmd *cmd ); - virtual void SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ); - virtual void FinishMove( CBasePlayer *player, CUserCmd *ucmd, CMoveData *move ); -}; - -// PlayerMove Interface -static CSDKPlayerMove g_PlayerMove; - -//----------------------------------------------------------------------------- -// Singleton accessor -//----------------------------------------------------------------------------- -CPlayerMove *PlayerMove() -{ - return &g_PlayerMove; -} - -//----------------------------------------------------------------------------- -// Main setup, finish -//----------------------------------------------------------------------------- - -void CSDKPlayerMove::StartCommand( CBasePlayer *player, CUserCmd *cmd ) -{ - BaseClass::StartCommand( player, cmd ); -} - -//----------------------------------------------------------------------------- -// Purpose: This is called pre player movement and copies all the data necessary -// from the player for movement. (Server-side, the client-side version -// of this code can be found in prediction.cpp.) -//----------------------------------------------------------------------------- -void CSDKPlayerMove::SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) -{ - BaseClass::SetupMove( player, ucmd, pHelper, move ); - - IServerVehicle *pVehicle = player->GetVehicle(); - if (pVehicle && gpGlobals->frametime != 0) - { - pVehicle->SetupMove( player, ucmd, pHelper, move ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: This is called post player movement to copy back all data that -// movement could have modified and that is necessary for future -// movement. (Server-side, the client-side version of this code can -// be found in prediction.cpp.) -//----------------------------------------------------------------------------- -void CSDKPlayerMove::FinishMove( CBasePlayer *player, CUserCmd *ucmd, CMoveData *move ) -{ - // Call the default FinishMove code. - BaseClass::FinishMove( player, ucmd, move ); - - IServerVehicle *pVehicle = player->GetVehicle(); - if (pVehicle && gpGlobals->frametime != 0) - { - pVehicle->FinishMove( player, ucmd, move ); - } -} diff --git a/game/server/sdk/sdk_team.cpp b/game/server/sdk/sdk_team.cpp deleted file mode 100644 index 5f306f191..000000000 --- a/game/server/sdk/sdk_team.cpp +++ /dev/null @@ -1,40 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Team management class. Contains all the details for a specific team -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "sdk_team.h" -#include "entitylist.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -// Datatable -IMPLEMENT_SERVERCLASS_ST(CSDKTeam, DT_SDKTeam) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( sdk_team_manager, CSDKTeam ); - -//----------------------------------------------------------------------------- -// Purpose: Get a pointer to the specified TF team manager -//----------------------------------------------------------------------------- -CSDKTeam *GetGlobalSDKTeam( int iIndex ) -{ - return (CSDKTeam*)GetGlobalTeam( iIndex ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Needed because this is an entity, but should never be used -//----------------------------------------------------------------------------- -void CSDKTeam::Init( const char *pName, int iNumber ) -{ - BaseClass::Init( pName, iNumber ); - - // Only detect changes every half-second. - NetworkProp()->SetUpdateInterval( 0.75f ); -} - diff --git a/game/server/sdk/sdk_team.h b/game/server/sdk/sdk_team.h deleted file mode 100644 index e9ff06301..000000000 --- a/game/server/sdk/sdk_team.h +++ /dev/null @@ -1,38 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Team management class. Contains all the details for a specific team -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SDK_TEAM_H -#define SDK_TEAM_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "utlvector.h" -#include "team.h" - - -//----------------------------------------------------------------------------- -// Purpose: Team Manager -//----------------------------------------------------------------------------- -class CSDKTeam : public CTeam -{ - DECLARE_CLASS( CSDKTeam, CTeam ); - DECLARE_SERVERCLASS(); - -public: - - // Initialization - virtual void Init( const char *pName, int iNumber ); -}; - - -extern CSDKTeam *GetGlobalSDKTeam( int iIndex ); - - -#endif // TF_TEAM_H diff --git a/game/server/sdk/sdk_vehicle_jeep.cpp b/game/server/sdk/sdk_vehicle_jeep.cpp deleted file mode 100644 index d1cd861e2..000000000 --- a/game/server/sdk/sdk_vehicle_jeep.cpp +++ /dev/null @@ -1,1679 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "vehicle_base.h" -#include "engine/IEngineSound.h" -#include "in_buttons.h" -#include "ammodef.h" -#include "IEffects.h" -#include "beam_shared.h" -#include "soundenvelope.h" -#include "decals.h" -#include "soundent.h" -#include "te_effect_dispatch.h" -#include "ndebugoverlay.h" -#include "movevars_shared.h" -#include "bone_setup.h" -#include "ai_basenpc.h" -#include "ai_hint.h" -#include "globalstate.h" -#include "eventqueue.h" -#include "rumble_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -ConVar sdk_jeep_weapon_damage( "sdk_jeep_weapon_damage", "15" ); -ConVar sdk_jeep_max_rounds ( "sdk_jeep_max_rounds", "0", FCVAR_REPLICATED ); -#define VEHICLE_HITBOX_DRIVER 1 -#define LOCK_SPEED 10 -#define JEEP_GUN_YAW "vehicle_weapon_yaw" -#define JEEP_GUN_PITCH "vehicle_weapon_pitch" -#define JEEP_GUN_SPIN "gun_spin" -#define JEEP_GUN_SPIN_RATE 20 - -#define CANNON_MAX_UP_PITCH 20 -#define CANNON_MAX_DOWN_PITCH 20 -#define CANNON_MAX_LEFT_YAW 90 -#define CANNON_MAX_RIGHT_YAW 90 - -#define GAUSS_BEAM_SPRITE "sprites/laserbeam.vmt" - -#define GAUSS_CHARGE_TIME 0.2f -#define MAX_GAUSS_CHARGE 16 -#define MAX_GAUSS_CHARGE_TIME 3 -#define DANGER_GAUSS_CHARGE_TIME 10 -#define GAUSS_NUM_BEAMS 4 - - -#define OVERTURNED_EXIT_WAITTIME 2.0f - -#define JEEP_AMMOCRATE_HITGROUP 5 -#define JEEP_WHEEL_COUNT 4 - -#define JEEP_STEERING_SLOW_ANGLE 50.0f -#define JEEP_STEERING_FAST_ANGLE 15.0f - -#define JEEP_AMMO_CRATE_CLOSE_DELAY 2.0f - -#define JEEP_DELTA_LENGTH_MAX 12.0f // 1 foot -#define JEEP_FRAMETIME_MIN 1e-6 - -ConVar hud_jeephint_numentries( "hud_jeephint_numentries", "10", FCVAR_NONE ); -ConVar g_jeepexitspeed( "g_jeepexitspeed", "100", FCVAR_CHEAT ); - -//============================================================================= -// -// Jeep water data. -// -struct JeepWaterData_t -{ - bool m_bWheelInWater[JEEP_WHEEL_COUNT]; - bool m_bWheelWasInWater[JEEP_WHEEL_COUNT]; - Vector m_vecWheelContactPoints[JEEP_WHEEL_COUNT]; - float m_flNextRippleTime[JEEP_WHEEL_COUNT]; - bool m_bBodyInWater; - bool m_bBodyWasInWater; - - DECLARE_SIMPLE_DATADESC(); -}; - -BEGIN_SIMPLE_DATADESC( JeepWaterData_t ) - DEFINE_ARRAY( m_bWheelInWater, FIELD_BOOLEAN, JEEP_WHEEL_COUNT ), - DEFINE_ARRAY( m_bWheelWasInWater, FIELD_BOOLEAN, JEEP_WHEEL_COUNT ), - DEFINE_ARRAY( m_vecWheelContactPoints, FIELD_VECTOR, JEEP_WHEEL_COUNT ), - DEFINE_ARRAY( m_flNextRippleTime, FIELD_TIME, JEEP_WHEEL_COUNT ), - DEFINE_FIELD( m_bBodyInWater, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bBodyWasInWater, FIELD_BOOLEAN ), -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: Four wheel physics vehicle server vehicle with weaponry -//----------------------------------------------------------------------------- -class CJeepFourWheelServerVehicle : public CFourWheelServerVehicle -{ - typedef CFourWheelServerVehicle BaseClass; -// IServerVehicle -public: - bool NPC_HasPrimaryWeapon( void ) { return true; } - void NPC_AimPrimaryWeapon( Vector vecTarget ); - int GetExitAnimToUse( Vector &vecEyeExitEndpoint, bool &bAllPointsBlocked ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CPropJeep : public CPropVehicleDriveable -{ - DECLARE_CLASS( CPropJeep, CPropVehicleDriveable ); - -public: - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - CPropJeep( void ); - - // CPropVehicle - virtual void ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ); - virtual void DriveVehicle( float flFrameTime, CUserCmd *ucmd, int iButtonsDown, int iButtonsReleased ); - virtual void SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ); - virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - virtual void DampenEyePosition( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles ); - virtual bool AllowBlockedExit( CBasePlayer *pPlayer, int nRole ) { return false; } - virtual bool CanExitVehicle( CBaseEntity *pEntity ); - virtual bool IsVehicleBodyInWater() { return m_WaterData.m_bBodyInWater; } - - // Passengers do not directly receive damage from blasts or radiation damage - virtual bool PassengerShouldReceiveDamage( CTakeDamageInfo &info ) - { - if ( GetServerVehicle() && GetServerVehicle()->IsPassengerExiting() ) - return false; - - if ( info.GetDamageType() & DMG_VEHICLE ) - return true; - - return (info.GetDamageType() & (DMG_RADIATION|DMG_BLAST) ) == 0; - } - - // CBaseEntity - void Think(void); - void Precache( void ); - void Spawn( void ); - void Activate( void ); - - virtual void CreateServerVehicle( void ); - virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true ); - virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - virtual float PassengerDamageModifier( const CTakeDamageInfo &info ); - virtual void EnterVehicle( CBasePlayer *pPlayer ); - virtual void ExitVehicle( int nRole ); - - void AimGunAt( Vector *endPos, float flInterval ); - bool TauCannonHasBeenCutOff( void ) { return m_bGunHasBeenCutOff; } - - // NPC Driving - bool NPC_HasPrimaryWeapon( void ) { return true; } - void NPC_AimPrimaryWeapon( Vector vecTarget ); - - const char *GetTracerType( void ) { return "AR2Tracer"; } - void DoImpactEffect( trace_t &tr, int nDamageType ); - - bool HeadlightIsOn( void ) { return m_bHeadlightIsOn; } - void HeadlightTurnOn( void ) { m_bHeadlightIsOn = true; } - void HeadlightTurnOff( void ) { m_bHeadlightIsOn = false; } - -private: - - void FireCannon( void ); - void ChargeCannon( void ); - void FireChargedCannon( void ); - - void DrawBeam( const Vector &startPos, const Vector &endPos, float width ); - void StopChargeSound( void ); - void GetCannonAim( Vector *resultDir ); - - void InitWaterData( void ); - void HandleWater( void ); - bool CheckWater( void ); - void CheckWaterLevel( void ); - void CreateSplash( const Vector &vecPosition ); - void CreateRipple( const Vector &vecPosition ); - - void UpdateSteeringAngle( void ); - void CreateDangerSounds( void ); - - void ComputePDControllerCoefficients( float *pCoefficientsOut, float flFrequency, float flDampening, float flDeltaTime ); - void DampenForwardMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime ); - void DampenUpMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime ); - - void InputShowHudHint( inputdata_t &inputdata ); - void InputStartRemoveTauCannon( inputdata_t &inputdata ); - void InputFinishRemoveTauCannon( inputdata_t &inputdata ); - -private: - - bool m_bGunHasBeenCutOff; - float m_flDangerSoundTime; - int m_nBulletType; - bool m_bCannonCharging; - float m_flCannonTime; - float m_flCannonChargeStartTime; - Vector m_vecGunOrigin; - CSoundPatch *m_sndCannonCharge; - int m_nSpinPos; - float m_aimYaw; - float m_aimPitch; - float m_throttleDisableTime; - float m_flAmmoCrateCloseTime; - - // handbrake after the fact to keep vehicles from rolling - float m_flHandbrakeTime; - bool m_bInitialHandbrake; - - float m_flOverturnedTime; - - Vector m_vecLastEyePos; - Vector m_vecLastEyeTarget; - Vector m_vecEyeSpeed; - Vector m_vecTargetSpeed; - - JeepWaterData_t m_WaterData; - - int m_iNumberOfEntries; - int m_nAmmoType; - - // Seagull perching - float m_flPlayerExitedTime; // Time at which the player last left this vehicle - float m_flLastSawPlayerAt; // Time at which we last saw the player - EHANDLE m_hLastPlayerInVehicle; - bool m_bHasPoop; - - CNetworkVar( bool, m_bHeadlightIsOn ); -}; - -BEGIN_DATADESC( CPropJeep ) - DEFINE_FIELD( m_bGunHasBeenCutOff, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flDangerSoundTime, FIELD_TIME ), - DEFINE_FIELD( m_nBulletType, FIELD_INTEGER ), - DEFINE_FIELD( m_bCannonCharging, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flCannonTime, FIELD_TIME ), - DEFINE_FIELD( m_flCannonChargeStartTime, FIELD_TIME ), - DEFINE_FIELD( m_vecGunOrigin, FIELD_POSITION_VECTOR ), - DEFINE_SOUNDPATCH( m_sndCannonCharge ), - DEFINE_FIELD( m_nSpinPos, FIELD_INTEGER ), - DEFINE_FIELD( m_aimYaw, FIELD_FLOAT ), - DEFINE_FIELD( m_aimPitch, FIELD_FLOAT ), - DEFINE_FIELD( m_throttleDisableTime, FIELD_TIME ), - DEFINE_FIELD( m_flHandbrakeTime, FIELD_TIME ), - DEFINE_FIELD( m_bInitialHandbrake, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flOverturnedTime, FIELD_TIME ), - DEFINE_FIELD( m_flAmmoCrateCloseTime, FIELD_FLOAT ), - DEFINE_FIELD( m_vecLastEyePos, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecLastEyeTarget, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecEyeSpeed, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecTargetSpeed, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_bHeadlightIsOn, FIELD_BOOLEAN ), - DEFINE_EMBEDDED( m_WaterData ), - - DEFINE_FIELD( m_iNumberOfEntries, FIELD_INTEGER ), - DEFINE_FIELD( m_nAmmoType, FIELD_INTEGER ), - - DEFINE_FIELD( m_flPlayerExitedTime, FIELD_TIME ), - DEFINE_FIELD( m_flLastSawPlayerAt, FIELD_TIME ), - DEFINE_FIELD( m_hLastPlayerInVehicle, FIELD_EHANDLE ), - DEFINE_FIELD( m_bHasPoop, FIELD_BOOLEAN ), - - DEFINE_INPUTFUNC( FIELD_VOID, "StartRemoveTauCannon", InputStartRemoveTauCannon ), - DEFINE_INPUTFUNC( FIELD_VOID, "FinishRemoveTauCannon", InputFinishRemoveTauCannon ), - -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CPropJeep, DT_PropJeep ) - SendPropBool( SENDINFO( m_bHeadlightIsOn ) ), -END_SEND_TABLE(); - -LINK_ENTITY_TO_CLASS( prop_vehicle_jeep, CPropJeep ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CPropJeep::CPropJeep( void ) -{ - m_bHasGun = true; - m_bGunHasBeenCutOff = false; - m_bCannonCharging = false; - m_flCannonChargeStartTime = 0; - m_flCannonTime = 0; - m_nBulletType = -1; - m_flOverturnedTime = 0.0f; - m_iNumberOfEntries = 0; - - m_vecEyeSpeed.Init(); - - InitWaterData(); - - m_bUnableToFire = true; - m_flAmmoCrateCloseTime = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::CreateServerVehicle( void ) -{ - // Create our armed server vehicle - m_pServerVehicle = new CJeepFourWheelServerVehicle(); - m_pServerVehicle->SetVehicle( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::Precache( void ) -{ - UTIL_PrecacheOther( "npc_seagull" ); - - PrecacheScriptSound( "PropJeep.AmmoClose" ); - PrecacheScriptSound( "PropJeep.FireCannon" ); - PrecacheScriptSound( "PropJeep.FireChargedCannon" ); - PrecacheScriptSound( "PropJeep.AmmoOpen" ); - - PrecacheScriptSound( "Jeep.GaussCharge" ); - - PrecacheModel( GAUSS_BEAM_SPRITE ); - - BaseClass::Precache(); -} - -//------------------------------------------------ -// Spawn -//------------------------------------------------ -void CPropJeep::Spawn( void ) -{ - // Setup vehicle as a real-wheels car. - SetVehicleType( VEHICLE_TYPE_CAR_WHEELS ); - - BaseClass::Spawn(); - m_flHandbrakeTime = gpGlobals->curtime + 0.1; - m_bInitialHandbrake = false; - - m_VehiclePhysics.SetHasBrakePedal( false ); - - m_flMinimumSpeedToEnterExit = LOCK_SPEED; - - m_nBulletType = GetAmmoDef()->Index("JeepAmmo"); - - if ( m_bHasGun ) - { - SetBodygroup( 1, true ); - } - else - { - SetBodygroup( 1, false ); - } - - // Initialize pose parameters - SetPoseParameter( JEEP_GUN_YAW, 0 ); - SetPoseParameter( JEEP_GUN_PITCH, 0 ); - m_nSpinPos = 0; - SetPoseParameter( JEEP_GUN_SPIN, m_nSpinPos ); - m_aimYaw = 0; - m_aimPitch = 0; - - AddSolidFlags( FSOLID_NOT_STANDABLE ); - - CAmmoDef *pAmmoDef = GetAmmoDef(); - m_nAmmoType = pAmmoDef->Index("JeepAmmo"); -} -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CPropJeep::Activate() -{ - BaseClass::Activate(); - - CBaseServerVehicle *pServerVehicle = dynamic_cast(GetServerVehicle()); - if ( pServerVehicle ) - { - if( pServerVehicle->GetPassenger() ) - { - // If a jeep comes back from a save game with a driver, make sure the engine rumble starts up. - pServerVehicle->StartEngineRumble(); - } - } -} -//----------------------------------------------------------------------------- -// Purpose: -// Input : &tr - -// nDamageType - -//----------------------------------------------------------------------------- -void CPropJeep::DoImpactEffect( trace_t &tr, int nDamageType ) -{ - //Draw our beam - DrawBeam( tr.startpos, tr.endpos, 2.4 ); - - if ( (tr.surface.flags & SURF_SKY) == false ) - { - CPVSFilter filter( tr.endpos ); - te->GaussExplosion( filter, 0.0f, tr.endpos, tr.plane.normal, 0 ); - - UTIL_ImpactTrace( &tr, m_nBulletType ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::TraceAttack( const CTakeDamageInfo &inputInfo, const Vector &vecDir, trace_t *ptr ) -{ - CTakeDamageInfo info = inputInfo; - if ( ptr->hitbox != VEHICLE_HITBOX_DRIVER ) - { - if ( inputInfo.GetDamageType() & DMG_BULLET ) - { - info.ScaleDamage( 0.0001 ); - } - } - - BaseClass::TraceAttack( info, vecDir, ptr ); -} - -//----------------------------------------------------------------------------- -// Purpose: Modifies the passenger's damage taken through us -//----------------------------------------------------------------------------- -float CPropJeep::PassengerDamageModifier( const CTakeDamageInfo &info ) -{ - if ( info.GetInflictor() && FClassnameIs( info.GetInflictor(), "hunter_flechette" ) ) - return 0.1f; - - return 1.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CPropJeep::OnTakeDamage( const CTakeDamageInfo &inputInfo ) -{ - //Do scaled up physics damage to the car - CTakeDamageInfo info = inputInfo; - info.ScaleDamage( 25 ); - - // HACKHACK: Scale up grenades until we get a better explosion/pressure damage system - if ( inputInfo.GetDamageType() & DMG_BLAST ) - { - info.SetDamageForce( inputInfo.GetDamageForce() * 10 ); - } - VPhysicsTakeDamage( info ); - - // reset the damage - info.SetDamage( inputInfo.GetDamage() ); - - // small amounts of shock damage disrupt the car, but aren't transferred to the player - if ( info.GetDamageType() == DMG_SHOCK ) - { - if ( info.GetDamage() <= 10 ) - { - // take 10% damage and make the engine stall - info.ScaleDamage( 0.1 ); - m_throttleDisableTime = gpGlobals->curtime + 2; - } - } - - //Check to do damage to driver - if ( GetDriver() ) - { - //Take no damage from physics damages - if ( info.GetDamageType() & DMG_CRUSH ) - return 0; - - // Scale the damage and mark that we're passing it in so the base player accepts the damage - info.ScaleDamage( PassengerDamageModifier( info ) ); - info.SetDamageType( info.GetDamageType() | DMG_VEHICLE ); - - // Deal the damage to the passenger - GetDriver()->TakeDamage( info ); - } - - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Vector CPropJeep::BodyTarget( const Vector &posSrc, bool bNoisy ) -{ - Vector shotPos; - matrix3x4_t matrix; - - int eyeAttachmentIndex = LookupAttachment("vehicle_driver_eyes"); - GetAttachment( eyeAttachmentIndex, matrix ); - MatrixGetColumn( matrix, 3, shotPos ); - - if ( bNoisy ) - { - shotPos[0] += random->RandomFloat( -8.0f, 8.0f ); - shotPos[1] += random->RandomFloat( -8.0f, 8.0f ); - shotPos[2] += random->RandomFloat( -8.0f, 8.0f ); - } - - return shotPos; -} - -//----------------------------------------------------------------------------- -// Purpose: Aim Gun at a target -//----------------------------------------------------------------------------- -void CPropJeep::AimGunAt( Vector *endPos, float flInterval ) -{ - Vector aimPos = *endPos; - - // See if the gun should be allowed to aim - if ( IsOverturned() || m_bEngineLocked ) - { - SetPoseParameter( JEEP_GUN_YAW, 0 ); - SetPoseParameter( JEEP_GUN_PITCH, 0 ); - SetPoseParameter( JEEP_GUN_SPIN, 0 ); - return; - - // Make the gun go limp and look "down" - Vector v_forward, v_up; - AngleVectors( GetLocalAngles(), NULL, &v_forward, &v_up ); - aimPos = WorldSpaceCenter() + ( v_forward * -32.0f ) - Vector( 0, 0, 128.0f ); - } - - matrix3x4_t gunMatrix; - GetAttachment( LookupAttachment("gun_ref"), gunMatrix ); - - // transform the enemy into gun space - Vector localEnemyPosition; - VectorITransform( aimPos, gunMatrix, localEnemyPosition ); - - // do a look at in gun space (essentially a delta-lookat) - QAngle localEnemyAngles; - VectorAngles( localEnemyPosition, localEnemyAngles ); - - // convert to +/- 180 degrees - localEnemyAngles.x = UTIL_AngleDiff( localEnemyAngles.x, 0 ); - localEnemyAngles.y = UTIL_AngleDiff( localEnemyAngles.y, 0 ); - - float targetYaw = m_aimYaw + localEnemyAngles.y; - float targetPitch = m_aimPitch + localEnemyAngles.x; - - // Constrain our angles - float newTargetYaw = clamp( targetYaw, -CANNON_MAX_LEFT_YAW, CANNON_MAX_RIGHT_YAW ); - float newTargetPitch = clamp( targetPitch, -CANNON_MAX_DOWN_PITCH, CANNON_MAX_UP_PITCH ); - - // If the angles have been clamped, we're looking outside of our valid range - if ( fabs(newTargetYaw-targetYaw) > 1e-4 || fabs(newTargetPitch-targetPitch) > 1e-4 ) - { - m_bUnableToFire = true; - } - - targetYaw = newTargetYaw; - targetPitch = newTargetPitch; - - // Exponentially approach the target - float yawSpeed = 8; - float pitchSpeed = 8; - - m_aimYaw = UTIL_Approach( targetYaw, m_aimYaw, yawSpeed ); - m_aimPitch = UTIL_Approach( targetPitch, m_aimPitch, pitchSpeed ); - - SetPoseParameter( JEEP_GUN_YAW, -m_aimYaw); - SetPoseParameter( JEEP_GUN_PITCH, -m_aimPitch ); - - InvalidateBoneCache(); - - // read back to avoid drift when hitting limits - // as long as the velocity is less than the delta between the limit and 180, this is fine. - m_aimPitch = -GetPoseParameter( JEEP_GUN_PITCH ); - m_aimYaw = -GetPoseParameter( JEEP_GUN_YAW ); - - // Now draw crosshair for actual aiming point - Vector vecMuzzle, vecMuzzleDir; - QAngle vecMuzzleAng; - - GetAttachment( "Muzzle", vecMuzzle, vecMuzzleAng ); - AngleVectors( vecMuzzleAng, &vecMuzzleDir ); - - trace_t tr; - UTIL_TraceLine( vecMuzzle, vecMuzzle + (vecMuzzleDir * MAX_TRACE_LENGTH), MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - // see if we hit something, if so, adjust endPos to hit location - if ( tr.fraction < 1.0 ) - { - m_vecGunCrosshair = vecMuzzle + ( vecMuzzleDir * MAX_TRACE_LENGTH * tr.fraction ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::InitWaterData( void ) -{ - m_WaterData.m_bBodyInWater = false; - m_WaterData.m_bBodyWasInWater = false; - - for ( int iWheel = 0; iWheel < JEEP_WHEEL_COUNT; ++iWheel ) - { - m_WaterData.m_bWheelInWater[iWheel] = false; - m_WaterData.m_bWheelWasInWater[iWheel] = false; - m_WaterData.m_vecWheelContactPoints[iWheel].Init(); - m_WaterData.m_flNextRippleTime[iWheel] = 0; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::HandleWater( void ) -{ - // Only check the wheels and engine in water if we have a driver (player). - if ( !GetDriver() ) - return; - - // Check to see if we are in water. - if ( CheckWater() ) - { - for ( int iWheel = 0; iWheel < JEEP_WHEEL_COUNT; ++iWheel ) - { - // Create an entry/exit splash! - if ( m_WaterData.m_bWheelInWater[iWheel] != m_WaterData.m_bWheelWasInWater[iWheel] ) - { - CreateSplash( m_WaterData.m_vecWheelContactPoints[iWheel] ); - CreateRipple( m_WaterData.m_vecWheelContactPoints[iWheel] ); - } - - // Create ripples. - if ( m_WaterData.m_bWheelInWater[iWheel] && m_WaterData.m_bWheelWasInWater[iWheel] ) - { - if ( m_WaterData.m_flNextRippleTime[iWheel] < gpGlobals->curtime ) - { - // Stagger ripple times - m_WaterData.m_flNextRippleTime[iWheel] = gpGlobals->curtime + RandomFloat( 0.1, 0.3 ); - CreateRipple( m_WaterData.m_vecWheelContactPoints[iWheel] ); - } - } - } - } - - // Save of data from last think. - for ( int iWheel = 0; iWheel < JEEP_WHEEL_COUNT; ++iWheel ) - { - m_WaterData.m_bWheelWasInWater[iWheel] = m_WaterData.m_bWheelInWater[iWheel]; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CPropJeep::CheckWater( void ) -{ - bool bInWater = false; - - // Check all four wheels. - for ( int iWheel = 0; iWheel < JEEP_WHEEL_COUNT; ++iWheel ) - { - // Get the current wheel and get its contact point. - IPhysicsObject *pWheel = m_VehiclePhysics.GetWheel( iWheel ); - if ( !pWheel ) - continue; - - // Check to see if we hit water. - if ( pWheel->GetContactPoint( &m_WaterData.m_vecWheelContactPoints[iWheel], NULL ) ) - { - m_WaterData.m_bWheelInWater[iWheel] = ( UTIL_PointContents( m_WaterData.m_vecWheelContactPoints[iWheel] ) & MASK_WATER ) ? true : false; - if ( m_WaterData.m_bWheelInWater[iWheel] ) - { - bInWater = true; - } - } - } - - // Check the body and the BONNET. - int iEngine = LookupAttachment( "vehicle_engine" ); - Vector vecEnginePoint; - QAngle vecEngineAngles; - GetAttachment( iEngine, vecEnginePoint, vecEngineAngles ); - - m_WaterData.m_bBodyInWater = ( UTIL_PointContents( vecEnginePoint ) & MASK_WATER ) ? true : false; - if ( m_WaterData.m_bBodyInWater ) - { - if ( m_bHasPoop ) - { - RemoveAllDecals(); - m_bHasPoop = false; - } - - if ( !m_VehiclePhysics.IsEngineDisabled() ) - { - m_VehiclePhysics.SetDisableEngine( true ); - } - } - else - { - if ( m_VehiclePhysics.IsEngineDisabled() ) - { - m_VehiclePhysics.SetDisableEngine( false ); - } - } - - if ( bInWater ) - { - // Check the player's water level. - CheckWaterLevel(); - } - - return bInWater; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::CheckWaterLevel( void ) -{ - CBaseEntity *pEntity = GetDriver(); - if ( pEntity && pEntity->IsPlayer() ) - { - CBasePlayer *pPlayer = static_cast( pEntity ); - - Vector vecAttachPoint; - QAngle vecAttachAngles; - - // Check eyes. (vehicle_driver_eyes point) - int iAttachment = LookupAttachment( "vehicle_driver_eyes" ); - GetAttachment( iAttachment, vecAttachPoint, vecAttachAngles ); - - // Add the jeep's Z view offset - Vector vecUp; - AngleVectors( vecAttachAngles, NULL, NULL, &vecUp ); - vecUp.z = clamp( vecUp.z, 0.0f, vecUp.z ); - vecAttachPoint.z += r_JeepViewZHeight.GetFloat() * vecUp.z; - - bool bEyes = ( UTIL_PointContents( vecAttachPoint ) & MASK_WATER ) ? true : false; - if ( bEyes ) - { - pPlayer->SetWaterLevel( WL_Eyes ); - return; - } - - // Check waist. (vehicle_engine point -- see parent function). - if ( m_WaterData.m_bBodyInWater ) - { - pPlayer->SetWaterLevel( WL_Waist ); - return; - } - - // Check feet. (vehicle_feet_passenger0 point) - iAttachment = LookupAttachment( "vehicle_feet_passenger0" ); - GetAttachment( iAttachment, vecAttachPoint, vecAttachAngles ); - bool bFeet = ( UTIL_PointContents( vecAttachPoint ) & MASK_WATER ) ? true : false; - if ( bFeet ) - { - pPlayer->SetWaterLevel( WL_Feet ); - return; - } - - // Not in water. - pPlayer->SetWaterLevel( WL_NotInWater ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::CreateSplash( const Vector &vecPosition ) -{ - // Splash data. - CEffectData data; - data.m_fFlags = 0; - data.m_vOrigin = vecPosition; - data.m_vNormal.Init( 0.0f, 0.0f, 1.0f ); - VectorAngles( data.m_vNormal, data.m_vAngles ); - data.m_flScale = 10.0f + random->RandomFloat( 0, 2 ); - - // Create the splash.. - DispatchEffect( "watersplash", data ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::CreateRipple( const Vector &vecPosition ) -{ - // Ripple data. - CEffectData data; - data.m_fFlags = 0; - data.m_vOrigin = vecPosition; - data.m_vNormal.Init( 0.0f, 0.0f, 1.0f ); - VectorAngles( data.m_vNormal, data.m_vAngles ); - data.m_flScale = 10.0f + random->RandomFloat( 0, 2 ); - if ( GetWaterType() & CONTENTS_SLIME ) - { - data.m_fFlags |= FX_WATER_IN_SLIME; - } - - // Create the ripple. - DispatchEffect( "waterripple", data ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::Think(void) -{ - BaseClass::Think(); - -/* - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - - if ( m_bEngineLocked ) - { - m_bUnableToFire = true; - - if ( pPlayer != NULL ) - { - pPlayer->m_Local.m_iHideHUD |= HIDEHUD_VEHICLE_CROSSHAIR; - } - } - else - { - // Start this as false and update it again each frame - m_bUnableToFire = false; - - if ( pPlayer != NULL ) - { - pPlayer->m_Local.m_iHideHUD &= ~HIDEHUD_VEHICLE_CROSSHAIR; - } - } -*/ - - // Water!? - HandleWater(); - - SetSimulationTime( gpGlobals->curtime ); - - SetNextThink( gpGlobals->curtime ); - SetAnimatedEveryTick( true ); - - if ( !m_bInitialHandbrake ) // after initial timer expires, set the handbrake - { - m_bInitialHandbrake = true; - m_VehiclePhysics.SetHandbrake( true ); - m_VehiclePhysics.Think(); - } - - // Check overturned status. - if ( !IsOverturned() ) - { - m_flOverturnedTime = 0.0f; - } - else - { - m_flOverturnedTime += gpGlobals->frametime; - } - - // spin gun if charging cannon - //FIXME: Don't bother for E3 - if ( m_bCannonCharging ) - { - m_nSpinPos += JEEP_GUN_SPIN_RATE; - SetPoseParameter( JEEP_GUN_SPIN, m_nSpinPos ); - } - - // Aim gun based on the player view direction. - if ( m_hPlayer && !m_bExitAnimOn && !m_bEnterAnimOn ) - { - Vector vecEyeDir, vecEyePos; - m_hPlayer->EyePositionAndVectors( &vecEyePos, &vecEyeDir, NULL, NULL ); - - // Trace out from the player's eye point. - Vector vecEndPos = vecEyePos + ( vecEyeDir * MAX_TRACE_LENGTH ); - trace_t trace; - UTIL_TraceLine( vecEyePos, vecEndPos, MASK_SHOT, this, COLLISION_GROUP_NONE, &trace ); - - // See if we hit something, if so, adjust end position to hit location. - if ( trace.fraction < 1.0 ) - { - vecEndPos = vecEyePos + ( vecEyeDir * MAX_TRACE_LENGTH * trace.fraction ); - } - - //m_vecLookCrosshair = vecEndPos; - AimGunAt( &vecEndPos, 0.1f ); - } - - StudioFrameAdvance(); - - // If the enter or exit animation has finished, tell the server vehicle - if ( IsSequenceFinished() && (m_bExitAnimOn || m_bEnterAnimOn) ) - { - if ( m_bEnterAnimOn ) - { - m_VehiclePhysics.ReleaseHandbrake(); - StartEngine(); - - // HACKHACK: This forces the jeep to play a sound when it gets entered underwater - if ( m_VehiclePhysics.IsEngineDisabled() ) - { - CBaseServerVehicle *pServerVehicle = dynamic_cast(GetServerVehicle()); - if ( pServerVehicle ) - { - pServerVehicle->SoundStartDisabled(); - } - } - - // The first few time we get into the jeep, print the jeep help - if ( m_iNumberOfEntries < hud_jeephint_numentries.GetInt() ) - { - g_EventQueue.AddEvent( this, "ShowHudHint", 1.5f, this, this ); - m_iNumberOfEntries++; - } - } - - // If we're exiting and have had the tau cannon removed, we don't want to reset the animation - GetServerVehicle()->HandleEntryExitFinish( m_bExitAnimOn, true ); - } - - // See if the ammo crate needs to close - if ( ( m_flAmmoCrateCloseTime < gpGlobals->curtime ) && ( GetSequence() == LookupSequence( "ammo_open" ) ) ) - { - m_flAnimTime = gpGlobals->curtime; - m_flPlaybackRate = 0.0; - SetCycle( 0 ); - ResetSequence( LookupSequence( "ammo_close" ) ); - } - else if ( ( GetSequence() == LookupSequence( "ammo_close" ) ) && IsSequenceFinished() ) - { - m_flAnimTime = gpGlobals->curtime; - m_flPlaybackRate = 0.0; - SetCycle( 0 ); - - int nSequence = SelectWeightedSequence( ACT_IDLE ); - ResetSequence( nSequence ); - - CPASAttenuationFilter sndFilter( this, "PropJeep.AmmoClose" ); - EmitSound( sndFilter, entindex(), "PropJeep.AmmoClose" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &startPos - -// &endPos - -// width - -// useMuzzle - -//----------------------------------------------------------------------------- -void CPropJeep::DrawBeam( const Vector &startPos, const Vector &endPos, float width ) -{ - //Tracer down the middle - UTIL_Tracer( startPos, endPos, 0, TRACER_DONT_USE_ATTACHMENT, 6500, false, "GaussTracer" ); - - //Draw the main beam shaft - CBeam *pBeam = CBeam::BeamCreate( GAUSS_BEAM_SPRITE, 0.5 ); - - pBeam->SetStartPos( startPos ); - pBeam->PointEntInit( endPos, this ); - pBeam->SetEndAttachment( LookupAttachment("Muzzle") ); - pBeam->SetWidth( width ); - pBeam->SetEndWidth( 0.05f ); - pBeam->SetBrightness( 255 ); - pBeam->SetColor( 255, 185+random->RandomInt( -16, 16 ), 40 ); - pBeam->RelinkBeam(); - pBeam->LiveForTime( 0.1f ); - - //Draw electric bolts along shaft - pBeam = CBeam::BeamCreate( GAUSS_BEAM_SPRITE, 3.0f ); - - pBeam->SetStartPos( startPos ); - pBeam->PointEntInit( endPos, this ); - pBeam->SetEndAttachment( LookupAttachment("Muzzle") ); - - pBeam->SetBrightness( random->RandomInt( 64, 255 ) ); - pBeam->SetColor( 255, 255, 150+random->RandomInt( 0, 64 ) ); - pBeam->RelinkBeam(); - pBeam->LiveForTime( 0.1f ); - pBeam->SetNoise( 1.6f ); - pBeam->SetEndWidth( 0.1f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::FireCannon( void ) -{ - //Don't fire again if it's been too soon - if ( m_flCannonTime > gpGlobals->curtime ) - return; - - if ( m_bUnableToFire ) - return; - - CDisablePredictionFiltering disabler; - - m_flCannonTime = gpGlobals->curtime + 0.2f; - m_bCannonCharging = false; - - //Find the direction the gun is pointing in - Vector aimDir; - GetCannonAim( &aimDir ); - - FireBulletsInfo_t info( 1, m_vecGunOrigin, aimDir, VECTOR_CONE_1DEGREES, MAX_TRACE_LENGTH, m_nAmmoType ); - - info.m_nFlags = FIRE_BULLETS_ALLOW_WATER_SURFACE_IMPACTS; - info.m_pAttacker = m_hPlayer; - - FireBullets( info ); - - // Register a muzzleflash for the AI - if ( m_hPlayer ) - { - m_hPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 0.5 ); - m_hPlayer->RumbleEffect( RUMBLE_PISTOL, 0, RUMBLE_FLAG_RESTART ); - } - - CPASAttenuationFilter sndFilter( this, "PropJeep.FireCannon" ); - EmitSound( sndFilter, entindex(), "PropJeep.FireCannon" ); - - // make cylinders of gun spin a bit - m_nSpinPos += JEEP_GUN_SPIN_RATE; - //SetPoseParameter( JEEP_GUN_SPIN, m_nSpinPos ); //FIXME: Don't bother with this for E3, won't look right -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::FireChargedCannon( void ) -{ - CDisablePredictionFiltering disabler; - bool penetrated = false; - - m_bCannonCharging = false; - m_flCannonTime = gpGlobals->curtime + 0.5f; - - StopChargeSound(); - - CPASAttenuationFilter sndFilter( this, "PropJeep.FireChargedCannon" ); - EmitSound( sndFilter, entindex(), "PropJeep.FireChargedCannon" ); - - if( m_hPlayer ) - { - m_hPlayer->RumbleEffect( RUMBLE_357, 0, RUMBLE_FLAG_RESTART ); - } - - //Find the direction the gun is pointing in - Vector aimDir; - GetCannonAim( &aimDir ); - - Vector endPos = m_vecGunOrigin + ( aimDir * MAX_TRACE_LENGTH ); - - //Shoot a shot straight out - trace_t tr; - UTIL_TraceLine( m_vecGunOrigin, endPos, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - ClearMultiDamage(); - - //Find how much damage to do - float flChargeAmount = ( gpGlobals->curtime - m_flCannonChargeStartTime ) / MAX_GAUSS_CHARGE_TIME; - - //Clamp this - if ( flChargeAmount > 1.0f ) - { - flChargeAmount = 1.0f; - } - - //Determine the damage amount - //FIXME: Use ConVars! - float flDamage = 15 + ( ( 250 - 15 ) * flChargeAmount ); - - CBaseEntity *pHit = tr.m_pEnt; - - //Look for wall penetration - if ( tr.DidHitWorld() && !(tr.surface.flags & SURF_SKY) ) - { - //Try wall penetration - UTIL_ImpactTrace( &tr, m_nBulletType, "ImpactJeep" ); - UTIL_DecalTrace( &tr, "RedGlowFade" ); - - CPVSFilter filter( tr.endpos ); - te->GaussExplosion( filter, 0.0f, tr.endpos, tr.plane.normal, 0 ); - - Vector testPos = tr.endpos + ( aimDir * 48.0f ); - - UTIL_TraceLine( testPos, tr.endpos, MASK_SHOT, GetDriver(), COLLISION_GROUP_NONE, &tr ); - - if ( tr.allsolid == false ) - { - UTIL_DecalTrace( &tr, "RedGlowFade" ); - - penetrated = true; - } - } - else if ( pHit != NULL ) - { - CTakeDamageInfo dmgInfo( this, GetDriver(), flDamage, DMG_SHOCK ); - CalculateBulletDamageForce( &dmgInfo, GetAmmoDef()->Index("JeepAmmo"), aimDir, tr.endpos, 1.0f + flChargeAmount * 4.0f ); - - //Do direct damage to anything in our path - pHit->DispatchTraceAttack( dmgInfo, aimDir, &tr ); - } - - ApplyMultiDamage(); - - //Kick up an effect - if ( !(tr.surface.flags & SURF_SKY) ) - { - UTIL_ImpactTrace( &tr, m_nBulletType, "ImpactJeep" ); - - //Do a gauss explosion - CPVSFilter filter( tr.endpos ); - te->GaussExplosion( filter, 0.0f, tr.endpos, tr.plane.normal, 0 ); - } - - //Show the effect - DrawBeam( m_vecGunOrigin, tr.endpos, 9.6 ); - - // Register a muzzleflash for the AI - if ( m_hPlayer ) - { - m_hPlayer->SetMuzzleFlashTime( gpGlobals->curtime + 0.5f ); - } - - //Rock the car - IPhysicsObject *pObj = VPhysicsGetObject(); - - if ( pObj != NULL ) - { - Vector shoveDir = aimDir * -( flDamage * 500.0f ); - - pObj->ApplyForceOffset( shoveDir, m_vecGunOrigin ); - } - - //Do radius damage if we didn't penetrate the wall - if ( penetrated == true ) - { - RadiusDamage( CTakeDamageInfo( this, this, flDamage, DMG_SHOCK ), tr.endpos, 200.0f, CLASS_NONE, NULL ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::ChargeCannon( void ) -{ - //Don't fire again if it's been too soon - if ( m_flCannonTime > gpGlobals->curtime ) - return; - - //See if we're starting a charge - if ( m_bCannonCharging == false ) - { - m_flCannonChargeStartTime = gpGlobals->curtime; - m_bCannonCharging = true; - - //Start charging sound - CPASAttenuationFilter filter( this ); - m_sndCannonCharge = (CSoundEnvelopeController::GetController()).SoundCreate( filter, entindex(), CHAN_STATIC, "Jeep.GaussCharge", ATTN_NORM ); - - if ( m_hPlayer ) - { - m_hPlayer->RumbleEffect( RUMBLE_FLAT_LEFT, (int)(0.1 * 100), RUMBLE_FLAG_RESTART | RUMBLE_FLAG_LOOP | RUMBLE_FLAG_INITIAL_SCALE ); - } - - assert(m_sndCannonCharge!=NULL); - if ( m_sndCannonCharge != NULL ) - { - (CSoundEnvelopeController::GetController()).Play( m_sndCannonCharge, 1.0f, 50 ); - (CSoundEnvelopeController::GetController()).SoundChangePitch( m_sndCannonCharge, 250, 3.0f ); - } - - return; - } - else - { - float flChargeAmount = ( gpGlobals->curtime - m_flCannonChargeStartTime ) / MAX_GAUSS_CHARGE_TIME; - if ( flChargeAmount > 1.0f ) - { - flChargeAmount = 1.0f; - } - - float rumble = flChargeAmount * 0.5f; - - if( m_hPlayer ) - { - m_hPlayer->RumbleEffect( RUMBLE_FLAT_LEFT, (int)(rumble * 100), RUMBLE_FLAG_UPDATE_SCALE ); - } - } - - //TODO: Add muzzle effect? - - //TODO: Check for overcharge and have the weapon simply fire or instead "decharge"? -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::StopChargeSound( void ) -{ - if ( m_sndCannonCharge != NULL ) - { - (CSoundEnvelopeController::GetController()).SoundFadeOut( m_sndCannonCharge, 0.1f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Finds the true aiming position of the gun (looks at what player -// is looking at and adjusts) -// Input : &resultDir - direction to be calculated -//----------------------------------------------------------------------------- -void CPropJeep::GetCannonAim( Vector *resultDir ) -{ - Vector muzzleOrigin; - QAngle muzzleAngles; - - GetAttachment( LookupAttachment("gun_ref"), muzzleOrigin, muzzleAngles ); - - AngleVectors( muzzleAngles, resultDir ); -} - -//----------------------------------------------------------------------------- -// Purpose: If the player uses the jeep while at the back, he gets ammo from the crate instead -//----------------------------------------------------------------------------- -void CPropJeep::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - CBasePlayer *pPlayer = ToBasePlayer( pActivator ); - - if ( pPlayer == NULL) - return; - - // Find out if the player's looking at our ammocrate hitbox - Vector vecForward; - pPlayer->EyeVectors( &vecForward, NULL, NULL ); - - trace_t tr; - Vector vecStart = pPlayer->EyePosition(); - UTIL_TraceLine( vecStart, vecStart + vecForward * 1024, MASK_SOLID | CONTENTS_DEBRIS | CONTENTS_HITBOX, pPlayer, COLLISION_GROUP_NONE, &tr ); - - if ( tr.m_pEnt == this && tr.hitgroup == JEEP_AMMOCRATE_HITGROUP ) - { - // Player's using the crate. - // Fill up his SMG ammo. - pPlayer->GiveAmmo( 300, "SMG1"); - - if ( ( GetSequence() != LookupSequence( "ammo_open" ) ) && ( GetSequence() != LookupSequence( "ammo_close" ) ) ) - { - // Open the crate - m_flAnimTime = gpGlobals->curtime; - m_flPlaybackRate = 0.0; - SetCycle( 0 ); - ResetSequence( LookupSequence( "ammo_open" ) ); - - CPASAttenuationFilter sndFilter( this, "PropJeep.AmmoOpen" ); - EmitSound( sndFilter, entindex(), "PropJeep.AmmoOpen" ); - } - - m_flAmmoCrateCloseTime = gpGlobals->curtime + JEEP_AMMO_CRATE_CLOSE_DELAY; - return; - } - - // Fall back and get in the vehicle instead - BaseClass::Use( pActivator, pCaller, useType, value ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CPropJeep::CanExitVehicle( CBaseEntity *pEntity ) -{ - return ( !m_bEnterAnimOn && !m_bExitAnimOn && !m_bLocked && (m_nSpeed <= g_jeepexitspeed.GetFloat() ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::DampenEyePosition( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles ) -{ - // Get the frametime. (Check to see if enough time has passed to warrent dampening). - float flFrameTime = gpGlobals->frametime; - if ( flFrameTime < JEEP_FRAMETIME_MIN ) - { - vecVehicleEyePos = m_vecLastEyePos; - DampenUpMotion( vecVehicleEyePos, vecVehicleEyeAngles, 0.0f ); - return; - } - - // Keep static the sideways motion. - - // Dampen forward/backward motion. - DampenForwardMotion( vecVehicleEyePos, vecVehicleEyeAngles, flFrameTime ); - - // Blend up/down motion. - DampenUpMotion( vecVehicleEyePos, vecVehicleEyeAngles, flFrameTime ); -} - -//----------------------------------------------------------------------------- -// Use the controller as follows: -// speed += ( pCoefficientsOut[0] * ( targetPos - currentPos ) + pCoefficientsOut[1] * ( targetSpeed - currentSpeed ) ) * flDeltaTime; -//----------------------------------------------------------------------------- -void CPropJeep::ComputePDControllerCoefficients( float *pCoefficientsOut, - float flFrequency, float flDampening, - float flDeltaTime ) -{ - float flKs = 9.0f * flFrequency * flFrequency; - float flKd = 4.5f * flFrequency * flDampening; - - float flScale = 1.0f / ( 1.0f + flKd * flDeltaTime + flKs * flDeltaTime * flDeltaTime ); - - pCoefficientsOut[0] = flKs * flScale; - pCoefficientsOut[1] = ( flKd + flKs * flDeltaTime ) * flScale; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::DampenForwardMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime ) -{ - // Get forward vector. - Vector vecForward; - AngleVectors( vecVehicleEyeAngles, &vecForward); - - // Simulate the eye position forward based on the data from last frame - // (assumes no acceleration - it will get that from the "spring"). - Vector vecCurrentEyePos = m_vecLastEyePos + m_vecEyeSpeed * flFrameTime; - - // Calculate target speed based on the current vehicle eye position and the last vehicle eye position and frametime. - Vector vecVehicleEyeSpeed = ( vecVehicleEyePos - m_vecLastEyeTarget ) / flFrameTime; - m_vecLastEyeTarget = vecVehicleEyePos; - - // Calculate the speed and position deltas. - Vector vecDeltaSpeed = vecVehicleEyeSpeed - m_vecEyeSpeed; - Vector vecDeltaPos = vecVehicleEyePos - vecCurrentEyePos; - - // Clamp. - if ( vecDeltaPos.Length() > JEEP_DELTA_LENGTH_MAX ) - { - float flSign = vecForward.Dot( vecVehicleEyeSpeed ) >= 0.0f ? -1.0f : 1.0f; - vecVehicleEyePos += flSign * ( vecForward * JEEP_DELTA_LENGTH_MAX ); - m_vecLastEyePos = vecVehicleEyePos; - m_vecEyeSpeed = vecVehicleEyeSpeed; - return; - } - - // Generate an updated (dampening) speed for use in next frames position extrapolation. - float flCoefficients[2]; - ComputePDControllerCoefficients( flCoefficients, r_JeepViewDampenFreq.GetFloat(), r_JeepViewDampenDamp.GetFloat(), flFrameTime ); - m_vecEyeSpeed += ( ( flCoefficients[0] * vecDeltaPos + flCoefficients[1] * vecDeltaSpeed ) * flFrameTime ); - - // Save off data for next frame. - m_vecLastEyePos = vecCurrentEyePos; - - // Move eye forward/backward. - Vector vecForwardOffset = vecForward * ( vecForward.Dot( vecDeltaPos ) ); - vecVehicleEyePos -= vecForwardOffset; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::DampenUpMotion( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles, float flFrameTime ) -{ - // Get up vector. - Vector vecUp; - AngleVectors( vecVehicleEyeAngles, NULL, NULL, &vecUp ); - vecUp.z = clamp( vecUp.z, 0.0f, vecUp.z ); - vecVehicleEyePos.z += r_JeepViewZHeight.GetFloat() * vecUp.z; - - // NOTE: Should probably use some damped equation here. -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) -{ - // If we are overturned and hit any key - leave the vehicle (IN_USE is already handled!). - if ( m_flOverturnedTime > OVERTURNED_EXIT_WAITTIME ) - { - if ( (ucmd->buttons & (IN_FORWARD|IN_BACK|IN_MOVELEFT|IN_MOVERIGHT|IN_SPEED|IN_JUMP|IN_ATTACK|IN_ATTACK2) ) && !m_bExitAnimOn ) - { - // Can't exit yet? We're probably still moving. Swallow the keys. - if ( !CanExitVehicle(player) ) - return; - - if ( !GetServerVehicle()->HandlePassengerExit( m_hPlayer ) && ( m_hPlayer != NULL ) ) - { - m_hPlayer->PlayUseDenySound(); - } - return; - } - } - - // If the throttle is disabled or we're upside-down, don't allow throttling (including turbo) - CUserCmd tmp; - if ( ( m_throttleDisableTime > gpGlobals->curtime ) || ( IsOverturned() ) ) - { - m_bUnableToFire = true; - - tmp = (*ucmd); - tmp.buttons &= ~(IN_FORWARD|IN_BACK|IN_SPEED); - ucmd = &tmp; - } - - BaseClass::SetupMove( player, ucmd, pHelper, move ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::DriveVehicle( float flFrameTime, CUserCmd *ucmd, int iButtonsDown, int iButtonsReleased ) -{ - int iButtons = ucmd->buttons; - - //Adrian: No headlights on Superfly. -/* if ( ucmd->impulse == 100 ) - { - if (HeadlightIsOn()) - { - HeadlightTurnOff(); - } - else - { - HeadlightTurnOn(); - } - }*/ - - // If we're holding down an attack button, update our state - if ( IsOverturned() == false ) - { - if ( iButtons & IN_ATTACK ) - { - if ( m_bCannonCharging ) - { - FireChargedCannon(); - } - else - { - FireCannon(); - } - } - else if ( iButtons & IN_ATTACK2 ) - { - ChargeCannon(); - } - } - - // If we've released our secondary button, fire off our cannon - if ( ( iButtonsReleased & IN_ATTACK2 ) && ( m_bCannonCharging ) ) - { - FireChargedCannon(); - } - - BaseClass::DriveVehicle( flFrameTime, ucmd, iButtonsDown, iButtonsReleased ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -// *pMoveData - -//----------------------------------------------------------------------------- -void CPropJeep::ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ) -{ - BaseClass::ProcessMovement( pPlayer, pMoveData ); - - // Update the steering angles based on speed. - UpdateSteeringAngle(); - - // Create dangers sounds in front of the vehicle. - CreateDangerSounds(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::UpdateSteeringAngle( void ) -{ - float flMaxSpeed = m_VehiclePhysics.GetMaxSpeed(); - float flSpeed = m_VehiclePhysics.GetSpeed(); - - float flRatio = 1.0f - ( flSpeed / flMaxSpeed ); - float flSteeringDegrees = JEEP_STEERING_FAST_ANGLE + ( ( JEEP_STEERING_SLOW_ANGLE - JEEP_STEERING_FAST_ANGLE ) * flRatio ); - flSteeringDegrees = clamp( flSteeringDegrees, JEEP_STEERING_FAST_ANGLE, JEEP_STEERING_SLOW_ANGLE ); - m_VehiclePhysics.SetSteeringDegrees( flSteeringDegrees ); -} - -//----------------------------------------------------------------------------- -// Purpose: Create danger sounds in front of the vehicle. -//----------------------------------------------------------------------------- -void CPropJeep::CreateDangerSounds( void ) -{ - QAngle dummy; - GetAttachment( "Muzzle", m_vecGunOrigin, dummy ); - - if ( m_flDangerSoundTime > gpGlobals->curtime ) - return; - - QAngle vehicleAngles = GetLocalAngles(); - Vector vecStart = GetAbsOrigin(); - Vector vecDir, vecRight; - - GetVectors( &vecDir, &vecRight, NULL ); - - const float soundDuration = 0.25; - float speed = m_VehiclePhysics.GetHLSpeed(); - // Make danger sounds ahead of the jeep - if ( fabs(speed) > 120 ) - { - Vector vecSpot; - - float steering = m_VehiclePhysics.GetSteering(); - if ( steering != 0 ) - { - if ( speed > 0 ) - { - vecDir += vecRight * steering * 0.5; - } - else - { - vecDir -= vecRight * steering * 0.5; - } - VectorNormalize(vecDir); - } - const float radius = speed * 0.4; - // 0.3 seconds ahead of the jeep - vecSpot = vecStart + vecDir * (speed * 1.1f); - CSoundEnt::InsertSound( SOUND_DANGER | SOUND_CONTEXT_PLAYER_VEHICLE, vecSpot, (int)radius, soundDuration, this, 0 ); - CSoundEnt::InsertSound( SOUND_PHYSICS_DANGER | SOUND_CONTEXT_PLAYER_VEHICLE, vecSpot, (int)radius, soundDuration, this, 1 ); - //NDebugOverlay::Box(vecSpot, Vector(-radius,-radius,-radius),Vector(radius,radius,radius), 255, 0, 255, 0, soundDuration); - -#if 0 - trace_t tr; - // put sounds a bit to left and right but slightly closer to Jeep to make a "cone" of sound - // in front of it - vecSpot = vecStart + vecDir * (speed * 0.5f) - vecRight * speed * 0.5; - UTIL_TraceLine( vecStart, vecSpot, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - CSoundEnt::InsertSound( SOUND_DANGER, vecSpot, 400, soundDuration, this, 1 ); - - vecSpot = vecStart + vecDir * (speed * 0.5f) + vecRight * speed * 0.5; - UTIL_TraceLine( vecStart, vecSpot, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - CSoundEnt::InsertSound( SOUND_DANGER, vecSpot, 400, soundDuration, this, 2); -#endif - } - - m_flDangerSoundTime = gpGlobals->curtime + 0.1; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::EnterVehicle( CBasePlayer *pPlayer ) -{ - if ( !pPlayer ) - return; - - CheckWater(); - BaseClass::EnterVehicle( pPlayer ); - - // Start looking for seagulls to land - m_hLastPlayerInVehicle = m_hPlayer; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::ExitVehicle( int nRole ) -{ - HeadlightTurnOff(); - - BaseClass::ExitVehicle( nRole ); - - //If the player has exited, stop charging - StopChargeSound(); - m_bCannonCharging = false; - - // Remember when we last saw the player - m_flPlayerExitedTime = gpGlobals->curtime; - m_flLastSawPlayerAt = gpGlobals->curtime; -} - -//----------------------------------------------------------------------------- -// Purpose: Show people how to drive! -//----------------------------------------------------------------------------- -void CPropJeep::InputShowHudHint( inputdata_t &inputdata ) -{ - CBaseServerVehicle *pServerVehicle = dynamic_cast(GetServerVehicle()); - if ( pServerVehicle ) - { - if( pServerVehicle->GetPassenger( VEHICLE_ROLE_DRIVER ) ) - { - UTIL_HudHintText( m_hPlayer, "#Valve_Hint_JeepKeys" ); - m_iNumberOfEntries++; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::InputStartRemoveTauCannon( inputdata_t &inputdata ) -{ - // Start the gun removal animation - m_flAnimTime = gpGlobals->curtime; - m_flPlaybackRate = 0.0; - SetCycle( 0 ); - ResetSequence( LookupSequence( "tau_levitate" ) ); - - m_bGunHasBeenCutOff = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropJeep::InputFinishRemoveTauCannon( inputdata_t &inputdata ) -{ - // Remove & hide the gun - SetBodygroup( 1, false ); - m_bHasGun = false; -} - -//======================================================================================================================================== -// JEEP FOUR WHEEL PHYSICS VEHICLE SERVER VEHICLE -//======================================================================================================================================== -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CJeepFourWheelServerVehicle::NPC_AimPrimaryWeapon( Vector vecTarget ) -{ - ((CPropJeep*)m_pVehicle)->AimGunAt( &vecTarget, 0.1f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &vecEyeExitEndpoint - -// Output : int -//----------------------------------------------------------------------------- -int CJeepFourWheelServerVehicle::GetExitAnimToUse( Vector &vecEyeExitEndpoint, bool &bAllPointsBlocked ) -{ - bAllPointsBlocked = false; - - if ( !m_bParsedAnimations ) - { - // Load the entry/exit animations from the vehicle - ParseEntryExitAnims(); - m_bParsedAnimations = true; - } - - // Comment out the "don't have the gun" animation (assume we always have it) - /* - CBaseAnimating *pAnimating = dynamic_cast(m_pVehicle); - // If we don't have the gun anymore, we want to get out using the "gun-less" animation - if ( pAnimating ) - { - // HACK: We know the tau-cannon removed exit anim uses the first upright anim's exit details - trace_t tr; - - // Convert our offset points to worldspace ones - Vector vehicleExitOrigin = m_ExitAnimations[0].vecExitPointLocal; - QAngle vehicleExitAngles = m_ExitAnimations[0].vecExitAnglesLocal; - UTIL_ParentToWorldSpace( pAnimating, vehicleExitOrigin, vehicleExitAngles ); - - // Ensure the endpoint is clear by dropping a point down from above - vehicleExitOrigin -= VEC_VIEW; - Vector vecMove = Vector(0,0,64); - Vector vecStart = vehicleExitOrigin + vecMove; - Vector vecEnd = vehicleExitOrigin - vecMove; - UTIL_TraceHull( vecStart, vecEnd, VEC_HULL_MIN, VEC_HULL_MAX, MASK_SOLID, NULL, COLLISION_GROUP_NONE, &tr ); - - Assert( !tr.startsolid && tr.fraction < 1.0 ); - m_vecCurrentExitEndPoint = vecStart + ((vecEnd - vecStart) * tr.fraction); - vecEyeExitEndpoint = m_vecCurrentExitEndPoint + VEC_VIEW; - m_iCurrentExitAnim = 0; - return pAnimating->LookupSequence( "exit_tauremoved" ); - } -*/ - return BaseClass::GetExitAnimToUse( vecEyeExitEndpoint, bAllPointsBlocked ); -} diff --git a/game/server/sdk/te_firebullets.cpp b/game/server/sdk/te_firebullets.cpp deleted file mode 100644 index 327e97309..000000000 --- a/game/server/sdk/te_firebullets.cpp +++ /dev/null @@ -1,98 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" - - -#define NUM_BULLET_SEED_BITS 8 - - -//----------------------------------------------------------------------------- -// Purpose: Display's a blood sprite -//----------------------------------------------------------------------------- -class CTEFireBullets : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEFireBullets, CBaseTempEntity ); - DECLARE_SERVERCLASS(); - - CTEFireBullets( const char *name ); - virtual ~CTEFireBullets( void ); - -public: - CNetworkVar( int, m_iPlayer ); // player who fired - CNetworkVector( m_vecOrigin ); // firing origin - CNetworkQAngle( m_vecAngles ); // firing angle - CNetworkVar( int, m_iWeaponID ); // weapon ID - CNetworkVar( int, m_iMode ); // primary or secondary fire ? - CNetworkVar( int, m_iSeed ); // shared random seed - CNetworkVar( float, m_flSpread ); // bullets spread - -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEFireBullets::CTEFireBullets( const char *name ) : - CBaseTempEntity( name ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEFireBullets::~CTEFireBullets( void ) -{ -} - -IMPLEMENT_SERVERCLASS_ST_NOBASE(CTEFireBullets, DT_TEFireBullets) - SendPropVector( SENDINFO(m_vecOrigin), -1, SPROP_COORD ), - SendPropAngle( SENDINFO_VECTORELEM2( m_vecAngles, 0, x ), 13, 0 ), - SendPropAngle( SENDINFO_VECTORELEM2( m_vecAngles, 1, y ), 13, 0 ), - SendPropInt( SENDINFO( m_iWeaponID ), 5, SPROP_UNSIGNED ), // max 31 weapons - SendPropInt( SENDINFO( m_iMode ), 1, SPROP_UNSIGNED ), - SendPropInt( SENDINFO( m_iSeed ), NUM_BULLET_SEED_BITS, SPROP_UNSIGNED ), - SendPropInt( SENDINFO( m_iPlayer ), 6, SPROP_UNSIGNED ), // max 64 players, see MAX_PLAYERS - SendPropFloat( SENDINFO( m_flSpread ), 10, 0, 0, 1 ), -END_SEND_TABLE() - - -// Singleton -static CTEFireBullets g_TEFireBullets( "Shotgun Shot" ); - - -void TE_FireBullets( - int iPlayerIndex, - const Vector &vOrigin, - const QAngle &vAngles, - int iWeaponID, - int iMode, - int iSeed, - float flSpread ) -{ - CPASFilter filter( vOrigin ); - filter.UsePredictionRules(); - - g_TEFireBullets.m_iPlayer = iPlayerIndex-1; - g_TEFireBullets.m_vecOrigin = vOrigin; - g_TEFireBullets.m_vecAngles = vAngles; - g_TEFireBullets.m_iSeed = iSeed; - g_TEFireBullets.m_flSpread = flSpread; - g_TEFireBullets.m_iMode = iMode; - g_TEFireBullets.m_iWeaponID = iWeaponID; - - Assert( iSeed < (1 << NUM_BULLET_SEED_BITS) ); - - g_TEFireBullets.Create( filter, 0 ); -} diff --git a/game/server/sdk/te_firebullets.h b/game/server/sdk/te_firebullets.h deleted file mode 100644 index 2c2da1bc5..000000000 --- a/game/server/sdk/te_firebullets.h +++ /dev/null @@ -1,24 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef TE_FIREBULLETS_H -#define TE_FIREBULLETS_H -#ifdef _WIN32 -#pragma once -#endif - - -void TE_FireBullets( - int iPlayerIndex, - const Vector &vOrigin, - const QAngle &vAngles, - int iWeaponID, - int iMode, - int iSeed, - float flSpread - ); - -#endif // TE_FIREBULLETS_H diff --git a/game/server/sendproxy.cpp b/game/server/sendproxy.cpp deleted file mode 100644 index 4032f7333..000000000 --- a/game/server/sendproxy.cpp +++ /dev/null @@ -1,197 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: implements various common send proxies -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "sendproxy.h" -#include "basetypes.h" -#include "baseentity.h" -#include "team.h" -#include "player.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -void SendProxy_Color32ToInt( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ) -{ - color32 *pIn = (color32*)pData; - *((unsigned int*)&pOut->m_Int) = ((unsigned int)pIn->r << 24) | ((unsigned int)pIn->g << 16) | ((unsigned int)pIn->b << 8) | ((unsigned int)pIn->a); -} - -void SendProxy_EHandleToInt( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID) -{ - CBaseHandle *pHandle = (CBaseHandle*)pVarData; - - if ( pHandle && pHandle->Get() ) - { - int iSerialNum = pHandle->GetSerialNumber() & (1 << NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS) - 1; - pOut->m_Int = pHandle->GetEntryIndex() | (iSerialNum << MAX_EDICT_BITS); - } - else - { - pOut->m_Int = INVALID_NETWORKED_EHANDLE_VALUE; - } -} - -void SendProxy_IntAddOne( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID) -{ - int *pInt = (int *)pVarData; - - pOut->m_Int = (*pInt) + 1; -} - -void SendProxy_ShortAddOne( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID) -{ - short *pInt = (short *)pVarData; - - pOut->m_Int = (*pInt) + 1; -} - -SendProp SendPropBool( - const char *pVarName, - int offset, - int sizeofVar ) -{ - Assert( sizeofVar == sizeof( bool ) ); - return SendPropInt( pVarName, offset, sizeofVar, 1, SPROP_UNSIGNED ); -} - - -SendProp SendPropEHandle( - const char *pVarName, - int offset, - int flags, - int sizeofVar, - SendVarProxyFn proxyFn ) -{ - return SendPropInt( pVarName, offset, sizeofVar, NUM_NETWORKED_EHANDLE_BITS, SPROP_UNSIGNED|flags, proxyFn ); -} - -SendProp SendPropIntWithMinusOneFlag( const char *pVarName, int offset, int sizeofVar, int nBits, SendVarProxyFn proxyFn ) -{ - return SendPropInt( pVarName, offset, sizeofVar, nBits, SPROP_UNSIGNED, proxyFn ); -} - -//----------------------------------------------------------------------------- -// Purpose: Proxy that only sends data to team members -// Input : *pStruct - -// *pData - -// *pOut - -// objectID - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -void* SendProxy_OnlyToTeam( const SendProp *pProp, const void *pStruct, const void *pVarData, CSendProxyRecipients *pRecipients, int objectID ) -{ - CBaseEntity *pEntity = (CBaseEntity*)pStruct; - if ( pEntity ) - { - CTeam *pTeam = pEntity->GetTeam(); - if ( pTeam ) - { - pRecipients->ClearAllRecipients(); - for ( int i=0; i < pTeam->GetNumPlayers(); i++ ) - pRecipients->SetRecipient( pTeam->GetPlayer( i )->GetClientIndex() ); - - return (void*)pVarData; - } - } - - return NULL; -} -REGISTER_SEND_PROXY_NON_MODIFIED_POINTER( SendProxy_OnlyToTeam ); - -#define TIME_BITS 24 - -// This table encodes edict data. -/*static void SendProxy_Time( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID ) -{ - float clock_base = floor( gpGlobals->curtime ); - float t = *( float * )pVarData; - float dt = t - clock_base; - int addt = Floor2Int( 1000.0f * dt + 0.5f ); - // TIME_BITS bits gives us TIME_BITS-1 bits plus sign bit - int maxoffset = 1 << ( TIME_BITS - 1); - - addt = clamp( addt, -maxoffset, maxoffset ); - - pOut->m_Int = addt; -}*/ - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pVarName - -// sizeofVar - -// flags - -// pId - -// Output : SendProp -//----------------------------------------------------------------------------- -SendProp SendPropTime( - const char *pVarName, - int offset, - int sizeofVar ) -{ -// return SendPropInt( pVarName, offset, sizeofVar, TIME_BITS, 0, SendProxy_Time ); - // FIXME: Re-enable above when it doesn't cause lots of deltas - return SendPropFloat( pVarName, offset, sizeofVar, -1, SPROP_NOSCALE ); -} - -#if !defined( NO_ENTITY_PREDICTION ) - -#define PREDICTABLE_ID_BITS 31 - -//----------------------------------------------------------------------------- -// Purpose: Converts a predictable Id to an integer -// Input : *pStruct - -// *pVarData - -// *pOut - -// iElement - -// objectID - -//----------------------------------------------------------------------------- -static void SendProxy_PredictableIdToInt( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID ) -{ - CPredictableId* pId = ( CPredictableId * )pVarData; - if ( pId ) - { - pOut->m_Int = pId->GetRaw(); - } - else - { - pOut->m_Int = 0; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pVarName - -// sizeofVar - -// flags - -// pId - -// Output : SendProp -//----------------------------------------------------------------------------- -SendProp SendPropPredictableId( - const char *pVarName, - int offset, - int sizeofVar ) -{ - return SendPropInt( pVarName, offset, sizeofVar, PREDICTABLE_ID_BITS, SPROP_UNSIGNED, SendProxy_PredictableIdToInt ); -} - -#endif - -void SendProxy_StringT_To_String( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID ) -{ - string_t &str = *((string_t*)pVarData); - pOut->m_pString = (char*)STRING( str ); -} - - -SendProp SendPropStringT( const char *pVarName, int offset, int sizeofVar ) -{ - // Make sure it's the right type. - Assert( sizeofVar == sizeof( string_t ) ); - - return SendPropString( pVarName, offset, DT_MAX_STRING_BUFFERSIZE, 0, SendProxy_StringT_To_String ); -} diff --git a/game/server/sendproxy.h b/game/server/sendproxy.h deleted file mode 100644 index 55572b7c9..000000000 --- a/game/server/sendproxy.h +++ /dev/null @@ -1,63 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: implements various common send proxies -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SENDPROXY_H -#define SENDPROXY_H - - -#include "dt_send.h" - - -class DVariant; - -void SendProxy_Color32ToInt( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); -void SendProxy_EHandleToInt( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID ); -void SendProxy_IntAddOne( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID ); -void SendProxy_ShortAddOne( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID ); - -SendProp SendPropBool( - const char *pVarName, - int offset, - int sizeofVar ); - -SendProp SendPropEHandle( - const char *pVarName, - int offset, - int flags = 0, - int sizeofVar=SIZEOF_IGNORE, - SendVarProxyFn proxyFn=SendProxy_EHandleToInt ); - -SendProp SendPropTime( - const char *pVarName, - int offset, - int sizeofVar=SIZEOF_IGNORE ); - -#if !defined( NO_ENTITY_PREDICTION ) -SendProp SendPropPredictableId( - const char *pVarName, - int offset, - int sizeofVar=SIZEOF_IGNORE ); -#endif - -SendProp SendPropIntWithMinusOneFlag( - const char *pVarName, - int offset, - int bits, - int sizeofVar=SIZEOF_IGNORE, - SendVarProxyFn proxyFn=SendProxy_IntAddOne ); - - -// Send a string_t as a string property. -SendProp SendPropStringT( const char *pVarName, int offset, int sizeofVar ); - -//----------------------------------------------------------------------------- -// Purpose: Proxy that only sends data to team members -//----------------------------------------------------------------------------- -void* SendProxy_OnlyToTeam( const SendProp *pProp, const void *pStruct, const void *pVarData, CSendProxyRecipients *pRecipients, int objectID ); - - -#endif // SENDPROXY_H diff --git a/game/server/server_episodic-2005.vcproj b/game/server/server_episodic-2005.vcproj deleted file mode 100644 index 9944f3868..000000000 --- a/game/server/server_episodic-2005.vcproj +++ /dev/null @@ -1,5387 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/game/server/server_hl2-2005.vcproj b/game/server/server_hl2-2005.vcproj deleted file mode 100644 index 86bfae720..000000000 --- a/game/server/server_hl2-2005.vcproj +++ /dev/null @@ -1,5280 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/game/server/serverbenchmark_base.cpp b/game/server/serverbenchmark_base.cpp deleted file mode 100644 index 25baabda7..000000000 --- a/game/server/serverbenchmark_base.cpp +++ /dev/null @@ -1,424 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#include "serverbenchmark_base.h" -#include "props.h" -#include "filesystem.h" -#include "tier0/icommandline.h" - - -// Server benchmark. Only works on specified maps. -// Lasts for N ticks. -// Enable sv_stressbots. -// Create 20 players and move them around and have them shoot. -// At the end, report the # seconds it took to complete the test. -// Don't start measuring for the first N ticks to account for HD load. - -static ConVar sv_benchmark_numticks( "sv_benchmark_numticks", "3300", 0, "If > 0, then it only runs the benchmark for this # of ticks." ); -static ConVar sv_benchmark_autovprofrecord( "sv_benchmark_autovprofrecord", "0", 0, "If running a benchmark and this is set, it will record a vprof file over the duration of the benchmark with filename benchmark.vprof." ); - -static float s_flBenchmarkStartWaitSeconds = 3; // Wait this many seconds after level load before starting the benchmark. - -static int s_nBenchmarkBotsToCreate = 22; // Create this many bots. -static int s_nBenchmarkBotCreateInterval = 50; // Create a bot every N ticks. - -static int s_nBenchmarkPhysicsObjects = 100; // Create this many physics objects. - - -static double Benchmark_ValidTime() -{ - bool bOld = Plat_IsInBenchmarkMode(); - Plat_SetBenchmarkMode( false ); - double flRet = Plat_FloatTime(); - Plat_SetBenchmarkMode( bOld ); - - return flRet; -} - - -// ---------------------------------------------------------------------------------------------- // -// CServerBenchmark implementation. -// ---------------------------------------------------------------------------------------------- // -class CServerBenchmark : public IServerBenchmark -{ -public: - CServerBenchmark() - { - m_BenchmarkState = BENCHMARKSTATE_NOT_RUNNING; - - // The benchmark should always have the same seed and do exactly the same thing on the same ticks. - m_RandomStream.SetSeed( 1111 ); - } - - virtual bool StartBenchmark() - { - bool bBenchmark = (CommandLine()->FindParm( "-sv_benchmark" ) != 0); - - return InternalStartBenchmark( bBenchmark, s_flBenchmarkStartWaitSeconds ); - } - - // nBenchmarkMode: 0 = no benchmark - // 1 = benchmark - // 2 = exit out afterwards and write sv_benchmark.txt - bool InternalStartBenchmark( int nBenchmarkMode, float flCountdown ) - { - bool bWasRunningBenchmark = (m_BenchmarkState != BENCHMARKSTATE_NOT_RUNNING); - - if ( nBenchmarkMode == 0 ) - { - // Tear down the previous benchmark environment if necessary. - if ( bWasRunningBenchmark ) - EndBenchmark(); - return false; - } - - m_nBenchmarkMode = nBenchmarkMode; - - if ( !CServerBenchmarkHook::s_pBenchmarkHook ) - Error( "This game doesn't support server benchmarks (no CServerBenchmarkHook found)." ); - - m_BenchmarkState = BENCHMARKSTATE_START_WAIT; - m_flBenchmarkStartTime = Plat_FloatTime(); - m_flBenchmarkStartWaitTime = flCountdown; - - m_nBotsCreated = 0; - m_nStartWaitCounter = -1; - - // Setup the benchmark environment. - engine->SetDedicatedServerBenchmarkMode( true ); // Run 1 tick per frame and ignore all timing stuff. - - // Tell the game-specific hook that we're starting. - CServerBenchmarkHook::s_pBenchmarkHook->StartBenchmark(); - CServerBenchmarkHook::s_pBenchmarkHook->GetPhysicsModelNames( m_PhysicsModelNames ); - - return true; - } - - virtual void UpdateBenchmark() - { - // No benchmark running? - if ( m_BenchmarkState == BENCHMARKSTATE_NOT_RUNNING ) - return; - - // Wait a certain number of ticks to start the benchmark. - if ( m_BenchmarkState == BENCHMARKSTATE_START_WAIT ) - { - if ( (Plat_FloatTime() - m_flBenchmarkStartTime) < m_flBenchmarkStartWaitTime ) - { - UpdateStartWaitCounter(); - return; - } - else - { - // Ok, now we're officially starting it. - Msg( "Starting benchmark!\n" ); - m_flLastBenchmarkCounterUpdate = m_flBenchmarkStartTime = Plat_FloatTime(); - m_fl_ValidTime_BenchmarkStartTime = Benchmark_ValidTime(); - m_nBenchmarkStartTick = gpGlobals->tickcount; - m_nLastPhysicsObjectTick = m_nLastPhysicsForceTick = 0; - m_BenchmarkState = BENCHMARKSTATE_RUNNING; - - StartVProfRecord(); - - RandomSeed( 0 ); - m_RandomStream.SetSeed( 0 ); - } - } - - int nTicksRunSoFar = gpGlobals->tickcount - m_nBenchmarkStartTick; - UpdateBenchmarkCounter(); - - // Are we finished with the benchmark? - if ( nTicksRunSoFar >= sv_benchmark_numticks.GetInt() ) - { - EndVProfRecord(); - OutputResults(); - EndBenchmark(); - return; - } - - // Ok, update whatever we're doing in the benchmark. - UpdatePlayerCreation(); - UpdateVPhysicsObjects(); - CServerBenchmarkHook::s_pBenchmarkHook->UpdateBenchmark(); - } - - void StartVProfRecord() - { - if ( sv_benchmark_autovprofrecord.GetInt() ) - { - engine->ServerCommand( "vprof_record_start benchmark\n" ); - engine->ServerExecute(); - } - } - - void EndVProfRecord() - { - if ( sv_benchmark_autovprofrecord.GetInt() ) - { - engine->ServerCommand( "vprof_record_stop\n" ); - engine->ServerExecute(); - } - } - - void EndBenchmark() - { - // Write out the results if we're running the build scripts. - float flRunTime = Benchmark_ValidTime() - m_fl_ValidTime_BenchmarkStartTime; - if ( m_nBenchmarkMode == 2 ) - { - FileHandle_t fh = filesystem->Open( "sv_benchmark_results.txt", "wt", "DEFAULT_WRITE_PATH" ); - - // If this file doesn't get written out, then the build script will generate an email that there's a problem somewhere. - if ( fh ) - { - filesystem->FPrintf( fh, "sv_benchmark := %.2f\n", flRunTime ); - } - filesystem->Close( fh ); - - // Quit out. - engine->ServerCommand( "quit\n" ); - } - - m_BenchmarkState = BENCHMARKSTATE_NOT_RUNNING; - engine->SetDedicatedServerBenchmarkMode( false ); - } - - virtual bool IsLocalBenchmarkPlayer( CBasePlayer *pPlayer ) - { - if ( m_BenchmarkState != BENCHMARKSTATE_NOT_RUNNING ) - { - if( !engine->IsDedicatedServer() && pPlayer->entindex() == 1 ) - return true; - } - - return false; - } - - void UpdateVPhysicsObjects() - { - int nPhysicsObjectInterval = sv_benchmark_numticks.GetInt() / s_nBenchmarkPhysicsObjects; - - int nNextSpawnTick = m_nLastPhysicsObjectTick + nPhysicsObjectInterval; - if ( GetTickOffset() >= nNextSpawnTick ) - { - m_nLastPhysicsObjectTick = nNextSpawnTick; - - if ( m_PhysicsObjects.Count() < s_nBenchmarkPhysicsObjects ) - { - // Find a bot to spawn it from. - CUtlVector curPlayers; - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - if ( pPlayer && (pPlayer->GetFlags() & FL_FAKECLIENT) ) - { - curPlayers.AddToTail( pPlayer ); - } - } - - if ( curPlayers.Count() > 0 && m_PhysicsModelNames.Count() > 0 ) - { - int iModelName = this->RandomInt( 0, m_PhysicsModelNames.Count() - 1 ); - const char *pModelName = m_PhysicsModelNames[iModelName]; - - int iPlayer = this->RandomInt( 0, curPlayers.Count() - 1 ); - - Vector vSpawnPos = curPlayers[iPlayer]->EyePosition() + Vector( 0, 0, 50 ); - - // We'll try 15 locations around the player to spawn this thing. - for ( int i=0; i < 15; i++ ) - { - Vector vOffset( this->RandomFloat( -2000, 2000 ), this->RandomFloat( -2000, 2000 ), 0 ); - CPhysicsProp *pProp = CreatePhysicsProp( pModelName, vSpawnPos, vSpawnPos+vOffset, curPlayers[iPlayer], false, "prop_physics_multiplayer" ); - if ( pProp ) - { - m_PhysicsObjects.AddToTail( pProp ); - pProp->SetAbsVelocity( Vector( this->RandomFloat(-500,500), this->RandomFloat(-500,500), this->RandomFloat(-500,500) ) ); - break; - } - } - } - } - } - - // Give them all a boost periodically. - int nPhysicsForceInterval = sv_benchmark_numticks.GetInt() / 20; - - int nNextForceTick = m_nLastPhysicsForceTick + nPhysicsForceInterval; - if ( GetTickOffset() >= nNextForceTick ) - { - m_nLastPhysicsForceTick = nNextForceTick; - - for ( int i=0; i < m_PhysicsObjects.Count(); i++ ) - { - CBaseEntity *pEnt = m_PhysicsObjects[i]; - if ( pEnt ) - { - IPhysicsObject *pPhysicsObject = pEnt->VPhysicsGetObject(); - if ( pPhysicsObject ) - { - float flAngImpulse = 300000; - float flForce = 500000; - AngularImpulse vAngularImpulse( this->RandomFloat(-flAngImpulse,flAngImpulse), this->RandomFloat(-flAngImpulse,flAngImpulse), this->RandomFloat(flAngImpulse,flAngImpulse) ); - pPhysicsObject->ApplyForceCenter( Vector( this->RandomFloat(-flForce,flForce), this->RandomFloat(-flForce,flForce), this->RandomFloat(0,flForce) ) ); - } - } - } - } - } - - void UpdateStartWaitCounter() - { - int nSecondsLeft = (int)ceil( m_flBenchmarkStartWaitTime - (Plat_FloatTime() - m_flBenchmarkStartTime) ); - if ( m_nStartWaitCounter != nSecondsLeft ) - { - Msg( "Starting benchmark in %d seconds...\n", nSecondsLeft ); - m_nStartWaitCounter = nSecondsLeft; - } - } - - void UpdateBenchmarkCounter() - { - float flCurTime = Plat_FloatTime(); - if ( (flCurTime - m_flLastBenchmarkCounterUpdate) > 3.0f ) - { - m_flLastBenchmarkCounterUpdate = flCurTime; - Msg( "Benchmark: %d%% complete.\n", ((gpGlobals->tickcount - m_nBenchmarkStartTick) * 100) / sv_benchmark_numticks.GetInt() ); - } - } - - virtual bool IsBenchmarkRunning() - { - return (m_BenchmarkState == BENCHMARKSTATE_RUNNING); - } - - virtual int GetTickOffset() - { - if ( m_BenchmarkState == BENCHMARKSTATE_RUNNING ) - { - Assert( gpGlobals->tickcount >= m_nBenchmarkStartTick ); - return gpGlobals->tickcount - m_nBenchmarkStartTick; - } - else - { - return gpGlobals->tickcount; - } - } - - - void UpdatePlayerCreation() - { - if ( m_nBotsCreated >= s_nBenchmarkBotsToCreate ) - return; - - // Spawn the player. - int nTicksRunSoFar = gpGlobals->tickcount - m_nBenchmarkStartTick; - - if ( (nTicksRunSoFar % s_nBenchmarkBotCreateInterval) == 0 ) - { - CServerBenchmarkHook::s_pBenchmarkHook->CreateBot(); - ++m_nBotsCreated; - } - } - - void OutputResults() - { - float flRunTime = Benchmark_ValidTime() - m_fl_ValidTime_BenchmarkStartTime; - - Warning( "------------------ SERVER BENCHMARK RESULTS ------------------\n" ); - Warning( "Total time : %.2f seconds\n", flRunTime ); - Warning( "Num ticks simulated : %d\n", sv_benchmark_numticks.GetInt() ); - Warning( "Ticks per second : %.2f\n", sv_benchmark_numticks.GetInt() / flRunTime ); - Warning( "Benchmark CRC : %d\n", CalculateBenchmarkCRC() ); - Warning( "--------------------------------------------------------------\n" ); - } - - int CalculateBenchmarkCRC() - { - int crc = 0; - - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - if ( pPlayer && (pPlayer->GetFlags() & FL_FAKECLIENT) ) - { - crc += pPlayer->GetTeamNumber(); - crc += (int)pPlayer->GetAbsOrigin().x; - crc += (int)pPlayer->GetAbsOrigin().y; - } - } - - return crc; - } - - virtual int RandomInt( int nMin, int nMax ) - { - return m_RandomStream.RandomInt( nMin, nMax ); - } - - virtual float RandomFloat( float nMin, float nMax ) - { - return m_RandomStream.RandomFloat( nMin, nMax ); - } - - -private: - - typedef enum EBenchmarkState - { - BENCHMARKSTATE_NOT_RUNNING, - BENCHMARKSTATE_START_WAIT, - BENCHMARKSTATE_RUNNING - }; - EBenchmarkState m_BenchmarkState; - - float m_fl_ValidTime_BenchmarkStartTime; - - float m_flBenchmarkStartTime; - float m_flLastBenchmarkCounterUpdate; - float m_flBenchmarkStartWaitTime; - - int m_nBenchmarkStartTick; - int m_nStartWaitCounter; - int m_nLastPhysicsObjectTick; - int m_nLastPhysicsForceTick; - - int m_nBotsCreated; - CUtlVector< EHANDLE > m_PhysicsObjects; - - CUtlVector m_PhysicsModelNames; - int m_nBenchmarkMode; - - CUniformRandomStream m_RandomStream; -}; - -static CServerBenchmark g_ServerBenchmark; -IServerBenchmark *g_pServerBenchmark = &g_ServerBenchmark; - -CON_COMMAND( sv_benchmark_force_start, "Force start the benchmark. This is only for debugging. It's better to set sv_benchmark to 1 and restart the level." ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - g_ServerBenchmark.InternalStartBenchmark( 1, 1 ); -} - - -// ---------------------------------------------------------------------------------------------- // -// CServerBenchmarkHook implementation. -// ---------------------------------------------------------------------------------------------- // - -CServerBenchmarkHook *CServerBenchmarkHook::s_pBenchmarkHook = NULL; - -CServerBenchmarkHook::CServerBenchmarkHook() -{ - if ( s_pBenchmarkHook ) - Error( "There can only be one CServerBenchmarkHook" ); - - s_pBenchmarkHook = this; -} diff --git a/game/server/serverbenchmark_base.h b/game/server/serverbenchmark_base.h deleted file mode 100644 index 0572c6a73..000000000 --- a/game/server/serverbenchmark_base.h +++ /dev/null @@ -1,63 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef SERVERBENCHMARK_BASE_H -#define SERVERBENCHMARK_BASE_H -#ifdef _WIN32 -#pragma once -#endif - - -// The base server code calls into this. -class IServerBenchmark -{ -public: - virtual bool StartBenchmark() = 0; - virtual void UpdateBenchmark() = 0; - - virtual bool IsBenchmarkRunning() = 0; - virtual bool IsLocalBenchmarkPlayer( CBasePlayer *pPlayer ) = 0; - - // Game-specific benchmark code should use this. - virtual int RandomInt( int nMin, int nMax ) = 0; - virtual float RandomFloat( float flMin, float flMax ) = 0; - virtual int GetTickOffset() = 0; -}; - -extern IServerBenchmark *g_pServerBenchmark; - - -// -// Each game can derive from this to hook into the server benchmark. -// -// Hooks should always use g_pServerBenchmark->RandomInt/Float to get random numbers -// so the benchmark is deterministic. -// -// If they use an absolute tick number for anything, then they should also call g_pServerBenchmark->GetTickOffset() -// to get a tick count since the start of the benchmark instead of looking at gpGlobals->tickcount. -// -class CServerBenchmarkHook -{ -public: - CServerBenchmarkHook(); - - virtual void StartBenchmark() {} - virtual void UpdateBenchmark() {} - - // Give a list of model names that can be spawned in for physics props during the simulation. - virtual void GetPhysicsModelNames( CUtlVector &modelNames ) = 0; - - // The benchmark will call this to create a bot each time it wants to create a player. - // If you want to manage the bots yourself, you can return NULL here. - virtual CBasePlayer* CreateBot() = 0; - -private: - friend class CServerBenchmark; - static CServerBenchmarkHook *s_pBenchmarkHook; // There can be only one!! -}; - - -#endif // SERVERBENCHMARK_BASE_H diff --git a/game/server/shadowcontrol.cpp b/game/server/shadowcontrol.cpp deleted file mode 100644 index 080621672..000000000 --- a/game/server/shadowcontrol.cpp +++ /dev/null @@ -1,152 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Shadow control entity. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//------------------------------------------------------------------------------ -// FIXME: This really should inherit from something more lightweight -//------------------------------------------------------------------------------ - - -//------------------------------------------------------------------------------ -// Purpose : Shadow control entity -//------------------------------------------------------------------------------ -class CShadowControl : public CBaseEntity -{ -public: - DECLARE_CLASS( CShadowControl, CBaseEntity ); - - CShadowControl(); - - void Spawn( void ); - bool KeyValue( const char *szKeyName, const char *szValue ); - int UpdateTransmitState(); - void InputSetAngles( inputdata_t &inputdata ); - - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - -private: - CNetworkVector( m_shadowDirection ); - CNetworkColor32( m_shadowColor ); - CNetworkVar( float, m_flShadowMaxDist ); - CNetworkVar( bool, m_bDisableShadows ); -}; - -LINK_ENTITY_TO_CLASS(shadow_control, CShadowControl); - -BEGIN_DATADESC( CShadowControl ) - - DEFINE_KEYFIELD( m_flShadowMaxDist, FIELD_FLOAT, "distance" ), - DEFINE_KEYFIELD( m_bDisableShadows, FIELD_BOOLEAN, "disableallshadows" ), - - // Inputs - DEFINE_INPUT( m_shadowColor, FIELD_COLOR32, "color" ), - DEFINE_INPUT( m_shadowDirection, FIELD_VECTOR, "direction" ), - DEFINE_INPUT( m_flShadowMaxDist, FIELD_FLOAT, "SetDistance" ), - DEFINE_INPUT( m_bDisableShadows, FIELD_BOOLEAN, "SetShadowsDisabled" ), - - DEFINE_INPUTFUNC( FIELD_STRING, "SetAngles", InputSetAngles ), - -END_DATADESC() - - -IMPLEMENT_SERVERCLASS_ST_NOBASE(CShadowControl, DT_ShadowControl) - SendPropVector(SENDINFO(m_shadowDirection), -1, SPROP_NOSCALE ), - SendPropInt(SENDINFO(m_shadowColor), 32, SPROP_UNSIGNED), - SendPropFloat(SENDINFO(m_flShadowMaxDist), 0, SPROP_NOSCALE ), - SendPropBool(SENDINFO(m_bDisableShadows)), -END_SEND_TABLE() - - -CShadowControl::CShadowControl() -{ - m_shadowDirection.Init( 0.2, 0.2, -2 ); - m_flShadowMaxDist = 50.0f; - m_shadowColor.Init( 64, 64, 64, 0 ); - m_bDisableShadows = false; -} - - -//------------------------------------------------------------------------------ -// Purpose : Send even though we don't have a model -//------------------------------------------------------------------------------ -int CShadowControl::UpdateTransmitState() -{ - // ALWAYS transmit to all clients. - return SetTransmitState( FL_EDICT_ALWAYS ); -} - - -bool CShadowControl::KeyValue( const char *szKeyName, const char *szValue ) -{ - if ( FStrEq( szKeyName, "color" ) ) - { - color32 tmp; - UTIL_StringToColor32( &tmp, szValue ); - m_shadowColor = tmp; - return true; - } - - if ( FStrEq( szKeyName, "angles" ) ) - { - QAngle angles; - UTIL_StringToVector( angles.Base(), szValue ); - if (angles == vec3_angle) - { - angles.Init( 80, 30, 0 ); - } - Vector vForward; - AngleVectors( angles, &vForward ); - m_shadowDirection = vForward; - return true; - } - - // For backward compatibility... - if ( FStrEq( szKeyName, "direction" ) ) - { - // Only use this if angles haven't been set... - if ( fabs(m_shadowDirection->LengthSqr() - 1.0f) > 1e-3 ) - { - Vector vTemp; - UTIL_StringToVector( vTemp.Base(), szValue ); - m_shadowDirection = vTemp; - } - return true; - } - - return BaseClass::KeyValue( szKeyName, szValue ); -} - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CShadowControl::Spawn( void ) -{ - Precache(); - SetSolid( SOLID_NONE ); -} - -//------------------------------------------------------------------------------ -// Input values -//------------------------------------------------------------------------------ -void CShadowControl::InputSetAngles( inputdata_t &inputdata ) -{ - const char *pAngles = inputdata.value.String(); - - QAngle angles; - UTIL_StringToVector( angles.Base(), pAngles ); - - Vector vTemp; - AngleVectors( angles, &vTemp ); - m_shadowDirection = vTemp; -} diff --git a/game/server/slideshow_display.cpp b/game/server/slideshow_display.cpp deleted file mode 100644 index 8a9fd0bec..000000000 --- a/game/server/slideshow_display.cpp +++ /dev/null @@ -1,625 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements the big scary boom-boom machine Antlions fear. -// -//=============================================================================// - -#include "cbase.h" -#include "EnvMessage.h" -#include "fmtstr.h" -#include "vguiscreen.h" -#include "filesystem.h" - - -#define SLIDESHOW_LIST_BUFFER_MAX 8192 - - -struct SlideKeywordList_t -{ - char szSlideKeyword[64]; -}; - - -class CSlideshowDisplay : public CBaseEntity -{ -public: - - DECLARE_CLASS( CSlideshowDisplay, CBaseEntity ); - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - virtual ~CSlideshowDisplay(); - - virtual bool KeyValue( const char *szKeyName, const char *szValue ); - - virtual int UpdateTransmitState(); - virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ); - - virtual void Spawn( void ); - virtual void Precache( void ); - virtual void OnRestore( void ); - - void ScreenVisible( bool bVisible ); - - void Disable( void ); - void Enable( void ); - - void InputDisable( inputdata_t &inputdata ); - void InputEnable( inputdata_t &inputdata ); - - void InputSetDisplayText( inputdata_t &inputdata ); - void InputRemoveAllSlides( inputdata_t &inputdata ); - void InputAddSlides( inputdata_t &inputdata ); - - void InputSetMinSlideTime( inputdata_t &inputdata ); - void InputSetMaxSlideTime( inputdata_t &inputdata ); - - void InputSetCycleType( inputdata_t &inputdata ); - void InputSetNoListRepeats( inputdata_t &inputdata ); - -private: - - // Control panel - void GetControlPanelInfo( int nPanelIndex, const char *&pPanelName ); - void GetControlPanelClassName( int nPanelIndex, const char *&pPanelName ); - void SpawnControlPanels( void ); - void RestoreControlPanels( void ); - void BuildSlideShowImagesList( void ); - -private: - - CNetworkVar( bool, m_bEnabled ); - - CNetworkString( m_szDisplayText, 128 ); - - CNetworkString( m_szSlideshowDirectory, 128 ); - string_t m_String_tSlideshowDirectory; - - CUtlVector m_SlideKeywordList; - CNetworkArray( unsigned char, m_chCurrentSlideLists, 16 ); - - CNetworkVar( float, m_fMinSlideTime ); - CNetworkVar( float, m_fMaxSlideTime ); - - CNetworkVar( int, m_iCycleType ); - CNetworkVar( bool, m_bNoListRepeats ); - - int m_iScreenWidth; - int m_iScreenHeight; - - bool m_bDoFullTransmit; - - typedef CHandle ScreenHandle_t; - CUtlVector m_hScreens; -}; - - -LINK_ENTITY_TO_CLASS( vgui_slideshow_display, CSlideshowDisplay ); - -//----------------------------------------------------------------------------- -// Save/load -//----------------------------------------------------------------------------- -BEGIN_DATADESC( CSlideshowDisplay ) - DEFINE_FIELD( m_bEnabled, FIELD_BOOLEAN ), - - DEFINE_AUTO_ARRAY_KEYFIELD( m_szDisplayText, FIELD_CHARACTER, "displaytext" ), - - DEFINE_AUTO_ARRAY( m_szSlideshowDirectory, FIELD_CHARACTER ), - DEFINE_KEYFIELD( m_String_tSlideshowDirectory, FIELD_STRING, "directory" ), - - // DEFINE_FIELD( m_SlideKeywordList, CUtlVector < SlideKeywordList_t* > ), - DEFINE_AUTO_ARRAY( m_chCurrentSlideLists, FIELD_CHARACTER ), - - DEFINE_KEYFIELD( m_fMinSlideTime, FIELD_FLOAT, "minslidetime" ), - DEFINE_KEYFIELD( m_fMaxSlideTime, FIELD_FLOAT, "maxslidetime" ), - - DEFINE_KEYFIELD( m_iCycleType, FIELD_INTEGER, "cycletype" ), - DEFINE_KEYFIELD( m_bNoListRepeats, FIELD_BOOLEAN, "nolistrepeats" ), - - DEFINE_KEYFIELD( m_iScreenWidth, FIELD_INTEGER, "width" ), - DEFINE_KEYFIELD( m_iScreenHeight, FIELD_INTEGER, "height" ), - - //DEFINE_FIELD( m_bDoFullTransmit, FIELD_BOOLEAN ), - - //DEFINE_UTLVECTOR( m_hScreens, FIELD_EHANDLE ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - - DEFINE_INPUTFUNC( FIELD_STRING, "SetDisplayText", InputSetDisplayText ), - - DEFINE_INPUTFUNC( FIELD_VOID, "RemoveAllSlides", InputRemoveAllSlides ), - DEFINE_INPUTFUNC( FIELD_STRING, "AddSlides", InputAddSlides ), - - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetMinSlideTime", InputSetMinSlideTime ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetMaxSlideTime", InputSetMaxSlideTime ), - - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetCycleType", InputSetCycleType ), - DEFINE_INPUTFUNC( FIELD_BOOLEAN, "SetNoListRepeats", InputSetNoListRepeats ), - -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CSlideshowDisplay, DT_SlideshowDisplay ) - SendPropBool( SENDINFO(m_bEnabled) ), - SendPropString( SENDINFO( m_szDisplayText ) ), - SendPropString( SENDINFO( m_szSlideshowDirectory ) ), - SendPropArray3( SENDINFO_ARRAY3(m_chCurrentSlideLists), SendPropInt( SENDINFO_ARRAY(m_chCurrentSlideLists), 8, SPROP_UNSIGNED ) ), - SendPropFloat( SENDINFO(m_fMinSlideTime), 11, 0, 0.0f, 20.0f ), - SendPropFloat( SENDINFO(m_fMaxSlideTime), 11, 0, 0.0f, 20.0f ), - SendPropInt( SENDINFO(m_iCycleType), 2, SPROP_UNSIGNED ), - SendPropBool( SENDINFO(m_bNoListRepeats) ), -END_SEND_TABLE() - - -CSlideshowDisplay::~CSlideshowDisplay() -{ - int i; - // Kill the control panels - for ( i = m_hScreens.Count(); --i >= 0; ) - { - DestroyVGuiScreen( m_hScreens[i].Get() ); - } - m_hScreens.RemoveAll(); -} - -//----------------------------------------------------------------------------- -// Read in worldcraft data... -//----------------------------------------------------------------------------- -bool CSlideshowDisplay::KeyValue( const char *szKeyName, const char *szValue ) -{ - //!! temp hack, until worldcraft is fixed - // strip the # tokens from (duplicate) key names - char *s = (char *)strchr( szKeyName, '#' ); - if ( s ) - { - *s = '\0'; - } - - // NOTE: Have to do these separate because they set two values instead of one - if( FStrEq( szKeyName, "angles" ) ) - { - Assert( GetMoveParent() == NULL ); - QAngle angles; - UTIL_StringToVector( angles.Base(), szValue ); - - // Because the vgui screen basis is strange (z is front, y is up, x is right) - // we need to rotate the typical basis before applying it - VMatrix mat, rotation, tmp; - MatrixFromAngles( angles, mat ); - MatrixBuildRotationAboutAxis( rotation, Vector( 0, 1, 0 ), 90 ); - MatrixMultiply( mat, rotation, tmp ); - MatrixBuildRotateZ( rotation, 90 ); - MatrixMultiply( tmp, rotation, mat ); - MatrixToAngles( mat, angles ); - SetAbsAngles( angles ); - - return true; - } - - return BaseClass::KeyValue( szKeyName, szValue ); -} - -int CSlideshowDisplay::UpdateTransmitState() -{ - if ( m_bDoFullTransmit ) - { - m_bDoFullTransmit = false; - return SetTransmitState( FL_EDICT_ALWAYS ); - } - - return SetTransmitState( FL_EDICT_FULLCHECK ); -} - -void CSlideshowDisplay::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ) -{ - // Are we already marked for transmission? - if ( pInfo->m_pTransmitEdict->Get( entindex() ) ) - return; - - BaseClass::SetTransmit( pInfo, bAlways ); - - // Force our screens to be sent too. - for ( int i=0; i < m_hScreens.Count(); i++ ) - { - CVGuiScreen *pScreen = m_hScreens[i].Get(); - pScreen->SetTransmit( pInfo, bAlways ); - } -} - -void CSlideshowDisplay::Spawn( void ) -{ - Q_strcpy( m_szSlideshowDirectory.GetForModify(), m_String_tSlideshowDirectory.ToCStr() ); - Precache(); - - BaseClass::Spawn(); - - m_bEnabled = false; - - // Clear out selected list - m_chCurrentSlideLists.GetForModify( 0 ) = 0; // Select all slides to begin with - for ( int i = 1; i < 16; ++i ) - m_chCurrentSlideLists.GetForModify( i ) = (unsigned char)-1; - - SpawnControlPanels(); - - ScreenVisible( m_bEnabled ); - - m_bDoFullTransmit = true; -} - -void CSlideshowDisplay::Precache( void ) -{ - BaseClass::Precache(); - - BuildSlideShowImagesList(); - - PrecacheVGuiScreen( "slideshow_display_screen" ); -} - -void CSlideshowDisplay::OnRestore( void ) -{ - BaseClass::OnRestore(); - - BuildSlideShowImagesList(); - - RestoreControlPanels(); - - ScreenVisible( m_bEnabled ); -} - -void CSlideshowDisplay::ScreenVisible( bool bVisible ) -{ - for ( int iScreen = 0; iScreen < m_hScreens.Count(); ++iScreen ) - { - CVGuiScreen *pScreen = m_hScreens[ iScreen ].Get(); - if ( bVisible ) - pScreen->RemoveEffects( EF_NODRAW ); - else - pScreen->AddEffects( EF_NODRAW ); - } -} - -void CSlideshowDisplay::Disable( void ) -{ - if ( !m_bEnabled ) - return; - - m_bEnabled = false; - - ScreenVisible( false ); -} - -void CSlideshowDisplay::Enable( void ) -{ - if ( m_bEnabled ) - return; - - m_bEnabled = true; - - ScreenVisible( true ); -} - - -void CSlideshowDisplay::InputDisable( inputdata_t &inputdata ) -{ - Disable(); -} - -void CSlideshowDisplay::InputEnable( inputdata_t &inputdata ) -{ - Enable(); -} - - -void CSlideshowDisplay::InputSetDisplayText( inputdata_t &inputdata ) -{ - Q_strcpy( m_szDisplayText.GetForModify(), inputdata.value.String() ); -} - -void CSlideshowDisplay::InputRemoveAllSlides( inputdata_t &inputdata ) -{ - // Clear out selected list - for ( int i = 0; i < 16; ++i ) - m_chCurrentSlideLists.GetForModify( i ) = (unsigned char)-1; -} - -void CSlideshowDisplay::InputAddSlides( inputdata_t &inputdata ) -{ - // Find the list with the current keyword - int iList; - for ( iList = 0; iList < m_SlideKeywordList.Count(); ++iList ) - { - if ( Q_strcmp( m_SlideKeywordList[ iList ]->szSlideKeyword, inputdata.value.String() ) == 0 ) - break; - } - - if ( iList < m_SlideKeywordList.Count() ) - { - // Found the keyword list, so add this index to the selected lists - int iNumCurrentSlideLists; - for ( iNumCurrentSlideLists = 0; iNumCurrentSlideLists < 16; ++iNumCurrentSlideLists ) - { - if ( m_chCurrentSlideLists[ iNumCurrentSlideLists ] == (unsigned char)-1 ) - break; - } - - if ( iNumCurrentSlideLists >= 16 ) - return; - - m_chCurrentSlideLists.GetForModify( iNumCurrentSlideLists ) = iList; - } -} - - -void CSlideshowDisplay::InputSetMinSlideTime( inputdata_t &inputdata ) -{ - m_fMinSlideTime = inputdata.value.Float(); -} - -void CSlideshowDisplay::InputSetMaxSlideTime( inputdata_t &inputdata ) -{ - m_fMaxSlideTime = inputdata.value.Float(); -} - - -void CSlideshowDisplay::InputSetCycleType( inputdata_t &inputdata ) -{ - m_iCycleType = inputdata.value.Int(); -} - -void CSlideshowDisplay::InputSetNoListRepeats( inputdata_t &inputdata ) -{ - m_bNoListRepeats = inputdata.value.Bool(); -} - - -void CSlideshowDisplay::GetControlPanelInfo( int nPanelIndex, const char *&pPanelName ) -{ - pPanelName = "slideshow_display_screen"; -} - -void CSlideshowDisplay::GetControlPanelClassName( int nPanelIndex, const char *&pPanelName ) -{ - pPanelName = "vgui_screen"; -} - -//----------------------------------------------------------------------------- -// This is called by the base object when it's time to spawn the control panels -//----------------------------------------------------------------------------- -void CSlideshowDisplay::SpawnControlPanels() -{ - int nPanel; - for ( nPanel = 0; true; ++nPanel ) - { - const char *pScreenName; - GetControlPanelInfo( nPanel, pScreenName ); - if (!pScreenName) - continue; - - const char *pScreenClassname; - GetControlPanelClassName( nPanel, pScreenClassname ); - if ( !pScreenClassname ) - continue; - - float flWidth = m_iScreenWidth; - float flHeight = m_iScreenHeight; - - CVGuiScreen *pScreen = CreateVGuiScreen( pScreenClassname, pScreenName, this, this, -1 ); - pScreen->ChangeTeam( GetTeamNumber() ); - pScreen->SetActualSize( flWidth, flHeight ); - pScreen->SetActive( true ); - pScreen->MakeVisibleOnlyToTeammates( false ); - pScreen->SetTransparency( true ); - int nScreen = m_hScreens.AddToTail( ); - m_hScreens[nScreen].Set( pScreen ); - - return; - } -} - -void CSlideshowDisplay::RestoreControlPanels( void ) -{ - int nPanel; - for ( nPanel = 0; true; ++nPanel ) - { - const char *pScreenName; - GetControlPanelInfo( nPanel, pScreenName ); - if (!pScreenName) - continue; - - const char *pScreenClassname; - GetControlPanelClassName( nPanel, pScreenClassname ); - if ( !pScreenClassname ) - continue; - - CVGuiScreen *pScreen = (CVGuiScreen *)gEntList.FindEntityByClassname( NULL, pScreenClassname ); - - while ( ( pScreen && pScreen->GetOwnerEntity() != this ) || Q_strcmp( pScreen->GetPanelName(), pScreenName ) != 0 ) - { - pScreen = (CVGuiScreen *)gEntList.FindEntityByClassname( pScreen, pScreenClassname ); - } - - if ( pScreen ) - { - int nScreen = m_hScreens.AddToTail( ); - m_hScreens[nScreen].Set( pScreen ); - pScreen->SetActive( true ); - } - - return; - } -} - -void CSlideshowDisplay::BuildSlideShowImagesList( void ) -{ - FileFindHandle_t matHandle; - char szDirectory[_MAX_PATH]; - char szMatFileName[_MAX_PATH] = {'\0'}; - char szFileBuffer[ SLIDESHOW_LIST_BUFFER_MAX ]; - char *pchCurrentLine = NULL; - - if ( IsX360() ) - { - Q_snprintf( szDirectory, sizeof( szDirectory ), "materials/vgui/%s/slides.txt", m_szSlideshowDirectory.Get() ); - - FileHandle_t fh = g_pFullFileSystem->Open( szDirectory, "rt" ); - if ( !fh ) - { - DevWarning( "Couldn't read slideshow image file %s!", szDirectory ); - return; - } - - int iFileSize = MIN( g_pFullFileSystem->Size( fh ), SLIDESHOW_LIST_BUFFER_MAX ); - - int iBytesRead = g_pFullFileSystem->Read( szFileBuffer, iFileSize, fh ); - g_pFullFileSystem->Close( fh ); - - // Ensure we don't write outside of our buffer - if ( iBytesRead > iFileSize ) - iBytesRead = iFileSize; - szFileBuffer[ iBytesRead ] = '\0'; - - pchCurrentLine = szFileBuffer; - - // Seek to end of first line - char *pchNextLine = pchCurrentLine; - while ( *pchNextLine != '\0' && *pchNextLine != '\n' && *pchNextLine != ' ' ) - ++pchNextLine; - - if ( *pchNextLine != '\0' ) - { - // Mark end of string - *pchNextLine = '\0'; - - // Seek to start of next string - ++pchNextLine; - while ( *pchNextLine != '\0' && ( *pchNextLine == '\n' || *pchNextLine == ' ' ) ) - ++pchNextLine; - } - - Q_strncpy( szMatFileName, pchCurrentLine, sizeof(szMatFileName) ); - pchCurrentLine = pchNextLine; - } - else - { - Q_snprintf( szDirectory, sizeof( szDirectory ), "materials/vgui/%s/*.vmt", m_szSlideshowDirectory.Get() ); - const char *pMatFileName = g_pFullFileSystem->FindFirst( szDirectory, &matHandle ); - - if ( pMatFileName ) - Q_strncpy( szMatFileName, pMatFileName, sizeof(szMatFileName) ); - } - - int iSlideIndex = 0; - - while ( szMatFileName[ 0 ] ) - { - char szFileName[_MAX_PATH]; - Q_snprintf( szFileName, sizeof( szFileName ), "vgui/%s/%s", m_szSlideshowDirectory.Get(), szMatFileName ); - szFileName[ Q_strlen( szFileName ) - 4 ] = '\0'; - - PrecacheMaterial( szFileName ); - - // Get material keywords - char szFullFileName[_MAX_PATH]; - Q_snprintf( szFullFileName, sizeof( szFullFileName ), "materials/vgui/%s/%s", m_szSlideshowDirectory.Get(), szMatFileName ); - - KeyValues *pMaterialKeys = new KeyValues( "material" ); - bool bLoaded = pMaterialKeys->LoadFromFile( g_pFullFileSystem, szFullFileName, NULL ); - - if ( bLoaded ) - { - char szKeywords[ 256 ]; - Q_strcpy( szKeywords, pMaterialKeys->GetString( "%keywords", "" ) ); - - char *pchKeyword = szKeywords; - - while ( pchKeyword[ 0 ] != '\0' ) - { - char *pNextKeyword = pchKeyword; - - // Skip commas and spaces - while ( pNextKeyword[ 0 ] != '\0' && pNextKeyword[ 0 ] != ',' ) - ++pNextKeyword; - - if ( pNextKeyword[ 0 ] != '\0' ) - { - pNextKeyword[ 0 ] = '\0'; - ++pNextKeyword; - - while ( pNextKeyword[ 0 ] != '\0' && ( pNextKeyword[ 0 ] == ',' || pNextKeyword[ 0 ] == ' ' ) ) - ++pNextKeyword; - } - - // Find the list with the current keyword - int iList; - for ( iList = 0; iList < m_SlideKeywordList.Count(); ++iList ) - { - if ( Q_strcmp( m_SlideKeywordList[ iList ]->szSlideKeyword, pchKeyword ) == 0 ) - break; - } - - if ( iList >= m_SlideKeywordList.Count() ) - { - // Couldn't find the list, so create it - iList = m_SlideKeywordList.AddToTail( new SlideKeywordList_t ); - Q_strcpy( m_SlideKeywordList[ iList ]->szSlideKeyword, pchKeyword ); - } - - pchKeyword = pNextKeyword; - } - } - - // Find the generic list - int iList; - for ( iList = 0; iList < m_SlideKeywordList.Count(); ++iList ) - { - if ( Q_strcmp( m_SlideKeywordList[ iList ]->szSlideKeyword, "" ) == 0 ) - break; - } - - if ( iList >= m_SlideKeywordList.Count() ) - { - // Couldn't find the generic list, so create it - iList = m_SlideKeywordList.AddToHead( new SlideKeywordList_t ); - Q_strcpy( m_SlideKeywordList[ iList ]->szSlideKeyword, "" ); - } - - if ( IsX360() ) - { - // Seek to end of first line - char *pchNextLine = pchCurrentLine; - while ( *pchNextLine != '\0' && *pchNextLine != '\n' && *pchNextLine != ' ' ) - ++pchNextLine; - - if ( *pchNextLine != '\0' ) - { - // Mark end of string - *pchNextLine = '\0'; - - // Seek to start of next string - ++pchNextLine; - while ( *pchNextLine != '\0' && ( *pchNextLine == '\n' || *pchNextLine == ' ' ) ) - ++pchNextLine; - } - - Q_strncpy( szMatFileName, pchCurrentLine, sizeof(szMatFileName) ); - pchCurrentLine = pchNextLine; - } - else - { - const char *pMatFileName = g_pFullFileSystem->FindNext( matHandle ); - - if ( pMatFileName ) - Q_strncpy( szMatFileName, pMatFileName, sizeof(szMatFileName) ); - else - szMatFileName[ 0 ] = '\0'; - } - - ++iSlideIndex; - } - - if ( !IsX360() ) - { - g_pFullFileSystem->FindClose( matHandle ); - } -} diff --git a/game/server/smoke_trail.cpp b/game/server/smoke_trail.cpp deleted file mode 100644 index fe1650066..000000000 --- a/game/server/smoke_trail.cpp +++ /dev/null @@ -1,645 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "smoke_trail.h" -#include "dt_send.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SMOKETRAIL_ENTITYNAME "env_smoketrail" -#define SPORETRAIL_ENTITYNAME "env_sporetrail" -#define SPOREEXPLOSION_ENTITYNAME "env_sporeexplosion" -#define DUSTTRAIL_ENTITYNAME "env_dusttrail" - -//----------------------------------------------------------------------------- -//Data table -//----------------------------------------------------------------------------- -IMPLEMENT_SERVERCLASS_ST(SmokeTrail, DT_SmokeTrail) - SendPropFloat(SENDINFO(m_SpawnRate), 8, 0, 1, 1024), - SendPropVector(SENDINFO(m_StartColor), 8, 0, 0, 1), - SendPropVector(SENDINFO(m_EndColor), 8, 0, 0, 1), - SendPropFloat(SENDINFO(m_ParticleLifetime), 16, SPROP_ROUNDUP, 0.1, 100), - SendPropFloat(SENDINFO(m_StopEmitTime), 0, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_MinSpeed), -1, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_MaxSpeed), -1, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_MinDirectedSpeed), -1, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_MaxDirectedSpeed), -1, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_StartSize), -1, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_EndSize), -1, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_SpawnRadius), -1, SPROP_NOSCALE), - SendPropBool(SENDINFO(m_bEmit) ), - SendPropInt(SENDINFO(m_nAttachment), 32 ), - SendPropFloat(SENDINFO(m_Opacity), -1, SPROP_NOSCALE), -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS(env_smoketrail, SmokeTrail); - -BEGIN_DATADESC( SmokeTrail ) - - DEFINE_FIELD( m_StartColor, FIELD_VECTOR ), - DEFINE_FIELD( m_EndColor, FIELD_VECTOR ), - DEFINE_KEYFIELD( m_Opacity, FIELD_FLOAT, "opacity" ), - DEFINE_KEYFIELD( m_SpawnRate, FIELD_FLOAT, "spawnrate" ), - DEFINE_KEYFIELD( m_ParticleLifetime, FIELD_FLOAT, "lifetime" ), - DEFINE_FIELD( m_StopEmitTime, FIELD_TIME ), - DEFINE_KEYFIELD( m_MinSpeed, FIELD_FLOAT, "minspeed" ), - DEFINE_KEYFIELD( m_MaxSpeed, FIELD_FLOAT, "maxspeed" ), - DEFINE_KEYFIELD( m_MinDirectedSpeed, FIELD_FLOAT, "mindirectedspeed" ), - DEFINE_KEYFIELD( m_MaxDirectedSpeed, FIELD_FLOAT, "maxdirectedspeed" ), - DEFINE_KEYFIELD( m_StartSize, FIELD_FLOAT, "startsize" ), - DEFINE_KEYFIELD( m_EndSize, FIELD_FLOAT, "endsize" ), - DEFINE_KEYFIELD( m_SpawnRadius, FIELD_FLOAT, "spawnradius" ), - DEFINE_FIELD( m_bEmit, FIELD_BOOLEAN ), - DEFINE_FIELD( m_nAttachment, FIELD_INTEGER ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : -//----------------------------------------------------------------------------- -SmokeTrail::SmokeTrail() -{ - m_SpawnRate = 10; - m_StartColor.GetForModify().Init(0.5, 0.5, 0.5); - m_EndColor.GetForModify().Init(0,0,0); - m_ParticleLifetime = 5; - m_StopEmitTime = 0; // Don't stop emitting particles - m_MinSpeed = 2; - m_MaxSpeed = 4; - m_MinDirectedSpeed = m_MaxDirectedSpeed = 0; - m_StartSize = 35; - m_EndSize = 55; - m_SpawnRadius = 2; - m_bEmit = true; - m_nAttachment = 0; - m_Opacity = 0.5f; -} - - -//----------------------------------------------------------------------------- -// Parse data from a map file -//----------------------------------------------------------------------------- -bool SmokeTrail::KeyValue( const char *szKeyName, const char *szValue ) -{ - if ( FStrEq( szKeyName, "startcolor" ) ) - { - color32 tmp; - UTIL_StringToColor32( &tmp, szValue ); - m_StartColor.GetForModify().Init( tmp.r / 255.0f, tmp.g / 255.0f, tmp.b / 255.0f ); - return true; - } - - if ( FStrEq( szKeyName, "endcolor" ) ) - { - color32 tmp; - UTIL_StringToColor32( &tmp, szValue ); - m_EndColor.GetForModify().Init( tmp.r / 255.0f, tmp.g / 255.0f, tmp.b / 255.0f ); - return true; - } - - if ( FStrEq( szKeyName, "emittime" ) ) - { - m_StopEmitTime = gpGlobals->curtime + atof( szValue ); - return true; - } - - return BaseClass::KeyValue( szKeyName, szValue ); -} - - -//----------------------------------------------------------------------------- -// Purpose : -// Input : -// Output : -//----------------------------------------------------------------------------- -void SmokeTrail::SetEmit(bool bVal) -{ - m_bEmit = bVal; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : SmokeTrail* -//----------------------------------------------------------------------------- -SmokeTrail* SmokeTrail::CreateSmokeTrail() -{ - CBaseEntity *pEnt = CreateEntityByName(SMOKETRAIL_ENTITYNAME); - if(pEnt) - { - SmokeTrail *pSmoke = dynamic_cast(pEnt); - if(pSmoke) - { - pSmoke->Activate(); - return pSmoke; - } - else - { - UTIL_Remove(pEnt); - } - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Attach the smoke trail to an entity or point -// Input : index - entity that has the attachment -// attachment - point to attach to -//----------------------------------------------------------------------------- -void SmokeTrail::FollowEntity( CBaseEntity *pEntity, const char *pAttachmentName ) -{ - // For attachments - if ( pAttachmentName && pEntity && pEntity->GetBaseAnimating() ) - { - m_nAttachment = pEntity->GetBaseAnimating()->LookupAttachment( pAttachmentName ); - } - else - { - m_nAttachment = 0; - } - - BaseClass::FollowEntity( pEntity ); -} - - -//================================================== -// RocketTrail -//================================================== - -//Data table -IMPLEMENT_SERVERCLASS_ST(RocketTrail, DT_RocketTrail) - SendPropFloat(SENDINFO(m_SpawnRate), 8, 0, 1, 1024), - SendPropVector(SENDINFO(m_StartColor), 8, 0, 0, 1), - SendPropVector(SENDINFO(m_EndColor), 8, 0, 0, 1), - SendPropFloat(SENDINFO(m_ParticleLifetime), 16, SPROP_ROUNDUP, 0.1, 100), - SendPropFloat(SENDINFO(m_StopEmitTime), 0, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_MinSpeed), -1, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_MaxSpeed), -1, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_StartSize), -1, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_EndSize), -1, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_SpawnRadius), -1, SPROP_NOSCALE), - SendPropBool(SENDINFO(m_bEmit)), - SendPropInt(SENDINFO(m_nAttachment), 32 ), - SendPropFloat(SENDINFO(m_Opacity), -1, SPROP_NOSCALE), - SendPropInt (SENDINFO(m_bDamaged), 1, SPROP_UNSIGNED), - SendPropFloat(SENDINFO(m_flFlareScale), -1, SPROP_NOSCALE), -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( env_rockettrail, RocketTrail ); - -BEGIN_DATADESC( RocketTrail ) - - DEFINE_FIELD( m_StartColor, FIELD_VECTOR ), - DEFINE_FIELD( m_EndColor, FIELD_VECTOR ), - DEFINE_FIELD( m_Opacity, FIELD_FLOAT ), - DEFINE_FIELD( m_SpawnRate, FIELD_FLOAT ), - DEFINE_FIELD( m_ParticleLifetime, FIELD_FLOAT ), - DEFINE_FIELD( m_StopEmitTime, FIELD_TIME ), - DEFINE_FIELD( m_MinSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_MaxSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_StartSize, FIELD_FLOAT ), - DEFINE_FIELD( m_EndSize, FIELD_FLOAT ), - DEFINE_FIELD( m_SpawnRadius, FIELD_FLOAT ), - DEFINE_FIELD( m_bEmit, FIELD_BOOLEAN ), - DEFINE_FIELD( m_nAttachment, FIELD_INTEGER ), - DEFINE_FIELD( m_bDamaged, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flFlareScale, FIELD_FLOAT ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -// Output : -//----------------------------------------------------------------------------- -RocketTrail::RocketTrail() -{ - m_SpawnRate = 10; - m_StartColor.GetForModify().Init(0.5, 0.5, 0.5); - m_EndColor.GetForModify().Init(0,0,0); - m_ParticleLifetime = 5; - m_StopEmitTime = 0; // Don't stop emitting particles - m_MinSpeed = 2; - m_MaxSpeed = 4; - m_StartSize = 35; - m_EndSize = 55; - m_SpawnRadius = 2; - m_bEmit = true; - m_nAttachment = 0; - m_Opacity = 0.5f; - m_flFlareScale = 1.5; -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void RocketTrail::SetEmit(bool bVal) -{ - m_bEmit = bVal; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : SmokeTrail* -//----------------------------------------------------------------------------- -RocketTrail* RocketTrail::CreateRocketTrail() -{ - CBaseEntity *pEnt = CreateEntityByName( "env_rockettrail" ); - - if( pEnt != NULL ) - { - RocketTrail *pTrail = dynamic_cast(pEnt); - - if( pTrail != NULL ) - { - pTrail->Activate(); - return pTrail; - } - else - { - UTIL_Remove( pEnt ); - } - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Attach the smoke trail to an entity or point -// Input : index - entity that has the attachment -// attachment - point to attach to -//----------------------------------------------------------------------------- -void RocketTrail::FollowEntity( CBaseEntity *pEntity, const char *pAttachmentName ) -{ - // For attachments - if ( pAttachmentName && pEntity && pEntity->GetBaseAnimating() ) - { - m_nAttachment = pEntity->GetBaseAnimating()->LookupAttachment( pAttachmentName ); - } - else - { - m_nAttachment = 0; - } - - BaseClass::FollowEntity( pEntity ); -} - -//================================================== -// SporeTrail -//================================================== - -IMPLEMENT_SERVERCLASS_ST( SporeTrail, DT_SporeTrail ) - SendPropFloat (SENDINFO(m_flSpawnRate), 8, 0, 1, 1024), - SendPropVector (SENDINFO(m_vecEndColor), 8, 0, 0, 1), - SendPropFloat (SENDINFO(m_flParticleLifetime), 16, SPROP_ROUNDUP, 0.1, 100), - SendPropFloat (SENDINFO(m_flStartSize), -1, SPROP_NOSCALE), - SendPropFloat (SENDINFO(m_flEndSize), -1, SPROP_NOSCALE), - SendPropFloat (SENDINFO(m_flSpawnRadius), -1, SPROP_NOSCALE), - SendPropBool (SENDINFO(m_bEmit)), -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS(env_sporetrail, SporeTrail); - -BEGIN_DATADESC( SporeTrail ) - - DEFINE_FIELD( m_vecEndColor, FIELD_VECTOR ), - DEFINE_FIELD( m_flSpawnRate, FIELD_FLOAT ), - DEFINE_FIELD( m_flParticleLifetime, FIELD_FLOAT ), - DEFINE_FIELD( m_flStartSize, FIELD_FLOAT ), - DEFINE_FIELD( m_flEndSize, FIELD_FLOAT ), - DEFINE_FIELD( m_flSpawnRadius, FIELD_FLOAT ), - DEFINE_FIELD( m_bEmit, FIELD_BOOLEAN ), - -END_DATADESC() - -SporeTrail::SporeTrail( void ) -{ - m_vecEndColor.GetForModify().Init(); - - m_flSpawnRate = 100.0f; - m_flParticleLifetime = 1.0f; - m_flStartSize = 1.0f; - m_flEndSize = 0.0f; - m_flSpawnRadius = 16.0f; - SetRenderColor( 255, 255, 255, 255 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : SporeTrail* -//----------------------------------------------------------------------------- -SporeTrail* SporeTrail::CreateSporeTrail() -{ - CBaseEntity *pEnt = CreateEntityByName( SPORETRAIL_ENTITYNAME ); - - if(pEnt) - { - SporeTrail *pSpore = dynamic_cast(pEnt); - - if ( pSpore ) - { - pSpore->Activate(); - return pSpore; - } - else - { - UTIL_Remove( pEnt ); - } - } - - return NULL; -} - -//================================================== -// SporeExplosion -//================================================== - -IMPLEMENT_SERVERCLASS_ST( SporeExplosion, DT_SporeExplosion ) - SendPropFloat (SENDINFO(m_flSpawnRate), 8, 0, 1, 1024), - SendPropFloat (SENDINFO(m_flParticleLifetime), 16, SPROP_ROUNDUP, 0.1, 100), - SendPropFloat (SENDINFO(m_flStartSize), -1, SPROP_NOSCALE), - SendPropFloat (SENDINFO(m_flEndSize), -1, SPROP_NOSCALE), - SendPropFloat (SENDINFO(m_flSpawnRadius), -1, SPROP_NOSCALE), - SendPropBool (SENDINFO(m_bEmit) ), - SendPropBool (SENDINFO(m_bDontRemove) ), -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( env_sporeexplosion, SporeExplosion ); - -BEGIN_DATADESC( SporeExplosion ) - - DEFINE_KEYFIELD( m_flSpawnRate, FIELD_FLOAT, "spawnrate" ), - DEFINE_FIELD( m_flParticleLifetime, FIELD_FLOAT ), - DEFINE_FIELD( m_flStartSize, FIELD_FLOAT ), - DEFINE_FIELD( m_flEndSize, FIELD_FLOAT ), - DEFINE_FIELD( m_flSpawnRadius, FIELD_FLOAT ), - DEFINE_FIELD( m_bEmit, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "startdisabled" ), - DEFINE_FIELD( m_bDontRemove, FIELD_BOOLEAN ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - -END_DATADESC() - -SporeExplosion::SporeExplosion( void ) -{ - m_flSpawnRate = 100.0f; - m_flParticleLifetime = 1.0f; - m_flStartSize = 1.0f; - m_flEndSize = 0.0f; - m_flSpawnRadius = 16.0f; - SetRenderColor( 255, 255, 255, 255 ); - m_bEmit = true; - m_bDisabled = false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void SporeExplosion::Spawn( void ) -{ - BaseClass::Spawn(); - - m_bEmit = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : SporeExplosion* -//----------------------------------------------------------------------------- -SporeExplosion *SporeExplosion::CreateSporeExplosion() -{ - CBaseEntity *pEnt = CreateEntityByName( SPOREEXPLOSION_ENTITYNAME ); - - if ( pEnt ) - { - SporeExplosion *pSpore = dynamic_cast(pEnt); - - if ( pSpore ) - { - pSpore->Activate(); - return pSpore; - } - else - { - UTIL_Remove( pEnt ); - } - } - - return NULL; -} - -void SporeExplosion::InputEnable( inputdata_t &inputdata ) -{ - m_bDontRemove = true; - m_bDisabled = false; - m_bEmit = true; -} - -void SporeExplosion::InputDisable( inputdata_t &inputdata ) -{ - m_bDontRemove = true; - m_bDisabled = true; - m_bEmit = false; -} - -BEGIN_DATADESC( CFireTrail ) - - DEFINE_FIELD( m_flLifetime, FIELD_FLOAT ), - DEFINE_FIELD( m_nAttachment, FIELD_INTEGER ), - -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CFireTrail, DT_FireTrail ) - SendPropInt( SENDINFO( m_nAttachment ), 32 ), - SendPropFloat( SENDINFO( m_flLifetime ), 0, SPROP_NOSCALE ), -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( env_fire_trail, CFireTrail ); - -void CFireTrail::Precache( void ) -{ - PrecacheMaterial( "sprites/flamelet1" ); - PrecacheMaterial( "sprites/flamelet2" ); - PrecacheMaterial( "sprites/flamelet3" ); - PrecacheMaterial( "sprites/flamelet4" ); - PrecacheMaterial( "sprites/flamelet5" ); - PrecacheMaterial( "particle/particle_smokegrenade" ); - PrecacheMaterial( "particle/particle_noisesphere" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Attach the smoke trail to an entity or point -// Input : index - entity that has the attachment -// attachment - point to attach to -//----------------------------------------------------------------------------- -void CFireTrail::FollowEntity( CBaseEntity *pEntity, const char *pAttachmentName ) -{ - // For attachments - if ( pAttachmentName && pEntity && pEntity->GetBaseAnimating() ) - { - m_nAttachment = pEntity->GetBaseAnimating()->LookupAttachment( pAttachmentName ); - } - else - { - m_nAttachment = 0; - } - - BaseClass::FollowEntity( pEntity ); -} - -//----------------------------------------------------------------------------- -// Purpose: Create and return a new fire trail entity -//----------------------------------------------------------------------------- -CFireTrail *CFireTrail::CreateFireTrail( void ) -{ - CBaseEntity *pEnt = CreateEntityByName( "env_fire_trail" ); - - if ( pEnt ) - { - CFireTrail *pTrail = dynamic_cast(pEnt); - - if ( pTrail ) - { - pTrail->Activate(); - return pTrail; - } - else - { - UTIL_Remove( pEnt ); - } - } - - return NULL; -} - - -//----------------------------------------------------------------------------- -//Data table -//----------------------------------------------------------------------------- -IMPLEMENT_SERVERCLASS_ST(DustTrail, DT_DustTrail) - SendPropFloat(SENDINFO(m_SpawnRate), 8, 0, 1, 1024), - SendPropVector(SENDINFO(m_Color), 8, 0, 0, 1), - SendPropFloat(SENDINFO(m_ParticleLifetime), 16, SPROP_ROUNDUP, 0.1, 100), - SendPropFloat(SENDINFO(m_StopEmitTime), 0, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_MinSpeed), -1, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_MaxSpeed), -1, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_MinDirectedSpeed), -1, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_MaxDirectedSpeed), -1, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_StartSize), -1, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_EndSize), -1, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_SpawnRadius), -1, SPROP_NOSCALE), - SendPropBool(SENDINFO(m_bEmit) ), - SendPropFloat(SENDINFO(m_Opacity), -1, SPROP_NOSCALE), -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( env_dusttrail, DustTrail); - -BEGIN_DATADESC( DustTrail ) - - DEFINE_FIELD( m_Color, FIELD_VECTOR ), - DEFINE_KEYFIELD( m_Opacity, FIELD_FLOAT, "opacity" ), - DEFINE_KEYFIELD( m_SpawnRate, FIELD_FLOAT, "spawnrate" ), - DEFINE_KEYFIELD( m_ParticleLifetime, FIELD_FLOAT, "lifetime" ), - DEFINE_FIELD( m_StopEmitTime, FIELD_TIME ), - DEFINE_KEYFIELD( m_MinSpeed, FIELD_FLOAT, "minspeed" ), - DEFINE_KEYFIELD( m_MaxSpeed, FIELD_FLOAT, "maxspeed" ), - DEFINE_KEYFIELD( m_MinDirectedSpeed, FIELD_FLOAT, "mindirectedspeed" ), - DEFINE_KEYFIELD( m_MaxDirectedSpeed, FIELD_FLOAT, "maxdirectedspeed" ), - DEFINE_KEYFIELD( m_StartSize, FIELD_FLOAT, "startsize" ), - DEFINE_KEYFIELD( m_EndSize, FIELD_FLOAT, "endsize" ), - DEFINE_KEYFIELD( m_SpawnRadius, FIELD_FLOAT, "spawnradius" ), - DEFINE_FIELD( m_bEmit, FIELD_BOOLEAN ), - DEFINE_FIELD( m_nAttachment, FIELD_INTEGER ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : -//----------------------------------------------------------------------------- -DustTrail::DustTrail() -{ - m_SpawnRate = 10; - m_Color.GetForModify().Init(0.5, 0.5, 0.5); - m_ParticleLifetime = 5; - m_StopEmitTime = 0; // Don't stop emitting particles - m_MinSpeed = 2; - m_MaxSpeed = 4; - m_MinDirectedSpeed = m_MaxDirectedSpeed = 0; - m_StartSize = 35; - m_EndSize = 55; - m_SpawnRadius = 2; - m_bEmit = true; - m_Opacity = 0.5f; -} - - -//----------------------------------------------------------------------------- -// Parse data from a map file -//----------------------------------------------------------------------------- -bool DustTrail::KeyValue( const char *szKeyName, const char *szValue ) -{ - if ( FStrEq( szKeyName, "color" ) ) - { - color32 tmp; - UTIL_StringToColor32( &tmp, szValue ); - m_Color.GetForModify().Init( tmp.r / 255.0f, tmp.g / 255.0f, tmp.b / 255.0f ); - return true; - } - - if ( FStrEq( szKeyName, "emittime" ) ) - { - m_StopEmitTime = gpGlobals->curtime + atof( szValue ); - return true; - } - - return BaseClass::KeyValue( szKeyName, szValue ); -} - - -//----------------------------------------------------------------------------- -// Purpose : -// Input : -// Output : -//----------------------------------------------------------------------------- -void DustTrail::SetEmit(bool bVal) -{ - m_bEmit = bVal; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : DustTrail* -//----------------------------------------------------------------------------- -DustTrail* DustTrail::CreateDustTrail() -{ - CBaseEntity *pEnt = CreateEntityByName(DUSTTRAIL_ENTITYNAME); - if(pEnt) - { - DustTrail *pDust = dynamic_cast(pEnt); - if(pDust) - { - pDust->Activate(); - return pDust; - } - else - { - UTIL_Remove(pEnt); - } - } - - return NULL; -} diff --git a/game/server/smoke_trail.h b/game/server/smoke_trail.h deleted file mode 100644 index a38011452..000000000 --- a/game/server/smoke_trail.h +++ /dev/null @@ -1,210 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef SMOKE_TRAIL_H -#define SMOKE_TRAIL_H - -#include "baseparticleentity.h" - -//================================================== -// SmokeTrail -//================================================== - -class SmokeTrail : public CBaseParticleEntity -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( SmokeTrail, CBaseParticleEntity ); - DECLARE_SERVERCLASS(); - - SmokeTrail(); - virtual bool KeyValue( const char *szKeyName, const char *szValue ); - void SetEmit(bool bVal); - void FollowEntity( CBaseEntity *pEntity, const char *pAttachmentName = NULL); - static SmokeTrail* CreateSmokeTrail(); - -public: - // Effect parameters. These will assume default values but you can change them. - CNetworkVector( m_StartColor ); // Fade between these colors. - CNetworkVector( m_EndColor ); - CNetworkVar( float, m_Opacity ); - - CNetworkVar( float, m_SpawnRate ); // How many particles per second. - CNetworkVar( float, m_ParticleLifetime ); // How long do the particles live? - CNetworkVar( float, m_StopEmitTime ); // When do I stop emitting particles? - CNetworkVar( float, m_MinSpeed ); // Speed range. - CNetworkVar( float, m_MaxSpeed ); - CNetworkVar( float, m_StartSize ); // Size ramp. - CNetworkVar( float, m_EndSize ); - CNetworkVar( float, m_SpawnRadius ); - CNetworkVar( float, m_MinDirectedSpeed ); // Speed range. - CNetworkVar( float, m_MaxDirectedSpeed ); - CNetworkVar( bool, m_bEmit ); - - CNetworkVar( int, m_nAttachment ); -}; - -//================================================== -// RocketTrail -//================================================== - -class RocketTrail : public CBaseParticleEntity -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( RocketTrail, CBaseParticleEntity ); - DECLARE_SERVERCLASS(); - - RocketTrail(); - void SetEmit(bool bVal); - void FollowEntity( CBaseEntity *pEntity, const char *pAttachmentName = NULL); - static RocketTrail *CreateRocketTrail(); - -public: - // Effect parameters. These will assume default values but you can change them. - CNetworkVector( m_StartColor ); // Fade between these colors. - CNetworkVector( m_EndColor ); - CNetworkVar( float, m_Opacity ); - - CNetworkVar( float, m_SpawnRate ); // How many particles per second. - CNetworkVar( float, m_ParticleLifetime ); // How long do the particles live? - CNetworkVar( float, m_StopEmitTime ); // When do I stop emitting particles? - CNetworkVar( float, m_MinSpeed ); // Speed range. - CNetworkVar( float, m_MaxSpeed ); - CNetworkVar( float, m_StartSize ); // Size ramp. - CNetworkVar( float, m_EndSize ); - CNetworkVar( float, m_SpawnRadius ); - - CNetworkVar( bool, m_bEmit ); - - CNetworkVar( int, m_nAttachment ); - - CNetworkVar( bool, m_bDamaged ); - - CNetworkVar( float, m_flFlareScale ); // Size of the flare -}; - -//================================================== -// SporeTrail -//================================================== - -class SporeTrail : public CBaseParticleEntity -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( SporeTrail, CBaseParticleEntity ); - DECLARE_SERVERCLASS(); - - SporeTrail( void ); - - static SporeTrail* CreateSporeTrail(); - -//Data members -public: - - CNetworkVector( m_vecEndColor ); - - CNetworkVar( float, m_flSpawnRate ); - CNetworkVar( float, m_flParticleLifetime ); - CNetworkVar( float, m_flStartSize ); - CNetworkVar( float, m_flEndSize ); - CNetworkVar( float, m_flSpawnRadius ); - - CNetworkVar( bool, m_bEmit ); -}; - -//================================================== -// SporeExplosion -//================================================== - -class SporeExplosion : public CBaseParticleEntity -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( SporeExplosion, CBaseParticleEntity ); - DECLARE_SERVERCLASS(); - - SporeExplosion( void ); - void Spawn( void ); - - static SporeExplosion* CreateSporeExplosion(); - - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - -//Data members -public: - - bool m_bDisabled; - - CNetworkVar( float, m_flSpawnRate ); - CNetworkVar( float, m_flParticleLifetime ); - CNetworkVar( float, m_flStartSize ); - CNetworkVar( float, m_flEndSize ); - CNetworkVar( float, m_flSpawnRadius ); - - CNetworkVar( bool, m_bEmit ); - CNetworkVar( bool, m_bDontRemove ); -}; - -//================================================== -// CFireTrail -//================================================== - -class CFireTrail : public CBaseParticleEntity -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( CFireTrail, CBaseParticleEntity ); - DECLARE_SERVERCLASS(); - - static CFireTrail *CreateFireTrail( void ); - void FollowEntity( CBaseEntity *pEntity, const char *pAttachmentName ); - void Precache( void ); - - CNetworkVar( int, m_nAttachment ); - CNetworkVar( float, m_flLifetime ); -}; - -//================================================== -// DustTrail -//================================================== - -class DustTrail : public CBaseParticleEntity -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( DustTrail, CBaseParticleEntity ); - DECLARE_SERVERCLASS(); - - DustTrail(); - virtual bool KeyValue( const char *szKeyName, const char *szValue ); - void SetEmit(bool bVal); - static DustTrail* CreateDustTrail(); - -public: - // Effect parameters. These will assume default values but you can change them. - CNetworkVector( m_Color ); - CNetworkVar( float, m_Opacity ); - - CNetworkVar( float, m_SpawnRate ); // How many particles per second. - CNetworkVar( float, m_ParticleLifetime ); // How long do the particles live? - CNetworkVar( float, m_StopEmitTime ); // When do I stop emitting particles? - CNetworkVar( float, m_MinSpeed ); // Speed range. - CNetworkVar( float, m_MaxSpeed ); - CNetworkVar( float, m_StartSize ); // Size ramp. - CNetworkVar( float, m_EndSize ); - CNetworkVar( float, m_SpawnRadius ); - CNetworkVar( float, m_MinDirectedSpeed ); // Speed range. - CNetworkVar( float, m_MaxDirectedSpeed ); - CNetworkVar( bool, m_bEmit ); - - CNetworkVar( int, m_nAttachment ); -}; - - -#endif diff --git a/game/server/smokestack.cpp b/game/server/smokestack.cpp deleted file mode 100644 index 9dbbdc658..000000000 --- a/game/server/smokestack.cpp +++ /dev/null @@ -1,276 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements the server side of a steam jet particle system entity. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "smokestack.h" -#include "particle_light.h" -#include "filesystem.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -//Networking -IMPLEMENT_SERVERCLASS_ST(CSmokeStack, DT_SmokeStack) - SendPropFloat(SENDINFO(m_SpreadSpeed), 0, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_Speed), 0, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_StartSize), 0, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_EndSize), 0, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_Rate), 0, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_JetLength), 0, SPROP_NOSCALE), - SendPropInt(SENDINFO(m_bEmit), 1, SPROP_UNSIGNED), - SendPropFloat(SENDINFO(m_flBaseSpread), 0, SPROP_NOSCALE), - SendPropFloat(SENDINFO( m_flRollSpeed ), 0, SPROP_NOSCALE ), - - // Note: the base color is specified in the smokestack entity, but the directional - // and ambient light must come from env_particlelight entities. - SendPropVector( SENDINFO_NOCHECK(m_DirLight.m_vPos), 0, SPROP_NOSCALE ), - SendPropVector( SENDINFO_NOCHECK(m_DirLight.m_vColor), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO_NOCHECK(m_DirLight.m_flIntensity), 0, SPROP_NOSCALE ), - - SendPropVector( SENDINFO_NOCHECK(m_AmbientLight.m_vPos), 0, SPROP_NOSCALE ), - SendPropVector( SENDINFO_NOCHECK(m_AmbientLight.m_vColor), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO_NOCHECK(m_AmbientLight.m_flIntensity), 0, SPROP_NOSCALE ), - - SendPropVector(SENDINFO(m_vWind), 0, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_flTwist), 0, SPROP_NOSCALE), - SendPropIntWithMinusOneFlag( SENDINFO(m_iMaterialModel), 16 ) - -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( env_smokestack, CSmokeStack ); - - -//Save/restore - -BEGIN_SIMPLE_DATADESC( CSmokeStackLightInfo ) - DEFINE_FIELD( m_vPos, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vColor, FIELD_VECTOR ), - DEFINE_FIELD( m_flIntensity, FIELD_FLOAT ), -END_DATADESC() - -BEGIN_DATADESC( CSmokeStack ) - - //Keyvalue fields - DEFINE_KEYFIELD( m_StartSize, FIELD_FLOAT, "StartSize" ), - DEFINE_KEYFIELD( m_EndSize, FIELD_FLOAT, "EndSize" ), - DEFINE_KEYFIELD( m_InitialState, FIELD_BOOLEAN, "InitialState" ), - DEFINE_KEYFIELD( m_flBaseSpread, FIELD_FLOAT, "BaseSpread" ), - DEFINE_KEYFIELD( m_flTwist, FIELD_FLOAT, "Twist" ), - DEFINE_KEYFIELD( m_flRollSpeed, FIELD_FLOAT, "Roll" ), - - DEFINE_FIELD( m_strMaterialModel, FIELD_STRING ), - DEFINE_FIELD( m_iMaterialModel,FIELD_INTEGER ), - - DEFINE_EMBEDDED( m_AmbientLight ), - DEFINE_EMBEDDED( m_DirLight ), - - DEFINE_KEYFIELD( m_WindAngle, FIELD_INTEGER, "WindAngle" ), - DEFINE_KEYFIELD( m_WindSpeed, FIELD_INTEGER, "WindSpeed" ), - - //Regular fields - DEFINE_FIELD( m_vWind, FIELD_VECTOR ), - DEFINE_FIELD( m_bEmit, FIELD_INTEGER ), - - // Inputs - DEFINE_INPUT( m_JetLength, FIELD_FLOAT, "JetLength" ), - DEFINE_INPUT( m_SpreadSpeed, FIELD_FLOAT, "SpreadSpeed" ), - DEFINE_INPUT( m_Speed, FIELD_FLOAT, "Speed" ), - DEFINE_INPUT( m_Rate, FIELD_FLOAT, "Rate" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Purpose: Called before spawning, after key values have been set. -//----------------------------------------------------------------------------- -CSmokeStack::CSmokeStack() -{ - memset( &m_AmbientLight, 0, sizeof(m_AmbientLight) ); - memset( &m_DirLight, 0, sizeof(m_DirLight) ); - - IMPLEMENT_NETWORKVAR_CHAIN( &m_AmbientLight ); - IMPLEMENT_NETWORKVAR_CHAIN( &m_DirLight ); - - m_flTwist = 0; - SetRenderColor( 0, 0, 0, 255 ); - m_vWind.GetForModify().Init(); - m_WindAngle = m_WindSpeed = 0; - m_iMaterialModel = -1; - m_flRollSpeed = 0.0f; -} - - -CSmokeStack::~CSmokeStack() -{ -} - - -void CSmokeStack::Spawn( void ) -{ - if ( m_InitialState ) - { - m_bEmit = true; - } -} - - -void CSmokeStack::Activate() -{ - DetectInSkybox(); - - bool bGotDirLight = false; - - // Find local lights. - CBaseEntity *pTestEnt = NULL; - while ( 1 ) - { - pTestEnt = gEntList.FindEntityByClassname( pTestEnt, PARTICLELIGHT_ENTNAME ); - if ( !pTestEnt ) - break; - - CParticleLight *pLight = (CParticleLight*)pTestEnt; - if( !FStrEq( STRING(GetEntityName()), STRING(pLight->m_PSName) ) ) - continue; - - CSmokeStackLightInfo *pInfo = &m_AmbientLight; - if ( pLight->m_bDirectional ) - { - bGotDirLight = true; - pInfo = &m_DirLight; - } - - pInfo->m_flIntensity = pLight->m_flIntensity; - pInfo->m_vColor = pLight->m_vColor; - pInfo->m_vPos = pLight->GetAbsOrigin(); - } - - // Put our light colors in 0-1 space. - m_AmbientLight.m_vColor.GetForModify() /= 255.0f; - m_DirLight.m_vColor.GetForModify() /= 255.0f; - - BaseClass::Activate(); - - // Legacy support.. - if ( m_iMaterialModel == -1 ) - m_iMaterialModel = PrecacheModel( "particle/SmokeStack.vmt" ); -} - - -bool CSmokeStack::KeyValue( const char *szKeyName, const char *szValue ) -{ - if( stricmp( szKeyName, "Wind" ) == 0 ) - { - sscanf( szValue, "%f %f %f", &m_vWind.GetForModify().x, &m_vWind.GetForModify().y, &m_vWind.GetForModify().z ); - return true; - } - else if( stricmp( szKeyName, "WindAngle" ) == 0 ) - { - m_WindAngle = atoi( szValue ); - RecalcWindVector(); - return true; - } - else if( stricmp( szKeyName, "WindSpeed" ) == 0 ) - { - m_WindSpeed = atoi( szValue ); - RecalcWindVector(); - return true; - } - else if ( stricmp( szKeyName, "SmokeMaterial" ) == 0 ) - { - // Make sure we have a vmt extension. - if ( Q_stristr( szValue, ".vmt" ) ) - { - m_strMaterialModel = AllocPooledString( szValue ); - } - else - { - char str[512]; - Q_snprintf( str, sizeof( str ), "%s.vmt", szValue ); - m_strMaterialModel = AllocPooledString( str ); - } - - const char *pName = STRING( m_strMaterialModel ); - char szStrippedName[512]; - - m_iMaterialModel = PrecacheModel( pName ); - Q_StripExtension( pName, szStrippedName, Q_strlen(pName)+1 ); - - int iLength = Q_strlen( szStrippedName ); - szStrippedName[iLength-1] = '\0'; - - int iCount = 1; - char str[512]; - Q_snprintf( str, sizeof( str ), "%s%d.vmt", szStrippedName, iCount ); - - while ( filesystem->FileExists( UTIL_VarArgs( "materials/%s", str ) ) ) - { - PrecacheModel( str ); - iCount++; - - Q_snprintf( str, sizeof( str ), "%s%d.vmt", szStrippedName, iCount ); - } - - return true; - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } -} - - -void CSmokeStack::Precache() -{ - m_iMaterialModel = PrecacheModel( STRING( m_strMaterialModel ) ); - - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for toggling the steam jet on/off. -//----------------------------------------------------------------------------- -void CSmokeStack::InputToggle( inputdata_t &inputdata ) -{ - m_bEmit = !m_bEmit; -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for turning on the steam jet. -//----------------------------------------------------------------------------- -void CSmokeStack::InputTurnOn( inputdata_t &inputdata ) -{ - m_bEmit = true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for turning off the steam jet. -//----------------------------------------------------------------------------- -void CSmokeStack::InputTurnOff( inputdata_t &inputdata ) -{ - m_bEmit = false; -} - - -void CSmokeStack::RecalcWindVector() -{ - m_vWind = Vector( - cos( DEG2RAD( (float)m_WindAngle ) ) * m_WindSpeed, - sin( DEG2RAD( (float)m_WindAngle ) ) * m_WindSpeed, - 0 ); - -} - - diff --git a/game/server/smokestack.h b/game/server/smokestack.h deleted file mode 100644 index db1da05d1..000000000 --- a/game/server/smokestack.h +++ /dev/null @@ -1,85 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Defines the server side of a steam jet particle system entity. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SMOKESTACK_H -#define SMOKESTACK_H -#pragma once - -#include "baseparticleentity.h" - -//================================================== -// CSmokeStack -//================================================== - -class CSmokeStackLightInfo -{ -public: - DECLARE_CLASS_NOBASE( CSmokeStackLightInfo ); - DECLARE_SIMPLE_DATADESC(); - DECLARE_NETWORKVAR_CHAIN(); - - CNetworkVector( m_vPos ); - CNetworkVector( m_vColor ); - CNetworkVar( float, m_flIntensity ); -}; - -class CSmokeStack : public CBaseParticleEntity -{ -public: - DECLARE_CLASS( CSmokeStack, CBaseParticleEntity ); - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - CSmokeStack(); - ~CSmokeStack(); - - virtual void Spawn( void ); - virtual void Activate(); - virtual bool KeyValue( const char *szKeyName, const char *szValue ); - virtual void Precache(); - - -protected: - - // Input handlers. - void InputTurnOn(inputdata_t &data); - void InputTurnOff(inputdata_t &data); - void InputToggle(inputdata_t &data); - - void RecalcWindVector(); - - -// Stuff from the datatable. -public: - CNetworkVar( float, m_SpreadSpeed ); - CNetworkVar( float, m_Speed ); - CNetworkVar( float, m_StartSize ); - CNetworkVar( float, m_EndSize ); - CNetworkVar( float, m_Rate ); - CNetworkVar( float, m_JetLength ); // Length of the jet. Lifetime is derived from this. - CNetworkVar( float, m_flRollSpeed ); - - CNetworkVar( int, m_bEmit ); // Emit particles? - CNetworkVar( float, m_flBaseSpread ); - - CSmokeStackLightInfo m_AmbientLight; - CSmokeStackLightInfo m_DirLight; - - CNetworkVar( float, m_flTwist ); - - string_t m_strMaterialModel; - CNetworkVar( int, m_iMaterialModel ); - - int m_WindAngle; - int m_WindSpeed; - CNetworkVector( m_vWind ); // m_vWind is just calculated from m_WindAngle and m_WindSpeed. - - bool m_InitialState; -}; - -#endif // SMOKESTACK_H - diff --git a/game/server/sound.cpp b/game/server/sound.cpp deleted file mode 100644 index fbecf7da9..000000000 --- a/game/server/sound.cpp +++ /dev/null @@ -1,1440 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Entities relating to in-level sound effects. -// -// ambient_generic: a sound emitter used for one-shot and looping sounds. -// -// env_speaker: used for public address announcements over loudspeakers. -// This tries not to drown out talking NPCs. -// -// env_soundscape: controls what sound script an area uses. -// -//=============================================================================// - -#include "cbase.h" -#include "player.h" -#include "mathlib/mathlib.h" -#include "ai_speech.h" -#include "stringregistry.h" -#include "gamerules.h" -#include "game.h" -#include -#include "entitylist.h" -#include "vstdlib/random.h" -#include "engine/IEngineSound.h" -#include "ndebugoverlay.h" -#include "soundscape.h" -#include "igamesystem.h" -#include "KeyValues.h" -#include "filesystem.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Compute a suitable attenuation value given an audible radius -// Input : radius - -// playEverywhere - (disable attenuation) -//----------------------------------------------------------------------------- -#define REFERENCE_dB 60.0 - -#define AMBIENT_GENERIC_UPDATE_RATE 5 // update at 5hz -#define AMBIENT_GENERIC_THINK_DELAY ( 1.0f / float( AMBIENT_GENERIC_UPDATE_RATE ) ) - -#ifdef HL1_DLL -ConVar hl1_ref_db_distance( "hl1_ref_db_distance", "18.0" ); -#define REFERENCE_dB_DISTANCE hl1_ref_db_distance.GetFloat() -#else -#define REFERENCE_dB_DISTANCE 36.0 -#endif//HL1_DLL - -static soundlevel_t ComputeSoundlevel( float radius, bool playEverywhere ) -{ - soundlevel_t soundlevel = SNDLVL_NONE; - - if ( radius > 0 && !playEverywhere ) - { - // attenuation is set to a distance, compute falloff - - float dB_loss = 20 * log10( radius / REFERENCE_dB_DISTANCE ); - - soundlevel = (soundlevel_t)(int)(40 + dB_loss); // sound at 40dB at reference distance - } - - return soundlevel; -} - -// ==================== GENERIC AMBIENT SOUND ====================================== - -// runtime pitch shift and volume fadein/out structure - -// NOTE: IF YOU CHANGE THIS STRUCT YOU MUST CHANGE THE SAVE/RESTORE VERSION NUMBER -// SEE BELOW (in the typedescription for the class) -typedef struct dynpitchvol -{ - // NOTE: do not change the order of these parameters - // NOTE: unless you also change order of rgdpvpreset array elements! - int preset; - - int pitchrun; // pitch shift % when sound is running 0 - 255 - int pitchstart; // pitch shift % when sound stops or starts 0 - 255 - int spinup; // spinup time 0 - 100 - int spindown; // spindown time 0 - 100 - - int volrun; // volume change % when sound is running 0 - 10 - int volstart; // volume change % when sound stops or starts 0 - 10 - int fadein; // volume fade in time 0 - 100 - int fadeout; // volume fade out time 0 - 100 - - // Low Frequency Oscillator - int lfotype; // 0) off 1) square 2) triangle 3) random - int lforate; // 0 - 1000, how fast lfo osciallates - - int lfomodpitch; // 0-100 mod of current pitch. 0 is off. - int lfomodvol; // 0-100 mod of current volume. 0 is off. - - int cspinup; // each trigger hit increments counter and spinup pitch - - - int cspincount; - - int pitch; - int spinupsav; - int spindownsav; - int pitchfrac; - - int vol; - int fadeinsav; - int fadeoutsav; - int volfrac; - - int lfofrac; - int lfomult; - - -} dynpitchvol_t; - -#define CDPVPRESETMAX 27 - -// presets for runtime pitch and vol modulation of ambient sounds - -dynpitchvol_t rgdpvpreset[CDPVPRESETMAX] = -{ -// pitch pstart spinup spindwn volrun volstrt fadein fadeout lfotype lforate modptch modvol cspnup -{1, 255, 75, 95, 95, 10, 1, 50, 95, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0}, -{2, 255, 85, 70, 88, 10, 1, 20, 88, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0}, -{3, 255, 100, 50, 75, 10, 1, 10, 75, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0}, -{4, 100, 100, 0, 0, 10, 1, 90, 90, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0}, -{5, 100, 100, 0, 0, 10, 1, 80, 80, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0}, -{6, 100, 100, 0, 0, 10, 1, 50, 70, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0}, -{7, 100, 100, 0, 0, 5, 1, 40, 50, 1, 50, 0, 10, 0, 0,0,0,0,0,0,0,0,0,0}, -{8, 100, 100, 0, 0, 5, 1, 40, 50, 1, 150, 0, 10, 0, 0,0,0,0,0,0,0,0,0,0}, -{9, 100, 100, 0, 0, 5, 1, 40, 50, 1, 750, 0, 10, 0, 0,0,0,0,0,0,0,0,0,0}, -{10,128, 100, 50, 75, 10, 1, 30, 40, 2, 8, 20, 0, 0, 0,0,0,0,0,0,0,0,0,0}, -{11,128, 100, 50, 75, 10, 1, 30, 40, 2, 25, 20, 0, 0, 0,0,0,0,0,0,0,0,0,0}, -{12,128, 100, 50, 75, 10, 1, 30, 40, 2, 70, 20, 0, 0, 0,0,0,0,0,0,0,0,0,0}, -{13,50, 50, 0, 0, 10, 1, 20, 50, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0}, -{14,70, 70, 0, 0, 10, 1, 20, 50, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0}, -{15,90, 90, 0, 0, 10, 1, 20, 50, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0}, -{16,120, 120, 0, 0, 10, 1, 20, 50, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0}, -{17,180, 180, 0, 0, 10, 1, 20, 50, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0}, -{18,255, 255, 0, 0, 10, 1, 20, 50, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0}, -{19,200, 75, 90, 90, 10, 1, 50, 90, 2, 100, 20, 0, 0, 0,0,0,0,0,0,0,0,0,0}, -{20,255, 75, 97, 90, 10, 1, 50, 90, 1, 40, 50, 0, 0, 0,0,0,0,0,0,0,0,0,0}, -{21,100, 100, 0, 0, 10, 1, 30, 50, 3, 15, 20, 0, 0, 0,0,0,0,0,0,0,0,0,0}, -{22,160, 160, 0, 0, 10, 1, 50, 50, 3, 500, 25, 0, 0, 0,0,0,0,0,0,0,0,0,0}, -{23,255, 75, 88, 0, 10, 1, 40, 0, 0, 0, 0, 0, 5, 0,0,0,0,0,0,0,0,0,0}, -{24,200, 20, 95, 70, 10, 1, 70, 70, 3, 20, 50, 0, 0, 0,0,0,0,0,0,0,0,0,0}, -{25,180, 100, 50, 60, 10, 1, 40, 60, 2, 90, 100, 100, 0, 0,0,0,0,0,0,0,0,0,0}, -{26,60, 60, 0, 0, 10, 1, 40, 70, 3, 80, 20, 50, 0, 0,0,0,0,0,0,0,0,0,0}, -{27,128, 90, 10, 10, 10, 1, 20, 40, 1, 5, 10, 20, 0, 0,0,0,0,0,0,0,0,0,0} -}; - -class CAmbientGeneric : public CPointEntity -{ -public: - DECLARE_CLASS( CAmbientGeneric, CPointEntity ); - - bool KeyValue( const char *szKeyName, const char *szValue ); - void Spawn( void ); - void Precache( void ); - void Activate( void ); - void RampThink( void ); - void InitModulationParms(void); - void ComputeMaxAudibleDistance( ); - - // Rules about which entities need to transmit along with me - virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ); - virtual void UpdateOnRemove( void ); - - void ToggleSound(); - void SendSound( SoundFlags_t flags ); - - // Input handlers - void InputPlaySound( inputdata_t &inputdata ); - void InputStopSound( inputdata_t &inputdata ); - void InputToggleSound( inputdata_t &inputdata ); - void InputPitch( inputdata_t &inputdata ); - void InputVolume( inputdata_t &inputdata ); - void InputFadeIn( inputdata_t &inputdata ); - void InputFadeOut( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - - float m_radius; - float m_flMaxRadius; - soundlevel_t m_iSoundLevel; // dB value - dynpitchvol_t m_dpv; - - bool m_fActive; // only true when the entity is playing a looping sound - bool m_fLooping; // true when the sound played will loop - - string_t m_iszSound; // Path/filename of WAV file to play. - string_t m_sSourceEntName; - EHANDLE m_hSoundSource; // entity from which the sound comes - int m_nSoundSourceEntIndex; // In case the entity goes away before we finish stopping the sound... -}; - -LINK_ENTITY_TO_CLASS( ambient_generic, CAmbientGeneric ); - -BEGIN_DATADESC( CAmbientGeneric ) - - DEFINE_KEYFIELD( m_iszSound, FIELD_SOUNDNAME, "message" ), - DEFINE_KEYFIELD( m_radius, FIELD_FLOAT, "radius" ), - DEFINE_KEYFIELD( m_sSourceEntName, FIELD_STRING, "SourceEntityName" ), - // recomputed in Activate() - // DEFINE_FIELD( m_hSoundSource, EHANDLE ), - // DEFINE_FIELD( m_nSoundSourceEntIndex, FIELD_INTERGER ), - - DEFINE_FIELD( m_flMaxRadius, FIELD_FLOAT ), - DEFINE_FIELD( m_fActive, FIELD_BOOLEAN ), - DEFINE_FIELD( m_fLooping, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iSoundLevel, FIELD_INTEGER ), - - // HACKHACK - This is not really in the spirit of the save/restore design, but save this - // out as a binary data block. If the dynpitchvol_t is changed, old saved games will NOT - // load these correctly, so bump the save/restore version if you change the size of the struct - // The right way to do this is to split the input parms (read in keyvalue) into members and re-init this - // struct in Precache(), but it's unlikely that the struct will change, so it's not worth the time right now. - DEFINE_ARRAY( m_dpv, FIELD_CHARACTER, sizeof(dynpitchvol_t) ), - - // Function Pointers - DEFINE_FUNCTION( RampThink ), - - // Inputs - DEFINE_INPUTFUNC(FIELD_VOID, "PlaySound", InputPlaySound ), - DEFINE_INPUTFUNC(FIELD_VOID, "StopSound", InputStopSound ), - DEFINE_INPUTFUNC(FIELD_VOID, "ToggleSound", InputToggleSound ), - DEFINE_INPUTFUNC(FIELD_FLOAT, "Pitch", InputPitch ), - DEFINE_INPUTFUNC(FIELD_FLOAT, "Volume", InputVolume ), - DEFINE_INPUTFUNC(FIELD_FLOAT, "FadeIn", InputFadeIn ), - DEFINE_INPUTFUNC(FIELD_FLOAT, "FadeOut", InputFadeOut ), - -END_DATADESC() - - -#define SF_AMBIENT_SOUND_EVERYWHERE 1 -#define SF_AMBIENT_SOUND_START_SILENT 16 -#define SF_AMBIENT_SOUND_NOT_LOOPING 32 - - -//----------------------------------------------------------------------------- -// Spawn -//----------------------------------------------------------------------------- -void CAmbientGeneric::Spawn( void ) -{ - m_iSoundLevel = ComputeSoundlevel( m_radius, FBitSet( m_spawnflags, SF_AMBIENT_SOUND_EVERYWHERE )?true:false ); - ComputeMaxAudibleDistance( ); - - char *szSoundFile = (char *)STRING( m_iszSound ); - if ( !m_iszSound || strlen( szSoundFile ) < 1 ) - { - Warning( "Empty %s (%s) at %.2f, %.2f, %.2f\n", GetClassname(), GetDebugName(), GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z ); - UTIL_Remove(this); - return; - } - - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NONE ); - - // Set up think function for dynamic modification - // of ambient sound's pitch or volume. Don't - // start thinking yet. - - SetThink(&CAmbientGeneric::RampThink); - SetNextThink( TICK_NEVER_THINK ); - - m_fActive = false; - - if ( FBitSet ( m_spawnflags, SF_AMBIENT_SOUND_NOT_LOOPING ) ) - { - m_fLooping = false; - } - else - { - m_fLooping = true; - } - - m_hSoundSource = NULL; - m_nSoundSourceEntIndex = -1; - - Precache( ); - - // init all dynamic modulation parms - InitModulationParms(); -} - - -//----------------------------------------------------------------------------- -// Computes the max audible radius for a given sound level -//----------------------------------------------------------------------------- -#define MIN_AUDIBLE_VOLUME 1.01e-3 - -void CAmbientGeneric::ComputeMaxAudibleDistance( ) -{ - if (( m_iSoundLevel == SNDLVL_NONE ) || ( m_radius == 0.0f )) - { - m_flMaxRadius = -1.0f; - return; - } - - // Sadly, there's no direct way of getting at this. - // We have to do an interative computation. - float flGain = enginesound->GetDistGainFromSoundLevel( m_iSoundLevel, m_radius ); - if ( flGain <= MIN_AUDIBLE_VOLUME ) - { - m_flMaxRadius = m_radius; - return; - } - - float flMinRadius = m_radius; - float flMaxRadius = m_radius * 2; - while ( true ) - { - // First, find a min + max range surrounding the desired distance gain - float flGain = enginesound->GetDistGainFromSoundLevel( m_iSoundLevel, flMaxRadius ); - if ( flGain <= MIN_AUDIBLE_VOLUME ) - break; - - // Always audible. - if ( flMaxRadius > 1e5 ) - { - m_flMaxRadius = -1.0f; - return; - } - - flMinRadius = flMaxRadius; - flMaxRadius *= 2.0f; - } - - // Now home in a little bit - int nInterations = 4; - while ( --nInterations >= 0 ) - { - float flTestRadius = (flMinRadius + flMaxRadius) * 0.5f; - float flGain = enginesound->GetDistGainFromSoundLevel( m_iSoundLevel, flTestRadius ); - if ( flGain <= MIN_AUDIBLE_VOLUME ) - { - flMaxRadius = flTestRadius; - } - else - { - flMinRadius = flTestRadius; - } - } - - m_flMaxRadius = flMaxRadius; -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for changing pitch. -// Input : Float new pitch from 0 - 255 (100 = as recorded). -//----------------------------------------------------------------------------- -void CAmbientGeneric::InputPitch( inputdata_t &inputdata ) -{ - m_dpv.pitch = (int)clamp( inputdata.value.Float(), 0, 255 ); - - SendSound( SND_CHANGE_PITCH ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for changing volume. -// Input : Float new volume, from 0 - 10. -//----------------------------------------------------------------------------- -void CAmbientGeneric::InputVolume( inputdata_t &inputdata ) -{ - // - // Multiply the input value by ten since volumes are expected to be from 0 - 100. - // - m_dpv.vol = (int)clamp( inputdata.value.Float(), 0, 10 ) * 10; - m_dpv.volfrac = m_dpv.vol << 8; - - SendSound( SND_CHANGE_VOL ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for fading in volume over time. -// Input : Float volume fade in time 0 - 100 seconds -//----------------------------------------------------------------------------- -void CAmbientGeneric::InputFadeIn( inputdata_t &inputdata ) -{ - // cancel any fade out that might be happening - m_dpv.fadeout = 0; - - m_dpv.fadein = inputdata.value.Int(); - if (m_dpv.fadein > 100) m_dpv.fadein = 100; - if (m_dpv.fadein < 0) m_dpv.fadein = 0; - - if (m_dpv.fadein > 0) - m_dpv.fadein = ( 100 << 8 ) / ( m_dpv.fadein * AMBIENT_GENERIC_UPDATE_RATE ); - - SetNextThink( gpGlobals->curtime + 0.1f ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for fading out volume over time. -// Input : Float volume fade out time 0 - 100 seconds -//----------------------------------------------------------------------------- -void CAmbientGeneric::InputFadeOut( inputdata_t &inputdata ) -{ - // cancel any fade in that might be happening - m_dpv.fadein = 0; - - m_dpv.fadeout = inputdata.value.Int(); - - if (m_dpv.fadeout > 100) m_dpv.fadeout = 100; - if (m_dpv.fadeout < 0) m_dpv.fadeout = 0; - - if (m_dpv.fadeout > 0) - m_dpv.fadeout = ( 100 << 8 ) / ( m_dpv.fadeout * AMBIENT_GENERIC_UPDATE_RATE ); - - SetNextThink( gpGlobals->curtime + 0.1f ); -} - - -void CAmbientGeneric::Precache( void ) -{ - char *szSoundFile = (char *)STRING( m_iszSound ); - if ( m_iszSound != NULL_STRING && strlen( szSoundFile ) > 1 ) - { - if (*szSoundFile != '!') - { - PrecacheScriptSound(szSoundFile); - } - } - - if ( !FBitSet (m_spawnflags, SF_AMBIENT_SOUND_START_SILENT ) ) - { - // start the sound ASAP - if (m_fLooping) - m_fActive = true; - } -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CAmbientGeneric::Activate( void ) -{ - BaseClass::Activate(); - - // Initialize sound source. If no source was given, or source can't be found - // then this is the source - if (m_hSoundSource == NULL) - { - if (m_sSourceEntName != NULL_STRING) - { - m_hSoundSource = gEntList.FindEntityByName( NULL, m_sSourceEntName ); - if ( m_hSoundSource != NULL ) - { - m_nSoundSourceEntIndex = m_hSoundSource->entindex(); - } - } - - if (m_hSoundSource == NULL) - { - m_hSoundSource = this; - m_nSoundSourceEntIndex = entindex(); - } - else - { - if ( !FBitSet( m_spawnflags, SF_AMBIENT_SOUND_EVERYWHERE ) ) - { - AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); - } - } - } - - // If active start the sound - if ( m_fActive ) - { - int flags = SND_SPAWNING; - // If we are loading a saved game, we can't write into the init/signon buffer here, so just issue - // as a regular sound message... - if ( gpGlobals->eLoadType == MapLoad_Transition || - gpGlobals->eLoadType == MapLoad_LoadGame || - g_pGameRules->InRoundRestart() ) - { - flags = SND_NOFLAGS; - } - - // Tracker 76119: 8/12/07 ywb: - // Make sure pitch and volume are set up to the correct value (especially after restoring a .sav file) - flags |= ( SND_CHANGE_PITCH | SND_CHANGE_VOL ); - - // Don't bother sending over to client if volume is zero, though - if ( m_dpv.vol > 0 ) - { - SendSound( (SoundFlags_t)flags ); - } - - SetNextThink( gpGlobals->curtime + 0.1f ); - } -} - - -//----------------------------------------------------------------------------- -// Rules about which entities need to transmit along with me -//----------------------------------------------------------------------------- -void CAmbientGeneric::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ) -{ - // Ambient generics never transmit; this is just a way for us to ensure - // the sound source gets transmitted; that's why we don't call pInfo->m_pTransmitEdict->Set - if ( !m_hSoundSource || m_hSoundSource == this || !m_fActive ) - return; - - // Don't bother sending the position of the source if we have to play everywhere - if ( FBitSet( m_spawnflags, SF_AMBIENT_SOUND_EVERYWHERE ) ) - return; - - Assert( pInfo->m_pClientEnt ); - CBaseEntity *pClient = (CBaseEntity*)(pInfo->m_pClientEnt->GetUnknown()); - if ( !pClient ) - return; - - // Send the sound source if he's close enough - if ( ( m_flMaxRadius < 0 ) || ( pClient->GetAbsOrigin().DistToSqr( m_hSoundSource->GetAbsOrigin() ) <= m_flMaxRadius * m_flMaxRadius ) ) - { - m_hSoundSource->SetTransmit( pInfo, false ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAmbientGeneric::UpdateOnRemove( void ) -{ - if ( m_fActive ) - { - // Stop the sound we're generating - SendSound( SND_STOP ); - } - - BaseClass::UpdateOnRemove(); -} - -//----------------------------------------------------------------------------- -// Purpose: Think at 5hz if we are dynamically modifying pitch or volume of the -// playing sound. This function will ramp pitch and/or volume up or -// down, modify pitch/volume with lfo if active. -//----------------------------------------------------------------------------- -void CAmbientGeneric::RampThink( void ) -{ - int pitch = m_dpv.pitch; - int vol = m_dpv.vol; - int flags = 0; - int fChanged = 0; // false if pitch and vol remain unchanged this round - int prev; - - if (!m_dpv.spinup && !m_dpv.spindown && !m_dpv.fadein && !m_dpv.fadeout && !m_dpv.lfotype) - return; // no ramps or lfo, stop thinking - - // ============== - // pitch envelope - // ============== - if (m_dpv.spinup || m_dpv.spindown) - { - prev = m_dpv.pitchfrac >> 8; - - if (m_dpv.spinup > 0) - m_dpv.pitchfrac += m_dpv.spinup; - else if (m_dpv.spindown > 0) - m_dpv.pitchfrac -= m_dpv.spindown; - - pitch = m_dpv.pitchfrac >> 8; - - if (pitch > m_dpv.pitchrun) - { - pitch = m_dpv.pitchrun; - m_dpv.spinup = 0; // done with ramp up - } - - if (pitch < m_dpv.pitchstart) - { - pitch = m_dpv.pitchstart; - m_dpv.spindown = 0; // done with ramp down - - // shut sound off - SendSound( SND_STOP ); - - // return without setting m_flNextThink - return; - } - - if (pitch > 255) pitch = 255; - if (pitch < 1) pitch = 1; - - m_dpv.pitch = pitch; - - fChanged |= (prev != pitch); - flags |= SND_CHANGE_PITCH; - } - - // ================== - // amplitude envelope - // ================== - if (m_dpv.fadein || m_dpv.fadeout) - { - prev = m_dpv.volfrac >> 8; - - if (m_dpv.fadein > 0) - m_dpv.volfrac += m_dpv.fadein; - else if (m_dpv.fadeout > 0) - m_dpv.volfrac -= m_dpv.fadeout; - - vol = m_dpv.volfrac >> 8; - - if (vol > m_dpv.volrun) - { - vol = m_dpv.volrun; - m_dpv.volfrac = vol << 8; - m_dpv.fadein = 0; // done with ramp up - } - - if (vol < m_dpv.volstart) - { - vol = m_dpv.volstart; - m_dpv.vol = vol; - m_dpv.volfrac = vol << 8; - m_dpv.fadeout = 0; // done with ramp down - - // shut sound off - SendSound( SND_STOP ); - - // return without setting m_flNextThink - return; - } - - if (vol > 100) - { - vol = 100; - m_dpv.volfrac = vol << 8; - } - if (vol < 1) - { - vol = 1; - m_dpv.volfrac = vol << 8; - } - - m_dpv.vol = vol; - - fChanged |= (prev != vol); - flags |= SND_CHANGE_VOL; - } - - // =================== - // pitch/amplitude LFO - // =================== - if (m_dpv.lfotype) - { - int pos; - - if (m_dpv.lfofrac > 0x6fffffff) - m_dpv.lfofrac = 0; - - // update lfo, lfofrac/255 makes a triangle wave 0-255 - m_dpv.lfofrac += m_dpv.lforate; - pos = m_dpv.lfofrac >> 8; - - if (m_dpv.lfofrac < 0) - { - m_dpv.lfofrac = 0; - m_dpv.lforate = abs(m_dpv.lforate); - pos = 0; - } - else if (pos > 255) - { - pos = 255; - m_dpv.lfofrac = (255 << 8); - m_dpv.lforate = -abs(m_dpv.lforate); - } - - switch(m_dpv.lfotype) - { - case LFO_SQUARE: - if (pos < 128) - m_dpv.lfomult = 255; - else - m_dpv.lfomult = 0; - - break; - case LFO_RANDOM: - if (pos == 255) - m_dpv.lfomult = random->RandomInt(0, 255); - break; - case LFO_TRIANGLE: - default: - m_dpv.lfomult = pos; - break; - } - - if (m_dpv.lfomodpitch) - { - prev = pitch; - - // pitch 0-255 - pitch += ((m_dpv.lfomult - 128) * m_dpv.lfomodpitch) / 100; - - if (pitch > 255) pitch = 255; - if (pitch < 1) pitch = 1; - - - fChanged |= (prev != pitch); - flags |= SND_CHANGE_PITCH; - } - - if (m_dpv.lfomodvol) - { - // vol 0-100 - prev = vol; - - vol += ((m_dpv.lfomult - 128) * m_dpv.lfomodvol) / 100; - - if (vol > 100) vol = 100; - if (vol < 0) vol = 0; - - fChanged |= (prev != vol); - flags |= SND_CHANGE_VOL; - } - - } - - // Send update to playing sound only if we actually changed - // pitch or volume in this routine. - - if (flags && fChanged) - { - if (pitch == PITCH_NORM) - pitch = PITCH_NORM + 1; // don't send 'no pitch' ! - - CBaseEntity* pSoundSource = m_hSoundSource; - if (pSoundSource) - { - UTIL_EmitAmbientSound(pSoundSource->GetSoundSourceIndex(), pSoundSource->GetAbsOrigin(), - STRING( m_iszSound ), (vol * 0.01), m_iSoundLevel, flags, pitch); - } - } - - // update ramps at 5hz - SetNextThink( gpGlobals->curtime + AMBIENT_GENERIC_THINK_DELAY ); - return; -} - - -//----------------------------------------------------------------------------- -// Purpose: Init all ramp params in preparation to play a new sound. -//----------------------------------------------------------------------------- -void CAmbientGeneric::InitModulationParms(void) -{ - int pitchinc; - - m_dpv.volrun = m_iHealth * 10; // 0 - 100 - if (m_dpv.volrun > 100) m_dpv.volrun = 100; - if (m_dpv.volrun < 0) m_dpv.volrun = 0; - - // get presets - if (m_dpv.preset != 0 && m_dpv.preset <= CDPVPRESETMAX) - { - // load preset values - m_dpv = rgdpvpreset[m_dpv.preset - 1]; - - // fixup preset values, just like - // fixups in KeyValue routine. - if (m_dpv.spindown > 0) - m_dpv.spindown = (101 - m_dpv.spindown) * 64; - if (m_dpv.spinup > 0) - m_dpv.spinup = (101 - m_dpv.spinup) * 64; - - m_dpv.volstart *= 10; - m_dpv.volrun *= 10; - - if (m_dpv.fadein > 0) - m_dpv.fadein = (101 - m_dpv.fadein) * 64; - if (m_dpv.fadeout > 0) - m_dpv.fadeout = (101 - m_dpv.fadeout) * 64; - - m_dpv.lforate *= 256; - - m_dpv.fadeinsav = m_dpv.fadein; - m_dpv.fadeoutsav = m_dpv.fadeout; - m_dpv.spinupsav = m_dpv.spinup; - m_dpv.spindownsav = m_dpv.spindown; - } - - m_dpv.fadein = m_dpv.fadeinsav; - m_dpv.fadeout = 0; - - if (m_dpv.fadein) - m_dpv.vol = m_dpv.volstart; - else - m_dpv.vol = m_dpv.volrun; - - m_dpv.spinup = m_dpv.spinupsav; - m_dpv.spindown = 0; - - if (m_dpv.spinup) - m_dpv.pitch = m_dpv.pitchstart; - else - m_dpv.pitch = m_dpv.pitchrun; - - if (m_dpv.pitch == 0) - m_dpv.pitch = PITCH_NORM; - - m_dpv.pitchfrac = m_dpv.pitch << 8; - m_dpv.volfrac = m_dpv.vol << 8; - - m_dpv.lfofrac = 0; - m_dpv.lforate = abs(m_dpv.lforate); - - m_dpv.cspincount = 1; - - if (m_dpv.cspinup) - { - pitchinc = (255 - m_dpv.pitchstart) / m_dpv.cspinup; - - m_dpv.pitchrun = m_dpv.pitchstart + pitchinc; - if (m_dpv.pitchrun > 255) m_dpv.pitchrun = 255; - } - - if ((m_dpv.spinupsav || m_dpv.spindownsav || (m_dpv.lfotype && m_dpv.lfomodpitch)) - && (m_dpv.pitch == PITCH_NORM)) - m_dpv.pitch = PITCH_NORM + 1; // must never send 'no pitch' as first pitch - // if we intend to pitch shift later! -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that begins playing the sound. -//----------------------------------------------------------------------------- -void CAmbientGeneric::InputPlaySound( inputdata_t &inputdata ) -{ - if (!m_fActive) - { - //Adrian: Stop our current sound before starting a new one! - SendSound( SND_STOP ); - - ToggleSound(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that stops playing the sound. -//----------------------------------------------------------------------------- -void CAmbientGeneric::InputStopSound( inputdata_t &inputdata ) -{ - if (m_fActive) - { - ToggleSound(); - } -} - -void CAmbientGeneric::SendSound( SoundFlags_t flags) -{ - char *szSoundFile = (char *)STRING( m_iszSound ); - CBaseEntity* pSoundSource = m_hSoundSource; - if ( pSoundSource ) - { - if ( flags == SND_STOP ) - { - UTIL_EmitAmbientSound(pSoundSource->GetSoundSourceIndex(), pSoundSource->GetAbsOrigin(), szSoundFile, - 0, SNDLVL_NONE, flags, 0); - } - else - { - UTIL_EmitAmbientSound(pSoundSource->GetSoundSourceIndex(), pSoundSource->GetAbsOrigin(), szSoundFile, - (m_dpv.vol * 0.01), m_iSoundLevel, flags, m_dpv.pitch); - } - } - else - { - if ( ( flags == SND_STOP ) && - ( m_nSoundSourceEntIndex != -1 ) ) - { - UTIL_EmitAmbientSound(m_nSoundSourceEntIndex, GetAbsOrigin(), szSoundFile, - 0, SNDLVL_NONE, flags, 0); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that stops playing the sound. -//----------------------------------------------------------------------------- -void CAmbientGeneric::InputToggleSound( inputdata_t &inputdata ) -{ - ToggleSound(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Turns an ambient sound on or off. If the ambient is a looping sound, -// mark sound as active (m_fActive) if it's playing, innactive if not. -// If the sound is not a looping sound, never mark it as active. -// Input : pActivator - -// pCaller - -// useType - -// value - -//----------------------------------------------------------------------------- -void CAmbientGeneric::ToggleSound() -{ - // m_fActive is true only if a looping sound is playing. - - if ( m_fActive ) - {// turn sound off - - if (m_dpv.cspinup) - { - // Don't actually shut off. Each toggle causes - // incremental spinup to max pitch - - if (m_dpv.cspincount <= m_dpv.cspinup) - { - int pitchinc; - - // start a new spinup - m_dpv.cspincount++; - - pitchinc = (255 - m_dpv.pitchstart) / m_dpv.cspinup; - - m_dpv.spinup = m_dpv.spinupsav; - m_dpv.spindown = 0; - - m_dpv.pitchrun = m_dpv.pitchstart + pitchinc * m_dpv.cspincount; - if (m_dpv.pitchrun > 255) m_dpv.pitchrun = 255; - - SetNextThink( gpGlobals->curtime + 0.1f ); - } - - } - else - { - m_fActive = false; - - // HACKHACK - this makes the code in Precache() work properly after a save/restore - m_spawnflags |= SF_AMBIENT_SOUND_START_SILENT; - - if (m_dpv.spindownsav || m_dpv.fadeoutsav) - { - // spin it down (or fade it) before shutoff if spindown is set - m_dpv.spindown = m_dpv.spindownsav; - m_dpv.spinup = 0; - - m_dpv.fadeout = m_dpv.fadeoutsav; - m_dpv.fadein = 0; - SetNextThink( gpGlobals->curtime + 0.1f ); - } - else - { - SendSound( SND_STOP ); // stop sound - } - } - } - else - {// turn sound on - - // only toggle if this is a looping sound. If not looping, each - // trigger will cause the sound to play. If the sound is still - // playing from a previous trigger press, it will be shut off - // and then restarted. - - if (m_fLooping) - m_fActive = true; - else - { - // shut sound off now - may be interrupting a long non-looping sound - SendSound( SND_STOP ); // stop sound - } - - // init all ramp params for startup - - InitModulationParms(); - - SendSound( SND_NOFLAGS ); // send sound - - SetNextThink( gpGlobals->curtime + 0.1f ); - - } -} - - -// KeyValue - load keyvalue pairs into member data of the -// ambient generic. NOTE: called BEFORE spawn! -bool CAmbientGeneric::KeyValue( const char *szKeyName, const char *szValue ) -{ - // NOTE: changing any of the modifiers in this code - // NOTE: also requires changing InitModulationParms code. - - // preset - if (FStrEq(szKeyName, "preset")) - { - m_dpv.preset = atoi(szValue); - } - // pitchrun - else if (FStrEq(szKeyName, "pitch")) - { - m_dpv.pitchrun = atoi(szValue); - - if (m_dpv.pitchrun > 255) m_dpv.pitchrun = 255; - if (m_dpv.pitchrun < 0) m_dpv.pitchrun = 0; - } - // pitchstart - else if (FStrEq(szKeyName, "pitchstart")) - { - m_dpv.pitchstart = atoi(szValue); - - if (m_dpv.pitchstart > 255) m_dpv.pitchstart = 255; - if (m_dpv.pitchstart < 0) m_dpv.pitchstart = 0; - } - // spinup - else if (FStrEq(szKeyName, "spinup")) - { - m_dpv.spinup = atoi(szValue); - - if (m_dpv.spinup > 100) m_dpv.spinup = 100; - if (m_dpv.spinup < 0) m_dpv.spinup = 0; - - if (m_dpv.spinup > 0) - m_dpv.spinup = (101 - m_dpv.spinup) * 64; - m_dpv.spinupsav = m_dpv.spinup; - } - // spindown - else if (FStrEq(szKeyName, "spindown")) - { - m_dpv.spindown = atoi(szValue); - - if (m_dpv.spindown > 100) m_dpv.spindown = 100; - if (m_dpv.spindown < 0) m_dpv.spindown = 0; - - if (m_dpv.spindown > 0) - m_dpv.spindown = (101 - m_dpv.spindown) * 64; - m_dpv.spindownsav = m_dpv.spindown; - } - // volstart - else if (FStrEq(szKeyName, "volstart")) - { - m_dpv.volstart = atoi(szValue); - - if (m_dpv.volstart > 10) m_dpv.volstart = 10; - if (m_dpv.volstart < 0) m_dpv.volstart = 0; - - m_dpv.volstart *= 10; // 0 - 100 - } - // legacy fadein - else if (FStrEq(szKeyName, "fadein")) - { - m_dpv.fadein = atoi(szValue); - - if (m_dpv.fadein > 100) m_dpv.fadein = 100; - if (m_dpv.fadein < 0) m_dpv.fadein = 0; - - if (m_dpv.fadein > 0) - m_dpv.fadein = (101 - m_dpv.fadein) * 64; - m_dpv.fadeinsav = m_dpv.fadein; - } - // legacy fadeout - else if (FStrEq(szKeyName, "fadeout")) - { - m_dpv.fadeout = atoi(szValue); - - if (m_dpv.fadeout > 100) m_dpv.fadeout = 100; - if (m_dpv.fadeout < 0) m_dpv.fadeout = 0; - - if (m_dpv.fadeout > 0) - m_dpv.fadeout = (101 - m_dpv.fadeout) * 64; - m_dpv.fadeoutsav = m_dpv.fadeout; - } - // fadeinsecs - else if (FStrEq(szKeyName, "fadeinsecs")) - { - m_dpv.fadein = atoi(szValue); - - if (m_dpv.fadein > 100) m_dpv.fadein = 100; - if (m_dpv.fadein < 0) m_dpv.fadein = 0; - - if (m_dpv.fadein > 0) - m_dpv.fadein = ( 100 << 8 ) / ( m_dpv.fadein * AMBIENT_GENERIC_UPDATE_RATE ); - m_dpv.fadeinsav = m_dpv.fadein; - } - // fadeoutsecs - else if (FStrEq(szKeyName, "fadeoutsecs")) - { - m_dpv.fadeout = atoi(szValue); - - if (m_dpv.fadeout > 100) m_dpv.fadeout = 100; - if (m_dpv.fadeout < 0) m_dpv.fadeout = 0; - - if (m_dpv.fadeout > 0) - m_dpv.fadeout = ( 100 << 8 ) / ( m_dpv.fadeout * AMBIENT_GENERIC_UPDATE_RATE ); - m_dpv.fadeoutsav = m_dpv.fadeout; - } - // lfotype - else if (FStrEq(szKeyName, "lfotype")) - { - m_dpv.lfotype = atoi(szValue); - if (m_dpv.lfotype > 4) m_dpv.lfotype = LFO_TRIANGLE; - } - // lforate - else if (FStrEq(szKeyName, "lforate")) - { - m_dpv.lforate = atoi(szValue); - - if (m_dpv.lforate > 1000) m_dpv.lforate = 1000; - if (m_dpv.lforate < 0) m_dpv.lforate = 0; - - m_dpv.lforate *= 256; - } - // lfomodpitch - else if (FStrEq(szKeyName, "lfomodpitch")) - { - m_dpv.lfomodpitch = atoi(szValue); - if (m_dpv.lfomodpitch > 100) m_dpv.lfomodpitch = 100; - if (m_dpv.lfomodpitch < 0) m_dpv.lfomodpitch = 0; - } - - // lfomodvol - else if (FStrEq(szKeyName, "lfomodvol")) - { - m_dpv.lfomodvol = atoi(szValue); - if (m_dpv.lfomodvol > 100) m_dpv.lfomodvol = 100; - if (m_dpv.lfomodvol < 0) m_dpv.lfomodvol = 0; - } - // cspinup - else if (FStrEq(szKeyName, "cspinup")) - { - m_dpv.cspinup = atoi(szValue); - if (m_dpv.cspinup > 100) m_dpv.cspinup = 100; - if (m_dpv.cspinup < 0) m_dpv.cspinup = 0; - } - else - return BaseClass::KeyValue( szKeyName, szValue ); - - return true; -} - - -// =================== ROOM SOUND FX ========================================== - - - - -// ==================== SENTENCE GROUPS, UTILITY FUNCTIONS ====================================== - -int fSentencesInit = false; - -// ===================== SENTENCE GROUPS, MAIN ROUTINES ======================== - -// given sentence group index, play random sentence for given entity. -// returns sentenceIndex - which sentence was picked -// Ipick is only needed if you plan on stopping the sound before playback is done (see SENTENCEG_Stop). -// sentenceIndex can be used to find the name/length of the sentence - -int SENTENCEG_PlayRndI(edict_t *entity, int isentenceg, - float volume, soundlevel_t soundlevel, int flags, int pitch) -{ - char name[64]; - int ipick; - - if (!fSentencesInit) - return -1; - - name[0] = 0; - - ipick = engine->SentenceGroupPick( isentenceg, name, sizeof( name ) ); - if (ipick > 0 && name != '\0') - { - int sentenceIndex = SENTENCEG_Lookup( name ); - CPASAttenuationFilter filter( GetContainingEntity( entity ), soundlevel ); - CBaseEntity::EmitSentenceByIndex( filter, ENTINDEX(entity), CHAN_VOICE, sentenceIndex, volume, soundlevel, flags, pitch ); - return sentenceIndex; - } - - return -1; -} - - -//----------------------------------------------------------------------------- -// Picks a sentence, but doesn't play it -//----------------------------------------------------------------------------- -int SENTENCEG_PickRndSz(const char *szgroupname) -{ - char name[64]; - int ipick; - int isentenceg; - - if (!fSentencesInit) - return -1; - - name[0] = 0; - - isentenceg = engine->SentenceGroupIndexFromName(szgroupname); - if (isentenceg < 0) - { - Warning( "No such sentence group %s\n", szgroupname ); - return -1; - } - - ipick = engine->SentenceGroupPick(isentenceg, name, sizeof( name )); - if (ipick >= 0 && name[0]) - { - return SENTENCEG_Lookup( name ); - } - return -1; -} - -//----------------------------------------------------------------------------- -// Plays a sentence by sentence index -//----------------------------------------------------------------------------- -void SENTENCEG_PlaySentenceIndex( edict_t *entity, int iSentenceIndex, float volume, soundlevel_t soundlevel, int flags, int pitch ) -{ - if ( iSentenceIndex >= 0 ) - { - CPASAttenuationFilter filter( GetContainingEntity( entity ), soundlevel ); - CBaseEntity::EmitSentenceByIndex( filter, ENTINDEX(entity), CHAN_VOICE, iSentenceIndex, volume, soundlevel, flags, pitch ); - } -} - - -int SENTENCEG_PlayRndSz(edict_t *entity, const char *szgroupname, - float volume, soundlevel_t soundlevel, int flags, int pitch) -{ - char name[64]; - int ipick; - int isentenceg; - - if (!fSentencesInit) - return -1; - - name[0] = 0; - - isentenceg = engine->SentenceGroupIndexFromName(szgroupname); - if (isentenceg < 0) - { - Warning( "No such sentence group %s\n", szgroupname ); - return -1; - } - - ipick = engine->SentenceGroupPick(isentenceg, name, sizeof( name )); - if (ipick >= 0 && name[0]) - { - int sentenceIndex = SENTENCEG_Lookup( name ); - CPASAttenuationFilter filter( GetContainingEntity( entity ), soundlevel ); - CBaseEntity::EmitSentenceByIndex( filter, ENTINDEX(entity), CHAN_VOICE, sentenceIndex, volume, soundlevel, flags, pitch ); - return sentenceIndex; - } - - return -1; -} - -// play sentences in sequential order from sentence group. Reset after last sentence. - -int SENTENCEG_PlaySequentialSz(edict_t *entity, const char *szgroupname, - float volume, soundlevel_t soundlevel, int flags, int pitch, int ipick, int freset) -{ - char name[64]; - int ipicknext; - int isentenceg; - - if (!fSentencesInit) - return -1; - - name[0] = 0; - - isentenceg = engine->SentenceGroupIndexFromName(szgroupname); - if (isentenceg < 0) - return -1; - - ipicknext = engine->SentenceGroupPickSequential(isentenceg, name, sizeof( name ), ipick, freset); - if (ipicknext >= 0 && name[0]) - { - int sentenceIndex = SENTENCEG_Lookup( name ); - CPASAttenuationFilter filter( GetContainingEntity( entity ), soundlevel ); - CBaseEntity::EmitSentenceByIndex( filter, ENTINDEX(entity), CHAN_VOICE, sentenceIndex, volume, soundlevel, flags, pitch ); - return sentenceIndex; - } - - return -1; -} - - -#if 0 -// for this entity, for the given sentence within the sentence group, stop -// the sentence. - -void SENTENCEG_Stop(edict_t *entity, int isentenceg, int ipick) -{ - char buffer[64]; - char sznum[8]; - - if (!fSentencesInit) - return; - - if (isentenceg < 0 || ipick < 0) - return; - - Q_snprintf(buffer,sizeof(buffer),"!%s%d", engine->SentenceGroupNameFromIndex( isentenceg ), ipick ); - - UTIL_StopSound(entity, CHAN_VOICE, buffer); -} -#endif - -// open sentences.txt, scan for groups, build rgsentenceg -// Should be called from world spawn, only works on the -// first call and is ignored subsequently. -void SENTENCEG_Init() -{ - if (fSentencesInit) - return; - - engine->PrecacheSentenceFile( "scripts/sentences.txt" ); - fSentencesInit = true; -} - -// convert sentence (sample) name to !sentencenum, return !sentencenum - -int SENTENCEG_Lookup(const char *sample) -{ - return engine->SentenceIndexFromName( sample + 1 ); -} - - -int SENTENCEG_GetIndex(const char *szrootname) -{ - return engine->SentenceGroupIndexFromName( szrootname ); -} - -void UTIL_RestartAmbientSounds( void ) -{ - CAmbientGeneric *pAmbient = NULL; - while ( ( pAmbient = (CAmbientGeneric*) gEntList.FindEntityByClassname( pAmbient, "ambient_generic" ) ) != NULL ) - { - if (pAmbient->m_fActive ) - { - if ( strstr( STRING( pAmbient->m_iszSound ), "mp3" ) ) - { - pAmbient->SendSound( SND_CHANGE_VOL ); // fake a change, so we don't create 2 sounds - } - pAmbient->SendSound( SND_CHANGE_VOL ); // fake a change, so we don't create 2 sounds - } - } -} - - -// play a specific sentence over the HEV suit speaker - just pass player entity, and !sentencename - -void UTIL_EmitSoundSuit(edict_t *entity, const char *sample) -{ - float fvol; - int pitch = PITCH_NORM; - - fvol = suitvolume.GetFloat(); - if (random->RandomInt(0,1)) - pitch = random->RandomInt(0,6) + 98; - - // If friendlies are talking, reduce the volume of the suit - if ( !g_AIFriendliesTalkSemaphore.IsAvailable( GetContainingEntity( entity ) ) ) - { - fvol *= 0.3; - } - - if (fvol > 0.05) - { - CPASAttenuationFilter filter( GetContainingEntity( entity ) ); - filter.MakeReliable(); - - EmitSound_t ep; - ep.m_nChannel = CHAN_STATIC; - ep.m_pSoundName = sample; - ep.m_flVolume = fvol; - ep.m_SoundLevel = SNDLVL_NORM; - ep.m_nPitch = pitch; - - CBaseEntity::EmitSound( filter, ENTINDEX(entity), ep ); - } -} - -// play a sentence, randomly selected from the passed in group id, over the HEV suit speaker - -int UTIL_EmitGroupIDSuit(edict_t *entity, int isentenceg) -{ - float fvol; - int pitch = PITCH_NORM; - int sentenceIndex = -1; - - fvol = suitvolume.GetFloat(); - if (random->RandomInt(0,1)) - pitch = random->RandomInt(0,6) + 98; - - // If friendlies are talking, reduce the volume of the suit - if ( !g_AIFriendliesTalkSemaphore.IsAvailable( GetContainingEntity( entity ) ) ) - { - fvol *= 0.3; - } - - if (fvol > 0.05) - sentenceIndex = SENTENCEG_PlayRndI(entity, isentenceg, fvol, SNDLVL_NORM, 0, pitch); - - return sentenceIndex; -} - -// play a sentence, randomly selected from the passed in groupname - -int UTIL_EmitGroupnameSuit(edict_t *entity, const char *groupname) -{ - float fvol; - int pitch = PITCH_NORM; - int sentenceIndex = -1; - - fvol = suitvolume.GetFloat(); - if (random->RandomInt(0,1)) - pitch = random->RandomInt(0,6) + 98; - - // If friendlies are talking, reduce the volume of the suit - if ( !g_AIFriendliesTalkSemaphore.IsAvailable( GetContainingEntity( entity ) ) ) - { - fvol *= 0.3; - } - - if (fvol > 0.05) - sentenceIndex = SENTENCEG_PlayRndSz(entity, groupname, fvol, SNDLVL_NORM, 0, pitch); - - return sentenceIndex; -} - -// ===================== MATERIAL TYPE DETECTION, MAIN ROUTINES ======================== -// -// Used to detect the texture the player is standing on, map the -// texture name to a material type. Play footstep sound based -// on material type. - -char TEXTURETYPE_Find( trace_t *ptr ) -{ - const surfacedata_t *psurfaceData = physprops->GetSurfaceData( ptr->surface.surfaceProps ); - - return psurfaceData->game.material; -} diff --git a/game/server/soundent.cpp b/game/server/soundent.cpp deleted file mode 100644 index d44f45db0..000000000 --- a/game/server/soundent.cpp +++ /dev/null @@ -1,808 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "soundent.h" -#include "game.h" -#include "world.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Some enumerations needed by CSoundEnt -//----------------------------------------------------------------------------- - -// identifiers passed to functions that can operate on either list, to indicate which list to operate on. -#define SOUNDLISTTYPE_FREE 1 -#define SOUNDLISTTYPE_ACTIVE 2 - - - -LINK_ENTITY_TO_CLASS( soundent, CSoundEnt ); - -static CSoundEnt *g_pSoundEnt = NULL; - -BEGIN_SIMPLE_DATADESC( CSound ) - - DEFINE_FIELD( m_hOwner, FIELD_EHANDLE ), - DEFINE_FIELD( m_iVolume, FIELD_INTEGER ), - DEFINE_FIELD( m_flOcclusionScale, FIELD_FLOAT ), - DEFINE_FIELD( m_iType, FIELD_INTEGER ), -// DEFINE_FIELD( m_iNextAudible, FIELD_INTEGER ), - DEFINE_FIELD( m_bNoExpirationTime, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flExpireTime, FIELD_TIME ), - DEFINE_FIELD( m_iNext, FIELD_SHORT ), - DEFINE_FIELD( m_ownerChannelIndex, FIELD_INTEGER ), - DEFINE_FIELD( m_vecOrigin, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_bHasOwner, FIELD_BOOLEAN ), -// DEFINE_FIELD( m_iMyIndex, FIELD_INTEGER ), - DEFINE_FIELD( m_hTarget, FIELD_EHANDLE ), - -END_DATADESC() - - -//========================================================= -// CSound - Clear - zeros all fields for a sound -//========================================================= -void CSound::Clear ( void ) -{ - m_vecOrigin = vec3_origin; - m_iType = 0; - m_iVolume = 0; - m_flOcclusionScale = 0; - m_flExpireTime = 0; - m_bNoExpirationTime = false; - m_iNext = SOUNDLIST_EMPTY; - m_iNextAudible = 0; -} - -//========================================================= -// Reset - clears the volume, origin, and type for a sound, -// but doesn't expire or unlink it. -//========================================================= -void CSound::Reset ( void ) -{ - m_vecOrigin = vec3_origin; - m_iType = 0; - m_iVolume = 0; - m_iNext = SOUNDLIST_EMPTY; -} - -//========================================================= -// FIsSound - returns true if the sound is an Audible sound -//========================================================= -bool CSound::FIsSound ( void ) -{ - switch( SoundTypeNoContext() ) - { - case SOUND_COMBAT: - case SOUND_WORLD: - case SOUND_PLAYER: - case SOUND_DANGER: - case SOUND_DANGER_SNIPERONLY: - case SOUND_THUMPER: - case SOUND_BULLET_IMPACT: - case SOUND_BUGBAIT: - case SOUND_PHYSICS_DANGER: - case SOUND_MOVE_AWAY: - case SOUND_PLAYER_VEHICLE: - return true; - - default: - return false; - } -} - -//========================================================= -// FIsScent - returns true if the sound is actually a scent -// do we really need this function? If a sound isn't a sound, -// it must be a scent. (sjb) -//========================================================= -bool CSound::FIsScent ( void ) -{ - switch( m_iType ) - { - case SOUND_CARCASS: - case SOUND_MEAT: - case SOUND_GARBAGE: - return true; - - default: - return false; - } -} - - -//--------------------------------------------------------- -// This function returns the spot the listener should be -// interested in if he hears the sound. MOST of the time, -// this spot is the same as the sound's origin. But sometimes -// (like with bullet impacts) the entity that owns the -// sound is more interesting than the actual location of the -// sound effect. -//--------------------------------------------------------- -const Vector &CSound::GetSoundReactOrigin( void ) -{ - - // Check pure types. - switch( m_iType ) - { - case SOUND_BULLET_IMPACT: - case SOUND_PHYSICS_DANGER: - if( m_hOwner.Get() != NULL ) - { - // We really want the origin of this sound's - // owner. - return m_hOwner->GetAbsOrigin(); - } - else - { - // If the owner is somehow invalid, we'll settle - // for the sound's origin rather than a crash. - return GetSoundOrigin(); - } - break; - } - - if( m_iType & SOUND_CONTEXT_REACT_TO_SOURCE ) - { - if( m_hOwner.Get() != NULL ) - { - return m_hOwner->GetAbsOrigin(); - } - } - - // Check for types with additional context. - if( m_iType & SOUND_DANGER ) - { - if( (m_iType & SOUND_CONTEXT_FROM_SNIPER) ) - { - if( m_hOwner.Get() != NULL ) - { - // Be afraid of the sniper's location, not where the bullet will hit. - return m_hOwner->GetAbsOrigin(); - } - else - { - return GetSoundOrigin(); - } - } - } - - - return GetSoundOrigin(); -} - - - -//----------------------------------------------------------------------------- -// Save/load -//----------------------------------------------------------------------------- -BEGIN_DATADESC( CSoundEnt ) - - DEFINE_FIELD( m_iFreeSound, FIELD_INTEGER ), - DEFINE_FIELD( m_iActiveSound, FIELD_INTEGER ), - DEFINE_FIELD( m_cLastActiveSounds, FIELD_INTEGER ), - DEFINE_EMBEDDED_ARRAY( m_SoundPool, MAX_WORLD_SOUNDS_SP ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Class factory methods -//----------------------------------------------------------------------------- -bool CSoundEnt::InitSoundEnt() -{ - ///!!!LATER - do we want a sound ent in deathmatch? (sjb) - g_pSoundEnt = (CSoundEnt*)CBaseEntity::Create( "soundent", vec3_origin, vec3_angle, GetWorldEntity() ); - if ( !g_pSoundEnt ) - { - Warning( "**COULD NOT CREATE SOUNDENT**\n" ); - return false; - } - g_pSoundEnt->AddEFlags( EFL_KEEP_ON_RECREATE_ENTITIES ); - return true; -} - -void CSoundEnt::ShutdownSoundEnt() -{ - if ( g_pSoundEnt ) - { - g_pSoundEnt->FreeList(); - g_pSoundEnt = NULL; - } -} - - -//----------------------------------------------------------------------------- -// Construction, destruction -//----------------------------------------------------------------------------- -CSoundEnt::CSoundEnt() -{ -} - -CSoundEnt::~CSoundEnt() -{ -} - - -//========================================================= -// Spawn -//========================================================= -void CSoundEnt::Spawn( void ) -{ - SetSolid( SOLID_NONE ); - Initialize(); - - SetNextThink( gpGlobals->curtime + 1 ); -} - -void CSoundEnt::OnRestore() -{ - BaseClass::OnRestore(); - - // Make sure the singleton points to the restored version of this. - if ( g_pSoundEnt ) - { - Assert( g_pSoundEnt != this ); - UTIL_Remove( g_pSoundEnt ); - } - g_pSoundEnt = this; -} - - -//========================================================= -// Think - at interval, the entire active sound list is checked -// for sounds that have ExpireTimes less than or equal -// to the current world time, and these sounds are deallocated. -//========================================================= -void CSoundEnt::Think ( void ) -{ - int iSound; - int iPreviousSound; - - SetNextThink( gpGlobals->curtime + 0.1 );// how often to check the sound list. - - iPreviousSound = SOUNDLIST_EMPTY; - iSound = m_iActiveSound; - - while ( iSound != SOUNDLIST_EMPTY ) - { - if ( (m_SoundPool[ iSound ].m_flExpireTime <= gpGlobals->curtime && (!m_SoundPool[ iSound ].m_bNoExpirationTime)) || !m_SoundPool[iSound].ValidateOwner() ) - { - int iNext = m_SoundPool[ iSound ].m_iNext; - - if( displaysoundlist.GetInt() == 1 ) - { - Msg(" Removed Sound: %d (Time:%f)\n", m_SoundPool[ iSound ].SoundType(), gpGlobals->curtime ); - } - if( displaysoundlist.GetInt() == 2 && m_SoundPool[ iSound ].IsSoundType( SOUND_DANGER ) ) - { - Msg(" Removed Danger Sound: %d (time:%f)\n", m_SoundPool[ iSound ].SoundType(), gpGlobals->curtime ); - } - - // move this sound back into the free list - FreeSound( iSound, iPreviousSound ); - - iSound = iNext; - } - else - { - if( displaysoundlist.GetBool() ) - { - Vector forward, right, up; - GetVectors( &forward, &right, &up ); - byte r, g, b; - - // Default to yellow. - r = 255; - g = 255; - b = 0; - - CSound *pSound = &m_SoundPool[ iSound ]; - - if( pSound->IsSoundType( SOUND_DANGER ) ) - { - r = 255; - g = 0; - b = 0; - } - - if( displaysoundlist.GetInt() == 1 || (displaysoundlist.GetInt() == 2 && pSound->IsSoundType( SOUND_DANGER ) ) ) - { - NDebugOverlay::Line( pSound->GetSoundOrigin(), pSound->GetSoundOrigin() + forward * pSound->Volume(), r,g,b, false, 0.1 ); - NDebugOverlay::Line( pSound->GetSoundOrigin(), pSound->GetSoundOrigin() - forward * pSound->Volume(), r,g,b, false, 0.1 ); - - NDebugOverlay::Line( pSound->GetSoundOrigin(), pSound->GetSoundOrigin() + right * pSound->Volume(), r,g,b, false, 0.1 ); - NDebugOverlay::Line( pSound->GetSoundOrigin(), pSound->GetSoundOrigin() - right * pSound->Volume(), r,g,b, false, 0.1 ); - - NDebugOverlay::Line( pSound->GetSoundOrigin(), pSound->GetSoundOrigin() + up * pSound->Volume(), r,g,b, false, 0.1 ); - NDebugOverlay::Line( pSound->GetSoundOrigin(), pSound->GetSoundOrigin() - up * pSound->Volume(), r,g,b, false, 0.1 ); - - if( pSound->m_flOcclusionScale != 1.0 ) - { - // Draw the occluded radius, too. - r = 0; g = 150; b = 255; - NDebugOverlay::Line( pSound->GetSoundOrigin(), pSound->GetSoundOrigin() + forward * pSound->OccludedVolume(), r,g,b, false, 0.1 ); - NDebugOverlay::Line( pSound->GetSoundOrigin(), pSound->GetSoundOrigin() - forward * pSound->OccludedVolume(), r,g,b, false, 0.1 ); - - NDebugOverlay::Line( pSound->GetSoundOrigin(), pSound->GetSoundOrigin() + right * pSound->OccludedVolume(), r,g,b, false, 0.1 ); - NDebugOverlay::Line( pSound->GetSoundOrigin(), pSound->GetSoundOrigin() - right * pSound->OccludedVolume(), r,g,b, false, 0.1 ); - - NDebugOverlay::Line( pSound->GetSoundOrigin(), pSound->GetSoundOrigin() + up * pSound->OccludedVolume(), r,g,b, false, 0.1 ); - NDebugOverlay::Line( pSound->GetSoundOrigin(), pSound->GetSoundOrigin() - up * pSound->OccludedVolume(), r,g,b, false, 0.1 ); - } - } - - DevMsg( 2, "Soundlist: %d / %d (%d)\n", ISoundsInList( SOUNDLISTTYPE_ACTIVE ),ISoundsInList( SOUNDLISTTYPE_FREE ), ISoundsInList( SOUNDLISTTYPE_ACTIVE ) - m_cLastActiveSounds ); - m_cLastActiveSounds = ISoundsInList ( SOUNDLISTTYPE_ACTIVE ); - } - - iPreviousSound = iSound; - iSound = m_SoundPool[ iSound ].m_iNext; - } - } - -} - -//========================================================= -// Precache - dummy function -//========================================================= -void CSoundEnt::Precache ( void ) -{ -} - -//========================================================= -// FreeSound - clears the passed active sound and moves it -// to the top of the free list. TAKE CARE to only call this -// function for sounds in the Active list!! -//========================================================= -void CSoundEnt::FreeSound ( int iSound, int iPrevious ) -{ - if ( !g_pSoundEnt ) - { - // no sound ent! - return; - } - - if ( iPrevious != SOUNDLIST_EMPTY ) - { - // iSound is not the head of the active list, so - // must fix the index for the Previous sound - g_pSoundEnt->m_SoundPool[ iPrevious ].m_iNext = g_pSoundEnt->m_SoundPool[ iSound ].m_iNext; - } - else - { - // the sound we're freeing IS the head of the active list. - g_pSoundEnt->m_iActiveSound = g_pSoundEnt->m_SoundPool [ iSound ].m_iNext; - } - - // make iSound the head of the Free list. - g_pSoundEnt->m_SoundPool[ iSound ].m_iNext = g_pSoundEnt->m_iFreeSound; - g_pSoundEnt->m_iFreeSound = iSound; -} - -//========================================================= -// IAllocSound - moves a sound from the Free list to the -// Active list returns the index of the alloc'd sound -//========================================================= -int CSoundEnt::IAllocSound( void ) -{ - int iNewSound; - - if ( m_iFreeSound == SOUNDLIST_EMPTY ) - { - // no free sound! - if ( developer.GetInt() >= 2 ) - Msg( "Free Sound List is full!\n" ); - - return SOUNDLIST_EMPTY; - } - - // there is at least one sound available, so move it to the - // Active sound list, and return its SoundPool index. - - iNewSound = m_iFreeSound;// copy the index of the next free sound - - m_iFreeSound = m_SoundPool[ m_iFreeSound ].m_iNext;// move the index down into the free list. - - m_SoundPool[ iNewSound ].m_iNext = m_iActiveSound;// point the new sound at the top of the active list. - - m_iActiveSound = iNewSound;// now make the new sound the top of the active list. You're done. - -#ifdef DEBUG - m_SoundPool[ iNewSound ].m_iMyIndex = iNewSound; -#endif // DEBUG - - return iNewSound; -} - -//========================================================= -// InsertSound - Allocates a free sound and fills it with -// sound info. -//========================================================= -void CSoundEnt::InsertSound ( int iType, const Vector &vecOrigin, int iVolume, float flDuration, CBaseEntity *pOwner, int soundChannelIndex, CBaseEntity *pSoundTarget ) -{ - int iThisSound; - - if ( !g_pSoundEnt ) - return; - - if( soundChannelIndex == SOUNDENT_CHANNEL_UNSPECIFIED ) - { - // No sound channel specified. So just make a new sound. - iThisSound = g_pSoundEnt->IAllocSound(); - } - else - { - // If this entity has already got a sound in the soundlist that's on this - // channel, update that sound. Otherwise add a new one. - iThisSound = g_pSoundEnt->FindOrAllocateSound( pOwner, soundChannelIndex ); - } - - if ( iThisSound == SOUNDLIST_EMPTY ) - { - DevMsg( "Could not AllocSound() for InsertSound() (Game DLL)\n" ); - return; - } - - CSound *pSound; - - pSound = &g_pSoundEnt->m_SoundPool[ iThisSound ]; - - pSound->SetSoundOrigin( vecOrigin ); - pSound->m_iType = iType; - pSound->m_iVolume = iVolume; - pSound->m_flOcclusionScale = 0.5; - pSound->m_flExpireTime = gpGlobals->curtime + flDuration; - pSound->m_bNoExpirationTime = false; - pSound->m_hOwner.Set( pOwner ); - pSound->m_hTarget.Set( pSoundTarget ); - pSound->m_ownerChannelIndex = soundChannelIndex; - - // Keep track of whether this sound had an owner when it was made. If the sound has a long duration, - // the owner could disappear by the time someone hears this sound, so we have to look at this boolean - // and throw out sounds who have a NULL owner but this field set to true. (sjb) 12/2/2005 - if( pOwner ) - { - pSound->m_bHasOwner = true; - } - else - { - pSound->m_bHasOwner = false; - } - - if( displaysoundlist.GetInt() == 1 ) - { - Msg(" Added Sound! Type:%d Duration:%f (Time:%f)\n", pSound->SoundType(), flDuration, gpGlobals->curtime ); - } - if( displaysoundlist.GetInt() == 2 && (iType & SOUND_DANGER) ) - { - Msg(" Added Danger Sound! Duration:%f (Time:%f)\n", flDuration, gpGlobals->curtime ); - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CSoundEnt::FindOrAllocateSound( CBaseEntity *pOwner, int soundChannelIndex ) -{ - int iSound = m_iActiveSound; - - while ( iSound != SOUNDLIST_EMPTY ) - { - CSound &sound = m_SoundPool[iSound]; - - if ( sound.m_ownerChannelIndex == soundChannelIndex && sound.m_hOwner == pOwner ) - { - return iSound; - } - - iSound = sound.m_iNext; - } - - return IAllocSound(); -} - -//========================================================= -// Initialize - clears all sounds and moves them into the -// free sound list. -//========================================================= -void CSoundEnt::Initialize ( void ) -{ - int i; - int iSound; - - m_cLastActiveSounds = 0; - m_iFreeSound = 0; - m_iActiveSound = SOUNDLIST_EMPTY; - - // In SP, we should only use the first 64 slots so save/load works right. - // In MP, have one for each player and 32 extras. - int nTotalSoundsInPool = MAX_WORLD_SOUNDS_SP; - if ( gpGlobals->maxClients > 1 ) - nTotalSoundsInPool = MIN( MAX_WORLD_SOUNDS_MP, gpGlobals->maxClients + 32 ); - - if ( gpGlobals->maxClients+16 > nTotalSoundsInPool ) - { - Warning( "CSoundEnt pool is low on sounds due to high number of clients.\n" ); - } - - for ( i = 0 ; i < nTotalSoundsInPool ; i++ ) - { - // clear all sounds, and link them into the free sound list. - m_SoundPool[ i ].Clear(); - m_SoundPool[ i ].m_iNext = i + 1; - } - - m_SoundPool[ i - 1 ].m_iNext = SOUNDLIST_EMPTY;// terminate the list here. - - - // now reserve enough sounds for each client - for ( i = 0 ; i < gpGlobals->maxClients ; i++ ) - { - iSound = IAllocSound(); - - if ( iSound == SOUNDLIST_EMPTY ) - { - DevMsg( "Could not AllocSound() for Client Reserve! (DLL)\n" ); - return; - } - - m_SoundPool[ iSound ].m_bNoExpirationTime = true; - } -} - -//========================================================= -// ISoundsInList - returns the number of sounds in the desired -// sound list. -//========================================================= -int CSoundEnt::ISoundsInList ( int iListType ) -{ - int i; - int iThisSound = SOUNDLIST_EMPTY; - - if ( iListType == SOUNDLISTTYPE_FREE ) - { - iThisSound = m_iFreeSound; - } - else if ( iListType == SOUNDLISTTYPE_ACTIVE ) - { - iThisSound = m_iActiveSound; - } - else - { - Msg( "Unknown Sound List Type!\n" ); - } - - if ( iThisSound == SOUNDLIST_EMPTY ) - { - return 0; - } - - i = 0; - - while ( iThisSound != SOUNDLIST_EMPTY ) - { - i++; - - iThisSound = m_SoundPool[ iThisSound ].m_iNext; - } - - return i; -} - -//========================================================= -// ActiveList - returns the head of the active sound list -//========================================================= -int CSoundEnt::ActiveList ( void ) -{ - if ( !g_pSoundEnt ) - { - return SOUNDLIST_EMPTY; - } - - return g_pSoundEnt->m_iActiveSound; -} - -//========================================================= -// FreeList - returns the head of the free sound list -//========================================================= -int CSoundEnt::FreeList ( void ) -{ - if ( !g_pSoundEnt ) - { - return SOUNDLIST_EMPTY; - } - - return g_pSoundEnt->m_iFreeSound; -} - -//========================================================= -// SoundPointerForIndex - returns a pointer to the instance -// of CSound at index's position in the sound pool. -//========================================================= -CSound* CSoundEnt::SoundPointerForIndex( int iIndex ) -{ - if ( !g_pSoundEnt ) - { - return NULL; - } - - if ( iIndex > ( MAX_WORLD_SOUNDS_MP - 1 ) ) - { - Msg( "SoundPointerForIndex() - Index too large!\n" ); - return NULL; - } - - if ( iIndex < 0 ) - { - Msg( "SoundPointerForIndex() - Index < 0!\n" ); - return NULL; - } - - return &g_pSoundEnt->m_SoundPool[ iIndex ]; -} - -//========================================================= -// Clients are numbered from 1 to MAXCLIENTS, but the client -// reserved sounds in the soundlist are from 0 to MAXCLIENTS - 1, -// so this function ensures that a client gets the proper index -// to his reserved sound in the soundlist. -//========================================================= -int CSoundEnt::ClientSoundIndex ( edict_t *pClient ) -{ - int iReturn = ENTINDEX( pClient ) - 1; - -#ifdef _DEBUG - if ( iReturn < 0 || iReturn >= gpGlobals->maxClients ) - { - Msg( "** ClientSoundIndex returning a bogus value! **\n" ); - } -#endif // _DEBUG - - return iReturn; -} - -//----------------------------------------------------------------------------- -// Purpose: Return the loudest sound of the specified type at "earposition" -//----------------------------------------------------------------------------- -CSound* CSoundEnt::GetLoudestSoundOfType( int iType, const Vector &vecEarPosition ) -{ - CSound *pLoudestSound = NULL; - - int iThisSound; - int iBestSound = SOUNDLIST_EMPTY; - float flBestDist = MAX_COORD_RANGE*MAX_COORD_RANGE;// so first nearby sound will become best so far. - float flDist; - CSound *pSound; - - iThisSound = ActiveList(); - - while ( iThisSound != SOUNDLIST_EMPTY ) - { - pSound = SoundPointerForIndex( iThisSound ); - - if ( pSound && pSound->m_iType == iType && pSound->ValidateOwner() ) - { - flDist = ( pSound->GetSoundOrigin() - vecEarPosition ).Length(); - - //FIXME: This doesn't match what's in Listen() - //flDist = UTIL_DistApprox( pSound->GetSoundOrigin(), vecEarPosition ); - - if ( flDist <= pSound->m_iVolume && flDist < flBestDist ) - { - pLoudestSound = pSound; - - iBestSound = iThisSound; - flBestDist = flDist; - } - } - - iThisSound = pSound->m_iNext; - } - - return pLoudestSound; -} - - -//----------------------------------------------------------------------------- -// Purpose: Inserts an AI sound into the world sound list. -//----------------------------------------------------------------------------- -class CAISound : public CPointEntity -{ -public: - CAISound() - { - // Initialize these new keyvalues appropriately - // in order to support legacy instances of ai_sound. - m_iSoundContext = 0x00000000; - m_iVolume = 0; - m_flDuration = 0.3; - } - - DECLARE_CLASS( CAISound, CPointEntity ); - - DECLARE_DATADESC(); - - // data - int m_iSoundType; - int m_iSoundContext; - int m_iVolume; - float m_flDuration; - string_t m_iszProxyEntityName; - - // Input handlers - void InputInsertSound( inputdata_t &inputdata ); - void InputEmitAISound( inputdata_t &inputdata ); -}; - -LINK_ENTITY_TO_CLASS( ai_sound, CAISound ); - -BEGIN_DATADESC( CAISound ) - - DEFINE_KEYFIELD( m_iSoundType, FIELD_INTEGER, "soundtype" ), - DEFINE_KEYFIELD( m_iSoundContext, FIELD_INTEGER, "soundcontext" ), - DEFINE_KEYFIELD( m_iVolume, FIELD_INTEGER, "volume" ), - DEFINE_KEYFIELD( m_flDuration, FIELD_FLOAT, "duration" ), - DEFINE_KEYFIELD( m_iszProxyEntityName, FIELD_STRING, "locationproxy" ), - - DEFINE_INPUTFUNC( FIELD_INTEGER, "InsertSound", InputInsertSound ), - DEFINE_INPUTFUNC( FIELD_VOID, "EmitAISound", InputEmitAISound ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: *** OBSOLETE **** Here for legacy support only! -//----------------------------------------------------------------------------- -void CAISound::InputInsertSound( inputdata_t &inputdata ) -{ - int iVolume; - - iVolume = inputdata.value.Int(); - - Vector vecLocation = GetAbsOrigin(); - - if( m_iszProxyEntityName != NULL_STRING ) - { - CBaseEntity *pProxy = gEntList.FindEntityByName( NULL, m_iszProxyEntityName ); - - if( pProxy ) - { - vecLocation = pProxy->GetAbsOrigin(); - } - else - { - DevWarning("Warning- ai_sound cannot find proxy entity named '%s'. Using self.\n", STRING(m_iszProxyEntityName) ); - } - } - - g_pSoundEnt->InsertSound( m_iSoundType, vecLocation, iVolume, m_flDuration, this ); -} - -void CAISound::InputEmitAISound( inputdata_t &inputdata ) -{ - Vector vecLocation = GetAbsOrigin(); - - if( m_iszProxyEntityName != NULL_STRING ) - { - CBaseEntity *pProxy = gEntList.FindEntityByName( NULL, m_iszProxyEntityName ); - - if( pProxy ) - { - vecLocation = pProxy->GetAbsOrigin(); - } - else - { - DevWarning("Warning- ai_sound cannot find proxy entity named '%s'. Using self.\n", STRING(m_iszProxyEntityName) ); - } - } - - g_pSoundEnt->InsertSound( m_iSoundType | m_iSoundContext, vecLocation, m_iVolume, m_flDuration, this ); -} - - diff --git a/game/server/soundent.h b/game/server/soundent.h deleted file mode 100644 index 7e0523985..000000000 --- a/game/server/soundent.h +++ /dev/null @@ -1,264 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -// Soundent.h - the entity that spawns when the world -// spawns, and handles the world's active and free sound -// lists. - -#ifndef SOUNDENT_H -#define SOUNDENT_H - -#ifdef _WIN32 -#pragma once -#endif - -enum -{ - MAX_WORLD_SOUNDS_SP = 64, // Maximum number of sounds handled by the world at one time in single player. - // This is also the number of entries saved in a savegame file (for b/w compatibility). - - MAX_WORLD_SOUNDS_MP = 128 // The sound array size is set this large but we'll only use gpGlobals->maxPlayers+32 entries in mp. -}; - -enum -{ - SOUND_NONE = 0, - SOUND_COMBAT = 0x00000001, - SOUND_WORLD = 0x00000002, - SOUND_PLAYER = 0x00000004, - SOUND_DANGER = 0x00000008, - SOUND_BULLET_IMPACT = 0x00000010, - SOUND_CARCASS = 0x00000020, - SOUND_MEAT = 0x00000040, - SOUND_GARBAGE = 0x00000080, - SOUND_THUMPER = 0x00000100, // keeps certain creatures at bay - SOUND_BUGBAIT = 0x00000200, // gets the antlion's attention - SOUND_PHYSICS_DANGER = 0x00000400, - SOUND_DANGER_SNIPERONLY = 0x00000800, // only scares the sniper NPC. - SOUND_MOVE_AWAY = 0x00001000, - SOUND_PLAYER_VEHICLE = 0x00002000, - SOUND_READINESS_LOW = 0x00004000, // Changes listener's readiness (Player Companion only) - SOUND_READINESS_MEDIUM = 0x00008000, - SOUND_READINESS_HIGH = 0x00010000, - - // Contexts begin here. - SOUND_CONTEXT_FROM_SNIPER = 0x00100000, // additional context for SOUND_DANGER - SOUND_CONTEXT_GUNFIRE = 0x00200000, // Added to SOUND_COMBAT - SOUND_CONTEXT_MORTAR = 0x00400000, // Explosion going to happen here. - SOUND_CONTEXT_COMBINE_ONLY = 0x00800000, // Only combine can hear sounds marked this way - SOUND_CONTEXT_REACT_TO_SOURCE = 0x01000000, // React to sound source's origin, not sound's location - SOUND_CONTEXT_EXPLOSION = 0x02000000, // Context added to SOUND_COMBAT, usually. - SOUND_CONTEXT_EXCLUDE_COMBINE = 0x04000000, // Combine do NOT hear this - SOUND_CONTEXT_DANGER_APPROACH = 0x08000000, // Treat as a normal danger sound if you see the source, otherwise turn to face source. - SOUND_CONTEXT_ALLIES_ONLY = 0x10000000, // Only player allies can hear this sound - SOUND_CONTEXT_PLAYER_VEHICLE = 0x20000000, // HACK: need this because we're not treating the SOUND_xxx values as true bit values! See switch in OnListened. - - ALL_CONTEXTS = 0xFFF00000, - - ALL_SCENTS = SOUND_CARCASS | SOUND_MEAT | SOUND_GARBAGE, - - ALL_SOUNDS = 0x000FFFFF & ~ALL_SCENTS, - -}; - -// Make as many of these as you want. -enum -{ - SOUNDENT_CHANNEL_UNSPECIFIED = 0, - SOUNDENT_CHANNEL_REPEATING, - SOUNDENT_CHANNEL_REPEATED_DANGER, // for things that make danger sounds frequently. - SOUNDENT_CHANNEL_REPEATED_PHYSICS_DANGER, - SOUNDENT_CHANNEL_WEAPON, - SOUNDENT_CHANNEL_INJURY, - SOUNDENT_CHANNEL_BULLET_IMPACT, - SOUNDENT_CHANNEL_NPC_FOOTSTEP, - SOUNDENT_CHANNEL_SPOOKY_NOISE, // made by zombies in darkness - SOUNDENT_CHANNEL_ZOMBINE_GRENADE, -}; - -enum -{ - SOUNDLIST_EMPTY = -1 -}; - -#define SOUNDENT_VOLUME_MACHINEGUN 1500 -#define SOUNDENT_VOLUME_SHOTGUN 1500 -#define SOUNDENT_VOLUME_PISTOL 1500 -#define SOUNDENT_VOLUME_EMPTY 500 // volume of the "CLICK" when you have no bullets - -enum -{ - SOUND_PRIORITY_VERY_LOW = -2, - SOUND_PRIORITY_LOW, - SOUND_PRIORITY_NORMAL = 0, - SOUND_PRIORITY_HIGH, - SOUND_PRIORITY_VERY_HIGH, - SOUND_PRIORITY_HIGHEST, -}; - -//========================================================= -// CSound - an instance of a sound in the world. -//========================================================= -class CSound -{ - DECLARE_SIMPLE_DATADESC(); - -public: - bool DoesSoundExpire() const; - float SoundExpirationTime() const; - void SetSoundOrigin( const Vector &vecOrigin ) { m_vecOrigin = vecOrigin; } - const Vector& GetSoundOrigin( void ) { return m_vecOrigin; } - const Vector& GetSoundReactOrigin( void ); - bool FIsSound( void ); - bool FIsScent( void ); - bool IsSoundType( int nSoundFlags ) const; - int SoundType( ) const; - int SoundContext() const; - int SoundTypeNoContext( ) const; - int Volume( ) const; - float OccludedVolume() { return m_iVolume * m_flOcclusionScale; } - int NextSound() const; - void Reset ( void ); - int SoundChannel( void ) const; - bool ValidateOwner() const; - - EHANDLE m_hOwner; // sound's owner - EHANDLE m_hTarget; // Sounds's target - an odd concept. For a gunfire sound, the target is the entity being fired at - int m_iVolume; // how loud the sound is - float m_flOcclusionScale; // How loud the sound is when occluded by the world. (volume * occlusionscale) - int m_iType; // what type of sound this is - int m_iNextAudible; // temporary link that NPCs use to build a list of audible sounds - -private: - void Clear ( void ); - - float m_flExpireTime; // when the sound should be purged from the list - short m_iNext; // index of next sound in this list ( Active or Free ) - bool m_bNoExpirationTime; - int m_ownerChannelIndex; - - Vector m_vecOrigin; // sound's location in space - - bool m_bHasOwner; // Lets us know if this sound was created with an owner. In case the owner goes null. - -#ifdef DEBUG - int m_iMyIndex; // debugging -#endif - - friend class CSoundEnt; -}; - -inline bool CSound::DoesSoundExpire() const -{ - return m_bNoExpirationTime == false; -} - -inline float CSound::SoundExpirationTime() const -{ - return m_bNoExpirationTime ? FLT_MAX : m_flExpireTime; -} - -inline bool CSound::IsSoundType( int nSoundFlags ) const -{ - return (m_iType & nSoundFlags) != 0; -} - -inline int CSound::SoundType( ) const -{ - return m_iType; -} - -inline int CSound::SoundContext( ) const -{ - return m_iType & ALL_CONTEXTS; -} - -inline int CSound::SoundTypeNoContext( ) const -{ - return m_iType & ~ALL_CONTEXTS; -} - -inline int CSound::Volume( ) const -{ - return m_iVolume; -} - -inline int CSound::NextSound() const -{ - return m_iNext; -} - -inline int CSound::SoundChannel( void ) const -{ - return m_ownerChannelIndex; -} - -// The owner is considered valid if: -// -The sound never had an assigned owner (quite common) -// -The sound was assigned an owner and that owner still exists -inline bool CSound::ValidateOwner( void ) const -{ - return ( !m_bHasOwner || (m_hOwner.Get() != NULL) ); -} - -//========================================================= -// CSoundEnt - a single instance of this entity spawns when -// the world spawns. The SoundEnt's job is to update the -// world's Free and Active sound lists. -//========================================================= -class CSoundEnt : public CPointEntity -{ - DECLARE_DATADESC(); - -public: - DECLARE_CLASS( CSoundEnt, CPointEntity ); - - // Construction, destruction - static bool InitSoundEnt(); - static void ShutdownSoundEnt(); - - CSoundEnt(); - virtual ~CSoundEnt(); - - virtual void OnRestore(); - void Precache ( void ); - void Spawn( void ); - void Think( void ); - void Initialize ( void ); - int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } - - static void InsertSound ( int iType, const Vector &vecOrigin, int iVolume, float flDuration, CBaseEntity *pOwner = NULL, int soundChannelIndex = SOUNDENT_CHANNEL_UNSPECIFIED, CBaseEntity *pSoundTarget = NULL ); - static void FreeSound ( int iSound, int iPrevious ); - static int ActiveList( void );// return the head of the active list - static int FreeList( void );// return the head of the free list - static CSound* SoundPointerForIndex( int iIndex );// return a pointer for this index in the sound list - static CSound* GetLoudestSoundOfType( int iType, const Vector &vecEarPosition ); - static int ClientSoundIndex ( edict_t *pClient ); - - bool IsEmpty( void ); - int ISoundsInList ( int iListType ); - int IAllocSound ( void ); - int FindOrAllocateSound( CBaseEntity *pOwner, int soundChannelIndex ); - -private: - int m_iFreeSound; // index of the first sound in the free sound list - int m_iActiveSound; // indes of the first sound in the active sound list - int m_cLastActiveSounds; // keeps track of the number of active sounds at the last update. (for diagnostic work) - CSound m_SoundPool[ MAX_WORLD_SOUNDS_MP ]; -}; - - -//----------------------------------------------------------------------------- -// Inline methods -//----------------------------------------------------------------------------- -inline bool CSoundEnt::IsEmpty( void ) -{ - return m_iActiveSound == SOUNDLIST_EMPTY; -} - - -#endif //SOUNDENT_H diff --git a/game/server/soundscape.cpp b/game/server/soundscape.cpp deleted file mode 100644 index 6267730fb..000000000 --- a/game/server/soundscape.cpp +++ /dev/null @@ -1,627 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#include "cbase.h" -#include "soundscape.h" -#include "datamap.h" -#include "soundscape_system.h" -#include "triggers.h" -#include "saverestore_utlvector.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar soundscape_debug( "soundscape_debug", "0", FCVAR_CHEAT, "When on, draws lines to all env_soundscape entities. Green lines show the active soundscape, red lines show soundscapes that aren't in range, and white lines show soundscapes that are in range, but not the active soundscape." ); - -// ----------------------------------------------------------------------------- // -// CEnvSoundscapeProxy stuff. -// ----------------------------------------------------------------------------- // - -LINK_ENTITY_TO_CLASS( env_soundscape_proxy, CEnvSoundscapeProxy ); - -BEGIN_DATADESC( CEnvSoundscapeProxy ) - - DEFINE_KEYFIELD( m_MainSoundscapeName, FIELD_STRING, "MainSoundscapeName" ) - -END_DATADESC() - - -CEnvSoundscapeProxy::CEnvSoundscapeProxy() -{ - m_MainSoundscapeName = NULL_STRING; -} - - -void CEnvSoundscapeProxy::Activate() -{ - if ( m_MainSoundscapeName != NULL_STRING ) - { - CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, m_MainSoundscapeName ); - if ( pEntity ) - { - m_hProxySoundscape = dynamic_cast< CEnvSoundscape* >( pEntity ); - } - } - - if ( m_hProxySoundscape ) - { - // Copy the relevant parameters from our main soundscape. - m_soundscapeIndex = m_hProxySoundscape->m_soundscapeIndex; - for ( size_t i=0; i < ARRAYSIZE( m_positionNames ); i++ ) - m_positionNames[i] = m_hProxySoundscape->m_positionNames[i]; - } - else - { - Warning( "env_soundscape_proxy can't find target soundscape: '%s'\n", STRING( m_MainSoundscapeName ) ); - } - - BaseClass::Activate(); -} - - -// ----------------------------------------------------------------------------- // -// CEnvSoundscape stuff. -// ----------------------------------------------------------------------------- // - -LINK_ENTITY_TO_CLASS( env_soundscape, CEnvSoundscape ); - -BEGIN_DATADESC( CEnvSoundscape ) - - DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "radius" ), - // don't save, recomputed on load - //DEFINE_FIELD( m_soundscapeIndex, FIELD_INTEGER ), - DEFINE_FIELD( m_soundscapeName, FIELD_STRING ), - DEFINE_FIELD( m_hProxySoundscape, FIELD_EHANDLE ), - -// Silence, Classcheck! -// DEFINE_ARRAY( m_positionNames, FIELD_STRING, 4 ), - - DEFINE_KEYFIELD( m_positionNames[0], FIELD_STRING, "position0" ), - DEFINE_KEYFIELD( m_positionNames[1], FIELD_STRING, "position1" ), - DEFINE_KEYFIELD( m_positionNames[2], FIELD_STRING, "position2" ), - DEFINE_KEYFIELD( m_positionNames[3], FIELD_STRING, "position3" ), - DEFINE_KEYFIELD( m_positionNames[4], FIELD_STRING, "position4" ), - DEFINE_KEYFIELD( m_positionNames[5], FIELD_STRING, "position5" ), - DEFINE_KEYFIELD( m_positionNames[6], FIELD_STRING, "position6" ), - DEFINE_KEYFIELD( m_positionNames[7], FIELD_STRING, "position7" ), - - DEFINE_UTLVECTOR( m_hPlayersInPVS, FIELD_EHANDLE ), - DEFINE_FIELD( m_flNextUpdatePlayersInPVS, FIELD_TIME ), - - DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - DEFINE_INPUTFUNC( FIELD_VOID, "ToggleEnabled", InputToggleEnabled ), - - DEFINE_OUTPUT( m_OnPlay, "OnPlay" ), - - -END_DATADESC() - -CEnvSoundscape::CEnvSoundscape() -{ - m_soundscapeName = NULL_STRING; - m_flNextUpdatePlayersInPVS = 0; - m_soundscapeIndex = -1; - m_bDisabled = false; - g_SoundscapeSystem.AddSoundscapeEntity( this ); -} - -CEnvSoundscape::~CEnvSoundscape() -{ - g_SoundscapeSystem.RemoveSoundscapeEntity( this ); -} - -void CEnvSoundscape::InputEnable( inputdata_t &inputdata ) -{ - if (!IsEnabled()) - { - Enable(); - } -} - -void CEnvSoundscape::InputDisable( inputdata_t &inputdata ) -{ - if (IsEnabled()) - { - Disable(); - } -} - -void CEnvSoundscape::InputToggleEnabled( inputdata_t &inputdata ) -{ - if ( IsEnabled() ) - { - Disable(); - } - else - { - Enable(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Returns whether the laser is currently active. -//----------------------------------------------------------------------------- -bool CEnvSoundscape::IsEnabled( void ) const -{ - return !m_bDisabled; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvSoundscape::Disable( void ) -{ - m_bDisabled = true; - - // Reset if we are the currently active soundscape -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CEnvSoundscape::Enable( void ) -{ - m_bDisabled = false; - - // Force the player to recheck soundscapes -} - -bool CEnvSoundscape::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "soundscape")) - { - m_soundscapeName = AllocPooledString( szValue ); - } - else - return BaseClass::KeyValue( szKeyName, szValue ); - - return true; -} - -// returns true if the given sound entity is in range -// and can see the given player entity (pTarget) - -bool CEnvSoundscape::InRangeOfPlayer( CBasePlayer *pTarget ) -{ - Vector vecSpot1 = EarPosition(); - Vector vecSpot2 = pTarget->EarPosition(); - - // calc range from sound entity to player - Vector vecRange = vecSpot2 - vecSpot1; - float range = vecRange.Length(); - if ( m_flRadius > range || m_flRadius == -1 ) - { - trace_t tr; - - UTIL_TraceLine( vecSpot1, vecSpot2, MASK_SOLID_BRUSHONLY|MASK_WATER, pTarget, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction == 1 && !tr.startsolid ) - { - return true; - } - } - - return false; -} - -int CEnvSoundscape::UpdateTransmitState() -{ - // Always transmit all soundscapes to the player. - return SetTransmitState( FL_EDICT_ALWAYS ); -} - -void CEnvSoundscape::WriteAudioParamsTo( audioparams_t &audio ) -{ - audio.ent.Set( this ); - audio.soundscapeIndex = m_soundscapeIndex; - audio.localBits = 0; - for ( int i = 0; i < (int)ARRAYSIZE(m_positionNames); i++ ) - { - if ( m_positionNames[i] != NULL_STRING ) - { - // We are a valid entity for a sound position - CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, m_positionNames[i], this, this ); - if ( pEntity ) - { - audio.localBits |= 1<GetAbsOrigin() ); - } - } - } - - m_OnPlay.FireOutput( this, this ); -} - - -bool CEnvSoundscape::UpdatePlayersInPVS() -{ - // Only update players in PVS every 2 seconds. - if ( gpGlobals->curtime < m_flNextUpdatePlayersInPVS ) - return false; - - m_flNextUpdatePlayersInPVS = gpGlobals->curtime + 2.0f + RandomFloat( -0.3, 0.3 ); - - // Find the players in our PVS. - unsigned char myPVS[16 * 1024]; - int pvsLen = engine->GetPVSForCluster( engine->GetClusterForOrigin( GetAbsOrigin() ), sizeof( myPVS ), myPVS ); - - m_hPlayersInPVS.Purge(); - for ( int i=1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - - if ( !pPlayer ) - continue; - - Vector vecWorldMins, vecWorldMaxs; - pPlayer->CollisionProp()->WorldSpaceAABB( &vecWorldMins, &vecWorldMaxs ); - if ( engine->CheckBoxInPVS( vecWorldMins, vecWorldMaxs, myPVS, pvsLen ) ) - { - m_hPlayersInPVS.AddToTail( pPlayer ); - } - } - return true; -} - - -// -// A client that is visible and in range of a sound entity will -// have its soundscape set by that sound entity. If two or more -// sound entities are contending for a client, then the nearest -// sound entity to the client will set the client's soundscape. -// A client's soundscape will remain set to its prior value until -// a new in-range, visible sound entity resets a new soundscape. -// - -// CONSIDER: if player in water state, autoset and underwater soundscape? -void CEnvSoundscape::Update() -{ - bool bUpdated = UpdatePlayersInPVS(); - - if ( !IsEnabled() ) - return; - - // Only update soundscapes in multiplayer when the PVS gets updated - if ( g_pGameRules->IsMultiplayer() && !bUpdated && !soundscape_debug.GetBool() ) - return; - - bool bDebugThis = soundscape_debug.GetInt() == 1; - - for ( int i=0; i < m_hPlayersInPVS.Count(); i++ ) - { - CBasePlayer *pPlayer = m_hPlayersInPVS[i]; - if ( !pPlayer ) - continue; - - if ( !InRangeOfPlayer( pPlayer ) ) - continue; - - // check to see if this is the sound entity that is - // currently affecting this player - audioparams_t &audio = pPlayer->GetAudioParams(); - - // if we got this far, we're looking at an entity that is contending - // for current player sound. the closest entity to player wins. - CEnvSoundscape *pCurrent = (CEnvSoundscape *)audio.ent.Get(); - if ( !pCurrent || - !pCurrent->IsEnabled() || - !pCurrent->InRangeOfPlayer( pPlayer ) ) - { - // The old one is obscured or out of range.. take over. - WriteAudioParamsTo( audio ); - } - else if ( pCurrent && - EarPosition().DistTo( pPlayer->EarPosition() ) < pCurrent->EarPosition().DistTo( pPlayer->EarPosition() ) ) - { - // new entity is closer to player, so it wins. - WriteAudioParamsTo( audio ); - } - - if ( !bDebugThis ) - { - bDebugThis = soundscape_debug.GetInt() == 2; - } - } - - if ( bDebugThis ) - { - - // draw myself - NDebugOverlay::Box(GetAbsOrigin(), Vector(-10,-10,-10), Vector(10,10,10), 255, 0, 255, 64, NDEBUG_PERSIST_TILL_NEXT_SERVER ); - - // Don't use GetLocalPlayer(), because that prevents multiplayer games using this for testing with a single client in the game - CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); - if ( pPlayer ) - { - audioparams_t &audio = pPlayer->GetAudioParams(); - if ( audio.ent.Get() != this ) - { - if ( InRangeOfPlayer( pPlayer ) ) - { - NDebugOverlay::Line( GetAbsOrigin(), pPlayer->WorldSpaceCenter(), 255, 255, 255, true, NDEBUG_PERSIST_TILL_NEXT_SERVER ); - } - else - { - NDebugOverlay::Line( GetAbsOrigin(), pPlayer->WorldSpaceCenter(), 255, 0, 0, true, NDEBUG_PERSIST_TILL_NEXT_SERVER ); - } - } - else - { - if ( InRangeOfPlayer( pPlayer ) ) - { - NDebugOverlay::Line( GetAbsOrigin(), pPlayer->WorldSpaceCenter(), 0, 255, 0, true, NDEBUG_PERSIST_TILL_NEXT_SERVER ); - } - else - { - NDebugOverlay::Line( GetAbsOrigin(), pPlayer->WorldSpaceCenter(), 255, 170, 0, true, NDEBUG_PERSIST_TILL_NEXT_SERVER ); - } - - // also draw lines to each sound position. - // we don't store the number of local sound positions, just a bitvector of which ones are on. - unsigned int soundbits = audio.localBits.Get(); - float periodic = 2.0f * sin((fmod(gpGlobals->curtime,2.0f) - 1.0f) * M_PI); // = -4f .. 4f - for (int ii = 0 ; ii < NUM_AUDIO_LOCAL_SOUNDS ; ++ii ) - { - if ( soundbits & (1 << ii) ) - { - const Vector &soundLoc = audio.localSound.Get(ii); - NDebugOverlay::Line( GetAbsOrigin(), soundLoc, 0, 32 , 255 , false, NDEBUG_PERSIST_TILL_NEXT_SERVER ); - NDebugOverlay::Cross3D( soundLoc, 16.0f + periodic, 0, 0, 255, false, NDEBUG_PERSIST_TILL_NEXT_SERVER ); - } - } - } - } - - NDebugOverlay::EntityTextAtPosition( GetAbsOrigin(), 0, STRING(m_soundscapeName), NDEBUG_PERSIST_TILL_NEXT_SERVER ); - } - -} - -// -// env_soundscape - spawn a sound entity that will set player soundscape -// when player moves in range and sight. -// -// -void CEnvSoundscape::Spawn( ) -{ - Precache(); - // Because the soundscape has no model, need to make sure it doesn't get culled from the PVS for this reason and therefore - // never exist on the client, etc. - AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); - -} - -void CEnvSoundscape::Precache() -{ - if ( m_soundscapeName == NULL_STRING ) - { - DevMsg("Found soundscape entity with no soundscape name.\n", STRING(m_soundscapeName) ); - return; - } - - m_soundscapeIndex = g_SoundscapeSystem.GetSoundscapeIndex( STRING(m_soundscapeName) ); - if ( IsX360()) - { - g_SoundscapeSystem.PrecacheSounds( m_soundscapeIndex ); - } - if ( !g_SoundscapeSystem.IsValidIndex( m_soundscapeIndex ) ) - { - DevWarning("Can't find soundscape: %s\n", STRING(m_soundscapeName) ); - } -} - -void CEnvSoundscape::DrawDebugGeometryOverlays( void ) -{ - if ( m_debugOverlays & (OVERLAY_BBOX_BIT|OVERLAY_PIVOT_BIT|OVERLAY_ABSBOX_BIT) ) - { - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - if ( pPlayer ) - { - audioparams_t &audio = pPlayer->GetAudioParams(); - if ( audio.ent.Get() == this ) - { - NDebugOverlay::Line(GetAbsOrigin(), pPlayer->WorldSpaceCenter(), 255, 0, 255, false, 0 ); - } - } - } - - BaseClass::DrawDebugGeometryOverlays(); -} - - -// ---------------------------------------------------------------------------------------------------- // -// CEnvSoundscapeTriggerable -// ---------------------------------------------------------------------------------------------------- // - -LINK_ENTITY_TO_CLASS( env_soundscape_triggerable, CEnvSoundscapeTriggerable ); - -BEGIN_DATADESC( CEnvSoundscapeTriggerable ) -END_DATADESC() - - -CEnvSoundscapeTriggerable::CEnvSoundscapeTriggerable() -{ -} - - -void CEnvSoundscapeTriggerable::DelegateStartTouch( CBaseEntity *pEnt ) -{ - CBasePlayer *pPlayer = dynamic_cast< CBasePlayer* >( pEnt ); - if ( !pPlayer ) - return; - - // Just in case.. we shouldn't already be in the player's list because it should have - // called DelegateEndTouch, but this seems to happen when they're noclipping. - pPlayer->m_hTriggerSoundscapeList.FindAndRemove( this ); - - // Add us to the player's list of soundscapes and - pPlayer->m_hTriggerSoundscapeList.AddToHead( this ); - WriteAudioParamsTo( pPlayer->GetAudioParams() ); -} - - -void CEnvSoundscapeTriggerable::DelegateEndTouch( CBaseEntity *pEnt ) -{ - CBasePlayer *pPlayer = dynamic_cast< CBasePlayer* >( pEnt ); - if ( !pPlayer ) - return; - - // Remove us from the ent's list of soundscapes. - pPlayer->m_hTriggerSoundscapeList.FindAndRemove( this ); - while ( pPlayer->m_hTriggerSoundscapeList.Count() > 0 ) - { - CEnvSoundscapeTriggerable *pSS = dynamic_cast< CEnvSoundscapeTriggerable* >( pPlayer->m_hTriggerSoundscapeList[0].Get() ); - if ( pSS ) - { - // Make this one current. - pSS->WriteAudioParamsTo( pPlayer->GetAudioParams() ); - return; - } - else - { - pPlayer->m_hTriggerSoundscapeList.Remove( 0 ); - } - } - - // No soundscapes left. - pPlayer->GetAudioParams().ent = NULL; -} - - -void CEnvSoundscapeTriggerable::Think() -{ - // Overrides the base class's think and prevents it from running at all. -} - - -// ---------------------------------------------------------------------------------------------------- // -// CTriggerSoundscape -// ---------------------------------------------------------------------------------------------------- // - -class CTriggerSoundscape : public CBaseTrigger -{ -public: - DECLARE_CLASS( CTriggerSoundscape, CBaseTrigger ); - DECLARE_DATADESC(); - - CTriggerSoundscape(); - - virtual void StartTouch( CBaseEntity *pOther ); - virtual void EndTouch( CBaseEntity *pOther ); - - virtual void Spawn(); - virtual void Activate(); - - void PlayerUpdateThink(); - -private: - CHandle m_hSoundscape; - string_t m_SoundscapeName; - - CUtlVector m_spectators; // spectators in our volume -}; - - -LINK_ENTITY_TO_CLASS( trigger_soundscape, CTriggerSoundscape ); - -BEGIN_DATADESC( CTriggerSoundscape ) - DEFINE_THINKFUNC( PlayerUpdateThink ), - DEFINE_KEYFIELD( m_SoundscapeName, FIELD_STRING, "soundscape" ), - DEFINE_FIELD( m_hSoundscape, FIELD_EHANDLE ), - DEFINE_UTLVECTOR( m_spectators, FIELD_EHANDLE ), -END_DATADESC() - - -CTriggerSoundscape::CTriggerSoundscape() -{ -} - - -void CTriggerSoundscape::StartTouch( CBaseEntity *pOther ) -{ - if ( m_hSoundscape ) - m_hSoundscape->DelegateStartTouch( pOther ); - - BaseClass::StartTouch( pOther ); -} - - -void CTriggerSoundscape::EndTouch( CBaseEntity *pOther ) -{ - if ( m_hSoundscape ) - m_hSoundscape->DelegateEndTouch( pOther ); - - BaseClass::EndTouch( pOther ); -} - - -void CTriggerSoundscape::Spawn() -{ - BaseClass::Spawn(); - InitTrigger(); - - SetThink( &CTriggerSoundscape::PlayerUpdateThink ); - SetNextThink( gpGlobals->curtime + 0.2 ); -} - - -void CTriggerSoundscape::Activate() -{ - m_hSoundscape = dynamic_cast< CEnvSoundscapeTriggerable* >( gEntList.FindEntityByName( NULL, m_SoundscapeName ) ); - BaseClass::Activate(); -} - - -// look for dead/spectating players in our volume, to call touch on -void CTriggerSoundscape::PlayerUpdateThink() -{ - int i; - SetNextThink( gpGlobals->curtime + 0.2 ); - - CUtlVector oldSpectators; - oldSpectators = m_spectators; - m_spectators.RemoveAll(); - - for ( i=1; i <= gpGlobals->maxClients; ++i ) - { - CBasePlayer *player = UTIL_PlayerByIndex( i ); - - if ( !player ) - continue; - - if ( player->IsAlive() ) - continue; - - // if the spectator is intersecting the trigger, track it, and start a touch if it is just starting to touch - if ( Intersects( player ) ) - { - if ( !oldSpectators.HasElement( player ) ) - { - StartTouch( player ); - } - m_spectators.AddToTail( player ); - } - } - - // check for spectators who are no longer intersecting - for ( i=0; i m_hProxySoundscape; - - -private: - - // Updated every couple seconds. Then we check against these players often. - CUtlVector m_hPlayersInPVS; - - // Next time to update the m_hPlayersInPVS list. - float m_flNextUpdatePlayersInPVS; - - bool m_bDisabled; -}; - - -class CEnvSoundscapeProxy : public CEnvSoundscape -{ -public: - DECLARE_CLASS( CEnvSoundscapeProxy, CEnvSoundscape ); - DECLARE_DATADESC(); - - CEnvSoundscapeProxy(); - virtual void Activate(); - - // Here just to stop it falling back to CEnvSoundscape's, and - // printing bogus errors about missing soundscapes. - virtual void Precache() { return; } - -private: - string_t m_MainSoundscapeName; -}; - - -class CEnvSoundscapeTriggerable : public CEnvSoundscape -{ -friend class CTriggerSoundscape; - -public: - DECLARE_CLASS( CEnvSoundscapeTriggerable, CEnvSoundscape ); - DECLARE_DATADESC(); - - CEnvSoundscapeTriggerable(); - - // Overrides the base class's think and prevents it from running at all. - virtual void Think(); - - -private: - - // Passed through from CTriggerSoundscape. - void DelegateStartTouch( CBaseEntity *pEnt ); - void DelegateEndTouch( CBaseEntity *pEnt ); -}; - - -#endif // SOUNDSCAPE_H diff --git a/game/server/soundscape_system.cpp b/game/server/soundscape_system.cpp deleted file mode 100644 index 0f2c058ce..000000000 --- a/game/server/soundscape_system.cpp +++ /dev/null @@ -1,343 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - - -#include "cbase.h" -#include "soundscape_system.h" -#include "soundscape.h" -#include "KeyValues.h" -#include "filesystem.h" -#include "game.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SOUNDSCAPE_MANIFEST_FILE "scripts/soundscapes_manifest.txt" - -CON_COMMAND(soundscape_flush, "Flushes the server & client side soundscapes") -{ - CBasePlayer *pPlayer = ToBasePlayer( UTIL_GetCommandClient() ); - if ( engine->IsDedicatedServer() ) - { - // If it's a dedicated server, only the server console can run this. - if ( pPlayer ) - return; - } - else - { - // If it's a listen server, only the listen server host can run this. - if ( !pPlayer || pPlayer != UTIL_GetListenServerHost() ) - return; - } - - g_SoundscapeSystem.FlushSoundscapes(); // don't bother forgetting about the entities - g_SoundscapeSystem.Init(); - - - if ( engine->IsDedicatedServer() ) - { - // If the ds console typed it, send it to everyone. - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pSendToPlayer = UTIL_PlayerByIndex( i ); - if ( pSendToPlayer ) - engine->ClientCommand( pSendToPlayer->edict(), "cl_soundscape_flush\n" ); - } - } - else - { - engine->ClientCommand( pPlayer->edict(), "cl_soundscape_flush\n" ); - } -} - -CSoundscapeSystem g_SoundscapeSystem( "CSoundscapeSystem" ); - -extern ConVar soundscape_debug; - -void CSoundscapeSystem::AddSoundscapeFile( const char *filename ) -{ - MEM_ALLOC_CREDIT(); - // Open the soundscape data file, and abort if we can't - KeyValues *pKeyValuesData = new KeyValues( filename ); - if ( filesystem->LoadKeyValues( *pKeyValuesData, IFileSystem::TYPE_SOUNDSCAPE, filename, "GAME" ) ) - { - // parse out all of the top level sections and save their names - KeyValues *pKeys = pKeyValuesData; - while ( pKeys ) - { - if ( pKeys->GetFirstSubKey() ) - { - if ( g_pDeveloper->GetBool() ) - { - if ( strstr( pKeys->GetName(), "{" ) ) - { - Msg("Error parsing soundscape file %s after %s\n", filename, m_soundscapeCount>0 ?m_soundscapes.GetStringText( m_soundscapeCount-1 ) : "FIRST" ); - } - } - m_soundscapes.AddString( pKeys->GetName(), m_soundscapeCount ); - - if ( IsX360() ) - { - AddSoundscapeSounds( pKeys, m_soundscapeCount ); - } - m_soundscapeCount++; - } - pKeys = pKeys->GetNextKey(); - } - } - pKeyValuesData->deleteThis(); -} - -CON_COMMAND( sv_soundscape_printdebuginfo, "print soundscapes" ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - g_SoundscapeSystem.PrintDebugInfo(); -} - - -void CSoundscapeSystem::PrintDebugInfo() -{ - Msg( "\n------- SERVER SOUNDSCAPES -------\n" ); - for ( int key=m_soundscapes.First(); key != m_soundscapes.InvalidIndex(); key = m_soundscapes.Next( key ) ) - { - int id = m_soundscapes.GetIDForKey( key ); - const char *pName = m_soundscapes.GetStringForKey( key ); - - Msg( "- %d: %s\n", id, pName ); - } - Msg( "-------- SOUNDSCAPE ENTITIES -----\n" ); - for( int entityIndex = 0; entityIndex < m_soundscapeEntities.Size(); ++entityIndex ) - { - CEnvSoundscape *currentSoundscape = m_soundscapeEntities[entityIndex]; - Msg("- %d: %s x:%.4f y:%.4f z:%.4f\n", - entityIndex, - STRING(currentSoundscape->GetSoundscapeName()), - currentSoundscape->GetAbsOrigin().x, - currentSoundscape->GetAbsOrigin().y, - currentSoundscape->GetAbsOrigin().z - ); - } - Msg( "----------------------------------\n\n" ); -} - -bool CSoundscapeSystem::Init() -{ - m_soundscapeCount = 0; - - const char *mapname = STRING( gpGlobals->mapname ); - const char *mapSoundscapeFilename = NULL; - if ( mapname && *mapname ) - { - mapSoundscapeFilename = UTIL_VarArgs( "scripts/soundscapes_%s.txt", mapname ); - } - - KeyValues *manifest = new KeyValues( SOUNDSCAPE_MANIFEST_FILE ); - if ( filesystem->LoadKeyValues( *manifest, IFileSystem::TYPE_SOUNDSCAPE, SOUNDSCAPE_MANIFEST_FILE, "GAME" ) ) - { - for ( KeyValues *sub = manifest->GetFirstSubKey(); sub != NULL; sub = sub->GetNextKey() ) - { - if ( !Q_stricmp( sub->GetName(), "file" ) ) - { - // Add - AddSoundscapeFile( sub->GetString() ); - if ( mapSoundscapeFilename && FStrEq( sub->GetString(), mapSoundscapeFilename ) ) - { - mapSoundscapeFilename = NULL; // we've already loaded the map's soundscape - } - continue; - } - - Warning( "CSoundscapeSystem::Init: Manifest '%s' with bogus file type '%s', expecting 'file'\n", - SOUNDSCAPE_MANIFEST_FILE, sub->GetName() ); - } - - if ( mapSoundscapeFilename && filesystem->FileExists( mapSoundscapeFilename ) ) - { - AddSoundscapeFile( mapSoundscapeFilename ); - } - } - else - { - Error( "Unable to load manifest file '%s'\n", SOUNDSCAPE_MANIFEST_FILE ); - } - manifest->deleteThis(); - m_activeIndex = -1; - - return true; -} - -void CSoundscapeSystem::FlushSoundscapes( void ) -{ - m_soundscapeCount = 0; - m_soundscapes.ClearStrings(); -} - -void CSoundscapeSystem::Shutdown() -{ - FlushSoundscapes(); - m_soundscapeEntities.RemoveAll(); - m_activeIndex = -1; - - if ( IsX360() ) - { - m_soundscapeSounds.Purge(); - } -} - -void CSoundscapeSystem::LevelInitPreEntity() -{ - g_SoundscapeSystem.Shutdown(); - g_SoundscapeSystem.Init(); -} - -void CSoundscapeSystem::LevelInitPostEntity() -{ - if ( IsX360() ) - { - m_soundscapeSounds.Purge(); - } -} - -int CSoundscapeSystem::GetSoundscapeIndex( const char *pName ) -{ - return m_soundscapes.GetStringID( pName ); -} - -bool CSoundscapeSystem::IsValidIndex( int index ) -{ - if ( index >= 0 && index < m_soundscapeCount ) - return true; - return false; -} - -void CSoundscapeSystem::AddSoundscapeEntity( CEnvSoundscape *pSoundscape ) -{ - if ( m_soundscapeEntities.Find( pSoundscape ) == -1 ) - { - m_soundscapeEntities.AddToTail( pSoundscape ); - } -} - -void CSoundscapeSystem::RemoveSoundscapeEntity( CEnvSoundscape *pSoundscape ) -{ - m_soundscapeEntities.FindAndRemove( pSoundscape ); -} - -void CSoundscapeSystem::FrameUpdatePostEntityThink() -{ - int total = m_soundscapeEntities.Count(); - if ( total > 0 ) - { - if ( !m_soundscapeEntities.IsValidIndex(m_activeIndex) ) - { - m_activeIndex = 0; - } - - // update 2 soundscape entities each tick. (when debugging update - // them all) - int count = soundscape_debug.GetBool() ? total : MIN(2, total); - for ( int i = 0; i < count; i++ ) - { - m_activeIndex++; - m_activeIndex = m_activeIndex % total; - m_soundscapeEntities[m_activeIndex]->Update(); - } - } -} - -void CSoundscapeSystem::AddSoundscapeSounds( KeyValues *pSoundscape, int soundscapeIndex ) -{ - if ( !IsX360() ) - { - return; - } - - int i = m_soundscapeSounds.AddToTail(); - Assert( i == soundscapeIndex ); - - KeyValues *pKey = pSoundscape->GetFirstSubKey(); - while ( pKey ) - { - if ( !Q_strcasecmp( pKey->GetName(), "playlooping" ) ) - { - KeyValues *pAmbientKey = pKey->GetFirstSubKey(); - while ( pAmbientKey ) - { - if ( !Q_strcasecmp( pAmbientKey->GetName(), "wave" ) ) - { - char const *pSoundName = pAmbientKey->GetString(); - m_soundscapeSounds[i].AddToTail( pSoundName ); - } - pAmbientKey = pAmbientKey->GetNextKey(); - } - } - else if ( !Q_strcasecmp( pKey->GetName(), "playrandom" ) ) - { - KeyValues *pRandomKey = pKey->GetFirstSubKey(); - while ( pRandomKey ) - { - if ( !Q_strcasecmp( pRandomKey->GetName(), "rndwave" ) ) - { - KeyValues *pRndWaveKey = pRandomKey->GetFirstSubKey(); - while ( pRndWaveKey ) - { - if ( !Q_strcasecmp( pRndWaveKey->GetName(), "wave" ) ) - { - char const *pSoundName = pRndWaveKey->GetString(); - m_soundscapeSounds[i].AddToTail( pSoundName ); - } - pRndWaveKey = pRndWaveKey->GetNextKey(); - } - } - pRandomKey = pRandomKey->GetNextKey(); - } - } - else if ( !Q_strcasecmp( pKey->GetName(), "playsoundscape" ) ) - { - KeyValues *pPlayKey = pKey->GetFirstSubKey(); - while ( pPlayKey ) - { - if ( !Q_strcasecmp( pPlayKey->GetName(), "name" ) ) - { - char const *pSoundName = pPlayKey->GetString(); - m_soundscapeSounds[i].AddToTail( pSoundName ); - } - pPlayKey = pPlayKey->GetNextKey(); - } - } - pKey = pKey->GetNextKey(); - } -} - -void CSoundscapeSystem::PrecacheSounds( int soundscapeIndex ) -{ - if ( !IsX360() ) - { - return; - } - - if ( !IsValidIndex( soundscapeIndex ) ) - { - return; - } - - int count = m_soundscapeSounds[soundscapeIndex].Count(); - for ( int i=0; i m_soundscapeEntities; - int m_activeIndex; - CUtlVector< CUtlVector< CUtlString > > m_soundscapeSounds; -}; - -extern CSoundscapeSystem g_SoundscapeSystem; - - -#endif // SOUNDSCAPE_SYSTEM_H diff --git a/game/server/spark.h b/game/server/spark.h deleted file mode 100644 index be955e75f..000000000 --- a/game/server/spark.h +++ /dev/null @@ -1,15 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SPARK_H -#define SPARK_H -#ifdef _WIN32 -#pragma once -#endif - -void DoSpark( CBaseEntity *ent, const Vector &location, int nMagnitude, int nTrailLength, bool bPlaySound, const Vector &vecDir ); -#endif // SPARK_H diff --git a/game/server/spotlightend.cpp b/game/server/spotlightend.cpp deleted file mode 100644 index ca6233365..000000000 --- a/game/server/spotlightend.cpp +++ /dev/null @@ -1,52 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Dynamic light at the end of a spotlight -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "spotlightend.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -LINK_ENTITY_TO_CLASS(spotlight_end, CSpotlightEnd); - -IMPLEMENT_SERVERCLASS_ST(CSpotlightEnd, DT_SpotlightEnd) - SendPropFloat(SENDINFO(m_flLightScale), 0, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_Radius), 0, SPROP_NOSCALE), -// SendPropVector(SENDINFO(m_vSpotlightDir), -1, SPROP_NORMAL), -// SendPropVector(SENDINFO(m_vSpotlightOrg), -1, SPROP_COORD), -END_SEND_TABLE() - - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CSpotlightEnd ) - - DEFINE_FIELD( m_flLightScale, FIELD_FLOAT ), - DEFINE_FIELD( m_Radius, FIELD_FLOAT ), - DEFINE_FIELD( m_vSpotlightDir, FIELD_VECTOR ), - DEFINE_FIELD( m_vSpotlightOrg, FIELD_POSITION_VECTOR ), - -END_DATADESC() - - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CSpotlightEnd::Spawn( void ) -{ - Precache(); - m_flLightScale = 100; - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_FLY ); - UTIL_SetSize( this, vec3_origin, vec3_origin ); - AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); -} diff --git a/game/server/spotlightend.h b/game/server/spotlightend.h deleted file mode 100644 index 7e13c136f..000000000 --- a/game/server/spotlightend.h +++ /dev/null @@ -1,47 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Dynamic light at the end of a spotlight -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef SPOTLIGHTEND_H -#define SPOTLIGHTEND_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "baseentity.h" - -class CSpotlightEnd : public CBaseEntity -{ - DECLARE_DATADESC(); -public: - DECLARE_CLASS( CSpotlightEnd, CBaseEntity ); - - void Spawn( void ); - - int ObjectCaps( void ) - { - // Don't save and don't go across transitions - return (BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | FCAP_DONT_SAVE; - } - - DECLARE_SERVERCLASS(); - -public: - CNetworkVar( float, m_flLightScale ); - CNetworkVar( float, m_Radius ); -// CNetworkVector( m_vSpotlightDir ); -// CNetworkVector( m_vSpotlightOrg ); - Vector m_vSpotlightDir; - Vector m_vSpotlightOrg; -}; - -#endif //SPOTLIGHTEND_H - - diff --git a/game/server/sprite_perfmonitor.cpp b/game/server/sprite_perfmonitor.cpp deleted file mode 100644 index 0cc22e756..000000000 --- a/game/server/sprite_perfmonitor.cpp +++ /dev/null @@ -1,95 +0,0 @@ -//====== Copyright 1996-2006, Valve Corporation, All rights reserved. ======= -// -// Purpose: an entity which turns on and off counting and display of the particle -// performance metric -// -//============================================================================= - -#include "cbase.h" -#include "baseentity.h" -#include "entityoutput.h" -#include "convar.h" -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Entity that particle performance measuring -//----------------------------------------------------------------------------- -class CParticlePerformanceMonitor : public CPointEntity -{ - DECLARE_CLASS( CParticlePerformanceMonitor, CPointEntity ); -public: - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - void Spawn( void ); - int UpdateTransmitState( void ); - - // Inputs - void InputTurnOnDisplay( inputdata_t &inputdata ); - void InputTurnOffDisplay( inputdata_t &inputdata ); - void InputStartMeasuring( inputdata_t &inputdata ); - void InputStopMeasuring( inputdata_t &inputdata ); - -private: - CNetworkVar( bool, m_bDisplayPerf ); - CNetworkVar( bool, m_bMeasurePerf ); -}; - -LINK_ENTITY_TO_CLASS( env_particle_performance_monitor, CParticlePerformanceMonitor ); - -BEGIN_DATADESC( CParticlePerformanceMonitor ) - DEFINE_FIELD( m_bDisplayPerf, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bMeasurePerf, FIELD_BOOLEAN ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOnDisplay", InputTurnOnDisplay ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOffDisplay", InputTurnOffDisplay ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartMeasuring", InputStartMeasuring ), - DEFINE_INPUTFUNC( FIELD_VOID, "StopMeasuring", InputStopMeasuring ), -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CParticlePerformanceMonitor, DT_ParticlePerformanceMonitor ) - SendPropInt( SENDINFO(m_bDisplayPerf), 1, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_bMeasurePerf), 1, SPROP_UNSIGNED ), -END_SEND_TABLE() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CParticlePerformanceMonitor::Spawn( void ) -{ - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NONE ); - m_bDisplayPerf = false; - m_bMeasurePerf = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CParticlePerformanceMonitor::UpdateTransmitState() -{ - return SetTransmitState( FL_EDICT_ALWAYS ); -} - -void CParticlePerformanceMonitor::InputTurnOnDisplay( inputdata_t &inputdata ) -{ - m_bDisplayPerf = true; -} - -void CParticlePerformanceMonitor::InputTurnOffDisplay( inputdata_t &inputdata ) -{ - m_bDisplayPerf = false; -} - -void CParticlePerformanceMonitor::InputStartMeasuring( inputdata_t &inputdata ) -{ - m_bMeasurePerf = true; -} - -void CParticlePerformanceMonitor::InputStopMeasuring( inputdata_t &inputdata ) -{ - m_bMeasurePerf = false; -} - diff --git a/game/server/stdafx.cpp b/game/server/stdafx.cpp deleted file mode 100644 index 9020b91ed..000000000 --- a/game/server/stdafx.cpp +++ /dev/null @@ -1,11 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Builds the precompiled header for the game DLL -// -// $NoKeywords: $ -//=============================================================================// - - -#include "cbase.h" - -// NOTE: DO NOT ADD ANY CODE OR HEADERS TO THIS FILE!!! diff --git a/game/server/steamjet.cpp b/game/server/steamjet.cpp deleted file mode 100644 index 3159c3a1d..000000000 --- a/game/server/steamjet.cpp +++ /dev/null @@ -1,130 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements the server side of a steam jet particle system entity. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "steamjet.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//Networking -IMPLEMENT_SERVERCLASS_ST(CSteamJet, DT_SteamJet) - SendPropFloat(SENDINFO(m_SpreadSpeed), 0, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_Speed), 0, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_StartSize), 0, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_EndSize), 0, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_Rate), 0, SPROP_NOSCALE), - SendPropFloat(SENDINFO(m_JetLength), 0, SPROP_NOSCALE), - SendPropInt(SENDINFO(m_bEmit), 1, SPROP_UNSIGNED), - SendPropInt(SENDINFO(m_bFaceLeft), 1, SPROP_UNSIGNED), // For support of legacy env_steamjet, which faced left instead of forward. - SendPropInt(SENDINFO(m_nType), 32, SPROP_UNSIGNED), - SendPropInt( SENDINFO(m_spawnflags), 8, SPROP_UNSIGNED ), - SendPropFloat(SENDINFO(m_flRollSpeed), 0, SPROP_NOSCALE), -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( env_steam, CSteamJet ); -LINK_ENTITY_TO_CLASS( env_steamjet, CSteamJet ); // For support of legacy env_steamjet, which faced left instead of forward. - -//Save/restore -BEGIN_DATADESC( CSteamJet ) - - //Keyvalue fields - DEFINE_KEYFIELD( m_StartSize, FIELD_FLOAT, "StartSize" ), - DEFINE_KEYFIELD( m_EndSize, FIELD_FLOAT, "EndSize" ), - DEFINE_KEYFIELD( m_InitialState, FIELD_BOOLEAN, "InitialState" ), - DEFINE_KEYFIELD( m_nType, FIELD_INTEGER, "Type" ), - DEFINE_KEYFIELD( m_flRollSpeed, FIELD_FLOAT, "RollSpeed" ), - - //Regular fields - DEFINE_FIELD( m_bEmit, FIELD_INTEGER ), - DEFINE_FIELD( m_bFaceLeft, FIELD_BOOLEAN ), - - // Inputs - DEFINE_INPUT( m_JetLength, FIELD_FLOAT, "JetLength" ), - DEFINE_INPUT( m_SpreadSpeed, FIELD_FLOAT, "SpreadSpeed" ), - DEFINE_INPUT( m_Speed, FIELD_FLOAT, "Speed" ), - DEFINE_INPUT( m_Rate, FIELD_FLOAT, "Rate" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - -END_DATADESC() - - -CSteamJet::CSteamJet( void ) -{ - m_flRollSpeed = 8.0f; -} -//----------------------------------------------------------------------------- -// Purpose: Called before spawning, after key values have been set. -//----------------------------------------------------------------------------- -void CSteamJet::Spawn( void ) -{ - Precache(); - - // - // Legacy env_steamjet pointed left instead of forward. - // - if ( FClassnameIs( this, "env_steamjet" )) - { - m_bFaceLeft = true; - } - - if ( m_InitialState ) - { - m_bEmit = true; - } -} - -void CSteamJet::Precache( void ) -{ - PrecacheMaterial( "particle/particle_smokegrenade" ); - PrecacheMaterial( "sprites/heatwave" ); -} - - void CSteamJet::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) - { - if (!pActivator->IsPlayer()) - { - if (useType == USE_ON) - { - m_bEmit = true; - } - else if (useType == USE_OFF) - { - m_bEmit = false; - } - } - } - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for toggling the steam jet on/off. -//----------------------------------------------------------------------------- -void CSteamJet::InputToggle(inputdata_t &data) -{ - m_bEmit = !m_bEmit; -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for turning on the steam jet. -//----------------------------------------------------------------------------- -void CSteamJet::InputTurnOn(inputdata_t &data) -{ - m_bEmit = true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for turning off the steam jet. -//----------------------------------------------------------------------------- -void CSteamJet::InputTurnOff(inputdata_t &data) -{ - m_bEmit = false; -} diff --git a/game/server/steamjet.h b/game/server/steamjet.h deleted file mode 100644 index 8eec5b6fa..000000000 --- a/game/server/steamjet.h +++ /dev/null @@ -1,60 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Defines the server side of a steam jet particle system entity. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef STEAMJET_H -#define STEAMJET_H -#pragma once - -#include "baseparticleentity.h" - -//NOTENOTE: Mirrored in cl_dlls\c_steamjet.cpp -#define STEAM_NORMAL 0 -#define STEAM_HEATWAVE 1 - -//================================================== -// CSteamJet -//================================================== - -class CSteamJet : public CBaseParticleEntity -{ -public: - CSteamJet(); - DECLARE_CLASS( CSteamJet, CBaseParticleEntity ); - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - virtual void Spawn( void ); - virtual void Precache( void ); - -protected: - - // Input handlers. - void InputTurnOn(inputdata_t &data); - void InputTurnOff(inputdata_t &data); - void InputToggle(inputdata_t &data); - -// Stuff from the datatable. -public: - CNetworkVar( float, m_SpreadSpeed ); - CNetworkVar( float, m_Speed ); - CNetworkVar( float, m_StartSize ); - CNetworkVar( float, m_EndSize ); - CNetworkVar( float, m_Rate ); - CNetworkVar( float, m_JetLength ); // Length of the jet. Lifetime is derived from this. - - CNetworkVar( int, m_bEmit ); // Emit particles? - CNetworkVar( bool, m_bFaceLeft ); // For support of legacy env_steamjet, which faced left instead of forward. - bool m_InitialState; - - CNetworkVar( int, m_nType ); // Type of steam (normal, heatwave) - CNetworkVar( float, m_flRollSpeed ); - - virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); -}; - -#endif // STEAMJET_H - diff --git a/game/server/subs.cpp b/game/server/subs.cpp deleted file mode 100644 index 9182726af..000000000 --- a/game/server/subs.cpp +++ /dev/null @@ -1,349 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Frequently used global functions. -// -// $NoKeywords: $ -//=============================================================================// - - -#include "cbase.h" -#include "doors.h" -#include "entitylist.h" -#include "globals.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// Landmark class -void CPointEntity::Spawn( void ) -{ - SetSolid( SOLID_NONE ); -// UTIL_SetSize(this, vec3_origin, vec3_origin); -} - - -class CNullEntity : public CBaseEntity -{ -public: - DECLARE_CLASS( CNullEntity, CBaseEntity ); - - void Spawn( void ); -}; - - -// Null Entity, remove on startup -void CNullEntity::Spawn( void ) -{ - UTIL_Remove( this ); -} -LINK_ENTITY_TO_CLASS(info_null,CNullEntity); - -class CBaseDMStart : public CPointEntity -{ -public: - DECLARE_CLASS( CBaseDMStart, CPointEntity ); - - bool IsTriggered( CBaseEntity *pEntity ); - - DECLARE_DATADESC(); - - string_t m_Master; - -private: -}; - -BEGIN_DATADESC( CBaseDMStart ) - - DEFINE_KEYFIELD( m_Master, FIELD_STRING, "master" ), - -END_DATADESC() - - -// These are the new entry points to entities. -LINK_ENTITY_TO_CLASS(info_player_deathmatch,CBaseDMStart); -LINK_ENTITY_TO_CLASS(info_player_start,CPointEntity); -LINK_ENTITY_TO_CLASS(info_landmark,CPointEntity); - -bool CBaseDMStart::IsTriggered( CBaseEntity *pEntity ) -{ - bool master = UTIL_IsMasterTriggered( m_Master, pEntity ); - - return master; -} - - -// Convenient way to delay removing oneself -void CBaseEntity::SUB_Remove( void ) -{ - if (m_iHealth > 0) - { - // this situation can screw up NPCs who can't tell their entity pointers are invalid. - m_iHealth = 0; - DevWarning( 2, "SUB_Remove called on entity with health > 0\n"); - } - - UTIL_Remove( this ); -} - - -// Convenient way to explicitly do nothing (passed to functions that require a method) -void CBaseEntity::SUB_DoNothing( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: Finds all active entities with the given targetname and calls their -// 'Use' function. -// Input : targetName - Target name to search for. -// pActivator - -// pCaller - -// useType - -// value - -//----------------------------------------------------------------------------- -void FireTargets( const char *targetName, CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - CBaseEntity *pTarget = NULL; - if ( !targetName || !targetName[0] ) - return; - - DevMsg( 2, "Firing: (%s)\n", targetName ); - - for (;;) - { - CBaseEntity *pSearchingEntity = pActivator; - pTarget = gEntList.FindEntityByName( pTarget, targetName, pSearchingEntity, pActivator, pCaller ); - if ( !pTarget ) - break; - - if (!pTarget->IsMarkedForDeletion() ) // Don't use dying ents - { - DevMsg( 2, "[%03d] Found: %s, firing (%s)\n", gpGlobals->tickcount%1000, pTarget->GetDebugName(), targetName ); - pTarget->Use( pActivator, pCaller, useType, value ); - } - } -} - -enum togglemovetypes_t -{ - MOVE_TOGGLE_NONE = 0, - MOVE_TOGGLE_LINEAR = 1, - MOVE_TOGGLE_ANGULAR = 2, -}; - -// Global Savedata for Toggle -BEGIN_DATADESC( CBaseToggle ) - - DEFINE_FIELD( m_toggle_state, FIELD_INTEGER ), - DEFINE_FIELD( m_flMoveDistance, FIELD_FLOAT ), - DEFINE_FIELD( m_flWait, FIELD_FLOAT ), - DEFINE_FIELD( m_flLip, FIELD_FLOAT ), - DEFINE_FIELD( m_vecPosition1, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecPosition2, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecMoveAng, FIELD_VECTOR ), // UNDONE: Position could go through transition, but also angle? - DEFINE_FIELD( m_vecAngle1, FIELD_VECTOR ), // UNDONE: Position could go through transition, but also angle? - DEFINE_FIELD( m_vecAngle2, FIELD_VECTOR ), // UNDONE: Position could go through transition, but also angle? - DEFINE_FIELD( m_flHeight, FIELD_FLOAT ), - DEFINE_FIELD( m_hActivator, FIELD_EHANDLE ), - DEFINE_FIELD( m_vecFinalDest, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecFinalAngle, FIELD_VECTOR ), - DEFINE_FIELD( m_sMaster, FIELD_STRING), - DEFINE_FIELD( m_movementType, FIELD_INTEGER ), // Linear or angular movement? (togglemovetypes_t) - -END_DATADESC() - - -CBaseToggle::CBaseToggle() -{ -#ifdef _DEBUG - // necessary since in debug, we initialize vectors to NAN for debugging - m_vecPosition1.Init(); - m_vecPosition2.Init(); - m_vecAngle1.Init(); - m_vecAngle2.Init(); - m_vecFinalDest.Init(); - m_vecFinalAngle.Init(); -#endif -} - -bool CBaseToggle::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "lip")) - { - m_flLip = atof(szValue); - } - else if (FStrEq(szKeyName, "wait")) - { - m_flWait = atof(szValue); - } - else if (FStrEq(szKeyName, "master")) - { - m_sMaster = AllocPooledString(szValue); - } - else if (FStrEq(szKeyName, "distance")) - { - m_flMoveDistance = atof(szValue); - } - else - return BaseClass::KeyValue( szKeyName, szValue ); - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Calculate m_vecVelocity and m_flNextThink to reach vecDest from -// GetOrigin() traveling at flSpeed. -// Input : Vector vecDest - -// flSpeed - -//----------------------------------------------------------------------------- -void CBaseToggle::LinearMove( const Vector &vecDest, float flSpeed ) -{ - ASSERTSZ(flSpeed != 0, "LinearMove: no speed is defined!"); - - m_vecFinalDest = vecDest; - - m_movementType = MOVE_TOGGLE_LINEAR; - // Already there? - if (vecDest == GetLocalOrigin()) - { - MoveDone(); - return; - } - - // set destdelta to the vector needed to move - Vector vecDestDelta = vecDest - GetLocalOrigin(); - - // divide vector length by speed to get time to reach dest - float flTravelTime = vecDestDelta.Length() / flSpeed; - - // set m_flNextThink to trigger a call to LinearMoveDone when dest is reached - SetMoveDoneTime( flTravelTime ); - - // scale the destdelta vector by the time spent traveling to get velocity - SetLocalVelocity( vecDestDelta / flTravelTime ); -} - - -void CBaseToggle::MoveDone( void ) -{ - switch ( m_movementType ) - { - case MOVE_TOGGLE_LINEAR: - LinearMoveDone(); - break; - case MOVE_TOGGLE_ANGULAR: - AngularMoveDone(); - break; - } - m_movementType = MOVE_TOGGLE_NONE; - BaseClass::MoveDone(); -} -//----------------------------------------------------------------------------- -// Purpose: After moving, set origin to exact final destination, call "move done" function. -//----------------------------------------------------------------------------- -void CBaseToggle::LinearMoveDone( void ) -{ - UTIL_SetOrigin( this, m_vecFinalDest); - SetAbsVelocity( vec3_origin ); - SetMoveDoneTime( -1 ); -} - - -// DVS TODO: obselete, remove? -bool CBaseToggle::IsLockedByMaster( void ) -{ - if (m_sMaster != NULL_STRING && !UTIL_IsMasterTriggered(m_sMaster, m_hActivator)) - return true; - else - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Calculate m_vecVelocity and m_flNextThink to reach vecDest from -// GetLocalOrigin() traveling at flSpeed. Just like LinearMove, but rotational. -// Input : vecDestAngle - -// flSpeed - -//----------------------------------------------------------------------------- -void CBaseToggle::AngularMove( const QAngle &vecDestAngle, float flSpeed ) -{ - ASSERTSZ(flSpeed != 0, "AngularMove: no speed is defined!"); - - m_vecFinalAngle = vecDestAngle; - - m_movementType = MOVE_TOGGLE_ANGULAR; - // Already there? - if (vecDestAngle == GetLocalAngles()) - { - MoveDone(); - return; - } - - // set destdelta to the vector needed to move - QAngle vecDestDelta = vecDestAngle - GetLocalAngles(); - - // divide by speed to get time to reach dest - float flTravelTime = vecDestDelta.Length() / flSpeed; - - const float MinTravelTime = 0.01f; - if ( flTravelTime < MinTravelTime ) - { - // If we only travel for a short time, we can fail WillSimulateGamePhysics() - flTravelTime = MinTravelTime; - flSpeed = vecDestDelta.Length() / flTravelTime; - } - - // set m_flNextThink to trigger a call to AngularMoveDone when dest is reached - SetMoveDoneTime( flTravelTime ); - - // scale the destdelta vector by the time spent traveling to get velocity - SetLocalAngularVelocity( vecDestDelta * (1.0 / flTravelTime) ); -} - - -//----------------------------------------------------------------------------- -// Purpose: After rotating, set angle to exact final angle, call "move done" function. -//----------------------------------------------------------------------------- -void CBaseToggle::AngularMoveDone( void ) -{ - SetLocalAngles( m_vecFinalAngle ); - SetLocalAngularVelocity( vec3_angle ); - SetMoveDoneTime( -1 ); -} - - -float CBaseToggle::AxisValue( int flags, const QAngle &angles ) -{ - if ( FBitSet(flags, SF_DOOR_ROTATE_ROLL) ) - return angles.z; - if ( FBitSet(flags, SF_DOOR_ROTATE_PITCH) ) - return angles.x; - - return angles.y; -} - - -void CBaseToggle::AxisDir( void ) -{ - if ( m_spawnflags & SF_DOOR_ROTATE_ROLL ) - m_vecMoveAng = QAngle( 0, 0, 1 ); // angles are roll - else if ( m_spawnflags & SF_DOOR_ROTATE_PITCH ) - m_vecMoveAng = QAngle( 1, 0, 0 ); // angles are pitch - else - m_vecMoveAng = QAngle( 0, 1, 0 ); // angles are yaw -} - - -float CBaseToggle::AxisDelta( int flags, const QAngle &angle1, const QAngle &angle2 ) -{ - // UNDONE: Use AngleDistance() here? - if ( FBitSet (flags, SF_DOOR_ROTATE_ROLL) ) - return angle1.z - angle2.z; - - if ( FBitSet (flags, SF_DOOR_ROTATE_PITCH) ) - return angle1.x - angle2.x; - - return angle1.y - angle2.y; -} - - diff --git a/game/server/sun.cpp b/game/server/sun.cpp deleted file mode 100644 index 4c11baeff..000000000 --- a/game/server/sun.cpp +++ /dev/null @@ -1,203 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "baseentity.h" -#include "sendproxy.h" -#include "sun_shared.h" -#include "map_utils.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CSun : public CBaseEntity -{ -public: - DECLARE_CLASS( CSun, CBaseEntity ); - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - CSun(); - - virtual void Activate(); - - // Input handlers - void InputTurnOn( inputdata_t &inputdata ); - void InputTurnOff( inputdata_t &inputdata ); - void InputSetColor( inputdata_t &inputdata ); - - virtual int UpdateTransmitState(); - -public: - CNetworkVector( m_vDirection ); - - string_t m_strMaterial; - string_t m_strOverlayMaterial; - - int m_bUseAngles; - float m_flPitch; - float m_flYaw; - - CNetworkVar( int, m_nSize ); // Size of the main core image - CNetworkVar( int, m_nOverlaySize ); // Size for the glow overlay - CNetworkVar( color32, m_clrOverlay ); - CNetworkVar( bool, m_bOn ); - CNetworkVar( int, m_nMaterial ); - CNetworkVar( int, m_nOverlayMaterial ); - CNetworkVar( float, m_flHDRColorScale ); -}; - -IMPLEMENT_SERVERCLASS_ST_NOBASE( CSun, DT_Sun ) - SendPropInt( SENDINFO(m_clrRender), 32, SPROP_UNSIGNED, SendProxy_Color32ToInt ), - SendPropInt( SENDINFO(m_clrOverlay), 32, SPROP_UNSIGNED, SendProxy_Color32ToInt ), - SendPropVector( SENDINFO(m_vDirection), 0, SPROP_NORMAL ), - SendPropInt( SENDINFO(m_bOn), 1, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nSize), 10, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nOverlaySize), 10, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nMaterial), 32, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nOverlayMaterial), 32, SPROP_UNSIGNED ), - SendPropFloat( SENDINFO_NAME( m_flHDRColorScale, HDRColorScale ), 0, SPROP_NOSCALE, 0.0f, 100.0f ), -END_SEND_TABLE() - - -LINK_ENTITY_TO_CLASS( env_sun, CSun ); - - -BEGIN_DATADESC( CSun ) - - DEFINE_FIELD( m_vDirection, FIELD_VECTOR ), - - DEFINE_KEYFIELD( m_bUseAngles, FIELD_INTEGER, "use_angles" ), - DEFINE_KEYFIELD( m_flPitch, FIELD_FLOAT, "pitch" ), - DEFINE_KEYFIELD( m_flYaw, FIELD_FLOAT, "angle" ), - DEFINE_KEYFIELD( m_nSize, FIELD_INTEGER, "size" ), - DEFINE_KEYFIELD( m_clrOverlay, FIELD_COLOR32, "overlaycolor" ), - DEFINE_KEYFIELD( m_nOverlaySize, FIELD_INTEGER, "overlaysize" ), - DEFINE_KEYFIELD( m_strMaterial, FIELD_STRING, "material" ), - DEFINE_KEYFIELD( m_strOverlayMaterial, FIELD_STRING, "overlaymaterial" ), - - // NOT SAVED - // m_nOverlayMaterial - // m_nMaterial - - DEFINE_FIELD( m_bOn, FIELD_BOOLEAN ), - - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - DEFINE_INPUTFUNC( FIELD_COLOR32, "SetColor", InputSetColor ), - - DEFINE_KEYFIELD( m_flHDRColorScale, FIELD_FLOAT, "HDRColorScale" ), -END_DATADESC() - -CSun::CSun() -{ - m_vDirection.Init( 0, 0, 1 ); - - m_bUseAngles = false; - m_flPitch = 0; - m_flYaw = 0; - m_nSize = 16; - - m_bOn = true; - AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); - - m_strMaterial = NULL_STRING; - m_strOverlayMaterial = NULL_STRING; - m_nOverlaySize = -1; -} - -void CSun::Activate() -{ - BaseClass::Activate(); - - // Find our target. - if ( m_bUseAngles ) - { - SetupLightNormalFromProps( GetAbsAngles(), m_flYaw, m_flPitch, m_vDirection.GetForModify() ); - m_vDirection = -m_vDirection.Get(); - } - else - { - CBaseEntity *pEnt = gEntList.FindEntityByName( 0, m_target ); - if( pEnt ) - { - Vector vDirection = GetAbsOrigin() - pEnt->GetAbsOrigin(); - VectorNormalize( vDirection ); - m_vDirection = vDirection; - } - } - - // Default behavior - if ( m_nOverlaySize == -1 ) - { - m_nOverlaySize = m_nSize; - } - - // Cache off our image indices - if ( m_strMaterial == NULL_STRING ) - { - m_strMaterial = AllocPooledString( "sprites/light_glow02_add_noz.vmt" ); - } - else - { - const char *pExtension = V_GetFileExtension( STRING( m_strMaterial ) ); - if ( !pExtension ) - { - char szFixedString[MAX_PATH]; - V_strncpy( szFixedString, STRING( m_strMaterial ), sizeof( szFixedString ) ); - V_strncat( szFixedString, ".vmt", sizeof( szFixedString ) ); - m_strMaterial = AllocPooledString( szFixedString ); - } - } - - if ( m_strOverlayMaterial == NULL_STRING ) - { - m_strOverlayMaterial = AllocPooledString( "sprites/light_glow02_add_noz.vmt" ); - } - else - { - const char *pExtension = V_GetFileExtension( STRING( m_strOverlayMaterial ) ); - if ( !pExtension ) - { - char szFixedString[MAX_PATH]; - V_strncpy( szFixedString, STRING( m_strOverlayMaterial ), sizeof( szFixedString ) ); - V_strncat( szFixedString, ".vmt", sizeof( szFixedString ) ); - m_strOverlayMaterial = AllocPooledString( szFixedString ); - } - } - - m_nMaterial = PrecacheModel( STRING( m_strMaterial ) ); - m_nOverlayMaterial = PrecacheModel( STRING( m_strOverlayMaterial ) ); -} - -void CSun::InputTurnOn( inputdata_t &inputdata ) -{ - if( !m_bOn ) - { - m_bOn = true; - } -} - -void CSun::InputTurnOff( inputdata_t &inputdata ) -{ - if ( m_bOn ) - { - m_bOn = false; - } -} - -void CSun::InputSetColor( inputdata_t &inputdata ) -{ - m_clrRender = inputdata.value.Color32(); -} - -int CSun::UpdateTransmitState() -{ - return SetTransmitState( FL_EDICT_ALWAYS ); -} - - diff --git a/game/server/tanktrain.cpp b/game/server/tanktrain.cpp deleted file mode 100644 index bb08e9870..000000000 --- a/game/server/tanktrain.cpp +++ /dev/null @@ -1,535 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "trains.h" -#include "entitylist.h" -#include "soundenvelope.h" -#include "engine/IEngineSound.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern short g_sModelIndexFireball; -#define SPRITE_FIREBALL "sprites/zerogxplode.vmt" -#define SPRITE_SMOKE "sprites/steam1.vmt" - -void UTIL_RemoveHierarchy( CBaseEntity *pDead ) -{ - if ( !pDead ) - return; - - if ( pDead->edict() ) - { - CBaseEntity *pChild = pDead->FirstMoveChild(); - while ( pChild ) - { - CBaseEntity *pEntity = pChild; - pChild = pChild->NextMovePeer(); - - UTIL_RemoveHierarchy( pEntity ); - } - } - UTIL_Remove( pDead ); -} - -class CFuncTankTrain : public CFuncTrackTrain -{ -public: - DECLARE_CLASS( CFuncTankTrain, CFuncTrackTrain ); - - void Spawn( void ); - - // Filter out damage messages that don't contain blast damage (impervious to other forms of attack) - int OnTakeDamage( const CTakeDamageInfo &info ); - void Event_Killed( const CTakeDamageInfo &info ); - void Blocked( CBaseEntity *pOther ) - { - // FIxme, set speed to zero? - } - DECLARE_DATADESC(); - -private: - - COutputEvent m_OnDeath; -}; - -LINK_ENTITY_TO_CLASS( func_tanktrain, CFuncTankTrain ); - -BEGIN_DATADESC( CFuncTankTrain ) - - // Outputs - DEFINE_OUTPUT(m_OnDeath, "OnDeath"), - -END_DATADESC() - - -void CFuncTankTrain::Spawn( void ) -{ - m_takedamage = true; - BaseClass::Spawn(); -} - -// Filter out damage messages that don't contain blast damage (impervious to other forms of attack) -int CFuncTankTrain::OnTakeDamage( const CTakeDamageInfo &info ) -{ - if ( ! (info.GetDamageType() & DMG_BLAST) ) - return 0; - - return BaseClass::OnTakeDamage( info ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Called when the train is killed. -// Input : pInflictor - What killed us. -// pAttacker - Who killed us. -// flDamage - The damage that the killing blow inflicted. -// bitsDamageType - Bitfield of damage types that were inflicted. -//----------------------------------------------------------------------------- -void CFuncTankTrain::Event_Killed( const CTakeDamageInfo &info ) -{ - m_takedamage = DAMAGE_NO; - m_lifeState = LIFE_DEAD; - - m_OnDeath.FireOutput( info.GetInflictor(), this ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Changes the target entity for a func_tank or tanktrain_ai -//----------------------------------------------------------------------------- -class CTankTargetChange : public CPointEntity -{ -public: - DECLARE_CLASS( CTankTargetChange, CPointEntity ); - - void Precache( void ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - DECLARE_DATADESC(); - -private: - variant_t m_newTarget; - string_t m_newTargetName; -}; - -LINK_ENTITY_TO_CLASS( tanktrain_aitarget, CTankTargetChange ); - -BEGIN_DATADESC( CTankTargetChange ) - - // DEFINE_FIELD( m_newTarget, variant_t ), - DEFINE_KEYFIELD( m_newTargetName, FIELD_STRING, "newtarget" ), - -END_DATADESC() - - -void CTankTargetChange::Precache( void ) -{ - BaseClass::Precache(); - - // This needs to be in Precache so save/load works - m_newTarget.SetString( m_newTargetName ); -} - -void CTankTargetChange::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - CBaseEntity *pTarget = gEntList.FindEntityByName( NULL, m_target, NULL, pActivator, pCaller ); - - // UNDONE: This should use more of the event system - while ( pTarget ) - { - // Change the target over - pTarget->AcceptInput( "TargetEntity", this, this, m_newTarget, 0 ); - pTarget = gEntList.FindEntityByName( pTarget, m_target, NULL, pActivator, pCaller ); - } -} - - -// UNDONE: Should be just a logical entity, but we act as another static sound channel for the train -class CTankTrainAI : public CPointEntity -{ -public: - DECLARE_CLASS( CTankTrainAI, CPointEntity ); - - virtual ~CTankTrainAI( void ); - - void Precache( void ); - void Spawn( void ); - void Activate( void ); - void Think( void ); - - int SoundEnginePitch( void ); - void SoundEngineStart( void ); - void SoundEngineStop( void ); - void SoundShutdown( void ); - - CBaseEntity *FindTarget( string_t target, CBaseEntity *pActivator ); - - DECLARE_DATADESC(); - - // INPUTS - void InputTargetEntity( inputdata_t &inputdata ); - -private: - CHandle m_hTrain; - EHANDLE m_hTargetEntity; - int m_soundPlaying; - - CSoundPatch *m_soundTreads; - CSoundPatch *m_soundEngine; - - string_t m_startSoundName; - string_t m_engineSoundName; - string_t m_movementSoundName; - string_t m_targetEntityName; -}; - -LINK_ENTITY_TO_CLASS( tanktrain_ai, CTankTrainAI ); - -BEGIN_DATADESC( CTankTrainAI ) - - DEFINE_FIELD( m_hTrain, FIELD_EHANDLE), - DEFINE_FIELD( m_hTargetEntity, FIELD_EHANDLE), - DEFINE_FIELD( m_soundPlaying, FIELD_INTEGER), - DEFINE_SOUNDPATCH( m_soundTreads ), - DEFINE_SOUNDPATCH( m_soundEngine ), - - DEFINE_KEYFIELD( m_startSoundName, FIELD_STRING, "startsound" ), - DEFINE_KEYFIELD( m_engineSoundName, FIELD_STRING, "enginesound" ), - DEFINE_KEYFIELD( m_movementSoundName, FIELD_STRING, "movementsound" ), - DEFINE_FIELD( m_targetEntityName, FIELD_STRING), - - // Inputs - DEFINE_INPUTFUNC( FIELD_STRING, "TargetEntity", InputTargetEntity ), - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Purpose: Input handler for setting the target entity by name. -//----------------------------------------------------------------------------- -void CTankTrainAI::InputTargetEntity( inputdata_t &inputdata ) -{ - m_targetEntityName = inputdata.value.StringID(); - m_hTargetEntity = FindTarget( m_targetEntityName, inputdata.pActivator ); - SetNextThink( gpGlobals->curtime ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Finds the first entity in the entity list with the given name. -// Input : target - String ID of the entity to find. -// pActivator - The activating entity if this is called from an input -// or Use handler, NULL otherwise. -//----------------------------------------------------------------------------- -CBaseEntity *CTankTrainAI::FindTarget( string_t target, CBaseEntity *pActivator ) -{ - return gEntList.FindEntityGeneric( NULL, STRING( target ), this, pActivator ); -} - - -CTankTrainAI::~CTankTrainAI( void ) -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - - if ( m_soundTreads ) - { - controller.SoundDestroy( m_soundTreads ); - } - - if ( m_soundEngine ) - { - controller.SoundDestroy( m_soundEngine ); - } -} - -void CTankTrainAI::Precache( void ) -{ - PrecacheScriptSound( STRING( m_startSoundName ) ); - PrecacheScriptSound( STRING( m_engineSoundName ) ); - PrecacheScriptSound( STRING( m_movementSoundName ) ); -} - -int CTankTrainAI::SoundEnginePitch( void ) -{ - CFuncTrackTrain *pTrain = m_hTrain; - - // we know this isn't NULL here - if ( pTrain->GetMaxSpeed() ) - { - return (int)(90 + (fabs(pTrain->GetCurrentSpeed()) * (20) / pTrain->GetMaxSpeed())); - } - return 100; -} - - -void CTankTrainAI::SoundEngineStart( void ) -{ - CFuncTrackTrain *pTrain = m_hTrain; - - SoundEngineStop(); - // play startup sound for train - if ( m_startSoundName != NULL_STRING ) - { - CPASAttenuationFilter filter( pTrain ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_ITEM; - ep.m_pSoundName = STRING(m_startSoundName); - ep.m_flVolume = 1.0f; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, pTrain->entindex(), ep ); - } - - // play the looping sounds using the envelope controller - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - - if ( m_soundTreads ) - { - controller.Play( m_soundTreads, 1.0, 100 ); - } - - if ( m_soundEngine ) - { - controller.Play( m_soundEngine, 0.5, 90 ); - controller.CommandClear( m_soundEngine ); - controller.CommandAdd( m_soundEngine, 0, SOUNDCTRL_CHANGE_PITCH, 1.5, random->RandomInt(130, 145) ); - controller.CommandAdd( m_soundEngine, 1.5, SOUNDCTRL_CHANGE_PITCH, 2, random->RandomInt(105, 115) ); - } - - m_soundPlaying = true; -} - - -void CTankTrainAI::SoundEngineStop( void ) -{ - if ( !m_soundPlaying ) - return; - - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - - if ( m_soundTreads ) - { - controller.SoundFadeOut( m_soundTreads, 0.25 ); - } - - if ( m_soundEngine ) - { - controller.CommandClear( m_soundEngine ); - controller.SoundChangePitch( m_soundEngine, 70, 3.0 ); - } - m_soundPlaying = false; -} - - -void CTankTrainAI::SoundShutdown( void ) -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - if ( m_soundTreads ) - { - controller.Shutdown( m_soundTreads ); - } - - if ( m_soundEngine ) - { - controller.Shutdown( m_soundEngine ); - } - m_soundPlaying = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Set up think and AI -//----------------------------------------------------------------------------- -void CTankTrainAI::Spawn( void ) -{ - Precache(); - m_soundPlaying = false; - m_hTargetEntity = NULL; -} - -void CTankTrainAI::Activate( void ) -{ - BaseClass::Activate(); - - CBaseEntity *pTarget = NULL; - - CFuncTrackTrain *pTrain = NULL; - - if ( m_target != NULL_STRING ) - { - do - { - pTarget = gEntList.FindEntityByName( pTarget, m_target ); - pTrain = dynamic_cast(pTarget); - } while (!pTrain && pTarget); - } - - m_hTrain = pTrain; - - if ( pTrain ) - { - SetNextThink( gpGlobals->curtime + 0.5f ); - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - - if ( m_movementSoundName != NULL_STRING ) - { - CPASAttenuationFilter filter( this, ATTN_NORM * 0.5 ); - m_soundTreads = controller.SoundCreate( filter, pTrain->entindex(), CHAN_STATIC, STRING(m_movementSoundName), ATTN_NORM*0.5 ); - } - if ( m_engineSoundName != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - m_soundEngine = controller.SoundCreate( filter, pTrain->entindex(), CHAN_STATIC, STRING(m_engineSoundName), ATTN_NORM ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Dumb linear serach of the path -// Input : *pStart - starting path node -// &startPosition - starting position -// &destination - position to move close to -// Output : int move direction 1 = forward, -1 = reverse, 0 = stop -//----------------------------------------------------------------------------- -int PathFindDirection( CPathTrack *pStart, const Vector &startPosition, const Vector &destination ) -{ - if ( !pStart ) - return 0; // no path, don't move - - CPathTrack *pPath = pStart->m_pnext; - CPathTrack *pNearest = pStart; - - float nearestDist = (pNearest->GetLocalOrigin() - destination).LengthSqr(); - float length = 0; - float nearestForward = 0, nearestReverse = 0; - - do - { - float dist = (pPath->GetLocalOrigin() - destination).LengthSqr(); - - // This is closer than our current estimate - if ( dist < nearestDist ) - { - nearestDist = dist; - pNearest = pPath; - nearestForward = length; // current path length forward - nearestReverse = 0; // count until we hit the start again - } - CPathTrack *pNext = pPath->m_pnext; - if ( pNext ) - { - // UNDONE: Cache delta in path? - float delta = (pNext->GetLocalOrigin() - pPath->GetLocalOrigin()).LengthSqr(); - length += delta; - // add to current reverse estimate - nearestReverse += delta; - pPath = pNext; - } - else - { - // not a looping path - // traverse back to other end of the path - int fail = 0; - while ( pPath->m_pprevious ) - { - fail++; - // HACKHACK: Don't infinite loop - if ( fail > 256 ) - break; - pPath = pPath->m_pprevious; - } - // don't take the reverse path to old node - nearestReverse = nearestForward + 1; - // dont' take forward path to new node (if we find one) - length = (float)COORD_EXTENT * (float)COORD_EXTENT; // HACKHACK: Max quad length - } - - } while ( pPath != pStart ); - - // UNDONE: Fix this fudge factor - // if you are already at the path, or <100 units away, don't move - if ( pNearest == pStart || (pNearest->GetLocalOrigin() - startPosition).LengthSqr() < 100 ) - return 0; - - if ( nearestForward <= nearestReverse ) - return 1; - - return -1; -} - - -//----------------------------------------------------------------------------- -// Purpose: Find a point on my path near to the target and move toward it -//----------------------------------------------------------------------------- -void CTankTrainAI::Think( void ) -{ - CFuncTrackTrain *pTrain = m_hTrain; - - if ( !pTrain || pTrain->m_lifeState != LIFE_ALIVE ) - { - SoundShutdown(); - if ( pTrain ) - UTIL_RemoveHierarchy( pTrain ); - UTIL_Remove( this ); - return; - } - - int desired = 0; - CBaseEntity *pTarget = m_hTargetEntity; - if ( pTarget ) - { - desired = PathFindDirection( pTrain->m_ppath, pTrain->GetLocalOrigin(), pTarget->GetLocalOrigin() ); - } - - // If the train wants to stop, figure out throttle - // otherwise, just throttle in the indicated direction and let the train logic - // clip the speed - if ( !desired ) - { - if ( pTrain->m_flSpeed > 0 ) - { - desired = -1; - } - else if ( pTrain->m_flSpeed < 0 ) - { - desired = 1; - } - } - - // UNDONE: Align the think time with arrival, and bump this up to a few seconds - SetNextThink( gpGlobals->curtime + 0.5f ); - - if ( desired != 0 ) - { - int wasMoving = (pTrain->m_flSpeed == 0) ? false : true; - // chaser wants train to move, send message - pTrain->SetSpeed( desired ); - int isMoving = (pTrain->m_flSpeed == 0) ? false : true; - - if ( !isMoving && wasMoving ) - { - SoundEngineStop(); - } - else if ( isMoving ) - { - if ( !wasMoving ) - { - SoundEngineStart(); - } - } - } - else - { - SoundEngineStop(); - // UNDONE: Align the think time with arrival, and bump this up to a few seconds - SetNextThink( gpGlobals->curtime + 1.0f ); - } -} diff --git a/game/server/te.cpp b/game/server/te.cpp deleted file mode 100644 index e33a68dc8..000000000 --- a/game/server/te.cpp +++ /dev/null @@ -1,526 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "te.h" -#include "effect_dispatch_data.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// External definitions -void TE_ArmorRicochet( IRecipientFilter& filter, float delay, - const Vector* pos, const Vector* dir ); -void TE_BeamEntPoint( IRecipientFilter& filter, float delay, - int nStartEntity, const Vector *start, int nEndEntity, const Vector* end, int modelindex, int haloindex, int startframe, int framerate, - float life, float width, float endWidth, int fadeLength, float amplitude, - int r, int g, int b, int a, int speed ); -void TE_BeamEnts( IRecipientFilter& filter, float delay, - int start, int end, int modelindex, int haloindex, int startframe, int framerate, - float life, float width, float endWidth, int fadeLength, float amplitude, - int r, int g, int b, int a, int speed ); -void TE_BeamFollow( IRecipientFilter& filter, float delay, - int iEntIndex, int modelIndex, int haloIndex, float life, float width, float endWidth, - float fadeLength,float r, float g, float b, float a ); -void TE_BeamPoints( IRecipientFilter& filter, float delay, - const Vector* start, const Vector* end, int modelindex, int haloindex, int startframe, int framerate, - float life, float width, float endWidth, int fadeLength, float amplitude, - int r, int g, int b, int a, int speed ); -void TE_BeamLaser( IRecipientFilter& filter, float delay, - int start, int end, int modelindex, int haloindex, int startframe, int framerate, - float life, float width, float endWidth, int fadeLength, float amplitude, int r, int g, int b, int a, int speed ); -void TE_BeamRing( IRecipientFilter& filter, float delay, - int start, int end, int modelindex, int haloindex, int startframe, int framerate, - float life, float width, int spread, float amplitude, int r, int g, int b, int a, int speed, int flags = 0 ); -void TE_BeamRingPoint( IRecipientFilter& filter, float delay, - const Vector& center, float start_radius, float end_radius, int modelindex, int haloindex, int startframe, int framerate, - float life, float width, int spread, float amplitude, int r, int g, int b, int a, int speed, int flags = 0 ); -void TE_BeamSpline( IRecipientFilter& filter, float delay, - int points, Vector* rgPoints ); -void TE_BloodStream( IRecipientFilter& filter, float delay, - const Vector* org, const Vector* dir, int r, int g, int b, int a, int amount ); -void TE_BloodSprite( IRecipientFilter& filter, float delay, - const Vector* org, const Vector *dir, int r, int g, int b, int a, int size ); -void TE_BreakModel( IRecipientFilter& filter, float delay, - const Vector& pos, const QAngle &angles, const Vector& size, const Vector& vel, - int modelindex, int randomization, int count, float time, int flags ); -void TE_BSPDecal( IRecipientFilter& filter, float delay, - const Vector* pos, int entity, int index ); -void TE_ProjectDecal( IRecipientFilter& filer, float delay, - const Vector* pos, const QAngle *angles, float distance, int index ); -void TE_Bubbles( IRecipientFilter& filter, float delay, - const Vector* mins, const Vector* maxs, float height, int modelindex, int count, float speed ); -void TE_BubbleTrail( IRecipientFilter& filter, float delay, - const Vector* mins, const Vector* maxs, float height, int modelindex, int count, float speed ); -void TE_Decal( IRecipientFilter& filter, float delay, - const Vector* pos, const Vector* start, int entity, int hitbox, int index ); -void TE_DynamicLight( IRecipientFilter& filter, float delay, - const Vector* org, int r, int g, int b, int exponent, float radius, float time, float decay ); -void TE_Explosion( IRecipientFilter& filter, float delay, - const Vector* pos, int modelindex, float scale, int framerate, int flags, int radius, int magnitude, const Vector* normal = NULL, unsigned char materialType = 'C' ); -void TE_ShatterSurface( IRecipientFilter& filter, float delay, - const Vector* pos, const QAngle* angle, const Vector* vForce, const Vector* vForcePos, - float width, float height, float shardsize, ShatterSurface_t surfacetype, - int front_r, int front_g, int front_b, int back_r, int back_g, int back_b); -void TE_GlowSprite( IRecipientFilter& filter, float delay, - const Vector* pos, int modelindex, float life, float size, int brightness ); -void TE_FootprintDecal( IRecipientFilter& filter, float delay, const Vector *origin, const Vector* right, - int entity, int index, unsigned char materialType ); -void TE_Fizz( IRecipientFilter& filter, float delay, - const CBaseEntity *ed, int modelindex, int density, int current ); -void TE_KillPlayerAttachments( IRecipientFilter& filter, float delay, - int player ); -void TE_LargeFunnel( IRecipientFilter& filter, float delay, - const Vector* pos, int modelindex, int reversed ); -void TE_MetalSparks( IRecipientFilter& filter, float delay, - const Vector* pos, const Vector* dir ); -void TE_EnergySplash( IRecipientFilter& filter, float delay, - const Vector* pos, const Vector* dir, bool bExplosive ); -void TE_PlayerDecal( IRecipientFilter& filter, float delay, - const Vector* pos, int player, int entity ); -void TE_ShowLine( IRecipientFilter& filter, float delay, - const Vector* start, const Vector* end ); -void TE_Smoke( IRecipientFilter& filter, float delay, - const Vector* pos, int modelindex, float scale, int framerate ); -void TE_Sparks( IRecipientFilter& filter, float delay, - const Vector* pos, int nMagnitude, int nTrailLength, const Vector *pDir ); -void TE_Sprite( IRecipientFilter& filter, float delay, - const Vector* pos, int modelindex, float size, int brightness ); -void TE_SpriteSpray( IRecipientFilter& filter, float delay, - const Vector* pos, const Vector* dir, int modelindex, int speed, float noise, int count ); -void TE_WorldDecal( IRecipientFilter& filter, float delay, - const Vector* pos, int index ); -void TE_MuzzleFlash( IRecipientFilter& filter, float delayt, - const Vector &start, const QAngle &angles, float scale, int type ); -void TE_Dust( IRecipientFilter& filter, float delayt, - const Vector &pos, const Vector &dir, float size, float speed ); -void TE_DispatchEffect( IRecipientFilter& filter, float delay, - const Vector &pos, const char *pName, const CEffectData &data ); -void TE_PhysicsProp( IRecipientFilter& filter, float delay, - int modelindex, int skin, const Vector& pos, const QAngle &angles, const Vector& vel, int flags, int effects ); -void TE_ClientProjectile( IRecipientFilter& filter, float delay, - const Vector* vecOrigin, const Vector* vecVelocity, int modelindex, int lifetime, CBaseEntity *pOwner ); - -#ifdef HL2_DLL -void TE_GaussExplosion( IRecipientFilter& filter, float delayt, - const Vector &pos, const Vector &dir, int type ); -#endif - -class CTempEntsSystem : public ITempEntsSystem -{ -private: - //----------------------------------------------------------------------------- - // Purpose: Returning true means don't even call TE func - // Input : filter - - // *suppress_host - - // Output : static bool - //----------------------------------------------------------------------------- - bool SuppressTE( IRecipientFilter& filter ) - { - if ( GetSuppressHost() ) - { - CRecipientFilter& _filter = (( CRecipientFilter & )filter); - - if ( !_filter.IgnorePredictionCull() ) - { - _filter.RemoveRecipient( (CBasePlayer *)GetSuppressHost() ); - } - - if ( !_filter.GetRecipientCount() ) - { - // Suppress it - return true; - } - } - - // There's at least one recipient - return false; - } -public: - - virtual void ArmorRicochet( IRecipientFilter& filter, float delay, - const Vector* pos, const Vector* dir ) - { - if ( !SuppressTE( filter ) ) - { - TE_ArmorRicochet( filter, delay, pos, dir ); - } - } - - virtual void BeamEntPoint( IRecipientFilter& filter, float delay, - int nStartEntity, const Vector *pStart, int nEndEntity, const Vector* pEnd, - int modelindex, int haloindex, int startframe, int framerate, - float life, float width, float endWidth, int fadeLength, float amplitude, - int r, int g, int b, int a, int speed ) - { - if ( !SuppressTE( filter ) ) - { - TE_BeamEntPoint( filter, delay, nStartEntity, pStart, nEndEntity, pEnd, modelindex, haloindex, startframe, framerate, - life, width, endWidth, fadeLength, amplitude, r, g, b, a, speed ); - } - } - - virtual void BeamEnts( IRecipientFilter& filter, float delay, - int start, int end, int modelindex, int haloindex, int startframe, int framerate, - float life, float width, float endWidth, int fadeLength, float amplitude, - int r, int g, int b, int a, int speed ) - { - if ( !SuppressTE( filter ) ) - { - TE_BeamEnts( filter, delay, - start, end, modelindex, haloindex, startframe, framerate, - life, width, endWidth, fadeLength, amplitude, - r, g, b, a, speed ); - } - } - virtual void BeamFollow( IRecipientFilter& filter, float delay, - int iEntIndex, int modelIndex, int haloIndex, float life, float width, float endWidth, - float fadeLength, float r, float g, float b, float a ) - { - if ( !SuppressTE( filter ) ) - { - TE_BeamFollow( filter, delay, - iEntIndex, modelIndex, haloIndex, life, width, endWidth, fadeLength, - r, g, b, a ); - } - } - virtual void BeamPoints( IRecipientFilter& filter, float delay, - const Vector* start, const Vector* end, int modelindex, int haloindex, int startframe, int framerate, - float life, float width, float endWidth, int fadeLength, float amplitude, - int r, int g, int b, int a, int speed ) - { - if ( !SuppressTE( filter ) ) - { - TE_BeamPoints( filter, delay, - start, end, modelindex, haloindex, startframe, framerate, - life, width, endWidth, fadeLength, amplitude, - r, g, b, a, speed ); - } - } - virtual void BeamLaser( IRecipientFilter& filter, float delay, - int start, int end, int modelindex, int haloindex, int startframe, int framerate, - float life, float width, float endWidth, int fadeLength, float amplitude, int r, int g, int b, int a, int speed ) - { - if ( !SuppressTE( filter ) ) - { - TE_BeamLaser( filter, delay, - start, end, modelindex, haloindex, startframe, framerate, - life, width, endWidth, fadeLength, amplitude, r, g, b, a, speed ); - } - } - virtual void BeamRing( IRecipientFilter& filter, float delay, - int start, int end, int modelindex, int haloindex, int startframe, int framerate, - float life, float width, int spread, float amplitude, int r, int g, int b, int a, int speed, int flags ) - { - if ( !SuppressTE( filter ) ) - { - TE_BeamRing( filter, delay, - start, end, modelindex, haloindex, startframe, framerate, - life, width, spread, amplitude, r, g, b, a, speed, flags ); - } - } - virtual void BeamRingPoint( IRecipientFilter& filter, float delay, - const Vector& center, float start_radius, float end_radius, int modelindex, int haloindex, int startframe, int framerate, - float life, float width, int spread, float amplitude, int r, int g, int b, int a, int speed, int flags ) - { - if ( !SuppressTE( filter ) ) - { - TE_BeamRingPoint( filter, delay, - center, start_radius, end_radius, modelindex, haloindex, startframe, framerate, - life, width, spread, amplitude, r, g, b, a, speed, flags ); - } - } - virtual void BeamSpline( IRecipientFilter& filter, float delay, - int points, Vector* rgPoints ) - { - if ( !SuppressTE( filter ) ) - { - TE_BeamSpline( filter, delay, points, rgPoints ); - } - } - virtual void BloodStream( IRecipientFilter& filter, float delay, - const Vector* org, const Vector* dir, int r, int g, int b, int a, int amount ) - { - if ( !SuppressTE( filter ) ) - { - TE_BloodStream( filter, delay, org, dir, r, g, b, a, amount ); - } - } - virtual void BloodSprite( IRecipientFilter& filter, float delay, - const Vector* org, const Vector *dir, int r, int g, int b, int a, int size ) - { - if ( !SuppressTE( filter ) ) - { - TE_BloodSprite( filter, delay, org, dir, r, g, b, a, size ); - } - } - virtual void BreakModel( IRecipientFilter& filter, float delay, - const Vector& pos, const QAngle &angle, const Vector& size, const Vector& vel, - int modelindex, int randomization, int count, float time, int flags ) - { - if ( !SuppressTE( filter ) ) - { - TE_BreakModel( filter, delay, pos, angle, size, vel, modelindex, randomization, count, time, flags ); - } - } - virtual void BSPDecal( IRecipientFilter& filter, float delay, - const Vector* pos, int entity, int index ) - { - if ( !SuppressTE( filter ) ) - { - TE_BSPDecal( filter, delay, pos, entity, index ); - } - } - - virtual void ProjectDecal( IRecipientFilter& filter, float delay, - const Vector* pos, const QAngle *angles, float distance, int index ) - { - if ( !SuppressTE( filter ) ) - { - TE_ProjectDecal( filter, delay, pos, angles, distance, index ); - } - } - - virtual void Bubbles( IRecipientFilter& filter, float delay, - const Vector* mins, const Vector* maxs, float height, int modelindex, int count, float speed ) - { - if ( !SuppressTE( filter ) ) - { - TE_Bubbles( filter, delay, mins, maxs, height, modelindex, count, speed ); - } - } - virtual void BubbleTrail( IRecipientFilter& filter, float delay, - const Vector* mins, const Vector* maxs, float flWaterZ, int modelindex, int count, float speed ) - { - if ( !SuppressTE( filter ) ) - { - TE_BubbleTrail( filter, delay, mins, maxs, flWaterZ, modelindex, count, speed ); - } - } - virtual void Decal( IRecipientFilter& filter, float delay, - const Vector* pos, const Vector* start, int entity, int hitbox, int index ) - { - if ( !SuppressTE( filter ) ) - { - TE_Decal( filter, delay, pos, start, entity, hitbox, index ); - } - } - virtual void DynamicLight( IRecipientFilter& filter, float delay, - const Vector* org, int r, int g, int b, int exponent, float radius, float time, float decay ) - { - if ( !SuppressTE( filter ) ) - { - TE_DynamicLight( filter, delay, org, r, g, b, exponent, radius, time, decay ); - } - } - virtual void Explosion( IRecipientFilter& filter, float delay, - const Vector* pos, int modelindex, float scale, int framerate, int flags, int radius, int magnitude, const Vector* normal = NULL, unsigned char materialType = 'C' ) - { - if ( !SuppressTE( filter ) ) - { - TE_Explosion( filter, delay, pos, modelindex, scale, framerate, flags, radius, magnitude, normal, materialType ); - } - } - virtual void ShatterSurface( IRecipientFilter& filter, float delay, - const Vector* pos, const QAngle* angle, const Vector* vForce, const Vector* vForcePos, - float width, float height, float shardsize, ShatterSurface_t surfacetype, - int front_r, int front_g, int front_b, int back_r, int back_g, int back_b) - { - if ( !SuppressTE( filter ) ) - { - TE_ShatterSurface( filter, delay, pos, angle, vForce, vForcePos, width, height, shardsize, surfacetype, - front_r, front_g, front_b, back_r, back_g, back_b ); - } - } - virtual void GlowSprite( IRecipientFilter& filter, float delay, - const Vector* pos, int modelindex, float life, float size, int brightness ) - { - if ( !SuppressTE( filter ) ) - { - TE_GlowSprite( filter, delay, pos, modelindex, life, size, brightness ); - } - } - virtual void FootprintDecal( IRecipientFilter& filter, float delay, const Vector *origin, const Vector* right, - int entity, int index, unsigned char materialType ) - { - if ( !SuppressTE( filter ) ) - { - TE_FootprintDecal( filter, delay, origin, right, - entity, index, materialType ); - } - } - virtual void Fizz( IRecipientFilter& filter, float delay, - const CBaseEntity *ed, int modelindex, int density, int current ) - { - if ( !SuppressTE( filter ) ) - { - TE_Fizz( filter, delay, - ed, modelindex, density, current ); - } - } - virtual void KillPlayerAttachments( IRecipientFilter& filter, float delay, - int player ) - { - if ( !SuppressTE( filter ) ) - { - TE_KillPlayerAttachments( filter, delay, player ); - } - } - virtual void LargeFunnel( IRecipientFilter& filter, float delay, - const Vector* pos, int modelindex, int reversed ) - { - if ( !SuppressTE( filter ) ) - { - TE_LargeFunnel( filter, delay, pos, modelindex, reversed ); - } - } - virtual void MetalSparks( IRecipientFilter& filter, float delay, - const Vector* pos, const Vector* dir ) - { - if ( !SuppressTE( filter ) ) - { - TE_MetalSparks( filter, delay, pos, dir ); - } - } - virtual void EnergySplash( IRecipientFilter& filter, float delay, - const Vector* pos, const Vector* dir, bool bExplosive ) - { - if ( !SuppressTE( filter ) ) - { - TE_EnergySplash( filter, delay, - pos, dir, bExplosive ); - } - } - virtual void PlayerDecal( IRecipientFilter& filter, float delay, - const Vector* pos, int player, int entity ) - { - if ( !SuppressTE( filter ) ) - { - TE_PlayerDecal( filter, delay, - pos, player, entity ); - } - } - virtual void ShowLine( IRecipientFilter& filter, float delay, - const Vector* start, const Vector* end ) - { - if ( !SuppressTE( filter ) ) - { - TE_ShowLine( filter, delay, - start, end ); - } - } - virtual void Smoke( IRecipientFilter& filter, float delay, - const Vector* pos, int modelindex, float scale, int framerate ) - { - if ( !SuppressTE( filter ) ) - { - TE_Smoke( filter, delay, - pos, modelindex, scale, framerate ); - } - } - virtual void Sparks( IRecipientFilter& filter, float delay, - const Vector* pos, int nMagnitude, int nTrailLength, const Vector *pDir ) - { - if ( !SuppressTE( filter ) ) - { - TE_Sparks( filter, delay, - pos, nMagnitude, nTrailLength, pDir ); - } - } - virtual void Sprite( IRecipientFilter& filter, float delay, - const Vector* pos, int modelindex, float size, int brightness ) - { - if ( !SuppressTE( filter ) ) - { - TE_Sprite( filter, delay, - pos, modelindex, size, brightness ); - } - } - virtual void SpriteSpray( IRecipientFilter& filter, float delay, - const Vector* pos, const Vector* dir, int modelindex, int speed, float noise, int count ) - { - if ( !SuppressTE( filter ) ) - { - TE_SpriteSpray( filter, delay, - pos, dir, modelindex, speed, noise, count ); - } - } - virtual void WorldDecal( IRecipientFilter& filter, float delay, - const Vector* pos, int index ) - { - if ( !SuppressTE( filter ) ) - { - TE_WorldDecal( filter, delay, - pos, index ); - } - } - virtual void MuzzleFlash( IRecipientFilter& filter, float delay, - const Vector &start, const QAngle &angles, float scale, int type ) - { - if ( !SuppressTE( filter ) ) - { - TE_MuzzleFlash( filter, delay, - start, angles, scale, type ); - } - } - virtual void Dust( IRecipientFilter& filter, float delay, - const Vector &pos, const Vector &dir, float size, float speed ) - { - if ( !SuppressTE( filter ) ) - { - TE_Dust( filter, delay, - pos, dir, size, speed ); - } - } - virtual void GaussExplosion( IRecipientFilter& filter, float delay, - const Vector &pos, const Vector &dir, int type ) - { -#ifdef HL2_DLL - if ( !SuppressTE( filter ) ) - { - TE_GaussExplosion( filter, delay, pos, dir, type ); - } -#endif - } - - virtual void DispatchEffect( IRecipientFilter& filter, float delay, - const Vector &pos, const char *pName, const CEffectData &data ) - { - if ( !SuppressTE( filter ) ) - { - TE_DispatchEffect( filter, delay, pos, pName, data ); - } - } - - virtual void PhysicsProp( IRecipientFilter& filter, float delay, int modelindex, int skin, - const Vector& pos, const QAngle &angles, const Vector& vel, int flags, int effects ) - { - if ( !SuppressTE( filter ) ) - { - TE_PhysicsProp( filter, delay, modelindex, skin, pos, angles, vel, flags, effects ); - } - } - - // For playback from external tools - virtual void TriggerTempEntity( KeyValues *pKeyValues ) - { - Assert(0); - } - - virtual void ClientProjectile( IRecipientFilter& filter, float delay, - const Vector* vecOrigin, const Vector* vecVelocity, int modelindex, int lifetime, CBaseEntity *pOwner ) - { - if ( !SuppressTE( filter ) ) - { - TE_ClientProjectile( filter, delay, vecOrigin, vecVelocity, modelindex, lifetime, pOwner ); - } - } -}; - -static CTempEntsSystem g_TESystem; -// Expose to rest of engine -ITempEntsSystem *te = &g_TESystem; diff --git a/game/server/te.h b/game/server/te.h deleted file mode 100644 index acd8e00c5..000000000 --- a/game/server/te.h +++ /dev/null @@ -1,17 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $NoKeywords: $ -//=============================================================================// - -#if !defined( TE_H ) -#define TE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "itempents.h" - -#endif // TE_H diff --git a/game/server/te_armorricochet.cpp b/game/server/te_armorricochet.cpp deleted file mode 100644 index a9dd242d0..000000000 --- a/game/server/te_armorricochet.cpp +++ /dev/null @@ -1,142 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Dispatches sparks -//----------------------------------------------------------------------------- -class CTEMetalSparks : public CBaseTempEntity -{ -DECLARE_CLASS( CTEMetalSparks, CBaseTempEntity ); - -public: - CTEMetalSparks( const char *name ); - virtual ~CTEMetalSparks( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkVector( m_vecPos ); - CNetworkVector( m_vecDir ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEMetalSparks::CTEMetalSparks( const char *name ) : - CBaseTempEntity( name ) -{ - m_vecPos.Init(); - m_vecDir.Init(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEMetalSparks::~CTEMetalSparks( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEMetalSparks::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - m_vecPos = current_origin; - - AngleVectors( current_angles, &m_vecDir.GetForModify() ); - - Vector forward; - - m_vecPos += Vector( 0, 0, 24 ); - - AngleVectors( current_angles, &forward ); - forward[2] = 0.0; - VectorNormalize( forward ); - - VectorMA( m_vecPos, 100.0, forward, m_vecPos.GetForModify() ); - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST_NOBASE( CTEMetalSparks, DT_TEMetalSparks) - SendPropVector( SENDINFO(m_vecPos), -1, SPROP_COORD), - SendPropVector( SENDINFO(m_vecDir), -1, SPROP_COORD), -END_SEND_TABLE() - -// Singleton to fire TEMetalSparks objects -static CTEMetalSparks g_TEMetalSparks( "Metal Sparks" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// *pos - -// scale - -//----------------------------------------------------------------------------- -void TE_MetalSparks( IRecipientFilter& filter, float delay, - const Vector* pos, const Vector* dir ) -{ - g_TEMetalSparks.m_vecPos = *pos; - g_TEMetalSparks.m_vecDir = *dir; - - Assert( dir->Length() < 1.01 ); // make sure it's a normal - - // Send it over the wire - g_TEMetalSparks.Create( filter, delay ); -} - -class CTEArmorRicochet : public CTEMetalSparks -{ -DECLARE_CLASS( CTEArmorRicochet, CTEMetalSparks ); - -public: - CTEArmorRicochet( const char *name ) : CTEMetalSparks(name) {} - DECLARE_SERVERCLASS(); -}; - -IMPLEMENT_SERVERCLASS_ST( CTEArmorRicochet, DT_TEArmorRicochet) -END_SEND_TABLE() - -static CTEArmorRicochet g_TEArmorRicochet( "Armor Ricochet" ); -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// *pos - -// scale - -//----------------------------------------------------------------------------- -void TE_ArmorRicochet( IRecipientFilter& filter, float delay, - const Vector* pos, const Vector* dir ) -{ - g_TEArmorRicochet.m_vecPos = *pos; - g_TEArmorRicochet.m_vecDir = *dir; - - // Send it over the wire - g_TEArmorRicochet.Create( filter, delay ); -} diff --git a/game/server/te_basebeam.cpp b/game/server/te_basebeam.cpp deleted file mode 100644 index 5983cf1b7..000000000 --- a/game/server/te_basebeam.cpp +++ /dev/null @@ -1,66 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "te_basebeam.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEBaseBeam::CTEBaseBeam( const char *name ) : - CBaseTempEntity( name ) -{ - m_nModelIndex = 0; - m_nHaloIndex = 0; - m_nStartFrame = 0; - m_nFrameRate = 0; - m_fLife = 0.0; - m_fWidth = 0; - m_fEndWidth = 0; - m_nFadeLength = 0; - m_fAmplitude = 0; - r = g = b = a = 0; - m_nSpeed = 0; - m_nFlags = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEBaseBeam::~CTEBaseBeam( void ) -{ -} - - - -IMPLEMENT_SERVERCLASS_ST_NOBASE( CTEBaseBeam, DT_BaseBeam ) - SendPropModelIndex( SENDINFO(m_nModelIndex) ), - SendPropModelIndex( SENDINFO(m_nHaloIndex) ), - SendPropInt( SENDINFO(m_nStartFrame), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nFrameRate), 8, SPROP_UNSIGNED ), - SendPropFloat( SENDINFO(m_fLife), 8, 0, 0.0, 25.6 ), - SendPropFloat( SENDINFO(m_fWidth), 10, 0, 0.0, 128.0 ), - SendPropFloat( SENDINFO(m_fEndWidth), 10, 0, 0.0, 128.0 ), - SendPropInt( SENDINFO(m_nFadeLength), 8, SPROP_UNSIGNED ), - SendPropFloat( SENDINFO(m_fAmplitude), 8, 0, 0.0, 64.0 ), - SendPropInt( SENDINFO(m_nSpeed), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(r), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(g), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(b), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(a), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nFlags), 32, SPROP_UNSIGNED ), -END_SEND_TABLE() - diff --git a/game/server/te_basebeam.h b/game/server/te_basebeam.h deleted file mode 100644 index 0a18b12b6..000000000 --- a/game/server/te_basebeam.h +++ /dev/null @@ -1,59 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -//----------------------------------------------------------------------------- -// Purpose: Dispatches a beam ring between two entities -//----------------------------------------------------------------------------- -#if !defined( TE_BASEBEAM_H ) -#define TE_BASEBEAM_H -#ifdef _WIN32 -#pragma once -#endif - -#include "basetempentity.h" - -abstract_class CTEBaseBeam : public CBaseTempEntity -{ -public: - - DECLARE_CLASS( CTEBaseBeam, CBaseTempEntity ); - DECLARE_SERVERCLASS(); - - -public: - CTEBaseBeam( const char *name ); - virtual ~CTEBaseBeam( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ) = 0; - -public: - CNetworkVar( int, m_nModelIndex ); - CNetworkVar( int, m_nHaloIndex ); - CNetworkVar( int, m_nStartFrame ); - CNetworkVar( int, m_nFrameRate ); - CNetworkVar( float, m_fLife ); - CNetworkVar( float, m_fWidth ); - CNetworkVar( float, m_fEndWidth ); - CNetworkVar( int, m_nFadeLength ); - CNetworkVar( float, m_fAmplitude ); - CNetworkVar( int, r ); - CNetworkVar( int, g ); - CNetworkVar( int, b ); - CNetworkVar( int, a ); - CNetworkVar( int, m_nSpeed ); - CNetworkVar( int, m_nFlags ); -}; - -EXTERN_SEND_TABLE(DT_BaseBeam); - -#endif // TE_BASEBEAM_H diff --git a/game/server/te_beamentpoint.cpp b/game/server/te_beamentpoint.cpp deleted file mode 100644 index d379dd415..000000000 --- a/game/server/te_beamentpoint.cpp +++ /dev/null @@ -1,154 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" -#include "te_basebeam.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern short g_sModelIndexSmoke; // (in combatweapon.cpp) holds the index for the smoke cloud - -//----------------------------------------------------------------------------- -// Purpose: Dispatches a beam ring between two entities -//----------------------------------------------------------------------------- -class CTEBeamEntPoint : public CTEBaseBeam -{ -public: - DECLARE_CLASS( CTEBeamEntPoint, CTEBaseBeam ); - DECLARE_SERVERCLASS(); - - CTEBeamEntPoint( const char *name ); - virtual ~CTEBeamEntPoint( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - -public: - CNetworkVar( int, m_nStartEntity ); - CNetworkVector( m_vecStartPoint ); - CNetworkVar( int, m_nEndEntity ); - CNetworkVector( m_vecEndPoint ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEBeamEntPoint::CTEBeamEntPoint( const char *name ) : - CTEBaseBeam( name ) -{ - m_nStartEntity = 0; - m_nEndEntity = 0; - m_vecStartPoint.Init(); - m_vecEndPoint.Init(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEBeamEntPoint::~CTEBeamEntPoint( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEBeamEntPoint::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - m_nStartEntity = 1; - - m_nModelIndex = g_sModelIndexSmoke; - m_nStartFrame = 0; - m_nFrameRate = 10; - m_fLife = 2.0; - m_fWidth = 1.0; - m_fAmplitude = 1.0; - r = 0; - g = 63; - b = 127; - a = 150; - m_nSpeed = 1; - - m_vecEndPoint = current_origin; - - Vector forward, right; - - m_vecEndPoint += Vector( 0, 0, 24 ); - - AngleVectors( current_angles, &forward, &right, 0 ); - forward[2] = 0.0; - VectorNormalize( forward ); - - VectorMA( m_vecEndPoint, 50.0, forward, m_vecEndPoint.GetForModify() ); - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST(CTEBeamEntPoint, DT_TEBeamEntPoint) - SendPropInt( SENDINFO(m_nStartEntity), 24, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nEndEntity), 24, SPROP_UNSIGNED ), - SendPropVector( SENDINFO(m_vecStartPoint), -1, SPROP_COORD ), - SendPropVector( SENDINFO(m_vecEndPoint), -1, SPROP_COORD ), -END_SEND_TABLE() - - -// Singleton to fire TEBeamEntPoint objects -static CTEBeamEntPoint g_TEBeamEntPoint( "BeamEntPoint" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// int start - -// *end - -// modelindex - -// startframe - -// framerate - -// msg_dest - -// delay - -// origin - -// recipient - -//----------------------------------------------------------------------------- -void TE_BeamEntPoint( IRecipientFilter& filter, float delay, - int nStartEntity, const Vector *start, int nEndEntity, const Vector* end, - int modelindex, int haloindex, int startframe, int framerate, - float life, float width, float endWidth, int fadeLength, float amplitude, int r, int g, int b, int a, int speed ) -{ - g_TEBeamEntPoint.m_nStartEntity = (nStartEntity > 0) ? (nStartEntity & 0x0FFF) | ((1 & 0xF)<<12) : 0; - g_TEBeamEntPoint.m_nEndEntity = (nEndEntity > 0) ? (nEndEntity & 0x0FFF) | ((1 & 0xF)<<12) : 0; - g_TEBeamEntPoint.m_vecStartPoint = start ? *start : vec3_origin; - g_TEBeamEntPoint.m_vecEndPoint = end ? *end : vec3_origin; - g_TEBeamEntPoint.m_nModelIndex = modelindex; - g_TEBeamEntPoint.m_nHaloIndex = haloindex; - g_TEBeamEntPoint.m_nStartFrame = startframe; - g_TEBeamEntPoint.m_nFrameRate = framerate; - g_TEBeamEntPoint.m_fLife = life; - g_TEBeamEntPoint.m_fWidth = width; - g_TEBeamEntPoint.m_fEndWidth = endWidth; - g_TEBeamEntPoint.m_nFadeLength = fadeLength; - g_TEBeamEntPoint.m_fAmplitude = amplitude; - g_TEBeamEntPoint.m_nSpeed = speed; - g_TEBeamEntPoint.r = r; - g_TEBeamEntPoint.g = g; - g_TEBeamEntPoint.b = b; - g_TEBeamEntPoint.a = a; - - // Send it over the wire - g_TEBeamEntPoint.Create( filter, delay ); -} diff --git a/game/server/te_beaments.cpp b/game/server/te_beaments.cpp deleted file mode 100644 index c1240e1be..000000000 --- a/game/server/te_beaments.cpp +++ /dev/null @@ -1,134 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" -#include "te_basebeam.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern short g_sModelIndexSmoke; // (in combatweapon.cpp) holds the index for the smoke cloud - -//----------------------------------------------------------------------------- -// Purpose: Dispatches a beam between two entities -//----------------------------------------------------------------------------- -class CTEBeamEnts : public CTEBaseBeam -{ -public: - DECLARE_CLASS( CTEBeamEnts, CTEBaseBeam ); - DECLARE_SERVERCLASS(); - - CTEBeamEnts( const char *name ); - virtual ~CTEBeamEnts( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - -public: - CNetworkVar( int, m_nStartEntity ); - CNetworkVar( int, m_nEndEntity ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEBeamEnts::CTEBeamEnts( const char *name ) : - CTEBaseBeam( name ) -{ - m_nStartEntity = 0; - m_nEndEntity = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEBeamEnts::~CTEBeamEnts( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEBeamEnts::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - m_nStartEntity = 1; - m_nEndEntity = 0; - - m_nModelIndex = g_sModelIndexSmoke; - m_nStartFrame = 0; - m_nFrameRate = 10; - m_fLife = 2.0; - m_fWidth = 1.0; - m_fAmplitude = 1; - r = 127; - g = 63; - b = 0; - a = 150; - m_nSpeed = 1; - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST(CTEBeamEnts, DT_TEBeamEnts) - SendPropInt( SENDINFO(m_nStartEntity), 24, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nEndEntity), 24, SPROP_UNSIGNED ), -END_SEND_TABLE() - - -// Singleton to fire TEBeamEnts objects -static CTEBeamEnts g_TEBeamEnts( "BeamEnts" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// int start - -// end - -// modelindex - -// startframe - -// framerate - -// msg_dest - -// delay - -// origin - -// recipient - -//----------------------------------------------------------------------------- -void TE_BeamEnts( IRecipientFilter& filter, float delay, - int start, int end, int modelindex, int haloindex, int startframe, int framerate, - float life, float width, float endWidth, int fadeLength, float amplitude, int r, int g, int b, int a, int speed ) -{ - g_TEBeamEnts.m_nStartEntity = (start & 0x0FFF) | ((1 & 0xF)<<12); - g_TEBeamEnts.m_nEndEntity = (end & 0x0FFF) | ((1 & 0xF)<<12); - g_TEBeamEnts.m_nModelIndex = modelindex; - g_TEBeamEnts.m_nHaloIndex = haloindex; - g_TEBeamEnts.m_nStartFrame = startframe; - g_TEBeamEnts.m_nFrameRate = framerate; - g_TEBeamEnts.m_fLife = life; - g_TEBeamEnts.m_fWidth = width; - g_TEBeamEnts.m_fEndWidth = endWidth; - g_TEBeamEnts.m_nFadeLength = fadeLength; - g_TEBeamEnts.m_fAmplitude = amplitude; - g_TEBeamEnts.m_nSpeed = speed; - g_TEBeamEnts.r = r; - g_TEBeamEnts.g = g; - g_TEBeamEnts.b = b; - g_TEBeamEnts.a = a; - - // Send it over the wire - g_TEBeamEnts.Create( filter, delay ); -} diff --git a/game/server/te_beamfollow.cpp b/game/server/te_beamfollow.cpp deleted file mode 100644 index 07b3c54c2..000000000 --- a/game/server/te_beamfollow.cpp +++ /dev/null @@ -1,112 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" -#include "te_basebeam.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Dispatches a beam ring between two entities -//----------------------------------------------------------------------------- -class CTEBeamFollow : public CTEBaseBeam -{ - DECLARE_CLASS( CTEBeamFollow, CTEBaseBeam ); -public: - - DECLARE_SERVERCLASS(); - - CTEBeamFollow( const char *name ); - virtual ~CTEBeamFollow( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - -public: - - CNetworkVar( int, m_iEntIndex ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEBeamFollow::CTEBeamFollow( const char *name ) : - CTEBaseBeam( name ) -{ - m_iEntIndex = -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEBeamFollow::~CTEBeamFollow( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEBeamFollow::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - m_iEntIndex = 1; -} - -IMPLEMENT_SERVERCLASS_ST(CTEBeamFollow, DT_TEBeamFollow) - SendPropInt( SENDINFO(m_iEntIndex), 24, SPROP_UNSIGNED ), -END_SEND_TABLE() - - -// Singleton to fire TEBeamEntPoint objects -static CTEBeamFollow g_TEBeamFollow( "BeamFollow" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : filter - -// delay - -// iEntIndex - -// modelIndex - -// modelindex - -// haloIndex - -// life - -// width - -// endWidth - -// fadeLength - -// r - -// g - -// b - -// a - -//----------------------------------------------------------------------------- -void TE_BeamFollow( IRecipientFilter& filter, float delay, - int iEntIndex, int modelIndex, int haloIndex, float life, float width, float endWidth, - float fadeLength,float r, float g, float b, float a ) -{ - g_TEBeamFollow.m_iEntIndex = (iEntIndex & 0x0FFF) | ((1 & 0xF)<<12); - g_TEBeamFollow.m_nModelIndex = modelIndex; - g_TEBeamFollow.m_nHaloIndex = haloIndex; - g_TEBeamFollow.m_nStartFrame = 0; - g_TEBeamFollow.m_nFrameRate = 0; - g_TEBeamFollow.m_fLife = life; - g_TEBeamFollow.m_fWidth = width; - g_TEBeamFollow.m_fEndWidth = endWidth; - g_TEBeamFollow.m_nFadeLength = fadeLength; - g_TEBeamFollow.r = r; - g_TEBeamFollow.g = g; - g_TEBeamFollow.b = b; - g_TEBeamFollow.a = a; - - // Send it over the wire - g_TEBeamFollow.Create( filter, delay ); -} diff --git a/game/server/te_beamlaser.cpp b/game/server/te_beamlaser.cpp deleted file mode 100644 index 148e98747..000000000 --- a/game/server/te_beamlaser.cpp +++ /dev/null @@ -1,127 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Beam used for Laser sights. Fades out when it's perpendicular to the viewpoint. -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" -#include "te_basebeam.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern short g_sModelIndexSmoke; // (in combatweapon.cpp) holds the index for the smoke cloud - -//----------------------------------------------------------------------------- -// Purpose: Beam used for Laser sights. Fades out when it's perpendicular to the viewpoint. -//----------------------------------------------------------------------------- -class CTEBeamLaser : public CTEBaseBeam -{ - DECLARE_CLASS( CTEBeamLaser, CTEBaseBeam ); -public: - DECLARE_SERVERCLASS(); - - CTEBeamLaser( const char *name ); - virtual ~CTEBeamLaser( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - -public: - CNetworkVar( int, m_nStartEntity ); - CNetworkVar( int, m_nEndEntity ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEBeamLaser::CTEBeamLaser( const char *name ) : - CTEBaseBeam( name ) -{ - m_nStartEntity = 0; - m_nEndEntity = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEBeamLaser::~CTEBeamLaser( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEBeamLaser::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - m_nStartEntity = 1; - m_nEndEntity = 0; - - m_nModelIndex = g_sModelIndexSmoke; - m_nStartFrame = 0; - m_nFrameRate = 10; - m_fLife = 2.0; - m_fWidth = 1.0; - m_fAmplitude = 1.0; - r = 127; - g = 63; - b = 0; - a = 150; - m_nSpeed = 1; - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST( CTEBeamLaser, DT_TEBeamLaser) - SendPropInt( SENDINFO(m_nStartEntity), 24, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nEndEntity), 24, SPROP_UNSIGNED ), -END_SEND_TABLE() - - -// Singleton to fire TEBeamLaser objects -static CTEBeamLaser g_TEBeamLaser( "BeamLaser" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// *start - -// *end - -// modelindex - -// startframe - -// framerate - -// msg_dest - -// delay - -// origin - -// recipient - -//----------------------------------------------------------------------------- -void TE_BeamLaser( IRecipientFilter& filter, float delay, - int start, int end, int modelindex, int haloindex, int startframe, int framerate, - float life, float width, float endWidth, int fadeLength, float amplitude, int r, int g, int b, int a, int speed ) -{ - g_TEBeamLaser.m_nStartEntity = (start & 0x0FFF) | ((1 & 0xF)<<12); - g_TEBeamLaser.m_nEndEntity = (end & 0x0FFF) | ((1 & 0xF)<<12); - g_TEBeamLaser.m_nModelIndex = modelindex; - g_TEBeamLaser.m_nHaloIndex = haloindex; - g_TEBeamLaser.m_nStartFrame = startframe; - g_TEBeamLaser.m_nFrameRate = framerate; - g_TEBeamLaser.m_fLife = life; - g_TEBeamLaser.m_fWidth = width; - g_TEBeamLaser.m_fEndWidth = endWidth; - g_TEBeamLaser.m_nFadeLength = fadeLength; - g_TEBeamLaser.m_fAmplitude = amplitude; - g_TEBeamLaser.m_nSpeed = speed; - g_TEBeamLaser.r = r; - g_TEBeamLaser.g = g; - g_TEBeamLaser.b = b; - g_TEBeamLaser.a = a; - - // Send it over the wire - g_TEBeamLaser.Create( filter, delay ); -} diff --git a/game/server/te_beampoints.cpp b/game/server/te_beampoints.cpp deleted file mode 100644 index ecdb7216b..000000000 --- a/game/server/te_beampoints.cpp +++ /dev/null @@ -1,144 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" -#include "te_basebeam.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern short g_sModelIndexSmoke; // (in combatweapon.cpp) holds the index for the smoke cloud - -//----------------------------------------------------------------------------- -// Purpose: Dispatches a beam ring between two entities -//----------------------------------------------------------------------------- -class CTEBeamPoints : public CTEBaseBeam -{ -public: - DECLARE_CLASS( CTEBeamPoints, CTEBaseBeam ); - DECLARE_SERVERCLASS(); - - CTEBeamPoints( const char *name ); - virtual ~CTEBeamPoints( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - -public: - CNetworkVector( m_vecStartPoint ); - CNetworkVector( m_vecEndPoint ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEBeamPoints::CTEBeamPoints( const char *name ) : - CTEBaseBeam( name ) -{ - m_vecStartPoint.Init(); - m_vecEndPoint.Init(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEBeamPoints::~CTEBeamPoints( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEBeamPoints::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - m_nModelIndex = g_sModelIndexSmoke; - m_nStartFrame = 0; - m_nFrameRate = 10; - m_fLife = 2.0; - m_fWidth = 1.0; - m_fAmplitude = 1; - r = 0; - g = 63; - b = 127; - a = 150; - m_nSpeed = 1; - - m_vecStartPoint = current_origin; - - Vector forward, right; - - m_vecStartPoint += Vector( 0, 0, 30 ); - - AngleVectors( current_angles, &forward, &right, 0 ); - forward[2] = 0.0; - VectorNormalize( forward ); - - VectorMA( m_vecStartPoint, 75.0, forward, m_vecStartPoint.GetForModify() ); - VectorMA( m_vecStartPoint, 25.0, right, m_vecEndPoint.GetForModify() ); - VectorMA( m_vecStartPoint, -25.0, right, m_vecStartPoint.GetForModify() ); - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST( CTEBeamPoints, DT_TEBeamPoints) - SendPropVector( SENDINFO(m_vecStartPoint), -1, SPROP_COORD ), - SendPropVector( SENDINFO(m_vecEndPoint), -1, SPROP_COORD ), -END_SEND_TABLE() - - -// Singleton to fire TEBeamPoints objects -static CTEBeamPoints g_TEBeamPoints( "BeamPoints" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// *start - -// *end - -// modelindex - -// startframe - -// framerate - -// msg_dest - -// delay - -// origin - -// recipient - -//----------------------------------------------------------------------------- -void TE_BeamPoints( IRecipientFilter& filter, float delay, - const Vector* start, const Vector* end, int modelindex, int haloindex, int startframe, int framerate, - float life, float width, float endWidth, int fadeLength, float amplitude, int r, int g, int b, int a, int speed ) -{ - g_TEBeamPoints.m_vecStartPoint = *start; - g_TEBeamPoints.m_vecEndPoint = *end; - g_TEBeamPoints.m_nModelIndex = modelindex; - g_TEBeamPoints.m_nHaloIndex = haloindex; - g_TEBeamPoints.m_nStartFrame = startframe; - g_TEBeamPoints.m_nFrameRate = framerate; - g_TEBeamPoints.m_fLife = life; - g_TEBeamPoints.m_fWidth = width; - g_TEBeamPoints.m_fEndWidth = endWidth; - g_TEBeamPoints.m_nFadeLength = fadeLength; - g_TEBeamPoints.m_fAmplitude = amplitude; - g_TEBeamPoints.m_nSpeed = speed; - g_TEBeamPoints.r = r; - g_TEBeamPoints.g = g; - g_TEBeamPoints.b = b; - g_TEBeamPoints.a = a; - - // Send it over the wire - g_TEBeamPoints.Create( filter, delay ); -} diff --git a/game/server/te_beamring.cpp b/game/server/te_beamring.cpp deleted file mode 100644 index 21b86addb..000000000 --- a/game/server/te_beamring.cpp +++ /dev/null @@ -1,135 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" -#include "te_basebeam.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern short g_sModelIndexSmoke; // (in combatweapon.cpp) holds the index for the smoke cloud - -//----------------------------------------------------------------------------- -// Purpose: Dispatches a beam ring between two entities -//----------------------------------------------------------------------------- -class CTEBeamRing : public CTEBaseBeam -{ -public: - DECLARE_CLASS( CTEBeamRing, CTEBaseBeam ); - DECLARE_SERVERCLASS(); - - CTEBeamRing( const char *name ); - virtual ~CTEBeamRing( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - -public: - CNetworkVar( int, m_nStartEntity ); - CNetworkVar( int, m_nEndEntity ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEBeamRing::CTEBeamRing( const char *name ) : - CTEBaseBeam( name ) -{ - m_nStartEntity = 0; - m_nEndEntity = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEBeamRing::~CTEBeamRing( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEBeamRing::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - m_nStartEntity = 1; - m_nEndEntity = 0; - - m_nModelIndex = g_sModelIndexSmoke; - m_nStartFrame = 0; - m_nFrameRate = 2; - m_fLife = 10.0; - m_fWidth = 2.0; - m_fAmplitude = 1; - r = 255; - g = 255; - b = 0; - a = 127; - m_nSpeed = 5; - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - - -IMPLEMENT_SERVERCLASS_ST( CTEBeamRing, DT_TEBeamRing) - SendPropInt( SENDINFO(m_nStartEntity), MAX_EDICT_BITS, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nEndEntity), MAX_EDICT_BITS, SPROP_UNSIGNED ), -END_SEND_TABLE() - - -// Singleton to fire TEBeamRing objects -static CTEBeamRing g_TEBeamRing( "BeamRing" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// int start - -// end - -// modelindex - -// startframe - -// framerate - -// msg_dest - -// delay - -// origin - -// recipient - -//----------------------------------------------------------------------------- -void TE_BeamRing( IRecipientFilter& filter, float delay, - int start, int end, int modelindex, int haloindex, int startframe, int framerate, - float life, float width, int spread, float amplitude, int r, int g, int b, int a, int speed, int flags ) -{ - g_TEBeamRing.m_nStartEntity = (start & 0x0FFF) | ((1 & 0xF)<<12); - g_TEBeamRing.m_nEndEntity = (end & 0x0FFF) | ((1 & 0xF)<<12); - g_TEBeamRing.m_nModelIndex = modelindex; - g_TEBeamRing.m_nHaloIndex = haloindex; - g_TEBeamRing.m_nStartFrame = startframe; - g_TEBeamRing.m_nFrameRate = framerate; - g_TEBeamRing.m_fLife = life; - g_TEBeamRing.m_fWidth = width; - g_TEBeamRing.m_fEndWidth = width; - g_TEBeamRing.m_nFadeLength = 0; - g_TEBeamRing.m_fAmplitude = amplitude; - g_TEBeamRing.m_nSpeed = speed; - g_TEBeamRing.r = r; - g_TEBeamRing.g = g; - g_TEBeamRing.b = b; - g_TEBeamRing.a = a; - g_TEBeamRing.m_nFlags = flags; - - // Send it over the wire - g_TEBeamRing.Create( filter, delay ); -} diff --git a/game/server/te_beamringpoint.cpp b/game/server/te_beamringpoint.cpp deleted file mode 100644 index f97eed432..000000000 --- a/game/server/te_beamringpoint.cpp +++ /dev/null @@ -1,124 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" -#include "te_basebeam.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern short g_sModelIndexSmoke; // (in combatweapon.cpp) holds the index for the smoke cloud - -//----------------------------------------------------------------------------- -// Purpose: Dispatches a beam ring between two entities -//----------------------------------------------------------------------------- -class CTEBeamRingPoint : public CTEBaseBeam -{ -public: - DECLARE_CLASS( CTEBeamRingPoint, CTEBaseBeam ); - DECLARE_SERVERCLASS(); - - CTEBeamRingPoint( const char *name ); - virtual ~CTEBeamRingPoint( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - -public: - CNetworkVector( m_vecCenter ); - CNetworkVar( float, m_flStartRadius ); - CNetworkVar( float, m_flEndRadius ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEBeamRingPoint::CTEBeamRingPoint( const char *name ) : - CTEBaseBeam( name ) -{ - m_vecCenter.Init(); - m_flStartRadius = 0.0f; - m_flEndRadius = 0.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEBeamRingPoint::~CTEBeamRingPoint( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEBeamRingPoint::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - m_vecCenter = current_origin; - m_flEndRadius = 256.0f; - m_flStartRadius = 16.0f; - - m_nModelIndex = g_sModelIndexSmoke; - m_nStartFrame = 0; - m_nFrameRate = 2; - m_fLife = 10.0; - m_fWidth = 2.0; - m_fAmplitude = 1; - r = 255; - g = 255; - b = 0; - a = 127; - m_nSpeed = 5; - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - - -IMPLEMENT_SERVERCLASS_ST( CTEBeamRingPoint, DT_TEBeamRingPoint) - SendPropVector( SENDINFO(m_vecCenter), -1, SPROP_COORD ), - SendPropFloat( SENDINFO(m_flStartRadius), 16, SPROP_ROUNDUP, 0.0f, 4096.0f ), - SendPropFloat( SENDINFO(m_flEndRadius), 16, SPROP_ROUNDUP, 0.0f, 4096.0f ), -END_SEND_TABLE() - - -// Singleton to fire TEBeamRingPoint objects -static CTEBeamRingPoint g_TEBeamRingPoint( "BeamRingPoint" ); - -void TE_BeamRingPoint( IRecipientFilter& filter, float delay, - const Vector& center, float start_radius, float end_radius, int modelindex, int haloindex, int startframe, int framerate, - float life, float width, int spread, float amplitude, int r, int g, int b, int a, int speed, int flags ) -{ - g_TEBeamRingPoint.m_vecCenter = center; - g_TEBeamRingPoint.m_flStartRadius = start_radius; - g_TEBeamRingPoint.m_flEndRadius = end_radius; - g_TEBeamRingPoint.m_nModelIndex = modelindex; - g_TEBeamRingPoint.m_nHaloIndex = haloindex; - g_TEBeamRingPoint.m_nStartFrame = startframe; - g_TEBeamRingPoint.m_nFrameRate = framerate; - g_TEBeamRingPoint.m_fLife = life; - g_TEBeamRingPoint.m_fWidth = width; - g_TEBeamRingPoint.m_fEndWidth = width; - g_TEBeamRingPoint.m_nFadeLength = 0; - g_TEBeamRingPoint.m_fAmplitude = amplitude; - g_TEBeamRingPoint.m_nSpeed = speed; - g_TEBeamRingPoint.r = r; - g_TEBeamRingPoint.g = g; - g_TEBeamRingPoint.b = b; - g_TEBeamRingPoint.a = a; - g_TEBeamRingPoint.m_nFlags = flags; - - // Send it over the wire - g_TEBeamRingPoint.Create( filter, delay ); -} diff --git a/game/server/te_beamspline.cpp b/game/server/te_beamspline.cpp deleted file mode 100644 index 77fefce56..000000000 --- a/game/server/te_beamspline.cpp +++ /dev/null @@ -1,134 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define MAX_SPLINE_POINTS 16 -//----------------------------------------------------------------------------- -// Purpose: Dispatches beam spline tempentity -//----------------------------------------------------------------------------- -class CTEBeamSpline : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEBeamSpline, CBaseTempEntity ); - - CTEBeamSpline( const char *name ); - virtual ~CTEBeamSpline( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkArray( Vector, m_vecPoints, MAX_SPLINE_POINTS ); - CNetworkVar( int, m_nPoints ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEBeamSpline::CTEBeamSpline( const char *name ) : - CBaseTempEntity( name ) -{ - int i; - for ( i = 0; i < MAX_SPLINE_POINTS; i++ ) - { - m_vecPoints.GetForModify( i ).Init(); - } - m_nPoints = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEBeamSpline::~CTEBeamSpline( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEBeamSpline::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - m_nPoints = 6; - Vector m_vecStart = current_origin; - - Vector forward, right; - - m_vecStart[2] += 24; - - AngleVectors( current_angles, &forward, &right, 0 ); - forward[2] = 0.0; - VectorNormalize( forward ); - - VectorMA( m_vecStart, 100.0, forward, m_vecStart ); - - VectorMA( m_vecStart, -128.0, right, m_vecStart ); - - for ( int i = 0; i < m_nPoints; i++ ) - { - m_vecPoints.Set( i, m_vecStart ); - VectorMA( m_vecStart, 128/m_nPoints, right, m_vecStart ); - VectorMA( m_vecStart, 30.0/m_nPoints, forward, m_vecStart ); - } - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST_NOBASE(CTEBeamSpline, DT_TEBeamSpline) - SendPropInt( SENDINFO( m_nPoints ), 5, SPROP_UNSIGNED ), - - SendPropArray( - SendPropVector( SENDINFO_ARRAY(m_vecPoints), -1, SPROP_COORD), - m_vecPoints) -END_SEND_TABLE() - - -// Singleton to fire TEBeamSpline objects -static CTEBeamSpline g_TEBeamSpline( "BeamSpline" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// points - -// *points - -//----------------------------------------------------------------------------- -void TE_BeamSpline( IRecipientFilter& filter, float delay, - int points, Vector* rgPoints ) -{ - int i; - g_TEBeamSpline.m_nPoints = points; - for ( i = 0; i < points; i++ ) - { - g_TEBeamSpline.m_vecPoints.Set( i, rgPoints[ i ] ); - } - - for ( ; i < MAX_SPLINE_POINTS; i++ ) - { - g_TEBeamSpline.m_vecPoints.GetForModify( i ).Init(); - } - - // Send it over the wire - g_TEBeamSpline.Create( filter, delay ); -} diff --git a/game/server/te_bloodsprite.cpp b/game/server/te_bloodsprite.cpp deleted file mode 100644 index dbcc961b7..000000000 --- a/game/server/te_bloodsprite.cpp +++ /dev/null @@ -1,151 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern short g_sModelIndexBloodDrop; // (in combatweapon.cpp) holds the sprite index for the initial blood -extern short g_sModelIndexBloodSpray; // (in combatweapon.cpp) holds the sprite index for splattered blood - -//----------------------------------------------------------------------------- -// Purpose: Display's a blood sprite -//----------------------------------------------------------------------------- -class CTEBloodSprite : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEBloodSprite, CBaseTempEntity ); - - CTEBloodSprite( const char *name ); - virtual ~CTEBloodSprite( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkVector( m_vecOrigin ); - CNetworkVector( m_vecDirection ); - CNetworkVar( int, m_nSprayModel ); - CNetworkVar( int, m_nDropModel ); - CNetworkVar( int, r ); - CNetworkVar( int, g ); - CNetworkVar( int, b ); - CNetworkVar( int, a ); - CNetworkVar( int, m_nSize ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEBloodSprite::CTEBloodSprite( const char *name ) : - CBaseTempEntity( name ) -{ - m_vecOrigin.Init(); - m_nSprayModel = 0; - m_nDropModel = 0; - r = 0; - g = 0; - b = 0; - a = 0; - m_nSize = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEBloodSprite::~CTEBloodSprite( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEBloodSprite::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - r = 255; - g = 255; - b = 63; - a = 255; - m_nSize = 16; - m_vecOrigin = current_origin; - - m_nSprayModel = g_sModelIndexBloodSpray; - m_nDropModel = g_sModelIndexBloodDrop; - - Vector forward; - - m_vecOrigin.GetForModify()[2] += 24; - - AngleVectors( current_angles, &forward ); - forward[2] = 0.0; - VectorNormalize( forward ); - - VectorMA( m_vecOrigin, 50.0, forward, m_vecOrigin.GetForModify() ); - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST_NOBASE(CTEBloodSprite, DT_TEBloodSprite) - SendPropVector( SENDINFO(m_vecOrigin), -1, SPROP_COORD), - SendPropVector( SENDINFO(m_vecDirection), -1, SPROP_COORD), - SendPropInt( SENDINFO(r), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(g), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(b), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(a), 8, SPROP_UNSIGNED ), - SendPropModelIndex( SENDINFO(m_nSprayModel) ), - SendPropModelIndex( SENDINFO(m_nDropModel) ), - SendPropInt( SENDINFO(m_nSize), 8, SPROP_UNSIGNED ), -END_SEND_TABLE() - -// Singleton -static CTEBloodSprite g_TEBloodSprite( "Blood Sprite" ); - -//----------------------------------------------------------------------------- -// Purpose: Public interface -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// *org - -// r - -// g - -// b - -// a - -// size - -//----------------------------------------------------------------------------- -void TE_BloodSprite( IRecipientFilter& filter, float delay, - const Vector *org, const Vector *dir, int r, int g, int b, int a, int size ) -{ - // Set up parameters - g_TEBloodSprite.m_vecOrigin = *org; - g_TEBloodSprite.m_vecDirection = *dir; - g_TEBloodSprite.r = r; - g_TEBloodSprite.g = g; - g_TEBloodSprite.b = b; - g_TEBloodSprite.a = a; - g_TEBloodSprite.m_nSize = size; - - // Implicit - g_TEBloodSprite.m_nSprayModel = g_sModelIndexBloodSpray; - g_TEBloodSprite.m_nDropModel = g_sModelIndexBloodDrop; - - // Create it - g_TEBloodSprite.Create( filter, delay ); -} diff --git a/game/server/te_bloodstream.cpp b/game/server/te_bloodstream.cpp deleted file mode 100644 index a5f9787cf..000000000 --- a/game/server/te_bloodstream.cpp +++ /dev/null @@ -1,135 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "te_particlesystem.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Dispatches blood stream tempentity -//----------------------------------------------------------------------------- -class CTEBloodStream : public CTEParticleSystem -{ -public: - DECLARE_CLASS( CTEBloodStream, CTEParticleSystem ); - - CTEBloodStream( const char *name ); - virtual ~CTEBloodStream( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkVector( m_vecDirection ); - CNetworkVar( int, r ); - CNetworkVar( int, g ); - CNetworkVar( int, b ); - CNetworkVar( int, a ); - CNetworkVar( int, m_nAmount ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEBloodStream::CTEBloodStream( const char *name ) : - BaseClass( name ) -{ - m_vecDirection.Init(); - r = 0; - g = 0; - b = 0; - a = 0; - m_nAmount = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEBloodStream::~CTEBloodStream( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEBloodStream::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - r = 247; - g = 0; - b = 0; - a = 255; - m_nAmount = random->RandomInt(50, 150); - m_vecOrigin = current_origin; - - Vector forward; - - m_vecOrigin.GetForModify()[2] += 24; - - AngleVectors( current_angles, &forward ); - forward[2] = 0.0; - VectorNormalize( forward ); - - m_vecOrigin += forward * 50; - - m_vecDirection = UTIL_RandomBloodVector(); - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST(CTEBloodStream, DT_TEBloodStream) - SendPropVector( SENDINFO(m_vecDirection), 11, 0, -10.0, 10.0 ), - SendPropInt( SENDINFO(r), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(g), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(b), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(a), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nAmount), 8, SPROP_UNSIGNED ), -END_SEND_TABLE() - -// Singleton to fire TEBloodStream objects -static CTEBloodStream g_TEBloodStream( "Blood Stream" ); - -//----------------------------------------------------------------------------- -// Purpose: Creates a blood stream -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// *org - -// *dir - -// r - -// g - -// b - -// a - -// amount - -//----------------------------------------------------------------------------- -void TE_BloodStream( IRecipientFilter& filter, float delay, - const Vector* org, const Vector* dir, int r, int g, int b, int a, int amount ) -{ - g_TEBloodStream.m_vecOrigin = *org; - g_TEBloodStream.m_vecDirection = *dir; - g_TEBloodStream.r = r; - g_TEBloodStream.g = g; - g_TEBloodStream.b = b; - g_TEBloodStream.a = a; - g_TEBloodStream.m_nAmount = amount; - - // Send it over the wire - g_TEBloodStream.Create( filter, delay ); -} diff --git a/game/server/te_breakmodel.cpp b/game/server/te_breakmodel.cpp deleted file mode 100644 index 6eb3483af..000000000 --- a/game/server/te_breakmodel.cpp +++ /dev/null @@ -1,146 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" -#include "vstdlib/random.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Dispatches model smash pieces -//----------------------------------------------------------------------------- -class CTEBreakModel : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEBreakModel, CBaseTempEntity ); - - CTEBreakModel( const char *name ); - virtual ~CTEBreakModel( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - virtual void Precache( void ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkVector( m_vecOrigin ); - CNetworkVector( m_vecSize ); - CNetworkVector( m_vecVelocity ); - CNetworkQAngle( m_angRotation ); - CNetworkVar( int, m_nRandomization ); - CNetworkVar( int, m_nModelIndex ); - CNetworkVar( int, m_nCount ); - CNetworkVar( float, m_fTime ); - CNetworkVar( int, m_nFlags ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEBreakModel::CTEBreakModel( const char *name ) : - CBaseTempEntity( name ) -{ - m_vecOrigin.Init(); - m_vecSize.Init(); - m_vecVelocity.Init(); - m_angRotation.Init(); - m_nModelIndex = 0; - m_nRandomization = 0; - m_nCount = 0; - m_fTime = 0.0; - m_nFlags = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEBreakModel::~CTEBreakModel( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTEBreakModel::Precache( void ) -{ - CBaseEntity::PrecacheModel( "models/gibs/hgibs.mdl" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEBreakModel::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - m_nModelIndex = CBaseEntity::PrecacheModel( "models/gibs/hgibs.mdl" ); - m_vecOrigin = current_origin; - m_angRotation = current_angles; - m_vecSize.Init( 16, 16, 16 ); - - m_vecVelocity.Init( random->RandomFloat( -10, 10 ), random->RandomFloat( -10, 10 ), random->RandomFloat( 0, 20 ) ); - - m_nRandomization = 100; - m_nCount = 10; - m_fTime = 5.0; - m_nFlags = 0; - - Vector forward, right; - - m_vecOrigin += Vector( 0, 0, 24 ); - - AngleVectors( current_angles, &forward, &right, 0 ); - forward[2] = 0.0; - VectorNormalize( forward ); - - VectorMA( m_vecOrigin, 50.0, forward, m_vecOrigin.GetForModify() ); - VectorMA( m_vecOrigin, 25.0, right, m_vecOrigin.GetForModify() ); - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST(CTEBreakModel, DT_TEBreakModel) - SendPropVector( SENDINFO(m_vecOrigin), -1, SPROP_COORD), - SendPropAngle( SENDINFO_VECTORELEM2(m_angRotation, 0, x), 13 ), - SendPropAngle( SENDINFO_VECTORELEM2(m_angRotation, 1, y), 13 ), - SendPropAngle( SENDINFO_VECTORELEM2(m_angRotation, 2, z), 13 ), - SendPropVector( SENDINFO(m_vecSize), -1, SPROP_COORD), - SendPropVector( SENDINFO(m_vecVelocity), -1, SPROP_COORD), - SendPropModelIndex( SENDINFO(m_nModelIndex) ), - SendPropInt( SENDINFO(m_nRandomization), 9, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nCount), 8, SPROP_UNSIGNED ), - SendPropFloat( SENDINFO(m_fTime), 10, 0, 0, 102.4 ), - SendPropInt( SENDINFO(m_nFlags), 8, SPROP_UNSIGNED ), -END_SEND_TABLE() - -// Singleton to fire TEBreakModel objects -static CTEBreakModel g_TEBreakModel( "breakmodel" ); - -void TE_BreakModel( IRecipientFilter& filter, float delay, - const Vector& pos, const QAngle& angles, const Vector& size, const Vector& vel, int modelindex, int randomization, - int count, float time, int flags ) -{ - g_TEBreakModel.m_vecOrigin = pos; - g_TEBreakModel.m_angRotation = angles; - g_TEBreakModel.m_vecSize = size; - g_TEBreakModel.m_vecVelocity = vel; - g_TEBreakModel.m_nModelIndex = modelindex; - g_TEBreakModel.m_nRandomization = randomization; - g_TEBreakModel.m_nCount = count; - g_TEBreakModel.m_fTime = time; - g_TEBreakModel.m_nFlags = flags; - - // Send it over the wire - g_TEBreakModel.Create( filter, delay ); -} diff --git a/game/server/te_bspdecal.cpp b/game/server/te_bspdecal.cpp deleted file mode 100644 index 5572b8562..000000000 --- a/game/server/te_bspdecal.cpp +++ /dev/null @@ -1,125 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Dispatches BSP decal tempentity -//----------------------------------------------------------------------------- -class CTEBSPDecal : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEBSPDecal, CBaseTempEntity ); - - CTEBSPDecal( const char *name ); - virtual ~CTEBSPDecal( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkVector( m_vecOrigin ); - CNetworkVar( int, m_nEntity ); - CNetworkVar( int, m_nIndex ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEBSPDecal::CTEBSPDecal( const char *name ) : - CBaseTempEntity( name ) -{ - m_vecOrigin.Init(); - m_nEntity = 0; - m_nIndex = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEBSPDecal::~CTEBSPDecal( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEBSPDecal::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - m_nEntity = 0; - m_nIndex = 0; - m_vecOrigin = current_origin; - - Vector vecEnd; - - Vector forward; - - m_vecOrigin.GetForModify()[2] += 24; - - AngleVectors( current_angles, &forward ); - forward[2] = 0.0; - VectorNormalize( forward ); - - VectorMA( m_vecOrigin, 50.0, forward, m_vecOrigin.GetForModify() ); - VectorMA( m_vecOrigin, 1024.0, forward, vecEnd ); - - trace_t tr; - - UTIL_TraceLine( m_vecOrigin, vecEnd, MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr ); - - m_vecOrigin = tr.endpos; - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - - -IMPLEMENT_SERVERCLASS_ST(CTEBSPDecal, DT_TEBSPDecal) - SendPropVector( SENDINFO(m_vecOrigin), -1, SPROP_COORD), - SendPropInt( SENDINFO(m_nEntity), MAX_EDICT_BITS, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nIndex), 9, SPROP_UNSIGNED ), -END_SEND_TABLE() - - -// Singleton to fire TEBSPDecal objects -static CTEBSPDecal g_TEBSPDecal( "BSP Decal" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// *pos - -// entity - -// index - -// modelindex - -//----------------------------------------------------------------------------- -void TE_BSPDecal( IRecipientFilter& filter, float delay, - const Vector* pos, int entity, int index ) -{ - g_TEBSPDecal.m_vecOrigin = *pos; - g_TEBSPDecal.m_nEntity = entity; - g_TEBSPDecal.m_nIndex = index; - - // Send it over the wire - g_TEBSPDecal.Create( filter, delay ); -} diff --git a/game/server/te_bubbles.cpp b/game/server/te_bubbles.cpp deleted file mode 100644 index ab4f03d33..000000000 --- a/game/server/te_bubbles.cpp +++ /dev/null @@ -1,137 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern short g_sModelIndexBubbles;// holds the index for the bubbles model - -//----------------------------------------------------------------------------- -// Purpose: Dispatches bubbles -//----------------------------------------------------------------------------- -class CTEBubbles : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEBubbles, CBaseTempEntity ); - - CTEBubbles( const char *name ); - virtual ~CTEBubbles( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkVector( m_vecMins ); - CNetworkVector( m_vecMaxs ); - CNetworkVar( float, m_fHeight ); - CNetworkVar( int, m_nModelIndex ); - CNetworkVar( int, m_nCount ); - CNetworkVar( float, m_fSpeed ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEBubbles::CTEBubbles( const char *name ) : - CBaseTempEntity( name ) -{ - m_vecMins.Init(); - m_vecMaxs.Init(); - m_fHeight = 0.0; - m_nModelIndex = 0; - m_nCount = 0; - m_fSpeed = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEBubbles::~CTEBubbles( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEBubbles::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - m_vecMins = current_origin; - - Vector forward; - - m_vecMins.GetForModify()[2] += 24; - - AngleVectors( current_angles, &forward ); - forward[2] = 0.0; - VectorNormalize( forward ); - - VectorMA( m_vecMins, 100.0, forward, m_vecMins.GetForModify() ); - - m_vecMaxs = m_vecMins + Vector( 256, 256, 256 ); - - m_fSpeed = 2; - m_nCount = 50; - m_fHeight = 256; - - m_nModelIndex = g_sModelIndexBubbles; - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST(CTEBubbles, DT_TEBubbles) - SendPropVector( SENDINFO(m_vecMins), -1, SPROP_COORD), - SendPropVector( SENDINFO(m_vecMaxs), -1, SPROP_COORD), - SendPropModelIndex( SENDINFO(m_nModelIndex) ), - SendPropFloat( SENDINFO(m_fHeight ), 17, 0, MIN_COORD_INTEGER, MAX_COORD_INTEGER ), - SendPropInt( SENDINFO(m_nCount), 8, SPROP_UNSIGNED ), - SendPropFloat( SENDINFO(m_fSpeed ), 17, 0, MIN_COORD_INTEGER, MAX_COORD_INTEGER ), -END_SEND_TABLE() - - -// Singleton to fire TEBubbles objects -static CTEBubbles g_TEBubbles( "Bubbles" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// *mins - -// *maxs - -// height - -// modelindex - -// count - -// speed - -//----------------------------------------------------------------------------- -void TE_Bubbles( IRecipientFilter& filter, float delay, - const Vector* mins, const Vector* maxs, float height, int modelindex, int count, float speed ) -{ - g_TEBubbles.m_vecMins = *mins; - g_TEBubbles.m_vecMaxs = *maxs; - g_TEBubbles.m_fHeight = height; - g_TEBubbles.m_nModelIndex = modelindex; - g_TEBubbles.m_nCount = count; - g_TEBubbles.m_fSpeed = speed; - - // Send it over the wire - g_TEBubbles.Create( filter, delay ); -} diff --git a/game/server/te_bubbletrail.cpp b/game/server/te_bubbletrail.cpp deleted file mode 100644 index fae51c7cc..000000000 --- a/game/server/te_bubbletrail.cpp +++ /dev/null @@ -1,140 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern short g_sModelIndexBubbles;// holds the index for the bubbles model - -enum -{ - BUBBLE_TRAIL_COUNT_BITS = 8, - BUBBLE_TRAIL_MAX_COUNT = ( (1 << BUBBLE_TRAIL_COUNT_BITS) - 1 ), -}; - - -//----------------------------------------------------------------------------- -// Purpose: Dispatches bubble trail -//----------------------------------------------------------------------------- -class CTEBubbleTrail : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEBubbleTrail, CBaseTempEntity ); - - CTEBubbleTrail( const char *name ); - virtual ~CTEBubbleTrail( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkVector( m_vecMins ); - CNetworkVector( m_vecMaxs ); - CNetworkVar( float, m_flWaterZ ); - CNetworkVar( int, m_nModelIndex ); - CNetworkVar( int, m_nCount ); - CNetworkVar( float, m_fSpeed ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEBubbleTrail::CTEBubbleTrail( const char *name ) : - CBaseTempEntity( name ) -{ - m_vecMins.Init(); - m_vecMaxs.Init(); - m_flWaterZ = 0.0; - m_nModelIndex = 0; - m_nCount = 0; - m_fSpeed = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEBubbleTrail::~CTEBubbleTrail( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEBubbleTrail::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - m_vecMins = current_origin; - - Vector forward; - - m_vecMins.GetForModify()[2] += 24; - - AngleVectors( current_angles, &forward ); - forward[2] = 0.0; - VectorNormalize( forward ); - - VectorMA( m_vecMins, 100.0, forward, m_vecMins.GetForModify() ); - - m_vecMaxs = m_vecMins + Vector( 256, 256, 256 ); - - m_fSpeed = 8; - m_nCount = 20; - m_flWaterZ = 0; - - m_nModelIndex = g_sModelIndexBubbles; - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST(CTEBubbleTrail, DT_TEBubbleTrail) - SendPropVector( SENDINFO(m_vecMins), -1, SPROP_COORD), - SendPropVector( SENDINFO(m_vecMaxs), -1, SPROP_COORD), - SendPropModelIndex( SENDINFO(m_nModelIndex) ), - SendPropFloat( SENDINFO(m_flWaterZ ), 17, 0, MIN_COORD_INTEGER, MAX_COORD_INTEGER ), - SendPropInt( SENDINFO(m_nCount), BUBBLE_TRAIL_COUNT_BITS, SPROP_UNSIGNED ), - SendPropFloat( SENDINFO(m_fSpeed ), 17, 0, MIN_COORD_INTEGER, MAX_COORD_INTEGER ), -END_SEND_TABLE() - - -// Singleton to fire TEBubbleTrail objects -static CTEBubbleTrail g_TEBubbleTrail( "Bubble Trail" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// *mins - -// *maxs - -// height - -// modelindex - -// count - -// speed - -//----------------------------------------------------------------------------- -void TE_BubbleTrail( IRecipientFilter& filter, float delay, - const Vector* mins, const Vector* maxs, float flWaterZ, int modelindex, int count, float speed ) -{ - g_TEBubbleTrail.m_vecMins = *mins; - g_TEBubbleTrail.m_vecMaxs = *maxs; - g_TEBubbleTrail.m_flWaterZ = flWaterZ; - g_TEBubbleTrail.m_nModelIndex = modelindex; - g_TEBubbleTrail.m_nCount = MIN( count, BUBBLE_TRAIL_MAX_COUNT ); - g_TEBubbleTrail.m_fSpeed = speed; - - // Send it over the wire - g_TEBubbleTrail.Create( filter, delay ); -} diff --git a/game/server/te_clientprojectile.cpp b/game/server/te_clientprojectile.cpp deleted file mode 100644 index 5c29e9dd2..000000000 --- a/game/server/te_clientprojectile.cpp +++ /dev/null @@ -1,117 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#include "basetempentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CTEClientProjectile : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEClientProjectile, CBaseTempEntity ); - - CTEClientProjectile( const char *name ); - virtual ~CTEClientProjectile( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkVector( m_vecOrigin ); - CNetworkVector( m_vecVelocity ); - CNetworkVar( int, m_nModelIndex ); - CNetworkVar( int, m_nLifeTime ); - CNetworkHandle( CBaseEntity, m_hOwner ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEClientProjectile::CTEClientProjectile( const char *name ) : - CBaseTempEntity( name ) -{ - m_vecOrigin.Init(); - m_vecVelocity.Init(); - m_nModelIndex = 0; - m_nLifeTime = 0; - m_hOwner = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEClientProjectile::~CTEClientProjectile( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEClientProjectile::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - m_vecOrigin = current_origin; - - Vector forward; - AngleVectors( current_angles, &forward ); - forward[2] = 0.0; - VectorNormalize( forward ); - - m_vecVelocity = forward * 2048; - - m_nLifeTime = 5; - m_hOwner = NULL; - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST(CTEClientProjectile, DT_TEClientProjectile) - SendPropVector( SENDINFO(m_vecOrigin), -1, SPROP_COORD), - SendPropVector( SENDINFO(m_vecVelocity), -1, SPROP_COORD), - SendPropModelIndex( SENDINFO(m_nModelIndex) ), - SendPropInt( SENDINFO(m_nLifeTime), 6, SPROP_UNSIGNED ), - SendPropEHandle(SENDINFO(m_hOwner)), -END_SEND_TABLE() - - -// Singleton to fire TEClientProjectile objects -static CTEClientProjectile g_TEClientProjectile( "Client Projectile" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// *mins - -// *maxs - -// height - -// modelindex - -// count - -// speed - -//----------------------------------------------------------------------------- -void TE_ClientProjectile( IRecipientFilter& filter, float delay, - const Vector* vecOrigin, const Vector* vecVelocity, int modelindex, int lifetime, CBaseEntity *pOwner ) -{ - g_TEClientProjectile.m_vecOrigin = *vecOrigin; - g_TEClientProjectile.m_vecVelocity = *vecVelocity; - g_TEClientProjectile.m_nModelIndex = modelindex; - g_TEClientProjectile.m_nLifeTime = lifetime; - g_TEClientProjectile.m_hOwner = pOwner; - - // Send it over the wire - g_TEClientProjectile.Create( filter, delay ); -} diff --git a/game/server/te_decal.cpp b/game/server/te_decal.cpp deleted file mode 100644 index b54c37cf1..000000000 --- a/game/server/te_decal.cpp +++ /dev/null @@ -1,131 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Dispatches decal tempentity -//----------------------------------------------------------------------------- -class CTEDecal : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEDecal, CBaseTempEntity ); - - CTEDecal( const char *name ); - virtual ~CTEDecal( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkVector( m_vecOrigin ); - CNetworkVector( m_vecStart ); - CNetworkVar( int, m_nEntity ); - CNetworkVar( int, m_nHitbox ); - CNetworkVar( int, m_nIndex ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEDecal::CTEDecal( const char *name ) : - CBaseTempEntity( name ) -{ - m_vecOrigin.Init(); - m_nEntity = 0; - m_nIndex = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEDecal::~CTEDecal( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEDecal::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - m_nEntity = 0; - m_nIndex = 0; - m_vecOrigin = current_origin; - - Vector vecEnd; - - Vector forward; - - m_vecOrigin.GetForModify()[2] += 24; - - AngleVectors( current_angles, &forward ); - forward[2] = 0.0; - VectorNormalize( forward ); - - VectorMA( m_vecOrigin, 50.0, forward, m_vecOrigin.GetForModify() ); - VectorMA( m_vecOrigin, 1024.0, forward, vecEnd ); - - trace_t tr; - - UTIL_TraceLine( m_vecOrigin, vecEnd, MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr ); - - m_vecOrigin = tr.endpos; - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - - -IMPLEMENT_SERVERCLASS_ST(CTEDecal, DT_TEDecal) - SendPropVector( SENDINFO(m_vecOrigin), -1, SPROP_COORD), - SendPropVector( SENDINFO(m_vecStart), -1, SPROP_COORD), - SendPropInt( SENDINFO(m_nEntity), MAX_EDICT_BITS, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nHitbox), 12, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nIndex), 9, SPROP_UNSIGNED ), -END_SEND_TABLE() - - -// Singleton to fire TEDecal objects -static CTEDecal g_TEDecal( "Entity Decal" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// *pos - -// entity - -// index - -//----------------------------------------------------------------------------- -void TE_Decal( IRecipientFilter& filter, float delay, - const Vector* pos, const Vector* start, int entity, int hitbox, int index ) -{ - Assert( pos && start ); - g_TEDecal.m_vecOrigin = *pos; - g_TEDecal.m_vecStart = *start; - g_TEDecal.m_nEntity = entity; - g_TEDecal.m_nHitbox = hitbox; - g_TEDecal.m_nIndex = index; - - // Send it over the wire - g_TEDecal.Create( filter, delay ); -} diff --git a/game/server/te_dynamiclight.cpp b/game/server/te_dynamiclight.cpp deleted file mode 100644 index 8a36b701b..000000000 --- a/game/server/te_dynamiclight.cpp +++ /dev/null @@ -1,144 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Displays a dynamic light -//----------------------------------------------------------------------------- -class CTEDynamicLight : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEDynamicLight, CBaseTempEntity ); - - CTEDynamicLight( const char *name ); - virtual ~CTEDynamicLight( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkVector( m_vecOrigin ); - CNetworkVar( float, m_fRadius ); - CNetworkVar( int, r ); - CNetworkVar( int, g ); - CNetworkVar( int, b ); - CNetworkVar( int, exponent ); - CNetworkVar( float, m_fTime ); - CNetworkVar( float, m_fDecay ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEDynamicLight::CTEDynamicLight( const char *name ) : - CBaseTempEntity( name ) -{ - m_vecOrigin.Init(); - r = 0; - g = 0; - b = 0; - exponent = 0; - m_fRadius = 0.0; - m_fTime = 0.0; - m_fDecay = 0.0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEDynamicLight::~CTEDynamicLight( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEDynamicLight::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - r = 255; - g = 255; - b = 63; - m_vecOrigin = current_origin; - - m_fRadius = 200; - m_fTime = 2.0; - m_fDecay = 0.0; - - Vector forward; - - m_vecOrigin.GetForModify()[2] += 24; - - AngleVectors( current_angles, &forward ); - forward[2] = 0.0; - VectorNormalize( forward ); - - VectorMA( m_vecOrigin, 50.0, forward, m_vecOrigin.GetForModify() ); - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST(CTEDynamicLight, DT_TEDynamicLight) - SendPropVector( SENDINFO(m_vecOrigin), -1, SPROP_COORD), - SendPropInt( SENDINFO(r), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(g), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(b), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(exponent), 8, 0 ), - SendPropFloat( SENDINFO(m_fRadius), 8, SPROP_ROUNDUP, 0, 2560.0 ), - SendPropFloat( SENDINFO(m_fTime), 8, SPROP_ROUNDDOWN, 0, 25.6 ), - SendPropFloat( SENDINFO(m_fDecay), 8, SPROP_ROUNDDOWN, 0, 2560.0 ), -END_SEND_TABLE() - - -// Singleton -static CTEDynamicLight g_TEDynamicLight( "Dynamic Light" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// *org - -// r - -// g - -// b - -// radius - -// time - -// decay - -//----------------------------------------------------------------------------- -void TE_DynamicLight( IRecipientFilter& filter, float delay, - const Vector* org, int r, int g, int b, int exponent, float radius, float time, float decay ) -{ - // Set up parameters - g_TEDynamicLight.m_vecOrigin = *org; - g_TEDynamicLight.r = r; - g_TEDynamicLight.g = g; - g_TEDynamicLight.b = b; - g_TEDynamicLight.exponent = exponent; - g_TEDynamicLight.m_fRadius = radius; - g_TEDynamicLight.m_fTime = time; - g_TEDynamicLight.m_fDecay = decay; - - // Create it - g_TEDynamicLight.Create( filter, delay ); -} diff --git a/game/server/te_effect_dispatch.cpp b/game/server/te_effect_dispatch.cpp deleted file mode 100644 index 736fd5ff7..000000000 --- a/game/server/te_effect_dispatch.cpp +++ /dev/null @@ -1,86 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" -#include "te_effect_dispatch.h" -#include "networkstringtable_gamedll.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: This TE provides a simple interface to dispatch effects by name using DispatchEffect(). -//----------------------------------------------------------------------------- -class CTEEffectDispatch : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEEffectDispatch, CBaseTempEntity ); - - CTEEffectDispatch( const char *name ); - virtual ~CTEEffectDispatch( void ); - - DECLARE_SERVERCLASS(); - -public: - CEffectData m_EffectData; -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEEffectDispatch::CTEEffectDispatch( const char *name ) : - CBaseTempEntity( name ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEEffectDispatch::~CTEEffectDispatch( void ) -{ -} - -IMPLEMENT_SERVERCLASS_ST( CTEEffectDispatch, DT_TEEffectDispatch ) - - SendPropDataTable( SENDINFO_DT( m_EffectData ), &REFERENCE_SEND_TABLE( DT_EffectData ) ) - -END_SEND_TABLE() - - -// Singleton to fire TEEffectDispatch objects -static CTEEffectDispatch g_TEEffectDispatch( "EffectDispatch" ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void TE_DispatchEffect( IRecipientFilter& filter, float delay, const Vector &pos, const char *pName, const CEffectData &data ) -{ - // Copy the supplied effect data. - g_TEEffectDispatch.m_EffectData = data; - - // Get the entry index in the string table. - g_TEEffectDispatch.m_EffectData.m_iEffectName = g_pStringTableEffectDispatch->AddString( CBaseEntity::IsServer(), pName ); - - // Send it to anyone who can see the effect's origin. - g_TEEffectDispatch.Create( filter, 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void DispatchEffect( const char *pName, const CEffectData &data ) -{ - CPASFilter filter( data.m_vOrigin ); - te->DispatchEffect( filter, 0.0, data.m_vOrigin, pName, data ); -} diff --git a/game/server/te_effect_dispatch.h b/game/server/te_effect_dispatch.h deleted file mode 100644 index 5b453e8c9..000000000 --- a/game/server/te_effect_dispatch.h +++ /dev/null @@ -1,19 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef TE_EFFECT_DISPATCH_H -#define TE_EFFECT_DISPATCH_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "effect_dispatch_data.h" - -void DispatchEffect( const char *pName, const CEffectData &data ); - -#endif // TE_EFFECT_DISPATCH_H diff --git a/game/server/te_energysplash.cpp b/game/server/te_energysplash.cpp deleted file mode 100644 index acba4e653..000000000 --- a/game/server/te_energysplash.cpp +++ /dev/null @@ -1,112 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "te_particlesystem.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Dispatches energy splashes -//----------------------------------------------------------------------------- -class CTEEnergySplash : public CBaseTempEntity -{ -DECLARE_CLASS( CTEEnergySplash, CBaseTempEntity ); - -public: - CTEEnergySplash( const char *name ); - virtual ~CTEEnergySplash( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkVector( m_vecPos ); - CNetworkVector( m_vecDir ); - CNetworkVar( bool, m_bExplosive ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEEnergySplash::CTEEnergySplash( const char *name ) : - CBaseTempEntity( name ) -{ - m_vecPos.Init(); - m_vecDir.Init(); - m_bExplosive = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEEnergySplash::~CTEEnergySplash( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEEnergySplash::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - m_vecPos = current_origin; - - AngleVectors( current_angles, &m_vecDir.GetForModify() ); - - Vector forward; - - m_vecPos.GetForModify()[2] += 24; - - forward = m_vecDir; - forward[2] = 0.0; - VectorNormalize( forward ); - - VectorMA( m_vecPos, 100.0, forward, m_vecPos.GetForModify() ); - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST_NOBASE( CTEEnergySplash, DT_TEEnergySplash) - SendPropVector( SENDINFO(m_vecPos), -1, SPROP_COORD), - SendPropVector( SENDINFO(m_vecDir), -1, SPROP_COORD), - SendPropInt( SENDINFO(m_bExplosive), 1, SPROP_UNSIGNED), -END_SEND_TABLE() - -// Singleton to fire TEEnergySplash objects -static CTEEnergySplash g_TEEnergySplash( "Energy Splash" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// *pos - -// scale - -//----------------------------------------------------------------------------- -void TE_EnergySplash( IRecipientFilter& filter, float delay, - const Vector* pos, const Vector* dir, bool bExplosive ) -{ - g_TEEnergySplash.m_vecPos = *pos; - g_TEEnergySplash.m_vecDir = *dir; - g_TEEnergySplash.m_bExplosive = bExplosive; - - // Send it over the wire - g_TEEnergySplash.Create( filter, delay ); -} diff --git a/game/server/te_explosion.cpp b/game/server/te_explosion.cpp deleted file mode 100644 index dd09c6405..000000000 --- a/game/server/te_explosion.cpp +++ /dev/null @@ -1,132 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "te_particlesystem.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern short g_sModelIndexFireball; // (in combatweapon.cpp) holds the index for the smoke cloud - -//----------------------------------------------------------------------------- -// Purpose: Dispatches explosion tempentity -//----------------------------------------------------------------------------- -class CTEExplosion : public CTEParticleSystem -{ -public: - DECLARE_CLASS( CTEExplosion, CTEParticleSystem ); - DECLARE_SERVERCLASS(); - - CTEExplosion( const char *name ); - virtual ~CTEExplosion( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - -public: - CNetworkVar( int, m_nModelIndex ); - CNetworkVar( float, m_fScale ); - CNetworkVar( int, m_nFrameRate ); - CNetworkVar( int, m_nFlags ); - CNetworkVector( m_vecNormal ); - CNetworkVar( unsigned char, m_chMaterialType ); - CNetworkVar( int, m_nRadius ); - CNetworkVar( int, m_nMagnitude ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEExplosion::CTEExplosion( const char *name ) : - BaseClass( name ) -{ - m_nModelIndex = 0; - m_fScale = 0; - m_nFrameRate = 0; - m_nFlags = 0; - m_vecNormal.Init(); - m_chMaterialType = 'C'; - m_nRadius = 0; - m_nMagnitude = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEExplosion::~CTEExplosion( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEExplosion::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - m_nModelIndex = g_sModelIndexFireball; - m_fScale = 0.5; - m_nFrameRate = 15; - m_nFlags = TE_EXPLFLAG_NONE; - m_vecOrigin = current_origin; - - Vector forward; - - m_vecOrigin.GetForModify()[2] += 24; - - AngleVectors( current_angles, &forward ); - forward[2] = 0.0; - VectorNormalize( forward ); - - m_vecOrigin += forward * 50; - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST(CTEExplosion, DT_TEExplosion) - SendPropModelIndex( SENDINFO(m_nModelIndex) ), - SendPropFloat( SENDINFO(m_fScale ), 9, 0, 0.0, 51.2 ), - SendPropInt( SENDINFO(m_nFrameRate), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nFlags), 8, SPROP_UNSIGNED ), - SendPropVector( SENDINFO(m_vecNormal), -1, SPROP_COORD), - SendPropInt( SENDINFO(m_chMaterialType), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nRadius), 32, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nMagnitude), 32, SPROP_UNSIGNED ), -END_SEND_TABLE() - -// Singleton to fire TEExplosion objects -static CTEExplosion g_TEExplosion( "Explosion" ); - -void TE_Explosion( IRecipientFilter& filter, float delay, - const Vector* pos, int modelindex, float scale, int framerate, int flags, int radius, int magnitude, const Vector* normal, unsigned char materialType ) -{ - g_TEExplosion.m_vecOrigin = *pos; - g_TEExplosion.m_nModelIndex = modelindex; - g_TEExplosion.m_fScale = scale; - g_TEExplosion.m_nFrameRate = framerate; - g_TEExplosion.m_nFlags = flags; - g_TEExplosion.m_nRadius = radius; - g_TEExplosion.m_nMagnitude = magnitude; - - if ( normal ) - g_TEExplosion.m_vecNormal = *normal; - else - g_TEExplosion.m_vecNormal = Vector(0,0,1); - g_TEExplosion.m_chMaterialType = materialType; - - // Send it over the wire - g_TEExplosion.Create( filter, delay ); -} diff --git a/game/server/te_fizz.cpp b/game/server/te_fizz.cpp deleted file mode 100644 index 8c806bbcf..000000000 --- a/game/server/te_fizz.cpp +++ /dev/null @@ -1,112 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Dispatches Fizz tempentity -//----------------------------------------------------------------------------- -class CTEFizz : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEFizz, CBaseTempEntity ); - - CTEFizz( const char *name ); - virtual ~CTEFizz( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - virtual void Precache( void ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkVar( int, m_nEntity ); - CNetworkVar( int, m_nModelIndex ); - CNetworkVar( int, m_nDensity ); - CNetworkVar( int, m_nCurrent ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEFizz::CTEFizz( const char *name ) : - CBaseTempEntity( name ) -{ - m_nEntity = 0; - m_nModelIndex = 0; - m_nDensity = 0; - m_nCurrent = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEFizz::~CTEFizz( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEFizz::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - m_nModelIndex = CBaseEntity::PrecacheModel( "sprites/bubble.vmt" );; - m_nDensity = 200; - m_nEntity = 1; - m_nCurrent = 100; - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTEFizz::Precache( void ) -{ - CBaseEntity::PrecacheModel( "sprites/bubble.vmt" ); -} - - -IMPLEMENT_SERVERCLASS_ST(CTEFizz, DT_TEFizz) - SendPropInt( SENDINFO(m_nEntity), MAX_EDICT_BITS, SPROP_UNSIGNED ), - SendPropModelIndex( SENDINFO(m_nModelIndex) ), - SendPropInt( SENDINFO(m_nDensity), 8, SPROP_UNSIGNED ), - SendPropInt(SENDINFO(m_nCurrent), 16 ), -END_SEND_TABLE() - - -// Singleton to fire TEFizz objects -static CTEFizz g_TEFizz( "Fizz" ); - -void TE_Fizz( IRecipientFilter& filter, float delay, - const CBaseEntity *entity, int modelindex, int density, int current ) -{ - Assert( entity ); - - g_TEFizz.m_nEntity = ENTINDEX( (edict_t *)entity->edict() ); - g_TEFizz.m_nModelIndex = modelindex; - g_TEFizz.m_nDensity = density; - g_TEFizz.m_nCurrent = current; - - // Send it over the wire - g_TEFizz.Create( filter, delay ); -} diff --git a/game/server/te_footprintdecal.cpp b/game/server/te_footprintdecal.cpp deleted file mode 100644 index c625ab257..000000000 --- a/game/server/te_footprintdecal.cpp +++ /dev/null @@ -1,91 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Dispatches footprint decal tempentity -//----------------------------------------------------------------------------- - -#define FOOTPRINT_DECAY_TIME 3.0f - -class CTEFootprintDecal : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEFootprintDecal, CBaseTempEntity ); - - CTEFootprintDecal( const char *name ); - virtual ~CTEFootprintDecal( void ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkVector( m_vecOrigin ); - CNetworkVector( m_vecDirection ); - CNetworkVar( int, m_nEntity ); - CNetworkVar( int, m_nIndex ); - CNetworkVar( unsigned char, m_chMaterialType ); -}; - -IMPLEMENT_SERVERCLASS_ST(CTEFootprintDecal, DT_TEFootprintDecal) - SendPropVector( SENDINFO(m_vecOrigin), -1, SPROP_COORD), - SendPropVector( SENDINFO(m_vecDirection), -1, SPROP_COORD), - SendPropInt( SENDINFO(m_nEntity), 11, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nIndex), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_chMaterialType), 8, SPROP_UNSIGNED ), -END_SEND_TABLE() - - -// Singleton to fire TEFootprintDecal objects -static CTEFootprintDecal g_TEFootprintDecal( "Footprint Decal" ); - -//----------------------------------------------------------------------------- -// constructor, destructor -//----------------------------------------------------------------------------- - -CTEFootprintDecal::CTEFootprintDecal( const char *name ) : - CBaseTempEntity( name ) -{ - m_vecOrigin.Init(); - m_nEntity = 0; - m_nIndex = 0; - m_chMaterialType = 'C'; -} - -CTEFootprintDecal::~CTEFootprintDecal( void ) -{ -} - -//----------------------------------------------------------------------------- -// places a footprint decal -//----------------------------------------------------------------------------- - -void TE_FootprintDecal( IRecipientFilter& filter, float delay, - const Vector *origin, const Vector *right, int entity, int index, - unsigned char materialType ) -{ - Assert( origin ); - g_TEFootprintDecal.m_vecOrigin = *origin; - g_TEFootprintDecal.m_vecDirection = *right; - g_TEFootprintDecal.m_nEntity = entity; - g_TEFootprintDecal.m_nIndex = index; - g_TEFootprintDecal.m_chMaterialType = materialType; - - VectorNormalize(g_TEFootprintDecal.m_vecDirection.GetForModify()); - - // Send it over the wire - g_TEFootprintDecal.Create( filter, delay ); -} diff --git a/game/server/te_glassshatter.cpp b/game/server/te_glassshatter.cpp deleted file mode 100644 index 02735efad..000000000 --- a/game/server/te_glassshatter.cpp +++ /dev/null @@ -1,155 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" -#include "shattersurfacetypes.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Dispatches Glass Shatter tempentity -//----------------------------------------------------------------------------- -class CTEShatterSurface : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEShatterSurface, CBaseTempEntity ); - - CTEShatterSurface( const char *name ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkVector( m_vecOrigin ); - CNetworkQAngle( m_vecAngles ); - CNetworkVector( m_vecForce ); - CNetworkVector( m_vecForcePos ); - CNetworkVar( float, m_flWidth ); - CNetworkVar( float, m_flHeight ); - CNetworkVar( float, m_flShardSize ); - CNetworkVar( int, m_nSurfaceType ); - CNetworkArray( byte, m_uchFrontColor, 3 ); - CNetworkArray( byte, m_uchBackColor, 3 ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEShatterSurface::CTEShatterSurface( const char *name ) : - CBaseTempEntity( name ) -{ - m_vecOrigin.Init(); - m_vecAngles.Init(); - m_vecForce.Init(); - m_vecForcePos.Init(); - m_flWidth = 16.0f; - m_flHeight = 16.0f; - m_flShardSize = 3.0f; - m_uchFrontColor.Set( 0, 255 ); - m_uchFrontColor.Set( 1, 255 ); - m_uchFrontColor.Set( 2, 255 ); - m_uchBackColor.Set( 0, 255 ); - m_uchBackColor.Set( 1, 255 ); - m_uchBackColor.Set( 2, 255 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEShatterSurface::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - m_vecOrigin = current_origin; - - Vector vecEnd; - - Vector forward; - - m_vecOrigin.GetForModify()[2] += 24; - - AngleVectors( current_angles, &forward ); - forward[2] = 0.0; - VectorNormalize( forward ); - - VectorMA( m_vecOrigin, 50.0, forward, m_vecOrigin.GetForModify() ); - VectorMA( m_vecOrigin, 1024.0, forward, vecEnd ); - - trace_t tr; - - UTIL_TraceLine( m_vecOrigin, vecEnd, MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr ); - - m_vecOrigin = tr.endpos; - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST(CTEShatterSurface, DT_TEShatterSurface) - SendPropVector( SENDINFO(m_vecOrigin), -1, SPROP_COORD), - SendPropVector( SENDINFO(m_vecAngles), -1, SPROP_COORD), - SendPropVector( SENDINFO(m_vecForce), -1, SPROP_COORD), - SendPropVector( SENDINFO(m_vecForcePos), -1, SPROP_COORD), - SendPropFloat( SENDINFO(m_flWidth), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO(m_flHeight), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO(m_flShardSize), 0, SPROP_NOSCALE ), - SendPropInt( SENDINFO(m_nSurfaceType), 2, SPROP_UNSIGNED ), - SendPropInt( SENDINFO_ARRAYELEM2( m_uchFrontColor, 0 ), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO_ARRAYELEM2( m_uchFrontColor, 1 ), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO_ARRAYELEM2( m_uchFrontColor, 2 ), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO_ARRAYELEM2( m_uchBackColor, 0 ), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO_ARRAYELEM2( m_uchBackColor, 1 ), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO_ARRAYELEM2( m_uchBackColor, 2 ), 8, SPROP_UNSIGNED ), -END_SEND_TABLE() - - -// Singleton to fire TEShatterSurface objects -static CTEShatterSurface g_TEShatterSurface( "Surface Shatter" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// *pos - -// entity - -// index - -//----------------------------------------------------------------------------- -void TE_ShatterSurface( IRecipientFilter& filter, float delay, - const Vector* pos, const QAngle* angle, const Vector* force, const Vector* forcepos, - float width, float height, float shardsize, ShatterSurface_t surfacetype, - int front_r, int front_g, int front_b, int back_r, int back_g, int back_b) -{ - g_TEShatterSurface.m_vecOrigin = *pos; - g_TEShatterSurface.m_vecAngles = *angle; - g_TEShatterSurface.m_vecForce = *force; - g_TEShatterSurface.m_vecForcePos = *forcepos; - g_TEShatterSurface.m_flWidth = width; - g_TEShatterSurface.m_flHeight = height; - g_TEShatterSurface.m_flShardSize = shardsize; - g_TEShatterSurface.m_nSurfaceType = surfacetype; - g_TEShatterSurface.m_uchFrontColor.Set( 0, front_r ); - g_TEShatterSurface.m_uchFrontColor.Set( 1, front_g ); - g_TEShatterSurface.m_uchFrontColor.Set( 2, front_b ); - g_TEShatterSurface.m_uchBackColor.Set( 0, back_r ); - g_TEShatterSurface.m_uchBackColor.Set( 1, back_g ); - g_TEShatterSurface.m_uchBackColor.Set( 2, back_b ); - - // Send it over the wire - g_TEShatterSurface.Create( filter, delay ); -} diff --git a/game/server/te_glowsprite.cpp b/game/server/te_glowsprite.cpp deleted file mode 100644 index 541b437d5..000000000 --- a/game/server/te_glowsprite.cpp +++ /dev/null @@ -1,130 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern short g_sModelIndexSmoke; // (in combatweapon.cpp) holds the index for the smoke cloud - -//----------------------------------------------------------------------------- -// Purpose: Dispatches Sprite tempentity -//----------------------------------------------------------------------------- -class CTEGlowSprite : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEGlowSprite, CBaseTempEntity ); - - CTEGlowSprite( const char *name ); - virtual ~CTEGlowSprite( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkVector( m_vecOrigin ); - CNetworkVar( int, m_nModelIndex ); - CNetworkVar( float, m_fScale ); - CNetworkVar( float, m_fLife ); - CNetworkVar( int, m_nBrightness ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEGlowSprite::CTEGlowSprite( const char *name ) : - CBaseTempEntity( name ) -{ - m_vecOrigin.Init(); - m_nModelIndex = 0; - m_fScale = 0; - m_fLife = 0; - m_nBrightness = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEGlowSprite::~CTEGlowSprite( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEGlowSprite::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - m_nModelIndex = g_sModelIndexSmoke; - m_fScale = 0.8; - m_nBrightness = 200; - m_fLife = 2.0; - m_vecOrigin = current_origin; - - Vector forward, right; - - m_vecOrigin.GetForModify()[2] += 24; - - AngleVectors( current_angles, &forward, &right, NULL ); - forward[2] = 0.0; - VectorNormalize( forward ); - - VectorMA( m_vecOrigin, 50.0, forward, m_vecOrigin.GetForModify() ); - VectorMA( m_vecOrigin, -25.0, right, m_vecOrigin.GetForModify() ); - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - - -IMPLEMENT_SERVERCLASS_ST(CTEGlowSprite, DT_TEGlowSprite) - SendPropVector( SENDINFO(m_vecOrigin), -1, SPROP_COORD), - SendPropModelIndex( SENDINFO(m_nModelIndex) ), - SendPropFloat( SENDINFO(m_fScale ), 8, SPROP_ROUNDDOWN, 0.0, 25.6 ), - SendPropFloat( SENDINFO(m_fLife ), 8, SPROP_ROUNDDOWN, 0.0, 25.6 ), - SendPropInt( SENDINFO(m_nBrightness), 8, SPROP_UNSIGNED ), -END_SEND_TABLE() - - -// Singleton to fire TEGlowSprite objects -static CTEGlowSprite g_TEGlowSprite( "GlowSprite" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// *pos - -// modelindex - -// life - -// size - -// brightness - -//----------------------------------------------------------------------------- -void TE_GlowSprite( IRecipientFilter& filter, float delay, - const Vector* pos, int modelindex, float life, float size, int brightness ) -{ - g_TEGlowSprite.m_vecOrigin = *pos; - g_TEGlowSprite.m_nModelIndex = modelindex; - g_TEGlowSprite.m_fLife = life; - g_TEGlowSprite.m_fScale = size; - g_TEGlowSprite.m_nBrightness = brightness; - - // Send it over the wire - g_TEGlowSprite.Create( filter, delay ); -} diff --git a/game/server/te_impact.cpp b/game/server/te_impact.cpp deleted file mode 100644 index 4d1e15a0b..000000000 --- a/game/server/te_impact.cpp +++ /dev/null @@ -1,97 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Send generic impact messages to the client for visualization -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Dispatches Gunshot decal tempentity -//----------------------------------------------------------------------------- -class CTEImpact : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEImpact, CBaseTempEntity ); - - DECLARE_SERVERCLASS(); - - CTEImpact( const char *name ); - virtual ~CTEImpact(); - - void Precache( void ); - void Test( const Vector& current_origin, const Vector& current_normal ); - -public: - - CNetworkVector( m_vecOrigin ); - CNetworkVector( m_vecNormal ); //NOTENOTE: In a multi-play setup we'll probably want non-oriented effects for bandwidth - CNetworkVar( int, m_iType ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -// Output : -//----------------------------------------------------------------------------- -CTEImpact::CTEImpact( const char *name ) : CBaseTempEntity( name ) -{ - m_vecOrigin.Init(); - m_vecNormal.Init(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEImpact::~CTEImpact( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTEImpact::Precache( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEImpact::Test( const Vector& current_origin, const Vector& current_normal ) -{ -} - - -//Server class implementation -IMPLEMENT_SERVERCLASS_ST( CTEImpact, DT_TEImpact) - SendPropVector( SENDINFO( m_vecOrigin ), -1, SPROP_COORD ), - SendPropVector( SENDINFO( m_vecNormal ), -1, SPROP_COORD ), - SendPropInt( SENDINFO( m_iType ), 32, SPROP_UNSIGNED ), -END_SEND_TABLE() - -// Singleton to fire TEImpact objects -static CTEImpact g_TEImpact( "Impact" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -//----------------------------------------------------------------------------- -void TE_Impact( IRecipientFilter& filter, float delay ) -{ - g_TEImpact.Create( filter, delay ); -} diff --git a/game/server/te_killplayerattachments.cpp b/game/server/te_killplayerattachments.cpp deleted file mode 100644 index 5cd7a8e97..000000000 --- a/game/server/te_killplayerattachments.cpp +++ /dev/null @@ -1,92 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Dispatches blood stream tempentity -//----------------------------------------------------------------------------- -class CTEKillPlayerAttachments : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEKillPlayerAttachments, CBaseTempEntity ); - - CTEKillPlayerAttachments( const char *name ); - virtual ~CTEKillPlayerAttachments( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkVar( int, m_nPlayer ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEKillPlayerAttachments::CTEKillPlayerAttachments( const char *name ) : - CBaseTempEntity( name ) -{ - m_nPlayer = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEKillPlayerAttachments::~CTEKillPlayerAttachments( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEKillPlayerAttachments::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - m_nPlayer = 1; - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - - -IMPLEMENT_SERVERCLASS_ST(CTEKillPlayerAttachments, DT_TEKillPlayerAttachments) - SendPropInt( SENDINFO(m_nPlayer), 5, SPROP_UNSIGNED ), -END_SEND_TABLE() - - -// Singleton to fire TEKillPlayerAttachments objects -static CTEKillPlayerAttachments g_TEKillPlayerAttachments( "KillPlayerAttachments" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// player - -//----------------------------------------------------------------------------- -void TE_KillPlayerAttachments( IRecipientFilter& filter, float delay, - int player ) -{ - g_TEKillPlayerAttachments.m_nPlayer = player; - - // Send it over the wire - g_TEKillPlayerAttachments.Create( filter, delay ); -} diff --git a/game/server/te_largefunnel.cpp b/game/server/te_largefunnel.cpp deleted file mode 100644 index dbb0abab1..000000000 --- a/game/server/te_largefunnel.cpp +++ /dev/null @@ -1,103 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "te_particlesystem.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern short g_sModelIndexSmoke; // (in combatweapon.cpp) holds the index for the smoke cloud - -//----------------------------------------------------------------------------- -// Purpose: Dispatches smoke tempentity -//----------------------------------------------------------------------------- -class CTELargeFunnel : public CTEParticleSystem -{ -public: - DECLARE_CLASS( CTELargeFunnel, CTEParticleSystem ); - DECLARE_SERVERCLASS(); - - CTELargeFunnel( const char *name ); - virtual ~CTELargeFunnel( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - -public: - CNetworkVar( int, m_nModelIndex ); - CNetworkVar( int, m_nReversed ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTELargeFunnel::CTELargeFunnel( const char *name ) : - BaseClass( name ) -{ - m_nModelIndex = 0; - m_nReversed = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTELargeFunnel::~CTELargeFunnel( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTELargeFunnel::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - m_nModelIndex = g_sModelIndexSmoke; - m_nReversed = 0; - m_vecOrigin = current_origin; - - Vector forward, right; - - m_vecOrigin.GetForModify()[2] += 24; - - AngleVectors( current_angles, &forward, &right, NULL ); - forward[2] = 0.0; - VectorNormalize( forward ); - - VectorMA( m_vecOrigin.Get(), 50.0, forward, m_vecOrigin.GetForModify() ); - VectorMA( m_vecOrigin.Get(), 25.0, right, m_vecOrigin.GetForModify() ); - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST(CTELargeFunnel, DT_TELargeFunnel) - SendPropModelIndex( SENDINFO(m_nModelIndex) ), - SendPropInt( SENDINFO(m_nReversed), 2, SPROP_UNSIGNED ), -END_SEND_TABLE() - - -// Singleton to fire TELargeFunnel objects -static CTELargeFunnel g_TELargeFunnel( "Large Funnel" ); - -void TE_LargeFunnel( IRecipientFilter& filter, float delay, - const Vector* pos, int modelindex, int reversed ) -{ - g_TELargeFunnel.m_vecOrigin = *pos; - g_TELargeFunnel.m_nModelIndex = modelindex; - g_TELargeFunnel.m_nReversed = reversed; - - // Send it over the wire - g_TELargeFunnel.Create( filter, delay ); -} diff --git a/game/server/te_muzzleflash.cpp b/game/server/te_muzzleflash.cpp deleted file mode 100644 index d80fdf7cd..000000000 --- a/game/server/te_muzzleflash.cpp +++ /dev/null @@ -1,99 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Create a muzzle flash temp ent -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "basetempentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Dispatches user tracer stream tempentity -//----------------------------------------------------------------------------- -class CTEMuzzleFlash : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEMuzzleFlash, CBaseTempEntity ); - - DECLARE_SERVERCLASS(); - - CTEMuzzleFlash( const char *name ); - virtual ~CTEMuzzleFlash( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - -public: - - CNetworkVector( m_vecOrigin ); - CNetworkQAngle( m_vecAngles ); - CNetworkVar( float, m_flScale ); - CNetworkVar( int, m_nType ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEMuzzleFlash::CTEMuzzleFlash( const char *name ) : - CBaseTempEntity( name ) -{ - m_vecOrigin.Init(); - m_vecAngles.Init(); - - m_flScale = 1.0f; - m_nType = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEMuzzleFlash::~CTEMuzzleFlash( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEMuzzleFlash::Test( const Vector& current_origin, const QAngle& current_angles ) -{ -} - - -IMPLEMENT_SERVERCLASS_ST( CTEMuzzleFlash, DT_TEMuzzleFlash ) - SendPropVector( SENDINFO(m_vecOrigin), -1, SPROP_COORD ), - SendPropVector( SENDINFO(m_vecAngles), -1, SPROP_COORD ), - SendPropFloat( SENDINFO(m_flScale), -1, SPROP_NOSCALE ), - SendPropInt( SENDINFO(m_nType), 32, SPROP_UNSIGNED ), -END_SEND_TABLE() - -// Singleton to fire TEMuzzleFlash objects -static CTEMuzzleFlash g_TEMuzzleFlash( "MuzzleFlash" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// origin - -// *recipient - -// *origin - -// *dir - -// scale - -// type - -//----------------------------------------------------------------------------- -void TE_MuzzleFlash( IRecipientFilter& filter, float delay, - const Vector &start, const QAngle &angles, float scale, int type ) -{ - g_TEMuzzleFlash.m_vecOrigin = start; - g_TEMuzzleFlash.m_vecAngles = angles; - g_TEMuzzleFlash.m_flScale = scale; - g_TEMuzzleFlash.m_nType = type; - - // Send it over the wire - g_TEMuzzleFlash.Create( filter, delay ); -} diff --git a/game/server/te_particlesystem.cpp b/game/server/te_particlesystem.cpp deleted file mode 100644 index a88caf052..000000000 --- a/game/server/te_particlesystem.cpp +++ /dev/null @@ -1,31 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "dt_send.h" -#include "server_class.h" -#include "te_particlesystem.h" -#include "coordsize.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -IMPLEMENT_SERVERCLASS_ST(CTEParticleSystem, DT_TEParticleSystem) -#if defined( TF_DLL ) - SendPropFloat( SENDINFO_VECTORELEM2(m_vecOrigin, 0, x), -1, SPROP_COORD_MP_INTEGRAL ), - SendPropFloat( SENDINFO_VECTORELEM2(m_vecOrigin, 1, y), -1, SPROP_COORD_MP_INTEGRAL ), - SendPropFloat( SENDINFO_VECTORELEM2(m_vecOrigin, 2, z), -1, SPROP_COORD_MP_INTEGRAL ), -#else - SendPropFloat( SENDINFO_VECTORELEM2(m_vecOrigin, 0, x), -1, SPROP_COORD), - SendPropFloat( SENDINFO_VECTORELEM2(m_vecOrigin, 1, y), -1, SPROP_COORD), - SendPropFloat( SENDINFO_VECTORELEM2(m_vecOrigin, 2, z), -1, SPROP_COORD), -#endif -END_SEND_TABLE() - - - - diff --git a/game/server/te_particlesystem.h b/game/server/te_particlesystem.h deleted file mode 100644 index 3f23d7058..000000000 --- a/game/server/te_particlesystem.h +++ /dev/null @@ -1,33 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef TE_PARTICLESYSTEM_H -#define TE_PARTICLESYSTEM_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "basetempentity.h" - - -class CTEParticleSystem : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEParticleSystem, CBaseTempEntity ); - DECLARE_SERVERCLASS(); - - CTEParticleSystem(const char *pName) : BaseClass(pName) - { - m_vecOrigin.GetForModify().Init(); - } - - CNetworkVector( m_vecOrigin ); -}; - - -#endif // TE_PARTICLESYSTEM_H diff --git a/game/server/te_physicsprop.cpp b/game/server/te_physicsprop.cpp deleted file mode 100644 index 0dc8bbf65..000000000 --- a/game/server/te_physicsprop.cpp +++ /dev/null @@ -1,133 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: create clientside physics prop, as breaks model if needed -//----------------------------------------------------------------------------- -class CTEPhysicsProp : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEPhysicsProp, CBaseTempEntity ); - - CTEPhysicsProp( const char *name ); - virtual ~CTEPhysicsProp( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - virtual void Precache( void ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkVector( m_vecOrigin ); - CNetworkQAngle( m_angRotation ); - CNetworkVector( m_vecVelocity ); - CNetworkVar( int, m_nModelIndex ); - CNetworkVar( int, m_nSkin ); - CNetworkVar( int, m_nFlags ); - CNetworkVar( int, m_nEffects ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEPhysicsProp::CTEPhysicsProp( const char *name ) : - CBaseTempEntity( name ) -{ - m_vecOrigin.Init(); - m_angRotation.Init(); - m_vecVelocity.Init(); - m_nModelIndex = 0; - m_nSkin = 0; - m_nFlags = 0; - m_nEffects = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEPhysicsProp::~CTEPhysicsProp( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTEPhysicsProp::Precache( void ) -{ - CBaseEntity::PrecacheModel( "models/gibs/hgibs.mdl" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEPhysicsProp::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - m_nModelIndex = CBaseEntity::PrecacheModel( "models/gibs/hgibs.mdl" ); - m_nSkin = 0; - m_vecOrigin = current_origin; - m_angRotation = current_angles; - - m_vecVelocity.Init( random->RandomFloat( -10, 10 ), random->RandomFloat( -10, 10 ), random->RandomFloat( 0, 20 ) ); - m_nFlags = 0; - m_nEffects = 0; - - Vector forward, right; - - m_vecOrigin += Vector( 0, 0, 24 ); - - AngleVectors( current_angles, &forward, &right, 0 ); - forward[2] = 0.0; - VectorNormalize( forward ); - - VectorMA( m_vecOrigin, 50.0, forward, m_vecOrigin.GetForModify() ); - VectorMA( m_vecOrigin, 25.0, right, m_vecOrigin.GetForModify() ); - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST(CTEPhysicsProp, DT_TEPhysicsProp) - SendPropVector( SENDINFO(m_vecOrigin), -1, SPROP_COORD), - SendPropAngle( SENDINFO_VECTORELEM2(m_angRotation, 0, x), 13 ), - SendPropAngle( SENDINFO_VECTORELEM2(m_angRotation, 1, y), 13 ), - SendPropAngle( SENDINFO_VECTORELEM2(m_angRotation, 2, z), 13 ), - SendPropVector( SENDINFO(m_vecVelocity), -1, SPROP_COORD), - SendPropModelIndex( SENDINFO(m_nModelIndex) ), - SendPropInt( SENDINFO(m_nSkin), ANIMATION_SKIN_BITS), - SendPropInt( SENDINFO(m_nFlags), 2, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nEffects), EF_MAX_BITS, SPROP_UNSIGNED), -END_SEND_TABLE() - -// Singleton to fire TEBreakModel objects -static CTEPhysicsProp s_TEPhysicsProp( "physicsprop" ); - -void TE_PhysicsProp( IRecipientFilter& filter, float delay, - int modelindex, int skin, const Vector& pos, const QAngle &angles, const Vector& vel, int flags, int effects ) -{ - s_TEPhysicsProp.m_vecOrigin = pos; - s_TEPhysicsProp.m_angRotation = angles; - s_TEPhysicsProp.m_vecVelocity = vel; - s_TEPhysicsProp.m_nModelIndex = modelindex; - s_TEPhysicsProp.m_nSkin = skin; - s_TEPhysicsProp.m_nFlags = flags; - s_TEPhysicsProp.m_nEffects = effects; - - // Send it over the wire - s_TEPhysicsProp.Create( filter, delay ); -} diff --git a/game/server/te_playerdecal.cpp b/game/server/te_playerdecal.cpp deleted file mode 100644 index 68480c4d3..000000000 --- a/game/server/te_playerdecal.cpp +++ /dev/null @@ -1,124 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Dispatches decal tempentity -//----------------------------------------------------------------------------- -class CTEPlayerDecal : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEPlayerDecal, CBaseTempEntity ); - - CTEPlayerDecal( const char *name ); - virtual ~CTEPlayerDecal( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkVar( int, m_nPlayer ); - CNetworkVector( m_vecOrigin ); - CNetworkVar( int, m_nEntity ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEPlayerDecal::CTEPlayerDecal( const char *name ) : - CBaseTempEntity( name ) -{ - m_nPlayer = 0; - m_vecOrigin.Init(); - m_nEntity = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEPlayerDecal::~CTEPlayerDecal( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEPlayerDecal::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - m_nPlayer = 1; - m_nEntity = 0; - m_vecOrigin = current_origin; - - Vector vecEnd; - - Vector forward; - - m_vecOrigin.GetForModify()[2] += 24; - - AngleVectors( current_angles, &forward ); - forward[2] = 0.0; - VectorNormalize( forward ); - - VectorMA( m_vecOrigin, 50.0, forward, m_vecOrigin.GetForModify() ); - VectorMA( m_vecOrigin, 1024.0, forward, vecEnd ); - - trace_t tr; - - UTIL_TraceLine( m_vecOrigin, vecEnd, MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr ); - - m_vecOrigin = tr.endpos; - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST(CTEPlayerDecal, DT_TEPlayerDecal) - SendPropVector( SENDINFO(m_vecOrigin), -1, SPROP_COORD), - SendPropInt( SENDINFO(m_nEntity), MAX_EDICT_BITS, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nPlayer), Q_log2( MAX_PLAYERS ), SPROP_UNSIGNED ), -END_SEND_TABLE() - - -// Singleton to fire TEPlayerDecal objects -static CTEPlayerDecal g_TEPlayerDecal( "Player Decal" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// *pos - -// player - -// entity - -// index - -//----------------------------------------------------------------------------- -void TE_PlayerDecal( IRecipientFilter& filter, float delay, - const Vector* pos, int player, int entity ) -{ - g_TEPlayerDecal.m_vecOrigin = *pos; - g_TEPlayerDecal.m_nPlayer = player; - g_TEPlayerDecal.m_nEntity = entity; - - // Send it over the wire - g_TEPlayerDecal.Create( filter, delay ); -} diff --git a/game/server/te_projecteddecal.cpp b/game/server/te_projecteddecal.cpp deleted file mode 100644 index a189524c3..000000000 --- a/game/server/te_projecteddecal.cpp +++ /dev/null @@ -1,122 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Dispatches BSP decal tempentity -//----------------------------------------------------------------------------- -class CTEProjectedDecal : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEProjectedDecal, CBaseTempEntity ); - - CTEProjectedDecal( const char *name ); - virtual ~CTEProjectedDecal( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkVector( m_vecOrigin ); - CNetworkVar( int, m_nIndex ); - CNetworkVar( float, m_flDistance ); - CNetworkQAngle( m_angRotation ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEProjectedDecal::CTEProjectedDecal( const char *name ) : - CBaseTempEntity( name ) -{ - m_vecOrigin.Init(); - m_angRotation.Init(); - m_flDistance = 64.0f; - m_nIndex = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEProjectedDecal::~CTEProjectedDecal( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEProjectedDecal::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - m_flDistance = 1024.0f; - m_nIndex = 0; - m_vecOrigin = current_origin; - m_angRotation = current_angles; - - Vector vecEnd; - - Vector forward; - - m_vecOrigin.GetForModify()[2] += 24; - - AngleVectors( current_angles, &forward ); - forward[2] = 0.0; - VectorNormalize( forward ); - - VectorMA( m_vecOrigin, 24.0, forward, m_vecOrigin.GetForModify() ); - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST(CTEProjectedDecal, DT_TEProjectedDecal) - SendPropVector( SENDINFO(m_vecOrigin), -1, SPROP_COORD), - SendPropQAngles( SENDINFO(m_angRotation), 10 ), - SendPropFloat( SENDINFO(m_flDistance), 10, SPROP_ROUNDUP, 0, 1024 ), - SendPropInt( SENDINFO(m_nIndex), 9, SPROP_UNSIGNED ), -END_SEND_TABLE() - - -// Singleton to fire TEBSPDecal objects -static CTEProjectedDecal g_TEProjectedDecal( "Projected Decal" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// *pos - -// entity - -// index - -// modelindex - -//----------------------------------------------------------------------------- -void TE_ProjectDecal( IRecipientFilter& filter, float delay, - const Vector* pos, const QAngle *angles, float distance, int index ) -{ - g_TEProjectedDecal.m_vecOrigin = *pos; - g_TEProjectedDecal.m_angRotation = *angles; - g_TEProjectedDecal.m_flDistance = distance; - g_TEProjectedDecal.m_nIndex = index; - - // Send it over the wire - g_TEProjectedDecal.Create( filter, delay ); -} diff --git a/game/server/te_showline.cpp b/game/server/te_showline.cpp deleted file mode 100644 index e1818e860..000000000 --- a/game/server/te_showline.cpp +++ /dev/null @@ -1,107 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "te_particlesystem.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Dispatches line -//----------------------------------------------------------------------------- -class CTEShowLine : public CTEParticleSystem -{ -public: - DECLARE_CLASS( CTEShowLine, CTEParticleSystem ); - DECLARE_SERVERCLASS(); - - CTEShowLine( const char *name ); - virtual ~CTEShowLine( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - -public: - CNetworkVector( m_vecEnd ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEShowLine::CTEShowLine( const char *name ) : - BaseClass( name ) -{ - m_vecEnd.Init(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEShowLine::~CTEShowLine( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEShowLine::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - m_vecOrigin = current_origin; - - Vector forward, right; - - m_vecOrigin.GetForModify()[2] += 24; - - AngleVectors( current_angles, &forward, &right, NULL ); - forward[2] = 0.0; - VectorNormalize( forward ); - - VectorMA( m_vecOrigin, 100.0, forward, m_vecEnd.GetForModify() ); - - m_vecOrigin = m_vecEnd + right * -128; - m_vecEnd += right * 128; - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST( CTEShowLine, DT_TEShowLine) - SendPropVector( SENDINFO(m_vecEnd), -1, SPROP_COORD), -END_SEND_TABLE() - - -// Singleton to fire TEShowLine objects -static CTEShowLine g_TEShowLine( "Show Line" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// *start - -// *end - -//----------------------------------------------------------------------------- -void TE_ShowLine( IRecipientFilter& filter, float delay, - const Vector* start, const Vector* end ) -{ - g_TEShowLine.m_vecOrigin = *start; - g_TEShowLine.m_vecEnd = *end; - - // Send it over the wire - g_TEShowLine.Create( filter, delay ); -} diff --git a/game/server/te_smoke.cpp b/game/server/te_smoke.cpp deleted file mode 100644 index 5675661dc..000000000 --- a/game/server/te_smoke.cpp +++ /dev/null @@ -1,112 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern short g_sModelIndexSmoke; // (in combatweapon.cpp) holds the index for the smoke cloud - -//----------------------------------------------------------------------------- -// Purpose: Dispatches smoke tempentity -//----------------------------------------------------------------------------- -class CTESmoke : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTESmoke, CBaseTempEntity ); - - CTESmoke( const char *name ); - virtual ~CTESmoke( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkVector( m_vecOrigin ); - CNetworkVar( int, m_nModelIndex ); - CNetworkVar( float, m_fScale ); - CNetworkVar( int, m_nFrameRate ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTESmoke::CTESmoke( const char *name ) : - CBaseTempEntity( name ) -{ - m_vecOrigin.Init(); - m_nModelIndex = 0; - m_fScale = 0; - m_nFrameRate = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTESmoke::~CTESmoke( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTESmoke::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - m_nModelIndex = g_sModelIndexSmoke; - m_fScale = 5.0; - m_nFrameRate = 12; - m_vecOrigin = current_origin; - - Vector forward, right; - - m_vecOrigin.GetForModify()[2] += 24; - - AngleVectors( current_angles, &forward, &right, NULL ); - forward[2] = 0.0; - VectorNormalize( forward ); - - VectorMA( m_vecOrigin, 50.0, forward, m_vecOrigin.GetForModify() ); - VectorMA( m_vecOrigin, 25.0, right, m_vecOrigin.GetForModify() ); - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST(CTESmoke, DT_TESmoke) - SendPropVector( SENDINFO(m_vecOrigin), -1, SPROP_COORD), - SendPropModelIndex( SENDINFO(m_nModelIndex) ), - SendPropFloat( SENDINFO(m_fScale ), 8, SPROP_ROUNDDOWN, 0.0, 25.6 ), - SendPropInt( SENDINFO(m_nFrameRate), 8, SPROP_UNSIGNED ), -END_SEND_TABLE() - - -// Singleton to fire TESmoke objects -static CTESmoke g_TESmoke( "Smoke" ); - -void TE_Smoke( IRecipientFilter& filter, float delay, - const Vector* pos, int modelindex, float scale, int framerate ) -{ - g_TESmoke.m_vecOrigin = *pos; - g_TESmoke.m_nModelIndex = modelindex; - g_TESmoke.m_fScale = scale; - g_TESmoke.m_nFrameRate = framerate; - - // Send it over the wire - g_TESmoke.Create( filter, delay ); -} diff --git a/game/server/te_sparks.cpp b/game/server/te_sparks.cpp deleted file mode 100644 index cf1a5be5a..000000000 --- a/game/server/te_sparks.cpp +++ /dev/null @@ -1,101 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "te_particlesystem.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Dispatches sparks -//----------------------------------------------------------------------------- -class CTESparks : public CTEParticleSystem -{ -public: - DECLARE_CLASS( CTESparks, CTEParticleSystem ); - DECLARE_SERVERCLASS(); - - CTESparks( const char *name ); - virtual ~CTESparks( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - CNetworkVar( int, m_nMagnitude ); - CNetworkVar( int, m_nTrailLength ); - CNetworkVector( m_vecDir ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTESparks::CTESparks( const char *name ) : - BaseClass( name ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTESparks::~CTESparks( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTESparks::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - m_vecOrigin = current_origin; - - Vector forward; - - m_vecOrigin.GetForModify()[2] += 24; - - AngleVectors( current_angles, &forward ); - forward[2] = 0.0; - VectorNormalize( forward ); - - m_vecOrigin += forward * 100; - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST(CTESparks, DT_TESparks) - SendPropInt( SENDINFO( m_nMagnitude ), 4, SPROP_UNSIGNED ), - SendPropInt( SENDINFO( m_nTrailLength ), 4, SPROP_UNSIGNED ), - SendPropVector( SENDINFO( m_vecDir ), -1, SPROP_COORD ), -END_SEND_TABLE() - - -// Singleton to fire TESparks objects -static CTESparks g_TESparks( "Sparks" ); - -void TE_Sparks( IRecipientFilter& filter, float delay, - const Vector *pos, int nMagnitude, int nTrailLength, const Vector *pDir ) -{ - g_TESparks.m_vecOrigin = *pos; - g_TESparks.m_nMagnitude = nMagnitude; - g_TESparks.m_nTrailLength = nTrailLength; - - if ( pDir ) - { - g_TESparks.m_vecDir = *pDir; - } - else - { - g_TESparks.m_vecDir = vec3_origin; - } - - // Send it over the wire - g_TESparks.Create( filter, delay ); -} diff --git a/game/server/te_sprite.cpp b/game/server/te_sprite.cpp deleted file mode 100644 index b9633f69b..000000000 --- a/game/server/te_sprite.cpp +++ /dev/null @@ -1,121 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Dispatches Sprite tempentity -//----------------------------------------------------------------------------- -class CTESprite : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTESprite, CBaseTempEntity ); - - CTESprite( const char *name ); - virtual ~CTESprite( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - virtual void Precache( void ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkVector( m_vecOrigin ); - CNetworkVar( int, m_nModelIndex ); - CNetworkVar( float, m_fScale ); - CNetworkVar( int, m_nBrightness ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTESprite::CTESprite( const char *name ) : - CBaseTempEntity( name ) -{ - m_vecOrigin.Init(); - m_nModelIndex = 0; - m_fScale = 0; - m_nBrightness = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTESprite::~CTESprite( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTESprite::Precache( void ) -{ - CBaseEntity::PrecacheModel("sprites/gunsmoke.vmt"); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTESprite::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - m_nModelIndex = CBaseEntity::PrecacheModel("sprites/gunsmoke.vmt"); - m_fScale = 0.8; - m_nBrightness = 200; - m_vecOrigin = current_origin; - - Vector forward, right; - - m_vecOrigin.GetForModify()[2] += 24; - - AngleVectors( current_angles, &forward, &right, NULL ); - forward[2] = 0.0; - VectorNormalize( forward ); - - VectorMA( m_vecOrigin, 50.0, forward, m_vecOrigin.GetForModify() ); - VectorMA( m_vecOrigin, -25.0, right, m_vecOrigin.GetForModify() ); - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - - -IMPLEMENT_SERVERCLASS_ST(CTESprite, DT_TESprite) - SendPropVector( SENDINFO(m_vecOrigin), -1, SPROP_COORD), - SendPropModelIndex( SENDINFO(m_nModelIndex) ), - SendPropFloat( SENDINFO(m_fScale ), 8, SPROP_ROUNDDOWN, 0.0, 25.6 ), - SendPropInt( SENDINFO(m_nBrightness), 8, SPROP_UNSIGNED ), -END_SEND_TABLE() - - -// Singleton to fire TESprite objects -static CTESprite g_TESprite( "Sprite" ); - -void TE_Sprite( IRecipientFilter& filter, float delay, - const Vector *pos, int modelindex, float size, int brightness ) -{ - g_TESprite.m_vecOrigin = *pos; - g_TESprite.m_nModelIndex = modelindex; - g_TESprite.m_fScale = size; - g_TESprite.m_nBrightness = brightness; - - // Send it over the wire - g_TESprite.Create( filter, delay ); -} diff --git a/game/server/te_spritespray.cpp b/game/server/te_spritespray.cpp deleted file mode 100644 index 39af3e23d..000000000 --- a/game/server/te_spritespray.cpp +++ /dev/null @@ -1,136 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern short g_sModelIndexSmoke; // (in combatweapon.cpp) holds the index for the smoke cloud - -//----------------------------------------------------------------------------- -// Purpose: Dispatches Sprite Spray tempentity -//----------------------------------------------------------------------------- -class CTESpriteSpray : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTESpriteSpray, CBaseTempEntity ); - - CTESpriteSpray( const char *name ); - virtual ~CTESpriteSpray( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkVector( m_vecOrigin ); - CNetworkVector( m_vecDirection ); - CNetworkVar( int, m_nModelIndex ); - CNetworkVar( int, m_nSpeed ); - CNetworkVar( float, m_fNoise ); - CNetworkVar( int, m_nCount ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTESpriteSpray::CTESpriteSpray( const char *name ) : - CBaseTempEntity( name ) -{ - m_vecOrigin.Init(); - m_vecDirection.Init(); - m_nModelIndex = 0; - m_fNoise = 0; - m_nSpeed = 0; - m_nCount = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTESpriteSpray::~CTESpriteSpray( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTESpriteSpray::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - m_nModelIndex = g_sModelIndexSmoke; - m_fNoise = 0.8; - m_nCount = 5; - m_nSpeed = 30; - m_vecOrigin = current_origin; - - Vector forward, right; - - m_vecOrigin.GetForModify()[2] += 24; - - AngleVectors( current_angles, &forward, &right, NULL ); - forward[2] = 0.0; - VectorNormalize( forward ); - - VectorMA( m_vecOrigin, 50.0, forward, m_vecOrigin.GetForModify() ); - VectorMA( m_vecOrigin, -25.0, right, m_vecOrigin.GetForModify() ); - - m_vecDirection.Init( random->RandomInt( -100, 100 ), random->RandomInt( -100, 100 ), random->RandomInt( 0, 100 ) ); - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST(CTESpriteSpray, DT_TESpriteSpray) - SendPropVector( SENDINFO(m_vecOrigin), -1, SPROP_COORD), - SendPropVector( SENDINFO(m_vecDirection), -1, SPROP_COORD), - SendPropModelIndex(SENDINFO(m_nModelIndex)), - SendPropFloat( SENDINFO(m_fNoise ), 8, SPROP_ROUNDDOWN, 0.0, 2.56 ), - SendPropInt( SENDINFO(m_nSpeed ), 8, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_nCount), 8, SPROP_UNSIGNED ), -END_SEND_TABLE() - - -// Singleton to fire TESpriteSpray objects -static CTESpriteSpray g_TESpriteSpray( "Sprite Spray" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// *pos - -// *dir - -// modelindex - -// speed - -// noise - -// count - -//----------------------------------------------------------------------------- -void TE_SpriteSpray( IRecipientFilter& filter, float delay, - const Vector *pos, const Vector *dir, int modelindex, int speed, float noise, int count ) -{ - g_TESpriteSpray.m_vecOrigin = *pos; - g_TESpriteSpray.m_vecDirection = *dir; - g_TESpriteSpray.m_nModelIndex = modelindex; - g_TESpriteSpray.m_nSpeed = speed; - g_TESpriteSpray.m_fNoise = noise; - g_TESpriteSpray.m_nCount = count; - - // Send it over the wire - g_TESpriteSpray.Create( filter, delay ); -} diff --git a/game/server/te_worlddecal.cpp b/game/server/te_worlddecal.cpp deleted file mode 100644 index b20bbb3e2..000000000 --- a/game/server/te_worlddecal.cpp +++ /dev/null @@ -1,121 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetempentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Dispatches world decal tempentity -//----------------------------------------------------------------------------- -class CTEWorldDecal : public CBaseTempEntity -{ -public: - DECLARE_CLASS( CTEWorldDecal, CBaseTempEntity ); - - CTEWorldDecal( const char *name ); - virtual ~CTEWorldDecal( void ); - - virtual void Test( const Vector& current_origin, const QAngle& current_angles ); - - DECLARE_SERVERCLASS(); - -public: - CNetworkVector( m_vecOrigin ); - CNetworkVar( int, m_nIndex ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CTEWorldDecal::CTEWorldDecal( const char *name ) : - CBaseTempEntity( name ) -{ - m_vecOrigin.Init(); - m_nIndex = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTEWorldDecal::~CTEWorldDecal( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *current_origin - -// *current_angles - -//----------------------------------------------------------------------------- -void CTEWorldDecal::Test( const Vector& current_origin, const QAngle& current_angles ) -{ - // Fill in data - m_nIndex = 0; - m_vecOrigin = current_origin; - - Vector vecEnd; - - Vector forward; - - m_vecOrigin.GetForModify()[2] += 24; - - AngleVectors( current_angles, &forward ); - forward[2] = 0.0; - VectorNormalize( forward ); - - VectorMA( m_vecOrigin, 50.0, forward, m_vecOrigin.GetForModify() ); - VectorMA( m_vecOrigin, 1024.0, forward, vecEnd ); - - trace_t tr; - - UTIL_TraceLine( m_vecOrigin, vecEnd, MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &tr ); - - m_vecOrigin = tr.endpos; - - CBroadcastRecipientFilter filter; - Create( filter, 0.0 ); -} - -IMPLEMENT_SERVERCLASS_ST(CTEWorldDecal, DT_TEWorldDecal) -#if defined( TF_DLL ) - SendPropVector( SENDINFO(m_vecOrigin), -1, SPROP_COORD_MP_INTEGRAL ), -#else - SendPropVector( SENDINFO(m_vecOrigin), -1, SPROP_COORD), -#endif - SendPropInt( SENDINFO(m_nIndex), 9, SPROP_UNSIGNED ), -END_SEND_TABLE() - - -// Singleton to fire TEWorldDecal objects -static CTEWorldDecal g_TEWorldDecal( "World Decal" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : msg_dest - -// delay - -// *origin - -// *recipient - -// *pos - -// index - -//----------------------------------------------------------------------------- -void TE_WorldDecal( IRecipientFilter& filter, float delay, - const Vector* pos, int index ) -{ - g_TEWorldDecal.m_vecOrigin = *pos; - g_TEWorldDecal.m_nIndex = index; - - // Send it over the wire - g_TEWorldDecal.Create( filter, delay ); -} diff --git a/game/server/team.cpp b/game/server/team.cpp deleted file mode 100644 index dd7365b5f..000000000 --- a/game/server/team.cpp +++ /dev/null @@ -1,329 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Team management class. Contains all the details for a specific team -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "team.h" -#include "player.h" -#include "team_spawnpoint.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -CUtlVector< CTeam * > g_Teams; - -//----------------------------------------------------------------------------- -// Purpose: SendProxy that converts the Team's player UtlVector to entindexes -//----------------------------------------------------------------------------- -void SendProxy_PlayerList( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ) -{ - CTeam *pTeam = (CTeam*)pData; - - // If this assertion fails, then SendProxyArrayLength_PlayerArray must have failed. - Assert( iElement < pTeam->m_aPlayers.Size() ); - - CBasePlayer *pPlayer = pTeam->m_aPlayers[iElement]; - pOut->m_Int = pPlayer->entindex(); -} - - -int SendProxyArrayLength_PlayerArray( const void *pStruct, int objectID ) -{ - CTeam *pTeam = (CTeam*)pStruct; - return pTeam->m_aPlayers.Count(); -} - - -// Datatable -IMPLEMENT_SERVERCLASS_ST_NOBASE(CTeam, DT_Team) - SendPropInt( SENDINFO(m_iTeamNum), 5 ), - SendPropInt( SENDINFO(m_iScore), 0 ), - SendPropInt( SENDINFO(m_iRoundsWon), 8 ), - SendPropString( SENDINFO( m_szTeamname ) ), - - SendPropArray2( - SendProxyArrayLength_PlayerArray, - SendPropInt("player_array_element", 0, 4, 10, SPROP_UNSIGNED, SendProxy_PlayerList), - MAX_PLAYERS, - 0, - "player_array" - ) -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( team_manager, CTeam ); - -//----------------------------------------------------------------------------- -// Purpose: Get a pointer to the specified team manager -//----------------------------------------------------------------------------- -CTeam *GetGlobalTeam( int iIndex ) -{ - if ( iIndex < 0 || iIndex >= GetNumberOfTeams() ) - return NULL; - - return g_Teams[ iIndex ]; -} - -//----------------------------------------------------------------------------- -// Purpose: Get the number of team managers -//----------------------------------------------------------------------------- -int GetNumberOfTeams( void ) -{ - return g_Teams.Size(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Needed because this is an entity, but should never be used -//----------------------------------------------------------------------------- -CTeam::CTeam( void ) -{ - memset( m_szTeamname.GetForModify(), 0, sizeof(m_szTeamname) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTeam::~CTeam( void ) -{ - m_aSpawnPoints.Purge(); - m_aPlayers.Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: Called every frame -//----------------------------------------------------------------------------- -void CTeam::Think( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: Teams are always transmitted to clients -//----------------------------------------------------------------------------- -int CTeam::UpdateTransmitState() -{ - return SetTransmitState( FL_EDICT_ALWAYS ); -} - -//----------------------------------------------------------------------------- -// Visibility/scanners -//----------------------------------------------------------------------------- -bool CTeam::ShouldTransmitToPlayer( CBasePlayer* pRecipient, CBaseEntity* pEntity ) -{ - // Always transmit the observer target to players - if ( pRecipient && pRecipient->IsObserver() && pRecipient->GetObserverTarget() == pEntity ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Initialization -//----------------------------------------------------------------------------- -void CTeam::Init( const char *pName, int iNumber ) -{ - InitializeSpawnpoints(); - InitializePlayers(); - - m_iScore = 0; - - Q_strncpy( m_szTeamname.GetForModify(), pName, MAX_TEAM_NAME_LENGTH ); - m_iTeamNum = iNumber; -} - -//----------------------------------------------------------------------------- -// DATA HANDLING -//----------------------------------------------------------------------------- -int CTeam::GetTeamNumber( void ) const -{ - return m_iTeamNum; -} - -//----------------------------------------------------------------------------- -// Purpose: Get the team's name -//----------------------------------------------------------------------------- -const char *CTeam::GetName( void ) -{ - return m_szTeamname; -} - - -//----------------------------------------------------------------------------- -// Purpose: Update the player's client data -//----------------------------------------------------------------------------- -void CTeam::UpdateClientData( CBasePlayer *pPlayer ) -{ -} - -//------------------------------------------------------------------------------------------------------------------ -// SPAWNPOINTS -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeam::InitializeSpawnpoints( void ) -{ - m_iLastSpawn = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeam::AddSpawnpoint( CTeamSpawnPoint *pSpawnpoint ) -{ - m_aSpawnPoints.AddToTail( pSpawnpoint ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeam::RemoveSpawnpoint( CTeamSpawnPoint *pSpawnpoint ) -{ - for (int i = 0; i < m_aSpawnPoints.Size(); i++ ) - { - if ( m_aSpawnPoints[i] == pSpawnpoint ) - { - m_aSpawnPoints.Remove( i ); - return; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Spawn the player at one of this team's spawnpoints. Return true if successful. -//----------------------------------------------------------------------------- -CBaseEntity *CTeam::SpawnPlayer( CBasePlayer *pPlayer ) -{ - if ( m_aSpawnPoints.Size() == 0 ) - return NULL; - - // Randomize the start spot - int iSpawn = m_iLastSpawn + random->RandomInt( 1,3 ); - if ( iSpawn >= m_aSpawnPoints.Size() ) - iSpawn -= m_aSpawnPoints.Size(); - int iStartingSpawn = iSpawn; - - // Now loop through the spawnpoints and pick one - int loopCount = 0; - do - { - if ( iSpawn >= m_aSpawnPoints.Size() ) - { - ++loopCount; - iSpawn = 0; - } - - // check if pSpot is valid, and that the player is on the right team - if ( (loopCount > 3) || m_aSpawnPoints[iSpawn]->IsValid( pPlayer ) ) - { - // DevMsg( 1, "player: spawning at (%s)\n", STRING(m_aSpawnPoints[iSpawn]->m_iName) ); - m_aSpawnPoints[iSpawn]->m_OnPlayerSpawn.FireOutput( pPlayer, m_aSpawnPoints[iSpawn] ); - - m_iLastSpawn = iSpawn; - return m_aSpawnPoints[iSpawn]; - } - - iSpawn++; - } while ( iSpawn != iStartingSpawn ); // loop if we're not back to the start - - return NULL; -} - -//------------------------------------------------------------------------------------------------------------------ -// PLAYERS -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeam::InitializePlayers( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: Add the specified player to this team. Remove them from their current team, if any. -//----------------------------------------------------------------------------- -void CTeam::AddPlayer( CBasePlayer *pPlayer ) -{ - m_aPlayers.AddToTail( pPlayer ); - NetworkStateChanged(); -} - -//----------------------------------------------------------------------------- -// Purpose: Remove this player from the team -//----------------------------------------------------------------------------- -void CTeam::RemovePlayer( CBasePlayer *pPlayer ) -{ - m_aPlayers.FindAndRemove( pPlayer ); - NetworkStateChanged(); -} - -//----------------------------------------------------------------------------- -// Purpose: Return the number of players in this team. -//----------------------------------------------------------------------------- -int CTeam::GetNumPlayers( void ) -{ - return m_aPlayers.Size(); -} - -//----------------------------------------------------------------------------- -// Purpose: Get a specific player -//----------------------------------------------------------------------------- -CBasePlayer *CTeam::GetPlayer( int iIndex ) -{ - Assert( iIndex >= 0 && iIndex < m_aPlayers.Size() ); - return m_aPlayers[ iIndex ]; -} - -//------------------------------------------------------------------------------------------------------------------ -// SCORING -//----------------------------------------------------------------------------- -// Purpose: Add / Remove score for this team -//----------------------------------------------------------------------------- -void CTeam::AddScore( int iScore ) -{ - m_iScore += iScore; -} - -void CTeam::SetScore( int iScore ) -{ - m_iScore = iScore; -} - -//----------------------------------------------------------------------------- -// Purpose: Get this team's score -//----------------------------------------------------------------------------- -int CTeam::GetScore( void ) -{ - return m_iScore; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeam::ResetScores( void ) -{ - SetScore(0); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeam::AwardAchievement( int iAchievement ) -{ - Assert( iAchievement >= 0 && iAchievement < 255 ); // must fit in short - - CRecipientFilter filter; - - int iNumPlayers = GetNumPlayers(); - - for ( int i=0;i m_aSpawnPoints; - CUtlVector< CBasePlayer * > m_aPlayers; - - // Data - CNetworkString( m_szTeamname, MAX_TEAM_NAME_LENGTH ); - CNetworkVar( int, m_iScore ); - CNetworkVar( int, m_iRoundsWon ); - int m_iDeaths; - - // Spawnpoints - int m_iLastSpawn; // Index of the last spawnpoint used - - CNetworkVar( int, m_iTeamNum ); // Which team is this? -}; - -extern CUtlVector< CTeam * > g_Teams; -extern CTeam *GetGlobalTeam( int iIndex ); -extern int GetNumberOfTeams( void ); - -#endif // TEAM_H diff --git a/game/server/team_control_point.cpp b/game/server/team_control_point.cpp deleted file mode 100644 index 97ec96ebe..000000000 --- a/game/server/team_control_point.cpp +++ /dev/null @@ -1,897 +0,0 @@ -//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#include "cbase.h" -#include "team_control_point.h" -#include "player.h" -#include "teamplay_gamerules.h" -#include "teamplayroundbased_gamerules.h" -#include "team.h" -#include "team_control_point_master.h" -#include "mp_shareddefs.h" -#include "engine/IEngineSound.h" -#include "soundenvelope.h" - -BEGIN_DATADESC(CTeamControlPoint) - DEFINE_KEYFIELD( m_iszPrintName, FIELD_STRING, "point_printname" ), - DEFINE_KEYFIELD( m_iCPGroup, FIELD_INTEGER, "point_group" ), - DEFINE_KEYFIELD( m_iDefaultOwner, FIELD_INTEGER, "point_default_owner" ), - DEFINE_KEYFIELD( m_iPointIndex, FIELD_INTEGER, "point_index" ), - DEFINE_KEYFIELD( m_iWarnOnCap, FIELD_INTEGER, "point_warn_on_cap" ), - DEFINE_KEYFIELD( m_iszWarnSound, FIELD_STRING, "point_warn_sound" ), - - DEFINE_KEYFIELD( m_iszCaptureStartSound, FIELD_STRING, "point_capture_start_sound" ), - DEFINE_KEYFIELD( m_iszCaptureEndSound, FIELD_STRING, "point_capture_end_sound" ), - DEFINE_KEYFIELD( m_iszCaptureInProgress, FIELD_STRING, "point_capture_progress_sound" ), - DEFINE_KEYFIELD( m_iszCaptureInterrupted, FIELD_STRING, "point_capture_interrupted_sound" ), - DEFINE_KEYFIELD( m_bRandomOwnerOnRestart, FIELD_BOOLEAN, "random_owner_on_restart" ), - -// DEFINE_FIELD( m_iTeam, FIELD_INTEGER ), -// DEFINE_FIELD( m_iIndex, FIELD_INTEGER ), -// DEFINE_FIELD( m_TeamData, CUtlVector < perteamdata_t > ), -// DEFINE_FIELD( m_bPointVisible, FIELD_INTEGER ), -// DEFINE_FIELD( m_bActive, FIELD_BOOLEAN ), -// DEFINE_FIELD( m_iszName, FIELD_STRING ), -// DEFINE_FIELD( m_bStartDisabled, FIELD_BOOLEAN ), -// DEFINE_FIELD( m_flLastContestedAt, FIELD_FLOAT ), -// DEFINE_FIELD( m_pCaptureInProgressSound, CSoundPatch ), - - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetOwner", InputSetOwner ), - DEFINE_INPUTFUNC( FIELD_VOID, "ShowModel", InputShowModel ), - DEFINE_INPUTFUNC( FIELD_VOID, "HideModel", InputHideModel ), - DEFINE_INPUTFUNC( FIELD_VOID, "RoundActivate", InputRoundActivate ), - - DEFINE_OUTPUT( m_OnCapTeam1, "OnCapTeam1" ), // these are fired whenever the point changes modes - DEFINE_OUTPUT( m_OnCapTeam2, "OnCapTeam2" ), - DEFINE_OUTPUT( m_OnCapReset, "OnCapReset" ), - - DEFINE_OUTPUT( m_OnOwnerChangedToTeam1, "OnOwnerChangedToTeam1" ), // these are fired when a team does the work to change the owner - DEFINE_OUTPUT( m_OnOwnerChangedToTeam2, "OnOwnerChangedToTeam2" ), - - DEFINE_OUTPUT( m_OnRoundStartOwnedByTeam1, "OnRoundStartOwnedByTeam1" ), // these are fired when a round is starting - DEFINE_OUTPUT( m_OnRoundStartOwnedByTeam2, "OnRoundStartOwnedByTeam2" ), - - DEFINE_THINKFUNC( AnimThink ), -END_DATADESC(); - -LINK_ENTITY_TO_CLASS( team_control_point, CTeamControlPoint ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTeamControlPoint::CTeamControlPoint() -{ - m_TeamData.SetSize( GetNumberOfTeams() ); - m_pCaptureInProgressSound = NULL; - -#ifdef TF_DLL - UseClientSideAnimation(); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPoint::Spawn( void ) -{ - // Validate our default team - if ( m_iDefaultOwner < 0 || m_iDefaultOwner >= GetNumberOfTeams() ) - { - Warning( "team_control_point '%s' has bad point_default_owner.\n", GetDebugName() ); - m_iDefaultOwner = TEAM_UNASSIGNED; - } - -#ifdef TF_DLL - if ( m_iszCaptureStartSound == NULL_STRING ) - { - m_iszCaptureStartSound = AllocPooledString( "Hologram.Start" ); - } - if ( m_iszCaptureEndSound == NULL_STRING ) - { - m_iszCaptureEndSound = AllocPooledString( "Hologram.Stop" ); - } - if ( m_iszCaptureInProgress == NULL_STRING ) - { - m_iszCaptureInProgress = AllocPooledString( "Hologram.Move" ); - } - if ( m_iszCaptureInterrupted == NULL_STRING ) - { - m_iszCaptureInterrupted = AllocPooledString( "Hologram.Interrupted" ); - } -#endif - - Precache(); - - InternalSetOwner( m_iDefaultOwner, false ); //init the owner of this point - - SetActive( !m_bStartDisabled ); - - BaseClass::Spawn(); - - SetPlaybackRate( 1.0 ); - SetThink( &CTeamControlPoint::AnimThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - if ( FBitSet( m_spawnflags, SF_CAP_POINT_HIDE_MODEL ) ) - { - AddEffects( EF_NODRAW ); - } - - if ( FBitSet( m_spawnflags, SF_CAP_POINT_HIDE_SHADOW ) ) - { - AddEffects( EF_NOSHADOW ); - } - - m_flLastContestedAt = -1; - - m_pCaptureInProgressSound = NULL; - - -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamControlPoint::KeyValue( const char *szKeyName, const char *szValue ) -{ - if ( !Q_strncmp( szKeyName, "team_capsound_", 14 ) ) - { - int iTeam = atoi(szKeyName+14); - Assert( iTeam >= 0 && iTeam < m_TeamData.Count() ); - - m_TeamData[iTeam].iszCapSound = AllocPooledString(szValue); - } - else if ( !Q_strncmp( szKeyName, "team_model_", 11 ) ) - { - int iTeam = atoi(szKeyName+11); - Assert( iTeam >= 0 && iTeam < m_TeamData.Count() ); - - m_TeamData[iTeam].iszModel = AllocPooledString(szValue); - } - else if ( !Q_strncmp( szKeyName, "team_timedpoints_", 17 ) ) - { - int iTeam = atoi(szKeyName+17); - Assert( iTeam >= 0 && iTeam < m_TeamData.Count() ); - - m_TeamData[iTeam].iTimedPoints = atoi(szValue); - } - else if ( !Q_strncmp( szKeyName, "team_bodygroup_", 15 ) ) - { - int iTeam = atoi(szKeyName+15); - Assert( iTeam >= 0 && iTeam < m_TeamData.Count() ); - - m_TeamData[iTeam].iModelBodygroup = atoi(szValue); - } - else if ( !Q_strncmp( szKeyName, "team_icon_", 10 ) ) - { - int iTeam = atoi(szKeyName+10); - Assert( iTeam >= 0 && iTeam < m_TeamData.Count() ); - - m_TeamData[iTeam].iszIcon = AllocPooledString(szValue); - } - else if ( !Q_strncmp( szKeyName, "team_overlay_", 13 ) ) - { - int iTeam = atoi(szKeyName+13); - Assert( iTeam >= 0 && iTeam < m_TeamData.Count() ); - - m_TeamData[iTeam].iszOverlay = AllocPooledString(szValue); - } - else if ( !Q_strncmp( szKeyName, "team_previouspoint_", 19 ) ) - { - int iTeam; - int iPoint = 0; - sscanf( szKeyName+19, "%d_%d", &iTeam, &iPoint ); - Assert( iTeam >= 0 && iTeam < m_TeamData.Count() ); - Assert( iPoint >= 0 && iPoint < MAX_PREVIOUS_POINTS ); - m_TeamData[iTeam].iszPreviousPoint[iPoint] = AllocPooledString(szValue); - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPoint::Precache( void ) -{ - for ( int i = 0; i < m_TeamData.Count(); i++ ) - { - // Skip over spectator - if ( i == TEAM_SPECTATOR ) - continue; - - if ( m_TeamData[i].iszCapSound != NULL_STRING ) - { - PrecacheScriptSound( STRING(m_TeamData[i].iszCapSound) ); - } - - if ( m_TeamData[i].iszModel != NULL_STRING ) - { - PrecacheModel( STRING(m_TeamData[i].iszModel) ); - } - - if ( m_TeamData[i].iszIcon != NULL_STRING ) - { - PrecacheMaterial( STRING( m_TeamData[i].iszIcon ) ); - m_TeamData[i].iIcon = GetMaterialIndex( STRING( m_TeamData[i].iszIcon ) ); - Assert( m_TeamData[i].iIcon != 0 ); - } - - if ( !m_TeamData[i].iIcon ) - { - Warning( "Invalid hud icon material for team %d in control point '%s' ( point index %d )\n", i, GetDebugName(), GetPointIndex() ); - } - - if ( m_TeamData[i].iszOverlay != NULL_STRING ) - { - PrecacheMaterial( STRING( m_TeamData[i].iszOverlay ) ); - m_TeamData[i].iOverlay = GetMaterialIndex( STRING( m_TeamData[i].iszOverlay ) ); - Assert( m_TeamData[i].iOverlay != 0 ); - - if ( !m_TeamData[i].iOverlay ) - { - Warning( "Invalid hud overlay material for team %d in control point '%s' ( point index %d )\n", i, GetDebugName(), GetPointIndex() ); - } - } - } - - PrecacheScriptSound( STRING( m_iszCaptureStartSound ) ); - PrecacheScriptSound( STRING( m_iszCaptureEndSound ) ); - PrecacheScriptSound( STRING( m_iszCaptureInProgress ) ); - PrecacheScriptSound( STRING( m_iszCaptureInterrupted ) ); - - if ( m_iszWarnSound != NULL_STRING ) - { - PrecacheScriptSound( STRING( m_iszWarnSound ) ); - } - -#ifdef TF_DLL - PrecacheScriptSound( "Announcer.ControlPointContested" ); -#endif -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CTeamControlPoint::AnimThink( void ) -{ - StudioFrameAdvance(); - DispatchAnimEvents(this); - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -//----------------------------------------------------------------------------- -// Purpose: Used by ControlMaster to this point to its default owner -//----------------------------------------------------------------------------- -void CTeamControlPoint::InputReset( inputdata_t &input ) -{ - m_flLastContestedAt = -1; - InternalSetOwner( m_iDefaultOwner, false ); - ObjectiveResource()->SetOwningTeam( GetPointIndex(), m_iTeam ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPoint::HandleScoring( int iTeam ) -{ - if ( TeamplayRoundBasedRules() && !TeamplayRoundBasedRules()->ShouldScorePerRound() ) - { - GetGlobalTeam( iTeam )->AddScore( 1 ); - TeamplayRoundBasedRules()->HandleTeamScoreModify( iTeam, 1 ); - - CTeamControlPointMaster *pMaster = g_hControlPointMasters.Count() ? g_hControlPointMasters[0] : NULL; - if ( pMaster && !pMaster->WouldNewCPOwnerWinGame( this, iTeam ) ) - { - CTeamRecipientFilter filter( iTeam ); - EmitSound( filter, entindex(), "Hud.EndRoundScored" ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Used by Area caps to set the owner -//----------------------------------------------------------------------------- -void CTeamControlPoint::InputSetOwner( inputdata_t &input ) -{ - int iCapTeam = input.value.Int(); - - Assert( iCapTeam >= 0 && iCapTeam < GetNumberOfTeams() ); - - Assert( input.pCaller ); - - if ( GetOwner() == iCapTeam ) - return; - - if ( TeamplayGameRules()->PointsMayBeCaptured() ) - { - // must be done before setting the owner - HandleScoring( iCapTeam ); - - if ( input.pCaller->IsPlayer() ) - { - int iCappingPlayer = input.pCaller->entindex(); - InternalSetOwner( iCapTeam, true, 1, &iCappingPlayer ); - } - else - { - InternalSetOwner( iCapTeam, false ); - } - - ObjectiveResource()->SetOwningTeam( GetPointIndex(), m_iTeam ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPoint::InputShowModel( inputdata_t &input ) -{ - RemoveEffects( EF_NODRAW ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPoint::InputHideModel( inputdata_t &input ) -{ - AddEffects( EF_NODRAW ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CTeamControlPoint::GetCurrentHudIconIndex( void ) -{ - return m_TeamData[GetOwner()].iIcon; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CTeamControlPoint::GetHudIconIndexForTeam( int iGameTeam ) -{ - return m_TeamData[iGameTeam].iIcon; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CTeamControlPoint::GetHudOverlayIndexForTeam( int iGameTeam ) -{ - return m_TeamData[iGameTeam].iOverlay; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CTeamControlPoint::GetPreviousPointForTeam( int iGameTeam, int iPrevPoint ) -{ - Assert( iPrevPoint >= 0 && iPrevPoint < MAX_PREVIOUS_POINTS ); - - int iRetVal = -1; - CBaseEntity *pEntity = gEntList.FindEntityByName( NULL, STRING(m_TeamData[iGameTeam].iszPreviousPoint[iPrevPoint]) ); - - if ( pEntity ) - { - CTeamControlPoint *pPoint = dynamic_cast( pEntity ); - - if ( pPoint ) - { - iRetVal = pPoint->GetPointIndex(); - } - } - - return iRetVal; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPoint::ForceOwner( int iTeam ) -{ - InternalSetOwner( iTeam, false, 0, 0 ); - ObjectiveResource()->SetOwningTeam( GetPointIndex(), m_iTeam ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPoint::SetOwner( int iCapTeam, bool bMakeSound, int iNumCappers, int *pCappingPlayers ) -{ - if ( TeamplayGameRules()->PointsMayBeCaptured() ) - { - // must be done before setting the owner - HandleScoring( iCapTeam ); - - InternalSetOwner( iCapTeam, bMakeSound, iNumCappers, pCappingPlayers ); - ObjectiveResource()->SetOwningTeam( GetPointIndex(), m_iTeam ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPoint::CaptureStart( void ) -{ - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_point_startcapture" ); - if ( event ) - { - event->SetInt( "cp", m_iPointIndex ); - event->SetString( "cpname", STRING(m_iszPrintName) ); - event->SetInt( "team", m_iTeam ); - - // pCappingPlayers is a null terminated list of player indices - - char capper[8]; - - Q_snprintf( capper, sizeof( capper ), "%d", entindex() ); - - event->SetString( "cappers", capper ); - event->SetInt( "priority", 7 ); - - gameeventmanager->FireEvent( event ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPoint::CaptureEnd( void ) -{ - StopLoopingSounds(); - - if ( !FBitSet( m_spawnflags, SF_CAP_POINT_NO_CAP_SOUNDS ) ) - { - EmitSound( STRING( m_iszCaptureEndSound ) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPoint::CaptureInterrupted( bool bBlocked ) -{ - StopLoopingSounds(); - - if ( FBitSet( m_spawnflags, SF_CAP_POINT_NO_CAP_SOUNDS ) ) - { - return; - } - - const char *pSoundName = NULL; - - if ( bBlocked == true ) - { - pSoundName = STRING( m_iszCaptureInterrupted ); - } - else - { - pSoundName = STRING( m_iszCaptureInProgress ); - EmitSound( STRING( m_iszCaptureStartSound ) ); - } - - if ( m_pCaptureInProgressSound == NULL && pSoundName != NULL ) - { - CPASFilter filter( GetAbsOrigin() ); - - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - m_pCaptureInProgressSound = controller.SoundCreate( filter, entindex(), pSoundName ); - - controller.Play( m_pCaptureInProgressSound, 1.0, 100 ); - } - -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPoint::StopLoopingSounds( void ) -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - - if ( m_pCaptureInProgressSound ) - { - controller.SoundDestroy( m_pCaptureInProgressSound ); - m_pCaptureInProgressSound = NULL; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Sets the new owner of the point, plays the appropriate sound and shows the right model -//----------------------------------------------------------------------------- -void CTeamControlPoint::InternalSetOwner( int iCapTeam, bool bMakeSound, int iNumCappers, int *pCappingPlayers ) -{ - Assert( iCapTeam >= 0 && iCapTeam < GetNumberOfTeams() ); - - int iOldTeam = m_iTeam; - - m_iTeam = iCapTeam; - ChangeTeam( iCapTeam ); - - if ( bMakeSound ) - { - CBroadcastRecipientFilter filter; - EmitSound( filter, entindex(), STRING( m_TeamData[m_iTeam].iszCapSound ) ); - } - - // Update visuals - SetModel( STRING(m_TeamData[m_iTeam].iszModel) ); - SetBodygroup( 0, m_iTeam ); - m_nSkin = ( m_iTeam == TEAM_UNASSIGNED ) ? 2 : (m_iTeam - 2); - ResetSequence( LookupSequence("idle") ); - - // We add 1 to the index because we consider the default "no points capped" as 0. - TeamplayGameRules()->SetLastCapPointChanged( m_iPointIndex+1 ); - - // Determine the pose parameters for each team - for ( int i = 0; i < m_TeamData.Count(); i++ ) - { - // Skip spectator - if ( i == TEAM_SPECTATOR ) - continue; - - if ( GetModelPtr() && GetModelPtr()->SequencesAvailable() ) - { - m_TeamData[i].iTeamPoseParam = LookupPoseParameter( UTIL_VarArgs( "cappoint_%d_percentage", i ) ); - } - else - { - m_TeamData[i].iTeamPoseParam = -1; - } - } - UpdateCapPercentage(); - - if ( m_iTeam == TEAM_UNASSIGNED ) - { - m_OnCapReset.FireOutput( this, this ); - } - else - { - // Remap team to get first game team = 1 - switch ( m_iTeam - FIRST_GAME_TEAM+1 ) - { - case 1: - m_OnCapTeam1.FireOutput( this, this ); - break; - case 2: - m_OnCapTeam2.FireOutput( this, this ); - break; - default: - Assert(0); - break; - } - } - - // If we're playing a sound, this is a true cap by players. - if ( bMakeSound ) - { - if ( iOldTeam > LAST_SHARED_TEAM && iOldTeam != m_iTeam ) - { - // Make the members of our old team say something - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBaseMultiplayerPlayer *pPlayer = ToBaseMultiplayerPlayer( UTIL_PlayerByIndex( i ) ); - if ( !pPlayer ) - continue; - if ( pPlayer->GetTeamNumber() == iOldTeam ) - { - pPlayer->SpeakConceptIfAllowed( MP_CONCEPT_LOST_CONTROL_POINT ); - } - } - } - - for( int i = 0; i < iNumCappers; i++ ) - { - int playerIndex = pCappingPlayers[i]; - - Assert( playerIndex > 0 && playerIndex <= gpGlobals->maxClients ); - - PlayerCapped( ToBaseMultiplayerPlayer(UTIL_PlayerByIndex( playerIndex )) ); - } - - // Remap team to get first game team = 1 - switch ( m_iTeam - FIRST_GAME_TEAM+1 ) - { - case 1: - m_OnOwnerChangedToTeam1.FireOutput( this, this ); - break; - case 2: - m_OnOwnerChangedToTeam2.FireOutput( this, this ); - break; - } - - if ( m_iTeam != TEAM_UNASSIGNED && iNumCappers ) - { - SendCapString( m_iTeam, iNumCappers, pCappingPlayers ); - } - } - - // Have control point master check the win conditions now! - CBaseEntity *pEnt = gEntList.FindEntityByClassname( NULL, GetControlPointMasterName() ); - - while( pEnt ) - { - CTeamControlPointMaster *pMaster = dynamic_cast( pEnt ); - - if ( pMaster->IsActive() ) - { - pMaster->CheckWinConditions(); - } - - pEnt = gEntList.FindEntityByClassname( pEnt, GetControlPointMasterName() ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPoint::SendCapString( int iCapTeam, int iNumCappers, int *pCappingPlayers ) -{ - if ( strlen( STRING(m_iszPrintName) ) <= 0 ) - return; - - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_point_captured" ); - if ( event ) - { - event->SetInt( "cp", m_iPointIndex ); - event->SetString( "cpname", STRING(m_iszPrintName) ); - event->SetInt( "team", iCapTeam ); - - char cappers[9]; // pCappingPlayers is max length 8 - int i; - for( i=0;iSetString( "cappers", cappers ); - event->SetInt( "priority", 9 ); - - gameeventmanager->FireEvent( event ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPoint::CaptureBlocked( CBaseMultiplayerPlayer *pPlayer ) -{ - if( strlen( STRING(m_iszPrintName) ) <= 0 ) - return; - - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_capture_blocked" ); - - if ( event ) - { - event->SetInt( "cp", m_iPointIndex ); - event->SetString( "cpname", STRING(m_iszPrintName) ); - event->SetInt( "blocker", pPlayer->entindex() ); - event->SetInt( "priority", 9 ); - - gameeventmanager->FireEvent( event ); - } - - PlayerBlocked( pPlayer ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CTeamControlPoint::GetOwner( void ) const -{ - return m_iTeam; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CTeamControlPoint::GetDefaultOwner( void ) const -{ - return m_iDefaultOwner; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CTeamControlPoint::GetCPGroup( void ) -{ - return m_iCPGroup; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the time-based point value of this control point -//----------------------------------------------------------------------------- -int CTeamControlPoint::PointValue( void ) -{ - if ( GetOwner() != m_iDefaultOwner ) - return m_TeamData[ GetOwner() ].iTimedPoints; - - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPoint::SetActive( bool active ) -{ - m_bActive = active; - - if( active ) - { - RemoveEffects( EF_NODRAW ); - } - else - { - AddEffects( EF_NODRAW ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPoint::SetCappersRequiredForTeam( int iGameTeam, int iCappers ) -{ - m_TeamData[iGameTeam].iPlayersRequired = iCappers; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CTeamControlPoint::LastContestedAt( void ) -{ - return m_flLastContestedAt; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPoint::SetLastContestedAt( float flTime ) -{ - m_flLastContestedAt = flTime; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPoint::UpdateCapPercentage( void ) -{ - for ( int i = LAST_SHARED_TEAM+1; i < m_TeamData.Count(); i++ ) - { - // Skip spectator - if ( i == TEAM_SPECTATOR ) - continue; - - float flPerc = GetTeamCapPercentage(i); - - if ( m_TeamData[i].iTeamPoseParam != -1 ) - { - SetPoseParameter( m_TeamData[i].iTeamPoseParam, flPerc ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CTeamControlPoint::GetTeamCapPercentage( int iTeam ) -{ - int iCappingTeam = ObjectiveResource()->GetCappingTeam( GetPointIndex() ); - if ( iCappingTeam == TEAM_UNASSIGNED ) - { - // No-one's capping this point. - if ( iTeam == m_iTeam ) - return 1.0; - - return 0.0; - } - - float flCapPerc = ObjectiveResource()->GetCPCapPercentage( GetPointIndex() ); - if ( iTeam == iCappingTeam ) - return (1.0 - flCapPerc); - if ( iTeam == m_iTeam ) - return flCapPerc; - - return 0.0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CTeamControlPoint::DrawDebugTextOverlays( void ) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[1024]; - Q_snprintf(tempstr, sizeof(tempstr), "INDEX: (%d)", GetPointIndex() ); - EntityText(text_offset,tempstr,0); - text_offset++; - - Q_snprintf( tempstr, sizeof(tempstr), "Red Previous Points: "); - for ( int i = 0; i < MAX_PREVIOUS_POINTS; i++ ) - { - if ( m_TeamData[2].iszPreviousPoint[i] != NULL_STRING ) - { - Q_strncat( tempstr, STRING(m_TeamData[2].iszPreviousPoint[i]), 1024, COPY_ALL_CHARACTERS ); - Q_strncat( tempstr, ", ", 1024, COPY_ALL_CHARACTERS ); - } - } - EntityText(text_offset,tempstr,0); - text_offset++; - - Q_snprintf( tempstr, sizeof(tempstr), "Blue Previous Points: " ); - for ( int i = 0; i < MAX_PREVIOUS_POINTS; i++ ) - { - if ( m_TeamData[3].iszPreviousPoint[i] != NULL_STRING ) - { - Q_strncat( tempstr, STRING(m_TeamData[3].iszPreviousPoint[i]), 1024, COPY_ALL_CHARACTERS ); - Q_strncat( tempstr, ", ", 1024, COPY_ALL_CHARACTERS ); - } - } - EntityText(text_offset,tempstr,0); - text_offset++; - - for ( int i = 0; i < MAX_CONTROL_POINT_TEAMS; i++ ) - { - if ( ObjectiveResource()->GetBaseControlPointForTeam(i) == GetPointIndex() ) - { - Q_snprintf(tempstr, sizeof(tempstr), "Base Control Point for Team %d", i ); - EntityText(text_offset,tempstr,0); - text_offset++; - } - } - } - - return text_offset; -} - -//----------------------------------------------------------------------------- -// Purpose: The specified player took part in capping this point. -//----------------------------------------------------------------------------- -void CTeamControlPoint::PlayerCapped( CBaseMultiplayerPlayer *pPlayer ) -{ - if ( pPlayer ) - { - pPlayer->SpeakConceptIfAllowed( MP_CONCEPT_CAPTURED_POINT ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: The specified player blocked the enemy team from capping this point. -//----------------------------------------------------------------------------- -void CTeamControlPoint::PlayerBlocked( CBaseMultiplayerPlayer *pPlayer ) -{ - if ( pPlayer ) - { - pPlayer->SpeakConceptIfAllowed( MP_CONCEPT_CAPTURE_BLOCKED ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPoint::InputRoundActivate( inputdata_t &inputdata ) -{ - switch ( m_iTeam - FIRST_GAME_TEAM+1 ) - { - case 1: - m_OnRoundStartOwnedByTeam1.FireOutput( this, this ); - break; - case 2: - m_OnRoundStartOwnedByTeam2.FireOutput( this, this ); - break; - } -} diff --git a/game/server/team_control_point.h b/game/server/team_control_point.h deleted file mode 100644 index 5450ead3f..000000000 --- a/game/server/team_control_point.h +++ /dev/null @@ -1,183 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef TEAM_CONTROL_POINT_H -#define TEAM_CONTROL_POINT_H -#ifdef _WIN32 -#pragma once -#endif - -#include "basemultiplayerplayer.h" - -// Spawnflags -#define SF_CAP_POINT_HIDEFLAG (1<<0) -#define SF_CAP_POINT_HIDE_MODEL (1<<1) -#define SF_CAP_POINT_HIDE_SHADOW (1<<2) -#define SF_CAP_POINT_NO_CAP_SOUNDS (1<<3) -#define SF_CAP_POINT_NO_ANNOUNCER (1<<4) - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CTeamControlPoint : public CBaseAnimating -{ - DECLARE_CLASS( CTeamControlPoint, CBaseAnimating ); -public: - DECLARE_DATADESC(); - - CTeamControlPoint(); - - // Derived, game-specific control points must override these functions -public: - // Used to find game specific entities - virtual const char *GetControlPointMasterName( void ) { return "team_control_point_master"; } - -public: - virtual void Spawn( void ); - virtual bool KeyValue( const char *szKeyName, const char *szValue ); - virtual void Precache( void ); - virtual int DrawDebugTextOverlays( void ); - - //Inputs - inline void Enable( inputdata_t &input ) { SetActive( false ); } - inline void Disable( inputdata_t &input ) { SetActive( true ); } - void InputReset( inputdata_t &input ); - void InputSetOwner( inputdata_t &input ); - void InputShowModel( inputdata_t &input ); - void InputHideModel( inputdata_t &input ); - void InputRoundActivate( inputdata_t &inputdata ); - - // Owner handling - void ForceOwner( int iTeam ); // used when selecting a specific round to play - void SetOwner( int iCapTeam, bool bMakeSound = true, int iNumCappers = 0, int *iCappingPlayers = NULL ); - int GetOwner( void ) const; - int GetDefaultOwner( void ) const; - bool RandomOwnerOnRestart( void ){ return m_bRandomOwnerOnRestart; } - - void SetActive( bool active ); - inline bool IsActive( void ) { return m_bActive; } - void AnimThink( void ); - - bool PointIsVisible( void ) { return !( FBitSet( m_spawnflags, SF_CAP_POINT_HIDEFLAG ) ); } - - inline const char *GetName( void ) { return STRING(m_iszPrintName); } - int GetCPGroup( void ); - int GetPointIndex( void ) { return m_iPointIndex; } - void SetPointIndex( int index ) { m_iPointIndex = index; } - - int GetWarnOnCap( void ) { return m_iWarnOnCap; } - string_t GetWarnSound( void ) { return m_iszWarnSound; } - - int GetTeamIcon( int iTeam ); - - int GetCurrentHudIconIndex( void ); - int GetHudIconIndexForTeam( int iGameTeam ); - int GetHudOverlayIndexForTeam( int iGameTeam ); - int GetPreviousPointForTeam( int iGameTeam, int iPrevPoint ); - - void SetCappersRequiredForTeam( int iGameTeam, int iCappers ); - - void CaptureBlocked( CBaseMultiplayerPlayer *pPlayer ); - - int PointValue( void ); - - float LastContestedAt( void ); - void SetLastContestedAt( float flTime ); - - void UpdateCapPercentage( void ); - - // The specified player took part in capping this point. - virtual void PlayerCapped( CBaseMultiplayerPlayer *pPlayer ); - - // The specified player blocked the enemy team from capping this point. - virtual void PlayerBlocked( CBaseMultiplayerPlayer *pPlayer ); - - void CaptureEnd( void ); - void CaptureStart( void ); - void CaptureInterrupted( bool bBlocked ); - - virtual void StopLoopingSounds( void ); - -private: - void SendCapString( int iCapTeam, int iNumCappers, int *pCappingPlayers ); - void InternalSetOwner( int iCapTeam, bool bMakeSound = true, int iNumCappers = 0, int *iCappingPlayers = NULL ); - float GetTeamCapPercentage( int iTeam ); - void HandleScoring( int iTeam ); - - int m_iTeam; - int m_iDefaultOwner; // Team that initially owns the cap point - int m_iIndex; // The index of this point in the controlpointArray - int m_iWarnOnCap; // Warn the team that owns the control point when the opposing team starts to capture it. - string_t m_iszPrintName; - string_t m_iszWarnSound; // Sound played if the team needs to be warned about this point being captured - bool m_bRandomOwnerOnRestart; // Do we want to randomize the owner after a restart? - - // We store a copy of this data for each team, +1 for the un-owned state. - struct perteamdata_t - { - perteamdata_t() - { - iszCapSound = NULL_STRING; - iszModel = NULL_STRING; - iModelBodygroup = -1; - iIcon = 0; - iszIcon = NULL_STRING; - iOverlay = 0; - iszOverlay = NULL_STRING; - iPlayersRequired = 0; - iTimedPoints = 0; - for ( int i = 0; i < MAX_PREVIOUS_POINTS; i++ ) - { - iszPreviousPoint[i] = NULL_STRING; - } - iTeamPoseParam = 0; - } - - string_t iszCapSound; - string_t iszModel; - int iModelBodygroup; - int iTeamPoseParam; - int iIcon; - string_t iszIcon; - int iOverlay; - string_t iszOverlay; - int iPlayersRequired; - int iTimedPoints; - string_t iszPreviousPoint[MAX_PREVIOUS_POINTS]; - }; - CUtlVector m_TeamData; - - COutputEvent m_OnCapReset; - - COutputEvent m_OnCapTeam1; - COutputEvent m_OnCapTeam2; - - COutputEvent m_OnOwnerChangedToTeam1; - COutputEvent m_OnOwnerChangedToTeam2; - - COutputEvent m_OnRoundStartOwnedByTeam1; - COutputEvent m_OnRoundStartOwnedByTeam2; - - int m_bPointVisible; //should this capture point be visible on the hud? - int m_iPointIndex; //the mapper set index value of this control point - - int m_iCPGroup; //the group that this control point belongs to - bool m_bActive; // - - string_t m_iszName; //Name used in cap messages - - bool m_bStartDisabled; - - float m_flLastContestedAt; - - CSoundPatch *m_pCaptureInProgressSound; - string_t m_iszCaptureStartSound; - string_t m_iszCaptureEndSound; - string_t m_iszCaptureInProgress; - string_t m_iszCaptureInterrupted; -}; - -#endif // TEAM_CONTROL_POINT_H diff --git a/game/server/team_control_point_master.cpp b/game/server/team_control_point_master.cpp deleted file mode 100644 index d795ff7e8..000000000 --- a/game/server/team_control_point_master.cpp +++ /dev/null @@ -1,1292 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#include "cbase.h" -#include "team_objectiveresource.h" -#include "team_control_point_master.h" -#include "teamplayroundbased_gamerules.h" - - -BEGIN_DATADESC( CTeamControlPointMaster ) - DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ), - DEFINE_KEYFIELD( m_iszCapLayoutInHUD, FIELD_STRING, "caplayout" ), - DEFINE_KEYFIELD( m_iInvalidCapWinner, FIELD_INTEGER, "cpm_restrict_team_cap_win" ), - DEFINE_KEYFIELD( m_bSwitchTeamsOnWin, FIELD_BOOLEAN, "switch_teams" ), - DEFINE_KEYFIELD( m_bScorePerCapture, FIELD_BOOLEAN, "score_style" ), - DEFINE_KEYFIELD( m_bPlayAllRounds, FIELD_BOOLEAN, "play_all_rounds" ), - - DEFINE_KEYFIELD( m_flPartialCapturePointsRate, FIELD_FLOAT, "partial_cap_points_rate" ), - -// DEFINE_FIELD( m_ControlPoints, CUtlMap < int , CTeamControlPoint * > ), -// DEFINE_FIELD( m_bFoundPoints, FIELD_BOOLEAN ), -// DEFINE_FIELD( m_ControlPointRounds, CUtlVector < CTeamControlPointRound * > ), -// DEFINE_FIELD( m_iCurrentRoundIndex, FIELD_INTEGER ), -// DEFINE_ARRAY( m_iszTeamBaseIcons, FIELD_STRING, MAX_TEAMS ), -// DEFINE_ARRAY( m_iTeamBaseIcons, FIELD_INTEGER, MAX_TEAMS ), -// DEFINE_FIELD( m_bFirstRoundAfterRestart, FIELD_BOOLEAN ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetWinner", InputSetWinner ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetWinnerAndForceCaps", InputSetWinnerAndForceCaps ), - DEFINE_INPUTFUNC( FIELD_VOID, "RoundSpawn", InputRoundSpawn ), - DEFINE_INPUTFUNC( FIELD_VOID, "RoundActivate", InputRoundActivate ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetCapLayout", InputSetCapLayout ), - - DEFINE_FUNCTION( CPMThink ), - - DEFINE_OUTPUT( m_OnWonByTeam1, "OnWonByTeam1" ), - DEFINE_OUTPUT( m_OnWonByTeam2, "OnWonByTeam2" ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( team_control_point_master, CTeamControlPointMaster ); - -ConVar mp_time_between_capscoring( "mp_time_between_capscoring", "30", FCVAR_GAMEDLL, "Delay between scoring of owned capture points.", true, 1, false, 0 ); - -// sort function for the list of control_point_rounds (we're sorting them by priority...highest first) -int ControlPointRoundSort( CTeamControlPointRound* const *p1, CTeamControlPointRound* const *p2 ) -{ - // check the priority - if ( (*p2)->GetPriorityValue() > (*p1)->GetPriorityValue() ) - { - return 1; - } - - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: init -//----------------------------------------------------------------------------- -CTeamControlPointMaster::CTeamControlPointMaster() -{ - m_flPartialCapturePointsRate = 0.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointMaster::Spawn( void ) -{ - Precache(); - - SetTouch( NULL ); - m_bFoundPoints = false; - SetDefLessFunc( m_ControlPoints ); - - m_iCurrentRoundIndex = -1; - m_bFirstRoundAfterRestart = true; - - BaseClass::Spawn(); - - if ( g_hControlPointMasters.Find(this) == g_hControlPointMasters.InvalidIndex() ) - { - g_hControlPointMasters.AddToTail( this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointMaster::UpdateOnRemove( void ) -{ - BaseClass::UpdateOnRemove(); - - g_hControlPointMasters.FindAndRemove( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamControlPointMaster::KeyValue( const char *szKeyName, const char *szValue ) -{ - if ( !Q_strncmp( szKeyName, "team_base_icon_", 15 ) ) - { - int iTeam = atoi(szKeyName+15); - Assert( iTeam >= 0 && iTeam < MAX_TEAMS ); - - m_iszTeamBaseIcons[iTeam] = AllocPooledString(szValue); - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointMaster::Precache( void ) -{ - for ( int i = 0; i < MAX_TEAMS; i++ ) - { - if ( m_iszTeamBaseIcons[i] != NULL_STRING ) - { - PrecacheMaterial( STRING( m_iszTeamBaseIcons[i] ) ); - m_iTeamBaseIcons[i] = GetMaterialIndex( STRING( m_iszTeamBaseIcons[i] ) ); - Assert( m_iTeamBaseIcons[i] != 0 ); - } - } - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointMaster::Activate( void ) -{ - BaseClass::Activate(); - - // Find control points right away. This allows client hud elements to know the - // number & starting state of control points before the game actually starts. - FindControlPoints(); - FindControlPointRounds(); - - SetBaseControlPoints(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointMaster::RoundRespawn( void ) -{ - -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointMaster::Reset( void ) -{ - -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamControlPointMaster::FindControlPoints( void ) -{ - //go through all the points - CBaseEntity *pEnt = gEntList.FindEntityByClassname( NULL, GetControlPointName() ); - - int numFound = 0; - - while( pEnt ) - { - CTeamControlPoint *pPoint = assert_cast(pEnt); - - if( pPoint->IsActive() ) - { - int index = pPoint->GetPointIndex(); - - Assert( index >= 0 ); - - if( m_ControlPoints.Find( index ) == m_ControlPoints.InvalidIndex()) - { - DevMsg( 2, "**** Adding control point %s with index %d to control point master\n", pPoint->GetName(), index ); - m_ControlPoints.Insert( index, pPoint ); - numFound++; - } - else - { - Warning( "!!!!\nMultiple control points with the same index, duplicates ignored\n!!!!\n" ); - UTIL_Remove( pPoint ); - } - } - - pEnt = gEntList.FindEntityByClassname( pEnt, GetControlPointName() ); - } - - if( numFound > MAX_CONTROL_POINTS ) - { - Warning( "Too many control points! Max is %d\n", MAX_CONTROL_POINTS ); - } - - //Remap the indeces of the control points so they are 0-based - //====================== - unsigned int j; - - bool bHandled[MAX_CONTROL_POINTS]; - memset( bHandled, 0, sizeof(bHandled) ); - - unsigned int numPoints = m_ControlPoints.Count(); - unsigned int newIndex = 0; - - while( newIndex < numPoints ) - { - //Find the lowest numbered, unhandled point - int lowestIndex = -1; - int lowestValue = 999; - - //find the lowest unhandled index - for( j=0; jGetPointIndex() < lowestValue ) - { - lowestIndex = j; - lowestValue = m_ControlPoints[j]->GetPointIndex(); - } - } - - //Don't examine this point again - bHandled[lowestIndex] = true; - - //Give it its new index - m_ControlPoints[lowestIndex]->SetPointIndex( newIndex ); - newIndex++; - } - - if( m_ControlPoints.Count() == 0 ) - { - Warning( "Error! No control points found in map!\n"); - return false; - } - - // Now setup the objective resource - ObjectiveResource()->SetNumControlPoints( m_ControlPoints.Count() ); - for ( unsigned int i = 0; i < m_ControlPoints.Count(); i++ ) - { - CTeamControlPoint *pPoint = m_ControlPoints[i]; - - int iPointIndex = m_ControlPoints[i]->GetPointIndex(); - - ObjectiveResource()->SetOwningTeam( iPointIndex, pPoint->GetOwner() ); - ObjectiveResource()->SetCPVisible( iPointIndex, pPoint->PointIsVisible() ); - ObjectiveResource()->SetCPPosition( iPointIndex, pPoint->GetAbsOrigin() ); - ObjectiveResource()->SetWarnOnCap( iPointIndex, pPoint->GetWarnOnCap() ); - ObjectiveResource()->SetWarnSound( iPointIndex, pPoint->GetWarnSound() ); - for ( int team = 0; team < GetNumberOfTeams(); team++ ) - { - ObjectiveResource()->SetCPIcons( iPointIndex, team, pPoint->GetHudIconIndexForTeam(team) ); - ObjectiveResource()->SetCPOverlays( iPointIndex, team, pPoint->GetHudOverlayIndexForTeam(team) ); - for ( int prevpoint = 0; prevpoint < MAX_PREVIOUS_POINTS; prevpoint++ ) - { - ObjectiveResource()->SetPreviousPoint( iPointIndex, team, prevpoint, pPoint->GetPreviousPointForTeam(team, prevpoint) ); - } - } - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointMaster::SetBaseControlPoints( void ) -{ - for ( int team = 0; team < GetNumberOfTeams(); team++ ) - { - ObjectiveResource()->SetTeamBaseIcons( team, m_iTeamBaseIcons[team] ); - ObjectiveResource()->SetBaseCP( GetBaseControlPoint(team), team ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamControlPointMaster::FindControlPointRounds( void ) -{ - bool bFoundRounds = false; - - m_ControlPointRounds.RemoveAll(); - CBaseEntity *pEnt = gEntList.FindEntityByClassname( NULL, GetControlPointRoundName() ); - - while( pEnt ) - { - CTeamControlPointRound *pRound = assert_cast( pEnt ); - - if( pRound && ( m_ControlPointRounds.Find( pRound ) == m_ControlPointRounds.InvalidIndex() ) ) - { - DevMsg( 2, "**** Adding control point round %s to control point master\n", pRound->GetEntityName().ToCStr() ); - m_ControlPointRounds.AddToHead( pRound ); - } - - pEnt = gEntList.FindEntityByClassname( pEnt, GetControlPointRoundName() ); - } - - if ( m_ControlPointRounds.Count() > 0 ) - { - // sort them in our list by priority (highest priority first) - m_ControlPointRounds.Sort( ControlPointRoundSort ); - bFoundRounds = true; - } - - if ( g_pObjectiveResource ) - { - g_pObjectiveResource->SetPlayingMiniRounds( bFoundRounds ); - g_pObjectiveResource->SetCapLayoutInHUD( STRING(m_iszCapLayoutInHUD) ); - } - - return bFoundRounds; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamControlPointMaster::PointCanBeCapped( CTeamControlPoint *pPoint ) -{ - // are we playing a round and is this point in the round? - if ( m_ControlPointRounds.Count() > 0 && m_iCurrentRoundIndex != -1 ) - { - return m_ControlPointRounds[m_iCurrentRoundIndex]->IsControlPointInRound( pPoint ); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamControlPointMaster::FindControlPointRoundToPlay( void ) -{ - for ( int i = 0 ; i < m_ControlPointRounds.Count() ; ++i ) - { - CTeamControlPointRound *pRound = m_ControlPointRounds[i]; - - if ( pRound ) - { - if ( pRound->IsPlayable() ) - { - // we found one that's playable - return true; - } - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamControlPointMaster::SelectSpecificRound( void ) -{ - CTeamControlPointRound *pRound = NULL; - CTeamplayRoundBasedRules *pRules = dynamic_cast( GameRules() ); - - if ( pRules ) - { - if ( pRules->GetRoundToPlayNext() != NULL_STRING ) - { - // do we have the name of a round? - pRound = dynamic_cast( gEntList.FindEntityByName( NULL, STRING( pRules->GetRoundToPlayNext() ) ) ); - - if ( pRound ) - { - if ( ( m_ControlPointRounds.Find( pRound )== m_ControlPointRounds.InvalidIndex() ) || - ( !pRound->IsPlayable() && !pRound->MakePlayable() ) ) - { - pRound = NULL; - } - } - - pRules->SetRoundToPlayNext( NULL_STRING ); - } - } - - // do we have a round to play? - if ( pRound ) - { - m_iCurrentRoundIndex = m_ControlPointRounds.Find( pRound ); - m_ControlPointRounds[m_iCurrentRoundIndex]->SelectedToPlay(); - - if ( pRules ) - { - pRules->SetRoundOverlayDetails(); - } - - FireRoundStartOutput(); - DevMsg( 2, "**** Selected round %s to play\n", m_ControlPointRounds[m_iCurrentRoundIndex]->GetEntityName().ToCStr() ); - - if ( !pRules->IsInWaitingForPlayers() ) - { - UTIL_LogPrintf( "World triggered \"Mini_Round_Selected\" (round \"%s\")\n", m_ControlPointRounds[m_iCurrentRoundIndex]->GetEntityName().ToCStr() ); - UTIL_LogPrintf( "World triggered \"Mini_Round_Start\"\n" ); - } - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointMaster::RegisterRoundBeingPlayed( void ) -{ - // let the game rules know what round we're playing - CTeamplayRoundBasedRules *pRules = dynamic_cast( GameRules() ); - if ( pRules ) - { - string_t iszEntityName = m_ControlPointRounds[m_iCurrentRoundIndex]->GetEntityName(); - - pRules->AddPlayedRound( iszEntityName ); - - if ( m_bFirstRoundAfterRestart ) - { - pRules->SetFirstRoundPlayed( iszEntityName ); - m_bFirstRoundAfterRestart = false; - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamControlPointMaster::GetControlPointRoundToPlay( void ) -{ - int i = 0; - - // are we trying to pick a specific round? - if ( SelectSpecificRound() ) - { - SetBaseControlPoints(); - RegisterRoundBeingPlayed(); - return true; - } - - // rounds are sorted with the higher priority rounds first - for ( i = 0 ; i < m_ControlPointRounds.Count() ; ++i ) - { - CTeamControlPointRound *pRound = m_ControlPointRounds[i]; - - if ( pRound ) - { - if ( pRound->IsPlayable() ) - { - // we found one that's playable - break; - } - } - } - - if ( i >= m_ControlPointRounds.Count() || m_ControlPointRounds[i] == NULL ) - { - // we didn't find one to play - m_iCurrentRoundIndex = -1; - return false; - } - - // we have a priority value, now we need to randomly pick a round with this priority that's playable - int nPriority = m_ControlPointRounds[i]->GetPriorityValue(); - CUtlVector nRounds; - - CTeamplayRoundBasedRules *pRules = dynamic_cast( GameRules() ); - string_t iszLastRoundPlayed = pRules ? pRules->GetLastPlayedRound() : NULL_STRING; - int iLastRoundPlayed = -1; - - string_t iszFirstRoundPlayed = pRules ? pRules->GetFirstRoundPlayed() : NULL_STRING; - int iFirstRoundPlayed = -1; // after a full restart - - // loop through and find the rounds with this priority value - for ( i = 0 ; i < m_ControlPointRounds.Count() ; ++i ) - { - CTeamControlPointRound *pRound = m_ControlPointRounds[i]; - - if ( pRound ) - { - string_t iszRoundName = pRound->GetEntityName(); - - if ( pRound->IsPlayable() && pRound->GetPriorityValue() == nPriority ) - { - if ( iszLastRoundPlayed == iszRoundName ) // is this the last round we played? - { - iLastRoundPlayed = i; - } - - if ( m_bFirstRoundAfterRestart ) - { - // is this the first round we played after the last full restart? - if ( ( iszFirstRoundPlayed != NULL_STRING ) && ( iszFirstRoundPlayed == iszRoundName ) ) - { - iFirstRoundPlayed = i; - } - } - - nRounds.AddToHead(i); - } - } - } - - if ( nRounds.Count() <= 0 ) - { - // we didn't find one to play - m_iCurrentRoundIndex = -1; - return false; - } - - // if we have more than one and the last played round is in our list, remove it - if ( nRounds.Count() > 1 ) - { - if ( iLastRoundPlayed != -1 ) - { - int elementIndex = nRounds.Find( iLastRoundPlayed ); - nRounds.Remove( elementIndex ); - } - } - - // if this is the first round after a full restart, we still have more than one round in our list, - // and the first played round (after the last full restart) is in our list, remove it - if ( m_bFirstRoundAfterRestart ) - { - if ( nRounds.Count() > 1 ) - { - if ( iFirstRoundPlayed != -1 ) - { - int elementIndex = nRounds.Find( iFirstRoundPlayed ); - nRounds.Remove( elementIndex ); - } - } - } - - // pick one to play but try to avoid picking one that we have recently played if there are other rounds to play - int index = random->RandomInt( 0, nRounds.Count() - 1 ); - - // only need to check this if we have more than one round with this priority value - if ( pRules && nRounds.Count() > 1 ) - { - // keep picking a round until we find one that's not a previously played round - // or until we don't have any more rounds to choose from - while ( pRules->IsPreviouslyPlayedRound( m_ControlPointRounds[ nRounds[ index ] ]->GetEntityName() ) && - nRounds.Count() > 1 ) - { - nRounds.Remove( index ); // we have played this round recently so get it out of the list - index = random->RandomInt( 0, nRounds.Count() - 1 ); - } - } - - // pick one to play and fire its OnSelected output - m_iCurrentRoundIndex = nRounds[ index ]; - m_ControlPointRounds[m_iCurrentRoundIndex]->SelectedToPlay(); - - if ( pRules ) - { - pRules->SetRoundOverlayDetails(); - } - - FireRoundStartOutput(); - DevMsg( 2, "**** Selected round %s to play\n", m_ControlPointRounds[m_iCurrentRoundIndex]->GetEntityName().ToCStr() ); - - if ( !pRules->IsInWaitingForPlayers() ) - { - UTIL_LogPrintf( "World triggered \"Mini_Round_Selected\" (round \"%s\")\n", m_ControlPointRounds[m_iCurrentRoundIndex]->GetEntityName().ToCStr() ); - UTIL_LogPrintf( "World triggered \"Mini_Round_Start\"\n" ); - } - - SetBaseControlPoints(); - RegisterRoundBeingPlayed(); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Called every 0.1 seconds and checks the status of all the control points -// if one team owns them all, it gives points and resets -// Think also gives the time based points at the specified time intervals -//----------------------------------------------------------------------------- -void CTeamControlPointMaster::CPMThink( void ) -{ - if ( m_bDisabled || !TeamplayGameRules()->PointsMayBeCaptured() ) - { - SetContextThink( &CTeamControlPointMaster::CPMThink, gpGlobals->curtime + 0.2, CPM_THINK ); - return; - } - - // If we call this from team_control_point, this function should never - // trigger a win. but we'll leave it here just in case. - CheckWinConditions(); - - // the next time we 'think' - SetContextThink( &CTeamControlPointMaster::CPMThink, gpGlobals->curtime + 0.2, CPM_THINK ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointMaster::CheckWinConditions( void ) -{ - if ( m_bDisabled ) - return; - - if ( m_ControlPointRounds.Count() > 0 ) - { - if ( m_iCurrentRoundIndex != -1 ) - { - // Check the current round to see if one team is a winner yet - int iWinners = m_ControlPointRounds[m_iCurrentRoundIndex]->CheckWinConditions(); - if ( iWinners != -1 && iWinners >= FIRST_GAME_TEAM ) - { - bool bForceMapReset = ( FindControlPointRoundToPlay() == false ); // are there any more rounds to play? - - if ( !bForceMapReset ) - { - // we have more rounds to play - TeamplayGameRules()->SetWinningTeam( iWinners, WINREASON_ALL_POINTS_CAPTURED, bForceMapReset ); - } - else - { - // we have played all of the available rounds - TeamplayGameRules()->SetWinningTeam( iWinners, WINREASON_ALL_POINTS_CAPTURED, bForceMapReset, m_bSwitchTeamsOnWin ); - } - - FireTeamWinOutput( iWinners ); - } - } - } - else - { - // Check that the points aren't all held by one team...if they are - // this will reset the round and will reset all the points - int iWinners = TeamOwnsAllPoints(); - if ( ( iWinners >= FIRST_GAME_TEAM ) && - ( iWinners != m_iInvalidCapWinner ) ) - { - TeamplayGameRules()->SetWinningTeam( iWinners, WINREASON_ALL_POINTS_CAPTURED, true, m_bSwitchTeamsOnWin ); - FireTeamWinOutput( iWinners ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointMaster::InputSetWinner( inputdata_t &input ) -{ - int iTeam = input.value.Int(); - InternalSetWinner( iTeam ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointMaster::InputSetWinnerAndForceCaps( inputdata_t &input ) -{ - int iTeam = input.value.Int(); - - // Set all cap points in the current round to be owned by the winning team - for ( unsigned int i = 0; i < m_ControlPoints.Count(); i++ ) - { - CTeamControlPoint *pPoint = m_ControlPoints[i]; - if ( pPoint && (!PlayingMiniRounds() || ObjectiveResource()->IsInMiniRound(pPoint->GetPointIndex()) ) ) - { - pPoint->ForceOwner( iTeam ); - } - } - - InternalSetWinner( iTeam ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointMaster::InternalSetWinner( int iTeam ) -{ - bool bForceMapReset = true; - - if ( m_ControlPointRounds.Count() > 0 ) - { - // if we're playing rounds and there are more to play, don't do a full reset - bForceMapReset = ( FindControlPointRoundToPlay() == false ); - } - - if ( iTeam == TEAM_UNASSIGNED ) - { - TeamplayGameRules()->SetStalemate( STALEMATE_TIMER, bForceMapReset ); - } - else - { - if ( !bForceMapReset ) - { - TeamplayGameRules()->SetWinningTeam( iTeam, WINREASON_ALL_POINTS_CAPTURED, bForceMapReset ); - } - else - { - TeamplayGameRules()->SetWinningTeam( iTeam, WINREASON_ALL_POINTS_CAPTURED, bForceMapReset, m_bSwitchTeamsOnWin ); - } - - FireTeamWinOutput( iTeam ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointMaster::HandleRandomOwnerControlPoints( void ) -{ - CUtlVector vecPoints; - CUtlVector vecTeams; - - int i = 0; - - // loop through and find all of the points that want random owners after a full restart - for ( i = 0 ; i < (int)m_ControlPoints.Count() ; i++ ) - { - CTeamControlPoint *pPoint = m_ControlPoints[i]; - - if ( pPoint && pPoint->RandomOwnerOnRestart() ) - { - vecPoints.AddToHead( pPoint ); - vecTeams.AddToHead( pPoint->GetTeamNumber() ); - } - } - - // now loop through and mix up the owners (if we found any points with this flag set) - for ( i = 0 ; i < vecPoints.Count() ; i++ ) - { - CTeamControlPoint *pPoint = vecPoints[i]; - - if ( pPoint ) - { - int index = random->RandomInt( 0, vecTeams.Count() - 1 ); - pPoint->ForceOwner( vecTeams[index] ); - - vecTeams.Remove( index ); - } - } - - vecPoints.RemoveAll(); - vecTeams.RemoveAll(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointMaster::InputRoundSpawn( inputdata_t &input ) -{ - //clear out old control points - m_ControlPoints.RemoveAll(); - - //find the control points, and if successful, do CPMThink - if ( FindControlPoints() ) - { -/* if ( m_bFirstRoundAfterRestart ) - { - CTeamplayRoundBasedRules *pRules = dynamic_cast( GameRules() ); - if ( pRules && ( pRules->GetRoundToPlayNext() == NULL_STRING ) ) - { - // we only want to handle the random points if we don't have a specific round to play next - // (prevents points being randomized again after "waiting for players" has finished and we're going to play the same round) - HandleRandomOwnerControlPoints(); - } - } -*/ - SetContextThink( &CTeamControlPointMaster::CPMThink, gpGlobals->curtime + 0.1, CPM_THINK ); - } - - // clear out the old rounds - m_ControlPointRounds.RemoveAll(); - - // find the rounds (if the map has any) - FindControlPointRounds(); - - SetBaseControlPoints(); - - // init the ClientAreas - int index = 0; - - CBaseEntity *pEnt = gEntList.FindEntityByClassname( NULL, GetTriggerAreaCaptureName() ); - while( pEnt ) - { - CTriggerAreaCapture *pArea = (CTriggerAreaCapture *)pEnt; - Assert( pArea ); - pArea->SetAreaIndex( index ); - index++; - - pEnt = gEntList.FindEntityByClassname( pEnt, GetTriggerAreaCaptureName() ); - } - - ObjectiveResource()->ResetControlPoints(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointMaster::InputRoundActivate( inputdata_t &input ) -{ - // if we're using mini-rounds and haven't picked one yet, find one to play - if ( PlayingMiniRounds() && GetCurrentRound() == NULL ) - { - GetControlPointRoundToPlay(); - } - - if ( PlayingMiniRounds() ) - { - // Tell the objective resource what control points are in use in the selected mini-round - CTeamControlPointRound *pRound = GetCurrentRound(); - if ( pRound ) - { - for ( unsigned int i = 0; i < m_ControlPoints.Count(); i++ ) - { - CTeamControlPoint *pPoint = m_ControlPoints[i]; - if ( pPoint ) - { - ObjectiveResource()->SetInMiniRound( pPoint->GetPointIndex(), pRound->IsControlPointInRound( pPoint ) ); - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointMaster::InputSetCapLayout( inputdata_t &inputdata ) -{ - m_iszCapLayoutInHUD = inputdata.value.StringID(); - g_pObjectiveResource->SetCapLayoutInHUD( STRING(m_iszCapLayoutInHUD) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointMaster::FireTeamWinOutput( int iWinningTeam ) -{ - // Remap team so that first game team = 1 - switch( iWinningTeam - FIRST_GAME_TEAM+1 ) - { - case 1: - m_OnWonByTeam1.FireOutput(this,this); - break; - case 2: - m_OnWonByTeam2.FireOutput(this,this); - break; - default: - Assert(0); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointMaster::FireRoundStartOutput( void ) -{ - CTeamControlPointRound *pRound = GetCurrentRound(); - - if ( pRound ) - { - pRound->FireOnStartOutput(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointMaster::FireRoundEndOutput( void ) -{ - CTeamControlPointRound *pRound = GetCurrentRound(); - - if ( pRound ) - { - pRound->FireOnEndOutput(); - m_iCurrentRoundIndex = -1; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CTeamControlPointMaster::PointLastContestedAt( int point ) -{ - CTeamControlPoint *pPoint = GetControlPoint(point); - if ( pPoint ) - return pPoint->LastContestedAt(); - - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: This function returns the team that owns all the cap points. -// If its not the case that one team owns them all, it returns 0. -// CPs are broken into groups. A team can win by owning all flags within a single group. -// -// Can be passed an overriding team. If this is not null, the passed team -// number will be used for that cp. Used to predict if that CP changing would -// win the game. -//----------------------------------------------------------------------------- -int CTeamControlPointMaster::TeamOwnsAllPoints( CTeamControlPoint *pOverridePoint /* = NULL */, int iOverrideNewTeam /* = TEAM_UNASSIGNED */ ) -{ - unsigned int i; - - int iWinningTeam[MAX_CONTROL_POINT_GROUPS]; - - for( i=0;iGetCPGroup(); - int owner = m_ControlPoints[i]->GetOwner(); - - if ( pOverridePoint == m_ControlPoints[i] ) - { - owner = iOverrideNewTeam; - } - - // the first one we find in this group, set the win to true - if ( iWinningTeam[group] == TEAM_INVALID ) - { - iWinningTeam[group] = owner; - } - // unassigned means this group is already contested, move on - else if ( iWinningTeam[group] == TEAM_UNASSIGNED ) - { - continue; - } - // if we find another one in the group that isn't the same owner, set the win to false - else if ( owner != iWinningTeam[group] ) - { - iWinningTeam[group] = TEAM_UNASSIGNED; - } - } - - // report the first win we find as the winner - for ( i=0;i= FIRST_GAME_TEAM ) - return iWinningTeam[i]; - } - - // no wins yet - return TEAM_UNASSIGNED; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamControlPointMaster::WouldNewCPOwnerWinGame( CTeamControlPoint *pPoint, int iNewOwner ) -{ - return ( TeamOwnsAllPoints( pPoint, iNewOwner ) == iNewOwner ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamControlPointMaster::IsBaseControlPoint( int iPointIndex ) -{ - bool retVal = false; - - for ( int iTeam = LAST_SHARED_TEAM+1; iTeam < GetNumberOfTeams(); iTeam++ ) - { - if ( GetBaseControlPoint( iTeam ) == iPointIndex ) - { - retVal = true; - break; - } - } - - return retVal; -} - -//----------------------------------------------------------------------------- -// Purpose: Get the control point for the specified team that's at their end of -// the control point chain. -//----------------------------------------------------------------------------- -int CTeamControlPointMaster::GetBaseControlPoint( int iTeam ) -{ - int iRetVal = -1; - int nLowestValue = 999, nHighestValue = -1; - int iLowestIndex = 0, iHighestIndex = 0; - - for( int i = 0 ; i < (int)m_ControlPoints.Count() ; i++ ) - { - CTeamControlPoint *pPoint = m_ControlPoints[i]; - - int iPointIndex = m_ControlPoints[i]->GetPointIndex(); - - if ( PlayingMiniRounds() && iTeam > LAST_SHARED_TEAM ) - { - if ( PointCanBeCapped( pPoint ) ) // is this point in the current round? - { - if ( iPointIndex > nHighestValue ) - { - nHighestValue = iPointIndex; - iHighestIndex = i; - } - - if ( iPointIndex < nLowestValue ) - { - nLowestValue = iPointIndex; - iLowestIndex = i; - } - } - } - else - { - if ( pPoint->GetDefaultOwner() != iTeam ) - { - continue; - } - - // If it's the first or the last point, it's their base - if ( iPointIndex == 0 || iPointIndex == (((int)m_ControlPoints.Count())-1) ) - { - iRetVal = iPointIndex; - break; - } - } - } - - if ( PlayingMiniRounds() && iTeam > LAST_SHARED_TEAM ) - { - if ( nLowestValue != 999 && nHighestValue != -1 ) - { - CTeamControlPoint *pLowestPoint = m_ControlPoints[iLowestIndex]; - CTeamControlPoint *pHighestPoint = m_ControlPoints[iHighestIndex]; - - // which point is owned by this team? - if ( ( pLowestPoint->GetDefaultOwner() == iTeam && pHighestPoint->GetDefaultOwner() == iTeam ) || // if the same team owns both, take the highest value to be the last point - ( pHighestPoint->GetDefaultOwner() == iTeam ) ) - { - iRetVal = nHighestValue; - } - else if ( pLowestPoint->GetDefaultOwner() == iTeam ) - { - iRetVal = nLowestValue; - } - } - } - - return iRetVal; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointMaster::InputEnable( inputdata_t &input ) -{ - m_bDisabled = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointMaster::InputDisable( inputdata_t &input ) -{ - m_bDisabled = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CTeamControlPointMaster::GetNumPointsOwnedByTeam( int iTeam ) -{ - int nCount = 0; - - for( int i = 0 ; i < (int)m_ControlPoints.Count() ; i++ ) - { - CTeamControlPoint *pPoint = m_ControlPoints[i]; - - if ( pPoint && ( pPoint->GetTeamNumber() == iTeam ) ) - { - nCount++; - } - } - - return nCount; -} - -//----------------------------------------------------------------------------- -// Purpose: returns how many more mini-rounds it will take for specified team -// to win, if they keep winning every mini-round -//----------------------------------------------------------------------------- -int CTeamControlPointMaster::CalcNumRoundsRemaining( int iTeam ) -{ - // To determine how many rounds remain for a given team if it consistently wins mini-rounds, we have to - // simulate forward each mini-round and track the control point ownership that would result - - // vector of control points the team owns in our forward-simulation - CUtlVector vecControlPointsOwned; - - // start with all the control points the team currently owns - FOR_EACH_MAP_FAST( m_ControlPoints, iControlPoint ) - { - if ( m_ControlPoints[iControlPoint]->GetOwner() == iTeam ) - { - vecControlPointsOwned.AddToTail( m_ControlPoints[iControlPoint] ); - } - } - - int iRoundsRemaining = 0; - - // keep simulating what will happen next if this team keeps winning, until - // it owns all the control points in the map - while ( vecControlPointsOwned.Count() < (int) m_ControlPoints.Count() ) - { - iRoundsRemaining++; - - // choose the next highest-priority round that is playable - for ( int i = 0 ; i < m_ControlPointRounds.Count() ; ++i ) - { - CTeamControlPointRound *pRound = m_ControlPointRounds[i]; - if ( !pRound ) - continue; - - // see if one team owns all control points in this round - int iRoundOwningTeam = TEAM_INVALID; - int iControlPoint; - for ( iControlPoint = 0; iControlPoint < pRound->m_ControlPoints.Count(); iControlPoint++ ) - { - CTeamControlPoint *pControlPoint = pRound->m_ControlPoints[iControlPoint]; - int iControlPointOwningTeam = TEAM_INVALID; - - // determine who owns this control point. - // First, check our simulated ownership - if ( vecControlPointsOwned.InvalidIndex() != vecControlPointsOwned.Find( pControlPoint ) ) - { - // This team has won this control point in forward simulation - iControlPointOwningTeam = iTeam; - } - else - { - // use actual control point ownership - iControlPointOwningTeam = pControlPoint->GetOwner(); - } - - if ( 0 == iControlPoint ) - { - // if this is the first control point, assign ownership to the team that owns this control point - iRoundOwningTeam = iControlPointOwningTeam; - } - else - { - // for all other control points, if the control point ownership does not match other control points, reset - // round ownership to no team - if ( iRoundOwningTeam != iControlPointOwningTeam ) - { - iRoundOwningTeam = TEAM_INVALID; - } - } - } - // this round is playable if all control points are not owned by one team (or owned by a team that can't win by capping them) - bool bPlayable = ( ( iRoundOwningTeam < FIRST_GAME_TEAM ) || ( iRoundOwningTeam == pRound->GetInvalidCapWinner() ) ); - if ( !bPlayable ) - continue; - - // Pretend this team played and won this round. It now owns all control points from this round. Add all the - // control points from this round that are not already own the owned list to the owned list - int iNewControlPointsOwned = 0; - FOR_EACH_VEC( pRound->m_ControlPoints, iControlPoint ) - { - CTeamControlPoint *pControlPoint = pRound->m_ControlPoints[iControlPoint]; - if ( vecControlPointsOwned.InvalidIndex() == vecControlPointsOwned.Find( pControlPoint ) ) - { - vecControlPointsOwned.AddToTail( pControlPoint ); - iNewControlPointsOwned++; - } - } - // sanity check: team being simulated should be owning at least one more new control point per round, or they're not making progress - Assert( iNewControlPointsOwned > 0 ); - - // now go back and pick the next playable round (if any) given the control points this team now owns, - // repeat until all control points are owned. The number of iterations it takes is the # of rounds remaining - // for this team to win. - break; - } - } - - return iRoundsRemaining; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CTeamControlPointMaster::GetPartialCapturePointRate( void ) -{ - return m_flPartialCapturePointsRate; -} -/* -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointMaster::ListRounds( void ) -{ - if ( PlayingMiniRounds() ) - { - ConMsg( "Rounds in this map:\n\n" ); - - for ( int i = 0; i < m_ControlPointRounds.Count() ; ++i ) - { - CTeamControlPointRound* pRound = m_ControlPointRounds[i]; - - if ( pRound ) - { - const char *pszName = STRING( pRound->GetEntityName() ); - ConMsg( "%s\n", pszName ); - } - } - } - else - { - ConMsg( "* No rounds in this map *\n" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void cc_ListRounds( void ) -{ - CTeamControlPointMaster *pMaster = g_hControlPointMasters.Count() ? g_hControlPointMasters[0] : NULL; - if ( pMaster ) - { - pMaster->ListRounds(); - } -} - -static ConCommand listrounds( "listrounds", cc_ListRounds, "List the rounds for the current map", FCVAR_CHEAT ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void cc_PlayRound( const CCommand& args ) -{ - if ( args.ArgC() > 1 ) - { - CTeamplayRoundBasedRules *pRules = dynamic_cast( GameRules() ); - CTeamControlPointMaster *pMaster = g_hControlPointMasters.Count() ? g_hControlPointMasters[0] : NULL; - - if ( pRules && pMaster ) - { - if ( pMaster->PlayingMiniRounds() ) - { - // did we get the name of a round? - CTeamControlPointRound *pRound = dynamic_cast( gEntList.FindEntityByName( NULL, args[1] ) ); - - if ( pRound ) - { - pRules->SetRoundToPlayNext( pRound->GetEntityName() ); - mp_restartgame.SetValue( 5 ); - } - else - { - ConMsg( "* Round \"%s\" not found in this map *\n", args[1] ); - } - } - } - } - else - { - ConMsg( "Usage: playround < round name >\n" ); - } -} - -static ConCommand playround( "playround", cc_PlayRound, "Play the selected round\n\tArgument: {round name given by \"listrounds\" command}", FCVAR_CHEAT ); -*/ diff --git a/game/server/team_control_point_master.h b/game/server/team_control_point_master.h deleted file mode 100644 index 3db254f7a..000000000 --- a/game/server/team_control_point_master.h +++ /dev/null @@ -1,206 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef TEAM_CONTROL_POINT_MASTER_H -#define TEAM_CONTROL_POINT_MASTER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "utlmap.h" -#include "team.h" -#include "teamplay_gamerules.h" -#include "team_control_point.h" -#include "trigger_area_capture.h" -#include "team_objectiveresource.h" -#include "team_control_point_round.h" - -#define CPM_THINK "CTeamControlPointMasterCPMThink" -#define CPM_POSTINITTHINK "CTeamControlPointMasterCPMPostInitThink" - -//----------------------------------------------------------------------------- -// Purpose: One ControlPointMaster is spawned per level. Shortly after spawning it detects all the Control -// points in the map and puts them into the m_ControlPoints. From there it detects the state -// where all points are captured and resets them if necessary It gives points every time interval to -// the owners of the points -//----------------------------------------------------------------------------- -class CTeamControlPointMaster : public CBaseEntity -{ - DECLARE_CLASS( CTeamControlPointMaster, CBaseEntity ); - - // Derived, game-specific control point masters must override these functions -public: - CTeamControlPointMaster(); - - // Used to find game specific entities - virtual const char *GetTriggerAreaCaptureName( void ) { return "trigger_capture_area"; } - virtual const char *GetControlPointName( void ) { return "team_control_point"; } - virtual const char *GetControlPointRoundName( void ) { return "team_control_point_round"; } - -public: - virtual void Spawn( void ); - virtual void UpdateOnRemove( void ); - virtual bool KeyValue( const char *szKeyName, const char *szValue ); - virtual void Precache( void ); - virtual void Activate( void ); - - void RoundRespawn( void ); - void Reset( void ); - - int GetNumPoints( void ){ return m_ControlPoints.Count(); } - int GetNumPointsOwnedByTeam( int iTeam ); - int CalcNumRoundsRemaining( int iTeam ); - - bool IsActive( void ) { return ( m_bDisabled == false ); } - - void FireTeamWinOutput( int iWinningTeam ); - - bool PointCanBeCapped( CTeamControlPoint *pPoint ); - void CheckWinConditions( void ); - - bool WouldNewCPOwnerWinGame( CTeamControlPoint *pPoint, int iNewOwner ); - - int GetBaseControlPoint( int iTeam ); - bool IsBaseControlPoint( int iPointIndex ); - - bool PlayingMiniRounds( void ){ return ( m_ControlPointRounds.Count() > 0 ); } - - float PointLastContestedAt( int point ); - CTeamControlPoint *GetControlPoint( int point ) - { - Assert( point >= 0 ); - Assert( point < MAX_CONTROL_POINTS ); - - for ( unsigned int i = 0; i < m_ControlPoints.Count(); i++ ) - { - CTeamControlPoint *pPoint = m_ControlPoints[i]; - if ( pPoint && pPoint->GetPointIndex() == point ) - return pPoint; - } - - return NULL; - } - - CTeamControlPointRound *GetCurrentRound( void ) - { - if ( !PlayingMiniRounds() || m_iCurrentRoundIndex == -1 ) - { - return NULL; - } - - return m_ControlPointRounds[m_iCurrentRoundIndex]; - } - - string_t GetRoundToUseAfterRestart( void ) - { - int nCurrentPriority = -1; - int nHighestPriority = -1; - - string_t nRetVal = NULL_STRING; - - if ( PlayingMiniRounds() && GetCurrentRound() ) - { - nCurrentPriority = GetCurrentRound()->GetPriorityValue(); - nHighestPriority = GetHighestRoundPriorityValue(); - - // if the current round has the highest priority, then use it again - if ( nCurrentPriority == nHighestPriority ) - { - nRetVal = GetCurrentRound()->GetEntityName(); - } - } - - return nRetVal; - } - - void FireRoundStartOutput( void ); - void FireRoundEndOutput( void ); - - bool ShouldScorePerCapture( void ){ return m_bScorePerCapture; } - bool ShouldPlayAllControlPointRounds( void ){ return m_bPlayAllRounds; } - bool FindControlPointRoundToPlay( void ); // checks to see if there are any more rounds to play (but doesn't actually "get" one to play) - -// void ListRounds( void ); - - float GetPartialCapturePointRate( void ); - -private: - void EXPORT CPMThink( void ); - - void SetBaseControlPoints( void ); - int TeamOwnsAllPoints( CTeamControlPoint *pOverridePoint = NULL, int iOverrideNewTeam = TEAM_UNASSIGNED ); - - bool FindControlPoints( void ); // look in the map to find active control points - bool FindControlPointRounds( void ); // look in the map to find active control point rounds - bool GetControlPointRoundToPlay( void ); // gets the next round we should play - bool SelectSpecificRound( void ); // selects a specific round to play - - int GetHighestRoundPriorityValue( void ) - { - int nRetVal = -1; - - // rounds are sorted with the higher priority rounds first - for ( int i = 0 ; i < m_ControlPointRounds.Count() ; ++i ) - { - CTeamControlPointRound *pRound = m_ControlPointRounds[i]; - - if ( pRound ) - { - if ( pRound->GetPriorityValue() > nRetVal ) - { - nRetVal = pRound->GetPriorityValue(); - } - } - } - - return nRetVal; - } - - void RegisterRoundBeingPlayed( void ); - - CUtlMap m_ControlPoints; - - bool m_bFoundPoints; // true when the control points have been found and the array is initialized - - CUtlVector m_ControlPointRounds; - int m_iCurrentRoundIndex; - - DECLARE_DATADESC(); - - bool m_bDisabled; - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - - void InputRoundSpawn( inputdata_t &inputdata ); - void InputRoundActivate( inputdata_t &inputdata ); - void InputSetWinner( inputdata_t &inputdata ); - void InputSetWinnerAndForceCaps( inputdata_t &inputdata ); - void InputSetCapLayout( inputdata_t &inputdata ); - - void InternalSetWinner( int iTeam ); - - void HandleRandomOwnerControlPoints( void ); - - string_t m_iszTeamBaseIcons[MAX_TEAMS]; - int m_iTeamBaseIcons[MAX_TEAMS]; - string_t m_iszCapLayoutInHUD; - - int m_iInvalidCapWinner; - bool m_bSwitchTeamsOnWin; - bool m_bScorePerCapture; - bool m_bPlayAllRounds; - - bool m_bFirstRoundAfterRestart; - - COutputEvent m_OnWonByTeam1; - COutputEvent m_OnWonByTeam2; - - float m_flPartialCapturePointsRate; -}; - -extern CUtlVector< CHandle > g_hControlPointMasters; - -#endif // TEAM_CONTROL_POINT_MASTER_H diff --git a/game/server/team_control_point_round.cpp b/game/server/team_control_point_round.cpp deleted file mode 100644 index 409efe9dd..000000000 --- a/game/server/team_control_point_round.cpp +++ /dev/null @@ -1,374 +0,0 @@ -//===== Copyright 1996-2006, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#include "cbase.h" -#include "team_control_point_master.h" -#include "teamplayroundbased_gamerules.h" -#include "team_control_point_round.h" - -BEGIN_DATADESC( CTeamControlPointRound ) - DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ), - - DEFINE_KEYFIELD( m_iszCPNames, FIELD_STRING, "cpr_cp_names" ), - DEFINE_KEYFIELD( m_nPriority, FIELD_INTEGER, "cpr_priority" ), - DEFINE_KEYFIELD( m_iInvalidCapWinner, FIELD_INTEGER, "cpr_restrict_team_cap_win" ), - DEFINE_KEYFIELD( m_iszPrintName, FIELD_STRING, "cpr_printname" ), -// DEFINE_FIELD( m_ControlPoints, CUtlVector < CHandle < CTeamControlPoint > > ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - - DEFINE_INPUTFUNC( FIELD_VOID, "RoundSpawn", InputRoundSpawn ), - - DEFINE_OUTPUT( m_OnStart, "OnStart" ), - DEFINE_OUTPUT( m_OnEnd, "OnEnd" ), - DEFINE_OUTPUT( m_OnWonByTeam1, "OnWonByTeam1" ), - DEFINE_OUTPUT( m_OnWonByTeam2, "OnWonByTeam2" ), -END_DATADESC() - -LINK_ENTITY_TO_CLASS( team_control_point_round, CTeamControlPointRound ); - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointRound::Spawn( void ) -{ - SetTouch( NULL ); - - BaseClass::Spawn(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointRound::Activate( void ) -{ - BaseClass::Activate(); - - FindControlPoints(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointRound::FindControlPoints( void ) -{ - // Let out control point masters know that the round has started - CTeamControlPointMaster *pMaster = g_hControlPointMasters.Count() ? g_hControlPointMasters[0] : NULL; - - if ( pMaster ) - { - // go through all the points - CBaseEntity *pEnt = gEntList.FindEntityByClassname( NULL, pMaster->GetControlPointName() ); - - while( pEnt ) - { - CTeamControlPoint *pPoint = assert_cast(pEnt); - - if ( pPoint ) - { - const char *pString = STRING( m_iszCPNames ); - const char *pName = STRING( pPoint->GetEntityName() ); - - // HACK to work around a problem with cp_a being returned for an entity name with cp_A - const char *pos = Q_stristr( pString, pName ); - if ( pos ) - { - int len = Q_strlen( STRING( pPoint->GetEntityName() ) ); - if ( *(pos + len) == ' ' || *(pos + len) == '\0' ) - { - if( m_ControlPoints.Find( pPoint ) == m_ControlPoints.InvalidIndex() ) - { - DevMsg( 2, "Adding control point %s to control point round %s\n", pPoint->GetEntityName().ToCStr(), GetEntityName().ToCStr() ); - m_ControlPoints.AddToHead( pPoint ); - } - } - } - } - - pEnt = gEntList.FindEntityByClassname( pEnt, pMaster->GetControlPointName() ); - } - } - - if( m_ControlPoints.Count() == 0 ) - { - Warning( "Error! No control points found in map for team_game_round %s!\n", GetEntityName().ToCStr() ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Check that the points aren't all held by one team if they are -// this will reset the round and will reset all the points -//----------------------------------------------------------------------------- -int CTeamControlPointRound::CheckWinConditions( void ) -{ - int iWinners = TeamOwnsAllPoints(); - if ( ( iWinners >= FIRST_GAME_TEAM ) && - ( iWinners != m_iInvalidCapWinner ) ) - { - FireTeamWinOutput( iWinners ); - return iWinners; - } - - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointRound::FireTeamWinOutput( int iWinningTeam ) -{ - // Remap team so that first game team = 1 - switch( iWinningTeam - FIRST_GAME_TEAM+1 ) - { - case 1: - m_OnWonByTeam1.FireOutput( this, this ); - break; - case 2: - m_OnWonByTeam2.FireOutput( this, this ); - break; - default: - Assert(0); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CTeamControlPointRound::GetPointOwner( int point ) -{ - Assert( point >= 0 ); - Assert( point < MAX_CONTROL_POINTS ); - - CTeamControlPoint *pPoint = m_ControlPoints[point]; - - if ( pPoint ) - return pPoint->GetOwner(); - - return TEAM_UNASSIGNED; -} - -//----------------------------------------------------------------------------- -// Purpose: This function returns the team that owns all the cap points. -// If its not the case that one team owns them all, it returns 0. -// -// Can be passed an overriding team. If this is not null, the passed team -// number will be used for that cp. Used to predict if that CP changing would -// win the game. -//----------------------------------------------------------------------------- -int CTeamControlPointRound::TeamOwnsAllPoints( CTeamControlPoint *pOverridePoint /* = NULL */, int iOverrideNewTeam /* = TEAM_UNASSIGNED */ ) -{ - int iWinningTeam = TEAM_INVALID; - - // if TEAM_INVALID, haven't found a flag yet - // if TEAM_UNASSIGNED, it's still being contested - - // for each control point - for( int i = 0 ; i < m_ControlPoints.Count() ; i++ ) - { - int owner = m_ControlPoints[i]->GetOwner(); - - if ( pOverridePoint == m_ControlPoints[i] ) - { - owner = iOverrideNewTeam; - } - - // the first one we find, set the win to true - if ( iWinningTeam == TEAM_INVALID ) - { - iWinningTeam = owner; - } - // unassigned means this is being contested, move on - else if ( iWinningTeam == TEAM_UNASSIGNED ) - { - continue; - } - // if we find another one in the group that isn't the same owner, set the win to false - else if ( owner != iWinningTeam ) - { - iWinningTeam = TEAM_UNASSIGNED; - } - } - - // report the first win we find as the winner - if ( iWinningTeam >= FIRST_GAME_TEAM ) - { - return iWinningTeam; - } - - // no wins yet - return TEAM_UNASSIGNED; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamControlPointRound::WouldNewCPOwnerWinGame( CTeamControlPoint *pPoint, int iNewOwner ) -{ - return ( TeamOwnsAllPoints( pPoint, iNewOwner ) == iNewOwner ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointRound::InputEnable( inputdata_t &input ) -{ - m_bDisabled = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointRound::InputDisable( inputdata_t &input ) -{ - m_bDisabled = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointRound::InputRoundSpawn( inputdata_t &input ) -{ - // clear out old control points - m_ControlPoints.RemoveAll(); - - // find the control points - FindControlPoints(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointRound::SetupSpawnPoints( void ) -{ - CTeamplayRoundBasedRules *pRules = TeamplayRoundBasedRules(); - - if ( pRules ) - { - pRules->SetupSpawnPointsForRound(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointRound::SelectedToPlay( void ) -{ - SetupSpawnPoints(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointRound::FireOnStartOutput( void ) -{ - m_OnStart.FireOutput( this, this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamControlPointRound::FireOnEndOutput( void ) -{ - m_OnEnd.FireOutput( this, this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamControlPointRound::IsControlPointInRound( CTeamControlPoint *pPoint ) -{ - if ( !pPoint ) - { - return false; - } - - return ( m_ControlPoints.Find( pPoint ) != m_ControlPoints.InvalidIndex() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamControlPointRound::IsPlayable( void ) -{ - int iWinners = TeamOwnsAllPoints(); - - if ( ( iWinners >= FIRST_GAME_TEAM ) && - ( iWinners != m_iInvalidCapWinner ) ) - { - return false; // someone has already won this round - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamControlPointRound::MakePlayable( void ) -{ - CTeamControlPointMaster *pMaster = g_hControlPointMasters.Count() ? g_hControlPointMasters[0] : NULL; - if ( pMaster ) - { - if ( !IsPlayable() ) - { - // we need to try switching the owners of the teams to make this round playable - for ( int i = FIRST_GAME_TEAM ; i < GetNumberOfTeams() ; i++ ) - { - for ( int j = 0 ; j < m_ControlPoints.Count() ; j++ ) - { - if ( ( !pMaster->IsBaseControlPoint( m_ControlPoints[j]->GetPointIndex() ) ) && // this is NOT the base point for one of the teams (we don't want to assign the base to the wrong team) - ( !WouldNewCPOwnerWinGame( m_ControlPoints[j], i ) ) ) // making this change would make this round playable - { - // need to find the trigger area associated with this point - CBaseEntity *pEnt = gEntList.FindEntityByClassname( NULL, pMaster->GetTriggerAreaCaptureName() ); - while( pEnt ) - { - CTriggerAreaCapture *pArea = assert_cast( pEnt ); - if ( pArea ) - { - if ( pArea->TeamCanCap( i ) ) - { - CHandle hPoint = pArea->GetControlPoint(); - if ( hPoint == m_ControlPoints[j] ) - { - // found! - pArea->ForceOwner( i ); // this updates the trigger_area *and* the control_point - return true; - } - } - } - - pEnt = gEntList.FindEntityByClassname( pEnt, pMaster->GetTriggerAreaCaptureName() ); - } - } - } - } - } - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: returns the first point found that the given team owns -//----------------------------------------------------------------------------- -CHandle CTeamControlPointRound::GetPointOwnedBy( int iTeam ) -{ - for( int i = 0 ; i < m_ControlPoints.Count() ; i++ ) - { - if ( m_ControlPoints[i]->GetOwner() == iTeam ) - { - return m_ControlPoints[i]; - } - } - - return NULL; -} diff --git a/game/server/team_control_point_round.h b/game/server/team_control_point_round.h deleted file mode 100644 index e019f1ebc..000000000 --- a/game/server/team_control_point_round.h +++ /dev/null @@ -1,83 +0,0 @@ -//====== Copyright 1996-2006, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef TEAM_CONTROL_POINT_ROUND_H -#define TEAM_CONTROL_POINT_ROUND_H -#ifdef _WIN32 -#pragma once -#endif - -#include "utlmap.h" -#include "team.h" -#include "teamplay_gamerules.h" -#include "team_control_point.h" -#include "trigger_area_capture.h" -#include "team_objectiveresource.h" - - -class CTeamControlPointRound : public CBaseEntity -{ - DECLARE_CLASS( CTeamControlPointRound, CBaseEntity ); - -public: - virtual void Spawn( void ); - virtual void Activate( void ); - - bool IsDisabled( void ){ return m_bDisabled; } - - int GetPointOwner( int point ); -// int CountAdvantageFlags( int team ); - bool WouldNewCPOwnerWinGame( CTeamControlPoint *pPoint, int iNewOwner ); - - void FireTeamWinOutput( int iWinningTeam ); - - void SelectedToPlay( void ); - - int CheckWinConditions( void ); // returns the team number of the team that's won, or returns -1 if no winner - - int GetPriorityValue( void ) const { return m_nPriority; } - - bool IsPlayable( void ); - bool MakePlayable( void ); - bool IsControlPointInRound( CTeamControlPoint *pPoint ); - - void FireOnStartOutput( void ); - void FireOnEndOutput( void ); - - inline const char *GetName( void ) { return STRING(m_iszPrintName); } - - CHandle GetPointOwnedBy( int iTeam ); - - bool RoundOwnedByTeam( int iTeam ){ return ( TeamOwnsAllPoints() == iTeam ); } - int GetInvalidCapWinner() { return m_iInvalidCapWinner; } - - CUtlVector< CHandle > m_ControlPoints; - -private: - void FindControlPoints( void ); //look in the map to find the control points for this round - void SetupSpawnPoints( void ); - int TeamOwnsAllPoints( CTeamControlPoint *pOverridePoint = NULL, int iOverrideNewTeam = TEAM_UNASSIGNED ); - - DECLARE_DATADESC(); - - bool m_bDisabled; - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - - void InputRoundSpawn( inputdata_t &inputdata ); - - string_t m_iszCPNames; - int m_nPriority; - int m_iInvalidCapWinner; - string_t m_iszPrintName; - - COutputEvent m_OnStart; - COutputEvent m_OnEnd; - COutputEvent m_OnWonByTeam1; - COutputEvent m_OnWonByTeam2; -}; - -#endif // TEAM_CONTROL_POINT_ROUND_H diff --git a/game/server/team_objectiveresource.cpp b/game/server/team_objectiveresource.cpp deleted file mode 100644 index 194a8d334..000000000 --- a/game/server/team_objectiveresource.cpp +++ /dev/null @@ -1,472 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: An entity that networks the state of the game's objectives. -// May contain data for objectives that aren't used by your mod, but -// the extra data will never be networked as long as it's zeroed out. -// -//============================================================================= -#include "cbase.h" -#include "team_objectiveresource.h" -#include "shareddefs.h" -#include -#include "team.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define CAPHUD_PARITY_BITS 6 -#define CAPHUD_PARITY_MASK ((1<curtime + LAZY_UPDATE_TIME ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::ObjectiveThink( void ) -{ - SetNextThink( gpGlobals->curtime + LAZY_UPDATE_TIME ); - - for ( int i = 0; i < m_iNumControlPoints; i++ ) - { - if ( m_iCappingTeam[i] ) - { - m_flLazyCapPerc.Set( i, m_flCapPercentages[i] ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: The objective resource is always transmitted to clients -//----------------------------------------------------------------------------- -int CBaseTeamObjectiveResource::UpdateTransmitState() -{ - // ALWAYS transmit to all clients. - return SetTransmitState( FL_EDICT_ALWAYS ); -} - -//----------------------------------------------------------------------------- -// Purpose: Round is starting, reset state -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::ResetControlPoints( void ) -{ - for ( int i=0; i < MAX_CONTROL_POINTS; i++ ) - { - m_iCappingTeam.Set( i, TEAM_UNASSIGNED ); - m_iTeamInZone.Set( i, TEAM_UNASSIGNED ); - m_bInMiniRound.Set( i, true ); - - for ( int team = 0; team < MAX_CONTROL_POINT_TEAMS; team++ ) - { - m_iNumTeamMembers.Set( TEAM_ARRAY( i, team ), 0 ); - } - } - - UpdateCapHudElement(); - m_bControlPointsReset = !m_bControlPointsReset; -} - -//----------------------------------------------------------------------------- -// Purpose: Data setting functions -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::SetNumControlPoints( int num ) -{ - Assert( num <= MAX_CONTROL_POINTS ); - m_iNumControlPoints = num; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::SetCPIcons( int index, int iTeam, int iIcon ) -{ - AssertValidIndex(index); - m_iTeamIcons.Set( TEAM_ARRAY( index, iTeam ), iIcon ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::SetCPOverlays( int index, int iTeam, int iIcon ) -{ - AssertValidIndex(index); - m_iTeamOverlays.Set( TEAM_ARRAY( index, iTeam ), iIcon ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::SetTeamBaseIcons( int iTeam, int iBaseIcon ) -{ - Assert( iTeam >= 0 && iTeam < MAX_TEAMS ); - m_iTeamBaseIcons.Set( iTeam, iBaseIcon ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::SetCPPosition( int index, const Vector& vPosition ) -{ - AssertValidIndex(index); - m_vCPPositions.Set( index, vPosition ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::SetCPVisible( int index, bool bVisible ) -{ - AssertValidIndex(index); - m_bCPIsVisible.Set( index, bVisible ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::SetWarnOnCap( int index, int iWarnLevel ) -{ - AssertValidIndex(index); - m_iWarnOnCap.Set( index, iWarnLevel ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::SetWarnSound( int index, string_t iszSound ) -{ - AssertValidIndex(index); - m_iszWarnSound.Set( index, iszSound ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::SetCPRequiredCappers( int index, int iTeam, int iReqPlayers ) -{ - AssertValidIndex(index); - m_iTeamReqCappers.Set( TEAM_ARRAY( index, iTeam ), iReqPlayers ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::SetCPCapTime( int index, int iTeam, float flTime ) -{ - AssertValidIndex(index); - m_flTeamCapTime.Set( TEAM_ARRAY( index, iTeam ), flTime ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::SetCPCapPercentage( int index, float flTime ) -{ - AssertValidIndex(index); - m_flCapPercentages[index] = flTime; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CBaseTeamObjectiveResource::GetCPCapPercentage( int index ) -{ - AssertValidIndex(index); - return m_flCapPercentages[index]; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::SetTeamCanCap( int index, int iTeam, bool bCanCap ) -{ - AssertValidIndex(index); - m_bTeamCanCap.Set( TEAM_ARRAY( index, iTeam ), bCanCap ); - UpdateCapHudElement(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::SetBaseCP( int index, int iTeam ) -{ - Assert( iTeam < MAX_TEAMS ); - m_iBaseControlPoints.Set( iTeam, index ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::SetPreviousPoint( int index, int iTeam, int iPrevIndex, int iPrevPoint ) -{ - AssertValidIndex(index); - Assert( iPrevIndex >= 0 && iPrevIndex < MAX_PREVIOUS_POINTS ); - int iIntIndex = iPrevIndex + (index * MAX_PREVIOUS_POINTS) + (iTeam * MAX_CONTROL_POINTS * MAX_PREVIOUS_POINTS); - m_iPreviousPoints.Set( iIntIndex, iPrevPoint ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBaseTeamObjectiveResource::GetPreviousPointForPoint( int index, int team, int iPrevIndex ) -{ - AssertValidIndex(index); - Assert( iPrevIndex >= 0 && iPrevIndex < MAX_PREVIOUS_POINTS ); - int iIntIndex = iPrevIndex + (index * MAX_PREVIOUS_POINTS) + (team * MAX_CONTROL_POINTS * MAX_PREVIOUS_POINTS); - return m_iPreviousPoints[ iIntIndex ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseTeamObjectiveResource::TeamCanCapPoint( int index, int team ) -{ - AssertValidIndex(index); - return m_bTeamCanCap[ TEAM_ARRAY( index, team ) ]; -} - -//----------------------------------------------------------------------------- -// Purpose: Data setting functions -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::SetNumPlayers( int index, int team, int iNumPlayers ) -{ - AssertValidIndex(index); - m_iNumTeamMembers.Set( TEAM_ARRAY( index, team ), iNumPlayers ); - UpdateCapHudElement(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::StartCap( int index, int team ) -{ - AssertValidIndex(index); - if ( m_iCappingTeam.Get( index ) != team ) - { - m_iCappingTeam.Set( index, team ); - UpdateCapHudElement(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::SetOwningTeam( int index, int team ) -{ - AssertValidIndex(index); - m_iOwner.Set( index, team ); - - // clear the capper - m_iCappingTeam.Set( index, TEAM_UNASSIGNED ); - UpdateCapHudElement(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::SetCappingTeam( int index, int team ) -{ - AssertValidIndex(index); - if ( m_iCappingTeam.Get( index ) != team ) - { - m_iCappingTeam.Set( index, team ); - UpdateCapHudElement(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::SetTeamInZone( int index, int team ) -{ - AssertValidIndex(index); - if ( m_iTeamInZone.Get( index ) != team ) - { - m_iTeamInZone.Set( index, team ); - UpdateCapHudElement(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::SetCapBlocked( int index, bool bBlocked ) -{ - AssertValidIndex(index); - if ( m_bBlocked.Get( index ) != bBlocked ) - { - m_bBlocked.Set( index, bBlocked ); - UpdateCapHudElement(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBaseTeamObjectiveResource::GetOwningTeam( int index ) -{ - if ( index >= m_iNumControlPoints ) - return TEAM_UNASSIGNED; - - return m_iOwner[index]; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::UpdateCapHudElement( void ) -{ - m_iUpdateCapHudParity = (m_iUpdateCapHudParity + 1) & CAPHUD_PARITY_MASK; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseTeamObjectiveResource::SetTrainPathDistance( int index, float flDistance ) -{ - AssertValidIndex(index); - - m_flPathDistance.Set( index, flDistance ); -} diff --git a/game/server/team_objectiveresource.h b/game/server/team_objectiveresource.h deleted file mode 100644 index 5e66300b7..000000000 --- a/game/server/team_objectiveresource.h +++ /dev/null @@ -1,168 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef TEAM_OBJECTIVERESOURCE_H -#define TEAM_OBJECTIVERESOURCE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "shareddefs.h" - -#define TEAM_ARRAY( index, team ) (index + (team * MAX_CONTROL_POINTS)) - -//----------------------------------------------------------------------------- -// Purpose: An entity that networks the state of the game's objectives. -// May contain data for objectives that aren't used by your mod, but -// the extra data will never be networked as long as it's zeroed out. -//----------------------------------------------------------------------------- -class CBaseTeamObjectiveResource : public CBaseEntity -{ - DECLARE_CLASS( CBaseTeamObjectiveResource, CBaseEntity ); -public: - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - CBaseTeamObjectiveResource(); - ~CBaseTeamObjectiveResource(); - - virtual void Spawn( void ); - virtual int UpdateTransmitState(void); - - virtual void ObjectiveThink( void ); - - //-------------------------------------------------------------------- - // CONTROL POINT DATA - //-------------------------------------------------------------------- -public: - void ResetControlPoints( void ); - - // Data functions, called to set up the state at the beginning of a round - void SetNumControlPoints( int num ); - int GetNumControlPoints( void ) { return m_iNumControlPoints; } - void SetCPIcons( int index, int iTeam, int iIcon ); - void SetCPOverlays( int index, int iTeam, int iIcon ); - void SetTeamBaseIcons( int iTeam, int iBaseIcon ); - void SetCPPosition( int index, const Vector& vPosition ); - void SetCPVisible( int index, bool bVisible ); - void SetCPRequiredCappers( int index, int iTeam, int iReqPlayers ); - void SetCPCapTime( int index, int iTeam, float flTime ); - void SetCPCapPercentage( int index, float flTime ); - float GetCPCapPercentage( int index ); - void SetTeamCanCap( int index, int iTeam, bool bCanCap ); - void SetBaseCP( int index, int iTeam ); - void SetPreviousPoint( int index, int iTeam, int iPrevIndex, int iPrevPoint ); - int GetPreviousPointForPoint( int index, int team, int iPrevIndex ); - bool TeamCanCapPoint( int index, int team ); - void SetCapLayoutInHUD( const char *pszLayout ) { Q_strncpy(m_pszCapLayoutInHUD.GetForModify(), pszLayout, MAX_CAPLAYOUT_LENGTH ); } - void SetWarnOnCap( int index, int iWarnLevel ); - void SetWarnSound( int index, string_t iszSound ); - - // State functions, called many times - void SetNumPlayers( int index, int team, int iNumPlayers ); - void StartCap( int index, int team ); - void SetOwningTeam( int index, int team ); - void SetCappingTeam( int index, int team ); - void SetTeamInZone( int index, int team ); - void SetCapBlocked( int index, bool bBlocked ); - int GetOwningTeam( int index ); - - void AssertValidIndex( int index ) - { - Assert( 0 <= index && index <= MAX_CONTROL_POINTS && index < m_iNumControlPoints ); - } - - int GetBaseControlPointForTeam( int iTeam ) - { - Assert( iTeam < MAX_TEAMS ); - return m_iBaseControlPoints[iTeam]; - } - - int GetCappingTeam( int index ) - { - if ( index >= m_iNumControlPoints ) - return TEAM_UNASSIGNED; - - return m_iCappingTeam[index]; - } - - void SetTimerInHUD( CBaseEntity *pTimer ) - { - m_iTimerToShowInHUD = pTimer ? pTimer->entindex() : 0; - } - - - void SetStopWatchTimer( CBaseEntity *pTimer ) - { - m_iStopWatchTimer = pTimer ? pTimer->entindex() : 0; - } - - int GetTimerInHUD( void ) { return m_iTimerToShowInHUD; } - - // Mini-rounds data - void SetPlayingMiniRounds( bool bPlayingMiniRounds ){ m_bPlayingMiniRounds = bPlayingMiniRounds; } - bool PlayingMiniRounds( void ){ return m_bPlayingMiniRounds; } - void SetInMiniRound( int index, bool bInRound ) { m_bInMiniRound.Set( index, bInRound ); } - bool IsInMiniRound( int index ) { return m_bInMiniRound[index]; } - - void UpdateCapHudElement( void ); - - // Train Path data - void SetTrainPathDistance( int index, float flDistance ); - -private: - CNetworkVar( int, m_iTimerToShowInHUD ); - CNetworkVar( int, m_iStopWatchTimer ); - - CNetworkVar( int, m_iNumControlPoints ); - CNetworkVar( bool, m_bPlayingMiniRounds ); - CNetworkVar( bool, m_bControlPointsReset ); - CNetworkVar( int, m_iUpdateCapHudParity ); - - // data variables - CNetworkArray( Vector, m_vCPPositions, MAX_CONTROL_POINTS ); - CNetworkArray( int, m_bCPIsVisible, MAX_CONTROL_POINTS ); - CNetworkArray( float, m_flLazyCapPerc, MAX_CONTROL_POINTS ); - CNetworkArray( int, m_iTeamIcons, MAX_CONTROL_POINTS * MAX_CONTROL_POINT_TEAMS ); - CNetworkArray( int, m_iTeamOverlays, MAX_CONTROL_POINTS * MAX_CONTROL_POINT_TEAMS ); - CNetworkArray( int, m_iTeamReqCappers, MAX_CONTROL_POINTS * MAX_CONTROL_POINT_TEAMS ); - CNetworkArray( float, m_flTeamCapTime, MAX_CONTROL_POINTS * MAX_CONTROL_POINT_TEAMS ); - CNetworkArray( int, m_iPreviousPoints, MAX_CONTROL_POINTS * MAX_CONTROL_POINT_TEAMS * MAX_PREVIOUS_POINTS ); - CNetworkArray( bool, m_bTeamCanCap, MAX_CONTROL_POINTS * MAX_CONTROL_POINT_TEAMS ); - CNetworkArray( int, m_iTeamBaseIcons, MAX_TEAMS ); - CNetworkArray( int, m_iBaseControlPoints, MAX_TEAMS ); - CNetworkArray( bool, m_bInMiniRound, MAX_CONTROL_POINTS ); - CNetworkArray( int, m_iWarnOnCap, MAX_CONTROL_POINTS ); - CNetworkArray( string_t, m_iszWarnSound, MAX_CONTROL_POINTS ); - CNetworkArray( float, m_flPathDistance, MAX_CONTROL_POINTS ); - - // change when players enter/exit an area - CNetworkArray( int, m_iNumTeamMembers, MAX_CONTROL_POINTS * MAX_CONTROL_POINT_TEAMS ); - - // changes when a cap starts. start and end times are calculated on client - CNetworkArray( int, m_iCappingTeam, MAX_CONTROL_POINTS ); - - CNetworkArray( int, m_iTeamInZone, MAX_CONTROL_POINTS ); - CNetworkArray( bool, m_bBlocked, MAX_CONTROL_POINTS ); - - // changes when a point is successfully captured - CNetworkArray( int, m_iOwner, MAX_CONTROL_POINTS ); - - // describes how to lay out the cap points in the hud - CNetworkString( m_pszCapLayoutInHUD, MAX_CAPLAYOUT_LENGTH ); - - // Not networked, because the client recalculates it - float m_flCapPercentages[ MAX_CONTROL_POINTS ]; -}; - -extern CBaseTeamObjectiveResource *g_pObjectiveResource; - -inline CBaseTeamObjectiveResource *ObjectiveResource() -{ - return g_pObjectiveResource; -} - -#endif // TEAM_OBJECTIVERESOURCE_H diff --git a/game/server/team_spawnpoint.cpp b/game/server/team_spawnpoint.cpp deleted file mode 100644 index 9b37e740d..000000000 --- a/game/server/team_spawnpoint.cpp +++ /dev/null @@ -1,133 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Team spawnpoint handling -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "entitylist.h" -#include "entityoutput.h" -#include "player.h" -#include "eventqueue.h" -#include "gamerules.h" -#include "team_spawnpoint.h" -#include "team.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -LINK_ENTITY_TO_CLASS( info_player_teamspawn, CTeamSpawnPoint ); - -BEGIN_DATADESC( CTeamSpawnPoint ) - - // keys - DEFINE_KEYFIELD( m_iDisabled, FIELD_INTEGER, "StartDisabled" ), - - // input functions - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - - // outputs - DEFINE_OUTPUT( m_OnPlayerSpawn, "OnPlayerSpawn" ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: Attach this spawnpoint to it's team -//----------------------------------------------------------------------------- -void CTeamSpawnPoint::Activate( void ) -{ - BaseClass::Activate(); - if ( GetTeamNumber() > 0 && GetTeamNumber() <= MAX_TEAMS ) - { - GetGlobalTeam( GetTeamNumber() )->AddSpawnpoint( this ); - } - else - { - Warning( "info_player_teamspawn with invalid team number: %d\n", GetTeamNumber() ); - UTIL_Remove( this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Is this spawnpoint ready for a player to spawn in? -//----------------------------------------------------------------------------- -bool CTeamSpawnPoint::IsValid( CBasePlayer *pPlayer ) -{ - CBaseEntity *ent = NULL; - for ( CEntitySphereQuery sphere( GetAbsOrigin(), 128 ); ( ent = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() ) - { - // if ent is a client, don't spawn on 'em - CBaseEntity *plent = ent; - if ( plent && plent->IsPlayer() && plent != pPlayer ) - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamSpawnPoint::InputEnable( inputdata_t &inputdata ) -{ - m_iDisabled = FALSE; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamSpawnPoint::InputDisable( inputdata_t &inputdata ) -{ - m_iDisabled = TRUE; -} - - -//=========================================================================================================== -// VEHICLE SPAWNPOINTS -//=========================================================================================================== -LINK_ENTITY_TO_CLASS( info_vehicle_groundspawn, CTeamVehicleSpawnPoint ); - -BEGIN_DATADESC( CTeamVehicleSpawnPoint ) - - // outputs - DEFINE_OUTPUT( m_OnVehicleSpawn, "OnVehicleSpawn" ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: Is this spawnpoint ready for a vehicle to spawn in? -//----------------------------------------------------------------------------- -bool CTeamVehicleSpawnPoint::IsValid( void ) -{ - CBaseEntity *ent = NULL; - for ( CEntitySphereQuery sphere( GetAbsOrigin(), 128 ); ( ent = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() ) - { - // if ent is a client, don't spawn on 'em - CBaseEntity *plent = ent; - if ( plent && plent->IsPlayer() ) - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Attach this spawnpoint to it's team -//----------------------------------------------------------------------------- -void CTeamVehicleSpawnPoint::Activate( void ) -{ - BaseClass::Activate(); - if ( GetTeamNumber() > 0 && GetTeamNumber() <= MAX_TEAMS ) - { - // Don't add vehicle spawnpoints to the team for now - //GetGlobalTeam( GetTeamNumber() )->AddSpawnpoint( this ); - } - else - { - Warning( "info_vehicle_groundspawn with invalid team number: %d\n", GetTeamNumber() ); - UTIL_Remove( this ); - } -} diff --git a/game/server/team_spawnpoint.h b/game/server/team_spawnpoint.h deleted file mode 100644 index 84f7f870d..000000000 --- a/game/server/team_spawnpoint.h +++ /dev/null @@ -1,56 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Team spawnpoint entity -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef TF_TEAMSPAWNPOINT_H -#define TF_TEAMSPAWNPOINT_H -#pragma once - -#include "baseentity.h" -#include "entityoutput.h" - -class CTeam; - -//----------------------------------------------------------------------------- -// Purpose: points at which the player can spawn, restricted by team -//----------------------------------------------------------------------------- -class CTeamSpawnPoint : public CPointEntity -{ -public: - DECLARE_CLASS( CTeamSpawnPoint, CPointEntity ); - - void Activate( void ); - virtual bool IsValid( CBasePlayer *pPlayer ); - - COutputEvent m_OnPlayerSpawn; - -protected: - int m_iDisabled; - - // Input handlers - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - - DECLARE_DATADESC(); -}; - -//----------------------------------------------------------------------------- -// Purpose: points at which vehicles can spawn, restricted by team -//----------------------------------------------------------------------------- -class CTeamVehicleSpawnPoint : public CTeamSpawnPoint -{ - DECLARE_CLASS( CTeamVehicleSpawnPoint, CTeamSpawnPoint ); -public: - void Activate( void ); - bool IsValid( void ); - - COutputEvent m_OnVehicleSpawn; - - DECLARE_DATADESC(); -}; - - -#endif // TF_TEAMSPAWNPOINT_H diff --git a/game/server/team_train_watcher.cpp b/game/server/team_train_watcher.cpp deleted file mode 100644 index bee9679a9..000000000 --- a/game/server/team_train_watcher.cpp +++ /dev/null @@ -1,562 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#include "cbase.h" -#include "team_train_watcher.h" -#include "team_control_point.h" -#include "trains.h" -#include "team_objectiveresource.h" -#include "teamplayroundbased_gamerules.h" -#include "team_control_point.h" -#include "team_control_point_master.h" -#include "engine/IEngineSound.h" -#include "soundenvelope.h" -#include "mp_shareddefs.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -static CSoundPatch *g_pAlarm = NULL; - -BEGIN_DATADESC( CTeamTrainWatcher ) - - // Inputs. - DEFINE_INPUTFUNC( FIELD_VOID, "RoundActivate", InputRoundActivate ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetNumTrainCappers", InputSetNumTrainCappers ), - DEFINE_INPUTFUNC( FIELD_VOID, "OnStartOvertime", InputOnStartOvertime ), - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - - // Outputs - DEFINE_OUTPUT( m_OnTrainStartRecede, "OnTrainStartRecede" ), - - // key - DEFINE_KEYFIELD( m_iszTrain, FIELD_STRING, "train" ), - DEFINE_KEYFIELD( m_iszStartNode, FIELD_STRING, "start_node" ), - DEFINE_KEYFIELD( m_iszGoalNode, FIELD_STRING, "goal_node" ), - - DEFINE_KEYFIELD( m_iszLinkedPathTracks[0], FIELD_STRING, "linked_pathtrack_1" ), - DEFINE_KEYFIELD( m_iszLinkedCPs[0], FIELD_STRING, "linked_cp_1" ), - - DEFINE_KEYFIELD( m_iszLinkedPathTracks[1], FIELD_STRING, "linked_pathtrack_2" ), - DEFINE_KEYFIELD( m_iszLinkedCPs[1], FIELD_STRING, "linked_cp_2" ), - - DEFINE_KEYFIELD( m_iszLinkedPathTracks[2], FIELD_STRING, "linked_pathtrack_3" ), - DEFINE_KEYFIELD( m_iszLinkedCPs[2], FIELD_STRING, "linked_cp_3" ), - - DEFINE_KEYFIELD( m_iszLinkedPathTracks[3], FIELD_STRING, "linked_pathtrack_4" ), - DEFINE_KEYFIELD( m_iszLinkedCPs[3], FIELD_STRING, "linked_cp_4" ), - - // can be up to 8 links - - // min speed for train hud speed levels - DEFINE_KEYFIELD( m_flSpeedLevels[0], FIELD_FLOAT, "hud_min_speed_level_1" ), - DEFINE_KEYFIELD( m_flSpeedLevels[1], FIELD_FLOAT, "hud_min_speed_level_2" ), - DEFINE_KEYFIELD( m_flSpeedLevels[2], FIELD_FLOAT, "hud_min_speed_level_3" ), - - DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ), - -END_DATADESC() - - -IMPLEMENT_SERVERCLASS_ST_NOBASE(CTeamTrainWatcher, DT_TeamTrainWatcher) - - SendPropFloat( SENDINFO( m_flTotalProgress ), 11, 0, 0.0f, 1.0f ), - SendPropInt( SENDINFO( m_iTrainSpeedLevel ), 4 ), - SendPropTime( SENDINFO( m_flRecedeTime ) ), - SendPropInt( SENDINFO( m_nNumCappers ), 5, SPROP_UNSIGNED ), - -END_SEND_TABLE() - - -LINK_ENTITY_TO_CLASS( team_train_watcher, CTeamTrainWatcher ); - -CTeamTrainWatcher::CTeamTrainWatcher() -{ - m_bDisabled = false; - m_flRecedeTime = 0; - m_bWaitingToRecede = false; - m_bCapBlocked = false; - - m_flNextSpeakForwardConceptTime = 0; - m_hAreaCap = NULL; -} - -int CTeamTrainWatcher::UpdateTransmitState() -{ - if ( m_bDisabled ) - { - return SetTransmitState( FL_EDICT_DONTSEND ); - } - - return SetTransmitState( FL_EDICT_ALWAYS ); -} - -void CTeamTrainWatcher::InputRoundActivate( inputdata_t &inputdata ) -{ - StopCaptureAlarm(); - - if ( !m_bDisabled ) - { - WatcherActivate(); - } -} - -void CTeamTrainWatcher::InputEnable( inputdata_t &inputdata ) -{ - StopCaptureAlarm(); - - m_bDisabled = false; - - WatcherActivate(); - - UpdateTransmitState(); -} - -void CTeamTrainWatcher::InputDisable( inputdata_t &inputdata ) -{ - StopCaptureAlarm(); - - m_bDisabled = true; - SetThink( NULL ); - - m_bWaitingToRecede = false; - - UpdateTransmitState(); -} - -ConVar tf_escort_recede_time( "tf_escort_recede_time", "30", 0, "", true, 0, false, 0 ); -ConVar tf_escort_recede_time_overtime( "tf_escort_recede_time_overtime", "5", 0, "", true, 0, false, 0 ); - -void CTeamTrainWatcher::InputSetNumTrainCappers( inputdata_t &inputdata ) -{ - if ( IsDisabled() ) - { - return; - } - - int iNumCappers = inputdata.value.Int(); - m_nNumCappers = iNumCappers; - - // inputdata.pCaller is hopefully an area capture - // lets see if its blocked, and not start receding if it is - CTriggerAreaCapture *pAreaCap = dynamic_cast(inputdata.pCaller); - if ( pAreaCap ) - { - m_bCapBlocked = pAreaCap->IsBlocked(); - m_hAreaCap = pAreaCap; - } - - if ( iNumCappers <= 0 && !m_bCapBlocked ) - { - if ( !m_bWaitingToRecede ) - { - // start receding in [tf_escort_cart_recede_time] seconds - m_bWaitingToRecede = true; - - if ( TeamplayRoundBasedRules() && TeamplayRoundBasedRules()->InOvertime() ) - { - m_flRecedeTotalTime = tf_escort_recede_time_overtime.GetFloat(); - } - else - { - m_flRecedeTotalTime = tf_escort_recede_time.GetFloat(); - } - - m_flRecedeStartTime = gpGlobals->curtime; - m_flRecedeTime = m_flRecedeStartTime + m_flRecedeTotalTime; - } - } - else - { - // cancel receding - m_bWaitingToRecede = false; - m_flRecedeTime = 0; - } -} - -void CTeamTrainWatcher::InputOnStartOvertime( inputdata_t &inputdata ) -{ - // recalculate the recede time - if ( m_bWaitingToRecede ) - { - float flRecedeTimeRemaining = m_flRecedeTime - gpGlobals->curtime; - float flOvertimeRecedeLen = tf_escort_recede_time_overtime.GetFloat(); - - // drop to overtime recede time if it's more than that - if ( flRecedeTimeRemaining > flOvertimeRecedeLen ) - { - m_flRecedeTotalTime = flOvertimeRecedeLen; - m_flRecedeStartTime = gpGlobals->curtime; - m_flRecedeTime = m_flRecedeStartTime + m_flRecedeTotalTime; - } - } -} - -// ========================================================== -// given a start node and a list of goal nodes -// calculate the distance between each -// ========================================================== -void CTeamTrainWatcher::WatcherActivate( void ) -{ - m_flRecedeTime = 0; - m_bWaitingToRecede = false; - m_bCapBlocked = false; - m_flNextSpeakForwardConceptTime = 0; - m_hAreaCap = NULL; - - StopCaptureAlarm(); - - // init our train - m_hTrain = dynamic_cast( gEntList.FindEntityByName( NULL, m_iszTrain ) ); - if ( !m_hTrain ) - { - Warning("%s failed to find train named '%s'\n", GetClassname(), STRING(m_iszTrain) ); - } - - // init our array of path_tracks linked to control points - m_iNumCPLinks = 0; - - int i; - for ( i=0;i( gEntList.FindEntityByName( NULL, m_iszLinkedPathTracks[i] ) ); - CTeamControlPoint *pCP = dynamic_cast( gEntList.FindEntityByName( NULL, m_iszLinkedCPs[i] ) ); - if ( pPathTrack && pCP ) - { - m_CPLinks[m_iNumCPLinks].hPathTrack = pPathTrack; - m_CPLinks[m_iNumCPLinks].hCP = pCP; - m_CPLinks[m_iNumCPLinks].flDistanceFromStart = 0; // filled in when we parse the nodes - m_CPLinks[m_iNumCPLinks].bAlertPlayed = false; - m_iNumCPLinks++; - } - } - - // init our start and goal nodes - m_hStartNode = dynamic_cast( gEntList.FindEntityByName( NULL, m_iszStartNode ) ); - if ( !m_hStartNode ) - { - Warning("%s failed to find path_track named '%s'\n", GetClassname(), STRING(m_iszStartNode) ); - } - - m_hGoalNode = dynamic_cast( gEntList.FindEntityByName( NULL, m_iszGoalNode ) ); - if ( !m_hGoalNode ) - { - Warning("%s failed to find path_track named '%s'\n", GetClassname(), STRING(m_iszGoalNode) ); - } - - m_flTotalPathDistance = 0.0f; - - if( m_hStartNode.Get() && m_hGoalNode.Get() ) - { - CPathTrack *pNode = m_hStartNode; - CPathTrack *pPrev = pNode; - pNode = pNode->GetNext(); - - // don't check the start node for links. If it's linked, it will have 0 distance anyway - - while ( pNode ) - { - Vector dir = pNode->GetLocalOrigin() - pPrev->GetLocalOrigin(); - float length = dir.Length(); - - m_flTotalPathDistance += length; - - // if pNode is one of our cp nodes, store its distance from m_hStartNode - for ( i=0;iGetNext(); - } - } - - // We have total distance and increments in our links array - for ( i=0;iGetPointIndex(); -// This can be pulled once DoD includes team_objectiveresource.* and c_team_objectiveresource.* -#ifndef DOD_DLL - ObjectiveResource()->SetTrainPathDistance( iCPIndex, m_CPLinks[i].flDistanceFromStart / m_flTotalPathDistance ); -#endif - DevMsg( "link %d = %.2f\n", iCPIndex, m_CPLinks[i].flDistanceFromStart / m_flTotalPathDistance ); - } - - SetThink( &CTeamTrainWatcher::WatcherThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -void CTeamTrainWatcher::StopCaptureAlarm( void ) -{ - if ( g_pAlarm ) - { - CSoundEnvelopeController::GetController().SoundDestroy( g_pAlarm ); - g_pAlarm = NULL; - } -} - -void CTeamTrainWatcher::StartCaptureAlarm( CTeamControlPoint *pPoint ) -{ - StopCaptureAlarm(); - - if ( pPoint ) - { - CReliableBroadcastRecipientFilter filter; - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - g_pAlarm = controller.SoundCreate( filter, pPoint->entindex(), CHAN_STATIC, TF_TRAIN_ALARM, ATTN_NORM ); - controller.Play( g_pAlarm, 1.0, PITCH_NORM ); - } -} - -void CTeamTrainWatcher::PlayCaptureAlert( CTeamControlPoint *pPoint, bool bFinalPointInMap ) -{ - if ( !pPoint ) - return; - - if ( TeamplayRoundBasedRules() ) - { - TeamplayRoundBasedRules()->PlayTrainCaptureAlert( pPoint, bFinalPointInMap ); - } -} - -void CTeamTrainWatcher::WatcherThink( void ) -{ - if ( m_bWaitingToRecede ) - { - if ( m_flRecedeTime < gpGlobals->curtime ) - { - m_bWaitingToRecede = false; - - // don't actually recede in overtime - if ( TeamplayRoundBasedRules() && !TeamplayRoundBasedRules()->InOvertime() ) - { - // fire recede output - m_OnTrainStartRecede.FireOutput( this, this ); - } - } - } - - if ( TeamplayRoundBasedRules() && TeamplayRoundBasedRules()->State_Get() == GR_STATE_TEAM_WIN ) - { - StopCaptureAlarm(); - } - - // given its next node, we can walk the nodes and find the linear - // distance to the next cp node, or to the goal node - - CFuncTrackTrain *pTrain = m_hTrain; - if ( pTrain ) - { - int iOldTrainSpeedLevel = m_iTrainSpeedLevel; - - // how fast is the train moving? - float flSpeed = pTrain->GetDesiredSpeed(); - - // divide speed into regions - // anything negative is -1 - - if ( flSpeed < 0 ) - { - m_iTrainSpeedLevel = -1; - - // even though our desired speed might be negative, - // our actual speed might be zero if we're at a dead end... - // this will turn off the < image when the train is done moving backwards - if ( pTrain->GetCurrentSpeed() == 0 ) - { - m_iTrainSpeedLevel = 0; - } - } - else if ( flSpeed > m_flSpeedLevels[2] ) - { - m_iTrainSpeedLevel = 3; - } - else if ( flSpeed > m_flSpeedLevels[1] ) - { - m_iTrainSpeedLevel = 2; - } - else if ( flSpeed > m_flSpeedLevels[0] ) - { - m_iTrainSpeedLevel = 1; - } - else - { - m_iTrainSpeedLevel = 0; - } - - // play any concepts that we might need to play - if ( m_iTrainSpeedLevel != iOldTrainSpeedLevel ) - { - if ( TeamplayRoundBasedRules() ) - { - if ( m_iTrainSpeedLevel == 0 && iOldTrainSpeedLevel != 0 ) - { - TeamplayRoundBasedRules()->HaveAllPlayersSpeakConceptIfAllowed( MP_CONCEPT_CART_STOP ); - m_flNextSpeakForwardConceptTime = 0; - } - else if ( m_iTrainSpeedLevel < 0 && iOldTrainSpeedLevel == 0 ) - { - TeamplayRoundBasedRules()->HaveAllPlayersSpeakConceptIfAllowed( MP_CONCEPT_CART_MOVING_BACKWARD ); - m_flNextSpeakForwardConceptTime = 0; - } - } - } - - if ( m_iTrainSpeedLevel > 0 && m_flNextSpeakForwardConceptTime < gpGlobals->curtime ) - { - if ( m_hAreaCap.Get() ) - { - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBaseMultiplayerPlayer *pPlayer = ToBaseMultiplayerPlayer( UTIL_PlayerByIndex( i ) ); - if ( pPlayer ) - { - if ( m_hAreaCap->IsTouching( pPlayer ) ) - { - pPlayer->SpeakConceptIfAllowed( MP_CONCEPT_CART_MOVING_FORWARD ); - } - } - } - } - - m_flNextSpeakForwardConceptTime = gpGlobals->curtime + 3.0; - } - - // what percent progress are we at? - CPathTrack *pNode = ( pTrain->m_ppath ) ? pTrain->m_ppath->GetNext() : NULL; - - // if we're moving backwards, GetNext is going to be wrong - if ( flSpeed < 0 ) - { - pNode = pTrain->m_ppath; - } - - if ( pNode ) - { - float flDistanceToGoal = 0; - - // distance to next node - Vector vecDir = pNode->GetLocalOrigin() - pTrain->GetLocalOrigin(); - flDistanceToGoal = vecDir.Length(); - - // distance of next node to goal node - if ( pNode && pNode != m_hGoalNode ) - { - // walk this until we get to goal node, or a dead end - CPathTrack *pPrev = pNode; - pNode = pNode->GetNext(); - while ( pNode ) - { - vecDir = pNode->GetLocalOrigin() - pPrev->GetLocalOrigin(); - flDistanceToGoal += vecDir.Length(); - - if ( pNode == m_hGoalNode ) - break; - - pPrev = pNode; - pNode = pNode->GetNext(); - } - } - - if ( m_flTotalPathDistance <= 0 ) - { - Assert( !"No path distance in team_train_watcher\n" ); - m_flTotalPathDistance = 1; - } - - m_flTotalProgress = clamp( 1.0 - ( flDistanceToGoal / m_flTotalPathDistance ), 0.0, 1.0 ); - - float flTrainDistanceFromStart = m_flTotalPathDistance - flDistanceToGoal; - - // play alert sounds if necessary - for ( int iCount = 0 ; iCount < m_iNumCPLinks ; iCount++ ) - { - if ( flTrainDistanceFromStart < m_CPLinks[iCount].flDistanceFromStart - TF_TRAIN_ALERT_DISTANCE ) - { - // back up twice the alert distance before resetting our flag to play the warning again - if ( flTrainDistanceFromStart < m_CPLinks[iCount].flDistanceFromStart - ( TF_TRAIN_ALERT_DISTANCE * 2 ) ) - { - // reset our alert flag - m_CPLinks[iCount].bAlertPlayed = false; - } - } - else - { - if ( flTrainDistanceFromStart < m_CPLinks[iCount].flDistanceFromStart && !m_CPLinks[iCount].bAlertPlayed ) - { - m_CPLinks[iCount].bAlertPlayed = true; - - CTeamControlPoint *pLastPoint = NULL; - CTeamControlPoint *pCurrentPoint = m_CPLinks[iCount].hCP.Get(); - CTeamControlPointMaster *pMaster = g_hControlPointMasters.Count() ? g_hControlPointMasters[0] : NULL; - if ( pMaster ) - { - pLastPoint = pMaster->GetControlPoint( pMaster->GetNumPoints() - 1 ); - } - - bool bFinalPointInMap = pLastPoint && ( pLastPoint == pCurrentPoint ); - - PlayCaptureAlert( pCurrentPoint, bFinalPointInMap ); - } - } - } - - // check to see if we need to start or stop the alarm - if ( flDistanceToGoal <= TF_TRAIN_ALARM_DISTANCE ) - { - if ( !g_pAlarm && m_iNumCPLinks > 0 ) - { - // start the alarm at the final point - StartCaptureAlarm( m_CPLinks[m_iNumCPLinks-1].hCP.Get() ); - } - } - else - { - if ( g_pAlarm ) - { - StopCaptureAlarm(); - } - } - } - } - - SetNextThink( gpGlobals->curtime + 0.1 ); -} - - -CBaseEntity *CTeamTrainWatcher::GetTrainEntity( void ) -{ - return m_hTrain.Get(); -} - -bool CTeamTrainWatcher::TimerMayExpire( void ) -{ - if ( IsDisabled() ) - { - return true; - } - - // Still in overtime if we're waiting to recede - if ( m_bWaitingToRecede ) - return false; - - // capture blocked so we're not receding, but game shouldn't end - if ( m_bCapBlocked ) - return false; - - // not waiting, so we're capping, in which case the area capture - // will not let us expire - return true; -} diff --git a/game/server/team_train_watcher.h b/game/server/team_train_watcher.h deleted file mode 100644 index 7f14455c4..000000000 --- a/game/server/team_train_watcher.h +++ /dev/null @@ -1,127 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef TEAM_TRAIN_WATCHER_H -#define TEAM_TRAIN_WATCHER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "cbase.h" -#include "trigger_area_capture.h" - -class CFuncTrackTrain; -class CPathTrack; -class CTeamControlPoint; - -#define TF_TRAIN_ALERT_DISTANCE 750 // alert is the VO warning -#define TF_TRAIN_ALARM_DISTANCE 200 // alarm is the looping sound played at the control point - -#define TF_TRAIN_ATTACK_ALERT "Announcer.Cart.AttackWarning" -#define TF_TRAIN_DEFEND_ALERT "Announcer.Cart.DefendWarning" -#define TF_TRAIN_ATTACK_FINAL_ALERT "Announcer.Cart.AttackFinalWarning" -#define TF_TRAIN_DEFEND_FINAL_ALERT "Announcer.Cart.DefendFinalWarning" -#define TF_TRAIN_ALARM "Cart.Warning" - -class CTeamTrainWatcher : public CBaseEntity -{ - DECLARE_CLASS( CTeamTrainWatcher, CBaseEntity ); -public: - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - CTeamTrainWatcher(); - - virtual int UpdateTransmitState(); - - void InputRoundActivate( inputdata_t &inputdata ); - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - - void InputSetNumTrainCappers( inputdata_t &inputdata ); - void InputOnStartOvertime( inputdata_t &inputdata ); - - // ========================================================== - // given a start node and a list of goal nodes - // calculate the distance between each - // ========================================================== - void WatcherActivate( void ); - - void WatcherThink( void ); - - CBaseEntity *GetTrainEntity( void ); - bool IsDisabled( void ) { return m_bDisabled; } - - bool TimerMayExpire( void ); - - void StopCaptureAlarm( void ); - -private: - - void StartCaptureAlarm( CTeamControlPoint *pPoint ); - void PlayCaptureAlert( CTeamControlPoint *pPoint, bool bFinalPointInMap ); - -private: - - bool m_bDisabled; - - // === Data === - - // pointer to the train that we're checking - CHandle m_hTrain; - - // start node - CHandle m_hStartNode; - - // goal node - CHandle m_hGoalNode; - - string_t m_iszTrain; - string_t m_iszStartNode; - string_t m_iszGoalNode; - - // list of node associations with control points - typedef struct - { - CHandle hPathTrack; - CHandle hCP; - float flDistanceFromStart; - bool bAlertPlayed; - } node_cp_pair_t; - - node_cp_pair_t m_CPLinks[MAX_CONTROL_POINTS]; - int m_iNumCPLinks; - - string_t m_iszLinkedPathTracks[MAX_CONTROL_POINTS]; - string_t m_iszLinkedCPs[MAX_CONTROL_POINTS]; - - float m_flTotalPathDistance; // calculated only at round start, node graph - // may get chopped as the round progresses - - float m_flSpeedLevels[3]; - - // === Networked Data === - - // current total progress, percentage - CNetworkVar( float, m_flTotalProgress ); - - CNetworkVar( int, m_iTrainSpeedLevel ); - - CNetworkVar( int, m_nNumCappers ); - - bool m_bWaitingToRecede; - CNetworkVar( float, m_flRecedeTime ); - float m_flRecedeTotalTime; - float m_flRecedeStartTime; - COutputEvent m_OnTrainStartRecede; - - bool m_bCapBlocked; - - float m_flNextSpeakForwardConceptTime; // used to have players speak the forward concept every X seconds - CHandle m_hAreaCap; -}; - -#endif //TEAM_TRAIN_WATCHER_H diff --git a/game/server/tempmonster.cpp b/game/server/tempmonster.cpp deleted file mode 100644 index 6294a3bde..000000000 --- a/game/server/tempmonster.cpp +++ /dev/null @@ -1,105 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -//========================================================= -// NPC template -//========================================================= -#include "cbase.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#if 0 - -//========================================================= -// NPC's Anim Events Go Here -//========================================================= - -class CMyNPC : public CAI_BaseNPC -{ -public: - DECLARE_CLASS( CMyNPC, CAI_BaseNPC ); - - void Spawn( void ); - void Precache( void ); - void MaxYawSpeed( void ); - int Classify ( void ); - void HandleAnimEvent( animevent_t *pEvent ); -}; -LINK_ENTITY_TO_CLASS( my_NPC, CMyNPC ); - -//========================================================= -// Classify - indicates this NPC's place in the -// relationship table. -//========================================================= -int CMyNPC::Classify ( void ) -{ - return CLASS_MY_NPC; -} - -//========================================================= -// SetYawSpeed - allows each sequence to have a different -// turn rate associated with it. -//========================================================= -float CMyNPC::MaxYawSpeed ( void ) -{ - switch ( m_Activity ) - { - case ACT_IDLE: - default: - return 90; - } -} - -//========================================================= -// HandleAnimEvent - catches the NPC-specific messages -// that occur when tagged animation frames are played. -//========================================================= -void CMyNPC::HandleAnimEvent( animevent_t *pEvent ) -{ - switch( pEvent->event ) - { - case 0: - default: - CAI_BaseNPC::HandleAnimEvent( pEvent ); - break; - } -} - -//========================================================= -// Spawn -//========================================================= -void CMyNPC::Spawn() -{ - Precache( ); - - engine.SetModel(edict(), "models/mymodel.mdl"); - UTIL_SetSize( this, Vector( -12, -12, 0 ), Vector( 12, 12, 24 ) ); - - SetSolid( SOLID_SLIDEBOX ); - SetMoveType( MOVETYPE_STEP ); - m_bloodColor = BLOOD_COLOR_GREEN; - m_iHealth = 8; - m_vecViewOffset = Vector ( 0, 0, 0 );// position of the eyes relative to NPC's origin. - m_flFieldOfView = 0.5;// indicates the width of this NPC's forward view cone ( as a dotproduct result ) - m_NPCState = NPCSTATE_NONE; - - NPCInit(); -} - -//========================================================= -// Precache - precaches all resources this NPC needs -//========================================================= -void CMyNPC::Precache() -{ - engine.PrecacheModel("models/mymodel.mdl"); -} - -//========================================================= -// AI Schedules Specific to this NPC -//========================================================= -#endif diff --git a/game/server/tesla.cpp b/game/server/tesla.cpp deleted file mode 100644 index 2d5eeed88..000000000 --- a/game/server/tesla.cpp +++ /dev/null @@ -1,180 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "tesla.h" -#include "te_effect_dispatch.h" -#include "sendproxy.h" -#include "engine/IEngineSound.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -LINK_ENTITY_TO_CLASS( point_tesla, CTesla ); - -BEGIN_DATADESC( CTesla ) - - DEFINE_KEYFIELD( m_SourceEntityName,FIELD_STRING, "m_SourceEntityName" ), - DEFINE_KEYFIELD( m_SoundName, FIELD_STRING, "m_SoundName" ), - DEFINE_KEYFIELD( m_iszSpriteName, FIELD_STRING, "texture" ), - - DEFINE_KEYFIELD( m_Color, FIELD_COLOR32, "m_Color" ), - DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "m_flRadius" ), - - //DEFINE_ARRAY( m_flThickness, FIELD_FLOAT, 2 ), - DEFINE_KEYFIELD( m_flThickness[0], FIELD_FLOAT, "thick_min" ), - DEFINE_KEYFIELD( m_flThickness[1], FIELD_FLOAT, "thick_max" ), - - //DEFINE_ARRAY( m_flTimeVisible, FIELD_FLOAT, 2 ), - DEFINE_KEYFIELD( m_flTimeVisible[0],FIELD_FLOAT, "lifetime_min" ), - DEFINE_KEYFIELD( m_flTimeVisible[1],FIELD_FLOAT, "lifetime_max" ), - - //DEFINE_ARRAY( m_flArcInterval, FIELD_FLOAT, 2 ), - DEFINE_KEYFIELD( m_flArcInterval[0],FIELD_FLOAT, "interval_min" ), - DEFINE_KEYFIELD( m_flArcInterval[1],FIELD_FLOAT, "interval_max" ), - - //DEFINE_ARRAY( m_NumBeams, FIELD_INTEGER, 2 ), - DEFINE_KEYFIELD( m_NumBeams[0], FIELD_INTEGER, "beamcount_min" ), - DEFINE_KEYFIELD( m_NumBeams[1], FIELD_INTEGER, "beamcount_max" ), - - DEFINE_KEYFIELD( m_bOn, FIELD_BOOLEAN, "m_bOn" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - DEFINE_INPUTFUNC( FIELD_VOID, "DoSpark", InputDoSpark ), - - DEFINE_FUNCTION( ShootArcThink ) - -END_DATADESC() - - -IMPLEMENT_SERVERCLASS_ST( CTesla, DT_Tesla ) - SendPropStringT( SENDINFO( m_SoundName ) ), - SendPropStringT( SENDINFO( m_iszSpriteName ) ) -END_SEND_TABLE() - - -CTesla::CTesla() -{ - m_SourceEntityName = NULL_STRING; - m_SoundName = NULL_STRING; - m_iszSpriteName = NULL_STRING; - m_NumBeams[0] = m_NumBeams[1] = 6; - m_flRadius = 200; - m_flThickness[0] = m_flThickness[1] = 5; - m_flTimeVisible[0] = 0.3; - m_flTimeVisible[1] = 0.55; - m_flArcInterval[0] = m_flArcInterval[1] = 0.5; - - AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); -} - - -void CTesla::Spawn() -{ - if ( m_iszSpriteName.Get() == NULL_STRING ) - { - m_iszSpriteName = AllocPooledString("sprites/physbeam.vmt"); - } - - Precache(); - BaseClass::Spawn(); -} - - -void CTesla::Activate() -{ - BaseClass::Activate(); - - SetThink( &CTesla::ShootArcThink ); - SetupForNextArc(); -} - - -void CTesla::Precache() -{ - PrecacheModel( STRING(m_iszSpriteName.Get()) ); - BaseClass::Precache(); - - PrecacheScriptSound( STRING( m_SoundName.Get() ) ); -} - - -void CTesla::SetupForNextArc() -{ - if (m_bOn) - { - float flTimeToNext = RandomFloat( m_flArcInterval[0], m_flArcInterval[1] ); - SetNextThink( gpGlobals->curtime + flTimeToNext ); - } - else - { - SetNextThink( TICK_NEVER_THINK ); - } -} - - -CBaseEntity* CTesla::GetSourceEntity() -{ - if ( m_SourceEntityName != NULL_STRING ) - { - CBaseEntity *pRet = gEntList.FindEntityByName( NULL, m_SourceEntityName ); - if ( pRet ) - return pRet; - } - - return this; -} - - -void CTesla::ShootArcThink() -{ - DoSpark(); - SetupForNextArc(); -} - - -void CTesla::DoSpark() -{ - // Shoot out an arc. - EntityMessageBegin( this ); - - CBaseEntity *pEnt = GetSourceEntity(); - - WRITE_VEC3COORD( pEnt->GetAbsOrigin() ); - WRITE_SHORT( pEnt->entindex() ); - WRITE_FLOAT( m_flRadius ); - WRITE_BYTE( m_Color.r ); - WRITE_BYTE( m_Color.g ); - WRITE_BYTE( m_Color.b ); - WRITE_BYTE( m_Color.a ); - WRITE_CHAR( RandomInt( m_NumBeams[0], m_NumBeams[1] ) ); - WRITE_FLOAT( RandomFloat( m_flThickness[0], m_flThickness[1] ) ); - WRITE_FLOAT( RandomFloat( m_flTimeVisible[0], m_flTimeVisible[1] ) ); - - MessageEnd(); -} - - -void CTesla::InputDoSpark( inputdata_t &inputdata ) -{ - DoSpark(); -} - - -void CTesla::InputTurnOn( inputdata_t &inputdata ) -{ - m_bOn = true; - SetupForNextArc(); -} - - -void CTesla::InputTurnOff( inputdata_t &inputdata ) -{ - m_bOn = false; - SetupForNextArc(); -} - diff --git a/game/server/tesla.h b/game/server/tesla.h deleted file mode 100644 index 6def4eb8e..000000000 --- a/game/server/tesla.h +++ /dev/null @@ -1,62 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef TESLA_H -#define TESLA_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "baseentity.h" - - -class CTesla : public CBaseEntity -{ -public: - DECLARE_CLASS( CTesla, CBaseEntity ); - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - CTesla(); - - virtual void Spawn(); - virtual void Activate(); - virtual void Precache(); - - void InputTurnOn( inputdata_t &inputdata ); - void InputTurnOff( inputdata_t &inputdata ); - void InputDoSpark( inputdata_t &inputdata ); - - void DoSpark(); - void ShootArcThink(); - - void SetupForNextArc(); - CBaseEntity* GetSourceEntity(); - - -public: - - // Tesla parameters. - string_t m_SourceEntityName; // Which entity the arcs come from. - CNetworkVar( string_t, m_SoundName ); // What sound to play when arcing. - - color32 m_Color; - int m_NumBeams[2]; // Number of beams per spark. - - float m_flRadius; // Radius it looks for surfaces to arc to. - - float m_flThickness[2]; // Beam thickness. - float m_flTimeVisible[2]; // How long each beam stays around (min/max). - float m_flArcInterval[2]; // Time between args (min/max). - - bool m_bOn; - - CNetworkVar( string_t, m_iszSpriteName ); -}; - - -#endif // TESLA_H diff --git a/game/server/test_proxytoggle.cpp b/game/server/test_proxytoggle.cpp deleted file mode 100644 index d9bab08ef..000000000 --- a/game/server/test_proxytoggle.cpp +++ /dev/null @@ -1,110 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "baseentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CTest_ProxyToggle_Networkable; -static CTest_ProxyToggle_Networkable *g_pTestObj = 0; -static bool g_bEnableProxy = true; - - -// ---------------------------------------------------------------------------------------- // -// CTest_ProxyToggle_Networkable -// ---------------------------------------------------------------------------------------- // - -class CTest_ProxyToggle_Networkable : public CBaseEntity -{ -public: - DECLARE_CLASS( CTest_ProxyToggle_Networkable, CBaseEntity ); - DECLARE_SERVERCLASS(); - - CTest_ProxyToggle_Networkable() - { - m_WithProxy = 1241; - g_pTestObj = this; - } - - ~CTest_ProxyToggle_Networkable() - { - g_pTestObj = NULL; - } - - int UpdateTransmitState() - { - return SetTransmitState( FL_EDICT_ALWAYS ); - } - - CNetworkVar( int, m_WithProxy ); -}; - -void* SendProxy_TestProxyToggle( const SendProp *pProp, const void *pStructBase, const void *pData, CSendProxyRecipients *pRecipients, int objectID ) -{ - if ( g_bEnableProxy ) - { - return (void*)pData; - } - else - { - pRecipients->ClearAllRecipients(); - return NULL; - } -} -REGISTER_SEND_PROXY_NON_MODIFIED_POINTER( SendProxy_TestProxyToggle ); - - -// ---------------------------------------------------------------------------------------- // -// Datatables. -// ---------------------------------------------------------------------------------------- // - -LINK_ENTITY_TO_CLASS( test_proxytoggle, CTest_ProxyToggle_Networkable ); - -BEGIN_SEND_TABLE_NOBASE( CTest_ProxyToggle_Networkable, DT_ProxyToggle_ProxiedData ) - SendPropInt( SENDINFO( m_WithProxy ) ) -END_SEND_TABLE() - -IMPLEMENT_SERVERCLASS_ST( CTest_ProxyToggle_Networkable, DT_ProxyToggle ) - SendPropDataTable( "blah", 0, &REFERENCE_SEND_TABLE( DT_ProxyToggle_ProxiedData ), SendProxy_TestProxyToggle ) -END_SEND_TABLE() - - - -// ---------------------------------------------------------------------------------------- // -// Console commands for this test. -// ---------------------------------------------------------------------------------------- // - -void Test_ProxyToggle_EnableProxy( const CCommand &args ) -{ - if ( args.ArgC() < 2 ) - { - Error( "Test_ProxyToggle_EnableProxy: requires parameter (0 or 1)." ); - } - - g_bEnableProxy = !!atoi( args[ 1 ] ); -} - -void Test_ProxyToggle_SetValue( const CCommand &args ) -{ - if ( args.ArgC() < 2 ) - { - Error( "Test_ProxyToggle_SetValue: requires value parameter." ); - } - else if ( !g_pTestObj ) - { - Error( "Test_ProxyToggle_SetValue: no entity present." ); - } - - g_pTestObj->m_WithProxy = atoi( args[ 1 ] ); -} - -ConCommand cc_Test_ProxyToggle_EnableProxy( "Test_ProxyToggle_EnableProxy", Test_ProxyToggle_EnableProxy, 0, FCVAR_CHEAT ); -ConCommand cc_Test_ProxyToggle_SetValue( "Test_ProxyToggle_SetValue", Test_ProxyToggle_SetValue, 0, FCVAR_CHEAT ); - - diff --git a/game/server/test_stressentities.cpp b/game/server/test_stressentities.cpp deleted file mode 100644 index 3b24debcd..000000000 --- a/game/server/test_stressentities.cpp +++ /dev/null @@ -1,152 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "test_stressentities.h" -#include "vstdlib/random.h" -#include "world.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -CStressEntityReg *CStressEntityReg::s_pHead = NULL; - - -// CStressEntityReg::s_pHead in array form for convenient access. -CUtlVector g_StressEntityRegs; - -CUtlVector g_StressEntities; - - -CBaseEntity* MoveToRandomSpot( CBaseEntity *pEnt ) -{ - if ( pEnt ) - { - CBasePlayer *pLocalPlayer = UTIL_GetLocalPlayer(); - if ( pLocalPlayer ) - { - Vector vForward; - pLocalPlayer->EyeVectors(&vForward ); - - UTIL_SetOrigin( pEnt, GetRandomSpot() ); - } - } - - return pEnt; -} - - -Vector GetRandomSpot() -{ - CWorld *pEnt = GetWorldEntity(); - if ( pEnt ) - { - Vector vMin, vMax; - pEnt->GetWorldBounds( vMin, vMax ); - return Vector( - RandomFloat( vMin.x, vMax.x ), - RandomFloat( vMin.y, vMax.y ), - RandomFloat( vMin.z, vMax.z ) ); - } - else - { - return Vector( 0, 0, 0 ); - } -} - - -void Test_InitRandomEntitySpawner( const CCommand &args ) -{ - // Put the list of registered functions into array form for convenience. - g_StressEntityRegs.Purge(); - for ( CStressEntityReg *pCur=CStressEntityReg::GetListHead(); pCur; pCur=pCur->GetNext() ) - g_StressEntityRegs.AddToTail( pCur ); - - // Create slots for all the entities.. - int nSlots = 100; - if ( args.ArgC() >= 2 ) - nSlots = atoi( args[ 1 ] ); - - g_StressEntities.Purge(); - g_StressEntities.SetSize( nSlots ); - - Msg( "Test_InitRandomEntitySpawner: created %d slots.\n", nSlots ); -} - - -void Test_SpawnRandomEntities( const CCommand &args ) -{ - if ( args.ArgC() < 3 ) - { - Error( "Test_SpawnRandomEntities missing arguments." ); - } - - if ( g_StressEntities.Count() == 0 ) - { - Error( "Test_SpawnRandomEntities: not initialized (call Test_InitRandomEntitySpawner frst)." ); - } - - int nMin = atoi( args[ 1 ] ); - int nMax = atoi( args[ 2 ] ); - int count = RandomInt( nMin, nMax ); - - for ( int i=0; i < count; i++ ) - { - int iSlot = RandomInt( 0, g_StressEntities.Count() - 1 ); - - // Remove any old entity in this slot. - if ( g_StressEntities[iSlot].Get() ) - UTIL_RemoveImmediate( g_StressEntities[iSlot] ); - - // Create a new one in this slot. - int iType = RandomInt( 0, g_StressEntityRegs.Count() - 1 ); - g_StressEntities[iSlot] = g_StressEntityRegs[iType]->GetFn()(); - } -} - - -void Test_RandomizeInPVS( const CCommand &args ) -{ - if ( args.ArgC() < 2 ) - { - Error( "Test_RandomizeInPVS " ); - } - - int percent = atoi( args[ 1 ] ); - for ( int i=0; i < g_StressEntities.Count(); i++ ) - { - CBaseEntity *pEnt = g_StressEntities[i]; - - if ( pEnt ) - { - if ( RandomInt( 0, 100 ) < percent ) - { - if ( pEnt->IsEffectActive( EF_NODRAW ) ) - pEnt->RemoveEffects( EF_NODRAW ); - else - pEnt->AddEffects( EF_NODRAW ); - } - } - } -} - - -void Test_RemoveAllRandomEntities() -{ - for ( int i=0; i < g_StressEntities.Count(); i++ ) - { - if ( g_StressEntities[i].Get() ) - UTIL_Remove( g_StressEntities[i] ); - } -} - - -ConCommand cc_Test_InitRandomEntitySpawner( "Test_InitRandomEntitySpawner", Test_InitRandomEntitySpawner, 0, FCVAR_CHEAT ); -ConCommand cc_Test_SpawnRandomEntities( "Test_SpawnRandomEntities", Test_SpawnRandomEntities, 0, FCVAR_CHEAT ); -ConCommand cc_Test_RandomizeInPVS( "Test_RandomizeInPVS", Test_RandomizeInPVS, 0, FCVAR_CHEAT ); -ConCommand cc_Test_RemoveAllRandomEntities( "Test_RemoveAllRandomEntities", Test_RemoveAllRandomEntities, 0, FCVAR_CHEAT ); - diff --git a/game/server/test_stressentities.h b/game/server/test_stressentities.h deleted file mode 100644 index 0f5918091..000000000 --- a/game/server/test_stressentities.h +++ /dev/null @@ -1,56 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef TEST_STRESSENTITIES_H -#define TEST_STRESSENTITIES_H -#ifdef _WIN32 -#pragma once -#endif - - -class CBaseEntity; - - -typedef CBaseEntity* (*StressEntityFn)(); // Function to create an entity for the stress test. - - -// Each game DLL can instantiate these to register types of entities it can create -// for the entity stress test. -class CStressEntityReg -{ -public: - - CStressEntityReg( StressEntityFn fn ) - { - m_pFn = fn; - m_pNext = s_pHead; - s_pHead = this; - } - - static CStressEntityReg*GetListHead() { return s_pHead; } - CStressEntityReg* GetNext() { return m_pNext; } - StressEntityFn GetFn() { return m_pFn; } - - -private: - static CStressEntityReg *s_pHead; // List of all CStressEntityReg's. - CStressEntityReg *m_pNext; - StressEntityFn m_pFn; -}; - - -// Use this macro to register a function to create stresstest entities. -#define REGISTER_STRESS_ENTITY( fnName ) static CStressEntityReg s_##fnName##__( fnName ); - - -// Helper function for the functions that create the stress entities. -// Moves the entity to a random place in the level and returns the entity. -CBaseEntity* MoveToRandomSpot( CBaseEntity *pEnt ); -Vector GetRandomSpot(); - - -#endif // TEST_STRESSENTITIES_H diff --git a/game/server/testfunctions.cpp b/game/server/testfunctions.cpp deleted file mode 100644 index 7547a14e7..000000000 --- a/game/server/testfunctions.cpp +++ /dev/null @@ -1,62 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "convar.h" -#include "tier0/dbg.h" -#include "player.h" -#include "world.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -void Test_CreateEntity( const CCommand &args ) -{ - if ( args.ArgC() < 2 ) - { - Error( "Test_CreateEntity: requires entity classname argument." ); - } - - const char *pClassName = args[ 1 ]; - - if ( !CreateEntityByName( pClassName ) ) - { - Error( "Test_CreateEntity( %s ) failed.", pClassName ); - } -} - - -void Test_RandomPlayerPosition() -{ - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - CWorld *pWorld = GetWorldEntity(); - if ( !pPlayer ) - { - Error( "Test_RandomPlayerPosition: no local player entity." ); - } - else if ( !pWorld ) - { - Error( "Test_RandomPlayerPosition: no world entity." ); - } - - - - Vector vMin, vMax; - pWorld->GetWorldBounds( vMin, vMax ); - - Vector vecOrigin; - vecOrigin.x = RandomFloat( vMin.x, vMax.x ); - vecOrigin.y = RandomFloat( vMin.y, vMax.y ); - vecOrigin.z = RandomFloat( vMin.z, vMax.z ); - pPlayer->ForceOrigin( vecOrigin ); -} - - -ConCommand cc_Test_CreateEntity( "Test_CreateEntity", Test_CreateEntity, 0, FCVAR_CHEAT ); -ConCommand cc_Test_RandomPlayerPosition( "Test_RandomPlayerPosition", Test_RandomPlayerPosition, 0, FCVAR_CHEAT ); - - diff --git a/game/server/testtraceline.cpp b/game/server/testtraceline.cpp deleted file mode 100644 index b6d1365b7..000000000 --- a/game/server/testtraceline.cpp +++ /dev/null @@ -1,82 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// -------------------------------------------------------------------------------- // -// An entity used to test traceline -// -------------------------------------------------------------------------------- // - -class CTestTraceline : public CPointEntity -{ -public: - DECLARE_CLASS( CTestTraceline, CPointEntity ); - - void Spawn( void ); - int UpdateTransmitState(); - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - -private: - void Spin( void ); -}; - - -// This table encodes the CBaseEntity data. -IMPLEMENT_SERVERCLASS_ST_NOBASE(CTestTraceline, DT_TestTraceline) - SendPropInt (SENDINFO(m_clrRender), 32, SPROP_UNSIGNED ), - SendPropVector (SENDINFO(m_vecOrigin), 19, 0, MIN_COORD_INTEGER, MAX_COORD_INTEGER), - SendPropFloat (SENDINFO_VECTORELEM2(m_angRotation, 0, x), 19, 0, MIN_COORD_INTEGER, MAX_COORD_INTEGER), - SendPropFloat (SENDINFO_VECTORELEM2(m_angRotation, 1, y), 19, 0, MIN_COORD_INTEGER, MAX_COORD_INTEGER), - SendPropFloat (SENDINFO_VECTORELEM2(m_angRotation, 2, z), 19, 0, MIN_COORD_INTEGER, MAX_COORD_INTEGER), - SendPropEHandle (SENDINFO_NAME(m_hMoveParent, moveparent)), -END_SEND_TABLE() - -LINK_ENTITY_TO_CLASS( test_traceline, CTestTraceline ); - -BEGIN_DATADESC( CTestTraceline ) - - // Function Pointers - DEFINE_FUNCTION( Spin ), - -END_DATADESC() - - -void CTestTraceline::Spawn( void ) -{ - SetRenderColor( 255, 255, 255, 255 ); - SetNextThink( gpGlobals->curtime ); - - SetThink( &CTestTraceline::Spin ); -} - -void CTestTraceline::Spin( void ) -{ - static ConVar traceline_spin( "traceline_spin","1" ); - - if (traceline_spin.GetInt()) - { - float s = sin( gpGlobals->curtime ); - QAngle angles = GetLocalAngles(); - - angles[0] = 180.0 * 0.5 * (s * s * s + 1.0f) + 90; - angles[1] = gpGlobals->curtime * 10; - - SetLocalAngles( angles ); - - } - SetNextThink( gpGlobals->curtime ); -} - -int CTestTraceline::UpdateTransmitState() -{ - return SetTransmitState( FL_EDICT_ALWAYS ); -} diff --git a/game/server/textstatsmgr.cpp b/game/server/textstatsmgr.cpp deleted file mode 100644 index cb16727c4..000000000 --- a/game/server/textstatsmgr.cpp +++ /dev/null @@ -1,174 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "textstatsmgr.h" -#include "tier0/dbg.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -CTextStatsMgr g_TextStatsMgr; // The default text stats manager. - - -// ------------------------------------------------------------------------------------------ // -// CTextStatsMgr implementation. -// ------------------------------------------------------------------------------------------ // -CTextStatsMgr::CTextStatsMgr( void ) -{ - m_szStatFilename[0] = 0; -} - -bool CTextStatsMgr::WriteFile( IFileSystem *pFileSys, const char *pFilename ) -{ - // If no filename was specified, use out preset one - if ( !pFilename ) - { - pFilename = m_szStatFilename; - } - - FileHandle_t hFile = pFileSys->Open( pFilename, "wt", "LOGDIR" ); - if ( hFile == FILESYSTEM_INVALID_HANDLE ) - return false; - - CTextStat *pHead = CTextStat::GetTextStatsList(); - for ( CTextStat *pCur=pHead->m_pNext; pCur != pHead; pCur=pCur->m_pNext ) - { - if ( pCur->m_pMgr == this ) - pCur->m_PrintFn( pFileSys, hFile, pCur->m_pUserData ); - } - - pFileSys->Close( hFile ); - - // Call each CTextStatFile.. - for( CTextStatFile *pCurFile=CTextStatFile::s_pHead; pCurFile; pCurFile=pCurFile->m_pNext ) - { - pCurFile->m_pFn(); - } - - return true; -} - -char *CTextStatsMgr::GetStatsFilename( void ) -{ - return m_szStatFilename; -} - -void CTextStatsMgr::SetStatsFilename( const char *sFilename ) -{ - Assert( sFilename && sFilename[0] ); - - Q_strncpy( m_szStatFilename, sFilename, sizeof(m_szStatFilename) ); -} - -// ------------------------------------------------------------------------------------------ // -// CTextStat implementation. -// ------------------------------------------------------------------------------------------ // - -CTextStat::CTextStat() -{ - m_pPrev = m_pNext = this; - m_pMgr = NULL; -} - - -CTextStat::CTextStat( TextStatPrintFn printFn, void *pUserData, CTextStatsMgr *pMgr ) -{ - m_pPrev = m_pNext = this; - Init( printFn, pUserData, pMgr ); -} - - -CTextStat::~CTextStat() -{ - Term(); -} - - -void CTextStat::Init( TextStatPrintFn printFn, void *pUserData, CTextStatsMgr *pMgr ) -{ - Term(); - - m_pPrev = GetTextStatsList(); - m_pNext = GetTextStatsList()->m_pNext; - m_pPrev->m_pNext = m_pNext->m_pPrev = this; - - m_PrintFn = printFn; - m_pUserData = pUserData; - m_pMgr = pMgr; -} - - -void CTextStat::Term() -{ - // Remove from the global list. - m_pPrev->m_pNext = m_pNext; - m_pNext->m_pPrev = m_pPrev; - m_pPrev = m_pNext = this; - m_pMgr = NULL; -} - - -CTextStat::CTextStat( bool bGlobalListHead ) -{ - Assert( bGlobalListHead ); - m_pPrev = m_pNext = this; -} - - -CTextStat* CTextStat::GetTextStatsList() -{ - static CTextStat theList( true ); - return &theList; -} - - -void CTextStat::RemoveFn( void *pUserData ) -{ - CTextStat *pReg = (CTextStat*)pUserData; - pReg->Term(); -} - - -// ------------------------------------------------------------------------------------------ // -// CTextStatInt implementation. -// ------------------------------------------------------------------------------------------ // - -CTextStatInt::CTextStatInt( const char *pName, int initialValue, CTextStatsMgr *pMgr ) -{ - m_pName = pName; - m_Value = initialValue; - m_Reg.Init( &CTextStatInt::PrintFn, this, pMgr ); -} - - -void CTextStatInt::PrintFn( IFileSystem *pFileSys, FileHandle_t hFile, void *pUserData ) -{ - CTextStatInt *pStat = (CTextStatInt*)pUserData; - pFileSys->FPrintf( hFile, "%s %d\n", pStat->m_pName, pStat->m_Value ); -} - - - -// ------------------------------------------------------------------------------------------ // -// CTextStatFile functions. -// ------------------------------------------------------------------------------------------ // - -CTextStatFile *CTextStatFile::s_pHead = NULL; - - -CTextStatFile::CTextStatFile( TextStatFileFn fn ) -{ - m_pFn = fn; - m_pNext = CTextStatFile::s_pHead; - CTextStatFile::s_pHead = this; -} - - - - - diff --git a/game/server/textstatsmgr.h b/game/server/textstatsmgr.h deleted file mode 100644 index 2033ff60c..000000000 --- a/game/server/textstatsmgr.h +++ /dev/null @@ -1,133 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef TEXTSTATSMGR_H -#define TEXTSTATSMGR_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "filesystem.h" -#include "utllinkedlist.h" - - -// Text stats get to print their stuff by implementing this type of function. -typedef void (*TextStatPrintFn)( IFileSystem *pFileSys, FileHandle_t hFile, void *pUserData ); -typedef void (*TextStatFileFn)(); - - -// The CTextStatsMgr is just a collection of CTextStat's that go into the same file. -class CTextStatsMgr -{ -public: - CTextStatsMgr( void ); - - // Write a file with all the registered stats. - bool WriteFile( IFileSystem *pFileSystem, const char *pFilename = NULL ); - - // Get the preset filename to write stats to, if none is specified when writing - char *GetStatsFilename( void ); - - // Set the filename to write stats to, if none is specified when writing - void SetStatsFilename( const char *sFilename ); - -private: - char m_szStatFilename[ MAX_PATH ]; -}; - - -// This is the default CTextStatsMgr, but there can be any number of them. -extern CTextStatsMgr g_TextStatsMgr; - - - -// Make these to register text stat functions. -class CTextStat -{ -friend class CTextStatsMgr; - -public: - CTextStat(); - CTextStat( TextStatPrintFn fn, void *pUserData, CTextStatsMgr *pMgr=&g_TextStatsMgr ); - ~CTextStat(); - - // This can be called if you don't want to pass parameters into the constructor. - void Init( TextStatPrintFn printFn, void *pUserData, CTextStatsMgr *pMgr=&g_TextStatsMgr ); - void Term(); - - -private: - - // Special constructor to just tie off the linked list. - CTextStat( bool bGlobalListHead ); - - // The global list of CTextStats. - static CTextStat* GetTextStatsList(); - - static void RemoveFn( void *pUserData ); - - // Link it into the global list. - CTextStat *m_pPrev; - CTextStat *m_pNext; - - CTextStatsMgr *m_pMgr; - - TextStatPrintFn m_PrintFn; - void *m_pUserData; -}; - - -// This class registers like a ConVar and acts like an int. When the game is shutdown, -// its value will be saved in the stats file along with its name.s -class CTextStatInt -{ -public: - CTextStatInt( const char *pName, int initialValue=0, CTextStatsMgr *pMgr=&g_TextStatsMgr ); - - operator int() const { return m_Value; } - int operator=( int val ) { m_Value = val; return m_Value; } - - int operator++() { m_Value++; return m_Value; } - int operator--() { m_Value--; return m_Value; } - int operator+=( int val ) { m_Value += val; return m_Value; } - int operator-=( int val ) { m_Value -= val; return m_Value; } - int operator*=( int val ) { m_Value *= val; return m_Value; } - int operator/=( int val ) { m_Value /= val; return m_Value; } - - -private: - - static void PrintFn( IFileSystem *pFileSys, FileHandle_t hFile, void *pUserData ); - - -private: - - const char *m_pName; - int m_Value; - - CTextStat m_Reg; // Use to register ourselves. -}; - - -// This can be registered to get a callback when the text stats mgr is saving its files. -// You can write data out to your own file in here. -class CTextStatFile -{ -public: - CTextStatFile( TextStatFileFn fn ); - -private: - friend class CTextStatsMgr; - - static CTextStatFile *s_pHead; - CTextStatFile *m_pNext; - TextStatFileFn m_pFn; -}; - - -#endif // TEXTSTATSMGR_H diff --git a/game/server/timedeventmgr.cpp b/game/server/timedeventmgr.cpp deleted file mode 100644 index ee2dca738..000000000 --- a/game/server/timedeventmgr.cpp +++ /dev/null @@ -1,151 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "timedeventmgr.h" -#include "tier0/vprof.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// ------------------------------------------------------------------------------------------ // -// CEventRegister. -// ------------------------------------------------------------------------------------------ // - -CEventRegister::CEventRegister() -{ - m_bRegistered = false; - m_pEventMgr = NULL; -} - - -CEventRegister::~CEventRegister() -{ - Term(); -} - - -void CEventRegister::Init( CTimedEventMgr *pMgr, IEventRegisterCallback *pCallback ) -{ - Term(); - m_pEventMgr = pMgr; - m_pCallback = pCallback; -} - - -void CEventRegister::Term() -{ - // Unregister. - if ( m_pEventMgr && m_bRegistered ) - { - m_pEventMgr->RemoveEvent( this ); - } -} - - -void CEventRegister::SetUpdateInterval( float interval ) -{ - Assert( m_pEventMgr ); - - if ( m_pEventMgr ) - { - // Register for this event. - m_flUpdateInterval = interval; - m_flNextEventTime = gpGlobals->curtime + m_flUpdateInterval; - - m_pEventMgr->RegisterForNextEvent( this ); - } -} - - -void CEventRegister::StopUpdates() -{ - if ( m_pEventMgr ) - { - // Unregister our next event. - m_pEventMgr->RemoveEvent( this ); - } -} - - -void CEventRegister::Reregister() -{ - if ( m_flUpdateInterval > 1e-6 && m_pEventMgr ) - { - while ( m_flNextEventTime <= gpGlobals->curtime ) - { - m_flNextEventTime += m_flUpdateInterval; - } - - m_pEventMgr->RegisterForNextEvent( this ); - } -} - - -// ------------------------------------------------------------------------------------------ // -// CTimedEventMgr. -// ------------------------------------------------------------------------------------------ // - -bool TimedEventMgr_LessFunc( CEventRegister* const &a, CEventRegister* const &b ) -{ - return a->m_flNextEventTime > b->m_flNextEventTime; -} - - -CTimedEventMgr::CTimedEventMgr() -{ - m_Events.SetLessFunc( TimedEventMgr_LessFunc ); -} - - -void CTimedEventMgr::FireEvents() -{ - VPROF( "CTimedEventMgr::FireEvents" ); - while ( m_Events.Count() ) - { - // Fire the top element, then break out. - CEventRegister *pEvent = m_Events.ElementAtHead(); - if ( gpGlobals->curtime >= pEvent->m_flNextEventTime ) - { - // Reregister for the timed event, then fire the callback for the event. - m_Events.RemoveAtHead(); - pEvent->m_bRegistered = false; - pEvent->Reregister(); - - pEvent->m_pCallback->FireEvent(); - } - else - { - break; - } - } -} - - -void CTimedEventMgr::RegisterForNextEvent( CEventRegister *pEvent ) -{ - RemoveEvent( pEvent ); - m_Events.Insert( pEvent ); - pEvent->m_bRegistered = true; -} - - -void CTimedEventMgr::RemoveEvent( CEventRegister *pEvent ) -{ - if ( pEvent->m_bRegistered ) - { - // Find the event in the list and remove it. - int cnt = m_Events.Count(); - for ( int i=0; i < cnt; i++ ) - { - if ( m_Events.Element( i ) == pEvent ) - { - m_Events.RemoveAt( i ); - break; - } - } - } -} diff --git a/game/server/timedeventmgr.h b/game/server/timedeventmgr.h deleted file mode 100644 index 5e2155e1c..000000000 --- a/game/server/timedeventmgr.h +++ /dev/null @@ -1,93 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef TIMEDEVENTMGR_H -#define TIMEDEVENTMGR_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "utlpriorityqueue.h" - - -// -// -// These classes provide fast timed event callbacks. To use them, make a CTimedEventMgr -// and put CEventRegister objects in your objects that want the timed events. -// -// - - -class CTimedEventMgr; - - -abstract_class IEventRegisterCallback -{ -public: - virtual void FireEvent() = 0; -}; - - -class CEventRegister -{ -friend bool TimedEventMgr_LessFunc( CEventRegister* const &a, CEventRegister* const &b ); -friend class CTimedEventMgr; - -public: - CEventRegister(); - ~CEventRegister(); - - // Call this before ever calling SetUpdateInterval(). - void Init( CTimedEventMgr *pMgr, IEventRegisterCallback *pCallback ); - - // Use these to start and stop getting updates. - void SetUpdateInterval( float interval ); - void StopUpdates(); - - inline bool IsRegistered() const { return m_bRegistered; } - -private: - - void Reregister(); // After having an event processed, this is called to have it register for the next one. - void Term(); - - -private: - - CTimedEventMgr *m_pEventMgr; - float m_flNextEventTime; - float m_flUpdateInterval; - IEventRegisterCallback *m_pCallback; - bool m_bRegistered; -}; - - -class CTimedEventMgr -{ -friend class CEventRegister; - -public: - CTimedEventMgr(); - - // Call this each frame to fire events. - void FireEvents(); - - -private: - - // Things used by CEventRegister. - void RegisterForNextEvent( CEventRegister *pEvent ); - void RemoveEvent( CEventRegister *pEvent ); - -private: - - // Events, sorted by the time at which they will fire. - CUtlPriorityQueue m_Events; -}; - - -#endif // TIMEDEVENTMGR_H diff --git a/game/server/toolframework_server.cpp b/game/server/toolframework_server.cpp deleted file mode 100644 index c6928980c..000000000 --- a/game/server/toolframework_server.cpp +++ /dev/null @@ -1,138 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// -#include "cbase.h" -#include "igamesystem.h" -#include "toolframework/iserverenginetools.h" -#include "init_factory.h" - -//----------------------------------------------------------------------------- -// Purpose: This is an autogame system which is used to call back into the engine at appropriate points -// so that IToolSystems can get these hooks at the correct time -//----------------------------------------------------------------------------- -class CToolFrameworkServer : public CAutoGameSystemPerFrame, public IToolFrameworkServer -{ -public: - virtual bool Init(); - // Level init, shutdown - virtual void LevelInitPreEntity(); - // entities are created / spawned / precached here - virtual void LevelInitPostEntity(); - virtual void LevelShutdownPreEntity(); - // Entities are deleted / released here... - virtual void LevelShutdownPostEntity(); - // Called each frame before entities think - virtual void FrameUpdatePreEntityThink(); - // called after entities think - virtual void FrameUpdatePostEntityThink(); - virtual void PreClientUpdate(); - virtual void PreSetupVisibility(); - - - IServerEngineTools *m_pTools; -}; - -// Singleton -static CToolFrameworkServer g_ToolFrameworkServer; -IToolFrameworkServer *g_pToolFrameworkServer = &g_ToolFrameworkServer; - -#ifndef NO_TOOLFRAMEWORK - -bool ToolsEnabled() -{ - return g_ToolFrameworkServer.m_pTools && g_ToolFrameworkServer.m_pTools->InToolMode() && !engine->IsDedicatedServer(); -} - -#endif - -bool CToolFrameworkServer::Init() -{ - factorylist_t list; - FactoryList_Retrieve( list ); - - // Latch onto internal interface - m_pTools = ( IServerEngineTools * )list.engineFactory( VSERVERENGINETOOLS_INTERFACE_VERSION, NULL ); - - if ( !m_pTools && !engine->IsDedicatedServer() ) - { - return false; - } - - return true; -} - -void CToolFrameworkServer::LevelInitPreEntity() -{ - if ( !m_pTools ) - { - return; - } - m_pTools->LevelInitPreEntityAllTools(); -} - -void CToolFrameworkServer::LevelInitPostEntity() -{ - if ( !m_pTools ) - { - return; - } - m_pTools->LevelInitPostEntityAllTools(); -} - -void CToolFrameworkServer::LevelShutdownPreEntity() -{ - if ( !m_pTools ) - { - return; - } - m_pTools->LevelShutdownPreEntityAllTools(); -} - -void CToolFrameworkServer::LevelShutdownPostEntity() -{ - if ( !m_pTools ) - { - return; - } - m_pTools->LevelShutdownPostEntityAllTools(); -} - -void CToolFrameworkServer::FrameUpdatePreEntityThink() -{ - if ( !m_pTools ) - { - return; - } - m_pTools->FrameUpdatePreEntityThinkAllTools(); -} - -void CToolFrameworkServer::FrameUpdatePostEntityThink() -{ - if ( !m_pTools ) - { - return; - } - m_pTools->FrameUpdatePostEntityThinkAllTools(); -} - -void CToolFrameworkServer::PreClientUpdate() -{ - if ( !m_pTools ) - { - return; - } - m_pTools->PreClientUpdateAllTools(); -} - -void CToolFrameworkServer::PreSetupVisibility() -{ - if ( !m_pTools ) - { - return; - } - m_pTools->PreSetupVisibilityAllTools(); -} diff --git a/game/server/toolframework_server.h b/game/server/toolframework_server.h deleted file mode 100644 index 058822e41..000000000 --- a/game/server/toolframework_server.h +++ /dev/null @@ -1,27 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// - -#ifndef TOOLFRAMEWORK_SERVER_H -#define TOOLFRAMEWORK_SERVER_H - -#ifdef _WIN32 -#pragma once -#endif - - -//----------------------------------------------------------------------------- -// Are tools enabled? -//----------------------------------------------------------------------------- -#ifndef NO_TOOLFRAMEWORK -bool ToolsEnabled(); -#else -#define ToolsEnabled() 0 -#endif - - -#endif // TOOLFRAMEWORK_SERVER_H diff --git a/game/server/trains.cpp b/game/server/trains.cpp deleted file mode 100644 index fc28f3ff1..000000000 --- a/game/server/trains.cpp +++ /dev/null @@ -1,3303 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Spawn, think, and touch functions for trains, etc. -// -//=============================================================================// - -#include "cbase.h" -#include "ai_basenpc.h" -#include "trains.h" -#include "ndebugoverlay.h" -#include "entitylist.h" -#include "engine/IEngineSound.h" -#include "soundenvelope.h" -#include "physics_npc_solver.h" -#include "vphysics/friction.h" -#include "hierarchy.h" -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -static void PlatSpawnInsideTrigger(edict_t *pevPlatform); - -#define SF_PLAT_TOGGLE 0x0001 - -class CBasePlatTrain : public CBaseToggle -{ - DECLARE_CLASS( CBasePlatTrain, CBaseToggle ); - -public: - ~CBasePlatTrain(); - bool KeyValue( const char *szKeyName, const char *szValue ); - void Precache( void ); - - // This is done to fix spawn flag collisions between this class and a derived class - virtual bool IsTogglePlat( void ) { return (m_spawnflags & SF_PLAT_TOGGLE) ? true : false; } - - DECLARE_DATADESC(); - - void PlayMovingSound(); - void StopMovingSound(); - - string_t m_NoiseMoving; // sound a plat makes while moving - string_t m_NoiseArrived; - - CSoundPatch *m_pMovementSound; -#ifdef HL1_DLL - int m_MoveSound; - int m_StopSound; -#endif - - float m_volume; // Sound volume - float m_flTWidth; - float m_flTLength; -}; - -BEGIN_DATADESC( CBasePlatTrain ) - - DEFINE_KEYFIELD( m_NoiseMoving, FIELD_SOUNDNAME, "noise1" ), - DEFINE_KEYFIELD( m_NoiseArrived, FIELD_SOUNDNAME, "noise2" ), - -#ifdef HL1_DLL - DEFINE_KEYFIELD( m_MoveSound, FIELD_INTEGER, "movesnd" ), - DEFINE_KEYFIELD( m_StopSound, FIELD_INTEGER, "stopsnd" ), - -#endif - DEFINE_SOUNDPATCH( m_pMovementSound ), - - DEFINE_KEYFIELD( m_volume, FIELD_FLOAT, "volume" ), - - DEFINE_FIELD( m_flTWidth, FIELD_FLOAT ), - DEFINE_FIELD( m_flTLength, FIELD_FLOAT ), - DEFINE_KEYFIELD( m_flLip, FIELD_FLOAT, "lip" ), - DEFINE_KEYFIELD( m_flWait, FIELD_FLOAT, "wait" ), - DEFINE_KEYFIELD( m_flHeight, FIELD_FLOAT, "height" ), - -END_DATADESC() - - -bool CBasePlatTrain::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "rotation")) - { - m_vecFinalAngle.x = atof(szValue); - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } - - return true; -} - - -CBasePlatTrain::~CBasePlatTrain() -{ - StopMovingSound(); -} - -void CBasePlatTrain::PlayMovingSound() -{ - StopMovingSound(); - if(m_NoiseMoving != NULL_STRING ) - { - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - CPASAttenuationFilter filter( this ); - m_pMovementSound = controller.SoundCreate( filter, entindex(), CHAN_STATIC, STRING(m_NoiseMoving), ATTN_NORM ); - - controller.Play( m_pMovementSound, m_volume, PITCH_NORM ); - } -} - -void CBasePlatTrain::StopMovingSound() -{ - if ( m_pMovementSound ) - { - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - - controller.SoundDestroy( m_pMovementSound ); - m_pMovementSound = NULL; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlatTrain::Precache( void ) -{ - //Fill in a default value if necessary - UTIL_ValidateSoundName( m_NoiseMoving, "Plat.DefaultMoving" ); - UTIL_ValidateSoundName( m_NoiseArrived, "Plat.DefaultArrive" ); - -#ifdef HL1_DLL -// set the plat's "in-motion" sound - switch (m_MoveSound) - { - default: - case 0: - m_NoiseMoving = MAKE_STRING( "Plat.DefaultMoving" ); - break; - case 1: - m_NoiseMoving = MAKE_STRING("Plat.BigElev1"); - break; - case 2: - m_NoiseMoving = MAKE_STRING("Plat.BigElev2"); - break; - case 3: - m_NoiseMoving = MAKE_STRING("Plat.TechElev1"); - break; - case 4: - m_NoiseMoving = MAKE_STRING("Plat.TechElev2"); - break; - case 5: - m_NoiseMoving = MAKE_STRING("Plat.TechElev3"); - break; - case 6: - m_NoiseMoving = MAKE_STRING("Plat.FreightElev1"); - break; - case 7: - m_NoiseMoving = MAKE_STRING("Plat.FreightElev2"); - break; - case 8: - m_NoiseMoving = MAKE_STRING("Plat.HeavyElev"); - break; - case 9: - m_NoiseMoving = MAKE_STRING("Plat.RackElev"); - break; - case 10: - m_NoiseMoving = MAKE_STRING("Plat.RailElev"); - break; - case 11: - m_NoiseMoving = MAKE_STRING("Plat.SqueakElev"); - break; - case 12: - m_NoiseMoving = MAKE_STRING("Plat.OddElev1"); - break; - case 13: - m_NoiseMoving = MAKE_STRING("Plat.OddElev2"); - break; - } - -// set the plat's 'reached destination' stop sound - switch (m_StopSound) - { - default: - case 0: - m_NoiseArrived = MAKE_STRING( "Plat.DefaultArrive" ); - break; - case 1: - m_NoiseArrived = MAKE_STRING("Plat.BigElevStop1"); - break; - case 2: - m_NoiseArrived = MAKE_STRING("Plat.BigElevStop2"); - break; - case 3: - m_NoiseArrived = MAKE_STRING("Plat.FreightElevStop"); - break; - case 4: - m_NoiseArrived = MAKE_STRING("Plat.HeavyElevStop"); - break; - case 5: - m_NoiseArrived = MAKE_STRING("Plat.RackStop"); - break; - case 6: - m_NoiseArrived = MAKE_STRING("Plat.RailStop"); - break; - case 7: - m_NoiseArrived = MAKE_STRING("Plat.SqueakStop"); - break; - case 8: - m_NoiseArrived = MAKE_STRING("Plat.QuickStop"); - break; - } - -#endif // HL1_DLL - - //Precache them all - PrecacheScriptSound( (char *) STRING(m_NoiseMoving) ); - PrecacheScriptSound( (char *) STRING(m_NoiseArrived) ); - -} - - -class CFuncPlat : public CBasePlatTrain -{ - DECLARE_CLASS( CFuncPlat, CBasePlatTrain ); -public: - void Spawn( void ); - void Precache( void ); - bool CreateVPhysics(); - void Setup( void ); - - virtual void Blocked( CBaseEntity *pOther ); - void PlatUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - void CallGoDown( void ) { GoDown(); } - void CallHitTop( void ) { HitTop(); } - void CallHitBottom( void ) { HitBottom(); } - - virtual void GoUp( void ); - virtual void GoDown( void ); - virtual void HitTop( void ); - virtual void HitBottom( void ); - - void InputToggle(inputdata_t &data); - void InputGoUp(inputdata_t &data); - void InputGoDown(inputdata_t &data); - - DECLARE_DATADESC(); - -private: - - string_t m_sNoise; -}; - - -BEGIN_DATADESC( CFuncPlat ) - - DEFINE_FIELD( m_sNoise, FIELD_STRING ), - - // Function Pointers - DEFINE_FUNCTION( PlatUse ), - DEFINE_FUNCTION( CallGoDown ), - DEFINE_FUNCTION( CallHitTop ), - DEFINE_FUNCTION( CallHitBottom ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - DEFINE_INPUTFUNC( FIELD_VOID, "GoUp", InputGoUp ), - DEFINE_INPUTFUNC( FIELD_VOID, "GoDown", InputGoDown ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( func_plat, CFuncPlat ); - -//================================================== -// CPlatTrigger -//================================================== -class CPlatTrigger : public CBaseEntity -{ - DECLARE_CLASS( CPlatTrigger, CBaseEntity ); -public: - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() | FCAP_DONT_SAVE; } - void SpawnInsideTrigger( CFuncPlat *pPlatform ); - void Touch( CBaseEntity *pOther ); - CFuncPlat *m_pPlatform; -}; - -void CFuncPlat::Setup( void ) -{ - if (m_flTLength == 0) - { - m_flTLength = 80; - } - - if (m_flTWidth == 0) - { - m_flTWidth = 10; - } - - SetLocalAngles( vec3_angle ); - SetSolid( SOLID_BSP ); - SetMoveType( MOVETYPE_PUSH ); - - // Set size and link into world - SetModel( STRING( GetModelName() ) ); - - m_vecPosition1 = GetLocalOrigin(); //Top - m_vecPosition2 = GetLocalOrigin(); //Bottom - - if ( m_flHeight != 0 ) - { - m_vecPosition2.z = GetLocalOrigin().z - m_flHeight; - } - else - { - // NOTE: This works because the angles were set to vec3_angle above - m_vecPosition2.z = GetLocalOrigin().z - CollisionProp()->OBBSize().z + 8; - } - - if (m_flSpeed == 0) - { - m_flSpeed = 150; - } - - if ( m_volume == 0.0f ) - { - m_volume = 0.85f; - } -} - - -void CFuncPlat::Precache( ) -{ - BaseClass::Precache(); - - if ( IsTogglePlat() == false ) - { - // Create the "start moving" trigger - PlatSpawnInsideTrigger( edict() ); - } -} - - -void CFuncPlat::Spawn( ) - -{ - Setup(); - Precache(); - - // If this platform is the target of some button, it starts at the TOP position, - // and is brought down by that button. Otherwise, it starts at BOTTOM. - if ( GetEntityName() != NULL_STRING ) - { - UTIL_SetOrigin( this, m_vecPosition1); - m_toggle_state = TS_AT_TOP; - SetUse( &CFuncPlat::PlatUse ); - } - else - { - UTIL_SetOrigin( this, m_vecPosition2); - m_toggle_state = TS_AT_BOTTOM; - } - CreateVPhysics(); -} - -bool CFuncPlat::CreateVPhysics() -{ - VPhysicsInitShadow( false, false ); - return true; -} - - -static void PlatSpawnInsideTrigger(edict_t* pevPlatform) -{ - // old code: //GetClassPtr( (CPlatTrigger *)NULL)->SpawnInsideTrigger( GetClassPtr( (CFuncPlat *)pevPlatform ) ); - CPlatTrigger *plattrig = CREATE_UNSAVED_ENTITY( CPlatTrigger, "plat_trigger" ); - plattrig->SpawnInsideTrigger( (CFuncPlat *)GetContainingEntity( pevPlatform ) ); -} - - -// -// Create a trigger entity for a platform. -// -void CPlatTrigger::SpawnInsideTrigger( CFuncPlat *pPlatform ) -{ - m_pPlatform = pPlatform; - // Create trigger entity, "point" it at the owning platform, give it a touch method - SetSolid( SOLID_BSP ); - AddSolidFlags( FSOLID_TRIGGER ); - SetMoveType( MOVETYPE_NONE ); - SetLocalOrigin( pPlatform->GetLocalOrigin() ); - - // Establish the trigger field's size - CCollisionProperty *pCollision = m_pPlatform->CollisionProp(); - Vector vecTMin = pCollision->OBBMins() + Vector ( 25 , 25 , 0 ); - Vector vecTMax = pCollision->OBBMaxs() + Vector ( 25 , 25 , 8 ); - vecTMin.z = vecTMax.z - ( m_pPlatform->m_vecPosition1.z - m_pPlatform->m_vecPosition2.z + 8 ); - if ( pCollision->OBBSize().x <= 50 ) - { - vecTMin.x = (pCollision->OBBMins().x + pCollision->OBBMaxs().x) / 2; - vecTMax.x = vecTMin.x + 1; - } - if ( pCollision->OBBSize().y <= 50 ) - { - vecTMin.y = (pCollision->OBBMins().y + pCollision->OBBMaxs().y) / 2; - vecTMax.y = vecTMin.y + 1; - } - UTIL_SetSize ( this, vecTMin, vecTMax ); -} - - -// -// When the platform's trigger field is touched, the platform ??? -// -void CPlatTrigger::Touch( CBaseEntity *pOther ) -{ - // Ignore touches by non-players - if ( !pOther->IsPlayer() ) - return; - - // Ignore touches by corpses - if (!pOther->IsAlive()) - return; - - // Make linked platform go up/down. - if (m_pPlatform->m_toggle_state == TS_AT_BOTTOM) - m_pPlatform->GoUp(); - else if (m_pPlatform->m_toggle_state == TS_AT_TOP) - m_pPlatform->SetMoveDoneTime( 1 );// delay going down -} - - - -//----------------------------------------------------------------------------- -// Purpose: Used when a platform is the target of a button. -// Start bringing platform down. -// Input : pActivator - -// pCaller - -// useType - -// value - -//----------------------------------------------------------------------------- -void CFuncPlat::InputToggle(inputdata_t &data) -{ - if ( IsTogglePlat() ) - { - if (m_toggle_state == TS_AT_TOP) - GoDown(); - else if ( m_toggle_state == TS_AT_BOTTOM ) - GoUp(); - } - else - { - SetUse( NULL ); - - if (m_toggle_state == TS_AT_TOP) - GoDown(); - } -} - -void CFuncPlat::InputGoUp(inputdata_t &data) -{ - if ( m_toggle_state == TS_AT_BOTTOM ) - GoUp(); -} - -void CFuncPlat::InputGoDown(inputdata_t &data) -{ - if ( m_toggle_state == TS_AT_TOP ) - GoDown(); -} - -//----------------------------------------------------------------------------- -// Purpose: Used when a platform is the target of a button. -// Start bringing platform down. -// Input : pActivator - -// pCaller - -// useType - -// value - -//----------------------------------------------------------------------------- -void CFuncPlat::PlatUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - if ( IsTogglePlat() ) - { - // Top is off, bottom is on - bool on = (m_toggle_state == TS_AT_BOTTOM) ? true : false; - - if ( !ShouldToggle( useType, on ) ) - return; - - if (m_toggle_state == TS_AT_TOP) - GoDown(); - else if ( m_toggle_state == TS_AT_BOTTOM ) - GoUp(); - } - else - { - SetUse( NULL ); - - if (m_toggle_state == TS_AT_TOP) - GoDown(); - } -} - - -// -// Platform is at top, now starts moving down. -// -void CFuncPlat::GoDown( void ) -{ - PlayMovingSound(); - - ASSERT(m_toggle_state == TS_AT_TOP || m_toggle_state == TS_GOING_UP); - m_toggle_state = TS_GOING_DOWN; - SetMoveDone(&CFuncPlat::CallHitBottom); - LinearMove(m_vecPosition2, m_flSpeed); -} - - -// -// Platform has hit bottom. Stops and waits forever. -// -void CFuncPlat::HitBottom( void ) -{ - StopMovingSound(); - - if ( m_NoiseArrived != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_WEAPON; - ep.m_pSoundName = STRING(m_NoiseArrived); - ep.m_flVolume = m_volume; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - } - - ASSERT(m_toggle_state == TS_GOING_DOWN); - m_toggle_state = TS_AT_BOTTOM; -} - - -// -// Platform is at bottom, now starts moving up -// -void CFuncPlat::GoUp( void ) -{ - PlayMovingSound(); - - ASSERT(m_toggle_state == TS_AT_BOTTOM || m_toggle_state == TS_GOING_DOWN); - m_toggle_state = TS_GOING_UP; - SetMoveDone(&CFuncPlat::CallHitTop); - LinearMove(m_vecPosition1, m_flSpeed); -} - - -// -// Platform has hit top. Pauses, then starts back down again. -// -void CFuncPlat::HitTop( void ) -{ - StopMovingSound(); - - if ( m_NoiseArrived != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_WEAPON; - ep.m_pSoundName = STRING(m_NoiseArrived); - ep.m_flVolume = m_volume; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - } - - ASSERT(m_toggle_state == TS_GOING_UP); - m_toggle_state = TS_AT_TOP; - - if ( !IsTogglePlat() ) - { - // After a delay, the platform will automatically start going down again. - SetMoveDone( &CFuncPlat::CallGoDown ); - SetMoveDoneTime( 3 ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Called when we are blocked. -//----------------------------------------------------------------------------- -void CFuncPlat::Blocked( CBaseEntity *pOther ) -{ - DevMsg( 2, "%s Blocked by %s\n", GetClassname(), pOther->GetClassname() ); - - // Hurt the blocker a little - pOther->TakeDamage( CTakeDamageInfo( this, this, 1, DMG_CRUSH ) ); - - if (m_sNoise != NULL_STRING) - { - StopSound(entindex(), CHAN_STATIC, (char*)STRING(m_sNoise)); - } - - // Send the platform back where it came from - ASSERT(m_toggle_state == TS_GOING_UP || m_toggle_state == TS_GOING_DOWN); - if (m_toggle_state == TS_GOING_UP) - { - GoDown(); - } - else if (m_toggle_state == TS_GOING_DOWN) - { - GoUp (); - } -} - - -class CFuncPlatRot : public CFuncPlat -{ - DECLARE_CLASS( CFuncPlatRot, CFuncPlat ); -public: - void Spawn( void ); - void SetupRotation( void ); - - virtual void GoUp( void ); - virtual void GoDown( void ); - virtual void HitTop( void ); - virtual void HitBottom( void ); - - void RotMove( QAngle &destAngle, float time ); - DECLARE_DATADESC(); - - QAngle m_end, m_start; -}; - -LINK_ENTITY_TO_CLASS( func_platrot, CFuncPlatRot ); - -BEGIN_DATADESC( CFuncPlatRot ) - - DEFINE_FIELD( m_end, FIELD_VECTOR ), - DEFINE_FIELD( m_start, FIELD_VECTOR ), - -END_DATADESC() - - -void CFuncPlatRot::SetupRotation( void ) -{ - if ( m_vecFinalAngle.x != 0 ) // This plat rotates too! - { - CBaseToggle::AxisDir(); - m_start = GetLocalAngles(); - m_end = GetLocalAngles() + m_vecMoveAng * m_vecFinalAngle.x; - } - else - { - m_start = vec3_angle; - m_end = vec3_angle; - } - if ( GetEntityName() != NULL_STRING ) // Start at top - { - SetLocalAngles( m_end ); - } -} - - -void CFuncPlatRot::Spawn( void ) -{ - BaseClass::Spawn(); - SetupRotation(); -} - -void CFuncPlatRot::GoDown( void ) -{ - BaseClass::GoDown(); - RotMove( m_start, GetMoveDoneTime() ); -} - - -// -// Platform has hit bottom. Stops and waits forever. -// -void CFuncPlatRot::HitBottom( void ) -{ - BaseClass::HitBottom(); - SetLocalAngularVelocity( vec3_angle ); - SetLocalAngles( m_start ); -} - - -// -// Platform is at bottom, now starts moving up -// -void CFuncPlatRot::GoUp( void ) -{ - BaseClass::GoUp(); - RotMove( m_end, GetMoveDoneTime() ); -} - - -// -// Platform has hit top. Pauses, then starts back down again. -// -void CFuncPlatRot::HitTop( void ) -{ - BaseClass::HitTop(); - SetLocalAngularVelocity( vec3_angle ); - SetLocalAngles( m_end ); -} - - -void CFuncPlatRot::RotMove( QAngle &destAngle, float time ) -{ - // set destdelta to the vector needed to move - QAngle vecDestDelta = destAngle - GetLocalAngles(); - - // Travel time is so short, we're practically there already; so make it so. - if ( time >= 0.1) - SetLocalAngularVelocity( vecDestDelta * (1.0 / time) ); - else - { - SetLocalAngularVelocity( vecDestDelta ); - SetMoveDoneTime( 1 ); - } -} - - -class CFuncTrain : public CBasePlatTrain -{ - DECLARE_CLASS( CFuncTrain, CBasePlatTrain ); -public: - void Spawn( void ); - void Precache( void ); - void Activate( void ); - void OnRestore( void ); - - void SetupTarget( void ); - void Blocked( CBaseEntity *pOther ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - void Wait( void ); - void Next( void ); - - //Inputs - void InputToggle(inputdata_t &data); - void InputStart(inputdata_t &data); - void InputStop(inputdata_t &data); - - void Start( void ); - void Stop( void ); - - DECLARE_DATADESC(); - -public: - EHANDLE m_hCurrentTarget; - - bool m_activated; - EHANDLE m_hEnemy; - float m_flBlockDamage; // Damage to inflict when blocked. - float m_flNextBlockTime; - string_t m_iszLastTarget; - -}; - -LINK_ENTITY_TO_CLASS( func_train, CFuncTrain ); - - -BEGIN_DATADESC( CFuncTrain ) - - DEFINE_FIELD( m_hCurrentTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_activated, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hEnemy, FIELD_EHANDLE ), - DEFINE_FIELD( m_iszLastTarget, FIELD_STRING ), - DEFINE_FIELD( m_flNextBlockTime, FIELD_TIME ), - - DEFINE_KEYFIELD( m_flBlockDamage, FIELD_FLOAT, "dmg" ), - - // Function Pointers - DEFINE_FUNCTION( Wait ), - DEFINE_FUNCTION( Next ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - DEFINE_INPUTFUNC( FIELD_VOID, "Start", InputStart ), - DEFINE_INPUTFUNC( FIELD_VOID, "Stop", InputStop ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: Handles a train being blocked by an entity. -// Input : pOther - What was hit. -//----------------------------------------------------------------------------- -void CFuncTrain::Blocked( CBaseEntity *pOther ) -{ - if ( gpGlobals->curtime < m_flNextBlockTime ) - return; - - m_flNextBlockTime = gpGlobals->curtime + 0.5; - - //Inflict damage - pOther->TakeDamage( CTakeDamageInfo( this, this, m_flBlockDamage, DMG_CRUSH ) ); -} - - -void CFuncTrain::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - //If we've been waiting to be retriggered, move to the next destination - if ( m_spawnflags & SF_TRAIN_WAIT_RETRIGGER ) - { - // Move toward my target - m_spawnflags &= ~SF_TRAIN_WAIT_RETRIGGER; - Next(); - } - else - { - m_spawnflags |= SF_TRAIN_WAIT_RETRIGGER; - - // Pop back to last target if it's available - if ( m_hEnemy ) - { - m_target = m_hEnemy->GetEntityName(); - } - - SetNextThink( TICK_NEVER_THINK ); - SetLocalVelocity( vec3_origin ); - - if ( m_NoiseArrived != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_VOICE; - ep.m_pSoundName = STRING(m_NoiseArrived); - ep.m_flVolume = m_volume; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - } - } -} - -void CFuncTrain::Wait( void ) -{ - //If we're moving passed a path track, then trip its output - variant_t emptyVariant; - m_hCurrentTarget->AcceptInput( "InPass", this, this, emptyVariant, 0 ); - - // need pointer to LAST target. - if ( m_hCurrentTarget->HasSpawnFlags( SF_TRAIN_WAIT_RETRIGGER ) || HasSpawnFlags( SF_TRAIN_WAIT_RETRIGGER ) ) - { - AddSpawnFlags( SF_TRAIN_WAIT_RETRIGGER ); - - // Clear the sound channel. - StopMovingSound(); - - if ( m_NoiseArrived != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_VOICE; - ep.m_pSoundName = STRING(m_NoiseArrived); - ep.m_flVolume = m_volume; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - } - - SetMoveDoneTime( -1 ); - - return; - } - - //NOTENOTE: -1 wait will wait forever - if ( m_flWait != 0 ) - { - SetMoveDoneTime( m_flWait ); - - StopMovingSound(); - - if ( m_NoiseArrived != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_VOICE; - ep.m_pSoundName = STRING(m_NoiseArrived); - ep.m_flVolume = m_volume; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - } - - SetMoveDone( &CFuncTrain::Next ); - } - else - { - // Do it right now - Next(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Advances the train to the next path corner on the path. -//----------------------------------------------------------------------------- -void CFuncTrain::Next( void ) -{ - //Find our next target - CBaseEntity *pTarg = GetNextTarget(); - - //If none, we're done - if ( pTarg == NULL ) - { - //Stop the moving sound - StopMovingSound(); - - // Play stop sound - if ( m_NoiseArrived != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_VOICE; - ep.m_pSoundName = STRING(m_NoiseArrived); - ep.m_flVolume = m_volume; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - } - - return; - } - - // Save last target in case we need to find it again - m_iszLastTarget = m_target; - - m_target = pTarg->m_target; - m_flWait = pTarg->GetDelay(); - - // If our target has a speed, take it - if ( m_hCurrentTarget && m_hCurrentTarget->m_flSpeed != 0 ) - { - m_flSpeed = m_hCurrentTarget->m_flSpeed; - DevMsg( 2, "Train %s speed to %4.2f\n", GetDebugName(), m_flSpeed ); - } - - // Keep track of this since path corners change our target for us - m_hCurrentTarget = pTarg; - m_hEnemy = pTarg; - - //Check for teleport - if ( m_hCurrentTarget->HasSpawnFlags( SF_CORNER_TELEPORT ) ) - { - AddEffects( EF_NOINTERP ); - - // This is supposed to place the center of the func_train at the target's origin. - // FIXME: This is totally busted! It's using the wrong space for the computation... - UTIL_SetOrigin( this, pTarg->GetLocalOrigin() - CollisionProp()->OBBCenter() ); - - // Get on with doing the next path corner. - Wait(); - } - else - { - // Normal linear move - PlayMovingSound(); - - RemoveEffects( EF_NOINTERP ); - SetMoveDone( &CFuncTrain::Wait ); - - // This is supposed to place the center of the func_train at the target's origin. - // FIXME: This is totally busted! It's using the wrong space for the computation... - LinearMove ( pTarg->GetLocalOrigin() - CollisionProp()->OBBCenter(), m_flSpeed ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Called after all the entities spawn. -//----------------------------------------------------------------------------- -void CFuncTrain::Activate( void ) -{ - BaseClass::Activate(); - - // Not yet active, so teleport to first target - if ( m_activated == false ) - { - SetupTarget(); - - m_activated = true; - - if ( m_hCurrentTarget.Get() == NULL ) - return; - - // This is supposed to place the center of the func_train at the target's origin. - // FIXME: This is totally busted! It's using the wrong space for the computation... - UTIL_SetOrigin( this, m_hCurrentTarget->GetLocalOrigin() - CollisionProp()->OBBCenter() ); - if ( GetSolid() == SOLID_BSP ) - { - VPhysicsInitShadow( false, false ); - } - - // Start immediately if not triggered - if ( !GetEntityName() ) - { - SetMoveDoneTime( 0.1 ); - SetMoveDone( &CFuncTrain::Next ); - } - else - { - m_spawnflags |= SF_TRAIN_WAIT_RETRIGGER; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncTrain::SetupTarget( void ) -{ - // Find our target whenever we don't have one (level transition) - if ( !m_hCurrentTarget ) - { - CBaseEntity *pTarg = gEntList.FindEntityByName( NULL, m_target ); - - if ( pTarg == NULL ) - { - Msg( "Can't find target of train %s\n", STRING(m_target) ); - return; - } - - // Keep track of this since path corners change our target for us - m_target = pTarg->m_target; - m_hCurrentTarget = pTarg; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncTrain::Spawn( void ) -{ - Precache(); - - if ( m_flSpeed == 0 ) - { - m_flSpeed = 100; - } - - if ( !m_target ) - { - Warning("FuncTrain '%s' has no target.\n", GetDebugName()); - } - - if ( m_flBlockDamage == 0 ) - { - m_flBlockDamage = 2; - } - - SetMoveType( MOVETYPE_PUSH ); - SetSolid( SOLID_BSP ); - SetModel( STRING( GetModelName() ) ); - if ( m_spawnflags & SF_TRACKTRAIN_PASSABLE ) - { - AddSolidFlags( FSOLID_NOT_SOLID ); - } - - m_activated = false; - - if ( m_volume == 0.0f ) - { - m_volume = 0.85f; - } -} - - -void CFuncTrain::Precache( void ) -{ - BaseClass::Precache(); -} - - -void CFuncTrain::OnRestore( void ) -{ - BaseClass::OnRestore(); - - // Are we moving? - if ( IsMoving() ) - { - // Continue moving to the same target - m_target = m_iszLastTarget; - } - - SetupTarget(); -} - - -void CFuncTrain::InputToggle( inputdata_t &data ) -{ - //If we've been waiting to be retriggered, move to the next destination - if( HasSpawnFlags( SF_TRAIN_WAIT_RETRIGGER ) ) - { - Start(); - } - else - { - Stop(); - } -} - - -void CFuncTrain::InputStart( inputdata_t &data ) -{ - Start(); -} - - -void CFuncTrain::InputStop( inputdata_t &data ) -{ - Stop(); -} - - -void CFuncTrain::Start( void ) -{ - //start moving - if( HasSpawnFlags( SF_TRAIN_WAIT_RETRIGGER ) ) - { - // Move toward my target - RemoveSpawnFlags( SF_TRAIN_WAIT_RETRIGGER ); - Next(); - } -} - - -void CFuncTrain::Stop( void ) -{ - //stop moving - if( !HasSpawnFlags( SF_TRAIN_WAIT_RETRIGGER ) ) - { - AddSpawnFlags( SF_TRAIN_WAIT_RETRIGGER ); - - // Pop back to last target if it's available - if ( m_hEnemy ) - { - m_target = m_hEnemy->GetEntityName(); - } - - SetNextThink( TICK_NEVER_THINK ); - SetAbsVelocity( vec3_origin ); - - if ( m_NoiseArrived != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_VOICE; - ep.m_pSoundName = STRING(m_NoiseArrived); - ep.m_flVolume = m_volume; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - } - - //Do not teleport to our final move destination - SetMoveDone( NULL ); - SetMoveDoneTime( -1 ); - } -} - -BEGIN_DATADESC( CFuncTrackTrain ) - - DEFINE_KEYFIELD( m_length, FIELD_FLOAT, "wheels" ), - DEFINE_KEYFIELD( m_height, FIELD_FLOAT, "height" ), - DEFINE_KEYFIELD( m_maxSpeed, FIELD_FLOAT, "startspeed" ), - DEFINE_KEYFIELD( m_flBank, FIELD_FLOAT, "bank" ), - DEFINE_KEYFIELD( m_flBlockDamage, FIELD_FLOAT, "dmg" ), - DEFINE_KEYFIELD( m_iszSoundMove, FIELD_SOUNDNAME, "MoveSound" ), - DEFINE_KEYFIELD( m_iszSoundMovePing, FIELD_SOUNDNAME, "MovePingSound" ), - DEFINE_KEYFIELD( m_iszSoundStart, FIELD_SOUNDNAME, "StartSound" ), - DEFINE_KEYFIELD( m_iszSoundStop, FIELD_SOUNDNAME, "StopSound" ), - DEFINE_KEYFIELD( m_nMoveSoundMinPitch, FIELD_INTEGER, "MoveSoundMinPitch" ), - DEFINE_KEYFIELD( m_nMoveSoundMaxPitch, FIELD_INTEGER, "MoveSoundMaxPitch" ), - DEFINE_KEYFIELD( m_flMoveSoundMinTime, FIELD_FLOAT, "MoveSoundMinTime" ), - DEFINE_KEYFIELD( m_flMoveSoundMaxTime, FIELD_FLOAT, "MoveSoundMaxTime" ), - DEFINE_FIELD( m_flNextMoveSoundTime, FIELD_TIME ), - DEFINE_KEYFIELD( m_eVelocityType, FIELD_INTEGER, "velocitytype" ), - DEFINE_KEYFIELD( m_eOrientationType, FIELD_INTEGER, "orientationtype" ), - - DEFINE_FIELD( m_ppath, FIELD_CLASSPTR ), - DEFINE_FIELD( m_dir, FIELD_FLOAT ), - DEFINE_FIELD( m_controlMins, FIELD_VECTOR ), - DEFINE_FIELD( m_controlMaxs, FIELD_VECTOR ), - DEFINE_FIELD( m_flVolume, FIELD_FLOAT ), - DEFINE_FIELD( m_oldSpeed, FIELD_FLOAT ), - //DEFINE_FIELD( m_lastBlockPos, FIELD_POSITION_VECTOR ), // temp values for blocking, don't save - //DEFINE_FIELD( m_lastBlockTick, FIELD_INTEGER ), - - DEFINE_FIELD( m_bSoundPlaying, FIELD_BOOLEAN ), - - DEFINE_KEYFIELD( m_bManualSpeedChanges, FIELD_BOOLEAN, "ManualSpeedChanges" ), - DEFINE_KEYFIELD( m_flAccelSpeed, FIELD_FLOAT, "ManualAccelSpeed" ), - DEFINE_KEYFIELD( m_flDecelSpeed, FIELD_FLOAT, "ManualDecelSpeed" ), - -#ifdef HL1_DLL - DEFINE_FIELD( m_bOnTrackChange, FIELD_BOOLEAN ), -#endif - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Stop", InputStop ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartForward", InputStartForward ), - DEFINE_INPUTFUNC( FIELD_VOID, "StartBackward", InputStartBackward ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - DEFINE_INPUTFUNC( FIELD_VOID, "Resume", InputResume ), - DEFINE_INPUTFUNC( FIELD_VOID, "Reverse", InputReverse ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetSpeed", InputSetSpeed ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetSpeedDir", InputSetSpeedDir ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetSpeedReal", InputSetSpeedReal ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetSpeedDirAccel", InputSetSpeedDirAccel ), - - // Outputs - DEFINE_OUTPUT( m_OnStart, "OnStart" ), - DEFINE_OUTPUT( m_OnNext, "OnNextPoint" ), - - // Function Pointers - DEFINE_FUNCTION( Next ), - DEFINE_FUNCTION( Find ), - DEFINE_FUNCTION( NearestPath ), - DEFINE_FUNCTION( DeadEnd ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( func_tracktrain, CFuncTrackTrain ); - - -//----------------------------------------------------------------------------- -// Datatable -//----------------------------------------------------------------------------- -IMPLEMENT_SERVERCLASS_ST( CFuncTrackTrain, DT_FuncTrackTrain ) -END_SEND_TABLE() - - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CFuncTrackTrain::CFuncTrackTrain() -{ -#ifdef _DEBUG - m_controlMins.Init(); - m_controlMaxs.Init(); -#endif - - // These defaults match old func_tracktrains. Changing these defaults would - // require a vmf_tweak of older content to keep it from breaking. - m_eOrientationType = TrainOrientation_AtPathTracks; - m_eVelocityType = TrainVelocity_Instantaneous; - m_lastBlockPos.Init(); - m_lastBlockTick = gpGlobals->tickcount; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CFuncTrackTrain::DrawDebugTextOverlays( void ) -{ - int nOffset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[512]; - Q_snprintf( tempstr,sizeof(tempstr), "angles: %g %g %g", (double)GetLocalAngles()[PITCH], (double)GetLocalAngles()[YAW], (double)GetLocalAngles()[ROLL] ); - EntityText( nOffset, tempstr, 0 ); - nOffset++; - - float flCurSpeed = GetLocalVelocity().Length(); - Q_snprintf( tempstr,sizeof(tempstr), "current speed (goal): %g (%g)", (double)flCurSpeed, (double)m_flSpeed ); - EntityText( nOffset, tempstr, 0 ); - nOffset++; - - Q_snprintf( tempstr,sizeof(tempstr), "max speed: %g", (double)m_maxSpeed ); - EntityText( nOffset, tempstr, 0 ); - nOffset++; - } - - return nOffset; -} - - -void CFuncTrackTrain::DrawDebugGeometryOverlays() -{ - BaseClass::DrawDebugGeometryOverlays(); - if (m_debugOverlays & OVERLAY_BBOX_BIT) - { - NDebugOverlay::Box( GetAbsOrigin(), -Vector(4,4,4),Vector(4,4,4), 255, 0, 255, 0, 0); - Vector out; - VectorTransform( Vector(m_length,0,0), EntityToWorldTransform(), out ); - NDebugOverlay::Box( out, -Vector(4,4,4),Vector(4,4,4), 255, 0, 255, 0, 0); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CFuncTrackTrain::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "volume")) - { - m_flVolume = (float) (atoi(szValue)); - m_flVolume *= 0.1f; - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that stops the train. -//----------------------------------------------------------------------------- -void CFuncTrackTrain::InputStop( inputdata_t &inputdata ) -{ - Stop(); -} - - -//------------------------------------------------------------------------------ -// Purpose: Input handler that starts the train moving. -//------------------------------------------------------------------------------ -void CFuncTrackTrain::InputResume( inputdata_t &inputdata ) -{ - m_flSpeed = m_oldSpeed; - Start(); -} - - -//------------------------------------------------------------------------------ -// Purpose: Input handler that reverses the trains current direction of motion. -//------------------------------------------------------------------------------ -void CFuncTrackTrain::InputReverse( inputdata_t &inputdata ) -{ - SetDirForward( !IsDirForward() ); - SetSpeed( m_flSpeed ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns whether we are travelling forward along our path. -//----------------------------------------------------------------------------- -bool CFuncTrackTrain::IsDirForward() -{ - return ( m_dir == 1 ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Sets whether we go forward or backward along our path. -//----------------------------------------------------------------------------- -void CFuncTrackTrain::SetDirForward( bool bForward ) -{ - if ( bForward && ( m_dir != 1 ) ) - { - // Reverse direction. - if ( m_ppath && m_ppath->GetPrevious() ) - { - m_ppath = m_ppath->GetPrevious(); - } - - m_dir = 1; - } - else if ( !bForward && ( m_dir != -1 ) ) - { - // Reverse direction. - if ( m_ppath && m_ppath->GetNext() ) - { - m_ppath = m_ppath->GetNext(); - } - - m_dir = -1; - } -} - - -//------------------------------------------------------------------------------ -// Purpose: Input handler that starts the train moving. -//------------------------------------------------------------------------------ -void CFuncTrackTrain::InputStartForward( inputdata_t &inputdata ) -{ - SetDirForward( true ); - SetSpeed( m_maxSpeed ); -} - - -//------------------------------------------------------------------------------ -// Purpose: Input handler that starts the train moving. -//------------------------------------------------------------------------------ -void CFuncTrackTrain::InputStartBackward( inputdata_t &inputdata ) -{ - SetDirForward( false ); - SetSpeed( m_maxSpeed ); -} - - -//------------------------------------------------------------------------------ -// Purpose: Starts the train moving. -//------------------------------------------------------------------------------ -void CFuncTrackTrain::Start( void ) -{ - m_OnStart.FireOutput(this,this); - Next(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Toggles the train between moving and not moving. -//----------------------------------------------------------------------------- -void CFuncTrackTrain::InputToggle( inputdata_t &inputdata ) -{ - if ( m_flSpeed == 0 ) - { - SetSpeed( m_maxSpeed ); - } - else - { - SetSpeed( 0 ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Handles player use so players can control the speed of the train. -//----------------------------------------------------------------------------- -void CFuncTrackTrain::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - // player +USE - if ( useType == USE_SET ) - { - float delta = value; - - delta = ((int)(m_flSpeed * 4) / (int)m_maxSpeed)*0.25 + 0.25 * delta; - if ( delta > 1 ) - delta = 1; - else if ( delta < -0.25 ) - delta = -0.25; - if ( m_spawnflags & SF_TRACKTRAIN_FORWARDONLY ) - { - if ( delta < 0 ) - delta = 0; - } - SetDirForward( delta >= 0 ); - delta = fabs(delta); - SetSpeed( m_maxSpeed * delta ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that sets the speed of the train. -// Input : Float speed from 0 to max speed, in units per second. -//----------------------------------------------------------------------------- -void CFuncTrackTrain::InputSetSpeedReal( inputdata_t &inputdata ) -{ - SetSpeed( clamp( inputdata.value.Float(), 0, m_maxSpeed ) ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that sets the speed of the train. -// Input : Float speed scale from 0 to 1. -//----------------------------------------------------------------------------- -void CFuncTrackTrain::InputSetSpeed( inputdata_t &inputdata ) -{ - float flScale = clamp( inputdata.value.Float(), 0, 1 ); - SetSpeed( m_maxSpeed * flScale ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that sets the speed of the train and the direction -// based on the sign of the speed. -// Input : Float speed scale from -1 to 1. Negatives values indicate a reversed -// direction. -//----------------------------------------------------------------------------- -void CFuncTrackTrain::InputSetSpeedDir( inputdata_t &inputdata ) -{ - float newSpeed = inputdata.value.Float(); - SetDirForward( newSpeed >= 0 ); - newSpeed = fabs(newSpeed); - float flScale = clamp( newSpeed, 0, 1 ); - SetSpeed( m_maxSpeed * flScale ); -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler that sets the speed of the train and the direction -// based on the sign of the speed, and accels/decels to that speed -// Input : Float speed scale from -1 to 1. Negatives values indicate a reversed -// direction. -//----------------------------------------------------------------------------- -void CFuncTrackTrain::InputSetSpeedDirAccel( inputdata_t &inputdata ) -{ - float newSpeed = inputdata.value.Float(); - SetDirForward( newSpeed >= 0 ); - newSpeed = fabs(newSpeed); - float flScale = clamp( newSpeed, 0, 1 ); - SetSpeed( m_maxSpeed * flScale, true ); -} - -//----------------------------------------------------------------------------- -// Purpose: Sets the speed of the train to the given value in units per second. -//----------------------------------------------------------------------------- -void CFuncTrackTrain::SetSpeed( float flSpeed, bool bAccel /*= false */ ) -{ - m_bAccelToSpeed = bAccel; - - float flOldSpeed = m_flSpeed; - - if ( m_bAccelToSpeed ) - { - m_flDesiredSpeed = fabs( flSpeed ) * m_dir; - m_flSpeedChangeTime = gpGlobals->curtime; - - if ( m_flSpeed == 0 && fabs(m_flDesiredSpeed) > 0 ) - { - m_flSpeed = 0.1; // little push to get us going - } - - Start(); - - return; - } - - m_flSpeed = fabs( flSpeed ) * m_dir; - - if ( m_flSpeed != flOldSpeed) - { - // Changing speed. - if ( m_flSpeed != 0 ) - { - if ( flOldSpeed == 0 ) - { - // Starting to move. - Start(); - } - else - { - // Continuing to move. - Next(); - } - } - else - { - // Stopping. - Stop(); - } - } - - DevMsg( 2, "TRAIN(%s), speed to %.2f\n", GetDebugName(), m_flSpeed ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Stops the train. -//----------------------------------------------------------------------------- -void CFuncTrackTrain::Stop( void ) -{ - SetLocalVelocity( vec3_origin ); - SetLocalAngularVelocity( vec3_angle ); - m_oldSpeed = m_flSpeed; - m_flSpeed = 0; - SoundStop(); - SetThink(NULL); -} - -static CBaseEntity *FindPhysicsBlockerForHierarchy( CBaseEntity *pParentEntity ) -{ - CUtlVector list; - GetAllInHierarchy( pParentEntity, list ); - CBaseEntity *pPhysicsBlocker = NULL; - float maxForce = 0; - for ( int i = 0; i < list.Count(); i++ ) - { - IPhysicsObject *pPhysics = list[i]->VPhysicsGetObject(); - if ( pPhysics ) - { - IPhysicsFrictionSnapshot *pSnapshot = pPhysics->CreateFrictionSnapshot(); - while ( pSnapshot->IsValid() ) - { - IPhysicsObject *pOther = pSnapshot->GetObject(1); - CBaseEntity *pOtherEntity = static_cast(pOther->GetGameData()); - if ( pOtherEntity->GetMoveType() == MOVETYPE_VPHYSICS ) - { - Vector normal; - pSnapshot->GetSurfaceNormal(normal); - float dot = DotProduct( pParentEntity->GetAbsVelocity(), pSnapshot->GetNormalForce() * normal ); - if ( !pPhysicsBlocker || dot > maxForce ) - { - pPhysicsBlocker = pOtherEntity; - maxForce = dot; - } - } - pSnapshot->NextFrictionData(); - } - pPhysics->DestroyFrictionSnapshot( pSnapshot ); - } - } - return pPhysicsBlocker; -} - -//----------------------------------------------------------------------------- -// Purpose: Called when we are blocked by another entity. -// Input : pOther - -//----------------------------------------------------------------------------- -void CFuncTrackTrain::Blocked( CBaseEntity *pOther ) -{ - // Blocker is on-ground on the train - if ( ( pOther->GetFlags() & FL_ONGROUND ) && pOther->GetGroundEntity() == this ) - { - DevMsg( 1, "TRAIN(%s): Blocked by %s\n", GetDebugName(), pOther->GetClassname() ); - float deltaSpeed = fabs(m_flSpeed); - if ( deltaSpeed > 50 ) - deltaSpeed = 50; - - Vector vecNewVelocity; - pOther->GetVelocity( &vecNewVelocity ); - if ( !vecNewVelocity.z ) - { - pOther->ApplyAbsVelocityImpulse( Vector(0,0,deltaSpeed) ); - } - return; - } - else - { - Vector vecNewVelocity; - vecNewVelocity = pOther->GetAbsOrigin() - GetAbsOrigin(); - VectorNormalize(vecNewVelocity); - vecNewVelocity *= m_flBlockDamage; - pOther->SetAbsVelocity( vecNewVelocity ); - } - if ( HasSpawnFlags(SF_TRACKTRAIN_UNBLOCKABLE_BY_PLAYER) ) - { - CBaseEntity *pPhysicsBlocker = FindPhysicsBlockerForHierarchy(this); - if ( pPhysicsBlocker ) - { - // This code keeps track of how long this train has been blocked - // The heuristic here is to keep instantaneous blocks from invoking the somewhat - // heavy-handed solver (which will disable collisions until we're clear) in cases - // where physics can solve it easily enough. - int ticksBlocked = gpGlobals->tickcount - m_lastBlockTick; - float dist = 0.0f; - // wait at least 10 ticks and make sure the train isn't actually moving before really blocking - const int MIN_BLOCKED_TICKS = 10; - if ( ticksBlocked > MIN_BLOCKED_TICKS ) - { - dist = (GetAbsOrigin() - m_lastBlockPos).Length(); - // must have moved at least 10% of normal velocity over the blocking interval, or we're being blocked - float minLength = GetAbsVelocity().Length() * TICK_INTERVAL * MIN_BLOCKED_TICKS * 0.10f; - if ( dist < minLength ) - { - // been stuck for more than one tick without moving much? - // yes, disable collisions with the physics object most likely to be blocking us - EntityPhysics_CreateSolver( this, pPhysicsBlocker, true, 4.0f ); - } - } - // first time blocking or moved too far since last block, reset - if ( dist > 1.0f || m_lastBlockTick < 0 ) - { - m_lastBlockPos = GetAbsOrigin(); - m_lastBlockTick = gpGlobals->tickcount; - } - } - // unblockable shouldn't damage the player in this case - if ( pOther->IsPlayer() ) - return; - } - - DevWarning( 2, "TRAIN(%s): Blocked by %s (dmg:%.2f)\n", GetDebugName(), pOther->GetClassname(), m_flBlockDamage ); - if ( m_flBlockDamage <= 0 ) - return; - - // we can't hurt this thing, so we're not concerned with it - pOther->TakeDamage( CTakeDamageInfo( this, this, m_flBlockDamage, DMG_CRUSH ) ); -} - - -extern void FixupAngles( QAngle &v ); - -#define TRAIN_MAXSPEED 1000 // approx max speed for sound pitch calculation - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncTrackTrain::SoundStop( void ) -{ - // if sound playing, stop it - if ( m_bSoundPlaying ) - { - if ( m_iszSoundMove != NULL_STRING ) - { - StopSound( entindex(), CHAN_STATIC, STRING( m_iszSoundMove ) ); - } - - if ( m_iszSoundStop != NULL_STRING ) - { - CPASAttenuationFilter filter( this ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_ITEM; - ep.m_pSoundName = STRING(m_iszSoundStop); - ep.m_flVolume = m_flVolume; - ep.m_SoundLevel = SNDLVL_NORM; - - EmitSound( filter, entindex(), ep ); - } - } - - m_bSoundPlaying = false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Update pitch based on speed, start sound if not playing. -// NOTE: when train goes through transition, m_bSoundPlaying should become -// false, which will cause the looped sound to restart. -//----------------------------------------------------------------------------- -void CFuncTrackTrain::SoundUpdate( void ) -{ - if ( ( !m_iszSoundMove ) && ( !m_iszSoundStart ) && ( !m_iszSoundMovePing )) - { - return; - } - - // In multiplayer, only update the sound once a second - if ( g_pGameRules->IsMultiplayer() && m_bSoundPlaying ) - { - if ( m_flNextMPSoundTime > gpGlobals->curtime ) - return; - - m_flNextMPSoundTime = gpGlobals->curtime + 1.0; - } - - float flSpeedRatio = 0; - if ( HasSpawnFlags( SF_TRACKTRAIN_USE_MAXSPEED_FOR_PITCH ) ) - { - flSpeedRatio = clamp( fabs( m_flSpeed ) / m_maxSpeed, 0, 1 ); - } - else - { - flSpeedRatio = clamp( fabs( m_flSpeed ) / TRAIN_MAXSPEED, 0, 1 ); - } - - float flpitch = RemapVal( flSpeedRatio, 0, 1, m_nMoveSoundMinPitch, m_nMoveSoundMaxPitch ); - - CPASAttenuationFilter filter( this ); - CPASAttenuationFilter filterReliable( this ); - filterReliable.MakeReliable(); - - Vector vecWorldSpaceCenter = WorldSpaceCenter(); - - if (!m_bSoundPlaying) - { - if ( m_iszSoundStart != NULL_STRING ) - { - EmitSound_t ep; - ep.m_nChannel = CHAN_ITEM; - ep.m_pSoundName = STRING(m_iszSoundStart); - ep.m_flVolume = m_flVolume; - ep.m_SoundLevel = SNDLVL_NORM; - ep.m_pOrigin = &vecWorldSpaceCenter; - - EmitSound( filter, entindex(), ep ); - } - - if ( m_iszSoundMove != NULL_STRING ) - { - EmitSound_t ep; - ep.m_nChannel = CHAN_STATIC; - ep.m_pSoundName = STRING(m_iszSoundMove); - ep.m_flVolume = m_flVolume; - ep.m_SoundLevel = SNDLVL_NORM; - ep.m_nPitch = (int)flpitch; - ep.m_pOrigin = &vecWorldSpaceCenter; - - EmitSound( filterReliable, entindex(), ep ); - } - - // We've just started moving. Delay the next move ping sound. - m_flNextMoveSoundTime = gpGlobals->curtime + RemapVal( flSpeedRatio, 0, 1, m_flMoveSoundMaxTime, m_flMoveSoundMinTime ); - - m_bSoundPlaying = true; - } - else - { - if ( m_iszSoundMove != NULL_STRING ) - { - // update pitch - EmitSound_t ep; - ep.m_nChannel = CHAN_STATIC; - ep.m_pSoundName = STRING(m_iszSoundMove); - ep.m_flVolume = m_flVolume; - ep.m_SoundLevel = SNDLVL_NORM; - ep.m_nPitch = (int)flpitch; - ep.m_nFlags = SND_CHANGE_PITCH; - ep.m_pOrigin = &vecWorldSpaceCenter; - - // In multiplayer, don't make this reliable - if ( g_pGameRules->IsMultiplayer() ) - { - EmitSound( filter, entindex(), ep ); - } - else - { - EmitSound( filterReliable, entindex(), ep ); - } - } - - if ( ( m_iszSoundMovePing != NULL_STRING ) && ( gpGlobals->curtime > m_flNextMoveSoundTime ) ) - { - EmitSound(STRING(m_iszSoundMovePing)); - m_flNextMoveSoundTime = gpGlobals->curtime + RemapVal( flSpeedRatio, 0, 1, m_flMoveSoundMaxTime, m_flMoveSoundMinTime ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pNode - -//----------------------------------------------------------------------------- -void CFuncTrackTrain::ArriveAtNode( CPathTrack *pNode ) -{ - // BUGBUG: This is wrong. We need to fire all targets between the one we've passed and the one - // we've switched to. - FirePassInputs( pNode, pNode->GetNext(), true ); - - // - // Disable train controls if this path track says to do so. - // - if ( pNode->HasSpawnFlags( SF_PATH_DISABLE_TRAIN ) ) - { - m_spawnflags |= SF_TRACKTRAIN_NOCONTROL; - } - - // - // Don't override the train speed if it's under user control. - // - if ( m_spawnflags & SF_TRACKTRAIN_NOCONTROL ) - { - // - // Don't copy speed from path track if it is 0 (uninitialized). - // - if ( pNode->m_flSpeed != 0 ) - { - SetSpeed( pNode->m_flSpeed ); - DevMsg( 2, "TrackTrain %s arrived at %s, speed to %4.2f\n", GetDebugName(), pNode->GetDebugName(), pNode->m_flSpeed ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Controls how the train accelerates as it moves along the path. -//----------------------------------------------------------------------------- -TrainVelocityType_t CFuncTrackTrain::GetTrainVelocityType() -{ - return m_eVelocityType; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pnext - -//----------------------------------------------------------------------------- -void CFuncTrackTrain::UpdateTrainVelocity( CPathTrack *pPrev, CPathTrack *pNext, const Vector &nextPos, float flInterval ) -{ - switch ( GetTrainVelocityType() ) - { - case TrainVelocity_Instantaneous: - { - Vector velDesired = nextPos - GetLocalOrigin(); - VectorNormalize( velDesired ); - velDesired *= fabs( m_flSpeed ); - SetLocalVelocity( velDesired ); - break; - } - - case TrainVelocity_LinearBlend: - case TrainVelocity_EaseInEaseOut: - { - if ( m_bAccelToSpeed ) - { - float flPrevSpeed = m_flSpeed; - float flNextSpeed = m_flDesiredSpeed; - - if ( flPrevSpeed != flNextSpeed ) - { - float flSpeedChangeTime = ( fabs(flNextSpeed) > fabs(flPrevSpeed) ) ? m_flAccelSpeed : m_flDecelSpeed; - m_flSpeed = UTIL_Approach( m_flDesiredSpeed, m_flSpeed, flSpeedChangeTime * gpGlobals->frametime ); - } - } - else if ( pPrev && pNext ) - { - // Get the speed to blend from. - float flPrevSpeed = m_flSpeed; - if ( pPrev->m_flSpeed != 0 ) - { - flPrevSpeed = pPrev->m_flSpeed; - } - - // Get the speed to blend to. - float flNextSpeed = flPrevSpeed; - if ( pNext->m_flSpeed != 0 ) - { - flNextSpeed = pNext->m_flSpeed; - } - - // If they're different, do the blend. - if ( flPrevSpeed != flNextSpeed ) - { - Vector vecSegment = pNext->GetLocalOrigin() - pPrev->GetLocalOrigin(); - float flSegmentLen = vecSegment.Length(); - if ( flSegmentLen ) - { - Vector vecCurOffset = GetLocalOrigin() - pPrev->GetLocalOrigin(); - float p = vecCurOffset.Length() / flSegmentLen; - if ( GetTrainVelocityType() == TrainVelocity_EaseInEaseOut ) - { - p = SimpleSplineRemapVal( p, 0.0f, 1.0f, 0.0f, 1.0f ); - } - - m_flSpeed = m_dir * ( flPrevSpeed * ( 1 - p ) + flNextSpeed * p ); - } - } - else - { - m_flSpeed = m_dir * flPrevSpeed; - } - } - - Vector velDesired = nextPos - GetLocalOrigin(); - VectorNormalize( velDesired ); - velDesired *= fabs( m_flSpeed ); - SetLocalVelocity( velDesired ); - break; - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Controls how the train blends angles as it moves along the path. -//----------------------------------------------------------------------------- -TrainOrientationType_t CFuncTrackTrain::GetTrainOrientationType() -{ -#ifdef HL1_DLL - return TrainOrientation_AtPathTracks; -#else - return m_eOrientationType; -#endif -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pnext - -//----------------------------------------------------------------------------- -void CFuncTrackTrain::UpdateTrainOrientation( CPathTrack *pPrev, CPathTrack *pNext, const Vector &nextPos, float flInterval ) -{ - // FIXME: old way of doing fixed orienation trains, remove! - if ( HasSpawnFlags( SF_TRACKTRAIN_FIXED_ORIENTATION ) ) - return; - - // Trains *can* work in local space, but only if all elements of the track share - // the same move parent as the train. - Assert( !pPrev || (pPrev->GetMoveParent() == GetMoveParent()) ); - - switch ( GetTrainOrientationType() ) - { - case TrainOrientation_Fixed: - { - // Fixed orientation. Do nothing. - break; - } - - case TrainOrientation_AtPathTracks: - { - UpdateOrientationAtPathTracks( pPrev, pNext, nextPos, flInterval ); - break; - } - - case TrainOrientation_EaseInEaseOut: - case TrainOrientation_LinearBlend: - { - UpdateOrientationBlend( GetTrainOrientationType(), pPrev, pNext, nextPos, flInterval ); - break; - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Adjusts our angles as we hit each path track. This is for support of -// trains with wheels that round corners a la HL1 trains. -// FIXME: move into path_track, have the angles come back from LookAhead -//----------------------------------------------------------------------------- -void CFuncTrackTrain::UpdateOrientationAtPathTracks( CPathTrack *pPrev, CPathTrack *pNext, const Vector &nextPos, float flInterval ) -{ - if ( !m_ppath ) - return; - - Vector nextFront = GetLocalOrigin(); - - CPathTrack *pNextNode = NULL; - - nextFront.z -= m_height; - if ( m_length > 0 ) - { - m_ppath->LookAhead( nextFront, IsDirForward() ? m_length : -m_length, 0, &pNextNode ); - } - else - { - m_ppath->LookAhead( nextFront, IsDirForward() ? 100 : -100, 0, &pNextNode ); - } - nextFront.z += m_height; - - Vector vecFaceDir = nextFront - GetLocalOrigin(); - if ( !IsDirForward() ) - { - vecFaceDir *= -1; - } - QAngle angles; - VectorAngles( vecFaceDir, angles ); - // !!! All of this crap has to be done to make the angles not wrap around, revisit this. - FixupAngles( angles ); - - // Wrapped with this bool so we don't affect old trains - if ( m_bManualSpeedChanges ) - { - if ( pNextNode && pNextNode->GetOrientationType() == TrackOrientation_FacePathAngles ) - { - angles = pNextNode->GetOrientation( IsDirForward() ); - } - } - - QAngle curAngles = GetLocalAngles(); - FixupAngles( curAngles ); - - if ( !pPrev || (vecFaceDir.x == 0 && vecFaceDir.y == 0) ) - angles = curAngles; - - DoUpdateOrientation( curAngles, angles, flInterval ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Blends our angles using one of two orientation blending types. -// ASSUMES that eOrientationType is either LinearBlend or EaseInEaseOut. -// FIXME: move into path_track, have the angles come back from LookAhead -//----------------------------------------------------------------------------- -void CFuncTrackTrain::UpdateOrientationBlend( TrainOrientationType_t eOrientationType, CPathTrack *pPrev, CPathTrack *pNext, const Vector &nextPos, float flInterval ) -{ - // Get the angles to blend from. - QAngle angPrev = pPrev->GetOrientation( IsDirForward() ); - FixupAngles( angPrev ); - - // Get the angles to blend to. - QAngle angNext; - if ( pNext ) - { - angNext = pNext->GetOrientation( IsDirForward() ); - FixupAngles( angNext ); - } - else - { - // At a dead end, just use the last path track's angles. - angNext = angPrev; - } - - if ( m_spawnflags & SF_TRACKTRAIN_NOPITCH ) - { - angNext[PITCH] = angPrev[PITCH]; - } - - // Calculate our parametric distance along the path segment from 0 to 1. - float p = 0; - if ( pPrev && ( angPrev != angNext ) ) - { - Vector vecSegment = pNext->GetLocalOrigin() - pPrev->GetLocalOrigin(); - float flSegmentLen = vecSegment.Length(); - if ( flSegmentLen ) - { - Vector vecCurOffset = GetLocalOrigin() - pPrev->GetLocalOrigin(); - p = vecCurOffset.Length() / flSegmentLen; - } - } - - if ( eOrientationType == TrainOrientation_EaseInEaseOut ) - { - p = SimpleSplineRemapVal( p, 0.0f, 1.0f, 0.0f, 1.0f ); - } - - //Msg( "UpdateOrientationFacePathAngles: %s->%s, p=%f, ", pPrev->GetDebugName(), pNext->GetDebugName(), p ); - - Quaternion qtPrev; - Quaternion qtNext; - - AngleQuaternion( angPrev, qtPrev ); - AngleQuaternion( angNext, qtNext ); - - QAngle angNew = angNext; - float flAngleDiff = QuaternionAngleDiff( qtPrev, qtNext ); - if ( flAngleDiff ) - { - Quaternion qtNew; - QuaternionSlerp( qtPrev, qtNext, p, qtNew ); - QuaternionAngles( qtNew, angNew ); - } - - if ( m_spawnflags & SF_TRACKTRAIN_NOPITCH ) - { - angNew[PITCH] = angPrev[PITCH]; - } - - DoUpdateOrientation( GetLocalAngles(), angNew, flInterval ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Sets our angular velocity to approach the target angles over the given interval. -//----------------------------------------------------------------------------- -void CFuncTrackTrain::DoUpdateOrientation( const QAngle &curAngles, const QAngle &angles, float flInterval ) -{ - float vy, vx; - if ( !(m_spawnflags & SF_TRACKTRAIN_NOPITCH) ) - { - vx = UTIL_AngleDistance( angles.x, curAngles.x ); - } - else - { - vx = 0; - } - - vy = UTIL_AngleDistance( angles.y, curAngles.y ); - - // HACKHACK: Clamp really small angular deltas to avoid rotating movement on things - // that are close enough - if ( fabs(vx) < 0.1 ) - { - vx = 0; - } - if ( fabs(vy) < 0.1 ) - { - vy = 0; - } - - if ( flInterval == 0 ) - { - // Avoid dividing by zero - flInterval = 0.1; - } - - QAngle vecAngVel( vx / flInterval, vy / flInterval, GetLocalAngularVelocity().z ); - - if ( m_flBank != 0 ) - { - if ( vecAngVel.y < -5 ) - { - vecAngVel.z = UTIL_AngleDistance( UTIL_ApproachAngle( -m_flBank, curAngles.z, m_flBank*2 ), curAngles.z); - } - else if ( vecAngVel.y > 5 ) - { - vecAngVel.z = UTIL_AngleDistance( UTIL_ApproachAngle( m_flBank, curAngles.z, m_flBank*2 ), curAngles.z); - } - else - { - vecAngVel.z = UTIL_AngleDistance( UTIL_ApproachAngle( 0, curAngles.z, m_flBank*4 ), curAngles.z) * 4; - } - } - - SetLocalAngularVelocity( vecAngVel ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pTeleport - -//----------------------------------------------------------------------------- -void CFuncTrackTrain::TeleportToPathTrack( CPathTrack *pTeleport ) -{ - QAngle angCur = GetLocalAngles(); - - Vector nextPos = pTeleport->GetLocalOrigin(); - Vector look = nextPos; - pTeleport->LookAhead( look, m_length, 0 ); - - QAngle nextAngles; - if ( HasSpawnFlags( SF_TRACKTRAIN_FIXED_ORIENTATION ) || ( look == nextPos ) ) - { - nextAngles = GetLocalAngles(); - } - else - { - nextAngles = pTeleport->GetOrientation( IsDirForward() ); - if ( HasSpawnFlags( SF_TRACKTRAIN_NOPITCH ) ) - { - nextAngles[PITCH] = angCur[PITCH]; - } - } - - Teleport( &pTeleport->GetLocalOrigin(), &nextAngles, NULL ); - SetLocalAngularVelocity( vec3_angle ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Advances the train to the next path corner on the path. -//----------------------------------------------------------------------------- -void CFuncTrackTrain::Next( void ) -{ - if ( !m_flSpeed ) - { - DevMsg( 2, "TRAIN(%s): Speed is 0\n", GetDebugName() ); - SoundStop(); - return; - } - - if ( !m_ppath ) - { - DevMsg( 2, "TRAIN(%s): Lost path\n", GetDebugName() ); - SoundStop(); - m_flSpeed = 0; - return; - } - - SoundUpdate(); - - // - // Based on our current position and speed, look ahead along our path and see - // where we should be in 0.1 seconds. - // - Vector nextPos = GetLocalOrigin(); - float flSpeed = m_flSpeed; - - nextPos.z -= m_height; - CPathTrack *pNextNext = NULL; - CPathTrack *pNext = m_ppath->LookAhead( nextPos, flSpeed * 0.1, 1, &pNextNext ); - //Assert( pNext != NULL ); - - // If we're moving towards a dead end, but our desired speed goes in the opposite direction - // this fixes us from stalling - if ( m_bManualSpeedChanges && ( ( flSpeed < 0 ) != ( m_flDesiredSpeed < 0 ) ) ) - { - if ( !pNext ) - pNext = m_ppath; - } - - if (m_debugOverlays & OVERLAY_BBOX_BIT) - { - if ( pNext != NULL ) - { - NDebugOverlay::Line( GetAbsOrigin(), pNext->GetAbsOrigin(), 255, 0, 0, true, 0.1 ); - NDebugOverlay::Line( pNext->GetAbsOrigin(), pNext->GetAbsOrigin() + Vector( 0,0,32), 255, 0, 0, true, 0.1 ); - NDebugOverlay::Box( pNext->GetAbsOrigin(), Vector( -8, -8, -8 ), Vector( 8, 8, 8 ), 255, 0, 0, 0, 0.1 ); - } - - if ( pNextNext != NULL ) - { - NDebugOverlay::Line( GetAbsOrigin(), pNextNext->GetAbsOrigin(), 0, 255, 0, true, 0.1 ); - NDebugOverlay::Line( pNextNext->GetAbsOrigin(), pNextNext->GetAbsOrigin() + Vector( 0,0,32), 0, 255, 0, true, 0.1 ); - NDebugOverlay::Box( pNextNext->GetAbsOrigin(), Vector( -8, -8, -8 ), Vector( 8, 8, 8 ), 0, 255, 0, 0, 0.1 ); - } - } - - nextPos.z += m_height; - - // Trains *can* work in local space, but only if all elements of the track share - // the same move parent as the train. - Assert( !pNext || (pNext->GetMoveParent() == GetMoveParent()) ); - - if ( pNext ) - { - UpdateTrainVelocity( pNext, pNextNext, nextPos, gpGlobals->frametime ); - UpdateTrainOrientation( pNext, pNextNext, nextPos, gpGlobals->frametime ); - - if ( pNext != m_ppath ) - { - // - // We have reached a new path track. Fire its OnPass output. - // - m_ppath = pNext; - ArriveAtNode( pNext ); -#ifdef HL1_DLL - m_bOnTrackChange = false; -#endif - - // - // See if we should teleport to the next path track. - // - CPathTrack *pTeleport = pNext->GetNext(); - if ( ( pTeleport != NULL ) && pTeleport->HasSpawnFlags( SF_PATH_TELEPORT ) ) - { - TeleportToPathTrack( pTeleport ); - } - } - - m_OnNext.FireOutput( pNext, this ); - - SetThink( &CFuncTrackTrain::Next ); - SetMoveDoneTime( 0.5 ); - SetNextThink( gpGlobals->curtime ); - SetMoveDone( NULL ); - } - else - { - // - // We've reached the end of the path, stop. - // - SoundStop(); - SetLocalVelocity(nextPos - GetLocalOrigin()); - SetLocalAngularVelocity( vec3_angle ); - float distance = GetLocalVelocity().Length(); - m_oldSpeed = m_flSpeed; - - m_flSpeed = 0; - - // Move to the dead end - - // Are we there yet? - if ( distance > 0 ) - { - // no, how long to get there? - float flTime = distance / fabs( m_oldSpeed ); - SetLocalVelocity( GetLocalVelocity() * (m_oldSpeed / distance) ); - SetMoveDone( &CFuncTrackTrain::DeadEnd ); - SetNextThink( TICK_NEVER_THINK ); - SetMoveDoneTime( flTime ); - } - else - { - DeadEnd(); - } - } -} - - -void CFuncTrackTrain::FirePassInputs( CPathTrack *pStart, CPathTrack *pEnd, bool forward ) -{ - CPathTrack *pCurrent = pStart; - - // swap if going backward - if ( !forward ) - { - pCurrent = pEnd; - pEnd = pStart; - } - variant_t emptyVariant; - - while ( pCurrent && pCurrent != pEnd ) - { - //Msg("Fired pass on %s\n", STRING(pCurrent->GetEntityName()) ); - pCurrent->AcceptInput( "InPass", this, this, emptyVariant, 0 ); - pCurrent = forward ? pCurrent->GetNext() : pCurrent->GetPrevious(); - } -} - - -void CFuncTrackTrain::DeadEnd( void ) -{ - // Fire the dead-end target if there is one - CPathTrack *pTrack, *pNext; - - pTrack = m_ppath; - - DevMsg( 2, "TRAIN(%s): Dead end ", GetDebugName() ); - // Find the dead end path node - // HACKHACK -- This is bugly, but the train can actually stop moving at a different node depending on it's speed - // so we have to traverse the list to it's end. - if ( pTrack ) - { - if ( m_oldSpeed < 0 ) - { - do - { - pNext = pTrack->ValidPath( pTrack->GetPrevious(), true ); - if ( pNext ) - pTrack = pNext; - } while ( pNext ); - } - else - { - do - { - pNext = pTrack->ValidPath( pTrack->GetNext(), true ); - if ( pNext ) - pTrack = pNext; - } while ( pNext ); - } - } - - SetLocalVelocity( vec3_origin ); - SetLocalAngularVelocity( vec3_angle ); - if ( pTrack ) - { - DevMsg( 2, "at %s\n", pTrack->GetDebugName() ); - variant_t emptyVariant; - pTrack->AcceptInput( "InPass", this, this, emptyVariant, 0 ); - } - else - { - DevMsg( 2, "\n" ); - } -} - - -void CFuncTrackTrain::SetControls( CBaseEntity *pControls ) -{ - Vector offset = pControls->GetLocalOrigin(); - - m_controlMins = pControls->WorldAlignMins() + offset; - m_controlMaxs = pControls->WorldAlignMaxs() + offset; -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns true if the entity's origin is within the controls region. -//----------------------------------------------------------------------------- -bool CFuncTrackTrain::OnControls( CBaseEntity *pTest ) -{ - Vector offset = pTest->GetLocalOrigin() - GetLocalOrigin(); - - if ( m_spawnflags & SF_TRACKTRAIN_NOCONTROL ) - return false; - - // Transform offset into local coordinates - VMatrix tmp = SetupMatrixAngles( GetLocalAngles() ); - // rotate into local space - Vector local = tmp.VMul3x3Transpose( offset ); - - /* - NDebugOverlay::Box( GetLocalOrigin(), m_controlMins, m_controlMaxs, - 255, 0, 0, 100, 5.0 ); - - NDebugOverlay::Box( GetLocalOrigin() + local, Vector(-5,-5,-5), Vector(5,5,5), - 0, 0, 255, 100, 5.0 ); - */ - - if ( local.x >= m_controlMins.x && local.y >= m_controlMins.y && local.z >= m_controlMins.z && - local.x <= m_controlMaxs.x && local.y <= m_controlMaxs.y && local.z <= m_controlMaxs.z ) - return true; - - return false; -} - - -void CFuncTrackTrain::Find( void ) -{ - m_ppath = (CPathTrack *)gEntList.FindEntityByName( NULL, m_target ); - if ( !m_ppath ) - return; - - if ( !FClassnameIs( m_ppath, "path_track" ) -#ifndef PORTAL //env_portal_path_track is a child of path_track and would like to get found - && !FClassnameIs( m_ppath, "env_portal_path_track" ) -#endif //#ifndef PORTAL - ) - { - Warning( "func_track_train must be on a path of path_track\n" ); - Assert(0); - m_ppath = NULL; - return; - } - - - - Vector nextPos = m_ppath->GetLocalOrigin(); - Vector look = nextPos; - m_ppath->LookAhead( look, m_length, 0 ); - nextPos.z += m_height; - look.z += m_height; - - QAngle nextAngles; - if ( HasSpawnFlags( SF_TRACKTRAIN_FIXED_ORIENTATION ) ) - { - nextAngles = GetLocalAngles(); - } - else - { - VectorAngles( look - nextPos, nextAngles ); - if ( HasSpawnFlags( SF_TRACKTRAIN_NOPITCH ) ) - { - nextAngles.x = 0; - } - } - - Teleport( &nextPos, &nextAngles, NULL ); - - ArriveAtNode( m_ppath ); - - if ( m_flSpeed != 0 ) - { - SetNextThink( gpGlobals->curtime + 0.1f ); - SetThink( &CFuncTrackTrain::Next ); - SoundUpdate(); - } -} - - -void CFuncTrackTrain::NearestPath( void ) -{ - CBaseEntity *pTrack = NULL; - CBaseEntity *pNearest = NULL; - float dist, closest; - - closest = 1024; - - for ( CEntitySphereQuery sphere( GetAbsOrigin(), 1024 ); ( pTrack = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() ) - { - // filter out non-tracks - if ( !(pTrack->GetFlags() & (FL_CLIENT|FL_NPC)) && FClassnameIs( pTrack, "path_track" ) ) - { - dist = (GetAbsOrigin() - pTrack->GetAbsOrigin()).Length(); - if ( dist < closest ) - { - closest = dist; - pNearest = pTrack; - } - } - } - - if ( !pNearest ) - { - Msg( "Can't find a nearby track !!!\n" ); - SetThink(NULL); - return; - } - - DevMsg( 2, "TRAIN: %s, Nearest track is %s\n", GetDebugName(), pNearest->GetDebugName() ); - // If I'm closer to the next path_track on this path, then it's my real path - pTrack = ((CPathTrack *)pNearest)->GetNext(); - if ( pTrack ) - { - if ( (GetLocalOrigin() - pTrack->GetLocalOrigin()).Length() < (GetLocalOrigin() - pNearest->GetLocalOrigin()).Length() ) - pNearest = pTrack; - } - - m_ppath = (CPathTrack *)pNearest; - - if ( m_flSpeed != 0 ) - { - SetMoveDoneTime( 0.1 ); - SetMoveDone( &CFuncTrackTrain::Next ); - } -} - -void CFuncTrackTrain::OnRestore( void ) -{ - BaseClass::OnRestore(); - if ( !m_ppath -#ifdef HL1_DLL - && !m_bOnTrackChange -#endif - ) - { - NearestPath(); - SetThink( NULL ); - } -} - - -CFuncTrackTrain *CFuncTrackTrain::Instance( edict_t *pent ) -{ - CBaseEntity *pEntity = CBaseEntity::Instance( pent ); - if ( FClassnameIs( pEntity, "func_tracktrain" ) ) - return (CFuncTrackTrain *)pEntity; - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncTrackTrain::Spawn( void ) -{ - if ( m_maxSpeed == 0 ) - { - if ( m_flSpeed == 0 ) - { - m_maxSpeed = 100; - } - else - { - m_maxSpeed = m_flSpeed; - } - } - - if ( m_nMoveSoundMinPitch == 0 ) - { - m_nMoveSoundMinPitch = 60; - } - - if ( m_nMoveSoundMaxPitch == 0 ) - { - m_nMoveSoundMaxPitch = 200; - } - - SetLocalVelocity(vec3_origin); - SetLocalAngularVelocity( vec3_angle ); - - m_dir = 1; - - if ( !m_target ) - { - Msg("FuncTrackTrain '%s' has no target.\n", GetDebugName()); - } - - SetModel( STRING( GetModelName() ) ); - SetMoveType( MOVETYPE_PUSH ); - -#ifdef HL1_DLL - // BUGBUG: For now, just force this for testing. Remove if we want to tag all of the trains in the levels - SetSolid( SOLID_BSP ); -#else - SetSolid( HasSpawnFlags( SF_TRACKTRAIN_HL1TRAIN ) ? SOLID_BSP : SOLID_VPHYSICS ); - //SetSolid( SOLID_VPHYSICS ); -#endif - - if ( HasSpawnFlags( SF_TRACKTRAIN_UNBLOCKABLE_BY_PLAYER ) ) - { - AddFlag( FL_UNBLOCKABLE_BY_PLAYER ); - } - if ( m_spawnflags & SF_TRACKTRAIN_PASSABLE ) - { - AddSolidFlags( FSOLID_NOT_SOLID ); - } - - m_controlMins = CollisionProp()->OBBMins(); - m_controlMaxs = CollisionProp()->OBBMaxs(); - m_controlMaxs.z += 72; -// start trains on the next frame, to make sure their targets have had -// a chance to spawn/activate - SetThink( &CFuncTrackTrain::Find ); - SetNextThink( gpGlobals->curtime ); - Precache(); - - CreateVPhysics(); -} - - -bool CFuncTrackTrain::CreateVPhysics( void ) -{ - VPhysicsInitShadow( false, false ); - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Precaches the train sounds. -//----------------------------------------------------------------------------- -void CFuncTrackTrain::Precache( void ) -{ - if (m_flVolume == 0.0) - { - m_flVolume = 1.0; - } - - if ( m_iszSoundMove != NULL_STRING ) - { - PrecacheScriptSound( STRING( m_iszSoundMove ) ); - } - - if ( m_iszSoundMovePing != NULL_STRING ) - { - PrecacheScriptSound( STRING( m_iszSoundMovePing ) ); - } - - if ( m_iszSoundStart != NULL_STRING ) - { - PrecacheScriptSound( STRING( m_iszSoundStart ) ); - } - - if ( m_iszSoundStop != NULL_STRING ) - { - PrecacheScriptSound( STRING( m_iszSoundStop ) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncTrackTrain::UpdateOnRemove() -{ - SoundStop(); - BaseClass::UpdateOnRemove(); -} - -void CFuncTrackTrain::MoveDone() -{ - m_lastBlockPos.Init(); - m_lastBlockTick = -1; - BaseClass::MoveDone(); -} - - - -//----------------------------------------------------------------------------- -// Purpose: Defines the volume of space that the player must stand in to -// control the train -//----------------------------------------------------------------------------- -class CFuncTrainControls : public CBaseEntity -{ - DECLARE_CLASS( CFuncTrainControls, CBaseEntity ); -public: - void Spawn( void ); - void Find( void ); - - DECLARE_DATADESC(); -}; - -BEGIN_DATADESC( CFuncTrainControls ) - - // Function Pointers - DEFINE_FUNCTION( Find ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( func_traincontrols, CFuncTrainControls ); - - -void CFuncTrainControls::Find( void ) -{ - CBaseEntity *pTarget = NULL; - - do - { - pTarget = gEntList.FindEntityByName( pTarget, m_target ); - } while ( pTarget && !FClassnameIs(pTarget, "func_tracktrain") ); - - if ( !pTarget ) - { - Msg( "No train %s\n", STRING(m_target) ); - return; - } - - CFuncTrackTrain *ptrain = (CFuncTrackTrain*) pTarget; - ptrain->SetControls( this ); - - SetThink( NULL ); -} - - -void CFuncTrainControls::Spawn( void ) -{ - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NONE ); - SetModel( STRING( GetModelName() ) ); - AddEffects( EF_NODRAW ); - - Assert( GetParent() && "func_traincontrols needs parent to properly align to train" ); - - SetThink( &CFuncTrainControls::Find ); - SetNextThink( gpGlobals->curtime ); -} - - -#define SF_TRACK_ACTIVATETRAIN 0x00000001 -#define SF_TRACK_RELINK 0x00000002 -#define SF_TRACK_ROTMOVE 0x00000004 -#define SF_TRACK_STARTBOTTOM 0x00000008 -#define SF_TRACK_DONT_MOVE 0x00000010 - - -typedef enum { TRAIN_SAFE, TRAIN_BLOCKING, TRAIN_FOLLOWING } TRAIN_CODE; - - -//----------------------------------------------------------------------------- -// This entity is a rotating/moving platform that will carry a train to a new track. -// It must be larger in X-Y planar area than the train, since it must contain the -// train within these dimensions in order to operate when the train is near it. -//----------------------------------------------------------------------------- -class CFuncTrackChange : public CFuncPlatRot -{ - DECLARE_CLASS( CFuncTrackChange, CFuncPlatRot ); -public: - void Spawn( void ); - void Precache( void ); - -// virtual void Blocked( void ); - virtual void GoUp( void ); - virtual void GoDown( void ); - - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - void Find( void ); - TRAIN_CODE EvaluateTrain( CPathTrack *pcurrent ); - void UpdateTrain( QAngle &dest ); - virtual void HitBottom( void ); - virtual void HitTop( void ); - void Touch( CBaseEntity *pOther ); - virtual void UpdateAutoTargets( int toggleState ); - virtual bool IsTogglePlat( void ) { return true; } - - void DisableUse( void ) { m_use = 0; } - void EnableUse( void ) { m_use = 1; } - int UseEnabled( void ) { return m_use; } - - DECLARE_DATADESC(); - - CPathTrack *m_trackTop; - CPathTrack *m_trackBottom; - - CFuncTrackTrain *m_train; - - string_t m_trackTopName; - string_t m_trackBottomName; - string_t m_trainName; - TRAIN_CODE m_code; - int m_targetState; - int m_use; -}; - -LINK_ENTITY_TO_CLASS( func_trackchange, CFuncTrackChange ); - -BEGIN_DATADESC( CFuncTrackChange ) - - DEFINE_GLOBAL_FIELD( m_trackTop, FIELD_CLASSPTR ), - DEFINE_GLOBAL_FIELD( m_trackBottom, FIELD_CLASSPTR ), - DEFINE_GLOBAL_FIELD( m_train, FIELD_CLASSPTR ), - DEFINE_GLOBAL_KEYFIELD( m_trackTopName, FIELD_STRING, "toptrack" ), - DEFINE_GLOBAL_KEYFIELD( m_trackBottomName, FIELD_STRING, "bottomtrack" ), - DEFINE_GLOBAL_KEYFIELD( m_trainName, FIELD_STRING, "train" ), - DEFINE_FIELD( m_code, FIELD_INTEGER ), - DEFINE_FIELD( m_targetState, FIELD_INTEGER ), - DEFINE_FIELD( m_use, FIELD_INTEGER ), - - // Function Pointers - DEFINE_FUNCTION( Find ), - -END_DATADESC() - - -void CFuncTrackChange::Spawn( void ) -{ - Setup(); - if ( FBitSet( m_spawnflags, SF_TRACK_DONT_MOVE ) ) - m_vecPosition2.z = GetLocalOrigin().z; - - SetupRotation(); - - if ( FBitSet( m_spawnflags, SF_TRACK_STARTBOTTOM ) ) - { - UTIL_SetOrigin( this, m_vecPosition2); - m_toggle_state = TS_AT_BOTTOM; - SetLocalAngles( m_start ); - m_targetState = TS_AT_TOP; - } - else - { - UTIL_SetOrigin( this, m_vecPosition1); - m_toggle_state = TS_AT_TOP; - SetLocalAngles( m_end ); - m_targetState = TS_AT_BOTTOM; - } - - EnableUse(); - SetThink( &CFuncTrackChange::Find ); - SetNextThink( gpGlobals->curtime + 2 ); - Precache(); -} - - -void CFuncTrackChange::Precache( void ) -{ - BaseClass::Precache(); - - PrecacheScriptSound( "FuncTrackChange.Blocking" ); -} - - -// UNDONE: Filter touches before re-evaluating the train. -void CFuncTrackChange::Touch( CBaseEntity *pOther ) -{ -} - - -void CFuncTrackChange::Find( void ) -{ - // Find track entities - CBaseEntity *target; - - target = gEntList.FindEntityByName( NULL, m_trackTopName ); - if ( target ) - { - m_trackTop = (CPathTrack*) target; - target = gEntList.FindEntityByName( NULL, m_trackBottomName ); - if ( target ) - { - m_trackBottom = (CPathTrack*) target; - target = gEntList.FindEntityByName( NULL, m_trainName ); - if ( target ) - { - m_train = (CFuncTrackTrain *)gEntList.FindEntityByName( NULL, m_trainName ); - if ( !m_train ) - { - Warning( "Can't find train for track change! %s\n", STRING(m_trainName) ); - Assert(0); - return; - } - Vector center = WorldSpaceCenter(); - m_trackBottom = m_trackBottom->Nearest( center ); - m_trackTop = m_trackTop->Nearest( center ); - UpdateAutoTargets( m_toggle_state ); - SetThink( NULL ); - return; - } - else - { - Warning( "Can't find train for track change! %s\n", STRING(m_trainName) ); - Assert(0); - target = gEntList.FindEntityByName( NULL, m_trainName ); - } - } - else - { - Warning( "Can't find bottom track for track change! %s\n", STRING(m_trackBottomName) ); - Assert(0); - } - } - else - { - Warning( "Can't find top track for track change! %s\n", STRING(m_trackTopName) ); - Assert(0); - } -} - - -TRAIN_CODE CFuncTrackChange::EvaluateTrain( CPathTrack *pcurrent ) -{ - // Go ahead and work, we don't have anything to switch, so just be an elevator - if ( !pcurrent || !m_train ) - return TRAIN_SAFE; - - if ( m_train->m_ppath == pcurrent || (pcurrent->m_pprevious && m_train->m_ppath == pcurrent->m_pprevious) || - (pcurrent->m_pnext && m_train->m_ppath == pcurrent->m_pnext) ) - { - if ( m_train->m_flSpeed != 0 ) - return TRAIN_BLOCKING; - - Vector dist = GetLocalOrigin() - m_train->GetLocalOrigin(); - float length = dist.Length2D(); - if ( length < m_train->m_length ) // Empirically determined close distance - return TRAIN_FOLLOWING; - else if ( length > (150 + m_train->m_length) ) - return TRAIN_SAFE; - - return TRAIN_BLOCKING; - } - - return TRAIN_SAFE; -} - - -void CFuncTrackChange::UpdateTrain( QAngle &dest ) -{ - float time = GetMoveDoneTime(); - - m_train->SetAbsVelocity( GetAbsVelocity() ); - m_train->SetLocalAngularVelocity( GetLocalAngularVelocity() ); - m_train->SetMoveDoneTime( time ); - - // Attempt at getting the train to rotate properly around the origin of the trackchange - if ( time <= 0 ) - return; - - Vector offset = m_train->GetLocalOrigin() - GetLocalOrigin(); - QAngle delta = dest - GetLocalAngles(); - // Transform offset into local coordinates - Vector forward, right, up; - AngleVectorsTranspose( delta, &forward, &right, &up ); - Vector local; - local.x = DotProduct( offset, forward ); - local.y = DotProduct( offset, right ); - local.z = DotProduct( offset, up ); - - local = local - offset; - m_train->SetAbsVelocity( GetAbsVelocity() + (local * (1.0/time)) ); -} - - -void CFuncTrackChange::GoDown( void ) -{ - if ( m_code == TRAIN_BLOCKING ) - return; - - // HitBottom may get called during CFuncPlat::GoDown(), so set up for that - // before you call GoDown() - - UpdateAutoTargets( TS_GOING_DOWN ); - // If ROTMOVE, move & rotate - if ( FBitSet( m_spawnflags, SF_TRACK_DONT_MOVE ) ) - { - SetMoveDone( &CFuncTrackChange::CallHitBottom ); - m_toggle_state = TS_GOING_DOWN; - AngularMove( m_start, m_flSpeed ); - } - else - { - BaseClass::GoDown(); - SetMoveDone( &CFuncTrackChange::CallHitBottom ); - RotMove( m_start, GetMoveDoneTime() ); - } - // Otherwise, rotate first, move second - - // If the train is moving with the platform, update it - if ( m_code == TRAIN_FOLLOWING ) - { - UpdateTrain( m_start ); - m_train->m_ppath = NULL; -#ifdef HL1_DLL - m_train->m_bOnTrackChange = true; -#endif - } -} - - -// -// Platform is at bottom, now starts moving up -// -void CFuncTrackChange::GoUp( void ) -{ - if ( m_code == TRAIN_BLOCKING ) - return; - - // HitTop may get called during CFuncPlat::GoUp(), so set up for that - // before you call GoUp(); - - UpdateAutoTargets( TS_GOING_UP ); - if ( FBitSet( m_spawnflags, SF_TRACK_DONT_MOVE ) ) - { - m_toggle_state = TS_GOING_UP; - SetMoveDone( &CFuncTrackChange::CallHitTop ); - AngularMove( m_end, m_flSpeed ); - } - else - { - // If ROTMOVE, move & rotate - BaseClass::GoUp(); - SetMoveDone( &CFuncTrackChange::CallHitTop ); - RotMove( m_end, GetMoveDoneTime() ); - } - - // Otherwise, move first, rotate second - - // If the train is moving with the platform, update it - if ( m_code == TRAIN_FOLLOWING ) - { - UpdateTrain( m_end ); - m_train->m_ppath = NULL; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Normal track change -// Input : toggleState - -//----------------------------------------------------------------------------- -void CFuncTrackChange::UpdateAutoTargets( int toggleState ) -{ - if ( !m_trackTop || !m_trackBottom ) - return; - - if ( toggleState == TS_AT_TOP ) - { - m_trackTop->RemoveSpawnFlags( SF_PATH_DISABLED ); - } - else - { - m_trackTop->AddSpawnFlags( SF_PATH_DISABLED ); - } - - if ( toggleState == TS_AT_BOTTOM ) - { - m_trackBottom->RemoveSpawnFlags( SF_PATH_DISABLED ); - } - else - { - m_trackBottom->AddSpawnFlags( SF_PATH_DISABLED ); - } -} - - -void CFuncTrackChange::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - if ( m_toggle_state != TS_AT_TOP && m_toggle_state != TS_AT_BOTTOM ) - return; - - // If train is in "safe" area, but not on the elevator, play alarm sound - if ( m_toggle_state == TS_AT_TOP ) - m_code = EvaluateTrain( m_trackTop ); - else if ( m_toggle_state == TS_AT_BOTTOM ) - m_code = EvaluateTrain( m_trackBottom ); - else - m_code = TRAIN_BLOCKING; - if ( m_code == TRAIN_BLOCKING ) - { - // Play alarm and return - EmitSound( "FuncTrackChange.Blocking" ); - return; - } - - // Otherwise, it's safe to move - // If at top, go down - // at bottom, go up - - DisableUse(); - if (m_toggle_state == TS_AT_TOP) - GoDown(); - else - GoUp(); -} - - -// -// Platform has hit bottom. Stops and waits forever. -// -void CFuncTrackChange::HitBottom( void ) -{ - BaseClass::HitBottom(); - if ( m_code == TRAIN_FOLLOWING ) - { -// UpdateTrain(); - m_train->SetTrack( m_trackBottom ); - } - SetMoveDone( NULL ); - SetMoveDoneTime( -1 ); - - UpdateAutoTargets( m_toggle_state ); - - EnableUse(); -} - - -// -// Platform has hit bottom. Stops and waits forever. -// -void CFuncTrackChange::HitTop( void ) -{ - BaseClass::HitTop(); - if ( m_code == TRAIN_FOLLOWING ) - { -// UpdateTrain(); - m_train->SetTrack( m_trackTop ); - } - - // Don't let the plat go back down - SetMoveDone( NULL ); - SetMoveDoneTime( -1 ); - UpdateAutoTargets( m_toggle_state ); - EnableUse(); -} - - -class CFuncTrackAuto : public CFuncTrackChange -{ - DECLARE_CLASS( CFuncTrackAuto, CFuncTrackChange ); -public: - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - virtual void UpdateAutoTargets( int toggleState ); - void TriggerTrackChange( inputdata_t &inputdata ); - - DECLARE_DATADESC(); -}; - -BEGIN_DATADESC( CFuncTrackAuto ) - DEFINE_INPUTFUNC( FIELD_VOID, "Trigger", TriggerTrackChange ), -END_DATADESC() - -LINK_ENTITY_TO_CLASS( func_trackautochange, CFuncTrackAuto ); - - -// Auto track change -void CFuncTrackAuto::UpdateAutoTargets( int toggleState ) -{ - CPathTrack *pTarget, *pNextTarget; - - if ( !m_trackTop || !m_trackBottom ) - return; - - if ( m_targetState == TS_AT_TOP ) - { - pTarget = m_trackTop->GetNext(); - pNextTarget = m_trackBottom->GetNext(); - } - else - { - pTarget = m_trackBottom->GetNext(); - pNextTarget = m_trackTop->GetNext(); - } - if ( pTarget ) - { - pTarget->RemoveSpawnFlags( SF_PATH_DISABLED ); - if ( m_code == TRAIN_FOLLOWING && m_train && m_train->m_flSpeed == 0 ) - { - m_train->SetSpeed( pTarget->m_flSpeed ); - m_train->Use( this, this, USE_SET, 0 ); - } - } - - if ( pNextTarget ) - { - pNextTarget->AddSpawnFlags( SF_PATH_DISABLED ); - } -} - - -void CFuncTrackAuto::TriggerTrackChange ( inputdata_t &inputdata ) -{ - CPathTrack *pTarget; - - if ( !UseEnabled() ) - return; - - if ( m_toggle_state == TS_AT_TOP ) - pTarget = m_trackTop; - else if ( m_toggle_state == TS_AT_BOTTOM ) - pTarget = m_trackBottom; - else - pTarget = NULL; - - if ( inputdata.pActivator && FClassnameIs( inputdata.pActivator, "func_tracktrain" ) ) - { - m_code = EvaluateTrain( pTarget ); - // Safe to fire? - if ( m_code == TRAIN_FOLLOWING && m_toggle_state != m_targetState ) - { - DisableUse(); - if (m_toggle_state == TS_AT_TOP) - GoDown(); - else - GoUp(); - } - } - else - { - if ( pTarget ) - pTarget = pTarget->GetNext(); - if ( pTarget && m_train->m_ppath != pTarget && ShouldToggle( USE_TOGGLE, m_targetState ) ) - { - if ( m_targetState == TS_AT_TOP ) - m_targetState = TS_AT_BOTTOM; - else - m_targetState = TS_AT_TOP; - } - - UpdateAutoTargets( m_targetState ); - } -} - - -void CFuncTrackAuto::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - CPathTrack *pTarget; - - if ( !UseEnabled() ) - return; - - if ( m_toggle_state == TS_AT_TOP ) - pTarget = m_trackTop; - else if ( m_toggle_state == TS_AT_BOTTOM ) - pTarget = m_trackBottom; - else - pTarget = NULL; - - if ( FClassnameIs( pActivator, "func_tracktrain" ) ) - { - m_code = EvaluateTrain( pTarget ); - // Safe to fire? - if ( m_code == TRAIN_FOLLOWING && m_toggle_state != m_targetState ) - { - DisableUse(); - if (m_toggle_state == TS_AT_TOP) - GoDown(); - else - GoUp(); - } - } - else - { - if ( pTarget ) - pTarget = pTarget->GetNext(); - if ( pTarget && m_train->m_ppath != pTarget && ShouldToggle( useType, m_targetState ) ) - { - if ( m_targetState == TS_AT_TOP ) - m_targetState = TS_AT_BOTTOM; - else - m_targetState = TS_AT_TOP; - } - - UpdateAutoTargets( m_targetState ); - } -} diff --git a/game/server/trains.h b/game/server/trains.h deleted file mode 100644 index 78e681054..000000000 --- a/game/server/trains.h +++ /dev/null @@ -1,196 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef TRAINS_H -#define TRAINS_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "entityoutput.h" -#include "pathtrack.h" - - -// Spawnflags of CPathCorner -#define SF_CORNER_WAITFORTRIG 0x001 -#define SF_CORNER_TELEPORT 0x002 - -// Tracktrain spawn flags -#define SF_TRACKTRAIN_NOPITCH 0x0001 -#define SF_TRACKTRAIN_NOCONTROL 0x0002 -#define SF_TRACKTRAIN_FORWARDONLY 0x0004 -#define SF_TRACKTRAIN_PASSABLE 0x0008 -#define SF_TRACKTRAIN_FIXED_ORIENTATION 0x0010 -#define SF_TRACKTRAIN_HL1TRAIN 0x0080 -#define SF_TRACKTRAIN_USE_MAXSPEED_FOR_PITCH 0x0100 -#define SF_TRACKTRAIN_UNBLOCKABLE_BY_PLAYER 0x0200 - -#define TRAIN_ACTIVE 0x80 -#define TRAIN_NEW 0xc0 -#define TRAIN_OFF 0x00 -#define TRAIN_NEUTRAL 0x01 -#define TRAIN_SLOW 0x02 -#define TRAIN_MEDIUM 0x03 -#define TRAIN_FAST 0x04 -#define TRAIN_BACK 0x05 - - -enum TrainVelocityType_t -{ - TrainVelocity_Instantaneous = 0, - TrainVelocity_LinearBlend, - TrainVelocity_EaseInEaseOut, -}; - - -enum TrainOrientationType_t -{ - TrainOrientation_Fixed = 0, - TrainOrientation_AtPathTracks, - TrainOrientation_LinearBlend, - TrainOrientation_EaseInEaseOut, -}; - -class CFuncTrackTrain : public CBaseEntity -{ - DECLARE_CLASS( CFuncTrackTrain, CBaseEntity ); - DECLARE_SERVERCLASS(); - -public: - CFuncTrackTrain(); - - void Spawn( void ); - bool CreateVPhysics( void ); - void Precache( void ); - void UpdateOnRemove(); - void MoveDone(); - - void Blocked( CBaseEntity *pOther ); - bool KeyValue( const char *szKeyName, const char *szValue ); - - virtual int DrawDebugTextOverlays(); - void DrawDebugGeometryOverlays(); - - void Next( void ); - void Find( void ); - void NearestPath( void ); - void DeadEnd( void ); - - void SetTrack( CPathTrack *track ) { m_ppath = track->Nearest(GetLocalOrigin()); } - void SetControls( CBaseEntity *pControls ); - bool OnControls( CBaseEntity *pControls ); - - void SoundStop( void ); - void SoundUpdate( void ); - - void Start( void ); - void Stop( void ); - - bool IsDirForward(); - void SetDirForward( bool bForward ); - void SetSpeed( float flSpeed, bool bAccel = false ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - // Input handlers - void InputSetSpeed( inputdata_t &inputdata ); - void InputSetSpeedDir( inputdata_t &inputdata ); - void InputSetSpeedReal( inputdata_t &inputdata ); - void InputStop( inputdata_t &inputdata ); - void InputResume( inputdata_t &inputdata ); - void InputReverse( inputdata_t &inputdata ); - void InputStartForward( inputdata_t &inputdata ); - void InputStartBackward( inputdata_t &inputdata ); - void InputToggle( inputdata_t &inputdata ); - void InputSetSpeedDirAccel( inputdata_t &inputdata ); - - static CFuncTrackTrain *Instance( edict_t *pent ); - - DECLARE_DATADESC(); - - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() | FCAP_DIRECTIONAL_USE | FCAP_USE_ONGROUND; } - - virtual void OnRestore( void ); - - float GetMaxSpeed() const { return m_maxSpeed; } - float GetCurrentSpeed() const { return m_flSpeed; } - float GetDesiredSpeed() const { return m_flDesiredSpeed;} - - virtual bool IsBaseTrain( void ) const { return true; } - -private: - - void ArriveAtNode( CPathTrack *pNode ); - void FirePassInputs( CPathTrack *pStart, CPathTrack *pEnd, bool forward ); - -public: - - // UNDONE: Add accessors? - CPathTrack *m_ppath; - float m_length; - -#ifdef HL1_DLL - bool m_bOnTrackChange; // we don't want to find a new node if we restore while - // riding on a func_trackchange -#endif - -private: - - TrainVelocityType_t GetTrainVelocityType(); - void UpdateTrainVelocity( CPathTrack *pnext, CPathTrack *pNextNext, const Vector &nextPos, float flInterval ); - - TrainOrientationType_t GetTrainOrientationType(); - void UpdateTrainOrientation( CPathTrack *pnext, CPathTrack *pNextNext, const Vector &nextPos, float flInterval ); - void UpdateOrientationAtPathTracks( CPathTrack *pnext, CPathTrack *pNextNext, const Vector &nextPos, float flInterval ); - void UpdateOrientationBlend( TrainOrientationType_t eOrientationType, CPathTrack *pPrev, CPathTrack *pNext, const Vector &nextPos, float flInterval ); - void DoUpdateOrientation( const QAngle &curAngles, const QAngle &angles, float flInterval ); - - void TeleportToPathTrack( CPathTrack *pTeleport ); - - - Vector m_controlMins; - Vector m_controlMaxs; - Vector m_lastBlockPos; // These are used to build a heuristic decision about being temporarily blocked by physics objects - int m_lastBlockTick; // ^^^^^^^ - float m_flVolume; - float m_flBank; - float m_oldSpeed; - float m_flBlockDamage; // Damage to inflict when blocked. - float m_height; - float m_maxSpeed; - float m_dir; - - - string_t m_iszSoundMove; // Looping sound to play while moving. Pitch shifted based on speed. - string_t m_iszSoundMovePing; // Ping sound to play while moving. Interval decreased based on speed. - string_t m_iszSoundStart; // Sound to play when starting to move. - string_t m_iszSoundStop; // Sound to play when stopping. - - float m_flMoveSoundMinTime; // The most often to play the move 'ping' sound (used at max speed) - float m_flMoveSoundMaxTime; // The least often to play the move 'ping' sound (used approaching zero speed) - float m_flNextMoveSoundTime; - - int m_nMoveSoundMinPitch; // The sound pitch to approach as we come to a stop - int m_nMoveSoundMaxPitch; // The sound pitch to approach as we approach our max speed (actually, it's hardcoded to 1000 in/sec) - - TrainOrientationType_t m_eOrientationType; - TrainVelocityType_t m_eVelocityType; - bool m_bSoundPlaying; - - COutputEvent m_OnStart,m_OnNext; - - bool m_bManualSpeedChanges; // set when we want to send entity IO to govern speed and obey our TrainVelocityType_t - float m_flDesiredSpeed; // target speed, when m_bManualSpeedChanges is set - float m_flSpeedChangeTime; - float m_flAccelSpeed; - float m_flDecelSpeed; - bool m_bAccelToSpeed; - - float m_flNextMPSoundTime; -}; - - -#endif // TRAINS_H diff --git a/game/server/trigger_area_capture.cpp b/game/server/trigger_area_capture.cpp deleted file mode 100644 index 324c9d1d8..000000000 --- a/game/server/trigger_area_capture.cpp +++ /dev/null @@ -1,1146 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#include "cbase.h" -#include "trigger_area_capture.h" -#include "player.h" -#include "teamplay_gamerules.h" -#include "team.h" -#include "team_objectiveresource.h" -#include "team_control_point_master.h" -#include "teamplayroundbased_gamerules.h" - -extern ConVar mp_capstyle; -extern ConVar mp_blockstyle; -extern ConVar mp_capdeteriorate_time; - -BEGIN_DATADESC(CTriggerAreaCapture) - - // Touch functions - DEFINE_FUNCTION( AreaTouch ), - - // Think functions - DEFINE_THINKFUNC( CaptureThink ), - - // Keyfields - DEFINE_KEYFIELD( m_iszCapPointName, FIELD_STRING, "area_cap_point" ), - DEFINE_KEYFIELD( m_flCapTime, FIELD_FLOAT, "area_time_to_cap" ), - -// DEFINE_FIELD( m_iCapMode, FIELD_INTEGER ), -// DEFINE_FIELD( m_bCapturing, FIELD_BOOLEAN ), -// DEFINE_FIELD( m_nCapturingTeam, FIELD_INTEGER ), -// DEFINE_FIELD( m_nOwningTeam, FIELD_INTEGER ), -// DEFINE_FIELD( m_nTeamInZone, FIELD_INTEGER ), -// DEFINE_FIELD( m_fTimeRemaining, FIELD_FLOAT ), -// DEFINE_FIELD( m_flLastReductionTime, FIELD_FLOAT ), -// DEFINE_FIELD( m_bBlocked, FIELD_BOOLEAN ), -// DEFINE_FIELD( m_TeamData, CUtlVector < perteamdata_t > ), -// DEFINE_FIELD( m_Blockers, CUtlVector < blockers_t > ), -// DEFINE_FIELD( m_bActive, FIELD_BOOLEAN ), -// DEFINE_FIELD( m_iAreaIndex, FIELD_INTEGER ), -// DEFINE_FIELD( m_hPoint, CHandle < CTeamControlPoint > ), -// DEFINE_FIELD( m_bRequiresObject, FIELD_BOOLEAN ), -// DEFINE_FIELD( m_iCapAttemptNumber, FIELD_INTEGER ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "RoundSpawn", InputRoundSpawn ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetTeamCanCap", InputSetTeamCanCap ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetControlPoint", InputSetControlPoint ), - DEFINE_INPUTFUNC( FIELD_VOID, "CaptureCurrentCP", InputCaptureCurrentCP ), - - // Outputs - DEFINE_OUTPUT( m_OnStartTeam1, "OnStartTeam1" ), - DEFINE_OUTPUT( m_OnStartTeam2, "OnStartTeam2" ), - DEFINE_OUTPUT( m_OnBreakTeam1, "OnBreakTeam1" ), - DEFINE_OUTPUT( m_OnBreakTeam2, "OnBreakTeam2" ), - DEFINE_OUTPUT( m_OnCapTeam1, "OnCapTeam1" ), - DEFINE_OUTPUT( m_OnCapTeam2, "OnCapTeam2" ), - - DEFINE_OUTPUT( m_StartOutput, "OnStartCap" ), - DEFINE_OUTPUT( m_BreakOutput, "OnBreakCap" ), - DEFINE_OUTPUT( m_CapOutput, "OnEndCap" ), - - DEFINE_OUTPUT( m_OnNumCappersChanged, "OnNumCappersChanged" ), - -END_DATADESC(); - -LINK_ENTITY_TO_CLASS( trigger_capture_area, CTriggerAreaCapture ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTriggerAreaCapture::CTriggerAreaCapture() -{ - m_TeamData.SetSize( GetNumberOfTeams() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerAreaCapture::Spawn( void ) -{ - BaseClass::Spawn(); - - AddSpawnFlags( SF_TRIGGER_ALLOW_CLIENTS ); - - InitTrigger(); - - Precache(); - - m_iAreaIndex = -1; - - SetTouch ( &CTriggerAreaCapture::AreaTouch ); - SetThink( &CTriggerAreaCapture::CaptureThink ); - SetNextThink( gpGlobals->curtime + AREA_THINK_TIME ); - - for ( int i = 0; i < m_TeamData.Count(); i++ ) - { - if ( m_TeamData[i].iNumRequiredToCap < 1 ) - { - m_TeamData[i].iNumRequiredToCap = 1; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTriggerAreaCapture::KeyValue( const char *szKeyName, const char *szValue ) -{ - if ( !Q_strncmp( szKeyName, "team_numcap_", 12 ) ) - { - int iTeam = atoi(szKeyName+12); - Assert( iTeam >= 0 && iTeam < m_TeamData.Count() ); - - m_TeamData[iTeam].iNumRequiredToCap = atoi(szValue); - } - else if ( !Q_strncmp( szKeyName, "team_cancap_", 12 ) ) - { - int iTeam = atoi(szKeyName+12); - Assert( iTeam >= 0 && iTeam < m_TeamData.Count() ); - - m_TeamData[iTeam].bCanCap = (atoi(szValue) != 0); - } - else if ( !Q_strncmp( szKeyName, "team_spawn_", 11 ) ) - { - int iTeam = atoi(szKeyName+11); - Assert( iTeam >= 0 && iTeam < m_TeamData.Count() ); - - m_TeamData[iTeam].iSpawnAdjust = atoi(szValue); - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerAreaCapture::Precache( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerAreaCapture::SetAreaIndex( int index ) -{ - m_iAreaIndex = index; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTriggerAreaCapture::IsActive( void ) -{ - return !m_bDisabled; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerAreaCapture::StartTouch(CBaseEntity *pOther) -{ - BaseClass::StartTouch( pOther ); - - if ( PassesTriggerFilters(pOther) && m_hPoint ) - { - IGameEvent *event = gameeventmanager->CreateEvent( "controlpoint_starttouch" ); - if ( event ) - { - event->SetInt( "player", pOther->entindex() ); - event->SetInt( "area", m_hPoint->GetPointIndex() ); - gameeventmanager->FireEvent( event ); - } - - // Call capture think immediately to make it update our area's player counts. - // If we don't do this, the player can receive the above event telling him he's - // in a zone, but the objective resource still thinks he's not. - CaptureThink(); - - if ( m_bCapturing ) - { - CTeamControlPointMaster *pMaster = g_hControlPointMasters.Count() ? g_hControlPointMasters[0] : NULL; - if ( pMaster ) - { - float flRate = pMaster->GetPartialCapturePointRate(); - - if ( flRate > 0.0f ) - { - CBaseMultiplayerPlayer *pPlayer = ToBaseMultiplayerPlayer(pOther); - if ( pPlayer ) - { - pPlayer->StartScoringEscortPoints( flRate ); - } - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerAreaCapture::EndTouch(CBaseEntity *pOther) -{ - if ( PassesTriggerFilters(pOther) && m_hPoint ) - { - IGameEvent *event = gameeventmanager->CreateEvent( "controlpoint_endtouch" ); - if ( event ) - { - event->SetInt( "player", pOther->entindex() ); - event->SetInt( "area", m_hPoint->GetPointIndex() ); - gameeventmanager->FireEvent( event ); - } - - // incase we leave but the area keeps capturing - CBaseMultiplayerPlayer *pPlayer = ToBaseMultiplayerPlayer(pOther); - if ( pPlayer ) - { - pPlayer->StopScoringEscortPoints(); - } - } - - BaseClass::EndTouch( pOther ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerAreaCapture::AreaTouch( CBaseEntity *pOther ) -{ - if ( !IsActive() ) - return; - if ( !PassesTriggerFilters(pOther) ) - return; - - // Don't cap areas unless the round is running - if ( !TeamplayGameRules()->PointsMayBeCaptured() ) - return; - - Assert( m_iAreaIndex != -1 ); - - // dont touch for non-alive or non-players - if( !pOther->IsPlayer() || !pOther->IsAlive() ) - return; - - // make sure this point is in the round being played (if we're playing one) - CTeamControlPointMaster *pMaster = g_hControlPointMasters.Count() ? g_hControlPointMasters[0] : NULL; - if ( pMaster && m_hPoint ) - { - if ( !pMaster->PointCanBeCapped( m_hPoint ) ) - { - return; - } - } - - if ( m_hPoint ) - { - m_nOwningTeam = m_hPoint->GetOwner(); - } - - CBaseMultiplayerPlayer *pPlayer = ToBaseMultiplayerPlayer(pOther); - Assert( pPlayer ); - - if ( pPlayer->GetTeamNumber() != m_nOwningTeam ) - { - if ( m_TeamData[ pPlayer->GetTeamNumber() ].bCanCap ) - { - DisplayCapHintTo( pPlayer ); - } - } -} - -ConVar mp_simulatemultiplecappers( "mp_simulatemultiplecappers", "1", FCVAR_CHEAT ); - -#define MAX_CAPTURE_TEAMS 8 - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerAreaCapture::CaptureThink( void ) -{ - SetNextThink( gpGlobals->curtime + AREA_THINK_TIME ); - - // make sure this point is in the round being played (if we're playing one) - CTeamControlPointMaster *pMaster = g_hControlPointMasters.Count() ? g_hControlPointMasters[0] : NULL; - if ( pMaster && m_hPoint ) - { - if ( !pMaster->PointCanBeCapped( m_hPoint ) ) - { - return; - } - } - - if ( !TeamplayGameRules()->PointsMayBeCaptured() ) - { - // Points aren't allowed to be captured. If we were - // being captured, we need to clean up and reset. - if ( m_bCapturing ) - { - BreakCapture( false ); - UpdateNumPlayers(); - } - return; - } - - // go through our list of players - Assert( GetNumberOfTeams() <= MAX_CAPTURE_TEAMS ); - int iNumPlayers[MAX_CAPTURE_TEAMS]; - int iNumBlockablePlayers[MAX_CAPTURE_TEAMS]; // Players in the zone who can't cap, but can block / pause caps - CBaseMultiplayerPlayer *pFirstPlayerTouching[MAX_CAPTURE_TEAMS]; - for ( int i = FIRST_GAME_TEAM; i < GetNumberOfTeams(); i++ ) - { - iNumPlayers[i] = 0; - iNumBlockablePlayers[i] = 0; - pFirstPlayerTouching[i] = NULL; - } - - // Loop through the entities we're touching, and find players - for ( int i = 0; i < m_hTouchingEntities.Count(); i++ ) - { - CBaseEntity *ent = m_hTouchingEntities[i]; - if ( ent && ent->IsPlayer() ) - { - CBaseMultiplayerPlayer *pPlayer = ToBaseMultiplayerPlayer(ent); - if ( pPlayer->IsAlive() ) - { - int iTeam = pPlayer->GetTeamNumber(); - - // If a team's not allowed to cap a point, don't count players in it at all - if ( !TeamplayGameRules()->TeamMayCapturePoint( iTeam, m_hPoint->GetPointIndex() ) ) - continue; - - if ( !TeamplayGameRules()->PlayerMayCapturePoint( pPlayer, m_hPoint->GetPointIndex() ) ) - { - if ( TeamplayGameRules()->PlayerMayBlockPoint( pPlayer, m_hPoint->GetPointIndex() ) ) - { - if ( iNumPlayers[iTeam] == 0 && iNumBlockablePlayers[iTeam] == 0 ) - { - pFirstPlayerTouching[iTeam] = pPlayer; - } - - iNumBlockablePlayers[iTeam] += TeamplayGameRules()->GetCaptureValueForPlayer( pPlayer ); - } - continue; - } - - if ( iTeam >= FIRST_GAME_TEAM ) - { - if ( iNumPlayers[iTeam] == 0 && iNumBlockablePlayers[iTeam] == 0 ) - { - pFirstPlayerTouching[iTeam] = pPlayer; - } - - iNumPlayers[iTeam] += TeamplayGameRules()->GetCaptureValueForPlayer( pPlayer ); - } - } - } - } - - int iTeamsInZone = 0; - bool bUpdatePlayers = false; - m_nTeamInZone = TEAM_UNASSIGNED; - for ( int i = FIRST_GAME_TEAM; i < GetNumberOfTeams(); i++ ) - { - iNumPlayers[i] *= mp_simulatemultiplecappers.GetInt(); - - if ( m_TeamData[i].iNumTouching != iNumPlayers[i] ) - { - m_TeamData[i].iNumTouching = iNumPlayers[i]; - bUpdatePlayers = true; - } - m_TeamData[i].iBlockedTouching = m_TeamData[i].iNumTouching; - - if ( m_TeamData[i].iNumTouching ) - { - iTeamsInZone++; - - m_nTeamInZone = i; - } - } - - if ( iTeamsInZone > 1 ) - { - m_nTeamInZone = TEAM_UNASSIGNED; - } - else - { - // If we've got non-cappable, yet blockable players here for the team that's defending, they - // need to block the cap. This catches cases like the TF invulnerability, which needs to block - // caps, but isn't allowed to contribute to a cap. - for ( int i = FIRST_GAME_TEAM; i < GetNumberOfTeams(); i++ ) - { - if ( !iNumBlockablePlayers[i] || m_nTeamInZone == i ) - continue; - - iTeamsInZone++; - } - } - - UpdateTeamInZone(); - - // If the cap is being blocked, reset the number of players so the client - // knows to stop the capture as well. - if ( mp_blockstyle.GetInt() == 1 ) - { - if ( m_bCapturing && iTeamsInZone > 1 ) - { - for ( int i = FIRST_GAME_TEAM; i < GetNumberOfTeams(); i++ ) - { - iNumPlayers[i] = 0; - if ( m_TeamData[i].iNumTouching != iNumPlayers[i] ) - { - m_TeamData[i].iNumTouching = iNumPlayers[i]; - bUpdatePlayers = true; - } - } - } - } - - if ( bUpdatePlayers ) - { - UpdateNumPlayers(); - } - - // When a player blocks, tell them the cap index and attempt number - // only give successive blocks to them if the attempt number is different - if ( m_bCapturing ) - { - if ( m_hPoint ) - { - m_hPoint->SetLastContestedAt( gpGlobals->curtime ); - } - - // Calculate the amount of modification to the cap time - float flTimeDelta = gpGlobals->curtime - m_flLastReductionTime; - float flReduction = flTimeDelta; - if ( mp_capstyle.GetInt() == 1 ) - { - // Diminishing returns for successive players. - for ( int i = 1; i < m_TeamData[m_nTeamInZone].iNumTouching; i++ ) - { - flReduction += (flTimeDelta / (float)(i+1)); - } - } - m_flLastReductionTime = gpGlobals->curtime; - - //if more than one team is in the zone - if( iTeamsInZone > 1 ) - { - if ( !m_bBlocked ) - { - m_bBlocked = true; - UpdateBlocked(); - } - - // See if anyone gets credit for the block - float flPercentToGo = m_fTimeRemaining / m_flCapTime; - if ( mp_capstyle.GetInt() == 1 ) - { - flPercentToGo = m_fTimeRemaining / ((m_flCapTime * 2) * m_TeamData[m_nCapturingTeam].iNumRequiredToCap); - } - - if ( flPercentToGo <= 0.5 && m_hPoint ) - { - // find the first player that is not on the capturing team - // they have just broken a cap and should be rewarded - // tell the player the capture attempt number, for checking later - CBaseMultiplayerPlayer *pBlockingPlayer = NULL; - for ( int i = FIRST_GAME_TEAM; i < GetNumberOfTeams(); i++ ) - { - if ( m_nCapturingTeam == i ) - continue; - - if ( pFirstPlayerTouching[i] ) - { - pBlockingPlayer = pFirstPlayerTouching[i]; - break; - } - } - Assert( pBlockingPlayer ); - - if ( pBlockingPlayer ) - { - bool bRepeatBlocker = false; - for ( int i = m_Blockers.Count()-1; i >= 0; i-- ) - { - if ( m_Blockers[i].hPlayer != pBlockingPlayer ) - continue; - - // If this guy's was a blocker, but not valid now, remove him from the list - if ( m_Blockers[i].iCapAttemptNumber != m_iCapAttemptNumber || !IsTouching(m_Blockers[i].hPlayer) ) - { - m_Blockers.Remove(i); - continue; - } - - bRepeatBlocker = true; - break; - } - - if ( !bRepeatBlocker ) - { - m_hPoint->CaptureBlocked( pBlockingPlayer ); - - // Add this guy to our blocker list - int iNew = m_Blockers.AddToTail(); - m_Blockers[iNew].hPlayer = pBlockingPlayer; - m_Blockers[iNew].iCapAttemptNumber = m_iCapAttemptNumber; - } - } - } - - if ( mp_blockstyle.GetInt() == 0 ) - { - BreakCapture( false ); - } - return; - } - - if ( m_bBlocked ) - { - m_bBlocked = false; - UpdateBlocked(); - } - - float flTotalTimeToCap = m_flCapTime; - if ( mp_capstyle.GetInt() == 1 ) - { - flTotalTimeToCap = ((m_flCapTime * 2) * m_TeamData[m_nCapturingTeam].iNumRequiredToCap); - } - - // Now remove the reduction amount after we've determined there's only 1 team in the area - if ( m_nCapturingTeam == m_nTeamInZone ) - { - SetCapTimeRemaining( m_fTimeRemaining - flReduction ); - } - else if ( m_nOwningTeam == TEAM_UNASSIGNED && m_nTeamInZone != TEAM_UNASSIGNED ) - { - SetCapTimeRemaining( m_fTimeRemaining + flReduction ); - } - else - { - // Caps deteriorate over time - if ( TeamplayRoundBasedRules() && m_hPoint && TeamplayRoundBasedRules()->TeamMayCapturePoint(m_nCapturingTeam,m_hPoint->GetPointIndex()) ) - { - float flDecrease = (flTotalTimeToCap / mp_capdeteriorate_time.GetFloat()) * flTimeDelta; - if ( TeamplayRoundBasedRules() && TeamplayRoundBasedRules()->InOvertime() ) - { - flDecrease *= 6; - } - SetCapTimeRemaining( m_fTimeRemaining + flDecrease ); - } - else - { - SetCapTimeRemaining( flTotalTimeToCap ); - } - } - - /* - //if no-one is in the area - if( iTeamsInZone == 0 ) - { - BreakCapture( true ); - return; - } - - //if they've lost the number of players needed to cap - int iTeamMembersHere = m_TeamData[m_nCapturingTeam].iNumTouching + iNumBlockablePlayers[m_nCapturingTeam]; - if ( (iTeamMembersHere == 0 ) || (mp_capstyle.GetInt() == 0 && iTeamMembersHere < m_TeamData[m_nCapturingTeam].iNumRequiredToCap) ) - { - BreakCapture( true ); - return; - } - */ - - // if the cap is done - if ( m_fTimeRemaining <= 0 ) - { - EndCapture( m_nCapturingTeam ); - return; //we're done - } - else - { - if ( m_fTimeRemaining >= flTotalTimeToCap ) - { - BreakCapture( false ); - return; - } - } - } - else - { - // If there are any teams in the zone that aren't the owner, try to start capping - if ( iTeamsInZone > 0 ) - { - for ( int i = FIRST_GAME_TEAM; i < GetNumberOfTeams(); i++ ) - { - if ( !m_TeamData[i].bCanCap || m_nOwningTeam == i ) - continue; - - if ( m_TeamData[i].iNumTouching == 0 ) - continue; - - if ( mp_capstyle.GetInt() == 0 && m_TeamData[i].iNumTouching < m_TeamData[i].iNumRequiredToCap ) - continue; - - StartCapture( i, CAPTURE_NORMAL ); - break; - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerAreaCapture::SetCapTimeRemaining( float flTime ) -{ - m_fTimeRemaining = flTime; - - float flCapPercentage = 0; - if ( m_nCapturingTeam ) - { - flCapPercentage = m_fTimeRemaining / m_flCapTime; - if ( mp_capstyle.GetInt() == 1 ) - { - flCapPercentage = m_fTimeRemaining / ((m_flCapTime * 2) * m_TeamData[m_nCapturingTeam].iNumRequiredToCap); - } - } - - ObjectiveResource()->SetCPCapPercentage( m_hPoint->GetPointIndex(), flCapPercentage ); - - if ( m_hPoint ) - { - m_hPoint->UpdateCapPercentage(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerAreaCapture::SetOwner( int team ) -{ - //break any current capturing - BreakCapture( false ); - - HandleRespawnTimeAdjustments( m_nOwningTeam, team ); - - //set the owner to the passed value - m_nOwningTeam = team; - - UpdateOwningTeam(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerAreaCapture::ForceOwner( int team ) -{ - SetOwner( team ); - - if ( m_hPoint ) - { - m_hPoint->ForceOwner( team ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerAreaCapture::HandleRespawnTimeAdjustments( int oldTeam, int newTeam ) -{ - if ( oldTeam > LAST_SHARED_TEAM ) - { - // reverse the adjust made when the old team captured this point (if we made one) - if ( m_TeamData[oldTeam].iSpawnAdjust != 0 ) - { - TeamplayRoundBasedRules()->AddTeamRespawnWaveTime( oldTeam, -m_TeamData[oldTeam].iSpawnAdjust ); - } - } - - if ( newTeam > LAST_SHARED_TEAM ) - { - if ( m_TeamData[newTeam].iSpawnAdjust != 0 ) - { - TeamplayRoundBasedRules()->AddTeamRespawnWaveTime( newTeam, m_TeamData[newTeam].iSpawnAdjust ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerAreaCapture::StartCapture( int team, int capmode ) -{ - // Remap team to get first game team = 1 - switch ( team - FIRST_GAME_TEAM+1 ) - { - case 1: - m_OnStartTeam1.FireOutput( this, this ); - break; - case 2: - m_OnStartTeam2.FireOutput( this, this ); - break; - default: - Assert(0); - break; - } - - m_StartOutput.FireOutput(this,this); - - m_nCapturingTeam = team; - - UpdateNumPlayers(); - - if ( mp_capstyle.GetInt() == 1 ) - { - SetCapTimeRemaining( ((m_flCapTime * 2) * m_TeamData[team].iNumRequiredToCap) ); - } - else - { - SetCapTimeRemaining( m_flCapTime ); - } - m_bCapturing = true; - m_bBlocked = false; - m_iCapMode = capmode; - - m_flLastReductionTime = gpGlobals->curtime; - - UpdateCappingTeam( m_nCapturingTeam ); - UpdateBlocked(); - - if( m_hPoint ) - { - m_hPoint->CaptureStart(); - } - - // tell all touching players to start racking up capture points - CTeamControlPointMaster *pMaster = g_hControlPointMasters.Count() ? g_hControlPointMasters[0] : NULL; - if ( pMaster ) - { - float flRate = pMaster->GetPartialCapturePointRate(); - - if ( flRate > 0.0f ) - { - // for each player touch - CTeam *pTeam = GetGlobalTeam( m_nCapturingTeam ); - if ( pTeam ) - { - for ( int i=0;iGetNumPlayers();i++ ) - { - CBaseMultiplayerPlayer *pPlayer = ToBaseMultiplayerPlayer( pTeam->GetPlayer(i) ); - if ( pPlayer && IsTouching( pPlayer ) ) - { - pPlayer->StartScoringEscortPoints( flRate ); - } - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerAreaCapture::EndCapture( int team ) -{ - IncrementCapAttemptNumber(); - - // Remap team to get first game team = 1 - switch ( team - FIRST_GAME_TEAM+1 ) - { - case 1: - m_OnCapTeam1.FireOutput( this, this ); - break; - case 2: - m_OnCapTeam2.FireOutput( this, this ); - break; - default: - Assert(0); - break; - } - - m_CapOutput.FireOutput(this,this); - - int numcappers = 0; - int cappingplayers[MAX_AREA_CAPPERS]; - - CBaseMultiplayerPlayer *pCappingPlayer = NULL; - - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBaseEntity *ent = UTIL_PlayerByIndex( i ); - if ( ent ) - { - CBaseMultiplayerPlayer *player = ToBaseMultiplayerPlayer(ent); - - if ( IsTouching( player ) && ( player->GetTeamNumber() == team ) ) // need to make sure disguised spies aren't included in the list of capping players - { - if( pCappingPlayer == NULL ) - { - pCappingPlayer = player; - } - - if ( numcappers < MAX_AREA_CAPPERS-1 ) - { - cappingplayers[numcappers] = i; - numcappers++; - } - } - } - } - - if ( numcappers < MAX_AREA_CAPPERS ) - { - cappingplayers[numcappers] = 0; //null terminate :) - } - - // Handle this before we assign the new team as the owner of this area - HandleRespawnTimeAdjustments( m_nOwningTeam, team ); - - m_nOwningTeam = team; - m_bCapturing = false; - m_nCapturingTeam = TEAM_UNASSIGNED; - SetCapTimeRemaining( 0 ); - - //there may have been more than one capper, but only report this one. - //he hasn't gotten points yet, and his name will go in the cap string if its needed - //first capper gets name sent and points given by flag. - //other cappers get points manually above, no name in message - - //send the player in the cap string - if( m_hPoint ) - { - OnEndCapture( m_nOwningTeam ); - - UpdateOwningTeam(); - m_hPoint->SetOwner( m_nOwningTeam, true, numcappers, cappingplayers ); - m_hPoint->CaptureEnd(); - } - - m_OnNumCappersChanged.Set( 0, this, this ); - - // tell all touching players to stop racking up capture points - CTeam *pTeam = GetGlobalTeam( m_nCapturingTeam ); - if ( pTeam ) - { - for ( int i=0;iGetNumPlayers();i++ ) - { - CBaseMultiplayerPlayer *pPlayer = ToBaseMultiplayerPlayer( pTeam->GetPlayer(i) ); - if ( pPlayer && IsTouching( pPlayer ) ) - { - pPlayer->StopScoringEscortPoints(); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerAreaCapture::BreakCapture( bool bNotEnoughPlayers ) -{ - if( m_bCapturing ) - { - // Remap team to get first game team = 1 - switch ( m_nCapturingTeam - FIRST_GAME_TEAM+1 ) - { - case 1: - m_OnBreakTeam1.FireOutput( this, this ); - break; - case 2: - m_OnBreakTeam2.FireOutput( this, this ); - break; - default: - Assert(0); - break; - } - - m_BreakOutput.FireOutput(this,this); - - m_bCapturing = false; - m_nCapturingTeam = TEAM_UNASSIGNED; - - UpdateCappingTeam( TEAM_UNASSIGNED ); - - if ( bNotEnoughPlayers ) - { - IncrementCapAttemptNumber(); - } - - SetCapTimeRemaining( 0 ); - - if( m_hPoint ) - { - m_hPoint->CaptureEnd(); - } - - m_OnNumCappersChanged.Set( 0, this, this ); - - // tell all touching players to stop racking up capture points - CTeam *pTeam = GetGlobalTeam( m_nCapturingTeam ); - if ( pTeam ) - { - for ( int i=0;iGetNumPlayers();i++ ) - { - CBaseMultiplayerPlayer *pPlayer = ToBaseMultiplayerPlayer( pTeam->GetPlayer(i) ); - if ( pPlayer && IsTouching( pPlayer ) ) - { - pPlayer->StopScoringEscortPoints(); - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerAreaCapture::IncrementCapAttemptNumber( void ) -{ - m_iCapAttemptNumber++; - - m_Blockers.Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerAreaCapture::InputRoundSpawn( inputdata_t &inputdata ) -{ - // find the flag we're linked to - if( !m_hPoint ) - { - m_hPoint = dynamic_cast( gEntList.FindEntityByName(NULL, STRING(m_iszCapPointName) ) ); - - if ( m_hPoint ) - { - m_nOwningTeam = m_hPoint->GetOwner(); - - for ( int i = FIRST_GAME_TEAM; i < GetNumberOfTeams(); i++ ) - { - m_hPoint->SetCappersRequiredForTeam( i, m_TeamData[i].iNumRequiredToCap ); - - ObjectiveResource()->SetCPRequiredCappers( m_hPoint->GetPointIndex(), i, m_TeamData[i].iNumRequiredToCap ); - ObjectiveResource()->SetTeamCanCap( m_hPoint->GetPointIndex(), i, m_TeamData[i].bCanCap ); - - if ( mp_capstyle.GetInt() == 1 ) - { - ObjectiveResource()->SetCPCapTime( m_hPoint->GetPointIndex(), i, (m_flCapTime * 2) * m_TeamData[i].iNumRequiredToCap ); - } - else - { - ObjectiveResource()->SetCPCapTime( m_hPoint->GetPointIndex(), i, m_flCapTime ); - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerAreaCapture::InputSetTeamCanCap( inputdata_t &inputdata ) -{ - // Get the interaction name & target - char parseString[255]; - Q_strncpy(parseString, inputdata.value.String(), sizeof(parseString)); - - char *pszParam = strtok(parseString," "); - if ( pszParam && pszParam[0] ) - { - int iTeam = atoi( pszParam ); - pszParam = strtok(NULL," "); - - if ( pszParam && pszParam[0] ) - { - bool bCanCap = (atoi(pszParam) != 0); - - if ( iTeam >= 0 && iTeam < GetNumberOfTeams() ) - { - m_TeamData[iTeam].bCanCap = bCanCap; - if ( m_hPoint ) - { - ObjectiveResource()->SetTeamCanCap( m_hPoint->GetPointIndex(), iTeam, m_TeamData[iTeam].bCanCap ); - } - return; - } - } - } - - Warning("%s(%s) received SetTeamCanCap input with invalid format. Format should be: .\n", GetClassname(), GetDebugName() ); -} - -void CTriggerAreaCapture::InputCaptureCurrentCP( inputdata_t &inputdata ) -{ - if ( m_bCapturing ) - { - EndCapture( m_nCapturingTeam ); - } -} - -void CTriggerAreaCapture::InputSetControlPoint( inputdata_t &inputdata ) -{ - BreakCapture( false ); // clear the capping for the previous point, forces us to recalc on the new one - - char parseString[255]; - Q_strncpy(parseString, inputdata.value.String(), sizeof(parseString)); - - m_iszCapPointName = MAKE_STRING( parseString ); - m_hPoint = NULL; // force a reset of this - InputRoundSpawn( inputdata ); - - // force everyone touching to re-touch so the hud gets set up properly - for ( int i = 0; i < m_hTouchingEntities.Count(); i++ ) - { - CBaseEntity *ent = m_hTouchingEntities[i]; - if ( ent && ent->IsPlayer() ) - { - EndTouch( ent ); - StartTouch( ent ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Check if this player's death causes a block -// return FALSE if the player is not in this area -// return TRUE otherwise ( eg player is in area, but his death does not cause break ) -//----------------------------------------------------------------------------- -bool CTriggerAreaCapture::CheckIfDeathCausesBlock( CBaseMultiplayerPlayer *pVictim, CBaseMultiplayerPlayer *pKiller ) -{ - if ( !pVictim || !pKiller ) - return false; - - // make sure this player is in this area - if ( !IsTouching( pVictim ) ) - return false; - - // Teamkills shouldn't give a block reward - if ( pVictim->GetTeamNumber() == pKiller->GetTeamNumber() ) - return true; - - // return if the area is not being capped - if ( !m_bCapturing ) - return true; - - int iTeam = pVictim->GetTeamNumber(); - - // return if this player's team is not capping the area - if ( iTeam != m_nCapturingTeam ) - return true; - - // break early incase we kill multiple people in the same frame - bool bBreakCap = false; - if ( mp_capstyle.GetInt() == 1 ) - { - bBreakCap = (m_TeamData[m_nCapturingTeam].iBlockedTouching - 1) <= 0; - } - else - { - bBreakCap = ( m_TeamData[m_nCapturingTeam].iBlockedTouching - 1 < m_TeamData[m_nCapturingTeam].iNumRequiredToCap ); - } - - if ( bBreakCap ) - { - m_hPoint->CaptureBlocked( pKiller ); - //BreakCapture( true ); - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerAreaCapture::UpdateNumPlayers( void ) -{ - if( !m_hPoint ) - return; - - int index = m_hPoint->GetPointIndex(); - for ( int i = 0; i < m_TeamData.Count(); i++ ) - { - if ( i >= FIRST_GAME_TEAM && i == m_nCapturingTeam ) - { - m_OnNumCappersChanged.Set( m_TeamData[i].iNumTouching, this, this ); - } - - ObjectiveResource()->SetNumPlayers( index, i, m_TeamData[i].iNumTouching ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerAreaCapture::UpdateOwningTeam( void ) -{ - if ( m_hPoint ) - { - ObjectiveResource()->SetOwningTeam( m_hPoint->GetPointIndex(), m_nOwningTeam ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerAreaCapture::UpdateCappingTeam( int iTeam ) -{ - if ( m_hPoint ) - { - ObjectiveResource()->SetCappingTeam( m_hPoint->GetPointIndex(), iTeam ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerAreaCapture::UpdateTeamInZone( void ) -{ - if ( m_hPoint ) - { - ObjectiveResource()->SetTeamInZone( m_hPoint->GetPointIndex(), m_nTeamInZone ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerAreaCapture::UpdateBlocked( void ) -{ - if ( m_hPoint ) - { - ObjectiveResource()->SetCapBlocked( m_hPoint->GetPointIndex(), m_bBlocked ); - m_hPoint->CaptureInterrupted( m_bBlocked ); - } -} diff --git a/game/server/trigger_area_capture.h b/game/server/trigger_area_capture.h deleted file mode 100644 index a28eb91b0..000000000 --- a/game/server/trigger_area_capture.h +++ /dev/null @@ -1,160 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef TRIGGER_AREA_CAPTURE_H -#define TRIGGER_AREA_CAPTURE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "basemultiplayerplayer.h" -#include "triggers.h" -#include "team_control_point.h" - -#define AREA_ATTEND_TIME 0.7f - -#define AREA_THINK_TIME 0.1f - -#define CAPTURE_NORMAL 0 -#define CAPTURE_CATCHUP_ALIVEPLAYERS 1 - -#define MAX_CLIENT_AREAS 128 -#define MAX_AREA_CAPPERS 9 - -//----------------------------------------------------------------------------- -// Purpose: An area entity that players must remain in in order to active another entity -// Triggers are fired on start of capture, on end of capture and on broken capture -// Can either be capped by both teams at once, or just by one -// Time to capture and number of people required to capture are both passed by the mapper -//----------------------------------------------------------------------------- -class CTriggerAreaCapture : public CBaseTrigger -{ - DECLARE_CLASS( CTriggerAreaCapture, CBaseTrigger ); -public: - CTriggerAreaCapture(); - - // Derived, game-specific area triggers must override these functions -public: - // Display a hint about capturing zones to the player - virtual void DisplayCapHintTo( CBaseMultiplayerPlayer *pPlayer ) { return; } - - // A team has finished capturing the zone. - virtual void OnEndCapture( int iTeam ) { return; } - -public: - virtual void Spawn( void ); - virtual void Precache( void ); - virtual bool KeyValue( const char *szKeyName, const char *szValue ); - - void SetAreaIndex( int index ); - bool IsActive( void ); - bool CheckIfDeathCausesBlock( CBaseMultiplayerPlayer *pVictim, CBaseMultiplayerPlayer *pKiller ); - - void UpdateNumPlayers( void ); - void UpdateOwningTeam( void ); - void UpdateCappingTeam( int iTeam ); - void UpdateTeamInZone( void ); - void UpdateBlocked( void ); - - void ForceOwner( int team ); // by the control_point_round to force an owner of this point (so we can play a specific round) - - bool TeamCanCap( int iTeam ){ return m_TeamData[iTeam].bCanCap; } - CHandle GetControlPoint( void ){ return m_hPoint; } - - int GetOwningTeam( void ) { return m_nOwningTeam; } - - bool IsBlocked( void ) { return m_bBlocked; } - -private: - void StartTouch(CBaseEntity *pOther); - void EXPORT AreaTouch( CBaseEntity *pOther ); - void EndTouch(CBaseEntity *pOther); - void CaptureThink( void ); - - void StartCapture( int team, int capmode ); - void EndCapture( int team ); - void BreakCapture( bool bNotEnoughPlayers ); - void IncrementCapAttemptNumber( void ); - void SwitchCapture( int team ); - void SendNumPlayers( void ); - - void SetOwner( int team ); //sets the owner of this point - useful for resetting all to -1 - - void InputRoundSpawn( inputdata_t &inputdata ); - void InputCaptureCurrentCP( inputdata_t &inputdata ); - void InputSetTeamCanCap( inputdata_t &inputdata ); - void InputSetControlPoint( inputdata_t &inputdata ); - - void SetCapTimeRemaining( float flTime ); - - void HandleRespawnTimeAdjustments( int oldTeam, int newTeam ); - -private: - int m_iCapMode; //which capture mode we're in - bool m_bCapturing; - int m_nCapturingTeam; //the team that is capturing this point - int m_nOwningTeam; //the team that has captured this point - int m_nTeamInZone; //if there's one team in the zone, this is it. - float m_flCapTime; //the total time it takes to capture the area, in seconds - float m_fTimeRemaining; //the time left in the capture - float m_flLastReductionTime; - bool m_bBlocked; - - struct perteamdata_t - { - perteamdata_t() - { - iNumRequiredToCap = 0; - iNumTouching = 0; - iBlockedTouching = 0; - bCanCap = false; - iSpawnAdjust = 0; - } - - int iNumRequiredToCap; - int iNumTouching; - int iBlockedTouching; // Number of capping players on the cap while it's being blocked - bool bCanCap; - int iSpawnAdjust; - }; - CUtlVector m_TeamData; - - struct blockers_t - { - CHandle hPlayer; - int iCapAttemptNumber; - }; - CUtlVector m_Blockers; - - bool m_bActive; - - COutputEvent m_OnStartTeam1; - COutputEvent m_OnStartTeam2; - COutputEvent m_OnBreakTeam1; - COutputEvent m_OnBreakTeam2; - COutputEvent m_OnCapTeam1; - COutputEvent m_OnCapTeam2; - - COutputEvent m_StartOutput; - COutputEvent m_BreakOutput; - COutputEvent m_CapOutput; - - COutputInt m_OnNumCappersChanged; - - int m_iAreaIndex; //index of this area among all other areas - - CHandle m_hPoint; //the capture point that we are linked to! - - bool m_bRequiresObject; - - string_t m_iszCapPointName; //name of the cap point that we're linked to - - int m_iCapAttemptNumber; // number used to keep track of discrete cap attempts, for block tracking - - DECLARE_DATADESC(); -}; - -#endif // TRIGGER_AREA_CAPTURE_H diff --git a/game/server/trigger_portal.cpp b/game/server/trigger_portal.cpp deleted file mode 100644 index dc8c7436e..000000000 --- a/game/server/trigger_portal.cpp +++ /dev/null @@ -1,343 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Entity which teleports touched entities and reorients their physics -// -//=============================================================================// - -#include "cbase.h" -#include "baseentity.h" -#include "triggers.h" -#include "modelentities.h" -#include "saverestore_utlvector.h" -#include "player_pickup.h" -#include "vphysics/friction.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define TRIGGER_DISABLED_THINK "PortalDisabledThink" - -ConVar portal_debug( "portal_debug", "0", FCVAR_CHEAT, "Turn on debugging for portal connections." ); - -////////////////////////////////////////////////////////////////////////// -// CTriggerPortal -// Moves touched entity to a target location, changing the model's orientation -// to match the exit target. It differs from CTriggerTeleport in that it -// reorients physics and has inputs to enable/disable its function. -////////////////////////////////////////////////////////////////////////// -class CTriggerPortal : public CBaseTrigger -{ -public: - DECLARE_DATADESC(); - DECLARE_CLASS( CTriggerPortal, CBaseTrigger ); - DECLARE_SERVERCLASS(); - - virtual void Spawn( void ); - virtual void Activate(); - - void Touch( CBaseEntity *pOther ); - void EndTouch(CBaseEntity *pOther); - void DisableForIncomingEntity( CBaseEntity *pEntity ); - bool IsTouchingPortal( CBaseEntity *pEntity ); - - void DisabledThink( void ); - - // TEMP: Since brushes have no directionality, give this wall a forward face specified in hammer - QAngle m_qFaceAngles; - -private: - string_t m_strRemotePortal; - CNetworkHandle( CTriggerPortal, m_hRemotePortal ); - CUtlVector m_hDisabledForEntities; - - // Input for setting remote portal entity (for teleporting to it) - void SetRemotePortal ( const char* strRemotePortalName ); - void InputSetRemotePortal ( inputdata_t &inputdata ); - -}; - -LINK_ENTITY_TO_CLASS( trigger_portal, CTriggerPortal ); - -BEGIN_DATADESC( CTriggerPortal ) - DEFINE_KEYFIELD( m_strRemotePortal, FIELD_STRING, "RemotePortal" ), - - DEFINE_FIELD( m_hRemotePortal, FIELD_EHANDLE ), - DEFINE_UTLVECTOR( m_hDisabledForEntities, FIELD_EHANDLE ), - - // TEMP: Only keep this field while portals are still brushes - DEFINE_FIELD( m_qFaceAngles, FIELD_VECTOR ), - - DEFINE_THINKFUNC( DisabledThink ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - DEFINE_INPUTFUNC( FIELD_STRING, "SetRemotePortal", InputSetRemotePortal ), -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CTriggerPortal, DT_TriggerPortal ) - SendPropEHandle(SENDINFO(m_hRemotePortal)), -END_SEND_TABLE() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerPortal::Spawn( void ) -{ - BaseClass::Spawn(); - - InitTrigger(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -//----------------------------------------------------------------------------- -void CTriggerPortal::Activate() -{ - BaseClass::Activate(); - - m_qFaceAngles = this->GetAbsAngles(); - - // keep the remote portal's pointer at activate time to avoid redundant FindEntity calls - if ( m_strRemotePortal != NULL_STRING ) - { - SetRemotePortal( STRING(m_strRemotePortal) ); - m_strRemotePortal = NULL_STRING; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CTriggerPortal::InputSetRemotePortal(inputdata_t &inputdata ) -{ - SetRemotePortal( inputdata.value.String() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : strRemotePortalName - -//----------------------------------------------------------------------------- -void CTriggerPortal::SetRemotePortal(const char *strRemotePortalName ) -{ - m_hRemotePortal = dynamic_cast (gEntList.FindEntityByName( NULL, strRemotePortalName, NULL, NULL, NULL )); - if ( m_hRemotePortal == NULL ) - { - Warning ( "trigger_portal: Cannot find remote portal entity named %s\n", strRemotePortalName ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOther - -//----------------------------------------------------------------------------- -void CTriggerPortal::EndTouch(CBaseEntity *pOther) -{ - BaseClass::EndTouch(pOther); - - if ( portal_debug.GetBool() ) - { - Msg("%s ENDTOUCH: for %s\n", GetDebugName(), pOther->GetDebugName() ); - } - - EHANDLE hHandle; - hHandle = pOther; - m_hDisabledForEntities.FindAndRemove( hHandle ); -} - -//----------------------------------------------------------------------------- -// Purpose: Upon touching a non-filtered entity, CTriggerPortal teleports them to it's -// remote portal location. -// Input : *pOther - -//----------------------------------------------------------------------------- -void CTriggerPortal::Touch( CBaseEntity *pOther ) -{ - // If we are enabled, and allowed to react to the touched entity - if ( PassesTriggerFilters(pOther) ) - { - // If we somehow lost our pointer to the remote portal, get a new one - if ( m_hRemotePortal == NULL ) - { - Disable(); - return; - } - - bool bDebug = portal_debug.GetBool(); - if ( bDebug ) - { - Msg("%s TOUCH: for %s\n", GetDebugName(), pOther->GetDebugName() ); - } - - // Don't touch entities that came through us and haven't left us yet. - EHANDLE hHandle; - hHandle = pOther; - if ( m_hDisabledForEntities.Find(hHandle) != m_hDisabledForEntities.InvalidIndex() ) - { - Msg(" IGNORED\n", GetDebugName(), pOther->GetDebugName() ); - return; - } - - Pickup_ForcePlayerToDropThisObject( pOther ); - - // de-ground this entity - pOther->SetGroundEntity( NULL ); - - // Build a this --> remote transformation - VMatrix matMyModelToWorld, matMyInverse; - matMyModelToWorld = this->EntityToWorldTransform(); - MatrixInverseGeneral ( matMyModelToWorld, matMyInverse ); - - // Teleport our object - VMatrix matRemotePortalTransform = m_hRemotePortal->EntityToWorldTransform(); - Vector ptNewOrigin, vLook, vRight, vUp, vNewLook; - pOther->GetVectors( &vLook, &vRight, &vUp ); - - // Move origin - ptNewOrigin = matMyInverse * pOther->GetAbsOrigin(); - ptNewOrigin = matRemotePortalTransform * Vector( ptNewOrigin.x, -ptNewOrigin.y, ptNewOrigin.z ); - - // Re-aim camera - vNewLook = matMyInverse.ApplyRotation( vLook ); - vNewLook = matRemotePortalTransform.ApplyRotation( Vector( -vNewLook.x, -vNewLook.y, vNewLook.z ) ); - - // Reorient the physics - Vector vVelocity, vOldVelocity; - pOther->GetVelocity( &vOldVelocity ); - vVelocity = matMyInverse.ApplyRotation( vOldVelocity ); - vVelocity = matRemotePortalTransform.ApplyRotation( Vector( -vVelocity.x, -vVelocity.y, vVelocity.z ) ); - - QAngle qNewAngles; - VectorAngles( vNewLook, qNewAngles ); - - if ( pOther->IsPlayer() ) - { - ((CBasePlayer*)pOther)->SnapEyeAngles(qNewAngles); - } - - Vector vecOldPos = pOther->WorldSpaceCenter(); - if ( bDebug ) - { - NDebugOverlay::Box( pOther->GetAbsOrigin(), pOther->WorldAlignMins(), pOther->WorldAlignMaxs(), 255,0,0, 8, 20 ); - NDebugOverlay::Axis( pOther->GetAbsOrigin(), pOther->GetAbsAngles(), 10.0f, true, 50 ); - } - - // place player at the new destination - CTriggerPortal *pPortal = m_hRemotePortal.Get(); - pPortal->DisableForIncomingEntity( pOther ); - pOther->Teleport( &ptNewOrigin, &qNewAngles, &vVelocity ); - - if ( bDebug ) - { - NDebugOverlay::Box( pOther->GetAbsOrigin(), pOther->WorldAlignMins(), pOther->WorldAlignMaxs(), 0,255,0, 8, 20 ); - NDebugOverlay::Line( vecOldPos, pOther->WorldSpaceCenter(), 0,255,0, true, 20 ); - NDebugOverlay::Axis( pOther->GetAbsOrigin(), pOther->GetAbsAngles(), 10.0f, true, 50 ); - - Msg("%s TELEPORTED: %s\n", GetDebugName(), pOther->GetDebugName() ); - } - - // test collision on the new teleport location - Vector vMin, vMax, vCenter; - pOther->CollisionProp()->WorldSpaceAABB( &vMin, &vMax ); - vCenter = (vMin + vMax) * 0.5f; - vMin -= vCenter; - vMax -= vCenter; - - Vector vStart, vEnd; - vStart = ptNewOrigin; - vEnd = ptNewOrigin; - - Ray_t ray; - ray.Init( vStart, vEnd, vMin, vMax ); - trace_t tr; - pPortal->TestCollision( ray, pOther->PhysicsSolidMaskForEntity(), tr ); - - // Teleportation caused us to hit something, deal with it. - if ( tr.DidHit() ) - { - - } - - - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerPortal::DisableForIncomingEntity( CBaseEntity *pEntity ) -{ - EHANDLE hHandle; - hHandle = pEntity; - Assert( m_hDisabledForEntities.Find(hHandle) == m_hDisabledForEntities.InvalidIndex() ); - m_hDisabledForEntities.AddToTail( hHandle ); - - // Start thinking, and remove the other as soon as it's not touching me. - // Needs to be done in addition to EndTouch, because entities may move fast - // enough through the portal to come out not touching the other portal. - SetContextThink( &CTriggerPortal::DisabledThink, gpGlobals->curtime + 0.1, TRIGGER_DISABLED_THINK ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerPortal::DisabledThink( void ) -{ - // If we've got no disabled entities left, we're done - if ( !m_hDisabledForEntities.Count() ) - { - SetContextThink( NULL, gpGlobals->curtime, TRIGGER_DISABLED_THINK ); - return; - } - - for ( int i = m_hDisabledForEntities.Count()-1; i >= 0; i-- ) - { - CBaseEntity *pEntity = m_hDisabledForEntities[i]; - if ( !pEntity || !IsTouchingPortal(pEntity) ) - { - m_hDisabledForEntities.Remove(i); - } - } - - SetContextThink( &CTriggerPortal::DisabledThink, gpGlobals->curtime + 0.1, TRIGGER_DISABLED_THINK ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTriggerPortal::IsTouchingPortal( CBaseEntity *pEntity ) -{ - // First, check the touchlinks. This will find non-vphysics entities touching us - touchlink_t *root = ( touchlink_t * )GetDataObject( TOUCHLINK ); - if ( root ) - { - for ( touchlink_t *link = root->nextLink; link != root; link = link->nextLink ) - { - CBaseEntity *pTouch = link->entityTouched; - if ( pTouch == pEntity ) - return true; - } - } - - // Then check the friction snapshot. This will find vphysics objects touching us. - IPhysicsObject *pPhysics = VPhysicsGetObject(); - if ( !pPhysics ) - return false; - - IPhysicsFrictionSnapshot *pSnapshot = pPhysics->CreateFrictionSnapshot(); - bool bFound = false; - while ( pSnapshot->IsValid() ) - { - IPhysicsObject *pOther = pSnapshot->GetObject( 1 ); - if ( ((CBaseEntity *)pOther->GetGameData()) == pEntity ) - { - bFound = true; - break; - } - - pSnapshot->NextFrictionData(); - } - pPhysics->DestroyFrictionSnapshot( pSnapshot ); - - return bFound; -} diff --git a/game/server/triggers.cpp b/game/server/triggers.cpp deleted file mode 100644 index 6e9b06f75..000000000 --- a/game/server/triggers.cpp +++ /dev/null @@ -1,4873 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: Spawn and use functions for editor-placed triggers. -// -//===========================================================================// - -#include "cbase.h" -#include "ai_basenpc.h" -#include "player.h" -#include "saverestore.h" -#include "gamerules.h" -#include "entityapi.h" -#include "entitylist.h" -#include "ndebugoverlay.h" -#include "globalstate.h" -#include "filters.h" -#include "vstdlib/random.h" -#include "triggers.h" -#include "saverestoretypes.h" -#include "hierarchy.h" -#include "bspfile.h" -#include "saverestore_utlvector.h" -#include "physics_saverestore.h" -#include "te_effect_dispatch.h" -#include "ammodef.h" -#include "iservervehicle.h" -#include "movevars_shared.h" -#include "physics_prop_ragdoll.h" -#include "props.h" -#include "RagdollBoogie.h" -#include "EntityParticleTrail.h" -#include "in_buttons.h" -#include "ai_behavior_follow.h" -#include "ai_behavior_lead.h" -#include "gameinterface.h" - -#ifdef HL2_DLL -#include "hl2_player.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define DEBUG_TRANSITIONS_VERBOSE 2 -ConVar g_debug_transitions( "g_debug_transitions", "0", FCVAR_NONE, "Set to 1 and restart the map to be warned if the map has no trigger_transition volumes. Set to 2 to see a dump of all entities & associated results during a transition." ); - -// Global list of triggers that care about weapon fire -// Doesn't need saving, the triggers re-add themselves on restore. -CUtlVector< CHandle > g_hWeaponFireTriggers; - -extern CServerGameDLL g_ServerGameDLL; -extern bool g_fGameOver; -ConVar showtriggers( "showtriggers", "0", FCVAR_CHEAT, "Shows trigger brushes" ); - -bool IsTriggerClass( CBaseEntity *pEntity ); - -// Command to dynamically toggle trigger visibility -void Cmd_ShowtriggersToggle_f( const CCommand &args ) -{ - // Loop through the entities in the game and make visible anything derived from CBaseTrigger - CBaseEntity *pEntity = gEntList.FirstEnt(); - while ( pEntity ) - { - if ( IsTriggerClass(pEntity) ) - { - // If a classname is specified, only show triggles of that type - if ( args.ArgC() > 1 ) - { - const char *sClassname = args[1]; - if ( sClassname && sClassname[0] ) - { - if ( !FClassnameIs( pEntity, sClassname ) ) - { - pEntity = gEntList.NextEnt( pEntity ); - continue; - } - } - } - - if ( pEntity->IsEffectActive( EF_NODRAW ) ) - { - pEntity->RemoveEffects( EF_NODRAW ); - } - else - { - pEntity->AddEffects( EF_NODRAW ); - } - } - - pEntity = gEntList.NextEnt( pEntity ); - } -} - -static ConCommand showtriggers_toggle( "showtriggers_toggle", Cmd_ShowtriggersToggle_f, "Toggle show triggers", FCVAR_CHEAT ); - -// Global Savedata for base trigger -BEGIN_DATADESC( CBaseTrigger ) - - // Keyfields - DEFINE_KEYFIELD( m_iFilterName, FIELD_STRING, "filtername" ), - DEFINE_FIELD( m_hFilter, FIELD_EHANDLE ), - DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ), - DEFINE_UTLVECTOR( m_hTouchingEntities, FIELD_EHANDLE ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), - DEFINE_INPUTFUNC( FIELD_VOID, "TouchTest", InputTouchTest ), - - DEFINE_INPUTFUNC( FIELD_VOID, "StartTouch", InputStartTouch ), - DEFINE_INPUTFUNC( FIELD_VOID, "EndTouch", InputEndTouch ), - - // Outputs - DEFINE_OUTPUT( m_OnStartTouch, "OnStartTouch"), - DEFINE_OUTPUT( m_OnStartTouchAll, "OnStartTouchAll"), - DEFINE_OUTPUT( m_OnEndTouch, "OnEndTouch"), - DEFINE_OUTPUT( m_OnEndTouchAll, "OnEndTouchAll"), - DEFINE_OUTPUT( m_OnTouching, "OnTouching" ), - DEFINE_OUTPUT( m_OnNotTouching, "OnNotTouching" ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( trigger, CBaseTrigger ); - - -CBaseTrigger::CBaseTrigger() -{ - AddEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID ); -} - -//------------------------------------------------------------------------------ -// Purpose: Input handler to turn on this trigger. -//------------------------------------------------------------------------------ -void CBaseTrigger::InputEnable( inputdata_t &inputdata ) -{ - Enable(); -} - - -//------------------------------------------------------------------------------ -// Purpose: Input handler to turn off this trigger. -//------------------------------------------------------------------------------ -void CBaseTrigger::InputDisable( inputdata_t &inputdata ) -{ - Disable(); -} - -void CBaseTrigger::InputTouchTest( inputdata_t &inputdata ) -{ - TouchTest(); -} - -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -void CBaseTrigger::Spawn() -{ - if ( HasSpawnFlags( SF_TRIGGER_ONLY_PLAYER_ALLY_NPCS ) || HasSpawnFlags( SF_TRIGGER_ONLY_NPCS_IN_VEHICLES ) ) - { - // Automatically set this trigger to work with NPC's. - AddSpawnFlags( SF_TRIGGER_ALLOW_NPCS ); - } - - if ( HasSpawnFlags( SF_TRIGGER_ONLY_CLIENTS_IN_VEHICLES ) ) - { - AddSpawnFlags( SF_TRIGGER_ALLOW_CLIENTS ); - } - - if ( HasSpawnFlags( SF_TRIGGER_ONLY_CLIENTS_OUT_OF_VEHICLES ) ) - { - AddSpawnFlags( SF_TRIGGER_ALLOW_CLIENTS ); - } - - BaseClass::Spawn(); -} - - -//------------------------------------------------------------------------------ -// Cleanup -//------------------------------------------------------------------------------ -void CBaseTrigger::UpdateOnRemove( void ) -{ - if ( VPhysicsGetObject()) - { - VPhysicsGetObject()->RemoveTrigger(); - } - - BaseClass::UpdateOnRemove(); -} - -//------------------------------------------------------------------------------ -// Purpose: Turns on this trigger. -//------------------------------------------------------------------------------ -void CBaseTrigger::Enable( void ) -{ - m_bDisabled = false; - - if ( VPhysicsGetObject()) - { - VPhysicsGetObject()->EnableCollisions( true ); - } - - if (!IsSolidFlagSet( FSOLID_TRIGGER )) - { - AddSolidFlags( FSOLID_TRIGGER ); - PhysicsTouchTriggers(); - } -} - - -//------------------------------------------------------------------------------ -// Purpose : -//------------------------------------------------------------------------------ -void CBaseTrigger::Activate( void ) -{ - // Get a handle to my filter entity if there is one - if (m_iFilterName != NULL_STRING) - { - m_hFilter = dynamic_cast(gEntList.FindEntityByName( NULL, m_iFilterName )); - } - - BaseClass::Activate(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Called after player becomes active in the game -//----------------------------------------------------------------------------- -void CBaseTrigger::PostClientActive( void ) -{ - BaseClass::PostClientActive(); - - if ( !m_bDisabled ) - { - PhysicsTouchTriggers(); - } -} - -//------------------------------------------------------------------------------ -// Purpose: Turns off this trigger. -//------------------------------------------------------------------------------ -void CBaseTrigger::Disable( void ) -{ - m_bDisabled = true; - - if ( VPhysicsGetObject()) - { - VPhysicsGetObject()->EnableCollisions( false ); - } - - if (IsSolidFlagSet(FSOLID_TRIGGER)) - { - RemoveSolidFlags( FSOLID_TRIGGER ); - PhysicsTouchTriggers(); - } -} -//------------------------------------------------------------------------------ -// Purpose: Tests to see if anything is touching this trigger. -//------------------------------------------------------------------------------ -void CBaseTrigger::TouchTest( void ) -{ - // If the trigger is disabled don't test to see if anything is touching it. - if ( !m_bDisabled ) - { - if ( m_hTouchingEntities.Count() !=0 ) - { - - m_OnTouching.FireOutput( this, this ); - } - else - { - m_OnNotTouching.FireOutput( this, this ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CBaseTrigger::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - // -------------- - // Print Target - // -------------- - char tempstr[255]; - if (IsSolidFlagSet(FSOLID_TRIGGER)) - { - Q_strncpy(tempstr,"State: Enabled",sizeof(tempstr)); - } - else - { - Q_strncpy(tempstr,"State: Disabled",sizeof(tempstr)); - } - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseTrigger::InitTrigger( ) -{ - SetSolid( GetParent() ? SOLID_VPHYSICS : SOLID_BSP ); - AddSolidFlags( FSOLID_NOT_SOLID ); - if (m_bDisabled) - { - RemoveSolidFlags( FSOLID_TRIGGER ); - } - else - { - AddSolidFlags( FSOLID_TRIGGER ); - } - - SetMoveType( MOVETYPE_NONE ); - SetModel( STRING( GetModelName() ) ); // set size and link into world - if ( showtriggers.GetInt() == 0 ) - { - AddEffects( EF_NODRAW ); - } - - m_hTouchingEntities.Purge(); - - if ( HasSpawnFlags( SF_TRIG_TOUCH_DEBRIS ) ) - { - CollisionProp()->AddSolidFlags( FSOLID_TRIGGER_TOUCH_DEBRIS ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns true if this entity passes the filter criteria, false if not. -// Input : pOther - The entity to be filtered. -//----------------------------------------------------------------------------- -bool CBaseTrigger::PassesTriggerFilters(CBaseEntity *pOther) -{ - // First test spawn flag filters - if ( HasSpawnFlags(SF_TRIGGER_ALLOW_ALL) || - (HasSpawnFlags(SF_TRIGGER_ALLOW_CLIENTS) && (pOther->GetFlags() & FL_CLIENT)) || - (HasSpawnFlags(SF_TRIGGER_ALLOW_NPCS) && (pOther->GetFlags() & FL_NPC)) || - (HasSpawnFlags(SF_TRIGGER_ALLOW_PUSHABLES) && FClassnameIs(pOther, "func_pushable")) || - (HasSpawnFlags(SF_TRIGGER_ALLOW_PHYSICS) && pOther->GetMoveType() == MOVETYPE_VPHYSICS) -#if defined( HL2_EPISODIC ) || defined( TF_DLL ) - || - ( HasSpawnFlags(SF_TRIG_TOUCH_DEBRIS) && - (pOther->GetCollisionGroup() == COLLISION_GROUP_DEBRIS || - pOther->GetCollisionGroup() == COLLISION_GROUP_DEBRIS_TRIGGER || - pOther->GetCollisionGroup() == COLLISION_GROUP_INTERACTIVE_DEBRIS) - ) -#endif - ) - { - if ( pOther->GetFlags() & FL_NPC ) - { - CAI_BaseNPC *pNPC = pOther->MyNPCPointer(); - - if ( HasSpawnFlags( SF_TRIGGER_ONLY_PLAYER_ALLY_NPCS ) ) - { - if ( !pNPC || !pNPC->IsPlayerAlly() ) - { - return false; - } - } - - if ( HasSpawnFlags( SF_TRIGGER_ONLY_NPCS_IN_VEHICLES ) ) - { - if ( !pNPC || !pNPC->IsInAVehicle() ) - return false; - } - } - - bool bOtherIsPlayer = pOther->IsPlayer(); - - if ( HasSpawnFlags(SF_TRIGGER_ONLY_CLIENTS_IN_VEHICLES) && bOtherIsPlayer ) - { - if ( !((CBasePlayer*)pOther)->IsInAVehicle() ) - return false; - - // Make sure we're also not exiting the vehicle at the moment - IServerVehicle *pVehicleServer = ((CBasePlayer*)pOther)->GetVehicle(); - if ( pVehicleServer == NULL ) - return false; - - if ( pVehicleServer->IsPassengerExiting() ) - return false; - } - - if ( HasSpawnFlags(SF_TRIGGER_ONLY_CLIENTS_OUT_OF_VEHICLES) && bOtherIsPlayer ) - { - if ( ((CBasePlayer*)pOther)->IsInAVehicle() ) - return false; - } - - CBaseFilter *pFilter = m_hFilter.Get(); - return (!pFilter) ? true : pFilter->PassesFilter( this, pOther ); - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Called to simulate what happens when an entity touches the trigger. -// Input : pOther - The entity that is touching us. -//----------------------------------------------------------------------------- -void CBaseTrigger::InputStartTouch( inputdata_t &inputdata ) -{ - //Pretend we just touched the trigger. - StartTouch( inputdata.pCaller ); -} -//----------------------------------------------------------------------------- -// Purpose: Called to simulate what happens when an entity leaves the trigger. -// Input : pOther - The entity that is touching us. -//----------------------------------------------------------------------------- -void CBaseTrigger::InputEndTouch( inputdata_t &inputdata ) -{ - //And... pretend we left the trigger. - EndTouch( inputdata.pCaller ); -} - -//----------------------------------------------------------------------------- -// Purpose: Called when an entity starts touching us. -// Input : pOther - The entity that is touching us. -//----------------------------------------------------------------------------- -void CBaseTrigger::StartTouch(CBaseEntity *pOther) -{ - if (PassesTriggerFilters(pOther) ) - { - EHANDLE hOther; - hOther = pOther; - - bool bAdded = false; - if ( m_hTouchingEntities.Find( hOther ) == m_hTouchingEntities.InvalidIndex() ) - { - m_hTouchingEntities.AddToTail( hOther ); - bAdded = true; - } - - m_OnStartTouch.FireOutput(pOther, this); - - if ( bAdded && ( m_hTouchingEntities.Count() == 1 ) ) - { - // First entity to touch us that passes our filters - m_OnStartTouchAll.FireOutput( pOther, this ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Called when an entity stops touching us. -// Input : pOther - The entity that was touching us. -//----------------------------------------------------------------------------- -void CBaseTrigger::EndTouch(CBaseEntity *pOther) -{ - if ( IsTouching( pOther ) ) - { - EHANDLE hOther; - hOther = pOther; - m_hTouchingEntities.FindAndRemove( hOther ); - - //FIXME: Without this, triggers fire their EndTouch outputs when they are disabled! - //if ( !m_bDisabled ) - //{ - m_OnEndTouch.FireOutput(pOther, this); - //} - - // If there are no more entities touching this trigger, fire the lost all touches - // Loop through the touching entities backwards. Clean out old ones, and look for existing - bool bFoundOtherTouchee = false; - int iSize = m_hTouchingEntities.Count(); - for ( int i = iSize-1; i >= 0; i-- ) - { - EHANDLE hOther; - hOther = m_hTouchingEntities[i]; - - if ( !hOther ) - { - m_hTouchingEntities.Remove( i ); - } - else - { - bFoundOtherTouchee = true; - } - } - - //FIXME: Without this, triggers fire their EndTouch outputs when they are disabled! - // Didn't find one? - if ( !bFoundOtherTouchee /*&& !m_bDisabled*/ ) - { - m_OnEndTouchAll.FireOutput(pOther, this); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if the specified entity is touching us -//----------------------------------------------------------------------------- -bool CBaseTrigger::IsTouching( CBaseEntity *pOther ) -{ - EHANDLE hOther; - hOther = pOther; - return ( m_hTouchingEntities.Find( hOther ) != m_hTouchingEntities.InvalidIndex() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Return a pointer to the first entity of the specified type being touched by this trigger -//----------------------------------------------------------------------------- -CBaseEntity *CBaseTrigger::GetTouchedEntityOfType( const char *sClassName ) -{ - int iCount = m_hTouchingEntities.Count(); - for ( int i = 0; i < iCount; i++ ) - { - CBaseEntity *pEntity = m_hTouchingEntities[i]; - if ( FClassnameIs( pEntity, sClassName ) ) - return pEntity; - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Toggles this trigger between enabled and disabled. -//----------------------------------------------------------------------------- -void CBaseTrigger::InputToggle( inputdata_t &inputdata ) -{ - if (IsSolidFlagSet( FSOLID_TRIGGER )) - { - RemoveSolidFlags(FSOLID_TRIGGER); - } - else - { - AddSolidFlags(FSOLID_TRIGGER); - } - - PhysicsTouchTriggers(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Removes anything that touches it. If the trigger has a targetname, -// firing it will toggle state. -//----------------------------------------------------------------------------- -class CTriggerRemove : public CBaseTrigger -{ -public: - DECLARE_CLASS( CTriggerRemove, CBaseTrigger ); - - void Spawn( void ); - void Touch( CBaseEntity *pOther ); - - DECLARE_DATADESC(); - - // Outputs - COutputEvent m_OnRemove; -}; - -BEGIN_DATADESC( CTriggerRemove ) - - // Outputs - DEFINE_OUTPUT( m_OnRemove, "OnRemove" ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( trigger_remove, CTriggerRemove ); - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerRemove::Spawn( void ) -{ - BaseClass::Spawn(); - InitTrigger(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Trigger hurt that causes radiation will do a radius check and set -// the player's geiger counter level according to distance from center -// of trigger. -//----------------------------------------------------------------------------- -void CTriggerRemove::Touch( CBaseEntity *pOther ) -{ - if (!PassesTriggerFilters(pOther)) - return; - - UTIL_Remove( pOther ); -} - - -BEGIN_DATADESC( CTriggerHurt ) - - // Function Pointers - DEFINE_FUNCTION( RadiationThink ), - DEFINE_FUNCTION( HurtThink ), - - // Fields - DEFINE_FIELD( m_flOriginalDamage, FIELD_FLOAT ), - DEFINE_KEYFIELD( m_flDamage, FIELD_FLOAT, "damage" ), - DEFINE_KEYFIELD( m_flDamageCap, FIELD_FLOAT, "damagecap" ), - DEFINE_KEYFIELD( m_bitsDamageInflict, FIELD_INTEGER, "damagetype" ), - DEFINE_KEYFIELD( m_damageModel, FIELD_INTEGER, "damagemodel" ), - DEFINE_KEYFIELD( m_bNoDmgForce, FIELD_BOOLEAN, "nodmgforce" ), - - DEFINE_FIELD( m_flLastDmgTime, FIELD_TIME ), - DEFINE_FIELD( m_flDmgResetTime, FIELD_TIME ), - DEFINE_UTLVECTOR( m_hurtEntities, FIELD_EHANDLE ), - - // Inputs - DEFINE_INPUT( m_flDamage, FIELD_FLOAT, "SetDamage" ), - - // Outputs - DEFINE_OUTPUT( m_OnHurt, "OnHurt" ), - DEFINE_OUTPUT( m_OnHurtPlayer, "OnHurtPlayer" ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( trigger_hurt, CTriggerHurt ); - - -//----------------------------------------------------------------------------- -// Purpose: Called when spawning, after keyvalues have been handled. -//----------------------------------------------------------------------------- -void CTriggerHurt::Spawn( void ) -{ - BaseClass::Spawn(); - - InitTrigger(); - - m_flOriginalDamage = m_flDamage; - - SetNextThink( TICK_NEVER_THINK ); - SetThink( NULL ); - if (m_bitsDamageInflict & DMG_RADIATION) - { - SetThink ( &CTriggerHurt::RadiationThink ); - SetNextThink( gpGlobals->curtime + random->RandomFloat(0.0, 0.5) ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Trigger hurt that causes radiation will do a radius check and set -// the player's geiger counter level according to distance from center -// of trigger. -//----------------------------------------------------------------------------- -void CTriggerHurt::RadiationThink( void ) -{ - // check to see if a player is in pvs - // if not, continue - Vector vecSurroundMins, vecSurroundMaxs; - CollisionProp()->WorldSpaceSurroundingBounds( &vecSurroundMins, &vecSurroundMaxs ); - CBasePlayer *pPlayer = static_cast(UTIL_FindClientInPVS( vecSurroundMins, vecSurroundMaxs )); - - if (pPlayer) - { - // get range to player; - float flRange = CollisionProp()->CalcDistanceFromPoint( pPlayer->WorldSpaceCenter() ); - flRange *= 3.0f; - pPlayer->NotifyNearbyRadiationSource(flRange); - } - - float dt = gpGlobals->curtime - m_flLastDmgTime; - if ( dt >= 0.5 ) - { - HurtAllTouchers( dt ); - } - - SetNextThink( gpGlobals->curtime + 0.25 ); -} - - -//----------------------------------------------------------------------------- -// Purpose: When touched, a hurt trigger does m_flDamage points of damage each half-second. -// Input : pOther - The entity that is touching us. -//----------------------------------------------------------------------------- -bool CTriggerHurt::HurtEntity( CBaseEntity *pOther, float damage ) -{ - if ( !pOther->m_takedamage || !PassesTriggerFilters(pOther) ) - return false; - - if ( damage < 0 ) - { - pOther->TakeHealth( -damage, m_bitsDamageInflict ); - } - else - { - // The damage position is the nearest point on the damaged entity - // to the trigger's center. Not perfect, but better than nothing. - Vector vecCenter = CollisionProp()->WorldSpaceCenter(); - - Vector vecDamagePos; - pOther->CollisionProp()->CalcNearestPoint( vecCenter, &vecDamagePos ); - - CTakeDamageInfo info( this, this, damage, m_bitsDamageInflict ); - info.SetDamagePosition( vecDamagePos ); - if ( !m_bNoDmgForce ) - { - GuessDamageForce( &info, ( vecDamagePos - vecCenter ), vecDamagePos ); - } - else - { - info.SetDamageForce( vec3_origin ); - } - - pOther->TakeDamage( info ); - } - - if (pOther->IsPlayer()) - { - m_OnHurtPlayer.FireOutput(pOther, this); - } - else - { - m_OnHurt.FireOutput(pOther, this); - } - m_hurtEntities.AddToTail( EHANDLE(pOther) ); - //NDebugOverlay::Box( pOther->GetAbsOrigin(), pOther->WorldAlignMins(), pOther->WorldAlignMaxs(), 255,0,0,0,0.5 ); - return true; -} - -void CTriggerHurt::HurtThink() -{ - // if I hurt anyone, think again - if ( HurtAllTouchers( 0.5 ) <= 0 ) - { - SetThink(NULL); - } - else - { - SetNextThink( gpGlobals->curtime + 0.5f ); - } -} - -void CTriggerHurt::EndTouch( CBaseEntity *pOther ) -{ - if (PassesTriggerFilters(pOther)) - { - EHANDLE hOther; - hOther = pOther; - - // if this guy has never taken damage, hurt him now - if ( !m_hurtEntities.HasElement( hOther ) ) - { - HurtEntity( pOther, m_flDamage * 0.5 ); - } - } - BaseClass::EndTouch( pOther ); -} - -//----------------------------------------------------------------------------- -// Purpose: called from RadiationThink() as well as HurtThink() -// This function applies damage to any entities currently touching the -// trigger -// Input : dt - time since last call -// Output : int - number of entities actually hurt -//----------------------------------------------------------------------------- -#define TRIGGER_HURT_FORGIVE_TIME 3.0f // time in seconds -int CTriggerHurt::HurtAllTouchers( float dt ) -{ - int hurtCount = 0; - // half second worth of damage - float fldmg = m_flDamage * dt; - m_flLastDmgTime = gpGlobals->curtime; - - m_hurtEntities.RemoveAll(); - - touchlink_t *root = ( touchlink_t * )GetDataObject( TOUCHLINK ); - if ( root ) - { - for ( touchlink_t *link = root->nextLink; link != root; link = link->nextLink ) - { - CBaseEntity *pTouch = link->entityTouched; - if ( pTouch ) - { - if ( HurtEntity( pTouch, fldmg ) ) - { - hurtCount++; - } - } - } - } - - if( m_damageModel == DAMAGEMODEL_DOUBLE_FORGIVENESS ) - { - if( hurtCount == 0 ) - { - if( gpGlobals->curtime > m_flDmgResetTime ) - { - // Didn't hurt anyone. Reset the damage if it's time. (hence, the forgiveness) - m_flDamage = m_flOriginalDamage; - } - } - else - { - // Hurt someone! double the damage - m_flDamage *= 2.0f; - - if( m_flDamage > m_flDamageCap ) - { - // Clamp - m_flDamage = m_flDamageCap; - } - - // Now, put the damage reset time into the future. The forgive time is how long the trigger - // must go without harming anyone in order that its accumulated damage be reset to the amount - // set by the level designer. This is a stop-gap for an exploit where players could hop through - // slime and barely take any damage because the trigger would reset damage anytime there was no - // one in the trigger when this function was called. (sjb) - m_flDmgResetTime = gpGlobals->curtime + TRIGGER_HURT_FORGIVE_TIME; - } - } - - return hurtCount; -} - -void CTriggerHurt::Touch( CBaseEntity *pOther ) -{ - if ( m_pfnThink == NULL ) - { - SetThink( &CTriggerHurt::HurtThink ); - SetNextThink( gpGlobals->curtime ); - } -} - - -// ################################################################################## -// >> TriggerMultiple -// ################################################################################## -LINK_ENTITY_TO_CLASS( trigger_multiple, CTriggerMultiple ); - - -BEGIN_DATADESC( CTriggerMultiple ) - - // Function Pointers - DEFINE_FUNCTION(MultiTouch), - DEFINE_FUNCTION(MultiWaitOver ), - - // Outputs - DEFINE_OUTPUT(m_OnTrigger, "OnTrigger") - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Purpose: Called when spawning, after keyvalues have been handled. -//----------------------------------------------------------------------------- -void CTriggerMultiple::Spawn( void ) -{ - BaseClass::Spawn(); - - InitTrigger(); - - if (m_flWait == 0) - { - m_flWait = 0.2; - } - - ASSERTSZ(m_iHealth == 0, "trigger_multiple with health"); - SetTouch( &CTriggerMultiple::MultiTouch ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Touch function. Activates the trigger. -// Input : pOther - The thing that touched us. -//----------------------------------------------------------------------------- -void CTriggerMultiple::MultiTouch(CBaseEntity *pOther) -{ - if (PassesTriggerFilters(pOther)) - { - ActivateMultiTrigger( pOther ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pActivator - -//----------------------------------------------------------------------------- -void CTriggerMultiple::ActivateMultiTrigger(CBaseEntity *pActivator) -{ - if (GetNextThink() > gpGlobals->curtime) - return; // still waiting for reset time - - m_hActivator = pActivator; - - m_OnTrigger.FireOutput(m_hActivator, this); - - if (m_flWait > 0) - { - SetThink( &CTriggerMultiple::MultiWaitOver ); - SetNextThink( gpGlobals->curtime + m_flWait ); - } - else - { - // we can't just remove (self) here, because this is a touch function - // called while C code is looping through area links... - SetTouch( NULL ); - SetNextThink( gpGlobals->curtime + 0.1f ); - SetThink( &CTriggerMultiple::SUB_Remove ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: The wait time has passed, so set back up for another activation -//----------------------------------------------------------------------------- -void CTriggerMultiple::MultiWaitOver( void ) -{ - SetThink( NULL ); -} - -// ################################################################################## -// >> TriggerOnce -// ################################################################################## -class CTriggerOnce : public CTriggerMultiple -{ - DECLARE_CLASS( CTriggerOnce, CTriggerMultiple ); -public: - - void Spawn( void ); -}; - -LINK_ENTITY_TO_CLASS( trigger_once, CTriggerOnce ); - -void CTriggerOnce::Spawn( void ) -{ - BaseClass::Spawn(); - - m_flWait = -1; -} - - -// ################################################################################## -// >> TriggerLook -// -// Triggers once when player is looking at m_target -// -// ################################################################################## -#define SF_TRIGGERLOOK_FIREONCE 128 -#define SF_TRIGGERLOOK_USEVELOCITY 256 - -class CTriggerLook : public CTriggerOnce -{ - DECLARE_CLASS( CTriggerLook, CTriggerOnce ); -public: - - EHANDLE m_hLookTarget; - float m_flFieldOfView; - float m_flLookTime; // How long must I look for - float m_flLookTimeTotal; // How long have I looked - float m_flLookTimeLast; // When did I last look - float m_flTimeoutDuration; // Number of seconds after start touch to fire anyway - bool m_bTimeoutFired; // True if the OnTimeout output fired since the last StartTouch. - EHANDLE m_hActivator; // The entity that triggered us. - - void Spawn( void ); - void Touch( CBaseEntity *pOther ); - void StartTouch(CBaseEntity *pOther); - void EndTouch( CBaseEntity *pOther ); - int DrawDebugTextOverlays(void); - - DECLARE_DATADESC(); - -private: - - void Trigger(CBaseEntity *pActivator, bool bTimeout); - void TimeoutThink(); - - COutputEvent m_OnTimeout; -}; - -LINK_ENTITY_TO_CLASS( trigger_look, CTriggerLook ); -BEGIN_DATADESC( CTriggerLook ) - - DEFINE_FIELD( m_hLookTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_flLookTimeTotal, FIELD_FLOAT ), - DEFINE_FIELD( m_flLookTimeLast, FIELD_TIME ), - DEFINE_KEYFIELD( m_flTimeoutDuration, FIELD_FLOAT, "timeout" ), - DEFINE_FIELD( m_bTimeoutFired, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hActivator, FIELD_EHANDLE ), - - DEFINE_OUTPUT( m_OnTimeout, "OnTimeout" ), - - DEFINE_FUNCTION( TimeoutThink ), - - // Inputs - DEFINE_INPUT( m_flFieldOfView, FIELD_FLOAT, "FieldOfView" ), - DEFINE_INPUT( m_flLookTime, FIELD_FLOAT, "LookTime" ), - -END_DATADESC() - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CTriggerLook::Spawn( void ) -{ - m_hLookTarget = NULL; - m_flLookTimeTotal = -1; - m_bTimeoutFired = false; - - BaseClass::Spawn(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pOther - -//----------------------------------------------------------------------------- -void CTriggerLook::StartTouch(CBaseEntity *pOther) -{ - BaseClass::StartTouch(pOther); - - if (pOther->IsPlayer() && m_flTimeoutDuration) - { - m_bTimeoutFired = false; - m_hActivator = pOther; - SetThink(&CTriggerLook::TimeoutThink); - SetNextThink(gpGlobals->curtime + m_flTimeoutDuration); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerLook::TimeoutThink(void) -{ - Trigger(m_hActivator, true); -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CTriggerLook::EndTouch(CBaseEntity *pOther) -{ - BaseClass::EndTouch(pOther); - - if (pOther->IsPlayer()) - { - SetThink(NULL); - SetNextThink( TICK_NEVER_THINK ); - - m_flLookTimeTotal = -1; - } -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CTriggerLook::Touch(CBaseEntity *pOther) -{ - // Don't fire the OnTrigger if we've already fired the OnTimeout. This will be - // reset in OnEndTouch. - if (m_bTimeoutFired) - return; - - // -------------------------------- - // Make sure we have a look target - // -------------------------------- - if (m_hLookTarget == NULL) - { - m_hLookTarget = GetNextTarget(); - if (m_hLookTarget == NULL) - { - return; - } - } - - // This is designed for single player only - // so we'll always have the same player - if (pOther->IsPlayer()) - { - // ---------------------------------------- - // Check that toucher is facing the target - // ---------------------------------------- - Vector vLookDir; - if ( HasSpawnFlags( SF_TRIGGERLOOK_USEVELOCITY ) ) - { - vLookDir = pOther->GetAbsVelocity(); - if ( vLookDir == vec3_origin ) - { - // See if they're in a vehicle - CBasePlayer *pPlayer = (CBasePlayer *)pOther; - if ( pPlayer->IsInAVehicle() ) - { - vLookDir = pPlayer->GetVehicle()->GetVehicleEnt()->GetSmoothedVelocity(); - } - } - VectorNormalize( vLookDir ); - } - else - { - vLookDir = ((CBaseCombatCharacter*)pOther)->EyeDirection3D( ); - } - - Vector vTargetDir = m_hLookTarget->GetAbsOrigin() - pOther->EyePosition(); - VectorNormalize(vTargetDir); - - float fDotPr = DotProduct(vLookDir,vTargetDir); - if (fDotPr > m_flFieldOfView) - { - // Is it the first time I'm looking? - if (m_flLookTimeTotal == -1) - { - m_flLookTimeLast = gpGlobals->curtime; - m_flLookTimeTotal = 0; - } - else - { - m_flLookTimeTotal += gpGlobals->curtime - m_flLookTimeLast; - m_flLookTimeLast = gpGlobals->curtime; - } - - if (m_flLookTimeTotal >= m_flLookTime) - { - Trigger(pOther, false); - } - } - else - { - m_flLookTimeTotal = -1; - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Called when the trigger is fired by look logic or timeout. -//----------------------------------------------------------------------------- -void CTriggerLook::Trigger(CBaseEntity *pActivator, bool bTimeout) -{ - if (bTimeout) - { - // Fired due to timeout (player never looked at the target). - m_OnTimeout.FireOutput(pActivator, this); - - // Don't fire the OnTrigger for this toucher. - m_bTimeoutFired = true; - } - else - { - // Fire because the player looked at the target. - m_OnTrigger.FireOutput(pActivator, this); - m_flLookTimeTotal = -1; - - // Cancel the timeout think. - SetThink(NULL); - SetNextThink( TICK_NEVER_THINK ); - } - - if (HasSpawnFlags(SF_TRIGGERLOOK_FIREONCE)) - { - SetThink(&CTriggerLook::SUB_Remove); - SetNextThink(gpGlobals->curtime); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CTriggerLook::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - // ---------------- - // Print Look time - // ---------------- - char tempstr[255]; - Q_snprintf(tempstr,sizeof(tempstr),"Time: %3.2f",m_flLookTime - MAX(0,m_flLookTimeTotal)); - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} - - -// ################################################################################## -// >> TriggerVolume -// ################################################################################## -class CTriggerVolume : public CPointEntity // Derive from point entity so this doesn't move across levels -{ -public: - DECLARE_CLASS( CTriggerVolume, CPointEntity ); - - void Spawn( void ); -}; - -LINK_ENTITY_TO_CLASS( trigger_transition, CTriggerVolume ); - -// Define space that travels across a level transition -void CTriggerVolume::Spawn( void ) -{ - SetSolid( SOLID_BSP ); - AddSolidFlags( FSOLID_NOT_SOLID ); - SetMoveType( MOVETYPE_NONE ); - SetModel( STRING( GetModelName() ) ); // set size and link into world - if ( showtriggers.GetInt() == 0 ) - { - AddEffects( EF_NODRAW ); - } -} - -#define SF_CHANGELEVEL_NOTOUCH 0x0002 -#define SF_CHANGELEVEL_CHAPTER 0x0004 - -#define cchMapNameMost 32 - -enum -{ - TRANSITION_VOLUME_SCREENED_OUT = 0, - TRANSITION_VOLUME_NOT_FOUND = 1, - TRANSITION_VOLUME_PASSED = 2, -}; - - -//------------------------------------------------------------------------------ -// Reesponsible for changing levels when the player touches it -//------------------------------------------------------------------------------ -class CChangeLevel : public CBaseTrigger -{ - DECLARE_DATADESC(); - -public: - DECLARE_CLASS( CChangeLevel, CBaseTrigger ); - - void Spawn( void ); - void Activate( void ); - bool KeyValue( const char *szKeyName, const char *szValue ); - - static int ChangeList( levellist_t *pLevelList, int maxList ); - -private: - void TouchChangeLevel( CBaseEntity *pOther ); - void ChangeLevelNow( CBaseEntity *pActivator ); - - void InputChangeLevel( inputdata_t &inputdata ); - - bool IsEntityInTransition( CBaseEntity *pEntity ); - void NotifyEntitiesOutOfTransition(); - - void WarnAboutActiveLead( void ); - - static CBaseEntity *FindLandmark( const char *pLandmarkName ); - static int AddTransitionToList( levellist_t *pLevelList, int listCount, const char *pMapName, const char *pLandmarkName, edict_t *pentLandmark ); - static int InTransitionVolume( CBaseEntity *pEntity, const char *pVolumeName ); - - // Builds the list of entities to save when moving across a transition - static int BuildChangeLevelList( levellist_t *pLevelList, int maxList ); - - // Builds the list of entities to bring across a particular transition - static int BuildEntityTransitionList( CBaseEntity *pLandmarkEntity, const char *pLandmarkName, CBaseEntity **ppEntList, int *pEntityFlags, int nMaxList ); - - // Adds a single entity to the transition list, if appropriate. Returns the new count - static int AddEntityToTransitionList( CBaseEntity *pEntity, int flags, int nCount, CBaseEntity **ppEntList, int *pEntityFlags ); - - // Adds in all entities depended on by entities near the transition - static int AddDependentEntities( int nCount, CBaseEntity **ppEntList, int *pEntityFlags, int nMaxList ); - - // Figures out save flags for the entity - static int ComputeEntitySaveFlags( CBaseEntity *pEntity ); - -private: - char m_szMapName[cchMapNameMost]; // trigger_changelevel only: next map - char m_szLandmarkName[cchMapNameMost]; // trigger_changelevel only: landmark on next map - bool m_bTouched; - - // Outputs - COutputEvent m_OnChangeLevel; -}; - - -LINK_ENTITY_TO_CLASS( trigger_changelevel, CChangeLevel ); - -// Global Savedata for changelevel trigger -BEGIN_DATADESC( CChangeLevel ) - - DEFINE_AUTO_ARRAY( m_szMapName, FIELD_CHARACTER ), - DEFINE_AUTO_ARRAY( m_szLandmarkName, FIELD_CHARACTER ), -// DEFINE_FIELD( m_touchTime, FIELD_TIME ), // don't save -// DEFINE_FIELD( m_bTouched, FIELD_BOOLEAN ), - - // Function Pointers - DEFINE_FUNCTION( TouchChangeLevel ), - - DEFINE_INPUTFUNC( FIELD_VOID, "ChangeLevel", InputChangeLevel ), - - // Outputs - DEFINE_OUTPUT( m_OnChangeLevel, "OnChangeLevel"), - -END_DATADESC() - - -// -// Cache user-entity-field values until spawn is called. -// - -bool CChangeLevel::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "map")) - { - if (strlen(szValue) >= cchMapNameMost) - { - Warning( "Map name '%s' too long (32 chars)\n", szValue ); - Assert(0); - } - Q_strncpy(m_szMapName, szValue, sizeof(m_szMapName)); - } - else if (FStrEq(szKeyName, "landmark")) - { - if (strlen(szValue) >= cchMapNameMost) - { - Warning( "Landmark name '%s' too long (32 chars)\n", szValue ); - Assert(0); - } - - Q_strncpy(m_szLandmarkName, szValue, sizeof( m_szLandmarkName )); - } - else - return BaseClass::KeyValue( szKeyName, szValue ); - - return true; -} - - - -void CChangeLevel::Spawn( void ) -{ - if ( FStrEq( m_szMapName, "" ) ) - { - Msg( "a trigger_changelevel doesn't have a map" ); - } - - if ( FStrEq( m_szLandmarkName, "" ) ) - { - Msg( "trigger_changelevel to %s doesn't have a landmark", m_szMapName ); - } - - InitTrigger(); - - if ( !HasSpawnFlags(SF_CHANGELEVEL_NOTOUCH) ) - { - SetTouch( &CChangeLevel::TouchChangeLevel ); - } - -// Msg( "TRANSITION: %s (%s)\n", m_szMapName, m_szLandmarkName ); -} - -void CChangeLevel::Activate( void ) -{ - BaseClass::Activate(); - - if ( gpGlobals->eLoadType == MapLoad_NewGame ) - { - if ( HasSpawnFlags( SF_CHANGELEVEL_CHAPTER ) ) - { - VPhysicsInitStatic(); - RemoveSolidFlags( FSOLID_NOT_SOLID | FSOLID_TRIGGER ); - SetTouch( NULL ); - return; - } - } - - // Level transitions will bust if they are in solid - CBaseEntity *pLandmark = FindLandmark( m_szLandmarkName ); - if ( pLandmark ) - { - int clusterIndex = engine->GetClusterForOrigin( pLandmark->GetAbsOrigin() ); - if ( clusterIndex < 0 ) - { - Warning( "trigger_changelevel to map %s has a landmark embedded in solid!\n" - "This will break level transitions!\n", m_szMapName ); - } - - if ( g_debug_transitions.GetInt() ) - { - if ( !gEntList.FindEntityByClassname( NULL, "trigger_transition" ) ) - { - Warning( "Map has no trigger_transition volumes for landmark %s\n", m_szLandmarkName ); - } - } - } - - m_bTouched = false; -} - - -static char st_szNextMap[cchMapNameMost]; -static char st_szNextSpot[cchMapNameMost]; - -// Used to show debug for only the transition volume we're currently in -static int g_iDebuggingTransition = 0; - -CBaseEntity *CChangeLevel::FindLandmark( const char *pLandmarkName ) -{ - CBaseEntity *pentLandmark; - - pentLandmark = gEntList.FindEntityByName( NULL, pLandmarkName ); - while ( pentLandmark ) - { - // Found the landmark - if ( FClassnameIs( pentLandmark, "info_landmark" ) ) - return pentLandmark; - else - pentLandmark = gEntList.FindEntityByName( pentLandmark, pLandmarkName ); - } - Warning( "Can't find landmark %s\n", pLandmarkName ); - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Allows level transitions to be triggered by buttons, etc. -//----------------------------------------------------------------------------- -void CChangeLevel::InputChangeLevel( inputdata_t &inputdata ) -{ - // Ignore changelevel transitions if the player's dead or attempting a challenge - if ( gpGlobals->maxClients == 1 ) - { - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - if ( pPlayer && ( !pPlayer->IsAlive() || pPlayer->GetBonusChallenge() > 0 ) ) - return; - } - - ChangeLevelNow( inputdata.pActivator ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Performs the level change and fires targets. -// Input : pActivator - -//----------------------------------------------------------------------------- -bool CChangeLevel::IsEntityInTransition( CBaseEntity *pEntity ) -{ - int transitionState = InTransitionVolume(pEntity, m_szLandmarkName); - if ( transitionState == TRANSITION_VOLUME_SCREENED_OUT ) - { - return false; - } - - // look for a landmark entity - CBaseEntity *pLandmark = FindLandmark( m_szLandmarkName ); - - if ( !pLandmark ) - return false; - - // Check to make sure it's also in the PVS of landmark - byte pvs[MAX_MAP_CLUSTERS/8]; - int clusterIndex = engine->GetClusterForOrigin( pLandmark->GetAbsOrigin() ); - engine->GetPVSForCluster( clusterIndex, sizeof(pvs), pvs ); - Vector vecSurroundMins, vecSurroundMaxs; - pEntity->CollisionProp()->WorldSpaceSurroundingBounds( &vecSurroundMins, &vecSurroundMaxs ); - - return engine->CheckBoxInPVS( vecSurroundMins, vecSurroundMaxs, pvs, sizeof( pvs ) ); -} - -void CChangeLevel::NotifyEntitiesOutOfTransition() -{ - CBaseEntity *pEnt = gEntList.FirstEnt(); - while ( pEnt ) - { - // Found the landmark - if ( pEnt->ObjectCaps() & FCAP_NOTIFY_ON_TRANSITION ) - { - variant_t emptyVariant; - if ( !(pEnt->ObjectCaps() & (FCAP_ACROSS_TRANSITION|FCAP_FORCE_TRANSITION)) || !IsEntityInTransition( pEnt ) ) - { - pEnt->AcceptInput( "OutsideTransition", this, this, emptyVariant, 0 ); - } - else - { - pEnt->AcceptInput( "InsideTransition", this, this, emptyVariant, 0 ); - } - } - pEnt = gEntList.NextEnt( pEnt ); - } -} - -//------------------------------------------------------------------------------ -// Purpose : Checks all spawned AIs and prints a warning if any are actively leading -// Input : -// Output : -//------------------------------------------------------------------------------ -void CChangeLevel::WarnAboutActiveLead( void ) -{ - int i; - CAI_BaseNPC * ai; - CAI_BehaviorBase * behavior; - - for ( i = 0; i < g_AI_Manager.NumAIs(); i++ ) - { - ai = g_AI_Manager.AccessAIs()[i]; - behavior = ai->GetRunningBehavior(); - if ( behavior ) - { - if ( dynamic_cast( behavior ) ) - { - Warning( "Entity '%s' is still actively leading\n", STRING( ai->GetEntityName() ) ); - } - } - } -} - -void CChangeLevel::ChangeLevelNow( CBaseEntity *pActivator ) -{ - CBaseEntity *pLandmark; - - Assert(!FStrEq(m_szMapName, "")); - - // Don't work in deathmatch - if ( g_pGameRules->IsDeathmatch() ) - return; - - // Some people are firing these multiple times in a frame, disable - if ( m_bTouched ) - return; - - m_bTouched = true; - - CBaseEntity *pPlayer = (pActivator && pActivator->IsPlayer()) ? pActivator : UTIL_GetLocalPlayer(); - - int transitionState = InTransitionVolume(pPlayer, m_szLandmarkName); - if ( transitionState == TRANSITION_VOLUME_SCREENED_OUT ) - { - DevMsg( 2, "Player isn't in the transition volume %s, aborting\n", m_szLandmarkName ); - return; - } - - // look for a landmark entity - pLandmark = FindLandmark( m_szLandmarkName ); - - if ( !pLandmark ) - return; - - // no transition volumes, check PVS of landmark - if ( transitionState == TRANSITION_VOLUME_NOT_FOUND ) - { - byte pvs[MAX_MAP_CLUSTERS/8]; - int clusterIndex = engine->GetClusterForOrigin( pLandmark->GetAbsOrigin() ); - engine->GetPVSForCluster( clusterIndex, sizeof(pvs), pvs ); - if ( pPlayer ) - { - Vector vecSurroundMins, vecSurroundMaxs; - pPlayer->CollisionProp()->WorldSpaceSurroundingBounds( &vecSurroundMins, &vecSurroundMaxs ); - bool playerInPVS = engine->CheckBoxInPVS( vecSurroundMins, vecSurroundMaxs, pvs, sizeof( pvs ) ); - - //Assert( playerInPVS ); - if ( !playerInPVS ) - { - Warning( "Player isn't in the landmark's (%s) PVS, aborting\n", m_szLandmarkName ); -#ifndef HL1_DLL - // HL1 works even with these errors! - return; -#endif - } - } - } - - WarnAboutActiveLead(); - - g_iDebuggingTransition = 0; - st_szNextSpot[0] = 0; // Init landmark to NULL - Q_strncpy(st_szNextSpot, m_szLandmarkName,sizeof(st_szNextSpot)); - // This object will get removed in the call to engine->ChangeLevel, copy the params into "safe" memory - Q_strncpy(st_szNextMap, m_szMapName, sizeof(st_szNextMap)); - - m_hActivator = pActivator; - - m_OnChangeLevel.FireOutput(pActivator, this); - - NotifyEntitiesOutOfTransition(); - - -//// Msg( "Level touches %d levels\n", ChangeList( levels, 16 ) ); - if ( g_debug_transitions.GetInt() ) - { - Msg( "CHANGE LEVEL: %s %s\n", st_szNextMap, st_szNextSpot ); - } - - // If we're debugging, don't actually change level - if ( g_debug_transitions.GetInt() == 0 ) - { - engine->ChangeLevel( st_szNextMap, st_szNextSpot ); - } - else - { - // Build a change list so we can see what would be transitioning - CSaveRestoreData *pSaveData = SaveInit( 0 ); - if ( pSaveData ) - { - g_pGameSaveRestoreBlockSet->PreSave( pSaveData ); - pSaveData->levelInfo.connectionCount = BuildChangeList( pSaveData->levelInfo.levelList, MAX_LEVEL_CONNECTIONS ); - g_pGameSaveRestoreBlockSet->PostSave(); - } - - SetTouch( NULL ); - } -} - -// -// GLOBALS ASSUMED SET: st_szNextMap -// -void CChangeLevel::TouchChangeLevel( CBaseEntity *pOther ) -{ - CBasePlayer *pPlayer = ToBasePlayer(pOther); - if ( !pPlayer ) - return; - - if( pPlayer->IsSinglePlayerGameEnding() ) - { - // Some semblance of deceleration, but allow player to fall normally. - // Also, disable controls. - Vector vecVelocity = pPlayer->GetAbsVelocity(); - vecVelocity.x *= 0.5f; - vecVelocity.y *= 0.5f; - pPlayer->SetAbsVelocity( vecVelocity ); - pPlayer->AddFlag( FL_FROZEN ); - return; - } - - if ( !pPlayer->IsInAVehicle() && pPlayer->GetMoveType() == MOVETYPE_NOCLIP ) - { - DevMsg("In level transition: %s %s\n", st_szNextMap, st_szNextSpot ); - return; - } - - ChangeLevelNow( pOther ); -} - - -// Add a transition to the list, but ignore duplicates -// (a designer may have placed multiple trigger_changelevels with the same landmark) -int CChangeLevel::AddTransitionToList( levellist_t *pLevelList, int listCount, const char *pMapName, const char *pLandmarkName, edict_t *pentLandmark ) -{ - int i; - - if ( !pLevelList || !pMapName || !pLandmarkName || !pentLandmark ) - return 0; - - // Ignore changelevels to the level we're ready in. Mapmakers love to do this! - if ( stricmp( pMapName, STRING(gpGlobals->mapname) ) == 0 ) - return 0; - - for ( i = 0; i < listCount; i++ ) - { - if ( pLevelList[i].pentLandmark == pentLandmark && stricmp( pLevelList[i].mapName, pMapName ) == 0 ) - return 0; - } - Q_strncpy( pLevelList[listCount].mapName, pMapName, sizeof(pLevelList[listCount].mapName) ); - Q_strncpy( pLevelList[listCount].landmarkName, pLandmarkName, sizeof(pLevelList[listCount].landmarkName) ); - pLevelList[listCount].pentLandmark = pentLandmark; - - CBaseEntity *ent = CBaseEntity::Instance( pentLandmark ); - Assert( ent ); - - pLevelList[listCount].vecLandmarkOrigin = ent->GetAbsOrigin(); - - return 1; -} - -int BuildChangeList( levellist_t *pLevelList, int maxList ) -{ - return CChangeLevel::ChangeList( pLevelList, maxList ); -} - -struct collidelist_t -{ - const CPhysCollide *pCollide; - Vector origin; - QAngle angles; -}; - - -// NOTE: This routine is relatively slow. If you need to use it for per-frame work, consider that fact. -// UNDONE: Expand this to the full matrix of solid types on each side and move into enginetrace -static bool TestEntityTriggerIntersection_Accurate( CBaseEntity *pTrigger, CBaseEntity *pEntity ) -{ - Assert( pTrigger->GetSolid() == SOLID_BSP ); - - if ( pTrigger->Intersects( pEntity ) ) // It touches one, it's in the volume - { - switch ( pEntity->GetSolid() ) - { - case SOLID_BBOX: - { - ICollideable *pCollide = pTrigger->CollisionProp(); - Ray_t ray; - trace_t tr; - ray.Init( pEntity->GetAbsOrigin(), pEntity->GetAbsOrigin(), pEntity->WorldAlignMins(), pEntity->WorldAlignMaxs() ); - enginetrace->ClipRayToCollideable( ray, MASK_ALL, pCollide, &tr ); - - if ( tr.startsolid ) - return true; - } - break; - case SOLID_BSP: - case SOLID_VPHYSICS: - { - CPhysCollide *pTriggerCollide = modelinfo->GetVCollide( pTrigger->GetModelIndex() )->solids[0]; - Assert( pTriggerCollide ); - - CUtlVector collideList; - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int physicsCount = pEntity->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - if ( physicsCount ) - { - for ( int i = 0; i < physicsCount; i++ ) - { - const CPhysCollide *pCollide = pList[i]->GetCollide(); - if ( pCollide ) - { - collidelist_t element; - element.pCollide = pCollide; - pList[i]->GetPosition( &element.origin, &element.angles ); - collideList.AddToTail( element ); - } - } - } - else - { - vcollide_t *pVCollide = modelinfo->GetVCollide( pEntity->GetModelIndex() ); - if ( pVCollide && pVCollide->solidCount ) - { - collidelist_t element; - element.pCollide = pVCollide->solids[0]; - element.origin = pEntity->GetAbsOrigin(); - element.angles = pEntity->GetAbsAngles(); - collideList.AddToTail( element ); - } - } - for ( int i = collideList.Count()-1; i >= 0; --i ) - { - const collidelist_t &element = collideList[i]; - trace_t tr; - physcollision->TraceCollide( element.origin, element.origin, element.pCollide, element.angles, pTriggerCollide, pTrigger->GetAbsOrigin(), pTrigger->GetAbsAngles(), &tr ); - if ( tr.startsolid ) - return true; - } - } - break; - - default: - return true; - } - } - return false; -} - -int CChangeLevel::InTransitionVolume( CBaseEntity *pEntity, const char *pVolumeName ) -{ - CBaseEntity *pVolume; - - if ( pEntity->ObjectCaps() & FCAP_FORCE_TRANSITION ) - return TRANSITION_VOLUME_PASSED; - - // If you're following another entity, follow it through the transition (weapons follow the player) - pEntity = pEntity->GetRootMoveParent(); - - int inVolume = TRANSITION_VOLUME_NOT_FOUND; // Unless we find a trigger_transition, everything is in the volume - - pVolume = gEntList.FindEntityByName( NULL, pVolumeName ); - while ( pVolume ) - { - if ( pVolume && FClassnameIs( pVolume, "trigger_transition" ) ) - { - if ( TestEntityTriggerIntersection_Accurate(pVolume, pEntity ) ) // It touches one, it's in the volume - return TRANSITION_VOLUME_PASSED; - - inVolume = TRANSITION_VOLUME_SCREENED_OUT; // Found a trigger_transition, but I don't intersect it -- if I don't find another, don't go! - } - pVolume = gEntList.FindEntityByName( pVolume, pVolumeName ); - } - return inVolume; -} - - -//------------------------------------------------------------------------------ -// Builds the list of entities to save when moving across a transition -//------------------------------------------------------------------------------ -int CChangeLevel::BuildChangeLevelList( levellist_t *pLevelList, int maxList ) -{ - int nCount = 0; - - CBaseEntity *pentChangelevel = gEntList.FindEntityByClassname( NULL, "trigger_changelevel" ); - while ( pentChangelevel ) - { - CChangeLevel *pTrigger = dynamic_cast(pentChangelevel); - if ( pTrigger ) - { - // Find the corresponding landmark - CBaseEntity *pentLandmark = FindLandmark( pTrigger->m_szLandmarkName ); - if ( pentLandmark ) - { - // Build a list of unique transitions - if ( AddTransitionToList( pLevelList, nCount, pTrigger->m_szMapName, pTrigger->m_szLandmarkName, pentLandmark->edict() ) ) - { - ++nCount; - if ( nCount >= maxList ) // FULL!! - break; - } - } - } - pentChangelevel = gEntList.FindEntityByClassname( pentChangelevel, "trigger_changelevel" ); - } - - return nCount; -} - - -//------------------------------------------------------------------------------ -// Adds a single entity to the transition list, if appropriate. Returns the new count -//------------------------------------------------------------------------------ -int CChangeLevel::ComputeEntitySaveFlags( CBaseEntity *pEntity ) -{ - if ( g_iDebuggingTransition == DEBUG_TRANSITIONS_VERBOSE ) - { - Msg( "Trying %s (%s): ", pEntity->GetClassname(), pEntity->GetDebugName() ); - } - - int caps = pEntity->ObjectCaps(); - if ( caps & FCAP_DONT_SAVE ) - { - if ( g_iDebuggingTransition == DEBUG_TRANSITIONS_VERBOSE ) - { - Msg( "IGNORED due to being marked \"Don't save\".\n" ); - } - return 0; - } - - // If this entity can be moved or is global, mark it - int flags = 0; - if ( caps & FCAP_ACROSS_TRANSITION ) - { - flags |= FENTTABLE_MOVEABLE; - } - if ( pEntity->m_iGlobalname != NULL_STRING && !pEntity->IsDormant() ) - { - flags |= FENTTABLE_GLOBAL; - } - - if ( g_iDebuggingTransition == DEBUG_TRANSITIONS_VERBOSE && !flags ) - { - Msg( "IGNORED, no across_transition flag & no globalname\n" ); - } - - return flags; -} - - -//------------------------------------------------------------------------------ -// Adds a single entity to the transition list, if appropriate. Returns the new count -//------------------------------------------------------------------------------ -inline int CChangeLevel::AddEntityToTransitionList( CBaseEntity *pEntity, int flags, int nCount, CBaseEntity **ppEntList, int *pEntityFlags ) -{ - ppEntList[ nCount ] = pEntity; - pEntityFlags[ nCount ] = flags; - ++nCount; - - // If we're debugging, make it visible - if ( g_iDebuggingTransition ) - { - if ( g_iDebuggingTransition == DEBUG_TRANSITIONS_VERBOSE ) - { - // In verbose mode we've already printed out what the entity is - Msg("ADDED.\n"); - } - else - { - // In non-verbose mode, we just print this line - Msg( "ADDED %s (%s) to transition.\n", pEntity->GetClassname(), pEntity->GetDebugName() ); - } - - pEntity->m_debugOverlays |= (OVERLAY_BBOX_BIT | OVERLAY_NAME_BIT); - } - - return nCount; -} - - -//------------------------------------------------------------------------------ -// Builds the list of entities to bring across a particular transition -//------------------------------------------------------------------------------ -int CChangeLevel::BuildEntityTransitionList( CBaseEntity *pLandmarkEntity, const char *pLandmarkName, - CBaseEntity **ppEntList, int *pEntityFlags, int nMaxList ) -{ - int iEntity = 0; - - // Only show debug for the transition to the level we're going to - if ( g_debug_transitions.GetInt() && pLandmarkEntity->NameMatches(st_szNextSpot) ) - { - g_iDebuggingTransition = g_debug_transitions.GetInt(); - - // Show us where the landmark entity is - pLandmarkEntity->m_debugOverlays |= (OVERLAY_PIVOT_BIT | OVERLAY_BBOX_BIT | OVERLAY_NAME_BIT); - } - else - { - g_iDebuggingTransition = 0; - } - - // Follow the linked list of entities in the PVS of the transition landmark - CBaseEntity *pEntity = NULL; - while ( (pEntity = UTIL_EntitiesInPVS( pLandmarkEntity, pEntity)) != NULL ) - { - int flags = ComputeEntitySaveFlags( pEntity ); - if ( !flags ) - continue; - - // Check to make sure the entity isn't screened out by a trigger_transition - if ( !InTransitionVolume( pEntity, pLandmarkName ) ) - { - if ( g_iDebuggingTransition == DEBUG_TRANSITIONS_VERBOSE ) - { - Msg( "IGNORED, outside transition volume.\n" ); - } - continue; - } - - if ( iEntity >= nMaxList ) - { - Warning( "Too many entities across a transition!\n" ); - Assert( 0 ); - return iEntity; - } - - iEntity = AddEntityToTransitionList( pEntity, flags, iEntity, ppEntList, pEntityFlags ); - } - - return iEntity; -} - - -//------------------------------------------------------------------------------ -// Tests bits in a bitfield -//------------------------------------------------------------------------------ -static inline bool IsBitSet( char *pBuf, int nBit ) -{ - return (pBuf[ nBit >> 3 ] & ( 1 << (nBit & 0x7) )) != 0; -} - -static inline void Set( char *pBuf, int nBit ) -{ - pBuf[ nBit >> 3 ] |= 1 << (nBit & 0x7); -} - - -//------------------------------------------------------------------------------ -// Adds in all entities depended on by entities near the transition -//------------------------------------------------------------------------------ -#define MAX_ENTITY_BYTE_COUNT (NUM_ENT_ENTRIES >> 3) -int CChangeLevel::AddDependentEntities( int nCount, CBaseEntity **ppEntList, int *pEntityFlags, int nMaxList ) -{ - char pEntitiesSaved[MAX_ENTITY_BYTE_COUNT]; - memset( pEntitiesSaved, 0, MAX_ENTITY_BYTE_COUNT * sizeof(char) ); - - // Populate the initial bitfield - int i; - for ( i = 0; i < nCount; ++i ) - { - // NOTE: Must use GetEntryIndex because we're saving non-networked entities - int nEntIndex = ppEntList[i]->GetRefEHandle().GetEntryIndex(); - - // We shouldn't already have this entity in the list! - Assert( !IsBitSet( pEntitiesSaved, nEntIndex ) ); - - // Mark the entity as being in the list - Set( pEntitiesSaved, nEntIndex ); - } - - IEntitySaveUtils *pSaveUtils = GetEntitySaveUtils(); - - // Iterate over entities whose dependencies we've not yet processed - // NOTE: nCount will change value during this loop in AddEntityToTransitionList - for ( i = 0; i < nCount; ++i ) - { - CBaseEntity *pEntity = ppEntList[i]; - - // Find dependencies in the hash. - int nDepCount = pSaveUtils->GetEntityDependencyCount( pEntity ); - if ( !nDepCount ) - continue; - - CBaseEntity **ppDependentEntities = (CBaseEntity**)stackalloc( nDepCount * sizeof(CBaseEntity*) ); - pSaveUtils->GetEntityDependencies( pEntity, nDepCount, ppDependentEntities ); - for ( int j = 0; j < nDepCount; ++j ) - { - CBaseEntity *pDependent = ppDependentEntities[j]; - if ( !pDependent ) - continue; - - // NOTE: Must use GetEntryIndex because we're saving non-networked entities - int nEntIndex = pDependent->GetRefEHandle().GetEntryIndex(); - - // Don't re-add it if it's already in the list - if ( IsBitSet( pEntitiesSaved, nEntIndex ) ) - continue; - - // Mark the entity as being in the list - Set( pEntitiesSaved, nEntIndex ); - - int flags = ComputeEntitySaveFlags( pEntity ); - if ( flags ) - { - if ( nCount >= nMaxList ) - { - Warning( "Too many entities across a transition!\n" ); - Assert( 0 ); - return false; - } - - if ( g_debug_transitions.GetInt() ) - { - Msg( "ADDED DEPENDANCY: %s (%s)\n", pEntity->GetClassname(), pEntity->GetDebugName() ); - } - - nCount = AddEntityToTransitionList( pEntity, flags, nCount, ppEntList, pEntityFlags ); - } - else - { - Warning("Warning!! Save dependency is linked to an entity that doesn't want to be saved!\n"); - } - } - } - - return nCount; -} - - -//------------------------------------------------------------------------------ -// This builds the list of all transitions on this level and which entities -// are in their PVS's and can / should be moved across. -//------------------------------------------------------------------------------ - -// We can only ever move 512 entities across a transition -#define MAX_ENTITY 512 - -// FIXME: This has grown into a complicated beast. Can we make this more elegant? -int CChangeLevel::ChangeList( levellist_t *pLevelList, int maxList ) -{ - // Find all of the possible level changes on this BSP - int count = BuildChangeLevelList( pLevelList, maxList ); - - if ( !gpGlobals->pSaveData || ( static_cast(gpGlobals->pSaveData)->NumEntities() == 0 ) ) - return count; - - CSave saveHelper( static_cast(gpGlobals->pSaveData) ); - - // For each level change, find nearby entities and save them - int i; - for ( i = 0; i < count; i++ ) - { - CBaseEntity *pEntList[ MAX_ENTITY ]; - int entityFlags[ MAX_ENTITY ]; - - // First, figure out which entities are near the transition - CBaseEntity *pLandmarkEntity = CBaseEntity::Instance( pLevelList[i].pentLandmark ); - int iEntity = BuildEntityTransitionList( pLandmarkEntity, pLevelList[i].landmarkName, pEntList, entityFlags, MAX_ENTITY ); - - // FIXME: Activate if we have a dependency problem on level transition - // Next, add in all entities depended on by entities near the transition -// iEntity = AddDependentEntities( iEntity, pEntList, entityFlags, MAX_ENTITY ); - - int j; - for ( j = 0; j < iEntity; j++ ) - { - // Mark entity table with 1<IsSolid() || (pOther->GetMoveType() == MOVETYPE_PUSH || pOther->GetMoveType() == MOVETYPE_NONE ) ) - return; - - if (!PassesTriggerFilters(pOther)) - return; - - // FIXME: If something is hierarchically attached, should we try to push the parent? - if (pOther->GetMoveParent()) - return; - - // Transform the push dir into global space - Vector vecAbsDir; - VectorRotate( m_vecPushDir, EntityToWorldTransform(), vecAbsDir ); - - // Instant trigger, just transfer velocity and remove - if (HasSpawnFlags(SF_TRIG_PUSH_ONCE)) - { - pOther->ApplyAbsVelocityImpulse( m_flPushSpeed * vecAbsDir ); - - if ( vecAbsDir.z > 0 ) - { - pOther->SetGroundEntity( NULL ); - } - UTIL_Remove( this ); - return; - } - - switch( pOther->GetMoveType() ) - { - case MOVETYPE_NONE: - case MOVETYPE_PUSH: - case MOVETYPE_NOCLIP: - break; - - case MOVETYPE_VPHYSICS: - { - IPhysicsObject *pPhys = pOther->VPhysicsGetObject(); - if ( pPhys ) - { - // UNDONE: Assume the velocity is for a 100kg object, scale with mass - pPhys->ApplyForceCenter( m_flPushSpeed * vecAbsDir * 100.0f * gpGlobals->frametime ); - return; - } - } - break; - - default: - { -#if defined( HL2_DLL ) - // HACK HACK HL2 players on ladders will only be disengaged if the sf is set, otherwise no push occurs. - if ( pOther->IsPlayer() && - pOther->GetMoveType() == MOVETYPE_LADDER ) - { - if ( !HasSpawnFlags(SF_TRIG_PUSH_AFFECT_PLAYER_ON_LADDER) ) - { - // Ignore the push - return; - } - } -#endif - - Vector vecPush = (m_flPushSpeed * vecAbsDir); - if ( pOther->GetFlags() & FL_BASEVELOCITY ) - { - vecPush = vecPush + pOther->GetBaseVelocity(); - } - if ( vecPush.z > 0 && (pOther->GetFlags() & FL_ONGROUND) ) - { - pOther->SetGroundEntity( NULL ); - Vector origin = pOther->GetAbsOrigin(); - origin.z += 1.0f; - pOther->SetAbsOrigin( origin ); - } - -#ifdef HL1_DLL - // Apply the z velocity as a force so it counteracts gravity properly - Vector vecImpulse( 0, 0, vecPush.z * 0.025 );//magic hack number - - pOther->ApplyAbsVelocityImpulse( vecImpulse ); - - // apply x, y as a base velocity so we travel at constant speed on conveyors - vecPush.z = 0; -#endif - - pOther->SetBaseVelocity( vecPush ); - pOther->AddFlag( FL_BASEVELOCITY ); - } - break; - } -} - - -//----------------------------------------------------------------------------- -// Teleport trigger -//----------------------------------------------------------------------------- -const int SF_TELEPORT_PRESERVE_ANGLES = 0x20; // Preserve angles even when a local landmark is not specified - -class CTriggerTeleport : public CBaseTrigger -{ -public: - DECLARE_CLASS( CTriggerTeleport, CBaseTrigger ); - - void Spawn( void ); - void Touch( CBaseEntity *pOther ); - - string_t m_iLandmark; - - DECLARE_DATADESC(); -}; - -LINK_ENTITY_TO_CLASS( trigger_teleport, CTriggerTeleport ); - -BEGIN_DATADESC( CTriggerTeleport ) - - DEFINE_KEYFIELD( m_iLandmark, FIELD_STRING, "landmark" ), - -END_DATADESC() - - - -void CTriggerTeleport::Spawn( void ) -{ - InitTrigger(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Teleports the entity that touched us to the location of our target, -// setting the toucher's angles to our target's angles if they are a -// player. -// -// If a landmark was specified, the toucher is offset from the target -// by their initial offset from the landmark and their angles are -// left alone. -// -// Input : pOther - The entity that touched us. -//----------------------------------------------------------------------------- -void CTriggerTeleport::Touch( CBaseEntity *pOther ) -{ - CBaseEntity *pentTarget = NULL; - - if (!PassesTriggerFilters(pOther)) - { - return; - } - - // The activator and caller are the same - pentTarget = gEntList.FindEntityByName( pentTarget, m_target, NULL, pOther, pOther ); - if (!pentTarget) - { - return; - } - - // - // If a landmark was specified, offset the player relative to the landmark. - // - CBaseEntity *pentLandmark = NULL; - Vector vecLandmarkOffset(0, 0, 0); - if (m_iLandmark != NULL_STRING) - { - // The activator and caller are the same - pentLandmark = gEntList.FindEntityByName(pentLandmark, m_iLandmark, NULL, pOther, pOther ); - if (pentLandmark) - { - vecLandmarkOffset = pOther->GetAbsOrigin() - pentLandmark->GetAbsOrigin(); - } - } - - pOther->SetGroundEntity( NULL ); - - Vector tmp = pentTarget->GetAbsOrigin(); - - if (!pentLandmark && pOther->IsPlayer()) - { - // make origin adjustments in case the teleportee is a player. (origin in center, not at feet) - tmp.z -= pOther->WorldAlignMins().z; - } - - // - // Only modify the toucher's angles and zero their velocity if no landmark was specified. - // - const QAngle *pAngles = NULL; - Vector *pVelocity = NULL; - -#ifdef HL1_DLL - Vector vecZero(0,0,0); -#endif - - if (!pentLandmark && !HasSpawnFlags(SF_TELEPORT_PRESERVE_ANGLES) ) - { - pAngles = &pentTarget->GetAbsAngles(); - -#ifdef HL1_DLL - pVelocity = &vecZero; -#else - pVelocity = NULL; //BUGBUG - This does not set the player's velocity to zero!!! -#endif - } - - tmp += vecLandmarkOffset; - pOther->Teleport( &tmp, pAngles, pVelocity ); -} - - -LINK_ENTITY_TO_CLASS( info_teleport_destination, CPointEntity ); - - -//----------------------------------------------------------------------------- -// Purpose: Saves the game when the player touches the trigger. Can be enabled or disabled -//----------------------------------------------------------------------------- -class CTriggerToggleSave : public CBaseTrigger -{ -public: - DECLARE_CLASS( CTriggerToggleSave, CBaseTrigger ); - - void Spawn( void ); - void Touch( CBaseEntity *pOther ); - - void InputEnable( inputdata_t &inputdata ) - { - m_bDisabled = false; - } - - void InputDisable( inputdata_t &inputdata ) - { - m_bDisabled = true; - } - - bool m_bDisabled; // Initial state - - DECLARE_DATADESC(); -}; - -BEGIN_DATADESC( CTriggerToggleSave ) - DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), -END_DATADESC() - -LINK_ENTITY_TO_CLASS( trigger_togglesave, CTriggerToggleSave ); - - -//----------------------------------------------------------------------------- -// Purpose: Called when spawning, after keyvalues have been set. -//----------------------------------------------------------------------------- -void CTriggerToggleSave::Spawn( void ) -{ - if ( g_pGameRules->IsDeathmatch() ) - { - UTIL_Remove( this ); - return; - } - - InitTrigger(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Performs the autosave when the player touches us. -// Input : pOther - -//----------------------------------------------------------------------------- -void CTriggerToggleSave::Touch( CBaseEntity *pOther ) -{ - if( m_bDisabled ) - return; - - // Only save on clients - if ( !pOther->IsPlayer() ) - return; - - // Can be re-enabled - m_bDisabled = true; - - engine->ServerCommand( "autosave\n" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Saves the game when the player touches the trigger. -//----------------------------------------------------------------------------- -class CTriggerSave : public CBaseTrigger -{ -public: - DECLARE_CLASS( CTriggerSave, CBaseTrigger ); - - void Spawn( void ); - void Touch( CBaseEntity *pOther ); - DECLARE_DATADESC(); - - bool m_bForceNewLevelUnit; - float m_fDangerousTimer; - int m_minHitPoints; -}; - - -BEGIN_DATADESC( CTriggerSave ) - - DEFINE_KEYFIELD( m_bForceNewLevelUnit, FIELD_BOOLEAN, "NewLevelUnit" ), - DEFINE_KEYFIELD( m_minHitPoints, FIELD_INTEGER, "MinimumHitPoints" ), - DEFINE_KEYFIELD( m_fDangerousTimer, FIELD_FLOAT, "DangerousTimer" ), - -END_DATADESC() -LINK_ENTITY_TO_CLASS( trigger_autosave, CTriggerSave ); - - -//----------------------------------------------------------------------------- -// Purpose: Called when spawning, after keyvalues have been set. -//----------------------------------------------------------------------------- -void CTriggerSave::Spawn( void ) -{ - if ( g_pGameRules->IsDeathmatch() ) - { - UTIL_Remove( this ); - return; - } - - InitTrigger(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Performs the autosave when the player touches us. -// Input : pOther - -//----------------------------------------------------------------------------- -void CTriggerSave::Touch( CBaseEntity *pOther ) -{ - // Only save on clients - if ( !pOther->IsPlayer() ) - return; - - if ( m_fDangerousTimer != 0.0f ) - { - if ( g_ServerGameDLL.m_fAutoSaveDangerousTime != 0.0f && g_ServerGameDLL.m_fAutoSaveDangerousTime >= gpGlobals->curtime ) - { - // A previous dangerous auto save was waiting to become safe - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); - - if ( pPlayer->GetDeathTime() == 0.0f || pPlayer->GetDeathTime() > gpGlobals->curtime ) - { - // The player isn't dead, so make the dangerous auto save safe - engine->ServerCommand( "autosavedangerousissafe\n" ); - } - } - } - - // this is a one-way transition - there is no way to return to the previous map. - if ( m_bForceNewLevelUnit ) - { - engine->ClearSaveDir(); - } - UTIL_Remove( this ); - - if ( m_fDangerousTimer != 0.0f ) - { - // There's a dangerous timer. Save if we have enough hitpoints. - CBasePlayer *pPlayer = UTIL_PlayerByIndex( 1 ); - - if (pPlayer && pPlayer->GetHealth() >= m_minHitPoints) - { - engine->ServerCommand( "autosavedangerous\n" ); - g_ServerGameDLL.m_fAutoSaveDangerousTime = gpGlobals->curtime + m_fDangerousTimer; - } - } - else - { - engine->ServerCommand( "autosave\n" ); - } -} - - -class CTriggerGravity : public CBaseTrigger -{ -public: - DECLARE_CLASS( CTriggerGravity, CBaseTrigger ); - DECLARE_DATADESC(); - - void Spawn( void ); - void GravityTouch( CBaseEntity *pOther ); -}; -LINK_ENTITY_TO_CLASS( trigger_gravity, CTriggerGravity ); - -BEGIN_DATADESC( CTriggerGravity ) - - // Function Pointers - DEFINE_FUNCTION(GravityTouch), - -END_DATADESC() - -void CTriggerGravity::Spawn( void ) -{ - BaseClass::Spawn(); - InitTrigger(); - SetTouch( &CTriggerGravity::GravityTouch ); -} - -void CTriggerGravity::GravityTouch( CBaseEntity *pOther ) -{ - // Only save on clients - if ( !pOther->IsPlayer() ) - return; - - pOther->SetGravity( GetGravity() ); -} - - -// this is a really bad idea. -class CAI_ChangeTarget : public CBaseEntity -{ -public: - DECLARE_CLASS( CAI_ChangeTarget, CBaseEntity ); - - // Input handlers. - void InputActivate( inputdata_t &inputdata ); - - int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } - - DECLARE_DATADESC(); - -private: - string_t m_iszNewTarget; -}; -LINK_ENTITY_TO_CLASS( ai_changetarget, CAI_ChangeTarget ); - -BEGIN_DATADESC( CAI_ChangeTarget ) - - DEFINE_KEYFIELD( m_iszNewTarget, FIELD_STRING, "m_iszNewTarget" ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ), - -END_DATADESC() - - -void CAI_ChangeTarget::InputActivate( inputdata_t &inputdata ) -{ - CBaseEntity *pTarget = NULL; - - while ((pTarget = gEntList.FindEntityByName( pTarget, m_target, NULL, inputdata.pActivator, inputdata.pCaller )) != NULL) - { - pTarget->m_target = m_iszNewTarget; - CAI_BaseNPC *pNPC = pTarget->MyNPCPointer( ); - if (pNPC) - { - pNPC->SetGoalEnt( NULL ); - } - } -} - - - - - - - - -//----------------------------------------------------------------------------- -// Purpose: Change an NPC's hint group to something new -//----------------------------------------------------------------------------- -class CAI_ChangeHintGroup : public CBaseEntity -{ -public: - DECLARE_CLASS( CAI_ChangeHintGroup, CBaseEntity ); - - int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } - - // Input handlers. - void InputActivate( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - -private: - CAI_BaseNPC *FindQualifiedNPC( CAI_BaseNPC *pPrev, CBaseEntity *pActivator, CBaseEntity *pCaller ); - - int m_iSearchType; - string_t m_strSearchName; - string_t m_strNewHintGroup; - float m_flRadius; - bool m_bHintGroupNavLimiting; -}; -LINK_ENTITY_TO_CLASS( ai_changehintgroup, CAI_ChangeHintGroup ); - -BEGIN_DATADESC( CAI_ChangeHintGroup ) - - DEFINE_KEYFIELD( m_iSearchType, FIELD_INTEGER, "SearchType" ), - DEFINE_KEYFIELD( m_strSearchName, FIELD_STRING, "SearchName" ), - DEFINE_KEYFIELD( m_strNewHintGroup, FIELD_STRING, "NewHintGroup" ), - DEFINE_KEYFIELD( m_flRadius, FIELD_FLOAT, "Radius" ), - DEFINE_KEYFIELD( m_bHintGroupNavLimiting, FIELD_BOOLEAN, "hintlimiting" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ), - -END_DATADESC() - -CAI_BaseNPC *CAI_ChangeHintGroup::FindQualifiedNPC( CAI_BaseNPC *pPrev, CBaseEntity *pActivator, CBaseEntity *pCaller ) -{ - CBaseEntity *pEntity = pPrev; - CAI_BaseNPC *pResult = NULL; - const char *pszSearchName = STRING(m_strSearchName); - while ( !pResult ) - { - // Find a candidate - switch ( m_iSearchType ) - { - case 0: - { - pEntity = gEntList.FindEntityByNameWithin( pEntity, pszSearchName, GetLocalOrigin(), m_flRadius, NULL, pActivator, pCaller ); - break; - } - - case 1: - { - pEntity = gEntList.FindEntityByClassnameWithin( pEntity, pszSearchName, GetLocalOrigin(), m_flRadius ); - break; - } - - case 2: - { - pEntity = gEntList.FindEntityInSphere( pEntity, GetLocalOrigin(), ( m_flRadius != 0.0 ) ? m_flRadius : FLT_MAX ); - break; - } - } - - if ( !pEntity ) - return NULL; - - // Qualify - pResult = pEntity->MyNPCPointer(); - if ( pResult && m_iSearchType == 2 && (!FStrEq( STRING(pResult->GetHintGroup()), pszSearchName ) ) ) - { - pResult = NULL; - } - } - - return pResult; -} - -void CAI_ChangeHintGroup::InputActivate( inputdata_t &inputdata ) -{ - CAI_BaseNPC *pTarget = NULL; - - while((pTarget = FindQualifiedNPC( pTarget, inputdata.pActivator, inputdata.pCaller )) != NULL) - { - pTarget->SetHintGroup( m_strNewHintGroup, m_bHintGroupNavLimiting ); - } -} - - - - -#define SF_CAMERA_PLAYER_POSITION 1 -#define SF_CAMERA_PLAYER_TARGET 2 -#define SF_CAMERA_PLAYER_TAKECONTROL 4 -#define SF_CAMERA_PLAYER_INFINITE_WAIT 8 -#define SF_CAMERA_PLAYER_SNAP_TO 16 -#define SF_CAMERA_PLAYER_NOT_SOLID 32 -#define SF_CAMERA_PLAYER_INTERRUPT 64 - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CTriggerCamera : public CBaseEntity -{ -public: - DECLARE_CLASS( CTriggerCamera, CBaseEntity ); - - void Spawn( void ); - bool KeyValue( const char *szKeyName, const char *szValue ); - void Enable( void ); - void Disable( void ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - void FollowTarget( void ); - void Move(void); - - // Always transmit to clients so they know where to move the view to - virtual int UpdateTransmitState(); - - DECLARE_DATADESC(); - - // Input handlers - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - -private: - EHANDLE m_hPlayer; - EHANDLE m_hTarget; - - // used for moving the camera along a path (rail rides) - CBaseEntity *m_pPath; - string_t m_sPath; - float m_flWait; - float m_flReturnTime; - float m_flStopTime; - float m_moveDistance; - float m_targetSpeed; - float m_initialSpeed; - float m_acceleration; - float m_deceleration; - int m_state; - Vector m_vecMoveDir; - - - string_t m_iszTargetAttachment; - int m_iAttachmentIndex; - bool m_bSnapToGoal; - -#if HL2_EPISODIC - bool m_bInterpolatePosition; - - // these are interpolation vars used for interpolating the camera over time - Vector m_vStartPos, m_vEndPos; - float m_flInterpStartTime; - - const static float kflPosInterpTime; // seconds -#endif - - int m_nPlayerButtons; - int m_nOldTakeDamage; - -private: - COutputEvent m_OnEndFollow; -}; - -#if HL2_EPISODIC -const float CTriggerCamera::kflPosInterpTime = 2.0f; -#endif - -LINK_ENTITY_TO_CLASS( point_viewcontrol, CTriggerCamera ); - -BEGIN_DATADESC( CTriggerCamera ) - - DEFINE_FIELD( m_hPlayer, FIELD_EHANDLE ), - DEFINE_FIELD( m_hTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_pPath, FIELD_CLASSPTR ), - DEFINE_FIELD( m_sPath, FIELD_STRING ), - DEFINE_FIELD( m_flWait, FIELD_FLOAT ), - DEFINE_FIELD( m_flReturnTime, FIELD_TIME ), - DEFINE_FIELD( m_flStopTime, FIELD_TIME ), - DEFINE_FIELD( m_moveDistance, FIELD_FLOAT ), - DEFINE_FIELD( m_targetSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_initialSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_acceleration, FIELD_FLOAT ), - DEFINE_FIELD( m_deceleration, FIELD_FLOAT ), - DEFINE_FIELD( m_state, FIELD_INTEGER ), - DEFINE_FIELD( m_vecMoveDir, FIELD_VECTOR ), - DEFINE_KEYFIELD( m_iszTargetAttachment, FIELD_STRING, "targetattachment" ), - DEFINE_FIELD( m_iAttachmentIndex, FIELD_INTEGER ), - DEFINE_FIELD( m_bSnapToGoal, FIELD_BOOLEAN ), -#if HL2_EPISODIC - DEFINE_KEYFIELD( m_bInterpolatePosition, FIELD_BOOLEAN, "interpolatepositiontoplayer" ), - DEFINE_FIELD( m_vStartPos, FIELD_VECTOR ), - DEFINE_FIELD( m_vEndPos, FIELD_VECTOR ), - DEFINE_FIELD( m_flInterpStartTime, FIELD_TIME ), -#endif - DEFINE_FIELD( m_nPlayerButtons, FIELD_INTEGER ), - DEFINE_FIELD( m_nOldTakeDamage, FIELD_INTEGER ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - - // Function Pointers - DEFINE_FUNCTION( FollowTarget ), - DEFINE_OUTPUT( m_OnEndFollow, "OnEndFollow" ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerCamera::Spawn( void ) -{ - BaseClass::Spawn(); - - SetMoveType( MOVETYPE_NOCLIP ); - SetSolid( SOLID_NONE ); // Remove model & collisions - SetRenderColorA( 0 ); // The engine won't draw this model if this is set to 0 and blending is on - m_nRenderMode = kRenderTransTexture; - - m_state = USE_OFF; - - m_initialSpeed = m_flSpeed; - - if ( m_acceleration == 0 ) - m_acceleration = 500; - - if ( m_deceleration == 0 ) - m_deceleration = 500; - - DispatchUpdateTransmitState(); -} - -int CTriggerCamera::UpdateTransmitState() -{ - // always tranmit if currently used by a monitor - if ( m_state == USE_ON ) - { - return SetTransmitState( FL_EDICT_ALWAYS ); - } - else - { - return SetTransmitState( FL_EDICT_DONTSEND ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTriggerCamera::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "wait")) - { - m_flWait = atof(szValue); - } - else if (FStrEq(szKeyName, "moveto")) - { - m_sPath = AllocPooledString( szValue ); - } - else if (FStrEq(szKeyName, "acceleration")) - { - m_acceleration = atof( szValue ); - } - else if (FStrEq(szKeyName, "deceleration")) - { - m_deceleration = atof( szValue ); - } - else - return BaseClass::KeyValue( szKeyName, szValue ); - - return true; -} - -//------------------------------------------------------------------------------ -// Purpose: Input handler to turn on this trigger. -//------------------------------------------------------------------------------ -void CTriggerCamera::InputEnable( inputdata_t &inputdata ) -{ - m_hPlayer = inputdata.pActivator; - Enable(); -} - - -//------------------------------------------------------------------------------ -// Purpose: Input handler to turn off this trigger. -//------------------------------------------------------------------------------ -void CTriggerCamera::InputDisable( inputdata_t &inputdata ) -{ - Disable(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerCamera::Enable( void ) -{ - m_state = USE_ON; - - if ( !m_hPlayer || !m_hPlayer->IsPlayer() ) - { - m_hPlayer = UTIL_GetLocalPlayer(); - } - - if ( !m_hPlayer ) - { - DispatchUpdateTransmitState(); - return; - } - - Assert( m_hPlayer->IsPlayer() ); - CBasePlayer *pPlayer = NULL; - - if ( m_hPlayer->IsPlayer() ) - { - pPlayer = ((CBasePlayer*)m_hPlayer.Get()); - } - else - { - Warning("CTriggerCamera could not find a player!\n"); - return; - } - - // if the player was already under control of a similar trigger, disable the previous trigger. - { - CBaseEntity *pPrevViewControl = pPlayer->GetViewEntity(); - if (pPrevViewControl && pPrevViewControl != pPlayer) - { - CTriggerCamera *pOtherCamera = dynamic_cast(pPrevViewControl); - if ( pOtherCamera ) - { - if ( pOtherCamera == this ) - { - // what the hell do you think you are doing? - Warning("Viewcontrol %s was enabled twice in a row!\n", GetDebugName()); - return; - } - else - { - pOtherCamera->Disable(); - } - } - } - } - - - m_nPlayerButtons = pPlayer->m_nButtons; - - - // Make the player invulnerable while under control of the camera. This will prevent situations where the player dies while under camera control but cannot restart their game due to disabled player inputs. - m_nOldTakeDamage = m_hPlayer->m_takedamage; - m_hPlayer->m_takedamage = DAMAGE_NO; - - if ( HasSpawnFlags( SF_CAMERA_PLAYER_NOT_SOLID ) ) - { - m_hPlayer->AddSolidFlags( FSOLID_NOT_SOLID ); - } - - m_flReturnTime = gpGlobals->curtime + m_flWait; - m_flSpeed = m_initialSpeed; - m_targetSpeed = m_initialSpeed; - - // this pertains to view angles, not translation. - if ( HasSpawnFlags( SF_CAMERA_PLAYER_SNAP_TO ) ) - { - m_bSnapToGoal = true; - } - - if ( HasSpawnFlags(SF_CAMERA_PLAYER_TARGET ) ) - { - m_hTarget = m_hPlayer; - } - else - { - m_hTarget = GetNextTarget(); - } - - // If we don't have a target, ignore the attachment / etc - if ( m_hTarget ) - { - m_iAttachmentIndex = 0; - if ( m_iszTargetAttachment != NULL_STRING ) - { - if ( !m_hTarget->GetBaseAnimating() ) - { - Warning("%s tried to target an attachment (%s) on target %s, which has no model.\n", GetClassname(), STRING(m_iszTargetAttachment), STRING(m_hTarget->GetEntityName()) ); - } - else - { - m_iAttachmentIndex = m_hTarget->GetBaseAnimating()->LookupAttachment( STRING(m_iszTargetAttachment) ); - if ( !m_iAttachmentIndex ) - { - Warning("%s could not find attachment %s on target %s.\n", GetClassname(), STRING(m_iszTargetAttachment), STRING(m_hTarget->GetEntityName()) ); - } - } - } - } - - if (HasSpawnFlags(SF_CAMERA_PLAYER_TAKECONTROL ) ) - { - ((CBasePlayer*)m_hPlayer.Get())->EnableControl(FALSE); - } - - if ( m_sPath != NULL_STRING ) - { - m_pPath = gEntList.FindEntityByName( NULL, m_sPath, NULL, m_hPlayer ); - } - else - { - m_pPath = NULL; - } - - m_flStopTime = gpGlobals->curtime; - if ( m_pPath ) - { - if ( m_pPath->m_flSpeed != 0 ) - m_targetSpeed = m_pPath->m_flSpeed; - - m_flStopTime += m_pPath->GetDelay(); - } - - - // copy over player information. If we're interpolating from - // the player position, do something more elaborate. -#if HL2_EPISODIC - if (m_bInterpolatePosition) - { - // initialize the values we'll spline between - m_vStartPos = m_hPlayer->EyePosition(); - m_vEndPos = GetAbsOrigin(); - m_flInterpStartTime = gpGlobals->curtime; - UTIL_SetOrigin( this, m_hPlayer->EyePosition() ); - SetLocalAngles( QAngle( m_hPlayer->GetLocalAngles().x, m_hPlayer->GetLocalAngles().y, 0 ) ); - - SetAbsVelocity( vec3_origin ); - } - else -#endif - if (HasSpawnFlags(SF_CAMERA_PLAYER_POSITION ) ) - { - UTIL_SetOrigin( this, m_hPlayer->EyePosition() ); - SetLocalAngles( QAngle( m_hPlayer->GetLocalAngles().x, m_hPlayer->GetLocalAngles().y, 0 ) ); - SetAbsVelocity( m_hPlayer->GetAbsVelocity() ); - } - else - { - SetAbsVelocity( vec3_origin ); - } - - - pPlayer->SetViewEntity( this ); - - // Hide the player's viewmodel - if ( pPlayer->GetActiveWeapon() ) - { - pPlayer->GetActiveWeapon()->AddEffects( EF_NODRAW ); - } - - // Only track if we have a target - if ( m_hTarget ) - { - // follow the player down - SetThink( &CTriggerCamera::FollowTarget ); - SetNextThink( gpGlobals->curtime ); - } - - m_moveDistance = 0; - Move(); - - DispatchUpdateTransmitState(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerCamera::Disable( void ) -{ - if ( m_hPlayer && m_hPlayer->IsAlive() ) - { - if ( HasSpawnFlags( SF_CAMERA_PLAYER_NOT_SOLID ) ) - { - m_hPlayer->RemoveSolidFlags( FSOLID_NOT_SOLID ); - } - - ((CBasePlayer*)m_hPlayer.Get())->SetViewEntity( m_hPlayer ); - ((CBasePlayer*)m_hPlayer.Get())->EnableControl(TRUE); - - // Restore the player's viewmodel - if ( ((CBasePlayer*)m_hPlayer.Get())->GetActiveWeapon() ) - { - ((CBasePlayer*)m_hPlayer.Get())->GetActiveWeapon()->RemoveEffects( EF_NODRAW ); - } - } - - //return the player to previous takedamage state - m_hPlayer->m_takedamage = m_nOldTakeDamage; - - m_state = USE_OFF; - m_flReturnTime = gpGlobals->curtime; - SetThink( NULL ); - - m_OnEndFollow.FireOutput(this, this); // dvsents2: what is the best name for this output? - SetLocalAngularVelocity( vec3_angle ); - - DispatchUpdateTransmitState(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerCamera::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - if ( !ShouldToggle( useType, m_state ) ) - return; - - // Toggle state - if ( m_state != USE_OFF ) - { - Disable(); - } - else - { - m_hPlayer = pActivator; - Enable(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerCamera::FollowTarget( ) -{ - if (m_hPlayer == NULL) - return; - - if ( m_hTarget == NULL ) - { - Disable(); - return; - } - - if ( !HasSpawnFlags(SF_CAMERA_PLAYER_INFINITE_WAIT) && (!m_hTarget || m_flReturnTime < gpGlobals->curtime) ) - { - Disable(); - return; - } - - QAngle vecGoal; - if ( m_iAttachmentIndex ) - { - Vector vecOrigin; - m_hTarget->GetBaseAnimating()->GetAttachment( m_iAttachmentIndex, vecOrigin ); - VectorAngles( vecOrigin - GetAbsOrigin(), vecGoal ); - } - else - { - if ( m_hTarget ) - { - VectorAngles( m_hTarget->GetAbsOrigin() - GetAbsOrigin(), vecGoal ); - } - else - { - // Use the viewcontroller's angles - vecGoal = GetAbsAngles(); - } - } - - // Should we just snap to the goal angles? - if ( m_bSnapToGoal ) - { - SetAbsAngles( vecGoal ); - m_bSnapToGoal = false; - } - else - { - // UNDONE: Can't we just use UTIL_AngleDiff here? - QAngle angles = GetLocalAngles(); - - if (angles.y > 360) - angles.y -= 360; - - if (angles.y < 0) - angles.y += 360; - - SetLocalAngles( angles ); - - float dx = vecGoal.x - GetLocalAngles().x; - float dy = vecGoal.y - GetLocalAngles().y; - - if (dx < -180) - dx += 360; - if (dx > 180) - dx = dx - 360; - - if (dy < -180) - dy += 360; - if (dy > 180) - dy = dy - 360; - - QAngle vecAngVel; - vecAngVel.Init( dx * 40 * gpGlobals->frametime, dy * 40 * gpGlobals->frametime, GetLocalAngularVelocity().z ); - SetLocalAngularVelocity(vecAngVel); - } - - if (!HasSpawnFlags(SF_CAMERA_PLAYER_TAKECONTROL)) - { - SetAbsVelocity( GetAbsVelocity() * 0.8 ); - if (GetAbsVelocity().Length( ) < 10.0) - { - SetAbsVelocity( vec3_origin ); - } - } - - SetNextThink( gpGlobals->curtime ); - - Move(); -} - -void CTriggerCamera::Move() -{ - if ( HasSpawnFlags( SF_CAMERA_PLAYER_INTERRUPT ) ) - { - if ( m_hPlayer ) - { - CBasePlayer *pPlayer = ToBasePlayer( m_hPlayer ); - - if ( pPlayer ) - { - int buttonsChanged = m_nPlayerButtons ^ pPlayer->m_nButtons; - - if ( buttonsChanged && pPlayer->m_nButtons ) - { - Disable(); - return; - } - - m_nPlayerButtons = pPlayer->m_nButtons; - } - } - } - - // In vanilla HL2, the camera is either on a path, or doesn't move. In episodic - // we add the capacity for interpolation to the start point. -#if HL2_EPISODIC - if (m_pPath) -#else - // Not moving on a path, return - if (!m_pPath) - return; -#endif - { - // Subtract movement from the previous frame - m_moveDistance -= m_flSpeed * gpGlobals->frametime; - - // Have we moved enough to reach the target? - if ( m_moveDistance <= 0 ) - { - variant_t emptyVariant; - m_pPath->AcceptInput( "InPass", this, this, emptyVariant, 0 ); - // Time to go to the next target - m_pPath = m_pPath->GetNextTarget(); - - // Set up next corner - if ( !m_pPath ) - { - SetAbsVelocity( vec3_origin ); - } - else - { - if ( m_pPath->m_flSpeed != 0 ) - m_targetSpeed = m_pPath->m_flSpeed; - - m_vecMoveDir = m_pPath->GetLocalOrigin() - GetLocalOrigin(); - m_moveDistance = VectorNormalize( m_vecMoveDir ); - m_flStopTime = gpGlobals->curtime + m_pPath->GetDelay(); - } - } - - if ( m_flStopTime > gpGlobals->curtime ) - m_flSpeed = UTIL_Approach( 0, m_flSpeed, m_deceleration * gpGlobals->frametime ); - else - m_flSpeed = UTIL_Approach( m_targetSpeed, m_flSpeed, m_acceleration * gpGlobals->frametime ); - - float fraction = 2 * gpGlobals->frametime; - SetAbsVelocity( ((m_vecMoveDir * m_flSpeed) * fraction) + (GetAbsVelocity() * (1-fraction)) ); - } -#if HL2_EPISODIC - else if (m_bInterpolatePosition) - { - // get the interpolation parameter [0..1] - float tt = (gpGlobals->curtime - m_flInterpStartTime) / kflPosInterpTime; - if (tt >= 1.0f) - { - // we're there, we're done - UTIL_SetOrigin( this, m_vEndPos ); - SetAbsVelocity( vec3_origin ); - - m_bInterpolatePosition = false; - } - else - { - Assert(tt >= 0); - - Vector nextPos = ( (m_vEndPos - m_vStartPos) * SimpleSpline(tt) ) + m_vStartPos; - // rather than stomping origin, set the velocity so that we get there in the proper time - Vector desiredVel = (nextPos - GetAbsOrigin()) * (1.0f / gpGlobals->frametime); - SetAbsVelocity( desiredVel ); - } - } -#endif -} - - -//----------------------------------------------------------------------------- -// Purpose: Starts/stops cd audio tracks -//----------------------------------------------------------------------------- -class CTriggerCDAudio : public CBaseTrigger -{ -public: - DECLARE_CLASS( CTriggerCDAudio, CBaseTrigger ); - - void Spawn( void ); - - virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - void PlayTrack( void ); - void Touch ( CBaseEntity *pOther ); -}; - -LINK_ENTITY_TO_CLASS( trigger_cdaudio, CTriggerCDAudio ); - - -//----------------------------------------------------------------------------- -// Purpose: Changes tracks or stops CD when player touches -// Input : pOther - The entity that touched us. -//----------------------------------------------------------------------------- -void CTriggerCDAudio::Touch ( CBaseEntity *pOther ) -{ - if ( !pOther->IsPlayer() ) - { - return; - } - - PlayTrack(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerCDAudio::Spawn( void ) -{ - BaseClass::Spawn(); - InitTrigger(); -} - - -void CTriggerCDAudio::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - PlayTrack(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Issues a client command to play a given CD track. Called from -// trigger_cdaudio and target_cdaudio. -// Input : iTrack - Track number to play. -//----------------------------------------------------------------------------- -static void PlayCDTrack( int iTrack ) -{ - edict_t *pClient; - - // manually find the single player. - pClient = engine->PEntityOfEntIndex( 1 ); - - Assert(gpGlobals->maxClients == 1); - - // Can't play if the client is not connected! - if ( !pClient ) - return; - - // UNDONE: Move this to engine sound - if ( iTrack < -1 || iTrack > 30 ) - { - Warning( "TriggerCDAudio - Track %d out of range\n" ); - return; - } - - if ( iTrack == -1 ) - { - engine->ClientCommand ( pClient, "cd pause\n"); - } - else - { - char string [ 64 ]; - - Q_snprintf( string,sizeof(string), "cd play %3d\n", iTrack ); - engine->ClientCommand ( pClient, string); - } -} - - -// only plays for ONE client, so only use in single play! -void CTriggerCDAudio::PlayTrack( void ) -{ - PlayCDTrack( (int)m_iHealth ); - - SetTouch( NULL ); - UTIL_Remove( this ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Measures the proximity to a specified entity of any entities within -// the trigger, provided they are within a given radius of the specified -// entity. The nearest entity distance is output as a number from [0 - 1]. -//----------------------------------------------------------------------------- -class CTriggerProximity : public CBaseTrigger -{ -public: - - DECLARE_CLASS( CTriggerProximity, CBaseTrigger ); - - virtual void Spawn(void); - virtual void Activate(void); - virtual void StartTouch(CBaseEntity *pOther); - virtual void EndTouch(CBaseEntity *pOther); - - void MeasureThink(void); - -protected: - - EHANDLE m_hMeasureTarget; - string_t m_iszMeasureTarget; // The entity from which we measure proximities. - float m_fRadius; // The radius around the measure target that we measure within. - int m_nTouchers; // Number of entities touching us. - - // Outputs - COutputFloat m_NearestEntityDistance; - - DECLARE_DATADESC(); -}; - - -BEGIN_DATADESC( CTriggerProximity ) - - // Functions - DEFINE_FUNCTION(MeasureThink), - - // Keys - DEFINE_KEYFIELD(m_iszMeasureTarget, FIELD_STRING, "measuretarget"), - DEFINE_FIELD( m_hMeasureTarget, FIELD_EHANDLE ), - DEFINE_KEYFIELD(m_fRadius, FIELD_FLOAT, "radius"), - DEFINE_FIELD( m_nTouchers, FIELD_INTEGER ), - - // Outputs - DEFINE_OUTPUT(m_NearestEntityDistance, "NearestEntityDistance"), - -END_DATADESC() - - - -LINK_ENTITY_TO_CLASS(trigger_proximity, CTriggerProximity); -LINK_ENTITY_TO_CLASS(logic_proximity, CPointEntity); - - -//----------------------------------------------------------------------------- -// Purpose: Called when spawning, after keyvalues have been handled. -//----------------------------------------------------------------------------- -void CTriggerProximity::Spawn(void) -{ - // Avoid divide by zero in MeasureThink! - if (m_fRadius == 0) - { - m_fRadius = 32; - } - - InitTrigger(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Called after all entities have spawned and after a load game. -// Finds the reference point from which to measure. -//----------------------------------------------------------------------------- -void CTriggerProximity::Activate(void) -{ - BaseClass::Activate(); - m_hMeasureTarget = gEntList.FindEntityByName(NULL, m_iszMeasureTarget ); - - // - // Disable our Touch function if we were given a bad measure target. - // - if ((m_hMeasureTarget == NULL) || (m_hMeasureTarget->edict() == NULL)) - { - Warning( "TriggerProximity - Missing measure target or measure target with no origin!\n"); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Decrements the touch count and cancels the think if the count reaches -// zero. -// Input : pOther - -//----------------------------------------------------------------------------- -void CTriggerProximity::StartTouch(CBaseEntity *pOther) -{ - BaseClass::StartTouch( pOther ); - - if ( PassesTriggerFilters( pOther ) ) - { - m_nTouchers++; - - SetThink( &CTriggerProximity::MeasureThink ); - SetNextThink( gpGlobals->curtime ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Decrements the touch count and cancels the think if the count reaches -// zero. -// Input : pOther - -//----------------------------------------------------------------------------- -void CTriggerProximity::EndTouch(CBaseEntity *pOther) -{ - BaseClass::EndTouch( pOther ); - - if ( PassesTriggerFilters( pOther ) ) - { - m_nTouchers--; - - if ( m_nTouchers == 0 ) - { - SetThink( NULL ); - SetNextThink( TICK_NEVER_THINK ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Think function called every frame as long as we have entities touching -// us that we care about. Finds the closest entity to the measure -// target and outputs the distance as a normalized value from [0..1]. -//----------------------------------------------------------------------------- -void CTriggerProximity::MeasureThink( void ) -{ - if ( ( m_hMeasureTarget == NULL ) || ( m_hMeasureTarget->edict() == NULL ) ) - { - SetThink(NULL); - SetNextThink( TICK_NEVER_THINK ); - return; - } - - // - // Traverse our list of touchers and find the entity that is closest to the - // measure target. - // - float fMinDistance = m_fRadius + 100; - CBaseEntity *pNearestEntity = NULL; - - touchlink_t *root = ( touchlink_t * )GetDataObject( TOUCHLINK ); - if ( root ) - { - touchlink_t *pLink = root->nextLink; - while ( pLink != root ) - { - CBaseEntity *pEntity = pLink->entityTouched; - - // If this is an entity that we care about, check its distance. - if ( ( pEntity != NULL ) && PassesTriggerFilters( pEntity ) ) - { - float flDistance = (pEntity->GetLocalOrigin() - m_hMeasureTarget->GetLocalOrigin()).Length(); - if (flDistance < fMinDistance) - { - fMinDistance = flDistance; - pNearestEntity = pEntity; - } - } - - pLink = pLink->nextLink; - } - } - - // Update our output with the nearest entity distance, normalized to [0..1]. - if ( fMinDistance <= m_fRadius ) - { - fMinDistance /= m_fRadius; - if ( fMinDistance != m_NearestEntityDistance.Get() ) - { - m_NearestEntityDistance.Set( fMinDistance, pNearestEntity, this ); - } - } - - SetNextThink( gpGlobals->curtime ); -} - - -// ################################################################################## -// >> TriggerWind -// -// Blows physics objects in the trigger -// -// ################################################################################## - -#define MAX_WIND_CHANGE 5 - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -class CPhysicsWind : public IMotionEvent -{ - DECLARE_SIMPLE_DATADESC(); - -public: - simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) - { - // If we have no windspeed, we're not doing anything - if ( !m_flWindSpeed ) - return IMotionEvent::SIM_NOTHING; - - // Get a cosine modulated noise between 5 and 20 that is object specific - int nNoiseMod = 5+(int)pObject%15; // - - // Turn wind yaw direction into a vector and add noise - QAngle vWindAngle = vec3_angle; - vWindAngle[1] = m_nWindYaw+(30*cos(nNoiseMod * gpGlobals->curtime + nNoiseMod)); - Vector vWind; - AngleVectors(vWindAngle,&vWind); - - // Add lift with noise - vWind.z = 1.1 + (1.0 * sin(nNoiseMod * gpGlobals->curtime + nNoiseMod)); - - linear = 3*vWind*m_flWindSpeed; - angular = vec3_origin; - return IMotionEvent::SIM_GLOBAL_FORCE; - } - - int m_nWindYaw; - float m_flWindSpeed; -}; - -BEGIN_SIMPLE_DATADESC( CPhysicsWind ) - - DEFINE_FIELD( m_nWindYaw, FIELD_INTEGER ), - DEFINE_FIELD( m_flWindSpeed, FIELD_FLOAT ), - -END_DATADESC() - - -extern short g_sModelIndexSmoke; -extern float GetFloorZ(const Vector &origin); -#define WIND_THINK_CONTEXT "WindThinkContext" - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CTriggerWind : public CBaseVPhysicsTrigger -{ - DECLARE_CLASS( CTriggerWind, CBaseVPhysicsTrigger ); -public: - DECLARE_DATADESC(); - - void Spawn( void ); - bool KeyValue( const char *szKeyName, const char *szValue ); - void OnRestore(); - void UpdateOnRemove(); - bool CreateVPhysics(); - void StartTouch( CBaseEntity *pOther ); - void EndTouch( CBaseEntity *pOther ); - void WindThink( void ); - int DrawDebugTextOverlays( void ); - - // Input handlers - void InputEnable( inputdata_t &inputdata ); - void InputSetSpeed( inputdata_t &inputdata ); - -private: - int m_nSpeedBase; // base line for how hard the wind blows - int m_nSpeedNoise; // noise added to wind speed +/- - int m_nSpeedCurrent;// current wind speed - int m_nSpeedTarget; // wind speed I'm approaching - - int m_nDirBase; // base line for direction the wind blows (yaw) - int m_nDirNoise; // noise added to wind direction - int m_nDirCurrent; // the current wind direction - int m_nDirTarget; // wind direction I'm approaching - - int m_nHoldBase; // base line for how long to wait before changing wind - int m_nHoldNoise; // noise added to how long to wait before changing wind - - bool m_bSwitch; // when does wind change - - IPhysicsMotionController* m_pWindController; - CPhysicsWind m_WindCallback; - -}; - -LINK_ENTITY_TO_CLASS( trigger_wind, CTriggerWind ); - -BEGIN_DATADESC( CTriggerWind ) - - DEFINE_FIELD( m_nSpeedCurrent, FIELD_INTEGER), - DEFINE_FIELD( m_nSpeedTarget, FIELD_INTEGER), - DEFINE_FIELD( m_nDirBase, FIELD_INTEGER), - DEFINE_FIELD( m_nDirCurrent, FIELD_INTEGER), - DEFINE_FIELD( m_nDirTarget, FIELD_INTEGER), - DEFINE_FIELD( m_bSwitch, FIELD_BOOLEAN), - - DEFINE_FIELD( m_nSpeedBase, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_nSpeedNoise, FIELD_INTEGER, "SpeedNoise"), - DEFINE_KEYFIELD( m_nDirNoise, FIELD_INTEGER, "DirectionNoise"), - DEFINE_KEYFIELD( m_nHoldBase, FIELD_INTEGER, "HoldTime"), - DEFINE_KEYFIELD( m_nHoldNoise, FIELD_INTEGER, "HoldNoise"), - - DEFINE_PHYSPTR( m_pWindController ), - DEFINE_EMBEDDED( m_WindCallback ), - - DEFINE_FUNCTION( WindThink ), - - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetSpeed", InputSetSpeed ), - -END_DATADESC() - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CTriggerWind::Spawn( void ) -{ - m_bSwitch = true; - m_nDirBase = (int)GetLocalAngles().y; - - BaseClass::Spawn(); - - m_nSpeedCurrent = m_nSpeedBase; - m_nDirCurrent = m_nDirBase; - - SetContextThink( &CTriggerWind::WindThink, gpGlobals->curtime, WIND_THINK_CONTEXT ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTriggerWind::KeyValue( const char *szKeyName, const char *szValue ) -{ - // Done here to avoid collision with CBaseEntity's speed key - if ( FStrEq(szKeyName, "Speed") ) - { - m_nSpeedBase = atoi( szValue ); - } - else - return BaseClass::KeyValue( szKeyName, szValue ); - - return true; -} - -//------------------------------------------------------------------------------ -// Create VPhysics -//------------------------------------------------------------------------------ -bool CTriggerWind::CreateVPhysics() -{ - BaseClass::CreateVPhysics(); - - m_pWindController = physenv->CreateMotionController( &m_WindCallback ); - return true; -} - -//------------------------------------------------------------------------------ -// Cleanup -//------------------------------------------------------------------------------ -void CTriggerWind::UpdateOnRemove() -{ - if ( m_pWindController ) - { - physenv->DestroyMotionController( m_pWindController ); - m_pWindController = NULL; - } - - BaseClass::UpdateOnRemove(); -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CTriggerWind::OnRestore() -{ - BaseClass::OnRestore(); - if ( m_pWindController ) - { - m_pWindController->SetEventHandler( &m_WindCallback ); - } -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CTriggerWind::StartTouch(CBaseEntity *pOther) -{ - if ( !PassesTriggerFilters(pOther) ) - return; - if ( pOther->IsPlayer() ) - return; - - IPhysicsObject *pPhys = pOther->VPhysicsGetObject(); - if ( pPhys) - { - m_pWindController->AttachObject( pPhys, false ); - pPhys->Wake(); - } -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CTriggerWind::EndTouch(CBaseEntity *pOther) -{ - if ( !PassesTriggerFilters(pOther) ) - return; - if ( pOther->IsPlayer() ) - return; - - IPhysicsObject *pPhys = pOther->VPhysicsGetObject(); - if ( pPhys && m_pWindController ) - { - m_pWindController->DetachObject( pPhys ); - } -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CTriggerWind::InputEnable( inputdata_t &inputdata ) -{ - BaseClass::InputEnable( inputdata ); - SetContextThink( &CTriggerWind::WindThink, gpGlobals->curtime + 0.1f, WIND_THINK_CONTEXT ); -} - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CTriggerWind::WindThink( void ) -{ - // By default... - SetContextThink( &CTriggerWind::WindThink, gpGlobals->curtime + 0.1, WIND_THINK_CONTEXT ); - - // Is it time to change the wind? - if (m_bSwitch) - { - m_bSwitch = false; - - // Set new target direction and speed - m_nSpeedTarget = m_nSpeedBase + random->RandomInt( -m_nSpeedNoise, m_nSpeedNoise ); - m_nDirTarget = (int)UTIL_AngleMod( m_nDirBase + random->RandomInt(-m_nDirNoise, m_nDirNoise) ); - } - else - { - bool bDone = true; - // either ramp up, or sleep till change - if (abs(m_nSpeedTarget - m_nSpeedCurrent) > MAX_WIND_CHANGE) - { - m_nSpeedCurrent += (m_nSpeedTarget > m_nSpeedCurrent) ? MAX_WIND_CHANGE : -MAX_WIND_CHANGE; - bDone = false; - } - - if (abs(m_nDirTarget - m_nDirCurrent) > MAX_WIND_CHANGE) - { - - m_nDirCurrent = (int)UTIL_ApproachAngle( m_nDirTarget, m_nDirCurrent, MAX_WIND_CHANGE ); - bDone = false; - } - - if (bDone) - { - m_nSpeedCurrent = m_nSpeedTarget; - SetContextThink( &CTriggerWind::WindThink, m_nHoldBase + random->RandomFloat(-m_nHoldNoise,m_nHoldNoise), WIND_THINK_CONTEXT ); - m_bSwitch = true; - } - } - - // If we're starting to blow, where we weren't before, wake up all our objects - if ( m_nSpeedCurrent ) - { - m_pWindController->WakeObjects(); - } - - // store the wind data in the controller callback - m_WindCallback.m_nWindYaw = m_nDirCurrent; - if ( m_bDisabled ) - { - m_WindCallback.m_flWindSpeed = 0; - } - else - { - m_WindCallback.m_flWindSpeed = m_nSpeedCurrent; - } -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CTriggerWind::InputSetSpeed( inputdata_t &inputdata ) -{ - // Set new speed and mark to switch - m_nSpeedBase = inputdata.value.Int(); - m_bSwitch = true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CTriggerWind::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - // -------------- - // Print Target - // -------------- - char tempstr[255]; - Q_snprintf(tempstr,sizeof(tempstr),"Dir: %i (%i)",m_nDirCurrent,m_nDirTarget); - EntityText(text_offset,tempstr,0); - text_offset++; - - Q_snprintf(tempstr,sizeof(tempstr),"Speed: %i (%i)",m_nSpeedCurrent,m_nSpeedTarget); - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} - - -// ################################################################################## -// >> TriggerImpact -// -// Blows physics objects in the trigger -// -// ################################################################################## -#define TRIGGERIMPACT_VIEWKICK_SCALE 0.1 - -class CTriggerImpact : public CTriggerMultiple -{ - DECLARE_CLASS( CTriggerImpact, CTriggerMultiple ); -public: - DECLARE_DATADESC(); - - float m_flMagnitude; - float m_flNoise; - float m_flViewkick; - - void Spawn( void ); - void StartTouch( CBaseEntity *pOther ); - - // Inputs - void InputSetMagnitude( inputdata_t &inputdata ); - void InputImpact( inputdata_t &inputdata ); - - // Outputs - COutputVector m_pOutputForce; // Output force in case anyone else wants to use it - - // Debug - int DrawDebugTextOverlays(void); -}; - -LINK_ENTITY_TO_CLASS( trigger_impact, CTriggerImpact ); - -BEGIN_DATADESC( CTriggerImpact ) - - DEFINE_KEYFIELD( m_flMagnitude, FIELD_FLOAT, "Magnitude"), - DEFINE_KEYFIELD( m_flNoise, FIELD_FLOAT, "Noise"), - DEFINE_KEYFIELD( m_flViewkick, FIELD_FLOAT, "Viewkick"), - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Impact", InputImpact ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetMagnitude", InputSetMagnitude ), - - // Outputs - DEFINE_OUTPUT(m_pOutputForce, "ImpactForce"), - - // Function Pointers - DEFINE_FUNCTION( Disable ), - - -END_DATADESC() - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CTriggerImpact::Spawn( void ) -{ - // Clamp date in case user made an error - m_flNoise = clamp(m_flNoise,0,1); - m_flViewkick = clamp(m_flViewkick,0,1); - - // Always start disabled - m_bDisabled = true; - BaseClass::Spawn(); -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CTriggerImpact::InputImpact( inputdata_t &inputdata ) -{ - // Output the force vector in case anyone else wants to use it - Vector vDir; - AngleVectors( GetLocalAngles(),&vDir ); - m_pOutputForce.Set( m_flMagnitude * vDir, inputdata.pActivator, inputdata.pCaller); - - // Enable long enough to throw objects inside me - Enable(); - SetNextThink( gpGlobals->curtime + 0.1f ); - SetThink(&CTriggerImpact::Disable); -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CTriggerImpact::StartTouch(CBaseEntity *pOther) -{ - //If the entity is valid and has physics, hit it - if ( ( pOther != NULL ) && ( pOther->VPhysicsGetObject() != NULL ) ) - { - Vector vDir; - AngleVectors( GetLocalAngles(),&vDir ); - vDir += RandomVector(-m_flNoise,m_flNoise); - pOther->VPhysicsGetObject()->ApplyForceCenter( m_flMagnitude * vDir ); - } - - // If the player, so a view kick - if (pOther->IsPlayer() && fabs(m_flMagnitude)>0 ) - { - Vector vDir; - AngleVectors( GetLocalAngles(),&vDir ); - - float flPunch = -m_flViewkick*m_flMagnitude*TRIGGERIMPACT_VIEWKICK_SCALE; - pOther->ViewPunch( QAngle( vDir.y * flPunch, 0, vDir.x * flPunch ) ); - } -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CTriggerImpact::InputSetMagnitude( inputdata_t &inputdata ) -{ - m_flMagnitude = inputdata.value.Float(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays -// Output : Current text offset from the top -//----------------------------------------------------------------------------- -int CTriggerImpact::DrawDebugTextOverlays(void) -{ - int text_offset = BaseClass::DrawDebugTextOverlays(); - - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - char tempstr[255]; - Q_snprintf(tempstr,sizeof(tempstr),"Magnitude: %3.2f",m_flMagnitude); - EntityText(text_offset,tempstr,0); - text_offset++; - } - return text_offset; -} - -//----------------------------------------------------------------------------- -// Purpose: Disables auto movement on players that touch it -//----------------------------------------------------------------------------- - -const int SF_TRIGGER_MOVE_AUTODISABLE = 0x80; // disable auto movement -const int SF_TRIGGER_AUTO_DUCK = 0x800; // Duck automatically - -class CTriggerPlayerMovement : public CBaseTrigger -{ - DECLARE_CLASS( CTriggerPlayerMovement, CBaseTrigger ); -public: - - void Spawn( void ); - void StartTouch( CBaseEntity *pOther ); - void EndTouch( CBaseEntity *pOther ); - - DECLARE_DATADESC(); - -}; - -BEGIN_DATADESC( CTriggerPlayerMovement ) - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( trigger_playermovement, CTriggerPlayerMovement ); - - -//----------------------------------------------------------------------------- -// Purpose: Called when spawning, after keyvalues have been handled. -//----------------------------------------------------------------------------- -void CTriggerPlayerMovement::Spawn( void ) -{ - if( HasSpawnFlags( SF_TRIGGER_ONLY_PLAYER_ALLY_NPCS ) ) - { - // @Note (toml 01-07-04): fix up spawn flag collision coding error. Remove at some point once all maps fixed up please! - DevMsg("*** trigger_playermovement using obsolete spawnflag. Remove and reset with new value for \"Disable auto player movement\"\n" ); - RemoveSpawnFlags(SF_TRIGGER_ONLY_PLAYER_ALLY_NPCS); - AddSpawnFlags(SF_TRIGGER_MOVE_AUTODISABLE); - } - BaseClass::Spawn(); - - InitTrigger(); -} - - -// UNDONE: This will not support a player touching more than one of these -// UNDONE: Do we care? If so, ref count automovement in the player? -void CTriggerPlayerMovement::StartTouch( CBaseEntity *pOther ) -{ - if (!PassesTriggerFilters(pOther)) - return; - - CBasePlayer *pPlayer = ToBasePlayer( pOther ); - - if ( !pPlayer ) - return; - - if ( HasSpawnFlags( SF_TRIGGER_AUTO_DUCK ) ) - { - pPlayer->ForceButtons( IN_DUCK ); - } - - // UNDONE: Currently this is the only operation this trigger can do - if ( HasSpawnFlags(SF_TRIGGER_MOVE_AUTODISABLE) ) - { - pPlayer->m_Local.m_bAllowAutoMovement = false; - } -} - -void CTriggerPlayerMovement::EndTouch( CBaseEntity *pOther ) -{ - if (!PassesTriggerFilters(pOther)) - return; - - CBasePlayer *pPlayer = ToBasePlayer( pOther ); - - if ( !pPlayer ) - return; - - if ( HasSpawnFlags( SF_TRIGGER_AUTO_DUCK ) ) - { - pPlayer->UnforceButtons( IN_DUCK ); - } - - if ( HasSpawnFlags(SF_TRIGGER_MOVE_AUTODISABLE) ) - { - pPlayer->m_Local.m_bAllowAutoMovement = true; - } -} - -//------------------------------------------------------------------------------ -// Base VPhysics trigger implementation -//------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -// Save/load -//------------------------------------------------------------------------------ -BEGIN_DATADESC( CBaseVPhysicsTrigger ) - DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ), - DEFINE_KEYFIELD( m_iFilterName, FIELD_STRING, "filtername" ), - DEFINE_FIELD( m_hFilter, FIELD_EHANDLE ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Toggle", InputToggle ), -END_DATADESC() - -//------------------------------------------------------------------------------ -// Spawn -//------------------------------------------------------------------------------ -void CBaseVPhysicsTrigger::Spawn() -{ - Precache(); - - SetSolid( SOLID_VPHYSICS ); - AddSolidFlags( FSOLID_NOT_SOLID ); - - // NOTE: Don't make yourself FSOLID_TRIGGER here or you'll get game - // collisions AND vphysics collisions. You don't want any game collisions - // so just use FSOLID_NOT_SOLID - - SetMoveType( MOVETYPE_NONE ); - SetModel( STRING( GetModelName() ) ); // set size and link into world - if ( showtriggers.GetInt() == 0 ) - { - AddEffects( EF_NODRAW ); - } - - CreateVPhysics(); -} - -//------------------------------------------------------------------------------ -// Create VPhysics -//------------------------------------------------------------------------------ -bool CBaseVPhysicsTrigger::CreateVPhysics() -{ - IPhysicsObject *pPhysics; - if ( !HasSpawnFlags( SF_VPHYSICS_MOTION_MOVEABLE ) ) - { - pPhysics = VPhysicsInitStatic(); - } - else - { - pPhysics = VPhysicsInitShadow( false, false ); - } - - pPhysics->BecomeTrigger(); - return true; -} - -//------------------------------------------------------------------------------ -// Cleanup -//------------------------------------------------------------------------------ -void CBaseVPhysicsTrigger::UpdateOnRemove() -{ - if ( VPhysicsGetObject()) - { - VPhysicsGetObject()->RemoveTrigger(); - } - - BaseClass::UpdateOnRemove(); -} - -//------------------------------------------------------------------------------ -// Activate -//------------------------------------------------------------------------------ -void CBaseVPhysicsTrigger::Activate( void ) -{ - // Get a handle to my filter entity if there is one - if (m_iFilterName != NULL_STRING) - { - m_hFilter = dynamic_cast(gEntList.FindEntityByName( NULL, m_iFilterName )); - } - - BaseClass::Activate(); -} - -//------------------------------------------------------------------------------ -// Inputs -//------------------------------------------------------------------------------ -void CBaseVPhysicsTrigger::InputToggle( inputdata_t &inputdata ) -{ - if ( m_bDisabled ) - { - InputEnable( inputdata ); - } - else - { - InputDisable( inputdata ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseVPhysicsTrigger::InputEnable( inputdata_t &inputdata ) -{ - if ( m_bDisabled ) - { - m_bDisabled = false; - if ( VPhysicsGetObject()) - { - VPhysicsGetObject()->EnableCollisions( true ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseVPhysicsTrigger::InputDisable( inputdata_t &inputdata ) -{ - if ( !m_bDisabled ) - { - m_bDisabled = true; - if ( VPhysicsGetObject()) - { - VPhysicsGetObject()->EnableCollisions( false ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseVPhysicsTrigger::StartTouch( CBaseEntity *pOther ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseVPhysicsTrigger::EndTouch( CBaseEntity *pOther ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseVPhysicsTrigger::PassesTriggerFilters( CBaseEntity *pOther ) -{ - if ( pOther->GetMoveType() != MOVETYPE_VPHYSICS && !pOther->IsPlayer() ) - return false; - - // First test spawn flag filters - if ( HasSpawnFlags(SF_TRIGGER_ALLOW_ALL) || - (HasSpawnFlags(SF_TRIGGER_ALLOW_CLIENTS) && (pOther->GetFlags() & FL_CLIENT)) || - (HasSpawnFlags(SF_TRIGGER_ALLOW_NPCS) && (pOther->GetFlags() & FL_NPC)) || - (HasSpawnFlags(SF_TRIGGER_ALLOW_PUSHABLES) && FClassnameIs(pOther, "func_pushable")) || - (HasSpawnFlags(SF_TRIGGER_ALLOW_PHYSICS) && pOther->GetMoveType() == MOVETYPE_VPHYSICS)) - { - bool bOtherIsPlayer = pOther->IsPlayer(); - if( HasSpawnFlags(SF_TRIGGER_ONLY_PLAYER_ALLY_NPCS) && !bOtherIsPlayer ) - { - CAI_BaseNPC *pNPC = pOther->MyNPCPointer(); - - if( !pNPC || !pNPC->IsPlayerAlly() ) - { - return false; - } - } - - if ( HasSpawnFlags(SF_TRIGGER_ONLY_CLIENTS_IN_VEHICLES) && bOtherIsPlayer ) - { - if ( !((CBasePlayer*)pOther)->IsInAVehicle() ) - return false; - } - - if ( HasSpawnFlags(SF_TRIGGER_ONLY_CLIENTS_OUT_OF_VEHICLES) && bOtherIsPlayer ) - { - if ( ((CBasePlayer*)pOther)->IsInAVehicle() ) - return false; - } - - CBaseFilter *pFilter = m_hFilter.Get(); - return (!pFilter) ? true : pFilter->PassesFilter( this, pOther ); - } - return false; -} - -//===================================================================================================================== -//----------------------------------------------------------------------------- -// Purpose: VPhysics trigger that changes the motion of vphysics objects that touch it -//----------------------------------------------------------------------------- -class CTriggerVPhysicsMotion : public CBaseVPhysicsTrigger, public IMotionEvent -{ - DECLARE_CLASS( CTriggerVPhysicsMotion, CBaseVPhysicsTrigger ); - -public: - void Spawn(); - void Precache(); - virtual void UpdateOnRemove(); - bool CreateVPhysics(); - void OnRestore(); - - // UNDONE: Pass trigger event in or change Start/EndTouch. Add ITriggerVPhysics perhaps? - // BUGBUG: If a player touches two of these, his movement will screw up. - // BUGBUG: If a player uses crouch/uncrouch it will generate touch events and clear the motioncontroller flag - void StartTouch( CBaseEntity *pOther ); - void EndTouch( CBaseEntity *pOther ); - - void InputSetVelocityLimitTime( inputdata_t &inputdata ); - - float LinearLimit(); - - inline bool HasGravityScale() { return m_gravityScale != 1.0 ? true : false; } - inline bool HasAirDensity() { return m_addAirDensity != 0 ? true : false; } - inline bool HasLinearLimit() { return LinearLimit() != 0.0f; } - inline bool HasLinearScale() { return m_linearScale != 1.0 ? true : false; } - inline bool HasAngularLimit() { return m_angularLimit != 0 ? true : false; } - inline bool HasAngularScale() { return m_angularScale != 1.0 ? true : false; } - inline bool HasLinearForce() { return m_linearForce != 0.0 ? true : false; } - - DECLARE_DATADESC(); - - virtual simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ); - -private: - IPhysicsMotionController *m_pController; - -#ifndef _XBOX - EntityParticleTrailInfo_t m_ParticleTrail; -#endif //!_XBOX - - float m_gravityScale; - float m_addAirDensity; - float m_linearLimit; - float m_linearLimitDelta; - float m_linearLimitTime; - float m_linearLimitStart; - float m_linearLimitStartTime; - float m_linearScale; - float m_angularLimit; - float m_angularScale; - float m_linearForce; - QAngle m_linearForceAngles; -}; - - -//------------------------------------------------------------------------------ -// Save/load -//------------------------------------------------------------------------------ -BEGIN_DATADESC( CTriggerVPhysicsMotion ) - DEFINE_PHYSPTR( m_pController ), -#ifndef _XBOX - DEFINE_EMBEDDED( m_ParticleTrail ), -#endif //!_XBOX - DEFINE_INPUT( m_gravityScale, FIELD_FLOAT, "SetGravityScale" ), - DEFINE_INPUT( m_addAirDensity, FIELD_FLOAT, "SetAdditionalAirDensity" ), - DEFINE_INPUT( m_linearLimit, FIELD_FLOAT, "SetVelocityLimit" ), - DEFINE_INPUT( m_linearLimitDelta, FIELD_FLOAT, "SetVelocityLimitDelta" ), - DEFINE_FIELD( m_linearLimitTime, FIELD_FLOAT ), - DEFINE_FIELD( m_linearLimitStart, FIELD_TIME ), - DEFINE_FIELD( m_linearLimitStartTime, FIELD_TIME ), - DEFINE_INPUT( m_linearScale, FIELD_FLOAT, "SetVelocityScale" ), - DEFINE_INPUT( m_angularLimit, FIELD_FLOAT, "SetAngVelocityLimit" ), - DEFINE_INPUT( m_angularScale, FIELD_FLOAT, "SetAngVelocityScale" ), - DEFINE_INPUT( m_linearForce, FIELD_FLOAT, "SetLinearForce" ), - DEFINE_INPUT( m_linearForceAngles, FIELD_VECTOR, "SetLinearForceAngles" ), - - DEFINE_INPUTFUNC( FIELD_STRING, "SetVelocityLimitTime", InputSetVelocityLimitTime ), -END_DATADESC() - -LINK_ENTITY_TO_CLASS( trigger_vphysics_motion, CTriggerVPhysicsMotion ); - - -//------------------------------------------------------------------------------ -// Spawn -//------------------------------------------------------------------------------ -void CTriggerVPhysicsMotion::Spawn() -{ - Precache(); - - BaseClass::Spawn(); -} - -//------------------------------------------------------------------------------ -// Precache -//------------------------------------------------------------------------------ -void CTriggerVPhysicsMotion::Precache() -{ -#ifndef _XBOX - if ( m_ParticleTrail.m_strMaterialName != NULL_STRING ) - { - PrecacheMaterial( STRING(m_ParticleTrail.m_strMaterialName) ); - } -#endif //!_XBOX -} - -//------------------------------------------------------------------------------ -// Create VPhysics -//------------------------------------------------------------------------------ -float CTriggerVPhysicsMotion::LinearLimit() -{ - if ( m_linearLimitTime == 0.0f ) - return m_linearLimit; - - float dt = gpGlobals->curtime - m_linearLimitStartTime; - if ( dt >= m_linearLimitTime ) - { - m_linearLimitTime = 0.0; - return m_linearLimit; - } - - dt /= m_linearLimitTime; - float flLimit = RemapVal( dt, 0.0f, 1.0f, m_linearLimitStart, m_linearLimit ); - return flLimit; -} - - -//------------------------------------------------------------------------------ -// Create VPhysics -//------------------------------------------------------------------------------ -bool CTriggerVPhysicsMotion::CreateVPhysics() -{ - m_pController = physenv->CreateMotionController( this ); - BaseClass::CreateVPhysics(); - - return true; -} - - -//------------------------------------------------------------------------------ -// Cleanup -//------------------------------------------------------------------------------ -void CTriggerVPhysicsMotion::UpdateOnRemove() -{ - if ( m_pController ) - { - physenv->DestroyMotionController( m_pController ); - m_pController = NULL; - } - - BaseClass::UpdateOnRemove(); -} - - -//------------------------------------------------------------------------------ -// Restore -//------------------------------------------------------------------------------ -void CTriggerVPhysicsMotion::OnRestore() -{ - BaseClass::OnRestore(); - if ( m_pController ) - { - m_pController->SetEventHandler( this ); - } -} - -//------------------------------------------------------------------------------ -// Start/End Touch -//------------------------------------------------------------------------------ -// UNDONE: Pass trigger event in or change Start/EndTouch. Add ITriggerVPhysics perhaps? -// BUGBUG: If a player touches two of these, his movement will screw up. -// BUGBUG: If a player uses crouch/uncrouch it will generate touch events and clear the motioncontroller flag -void CTriggerVPhysicsMotion::StartTouch( CBaseEntity *pOther ) -{ - BaseClass::StartTouch( pOther ); - - if ( !PassesTriggerFilters(pOther) ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( pOther ); - if ( pPlayer ) - { - pPlayer->SetPhysicsFlag( PFLAG_VPHYSICS_MOTIONCONTROLLER, true ); - pPlayer->m_Local.m_bSlowMovement = true; - } - - triggerevent_t event; - PhysGetTriggerEvent( &event, this ); - if ( event.pObject ) - { - // these all get done again on save/load, so check - m_pController->AttachObject( event.pObject, true ); - } - - // Don't show these particles on the XBox -#ifndef _XBOX - if ( m_ParticleTrail.m_strMaterialName != NULL_STRING ) - { - CEntityParticleTrail::Create( pOther, m_ParticleTrail, this ); - } -#endif - - if ( pOther->GetBaseAnimating() && pOther->GetBaseAnimating()->IsRagdoll() ) - { - CRagdollBoogie::IncrementSuppressionCount( pOther ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTriggerVPhysicsMotion::EndTouch( CBaseEntity *pOther ) -{ - BaseClass::EndTouch( pOther ); - - if ( !PassesTriggerFilters(pOther) ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( pOther ); - if ( pPlayer ) - { - pPlayer->SetPhysicsFlag( PFLAG_VPHYSICS_MOTIONCONTROLLER, false ); - pPlayer->m_Local.m_bSlowMovement = false; - } - triggerevent_t event; - PhysGetTriggerEvent( &event, this ); - if ( event.pObject && m_pController ) - { - m_pController->DetachObject( event.pObject ); - } - -#ifndef _XBOX - if ( m_ParticleTrail.m_strMaterialName != NULL_STRING ) - { - CEntityParticleTrail::Destroy( pOther, m_ParticleTrail ); - } -#endif //!_XBOX - - if ( pOther->GetBaseAnimating() && pOther->GetBaseAnimating()->IsRagdoll() ) - { - CRagdollBoogie::DecrementSuppressionCount( pOther ); - } -} - - -//------------------------------------------------------------------------------ -// Inputs -//------------------------------------------------------------------------------ -void CTriggerVPhysicsMotion::InputSetVelocityLimitTime( inputdata_t &inputdata ) -{ - m_linearLimitStart = LinearLimit(); - m_linearLimitStartTime = gpGlobals->curtime; - - float args[2]; - UTIL_StringToFloatArray( args, 2, inputdata.value.String() ); - m_linearLimit = args[0]; - m_linearLimitTime = args[1]; -} - -//------------------------------------------------------------------------------ -// Apply the forces to the entity -//------------------------------------------------------------------------------ -IMotionEvent::simresult_e CTriggerVPhysicsMotion::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) -{ - if ( m_bDisabled ) - return SIM_NOTHING; - - linear.Init(); - angular.Init(); - - if ( HasGravityScale() ) - { - // assume object already has 1.0 gravities applied to it, so apply the additional amount - linear.z -= (m_gravityScale-1) * sv_gravity.GetFloat(); - } - - if ( HasLinearForce() ) - { - Vector vecForceDir; - AngleVectors( m_linearForceAngles, &vecForceDir ); - VectorMA( linear, m_linearForce, vecForceDir, linear ); - } - - if ( HasAirDensity() || HasLinearLimit() || HasLinearScale() || HasAngularLimit() || HasAngularScale() ) - { - Vector vel; - AngularImpulse angVel; - pObject->GetVelocity( &vel, &angVel ); - vel += linear * deltaTime; // account for gravity scale - - Vector unitVel = vel; - Vector unitAngVel = angVel; - - float speed = VectorNormalize( unitVel ); - float angSpeed = VectorNormalize( unitAngVel ); - - float speedScale = 0.0; - float angSpeedScale = 0.0; - - if ( HasAirDensity() ) - { - float linearDrag = -0.5 * m_addAirDensity * pObject->CalculateLinearDrag( unitVel ) * deltaTime; - if ( linearDrag < -1 ) - { - linearDrag = -1; - } - speedScale += linearDrag / deltaTime; - float angDrag = -0.5 * m_addAirDensity * pObject->CalculateAngularDrag( unitAngVel ) * deltaTime; - if ( angDrag < -1 ) - { - angDrag = -1; - } - angSpeedScale += angDrag / deltaTime; - } - - if ( HasLinearLimit() && speed > m_linearLimit ) - { - float flDeltaVel = (LinearLimit() - speed) / deltaTime; - if ( m_linearLimitDelta != 0.0f ) - { - float flMaxDeltaVel = -m_linearLimitDelta / deltaTime; - if ( flDeltaVel < flMaxDeltaVel ) - { - flDeltaVel = flMaxDeltaVel; - } - } - VectorMA( linear, flDeltaVel, unitVel, linear ); - } - if ( HasAngularLimit() && angSpeed > m_angularLimit ) - { - angular += ((m_angularLimit - angSpeed)/deltaTime) * unitAngVel; - } - if ( HasLinearScale() ) - { - speedScale = ( (speedScale+1) * m_linearScale ) - 1; - } - if ( HasAngularScale() ) - { - angSpeedScale = ( (angSpeedScale+1) * m_angularScale ) - 1; - } - linear += vel * speedScale; - angular += angVel * angSpeedScale; - } - - return SIM_GLOBAL_ACCELERATION; -} - -class CServerRagdollTrigger : public CBaseTrigger -{ - DECLARE_CLASS( CServerRagdollTrigger, CBaseTrigger ); - -public: - - virtual void StartTouch( CBaseEntity *pOther ); - virtual void EndTouch( CBaseEntity *pOther ); - virtual void Spawn( void ); - -}; - -LINK_ENTITY_TO_CLASS( trigger_serverragdoll, CServerRagdollTrigger ); - -void CServerRagdollTrigger::Spawn( void ) -{ - BaseClass::Spawn(); - - InitTrigger(); -} - -void CServerRagdollTrigger::StartTouch(CBaseEntity *pOther) -{ - BaseClass::StartTouch( pOther ); - - if ( pOther->IsPlayer() ) - return; - - CBaseCombatCharacter *pCombatChar = pOther->MyCombatCharacterPointer(); - - if ( pCombatChar ) - { - pCombatChar->m_bForceServerRagdoll = true; - } -} - -void CServerRagdollTrigger::EndTouch(CBaseEntity *pOther) -{ - BaseClass::EndTouch( pOther ); - - if ( pOther->IsPlayer() ) - return; - - CBaseCombatCharacter *pCombatChar = pOther->MyCombatCharacterPointer(); - - if ( pCombatChar ) - { - pCombatChar->m_bForceServerRagdoll = false; - } -} - -#ifdef HL1_DLL -//---------------------------------------------------------------------------------- -// func_friction -//---------------------------------------------------------------------------------- -class CFrictionModifier : public CBaseTrigger -{ - DECLARE_CLASS( CFrictionModifier, CBaseTrigger ); - -public: - void Spawn( void ); - bool KeyValue( const char *szKeyName, const char *szValue ); - - virtual void StartTouch(CBaseEntity *pOther); - virtual void EndTouch(CBaseEntity *pOther); - - virtual int ObjectCaps( void ) { return CBaseEntity::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } - float m_frictionFraction; - - DECLARE_DATADESC(); - -}; - -LINK_ENTITY_TO_CLASS( func_friction, CFrictionModifier ); - -BEGIN_DATADESC( CFrictionModifier ) - DEFINE_FIELD( m_frictionFraction, FIELD_FLOAT ), -END_DATADESC() - -// Modify an entity's friction -void CFrictionModifier::Spawn( void ) -{ - BaseClass::Spawn(); - - InitTrigger(); -} - -// Sets toucher's friction to m_frictionFraction (1.0 = normal friction) -bool CFrictionModifier::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "modifier")) - { - m_frictionFraction = atof(szValue) / 100.0; - } - else - { - BaseClass::KeyValue( szKeyName, szValue ); - } - return true; -} - -void CFrictionModifier::StartTouch( CBaseEntity *pOther ) -{ - if ( !pOther->IsPlayer() ) // ignore player - { - pOther->SetFriction( m_frictionFraction ); - } -} - -void CFrictionModifier::EndTouch( CBaseEntity *pOther ) -{ - if ( !pOther->IsPlayer() ) // ignore player - { - pOther->SetFriction( 1.0f ); - } -} - -#endif //HL1_DLL - -bool IsTriggerClass( CBaseEntity *pEntity ) -{ - if ( NULL != dynamic_cast(pEntity) ) - return true; - - if ( NULL != dynamic_cast(pEntity) ) - return true; - - if ( NULL != dynamic_cast(pEntity) ) - return true; - - return false; -} diff --git a/game/server/triggers.h b/game/server/triggers.h deleted file mode 100644 index fe4558dc4..000000000 --- a/game/server/triggers.h +++ /dev/null @@ -1,207 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef TRIGGERS_H -#define TRIGGERS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "basetoggle.h" -#include "entityoutput.h" - -// -// Spawnflags -// - -enum -{ - SF_TRIGGER_ALLOW_CLIENTS = 0x01, // Players can fire this trigger - SF_TRIGGER_ALLOW_NPCS = 0x02, // NPCS can fire this trigger - SF_TRIGGER_ALLOW_PUSHABLES = 0x04, // Pushables can fire this trigger - SF_TRIGGER_ALLOW_PHYSICS = 0x08, // Physics objects can fire this trigger - SF_TRIGGER_ONLY_PLAYER_ALLY_NPCS = 0x10, // *if* NPCs can fire this trigger, this flag means only player allies do so - SF_TRIGGER_ONLY_CLIENTS_IN_VEHICLES = 0x20, // *if* Players can fire this trigger, this flag means only players inside vehicles can - SF_TRIGGER_ALLOW_ALL = 0x40, // Everything can fire this trigger EXCEPT DEBRIS! - SF_TRIGGER_ONLY_CLIENTS_OUT_OF_VEHICLES = 0x200, // *if* Players can fire this trigger, this flag means only players outside vehicles can - SF_TRIG_PUSH_ONCE = 0x80, // trigger_push removes itself after firing once - SF_TRIG_PUSH_AFFECT_PLAYER_ON_LADDER = 0x100, // if pushed object is player on a ladder, then this disengages them from the ladder (HL2only) - SF_TRIG_TOUCH_DEBRIS = 0x400, // Will touch physics debris objects - SF_TRIGGER_ONLY_NPCS_IN_VEHICLES = 0X800, // *if* NPCs can fire this trigger, only NPCs in vehicles do so (respects player ally flag too) -}; - -// DVS TODO: get rid of CBaseToggle -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CBaseTrigger : public CBaseToggle -{ - DECLARE_CLASS( CBaseTrigger, CBaseToggle ); -public: - CBaseTrigger(); - - void Activate( void ); - virtual void PostClientActive( void ); - void InitTrigger( void ); - - void Enable( void ); - void Disable( void ); - void Spawn( void ); - void UpdateOnRemove( void ); - void TouchTest( void ); - - // Input handlers - virtual void InputEnable( inputdata_t &inputdata ); - virtual void InputDisable( inputdata_t &inputdata ); - virtual void InputToggle( inputdata_t &inputdata ); - virtual void InputTouchTest ( inputdata_t &inputdata ); - - virtual void InputStartTouch( inputdata_t &inputdata ); - virtual void InputEndTouch( inputdata_t &inputdata ); - - virtual bool UsesFilter( void ){ return ( m_hFilter.Get() != NULL ); } - virtual bool PassesTriggerFilters(CBaseEntity *pOther); - virtual void StartTouch(CBaseEntity *pOther); - virtual void EndTouch(CBaseEntity *pOther); - bool IsTouching( CBaseEntity *pOther ); - - CBaseEntity *GetTouchedEntityOfType( const char *sClassName ); - - int DrawDebugTextOverlays(void); - - // by default, triggers don't deal with TraceAttack - void TraceAttack(CBaseEntity *pAttacker, float flDamage, const Vector &vecDir, trace_t *ptr, int bitsDamageType) {} - - bool m_bDisabled; - string_t m_iFilterName; - CHandle m_hFilter; - -protected: - - // Outputs - COutputEvent m_OnStartTouch; - COutputEvent m_OnStartTouchAll; - COutputEvent m_OnEndTouch; - COutputEvent m_OnEndTouchAll; - COutputEvent m_OnTouching; - COutputEvent m_OnNotTouching; - - // Entities currently being touched by this trigger - CUtlVector< EHANDLE > m_hTouchingEntities; - - DECLARE_DATADESC(); -}; - -//----------------------------------------------------------------------------- -// Purpose: Variable sized repeatable trigger. Must be targeted at one or more entities. -// If "delay" is set, the trigger waits some time after activating before firing. -// "wait" : Seconds between triggerings. (.2 default/minimum) -//----------------------------------------------------------------------------- -class CTriggerMultiple : public CBaseTrigger -{ - DECLARE_CLASS( CTriggerMultiple, CBaseTrigger ); -public: - void Spawn( void ); - void MultiTouch( CBaseEntity *pOther ); - void MultiWaitOver( void ); - void ActivateMultiTrigger(CBaseEntity *pActivator); - - DECLARE_DATADESC(); - - // Outputs - COutputEvent m_OnTrigger; -}; - -// Global list of triggers that care about weapon fire -extern CUtlVector< CHandle > g_hWeaponFireTriggers; - - -//------------------------------------------------------------------------------ -// Base VPhysics trigger implementation -// NOTE: This uses vphysics to compute touch events. It doesn't do a per-frame Touch call, so the -// Entity I/O is different from a regular trigger -//------------------------------------------------------------------------------ -#define SF_VPHYSICS_MOTION_MOVEABLE 0x1000 - -class CBaseVPhysicsTrigger : public CBaseEntity -{ - DECLARE_CLASS( CBaseVPhysicsTrigger , CBaseEntity ); - -public: - DECLARE_DATADESC(); - - virtual void Spawn(); - virtual void UpdateOnRemove(); - virtual bool CreateVPhysics(); - virtual void Activate( void ); - virtual bool PassesTriggerFilters(CBaseEntity *pOther); - - // UNDONE: Pass trigger event in or change Start/EndTouch. Add ITriggerVPhysics perhaps? - // BUGBUG: If a player touches two of these, his movement will screw up. - // BUGBUG: If a player uses crouch/uncrouch it will generate touch events and clear the motioncontroller flag - virtual void StartTouch( CBaseEntity *pOther ); - virtual void EndTouch( CBaseEntity *pOther ); - - void InputToggle( inputdata_t &inputdata ); - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - - -protected: - bool m_bDisabled; - string_t m_iFilterName; - CHandle m_hFilter; -}; - -//----------------------------------------------------------------------------- -// Purpose: Hurts anything that touches it. If the trigger has a targetname, -// firing it will toggle state. -//----------------------------------------------------------------------------- -class CTriggerHurt : public CBaseTrigger -{ -public: - CTriggerHurt() - { - // This field came along after levels were built so the field defaults to 20 here in the constructor. - m_flDamageCap = 20.0f; - } - - DECLARE_CLASS( CTriggerHurt, CBaseTrigger ); - - void Spawn( void ); - void RadiationThink( void ); - void HurtThink( void ); - void Touch( CBaseEntity *pOther ); - void EndTouch( CBaseEntity *pOther ); - bool HurtEntity( CBaseEntity *pOther, float damage ); - int HurtAllTouchers( float dt ); - - DECLARE_DATADESC(); - - float m_flOriginalDamage; // Damage as specified by the level designer. - float m_flDamage; // Damage per second. - float m_flDamageCap; // Maximum damage per second. - float m_flLastDmgTime; // Time that we last applied damage. - float m_flDmgResetTime; // For forgiveness, the time to reset the counter that accumulates damage. - int m_bitsDamageInflict; // DMG_ damage type that the door or tigger does - int m_damageModel; - bool m_bNoDmgForce; // Should damage from this trigger impart force on what it's hurting - - enum - { - DAMAGEMODEL_NORMAL = 0, - DAMAGEMODEL_DOUBLE_FORGIVENESS, - }; - - // Outputs - COutputEvent m_OnHurt; - COutputEvent m_OnHurtPlayer; - - CUtlVector m_hurtEntities; -}; - -#endif // TRIGGERS_H diff --git a/game/server/util.cpp b/game/server/util.cpp deleted file mode 100644 index 46bf2b314..000000000 --- a/game/server/util.cpp +++ /dev/null @@ -1,3275 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Utility code. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "saverestore.h" -#include "globalstate.h" -#include -#include "shake.h" -#include "decals.h" -#include "player.h" -#include "gamerules.h" -#include "entitylist.h" -#include "bspfile.h" -#include "mathlib/mathlib.h" -#include "IEffects.h" -#include "vstdlib/random.h" -#include "soundflags.h" -#include "ispatialpartition.h" -#include "igamesystem.h" -#include "saverestoretypes.h" -#include "checksum_crc.h" -#include "hierarchy.h" -#include "iservervehicle.h" -#include "te_effect_dispatch.h" -#include "utldict.h" -#include "collisionutils.h" -#include "movevars_shared.h" -#include "inetchannelinfo.h" -#include "tier0/vprof.h" -#include "ndebugoverlay.h" -#include "engine/ivdebugoverlay.h" -#include "datacache/imdlcache.h" -#include "util.h" - -#ifdef PORTAL -#include "PortalSimulation.h" -//#include "Portal_PhysicsEnvironmentMgr.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern short g_sModelIndexSmoke; // (in combatweapon.cpp) holds the index for the smoke cloud -extern short g_sModelIndexBloodDrop; // (in combatweapon.cpp) holds the sprite index for the initial blood -extern short g_sModelIndexBloodSpray; // (in combatweapon.cpp) holds the sprite index for splattered blood - -#ifdef DEBUG -void DBG_AssertFunction( bool fExpr, const char *szExpr, const char *szFile, int szLine, const char *szMessage ) -{ - if (fExpr) - return; - char szOut[512]; - if (szMessage != NULL) - Q_snprintf(szOut,sizeof(szOut), "ASSERT FAILED:\n %s \n(%s@%d)\n%s", szExpr, szFile, szLine, szMessage); - else - Q_snprintf(szOut,sizeof(szOut), "ASSERT FAILED:\n %s \n(%s@%d)\n", szExpr, szFile, szLine); - Warning( szOut); -} -#endif // DEBUG - - -//----------------------------------------------------------------------------- -// Entity creation factory -//----------------------------------------------------------------------------- -class CEntityFactoryDictionary : public IEntityFactoryDictionary -{ -public: - CEntityFactoryDictionary(); - - virtual void InstallFactory( IEntityFactory *pFactory, const char *pClassName ); - virtual IServerNetworkable *Create( const char *pClassName ); - virtual void Destroy( const char *pClassName, IServerNetworkable *pNetworkable ); - virtual const char *GetCannonicalName( const char *pClassName ); - void ReportEntitySizes(); - -private: - IEntityFactory *FindFactory( const char *pClassName ); -public: - CUtlDict< IEntityFactory *, unsigned short > m_Factories; -}; - -//----------------------------------------------------------------------------- -// Singleton accessor -//----------------------------------------------------------------------------- -IEntityFactoryDictionary *EntityFactoryDictionary() -{ - static CEntityFactoryDictionary s_EntityFactory; - return &s_EntityFactory; -} - -void DumpEntityFactories_f() -{ - CEntityFactoryDictionary *dict = ( CEntityFactoryDictionary * )EntityFactoryDictionary(); - if ( dict ) - { - for ( int i = dict->m_Factories.First(); i != dict->m_Factories.InvalidIndex(); i = dict->m_Factories.Next( i ) ) - { - Warning( "%s\n", dict->m_Factories.GetElementName( i ) ); - } - } -} - -static ConCommand dumpentityfactories( "dumpentityfactories", DumpEntityFactories_f, "Lists all entity factory names.", FCVAR_GAMEDLL ); - - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -CON_COMMAND( dump_entity_sizes, "Print sizeof(entclass)" ) -{ - ((CEntityFactoryDictionary*)EntityFactoryDictionary())->ReportEntitySizes(); -} - - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CEntityFactoryDictionary::CEntityFactoryDictionary() : m_Factories( true, 0, 128 ) -{ -} - - -//----------------------------------------------------------------------------- -// Finds a new factory -//----------------------------------------------------------------------------- -IEntityFactory *CEntityFactoryDictionary::FindFactory( const char *pClassName ) -{ - unsigned short nIndex = m_Factories.Find( pClassName ); - if ( nIndex == m_Factories.InvalidIndex() ) - return NULL; - return m_Factories[nIndex]; -} - - -//----------------------------------------------------------------------------- -// Install a new factory -//----------------------------------------------------------------------------- -void CEntityFactoryDictionary::InstallFactory( IEntityFactory *pFactory, const char *pClassName ) -{ - Assert( FindFactory( pClassName ) == NULL ); - m_Factories.Insert( pClassName, pFactory ); -} - - -//----------------------------------------------------------------------------- -// Instantiate something using a factory -//----------------------------------------------------------------------------- -IServerNetworkable *CEntityFactoryDictionary::Create( const char *pClassName ) -{ - IEntityFactory *pFactory = FindFactory( pClassName ); - if ( !pFactory ) - { - Warning("Attempted to create unknown entity type %s!\n", pClassName ); - return NULL; - } -#if defined(TRACK_ENTITY_MEMORY) && defined(USE_MEM_DEBUG) - MEM_ALLOC_CREDIT_( m_Factories.GetElementName( m_Factories.Find( pClassName ) ) ); -#endif - return pFactory->Create( pClassName ); -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -const char *CEntityFactoryDictionary::GetCannonicalName( const char *pClassName ) -{ - return m_Factories.GetElementName( m_Factories.Find( pClassName ) ); -} - -//----------------------------------------------------------------------------- -// Destroy a networkable -//----------------------------------------------------------------------------- -void CEntityFactoryDictionary::Destroy( const char *pClassName, IServerNetworkable *pNetworkable ) -{ - IEntityFactory *pFactory = FindFactory( pClassName ); - if ( !pFactory ) - { - Warning("Attempted to destroy unknown entity type %s!\n", pClassName ); - return; - } - - pFactory->Destroy( pNetworkable ); -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -void CEntityFactoryDictionary::ReportEntitySizes() -{ - for ( int i = m_Factories.First(); i != m_Factories.InvalidIndex(); i = m_Factories.Next( i ) ) - { - Msg( " %s: %d", m_Factories.GetElementName( i ), m_Factories[i]->GetEntitySize() ); - } -} - - -//----------------------------------------------------------------------------- -// class CFlaggedEntitiesEnum -//----------------------------------------------------------------------------- - -CFlaggedEntitiesEnum::CFlaggedEntitiesEnum( CBaseEntity **pList, int listMax, int flagMask ) -{ - m_pList = pList; - m_listMax = listMax; - m_flagMask = flagMask; - m_count = 0; -} - -bool CFlaggedEntitiesEnum::AddToList( CBaseEntity *pEntity ) -{ - if ( m_count >= m_listMax ) - { - AssertMsgOnce( 0, "reached enumerated list limit. Increase limit, decrease radius, or make it so entity flags will work for you" ); - return false; - } - m_pList[m_count] = pEntity; - m_count++; - return true; -} - -IterationRetval_t CFlaggedEntitiesEnum::EnumElement( IHandleEntity *pHandleEntity ) -{ - CBaseEntity *pEntity = gEntList.GetBaseEntity( pHandleEntity->GetRefEHandle() ); - if ( pEntity ) - { - if ( m_flagMask && !(pEntity->GetFlags() & m_flagMask) ) // Does it meet the criteria? - return ITERATION_CONTINUE; - - if ( !AddToList( pEntity ) ) - return ITERATION_STOP; - } - - return ITERATION_CONTINUE; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int UTIL_PrecacheDecal( const char *name, bool preload ) -{ - // If this is out of order, make sure to warn. - if ( !CBaseEntity::IsPrecacheAllowed() ) - { - if ( !engine->IsDecalPrecached( name ) ) - { - Assert( !"UTIL_PrecacheDecal: too late" ); - - Warning( "Late precache of %s\n", name ); - } - } - - return engine->PrecacheDecal( name, preload ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float UTIL_GetSimulationInterval() -{ - if ( CBaseEntity::IsSimulatingOnAlternateTicks() ) - return ( TICK_INTERVAL * 2.0 ); - return TICK_INTERVAL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int UTIL_EntitiesInBox( const Vector &mins, const Vector &maxs, CFlaggedEntitiesEnum *pEnum ) -{ - partition->EnumerateElementsInBox( PARTITION_ENGINE_NON_STATIC_EDICTS, mins, maxs, false, pEnum ); - return pEnum->GetCount(); -} - -int UTIL_EntitiesAlongRay( const Ray_t &ray, CFlaggedEntitiesEnum *pEnum ) -{ - partition->EnumerateElementsAlongRay( PARTITION_ENGINE_NON_STATIC_EDICTS, ray, false, pEnum ); - return pEnum->GetCount(); -} - -int UTIL_EntitiesInSphere( const Vector ¢er, float radius, CFlaggedEntitiesEnum *pEnum ) -{ - partition->EnumerateElementsInSphere( PARTITION_ENGINE_NON_STATIC_EDICTS, center, radius, false, pEnum ); - return pEnum->GetCount(); -} - -CEntitySphereQuery::CEntitySphereQuery( const Vector ¢er, float radius, int flagMask ) -{ - m_listIndex = 0; - m_listCount = UTIL_EntitiesInSphere( m_pList, ARRAYSIZE(m_pList), center, radius, flagMask ); -} - -CBaseEntity *CEntitySphereQuery::GetCurrentEntity() -{ - if ( m_listIndex < m_listCount ) - return m_pList[m_listIndex]; - return NULL; -} - - -//----------------------------------------------------------------------------- -// Simple trace filter -//----------------------------------------------------------------------------- -class CTracePassFilter : public CTraceFilter -{ -public: - CTracePassFilter( IHandleEntity *pPassEnt ) : m_pPassEnt( pPassEnt ) {} - - bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) - { - if ( !StandardFilterRules( pHandleEntity, contentsMask ) ) - return false; - - if (!PassServerEntityFilter( pHandleEntity, m_pPassEnt )) - return false; - - return true; - } - -private: - IHandleEntity *m_pPassEnt; -}; - - -//----------------------------------------------------------------------------- -// Drops an entity onto the floor -//----------------------------------------------------------------------------- -int UTIL_DropToFloor( CBaseEntity *pEntity, unsigned int mask, CBaseEntity *pIgnore) -{ - // Assume no ground - pEntity->SetGroundEntity( NULL ); - - Assert( pEntity ); - - trace_t trace; - // HACK: is this really the only sure way to detect crossing a terrain boundry? - UTIL_TraceEntity( pEntity, pEntity->GetAbsOrigin(), pEntity->GetAbsOrigin(), mask, pIgnore, pEntity->GetCollisionGroup(), &trace ); - if (trace.fraction == 0.0) - return -1; - - UTIL_TraceEntity( pEntity, pEntity->GetAbsOrigin(), pEntity->GetAbsOrigin() - Vector(0,0,256), mask, pIgnore, pEntity->GetCollisionGroup(), &trace ); - - if (trace.allsolid) - return -1; - - if (trace.fraction == 1) - return 0; - - pEntity->SetAbsOrigin( trace.endpos ); - pEntity->SetGroundEntity( trace.m_pEnt ); - - return 1; -} - -//----------------------------------------------------------------------------- -// Returns false if any part of the bottom of the entity is off an edge that -// is not a staircase. -//----------------------------------------------------------------------------- -bool UTIL_CheckBottom( CBaseEntity *pEntity, ITraceFilter *pTraceFilter, float flStepSize ) -{ - Vector mins, maxs, start, stop; - trace_t trace; - int x, y; - float mid, bottom; - - Assert( pEntity ); - - CTracePassFilter traceFilter(pEntity); - if ( !pTraceFilter ) - { - pTraceFilter = &traceFilter; - } - - unsigned int mask = pEntity->PhysicsSolidMaskForEntity(); - - VectorAdd (pEntity->GetAbsOrigin(), pEntity->WorldAlignMins(), mins); - VectorAdd (pEntity->GetAbsOrigin(), pEntity->WorldAlignMaxs(), maxs); - - // if all of the points under the corners are solid world, don't bother - // with the tougher checks - // the corners must be within 16 of the midpoint - start[2] = mins[2] - 1; - for (x=0 ; x<=1 ; x++) - { - for (y=0 ; y<=1 ; y++) - { - start[0] = x ? maxs[0] : mins[0]; - start[1] = y ? maxs[1] : mins[1]; - if (enginetrace->GetPointContents(start) != CONTENTS_SOLID) - goto realcheck; - } - } - return true; // we got out easy - -realcheck: - // check it for real... - start[2] = mins[2] + flStepSize; // seems to help going up/down slopes. - - // the midpoint must be within 16 of the bottom - start[0] = stop[0] = (mins[0] + maxs[0])*0.5; - start[1] = stop[1] = (mins[1] + maxs[1])*0.5; - stop[2] = start[2] - 2*flStepSize; - - UTIL_TraceLine( start, stop, mask, pTraceFilter, &trace ); - - if (trace.fraction == 1.0) - return false; - mid = bottom = trace.endpos[2]; - - // the corners must be within 16 of the midpoint - for (x=0 ; x<=1 ; x++) - { - for (y=0 ; y<=1 ; y++) - { - start[0] = stop[0] = x ? maxs[0] : mins[0]; - start[1] = stop[1] = y ? maxs[1] : mins[1]; - - UTIL_TraceLine( start, stop, mask, pTraceFilter, &trace ); - - if (trace.fraction != 1.0 && trace.endpos[2] > bottom) - bottom = trace.endpos[2]; - if (trace.fraction == 1.0 || mid - trace.endpos[2] > flStepSize) - return false; - } - } - return true; -} - - - -bool g_bDisableEhandleAccess = false; -bool g_bReceivedChainedUpdateOnRemove = false; -//----------------------------------------------------------------------------- -// Purpose: Sets the entity up for deletion. Entity will not actually be deleted -// until the next frame, so there can be no pointer errors. -// Input : *oldObj - object to delete -//----------------------------------------------------------------------------- -void UTIL_Remove( IServerNetworkable *oldObj ) -{ - CServerNetworkProperty* pProp = static_cast( oldObj ); - if ( !pProp || pProp->IsMarkedForDeletion() ) - return; - - if ( PhysIsInCallback() ) - { - // This assert means that someone is deleting an entity inside a callback. That isn't supported so - // this code will defer the deletion of that object until the end of the current physics simulation frame - // Since this is hidden from the calling code it's preferred to call PhysCallbackRemove() directly from the caller - // in case the deferred delete will have unwanted results (like continuing to receive callbacks). That will make it - // obvious why the unwanted results are happening so the caller can handle them appropriately. (some callbacks can be masked - // or the calling entity can be flagged to filter them in most cases) - Assert(0); - PhysCallbackRemove(oldObj); - return; - } - - // mark it for deletion - pProp->MarkForDeletion( ); - - CBaseEntity *pBaseEnt = oldObj->GetBaseEntity(); - if ( pBaseEnt ) - { -#ifdef PORTAL //make sure entities are in the primary physics environment for the portal mod, this code should be safe even if the entity is in neither extra environment - CPortalSimulator::Pre_UTIL_Remove( pBaseEnt ); -#endif - g_bReceivedChainedUpdateOnRemove = false; - pBaseEnt->UpdateOnRemove(); - - Assert( g_bReceivedChainedUpdateOnRemove ); - - // clear oldObj targetname / other flags now - pBaseEnt->SetName( NULL_STRING ); - -#ifdef PORTAL - CPortalSimulator::Post_UTIL_Remove( pBaseEnt ); -#endif - } - - gEntList.AddToDeleteList( oldObj ); -} - -void UTIL_Remove( CBaseEntity *oldObj ) -{ - if ( !oldObj ) - return; - UTIL_Remove( oldObj->NetworkProp() ); -} - -static int s_RemoveImmediateSemaphore = 0; -void UTIL_DisableRemoveImmediate() -{ - s_RemoveImmediateSemaphore++; -} -void UTIL_EnableRemoveImmediate() -{ - s_RemoveImmediateSemaphore--; - Assert(s_RemoveImmediateSemaphore>=0); -} -//----------------------------------------------------------------------------- -// Purpose: deletes an entity, without any delay. WARNING! Only use this when sure -// no pointers rely on this entity. -// Input : *oldObj - the entity to delete -//----------------------------------------------------------------------------- -void UTIL_RemoveImmediate( CBaseEntity *oldObj ) -{ - // valid pointer or already removed? - if ( !oldObj || oldObj->IsEFlagSet(EFL_KILLME) ) - return; - - if ( s_RemoveImmediateSemaphore ) - { - UTIL_Remove(oldObj); - return; - } - -#ifdef PORTAL //make sure entities are in the primary physics environment for the portal mod, this code should be safe even if the entity is in neither extra environment - CPortalSimulator::Pre_UTIL_Remove( oldObj ); -#endif - - oldObj->AddEFlags( EFL_KILLME ); // Make sure to ignore further calls into here or UTIL_Remove. - - g_bReceivedChainedUpdateOnRemove = false; - oldObj->UpdateOnRemove(); - Assert( g_bReceivedChainedUpdateOnRemove ); - - // Entities shouldn't reference other entities in their destructors - // that type of code should only occur in an UpdateOnRemove call - g_bDisableEhandleAccess = true; - delete oldObj; - g_bDisableEhandleAccess = false; - -#ifdef PORTAL - CPortalSimulator::Post_UTIL_Remove( oldObj ); -#endif -} - - -// returns a CBaseEntity pointer to a player by index. Only returns if the player is spawned and connected -// otherwise returns NULL -// Index is 1 based -CBasePlayer *UTIL_PlayerByIndex( int playerIndex ) -{ - CBasePlayer *pPlayer = NULL; - - if ( playerIndex > 0 && playerIndex <= gpGlobals->maxClients ) - { - edict_t *pPlayerEdict = INDEXENT( playerIndex ); - if ( pPlayerEdict && !pPlayerEdict->IsFree() ) - { - pPlayer = (CBasePlayer*)GetContainingEntity( pPlayerEdict ); - } - } - - return pPlayer; -} - -CBasePlayer* UTIL_PlayerByName( const char *name ) -{ - if ( !name || !name[0] ) - return NULL; - - for (int i = 1; i<=gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - - if ( !pPlayer ) - continue; - - if ( !pPlayer->IsConnected() ) - continue; - - if ( Q_stricmp( pPlayer->GetPlayerName(), name ) == 0 ) - { - return pPlayer; - } - } - - return NULL; -} - -CBasePlayer* UTIL_PlayerByUserId( int userID ) -{ - for (int i = 1; i<=gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - - if ( !pPlayer ) - continue; - - if ( !pPlayer->IsConnected() ) - continue; - - if ( engine->GetPlayerUserId(pPlayer->edict()) == userID ) - { - return pPlayer; - } - } - - return NULL; -} - -// -// Return the local player. -// If this is a multiplayer game, return NULL. -// -CBasePlayer *UTIL_GetLocalPlayer( void ) -{ - if ( gpGlobals->maxClients > 1 ) - { - if ( developer.GetBool() ) - { - Assert( !"UTIL_GetLocalPlayer" ); - -#ifdef DEBUG - Warning( "UTIL_GetLocalPlayer() called in multiplayer game.\n" ); -#endif - } - - return NULL; - } - - return UTIL_PlayerByIndex( 1 ); -} - -// -// Get the local player on a listen server - this is for multiplayer use only -// -CBasePlayer *UTIL_GetListenServerHost( void ) -{ - // no "local player" if this is a dedicated server or a single player game - if (engine->IsDedicatedServer()) - { - Assert( !"UTIL_GetListenServerHost" ); - Warning( "UTIL_GetListenServerHost() called from a dedicated server or single-player game.\n" ); - return NULL; - } - - return UTIL_PlayerByIndex( 1 ); -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Returns true if the command was issued by the listenserver host, or by the dedicated server, via rcon or the server console. - * This is valid during ConCommand execution. - */ -bool UTIL_IsCommandIssuedByServerAdmin( void ) -{ - int issuingPlayerIndex = UTIL_GetCommandClientIndex(); - - if ( engine->IsDedicatedServer() && issuingPlayerIndex > 0 ) - return false; - - if ( issuingPlayerIndex > 1 ) - return false; - - return true; -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Returns a CBaseEntity pointer by entindex. Index is 1 based. - */ -CBaseEntity *UTIL_EntityByIndex( int entityIndex ) -{ - CBaseEntity *entity = NULL; - - if ( entityIndex > 0 ) - { - edict_t *edict = INDEXENT( entityIndex ); - if ( edict && !edict->IsFree() ) - { - entity = GetContainingEntity( edict ); - } - } - - return entity; -} - - -int ENTINDEX( CBaseEntity *pEnt ) -{ - // This works just like ENTINDEX for edicts. - if ( pEnt ) - return pEnt->entindex(); - else - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : playerIndex - -// ping - -// packetloss - -//----------------------------------------------------------------------------- -void UTIL_GetPlayerConnectionInfo( int playerIndex, int& ping, int &packetloss ) -{ - CBasePlayer *player = UTIL_PlayerByIndex( playerIndex ); - - INetChannelInfo *nci = engine->GetPlayerNetInfo(playerIndex); - - if ( nci && player && !player->IsBot() ) - { - float latency = nci->GetAvgLatency( FLOW_OUTGOING ); // in seconds - - // that should be the correct latency, we assume that cmdrate is higher - // then updaterate, what is the case for default settings - const char * szCmdRate = engine->GetClientConVarValue( playerIndex, "cl_cmdrate" ); - - int nCmdRate = MAX( 1, Q_atoi( szCmdRate ) ); - latency -= (0.5f/nCmdRate) + TICKS_TO_TIME( 1.0f ); // correct latency - - // in GoldSrc we had a different, not fixed tickrate. so we have to adjust - // Source pings by half a tick to match the old GoldSrc pings. - latency -= TICKS_TO_TIME( 0.5f ); - - ping = (int)(latency * 1000.0f); // as msecs - ping = clamp( ping, 5, 1000 ); // set bounds, dont show pings under 5 msecs - - packetloss = (int)(100.0f * nci->GetAvgLoss( FLOW_INCOMING )); // loss in percentage - packetloss = clamp( packetloss, 0, 100 ); - } - else - { - ping = 0; - packetloss = 0; - } -} - -static unsigned short FixedUnsigned16( float value, float scale ) -{ - int output; - - output = (int)(value * scale); - if ( output < 0 ) - output = 0; - if ( output > 0xFFFF ) - output = 0xFFFF; - - return (unsigned short)output; -} - - -//----------------------------------------------------------------------------- -// Compute shake amplitude -//----------------------------------------------------------------------------- -inline float ComputeShakeAmplitude( const Vector ¢er, const Vector &shakePt, float amplitude, float radius ) -{ - if ( radius <= 0 ) - return amplitude; - - float localAmplitude = -1; - Vector delta = center - shakePt; - float distance = delta.Length(); - - if ( distance <= radius ) - { - // Make the amplitude fall off over distance - float flPerc = 1.0 - (distance / radius); - localAmplitude = amplitude * flPerc; - } - - return localAmplitude; -} - - -//----------------------------------------------------------------------------- -// Transmits the actual shake event -//----------------------------------------------------------------------------- -inline void TransmitShakeEvent( CBasePlayer *pPlayer, float localAmplitude, float frequency, float duration, ShakeCommand_t eCommand ) -{ - if (( localAmplitude > 0 ) || ( eCommand == SHAKE_STOP )) - { - if ( eCommand == SHAKE_STOP ) - localAmplitude = 0; - - CSingleUserRecipientFilter user( pPlayer ); - user.MakeReliable(); - UserMessageBegin( user, "Shake" ); - WRITE_BYTE( eCommand ); // shake command (SHAKE_START, STOP, FREQUENCY, AMPLITUDE) - WRITE_FLOAT( localAmplitude ); // shake magnitude/amplitude - WRITE_FLOAT( frequency ); // shake noise frequency - WRITE_FLOAT( duration ); // shake lasts this long - MessageEnd(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Shake the screen of all clients within radius. -// radius == 0, shake all clients -// UNDONE: Fix falloff model (disabled)? -// UNDONE: Affect user controls? -// Input : center - Center of screen shake, radius is measured from here. -// amplitude - Amplitude of shake -// frequency - -// duration - duration of shake in seconds. -// radius - Radius of effect, 0 shakes all clients. -// command - One of the following values: -// SHAKE_START - starts the screen shake for all players within the radius -// SHAKE_STOP - stops the screen shake for all players within the radius -// SHAKE_AMPLITUDE - modifies the amplitude of the screen shake -// for all players within the radius -// SHAKE_FREQUENCY - modifies the frequency of the screen shake -// for all players within the radius -// bAirShake - if this is false, then it will only shake players standing on the ground. -//----------------------------------------------------------------------------- -const float MAX_SHAKE_AMPLITUDE = 16.0f; -void UTIL_ScreenShake( const Vector ¢er, float amplitude, float frequency, float duration, float radius, ShakeCommand_t eCommand, bool bAirShake ) -{ - int i; - float localAmplitude; - - if ( amplitude > MAX_SHAKE_AMPLITUDE ) - { - amplitude = MAX_SHAKE_AMPLITUDE; - } - for ( i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBaseEntity *pPlayer = UTIL_PlayerByIndex( i ); - - // - // Only start shakes for players that are on the ground unless doing an air shake. - // - if ( !pPlayer || (!bAirShake && (eCommand == SHAKE_START) && !(pPlayer->GetFlags() & FL_ONGROUND)) ) - { - continue; - } - - localAmplitude = ComputeShakeAmplitude( center, pPlayer->WorldSpaceCenter(), amplitude, radius ); - - // This happens if the player is outside the radius, in which case we should ignore - // all commands - if (localAmplitude < 0) - continue; - - TransmitShakeEvent( (CBasePlayer *)pPlayer, localAmplitude, frequency, duration, eCommand ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Shake an object and all players on or near it -//----------------------------------------------------------------------------- -void UTIL_ScreenShakeObject( CBaseEntity *pEnt, const Vector ¢er, float amplitude, float frequency, float duration, float radius, ShakeCommand_t eCommand, bool bAirShake ) -{ - int i; - float localAmplitude; - - CBaseEntity *pHighestParent = pEnt->GetRootMoveParent(); - for ( i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBaseEntity *pPlayer = UTIL_PlayerByIndex( i ); - if (!pPlayer) - continue; - - // Shake the object, or anything hierarchically attached to it at maximum amplitude - localAmplitude = 0; - if (pHighestParent == pPlayer->GetRootMoveParent()) - { - localAmplitude = amplitude; - } - else if ((pPlayer->GetFlags() & FL_ONGROUND) && (pPlayer->GetGroundEntity()->GetRootMoveParent() == pHighestParent)) - { - // If the player is standing on the object, use maximum amplitude - localAmplitude = amplitude; - } - else - { - // Only shake players that are on the ground. - if ( !bAirShake && !(pPlayer->GetFlags() & FL_ONGROUND) ) - { - continue; - } - - localAmplitude = ComputeShakeAmplitude( center, pPlayer->WorldSpaceCenter(), amplitude, radius ); - - // This happens if the player is outside the radius, - // in which case we should ignore all commands - if (localAmplitude < 0) - continue; - } - - TransmitShakeEvent( (CBasePlayer *)pPlayer, localAmplitude, frequency, duration, eCommand ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Punches the view of all clients within radius. -// If radius is 0, punches all clients. -// Input : center - Center of punch, radius is measured from here. -// radius - Radius of effect, 0 punches all clients. -// bInAir - if this is false, then it will only punch players standing on the ground. -//----------------------------------------------------------------------------- -void UTIL_ViewPunch( const Vector ¢er, QAngle angPunch, float radius, bool bInAir ) -{ - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBaseEntity *pPlayer = UTIL_PlayerByIndex( i ); - - // - // Only apply the punch to players that are on the ground unless doing an air punch. - // - if ( !pPlayer || (!bInAir && !(pPlayer->GetFlags() & FL_ONGROUND)) ) - { - continue; - } - - QAngle angTemp = angPunch; - - if ( radius > 0 ) - { - Vector delta = center - pPlayer->GetAbsOrigin(); - float distance = delta.Length(); - - if ( distance <= radius ) - { - // Make the punch amplitude fall off over distance. - float flPerc = 1.0 - (distance / radius); - angTemp *= flPerc; - } - else - { - continue; - } - } - - pPlayer->ViewPunch( angTemp ); - } -} - - -void UTIL_ScreenFadeBuild( ScreenFade_t &fade, const color32 &color, float fadeTime, float fadeHold, int flags ) -{ - fade.duration = FixedUnsigned16( fadeTime, 1<IsNetClient() ) - return; - - CSingleUserRecipientFilter user( (CBasePlayer *)pEntity ); - user.MakeReliable(); - - UserMessageBegin( user, "Fade" ); // use the magic #1 for "one client" - WRITE_SHORT( fade.duration ); // fade lasts this long - WRITE_SHORT( fade.holdTime ); // fade lasts this long - WRITE_SHORT( fade.fadeFlags ); // fade type (in / out) - WRITE_BYTE( fade.r ); // fade red - WRITE_BYTE( fade.g ); // fade green - WRITE_BYTE( fade.b ); // fade blue - WRITE_BYTE( fade.a ); // fade blue - MessageEnd(); -} - - -void UTIL_ScreenFadeAll( const color32 &color, float fadeTime, float fadeHold, int flags ) -{ - int i; - ScreenFade_t fade; - - - UTIL_ScreenFadeBuild( fade, color, fadeTime, fadeHold, flags ); - - for ( i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBaseEntity *pPlayer = UTIL_PlayerByIndex( i ); - - UTIL_ScreenFadeWrite( fade, pPlayer ); - } -} - - -void UTIL_ScreenFade( CBaseEntity *pEntity, const color32 &color, float fadeTime, float fadeHold, int flags ) -{ - ScreenFade_t fade; - - UTIL_ScreenFadeBuild( fade, color, fadeTime, fadeHold, flags ); - UTIL_ScreenFadeWrite( fade, pEntity ); -} - - -void UTIL_HudMessage( CBasePlayer *pToPlayer, const hudtextparms_t &textparms, const char *pMessage ) -{ - CRecipientFilter filter; - - if( pToPlayer ) - { - filter.AddRecipient( pToPlayer ); - } - else - { - filter.AddAllPlayers(); - } - - filter.MakeReliable(); - - UserMessageBegin( filter, "HudMsg" ); - WRITE_BYTE ( textparms.channel & 0xFF ); - WRITE_FLOAT( textparms.x ); - WRITE_FLOAT( textparms.y ); - WRITE_BYTE ( textparms.r1 ); - WRITE_BYTE ( textparms.g1 ); - WRITE_BYTE ( textparms.b1 ); - WRITE_BYTE ( textparms.a1 ); - WRITE_BYTE ( textparms.r2 ); - WRITE_BYTE ( textparms.g2 ); - WRITE_BYTE ( textparms.b2 ); - WRITE_BYTE ( textparms.a2 ); - WRITE_BYTE ( textparms.effect ); - WRITE_FLOAT( textparms.fadeinTime ); - WRITE_FLOAT( textparms.fadeoutTime ); - WRITE_FLOAT( textparms.holdTime ); - WRITE_FLOAT( textparms.fxTime ); - WRITE_STRING( pMessage ); - MessageEnd(); -} - -void UTIL_HudMessageAll( const hudtextparms_t &textparms, const char *pMessage ) -{ - UTIL_HudMessage( NULL, textparms, pMessage ); -} - -void UTIL_HudHintText( CBaseEntity *pEntity, const char *pMessage ) -{ - if ( !pEntity ) - return; - - CSingleUserRecipientFilter user( (CBasePlayer *)pEntity ); - user.MakeReliable(); - UserMessageBegin( user, "KeyHintText" ); - WRITE_BYTE( 1 ); // one string - WRITE_STRING( pMessage ); - MessageEnd(); -} - -void UTIL_ClientPrintFilter( IRecipientFilter& filter, int msg_dest, const char *msg_name, const char *param1, const char *param2, const char *param3, const char *param4 ) -{ - UserMessageBegin( filter, "TextMsg" ); - WRITE_BYTE( msg_dest ); - WRITE_STRING( msg_name ); - - if ( param1 ) - WRITE_STRING( param1 ); - else - WRITE_STRING( "" ); - - if ( param2 ) - WRITE_STRING( param2 ); - else - WRITE_STRING( "" ); - - if ( param3 ) - WRITE_STRING( param3 ); - else - WRITE_STRING( "" ); - - if ( param4 ) - WRITE_STRING( param4 ); - else - WRITE_STRING( "" ); - - MessageEnd(); -} - -void UTIL_ClientPrintAll( int msg_dest, const char *msg_name, const char *param1, const char *param2, const char *param3, const char *param4 ) -{ - CReliableBroadcastRecipientFilter filter; - - UTIL_ClientPrintFilter( filter, msg_dest, msg_name, param1, param2, param3, param4 ); -} - -void ClientPrint( CBasePlayer *player, int msg_dest, const char *msg_name, const char *param1, const char *param2, const char *param3, const char *param4 ) -{ - if ( !player ) - return; - - CSingleUserRecipientFilter user( player ); - user.MakeReliable(); - - UTIL_ClientPrintFilter( user, msg_dest, msg_name, param1, param2, param3, param4 ); -} - -void UTIL_SayTextFilter( IRecipientFilter& filter, const char *pText, CBasePlayer *pPlayer, bool bChat ) -{ - UserMessageBegin( filter, "SayText" ); - if ( pPlayer ) - { - WRITE_BYTE( pPlayer->entindex() ); - } - else - { - WRITE_BYTE( 0 ); // world, dedicated server says - } - WRITE_STRING( pText ); - WRITE_BYTE( bChat ); - MessageEnd(); -} - -void UTIL_SayText2Filter( IRecipientFilter& filter, CBasePlayer *pEntity, bool bChat, const char *msg_name, const char *param1, const char *param2, const char *param3, const char *param4 ) -{ - UserMessageBegin( filter, "SayText2" ); - if ( pEntity ) - { - WRITE_BYTE( pEntity->entindex() ); - } - else - { - WRITE_BYTE( 0 ); // world, dedicated server says - } - - WRITE_BYTE( bChat ); - - WRITE_STRING( msg_name ); - - if ( param1 ) - WRITE_STRING( param1 ); - else - WRITE_STRING( "" ); - - if ( param2 ) - WRITE_STRING( param2 ); - else - WRITE_STRING( "" ); - - if ( param3 ) - WRITE_STRING( param3 ); - else - WRITE_STRING( "" ); - - if ( param4 ) - WRITE_STRING( param4 ); - else - WRITE_STRING( "" ); - - MessageEnd(); -} - -void UTIL_SayText( const char *pText, CBasePlayer *pToPlayer ) -{ - if ( !pToPlayer->IsNetClient() ) - return; - - CSingleUserRecipientFilter user( pToPlayer ); - user.MakeReliable(); - - UTIL_SayTextFilter( user, pText, pToPlayer, false ); -} - -void UTIL_SayTextAll( const char *pText, CBasePlayer *pPlayer, bool bChat ) -{ - CReliableBroadcastRecipientFilter filter; - UTIL_SayTextFilter( filter, pText, pPlayer, bChat ); -} - -void UTIL_ShowMessage( const char *pString, CBasePlayer *pPlayer ) -{ - CRecipientFilter filter; - - if ( pPlayer ) - { - filter.AddRecipient( pPlayer ); - } - else - { - filter.AddAllPlayers(); - } - - filter.MakeReliable(); - - UserMessageBegin( filter, "HudText" ); - WRITE_STRING( pString ); - MessageEnd(); -} - - -void UTIL_ShowMessageAll( const char *pString ) -{ - UTIL_ShowMessage( pString, NULL ); -} - -// So we always return a valid surface -static csurface_t g_NullSurface = { "**empty**", 0 }; - -void UTIL_SetTrace(trace_t& trace, const Ray_t &ray, edict_t *ent, float fraction, - int hitgroup, unsigned int contents, const Vector& normal, float intercept ) -{ - trace.startsolid = (fraction == 0.0f); - trace.fraction = fraction; - VectorCopy( ray.m_Start, trace.startpos ); - VectorMA( ray.m_Start, fraction, ray.m_Delta, trace.endpos ); - VectorCopy( normal, trace.plane.normal ); - trace.plane.dist = intercept; - trace.m_pEnt = CBaseEntity::Instance( ent ); - trace.hitgroup = hitgroup; - trace.surface = g_NullSurface; - trace.contents = contents; -} - -void UTIL_ClearTrace( trace_t &trace ) -{ - memset( &trace, 0, sizeof(trace)); - trace.fraction = 1.f; - trace.fractionleftsolid = 0; - trace.surface = g_NullSurface; -} - - - -//----------------------------------------------------------------------------- -// Sets the entity size -//----------------------------------------------------------------------------- -static void SetMinMaxSize (CBaseEntity *pEnt, const Vector& mins, const Vector& maxs ) -{ - for ( int i=0 ; i<3 ; i++ ) - { - if ( mins[i] > maxs[i] ) - { - Error( "%s: backwards mins/maxs", ( pEnt ) ? pEnt->GetDebugName() : "" ); - } - } - - Assert( pEnt ); - - pEnt->SetCollisionBounds( mins, maxs ); -} - - -//----------------------------------------------------------------------------- -// Sets the model size -//----------------------------------------------------------------------------- -void UTIL_SetSize( CBaseEntity *pEnt, const Vector &vecMin, const Vector &vecMax ) -{ - SetMinMaxSize (pEnt, vecMin, vecMax); -} - - -//----------------------------------------------------------------------------- -// Sets the model to be associated with an entity -//----------------------------------------------------------------------------- -void UTIL_SetModel( CBaseEntity *pEntity, const char *pModelName ) -{ - // check to see if model was properly precached - int i = modelinfo->GetModelIndex( pModelName ); - if ( i < 0 ) - { - Error("%i/%s - %s: UTIL_SetModel: not precached: %s\n", pEntity->entindex(), - STRING( pEntity->GetEntityName() ), - pEntity->GetClassname(), pModelName); - } - - pEntity->SetModelIndex( i ) ; - pEntity->SetModelName( AllocPooledString( pModelName ) ); - - // brush model - const model_t *mod = modelinfo->GetModel( i ); - if ( mod ) - { - Vector mins, maxs; - modelinfo->GetModelBounds( mod, mins, maxs ); - SetMinMaxSize (pEntity, mins, maxs); - } - else - { - SetMinMaxSize (pEntity, vec3_origin, vec3_origin); - } - - CBaseAnimating *pAnimating = pEntity->GetBaseAnimating(); - if ( pAnimating ) - { - pAnimating->m_nForceBone = 0; - } -} - - -void UTIL_SetOrigin( CBaseEntity *entity, const Vector &vecOrigin, bool bFireTriggers ) -{ - entity->SetLocalOrigin( vecOrigin ); - if ( bFireTriggers ) - { - entity->PhysicsTouchTriggers(); - } -} - - -void UTIL_ParticleEffect( const Vector &vecOrigin, const Vector &vecDirection, ULONG ulColor, ULONG ulCount ) -{ - Msg( "UTIL_ParticleEffect: Disabled\n" ); -} - -void UTIL_Smoke( const Vector &origin, const float scale, const float framerate ) -{ - g_pEffects->Smoke( origin, g_sModelIndexSmoke, scale, framerate ); -} - -// snaps a vector to the nearest axis vector (if within epsilon) -void UTIL_SnapDirectionToAxis( Vector &direction, float epsilon ) -{ - float proj = 1 - epsilon; - for ( int i = 0; i < 3; i ++ ) - { - if ( fabs(direction[i]) > proj ) - { - // snap to axis unit vector - if ( direction[i] < 0 ) - direction[i] = -1.0f; - else - direction[i] = 1.0f; - direction[(i+1)%3] = 0; - direction[(i+2)%3] = 0; - return; - } - } -} - -char *UTIL_VarArgs( const char *format, ... ) -{ - va_list argptr; - static char string[1024]; - - va_start (argptr, format); - Q_vsnprintf(string, sizeof(string), format,argptr); - va_end (argptr); - - return string; -} - -bool UTIL_IsMasterTriggered(string_t sMaster, CBaseEntity *pActivator) -{ - if (sMaster != NULL_STRING) - { - CBaseEntity *pMaster = gEntList.FindEntityByName( NULL, sMaster, NULL, pActivator ); - - if ( pMaster && (pMaster->ObjectCaps() & FCAP_MASTER) ) - { - return pMaster->IsTriggered( pActivator ); - } - - Warning( "Master was null or not a master!\n"); - } - - // if this isn't a master entity, just say yes. - return true; -} - -void UTIL_BloodStream( const Vector &origin, const Vector &direction, int color, int amount ) -{ - if ( !UTIL_ShouldShowBlood( color ) ) - return; - - if ( g_Language.GetInt() == LANGUAGE_GERMAN && color == BLOOD_COLOR_RED ) - color = 0; - - CPVSFilter filter( origin ); - te->BloodStream( filter, 0.0, &origin, &direction, 247, 63, 14, 255, MIN( amount, 255 ) ); -} - - -Vector UTIL_RandomBloodVector( void ) -{ - Vector direction; - - direction.x = random->RandomFloat ( -1, 1 ); - direction.y = random->RandomFloat ( -1, 1 ); - direction.z = random->RandomFloat ( 0, 1 ); - - return direction; -} - - -//------------------------------------------------------------------------------ -// Purpose : Creates both an decal and any associated impact effects (such -// as flecks) for the given iDamageType and the trace's end position -// Input : -// Output : -//------------------------------------------------------------------------------ -void UTIL_ImpactTrace( trace_t *pTrace, int iDamageType, const char *pCustomImpactName ) -{ - CBaseEntity *pEntity = pTrace->m_pEnt; - - // Is the entity valid, is the surface sky? - if ( !pEntity || !UTIL_IsValidEntity( pEntity ) || (pTrace->surface.flags & SURF_SKY) ) - return; - - if ( pTrace->fraction == 1.0 ) - return; - - pEntity->ImpactTrace( pTrace, iDamageType, pCustomImpactName ); -} - -/* -============== -UTIL_PlayerDecalTrace - -A player is trying to apply his custom decal for the spray can. -Tell connected clients to display it, or use the default spray can decal -if the custom can't be loaded. -============== -*/ -void UTIL_PlayerDecalTrace( trace_t *pTrace, int playernum ) -{ - if (pTrace->fraction == 1.0) - return; - - CBroadcastRecipientFilter filter; - - te->PlayerDecal( filter, 0.0, - &pTrace->endpos, playernum, pTrace->m_pEnt->entindex() ); -} - -bool UTIL_TeamsMatch( const char *pTeamName1, const char *pTeamName2 ) -{ - // Everyone matches unless it's teamplay - if ( !g_pGameRules->IsTeamplay() ) - return true; - - // Both on a team? - if ( *pTeamName1 != 0 && *pTeamName2 != 0 ) - { - if ( !stricmp( pTeamName1, pTeamName2 ) ) // Same Team? - return true; - } - - return false; -} - - -void UTIL_AxisStringToPointPoint( Vector &start, Vector &end, const char *pString ) -{ - char tmpstr[256]; - - Q_strncpy( tmpstr, pString, sizeof(tmpstr) ); - char *pVec = strtok( tmpstr, "," ); - int i = 0; - while ( pVec != NULL && *pVec ) - { - if ( i == 0 ) - { - UTIL_StringToVector( start.Base(), pVec ); - i++; - } - else - { - UTIL_StringToVector( end.Base(), pVec ); - } - pVec = strtok( NULL, "," ); - } -} - -void UTIL_AxisStringToPointDir( Vector &start, Vector &dir, const char *pString ) -{ - Vector end; - UTIL_AxisStringToPointPoint( start, end, pString ); - dir = end - start; - VectorNormalize(dir); -} - -void UTIL_AxisStringToUnitDir( Vector &dir, const char *pString ) -{ - Vector start; - UTIL_AxisStringToPointDir( start, dir, pString ); -} - -/* -================================================== -UTIL_ClipPunchAngleOffset -================================================== -*/ - -void UTIL_ClipPunchAngleOffset( QAngle &in, const QAngle &punch, const QAngle &clip ) -{ - QAngle final = in + punch; - - //Clip each component - for ( int i = 0; i < 3; i++ ) - { - if ( final[i] > clip[i] ) - { - final[i] = clip[i]; - } - else if ( final[i] < -clip[i] ) - { - final[i] = -clip[i]; - } - - //Return the result - in[i] = final[i] - punch[i]; - } -} - -float UTIL_WaterLevel( const Vector &position, float minz, float maxz ) -{ - Vector midUp = position; - midUp.z = minz; - - if ( !(UTIL_PointContents(midUp) & MASK_WATER) ) - return minz; - - midUp.z = maxz; - if ( UTIL_PointContents(midUp) & MASK_WATER ) - return maxz; - - float diff = maxz - minz; - while (diff > 1.0) - { - midUp.z = minz + diff/2.0; - if ( UTIL_PointContents(midUp) & MASK_WATER ) - { - minz = midUp.z; - } - else - { - maxz = midUp.z; - } - diff = maxz - minz; - } - - return midUp.z; -} - - -//----------------------------------------------------------------------------- -// Like UTIL_WaterLevel, but *way* less expensive. -// I didn't replace UTIL_WaterLevel everywhere to avoid breaking anything. -//----------------------------------------------------------------------------- -class CWaterTraceFilter : public CTraceFilter -{ -public: - bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) - { - CBaseEntity *pCollide = EntityFromEntityHandle( pHandleEntity ); - - // Static prop case... - if ( !pCollide ) - return false; - - // Only impact water stuff... - if ( pCollide->GetSolidFlags() & FSOLID_VOLUME_CONTENTS ) - return true; - - return false; - } -}; - -float UTIL_FindWaterSurface( const Vector &position, float minz, float maxz ) -{ - Vector vecStart, vecEnd; - vecStart.Init( position.x, position.y, maxz ); - vecEnd.Init( position.x, position.y, minz ); - - Ray_t ray; - trace_t tr; - CWaterTraceFilter waterTraceFilter; - ray.Init( vecStart, vecEnd ); - enginetrace->TraceRay( ray, MASK_WATER, &waterTraceFilter, &tr ); - - return tr.endpos.z; -} - - -extern short g_sModelIndexBubbles;// holds the index for the bubbles model - -void UTIL_Bubbles( const Vector& mins, const Vector& maxs, int count ) -{ - Vector mid = (mins + maxs) * 0.5; - - float flHeight = UTIL_WaterLevel( mid, mid.z, mid.z + 1024 ); - flHeight = flHeight - mins.z; - - CPASFilter filter( mid ); - - te->Bubbles( filter, 0.0, - &mins, &maxs, flHeight, g_sModelIndexBubbles, count, 8.0 ); -} - -void UTIL_BubbleTrail( const Vector& from, const Vector& to, int count ) -{ - // Find water surface will return from.z if the from point is above water - float flStartHeight = UTIL_FindWaterSurface( from, from.z, from.z + 256 ); - flStartHeight = flStartHeight - from.z; - - float flEndHeight = UTIL_FindWaterSurface( to, to.z, to.z + 256 ); - flEndHeight = flEndHeight - to.z; - - if ( ( flStartHeight == 0 ) && ( flEndHeight == 0 ) ) - return; - - float flWaterZ = flStartHeight + from.z; - - const Vector *pFrom = &from; - const Vector *pTo = &to; - Vector vecWaterPoint; - if ( ( flStartHeight == 0 ) || ( flEndHeight == 0 ) ) - { - if ( flStartHeight == 0 ) - { - flWaterZ = flEndHeight + to.z; - } - - float t = IntersectRayWithAAPlane( from, to, 2, 1.0f, flWaterZ ); - Assert( (t >= -1e-3f) && ( t <= 1.0f ) ); - VectorLerp( from, to, t, vecWaterPoint ); - if ( flStartHeight == 0 ) - { - pFrom = &vecWaterPoint; - - // Reduce the count by the actual length - count = (int)( count * ( 1.0f - t ) ); - } - else - { - pTo = &vecWaterPoint; - - // Reduce the count by the actual length - count = (int)( count * t ); - } - } - - CBroadcastRecipientFilter filter; - te->BubbleTrail( filter, 0.0, pFrom, pTo, flWaterZ, g_sModelIndexBubbles, count, 8.0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : Start - -// End - -// ModelIndex - -// FrameStart - -// FrameRate - -// Life - -// Width - -// Noise - -// Red - -// Green - -// Brightness - -// Speed - -//----------------------------------------------------------------------------- -void UTIL_Beam( Vector &Start, Vector &End, int nModelIndex, int nHaloIndex, unsigned char FrameStart, unsigned char FrameRate, - float Life, unsigned char Width, unsigned char EndWidth, unsigned char FadeLength, unsigned char Noise, unsigned char Red, unsigned char Green, - unsigned char Blue, unsigned char Brightness, unsigned char Speed) -{ - CBroadcastRecipientFilter filter; - - te->BeamPoints( filter, 0.0, - &Start, - &End, - nModelIndex, - nHaloIndex, - FrameStart, - FrameRate, - Life, - Width, - EndWidth, - FadeLength, - Noise, - Red, - Green, - Blue, - Brightness, - Speed ); -} - -bool UTIL_IsValidEntity( CBaseEntity *pEnt ) -{ - edict_t *pEdict = pEnt->edict(); - if ( !pEdict || pEdict->IsFree() ) - return false; - return true; -} - - -#define PRECACHE_OTHER_ONCE -// UNDONE: Do we need this to avoid doing too much of this? Measure startup times and see -#if defined( PRECACHE_OTHER_ONCE ) - -#include "utlsymbol.h" -class CPrecacheOtherList : public CAutoGameSystem -{ -public: - CPrecacheOtherList( char const *name ) : CAutoGameSystem( name ) - { - } - virtual void LevelInitPreEntity(); - virtual void LevelShutdownPostEntity(); - - bool AddOrMarkPrecached( const char *pClassname ); - -private: - CUtlSymbolTable m_list; -}; - -void CPrecacheOtherList::LevelInitPreEntity() -{ - m_list.RemoveAll(); -} - -void CPrecacheOtherList::LevelShutdownPostEntity() -{ - m_list.RemoveAll(); -} - -//----------------------------------------------------------------------------- -// Purpose: mark or add -// Input : *pEntity - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CPrecacheOtherList::AddOrMarkPrecached( const char *pClassname ) -{ - CUtlSymbol sym = m_list.Find( pClassname ); - if ( sym.IsValid() ) - return false; - - m_list.AddString( pClassname ); - return true; -} - -CPrecacheOtherList g_PrecacheOtherList( "CPrecacheOtherList" ); -#endif - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *szClassname - -// *modelName - -//----------------------------------------------------------------------------- -void UTIL_PrecacheOther( const char *szClassname, const char *modelName ) -{ -#if defined( PRECACHE_OTHER_ONCE ) - // already done this one?, if not, mark as done - if ( !g_PrecacheOtherList.AddOrMarkPrecached( szClassname ) ) - return; -#endif - - CBaseEntity *pEntity = CreateEntityByName( szClassname ); - if ( !pEntity ) - { - Warning( "NULL Ent in UTIL_PrecacheOther\n" ); - return; - } - - // If we have a specified model, set it before calling precache - if ( modelName && modelName[0] ) - { - pEntity->SetModelName( AllocPooledString( modelName ) ); - } - - if (pEntity) - pEntity->Precache( ); - - UTIL_RemoveImmediate( pEntity ); -} - -//========================================================= -// UTIL_LogPrintf - Prints a logged message to console. -// Preceded by LOG: ( timestamp ) < message > -//========================================================= -void UTIL_LogPrintf( const char *fmt, ... ) -{ - va_list argptr; - char tempString[1024]; - - va_start ( argptr, fmt ); - Q_vsnprintf( tempString, sizeof(tempString), fmt, argptr ); - va_end ( argptr ); - - // Print to server console - engine->LogPrint( tempString ); -} - -//========================================================= -// UTIL_DotPoints - returns the dot product of a line from -// src to check and vecdir. -//========================================================= -float UTIL_DotPoints ( const Vector &vecSrc, const Vector &vecCheck, const Vector &vecDir ) -{ - Vector2D vec2LOS; - - vec2LOS = ( vecCheck - vecSrc ).AsVector2D(); - Vector2DNormalize( vec2LOS ); - - return DotProduct2D(vec2LOS, vecDir.AsVector2D()); -} - - -//========================================================= -// UTIL_StripToken - for redundant keynames -//========================================================= -void UTIL_StripToken( const char *pKey, char *pDest ) -{ - int i = 0; - - while ( pKey[i] && pKey[i] != '#' ) - { - pDest[i] = pKey[i]; - i++; - } - pDest[i] = 0; -} - - -// computes gravity scale for an absolute gravity. Pass the result into CBaseEntity::SetGravity() -float UTIL_ScaleForGravity( float desiredGravity ) -{ - float worldGravity = sv_gravity.GetFloat(); - return worldGravity > 0 ? desiredGravity / worldGravity : 0; -} - - -//----------------------------------------------------------------------------- -// Purpose: Implemented for mathlib.c error handling -// Input : *error - -//----------------------------------------------------------------------------- -extern "C" void Sys_Error( char *error, ... ) -{ - va_list argptr; - char string[1024]; - - va_start( argptr, error ); - Q_vsnprintf( string, sizeof(string), error, argptr ); - va_end( argptr ); - - Warning( "%s", string ); - Assert(0); -} - - -//----------------------------------------------------------------------------- -// Purpose: Spawns an entity into the game, initializing it with the map ent data block -// Input : *pEntity - the newly created entity -// *mapData - pointer a block of entity map data -// Output : -1 if the entity was not successfully created; 0 on success -//----------------------------------------------------------------------------- -int DispatchSpawn( CBaseEntity *pEntity ) -{ - if ( pEntity ) - { - MDLCACHE_CRITICAL_SECTION(); - - // keep a smart pointer that will now if the object gets deleted - EHANDLE pEntSafe; - pEntSafe = pEntity; - - // Initialize these or entities who don't link to the world won't have anything in here - // is this necessary? - //pEntity->SetAbsMins( pEntity->GetOrigin() - Vector(1,1,1) ); - //pEntity->SetAbsMaxs( pEntity->GetOrigin() + Vector(1,1,1) ); - -#if defined(TRACK_ENTITY_MEMORY) && defined(USE_MEM_DEBUG) - const char *pszClassname = NULL; - int iClassname = ((CEntityFactoryDictionary*)EntityFactoryDictionary())->m_Factories.Find( pEntity->GetClassname() ); - if ( iClassname != ((CEntityFactoryDictionary*)EntityFactoryDictionary())->m_Factories.InvalidIndex() ) - pszClassname = ((CEntityFactoryDictionary*)EntityFactoryDictionary())->m_Factories.GetElementName( iClassname ); - if ( pszClassname ) - { - MemAlloc_PushAllocDbgInfo( pszClassname, __LINE__ ); - } -#endif - bool bAsyncAnims = mdlcache->SetAsyncLoad( MDLCACHE_ANIMBLOCK, false ); - CBaseAnimating *pAnimating = pEntity->GetBaseAnimating(); - if (!pAnimating) - { - pEntity->Spawn(); - } - else - { - // Don't allow the PVS check to skip animation setup during spawning - pAnimating->SetBoneCacheFlags( BCF_IS_IN_SPAWN ); - pEntity->Spawn(); - pAnimating->ClearBoneCacheFlags( BCF_IS_IN_SPAWN ); - } - mdlcache->SetAsyncLoad( MDLCACHE_ANIMBLOCK, bAsyncAnims ); - -#if defined(TRACK_ENTITY_MEMORY) && defined(USE_MEM_DEBUG) - if ( pszClassname ) - { - MemAlloc_PopAllocDbgInfo(); - } -#endif - // Try to get the pointer again, in case the spawn function deleted the entity. - // UNDONE: Spawn() should really return a code to ask that the entity be deleted, but - // that would touch too much code for me to do that right now. - - if ( pEntSafe == NULL || pEntity->IsMarkedForDeletion() ) - return -1; - - if ( pEntity->m_iGlobalname != NULL_STRING ) - { - // Handle global stuff here - int globalIndex = GlobalEntity_GetIndex( pEntity->m_iGlobalname ); - if ( globalIndex >= 0 ) - { - // Already dead? delete - if ( GlobalEntity_GetState(globalIndex) == GLOBAL_DEAD ) - { - pEntity->Remove(); - return -1; - } - else if ( !FStrEq(STRING(gpGlobals->mapname), GlobalEntity_GetMap(globalIndex)) ) - { - pEntity->MakeDormant(); // Hasn't been moved to this level yet, wait but stay alive - } - // In this level & not dead, continue on as normal - } - else - { - // Spawned entities default to 'On' - GlobalEntity_Add( pEntity->m_iGlobalname, gpGlobals->mapname, GLOBAL_ON ); -// Msg( "Added global entity %s (%s)\n", pEntity->GetClassname(), STRING(pEntity->m_iGlobalname) ); - } - } - - gEntList.NotifySpawn( pEntity ); - } - - return 0; -} - -// UNDONE: This could be a better test - can we run the absbox through the bsp and see -// if it contains any solid space? or would that eliminate some entities we want to keep? -int UTIL_EntityInSolid( CBaseEntity *ent ) -{ - Vector point; - - CBaseEntity *pParent = ent->GetMoveParent(); - // HACKHACK -- If you're attached to a client, always go through - if ( pParent ) - { - if ( pParent->IsPlayer() ) - return 0; - - ent = ent->GetRootMoveParent(); - } - - point = ent->WorldSpaceCenter(); - return ( enginetrace->GetPointContents( point ) & MASK_SOLID ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Initialize the matrix from an entity -// Input : *pEntity - -//----------------------------------------------------------------------------- -void EntityMatrix::InitFromEntity( CBaseEntity *pEntity, int iAttachment ) -{ - if ( !pEntity ) - { - Identity(); - return; - } - - // Get an attachment's matrix? - if ( iAttachment != 0 ) - { - CBaseAnimating *pAnimating = pEntity->GetBaseAnimating(); - if ( pAnimating && pAnimating->GetModelPtr() ) - { - Vector vOrigin; - QAngle vAngles; - if ( pAnimating->GetAttachment( iAttachment, vOrigin, vAngles ) ) - { - ((VMatrix *)this)->SetupMatrixOrgAngles( vOrigin, vAngles ); - return; - } - } - } - - ((VMatrix *)this)->SetupMatrixOrgAngles( pEntity->GetAbsOrigin(), pEntity->GetAbsAngles() ); -} - - -void EntityMatrix::InitFromEntityLocal( CBaseEntity *entity ) -{ - if ( !entity || !entity->edict() ) - { - Identity(); - return; - } - ((VMatrix *)this)->SetupMatrixOrgAngles( entity->GetLocalOrigin(), entity->GetLocalAngles() ); -} - -//================================================== -// Purpose: -// Input: -// Output: -//================================================== - -void UTIL_ValidateSoundName( string_t &name, const char *defaultStr ) -{ - if ( ( !name || - strlen( (char*) STRING( name ) ) < 1 ) || - !Q_stricmp( (char *)STRING(name), "0" ) ) - { - name = AllocPooledString( defaultStr ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Slightly modified strtok. Does not modify the input string. Does -// not skip over more than one separator at a time. This allows parsing -// strings where tokens between separators may or may not be present: -// -// Door01,,,0 would be parsed as "Door01" "" "" "0" -// Door01,Open,,0 would be parsed as "Door01" "Open" "" "0" -// -// Input : token - Returns with a token, or zero length if the token was missing. -// str - String to parse. -// sep - Character to use as separator. UNDONE: allow multiple separator chars -// Output : Returns a pointer to the next token to be parsed. -//----------------------------------------------------------------------------- -const char *nexttoken(char *token, const char *str, char sep) -{ - if ((str == NULL) || (*str == '\0')) - { - *token = '\0'; - return(NULL); - } - - // - // Copy everything up to the first separator into the return buffer. - // Do not include separators in the return buffer. - // - while ((*str != sep) && (*str != '\0')) - { - *token++ = *str++; - } - *token = '\0'; - - // - // Advance the pointer unless we hit the end of the input string. - // - if (*str == '\0') - { - return(str); - } - - return(++str); -} - -//----------------------------------------------------------------------------- -// Purpose: Helper for UTIL_FindClientInPVS -// Input : check - last checked client -// Output : static int UTIL_GetNewCheckClient -//----------------------------------------------------------------------------- -// FIXME: include bspfile.h here? -class CCheckClient : public CAutoGameSystem -{ -public: - CCheckClient( char const *name ) : CAutoGameSystem( name ) - { - } - - void LevelInitPreEntity() - { - m_checkCluster = -1; - m_lastcheck = 1; - m_lastchecktime = -1; - m_bClientPVSIsExpanded = false; - } - - byte m_checkPVS[MAX_MAP_LEAFS/8]; - byte m_checkVisibilityPVS[MAX_MAP_LEAFS/8]; - int m_checkCluster; - int m_lastcheck; - float m_lastchecktime; - bool m_bClientPVSIsExpanded; -}; - -CCheckClient g_CheckClient( "CCheckClient" ); - - -static int UTIL_GetNewCheckClient( int check ) -{ - int i; - edict_t *ent; - Vector org; - -// cycle to the next one - - if (check < 1) - check = 1; - if (check > gpGlobals->maxClients) - check = gpGlobals->maxClients; - - if (check == gpGlobals->maxClients) - i = 1; - else - i = check + 1; - - for ( ; ; i++) - { - if ( i > gpGlobals->maxClients ) - { - i = 1; - } - - ent = engine->PEntityOfEntIndex( i ); - if ( !ent ) - continue; - - // Looped but didn't find anything else - if ( i == check ) - break; - - if ( !ent->GetUnknown() ) - continue; - - CBaseEntity *entity = GetContainingEntity( ent ); - if ( !entity ) - continue; - - if ( entity->GetFlags() & FL_NOTARGET ) - continue; - - // anything that is a client, or has a client as an enemy - break; - } - - if ( i != check ) - { - memset( g_CheckClient.m_checkVisibilityPVS, 0, sizeof(g_CheckClient.m_checkVisibilityPVS) ); - g_CheckClient.m_bClientPVSIsExpanded = false; - } - - if ( ent ) - { - // get the PVS for the entity - CBaseEntity *pce = GetContainingEntity( ent ); - if ( !pce ) - return i; - - org = pce->EyePosition(); - - int clusterIndex = engine->GetClusterForOrigin( org ); - if ( clusterIndex != g_CheckClient.m_checkCluster ) - { - g_CheckClient.m_checkCluster = clusterIndex; - engine->GetPVSForCluster( clusterIndex, sizeof(g_CheckClient.m_checkPVS), g_CheckClient.m_checkPVS ); - } - } - - return i; -} - - -//----------------------------------------------------------------------------- -// Gets the current check client.... -//----------------------------------------------------------------------------- -static edict_t *UTIL_GetCurrentCheckClient() -{ - edict_t *ent; - - // find a new check if on a new frame - float delta = gpGlobals->curtime - g_CheckClient.m_lastchecktime; - if ( delta >= 0.1 || delta < 0 ) - { - g_CheckClient.m_lastcheck = UTIL_GetNewCheckClient( g_CheckClient.m_lastcheck ); - g_CheckClient.m_lastchecktime = gpGlobals->curtime; - } - - // return check if it might be visible - ent = engine->PEntityOfEntIndex( g_CheckClient.m_lastcheck ); - - // Allow dead clients -- JAY - // Our monsters know the difference, and this function gates alot of behavior - // It's annoying to die and see monsters stop thinking because you're no longer - // "in" their PVS - if ( !ent || ent->IsFree() || !ent->GetUnknown()) - { - return NULL; - } - - return ent; -} - -void UTIL_SetClientVisibilityPVS( edict_t *pClient, const unsigned char *pvs, int pvssize ) -{ - if ( pClient == UTIL_GetCurrentCheckClient() ) - { - Assert( pvssize <= (int)sizeof(g_CheckClient.m_checkVisibilityPVS) ); - - g_CheckClient.m_bClientPVSIsExpanded = false; - - unsigned *pFrom = (unsigned *)pvs; - unsigned *pMask = (unsigned *)g_CheckClient.m_checkPVS; - unsigned *pTo = (unsigned *)g_CheckClient.m_checkVisibilityPVS; - - int limit = pvssize / 4; - int i; - - for ( i = 0; i < limit; i++ ) - { - pTo[i] = pFrom[i] & ~pMask[i]; - - if ( pFrom[i] ) - { - g_CheckClient.m_bClientPVSIsExpanded = true; - } - } - - int remainder = pvssize % 4; - for ( i = 0; i < remainder; i++ ) - { - ((unsigned char *)&pTo[limit])[i] = ((unsigned char *)&pFrom[limit])[i] & !((unsigned char *)&pMask[limit])[i]; - - if ( ((unsigned char *)&pFrom[limit])[i] != 0) - { - g_CheckClient.m_bClientPVSIsExpanded = true; - } - } - } -} - -bool UTIL_ClientPVSIsExpanded() -{ - return g_CheckClient.m_bClientPVSIsExpanded; -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns a client (or object that has a client enemy) that would be a valid target. -// If there are more than one valid options, they are cycled each frame -// If (self.origin + self.viewofs) is not in the PVS of the current target, it is not returned at all. -// Input : *pEdict - -// Output : edict_t* -//----------------------------------------------------------------------------- -CBaseEntity *UTIL_FindClientInPVS( const Vector &vecBoxMins, const Vector &vecBoxMaxs ) -{ - edict_t *ent = UTIL_GetCurrentCheckClient(); - if ( !ent ) - { - return NULL; - } - - if ( !engine->CheckBoxInPVS( vecBoxMins, vecBoxMaxs, g_CheckClient.m_checkPVS, sizeof( g_CheckClient.m_checkPVS ) ) ) - { - return NULL; - } - - // might be able to see it - return GetContainingEntity( ent ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns a client (or object that has a client enemy) that would be a valid target. -// If there are more than one valid options, they are cycled each frame -// If (self.origin + self.viewofs) is not in the PVS of the current target, it is not returned at all. -// Input : *pEdict - -// Output : edict_t* -//----------------------------------------------------------------------------- -ConVar sv_strict_notarget( "sv_strict_notarget", "0", 0, "If set, notarget will cause entities to never think they are in the pvs" ); - -static edict_t *UTIL_FindClientInPVSGuts(edict_t *pEdict, unsigned char *pvs, unsigned pvssize ) -{ - Vector view; - - edict_t *ent = UTIL_GetCurrentCheckClient(); - if ( !ent ) - { - return NULL; - } - - CBaseEntity *pPlayerEntity = GetContainingEntity( ent ); - if( (!pPlayerEntity || (pPlayerEntity->GetFlags() & FL_NOTARGET)) && sv_strict_notarget.GetBool() ) - { - return NULL; - } - // if current entity can't possibly see the check entity, return 0 - // UNDONE: Build a box for this and do it over that box - // UNDONE: Use CM_BoxLeafnums() - CBaseEntity *pe = GetContainingEntity( pEdict ); - if ( pe ) - { - view = pe->EyePosition(); - - if ( !engine->CheckOriginInPVS( view, pvs, pvssize ) ) - { - return NULL; - } - } - - // might be able to see it - return ent; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns a client that could see the entity directly -//----------------------------------------------------------------------------- - -edict_t *UTIL_FindClientInPVS(edict_t *pEdict) -{ - return UTIL_FindClientInPVSGuts( pEdict, g_CheckClient.m_checkPVS, sizeof( g_CheckClient.m_checkPVS ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns a client that could see the entity, including through a camera -//----------------------------------------------------------------------------- -edict_t *UTIL_FindClientInVisibilityPVS( edict_t *pEdict ) -{ - return UTIL_FindClientInPVSGuts( pEdict, g_CheckClient.m_checkVisibilityPVS, sizeof( g_CheckClient.m_checkVisibilityPVS ) ); -} - - - -//----------------------------------------------------------------------------- -// Purpose: Returns a chain of entities within the PVS of another entity (client) -// starting_ent is the ent currently at in the list -// a starting_ent of NULL signifies the beginning of a search -// Input : *pplayer - -// *starting_ent - -// Output : edict_t -//----------------------------------------------------------------------------- -CBaseEntity *UTIL_EntitiesInPVS( CBaseEntity *pPVSEntity, CBaseEntity *pStartingEntity ) -{ - Vector org; - static byte pvs[ MAX_MAP_CLUSTERS/8 ]; - static Vector lastOrg( 0, 0, 0 ); - - if ( !pPVSEntity ) - return NULL; - - // NOTE: These used to be caching code here to prevent this from - // being called over+over which breaks when you go back + forth - // across level transitions - // So, we'll always get the PVS each time we start a new EntitiesInPVS iteration. - // Given that weapon_binocs + leveltransition code is the only current clients - // of this, this seems safe. - if ( !pStartingEntity ) - { - org = pPVSEntity->EyePosition(); - int clusterIndex = engine->GetClusterForOrigin( org ); - Assert( clusterIndex >= 0 ); - engine->GetPVSForCluster( clusterIndex, sizeof(pvs), pvs ); - } - - for ( CBaseEntity *pEntity = gEntList.NextEnt(pStartingEntity); pEntity; pEntity = gEntList.NextEnt(pEntity) ) - { - // Only return attached ents. - if ( !pEntity->edict() ) - continue; - - CBaseEntity *pParent = pEntity->GetRootMoveParent(); - - Vector vecSurroundMins, vecSurroundMaxs; - pParent->CollisionProp()->WorldSpaceSurroundingBounds( &vecSurroundMins, &vecSurroundMaxs ); - if ( !engine->CheckBoxInPVS( vecSurroundMins, vecSurroundMaxs, pvs, sizeof( pvs ) ) ) - continue; - - return pEntity; - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Get the predicted postion of an entity of a certain number of seconds -// Use this function with caution, it has great potential for annoying the player, especially -// if used for target firing predition -// Input : *pTarget - target entity to predict -// timeDelta - amount of time to predict ahead (in seconds) -// &vecPredictedPosition - output -//----------------------------------------------------------------------------- -void UTIL_PredictedPosition( CBaseEntity *pTarget, float flTimeDelta, Vector *vecPredictedPosition ) -{ - if ( ( pTarget == NULL ) || ( vecPredictedPosition == NULL ) ) - return; - - Vector vecPredictedVel; - - //FIXME: Should we look at groundspeed or velocity for non-clients?? - - //Get the proper velocity to predict with - CBasePlayer *pPlayer = ToBasePlayer( pTarget ); - - //Player works differently than other entities - if ( pPlayer != NULL ) - { - if ( pPlayer->IsInAVehicle() ) - { - //Calculate the predicted position in this vehicle - vecPredictedVel = pPlayer->GetVehicleEntity()->GetSmoothedVelocity(); - } - else - { - //Get the player's stored velocity - vecPredictedVel = pPlayer->GetSmoothedVelocity(); - } - } - else - { - // See if we're a combat character in a vehicle - CBaseCombatCharacter *pCCTarget = pTarget->MyCombatCharacterPointer(); - if ( pCCTarget != NULL && pCCTarget->IsInAVehicle() ) - { - //Calculate the predicted position in this vehicle - vecPredictedVel = pCCTarget->GetVehicleEntity()->GetSmoothedVelocity(); - } - else - { - // See if we're an animating entity - CBaseAnimating *pAnimating = dynamic_cast(pTarget); - if ( pAnimating != NULL ) - { - vecPredictedVel = pAnimating->GetGroundSpeedVelocity(); - } - else - { - // Otherwise we're a vanilla entity - vecPredictedVel = pTarget->GetSmoothedVelocity(); - } - } - } - - //Get the result - (*vecPredictedPosition) = pTarget->GetAbsOrigin() + ( vecPredictedVel * flTimeDelta ); -} - -//----------------------------------------------------------------------------- -// Purpose: Points the destination entity at the target entity -// Input : *pDest - entity to be pointed at the target -// *pTarget - target to point at -//----------------------------------------------------------------------------- -bool UTIL_PointAtEntity( CBaseEntity *pDest, CBaseEntity *pTarget ) -{ - if ( ( pDest == NULL ) || ( pTarget == NULL ) ) - { - return false; - } - - Vector dir = (pTarget->GetAbsOrigin() - pDest->GetAbsOrigin()); - - VectorNormalize( dir ); - - //Store off as angles - QAngle angles; - VectorAngles( dir, angles ); - pDest->SetLocalAngles( angles ); - pDest->SetAbsAngles( angles ); - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Points the destination entity at the target entity by name -// Input : *pDest - entity to be pointed at the target -// strTarget - name of entity to target (will only choose the first!) -//----------------------------------------------------------------------------- -void UTIL_PointAtNamedEntity( CBaseEntity *pDest, string_t strTarget ) -{ - //Attempt to find the entity - if ( !UTIL_PointAtEntity( pDest, gEntList.FindEntityByName( NULL, strTarget ) ) ) - { - DevMsg( 1, "%s (%s) was unable to point at an entity named: %s\n", pDest->GetClassname(), pDest->GetDebugName(), STRING( strTarget ) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Copy the pose parameter values from one entity to the other -// Input : *pSourceEntity - entity to copy from -// *pDestEntity - entity to copy to -//----------------------------------------------------------------------------- -bool UTIL_TransferPoseParameters( CBaseEntity *pSourceEntity, CBaseEntity *pDestEntity ) -{ - CBaseAnimating *pSourceBaseAnimating = dynamic_cast( pSourceEntity ); - CBaseAnimating *pDestBaseAnimating = dynamic_cast( pDestEntity ); - - if ( !pSourceBaseAnimating || !pDestBaseAnimating ) - return false; - - for ( int iPose = 0; iPose < MAXSTUDIOPOSEPARAM; ++iPose ) - { - pDestBaseAnimating->SetPoseParameter( iPose, pSourceBaseAnimating->GetPoseParameter( iPose ) ); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Make a muzzle flash appear -// Input : &origin - position of the muzzle flash -// &angles - angles of the fire direction -// scale - scale of the muzzle flash -// type - type of muzzle flash -//----------------------------------------------------------------------------- -void UTIL_MuzzleFlash( const Vector &origin, const QAngle &angles, int scale, int type ) -{ - CPASFilter filter( origin ); - - te->MuzzleFlash( filter, 0.0f, origin, angles, scale, type ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : vStartPos - start of the line -// vEndPos - end of the line -// vPoint - point to find nearest point to on specified line -// clampEnds - clamps returned points to being on the line segment specified -// Output : Vector - nearest point on the specified line -//----------------------------------------------------------------------------- -Vector UTIL_PointOnLineNearestPoint(const Vector& vStartPos, const Vector& vEndPos, const Vector& vPoint, bool clampEnds ) -{ - Vector vEndToStart = (vEndPos - vStartPos); - Vector vOrgToStart = (vPoint - vStartPos); - float fNumerator = DotProduct(vEndToStart,vOrgToStart); - float fDenominator = vEndToStart.Length() * vOrgToStart.Length(); - float fIntersectDist = vOrgToStart.Length()*(fNumerator/fDenominator); - float flLineLength = VectorNormalize( vEndToStart ); - - if ( clampEnds ) - { - fIntersectDist = clamp( fIntersectDist, 0.0f, flLineLength ); - } - - Vector vIntersectPos = vStartPos + vEndToStart * fIntersectDist; - - return vIntersectPos; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -AngularImpulse WorldToLocalRotation( const VMatrix &localToWorld, const Vector &worldAxis, float rotation ) -{ - // fix axes of rotation to match axes of vector - Vector rot = worldAxis * rotation; - // since the matrix maps local to world, do a transpose rotation to get world to local - AngularImpulse ang = localToWorld.VMul3x3Transpose( rot ); - - return ang; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *filename - -// *pLength - -// Output : byte -//----------------------------------------------------------------------------- -byte *UTIL_LoadFileForMe( const char *filename, int *pLength ) -{ - void *buffer = NULL; - - int length = filesystem->ReadFileEx( filename, "GAME", &buffer, true, true ); - - if ( pLength ) - { - *pLength = length; - } - - return (byte *)buffer; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *buffer - -//----------------------------------------------------------------------------- -void UTIL_FreeFile( byte *buffer ) -{ - filesystem->FreeOptimalReadBuffer( buffer ); -} - -//----------------------------------------------------------------------------- -// Purpose: Determines whether an entity is within a certain angular tolerance to viewer -// Input : *pEntity - entity which is the "viewer" -// vecPosition - position to test against -// flTolerance - tolerance (as dot-product) -// *pflDot - if not NULL, holds the -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool UTIL_IsFacingWithinTolerance( CBaseEntity *pViewer, const Vector &vecPosition, float flDotTolerance, float *pflDot /*= NULL*/ ) -{ - if ( pflDot ) - { - *pflDot = 0.0f; - } - - // Required elements - if ( pViewer == NULL ) - return false; - - Vector forward; - pViewer->GetVectors( &forward, NULL, NULL ); - - Vector dir = vecPosition - pViewer->GetAbsOrigin(); - VectorNormalize( dir ); - - // Larger dot product corresponds to a smaller angle - float flDot = dir.Dot( forward ); - - // Return the result - if ( pflDot ) - { - *pflDot = flDot; - } - - // Within the goal tolerance - if ( flDot >= flDotTolerance ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Determines whether an entity is within a certain angular tolerance to viewer -// Input : *pEntity - entity which is the "viewer" -// *pTarget - entity to test against -// flTolerance - tolerance (as dot-product) -// *pflDot - if not NULL, holds the -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool UTIL_IsFacingWithinTolerance( CBaseEntity *pViewer, CBaseEntity *pTarget, float flDotTolerance, float *pflDot /*= NULL*/ ) -{ - if ( pViewer == NULL || pTarget == NULL ) - return false; - - return UTIL_IsFacingWithinTolerance( pViewer, pTarget->GetAbsOrigin(), flDotTolerance, pflDot ); -} - -//----------------------------------------------------------------------------- -// Purpose: Fills in color for debug purposes based on a relationship -// Input : nRelationship - relationship to test -// *pR, *pG, *pB - colors to fill -//----------------------------------------------------------------------------- -void UTIL_GetDebugColorForRelationship( int nRelationship, int &r, int &g, int &b ) -{ - switch ( nRelationship ) - { - case D_LI: - r = 0; - g = 255; - b = 0; - break; - case D_NU: - r = 0; - g = 0; - b = 255; - break; - case D_HT: - r = 255; - g = 0; - b = 0; - break; - case D_FR: - r = 255; - g = 255; - b = 0; - break; - default: - r = 255; - g = 255; - b = 255; - break; - } -} - -void LoadAndSpawnEntities_ParseEntKVBlockHelper( CBaseEntity *pNode, KeyValues *pkvNode ) -{ - KeyValues *pkvNodeData = pkvNode->GetFirstSubKey(); - while ( pkvNodeData ) - { - // Handle the connections block - if ( !Q_strcmp(pkvNodeData->GetName(), "connections") ) - { - LoadAndSpawnEntities_ParseEntKVBlockHelper( pNode, pkvNodeData ); - } - else - { - pNode->KeyValue( pkvNodeData->GetName(), pkvNodeData->GetString() ); - } - - pkvNodeData = pkvNodeData->GetNextKey(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Loads and parses a file and spawns entities defined in it. -//----------------------------------------------------------------------------- -bool UTIL_LoadAndSpawnEntitiesFromScript( CUtlVector &entities, const char *pScriptFile, const char *pBlock, bool bActivate ) -{ - KeyValues *pkvFile = new KeyValues( pBlock ); - - if ( pkvFile->LoadFromFile( filesystem, pScriptFile, "MOD" ) ) - { - // Load each block, and spawn the entities - KeyValues *pkvNode = pkvFile->GetFirstSubKey(); - while ( pkvNode ) - { - // Get name - const char *pNodeName = pkvNode->GetName(); - - if ( stricmp( pNodeName, "entity" ) ) - { - pkvNode = pkvNode->GetNextKey(); - continue; - } - - KeyValues *pClassname = pkvNode->FindKey( "classname" ); - - if ( pClassname ) - { - // Use the classname instead - pNodeName = pClassname->GetString(); - } - - // Spawn the entity - CBaseEntity *pNode = CreateEntityByName( pNodeName ); - - if ( pNode ) - { - LoadAndSpawnEntities_ParseEntKVBlockHelper( pNode, pkvNode ); - DispatchSpawn( pNode ); - entities.AddToTail( pNode ); - } - else - { - Warning( "UTIL_LoadAndSpawnEntitiesFromScript: Failed to spawn entity, type: '%s'\n", pNodeName ); - } - - // Move to next entity - pkvNode = pkvNode->GetNextKey(); - } - - if ( bActivate == true ) - { - bool bAsyncAnims = mdlcache->SetAsyncLoad( MDLCACHE_ANIMBLOCK, false ); - // Then activate all the entities - for ( int i = 0; i < entities.Count(); i++ ) - { - entities[i]->Activate(); - } - mdlcache->SetAsyncLoad( MDLCACHE_ANIMBLOCK, bAsyncAnims ); - } - } - else - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Convert a vector an angle from worldspace to the entity's parent's local space -// Input : *pEntity - Entity whose parent we're concerned with -//----------------------------------------------------------------------------- -void UTIL_ParentToWorldSpace( CBaseEntity *pEntity, Vector &vecPosition, QAngle &vecAngles ) -{ - if ( pEntity == NULL ) - return; - - // Construct the entity-to-world matrix - // Start with making an entity-to-parent matrix - matrix3x4_t matEntityToParent; - AngleMatrix( vecAngles, matEntityToParent ); - MatrixSetColumn( vecPosition, 3, matEntityToParent ); - - // concatenate with our parent's transform - matrix3x4_t matScratch, matResult; - matrix3x4_t matParentToWorld; - - if ( pEntity->GetParent() != NULL ) - { - matParentToWorld = pEntity->GetParentToWorldTransform( matScratch ); - } - else - { - matParentToWorld = pEntity->EntityToWorldTransform(); - } - - ConcatTransforms( matParentToWorld, matEntityToParent, matResult ); - - // pull our absolute position out of the matrix - MatrixGetColumn( matResult, 3, vecPosition ); - MatrixAngles( matResult, vecAngles ); -} - -//----------------------------------------------------------------------------- -// Purpose: Convert a vector and quaternion from worldspace to the entity's parent's local space -// Input : *pEntity - Entity whose parent we're concerned with -//----------------------------------------------------------------------------- -void UTIL_ParentToWorldSpace( CBaseEntity *pEntity, Vector &vecPosition, Quaternion &quat ) -{ - if ( pEntity == NULL ) - return; - - QAngle vecAngles; - QuaternionAngles( quat, vecAngles ); - UTIL_ParentToWorldSpace( pEntity, vecPosition, vecAngles ); - AngleQuaternion( vecAngles, quat ); -} - -//----------------------------------------------------------------------------- -// Purpose: Convert a vector an angle from worldspace to the entity's parent's local space -// Input : *pEntity - Entity whose parent we're concerned with -//----------------------------------------------------------------------------- -void UTIL_WorldToParentSpace( CBaseEntity *pEntity, Vector &vecPosition, QAngle &vecAngles ) -{ - if ( pEntity == NULL ) - return; - - // Construct the entity-to-world matrix - // Start with making an entity-to-parent matrix - matrix3x4_t matEntityToParent; - AngleMatrix( vecAngles, matEntityToParent ); - MatrixSetColumn( vecPosition, 3, matEntityToParent ); - - // concatenate with our parent's transform - matrix3x4_t matScratch, matResult; - matrix3x4_t matWorldToParent; - - if ( pEntity->GetParent() != NULL ) - { - matScratch = pEntity->GetParentToWorldTransform( matScratch ); - } - else - { - matScratch = pEntity->EntityToWorldTransform(); - } - - MatrixInvert( matScratch, matWorldToParent ); - ConcatTransforms( matWorldToParent, matEntityToParent, matResult ); - - // pull our absolute position out of the matrix - MatrixGetColumn( matResult, 3, vecPosition ); - MatrixAngles( matResult, vecAngles ); -} - -//----------------------------------------------------------------------------- -// Purpose: Convert a vector and quaternion from worldspace to the entity's parent's local space -// Input : *pEntity - Entity whose parent we're concerned with -//----------------------------------------------------------------------------- -void UTIL_WorldToParentSpace( CBaseEntity *pEntity, Vector &vecPosition, Quaternion &quat ) -{ - if ( pEntity == NULL ) - return; - - QAngle vecAngles; - QuaternionAngles( quat, vecAngles ); - UTIL_WorldToParentSpace( pEntity, vecPosition, vecAngles ); - AngleQuaternion( vecAngles, quat ); -} - -//----------------------------------------------------------------------------- -// Purpose: Given a vector, clamps the scalar axes to MAX_COORD_FLOAT ranges from worldsize.h -// Input : *pVecPos - -//----------------------------------------------------------------------------- -void UTIL_BoundToWorldSize( Vector *pVecPos ) -{ - Assert( pVecPos ); - for ( int i = 0; i < 3; ++i ) - { - (*pVecPos)[ i ] = clamp( (*pVecPos)[ i ], MIN_COORD_FLOAT, MAX_COORD_FLOAT ); - } -} - -//============================================================================= -// -// Tests! -// - -#define NUM_KDTREE_TESTS 2500 -#define NUM_KDTREE_ENTITY_SIZE 256 - -void CC_KDTreeTest( const CCommand &args ) -{ - Msg( "Testing kd-tree entity queries." ); - - // Get the testing spot. -// CBaseEntity *pSpot = gEntList.FindEntityByClassname( NULL, "info_player_start" ); -// Vector vecStart = pSpot->GetAbsOrigin(); - - CBasePlayer *pPlayer = static_cast( UTIL_GetLocalPlayer() ); - Vector vecStart = pPlayer->GetAbsOrigin(); - - static Vector *vecTargets = NULL; - static bool bFirst = true; - - // Generate the targets - rays (1K long). - if ( bFirst ) - { - vecTargets = new Vector [NUM_KDTREE_TESTS]; - double flRadius = 0; - double flTheta = 0; - double flPhi = 0; - for ( int i = 0; i < NUM_KDTREE_TESTS; ++i ) - { - flRadius += NUM_KDTREE_TESTS * 123.123; - flRadius = fmod( flRadius, 128.0 ); - flRadius = fabs( flRadius ); - - flTheta += NUM_KDTREE_TESTS * 76.76; - flTheta = fmod( flTheta, (double) DEG2RAD( 360 ) ); - flTheta = fabs( flTheta ); - - flPhi += NUM_KDTREE_TESTS * 1997.99; - flPhi = fmod( flPhi, (double) DEG2RAD( 180 ) ); - flPhi = fabs( flPhi ); - - float st, ct, sp, cp; - SinCos( flTheta, &st, &ct ); - SinCos( flPhi, &sp, &cp ); - - vecTargets[i].x = flRadius * ct * sp; - vecTargets[i].y = flRadius * st * sp; - vecTargets[i].z = flRadius * cp; - - // Make the trace 1024 units long. - Vector vecDir = vecTargets[i] - vecStart; - VectorNormalize( vecDir ); - vecTargets[i] = vecStart + vecDir * 1024; - } - - bFirst = false; - } - - int nTestType = 0; - if ( args.ArgC() >= 2 ) - { - nTestType = atoi( args[ 1 ] ); - } - - vtune( true ); - -#ifdef VPROF_ENABLED - g_VProfCurrentProfile.Resume(); - g_VProfCurrentProfile.Start(); - g_VProfCurrentProfile.Reset(); - g_VProfCurrentProfile.MarkFrame(); -#endif - - switch ( nTestType ) - { - case 0: - { - VPROF( "TraceTotal" ); - - trace_t trace; - for ( int iTest = 0; iTest < NUM_KDTREE_TESTS; ++iTest ) - { - UTIL_TraceLine( vecStart, vecTargets[iTest], MASK_SOLID_BRUSHONLY, NULL, COLLISION_GROUP_NONE, &trace ); - } - break; - } - case 1: - { - VPROF( "TraceTotal" ); - - trace_t trace; - for ( int iTest = 0; iTest < NUM_KDTREE_TESTS; ++iTest ) - { - UTIL_TraceHull( vecStart, vecTargets[iTest], VEC_HULL_MIN, VEC_HULL_MAX, MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &trace ); - } - break; - } - case 2: - { - Vector vecMins[NUM_KDTREE_TESTS]; - Vector vecMaxs[NUM_KDTREE_TESTS]; - int iTest; - for ( iTest = 0; iTest < NUM_KDTREE_TESTS; ++iTest ) - { - vecMins[iTest] = vecStart; - vecMaxs[iTest] = vecStart; - for ( int iAxis = 0; iAxis < 3; ++iAxis ) - { - if ( vecTargets[iTest].x < vecMins[iTest].x ) { vecMins[iTest].x = vecTargets[iTest].x; } - if ( vecTargets[iTest].y < vecMins[iTest].y ) { vecMins[iTest].y = vecTargets[iTest].y; } - if ( vecTargets[iTest].z < vecMins[iTest].z ) { vecMins[iTest].z = vecTargets[iTest].z; } - - if ( vecTargets[iTest].x > vecMaxs[iTest].x ) { vecMaxs[iTest].x = vecTargets[iTest].x; } - if ( vecTargets[iTest].y > vecMaxs[iTest].y ) { vecMaxs[iTest].y = vecTargets[iTest].y; } - if ( vecTargets[iTest].z > vecMaxs[iTest].z ) { vecMaxs[iTest].z = vecTargets[iTest].z; } - } - } - - - VPROF( "TraceTotal" ); - - int nCount = 0; - - Vector vecDelta; - trace_t trace; - CBaseEntity *pList[1024]; - for ( iTest = 0; iTest < NUM_KDTREE_TESTS; ++iTest ) - { - nCount += UTIL_EntitiesInBox( pList, 1024, vecMins[iTest], vecMaxs[iTest], 0 ); - } - - Msg( "Count = %d\n", nCount ); - break; - } - case 3: - { - Vector vecDelta; - float flRadius[NUM_KDTREE_TESTS]; - int iTest; - for ( iTest = 0; iTest < NUM_KDTREE_TESTS; ++iTest ) - { - VectorSubtract( vecTargets[iTest], vecStart, vecDelta ); - flRadius[iTest] = vecDelta.Length() * 0.5f; - } - - VPROF( "TraceTotal" ); - - int nCount = 0; - - trace_t trace; - CBaseEntity *pList[1024]; - for ( iTest = 0; iTest < NUM_KDTREE_TESTS; ++iTest ) - { - nCount += UTIL_EntitiesInSphere( pList, 1024, vecStart, flRadius[iTest], 0 ); - } - - Msg( "Count = %d\n", nCount ); - break; - } - default: - { - break; - } - } - -#ifdef VPROF_ENABLED - g_VProfCurrentProfile.MarkFrame(); - g_VProfCurrentProfile.Pause(); - g_VProfCurrentProfile.OutputReport( VPRT_FULL ); -#endif - - vtune( false ); -} - -static ConCommand kdtree_test( "kdtree_test", CC_KDTreeTest, "Tests spatial partition for entities queries.", FCVAR_CHEAT ); - -void CC_VoxelTreeView( void ) -{ - Msg( "VoxelTreeView\n" ); - partition->RenderAllObjectsInTree( 10.0f ); -} - -static ConCommand voxeltree_view( "voxeltree_view", CC_VoxelTreeView, "View entities in the voxel-tree.", FCVAR_CHEAT ); - -void CC_VoxelTreePlayerView( void ) -{ - Msg( "VoxelTreePlayerView\n" ); - - CBasePlayer *pPlayer = static_cast( UTIL_GetLocalPlayer() ); - Vector vecStart = pPlayer->GetAbsOrigin(); - partition->RenderObjectsInPlayerLeafs( vecStart - VEC_HULL_MIN, vecStart + VEC_HULL_MAX, 3.0f ); -} - -static ConCommand voxeltree_playerview( "voxeltree_playerview", CC_VoxelTreePlayerView, "View entities in the voxel-tree at the player position.", FCVAR_CHEAT ); - -void CC_VoxelTreeBox( const CCommand &args ) -{ - Vector vecMin, vecMax; - if ( args.ArgC() >= 6 ) - { - vecMin.x = atof( args[ 1 ] ); - vecMin.y = atof( args[ 2 ] ); - vecMin.z = atof( args[ 3 ] ); - - vecMax.x = atof( args[ 4 ] ); - vecMax.y = atof( args[ 5 ] ); - vecMax.z = atof( args[ 6 ] ); - } - else - { - return; - } - - float flTime = 10.0f; - - Vector vecPoints[8]; - vecPoints[0].Init( vecMin.x, vecMin.y, vecMin.z ); - vecPoints[1].Init( vecMin.x, vecMax.y, vecMin.z ); - vecPoints[2].Init( vecMax.x, vecMax.y, vecMin.z ); - vecPoints[3].Init( vecMax.x, vecMin.y, vecMin.z ); - vecPoints[4].Init( vecMin.x, vecMin.y, vecMax.z ); - vecPoints[5].Init( vecMin.x, vecMax.y, vecMax.z ); - vecPoints[6].Init( vecMax.x, vecMax.y, vecMax.z ); - vecPoints[7].Init( vecMax.x, vecMin.y, vecMax.z ); - - debugoverlay->AddLineOverlay( vecPoints[0], vecPoints[1], 255, 0, 0, true, flTime ); - debugoverlay->AddLineOverlay( vecPoints[1], vecPoints[2], 255, 0, 0, true, flTime ); - debugoverlay->AddLineOverlay( vecPoints[2], vecPoints[3], 255, 0, 0, true, flTime ); - debugoverlay->AddLineOverlay( vecPoints[3], vecPoints[0], 255, 0, 0, true, flTime ); - - debugoverlay->AddLineOverlay( vecPoints[4], vecPoints[5], 255, 0, 0, true, flTime ); - debugoverlay->AddLineOverlay( vecPoints[5], vecPoints[6], 255, 0, 0, true, flTime ); - debugoverlay->AddLineOverlay( vecPoints[6], vecPoints[7], 255, 0, 0, true, flTime ); - debugoverlay->AddLineOverlay( vecPoints[7], vecPoints[4], 255, 0, 0, true, flTime ); - - debugoverlay->AddLineOverlay( vecPoints[0], vecPoints[4], 255, 0, 0, true, flTime ); - debugoverlay->AddLineOverlay( vecPoints[3], vecPoints[7], 255, 0, 0, true, flTime ); - debugoverlay->AddLineOverlay( vecPoints[1], vecPoints[5], 255, 0, 0, true, flTime ); - debugoverlay->AddLineOverlay( vecPoints[2], vecPoints[6], 255, 0, 0, true, flTime ); - - Msg( "VoxelTreeBox - (%f %f %f) to (%f %f %f)\n", vecMin.x, vecMin.y, vecMin.z, vecMax.x, vecMax.y, vecMax.z ); - partition->RenderObjectsInBox( vecMin, vecMax, flTime ); -} - -static ConCommand voxeltree_box( "voxeltree_box", CC_VoxelTreeBox, "View entities in the voxel-tree inside box .", FCVAR_CHEAT ); - -void CC_VoxelTreeSphere( const CCommand &args ) -{ - Vector vecCenter; - float flRadius; - if ( args.ArgC() >= 4 ) - { - vecCenter.x = atof( args[ 1 ] ); - vecCenter.y = atof( args[ 2 ] ); - vecCenter.z = atof( args[ 3 ] ); - - flRadius = atof( args[ 3 ] ); - } - else - { - return; - } - - float flTime = 3.0f; - - Vector vecMin, vecMax; - vecMin.Init( vecCenter.x - flRadius, vecCenter.y - flRadius, vecCenter.z - flRadius ); - vecMax.Init( vecCenter.x + flRadius, vecCenter.y + flRadius, vecCenter.z + flRadius ); - - Vector vecPoints[8]; - vecPoints[0].Init( vecMin.x, vecMin.y, vecMin.z ); - vecPoints[1].Init( vecMin.x, vecMax.y, vecMin.z ); - vecPoints[2].Init( vecMax.x, vecMax.y, vecMin.z ); - vecPoints[3].Init( vecMax.x, vecMin.y, vecMin.z ); - vecPoints[4].Init( vecMin.x, vecMin.y, vecMax.z ); - vecPoints[5].Init( vecMin.x, vecMax.y, vecMax.z ); - vecPoints[6].Init( vecMax.x, vecMax.y, vecMax.z ); - vecPoints[7].Init( vecMax.x, vecMin.y, vecMax.z ); - - debugoverlay->AddLineOverlay( vecPoints[0], vecPoints[1], 255, 0, 0, true, flTime ); - debugoverlay->AddLineOverlay( vecPoints[1], vecPoints[2], 255, 0, 0, true, flTime ); - debugoverlay->AddLineOverlay( vecPoints[2], vecPoints[3], 255, 0, 0, true, flTime ); - debugoverlay->AddLineOverlay( vecPoints[3], vecPoints[0], 255, 0, 0, true, flTime ); - - debugoverlay->AddLineOverlay( vecPoints[4], vecPoints[5], 255, 0, 0, true, flTime ); - debugoverlay->AddLineOverlay( vecPoints[5], vecPoints[6], 255, 0, 0, true, flTime ); - debugoverlay->AddLineOverlay( vecPoints[6], vecPoints[7], 255, 0, 0, true, flTime ); - debugoverlay->AddLineOverlay( vecPoints[7], vecPoints[4], 255, 0, 0, true, flTime ); - - debugoverlay->AddLineOverlay( vecPoints[0], vecPoints[4], 255, 0, 0, true, flTime ); - debugoverlay->AddLineOverlay( vecPoints[3], vecPoints[7], 255, 0, 0, true, flTime ); - debugoverlay->AddLineOverlay( vecPoints[1], vecPoints[5], 255, 0, 0, true, flTime ); - debugoverlay->AddLineOverlay( vecPoints[2], vecPoints[6], 255, 0, 0, true, flTime ); - - Msg( "VoxelTreeSphere - (%f %f %f), %f\n", vecCenter.x, vecCenter.y, vecCenter.z, flRadius ); - partition->RenderObjectsInSphere( vecCenter, flRadius, flTime ); -} - -static ConCommand voxeltree_sphere( "voxeltree_sphere", CC_VoxelTreeSphere, "View entities in the voxel-tree inside sphere .", FCVAR_CHEAT ); - - - -#define NUM_COLLISION_TESTS 2500 -void CC_CollisionTest( const CCommand &args ) -{ - if ( !physenv ) - return; - - Msg( "Testing collision system\n" ); - partition->ReportStats( "" ); - int i; - CBaseEntity *pSpot = gEntList.FindEntityByClassname( NULL, "info_player_start"); - Vector start = pSpot->GetAbsOrigin(); - static Vector *targets = NULL; - static bool first = true; - static float test[2] = {1,1}; - if ( first ) - { - targets = new Vector[NUM_COLLISION_TESTS]; - float radius = 0; - float theta = 0; - float phi = 0; - for ( i = 0; i < NUM_COLLISION_TESTS; i++ ) - { - radius += NUM_COLLISION_TESTS * 123.123; - radius = fabs(fmod(radius, 128)); - theta += NUM_COLLISION_TESTS * 76.76; - theta = fabs(fmod(theta, DEG2RAD(360))); - phi += NUM_COLLISION_TESTS * 1997.99; - phi = fabs(fmod(phi, DEG2RAD(180))); - - float st, ct, sp, cp; - SinCos( theta, &st, &ct ); - SinCos( phi, &sp, &cp ); - - targets[i].x = radius * ct * sp; - targets[i].y = radius * st * sp; - targets[i].z = radius * cp; - - // make the trace 1024 units long - Vector dir = targets[i] - start; - VectorNormalize(dir); - targets[i] = start + dir * 1024; - } - first = false; - } - - //Vector results[NUM_COLLISION_TESTS]; - - int testType = 0; - if ( args.ArgC() >= 2 ) - { - testType = atoi(args[1]); - } - float duration = 0; - Vector size[2]; - size[0].Init(0,0,0); - size[1].Init(16,16,16); - unsigned int dots = 0; - int nMask = MASK_ALL & ~(CONTENTS_MONSTER | CONTENTS_HITBOX ); - for ( int j = 0; j < 2; j++ ) - { - float startTime = engine->Time(); - if ( testType == 1 ) - { - trace_t tr; - for ( i = 0; i < NUM_COLLISION_TESTS; i++ ) - { - UTIL_TraceHull( start, targets[i], -size[1], size[1], nMask, NULL, COLLISION_GROUP_NONE, &tr ); - } - } - else - { - testType = 0; - trace_t tr; - - for ( i = 0; i < NUM_COLLISION_TESTS; i++ ) - { - if ( i == 0 ) - { - partition->RenderLeafsForRayTraceStart( 10.0f ); - } - - UTIL_TraceLine( start, targets[i], nMask, NULL, COLLISION_GROUP_NONE, &tr ); - - if ( i == 0 ) - { - partition->RenderLeafsForRayTraceEnd( ); - } - } - } - - duration += engine->Time() - startTime; - } - test[testType] = duration; - Msg("%d collisions in %.2f ms (%u dots)\n", NUM_COLLISION_TESTS, duration*1000, dots ); - partition->ReportStats( "" ); -#if 1 - int red = 255, green = 0, blue = 0; - for ( i = 0; i < 1 /*NUM_COLLISION_TESTS*/; i++ ) - { - NDebugOverlay::Line( start, targets[i], red, green, blue, false, 2 ); - } -#endif -} -static ConCommand collision_test("collision_test", CC_CollisionTest, "Tests collision system", FCVAR_CHEAT ); - - - - diff --git a/game/server/util.h b/game/server/util.h deleted file mode 100644 index 417cb3170..000000000 --- a/game/server/util.h +++ /dev/null @@ -1,632 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Misc utility code. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef UTIL_H -#define UTIL_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ai_activity.h" -#include "enginecallback.h" -#include "basetypes.h" -#include "tempentity.h" -#include "string_t.h" -#include "gamestringpool.h" -#include "engine/IEngineTrace.h" -#include "worldsize.h" -#include "dt_send.h" -#include "server_class.h" -#include "shake.h" - -#include "vstdlib/random.h" -#include - -#include "utlvector.h" -#include "util_shared.h" -#include "shareddefs.h" -#include "networkvar.h" - -struct levellist_t; -class IServerNetworkable; -class IEntityFactory; - -#ifdef _WIN32 - #define SETUP_EXTERNC(mapClassName)\ - extern "C" _declspec( dllexport ) IServerNetworkable* mapClassName( void ); -#else - #define SETUP_EXTERNC(mapClassName) -#endif - - -#include "tier0/memdbgon.h" - -CBaseEntity *CreateEntityByName(const char *className, int iForceEdictIndex); - -// entity creation -// creates an entity that has not been linked to a classname -template< class T > -T *_CreateEntityTemplate( T *newEnt, const char *className ) -{ - newEnt = new T; // this is the only place 'new' should be used! - newEnt->PostConstructor( className ); - return newEnt; -} - -#include "tier0/memdbgoff.h" - -// creates an entity by name, and ensure it's correctness -// does not spawn the entity -// use the CREATE_ENTITY() macro which wraps this, instead of using it directly -template< class T > -T *_CreateEntity( T *newClass, const char *className ) -{ - T *newEnt = dynamic_cast( CreateEntityByName(className, -1) ); - if ( !newEnt ) - { - Warning( "classname %s used to create wrong class type\n" ); - Assert(0); - } - - return newEnt; -} - -#define CREATE_ENTITY( newClass, className ) _CreateEntity( (newClass*)NULL, className ) -#define CREATE_UNSAVED_ENTITY( newClass, className ) _CreateEntityTemplate( (newClass*)NULL, className ) - - -// This is the glue that hooks .MAP entity class names to our CPP classes -abstract_class IEntityFactoryDictionary -{ -public: - virtual void InstallFactory( IEntityFactory *pFactory, const char *pClassName ) = 0; - virtual IServerNetworkable *Create( const char *pClassName ) = 0; - virtual void Destroy( const char *pClassName, IServerNetworkable *pNetworkable ) = 0; - virtual IEntityFactory *FindFactory( const char *pClassName ) = 0; - virtual const char *GetCannonicalName( const char *pClassName ) = 0; -}; - -IEntityFactoryDictionary *EntityFactoryDictionary(); - -inline bool CanCreateEntityClass( const char *pszClassname ) -{ - return ( EntityFactoryDictionary() != NULL && EntityFactoryDictionary()->FindFactory( pszClassname ) != NULL ); -} - -abstract_class IEntityFactory -{ -public: - virtual IServerNetworkable *Create( const char *pClassName ) = 0; - virtual void Destroy( IServerNetworkable *pNetworkable ) = 0; - virtual size_t GetEntitySize() = 0; -}; - -template -class CEntityFactory : public IEntityFactory -{ -public: - CEntityFactory( const char *pClassName ) - { - EntityFactoryDictionary()->InstallFactory( this, pClassName ); - } - - IServerNetworkable *Create( const char *pClassName ) - { - T* pEnt = _CreateEntityTemplate((T*)NULL, pClassName); - return pEnt->NetworkProp(); - } - - void Destroy( IServerNetworkable *pNetworkable ) - { - if ( pNetworkable ) - { - pNetworkable->Release(); - } - } - - virtual size_t GetEntitySize() - { - return sizeof(T); - } -}; - -#define LINK_ENTITY_TO_CLASS(mapClassName,DLLClassName) \ - static CEntityFactory mapClassName( #mapClassName ); - - -// -// Conversion among the three types of "entity", including identity-conversions. -// -inline int ENTINDEX( edict_t *pEdict) -{ - return engine->IndexOfEdict(pEdict); -} - -int ENTINDEX( CBaseEntity *pEnt ); - -inline edict_t* INDEXENT( int iEdictNum ) -{ - return engine->PEntityOfEntIndex(iEdictNum); -} - -// Testing the three types of "entity" for nullity -inline bool FNullEnt(const edict_t* pent) -{ - return pent == NULL || ENTINDEX((edict_t*)pent) == 0; -} - -// Dot products for view cone checking -#define VIEW_FIELD_FULL (float)-1.0 // +-180 degrees -#define VIEW_FIELD_WIDE (float)-0.7 // +-135 degrees 0.1 // +-85 degrees, used for full FOV checks -#define VIEW_FIELD_NARROW (float)0.7 // +-45 degrees, more narrow check used to set up ranged attacks -#define VIEW_FIELD_ULTRA_NARROW (float)0.9 // +-25 degrees, more narrow check used to set up ranged attacks - -class CBaseEntity; -class CBasePlayer; - -extern CGlobalVars *gpGlobals; - -// Misc useful -inline bool FStrEq(const char *sz1, const char *sz2) -{ - return ( sz1 == sz2 || stricmp(sz1, sz2) == 0 ); -} - -#if 0 -// UNDONE: Remove/alter MAKE_STRING so we can do this? -inline bool FStrEq( string_t str1, string_t str2 ) -{ - // now that these are pooled, we can compare them with - // integer equality - return str1 == str2; -} -#endif - -const char *nexttoken(char *token, const char *str, char sep); - -// Misc. Prototypes -void UTIL_SetSize (CBaseEntity *pEnt, const Vector &vecMin, const Vector &vecMax); -void UTIL_ClearTrace ( trace_t &trace ); -void UTIL_SetTrace (trace_t& tr, const Ray_t &ray, edict_t* edict, float fraction, int hitgroup, unsigned int contents, const Vector& normal, float intercept ); - -int UTIL_PrecacheDecal ( const char *name, bool preload = false ); - -//----------------------------------------------------------------------------- - -float UTIL_GetSimulationInterval(); - -//----------------------------------------------------------------------------- -// Purpose: Gets a player pointer by 1-based index -// If player is not yet spawned or connected, returns NULL -// Input : playerIndex - index of the player - first player is index 1 -//----------------------------------------------------------------------------- - -// NOTENOTE: Use UTIL_GetLocalPlayer instead of UTIL_PlayerByIndex IF you're in single player -// and you want the player. -CBasePlayer *UTIL_PlayerByIndex( int playerIndex ); - -// NOTENOTE: Use this instead of UTIL_PlayerByIndex IF you're in single player -// and you want the player. -// not useable in multiplayer - see UTIL_GetListenServerHost() -CBasePlayer* UTIL_GetLocalPlayer( void ); - -// get the local player on a listen server -CBasePlayer *UTIL_GetListenServerHost( void ); - -CBasePlayer* UTIL_PlayerByUserId( int userID ); -CBasePlayer* UTIL_PlayerByName( const char *name ); // not case sensitive - -// Returns true if the command was issued by the listenserver host, or by the dedicated server, via rcon or the server console. -// This is valid during ConCommand execution. -bool UTIL_IsCommandIssuedByServerAdmin( void ); - -CBaseEntity* UTIL_EntityByIndex( int entityIndex ); - -void UTIL_GetPlayerConnectionInfo( int playerIndex, int& ping, int &packetloss ); - -void UTIL_SetClientVisibilityPVS( edict_t *pClient, const unsigned char *pvs, int pvssize ); -bool UTIL_ClientPVSIsExpanded(); - -edict_t *UTIL_FindClientInPVS( edict_t *pEdict ); -edict_t *UTIL_FindClientInVisibilityPVS( edict_t *pEdict ); - -// This is a version which finds any clients whose PVS intersects the box -CBaseEntity *UTIL_FindClientInPVS( const Vector &vecBoxMins, const Vector &vecBoxMaxs ); - -CBaseEntity *UTIL_EntitiesInPVS( CBaseEntity *pPVSEntity, CBaseEntity *pStartingEntity ); - -//----------------------------------------------------------------------------- -// class CFlaggedEntitiesEnum -//----------------------------------------------------------------------------- -// enumerate entities that match a set of edict flags into a static array -class CFlaggedEntitiesEnum : public IPartitionEnumerator -{ -public: - CFlaggedEntitiesEnum( CBaseEntity **pList, int listMax, int flagMask ); - - // This gets called by the enumeration methods with each element - // that passes the test. - virtual IterationRetval_t EnumElement( IHandleEntity *pHandleEntity ); - - int GetCount() { return m_count; } - bool AddToList( CBaseEntity *pEntity ); - -private: - CBaseEntity **m_pList; - int m_listMax; - int m_flagMask; - int m_count; -}; - -// Pass in an array of pointers and an array size, it fills the array and returns the number inserted -int UTIL_EntitiesInBox( const Vector &mins, const Vector &maxs, CFlaggedEntitiesEnum *pEnum ); -int UTIL_EntitiesAlongRay( const Ray_t &ray, CFlaggedEntitiesEnum *pEnum ); -int UTIL_EntitiesInSphere( const Vector ¢er, float radius, CFlaggedEntitiesEnum *pEnum ); - -inline int UTIL_EntitiesInBox( CBaseEntity **pList, int listMax, const Vector &mins, const Vector &maxs, int flagMask ) -{ - CFlaggedEntitiesEnum boxEnum( pList, listMax, flagMask ); - return UTIL_EntitiesInBox( mins, maxs, &boxEnum ); -} - -inline int UTIL_EntitiesAlongRay( CBaseEntity **pList, int listMax, const Ray_t &ray, int flagMask ) -{ - CFlaggedEntitiesEnum rayEnum( pList, listMax, flagMask ); - return UTIL_EntitiesAlongRay( ray, &rayEnum ); -} - -inline int UTIL_EntitiesInSphere( CBaseEntity **pList, int listMax, const Vector ¢er, float radius, int flagMask ) -{ - CFlaggedEntitiesEnum sphereEnum( pList, listMax, flagMask ); - return UTIL_EntitiesInSphere( center, radius, &sphereEnum ); -} - -// marks the entity for deletion so it will get removed next frame -void UTIL_Remove( IServerNetworkable *oldObj ); -void UTIL_Remove( CBaseEntity *oldObj ); - -// deletes an entity, without any delay. Only use this when sure no pointers rely on this entity. -void UTIL_DisableRemoveImmediate(); -void UTIL_EnableRemoveImmediate(); -void UTIL_RemoveImmediate( CBaseEntity *oldObj ); - -// make this a fixed size so it just sits on the stack -#define MAX_SPHERE_QUERY 512 -class CEntitySphereQuery -{ -public: - // currently this builds the list in the constructor - // UNDONE: make an iterative query of ISpatialPartition so we could - // make queries like this optimal - CEntitySphereQuery( const Vector ¢er, float radius, int flagMask=0 ); - CBaseEntity *GetCurrentEntity(); - inline void NextEntity() { m_listIndex++; } - -private: - int m_listIndex; - int m_listCount; - CBaseEntity *m_pList[MAX_SPHERE_QUERY]; -}; - -enum soundlevel_t; - -// Drops an entity onto the floor -int UTIL_DropToFloor( CBaseEntity *pEntity, unsigned int mask, CBaseEntity *pIgnore = NULL ); - -// Returns false if any part of the bottom of the entity is off an edge that is not a staircase. -bool UTIL_CheckBottom( CBaseEntity *pEntity, ITraceFilter *pTraceFilter, float flStepSize ); - -void UTIL_SetOrigin ( CBaseEntity *entity, const Vector &vecOrigin, bool bFireTriggers = false ); -void UTIL_EmitAmbientSound ( int entindex, const Vector &vecOrigin, const char *samp, float vol, soundlevel_t soundlevel, int fFlags, int pitch, float soundtime = 0.0f, float *duration = NULL ); -void UTIL_ParticleEffect ( const Vector &vecOrigin, const Vector &vecDirection, ULONG ulColor, ULONG ulCount ); -void UTIL_ScreenShake ( const Vector ¢er, float amplitude, float frequency, float duration, float radius, ShakeCommand_t eCommand, bool bAirShake=false ); -void UTIL_ScreenShakeObject ( CBaseEntity *pEnt, const Vector ¢er, float amplitude, float frequency, float duration, float radius, ShakeCommand_t eCommand, bool bAirShake=false ); -void UTIL_ViewPunch ( const Vector ¢er, QAngle angPunch, float radius, bool bInAir ); -void UTIL_ShowMessage ( const char *pString, CBasePlayer *pPlayer ); -void UTIL_ShowMessageAll ( const char *pString ); -void UTIL_ScreenFadeAll ( const color32 &color, float fadeTime, float holdTime, int flags ); -void UTIL_ScreenFade ( CBaseEntity *pEntity, const color32 &color, float fadeTime, float fadeHold, int flags ); -void UTIL_MuzzleFlash ( const Vector &origin, const QAngle &angles, int scale, int type ); -Vector UTIL_PointOnLineNearestPoint(const Vector& vStartPos, const Vector& vEndPos, const Vector& vPoint, bool clampEnds = false ); - -int UTIL_EntityInSolid( CBaseEntity *ent ); - -bool UTIL_IsMasterTriggered (string_t sMaster, CBaseEntity *pActivator); -void UTIL_BloodStream( const Vector &origin, const Vector &direction, int color, int amount ); -void UTIL_BloodSpray( const Vector &pos, const Vector &dir, int color, int amount, int flags ); -Vector UTIL_RandomBloodVector( void ); -void UTIL_ImpactTrace( trace_t *pTrace, int iDamageType, const char *pCustomImpactName = NULL ); -void UTIL_PlayerDecalTrace( trace_t *pTrace, int playernum ); -void UTIL_Smoke( const Vector &origin, const float scale, const float framerate ); -void UTIL_AxisStringToPointDir( Vector &start, Vector &dir, const char *pString ); -void UTIL_AxisStringToPointPoint( Vector &start, Vector &end, const char *pString ); -void UTIL_AxisStringToUnitDir( Vector &dir, const char *pString ); -void UTIL_ClipPunchAngleOffset( QAngle &in, const QAngle &punch, const QAngle &clip ); -void UTIL_PredictedPosition( CBaseEntity *pTarget, float flTimeDelta, Vector *vecPredictedPosition ); -void UTIL_Beam( Vector &Start, Vector &End, int nModelIndex, int nHaloIndex, unsigned char FrameStart, unsigned char FrameRate, - float Life, unsigned char Width, unsigned char EndWidth, unsigned char FadeLength, unsigned char Noise, unsigned char Red, unsigned char Green, - unsigned char Blue, unsigned char Brightness, unsigned char Speed); - -char *UTIL_VarArgs( const char *format, ... ); -bool UTIL_IsValidEntity( CBaseEntity *pEnt ); -bool UTIL_TeamsMatch( const char *pTeamName1, const char *pTeamName2 ); - -// snaps a vector to the nearest axis vector (if within epsilon) -void UTIL_SnapDirectionToAxis( Vector &direction, float epsilon = 0.002f ); - -//Set the entity to point at the target specified -bool UTIL_PointAtEntity( CBaseEntity *pEnt, CBaseEntity *pTarget ); -void UTIL_PointAtNamedEntity( CBaseEntity *pEnt, string_t strTarget ); - -// Copy the pose parameter values from one entity to the other -bool UTIL_TransferPoseParameters( CBaseEntity *pSourceEntity, CBaseEntity *pDestEntity ); - -// Search for water transition along a vertical line -float UTIL_WaterLevel( const Vector &position, float minz, float maxz ); - -// Like UTIL_WaterLevel, but *way* less expensive. -// I didn't replace UTIL_WaterLevel everywhere to avoid breaking anything. -float UTIL_FindWaterSurface( const Vector &position, float minz, float maxz ); - -void UTIL_Bubbles( const Vector& mins, const Vector& maxs, int count ); -void UTIL_BubbleTrail( const Vector& from, const Vector& to, int count ); - -// allows precacheing of other entities -void UTIL_PrecacheOther( const char *szClassname, const char *modelName = NULL ); - -// prints a message to each client -void UTIL_ClientPrintAll( int msg_dest, const char *msg_name, const char *param1 = NULL, const char *param2 = NULL, const char *param3 = NULL, const char *param4 = NULL ); -inline void UTIL_CenterPrintAll( const char *msg_name, const char *param1 = NULL, const char *param2 = NULL, const char *param3 = NULL, const char *param4 = NULL ) -{ - UTIL_ClientPrintAll( HUD_PRINTCENTER, msg_name, param1, param2, param3, param4 ); -} - -void UTIL_ValidateSoundName( string_t &name, const char *defaultStr ); - -void UTIL_ClientPrintFilter( IRecipientFilter& filter, int msg_dest, const char *msg_name, const char *param1 = NULL, const char *param2 = NULL, const char *param3 = NULL, const char *param4 = NULL ); - -// prints messages through the HUD -void ClientPrint( CBasePlayer *player, int msg_dest, const char *msg_name, const char *param1 = NULL, const char *param2 = NULL, const char *param3 = NULL, const char *param4 = NULL ); - -// prints a message to the HUD say (chat) -void UTIL_SayText( const char *pText, CBasePlayer *pEntity ); -void UTIL_SayTextAll( const char *pText, CBasePlayer *pEntity = NULL, bool bChat = false ); -void UTIL_SayTextFilter( IRecipientFilter& filter, const char *pText, CBasePlayer *pEntity, bool bChat ); -void UTIL_SayText2Filter( IRecipientFilter& filter, CBasePlayer *pEntity, bool bChat, const char *msg_name, const char *param1 = NULL, const char *param2 = NULL, const char *param3 = NULL, const char *param4 = NULL ); - -byte *UTIL_LoadFileForMe( const char *filename, int *pLength ); -void UTIL_FreeFile( byte *buffer ); - -class CGameTrace; -typedef CGameTrace trace_t; - -//----------------------------------------------------------------------------- -// These are inlined for backwards compatibility -//----------------------------------------------------------------------------- -inline float UTIL_Approach( float target, float value, float speed ) -{ - return Approach( target, value, speed ); -} - -inline float UTIL_ApproachAngle( float target, float value, float speed ) -{ - return ApproachAngle( target, value, speed ); -} - -inline float UTIL_AngleDistance( float next, float cur ) -{ - return AngleDistance( next, cur ); -} - -inline float UTIL_AngleMod(float a) -{ - return anglemod(a); -} - -inline float UTIL_AngleDiff( float destAngle, float srcAngle ) -{ - return AngleDiff( destAngle, srcAngle ); -} - -typedef struct hudtextparms_s -{ - float x; - float y; - int effect; - byte r1, g1, b1, a1; - byte r2, g2, b2, a2; - float fadeinTime; - float fadeoutTime; - float holdTime; - float fxTime; - int channel; -} hudtextparms_t; - - -//----------------------------------------------------------------------------- -// Sets the model to be associated with an entity -//----------------------------------------------------------------------------- -void UTIL_SetModel( CBaseEntity *pEntity, const char *pModelName ); - - -// prints as transparent 'title' to the HUD -void UTIL_HudMessageAll( const hudtextparms_t &textparms, const char *pMessage ); -void UTIL_HudMessage( CBasePlayer *pToPlayer, const hudtextparms_t &textparms, const char *pMessage ); - -// brings up hud keyboard hints display -void UTIL_HudHintText( CBaseEntity *pEntity, const char *pMessage ); - -// Writes message to console with timestamp and FragLog header. -void UTIL_LogPrintf( const char *fmt, ... ); - -// Sorta like FInViewCone, but for nonNPCs. -float UTIL_DotPoints ( const Vector &vecSrc, const Vector &vecCheck, const Vector &vecDir ); - -void UTIL_StripToken( const char *pKey, char *pDest );// for redundant keynames - -// Misc functions -int BuildChangeList( levellist_t *pLevelList, int maxList ); - -// computes gravity scale for an absolute gravity. Pass the result into CBaseEntity::SetGravity() -float UTIL_ScaleForGravity( float desiredGravity ); -// -// How did I ever live without ASSERT? -// -#ifdef DEBUG -void DBG_AssertFunction(bool fExpr, const char* szExpr, const char* szFile, int szLine, const char* szMessage); -#define ASSERT(f) DBG_AssertFunction((bool)((f)!=0), #f, __FILE__, __LINE__, NULL) -#define ASSERTSZ(f, sz) DBG_AssertFunction((bool)((f)!=0), #f, __FILE__, __LINE__, sz) -#else // !DEBUG -#define ASSERT(f) -#define ASSERTSZ(f, sz) -#endif // !DEBUG - - -// -// Constants that were used only by QC (maybe not used at all now) -// -// Un-comment only as needed -// - -#include "globals.h" - -#define LFO_SQUARE 1 -#define LFO_TRIANGLE 2 -#define LFO_RANDOM 3 - -// func_rotating -#define SF_BRUSH_ROTATE_Y_AXIS 0 -#define SF_BRUSH_ROTATE_START_ON 1 -#define SF_BRUSH_ROTATE_BACKWARDS 2 -#define SF_BRUSH_ROTATE_Z_AXIS 4 -#define SF_BRUSH_ROTATE_X_AXIS 8 -#define SF_BRUSH_ROTATE_CLIENTSIDE 16 - - -#define SF_BRUSH_ROTATE_SMALLRADIUS 128 -#define SF_BRUSH_ROTATE_MEDIUMRADIUS 256 -#define SF_BRUSH_ROTATE_LARGERADIUS 512 - -#define PUSH_BLOCK_ONLY_X 1 -#define PUSH_BLOCK_ONLY_Y 2 - -#define SF_LIGHT_START_OFF 1 - -#define SPAWNFLAG_NOMESSAGE 1 -#define SPAWNFLAG_NOTOUCH 1 -#define SPAWNFLAG_DROIDONLY 4 - -#define SPAWNFLAG_USEONLY 1 // can't be touched, must be used (buttons) - -#define TELE_PLAYER_ONLY 1 -#define TELE_SILENT 2 - -// Sound Utilities - -enum soundlevel_t; - -void SENTENCEG_Init(); -void SENTENCEG_Stop(edict_t *entity, int isentenceg, int ipick); -int SENTENCEG_PlayRndI(edict_t *entity, int isentenceg, float volume, soundlevel_t soundlevel, int flags, int pitch); -int SENTENCEG_PlayRndSz(edict_t *entity, const char *szrootname, float volume, soundlevel_t soundlevel, int flags, int pitch); -int SENTENCEG_PlaySequentialSz(edict_t *entity, const char *szrootname, float volume, soundlevel_t soundlevel, int flags, int pitch, int ipick, int freset); -void SENTENCEG_PlaySentenceIndex( edict_t *entity, int iSentenceIndex, float volume, soundlevel_t soundlevel, int flags, int pitch ); -int SENTENCEG_PickRndSz(const char *szrootname); -int SENTENCEG_GetIndex(const char *szrootname); -int SENTENCEG_Lookup(const char *sample); - -char TEXTURETYPE_Find( trace_t *ptr ); - -void UTIL_EmitSoundSuit(edict_t *entity, const char *sample); -int UTIL_EmitGroupIDSuit(edict_t *entity, int isentenceg); -int UTIL_EmitGroupnameSuit(edict_t *entity, const char *groupname); -void UTIL_RestartAmbientSounds( void ); - -class EntityMatrix : public VMatrix -{ -public: - void InitFromEntity( CBaseEntity *pEntity, int iAttachment=0 ); - void InitFromEntityLocal( CBaseEntity *entity ); - - inline Vector LocalToWorld( const Vector &vVec ) const - { - return VMul4x3( vVec ); - } - - inline Vector WorldToLocal( const Vector &vVec ) const - { - return VMul4x3Transpose( vVec ); - } - - inline Vector LocalToWorldRotation( const Vector &vVec ) const - { - return VMul3x3( vVec ); - } - - inline Vector WorldToLocalRotation( const Vector &vVec ) const - { - return VMul3x3Transpose( vVec ); - } -}; - -inline float UTIL_DistApprox( const Vector &vec1, const Vector &vec2 ); -inline float UTIL_DistApprox2D( const Vector &vec1, const Vector &vec2 ); - -//--------------------------------------------------------- -//--------------------------------------------------------- -inline float UTIL_DistApprox( const Vector &vec1, const Vector &vec2 ) -{ - float dx; - float dy; - float dz; - - dx = vec1.x - vec2.x; - dy = vec1.y - vec2.y; - dz = vec1.z - vec2.z; - - return fabs(dx) + fabs(dy) + fabs(dz); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -inline float UTIL_DistApprox2D( const Vector &vec1, const Vector &vec2 ) -{ - float dx; - float dy; - - dx = vec1.x - vec2.x; - dy = vec1.y - vec2.y; - - return fabs(dx) + fabs(dy); -} - -// Find out if an entity is facing another entity or position within a given tolerance range -bool UTIL_IsFacingWithinTolerance( CBaseEntity *pViewer, const Vector &vecPosition, float flDotTolerance, float *pflDot = NULL ); -bool UTIL_IsFacingWithinTolerance( CBaseEntity *pViewer, CBaseEntity *pTarget, float flDotTolerance, float *pflDot = NULL ); - -void UTIL_GetDebugColorForRelationship( int nRelationship, int &r, int &g, int &b ); - -struct datamap_t; -extern const char *UTIL_FunctionToName( datamap_t *pMap, void *function ); -extern void *UTIL_FunctionFromName( datamap_t *pMap, const char *pName ); - -int UTIL_GetCommandClientIndex( void ); -CBasePlayer *UTIL_GetCommandClient( void ); -bool UTIL_GetModDir( char *lpszTextOut, unsigned int nSize ); - -AngularImpulse WorldToLocalRotation( const VMatrix &localToWorld, const Vector &worldAxis, float rotation ); -void UTIL_WorldToParentSpace( CBaseEntity *pEntity, Vector &vecPosition, QAngle &vecAngles ); -void UTIL_WorldToParentSpace( CBaseEntity *pEntity, Vector &vecPosition, Quaternion &quat ); -void UTIL_ParentToWorldSpace( CBaseEntity *pEntity, Vector &vecPosition, QAngle &vecAngles ); -void UTIL_ParentToWorldSpace( CBaseEntity *pEntity, Vector &vecPosition, Quaternion &quat ); - -bool UTIL_LoadAndSpawnEntitiesFromScript( CUtlVector &entities, const char *pScriptFile, const char *pBlock, bool bActivate = true ); - -// Given a vector, clamps the scalar axes to MAX_COORD_FLOAT ranges from worldsize.h -void UTIL_BoundToWorldSize( Vector *pVecPos ); - -#endif // UTIL_H diff --git a/game/server/variant_t.cpp b/game/server/variant_t.cpp deleted file mode 100644 index 8ab4e8afa..000000000 --- a/game/server/variant_t.cpp +++ /dev/null @@ -1,19 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "variant_t.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -void variant_t::SetEntity( CBaseEntity *val ) -{ - eVal = val; - fieldType = FIELD_EHANDLE; -} - - diff --git a/game/server/variant_t.h b/game/server/variant_t.h deleted file mode 100644 index 355431658..000000000 --- a/game/server/variant_t.h +++ /dev/null @@ -1,122 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef VARIANT_T_H -#define VARIANT_T_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "ehandle.h" -#include "mathlib/vmatrix.h" - -class CBaseEntity; - - -// -// A variant class for passing data in entity input/output connections. -// -class variant_t -{ - union - { - bool bVal; - string_t iszVal; - int iVal; - float flVal; - float vecVal[3]; - color32 rgbaVal; - }; - CHandle eVal; // this can't be in the union because it has a constructor. - - fieldtype_t fieldType; - -public: - - // constructor - variant_t() : iVal(0), fieldType(FIELD_VOID) {} - - inline bool Bool( void ) const { return( fieldType == FIELD_BOOLEAN ) ? bVal : false; } - inline const char *String( void ) const { return( fieldType == FIELD_STRING ) ? STRING(iszVal) : ToString(); } - inline string_t StringID( void ) const { return( fieldType == FIELD_STRING ) ? iszVal : NULL_STRING; } - inline int Int( void ) const { return( fieldType == FIELD_INTEGER ) ? iVal : 0; } - inline float Float( void ) const { return( fieldType == FIELD_FLOAT ) ? flVal : 0; } - inline const CHandle &Entity(void) const; - inline color32 Color32(void) const { return rgbaVal; } - inline void Vector3D(Vector &vec) const; - - fieldtype_t FieldType( void ) { return fieldType; } - - void SetBool( bool b ) { bVal = b; fieldType = FIELD_BOOLEAN; } - void SetString( string_t str ) { iszVal = str, fieldType = FIELD_STRING; } - void SetInt( int val ) { iVal = val, fieldType = FIELD_INTEGER; } - void SetFloat( float val ) { flVal = val, fieldType = FIELD_FLOAT; } - void SetEntity( CBaseEntity *val ); - void SetVector3D( const Vector &val ) { vecVal[0] = val[0]; vecVal[1] = val[1]; vecVal[2] = val[2]; fieldType = FIELD_VECTOR; } - void SetPositionVector3D( const Vector &val ) { vecVal[0] = val[0]; vecVal[1] = val[1]; vecVal[2] = val[2]; fieldType = FIELD_POSITION_VECTOR; } - void SetColor32( color32 val ) { rgbaVal = val; fieldType = FIELD_COLOR32; } - void SetColor32( int r, int g, int b, int a ) { rgbaVal.r = r; rgbaVal.g = g; rgbaVal.b = b; rgbaVal.a = a; fieldType = FIELD_COLOR32; } - void Set( fieldtype_t ftype, void *data ); - void SetOther( void *data ); - bool Convert( fieldtype_t newType ); - - static typedescription_t m_SaveBool[]; - static typedescription_t m_SaveInt[]; - static typedescription_t m_SaveFloat[]; - static typedescription_t m_SaveEHandle[]; - static typedescription_t m_SaveString[]; - static typedescription_t m_SaveColor[]; - static typedescription_t m_SaveVector[]; - static typedescription_t m_SavePositionVector[]; - static typedescription_t m_SaveVMatrix[]; - static typedescription_t m_SaveVMatrixWorldspace[]; - static typedescription_t m_SaveMatrix3x4Worldspace[]; - -protected: - - // - // Returns a string representation of the value without modifying the variant. - // - const char *ToString( void ) const; - - friend class CVariantSaveDataOps; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Returns this variant as a vector. -//----------------------------------------------------------------------------- -inline void variant_t::Vector3D(Vector &vec) const -{ - if (( fieldType == FIELD_VECTOR ) || ( fieldType == FIELD_POSITION_VECTOR )) - { - vec[0] = vecVal[0]; - vec[1] = vecVal[1]; - vec[2] = vecVal[2]; - } - else - { - vec = vec3_origin; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Returns this variant as an EHANDLE. -//----------------------------------------------------------------------------- -inline const CHandle &variant_t::Entity(void) const -{ - if ( fieldType == FIELD_EHANDLE ) - return eVal; - - static CHandle hNull; - hNull.Set(NULL); - return(hNull); -} - - -#endif // VARIANT_T_H diff --git a/game/server/vehicle_base.cpp b/game/server/vehicle_base.cpp deleted file mode 100644 index be3dcbeb8..000000000 --- a/game/server/vehicle_base.cpp +++ /dev/null @@ -1,1347 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: UNDONE: Rename this to prop_vehicle.cpp !!! -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "vcollide_parse.h" -#include "vehicle_base.h" -#include "ndebugoverlay.h" -#include "igamemovement.h" -#include "soundenvelope.h" -#include "in_buttons.h" -#include "npc_vehicledriver.h" -#include "physics_saverestore.h" -#include "saverestore_utlvector.h" -#include "func_break.h" -#include "physics_impact_damage.h" -#include "entityblocker.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SF_PROP_VEHICLE_ALWAYSTHINK 0x00000001 - -ConVar g_debug_vehiclebase( "g_debug_vehiclebase", "0", FCVAR_CHEAT ); -extern ConVar g_debug_vehicledriver; - -// CFourWheelServerVehicle -BEGIN_SIMPLE_DATADESC_( CFourWheelServerVehicle, CBaseServerVehicle ) - - DEFINE_EMBEDDED( m_ViewSmoothing ), - -END_DATADESC() - -// CPropVehicle -BEGIN_DATADESC( CPropVehicle ) - - DEFINE_EMBEDDED( m_VehiclePhysics ), - - // These are necessary to save here because the 'owner' of these fields must be the prop_vehicle - DEFINE_PHYSPTR( m_VehiclePhysics.m_pVehicle ), - DEFINE_PHYSPTR_ARRAY( m_VehiclePhysics.m_pWheels ), - - DEFINE_FIELD( m_nVehicleType, FIELD_INTEGER ), - - // Physics Influence - DEFINE_FIELD( m_hPhysicsAttacker, FIELD_EHANDLE ), - DEFINE_FIELD( m_flLastPhysicsInfluenceTime, FIELD_TIME ), - -#ifdef HL2_EPISODIC - DEFINE_UTLVECTOR( m_hPhysicsChildren, FIELD_EHANDLE ), -#endif // HL2_EPISODIC - - // Keys - DEFINE_KEYFIELD( m_vehicleScript, FIELD_STRING, "VehicleScript" ), - DEFINE_FIELD( m_vecSmoothedVelocity, FIELD_VECTOR ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_FLOAT, "Throttle", InputThrottle ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "Steer", InputSteering ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "Action", InputAction ), - DEFINE_INPUTFUNC( FIELD_VOID, "HandBrakeOn", InputHandBrakeOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "HandBrakeOff", InputHandBrakeOff ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( prop_vehicle, CPropVehicle ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -#ifdef _MSC_VER -#pragma warning (disable:4355) -#endif -CPropVehicle::CPropVehicle() : m_VehiclePhysics( this ) -{ - SetVehicleType( VEHICLE_TYPE_CAR_WHEELS ); -} -#ifdef _MSC_VER -#pragma warning (default:4355) -#endif - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CPropVehicle::~CPropVehicle () -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicle::Spawn( ) -{ - CFourWheelServerVehicle *pServerVehicle = dynamic_cast(GetServerVehicle()); - m_VehiclePhysics.SetOuter( this, pServerVehicle ); - - // NOTE: The model has to be set before we can spawn vehicle physics - BaseClass::Spawn(); - SetCollisionGroup( COLLISION_GROUP_VEHICLE ); - - m_VehiclePhysics.Spawn(); - if (!m_VehiclePhysics.Initialize( STRING(m_vehicleScript), m_nVehicleType )) - return; - SetNextThink( gpGlobals->curtime ); - - m_vecSmoothedVelocity.Init(); -} - -// this allows reloading the script variables from disk over an existing vehicle state -// This is useful for tuning vehicles or updating old saved game formats -CON_COMMAND(vehicle_flushscript, "Flush and reload all vehicle scripts") -{ - PhysFlushVehicleScripts(); - for ( CBaseEntity *pEnt = gEntList.FirstEnt(); pEnt != NULL; pEnt = gEntList.NextEnt(pEnt) ) - { - IServerVehicle *pServerVehicle = pEnt->GetServerVehicle(); - if ( pServerVehicle ) - { - pServerVehicle->ReloadScript(); - } - } -} -//----------------------------------------------------------------------------- -// Purpose: Restore -//----------------------------------------------------------------------------- -int CPropVehicle::Restore( IRestore &restore ) -{ - CFourWheelServerVehicle *pServerVehicle = dynamic_cast(GetServerVehicle()); - m_VehiclePhysics.SetOuter( this, pServerVehicle ); - return BaseClass::Restore( restore ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Tell the vehicle physics system whenever we teleport, so it can fixup the wheels. -//----------------------------------------------------------------------------- -void CPropVehicle::Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ) -{ - matrix3x4_t startMatrixInv; - - MatrixInvert( EntityToWorldTransform(), startMatrixInv ); - BaseClass::Teleport( newPosition, newAngles, newVelocity ); - - // Calculate the relative transform of the teleport - matrix3x4_t xform; - ConcatTransforms( EntityToWorldTransform(), startMatrixInv, xform ); - m_VehiclePhysics.Teleport( xform ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicle::DrawDebugGeometryOverlays() -{ - if (m_debugOverlays & OVERLAY_BBOX_BIT) - { - m_VehiclePhysics.DrawDebugGeometryOverlays(); - } - BaseClass::DrawDebugGeometryOverlays(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CPropVehicle::DrawDebugTextOverlays() -{ - int nOffset = BaseClass::DrawDebugTextOverlays(); - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - nOffset = m_VehiclePhysics.DrawDebugTextOverlays( nOffset ); - } - return nOffset; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBasePlayer *CPropVehicle::HasPhysicsAttacker( float dt ) -{ - if (gpGlobals->curtime - dt <= m_flLastPhysicsInfluenceTime) - { - return m_hPhysicsAttacker; - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Keep track of physgun influence -//----------------------------------------------------------------------------- -void CPropVehicle::OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ) -{ - m_hPhysicsAttacker = pPhysGunUser; - m_flLastPhysicsInfluenceTime = gpGlobals->curtime; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicle::InputThrottle( inputdata_t &inputdata ) -{ - m_VehiclePhysics.SetThrottle( inputdata.value.Float() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicle::InputSteering( inputdata_t &inputdata ) -{ - m_VehiclePhysics.SetSteering( inputdata.value.Float(), 2*gpGlobals->frametime ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicle::InputAction( inputdata_t &inputdata ) -{ - m_VehiclePhysics.SetAction( inputdata.value.Float() ); -} - -void CPropVehicle::InputHandBrakeOn( inputdata_t &inputdata ) -{ - m_VehiclePhysics.SetHandbrake( true ); -} - -void CPropVehicle::InputHandBrakeOff( inputdata_t &inputdata ) -{ - m_VehiclePhysics.ReleaseHandbrake(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicle::Think() -{ - m_VehiclePhysics.Think(); - - // Derived classes of CPropVehicle have their own code to determine how frequently to think. - // But the prop_vehicle entity native to this class will only think one time, so this flag - // was added to allow prop_vehicle to always think without affecting the derived classes. - if( HasSpawnFlags(SF_PROP_VEHICLE_ALWAYSTHINK) ) - { - SetNextThink(gpGlobals->curtime); - } -} - -#define SMOOTHING_FACTOR 0.9 - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicle::VPhysicsUpdate( IPhysicsObject *pPhysics ) -{ - if ( IsMarkedForDeletion() ) - return; - - Vector velocity; - VPhysicsGetObject()->GetVelocity( &velocity, NULL ); - - //Update our smoothed velocity - m_vecSmoothedVelocity = m_vecSmoothedVelocity * SMOOTHING_FACTOR + velocity * ( 1 - SMOOTHING_FACTOR ); - - // must be a wheel - if (!m_VehiclePhysics.VPhysicsUpdate( pPhysics )) - return; - - BaseClass::VPhysicsUpdate( pPhysics ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const Vector -//----------------------------------------------------------------------------- -Vector CPropVehicle::GetSmoothedVelocity( void ) -{ - return m_vecSmoothedVelocity; -} - -//============================================================================= -#ifdef HL2_EPISODIC - -//----------------------------------------------------------------------------- -// Purpose: Add an entity to a list which receives physics callbacks from the vehicle -//----------------------------------------------------------------------------- -void CPropVehicle::AddPhysicsChild( CBaseEntity *pChild ) -{ - // Don't add something we already have - if ( m_hPhysicsChildren.Find( pChild ) != m_hPhysicsChildren.InvalidIndex() ) - return ; - - m_hPhysicsChildren.AddToTail( pChild ); -} - -//----------------------------------------------------------------------------- -// Purpose: Removes entity from physics callback list -//----------------------------------------------------------------------------- -void CPropVehicle::RemovePhysicsChild( CBaseEntity *pChild ) -{ - int elemID = m_hPhysicsChildren.Find( pChild ); - - if ( m_hPhysicsChildren.IsValidIndex( elemID ) ) - { - m_hPhysicsChildren.Remove( elemID ); - } -} - -#endif //HL2_EPISODIC -//============================================================================= - -//----------------------------------------------------------------------------- -// Purpose: Player driveable vehicle class -//----------------------------------------------------------------------------- - -IMPLEMENT_SERVERCLASS_ST(CPropVehicleDriveable, DT_PropVehicleDriveable) - - SendPropEHandle(SENDINFO(m_hPlayer)), -// SendPropFloat(SENDINFO_DT_NAME(m_controls.throttle, m_throttle), 8, SPROP_ROUNDUP, 0.0f, 1.0f), - SendPropInt(SENDINFO(m_nSpeed), 8), - SendPropInt(SENDINFO(m_nRPM), 13), - SendPropFloat(SENDINFO(m_flThrottle), 0, SPROP_NOSCALE ), - SendPropInt(SENDINFO(m_nBoostTimeLeft), 8), - SendPropInt(SENDINFO(m_nHasBoost), 1, SPROP_UNSIGNED), - SendPropInt(SENDINFO(m_nScannerDisabledWeapons), 1, SPROP_UNSIGNED), - SendPropInt(SENDINFO(m_nScannerDisabledVehicle), 1, SPROP_UNSIGNED), - SendPropInt(SENDINFO(m_bEnterAnimOn), 1, SPROP_UNSIGNED ), - SendPropInt(SENDINFO(m_bExitAnimOn), 1, SPROP_UNSIGNED ), - SendPropInt(SENDINFO(m_bUnableToFire), 1, SPROP_UNSIGNED ), - SendPropVector(SENDINFO(m_vecEyeExitEndpoint), -1, SPROP_COORD), - SendPropBool(SENDINFO(m_bHasGun)), - SendPropVector(SENDINFO(m_vecGunCrosshair), -1, SPROP_COORD), -END_SEND_TABLE(); - -BEGIN_DATADESC( CPropVehicleDriveable ) - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Lock", InputLock ), - DEFINE_INPUTFUNC( FIELD_VOID, "Unlock", InputUnlock ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOn", InputTurnOn ), - DEFINE_INPUTFUNC( FIELD_VOID, "TurnOff", InputTurnOff ), - DEFINE_INPUT( m_bHasGun, FIELD_BOOLEAN, "EnableGun" ), - - // Outputs - DEFINE_OUTPUT( m_playerOn, "PlayerOn" ), - DEFINE_OUTPUT( m_playerOff, "PlayerOff" ), - DEFINE_OUTPUT( m_pressedAttack, "PressedAttack" ), - DEFINE_OUTPUT( m_pressedAttack2, "PressedAttack2" ), - DEFINE_OUTPUT( m_attackaxis, "AttackAxis" ), - DEFINE_OUTPUT( m_attack2axis, "Attack2Axis" ), - DEFINE_FIELD( m_hPlayer, FIELD_EHANDLE ), - - DEFINE_EMBEDDEDBYREF( m_pServerVehicle ), - DEFINE_FIELD( m_nSpeed, FIELD_INTEGER ), - DEFINE_FIELD( m_nRPM, FIELD_INTEGER ), - DEFINE_FIELD( m_flThrottle, FIELD_FLOAT ), - DEFINE_FIELD( m_nBoostTimeLeft, FIELD_INTEGER ), - DEFINE_FIELD( m_nHasBoost, FIELD_INTEGER ), - DEFINE_FIELD( m_nScannerDisabledWeapons, FIELD_BOOLEAN ), - DEFINE_FIELD( m_nScannerDisabledVehicle, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bUnableToFire, FIELD_BOOLEAN ), - DEFINE_FIELD( m_vecEyeExitEndpoint, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecGunCrosshair, FIELD_VECTOR ), - - DEFINE_FIELD( m_bEngineLocked, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_bLocked, FIELD_BOOLEAN, "VehicleLocked" ), - DEFINE_FIELD( m_flMinimumSpeedToEnterExit, FIELD_FLOAT ), - DEFINE_FIELD( m_bEnterAnimOn, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bExitAnimOn, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flTurnOffKeepUpright, FIELD_TIME ), - //DEFINE_FIELD( m_flNoImpactDamageTime, FIELD_TIME ), - - DEFINE_FIELD( m_hNPCDriver, FIELD_EHANDLE ), - DEFINE_FIELD( m_hKeepUpright, FIELD_EHANDLE ), - -END_DATADESC() - - -LINK_ENTITY_TO_CLASS( prop_vehicle_driveable, CPropVehicleDriveable ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CPropVehicleDriveable::CPropVehicleDriveable( void ) : - m_pServerVehicle( NULL ), - m_hKeepUpright( NULL ), - m_flTurnOffKeepUpright( 0 ), - m_flNoImpactDamageTime( 0 ) -{ - m_vecEyeExitEndpoint.Init(); - m_vecGunCrosshair.Init(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CPropVehicleDriveable::~CPropVehicleDriveable( void ) -{ - DestroyServerVehicle(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleDriveable::CreateServerVehicle( void ) -{ - // Create our server vehicle - m_pServerVehicle = new CFourWheelServerVehicle(); - m_pServerVehicle->SetVehicle( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleDriveable::DestroyServerVehicle() -{ - if ( m_pServerVehicle ) - { - delete m_pServerVehicle; - m_pServerVehicle = NULL; - } -} - -//------------------------------------------------ -// Precache -//------------------------------------------------ -void CPropVehicleDriveable::Precache( void ) -{ - BaseClass::Precache(); - - // This step is needed because if we're precaching from a templated instance, we'll miss our vehicle - // script sounds unless we do the parse below. This instance of the vehicle will be nuked when we're actually created. - if ( m_pServerVehicle == NULL ) - { - CreateServerVehicle(); - } - - // Load the script file and precache our assets - if ( m_pServerVehicle ) - { - m_pServerVehicle->Initialize( STRING( m_vehicleScript ) ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleDriveable::Spawn( void ) -{ - // Has to be created before Spawn is called (since that causes Precache to be called) - DestroyServerVehicle(); - CreateServerVehicle(); - - // Initialize our vehicle via script - if ( m_pServerVehicle->Initialize( STRING(m_vehicleScript) ) == false ) - { - Warning( "Vehicle (%s) unable to properly initialize due to script error in (%s)!\n", GetEntityName().ToCStr(), STRING( m_vehicleScript ) ); - SetThink( &CBaseEntity::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 0.1f ); - return; - } - - BaseClass::Spawn(); - - m_flMinimumSpeedToEnterExit = 0; - m_takedamage = DAMAGE_EVENTS_ONLY; - m_bEngineLocked = false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CPropVehicleDriveable::Restore( IRestore &restore ) -{ - // Has to be created before we can restore - // and we can't create it in the constructor because it could be - // overridden by a derived class. - DestroyServerVehicle(); - CreateServerVehicle(); - - int nRetVal = BaseClass::Restore( restore ); - - return nRetVal; -} - -//----------------------------------------------------------------------------- -// Purpose: Do extra fix-up after restore -//----------------------------------------------------------------------------- -void CPropVehicleDriveable::OnRestore( void ) -{ - BaseClass::OnRestore(); - - // NOTE: This is necessary to prevent overflow of datatables on level transition - // since the last exit eyepoint in the last level will have been fixed up - // based on the level landmarks, resulting in a position that lies outside - // typical map coordinates. If we're not in the middle of an exit anim, the - // eye exit endpoint field isn't being used at all. - if ( !m_bExitAnimOn ) - { - m_vecEyeExitEndpoint = GetAbsOrigin(); - } - - m_flNoImpactDamageTime = gpGlobals->curtime + 5.0f; - - IServerVehicle *pServerVehicle = GetServerVehicle(); - if ( pServerVehicle != NULL ) - { - // Restore the passenger information we're holding on to - pServerVehicle->RestorePassengerInfo(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Vehicles are permanently oriented off angle for vphysics. -//----------------------------------------------------------------------------- -void CPropVehicleDriveable::GetVectors(Vector* pForward, Vector* pRight, Vector* pUp) const -{ - // This call is necessary to cause m_rgflCoordinateFrame to be recomputed - const matrix3x4_t &entityToWorld = EntityToWorldTransform(); - - if (pForward != NULL) - { - MatrixGetColumn( entityToWorld, 1, *pForward ); - } - - if (pRight != NULL) - { - MatrixGetColumn( entityToWorld, 0, *pRight ); - } - - if (pUp != NULL) - { - MatrixGetColumn( entityToWorld, 2, *pUp ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: AngleVectors equivalent that accounts for the hacked 90 degree rotation of vehicles -// BUGBUG: VPhysics is hardcoded so that vehicles must face down Y instead of X like everything else -//----------------------------------------------------------------------------- -void CPropVehicleDriveable::VehicleAngleVectors( const QAngle &angles, Vector *pForward, Vector *pRight, Vector *pUp ) -{ - AngleVectors( angles, pRight, pForward, pUp ); - if ( pForward ) - { - *pForward *= -1; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleDriveable::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - CBasePlayer *pPlayer = ToBasePlayer( pActivator ); - if ( !pPlayer ) - return; - - ResetUseKey( pPlayer ); - - m_pServerVehicle->HandlePassengerEntry( pPlayer, (value>0) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseEntity *CPropVehicleDriveable::GetDriver( void ) -{ - if ( m_hNPCDriver ) - return m_hNPCDriver; - - return m_hPlayer; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleDriveable::EnterVehicle( CBaseCombatCharacter *pPassenger ) -{ - if ( pPassenger == NULL ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( pPassenger ); - if ( pPlayer != NULL ) - { - // Remove any player who may be in the vehicle at the moment - if ( m_hPlayer ) - { - ExitVehicle( VEHICLE_ROLE_DRIVER ); - } - - m_hPlayer = pPlayer; - m_playerOn.FireOutput( pPlayer, this, 0 ); - - // Don't start the engine if the player's using an entry animation, - // because we want to start the engine once the animation is done. - if ( !m_bEnterAnimOn ) - { - StartEngine(); - } - - // Start Thinking - SetNextThink( gpGlobals->curtime ); - - Vector vecViewOffset = m_pServerVehicle->GetSavedViewOffset(); - - // Clear our state - m_pServerVehicle->InitViewSmoothing( pPlayer->GetAbsOrigin() + vecViewOffset, pPlayer->EyeAngles() ); - - m_VehiclePhysics.GetVehicle()->OnVehicleEnter(); - } - else - { - // NPCs are not yet supported - jdw - Assert( 0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleDriveable::ExitVehicle( int nRole ) -{ - CBasePlayer *pPlayer = m_hPlayer; - if ( !pPlayer ) - return; - - m_hPlayer = NULL; - ResetUseKey( pPlayer ); - - m_playerOff.FireOutput( pPlayer, this, 0 ); - - // clear out the fire buttons - m_attackaxis.Set( 0, pPlayer, this ); - m_attack2axis.Set( 0, pPlayer, this ); - - m_nSpeed = 0; - m_flThrottle = 0.0f; - - StopEngine(); - - m_VehiclePhysics.GetVehicle()->OnVehicleExit(); - - // Clear our state - m_pServerVehicle->InitViewSmoothing( vec3_origin, vec3_angle ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleDriveable::ResetUseKey( CBasePlayer *pPlayer ) -{ - pPlayer->m_afButtonPressed &= ~IN_USE; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleDriveable::DriveVehicle( CBasePlayer *pPlayer, CUserCmd *ucmd ) -{ - //Lose control when the player dies - if ( pPlayer->IsAlive() == false ) - return; - - DriveVehicle( TICK_INTERVAL, ucmd, pPlayer->m_afButtonPressed, pPlayer->m_afButtonReleased ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleDriveable::DriveVehicle( float flFrameTime, CUserCmd *ucmd, int iButtonsDown, int iButtonsReleased ) -{ - int iButtons = ucmd->buttons; - - m_VehiclePhysics.UpdateDriverControls( ucmd, flFrameTime ); - - m_nSpeed = m_VehiclePhysics.GetSpeed(); //send speed to client - m_nRPM = clamp( m_VehiclePhysics.GetRPM(), 0, 4095 ); - m_nBoostTimeLeft = m_VehiclePhysics.BoostTimeLeft(); - m_nHasBoost = m_VehiclePhysics.HasBoost(); - m_flThrottle = m_VehiclePhysics.GetThrottle(); - - m_nScannerDisabledWeapons = false; // off for now, change once we have scanners - m_nScannerDisabledVehicle = false; // off for now, change once we have scanners - - // - // Fire the appropriate outputs based on button pressed events. - // - // BUGBUG: m_afButtonPressed is broken - check the player.cpp code!!! - float attack = 0, attack2 = 0; - - if ( iButtonsDown & IN_ATTACK ) - { - m_pressedAttack.FireOutput( this, this, 0 ); - } - if ( iButtonsDown & IN_ATTACK2 ) - { - m_pressedAttack2.FireOutput( this, this, 0 ); - } - - if ( iButtons & IN_ATTACK ) - { - attack = 1; - } - if ( iButtons & IN_ATTACK2 ) - { - attack2 = 1; - } - - m_attackaxis.Set( attack, this, this ); - m_attack2axis.Set( attack2, this, this ); -} - -//----------------------------------------------------------------------------- -// Purpose: Tells whether or not the car has been overturned -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CPropVehicleDriveable::IsOverturned( void ) -{ - Vector vUp; - VehicleAngleVectors( GetAbsAngles(), NULL, NULL, &vUp ); - - float upDot = DotProduct( Vector(0,0,1), vUp ); - - // Tweak this number to adjust what's considered "overturned" - if ( upDot < 0.0f ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleDriveable::Think() -{ - BaseClass::Think(); - - if ( ShouldThink() ) - { - SetNextThink( gpGlobals->curtime ); - } - - // If we have an NPC Driver, tell him to drive - if ( m_hNPCDriver ) - { - GetServerVehicle()->NPC_DriveVehicle(); - } - - // Keep thinking while we're waiting to turn off the keep upright - if ( m_flTurnOffKeepUpright ) - { - SetNextThink( gpGlobals->curtime ); - - // Time up? - if ( m_hKeepUpright != NULL && m_flTurnOffKeepUpright < gpGlobals->curtime ) - { - variant_t emptyVariant; - m_hKeepUpright->AcceptInput( "TurnOff", this, this, emptyVariant, USE_TOGGLE ); - m_flTurnOffKeepUpright = 0; - - UTIL_Remove( m_hKeepUpright ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleDriveable::SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) -{ - // If the engine's not active, prevent driving - if ( !IsEngineOn() || m_bEngineLocked ) - return; - - // If the player's entering/exiting the vehicle, prevent movement - if ( m_bEnterAnimOn || m_bExitAnimOn ) - return; - - DriveVehicle( player, ucmd ); -} - -//----------------------------------------------------------------------------- -// Purpose: Prevent the player from entering / exiting the vehicle -//----------------------------------------------------------------------------- -void CPropVehicleDriveable::InputLock( inputdata_t &inputdata ) -{ - m_bLocked = true; -} - -//----------------------------------------------------------------------------- -// Purpose: Allow the player to enter / exit the vehicle -//----------------------------------------------------------------------------- -void CPropVehicleDriveable::InputUnlock( inputdata_t &inputdata ) -{ - m_bLocked = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Return true of the player's allowed to enter the vehicle -//----------------------------------------------------------------------------- -bool CPropVehicleDriveable::CanEnterVehicle( CBaseEntity *pEntity ) -{ - // Only drivers are supported - Assert( pEntity && pEntity->IsPlayer() ); - - // Prevent entering if the vehicle's being driven by an NPC - if ( GetDriver() && GetDriver() != pEntity ) - return false; - - // Can't enter if we're upside-down - if ( IsOverturned() ) - return false; - - // Prevent entering if the vehicle's locked, or if it's moving too fast. - return ( !m_bLocked && (m_nSpeed <= m_flMinimumSpeedToEnterExit) ); -} - -//----------------------------------------------------------------------------- -// Purpose: Return true of the player's allowed to exit the vehicle -//----------------------------------------------------------------------------- -bool CPropVehicleDriveable::CanExitVehicle( CBaseEntity *pEntity ) -{ - // Prevent exiting if the vehicle's locked, or if it's moving too fast. - return ( !m_bEnterAnimOn && !m_bExitAnimOn && !m_bLocked && (m_nSpeed <= m_flMinimumSpeedToEnterExit) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleDriveable::InputTurnOn( inputdata_t &inputdata ) -{ - m_bEngineLocked = false; - - StartEngine(); - m_VehiclePhysics.SetDisableEngine( false ); - -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleDriveable::InputTurnOff( inputdata_t &inputdata ) -{ - m_bEngineLocked = true; - - StopEngine(); - m_VehiclePhysics.SetDisableEngine( true ); -} - -//----------------------------------------------------------------------------- -// Purpose: Check to see if the engine is on. -//----------------------------------------------------------------------------- -bool CPropVehicleDriveable::IsEngineOn( void ) -{ - return m_VehiclePhysics.IsOn(); -} - -//----------------------------------------------------------------------------- -// Purpose: Turn on the engine, but only if we're allowed to -//----------------------------------------------------------------------------- -void CPropVehicleDriveable::StartEngine( void ) -{ - if ( m_bEngineLocked ) - { - m_VehiclePhysics.SetHandbrake( true ); - return; - } - - m_VehiclePhysics.TurnOn(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleDriveable::StopEngine( void ) -{ - m_VehiclePhysics.TurnOff(); -} - -//----------------------------------------------------------------------------- -// Purpose: // The player takes damage if he hits something going fast enough -//----------------------------------------------------------------------------- -void CPropVehicleDriveable::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) -{ - -//============================================================================= -#ifdef HL2_EPISODIC - - // Notify all children - for ( int i = 0; i < m_hPhysicsChildren.Count(); i++ ) - { - if ( m_hPhysicsChildren[i] == NULL ) - continue; - - m_hPhysicsChildren[i]->VPhysicsCollision( index, pEvent ); - } - -#endif // HL2_EPISODIC -//============================================================================= - - // Don't care if we don't have a driver - CBaseCombatCharacter *pDriver = GetDriver() ? GetDriver()->MyCombatCharacterPointer() : NULL; - if ( !pDriver ) - return; - - // Make sure we don't keep hitting the same entity - int otherIndex = !index; - CBaseEntity *pHitEntity = pEvent->pEntities[otherIndex]; - if ( pEvent->deltaCollisionTime < 0.5 && (pHitEntity == this) ) - return; - - BaseClass::VPhysicsCollision( index, pEvent ); - - // if this is a bone follower, promote to the owner entity - if ( pHitEntity->GetOwnerEntity() && (pHitEntity->GetEffects() & EF_NODRAW) ) - { - CBaseEntity *pOwner = pHitEntity->GetOwnerEntity(); - // no friendly bone follower damage - // this allows strider legs to damage the player on impact but not d0g for example - if ( pDriver->IRelationType( pOwner ) == D_LI ) - return; - } - - // If we hit hard enough, damage the player - // Don't take damage from ramming bad guys - if ( pHitEntity->MyNPCPointer() ) - { - return; - } - - // Don't take damage from ramming ragdolls - if ( pEvent->pObjects[otherIndex]->GetGameFlags() & FVPHYSICS_PART_OF_RAGDOLL ) - return; - - // Ignore func_breakables - CBreakable *pBreakable = dynamic_cast(pHitEntity); - if ( pBreakable ) - { - // ROBIN: Do we want to only do this on func_breakables that are about to die? - //if ( pBreakable->HasSpawnFlags( SF_PHYSICS_BREAK_IMMEDIATELY ) ) - return; - } - - // Over our skill's minimum crash level? - int damageType = 0; - float flDamage = CalculatePhysicsImpactDamage( index, pEvent, gDefaultPlayerVehicleImpactDamageTable, 1.0, true, damageType ); - if ( flDamage > 0 && m_flNoImpactDamageTime < gpGlobals->curtime ) - { - Vector damagePos; - pEvent->pInternalData->GetContactPoint( damagePos ); - Vector damageForce = pEvent->postVelocity[index] * pEvent->pObjects[index]->GetMass(); - CTakeDamageInfo info( this, GetDriver(), damageForce, damagePos, flDamage, (damageType|DMG_VEHICLE) ); - GetDriver()->TakeDamage( info ); - } -} - -int CPropVehicleDriveable::VPhysicsGetObjectList( IPhysicsObject **pList, int listMax ) -{ - return GetPhysics()->VPhysicsGetObjectList( pList, listMax ); -} - -//----------------------------------------------------------------------------- -// Purpose: Handle trace attacks from the physcannon -//----------------------------------------------------------------------------- -void CPropVehicleDriveable::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - // If we've just been zapped by the physcannon, try and right ourselves - if ( info.GetDamageType() & DMG_PHYSGUN ) - { - float flUprightStrength = GetUprightStrength(); - if ( flUprightStrength ) - { - // Update our strength value if we already have an upright controller - if ( m_hKeepUpright ) - { - variant_t limitVariant; - limitVariant.SetFloat( flUprightStrength ); - m_hKeepUpright->AcceptInput( "SetAngularLimit", this, this, limitVariant, USE_TOGGLE ); - } - else - { - // If we don't have one, create an upright controller for us - m_hKeepUpright = CreateKeepUpright( GetAbsOrigin(), vec3_angle, this, GetUprightStrength(), false ); - } - - Assert( m_hKeepUpright ); - variant_t emptyVariant; - m_hKeepUpright->AcceptInput( "TurnOn", this, this, emptyVariant, USE_TOGGLE ); - - // Turn off the keepupright after a short time - m_flTurnOffKeepUpright = gpGlobals->curtime + GetUprightTime(); - SetNextThink( gpGlobals->curtime ); - } - -#ifdef HL2_EPISODIC - // Notify all children - for ( int i = 0; i < m_hPhysicsChildren.Count(); i++ ) - { - if ( m_hPhysicsChildren[i] == NULL ) - continue; - - variant_t emptyVariant; - m_hPhysicsChildren[i]->AcceptInput( "VehiclePunted", info.GetAttacker(), this, emptyVariant, USE_TOGGLE ); - } -#endif // HL2_EPISODIC - - } - - BaseClass::TraceAttack( info, vecDir, ptr ); -} - -//============================================================================= -// Passenger carrier - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPassenger - -// bCompanion - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CPropVehicleDriveable::NPC_CanEnterVehicle( CAI_BaseNPC *pPassenger, bool bCompanion ) -{ - // Always allowed unless a leaf class says otherwise - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPassenger - -// bCompanion - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CPropVehicleDriveable::NPC_CanExitVehicle( CAI_BaseNPC *pPassenger, bool bCompanion ) -{ - // Always allowed unless a leaf class says otherwise - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPassenger - -// bCompanion - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CPropVehicleDriveable::NPC_AddPassenger( CAI_BaseNPC *pPassenger, string_t strRoleName, int nSeatID ) -{ - // Must be allowed to enter - if ( NPC_CanEnterVehicle( pPassenger, true /*FIXME*/ ) == false ) - return false; - - IServerVehicle *pVehicleServer = GetServerVehicle(); - if ( pVehicleServer != NULL ) - return pVehicleServer->NPC_AddPassenger( pPassenger, strRoleName, nSeatID ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPassenger - -// bCompanion - -//----------------------------------------------------------------------------- -bool CPropVehicleDriveable::NPC_RemovePassenger( CAI_BaseNPC *pPassenger ) -{ - // Must be allowed to exit - if ( NPC_CanExitVehicle( pPassenger, true /*FIXME*/ ) == false ) - return false; - - IServerVehicle *pVehicleServer = GetServerVehicle(); - if ( pVehicleServer != NULL ) - return pVehicleServer->NPC_RemovePassenger( pPassenger ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pVictim - -// &info - -//----------------------------------------------------------------------------- -void CPropVehicleDriveable::Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info ) -{ - CBaseEntity *pDriver = GetDriver(); - if ( pDriver != NULL ) - { - pDriver->Event_KilledOther( pVictim, info ); - } - - BaseClass::Event_KilledOther( pVictim, info ); -} - -//======================================================================================================================================== -// FOUR WHEEL PHYSICS VEHICLE SERVER VEHICLE -//======================================================================================================================================== -CFourWheelServerVehicle::CFourWheelServerVehicle( void ) -{ - // Setup our smoothing data - memset( &m_ViewSmoothing, 0, sizeof( m_ViewSmoothing ) ); - - m_ViewSmoothing.bClampEyeAngles = true; - m_ViewSmoothing.bDampenEyePosition = true; - m_ViewSmoothing.flPitchCurveZero = PITCH_CURVE_ZERO; - m_ViewSmoothing.flPitchCurveLinear = PITCH_CURVE_LINEAR; - m_ViewSmoothing.flRollCurveZero = ROLL_CURVE_ZERO; - m_ViewSmoothing.flRollCurveLinear = ROLL_CURVE_LINEAR; -} - -#ifdef HL2_EPISODIC -ConVar r_JeepFOV( "r_JeepFOV", "82", FCVAR_CHEAT | FCVAR_REPLICATED ); -#else -ConVar r_JeepFOV( "r_JeepFOV", "90", FCVAR_CHEAT | FCVAR_REPLICATED ); -#endif // HL2_EPISODIC - -//----------------------------------------------------------------------------- -// Purpose: Setup our view smoothing information -//----------------------------------------------------------------------------- -void CFourWheelServerVehicle::InitViewSmoothing( const Vector &vecOrigin, const QAngle &vecAngles ) -{ - m_ViewSmoothing.bWasRunningAnim = false; - m_ViewSmoothing.vecOriginSaved = vecOrigin; - m_ViewSmoothing.vecAnglesSaved = vecAngles; - m_ViewSmoothing.flFOV = r_JeepFOV.GetFloat(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFourWheelServerVehicle::SetVehicle( CBaseEntity *pVehicle ) -{ - ASSERT( dynamic_cast(pVehicle) ); - BaseClass::SetVehicle( pVehicle ); - - // Save this for view smoothing - if ( pVehicle != NULL ) - { - m_ViewSmoothing.pVehicle = pVehicle->GetBaseAnimating(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Modify the player view/camera while in a vehicle -//----------------------------------------------------------------------------- -void CFourWheelServerVehicle::GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV /*= NULL*/ ) -{ - CBaseEntity *pDriver = GetPassenger( nRole ); - if ( pDriver && pDriver->IsPlayer()) - { - CBasePlayer *pPlayerDriver = ToBasePlayer( pDriver ); - CPropVehicleDriveable *pVehicle = GetFourWheelVehicle(); - SharedVehicleViewSmoothing( pPlayerDriver, - pAbsOrigin, pAbsAngles, - pVehicle->IsEnterAnimOn(), pVehicle->IsExitAnimOn(), - pVehicle->GetEyeExitEndpoint(), - &m_ViewSmoothing, - pFOV ); - } - else - { - // NPCs are not supported - Assert( 0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const vehicleparams_t *CFourWheelServerVehicle::GetVehicleParams( void ) -{ - return &GetFourWheelVehiclePhysics()->GetVehicleParams(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const vehicle_operatingparams_t *CFourWheelServerVehicle::GetVehicleOperatingParams( void ) -{ - return &GetFourWheelVehiclePhysics()->GetVehicleOperatingParams(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const vehicle_controlparams_t *CFourWheelServerVehicle::GetVehicleControlParams( void ) -{ - return &GetFourWheelVehiclePhysics()->GetVehicleControls(); -} - -IPhysicsVehicleController *CFourWheelServerVehicle::GetVehicleController() -{ - return GetFourWheelVehiclePhysics()->GetVehicleController(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CPropVehicleDriveable *CFourWheelServerVehicle::GetFourWheelVehicle( void ) -{ - return (CPropVehicleDriveable *)m_pVehicle; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CFourWheelVehiclePhysics *CFourWheelServerVehicle::GetFourWheelVehiclePhysics( void ) -{ - CPropVehicleDriveable *pVehicle = GetFourWheelVehicle(); - return pVehicle->GetPhysics(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CFourWheelServerVehicle::IsVehicleUpright( void ) -{ - return (GetFourWheelVehicle()->IsOverturned() == false); -} - -bool CFourWheelServerVehicle::IsVehicleBodyInWater() -{ - return GetFourWheelVehicle()->IsVehicleBodyInWater(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CFourWheelServerVehicle::IsPassengerEntering( void ) -{ - return GetFourWheelVehicle()->IsEnterAnimOn(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CFourWheelServerVehicle::IsPassengerExiting( void ) -{ - return GetFourWheelVehicle()->IsExitAnimOn(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFourWheelServerVehicle::NPC_SetDriver( CNPC_VehicleDriver *pDriver ) -{ - if ( pDriver ) - { - m_nNPCButtons = 0; - GetFourWheelVehicle()->m_hNPCDriver = pDriver; - GetFourWheelVehicle()->StartEngine(); - SetVehicleVolume( 1.0 ); // Vehicles driven by NPCs are louder - - // Set our owner entity to be the NPC, so it can path check without hitting us - GetFourWheelVehicle()->SetOwnerEntity( pDriver ); - - // Start Thinking - GetFourWheelVehicle()->SetNextThink( gpGlobals->curtime ); - } - else - { - GetFourWheelVehicle()->m_hNPCDriver = NULL; - GetFourWheelVehicle()->StopEngine(); - GetFourWheelVehicle()->SetOwnerEntity( NULL ); - SetVehicleVolume( 0.5 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFourWheelServerVehicle::NPC_DriveVehicle( void ) -{ - -#ifdef HL2_DLL - if ( g_debug_vehicledriver.GetInt() ) - { - if ( m_nNPCButtons ) - { - Vector vecForward, vecRight; - GetFourWheelVehicle()->GetVectors( &vecForward, &vecRight, NULL ); - if ( m_nNPCButtons & IN_FORWARD ) - { - NDebugOverlay::Line( GetFourWheelVehicle()->GetAbsOrigin(), GetFourWheelVehicle()->GetAbsOrigin() + vecForward * 200, 0,255,0, true, 0.1 ); - } - if ( m_nNPCButtons & IN_BACK ) - { - NDebugOverlay::Line( GetFourWheelVehicle()->GetAbsOrigin(), GetFourWheelVehicle()->GetAbsOrigin() - vecForward * 200, 0,255,0, true, 0.1 ); - } - if ( m_nNPCButtons & IN_MOVELEFT ) - { - NDebugOverlay::Line( GetFourWheelVehicle()->GetAbsOrigin(), GetFourWheelVehicle()->GetAbsOrigin() - vecRight * 200 * -m_flTurnDegrees, 0,255,0, true, 0.1 ); - } - if ( m_nNPCButtons & IN_MOVERIGHT ) - { - NDebugOverlay::Line( GetFourWheelVehicle()->GetAbsOrigin(), GetFourWheelVehicle()->GetAbsOrigin() + vecRight * 200 * m_flTurnDegrees, 0,255,0, true, 0.1 ); - } - if ( m_nNPCButtons & IN_JUMP ) - { - NDebugOverlay::Box( GetFourWheelVehicle()->GetAbsOrigin(), -Vector(20,20,20), Vector(20,20,20), 0,255,0, true, 0.1 ); - } - } - } -#endif - - int buttonsChanged = m_nPrevNPCButtons ^ m_nNPCButtons; - int afButtonPressed = buttonsChanged & m_nNPCButtons; // The changed ones still down are "pressed" - int afButtonReleased = buttonsChanged & (~m_nNPCButtons); // The ones not down are "released" - CUserCmd fakeCmd; - fakeCmd.Reset(); - fakeCmd.buttons = m_nNPCButtons; - fakeCmd.forwardmove += 200.0f * ( m_nNPCButtons & IN_FORWARD ); - fakeCmd.forwardmove -= 200.0f * ( m_nNPCButtons & IN_BACK ); - fakeCmd.sidemove -= 200.0f * ( m_nNPCButtons & IN_MOVELEFT ); - fakeCmd.sidemove += 200.0f * ( m_nNPCButtons & IN_MOVERIGHT ); - - GetFourWheelVehicle()->DriveVehicle( gpGlobals->frametime, &fakeCmd, afButtonPressed, afButtonReleased ); - m_nPrevNPCButtons = m_nNPCButtons; - - // NPC's cheat by using analog steering. - GetFourWheelVehiclePhysics()->SetSteering( m_flTurnDegrees, 0 ); - - // Clear out attack buttons each frame - m_nNPCButtons &= ~IN_ATTACK; - m_nNPCButtons &= ~IN_ATTACK2; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : nWheelIndex - -// &vecPos - -//----------------------------------------------------------------------------- -bool CFourWheelServerVehicle::GetWheelContactPoint( int nWheelIndex, Vector &vecPos ) -{ - // Dig through a couple layers to get to our data - CFourWheelVehiclePhysics *pVehiclePhysics = GetFourWheelVehiclePhysics(); - if ( pVehiclePhysics ) - { - IPhysicsVehicleController *pVehicleController = pVehiclePhysics->GetVehicle(); - if ( pVehicleController ) - { - return pVehicleController->GetWheelContactPoint( nWheelIndex, &vecPos, NULL ); - } - } - return false; -} diff --git a/game/server/vehicle_base.h b/game/server/vehicle_base.h deleted file mode 100644 index 764c60d99..000000000 --- a/game/server/vehicle_base.h +++ /dev/null @@ -1,313 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef VEHICLE_BASE_H -#define VEHICLE_BASE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "vphysics/vehicles.h" -#include "iservervehicle.h" -#include "fourwheelvehiclephysics.h" -#include "props.h" -#include "vehicle_sounds.h" -#include "phys_controller.h" -#include "entityblocker.h" -#include "vehicle_baseserver.h" -#include "vehicle_viewblend_shared.h" - -class CNPC_VehicleDriver; -class CFourWheelVehiclePhysics; -class CPropVehicleDriveable; -class CSoundPatch; - -// the tires are considered to be skidding if they have sliding velocity of 10 in/s or more -const float DEFAULT_SKID_THRESHOLD = 10.0f; - -//----------------------------------------------------------------------------- -// Purpose: Four wheel physics vehicle server vehicle -//----------------------------------------------------------------------------- -class CFourWheelServerVehicle : public CBaseServerVehicle -{ - DECLARE_CLASS( CFourWheelServerVehicle, CBaseServerVehicle ); - -// IServerVehicle -public: - virtual ~CFourWheelServerVehicle( void ) - { - } - - CFourWheelServerVehicle( void ); - virtual bool IsVehicleUpright( void ); - virtual bool IsVehicleBodyInWater( void ); - virtual void GetVehicleViewPosition( int nRole, Vector *pOrigin, QAngle *pAngles, float *pFOV = NULL ); - IPhysicsVehicleController *GetVehicleController(); - const vehicleparams_t *GetVehicleParams( void ); - const vehicle_controlparams_t *GetVehicleControlParams( void ); - const vehicle_operatingparams_t *GetVehicleOperatingParams( void ); - - // NPC Driving - void NPC_SetDriver( CNPC_VehicleDriver *pDriver ); - void NPC_DriveVehicle( void ); - - CPropVehicleDriveable *GetFourWheelVehicle( void ); - bool GetWheelContactPoint( int nWheelIndex, Vector &vecPos ); - -public: - virtual void SetVehicle( CBaseEntity *pVehicle ); - void InitViewSmoothing( const Vector &vecStartOrigin, const QAngle &vecStartAngles ); - bool IsPassengerEntering( void ); - bool IsPassengerExiting( void ); - - DECLARE_SIMPLE_DATADESC(); - -private: - CFourWheelVehiclePhysics *GetFourWheelVehiclePhysics( void ); - - ViewSmoothingData_t m_ViewSmoothing; -}; - -//----------------------------------------------------------------------------- -// Purpose: Base class for four wheel physics vehicles -//----------------------------------------------------------------------------- -class CPropVehicle : public CBaseProp, public CDefaultPlayerPickupVPhysics -{ - DECLARE_CLASS( CPropVehicle, CBaseProp ); -public: - CPropVehicle(); - virtual ~CPropVehicle(); - - void SetVehicleType( unsigned int nVehicleType ) { m_nVehicleType = nVehicleType; } - unsigned int GetVehicleType( void ) { return m_nVehicleType; } - - // CBaseEntity - void Spawn( void ); - virtual int Restore( IRestore &restore ); - void VPhysicsUpdate( IPhysicsObject *pPhysics ); - void DrawDebugGeometryOverlays(); - int DrawDebugTextOverlays(); - void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ); - virtual void Think( void ); - CFourWheelVehiclePhysics *GetPhysics( void ) { return &m_VehiclePhysics; } - CBasePlayer *HasPhysicsAttacker( float dt ); - void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason ); - - Vector GetSmoothedVelocity( void ); //Save and update our smoothed velocity for prediction - - virtual void DampenEyePosition( Vector &vecVehicleEyePos, QAngle &vecVehicleEyeAngles ) {} - - // Inputs - void InputThrottle( inputdata_t &inputdata ); - void InputSteering( inputdata_t &inputdata ); - void InputAction( inputdata_t &inputdata ); - void InputHandBrakeOn( inputdata_t &inputdata ); - void InputHandBrakeOff( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - -#ifdef HL2_EPISODIC - void AddPhysicsChild( CBaseEntity *pChild ); - void RemovePhysicsChild( CBaseEntity *pChild ); -#endif //HL2_EPISODIC - -protected: - // engine sounds - void SoundInit(); - void SoundShutdown(); - void SoundUpdate( const vehicle_operatingparams_t ¶ms, const vehicleparams_t &vehicle ); - void CalcWheelData( vehicleparams_t &vehicle ); - void ResetControls(); - - // Upright strength of the controller (angular limit) - virtual float GetUprightStrength( void ) { return 8.0f; } - virtual float GetUprightTime( void ) { return 5.0f; } - -protected: - CFourWheelVehiclePhysics m_VehiclePhysics; - unsigned int m_nVehicleType; - string_t m_vehicleScript; - -#ifdef HL2_EPISODIC - CUtlVector m_hPhysicsChildren; // List of entities who wish to get physics callbacks from the vehicle -#endif //HL2_EPISODIC - -private: - Vector m_vecSmoothedVelocity; - - CHandle m_hPhysicsAttacker; - - float m_flLastPhysicsInfluenceTime; -}; - -//============================================================================= -// NPC Passenger Carrier interface - -class INPCPassengerCarrier -{ -public: - virtual bool NPC_CanEnterVehicle( CAI_BaseNPC *pPassenger, bool bCompanion ) = 0; - virtual bool NPC_CanExitVehicle( CAI_BaseNPC *pPassenger, bool bCompanion ) = 0; - virtual bool NPC_AddPassenger( CAI_BaseNPC *pPassenger, string_t strRoleName, int nSeatID ) = 0; - virtual bool NPC_RemovePassenger( CAI_BaseNPC *pPassenger ) = 0; - virtual void NPC_FinishedEnterVehicle( CAI_BaseNPC *pPassenger, bool bCompanion ) = 0; - virtual void NPC_FinishedExitVehicle( CAI_BaseNPC *pPassenger, bool bCompanion ) = 0; -}; - -//----------------------------------------------------------------------------- -// Purpose: Drivable four wheel physics vehicles -//----------------------------------------------------------------------------- -class CPropVehicleDriveable : public CPropVehicle, public IDrivableVehicle, public INPCPassengerCarrier -{ - DECLARE_CLASS( CPropVehicleDriveable, CPropVehicle ); - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); -public: - CPropVehicleDriveable( void ); - ~CPropVehicleDriveable( void ); - - virtual void Precache( void ); - virtual void Spawn( void ); - virtual int Restore( IRestore &restore ); - virtual void OnRestore(); - virtual void CreateServerVehicle( void ); - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() | FCAP_IMPULSE_USE; }; - virtual void GetVectors(Vector* pForward, Vector* pRight, Vector* pUp) const; - virtual void VehicleAngleVectors( const QAngle &angles, Vector *pForward, Vector *pRight, Vector *pUp ); - virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - virtual void Think( void ); - virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - virtual void Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info ); - - // Vehicle handling - virtual void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); - virtual int VPhysicsGetObjectList( IPhysicsObject **pList, int listMax ); - - // Inputs - void InputLock( inputdata_t &inputdata ); - void InputUnlock( inputdata_t &inputdata ); - void InputTurnOn( inputdata_t &inputdata ); - void InputTurnOff( inputdata_t &inputdata ); - - // Locals - void ResetUseKey( CBasePlayer *pPlayer ); - - // Driving - void DriveVehicle( CBasePlayer *pPlayer, CUserCmd *ucmd ); // Player driving entrypoint - virtual void DriveVehicle( float flFrameTime, CUserCmd *ucmd, int iButtonsDown, int iButtonsReleased ); // Driving Button handling - - virtual bool IsOverturned( void ); - virtual bool IsVehicleBodyInWater( void ) { return false; } - - // Engine handling - void StartEngine( void ); - void StopEngine( void ); - bool IsEngineOn( void ); - -// IDrivableVehicle -public: - virtual CBaseEntity *GetDriver( void ); - virtual void ItemPostFrame( CBasePlayer *pPlayer ) { return; } - virtual void SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ); - virtual void ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ) { return; } - virtual void FinishMove( CBasePlayer *player, CUserCmd *ucmd, CMoveData *move ) { return; } - virtual bool CanEnterVehicle( CBaseEntity *pEntity ); - virtual bool CanExitVehicle( CBaseEntity *pEntity ); - virtual void SetVehicleEntryAnim( bool bOn ) { m_bEnterAnimOn = bOn; } - virtual void SetVehicleExitAnim( bool bOn, Vector vecEyeExitEndpoint ) { m_bExitAnimOn = bOn; if ( bOn ) m_vecEyeExitEndpoint = vecEyeExitEndpoint; } - virtual void EnterVehicle( CBaseCombatCharacter *pPassenger ); - - virtual bool AllowBlockedExit( CBaseCombatCharacter *pPassenger, int nRole ) { return true; } - virtual bool AllowMidairExit( CBaseCombatCharacter *pPassenger, int nRole ) { return false; } - virtual void PreExitVehicle( CBaseCombatCharacter *pPassenger, int nRole ) {} - virtual void ExitVehicle( int nRole ); - virtual string_t GetVehicleScriptName() { return m_vehicleScript; } - - virtual bool PassengerShouldReceiveDamage( CTakeDamageInfo &info ) { return true; } - - // If this is a vehicle, returns the vehicle interface - virtual IServerVehicle *GetServerVehicle() { return m_pServerVehicle; } - -protected: - - virtual bool ShouldThink() { return ( GetDriver() != NULL ); } - - inline bool HasGun(); - void DestroyServerVehicle(); - - // Contained IServerVehicle - CFourWheelServerVehicle *m_pServerVehicle; - - COutputEvent m_playerOn; - COutputEvent m_playerOff; - - COutputEvent m_pressedAttack; - COutputEvent m_pressedAttack2; - - COutputFloat m_attackaxis; - COutputFloat m_attack2axis; - - CNetworkHandle( CBasePlayer, m_hPlayer ); -public: - - CNetworkVar( int, m_nSpeed ); - CNetworkVar( int, m_nRPM ); - CNetworkVar( float, m_flThrottle ); - CNetworkVar( int, m_nBoostTimeLeft ); - CNetworkVar( int, m_nHasBoost ); - - CNetworkVector( m_vecEyeExitEndpoint ); - CNetworkVector( m_vecGunCrosshair ); - CNetworkVar( bool, m_bUnableToFire ); - CNetworkVar( bool, m_bHasGun ); - - CNetworkVar( bool, m_nScannerDisabledWeapons ); - CNetworkVar( bool, m_nScannerDisabledVehicle ); - - // NPC Driver - CHandle m_hNPCDriver; - EHANDLE m_hKeepUpright; - - // -------------------------------- - // NPC Passengers -public: - - virtual bool NPC_CanEnterVehicle( CAI_BaseNPC *pPassenger, bool bCompanion ); - virtual bool NPC_CanExitVehicle( CAI_BaseNPC *pPassenger, bool bCompanion ); - virtual bool NPC_AddPassenger( CAI_BaseNPC *pPassenger, string_t strRoleName, int nSeatID ); - virtual bool NPC_RemovePassenger( CAI_BaseNPC *pPassenger ); - virtual void NPC_FinishedEnterVehicle( CAI_BaseNPC *pPassenger, bool bCompanion ) {} - virtual void NPC_FinishedExitVehicle( CAI_BaseNPC *pPassenger, bool bCompanion ) {} - - // NPC Passengers - // -------------------------------- - - bool IsEnterAnimOn( void ) { return m_bEnterAnimOn; } - bool IsExitAnimOn( void ) { return m_bExitAnimOn; } - const Vector &GetEyeExitEndpoint( void ) { return m_vecEyeExitEndpoint; } - -protected: - // Entering / Exiting - bool m_bEngineLocked; // Mapmaker override on whether the vehicle's allowed to be turned on/off - bool m_bLocked; - float m_flMinimumSpeedToEnterExit; - CNetworkVar( bool, m_bEnterAnimOn ); - CNetworkVar( bool, m_bExitAnimOn ); - - // Used to turn the keepupright off after a short time - float m_flTurnOffKeepUpright; - float m_flNoImpactDamageTime; -}; - - -inline bool CPropVehicleDriveable::HasGun() -{ - return m_bHasGun; -} - - -#endif // VEHICLE_BASE_H diff --git a/game/server/vehicle_baseserver.cpp b/game/server/vehicle_baseserver.cpp deleted file mode 100644 index 7b77f38db..000000000 --- a/game/server/vehicle_baseserver.cpp +++ /dev/null @@ -1,2754 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "vcollide_parse.h" -#include "vehicle_base.h" -#include "npc_vehicledriver.h" -#include "in_buttons.h" -#include "engine/IEngineSound.h" -#include "soundenvelope.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" -#include "saverestore_utlvector.h" -#include "KeyValues.h" -#include "studio.h" -#include "bone_setup.h" -#include "collisionutils.h" -#include "animation.h" -#include "env_player_surface_trigger.h" -#include "rumble_shared.h" - -#ifdef HL2_DLL - #include "hl2_player.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar g_debug_vehiclesound( "g_debug_vehiclesound", "0", FCVAR_CHEAT ); -ConVar g_debug_vehicleexit( "g_debug_vehicleexit", "0", FCVAR_CHEAT ); - -ConVar sv_vehicle_autoaim_scale("sv_vehicle_autoaim_scale", "8"); - -bool ShouldVehicleIgnoreEntity( CBaseEntity *pVehicle, CBaseEntity *pCollide ); - -#define HITBOX_SET 2 - -//----------------------------------------------------------------------------- -// Save/load -//----------------------------------------------------------------------------- -BEGIN_DATADESC_NO_BASE( vehicle_gear_t ) - - DEFINE_FIELD( flMinSpeed, FIELD_FLOAT ), - DEFINE_FIELD( flMaxSpeed, FIELD_FLOAT ), - DEFINE_FIELD( flSpeedApproachFactor,FIELD_FLOAT ), - -END_DATADESC() - -BEGIN_DATADESC_NO_BASE( vehicle_crashsound_t ) - DEFINE_FIELD( flMinSpeed, FIELD_FLOAT ), - DEFINE_FIELD( flMinDeltaSpeed, FIELD_FLOAT ), - DEFINE_FIELD( iszCrashSound, FIELD_STRING ), - DEFINE_FIELD( gearLimit, FIELD_INTEGER ), -END_DATADESC() - -BEGIN_DATADESC_NO_BASE( vehiclesounds_t ) - - DEFINE_AUTO_ARRAY( iszSound, FIELD_STRING ), - DEFINE_UTLVECTOR( pGears, FIELD_EMBEDDED ), - DEFINE_UTLVECTOR( crashSounds, FIELD_EMBEDDED ), - DEFINE_AUTO_ARRAY( iszStateSounds, FIELD_STRING ), - DEFINE_AUTO_ARRAY( minStateTime, FIELD_FLOAT ), - -END_DATADESC() - -BEGIN_SIMPLE_DATADESC( CPassengerInfo ) - DEFINE_FIELD( m_hPassenger, FIELD_EHANDLE ), - DEFINE_FIELD( m_strRoleName, FIELD_STRING ), - DEFINE_FIELD( m_strSeatName, FIELD_STRING ), - // NOT SAVED - // DEFINE_FIELD( m_nRole, FIELD_INTEGER ), - // DEFINE_FIELD( m_nSeat, FIELD_INTEGER ), -END_DATADESC() - -BEGIN_SIMPLE_DATADESC( CBaseServerVehicle ) - -// These are reset every time by the constructor of the owning class -// DEFINE_FIELD( m_pVehicle, FIELD_CLASSPTR ), -// DEFINE_FIELD( m_pDrivableVehicle; ??? ), - - // Controls - DEFINE_FIELD( m_nNPCButtons, FIELD_INTEGER ), - DEFINE_FIELD( m_nPrevNPCButtons, FIELD_INTEGER ), - DEFINE_FIELD( m_flTurnDegrees, FIELD_FLOAT ), - DEFINE_FIELD( m_flVehicleVolume, FIELD_FLOAT ), - - // We're going to reparse this data from file in Precache - DEFINE_EMBEDDED( m_vehicleSounds ), - - DEFINE_FIELD( m_iSoundGear, FIELD_INTEGER ), - DEFINE_FIELD( m_flSpeedPercentage, FIELD_FLOAT ), - DEFINE_SOUNDPATCH( m_pStateSound ), - DEFINE_SOUNDPATCH( m_pStateSoundFade ), - DEFINE_FIELD( m_soundState, FIELD_INTEGER ), - DEFINE_FIELD( m_soundStateStartTime, FIELD_TIME ), - DEFINE_FIELD( m_lastSpeed, FIELD_FLOAT ), - -// NOT SAVED -// DEFINE_FIELD( m_EntryAnimations, CUtlVector ), -// DEFINE_FIELD( m_ExitAnimations, CUtlVector ), -// DEFINE_FIELD( m_bParsedAnimations, FIELD_BOOLEAN ), -// DEFINE_UTLVECTOR( m_PassengerRoles, FIELD_EMBEDDED ), - - DEFINE_FIELD( m_iCurrentExitAnim, FIELD_INTEGER ), - DEFINE_FIELD( m_vecCurrentExitEndPoint, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_chPreviousTextureType, FIELD_CHARACTER ), - - DEFINE_FIELD( m_savedViewOffset, FIELD_VECTOR ), - DEFINE_FIELD( m_hExitBlocker, FIELD_EHANDLE ), - - DEFINE_UTLVECTOR( m_PassengerInfo, FIELD_EMBEDDED ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: Base class for drivable vehicle handling. Contain it in your -// drivable vehicle. -//----------------------------------------------------------------------------- -CBaseServerVehicle::CBaseServerVehicle( void ) -{ - m_pVehicle = NULL; - m_pDrivableVehicle = NULL; - m_nNPCButtons = 0; - m_nPrevNPCButtons = 0; - m_flTurnDegrees = 0; - - m_bParsedAnimations = false; - m_iCurrentExitAnim = 0; - m_vecCurrentExitEndPoint = vec3_origin; - - m_flVehicleVolume = 0.5; - m_iSoundGear = 0; - m_pStateSound = NULL; - m_pStateSoundFade = NULL; - m_soundState = SS_NONE; - m_flSpeedPercentage = 0; - m_bUseLegacyExitChecks = false; - - m_vehicleSounds.Init(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseServerVehicle::~CBaseServerVehicle( void ) -{ - SoundShutdown(0); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::Precache( void ) -{ - int i; - // Precache our other sounds - for ( i = 0; i < VS_NUM_SOUNDS; i++ ) - { - if ( m_vehicleSounds.iszSound[i] != NULL_STRING ) - { - CBaseEntity::PrecacheScriptSound( STRING(m_vehicleSounds.iszSound[i]) ); - } - } - for ( i = 0; i < m_vehicleSounds.crashSounds.Count(); i++ ) - { - if ( m_vehicleSounds.crashSounds[i].iszCrashSound != NULL_STRING ) - { - CBaseEntity::PrecacheScriptSound( STRING(m_vehicleSounds.crashSounds[i].iszCrashSound) ); - } - } - - for ( i = 0; i < SS_NUM_STATES; i++ ) - { - if ( m_vehicleSounds.iszStateSounds[i] != NULL_STRING ) - { - CBaseEntity::PrecacheScriptSound( STRING(m_vehicleSounds.iszStateSounds[i]) ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Parses the vehicle's script for the vehicle sounds -//----------------------------------------------------------------------------- -bool CBaseServerVehicle::Initialize( const char *pScriptName ) -{ - // Attempt to parse our vehicle script - if ( PhysFindOrAddVehicleScript( pScriptName, NULL, &m_vehicleSounds ) == false ) - return false; - - Precache(); - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::SetVehicle( CBaseEntity *pVehicle ) -{ - m_pVehicle = pVehicle; - m_pDrivableVehicle = dynamic_cast(m_pVehicle); - Assert( m_pDrivableVehicle ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -IDrivableVehicle *CBaseServerVehicle::GetDrivableVehicle( void ) -{ - Assert( m_pDrivableVehicle ); - return m_pDrivableVehicle; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the driver. Unlike GetPassenger(VEHICLE_ROLE_DRIVER), it will return -// the NPC driver if it has one. -//----------------------------------------------------------------------------- -CBaseEntity *CBaseServerVehicle::GetDriver( void ) -{ - return GetPassenger( VEHICLE_ROLE_DRIVER ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseCombatCharacter *CBaseServerVehicle::GetPassenger( int nRole ) -{ - Assert( nRole == VEHICLE_ROLE_DRIVER ); - CBaseEntity *pDriver = GetDrivableVehicle()->GetDriver(); - - if ( pDriver == NULL ) - return NULL; - - return pDriver->MyCombatCharacterPointer(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBaseServerVehicle::GetPassengerRole( CBaseCombatCharacter *pPassenger ) -{ - if ( pPassenger == GetDrivableVehicle()->GetDriver() ) - return VEHICLE_ROLE_DRIVER; - - return VEHICLE_ROLE_NONE; -} - -//----------------------------------------------------------------------------- -// Purpose: Adds a passenger to the vehicle -// Input : nSeat - seat to sit in -// *pPassenger - character to enter -//----------------------------------------------------------------------------- -bool CBaseServerVehicle::NPC_AddPassenger( CBaseCombatCharacter *pPassenger, string_t strRoleName, int nSeat ) -{ - // Players cannot yet use this code! - jdw - Assert( pPassenger != NULL && pPassenger->IsPlayer() == false ); - if ( pPassenger == NULL || pPassenger->IsPlayer() ) - return false; - - // Find our role - int nRole = FindRoleIndexByName( strRoleName ); - if ( nRole == -1 ) - return false; - - // Cannot evict a passenger already in this position - CBaseCombatCharacter *pCurrentPassenger = NPC_GetPassengerInSeat( nRole, nSeat ); - if ( pCurrentPassenger == pPassenger ) - return true; - - // If we weren't the same passenger, we need to be empty - if ( pCurrentPassenger != NULL ) - return false; - - // Find the seat - for ( int i = 0; i < m_PassengerInfo.Count(); i++ ) - { - if ( m_PassengerInfo[i].GetSeat() == nSeat && m_PassengerInfo[i].GetRole() == nRole ) - { - m_PassengerInfo[i].m_hPassenger = pPassenger; - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Removes a passenger from the vehicle -// Input : *pPassenger - Passenger to remove -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseServerVehicle::NPC_RemovePassenger( CBaseCombatCharacter *pPassenger ) -{ - // Players cannot yet use this code! - jdw - Assert( pPassenger != NULL && pPassenger->IsPlayer() == false ); - if ( pPassenger == NULL || pPassenger->IsPlayer() ) - return false; - - // Find the seat - for ( int i = 0; i < m_PassengerInfo.Count(); i++ ) - { - if ( m_PassengerInfo[i].m_hPassenger == pPassenger ) - { - m_PassengerInfo[i].m_hPassenger = NULL; - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the attachment point index for the passenger's seat -// Input : *pPassenger - Passenger in the seat -// Output : int - Attachment point index for the vehicle -//----------------------------------------------------------------------------- -int CBaseServerVehicle::NPC_GetPassengerSeatAttachment( CBaseCombatCharacter *pPassenger ) -{ - // Get the role and seat the the supplied passenger - for ( int i = 0; i < m_PassengerInfo.Count(); i++ ) - { - // If this is the passenger, get the attachment it'll be at - if ( m_PassengerInfo[i].m_hPassenger == pPassenger ) - { - // The seat is the attachment point - int nSeat = m_PassengerInfo[i].GetSeat(); - int nRole = m_PassengerInfo[i].GetRole(); - - return m_PassengerRoles[nRole].m_PassengerSeats[nSeat].GetAttachmentID(); - } - } - - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: Get the worldspace position and angles of the specified seat -// Input : *pPassenger - Passenger's seat to use -//----------------------------------------------------------------------------- -bool CBaseServerVehicle::NPC_GetPassengerSeatPosition( CBaseCombatCharacter *pPassenger, Vector *vecResultPos, QAngle *vecResultAngles ) -{ - // Get our attachment point - int nSeatAttachment = NPC_GetPassengerSeatAttachment( pPassenger ); - if ( nSeatAttachment == -1 ) - return false; - - // Figure out which entrypoint hitbox the player is in - CBaseAnimating *pAnimating = dynamic_cast< CBaseAnimating * >( m_pVehicle ); - if ( pAnimating == NULL ) - return false; - - Vector vecPos; - QAngle vecAngles; - pAnimating->GetAttachment( nSeatAttachment, vecPos, vecAngles ); - - if ( vecResultPos != NULL ) - { - *vecResultPos = vecPos; - } - - if ( vecResultAngles != NULL ) - { - *vecResultAngles = vecAngles; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Get the localspace position and angles of the specified seat -// Input : *pPassenger - Passenger's seat to use -//----------------------------------------------------------------------------- -bool CBaseServerVehicle::NPC_GetPassengerSeatPositionLocal( CBaseCombatCharacter *pPassenger, Vector *vecResultPos, QAngle *vecResultAngles ) -{ - // Get our attachment point - int nSeatAttachment = NPC_GetPassengerSeatAttachment( pPassenger ); - if ( nSeatAttachment == -1 ) - return false; - - // Figure out which entrypoint hitbox the player is in - CBaseAnimating *pAnimating = m_pVehicle->GetBaseAnimating(); - if ( pAnimating == NULL ) - return false; - - Vector vecPos; - QAngle vecAngles; - pAnimating->InvalidateBoneCache(); // NOTE: We're moving with velocity, so we're almost always out of date - pAnimating->GetAttachmentLocal( nSeatAttachment, vecPos, vecAngles ); - - if ( vecResultPos != NULL ) - { - *vecResultPos = vecPos; - } - - if ( vecResultAngles != NULL ) - { - *vecResultAngles = vecAngles; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Retrieves a list of animations used to enter/exit the seat occupied by the passenger -// Input : *pPassenger - Passenger who's seat anims to retrieve -// nType - which set of animations to retrieve -//----------------------------------------------------------------------------- -const PassengerSeatAnims_t *CBaseServerVehicle::NPC_GetPassengerSeatAnims( CBaseCombatCharacter *pPassenger, PassengerSeatAnimType_t nType ) -{ - // Get the role and seat the the supplied passenger - for ( int i = 0; i < m_PassengerInfo.Count(); i++ ) - { - if ( m_PassengerInfo[i].m_hPassenger == pPassenger ) - { - int nSeat = m_PassengerInfo[i].GetSeat(); - int nRole = m_PassengerInfo[i].GetRole(); - switch( nType ) - { - case PASSENGER_SEAT_ENTRY: - return &m_PassengerRoles[nRole].m_PassengerSeats[nSeat].m_EntryTransitions; - break; - - case PASSENGER_SEAT_EXIT: - return &m_PassengerRoles[nRole].m_PassengerSeats[nSeat].m_ExitTransitions; - break; - - default: - return NULL; - break; - } - } - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Get and set the current driver. Use PassengerRole_t enum in shareddefs.h for adding passengers -//----------------------------------------------------------------------------- -void CBaseServerVehicle::SetPassenger( int nRole, CBaseCombatCharacter *pPassenger ) -{ - // Baseclass only handles vehicles with a single passenger - Assert( nRole == VEHICLE_ROLE_DRIVER ); - - if ( pPassenger != NULL && pPassenger->IsPlayer() == false ) - { - // Use NPC_AddPassenger() for NPCs at the moment, these will all be collapsed into one system -- jdw - Assert( 0 ); - return; - } - - // Getting in? or out? - if ( pPassenger != NULL ) - { - CBasePlayer *pPlayer = ToBasePlayer( pPassenger ); - if ( pPlayer != NULL ) - { - m_savedViewOffset = pPlayer->GetViewOffset(); - pPlayer->SetViewOffset( vec3_origin ); - pPlayer->ShowCrosshair( false ); - - GetDrivableVehicle()->EnterVehicle( pPassenger ); - -#ifdef HL2_DLL - // Stop the player sprint and flashlight. - CHL2_Player *pHL2Player = dynamic_cast( pPlayer ); - if ( pHL2Player ) - { - if ( pHL2Player->IsSprinting() ) - { - pHL2Player->StopSprinting(); - } - - if ( pHL2Player->FlashlightIsOn() ) - { - pHL2Player->FlashlightTurnOff(); - } - } -#endif - } - } - else - { - CBasePlayer *pPlayer = ToBasePlayer( GetDriver() ); - if ( pPlayer ) - { - // Restore the exiting player's view offset - pPlayer->SetViewOffset( m_savedViewOffset ); - pPlayer->ShowCrosshair( true ); - } - - GetDrivableVehicle()->ExitVehicle( nRole ); - GetDrivableVehicle()->SetVehicleEntryAnim( false ); - UTIL_Remove( m_hExitBlocker ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Get a position in *world space* inside the vehicle for the player to start at -//----------------------------------------------------------------------------- -void CBaseServerVehicle::GetPassengerSeatPoint( int nRole, Vector *pPoint, QAngle *pAngles ) -{ - Assert( nRole == VEHICLE_ROLE_DRIVER ); - - CBaseAnimating *pAnimating = dynamic_cast(m_pVehicle); - if ( pAnimating ) - { - char pAttachmentName[32]; - Q_snprintf( pAttachmentName, sizeof( pAttachmentName ), "vehicle_feet_passenger%d", nRole ); - int nFeetAttachmentIndex = pAnimating->LookupAttachment(pAttachmentName); - int nIdleSequence = pAnimating->SelectWeightedSequence( ACT_IDLE ); - if ( nFeetAttachmentIndex > 0 && nIdleSequence != -1 ) - { - // FIXME: This really wants to be a faster query than this implementation! - Vector vecOrigin; - QAngle vecAngles; - if ( GetLocalAttachmentAtTime( nIdleSequence, nFeetAttachmentIndex, 0.0f, &vecOrigin, &vecAngles ) ) - { - UTIL_ParentToWorldSpace( pAnimating, vecOrigin, vecAngles ); - if ( pPoint ) - { - *pPoint = vecOrigin; - } - - if ( pAngles ) - { - *pAngles = vecAngles; - } - - return; - } - } - } - - // Couldn't find the attachment point, so just use the origin - if ( pPoint ) - { - *pPoint = m_pVehicle->GetAbsOrigin(); - } - - if ( pAngles ) - { - *pAngles = m_pVehicle->GetAbsAngles(); - } -} - -//--------------------------------------------------------------------------------- -// Check Exit Point for leaving vehicle. -// -// Input: yaw/roll from vehicle angle to check for exit -// distance from origin to drop player (allows for different shaped vehicles -// Output: returns true if valid location, pEndPoint -// updated with actual exit point -//--------------------------------------------------------------------------------- -bool CBaseServerVehicle::CheckExitPoint( float yaw, int distance, Vector *pEndPoint ) -{ - QAngle vehicleAngles = m_pVehicle->GetLocalAngles(); - Vector vecStart = m_pVehicle->GetAbsOrigin(); - Vector vecDir; - - vecStart.z += 12; // always 12" from ground - vehicleAngles[YAW] += yaw; - AngleVectors( vehicleAngles, NULL, &vecDir, NULL ); - // Vehicles are oriented along the Y axis - vecDir *= -1; - *pEndPoint = vecStart + vecDir * distance; - - trace_t tr; - UTIL_TraceHull( vecStart, *pEndPoint, VEC_HULL_MIN, VEC_HULL_MAX, MASK_PLAYERSOLID, m_pVehicle, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction < 1.0 ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Where does this passenger exit the vehicle? -//----------------------------------------------------------------------------- -bool CBaseServerVehicle::GetPassengerExitPoint( int nRole, Vector *pExitPoint, QAngle *pAngles ) -{ - Assert( nRole == VEHICLE_ROLE_DRIVER ); - - // First, see if we've got an attachment point - CBaseAnimating *pAnimating = dynamic_cast(m_pVehicle); - if ( pAnimating ) - { - Vector vehicleExitOrigin; - QAngle vehicleExitAngles; - if ( pAnimating->GetAttachment( "vehicle_driver_exit", vehicleExitOrigin, vehicleExitAngles ) ) - { - // Make sure it's clear - trace_t tr; - UTIL_TraceHull( vehicleExitOrigin + Vector(0, 0, 12), vehicleExitOrigin, VEC_HULL_MIN, VEC_HULL_MAX, MASK_PLAYERSOLID, m_pVehicle, COLLISION_GROUP_NONE, &tr ); - if ( !tr.startsolid ) - { - *pAngles = vehicleExitAngles; - *pExitPoint = tr.endpos; - return true; - } - } - } - - // left side - if( CheckExitPoint( 90, 90, pExitPoint ) ) // angle from car, distance from origin, actual exit point - return true; - - // right side - if( CheckExitPoint( -90, 90, pExitPoint ) ) - return true; - - // front - if( CheckExitPoint( 0, 100, pExitPoint ) ) - return true; - - // back - if( CheckExitPoint( 180, 170, pExitPoint ) ) - return true; - - // All else failed, try popping them out the top. - Vector vecWorldMins, vecWorldMaxs; - m_pVehicle->CollisionProp()->WorldSpaceAABB( &vecWorldMins, &vecWorldMaxs ); - pExitPoint->x = (vecWorldMins.x + vecWorldMaxs.x) * 0.5f; - pExitPoint->y = (vecWorldMins.y + vecWorldMaxs.y) * 0.5f; - pExitPoint->z = vecWorldMaxs.z + 50.0f; - - // Make sure it's clear - trace_t tr; - UTIL_TraceHull( m_pVehicle->CollisionProp()->WorldSpaceCenter(), *pExitPoint, VEC_HULL_MIN, VEC_HULL_MAX, MASK_PLAYERSOLID, m_pVehicle, COLLISION_GROUP_NONE, &tr ); - if ( !tr.startsolid ) - { - return true; - } - - // No clear exit point available! - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::ParseExitAnim( KeyValues *pkvExitList, bool bEscapeExit ) -{ - // Look through the entry animations list - KeyValues *pkvExitAnim = pkvExitList->GetFirstSubKey(); - while ( pkvExitAnim ) - { - // Add 'em to our list - int iIndex = m_ExitAnimations.AddToTail(); - Q_strncpy( m_ExitAnimations[iIndex].szAnimName, pkvExitAnim->GetName(), sizeof(m_ExitAnimations[iIndex].szAnimName) ); - m_ExitAnimations[iIndex].bEscapeExit = bEscapeExit; - if ( !Q_strncmp( pkvExitAnim->GetString(), "upsidedown", 10 ) ) - { - m_ExitAnimations[iIndex].bUpright = false; - } - else - { - m_ExitAnimations[iIndex].bUpright = true; - } - - pkvExitAnim = pkvExitAnim->GetNextKey(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Parse the transition information -// Input : *pTransitionKeyValues - key values to parse -//----------------------------------------------------------------------------- -void CBaseServerVehicle::ParseNPCSeatTransition( KeyValues *pTransitionKeyValues, CPassengerSeatTransition *pTransition ) -{ - // Store it - const char *lpszAnimName = pTransitionKeyValues->GetString( "animation" ); - pTransition->m_strAnimationName = AllocPooledString( lpszAnimName ); - pTransition->m_nPriority = pTransitionKeyValues->GetInt( "priority" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Sorting function for vehicle seat animation priorities -//----------------------------------------------------------------------------- -typedef CPassengerSeatTransition SortSeatPriorityType; -int __cdecl SeatPrioritySort( const SortSeatPriorityType *s1, const SortSeatPriorityType *s2 ) -{ - return ( s1->GetPriority() > s2->GetPriority() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Parse one set of entry/exit data -// Input : *pSetKeyValues - Key values for this set -//----------------------------------------------------------------------------- -void CBaseServerVehicle::ParseNPCPassengerSeat( KeyValues *pSetKeyValues, CPassengerSeat *pSeat ) -{ - CBaseAnimating *pAnimating = (CBaseAnimating *) m_pVehicle; - - // Get our attachment name - const char *lpszAttachmentName = pSetKeyValues->GetString( "target_attachment" ); - int nAttachmentID = pAnimating->LookupAttachment( lpszAttachmentName ); - pSeat->m_nAttachmentID = nAttachmentID; - pSeat->m_strSeatName = AllocPooledString( lpszAttachmentName ); - - KeyValues *pKey = pSetKeyValues->GetFirstSubKey(); - while ( pKey != NULL ) - { - const char *lpszName = pKey->GetName(); - - if ( Q_stricmp( lpszName, "entry" ) == 0 ) - { - int nIndex = pSeat->m_EntryTransitions.AddToTail(); - Assert( pSeat->m_EntryTransitions.IsValidIndex( nIndex ) ); - - ParseNPCSeatTransition( pKey, &pSeat->m_EntryTransitions[nIndex] ); - } - else if ( Q_stricmp( lpszName, "exit" ) == 0 ) - { - int nIndex = pSeat->m_ExitTransitions.AddToTail(); - Assert( pSeat->m_ExitTransitions.IsValidIndex( nIndex ) ); - - ParseNPCSeatTransition( pKey, &pSeat->m_ExitTransitions[nIndex] ); - } - - // Advance - pKey = pKey->GetNextKey(); - } - - // Sort the seats based on their priority - pSeat->m_EntryTransitions.Sort( SeatPrioritySort ); - pSeat->m_ExitTransitions.Sort( SeatPrioritySort ); -} - -//----------------------------------------------------------------------------- -// Purpose: Find a passenger role (by name), or create a new one of that names -// Input : strName - name of the role -// : *nIndex - the index into the CUtlBuffer where this role resides -// Output : CPassengerRole * - Role found or created -//----------------------------------------------------------------------------- -CPassengerRole *CBaseServerVehicle::FindOrCreatePassengerRole( string_t strName, int *nIndex ) -{ - // Try to find an already created container of the same name - for ( int i = 0; i < m_PassengerRoles.Count(); i++ ) - { - // If we match, return it - if ( FStrEq( STRING( m_PassengerRoles[i].m_strName ), STRING( strName ) ) ) - { - // Supply the index, if requested - if ( nIndex != NULL ) - { - *nIndex = i; - } - - return &m_PassengerRoles[i]; - } - } - - // Create a new container - int nNewIndex = m_PassengerRoles.AddToTail(); - Assert( m_PassengerRoles.IsValidIndex( nNewIndex ) ); - - m_PassengerRoles[nNewIndex].m_strName = strName; - - // Supply the index, if requested - if ( nIndex != NULL ) - { - *nIndex = nNewIndex; - } - - return &m_PassengerRoles[nNewIndex]; -} - -ConVar g_debug_npc_vehicle_roles( "g_debug_npc_vehicle_roles", "0" ); - -//----------------------------------------------------------------------------- -// Purpose: Parse NPC entry and exit anim data -// Input : *pModelKeyValues - Key values from the vehicle model -//----------------------------------------------------------------------------- -void CBaseServerVehicle::ParseNPCRoles( KeyValues *pkvPassengerList ) -{ - // Get the definition section - if ( pkvPassengerList == NULL ) - return; - - // Get our animating class - CBaseAnimating *pAnimating = dynamic_cast(m_pVehicle); - Assert( pAnimating != NULL ); - if ( pAnimating == NULL ) - return; - - // For attachment polling - CStudioHdr *pStudioHdr = pAnimating->GetModelPtr(); - Assert( pStudioHdr != NULL ); - if ( pStudioHdr == NULL ) - return; - - // Parse all subkeys - int nRoleIndex; - KeyValues *pkvPassengerKey = pkvPassengerList->GetFirstSubKey(); - while ( pkvPassengerKey != NULL ) - { - string_t strRoleName = AllocPooledString( pkvPassengerKey->GetName() ); - - // Find or create the container - CPassengerRole *pRole = FindOrCreatePassengerRole( strRoleName, &nRoleIndex ); - if ( pRole == NULL ) - continue; - - // Add a new role - int nSeatIndex = pRole->m_PassengerSeats.AddToTail(); - Assert( pRole->m_PassengerSeats.IsValidIndex( nSeatIndex ) ); - - // Parse the information - ParseNPCPassengerSeat( pkvPassengerKey, &pRole->m_PassengerSeats[nSeatIndex] ); - - // Add a matching entry into our passenger manifest - int nPassengerIndex = m_PassengerInfo.AddToTail(); - m_PassengerInfo[nPassengerIndex].m_hPassenger = NULL; - m_PassengerInfo[nPassengerIndex].m_nSeat = nSeatIndex; - m_PassengerInfo[nPassengerIndex].m_nRole = nRoleIndex; - - // The following are used for index fix-ups after save game restoration - m_PassengerInfo[nPassengerIndex].m_strRoleName = strRoleName; - m_PassengerInfo[nPassengerIndex].m_strSeatName = pRole->m_PassengerSeats[nSeatIndex].m_strSeatName; - - // Advance to the next key - pkvPassengerKey = pkvPassengerKey->GetNextKey(); - } - - // ====================================================================================================== - // Debug print - - if ( g_debug_npc_vehicle_roles.GetBool() ) - { - Msg("Passenger Roles Parsed:\t%d\n\n", m_PassengerRoles.Count() ); - for ( int i = 0; i < m_PassengerRoles.Count(); i++ ) - { - Msg("\tPassenger Role:\t%s (%d seats)\n", STRING(m_PassengerRoles[i].m_strName), m_PassengerRoles[i].m_PassengerSeats.Count() ); - - // Iterate through all information sets under this name - for ( int j = 0; j < m_PassengerRoles[i].m_PassengerSeats.Count(); j++ ) - { - Msg("\t\tAttachment: %d\n", m_PassengerRoles[i].m_PassengerSeats[j].m_nAttachmentID ); - - // Entries - Msg("\t\tEntries:\t%d\n", m_PassengerRoles[i].m_PassengerSeats[j].m_EntryTransitions.Count() ); - Msg("\t\t=====================\n" ); - - for ( int nEntry = 0; nEntry < m_PassengerRoles[i].m_PassengerSeats[j].m_EntryTransitions.Count(); nEntry++ ) - { - Msg("\t\t\tAnimation:\t%s\t(Priority %d)\n", STRING(m_PassengerRoles[i].m_PassengerSeats[j].m_EntryTransitions[nEntry].m_strAnimationName), - m_PassengerRoles[i].m_PassengerSeats[j].m_EntryTransitions[nEntry].m_nPriority ); - } - - Msg("\n"); - - // Exits - Msg("\t\tExits:\t%d\n", m_PassengerRoles[i].m_PassengerSeats[j].m_ExitTransitions.Count() ); - Msg("\t\t=====================\n" ); - - for ( int nExits = 0; nExits < m_PassengerRoles[i].m_PassengerSeats[j].m_ExitTransitions.Count(); nExits++ ) - { - Msg("\t\t\tAnimation:\t%s\t(Priority %d)\n", STRING(m_PassengerRoles[i].m_PassengerSeats[j].m_ExitTransitions[nExits].m_strAnimationName), - m_PassengerRoles[i].m_PassengerSeats[j].m_ExitTransitions[nExits].m_nPriority ); - } - } - - Msg("\n"); - } - } - - // ====================================================================================================== -} -//----------------------------------------------------------------------------- -// Purpose: Get an attachment point at a specified time in its cycle (note: not exactly a speedy query, use sparingly!) -// Input : nSequence - sequence to test -// nAttachmentIndex - attachment to test -// flCyclePoint - 0.0 - 1.0 -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseServerVehicle::GetLocalAttachmentAtTime( int nQuerySequence, int nAttachmentIndex, float flCyclePoint, Vector *vecOriginOut, QAngle *vecAnglesOut ) -{ - CBaseAnimating *pAnimating = m_pVehicle->GetBaseAnimating(); - if ( pAnimating == NULL ) - return false; - - // TODO: It's annoying to stomp and restore this off each time when we're just going to stomp it again later, but the function - // should really leave the car in an acceptable state to run this query -- jdw - - // Store this off for restoration later - int nOldSequence = pAnimating->GetSequence(); - float flOldCycle = pAnimating->GetCycle(); - - // Setup the model for the query - pAnimating->SetSequence( nQuerySequence ); - pAnimating->SetCycle( flCyclePoint ); - pAnimating->InvalidateBoneCache(); - - // Query for the point - Vector vecOrigin; - QAngle vecAngles; - pAnimating->GetAttachmentLocal( nAttachmentIndex, vecOrigin, vecAngles ); - - if ( vecOriginOut != NULL ) - { - *vecOriginOut = vecOrigin; - } - - if ( vecAnglesOut != NULL ) - { - *vecAnglesOut = vecAngles; - } - - // Restore the model after the query - pAnimating->SetSequence( nOldSequence ); - pAnimating->SetCycle( flOldCycle ); - pAnimating->InvalidateBoneCache(); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Get an attachment point at a specified time in its cycle (note: not exactly a speedy query, use sparingly!) -// Input : lpszAnimName - name of the sequence to test -// nAttachmentIndex - attachment to test -// flCyclePoint - 0.0 - 1.0 -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseServerVehicle::GetLocalAttachmentAtTime( const char *lpszAnimName, int nAttachmentIndex, float flCyclePoint, Vector *vecOriginOut, QAngle *vecAnglesOut ) -{ - CBaseAnimating *pAnimating = m_pVehicle->GetBaseAnimating(); - if ( pAnimating == NULL ) - return false; - - int nQuerySequence = pAnimating->LookupSequence( lpszAnimName ); - if ( nQuerySequence < 0 ) - return false; - - return GetLocalAttachmentAtTime( nQuerySequence, nAttachmentIndex, flCyclePoint, vecOriginOut, vecAnglesOut ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::CacheEntryExitPoints( void ) -{ - CBaseAnimating *pAnimating = m_pVehicle->GetBaseAnimating(); - if ( pAnimating == NULL ) - return; - - int nAttachment = pAnimating->LookupAttachment( "vehicle_driver_eyes" ); - - // For each exit animation, determine where the end point is and cache it - for ( int i = 0; i < m_ExitAnimations.Count(); i++ ) - { - if ( GetLocalAttachmentAtTime( m_ExitAnimations[i].szAnimName, nAttachment, 1.0f, &m_ExitAnimations[i].vecExitPointLocal, &m_ExitAnimations[i].vecExitAnglesLocal ) == false ) - { - Warning("Exit animation %s failed to cache target points properly!\n", m_ExitAnimations[i].szAnimName ); - } - - if ( g_debug_vehicleexit.GetBool() ) - { - Vector vecExitPoint = m_ExitAnimations[i].vecExitPointLocal; - QAngle vecExitAngles = m_ExitAnimations[i].vecExitAnglesLocal; - UTIL_ParentToWorldSpace( pAnimating, vecExitPoint, vecExitAngles ); - - NDebugOverlay::Box( vecExitPoint, -Vector(8,8,8), Vector(8,8,8), 0, 255, 0, 0, 20.0f ); - NDebugOverlay::Axis( vecExitPoint, vecExitAngles, 8.0f, true, 20.0f ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::ParseEntryExitAnims( void ) -{ - // Try and find the right animation to play in the model's keyvalues - KeyValues *modelKeyValues = new KeyValues(""); - if ( modelKeyValues->LoadFromBuffer( modelinfo->GetModelName( m_pVehicle->GetModel() ), modelinfo->GetModelKeyValueText( m_pVehicle->GetModel() ) ) ) - { - // Do we have an entry section? - KeyValues *pkvEntryList = modelKeyValues->FindKey("vehicle_entry"); - if ( pkvEntryList ) - { - // Look through the entry animations list - KeyValues *pkvEntryAnim = pkvEntryList->GetFirstSubKey(); - while ( pkvEntryAnim ) - { - // Add 'em to our list - int iIndex = m_EntryAnimations.AddToTail(); - Q_strncpy( m_EntryAnimations[iIndex].szAnimName, pkvEntryAnim->GetName(), sizeof(m_EntryAnimations[iIndex].szAnimName) ); - m_EntryAnimations[iIndex].iHitboxGroup = pkvEntryAnim->GetInt(); - - pkvEntryAnim = pkvEntryAnim->GetNextKey(); - } - } - - // Do we have an exit section? - KeyValues *pkvExitList = modelKeyValues->FindKey("vehicle_exit"); - if ( pkvExitList ) - { - ParseExitAnim( pkvExitList, false ); - } - - // Do we have an exit section? - pkvExitList = modelKeyValues->FindKey("vehicle_escape_exit"); - if ( pkvExitList ) - { - ParseExitAnim( pkvExitList, true ); - } - - // Parse the NPC vehicle roles as well - KeyValues *pkvPassengerList = modelKeyValues->FindKey( "vehicle_npc_passengers" ); - if ( pkvPassengerList ) - { - ParseNPCRoles( pkvPassengerList ); - } - } - - modelKeyValues->deleteThis(); - - // Determine the entry and exit points for the - CacheEntryExitPoints(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::HandlePassengerEntry( CBaseCombatCharacter *pPassenger, bool bAllowEntryOutsideZone ) -{ - CBasePlayer *pPlayer = ToBasePlayer( pPassenger ); - if ( pPlayer != NULL ) - { - // Find out which hitbox the player's eyepoint is within - int iEntryAnim = GetEntryAnimForPoint( pPlayer->EyePosition() ); - - // Get this interface for animation queries - CBaseAnimating *pAnimating = dynamic_cast(m_pVehicle); - if ( !pAnimating ) - return; - - // Are we in an entrypoint zone? - if ( iEntryAnim == ACTIVITY_NOT_AVAILABLE ) - { - // Normal get in refuses to allow entry - if ( !bAllowEntryOutsideZone ) - return; - - // We failed to find a valid entry anim, but we've got to get back in because the player's - // got stuck exiting the vehicle. For now, just use the first get in anim - // UNDONE: We need a better solution for this. - iEntryAnim = pAnimating->LookupSequence( m_EntryAnimations[0].szAnimName ); - } - - // Check to see if this vehicle can be controlled or if it's locked - if ( GetDrivableVehicle()->CanEnterVehicle( pPlayer ) ) - { - // Make sure the passenger can get in as well - if ( pPlayer->CanEnterVehicle( this, VEHICLE_ROLE_DRIVER ) ) - { - // Setup the "enter" vehicle sequence and skip the animation if it isn't present. - pAnimating->SetCycle( 0 ); - pAnimating->m_flAnimTime = gpGlobals->curtime; - pAnimating->ResetSequence( iEntryAnim ); - pAnimating->ResetClientsideFrame(); - pAnimating->InvalidateBoneCache(); // This is necessary because we need to query attachment points this frame for blending! - GetDrivableVehicle()->SetVehicleEntryAnim( true ); - - pPlayer->GetInVehicle( this, VEHICLE_ROLE_DRIVER ); - } - } - } - else - { - // NPCs handle transitioning themselves, they should NOT call this function - Assert( 0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseServerVehicle::HandlePassengerExit( CBaseCombatCharacter *pPassenger ) -{ - CBasePlayer *pPlayer = ToBasePlayer( pPassenger ); - if ( pPlayer != NULL ) - { - // Clear hud hints - UTIL_HudHintText( pPlayer, "" ); - - vbs_sound_update_t params; - InitSoundParams(params); - params.bExitVehicle = true; - SoundState_Update( params ); - - // Find the right exit anim to use based on available exit points. - Vector vecExitPoint; - bool bAllPointsBlocked; - int iSequence = GetExitAnimToUse( vecExitPoint, bAllPointsBlocked ); - - // If all exit points were blocked and this vehicle doesn't allow exiting in - // these cases, bail. - Vector vecNewPos = pPlayer->GetAbsOrigin(); - QAngle angNewAngles = pPlayer->GetAbsAngles(); - - int nRole = GetPassengerRole( pPlayer ); - if ( ( bAllPointsBlocked ) || ( iSequence == ACTIVITY_NOT_AVAILABLE ) ) - { - // Animation-driven exit points are all blocked, or we have none. Fall back to the more simple static exit points. - if ( !GetPassengerExitPoint( nRole, &vecNewPos, &angNewAngles ) && !GetDrivableVehicle()->AllowBlockedExit( pPlayer, nRole ) ) - return false; - - // At this point, the player has exited the vehicle but did so without playing an animation. We need to give the vehicle a - // chance to do any post-animation clean-up it may need to perform. - HandleEntryExitFinish( false, true ); - } - - // Now we either have an exit sequence to play, a valid static exit position, or we don't care - // whether we're blocked or not. We're getting out, one way or another. - GetDrivableVehicle()->PreExitVehicle( pPlayer, nRole ); - - if ( iSequence > ACTIVITY_NOT_AVAILABLE ) - { - CBaseAnimating *pAnimating = dynamic_cast(m_pVehicle); - if ( pAnimating ) - { - pAnimating->SetCycle( 0 ); - pAnimating->m_flAnimTime = gpGlobals->curtime; - pAnimating->ResetSequence( iSequence ); - pAnimating->ResetClientsideFrame(); - GetDrivableVehicle()->SetVehicleExitAnim( true, vecExitPoint ); - - // Re-deploy our weapon - if ( pPlayer && pPlayer->IsAlive() ) - { - if ( pPlayer->GetActiveWeapon() ) - { - pPlayer->GetActiveWeapon()->Deploy(); - pPlayer->ShowCrosshair( true ); - } - } - - // To prevent anything moving into the volume the player's going to occupy at the end of the exit - // NOTE: Set the player as the blocker's owner so the player is allowed to intersect it - Vector vecExitFeetPoint = vecExitPoint - VEC_VIEW; - m_hExitBlocker = CEntityBlocker::Create( vecExitFeetPoint, VEC_HULL_MIN, VEC_HULL_MAX, pPlayer, true ); - - // We may as well stand where we're going to get out at and stop being parented - pPlayer->SetAbsOrigin( vecExitFeetPoint ); - pPlayer->SetParent( NULL ); - - return true; - } - } - - // Couldn't find an animation, so exit immediately - pPlayer->LeaveVehicle( vecNewPos, angNewAngles ); - return true; - } - else - { - // NPCs handle transitioning themselves, they should NOT call this function - Assert( 0 ); - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBaseServerVehicle::GetEntryAnimForPoint( const Vector &vecEyePoint ) -{ - // Parse the vehicle animations the first time they get in the vehicle - if ( !m_bParsedAnimations ) - { - // Load the entry/exit animations from the vehicle - ParseEntryExitAnims(); - m_bParsedAnimations = true; - } - - // No entry anims? Vehicles with no entry anims are always enterable. - if ( !m_EntryAnimations.Count() ) - return 0; - - // Figure out which entrypoint hitbox the player is in - CBaseAnimating *pAnimating = dynamic_cast(m_pVehicle); - if ( !pAnimating ) - return 0; - - CStudioHdr *pStudioHdr = pAnimating->GetModelPtr(); - if (!pStudioHdr) - return 0; - int iHitboxSet = FindHitboxSetByName( pStudioHdr, "entryboxes" ); - mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( iHitboxSet ); - if ( !set || !set->numhitboxes ) - return 0; - - // Loop through the hitboxes and find out which one we're in - for ( int i = 0; i < set->numhitboxes; i++ ) - { - mstudiobbox_t *pbox = set->pHitbox( i ); - - Vector vecPosition; - QAngle vecAngles; - pAnimating->GetBonePosition( pbox->bone, vecPosition, vecAngles ); - - // Build a rotation matrix from orientation - matrix3x4_t fRotateMatrix; - AngleMatrix( vecAngles, vecPosition, fRotateMatrix); - - Vector localEyePoint; - VectorITransform( vecEyePoint, fRotateMatrix, localEyePoint ); - if ( IsPointInBox( localEyePoint, pbox->bbmin, pbox->bbmax ) ) - { - // Find the entry animation for this hitbox - int iCount = m_EntryAnimations.Count(); - for ( int entry = 0; entry < iCount; entry++ ) - { - if ( m_EntryAnimations[entry].iHitboxGroup == pbox->group ) - { - // Get the sequence for the animation - return pAnimating->LookupSequence( m_EntryAnimations[entry].szAnimName ); - } - } - } - } - - // Fail - return ACTIVITY_NOT_AVAILABLE; -} - -//----------------------------------------------------------------------------- -// Purpose: Find an exit animation that'll get the player to a valid position -// Input : vecEyeExitEndpoint - Returns with the final eye position after exiting. -// bAllPointsBlocked - Returns whether all exit points were found to be blocked. -// Output : -//----------------------------------------------------------------------------- -int CBaseServerVehicle::GetExitAnimToUse( Vector &vecEyeExitEndpoint, bool &bAllPointsBlocked ) -{ - bAllPointsBlocked = false; - - // Parse the vehicle animations the first time they get in the vehicle - if ( !m_bParsedAnimations ) - { - // Load the entry/exit animations from the vehicle - ParseEntryExitAnims(); - m_bParsedAnimations = true; - } - - // No exit anims? - if ( !m_ExitAnimations.Count() ) - return ACTIVITY_NOT_AVAILABLE; - - // Figure out which entrypoint hitbox the player is in - CBaseAnimating *pAnimating = dynamic_cast(m_pVehicle); - if ( !pAnimating ) - return ACTIVITY_NOT_AVAILABLE; - - CStudioHdr *pStudioHdr = pAnimating->GetModelPtr(); - if (!pStudioHdr) - return ACTIVITY_NOT_AVAILABLE; - - bool bUpright = IsVehicleUpright(); - - // Loop through the exit animations and find one that ends in a clear position - // Also attempt to choose the animation which brings you closest to your view direction. - CBasePlayer *pPlayer = ToBasePlayer( GetDriver() ); - if ( pPlayer == NULL ) - return ACTIVITY_NOT_AVAILABLE; - - int nRole = GetPassengerRole( pPlayer ); - - int nBestExitAnim = -1; - bool bBestExitIsEscapePoint = true; - Vector vecViewDirection, vecViewOrigin, vecBestExitPoint( 0, 0, 0 ); - vecViewOrigin = pPlayer->EyePosition(); - pPlayer->EyeVectors( &vecViewDirection ); - vecViewDirection.z = 0.0f; - VectorNormalize( vecViewDirection ); - - float flMaxCosAngleDelta = -2.0f; - - int iCount = m_ExitAnimations.Count(); - for ( int i = 0; i < iCount; i++ ) - { - if ( m_ExitAnimations[i].bUpright != bUpright ) - continue; - - // Don't use an escape point if we found a non-escape point already - if ( !bBestExitIsEscapePoint && m_ExitAnimations[i].bEscapeExit ) - continue; - - Vector vehicleExitOrigin; - QAngle vehicleExitAngles; - - // NOTE: HL2 and Ep1 used a method that relied on the animators to place attachment points in the model which marked where - // the player would exit to. This was rendered unnecessary in Ep2, but the choreo vehicles of these older products - // did not have proper exit animations and relied on the exact queries that were happening before. For choreo vehicles, - // we now just allow them to perform those older queries to keep those products happy. - jdw - - // Get the position we think we're going to end up at - if ( m_bUseLegacyExitChecks ) - { - pAnimating->GetAttachment( m_ExitAnimations[i].szAnimName, vehicleExitOrigin, vehicleExitAngles ); - } - else - { - vehicleExitOrigin = m_ExitAnimations[i].vecExitPointLocal; - vehicleExitAngles = m_ExitAnimations[i].vecExitAnglesLocal; - UTIL_ParentToWorldSpace( pAnimating, vehicleExitOrigin, vehicleExitAngles ); - } - - // Don't bother checking points which are farther from our view direction. - Vector vecDelta; - VectorSubtract( vehicleExitOrigin, vecViewOrigin, vecDelta ); - vecDelta.z = 0.0f; - VectorNormalize( vecDelta ); - float flCosAngleDelta = DotProduct( vecDelta, vecViewDirection ); - - // But always check non-escape exits if our current best exit is an escape exit. - if ( !bBestExitIsEscapePoint || m_ExitAnimations[i].bEscapeExit ) - { - if ( flCosAngleDelta < flMaxCosAngleDelta ) - continue; - } - - // The attachment points are where the driver's eyes will end up, so we subtract the view offset - // to get the actual exit position. - vehicleExitOrigin -= VEC_VIEW; - - Vector vecMove(0,0,64); - Vector vecStart = vehicleExitOrigin + vecMove; - Vector vecEnd = vehicleExitOrigin - vecMove; - - // Starting at the exit point, trace a flat plane down until we hit ground - // NOTE: The hull has no vertical span because we want to test the lateral constraints against the ground, not height (yet) - trace_t tr; - UTIL_TraceHull( vecStart, vecEnd, VEC_HULL_MIN, Vector( VEC_HULL_MAX.x, VEC_HULL_MAX.y, VEC_HULL_MIN.z ), MASK_PLAYERSOLID, NULL, COLLISION_GROUP_NONE, &tr ); - - if ( g_debug_vehicleexit.GetBool() ) - { - NDebugOverlay::SweptBox( vecStart, vecEnd, VEC_HULL_MIN, Vector( VEC_HULL_MAX.x, VEC_HULL_MAX.y, VEC_HULL_MIN.y ), vec3_angle, 255, 255, 255, 8, 20.0f ); - } - - if ( tr.fraction < 1.0f ) - { - // If we hit the ground, try to now "stand up" at that point to see if we'll fit - UTIL_TraceHull( tr.endpos, tr.endpos, VEC_HULL_MIN, VEC_HULL_MAX, MASK_PLAYERSOLID, NULL, COLLISION_GROUP_NONE, &tr ); - - // See if we're unable to stand at this space - if ( tr.startsolid ) - { - if ( g_debug_vehicleexit.GetBool() ) - { - NDebugOverlay::Box( tr.endpos, VEC_HULL_MIN, VEC_HULL_MAX, 255, 0, 0, 8, 20.0f ); - } - continue; - } - - if ( g_debug_vehicleexit.GetBool() ) - { - NDebugOverlay::Box( tr.endpos, VEC_HULL_MIN, VEC_HULL_MAX, 0, 255, 0, 8, 20.0f ); - } - } - else if ( tr.allsolid || ( ( tr.fraction == 1.0 ) && !GetDrivableVehicle()->AllowMidairExit( pPlayer, nRole ) ) ) - { - if ( g_debug_vehicleexit.GetBool() ) - { - NDebugOverlay::Box( tr.endpos, VEC_HULL_MIN, VEC_HULL_MAX, 255,0,0, 64, 10 ); - } - continue; - } - - // Calculate the exit endpoint & viewpoint - Vector vecExitEndPoint = tr.endpos; - - // Make sure we can trace to the center of the exit point - UTIL_TraceLine( vecViewOrigin, vecExitEndPoint, MASK_PLAYERSOLID, pAnimating, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction != 1.0 ) - { -#ifdef HL2_EPISODIC - if ( ShouldVehicleIgnoreEntity( GetVehicleEnt(), tr.m_pEnt ) == false ) -#endif //HL2_EPISODIC - { - if ( g_debug_vehicleexit.GetBool() ) - { - NDebugOverlay::Line( vecViewOrigin, vecExitEndPoint, 255,0,0, true, 10 ); - } - continue; - } - } - - bBestExitIsEscapePoint = m_ExitAnimations[i].bEscapeExit; - vecBestExitPoint = vecExitEndPoint; - nBestExitAnim = i; - flMaxCosAngleDelta = flCosAngleDelta; - } - - if ( nBestExitAnim >= 0 ) - { - m_vecCurrentExitEndPoint = vecBestExitPoint; - - if ( g_debug_vehicleexit.GetBool() ) - { - NDebugOverlay::Cross3D( m_vecCurrentExitEndPoint, 16, 0, 255, 0, true, 10 ); - NDebugOverlay::Box( m_vecCurrentExitEndPoint, VEC_HULL_MIN, VEC_HULL_MAX, 255,255,255, 8, 10 ); - } - - vecEyeExitEndpoint = vecBestExitPoint + VEC_VIEW; - m_iCurrentExitAnim = nBestExitAnim; - return pAnimating->LookupSequence( m_ExitAnimations[m_iCurrentExitAnim].szAnimName ); - } - - // Fail, all exit points were blocked. - bAllPointsBlocked = true; - return ACTIVITY_NOT_AVAILABLE; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::HandleEntryExitFinish( bool bExitAnimOn, bool bResetAnim ) -{ - // Parse the vehicle animations. This is needed because they may have - // saved, and loaded during exit anim, which would clear the exit anim. - if ( !m_bParsedAnimations ) - { - // Load the entry/exit animations from the vehicle - ParseEntryExitAnims(); - m_bParsedAnimations = true; - } - - // Figure out which entrypoint hitbox the player is in - CBaseAnimating *pAnimating = m_pVehicle->GetBaseAnimating(); - if ( !pAnimating ) - return; - - // Did the entry anim just finish? - if ( bExitAnimOn ) - { - // The exit animation just finished - CBasePlayer *pPlayer = ToBasePlayer( GetDriver() ); - if ( pPlayer != NULL ) - { - Vector vecEyes; - QAngle vecEyeAng; - if ( m_iCurrentExitAnim >= 0 && m_iCurrentExitAnim < m_ExitAnimations.Count() ) - { - // Convert our offset points to worldspace ones - vecEyes = m_ExitAnimations[m_iCurrentExitAnim].vecExitPointLocal; - vecEyeAng = m_ExitAnimations[m_iCurrentExitAnim].vecExitAnglesLocal; - UTIL_ParentToWorldSpace( pAnimating, vecEyes, vecEyeAng ); - - // Use the endpoint we figured out when we exited - vecEyes = m_vecCurrentExitEndPoint; - } - else - { - pAnimating->GetAttachment( "vehicle_driver_eyes", vecEyes, vecEyeAng ); - } - - if ( g_debug_vehicleexit.GetBool() ) - { - NDebugOverlay::Box( vecEyes, -Vector(2,2,2), Vector(2,2,2), 255,0,0, 64, 10.0 ); - } - - // If the end point isn't clear, get back in the vehicle - /* - trace_t tr; - UTIL_TraceHull( vecEyes, vecEyes, VEC_HULL_MIN, VEC_HULL_MAX, MASK_SOLID, NULL, COLLISION_GROUP_NONE, &tr ); - if ( tr.startsolid && tr.fraction < 1.0 ) - { - pPlayer->LeaveVehicle( vecEyes, vecEyeAng ); - m_pVehicle->Use( pPlayer, pPlayer, USE_TOGGLE, 1 ); - return; - } - */ - - pPlayer->LeaveVehicle( vecEyes, vecEyeAng ); - } - } - - // Only reset the animation if we're told to - if ( bResetAnim ) - { - // Start the vehicle idling again - int iSequence = pAnimating->SelectWeightedSequence( ACT_IDLE ); - if ( iSequence > ACTIVITY_NOT_AVAILABLE ) - { - pAnimating->SetCycle( 0 ); - pAnimating->m_flAnimTime = gpGlobals->curtime; - pAnimating->ResetSequence( iSequence ); - pAnimating->ResetClientsideFrame(); - } - } - - GetDrivableVehicle()->SetVehicleEntryAnim( false ); - GetDrivableVehicle()->SetVehicleExitAnim( false, vec3_origin ); -} - -//----------------------------------------------------------------------------- -// Purpose: Where does the passenger see from? -//----------------------------------------------------------------------------- -void CBaseServerVehicle::GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV /*= NULL*/ ) -{ - Assert( nRole == VEHICLE_ROLE_DRIVER ); - CBaseCombatCharacter *pPassenger = GetPassenger( VEHICLE_ROLE_DRIVER ); - Assert( pPassenger ); - - CBasePlayer *pPlayer = ToBasePlayer( pPassenger ); - if ( pPlayer != NULL ) - { - // Call through the player to resolve the actual position (if available) - if ( pAbsOrigin != NULL ) - { - *pAbsOrigin = pPlayer->EyePosition(); - } - - if ( pAbsAngles != NULL ) - { - *pAbsAngles = pPlayer->EyeAngles(); - } - - if ( pFOV ) - { - *pFOV = pPlayer->GetFOV(); - } - } - else - { - // NPCs are not supported - Assert( 0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) -{ - GetDrivableVehicle()->SetupMove( player, ucmd, pHelper, move ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ) -{ - GetDrivableVehicle()->ProcessMovement( pPlayer, pMoveData ); - - trace_t tr; - UTIL_TraceLine( pPlayer->GetAbsOrigin(), pPlayer->GetAbsOrigin() - Vector( 0, 0, 256 ), MASK_PLAYERSOLID, GetVehicleEnt(), COLLISION_GROUP_NONE, &tr ); - - // If our gamematerial has changed, tell any player surface triggers that are watching - IPhysicsSurfaceProps *physprops = MoveHelper()->GetSurfaceProps(); - const surfacedata_t *pSurfaceProp = physprops->GetSurfaceData( tr.surface.surfaceProps ); - char cCurrGameMaterial = pSurfaceProp->game.material; - - // Changed? - if ( m_chPreviousTextureType != cCurrGameMaterial ) - { - CEnvPlayerSurfaceTrigger::SetPlayerSurface( pPlayer, cCurrGameMaterial ); - } - - m_chPreviousTextureType = cCurrGameMaterial; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::FinishMove( CBasePlayer *player, CUserCmd *ucmd, CMoveData *move ) -{ - GetDrivableVehicle()->FinishMove( player, ucmd, move ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::ItemPostFrame( CBasePlayer *player ) -{ - Assert( player == GetDriver() ); - - GetDrivableVehicle()->ItemPostFrame( player ); - - if ( player->m_afButtonPressed & IN_USE ) - { - if ( GetDrivableVehicle()->CanExitVehicle(player) ) - { - if ( !HandlePassengerExit( player ) && ( player != NULL ) ) - { - player->PlayUseDenySound(); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::NPC_ThrottleForward( void ) -{ - m_nNPCButtons |= IN_FORWARD; - m_nNPCButtons &= ~IN_BACK; - m_nNPCButtons &= ~IN_JUMP; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::NPC_ThrottleReverse( void ) -{ - m_nNPCButtons |= IN_BACK; - m_nNPCButtons &= ~IN_FORWARD; - m_nNPCButtons &= ~IN_JUMP; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::NPC_ThrottleCenter( void ) -{ - m_nNPCButtons &= ~IN_FORWARD; - m_nNPCButtons &= ~IN_BACK; - m_nNPCButtons &= ~IN_JUMP; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::NPC_Brake( void ) -{ - m_nNPCButtons &= ~IN_FORWARD; - m_nNPCButtons &= ~IN_BACK; - m_nNPCButtons |= IN_JUMP; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::NPC_TurnLeft( float flDegrees ) -{ - m_nNPCButtons |= IN_MOVELEFT; - m_nNPCButtons &= ~IN_MOVERIGHT; - m_flTurnDegrees = -flDegrees; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::NPC_TurnRight( float flDegrees ) -{ - m_nNPCButtons |= IN_MOVERIGHT; - m_nNPCButtons &= ~IN_MOVELEFT; - m_flTurnDegrees = flDegrees; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::NPC_TurnCenter( void ) -{ - m_nNPCButtons &= ~IN_MOVERIGHT; - m_nNPCButtons &= ~IN_MOVELEFT; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::NPC_PrimaryFire( void ) -{ - m_nNPCButtons |= IN_ATTACK; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::NPC_SecondaryFire( void ) -{ - m_nNPCButtons |= IN_ATTACK2; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::Weapon_PrimaryRanges( float *flMinRange, float *flMaxRange ) -{ - *flMinRange = 64; - *flMaxRange = 1024; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::Weapon_SecondaryRanges( float *flMinRange, float *flMaxRange ) -{ - *flMinRange = 64; - *flMaxRange = 1024; -} - -//----------------------------------------------------------------------------- -// Purpose: Return the time at which this vehicle's primary weapon can fire again -//----------------------------------------------------------------------------- -float CBaseServerVehicle::Weapon_PrimaryCanFireAt( void ) -{ - return gpGlobals->curtime; -} - -//----------------------------------------------------------------------------- -// Purpose: Return the time at which this vehicle's secondary weapon can fire again -//----------------------------------------------------------------------------- -float CBaseServerVehicle::Weapon_SecondaryCanFireAt( void ) -{ - return gpGlobals->curtime; -} - -const char *pSoundStateNames[] = -{ - "SS_NONE", - "SS_SHUTDOWN", - "SS_SHUTDOWN_WATER", - "SS_START_WATER", - "SS_START_IDLE", - "SS_IDLE", - "SS_GEAR_0", - "SS_GEAR_1", - "SS_GEAR_2", - "SS_GEAR_3", - "SS_GEAR_4", - "SS_SLOWDOWN", - "SS_SLOWDOWN_HIGHSPEED", - "SS_GEAR_0_RESUME", - "SS_GEAR_1_RESUME", - "SS_GEAR_2_RESUME", - "SS_GEAR_3_RESUME", - "SS_GEAR_4_RESUME", - "SS_TURBO", - "SS_REVERSE", -}; - - -static int SoundStateIndexFromName( const char *pName ) -{ - for ( size_t i = 0; i < SS_NUM_STATES; i++ ) - { - Assert( i < ARRAYSIZE(pSoundStateNames) ); - if ( !strcmpi( pSoundStateNames[i], pName ) ) - return i; - } - return -1; -} - -static const char *SoundStateNameFromIndex( int index ) -{ - index = clamp(index, 0, SS_NUM_STATES-1 ); - return pSoundStateNames[index]; -} - -void CBaseServerVehicle::PlaySound( const char *pSound ) -{ - if ( !pSound || !pSound[0] ) - return; - - if ( g_debug_vehiclesound.GetInt() ) - { - Msg("Playing non-looping vehicle sound: %s\n", pSound ); - } - m_pVehicle->EmitSound( pSound ); -} - -void CBaseServerVehicle::StopLoopingSound( float fadeTime ) -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - if ( m_pStateSoundFade ) - { - controller.SoundDestroy( m_pStateSoundFade ); - m_pStateSoundFade = NULL; - } - if ( m_pStateSound ) - { - m_pStateSoundFade = m_pStateSound; - m_pStateSound = NULL; - controller.SoundFadeOut( m_pStateSoundFade, fadeTime, false ); - } -} - -void CBaseServerVehicle::PlayLoopingSound( const char *pSoundName ) -{ - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - - CPASAttenuationFilter filter( m_pVehicle ); - CSoundPatch *pNewSound = NULL; - if ( pSoundName && pSoundName[0] ) - { - pNewSound = controller.SoundCreate( filter, m_pVehicle->entindex(), CHAN_STATIC, pSoundName, ATTN_NORM ); - } - - if ( m_pStateSound && pNewSound && controller.SoundGetName( pNewSound ) == controller.SoundGetName( m_pStateSound ) ) - { - // if the sound is the same, don't play this, just re-use the old one - controller.SoundDestroy( pNewSound ); - pNewSound = m_pStateSound; - controller.SoundChangeVolume( pNewSound, 1.0f, 0.0f ); - m_pStateSound = NULL; - } - else if ( g_debug_vehiclesound.GetInt() ) - { - const char *pStopSound = m_pStateSound ? controller.SoundGetName( m_pStateSound ).ToCStr() : "NULL"; - const char *pStartSound = pNewSound ? controller.SoundGetName( pNewSound ).ToCStr() : "NULL"; - Msg("Stop %s, start %s\n", pStopSound, pStartSound ); - } - - StopLoopingSound(); - m_pStateSound = pNewSound; - if ( m_pStateSound ) - { - controller.Play( m_pStateSound, 1.0f, 100 ); - } -} - -static sound_states MapGearToState( vbs_sound_update_t ¶ms, int gear ) -{ - switch( gear ) - { - case 0: return params.bReverse ? SS_REVERSE : SS_GEAR_0; - case 1: return SS_GEAR_1; - case 2: return SS_GEAR_2; - case 3: return SS_GEAR_3; - default:case 4: return SS_GEAR_4; - } -} - -static sound_states MapGearToMidState( vbs_sound_update_t ¶ms, int gear ) -{ - switch( gear ) - { - case 0: return params.bReverse ? SS_REVERSE : SS_GEAR_0_RESUME; - case 1: return SS_GEAR_1_RESUME; - case 2: return SS_GEAR_2_RESUME; - case 3: return SS_GEAR_3_RESUME; - default:case 4: return SS_GEAR_4_RESUME; - } -} - -bool CBaseServerVehicle::PlayCrashSound( float speed ) -{ - int i; - float delta = 0; - float absSpeed = fabs(speed); - float absLastSpeed = fabs(m_lastSpeed); - if ( absLastSpeed > absSpeed ) - { - delta = fabs(m_lastSpeed - speed); - } - - float rumble = delta / 8.0f; - - if( rumble > 60.0f ) - rumble = 60.0f; - - if( rumble > 5.0f ) - { - if ( GetDriver() ) - { - UTIL_ScreenShake( GetDriver()->GetAbsOrigin(), rumble, 150.0f, 1.0f, 240.0f, SHAKE_START_RUMBLEONLY, true ); - } - } - - for ( i = 0; i < m_vehicleSounds.crashSounds.Count(); i++ ) - { - const vehicle_crashsound_t &crash = m_vehicleSounds.crashSounds[i]; - if ( !crash.gearLimit ) - continue; - - if ( m_iSoundGear <= crash.gearLimit ) - { - if ( delta > crash.flMinDeltaSpeed && absLastSpeed > crash.flMinSpeed ) - { - PlaySound( crash.iszCrashSound.ToCStr() ); - return true; - } - } - } - - for ( i = m_vehicleSounds.crashSounds.Count()-1; i >= 0; --i ) - { - const vehicle_crashsound_t &crash = m_vehicleSounds.crashSounds[i]; - if ( delta > crash.flMinDeltaSpeed && absLastSpeed > crash.flMinSpeed ) - { - PlaySound( crash.iszCrashSound.ToCStr() ); - return true; - } - } - return false; -} - - -bool CBaseServerVehicle::CheckCrash( vbs_sound_update_t ¶ms ) -{ - if ( params.bVehicleInWater ) - return false; - - bool bCrashed = PlayCrashSound( params.flWorldSpaceSpeed ); - if ( bCrashed ) - { - if ( g_debug_vehiclesound.GetInt() ) - { - Msg("Crashed!: speed %.2f, lastSpeed %.2f\n", params.flWorldSpaceSpeed, m_lastSpeed ); - } - } - m_lastSpeed = params.flWorldSpaceSpeed; - return bCrashed; -} - - -sound_states CBaseServerVehicle::SoundState_ChooseState( vbs_sound_update_t ¶ms ) -{ - float timeInState = gpGlobals->curtime - m_soundStateStartTime; - bool bInStateForMinTime = timeInState > m_vehicleSounds.minStateTime[m_soundState] ? true : false; - - sound_states stateOut = m_soundState; - - // exit overrides everything else - if ( params.bExitVehicle ) - { - switch ( m_soundState ) - { - case SS_NONE: - case SS_SHUTDOWN: - case SS_SHUTDOWN_WATER: - return m_soundState; - default: - break; - } - return SS_SHUTDOWN; - } - - // check global state in states that don't mask them - switch( m_soundState ) - { - // global states masked for these states. - case SS_NONE: - case SS_START_IDLE: - case SS_SHUTDOWN: - break; - case SS_START_WATER: - case SS_SHUTDOWN_WATER: - if ( !params.bVehicleInWater ) - return SS_START_IDLE; - break; - - case SS_TURBO: - if ( params.bVehicleInWater ) - return SS_SHUTDOWN_WATER; - if ( CheckCrash(params) ) - return SS_IDLE; - break; - - case SS_IDLE: - if ( params.bVehicleInWater ) - return SS_SHUTDOWN_WATER; - break; - - case SS_REVERSE: - case SS_GEAR_0: - case SS_GEAR_1: - case SS_GEAR_2: - case SS_GEAR_3: - case SS_GEAR_4: - case SS_SLOWDOWN: - case SS_SLOWDOWN_HIGHSPEED: - case SS_GEAR_0_RESUME: - case SS_GEAR_1_RESUME: - case SS_GEAR_2_RESUME: - case SS_GEAR_3_RESUME: - case SS_GEAR_4_RESUME: - if ( params.bVehicleInWater ) - { - return SS_SHUTDOWN_WATER; - } - if ( params.bTurbo ) - { - return SS_TURBO; - } - if ( CheckCrash(params) ) - return SS_IDLE; - break; - - default: - break; - } - - switch( m_soundState ) - { - case SS_START_IDLE: - if ( bInStateForMinTime || params.bThrottleDown ) - return SS_IDLE; - break; - case SS_IDLE: - if ( bInStateForMinTime && params.bThrottleDown ) - { - if ( params.bTurbo ) - return SS_TURBO; - return params.bReverse ? SS_REVERSE : SS_GEAR_0; - } - break; - - case SS_GEAR_0_RESUME: - case SS_GEAR_0: - if ( (bInStateForMinTime && !params.bThrottleDown) || params.bReverse ) - { - return SS_IDLE; - } - if ( m_iSoundGear > 0 ) - { - return SS_GEAR_1; - } - break; - case SS_GEAR_1_RESUME: - case SS_GEAR_1: - if ( bInStateForMinTime ) - { - if ( !params.bThrottleDown ) - return SS_SLOWDOWN; - } - if ( m_iSoundGear != 1 ) - return MapGearToState( params, m_iSoundGear); - break; - - case SS_GEAR_2_RESUME: - case SS_GEAR_2: - if ( bInStateForMinTime ) - { - if ( !params.bThrottleDown ) - return SS_SLOWDOWN; - else if ( m_iSoundGear != 2 ) - return MapGearToState(params, m_iSoundGear); - } - break; - - case SS_GEAR_3_RESUME: - case SS_GEAR_3: - if ( bInStateForMinTime ) - { - if ( !params.bThrottleDown ) - return SS_SLOWDOWN; - else if ( m_iSoundGear != 3 ) - return MapGearToState(params, m_iSoundGear); - } - break; - - case SS_GEAR_4_RESUME: - case SS_GEAR_4: - if ( bInStateForMinTime && !params.bThrottleDown ) - { - return SS_SLOWDOWN; - } - if ( m_iSoundGear != 4 ) - { - return MapGearToMidState(params, m_iSoundGear); - } - break; - case SS_REVERSE: - if ( bInStateForMinTime && !params.bReverse ) - { - return SS_SLOWDOWN; - } - break; - - case SS_SLOWDOWN_HIGHSPEED: - case SS_SLOWDOWN: - if ( params.bThrottleDown ) - { - // map gears - return MapGearToMidState(params, m_iSoundGear); - } - if ( m_iSoundGear == 0 ) - { - return SS_IDLE; - } - break; - - case SS_NONE: - stateOut = params.bVehicleInWater ? SS_START_WATER : SS_START_IDLE; - break; - case SS_TURBO: - if ( bInStateForMinTime && !params.bTurbo ) - { - return MapGearToMidState(params, m_iSoundGear); - } - break; - default: - break; - } - - return stateOut; -} - -const char *CBaseServerVehicle::StateSoundName( sound_states state ) -{ - return m_vehicleSounds.iszStateSounds[state].ToCStr(); -} - -void CBaseServerVehicle::SoundState_OnNewState( sound_states lastState ) -{ - if ( g_debug_vehiclesound.GetInt() ) - { - int index = m_soundState; - Msg("Switched to state: %d (%s)\n", m_soundState, SoundStateNameFromIndex(index) ); - } - - switch ( m_soundState ) - { - case SS_SHUTDOWN: - case SS_SHUTDOWN_WATER: - case SS_START_WATER: - StopLoopingSound(); - PlaySound( StateSoundName(m_soundState) ); - break; - case SS_IDLE: - m_lastSpeed = -1; - PlayLoopingSound( StateSoundName(m_soundState) ); - break; - case SS_START_IDLE: - case SS_REVERSE: - case SS_GEAR_0: - case SS_GEAR_0_RESUME: - case SS_GEAR_1: - case SS_GEAR_1_RESUME: - case SS_GEAR_2: - case SS_GEAR_2_RESUME: - case SS_GEAR_3: - case SS_GEAR_3_RESUME: - case SS_GEAR_4: - case SS_GEAR_4_RESUME: - case SS_TURBO: - PlayLoopingSound( StateSoundName(m_soundState) ); - break; - - case SS_SLOWDOWN_HIGHSPEED: - case SS_SLOWDOWN: - if ( m_iSoundGear < 2 ) - { - PlayLoopingSound( StateSoundName( SS_SLOWDOWN ) ); - } - else - { - PlayLoopingSound( StateSoundName( SS_SLOWDOWN_HIGHSPEED ) ); - } - break; - - default:break; - } - - m_soundStateStartTime = gpGlobals->curtime; -} - - -void CBaseServerVehicle::SoundState_Update( vbs_sound_update_t ¶ms ) -{ - sound_states newState = SoundState_ChooseState( params ); - if ( newState != m_soundState ) - { - sound_states lastState = m_soundState; - m_soundState = newState; - SoundState_OnNewState( lastState ); - } - - switch( m_soundState ) - { - case SS_SHUTDOWN: - case SS_SHUTDOWN_WATER: - case SS_START_WATER: - case SS_START_IDLE: - case SS_IDLE: - case SS_REVERSE: - case SS_GEAR_0: - case SS_GEAR_4: - case SS_SLOWDOWN_HIGHSPEED: - case SS_SLOWDOWN: - case SS_GEAR_0_RESUME: - case SS_GEAR_4_RESUME: - break; - default:break; - } -} - -void CBaseServerVehicle::InitSoundParams( vbs_sound_update_t ¶ms ) -{ - params.Defaults(); - params.bVehicleInWater = IsVehicleBodyInWater(); -} - -//----------------------------------------------------------------------------- -// Purpose: Vehicle Sound Start -//----------------------------------------------------------------------------- -void CBaseServerVehicle::SoundStart() -{ - StartEngineRumble(); - - m_soundState = SS_NONE; - vbs_sound_update_t params; - InitSoundParams(params); - - SoundState_Update( params ); -} - -// vehicle is starting up disabled, but in some cases you still want to play a sound -// HACK: handle those here. -void CBaseServerVehicle::SoundStartDisabled() -{ - m_soundState = SS_NONE; - vbs_sound_update_t params; - InitSoundParams(params); - sound_states newState = SoundState_ChooseState( params ); - - switch( newState ) - { - case SS_START_WATER: - PlaySound( StateSoundName(newState) ); - break; - default: - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::SoundShutdown( float flFadeTime ) -{ - StopEngineRumble(); - - // Stop any looping sounds that may be running, as the following stop sound may not exist - // and thus leave a looping sound playing after the user gets out. - for ( int i = 0; i < NUM_SOUNDS_TO_STOP_ON_EXIT; i++ ) - { - StopSound( g_iSoundsToStopOnExit[i] ); - } - - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - if ( m_pStateSoundFade ) - { - controller.SoundFadeOut( m_pStateSoundFade, flFadeTime, true ); - m_pStateSoundFade = NULL; - } - if ( m_pStateSound ) - { - controller.SoundFadeOut( m_pStateSound, flFadeTime, true ); - m_pStateSound = NULL; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseServerVehicle::SoundUpdate( vbs_sound_update_t ¶ms ) -{ - if ( g_debug_vehiclesound.GetInt() > 1 ) - { - Msg("Throttle: %s, Reverse: %s\n", params.bThrottleDown?"on":"off", params.bReverse?"on":"off" ); - } - - float flCurrentSpeed = params.flCurrentSpeedFraction; - if ( g_debug_vehiclesound.GetInt() > 1 ) - { - Msg("CurrentSpeed: %.3f ", flCurrentSpeed ); - } - - // Figure out our speed for the purposes of sound playing. - // We slow the transition down a little to make the gear changes slower. - if ( m_vehicleSounds.pGears.Count() > 0 ) - { - if ( flCurrentSpeed > m_flSpeedPercentage ) - { - // don't accelerate when the throttle isn't down - if ( !params.bThrottleDown ) - { - flCurrentSpeed = m_flSpeedPercentage; - } - flCurrentSpeed = Approach( flCurrentSpeed, m_flSpeedPercentage, params.flFrameTime * m_vehicleSounds.pGears[m_iSoundGear].flSpeedApproachFactor ); - } - } - m_flSpeedPercentage = clamp( flCurrentSpeed, 0.0f, 1.0f ); - - if ( g_debug_vehiclesound.GetInt() > 1 ) - { - Msg("Sound Speed: %.3f\n", m_flSpeedPercentage ); - } - - // Only do gear changes when the throttle's down - RecalculateSoundGear( params ); - - SoundState_Update( params ); -} - -//----------------------------------------------------------------------------- -// Purpose: Play a non-gear based vehicle sound -//----------------------------------------------------------------------------- -void CBaseServerVehicle::PlaySound( vehiclesound iSound ) -{ - if ( m_vehicleSounds.iszSound[iSound] != NULL_STRING ) - { - CPASAttenuationFilter filter( m_pVehicle ); - - EmitSound_t ep; - ep.m_nChannel = CHAN_VOICE; - ep.m_pSoundName = STRING(m_vehicleSounds.iszSound[iSound]); - ep.m_flVolume = m_flVehicleVolume; - ep.m_SoundLevel = SNDLVL_NORM; - - CBaseEntity::EmitSound( filter, m_pVehicle->entindex(), ep ); - if ( g_debug_vehiclesound.GetInt() ) - { - Msg("Playing vehicle sound: %s\n", ep.m_pSoundName ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Stop a non-gear based vehicle sound -//----------------------------------------------------------------------------- -void CBaseServerVehicle::StopSound( vehiclesound iSound ) -{ - if ( m_vehicleSounds.iszSound[iSound] != NULL_STRING ) - { - CBaseEntity::StopSound( m_pVehicle->entindex(), CHAN_VOICE, STRING(m_vehicleSounds.iszSound[iSound]) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Calculate the gear we should be in based upon the vehicle's current speed -//----------------------------------------------------------------------------- -void CBaseServerVehicle::RecalculateSoundGear( vbs_sound_update_t ¶ms ) -{ - int iNumGears = m_vehicleSounds.pGears.Count(); - for ( int i = (iNumGears-1); i >= 0; i-- ) - { - if ( m_flSpeedPercentage > m_vehicleSounds.pGears[i].flMinSpeed ) - { - m_iSoundGear = i; - break; - } - } - - // If we're going in reverse, we want to stay in first gear - if ( params.bReverse ) - { - m_iSoundGear = 0; - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBaseServerVehicle::StartEngineRumble() -{ - return; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CBaseServerVehicle::StopEngineRumble() -{ - return; -} - -//----------------------------------------------------------------------------- -// Purpose: Find the passenger in the given seat of the vehicle -// Input : nSeatID - seat ID to check -// Output : CBaseCombatCharacter - character in the seat -//----------------------------------------------------------------------------- -CBaseCombatCharacter *CBaseServerVehicle::NPC_GetPassengerInSeat( int nRoleID, int nSeatID ) -{ - // Search all passengers in the vehicle - for ( int i = 0; i < m_PassengerInfo.Count(); i++ ) - { - // If the seat ID matches, return the entity in that seat - if ( m_PassengerInfo[i].GetSeat() == nSeatID && m_PassengerInfo[i].GetRole() == nRoleID ) - return m_PassengerInfo[i].m_hPassenger; - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Find the first available seat (ranked by priority) -// Input : nRoleID - Role index -// Output : int - Seat by index -//----------------------------------------------------------------------------- -int CBaseServerVehicle::NPC_GetAvailableSeat_Any( CBaseCombatCharacter *pPassenger, int nRoleID ) -{ - // Look through all available seats - for ( int i = 0; i < m_PassengerRoles[nRoleID].m_PassengerSeats.Count(); i++ ) - { - // See if anyone is already in this seat - CBaseCombatCharacter *pCurrentPassenger = NPC_GetPassengerInSeat( nRoleID, i ); - if ( pCurrentPassenger != NULL && pCurrentPassenger != pPassenger ) - continue; - - // This seat is open - return i; - } - - // Nothing found - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: Find the seat with the nearest entry point to the querier -// Input : *pPassenger - Terget to be nearest to -// nRoleID - Role index -// Output : int - Seat by index -//----------------------------------------------------------------------------- -int CBaseServerVehicle::NPC_GetAvailableSeat_Nearest( CBaseCombatCharacter *pPassenger, int nRoleID ) -{ - // Not yet implemented - Assert( 0 ); - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: Get a seat in the vehicle based on our role and criteria -// Input : *pPassenger - Entity attempting to find a seat -// strRoleName - Role the seat must serve -// nQueryType - Method for choosing the best seat (if multiple) -// Output : int - Seat by unique ID -//----------------------------------------------------------------------------- -int CBaseServerVehicle::NPC_GetAvailableSeat( CBaseCombatCharacter *pPassenger, string_t strRoleName, VehicleSeatQuery_e nQueryType ) -{ - // Parse the vehicle animations the first time they get in the vehicle - if ( m_bParsedAnimations == false ) - { - // Load the entry/exit animations from the vehicle - ParseEntryExitAnims(); - m_bParsedAnimations = true; - } - - // Get the role index - int nRole = FindRoleIndexByName( strRoleName ); - if ( m_PassengerRoles.IsValidIndex( nRole ) == false ) - return -1; - - switch( nQueryType ) - { - case VEHICLE_SEAT_ANY: - return NPC_GetAvailableSeat_Any( pPassenger, nRole ); - break; - - case VEHICLE_SEAT_NEAREST: - return NPC_GetAvailableSeat_Nearest( pPassenger, nRole ); - break; - - default: - Assert( 0 ); - break; - }; - - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: Determine if there's an available seat of a given role name -// Input : strRoleName - name of the role -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseServerVehicle::NPC_HasAvailableSeat( string_t strRoleName ) -{ - return ( NPC_GetAvailableSeat( NULL, strRoleName, VEHICLE_SEAT_ANY ) != -1 ); -} - -//----------------------------------------------------------------------------- -// Purpose: Find a role index by name -// Input : strRoleName - name of the role -//----------------------------------------------------------------------------- -int CBaseServerVehicle::FindRoleIndexByName( string_t strRoleName ) -{ - // Search through all our known roles - for ( int i = 0; i < m_PassengerRoles.Count(); i++ ) - { - // Return the index if the name matches - if ( FStrEq( STRING( m_PassengerRoles[i].GetName() ), STRING( strRoleName ) ) ) - return i; - } - - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: Find a seat index by its name -// Input : strSeatName - name of the seat -//----------------------------------------------------------------------------- -int CBaseServerVehicle::FindSeatIndexByName( int nRoleIndex, string_t strSeatName ) -{ - // Role must be valid - if ( m_PassengerRoles.IsValidIndex( nRoleIndex ) == false ) - return -1; - - // Used for attachment polling - CBaseAnimating *pAnimating = dynamic_cast(GetVehicleEnt()); - if ( pAnimating == NULL ) - return -1; - - // Get the index of the named attachment in the model - int nAttachmentID = pAnimating->LookupAttachment( STRING( strSeatName ) ); - - // Look through the roles for this seat attachment ID - for ( int i = 0; i < m_PassengerRoles[nRoleIndex].m_PassengerSeats.Count(); i++ ) - { - // Return that index if found - if ( m_PassengerRoles[nRoleIndex].m_PassengerSeats[i].GetAttachmentID() == nAttachmentID ) - return i; - } - - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: Called after loading a saved game -//----------------------------------------------------------------------------- -void CBaseServerVehicle::RestorePassengerInfo( void ) -{ - // If there is passenger information, then we have passengers in the vehicle - if ( m_PassengerInfo.Count() != 0 && m_bParsedAnimations == false ) - { - // Load the entry/exit animations from the vehicle - ParseEntryExitAnims(); - m_bParsedAnimations = true; - } - - // FIXME: If a passenger cannot fix-up its indices, it must be removed from the vehicle! - - // Fix-up every passenger with updated indices - for ( int i = 0; i < m_PassengerInfo.Count(); i++ ) - { - // Fix up the role first - int nRoleIndex = FindRoleIndexByName( m_PassengerInfo[i].m_strRoleName ); - if ( m_PassengerRoles.IsValidIndex( nRoleIndex ) ) - { - // New role index - m_PassengerInfo[i].m_nRole = nRoleIndex; - - // Then fix up the seat via attachment name - int nSeatIndex = FindSeatIndexByName( nRoleIndex, m_PassengerInfo[i].m_strSeatName ); - if ( m_PassengerRoles[nRoleIndex].m_PassengerSeats.IsValidIndex( nSeatIndex ) ) - { - // New seat index - m_PassengerInfo[i].m_nSeat = nSeatIndex; - } - else - { - // The seat attachment was not found. This most likely means that the seat attachment name has changed - // in the target vehicle and the NPC passenger is now stranded! - Assert( 0 ); - } - } - else - { - // The role was not found. This most likely means that the role names have changed - // in the target vehicle and the NPC passenger is now stranded! - Assert( 0 ); - } - } -} - -void CBaseServerVehicle::ReloadScript() -{ - if ( m_pDrivableVehicle ) - { - string_t script = m_pDrivableVehicle->GetVehicleScriptName(); - IPhysicsVehicleController *pController = GetVehicleController(); - vehicleparams_t *pVehicleParams = pController ? &(pController->GetVehicleParamsForChange()) : NULL; - PhysFindOrAddVehicleScript( script.ToCStr(), pVehicleParams, &m_vehicleSounds ); - if ( pController ) - { - pController->VehicleDataReload(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Passes this call down into the server vehicle where the tests are done -//----------------------------------------------------------------------------- -bool CBaseServerVehicle::PassengerShouldReceiveDamage( CTakeDamageInfo &info ) -{ - if ( GetDrivableVehicle() ) - return GetDrivableVehicle()->PassengerShouldReceiveDamage( info ); - - return true; -} - -//=========================================================================================================== -// Vehicle Sounds -//=========================================================================================================== - -// These are sounds that are to be automatically stopped whenever the vehicle's driver leaves it -vehiclesound g_iSoundsToStopOnExit[] = -{ - VS_ENGINE2_START, - VS_ENGINE2_STOP, -}; - -const char *vehiclesound_parsenames[VS_NUM_SOUNDS] = -{ - "skid_lowfriction", - "skid_normalfriction", - "skid_highfriction", - "engine2_start", - "engine2_stop", - "misc1", - "misc2", - "misc3", - "misc4", -}; - -CVehicleSoundsParser::CVehicleSoundsParser( void ) -{ - // UNDONE: Revisit this pattern - move sub-block processing ideas into the parser architecture - m_iCurrentGear = -1; - m_iCurrentState = -1; - m_iCurrentCrashSound = -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CVehicleSoundsParser::ParseKeyValue( void *pData, const char *pKey, const char *pValue ) -{ - vehiclesounds_t *pSounds = (vehiclesounds_t *)pData; - // New gear? - if ( !strcmpi( pKey, "gear" ) ) - { - // Create, initialize, and add a new gear to our list - int iNewGear = pSounds->pGears.AddToTail(); - pSounds->pGears[iNewGear].flMaxSpeed = 0; - pSounds->pGears[iNewGear].flSpeedApproachFactor = 1.0; - - // Set our min speed to the previous gear's max - if ( iNewGear == 0 ) - { - // First gear, so our minspeed is 0 - pSounds->pGears[iNewGear].flMinSpeed = 0; - } - else - { - pSounds->pGears[iNewGear].flMinSpeed = pSounds->pGears[iNewGear-1].flMaxSpeed; - } - - // Remember which gear we're reading data from - m_iCurrentGear = iNewGear; - } - else if ( !strcmpi( pKey, "state" ) ) - { - m_iCurrentState = 0; - } - else if ( !strcmpi( pKey, "crashsound" ) ) - { - m_iCurrentCrashSound = pSounds->crashSounds.AddToTail(); - pSounds->crashSounds[m_iCurrentCrashSound].flMinSpeed = 0; - pSounds->crashSounds[m_iCurrentCrashSound].flMinDeltaSpeed = 0; - pSounds->crashSounds[m_iCurrentCrashSound].iszCrashSound = NULL_STRING; - } - else - { - int i; - - // Are we currently in a gear block? - if ( m_iCurrentGear >= 0 ) - { - Assert( m_iCurrentGear < pSounds->pGears.Count() ); - - // Check gear keys - if ( !strcmpi( pKey, "max_speed" ) ) - { - pSounds->pGears[m_iCurrentGear].flMaxSpeed = atof(pValue); - return; - } - if ( !strcmpi( pKey, "speed_approach_factor" ) ) - { - pSounds->pGears[m_iCurrentGear].flSpeedApproachFactor = atof(pValue); - return; - } - } - // We're done reading a gear, so stop checking them. - m_iCurrentGear = -1; - - if ( m_iCurrentState >= 0 ) - { - if ( !strcmpi( pKey, "name" ) ) - { - m_iCurrentState = SoundStateIndexFromName( pValue ); - pSounds->iszStateSounds[m_iCurrentState] = NULL_STRING; - pSounds->minStateTime[m_iCurrentState] = 0.0f; - return; - } - else if ( !strcmpi( pKey, "sound" ) ) - { - pSounds->iszStateSounds[m_iCurrentState] = AllocPooledString(pValue); - return; - } - else if ( !strcmpi( pKey, "min_time" ) ) - { - pSounds->minStateTime[m_iCurrentState] = atof(pValue); - return; - } - } - // - m_iCurrentState = -1; - - if ( m_iCurrentCrashSound >= 0 ) - { - if ( !strcmpi( pKey, "min_speed" ) ) - { - pSounds->crashSounds[m_iCurrentCrashSound].flMinSpeed = atof(pValue); - return; - } - else if ( !strcmpi( pKey, "sound" ) ) - { - pSounds->crashSounds[m_iCurrentCrashSound].iszCrashSound = AllocPooledString(pValue); - return; - } - else if ( !strcmpi( pKey, "min_speed_change" ) ) - { - pSounds->crashSounds[m_iCurrentCrashSound].flMinDeltaSpeed = atof(pValue); - return; - } - else if ( !strcmpi( pKey, "gear_limit" ) ) - { - pSounds->crashSounds[m_iCurrentCrashSound].gearLimit = atoi(pValue); - return; - } - } - m_iCurrentCrashSound = -1; - - for ( i = 0; i < VS_NUM_SOUNDS; i++ ) - { - if ( !strcmpi( pKey, vehiclesound_parsenames[i] ) ) - { - pSounds->iszSound[i] = AllocPooledString(pValue); - return; - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CVehicleSoundsParser::SetDefaults( void *pData ) -{ - vehiclesounds_t *pSounds = (vehiclesounds_t *)pData; - pSounds->Init(); -} - diff --git a/game/server/vehicle_baseserver.h b/game/server/vehicle_baseserver.h deleted file mode 100644 index 4f834197d..000000000 --- a/game/server/vehicle_baseserver.h +++ /dev/null @@ -1,328 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef VEHICLE_BASESERVER_H -#define VEHICLE_BASESERVER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "vehicle_sounds.h" -#include "entityblocker.h" - -class CSoundPatch; - -struct vbs_sound_update_t -{ - float flFrameTime; - float flCurrentSpeedFraction; - float flWorldSpaceSpeed; - bool bThrottleDown; - bool bReverse; - bool bTurbo; - bool bVehicleInWater; - bool bExitVehicle; - - void Defaults() - { - flFrameTime = gpGlobals->frametime; - flCurrentSpeedFraction = 0; - flWorldSpaceSpeed = 0; - bThrottleDown = false; - bReverse = false; - bTurbo = false; - bVehicleInWater = false; - bExitVehicle = false; - } -}; - -// ----------------------------------------- -// Information about the passenger in the car -// ----------------------------------------- -class CPassengerInfo -{ -public: - CPassengerInfo( void ) : m_nRole( -1 ), m_nSeat( -1 ), m_strRoleName( NULL_STRING ), m_strSeatName( NULL_STRING ) {} - - DECLARE_SIMPLE_DATADESC(); - - int GetSeat( void ) const { return m_nSeat; } - int GetRole( void ) const { return m_nRole; } - CBaseCombatCharacter *GetPassenger( void ) const { return m_hPassenger; } - -private: - int m_nRole; // Role (by index) - int m_nSeat; // Seat (by index) - string_t m_strRoleName; // Used in restoration for fix-up - string_t m_strSeatName; // Used in restoration for fix-up - CHandle m_hPassenger; // Actual passenger - - friend class CBaseServerVehicle; -}; - -// ----------------------------------------- -// Seat transition information (animation and priority) -// ----------------------------------------- - -class CPassengerSeatTransition -{ -public: - CPassengerSeatTransition( void ) : m_strAnimationName( NULL_STRING ), m_nPriority( -1 ) {}; - - string_t GetAnimationName( void ) const { return m_strAnimationName; } - int GetPriority( void ) const { return m_nPriority; } - -private: - string_t m_strAnimationName; // Name of animation to play - int m_nPriority; // Priority of the transition - - friend class CBaseServerVehicle; -}; - -// ----------------------------------------- -// Seat in a vehicle (attachment and a collection of animations to reach it) -// ----------------------------------------- -class CPassengerSeat -{ -public: - CPassengerSeat( void ) : m_nAttachmentID( -1 ) {}; - int GetAttachmentID( void ) const { return m_nAttachmentID; } - -private: - string_t m_strSeatName; // Used for save/load fixup - int m_nAttachmentID; // Goal attachment - CUtlVector m_EntryTransitions; // Entry information - CUtlVector m_ExitTransitions; // Exit information - - friend class CBaseServerVehicle; -}; - -// ----------------------------------------- -// Passenger role information -// ----------------------------------------- -class CPassengerRole -{ -public: - CPassengerRole( void ) : m_strName( NULL_STRING ) {}; - string_t GetName( void ) const { return m_strName; } - -private: - string_t m_strName; // Name of the set - CUtlVector m_PassengerSeats; // Passenger info - - friend class CBaseServerVehicle; -}; - -//----------------------------------------------------------------------------- -// Purpose: Base class for drivable vehicle handling. Contain it in your -// drivable vehicle. -//----------------------------------------------------------------------------- -class CBaseServerVehicle : public IServerVehicle -{ -public: - DECLARE_SIMPLE_DATADESC(); - DECLARE_CLASS_NOBASE( CBaseServerVehicle ); - - CBaseServerVehicle( void ); - ~CBaseServerVehicle( void ); - - virtual void Precache( void ); - -// IVehicle -public: - virtual CBaseCombatCharacter *GetPassenger( int nRole = VEHICLE_ROLE_DRIVER ); - - virtual int GetPassengerRole( CBaseCombatCharacter *pPassenger ); - virtual void GetVehicleViewPosition( int nRole, Vector *pOrigin, QAngle *pAngles, float *pFOV = NULL ); - virtual bool IsPassengerUsingStandardWeapons( int nRole = VEHICLE_ROLE_DRIVER ) { return false; } - virtual void SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ); - virtual void ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ); - virtual void FinishMove( CBasePlayer *player, CUserCmd *ucmd, CMoveData *move ); - virtual void ItemPostFrame( CBasePlayer *pPlayer ); - -// IServerVehicle -public: - virtual CBaseEntity *GetVehicleEnt( void ) { return m_pVehicle; } - virtual void SetPassenger( int nRole, CBaseCombatCharacter *pPassenger ); - virtual bool IsPassengerVisible( int nRole = VEHICLE_ROLE_DRIVER ) { return false; } - virtual bool IsPassengerDamagable( int nRole = VEHICLE_ROLE_DRIVER ) { return true; } - virtual bool PassengerShouldReceiveDamage( CTakeDamageInfo &info ); - - virtual bool IsVehicleUpright( void ) { return true; } - virtual bool IsPassengerEntering( void ) { Assert( 0 ); return false; } - virtual bool IsPassengerExiting( void ) { Assert( 0 ); return false; } - - virtual void HandlePassengerEntry( CBaseCombatCharacter *pPassenger, bool bAllowEntryOutsideZone = false ); - virtual bool HandlePassengerExit( CBaseCombatCharacter *pPassenger ); - - virtual void GetPassengerSeatPoint( int nRole, Vector *pPoint, QAngle *pAngles ); - virtual bool GetPassengerExitPoint( int nRole, Vector *pPoint, QAngle *pAngles ); - virtual Class_T ClassifyPassenger( CBaseCombatCharacter *pPassenger, Class_T defaultClassification ) { return defaultClassification; } - virtual float PassengerDamageModifier( const CTakeDamageInfo &info ) { return 1.0; } - virtual const vehicleparams_t *GetVehicleParams( void ) { return NULL; } - virtual bool IsVehicleBodyInWater( void ) { return false; } - virtual IPhysicsVehicleController *GetVehicleController() { return NULL; } - - // NPC Driving - virtual bool NPC_CanDrive( void ) { return true; } - virtual void NPC_SetDriver( CNPC_VehicleDriver *pDriver ) { return; } - virtual void NPC_DriveVehicle( void ) { return; } - virtual void NPC_ThrottleCenter( void ); - virtual void NPC_ThrottleReverse( void ); - virtual void NPC_ThrottleForward( void ); - virtual void NPC_Brake( void ); - virtual void NPC_TurnLeft( float flDegrees ); - virtual void NPC_TurnRight( float flDegrees ); - virtual void NPC_TurnCenter( void ); - virtual void NPC_PrimaryFire( void ); - virtual void NPC_SecondaryFire( void ); - virtual bool NPC_HasPrimaryWeapon( void ) { return false; } - virtual bool NPC_HasSecondaryWeapon( void ) { return false; } - virtual void NPC_AimPrimaryWeapon( Vector vecTarget ) { return; } - virtual void NPC_AimSecondaryWeapon( Vector vecTarget ) { return; } - - // Weapon handling - virtual void Weapon_PrimaryRanges( float *flMinRange, float *flMaxRange ); - virtual void Weapon_SecondaryRanges( float *flMinRange, float *flMaxRange ); - virtual float Weapon_PrimaryCanFireAt( void ); // Return the time at which this vehicle's primary weapon can fire again - virtual float Weapon_SecondaryCanFireAt( void ); // Return the time at which this vehicle's secondary weapon can fire again - - // ---------------------------------------------------------------------------- - // NPC passenger data - -public: - - bool NPC_AddPassenger( CBaseCombatCharacter *pPassenger, string_t strRoleName, int nSeat ); - bool NPC_RemovePassenger( CBaseCombatCharacter *pPassenger ); - virtual bool NPC_GetPassengerSeatPosition( CBaseCombatCharacter *pPassenger, Vector *vecResultPos, QAngle *vecResultAngle ); - virtual bool NPC_GetPassengerSeatPositionLocal( CBaseCombatCharacter *pPassenger, Vector *vecResultPos, QAngle *vecResultAngles ); - virtual int NPC_GetPassengerSeatAttachment( CBaseCombatCharacter *pPassenger ); - virtual int NPC_GetAvailableSeat( CBaseCombatCharacter *pPassenger, string_t strRoleName, VehicleSeatQuery_e nQueryType ); - bool NPC_HasAvailableSeat( string_t strRoleName ); - - - virtual const PassengerSeatAnims_t *NPC_GetPassengerSeatAnims( CBaseCombatCharacter *pPassenger, PassengerSeatAnimType_t nType ); - virtual CBaseCombatCharacter *NPC_GetPassengerInSeat( int nRoleID, int nSeatID ); - - Vector GetSavedViewOffset( void ) { return m_savedViewOffset; } - -private: - - // Vehicle entering/exiting - void ParseNPCRoles( KeyValues *pModelKeyValues ); - void ParseNPCPassengerSeat( KeyValues *pSetKeyValues, CPassengerSeat *pSeat ); - void ParseNPCSeatTransition( KeyValues *pTransitionKeyValues, CPassengerSeatTransition *pTransition ); - -protected: - - int FindRoleIndexByName( string_t strRoleName ); - int FindSeatIndexByName( int nRoleIndex, string_t strSeatName ); - int NPC_GetAvailableSeat_Any( CBaseCombatCharacter *pPassenger, int nRoleID ); - int NPC_GetAvailableSeat_Nearest( CBaseCombatCharacter *pPassenger, int nRoleID ); - - CPassengerRole *FindOrCreatePassengerRole( string_t strName, int *nIndex = NULL ); - - CUtlVector< CPassengerInfo > m_PassengerInfo; - CUtlVector< CPassengerRole > m_PassengerRoles; // Not save/restored - - // ---------------------------------------------------------------------------- - void ReloadScript(); // debug/tuning -public: - - void UseLegacyExitChecks( bool bState ) { m_bUseLegacyExitChecks = bState; } - void RestorePassengerInfo( void ); - - virtual CBaseEntity *GetDriver( void ); // Player Driving - virtual void ParseEntryExitAnims( void ); - void ParseExitAnim( KeyValues *pkvExitList, bool bEscapeExit ); - virtual bool CheckExitPoint( float yaw, int distance, Vector *pEndPoint ); - virtual int GetEntryAnimForPoint( const Vector &vecPoint ); - virtual int GetExitAnimToUse( Vector &vecEyeExitEndpoint, bool &bAllPointsBlocked ); - virtual void HandleEntryExitFinish( bool bExitAnimOn, bool bResetAnim ); - - virtual void SetVehicle( CBaseEntity *pVehicle ); - IDrivableVehicle *GetDrivableVehicle( void ); - - // Sound handling - bool Initialize( const char *pScriptName ); - virtual void SoundStart(); - virtual void SoundStartDisabled(); - virtual void SoundShutdown( float flFadeTime = 0.0 ); - virtual void SoundUpdate( vbs_sound_update_t ¶ms ); - virtual void PlaySound( vehiclesound iSound ); - virtual void StopSound( vehiclesound iSound ); - virtual void RecalculateSoundGear( vbs_sound_update_t ¶ms ); - void SetVehicleVolume( float flVolume ) { m_flVehicleVolume = clamp( flVolume, 0.0, 1.0 ); } - - // Rumble - virtual void StartEngineRumble(); - virtual void StopEngineRumble(); - -public: - CBaseEntity *m_pVehicle; - IDrivableVehicle *m_pDrivableVehicle; - - // NPC Driving - int m_nNPCButtons; - int m_nPrevNPCButtons; - float m_flTurnDegrees; - - // Entry / Exit anims - struct entryanim_t - { - int iHitboxGroup; - char szAnimName[128]; - }; - CUtlVector< entryanim_t > m_EntryAnimations; - - struct exitanim_t - { - bool bUpright; - bool bEscapeExit; - char szAnimName[128]; - Vector vecExitPointLocal; // Point the animation leaves the player at when finished - QAngle vecExitAnglesLocal; - }; - - CUtlVector< exitanim_t > m_ExitAnimations; - bool m_bParsedAnimations; - bool m_bUseLegacyExitChecks; // HACK: Choreo vehicles use non-sensical setups to move the player, we need to poll their attachment point positions - int m_iCurrentExitAnim; - Vector m_vecCurrentExitEndPoint; - Vector m_savedViewOffset; - CHandle m_hExitBlocker; // Entity to prevent other entities blocking the player's exit point during the exit animation - - char m_chPreviousTextureType; - -// sound state - vehiclesounds_t m_vehicleSounds; -private: - float m_flVehicleVolume; - int m_iSoundGear; // The sound "gear" that we're currently in - float m_flSpeedPercentage; - - CSoundPatch *m_pStateSound; - CSoundPatch *m_pStateSoundFade; - sound_states m_soundState; - float m_soundStateStartTime; - float m_lastSpeed; - - void SoundState_OnNewState( sound_states lastState ); - void SoundState_Update( vbs_sound_update_t ¶ms ); - sound_states SoundState_ChooseState( vbs_sound_update_t ¶ms ); - void PlaySound( const char *pSound ); - void StopLoopingSound( float fadeTime = 0.25f ); - void PlayLoopingSound( const char *pSoundName ); - bool PlayCrashSound( float speed ); - bool CheckCrash( vbs_sound_update_t ¶ms ); - const char *StateSoundName( sound_states state ); - void InitSoundParams( vbs_sound_update_t ¶ms ); - void CacheEntryExitPoints( void ); - bool GetLocalAttachmentAtTime( int nQuerySequence, int nAttachmentIndex, float flCyclePoint, Vector *vecOriginOut, QAngle *vecAnglesOut ); - bool GetLocalAttachmentAtTime( const char *lpszAnimName, int nAttachmentIndex, float flCyclePoint, Vector *vecOriginOut, QAngle *vecAnglesOut ); -}; - -#endif // VEHICLE_BASESERVER_H diff --git a/game/server/vehicle_choreo_generic.cpp b/game/server/vehicle_choreo_generic.cpp deleted file mode 100644 index d638447f1..000000000 --- a/game/server/vehicle_choreo_generic.cpp +++ /dev/null @@ -1,985 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" -#include "vehicle_base.h" -#include "engine/IEngineSound.h" -#include "in_buttons.h" -#include "soundenvelope.h" -#include "soundent.h" -#include "physics_saverestore.h" -#include "vphysics/constraints.h" -#include "vcollide_parse.h" -#include "ndebugoverlay.h" -#ifdef HL2_DLL -#include "hl2_player.h" -#endif -#include "props.h" -#include "vehicle_choreo_generic_shared.h" -#include "ai_utils.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define VEHICLE_HITBOX_DRIVER 1 - -#define CHOREO_VEHICLE_VIEW_FOV 90 -#define CHOREO_VEHICLE_VIEW_YAW_MIN -60 -#define CHOREO_VEHICLE_VIEW_YAW_MAX 60 -#define CHOREO_VEHICLE_VIEW_PITCH_MIN -90 -#define CHOREO_VEHICLE_VIEW_PITCH_MAX 38 - -BEGIN_DATADESC_NO_BASE( vehicleview_t ) - DEFINE_FIELD( bClampEyeAngles, FIELD_BOOLEAN ), - DEFINE_FIELD( flPitchCurveZero, FIELD_FLOAT ), - DEFINE_FIELD( flPitchCurveLinear, FIELD_FLOAT ), - DEFINE_FIELD( flRollCurveZero, FIELD_FLOAT ), - DEFINE_FIELD( flRollCurveLinear, FIELD_FLOAT ), - DEFINE_FIELD( flFOV, FIELD_FLOAT ), - DEFINE_FIELD( flYawMin, FIELD_FLOAT ), - DEFINE_FIELD( flYawMax, FIELD_FLOAT ), - DEFINE_FIELD( flPitchMin, FIELD_FLOAT ), - DEFINE_FIELD( flPitchMax, FIELD_FLOAT ), -END_DATADESC() - -// -// Anim events. -// -enum -{ - AE_CHOREO_VEHICLE_OPEN = 1, - AE_CHOREO_VEHICLE_CLOSE = 2, -}; - - -extern ConVar g_debug_vehicledriver; - - -class CPropVehicleChoreoGeneric; - -/*static const char *pChoreoGenericFollowerBoneNames[] = -{ - "base", -};*/ - - -//----------------------------------------------------------------------------- -// Purpose: A KeyValues parse for vehicle sound blocks -//----------------------------------------------------------------------------- -class CVehicleChoreoViewParser : public IVPhysicsKeyHandler -{ -public: - CVehicleChoreoViewParser( void ); - -private: - virtual void ParseKeyValue( void *pData, const char *pKey, const char *pValue ); - virtual void SetDefaults( void *pData ); -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CChoreoGenericServerVehicle : public CBaseServerVehicle -{ - typedef CBaseServerVehicle BaseClass; - -// IServerVehicle -public: - void GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV = NULL ); - virtual void ItemPostFrame( CBasePlayer *pPlayer ); - -protected: - - CPropVehicleChoreoGeneric *GetVehicle( void ); -}; - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CPropVehicleChoreoGeneric : public CDynamicProp, public IDrivableVehicle -{ - DECLARE_CLASS( CPropVehicleChoreoGeneric, CDynamicProp ); - -public: - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); - - CPropVehicleChoreoGeneric( void ) - { - m_ServerVehicle.SetVehicle( this ); - m_bIgnoreMoveParent = false; - m_bForcePlayerEyePoint = false; - } - - ~CPropVehicleChoreoGeneric( void ) - { - } - - // CBaseEntity - virtual void Precache( void ); - void Spawn( void ); - void Think(void); - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() | FCAP_IMPULSE_USE; }; - virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - virtual void DrawDebugGeometryOverlays( void ); - - virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true ); - virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ); - virtual int OnTakeDamage( const CTakeDamageInfo &info ); - - void PlayerControlInit( CBasePlayer *pPlayer ); - void PlayerControlShutdown( void ); - void ResetUseKey( CBasePlayer *pPlayer ); - - virtual bool OverridePropdata() { return true; } - - bool ParseViewParams( const char *pScriptName ); - - void GetVectors(Vector* pForward, Vector* pRight, Vector* pUp) const; - - bool CreateVPhysics() - { - SetSolid(SOLID_VPHYSICS); - SetMoveType(MOVETYPE_NONE); - return true; - } - bool ShouldForceExit() { return m_bForcedExit; } - void ClearForcedExit() { m_bForcedExit = false; } - - // CBaseAnimating - void HandleAnimEvent( animevent_t *pEvent ); - - // Inputs - void InputEnterVehicleImmediate( inputdata_t &inputdata ); - void InputEnterVehicle( inputdata_t &inputdata ); - void InputExitVehicle( inputdata_t &inputdata ); - void InputLock( inputdata_t &inputdata ); - void InputUnlock( inputdata_t &inputdata ); - void InputOpen( inputdata_t &inputdata ); - void InputClose( inputdata_t &inputdata ); - void InputViewlock( inputdata_t &inputdata ); - - bool ShouldIgnoreParent( void ) { return m_bIgnoreMoveParent; } - - // Tuned to match HL2s definition, but this should probably return false in all cases - virtual bool PassengerShouldReceiveDamage( CTakeDamageInfo &info ) { return (info.GetDamageType() & (DMG_BLAST|DMG_RADIATION)) == 0; } - - CNetworkHandle( CBasePlayer, m_hPlayer ); - - CNetworkVarEmbedded( vehicleview_t, m_vehicleView ); -private: - vehicleview_t m_savedVehicleView; // gets saved out for viewlock/unlock input - -// IDrivableVehicle -public: - - virtual CBaseEntity *GetDriver( void ); - virtual void ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ) { return; } - virtual void FinishMove( CBasePlayer *player, CUserCmd *ucmd, CMoveData *move ) { return; } - virtual bool CanEnterVehicle( CBaseEntity *pEntity ); - virtual bool CanExitVehicle( CBaseEntity *pEntity ); - virtual void SetVehicleEntryAnim( bool bOn ); - virtual void SetVehicleExitAnim( bool bOn, Vector vecEyeExitEndpoint ) { m_bExitAnimOn = bOn; if ( bOn ) m_vecEyeExitEndpoint = vecEyeExitEndpoint; } - virtual void EnterVehicle( CBaseCombatCharacter *pPassenger ); - - virtual bool AllowBlockedExit( CBaseCombatCharacter *pPassenger, int nRole ) { return true; } - virtual bool AllowMidairExit( CBaseCombatCharacter *pPassenger, int nRole ) { return true; } - virtual void PreExitVehicle( CBaseCombatCharacter *pPassenger, int nRole ) {} - virtual void ExitVehicle( int nRole ); - - virtual void ItemPostFrame( CBasePlayer *pPlayer ) {} - virtual void SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) {} - virtual string_t GetVehicleScriptName() { return m_vehicleScript; } - - // If this is a vehicle, returns the vehicle interface - virtual IServerVehicle *GetServerVehicle() { return &m_ServerVehicle; } - - bool ShouldCollide( int collisionGroup, int contentsMask ) const; - - bool m_bForcePlayerEyePoint; // Uses player's eyepoint instead of 'vehicle_driver_eyes' attachment - -protected: - - // Contained IServerVehicle - CChoreoGenericServerVehicle m_ServerVehicle; - -private: - - // Entering / Exiting - bool m_bLocked; - CNetworkVar( bool, m_bEnterAnimOn ); - CNetworkVar( bool, m_bExitAnimOn ); - CNetworkVector( m_vecEyeExitEndpoint ); - bool m_bForcedExit; - bool m_bIgnoreMoveParent; - bool m_bIgnorePlayerCollisions; - - // Vehicle script filename - string_t m_vehicleScript; - - COutputEvent m_playerOn; - COutputEvent m_playerOff; - COutputEvent m_OnOpen; - COutputEvent m_OnClose; -}; - -LINK_ENTITY_TO_CLASS( prop_vehicle_choreo_generic, CPropVehicleChoreoGeneric ); - -BEGIN_DATADESC( CPropVehicleChoreoGeneric ) - - // Inputs - DEFINE_INPUTFUNC( FIELD_VOID, "Lock", InputLock ), - DEFINE_INPUTFUNC( FIELD_VOID, "Unlock", InputUnlock ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnterVehicle", InputEnterVehicle ), - DEFINE_INPUTFUNC( FIELD_VOID, "EnterVehicleImmediate", InputEnterVehicleImmediate ), - DEFINE_INPUTFUNC( FIELD_VOID, "ExitVehicle", InputExitVehicle ), - DEFINE_INPUTFUNC( FIELD_VOID, "Open", InputOpen ), - DEFINE_INPUTFUNC( FIELD_VOID, "Close", InputClose ), - DEFINE_INPUTFUNC( FIELD_BOOLEAN, "Viewlock", InputViewlock ), - - // Keys - DEFINE_EMBEDDED( m_ServerVehicle ), - - DEFINE_FIELD( m_hPlayer, FIELD_EHANDLE ), - DEFINE_FIELD( m_bEnterAnimOn, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bExitAnimOn, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bForcedExit, FIELD_BOOLEAN ), - DEFINE_FIELD( m_vecEyeExitEndpoint, FIELD_POSITION_VECTOR ), - - DEFINE_KEYFIELD( m_vehicleScript, FIELD_STRING, "vehiclescript" ), - DEFINE_KEYFIELD( m_bLocked, FIELD_BOOLEAN, "vehiclelocked" ), - - DEFINE_KEYFIELD( m_bIgnoreMoveParent, FIELD_BOOLEAN, "ignoremoveparent" ), - DEFINE_KEYFIELD( m_bIgnorePlayerCollisions, FIELD_BOOLEAN, "ignoreplayer" ), - DEFINE_KEYFIELD( m_bForcePlayerEyePoint, FIELD_BOOLEAN, "useplayereyes" ), - - DEFINE_OUTPUT( m_playerOn, "PlayerOn" ), - DEFINE_OUTPUT( m_playerOff, "PlayerOff" ), - DEFINE_OUTPUT( m_OnOpen, "OnOpen" ), - DEFINE_OUTPUT( m_OnClose, "OnClose" ), - - DEFINE_EMBEDDED( m_vehicleView ), - DEFINE_EMBEDDED( m_savedVehicleView ), - -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST(CPropVehicleChoreoGeneric, DT_PropVehicleChoreoGeneric) - SendPropEHandle(SENDINFO(m_hPlayer)), - SendPropBool(SENDINFO(m_bEnterAnimOn)), - SendPropBool(SENDINFO(m_bExitAnimOn)), - SendPropVector(SENDINFO(m_vecEyeExitEndpoint), -1, SPROP_COORD), - SendPropBool( SENDINFO_STRUCTELEM( m_vehicleView.bClampEyeAngles ) ), - SendPropFloat( SENDINFO_STRUCTELEM( m_vehicleView.flPitchCurveZero ) ), - SendPropFloat( SENDINFO_STRUCTELEM( m_vehicleView.flPitchCurveLinear ) ), - SendPropFloat( SENDINFO_STRUCTELEM( m_vehicleView.flRollCurveZero ) ), - SendPropFloat( SENDINFO_STRUCTELEM( m_vehicleView.flRollCurveLinear ) ), - SendPropFloat( SENDINFO_STRUCTELEM( m_vehicleView.flFOV ) ), - SendPropFloat( SENDINFO_STRUCTELEM( m_vehicleView.flYawMin ) ), - SendPropFloat( SENDINFO_STRUCTELEM( m_vehicleView.flYawMax ) ), - SendPropFloat( SENDINFO_STRUCTELEM( m_vehicleView.flPitchMin ) ), - SendPropFloat( SENDINFO_STRUCTELEM( m_vehicleView.flPitchMax ) ), -END_SEND_TABLE(); - - -bool ShouldVehicleIgnoreEntity( CBaseEntity *pVehicle, CBaseEntity *pCollide ) -{ - if ( pCollide->GetParent() == pVehicle ) - return true; - - CPropVehicleChoreoGeneric *pChoreoVehicle = dynamic_cast ( pVehicle ); - - if ( pChoreoVehicle == NULL ) - return false; - - if ( pCollide == NULL ) - return false; - - if ( pChoreoVehicle->ShouldIgnoreParent() == false ) - return false; - - if ( pChoreoVehicle->GetMoveParent() == pCollide ) - return true; - - return false; -} - - -//------------------------------------------------ -// Precache -//------------------------------------------------ -void CPropVehicleChoreoGeneric::Precache( void ) -{ - BaseClass::Precache(); - - m_ServerVehicle.Initialize( STRING(m_vehicleScript) ); - m_ServerVehicle.UseLegacyExitChecks( true ); -} - - -//------------------------------------------------ -// Spawn -//------------------------------------------------ -void CPropVehicleChoreoGeneric::Spawn( void ) -{ - Precache(); - SetModel( STRING( GetModelName() ) ); - SetCollisionGroup( COLLISION_GROUP_VEHICLE ); - - if ( GetSolid() != SOLID_NONE ) - { - BaseClass::Spawn(); - } - - m_takedamage = DAMAGE_EVENTS_ONLY; - - SetNextThink( gpGlobals->curtime ); - - ParseViewParams( STRING(m_vehicleScript) ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleChoreoGeneric::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - if ( ptr->hitbox == VEHICLE_HITBOX_DRIVER ) - { - if ( m_hPlayer != NULL ) - { - m_hPlayer->TakeDamage( info ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CPropVehicleChoreoGeneric::OnTakeDamage( const CTakeDamageInfo &inputInfo ) -{ - CTakeDamageInfo info = inputInfo; - info.ScaleDamage( 25 ); - - // reset the damage - info.SetDamage( inputInfo.GetDamage() ); - - // Check to do damage to prisoner - if ( m_hPlayer != NULL ) - { - // Take no damage from physics damages - if ( info.GetDamageType() & DMG_CRUSH ) - return 0; - - // Take the damage - m_hPlayer->TakeDamage( info ); - } - - return 0; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -Vector CPropVehicleChoreoGeneric::BodyTarget( const Vector &posSrc, bool bNoisy ) -{ - Vector shotPos; - - int eyeAttachmentIndex = LookupAttachment("vehicle_driver_eyes"); - GetAttachment( eyeAttachmentIndex, shotPos ); - - if ( bNoisy ) - { - shotPos[0] += random->RandomFloat( -8.0f, 8.0f ); - shotPos[1] += random->RandomFloat( -8.0f, 8.0f ); - shotPos[2] += random->RandomFloat( -8.0f, 8.0f ); - } - - return shotPos; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleChoreoGeneric::Think(void) -{ - SetNextThink( gpGlobals->curtime + 0.1 ); - - if ( GetDriver() ) - { - BaseClass::Think(); - - // If the enter or exit animation has finished, tell the server vehicle - if ( IsSequenceFinished() && (m_bExitAnimOn || m_bEnterAnimOn) ) - { - GetServerVehicle()->HandleEntryExitFinish( m_bExitAnimOn, true ); - } - } - - StudioFrameAdvance(); - DispatchAnimEvents( this ); -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CPropVehicleChoreoGeneric::InputOpen( inputdata_t &inputdata ) -{ - int nSequence = LookupSequence( "open" ); - - // Set to the desired anim, or default anim if the desired is not present - if ( nSequence > ACTIVITY_NOT_AVAILABLE ) - { - SetCycle( 0 ); - m_flAnimTime = gpGlobals->curtime; - ResetSequence( nSequence ); - ResetClientsideFrame(); - } - else - { - // Not available try to get default anim - Msg( "Choreo Generic Vehicle %s: missing open sequence\n", GetDebugName() ); - SetSequence( 0 ); - } -} - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CPropVehicleChoreoGeneric::InputClose( inputdata_t &inputdata ) -{ - if ( m_bLocked || m_bEnterAnimOn ) - return; - - int nSequence = LookupSequence( "close" ); - - // Set to the desired anim, or default anim if the desired is not present - if ( nSequence > ACTIVITY_NOT_AVAILABLE ) - { - SetCycle( 0 ); - m_flAnimTime = gpGlobals->curtime; - ResetSequence( nSequence ); - ResetClientsideFrame(); - } - else - { - // Not available try to get default anim - Msg( "Choreo Generic Vehicle %s: missing close sequence\n", GetDebugName() ); - SetSequence( 0 ); - } -} - - - -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CPropVehicleChoreoGeneric::InputViewlock( inputdata_t &inputdata ) -{ - if (inputdata.value.Bool()) // lock - { - if (m_savedVehicleView.flFOV == 0) // not already locked - { - m_savedVehicleView = m_vehicleView; - m_vehicleView.flYawMax = m_vehicleView.flYawMin = m_vehicleView.flPitchMin = m_vehicleView.flPitchMax = 0.0f; - } - } - else - { //unlock - Assert(m_savedVehicleView.flFOV); // is nonzero if something is saved, is zero if nothing was saved. - if (m_savedVehicleView.flFOV) - { - // m_vehicleView = m_savedVehicleView; - m_savedVehicleView.flFOV = 0; - - - m_vehicleView.flYawMax.Set( m_savedVehicleView.flYawMax); - m_vehicleView.flYawMin.Set( m_savedVehicleView.flYawMin); - m_vehicleView.flPitchMin.Set(m_savedVehicleView.flPitchMin); - m_vehicleView.flPitchMax.Set(m_savedVehicleView.flPitchMax); - - /* // note: the straight assignments, as in the lower two lines below, do not call the = overload and thus are never transmitted! - m_vehicleView.flYawMax = 50; // m_savedVehicleView.flYawMax; - m_vehicleView.flYawMin = -50; // m_savedVehicleView.flYawMin; - m_vehicleView.flPitchMin = m_savedVehicleView.flPitchMin; - m_vehicleView.flPitchMax = m_savedVehicleView.flPitchMax; - */ - } - } -} - - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleChoreoGeneric::HandleAnimEvent( animevent_t *pEvent ) -{ - if ( pEvent->event == AE_CHOREO_VEHICLE_OPEN ) - { - m_OnOpen.FireOutput( this, this ); - m_bLocked = false; - } - else if ( pEvent->event == AE_CHOREO_VEHICLE_CLOSE ) - { - m_OnClose.FireOutput( this, this ); - m_bLocked = true; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleChoreoGeneric::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - CBasePlayer *pPlayer = ToBasePlayer( pActivator ); - if ( !pPlayer ) - return; - - ResetUseKey( pPlayer ); - - GetServerVehicle()->HandlePassengerEntry( pPlayer, (value > 0) ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Return true of the player's allowed to enter / exit the vehicle -//----------------------------------------------------------------------------- -bool CPropVehicleChoreoGeneric::CanEnterVehicle( CBaseEntity *pEntity ) -{ - // Prevent entering if the vehicle's being driven by an NPC - if ( GetDriver() && GetDriver() != pEntity ) - return false; - - // Prevent entering if the vehicle's locked - return !m_bLocked; -} - - -//----------------------------------------------------------------------------- -// Purpose: Return true of the player is allowed to exit the vehicle. -//----------------------------------------------------------------------------- -bool CPropVehicleChoreoGeneric::CanExitVehicle( CBaseEntity *pEntity ) -{ - // Prevent exiting if the vehicle's locked, rotating, or playing an entry/exit anim. - return ( !m_bLocked && (GetLocalAngularVelocity() == vec3_angle) && !m_bEnterAnimOn && !m_bExitAnimOn ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Override base class to add display -//----------------------------------------------------------------------------- -void CPropVehicleChoreoGeneric::DrawDebugGeometryOverlays(void) -{ - // Draw if BBOX is on - if ( m_debugOverlays & OVERLAY_BBOX_BIT ) - { - } - - BaseClass::DrawDebugGeometryOverlays(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleChoreoGeneric::EnterVehicle( CBaseCombatCharacter *pPassenger ) -{ - if ( pPassenger == NULL ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( pPassenger ); - if ( pPlayer != NULL ) - { - // Remove any player who may be in the vehicle at the moment - if ( m_hPlayer ) - { - ExitVehicle( VEHICLE_ROLE_DRIVER ); - } - - m_hPlayer = pPlayer; - m_playerOn.FireOutput( pPlayer, this, 0 ); - - m_ServerVehicle.SoundStart(); - } - else - { - // NPCs not supported yet - jdw - Assert( 0 ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleChoreoGeneric::SetVehicleEntryAnim( bool bOn ) -{ - m_bEnterAnimOn = bOn; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleChoreoGeneric::ExitVehicle( int nRole ) -{ - CBasePlayer *pPlayer = m_hPlayer; - if ( !pPlayer ) - return; - - m_hPlayer = NULL; - ResetUseKey( pPlayer ); - - m_playerOff.FireOutput( pPlayer, this, 0 ); - m_bEnterAnimOn = false; - - m_ServerVehicle.SoundShutdown( 1.0 ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropVehicleChoreoGeneric::ResetUseKey( CBasePlayer *pPlayer ) -{ - pPlayer->m_afButtonPressed &= ~IN_USE; -} - - -//----------------------------------------------------------------------------- -// Purpose: Vehicles are permanently oriented off angle for vphysics. -//----------------------------------------------------------------------------- -void CPropVehicleChoreoGeneric::GetVectors(Vector* pForward, Vector* pRight, Vector* pUp) const -{ - // This call is necessary to cause m_rgflCoordinateFrame to be recomputed - const matrix3x4_t &entityToWorld = EntityToWorldTransform(); - - if (pForward != NULL) - { - MatrixGetColumn( entityToWorld, 1, *pForward ); - } - - if (pRight != NULL) - { - MatrixGetColumn( entityToWorld, 0, *pRight ); - } - - if (pUp != NULL) - { - MatrixGetColumn( entityToWorld, 2, *pUp ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseEntity *CPropVehicleChoreoGeneric::GetDriver( void ) -{ - return m_hPlayer; -} - -//----------------------------------------------------------------------------- -// Purpose: Prevent the player from entering / exiting the vehicle -//----------------------------------------------------------------------------- -void CPropVehicleChoreoGeneric::InputLock( inputdata_t &inputdata ) -{ - m_bLocked = true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Allow the player to enter / exit the vehicle -//----------------------------------------------------------------------------- -void CPropVehicleChoreoGeneric::InputUnlock( inputdata_t &inputdata ) -{ - m_bLocked = false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Force the player to enter the vehicle. -//----------------------------------------------------------------------------- -void CPropVehicleChoreoGeneric::InputEnterVehicle( inputdata_t &inputdata ) -{ - if ( m_bEnterAnimOn ) - return; - - // Try the activator first & use them if they are a player. - CBasePlayer *pPlayer = ToBasePlayer( inputdata.pActivator ); - if ( pPlayer == NULL ) - { - // Activator was not a player, just grab the single-player player. - pPlayer = AI_GetSinglePlayer(); - if ( pPlayer == NULL ) - return; - } - - // Force us to drop anything we're holding - pPlayer->ForceDropOfCarriedPhysObjects(); - - // FIXME: I hate code like this. I should really add a parameter to HandlePassengerEntry - // to allow entry into locked vehicles - bool bWasLocked = m_bLocked; - m_bLocked = false; - GetServerVehicle()->HandlePassengerEntry( pPlayer, true ); - m_bLocked = bWasLocked; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CPropVehicleChoreoGeneric::InputEnterVehicleImmediate( inputdata_t &inputdata ) -{ - if ( m_bEnterAnimOn ) - return; - - // Try the activator first & use them if they are a player. - CBasePlayer *pPlayer = ToBasePlayer( inputdata.pActivator ); - if ( pPlayer == NULL ) - { - // Activator was not a player, just grab the singleplayer player. - pPlayer = AI_GetSinglePlayer(); - if ( pPlayer == NULL ) - return; - } - - if ( pPlayer->IsInAVehicle() ) - { - // Force the player out of whatever vehicle they are in. - pPlayer->LeaveVehicle(); - } - - // Force us to drop anything we're holding - pPlayer->ForceDropOfCarriedPhysObjects(); - - pPlayer->GetInVehicle( GetServerVehicle(), VEHICLE_ROLE_DRIVER ); -} - -//----------------------------------------------------------------------------- -// Purpose: Force the player to exit the vehicle. -//----------------------------------------------------------------------------- -void CPropVehicleChoreoGeneric::InputExitVehicle( inputdata_t &inputdata ) -{ - m_bForcedExit = true; -} - -//----------------------------------------------------------------------------- -// Purpose: Parses the vehicle's script for the vehicle view parameters -//----------------------------------------------------------------------------- -bool CPropVehicleChoreoGeneric::ParseViewParams( const char *pScriptName ) -{ - byte *pFile = UTIL_LoadFileForMe( pScriptName, NULL ); - if ( !pFile ) - return false; - - IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( (char *)pFile ); - CVehicleChoreoViewParser viewParser; - while ( !pParse->Finished() ) - { - const char *pBlock = pParse->GetCurrentBlockName(); - if ( !strcmpi( pBlock, "vehicle_view" ) ) - { - pParse->ParseCustom( &m_vehicleView, &viewParser ); - } - else - { - pParse->SkipBlock(); - } - } - physcollision->VPhysicsKeyParserDestroy( pParse ); - UTIL_FreeFile( pFile ); - - Precache(); - - return true; -} - -//======================================================================================================================================== -// CRANE VEHICLE SERVER VEHICLE -//======================================================================================================================================== -CPropVehicleChoreoGeneric *CChoreoGenericServerVehicle::GetVehicle( void ) -{ - return (CPropVehicleChoreoGeneric *)GetDrivableVehicle(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pPlayer - -//----------------------------------------------------------------------------- -void CChoreoGenericServerVehicle::ItemPostFrame( CBasePlayer *player ) -{ - Assert( player == GetDriver() ); - - GetDrivableVehicle()->ItemPostFrame( player ); - - if (( player->m_afButtonPressed & IN_USE ) || GetVehicle()->ShouldForceExit() ) - { - GetVehicle()->ClearForcedExit(); - if ( GetDrivableVehicle()->CanExitVehicle(player) ) - { - // Let the vehicle try to play the exit animation - if ( !HandlePassengerExit( player ) && ( player != NULL ) ) - { - player->PlayUseDenySound(); - } - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoGenericServerVehicle::GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV /*= NULL*/ ) -{ - // FIXME: This needs to be reconciled with the other versions of this function! - Assert( nRole == VEHICLE_ROLE_DRIVER ); - CBasePlayer *pPlayer = ToBasePlayer( GetDrivableVehicle()->GetDriver() ); - Assert( pPlayer ); - - // Use the player's eyes instead of the attachment point - if ( GetVehicle()->m_bForcePlayerEyePoint ) - { - // Call to BaseClass because CBasePlayer::EyePosition calls this function. - *pAbsOrigin = pPlayer->BaseClass::EyePosition(); - *pAbsAngles = pPlayer->BaseClass::EyeAngles(); - return; - } - - *pAbsAngles = pPlayer->EyeAngles(); // yuck. this is an in/out parameter. - - float flPitchFactor = 1.0; - matrix3x4_t vehicleEyePosToWorld; - Vector vehicleEyeOrigin; - QAngle vehicleEyeAngles; - GetVehicle()->GetAttachment( "vehicle_driver_eyes", vehicleEyeOrigin, vehicleEyeAngles ); - AngleMatrix( vehicleEyeAngles, vehicleEyePosToWorld ); - - // Compute the relative rotation between the unperterbed eye attachment + the eye angles - matrix3x4_t cameraToWorld; - AngleMatrix( *pAbsAngles, cameraToWorld ); - - matrix3x4_t worldToEyePos; - MatrixInvert( vehicleEyePosToWorld, worldToEyePos ); - - matrix3x4_t vehicleCameraToEyePos; - ConcatTransforms( worldToEyePos, cameraToWorld, vehicleCameraToEyePos ); - - // Now perterb the attachment point - vehicleEyeAngles.x = RemapAngleRange( PITCH_CURVE_ZERO * flPitchFactor, PITCH_CURVE_LINEAR, vehicleEyeAngles.x ); - vehicleEyeAngles.z = RemapAngleRange( ROLL_CURVE_ZERO * flPitchFactor, ROLL_CURVE_LINEAR, vehicleEyeAngles.z ); - - AngleMatrix( vehicleEyeAngles, vehicleEyeOrigin, vehicleEyePosToWorld ); - - // Now treat the relative eye angles as being relative to this new, perterbed view position... - matrix3x4_t newCameraToWorld; - ConcatTransforms( vehicleEyePosToWorld, vehicleCameraToEyePos, newCameraToWorld ); - - // output new view abs angles - MatrixAngles( newCameraToWorld, *pAbsAngles ); - - // UNDONE: *pOrigin would already be correct in single player if the HandleView() on the server ran after vphysics - MatrixGetColumn( newCameraToWorld, 3, *pAbsOrigin ); -} - -bool CPropVehicleChoreoGeneric::ShouldCollide( int collisionGroup, int contentsMask ) const -{ - if ( m_bIgnorePlayerCollisions == true ) - { - if ( collisionGroup == COLLISION_GROUP_PLAYER || collisionGroup == COLLISION_GROUP_PLAYER_MOVEMENT ) - return false; - } - - return BaseClass::ShouldCollide( collisionGroup, contentsMask ); -} - - -CVehicleChoreoViewParser::CVehicleChoreoViewParser( void ) -{ - -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CVehicleChoreoViewParser::ParseKeyValue( void *pData, const char *pKey, const char *pValue ) -{ - vehicleview_t *pView = (vehicleview_t *)pData; - // New gear? - if ( !strcmpi( pKey, "clamp" ) ) - { - pView->bClampEyeAngles = !!atoi( pValue ); - } - else if ( !strcmpi( pKey, "pitchcurvezero" ) ) - { - pView->flPitchCurveZero = atof( pValue ); - } - else if ( !strcmpi( pKey, "pitchcurvelinear" ) ) - { - pView->flPitchCurveLinear = atof( pValue ); - } - else if ( !strcmpi( pKey, "rollcurvezero" ) ) - { - pView->flRollCurveZero = atof( pValue ); - } - else if ( !strcmpi( pKey, "rollcurvelinear" ) ) - { - pView->flRollCurveLinear = atof( pValue ); - } - else if ( !strcmpi( pKey, "yawmin" ) ) - { - pView->flYawMin = atof( pValue ); - } - else if ( !strcmpi( pKey, "yawmax" ) ) - { - pView->flYawMax = atof( pValue ); - } - else if ( !strcmpi( pKey, "pitchmin" ) ) - { - pView->flPitchMin = atof( pValue ); - } - else if ( !strcmpi( pKey, "pitchmax" ) ) - { - pView->flPitchMax = atof( pValue ); - } - else if ( !strcmpi( pKey, "fov" ) ) - { - pView->flFOV = atof( pValue ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CVehicleChoreoViewParser::SetDefaults( void *pData ) -{ - vehicleview_t *pView = (vehicleview_t *)pData; - - pView->bClampEyeAngles = true; - - pView->flPitchCurveZero = PITCH_CURVE_ZERO; - pView->flPitchCurveLinear = PITCH_CURVE_LINEAR; - pView->flRollCurveZero = ROLL_CURVE_ZERO; - pView->flRollCurveLinear = ROLL_CURVE_LINEAR; - pView->flFOV = CHOREO_VEHICLE_VIEW_FOV; - pView->flYawMin = CHOREO_VEHICLE_VIEW_YAW_MIN; - pView->flYawMax = CHOREO_VEHICLE_VIEW_YAW_MAX; - pView->flPitchMin = CHOREO_VEHICLE_VIEW_PITCH_MIN; - pView->flPitchMax = CHOREO_VEHICLE_VIEW_PITCH_MAX; - -} diff --git a/game/server/vehicle_sounds.h b/game/server/vehicle_sounds.h deleted file mode 100644 index d5472d7c9..000000000 --- a/game/server/vehicle_sounds.h +++ /dev/null @@ -1,137 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef VEHICLE_SOUNDS_H -#define VEHICLE_SOUNDS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "vcollide_parse.h" - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -enum vehiclesound -{ - VS_SKID_FRICTION_LOW, - VS_SKID_FRICTION_NORMAL, - VS_SKID_FRICTION_HIGH, - VS_ENGINE2_START, - VS_ENGINE2_STOP, - VS_MISC1, - VS_MISC2, - VS_MISC3, - VS_MISC4, - - VS_NUM_SOUNDS, -}; - -extern const char *vehiclesound_parsenames[VS_NUM_SOUNDS]; - -// This is a list of vehiclesounds to automatically stop when the vehicle's driver exits the vehicle -#define NUM_SOUNDS_TO_STOP_ON_EXIT 4 -extern vehiclesound g_iSoundsToStopOnExit[NUM_SOUNDS_TO_STOP_ON_EXIT]; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -struct vehicle_gear_t -{ - DECLARE_DATADESC(); - - float flMinSpeed; - float flMaxSpeed; - float flSpeedApproachFactor; -}; - -struct vehicle_crashsound_t -{ - DECLARE_DATADESC(); - - float flMinSpeed; - float flMinDeltaSpeed; - int gearLimit; - string_t iszCrashSound; -}; - -enum sound_states -{ - SS_NONE = 0, - SS_SHUTDOWN, - SS_SHUTDOWN_WATER, - SS_START_WATER, - SS_START_IDLE, - SS_IDLE, - SS_GEAR_0, - SS_GEAR_1, - SS_GEAR_2, - SS_GEAR_3, - SS_GEAR_4, - SS_SLOWDOWN, - SS_SLOWDOWN_HIGHSPEED, // not a real state, just a slot for state sounds - SS_GEAR_0_RESUME, - SS_GEAR_1_RESUME, - SS_GEAR_2_RESUME, - SS_GEAR_3_RESUME, - SS_GEAR_4_RESUME, - SS_TURBO, - SS_REVERSE, - - SS_NUM_STATES, -}; - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -struct vehiclesounds_t -{ - void Init( void ) - { - pGears.Purge(); - crashSounds.Purge(); - - for ( int i = 0; i < VS_NUM_SOUNDS; i++ ) - { - iszSound[i] = NULL_STRING; - } - - for ( int i = 0; i < SS_NUM_STATES; i++ ) - { - iszStateSounds[i] = NULL_STRING; - minStateTime[i] = 0.0f; - } - } - - DECLARE_DATADESC(); - - CUtlVector pGears; - CUtlVector crashSounds; - string_t iszSound[ VS_NUM_SOUNDS ]; - string_t iszStateSounds[SS_NUM_STATES]; - float minStateTime[SS_NUM_STATES]; -}; - -//----------------------------------------------------------------------------- -// Purpose: A KeyValues parse for vehicle sound blocks -//----------------------------------------------------------------------------- -class CVehicleSoundsParser : public IVPhysicsKeyHandler -{ -public: - CVehicleSoundsParser( void ); - - virtual void ParseKeyValue( void *pData, const char *pKey, const char *pValue ); - virtual void SetDefaults( void *pData ); - -private: - // Index of the gear we're currently reading data into - int m_iCurrentGear; - int m_iCurrentState; - int m_iCurrentCrashSound; -}; - -#endif // VEHICLE_SOUNDS_H diff --git a/game/server/vguiscreen.cpp b/game/server/vguiscreen.cpp deleted file mode 100644 index db48fadb8..000000000 --- a/game/server/vguiscreen.cpp +++ /dev/null @@ -1,419 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: This is an entity that represents a vgui screen -// -// $NoKeywords: $ -//===========================================================================// - -#include "cbase.h" -#include "vguiscreen.h" -#include "networkstringtable_gamedll.h" -#include "saverestore_stringtable.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// This is an entity that represents a vgui screen -//----------------------------------------------------------------------------- - -IMPLEMENT_SERVERCLASS_ST(CVGuiScreen, DT_VGuiScreen) - SendPropFloat(SENDINFO(m_flWidth), 0, SPROP_NOSCALE ), - SendPropFloat(SENDINFO(m_flHeight), 0, SPROP_NOSCALE ), - SendPropInt(SENDINFO(m_nAttachmentIndex), 5, SPROP_UNSIGNED ), - SendPropInt(SENDINFO(m_nPanelName), MAX_VGUI_SCREEN_STRING_BITS, SPROP_UNSIGNED ), - SendPropInt(SENDINFO(m_fScreenFlags), VGUI_SCREEN_MAX_BITS, SPROP_UNSIGNED ), - SendPropInt(SENDINFO(m_nOverlayMaterial), MAX_MATERIAL_STRING_BITS, SPROP_UNSIGNED ), - SendPropEHandle(SENDINFO(m_hPlayerOwner)), -END_SEND_TABLE(); - -LINK_ENTITY_TO_CLASS( vgui_screen, CVGuiScreen ); -LINK_ENTITY_TO_CLASS( vgui_screen_team, CVGuiScreen ); -PRECACHE_REGISTER( vgui_screen ); - - -//----------------------------------------------------------------------------- -// Save/load -//----------------------------------------------------------------------------- -BEGIN_DATADESC( CVGuiScreen ) - - DEFINE_CUSTOM_FIELD( m_nPanelName, &g_VguiScreenStringOps ), - DEFINE_FIELD( m_nAttachmentIndex, FIELD_INTEGER ), -// DEFINE_FIELD( m_nOverlayMaterial, FIELD_INTEGER ), - DEFINE_FIELD( m_fScreenFlags, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_flWidth, FIELD_FLOAT, "width" ), - DEFINE_KEYFIELD( m_flHeight, FIELD_FLOAT, "height" ), - DEFINE_KEYFIELD( m_strOverlayMaterial, FIELD_STRING, "overlaymaterial" ), - DEFINE_FIELD( m_hPlayerOwner, FIELD_EHANDLE ), - - DEFINE_INPUTFUNC( FIELD_VOID, "SetActive", InputSetActive ), - DEFINE_INPUTFUNC( FIELD_VOID, "SetInactive", InputSetInactive ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CVGuiScreen::CVGuiScreen() -{ - m_nOverlayMaterial = OVERLAY_MATERIAL_INVALID_STRING; - m_hPlayerOwner = 0; -} - - -//----------------------------------------------------------------------------- -// Read in worldcraft data... -//----------------------------------------------------------------------------- -bool CVGuiScreen::KeyValue( const char *szKeyName, const char *szValue ) -{ - //!! temp hack, until worldcraft is fixed - // strip the # tokens from (duplicate) key names - char *s = (char *)strchr( szKeyName, '#' ); - if ( s ) - { - *s = '\0'; - } - - if ( FStrEq( szKeyName, "panelname" )) - { - SetPanelName( szValue ); - return true; - } - - // NOTE: Have to do these separate because they set two values instead of one - if( FStrEq( szKeyName, "angles" ) ) - { - Assert( GetMoveParent() == NULL ); - QAngle angles; - UTIL_StringToVector( angles.Base(), szValue ); - - // Because the vgui screen basis is strange (z is front, y is up, x is right) - // we need to rotate the typical basis before applying it - VMatrix mat, rotation, tmp; - MatrixFromAngles( angles, mat ); - MatrixBuildRotationAboutAxis( rotation, Vector( 0, 1, 0 ), 90 ); - MatrixMultiply( mat, rotation, tmp ); - MatrixBuildRotateZ( rotation, 90 ); - MatrixMultiply( tmp, rotation, mat ); - MatrixToAngles( mat, angles ); - SetAbsAngles( angles ); - - return true; - } - - return BaseClass::KeyValue( szKeyName, szValue ); -} - - -//----------------------------------------------------------------------------- -// Precache... -//----------------------------------------------------------------------------- -void CVGuiScreen::Precache() -{ - BaseClass::Precache(); - if ( m_strOverlayMaterial != NULL_STRING ) - { - PrecacheMaterial( STRING(m_strOverlayMaterial) ); - } -} - - -//----------------------------------------------------------------------------- -// Spawn... -//----------------------------------------------------------------------------- -void CVGuiScreen::Spawn() -{ - Precache(); - - // This has no model, but we want it to transmit if it's in the PVS anyways - AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); - m_nAttachmentIndex = 0; - SetSolid( SOLID_OBB ); - AddSolidFlags( FSOLID_NOT_SOLID ); - SetActualSize( m_flWidth, m_flHeight ); - m_fScreenFlags.Set( VGUI_SCREEN_ACTIVE ); - - m_takedamage = DAMAGE_NO; - AddFlag( FL_NOTARGET ); -} - -//----------------------------------------------------------------------------- -// Spawn... -//----------------------------------------------------------------------------- -void CVGuiScreen::Activate() -{ - BaseClass::Activate(); - - if ( m_nOverlayMaterial == OVERLAY_MATERIAL_INVALID_STRING && m_strOverlayMaterial != NULL_STRING ) - { - SetOverlayMaterial( STRING(m_strOverlayMaterial) ); - } -} - -void CVGuiScreen::OnRestore() -{ - UpdateTransmitState(); - - BaseClass::OnRestore(); -} - -void CVGuiScreen::SetAttachmentIndex( int nIndex ) -{ - m_nAttachmentIndex = nIndex; -} - -void CVGuiScreen::SetOverlayMaterial( const char *pMaterial ) -{ - int iMaterial = GetMaterialIndex( pMaterial ); - - if ( iMaterial == 0 ) - { - m_nOverlayMaterial = OVERLAY_MATERIAL_INVALID_STRING; - } - else - { - m_nOverlayMaterial = iMaterial; - } -} - -bool CVGuiScreen::IsActive() const -{ - return (m_fScreenFlags & VGUI_SCREEN_ACTIVE) != 0; -} - -void CVGuiScreen::SetActive( bool bActive ) -{ - if (bActive != IsActive()) - { - if (!bActive) - { - m_fScreenFlags &= ~VGUI_SCREEN_ACTIVE; - } - else - { - m_fScreenFlags.Set( m_fScreenFlags | VGUI_SCREEN_ACTIVE ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CVGuiScreen::IsAttachedToViewModel() const -{ - return (m_fScreenFlags & VGUI_SCREEN_ATTACHED_TO_VIEWMODEL) != 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : bAttached - -//----------------------------------------------------------------------------- -void CVGuiScreen::SetAttachedToViewModel( bool bAttached ) -{ - if (bAttached != IsActive()) - { - if (!bAttached) - { - m_fScreenFlags &= ~VGUI_SCREEN_ATTACHED_TO_VIEWMODEL; - } - else - { - m_fScreenFlags.Set( m_fScreenFlags | VGUI_SCREEN_ATTACHED_TO_VIEWMODEL ); - - // attached screens have different transmit rules - DispatchUpdateTransmitState(); - } - - // attached screens have different transmit rules - DispatchUpdateTransmitState(); - } -} - -void CVGuiScreen::SetTransparency( bool bTransparent ) -{ - if (!bTransparent) - { - m_fScreenFlags &= ~VGUI_SCREEN_TRANSPARENT; - } - else - { - m_fScreenFlags.Set( m_fScreenFlags | VGUI_SCREEN_TRANSPARENT ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CVGuiScreen::InputSetActive( inputdata_t &inputdata ) -{ - SetActive( true ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CVGuiScreen::InputSetInactive( inputdata_t &inputdata ) -{ - SetActive( false ); -} - -bool CVGuiScreen::IsVisibleOnlyToTeammates() const -{ - return (m_fScreenFlags & VGUI_SCREEN_VISIBLE_TO_TEAMMATES) != 0; -} - -void CVGuiScreen::MakeVisibleOnlyToTeammates( bool bActive ) -{ - if (bActive != IsVisibleOnlyToTeammates()) - { - if (!bActive) - { - m_fScreenFlags &= ~VGUI_SCREEN_VISIBLE_TO_TEAMMATES; - } - else - { - m_fScreenFlags.Set( m_fScreenFlags | VGUI_SCREEN_VISIBLE_TO_TEAMMATES ); - } - } -} - -bool CVGuiScreen::IsVisibleToTeam( int nTeam ) -{ - // FIXME: Should this maybe go into a derived class of some sort? - // Don't bother with screens on the wrong team - if ( IsVisibleOnlyToTeammates() && (nTeam > 0) ) - { - // Hmmm... sort of a hack... - CBaseEntity *pOwner = GetOwnerEntity(); - if ( pOwner && (nTeam != pOwner->GetTeamNumber()) ) - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Screens attached to view models only go to client if viewmodel is being sent, too. -// Input : *recipient - -// *pvs - -// clientArea - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -int CVGuiScreen::UpdateTransmitState() -{ - if ( IsAttachedToViewModel() ) - { - // only send to the owner, or someone spectating the owner. - return SetTransmitState( FL_EDICT_FULLCHECK ); - } - else if ( GetMoveParent() ) - { - // Let the parent object trigger the send. This is more efficient than having it call CBaseEntity::ShouldTransmit - // for all the vgui screens in the map. - return SetTransmitState( FL_EDICT_PVSCHECK ); - } - else - { - return BaseClass::UpdateTransmitState(); - } -} - -int CVGuiScreen::ShouldTransmit( const CCheckTransmitInfo *pInfo ) -{ - Assert( IsAttachedToViewModel() ); - - CBaseEntity *pViewModel = GetOwnerEntity(); - - if ( pViewModel ) - { - return pViewModel->ShouldTransmit( pInfo ); - } - - return BaseClass::ShouldTransmit( pInfo ); -} - -//----------------------------------------------------------------------------- -// Convert the panel name into an integer -//----------------------------------------------------------------------------- -void CVGuiScreen::SetPanelName( const char *pPanelName ) -{ - m_nPanelName = g_pStringTableVguiScreen->AddString( CBaseEntity::IsServer(), pPanelName ); -} - -const char *CVGuiScreen::GetPanelName() const -{ - return g_pStringTableVguiScreen->GetString( m_nPanelName ); -} - - -//----------------------------------------------------------------------------- -// Sets the screen size + resolution -//----------------------------------------------------------------------------- -void CVGuiScreen::SetActualSize( float flWidth, float flHeight ) -{ - m_flWidth = flWidth; - m_flHeight = flHeight; - - Vector mins, maxs; - mins.Init( 0.0f, 0.0f, -0.1f ); - maxs.Init( 0.0f, 0.0f, 0.1f ); - if (flWidth > 0) - maxs.x = flWidth; - else - mins.x = flWidth; - if (flHeight > 0) - maxs.y = flHeight; - else - mins.y = flHeight; - - UTIL_SetSize( this, mins, maxs ); -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -void CVGuiScreen::SetPlayerOwner( CBasePlayer *pPlayer, bool bOwnerOnlyInput /* = false */ ) -{ - m_hPlayerOwner = pPlayer; - - if ( bOwnerOnlyInput ) - { - m_fScreenFlags.Set( VGUI_SCREEN_ONLY_USABLE_BY_OWNER ); - } -} - - -//----------------------------------------------------------------------------- -// Precaches a vgui screen -//----------------------------------------------------------------------------- -void PrecacheVGuiScreen( const char *pScreenType ) -{ - g_pStringTableVguiScreen->AddString( CBaseEntity::IsServer(), pScreenType ); -} - - -//----------------------------------------------------------------------------- -// Creates a vgui screen, attaches it to another player -//----------------------------------------------------------------------------- -CVGuiScreen *CreateVGuiScreen( const char *pScreenClassname, const char *pScreenType, CBaseEntity *pAttachedTo, CBaseEntity *pOwner, int nAttachmentIndex ) -{ - Assert( pAttachedTo ); - CVGuiScreen *pScreen = (CVGuiScreen *)CBaseEntity::Create( pScreenClassname, vec3_origin, vec3_angle, pAttachedTo ); - - pScreen->SetPanelName( pScreenType ); - pScreen->FollowEntity( pAttachedTo ); - pScreen->SetOwnerEntity( pOwner ); - pScreen->SetAttachmentIndex( nAttachmentIndex ); - - return pScreen; -} - -void DestroyVGuiScreen( CVGuiScreen *pVGuiScreen ) -{ - if (pVGuiScreen) - { - UTIL_Remove( pVGuiScreen ); - } -} diff --git a/game/server/vguiscreen.h b/game/server/vguiscreen.h deleted file mode 100644 index 956b817a2..000000000 --- a/game/server/vguiscreen.h +++ /dev/null @@ -1,88 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: This is an entity that represents a vgui screen -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef VGUISCREEN_H -#define VGUISCREEN_H - -#ifdef _WIN32 -#pragma once -#endif - - -//----------------------------------------------------------------------------- -// This is an entity that represents a vgui screen -//----------------------------------------------------------------------------- -class CVGuiScreen : public CBaseEntity -{ -public: - DECLARE_CLASS( CVGuiScreen, CBaseEntity ); - - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - CVGuiScreen(); - - virtual void Precache(); - virtual bool KeyValue( const char *szKeyName, const char *szValue ); - virtual void Spawn(); - virtual void Activate(); - virtual void OnRestore(); - - const char *GetPanelName() const; - - // Sets the screen size + resolution - void SetActualSize( float flWidth, float flHeight ); - - // Activates/deactivates the screen - bool IsActive() const; - void SetActive( bool bActive ); - - // Is this screen only visible to teammates? - bool IsVisibleOnlyToTeammates() const; - void MakeVisibleOnlyToTeammates( bool bActive ); - bool IsVisibleToTeam( int nTeam ); - - // Sets the overlay material - void SetOverlayMaterial( const char *pMaterial ); - - void SetAttachedToViewModel( bool bAttached ); - bool IsAttachedToViewModel() const; - - void SetTransparency( bool bTransparent ); - - virtual int UpdateTransmitState( void ); - virtual int ShouldTransmit( const CCheckTransmitInfo *pInfo ); - - void SetPlayerOwner( CBasePlayer *pPlayer, bool bOwnerOnlyInput = false ); - -private: - void SetAttachmentIndex( int nIndex ); - void SetPanelName( const char *pPanelName ); - void InputSetActive( inputdata_t &inputdata ); - void InputSetInactive( inputdata_t &inputdata ); - - string_t m_strOverlayMaterial; - - CNetworkVar( float, m_flWidth ); - CNetworkVar( float, m_flHeight ); - CNetworkVar( int, m_nPanelName ); // The name of the panel - CNetworkVar( int, m_nAttachmentIndex ); - CNetworkVar( int, m_nOverlayMaterial ); - CNetworkVar( int, m_fScreenFlags ); - CNetworkVar( EHANDLE, m_hPlayerOwner ); - - friend CVGuiScreen *CreateVGuiScreen( const char *pScreenClassname, const char *pScreenType, CBaseEntity *pAttachedTo, CBaseEntity *pOwner, int nAttachmentIndex ); -}; - - -void PrecacheVGuiScreen( const char *pScreenType ); -void PrecacheVGuiScreenOverlayMaterial( const char *pMaterialName ); -CVGuiScreen *CreateVGuiScreen( const char *pScreenClassname, const char *pScreenType, CBaseEntity *pAttachedTo, CBaseEntity *pOwner, int nAttachmentIndex ); -void DestroyVGuiScreen( CVGuiScreen *pVGuiScreen ); - - -#endif // VGUISCREEN_H diff --git a/game/server/waterbullet.cpp b/game/server/waterbullet.cpp deleted file mode 100644 index 8c16b54bb..000000000 --- a/game/server/waterbullet.cpp +++ /dev/null @@ -1,107 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: An effect for a single bullet passing through a body of water. -// The slug quickly decelerates, leaving a trail of bubbles behind it. -// -// TODO: make clientside -// -//=============================================================================// -#include "cbase.h" -#include "waterbullet.h" -#include "ndebugoverlay.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define WATERBULLET_INITIAL_SPEED 1000.0 -#define WATERBULLET_STOP_TIME 0.5 // how long it takes a bullet in water to come to a stop! - -#define WATERBULLET_DECAY ( WATERBULLET_INITIAL_SPEED / WATERBULLET_STOP_TIME ) - -BEGIN_DATADESC( CWaterBullet ) - - // Function Pointers - DEFINE_FUNCTION( Touch ), - DEFINE_FUNCTION( BulletThink ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( waterbullet, CWaterBullet ); - -IMPLEMENT_SERVERCLASS_ST( CWaterBullet, DT_WaterBullet ) -END_SEND_TABLE() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWaterBullet::Precache() -{ - PrecacheModel( "models/weapons/w_bullet.mdl" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWaterBullet::Spawn( const Vector &vecOrigin, const Vector &vecDir ) -{ - Precache(); - - SetSolid( SOLID_BBOX ); - SetModel( "models/weapons/w_bullet.mdl" ); - UTIL_SetSize( this, vec3_origin, vec3_origin ); - - SetMoveType( MOVETYPE_FLY ); - - SetGravity( 0.0 ); - - QAngle angles; - SetAbsOrigin( vecOrigin ); - - SetAbsVelocity( vecDir * 1500.0f ); - VectorAngles( GetAbsVelocity(), angles ); - SetAbsAngles( angles ); - - SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - SetTouch( &CWaterBullet::Touch ); - - SetThink( &CWaterBullet::BulletThink ); - SetNextThink( gpGlobals->curtime ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CWaterBullet::BulletThink() -{ - //NDebugOverlay::Line( GetAbsOrigin(), GetAbsOrigin() - GetAbsVelocity() * 0.1, 255, 255, 255, false, 1 ); - SetNextThink( gpGlobals->curtime + 0.05 ); - -/* - QAngle angles = GetAbsAngles(); - angles.x += random->RandomInt( -6, 6 ); - angles.y += random->RandomInt( -6, 6 ); - SetAbsAngles( angles ); -*/ - - Vector forward; - AngleVectors( GetAbsAngles(), &forward ); - SetAbsVelocity( forward * 1500.0f ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWaterBullet::Touch( CBaseEntity *pOther ) -{ - Vector vecDir = GetAbsVelocity(); - float speed = VectorNormalize( vecDir ); - - Vector vecStart = GetAbsOrigin() - ( vecDir * 8 ); - Vector vecEnd = GetAbsOrigin() + ( vecDir * speed ); - - trace_t tr; - UTIL_TraceLine( vecStart, vecEnd, MASK_SHOT, NULL, &tr ); - UTIL_ImpactTrace( &tr, DMG_BULLET ); - - UTIL_Remove( this ); -} diff --git a/game/server/waterbullet.h b/game/server/waterbullet.h deleted file mode 100644 index 36eb3706c..000000000 --- a/game/server/waterbullet.h +++ /dev/null @@ -1,31 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Entity that simulates bullets that are underwater. -// -//=============================================================================// - -#ifndef WEAPON_WATERBULLET_H -#define WEAPON_WATERBULLET_H -#ifdef _WIN32 -#pragma once -#endif - -#define WATER_BULLET_BUBBLES_PER_INCH 0.05f - -//========================================================= -//========================================================= -class CWaterBullet : public CBaseAnimating -{ - DECLARE_CLASS( CWaterBullet, CBaseAnimating ); - -public: - void Precache(); - void Spawn( const Vector &vecOrigin, const Vector &vecDir ); - void Touch( CBaseEntity *pOther ); - void BulletThink(); - - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); -}; - -#endif // WEAPON_WATERBULLET_H diff --git a/game/server/wcedit.cpp b/game/server/wcedit.cpp deleted file mode 100644 index c336ad22b..000000000 --- a/game/server/wcedit.cpp +++ /dev/null @@ -1,831 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Namespace for functions having to do with WC Edit mode -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "mathlib/mathlib.h" -#include "player.h" -#include "wcedit.h" -#include "ai_network.h" -#include "ai_initutils.h" -#include "ai_hull.h" -#include "ai_link.h" -#include "ai_node.h" -#include "ai_dynamiclink.h" -#include "ai_networkmanager.h" -#include "ndebugoverlay.h" -#include "editor_sendcommand.h" -#include "movevars_shared.h" -#include "model_types.h" -// UNDONE: Reduce some dependency here! -#include "physics_prop_ragdoll.h" -#include "items.h" -#include "utlsymbol.h" -#include "physobj.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern CAI_Node* FindPickerAINode( CBasePlayer* pPlayer, NodeType_e nNodeType ); -extern CAI_Link* FindPickerAILink( CBasePlayer* pPlayer ); -extern float GetFloorZ(const Vector &origin); - -//----------------------------------------------------------------------------- -// Purpose: Make sure the version of the map in WC is the same as the map -// that's being edited -// Input : -// Output : -//----------------------------------------------------------------------------- -bool NWCEdit::IsWCVersionValid(void) -{ - int status = Editor_CheckVersion(STRING(gpGlobals->mapname), gpGlobals->mapversion, false); - if (!status) - { - return true; - } - else if (status == Editor_NotRunning) - { - Msg("\nAborting map_edit\nWorldcraft not running...\n\n"); - UTIL_CenterPrintAll( "Worldcraft not running..." ); - engine->ServerCommand("disconnect\n"); - } - else - { - Msg("\nAborting map_edit\nWC/Engine map versions different...\n\n"); - UTIL_CenterPrintAll( "WC/Engine map versions different..." ); - engine->ServerCommand("disconnect\n"); - } - return false; -} - -//------------------------------------------------------------------------------ -// Purpose : Figure out placement position of air nodes form where player is -// looking. Keep distance from player constant but adjust height -// based on viewing angle -// Input : -// Output : -//------------------------------------------------------------------------------ -Vector NWCEdit::AirNodePlacementPosition( void ) -{ - CBasePlayer* pPlayer = UTIL_PlayerByIndex(CBaseEntity::m_nDebugPlayer); - - if (!pPlayer) - { - return vec3_origin; - } - - Vector pForward; - pPlayer->EyeVectors( &pForward ); - - Vector floorVec = pForward; - floorVec.z = 0; - VectorNormalize( floorVec ); - VectorNormalize( pForward ); - - float cosAngle = DotProduct(floorVec,pForward); - - float lookDist = g_pAINetworkManager->GetEditOps()->m_flAirEditDistance/cosAngle; - Vector lookPos = pPlayer->EyePosition()+pForward * lookDist; - - return lookPos; -} - -//----------------------------------------------------------------------------- -// Purpose: For create nodes in wc edit mode -// Input : -// Output : -//----------------------------------------------------------------------------- -void NWCEdit::CreateAINode( CBasePlayer *pPlayer ) -{ - // ------------------------------------------------------------- - // Check that WC is running with the right map version - // ------------------------------------------------------------- - if ( !IsWCVersionValid() || !pPlayer ) - return; - - pPlayer->AddSolidFlags( FSOLID_NOT_SOLID ); - - int hullType = g_pAINetworkManager->GetEditOps()->m_iHullDrawNum; - - // ----------------------------------- - // Get position of node to create - // ----------------------------------- - Vector vNewNodePos = vec3_origin; - bool bPositionValid = false; - if (g_pAINetworkManager->GetEditOps()->m_bAirEditMode) - { - vNewNodePos = NWCEdit::AirNodePlacementPosition(); - - // Make sure we can see the node - trace_t tr; - UTIL_TraceLine(pPlayer->EyePosition(), vNewNodePos, MASK_NPCSOLID_BRUSHONLY, pPlayer, COLLISION_GROUP_NONE, &tr); - if (tr.fraction == 1.0) - { - bPositionValid = true; - } - } - else - { - // Place node by where the player is looking - Vector forward; - pPlayer->EyeVectors( &forward ); - Vector startTrace = pPlayer->EyePosition(); - Vector endTrace = pPlayer->EyePosition() + forward * MAX_TRACE_LENGTH; - trace_t tr; - UTIL_TraceLine(startTrace,endTrace,MASK_NPCSOLID, pPlayer, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction != 1.0) - { - // Raise the end position up off the floor, place the node and drop him down - tr.endpos.z += 48; - vNewNodePos = tr.endpos; - bPositionValid = true; - } - } - - // ------------------------------------------------------------------------------- - // Now check that this is a valid location for the new node bu using test hull - // ------------------------------------------------------------------------------- - if (bPositionValid) - { - CBaseEntity *testHull = (CBaseEntity*)CAI_TestHull::GetTestHull(); - - // Set the size of the test hull - UTIL_SetSize(testHull, NAI_Hull::Mins(hullType), NAI_Hull::Maxs(hullType)); - - // Set origin of test hull - testHull->SetLocalOrigin( vNewNodePos ); - - // ----------------------------------------------------------------------- - // If a ground node, drop to floor and make sure can stand at test postion - // ----------------------------------------------------------------------- - if (!g_pAINetworkManager->GetEditOps()->m_bAirEditMode) - { - UTIL_DropToFloor( testHull, MASK_NPCSOLID ); - vNewNodePos = testHull->GetAbsOrigin(); - CTraceFilterSimple traceFilter( testHull, COLLISION_GROUP_NONE ); - if (!UTIL_CheckBottom(testHull, &traceFilter, sv_stepsize.GetFloat())) - { - CAI_TestHull::ReturnTestHull(); - bPositionValid = false; - goto DoneCreate; - } - } - - // ----------------------------------------------------------------------- - // Make sure hull fits at location by seeing if it can move up a fraction - // ----------------------------------------------------------------------- - Vector vUpBit = testHull->GetAbsOrigin(); - vUpBit.z += 1; - trace_t tr; - UTIL_TraceHull( testHull->GetAbsOrigin(), vUpBit, NAI_Hull::Mins(hullType), - NAI_Hull::Maxs(hullType), MASK_NPCSOLID, testHull, COLLISION_GROUP_NONE, &tr ); - if (tr.startsolid || tr.fraction != 1.0) - { - CAI_TestHull::ReturnTestHull(); - bPositionValid = false; - goto DoneCreate; - } - - // <> Round position till DS fixed WC bug - testHull->SetLocalOrigin( Vector( floor(testHull->GetAbsOrigin().x), - floor(testHull->GetAbsOrigin().y ), floor(testHull->GetAbsOrigin().z) ) ); - - // --------------------------------------- - // Send new node to WC - // --------------------------------------- - int status; - if (g_pAINetworkManager->GetEditOps()->m_bAirEditMode) - { - status = Editor_CreateNode("info_node_air", g_pAINetworkManager->GetEditOps()->m_nNextWCIndex, testHull->GetLocalOrigin().x, testHull->GetLocalOrigin().y, testHull->GetLocalOrigin().z, false); - } - else - { - // Create slightly higher in WC so it can be dropped when its loaded again - Vector origin = testHull->GetLocalOrigin(); - origin.z += 24.0; - testHull->SetLocalOrigin( origin ); - status = Editor_CreateNode("info_node", g_pAINetworkManager->GetEditOps()->m_nNextWCIndex, testHull->GetLocalOrigin().x, testHull->GetLocalOrigin().y, testHull->GetLocalOrigin().z, false); - } - if (status == Editor_BadCommand) - { - Msg( "Worldcraft failed on creation...\n" ); - CAI_TestHull::ReturnTestHull(); - } - else if (status == Editor_OK) - { - // ----------------------- - // Create a new ai node - // ----------------------- - CNodeEnt *pNodeEnt; - if (g_pAINetworkManager->GetEditOps()->m_bAirEditMode) - { - pNodeEnt = (CNodeEnt*)CreateEntityByName("info_node_air"); - } - else - { - pNodeEnt = (CNodeEnt*)CreateEntityByName("info_node"); - } - - // Note this is a new entity being created as part of wc editing - pNodeEnt->SetLocalOrigin( testHull->GetLocalOrigin() ); - CAI_TestHull::ReturnTestHull(); - - pNodeEnt->m_NodeData.nWCNodeID = g_pAINetworkManager->GetEditOps()->m_nNextWCIndex; - - pNodeEnt->m_debugOverlays |= OVERLAY_WC_CHANGE_ENTITY; - pNodeEnt->Spawn(); - } - } - -DoneCreate: - // ---------------------------------------------------------- - // Flash a red box as a warning that the hull won't fit here - // ---------------------------------------------------------- - if (!bPositionValid) - { - NDebugOverlay::Box(vNewNodePos, NAI_Hull::Mins(hullType), NAI_Hull::Maxs(hullType), 255,0,0,0,0.1); - } - - // Restore player collidability - pPlayer->SetSolid( SOLID_BBOX ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void NWCEdit::UndoDestroyAINode(void) -{ - // ------------------------------------------------------------- - // Check that WC is running with the right map version - // ------------------------------------------------------------- - if (!IsWCVersionValid()) - { - return; - } - - if (g_pAINetworkManager->GetEditOps()->m_pLastDeletedNode) - { - Vector nodePos = g_pAINetworkManager->GetEditOps()->m_pLastDeletedNode->GetOrigin(); - - int status; - int nOldWCID = g_pAINetworkManager->GetEditOps()->m_pNodeIndexTable[g_pAINetworkManager->GetEditOps()->m_pLastDeletedNode->GetId()]; - - if (g_pAINetworkManager->GetEditOps()->m_bAirEditMode) - { - status = Editor_CreateNode("info_node_air", nOldWCID, nodePos.x, nodePos.y, nodePos.z, false); - } - else - { - status = Editor_CreateNode("info_node", nOldWCID, nodePos.x, nodePos.y, nodePos.z, false); - } - if (status == Editor_BadCommand) - { - Msg( "Worldcraft failed on creation...\n" ); - } - else if (status == Editor_OK) - { - g_pAINetworkManager->GetEditOps()->m_pLastDeletedNode->SetType( NODE_GROUND ); - //@ tofo g_pAINetworkManager->GetEditOps()->m_pLastDeletedNode->m_pNetwork->BuildNetworkGraph(); - g_pAINetworkManager->BuildNetworkGraph(); - g_pAINetworkManager->GetEditOps()->m_pLastDeletedNode = NULL; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: For destroying nodes in wc edit mode -// Input : -// Output : -//----------------------------------------------------------------------------- -void NWCEdit::DestroyAINode( CBasePlayer *pPlayer ) -{ - // ------------------------------------------------------------- - // Check that WC is running with the right map version - // ------------------------------------------------------------- - if (!IsWCVersionValid()) - { - return; - } - - if (!pPlayer) - { - return; - } - - NodeType_e nNodeType = NODE_GROUND; - if (g_pAINetworkManager->GetEditOps()->m_bAirEditMode) - { - nNodeType = NODE_AIR; - } - - CAI_Node* pAINode = FindPickerAINode(pPlayer, nNodeType); - if (pAINode) - { - int status = Editor_DeleteNode(g_pAINetworkManager->GetEditOps()->m_pNodeIndexTable[pAINode->GetId()], false); - - if (status == Editor_BadCommand) - { - Msg( "Worldcraft failed on deletion...\n" ); - } - else if (status == Editor_OK) - { - // Mark this node as deleted and changed - pAINode->SetType( NODE_DELETED ); - pAINode->m_eNodeInfo |= bits_NODE_WC_CHANGED; - - // Note that network needs to be rebuild - g_pAINetworkManager->GetEditOps()->SetRebuildFlags(); - g_pAINetworkManager->GetEditOps()->m_pLastDeletedNode = pAINode; - - // Now go through at delete any dynamic links that were attached to this node - for (int link = 0; link < pAINode->NumLinks(); link++) - { - int nSrcID = pAINode->GetLinkByIndex(link)->m_iSrcID; - int nDstID = pAINode->GetLinkByIndex(link)->m_iDestID; - if (CAI_DynamicLink::GetDynamicLink(nSrcID, nDstID)) - { - int nWCSrcID = g_pAINetworkManager->GetEditOps()->m_pNodeIndexTable[nSrcID]; - int nWCDstID = g_pAINetworkManager->GetEditOps()->m_pNodeIndexTable[nDstID]; - int status = Editor_DeleteNodeLink(nWCSrcID, nWCDstID); - - if (status == Editor_BadCommand) - { - Msg( "Worldcraft failed on node link deletion...\n" ); - } - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: For restroring links in WC edit mode. This actually means -// destroying links in WC that have been marked as -// Input : -// Output : -//----------------------------------------------------------------------------- -void NWCEdit::CreateAILink( CBasePlayer* pPlayer ) -{ - // ------------------------------------------------------------- - // Check that WC is running with the right map version - // ------------------------------------------------------------- - if (!IsWCVersionValid()) - { - return; - } - - CAI_Link* pAILink = FindPickerAILink(pPlayer); - if (pAILink && (pAILink->m_LinkInfo & bits_LINK_OFF)) - { - int nWCSrcID = g_pAINetworkManager->GetEditOps()->m_pNodeIndexTable[pAILink->m_iSrcID]; - int nWCDstID = g_pAINetworkManager->GetEditOps()->m_pNodeIndexTable[pAILink->m_iDestID]; - int status = Editor_DeleteNodeLink(nWCSrcID, nWCDstID, false); - - if (status == Editor_BadCommand) - { - Msg( "Worldcraft failed on node link creation...\n" ); - } - else if (status == Editor_OK) - { - // Don't actually destroy the dynamic link while editing. Just mark the link - pAILink->m_LinkInfo &= ~bits_LINK_OFF; - - CAI_DynamicLink* pDynamicLink = CAI_DynamicLink::GetDynamicLink(pAILink->m_iSrcID, pAILink->m_iDestID); - UTIL_Remove(pDynamicLink); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: For destroying links in wc edit mode. Actually have to create -// a link in WC that is marked as off -// Input : -// Output : -//----------------------------------------------------------------------------- -void NWCEdit::DestroyAILink( CBasePlayer *pPlayer ) -{ - // ------------------------------------------------------------- - // Check that WC is running with the right map version - // ------------------------------------------------------------- - if (!IsWCVersionValid()) - { - return; - } - - CAI_Link* pAILink = FindPickerAILink(pPlayer); - if (pAILink) - { - int nWCSrcID = g_pAINetworkManager->GetEditOps()->m_pNodeIndexTable[pAILink->m_iSrcID]; - int nWCDstID = g_pAINetworkManager->GetEditOps()->m_pNodeIndexTable[pAILink->m_iDestID]; - int status = Editor_CreateNodeLink(nWCSrcID, nWCDstID, false); - - if (status == Editor_BadCommand) - { - Msg( "Worldcraft failed on node link creation...\n" ); - } - else if (status == Editor_OK) - { - // Create dynamic link and mark the link - CAI_DynamicLink* pNewLink = (CAI_DynamicLink*)CreateEntityByName("info_node_link" );; - pNewLink->m_nSrcID = pAILink->m_iSrcID; - pNewLink->m_nDestID = pAILink->m_iDestID; - pNewLink->m_nLinkState = LINK_OFF; - pAILink->m_LinkInfo |= bits_LINK_OFF; - } - } -} - -Vector *g_EntityPositions = NULL; -QAngle *g_EntityOrientations = NULL; -string_t *g_EntityClassnames = NULL; - -//----------------------------------------------------------------------------- -// Purpose: Saves the entity's position for future communication with Hammer -//----------------------------------------------------------------------------- -void NWCEdit::RememberEntityPosition( CBaseEntity *pEntity ) -{ - if ( !(pEntity->ObjectCaps() & FCAP_WCEDIT_POSITION) ) - return; - - if ( !g_EntityPositions ) - { - g_EntityPositions = new Vector[NUM_ENT_ENTRIES]; - g_EntityOrientations = new QAngle[NUM_ENT_ENTRIES]; - // have to save these too because some entities change the classname on spawn (e.g. prop_physics_override, physics_prop) - g_EntityClassnames = new string_t[NUM_ENT_ENTRIES]; - } - int index = pEntity->entindex(); - g_EntityPositions[index] = pEntity->GetAbsOrigin(); - g_EntityOrientations[index] = pEntity->GetAbsAngles(); - g_EntityClassnames[index] = pEntity->m_iClassname; -} - -//----------------------------------------------------------------------------- -// Purpose: Sends Hammer an update to the current position -//----------------------------------------------------------------------------- -void NWCEdit::UpdateEntityPosition( CBaseEntity *pEntity ) -{ - const Vector &newPos = pEntity->GetAbsOrigin(); - const QAngle &newAng = pEntity->GetAbsAngles(); - - DevMsg( 1, "%s\n origin %f %f %f\n angles %f %f %f\n", pEntity->GetClassname(), newPos.x, newPos.y, newPos.z, newAng.x, newAng.y, newAng.z ); - if ( Ragdoll_IsPropRagdoll(pEntity) ) - { - char tmp[2048]; - Ragdoll_GetAngleOverrideString( tmp, sizeof(tmp), pEntity ); - DevMsg( 1, "pose: %s\n", tmp ); - } - - if ( !(pEntity->ObjectCaps() & FCAP_WCEDIT_POSITION) ) - return; - - // can't do this unless in edit mode - if ( !engine->IsInEditMode() ) - return; - - int entIndex = pEntity->entindex(); - Vector pos = g_EntityPositions[entIndex]; - EditorSendResult_t result = Editor_BadCommand; - const char *pClassname = STRING(g_EntityClassnames[entIndex]); - - if ( pEntity->GetModel() && modelinfo->GetModelType(pEntity->GetModel()) == mod_brush ) - { - QAngle xformAngles; - RotationDelta( g_EntityOrientations[entIndex], newAng, &xformAngles ); - if ( xformAngles.Length() > 1e-4 ) - { - result = Editor_RotateEntity( pClassname, pos.x, pos.y, pos.z, xformAngles ); - } - else - { - // don't call through for an identity rotation, may just increase error - result = Editor_OK; - } - } - else - { - if ( Ragdoll_IsPropRagdoll(pEntity) ) - { - char tmp[2048]; - Ragdoll_GetAngleOverrideString( tmp, sizeof(tmp), pEntity ); - result = Editor_SetKeyValue( pClassname, pos.x, pos.y, pos.z, "angleOverride", tmp ); - if ( result != Editor_OK ) - goto error; - } - result = Editor_SetKeyValue( pClassname, pos.x, pos.y, pos.z, "angles", CFmtStr("%f %f %f", newAng.x, newAng.y, newAng.z) ); - } - if ( result != Editor_OK ) - goto error; - - result = Editor_SetKeyValue( pClassname, pos.x, pos.y, pos.z, "origin", CFmtStr("%f %f %f", newPos.x, newPos.y, newPos.z) ); - if ( result != Editor_OK ) - goto error; - - NDebugOverlay::EntityBounds(pEntity, 0, 255, 0, 0 ,5); - // save the update - RememberEntityPosition( pEntity ); - return; - -error: - NDebugOverlay::EntityBounds(pEntity, 255, 0, 0, 0 ,5); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CC_WC_Create( void ) -{ - // Only allowed in wc_edit_mode - if (engine->IsInEditMode()) - { - CBaseEntity::m_nDebugPlayer = UTIL_GetCommandClientIndex(); - - if (g_pAINetworkManager->GetEditOps()->m_bLinkEditMode) - { - NWCEdit::CreateAILink(UTIL_GetCommandClient()); - } - else - { - NWCEdit::CreateAINode(UTIL_GetCommandClient()); - } - } -} -static ConCommand wc_create("wc_create", CC_WC_Create, "When in WC edit mode, creates a node where the player is looking if a node is allowed at that location for the currently selected hull size (see ai_next_hull)", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CC_WC_Destroy( void ) -{ - // Only allowed in wc_edit_mode - if (engine->IsInEditMode()) - { - CBaseEntity::m_nDebugPlayer = UTIL_GetCommandClientIndex(); - - // UNDONE: For now just deal with info_nodes - //CBaseEntity* pEntity = FindEntity( pEdict, ""); - use when generalize this to any class - //int status = Editor_DeleteEntity("info_node", pEdict->origin.x, pEdict->origin.y, pEdict->origin.z, false); - - if (g_pAINetworkManager->GetEditOps()->m_bLinkEditMode) - { - NWCEdit::DestroyAILink(UTIL_GetCommandClient()); - } - else - { - NWCEdit::DestroyAINode(UTIL_GetCommandClient()); - } - } -} -static ConCommand wc_destroy("wc_destroy", CC_WC_Destroy, "When in WC edit mode, destroys the node that the player is nearest to looking at. (The node will be highlighted by a red box).", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CC_WC_DestroyUndo( void ) -{ - // Only allowed in wc_edit_mode - if (engine->IsInEditMode()) - { - CBaseEntity::m_nDebugPlayer = UTIL_GetCommandClientIndex(); - - NWCEdit::UndoDestroyAINode(); - } -} -static ConCommand wc_destroy_undo("wc_destroy_undo", CC_WC_DestroyUndo, "When in WC edit mode restores the last deleted node", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CC_WC_AirNodeEdit( void ) -{ - // Only allowed in wc_edit_mode - if (engine->IsInEditMode()) - { - // Toggle air edit mode state - if (g_pAINetworkManager->GetEditOps()->m_bAirEditMode) - { - g_pAINetworkManager->GetEditOps()->m_bAirEditMode = false; - } - else - { - g_pAINetworkManager->GetEditOps()->m_bAirEditMode = true; - } - } -} -static ConCommand wc_air_node_edit("wc_air_node_edit", CC_WC_AirNodeEdit, "When in WC edit mode, toggles laying down or air nodes instead of ground nodes", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CC_WC_AirNodeEditFurther( void ) -{ - // Only allowed in wc_edit_mode - if (engine->IsInEditMode() && g_pAINetworkManager->GetEditOps()->m_bAirEditMode) - { - g_pAINetworkManager->GetEditOps()->m_flAirEditDistance += 10.0; - } -} -static ConCommand wc_air_edit_further("wc_air_edit_further", CC_WC_AirNodeEditFurther, "When in WC edit mode and editing air nodes, moves position of air node crosshair and placement location further away from player", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CC_WC_AirNodeEditNearer( void ) -{ - // Only allowed in wc_edit_mode - if (engine->IsInEditMode() && g_pAINetworkManager->GetEditOps()->m_bAirEditMode) - { - g_pAINetworkManager->GetEditOps()->m_flAirEditDistance -= 10.0; - } -} -static ConCommand wc_air_edit_nearer("wc_air_edit_nearer", CC_WC_AirNodeEditNearer, "When in WC edit mode and editing air nodes, moves position of air node crosshair and placement location nearer to from player", FCVAR_CHEAT); - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CC_WC_LinkEdit( void ) -{ - // Only allowed in wc_edit_mode - if (engine->IsInEditMode()) - { - // Toggle air edit mode state - if (g_pAINetworkManager->GetEditOps()->m_bLinkEditMode) - { - g_pAINetworkManager->GetEditOps()->m_bLinkEditMode = false; - } - // Don't allow link mode if graph outdated - else if (!(g_pAINetworkManager->GetEditOps()->m_debugNetOverlays & bits_debugNeedRebuild)) - { - g_pAINetworkManager->GetEditOps()->m_bLinkEditMode = true; - } - } -} -static ConCommand wc_link_edit("wc_link_edit", CC_WC_LinkEdit, 0, FCVAR_CHEAT); - - -/// This is an entity used by the hammer_update_safe_entities command. It allows designers -/// to specify objects that should be ignored. It stores an array of sixteen strings -/// which may correspond to names. Designers may ignore more than sixteen objects by -/// placing more than one of these in a level. -class CWC_UpdateIgnoreList : public CBaseEntity -{ -public: - DECLARE_CLASS( CWC_UpdateIgnoreList, CBaseEntity ); - - enum { MAX_IGNORELIST_NAMES = 16 }; ///< the number of names in the array below - - inline const string_t &GetName( int x ) const { return m_nIgnoredEntityNames[x]; } - -protected: - // the list of names to ignore - string_t m_nIgnoredEntityNames[MAX_IGNORELIST_NAMES]; - -public: - DECLARE_DATADESC(); -}; - - -LINK_ENTITY_TO_CLASS( hammer_updateignorelist, CWC_UpdateIgnoreList ); - -BEGIN_DATADESC( CWC_UpdateIgnoreList ) - - // Be still, classcheck! - //DEFINE_FIELD( m_nIgnoredEntityNames, FIELD_STRING, MAX_IGNORELIST_NAMES ), - - DEFINE_KEYFIELD( m_nIgnoredEntityNames[0], FIELD_STRING, "IgnoredName01" ), - DEFINE_KEYFIELD( m_nIgnoredEntityNames[1], FIELD_STRING, "IgnoredName02" ), - DEFINE_KEYFIELD( m_nIgnoredEntityNames[2], FIELD_STRING, "IgnoredName03" ), - DEFINE_KEYFIELD( m_nIgnoredEntityNames[3], FIELD_STRING, "IgnoredName04" ), - DEFINE_KEYFIELD( m_nIgnoredEntityNames[4], FIELD_STRING, "IgnoredName05" ), - DEFINE_KEYFIELD( m_nIgnoredEntityNames[5], FIELD_STRING, "IgnoredName06" ), - DEFINE_KEYFIELD( m_nIgnoredEntityNames[6], FIELD_STRING, "IgnoredName07" ), - DEFINE_KEYFIELD( m_nIgnoredEntityNames[7], FIELD_STRING, "IgnoredName08" ), - DEFINE_KEYFIELD( m_nIgnoredEntityNames[8], FIELD_STRING, "IgnoredName09" ), - DEFINE_KEYFIELD( m_nIgnoredEntityNames[9], FIELD_STRING, "IgnoredName10" ), - DEFINE_KEYFIELD( m_nIgnoredEntityNames[10], FIELD_STRING, "IgnoredName11" ), - DEFINE_KEYFIELD( m_nIgnoredEntityNames[11], FIELD_STRING, "IgnoredName12" ), - DEFINE_KEYFIELD( m_nIgnoredEntityNames[12], FIELD_STRING, "IgnoredName13" ), - DEFINE_KEYFIELD( m_nIgnoredEntityNames[13], FIELD_STRING, "IgnoredName14" ), - DEFINE_KEYFIELD( m_nIgnoredEntityNames[14], FIELD_STRING, "IgnoredName15" ), - DEFINE_KEYFIELD( m_nIgnoredEntityNames[15], FIELD_STRING, "IgnoredName16" ), - -END_DATADESC() - - - -CON_COMMAND( hammer_update_entity, "Updates the entity's position/angles when in edit mode" ) -{ - if ( args.ArgC() < 2 ) - { - CBasePlayer *pPlayer = UTIL_GetCommandClient(); - trace_t tr; - Vector forward; - pPlayer->EyeVectors( &forward ); - UTIL_TraceLine(pPlayer->EyePosition(), pPlayer->EyePosition() + forward * MAX_COORD_RANGE, - MASK_SHOT_HULL|CONTENTS_GRATE|CONTENTS_DEBRIS, pPlayer, COLLISION_GROUP_NONE, &tr ); - - if ( tr.DidHit() && !tr.DidHitWorld() ) - { - NWCEdit::UpdateEntityPosition( tr.m_pEnt ); - } - } - else - { - CBaseEntity *pEnt = NULL; - while ((pEnt = gEntList.FindEntityGeneric( pEnt, args[1] ) ) != NULL) - { - NWCEdit::UpdateEntityPosition( pEnt ); - } - } -} - -CON_COMMAND( hammer_update_safe_entities, "Updates entities in the map that can safely be updated (don't have parents or are affected by constraints). Also excludes entities mentioned in any hammer_updateignorelist objects in this map." ) -{ - int iCount = 0; - CBaseEntity *pEnt = NULL; - - Msg("\n====================================================\nPerforming Safe Entity Update\n" ); - - // first look for any exclusion objects -- these are entities that list specific things to be ignored. - // All the names that are inside them, we store into a hash table (here implemented through a local - // CUtlSymbolTable) - - CUtlSymbolTable ignoredNames(16,32,true); // grow 16 strings at a time. Case insensitive. - while ( (pEnt = gEntList.FindEntityByClassname( pEnt, "hammer_updateignorelist" )) != NULL ) - { - // for each name in each of those strings, add it to the symbol table. - CWC_UpdateIgnoreList *piglist = static_cast(pEnt); - for (int ii = 0 ; ii < CWC_UpdateIgnoreList::MAX_IGNORELIST_NAMES ; ++ii ) - { - if (!!piglist->GetName(ii)) // if not null - { // add to symtab - ignoredNames.AddString(piglist->GetName(ii).ToCStr()); - } - } - } - - if ( ignoredNames.GetNumStrings() > 0 ) - { - Msg( "Ignoring %d specified targetnames.\n", ignoredNames.GetNumStrings() ); - } - - - // now iterate through everything in the world - for ( pEnt = gEntList.FirstEnt(); pEnt != NULL; pEnt = gEntList.NextEnt(pEnt) ) - { - if ( !(pEnt->ObjectCaps() & FCAP_WCEDIT_POSITION) ) - continue; - - // If we have a parent, or any children, we're not safe to update - if ( pEnt->GetMoveParent() || pEnt->FirstMoveChild() ) - continue; - - IPhysicsObject *pPhysics = pEnt->VPhysicsGetObject(); - if ( !pPhysics ) - continue; - // If we are affected by any constraints, we're not safe to update - if ( pPhysics->IsAttachedToConstraint( Ragdoll_IsPropRagdoll(pEnt) ) ) - continue; - // Motion disabled? - if ( !pPhysics->IsMoveable() ) - continue; - - // ignore brush models (per bug 61318) - if ( dynamic_cast(pEnt) ) - continue; - - // explicitly excluded by designer? - if ( ignoredNames.Find(pEnt->GetEntityName().ToCStr()).IsValid() ) - continue; - - NWCEdit::UpdateEntityPosition( pEnt ); - iCount++; - } - - Msg("Updated %d entities.\n", iCount); -} diff --git a/game/server/wcedit.h b/game/server/wcedit.h deleted file mode 100644 index f79614560..000000000 --- a/game/server/wcedit.h +++ /dev/null @@ -1,36 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Namespace for functions having to do with WC Edit mode -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef WCEDIT_H -#define WCEDIT_H -#pragma once - -class CBaseEntity; - -//============================================================================= -// >> NWCEdit -//============================================================================= -namespace NWCEdit -{ - Vector AirNodePlacementPosition( void ); - bool IsWCVersionValid(void); - void CreateAINode( CBasePlayer *pPlayer ); - void DestroyAINode( CBasePlayer *pPlayer ); - void CreateAILink( CBasePlayer *pPlayer ); - void DestroyAILink( CBasePlayer *pPlayer ); - void UndoDestroyAINode(void); - void RememberEntityPosition( CBaseEntity *pEntity ); - void UpdateEntityPosition( CBaseEntity *pEntity ); -}; - -#endif // WCEDIT_H diff --git a/game/server/weapon_cubemap.cpp b/game/server/weapon_cubemap.cpp deleted file mode 100644 index 0abe0d85e..000000000 --- a/game/server/weapon_cubemap.cpp +++ /dev/null @@ -1,48 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CWeaponCubemap : public CBaseCombatWeapon -{ -public: - - DECLARE_CLASS( CWeaponCubemap, CBaseCombatWeapon ); - - void Precache( void ); - - bool HasAnyAmmo( void ) { return true; } - - void Spawn( void ); - - DECLARE_SERVERCLASS(); -}; - -LINK_ENTITY_TO_CLASS( weapon_cubemap, CWeaponCubemap ); - -IMPLEMENT_SERVERCLASS_ST( CWeaponCubemap, DT_WeaponCubemap ) -END_SEND_TABLE() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCubemap::Precache( void ) -{ - BaseClass::Precache(); -} - -void CWeaponCubemap::Spawn( void ) -{ - BaseClass::Spawn(); - - //Hack to fix the cubemap weapon not being held by the player. - //Problem is the model has huge bounds so the new pickup code that checks if the player can see the model fails cause half the entity's bounds are inside the ground. - //Since this is just a dev tool I made this quick hack so level designers can use it again asap. - Adrian - UTIL_SetSize( this, Vector( -16, -16, -16 ), Vector( 16, 16, 16 ) ); -} diff --git a/game/server/weight_button.cpp b/game/server/weight_button.cpp deleted file mode 100644 index bfbca153a..000000000 --- a/game/server/weight_button.cpp +++ /dev/null @@ -1,102 +0,0 @@ - -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: 'Button' which activates after a specified amount of weight is touching it. -// -//=============================================================================// - -#include "cbase.h" - -class CWeightButton : public CBaseEntity -{ -public: - - DECLARE_DATADESC(); - DECLARE_CLASS( CWeightButton, CBaseEntity ); - - void Spawn( void ); - bool CreateVPhysics( void ); - - COutputEvent m_OnPressed; // After threshold weight has been reached - COutputEvent m_OnReleased; // After weight has been removed to go below weight threshold - - float m_fStressToActivate; // Amount of weight required to activate - bool m_bHasBeenPressed; // Once the button has been pressed, fire one - // output until the weight is reduced below the threshold - - void TriggerThink ( void ); - -}; - -LINK_ENTITY_TO_CLASS( func_weight_button, CWeightButton ); - -BEGIN_DATADESC( CWeightButton ) - - DEFINE_KEYFIELD( m_fStressToActivate, FIELD_FLOAT, "WeightToActivate" ), - DEFINE_FIELD( m_bHasBeenPressed, FIELD_BOOLEAN ), - - DEFINE_OUTPUT( m_OnPressed, "OnPressed" ), - DEFINE_OUTPUT( m_OnReleased, "OnReleased" ), - - DEFINE_THINKFUNC( TriggerThink ), - -END_DATADESC() - - -void CWeightButton::Spawn() -{ - BaseClass::Spawn(); - - // Convert movedir from angles to a vector - SetMoveType( MOVETYPE_VPHYSICS ); - SetSolid( SOLID_VPHYSICS ); - SetModel( STRING( GetModelName() ) ); - CreateVPhysics(); - SetThink( &CWeightButton::TriggerThink ); - SetNextThink( gpGlobals->curtime + TICK_INTERVAL ); - m_bHasBeenPressed = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Create VPhysics collision for this entity -//----------------------------------------------------------------------------- -bool CWeightButton::CreateVPhysics() -{ - VPhysicsInitShadow( false, false ); - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Every second, check total stress and fire an output if we have reached -// our threshold. If the stress is relieved below our threshold, fire a different output. -//----------------------------------------------------------------------------- -void CWeightButton::TriggerThink( void ) -{ - vphysics_objectstress_t vpobj_StressOut; - IPhysicsObject* pMyPhysics = VPhysicsGetObject(); - - if ( !pMyPhysics ) - { - SetNextThink( TICK_NEVER_THINK ); - return; - } - - float fStress = CalculateObjectStress( pMyPhysics, this, &vpobj_StressOut ); - -// fStress = vpobj_StressOut.receivedStress; - - if ( fStress > m_fStressToActivate && !m_bHasBeenPressed ) - { - m_OnPressed.FireOutput( this, this ); - m_bHasBeenPressed = true; - } - else if ( fStress < m_fStressToActivate && m_bHasBeenPressed ) - { - m_OnReleased.FireOutput( this, this ); - m_bHasBeenPressed = false; - } - - // think every tick - SetNextThink( gpGlobals->curtime + TICK_INTERVAL ); -} diff --git a/game/server/world.cpp b/game/server/world.cpp deleted file mode 100644 index 02fe22b0e..000000000 --- a/game/server/world.cpp +++ /dev/null @@ -1,733 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: Precaches and defs for entities and other data that must always be available. -// -// $NoKeywords: $ -//===========================================================================// - -#include "cbase.h" -#include "soundent.h" -#include "client.h" -#include "decals.h" -#include "EnvMessage.h" -#include "player.h" -#include "gamerules.h" -#include "teamplay_gamerules.h" -#include "physics.h" -#include "isaverestore.h" -#include "activitylist.h" -#include "eventlist.h" -#include "eventqueue.h" -#include "ai_network.h" -#include "ai_schedule.h" -#include "ai_networkmanager.h" -#include "ai_utils.h" -#include "basetempentity.h" -#include "world.h" -#include "mempool.h" -#include "igamesystem.h" -#include "engine/IEngineSound.h" -#include "globals.h" -#include "engine/IStaticPropMgr.h" -#include "particle_parse.h" -#include "globalstate.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern CBaseEntity *g_pLastSpawn; -void InitBodyQue(void); -extern void W_Precache(void); -extern void ActivityList_Free( void ); -extern CMemoryPool g_EntityListPool; - -#define SF_DECAL_NOTINDEATHMATCH 2048 - -class CDecal : public CPointEntity -{ -public: - DECLARE_CLASS( CDecal, CPointEntity ); - - void Spawn( void ); - bool KeyValue( const char *szKeyName, const char *szValue ); - - // Need to apply static decals here to get them into the signon buffer for the server appropriately - virtual void Activate(); - - void TriggerDecal( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - // Input handlers. - void InputActivate( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - -public: - int m_nTexture; - bool m_bLowPriority; - -private: - - void StaticDecal( void ); -}; - -BEGIN_DATADESC( CDecal ) - - DEFINE_FIELD( m_nTexture, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_bLowPriority, FIELD_BOOLEAN, "LowPriority" ), // Don't mark as FDECAL_PERMANENT so not save/restored and will be reused on the client preferentially - - // Function pointers - DEFINE_FUNCTION( StaticDecal ), - DEFINE_FUNCTION( TriggerDecal ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( infodecal, CDecal ); - -// UNDONE: These won't get sent to joining players in multi-player -void CDecal::Spawn( void ) -{ - if ( m_nTexture < 0 || - (gpGlobals->deathmatch && HasSpawnFlags( SF_DECAL_NOTINDEATHMATCH )) ) - { - UTIL_Remove( this ); - return; - } -} - -void CDecal::Activate() -{ - BaseClass::Activate(); - - if ( !GetEntityName() ) - { - StaticDecal(); - } - else - { - // if there IS a targetname, the decal sprays itself on when it is triggered. - SetThink ( &CDecal::SUB_DoNothing ); - SetUse(&CDecal::TriggerDecal); - } -} - -void CDecal::TriggerDecal ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - // this is set up as a USE function for info_decals that have targetnames, so that the - // decal doesn't get applied until it is fired. (usually by a scripted sequence) - trace_t trace; - int entityIndex; - - UTIL_TraceLine( GetAbsOrigin() - Vector(5,5,5), GetAbsOrigin() + Vector(5,5,5), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &trace ); - - entityIndex = trace.m_pEnt ? trace.m_pEnt->entindex() : 0; - - CBroadcastRecipientFilter filter; - - te->BSPDecal( filter, 0.0, - &GetAbsOrigin(), entityIndex, m_nTexture ); - - SetThink( &CDecal::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 0.1f ); -} - - -void CDecal::InputActivate( inputdata_t &inputdata ) -{ - TriggerDecal( inputdata.pActivator, inputdata.pCaller, USE_ON, 0 ); -} - - -void CDecal::StaticDecal( void ) -{ - class CTraceFilterValidForDecal : public CTraceFilterSimple - { - public: - CTraceFilterValidForDecal(const IHandleEntity *passentity, int collisionGroup ) - : CTraceFilterSimple( passentity, collisionGroup ) - { - } - - virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ) - { - static const char *ppszIgnoredClasses[] = - { - "weapon_*", - "item_*", - "prop_ragdoll", - "prop_dynamic", - "prop_static", - "prop_physics", - "npc_bullseye", // Tracker 15335 - }; - - CBaseEntity *pEntity = EntityFromEntityHandle( pServerEntity ); - - // Tracker 15335: Never impact decals against entities which are not rendering, either. - if ( pEntity->IsEffectActive( EF_NODRAW ) ) - return false; - - for ( size_t i = 0; i < ARRAYSIZE(ppszIgnoredClasses); i++ ) - { - if ( pEntity->ClassMatches( ppszIgnoredClasses[i] ) ) - return false; - } - - - return CTraceFilterSimple::ShouldHitEntity( pServerEntity, contentsMask ); - } - }; - - trace_t trace; - CTraceFilterValidForDecal traceFilter( this, COLLISION_GROUP_NONE ); - int entityIndex, modelIndex = 0; - - Vector position = GetAbsOrigin(); - UTIL_TraceLine( position - Vector(5,5,5), position + Vector(5,5,5), MASK_SOLID, &traceFilter, &trace ); - - bool canDraw = true; - - entityIndex = trace.m_pEnt ? trace.m_pEnt->entindex() : 0; - if ( entityIndex ) - { - CBaseEntity *ent = trace.m_pEnt; - if ( ent ) - { - modelIndex = ent->GetModelIndex(); - VectorITransform( GetAbsOrigin(), ent->EntityToWorldTransform(), position ); - - canDraw = ( modelIndex != 0 ); - if ( !canDraw ) - { - Warning( "Suppressed StaticDecal which would have hit entity %i (class:%s, name:%s) with modelindex = 0\n", - ent->entindex(), - ent->GetClassname(), - STRING( ent->GetEntityName() ) ); - } - } - } - - if ( canDraw ) - { - engine->StaticDecal( position, m_nTexture, entityIndex, modelIndex, m_bLowPriority ); - } - - SUB_Remove(); -} - - -bool CDecal::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "texture")) - { - // FIXME: should decals all be preloaded? - m_nTexture = UTIL_PrecacheDecal( szValue, true ); - - // Found - if (m_nTexture >= 0 ) - return true; - Warning( "Can't find decal %s\n", szValue ); - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Projects a decal against a prop -//----------------------------------------------------------------------------- -class CProjectedDecal : public CPointEntity -{ -public: - DECLARE_CLASS( CProjectedDecal, CPointEntity ); - - void Spawn( void ); - bool KeyValue( const char *szKeyName, const char *szValue ); - - // Need to apply static decals here to get them into the signon buffer for the server appropriately - virtual void Activate(); - - void TriggerDecal( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - - // Input handlers. - void InputActivate( inputdata_t &inputdata ); - - DECLARE_DATADESC(); - -public: - int m_nTexture; - float m_flDistance; - -private: - void ProjectDecal( CRecipientFilter& filter ); - - void StaticDecal( void ); -}; - -BEGIN_DATADESC( CProjectedDecal ) - - DEFINE_FIELD( m_nTexture, FIELD_INTEGER ), - - DEFINE_KEYFIELD( m_flDistance, FIELD_FLOAT, "Distance" ), - - // Function pointers - DEFINE_FUNCTION( StaticDecal ), - DEFINE_FUNCTION( TriggerDecal ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Activate", InputActivate ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( info_projecteddecal, CProjectedDecal ); - -// UNDONE: These won't get sent to joining players in multi-player -void CProjectedDecal::Spawn( void ) -{ - if ( m_nTexture < 0 || - (gpGlobals->deathmatch && HasSpawnFlags( SF_DECAL_NOTINDEATHMATCH )) ) - { - UTIL_Remove( this ); - return; - } -} - -void CProjectedDecal::Activate() -{ - BaseClass::Activate(); - - if ( !GetEntityName() ) - { - StaticDecal(); - } - else - { - // if there IS a targetname, the decal sprays itself on when it is triggered. - SetThink ( &CProjectedDecal::SUB_DoNothing ); - SetUse(&CProjectedDecal::TriggerDecal); - } -} - -void CProjectedDecal::InputActivate( inputdata_t &inputdata ) -{ - TriggerDecal( inputdata.pActivator, inputdata.pCaller, USE_ON, 0 ); -} - -void CProjectedDecal::ProjectDecal( CRecipientFilter& filter ) -{ - te->ProjectDecal( filter, 0.0, - &GetAbsOrigin(), &GetAbsAngles(), m_flDistance, m_nTexture ); -} - -void CProjectedDecal::TriggerDecal ( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - CBroadcastRecipientFilter filter; - - ProjectDecal( filter ); - - SetThink( &CProjectedDecal::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -void CProjectedDecal::StaticDecal( void ) -{ - CBroadcastRecipientFilter initFilter; - initFilter.MakeInitMessage(); - - ProjectDecal( initFilter ); - - SUB_Remove(); -} - - -bool CProjectedDecal::KeyValue( const char *szKeyName, const char *szValue ) -{ - if (FStrEq(szKeyName, "texture")) - { - // FIXME: should decals all be preloaded? - m_nTexture = UTIL_PrecacheDecal( szValue, true ); - - // Found - if (m_nTexture >= 0 ) - return true; - Warning( "Can't find decal %s\n", szValue ); - } - else - { - return BaseClass::KeyValue( szKeyName, szValue ); - } - - return true; -} - -//======================= -// CWorld -// -// This spawns first when each level begins. -//======================= -LINK_ENTITY_TO_CLASS( worldspawn, CWorld ); - -BEGIN_DATADESC( CWorld ) - - DEFINE_FIELD( m_flWaveHeight, FIELD_FLOAT ), - - // keyvalues are parsed from map, but not saved/loaded - DEFINE_KEYFIELD( m_iszChapterTitle, FIELD_STRING, "chaptertitle" ), - DEFINE_KEYFIELD( m_bStartDark, FIELD_BOOLEAN, "startdark" ), - DEFINE_KEYFIELD( m_bDisplayTitle, FIELD_BOOLEAN, "gametitle" ), - DEFINE_FIELD( m_WorldMins, FIELD_VECTOR ), - DEFINE_FIELD( m_WorldMaxs, FIELD_VECTOR ), -#ifdef _X360 - DEFINE_KEYFIELD( m_flMaxOccludeeArea, FIELD_FLOAT, "maxoccludeearea_x360" ), - DEFINE_KEYFIELD( m_flMinOccluderArea, FIELD_FLOAT, "minoccluderarea_x360" ), -#else - DEFINE_KEYFIELD( m_flMaxOccludeeArea, FIELD_FLOAT, "maxoccludeearea" ), - DEFINE_KEYFIELD( m_flMinOccluderArea, FIELD_FLOAT, "minoccluderarea" ), -#endif - DEFINE_KEYFIELD( m_flMaxPropScreenSpaceWidth, FIELD_FLOAT, "maxpropscreenwidth" ), - DEFINE_KEYFIELD( m_flMinPropScreenSpaceWidth, FIELD_FLOAT, "minpropscreenwidth" ), - DEFINE_KEYFIELD( m_iszDetailSpriteMaterial, FIELD_STRING, "detailmaterial" ), - DEFINE_KEYFIELD( m_bColdWorld, FIELD_BOOLEAN, "coldworld" ), - -END_DATADESC() - - -// SendTable stuff. -IMPLEMENT_SERVERCLASS_ST(CWorld, DT_WORLD) - SendPropFloat (SENDINFO(m_flWaveHeight), 8, SPROP_ROUNDUP, 0.0f, 8.0f), - SendPropVector (SENDINFO(m_WorldMins), -1, SPROP_COORD), - SendPropVector (SENDINFO(m_WorldMaxs), -1, SPROP_COORD), - SendPropInt (SENDINFO(m_bStartDark), 1, SPROP_UNSIGNED ), - SendPropFloat (SENDINFO(m_flMaxOccludeeArea), 0, SPROP_NOSCALE ), - SendPropFloat (SENDINFO(m_flMinOccluderArea), 0, SPROP_NOSCALE ), - SendPropFloat (SENDINFO(m_flMaxPropScreenSpaceWidth), 0, SPROP_NOSCALE ), - SendPropFloat (SENDINFO(m_flMinPropScreenSpaceWidth), 0, SPROP_NOSCALE ), - SendPropStringT (SENDINFO(m_iszDetailSpriteMaterial) ), - SendPropInt (SENDINFO(m_bColdWorld), 1, SPROP_UNSIGNED ), -END_SEND_TABLE() - -// -// Just to ignore the "wad" field. -// -bool CWorld::KeyValue( const char *szKeyName, const char *szValue ) -{ - if ( FStrEq(szKeyName, "skyname") ) - { - // Sent over net now. - ConVarRef skyname( "sv_skyname" ); - skyname.SetValue( szValue ); - } - else if ( FStrEq(szKeyName, "newunit") ) - { - // Single player only. Clear save directory if set - if ( atoi(szValue) ) - { - extern void Game_SetOneWayTransition(); - Game_SetOneWayTransition(); - } - } - else if ( FStrEq(szKeyName, "world_mins") ) - { - Vector vec; - sscanf( szValue, "%f %f %f", &vec.x, &vec.y, &vec.z ); - m_WorldMins = vec; - } - else if ( FStrEq(szKeyName, "world_maxs") ) - { - Vector vec; - sscanf( szValue, "%f %f %f", &vec.x, &vec.y, &vec.z ); - m_WorldMaxs = vec; - } - else - return BaseClass::KeyValue( szKeyName, szValue ); - - return true; -} - - -extern bool g_fGameOver; -static CWorld *g_WorldEntity = NULL; - -CWorld* GetWorldEntity() -{ - return g_WorldEntity; -} - -CWorld::CWorld( ) -{ - AddEFlags( EFL_NO_AUTO_EDICT_ATTACH | EFL_KEEP_ON_RECREATE_ENTITIES ); - NetworkProp()->AttachEdict( INDEXENT(RequiredEdictIndex()) ); - ActivityList_Init(); - EventList_Init(); - - SetSolid( SOLID_BSP ); - SetMoveType( MOVETYPE_NONE ); - - m_bColdWorld = false; -} - -CWorld::~CWorld( ) -{ - EventList_Free(); - ActivityList_Free(); - if ( g_pGameRules ) - { - g_pGameRules->LevelShutdown(); - delete g_pGameRules; - g_pGameRules = NULL; - } - g_WorldEntity = NULL; -} - - -//------------------------------------------------------------------------------ -// Purpose : Add a decal to the world -// Input : -// Output : -//------------------------------------------------------------------------------ -void CWorld::DecalTrace( trace_t *pTrace, char const *decalName) -{ - int index = decalsystem->GetDecalIndexForName( decalName ); - if ( index < 0 ) - return; - - CBroadcastRecipientFilter filter; - if ( pTrace->hitbox != 0 ) - { - te->Decal( filter, 0.0f, &pTrace->endpos, &pTrace->startpos, 0, pTrace->hitbox, index ); - } - else - { - te->WorldDecal( filter, 0.0, &pTrace->endpos, index ); - } -} - -void CWorld::RegisterSharedActivities( void ) -{ - ActivityList_RegisterSharedActivities(); -} - -void CWorld::RegisterSharedEvents( void ) -{ - EventList_RegisterSharedEvents(); -} - - -void CWorld::Spawn( void ) -{ - SetLocalOrigin( vec3_origin ); - SetLocalAngles( vec3_angle ); - // NOTE: SHOULD NEVER BE ANYTHING OTHER THAN 1!!! - SetModelIndex( 1 ); - // world model - SetModelName( AllocPooledString( modelinfo->GetModelName( GetModel() ) ) ); - AddFlag( FL_WORLDBRUSH ); - - g_EventQueue.Init(); - Precache( ); - GlobalEntity_Add( "is_console", STRING(gpGlobals->mapname), ( IsConsole() ) ? GLOBAL_ON : GLOBAL_OFF ); - GlobalEntity_Add( "is_pc", STRING(gpGlobals->mapname), ( !IsConsole() ) ? GLOBAL_ON : GLOBAL_OFF ); -} - -static const char *g_DefaultLightstyles[] = -{ - // 0 normal - "m", - // 1 FLICKER (first variety) - "mmnmmommommnonmmonqnmmo", - // 2 SLOW STRONG PULSE - "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba", - // 3 CANDLE (first variety) - "mmmmmaaaaammmmmaaaaaabcdefgabcdefg", - // 4 FAST STROBE - "mamamamamama", - // 5 GENTLE PULSE 1 - "jklmnopqrstuvwxyzyxwvutsrqponmlkj", - // 6 FLICKER (second variety) - "nmonqnmomnmomomno", - // 7 CANDLE (second variety) - "mmmaaaabcdefgmmmmaaaammmaamm", - // 8 CANDLE (third variety) - "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa", - // 9 SLOW STROBE (fourth variety) - "aaaaaaaazzzzzzzz", - // 10 FLUORESCENT FLICKER - "mmamammmmammamamaaamammma", - // 11 SLOW PULSE NOT FADE TO BLACK - "abcdefghijklmnopqrrqponmlkjihgfedcba", - // 12 UNDERWATER LIGHT MUTATION - // this light only distorts the lightmap - no contribution - // is made to the brightness of affected surfaces - "mmnnmmnnnmmnn", -}; - - -const char *GetDefaultLightstyleString( int styleIndex ) -{ - if ( styleIndex < (int)ARRAYSIZE(g_DefaultLightstyles) ) - { - return g_DefaultLightstyles[styleIndex]; - } - return "m"; -} - -void CWorld::Precache( void ) -{ - g_WorldEntity = this; - g_fGameOver = false; - g_pLastSpawn = NULL; - - ConVarRef stepsize( "sv_stepsize" ); - stepsize.SetValue( 18 ); - - ConVarRef roomtype( "room_type" ); - roomtype.SetValue( 0 ); - - // Set up game rules - Assert( !g_pGameRules ); - if (g_pGameRules) - { - delete g_pGameRules; - } - - InstallGameRules(); - Assert( g_pGameRules ); - g_pGameRules->Init(); - - CSoundEnt::InitSoundEnt(); - - // Only allow precaching between LevelInitPreEntity and PostEntity - CBaseEntity::SetAllowPrecache( true ); - IGameSystem::LevelInitPreEntityAllSystems( STRING( GetModelName() ) ); - - // Create the player resource - g_pGameRules->CreateStandardEntities(); - - // UNDONE: Make most of these things server systems or precache_registers - // ================================================= - // Activities - // ================================================= - ActivityList_Free(); - RegisterSharedActivities(); - - EventList_Free(); - RegisterSharedEvents(); - - InitBodyQue(); -// init sentence group playback stuff from sentences.txt. -// ok to call this multiple times, calls after first are ignored. - - SENTENCEG_Init(); - - // Precache standard particle systems - PrecacheStandardParticleSystems( ); - -// the area based ambient sounds MUST be the first precache_sounds - -// player precaches - W_Precache (); // get weapon precaches - ClientPrecache(); - g_pGameRules->Precache(); - // precache all temp ent stuff - CBaseTempEntity::PrecacheTempEnts(); - - g_Language.SetValue( LANGUAGE_ENGLISH ); // TODO use VGUI to get current language - - if ( g_Language.GetInt() == LANGUAGE_GERMAN ) - { - PrecacheModel( "models/germangibs.mdl" ); - } - else - { - PrecacheModel( "models/gibs/hgibs.mdl" ); - } - - PrecacheScriptSound( "BaseEntity.EnterWater" ); - PrecacheScriptSound( "BaseEntity.ExitWater" ); - -// -// Setup light animation tables. 'a' is total darkness, 'z' is maxbright. -// - for ( int i = 0; i < (int)ARRAYSIZE(g_DefaultLightstyles); i++ ) - { - engine->LightStyle( i, GetDefaultLightstyleString(i) ); - } - - // styles 32-62 are assigned by the light program for switchable lights - - // 63 testing - engine->LightStyle(63, "a"); - - // ================================================= - // Load and Init AI Networks - // ================================================= - CAI_NetworkManager::InitializeAINetworks(); - // ================================================= - // Load and Init AI Schedules - // ================================================= - g_AI_SchedulesManager.LoadAllSchedules(); - // ================================================= - // Initialize NPC Relationships - // ================================================= - g_pGameRules->InitDefaultAIRelationships(); - CBaseCombatCharacter::InitInteractionSystem(); - - // Call all registered precachers. - CPrecacheRegister::Precache(); - - if ( m_iszChapterTitle != NULL_STRING ) - { - DevMsg( 2, "Chapter title: %s\n", STRING(m_iszChapterTitle) ); - CMessage *pMessage = (CMessage *)CBaseEntity::Create( "env_message", vec3_origin, vec3_angle, NULL ); - if ( pMessage ) - { - pMessage->SetMessage( m_iszChapterTitle ); - m_iszChapterTitle = NULL_STRING; - - // send the message entity a play message command, delayed by 1 second - pMessage->AddSpawnFlags( SF_MESSAGE_ONCE ); - pMessage->SetThink( &CMessage::SUB_CallUseToggle ); - pMessage->SetNextThink( gpGlobals->curtime + 1.0f ); - } - } - - g_iszFuncBrushClassname = AllocPooledString("func_brush"); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float GetRealTime() -{ - return engine->Time(); -} - - -bool CWorld::GetDisplayTitle() const -{ - return m_bDisplayTitle; -} - -bool CWorld::GetStartDark() const -{ - return m_bStartDark; -} - -void CWorld::SetDisplayTitle( bool display ) -{ - m_bDisplayTitle = display; -} - -void CWorld::SetStartDark( bool startdark ) -{ - m_bStartDark = startdark; -} - -bool CWorld::IsColdWorld( void ) -{ - return m_bColdWorld; -} diff --git a/game/server/world.h b/game/server/world.h deleted file mode 100644 index 588c723ae..000000000 --- a/game/server/world.h +++ /dev/null @@ -1,80 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: The worldspawn entity. This spawns first when each level begins. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef WORLD_H -#define WORLD_H -#ifdef _WIN32 -#pragma once -#endif - - -class CWorld : public CBaseEntity -{ -public: - DECLARE_CLASS( CWorld, CBaseEntity ); - - CWorld(); - ~CWorld(); - - DECLARE_SERVERCLASS(); - - virtual int RequiredEdictIndex( void ) { return 0; } // the world always needs to be in slot 0 - - static void RegisterSharedActivities( void ); - static void RegisterSharedEvents( void ); - virtual void Spawn( void ); - virtual void Precache( void ); - virtual bool KeyValue( const char *szKeyName, const char *szValue ); - virtual void DecalTrace( trace_t *pTrace, char const *decalName ); - virtual void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) {} - virtual void VPhysicsFriction( IPhysicsObject *pObject, float energy, int surfaceProps, int surfacePropsHit ) {} - - inline void GetWorldBounds( Vector &vecMins, Vector &vecMaxs ) - { - VectorCopy( m_WorldMins, vecMins ); - VectorCopy( m_WorldMaxs, vecMaxs ); - } - - inline float GetWaveHeight() const - { - return (float)m_flWaveHeight; - } - - bool GetDisplayTitle() const; - bool GetStartDark() const; - - void SetDisplayTitle( bool display ); - void SetStartDark( bool startdark ); - - bool IsColdWorld( void ); - -private: - DECLARE_DATADESC(); - - string_t m_iszChapterTitle; - - CNetworkVar( float, m_flWaveHeight ); - CNetworkVector( m_WorldMins ); - CNetworkVector( m_WorldMaxs ); - CNetworkVar( float, m_flMaxOccludeeArea ); - CNetworkVar( float, m_flMinOccluderArea ); - CNetworkVar( float, m_flMinPropScreenSpaceWidth ); - CNetworkVar( float, m_flMaxPropScreenSpaceWidth ); - CNetworkVar( string_t, m_iszDetailSpriteMaterial ); - - // start flags - CNetworkVar( bool, m_bStartDark ); - CNetworkVar( bool, m_bColdWorld ); - bool m_bDisplayTitle; -}; - - -CWorld* GetWorldEntity(); -extern const char *GetDefaultLightstyleString( int styleIndex ); - - -#endif // WORLD_H diff --git a/game/shared/EntityParticleTrail_Shared.cpp b/game/shared/EntityParticleTrail_Shared.cpp deleted file mode 100644 index c202d3494..000000000 --- a/game/shared/EntityParticleTrail_Shared.cpp +++ /dev/null @@ -1,58 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Drops particles where the entity was. -// -//=============================================================================// - -#include "cbase.h" -#include "entityparticletrail_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Default values -//----------------------------------------------------------------------------- -EntityParticleTrailInfo_t::EntityParticleTrailInfo_t() -{ - m_strMaterialName = NULL_STRING; - m_flLifetime = 4.0f; - m_flStartSize = 2.0f; - m_flEndSize = 3.0f; -} - -//----------------------------------------------------------------------------- -// Save/load -//----------------------------------------------------------------------------- -#ifndef CLIENT_DLL - -BEGIN_SIMPLE_DATADESC( EntityParticleTrailInfo_t ) - - DEFINE_KEYFIELD( m_strMaterialName, FIELD_STRING, "ParticleTrailMaterial" ), - DEFINE_KEYFIELD( m_flLifetime, FIELD_FLOAT, "ParticleTrailLifetime" ), - DEFINE_KEYFIELD( m_flStartSize, FIELD_FLOAT, "ParticleTrailStartSize" ), - DEFINE_KEYFIELD( m_flEndSize, FIELD_FLOAT, "ParticleTrailEndSize" ), - -END_DATADESC() - -#endif - -//----------------------------------------------------------------------------- -// Networking -//----------------------------------------------------------------------------- -BEGIN_NETWORK_TABLE_NOBASE( EntityParticleTrailInfo_t, DT_EntityParticleTrailInfo ) - -#ifdef CLIENT_DLL - RecvPropFloat( RECVINFO( m_flLifetime ) ), - RecvPropFloat( RECVINFO( m_flStartSize ) ), - RecvPropFloat( RECVINFO( m_flEndSize ) ), -#else - SendPropFloat( SENDINFO( m_flLifetime ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO( m_flStartSize ), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO( m_flEndSize ), 0, SPROP_NOSCALE ), -#endif - -END_NETWORK_TABLE() - - - diff --git a/game/shared/GameEventListener.h b/game/shared/GameEventListener.h deleted file mode 100644 index c589b0ce3..000000000 --- a/game/shared/GameEventListener.h +++ /dev/null @@ -1,64 +0,0 @@ -//========= Copyright 1996-2006, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef GAME_EVENT_LISTENER_H -#define GAME_EVENT_LISTENER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "igameevents.h" - -// A safer method than inheriting straight from IGameEventListener2. -// Avoids requiring the user to remove themselves as listeners in -// their deconstructor, and sets the serverside variable based on -// our dll location. -class CGameEventListener : public IGameEventListener2 -{ -public: - CGameEventListener() : m_bRegisteredForEvents(false) - { - } - - ~CGameEventListener() - { - StopListeningForAllEvents(); - } - - void ListenForGameEvent( const char *name ) - { - m_bRegisteredForEvents = true; - -#ifdef CLIENT_DLL - bool bServerSide = false; -#else - bool bServerSide = true; -#endif - - gameeventmanager->AddListener( this, name, bServerSide ); - } - - void StopListeningForAllEvents() - { - // remove me from list - if ( m_bRegisteredForEvents ) - { - gameeventmanager->RemoveListener( this ); - m_bRegisteredForEvents = false; - } - } - - // Intentionally abstract - virtual void FireGameEvent( IGameEvent *event ) = 0; - -private: - - // Have we registered for any events? - bool m_bRegisteredForEvents; -}; - -#endif diff --git a/game/shared/GameStats.cpp b/game/shared/GameStats.cpp deleted file mode 100644 index bb5ab04e2..000000000 --- a/game/shared/GameStats.cpp +++ /dev/null @@ -1,1451 +0,0 @@ -//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" - - -#include "igamesystem.h" -#include "GameStats.h" -#include "tier1/utlstring.h" -#include "filesystem.h" -#include "tier1/utlbuffer.h" -#include "fmtstr.h" - -#ifndef SWDS -#include "iregistry.h" -#endif - -#include "tier1/utldict.h" -#include "tier0/icommandline.h" -#include -#ifdef GAME_DLL -#include "vehicle_base.h" -#endif - -#if defined( _X360 ) -#include "xbox/xbox_win32stubs.h" -#endif - -#define GAMESTATS_LOG_FILE "gamestats.log" -#define GAMESTATS_PATHID "MOD" - -/* -#define ONE_DAY_IN_SECONDS 86400 - -// Lower threshold in debug for testing... -#if defined( _DEBUG ) -#define WALKED_AWAY_FROM_KEYBOARD_SECONDS 15.0f // 15 seconds of movement == might be paused -#else -#define WALKED_AWAY_FROM_KEYBOARD_SECONDS 300.0f // 5 minutes of no movement == might be paused -#endif -*/ - -extern IUploadGameStats *gamestatsuploader; - -static char s_szPseudoUniqueID[20] = ""; - -static inline char const *SafeString( char const *pStr ) -{ - return ( pStr ) ? pStr : "?"; -} - -static CBaseGameStats s_GameStats_Singleton; -CBaseGameStats *gamestats = &s_GameStats_Singleton; //start out pointing at the basic version which does nothing by default -extern ConVar skill; -void OverWriteCharsWeHate( char *pStr ); - -bool StatsTrackingIsFullyEnabled( void ); - -class CGamestatsData -{ -public: - CGamestatsData() - { - m_pKVData = NULL; - m_bHaveData = false; - AllocData(); - } - - ~CGamestatsData() - { - FreeData(); - } - - void AllocData() - { - FreeData(); - m_pKVData = new KeyValues( "gamestats" ); - } - void FreeData() - { - if ( m_pKVData != NULL ) - { - m_pKVData->deleteThis(); - m_pKVData = NULL; - } - } - - KeyValues *m_pKVData; - bool m_bHaveData; -}; - -//used to drive most of the game stat event handlers as well as track basic stats under the hood of CBaseGameStats -class CBaseGameStats_Driver : public CAutoGameSystemPerFrame -{ -public: - CBaseGameStats_Driver( void ); - - typedef CAutoGameSystemPerFrame BaseClass; - - // IGameSystem overloads - virtual bool Init(); - virtual void Shutdown(); - - // Level init, shutdown - virtual void LevelInitPreEntity(); - virtual void LevelShutdownPreEntity(); - // Called during game save - virtual void OnSave(); - // Called during game restore, after the local player has connected and entities have been fully restored - virtual void OnRestore(); - - virtual void FrameUpdatePostEntityThink(); - - void PossibleMapChange( void ); - - void CollectData( StatSendType_t sendType ); - void SendData(); - void ResetData(); - bool AddBaseDataForSend( KeyValues *pKV, StatSendType_t sendType ); - - StatsBufferRecord_t m_StatsBuffer[STATS_WINDOW_SIZE]; - bool m_bBufferFull; - int m_nWriteIndex; - float m_flLastRealTime; - float m_flLastSampleTime; - float m_flTotalTimeInLevels; - int m_iNumLevels; - - template T AverageStat( T StatsBufferRecord_t::*field ) const - { - T sum = 0; - for( int i = 0; i < STATS_WINDOW_SIZE; i++ ) - sum += m_StatsBuffer[i].*field; - return sum / STATS_WINDOW_SIZE; - } - - template T MaxStat( T StatsBufferRecord_t::*field ) const - { - T maxsofar = -16000000; - for( int i = 0; i < STATS_WINDOW_SIZE; i++ ) - maxsofar = MAX( maxsofar, m_StatsBuffer[i].*field ); - return maxsofar; - } - - template T MinStat( T StatsBufferRecord_t::*field ) const - { - T minsofar = 16000000; - for( int i = 0; i < STATS_WINDOW_SIZE; i++ ) - minsofar = MIN( minsofar, m_StatsBuffer[i].*field ); - return minsofar; - } - - inline void AdvanceIndex( void ) - { - m_nWriteIndex++; - if ( m_nWriteIndex == STATS_WINDOW_SIZE ) - { - m_nWriteIndex = 0; - m_bBufferFull = true; - } - } - - void UpdatePerfStats( void ) - { - float flCurTime = Plat_FloatTime(); - if ( - ( m_flLastSampleTime == -1 ) || - ( flCurTime - m_flLastSampleTime >= STATS_RECORD_INTERVAL ) ) - { - if ( ( m_flLastRealTime > 0 ) && ( flCurTime > m_flLastRealTime ) ) - { - float flFrameRate = 1.0 / ( flCurTime - m_flLastRealTime ); - StatsBufferRecord_t &stat = m_StatsBuffer[m_nWriteIndex]; - stat.m_flFrameRate = flFrameRate; - AdvanceIndex(); - m_flLastSampleTime = flCurTime; - } - } - m_flLastRealTime = flCurTime; - } - - CUtlString m_PrevMapName; //used to track "OnMapChange" events - int m_iLoadedVersion; - char m_szLoadedUserID[ 17 ]; // GUID - - bool m_bEnabled; //false if incapable of uploading or the user doesn't want to enable stat tracking - bool m_bShuttingDown; - bool m_bInLevel; - bool m_bFirstLevel; - time_t m_tLastUpload; - - float m_flLevelStartTime; - - bool m_bStationary; - float m_flLastMovementTime; - CUserCmd m_LastUserCmd; - bool m_bGamePaused; - float m_flPauseStartTime; - - CGamestatsData *m_pGamestatsData; -}; -static CBaseGameStats_Driver CBGSDriver; - -void UpdatePerfStats( void ) -{ - CBGSDriver.UpdatePerfStats(); -} - -CBaseGameStats_Driver::CBaseGameStats_Driver( void ) : - BaseClass( "CGameStats" ), - m_bBufferFull( false ), - m_nWriteIndex( 0 ), - m_flLastRealTime( -1 ), - m_flLastSampleTime( -1 ), - m_flTotalTimeInLevels( 0 ), - m_iNumLevels( 0 ), - m_iLoadedVersion( -1 ), - m_bEnabled( false ), - m_bShuttingDown( false ), - m_bInLevel( false ), - m_bFirstLevel( true ), - m_flLevelStartTime( 0.0f ), - m_bStationary( false ), - m_flLastMovementTime( 0.0f ), - m_bGamePaused( false ), - m_pGamestatsData( NULL ) - -{ - m_szLoadedUserID[0] = 0;; - m_tLastUpload = 0; - m_LastUserCmd.Reset(); -} - -static FileHandle_t g_LogFileHandle = FILESYSTEM_INVALID_HANDLE; - -CBaseGameStats::CBaseGameStats() : - m_bLogging( false ), - m_bLoggingToFile( false ) -{ -} - -bool CBaseGameStats::StatTrackingAllowed( void ) -{ - return CBGSDriver.m_bEnabled; -} - -// Don't care about vcr hooks here... -#undef localtime -#undef asctime - -#include - -void CBaseGameStats::StatsLog( char const *fmt, ... ) -{ - if ( !m_bLogging && !m_bLoggingToFile ) - return; - - char buf[ 2048 ]; - va_list argptr; - va_start( argptr, fmt ); - Q_vsnprintf( buf, sizeof( buf ), fmt, argptr ); - va_end( argptr ); - - // Prepend timestamp and spew it - - // Prepend the time. - time_t aclock; - time( &aclock ); - struct tm *newtime = localtime( &aclock ); - - char timeString[ 128 ]; - Q_strncpy( timeString, asctime( newtime ), sizeof( timeString ) ); - // Get rid of the \n. - char *pEnd = strstr( timeString, "\n" ); - if ( pEnd ) - { - *pEnd = 0; - } - - if ( m_bLogging ) - { - DevMsg( "[GS %s - %7.2f] %s", timeString, gpGlobals->realtime, buf ); - } - - if ( m_bLoggingToFile ) - { - if ( FILESYSTEM_INVALID_HANDLE == g_LogFileHandle ) - { - g_LogFileHandle = filesystem->Open( GAMESTATS_LOG_FILE, "a", GAMESTATS_PATHID ); - } - - if ( FILESYSTEM_INVALID_HANDLE != g_LogFileHandle ) - { - filesystem->FPrintf( g_LogFileHandle, "[GS %s - %7.2f] %s", timeString, gpGlobals->realtime, buf ); - filesystem->Flush( g_LogFileHandle ); - } - } -} - -static char s_szSaveFileName[256] = ""; -static char s_szStatUploadRegistryKeyName[256] = ""; - -const char *CBaseGameStats::GetStatSaveFileName( void ) -{ - AssertMsg( s_szSaveFileName[0] != '\0', "Don't know what file to save stats to." ); - return s_szSaveFileName; -} - -const char *CBaseGameStats::GetStatUploadRegistryKeyName( void ) -{ - AssertMsg( s_szStatUploadRegistryKeyName[0] != '\0', "Don't know the registry key to use to mark stats uploads." ); - return s_szStatUploadRegistryKeyName; -} - -const char *CBaseGameStats::GetUserPseudoUniqueID( void ) -{ - AssertMsg( s_szPseudoUniqueID[0] != '\0', "Don't have a pseudo unique ID." ); - return s_szPseudoUniqueID; -} - -void CBaseGameStats::Event_Init( void ) -{ -#ifdef GAME_DLL - SetHL2UnlockedChapterStatistic(); - SetSteamStatistic( filesystem->IsSteam() ); - SetCyberCafeStatistic( gamestatsuploader->IsCyberCafeUser() ); - ConVarRef pDXLevel( "mat_dxlevel" ); - if( pDXLevel.IsValid() ) - { - SetDXLevelStatistic( pDXLevel.GetInt() ); - } - ++m_BasicStats.m_Summary.m_nCount; - - StatsLog( "CBaseGameStats::Event_Init [%dth session]\n", m_BasicStats.m_Summary.m_nCount ); -#endif // GAME_DLL -} - -void CBaseGameStats::Event_Shutdown( void ) -{ -#ifdef GAME_DLL - StatsLog( "CBaseGameStats::Event_Shutdown [%dth session]\n", m_BasicStats.m_Summary.m_nCount ); - - StatsLog( "\n====================================================================\n\n" ); -#endif -} - -void CBaseGameStats::Event_MapChange( const char *szOldMapName, const char *szNewMapName ) -{ - StatsLog( "CBaseGameStats::Event_MapChange to [%s]\n", szNewMapName ); -} - -void CBaseGameStats::Event_LevelInit( void ) -{ -#ifdef GAME_DLL - StatsLog( "CBaseGameStats::Event_LevelInit [%s]\n", CBGSDriver.m_PrevMapName.String() ); - - BasicGameStatsRecord_t *map = gamestats->m_BasicStats.FindOrAddRecordForMap( CBGSDriver.m_PrevMapName.String() ); - ++map->m_nCount; - - // HACK HACK: Punching this hole through only works in single player!!! - if ( gpGlobals->maxClients == 1 ) - { - ConVarRef closecaption( "closecaption" ); - if( closecaption.IsValid() ) - SetCaptionsStatistic( closecaption.GetBool() ); - - SetHDRStatistic( gamestatsuploader->IsHDREnabled() ); - - SetSkillStatistic( skill.GetInt() ); - SetSteamStatistic( filesystem->IsSteam() ); - SetCyberCafeStatistic( gamestatsuploader->IsCyberCafeUser() ); - } -#endif // GAME_DLL -} - -void CBaseGameStats::Event_LevelShutdown( float flElapsed ) -{ -#ifdef GAME_DLL - BasicGameStatsRecord_t *map = m_BasicStats.FindOrAddRecordForMap( CBGSDriver.m_PrevMapName.String() ); - Assert( map ); - map->m_nSeconds += (int)flElapsed; - gamestats->m_BasicStats.m_Summary.m_nSeconds += (int)flElapsed; - - StatsLog( "CBaseGameStats::Event_LevelShutdown [%s] %.2f elapsed %d total\n", CBGSDriver.m_PrevMapName.String(), flElapsed, gamestats->m_BasicStats.m_Summary.m_nSeconds ); -#endif // GAME_DLL -} - -void CBaseGameStats::Event_SaveGame( void ) -{ - StatsLog( "CBaseGameStats::Event_SaveGame [%s]\n", CBGSDriver.m_PrevMapName.String() ); -} - -void CBaseGameStats::Event_LoadGame( void ) -{ -#ifdef GAME_DLL - char const *pchSaveFile = engine->GetMostRecentlyLoadedFileName(); - StatsLog( "CBaseGameStats::Event_LoadGame [%s] from %s\n", CBGSDriver.m_PrevMapName.String(), pchSaveFile ); -#endif -} - -#ifdef GAME_DLL - -void CBaseGameStats::Event_PlayerKilled( CBasePlayer *pPlayer, const CTakeDamageInfo &info ) -{ - ++m_BasicStats.m_Summary.m_nDeaths; - - if( CBGSDriver.m_bInLevel ) - { - BasicGameStatsRecord_t *map = m_BasicStats.FindOrAddRecordForMap( CBGSDriver.m_PrevMapName.String() ); - ++map->m_nDeaths; - StatsLog( " Player died %dth time in level [%s]!!!\n", map->m_nDeaths, CBGSDriver.m_PrevMapName.String() ); - } - else - { - StatsLog( " Player died, but not in a level!!!\n" ); - Assert( 0 ); - } - - StatsLog( "CBaseGameStats::Event_PlayerKilled [%s] [%dth death]\n", pPlayer->GetPlayerName(), m_BasicStats.m_Summary.m_nDeaths ); -} - -void CBaseGameStats::Event_Commentary() -{ - if( CBGSDriver.m_bInLevel ) - { - BasicGameStatsRecord_t *map = m_BasicStats.FindOrAddRecordForMap( CBGSDriver.m_PrevMapName.String() ); - ++map->m_nCommentary; - } - - ++m_BasicStats.m_Summary.m_nCommentary; - - StatsLog( "CBaseGameStats::Event_Commentary [%d]\n", m_BasicStats.m_Summary.m_nCommentary ); -} - -void CBaseGameStats::Event_Credits() -{ - StatsLog( "CBaseGameStats::Event_Credits\n" ); - - float elapsed = 0.0f; - if( CBGSDriver.m_bInLevel ) - { - elapsed = gpGlobals->realtime - CBGSDriver.m_flLevelStartTime; - } - - if( elapsed < 0.0f ) - { - Assert( 0 ); - Warning( "EVENT_CREDITS with negative elapsed time (rt %f starttime %f)\n", gpGlobals->realtime, CBGSDriver.m_flLevelStartTime ); - elapsed = 0.0f; - } - - // Only set this one time!!! - if( gamestats->m_BasicStats.m_nSecondsToCompleteGame == 0 ) - { - if( gamestats->UserPlayedAllTheMaps() ) - { - gamestats->m_BasicStats.m_nSecondsToCompleteGame = (int)(elapsed + gamestats->m_BasicStats.m_Summary.m_nSeconds); - gamestats->SaveToFileNOW(); - } - } -} - -void CBaseGameStats::Event_CrateSmashed() -{ - StatsLog( "CBaseGameStats::Event_CrateSmashed\n" ); -} - -void CBaseGameStats::Event_Punted( CBaseEntity *pObject ) -{ - StatsLog( "CBaseGameStats::Event_Punted [%s]\n", pObject->GetClassname() ); -} - -void CBaseGameStats::Event_PlayerTraveled( CBasePlayer *pBasePlayer, float distanceInInches, bool bInVehicle, bool bSprinting ) -{ -} - -void CBaseGameStats::Event_FlippedVehicle( CBasePlayer *pDriver, CPropVehicleDriveable *pVehicle ) -{ - StatsLog( "CBaseGameStats::Event_FlippedVehicle [%s] flipped [%s]\n", pDriver->GetPlayerName(), pVehicle->GetClassname() ); -} - -// Called before .sav file is actually loaded (player should still be in previous level, if any) -void CBaseGameStats::Event_PreSaveGameLoaded( char const *pSaveName, bool bInGame ) -{ - StatsLog( "CBaseGameStats::Event_PreSaveGameLoaded [%s] %s\n", pSaveName, bInGame ? "in-game" : "at console" ); -} - -bool CBaseGameStats::SaveToFileNOW( bool bForceSyncWrite /* = false */ ) -{ - if ( !StatsTrackingIsFullyEnabled() ) - return false; - - // this code path is only for old format stats. Products that use new format take a different path. - if ( !gamestats->UseOldFormat() ) - return false; - - CUtlBuffer buf; - buf.PutShort( GAMESTATS_FILE_VERSION ); - buf.Put( s_szPseudoUniqueID, 16 ); - - if( ShouldTrackStandardStats() ) - m_BasicStats.SaveToBuffer( buf ); - else - buf.PutInt( GAMESTATS_STANDARD_NOT_SAVED ); - - gamestats->AppendCustomDataToSaveBuffer( buf ); - - char fullpath[ 512 ] = { 0 }; - if ( filesystem->FileExists( GetStatSaveFileName(), GAMESTATS_PATHID ) ) - { - filesystem->RelativePathToFullPath( GetStatSaveFileName(), GAMESTATS_PATHID, fullpath, sizeof( fullpath ) ); - } - else - { - // filename is local to game dir for Steam, so we need to prepend game dir for regular file save - char gamePath[256]; - engine->GetGameDir( gamePath, 256 ); - Q_StripTrailingSlash( gamePath ); - Q_snprintf( fullpath, sizeof( fullpath ), "%s/%s", gamePath, GetStatSaveFileName() ); - Q_strlower( fullpath ); - Q_FixSlashes( fullpath ); - } - - // StatsLog( "SaveToFileNOW '%s'\n", fullpath ); - - if( CBGSDriver.m_bShuttingDown || bForceSyncWrite ) //write synchronously - { - filesystem->WriteFile( fullpath, GAMESTATS_PATHID, buf ); - - StatsLog( "Shut down wrote to '%s'\n", fullpath ); - } - else - { - // Allocate memory for async system to use (and free afterward!!!) - size_t nBufferSize = buf.TellPut(); - void *pMem = malloc(nBufferSize); - CUtlBuffer statsBuffer( pMem, nBufferSize ); - statsBuffer.Put( buf.Base(), nBufferSize ); - - // Write data async - filesystem->AsyncWrite( fullpath, statsBuffer.Base(), statsBuffer.TellPut(), true, false ); - } - - return true; -} - -void CBaseGameStats::Event_PlayerConnected( CBasePlayer *pBasePlayer ) -{ - StatsLog( "CBaseGameStats::Event_PlayerConnected [%s]\n", pBasePlayer->GetPlayerName() ); -} - -void CBaseGameStats::Event_PlayerDisconnected( CBasePlayer *pBasePlayer ) -{ - StatsLog( "CBaseGameStats::Event_PlayerDisconnected\n", pBasePlayer->GetPlayerName() ); -} - -void CBaseGameStats::Event_PlayerDamage( CBasePlayer *pBasePlayer, const CTakeDamageInfo &info ) -{ - //StatsLog( "CBaseGameStats::Event_PlayerDamage [%s] took %.2f damage\n", pBasePlayer->GetPlayerName(), info.GetDamage() ); -} - -void CBaseGameStats::Event_PlayerKilledOther( CBasePlayer *pAttacker, CBaseEntity *pVictim, const CTakeDamageInfo &info ) -{ - StatsLog( "CBaseGameStats::Event_PlayerKilledOther [%s] killed [%s]\n", pAttacker->GetPlayerName(), pVictim->GetClassname() ); -} - -void CBaseGameStats::Event_WeaponFired( CBasePlayer *pShooter, bool bPrimary, char const *pchWeaponName ) -{ - StatsLog( "CBaseGameStats::Event_WeaponFired [%s] %s weapon [%s]\n", pShooter->GetPlayerName(), bPrimary ? "primary" : "secondary", pchWeaponName ); -} - -void CBaseGameStats::Event_WeaponHit( CBasePlayer *pShooter, bool bPrimary, char const *pchWeaponName, const CTakeDamageInfo &info ) -{ - StatsLog( "CBaseGameStats::Event_WeaponHit [%s] %s weapon [%s] damage [%f]\n", pShooter->GetPlayerName(), bPrimary ? "primary" : "secondary", pchWeaponName, info.GetDamage() ); -} - -void CBaseGameStats::Event_PlayerEnteredGodMode( CBasePlayer *pBasePlayer ) -{ - StatsLog( "CBaseGameStats::Event_PlayerEnteredGodMode [%s] entered GOD mode\n", pBasePlayer->GetPlayerName() ); -} - -void CBaseGameStats::Event_PlayerEnteredNoClip( CBasePlayer *pBasePlayer ) -{ - StatsLog( "CBaseGameStats::Event_PlayerEnteredNoClip [%s] entered NOCLIPe\n", pBasePlayer->GetPlayerName() ); -} - -void CBaseGameStats::Event_DecrementPlayerEnteredNoClip( CBasePlayer *pBasePlayer ) -{ - StatsLog( "CBaseGameStats::Event_DecrementPlayerEnteredNoClip [%s] decrementing NOCLIPe\n", pBasePlayer->GetPlayerName() ); -} - -void CBaseGameStats::Event_IncrementCountedStatistic( const Vector& vecAbsOrigin, char const *pchStatisticName, float flIncrementAmount ) -{ - StatsLog( "Incrementing %s by %f at pos (%d, %d, %d)\n", pchStatisticName, flIncrementAmount, (int)vecAbsOrigin.x, (int)vecAbsOrigin.y, (int)vecAbsOrigin.z ); -} - -bool CBaseGameStats::UploadStatsFileNOW( void ) -{ - if( !StatsTrackingIsFullyEnabled() || !HaveValidData() || !gamestats->UseOldFormat() ) - return false; - - if ( !filesystem->FileExists( gamestats->GetStatSaveFileName(), GAMESTATS_PATHID ) ) - { - return false; - } - - int curtime = (int)Plat_FloatTime(); - - CBGSDriver.m_tLastUpload = curtime; - - // Update the registry -#ifndef SWDS - IRegistry *reg = InstanceRegistry( "Steam" ); - Assert( reg ); - reg->WriteInt( GetStatUploadRegistryKeyName(), CBGSDriver.m_tLastUpload ); - ReleaseInstancedRegistry( reg ); -#endif - - CUtlBuffer buf; - filesystem->ReadFile( GetStatSaveFileName(), GAMESTATS_PATHID, buf ); - unsigned int uBlobSize = buf.TellPut(); - if ( uBlobSize == 0 ) - { - return false; - } - - const void *pvBlobData = ( const void * )buf.Base(); - - if( gamestatsuploader ) - { - return gamestatsuploader->UploadGameStats( "", - 1, - uBlobSize, - pvBlobData ); - } - - return false; -} - - -void CBaseGameStats::LoadingEvent_PlayerIDDifferentThanLoadedStats( void ) -{ - StatsLog( "CBaseGameStats::LoadingEvent_PlayerIDDifferentThanLoadedStats\n" ); -} - - -bool CBaseGameStats::LoadFromFile( void ) -{ - if ( filesystem->FileExists( gamestats->GetStatSaveFileName(), GAMESTATS_PATHID ) ) - { - char fullpath[ 512 ]; - filesystem->RelativePathToFullPath( gamestats->GetStatSaveFileName(), GAMESTATS_PATHID, fullpath, sizeof( fullpath ) ); - StatsLog( "Loading stats from '%s'\n", fullpath ); - } - - CUtlBuffer buf; - if ( filesystem->ReadFile( gamestats->GetStatSaveFileName(), GAMESTATS_PATHID, buf ) ) - { - bool bRetVal = true; - - int version = buf.GetShort(); - if ( version > GAMESTATS_FILE_VERSION ) - return false; //file is beyond our comprehension - - // Set global parse version - CBGSDriver.m_iLoadedVersion = version; - - buf.Get( CBGSDriver.m_szLoadedUserID, 16 ); - CBGSDriver.m_szLoadedUserID[ sizeof( CBGSDriver.m_szLoadedUserID ) - 1 ] = 0; - - if ( s_szPseudoUniqueID[ 0 ] != 0 ) - { - if ( Q_stricmp( CBGSDriver.m_szLoadedUserID, s_szPseudoUniqueID ) ) - { - //UserID changed, blow away log!!! - filesystem->RemoveFile( gamestats->GetStatSaveFileName(), GAMESTATS_PATHID ); - filesystem->RemoveFile( GAMESTATS_LOG_FILE, GAMESTATS_PATHID ); - Warning( "Userid changed, clearing stats file\n" ); - CBGSDriver.m_szLoadedUserID[0] = '\0'; - CBGSDriver.m_iLoadedVersion = -1; - gamestats->m_BasicStats.Clear(); - gamestats->LoadingEvent_PlayerIDDifferentThanLoadedStats(); - bRetVal = false; - } - - if ( version <= GAMESTATS_FILE_VERSION_OLD5 ) - { - gamestats->m_BasicStats.Clear(); - bRetVal = false; - } - else - { - // Peek ahead in buffer to see if we have the "no default stats" secret flag set. - int iCheckForStandardStatsInFile = *( int * )buf.PeekGet(); - bool bValid = true; - - if ( iCheckForStandardStatsInFile != (int)GAMESTATS_STANDARD_NOT_SAVED ) - { - //the GAMESTATS_STANDARD_NOT_SAVED flag coincides with user completion time, rewind so the gamestats parser can grab it - bValid = gamestats->m_BasicStats.ParseFromBuffer( buf, version ); - } - else - { - // skip over the flag - buf.GetInt(); - } - - if( !bValid ) - { - m_BasicStats.Clear(); - } - - if( ( buf.TellPut() - buf.TellGet() ) != 0 ) //more data left, must be custom data - { - gamestats->LoadCustomDataFromBuffer( buf ); - } - } - } - - return bRetVal; - } - else - { - filesystem->RemoveFile( GAMESTATS_LOG_FILE, GAMESTATS_PATHID ); - } - - return false; -} - -#endif // GAME_DLL - -bool CBaseGameStats_Driver::Init() -{ - const char *pGameDir = CommandLine()->ParmValue( "-game", "hl2" ); - - //standardizing is a good thing - char szLoweredGameDir[256]; - Q_strncpy( szLoweredGameDir, pGameDir, sizeof( szLoweredGameDir ) ); - Q_strlower( szLoweredGameDir ); - - gamestats = gamestats->OnInit( gamestats, szLoweredGameDir ); - - //determine constant strings needed for saving and uploading - Q_strncpy( s_szSaveFileName, szLoweredGameDir, sizeof( s_szSaveFileName ) ); - Q_strncat( s_szSaveFileName, "_gamestats.dat", sizeof( s_szSaveFileName ) ); - - Q_strncpy( s_szStatUploadRegistryKeyName, "GameStatsUpload_", sizeof( s_szStatUploadRegistryKeyName ) ); - Q_strncat( s_szStatUploadRegistryKeyName, szLoweredGameDir, sizeof( s_szStatUploadRegistryKeyName ) ); - - gamestats->m_bLoggingToFile = CommandLine()->FindParm( "-gamestatsloggingtofile" ) ? true : false; - gamestats->m_bLogging = CommandLine()->FindParm( "-gamestatslogging" ) ? true : false; - - if ( gamestatsuploader ) - { - m_bEnabled = gamestatsuploader->IsGameStatsLoggingEnabled(); - if ( m_bEnabled ) - { - gamestatsuploader->GetPseudoUniqueId( s_szPseudoUniqueID, sizeof( s_szPseudoUniqueID ) ); - } - } - - ResetData(); - -#ifdef GAME_DLL - if ( StatsTrackingIsFullyEnabled() ) - { - // FIXME: Load m_tLastUpload from registry and save it back out, too -#ifndef SWDS - IRegistry *reg = InstanceRegistry( "Steam" ); - Assert( reg ); - m_tLastUpload = reg->ReadInt( gamestats->GetStatUploadRegistryKeyName(), 0 ); - ReleaseInstancedRegistry( reg ); -#endif - //load existing stats - gamestats->LoadFromFile(); - } -#endif // GAME_DLL - - if ( s_szPseudoUniqueID[ 0 ] != 0 ) - { - gamestats->Event_Init(); -#ifdef GAME_DLL - if ( gamestats->UseOldFormat() ) - { - if( gamestats->AutoSave_OnInit() ) - gamestats->SaveToFileNOW(); - - if( gamestats->AutoUpload_OnInit() ) - gamestats->UploadStatsFileNOW(); - } -#endif - } - else - { - m_bEnabled = false; //unable to generate a pseudo-unique ID, disable tracking - } - - return true; -} - - -void CBaseGameStats_Driver::Shutdown() -{ - m_bShuttingDown = true; - - gamestats->Event_Shutdown(); - - if ( gamestats->UseOldFormat() ) - { -#ifdef GAME_DLL - if( gamestats->AutoSave_OnShutdown() ) - gamestats->SaveToFileNOW(); - - if( gamestats->AutoUpload_OnShutdown() ) - gamestats->UploadStatsFileNOW(); -#endif // GAME_DLL - } - else - { - // code path for new format game stats - if ( gamestats->ShouldSendDataOnAppShutdown() ) - { - CollectData( STATSEND_APPSHUTDOWN ); - SendData(); - } - } - if ( FILESYSTEM_INVALID_HANDLE != g_LogFileHandle ) - { - filesystem->Close( g_LogFileHandle ); - g_LogFileHandle = FILESYSTEM_INVALID_HANDLE; - } - - if ( m_pGamestatsData != NULL ) - { -#ifdef CLIENT_DLL - engine->SetGamestatsData( NULL ); -#endif - delete m_pGamestatsData; - m_pGamestatsData = NULL; - } -} - -void CBaseGameStats_Driver::PossibleMapChange( void ) -{ -#ifdef GAME_DLL - //detect and copy map changes - if ( Q_stricmp( m_PrevMapName.String(), STRING( gpGlobals->mapname ) ) ) - { - MEM_ALLOC_CREDIT(); - - CUtlString PrevMapBackup = m_PrevMapName; - - m_PrevMapName = STRING( gpGlobals->mapname ); - - gamestats->Event_MapChange( PrevMapBackup.String(), STRING( gpGlobals->mapname ) ); - - if ( gamestats->UseOldFormat() ) - { - if( gamestats->AutoSave_OnMapChange() ) - gamestats->SaveToFileNOW(); - - if( gamestats->AutoUpload_OnMapChange() ) - gamestats->UploadStatsFileNOW(); - } - } -#endif -} - - - -void CBaseGameStats_Driver::LevelInitPreEntity() -{ - m_bInLevel = true; - m_bFirstLevel = false; - - if ( Q_stricmp( s_szPseudoUniqueID, "unknown" ) == 0 ) - { - // "unknown" means this is a dedicated server and we weren't able to generate a unique ID (e.g. Linux server). - // Change the unique ID to be a hash of IP & port. We couldn't do this earlier because IP is not known until level - // init time. - ConVar *hostip = cvar->FindVar( "hostip" ); - ConVar *hostport = cvar->FindVar( "hostport" ); - if ( hostip && hostport ) - { - int crcInput[2]; - crcInput[0] = hostip->GetInt(); - crcInput[1] = hostport->GetInt(); - if ( crcInput[0] && crcInput[1] ) - { - CRC32_t crc = CRC32_ProcessSingleBuffer( crcInput, sizeof( crcInput ) ); - Q_snprintf( s_szPseudoUniqueID, ARRAYSIZE( s_szPseudoUniqueID ), "H:%x", crc ); - } - } - } - - PossibleMapChange(); - - m_flPauseStartTime = 0.0f; - m_flLevelStartTime = gpGlobals->realtime; - - gamestats->Event_LevelInit(); - -#ifdef GAME_DLL - if ( gamestats->UseOldFormat() ) - { - if( gamestats->AutoSave_OnLevelInit() ) - gamestats->SaveToFileNOW(); - - if( gamestats->AutoUpload_OnLevelInit() ) - gamestats->UploadStatsFileNOW(); - } -#endif -} - - -void CBaseGameStats_Driver::LevelShutdownPreEntity() -{ - float flElapsed = gpGlobals->realtime - m_flLevelStartTime; - - if ( flElapsed < 0.0f ) - { - Assert( 0 ); - Warning( "EVENT_LEVELSHUTDOWN: with negative elapsed time (rt %f starttime %f)\n", gpGlobals->realtime, m_flLevelStartTime ); - flElapsed = 0.0f; - } - - //Assert( m_bInLevel ); //so, apparently shutdowns can happen before inits - -#ifdef GAME_DLL - if ( m_bInLevel && ( gpGlobals->eLoadType != MapLoad_Background ) ) -#else - if ( m_bInLevel ) -#endif - { - m_flTotalTimeInLevels += flElapsed; - m_iNumLevels ++; - - gamestats->Event_LevelShutdown( flElapsed ); - - if ( gamestats->UseOldFormat() ) - { -#ifdef GAME_DLL - if( gamestats->AutoSave_OnLevelShutdown() ) - gamestats->SaveToFileNOW( true ); - - if( gamestats->AutoUpload_OnLevelShutdown() ) - gamestats->UploadStatsFileNOW(); -#endif - } - else - { - // code path for new format game stats - CollectData( STATSEND_LEVELSHUTDOWN ); - if ( gamestats->ShouldSendDataOnLevelShutdown() ) - { - SendData(); - } - } - m_bInLevel = false; - } -} - -void CBaseGameStats_Driver::OnSave() -{ - gamestats->Event_SaveGame(); -} - - -void CBaseGameStats_Driver::CollectData( StatSendType_t sendType ) -{ - CGamestatsData *pGamestatsData = NULL; -#ifdef GAME_DLL - // for server, check with the engine to see if there already a gamestats data container registered. (There will be if there is a client - // running in the same process.) - pGamestatsData = engine->GetGamestatsData(); - if ( pGamestatsData ) - { - // use the registered gamestats container, so free the one we allocated - if ( m_pGamestatsData != NULL ) - { - delete m_pGamestatsData; - m_pGamestatsData = NULL; - } - } - else - { - pGamestatsData = m_pGamestatsData; - } -#else - pGamestatsData = m_pGamestatsData; -#endif - Assert( pGamestatsData ); - KeyValues *pKV = pGamestatsData->m_pKVData; - - int iAppID = engine->GetAppID(); - pKV->SetInt( "appid", iAppID ); - - switch ( sendType ) - { - case STATSEND_LEVELSHUTDOWN: - { - // make a map node in the KeyValues to use for this level - char szMap[MAX_PATH+1]=""; -#ifdef CLIENT_DLL - Q_FileBase( engine->GetLevelName(), szMap, ARRAYSIZE( szMap ) ); -#else - Q_strncpy( szMap, gpGlobals->mapname.ToCStr(), ARRAYSIZE( szMap ) ); -#endif // CLIENT_DLL - if ( !szMap[0] ) - return; - KeyValues *pKVMap = new KeyValues( "map" ); - pKV->AddSubKey( pKVMap ); - pKVMap->SetString( "mapname", szMap ); - pKV = pKVMap; - - } - break; - case STATSEND_APPSHUTDOWN: - break; - default: - Assert( false ); - break; - } - - // add common data - pGamestatsData->m_bHaveData |= AddBaseDataForSend( pKV, sendType ); - // add game-specific data - pGamestatsData->m_bHaveData |= gamestats->AddDataForSend( pKV, sendType ); -} - - -void CBaseGameStats_Driver::SendData() -{ - // if we don't own the data container or there's no valid data, nothing to do - if ( !m_pGamestatsData || !m_pGamestatsData->m_bHaveData ) - return; - - // save the data to a buffer - CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); - m_pGamestatsData->m_pKVData->RecursiveSaveToFile( buf, 0 ); - - if ( CommandLine()->FindParm( "-gamestatsfileoutputonly" ) ) - { - // write file for debugging - const char szFileName[] = "gamestats.dat"; - filesystem->WriteFile( szFileName, GAMESTATS_PATHID, buf ); - } - else - { - // upload the file to Steam - if ( gamestatsuploader ) - gamestatsuploader->UploadGameStats( "", 1, buf.TellPut(), buf.Base() ); - } - - ResetData(); -} - -bool CBaseGameStats_Driver::AddBaseDataForSend( KeyValues *pKV, StatSendType_t sendType ) -{ - switch ( sendType ) - { - case STATSEND_APPSHUTDOWN: -#ifdef CLIENT_DLL - if ( m_iNumLevels > 0 ) - { - // add playtime data - KeyValues *pKVData = new KeyValues( "playtime" ); - pKVData->SetInt( "TotalLevelTime", m_flTotalTimeInLevels ); - pKVData->SetInt( "NumLevels", m_iNumLevels ); - pKV->AddSubKey( pKVData ); - return true; - } -#endif - break; - case STATSEND_LEVELSHUTDOWN: -#ifdef CLIENT_DLL - if ( m_bBufferFull ) - { - // add perf data - KeyValues *pKVPerf = new KeyValues( "perfdata" ); - float flAverageFrameRate = AverageStat( &StatsBufferRecord_t::m_flFrameRate ); - float flMinFrameRate = MinStat( &StatsBufferRecord_t::m_flFrameRate ); - float flMaxFrameRate = MaxStat( &StatsBufferRecord_t::m_flFrameRate ); - - pKVPerf->SetFloat( "AvgFPS", flAverageFrameRate ); - pKVPerf->SetFloat( "MinFPS", flMinFrameRate ); - pKVPerf->SetFloat( "MaxFPS", flMaxFrameRate ); - - pKV->AddSubKey( pKVPerf ); - - return true; - } -#endif - break; - } - - return false; -} - - -void CBaseGameStats_Driver::ResetData() -{ -#ifdef GAME_DLL - // on the server, if there is a gamestats data container registered (by a client in the same process), they're in charge of resetting it, nothing for us to do - if ( engine->GetGamestatsData() != NULL ) - return; -#endif - - if ( m_pGamestatsData != NULL ) - { - delete m_pGamestatsData; - m_pGamestatsData = NULL; - } - - m_pGamestatsData = new CGamestatsData(); - KeyValues *pKV = m_pGamestatsData->m_pKVData; - - pKV->SetInt( "version", GAMESTATS_VERSION ); - pKV->SetString( "srcid", s_szPseudoUniqueID ); - -#ifdef CLIENT_DLL - const CPUInformation &cpu = GetCPUInformation(); - OverWriteCharsWeHate( cpu.m_szProcessorID ); - pKV->SetString( "CPUID", cpu.m_szProcessorID ); - pKV->SetFloat( "CPUGhz", cpu.m_Speed * ( 1.0 / 1.0e9 ) ); - pKV->SetInt( "NumCores", cpu.m_nPhysicalProcessors ); - - MaterialAdapterInfo_t gpu; - materials->GetDisplayAdapterInfo( materials->GetCurrentAdapter(), gpu ); - - CMatRenderContextPtr pRenderContext( materials ); - int dest_width,dest_height; - pRenderContext->GetRenderTargetDimensions( dest_width, dest_height ); - - if ( gpu.m_pDriverName ) - { - OverWriteCharsWeHate( gpu.m_pDriverName ); - } - pKV->SetString( "GPUDrv", SafeString( gpu.m_pDriverName ) ); - pKV->SetInt( "GPUVendor", gpu.m_VendorID ); - pKV->SetInt( "GPUDeviceID", gpu.m_DeviceID ); - pKV->SetString( "GPUDriverVersion", CFmtStr( "%d.%d", gpu.m_nDriverVersionHigh, gpu.m_nDriverVersionLow ) ); - pKV->SetInt( "DxLvl", g_pMaterialSystemHardwareConfig->GetDXSupportLevel() ); - pKV->SetInt( "Width", dest_width ); - pKV->SetInt( "Height", dest_height ); - - engine->SetGamestatsData( m_pGamestatsData ); -#endif -} - -void CBaseGameStats_Driver::OnRestore() -{ - PossibleMapChange(); - - gamestats->Event_LoadGame(); -} - - -void CBaseGameStats_Driver::FrameUpdatePostEntityThink() -{ - bool bGamePaused = ( gpGlobals->frametime == 0.0f ); - - if ( !m_bInLevel ) - { - m_flPauseStartTime = 0.0f; - } - else if ( m_bGamePaused != bGamePaused ) - { - if ( bGamePaused ) - { - m_flPauseStartTime = gpGlobals->realtime; - } - else if ( m_flPauseStartTime != 0.0f ) - { - float flPausedTime = gpGlobals->realtime - m_flPauseStartTime; - if ( flPausedTime < 0.0f ) - { - Assert( 0 ); - Warning( "Game paused time showing up negative (rt %f pausestart %f)\n", gpGlobals->realtime, m_flPauseStartTime ); - flPausedTime = 0.0f; - } - - // Remove this from global time counters - - // Msg( "Pause: adding %f to level starttime\n", flPausedTime ); - - m_flLevelStartTime += flPausedTime; - m_flPauseStartTime = 0.0f; - - // Msg( "Paused for %.2f seconds\n", flPausedTime ); - } - m_bGamePaused = bGamePaused; - } -} - -bool StatsTrackingIsFullyEnabled( void ) -{ - return CBGSDriver.m_bEnabled && gamestats->StatTrackingEnabledForMod(); -} - -void CBaseGameStats::Clear( void ) -{ -#ifdef GAME_DLL - gamestats->m_BasicStats.Clear(); -#endif -} - -//----------------------------------------------------------------------------- -// Nukes any dangerous characters and replaces w/space char -//----------------------------------------------------------------------------- -void OverWriteCharsWeHate( char *pStr ) -{ - while( *pStr ) - { - switch( *pStr ) - { - case '\n': - case '\r': - case '\\': - case '\"': - case '\'': - case '\032': - case ';': - *pStr = ' '; - } - pStr++; - } -} - -#ifdef GAME_DLL - -void CBaseGameStats::SetSteamStatistic( bool bUsingSteam ) -{ - if( CBGSDriver.m_bFirstLevel ) - { - m_BasicStats.m_Summary.m_bSteam = bUsingSteam; - } - - if( CBGSDriver.m_bInLevel ) - { - BasicGameStatsRecord_t *map = m_BasicStats.FindOrAddRecordForMap( CBGSDriver.m_PrevMapName.String() ); - map->m_bSteam = bUsingSteam; - } - - m_BasicStats.m_bSteam = bUsingSteam; -} - -void CBaseGameStats::SetCyberCafeStatistic( bool bIsCyberCafeUser ) -{ - if( CBGSDriver.m_bFirstLevel ) - { - m_BasicStats.m_Summary.m_bCyberCafe = bIsCyberCafeUser; - } - - if( CBGSDriver.m_bInLevel ) - { - BasicGameStatsRecord_t *map = m_BasicStats.FindOrAddRecordForMap( CBGSDriver.m_PrevMapName.String() ); - map->m_bCyberCafe = bIsCyberCafeUser; - } - - m_BasicStats.m_bCyberCafe = bIsCyberCafeUser; -} - -void CBaseGameStats::SetHDRStatistic( bool bHDREnabled ) -{ - if( bHDREnabled ) - { - if( CBGSDriver.m_bInLevel ) - { - BasicGameStatsRecord_t *map = m_BasicStats.FindOrAddRecordForMap( CBGSDriver.m_PrevMapName.String() ); - ++map->m_nHDR; - } - - if( CBGSDriver.m_bFirstLevel ) - { - ++m_BasicStats.m_Summary.m_nHDR; - } - } -} - -void CBaseGameStats::SetCaptionsStatistic( bool bClosedCaptionsEnabled ) -{ - if( CBGSDriver.m_bInLevel ) - { - BasicGameStatsRecord_t *map = m_BasicStats.FindOrAddRecordForMap( CBGSDriver.m_PrevMapName.String() ); - ++map->m_nCaptions; - } - - if( CBGSDriver.m_bFirstLevel ) - { - ++m_BasicStats.m_Summary.m_nCaptions; - } -} - -void CBaseGameStats::SetSkillStatistic( int iSkillSetting ) -{ - int skill = clamp( iSkillSetting, 1, 3 ) - 1; - - if( CBGSDriver.m_bInLevel ) - { - BasicGameStatsRecord_t *map = m_BasicStats.FindOrAddRecordForMap( CBGSDriver.m_PrevMapName.String() ); - ++map->m_nSkill[ skill ]; - } - - if ( CBGSDriver. m_bFirstLevel ) - { - ++m_BasicStats.m_Summary.m_nSkill[ skill ]; - } -} - -void CBaseGameStats::SetDXLevelStatistic( int iDXLevel ) -{ - m_BasicStats.m_nDXLevel = iDXLevel; -} - -void CBaseGameStats::SetHL2UnlockedChapterStatistic( void ) -{ - // Now grab the hl2/cfg/config.cfg and suss out the sv_unlockedchapters cvar to estimate how far they got in HL2 - char const *relative = "cfg/config.cfg"; - char fullpath[ 512 ]; - char gamedir[256]; - engine->GetGameDir( gamedir, 256 ); - Q_snprintf( fullpath, sizeof( fullpath ), "%s/../hl2/%s", gamedir, relative ); - - if ( filesystem->FileExists( fullpath ) ) - { - FileHandle_t fh = filesystem->Open( fullpath, "rb" ); - if ( FILESYSTEM_INVALID_HANDLE != fh ) - { - // read file into memory - int size = filesystem->Size(fh); - char *configBuffer = new char[ size + 1 ]; - filesystem->Read( configBuffer, size, fh ); - configBuffer[size] = 0; - filesystem->Close( fh ); - - // loop through looking for all the cvars to apply - const char *search = Q_stristr(configBuffer, "sv_unlockedchapters" ); - if ( search ) - { - // read over the token - search = strtok( (char *)search, " \n" ); - search = strtok( NULL, " \n" ); - - if ( search[0]== '\"' ) - ++search; - - // read the value - int iChapter = Q_atoi( search ); - m_BasicStats.m_nHL2ChaptureUnlocked = iChapter; - } - - // free - delete [] configBuffer; - } - } -} - -static void CC_ResetGameStats( const CCommand &args ) -{ - gamestats->Clear(); - gamestats->SaveToFileNOW(); - gamestats->StatsLog( "CC_ResetGameStats : Server cleared game stats\n" ); -} - -static ConCommand resetGameStats("_resetgamestats", CC_ResetGameStats, "Erases current game stats and writes out a blank stats file", 0 ); - -class CPointGamestatsCounter : public CPointEntity -{ -public: - DECLARE_CLASS( CPointGamestatsCounter, CPointEntity ); - DECLARE_DATADESC(); - - CPointGamestatsCounter(); - -protected: - - void InputSetName( inputdata_t &inputdata ); - void InputIncrement( inputdata_t &inputdata ); - - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); -private: - - string_t m_strStatisticName; - bool m_bDisabled; -}; - -BEGIN_DATADESC( CPointGamestatsCounter ) - - DEFINE_KEYFIELD( m_strStatisticName, FIELD_STRING, "Name" ), - DEFINE_FIELD( m_bDisabled, FIELD_BOOLEAN ), - - // Inputs - DEFINE_INPUTFUNC( FIELD_STRING, "SetName", InputSetName ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "Increment", InputIncrement ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( point_gamestats_counter, CPointGamestatsCounter ) - - -CPointGamestatsCounter::CPointGamestatsCounter() : - m_strStatisticName( NULL_STRING ), - m_bDisabled( false ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: Changes name of statistic -//----------------------------------------------------------------------------- -void CPointGamestatsCounter::InputSetName( inputdata_t &inputdata ) -{ - m_strStatisticName = inputdata.value.StringID(); -} - -//----------------------------------------------------------------------------- -// Purpose: Changes name of statistic -//----------------------------------------------------------------------------- -void CPointGamestatsCounter::InputIncrement( inputdata_t &inputdata ) -{ - if ( m_bDisabled ) - return; - - if ( NULL_STRING == m_strStatisticName ) - { - DevMsg( 1, "CPointGamestatsCounter::InputIncrement: No stat name specified for point_gamestats_counter @%f, %f, %f [ent index %d]\n", - GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z, entindex() ); - return; - } - - gamestats->Event_IncrementCountedStatistic( GetAbsOrigin(), STRING( m_strStatisticName ), inputdata.value.Float() ); -} - -void CPointGamestatsCounter::InputEnable( inputdata_t &inputdata ) -{ - m_bDisabled = false; -} - -void CPointGamestatsCounter::InputDisable( inputdata_t &inputdata ) -{ - m_bDisabled = true; -} - -#endif // GAME_DLL diff --git a/game/shared/GameStats.h b/game/shared/GameStats.h deleted file mode 100644 index 2adf4d079..000000000 --- a/game/shared/GameStats.h +++ /dev/null @@ -1,337 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef GAMESTATS_H -#define GAMESTATS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/utldict.h" -#include "tier1/utlbuffer.h" -#include "igamesystem.h" - -const int GAMESTATS_VERSION = 1; - -enum StatSendType_t -{ - STATSEND_LEVELSHUTDOWN, - STATSEND_APPSHUTDOWN -}; - -struct StatsBufferRecord_t -{ - float m_flFrameRate; // fps - -}; - -#define STATS_WINDOW_SIZE ( 60 * 10 ) // # of records to hold -#define STATS_RECORD_INTERVAL 1 // # of seconds between data grabs. 2 * 300 = every 10 minutes - -class CGameStats; - -void UpdatePerfStats( void ); -void SetGameStatsHandler( CGameStats *pGameStats ); - -class CBasePlayer; -class CPropVehicleDriveable; -class CTakeDamageInfo; - -#ifdef GAME_DLL - -#define GAMESTATS_STANDARD_NOT_SAVED 0xFEEDBEEF - -enum GameStatsVersions_t -{ - GAMESTATS_FILE_VERSION_OLD = 001, - GAMESTATS_FILE_VERSION_OLD2, - GAMESTATS_FILE_VERSION_OLD3, - GAMESTATS_FILE_VERSION_OLD4, - GAMESTATS_FILE_VERSION_OLD5, - GAMESTATS_FILE_VERSION -}; - -struct BasicGameStatsRecord_t -{ -public: - BasicGameStatsRecord_t() : - m_nCount( 0 ), - m_nSeconds( 0 ), - m_nCommentary( 0 ), - m_nHDR( 0 ), - m_nCaptions( 0 ), - m_bSteam( true ), - m_bCyberCafe( false ), - m_nDeaths( 0 ) - { - Q_memset( m_nSkill, 0, sizeof( m_nSkill ) ); - } - - void Clear(); - - void SaveToBuffer( CUtlBuffer& buf ); - bool ParseFromBuffer( CUtlBuffer& buf, int iBufferStatsVersion ); - - // Data -public: - int m_nCount; - int m_nSeconds; - - int m_nCommentary; - int m_nHDR; - int m_nCaptions; - int m_nSkill[ 3 ]; - bool m_bSteam; - bool m_bCyberCafe; - int m_nDeaths; -}; - -struct BasicGameStats_t -{ -public: - BasicGameStats_t() : - m_nSecondsToCompleteGame( 0 ), - m_bSteam( true ), - m_bCyberCafe( false ), - m_nHL2ChaptureUnlocked( 0 ), - m_nDXLevel( 0 ) - { - } - - void Clear(); - - void SaveToBuffer( CUtlBuffer& buf ); - bool ParseFromBuffer( CUtlBuffer& buf, int iBufferStatsVersion ); - - BasicGameStatsRecord_t *FindOrAddRecordForMap( char const *mapname ); - - // Data -public: - int m_nSecondsToCompleteGame; // 0 means they haven't finished playing yet - - BasicGameStatsRecord_t m_Summary; // Summary record - CUtlDict< BasicGameStatsRecord_t, unsigned short > m_MapTotals; - bool m_bSteam; - bool m_bCyberCafe; - int m_nHL2ChaptureUnlocked; - int m_nDXLevel; -}; -#endif // GAME_DLL - -class CBaseGameStats -{ -public: - CBaseGameStats(); - - // override this to declare what format you want to send. New products should use new format. - virtual bool UseOldFormat() - { -#ifdef GAME_DLL - return true; // servers by default send old format for backward compat -#else - return false; // clients never used old format so no backward compat issues, they use new format by default -#endif - } - - // Implement this if you support new format gamestats. - // Return true if you added data to KeyValues, false if you have no data to report - virtual bool AddDataForSend( KeyValues *pKV, StatSendType_t sendType ) { return false; } - - // These methods used for new format gamestats only and control when data gets sent. - virtual bool ShouldSendDataOnLevelShutdown() - { - // by default, servers send data at every level change and clients don't -#ifdef GAME_DLL - return true; -#else - return false; -#endif - } - virtual bool ShouldSendDataOnAppShutdown() - { - // by default, clients send data at app shutdown and servers don't -#ifdef GAME_DLL - return false; -#else - return true; -#endif - } - - virtual void Event_Init( void ); - virtual void Event_Shutdown( void ); - virtual void Event_MapChange( const char *szOldMapName, const char *szNewMapName ); - virtual void Event_LevelInit( void ); - virtual void Event_LevelShutdown( float flElapsed ); - virtual void Event_SaveGame( void ); - virtual void Event_LoadGame( void ); - - void StatsLog( char const *fmt, ... ); - - // This is the first call made, so that we can "subclass" the CBaseGameStats based on gamedir as needed (e.g., ep2 vs. episodic) - virtual CBaseGameStats *OnInit( CBaseGameStats *pCurrentGameStats, char const *gamedir ) { return pCurrentGameStats; } - - // Frees up data from gamestats and resets it to a clean state. - virtual void Clear( void ); - - virtual bool StatTrackingEnabledForMod( void ) { return false; } //Override this to turn on the system. Stat tracking is disabled by default and will always be disabled at the user's request - static bool StatTrackingAllowed( void ); //query whether stat tracking is possible and warranted by the user - virtual bool HaveValidData( void ) { return true; } // whether we currently have an interesting enough data set to upload. Called at upload time; if false, data is not uploaded. - - virtual bool ShouldTrackStandardStats( void ) { return true; } //exactly what was tracked for EP1 release - - //Get mod specific strings used for tracking, defaults should work fine for most cases - virtual const char *GetStatSaveFileName( void ); - virtual const char *GetStatUploadRegistryKeyName( void ); - const char *GetUserPseudoUniqueID( void ); - - virtual bool UserPlayedAllTheMaps( void ) { return false; } //be sure to override this to determine user completion time - -#ifdef GAME_DLL - virtual void Event_PlayerKilled( CBasePlayer *pPlayer, const CTakeDamageInfo &info ); - virtual void Event_PlayerConnected( CBasePlayer *pBasePlayer ); - virtual void Event_PlayerDisconnected( CBasePlayer *pBasePlayer ); - virtual void Event_PlayerDamage( CBasePlayer *pBasePlayer, const CTakeDamageInfo &info ); - virtual void Event_PlayerKilledOther( CBasePlayer *pAttacker, CBaseEntity *pVictim, const CTakeDamageInfo &info ); - virtual void Event_Credits(); - virtual void Event_Commentary(); - virtual void Event_CrateSmashed(); - virtual void Event_Punted( CBaseEntity *pObject ); - virtual void Event_PlayerTraveled( CBasePlayer *pBasePlayer, float distanceInInches, bool bInVehicle, bool bSprinting ); - virtual void Event_WeaponFired( CBasePlayer *pShooter, bool bPrimary, char const *pchWeaponName ); - virtual void Event_WeaponHit( CBasePlayer *pShooter, bool bPrimary, char const *pchWeaponName, const CTakeDamageInfo &info ); - virtual void Event_FlippedVehicle( CBasePlayer *pDriver, CPropVehicleDriveable *pVehicle ); - virtual void Event_PreSaveGameLoaded( char const *pSaveName, bool bInGame ); - virtual void Event_PlayerEnteredGodMode( CBasePlayer *pBasePlayer ); - virtual void Event_PlayerEnteredNoClip( CBasePlayer *pBasePlayer ); - virtual void Event_DecrementPlayerEnteredNoClip( CBasePlayer *pBasePlayer ); - virtual void Event_IncrementCountedStatistic( const Vector& vecAbsOrigin, char const *pchStatisticName, float flIncrementAmount ); - //custom data to tack onto existing stats if you're not doing a complete overhaul - virtual void AppendCustomDataToSaveBuffer( CUtlBuffer &SaveBuffer ) { } //custom data you want thrown into the default save and upload path - virtual void LoadCustomDataFromBuffer( CUtlBuffer &LoadBuffer ) { }; //when loading the saved stats file, this will point to where you started saving data to the save buffer - - virtual void LoadingEvent_PlayerIDDifferentThanLoadedStats( void ); //Only called if you use the base SaveToFileNOW() and LoadFromFile() functions. Used in case you want to keep/invalidate data that was just loaded. - - virtual bool LoadFromFile( void ); //called just before Event_Init() - virtual bool SaveToFileNOW( bool bForceSyncWrite = false ); //saves buffers to their respective files now, returns success or failure - virtual bool UploadStatsFileNOW( void ); //uploads data to the CSER now, returns success or failure - - static bool AppendLump( int nMaxLumpCount, CUtlBuffer &SaveBuffer, unsigned short iLump, unsigned short iLumpCount, size_t nSize, void *pData ); - static bool GetLumpHeader( int nMaxLumpCount, CUtlBuffer &LoadBuffer, unsigned short &iLump, unsigned short &iLumpCount, bool bPermissive = false ); - static void LoadLump( CUtlBuffer &LoadBuffer, unsigned short iLumpCount, size_t nSize, void *pData ); - - //default save behavior is to save on level shutdown, and game shutdown - virtual bool AutoSave_OnInit( void ) { return false; } - virtual bool AutoSave_OnShutdown( void ) { return true; } - virtual bool AutoSave_OnMapChange( void ) { return false; } - virtual bool AutoSave_OnLevelInit( void ) { return false; } - virtual bool AutoSave_OnLevelShutdown( void ) { return true; } - - //default upload behavior is to upload on game shutdown - virtual bool AutoUpload_OnInit( void ) { return false; } - virtual bool AutoUpload_OnShutdown( void ) { return true; } - virtual bool AutoUpload_OnMapChange( void ) { return false; } - virtual bool AutoUpload_OnLevelInit( void ) { return false; } - virtual bool AutoUpload_OnLevelShutdown( void ) { return false; } - - // Helper for builtin stuff - void SetSteamStatistic( bool bUsingSteam ); - void SetCyberCafeStatistic( bool bIsCyberCafeUser ); - void SetHDRStatistic( bool bHDREnabled ); - void SetCaptionsStatistic( bool bClosedCaptionsEnabled ); - void SetSkillStatistic( int iSkillSetting ); - void SetDXLevelStatistic( int iDXLevel ); - void SetHL2UnlockedChapterStatistic( void ); -#endif // GAMEDLL -public: -#ifdef GAME_DLL - BasicGameStats_t m_BasicStats; //exposed in case you do a complete overhaul and still want to save it -#endif - bool m_bLogging : 1; - bool m_bLoggingToFile : 1; -}; - -#ifdef GAME_DLL - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &SaveBuffer - -// iLump - -// iLumpCount - -//----------------------------------------------------------------------------- -inline bool CBaseGameStats::AppendLump( int nMaxLumpCount, CUtlBuffer &SaveBuffer, unsigned short iLump, unsigned short iLumpCount, size_t nSize, void *pData ) -{ - // Verify the lump index. - Assert( ( iLump > 0 ) && ( iLump < nMaxLumpCount ) ); - - if ( !( ( iLump > 0 ) && ( iLump < nMaxLumpCount ) ) ) - return false; - - // Check to see if we have any elements to save. - if ( iLumpCount <= 0 ) - return false; - - // Write the lump id and element count. - SaveBuffer.PutUnsignedShort( iLump ); - SaveBuffer.PutUnsignedShort( iLumpCount ); - - size_t nTotalSize = iLumpCount * nSize; - SaveBuffer.Put( pData, nTotalSize ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &LoadBuffer - -// &iLump - -// &iLumpCount - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -inline bool CBaseGameStats::GetLumpHeader( int nMaxLumpCount, CUtlBuffer &LoadBuffer, unsigned short &iLump, unsigned short &iLumpCount, bool bPermissive /*= false*/ ) -{ - // Get the lump id and element count. - iLump = LoadBuffer.GetUnsignedShort(); - if ( !LoadBuffer.IsValid() ) - { - // check for EOF - return false; - } - iLumpCount = LoadBuffer.GetUnsignedShort(); - - if ( bPermissive ) - return true; - - // Verify the lump index. - Assert( ( iLump > 0 ) && ( iLump < nMaxLumpCount ) ); - if ( !( ( iLump > 0 ) && ( iLump < nMaxLumpCount ) ) ) - { - return false; - } - - // Check to see if we have any elements to save. - if ( iLumpCount <= 0 ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Loads 1 or more lumps of raw data -// Input : &LoadBuffer - buffer to be read from -// iLumpCount - # of lumps to read -// nSize - size of each lump -// pData - where to store the data -//----------------------------------------------------------------------------- -inline void CBaseGameStats::LoadLump( CUtlBuffer &LoadBuffer, unsigned short iLumpCount, size_t nSize, void *pData ) -{ - LoadBuffer.Get( pData, iLumpCount * nSize ); -} - -extern CBaseGameStats *gamestats; //starts out pointing at a singleton of the class above, overriding this in any constructor should work for replacing it - -#endif // GAME_DLL - -#endif // GAMESTATS_H diff --git a/game/shared/IEffects.h b/game/shared/IEffects.h deleted file mode 100644 index 908052762..000000000 --- a/game/shared/IEffects.h +++ /dev/null @@ -1,82 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Client-server neutral effects interface -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IEFFECTS_H -#define IEFFECTS_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "basetypes.h" -#include "mathlib/vector.h" -#include "interface.h" -#include "ipredictionsystem.h" - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -enum ShakeCommand_t; -class Vector; -class CGameTrace; -typedef CGameTrace trace_t; - - -//----------------------------------------------------------------------------- -// Client-server neutral effects interface -//----------------------------------------------------------------------------- -#define IEFFECTS_INTERFACE_VERSION "IEffects001" -abstract_class IEffects : public IPredictionSystem -{ -public: - // - // Particle effects - // - virtual void Beam( const Vector &Start, const Vector &End, int nModelIndex, - int nHaloIndex, unsigned char frameStart, unsigned char frameRate, - float flLife, unsigned char width, unsigned char endWidth, unsigned char fadeLength, - unsigned char noise, unsigned char red, unsigned char green, - unsigned char blue, unsigned char brightness, unsigned char speed) = 0; - - //----------------------------------------------------------------------------- - // Purpose: Emits smoke sprites. - // Input : origin - Where to emit the sprites. - // scale - Sprite scale * 10. - // framerate - Framerate at which to animate the smoke sprites. - //----------------------------------------------------------------------------- - virtual void Smoke( const Vector &origin, int modelIndex, float scale, float framerate ) = 0; - - virtual void Sparks( const Vector &position, int nMagnitude = 1, int nTrailLength = 1, const Vector *pvecDir = NULL ) = 0; - - virtual void Dust( const Vector &pos, const Vector &dir, float size, float speed ) = 0; - - virtual void MuzzleFlash( const Vector &vecOrigin, const QAngle &vecAngles, float flScale, int iType ) = 0; - - // like ricochet, but no sound - virtual void MetalSparks( const Vector &position, const Vector &direction ) = 0; - - virtual void EnergySplash( const Vector &position, const Vector &direction, bool bExplosive = false ) = 0; - - virtual void Ricochet( const Vector &position, const Vector &direction ) = 0; - - // FIXME: Should these methods remain in this interface? Or go in some - // other client-server neutral interface? - virtual float Time() = 0; - virtual bool IsServer() = 0; - - // Used by the playback system to suppress sounds - virtual void SuppressEffectsSounds( bool bSuppress ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Client-server neutral effects interface accessor -//----------------------------------------------------------------------------- -extern IEffects *g_pEffects; - - -#endif // IEFFECTS_H diff --git a/game/shared/IVehicle.h b/game/shared/IVehicle.h deleted file mode 100644 index 3df1608d3..000000000 --- a/game/shared/IVehicle.h +++ /dev/null @@ -1,47 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IVEHICLE_H -#define IVEHICLE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "baseplayer_shared.h" - -class CUserCmd; -class IMoveHelper; -class CMoveData; -class CBaseCombatCharacter; - -// This is used by the player to access vehicles. It's an interface so the -// vehicles are not restricted in what they can derive from. -abstract_class IVehicle -{ -public: - // Get and set the current driver. Use PassengerRole_t enum in shareddefs.h for adding passengers - virtual CBaseCombatCharacter* GetPassenger( int nRole = VEHICLE_ROLE_DRIVER ) = 0; - virtual int GetPassengerRole( CBaseCombatCharacter *pPassenger ) = 0; - - // Where is the passenger seeing from? - virtual void GetVehicleViewPosition( int nRole, Vector *pOrigin, QAngle *pAngles, float *pFOV = NULL ) = 0; - - // Does the player use his normal weapons while in this mode? - virtual bool IsPassengerUsingStandardWeapons( int nRole = VEHICLE_ROLE_DRIVER ) = 0; - - // Process movement - virtual void SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) = 0; - virtual void ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMoveData ) = 0; - virtual void FinishMove( CBasePlayer *player, CUserCmd *ucmd, CMoveData *move ) = 0; - - // Process input - virtual void ItemPostFrame( CBasePlayer *pPlayer ) = 0; -}; - - -#endif // IVEHICLE_H diff --git a/game/shared/ModelSoundsCache.cpp b/game/shared/ModelSoundsCache.cpp deleted file mode 100644 index 126616195..000000000 --- a/game/shared/ModelSoundsCache.cpp +++ /dev/null @@ -1,217 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#include "ModelSoundsCache.h" -#include "studio.h" -#include "eventlist.h" -#include "scriptevent.h" - -extern ISoundEmitterSystemBase *soundemitterbase; - -CStudioHdr *ModelSoundsCache_LoadModel( char const *filename ); -void ModelSoundsCache_PrecacheScriptSound( const char *soundname ); -void ModelSoundsCache_FinishModel( CStudioHdr *hdr ); -//----------------------------------------------------------------------------- -// Purpose: -// Input : *hdr - -// Output : static void -//----------------------------------------------------------------------------- - -void VerifySequenceIndex( CStudioHdr *pstudiohdr ); - -// HACK: This must match the #define in cl_animevent.h in the client .dll code!!! -#define CL_EVENT_SOUND 5004 -#define CL_EVENT_FOOTSTEP_LEFT 6004 -#define CL_EVENT_FOOTSTEP_RIGHT 6005 -#define CL_EVENT_MFOOTSTEP_LEFT 6006 -#define CL_EVENT_MFOOTSTEP_RIGHT 6007 - - -extern ISoundEmitterSystemBase *soundemitterbase; - -CModelSoundsCache::CModelSoundsCache() -{ -} - -CModelSoundsCache::CModelSoundsCache( const CModelSoundsCache& src ) -{ - sounds = src.sounds; -} - -char const *CModelSoundsCache::GetSoundName( int index ) -{ - return soundemitterbase->GetSoundName( sounds[ index ] ); -} - -void CModelSoundsCache::Save( CUtlBuffer& buf ) -{ - buf.PutShort( sounds.Count() ); - - for ( int i = 0; i < sounds.Count(); ++i ) - { - buf.PutString( GetSoundName( i ) ); - } -} - -void CModelSoundsCache::Restore( CUtlBuffer& buf ) -{ - MEM_ALLOC_CREDIT(); - unsigned short c; - - c = (unsigned short)buf.GetShort(); - - for ( int i = 0; i < c; ++i ) - { - char soundname[ 512 ]; - - buf.GetString( soundname, sizeof( soundname ) ); - - int idx = soundemitterbase->GetSoundIndex( soundname ); - if ( idx != -1 ) - { - Assert( idx <= 65535 ); - if ( sounds.Find( idx ) == sounds.InvalidIndex() ) - { - sounds.AddToTail( (unsigned short)idx ); - } - } - } -} - -void CModelSoundsCache::Rebuild( char const *filename ) -{ - sounds.RemoveAll(); - - CStudioHdr *hdr = ModelSoundsCache_LoadModel( filename ); - - if ( hdr ) - { - // Precache all sounds referenced in animation events - BuildAnimationEventSoundList( hdr, sounds ); - ModelSoundsCache_FinishModel( hdr ); - } -} - -void CModelSoundsCache::PrecacheSoundList() -{ - for ( int i = 0; i < sounds.Count(); ++i ) - { - ModelSoundsCache_PrecacheScriptSound( GetSoundName( i ) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Static method -// Input : sounds - -// *soundname - -//----------------------------------------------------------------------------- -void CModelSoundsCache::FindOrAddScriptSound( CUtlVector< unsigned short >& sounds, char const *soundname ) -{ - int soundindex = soundemitterbase->GetSoundIndex( soundname ); - if ( soundindex != -1 ) - { - // Only add it once per model... - if ( sounds.Find( soundindex ) == sounds.InvalidIndex() ) - { - MEM_ALLOC_CREDIT(); - sounds.AddToTail( soundindex ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Static method -// Input : *hdr - -// sounds - -//----------------------------------------------------------------------------- -void CModelSoundsCache::BuildAnimationEventSoundList( CStudioHdr *hdr, CUtlVector< unsigned short >& sounds ) -{ - Assert( hdr ); - - // force animation event resolution!!! - VerifySequenceIndex( hdr ); - - // Find all animation events which fire off sound script entries... - for ( int iSeq=0; iSeq < hdr->GetNumSeq(); iSeq++ ) - { - mstudioseqdesc_t *pSeq = &hdr->pSeqdesc( iSeq ); - - // Now read out all the sound events with their timing - for ( int iEvent=0; iEvent < (int)pSeq->numevents; iEvent++ ) - { - mstudioevent_t *pEvent = pSeq->pEvent( iEvent ); - - switch ( pEvent->event ) - { - default: - { - if ( pEvent->type & AE_TYPE_NEWEVENTSYSTEM ) - { - if ( pEvent->event == AE_SV_PLAYSOUND ) - { - FindOrAddScriptSound( sounds, pEvent->pszOptions() ); - } - } - } - break; - // Old-style client .dll animation event - case CL_EVENT_SOUND: - { - FindOrAddScriptSound( sounds, pEvent->pszOptions() ); - } - break; - case CL_EVENT_FOOTSTEP_LEFT: - case CL_EVENT_FOOTSTEP_RIGHT: - { - char soundname[256]; - char const *options = pEvent->pszOptions(); - if ( !options || !options[0] ) - { - options = "NPC_CombineS"; - } - - Q_snprintf( soundname, 256, "%s.RunFootstepLeft", options ); - FindOrAddScriptSound( sounds, soundname ); - Q_snprintf( soundname, 256, "%s.RunFootstepRight", options ); - FindOrAddScriptSound( sounds, soundname ); - Q_snprintf( soundname, 256, "%s.FootstepLeft", options ); - FindOrAddScriptSound( sounds, soundname ); - Q_snprintf( soundname, 256, "%s.FootstepRight", options ); - FindOrAddScriptSound( sounds, soundname ); - } - break; - case AE_CL_PLAYSOUND: - { - if ( !( pEvent->type & AE_TYPE_CLIENT ) ) - break; - - if ( pEvent->pszOptions()[0] ) - { - FindOrAddScriptSound( sounds, pEvent->pszOptions() ); - } - else - { - Warning( "-- Error --: empty soundname, .qc error on AE_CL_PLAYSOUND in model %s, sequence %s, animevent # %i\n", - hdr->pszName(), pSeq->pszLabel(), iEvent+1 ); - } - } - break; - case SCRIPT_EVENT_SOUND: - { - FindOrAddScriptSound( sounds, pEvent->pszOptions() ); - } - break; - - case SCRIPT_EVENT_SOUND_VOICE: - { - FindOrAddScriptSound( sounds, pEvent->pszOptions() ); - } - break; - } - } - } -} diff --git a/game/shared/ModelSoundsCache.h b/game/shared/ModelSoundsCache.h deleted file mode 100644 index 4ebb2c4fe..000000000 --- a/game/shared/ModelSoundsCache.h +++ /dev/null @@ -1,42 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef MODELSOUNDSCACHE_H -#define MODELSOUNDSCACHE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "UtlCachedFileData.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" - -#define MODELSOUNDSCACHE_VERSION 5 - -class CStudioHdr; - -#pragma pack(1) -class CModelSoundsCache : public IBaseCacheInfo -{ -public: - CUtlVector< unsigned short > sounds; - - CModelSoundsCache(); - CModelSoundsCache( const CModelSoundsCache& src ); - - void PrecacheSoundList(); - - virtual void Save( CUtlBuffer& buf ); - virtual void Restore( CUtlBuffer& buf ); - virtual void Rebuild( char const *filename ); - - static void FindOrAddScriptSound( CUtlVector< unsigned short >& sounds, char const *soundname ); - static void BuildAnimationEventSoundList( CStudioHdr *hdr, CUtlVector< unsigned short >& sounds ); -private: - char const *GetSoundName( int index ); -}; -#pragma pack() - -#endif // MODELSOUNDSCACHE_H diff --git a/game/shared/Multiplayer/multiplayer_animstate.cpp b/game/shared/Multiplayer/multiplayer_animstate.cpp deleted file mode 100644 index e4490f984..000000000 --- a/game/shared/Multiplayer/multiplayer_animstate.cpp +++ /dev/null @@ -1,1821 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======// -// -// Purpose: -// -//=============================================================================// -#include "cbase.h" -#include "tier0/vprof.h" -#include "animation.h" -#include "studio.h" -#include "apparent_velocity_helper.h" -#include "utldict.h" -#include "multiplayer_animstate.h" -#include "activitylist.h" - -#ifdef CLIENT_DLL -#include "c_baseplayer.h" -#include "engine/ivdebugoverlay.h" -#include "filesystem.h" -#include "eventlist.h" -ConVar anim_showmainactivity( "anim_showmainactivity", "0", FCVAR_CHEAT, "Show the idle, walk, run, and/or sprint activities." ); -#else -#include "player.h" -#endif - -#define MOVING_MINIMUM_SPEED 0.5f - -ConVar anim_showstate( "anim_showstate", "-1", FCVAR_CHEAT | FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Show the (client) animation state for the specified entity (-1 for none)." ); -ConVar anim_showstatelog( "anim_showstatelog", "0", FCVAR_CHEAT | FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "1 to output anim_showstate to Msg(). 2 to store in AnimState.log. 3 for both." ); -ConVar mp_showgestureslots( "mp_showgestureslots", "-1", FCVAR_CHEAT | FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Show multiplayer client/server gesture slot information for the specified player index (-1 for no one)." ); -ConVar mp_slammoveyaw( "mp_slammoveyaw", "0", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Force movement yaw along an animation path." ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -// &movementData - -//----------------------------------------------------------------------------- -CMultiPlayerAnimState::CMultiPlayerAnimState( CBasePlayer *pPlayer, MultiPlayerMovementData_t &movementData ) -#ifdef CLIENT_DLL - : m_iv_flMaxGroundSpeed( "CMultiPlayerAnimState::m_iv_flMaxGroundSpeed" ) -#endif -{ - // Pose parameters. - m_bPoseParameterInit = false; - m_PoseParameterData.Init(); - m_DebugAnimData.Init(); - - m_pPlayer = NULL; - m_angRender.Init(); - - m_bCurrentFeetYawInitialized = false; - m_flLastAnimationStateClearTime = 0.0f; - - m_flEyeYaw = 0.0f; - m_flEyePitch = 0.0f; - m_flGoalFeetYaw = 0.0f; - m_flCurrentFeetYaw = 0.0f; - m_flLastAimTurnTime = 0.0f; - - // Jumping. - m_bJumping = false; - m_flJumpStartTime = 0.0f; - m_bFirstJumpFrame = false; - - // Swimming - m_bInSwim = false; - m_bFirstSwimFrame = true; - - // Dying - m_bDying = false; - m_bFirstDyingFrame = true; - - m_eCurrentMainSequenceActivity = ACT_INVALID; - m_nSpecificMainSequence = -1; - - // Weapon data. - m_hActiveWeapon = NULL; - - // Ground speed interpolators. -#ifdef CLIENT_DLL - m_iv_flMaxGroundSpeed.Setup( &m_flMaxGroundSpeed, LATCH_ANIMATION_VAR | INTERPOLATE_LINEAR_ONLY ); - m_flLastGroundSpeedUpdateTime = 0.0f; -#endif - - m_flMaxGroundSpeed = 0.0f; - - m_bForceAimYaw = false; - - Init( pPlayer, movementData ); - - InitGestureSlots(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -//----------------------------------------------------------------------------- -CMultiPlayerAnimState::~CMultiPlayerAnimState() -{ - ShutdownGestureSlots(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -// &movementData - -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::Init( CBasePlayer *pPlayer, MultiPlayerMovementData_t &movementData ) -{ - // Get the player this animation data works on. - m_pPlayer = pPlayer; - - // Copy the movement data. - memcpy( &m_MovementData, &movementData, sizeof( MultiPlayerMovementData_t ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::ClearAnimationState() -{ - // Reset state. - m_bJumping = false; - m_bDying = false; - m_bCurrentFeetYawInitialized = false; - m_flLastAnimationStateClearTime = gpGlobals->curtime; - - ResetGestureSlots(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : event - -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::DoAnimationEvent( PlayerAnimEvent_t event, int nData ) -{ - switch( event ) - { - case PLAYERANIMEVENT_ATTACK_PRIMARY: - { - // Weapon primary fire. - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_STAND_PRIMARYFIRE ); - break; - } - case PLAYERANIMEVENT_ATTACK_SECONDARY: - { - // Weapon secondary fire. - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_STAND_SECONDARYFIRE ); - break; - } - case PLAYERANIMEVENT_ATTACK_GRENADE: - { - // Grenade throw. - RestartGesture( GESTURE_SLOT_GRENADE, ACT_MP_ATTACK_STAND_GRENADE ); - break; - } - case PLAYERANIMEVENT_RELOAD: - { - // Weapon reload. - if ( GetBasePlayer()->GetFlags() & FL_DUCKING ) - { - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_CROUCH ); - } - else if ( m_bInSwim ) - { - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_SWIM ); - } - else - { - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_STAND ); - } - break; - } - case PLAYERANIMEVENT_RELOAD_LOOP: - { - // Weapon reload. - if ( GetBasePlayer()->GetFlags() & FL_DUCKING ) - { - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_CROUCH_LOOP ); - } - else if ( m_bInSwim ) - { - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_SWIM_LOOP ); - } - else - { - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_STAND_LOOP ); - } - break; - } - case PLAYERANIMEVENT_RELOAD_END: - { - // Weapon reload. - if ( GetBasePlayer()->GetFlags() & FL_DUCKING ) - { - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_CROUCH_END ); - } - else if ( m_bInSwim ) - { - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_SWIM_END ); - } - else - { - RestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_STAND_END ); - } - break; - } - case PLAYERANIMEVENT_JUMP: - { - // Jump. - m_bJumping = true; - m_bFirstJumpFrame = true; - m_flJumpStartTime = gpGlobals->curtime; - - RestartMainSequence(); - - break; - } - case PLAYERANIMEVENT_DIE: - { - // Should be here - not supporting this yet! - Assert( 0 ); - - // Start playing the death animation - m_bDying = true; - - RestartMainSequence(); - break; - } - case PLAYERANIMEVENT_SPAWN: - { - // Player has respawned. Clear flags. - ClearAnimationState(); - break; - } - - case PLAYERANIMEVENT_SNAP_YAW: - m_PoseParameterData.m_flLastAimTurnTime = 0.0f; - break; - - case PLAYERANIMEVENT_CUSTOM: - { - Activity iIdealActivity = TranslateActivity( (Activity)nData ); - m_nSpecificMainSequence = GetBasePlayer()->SelectWeightedSequence( iIdealActivity ); - RestartMainSequence(); - } - break; - - case PLAYERANIMEVENT_CUSTOM_GESTURE: - // Weapon primary fire. - RestartGesture( GESTURE_SLOT_CUSTOM, (Activity)nData ); - break; - - case PLAYERANIMEVENT_CUSTOM_SEQUENCE: - m_nSpecificMainSequence = nData; - RestartMainSequence(); - break; - - case PLAYERANIMEVENT_CUSTOM_GESTURE_SEQUENCE: - // Weapon primary fire. -// RestartGestureSequence( nData, false ); - break; - - case PLAYERANIMEVENT_FLINCH_CHEST: - PlayFlinchGesture( ACT_MP_GESTURE_FLINCH_CHEST ); - break; - case PLAYERANIMEVENT_FLINCH_HEAD: - PlayFlinchGesture( ACT_MP_GESTURE_FLINCH_HEAD ); - break; - case PLAYERANIMEVENT_FLINCH_LEFTARM: - PlayFlinchGesture( ACT_MP_GESTURE_FLINCH_LEFTARM ); - break; - case PLAYERANIMEVENT_FLINCH_RIGHTARM: - PlayFlinchGesture( ACT_MP_GESTURE_FLINCH_RIGHTARM ); - break; - case PLAYERANIMEVENT_FLINCH_LEFTLEG: - PlayFlinchGesture( ACT_MP_GESTURE_FLINCH_LEFTLEG ); - break; - case PLAYERANIMEVENT_FLINCH_RIGHTLEG: - PlayFlinchGesture( ACT_MP_GESTURE_FLINCH_RIGHTLEG ); - break; - - default: - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::PlayFlinchGesture( Activity iActivity ) -{ - if ( !IsGestureSlotActive( GESTURE_SLOT_FLINCH ) ) - { - // See if we have the custom flinch. If not, revert to chest - if ( iActivity != ACT_MP_GESTURE_FLINCH_CHEST && GetBasePlayer()->SelectWeightedSequence( iActivity ) == -1 ) - { - RestartGesture( GESTURE_SLOT_FLINCH, ACT_MP_GESTURE_FLINCH_CHEST ); - } - else - { - RestartGesture( GESTURE_SLOT_FLINCH, iActivity ); - } - } -} - -//============================================================================= -// -// Multiplayer gesture code. -// - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CMultiPlayerAnimState::InitGestureSlots( void ) -{ - // Get the base player. - CBasePlayer *pPlayer = GetBasePlayer(); - if( pPlayer ) - { - // Set the number of animation overlays we will use. - pPlayer->SetNumAnimOverlays( GESTURE_SLOT_COUNT ); - } - - // Setup the number of gesture slots. - m_aGestureSlots.AddMultipleToTail( GESTURE_SLOT_COUNT ); - for ( int iGesture = 0; iGesture < GESTURE_SLOT_COUNT; ++iGesture ) - { - m_aGestureSlots[iGesture].m_pAnimLayer = pPlayer->GetAnimOverlay( iGesture ); - if ( !m_aGestureSlots[iGesture].m_pAnimLayer ) - return false; - - ResetGestureSlot( iGesture ); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::ShutdownGestureSlots( void ) -{ - // Clean up the gesture slots. - m_aGestureSlots.Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::ResetGestureSlots( void ) -{ - // Clear out all the gesture slots. - for ( int iGesture = 0; iGesture < GESTURE_SLOT_COUNT; ++iGesture ) - { - ResetGestureSlot( iGesture ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::ResetGestureSlot( int iGestureSlot ) -{ - // Sanity Check - Assert( iGestureSlot >= 0 && iGestureSlot < GESTURE_SLOT_COUNT ); - - GestureSlot_t *pGestureSlot = &m_aGestureSlots[iGestureSlot]; - if ( pGestureSlot ) - { -#ifdef CLIENT_DLL - // briefly set to 1.0 so we catch the events, before we reset the slot - pGestureSlot->m_pAnimLayer->m_flCycle = 1.0; - - RunGestureSlotAnimEventsToCompletion( pGestureSlot ); -#endif - - pGestureSlot->m_iGestureSlot = GESTURE_SLOT_INVALID; - pGestureSlot->m_iActivity = ACT_INVALID; - pGestureSlot->m_bAutoKill = false; - pGestureSlot->m_bActive = false; - if ( pGestureSlot->m_pAnimLayer ) - { - pGestureSlot->m_pAnimLayer->SetOrder( CBaseAnimatingOverlay::MAX_OVERLAYS ); -#ifdef CLIENT_DLL - pGestureSlot->m_pAnimLayer->Reset(); -#endif - } - } -} - -#ifdef CLIENT_DLL - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::RunGestureSlotAnimEventsToCompletion( GestureSlot_t *pGesture ) -{ - CBasePlayer *pPlayer = GetBasePlayer(); - if( !pPlayer ) - return; - - // Get the studio header for the player. - CStudioHdr *pStudioHdr = pPlayer->GetModelPtr(); - if ( !pStudioHdr ) - return; - - // Do all the anim events between previous cycle and 1.0, inclusive - mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( pGesture->m_pAnimLayer->m_nSequence ); - if ( seqdesc.numevents > 0 ) - { - mstudioevent_t *pevent = seqdesc.pEvent( 0 ); - - for (int i = 0; i < (int)seqdesc.numevents; i++) - { - if ( pevent[i].type & AE_TYPE_NEWEVENTSYSTEM ) - { - if ( !( pevent[i].type & AE_TYPE_CLIENT ) ) - continue; - } - else if ( pevent[i].event < 5000 ) //Adrian - Support the old event system - continue; - - if ( pevent[i].cycle > pGesture->m_pAnimLayer->m_flPrevCycle && - pevent[i].cycle <= pGesture->m_pAnimLayer->m_flCycle ) - { - pPlayer->FireEvent( pPlayer->GetAbsOrigin(), pPlayer->GetAbsAngles(), pevent[ i ].event, pevent[ i ].pszOptions() ); - } - } - } -} - -#endif - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CMultiPlayerAnimState::IsGestureSlotActive( int iGestureSlot ) -{ - // Sanity Check - Assert( iGestureSlot >= 0 && iGestureSlot < GESTURE_SLOT_COUNT ); - return m_aGestureSlots[iGestureSlot].m_bActive; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CMultiPlayerAnimState::IsGestureSlotPlaying( int iGestureSlot, Activity iGestureActivity ) -{ - // Sanity Check - Assert( iGestureSlot >= 0 && iGestureSlot < GESTURE_SLOT_COUNT ); - - // Check to see if the slot is active. - if ( !IsGestureSlotActive( iGestureSlot ) ) - return false; - - return ( m_aGestureSlots[iGestureSlot].m_iActivity == iGestureActivity ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::RestartGesture( int iGestureSlot, Activity iGestureActivity, bool bAutoKill ) -{ - // Sanity Check - Assert( iGestureSlot >= 0 && iGestureSlot < GESTURE_SLOT_COUNT ); - - if ( !IsGestureSlotPlaying( iGestureSlot, iGestureActivity ) ) - { -#ifdef CLIENT_DLL - if ( IsGestureSlotActive( iGestureSlot ) ) - { - GestureSlot_t *pGesture = &m_aGestureSlots[iGestureSlot]; - if ( pGesture && pGesture->m_pAnimLayer ) - { - pGesture->m_pAnimLayer->m_flCycle = 1.0; // run until the end - RunGestureSlotAnimEventsToCompletion( &m_aGestureSlots[iGestureSlot] ); - } - } -#endif - - Activity iIdealGestureActivity = TranslateActivity( iGestureActivity ); - AddToGestureSlot( iGestureSlot, iIdealGestureActivity, bAutoKill ); - return; - } - - // Reset the cycle = restart the gesture. - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flCycle = 0.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flPrevCycle = 0.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::AddToGestureSlot( int iGestureSlot, Activity iGestureActivity, bool bAutoKill ) -{ - // Sanity Check - Assert( iGestureSlot >= 0 && iGestureSlot < GESTURE_SLOT_COUNT ); - - CBasePlayer *pPlayer = GetBasePlayer(); - if ( !pPlayer ) - return; - - // Make sure we have a valid animation layer to fill out. - if ( !m_aGestureSlots[iGestureSlot].m_pAnimLayer ) - return; - - // Get the sequence. - int iGestureSequence = pPlayer->SelectWeightedSequence( iGestureActivity ); - if ( iGestureSequence <= 0 ) - return; - -#ifdef CLIENT_DLL - - // Setup the gesture. - m_aGestureSlots[iGestureSlot].m_iGestureSlot = iGestureSlot; - m_aGestureSlots[iGestureSlot].m_iActivity = iGestureActivity; - m_aGestureSlots[iGestureSlot].m_bAutoKill = bAutoKill; - m_aGestureSlots[iGestureSlot].m_bActive = true; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nSequence = iGestureSequence; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nOrder = iGestureSlot; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flWeight = 1.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flPlaybackRate = 1.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flCycle = 0.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flPrevCycle = 0.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flLayerAnimtime = 0.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flLayerFadeOuttime = 0.0f; - - pPlayer->m_flOverlayPrevEventCycle[iGestureSlot] = -1.0; - -#else - - // Setup the gesture. - m_aGestureSlots[iGestureSlot].m_iGestureSlot = iGestureSlot; - m_aGestureSlots[iGestureSlot].m_iActivity = iGestureActivity; - m_aGestureSlots[iGestureSlot].m_bAutoKill = bAutoKill; - m_aGestureSlots[iGestureSlot].m_bActive = true; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nActivity = iGestureActivity; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nOrder = iGestureSlot; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nPriority = 0; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flCycle = 0.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flPrevCycle = 0.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flPlaybackRate = 1.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nActivity = iGestureActivity; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nSequence = iGestureSequence; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flWeight = 1.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flBlendIn = 0.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flBlendOut = 0.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_bSequenceFinished = false; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flLastEventCheck = 0.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flLastEventCheck = gpGlobals->curtime; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_bLooping = false;//( ( GetSequenceFlags( GetModelPtr(), iGestureSequence ) & STUDIO_LOOPING ) != 0); - if ( bAutoKill ) - { - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_fFlags |= ANIM_LAYER_AUTOKILL; - } - else - { - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_fFlags &= ~ANIM_LAYER_AUTOKILL; - } - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_fFlags |= ANIM_LAYER_ACTIVE; - -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::AddVCDSequenceToGestureSlot( int iGestureSlot, int iGestureSequence, bool bAutoKill ) -{ - // Sanity Check - Assert( iGestureSlot >= 0 && iGestureSlot < GESTURE_SLOT_COUNT ); - - CBasePlayer *pPlayer = GetBasePlayer(); - if ( !pPlayer ) - return; - - // Make sure we have a valid animation layer to fill out. - if ( !m_aGestureSlots[iGestureSlot].m_pAnimLayer ) - return; - - // Set the activity. - Activity iGestureActivity = ACT_MP_VCD; - -#ifdef CLIENT_DLL - - // Setup the gesture. - m_aGestureSlots[iGestureSlot].m_iGestureSlot = iGestureSlot; - m_aGestureSlots[iGestureSlot].m_iActivity = iGestureActivity; - m_aGestureSlots[iGestureSlot].m_bAutoKill = bAutoKill; - m_aGestureSlots[iGestureSlot].m_bActive = true; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nSequence = iGestureSequence; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nOrder = iGestureSlot; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flWeight = 1.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flPlaybackRate = 1.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flCycle = 0.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flPrevCycle = 0.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flLayerAnimtime = 0.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flLayerFadeOuttime = 0.0f; - - pPlayer->m_flOverlayPrevEventCycle[iGestureSlot] = -1.0; - -#else - - // Setup the gesture. - m_aGestureSlots[iGestureSlot].m_iGestureSlot = iGestureSlot; - m_aGestureSlots[iGestureSlot].m_iActivity = iGestureActivity; - m_aGestureSlots[iGestureSlot].m_bAutoKill = bAutoKill; - m_aGestureSlots[iGestureSlot].m_bActive = true; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nActivity = iGestureActivity; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nOrder = iGestureSlot; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nPriority = 0; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flCycle = 0.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flPrevCycle = 0.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flPlaybackRate = 1.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nActivity = iGestureActivity; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_nSequence = iGestureSequence; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flWeight = 1.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flBlendIn = 0.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flBlendOut = 0.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_bSequenceFinished = false; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flLastEventCheck = 0.0f; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_flLastEventCheck = gpGlobals->curtime; - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_bLooping = false;//( ( GetSequenceFlags( GetModelPtr(), iGestureSequence ) & STUDIO_LOOPING ) != 0); - if ( bAutoKill ) - { - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_fFlags |= ANIM_LAYER_AUTOKILL; - } - else - { - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_fFlags &= ~ANIM_LAYER_AUTOKILL; - } - m_aGestureSlots[iGestureSlot].m_pAnimLayer->m_fFlags |= ANIM_LAYER_ACTIVE; - -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::ShowDebugInfo( void ) -{ - if ( anim_showstate.GetInt() == GetBasePlayer()->entindex() ) - { - DebugShowAnimStateForPlayer( GetBasePlayer()->IsServer() ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Cancel the current gesture and restart the main sequence. -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::RestartMainSequence( void ) -{ - CBaseAnimatingOverlay *pPlayer = GetBasePlayer(); - if ( pPlayer ) - { - pPlayer->m_flAnimTime = gpGlobals->curtime; - pPlayer->SetCycle( 0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *idealActivity - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CMultiPlayerAnimState::HandleJumping( Activity &idealActivity ) -{ - if ( m_bJumping ) - { - if ( m_bFirstJumpFrame ) - { - m_bFirstJumpFrame = false; - RestartMainSequence(); // Reset the animation. - } - - // Check to see if we hit water and stop jumping animation. - if ( GetBasePlayer()->GetWaterLevel() >= WL_Waist ) - { - m_bJumping = false; - RestartMainSequence(); - } - // Don't check if he's on the ground for a sec.. sometimes the client still has the - // on-ground flag set right when the message comes in. - else if ( gpGlobals->curtime - m_flJumpStartTime > 0.2f ) - { - if ( GetBasePlayer()->GetFlags() & FL_ONGROUND ) - { - m_bJumping = false; - RestartMainSequence(); - } - } - } - if ( m_bJumping ) - { - idealActivity = ACT_MP_JUMP; - return true; - } - else - { - return false; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *idealActivity - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CMultiPlayerAnimState::HandleDucking( Activity &idealActivity ) -{ - if ( GetBasePlayer()->GetFlags() & FL_DUCKING ) - { - if ( GetOuterXYSpeed() > MOVING_MINIMUM_SPEED ) - { - idealActivity = ACT_MP_CROUCHWALK; - } - else - { - idealActivity = ACT_MP_CROUCH_IDLE; - } - - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &idealActivity - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CMultiPlayerAnimState::HandleSwimming( Activity &idealActivity ) -{ - if ( GetBasePlayer()->GetWaterLevel() >= WL_Waist ) - { - if ( m_bFirstSwimFrame ) - { - // Reset the animation. - RestartMainSequence(); - m_bFirstSwimFrame = false; - } - - idealActivity = ACT_MP_SWIM; - m_bInSwim = true; - return true; - } - else - { - m_bInSwim = false; - - if ( !m_bFirstSwimFrame ) - { - m_bFirstSwimFrame = true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *idealActivity - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CMultiPlayerAnimState::HandleDying( Activity &idealActivity ) -{ - if ( m_bDying ) - { - if ( m_bFirstDyingFrame ) - { - // Reset the animation. - RestartMainSequence(); - m_bFirstDyingFrame = false; - } - - idealActivity = ACT_DIESIMPLE; - return true; - } - else - { - if ( !m_bFirstDyingFrame ) - { - m_bFirstDyingFrame = true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *idealActivity - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CMultiPlayerAnimState::HandleMoving( Activity &idealActivity ) -{ - // In TF we run all the time now. - float flSpeed = GetOuterXYSpeed(); - - if ( flSpeed > MOVING_MINIMUM_SPEED ) - { - // Always assume a run. - idealActivity = ACT_MP_RUN; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -// Output : Activity -//----------------------------------------------------------------------------- -Activity CMultiPlayerAnimState::CalcMainActivity() -{ - Activity idealActivity = ACT_MP_STAND_IDLE; - - if ( HandleJumping( idealActivity ) || - HandleDucking( idealActivity ) || - HandleSwimming( idealActivity ) || - HandleDying( idealActivity ) ) - { - // intentionally blank - } - else - { - HandleMoving( idealActivity ); - } - - ShowDebugInfo(); - - // Client specific. -#ifdef CLIENT_DLL - - if ( anim_showmainactivity.GetBool() ) - { - DebugShowActivity( idealActivity ); - } - -#endif - - return idealActivity; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : actDesired - -// Output : Activity -//----------------------------------------------------------------------------- -Activity CMultiPlayerAnimState::TranslateActivity( Activity actDesired ) -{ - // Translate activities for swimming. - if ( m_bInSwim ) - { - switch ( actDesired ) - { - case ACT_MP_ATTACK_STAND_PRIMARYFIRE: { actDesired = ACT_MP_ATTACK_SWIM_PRIMARYFIRE; break; } - case ACT_MP_ATTACK_STAND_SECONDARYFIRE: { actDesired = ACT_MP_ATTACK_SWIM_SECONDARYFIRE; break; } - case ACT_MP_ATTACK_STAND_GRENADE: { actDesired = ACT_MP_ATTACK_SWIM_GRENADE; break; } - case ACT_MP_RELOAD_STAND: { actDesired = ACT_MP_RELOAD_SWIM; break; } - default: break; - } - } - - return actDesired; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -// Output : float -//----------------------------------------------------------------------------- -float CMultiPlayerAnimState::GetCurrentMaxGroundSpeed() -{ - CStudioHdr *pStudioHdr = GetBasePlayer()->GetModelPtr(); - - if ( pStudioHdr == NULL ) - return 1.0f; - - float prevX = GetBasePlayer()->GetPoseParameter( m_PoseParameterData.m_iMoveX ); - float prevY = GetBasePlayer()->GetPoseParameter( m_PoseParameterData.m_iMoveY ); - - float d = sqrt( prevX * prevX + prevY * prevY ); - float newX, newY; - if ( d == 0.0 ) - { - newX = 1.0; - newY = 0.0; - } - else - { - newX = prevX / d; - newY = prevY / d; - } - - GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveX, newX ); - GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveY, newY ); - - float speed = GetBasePlayer()->GetSequenceGroundSpeed( GetBasePlayer()->GetSequence() ); - - GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveX, prevX ); - GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveY, prevY ); - - return speed; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *bIsMoving - -// Output : float -//----------------------------------------------------------------------------- -float CMultiPlayerAnimState::CalcMovementPlaybackRate( bool *bIsMoving ) -{ - // Get the player's current velocity and speed. - Vector vecVelocity; - GetOuterAbsVelocity( vecVelocity ); - float flSpeed = vecVelocity.Length2D(); - - // Determine if the player is considered moving or not. - bool bMoving = ( flSpeed > MOVING_MINIMUM_SPEED ); - - // Initialize the return data. - *bIsMoving = false; - float flReturn = 1.0f; - - // If we are moving. - if ( bMoving ) - { - // float flGroundSpeed = GetInterpolatedGroundSpeed(); - float flGroundSpeed = GetCurrentMaxGroundSpeed(); - if ( flGroundSpeed < 0.001f ) - { - flReturn = 0.01; - } - else - { - // Note this gets set back to 1.0 if sequence changes due to ResetSequenceInfo below - flReturn = flSpeed / flGroundSpeed; - flReturn = clamp( flReturn, 0.01f, 10.0f ); - } - - *bIsMoving = true; - } - - return flReturn; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CMultiPlayerAnimState::GetInterpolatedGroundSpeed( void ) -{ - return m_flMaxGroundSpeed; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pStudioHdr - -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::ComputeSequences( CStudioHdr *pStudioHdr ) -{ - VPROF( "CBasePlayerAnimState::ComputeSequences" ); - - // Lower body (walk/run/idle). - ComputeMainSequence(); - - // The groundspeed interpolator uses the main sequence info. - UpdateInterpolators(); - ComputeGestureSequence( pStudioHdr ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::ComputeMainSequence() -{ - VPROF( "CBasePlayerAnimState::ComputeMainSequence" ); - - CBaseAnimatingOverlay *pPlayer = GetBasePlayer(); - - // Have our class or the mod-specific class determine what the current activity is. - Activity idealActivity = CalcMainActivity(); - -#ifdef CLIENT_DLL - Activity oldActivity = m_eCurrentMainSequenceActivity; -#endif - - // Store our current activity so the aim and fire layers know what to do. - m_eCurrentMainSequenceActivity = idealActivity; - - // Hook to force playback of a specific requested full-body sequence - if ( m_nSpecificMainSequence >= 0 ) - { - if ( pPlayer->GetSequence() != m_nSpecificMainSequence ) - { - pPlayer->ResetSequence( m_nSpecificMainSequence ); - ResetGroundSpeed(); - return; - } - - if ( !pPlayer->IsSequenceFinished() ) - return; - - m_nSpecificMainSequence = -1; - RestartMainSequence(); - ResetGroundSpeed(); - } - - // Export to our outer class.. - int animDesired = SelectWeightedSequence( TranslateActivity( idealActivity ) ); - if ( pPlayer->GetSequenceActivity( pPlayer->GetSequence() ) == pPlayer->GetSequenceActivity( animDesired ) ) - return; - - if ( animDesired < 0 ) - { - animDesired = 0; - } - - pPlayer->ResetSequence( animDesired ); - -#ifdef CLIENT_DLL - // If we went from idle to walk, reset the interpolation history. - // Kind of hacky putting this here.. it might belong outside the base class. - if ( (oldActivity == ACT_MP_CROUCH_IDLE || oldActivity == ACT_MP_STAND_IDLE || oldActivity == ACT_MP_DEPLOYED_IDLE || oldActivity == ACT_MP_CROUCH_DEPLOYED_IDLE ) && - (idealActivity == ACT_MP_WALK || idealActivity == ACT_MP_CROUCHWALK ) ) - { - ResetGroundSpeed(); - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::ResetGroundSpeed( void ) -{ -#ifdef CLIENT_DLL - m_flMaxGroundSpeed = GetCurrentMaxGroundSpeed(); - m_iv_flMaxGroundSpeed.Reset(); - m_iv_flMaxGroundSpeed.NoteChanged( gpGlobals->curtime, 0, false ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::UpdateInterpolators() -{ - VPROF( "CBasePlayerAnimState::UpdateInterpolators" ); - - // First, figure out their current max speed based on their current activity. - float flCurMaxSpeed = GetCurrentMaxGroundSpeed(); - -#ifdef CLIENT_DLL - float flGroundSpeedInterval = 0.1; - - // Only update this 10x/sec so it has an interval to interpolate over. - if ( gpGlobals->curtime - m_flLastGroundSpeedUpdateTime >= flGroundSpeedInterval ) - { - m_flLastGroundSpeedUpdateTime = gpGlobals->curtime; - - m_flMaxGroundSpeed = flCurMaxSpeed; - m_iv_flMaxGroundSpeed.NoteChanged( gpGlobals->curtime, flGroundSpeedInterval, false ); - } - - m_iv_flMaxGroundSpeed.Interpolate( gpGlobals->curtime, flGroundSpeedInterval ); -#else - m_flMaxGroundSpeed = flCurMaxSpeed; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::ComputeFireSequence( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pStudioHdr - -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::ComputeGestureSequence( CStudioHdr *pStudioHdr ) -{ - // Update all active gesture layers. - for ( int iGesture = 0; iGesture < GESTURE_SLOT_COUNT; ++iGesture ) - { - if ( !m_aGestureSlots[iGesture].m_bActive ) - continue; - - UpdateGestureLayer( pStudioHdr, &m_aGestureSlots[iGesture] ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::UpdateGestureLayer( CStudioHdr *pStudioHdr, GestureSlot_t *pGesture ) -{ - // Sanity check. - if ( !pStudioHdr || !pGesture ) - return; - - CBasePlayer *pPlayer = GetBasePlayer(); - if( !pPlayer ) - return; - -#ifdef CLIENT_DLL - - // Get the current cycle. - float flCycle = pGesture->m_pAnimLayer->m_flCycle; - flCycle += pPlayer->GetSequenceCycleRate( pStudioHdr, pGesture->m_pAnimLayer->m_nSequence ) * gpGlobals->frametime; - - pGesture->m_pAnimLayer->m_flPrevCycle = pGesture->m_pAnimLayer->m_flCycle; - pGesture->m_pAnimLayer->m_flCycle = flCycle; - - if( flCycle > 1.0f ) - { - RunGestureSlotAnimEventsToCompletion( pGesture ); - - if ( pGesture->m_bAutoKill ) - { - ResetGestureSlot( pGesture->m_iGestureSlot ); - return; - } - else - { - pGesture->m_pAnimLayer->m_flCycle = 1.0f; - } - } - -#else - - if ( pGesture->m_iActivity != ACT_INVALID && pGesture->m_pAnimLayer->m_nActivity == ACT_INVALID ) - { - ResetGestureSlot( pGesture->m_iGestureSlot ); - } - -#endif -} - -extern ConVar mp_facefronttime; -extern ConVar mp_feetyawrate; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : eyeYaw - -// eyePitch - -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::Update( float eyeYaw, float eyePitch ) -{ - // Profile the animation update. - VPROF( "CMultiPlayerAnimState::Update" ); - - // Get the studio header for the player. - CStudioHdr *pStudioHdr = GetBasePlayer()->GetModelPtr(); - if ( !pStudioHdr ) - return; - - // Check to see if we should be updating the animation state - dead, ragdolled? - if ( !ShouldUpdateAnimState() ) - { - ClearAnimationState(); - return; - } - - // Store the eye angles. - m_flEyeYaw = AngleNormalize( eyeYaw ); - m_flEyePitch = AngleNormalize( eyePitch ); - - // Compute the player sequences. - ComputeSequences( pStudioHdr ); - - if ( SetupPoseParameters( pStudioHdr ) ) - { - // Pose parameter - what direction are the player's legs running in. - ComputePoseParam_MoveYaw( pStudioHdr ); - - // Pose parameter - Torso aiming (up/down). - ComputePoseParam_AimPitch( pStudioHdr ); - - // Pose parameter - Torso aiming (rotation). - ComputePoseParam_AimYaw( pStudioHdr ); - } - -#ifdef CLIENT_DLL - if ( C_BasePlayer::ShouldDrawLocalPlayer() ) - { - GetBasePlayer()->SetPlaybackRate( 1.0f ); - } -#endif - - if( mp_showgestureslots.GetInt() == GetBasePlayer()->entindex() ) - { - DebugGestureInfo(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CMultiPlayerAnimState::ShouldUpdateAnimState() -{ - // Don't update anim state if we're not visible - if ( GetBasePlayer()->IsEffectActive( EF_NODRAW ) ) - return false; - - // By default, don't update their animation state when they're dead because they're - // either a ragdoll or they're not drawn. -#ifdef CLIENT_DLL - if ( GetBasePlayer()->IsDormant() ) - return false; -#endif - - return (GetBasePlayer()->IsAlive() || m_bDying); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CMultiPlayerAnimState::SetupPoseParameters( CStudioHdr *pStudioHdr ) -{ - // Check to see if this has already been done. - if ( m_bPoseParameterInit ) - return true; - - // Save off the pose parameter indices. - if ( !pStudioHdr ) - return false; - - // Look for the movement blenders. - m_PoseParameterData.m_iMoveX = GetBasePlayer()->LookupPoseParameter( pStudioHdr, "move_x" ); - m_PoseParameterData.m_iMoveY = GetBasePlayer()->LookupPoseParameter( pStudioHdr, "move_y" ); - if ( ( m_PoseParameterData.m_iMoveX < 0 ) || ( m_PoseParameterData.m_iMoveY < 0 ) ) - return false; - - // Look for the aim pitch blender. - m_PoseParameterData.m_iAimPitch = GetBasePlayer()->LookupPoseParameter( pStudioHdr, "body_pitch" ); - if ( m_PoseParameterData.m_iAimPitch < 0 ) - return false; - - // Look for aim yaw blender. - m_PoseParameterData.m_iAimYaw = GetBasePlayer()->LookupPoseParameter( pStudioHdr, "body_yaw" ); - if ( m_PoseParameterData.m_iAimYaw < 0 ) - return false; - - m_bPoseParameterInit = true; - - return true; -} - -float SnapYawTo( float flValue ) -{ - float flSign = 1.0f; - if ( flValue < 0.0f ) - { - flSign = -1.0f; - flValue = -flValue; - } - - if ( flValue < 23.0f ) - { - flValue = 0.0f; - } - else if ( flValue < 67.0f ) - { - flValue = 45.0f; - } - else if ( flValue < 113.0f ) - { - flValue = 90.0f; - } - else if ( flValue < 157 ) - { - flValue = 135.0f; - } - else - { - flValue = 180.0f; - } - - return ( flValue * flSign ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pStudioHdr - -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::ComputePoseParam_MoveYaw( CStudioHdr *pStudioHdr ) -{ - // Get the estimated movement yaw. - EstimateYaw(); - - // Get the view yaw. - float flAngle = AngleNormalize( m_flEyeYaw ); - - // Calc side to side turning - the view vs. movement yaw. - float flYaw = flAngle - m_PoseParameterData.m_flEstimateYaw; - flYaw = AngleNormalize( -flYaw ); - - // Get the current speed the character is running. - bool bIsMoving; - float flPlaybackRate = CalcMovementPlaybackRate( &bIsMoving ); - - // Setup the 9-way blend parameters based on our speed and direction. - Vector2D vecCurrentMoveYaw( 0.0f, 0.0f ); - if ( bIsMoving ) - { - if ( mp_slammoveyaw.GetBool() ) - { - flYaw = SnapYawTo( flYaw ); - } - vecCurrentMoveYaw.x = cos( DEG2RAD( flYaw ) ) * flPlaybackRate; - vecCurrentMoveYaw.y = -sin( DEG2RAD( flYaw ) ) * flPlaybackRate; - } - - // Set the 9-way blend movement pose parameters. - GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveX, vecCurrentMoveYaw.x ); - GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iMoveY, vecCurrentMoveYaw.y ); - - m_DebugAnimData.m_vecMoveYaw = vecCurrentMoveYaw; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::EstimateYaw( void ) -{ - // Get the frame time. - float flDeltaTime = gpGlobals->frametime; - if ( flDeltaTime == 0.0f ) - return; - - // Get the player's velocity and angles. - Vector vecEstVelocity; - GetOuterAbsVelocity( vecEstVelocity ); - QAngle angles = GetBasePlayer()->GetLocalAngles(); - - // If we are not moving, sync up the feet and eyes slowly. - if ( vecEstVelocity.x == 0.0f && vecEstVelocity.y == 0.0f ) - { - float flYawDelta = angles[YAW] - m_PoseParameterData.m_flEstimateYaw; - flYawDelta = AngleNormalize( flYawDelta ); - - if ( flDeltaTime < 0.25f ) - { - flYawDelta *= ( flDeltaTime * 4.0f ); - } - else - { - flYawDelta *= flDeltaTime; - } - - m_PoseParameterData.m_flEstimateYaw += flYawDelta; - AngleNormalize( m_PoseParameterData.m_flEstimateYaw ); - } - else - { - m_PoseParameterData.m_flEstimateYaw = ( atan2( vecEstVelocity.y, vecEstVelocity.x ) * 180.0f / M_PI ); - m_PoseParameterData.m_flEstimateYaw = clamp( m_PoseParameterData.m_flEstimateYaw, -180.0f, 180.0f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::ComputePoseParam_AimPitch( CStudioHdr *pStudioHdr ) -{ - // Get the view pitch. - float flAimPitch = m_flEyePitch; - - // Set the aim pitch pose parameter and save. - GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iAimPitch, -flAimPitch ); - m_DebugAnimData.m_flAimPitch = flAimPitch; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::ComputePoseParam_AimYaw( CStudioHdr *pStudioHdr ) -{ - // Get the movement velocity. - Vector vecVelocity; - GetOuterAbsVelocity( vecVelocity ); - - // Check to see if we are moving. - bool bMoving = ( vecVelocity.Length() > 1.0f ) ? true : false; - - // If we are moving or are prone and undeployed. - if ( bMoving || m_bForceAimYaw ) - { - // The feet match the eye direction when moving - the move yaw takes care of the rest. - m_flGoalFeetYaw = m_flEyeYaw; - } - // Else if we are not moving. - else - { - // Initialize the feet. - if ( m_PoseParameterData.m_flLastAimTurnTime <= 0.0f ) - { - m_flGoalFeetYaw = m_flEyeYaw; - m_flCurrentFeetYaw = m_flEyeYaw; - m_PoseParameterData.m_flLastAimTurnTime = gpGlobals->curtime; - } - // Make sure the feet yaw isn't too far out of sync with the eye yaw. - // TODO: Do something better here! - else - { - float flYawDelta = AngleNormalize( m_flGoalFeetYaw - m_flEyeYaw ); - - if ( fabs( flYawDelta ) > 45.0f/*m_AnimConfig.m_flMaxBodyYawDegrees*/ ) - { - float flSide = ( flYawDelta > 0.0f ) ? -1.0f : 1.0f; - m_flGoalFeetYaw += ( 45.0f/*m_AnimConfig.m_flMaxBodyYawDegrees*/ * flSide ); - } - } - } - - // Fix up the feet yaw. - m_flGoalFeetYaw = AngleNormalize( m_flGoalFeetYaw ); - if ( m_flGoalFeetYaw != m_flCurrentFeetYaw ) - { - if ( m_bForceAimYaw ) - { - m_flCurrentFeetYaw = m_flGoalFeetYaw; - } - else - { - ConvergeYawAngles( m_flGoalFeetYaw, /*DOD_BODYYAW_RATE*/720.0f, gpGlobals->frametime, m_flCurrentFeetYaw ); - m_flLastAimTurnTime = gpGlobals->curtime; - } - } - - // Rotate the body into position. - m_angRender[YAW] = m_flCurrentFeetYaw; - - // Find the aim(torso) yaw base on the eye and feet yaws. - float flAimYaw = m_flEyeYaw - m_flCurrentFeetYaw; - flAimYaw = AngleNormalize( flAimYaw ); - - // Set the aim yaw and save. - GetBasePlayer()->SetPoseParameter( pStudioHdr, m_PoseParameterData.m_iAimYaw, -flAimYaw ); - m_DebugAnimData.m_flAimYaw = flAimYaw; - - // Turn off a force aim yaw - either we have already updated or we don't need to. - m_bForceAimYaw = false; - -#ifndef CLIENT_DLL - QAngle angle = GetBasePlayer()->GetAbsAngles(); - angle[YAW] = m_flCurrentFeetYaw; - - GetBasePlayer()->SetAbsAngles( angle ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flGoalYaw - -// flYawRate - -// flDeltaTime - -// &flCurrentYaw - -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::ConvergeYawAngles( float flGoalYaw, float flYawRate, float flDeltaTime, float &flCurrentYaw ) -{ -#define FADE_TURN_DEGREES 60.0f - - // Find the yaw delta. - float flDeltaYaw = flGoalYaw - flCurrentYaw; - float flDeltaYawAbs = fabs( flDeltaYaw ); - flDeltaYaw = AngleNormalize( flDeltaYaw ); - - // Always do at least a bit of the turn (1%). - float flScale = 1.0f; - flScale = flDeltaYawAbs / FADE_TURN_DEGREES; - flScale = clamp( flScale, 0.01f, 1.0f ); - - float flYaw = flYawRate * flDeltaTime * flScale; - if ( flDeltaYawAbs < flYaw ) - { - flCurrentYaw = flGoalYaw; - } - else - { - float flSide = ( flDeltaYaw < 0.0f ) ? -1.0f : 1.0f; - flCurrentYaw += ( flYaw * flSide ); - } - - flCurrentYaw = AngleNormalize( flCurrentYaw ); - -#undef FADE_TURN_DEGREES -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -// Output : const QAngle& -//----------------------------------------------------------------------------- -const QAngle& CMultiPlayerAnimState::GetRenderAngles() -{ - return m_angRender; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : vel - -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::GetOuterAbsVelocity( Vector& vel ) -{ -#if defined( CLIENT_DLL ) - GetBasePlayer()->EstimateAbsVelocity( vel ); -#else - vel = GetBasePlayer()->GetAbsVelocity(); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::Release( void ) -{ - delete this; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -// Output : float -//----------------------------------------------------------------------------- -float CMultiPlayerAnimState::GetOuterXYSpeed() -{ - Vector vel; - GetOuterAbsVelocity( vel ); - return vel.Length2D(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Anim_StateLog( const char *pMsg, ... ) -{ - // Format the string. - char str[4096]; - va_list marker; - va_start( marker, pMsg ); - Q_vsnprintf( str, sizeof( str ), pMsg, marker ); - va_end( marker ); - - // Log it? - if ( anim_showstatelog.GetInt() == 1 || anim_showstatelog.GetInt() == 3 ) - { - Msg( "%s", str ); - } - - if ( anim_showstatelog.GetInt() > 1 ) - { -// static FileHandle_t hFile = filesystem->Open( "AnimState.log", "wt" ); -// filesystem->FPrintf( hFile, "%s", str ); -// filesystem->Flush( hFile ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Anim_StatePrintf( int iLine, const char *pMsg, ... ) -{ - // Format the string. - char str[4096]; - va_list marker; - va_start( marker, pMsg ); - Q_vsnprintf( str, sizeof( str ), pMsg, marker ); - va_end( marker ); - - // Show it with Con_NPrintf. - engine->Con_NPrintf( iLine, "%s", str ); - - // Log it. - Anim_StateLog( "%s\n", str ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::DebugShowAnimStateForPlayer( bool bIsServer ) -{ - // Get the player's velocity. - Vector vecVelocity; - GetOuterAbsVelocity( vecVelocity ); - - // Start animation state logging. - int iLine = 5; - if ( bIsServer ) - { - iLine = 12; - } -// Anim_StateLog( "-------------%s: frame %d -----------------\n", bIsServer ? "Server" : "Client", gpGlobals->framecount ); - Anim_StatePrintf( iLine++, "-------------%s: frame %d -----------------\n", bIsServer ? "Server" : "Client", gpGlobals->framecount ); - - // Write out the main sequence and its data. - Anim_StatePrintf( iLine++, "Main: %s, Cycle: %.2f\n", GetSequenceName( GetBasePlayer()->GetModelPtr(), GetBasePlayer()->GetSequence() ), GetBasePlayer()->GetCycle() ); - -#if 0 - if ( m_bPlayingGesture ) - { - Anim_StatePrintf( iLine++, "Gesture: %s, Cycle: %.2f\n", - GetSequenceName( GetBasePlayer()->GetModelPtr(), m_iGestureSequence ), - m_flGestureCycle ); - } -#endif - - // Write out the layers and their data. - for ( int iAnim = 0; iAnim < GetBasePlayer()->GetNumAnimOverlays(); ++iAnim ) - { -#ifdef CLIENT_DLL - C_AnimationLayer *pLayer = GetBasePlayer()->GetAnimOverlay( iAnim ); - if ( pLayer && ( pLayer->m_nOrder != CBaseAnimatingOverlay::MAX_OVERLAYS ) ) - { - Anim_StatePrintf( iLine++, "Layer %s: Weight: %.2f, Cycle: %.2f", GetSequenceName( GetBasePlayer()->GetModelPtr(), pLayer->m_nSequence ), pLayer->m_flWeight, pLayer->m_flCycle ); - } -#else - CAnimationLayer *pLayer = GetBasePlayer()->GetAnimOverlay( iAnim ); - if ( pLayer && ( pLayer->m_nOrder != CBaseAnimatingOverlay::MAX_OVERLAYS ) ) - { - Anim_StatePrintf( iLine++, "Layer %s: Weight: %.2f, Cycle: %.2f", GetSequenceName( GetBasePlayer()->GetModelPtr(), pLayer->m_nSequence ), pLayer->m_flWeight, pLayer->m_flCycle ); - } -#endif - } - - // Write out the speed data. - Anim_StatePrintf( iLine++, "Time: %.2f, Speed: %.2f, MaxSpeed: %.2f", gpGlobals->curtime, vecVelocity.Length2D(), GetCurrentMaxGroundSpeed() ); - - // Write out the 9-way blend data. - Anim_StatePrintf( iLine++, "EntityYaw: %.2f, AimYaw: %.2f, AimPitch: %.2f, MoveX: %.2f, MoveY: %.2f", m_angRender[YAW], m_DebugAnimData.m_flAimYaw, m_DebugAnimData.m_flAimPitch, m_DebugAnimData.m_vecMoveYaw.x, m_DebugAnimData.m_vecMoveYaw.y ); - -// Anim_StateLog( "--------------------------------------------\n\n" ); - Anim_StatePrintf( iLine++, "--------------------------------------------\n\n" ); - - DebugShowEyeYaw(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::DebugShowEyeYaw( void ) -{ -#ifdef _NDEBUG - - float flBaseSize = 10; - float flHeight = 80; - - Vector vecPos = GetOuter()->GetAbsOrigin() + Vector( 0.0f, 0.0f, 3.0f ); - QAngle angles( 0.0f, 0.0f, 0.0f ); - - angles[YAW] = m_flEyeYaw; - - Vector vecForward, vecRight, vecUp; - AngleVectors( angles, &vecForward, &vecRight, &vecUp ); - - // Draw a red triangle on the ground for the eye yaw. - debugoverlay->AddTriangleOverlay( ( vecPos + vecRight * flBaseSize / 2.0f ), - ( vecPos - vecRight * flBaseSize / 2.0f ), - ( vecPos + vecForward * flHeight, 255, 0, 0, 255, false, 0.01f ); - -#endif -} - -#if defined( CLIENT_DLL ) -//----------------------------------------------------------------------------- -// Purpose: -// Input : activity - -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::DebugShowActivity( Activity activity ) -{ -#ifdef _DEBUG - - const char *pszActivity = "other"; - - switch( activity ) - { - case ACT_MP_STAND_IDLE: - { - pszActivity = "idle"; - break; - } - case ACT_MP_SPRINT: - { - pszActivity = "sprint"; - break; - } - case ACT_MP_WALK: - { - pszActivity = "walk"; - break; - } - case ACT_MP_RUN: - { - pszActivity = "run"; - break; - } - } - - Msg( "Activity: %s\n", pszActivity ); - -#endif -} -#endif - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iStartLine - -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::DebugShowAnimState( int iStartLine ) -{ - Vector vOuterVel; - GetOuterAbsVelocity( vOuterVel ); - - Anim_StateLog( "----------------- frame %d -----------------\n", gpGlobals->framecount ); - - int iLine = iStartLine; - Anim_StatePrintf( iLine++, "main: %s, cycle: %.2f\n", GetSequenceName( GetBasePlayer()->GetModelPtr(), GetBasePlayer()->GetSequence() ), GetBasePlayer()->GetCycle() ); - -#if defined( CLIENT_DLL ) - for ( int i=0; i < GetBasePlayer()->GetNumAnimOverlays()-1; i++ ) - { - C_AnimationLayer *pLayer = GetBasePlayer()->GetAnimOverlay( i /*i+1?*/ ); - Anim_StatePrintf( iLine++, "%s, weight: %.2f, cycle: %.2f, aim (%d)", - pLayer->m_nOrder == CBaseAnimatingOverlay::MAX_OVERLAYS ? "--" : GetSequenceName( GetBasePlayer()->GetModelPtr(), pLayer->m_nSequence ), - pLayer->m_nOrder == CBaseAnimatingOverlay::MAX_OVERLAYS ? -1 :(float)pLayer->m_flWeight, - pLayer->m_nOrder == CBaseAnimatingOverlay::MAX_OVERLAYS ? -1 :(float)pLayer->m_flCycle, - i - ); - } -#endif - - Anim_StatePrintf( iLine++, "vel: %.2f, time: %.2f, max: %.2f", - vOuterVel.Length2D(), gpGlobals->curtime, GetInterpolatedGroundSpeed() ); - -// AnimStatePrintf( iLine++, "ent yaw: %.2f, body_yaw: %.2f, body_pitch: %.2f, move_x: %.2f, move_y: %.2f", -// m_angRender[YAW], g_flLastBodyYaw, g_flLastBodyPitch, m_vLastMovePose.x, m_vLastMovePose.y ); - - Anim_StateLog( "--------------------------------------------\n\n" ); - - // Draw a red triangle on the ground for the eye yaw. - float flBaseSize = 10; - float flHeight = 80; - Vector vBasePos = GetBasePlayer()->GetAbsOrigin() + Vector( 0, 0, 3 ); - QAngle angles( 0, 0, 0 ); - angles[YAW] = m_flEyeYaw; - Vector vForward, vRight, vUp; - AngleVectors( angles, &vForward, &vRight, &vUp ); - debugoverlay->AddTriangleOverlay( vBasePos+vRight*flBaseSize/2, vBasePos-vRight*flBaseSize/2, vBasePos+vForward*flHeight, 255, 0, 0, 255, false, 0.01 ); - - // Draw a blue triangle on the ground for the body yaw. - angles[YAW] = m_angRender[YAW]; - AngleVectors( angles, &vForward, &vRight, &vUp ); - debugoverlay->AddTriangleOverlay( vBasePos+vRight*flBaseSize/2, vBasePos-vRight*flBaseSize/2, vBasePos+vForward*flHeight, 0, 0, 255, 255, false, 0.01 ); -} - -// Debug! -const char *s_aGestureSlotNames[GESTURE_SLOT_COUNT] = -{ - "Attack and Reload", - "Grenade", - "Jump", - "Swim", - "Flinch", - "VCD", - "Custom" -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::DebugGestureInfo( void ) -{ - CBasePlayer *pPlayer = GetBasePlayer(); - if ( !pPlayer ) - return; - - int iLine = ( pPlayer->IsServer() ? 12 : ( 14 + GESTURE_SLOT_COUNT ) ); - - Anim_StatePrintf( iLine++, "%s\n", ( pPlayer->IsServer() ? "Server" : "Client" ) ); - - for ( int iGesture = 0; iGesture < GESTURE_SLOT_COUNT; ++iGesture ) - { - GestureSlot_t *pGesture = &m_aGestureSlots[iGesture]; - if ( pGesture ) - { - if( pGesture->m_bActive ) - { - Anim_StatePrintf( iLine++, "Gesture Slot %d(%s): %s %s(A:%s, C:%f P:%f)\n", - iGesture, - s_aGestureSlotNames[iGesture], - ActivityList_NameForIndex( pGesture->m_iActivity ), - GetSequenceName( pPlayer->GetModelPtr(), pGesture->m_pAnimLayer->m_nSequence ), - ( pGesture->m_bAutoKill ? "true" : "false" ), - pGesture->m_pAnimLayer->m_flCycle, pGesture->m_pAnimLayer->m_flPlaybackRate ); - } - else - { - Anim_StatePrintf( iLine++, "Gesture Slot %d(%s): NOT ACTIVE!\n", iGesture, s_aGestureSlotNames[iGesture] ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: New Model, init the pose parameters -//----------------------------------------------------------------------------- -void CMultiPlayerAnimState::OnNewModel( void ) -{ - m_bPoseParameterInit = false; - ClearAnimationState(); -} diff --git a/game/shared/Multiplayer/multiplayer_animstate.h b/game/shared/Multiplayer/multiplayer_animstate.h deleted file mode 100644 index 7ef7c4163..000000000 --- a/game/shared/Multiplayer/multiplayer_animstate.h +++ /dev/null @@ -1,320 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======// -// -// Purpose: -// -//=============================================================================// -#ifndef MULTIPLAYERANIMSTATE_H -#define MULTIPLAYERANIMSTATE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "convar.h" -#include "basecombatweapon_shared.h" - -#if defined( CLIENT_DLL ) -class C_BasePlayer; -#define CPlayer C_BasePlayer -#else -class CBasePlayer; -#endif - -enum PlayerAnimEvent_t -{ - PLAYERANIMEVENT_ATTACK_PRIMARY, - PLAYERANIMEVENT_ATTACK_SECONDARY, - PLAYERANIMEVENT_ATTACK_GRENADE, - PLAYERANIMEVENT_RELOAD, - PLAYERANIMEVENT_RELOAD_LOOP, - PLAYERANIMEVENT_RELOAD_END, - PLAYERANIMEVENT_JUMP, - PLAYERANIMEVENT_SWIM, - PLAYERANIMEVENT_DIE, - PLAYERANIMEVENT_FLINCH_CHEST, - PLAYERANIMEVENT_FLINCH_HEAD, - PLAYERANIMEVENT_FLINCH_LEFTARM, - PLAYERANIMEVENT_FLINCH_RIGHTARM, - PLAYERANIMEVENT_FLINCH_LEFTLEG, - PLAYERANIMEVENT_FLINCH_RIGHTLEG, - PLAYERANIMEVENT_DOUBLEJUMP, - - // Cancel. - PLAYERANIMEVENT_CANCEL, - PLAYERANIMEVENT_SPAWN, - - // Snap to current yaw exactly - PLAYERANIMEVENT_SNAP_YAW, - - PLAYERANIMEVENT_CUSTOM, // Used to play specific activities - PLAYERANIMEVENT_CUSTOM_GESTURE, - PLAYERANIMEVENT_CUSTOM_SEQUENCE, // Used to play specific sequences - PLAYERANIMEVENT_CUSTOM_GESTURE_SEQUENCE, - - // TF Specific. Here until there's a derived game solution to this. - PLAYERANIMEVENT_ATTACK_PRE, - PLAYERANIMEVENT_ATTACK_POST, - PLAYERANIMEVENT_GRENADE1_DRAW, - PLAYERANIMEVENT_GRENADE2_DRAW, - PLAYERANIMEVENT_GRENADE1_THROW, - PLAYERANIMEVENT_GRENADE2_THROW, - PLAYERANIMEVENT_VOICE_COMMAND_GESTURE, - - PLAYERANIMEVENT_COUNT -}; - -// Gesture Slots. -enum -{ - GESTURE_SLOT_ATTACK_AND_RELOAD, - GESTURE_SLOT_GRENADE, - GESTURE_SLOT_JUMP, - GESTURE_SLOT_SWIM, - GESTURE_SLOT_FLINCH, - GESTURE_SLOT_VCD, - GESTURE_SLOT_CUSTOM, - - GESTURE_SLOT_COUNT, -}; - -#define GESTURE_SLOT_INVALID -1 - -struct GestureSlot_t -{ - int m_iGestureSlot; - Activity m_iActivity; - bool m_bAutoKill; - bool m_bActive; - CAnimationLayer *m_pAnimLayer; -}; - -inline bool IsCustomPlayerAnimEvent( PlayerAnimEvent_t event ) -{ - return ( event == PLAYERANIMEVENT_CUSTOM ) || ( event == PLAYERANIMEVENT_CUSTOM_GESTURE ) || - ( event == PLAYERANIMEVENT_CUSTOM_SEQUENCE ) || ( event == PLAYERANIMEVENT_CUSTOM_GESTURE_SEQUENCE ); -} - -struct MultiPlayerPoseData_t -{ - int m_iMoveX; - int m_iMoveY; - int m_iAimYaw; - int m_iAimPitch; - int m_iBodyHeight; - - float m_flEstimateYaw; - float m_flLastAimTurnTime; - - void Init() - { - m_iMoveX = 0; - m_iMoveY = 0; - m_iAimYaw = 0; - m_iAimPitch = 0; - m_iBodyHeight = 0; - m_flEstimateYaw = 0.0f; - m_flLastAimTurnTime = 0.0f; - } -}; - -struct DebugPlayerAnimData_t -{ - float m_flSpeed; - float m_flAimPitch; - float m_flAimYaw; - float m_flBodyHeight; - Vector2D m_vecMoveYaw; - - void Init() - { - m_flSpeed = 0.0f; - m_flAimPitch = 0.0f; - m_flAimYaw = 0.0f; - m_flBodyHeight = 0.0f; - m_vecMoveYaw.Init(); - } -}; - -struct MultiPlayerMovementData_t -{ - // Set speeds to -1 if they are not used. - float m_flWalkSpeed; - float m_flRunSpeed; - float m_flSprintSpeed; - float m_flBodyYawRate; -}; - - -//============================================================================= -// -// Multi-Player Animation State -// -class CMultiPlayerAnimState -{ -public: - - DECLARE_CLASS_NOBASE( CMultiPlayerAnimState ); - - // Creation/Destruction - CMultiPlayerAnimState() {} - CMultiPlayerAnimState( CBasePlayer *pPlayer, MultiPlayerMovementData_t &movementData ); - ~CMultiPlayerAnimState(); - - // This is called by both the client and the server in the same way to trigger events for - // players firing, jumping, throwing grenades, etc. - virtual void ClearAnimationState(); - virtual void DoAnimationEvent( PlayerAnimEvent_t event, int nData = 0 ); - virtual Activity CalcMainActivity(); - virtual void Update( float eyeYaw, float eyePitch ); - virtual void Release( void ); - - const QAngle &GetRenderAngles(); - - virtual Activity TranslateActivity( Activity actDesired ); - - virtual void SetRunSpeed( float flSpeed ) { m_MovementData.m_flRunSpeed = flSpeed; } - virtual void SetWalkSpeed( float flSpeed ) { m_MovementData.m_flWalkSpeed = flSpeed; } - virtual void SetSprintSpeed( float flSpeed ) { m_MovementData.m_flSprintSpeed = flSpeed; } - - // Debug - virtual void ShowDebugInfo( void ); - virtual void DebugShowAnimState( int iStartLine ); - - Activity GetCurrentMainActivity( void ) { return m_eCurrentMainSequenceActivity; } - - void OnNewModel( void ); - - // Gestures. - void ResetGestureSlots( void ); - void ResetGestureSlot( int iGestureSlot ); - void AddVCDSequenceToGestureSlot( int iGestureSlot, int iGestureSequence, bool bAutoKill = true ); - - // Feet. - bool m_bForceAimYaw; - -protected: - - virtual void Init( CBasePlayer *pPlayer, MultiPlayerMovementData_t &movementData ); - CBasePlayer *GetBasePlayer( void ) { return m_pPlayer; } - - // Allow inheriting classes to override SelectWeightedSequence - virtual int SelectWeightedSequence( Activity activity ) { return GetBasePlayer()->SelectWeightedSequence( activity ); } - virtual void RestartMainSequence(); - - void GetOuterAbsVelocity( Vector& vel ); - float GetOuterXYSpeed(); - - virtual bool HandleJumping( Activity &idealActivity ); - virtual bool HandleDucking( Activity &idealActivity ); - virtual bool HandleMoving( Activity &idealActivity ); - virtual bool HandleSwimming( Activity &idealActivity ); - virtual bool HandleDying( Activity &idealActivity ); - - // Gesture Slots - CUtlVector m_aGestureSlots; - bool InitGestureSlots( void ); - void ShutdownGestureSlots( void ); - bool IsGestureSlotActive( int iGestureSlot ); - bool IsGestureSlotPlaying( int iGestureSlot, Activity iGestureActivity ); - void AddToGestureSlot( int iGestureSlot, Activity iGestureActivity, bool bAutoKill ); - void RestartGesture( int iGestureSlot, Activity iGestureActivity, bool bAutoKill = true ); - void ComputeGestureSequence( CStudioHdr *pStudioHdr ); - void UpdateGestureLayer( CStudioHdr *pStudioHdr, GestureSlot_t *pGesture ); - void DebugGestureInfo( void ); - -#ifdef CLIENT_DLL - void RunGestureSlotAnimEventsToCompletion( GestureSlot_t *pGesture ); -#endif - - virtual void PlayFlinchGesture( Activity iActivity ); - - virtual float CalcMovementPlaybackRate( bool *bIsMoving ); - - // Pose paramters. - bool SetupPoseParameters( CStudioHdr *pStudioHdr ); - virtual void ComputePoseParam_MoveYaw( CStudioHdr *pStudioHdr ); - virtual void ComputePoseParam_AimPitch( CStudioHdr *pStudioHdr ); - virtual void ComputePoseParam_AimYaw( CStudioHdr *pStudioHdr ); - void ComputePoseParam_BodyHeight( CStudioHdr *pStudioHdr ); - virtual void EstimateYaw( void ); - void ConvergeYawAngles( float flGoalYaw, float flYawRate, float flDeltaTime, float &flCurrentYaw ); - - virtual float GetCurrentMaxGroundSpeed(); - virtual void ComputeSequences( CStudioHdr *pStudioHdr ); - void ComputeMainSequence(); - void UpdateInterpolators(); - void ResetGroundSpeed( void ); - float GetInterpolatedGroundSpeed( void ); - - void ComputeFireSequence(); - void ComputeDeployedSequence(); - - bool ShouldUpdateAnimState(); - - void DebugShowAnimStateForPlayer( bool bIsServer ); - void DebugShowEyeYaw( void ); - -// Client specific. -#ifdef CLIENT_DLL - - // Debug. - void DebugShowActivity( Activity activity ); - -#endif - -protected: - - CBasePlayer *m_pPlayer; - - QAngle m_angRender; - - // Pose parameters. - bool m_bPoseParameterInit; - MultiPlayerPoseData_t m_PoseParameterData; - DebugPlayerAnimData_t m_DebugAnimData; - - bool m_bCurrentFeetYawInitialized; - float m_flLastAnimationStateClearTime; - - float m_flEyeYaw; - float m_flEyePitch; - float m_flGoalFeetYaw; - float m_flCurrentFeetYaw; - float m_flLastAimTurnTime; - - MultiPlayerMovementData_t m_MovementData; - - // Jumping. - bool m_bJumping; - float m_flJumpStartTime; - bool m_bFirstJumpFrame; - - // Swimming. - bool m_bInSwim; - bool m_bFirstSwimFrame; - - // Dying - bool m_bDying; - bool m_bFirstDyingFrame; - - // Last activity we've used on the lower body. Used to determine if animations should restart. - Activity m_eCurrentMainSequenceActivity; - - // Specific full-body sequence to play - int m_nSpecificMainSequence; - - // Weapon data. - CHandle m_hActiveWeapon; - - // Ground speed interpolators. -#ifdef CLIENT_DLL - float m_flLastGroundSpeedUpdateTime; - CInterpolatedVar m_iv_flMaxGroundSpeed; -#endif - float m_flMaxGroundSpeed; -}; - -// If this is set, then the game code needs to make sure to send player animation events -// to the local player if he's the one being watched. -extern ConVar cl_showanimstate; - -#endif // DOD_PLAYERANIMSTATE_H diff --git a/game/shared/SceneCache.cpp b/game/shared/SceneCache.cpp deleted file mode 100644 index c13856530..000000000 --- a/game/shared/SceneCache.cpp +++ /dev/null @@ -1,132 +0,0 @@ -//====== Copyright 1996-2007, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#include "SceneCache.h" -#include "choreoscene.h" -#include "choreoevent.h" - -extern ISoundEmitterSystemBase *soundemitterbase; -CChoreoScene *BlockingLoadScene( const char *filename ); - -CSceneCache::CSceneCache() -{ - msecs = 0; -} - -CSceneCache::CSceneCache( const CSceneCache& src ) -{ - msecs = src.msecs; - sounds = src.sounds; -} - -int CSceneCache::GetSoundCount() const -{ - return sounds.Count(); -} - -char const *CSceneCache::GetSoundName( int index ) -{ - return soundemitterbase->GetSoundName( sounds[ index ] ); -} - -void CSceneCache::Save( CUtlBuffer& buf ) -{ - buf.PutUnsignedInt( msecs ); - - unsigned short c = GetSoundCount(); - buf.PutShort( c ); - - Assert( sounds.Count() <= 65536 ); - - for ( int i = 0; i < c; ++i ) - { - buf.PutString( GetSoundName( i ) ); - } -} - -void CSceneCache::Restore( CUtlBuffer& buf ) -{ - MEM_ALLOC_CREDIT(); - - msecs = buf.GetUnsignedInt(); - - unsigned short c = (unsigned short)buf.GetShort(); - - for ( int i = 0; i < c; ++i ) - { - char soundname[ 512 ]; - buf.GetString( soundname, sizeof( soundname ) ); - - int idx = soundemitterbase->GetSoundIndex( soundname ); - if ( idx != -1 ) - { - Assert( idx <= 65535 ); - if ( sounds.Find( idx ) == sounds.InvalidIndex() ) - { - sounds.AddToTail( (unsigned short)idx ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Static method -// Input : *event - -// soundlist - -//----------------------------------------------------------------------------- -void CSceneCache::PrecacheSceneEvent( CChoreoEvent *event, CUtlVector< unsigned short >& soundlist ) -{ - if ( !event || event->GetType() != CChoreoEvent::SPEAK ) - return; - - int idx = soundemitterbase->GetSoundIndex( event->GetParameters() ); - if ( idx != -1 ) - { - MEM_ALLOC_CREDIT(); - Assert( idx <= 65535 ); - soundlist.AddToTail( (unsigned short)idx ); - } - - if ( event->GetCloseCaptionType() == CChoreoEvent::CC_MASTER ) - { - char tok[ CChoreoEvent::MAX_CCTOKEN_STRING ]; - if ( event->GetPlaybackCloseCaptionToken( tok, sizeof( tok ) ) ) - { - int idx = soundemitterbase->GetSoundIndex( tok ); - if ( idx != -1 && soundlist.Find( idx ) == soundlist.InvalidIndex() ) - { - MEM_ALLOC_CREDIT(); - Assert( idx <= 65535 ); - soundlist.AddToTail( (unsigned short)idx ); - } - } - } -} - -void CSceneCache::Rebuild( char const *filename ) -{ - msecs = 0; - sounds.RemoveAll(); - - CChoreoScene *scene = BlockingLoadScene( filename ); - if ( scene ) - { - // Walk all events looking for SPEAK events - CChoreoEvent *event; - int c = scene->GetNumEvents(); - for ( int i = 0; i < c; ++i ) - { - event = scene->GetEvent( i ); - PrecacheSceneEvent( event, sounds ); - } - - // Update scene duration, too - msecs = (int)( scene->FindStopTime() * 1000.0f + 0.5f ); - - delete scene; - } -} diff --git a/game/shared/SceneCache.h b/game/shared/SceneCache.h deleted file mode 100644 index c561d44b2..000000000 --- a/game/shared/SceneCache.h +++ /dev/null @@ -1,42 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef SCENECACHE_H -#define SCENECACHE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "UtlCachedFileData.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" - -class CChoreoEvent; - -#define SCENECACHE_VERSION 7 - -#pragma pack(1) -class CSceneCache : public IBaseCacheInfo -{ -public: - unsigned int msecs; - CUtlVector< unsigned short > sounds; - - CSceneCache(); - CSceneCache( const CSceneCache& src ); - - int GetSoundCount() const; - char const *GetSoundName( int index ); - - virtual void Save( CUtlBuffer& buf ); - virtual void Restore( CUtlBuffer& buf ); - virtual void Rebuild( char const *filename ); - - static unsigned int ComputeSoundScriptFileTimestampChecksum(); - static void PrecacheSceneEvent( CChoreoEvent *event, CUtlVector< unsigned short >& soundlist ); -}; -#pragma pack() - -#endif // SCENECACHE_H diff --git a/game/shared/SoundEmitterSystem.cpp b/game/shared/SoundEmitterSystem.cpp deleted file mode 100644 index b0807bd9c..000000000 --- a/game/shared/SoundEmitterSystem.cpp +++ /dev/null @@ -1,1383 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include -#include -#include "engine/IEngineSound.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" -#include "igamesystem.h" -#include "soundchars.h" -#include "filesystem.h" -#include "tier0/vprof.h" -#include "checksum_crc.h" -#include "tier0/icommandline.h" - -#ifndef CLIENT_DLL -#include "envmicrophone.h" -#include "sceneentity.h" -#else -#include -#include -#include "hud_closecaption.h" -#define CRecipientFilter C_RecipientFilter -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -static ConVar sv_soundemitter_trace( "sv_soundemitter_trace", "0", FCVAR_REPLICATED, "Show all EmitSound calls including their symbolic name and the actual wave file they resolved to\n" ); - -extern ISoundEmitterSystemBase *soundemitterbase; -static ConVar *g_pClosecaption = NULL; - -#ifdef _XBOX -int LookupStringFromCloseCaptionToken( char const *token ); -const wchar_t *GetStringForIndex( int index ); -#endif -static bool g_bPermitDirectSoundPrecache = false; - -#if !defined( CLIENT_DLL ) - -void ClearModelSoundsCache(); - -#endif // !CLIENT_DLL - -void WaveTrace( char const *wavname, char const *funcname ) -{ - if ( IsX360() && !IsDebug() ) - { - return; - } - - static CUtlSymbolTable s_WaveTrace; - - // Make sure we only show the message once - if ( UTL_INVAL_SYMBOL == s_WaveTrace.Find( wavname ) ) - { - DevMsg( "%s directly referenced wave %s (should use game_sounds.txt system instead)\n", - funcname, wavname ); - s_WaveTrace.AddString( wavname ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &src - -//----------------------------------------------------------------------------- -EmitSound_t::EmitSound_t( const CSoundParameters &src ) -{ - m_nChannel = src.channel; - m_pSoundName = src.soundname; - m_flVolume = src.volume; - m_SoundLevel = src.soundlevel; - m_nFlags = 0; - m_nPitch = src.pitch; - m_pOrigin = 0; - m_flSoundTime = ( src.delay_msec == 0 ) ? 0.0f : gpGlobals->curtime + ( (float)src.delay_msec / 1000.0f ); - m_pflSoundDuration = 0; - m_bEmitCloseCaption = true; - m_bWarnOnMissingCloseCaption = false; - m_bWarnOnDirectWaveReference = false; - m_nSpeakerEntity = -1; -} - -void Hack_FixEscapeChars( char *str ) -{ - int len = Q_strlen( str ) + 1; - char *i = str; - char *o = (char *)_alloca( len ); - char *osave = o; - while ( *i ) - { - if ( *i == '\\' ) - { - switch ( *( i + 1 ) ) - { - case 'n': - *o = '\n'; - ++i; - break; - default: - *o = *i; - break; - } - } - else - { - *o = *i; - } - - ++i; - ++o; - } - *o = 0; - Q_strncpy( str, osave, len ); -} -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CSoundEmitterSystem : public CBaseGameSystem -{ -public: - virtual char const *Name() { return "CSoundEmitterSystem"; } - -#if !defined( CLIENT_DLL ) - bool m_bLogPrecache; - FileHandle_t m_hPrecacheLogFile; - CUtlSymbolTable m_PrecachedScriptSounds; -public: - CSoundEmitterSystem( char const *pszName ) : - m_bLogPrecache( false ), - m_hPrecacheLogFile( FILESYSTEM_INVALID_HANDLE ) - { - } - - void LogPrecache( char const *soundname ) - { - if ( !m_bLogPrecache ) - return; - - // Make sure we only show the message once - if ( UTL_INVAL_SYMBOL != m_PrecachedScriptSounds.Find( soundname ) ) - return; - - if (m_hPrecacheLogFile == FILESYSTEM_INVALID_HANDLE) - { - StartLog(); - } - - m_PrecachedScriptSounds.AddString( soundname ); - - if (m_hPrecacheLogFile != FILESYSTEM_INVALID_HANDLE) - { - filesystem->Write("\"", 1, m_hPrecacheLogFile); - filesystem->Write(soundname, Q_strlen(soundname), m_hPrecacheLogFile); - filesystem->Write("\"\n", 2, m_hPrecacheLogFile); - } - else - { - Warning( "Disabling precache logging due to file i/o problem!!!\n" ); - m_bLogPrecache = false; - } - } - - void StartLog() - { - m_PrecachedScriptSounds.RemoveAll(); - - if ( !m_bLogPrecache ) - return; - - if ( FILESYSTEM_INVALID_HANDLE != m_hPrecacheLogFile ) - { - return; - } - - filesystem->CreateDirHierarchy("reslists", "DEFAULT_WRITE_PATH"); - - // open the new level reslist - char path[_MAX_PATH]; - Q_snprintf(path, sizeof(path), "reslists\\%s.snd", gpGlobals->mapname.ToCStr() ); - m_hPrecacheLogFile = filesystem->Open(path, "wt", "GAME"); - } - - void FinishLog() - { - if ( FILESYSTEM_INVALID_HANDLE != m_hPrecacheLogFile ) - { - filesystem->Close( m_hPrecacheLogFile ); - m_hPrecacheLogFile = FILESYSTEM_INVALID_HANDLE; - } - - m_PrecachedScriptSounds.RemoveAll(); - } -#else - CSoundEmitterSystem( char const *name ) - { - } - -#endif - - // IServerSystem stuff - virtual bool Init() - { - Assert( soundemitterbase ); -#if !defined( CLIENT_DLL ) - m_bLogPrecache = CommandLine()->CheckParm( "-makereslists" ) ? true : false; -#endif - g_pClosecaption = cvar->FindVar("closecaption"); - Assert(g_pClosecaption); - return soundemitterbase->ModInit(); - } - - virtual void Shutdown() - { - Assert( soundemitterbase ); -#if !defined( CLIENT_DLL ) - FinishLog(); -#endif - soundemitterbase->ModShutdown(); - } - - virtual void TraceEmitSound( char const *fmt, ... ) - { - if ( !sv_soundemitter_trace.GetBool() ) - return; - - va_list argptr; - char string[256]; - va_start (argptr, fmt); - Q_vsnprintf( string, sizeof( string ), fmt, argptr ); - va_end (argptr); - - // Spew to console - Msg( "%s %s", CBaseEntity::IsServer() ? "(sv)" : "(cl)", string ); - } - - // Precache all wave files referenced in wave or rndwave keys - virtual void LevelInitPreEntity() - { - char mapname[ 256 ]; -#if !defined( CLIENT_DLL ) - StartLog(); - Q_snprintf( mapname, sizeof( mapname ), "maps/%s", STRING( gpGlobals->mapname ) ); -#else - Q_strncpy( mapname, engine->GetLevelName(), sizeof( mapname ) ); -#endif - - Q_FixSlashes( mapname ); - Q_strlower( mapname ); - - // Load in any map specific overrides - char scriptfile[ 512 ]; - Q_StripExtension( mapname, scriptfile, sizeof( scriptfile ) ); - Q_strncat( scriptfile, "_level_sounds.txt", sizeof( scriptfile ), COPY_ALL_CHARACTERS ); - - if ( filesystem->FileExists( scriptfile, "GAME" ) ) - { - soundemitterbase->AddSoundOverrides( scriptfile ); - } - -#if !defined( CLIENT_DLL ) - for ( int i=soundemitterbase->First(); i != soundemitterbase->InvalidIndex(); i=soundemitterbase->Next( i ) ) - { - CSoundParametersInternal *pParams = soundemitterbase->InternalGetParametersForSound( i ); - if ( pParams->ShouldPreload() ) - { - InternalPrecacheWaves( i ); - } - } -#endif - } - - virtual void LevelInitPostEntity() - { - } - - virtual void LevelShutdownPostEntity() - { - soundemitterbase->ClearSoundOverrides(); - -#if !defined( CLIENT_DLL ) - FinishLog(); -#endif - } - - void InternalPrecacheWaves( int soundIndex ) - { - CSoundParametersInternal *internal = soundemitterbase->InternalGetParametersForSound( soundIndex ); - if ( !internal ) - return; - - int waveCount = internal->NumSoundNames(); - if ( !waveCount ) - { - DevMsg( "CSoundEmitterSystem: sounds.txt entry '%s' has no waves listed under 'wave' or 'rndwave' key!!!\n", - soundemitterbase->GetSoundName( soundIndex ) ); - } - else - { - g_bPermitDirectSoundPrecache = true; - - for( int wave = 0; wave < waveCount; wave++ ) - { - CBaseEntity::PrecacheSound( soundemitterbase->GetWaveName( internal->GetSoundNames()[ wave ].symbol ) ); - } - - g_bPermitDirectSoundPrecache = false; - } - } - - void InternalPrefetchWaves( int soundIndex ) - { - CSoundParametersInternal *internal = soundemitterbase->InternalGetParametersForSound( soundIndex ); - if ( !internal ) - return; - - int waveCount = internal->NumSoundNames(); - if ( !waveCount ) - { - DevMsg( "CSoundEmitterSystem: sounds.txt entry '%s' has no waves listed under 'wave' or 'rndwave' key!!!\n", - soundemitterbase->GetSoundName( soundIndex ) ); - } - else - { - for( int wave = 0; wave < waveCount; wave++ ) - { - CBaseEntity::PrefetchSound( soundemitterbase->GetWaveName( internal->GetSoundNames()[ wave ].symbol ) ); - } - } - } - - HSOUNDSCRIPTHANDLE PrecacheScriptSound( const char *soundname ) - { - int soundIndex = soundemitterbase->GetSoundIndex( soundname ); - if ( !soundemitterbase->IsValidIndex( soundIndex ) ) - { - if ( Q_stristr( soundname, ".wav" ) || Q_strstr( soundname, ".mp3" ) ) - { - g_bPermitDirectSoundPrecache = true; - - CBaseEntity::PrecacheSound( soundname ); - - g_bPermitDirectSoundPrecache = false; - return SOUNDEMITTER_INVALID_HANDLE; - } - -#if !defined( CLIENT_DLL ) - if ( soundname[ 0 ] ) - { - static CUtlSymbolTable s_PrecacheScriptSoundFailures; - - // Make sure we only show the message once - if ( UTL_INVAL_SYMBOL == s_PrecacheScriptSoundFailures.Find( soundname ) ) - { - DevMsg( "PrecacheScriptSound '%s' failed, no such sound script entry\n", soundname ); - s_PrecacheScriptSoundFailures.AddString( soundname ); - } - } -#endif - return (HSOUNDSCRIPTHANDLE)soundIndex; - } -#if !defined( CLIENT_DLL ) - LogPrecache( soundname ); -#endif - - InternalPrecacheWaves( soundIndex ); - return (HSOUNDSCRIPTHANDLE)soundIndex; - } - - void PrefetchScriptSound( const char *soundname ) - { - int soundIndex = soundemitterbase->GetSoundIndex( soundname ); - if ( !soundemitterbase->IsValidIndex( soundIndex ) ) - { - if ( Q_stristr( soundname, ".wav" ) || Q_strstr( soundname, ".mp3" ) ) - { - CBaseEntity::PrefetchSound( soundname ); - } - return; - } - - InternalPrefetchWaves( soundIndex ); - } -public: - - void EmitSoundByHandle( IRecipientFilter& filter, int entindex, const EmitSound_t & ep, HSOUNDSCRIPTHANDLE& handle ) - { - // Pull data from parameters - CSoundParameters params; - - // Try to deduce the actor's gender - gender_t gender = GENDER_NONE; - CBaseEntity *ent = CBaseEntity::Instance( entindex ); - if ( ent ) - { - char const *actorModel = STRING( ent->GetModelName() ); - gender = soundemitterbase->GetActorGender( actorModel ); - } - - if ( !soundemitterbase->GetParametersForSoundEx( ep.m_pSoundName, handle, params, gender, true ) ) - { - return; - } - - if ( !params.soundname[0] ) - return; - - if ( !Q_strncasecmp( params.soundname, "vo", 2 ) && - !( params.channel == CHAN_STREAM || - params.channel == CHAN_VOICE ) ) - { - DevMsg( "EmitSound: Voice wave file %s doesn't specify CHAN_VOICE or CHAN_STREAM for sound %s\n", - params.soundname, ep.m_pSoundName ); - } - - // handle SND_CHANGEPITCH/SND_CHANGEVOL and other sound flags.etc. - if( ep.m_nFlags & SND_CHANGE_PITCH ) - { - params.pitch = ep.m_nPitch; - } - - if( ep.m_nFlags & SND_CHANGE_VOL ) - { - params.volume = ep.m_flVolume; - } - -#if !defined( CLIENT_DLL ) - bool bSwallowed = CEnvMicrophone::OnSoundPlayed( - entindex, - params.soundname, - params.soundlevel, - params.volume, - ep.m_nFlags, - params.pitch, - ep.m_pOrigin, - ep.m_flSoundTime, - ep.m_UtlVecSoundOrigin ); - if ( bSwallowed ) - return; -#endif - -#if defined( _DEBUG ) && !defined( CLIENT_DLL ) - if ( !enginesound->IsSoundPrecached( params.soundname ) ) - { - Msg( "Sound %s:%s was not precached\n", ep.m_pSoundName, params.soundname ); - } -#endif - - float st = ep.m_flSoundTime; - if ( !st && - params.delay_msec != 0 ) - { - st = gpGlobals->curtime + (float)params.delay_msec / 1000.f; - } - - enginesound->EmitSound( - filter, - entindex, - params.channel, - params.soundname, - params.volume, - (soundlevel_t)params.soundlevel, - ep.m_nFlags, - params.pitch, - ep.m_pOrigin, - NULL, - &ep.m_UtlVecSoundOrigin, - true, - st, - ep.m_nSpeakerEntity ); - if ( ep.m_pflSoundDuration ) - { - *ep.m_pflSoundDuration = enginesound->GetSoundDuration( params.soundname ); - } - - TraceEmitSound( "EmitSound: '%s' emitted as '%s' (ent %i)\n", - ep.m_pSoundName, params.soundname, entindex ); - - - // Don't caption modulations to the sound - if ( !( ep.m_nFlags & ( SND_CHANGE_PITCH | SND_CHANGE_VOL ) ) ) - { - EmitCloseCaption( filter, entindex, params, ep ); - } - } - - void EmitSound( IRecipientFilter& filter, int entindex, const EmitSound_t & ep ) - { - VPROF( "CSoundEmitterSystem::EmitSound (calls engine)" ); - if ( ep.m_pSoundName && - ( Q_stristr( ep.m_pSoundName, ".wav" ) || - Q_stristr( ep.m_pSoundName, ".mp3" ) || - ep.m_pSoundName[0] == '!' ) ) - { -#if !defined( CLIENT_DLL ) - bool bSwallowed = CEnvMicrophone::OnSoundPlayed( - entindex, - ep.m_pSoundName, - ep.m_SoundLevel, - ep.m_flVolume, - ep.m_nFlags, - ep.m_nPitch, - ep.m_pOrigin, - ep.m_flSoundTime, - ep.m_UtlVecSoundOrigin ); - if ( bSwallowed ) - return; -#endif - - if ( ep.m_bWarnOnDirectWaveReference && - Q_stristr( ep.m_pSoundName, ".wav" ) ) - { - WaveTrace( ep.m_pSoundName, "Emitsound" ); - } - -#if defined( _DEBUG ) && !defined( CLIENT_DLL ) - if ( !enginesound->IsSoundPrecached( ep.m_pSoundName ) ) - { - Msg( "Sound %s was not precached\n", ep.m_pSoundName ); - } -#endif - enginesound->EmitSound( - filter, - entindex, - ep.m_nChannel, - ep.m_pSoundName, - ep.m_flVolume, - ep.m_SoundLevel, - ep.m_nFlags, - ep.m_nPitch, - ep.m_pOrigin, - NULL, - &ep.m_UtlVecSoundOrigin, - true, - ep.m_flSoundTime, - ep.m_nSpeakerEntity ); - if ( ep.m_pflSoundDuration ) - { - *ep.m_pflSoundDuration = enginesound->GetSoundDuration( ep.m_pSoundName ); - } - - TraceEmitSound( "EmitSound: Raw wave emitted '%s' (ent %i)\n", - ep.m_pSoundName, entindex ); - return; - } - - if ( ep.m_hSoundScriptHandle == SOUNDEMITTER_INVALID_HANDLE ) - { - ep.m_hSoundScriptHandle = (HSOUNDSCRIPTHANDLE)soundemitterbase->GetSoundIndex( ep.m_pSoundName ); - } - - if ( ep.m_hSoundScriptHandle == -1 ) - return; - - EmitSoundByHandle( filter, entindex, ep, ep.m_hSoundScriptHandle ); - } - - void EmitCloseCaption( IRecipientFilter& filter, int entindex, bool fromplayer, char const *token, CUtlVector< Vector >& originlist, float duration, bool warnifmissing /*= false*/ ) - { - // No close captions in multiplayer... - if ( gpGlobals->maxClients > 1 || (gpGlobals->maxClients==1 && !g_pClosecaption->GetBool())) - { - return; - } - - // A negative duration means fill it in from the wav file if possible - if ( duration < 0.0f ) - { - char const *wav = soundemitterbase->GetWavFileForSound( token, GENDER_NONE ); - if ( wav ) - { - duration = enginesound->GetSoundDuration( wav ); - } - else - { - duration = 2.0f; - } - } - - char lowercase[ 256 ]; - Q_strncpy( lowercase, token, sizeof( lowercase ) ); - Q_strlower( lowercase ); - if ( Q_strstr( lowercase, "\\" ) ) - { - Hack_FixEscapeChars( lowercase ); - } - - // NOTE: We must make a copy or else if the filter is owned by a SoundPatch, we'll end up destructively removing - // all players from it!!!! - CRecipientFilter filterCopy; - filterCopy.CopyFrom( (CRecipientFilter &)filter ); - - // Remove any players who don't want close captions - CBaseEntity::RemoveRecipientsIfNotCloseCaptioning( (CRecipientFilter &)filterCopy ); - -#if !defined( CLIENT_DLL ) - { - // Defined in sceneentity.cpp - bool AttenuateCaption( const char *token, const Vector& listener, CUtlVector< Vector >& soundorigins ); - - if ( filterCopy.GetRecipientCount() > 0 ) - { - int c = filterCopy.GetRecipientCount(); - for ( int i = c - 1 ; i >= 0; --i ) - { - CBasePlayer *player = UTIL_PlayerByIndex( filterCopy.GetRecipientIndex( i ) ); - if ( !player ) - continue; - - Vector playerOrigin = player->GetAbsOrigin(); - - if ( AttenuateCaption( lowercase, playerOrigin, originlist ) ) - { - filterCopy.RemoveRecipient( player ); - } - } - } - } -#endif - // Anyone left? - if ( filterCopy.GetRecipientCount() > 0 ) - { - -#if !defined( CLIENT_DLL ) - - byte byteflags = 0; - if ( warnifmissing ) - { - byteflags |= CLOSE_CAPTION_WARNIFMISSING; - } - if ( fromplayer ) - { - byteflags |= CLOSE_CAPTION_FROMPLAYER; - } - - CBaseEntity *pActor = CBaseEntity::Instance( entindex ); - if ( pActor ) - { - char const *pszActorModel = STRING( pActor->GetModelName() ); - gender_t gender = soundemitterbase->GetActorGender( pszActorModel ); - - if ( gender == GENDER_MALE ) - { - byteflags |= CLOSE_CAPTION_GENDER_MALE; - } - else if ( gender == GENDER_FEMALE ) - { - byteflags |= CLOSE_CAPTION_GENDER_FEMALE; - } - } - - // Send caption and duration hint down to client - UserMessageBegin( filterCopy, "CloseCaption" ); - WRITE_STRING( lowercase ); - WRITE_SHORT( MIN( 255, (int)( duration * 10.0f ) ) ), - WRITE_BYTE( byteflags ), - MessageEnd(); -#else - // Direct dispatch - CHudCloseCaption *cchud = GET_HUDELEMENT( CHudCloseCaption ); - if ( cchud ) - { - cchud->ProcessCaption( lowercase, duration, fromplayer ); - } -#endif - } - } - - void EmitCloseCaption( IRecipientFilter& filter, int entindex, const CSoundParameters & params, const EmitSound_t & ep ) - { - // No close captions in multiplayer... - if ( gpGlobals->maxClients > 1 || (gpGlobals->maxClients==1 && !g_pClosecaption->GetBool())) - { - return; - } - - if ( !ep.m_bEmitCloseCaption ) - { - return; - } - - // NOTE: We must make a copy or else if the filter is owned by a SoundPatch, we'll end up destructively removing - // all players from it!!!! - CRecipientFilter filterCopy; - filterCopy.CopyFrom( (CRecipientFilter &)filter ); - - // Remove any players who don't want close captions - CBaseEntity::RemoveRecipientsIfNotCloseCaptioning( (CRecipientFilter &)filterCopy ); - - // Anyone left? - if ( filterCopy.GetRecipientCount() <= 0 ) - { - return; - } - - float duration = 0.0f; - if ( ep.m_pflSoundDuration ) - { - duration = *ep.m_pflSoundDuration; - } - else - { - duration = enginesound->GetSoundDuration( params.soundname ); - } - - bool fromplayer = false; - CBaseEntity *ent = CBaseEntity::Instance( entindex ); - if ( ent ) - { - while ( ent ) - { - if ( ent->IsPlayer() ) - { - fromplayer = true; - break; - } - - ent = ent->GetOwnerEntity(); - } - } - EmitCloseCaption( filter, entindex, fromplayer, ep.m_pSoundName, ep.m_UtlVecSoundOrigin, duration, ep.m_bWarnOnMissingCloseCaption ); - } - - void EmitAmbientSound( int entindex, const Vector& origin, const char *soundname, float flVolume, int iFlags, int iPitch, float soundtime /*= 0.0f*/, float *duration /*=NULL*/ ) - { - // Pull data from parameters - CSoundParameters params; - - if ( !soundemitterbase->GetParametersForSound( soundname, params, GENDER_NONE ) ) - { - return; - } - - if( iFlags & SND_CHANGE_PITCH ) - { - params.pitch = iPitch; - } - - if( iFlags & SND_CHANGE_VOL ) - { - params.volume = flVolume; - } - -#if defined( CLIENT_DLL ) - enginesound->EmitAmbientSound( params.soundname, params.volume, params.pitch, iFlags, soundtime ); -#else - engine->EmitAmbientSound(entindex, origin, params.soundname, params.volume, params.soundlevel, iFlags, params.pitch, soundtime ); -#endif - - bool needsCC = !( iFlags & ( SND_STOP | SND_CHANGE_VOL | SND_CHANGE_PITCH ) ); - - float soundduration = 0.0f; - - if ( duration || needsCC ) - { - soundduration = enginesound->GetSoundDuration( params.soundname ); - if ( duration ) - { - *duration = soundduration; - } - } - - TraceEmitSound( "EmitAmbientSound: '%s' emitted as '%s' (ent %i)\n", - soundname, params.soundname, entindex ); - - // We only want to trigger the CC on the start of the sound, not on any changes or halting of the sound - if ( needsCC ) - { - CRecipientFilter filter; - filter.AddAllPlayers(); - filter.MakeReliable(); - - CUtlVector< Vector > dummy; - EmitCloseCaption( filter, entindex, false, soundname, dummy, soundduration, false ); - } - - } - - void StopSoundByHandle( int entindex, const char *soundname, HSOUNDSCRIPTHANDLE& handle ) - { - if ( handle == SOUNDEMITTER_INVALID_HANDLE ) - { - handle = (HSOUNDSCRIPTHANDLE)soundemitterbase->GetSoundIndex( soundname ); - } - - if ( handle == SOUNDEMITTER_INVALID_HANDLE ) - return; - - CSoundParametersInternal *params; - - params = soundemitterbase->InternalGetParametersForSound( (int)handle ); - if ( !params ) - { - return; - } - - // HACK: we have to stop all sounds if there are > 1 in the rndwave section... - int c = params->NumSoundNames(); - for ( int i = 0; i < c; ++i ) - { - char const *wavename = soundemitterbase->GetWaveName( params->GetSoundNames()[ i ].symbol ); - Assert( wavename ); - - enginesound->StopSound( - entindex, - params->GetChannel(), - wavename ); - - TraceEmitSound( "StopSound: '%s' stopped as '%s' (ent %i)\n", - soundname, wavename, entindex ); - } - } - - void StopSound( int entindex, const char *soundname ) - { - HSOUNDSCRIPTHANDLE handle = (HSOUNDSCRIPTHANDLE)soundemitterbase->GetSoundIndex( soundname ); - if ( handle == SOUNDEMITTER_INVALID_HANDLE ) - { - return; - } - - StopSoundByHandle( entindex, soundname, handle ); - } - - - void StopSound( int iEntIndex, int iChannel, const char *pSample ) - { - if ( pSample && ( Q_stristr( pSample, ".wav" ) || Q_stristr( pSample, ".mp3" ) || pSample[0] == '!' ) ) - { - enginesound->StopSound( iEntIndex, iChannel, pSample ); - - TraceEmitSound( "StopSound: Raw wave stopped '%s' (ent %i)\n", - pSample, iEntIndex ); - } - else - { - // Look it up in sounds.txt and ignore other parameters - StopSound( iEntIndex, pSample ); - } - } - - void EmitAmbientSound( int entindex, const Vector &origin, const char *pSample, float volume, soundlevel_t soundlevel, int flags, int pitch, float soundtime /*= 0.0f*/, float *duration /*=NULL*/ ) - { -#if !defined( CLIENT_DLL ) - CUtlVector< Vector > dummyorigins; - - // Loop through all registered microphones and tell them the sound was just played - // NOTE: This means that pitch shifts/sound changes on the original ambient will not be reflected in the re-broadcasted sound - bool bSwallowed = CEnvMicrophone::OnSoundPlayed( - entindex, - pSample, - soundlevel, - volume, - flags, - pitch, - &origin, - soundtime, - dummyorigins ); - if ( bSwallowed ) - return; -#endif - - if ( pSample && ( Q_stristr( pSample, ".wav" ) || Q_stristr( pSample, ".mp3" )) ) - { -#if defined( CLIENT_DLL ) - enginesound->EmitAmbientSound( pSample, volume, pitch, flags, soundtime ); -#else - engine->EmitAmbientSound( entindex, origin, pSample, volume, soundlevel, flags, pitch, soundtime ); -#endif - - if ( duration ) - { - *duration = enginesound->GetSoundDuration( pSample ); - } - - TraceEmitSound( "EmitAmbientSound: Raw wave emitted '%s' (ent %i)\n", - pSample, entindex ); - } - else - { - EmitAmbientSound( entindex, origin, pSample, volume, flags, pitch, soundtime, duration ); - } - } -}; - -static CSoundEmitterSystem g_SoundEmitterSystem( "CSoundEmitterSystem" ); - -IGameSystem *SoundEmitterSystem() -{ - return &g_SoundEmitterSystem; -} - -#if defined( CLIENT_DLL ) -CON_COMMAND_F( cl_soundemitter_flush, "Flushes the sounds.txt system (client only)", FCVAR_CHEAT ) -#else -CON_COMMAND( sv_soundemitter_flush, "Flushes the sounds.txt system (server only)" ) -#endif -{ - // save the current soundscape - // kill the system - g_SoundEmitterSystem.Shutdown(); - - // restart the system - g_SoundEmitterSystem.Init(); - -#if !defined( CLIENT_DLL ) - // Redo precache all wave files... (this should work now that we have dynamic string tables) - g_SoundEmitterSystem.LevelInitPreEntity(); - - // These store raw sound indices for faster precaching, blow them away. - ClearModelSoundsCache(); -#endif - - // TODO: when we go to a handle system, we'll need to invalidate handles somehow -} - -#if !defined(_RETAIL) - -#if !defined( CLIENT_DLL ) - -#if !defined( _XBOX ) - -CON_COMMAND( sv_soundemitter_filecheck, "Report missing wave files for sounds and game_sounds files." ) -{ - int missing = soundemitterbase->CheckForMissingWavFiles( true ); - DevMsg( "---------------------------\nTotal missing files %i\n", missing ); -} - -CON_COMMAND( sv_findsoundname, "Find sound names which reference the specified wave files." ) -{ - if ( args.ArgC() != 2 ) - return; - - int c = soundemitterbase->GetSoundCount(); - int i; - - char const *search = args[ 1 ]; - if ( !search ) - return; - - for ( i = 0; i < c; i++ ) - { - CSoundParametersInternal *internal = soundemitterbase->InternalGetParametersForSound( i ); - if ( !internal ) - continue; - - int waveCount = internal->NumSoundNames(); - if ( waveCount > 0 ) - { - for( int wave = 0; wave < waveCount; wave++ ) - { - char const *wavefilename = soundemitterbase->GetWaveName( internal->GetSoundNames()[ wave ].symbol ); - - if ( Q_stristr( wavefilename, search ) ) - { - char const *soundname = soundemitterbase->GetSoundName( i ); - char const *scriptname = soundemitterbase->GetSourceFileForSound( i ); - - Msg( "Referenced by '%s:%s' -- %s\n", scriptname, soundname, wavefilename ); - } - } - } - } -} -#endif // !_XBOX - -#else -void Playgamesound_f( const CCommand &args ) -{ - CBasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); - if ( pPlayer ) - { - if ( args.ArgC() > 2 ) - { - Vector position = pPlayer->EyePosition(); - Vector forward; - pPlayer->GetVectors( &forward, NULL, NULL ); - position += atof( args[2] ) * forward; - CPASAttenuationFilter filter( pPlayer ); - EmitSound_t params; - params.m_pSoundName = args[1]; - params.m_pOrigin = &position; - params.m_flVolume = 0.0f; - params.m_nPitch = 0; - g_SoundEmitterSystem.EmitSound( filter, 0, params ); - } - else - { - pPlayer->EmitSound( args[1] ); - } - } - else - { - Msg("Can't play until a game is started.\n"); - // UNDONE: Make something like this work? - //CBroadcastRecipientFilter filter; - //g_SoundEmitterSystem.EmitSound( filter, 1, args[1], 0.0, 0, 0, &vec3_origin, 0, NULL ); - } -} - -static int GamesoundCompletion( const char *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] ) -{ - int current = 0; - - const char *cmdname = "playgamesound"; - char *substring = NULL; - int substringLen = 0; - if ( Q_strstr( partial, cmdname ) && strlen(partial) > strlen(cmdname) + 1 ) - { - substring = (char *)partial + strlen( cmdname ) + 1; - substringLen = strlen(substring); - } - - for ( int i = soundemitterbase->GetSoundCount()-1; i >= 0 && current < COMMAND_COMPLETION_MAXITEMS; i-- ) - { - const char *pSoundName = soundemitterbase->GetSoundName( i ); - if ( pSoundName ) - { - if ( !substring || !Q_strncasecmp( pSoundName, substring, substringLen ) ) - { - Q_snprintf( commands[ current ], sizeof( commands[ current ] ), "%s %s", cmdname, pSoundName ); - current++; - } - } - } - - return current; -} - -static ConCommand Command_Playgamesound( "playgamesound", Playgamesound_f, "Play a sound from the game sounds txt file", FCVAR_CLIENTCMD_CAN_EXECUTE | FCVAR_SERVER_CAN_EXECUTE, GamesoundCompletion ); -#endif - -#endif - -//----------------------------------------------------------------------------- -// Purpose: Non-static override for doing the general case of CPASAttenuationFilter( this ), and EmitSound( filter, entindex(), etc. ); -// Input : *soundname - -//----------------------------------------------------------------------------- -void CBaseEntity::EmitSound( const char *soundname, float soundtime /*= 0.0f*/, float *duration /*=NULL*/ ) -{ - //VPROF( "CBaseEntity::EmitSound" ); - VPROF_BUDGET( "CBaseEntity::EmitSound", _T( "CBaseEntity::EmitSound" ) ); - - CPASAttenuationFilter filter( this, soundname ); - - EmitSound_t params; - params.m_pSoundName = soundname; - params.m_flSoundTime = soundtime; - params.m_pflSoundDuration = duration; - params.m_bWarnOnDirectWaveReference = true; - - EmitSound( filter, entindex(), params ); -} - -//----------------------------------------------------------------------------- -// Purpose: Non-static override for doing the general case of CPASAttenuationFilter( this ), and EmitSound( filter, entindex(), etc. ); -// Input : *soundname - -//----------------------------------------------------------------------------- -void CBaseEntity::EmitSound( const char *soundname, HSOUNDSCRIPTHANDLE& handle, float soundtime /*= 0.0f*/, float *duration /*=NULL*/ ) -{ - VPROF_BUDGET( "CBaseEntity::EmitSound", _T( "CBaseEntity::EmitSound" ) ); - - // VPROF( "CBaseEntity::EmitSound" ); - CPASAttenuationFilter filter( this, soundname, handle ); - - EmitSound_t params; - params.m_pSoundName = soundname; - params.m_flSoundTime = soundtime; - params.m_pflSoundDuration = duration; - params.m_bWarnOnDirectWaveReference = true; - - EmitSound( filter, entindex(), params, handle ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : filter - -// iEntIndex - -// *soundname - -// *pOrigin - -//----------------------------------------------------------------------------- -void CBaseEntity::EmitSound( IRecipientFilter& filter, int iEntIndex, const char *soundname, const Vector *pOrigin /*= NULL*/, float soundtime /*= 0.0f*/, float *duration /*=NULL*/ ) -{ - VPROF_BUDGET( "CBaseEntity::EmitSound", _T( "CBaseEntity::EmitSound" ) ); - - // VPROF( "CBaseEntity::EmitSound" ); - EmitSound_t params; - params.m_pSoundName = soundname; - params.m_flSoundTime = soundtime; - params.m_pOrigin = pOrigin; - params.m_pflSoundDuration = duration; - params.m_bWarnOnDirectWaveReference = true; - - EmitSound( filter, iEntIndex, params, params.m_hSoundScriptHandle ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : filter - -// iEntIndex - -// *soundname - -// *pOrigin - -//----------------------------------------------------------------------------- -void CBaseEntity::EmitSound( IRecipientFilter& filter, int iEntIndex, const char *soundname, HSOUNDSCRIPTHANDLE& handle, const Vector *pOrigin /*= NULL*/, float soundtime /*= 0.0f*/, float *duration /*=NULL*/ ) -{ - VPROF_BUDGET( "CBaseEntity::EmitSound", _T( "CBaseEntity::EmitSound" ) ); - - //VPROF( "CBaseEntity::EmitSound" ); - EmitSound_t params; - params.m_pSoundName = soundname; - params.m_flSoundTime = soundtime; - params.m_pOrigin = pOrigin; - params.m_pflSoundDuration = duration; - params.m_bWarnOnDirectWaveReference = true; - - EmitSound( filter, iEntIndex, params, handle ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : filter - -// iEntIndex - -// params - -//----------------------------------------------------------------------------- -void CBaseEntity::EmitSound( IRecipientFilter& filter, int iEntIndex, const EmitSound_t & params ) -{ - VPROF_BUDGET( "CBaseEntity::EmitSound", _T( "CBaseEntity::EmitSound" ) ); - - // VPROF( "CBaseEntity::EmitSound" ); - // Call into the sound emitter system... - g_SoundEmitterSystem.EmitSound( filter, iEntIndex, params ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : filter - -// iEntIndex - -// params - -//----------------------------------------------------------------------------- -void CBaseEntity::EmitSound( IRecipientFilter& filter, int iEntIndex, const EmitSound_t & params, HSOUNDSCRIPTHANDLE& handle ) -{ - VPROF_BUDGET( "CBaseEntity::EmitSound", _T( "CBaseEntity::EmitSound" ) ); - - // VPROF( "CBaseEntity::EmitSound" ); - // Call into the sound emitter system... - g_SoundEmitterSystem.EmitSoundByHandle( filter, iEntIndex, params, handle ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *soundname - -//----------------------------------------------------------------------------- -void CBaseEntity::StopSound( const char *soundname ) -{ -#if defined( CLIENT_DLL ) - if ( entindex() == -1 ) - { - // If we're a clientside entity, we need to use the soundsourceindex instead of the entindex - StopSound( GetSoundSourceIndex(), soundname ); - return; - } -#endif - - StopSound( entindex(), soundname ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *soundname - -//----------------------------------------------------------------------------- -void CBaseEntity::StopSound( const char *soundname, HSOUNDSCRIPTHANDLE& handle ) -{ -#if defined( CLIENT_DLL ) - if ( entindex() == -1 ) - { - // If we're a clientside entity, we need to use the soundsourceindex instead of the entindex - StopSound( GetSoundSourceIndex(), soundname ); - return; - } -#endif - - g_SoundEmitterSystem.StopSoundByHandle( entindex(), soundname, handle ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iEntIndex - -// *soundname - -//----------------------------------------------------------------------------- -void CBaseEntity::StopSound( int iEntIndex, const char *soundname ) -{ - g_SoundEmitterSystem.StopSound( iEntIndex, soundname ); -} - -void CBaseEntity::StopSound( int iEntIndex, int iChannel, const char *pSample ) -{ - g_SoundEmitterSystem.StopSound( iEntIndex, iChannel, pSample ); -} - -soundlevel_t CBaseEntity::LookupSoundLevel( const char *soundname ) -{ - return soundemitterbase->LookupSoundLevel( soundname ); -} - - -soundlevel_t CBaseEntity::LookupSoundLevel( const char *soundname, HSOUNDSCRIPTHANDLE& handle ) -{ - return soundemitterbase->LookupSoundLevelByHandle( soundname, handle ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *entity - -// origin - -// flags - -// *soundname - -//----------------------------------------------------------------------------- -void CBaseEntity::EmitAmbientSound( int entindex, const Vector& origin, const char *soundname, int flags, float soundtime /*= 0.0f*/, float *duration /*=NULL*/ ) -{ - g_SoundEmitterSystem.EmitAmbientSound( entindex, origin, soundname, 0.0, flags, 0, soundtime, duration ); -} - -// HACK HACK: Do we need to pull the entire SENTENCEG_* wrapper over to the client .dll? -#if defined( CLIENT_DLL ) -int SENTENCEG_Lookup(const char *sample) -{ - return engine->SentenceIndexFromName( sample + 1 ); -} -#endif - -void UTIL_EmitAmbientSound( int entindex, const Vector &vecOrigin, const char *samp, float vol, soundlevel_t soundlevel, int fFlags, int pitch, float soundtime /*= 0.0f*/, float *duration /*=NULL*/ ) -{ - if (samp && *samp == '!') - { - int sentenceIndex = SENTENCEG_Lookup(samp); - if (sentenceIndex >= 0) - { - char name[32]; - Q_snprintf( name, sizeof(name), "!%d", sentenceIndex ); -#if !defined( CLIENT_DLL ) - engine->EmitAmbientSound( entindex, vecOrigin, name, vol, soundlevel, fFlags, pitch, soundtime ); -#else - enginesound->EmitAmbientSound( name, vol, pitch, fFlags, soundtime ); -#endif - if ( duration ) - { - *duration = enginesound->GetSoundDuration( name ); - } - - g_SoundEmitterSystem.TraceEmitSound( "UTIL_EmitAmbientSound: Sentence emitted '%s' (ent %i)\n", - name, entindex ); - } - } - else - { - g_SoundEmitterSystem.EmitAmbientSound( entindex, vecOrigin, samp, vol, soundlevel, fFlags, pitch, soundtime, duration ); - } -} - -static const char *UTIL_TranslateSoundName( const char *soundname, const char *actormodel ) -{ - Assert( soundname ); - - if ( Q_stristr( soundname, ".wav" ) || Q_stristr( soundname, ".mp3" ) ) - { - if ( Q_stristr( soundname, ".wav" ) ) - { - WaveTrace( soundname, "UTIL_TranslateSoundName" ); - } - return soundname; - } - - return soundemitterbase->GetWavFileForSound( soundname, actormodel ); -} - -void CBaseEntity::GenderExpandString( char const *in, char *out, int maxlen ) -{ - soundemitterbase->GenderExpandString( STRING( GetModelName() ), in, out, maxlen ); -} - -bool CBaseEntity::GetParametersForSound( const char *soundname, CSoundParameters ¶ms, const char *actormodel ) -{ - gender_t gender = soundemitterbase->GetActorGender( actormodel ); - - return soundemitterbase->GetParametersForSound( soundname, params, gender ); -} - -bool CBaseEntity::GetParametersForSound( const char *soundname, HSOUNDSCRIPTHANDLE& handle, CSoundParameters ¶ms, const char *actormodel ) -{ - gender_t gender = soundemitterbase->GetActorGender( actormodel ); - - return soundemitterbase->GetParametersForSoundEx( soundname, handle, params, gender ); -} - -HSOUNDSCRIPTHANDLE CBaseEntity::PrecacheScriptSound( const char *soundname ) -{ -#if !defined( CLIENT_DLL ) - return g_SoundEmitterSystem.PrecacheScriptSound( soundname ); -#else - return soundemitterbase->GetSoundIndex( soundname ); -#endif -} - -void CBaseEntity::PrefetchScriptSound( const char *soundname ) -{ - g_SoundEmitterSystem.PrefetchScriptSound( soundname ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *soundname - -// Output : float -//----------------------------------------------------------------------------- -float CBaseEntity::GetSoundDuration( const char *soundname, char const *actormodel ) -{ - return enginesound->GetSoundDuration( PSkipSoundChars( UTIL_TranslateSoundName( soundname, actormodel ) ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : filter - -// *token - -// duration - -// warnifmissing - -//----------------------------------------------------------------------------- -void CBaseEntity::EmitCloseCaption( IRecipientFilter& filter, int entindex, char const *token, CUtlVector< Vector >& soundorigin, float duration, bool warnifmissing /*= false*/ ) -{ - bool fromplayer = false; - CBaseEntity *ent = CBaseEntity::Instance( entindex ); - while ( ent ) - { - if ( ent->IsPlayer() ) - { - fromplayer = true; - break; - } - ent = ent->GetOwnerEntity(); - } - - g_SoundEmitterSystem.EmitCloseCaption( filter, entindex, fromplayer, token, soundorigin, duration, warnifmissing ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -// preload - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseEntity::PrecacheSound( const char *name ) -{ - if ( IsPC() && !g_bPermitDirectSoundPrecache ) - { - Warning( "Direct precache of %s\n", name ); - } - - // If this is out of order, warn - if ( !CBaseEntity::IsPrecacheAllowed() ) - { - if ( !enginesound->IsSoundPrecached( name ) ) - { - Assert( !"CBaseEntity::PrecacheSound: too late" ); - - Warning( "Late precache of %s\n", name ); - } - } - - bool bret = enginesound->PrecacheSound( name, true ); - return bret; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -void CBaseEntity::PrefetchSound( const char *name ) -{ - enginesound->PrefetchSound( name ); -} - diff --git a/game/shared/Sprite.cpp b/game/shared/Sprite.cpp deleted file mode 100644 index 3bc42f20f..000000000 --- a/game/shared/Sprite.cpp +++ /dev/null @@ -1,870 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements visual effects entities: sprites, beams, bubbles, etc. -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "Sprite.h" -#include "model_types.h" -#include "engine/ivmodelinfo.h" -#include "tier0/vprof.h" -#include "engine/ivdebugoverlay.h" - -#if defined( CLIENT_DLL ) - #include "enginesprite.h" - #include "iclientmode.h" - #include "c_baseviewmodel.h" -# ifdef PORTAL - #include "c_prop_portal.h" -# endif //ifdef PORTAL -#else - #include "baseviewmodel.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -const float MAX_SPRITE_SCALE = 64.0f; -const float MAX_GLOW_PROXY_SIZE = 64.0f; - -LINK_ENTITY_TO_CLASS( env_sprite, CSprite ); -LINK_ENTITY_TO_CLASS( env_sprite_oriented, CSpriteOriented ); -#if !defined( CLIENT_DLL ) -LINK_ENTITY_TO_CLASS( env_glow, CSprite ); // For backwards compatibility, remove when no longer needed. -#endif - -#if !defined( CLIENT_DLL ) -BEGIN_DATADESC( CSprite ) - - DEFINE_FIELD( m_flLastTime, FIELD_TIME ), - DEFINE_FIELD( m_flMaxFrame, FIELD_FLOAT ), - DEFINE_FIELD( m_hAttachedToEntity, FIELD_EHANDLE ), - DEFINE_FIELD( m_nAttachment, FIELD_INTEGER ), - DEFINE_FIELD( m_flDieTime, FIELD_TIME ), - - DEFINE_FIELD( m_nBrightness, FIELD_INTEGER ), - DEFINE_FIELD( m_flBrightnessTime, FIELD_FLOAT ), - - DEFINE_KEYFIELD( m_flSpriteScale, FIELD_FLOAT, "scale" ), - DEFINE_KEYFIELD( m_flSpriteFramerate, FIELD_FLOAT, "framerate" ), - DEFINE_KEYFIELD( m_flFrame, FIELD_FLOAT, "frame" ), -#ifdef PORTAL - DEFINE_FIELD( m_bDrawInMainRender, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bDrawInPortalRender, FIELD_BOOLEAN ), -#endif - DEFINE_KEYFIELD( m_flHDRColorScale, FIELD_FLOAT, "HDRColorScale" ), - - DEFINE_KEYFIELD( m_flGlowProxySize, FIELD_FLOAT, "GlowProxySize" ), - - DEFINE_FIELD( m_flScaleTime, FIELD_FLOAT ), - DEFINE_FIELD( m_flStartScale, FIELD_FLOAT ), - DEFINE_FIELD( m_flDestScale, FIELD_FLOAT ), - DEFINE_FIELD( m_flScaleTimeStart, FIELD_TIME ), - DEFINE_FIELD( m_nStartBrightness, FIELD_INTEGER ), - DEFINE_FIELD( m_nDestBrightness, FIELD_INTEGER ), - DEFINE_FIELD( m_flBrightnessTimeStart, FIELD_TIME ), - DEFINE_FIELD( m_bWorldSpaceScale, FIELD_BOOLEAN ), - - // Function Pointers - DEFINE_FUNCTION( AnimateThink ), - DEFINE_FUNCTION( ExpandThink ), - DEFINE_FUNCTION( AnimateUntilDead ), - DEFINE_FUNCTION( BeginFadeOutThink ), - - // Inputs - DEFINE_INPUT( m_flSpriteScale, FIELD_FLOAT, "SetScale" ), - DEFINE_INPUTFUNC( FIELD_VOID, "HideSprite", InputHideSprite ), - DEFINE_INPUTFUNC( FIELD_VOID, "ShowSprite", InputShowSprite ), - DEFINE_INPUTFUNC( FIELD_VOID, "ToggleSprite", InputToggleSprite ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "ColorRedValue", InputColorRedValue ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "ColorGreenValue", InputColorGreenValue ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "ColorBlueValue", InputColorBlueValue ), - -END_DATADESC() - -#else - -BEGIN_PREDICTION_DATA( CSprite ) - - // Networked - DEFINE_PRED_FIELD( m_hAttachedToEntity, FIELD_EHANDLE, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_nAttachment, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_flScaleTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_flSpriteScale, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_flSpriteFramerate, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_flFrame, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), -#ifdef PORTAL - DEFINE_PRED_FIELD( m_bDrawInMainRender, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_bDrawInPortalRender, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), -#endif - DEFINE_PRED_FIELD( m_flBrightnessTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_nBrightness, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), - - DEFINE_FIELD( m_flLastTime, FIELD_FLOAT ), - DEFINE_FIELD( m_flMaxFrame, FIELD_FLOAT ), - DEFINE_FIELD( m_flDieTime, FIELD_FLOAT ), - -// DEFINE_FIELD( m_flHDRColorScale, FIELD_FLOAT ), -// DEFINE_FIELD( m_flStartScale, FIELD_FLOAT ), //Starting scale -// DEFINE_FIELD( m_flDestScale, FIELD_FLOAT ), //Destination scale -// DEFINE_FIELD( m_flScaleTimeStart, FIELD_FLOAT ), //Real time for start of scale -// DEFINE_FIELD( m_nStartBrightness, FIELD_INTEGER ), //Starting brightness -// DEFINE_FIELD( m_nDestBrightness, FIELD_INTEGER ), //Destination brightness -// DEFINE_FIELD( m_flBrightnessTimeStart, FIELD_FLOAT ), //Real time for brightness - -END_PREDICTION_DATA() - -#endif - -IMPLEMENT_NETWORKCLASS_ALIASED( Sprite, DT_Sprite ); - -#if defined( CLIENT_DLL ) - -static void RecvProxy_SpriteScale( const CRecvProxyData *pData, void *pStruct, void *pOut ) -{ - ((CSprite*)pStruct)->SetSpriteScale( pData->m_Value.m_Float ); -} - -#endif - -BEGIN_NETWORK_TABLE( CSprite, DT_Sprite ) -#if !defined( CLIENT_DLL ) - SendPropEHandle( SENDINFO(m_hAttachedToEntity )), - SendPropInt( SENDINFO(m_nAttachment ), 8 ), - SendPropFloat( SENDINFO(m_flScaleTime ), 0, SPROP_NOSCALE ), - -#ifdef HL2_DLL - SendPropFloat( SENDINFO(m_flSpriteScale ), 0, SPROP_NOSCALE), -#else - SendPropFloat( SENDINFO(m_flSpriteScale ), 8, SPROP_ROUNDUP, 0.0f, MAX_SPRITE_SCALE), -#endif - SendPropFloat( SENDINFO(m_flGlowProxySize ), 6, SPROP_ROUNDUP, 0.0f, MAX_GLOW_PROXY_SIZE), - - SendPropFloat( SENDINFO(m_flHDRColorScale ), 0, SPROP_NOSCALE, 0.0f, 100.0f), - - SendPropFloat( SENDINFO(m_flSpriteFramerate ), 8, SPROP_ROUNDUP, 0, 60.0f), - SendPropFloat( SENDINFO(m_flFrame), 20, SPROP_ROUNDDOWN, 0.0f, 256.0f), -#ifdef PORTAL - SendPropBool( SENDINFO(m_bDrawInMainRender) ), - SendPropBool( SENDINFO(m_bDrawInPortalRender) ), -#endif //#ifdef PORTAL - SendPropFloat( SENDINFO(m_flBrightnessTime ), 0, SPROP_NOSCALE ), - SendPropInt( SENDINFO(m_nBrightness), 8, SPROP_UNSIGNED ), - SendPropBool( SENDINFO(m_bWorldSpaceScale) ), -#else - RecvPropEHandle(RECVINFO(m_hAttachedToEntity)), - RecvPropInt(RECVINFO(m_nAttachment)), - RecvPropFloat(RECVINFO(m_flScaleTime)), - RecvPropFloat(RECVINFO(m_flSpriteScale), 0, RecvProxy_SpriteScale), - RecvPropFloat(RECVINFO(m_flSpriteFramerate)), - RecvPropFloat(RECVINFO(m_flGlowProxySize)), - - RecvPropFloat( RECVINFO(m_flHDRColorScale )), - - RecvPropFloat(RECVINFO(m_flFrame)), -#ifdef PORTAL - RecvPropBool( RECVINFO(m_bDrawInMainRender) ), - RecvPropBool( RECVINFO(m_bDrawInPortalRender) ), -#endif //#ifdef PORTAL - RecvPropFloat(RECVINFO(m_flBrightnessTime)), - RecvPropInt(RECVINFO(m_nBrightness)), - RecvPropBool( RECVINFO(m_bWorldSpaceScale) ), -#endif -END_NETWORK_TABLE() - - -CSprite::CSprite() -{ - m_flGlowProxySize = 2.0f; - m_flHDRColorScale = 1.0f; - -#ifdef PORTAL - m_bDrawInMainRender = true; - m_bDrawInPortalRender = true; -#endif -} -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSprite::Spawn( void ) -{ - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NONE ); - m_flFrame = 0; - - Precache(); - SetModel( STRING( GetModelName() ) ); - CollisionProp()->SetSurroundingBoundsType( USE_GAME_CODE ); - - m_flMaxFrame = (float)modelinfo->GetModelFrameCount( GetModel() ) - 1; - AddEffects( EF_NOSHADOW | EF_NORECEIVESHADOW ); - -#if defined( CLIENT_DLL ) - SetNextClientThink( CLIENT_THINK_ALWAYS ); -#endif - -#if !defined( CLIENT_DLL ) - if ( GetEntityName() != NULL_STRING && !(m_spawnflags & SF_SPRITE_STARTON) ) - { - TurnOff(); - } - else -#endif - { - TurnOn(); - } - - // Worldcraft only sets y rotation, copy to Z - if ( GetLocalAngles().y != 0 && GetLocalAngles().z == 0 ) - { - QAngle angles = GetLocalAngles(); - - angles.z = angles.y; - angles.y = 0; - - SetLocalAngles( angles ); - } - - // Clamp our scale if necessary - float scale = m_flSpriteScale; - - if ( scale < 0 || scale > MAX_SPRITE_SCALE ) - { -#if !defined( CLIENT_DLL ) -#ifndef _LINUX - DevMsg( "LEVEL DESIGN ERROR: Sprite %s with bad scale %f [0..%f]\n", GetDebugName(), m_flSpriteScale, MAX_SPRITE_SCALE ); -#endif -#endif - scale = clamp( m_flSpriteScale, 0, MAX_SPRITE_SCALE ); - } - - //Set our state - SetBrightness( m_clrRender->a ); - SetScale( scale ); - -#if defined( CLIENT_DLL ) - m_flStartScale = m_flDestScale = m_flSpriteScale; - m_nStartBrightness = m_nDestBrightness = m_nBrightness; -#endif - -} - - -//----------------------------------------------------------------------------- -// Purpose: Initialize absmin & absmax to the appropriate box -//----------------------------------------------------------------------------- -void CSprite::EnableWorldSpaceScale( bool bEnable ) -{ - m_bWorldSpaceScale = bEnable; -} - -//----------------------------------------------------------------------------- -// Purpose: Initialize absmin & absmax to the appropriate box -//----------------------------------------------------------------------------- -void CSprite::ComputeWorldSpaceSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs ) -{ - float flScale = m_flSpriteScale * 0.5f; - - if ( m_bWorldSpaceScale == false ) - { - // Find the height and width of the source of the sprite - float width = modelinfo->GetModelSpriteWidth( GetModel() ); - float height = modelinfo->GetModelSpriteHeight( GetModel() ); - flScale *= MAX( width, height ); - } - - pVecWorldMins->Init( -flScale, -flScale, -flScale ); - pVecWorldMaxs->Init( flScale, flScale, flScale ); - *pVecWorldMins += GetAbsOrigin(); - *pVecWorldMaxs += GetAbsOrigin(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *szModelName - -//----------------------------------------------------------------------------- -void CSprite::SetModel( const char *szModelName ) -{ - int index = modelinfo->GetModelIndex( szModelName ); - const model_t *model = modelinfo->GetModel( index ); - if ( model && modelinfo->GetModelType( model ) != mod_sprite ) - { - Msg( "Setting CSprite to non-sprite model %s\n", szModelName?szModelName:"NULL" ); - } - -#if !defined( CLIENT_DLL ) - UTIL_SetModel( this, szModelName ); -#else - BaseClass::SetModel( szModelName ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSprite::Precache( void ) -{ - if ( GetModelName() != NULL_STRING ) - { - PrecacheModel( STRING( GetModelName() ) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pSpriteName - -// &origin - -//----------------------------------------------------------------------------- -void CSprite::SpriteInit( const char *pSpriteName, const Vector &origin ) -{ - SetModelName( MAKE_STRING(pSpriteName) ); - SetLocalOrigin( origin ); - Spawn(); -} - -#if !defined( CLIENT_DLL ) - -int CSprite::UpdateTransmitState( void ) -{ - if ( GetMoveParent() ) - { - // we must call ShouldTransmit() if we have a move parent - return SetTransmitState( FL_EDICT_FULLCHECK ); - } - else - { - return SetTransmitState( FL_EDICT_ALWAYS ); - } -} - -int CSprite::ShouldTransmit( const CCheckTransmitInfo *pInfo ) -{ - // Certain entities like sprites and ropes are strewn throughout the level and they rarely change. - // For these entities, it's more efficient to transmit them once and then always leave them on - // the client. Otherwise, the server will have to send big bursts of data with the entity states - // as they come in and out of the PVS. - - if ( GetMoveParent() ) - { - CBaseViewModel *pViewModel = dynamic_cast( GetMoveParent() ); - - if ( pViewModel ) - { - return pViewModel->ShouldTransmit( pInfo ); - } - } - - return FL_EDICT_ALWAYS; -} - -//----------------------------------------------------------------------------- -// Purpose: Fixup parent after restore -//----------------------------------------------------------------------------- -void CSprite::OnRestore() -{ - BaseClass::OnRestore(); - - // Reset attachment after save/restore - if ( GetFollowedEntity() ) - { - SetAttachment( GetFollowedEntity(), m_nAttachment ); - } - else - { - // Clear attachment - m_hAttachedToEntity = NULL; - m_nAttachment = 0; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pSpriteName - -// &origin - -// animate - -// Output : CSprite -//----------------------------------------------------------------------------- -CSprite *CSprite::SpriteCreate( const char *pSpriteName, const Vector &origin, bool animate ) -{ - CSprite *pSprite = CREATE_ENTITY( CSprite, "env_sprite" ); - pSprite->SpriteInit( pSpriteName, origin ); - pSprite->SetSolid( SOLID_NONE ); - UTIL_SetSize( pSprite, vec3_origin, vec3_origin ); - pSprite->SetMoveType( MOVETYPE_NONE ); - if ( animate ) - pSprite->TurnOn(); - - return pSprite; -} -#endif - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pSpriteName - -// &origin - -// animate - -// Output : CSprite -//----------------------------------------------------------------------------- -CSprite *CSprite::SpriteCreatePredictable( const char *module, int line, const char *pSpriteName, const Vector &origin, bool animate ) -{ - CSprite *pSprite = ( CSprite * )CBaseEntity::CreatePredictedEntityByName( "env_sprite", module, line ); - if ( pSprite ) - { - pSprite->SpriteInit( pSpriteName, origin ); - pSprite->SetSolid( SOLID_NONE ); - pSprite->SetSize( vec3_origin, vec3_origin ); - pSprite->SetMoveType( MOVETYPE_NONE ); - if ( animate ) - pSprite->TurnOn(); - } - - return pSprite; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSprite::AnimateThink( void ) -{ - Animate( m_flSpriteFramerate * (gpGlobals->curtime - m_flLastTime) ); - - SetNextThink( gpGlobals->curtime ); - m_flLastTime = gpGlobals->curtime; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSprite::AnimateUntilDead( void ) -{ - if ( gpGlobals->curtime > m_flDieTime ) - { - Remove( ); - } - else - { - AnimateThink(); - SetNextThink( gpGlobals->curtime ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : scaleSpeed - -// fadeSpeed - -//----------------------------------------------------------------------------- -void CSprite::Expand( float scaleSpeed, float fadeSpeed ) -{ - m_flSpeed = scaleSpeed; - m_iHealth = fadeSpeed; - SetThink( &CSprite::ExpandThink ); - - SetNextThink( gpGlobals->curtime ); - m_flLastTime = gpGlobals->curtime; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSprite::ExpandThink( void ) -{ - float frametime = gpGlobals->curtime - m_flLastTime; - SetSpriteScale( m_flSpriteScale + m_flSpeed * frametime ); - - int sub = (int)(m_iHealth * frametime); - if ( sub > m_clrRender->a ) - { - SetRenderColorA( 0 ); - Remove( ); - } - else - { - SetRenderColorA( m_clrRender->a - sub ); - SetNextThink( gpGlobals->curtime ); - m_flLastTime = gpGlobals->curtime; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : frames - -//----------------------------------------------------------------------------- -void CSprite::Animate( float frames ) -{ - m_flFrame += frames; - if ( m_flFrame > m_flMaxFrame ) - { -#if !defined( CLIENT_DLL ) - if ( m_spawnflags & SF_SPRITE_ONCE ) - { - TurnOff(); - } - else -#endif - { - if ( m_flMaxFrame > 0 ) - m_flFrame = fmod( m_flFrame, m_flMaxFrame ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSprite::SetBrightness( int brightness, float time ) -{ - m_nBrightness = brightness; //Take our current position as our starting position - m_flBrightnessTime = time; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSprite::SetSpriteScale( float scale ) -{ - if ( scale != m_flSpriteScale ) - { - m_flSpriteScale = scale; //Take our current position as our new starting position - // The surrounding box is based on sprite scale... it changes, box is dirty - CollisionProp()->MarkSurroundingBoundsDirty(); - } -} - -void CSprite::SetScale( float scale, float time ) -{ - m_flScaleTime = time; - SetSpriteScale( scale ); - // The surrounding box is based on sprite scale... it changes, box is dirty -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSprite::TurnOff( void ) -{ - AddEffects( EF_NODRAW ); - SetNextThink( TICK_NEVER_THINK ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSprite::TurnOn( void ) -{ - RemoveEffects( EF_NODRAW ); - if ( (m_flSpriteFramerate && m_flMaxFrame > 1.0) -#if !defined( CLIENT_DLL ) - || (m_spawnflags & SF_SPRITE_ONCE) -#endif - ) - { - SetThink( &CSprite::AnimateThink ); - SetNextThink( gpGlobals->curtime ); - m_flLastTime = gpGlobals->curtime; - } - m_flFrame = 0; -} - -#if !defined( CLIENT_DLL ) -// DVS TODO: Obsolete Use handler -void CSprite::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - int on = !IsEffectActive( EF_NODRAW ); - if ( ShouldToggle( useType, on ) ) - { - if ( on ) - { - TurnOff(); - } - else - { - TurnOn(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler that hides the sprite. -//----------------------------------------------------------------------------- -void CSprite::InputHideSprite( inputdata_t &inputdata ) -{ - TurnOff(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Input handler that hides the sprite. -//----------------------------------------------------------------------------- -void CSprite::InputShowSprite( inputdata_t &inputdata ) -{ - TurnOn(); -} - -void CSprite::InputColorRedValue( inputdata_t &inputdata ) -{ - int nNewColor = clamp( inputdata.value.Int(), 0, 255 ); - SetColor( nNewColor, m_clrRender->g, m_clrRender->b ); -} - -void CSprite::InputColorGreenValue( inputdata_t &inputdata ) -{ - int nNewColor = clamp( inputdata.value.Int(), 0, 255 ); - SetColor( m_clrRender->r, nNewColor, m_clrRender->b ); -} - -void CSprite::InputColorBlueValue( inputdata_t &inputdata ) -{ - int nNewColor = clamp( inputdata.value.Int(), 0, 255 ); - SetColor( m_clrRender->r, m_clrRender->g, nNewColor ); -} - -//----------------------------------------------------------------------------- -// Purpose: Input handler that toggles the sprite between hidden and shown. -//----------------------------------------------------------------------------- -void CSprite::InputToggleSprite( inputdata_t &inputdata ) -{ - if ( !IsEffectActive( EF_NODRAW ) ) - { - TurnOff(); - } - else - { - TurnOn(); - } -} -#endif - -#if defined( CLIENT_DLL ) - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CSprite::GetRenderScale( void ) -{ - //See if we're done scaling - if ( ( m_flScaleTime == 0 ) || ( (m_flScaleTimeStart+m_flScaleTime) < gpGlobals->curtime ) ) - return m_flSpriteScale; - - //Get our percentage - float timeDelta = ( gpGlobals->curtime - m_flScaleTimeStart ) / m_flScaleTime; - - //Return the result - return ( m_flStartScale + ( ( m_flDestScale - m_flStartScale ) * timeDelta ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: Get the rendered extents of the sprite -//----------------------------------------------------------------------------- -void CSprite::GetRenderBounds( Vector &vecMins, Vector &vecMaxs ) -{ - float flScale = GetRenderScale() * 0.5f; - - // If our scale is normalized we need to convert that to actual world units - if ( m_bWorldSpaceScale == false ) - { - CEngineSprite *psprite = (CEngineSprite *) modelinfo->GetModelExtraData( GetModel() ); - if ( psprite ) - { - float flSize = MAX( psprite->GetWidth(), psprite->GetHeight() ); - flScale *= flSize; - } - } - - vecMins.Init( -flScale, -flScale, -flScale ); - vecMaxs.Init( flScale, flScale, flScale ); - -#if 0 - // Visualize the bounds - debugoverlay->AddBoxOverlay( GetRenderOrigin(), vecMins, vecMaxs, GetRenderAngles(), 255, 255, 255, 0, 0.01f ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CSprite::GetRenderBrightness( void ) -{ - //See if we're done scaling - if ( ( m_flBrightnessTime == 0 ) || ( (m_flBrightnessTimeStart+m_flBrightnessTime) < gpGlobals->curtime ) ) - { - return m_nBrightness; - } - - //Get our percentage - float timeDelta = ( gpGlobals->curtime - m_flBrightnessTimeStart ) / m_flBrightnessTime; - - float brightness = ( (float) m_nStartBrightness + ( (float) ( m_nDestBrightness - m_nStartBrightness ) * timeDelta ) ); - - //Return the result - return (int) brightness; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSprite::OnDataChanged( DataUpdateType_t updateType ) -{ - BaseClass::OnDataChanged( updateType ); - - // Only think when sapping - SetNextClientThink( CLIENT_THINK_ALWAYS ); - if ( updateType == DATA_UPDATE_CREATED ) - { - m_flStartScale = m_flDestScale = m_flSpriteScale; - m_nStartBrightness = m_nDestBrightness = m_nBrightness; - } - - UpdateVisibility(); -} - -void CSprite::ClientThink( void ) -{ - BaseClass::ClientThink(); - - // Module render colors over time - if ( m_flSpriteScale != m_flDestScale ) - { - m_flStartScale = m_flDestScale; - m_flDestScale = m_flSpriteScale; - m_flScaleTimeStart = gpGlobals->curtime; - } - - if ( m_nBrightness != m_nDestBrightness ) - { - m_nStartBrightness = m_nDestBrightness; - m_nDestBrightness = m_nBrightness; - m_flBrightnessTimeStart = gpGlobals->curtime; - } -} - -extern bool g_bRenderingScreenshot; -extern ConVar r_drawviewmodel; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : flags - -// Output : int -//----------------------------------------------------------------------------- -int CSprite::DrawModel( int flags ) -{ - VPROF_BUDGET( "CSprite::DrawModel", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); - //See if we should draw - if ( !IsVisible() || ( m_bReadyToDraw == false ) ) - return 0; - -#ifdef PORTAL - if ( ( !g_pPortalRender->IsRenderingPortal() && !m_bDrawInMainRender ) || - ( g_pPortalRender->IsRenderingPortal() && !m_bDrawInPortalRender ) ) - { - return 0; - } -#endif //#ifdef PORTAL - - // Tracker 16432: If rendering a savegame screenshot then don't draw sprites - // who have viewmodels as their moveparent - if ( g_bRenderingScreenshot || !r_drawviewmodel.GetBool() ) - { - C_BaseViewModel *vm = dynamic_cast< C_BaseViewModel * >( GetMoveParent() ); - if ( vm ) - { - return 0; - } - } - - //Must be a sprite - if ( modelinfo->GetModelType( GetModel() ) != mod_sprite ) - { - Assert( 0 ); - return 0; - } - - float renderscale = GetRenderScale(); - if ( m_bWorldSpaceScale ) - { - CEngineSprite *psprite = ( CEngineSprite * )modelinfo->GetModelExtraData( GetModel() ); - float flMinSize = MIN( psprite->GetWidth(), psprite->GetHeight() ); - renderscale /= flMinSize; - } - - //Draw it - int drawn = DrawSprite( - this, - GetModel(), - GetAbsOrigin(), - GetAbsAngles(), - m_flFrame, // sprite frame to render - m_hAttachedToEntity, // attach to - m_nAttachment, // attachment point - GetRenderMode(), // rendermode - m_nRenderFX, - GetRenderBrightness(), // alpha - m_clrRender->r, - m_clrRender->g, - m_clrRender->b, - renderscale, // sprite scale - GetHDRColorScale() // HDR Color Scale - ); - - return drawn; -} - - -const Vector& CSprite::GetRenderOrigin() -{ - static Vector vOrigin; - vOrigin = GetAbsOrigin(); - - if ( m_hAttachedToEntity ) - { - C_BaseEntity *ent = m_hAttachedToEntity->GetBaseEntity(); - if ( ent ) - { - QAngle dummyAngles; - ent->GetAttachment( m_nAttachment, vOrigin, dummyAngles ); - } - } - - return vOrigin; -} - -#endif - -//----------------------------------------------------------------------------- -// Purpose: oriented sprites -// CSprites swap the roll and yaw angle inputs, and rotate the yaw 180 degrees -//----------------------------------------------------------------------------- - -#if !defined( CLIENT_DLL ) -IMPLEMENT_SERVERCLASS_ST( CSpriteOriented, DT_SpriteOriented ) -END_SEND_TABLE() -#else -#undef CSpriteOriented -IMPLEMENT_CLIENTCLASS_DT(C_SpriteOriented, DT_SpriteOriented, CSpriteOriented) -#define CSpriteOriented C_SpriteOriented -END_RECV_TABLE() -#endif - -#if !defined( CLIENT_DLL ) - -void CSpriteOriented::Spawn( void ) -{ - // save a copy of the angles, CSprite swaps the yaw and roll - QAngle angles = GetAbsAngles(); - BaseClass::Spawn(); - // ORIENTED sprites "forward" vector points in the players "view" direction, not the direction "out" from the sprite (gah) - angles.y = anglemod( angles.y + 180 ); - SetAbsAngles( angles ); -} - -#else - -bool CSpriteOriented::IsTransparent( void ) -{ - return true; -} - -#endif diff --git a/game/shared/Sprite.h b/game/shared/Sprite.h deleted file mode 100644 index 6cb880bd3..000000000 --- a/game/shared/Sprite.h +++ /dev/null @@ -1,297 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SPRITE_H -#define SPRITE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "predictable_entity.h" -#include "baseentity_shared.h" - -#define SF_SPRITE_STARTON 0x0001 -#define SF_SPRITE_ONCE 0x0002 -#define SF_SPRITE_TEMPORARY 0x8000 - -class CBasePlayer; - -#if defined( CLIENT_DLL ) -#define CSprite C_Sprite -#define CSpriteOriented C_SpriteOriented -#include "c_pixel_visibility.h" -class CEngineSprite; - -class C_SpriteRenderer -{ -public: - //----------------------------------------------------------------------------- - // Purpose: Sprite orientations - // WARNING! Change these in common/MaterialSystem/Sprite.cpp if you change them here! - //----------------------------------------------------------------------------- - typedef enum - { - SPR_VP_PARALLEL_UPRIGHT = 0, - SPR_FACING_UPRIGHT = 1, - SPR_VP_PARALLEL = 2, - SPR_ORIENTED = 3, - SPR_VP_PARALLEL_ORIENTED = 4 - } SPRITETYPE; - - // Determine sprite orientation - static void GetSpriteAxes( SPRITETYPE type, - const Vector& origin, - const QAngle& angles, - Vector& forward, - Vector& right, - Vector& up ); - - // Sprites can alter blending amount - virtual float GlowBlend( CEngineSprite *psprite, const Vector& entorigin, int rendermode, int renderfx, int alpha, float *scale ); - - // Draws tempent as a sprite - int DrawSprite( - IClientEntity *entity, - const model_t *model, - const Vector& origin, - const QAngle& angles, - float frame, - IClientEntity *attachedto, - int attachmentindex, - int rendermode, - int renderfx, - int alpha, - int r, - int g, - int b, - float scale, - float flHDRColorScale = 1.0f - ); - -protected: - pixelvis_handle_t m_queryHandle; - float m_flGlowProxySize; - float m_flHDRColorScale; -}; - -#endif - -class CSprite : public CBaseEntity -#if defined( CLIENT_DLL ) - , public C_SpriteRenderer -#endif -{ - DECLARE_CLASS( CSprite, CBaseEntity ); -public: - DECLARE_PREDICTABLE(); - DECLARE_NETWORKCLASS(); - - CSprite(); - virtual void SetModel( const char *szModelName ); - - void Spawn( void ); - void Precache( void ); - virtual void ComputeWorldSpaceSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs ); - - void SetGlowProxySize( float flSize ) { m_flGlowProxySize = flSize; } - -#if !defined( CLIENT_DLL ) - - virtual int ShouldTransmit( const CCheckTransmitInfo *pInfo ); - virtual int UpdateTransmitState( void ); - - void SetAsTemporary( void ) { AddSpawnFlags( SF_SPRITE_TEMPORARY ); } - bool IsTemporary( void ) { return ( HasSpawnFlags( SF_SPRITE_TEMPORARY ) ); } - - int ObjectCaps( void ) - { - int flags = 0; - - if ( IsTemporary() ) - { - flags = FCAP_DONT_SAVE; - } - - return (BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | flags; - } - - void OnRestore(); -#endif - - void AnimateThink( void ); - void ExpandThink( void ); - void Animate( float frames ); - void Expand( float scaleSpeed, float fadeSpeed ); - void SpriteInit( const char *pSpriteName, const Vector &origin ); - -#if !defined( CLIENT_DLL ) - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - // Input handlers - void InputHideSprite( inputdata_t &inputdata ); - void InputShowSprite( inputdata_t &inputdata ); - void InputToggleSprite( inputdata_t &inputdata ); - void InputColorRedValue( inputdata_t &inputdata ); - void InputColorBlueValue( inputdata_t &inputdata ); - void InputColorGreenValue( inputdata_t &inputdata ); -#endif - - inline void SetAttachment( CBaseEntity *pEntity, int attachment ) - { - if ( pEntity ) - { - m_hAttachedToEntity = pEntity; - m_nAttachment = attachment; - FollowEntity( pEntity ); - } - } - - void TurnOff( void ); - void TurnOn( void ); - bool IsOn() { return !IsEffectActive( EF_NODRAW ); } - - inline float Frames( void ) { return m_flMaxFrame; } - inline void SetTransparency( int rendermode, int r, int g, int b, int a, int fx ) - { - SetRenderMode( (RenderMode_t)rendermode ); - SetColor( r, g, b ); - SetBrightness( a ); - m_nRenderFX = fx; - } - inline void SetTexture( int spriteIndex ) { SetModelIndex( spriteIndex ); } - inline void SetColor( int r, int g, int b ) { SetRenderColor( r, g, b, GetRenderColor().a ); } - - void SetBrightness( int brightness, float duration = 0.0f ); - void SetScale( float scale, float duration = 0.0f ); - void SetSpriteScale( float scale ); - void EnableWorldSpaceScale( bool bEnable ); - - float GetScale( void ) { return m_flSpriteScale; } - int GetBrightness( void ) { return m_nBrightness; } - float GetHDRColorScale( void ) { return m_flHDRColorScale; } - - inline void FadeAndDie( float duration ) - { - SetBrightness( 0, duration ); - SetThink(&CSprite::AnimateUntilDead); - m_flDieTime = gpGlobals->curtime + duration; - SetNextThink( gpGlobals->curtime ); - } - - inline void AnimateAndDie( float framerate ) - { - SetThink(&CSprite::AnimateUntilDead); - m_flSpriteFramerate = framerate; - m_flDieTime = gpGlobals->curtime + (m_flMaxFrame / m_flSpriteFramerate); - SetNextThink( gpGlobals->curtime ); - } - - inline void AnimateForTime( float framerate, float time ) - { - SetThink(&CSprite::AnimateUntilDead); - m_flSpriteFramerate = framerate; - m_flDieTime = gpGlobals->curtime + time; - SetNextThink( gpGlobals->curtime ); - } - - // FIXME: This completely blows. - // Surely there's gotta be a better way. - void FadeOutFromSpawn( ) - { - SetThink(&CSprite::BeginFadeOutThink); - SetNextThink( gpGlobals->curtime + 0.01f ); - } - - void BeginFadeOutThink( ) - { - FadeAndDie( 0.25f ); - } - - void AnimateUntilDead( void ); -#if !defined( CLIENT_DLL ) - DECLARE_DATADESC(); - - static CSprite *SpriteCreate( const char *pSpriteName, const Vector &origin, bool animate ); -#endif - static CSprite *SpriteCreatePredictable( const char *module, int line, const char *pSpriteName, const Vector &origin, bool animate ); - -#if defined( CLIENT_DLL ) - virtual float GetRenderScale( void ); - virtual int GetRenderBrightness( void ); - - virtual int DrawModel( int flags ); - virtual const Vector& GetRenderOrigin(); - virtual void GetRenderBounds( Vector &vecMins, Vector &vecMaxs ); - virtual float GlowBlend( CEngineSprite *psprite, const Vector& entorigin, int rendermode, int renderfx, int alpha, float *scale ); - virtual void GetToolRecordingState( KeyValues *msg ); - -// Only supported in TF2 right now -#if defined( INVASION_CLIENT_DLL ) - virtual bool ShouldPredict( void ) - { - return true; - } -#endif - - virtual void ClientThink( void ); - virtual void OnDataChanged( DataUpdateType_t updateType ); - -#endif -public: - CNetworkHandle( CBaseEntity, m_hAttachedToEntity ); - CNetworkVar( int, m_nAttachment ); - CNetworkVar( float, m_flSpriteFramerate ); - CNetworkVar( float, m_flFrame ); -#ifdef PORTAL - CNetworkVar( bool, m_bDrawInMainRender ); - CNetworkVar( bool, m_bDrawInPortalRender ); -#endif - - float m_flDieTime; - -private: - - CNetworkVar( int, m_nBrightness ); - CNetworkVar( float, m_flBrightnessTime ); - - CNetworkVar( float, m_flSpriteScale ); - CNetworkVar( float, m_flScaleTime ); - CNetworkVar( bool, m_bWorldSpaceScale ); - CNetworkVar( float, m_flGlowProxySize ); - CNetworkVar( float, m_flHDRColorScale ); - - float m_flLastTime; - float m_flMaxFrame; - - float m_flStartScale; - float m_flDestScale; //Destination scale - float m_flScaleTimeStart; //Real time for start of scale - int m_nStartBrightness; - int m_nDestBrightness; //Destination brightness - float m_flBrightnessTimeStart;//Real time for brightness -}; - - -class CSpriteOriented : public CSprite -{ -public: - DECLARE_CLASS( CSpriteOriented, CSprite ); -#if !defined( CLIENT_DLL ) - DECLARE_SERVERCLASS(); - void Spawn( void ); -#else - DECLARE_CLIENTCLASS(); - virtual bool IsTransparent( void ); -#endif -}; - - - -// Macro to wrap creation -#define SPRITE_CREATE_PREDICTABLE( name, origin, animate ) \ - CSprite::SpriteCreatePredictable( __FILE__, __LINE__, name, origin, animate ) - -#endif // SPRITE_H diff --git a/game/shared/SpriteTrail.cpp b/game/shared/SpriteTrail.cpp deleted file mode 100644 index 3827120ab..000000000 --- a/game/shared/SpriteTrail.cpp +++ /dev/null @@ -1,587 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "SpriteTrail.h" - -#ifdef CLIENT_DLL - -#include "clientsideeffects.h" -#include "materialsystem/IMaterialSystem.h" -#include "materialsystem/IMesh.h" -#include "mathlib/VMatrix.h" -#include "view.h" -#include "beamdraw.h" -#include "enginesprite.h" -#include "tier0/vprof.h" - -extern CEngineSprite *Draw_SetSpriteTexture( const model_t *pSpriteModel, int frame, int rendermode ); - -#endif // CLIENT_DLL - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// constants -//----------------------------------------------------------------------------- -#define SCREEN_SPACE_TRAILS 0 - - -//----------------------------------------------------------------------------- -// Save/Restore -//----------------------------------------------------------------------------- -#if defined( CLIENT_DLL ) - -BEGIN_SIMPLE_DATADESC( TrailPoint_t ) -#if SCREEN_SPACE_TRAILS - DEFINE_FIELD( m_vecScreenPos, FIELD_VECTOR ), -#else - DEFINE_FIELD( m_vecScreenPos, FIELD_POSITION_VECTOR ), -#endif - - DEFINE_FIELD( m_flDieTime, FIELD_TIME ), - DEFINE_FIELD( m_flTexCoord, FIELD_FLOAT ), - DEFINE_FIELD( m_flWidthVariance,FIELD_FLOAT ), -END_DATADESC() - -#endif - -BEGIN_DATADESC( CSpriteTrail ) - - DEFINE_KEYFIELD( m_flLifeTime, FIELD_FLOAT, "lifetime" ), - DEFINE_KEYFIELD( m_flStartWidth, FIELD_FLOAT, "startwidth" ), - DEFINE_KEYFIELD( m_flEndWidth, FIELD_FLOAT, "endwidth" ), - DEFINE_KEYFIELD( m_iszSpriteName, FIELD_STRING, "spritename" ), - DEFINE_KEYFIELD( m_bAnimate, FIELD_BOOLEAN, "animate" ), - DEFINE_FIELD( m_flStartWidthVariance, FIELD_FLOAT ), - DEFINE_FIELD( m_flTextureRes, FIELD_FLOAT ), - DEFINE_FIELD( m_flMinFadeLength, FIELD_FLOAT ), - DEFINE_FIELD( m_vecSkyboxOrigin, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_flSkyboxScale, FIELD_FLOAT ), - - // These are client-only -#if defined( CLIENT_DLL ) - DEFINE_EMBEDDED_AUTO_ARRAY( m_vecSteps ), - DEFINE_FIELD( m_nFirstStep, FIELD_INTEGER ), - DEFINE_FIELD( m_nStepCount, FIELD_INTEGER ), - DEFINE_FIELD( m_flUpdateTime, FIELD_TIME ), - DEFINE_FIELD( m_vecPrevSkyboxOrigin, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_flPrevSkyboxScale, FIELD_FLOAT ), - DEFINE_FIELD( m_vecRenderMins, FIELD_VECTOR ), - DEFINE_FIELD( m_vecRenderMaxs, FIELD_VECTOR ), -#endif - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( env_spritetrail, CSpriteTrail ); - - -//----------------------------------------------------------------------------- -// Networking -//----------------------------------------------------------------------------- -IMPLEMENT_NETWORKCLASS_ALIASED( SpriteTrail, DT_SpriteTrail ); - -BEGIN_NETWORK_TABLE( CSpriteTrail, DT_SpriteTrail ) -#if !defined( CLIENT_DLL ) - SendPropFloat( SENDINFO(m_flLifeTime), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO(m_flStartWidth), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO(m_flEndWidth), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO(m_flStartWidthVariance), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO(m_flTextureRes), 0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO(m_flMinFadeLength), 0, SPROP_NOSCALE ), - SendPropVector( SENDINFO(m_vecSkyboxOrigin),0, SPROP_NOSCALE ), - SendPropFloat( SENDINFO(m_flSkyboxScale), 0, SPROP_NOSCALE ), -#else - RecvPropFloat( RECVINFO(m_flLifeTime)), - RecvPropFloat( RECVINFO(m_flStartWidth)), - RecvPropFloat( RECVINFO(m_flEndWidth)), - RecvPropFloat( RECVINFO(m_flStartWidthVariance)), - RecvPropFloat( RECVINFO(m_flTextureRes)), - RecvPropFloat( RECVINFO(m_flMinFadeLength)), - RecvPropVector( RECVINFO(m_vecSkyboxOrigin)), - RecvPropFloat( RECVINFO(m_flSkyboxScale)), -#endif -END_NETWORK_TABLE() - -//----------------------------------------------------------------------------- -// Prediction -//----------------------------------------------------------------------------- -BEGIN_PREDICTION_DATA( CSpriteTrail ) -END_PREDICTION_DATA() - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CSpriteTrail::CSpriteTrail( void ) -{ -#ifdef CLIENT_DLL - m_nFirstStep = 0; - m_nStepCount = 0; -#endif - - m_flStartWidthVariance = 0; - m_vecSkyboxOrigin.Init( 0, 0, 0 ); - m_flSkyboxScale = 1.0f; - m_flEndWidth = -1.0f; -} - -void CSpriteTrail::Spawn( void ) -{ -#ifdef CLIENT_DLL - BaseClass::Spawn(); -#else - - if ( GetModelName() != NULL_STRING ) - { - BaseClass::Spawn(); - return; - } - - SetModelName( m_iszSpriteName ); - BaseClass::Spawn(); - - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NOCLIP ); - - SetCollisionBounds( vec3_origin, vec3_origin ); - TurnOn(); - -#endif -} - -//----------------------------------------------------------------------------- -// Sets parameters of the sprite trail -//----------------------------------------------------------------------------- -void CSpriteTrail::Precache( void ) -{ - BaseClass::Precache(); - - if ( m_iszSpriteName != NULL_STRING ) - { - PrecacheModel( STRING(m_iszSpriteName) ); - } -} - -//----------------------------------------------------------------------------- -// Sets parameters of the sprite trail -//----------------------------------------------------------------------------- -void CSpriteTrail::SetLifeTime( float time ) -{ - m_flLifeTime = time; -} - -void CSpriteTrail::SetStartWidth( float flStartWidth ) -{ - m_flStartWidth = flStartWidth; - m_flStartWidth /= m_flSkyboxScale; -} - -void CSpriteTrail::SetStartWidthVariance( float flStartWidthVariance ) -{ - m_flStartWidthVariance = flStartWidthVariance; - m_flStartWidthVariance /= m_flSkyboxScale; -} - -void CSpriteTrail::SetEndWidth( float flEndWidth ) -{ - m_flEndWidth = flEndWidth; - m_flEndWidth /= m_flSkyboxScale; -} - -void CSpriteTrail::SetTextureResolution( float flTexelsPerInch ) -{ - m_flTextureRes = flTexelsPerInch; - m_flTextureRes *= m_flSkyboxScale; -} - -void CSpriteTrail::SetMinFadeLength( float flMinFadeLength ) -{ - m_flMinFadeLength = flMinFadeLength; - m_flMinFadeLength /= m_flSkyboxScale; -} - -void CSpriteTrail::SetSkybox( const Vector &vecSkyboxOrigin, float flSkyboxScale ) -{ - m_flTextureRes /= m_flSkyboxScale; - m_flMinFadeLength *= m_flSkyboxScale; - m_flStartWidth *= m_flSkyboxScale; - m_flEndWidth *= m_flSkyboxScale; - m_flStartWidthVariance *= m_flSkyboxScale; - - m_vecSkyboxOrigin = vecSkyboxOrigin; - m_flSkyboxScale = flSkyboxScale; - - m_flTextureRes *= m_flSkyboxScale; - m_flMinFadeLength /= m_flSkyboxScale; - m_flStartWidth /= m_flSkyboxScale; - m_flEndWidth /= m_flSkyboxScale; - m_flStartWidthVariance /= m_flSkyboxScale; - - if ( IsInSkybox() ) - { - AddEFlags( EFL_IN_SKYBOX ); - } - else - { - RemoveEFlags( EFL_IN_SKYBOX ); - } -} - - -//----------------------------------------------------------------------------- -// Is the trail in the skybox? -//----------------------------------------------------------------------------- -bool CSpriteTrail::IsInSkybox() const -{ - return (m_flSkyboxScale != 1.0f) || (m_vecSkyboxOrigin != vec3_origin); -} - - -#ifdef CLIENT_DLL - - -//----------------------------------------------------------------------------- -// On data update -//----------------------------------------------------------------------------- -void CSpriteTrail::OnPreDataChanged( DataUpdateType_t updateType ) -{ - BaseClass::OnPreDataChanged( updateType ); - m_vecPrevSkyboxOrigin = m_vecSkyboxOrigin; - m_flPrevSkyboxScale = m_flSkyboxScale; -} - -void CSpriteTrail::OnDataChanged( DataUpdateType_t updateType ) -{ - BaseClass::OnDataChanged( updateType ); - if ( updateType == DATA_UPDATE_CREATED ) - { - SetNextClientThink( CLIENT_THINK_ALWAYS ); - } - else - { - if ((m_flPrevSkyboxScale != m_flSkyboxScale) || (m_vecPrevSkyboxOrigin != m_vecSkyboxOrigin)) - { - ConvertSkybox(); - } - } -} - - -//----------------------------------------------------------------------------- -// Compute position + bounding box -//----------------------------------------------------------------------------- -void CSpriteTrail::ClientThink() -{ - // Update the trail + bounding box - UpdateTrail(); - UpdateBoundingBox(); -} - - -//----------------------------------------------------------------------------- -// Render bounds -//----------------------------------------------------------------------------- -void CSpriteTrail::GetRenderBounds( Vector& mins, Vector& maxs ) -{ - mins = m_vecRenderMins; - maxs = m_vecRenderMaxs; -} - - -//----------------------------------------------------------------------------- -// Converts the trail when it changes skyboxes -//----------------------------------------------------------------------------- -void CSpriteTrail::ConvertSkybox() -{ - for ( int i = 0; i < m_nStepCount; ++i ) - { - // This makes it so that we're always drawing to the current location - TrailPoint_t *pPoint = GetTrailPoint(i); - - VectorSubtract( pPoint->m_vecScreenPos, m_vecPrevSkyboxOrigin, pPoint->m_vecScreenPos ); - pPoint->m_vecScreenPos *= m_flPrevSkyboxScale / m_flSkyboxScale; - VectorSubtract( pPoint->m_vecScreenPos, m_vecSkyboxOrigin, pPoint->m_vecScreenPos ); - pPoint->m_flWidthVariance *= m_flPrevSkyboxScale / m_flSkyboxScale; - } -} - - -//----------------------------------------------------------------------------- -// Gets at the nth item in the list -//----------------------------------------------------------------------------- -TrailPoint_t *CSpriteTrail::GetTrailPoint( int n ) -{ - Assert( n < MAX_SPRITE_TRAIL_POINTS ); - COMPILE_TIME_ASSERT( (MAX_SPRITE_TRAIL_POINTS & (MAX_SPRITE_TRAIL_POINTS-1)) == 0 ); - int nIndex = (n + m_nFirstStep) & MAX_SPRITE_TRAIL_MASK; - return &m_vecSteps[nIndex]; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSpriteTrail::ComputeScreenPosition( Vector *pScreenPos ) -{ -#if SCREEN_SPACE_TRAILS - VMatrix viewMatrix; - materials->GetMatrix( MATERIAL_VIEW, &viewMatrix ); - *pScreenPos = viewMatrix * GetRenderOrigin(); -#else - *pScreenPos = GetRenderOrigin(); -#endif -} - - -//----------------------------------------------------------------------------- -// Compute position + bounding box -//----------------------------------------------------------------------------- -void CSpriteTrail::UpdateBoundingBox( void ) -{ - Vector vecRenderOrigin = GetRenderOrigin(); - m_vecRenderMins = vecRenderOrigin; - m_vecRenderMaxs = vecRenderOrigin; - - float flMaxWidth = m_flStartWidth; - if (( m_flEndWidth >= 0.0f ) && ( m_flEndWidth > m_flStartWidth )) - { - flMaxWidth = m_flEndWidth; - } - - Vector mins, maxs; - for ( int i = 0; i < m_nStepCount; ++i ) - { - TrailPoint_t *pPoint = GetTrailPoint(i); - - float flActualWidth = (flMaxWidth + pPoint->m_flWidthVariance) * 0.5f; - Vector size( flActualWidth, flActualWidth, flActualWidth ); - VectorSubtract( pPoint->m_vecScreenPos, size, mins ); - VectorAdd( pPoint->m_vecScreenPos, size, maxs ); - - VectorMin( m_vecRenderMins, mins, m_vecRenderMins ); - VectorMax( m_vecRenderMaxs, maxs, m_vecRenderMaxs ); - } - - m_vecRenderMins -= vecRenderOrigin; - m_vecRenderMaxs -= vecRenderOrigin; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSpriteTrail::UpdateTrail( void ) -{ - // Can't update too quickly - if ( m_flUpdateTime > gpGlobals->curtime ) - return; - - Vector screenPos; - ComputeScreenPosition( &screenPos ); - TrailPoint_t *pLast = m_nStepCount ? GetTrailPoint( m_nStepCount-1 ) : NULL; - if ( ( pLast == NULL ) || ( pLast->m_vecScreenPos.DistToSqr( screenPos ) > 4.0f ) ) - { - // If we're over our limit, steal the last point and put it up front - if ( m_nStepCount >= MAX_SPRITE_TRAIL_POINTS ) - { - --m_nStepCount; - ++m_nFirstStep; - } - - // Save off its screen position, not its world position - TrailPoint_t *pNewPoint = GetTrailPoint( m_nStepCount ); - pNewPoint->m_vecScreenPos = screenPos; - pNewPoint->m_flDieTime = gpGlobals->curtime + m_flLifeTime; - pNewPoint->m_flWidthVariance = random->RandomFloat( -m_flStartWidthVariance, m_flStartWidthVariance ); - if (pLast) - { - pNewPoint->m_flTexCoord = pLast->m_flTexCoord + pLast->m_vecScreenPos.DistTo( screenPos ) * m_flTextureRes; - } - else - { - pNewPoint->m_flTexCoord = 0.0f; - } - - ++m_nStepCount; - } - - // Don't update again for a bit - m_flUpdateTime = gpGlobals->curtime + ( m_flLifeTime / (float) MAX_SPRITE_TRAIL_POINTS ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CSpriteTrail::DrawModel( int flags ) -{ - VPROF_BUDGET( "CSpriteTrail::DrawModel", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); - - // Must have at least one point - if ( m_nStepCount < 1 ) - return 1; - - //See if we should draw - if ( !IsVisible() || ( m_bReadyToDraw == false ) ) - return 0; - - CEngineSprite *pSprite = Draw_SetSpriteTexture( GetModel(), m_flFrame, GetRenderMode() ); - if ( pSprite == NULL ) - return 0; - - // Specify all the segments. - CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); - CBeamSegDraw segDraw; - segDraw.Start( pRenderContext, m_nStepCount + 1, pSprite->GetMaterial() ); - - // Setup the first point, always emanating from the attachment point - TrailPoint_t *pLast = GetTrailPoint( m_nStepCount-1 ); - TrailPoint_t currentPoint; - currentPoint.m_flDieTime = gpGlobals->curtime + m_flLifeTime; - ComputeScreenPosition( ¤tPoint.m_vecScreenPos ); - currentPoint.m_flTexCoord = pLast->m_flTexCoord + currentPoint.m_vecScreenPos.DistTo(pLast->m_vecScreenPos) * m_flTextureRes; - currentPoint.m_flWidthVariance = 0.0f; - -#if SCREEN_SPACE_TRAILS - VMatrix viewMatrix; - materials->GetMatrix( MATERIAL_VIEW, &viewMatrix ); - viewMatrix = viewMatrix.InverseTR(); -#endif - - TrailPoint_t *pPrevPoint = NULL; - float flTailAlphaDist = m_flMinFadeLength; - for ( int i = 0; i <= m_nStepCount; ++i ) - { - // This makes it so that we're always drawing to the current location - TrailPoint_t *pPoint = (i != m_nStepCount) ? GetTrailPoint(i) : ¤tPoint; - - float flLifePerc = (pPoint->m_flDieTime - gpGlobals->curtime) / m_flLifeTime; - flLifePerc = clamp( flLifePerc, 0.0f, 1.0f ); - - BeamSeg_t curSeg; - curSeg.m_vColor.x = (float) m_clrRender->r / 255.0f; - curSeg.m_vColor.y = (float) m_clrRender->g / 255.0f; - curSeg.m_vColor.z = (float) m_clrRender->b / 255.0f; - - float flAlphaFade = flLifePerc; - if ( flTailAlphaDist > 0.0f ) - { - if ( pPrevPoint ) - { - float flDist = pPoint->m_vecScreenPos.DistTo( pPrevPoint->m_vecScreenPos ); - flTailAlphaDist -= flDist; - } - - if ( flTailAlphaDist > 0.0f ) - { - float flTailFade = Lerp( (m_flMinFadeLength - flTailAlphaDist) / m_flMinFadeLength, 0.0f, 1.0f ); - if ( flTailFade < flAlphaFade ) - { - flAlphaFade = flTailFade; - } - } - } - curSeg.m_flAlpha = ( (float) GetRenderBrightness() / 255.0f ) * flAlphaFade; - -#if SCREEN_SPACE_TRAILS - curSeg.m_vPos = viewMatrix * pPoint->m_vecScreenPos; -#else - curSeg.m_vPos = pPoint->m_vecScreenPos; -#endif - - if ( m_flEndWidth >= 0.0f ) - { - curSeg.m_flWidth = Lerp( flLifePerc, m_flEndWidth.Get(), m_flStartWidth.Get() ); - } - else - { - curSeg.m_flWidth = m_flStartWidth.Get(); - } - curSeg.m_flWidth += pPoint->m_flWidthVariance; - if ( curSeg.m_flWidth < 0.0f ) - { - curSeg.m_flWidth = 0.0f; - } - - curSeg.m_flTexCoord = pPoint->m_flTexCoord; - - segDraw.NextSeg( &curSeg ); - - // See if we're done with this bad boy - if ( pPoint->m_flDieTime <= gpGlobals->curtime ) - { - // Push this back onto the top for use - ++m_nFirstStep; - --i; - --m_nStepCount; - } - - pPrevPoint = pPoint; - } - - segDraw.End(); - - return 1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Vector const& -//----------------------------------------------------------------------------- -const Vector &CSpriteTrail::GetRenderOrigin( void ) -{ - static Vector vOrigin; - vOrigin = GetAbsOrigin(); - - if ( m_hAttachedToEntity ) - { - C_BaseEntity *ent = m_hAttachedToEntity->GetBaseEntity(); - if ( ent ) - { - QAngle dummyAngles; - ent->GetAttachment( m_nAttachment, vOrigin, dummyAngles ); - } - } - - return vOrigin; -} - -const QAngle &CSpriteTrail::GetRenderAngles( void ) -{ - return vec3_angle; -} - -#endif //CLIENT_DLL - -#if !defined( CLIENT_DLL ) - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pSpriteName - -// &origin - -// animate - -// Output : CSpriteTrail -//----------------------------------------------------------------------------- -CSpriteTrail *CSpriteTrail::SpriteTrailCreate( const char *pSpriteName, const Vector &origin, bool animate ) -{ - CSpriteTrail *pSprite = CREATE_ENTITY( CSpriteTrail, "env_spritetrail" ); - - pSprite->SpriteInit( pSpriteName, origin ); - pSprite->SetSolid( SOLID_NONE ); - pSprite->SetMoveType( MOVETYPE_NOCLIP ); - - UTIL_SetSize( pSprite, vec3_origin, vec3_origin ); - - if ( animate ) - { - pSprite->TurnOn(); - } - - return pSprite; -} - -#endif //CLIENT_DLL == false diff --git a/game/shared/SpriteTrail.h b/game/shared/SpriteTrail.h deleted file mode 100644 index b135bcb34..000000000 --- a/game/shared/SpriteTrail.h +++ /dev/null @@ -1,111 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef SPRITETRAIL_H -#define SPRITETRAIL_H -#ifdef _WIN32 -#pragma once -#endif - -#include "Sprite.h" - -#if defined( CLIENT_DLL ) -#define CSpriteTrail C_SpriteTrail -#endif - - -//----------------------------------------------------------------------------- -// Sprite trail -//----------------------------------------------------------------------------- -struct TrailPoint_t -{ - DECLARE_SIMPLE_DATADESC(); - - Vector m_vecScreenPos; - float m_flDieTime; - float m_flTexCoord; - float m_flWidthVariance; -}; - -class CSpriteTrail : public CSprite -{ - DECLARE_CLASS( CSpriteTrail, CSprite ); - DECLARE_DATADESC(); - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - -public: - CSpriteTrail( void ); - - // Sets parameters of the sprite trail - void SetLifeTime( float time ); - void SetStartWidth( float flStartWidth ); - void SetEndWidth( float flEndWidth ); - void SetStartWidthVariance( float flStartWidthVariance ); - void SetTextureResolution( float flTexelsPerInch ); - void SetMinFadeLength( float flMinFadeLength ); - void SetSkybox( const Vector &vecSkyboxOrigin, float flSkyboxScale ); - - // Is the trail in the skybox? - bool IsInSkybox() const; - void Spawn( void ); - void Precache( void ); - -#if defined( CLIENT_DLL ) - // Client only code - virtual int DrawModel( int flags ); - virtual const Vector &GetRenderOrigin( void ); - virtual const QAngle &GetRenderAngles( void ); - - // On data update - virtual void OnPreDataChanged( DataUpdateType_t updateType ); - virtual void OnDataChanged( DataUpdateType_t updateType ); - virtual void GetRenderBounds( Vector& mins, Vector& maxs ); - virtual void ClientThink(); -#else - // Server only code - static CSpriteTrail *SpriteTrailCreate( const char *pSpriteName, const Vector &origin, bool animate ); -#endif - -private: -#if defined( CLIENT_DLL ) - enum - { - // NOTE: # of points max must be a power of two! - MAX_SPRITE_TRAIL_POINTS = 64, - MAX_SPRITE_TRAIL_MASK = 0x3F, - }; - - TrailPoint_t *GetTrailPoint( int n ); - void UpdateTrail( void ); - void ComputeScreenPosition( Vector *pScreenPos ); - void ConvertSkybox(); - void UpdateBoundingBox( void ); - - TrailPoint_t m_vecSteps[MAX_SPRITE_TRAIL_POINTS]; - int m_nFirstStep; - int m_nStepCount; - float m_flUpdateTime; - Vector m_vecPrevSkyboxOrigin; - float m_flPrevSkyboxScale; - Vector m_vecRenderMins; - Vector m_vecRenderMaxs; -#endif - - CNetworkVar( float, m_flLifeTime ); // Amount of time before a new trail segment fades away - CNetworkVar( float, m_flStartWidth ); // The starting scale - CNetworkVar( float, m_flEndWidth ); // The ending scale - CNetworkVar( float, m_flStartWidthVariance ); // The starting scale - CNetworkVar( float, m_flTextureRes ); // Texture resolution along the trail - CNetworkVar( float, m_flMinFadeLength ); // The end of the trail must fade out for this many units - CNetworkVector( m_vecSkyboxOrigin ); // What's our skybox origin? - CNetworkVar( float, m_flSkyboxScale ); // What's our skybox scale? - - string_t m_iszSpriteName; - bool m_bAnimate; -}; - -#endif // SPRITETRAIL_H diff --git a/game/shared/achievement_saverestore.cpp b/game/shared/achievement_saverestore.cpp deleted file mode 100644 index d166faca8..000000000 --- a/game/shared/achievement_saverestore.cpp +++ /dev/null @@ -1,157 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -#ifdef GAME_DLL - -#include "isaverestore.h" -#include "saverestore_utlvector.h" -#include "achievement_saverestore.h" -#include "achievementmgr.h" -#include "baseachievement.h" -#include "utlmap.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -static short ACHIEVEMENT_SAVE_RESTORE_VERSION = 2; - -//----------------------------------------------------------------------------- - -class CAchievementSaveRestoreBlockHandler : public CDefSaveRestoreBlockHandler -{ -public: - const char *GetBlockName() - { - return "Achievement"; - } - - //--------------------------------- - - void Save( ISave *pSave ) - { - CAchievementMgr *pAchievementMgr = dynamic_cast( engine->GetAchievementMgr() ); - if ( !pAchievementMgr ) - return; - - // save global achievement mgr state to separate file if there have been any changes, so in case of a crash - // the global state is consistent with last save game - pAchievementMgr->SaveGlobalStateIfDirty( pSave->IsAsync() ); - - pSave->StartBlock( "Achievements" ); - int iTotalAchievements = pAchievementMgr->GetAchievementCount(); - short nSaveCount = 0; - // count how many achievements should be saved. - for ( int i = 0; i < iTotalAchievements; i++ ) - { - IAchievement *pAchievement = pAchievementMgr->GetAchievementByIndex( i ); - if ( pAchievement->ShouldSaveWithGame() ) - { - nSaveCount++; - } - } - // Write # of saved achievements - pSave->WriteShort( &nSaveCount ); - // Write out each achievement - for ( int i = 0; i < iTotalAchievements; i++ ) - { - IAchievement *pAchievement = pAchievementMgr->GetAchievementByIndex( i ); - if ( pAchievement->ShouldSaveWithGame() ) - { - CBaseAchievement *pBaseAchievement = dynamic_cast< CBaseAchievement * >( pAchievement ); - if ( pBaseAchievement ) - { - short iAchievementID = (short) pBaseAchievement->GetAchievementID(); - // write the achievement ID - pSave->WriteShort( &iAchievementID ); - // write the achievement data - pSave->WriteAll( pBaseAchievement, pBaseAchievement->GetDataDescMap() ); - } - } - } - pSave->EndBlock(); - } - - //--------------------------------- - - void WriteSaveHeaders( ISave *pSave ) - { - pSave->WriteShort( &ACHIEVEMENT_SAVE_RESTORE_VERSION ); - } - - //--------------------------------- - - void ReadRestoreHeaders( IRestore *pRestore ) - { - // No reason why any future version shouldn't try to retain backward compatability. The default here is to not do so. - short version; - pRestore->ReadShort( &version ); - // only load if version matches and if we are loading a game, not a transition - m_fDoLoad = ( ( version == ACHIEVEMENT_SAVE_RESTORE_VERSION ) && - ( ( MapLoad_LoadGame == gpGlobals->eLoadType ) || ( MapLoad_NewGame == gpGlobals->eLoadType ) ) - ); - } - - //--------------------------------- - - void Restore( IRestore *pRestore, bool createPlayers ) - { - CAchievementMgr *pAchievementMgr = dynamic_cast( engine->GetAchievementMgr() ); - if ( !pAchievementMgr ) - return; - - if ( m_fDoLoad ) - { - pAchievementMgr->PreRestoreSavedGame(); - - pRestore->StartBlock(); - // read # of achievements - int nSavedAchievements = pRestore->ReadShort(); - - while ( nSavedAchievements-- ) - { - // read achievement ID - int iAchievementID = pRestore->ReadShort(); - // find the corresponding achievement object - CBaseAchievement *pAchievement = pAchievementMgr->GetAchievementByID( iAchievementID ); - Assert( pAchievement ); // It's a bug if we don't understand this achievement - if ( pAchievement ) - { - // read achievement data - pRestore->ReadAll( pAchievement, pAchievement->GetDataDescMap() ); - } - else - { - // if we don't recognize the achievement for some reason, read and discard the data and keep going - CBaseAchievement ignored; - pRestore->ReadAll( &ignored, ignored.GetDataDescMap() ); - } - } - pRestore->EndBlock(); - - pAchievementMgr->PostRestoreSavedGame(); - } - } - -private: - bool m_fDoLoad; -}; - -//----------------------------------------------------------------------------- - -CAchievementSaveRestoreBlockHandler g_AchievementSaveRestoreBlockHandler; - -//------------------------------------- - -ISaveRestoreBlockHandler *GetAchievementSaveRestoreBlockHandler() -{ - return &g_AchievementSaveRestoreBlockHandler; -} - - -#endif // GAME_DLL diff --git a/game/shared/achievement_saverestore.h b/game/shared/achievement_saverestore.h deleted file mode 100644 index 2852ea72b..000000000 --- a/game/shared/achievement_saverestore.h +++ /dev/null @@ -1,17 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ACHIEVEMENT_SAVERESTORE_H -#define ACHIEVEMENT_SAVERESTORE_H - -#if defined( _WIN32 ) -#pragma once -#endif - -ISaveRestoreBlockHandler *GetAchievementSaveRestoreBlockHandler(); - -#endif // ACHIEVEMENT_SAVERESTORE_H diff --git a/game/shared/achievementmgr.cpp b/game/shared/achievementmgr.cpp deleted file mode 100644 index e0b936715..000000000 --- a/game/shared/achievementmgr.cpp +++ /dev/null @@ -1,1676 +0,0 @@ -//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#ifdef _WIN32 -#include "winerror.h" -#endif -#include "achievementmgr.h" -#include "icommandline.h" -#include "KeyValues.h" -#include "filesystem.h" -#include "steam/steam_api.h" -#include "inputsystem/InputEnums.h" -#include "usermessages.h" -#include "fmtstr.h" -#ifdef CLIENT_DLL -#include "achievement_notification_panel.h" -#include "c_playerresource.h" -#ifdef TF_CLIENT_DLL -#include "item_inventory.h" -#endif //TF_CLIENT_DLL -#else -#include "enginecallback.h" -#endif // CLIENT_DLL -#ifndef _X360 -#include "steam/isteamuserstats.h" -#include "steam/isteamfriends.h" -#include "steam/isteamutils.h" -#else -#include "xbox/xbox_win32stubs.h" -#endif -#include "tier3/tier3.h" -#include "vgui/ILocalize.h" -#ifdef _X360 -#include "ixboxsystem.h" -#endif // _X360 -#include "engine/imatchmaking.h" -#include "tier0/vprof.h" - -ConVar cc_achievement_debug("achievement_debug", "0", FCVAR_CHEAT | FCVAR_REPLICATED, "Turn on achievement debug msgs." ); -const char *COM_GetModDirectory(); - -extern ConVar developer; - - -#ifdef SWDS -// Hack this for now until we get steam_api recompiling in the Steam codebase. -ISteamUserStats *SteamUserStats() -{ - return NULL; -} -#endif - -//----------------------------------------------------------------------------- -// Purpose: Write helper -//----------------------------------------------------------------------------- -static void WriteAchievementGlobalState( KeyValues *pKV ) -{ -#ifdef _X360 - if ( XBX_GetStorageDeviceId() == XBX_INVALID_STORAGE_ID || XBX_GetStorageDeviceId() == XBX_STORAGE_DECLINED ) - return; -#endif - - char szFilename[_MAX_PATH]; - - if ( IsX360() ) - { - Q_snprintf( szFilename, sizeof( szFilename ), "cfg:/%s_GameState.txt", COM_GetModDirectory() ); - } - else - { - Q_snprintf( szFilename, sizeof( szFilename ), "GameState.txt" ); - } - - pKV->SaveToFile( filesystem, szFilename, "MOD" ); - pKV->deleteThis(); - -#ifdef _X360 - if ( xboxsystem ) - { - xboxsystem->FinishContainerWrites(); - } -#endif -} -#ifndef _LINUX - -//----------------------------------------------------------------------------- -// Purpose: Async save thread -//----------------------------------------------------------------------------- -class CAchievementSaveThread : public CWorkerThread -{ -public: - CAchievementSaveThread() : - m_pKV( NULL ) - { - SetName( "AchievementSaveThread" ); - } - - ~CAchievementSaveThread() - { - } - - enum - { - CALL_FUNC, - EXIT, - }; - - void WriteAchievementGlobalState( KeyValues *pKV ) - { - Assert( !m_pKV ); - m_pKV = pKV; - CallWorker( CALL_FUNC ); - Assert( !m_pKV ); - } - - int Run() - { - unsigned nCall; - while ( WaitForCall( &nCall ) ) - { - if ( nCall == EXIT ) - { - Reply( 1 ); - break; - } - - KeyValues *pKV = m_pKV; - m_pKV = NULL; - Reply( 1 ); - ::WriteAchievementGlobalState( pKV ); - } - return 0; - } - -private: - KeyValues *m_pKV; -}; - -static CAchievementSaveThread g_AchievementSaveThread; - -#endif //_LINUX - -//----------------------------------------------------------------------------- -// Purpose: constructor -//----------------------------------------------------------------------------- -CAchievementMgr::CAchievementMgr() : CAutoGameSystemPerFrame( "CAchievementMgr" ) -#if !defined(NO_STEAM) -, m_CallbackUserStatsReceived( this, &CAchievementMgr::Steam_OnUserStatsReceived ), -m_CallbackUserStatsStored( this, &CAchievementMgr::Steam_OnUserStatsStored ) -#endif -{ - SetDefLessFunc( m_mapAchievement ); - m_flLastClassChangeTime = 0; - m_flTeamplayStartTime = 0; - m_iMiniroundsCompleted = 0; - m_szMap[0] = 0; - m_bDirty = false; - m_bGlobalStateLoaded = false; - m_bCheatsEverOn = false; - m_flTimeLastUpload = 0; - - m_AchievementsAwarded.RemoveAll(); -} - -//----------------------------------------------------------------------------- -// Purpose: Initializer -//----------------------------------------------------------------------------- -bool CAchievementMgr::Init() -{ - // We can be created on either client (for multiplayer games) or server - // (for single player), so register ourselves with the engine so UI has a uniform place - // to go get the pointer to us - -#ifdef _DEBUG - // There can be only one achievement manager instance; no one else should be registered - IAchievementMgr *pAchievementMgr = engine->GetAchievementMgr(); - Assert( NULL == pAchievementMgr ); -#endif // _DEBUG - - // register ourselves - engine->SetAchievementMgr( this ); - - // register for events -#ifdef GAME_DLL - ListenForGameEvent( "entity_killed" ); - ListenForGameEvent( "game_init" ); -#else - ListenForGameEvent( "player_death" ); - ListenForGameEvent( "player_stats_updated" ); - usermessages->HookMessage( "AchievementEvent", MsgFunc_AchievementEvent ); -#endif // CLIENT_DLL - -#ifdef TF_CLIENT_DLL - ListenForGameEvent( "localplayer_changeclass" ); - ListenForGameEvent( "localplayer_changeteam" ); - ListenForGameEvent( "teamplay_round_start" ); - ListenForGameEvent( "teamplay_round_win" ); -#endif // TF_CLIENT_DLL - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: called at init time after all systems are init'd. We have to -// do this in PostInit because the Steam app ID is not available earlier -//----------------------------------------------------------------------------- -void CAchievementMgr::PostInit() -{ -#ifndef _LINUX - if ( !g_AchievementSaveThread.IsAlive() ) - { - g_AchievementSaveThread.Start(); - if ( IsX360() ) - { - ThreadSetAffinity( (ThreadHandle_t)g_AchievementSaveThread.GetThreadHandle(), XBOX_PROCESSOR_3 ); - } - } -#endif //_LINUX - - // get current game dir - const char *pGameDir = COM_GetModDirectory(); - - CBaseAchievementHelper *pAchievementHelper = CBaseAchievementHelper::s_pFirst; - while ( pAchievementHelper ) - { - // create and initialize all achievements and insert them in our map - CBaseAchievement *pAchievement = pAchievementHelper->m_pfnCreate(); - pAchievement->m_pAchievementMgr = this; - pAchievement->Init(); - pAchievement->CalcProgressMsgIncrement(); - - // only add an achievement if it does not have a game filter (only compiled into the game it - // applies to, or truly cross-game) or, if it does have a game filter, the filter matches current game. - // (e.g. EP 1/2/... achievements are in shared binary but are game specific, they have a game filter for runtime check.) - const char *pGameDirFilter = pAchievement->m_pGameDirFilter; - if ( !pGameDirFilter || ( 0 == Q_strcmp( pGameDir, pGameDirFilter ) ) ) - { - m_mapAchievement.Insert( pAchievement->GetAchievementID(), pAchievement ); - } - else - { - // achievement is not for this game, don't use it - delete pAchievement; - } - - pAchievementHelper = pAchievementHelper->m_pNext; - } - - FOR_EACH_MAP( m_mapAchievement, iter ) - { - m_vecAchievement.AddToTail( m_mapAchievement[iter] ); - } - - // load global state from file - LoadGlobalState(); - - // download achievements/stats from Steam/XBox Live - DownloadUserData(); - -} - -//----------------------------------------------------------------------------- -// Purpose: Shuts down the achievement manager -//----------------------------------------------------------------------------- -void CAchievementMgr::Shutdown() -{ -#ifndef _LINUX - g_AchievementSaveThread.CallWorker( CAchievementSaveThread::EXIT ); -#endif - - SaveGlobalState(); - - FOR_EACH_MAP( m_mapAchievement, iter ) - { - delete m_mapAchievement[iter]; - } - m_mapAchievement.RemoveAll(); - m_vecAchievement.RemoveAll(); - m_vecKillEventListeners.RemoveAll(); - m_vecMapEventListeners.RemoveAll(); - m_vecComponentListeners.RemoveAll(); - m_AchievementsAwarded.RemoveAll(); - m_bGlobalStateLoaded = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Cleans up all achievements and then re-initializes them -//----------------------------------------------------------------------------- -void CAchievementMgr::InitializeAchievements() -{ - Shutdown(); - PostInit(); -} - -#ifdef CLIENT_DLL -extern const ConVar *sv_cheats; -#endif - -//----------------------------------------------------------------------------- -// Purpose: Do per-frame handling -//----------------------------------------------------------------------------- -void CAchievementMgr::Update( float frametime ) -{ -#ifdef CLIENT_DLL - if ( !sv_cheats ) - { - sv_cheats = cvar->FindVar( "sv_cheats" ); - } -#endif - - // keep track if cheats have ever been turned on during this level - if ( !WereCheatsEverOn() ) - { - if ( sv_cheats && sv_cheats->GetBool() ) - { - m_bCheatsEverOn = true; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: called on level init -//----------------------------------------------------------------------------- -void CAchievementMgr::LevelInitPreEntity() -{ - m_bCheatsEverOn = false; - - // load global state if we haven't already; X360 users may not have had a storage device available or selected at boot time - EnsureGlobalStateLoaded(); - -#ifdef GAME_DLL - // For single-player games, achievement mgr must live on the server. (Only the server has detailed knowledge of game state.) - Assert( !GameRules()->IsMultiplayer() ); -#else - // For multiplayer games, achievement mgr must live on the client. (Only the client can read/write player state from Steam/XBox Live.) - Assert( GameRules()->IsMultiplayer() ); -#endif - - // clear list of achievements listening for events - m_vecKillEventListeners.RemoveAll(); - m_vecMapEventListeners.RemoveAll(); - m_vecComponentListeners.RemoveAll(); - - m_AchievementsAwarded.RemoveAll(); - - m_flLastClassChangeTime = 0; - m_flTeamplayStartTime = 0; - m_iMiniroundsCompleted = 0; - - // client and server have map names available in different forms (full path on client, just file base name on server), - // cache it in base file name form here so we don't have to have different code paths each time we access it -#ifdef CLIENT_DLL - Q_FileBase( engine->GetLevelName(), m_szMap, ARRAYSIZE( m_szMap ) ); -#else - Q_strncpy( m_szMap, gpGlobals->mapname.ToCStr(), ARRAYSIZE( m_szMap ) ); -#endif // CLIENT_DLL - - if ( IsX360() ) - { - // need to remove the .360 extension on the end of the map name - char *pExt = Q_stristr( m_szMap, ".360" ); - if ( pExt ) - { - *pExt = '\0'; - } - } - - // look through all achievements, see which ones we want to have listen for events - FOR_EACH_MAP( m_mapAchievement, iAchievement ) - { - CBaseAchievement *pAchievement = m_mapAchievement[iAchievement]; - - // if the achievement only applies to a specific map, and it's not the current map, skip it - const char *pMapNameFilter = pAchievement->m_pMapNameFilter; - if ( pMapNameFilter && ( 0 != Q_strcmp( m_szMap, pMapNameFilter ) ) ) - continue; - - // if the achievement needs kill events, add it as a listener - if ( pAchievement->GetFlags() & ACH_LISTEN_KILL_EVENTS ) - { - m_vecKillEventListeners.AddToTail( pAchievement ); - } - // if the achievement needs map events, add it as a listener - if ( pAchievement->GetFlags() & ACH_LISTEN_MAP_EVENTS ) - { - m_vecMapEventListeners.AddToTail( pAchievement ); - } - // if the achievement needs map events, add it as a listener - if ( pAchievement->GetFlags() & ACH_LISTEN_COMPONENT_EVENTS ) - { - m_vecComponentListeners.AddToTail( pAchievement ); - } - if ( pAchievement->IsActive() ) - { - pAchievement->ListenForEvents(); - } - } - - m_flLevelInitTime = gpGlobals->curtime; -} - - -//----------------------------------------------------------------------------- -// Purpose: called on level shutdown -//----------------------------------------------------------------------------- -void CAchievementMgr::LevelShutdownPreEntity() -{ - // make all achievements stop listening for events - FOR_EACH_MAP( m_mapAchievement, iAchievement ) - { - CBaseAchievement *pAchievement = m_mapAchievement[iAchievement]; - pAchievement->StopListeningForAllEvents(); - } - - // save global state if we have any changes - SaveGlobalStateIfDirty(); - - UploadUserData(); -} - -//----------------------------------------------------------------------------- -// Purpose: returns achievement for specified ID -//----------------------------------------------------------------------------- -CBaseAchievement *CAchievementMgr::GetAchievementByID( int iAchievementID ) -{ - int iAchievement = m_mapAchievement.Find( iAchievementID ); - if ( iAchievement != m_mapAchievement.InvalidIndex() ) - { - return m_mapAchievement[iAchievement]; - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: returns achievement with specified name. NOTE: this iterates through -// all achievements to find the name, intended for debugging purposes. -// Use GetAchievementByID for fast lookup. -//----------------------------------------------------------------------------- -CBaseAchievement *CAchievementMgr::GetAchievementByName( const char *pchName ) -{ - VPROF("GetAchievementByName"); - FOR_EACH_MAP_FAST( m_mapAchievement, i ) - { - CBaseAchievement *pAchievement = m_mapAchievement[i]; - if ( pAchievement && 0 == ( Q_stricmp( pchName, pAchievement->GetName() ) ) ) - return pAchievement; - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true if the achievement with the specified name has been achieved -//----------------------------------------------------------------------------- -bool CAchievementMgr::HasAchieved( const char *pchName ) -{ - CBaseAchievement *pAchievement = GetAchievementByName( pchName ); - if ( pAchievement ) - return pAchievement->IsAchieved(); - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: downloads user data from Steam or XBox Live -//----------------------------------------------------------------------------- -void CAchievementMgr::DownloadUserData() -{ - if ( IsPC() ) - { - if ( steamapicontext->SteamUserStats() ) - { - // request stat download; will get called back at OnUserStatsReceived when complete - steamapicontext->SteamUserStats()->RequestCurrentStats( CGameID( engine->GetAppID() ) ); - } - } - else if ( IsX360() ) - { -#if defined( _X360 ) - if ( XBX_GetPrimaryUserId() == INVALID_USER_ID ) - return; - - // Download achievements from XBox Live - bool bDownloadSuccessful = true; - int nTotalAchievements = 99; - uint bytes; - int ret = xboxsystem->EnumerateAchievements( XBX_GetPrimaryUserId(), 0, 0, nTotalAchievements, &bytes, 0, false ); - if ( ret != ERROR_SUCCESS ) - { - Warning( "Enumerate Achievements failed! Error %d", ret ); - bDownloadSuccessful = false; - } - - // Enumerate the achievements from Live - void *pBuffer = new byte[bytes]; - if ( bDownloadSuccessful ) - { - ret = xboxsystem->EnumerateAchievements( XBX_GetPrimaryUserId(), 0, 0, nTotalAchievements, pBuffer, bytes, false ); - - if ( ret != nTotalAchievements ) - { - Warning( "Enumerate Achievements failed! Error %d", ret ); - bDownloadSuccessful = false; - } - } - - if ( bDownloadSuccessful ) - { - // Give live a chance to mark achievements as unlocked, in case the achievement manager - // wasn't able to get that data (storage device missing, read failure, etc) - XACHIEVEMENT_DETAILS *pXboxAchievements = (XACHIEVEMENT_DETAILS*)pBuffer; - for ( int i = 0; i < nTotalAchievements; ++i ) - { - CBaseAchievement *pAchievement = GetAchievementByID( pXboxAchievements[i].dwId ); - if ( !pAchievement ) - continue; - - // Give Live a chance to claim the achievement as unlocked - if ( AchievementEarned( pXboxAchievements[i].dwFlags ) ) - { - pAchievement->SetAchieved( true ); - } - } - } - - delete pBuffer; -#endif // X360 - } -} - -const char *COM_GetModDirectory() -{ - static char modDir[MAX_PATH]; - if ( Q_strlen( modDir ) == 0 ) - { - const char *gamedir = CommandLine()->ParmValue("-game", CommandLine()->ParmValue( "-defaultgamedir", "hl2" ) ); - Q_strncpy( modDir, gamedir, sizeof(modDir) ); - if ( strchr( modDir, '/' ) || strchr( modDir, '\\' ) ) - { - Q_StripLastDir( modDir, sizeof(modDir) ); - int dirlen = Q_strlen( modDir ); - Q_strncpy( modDir, gamedir + dirlen, sizeof(modDir) - dirlen ); - } - } - - return modDir; -} - -//----------------------------------------------------------------------------- -// Purpose: uploads user data to steam -//----------------------------------------------------------------------------- -void CAchievementMgr::UploadUserData() -{ - if ( IsPC() ) - { - if ( steamapicontext->SteamUserStats() ) - { - // Upload current Steam client achievements & stats state to Steam. Will get called back at OnUserStatsStored when complete. - // Only values previously set via SteamUserStats() get uploaded - CGameID gameID( engine->GetAppID() ); - steamapicontext->SteamUserStats()->StoreStats( gameID ); - m_flTimeLastUpload = Plat_FloatTime(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: loads global state from file -//----------------------------------------------------------------------------- -void CAchievementMgr::LoadGlobalState() -{ - if ( IsX360() ) - { -#ifdef _X360 - if ( XBX_GetStorageDeviceId() == XBX_INVALID_STORAGE_ID || XBX_GetStorageDeviceId() == XBX_STORAGE_DECLINED ) - return; -#endif - } - - char szFilename[_MAX_PATH]; - - if ( IsX360() ) - { - Q_snprintf( szFilename, sizeof( szFilename ), "cfg:/%s_GameState.txt", COM_GetModDirectory() ); - } - else - { - Q_snprintf( szFilename, sizeof( szFilename ), "GameState.txt" ); - } - - KeyValues *pKV = new KeyValues("GameState" ); - if ( pKV->LoadFromFile( filesystem, szFilename, "MOD" ) ) - { - KeyValues *pNode = pKV->GetFirstSubKey(); - while ( pNode ) - { - // look up this achievement - int iAchievementID = pNode->GetInt( "id", 0 ); - if ( iAchievementID > 0 ) - { - CBaseAchievement *pAchievement = GetAchievementByID( iAchievementID ); - if ( pAchievement ) - { - // set the count - if ( pNode->GetInt( "value" ) > 0 ) - { - pAchievement->SetCount( pAchievement->GetGoal() ); - } - else if ( !pAchievement->HasComponents() ) - { - pAchievement->SetCount( pNode->GetInt( "data" ) ); - } - - // if this achievement has components, set the component bits - if ( pAchievement->HasComponents() ) - { - int64 iComponentBits = pNode->GetUint64( "data" ); - pAchievement->SetComponentBits( iComponentBits ); - } - pAchievement->SetProgressShown( pNode->GetInt( "msg" ) ); - pAchievement->EvaluateIsAlreadyAchieved(); - } - } - - pNode = pNode->GetNextKey(); - } - - m_bGlobalStateLoaded = true; - } -} - -//----------------------------------------------------------------------------- -// Purpose: saves global state to file -//----------------------------------------------------------------------------- - -void CAchievementMgr::SaveGlobalState( bool bAsync ) -{ - VPROF_BUDGET( "CAchievementMgr::SaveGlobalState", "Achievements" ); - - KeyValues *pKV = new KeyValues("GameState" ); - FOR_EACH_MAP( m_mapAchievement, i ) - { - CBaseAchievement *pAchievement = m_mapAchievement[i]; - if ( pAchievement->ShouldSaveGlobal() ) - { - KeyValues *pNode = pKV->CreateNewKey(); - pNode->SetInt( "id", pAchievement->GetAchievementID() ); - pNode->SetInt( "value", pAchievement->IsAchieved() ? 1 : 0 ); - if ( pAchievement->HasComponents() ) - { - pNode->SetUint64( "data", pAchievement->GetComponentBits() ); - } - else - { - if ( !pAchievement->IsAchieved() ) - { - pNode->SetInt( "data", pAchievement->GetCount() ); - } - } - pNode->SetInt( "msg", pAchievement->GetProgressShown() ); - } - } - - if ( !bAsync ) - { - WriteAchievementGlobalState( pKV ); - } - else - { -#ifndef _LINUX - g_AchievementSaveThread.WriteAchievementGlobalState( pKV ); -#endif - } - - m_bDirty = false; -} - -//----------------------------------------------------------------------------- -// Purpose: loads global state if we have not already successfully loaded it -//----------------------------------------------------------------------------- -void CAchievementMgr::EnsureGlobalStateLoaded() -{ - if ( !m_bGlobalStateLoaded ) - { - LoadGlobalState(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: saves global state to file if there have been any changes -//----------------------------------------------------------------------------- -void CAchievementMgr::SaveGlobalStateIfDirty( bool bAsync ) -{ - if ( m_bDirty ) - { - SaveGlobalState( bAsync ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: awards specified achievement -//----------------------------------------------------------------------------- -void CAchievementMgr::AwardAchievement( int iAchievementID ) -{ - CBaseAchievement *pAchievement = GetAchievementByID( iAchievementID ); - Assert( pAchievement ); - if ( !pAchievement ) - return; - - if ( !CheckAchievementsEnabled() ) - { - Msg( "Achievements disabled, ignoring achievement unlock for %s\n", pAchievement->GetName() ); - return; - } - - if ( pAchievement->IsAchieved() ) - { - if ( cc_achievement_debug.GetInt() > 0 ) - { - Msg( "Achievement award called but already achieved: %s\n", pAchievement->GetName() ); - } - return; - } - pAchievement->SetAchieved( true ); - - if ( cc_achievement_debug.GetInt() > 0 ) - { - Msg( "Achievement awarded: %s\n", pAchievement->GetName() ); - } - - // save state at next good opportunity. (Don't do it immediately, may hitch at bad time.) - m_bDirty = true; - - if ( IsPC() ) - { - if ( steamapicontext->SteamUserStats() ) - { - VPROF_BUDGET( "AwardAchievement", VPROF_BUDGETGROUP_STEAM ); - // set this achieved in the Steam client - CGameID gameID( engine->GetAppID() ); - bool bRet = steamapicontext->SteamUserStats()->SetAchievement( gameID, pAchievement->GetName() ); - // Assert( bRet ); - if ( bRet ) - { - // upload achievement to steam - UploadUserData(); - m_AchievementsAwarded.AddToTail( iAchievementID ); - } - } - -#ifdef TF_CLIENT_DLL - // PREITEMHACK: For now, just force our inventory to update whenever our achievements change - InventoryManager()->UpdateLoadoutsFromSteam( true ); -#endif - } - else if ( IsX360() ) - { -#ifdef _X360 - if ( xboxsystem ) - xboxsystem->AwardAchievement( XBX_GetPrimaryUserId(), iAchievementID ); -#endif - } -} - -//----------------------------------------------------------------------------- -// Purpose: clears state for all achievements -//----------------------------------------------------------------------------- -void CAchievementMgr::PreRestoreSavedGame() -{ - // load global state if we haven't already; X360 users may not have had a storage device available or selected at boot time - EnsureGlobalStateLoaded(); - - FOR_EACH_MAP( m_mapAchievement, i ) - { - m_mapAchievement[i]->PreRestoreSavedGame(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: clears state for all achievements -//----------------------------------------------------------------------------- -void CAchievementMgr::PostRestoreSavedGame() -{ - FOR_EACH_MAP( m_mapAchievement, i ) - { - m_mapAchievement[i]->PostRestoreSavedGame(); - } -} - -extern bool IsInCommentaryMode( void ); -//----------------------------------------------------------------------------- -// Purpose: checks if achievements are enabled -//----------------------------------------------------------------------------- -bool CAchievementMgr::CheckAchievementsEnabled() -{ - // if PC, Steam must be running and user logged in - if ( IsPC() && !LoggedIntoSteam() ) - { - Msg( "Achievements disabled: Steam not running.\n" ); - return false; - } - -#if defined( _X360 ) - uint state = XUserGetSigninState( XBX_GetPrimaryUserId() ); - if ( state == eXUserSigninState_NotSignedIn ) - { - Msg( "Achievements disabled: not signed in to XBox user account.\n" ); - return false; - } -#endif - - // can't be in commentary mode, user is invincible - if ( IsInCommentaryMode() ) - { - Msg( "Achievements disabled: in commentary mode.\n" ); - return false; - } - -#ifdef CLIENT_DLL - // achievements disabled if playing demo - if ( engine->IsPlayingDemo() ) - { - Msg( "Achievements disabled: demo playing.\n" ); - return false; - } -#endif // CLIENT_DLL - - if ( IsPC() ) - { - // Don't award achievements if cheats are turned on. - if ( WereCheatsEverOn() ) - { - // Cheats get turned on automatically if you run with -dev which many people do internally, so allow cheats if developer is turned on and we're not running - // on Steam public - if ( ( developer.GetInt() == 0 ) || !steamapicontext->SteamUtils() || ( k_EUniversePublic == steamapicontext->SteamUtils()->GetConnectedUniverse() ) ) - { - Msg( "Achievements disabled: cheats turned on in this app session.\n" ); - return false; - } - } - } - - return true; -} - -#ifdef CLIENT_DLL - -//----------------------------------------------------------------------------- -// Purpose: Returns the whether all of the local player's team mates are -// on her friends list, and if there are at least the specified # of -// teammates. Involves cross-process calls to Steam so this is mildly -// expensive, don't call this every frame. -//----------------------------------------------------------------------------- -bool CalcPlayersOnFriendsList( int iMinFriends ) -{ - // Got message during connection - if ( !g_PR ) - return false; - - Assert( g_pGameRules->IsMultiplayer() ); - - // Do a cheap rejection: check teammate count first to see if we even need to bother checking w/Steam - // Subtract 1 for the local player. - if ( CalcPlayerCount()-1 < iMinFriends ) - return false; - - // determine local player team - int iLocalPlayerIndex = GetLocalPlayerIndex(); - uint64 XPlayerUid = 0; - - if ( IsPC() ) - { - if ( !steamapicontext->SteamFriends() || !steamapicontext->SteamUtils() || !g_pGameRules->IsMultiplayer() ) - return false; - } - else if ( IsX360() ) - { - if ( !matchmaking ) - return false; - - XPlayerUid = XBX_GetPrimaryUserId(); - } - else - { - // other platforms...? - return false; - } - // Loop through the players - int iTotalFriends = 0; - for( int iPlayerIndex = 1 ; iPlayerIndex <= MAX_PLAYERS; iPlayerIndex++ ) - { - // find all players who are on the local player's team - if( ( iPlayerIndex != iLocalPlayerIndex ) && ( g_PR->IsConnected( iPlayerIndex ) ) ) - { - if ( IsPC() ) - { - player_info_t pi; - if ( !engine->GetPlayerInfo( iPlayerIndex, &pi ) ) - continue; - if ( !pi.friendsID ) - continue; - - // check and see if they're on the local player's friends list - CSteamID steamID( pi.friendsID, 1, steamapicontext->SteamUtils()->GetConnectedUniverse(), k_EAccountTypeIndividual ); - if ( !steamapicontext->SteamFriends()->HasFriend( steamID, /*k_EFriendFlagImmediate*/ 0x04 ) ) - continue; - } - else if ( IsX360() ) - { - uint64 XUid[1]; - XUid[0] = matchmaking->PlayerIdToXuid( iPlayerIndex ); - BOOL bFriend; -#ifdef _X360 - XUserAreUsersFriends( XPlayerUid, XUid, 1, &bFriend, NULL ); -#endif // _X360 - if ( !bFriend ) - continue; - } - - iTotalFriends++; - } - } - - return (iTotalFriends >= iMinFriends); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns whether there are a specified # of teammates who all belong -// to same clan as local player. Involves cross-process calls to Steam -// so this is mildly expensive, don't call this every frame. -//----------------------------------------------------------------------------- -bool CalcHasNumClanPlayers( int iClanTeammates ) -{ - Assert( g_pGameRules->IsMultiplayer() ); - - if ( IsPC() ) - { - // Do a cheap rejection: check teammate count first to see if we even need to bother checking w/Steam - // Subtract 1 for the local player. - if ( CalcPlayerCount()-1 < iClanTeammates ) - return false; - - if ( !steamapicontext->SteamFriends() || !steamapicontext->SteamUtils() || !g_pGameRules->IsMultiplayer() ) - return false; - - // determine local player team - int iLocalPlayerIndex = GetLocalPlayerIndex(); - - for ( int iClan = 0; iClan < steamapicontext->SteamFriends()->GetClanCount(); iClan++ ) - { - int iClanMembersOnTeam = 0; - CSteamID clanID = steamapicontext->SteamFriends()->GetClanByIndex( iClan ); - // enumerate all players - for( int iPlayerIndex = 1 ; iPlayerIndex <= MAX_PLAYERS; iPlayerIndex++ ) - { - if( ( iPlayerIndex != iLocalPlayerIndex ) && ( g_PR->IsConnected( iPlayerIndex ) ) ) - { - player_info_t pi; - if ( engine->GetPlayerInfo( iPlayerIndex, &pi ) && ( pi.friendsID ) ) - { - // check and see if they're on the local player's friends list - CSteamID steamID( pi.friendsID, 1, steamapicontext->SteamUtils()->GetConnectedUniverse(), k_EAccountTypeIndividual ); - if ( steamapicontext->SteamFriends()->IsUserInSource( steamID, clanID ) ) - { - iClanMembersOnTeam++; - if ( iClanMembersOnTeam == iClanTeammates ) - return true; - } - } - } - } - } - - return false; - } - else if ( IsX360() ) - { - // TODO: implement for 360 - return false; - } - else - { - // other platforms...? - return false; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the # of teammates of the local player -//----------------------------------------------------------------------------- -int CalcTeammateCount() -{ - Assert( g_pGameRules->IsMultiplayer() ); - - // determine local player team - int iLocalPlayerIndex = GetLocalPlayerIndex(); - int iLocalPlayerTeam = g_PR->GetTeam( iLocalPlayerIndex ); - - int iNumTeammates = 0; - for( int iPlayerIndex = 1 ; iPlayerIndex <= MAX_PLAYERS; iPlayerIndex++ ) - { - // find all players who are on the local player's team - if( ( iPlayerIndex != iLocalPlayerIndex ) && ( g_PR->IsConnected( iPlayerIndex ) ) && ( g_PR->GetTeam( iPlayerIndex ) == iLocalPlayerTeam ) ) - { - iNumTeammates++; - } - } - return iNumTeammates; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the # of teammates of the local player -//----------------------------------------------------------------------------- -int CalcPlayerCount() -{ - int iCount = 0; - for( int iPlayerIndex = 1 ; iPlayerIndex <= MAX_PLAYERS; iPlayerIndex++ ) - { - // find all players who are on the local player's team - if( g_PR->IsConnected( iPlayerIndex ) ) - { - iCount++; - } - } - return iCount; -} - -#endif // CLIENT_DLL - -//----------------------------------------------------------------------------- -// Purpose: Resets all achievements. For debugging purposes only -//----------------------------------------------------------------------------- -void CAchievementMgr::ResetAchievements() -{ - if ( !IsPC() ) - { - DevMsg( "Only available on PC\n" ); - return; - } - - if ( !LoggedIntoSteam() ) - { - Msg( "Steam not running, achievements disabled. Cannot reset achievements.\n" ); - return; - } - - CGameID gameID( engine->GetAppID() ); - FOR_EACH_MAP( m_mapAchievement, i ) - { - CBaseAchievement *pAchievement = m_mapAchievement[i]; - ResetAchievement_Internal( pAchievement ); - } - if ( steamapicontext->SteamUserStats() ) - { - steamapicontext->SteamUserStats()->StoreStats( gameID ); - } - SaveGlobalState(); -} - -void CAchievementMgr::ResetAchievement( int iAchievementID ) -{ - if ( !IsPC() ) - { - DevMsg( "Only available on PC\n" ); - return; - } - - if ( !LoggedIntoSteam() ) - { - Msg( "Steam not running, achievements disabled. Cannot reset achievements.\n" ); - return; - } - - CGameID gameID( engine->GetAppID() ); - CBaseAchievement *pAchievement = GetAchievementByID( iAchievementID ); - Assert( pAchievement ); - if ( pAchievement ) - { - ResetAchievement_Internal( pAchievement ); - if ( steamapicontext->SteamUserStats() ) - { - steamapicontext->SteamUserStats()->StoreStats( gameID ); - } - SaveGlobalState(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Resets all achievements. For debugging purposes only -//----------------------------------------------------------------------------- -void CAchievementMgr::PrintAchievementStatus() -{ - if ( IsPC() && !LoggedIntoSteam() ) - { - Msg( "Steam not running, achievements disabled. Cannot view or unlock achievements.\n" ); - return; - } - - Msg( "%42s %-20s %s\n", "Name:", "Status:", "Point value:" ); - int iTotalAchievements = 0, iTotalPoints = 0; - FOR_EACH_MAP( m_mapAchievement, i ) - { - CBaseAchievement *pAchievement = m_mapAchievement[i]; - - Msg( "%42s ", pAchievement->GetName() ); - - CFailableAchievement *pFailableAchievement = dynamic_cast( pAchievement ); - if ( pAchievement->IsAchieved() ) - { - Msg( "%-20s", "ACHIEVED" ); - } - else if ( pFailableAchievement && pFailableAchievement->IsFailed() ) - { - Msg( "%-20s", "FAILED" ); - } - else - { - char szBuf[255]; - Q_snprintf( szBuf, ARRAYSIZE( szBuf ), "(%d/%d)%s", pAchievement->GetCount(), pAchievement->GetGoal(), - pAchievement->IsActive() ? "" : " (inactive)" ); - Msg( "%-20s", szBuf ); - } - Msg( " %d ", pAchievement->GetPointValue() ); - pAchievement->PrintAdditionalStatus(); - Msg( "\n" ); - iTotalAchievements++; - iTotalPoints += pAchievement->GetPointValue(); - } - Msg( "Total achievements: %d Total possible points: %d\n", iTotalAchievements, iTotalPoints ); -} - -//----------------------------------------------------------------------------- -// Purpose: called when a game event is fired -//----------------------------------------------------------------------------- -void CAchievementMgr::FireGameEvent( IGameEvent *event ) -{ - VPROF_( "CAchievementMgr::FireGameEvent", 1, VPROF_BUDGETGROUP_STEAM, false, 0 ); - const char *name = event->GetName(); - if ( 0 == Q_strcmp( name, "entity_killed" ) ) - { -#ifdef GAME_DLL - CBaseEntity *pVictim = UTIL_EntityByIndex( event->GetInt( "entindex_killed", 0 ) ); - CBaseEntity *pAttacker = UTIL_EntityByIndex( event->GetInt( "entindex_attacker", 0 ) ); - CBaseEntity *pInflictor = UTIL_EntityByIndex( event->GetInt( "entindex_inflictor", 0 ) ); - OnKillEvent( pVictim, pAttacker, pInflictor, event ); -#endif // GAME_DLL - } - else if ( 0 == Q_strcmp( name, "game_init" ) ) - { -#ifdef GAME_DLL - // clear all state as though we were loading a saved game, but without loading the game - PreRestoreSavedGame(); - PostRestoreSavedGame(); -#endif // GAME_DLL - } -#ifdef CLIENT_DLL - else if ( 0 == Q_strcmp( name, "player_death" ) ) - { - CBaseEntity *pVictim = ClientEntityList().GetEnt( engine->GetPlayerForUserID( event->GetInt("userid") ) ); - CBaseEntity *pAttacker = ClientEntityList().GetEnt( engine->GetPlayerForUserID( event->GetInt("attacker") ) ); - OnKillEvent( pVictim, pAttacker, NULL, event ); - } - else if ( 0 == Q_strcmp( name, "localplayer_changeclass" ) ) - { - // keep track of when the player last changed class - m_flLastClassChangeTime = gpGlobals->curtime; - } - else if ( 0 == Q_strcmp( name, "localplayer_changeteam" ) ) - { - // keep track of the time of transitions to and from a game team - C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer(); - if ( pLocalPlayer ) - { - int iTeam = pLocalPlayer->GetTeamNumber(); - if ( iTeam > TEAM_SPECTATOR ) - { - if ( 0 == m_flTeamplayStartTime ) - { - // player transitioned from no/spectator team to a game team, mark the time - m_flTeamplayStartTime = gpGlobals->curtime; - } - } - else - { - // player transitioned to no/spectator team, clear the teamplay start time - m_flTeamplayStartTime = 0; - } - } - } - else if ( 0 == Q_strcmp( name, "teamplay_round_start" ) ) - { - if ( event->GetBool( "full_reset" ) ) - { - // we're starting a full round, clear miniround count - m_iMiniroundsCompleted = 0; - } - } - else if ( 0 == Q_strcmp( name, "teamplay_round_win" ) ) - { - if ( false == event->GetBool( "full_round", true ) ) - { - // we just finished a miniround but the round is continuing, increment miniround count - m_iMiniroundsCompleted ++; - } - } - else if ( 0 == Q_strcmp( name, "player_stats_updated" ) ) - { - FOR_EACH_MAP( m_mapAchievement, i ) - { - CBaseAchievement *pAchievement = m_mapAchievement[i]; - pAchievement->OnPlayerStatsUpdate(); - } - } -#endif // CLIENT_DLL -} - -//----------------------------------------------------------------------------- -// Purpose: called when a player or character has been killed -//----------------------------------------------------------------------------- -void CAchievementMgr::OnKillEvent( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event ) -{ - // can have a NULL victim on client if victim has never entered local player's PVS - if ( !pVictim ) - return; - - // if single-player game, calculate if the attacker is the local player and if the victim is the player enemy - bool bAttackerIsPlayer = false; - bool bVictimIsPlayerEnemy = false; -#ifdef GAME_DLL - if ( !g_pGameRules->IsMultiplayer() ) - { - CBasePlayer *pLocalPlayer = UTIL_GetLocalPlayer(); - if ( pLocalPlayer ) - { - if ( pAttacker == pLocalPlayer ) - { - bAttackerIsPlayer = true; - } - - CBaseCombatCharacter *pBCC = dynamic_cast( pVictim ); - if ( pBCC && ( D_HT == pBCC->IRelationType( pLocalPlayer ) ) ) - { - bVictimIsPlayerEnemy = true; - } - } - } -#else - C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer(); - bVictimIsPlayerEnemy = !pLocalPlayer->InSameTeam( pVictim ); - if ( pAttacker == pLocalPlayer ) - { - bAttackerIsPlayer = true; - } -#endif // GAME_DLL - - // look through all the kill event listeners and notify any achievements whose filters we pass - FOR_EACH_VEC( m_vecKillEventListeners, iAchievement ) - { - CBaseAchievement *pAchievement = m_vecKillEventListeners[iAchievement]; - - if ( !pAchievement->IsActive() ) - continue; - - // if this achievement only looks for kills where attacker is player and that is not the case here, skip this achievement - if ( ( pAchievement->GetFlags() & ACH_FILTER_ATTACKER_IS_PLAYER ) && !bAttackerIsPlayer ) - continue; - - // if this achievement only looks for kills where victim is killer enemy and that is not the case here, skip this achievement - if ( ( pAchievement->GetFlags() & ACH_FILTER_VICTIM_IS_PLAYER_ENEMY ) && !bVictimIsPlayerEnemy ) - continue; - -#if GAME_DLL - // if this achievement only looks for a particular victim class name and this victim is a different class, skip this achievement - const char *pVictimClassNameFilter = pAchievement->m_pVictimClassNameFilter; - if ( pVictimClassNameFilter && !pVictim->ClassMatches( pVictimClassNameFilter ) ) - continue; - - // if this achievement only looks for a particular inflictor class name and this inflictor is a different class, skip this achievement - const char *pInflictorClassNameFilter = pAchievement->m_pInflictorClassNameFilter; - if ( pInflictorClassNameFilter && ( ( NULL == pInflictor ) || !pInflictor->ClassMatches( pInflictorClassNameFilter ) ) ) - continue; - - // if this achievement only looks for a particular attacker class name and this attacker is a different class, skip this achievement - const char *pAttackerClassNameFilter = pAchievement->m_pAttackerClassNameFilter; - if ( pAttackerClassNameFilter && ( ( NULL == pAttacker ) || !pAttacker->ClassMatches( pAttackerClassNameFilter ) ) ) - continue; - - // if this achievement only looks for a particular inflictor entity name and this inflictor has a different name, skip this achievement - const char *pInflictorEntityNameFilter = pAchievement->m_pInflictorEntityNameFilter; - if ( pInflictorEntityNameFilter && ( ( NULL == pInflictor ) || !pInflictor->NameMatches( pInflictorEntityNameFilter ) ) ) - continue; -#endif // GAME_DLL - - // we pass all filters for this achievement, notify the achievement of the kill - pAchievement->Event_EntityKilled( pVictim, pAttacker, pInflictor, event ); - } -} - -void CAchievementMgr::OnAchievementEvent( int iAchievementID ) -{ - // handle event for specific achievement - CBaseAchievement *pAchievement = GetAchievementByID( iAchievementID ); - Assert( pAchievement ); - if ( pAchievement ) - { - if ( !pAchievement->IsAchieved() ) - { - pAchievement->IncrementCount(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: called when a map-fired achievement event occurs -//----------------------------------------------------------------------------- -void CAchievementMgr::OnMapEvent( const char *pchEventName ) -{ - Assert( pchEventName && *pchEventName ); - if ( !pchEventName || !*pchEventName ) - return; - - // see if this event matches the prefix for an achievement component - FOR_EACH_VEC( m_vecComponentListeners, iAchievement ) - { - CBaseAchievement *pAchievement = m_vecComponentListeners[iAchievement]; - Assert( pAchievement->m_pszComponentPrefix ); - if ( 0 == Q_strncmp( pchEventName, pAchievement->m_pszComponentPrefix, pAchievement->m_iComponentPrefixLen ) ) - { - // prefix matches, tell the achievement a component was found - pAchievement->OnComponentEvent( pchEventName ); - return; - } - } - - // look through all the map event listeners - FOR_EACH_VEC( m_vecMapEventListeners, iAchievement ) - { - CBaseAchievement *pAchievement = m_vecMapEventListeners[iAchievement]; - pAchievement->OnMapEvent( pchEventName ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Returns an achievement as it's abstract object. This interface is used by gameui.dll for getting achievement info. -// Input : index - -// Output : IBaseAchievement* -//----------------------------------------------------------------------------- -IAchievement* CAchievementMgr::GetAchievementByIndex( int index ) -{ - Assert( m_vecAchievement.IsValidIndex(index) ); - return (IAchievement*)m_vecAchievement[index]; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns total achievement count. This interface is used by gameui.dll for getting achievement info. -// Input : - -// Output : Count of achievements in manager's vector. -//----------------------------------------------------------------------------- -int CAchievementMgr::GetAchievementCount() -{ - return m_vecAchievement.Count(); -} - - -#if !defined(NO_STEAM) -//----------------------------------------------------------------------------- -// Purpose: called when stat download is complete -//----------------------------------------------------------------------------- -void CAchievementMgr::Steam_OnUserStatsReceived( UserStatsReceived_t *pUserStatsReceived ) -{ - Assert( steamapicontext->SteamUserStats() ); - if ( !steamapicontext->SteamUserStats() ) - return; - - if ( pUserStatsReceived->m_eResult != k_EResultOK ) - { - DevMsg( "CTFSteamStats: failed to download stats from Steam, EResult %d\n", pUserStatsReceived->m_eResult ); - return; - } - - CGameID gameID( engine->GetAppID() ); - - // run through the achievements and set their achieved state according to Steam data - FOR_EACH_MAP( m_mapAchievement, i ) - { - CBaseAchievement *pAchievement = m_mapAchievement[i]; - bool bAchieved = false; - bool bRet = steamapicontext->SteamUserStats()->GetAchievement( gameID, pAchievement->GetName(), &bAchieved ); - if ( bRet ) - { - // set local achievement state - pAchievement->SetAchieved( bAchieved ); - } - else - { - DevMsg( "ISteamUserStats::GetAchievement failed for %s\n", pAchievement->GetName() ); - } - - if ( pAchievement->StoreProgressInSteam() ) - { - int iValue; - char pszProgressName[1024]; - Q_snprintf( pszProgressName, 1024, "%s_STAT", pAchievement->GetName() ); - bRet = steamapicontext->SteamUserStats()->GetStat( gameID, pszProgressName, &iValue ); - if ( bRet ) - { - pAchievement->SetCount( iValue ); - } - else - { - DevMsg( "ISteamUserStats::GetStat failed to get progress value from Steam for achievement %s\n", pszProgressName ); - } - } - } - - // send an event to anyone else who needs Steam user stat data - IGameEvent *event = gameeventmanager->CreateEvent( "user_data_downloaded" ); - if ( event ) - { -#ifdef GAME_DLL - gameeventmanager->FireEvent( event ); -#else - gameeventmanager->FireEventClientSide( event ); -#endif - } - -#ifdef TF_CLIENT_DLL - InventoryManager()->UpdateLoadoutsFromSteam(); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: called when stat upload is complete -//----------------------------------------------------------------------------- -void CAchievementMgr::Steam_OnUserStatsStored( UserStatsStored_t *pUserStatsStored ) -{ - if ( k_EResultOK != pUserStatsStored->m_eResult ) - { - DevMsg( "CAchievementMgr: failed to upload stats to Steam, EResult %d\n", pUserStatsStored->m_eResult ); - } - - else - { - if ( m_AchievementsAwarded.Count() > 0 ) - { -#ifndef GAME_DLL - // send a message to the server about our achievement - if ( g_pGameRules && g_pGameRules->IsMultiplayer() ) - { - C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer(); - if ( pLocalPlayer ) - { - char cmd[256]; - int iPlayerID = pLocalPlayer->GetUserID(); - unsigned short mask = UTIL_GetAchievementEventMask(); - - Q_snprintf( cmd, sizeof( cmd ), "achievement_earned %d %d", m_AchievementsAwarded[0] ^ mask, ( iPlayerID ^ m_AchievementsAwarded[0] ) ^ mask ); - engine->ClientCmd_Unrestricted( cmd ); - } - } -#endif - m_AchievementsAwarded.Remove( 0 ); - } - - // for each achievement that has not been achieved - FOR_EACH_MAP( m_mapAchievement, iAchievement ) - { - CBaseAchievement *pAchievement = m_mapAchievement[iAchievement]; - - if ( !pAchievement->IsAchieved() ) - { - pAchievement->OnSteamUserStatsStored(); - } - } - } -} -#endif // !defined(NO_STEAM) - - -void CAchievementMgr::ResetAchievement_Internal( CBaseAchievement *pAchievement ) -{ - Assert( pAchievement ); - CGameID gameID( engine->GetAppID() ); - - if ( steamapicontext->SteamUserStats() ) - { - steamapicontext->SteamUserStats()->ClearAchievement( gameID, pAchievement->GetName() ); - } - - pAchievement->SetAchieved( false ); - pAchievement->SetCount( 0 ); - if ( pAchievement->HasComponents() ) - { - pAchievement->SetComponentBits( 0 ); - } - pAchievement->SetProgressShown( 0 ); - pAchievement->StopListeningForAllEvents(); - if ( pAchievement->IsActive() ) - { - pAchievement->ListenForEvents(); - } -} - -#ifdef CLIENT_DLL - -void MsgFunc_AchievementEvent( bf_read &msg ) -{ - int iAchievementID = (int) msg.ReadShort(); - CAchievementMgr *pAchievementMgr = dynamic_cast( engine->GetAchievementMgr() ); - if ( !pAchievementMgr ) - return; - pAchievementMgr->OnAchievementEvent( iAchievementID ); -} - -#ifdef _DEBUG -CON_COMMAND_F( achievement_reset_all, "Clears all achievements", FCVAR_DEVELOPMENTONLY ) -{ - CAchievementMgr *pAchievementMgr = dynamic_cast( engine->GetAchievementMgr() ); - if ( !pAchievementMgr ) - return; - pAchievementMgr->ResetAchievements(); -} - -CON_COMMAND_F( achievement_reset, " Clears specified achievement", FCVAR_DEVELOPMENTONLY ) -{ - CAchievementMgr *pAchievementMgr = dynamic_cast( engine->GetAchievementMgr() ); - if ( !pAchievementMgr ) - return; - - if ( 2 != args.ArgC() ) - { - Msg( "Usage: achievement_reset \n" ); - return; - } - CBaseAchievement *pAchievement = pAchievementMgr->GetAchievementByName( args[1] ); - if ( !pAchievement ) - { - Msg( "Achievement %s not found\n", args[1] ); - return; - } - pAchievementMgr->ResetAchievement( pAchievement->GetAchievementID() ); - -} - -CON_COMMAND_F( achievement_status, "Shows status of all achievement", FCVAR_CHEAT ) -{ - CAchievementMgr *pAchievementMgr = dynamic_cast( engine->GetAchievementMgr() ); - if ( !pAchievementMgr ) - return; - pAchievementMgr->PrintAchievementStatus(); -} - -CON_COMMAND_F( achievement_unlock, " Unlocks achievement", FCVAR_DEVELOPMENTONLY ) -{ - CAchievementMgr *pAchievementMgr = dynamic_cast( engine->GetAchievementMgr() ); - if ( !pAchievementMgr ) - return; - - if ( 2 != args.ArgC() ) - { - Msg( "Usage: achievement_unlock \n" ); - return; - } - CBaseAchievement *pAchievement = pAchievementMgr->GetAchievementByName( args[1] ); - if ( !pAchievement ) - { - Msg( "Achievement %s not found\n", args[1] ); - return; - } - pAchievementMgr->AwardAchievement( pAchievement->GetAchievementID() ); -} - -CON_COMMAND_F( achievement_unlock_all, "Unlocks all achievements", FCVAR_DEVELOPMENTONLY ) -{ - CAchievementMgr *pAchievementMgr = dynamic_cast( engine->GetAchievementMgr() ); - if ( !pAchievementMgr ) - return; - - int iCount = pAchievementMgr->GetAchievementCount(); - for ( int i = 0; i < iCount; i++ ) - { - IAchievement *pAchievement = pAchievementMgr->GetAchievementByIndex( i ); - if ( !pAchievement->IsAchieved() ) - { - pAchievementMgr->AwardAchievement( pAchievement->GetAchievementID() ); - } - } -} - -CON_COMMAND_F( achievement_evaluate, " Causes failable achievement to be evaluated", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT ) -{ - CAchievementMgr *pAchievementMgr = dynamic_cast( engine->GetAchievementMgr() ); - if ( !pAchievementMgr ) - return; - - if ( 2 != args.ArgC() ) - { - Msg( "Usage: achievement_evaluate \n" ); - return; - } - CBaseAchievement *pAchievement = pAchievementMgr->GetAchievementByName( args[1] ); - if ( !pAchievement ) - { - Msg( "Achievement %s not found\n", args[1] ); - return; - } - - CFailableAchievement *pFailableAchievement = dynamic_cast( pAchievement ); - Assert( pFailableAchievement ); - if ( pFailableAchievement ) - { - pFailableAchievement->OnEvaluationEvent(); - } -} - -CON_COMMAND_F( achievement_test_friend_count, "Counts the # of teammates on local player's friends list", FCVAR_DEVELOPMENTONLY ) -{ - CAchievementMgr *pAchievementMgr = dynamic_cast( engine->GetAchievementMgr() ); - if ( !pAchievementMgr ) - return; - if ( 2 != args.ArgC() ) - { - Msg( "Usage: achievement_test_friend_count \n" ); - return; - } - int iMinFriends = atoi( args[1] ); - bool bRet = CalcPlayersOnFriendsList( iMinFriends ); - Msg( "You %s have at least %d friends in the game.\n", bRet ? "do" : "do not", iMinFriends ); -} - -CON_COMMAND_F( achievement_test_clan_count, "Determines if specified # of teammates belong to same clan w/local player", FCVAR_DEVELOPMENTONLY ) -{ - CAchievementMgr *pAchievementMgr = dynamic_cast( engine->GetAchievementMgr() ); - if ( !pAchievementMgr ) - return; - - if ( 2 != args.ArgC() ) - { - Msg( "Usage: achievement_test_clan_count <# of clan teammates>\n" ); - return; - } - int iClanPlayers = atoi( args[1] ); - bool bRet = CalcHasNumClanPlayers( iClanPlayers ); - Msg( "There %s %d players who you're in a Steam group with.\n", bRet ? "are" : "are not", iClanPlayers ); -} - -CON_COMMAND_F( achievement_mark_dirty, "Mark achievement data as dirty", FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT ) -{ - CAchievementMgr *pAchievementMgr = dynamic_cast( engine->GetAchievementMgr() ); - if ( !pAchievementMgr ) - return; - pAchievementMgr->SetDirty( true ); -} -#endif // _DEBUG - -#endif // CLIENT_DLL - -//----------------------------------------------------------------------------- -// Purpose: helper function to get entity model name -//----------------------------------------------------------------------------- -const char *GetModelName( CBaseEntity *pBaseEntity ) -{ - CBaseAnimating *pBaseAnimating = dynamic_cast( pBaseEntity ); - if ( pBaseAnimating ) - { - CStudioHdr *pStudioHdr = pBaseAnimating->GetModelPtr(); - if ( pStudioHdr ) - { - return pStudioHdr->pszName(); - } - } - - return ""; -} diff --git a/game/shared/achievementmgr.h b/game/shared/achievementmgr.h deleted file mode 100644 index 939c35330..000000000 --- a/game/shared/achievementmgr.h +++ /dev/null @@ -1,115 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef ACHIEVEMENTMGR_H -#define ACHIEVEMENTMGR_H -#ifdef _WIN32 -#pragma once -#endif -#include "baseachievement.h" -#include "GameEventListener.h" -#include "hl2orange.spa.h" -#include "iachievementmgr.h" -#include "utlmap.h" -#include "steam/steam_api.h" - -class CAchievementMgr : public CAutoGameSystemPerFrame, public CGameEventListener, public IAchievementMgr -{ -public: - CAchievementMgr(); - - virtual bool Init(); - virtual void PostInit(); - virtual void Shutdown(); - virtual void LevelInitPreEntity(); - virtual void LevelShutdownPreEntity(); - virtual void InitializeAchievements(); - virtual void Update( float frametime ); - - void OnMapEvent( const char *pchEventName ); - - // Interfaces exported to other dlls for achievement list queries - IAchievement* GetAchievementByIndex( int index ); - int GetAchievementCount(); - - CBaseAchievement *GetAchievementByID( int iAchievementID ); - CUtlMap &GetAchievements() { return m_mapAchievement; } - - CBaseAchievement *GetAchievementByName( const char *pchName ); - bool HasAchieved( const char *pchName ); - - void UploadUserData(); - void DownloadUserData(); - void SaveGlobalState( bool bAsync = false ); - void LoadGlobalState(); - void SaveGlobalStateIfDirty( bool bAsync = false ); - void EnsureGlobalStateLoaded(); - void AwardAchievement( int iAchievementID ); - void PreRestoreSavedGame(); - void PostRestoreSavedGame(); - void ResetAchievements(); - void ResetAchievement( int iAchievementID ); - void PrintAchievementStatus(); - float GetLastClassChangeTime() { return m_flLastClassChangeTime; } - float GetTeamplayStartTime() { return m_flTeamplayStartTime; } - int GetMiniroundsCompleted() { return (int)m_iMiniroundsCompleted; } - const char *GetMapName() { return m_szMap; } - void OnAchievementEvent( int iAchievementID ); - void SetDirty( bool bDirty ) { m_bDirty = bDirty; } - bool CheckAchievementsEnabled(); - bool LoggedIntoSteam() { return ( steamapicontext->SteamUser() && steamapicontext->SteamUserStats() && steamapicontext->SteamUser()->BLoggedOn() ); } - float GetTimeLastUpload() { return m_flTimeLastUpload; } // time we last uploaded to Steam - - bool WereCheatsEverOn( void ) { return m_bCheatsEverOn; } - -#if !defined(NO_STEAM) - STEAM_CALLBACK( CAchievementMgr, Steam_OnUserStatsReceived, UserStatsReceived_t, m_CallbackUserStatsReceived ); - STEAM_CALLBACK( CAchievementMgr, Steam_OnUserStatsStored, UserStatsStored_t, m_CallbackUserStatsStored ); -#endif - -private: - void FireGameEvent( IGameEvent *event ); - void OnKillEvent( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event ); - void ResetAchievement_Internal( CBaseAchievement *pAchievement ); - - CUtlMap m_mapAchievement; // map of all achievements - CUtlVector m_vecAchievement; // vector of all achievements for accessing by index - CUtlVector m_vecKillEventListeners; // vector of achievements that are listening for kill events - CUtlVector m_vecMapEventListeners; // vector of achievements that are listening for map events - CUtlVector m_vecComponentListeners; // vector of achievements that are listening for components that make up an achievement - - float m_flLevelInitTime; - - float m_flLastClassChangeTime; // Time when player last changed class - float m_flTeamplayStartTime; // Time when player joined a non-spectating team. Not updated if she switches game teams; cleared if she joins spectator - float m_iMiniroundsCompleted; // # of minirounds played since game start (for maps that have minirounds) - char m_szMap[MAX_PATH]; // file base of map name, cached since we access it frequently in this form - bool m_bDirty; // do we have interesting state that needs to be saved - bool m_bGlobalStateLoaded; // have we loaded global state - bool m_bCheatsEverOn; // have cheats ever been turned on in this level - float m_flTimeLastUpload; // last time we uploaded to Steam - - CUtlVector m_AchievementsAwarded; -}; - -// helper functions -const char *GetModelName( CBaseEntity *pBaseEntity ); - -#ifdef CLIENT_DLL -bool CalcPlayersOnFriendsList( int iMinPlayers ); -bool CalcHasNumClanPlayers( int iClanTeammates ); -int CalcPlayerCount(); -int CalcTeammateCount(); -#endif // CLIENT - -class IMatchmaking; -extern ConVar cc_achievement_debug; -extern IMatchmaking *matchmaking; - -#ifdef CLIENT_DLL -void MsgFunc_AchievementEvent( bf_read &msg ); -#endif // CLIENT_DLL -#endif // ACHIEVEMENTMGR_H diff --git a/game/shared/achievements_hlx.cpp b/game/shared/achievements_hlx.cpp deleted file mode 100644 index 11054d09f..000000000 --- a/game/shared/achievements_hlx.cpp +++ /dev/null @@ -1,253 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - - -#include "cbase.h" - -#ifdef GAME_DLL - -// this gets compiled in for HL2 + Ep(X) only -#if ( defined( HL2_DLL ) || defined( HL2_EPISODIC ) ) && ( !defined ( PORTAL ) ) - -#include "baseachievement.h" -#include "prop_combine_ball.h" -#include "combine_mine.h" -#include "basegrenade_shared.h" -#include "basehlcombatweapon_shared.h" -#include "ammodef.h" - -class CAchievementHLXKillWithPhysicsObjects : public CBaseAchievement -{ - void Init() - { - SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_WITH_GAME ); - SetInflictorFilter( "prop_physics" ); - SetGoal( 30 ); - - if ( IsPC() ) - { - // only in Ep2 for PC. (Shared across HLX for X360.) - SetGameDirFilter( "ep2" ); - } - } - - virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event ) - { - int iDamageBits = event->GetInt( "damagebits" ); - // was victim killed with crushing damage? - if ( iDamageBits & DMG_CRUSH ) - { - IncrementCount(); - } - } - -}; -DECLARE_ACHIEVEMENT( CAchievementHLXKillWithPhysicsObjects, ACHIEVEMENT_HLX_KILL_ENEMIES_WITHPHYSICS, "HLX_KILL_ENEMIES_WITHPHYSICS", 5 ); - -class CAchievementHLXKillWithHopper : public CBaseAchievement -{ - void Init() - { - SetFlags( ACH_LISTEN_KILL_ENEMY_EVENTS | ACH_SAVE_WITH_GAME ); - SetAttackerFilter( "combine_mine" ); - SetGoal( 1 ); - - if ( IsPC() ) - { - // only in Ep2 for PC. (Shared across HLX for X360.) - SetGameDirFilter( "ep2" ); - } - } - - virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event ) - { - // If we get here, a combine mine has killed a player enemy. Now check and see if the player planted it - CBounceBomb *pBounceBomb = dynamic_cast( pAttacker ); - if ( pBounceBomb && pBounceBomb->IsPlayerPlaced() ) - { - IncrementCount(); - } - } -}; -DECLARE_ACHIEVEMENT( CAchievementHLXKillWithHopper, ACHIEVEMENT_HLX_KILL_ENEMY_WITHHOPPERMINE, "HLX_KILL_ENEMY_WITHHOPPERMINE", 5 ); - -class CAchievementHLXKillWithManhack : public CBaseAchievement -{ - void Init() - { - SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_WITH_GAME ); - SetInflictorFilter( "npc_manhack" ); - SetGoal( 5 ); - - if ( IsPC() ) - { - // only in HL2 for PC. (Shared across HLX for X360.) - SetGameDirFilter( "hl2" ); - } - } - - virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event ) - { - // We've already filtered to only get called when a player enemy gets killed with a manhack. Now just check for the - // case of player smashing manhack into something, in which case the manhack is both the victim and inflictor. - // If that's not the case, this is a player kill w/manhack. - if ( pVictim != pInflictor ) - { - IncrementCount(); - } - } -}; -DECLARE_ACHIEVEMENT( CAchievementHLXKillWithManhack, ACHIEVEMENT_HLX_KILL_ENEMIES_WITHMANHACK, "HLX_KILL_ENEMIES_WITHMANHACK", 5 ); - -class CAchievementHLXKillSoldierWithOwnGrenade : public CBaseAchievement -{ -protected: - void Init() - { - SetFlags( ACH_LISTEN_KILL_ENEMY_EVENTS | ACH_SAVE_WITH_GAME ); - SetInflictorFilter( "npc_grenade_frag" ); - SetVictimFilter( "npc_combine_s" ); - SetGoal( 1 ); - - if ( IsPC() ) - { - // only in Ep2 for PC. (Shared across HLX for X360.) - SetGameDirFilter( "ep2" ); - } - } - - virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event ) - { - CBaseGrenade *pGrenade = dynamic_cast( pInflictor ); - if ( pGrenade ) - { - CBaseEntity *pThrower = pGrenade->GetThrower(); - CBaseEntity *pOriginalThrower = pGrenade->GetOriginalThrower(); - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - // check if player was most recent thrower, but the victim was the original thrower - if ( ( pPlayer == pThrower ) && ( pOriginalThrower == pVictim ) ) - { - IncrementCount(); - } - } - } -}; -DECLARE_ACHIEVEMENT( CAchievementHLXKillSoldierWithOwnGrenade, ACHIEVEMENT_HLX_KILL_SOLDIER_WITHHISGRENADE, "HLX_KILL_SOLDIER_WITHHISGRENADE", 10 ); - -class CAchievementHLXKillWithOneEnergyBall : public CBaseAchievement -{ -protected: - virtual void Init() - { - SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_WITH_GAME ); - SetInflictorFilter( "prop_combine_ball" ); - SetGoal( 1 ); - m_pLastInflictor = NULL; - m_iLocalCount = 0; - - if ( IsPC() ) - { - // only in Ep1 for PC. (Shared across HLX for X360.) - SetGameDirFilter( "episodic" ); - } - } - - virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event ) - { - // to count # of kills with same energy ball, keep track of previous inflictor - if ( m_pLastInflictor != NULL && pInflictor != m_pLastInflictor ) - { - // new inflictor, start the count over at 1 - m_iLocalCount = 1; - } - else - { - // same inflictor, keep counting - m_iLocalCount++; - if ( 5 == m_iLocalCount ) - { - IncrementCount(); - } - } - // keep track of last inflictor - m_pLastInflictor = pInflictor; - } - CBaseEntity *m_pLastInflictor; - int m_iLocalCount; -}; -DECLARE_ACHIEVEMENT( CAchievementHLXKillWithOneEnergyBall, ACHIEVEMENT_HLX_KILL_ENEMIES_WITHONEENERGYBALL, "HLX_KILL_ENEMIES_WITHONEENERGYBALL", 5 ); - -class CAchievementHLXKillEliteSoldierWithOwnEnergyBall : public CBaseAchievement -{ -protected: - virtual void Init() - { - SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_WITH_GAME ); - SetInflictorFilter( "prop_combine_ball" ); - SetVictimFilter( "npc_combine_s" ); - SetGoal( 1 ); - - if ( IsPC() ) - { - // only in Ep2 for PC. (Shared across HLX for X360.) - SetGameDirFilter( "episodic" ); - } - } - - virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event ) - { - CPropCombineBall *pBall = dynamic_cast( pInflictor ); - if ( pBall ) - { - // determine original owner of this ball - CBaseEntity *pOriginalOwner = pBall->GetOriginalOwner(); - // see if original owner is the victim - if ( pOriginalOwner && ( pOriginalOwner == pVictim ) ) - { - IncrementCount(); - } - } - } -}; -DECLARE_ACHIEVEMENT( CAchievementHLXKillEliteSoldierWithOwnEnergyBall, ACHIEVEMENT_HLX_KILL_ELITESOLDIER_WITHHISENERGYBALL, "HLX_KILL_ELITESOLDIER_WITHHISENERGYBALL", 10 ); - -//----------------------------------------------------------------------------- -// Purpose: Counts the accumulated # of primary and secondary attacks from all -// weapons (except grav gun). If bBulletOnly is true, only counts -// attacks with ammo that does bullet damage. -//----------------------------------------------------------------------------- -int CalcPlayerAttacks( bool bBulletOnly ) -{ - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - CAmmoDef *pAmmoDef = GetAmmoDef(); - if ( !pPlayer || !pAmmoDef ) - return 0; - - int iTotalAttacks = 0; - int iWeapons = pPlayer->WeaponCount(); - for ( int i = 0; i < iWeapons; i++ ) - { - CBaseHLCombatWeapon *pWeapon = dynamic_cast( pPlayer->GetWeapon( i ) ); - if ( pWeapon ) - { - // add primary attacks if we were asked for all attacks, or only if it uses bullet ammo if we were asked to count bullet attacks - if ( !bBulletOnly || ( pAmmoDef->m_AmmoType[pWeapon->GetPrimaryAmmoType()].nDamageType == DMG_BULLET ) ) - { - iTotalAttacks += pWeapon->m_iPrimaryAttacks; - } - // add secondary attacks if we were asked for all attacks, or only if it uses bullet ammo if we were asked to count bullet attacks - if ( !bBulletOnly || ( pAmmoDef->m_AmmoType[pWeapon->GetSecondaryAmmoType()].nDamageType == DMG_BULLET ) ) - { - iTotalAttacks += pWeapon->m_iSecondaryAttacks; - } - } - } - return iTotalAttacks; -} - -#endif // ( defined( HL2_DLL ) || defined( HL2_EPISODIC ) ) && ( !defined ( PORTAL ) ) - -#endif // GAME_DLL diff --git a/game/shared/activitylist.cpp b/game/shared/activitylist.cpp deleted file mode 100644 index 4af3484f9..000000000 --- a/game/shared/activitylist.cpp +++ /dev/null @@ -1,1960 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "ai_activity.h" -#include "activitylist.h" -#include "stringregistry.h" -#include "isaverestore.h" - -#include "filesystem.h" -#include -#include "utldict.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern IFileSystem *filesystem; - -// NOTE: If CStringRegistry allowed storing arbitrary data, we could just use that. -// in this case we have the "isPrivate" member and the replacement rules -// (activityIndex can be reused by private activities), so a custom table is necessary -struct activitylist_t -{ - int activityIndex; - unsigned short stringKey; - short isPrivate; -}; - -CUtlVector g_ActivityList; - -static CUtlDict< CActivityRemapCache, int > m_ActivityRemapDatabase; - -// This stores the actual activity names. Also, the string ID in the registry is simply an index -// into the g_ActivityList array. -CStringRegistry g_ActivityStrings; - -// this is just here to accelerate adds -static int g_HighestActivity = 0; - -int g_nActivityListVersion = 1; - - -void ActivityList_Init( void ) -{ - g_HighestActivity = 0; -} - -void ActivityList_Free( void ) -{ - g_ActivityStrings.ClearStrings(); - g_ActivityList.Purge(); - m_ActivityRemapDatabase.Purge(); - - // So studiohdrs can reindex activity indices - ++g_nActivityListVersion; -} - -// add a new activity to the database -activitylist_t *ActivityList_AddActivityEntry( const char *pName, int iActivityIndex, bool isPrivate ) -{ - MEM_ALLOC_CREDIT(); - int index = g_ActivityList.AddToTail(); - activitylist_t *pList = &g_ActivityList[index]; - pList->activityIndex = iActivityIndex; - pList->stringKey = g_ActivityStrings.AddString( pName, index ); - pList->isPrivate = isPrivate; - - // UNDONE: This implies that ALL shared activities are added before ANY custom activities - // UNDONE: Segment these instead? It's a 32-bit int, how many activities do we need? - if ( iActivityIndex > g_HighestActivity ) - { - g_HighestActivity = iActivityIndex; - } - - return pList; -} - -// get the database entry from a string -static activitylist_t *ListFromString( const char *pString ) -{ - // just use the string registry to do this search/map - int stringID = g_ActivityStrings.GetStringID( pString ); - if ( stringID < 0 ) - return NULL; - - return &g_ActivityList[stringID]; -} - -// Get the database entry for an index -static activitylist_t *ListFromActivity( int activityIndex ) -{ - // ugly linear search - for ( int i = 0; i < g_ActivityList.Size(); i++ ) - { - if ( g_ActivityList[i].activityIndex == activityIndex ) - { - return &g_ActivityList[i]; - } - } - - return NULL; -} - -bool ActivityList_RegisterSharedActivity( const char *pszActivityName, int iActivityIndex ) -{ - // UNDONE: Do we want to do these checks when not in developer mode? or maybe DEBUG only? - // They really only matter when you change the list of code controlled activities. IDs - // for content controlled activities never collide because they are generated. - - // technically order isn't dependent, but it's too damn easy to forget to add new ACT_'s to all three lists. - static int lastActivityIndex = -1; - Assert( iActivityIndex < LAST_SHARED_ACTIVITY && (iActivityIndex == lastActivityIndex + 1 || iActivityIndex == 0) ); - lastActivityIndex = iActivityIndex; - - // first, check to make sure the slot we're asking for is free. It must be for - // a shared activity. - activitylist_t *pList = ListFromString( pszActivityName ); - if ( !pList ) - { - pList = ListFromActivity( iActivityIndex ); - } - - if ( pList ) - { - Warning( "***\nShared activity collision! %s<->%s\n***\n", pszActivityName, g_ActivityStrings.GetStringForKey( pList->stringKey ) ); - Assert(0); - return false; - } - // ---------------------------------------------------------------- - - ActivityList_AddActivityEntry( pszActivityName, iActivityIndex, false ); - return true; -} - - -Activity ActivityList_RegisterPrivateActivity( const char *pszActivityName ) -{ - activitylist_t *pList = ListFromString( pszActivityName ); - if ( pList ) - { - // this activity is already in the list. If the activity we collided with is also private, - // then the collision is OK. Otherwise, it's a bug. - if ( pList->isPrivate ) - { - return (Activity)pList->activityIndex; - } - else - { - // this private activity collides with a shared activity. That is not allowed. - Warning( "***\nShared<->Private Activity collision!\n***\n" ); - Assert(0); - return ACT_INVALID; - } - } - - pList = ActivityList_AddActivityEntry( pszActivityName, g_HighestActivity+1, true ); - return (Activity)pList->activityIndex; -} - -// Get the index for a given activity name -// Done at load time for all models -int ActivityList_IndexForName( const char *pszActivityName ) -{ - // this is a fast O(lgn) search (actually does 2 O(lgn) searches) - activitylist_t *pList = ListFromString( pszActivityName ); - - if ( pList ) - { - return pList->activityIndex; - } - - return -1; -} - -// Get the name for a given index -// This should only be used in debug code, it does a linear search -// But at least it only compares integers -const char *ActivityList_NameForIndex( int activityIndex ) -{ - activitylist_t *pList = ListFromActivity( activityIndex ); - if ( pList ) - { - return g_ActivityStrings.GetStringForKey( pList->stringKey ); - } - return NULL; -} - -void ActivityList_RegisterSharedActivities( void ) -{ - REGISTER_SHARED_ACTIVITY( ACT_RESET ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE ); - REGISTER_SHARED_ACTIVITY( ACT_TRANSITION ); - REGISTER_SHARED_ACTIVITY( ACT_COVER ); - REGISTER_SHARED_ACTIVITY( ACT_COVER_MED ); - REGISTER_SHARED_ACTIVITY( ACT_COVER_LOW ); - REGISTER_SHARED_ACTIVITY( ACT_WALK ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_AIM ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_CROUCH ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_CROUCH_AIM ); - REGISTER_SHARED_ACTIVITY( ACT_RUN ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_CROUCH ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_CROUCH_AIM ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_PROTECTED ); - REGISTER_SHARED_ACTIVITY( ACT_SCRIPT_CUSTOM_MOVE ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK1 ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK2 ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK1_LOW ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK2_LOW ); - REGISTER_SHARED_ACTIVITY( ACT_DIESIMPLE ); - REGISTER_SHARED_ACTIVITY( ACT_DIEBACKWARD ); - REGISTER_SHARED_ACTIVITY( ACT_DIEFORWARD ); - REGISTER_SHARED_ACTIVITY( ACT_DIEVIOLENT ); - REGISTER_SHARED_ACTIVITY( ACT_DIERAGDOLL ); - REGISTER_SHARED_ACTIVITY( ACT_FLY ); - REGISTER_SHARED_ACTIVITY( ACT_HOVER ); - REGISTER_SHARED_ACTIVITY( ACT_GLIDE ); - REGISTER_SHARED_ACTIVITY( ACT_SWIM ); - REGISTER_SHARED_ACTIVITY( ACT_JUMP ); - REGISTER_SHARED_ACTIVITY( ACT_HOP ); - REGISTER_SHARED_ACTIVITY( ACT_LEAP ); - REGISTER_SHARED_ACTIVITY( ACT_LAND ); - REGISTER_SHARED_ACTIVITY( ACT_CLIMB_UP ); - REGISTER_SHARED_ACTIVITY( ACT_CLIMB_DOWN ); - REGISTER_SHARED_ACTIVITY( ACT_CLIMB_DISMOUNT ); - REGISTER_SHARED_ACTIVITY( ACT_SHIPLADDER_UP ); - REGISTER_SHARED_ACTIVITY( ACT_SHIPLADDER_DOWN ); - REGISTER_SHARED_ACTIVITY( ACT_STRAFE_LEFT ); - REGISTER_SHARED_ACTIVITY( ACT_STRAFE_RIGHT ); - REGISTER_SHARED_ACTIVITY( ACT_ROLL_LEFT ); - REGISTER_SHARED_ACTIVITY( ACT_ROLL_RIGHT ); - REGISTER_SHARED_ACTIVITY( ACT_TURN_LEFT ); - REGISTER_SHARED_ACTIVITY( ACT_TURN_RIGHT ); - REGISTER_SHARED_ACTIVITY( ACT_CROUCH ); - REGISTER_SHARED_ACTIVITY( ACT_CROUCHIDLE ); - REGISTER_SHARED_ACTIVITY( ACT_STAND ); - REGISTER_SHARED_ACTIVITY( ACT_USE ); - REGISTER_SHARED_ACTIVITY( ACT_SIGNAL1 ); - REGISTER_SHARED_ACTIVITY( ACT_SIGNAL2 ); - REGISTER_SHARED_ACTIVITY( ACT_SIGNAL3 ); - - REGISTER_SHARED_ACTIVITY( ACT_SIGNAL_ADVANCE ); - REGISTER_SHARED_ACTIVITY( ACT_SIGNAL_FORWARD ); - REGISTER_SHARED_ACTIVITY( ACT_SIGNAL_GROUP ); - REGISTER_SHARED_ACTIVITY( ACT_SIGNAL_HALT ); - REGISTER_SHARED_ACTIVITY( ACT_SIGNAL_LEFT ); - REGISTER_SHARED_ACTIVITY( ACT_SIGNAL_RIGHT ); - REGISTER_SHARED_ACTIVITY( ACT_SIGNAL_TAKECOVER ); - - REGISTER_SHARED_ACTIVITY( ACT_LOOKBACK_RIGHT ); - REGISTER_SHARED_ACTIVITY( ACT_LOOKBACK_LEFT ); - REGISTER_SHARED_ACTIVITY( ACT_COWER ); - REGISTER_SHARED_ACTIVITY( ACT_SMALL_FLINCH ); - REGISTER_SHARED_ACTIVITY( ACT_BIG_FLINCH ); - REGISTER_SHARED_ACTIVITY( ACT_MELEE_ATTACK1 ); - REGISTER_SHARED_ACTIVITY( ACT_MELEE_ATTACK2 ); - REGISTER_SHARED_ACTIVITY( ACT_RELOAD ); - REGISTER_SHARED_ACTIVITY( ACT_RELOAD_START ); - REGISTER_SHARED_ACTIVITY( ACT_RELOAD_FINISH ); - REGISTER_SHARED_ACTIVITY( ACT_RELOAD_LOW ); - REGISTER_SHARED_ACTIVITY( ACT_ARM ); - REGISTER_SHARED_ACTIVITY( ACT_DISARM ); - - REGISTER_SHARED_ACTIVITY( ACT_DROP_WEAPON ); - REGISTER_SHARED_ACTIVITY( ACT_DROP_WEAPON_SHOTGUN ); - - REGISTER_SHARED_ACTIVITY( ACT_PICKUP_GROUND ); - REGISTER_SHARED_ACTIVITY( ACT_PICKUP_RACK ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE_ANGRY ); - - REGISTER_SHARED_ACTIVITY( ACT_IDLE_RELAXED ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE_STIMULATED ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE_AGITATED ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE_STEALTH ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE_HURT ); - - REGISTER_SHARED_ACTIVITY( ACT_WALK_RELAXED ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_STIMULATED ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_AGITATED ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_STEALTH ); - - REGISTER_SHARED_ACTIVITY( ACT_RUN_RELAXED ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_STIMULATED ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_AGITATED ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_STEALTH ); - - REGISTER_SHARED_ACTIVITY( ACT_IDLE_AIM_RELAXED ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE_AIM_STIMULATED ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE_AIM_AGITATED ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE_AIM_STEALTH ); - - REGISTER_SHARED_ACTIVITY( ACT_WALK_AIM_RELAXED ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_AIM_STIMULATED ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_AIM_AGITATED ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_AIM_STEALTH ); - - REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM_RELAXED ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM_STIMULATED ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM_AGITATED ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM_STEALTH ); - - REGISTER_SHARED_ACTIVITY( ACT_CROUCHIDLE_STIMULATED ); - REGISTER_SHARED_ACTIVITY( ACT_CROUCHIDLE_AIM_STIMULATED ); - REGISTER_SHARED_ACTIVITY( ACT_CROUCHIDLE_AGITATED ); - - REGISTER_SHARED_ACTIVITY( ACT_WALK_HURT ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_HURT ); - REGISTER_SHARED_ACTIVITY( ACT_SPECIAL_ATTACK1 ); - REGISTER_SHARED_ACTIVITY( ACT_SPECIAL_ATTACK2 ); - REGISTER_SHARED_ACTIVITY( ACT_COMBAT_IDLE ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_SCARED ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_SCARED ); - REGISTER_SHARED_ACTIVITY( ACT_VICTORY_DANCE ); - - REGISTER_SHARED_ACTIVITY( ACT_DIE_HEADSHOT ); - REGISTER_SHARED_ACTIVITY( ACT_DIE_CHESTSHOT ); - REGISTER_SHARED_ACTIVITY( ACT_DIE_GUTSHOT ); - REGISTER_SHARED_ACTIVITY( ACT_DIE_BACKSHOT ); - - REGISTER_SHARED_ACTIVITY( ACT_FLINCH_HEAD ); - REGISTER_SHARED_ACTIVITY( ACT_FLINCH_CHEST ); - REGISTER_SHARED_ACTIVITY( ACT_FLINCH_STOMACH ); - REGISTER_SHARED_ACTIVITY( ACT_FLINCH_LEFTARM ); - REGISTER_SHARED_ACTIVITY( ACT_FLINCH_RIGHTARM ); - REGISTER_SHARED_ACTIVITY( ACT_FLINCH_LEFTLEG ); - REGISTER_SHARED_ACTIVITY( ACT_FLINCH_RIGHTLEG ); - REGISTER_SHARED_ACTIVITY( ACT_FLINCH_PHYSICS ); - - REGISTER_SHARED_ACTIVITY( ACT_IDLE_ON_FIRE ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_ON_FIRE ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_ON_FIRE ); - - REGISTER_SHARED_ACTIVITY( ACT_RAPPEL_LOOP ); - - REGISTER_SHARED_ACTIVITY( ACT_180_LEFT ); - REGISTER_SHARED_ACTIVITY( ACT_180_RIGHT ); - REGISTER_SHARED_ACTIVITY( ACT_90_LEFT ); - REGISTER_SHARED_ACTIVITY( ACT_90_RIGHT ); - REGISTER_SHARED_ACTIVITY( ACT_STEP_LEFT ); - REGISTER_SHARED_ACTIVITY( ACT_STEP_RIGHT ); - REGISTER_SHARED_ACTIVITY( ACT_STEP_BACK ); - REGISTER_SHARED_ACTIVITY( ACT_STEP_FORE ); - - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RANGE_ATTACK1 ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RANGE_ATTACK2 ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_MELEE_ATTACK1 ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_MELEE_ATTACK2 ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RANGE_ATTACK1_LOW ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RANGE_ATTACK2_LOW ); - REGISTER_SHARED_ACTIVITY( ACT_MELEE_ATTACK_SWING_GESTURE ); - - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_SMALL_FLINCH ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_BIG_FLINCH ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_FLINCH_BLAST ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_FLINCH_BLAST_SHOTGUN ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_FLINCH_BLAST_DAMAGED ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_FLINCH_BLAST_DAMAGED_SHOTGUN ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_FLINCH_HEAD ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_FLINCH_CHEST ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_FLINCH_STOMACH ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_FLINCH_LEFTARM ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_FLINCH_RIGHTARM ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_FLINCH_LEFTLEG ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_FLINCH_RIGHTLEG ); - - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_TURN_LEFT ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_TURN_RIGHT ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_TURN_LEFT45 ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_TURN_RIGHT45 ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_TURN_LEFT90 ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_TURN_RIGHT90 ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_TURN_LEFT45_FLAT ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_TURN_RIGHT45_FLAT ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_TURN_LEFT90_FLAT ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_TURN_RIGHT90_FLAT ); - - // registered for Half-Life HGRUNT compatability - REGISTER_SHARED_ACTIVITY( ACT_BARNACLE_HIT ); - REGISTER_SHARED_ACTIVITY( ACT_BARNACLE_PULL ); - REGISTER_SHARED_ACTIVITY( ACT_BARNACLE_CHOMP ); - REGISTER_SHARED_ACTIVITY( ACT_BARNACLE_CHEW ); - - REGISTER_SHARED_ACTIVITY( ACT_DO_NOT_DISTURB ); - - // Viewmodel activities may belong elsewhere, but since where is unclear right now, - // they'll be placed here. - REGISTER_SHARED_ACTIVITY( ACT_VM_DRAW ); - REGISTER_SHARED_ACTIVITY( ACT_VM_HOLSTER ); - REGISTER_SHARED_ACTIVITY( ACT_VM_IDLE ); - REGISTER_SHARED_ACTIVITY( ACT_VM_FIDGET ); - REGISTER_SHARED_ACTIVITY( ACT_VM_PULLBACK ); - REGISTER_SHARED_ACTIVITY( ACT_VM_PULLBACK_HIGH ); - REGISTER_SHARED_ACTIVITY( ACT_VM_PULLBACK_LOW ); - REGISTER_SHARED_ACTIVITY( ACT_VM_THROW ); - REGISTER_SHARED_ACTIVITY( ACT_VM_PULLPIN ); - REGISTER_SHARED_ACTIVITY( ACT_VM_PRIMARYATTACK ); - REGISTER_SHARED_ACTIVITY( ACT_VM_SECONDARYATTACK ); - REGISTER_SHARED_ACTIVITY( ACT_VM_RELOAD ); - REGISTER_SHARED_ACTIVITY( ACT_VM_DRYFIRE ); - REGISTER_SHARED_ACTIVITY( ACT_VM_HITLEFT ); - REGISTER_SHARED_ACTIVITY( ACT_VM_HITLEFT2 ); - REGISTER_SHARED_ACTIVITY( ACT_VM_HITRIGHT ); - REGISTER_SHARED_ACTIVITY( ACT_VM_HITRIGHT2 ); - REGISTER_SHARED_ACTIVITY( ACT_VM_HITCENTER ); - REGISTER_SHARED_ACTIVITY( ACT_VM_HITCENTER2 ); - REGISTER_SHARED_ACTIVITY( ACT_VM_MISSLEFT ); - REGISTER_SHARED_ACTIVITY( ACT_VM_MISSLEFT2 ); - REGISTER_SHARED_ACTIVITY( ACT_VM_MISSRIGHT ); - REGISTER_SHARED_ACTIVITY( ACT_VM_MISSRIGHT2 ); - REGISTER_SHARED_ACTIVITY( ACT_VM_MISSCENTER ); - REGISTER_SHARED_ACTIVITY( ACT_VM_MISSCENTER2 ); - REGISTER_SHARED_ACTIVITY( ACT_VM_HAULBACK ); - REGISTER_SHARED_ACTIVITY( ACT_VM_SWINGHARD ); - REGISTER_SHARED_ACTIVITY( ACT_VM_SWINGMISS ); - REGISTER_SHARED_ACTIVITY( ACT_VM_SWINGHIT ); - REGISTER_SHARED_ACTIVITY( ACT_VM_IDLE_TO_LOWERED ); - REGISTER_SHARED_ACTIVITY( ACT_VM_IDLE_LOWERED ); - REGISTER_SHARED_ACTIVITY( ACT_VM_LOWERED_TO_IDLE ); - REGISTER_SHARED_ACTIVITY( ACT_VM_RECOIL1 ); - REGISTER_SHARED_ACTIVITY( ACT_VM_RECOIL2 ); - REGISTER_SHARED_ACTIVITY( ACT_VM_RECOIL3 ); - REGISTER_SHARED_ACTIVITY( ACT_VM_PICKUP ); - REGISTER_SHARED_ACTIVITY( ACT_VM_RELEASE ); - - REGISTER_SHARED_ACTIVITY ( ACT_VM_ATTACH_SILENCER ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_DETACH_SILENCER ); - -//=========================== -// HL2 Specific Activities -//=========================== - // SLAM Specialty Activites - REGISTER_SHARED_ACTIVITY( ACT_SLAM_STICKWALL_IDLE); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_STICKWALL_ND_IDLE); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_STICKWALL_ATTACH); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_STICKWALL_ATTACH2); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_STICKWALL_ND_ATTACH); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_STICKWALL_ND_ATTACH2); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_STICKWALL_DETONATE); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_STICKWALL_DETONATOR_HOLSTER); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_STICKWALL_DRAW); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_STICKWALL_ND_DRAW); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_STICKWALL_TO_THROW); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_STICKWALL_TO_THROW_ND); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_STICKWALL_TO_TRIPMINE_ND ); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_THROW_IDLE); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_THROW_ND_IDLE); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_THROW_THROW); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_THROW_THROW2); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_THROW_THROW_ND); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_THROW_THROW_ND2); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_THROW_DRAW); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_THROW_ND_DRAW); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_THROW_TO_STICKWALL); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_THROW_TO_STICKWALL_ND); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_THROW_DETONATE); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_THROW_DETONATOR_HOLSTER); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_THROW_TO_TRIPMINE_ND ); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_TRIPMINE_IDLE); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_TRIPMINE_DRAW); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_TRIPMINE_ATTACH); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_TRIPMINE_ATTACH2); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_TRIPMINE_TO_STICKWALL_ND ); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_TRIPMINE_TO_THROW_ND ); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_DETONATOR_IDLE); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_DETONATOR_DRAW); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_DETONATOR_DETONATE); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_DETONATOR_HOLSTER); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_DETONATOR_STICKWALL_DRAW); - REGISTER_SHARED_ACTIVITY( ACT_SLAM_DETONATOR_THROW_DRAW); - - // SHOTGUN specialty activities - REGISTER_SHARED_ACTIVITY( ACT_SHOTGUN_RELOAD_START); - REGISTER_SHARED_ACTIVITY( ACT_SHOTGUN_RELOAD_FINISH); - REGISTER_SHARED_ACTIVITY( ACT_SHOTGUN_PUMP); - - // SMG2 special activities - REGISTER_SHARED_ACTIVITY( ACT_SMG2_IDLE2 ); - REGISTER_SHARED_ACTIVITY( ACT_SMG2_FIRE2 ); - REGISTER_SHARED_ACTIVITY( ACT_SMG2_DRAW2 ); - REGISTER_SHARED_ACTIVITY( ACT_SMG2_RELOAD2 ); - REGISTER_SHARED_ACTIVITY( ACT_SMG2_DRYFIRE2 ); - REGISTER_SHARED_ACTIVITY( ACT_SMG2_TOAUTO ); - REGISTER_SHARED_ACTIVITY( ACT_SMG2_TOBURST ); - - // Physcannon special activities - REGISTER_SHARED_ACTIVITY( ACT_PHYSCANNON_UPGRADE ); - - // weapon override activities - REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_AR1 ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_AR2 ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_AR2_LOW ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_AR2_GRENADE ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_HMG1 ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_ML ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_SMG1 ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_SMG1_LOW ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_SMG2 ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_SHOTGUN ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_SHOTGUN_LOW ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_PISTOL ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_PISTOL_LOW ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_SLAM ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_TRIPWIRE ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_THROW ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_SNIPER_RIFLE ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_ATTACK_RPG ); - REGISTER_SHARED_ACTIVITY( ACT_MELEE_ATTACK_SWING ); - - REGISTER_SHARED_ACTIVITY( ACT_RANGE_AIM_LOW ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_AIM_SMG1_LOW ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_AIM_PISTOL_LOW ); - REGISTER_SHARED_ACTIVITY( ACT_RANGE_AIM_AR2_LOW ); - - REGISTER_SHARED_ACTIVITY( ACT_COVER_PISTOL_LOW ); - REGISTER_SHARED_ACTIVITY( ACT_COVER_SMG1_LOW ); - - // weapon override activities - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RANGE_ATTACK_AR1 ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RANGE_ATTACK_AR2 ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RANGE_ATTACK_AR2_GRENADE ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RANGE_ATTACK_HMG1 ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RANGE_ATTACK_ML ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RANGE_ATTACK_SMG1 ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RANGE_ATTACK_SMG1_LOW ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RANGE_ATTACK_SMG2 ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RANGE_ATTACK_SHOTGUN ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RANGE_ATTACK_PISTOL ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RANGE_ATTACK_PISTOL_LOW ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RANGE_ATTACK_SLAM ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RANGE_ATTACK_TRIPWIRE ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RANGE_ATTACK_THROW ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RANGE_ATTACK_SNIPER_RIFLE ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_MELEE_ATTACK_SWING ); - - REGISTER_SHARED_ACTIVITY( ACT_IDLE_RIFLE ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE_SMG1 ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE_ANGRY_SMG1 ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE_PISTOL ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE_ANGRY_PISTOL ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE_ANGRY_SHOTGUN ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE_STEALTH_PISTOL ); - - REGISTER_SHARED_ACTIVITY( ACT_IDLE_PACKAGE ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_PACKAGE ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE_SUITCASE ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_SUITCASE ); - - REGISTER_SHARED_ACTIVITY( ACT_IDLE_SMG1_RELAXED ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE_SMG1_STIMULATED ); - - REGISTER_SHARED_ACTIVITY( ACT_WALK_RIFLE_RELAXED ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_RIFLE_RELAXED ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_RIFLE_STIMULATED ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_RIFLE_STIMULATED ); - - REGISTER_SHARED_ACTIVITY( ACT_IDLE_AIM_RIFLE_STIMULATED ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_AIM_RIFLE_STIMULATED ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM_RIFLE_STIMULATED ); - - REGISTER_SHARED_ACTIVITY( ACT_IDLE_SHOTGUN_RELAXED ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE_SHOTGUN_STIMULATED ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE_SHOTGUN_AGITATED ); - - // Policing activities - REGISTER_SHARED_ACTIVITY( ACT_WALK_ANGRY ); - REGISTER_SHARED_ACTIVITY( ACT_POLICE_HARASS1 ); - REGISTER_SHARED_ACTIVITY( ACT_POLICE_HARASS2 ); - - // Manned guns - REGISTER_SHARED_ACTIVITY( ACT_IDLE_MANNEDGUN ); - - // Melee weapon activities - REGISTER_SHARED_ACTIVITY( ACT_IDLE_MELEE ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE_ANGRY_MELEE ); - - // RPG activities - REGISTER_SHARED_ACTIVITY( ACT_IDLE_RPG_RELAXED ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE_RPG ); - REGISTER_SHARED_ACTIVITY( ACT_IDLE_ANGRY_RPG ); - REGISTER_SHARED_ACTIVITY( ACT_COVER_LOW_RPG ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_RPG ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_RPG ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_CROUCH_RPG ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_CROUCH_RPG ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_RPG_RELAXED ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_RPG_RELAXED ); - - REGISTER_SHARED_ACTIVITY( ACT_WALK_RIFLE ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_AIM_RIFLE ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_CROUCH_RIFLE ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_CROUCH_AIM_RIFLE ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_RIFLE ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM_RIFLE ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_CROUCH_RIFLE ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_CROUCH_AIM_RIFLE ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_STEALTH_PISTOL ); - - REGISTER_SHARED_ACTIVITY( ACT_WALK_AIM_SHOTGUN ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM_SHOTGUN ); - - REGISTER_SHARED_ACTIVITY( ACT_WALK_PISTOL ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_PISTOL ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_AIM_PISTOL ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM_PISTOL ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_STEALTH_PISTOL ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_AIM_STEALTH_PISTOL ); - REGISTER_SHARED_ACTIVITY( ACT_RUN_AIM_STEALTH_PISTOL ); - - // Reloads - REGISTER_SHARED_ACTIVITY( ACT_RELOAD_PISTOL ); - REGISTER_SHARED_ACTIVITY( ACT_RELOAD_PISTOL_LOW ); - REGISTER_SHARED_ACTIVITY( ACT_RELOAD_SMG1 ); - REGISTER_SHARED_ACTIVITY( ACT_RELOAD_SMG1_LOW ); - REGISTER_SHARED_ACTIVITY( ACT_RELOAD_SHOTGUN ); - REGISTER_SHARED_ACTIVITY( ACT_RELOAD_SHOTGUN_LOW ); - - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RELOAD ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RELOAD_PISTOL ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RELOAD_SMG1 ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_RELOAD_SHOTGUN ); - - // Busy animations - REGISTER_SHARED_ACTIVITY( ACT_BUSY_LEAN_LEFT ); - REGISTER_SHARED_ACTIVITY( ACT_BUSY_LEAN_LEFT_ENTRY ); - REGISTER_SHARED_ACTIVITY( ACT_BUSY_LEAN_LEFT_EXIT ); - REGISTER_SHARED_ACTIVITY( ACT_BUSY_LEAN_BACK ); - REGISTER_SHARED_ACTIVITY( ACT_BUSY_LEAN_BACK_ENTRY ); - REGISTER_SHARED_ACTIVITY( ACT_BUSY_LEAN_BACK_EXIT ); - REGISTER_SHARED_ACTIVITY( ACT_BUSY_SIT_GROUND ); - REGISTER_SHARED_ACTIVITY( ACT_BUSY_SIT_GROUND_ENTRY ); - REGISTER_SHARED_ACTIVITY( ACT_BUSY_SIT_GROUND_EXIT ); - REGISTER_SHARED_ACTIVITY( ACT_BUSY_SIT_CHAIR ); - REGISTER_SHARED_ACTIVITY( ACT_BUSY_SIT_CHAIR_ENTRY ); - REGISTER_SHARED_ACTIVITY( ACT_BUSY_SIT_CHAIR_EXIT ); - REGISTER_SHARED_ACTIVITY( ACT_BUSY_STAND ); - REGISTER_SHARED_ACTIVITY( ACT_BUSY_QUEUE ); - - // Dodge animations - REGISTER_SHARED_ACTIVITY( ACT_DUCK_DODGE ); - - REGISTER_SHARED_ACTIVITY( ACT_DIE_BARNACLE_SWALLOW ); - REGISTER_SHARED_ACTIVITY( ACT_GESTURE_BARNACLE_STRANGLE ); - REGISTER_SHARED_ACTIVITY( ACT_PHYSCANNON_DETACH ); - REGISTER_SHARED_ACTIVITY( ACT_PHYSCANNON_ANIMATE ); - REGISTER_SHARED_ACTIVITY( ACT_PHYSCANNON_ANIMATE_PRE ); - REGISTER_SHARED_ACTIVITY( ACT_PHYSCANNON_ANIMATE_POST ); - - REGISTER_SHARED_ACTIVITY( ACT_DIE_FRONTSIDE ); - REGISTER_SHARED_ACTIVITY( ACT_DIE_RIGHTSIDE ); - REGISTER_SHARED_ACTIVITY( ACT_DIE_BACKSIDE ); - REGISTER_SHARED_ACTIVITY( ACT_DIE_LEFTSIDE ); - - REGISTER_SHARED_ACTIVITY( ACT_OPEN_DOOR ); - - // Dynamic interactions - REGISTER_SHARED_ACTIVITY( ACT_DI_ALYX_ZOMBIE_MELEE ); - REGISTER_SHARED_ACTIVITY( ACT_DI_ALYX_ZOMBIE_TORSO_MELEE ); - REGISTER_SHARED_ACTIVITY( ACT_DI_ALYX_HEADCRAB_MELEE ); - REGISTER_SHARED_ACTIVITY( ACT_DI_ALYX_ANTLION ); - REGISTER_SHARED_ACTIVITY( ACT_DI_ALYX_ZOMBIE_SHOTGUN64 ); - REGISTER_SHARED_ACTIVITY( ACT_DI_ALYX_ZOMBIE_SHOTGUN26 ); - - //Readiness transitions - REGISTER_SHARED_ACTIVITY( ACT_READINESS_RELAXED_TO_STIMULATED ); - REGISTER_SHARED_ACTIVITY( ACT_READINESS_RELAXED_TO_STIMULATED_WALK ); - REGISTER_SHARED_ACTIVITY( ACT_READINESS_AGITATED_TO_STIMULATED ); - REGISTER_SHARED_ACTIVITY( ACT_READINESS_STIMULATED_TO_RELAXED ); - - REGISTER_SHARED_ACTIVITY( ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED ); - REGISTER_SHARED_ACTIVITY( ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED_WALK ); - REGISTER_SHARED_ACTIVITY( ACT_READINESS_PISTOL_AGITATED_TO_STIMULATED ); - REGISTER_SHARED_ACTIVITY( ACT_READINESS_PISTOL_STIMULATED_TO_RELAXED ); - - REGISTER_SHARED_ACTIVITY( ACT_IDLE_CARRY ); - REGISTER_SHARED_ACTIVITY( ACT_WALK_CARRY ); - -//=========================== -// TF2 Specific Activities -//=========================== - REGISTER_SHARED_ACTIVITY( ACT_STARTDYING ); - REGISTER_SHARED_ACTIVITY( ACT_DYINGLOOP ); - REGISTER_SHARED_ACTIVITY( ACT_DYINGTODEAD ); - REGISTER_SHARED_ACTIVITY( ACT_RIDE_MANNED_GUN ); - - // All viewmodels - REGISTER_SHARED_ACTIVITY( ACT_VM_SPRINT_ENTER ); - REGISTER_SHARED_ACTIVITY( ACT_VM_SPRINT_IDLE ); - REGISTER_SHARED_ACTIVITY( ACT_VM_SPRINT_LEAVE ); - - // Looping weapon firing - REGISTER_SHARED_ACTIVITY( ACT_FIRE_START ); - REGISTER_SHARED_ACTIVITY( ACT_FIRE_LOOP ); - REGISTER_SHARED_ACTIVITY( ACT_FIRE_END ); - - // TF2 - REGISTER_SHARED_ACTIVITY( ACT_CROUCHING_GRENADEIDLE ); - REGISTER_SHARED_ACTIVITY( ACT_CROUCHING_GRENADEREADY ); - REGISTER_SHARED_ACTIVITY( ACT_CROUCHING_PRIMARYATTACK ); - REGISTER_SHARED_ACTIVITY( ACT_OVERLAY_GRENADEIDLE ); - REGISTER_SHARED_ACTIVITY( ACT_OVERLAY_GRENADEREADY ); - REGISTER_SHARED_ACTIVITY( ACT_OVERLAY_PRIMARYATTACK ); - REGISTER_SHARED_ACTIVITY( ACT_OVERLAY_SHIELD_UP ); - REGISTER_SHARED_ACTIVITY( ACT_OVERLAY_SHIELD_DOWN ); - REGISTER_SHARED_ACTIVITY( ACT_OVERLAY_SHIELD_UP_IDLE ); - REGISTER_SHARED_ACTIVITY( ACT_OVERLAY_SHIELD_ATTACK ); - REGISTER_SHARED_ACTIVITY( ACT_OVERLAY_SHIELD_KNOCKBACK ); - REGISTER_SHARED_ACTIVITY( ACT_SHIELD_UP ); - REGISTER_SHARED_ACTIVITY( ACT_SHIELD_DOWN ); - REGISTER_SHARED_ACTIVITY( ACT_SHIELD_UP_IDLE ); - REGISTER_SHARED_ACTIVITY( ACT_SHIELD_ATTACK ); - REGISTER_SHARED_ACTIVITY( ACT_SHIELD_KNOCKBACK ); - REGISTER_SHARED_ACTIVITY( ACT_CROUCHING_SHIELD_UP ); - REGISTER_SHARED_ACTIVITY( ACT_CROUCHING_SHIELD_DOWN ); - REGISTER_SHARED_ACTIVITY( ACT_CROUCHING_SHIELD_UP_IDLE ); - REGISTER_SHARED_ACTIVITY( ACT_CROUCHING_SHIELD_ATTACK ); - REGISTER_SHARED_ACTIVITY( ACT_CROUCHING_SHIELD_KNOCKBACK ); - - REGISTER_SHARED_ACTIVITY( ACT_TURNRIGHT45 ); - REGISTER_SHARED_ACTIVITY( ACT_TURNLEFT45 ); - REGISTER_SHARED_ACTIVITY( ACT_TURN ); - - REGISTER_SHARED_ACTIVITY( ACT_OBJ_ASSEMBLING ); - REGISTER_SHARED_ACTIVITY( ACT_OBJ_DISMANTLING ); - REGISTER_SHARED_ACTIVITY( ACT_OBJ_STARTUP ); - REGISTER_SHARED_ACTIVITY( ACT_OBJ_RUNNING ); - REGISTER_SHARED_ACTIVITY( ACT_OBJ_IDLE ); - REGISTER_SHARED_ACTIVITY( ACT_OBJ_PLACING ); - REGISTER_SHARED_ACTIVITY( ACT_OBJ_DETERIORATING ); - REGISTER_SHARED_ACTIVITY( ACT_OBJ_UPGRADING ); - - // Deploy - REGISTER_SHARED_ACTIVITY( ACT_DEPLOY ); - REGISTER_SHARED_ACTIVITY( ACT_DEPLOY_IDLE ); - REGISTER_SHARED_ACTIVITY( ACT_UNDEPLOY ); - -//=========================== -// HL1 Specific Activities -//=========================== - - // Grenades - REGISTER_SHARED_ACTIVITY( ACT_GRENADE_ROLL ); - REGISTER_SHARED_ACTIVITY( ACT_GRENADE_TOSS ); - - // Hand grenade - REGISTER_SHARED_ACTIVITY( ACT_HANDGRENADE_THROW1 ); - REGISTER_SHARED_ACTIVITY( ACT_HANDGRENADE_THROW2 ); - REGISTER_SHARED_ACTIVITY( ACT_HANDGRENADE_THROW3 ); - - // Shotgun - REGISTER_SHARED_ACTIVITY( ACT_SHOTGUN_IDLE_DEEP ); - REGISTER_SHARED_ACTIVITY( ACT_SHOTGUN_IDLE4 ); - - // Glock - REGISTER_SHARED_ACTIVITY( ACT_GLOCK_SHOOTEMPTY ); - REGISTER_SHARED_ACTIVITY( ACT_GLOCK_SHOOT_RELOAD ); - - // RPG - REGISTER_SHARED_ACTIVITY( ACT_RPG_DRAW_UNLOADED ); - REGISTER_SHARED_ACTIVITY( ACT_RPG_HOLSTER_UNLOADED ); - REGISTER_SHARED_ACTIVITY( ACT_RPG_IDLE_UNLOADED ); - REGISTER_SHARED_ACTIVITY( ACT_RPG_FIDGET_UNLOADED ); - - // Crossbow - REGISTER_SHARED_ACTIVITY( ACT_CROSSBOW_DRAW_UNLOADED ); - REGISTER_SHARED_ACTIVITY( ACT_CROSSBOW_IDLE_UNLOADED ); - REGISTER_SHARED_ACTIVITY( ACT_CROSSBOW_FIDGET_UNLOADED ); - - // Gauss - REGISTER_SHARED_ACTIVITY( ACT_GAUSS_SPINUP ); - REGISTER_SHARED_ACTIVITY( ACT_GAUSS_SPINCYCLE ); - - // Tripmine - REGISTER_SHARED_ACTIVITY( ACT_TRIPMINE_GROUND ); - REGISTER_SHARED_ACTIVITY( ACT_TRIPMINE_WORLD ); - -//=========================== -// CSPort Specific Activities -//=========================== - - REGISTER_SHARED_ACTIVITY ( ACT_VM_PRIMARYATTACK_SILENCED ); // fire - REGISTER_SHARED_ACTIVITY ( ACT_VM_RELOAD_SILENCED ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_DRYFIRE_SILENCED ); // fire with no ammo loaded. - REGISTER_SHARED_ACTIVITY ( ACT_VM_IDLE_SILENCED ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_DRAW_SILENCED ); - - REGISTER_SHARED_ACTIVITY ( ACT_VM_IDLE_EMPTY_LEFT ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_DRYFIRE_LEFT ); - - REGISTER_SHARED_ACTIVITY ( ACT_PLAYER_IDLE_FIRE ); - REGISTER_SHARED_ACTIVITY ( ACT_PLAYER_CROUCH_FIRE ); - REGISTER_SHARED_ACTIVITY ( ACT_PLAYER_CROUCH_WALK_FIRE ); - REGISTER_SHARED_ACTIVITY ( ACT_PLAYER_WALK_FIRE ); - REGISTER_SHARED_ACTIVITY ( ACT_PLAYER_RUN_FIRE ); - REGISTER_SHARED_ACTIVITY ( ACT_IDLETORUN ); - REGISTER_SHARED_ACTIVITY ( ACT_RUNTOIDLE ); - -//=========================== -// DoD Specific Activities -//=========================== - - REGISTER_SHARED_ACTIVITY ( ACT_SPRINT ); - - // To get in and out of prone state. - REGISTER_SHARED_ACTIVITY ( ACT_GET_DOWN_STAND ); - REGISTER_SHARED_ACTIVITY ( ACT_GET_UP_STAND ); - REGISTER_SHARED_ACTIVITY ( ACT_GET_DOWN_CROUCH ); - REGISTER_SHARED_ACTIVITY ( ACT_GET_UP_CROUCH ); - REGISTER_SHARED_ACTIVITY ( ACT_PRONE_FORWARD ); - REGISTER_SHARED_ACTIVITY ( ACT_PRONE_IDLE ); - - REGISTER_SHARED_ACTIVITY ( ACT_DEEPIDLE1 ); - REGISTER_SHARED_ACTIVITY ( ACT_DEEPIDLE2 ); - REGISTER_SHARED_ACTIVITY ( ACT_DEEPIDLE3 ); - REGISTER_SHARED_ACTIVITY ( ACT_DEEPIDLE4 ); - - REGISTER_SHARED_ACTIVITY ( ACT_VM_RELOAD_DEPLOYED ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_RELOAD_IDLE ); - - REGISTER_SHARED_ACTIVITY ( ACT_VM_DRAW_DEPLOYED ); - - //Weapon is empty activities - REGISTER_SHARED_ACTIVITY ( ACT_VM_DRAW_EMPTY ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_PRIMARYATTACK_EMPTY ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_RELOAD_EMPTY ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_IDLE_EMPTY ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_IDLE_DEPLOYED_EMPTY ); - - REGISTER_SHARED_ACTIVITY ( ACT_VM_IDLE_8 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_IDLE_7 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_IDLE_6 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_IDLE_5 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_IDLE_4 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_IDLE_3 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_IDLE_2 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_IDLE_1 ); - - REGISTER_SHARED_ACTIVITY ( ACT_VM_IDLE_DEPLOYED ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_IDLE_DEPLOYED_8 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_IDLE_DEPLOYED_7 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_IDLE_DEPLOYED_6 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_IDLE_DEPLOYED_5 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_IDLE_DEPLOYED_4 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_IDLE_DEPLOYED_3 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_IDLE_DEPLOYED_2 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_IDLE_DEPLOYED_1 ); - - // Animation from prone idle to standing/crouch idle. Number designates bullets left - REGISTER_SHARED_ACTIVITY ( ACT_VM_UNDEPLOY ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_UNDEPLOY_8 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_UNDEPLOY_7 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_UNDEPLOY_6 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_UNDEPLOY_5 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_UNDEPLOY_4 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_UNDEPLOY_3 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_UNDEPLOY_2 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_UNDEPLOY_1 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_UNDEPLOY_EMPTY ); - - // Animation from standing/crouch idle to prone idle. Number designates bullets left - REGISTER_SHARED_ACTIVITY ( ACT_VM_DEPLOY ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_DEPLOY_8 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_DEPLOY_7 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_DEPLOY_6 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_DEPLOY_5 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_DEPLOY_4 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_DEPLOY_3 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_DEPLOY_2 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_DEPLOY_1 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_DEPLOY_EMPTY ); - - // Shooting animations for standing/crouch position. Number designates bullets left at START of animation - REGISTER_SHARED_ACTIVITY ( ACT_VM_PRIMARYATTACK_8 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_PRIMARYATTACK_7 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_PRIMARYATTACK_6 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_PRIMARYATTACK_5 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_PRIMARYATTACK_4 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_PRIMARYATTACK_3 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_PRIMARYATTACK_2 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_PRIMARYATTACK_1 ); - - // Shooting animations for prone position. Number designates bullets left at START of animation - REGISTER_SHARED_ACTIVITY ( ACT_VM_PRIMARYATTACK_DEPLOYED ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_PRIMARYATTACK_DEPLOYED_8 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_PRIMARYATTACK_DEPLOYED_7 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_PRIMARYATTACK_DEPLOYED_6 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_PRIMARYATTACK_DEPLOYED_5 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_PRIMARYATTACK_DEPLOYED_4 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_PRIMARYATTACK_DEPLOYED_3 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_PRIMARYATTACK_DEPLOYED_2 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_PRIMARYATTACK_DEPLOYED_1 ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_PRIMARYATTACK_DEPLOYED_EMPTY ); - - // Player anim ACTs - - // Base activities, we translate from these - REGISTER_SHARED_ACTIVITY ( ACT_DOD_DEPLOYED ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_DEPLOYED ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_IDLE_ZOOMED ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_ZOOMED ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_ZOOMED ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_ZOOMED ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_ZOOMED ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_FORWARD_ZOOMED ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_DEPLOYED ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PRONE_DEPLOYED ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_DEPLOYED ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PRONE_DEPLOYED ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PRONE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SECONDARYATTACK_PRONE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_CROUCH ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PRONE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_IDLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_AIM ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_IDLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_AIM ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_IDLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_AIM ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_IDLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_AIM ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_IDLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_AIM ); - - // Positions - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_AIM_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_AIM_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_AIM_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_AIM_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_AIM_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_AIM_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_IDLE_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_IDLE_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_IDLE_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_IDLE_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_IDLE_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SPRINT_IDLE_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONEWALK_IDLE_PISTOL ); - - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_AIM_C96 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_AIM_C96 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_AIM_C96 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_AIM_C96 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_AIM_C96 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_AIM_C96 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_IDLE_C96 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_IDLE_C96 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_IDLE_C96 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_IDLE_C96 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_IDLE_C96 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SPRINT_IDLE_C96 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONEWALK_IDLE_C96 ); - - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_AIM_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_AIM_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_AIM_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_AIM_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_AIM_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_AIM_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_IDLE_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_IDLE_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_IDLE_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_IDLE_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_IDLE_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SPRINT_IDLE_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONEWALK_IDLE_RIFLE ); - - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_AIM_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_AIM_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_AIM_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_AIM_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_AIM_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_AIM_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_IDLE_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_IDLE_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_IDLE_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_IDLE_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_IDLE_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SPRINT_IDLE_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONEWALK_IDLE_BOLT ); - - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_AIM_TOMMY ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_AIM_TOMMY ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_AIM_TOMMY ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_AIM_TOMMY ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_AIM_TOMMY ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_AIM_TOMMY ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_IDLE_TOMMY ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_IDLE_TOMMY ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_IDLE_TOMMY ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_IDLE_TOMMY ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_IDLE_TOMMY ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SPRINT_IDLE_TOMMY ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONEWALK_IDLE_TOMMY ); - - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_AIM_MP40 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_AIM_MP40 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_AIM_MP40 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_AIM_MP40 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_AIM_MP40 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_AIM_MP40 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_IDLE_MP40 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_IDLE_MP40 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_IDLE_MP40 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_IDLE_MP40 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_IDLE_MP40 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SPRINT_IDLE_MP40 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONEWALK_IDLE_MP40 ); - - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_AIM_MP44 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_AIM_MP44 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_AIM_MP44 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_AIM_MP44 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_AIM_MP44 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_AIM_MP44 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_IDLE_MP44 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_IDLE_MP44 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_IDLE_MP44 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_IDLE_MP44 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_IDLE_MP44 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SPRINT_IDLE_MP44 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONEWALK_IDLE_MP44 ); - - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_AIM_GREASE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_AIM_GREASE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_AIM_GREASE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_AIM_GREASE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_AIM_GREASE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_AIM_GREASE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_IDLE_GREASE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_IDLE_GREASE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_IDLE_GREASE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_IDLE_GREASE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_IDLE_GREASE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SPRINT_IDLE_GREASE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONEWALK_IDLE_GREASE ); - - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_AIM_MG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_AIM_MG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_AIM_MG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_AIM_MG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_AIM_MG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_AIM_MG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_IDLE_MG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_IDLE_MG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_IDLE_MG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_IDLE_MG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_IDLE_MG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SPRINT_IDLE_MG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONEWALK_IDLE_MG ); - - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_AIM_30CAL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_AIM_30CAL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_AIM_30CAL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_AIM_30CAL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_AIM_30CAL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_AIM_30CAL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_IDLE_30CAL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_IDLE_30CAL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_IDLE_30CAL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_IDLE_30CAL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_IDLE_30CAL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SPRINT_IDLE_30CAL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONEWALK_IDLE_30CAL ); - - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_AIM_GREN_FRAG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_AIM_GREN_FRAG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_AIM_GREN_FRAG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_AIM_GREN_FRAG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_AIM_GREN_FRAG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_AIM_GREN_FRAG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SPRINT_AIM_GREN_FRAG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONEWALK_AIM_GREN_FRAG ); - - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_AIM_GREN_STICK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_AIM_GREN_STICK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_AIM_GREN_STICK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_AIM_GREN_STICK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_AIM_GREN_STICK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_AIM_GREN_STICK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SPRINT_AIM_GREN_STICK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONEWALK_AIM_GREN_STICK ); - - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_AIM_KNIFE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_AIM_KNIFE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_AIM_KNIFE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_AIM_KNIFE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_AIM_KNIFE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_AIM_KNIFE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SPRINT_AIM_KNIFE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONEWALK_AIM_KNIFE ); - - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_AIM_SPADE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_AIM_SPADE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_AIM_SPADE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_AIM_SPADE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_AIM_SPADE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_AIM_SPADE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SPRINT_AIM_SPADE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONEWALK_AIM_SPADE ); - - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_AIM_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_AIM_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_AIM_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_AIM_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_AIM_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_AIM_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_IDLE_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_IDLE_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_IDLE_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_IDLE_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_IDLE_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SPRINT_IDLE_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONEWALK_IDLE_BAZOOKA ); - - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_AIM_PSCHRECK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_AIM_PSCHRECK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_AIM_PSCHRECK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_AIM_PSCHRECK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_AIM_PSCHRECK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_AIM_PSCHRECK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_IDLE_PSCHRECK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_IDLE_PSCHRECK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_IDLE_PSCHRECK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_IDLE_PSCHRECK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_IDLE_PSCHRECK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SPRINT_IDLE_PSCHRECK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONEWALK_IDLE_PSCHRECK ); - - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_AIM_BAR ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_AIM_BAR ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_AIM_BAR ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_AIM_BAR ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_AIM_BAR ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_AIM_BAR ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_IDLE_BAR ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_IDLE_BAR ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_IDLE_BAR ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_IDLE_BAR ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_IDLE_BAR ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SPRINT_IDLE_BAR ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONEWALK_IDLE_BAR ); - - // ZOom - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_ZOOM_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_ZOOM_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_ZOOM_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_ZOOM_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_ZOOM_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_ZOOM_RIFLE ); - - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_ZOOM_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_ZOOM_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_ZOOM_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_ZOOM_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_ZOOM_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_ZOOM_BOLT ); - - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_ZOOM_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_ZOOM_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_ZOOM_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_ZOOM_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_ZOOM_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_ZOOM_BAZOOKA ); - - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_ZOOM_PSCHRECK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_ZOOM_PSCHRECK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_ZOOM_PSCHRECK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_ZOOM_PSCHRECK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_ZOOM_PSCHRECK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_ZOOM_PSCHRECK ); - - // Deployed Aim - REGISTER_SHARED_ACTIVITY ( ACT_DOD_DEPLOY_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_DEPLOY_TOMMY ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_DEPLOY_MG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_DEPLOY_30CAL ); - - // Prone Deployed Aim - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_DEPLOY_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_DEPLOY_TOMMY ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_DEPLOY_MG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_DEPLOY_30CAL ); - - // Attacks - - // Rifle - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SECONDARYATTACK_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PRONE_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SECONDARYATTACK_PRONE_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PRONE_DEPLOYED_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_DEPLOYED_RIFLE ); - - // Bolt - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SECONDARYATTACK_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PRONE_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SECONDARYATTACK_PRONE_BOLT ); - - // Tommy - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_TOMMY ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PRONE_TOMMY ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SECONDARYATTACK_TOMMY ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SECONDARYATTACK_PRONE_TOMMY ); - - // MP40 - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_MP40 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PRONE_MP40 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SECONDARYATTACK_MP40 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SECONDARYATTACK_PRONE_MP40 ); - - // MP44 - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_MP44 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PRONE_MP44 ); - - // Greasegun - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_GREASE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PRONE_GREASE ); - - // Pistols (Colt, Luger) - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PRONE_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_C96 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PRONE_C96 ); - - // Mgs (mg42, mg34) - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_MG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PRONE_MG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PRONE_DEPLOYED_MG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_DEPLOYED_MG ); - - // 30cal - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_30CAL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PRONE_30CAL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_DEPLOYED_30CAL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PRONE_DEPLOYED_30CAL ); - - // Grenades - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_GREN_FRAG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PRONE_GREN_FRAG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_GREN_STICK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PRONE_GREN_STICK ); - - // Knife - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_KNIFE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PRONE_KNIFE ); - - // Spade - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_SPADE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PRONE_SPADE ); - - // Bazooka - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PRONE_BAZOOKA ); - - // Pschreck - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PSCHRECK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PRONE_PSCHRECK ); - - // Bar - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_BAR ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_PRONE_BAR ); - - // Reloads - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_GARAND ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_K43 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_BAR ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_MP40 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_MP44 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_M1CARBINE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_TOMMY ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_GREASEGUN ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_FG42 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_RIFLEGRENADE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_C96 ); - - // Crouch - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_CROUCH_BAR ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_CROUCH_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_CROUCH_RIFLEGRENADE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_CROUCH_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_CROUCH_MP44 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_CROUCH_MP40 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_CROUCH_TOMMY ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_CROUCH_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_CROUCH_PSCHRECK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_CROUCH_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_CROUCH_M1CARBINE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_CROUCH_C96 ); - - // Bazookas - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_ZOOMLOAD_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PSCHRECK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_ZOOMLOAD_PSCHRECK ); - - // Deployed - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_DEPLOYED_FG42 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_DEPLOYED_30CAL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_DEPLOYED_MG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_DEPLOYED_MG34 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_DEPLOYED_BAR ); - - // Prone - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PRONE_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PRONE_GARAND ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PRONE_M1CARBINE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PRONE_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PRONE_K43 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PRONE_MP40 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PRONE_MP44 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PRONE_BAR ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PRONE_GREASEGUN ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PRONE_TOMMY ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PRONE_FG42 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PRONE_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PRONE_RIFLEGRENADE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PRONE_C96 ); - - // Prone bazooka - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PRONE_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_ZOOMLOAD_PRONE_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PRONE_PSCHRECK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_ZOOMLOAD_PRONE_PSCHRECK ); - - // Prone deployed - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PRONE_DEPLOYED_BAR ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PRONE_DEPLOYED_FG42 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PRONE_DEPLOYED_30CAL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PRONE_DEPLOYED_MG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RELOAD_PRONE_DEPLOYED_MG34 ); - - // Prone zoomed aim - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_ZOOM_FORWARD_RIFLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_ZOOM_FORWARD_BOLT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_ZOOM_FORWARD_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONE_ZOOM_FORWARD_PSCHRECK ); - - // Crouch attack. - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_CROUCH ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_CROUCH_SPADE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_CROUCH_KNIFE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_CROUCH_GREN_FRAG ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRIMARYATTACK_CROUCH_GREN_STICK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SECONDARYATTACK_CROUCH ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SECONDARYATTACK_CROUCH_TOMMY ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SECONDARYATTACK_CROUCH_MP40 ); - - // Hand Signals - REGISTER_SHARED_ACTIVITY ( ACT_DOD_HS_IDLE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_HS_CROUCH ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_HS_IDLE_30CAL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_HS_IDLE_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_HS_IDLE_PSCHRECK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_HS_IDLE_KNIFE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_HS_IDLE_MG42 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_HS_IDLE_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_HS_IDLE_STICKGRENADE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_HS_IDLE_TOMMY ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_HS_IDLE_MP44 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_HS_IDLE_K98 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_HS_CROUCH_30CAL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_HS_CROUCH_BAZOOKA ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_HS_CROUCH_PSCHRECK ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_HS_CROUCH_KNIFE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_HS_CROUCH_MG42 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_HS_CROUCH_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_HS_CROUCH_STICKGRENADE ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_HS_CROUCH_TOMMY ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_HS_CROUCH_MP44 ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_HS_CROUCH_K98 ); - - REGISTER_SHARED_ACTIVITY ( ACT_DOD_STAND_IDLE_TNT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCH_IDLE_TNT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_CROUCHWALK_IDLE_TNT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_WALK_IDLE_TNT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_RUN_IDLE_TNT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_SPRINT_IDLE_TNT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PRONEWALK_IDLE_TNT ); - - REGISTER_SHARED_ACTIVITY ( ACT_DOD_PLANT_TNT ); - REGISTER_SHARED_ACTIVITY ( ACT_DOD_DEFUSE_TNT ); - -//HL2MP - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_IDLE ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_RUN ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_IDLE_CROUCH ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_WALK_CROUCH ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_GESTURE_RANGE_ATTACK ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_GESTURE_RELOAD ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_JUMP ); - - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_IDLE_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_RUN_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_IDLE_CROUCH_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_WALK_CROUCH_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_GESTURE_RANGE_ATTACK_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_GESTURE_RELOAD_PISTOL ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_JUMP_PISTOL ); - - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_IDLE_SMG1 ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_RUN_SMG1 ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_IDLE_CROUCH_SMG1 ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_WALK_CROUCH_SMG1 ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG1 ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_GESTURE_RELOAD_SMG1 ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_JUMP_SMG1 ); - - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_IDLE_AR2 ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_RUN_AR2 ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_IDLE_CROUCH_AR2 ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_WALK_CROUCH_AR2 ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_GESTURE_RANGE_ATTACK_AR2 ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_GESTURE_RELOAD_AR2 ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_JUMP_AR2 ); - - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_IDLE_SHOTGUN ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_RUN_SHOTGUN ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_IDLE_CROUCH_SHOTGUN ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_WALK_CROUCH_SHOTGUN ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_GESTURE_RANGE_ATTACK_SHOTGUN ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_GESTURE_RELOAD_SHOTGUN ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_JUMP_SHOTGUN ); - - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_IDLE_RPG ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_RUN_RPG ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_IDLE_CROUCH_RPG ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_WALK_CROUCH_RPG ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_GESTURE_RANGE_ATTACK_RPG ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_GESTURE_RELOAD_RPG ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_JUMP_RPG ); - - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_IDLE_GRENADE ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_RUN_GRENADE ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_IDLE_CROUCH_GRENADE ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_WALK_CROUCH_GRENADE ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_GESTURE_RANGE_ATTACK_GRENADE ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_GESTURE_RELOAD_GRENADE ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_JUMP_GRENADE ); - - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_IDLE_PHYSGUN ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_RUN_PHYSGUN ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_IDLE_CROUCH_PHYSGUN ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_WALK_CROUCH_PHYSGUN ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_GESTURE_RANGE_ATTACK_PHYSGUN ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_GESTURE_RELOAD_PHYSGUN ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_JUMP_PHYSGUN ); - - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_IDLE_CROSSBOW ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_RUN_CROSSBOW ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_IDLE_CROUCH_CROSSBOW ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_WALK_CROUCH_CROSSBOW ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_GESTURE_RANGE_ATTACK_CROSSBOW ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_GESTURE_RELOAD_CROSSBOW ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_JUMP_CROSSBOW ); - - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_IDLE_MELEE ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_RUN_MELEE ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_IDLE_CROUCH_MELEE ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_WALK_CROUCH_MELEE ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_GESTURE_RELOAD_MELEE ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_JUMP_MELEE ); - - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_IDLE_SLAM ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_RUN_SLAM ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_IDLE_CROUCH_SLAM ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_WALK_CROUCH_SLAM ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_GESTURE_RANGE_ATTACK_SLAM ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_GESTURE_RELOAD_SLAM ); - REGISTER_SHARED_ACTIVITY ( ACT_HL2MP_JUMP_SLAM ); - - // Portal - REGISTER_SHARED_ACTIVITY ( ACT_VM_FIZZLE ); - - // Multiplayer - REGISTER_SHARED_ACTIVITY ( ACT_MP_STAND_IDLE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_CROUCH_IDLE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_CROUCH_DEPLOYED_IDLE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_CROUCH_DEPLOYED ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_DEPLOYED_IDLE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RUN ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_WALK ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_AIRWALK ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_CROUCHWALK ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_SPRINT ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP_START ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP_FLOAT ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP_LAND ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_DOUBLEJUMP ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_SWIM ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_DEPLOYED ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_SWIM_DEPLOYED ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_VCD ); - - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_STAND_PRIMARYFIRE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_STAND_PRIMARYFIRE_DEPLOYED ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_STAND_SECONDARYFIRE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_STAND_GRENADE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_CROUCH_PRIMARYFIRE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_CROUCH_PRIMARYFIRE_DEPLOYED ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_CROUCH_SECONDARYFIRE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_CROUCH_GRENADE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_SWIM_PRIMARYFIRE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_SWIM_SECONDARYFIRE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_SWIM_GRENADE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_AIRWALK_PRIMARYFIRE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_AIRWALK_SECONDARYFIRE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_AIRWALK_GRENADE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_STAND ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_STAND_LOOP ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_STAND_END ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_CROUCH ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_CROUCH_LOOP ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_CROUCH_END ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_SWIM ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_SWIM_LOOP ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_SWIM_END ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_AIRWALK ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_AIRWALK_LOOP ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_AIRWALK_END ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_STAND_PREFIRE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_STAND_POSTFIRE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_STAND_STARTFIRE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_CROUCH_PREFIRE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_CROUCH_POSTFIRE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_SWIM_PREFIRE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_SWIM_POSTFIRE ); - - // Multiplayer - Primary - REGISTER_SHARED_ACTIVITY ( ACT_MP_STAND_PRIMARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_CROUCH_PRIMARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RUN_PRIMARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_WALK_PRIMARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_AIRWALK_PRIMARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_CROUCHWALK_PRIMARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP_PRIMARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP_START_PRIMARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP_FLOAT_PRIMARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP_LAND_PRIMARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_SWIM_PRIMARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_DEPLOYED_PRIMARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_SWIM_DEPLOYED_PRIMARY ); - - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_STAND_PRIMARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_STAND_PRIMARY_DEPLOYED ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_CROUCH_PRIMARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_CROUCH_PRIMARY_DEPLOYED ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_SWIM_PRIMARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_AIRWALK_PRIMARY ); - - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_STAND_PRIMARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_STAND_PRIMARY_LOOP ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_STAND_PRIMARY_END ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_CROUCH_PRIMARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_CROUCH_PRIMARY_LOOP ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_CROUCH_PRIMARY_END ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_SWIM_PRIMARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_SWIM_PRIMARY_LOOP ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_SWIM_PRIMARY_END ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_AIRWALK_PRIMARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_AIRWALK_PRIMARY_LOOP ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_AIRWALK_PRIMARY_END ); - - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_STAND_GRENADE_PRIMARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_CROUCH_GRENADE_PRIMARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_SWIM_GRENADE_PRIMARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_AIRWALK_GRENADE_PRIMARY ); - - // Secondary - REGISTER_SHARED_ACTIVITY ( ACT_MP_STAND_SECONDARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_CROUCH_SECONDARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RUN_SECONDARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_WALK_SECONDARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_AIRWALK_SECONDARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_CROUCHWALK_SECONDARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP_SECONDARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP_START_SECONDARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP_FLOAT_SECONDARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP_LAND_SECONDARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_SWIM_SECONDARY ); - - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_STAND_SECONDARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_CROUCH_SECONDARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_SWIM_SECONDARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_AIRWALK_SECONDARY ); - - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_STAND_SECONDARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_STAND_SECONDARY_LOOP ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_STAND_SECONDARY_END ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_CROUCH_SECONDARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_CROUCH_SECONDARY_LOOP ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_CROUCH_SECONDARY_END ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_SWIM_SECONDARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_SWIM_SECONDARY_LOOP ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_SWIM_SECONDARY_END ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_AIRWALK_SECONDARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_AIRWALK_SECONDARY_LOOP ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RELOAD_AIRWALK_SECONDARY_END ); - - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_STAND_GRENADE_SECONDARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_CROUCH_GRENADE_SECONDARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_SWIM_GRENADE_SECONDARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_AIRWALK_GRENADE_SECONDARY ); - - // Melee - REGISTER_SHARED_ACTIVITY ( ACT_MP_STAND_MELEE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_CROUCH_MELEE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RUN_MELEE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_WALK_MELEE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_AIRWALK_MELEE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_CROUCHWALK_MELEE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP_MELEE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP_START_MELEE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP_FLOAT_MELEE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP_LAND_MELEE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_SWIM_MELEE ); - - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_STAND_MELEE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_STAND_MELEE_SECONDARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_CROUCH_MELEE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_CROUCH_MELEE_SECONDARY ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_SWIM_MELEE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_AIRWALK_MELEE ); - - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_STAND_GRENADE_MELEE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_CROUCH_GRENADE_MELEE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_SWIM_GRENADE_MELEE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_AIRWALK_GRENADE_MELEE ); - - // Flinches - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_FLINCH ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_FLINCH_PRIMARY ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_FLINCH_SECONDARY ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_FLINCH_MELEE ); - - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_FLINCH_HEAD ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_FLINCH_CHEST ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_FLINCH_STOMACH ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_FLINCH_LEFTARM ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_FLINCH_RIGHTARM ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_FLINCH_LEFTLEG ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_FLINCH_RIGHTLEG ); - - // TF Specific - REGISTER_SHARED_ACTIVITY ( ACT_MP_GRENADE1_DRAW ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_GRENADE1_IDLE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_GRENADE1_ATTACK ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_GRENADE2_DRAW ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_GRENADE2_IDLE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_GRENADE2_ATTACK ); - - REGISTER_SHARED_ACTIVITY ( ACT_MP_PRIMARY_GRENADE1_DRAW ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_PRIMARY_GRENADE1_IDLE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_PRIMARY_GRENADE1_ATTACK ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_PRIMARY_GRENADE2_DRAW ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_PRIMARY_GRENADE2_IDLE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_PRIMARY_GRENADE2_ATTACK ); - - REGISTER_SHARED_ACTIVITY ( ACT_MP_SECONDARY_GRENADE1_DRAW ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_SECONDARY_GRENADE1_IDLE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_SECONDARY_GRENADE1_ATTACK ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_SECONDARY_GRENADE2_DRAW ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_SECONDARY_GRENADE2_IDLE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_SECONDARY_GRENADE2_ATTACK ); - - REGISTER_SHARED_ACTIVITY ( ACT_MP_MELEE_GRENADE1_DRAW ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_MELEE_GRENADE1_IDLE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_MELEE_GRENADE1_ATTACK ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_MELEE_GRENADE2_DRAW ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_MELEE_GRENADE2_IDLE ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_MELEE_GRENADE2_ATTACK ); - - - // Building - REGISTER_SHARED_ACTIVITY ( ACT_MP_STAND_BUILDING ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_CROUCH_BUILDING ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RUN_BUILDING ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_WALK_BUILDING ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_AIRWALK_BUILDING ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_CROUCHWALK_BUILDING ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP_BUILDING ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP_START_BUILDING ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP_FLOAT_BUILDING ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP_LAND_BUILDING ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_SWIM_BUILDING ); - - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_STAND_BUILDING ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_CROUCH_BUILDING ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_SWIM_BUILDING ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_AIRWALK_BUILDING ); - - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_STAND_GRENADE_BUILDING ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_CROUCH_GRENADE_BUILDING ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_SWIM_GRENADE_BUILDING ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_AIRWALK_GRENADE_BUILDING ); - - // PDA - REGISTER_SHARED_ACTIVITY ( ACT_MP_STAND_PDA ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_CROUCH_PDA ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_RUN_PDA ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_WALK_PDA ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_AIRWALK_PDA ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_CROUCHWALK_PDA ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP_PDA ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP_START_PDA ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP_FLOAT_PDA ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_JUMP_LAND_PDA ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_SWIM_PDA ); - - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_STAND_PDA ); - REGISTER_SHARED_ACTIVITY ( ACT_MP_ATTACK_SWIM_PDA ); - - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_HANDMOUTH ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_FINGERPOINT ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_FISTPUMP ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_THUMBSUP ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_NODYES ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_NODNO ); - - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_HANDMOUTH_PRIMARY ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_FINGERPOINT_PRIMARY ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_FISTPUMP_PRIMARY ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_THUMBSUP_PRIMARY ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_NODYES_PRIMARY ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_NODNO_PRIMARY ); - - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_HANDMOUTH_SECONDARY ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_FINGERPOINT_SECONDARY ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_FISTPUMP_SECONDARY ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_THUMBSUP_SECONDARY ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_NODYES_SECONDARY ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_NODNO_SECONDARY ); - - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_HANDMOUTH_MELEE ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_FINGERPOINT_MELEE ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_FISTPUMP_MELEE ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_THUMBSUP_MELEE ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_NODYES_MELEE ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_NODNO_MELEE ); - - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_HANDMOUTH_BUILDING ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_FINGERPOINT_BUILDING ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_FISTPUMP_BUILDING ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_THUMBSUP_BUILDING ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_NODYES_BUILDING ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_NODNO_BUILDING ); - - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_HANDMOUTH_PDA ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_FINGERPOINT_PDA ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_FISTPUMP_PDA ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_THUMBSUP_PDA ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_NODYES_PDA ); - REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_NODNO_PDA ); - - REGISTER_SHARED_ACTIVITY ( ACT_VM_UNUSABLE ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_UNUSABLE_TO_USABLE ); - REGISTER_SHARED_ACTIVITY ( ACT_VM_USABLE_TO_UNUSABLE ); - - REGISTER_SHARED_ACTIVITY( ACT_PRIMARY_VM_DRAW ); - REGISTER_SHARED_ACTIVITY( ACT_PRIMARY_VM_HOLSTER ); - REGISTER_SHARED_ACTIVITY( ACT_PRIMARY_VM_IDLE ); - REGISTER_SHARED_ACTIVITY( ACT_PRIMARY_VM_PULLBACK ); - REGISTER_SHARED_ACTIVITY( ACT_PRIMARY_VM_PRIMARYATTACK ); - REGISTER_SHARED_ACTIVITY( ACT_PRIMARY_VM_SECONDARYATTACK ); - REGISTER_SHARED_ACTIVITY( ACT_PRIMARY_VM_RELOAD ); - REGISTER_SHARED_ACTIVITY( ACT_PRIMARY_VM_DRYFIRE ); - REGISTER_SHARED_ACTIVITY( ACT_PRIMARY_VM_IDLE_TO_LOWERED ); - REGISTER_SHARED_ACTIVITY( ACT_PRIMARY_VM_IDLE_LOWERED ); - REGISTER_SHARED_ACTIVITY( ACT_PRIMARY_VM_LOWERED_TO_IDLE ); - - REGISTER_SHARED_ACTIVITY( ACT_SECONDARY_VM_DRAW ); - REGISTER_SHARED_ACTIVITY( ACT_SECONDARY_VM_HOLSTER ); - REGISTER_SHARED_ACTIVITY( ACT_SECONDARY_VM_IDLE ); - REGISTER_SHARED_ACTIVITY( ACT_SECONDARY_VM_PULLBACK ); - REGISTER_SHARED_ACTIVITY( ACT_SECONDARY_VM_PRIMARYATTACK ); - REGISTER_SHARED_ACTIVITY( ACT_SECONDARY_VM_SECONDARYATTACK ); - REGISTER_SHARED_ACTIVITY( ACT_SECONDARY_VM_RELOAD ); - REGISTER_SHARED_ACTIVITY( ACT_SECONDARY_VM_DRYFIRE ); - REGISTER_SHARED_ACTIVITY( ACT_SECONDARY_VM_IDLE_TO_LOWERED ); - REGISTER_SHARED_ACTIVITY( ACT_SECONDARY_VM_IDLE_LOWERED ); - REGISTER_SHARED_ACTIVITY( ACT_SECONDARY_VM_LOWERED_TO_IDLE ); - - REGISTER_SHARED_ACTIVITY( ACT_MELEE_VM_DRAW ); - REGISTER_SHARED_ACTIVITY( ACT_MELEE_VM_HOLSTER ); - REGISTER_SHARED_ACTIVITY( ACT_MELEE_VM_IDLE ); - REGISTER_SHARED_ACTIVITY( ACT_MELEE_VM_PULLBACK ); - REGISTER_SHARED_ACTIVITY( ACT_MELEE_VM_PRIMARYATTACK ); - REGISTER_SHARED_ACTIVITY( ACT_MELEE_VM_SECONDARYATTACK ); - REGISTER_SHARED_ACTIVITY( ACT_MELEE_VM_RELOAD ); - REGISTER_SHARED_ACTIVITY( ACT_MELEE_VM_DRYFIRE ); - REGISTER_SHARED_ACTIVITY( ACT_MELEE_VM_IDLE_TO_LOWERED ); - REGISTER_SHARED_ACTIVITY( ACT_MELEE_VM_IDLE_LOWERED ); - REGISTER_SHARED_ACTIVITY( ACT_MELEE_VM_LOWERED_TO_IDLE ); - - REGISTER_SHARED_ACTIVITY( ACT_PDA_VM_DRAW ); - REGISTER_SHARED_ACTIVITY( ACT_PDA_VM_HOLSTER ); - REGISTER_SHARED_ACTIVITY( ACT_PDA_VM_IDLE ); - REGISTER_SHARED_ACTIVITY( ACT_PDA_VM_PULLBACK ); - REGISTER_SHARED_ACTIVITY( ACT_PDA_VM_PRIMARYATTACK ); - REGISTER_SHARED_ACTIVITY( ACT_PDA_VM_SECONDARYATTACK ); - REGISTER_SHARED_ACTIVITY( ACT_PDA_VM_RELOAD ); - REGISTER_SHARED_ACTIVITY( ACT_PDA_VM_DRYFIRE ); - REGISTER_SHARED_ACTIVITY( ACT_PDA_VM_IDLE_TO_LOWERED ); - REGISTER_SHARED_ACTIVITY( ACT_PDA_VM_IDLE_LOWERED ); - REGISTER_SHARED_ACTIVITY( ACT_PDA_VM_LOWERED_TO_IDLE ); - - AssertMsg( g_HighestActivity == LAST_SHARED_ACTIVITY - 1, "Not all activities from ai_activity.h registered in activitylist.cpp" ); -} - -// HACKHACK: Keep backwards compatibility on broken activities temporarily -#define ACTIVITY_FILE_TAG 0x80800000 - -class CActivityDataOps : public CDefSaveRestoreOps -{ -public: - // save data type interface - virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave ) - { - int activityIndex = *((int *)fieldInfo.pField); - const char *pActivityName = ActivityList_NameForIndex( activityIndex ); - if ( !pActivityName ) - { - AssertOnce( activityIndex == -1 ); // FIXME: whatever activity this was, it's now being saved out as ACT_RESET - pActivityName = ActivityList_NameForIndex( 0 ); - } - int len = strlen(pActivityName) + 1; - - // Use the high 16-bits of this int to signify this file format - // this makes this backwards compatible. - // UNDONE: Remove after playtest save files are no longer needed - len |= ACTIVITY_FILE_TAG; - pSave->WriteInt( &len ); - pSave->WriteString( pActivityName ); - } - - virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore ) - { - char nameBuf[1024]; - - int *pActivityIndex = (int *)fieldInfo.pField; - - int nameLen = pRestore->ReadInt(); - if ( (nameLen & 0xFFFF0000) != ACTIVITY_FILE_TAG ) - { - // old save file, this is an index, not a name - *pActivityIndex = nameLen; - return; - } - nameLen &= 0xFFFF; - pRestore->ReadString( nameBuf, sizeof(nameBuf), nameLen ); - *pActivityIndex = ActivityList_IndexForName( nameBuf ); - if ( *pActivityIndex < 0 ) - { - *pActivityIndex = 0; - } - } - - virtual bool IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - int *pActivityIndex = (int *)fieldInfo.pField; - return (*pActivityIndex == 0); - } - - virtual void MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - int *pActivityIndex = (int *)fieldInfo.pField; - *pActivityIndex = 0; - } -}; - -static CActivityDataOps g_ActivityDataOps; - -ISaveRestoreOps* ActivityDataOps() -{ - return &g_ActivityDataOps; -} - - - - -void UTIL_LoadActivityRemapFile( const char *filename, const char *section, CUtlVector &entries ) -{ - int iIndex = m_ActivityRemapDatabase.Find( filename ); - - if ( iIndex != m_ActivityRemapDatabase.InvalidIndex() ) - { - CActivityRemapCache *actRemap = &m_ActivityRemapDatabase[iIndex]; - entries.AddVectorToTail( actRemap->m_cachedActivityRemaps ); - return; - } - - KeyValues *pkvFile = new KeyValues( section ); - - if ( pkvFile->LoadFromFile( filesystem, filename, NULL ) ) - { - KeyValues *pTestKey = pkvFile->GetFirstSubKey(); - - CActivityRemapCache actRemap; - - while ( pTestKey ) - { - Activity ActBase = (Activity)ActivityList_IndexForName( pTestKey->GetName() ); - - if ( ActBase != ACT_INVALID ) - { - KeyValues *pRemapKey = pTestKey->GetFirstSubKey(); - - CActivityRemap actMap; - actMap.mappedActivity = ACT_IDLE; - actMap.activity = ActBase; - - while ( pRemapKey ) - { - const char *pKeyName = pRemapKey->GetName(); - const char *pKeyValue = pRemapKey->GetString(); - - if ( !stricmp( pKeyName, "remapactivity" ) ) - { - Activity Act = (Activity)ActivityList_IndexForName( pKeyValue ); - - if ( Act == ACT_INVALID ) - { - actMap.mappedActivity = ActivityList_RegisterPrivateActivity( pKeyValue ); - } - else - { - actMap.mappedActivity = Act; - } - } - else if ( !stricmp( pKeyName, "extra" ) ) - { - actMap.SetExtraKeyValueBlock( pRemapKey->MakeCopy() ); - } - - pRemapKey = pRemapKey->GetNextKey(); - } - - entries.AddToTail( actMap ); - } - - pTestKey = pTestKey->GetNextKey(); - } - - actRemap.m_cachedActivityRemaps.AddVectorToTail( entries ); - m_ActivityRemapDatabase.Insert( filename, actRemap ); - } -} - -int ActivityList_HighestIndex() -{ - return g_HighestActivity; -} diff --git a/game/shared/activitylist.h b/game/shared/activitylist.h deleted file mode 100644 index 6b86684fb..000000000 --- a/game/shared/activitylist.h +++ /dev/null @@ -1,100 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ACTIVITYLIST_H -#define ACTIVITYLIST_H -#ifdef _WIN32 -#pragma once -#endif - -#include - -typedef struct activityentry_s activityentry_t; - -class CActivityRemap -{ -public: - - CActivityRemap() - { - pExtraBlock = NULL; - } - - void SetExtraKeyValueBlock ( KeyValues *pKVBlock ) - { - pExtraBlock = pKVBlock; - } - - KeyValues *GetExtraKeyValueBlock ( void ) { return pExtraBlock; } - - Activity activity; - Activity mappedActivity; - -private: - - KeyValues *pExtraBlock; -}; - - -class CActivityRemapCache -{ -public: - - CActivityRemapCache() - { - } - - CActivityRemapCache( const CActivityRemapCache& src ) - { - int c = src.m_cachedActivityRemaps.Count(); - for ( int i = 0; i < c; i++ ) - { - m_cachedActivityRemaps.AddToTail( src.m_cachedActivityRemaps[ i ] ); - } - } - - CActivityRemapCache& operator = ( const CActivityRemapCache& src ) - { - if ( this == &src ) - return *this; - - int c = src.m_cachedActivityRemaps.Count(); - for ( int i = 0; i < c; i++ ) - { - m_cachedActivityRemaps.AddToTail( src.m_cachedActivityRemaps[ i ] ); - } - - return *this; - } - - CUtlVector< CActivityRemap > m_cachedActivityRemaps; -}; - -void UTIL_LoadActivityRemapFile( const char *filename, const char *section, CUtlVector &entries ); - -//========================================================= -//========================================================= -extern void ActivityList_Init( void ); -extern void ActivityList_Free( void ); -extern bool ActivityList_RegisterSharedActivity( const char *pszActivityName, int iActivityIndex ); -extern Activity ActivityList_RegisterPrivateActivity( const char *pszActivityName ); -extern int ActivityList_IndexForName( const char *pszActivityName ); -extern const char *ActivityList_NameForIndex( int iActivityIndex ); -extern int ActivityList_HighestIndex(); - -// This macro guarantees that the names of each activity and the constant used to -// reference it in the code are identical. -#define REGISTER_SHARED_ACTIVITY( _n ) ActivityList_RegisterSharedActivity(#_n, _n); -#define REGISTER_PRIVATE_ACTIVITY( _n ) _n = ActivityList_RegisterPrivateActivity( #_n ); - -// Implemented in shared code -extern void ActivityList_RegisterSharedActivities( void ); - -class ISaveRestoreOps; -extern ISaveRestoreOps* ActivityDataOps(); - -#endif // ACTIVITYLIST_H diff --git a/game/shared/ai_activity.h b/game/shared/ai_activity.h deleted file mode 100644 index 6c9b736f0..000000000 --- a/game/shared/ai_activity.h +++ /dev/null @@ -1,1649 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_ACTIVITY_H -#define AI_ACTIVITY_H -#ifdef _WIN32 -#pragma once -#endif - -#define ACTIVITY_NOT_AVAILABLE -1 - -typedef enum -{ - ACT_INVALID = -1, // So we have something more succint to check for than '-1' - ACT_RESET = 0, // Set m_Activity to this invalid value to force a reset to m_IdealActivity - ACT_IDLE, - ACT_TRANSITION, - ACT_COVER, // FIXME: obsolete? redundant with ACT_COVER_LOW? - ACT_COVER_MED, // FIXME: unsupported? - ACT_COVER_LOW, // FIXME: rename ACT_IDLE_CROUCH? - ACT_WALK, - ACT_WALK_AIM, - ACT_WALK_CROUCH, - ACT_WALK_CROUCH_AIM, - ACT_RUN, - ACT_RUN_AIM, - ACT_RUN_CROUCH, - ACT_RUN_CROUCH_AIM, - ACT_RUN_PROTECTED, - ACT_SCRIPT_CUSTOM_MOVE, - ACT_RANGE_ATTACK1, - ACT_RANGE_ATTACK2, - ACT_RANGE_ATTACK1_LOW, // FIXME: not used yet, crouched versions of the range attack - ACT_RANGE_ATTACK2_LOW, // FIXME: not used yet, crouched versions of the range attack - ACT_DIESIMPLE, - ACT_DIEBACKWARD, - ACT_DIEFORWARD, - ACT_DIEVIOLENT, - ACT_DIERAGDOLL, - ACT_FLY, // Fly (and flap if appropriate) - ACT_HOVER, - ACT_GLIDE, - ACT_SWIM, - ACT_JUMP, - ACT_HOP, // vertical jump - ACT_LEAP, // long forward jump - ACT_LAND, - ACT_CLIMB_UP, - ACT_CLIMB_DOWN, - ACT_CLIMB_DISMOUNT, - ACT_SHIPLADDER_UP, - ACT_SHIPLADDER_DOWN, - ACT_STRAFE_LEFT, - ACT_STRAFE_RIGHT, - ACT_ROLL_LEFT, // tuck and roll, left - ACT_ROLL_RIGHT, // tuck and roll, right - ACT_TURN_LEFT, // turn quickly left (stationary) - ACT_TURN_RIGHT, // turn quickly right (stationary) - ACT_CROUCH, // FIXME: obsolete? only used be soldier (the act of crouching down from a standing position) - ACT_CROUCHIDLE, // FIXME: obsolete? only used be soldier (holding body in crouched position (loops)) - ACT_STAND, // FIXME: obsolete? should be transition (the act of standing from a crouched position) - ACT_USE, - ACT_SIGNAL1, - ACT_SIGNAL2, - ACT_SIGNAL3, - - ACT_SIGNAL_ADVANCE, // Squad handsignals, specific. - ACT_SIGNAL_FORWARD, - ACT_SIGNAL_GROUP, - ACT_SIGNAL_HALT, - ACT_SIGNAL_LEFT, - ACT_SIGNAL_RIGHT, - ACT_SIGNAL_TAKECOVER, - - ACT_LOOKBACK_RIGHT, // look back over shoulder without turning around. - ACT_LOOKBACK_LEFT, - ACT_COWER, // FIXME: unused, should be more extreme version of crouching - ACT_SMALL_FLINCH, // FIXME: needed? shouldn't flinching be down with overlays? - ACT_BIG_FLINCH, - ACT_MELEE_ATTACK1, - ACT_MELEE_ATTACK2, - ACT_RELOAD, - ACT_RELOAD_START, - ACT_RELOAD_FINISH, - ACT_RELOAD_LOW, - ACT_ARM, // pull out gun, for instance - ACT_DISARM, // reholster gun - ACT_DROP_WEAPON, - ACT_DROP_WEAPON_SHOTGUN, - ACT_PICKUP_GROUND, // pick up something in front of you on the ground - ACT_PICKUP_RACK, // pick up something from a rack or shelf in front of you. - ACT_IDLE_ANGRY, // FIXME: being used as an combat ready idle? alternate idle animation in which the monster is clearly agitated. (loop) - - ACT_IDLE_RELAXED, - ACT_IDLE_STIMULATED, - ACT_IDLE_AGITATED, - ACT_IDLE_STEALTH, - ACT_IDLE_HURT, - - ACT_WALK_RELAXED, - ACT_WALK_STIMULATED, - ACT_WALK_AGITATED, - ACT_WALK_STEALTH, - - ACT_RUN_RELAXED, - ACT_RUN_STIMULATED, - ACT_RUN_AGITATED, - ACT_RUN_STEALTH, - - ACT_IDLE_AIM_RELAXED, - ACT_IDLE_AIM_STIMULATED, - ACT_IDLE_AIM_AGITATED, - ACT_IDLE_AIM_STEALTH, - - ACT_WALK_AIM_RELAXED, - ACT_WALK_AIM_STIMULATED, - ACT_WALK_AIM_AGITATED, - ACT_WALK_AIM_STEALTH, - - ACT_RUN_AIM_RELAXED, - ACT_RUN_AIM_STIMULATED, - ACT_RUN_AIM_AGITATED, - ACT_RUN_AIM_STEALTH, - - ACT_CROUCHIDLE_STIMULATED, - ACT_CROUCHIDLE_AIM_STIMULATED, - ACT_CROUCHIDLE_AGITATED, - - ACT_WALK_HURT, // limp (loop) - ACT_RUN_HURT, // limp (loop) - ACT_SPECIAL_ATTACK1, // very monster specific special attacks. - ACT_SPECIAL_ATTACK2, - ACT_COMBAT_IDLE, // FIXME: unused? agitated idle. - ACT_WALK_SCARED, - ACT_RUN_SCARED, - ACT_VICTORY_DANCE, // killed a player, do a victory dance. - ACT_DIE_HEADSHOT, // die, hit in head. - ACT_DIE_CHESTSHOT, // die, hit in chest - ACT_DIE_GUTSHOT, // die, hit in gut - ACT_DIE_BACKSHOT, // die, hit in back - ACT_FLINCH_HEAD, - ACT_FLINCH_CHEST, - ACT_FLINCH_STOMACH, - ACT_FLINCH_LEFTARM, - ACT_FLINCH_RIGHTARM, - ACT_FLINCH_LEFTLEG, - ACT_FLINCH_RIGHTLEG, - ACT_FLINCH_PHYSICS, - - ACT_IDLE_ON_FIRE, // ON FIRE animations - ACT_WALK_ON_FIRE, - ACT_RUN_ON_FIRE, - - ACT_RAPPEL_LOOP, // Rappel down a rope! - - ACT_180_LEFT, // 180 degree left turn - ACT_180_RIGHT, - - ACT_90_LEFT, // 90 degree turns - ACT_90_RIGHT, - - ACT_STEP_LEFT, // Single steps - ACT_STEP_RIGHT, - ACT_STEP_BACK, - ACT_STEP_FORE, - - ACT_GESTURE_RANGE_ATTACK1, - ACT_GESTURE_RANGE_ATTACK2, - ACT_GESTURE_MELEE_ATTACK1, - ACT_GESTURE_MELEE_ATTACK2, - ACT_GESTURE_RANGE_ATTACK1_LOW, // FIXME: not used yet, crouched versions of the range attack - ACT_GESTURE_RANGE_ATTACK2_LOW, // FIXME: not used yet, crouched versions of the range attack - - ACT_MELEE_ATTACK_SWING_GESTURE, - - ACT_GESTURE_SMALL_FLINCH, - ACT_GESTURE_BIG_FLINCH, - ACT_GESTURE_FLINCH_BLAST, // Startled by an explosion - ACT_GESTURE_FLINCH_BLAST_SHOTGUN, - ACT_GESTURE_FLINCH_BLAST_DAMAGED, // Damaged by an explosion - ACT_GESTURE_FLINCH_BLAST_DAMAGED_SHOTGUN, - ACT_GESTURE_FLINCH_HEAD, - ACT_GESTURE_FLINCH_CHEST, - ACT_GESTURE_FLINCH_STOMACH, - ACT_GESTURE_FLINCH_LEFTARM, - ACT_GESTURE_FLINCH_RIGHTARM, - ACT_GESTURE_FLINCH_LEFTLEG, - ACT_GESTURE_FLINCH_RIGHTLEG, - - ACT_GESTURE_TURN_LEFT, - ACT_GESTURE_TURN_RIGHT, - ACT_GESTURE_TURN_LEFT45, - ACT_GESTURE_TURN_RIGHT45, - ACT_GESTURE_TURN_LEFT90, - ACT_GESTURE_TURN_RIGHT90, - ACT_GESTURE_TURN_LEFT45_FLAT, - ACT_GESTURE_TURN_RIGHT45_FLAT, - ACT_GESTURE_TURN_LEFT90_FLAT, - ACT_GESTURE_TURN_RIGHT90_FLAT, - - // HALF-LIFE 1 compatability stuff goes here. Temporary! - ACT_BARNACLE_HIT, // barnacle tongue hits a monster - ACT_BARNACLE_PULL, // barnacle is lifting the monster ( loop ) - ACT_BARNACLE_CHOMP, // barnacle latches on to the monster - ACT_BARNACLE_CHEW, // barnacle is holding the monster in its mouth ( loop ) - - // Sometimes, you just want to set an NPC's sequence to a sequence that doesn't actually - // have an activity. The AI will reset the NPC's sequence to whatever its IDEAL activity - // is, though. So if you set ideal activity to DO_NOT_DISTURB, the AI will not interfere - // with the NPC's current sequence. (SJB) - ACT_DO_NOT_DISTURB, - - // viewmodel (weapon) activities - // FIXME: move these to the specific viewmodels, no need to make global - ACT_VM_DRAW, - ACT_VM_HOLSTER, - ACT_VM_IDLE, - ACT_VM_FIDGET, - ACT_VM_PULLBACK, - ACT_VM_PULLBACK_HIGH, - ACT_VM_PULLBACK_LOW, - ACT_VM_THROW, - ACT_VM_PULLPIN, - ACT_VM_PRIMARYATTACK, // fire - ACT_VM_SECONDARYATTACK, // alt. fire - ACT_VM_RELOAD, - ACT_VM_DRYFIRE, // fire with no ammo loaded. - ACT_VM_HITLEFT, // bludgeon, swing to left - hit (primary attk) - ACT_VM_HITLEFT2, // bludgeon, swing to left - hit (secondary attk) - ACT_VM_HITRIGHT, // bludgeon, swing to right - hit (primary attk) - ACT_VM_HITRIGHT2, // bludgeon, swing to right - hit (secondary attk) - ACT_VM_HITCENTER, // bludgeon, swing center - hit (primary attk) - ACT_VM_HITCENTER2, // bludgeon, swing center - hit (secondary attk) - ACT_VM_MISSLEFT, // bludgeon, swing to left - miss (primary attk) - ACT_VM_MISSLEFT2, // bludgeon, swing to left - miss (secondary attk) - ACT_VM_MISSRIGHT, // bludgeon, swing to right - miss (primary attk) - ACT_VM_MISSRIGHT2, // bludgeon, swing to right - miss (secondary attk) - ACT_VM_MISSCENTER, // bludgeon, swing center - miss (primary attk) - ACT_VM_MISSCENTER2, // bludgeon, swing center - miss (secondary attk) - ACT_VM_HAULBACK, // bludgeon, haul the weapon back for a hard strike (secondary attk) - ACT_VM_SWINGHARD, // bludgeon, release the hard strike (secondary attk) - ACT_VM_SWINGMISS, - ACT_VM_SWINGHIT, - ACT_VM_IDLE_TO_LOWERED, - ACT_VM_IDLE_LOWERED, - ACT_VM_LOWERED_TO_IDLE, - ACT_VM_RECOIL1, - ACT_VM_RECOIL2, - ACT_VM_RECOIL3, - ACT_VM_PICKUP, - ACT_VM_RELEASE, - - ACT_VM_ATTACH_SILENCER, - ACT_VM_DETACH_SILENCER, - -//=========================== -// HL2 Specific Activities -//=========================== - // SLAM Specialty Activities - ACT_SLAM_STICKWALL_IDLE, - ACT_SLAM_STICKWALL_ND_IDLE, - ACT_SLAM_STICKWALL_ATTACH, - ACT_SLAM_STICKWALL_ATTACH2, - ACT_SLAM_STICKWALL_ND_ATTACH, - ACT_SLAM_STICKWALL_ND_ATTACH2, - ACT_SLAM_STICKWALL_DETONATE, - ACT_SLAM_STICKWALL_DETONATOR_HOLSTER, - ACT_SLAM_STICKWALL_DRAW, - ACT_SLAM_STICKWALL_ND_DRAW, - ACT_SLAM_STICKWALL_TO_THROW, - ACT_SLAM_STICKWALL_TO_THROW_ND, - ACT_SLAM_STICKWALL_TO_TRIPMINE_ND, - ACT_SLAM_THROW_IDLE, - ACT_SLAM_THROW_ND_IDLE, - ACT_SLAM_THROW_THROW, - ACT_SLAM_THROW_THROW2, - ACT_SLAM_THROW_THROW_ND, - ACT_SLAM_THROW_THROW_ND2, - ACT_SLAM_THROW_DRAW, - ACT_SLAM_THROW_ND_DRAW, - ACT_SLAM_THROW_TO_STICKWALL, - ACT_SLAM_THROW_TO_STICKWALL_ND, - ACT_SLAM_THROW_DETONATE, - ACT_SLAM_THROW_DETONATOR_HOLSTER, - ACT_SLAM_THROW_TO_TRIPMINE_ND, - ACT_SLAM_TRIPMINE_IDLE, - ACT_SLAM_TRIPMINE_DRAW, - ACT_SLAM_TRIPMINE_ATTACH, - ACT_SLAM_TRIPMINE_ATTACH2, - ACT_SLAM_TRIPMINE_TO_STICKWALL_ND, - ACT_SLAM_TRIPMINE_TO_THROW_ND, - ACT_SLAM_DETONATOR_IDLE, - ACT_SLAM_DETONATOR_DRAW, - ACT_SLAM_DETONATOR_DETONATE, - ACT_SLAM_DETONATOR_HOLSTER, - ACT_SLAM_DETONATOR_STICKWALL_DRAW, - ACT_SLAM_DETONATOR_THROW_DRAW, - - // Shotgun Specialty Activities - ACT_SHOTGUN_RELOAD_START, - ACT_SHOTGUN_RELOAD_FINISH, - ACT_SHOTGUN_PUMP, - - // SMG2 special activities - ACT_SMG2_IDLE2, - ACT_SMG2_FIRE2, - ACT_SMG2_DRAW2, - ACT_SMG2_RELOAD2, - ACT_SMG2_DRYFIRE2, - ACT_SMG2_TOAUTO, - ACT_SMG2_TOBURST, - - // Physcannon special activities - ACT_PHYSCANNON_UPGRADE, - - // weapon override activities - ACT_RANGE_ATTACK_AR1, - ACT_RANGE_ATTACK_AR2, - ACT_RANGE_ATTACK_AR2_LOW, - ACT_RANGE_ATTACK_AR2_GRENADE, - ACT_RANGE_ATTACK_HMG1, - ACT_RANGE_ATTACK_ML, - ACT_RANGE_ATTACK_SMG1, - ACT_RANGE_ATTACK_SMG1_LOW, - ACT_RANGE_ATTACK_SMG2, - ACT_RANGE_ATTACK_SHOTGUN, - ACT_RANGE_ATTACK_SHOTGUN_LOW, - ACT_RANGE_ATTACK_PISTOL, - ACT_RANGE_ATTACK_PISTOL_LOW, - ACT_RANGE_ATTACK_SLAM, - ACT_RANGE_ATTACK_TRIPWIRE, - ACT_RANGE_ATTACK_THROW, - ACT_RANGE_ATTACK_SNIPER_RIFLE, - ACT_RANGE_ATTACK_RPG, - ACT_MELEE_ATTACK_SWING, - - ACT_RANGE_AIM_LOW, - ACT_RANGE_AIM_SMG1_LOW, - ACT_RANGE_AIM_PISTOL_LOW, - ACT_RANGE_AIM_AR2_LOW, - - ACT_COVER_PISTOL_LOW, - ACT_COVER_SMG1_LOW, - - // weapon override activities - ACT_GESTURE_RANGE_ATTACK_AR1, - ACT_GESTURE_RANGE_ATTACK_AR2, - ACT_GESTURE_RANGE_ATTACK_AR2_GRENADE, - ACT_GESTURE_RANGE_ATTACK_HMG1, - ACT_GESTURE_RANGE_ATTACK_ML, - ACT_GESTURE_RANGE_ATTACK_SMG1, - ACT_GESTURE_RANGE_ATTACK_SMG1_LOW, - ACT_GESTURE_RANGE_ATTACK_SMG2, - ACT_GESTURE_RANGE_ATTACK_SHOTGUN, - ACT_GESTURE_RANGE_ATTACK_PISTOL, - ACT_GESTURE_RANGE_ATTACK_PISTOL_LOW, - ACT_GESTURE_RANGE_ATTACK_SLAM, - ACT_GESTURE_RANGE_ATTACK_TRIPWIRE, - ACT_GESTURE_RANGE_ATTACK_THROW, - ACT_GESTURE_RANGE_ATTACK_SNIPER_RIFLE, - ACT_GESTURE_MELEE_ATTACK_SWING, - - ACT_IDLE_RIFLE, - ACT_IDLE_SMG1, - ACT_IDLE_ANGRY_SMG1, - ACT_IDLE_PISTOL, - ACT_IDLE_ANGRY_PISTOL, - ACT_IDLE_ANGRY_SHOTGUN, - ACT_IDLE_STEALTH_PISTOL, - - ACT_IDLE_PACKAGE, - ACT_WALK_PACKAGE, - ACT_IDLE_SUITCASE, - ACT_WALK_SUITCASE, - - ACT_IDLE_SMG1_RELAXED, - ACT_IDLE_SMG1_STIMULATED, - ACT_WALK_RIFLE_RELAXED, - ACT_RUN_RIFLE_RELAXED, - ACT_WALK_RIFLE_STIMULATED, - ACT_RUN_RIFLE_STIMULATED, - - ACT_IDLE_AIM_RIFLE_STIMULATED, - ACT_WALK_AIM_RIFLE_STIMULATED, - ACT_RUN_AIM_RIFLE_STIMULATED, - - ACT_IDLE_SHOTGUN_RELAXED, - ACT_IDLE_SHOTGUN_STIMULATED, - ACT_IDLE_SHOTGUN_AGITATED, - - // Policing activities - ACT_WALK_ANGRY, - ACT_POLICE_HARASS1, - ACT_POLICE_HARASS2, - - // Manned guns - ACT_IDLE_MANNEDGUN, - - // Melee weapon - ACT_IDLE_MELEE, - ACT_IDLE_ANGRY_MELEE, - - // RPG activities - ACT_IDLE_RPG_RELAXED, - ACT_IDLE_RPG, - ACT_IDLE_ANGRY_RPG, - ACT_COVER_LOW_RPG, - ACT_WALK_RPG, - ACT_RUN_RPG, - ACT_WALK_CROUCH_RPG, - ACT_RUN_CROUCH_RPG, - ACT_WALK_RPG_RELAXED, - ACT_RUN_RPG_RELAXED, - - ACT_WALK_RIFLE, - ACT_WALK_AIM_RIFLE, - ACT_WALK_CROUCH_RIFLE, - ACT_WALK_CROUCH_AIM_RIFLE, - ACT_RUN_RIFLE, - ACT_RUN_AIM_RIFLE, - ACT_RUN_CROUCH_RIFLE, - ACT_RUN_CROUCH_AIM_RIFLE, - ACT_RUN_STEALTH_PISTOL, - - ACT_WALK_AIM_SHOTGUN, - ACT_RUN_AIM_SHOTGUN, - - ACT_WALK_PISTOL, - ACT_RUN_PISTOL, - ACT_WALK_AIM_PISTOL, - ACT_RUN_AIM_PISTOL, - ACT_WALK_STEALTH_PISTOL, - ACT_WALK_AIM_STEALTH_PISTOL, - ACT_RUN_AIM_STEALTH_PISTOL, - - // Reloads - ACT_RELOAD_PISTOL, - ACT_RELOAD_PISTOL_LOW, - ACT_RELOAD_SMG1, - ACT_RELOAD_SMG1_LOW, - ACT_RELOAD_SHOTGUN, - ACT_RELOAD_SHOTGUN_LOW, - - ACT_GESTURE_RELOAD, - ACT_GESTURE_RELOAD_PISTOL, - ACT_GESTURE_RELOAD_SMG1, - ACT_GESTURE_RELOAD_SHOTGUN, - - // Busy animations - ACT_BUSY_LEAN_LEFT, - ACT_BUSY_LEAN_LEFT_ENTRY, - ACT_BUSY_LEAN_LEFT_EXIT, - ACT_BUSY_LEAN_BACK, - ACT_BUSY_LEAN_BACK_ENTRY, - ACT_BUSY_LEAN_BACK_EXIT, - ACT_BUSY_SIT_GROUND, - ACT_BUSY_SIT_GROUND_ENTRY, - ACT_BUSY_SIT_GROUND_EXIT, - ACT_BUSY_SIT_CHAIR, - ACT_BUSY_SIT_CHAIR_ENTRY, - ACT_BUSY_SIT_CHAIR_EXIT, - ACT_BUSY_STAND, - ACT_BUSY_QUEUE, - - // Dodge animations - ACT_DUCK_DODGE, - - // For NPCs being lifted/eaten by barnacles: - // being swallowed by a barnacle - ACT_DIE_BARNACLE_SWALLOW, - // being lifted by a barnacle - ACT_GESTURE_BARNACLE_STRANGLE, - - ACT_PHYSCANNON_DETACH, // An activity to be played if we're picking this up with the physcannon - ACT_PHYSCANNON_ANIMATE, // An activity to be played by an object being picked up with the physcannon, but has different behavior to DETACH - ACT_PHYSCANNON_ANIMATE_PRE, // An activity to be played by an object being picked up with the physcannon, before playing the ACT_PHYSCANNON_ANIMATE - ACT_PHYSCANNON_ANIMATE_POST,// An activity to be played by an object being picked up with the physcannon, after playing the ACT_PHYSCANNON_ANIMATE - - ACT_DIE_FRONTSIDE, - ACT_DIE_RIGHTSIDE, - ACT_DIE_BACKSIDE, - ACT_DIE_LEFTSIDE, - - ACT_OPEN_DOOR, - - // Dynamic interactions - ACT_DI_ALYX_ZOMBIE_MELEE, - ACT_DI_ALYX_ZOMBIE_TORSO_MELEE, - ACT_DI_ALYX_HEADCRAB_MELEE, - ACT_DI_ALYX_ANTLION, - - ACT_DI_ALYX_ZOMBIE_SHOTGUN64, - ACT_DI_ALYX_ZOMBIE_SHOTGUN26, - - ACT_READINESS_RELAXED_TO_STIMULATED, - ACT_READINESS_RELAXED_TO_STIMULATED_WALK, - ACT_READINESS_AGITATED_TO_STIMULATED, - ACT_READINESS_STIMULATED_TO_RELAXED, - - ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED, - ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED_WALK, - ACT_READINESS_PISTOL_AGITATED_TO_STIMULATED, - ACT_READINESS_PISTOL_STIMULATED_TO_RELAXED, - - ACT_IDLE_CARRY, - ACT_WALK_CARRY, - -//=========================== -// TF2 Specific Activities -//=========================== - ACT_STARTDYING, - ACT_DYINGLOOP, - ACT_DYINGTODEAD, - - ACT_RIDE_MANNED_GUN, - - // All viewmodels - ACT_VM_SPRINT_ENTER, - ACT_VM_SPRINT_IDLE, - ACT_VM_SPRINT_LEAVE, - - // Looping weapon firing - ACT_FIRE_START, - ACT_FIRE_LOOP, - ACT_FIRE_END, - - ACT_CROUCHING_GRENADEIDLE, - ACT_CROUCHING_GRENADEREADY, - ACT_CROUCHING_PRIMARYATTACK, - ACT_OVERLAY_GRENADEIDLE, - ACT_OVERLAY_GRENADEREADY, - ACT_OVERLAY_PRIMARYATTACK, - ACT_OVERLAY_SHIELD_UP, - ACT_OVERLAY_SHIELD_DOWN, - ACT_OVERLAY_SHIELD_UP_IDLE, - ACT_OVERLAY_SHIELD_ATTACK, - ACT_OVERLAY_SHIELD_KNOCKBACK, - ACT_SHIELD_UP, - ACT_SHIELD_DOWN, - ACT_SHIELD_UP_IDLE, - ACT_SHIELD_ATTACK, - ACT_SHIELD_KNOCKBACK, - ACT_CROUCHING_SHIELD_UP, - ACT_CROUCHING_SHIELD_DOWN, - ACT_CROUCHING_SHIELD_UP_IDLE, - ACT_CROUCHING_SHIELD_ATTACK, - ACT_CROUCHING_SHIELD_KNOCKBACK, - - // turning in place - ACT_TURNRIGHT45, - ACT_TURNLEFT45, - - ACT_TURN, - - ACT_OBJ_ASSEMBLING, - ACT_OBJ_DISMANTLING, - ACT_OBJ_STARTUP, - ACT_OBJ_RUNNING, - ACT_OBJ_IDLE, - ACT_OBJ_PLACING, - ACT_OBJ_DETERIORATING, - ACT_OBJ_UPGRADING, - - // Deploy - ACT_DEPLOY, - ACT_DEPLOY_IDLE, - ACT_UNDEPLOY, - -//=========================== -// HL1 Specific Activities -//=========================== - // Grenades - ACT_GRENADE_ROLL, - ACT_GRENADE_TOSS, - - // Hand grenade - ACT_HANDGRENADE_THROW1, - ACT_HANDGRENADE_THROW2, - ACT_HANDGRENADE_THROW3, - - // Shotgun - ACT_SHOTGUN_IDLE_DEEP, - ACT_SHOTGUN_IDLE4, - - // Glock - ACT_GLOCK_SHOOTEMPTY, - ACT_GLOCK_SHOOT_RELOAD, - - // RPG - ACT_RPG_DRAW_UNLOADED, - ACT_RPG_HOLSTER_UNLOADED, - ACT_RPG_IDLE_UNLOADED, - ACT_RPG_FIDGET_UNLOADED, - - // Crossbow - ACT_CROSSBOW_DRAW_UNLOADED, - ACT_CROSSBOW_IDLE_UNLOADED, - ACT_CROSSBOW_FIDGET_UNLOADED, - - // Gauss - ACT_GAUSS_SPINUP, - ACT_GAUSS_SPINCYCLE, - - // Tripmine - ACT_TRIPMINE_GROUND, - ACT_TRIPMINE_WORLD, - -//=========================== -// CSPort Specific Activities -//=========================== - - ACT_VM_PRIMARYATTACK_SILENCED, // fire - ACT_VM_RELOAD_SILENCED, - ACT_VM_DRYFIRE_SILENCED, // fire with no ammo loaded. - ACT_VM_IDLE_SILENCED, - ACT_VM_DRAW_SILENCED, - ACT_VM_IDLE_EMPTY_LEFT, - ACT_VM_DRYFIRE_LEFT, - - ACT_PLAYER_IDLE_FIRE, - ACT_PLAYER_CROUCH_FIRE, - ACT_PLAYER_CROUCH_WALK_FIRE, - ACT_PLAYER_WALK_FIRE, - ACT_PLAYER_RUN_FIRE, - - ACT_IDLETORUN, - ACT_RUNTOIDLE, - - -//=========================== -// DoD Specific Activities -//=========================== - ACT_SPRINT, - - ACT_GET_DOWN_STAND, - ACT_GET_UP_STAND, - ACT_GET_DOWN_CROUCH, - ACT_GET_UP_CROUCH, - ACT_PRONE_FORWARD, - ACT_PRONE_IDLE, - - ACT_DEEPIDLE1, - ACT_DEEPIDLE2, - ACT_DEEPIDLE3, - ACT_DEEPIDLE4, - - ACT_VM_RELOAD_DEPLOYED, - ACT_VM_RELOAD_IDLE, - - ACT_VM_DRAW_DEPLOYED, - - //Weapon is empty activities - ACT_VM_DRAW_EMPTY, - ACT_VM_PRIMARYATTACK_EMPTY, - ACT_VM_RELOAD_EMPTY, - ACT_VM_IDLE_EMPTY, - ACT_VM_IDLE_DEPLOYED_EMPTY, - - ACT_VM_IDLE_8, - ACT_VM_IDLE_7, - ACT_VM_IDLE_6, - ACT_VM_IDLE_5, - ACT_VM_IDLE_4, - ACT_VM_IDLE_3, - ACT_VM_IDLE_2, - ACT_VM_IDLE_1, - - ACT_VM_IDLE_DEPLOYED, - ACT_VM_IDLE_DEPLOYED_8, - ACT_VM_IDLE_DEPLOYED_7, - ACT_VM_IDLE_DEPLOYED_6, - ACT_VM_IDLE_DEPLOYED_5, - ACT_VM_IDLE_DEPLOYED_4, - ACT_VM_IDLE_DEPLOYED_3, - ACT_VM_IDLE_DEPLOYED_2, - ACT_VM_IDLE_DEPLOYED_1, - - // Animation from prone idle to standing/crouch idle. Number designates bullets left - ACT_VM_UNDEPLOY, - ACT_VM_UNDEPLOY_8, - ACT_VM_UNDEPLOY_7, - ACT_VM_UNDEPLOY_6, - ACT_VM_UNDEPLOY_5, - ACT_VM_UNDEPLOY_4, - ACT_VM_UNDEPLOY_3, - ACT_VM_UNDEPLOY_2, - ACT_VM_UNDEPLOY_1, - ACT_VM_UNDEPLOY_EMPTY, - - // Animation from standing/crouch idle to prone idle. Number designates bullets left - ACT_VM_DEPLOY, - ACT_VM_DEPLOY_8, - ACT_VM_DEPLOY_7, - ACT_VM_DEPLOY_6, - ACT_VM_DEPLOY_5, - ACT_VM_DEPLOY_4, - ACT_VM_DEPLOY_3, - ACT_VM_DEPLOY_2, - ACT_VM_DEPLOY_1, - ACT_VM_DEPLOY_EMPTY, - - // Shooting animations for standing/crouch position. Number designates bullets left at START of animation - ACT_VM_PRIMARYATTACK_8, - ACT_VM_PRIMARYATTACK_7, - ACT_VM_PRIMARYATTACK_6, - ACT_VM_PRIMARYATTACK_5, - ACT_VM_PRIMARYATTACK_4, - ACT_VM_PRIMARYATTACK_3, - ACT_VM_PRIMARYATTACK_2, - ACT_VM_PRIMARYATTACK_1, - - // Shooting animations for prone position. Number designates bullets left at START of animation - ACT_VM_PRIMARYATTACK_DEPLOYED, - ACT_VM_PRIMARYATTACK_DEPLOYED_8, - ACT_VM_PRIMARYATTACK_DEPLOYED_7, - ACT_VM_PRIMARYATTACK_DEPLOYED_6, - ACT_VM_PRIMARYATTACK_DEPLOYED_5, - ACT_VM_PRIMARYATTACK_DEPLOYED_4, - ACT_VM_PRIMARYATTACK_DEPLOYED_3, - ACT_VM_PRIMARYATTACK_DEPLOYED_2, - ACT_VM_PRIMARYATTACK_DEPLOYED_1, - ACT_VM_PRIMARYATTACK_DEPLOYED_EMPTY, - - // Player anim ACTs - ACT_DOD_DEPLOYED, - ACT_DOD_PRONE_DEPLOYED, - ACT_DOD_IDLE_ZOOMED, - ACT_DOD_WALK_ZOOMED, - ACT_DOD_CROUCH_ZOOMED, - ACT_DOD_CROUCHWALK_ZOOMED, - ACT_DOD_PRONE_ZOOMED, - ACT_DOD_PRONE_FORWARD_ZOOMED, - ACT_DOD_PRIMARYATTACK_DEPLOYED, - ACT_DOD_PRIMARYATTACK_PRONE_DEPLOYED, - ACT_DOD_RELOAD_DEPLOYED, - ACT_DOD_RELOAD_PRONE_DEPLOYED, - ACT_DOD_PRIMARYATTACK_PRONE, - ACT_DOD_SECONDARYATTACK_PRONE, - ACT_DOD_RELOAD_CROUCH, - ACT_DOD_RELOAD_PRONE, - ACT_DOD_STAND_IDLE, - ACT_DOD_STAND_AIM, - ACT_DOD_CROUCH_IDLE, - ACT_DOD_CROUCH_AIM, - ACT_DOD_CROUCHWALK_IDLE, - ACT_DOD_CROUCHWALK_AIM, - ACT_DOD_WALK_IDLE, - ACT_DOD_WALK_AIM, - ACT_DOD_RUN_IDLE, - ACT_DOD_RUN_AIM, - - // Positions - ACT_DOD_STAND_AIM_PISTOL, - ACT_DOD_CROUCH_AIM_PISTOL, - ACT_DOD_CROUCHWALK_AIM_PISTOL, - ACT_DOD_WALK_AIM_PISTOL, - ACT_DOD_RUN_AIM_PISTOL, - ACT_DOD_PRONE_AIM_PISTOL, - ACT_DOD_STAND_IDLE_PISTOL, - ACT_DOD_CROUCH_IDLE_PISTOL, - ACT_DOD_CROUCHWALK_IDLE_PISTOL, - ACT_DOD_WALK_IDLE_PISTOL, - ACT_DOD_RUN_IDLE_PISTOL, - ACT_DOD_SPRINT_IDLE_PISTOL, - ACT_DOD_PRONEWALK_IDLE_PISTOL, - - ACT_DOD_STAND_AIM_C96, - ACT_DOD_CROUCH_AIM_C96, - ACT_DOD_CROUCHWALK_AIM_C96, - ACT_DOD_WALK_AIM_C96, - ACT_DOD_RUN_AIM_C96, - ACT_DOD_PRONE_AIM_C96, - ACT_DOD_STAND_IDLE_C96, - ACT_DOD_CROUCH_IDLE_C96, - ACT_DOD_CROUCHWALK_IDLE_C96, - ACT_DOD_WALK_IDLE_C96, - ACT_DOD_RUN_IDLE_C96, - ACT_DOD_SPRINT_IDLE_C96, - ACT_DOD_PRONEWALK_IDLE_C96, - - ACT_DOD_STAND_AIM_RIFLE, - ACT_DOD_CROUCH_AIM_RIFLE, - ACT_DOD_CROUCHWALK_AIM_RIFLE, - ACT_DOD_WALK_AIM_RIFLE, - ACT_DOD_RUN_AIM_RIFLE, - ACT_DOD_PRONE_AIM_RIFLE, - ACT_DOD_STAND_IDLE_RIFLE, - ACT_DOD_CROUCH_IDLE_RIFLE, - ACT_DOD_CROUCHWALK_IDLE_RIFLE, - ACT_DOD_WALK_IDLE_RIFLE, - ACT_DOD_RUN_IDLE_RIFLE, - ACT_DOD_SPRINT_IDLE_RIFLE, - ACT_DOD_PRONEWALK_IDLE_RIFLE, - - ACT_DOD_STAND_AIM_BOLT, - ACT_DOD_CROUCH_AIM_BOLT, - ACT_DOD_CROUCHWALK_AIM_BOLT, - ACT_DOD_WALK_AIM_BOLT, - ACT_DOD_RUN_AIM_BOLT, - ACT_DOD_PRONE_AIM_BOLT, - ACT_DOD_STAND_IDLE_BOLT, - ACT_DOD_CROUCH_IDLE_BOLT, - ACT_DOD_CROUCHWALK_IDLE_BOLT, - ACT_DOD_WALK_IDLE_BOLT, - ACT_DOD_RUN_IDLE_BOLT, - ACT_DOD_SPRINT_IDLE_BOLT, - ACT_DOD_PRONEWALK_IDLE_BOLT, - - ACT_DOD_STAND_AIM_TOMMY, - ACT_DOD_CROUCH_AIM_TOMMY, - ACT_DOD_CROUCHWALK_AIM_TOMMY, - ACT_DOD_WALK_AIM_TOMMY, - ACT_DOD_RUN_AIM_TOMMY, - ACT_DOD_PRONE_AIM_TOMMY, - ACT_DOD_STAND_IDLE_TOMMY, - ACT_DOD_CROUCH_IDLE_TOMMY, - ACT_DOD_CROUCHWALK_IDLE_TOMMY, - ACT_DOD_WALK_IDLE_TOMMY, - ACT_DOD_RUN_IDLE_TOMMY, - ACT_DOD_SPRINT_IDLE_TOMMY, - ACT_DOD_PRONEWALK_IDLE_TOMMY, - - ACT_DOD_STAND_AIM_MP40, - ACT_DOD_CROUCH_AIM_MP40, - ACT_DOD_CROUCHWALK_AIM_MP40, - ACT_DOD_WALK_AIM_MP40, - ACT_DOD_RUN_AIM_MP40, - ACT_DOD_PRONE_AIM_MP40, - ACT_DOD_STAND_IDLE_MP40, - ACT_DOD_CROUCH_IDLE_MP40, - ACT_DOD_CROUCHWALK_IDLE_MP40, - ACT_DOD_WALK_IDLE_MP40, - ACT_DOD_RUN_IDLE_MP40, - ACT_DOD_SPRINT_IDLE_MP40, - ACT_DOD_PRONEWALK_IDLE_MP40, - - ACT_DOD_STAND_AIM_MP44, - ACT_DOD_CROUCH_AIM_MP44, - ACT_DOD_CROUCHWALK_AIM_MP44, - ACT_DOD_WALK_AIM_MP44, - ACT_DOD_RUN_AIM_MP44, - ACT_DOD_PRONE_AIM_MP44, - ACT_DOD_STAND_IDLE_MP44, - ACT_DOD_CROUCH_IDLE_MP44, - ACT_DOD_CROUCHWALK_IDLE_MP44, - ACT_DOD_WALK_IDLE_MP44, - ACT_DOD_RUN_IDLE_MP44, - ACT_DOD_SPRINT_IDLE_MP44, - ACT_DOD_PRONEWALK_IDLE_MP44, - - ACT_DOD_STAND_AIM_GREASE, - ACT_DOD_CROUCH_AIM_GREASE, - ACT_DOD_CROUCHWALK_AIM_GREASE, - ACT_DOD_WALK_AIM_GREASE, - ACT_DOD_RUN_AIM_GREASE, - ACT_DOD_PRONE_AIM_GREASE, - ACT_DOD_STAND_IDLE_GREASE, - ACT_DOD_CROUCH_IDLE_GREASE, - ACT_DOD_CROUCHWALK_IDLE_GREASE, - ACT_DOD_WALK_IDLE_GREASE, - ACT_DOD_RUN_IDLE_GREASE, - ACT_DOD_SPRINT_IDLE_GREASE, - ACT_DOD_PRONEWALK_IDLE_GREASE, - - ACT_DOD_STAND_AIM_MG, - ACT_DOD_CROUCH_AIM_MG, - ACT_DOD_CROUCHWALK_AIM_MG, - ACT_DOD_WALK_AIM_MG, - ACT_DOD_RUN_AIM_MG, - ACT_DOD_PRONE_AIM_MG, - ACT_DOD_STAND_IDLE_MG, - ACT_DOD_CROUCH_IDLE_MG, - ACT_DOD_CROUCHWALK_IDLE_MG, - ACT_DOD_WALK_IDLE_MG, - ACT_DOD_RUN_IDLE_MG, - ACT_DOD_SPRINT_IDLE_MG, - ACT_DOD_PRONEWALK_IDLE_MG, - - ACT_DOD_STAND_AIM_30CAL, - ACT_DOD_CROUCH_AIM_30CAL, - ACT_DOD_CROUCHWALK_AIM_30CAL, - ACT_DOD_WALK_AIM_30CAL, - ACT_DOD_RUN_AIM_30CAL, - ACT_DOD_PRONE_AIM_30CAL, - ACT_DOD_STAND_IDLE_30CAL, - ACT_DOD_CROUCH_IDLE_30CAL, - ACT_DOD_CROUCHWALK_IDLE_30CAL, - ACT_DOD_WALK_IDLE_30CAL, - ACT_DOD_RUN_IDLE_30CAL, - ACT_DOD_SPRINT_IDLE_30CAL, - ACT_DOD_PRONEWALK_IDLE_30CAL, - - ACT_DOD_STAND_AIM_GREN_FRAG, - ACT_DOD_CROUCH_AIM_GREN_FRAG, - ACT_DOD_CROUCHWALK_AIM_GREN_FRAG, - ACT_DOD_WALK_AIM_GREN_FRAG, - ACT_DOD_RUN_AIM_GREN_FRAG, - ACT_DOD_PRONE_AIM_GREN_FRAG, - ACT_DOD_SPRINT_AIM_GREN_FRAG, - ACT_DOD_PRONEWALK_AIM_GREN_FRAG, - ACT_DOD_STAND_AIM_GREN_STICK, - ACT_DOD_CROUCH_AIM_GREN_STICK, - ACT_DOD_CROUCHWALK_AIM_GREN_STICK, - ACT_DOD_WALK_AIM_GREN_STICK, - ACT_DOD_RUN_AIM_GREN_STICK, - ACT_DOD_PRONE_AIM_GREN_STICK, - ACT_DOD_SPRINT_AIM_GREN_STICK, - ACT_DOD_PRONEWALK_AIM_GREN_STICK, - - ACT_DOD_STAND_AIM_KNIFE, - ACT_DOD_CROUCH_AIM_KNIFE, - ACT_DOD_CROUCHWALK_AIM_KNIFE, - ACT_DOD_WALK_AIM_KNIFE, - ACT_DOD_RUN_AIM_KNIFE, - ACT_DOD_PRONE_AIM_KNIFE, - ACT_DOD_SPRINT_AIM_KNIFE, - ACT_DOD_PRONEWALK_AIM_KNIFE, - - ACT_DOD_STAND_AIM_SPADE, - ACT_DOD_CROUCH_AIM_SPADE, - ACT_DOD_CROUCHWALK_AIM_SPADE, - ACT_DOD_WALK_AIM_SPADE, - ACT_DOD_RUN_AIM_SPADE, - ACT_DOD_PRONE_AIM_SPADE, - ACT_DOD_SPRINT_AIM_SPADE, - ACT_DOD_PRONEWALK_AIM_SPADE, - - ACT_DOD_STAND_AIM_BAZOOKA, - ACT_DOD_CROUCH_AIM_BAZOOKA, - ACT_DOD_CROUCHWALK_AIM_BAZOOKA, - ACT_DOD_WALK_AIM_BAZOOKA, - ACT_DOD_RUN_AIM_BAZOOKA, - ACT_DOD_PRONE_AIM_BAZOOKA, - ACT_DOD_STAND_IDLE_BAZOOKA, - ACT_DOD_CROUCH_IDLE_BAZOOKA, - ACT_DOD_CROUCHWALK_IDLE_BAZOOKA, - ACT_DOD_WALK_IDLE_BAZOOKA, - ACT_DOD_RUN_IDLE_BAZOOKA, - ACT_DOD_SPRINT_IDLE_BAZOOKA, - ACT_DOD_PRONEWALK_IDLE_BAZOOKA, - - ACT_DOD_STAND_AIM_PSCHRECK, - ACT_DOD_CROUCH_AIM_PSCHRECK, - ACT_DOD_CROUCHWALK_AIM_PSCHRECK, - ACT_DOD_WALK_AIM_PSCHRECK, - ACT_DOD_RUN_AIM_PSCHRECK, - ACT_DOD_PRONE_AIM_PSCHRECK, - ACT_DOD_STAND_IDLE_PSCHRECK, - ACT_DOD_CROUCH_IDLE_PSCHRECK, - ACT_DOD_CROUCHWALK_IDLE_PSCHRECK, - ACT_DOD_WALK_IDLE_PSCHRECK, - ACT_DOD_RUN_IDLE_PSCHRECK, - ACT_DOD_SPRINT_IDLE_PSCHRECK, - ACT_DOD_PRONEWALK_IDLE_PSCHRECK, - - ACT_DOD_STAND_AIM_BAR, - ACT_DOD_CROUCH_AIM_BAR, - ACT_DOD_CROUCHWALK_AIM_BAR, - ACT_DOD_WALK_AIM_BAR, - ACT_DOD_RUN_AIM_BAR, - ACT_DOD_PRONE_AIM_BAR, - ACT_DOD_STAND_IDLE_BAR, - ACT_DOD_CROUCH_IDLE_BAR, - ACT_DOD_CROUCHWALK_IDLE_BAR, - ACT_DOD_WALK_IDLE_BAR, - ACT_DOD_RUN_IDLE_BAR, - ACT_DOD_SPRINT_IDLE_BAR, - ACT_DOD_PRONEWALK_IDLE_BAR, - - // Zoomed aims - ACT_DOD_STAND_ZOOM_RIFLE, - ACT_DOD_CROUCH_ZOOM_RIFLE, - ACT_DOD_CROUCHWALK_ZOOM_RIFLE, - ACT_DOD_WALK_ZOOM_RIFLE, - ACT_DOD_RUN_ZOOM_RIFLE, - ACT_DOD_PRONE_ZOOM_RIFLE, - - ACT_DOD_STAND_ZOOM_BOLT, - ACT_DOD_CROUCH_ZOOM_BOLT, - ACT_DOD_CROUCHWALK_ZOOM_BOLT, - ACT_DOD_WALK_ZOOM_BOLT, - ACT_DOD_RUN_ZOOM_BOLT, - ACT_DOD_PRONE_ZOOM_BOLT, - - ACT_DOD_STAND_ZOOM_BAZOOKA, - ACT_DOD_CROUCH_ZOOM_BAZOOKA, - ACT_DOD_CROUCHWALK_ZOOM_BAZOOKA, - ACT_DOD_WALK_ZOOM_BAZOOKA, - ACT_DOD_RUN_ZOOM_BAZOOKA, - ACT_DOD_PRONE_ZOOM_BAZOOKA, - - ACT_DOD_STAND_ZOOM_PSCHRECK, - ACT_DOD_CROUCH_ZOOM_PSCHRECK, - ACT_DOD_CROUCHWALK_ZOOM_PSCHRECK, - ACT_DOD_WALK_ZOOM_PSCHRECK, - ACT_DOD_RUN_ZOOM_PSCHRECK, - ACT_DOD_PRONE_ZOOM_PSCHRECK, - - // Deployed Aim - ACT_DOD_DEPLOY_RIFLE, - ACT_DOD_DEPLOY_TOMMY, - ACT_DOD_DEPLOY_MG, - ACT_DOD_DEPLOY_30CAL, - - // Prone Deployed Aim - ACT_DOD_PRONE_DEPLOY_RIFLE , - ACT_DOD_PRONE_DEPLOY_TOMMY, - ACT_DOD_PRONE_DEPLOY_MG, - ACT_DOD_PRONE_DEPLOY_30CAL, - - // Attacks - - // Rifle - ACT_DOD_PRIMARYATTACK_RIFLE, - ACT_DOD_SECONDARYATTACK_RIFLE, - ACT_DOD_PRIMARYATTACK_PRONE_RIFLE, - ACT_DOD_SECONDARYATTACK_PRONE_RIFLE, - ACT_DOD_PRIMARYATTACK_PRONE_DEPLOYED_RIFLE, - ACT_DOD_PRIMARYATTACK_DEPLOYED_RIFLE, - - // Bolt - ACT_DOD_PRIMARYATTACK_BOLT, - ACT_DOD_SECONDARYATTACK_BOLT, - ACT_DOD_PRIMARYATTACK_PRONE_BOLT , - ACT_DOD_SECONDARYATTACK_PRONE_BOLT , - - // Tommy - ACT_DOD_PRIMARYATTACK_TOMMY, - ACT_DOD_PRIMARYATTACK_PRONE_TOMMY, - ACT_DOD_SECONDARYATTACK_TOMMY, - ACT_DOD_SECONDARYATTACK_PRONE_TOMMY, - - // MP40 - ACT_DOD_PRIMARYATTACK_MP40, - ACT_DOD_PRIMARYATTACK_PRONE_MP40 , - ACT_DOD_SECONDARYATTACK_MP40, - ACT_DOD_SECONDARYATTACK_PRONE_MP40 , - - // MP44 - ACT_DOD_PRIMARYATTACK_MP44, - ACT_DOD_PRIMARYATTACK_PRONE_MP44 , - - // Greasegun - ACT_DOD_PRIMARYATTACK_GREASE, - ACT_DOD_PRIMARYATTACK_PRONE_GREASE , - - // Pistols (Colt, Luger) - ACT_DOD_PRIMARYATTACK_PISTOL, - ACT_DOD_PRIMARYATTACK_PRONE_PISTOL , - ACT_DOD_PRIMARYATTACK_C96, - ACT_DOD_PRIMARYATTACK_PRONE_C96, - - // Mgs (mg42, mg34) - ACT_DOD_PRIMARYATTACK_MG, - ACT_DOD_PRIMARYATTACK_PRONE_MG , - ACT_DOD_PRIMARYATTACK_PRONE_DEPLOYED_MG , - ACT_DOD_PRIMARYATTACK_DEPLOYED_MG , - - // 30cal - ACT_DOD_PRIMARYATTACK_30CAL, - ACT_DOD_PRIMARYATTACK_PRONE_30CAL, - ACT_DOD_PRIMARYATTACK_DEPLOYED_30CAL, - ACT_DOD_PRIMARYATTACK_PRONE_DEPLOYED_30CAL , - - // Grenades - ACT_DOD_PRIMARYATTACK_GREN_FRAG, - ACT_DOD_PRIMARYATTACK_PRONE_GREN_FRAG, - ACT_DOD_PRIMARYATTACK_GREN_STICK, - ACT_DOD_PRIMARYATTACK_PRONE_GREN_STICK, - - // Knife - ACT_DOD_PRIMARYATTACK_KNIFE, - ACT_DOD_PRIMARYATTACK_PRONE_KNIFE, - - // Spade - ACT_DOD_PRIMARYATTACK_SPADE, - ACT_DOD_PRIMARYATTACK_PRONE_SPADE, - - // Bazooka - ACT_DOD_PRIMARYATTACK_BAZOOKA, - ACT_DOD_PRIMARYATTACK_PRONE_BAZOOKA, - - // Pschreck - ACT_DOD_PRIMARYATTACK_PSCHRECK, - ACT_DOD_PRIMARYATTACK_PRONE_PSCHRECK , - - // Bar - ACT_DOD_PRIMARYATTACK_BAR, - ACT_DOD_PRIMARYATTACK_PRONE_BAR, - - // Reloads - ACT_DOD_RELOAD_GARAND, - ACT_DOD_RELOAD_K43, - ACT_DOD_RELOAD_BAR, - ACT_DOD_RELOAD_MP40, - ACT_DOD_RELOAD_MP44, - ACT_DOD_RELOAD_BOLT, - ACT_DOD_RELOAD_M1CARBINE, - ACT_DOD_RELOAD_TOMMY, - ACT_DOD_RELOAD_GREASEGUN, - ACT_DOD_RELOAD_PISTOL, - ACT_DOD_RELOAD_FG42, - ACT_DOD_RELOAD_RIFLE, - ACT_DOD_RELOAD_RIFLEGRENADE, - ACT_DOD_RELOAD_C96, - - // Crouch - ACT_DOD_RELOAD_CROUCH_BAR, - ACT_DOD_RELOAD_CROUCH_RIFLE, - ACT_DOD_RELOAD_CROUCH_RIFLEGRENADE, - ACT_DOD_RELOAD_CROUCH_BOLT, - ACT_DOD_RELOAD_CROUCH_MP44, - ACT_DOD_RELOAD_CROUCH_MP40, - ACT_DOD_RELOAD_CROUCH_TOMMY, - ACT_DOD_RELOAD_CROUCH_BAZOOKA, - ACT_DOD_RELOAD_CROUCH_PSCHRECK, - ACT_DOD_RELOAD_CROUCH_PISTOL, - ACT_DOD_RELOAD_CROUCH_M1CARBINE, - ACT_DOD_RELOAD_CROUCH_C96, - - // Bazookas - ACT_DOD_RELOAD_BAZOOKA, - ACT_DOD_ZOOMLOAD_BAZOOKA, - ACT_DOD_RELOAD_PSCHRECK, - ACT_DOD_ZOOMLOAD_PSCHRECK, - - // Deployed - ACT_DOD_RELOAD_DEPLOYED_FG42, - ACT_DOD_RELOAD_DEPLOYED_30CAL, - ACT_DOD_RELOAD_DEPLOYED_MG, - ACT_DOD_RELOAD_DEPLOYED_MG34, - ACT_DOD_RELOAD_DEPLOYED_BAR, - - // Prone - ACT_DOD_RELOAD_PRONE_PISTOL, - ACT_DOD_RELOAD_PRONE_GARAND, - ACT_DOD_RELOAD_PRONE_M1CARBINE, - ACT_DOD_RELOAD_PRONE_BOLT, - ACT_DOD_RELOAD_PRONE_K43, - ACT_DOD_RELOAD_PRONE_MP40, - ACT_DOD_RELOAD_PRONE_MP44, - ACT_DOD_RELOAD_PRONE_BAR, - ACT_DOD_RELOAD_PRONE_GREASEGUN, - ACT_DOD_RELOAD_PRONE_TOMMY, - ACT_DOD_RELOAD_PRONE_FG42, - ACT_DOD_RELOAD_PRONE_RIFLE, - ACT_DOD_RELOAD_PRONE_RIFLEGRENADE, - ACT_DOD_RELOAD_PRONE_C96, - - // Prone bazooka - ACT_DOD_RELOAD_PRONE_BAZOOKA, - ACT_DOD_ZOOMLOAD_PRONE_BAZOOKA, - ACT_DOD_RELOAD_PRONE_PSCHRECK, - ACT_DOD_ZOOMLOAD_PRONE_PSCHRECK, - - // Prone deployed - ACT_DOD_RELOAD_PRONE_DEPLOYED_BAR, - ACT_DOD_RELOAD_PRONE_DEPLOYED_FG42, - ACT_DOD_RELOAD_PRONE_DEPLOYED_30CAL, - ACT_DOD_RELOAD_PRONE_DEPLOYED_MG, - ACT_DOD_RELOAD_PRONE_DEPLOYED_MG34, - - // Prone zoomed aim - ACT_DOD_PRONE_ZOOM_FORWARD_RIFLE, - ACT_DOD_PRONE_ZOOM_FORWARD_BOLT, - ACT_DOD_PRONE_ZOOM_FORWARD_BAZOOKA, - ACT_DOD_PRONE_ZOOM_FORWARD_PSCHRECK, - - // Crouch attack - ACT_DOD_PRIMARYATTACK_CROUCH, - ACT_DOD_PRIMARYATTACK_CROUCH_SPADE, - ACT_DOD_PRIMARYATTACK_CROUCH_KNIFE, - ACT_DOD_PRIMARYATTACK_CROUCH_GREN_FRAG, - ACT_DOD_PRIMARYATTACK_CROUCH_GREN_STICK, - ACT_DOD_SECONDARYATTACK_CROUCH, - ACT_DOD_SECONDARYATTACK_CROUCH_TOMMY, - ACT_DOD_SECONDARYATTACK_CROUCH_MP40, - - // Hand Signals - ACT_DOD_HS_IDLE, - ACT_DOD_HS_CROUCH, - ACT_DOD_HS_IDLE_30CAL, - ACT_DOD_HS_IDLE_BAZOOKA, - ACT_DOD_HS_IDLE_PSCHRECK, - ACT_DOD_HS_IDLE_KNIFE, - ACT_DOD_HS_IDLE_MG42, - ACT_DOD_HS_IDLE_PISTOL, - ACT_DOD_HS_IDLE_STICKGRENADE, - ACT_DOD_HS_IDLE_TOMMY, - ACT_DOD_HS_IDLE_MP44, - ACT_DOD_HS_IDLE_K98, - ACT_DOD_HS_CROUCH_30CAL, - ACT_DOD_HS_CROUCH_BAZOOKA, - ACT_DOD_HS_CROUCH_PSCHRECK, - ACT_DOD_HS_CROUCH_KNIFE, - ACT_DOD_HS_CROUCH_MG42, - ACT_DOD_HS_CROUCH_PISTOL, - ACT_DOD_HS_CROUCH_STICKGRENADE, - ACT_DOD_HS_CROUCH_TOMMY, - ACT_DOD_HS_CROUCH_MP44, - ACT_DOD_HS_CROUCH_K98, - - ACT_DOD_STAND_IDLE_TNT, - ACT_DOD_CROUCH_IDLE_TNT, - ACT_DOD_CROUCHWALK_IDLE_TNT, - ACT_DOD_WALK_IDLE_TNT, - ACT_DOD_RUN_IDLE_TNT, - ACT_DOD_SPRINT_IDLE_TNT, - ACT_DOD_PRONEWALK_IDLE_TNT, - - ACT_DOD_PLANT_TNT, - ACT_DOD_DEFUSE_TNT, - -// HL2MP - ACT_HL2MP_IDLE, - ACT_HL2MP_RUN, - ACT_HL2MP_IDLE_CROUCH, - ACT_HL2MP_WALK_CROUCH, - ACT_HL2MP_GESTURE_RANGE_ATTACK, - ACT_HL2MP_GESTURE_RELOAD, - ACT_HL2MP_JUMP, - - ACT_HL2MP_IDLE_PISTOL, - ACT_HL2MP_RUN_PISTOL, - ACT_HL2MP_IDLE_CROUCH_PISTOL, - ACT_HL2MP_WALK_CROUCH_PISTOL, - ACT_HL2MP_GESTURE_RANGE_ATTACK_PISTOL, - ACT_HL2MP_GESTURE_RELOAD_PISTOL, - ACT_HL2MP_JUMP_PISTOL, - - ACT_HL2MP_IDLE_SMG1, - ACT_HL2MP_RUN_SMG1, - ACT_HL2MP_IDLE_CROUCH_SMG1, - ACT_HL2MP_WALK_CROUCH_SMG1, - ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG1, - ACT_HL2MP_GESTURE_RELOAD_SMG1, - ACT_HL2MP_JUMP_SMG1, - - ACT_HL2MP_IDLE_AR2, - ACT_HL2MP_RUN_AR2, - ACT_HL2MP_IDLE_CROUCH_AR2, - ACT_HL2MP_WALK_CROUCH_AR2, - ACT_HL2MP_GESTURE_RANGE_ATTACK_AR2, - ACT_HL2MP_GESTURE_RELOAD_AR2, - ACT_HL2MP_JUMP_AR2, - - ACT_HL2MP_IDLE_SHOTGUN, - ACT_HL2MP_RUN_SHOTGUN, - ACT_HL2MP_IDLE_CROUCH_SHOTGUN, - ACT_HL2MP_WALK_CROUCH_SHOTGUN, - ACT_HL2MP_GESTURE_RANGE_ATTACK_SHOTGUN, - ACT_HL2MP_GESTURE_RELOAD_SHOTGUN, - ACT_HL2MP_JUMP_SHOTGUN, - - ACT_HL2MP_IDLE_RPG, - ACT_HL2MP_RUN_RPG, - ACT_HL2MP_IDLE_CROUCH_RPG, - ACT_HL2MP_WALK_CROUCH_RPG, - ACT_HL2MP_GESTURE_RANGE_ATTACK_RPG, - ACT_HL2MP_GESTURE_RELOAD_RPG, - ACT_HL2MP_JUMP_RPG, - - ACT_HL2MP_IDLE_GRENADE, - ACT_HL2MP_RUN_GRENADE, - ACT_HL2MP_IDLE_CROUCH_GRENADE, - ACT_HL2MP_WALK_CROUCH_GRENADE, - ACT_HL2MP_GESTURE_RANGE_ATTACK_GRENADE, - ACT_HL2MP_GESTURE_RELOAD_GRENADE, - ACT_HL2MP_JUMP_GRENADE, - - ACT_HL2MP_IDLE_PHYSGUN, - ACT_HL2MP_RUN_PHYSGUN, - ACT_HL2MP_IDLE_CROUCH_PHYSGUN, - ACT_HL2MP_WALK_CROUCH_PHYSGUN, - ACT_HL2MP_GESTURE_RANGE_ATTACK_PHYSGUN, - ACT_HL2MP_GESTURE_RELOAD_PHYSGUN, - ACT_HL2MP_JUMP_PHYSGUN, - - ACT_HL2MP_IDLE_CROSSBOW, - ACT_HL2MP_RUN_CROSSBOW, - ACT_HL2MP_IDLE_CROUCH_CROSSBOW, - ACT_HL2MP_WALK_CROUCH_CROSSBOW, - ACT_HL2MP_GESTURE_RANGE_ATTACK_CROSSBOW, - ACT_HL2MP_GESTURE_RELOAD_CROSSBOW, - ACT_HL2MP_JUMP_CROSSBOW, - - ACT_HL2MP_IDLE_MELEE, - ACT_HL2MP_RUN_MELEE, - ACT_HL2MP_IDLE_CROUCH_MELEE, - ACT_HL2MP_WALK_CROUCH_MELEE, - ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE, - ACT_HL2MP_GESTURE_RELOAD_MELEE, - ACT_HL2MP_JUMP_MELEE, - - ACT_HL2MP_IDLE_SLAM, - ACT_HL2MP_RUN_SLAM, - ACT_HL2MP_IDLE_CROUCH_SLAM, - ACT_HL2MP_WALK_CROUCH_SLAM, - ACT_HL2MP_GESTURE_RANGE_ATTACK_SLAM, - ACT_HL2MP_GESTURE_RELOAD_SLAM, - ACT_HL2MP_JUMP_SLAM, - -// Portal! - ACT_VM_FIZZLE, - - // Multiplayer - ACT_MP_STAND_IDLE, - ACT_MP_CROUCH_IDLE, - ACT_MP_CROUCH_DEPLOYED_IDLE, - ACT_MP_CROUCH_DEPLOYED, - ACT_MP_DEPLOYED_IDLE, - ACT_MP_RUN, - ACT_MP_WALK, - ACT_MP_AIRWALK, - ACT_MP_CROUCHWALK, - ACT_MP_SPRINT, - ACT_MP_JUMP, - ACT_MP_JUMP_START, - ACT_MP_JUMP_FLOAT, - ACT_MP_JUMP_LAND, - ACT_MP_DOUBLEJUMP, - ACT_MP_SWIM, - ACT_MP_DEPLOYED, - ACT_MP_SWIM_DEPLOYED, - ACT_MP_VCD, - - ACT_MP_ATTACK_STAND_PRIMARYFIRE, - ACT_MP_ATTACK_STAND_PRIMARYFIRE_DEPLOYED, - ACT_MP_ATTACK_STAND_SECONDARYFIRE, - ACT_MP_ATTACK_STAND_GRENADE, - ACT_MP_ATTACK_CROUCH_PRIMARYFIRE, - ACT_MP_ATTACK_CROUCH_PRIMARYFIRE_DEPLOYED, - ACT_MP_ATTACK_CROUCH_SECONDARYFIRE, - ACT_MP_ATTACK_CROUCH_GRENADE, - ACT_MP_ATTACK_SWIM_PRIMARYFIRE, - ACT_MP_ATTACK_SWIM_SECONDARYFIRE, - ACT_MP_ATTACK_SWIM_GRENADE, - ACT_MP_ATTACK_AIRWALK_PRIMARYFIRE, - ACT_MP_ATTACK_AIRWALK_SECONDARYFIRE, - ACT_MP_ATTACK_AIRWALK_GRENADE, - ACT_MP_RELOAD_STAND, - ACT_MP_RELOAD_STAND_LOOP, - ACT_MP_RELOAD_STAND_END, - ACT_MP_RELOAD_CROUCH, - ACT_MP_RELOAD_CROUCH_LOOP, - ACT_MP_RELOAD_CROUCH_END, - ACT_MP_RELOAD_SWIM, - ACT_MP_RELOAD_SWIM_LOOP, - ACT_MP_RELOAD_SWIM_END, - ACT_MP_RELOAD_AIRWALK, - ACT_MP_RELOAD_AIRWALK_LOOP, - ACT_MP_RELOAD_AIRWALK_END, - ACT_MP_ATTACK_STAND_PREFIRE, - ACT_MP_ATTACK_STAND_POSTFIRE, - ACT_MP_ATTACK_STAND_STARTFIRE, - ACT_MP_ATTACK_CROUCH_PREFIRE, - ACT_MP_ATTACK_CROUCH_POSTFIRE, - ACT_MP_ATTACK_SWIM_PREFIRE, - ACT_MP_ATTACK_SWIM_POSTFIRE, - - // Multiplayer - Primary - ACT_MP_STAND_PRIMARY, - ACT_MP_CROUCH_PRIMARY, - ACT_MP_RUN_PRIMARY, - ACT_MP_WALK_PRIMARY, - ACT_MP_AIRWALK_PRIMARY, - ACT_MP_CROUCHWALK_PRIMARY, - ACT_MP_JUMP_PRIMARY, - ACT_MP_JUMP_START_PRIMARY, - ACT_MP_JUMP_FLOAT_PRIMARY, - ACT_MP_JUMP_LAND_PRIMARY, - ACT_MP_SWIM_PRIMARY, - ACT_MP_DEPLOYED_PRIMARY, - ACT_MP_SWIM_DEPLOYED_PRIMARY, - - ACT_MP_ATTACK_STAND_PRIMARY, // RUN, WALK - ACT_MP_ATTACK_STAND_PRIMARY_DEPLOYED, - ACT_MP_ATTACK_CROUCH_PRIMARY, // CROUCHWALK - ACT_MP_ATTACK_CROUCH_PRIMARY_DEPLOYED, - ACT_MP_ATTACK_SWIM_PRIMARY, - ACT_MP_ATTACK_AIRWALK_PRIMARY, - - ACT_MP_RELOAD_STAND_PRIMARY, // RUN, WALK - ACT_MP_RELOAD_STAND_PRIMARY_LOOP, - ACT_MP_RELOAD_STAND_PRIMARY_END, - ACT_MP_RELOAD_CROUCH_PRIMARY, // CROUCHWALK - ACT_MP_RELOAD_CROUCH_PRIMARY_LOOP, - ACT_MP_RELOAD_CROUCH_PRIMARY_END, - ACT_MP_RELOAD_SWIM_PRIMARY, - ACT_MP_RELOAD_SWIM_PRIMARY_LOOP, - ACT_MP_RELOAD_SWIM_PRIMARY_END, - ACT_MP_RELOAD_AIRWALK_PRIMARY, - ACT_MP_RELOAD_AIRWALK_PRIMARY_LOOP, - ACT_MP_RELOAD_AIRWALK_PRIMARY_END, - - ACT_MP_ATTACK_STAND_GRENADE_PRIMARY, // RUN, WALK - ACT_MP_ATTACK_CROUCH_GRENADE_PRIMARY, // CROUCHWALK - ACT_MP_ATTACK_SWIM_GRENADE_PRIMARY, - ACT_MP_ATTACK_AIRWALK_GRENADE_PRIMARY, - - // Secondary - ACT_MP_STAND_SECONDARY, - ACT_MP_CROUCH_SECONDARY, - ACT_MP_RUN_SECONDARY, - ACT_MP_WALK_SECONDARY, - ACT_MP_AIRWALK_SECONDARY, - ACT_MP_CROUCHWALK_SECONDARY, - ACT_MP_JUMP_SECONDARY, - ACT_MP_JUMP_START_SECONDARY, - ACT_MP_JUMP_FLOAT_SECONDARY, - ACT_MP_JUMP_LAND_SECONDARY, - ACT_MP_SWIM_SECONDARY, - - ACT_MP_ATTACK_STAND_SECONDARY, // RUN, WALK - ACT_MP_ATTACK_CROUCH_SECONDARY, // CROUCHWALK - ACT_MP_ATTACK_SWIM_SECONDARY, - ACT_MP_ATTACK_AIRWALK_SECONDARY, - - ACT_MP_RELOAD_STAND_SECONDARY, // RUN, WALK - ACT_MP_RELOAD_STAND_SECONDARY_LOOP, - ACT_MP_RELOAD_STAND_SECONDARY_END, - ACT_MP_RELOAD_CROUCH_SECONDARY, // CROUCHWALK - ACT_MP_RELOAD_CROUCH_SECONDARY_LOOP, - ACT_MP_RELOAD_CROUCH_SECONDARY_END, - ACT_MP_RELOAD_SWIM_SECONDARY, - ACT_MP_RELOAD_SWIM_SECONDARY_LOOP, - ACT_MP_RELOAD_SWIM_SECONDARY_END, - ACT_MP_RELOAD_AIRWALK_SECONDARY, - ACT_MP_RELOAD_AIRWALK_SECONDARY_LOOP, - ACT_MP_RELOAD_AIRWALK_SECONDARY_END, - - ACT_MP_ATTACK_STAND_GRENADE_SECONDARY, // RUN, WALK - ACT_MP_ATTACK_CROUCH_GRENADE_SECONDARY, // CROUCHWALK - ACT_MP_ATTACK_SWIM_GRENADE_SECONDARY, - ACT_MP_ATTACK_AIRWALK_GRENADE_SECONDARY, - - // Melee - ACT_MP_STAND_MELEE, - ACT_MP_CROUCH_MELEE, - ACT_MP_RUN_MELEE, - ACT_MP_WALK_MELEE, - ACT_MP_AIRWALK_MELEE, - ACT_MP_CROUCHWALK_MELEE, - ACT_MP_JUMP_MELEE, - ACT_MP_JUMP_START_MELEE, - ACT_MP_JUMP_FLOAT_MELEE, - ACT_MP_JUMP_LAND_MELEE, - ACT_MP_SWIM_MELEE, - - ACT_MP_ATTACK_STAND_MELEE, // RUN, WALK - ACT_MP_ATTACK_STAND_MELEE_SECONDARY, - ACT_MP_ATTACK_CROUCH_MELEE, // CROUCHWALK - ACT_MP_ATTACK_CROUCH_MELEE_SECONDARY, - ACT_MP_ATTACK_SWIM_MELEE, - ACT_MP_ATTACK_AIRWALK_MELEE, - - ACT_MP_ATTACK_STAND_GRENADE_MELEE, // RUN, WALK - ACT_MP_ATTACK_CROUCH_GRENADE_MELEE, // CROUCHWALK - ACT_MP_ATTACK_SWIM_GRENADE_MELEE, - ACT_MP_ATTACK_AIRWALK_GRENADE_MELEE, - - // Flinches - ACT_MP_GESTURE_FLINCH, - ACT_MP_GESTURE_FLINCH_PRIMARY, - ACT_MP_GESTURE_FLINCH_SECONDARY, - ACT_MP_GESTURE_FLINCH_MELEE, - - ACT_MP_GESTURE_FLINCH_HEAD, - ACT_MP_GESTURE_FLINCH_CHEST, - ACT_MP_GESTURE_FLINCH_STOMACH, - ACT_MP_GESTURE_FLINCH_LEFTARM, - ACT_MP_GESTURE_FLINCH_RIGHTARM, - ACT_MP_GESTURE_FLINCH_LEFTLEG, - ACT_MP_GESTURE_FLINCH_RIGHTLEG, - -// Team Fortress specific - medic heal, medic infect, etc..... - ACT_MP_GRENADE1_DRAW, - ACT_MP_GRENADE1_IDLE, - ACT_MP_GRENADE1_ATTACK, - ACT_MP_GRENADE2_DRAW, - ACT_MP_GRENADE2_IDLE, - ACT_MP_GRENADE2_ATTACK, - - ACT_MP_PRIMARY_GRENADE1_DRAW, - ACT_MP_PRIMARY_GRENADE1_IDLE, - ACT_MP_PRIMARY_GRENADE1_ATTACK, - ACT_MP_PRIMARY_GRENADE2_DRAW, - ACT_MP_PRIMARY_GRENADE2_IDLE, - ACT_MP_PRIMARY_GRENADE2_ATTACK, - - ACT_MP_SECONDARY_GRENADE1_DRAW, - ACT_MP_SECONDARY_GRENADE1_IDLE, - ACT_MP_SECONDARY_GRENADE1_ATTACK, - ACT_MP_SECONDARY_GRENADE2_DRAW, - ACT_MP_SECONDARY_GRENADE2_IDLE, - ACT_MP_SECONDARY_GRENADE2_ATTACK, - - ACT_MP_MELEE_GRENADE1_DRAW, - ACT_MP_MELEE_GRENADE1_IDLE, - ACT_MP_MELEE_GRENADE1_ATTACK, - ACT_MP_MELEE_GRENADE2_DRAW, - ACT_MP_MELEE_GRENADE2_IDLE, - ACT_MP_MELEE_GRENADE2_ATTACK, - - // Building - ACT_MP_STAND_BUILDING, - ACT_MP_CROUCH_BUILDING, - ACT_MP_RUN_BUILDING, - ACT_MP_WALK_BUILDING, - ACT_MP_AIRWALK_BUILDING, - ACT_MP_CROUCHWALK_BUILDING, - ACT_MP_JUMP_BUILDING, - ACT_MP_JUMP_START_BUILDING, - ACT_MP_JUMP_FLOAT_BUILDING, - ACT_MP_JUMP_LAND_BUILDING, - ACT_MP_SWIM_BUILDING, - - ACT_MP_ATTACK_STAND_BUILDING, // RUN, WALK - ACT_MP_ATTACK_CROUCH_BUILDING, // CROUCHWALK - ACT_MP_ATTACK_SWIM_BUILDING, - ACT_MP_ATTACK_AIRWALK_BUILDING, - - ACT_MP_ATTACK_STAND_GRENADE_BUILDING, // RUN, WALK - ACT_MP_ATTACK_CROUCH_GRENADE_BUILDING, // CROUCHWALK - ACT_MP_ATTACK_SWIM_GRENADE_BUILDING, - ACT_MP_ATTACK_AIRWALK_GRENADE_BUILDING, - - ACT_MP_STAND_PDA, - ACT_MP_CROUCH_PDA, - ACT_MP_RUN_PDA, - ACT_MP_WALK_PDA, - ACT_MP_AIRWALK_PDA, - ACT_MP_CROUCHWALK_PDA, - ACT_MP_JUMP_PDA, - ACT_MP_JUMP_START_PDA, - ACT_MP_JUMP_FLOAT_PDA, - ACT_MP_JUMP_LAND_PDA, - ACT_MP_SWIM_PDA, - - ACT_MP_ATTACK_STAND_PDA, - ACT_MP_ATTACK_SWIM_PDA, - - ACT_MP_GESTURE_VC_HANDMOUTH, - ACT_MP_GESTURE_VC_FINGERPOINT, - ACT_MP_GESTURE_VC_FISTPUMP, - ACT_MP_GESTURE_VC_THUMBSUP, - ACT_MP_GESTURE_VC_NODYES, - ACT_MP_GESTURE_VC_NODNO, - - ACT_MP_GESTURE_VC_HANDMOUTH_PRIMARY, - ACT_MP_GESTURE_VC_FINGERPOINT_PRIMARY, - ACT_MP_GESTURE_VC_FISTPUMP_PRIMARY, - ACT_MP_GESTURE_VC_THUMBSUP_PRIMARY, - ACT_MP_GESTURE_VC_NODYES_PRIMARY, - ACT_MP_GESTURE_VC_NODNO_PRIMARY, - - ACT_MP_GESTURE_VC_HANDMOUTH_SECONDARY, - ACT_MP_GESTURE_VC_FINGERPOINT_SECONDARY, - ACT_MP_GESTURE_VC_FISTPUMP_SECONDARY, - ACT_MP_GESTURE_VC_THUMBSUP_SECONDARY, - ACT_MP_GESTURE_VC_NODYES_SECONDARY, - ACT_MP_GESTURE_VC_NODNO_SECONDARY, - - ACT_MP_GESTURE_VC_HANDMOUTH_MELEE, - ACT_MP_GESTURE_VC_FINGERPOINT_MELEE, - ACT_MP_GESTURE_VC_FISTPUMP_MELEE, - ACT_MP_GESTURE_VC_THUMBSUP_MELEE, - ACT_MP_GESTURE_VC_NODYES_MELEE, - ACT_MP_GESTURE_VC_NODNO_MELEE, - - ACT_MP_GESTURE_VC_HANDMOUTH_BUILDING, - ACT_MP_GESTURE_VC_FINGERPOINT_BUILDING, - ACT_MP_GESTURE_VC_FISTPUMP_BUILDING, - ACT_MP_GESTURE_VC_THUMBSUP_BUILDING, - ACT_MP_GESTURE_VC_NODYES_BUILDING, - ACT_MP_GESTURE_VC_NODNO_BUILDING, - - ACT_MP_GESTURE_VC_HANDMOUTH_PDA, - ACT_MP_GESTURE_VC_FINGERPOINT_PDA, - ACT_MP_GESTURE_VC_FISTPUMP_PDA, - ACT_MP_GESTURE_VC_THUMBSUP_PDA, - ACT_MP_GESTURE_VC_NODYES_PDA, - ACT_MP_GESTURE_VC_NODNO_PDA, - - - ACT_VM_UNUSABLE, - ACT_VM_UNUSABLE_TO_USABLE, - ACT_VM_USABLE_TO_UNUSABLE, - - // Specific viewmodel activities for weapon roles - ACT_PRIMARY_VM_DRAW, - ACT_PRIMARY_VM_HOLSTER, - ACT_PRIMARY_VM_IDLE, - ACT_PRIMARY_VM_PULLBACK, - ACT_PRIMARY_VM_PRIMARYATTACK, - ACT_PRIMARY_VM_SECONDARYATTACK, - ACT_PRIMARY_VM_RELOAD, - ACT_PRIMARY_VM_DRYFIRE, - ACT_PRIMARY_VM_IDLE_TO_LOWERED, - ACT_PRIMARY_VM_IDLE_LOWERED, - ACT_PRIMARY_VM_LOWERED_TO_IDLE, - - ACT_SECONDARY_VM_DRAW, - ACT_SECONDARY_VM_HOLSTER, - ACT_SECONDARY_VM_IDLE, - ACT_SECONDARY_VM_PULLBACK, - ACT_SECONDARY_VM_PRIMARYATTACK, - ACT_SECONDARY_VM_SECONDARYATTACK, - ACT_SECONDARY_VM_RELOAD, - ACT_SECONDARY_VM_DRYFIRE, - ACT_SECONDARY_VM_IDLE_TO_LOWERED, - ACT_SECONDARY_VM_IDLE_LOWERED, - ACT_SECONDARY_VM_LOWERED_TO_IDLE, - - ACT_MELEE_VM_DRAW, - ACT_MELEE_VM_HOLSTER, - ACT_MELEE_VM_IDLE, - ACT_MELEE_VM_PULLBACK, - ACT_MELEE_VM_PRIMARYATTACK, - ACT_MELEE_VM_SECONDARYATTACK, - ACT_MELEE_VM_RELOAD, - ACT_MELEE_VM_DRYFIRE, - ACT_MELEE_VM_IDLE_TO_LOWERED, - ACT_MELEE_VM_IDLE_LOWERED, - ACT_MELEE_VM_LOWERED_TO_IDLE, - - ACT_PDA_VM_DRAW, - ACT_PDA_VM_HOLSTER, - ACT_PDA_VM_IDLE, - ACT_PDA_VM_PULLBACK, - ACT_PDA_VM_PRIMARYATTACK, - ACT_PDA_VM_SECONDARYATTACK, - ACT_PDA_VM_RELOAD, - ACT_PDA_VM_DRYFIRE, - ACT_PDA_VM_IDLE_TO_LOWERED, - ACT_PDA_VM_IDLE_LOWERED, - ACT_PDA_VM_LOWERED_TO_IDLE, - - // this is the end of the global activities, private per-monster activities start here. - LAST_SHARED_ACTIVITY, -} Activity; - - -#endif // AI_ACTIVITY_H - diff --git a/game/shared/ai_debug_shared.h b/game/shared/ai_debug_shared.h deleted file mode 100644 index 1979d3503..000000000 --- a/game/shared/ai_debug_shared.h +++ /dev/null @@ -1,64 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef AI_DEBUG_SHARED_H -#define AI_DEBUG_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "tier0/vprof.h" - - -// This uses VPROF to profile -//#define VPROF_AI 1 - - -#ifdef VPROF_AI -inline void AI_TraceLine( const Vector& vecAbsStart, const Vector& vecAbsEnd, unsigned int mask, - const IHandleEntity *ignore, int collisionGroup, trace_t *ptr ) -{ - VPROF( "AI_TraceLine" ); - UTIL_TraceLine( vecAbsStart, vecAbsEnd, mask, ignore, collisionGroup, ptr ); -} - -inline void AI_TraceLine( const Vector& vecAbsStart, const Vector& vecAbsEnd, unsigned int mask, - ITraceFilter *pFilter, trace_t *ptr ) -{ - VPROF( "AI_TraceLine" ); - UTIL_TraceLine( vecAbsStart, vecAbsEnd, mask, pFilter, ptr ); -} - -inline void AI_TraceHull( const Vector &vecAbsStart, const Vector &vecAbsEnd, const Vector &hullMin, - const Vector &hullMax, unsigned int mask, const IHandleEntity *ignore, - int collisionGroup, trace_t *ptr ) -{ - VPROF( "AI_TraceHull" ); - UTIL_TraceHull( vecAbsStart, vecAbsEnd, hullMin, hullMax, mask, ignore, collisionGroup, ptr ); -} - -inline void AI_TraceHull( const Vector &vecAbsStart, const Vector &vecAbsEnd, const Vector &hullMin, - const Vector &hullMax, unsigned int mask, ITraceFilter *pFilter, trace_t *ptr ) -{ - VPROF( "AI_TraceHull" ); - UTIL_TraceHull( vecAbsStart, vecAbsEnd, hullMin, hullMax, mask, pFilter, ptr ); -} - -inline void AI_TraceEntity( CBaseEntity *pEntity, const Vector &vecAbsStart, const Vector &vecAbsEnd, unsigned int mask, trace_t *ptr ) -{ - VPROF( "AI_TraceEntity" ); - UTIL_TraceEntity( pEntity, vecAbsStart, vecAbsEnd, mask, ptr ); -} - -#else -#define AI_TraceLine UTIL_TraceLine -#define AI_TraceHull UTIL_TraceHull -#define AI_TraceEntity UTIL_TraceEntity -#endif - - -#endif // AI_DEBUG_SHARED_H diff --git a/game/shared/ammodef.cpp b/game/shared/ammodef.cpp deleted file mode 100644 index 9f3a045ae..000000000 --- a/game/shared/ammodef.cpp +++ /dev/null @@ -1,295 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Base combat character with no AI -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ammodef.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Return a pointer to the Ammo at the Index passed in -//----------------------------------------------------------------------------- -Ammo_t *CAmmoDef::GetAmmoOfIndex(int nAmmoIndex) -{ - if ( nAmmoIndex >= m_nAmmoIndex ) - return NULL; - - return &m_AmmoType[ nAmmoIndex ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int CAmmoDef::Index(const char *psz) -{ - int i; - - if (!psz) - return -1; - - for (i = 1; i < m_nAmmoIndex; i++) - { - if (stricmp( psz, m_AmmoType[i].pName ) == 0) - return i; - } - - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int CAmmoDef::PlrDamage(int nAmmoIndex) -{ - if ( nAmmoIndex < 1 || nAmmoIndex >= m_nAmmoIndex ) - return 0; - - if ( m_AmmoType[nAmmoIndex].pPlrDmg == USE_CVAR ) - { - if ( m_AmmoType[nAmmoIndex].pPlrDmgCVar ) - { - return m_AmmoType[nAmmoIndex].pPlrDmgCVar->GetInt(); - } - - return 0; - } - else - { - return m_AmmoType[nAmmoIndex].pPlrDmg; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int CAmmoDef::NPCDamage(int nAmmoIndex) -{ - if ( nAmmoIndex < 1 || nAmmoIndex >= m_nAmmoIndex ) - return 0; - - if ( m_AmmoType[nAmmoIndex].pNPCDmg == USE_CVAR ) - { - if ( m_AmmoType[nAmmoIndex].pNPCDmgCVar ) - { - return m_AmmoType[nAmmoIndex].pNPCDmgCVar->GetInt(); - } - - return 0; - } - else - { - return m_AmmoType[nAmmoIndex].pNPCDmg; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int CAmmoDef::MaxCarry(int nAmmoIndex) -{ - if ( nAmmoIndex < 1 || nAmmoIndex >= m_nAmmoIndex ) - return 0; - - if ( m_AmmoType[nAmmoIndex].pMaxCarry == USE_CVAR ) - { - if ( m_AmmoType[nAmmoIndex].pMaxCarryCVar ) - return m_AmmoType[nAmmoIndex].pMaxCarryCVar->GetInt(); - - return 0; - } - else - { - return m_AmmoType[nAmmoIndex].pMaxCarry; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int CAmmoDef::DamageType(int nAmmoIndex) -{ - if (nAmmoIndex < 1 || nAmmoIndex >= m_nAmmoIndex) - return 0; - - return m_AmmoType[nAmmoIndex].nDamageType; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CAmmoDef::Flags(int nAmmoIndex) -{ - if (nAmmoIndex < 1 || nAmmoIndex >= m_nAmmoIndex) - return 0; - - return m_AmmoType[nAmmoIndex].nFlags; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int CAmmoDef::MinSplashSize(int nAmmoIndex) -{ - if (nAmmoIndex < 1 || nAmmoIndex >= m_nAmmoIndex) - return 4; - - return m_AmmoType[nAmmoIndex].nMinSplashSize; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int CAmmoDef::MaxSplashSize(int nAmmoIndex) -{ - if (nAmmoIndex < 1 || nAmmoIndex >= m_nAmmoIndex) - return 8; - - return m_AmmoType[nAmmoIndex].nMaxSplashSize; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -int CAmmoDef::TracerType(int nAmmoIndex) -{ - if (nAmmoIndex < 1 || nAmmoIndex >= m_nAmmoIndex) - return 0; - - return m_AmmoType[nAmmoIndex].eTracerType; -} - -float CAmmoDef::DamageForce(int nAmmoIndex) -{ - if ( nAmmoIndex < 1 || nAmmoIndex >= m_nAmmoIndex ) - return 0; - - return m_AmmoType[nAmmoIndex].physicsForceImpulse; -} - -//----------------------------------------------------------------------------- -// Purpose: Create an Ammo type with the name, decal, and tracer. -// Does not increment m_nAmmoIndex because the functions below do so and -// are the only entry point. -//----------------------------------------------------------------------------- -bool CAmmoDef::AddAmmoType(char const* name, int damageType, int tracerType, int nFlags, int minSplashSize, int maxSplashSize ) -{ - if (m_nAmmoIndex == MAX_AMMO_TYPES) - return false; - - int len = strlen(name); - m_AmmoType[m_nAmmoIndex].pName = new char[len+1]; - Q_strncpy(m_AmmoType[m_nAmmoIndex].pName, name,len+1); - m_AmmoType[m_nAmmoIndex].nDamageType = damageType; - m_AmmoType[m_nAmmoIndex].eTracerType = tracerType; - m_AmmoType[m_nAmmoIndex].nMinSplashSize = minSplashSize; - m_AmmoType[m_nAmmoIndex].nMaxSplashSize = maxSplashSize; - m_AmmoType[m_nAmmoIndex].nFlags = nFlags; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Add an ammo type with it's damage & carrying capability specified via cvars -//----------------------------------------------------------------------------- -void CAmmoDef::AddAmmoType(char const* name, int damageType, int tracerType, - char const* plr_cvar, char const* npc_cvar, char const* carry_cvar, - float physicsForceImpulse, int nFlags, int minSplashSize, int maxSplashSize) -{ - if ( AddAmmoType( name, damageType, tracerType, nFlags, minSplashSize, maxSplashSize ) == false ) - return; - - if (plr_cvar) - { - m_AmmoType[m_nAmmoIndex].pPlrDmgCVar = cvar->FindVar(plr_cvar); - if (!m_AmmoType[m_nAmmoIndex].pPlrDmgCVar) - { - Msg("ERROR: Ammo (%s) found no CVar named (%s)\n",name,plr_cvar); - } - m_AmmoType[m_nAmmoIndex].pPlrDmg = USE_CVAR; - } - if (npc_cvar) - { - m_AmmoType[m_nAmmoIndex].pNPCDmgCVar = cvar->FindVar(npc_cvar); - if (!m_AmmoType[m_nAmmoIndex].pNPCDmgCVar) - { - Msg("ERROR: Ammo (%s) found no CVar named (%s)\n",name,npc_cvar); - } - m_AmmoType[m_nAmmoIndex].pNPCDmg = USE_CVAR; - } - if (carry_cvar) - { - m_AmmoType[m_nAmmoIndex].pMaxCarryCVar= cvar->FindVar(carry_cvar); - if (!m_AmmoType[m_nAmmoIndex].pMaxCarryCVar) - { - Msg("ERROR: Ammo (%s) found no CVar named (%s)\n",name,carry_cvar); - } - m_AmmoType[m_nAmmoIndex].pMaxCarry = USE_CVAR; - } - m_AmmoType[m_nAmmoIndex].physicsForceImpulse = physicsForceImpulse; - m_nAmmoIndex++; -} - -//----------------------------------------------------------------------------- -// Purpose: Add an ammo type with it's damage & carrying capability specified via integers -//----------------------------------------------------------------------------- -void CAmmoDef::AddAmmoType(char const* name, int damageType, int tracerType, - int plr_dmg, int npc_dmg, int carry, float physicsForceImpulse, - int nFlags, int minSplashSize, int maxSplashSize ) -{ - if ( AddAmmoType( name, damageType, tracerType, nFlags, minSplashSize, maxSplashSize ) == false ) - return; - - m_AmmoType[m_nAmmoIndex].pPlrDmg = plr_dmg; - m_AmmoType[m_nAmmoIndex].pNPCDmg = npc_dmg; - m_AmmoType[m_nAmmoIndex].pMaxCarry = carry; - m_AmmoType[m_nAmmoIndex].physicsForceImpulse = physicsForceImpulse; - - m_nAmmoIndex++; -} - -//----------------------------------------------------------------------------- -// Purpose: Constructor -// Input : -// Output : -//----------------------------------------------------------------------------- -CAmmoDef::CAmmoDef(void) -{ - // Start with an index of 1. Client assumes 0 is an invalid ammo type - m_nAmmoIndex = 1; - memset( m_AmmoType, 0, sizeof( m_AmmoType ) ); -} - -CAmmoDef::~CAmmoDef( void ) -{ - for ( int i = 1; i < MAX_AMMO_TYPES; i++ ) - { - delete[] m_AmmoType[ i ].pName; - } -} - - diff --git a/game/shared/ammodef.h b/game/shared/ammodef.h deleted file mode 100644 index 323831a49..000000000 --- a/game/shared/ammodef.h +++ /dev/null @@ -1,103 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Holds defintion for game ammo types -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef AI_AMMODEF_H -#define AI_AMMODEF_H - -#ifdef _WIN32 -#pragma once -#endif - -class ConVar; - -struct Ammo_t -{ - char *pName; - int nDamageType; - int eTracerType; - float physicsForceImpulse; - int nMinSplashSize; - int nMaxSplashSize; - - int nFlags; - - // Values for player/NPC damage and carrying capability - // If the integers are set, they override the CVars - int pPlrDmg; // CVar for player damage amount - int pNPCDmg; // CVar for NPC damage amount - int pMaxCarry; // CVar for maximum number can carry - const ConVar* pPlrDmgCVar; // CVar for player damage amount - const ConVar* pNPCDmgCVar; // CVar for NPC damage amount - const ConVar* pMaxCarryCVar; // CVar for maximum number can carry -}; - -// Used to tell AmmoDef to use the cvars, not the integers -#define USE_CVAR -1 -// Ammo is infinite -#define INFINITE_AMMO -2 - -enum AmmoTracer_t -{ - TRACER_NONE, - TRACER_LINE, - TRACER_RAIL, - TRACER_BEAM, - TRACER_LINE_AND_WHIZ, -}; - -enum AmmoFlags_t -{ - AMMO_FORCE_DROP_IF_CARRIED = 0x1, - AMMO_INTERPRET_PLRDAMAGE_AS_DAMAGE_TO_PLAYER = 0x2, -}; - - -#include "shareddefs.h" - -//============================================================================= -// >> CAmmoDef -//============================================================================= -class CAmmoDef -{ - -public: - int m_nAmmoIndex; - - Ammo_t m_AmmoType[MAX_AMMO_TYPES]; - - Ammo_t *GetAmmoOfIndex(int nAmmoIndex); - int Index(const char *psz); - int PlrDamage(int nAmmoIndex); - int NPCDamage(int nAmmoIndex); - int MaxCarry(int nAmmoIndex); - int DamageType(int nAmmoIndex); - int TracerType(int nAmmoIndex); - float DamageForce(int nAmmoIndex); - int MinSplashSize(int nAmmoIndex); - int MaxSplashSize(int nAmmoIndex); - int Flags(int nAmmoIndex); - - void AddAmmoType(char const* name, int damageType, int tracerType, int plr_dmg, int npc_dmg, int carry, float physicsForceImpulse, int nFlags, int minSplashSize = 4, int maxSplashSize = 8 ); - void AddAmmoType(char const* name, int damageType, int tracerType, char const* plr_cvar, char const* npc_var, char const* carry_cvar, float physicsForceImpulse, int nFlags, int minSplashSize = 4, int maxSplashSize = 8 ); - - CAmmoDef(void); - virtual ~CAmmoDef( void ); - -private: - bool AddAmmoType(char const* name, int damageType, int tracerType, int nFlags, int minSplashSize, int maxSplashSize ); -}; - - -// Get the global ammodef object. This is usually implemented in each mod's game rules file somewhere, -// so the mod can setup custom ammo types. -CAmmoDef* GetAmmoDef(); - - -#endif // AI_AMMODEF_H - diff --git a/game/shared/animation.cpp b/game/shared/animation.cpp deleted file mode 100644 index 1c3b38a88..000000000 --- a/game/shared/animation.cpp +++ /dev/null @@ -1,974 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "studio.h" -#include "activitylist.h" -#include "engine/IEngineSound.h" -#include "ai_activity.h" -#include "animation.h" -#include "bone_setup.h" -#include "scriptevent.h" -#include "npcevent.h" -#include "eventlist.h" -#include "tier0/vprof.h" - -#if !defined( CLIENT_DLL ) && !defined( MAKEXVCD ) -#include "util.h" -#include "enginecallback.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#ifdef _MSC_VER -#pragma warning( disable : 4244 ) -#endif - -#define iabs(i) (( (i) >= 0 ) ? (i) : -(i) ) - -int ExtractBbox( CStudioHdr *pstudiohdr, int sequence, Vector& mins, Vector& maxs ) -{ - if (! pstudiohdr) - return 0; - - if (!pstudiohdr->SequencesAvailable()) - return 0; - - mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( sequence ); - - mins = seqdesc.bbmin; - - maxs = seqdesc.bbmax; - - return 1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// Input : *pstudiohdr - -// iSequence - -// -// Output : mstudioseqdesc_t -//----------------------------------------------------------------------------- - -extern int g_nActivityListVersion; -extern int g_nEventListVersion; - -void SetEventIndexForSequence( mstudioseqdesc_t &seqdesc ) -{ - if ( &seqdesc == NULL ) - return; - - seqdesc.flags |= STUDIO_EVENT; - - if ( seqdesc.numevents == 0 ) - return; - - for ( int index = 0; index < (int)seqdesc.numevents; index++ ) - { - mstudioevent_t *pevent = seqdesc.pEvent( index ); - - if ( !pevent ) - continue; - - if ( pevent->type & AE_TYPE_NEWEVENTSYSTEM ) - { - const char *pEventName = pevent->pszEventName(); - - int iEventIndex = EventList_IndexForName( pEventName ); - - if ( iEventIndex == -1 ) - { - pevent->event = EventList_RegisterPrivateEvent( pEventName ); - } - else - { - pevent->event = iEventIndex; - pevent->type |= EventList_GetEventType( iEventIndex ); - } - } - } -} - -mstudioevent_t *GetEventIndexForSequence( mstudioseqdesc_t &seqdesc ) -{ - if (!(seqdesc.flags & STUDIO_EVENT)) - { - SetEventIndexForSequence( seqdesc ); - } - - return seqdesc.pEvent( 0 ); -} - - -void BuildAllAnimationEventIndexes( CStudioHdr *pstudiohdr ) -{ - if ( !pstudiohdr ) - return; - - if( pstudiohdr->GetEventListVersion() != g_nEventListVersion ) - { - for ( int i = 0 ; i < pstudiohdr->GetNumSeq() ; i++ ) - { - SetEventIndexForSequence( pstudiohdr->pSeqdesc( i ) ); - } - - pstudiohdr->SetEventListVersion( g_nEventListVersion ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Ensures that activity / index relationship is recalculated -// Input : -// Output : -//----------------------------------------------------------------------------- -void ResetEventIndexes( CStudioHdr *pstudiohdr ) -{ - if (! pstudiohdr) - return; - - pstudiohdr->SetEventListVersion( g_nEventListVersion - 1 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -void SetActivityForSequence( CStudioHdr *pstudiohdr, int i ) -{ - int iActivityIndex; - const char *pszActivityName; - mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( i ); - - seqdesc.flags |= STUDIO_ACTIVITY; - - pszActivityName = GetSequenceActivityName( pstudiohdr, i ); - if ( pszActivityName[0] != '\0' ) - { - iActivityIndex = ActivityList_IndexForName( pszActivityName ); - - if ( iActivityIndex == -1 ) - { - // Allow this now. Animators can create custom activities that are referenced only on the client or by scripts, etc. - //Warning( "***\nModel %s tried to reference unregistered activity: %s \n***\n", pstudiohdr->name, pszActivityName ); - //Assert(0); - // HACK: the client and server don't share the private activity list so registering it on the client would hose the server -#ifdef CLIENT_DLL - seqdesc.flags &= ~STUDIO_ACTIVITY; -#else - seqdesc.activity = ActivityList_RegisterPrivateActivity( pszActivityName ); -#endif - } - else - { - seqdesc.activity = iActivityIndex; - } - } -} - -//========================================================= -// IndexModelSequences - set activity and event indexes for all model -// sequences that have them. -//========================================================= - -void IndexModelSequences( CStudioHdr *pstudiohdr ) -{ - int i; - - if (! pstudiohdr) - return; - - if (!pstudiohdr->SequencesAvailable()) - return; - - for ( i = 0 ; i < pstudiohdr->GetNumSeq() ; i++ ) - { - SetActivityForSequence( pstudiohdr, i ); - SetEventIndexForSequence( pstudiohdr->pSeqdesc( i ) ); - } - - pstudiohdr->SetActivityListVersion( g_nActivityListVersion ); -} - -//----------------------------------------------------------------------------- -// Purpose: Ensures that activity / index relationship is recalculated -// Input : -// Output : -//----------------------------------------------------------------------------- -void ResetActivityIndexes( CStudioHdr *pstudiohdr ) -{ - if (! pstudiohdr) - return; - - pstudiohdr->SetActivityListVersion( g_nActivityListVersion - 1 ); -} - -void VerifySequenceIndex( CStudioHdr *pstudiohdr ) -{ - if ( !pstudiohdr ) - { - return; - } - - if( pstudiohdr->GetActivityListVersion( ) != g_nActivityListVersion ) - { - // this model's sequences have not yet been indexed by activity - IndexModelSequences( pstudiohdr ); - } -} - -#if !defined( MAKEXVCD ) -bool IsInPrediction() -{ - return CBaseEntity::GetPredictionPlayer() != NULL; -} - -int SelectWeightedSequence( CStudioHdr *pstudiohdr, int activity, int curSequence ) -{ - VPROF( "SelectWeightedSequence" ); - - if (! pstudiohdr) - return 0; - - if (!pstudiohdr->SequencesAvailable()) - return 0; - - VerifySequenceIndex( pstudiohdr ); - -#if STUDIO_SEQUENCE_ACTIVITY_LOOKUPS_ARE_SLOW - int weighttotal = 0; - int seq = ACTIVITY_NOT_AVAILABLE; - int weight = 0; - for (int i = 0; i < pstudiohdr->GetNumSeq(); i++) - { - int curActivity = GetSequenceActivity( pstudiohdr, i, &weight ); - if (curActivity == activity) - { - if ( curSequence == i && weight < 0 ) - { - seq = i; - break; - } - weighttotal += iabs(weight); - - int randomValue; - - if ( IsInPrediction() ) - randomValue = SharedRandomInt( "SelectWeightedSequence", 0, weighttotal - 1, i ); - else - randomValue = RandomInt( 0, weighttotal - 1 ); - - if (!weighttotal || randomValue < iabs(weight)) - seq = i; - } - } - - return seq; -#else - return pstudiohdr->SelectWeightedSequence( activity, curSequence ); -#endif -} - - -// Pick a sequence for the given activity. If the current sequence is appropriate for the -// current activity, and its stored weight is negative (whatever that means), always select -// it. Otherwise perform a weighted selection -- imagine a large roulette wheel, with each -// sequence having a number of spaces corresponding to its weight. -int CStudioHdr::CActivityToSequenceMapping::SelectWeightedSequence( CStudioHdr *pstudiohdr, int activity, int curSequence ) -{ - if (!ValidateAgainst(pstudiohdr)) - { - AssertMsg1(false, "CStudioHdr %s has changed its vmodel pointer without reinitializing its activity mapping! Now performing emergency reinitialization.", pstudiohdr->pszName()); - ExecuteOnce(DebuggerBreakIfDebugging()); - Reinitialize(pstudiohdr); - } - - // a null m_pSequenceTuples just means that this studio header has no activities. - if (!m_pSequenceTuples) - return ACTIVITY_NOT_AVAILABLE; - - // is the current sequence appropriate? - if (curSequence >= 0) - { - mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( curSequence ); - - if (seqdesc.activity == activity && seqdesc.actweight < 0) - return curSequence; - } - - // get the data for the given activity - HashValueType dummy( activity, 0, 0, 0 ); - UtlHashHandle_t handle = m_ActToSeqHash.Find(dummy); - if (!m_ActToSeqHash.IsValidHandle(handle)) - { - return ACTIVITY_NOT_AVAILABLE; - } - const HashValueType * __restrict actData = &m_ActToSeqHash[handle]; - - int weighttotal = actData->totalWeight; - // generate a random number from 0 to the total weight - int randomValue; - if ( IsInPrediction() ) - { - randomValue = SharedRandomInt( "SelectWeightedSequence", 0, weighttotal - 1 ); - } - else - { - randomValue = RandomInt( 0, weighttotal - 1 ); - } - - // chug through the entries in the list (they are sequential therefore cache-coherent) - // until we run out of random juice - SequenceTuple * __restrict sequenceInfo = m_pSequenceTuples + actData->startingIdx; - - const SequenceTuple *const stopHere = sequenceInfo + actData->count; // this is a backup - // in case the weights are somehow miscalculated -- we don't read or write through - // it (because it aliases the restricted pointer above); it's only here for - // the comparison. - - while (randomValue >= sequenceInfo->weight && sequenceInfo < stopHere) - { - randomValue -= sequenceInfo->weight; - ++sequenceInfo; - } - - return sequenceInfo->seqnum; - -} - - -#endif - -int SelectHeaviestSequence( CStudioHdr *pstudiohdr, int activity ) -{ - if ( !pstudiohdr ) - return 0; - - VerifySequenceIndex( pstudiohdr ); - - int maxweight = 0; - int seq = ACTIVITY_NOT_AVAILABLE; - int weight = 0; - for (int i = 0; i < pstudiohdr->GetNumSeq(); i++) - { - int curActivity = GetSequenceActivity( pstudiohdr, i, &weight ); - if (curActivity == activity) - { - if ( iabs(weight) > maxweight ) - { - maxweight = iabs(weight); - seq = i; - } - } - } - - return seq; -} - -void GetEyePosition ( CStudioHdr *pstudiohdr, Vector &vecEyePosition ) -{ - if ( !pstudiohdr ) - { - Warning( "GetEyePosition() Can't get pstudiohdr ptr!\n" ); - return; - } - - vecEyePosition = pstudiohdr->eyeposition(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Looks up an activity by name. -// Input : label - Name of the activity to look up, ie "ACT_IDLE" -// Output : Activity index or ACT_INVALID if not found. -//----------------------------------------------------------------------------- -int LookupActivity( CStudioHdr *pstudiohdr, const char *label ) -{ - VPROF( "LookupActivity" ); - - if ( !pstudiohdr ) - { - return 0; - } - - for ( int i = 0; i < pstudiohdr->GetNumSeq(); i++ ) - { - mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( i ); - if ( stricmp( seqdesc.pszActivityName(), label ) == 0 ) - { - return seqdesc.activity; - } - } - - return ACT_INVALID; -} - -#if !defined( MAKEXVCD ) -//----------------------------------------------------------------------------- -// Purpose: Looks up a sequence by sequence name first, then by activity name. -// Input : label - The sequence name or activity name to look up. -// Output : Returns the sequence index of the matching sequence, or ACT_INVALID. -//----------------------------------------------------------------------------- -int LookupSequence( CStudioHdr *pstudiohdr, const char *label ) -{ - VPROF( "LookupSequence" ); - - if (! pstudiohdr) - return 0; - - if (!pstudiohdr->SequencesAvailable()) - return 0; - - // - // Look up by sequence name. - // - for (int i = 0; i < pstudiohdr->GetNumSeq(); i++) - { - mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( i ); - if (stricmp( seqdesc.pszLabel(), label ) == 0) - return i; - } - - // - // Not found, look up by activity name. - // - int nActivity = LookupActivity( pstudiohdr, label ); - if (nActivity != ACT_INVALID ) - { - return SelectWeightedSequence( pstudiohdr, nActivity ); - } - - return ACT_INVALID; -} - -void GetSequenceLinearMotion( CStudioHdr *pstudiohdr, int iSequence, const float poseParameter[], Vector *pVec ) -{ - if (! pstudiohdr) - { - Msg( "Bad pstudiohdr in GetSequenceLinearMotion()!\n" ); - return; - } - - if (!pstudiohdr->SequencesAvailable()) - return; - - if( iSequence < 0 || iSequence >= pstudiohdr->GetNumSeq() ) - { - // Don't spam on bogus model - if ( pstudiohdr->GetNumSeq() > 0 ) - { - static int msgCount = 0; - while ( ++msgCount < 10 ) - { - Msg( "Bad sequence (%i out of %i max) in GetSequenceLinearMotion() for model '%s'!\n", iSequence, pstudiohdr->GetNumSeq(), pstudiohdr->pszName() ); - } - } - pVec->Init(); - return; - } - - QAngle vecAngles; - Studio_SeqMovement( pstudiohdr, iSequence, 0, 1.0, poseParameter, (*pVec), vecAngles ); -} -#endif - -const char *GetSequenceName( CStudioHdr *pstudiohdr, int iSequence ) -{ - if( !pstudiohdr || iSequence < 0 || iSequence >= pstudiohdr->GetNumSeq() ) - { - if ( pstudiohdr ) - { - Msg( "Bad sequence in GetSequenceName() for model '%s'!\n", pstudiohdr->pszName() ); - } - return "Unknown"; - } - - mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( iSequence ); - return seqdesc.pszLabel(); -} - -const char *GetSequenceActivityName( CStudioHdr *pstudiohdr, int iSequence ) -{ - if( !pstudiohdr || iSequence < 0 || iSequence >= pstudiohdr->GetNumSeq() ) - { - if ( pstudiohdr ) - { - Msg( "Bad sequence in GetSequenceActivityName() for model '%s'!\n", pstudiohdr->pszName() ); - } - return "Unknown"; - } - - mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( iSequence ); - return seqdesc.pszActivityName( ); -} - -int GetSequenceFlags( CStudioHdr *pstudiohdr, int sequence ) -{ - if ( !pstudiohdr || - !pstudiohdr->SequencesAvailable() || - sequence < 0 || - sequence >= pstudiohdr->GetNumSeq() ) - { - return 0; - } - - mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( sequence ); - - return seqdesc.flags; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pstudiohdr - -// sequence - -// type - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool HasAnimationEventOfType( CStudioHdr *pstudiohdr, int sequence, int type ) -{ - if ( !pstudiohdr || sequence >= pstudiohdr->GetNumSeq() ) - return false; - - mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( sequence ); - if ( !&seqdesc ) - return false; - - mstudioevent_t *pevent = GetEventIndexForSequence( seqdesc ); - if ( !pevent ) - return false; - - if (seqdesc.numevents == 0 ) - return false; - - int index; - for ( index = 0; index < (int)seqdesc.numevents; index++ ) - { - if ( pevent[ index ].event == type ) - { - return true; - } - } - - return false; -} - -int GetAnimationEvent( CStudioHdr *pstudiohdr, int sequence, animevent_t *pNPCEvent, float flStart, float flEnd, int index ) -{ - if ( !pstudiohdr || sequence >= pstudiohdr->GetNumSeq() || !pNPCEvent ) - return 0; - - mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( sequence ); - if (seqdesc.numevents == 0 || index >= (int)seqdesc.numevents ) - return 0; - - // Msg( "flStart %f flEnd %f (%d) %s\n", flStart, flEnd, seqdesc.numevents, seqdesc.label ); - mstudioevent_t *pevent = GetEventIndexForSequence( seqdesc ); - for (; index < (int)seqdesc.numevents; index++) - { - // Don't send client-side events to the server AI - if ( pevent[index].type & AE_TYPE_NEWEVENTSYSTEM ) - { - if ( !(pevent[index].type & AE_TYPE_SERVER) ) - continue; - } - else if ( pevent[index].event >= EVENT_CLIENT ) //Adrian - Support the old event system - continue; - - bool bOverlapEvent = false; - - if (pevent[index].cycle >= flStart && pevent[index].cycle < flEnd) - { - bOverlapEvent = true; - } - // FIXME: doesn't work with animations being played in reverse - else if ((seqdesc.flags & STUDIO_LOOPING) && flEnd < flStart) - { - if (pevent[index].cycle >= flStart || pevent[index].cycle < flEnd) - { - bOverlapEvent = true; - } - } - - if (bOverlapEvent) - { - pNPCEvent->pSource = NULL; - pNPCEvent->cycle = pevent[index].cycle; -#if !defined( MAKEXVCD ) - pNPCEvent->eventtime = gpGlobals->curtime; -#else - pNPCEvent->eventtime = 0.0f; -#endif - pNPCEvent->event = pevent[index].event; - pNPCEvent->options = pevent[index].pszOptions(); - pNPCEvent->type = pevent[index].type; - return index + 1; - } - } - return 0; -} - - - -int FindTransitionSequence( CStudioHdr *pstudiohdr, int iCurrentSequence, int iGoalSequence, int *piDir ) -{ - if ( !pstudiohdr ) - return iGoalSequence; - - if ( !pstudiohdr->SequencesAvailable() ) - return iGoalSequence; - - if ( ( iCurrentSequence < 0 ) || ( iCurrentSequence >= pstudiohdr->GetNumSeq() ) ) - return iGoalSequence; - - if ( ( iGoalSequence < 0 ) || ( iGoalSequence >= pstudiohdr->GetNumSeq() ) ) - { - // asking for a bogus sequence. Punt. - Assert( 0 ); - return iGoalSequence; - } - - - // bail if we're going to or from a node 0 - if (pstudiohdr->EntryNode( iCurrentSequence ) == 0 || pstudiohdr->EntryNode( iGoalSequence ) == 0) - { - *piDir = 1; - return iGoalSequence; - } - - int iEndNode; - - // Msg( "from %d to %d: ", pEndNode->iEndNode, pGoalNode->iStartNode ); - - // check to see if we should be going forward or backward through the graph - if (*piDir > 0) - { - iEndNode = pstudiohdr->ExitNode( iCurrentSequence ); - } - else - { - iEndNode = pstudiohdr->EntryNode( iCurrentSequence ); - } - - // if both sequences are on the same node, just go there - if (iEndNode == pstudiohdr->EntryNode( iGoalSequence )) - { - *piDir = 1; - return iGoalSequence; - } - - int iInternNode = pstudiohdr->GetTransition( iEndNode, pstudiohdr->EntryNode( iGoalSequence ) ); - - // if there is no transitionial node, just go to the goal sequence - if (iInternNode == 0) - return iGoalSequence; - - int i; - - // look for someone going from the entry node to next node it should hit - // this may be the goal sequences node or an intermediate node - for (i = 0; i < pstudiohdr->GetNumSeq(); i++) - { - mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc(i ); - if (pstudiohdr->EntryNode( i ) == iEndNode && pstudiohdr->ExitNode( i ) == iInternNode) - { - *piDir = 1; - return i; - } - if (seqdesc.nodeflags) - { - if (pstudiohdr->ExitNode( i ) == iEndNode && pstudiohdr->EntryNode( i ) == iInternNode) - { - *piDir = -1; - return i; - } - } - } - - // this means that two parts of the node graph are not connected. - DevMsg( 2, "error in transition graph: %s to %s\n", pstudiohdr->pszNodeName( iEndNode ), pstudiohdr->pszNodeName( pstudiohdr->EntryNode( iGoalSequence ) )); - // Go ahead and jump to the goal sequence - return iGoalSequence; -} - - - - - - -bool GotoSequence( CStudioHdr *pstudiohdr, int iCurrentSequence, float flCurrentCycle, float flCurrentRate, int iGoalSequence, int &nNextSequence, float &flNextCycle, int &iNextDir ) -{ - if ( !pstudiohdr ) - return false; - - if ( !pstudiohdr->SequencesAvailable() ) - return false; - - if ( ( iCurrentSequence < 0 ) || ( iCurrentSequence >= pstudiohdr->GetNumSeq() ) ) - return false; - - if ( ( iGoalSequence < 0 ) || ( iGoalSequence >= pstudiohdr->GetNumSeq() ) ) - { - // asking for a bogus sequence. Punt. - Assert( 0 ); - return false; - } - - // bail if we're going to or from a node 0 - if (pstudiohdr->EntryNode( iCurrentSequence ) == 0 || pstudiohdr->EntryNode( iGoalSequence ) == 0) - { - iNextDir = 1; - flNextCycle = 0.0; - nNextSequence = iGoalSequence; - return true; - } - - int iEndNode = pstudiohdr->ExitNode( iCurrentSequence ); - // Msg( "from %d to %d: ", pEndNode->iEndNode, pGoalNode->iStartNode ); - - // if we're in a transition sequence - if (pstudiohdr->EntryNode( iCurrentSequence ) != pstudiohdr->ExitNode( iCurrentSequence )) - { - // are we done with it? - if (flCurrentRate > 0.0 && flCurrentCycle >= 0.999) - { - iEndNode = pstudiohdr->ExitNode( iCurrentSequence ); - } - else if (flCurrentRate < 0.0 && flCurrentCycle <= 0.001) - { - iEndNode = pstudiohdr->EntryNode( iCurrentSequence ); - } - else - { - // nope, exit - return false; - } - } - - // if both sequences are on the same node, just go there - if (iEndNode == pstudiohdr->EntryNode( iGoalSequence )) - { - iNextDir = 1; - flNextCycle = 0.0; - nNextSequence = iGoalSequence; - return true; - } - - int iInternNode = pstudiohdr->GetTransition( iEndNode, pstudiohdr->EntryNode( iGoalSequence ) ); - - // if there is no transitionial node, just go to the goal sequence - if (iInternNode == 0) - { - iNextDir = 1; - flNextCycle = 0.0; - nNextSequence = iGoalSequence; - return true; - } - - int i; - - // look for someone going from the entry node to next node it should hit - // this may be the goal sequences node or an intermediate node - for (i = 0; i < pstudiohdr->GetNumSeq(); i++) - { - mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc(i ); - if (pstudiohdr->EntryNode( i ) == iEndNode && pstudiohdr->ExitNode( i ) == iInternNode) - { - iNextDir = 1; - flNextCycle = 0.0; - nNextSequence = i; - return true; - } - if (seqdesc.nodeflags) - { - if (pstudiohdr->ExitNode( i ) == iEndNode && pstudiohdr->EntryNode( i ) == iInternNode) - { - iNextDir = -1; - flNextCycle = 0.999; - nNextSequence = i; - return true; - } - } - } - - // this means that two parts of the node graph are not connected. - DevMsg( 2, "error in transition graph: %s to %s\n", pstudiohdr->pszNodeName( iEndNode ), pstudiohdr->pszNodeName( pstudiohdr->EntryNode( iGoalSequence ) )); - return false; -} - -void SetBodygroup( CStudioHdr *pstudiohdr, int& body, int iGroup, int iValue ) -{ - if (! pstudiohdr) - return; - - if (iGroup >= pstudiohdr->numbodyparts()) - return; - - mstudiobodyparts_t *pbodypart = pstudiohdr->pBodypart( iGroup ); - - if (iValue >= pbodypart->nummodels) - return; - - int iCurrent = (body / pbodypart->base) % pbodypart->nummodels; - - body = (body - (iCurrent * pbodypart->base) + (iValue * pbodypart->base)); -} - - -int GetBodygroup( CStudioHdr *pstudiohdr, int body, int iGroup ) -{ - if (! pstudiohdr) - return 0; - - if (iGroup >= pstudiohdr->numbodyparts()) - return 0; - - mstudiobodyparts_t *pbodypart = pstudiohdr->pBodypart( iGroup ); - - if (pbodypart->nummodels <= 1) - return 0; - - int iCurrent = (body / pbodypart->base) % pbodypart->nummodels; - - return iCurrent; -} - -const char *GetBodygroupName( CStudioHdr *pstudiohdr, int iGroup ) -{ - if ( !pstudiohdr) - return ""; - - if (iGroup >= pstudiohdr->numbodyparts()) - return ""; - - mstudiobodyparts_t *pbodypart = pstudiohdr->pBodypart( iGroup ); - return pbodypart->pszName(); -} - -int FindBodygroupByName( CStudioHdr *pstudiohdr, const char *name ) -{ - if ( !pstudiohdr ) - return -1; - - int group; - for ( group = 0; group < pstudiohdr->numbodyparts(); group++ ) - { - mstudiobodyparts_t *pbodypart = pstudiohdr->pBodypart( group ); - if ( !Q_strcasecmp( name, pbodypart->pszName() ) ) - { - return group; - } - } - - return -1; -} - -int GetBodygroupCount( CStudioHdr *pstudiohdr, int iGroup ) -{ - if ( !pstudiohdr ) - return 0; - - if (iGroup >= pstudiohdr->numbodyparts()) - return 0; - - mstudiobodyparts_t *pbodypart = pstudiohdr->pBodypart( iGroup ); - return pbodypart->nummodels; -} - -int GetNumBodyGroups( CStudioHdr *pstudiohdr ) -{ - if ( !pstudiohdr ) - return 0; - - return pstudiohdr->numbodyparts(); -} - -int GetSequenceActivity( CStudioHdr *pstudiohdr, int sequence, int *pweight ) -{ - if (!pstudiohdr || !pstudiohdr->SequencesAvailable() ) - { - if (pweight) - *pweight = 0; - return 0; - } - - mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( sequence ); - - if (!(seqdesc.flags & STUDIO_ACTIVITY)) - { - SetActivityForSequence( pstudiohdr, sequence ); - } - if (pweight) - *pweight = seqdesc.actweight; - return seqdesc.activity; -} - - -void GetAttachmentLocalSpace( CStudioHdr *pstudiohdr, int attachIndex, matrix3x4_t &pLocalToWorld ) -{ - if ( attachIndex >= 0 ) - { - const mstudioattachment_t &pAttachment = pstudiohdr->pAttachment(attachIndex); - MatrixCopy( pAttachment.local, pLocalToWorld ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pstudiohdr - -// *name - -// Output : int -//----------------------------------------------------------------------------- -int FindHitboxSetByName( CStudioHdr *pstudiohdr, const char *name ) -{ - if ( !pstudiohdr ) - return -1; - - for ( int i = 0; i < pstudiohdr->numhitboxsets(); i++ ) - { - mstudiohitboxset_t *set = pstudiohdr->pHitboxSet( i ); - if ( !set ) - continue; - - if ( !stricmp( set->pszName(), name ) ) - return i; - } - - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pstudiohdr - -// setnumber - -// Output : char const -//----------------------------------------------------------------------------- -const char *GetHitboxSetName( CStudioHdr *pstudiohdr, int setnumber ) -{ - if ( !pstudiohdr ) - return ""; - - mstudiohitboxset_t *set = pstudiohdr->pHitboxSet( setnumber ); - if ( !set ) - return ""; - - return set->pszName(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pstudiohdr - -// Output : int -//----------------------------------------------------------------------------- -int GetHitboxSetCount( CStudioHdr *pstudiohdr ) -{ - if ( !pstudiohdr ) - return 0; - - return pstudiohdr->numhitboxsets(); -} diff --git a/game/shared/animation.h b/game/shared/animation.h deleted file mode 100644 index 503f7c91b..000000000 --- a/game/shared/animation.h +++ /dev/null @@ -1,65 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef ANIMATION_H -#define ANIMATION_H - -#define ACTIVITY_NOT_AVAILABLE -1 - -struct animevent_t; -struct studiohdr_t; -class CStudioHdr; -struct mstudioseqdesc_t; - -int ExtractBbox( CStudioHdr *pstudiohdr, int sequence, Vector& mins, Vector& maxs ); - -void IndexModelSequences( CStudioHdr *pstudiohdr ); -void ResetActivityIndexes( CStudioHdr *pstudiohdr ); -void VerifySequenceIndex( CStudioHdr *pstudiohdr ); -int SelectWeightedSequence( CStudioHdr *pstudiohdr, int activity, int curSequence = -1 ); -int SelectHeaviestSequence( CStudioHdr *pstudiohdr, int activity ); -void SetEventIndexForSequence( mstudioseqdesc_t &seqdesc ); -void BuildAllAnimationEventIndexes( CStudioHdr *pstudiohdr ); -void ResetEventIndexes( CStudioHdr *pstudiohdr ); - -void GetEyePosition( CStudioHdr *pstudiohdr, Vector &vecEyePosition ); - -int LookupActivity( CStudioHdr *pstudiohdr, const char *label ); -int LookupSequence( CStudioHdr *pstudiohdr, const char *label ); - -#define NOMOTION 99999 -void GetSequenceLinearMotion( CStudioHdr *pstudiohdr, int iSequence, const float poseParameter[], Vector *pVec ); - -const char *GetSequenceName( CStudioHdr *pstudiohdr, int sequence ); -const char *GetSequenceActivityName( CStudioHdr *pstudiohdr, int iSequence ); - -int GetSequenceFlags( CStudioHdr *pstudiohdr, int sequence ); -int GetAnimationEvent( CStudioHdr *pstudiohdr, int sequence, animevent_t *pNPCEvent, float flStart, float flEnd, int index ); -bool HasAnimationEventOfType( CStudioHdr *pstudiohdr, int sequence, int type ); - -int FindTransitionSequence( CStudioHdr *pstudiohdr, int iCurrentSequence, int iGoalSequence, int *piDir ); -bool GotoSequence( CStudioHdr *pstudiohdr, int iCurrentSequence, float flCurrentCycle, float flCurrentRate, int iGoalSequence, int &nNextSequence, float &flNextCycle, int &iNextDir ); - -void SetBodygroup( CStudioHdr *pstudiohdr, int& body, int iGroup, int iValue ); -int GetBodygroup( CStudioHdr *pstudiohdr, int body, int iGroup ); - -const char *GetBodygroupName( CStudioHdr *pstudiohdr, int iGroup ); -int FindBodygroupByName( CStudioHdr *pstudiohdr, const char *name ); -int GetBodygroupCount( CStudioHdr *pstudiohdr, int iGroup ); -int GetNumBodyGroups( CStudioHdr *pstudiohdr ); - -int GetSequenceActivity( CStudioHdr *pstudiohdr, int sequence, int *pweight = NULL ); - -void GetAttachmentLocalSpace( CStudioHdr *pstudiohdr, int attachIndex, matrix3x4_t &pLocalToWorld ); - -float SetBlending( CStudioHdr *pstudiohdr, int sequence, int *pblendings, int iBlender, float flValue ); - -int FindHitboxSetByName( CStudioHdr *pstudiohdr, const char *name ); -const char *GetHitboxSetName( CStudioHdr *pstudiohdr, int setnumber ); -int GetHitboxSetCount( CStudioHdr *pstudiohdr ); - -#endif //ANIMATION_H diff --git a/game/shared/apparent_velocity_helper.h b/game/shared/apparent_velocity_helper.h deleted file mode 100644 index 852fbb9a5..000000000 --- a/game/shared/apparent_velocity_helper.h +++ /dev/null @@ -1,74 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef APPARENT_VELOCITY_HELPER_H -#define APPARENT_VELOCITY_HELPER_H -#ifdef _WIN32 -#pragma once -#endif - - -inline float CalcDistance( float x, float y ) -{ - return x - y; -} - -inline float CalcDistance( const Vector &a, const Vector &b ) -{ - return a.DistTo( b ); -} - - -template -class CDefaultCalcDistance -{ -public: - static inline float CalcDistance( const T &a, const T &b ) - { - return ::CalcDistance( a, b ); - } -}; - -class CCalcDistance2D -{ -public: - static inline float CalcDistance( const Vector &a, const Vector &b ) - { - return (a-b).Length2D(); - } -}; - - -template< class T, class Functor=CDefaultCalcDistance > -class CApparentVelocity -{ -public: - CApparentVelocity() - { - m_LastTime = -1; - } - - float AddSample( float time, T value ) - { - float flRet = 0; - if ( m_LastTime != -1 ) - { - flRet = Functor::CalcDistance(value, m_LastValue) / (time - m_LastTime); - } - - m_LastTime = time; - m_LastValue = value; - - return flRet; - } - -private: - T m_LastValue; - float m_LastTime; -}; - - -#endif // APPARENT_VELOCITY_HELPER_H diff --git a/game/shared/base_playeranimstate.cpp b/game/shared/base_playeranimstate.cpp deleted file mode 100644 index 63c9d9486..000000000 --- a/game/shared/base_playeranimstate.cpp +++ /dev/null @@ -1,1079 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "base_playeranimstate.h" -#include "tier0/vprof.h" -#include "animation.h" -#include "studio.h" -#include "apparent_velocity_helper.h" -#include "utldict.h" -#include "filesystem.h" - - -#ifdef CLIENT_DLL - #include "c_baseplayer.h" - #include "engine/ivdebugoverlay.h" - - ConVar cl_showanimstate( "cl_showanimstate", "-1", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "Show the (client) animation state for the specified entity (-1 for none)." ); - ConVar showanimstate_log( "cl_showanimstate_log", "0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "1 to output cl_showanimstate to Msg(). 2 to store in AnimStateClient.log. 3 for both." ); -#else - #include "player.h" - ConVar sv_showanimstate( "sv_showanimstate", "-1", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "Show the (server) animation state for the specified entity (-1 for none)." ); - ConVar showanimstate_log( "sv_showanimstate_log", "0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "1 to output sv_showanimstate to Msg(). 2 to store in AnimStateServer.log. 3 for both." ); -#endif - - -// Below this many degrees, slow down turning rate linearly -#define FADE_TURN_DEGREES 45.0f - -// After this, need to start turning feet -#define MAX_TORSO_ANGLE 70.0f - -// Below this amount, don't play a turning animation/perform IK -#define MIN_TURN_ANGLE_REQUIRING_TURN_ANIMATION 15.0f - - -ConVar mp_feetyawrate( - "mp_feetyawrate", - "720", - FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, - "How many degrees per second that we can turn our feet or upper body." ); - -ConVar mp_facefronttime( - "mp_facefronttime", - "3", - FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, - "After this amount of time of standing in place but aiming to one side, go ahead and move feet to face upper body." ); - -ConVar mp_ik( "mp_ik", "1", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Use IK on in-place turns." ); - -// Pose parameters stored for debugging. -float g_flLastBodyPitch, g_flLastBodyYaw, m_flLastMoveYaw; - - -// ------------------------------------------------------------------------------------------------ // -// CBasePlayerAnimState implementation. -// ------------------------------------------------------------------------------------------------ // - -CBasePlayerAnimState::CBasePlayerAnimState() -{ - m_flEyeYaw = 0.0f; - m_flEyePitch = 0.0f; - m_bCurrentFeetYawInitialized = false; - m_flCurrentTorsoYaw = 0.0f; - m_flCurrentTorsoYaw = TURN_NONE; - m_flMaxGroundSpeed = 0.0f; - m_flStoredCycle = 0.0f; - - m_flGaitYaw = 0.0f; - m_flGoalFeetYaw = 0.0f; - m_flCurrentFeetYaw = 0.0f; - m_flLastYaw = 0.0f; - m_flLastTurnTime = 0.0f; - m_angRender.Init(); - m_vLastMovePose.Init(); - m_iCurrent8WayIdleSequence = -1; - m_iCurrent8WayCrouchIdleSequence = -1; - - m_pOuter = NULL; - m_eCurrentMainSequenceActivity = ACT_IDLE; - m_flLastAnimationStateClearTime = 0.0f; -} - - -CBasePlayerAnimState::~CBasePlayerAnimState() -{ -} - - -void CBasePlayerAnimState::Init( CBaseAnimatingOverlay *pPlayer, const CModAnimConfig &config ) -{ - m_pOuter = pPlayer; - m_AnimConfig = config; - ClearAnimationState(); -} - - -void CBasePlayerAnimState::Release() -{ - delete this; -} - - -void CBasePlayerAnimState::ClearAnimationState() -{ - ClearAnimationLayers(); - m_bCurrentFeetYawInitialized = false; - m_flLastAnimationStateClearTime = gpGlobals->curtime; -} - - -float CBasePlayerAnimState::TimeSinceLastAnimationStateClear() const -{ - return gpGlobals->curtime - m_flLastAnimationStateClearTime; -} - - -void CBasePlayerAnimState::Update( float eyeYaw, float eyePitch ) -{ - VPROF( "CBasePlayerAnimState::Update" ); - - // Clear animation overlays because we're about to completely reconstruct them. - ClearAnimationLayers(); - - // Some mods don't want to update the player's animation state if they're dead and ragdolled. - if ( !ShouldUpdateAnimState() ) - { - ClearAnimationState(); - return; - } - - - CStudioHdr *pStudioHdr = GetOuter()->GetModelPtr(); - // Store these. All the calculations are based on them. - m_flEyeYaw = AngleNormalize( eyeYaw ); - m_flEyePitch = AngleNormalize( eyePitch ); - - // Compute sequences for all the layers. - ComputeSequences( pStudioHdr ); - - - // Compute all the pose params. - ComputePoseParam_BodyPitch( pStudioHdr ); // Look up/down. - ComputePoseParam_BodyYaw(); // Torso rotation. - ComputePoseParam_MoveYaw( pStudioHdr ); // What direction his legs are running in. - - - ComputePlaybackRate(); - - -#ifdef CLIENT_DLL - if ( cl_showanimstate.GetInt() == m_pOuter->entindex() ) - { - DebugShowAnimStateFull( 5 ); - } - else if ( cl_showanimstate.GetInt() == -2 ) - { - C_BasePlayer *targetPlayer = C_BasePlayer::GetLocalPlayer(); - - if( targetPlayer && ( targetPlayer->GetObserverMode() == OBS_MODE_IN_EYE || targetPlayer->GetObserverMode() == OBS_MODE_CHASE ) ) - { - C_BaseEntity *target = targetPlayer->GetObserverTarget(); - - if( target && target->IsPlayer() ) - { - targetPlayer = ToBasePlayer( target ); - } - } - - if ( m_pOuter == targetPlayer ) - { - DebugShowAnimStateFull( 6 ); - } - } -#else - if ( sv_showanimstate.GetInt() == m_pOuter->entindex() ) - { - DebugShowAnimState( 20 ); - } -#endif -} - - -bool CBasePlayerAnimState::ShouldUpdateAnimState() -{ - // By default, don't update their animation state when they're dead because they're - // either a ragdoll or they're not drawn. - return GetOuter()->IsAlive(); -} - - -bool CBasePlayerAnimState::ShouldChangeSequences( void ) const -{ - return true; -} - - -void CBasePlayerAnimState::SetOuterPoseParameter( int iParam, float flValue ) -{ - // Make sure to set all the history values too, otherwise the server can overwrite them. - GetOuter()->SetPoseParameter( iParam, flValue ); -} - - -void CBasePlayerAnimState::ClearAnimationLayers() -{ - VPROF( "CBasePlayerAnimState::ClearAnimationLayers" ); - if ( !m_pOuter ) - return; - - m_pOuter->SetNumAnimOverlays( AIMSEQUENCE_LAYER+NUM_AIMSEQUENCE_LAYERS ); - for ( int i=0; i < m_pOuter->GetNumAnimOverlays(); i++ ) - { - m_pOuter->GetAnimOverlay( i )->SetOrder( CBaseAnimatingOverlay::MAX_OVERLAYS ); -#ifndef CLIENT_DLL - m_pOuter->GetAnimOverlay( i )->m_fFlags = 0; -#endif - } -} - - -void CBasePlayerAnimState::RestartMainSequence() -{ - CBaseAnimatingOverlay *pPlayer = GetOuter(); - - pPlayer->m_flAnimTime = gpGlobals->curtime; - pPlayer->SetCycle( 0 ); -} - - -void CBasePlayerAnimState::ComputeSequences( CStudioHdr *pStudioHdr ) -{ - VPROF( "CBasePlayerAnimState::ComputeSequences" ); - - ComputeMainSequence(); // Lower body (walk/run/idle). - UpdateInterpolators(); // The groundspeed interpolator uses the main sequence info. - - if ( m_AnimConfig.m_bUseAimSequences ) - { - ComputeAimSequence(); // Upper body, based on weapon type. - } -} - -void CBasePlayerAnimState::ResetGroundSpeed( void ) -{ - m_flMaxGroundSpeed = GetCurrentMaxGroundSpeed(); -} - -void CBasePlayerAnimState::ComputeMainSequence() -{ - VPROF( "CBasePlayerAnimState::ComputeMainSequence" ); - - CBaseAnimatingOverlay *pPlayer = GetOuter(); - - // Have our class or the mod-specific class determine what the current activity is. - Activity idealActivity = CalcMainActivity(); - -#ifdef CLIENT_DLL - Activity oldActivity = m_eCurrentMainSequenceActivity; -#endif - - // Store our current activity so the aim and fire layers know what to do. - m_eCurrentMainSequenceActivity = idealActivity; - - // Export to our outer class.. - int animDesired = SelectWeightedSequence( TranslateActivity(idealActivity) ); - -#if !defined( HL1_CLIENT_DLL ) && !defined ( HL1_DLL ) - if ( pPlayer->GetSequenceActivity( pPlayer->GetSequence() ) == pPlayer->GetSequenceActivity( animDesired ) ) - return; -#endif - - if ( animDesired < 0 ) - animDesired = 0; - - pPlayer->ResetSequence( animDesired ); - -#ifdef CLIENT_DLL - // If we went from idle to walk, reset the interpolation history. - // Kind of hacky putting this here.. it might belong outside the base class. - if ( (oldActivity == ACT_CROUCHIDLE || oldActivity == ACT_IDLE) && - (idealActivity == ACT_WALK || idealActivity == ACT_RUN_CROUCH) ) - { - ResetGroundSpeed(); - } -#endif -} - - - - - -void CBasePlayerAnimState::UpdateAimSequenceLayers( - float flCycle, - int iFirstLayer, - bool bForceIdle, - CSequenceTransitioner *pTransitioner, - float flWeightScale - ) -{ - float flAimSequenceWeight = 1; - int iAimSequence = CalcAimLayerSequence( &flCycle, &flAimSequenceWeight, bForceIdle ); - if ( iAimSequence == -1 ) - iAimSequence = 0; - - // Feed the current state of the animation parameters to the sequence transitioner. - // It will hand back either 1 or 2 animations in the queue to set, depending on whether - // it's transitioning or not. We just dump those into the animation layers. - pTransitioner->CheckForSequenceChange( - m_pOuter->GetModelPtr(), - iAimSequence, - false, // don't force transitions on the same anim - true // yes, interpolate when transitioning - ); - - pTransitioner->UpdateCurrent( - m_pOuter->GetModelPtr(), - iAimSequence, - flCycle, - GetOuter()->GetPlaybackRate(), - gpGlobals->curtime - ); - - CAnimationLayer *pDest0 = m_pOuter->GetAnimOverlay( iFirstLayer ); - CAnimationLayer *pDest1 = m_pOuter->GetAnimOverlay( iFirstLayer+1 ); - - if ( pTransitioner->m_animationQueue.Count() == 1 ) - { - // If only 1 animation, then blend it in fully. - CAnimationLayer *pSource0 = &pTransitioner->m_animationQueue[0]; - *pDest0 = *pSource0; - - pDest0->m_flWeight = 1; - pDest1->m_flWeight = 0; - pDest0->m_nOrder = iFirstLayer; - -#ifndef CLIENT_DLL - pDest0->m_fFlags |= ANIM_LAYER_ACTIVE; -#endif - } - else if ( pTransitioner->m_animationQueue.Count() >= 2 ) - { - // The first one should be fading out. Fade in the new one inversely. - CAnimationLayer *pSource0 = &pTransitioner->m_animationQueue[0]; - CAnimationLayer *pSource1 = &pTransitioner->m_animationQueue[1]; - - *pDest0 = *pSource0; - *pDest1 = *pSource1; - Assert( pDest0->m_flWeight >= 0.0f && pDest0->m_flWeight <= 1.0f ); - pDest1->m_flWeight = 1 - pDest0->m_flWeight; // This layer just mirrors the other layer's weight (one fades in while the other fades out). - - pDest0->m_nOrder = iFirstLayer; - pDest1->m_nOrder = iFirstLayer+1; - -#ifndef CLIENT_DLL - pDest0->m_fFlags |= ANIM_LAYER_ACTIVE; - pDest1->m_fFlags |= ANIM_LAYER_ACTIVE; -#endif - } - - pDest0->m_flWeight *= flWeightScale * flAimSequenceWeight; - pDest0->m_flWeight = clamp( pDest0->m_flWeight, 0.0f, 1.0f ); - - pDest1->m_flWeight *= flWeightScale * flAimSequenceWeight; - pDest1->m_flWeight = clamp( pDest1->m_flWeight, 0.0f, 1.0f ); - - pDest0->m_flCycle = pDest1->m_flCycle = flCycle; -} - - -void CBasePlayerAnimState::OptimizeLayerWeights( int iFirstLayer, int nLayers ) -{ - int i; - - // Find the total weight of the blended layers, not including the idle layer (iFirstLayer) - float totalWeight = 0.0f; - for ( i=1; i < nLayers; i++ ) - { - CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iFirstLayer+i ); - if ( pLayer->IsActive() && pLayer->m_flWeight > 0.0f ) - { - totalWeight += pLayer->m_flWeight; - } - } - - // Set the idle layer's weight to be 1 minus the sum of other layer weights - CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iFirstLayer ); - if ( pLayer->IsActive() && pLayer->m_flWeight > 0.0f ) - { - pLayer->m_flWeight = 1.0f - totalWeight; - pLayer->m_flWeight = MAX(pLayer->m_flWeight, 0.0f); - } - - // This part is just an optimization. Since we have the walk/run animations weighted on top of - // the idle animations, all this does is disable the idle animations if the walk/runs are at - // full weighting, which is whenever a guy is at full speed. - // - // So it saves us blending a couple animation layers whenever a guy is walking or running full speed. - int iLastOne = -1; - for ( i=0; i < nLayers; i++ ) - { - CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iFirstLayer+i ); - if ( pLayer->IsActive() && pLayer->m_flWeight > 0.99 ) - iLastOne = i; - } - - if ( iLastOne != -1 ) - { - for ( int i=iLastOne-1; i >= 0; i-- ) - { - CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iFirstLayer+i ); -#ifdef CLIENT_DLL - pLayer->m_nOrder = CBaseAnimatingOverlay::MAX_OVERLAYS; -#else - pLayer->m_nOrder.Set( CBaseAnimatingOverlay::MAX_OVERLAYS ); - pLayer->m_fFlags = 0; -#endif - } - } -} - -bool CBasePlayerAnimState::ShouldBlendAimSequenceToIdle() -{ - Activity act = GetCurrentMainSequenceActivity(); - - return (act == ACT_RUN || act == ACT_WALK || act == ACT_RUNTOIDLE || act == ACT_RUN_CROUCH); -} - -void CBasePlayerAnimState::ComputeAimSequence() -{ - VPROF( "CBasePlayerAnimState::ComputeAimSequence" ); - - // Synchronize the lower and upper body cycles. - float flCycle = m_pOuter->GetCycle(); - - // Figure out the new cycle time. - UpdateAimSequenceLayers( flCycle, AIMSEQUENCE_LAYER, true, &m_IdleSequenceTransitioner, 1 ); - - if ( ShouldBlendAimSequenceToIdle() ) - { - // What we do here is blend between the idle upper body animation (like where he's got the dual elites - // held out in front of him but he's not moving) and his walk/run/crouchrun upper body animation, - // weighting it based on how fast he's moving. That way, when he's moving slowly, his upper - // body doesn't jiggle all around. - bool bIsMoving; - float flPlaybackRate = CalcMovementPlaybackRate( &bIsMoving ); - if ( bIsMoving ) - UpdateAimSequenceLayers( flCycle, AIMSEQUENCE_LAYER+2, false, &m_SequenceTransitioner, flPlaybackRate ); - } - - OptimizeLayerWeights( AIMSEQUENCE_LAYER, NUM_AIMSEQUENCE_LAYERS ); -} - - -int CBasePlayerAnimState::CalcSequenceIndex( const char *pBaseName, ... ) -{ - char szFullName[512]; - va_list marker; - va_start( marker, pBaseName ); - Q_vsnprintf( szFullName, sizeof( szFullName ), pBaseName, marker ); - va_end( marker ); - int iSequence = GetOuter()->LookupSequence( szFullName ); - - // Show warnings if we can't find anything here. - if ( iSequence == -1 ) - { - static CUtlDict dict; - if ( dict.Find( szFullName ) == -1 ) - { - dict.Insert( szFullName, 0 ); - Warning( "CalcSequenceIndex: can't find '%s'.\n", szFullName ); - } - - iSequence = 0; - } - - return iSequence; -} - - - -void CBasePlayerAnimState::UpdateInterpolators() -{ - VPROF( "CBasePlayerAnimState::UpdateInterpolators" ); - - // First, figure out their current max speed based on their current activity. - float flCurMaxSpeed = GetCurrentMaxGroundSpeed(); - m_flMaxGroundSpeed = flCurMaxSpeed; -} - - -float CBasePlayerAnimState::GetInterpolatedGroundSpeed() -{ - return m_flMaxGroundSpeed; -} - - -float CBasePlayerAnimState::CalcMovementPlaybackRate( bool *bIsMoving ) -{ - // Determine ideal playback rate - Vector vel; - GetOuterAbsVelocity( vel ); - - float speed = vel.Length2D(); - bool isMoving = ( speed > MOVING_MINIMUM_SPEED ); - - *bIsMoving = false; - float flReturnValue = 1; - - if ( isMoving && CanThePlayerMove() ) - { - float flGroundSpeed = GetInterpolatedGroundSpeed(); - if ( flGroundSpeed < 0.001f ) - { - flReturnValue = 0.01; - } - else - { - // Note this gets set back to 1.0 if sequence changes due to ResetSequenceInfo below - flReturnValue = speed / flGroundSpeed; - flReturnValue = clamp( flReturnValue, 0.01, 10 ); // don't go nuts here. - } - *bIsMoving = true; - } - - return flReturnValue; -} - - -bool CBasePlayerAnimState::CanThePlayerMove() -{ - return true; -} - - -void CBasePlayerAnimState::ComputePlaybackRate() -{ - VPROF( "CBasePlayerAnimState::ComputePlaybackRate" ); - if ( m_AnimConfig.m_LegAnimType != LEGANIM_9WAY && m_AnimConfig.m_LegAnimType != LEGANIM_8WAY ) - { - // When using a 9-way blend, playback rate is always 1 and we just scale the pose params - // to speed up or slow down the animation. - bool bIsMoving; - float flRate = CalcMovementPlaybackRate( &bIsMoving ); - if ( bIsMoving ) - GetOuter()->SetPlaybackRate( flRate ); - else - GetOuter()->SetPlaybackRate( 1 ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CBasePlayer -//----------------------------------------------------------------------------- -CBaseAnimatingOverlay *CBasePlayerAnimState::GetOuter() const -{ - return m_pOuter; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : dt - -//----------------------------------------------------------------------------- -void CBasePlayerAnimState::EstimateYaw() -{ - Vector est_velocity; - GetOuterAbsVelocity( est_velocity ); - - float flLength = est_velocity.Length2D(); - if ( flLength > MOVING_MINIMUM_SPEED ) - { - m_flGaitYaw = atan2( est_velocity[1], est_velocity[0] ); - m_flGaitYaw = RAD2DEG( m_flGaitYaw ); - m_flGaitYaw = AngleNormalize( m_flGaitYaw ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Override for backpeddling -// Input : dt - -//----------------------------------------------------------------------------- -void CBasePlayerAnimState::ComputePoseParam_MoveYaw( CStudioHdr *pStudioHdr ) -{ - VPROF( "CBasePlayerAnimState::ComputePoseParam_MoveYaw" ); - - //Matt: Goldsrc style animations need to not rotate the model - if ( m_AnimConfig.m_LegAnimType == LEGANIM_GOLDSRC ) - { -#ifndef CLIENT_DLL - //Adrian: Make the model's angle match the legs so the hitboxes match on both sides. - GetOuter()->SetLocalAngles( QAngle( 0, m_flCurrentFeetYaw, 0 ) ); -#endif - } - - // If using goldsrc-style animations where he's moving in the direction that his feet are facing, - // we don't use move yaw. - if ( m_AnimConfig.m_LegAnimType != LEGANIM_9WAY && m_AnimConfig.m_LegAnimType != LEGANIM_8WAY ) - return; - - // view direction relative to movement - float flYaw; - - EstimateYaw(); - - float ang = m_flEyeYaw; - if ( ang > 180.0f ) - { - ang -= 360.0f; - } - else if ( ang < -180.0f ) - { - ang += 360.0f; - } - - // calc side to side turning - flYaw = ang - m_flGaitYaw; - // Invert for mapping into 8way blend - flYaw = -flYaw; - flYaw = flYaw - (int)(flYaw / 360) * 360; - - if (flYaw < -180) - { - flYaw = flYaw + 360; - } - else if (flYaw > 180) - { - flYaw = flYaw - 360; - } - - - if ( m_AnimConfig.m_LegAnimType == LEGANIM_9WAY ) - { -#ifndef CLIENT_DLL - //Adrian: Make the model's angle match the legs so the hitboxes match on both sides. - GetOuter()->SetLocalAngles( QAngle( 0, m_flCurrentFeetYaw, 0 ) ); -#endif - - int iMoveX = GetOuter()->LookupPoseParameter( pStudioHdr, "move_x" ); - int iMoveY = GetOuter()->LookupPoseParameter( pStudioHdr, "move_y" ); - if ( iMoveX < 0 || iMoveY < 0 ) - return; - - bool bIsMoving; - float flPlaybackRate = CalcMovementPlaybackRate( &bIsMoving ); - - // Setup the 9-way blend parameters based on our speed and direction. - Vector2D vCurMovePose( 0, 0 ); - - if ( bIsMoving ) - { - vCurMovePose.x = cos( DEG2RAD( flYaw ) ) * flPlaybackRate; - vCurMovePose.y = -sin( DEG2RAD( flYaw ) ) * flPlaybackRate; - } - - GetOuter()->SetPoseParameter( pStudioHdr, iMoveX, vCurMovePose.x ); - GetOuter()->SetPoseParameter( pStudioHdr, iMoveY, vCurMovePose.y ); - - m_vLastMovePose = vCurMovePose; - } - else - { - int iMoveYaw = GetOuter()->LookupPoseParameter( pStudioHdr, "move_yaw" ); - if ( iMoveYaw >= 0 ) - { - GetOuter()->SetPoseParameter( pStudioHdr, iMoveYaw, flYaw ); - m_flLastMoveYaw = flYaw; - - // Now blend in his idle animation. - // This makes the 8-way blend act like a 9-way blend by blending to - // an idle sequence as he slows down. -#if defined(CLIENT_DLL) - bool bIsMoving; - CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( MAIN_IDLE_SEQUENCE_LAYER ); - - pLayer->m_flWeight = 1 - CalcMovementPlaybackRate( &bIsMoving ); - if ( !bIsMoving ) - { - pLayer->m_flWeight = 1; - } - - if ( ShouldChangeSequences() ) - { - // Whenever this layer stops blending, we can choose a new idle sequence to blend to, so he - // doesn't always use the same idle. - if ( pLayer->m_flWeight < 0.02f || m_iCurrent8WayIdleSequence == -1 ) - { - m_iCurrent8WayIdleSequence = m_pOuter->SelectWeightedSequence( ACT_IDLE ); - m_iCurrent8WayCrouchIdleSequence = m_pOuter->SelectWeightedSequence( ACT_CROUCHIDLE ); - } - - if ( m_eCurrentMainSequenceActivity == ACT_CROUCHIDLE || m_eCurrentMainSequenceActivity == ACT_RUN_CROUCH ) - pLayer->m_nSequence = m_iCurrent8WayCrouchIdleSequence; - else - pLayer->m_nSequence = m_iCurrent8WayIdleSequence; - } - - pLayer->m_flPlaybackRate = 1; - pLayer->m_flCycle += m_pOuter->GetSequenceCycleRate( pStudioHdr, pLayer->m_nSequence ) * gpGlobals->frametime; - pLayer->m_flCycle = fmod( pLayer->m_flCycle, 1 ); - pLayer->m_nOrder = MAIN_IDLE_SEQUENCE_LAYER; -#endif - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayerAnimState::ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr ) -{ - VPROF( "CBasePlayerAnimState::ComputePoseParam_BodyPitch" ); - - // Get pitch from v_angle - float flPitch = m_flEyePitch; - if ( flPitch > 180.0f ) - { - flPitch -= 360.0f; - } - flPitch = clamp( flPitch, -90, 90 ); - - // See if we have a blender for pitch - int pitch = GetOuter()->LookupPoseParameter( pStudioHdr, "body_pitch" ); - if ( pitch < 0 ) - return; - - GetOuter()->SetPoseParameter( pStudioHdr, pitch, flPitch ); - g_flLastBodyPitch = flPitch; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : goal - -// maxrate - -// dt - -// current - -// Output : int -//----------------------------------------------------------------------------- -int CBasePlayerAnimState::ConvergeAngles( float goal,float maxrate, float maxgap, float dt, float& current ) -{ - int direction = TURN_NONE; - - float anglediff = goal - current; - anglediff = AngleNormalize( anglediff ); - - float anglediffabs = fabs( anglediff ); - - float scale = 1.0f; - if ( anglediffabs <= FADE_TURN_DEGREES ) - { - scale = anglediffabs / FADE_TURN_DEGREES; - // Always do at least a bit of the turn ( 1% ) - scale = clamp( scale, 0.01f, 1.0f ); - } - - float maxmove = maxrate * dt * scale; - - if ( anglediffabs > maxgap ) - { - // gap is too big, jump - maxmove = (anglediffabs - maxgap); - } - - if ( anglediffabs < maxmove ) - { - // we are close enought, just set the final value - current = goal; - } - else - { - // adjust value up or down - if ( anglediff > 0 ) - { - current += maxmove; - direction = TURN_LEFT; - } - else - { - current -= maxmove; - direction = TURN_RIGHT; - } - } - - current = AngleNormalize( current ); - - return direction; -} - -void CBasePlayerAnimState::ComputePoseParam_BodyYaw() -{ - VPROF( "CBasePlayerAnimState::ComputePoseParam_BodyYaw" ); - - // Find out which way he's running (m_flEyeYaw is the way he's looking). - Vector vel; - GetOuterAbsVelocity( vel ); - bool bIsMoving = vel.Length2D() > MOVING_MINIMUM_SPEED; - - // If we just initialized this guy (maybe he just came into the PVS), then immediately - // set his feet in the right direction, otherwise they'll spin around from 0 to the - // right direction every time someone switches spectator targets. - if ( !m_bCurrentFeetYawInitialized ) - { - m_bCurrentFeetYawInitialized = true; - m_flGoalFeetYaw = m_flCurrentFeetYaw = m_flEyeYaw; - m_flLastTurnTime = 0.0f; - } - else if ( bIsMoving ) - { - // player is moving, feet yaw = aiming yaw - if ( m_AnimConfig.m_LegAnimType == LEGANIM_9WAY || m_AnimConfig.m_LegAnimType == LEGANIM_8WAY ) - { - // His feet point in the direction his eyes are, but they can run in any direction. - m_flGoalFeetYaw = m_flEyeYaw; - } - else - { - m_flGoalFeetYaw = RAD2DEG( atan2( vel.y, vel.x ) ); - - // If he's running backwards, flip his feet backwards. - Vector vEyeYaw( cos( DEG2RAD( m_flEyeYaw ) ), sin( DEG2RAD( m_flEyeYaw ) ), 0 ); - Vector vFeetYaw( cos( DEG2RAD( m_flGoalFeetYaw ) ), sin( DEG2RAD( m_flGoalFeetYaw ) ), 0 ); - if ( vEyeYaw.Dot( vFeetYaw ) < -0.01 ) - { - m_flGoalFeetYaw += 180; - } - } - - } - else if ( (gpGlobals->curtime - m_flLastTurnTime) > mp_facefronttime.GetFloat() ) - { - // player didn't move & turn for quite some time - m_flGoalFeetYaw = m_flEyeYaw; - } - else - { - // If he's rotated his view further than the model can turn, make him face forward. - float flDiff = AngleNormalize( m_flGoalFeetYaw - m_flEyeYaw ); - - if ( fabs(flDiff) > m_AnimConfig.m_flMaxBodyYawDegrees ) - { - if ( flDiff > 0 ) - m_flGoalFeetYaw -= m_AnimConfig.m_flMaxBodyYawDegrees; - else - m_flGoalFeetYaw += m_AnimConfig.m_flMaxBodyYawDegrees; - } - } - - m_flGoalFeetYaw = AngleNormalize( m_flGoalFeetYaw ); - - if ( m_flCurrentFeetYaw != m_flGoalFeetYaw ) - { - ConvergeAngles( m_flGoalFeetYaw, mp_feetyawrate.GetFloat(), m_AnimConfig.m_flMaxBodyYawDegrees, - gpGlobals->frametime, m_flCurrentFeetYaw ); - - m_flLastTurnTime = gpGlobals->curtime; - } - - float flCurrentTorsoYaw = AngleNormalize( m_flEyeYaw - m_flCurrentFeetYaw ); - - // Rotate entire body into position - m_angRender[YAW] = m_flCurrentFeetYaw; - m_angRender[PITCH] = m_angRender[ROLL] = 0; - - SetOuterBodyYaw( flCurrentTorsoYaw ); - g_flLastBodyYaw = flCurrentTorsoYaw; -} - - - -float CBasePlayerAnimState::SetOuterBodyYaw( float flValue ) -{ - int body_yaw = GetOuter()->LookupPoseParameter( "body_yaw" ); - if ( body_yaw < 0 ) - { - return 0; - } - - SetOuterPoseParameter( body_yaw, flValue ); - return flValue; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : activity - -// Output : Activity -//----------------------------------------------------------------------------- -Activity CBasePlayerAnimState::BodyYawTranslateActivity( Activity activity ) -{ - // Not even standing still, sigh - if ( activity != ACT_IDLE ) - return activity; - - // Not turning - switch ( m_nTurningInPlace ) - { - default: - case TURN_NONE: - return activity; - case TURN_RIGHT: - case TURN_LEFT: - return mp_ik.GetBool() ? ACT_TURN : activity; - } - - Assert( 0 ); - return activity; -} - -const QAngle& CBasePlayerAnimState::GetRenderAngles() -{ - return m_angRender; -} - - -void CBasePlayerAnimState::GetOuterAbsVelocity( Vector& vel ) const -{ -#if defined( CLIENT_DLL ) - GetOuter()->EstimateAbsVelocity( vel ); -#else - vel = GetOuter()->GetAbsVelocity(); -#endif -} - - -float CBasePlayerAnimState::GetOuterXYSpeed() const -{ - Vector vel; - GetOuterAbsVelocity( vel ); - return vel.Length2D(); -} - -// ----------------------------------------------------------------------------- -void CBasePlayerAnimState::AnimStateLog( const char *pMsg, ... ) -{ - // Format the string. - char str[4096]; - va_list marker; - va_start( marker, pMsg ); - Q_vsnprintf( str, sizeof( str ), pMsg, marker ); - va_end( marker ); - - // Log it? - if ( showanimstate_log.GetInt() == 1 || showanimstate_log.GetInt() == 3 ) - { - Msg( "%s", str ); - } - - if ( showanimstate_log.GetInt() > 1 ) - { -#ifdef CLIENT_DLL - const char *fname = "AnimStateClient.log"; -#else - const char *fname = "AnimStateServer.log"; -#endif - static FileHandle_t hFile = filesystem->Open( fname, "wt" ); - filesystem->FPrintf( hFile, "%s", str ); - filesystem->Flush( hFile ); - } -} - - -// ----------------------------------------------------------------------------- -void CBasePlayerAnimState::AnimStatePrintf( int iLine, const char *pMsg, ... ) -{ - // Format the string. - char str[4096]; - va_list marker; - va_start( marker, pMsg ); - Q_vsnprintf( str, sizeof( str ), pMsg, marker ); - va_end( marker ); - - // Show it with Con_NPrintf. - engine->Con_NPrintf( iLine, "%s", str ); - - // Log it. - AnimStateLog( "%s\n", str ); -} - - -// ----------------------------------------------------------------------------- -void CBasePlayerAnimState::DebugShowAnimState( int iStartLine ) -{ - Vector vOuterVel; - GetOuterAbsVelocity( vOuterVel ); - - int iLine = iStartLine; - AnimStatePrintf( iLine++, "main: %s(%d), cycle: %.2f cyclerate: %.2f playbackrate: %.2f\n", - GetSequenceName( m_pOuter->GetModelPtr(), m_pOuter->GetSequence() ), - m_pOuter->GetSequence(), - m_pOuter->GetCycle(), - m_pOuter->GetSequenceCycleRate(m_pOuter->GetModelPtr(), m_pOuter->GetSequence()), - m_pOuter->GetPlaybackRate() - ); - - if ( m_AnimConfig.m_LegAnimType == LEGANIM_8WAY ) - { - CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( MAIN_IDLE_SEQUENCE_LAYER ); - - AnimStatePrintf( iLine++, "idle: %s, weight: %.2f\n", - GetSequenceName( m_pOuter->GetModelPtr(), pLayer->m_nSequence ), - (float)pLayer->m_flWeight ); - } - - for ( int i=0; i < m_pOuter->GetNumAnimOverlays()-1; i++ ) - { - CAnimationLayer *pLayer = m_pOuter->GetAnimOverlay( AIMSEQUENCE_LAYER + i ); -#ifdef CLIENT_DLL - AnimStatePrintf( iLine++, "%s(%d), weight: %.2f, cycle: %.2f, order (%d), aim (%d)", - !pLayer->IsActive() ? "-- ": (pLayer->m_nSequence == 0 ? "-- " : GetSequenceName( m_pOuter->GetModelPtr(), pLayer->m_nSequence ) ), - !pLayer->IsActive() ? 0 : (int)pLayer->m_nSequence, - !pLayer->IsActive() ? 0 : (float)pLayer->m_flWeight, - !pLayer->IsActive() ? 0 : (float)pLayer->m_flCycle, - !pLayer->IsActive() ? 0 : (int)pLayer->m_nOrder, - i - ); -#else - AnimStatePrintf( iLine++, "%s(%d), flags (%d), weight: %.2f, cycle: %.2f, order (%d), aim (%d)", - !pLayer->IsActive() ? "-- " : ( pLayer->m_nSequence == 0 ? "-- " : GetSequenceName( m_pOuter->GetModelPtr(), pLayer->m_nSequence ) ), - !pLayer->IsActive() ? 0 : (int)pLayer->m_nSequence, - !pLayer->IsActive() ? 0 : (int)pLayer->m_fFlags,// Doesn't exist on client - !pLayer->IsActive() ? 0 : (float)pLayer->m_flWeight, - !pLayer->IsActive() ? 0 : (float)pLayer->m_flCycle, - !pLayer->IsActive() ? 0 : (int)pLayer->m_nOrder, - i - ); -#endif - } - - AnimStatePrintf( iLine++, "vel: %.2f, time: %.2f, max: %.2f, animspeed: %.2f", - vOuterVel.Length2D(), gpGlobals->curtime, GetInterpolatedGroundSpeed(), m_pOuter->GetSequenceGroundSpeed(m_pOuter->GetSequence()) ); - - if ( m_AnimConfig.m_LegAnimType == LEGANIM_8WAY ) - { - AnimStatePrintf( iLine++, "ent yaw: %.2f, body_yaw: %.2f, move_yaw: %.2f, gait_yaw: %.2f, body_pitch: %.2f", - m_angRender[YAW], g_flLastBodyYaw, m_flLastMoveYaw, m_flGaitYaw, g_flLastBodyPitch ); - } - else - { - AnimStatePrintf( iLine++, "ent yaw: %.2f, body_yaw: %.2f, body_pitch: %.2f, move_x: %.2f, move_y: %.2f", - m_angRender[YAW], g_flLastBodyYaw, g_flLastBodyPitch, m_vLastMovePose.x, m_vLastMovePose.y ); - } - - // Draw a red triangle on the ground for the eye yaw. - float flBaseSize = 10; - float flHeight = 80; - Vector vBasePos = GetOuter()->GetAbsOrigin() + Vector( 0, 0, 3 ); - QAngle angles( 0, 0, 0 ); - angles[YAW] = m_flEyeYaw; - Vector vForward, vRight, vUp; - AngleVectors( angles, &vForward, &vRight, &vUp ); - debugoverlay->AddTriangleOverlay( vBasePos+vRight*flBaseSize/2, vBasePos-vRight*flBaseSize/2, vBasePos+vForward*flHeight, 255, 0, 0, 255, false, 0.01 ); - - // Draw a blue triangle on the ground for the body yaw. - angles[YAW] = m_angRender[YAW]; - AngleVectors( angles, &vForward, &vRight, &vUp ); - debugoverlay->AddTriangleOverlay( vBasePos+vRight*flBaseSize/2, vBasePos-vRight*flBaseSize/2, vBasePos+vForward*flHeight, 0, 0, 255, 255, false, 0.01 ); - -} - -// ----------------------------------------------------------------------------- -void CBasePlayerAnimState::DebugShowAnimStateFull( int iStartLine ) -{ - AnimStateLog( "----------------- frame %d -----------------\n", gpGlobals->framecount ); - - DebugShowAnimState( iStartLine ); - - AnimStateLog( "--------------------------------------------\n\n" ); -} - -// ----------------------------------------------------------------------------- -int CBasePlayerAnimState::SelectWeightedSequence( Activity activity ) -{ - return GetOuter()->SelectWeightedSequence( activity ); -} - diff --git a/game/shared/base_playeranimstate.h b/game/shared/base_playeranimstate.h deleted file mode 100644 index 758b6a55c..000000000 --- a/game/shared/base_playeranimstate.h +++ /dev/null @@ -1,287 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef BASE_PLAYERANIMSTATE_H -#define BASE_PLAYERANIMSTATE_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "iplayeranimstate.h" -#include "studio.h" -#include "sequence_Transitioner.h" - -#ifdef CLIENT_DLL - class C_BaseAnimatingOverlay; - #define CBaseAnimatingOverlay C_BaseAnimatingOverlay -#else - class CBaseAnimatingOverlay; -#endif - -// If a guy is moving slower than this, then he's considered to not be moving -// (so he goes to his idle animation at full playback rate rather than his walk -// animation at low playback rate). -#define MOVING_MINIMUM_SPEED 0.5f - - -#define MAIN_IDLE_SEQUENCE_LAYER 0 // For 8-way blended models, this layer blends an idle on top of the run/walk animation to simulate a 9-way blend. - // For 9-way blended models, we don't use this layer. - -#define AIMSEQUENCE_LAYER 1 // Aim sequence uses layers 0 and 1 for the weapon idle animation (needs 2 layers so it can blend). -#define NUM_AIMSEQUENCE_LAYERS 4 // Then it uses layers 2 and 3 to blend in the weapon run/walk/crouchwalk animation. - - -// Everyone who derives from CBasePlayerAnimState gets to fill in this info -// to drive how the animation state is generated. -class CModAnimConfig -{ -public: - // This tells how far the upper body can rotate left and right. If he begins to rotate - // past this, it'll turn his feet to face his upper body. - float m_flMaxBodyYawDegrees; - - // How do the legs animate? - LegAnimType_t m_LegAnimType; - - // Use aim sequences? (CS hostages don't). - bool m_bUseAimSequences; -}; - - -// ------------------------------------------------------------------------------------------------ // -// CBasePlayerAnimState declaration. -// ------------------------------------------------------------------------------------------------ // - -abstract_class CBasePlayerAnimState : virtual public IPlayerAnimState -{ -public: - DECLARE_CLASS_NOBASE( CBasePlayerAnimState ); - - enum - { - TURN_NONE = 0, - TURN_LEFT, - TURN_RIGHT - }; - - CBasePlayerAnimState(); - virtual ~CBasePlayerAnimState(); - - void Init( CBaseAnimatingOverlay *pPlayer, const CModAnimConfig &config ); - virtual void Release(); - - // Update() and DoAnimationEvent() together maintain the entire player's animation state. - // - // Update() maintains the the lower body animation (the player's m_nSequence) - // and the upper body overlay based on the player's velocity and look direction. - // - // It also modulates these based on events triggered by DoAnimationEvent. - virtual void Update( float eyeYaw, float eyePitch ); - - // This is called by the client when a new player enters the PVS to clear any events - // the dormant version of the entity may have been playing. - virtual void ClearAnimationState(); - - // This is called every frame to prepare the animation layers to be filled with data - // since we reconstruct them every frame (in case they get stomped by the networking - // or anything else). - virtual void ClearAnimationLayers(); - - // The client uses this to figure out what angles to render the entity with (since as the guy turns, - // it will change his body_yaw pose parameter before changing his rendered angle). - virtual const QAngle& GetRenderAngles(); - - -// Overrideables. -public: - - virtual bool ShouldUpdateAnimState(); - - // This is called near the start of each frame. - // The base class figures out the main sequence and the aim sequence, and derived - // classes can overlay whatever other animations they want. - virtual void ComputeSequences( CStudioHdr *pStudioHdr ); - - // This is called to figure out what the main activity is. The mod-specific class - // overrides this to handle events like jumping, firing, etc. - virtual Activity CalcMainActivity() = 0; - - // This is called to calculate the aim layer sequence. It usually figures out the - // animation prefixes and suffixes and calls CalcSequenceIndex(). - virtual int CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle ) = 0; - - // This lets server-controlled idle sequences to play unchanged on the client - virtual bool ShouldChangeSequences( void ) const; - - // If this returns true, then it will blend the current aim layer sequence with an idle aim layer - // sequence based on how fast the character is moving, so it doesn't play the upper-body run at - // full speed if he's moving really slowly. - // - // We return false on this for animations that don't have blends, like reloads. - virtual bool ShouldBlendAimSequenceToIdle(); - - // For the body left/right rotation, some models use a pose parameter and some use a bone controller. - virtual float SetOuterBodyYaw( float flValue ); - - // Return true if the player is allowed to move. - virtual bool CanThePlayerMove(); - - // This is called every frame to see what the maximum speed the player can move is. - // It is used to determine where to put the move_x/move_y pose parameters or to - // determine the animation playback rate, based on the player's movement speed. - // The return value from here is interpolated so the playback rate or pose params don't move sharply. - virtual float GetCurrentMaxGroundSpeed() = 0; - - // Display Con_NPrint output about the animation state. This is called if - // we're on the client and if cl_showanimstate holds the current entity's index. - void DebugShowAnimStateFull( int iStartLine ); - - virtual void DebugShowAnimState( int iStartLine ); - void AnimStatePrintf( int iLine, const char *pMsg, ... ); - void AnimStateLog( const char *pMsg, ... ); - - // Calculate the playback rate for movement layer - virtual float CalcMovementPlaybackRate( bool *bIsMoving ); - - // Allow inheriting classes to translate their desired activity, while keeping all - // internal ACT comparisons using the base activity - virtual Activity TranslateActivity( Activity actDesired ) { return actDesired; } - - // Allow inheriting classes to override SelectWeightedSequence - virtual int SelectWeightedSequence( Activity activity ); - -public: - - void GetPoseParameters( CStudioHdr *pStudioHdr, float poseParameter[MAXSTUDIOPOSEPARAM] ); - - CBaseAnimatingOverlay *GetOuter() const; - - void RestartMainSequence(); - - -// Helpers for the derived classes to use. -protected: - - // Sets up the string you specify, looks for that sequence and returns the index. - // Complains in the console and returns 0 if it can't find it. - virtual int CalcSequenceIndex( const char *pBaseName, ... ); - - Activity GetCurrentMainSequenceActivity() const; - - void GetOuterAbsVelocity( Vector& vel ) const; - float GetOuterXYSpeed() const; - - // How long has it been since we cleared the animation state? - float TimeSinceLastAnimationStateClear() const; - - float GetEyeYaw() const { return m_flEyeYaw; } - -protected: - - CModAnimConfig m_AnimConfig; - CBaseAnimatingOverlay *m_pOuter; - -protected: - int ConvergeAngles( float goal,float maxrate, float maxgap, float dt, float& current ); - virtual void ComputePoseParam_MoveYaw( CStudioHdr *pStudioHdr ); - virtual void ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr ); - virtual void ComputePoseParam_BodyYaw(); - - virtual void ResetGroundSpeed( void ); - -protected: - // The player's eye yaw and pitch angles. - float m_flEyeYaw; - float m_flEyePitch; - - // The following variables are used for tweaking the yaw of the upper body when standing still and - // making sure that it smoothly blends in and out once the player starts moving - // Direction feet were facing when we stopped moving - float m_flGoalFeetYaw; - - float m_flCurrentFeetYaw; - bool m_bCurrentFeetYawInitialized; - - float m_flCurrentTorsoYaw; - - // To check if they are rotating in place - float m_flLastYaw; - - // Time when we stopped moving - float m_flLastTurnTime; - - // One of the above enums - int m_nTurningInPlace; - - QAngle m_angRender; - -private: - - // Update the prone state machine. - void UpdateProneState(); - - // Get the string that's appended to animation names for the player's current weapon. - const char* GetWeaponSuffix(); - - Activity BodyYawTranslateActivity( Activity activity ); - - void SetOuterPoseParameter( int iParam, float flValue ); - - - void EstimateYaw(); - - void ComputeMainSequence(); - void ComputeAimSequence(); - - void ComputePlaybackRate(); - - void UpdateInterpolators(); - float GetInterpolatedGroundSpeed(); - -private: - - float m_flMaxGroundSpeed; - - float m_flLastAnimationStateClearTime; - - // If he's using 8-way blending, then we blend to this idle - int m_iCurrent8WayIdleSequence; - int m_iCurrent8WayCrouchIdleSequence; - - // Last activity we've used on the lower body. Used to determine if animations should restart. - Activity m_eCurrentMainSequenceActivity; - - float m_flGaitYaw; - float m_flStoredCycle; - - Vector2D m_vLastMovePose; - - void UpdateAimSequenceLayers( - float flCycle, - int iFirstLayer, - bool bForceIdle, - CSequenceTransitioner *pTransitioner, - float flWeightScale - ); - - void OptimizeLayerWeights( int iFirstLayer, int nLayers ); - - // This gives us smooth transitions between aim anim sequences on the client. - CSequenceTransitioner m_IdleSequenceTransitioner; - CSequenceTransitioner m_SequenceTransitioner; -}; - -extern float g_flLastBodyPitch, g_flLastBodyYaw, m_flLastMoveYaw; - - -inline Activity CBasePlayerAnimState::GetCurrentMainSequenceActivity() const -{ - return m_eCurrentMainSequenceActivity; -} - - -#endif // BASE_PLAYERANIMSTATE_H diff --git a/game/shared/baseachievement.cpp b/game/shared/baseachievement.cpp deleted file mode 100644 index 5130a9755..000000000 --- a/game/shared/baseachievement.cpp +++ /dev/null @@ -1,654 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#include "achievementmgr.h" -#include "icommandline.h" -#ifdef CLIENT_DLL -#include "tier3/tier3.h" -#include "vgui/ilocalize.h" -#include "achievement_notification_panel.h" -#include "fmtstr.h" -#endif // CLIENT_DLL - -CBaseAchievementHelper *CBaseAchievementHelper::s_pFirst = NULL; - -BEGIN_DATADESC_NO_BASE( CBaseAchievement ) -DEFINE_FIELD( m_iCount, FIELD_INTEGER ), -END_DATADESC() - -BEGIN_DATADESC( CFailableAchievement ) -DEFINE_FIELD( m_bActivated, FIELD_BOOLEAN ), -DEFINE_FIELD( m_bFailed, FIELD_BOOLEAN ), -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: constructor -//----------------------------------------------------------------------------- -CBaseAchievement::CBaseAchievement() -{ - m_iFlags = 0; - m_iGoal = 0; - m_iProgressMsgIncrement = 0; - m_iProgressMsgMinimum = 0; - m_iAchievementID = 0; - m_iPointValue = 0; - m_bHideUntilAchieved = false; - m_bStoreProgressInSteam = false; - m_pVictimClassNameFilter = NULL; - m_pAttackerClassNameFilter = NULL; - m_pInflictorClassNameFilter = NULL; - m_pInflictorEntityNameFilter = NULL; - m_pMapNameFilter = NULL; - m_pGameDirFilter = NULL; - m_pszComponentNames = NULL; - m_pszComponentPrefix = NULL; - m_iNumComponents = 0; - m_iComponentPrefixLen = 0; - m_iComponentBits = 0; - m_iCount = 0; - m_iProgressShown = 0; - m_bAchieved = false; - m_pAchievementMgr = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: sets flags -//----------------------------------------------------------------------------- -void CBaseAchievement::SetFlags( int iFlags ) -{ - // must always specify a save method - Assert( iFlags & ( ACH_SAVE_WITH_GAME | ACH_SAVE_GLOBAL ) ); - - m_iFlags = iFlags; -} - -//----------------------------------------------------------------------------- -// Purpose: called when a game event being listened for is dispatched -//----------------------------------------------------------------------------- -void CBaseAchievement::FireGameEvent( IGameEvent *event ) -{ - // perform common filtering to make it simpler to write achievements - if ( !IsActive() ) - return; - - // if the achievement only applies to a specific map, and it's not the current map, skip it - if ( m_pMapNameFilter && ( 0 != Q_strcmp( m_pAchievementMgr->GetMapName(), m_pMapNameFilter ) ) ) - return; - - const char *name = event->GetName(); - if ( 0 == Q_strcmp( name, "teamplay_round_win" ) ) - { - // if this is a round win and the achievement wants full round events only, filter this out - // if this is not the end of a full round - if ( ( m_iFlags & ACH_FILTER_FULL_ROUND_ONLY ) && ( false == event->GetBool( "full_round" ) ) ) - return; - } - - // let the achievement handle the event - FireGameEvent_Internal( event ); -} - - -//----------------------------------------------------------------------------- -// Purpose: sets victim class to filter with -//----------------------------------------------------------------------------- -void CBaseAchievement::SetVictimFilter( const char *pClassName ) -{ - m_pVictimClassNameFilter = pClassName; -} - -//----------------------------------------------------------------------------- -// Purpose: sets attacker class to filter with -//----------------------------------------------------------------------------- -void CBaseAchievement::SetAttackerFilter( const char *pClassName ) -{ - m_pAttackerClassNameFilter = pClassName; -} - -//----------------------------------------------------------------------------- -// Purpose: sets inflictor class to filter with -//----------------------------------------------------------------------------- -void CBaseAchievement::SetInflictorFilter( const char *pClassName ) -{ - m_pInflictorClassNameFilter = pClassName; -} - -//----------------------------------------------------------------------------- -// Purpose: sets inflictor entity name to filter with -//----------------------------------------------------------------------------- -void CBaseAchievement::SetInflictorEntityNameFilter( const char *pEntityName ) -{ - m_pInflictorEntityNameFilter = pEntityName; -} - -//----------------------------------------------------------------------------- -// Purpose: sets map name to filter with -//----------------------------------------------------------------------------- -void CBaseAchievement::SetMapNameFilter( const char *pMapName ) -{ - m_pMapNameFilter = pMapName; -} - -//----------------------------------------------------------------------------- -// Purpose: sets game dir to filter with. Note: in general, achievements should -// only be compiled into products they pertain to. But if there are -// any game-specific achievements which need to be in a binary shared -// across products (e.g. Ep1 & Ep2), use the game dir as a runtime -// filter. -//----------------------------------------------------------------------------- -void CBaseAchievement::SetGameDirFilter( const char *pGameDir ) -{ - m_pGameDirFilter = pGameDir; -} - -//----------------------------------------------------------------------------- -// Purpose: sets prefix to look for in map event string to identify a component -// for this achievement -//----------------------------------------------------------------------------- -void CBaseAchievement::SetComponentPrefix( const char *pPrefix ) -{ - m_pszComponentPrefix = pPrefix; - m_iComponentPrefixLen = Q_strlen( pPrefix ); -} - -//----------------------------------------------------------------------------- -// Purpose: called when a kill that passes filter critera occurs. This -// is the default implementation, achievements can override to -// do special handling -//----------------------------------------------------------------------------- -void CBaseAchievement::Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event ) -{ - // extra paranoid check: should only get here if registered as a kill event listener - Assert( GetFlags() & ACH_LISTEN_KILL_EVENTS ); - if ( !( GetFlags() & ACH_LISTEN_KILL_EVENTS ) ) - return; - - // default implementation is just to increase count when filter criteria pass - IncrementCount(); -} - -//----------------------------------------------------------------------------- -// Purpose: called when an event that counts toward an achievement occurs -//----------------------------------------------------------------------------- -void CBaseAchievement::IncrementCount() -{ - if ( !IsAchieved() ) - { - if ( !m_pAchievementMgr->CheckAchievementsEnabled() ) - { - Msg( "Achievements disabled, ignoring achievement progress for %s\n", GetName() ); - return; - } - - // on client, where the count is kept, increment count - m_iCount++; - // if this achievement gets saved w/global state, flag our global state as dirty - if ( GetFlags() & ACH_SAVE_GLOBAL ) - { - m_pAchievementMgr->SetDirty( true ); - } - - if ( cc_achievement_debug.GetInt() ) - { - Msg( "Achievement count increased for %s: %d/%d\n", GetName(), m_iCount, m_iGoal ); - } - - // if this achievement's progress should be stored in Steam, set the steam stat for it - if ( StoreProgressInSteam() && steamapicontext->SteamUserStats() ) - { - // Set the Steam stat with the same name as the achievement. Only cached locally until we upload it. - char pszProgressName[1024]; - Q_snprintf( pszProgressName, 1024, "%s_STAT", GetName() ); - bool bRet = steamapicontext->SteamUserStats()->SetStat( CGameID( engine->GetAppID() ), pszProgressName, m_iCount ); - if ( !bRet ) - { - DevMsg( "ISteamUserStats::GetStat failed to set progress value in Steam for achievement %s\n", pszProgressName ); - } - - // Upload user data to commit the change to Steam so if the client crashes, progress isn't lost. - // Only upload if we haven't uploaded recently, to keep us from spamming Steam with uploads. If we don't - // upload now, it will get uploaded no later than level shutdown. - if ( ( m_pAchievementMgr->GetTimeLastUpload() == 0 ) || ( Plat_FloatTime() - m_pAchievementMgr->GetTimeLastUpload() > 60 * 15 ) ) - { - m_pAchievementMgr->UploadUserData(); - } - } - - // if we've hit goal, award the achievement - if ( m_iGoal > 0 ) - { - if ( m_iCount >= m_iGoal ) - { - AwardAchievement(); - } - else - { - HandleProgressUpdate(); - } - } - } -} - -void CBaseAchievement::HandleProgressUpdate() -{ - // if we've hit the right # of progress steps to show a progress notification, show it - if ( ( m_iProgressMsgIncrement > 0 ) && m_iCount >= m_iProgressMsgMinimum && ( 0 == ( m_iCount % m_iProgressMsgIncrement ) ) ) - { - // which notification is this - int iProgress = m_iCount / m_iProgressMsgIncrement; - // if we haven't already shown this progress step, show it - if ( iProgress > m_iProgressShown ) - { - ShowProgressNotification(); - // remember progress step shown so we don't show it again if the player loads an earlier save game - // and gets past this point again - m_iProgressShown = iProgress; - m_pAchievementMgr->SetDirty( true ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: calculates at how many steps we should show a progress notification -//----------------------------------------------------------------------------- -void CBaseAchievement::CalcProgressMsgIncrement() -{ - // by default, show progress at every 25% - m_iProgressMsgIncrement = m_iGoal / 4; - // if goal is not evenly divisible by 4, try some other values - if ( 0 != ( m_iGoal % 4 ) ) - { - if ( 0 == ( m_iGoal % 3 ) ) - { - // if evenly divisible by 3, use that - m_iProgressMsgIncrement = m_iGoal / 3; - } - else if ( 0 == ( m_iGoal % 5 ) ) - { - // if evenly divisible by 5, use that - m_iProgressMsgIncrement = m_iGoal / 5; - } - // otherwise stick with divided by 4, rounded off - } - - // don't show progress notifications for less than 5 things - if ( m_iProgressMsgIncrement < 5 ) - { - m_iProgressMsgIncrement = 0; - } -} - -//----------------------------------------------------------------------------- -// Purpose: see if we should award an achievement based on what just happened -//----------------------------------------------------------------------------- -void CBaseAchievement::EvaluateNewAchievement() -{ - if ( !IsAchieved() && m_iGoal > 0 && m_iCount >= m_iGoal ) - { - AwardAchievement(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: determine if we should set this achievement to be achieved based -// on other state. Used at init time. -//----------------------------------------------------------------------------- -void CBaseAchievement::EvaluateIsAlreadyAchieved() -{ - if ( !IsAchieved() && m_iGoal > 0 && m_iCount >= m_iGoal ) - { - m_bAchieved = true; - } -} - -//----------------------------------------------------------------------------- -// Purpose: called a map event for this achievement occurs -//----------------------------------------------------------------------------- -void CBaseAchievement::OnMapEvent( const char *pEventName ) -{ - Assert( m_iFlags & ACH_LISTEN_MAP_EVENTS ); - - if ( 0 == Q_stricmp( pEventName, GetName() ) ) - { - IncrementCount(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: called when an achievement is awarded -//----------------------------------------------------------------------------- -void CBaseAchievement::AwardAchievement() -{ - Assert( !IsAchieved() ); - if ( IsAchieved() ) - return; - - m_pAchievementMgr->AwardAchievement( m_iAchievementID ); -} - -//----------------------------------------------------------------------------- -// Purpose: called when a component of a multi-component event is found -//----------------------------------------------------------------------------- -void CBaseAchievement::OnComponentEvent( const char *pchComponentName ) -{ - // find the component name in our list - for ( int i = 0; i < m_iNumComponents; i++ ) - { - if ( 0 == Q_strcmp( pchComponentName, m_pszComponentNames[i] ) ) - { - EnsureComponentBitSetAndEvaluate( i ); - return; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: sets the specified component bit # if it is not already. -// If it does get set, evaluate if this satisfies an achievement -//----------------------------------------------------------------------------- -void CBaseAchievement::EnsureComponentBitSetAndEvaluate( int iBitNumber ) -{ - Assert( iBitNumber < 64 ); // this is bit #, not a bit mask - - if ( IsAchieved() ) - return; - - // calculate which bit this component corresponds to - uint64 iBitMask = ( (uint64) 1 ) << iBitNumber; - - // see if we already have gotten this component - if ( 0 == ( iBitMask & m_iComponentBits ) ) - { - if ( !m_pAchievementMgr->CheckAchievementsEnabled() ) - { - Msg( "Achievements disabled, ignoring achievement component for %s\n", GetName() ); - return; - } - - // new component, set the bit and increment the count - SetComponentBits( m_iComponentBits | iBitMask ); - Assert( m_iCount <= m_iGoal ); - if ( m_iCount == m_iGoal ) - { - // all components found, award the achievement (and save state) - AwardAchievement(); - } - else - { - // save our state at the next good opportunity - m_pAchievementMgr->SetDirty( true ); - - if ( cc_achievement_debug.GetInt() ) - { - Msg( "Component %d for achievement %s found\n", iBitNumber, GetName() ); - } - - ShowProgressNotification(); - } - } - else - { - if ( cc_achievement_debug.GetInt() ) - { - Msg( "Component %d for achievement %s found, but already had that component\n", iBitNumber, GetName() ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: displays achievement progress notification in the HUD -//----------------------------------------------------------------------------- -void CBaseAchievement::ShowProgressNotification() -{ - if ( !ShouldShowProgressNotification() ) - return; - - IGameEvent *event = gameeventmanager->CreateEvent( "achievement_event" ); - if ( event ) - { - event->SetString( "achievement_name", GetName() ); - event->SetInt( "cur_val", m_iCount ); - event->SetInt( "max_val", m_iGoal ); -#ifdef GAME_DLL - gameeventmanager->FireEvent( event ); -#else - gameeventmanager->FireEventClientSide( event ); -#endif - } -} - -//----------------------------------------------------------------------------- -// Purpose: clears dynamic state for this achievement -//----------------------------------------------------------------------------- -void CBaseAchievement::PreRestoreSavedGame() -{ - // if this achievement gets saved with the game, clear its state - if ( m_iFlags & ACH_SAVE_WITH_GAME ) - { - m_iCount = 0; - } -} - -//----------------------------------------------------------------------------- -// Purpose: called after the data in this achievement has been restored from saved game -//----------------------------------------------------------------------------- -void CBaseAchievement::PostRestoreSavedGame() -{ - EvaluateIsAlreadyAchieved(); -} - -//----------------------------------------------------------------------------- -// Purpose: sets component bits for this achievement -//----------------------------------------------------------------------------- -void CBaseAchievement::SetComponentBits( uint64 iComponentBits ) -{ - Assert( m_iFlags & ACH_HAS_COMPONENTS ); - // set the bit field - m_iComponentBits = iComponentBits; - // count how many bits are set and save that as the count - int iNumBitsSet = 0; - while ( iComponentBits > 0 ) - { - if ( iComponentBits & 1 ) - { - iNumBitsSet++; - } - iComponentBits >>= 1; - } - m_iCount = iNumBitsSet; -} - -//----------------------------------------------------------------------------- -// Purpose: returns whether we should save this achievement with a save game -//----------------------------------------------------------------------------- -bool CBaseAchievement::ShouldSaveWithGame() -{ - // save if we should get saved with the game, have a non-zero count, and have not - // been achieved (at which point the achievement state gets saved globally) - return ( ( m_iFlags & ACH_SAVE_WITH_GAME ) > 0 && ( GetCount() > 0 ) && !IsAchieved() ); -} - -//----------------------------------------------------------------------------- -// Purpose: returns whether we should save this achievement to the global file -//----------------------------------------------------------------------------- -bool CBaseAchievement::ShouldSaveGlobal() -{ - // save if we should get saved globally and have a non-zero count, or if we have been achieved - return ( ( ( m_iFlags & ACH_SAVE_GLOBAL ) > 0 && ( GetCount() > 0 ) ) || IsAchieved() || ( m_iProgressShown > 0 ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: returns whether this achievement is active -//----------------------------------------------------------------------------- -bool CBaseAchievement::IsActive() -{ - // we're not active if already achieved - if ( IsAchieved() ) - return false; - - // if there's a map filter and we're not on the specified map, we're not active - if ( ( m_pMapNameFilter ) && ( 0 != Q_strcmp( m_pAchievementMgr->GetMapName(), m_pMapNameFilter ) ) ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -CFailableAchievement::CFailableAchievement() : CBaseAchievement() -{ - m_bFailed = false; - m_bActivated = false; -} - -//----------------------------------------------------------------------------- -// Purpose: returns whether we should save this achievement with a save game -//----------------------------------------------------------------------------- -bool CFailableAchievement::ShouldSaveWithGame() -{ - // save if we should get saved with the game, and are active or have failed - return ( ( ( m_iFlags & ACH_SAVE_WITH_GAME ) > 0 ) && ( m_bActivated || m_bFailed ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: clears dynamic state for this achievement -//----------------------------------------------------------------------------- -void CFailableAchievement::PreRestoreSavedGame() -{ - m_bFailed = false; - m_bActivated = false; - - BaseClass::PreRestoreSavedGame(); -} - - -//----------------------------------------------------------------------------- -// Purpose: called after the data in this achievement has been restored from saved game -//----------------------------------------------------------------------------- -void CFailableAchievement::PostRestoreSavedGame() -{ - // if there is no activation event set for this achievement, it is always active, activate it now - if ( !m_bFailed && !GetActivationEventName()[0] ) - { - m_bActivated = true; - } - - if ( m_bActivated ) - { - Activate(); - } - - BaseClass::PostRestoreSavedGame(); -} - -//----------------------------------------------------------------------------- -// Purpose: called when a map event occurs -//----------------------------------------------------------------------------- -void CFailableAchievement::OnMapEvent( const char *pEventName ) -{ - // if we're not activated and we got the activation event, activate - if ( !m_bActivated && ( 0 == Q_stricmp( pEventName, GetActivationEventName() ) ) ) - { - OnActivationEvent(); - } - // if this is the evaluation event, see if we've failed or not - else if ( m_bActivated && 0 == Q_stricmp( pEventName, GetEvaluationEventName() ) ) - { - OnEvaluationEvent(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Called when this failable achievement is activated -//----------------------------------------------------------------------------- -void CFailableAchievement::Activate() -{ - m_bActivated = true; - ListenForEvents(); - if ( cc_achievement_debug.GetInt() ) - { - Msg( "Failable achievement %s now active\n", GetName() ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Called when this failable achievement should be evaluated -//----------------------------------------------------------------------------- -void CFailableAchievement::OnEvaluationEvent() -{ - if ( !m_bFailed ) - { - // we haven't failed and we reached the evaluation point, we've succeeded - IncrementCount(); - } - - if ( cc_achievement_debug.GetInt() ) - { - Msg( "Failable achievement %s has been evaluated (%s), now inactive\n", GetName(), m_bFailed ? "FAILED" : "AWARDED" ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Sets this achievement to failed -//----------------------------------------------------------------------------- -void CFailableAchievement::SetFailed() -{ - if ( !m_bFailed ) - { - m_bFailed = true; - - if ( cc_achievement_debug.GetInt() ) - { - Msg( "Achievement failed: %s (%s)\n", GetName(), GetName() ); - } - } -} - -//=========================================== - -void CAchievement_AchievedCount::Init() -{ - SetFlags( ACH_SAVE_GLOBAL ); - SetGoal( 1 ); - SetAchievementsRequired( 0, 0, 0 ); -} - -// Count how many achievements have been earned in our range -void CAchievement_AchievedCount::OnSteamUserStatsStored( void ) -{ - int iAllAchievements = m_pAchievementMgr->GetAchievementCount(); - int iAchieved = 0; - - for ( int i=0; iGetAchievementByIndex( i ); - Assert ( pCurAchievement ); - - int iAchievementID = pCurAchievement->GetAchievementID(); - if ( iAchievementID < m_iLowRange || iAchievementID > m_iHighRange ) - continue; - - if ( pCurAchievement->IsAchieved() ) - { - iAchieved++; - } - } - - if ( iAchieved >= m_iNumRequired ) - { - IncrementCount(); - } -} - -void CAchievement_AchievedCount::SetAchievementsRequired( int iNumRequired, int iLowRange, int iHighRange ) -{ - m_iNumRequired = iNumRequired; - m_iLowRange = iLowRange; - m_iHighRange = iHighRange; -} diff --git a/game/shared/baseachievement.h b/game/shared/baseachievement.h deleted file mode 100644 index b0fff33c2..000000000 --- a/game/shared/baseachievement.h +++ /dev/null @@ -1,219 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef BASEACHIEVEMENT_H -#define BASEACHIEVEMENT_H -#ifdef _WIN32 -#pragma once -#endif - -#include "GameEventListener.h" -#include "hl2orange.spa.h" -#include "iachievementmgr.h" - -class CAchievementMgr; - -// -// Base class for achievements -// - -class CBaseAchievement : public CGameEventListener, public IAchievement -{ - DECLARE_CLASS_NOBASE( CBaseAchievement ); -public: - CBaseAchievement(); - virtual void Init() {} - virtual void ListenForEvents() {}; - virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event ); - - int GetAchievementID() { return m_iAchievementID; } - void SetAchievementID( int iAchievementID ) { m_iAchievementID = iAchievementID; } - void SetName( const char *pszName ) { m_pszName = pszName; } - const char *GetName() { return m_pszName; } - void SetFlags( int iFlags ); - int GetFlags() { return m_iFlags; } - void SetGoal( int iGoal ) { m_iGoal = iGoal; } - int GetGoal() { return m_iGoal; } - void SetGameDirFilter( const char *pGameDir ); - bool HasComponents() { return ( m_iFlags & ACH_HAS_COMPONENTS ) > 0; } - void SetPointValue( int iPointValue ) { m_iPointValue = iPointValue; } - int GetPointValue() { return m_iPointValue; } - bool ShouldHideUntilAchieved() { return m_bHideUntilAchieved; } - void SetHideUntilAchieved( bool bHide ) { m_bHideUntilAchieved = bHide; } - void SetStoreProgressInSteam( bool bStoreProgressInSteam ) { m_bStoreProgressInSteam = bStoreProgressInSteam; } - bool StoreProgressInSteam() { return m_bStoreProgressInSteam; } - virtual bool ShouldShowProgressNotification() { return true; } - virtual void OnPlayerStatsUpdate() {} - - virtual bool ShouldSaveWithGame(); - bool ShouldSaveGlobal(); - virtual void PreRestoreSavedGame(); - virtual void PostRestoreSavedGame(); - void SetCount( int iCount ) { m_iCount = iCount; } - int GetCount() { return m_iCount; } - void SetProgressShown( int iProgressShown ) { m_iProgressShown = iProgressShown; } - int GetProgressShown() { return m_iProgressShown; } - virtual bool IsAchieved() { return m_bAchieved; } - virtual bool IsActive(); - void SetAchieved( bool bAchieved ) { m_bAchieved = bAchieved; } - uint64 GetComponentBits() { return m_iComponentBits; } - void SetComponentBits( uint64 iComponentBits ); - void OnComponentEvent( const char *pchComponentName ); - void EnsureComponentBitSetAndEvaluate( int iBitNumber ); - void EvaluateIsAlreadyAchieved(); - virtual void OnMapEvent( const char *pEventName ); - virtual void PrintAdditionalStatus() {} // for debugging, achievements may report additional status in achievement_status concmd - virtual void OnSteamUserStatsStored() {} - -protected: - virtual void FireGameEvent( IGameEvent *event ); - virtual void FireGameEvent_Internal( IGameEvent *event ) {}; - void SetVictimFilter( const char *pClassName ); - void SetAttackerFilter( const char *pClassName ); - void SetInflictorFilter( const char *pClassName ); - void SetInflictorEntityNameFilter( const char *pEntityName ); - void SetMapNameFilter( const char *pMapName ); - void SetComponentPrefix( const char *pPrefix ); - void IncrementCount(); - void EvaluateNewAchievement(); - void AwardAchievement(); - void ShowProgressNotification(); - void HandleProgressUpdate(); - virtual void CalcProgressMsgIncrement(); - - const char *m_pszName; // name of this achievement - int m_iAchievementID; // ID of this achievement - int m_iFlags; // ACH_* flags for this achievement - int m_iGoal; // goal # of steps to award this achievement - int m_iProgressMsgIncrement; // after how many steps show we show a progress notification - int m_iProgressMsgMinimum; // the minimum progress needed before showing progress notification - int m_iPointValue; // # of points this achievement is worth (currently only used for XBox Live) - bool m_bHideUntilAchieved; // should this achievement be hidden until achieved? - bool m_bStoreProgressInSteam; // should incremental progress be stored in Steam. A counter with same name as achievement must be set up in Steam. - const char *m_pInflictorClassNameFilter; // if non-NULL, inflictor class name to filter with - const char *m_pInflictorEntityNameFilter; // if non-NULL, inflictor entity name to filter with - const char *m_pVictimClassNameFilter; // if non-NULL, victim class name to filter with - const char *m_pAttackerClassNameFilter; // if non-NULL, attacker class name to filter with - const char *m_pMapNameFilter; // if non-NULL, map name to filter with - const char *m_pGameDirFilter; // if non-NULL, game dir name to filter with - - const char **m_pszComponentNames; - int m_iNumComponents; - const char *m_pszComponentPrefix; - int m_iComponentPrefixLen; - bool m_bAchieved; // is this achievement achieved - int m_iCount; // # of steps satisfied toward this achievement (only valid if not achieved) - int m_iProgressShown; // # of progress msgs we've shown - uint64 m_iComponentBits; // bitfield of components achieved - CAchievementMgr *m_pAchievementMgr; // our achievement manager - - friend class CAchievementMgr; -public: - DECLARE_DATADESC(); -}; - -class CFailableAchievement : public CBaseAchievement -{ - DECLARE_CLASS( CFailableAchievement, CBaseAchievement ); -public: - CFailableAchievement(); - void SetFailed(); - - virtual bool ShouldSaveWithGame(); - virtual void PreRestoreSavedGame(); - virtual void PostRestoreSavedGame(); - virtual bool IsAchieved() { return !m_bFailed && BaseClass::IsAchieved(); } - virtual bool IsActive() { return m_bActivated && !m_bFailed && BaseClass::IsActive(); } - bool IsFailed() { return m_bFailed; } - - virtual void OnMapEvent( const char *pEventName ); - virtual void OnActivationEvent() { Activate(); } - virtual void OnEvaluationEvent(); - virtual const char *GetActivationEventName() =0; - virtual const char *GetEvaluationEventName() =0; - -protected: - void Activate(); - - bool m_bActivated; // are we activated? (If there is a map event that turns us on, has that happened) - bool m_bFailed; // has this achievement failed - -public: - DECLARE_DATADESC(); -}; - -class CMapAchievement : public CBaseAchievement -{ - virtual void Init() - { - SetFlags( ACH_LISTEN_MAP_EVENTS | ACH_SAVE_GLOBAL ); - SetGoal( 1 ); - } -}; - - -//---------------------------------------------------------------------------------------------------------------- -class CAchievement_AchievedCount : public CBaseAchievement -{ -public: - void Init(); - virtual void OnSteamUserStatsStored( void ); - -protected: - void SetAchievementsRequired( int iNumRequired, int iLowRange, int iHighRange ); - -private: - int m_iNumRequired; - int m_iLowRange; - int m_iHighRange; -}; - -// -// Helper class for achievement creation -// - -typedef CBaseAchievement* (*achievementCreateFunc) (void); -class CBaseAchievementHelper -{ -public: - CBaseAchievementHelper( achievementCreateFunc createFunc ) - { - m_pfnCreate = createFunc; - m_pNext = s_pFirst; - s_pFirst = this; - } - achievementCreateFunc m_pfnCreate; - CBaseAchievementHelper *m_pNext; - static CBaseAchievementHelper *s_pFirst; -}; - -#define DECLARE_ACHIEVEMENT_( className, achievementID, achievementName, gameDirFilter, iPointValue, bHidden ) \ -static CBaseAchievement *Create_##className( void ) \ -{ \ - CBaseAchievement *pAchievement = new className( ); \ - pAchievement->SetAchievementID( achievementID ); \ - pAchievement->SetName( achievementName ); \ - pAchievement->SetPointValue( iPointValue ); \ - pAchievement->SetHideUntilAchieved( bHidden ); \ - if ( gameDirFilter ) pAchievement->SetGameDirFilter( gameDirFilter ); \ - return pAchievement; \ -}; \ -static CBaseAchievementHelper g_##className##_Helper( Create_##className ); - -#define DECLARE_ACHIEVEMENT( className, achievementID, achievementName, iPointValue ) \ - DECLARE_ACHIEVEMENT_( className, achievementID, achievementName, false, iPointValue, false ) - -#define DECLARE_MAP_EVENT_ACHIEVEMENT_( achievementID, achievementName, gameDirFilter, iPointValue, bHidden ) \ -class CAchievement##achievementID : public CMapAchievement {}; \ -DECLARE_ACHIEVEMENT_( CAchievement##achievementID, achievementID, achievementName, gameDirFilter, iPointValue, bHidden ) \ - -#define DECLARE_MAP_EVENT_ACHIEVEMENT( achievementID, achievementName, iPointValue ) \ - DECLARE_MAP_EVENT_ACHIEVEMENT_( achievementID, achievementName, false, iPointValue, false ) - -#define DECLARE_MAP_EVENT_ACHIEVEMENT_HIDDEN( achievementID, achievementName, iPointValue ) \ - DECLARE_MAP_EVENT_ACHIEVEMENT_( achievementID, achievementName, false, iPointValue, true ) - -#endif // BASEACHIEVEMENT_H diff --git a/game/shared/basecombatcharacter_shared.cpp b/game/shared/basecombatcharacter_shared.cpp deleted file mode 100644 index 30391f60d..000000000 --- a/game/shared/basecombatcharacter_shared.cpp +++ /dev/null @@ -1,210 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "ammodef.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Switches to the best weapon that is also better than the given weapon. -// Input : pCurrent - The current weapon used by the player. -// Output : Returns true if the weapon was switched, false if there was no better -// weapon to switch to. -//----------------------------------------------------------------------------- -bool CBaseCombatCharacter::SwitchToNextBestWeapon(CBaseCombatWeapon *pCurrent) -{ - CBaseCombatWeapon *pNewWeapon = g_pGameRules->GetNextBestWeapon(this, pCurrent); - - if ( ( pNewWeapon != NULL ) && ( pNewWeapon != pCurrent ) ) - { - return Weapon_Switch( pNewWeapon ); - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Switches to the given weapon (providing it has ammo) -// Input : -// Output : true is switch suceeded -//----------------------------------------------------------------------------- -bool CBaseCombatCharacter::Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmodelindex /*=0*/ ) -{ - if ( pWeapon == NULL ) - return false; - - // Already have it out? - if ( m_hActiveWeapon.Get() == pWeapon ) - { - if ( !m_hActiveWeapon->IsWeaponVisible() ) - return m_hActiveWeapon->Deploy( ); - return false; - } - - if (!Weapon_CanSwitchTo(pWeapon)) - { - return false; - } - - if ( m_hActiveWeapon ) - { - if ( !m_hActiveWeapon->Holster( pWeapon ) ) - return false; - } - - m_hActiveWeapon = pWeapon; - return pWeapon->Deploy( ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns whether or not we can switch to the given weapon. -// Input : pWeapon - -//----------------------------------------------------------------------------- -bool CBaseCombatCharacter::Weapon_CanSwitchTo( CBaseCombatWeapon *pWeapon ) -{ - if (IsPlayer()) - { - CBasePlayer *pPlayer = (CBasePlayer *)this; -#if !defined( CLIENT_DLL ) - IServerVehicle *pVehicle = pPlayer->GetVehicle(); -#else - IClientVehicle *pVehicle = pPlayer->GetVehicle(); -#endif - if (pVehicle && !pPlayer->UsingStandardWeaponsInVehicle()) - return false; - } - - if ( !pWeapon->HasAnyAmmo() && !GetAmmoCount( pWeapon->m_iPrimaryAmmoType ) ) - return false; - - if ( !pWeapon->CanDeploy() ) - return false; - - if ( m_hActiveWeapon ) - { - if ( !m_hActiveWeapon->CanHolster() ) - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CBaseCombatWeapon -//----------------------------------------------------------------------------- -CBaseCombatWeapon *CBaseCombatCharacter::GetActiveWeapon() const -{ - return m_hActiveWeapon; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iCount - -// iAmmoIndex - -//----------------------------------------------------------------------------- -void CBaseCombatCharacter::RemoveAmmo( int iCount, int iAmmoIndex ) -{ - if (iCount <= 0) - return; - - // Infinite ammo? - if ( GetAmmoDef()->MaxCarry( iAmmoIndex ) == INFINITE_AMMO ) - return; - - // Ammo pickup sound - m_iAmmo.Set( iAmmoIndex, MAX( m_iAmmo[iAmmoIndex] - iCount, 0 ) ); -} - -void CBaseCombatCharacter::RemoveAmmo( int iCount, const char *szName ) -{ - RemoveAmmo( iCount, GetAmmoDef()->Index(szName) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseCombatCharacter::RemoveAllAmmo( ) -{ - for ( int i = 0; i < MAX_AMMO_SLOTS; i++ ) - { - m_iAmmo.Set( i, 0 ); - } -} - -//----------------------------------------------------------------------------- -// FIXME: This is a sort of hack back-door only used by physgun! -//----------------------------------------------------------------------------- -void CBaseCombatCharacter::SetAmmoCount( int iCount, int iAmmoIndex ) -{ - // NOTE: No sound, no max check! Seems pretty bogus to me! - m_iAmmo.Set( iAmmoIndex, iCount ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the amount of ammunition of a particular type owned -// owned by the character -// Input : Ammo Index -// Output : The amount of ammo -//----------------------------------------------------------------------------- -int CBaseCombatCharacter::GetAmmoCount( int iAmmoIndex ) const -{ - if ( iAmmoIndex == -1 ) - return 0; - - // Infinite ammo? - if ( GetAmmoDef()->MaxCarry( iAmmoIndex ) == INFINITE_AMMO ) - return 999; - - return m_iAmmo[ iAmmoIndex ]; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the amount of ammunition of the specified type the character's carrying -//----------------------------------------------------------------------------- -int CBaseCombatCharacter::GetAmmoCount( char *szName ) const -{ - return GetAmmoCount( GetAmmoDef()->Index(szName) ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns weapon if already owns a weapon of this class -//----------------------------------------------------------------------------- -CBaseCombatWeapon* CBaseCombatCharacter::Weapon_OwnsThisType( const char *pszWeapon, int iSubType ) const -{ - // Check for duplicates - for (int i=0;iGetSubType() == iSubType ) - return m_hMyWeapons[i]; - } - } - return NULL; -} - - -int CBaseCombatCharacter::BloodColor() -{ - return m_bloodColor; -} - - -//----------------------------------------------------------------------------- -// Blood color (see BLOOD_COLOR_* macros in baseentity.h) -//----------------------------------------------------------------------------- -void CBaseCombatCharacter::SetBloodColor( int nBloodColor ) -{ - m_bloodColor = nBloodColor; -} - - - diff --git a/game/shared/basecombatweapon_shared.cpp b/game/shared/basecombatweapon_shared.cpp deleted file mode 100644 index e8075ba8a..000000000 --- a/game/shared/basecombatweapon_shared.cpp +++ /dev/null @@ -1,2480 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "in_buttons.h" -#include "engine/IEngineSound.h" -#include "ammodef.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" -#include "physics_saverestore.h" -#include "datacache/imdlcache.h" - - -#if !defined( CLIENT_DLL ) - -// Game DLL Headers -#include "soundent.h" -#include "eventqueue.h" -#include "fmtstr.h" -#include "gameweaponmanager.h" - -#ifdef HL2MP - #include "hl2mp_gamerules.h" -#endif - -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// The minimum time a hud hint for a weapon should be on screen. If we switch away before -// this, then teh hud hint counter will be deremented so the hint will be shown again, as -// if it had never been seen. The total display time for a hud hint is specified in client -// script HudAnimations.txt (which I can't read here). -#define MIN_HUDHINT_DISPLAY_TIME 7.0f - -#define HIDEWEAPON_THINK_CONTEXT "BaseCombatWeapon_HideThink" - -extern bool UTIL_ItemCanBeTouchedByPlayer( CBaseEntity *pItem, CBasePlayer *pPlayer ); - -CBaseCombatWeapon::CBaseCombatWeapon() -{ - // Constructor must call this - // CONSTRUCT_PREDICTABLE( CBaseCombatWeapon ); - - // Some default values. There should be set in the particular weapon classes - m_fMinRange1 = 65; - m_fMinRange2 = 65; - m_fMaxRange1 = 1024; - m_fMaxRange2 = 1024; - - m_bReloadsSingly = false; - - // Defaults to zero - m_nViewModelIndex = 0; - -#if defined( CLIENT_DLL ) - m_iState = m_iOldState = WEAPON_NOT_CARRIED; - m_iClip1 = -1; - m_iClip2 = -1; - m_iPrimaryAmmoType = -1; - m_iSecondaryAmmoType = -1; -#endif - -#if !defined( CLIENT_DLL ) - m_pConstraint = NULL; - OnBaseCombatWeaponCreated( this ); -#endif - - m_hWeaponFileInfo = GetInvalidWeaponInfoHandle(); - -#if defined( TF_DLL ) - UseClientSideAnimation(); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Destructor -//----------------------------------------------------------------------------- -CBaseCombatWeapon::~CBaseCombatWeapon( void ) -{ -#if !defined( CLIENT_DLL ) - //Remove our constraint, if we have one - if ( m_pConstraint != NULL ) - { - physenv->DestroyConstraint( m_pConstraint ); - m_pConstraint = NULL; - } - OnBaseCombatWeaponDestroyed( this ); -#endif -} - -void CBaseCombatWeapon::Activate( void ) -{ - BaseClass::Activate(); - -#ifndef CLIENT_DLL - if ( GetOwnerEntity() ) - return; - - if ( g_pGameRules->IsAllowedToSpawn( this ) == false ) - { - UTIL_Remove( this ); - return; - } -#endif - -} -void CBaseCombatWeapon::GiveDefaultAmmo( void ) -{ - // If I use clips, set my clips to the default - if ( UsesClipsForAmmo1() ) - { - m_iClip1 = GetDefaultClip1(); - } - else - { - SetPrimaryAmmoCount( GetDefaultClip1() ); - m_iClip1 = WEAPON_NOCLIP; - } - if ( UsesClipsForAmmo2() ) - { - m_iClip2 = GetDefaultClip2(); - } - else - { - SetSecondaryAmmoCount( GetDefaultClip2() ); - m_iClip2 = WEAPON_NOCLIP; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Set mode to world model and start falling to the ground -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::Spawn( void ) -{ - Precache(); - - SetSolid( SOLID_BBOX ); - m_flNextEmptySoundTime = 0.0f; - - // Weapons won't show up in trace calls if they are being carried... - RemoveEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID ); - - m_iState = WEAPON_NOT_CARRIED; - // Assume - m_nViewModelIndex = 0; - - GiveDefaultAmmo(); - - SetModel( GetWorldModel() ); - -#if !defined( CLIENT_DLL ) - if( IsX360() ) - { - AddEffects( EF_ITEM_BLINK ); - } - - FallInit(); - SetCollisionGroup( COLLISION_GROUP_WEAPON ); - m_takedamage = DAMAGE_EVENTS_ONLY; - - SetBlocksLOS( false ); - - // Default to non-removeable, because we don't want the - // game_weapon_manager entity to remove weapons that have - // been hand-placed by level designers. We only want to remove - // weapons that have been dropped by NPC's. - SetRemoveable( false ); -#endif - - // Bloat the box for player pickup - CollisionProp()->UseTriggerBounds( true, 36 ); - - // Use more efficient bbox culling on the client. Otherwise, it'll setup bones for most - // characters even when they're not in the frustum. - AddEffects( EF_BONEMERGE_FASTCULL ); - - m_iReloadHudHintCount = 0; - m_iAltFireHudHintCount = 0; - m_flHudHintMinDisplayTime = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: get this game's encryption key for decoding weapon kv files -// Output : virtual const unsigned char -//----------------------------------------------------------------------------- -const unsigned char *CBaseCombatWeapon::GetEncryptionKey( void ) -{ - return g_pGameRules->GetEncryptionKey(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::Precache( void ) -{ -#if defined( CLIENT_DLL ) - Assert( Q_strlen( GetClassname() ) > 0 ); - // Msg( "Client got %s\n", GetClassname() ); -#endif - m_iPrimaryAmmoType = m_iSecondaryAmmoType = -1; - - // Add this weapon to the weapon registry, and get our index into it - // Get weapon data from script file - if ( ReadWeaponDataFromFileForSlot( filesystem, GetClassname(), &m_hWeaponFileInfo, GetEncryptionKey() ) ) - { - // Get the ammo indexes for the ammo's specified in the data file - if ( GetWpnData().szAmmo1[0] ) - { - m_iPrimaryAmmoType = GetAmmoDef()->Index( GetWpnData().szAmmo1 ); - if (m_iPrimaryAmmoType == -1) - { - Msg("ERROR: Weapon (%s) using undefined primary ammo type (%s)\n",GetClassname(), GetWpnData().szAmmo1); - } - } - if ( GetWpnData().szAmmo2[0] ) - { - m_iSecondaryAmmoType = GetAmmoDef()->Index( GetWpnData().szAmmo2 ); - if (m_iSecondaryAmmoType == -1) - { - Msg("ERROR: Weapon (%s) using undefined secondary ammo type (%s)\n",GetClassname(),GetWpnData().szAmmo2); - } - - } -#if defined( CLIENT_DLL ) - gWR.LoadWeaponSprites( GetWeaponFileInfoHandle() ); -#endif - // Precache models (preload to avoid hitch) - m_iViewModelIndex = 0; - m_iWorldModelIndex = 0; - if ( GetViewModel() && GetViewModel()[0] ) - { - m_iViewModelIndex = CBaseEntity::PrecacheModel( GetViewModel() ); - } - if ( GetWorldModel() && GetWorldModel()[0] ) - { - m_iWorldModelIndex = CBaseEntity::PrecacheModel( GetWorldModel() ); - } - - // Precache sounds, too - for ( int i = 0; i < NUM_SHOOT_SOUND_TYPES; ++i ) - { - const char *shootsound = GetShootSound( i ); - if ( shootsound && shootsound[0] ) - { - CBaseEntity::PrecacheScriptSound( shootsound ); - } - } - } - else - { - // Couldn't read data file, remove myself - Warning( "Error reading weapon data file for: %s\n", GetClassname() ); - // Remove( ); //don't remove, this gets released soon! - } -} - -//----------------------------------------------------------------------------- -// Purpose: Get my data in the file weapon info array -//----------------------------------------------------------------------------- -const FileWeaponInfo_t &CBaseCombatWeapon::GetWpnData( void ) const -{ - return *GetFileWeaponInfoFromHandle( m_hWeaponFileInfo ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const char *CBaseCombatWeapon::GetViewModel( int /*viewmodelindex = 0 -- this is ignored in the base class here*/ ) const -{ - return GetWpnData().szViewModel; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const char *CBaseCombatWeapon::GetWorldModel( void ) const -{ - return GetWpnData().szWorldModel; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const char *CBaseCombatWeapon::GetAnimPrefix( void ) const -{ - return GetWpnData().szAnimationPrefix; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : char const -//----------------------------------------------------------------------------- -const char *CBaseCombatWeapon::GetPrintName( void ) const -{ - return GetWpnData().szPrintName; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBaseCombatWeapon::GetMaxClip1( void ) const -{ - return GetWpnData().iMaxClip1; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBaseCombatWeapon::GetMaxClip2( void ) const -{ - return GetWpnData().iMaxClip2; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBaseCombatWeapon::GetDefaultClip1( void ) const -{ - return GetWpnData().iDefaultClip1; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBaseCombatWeapon::GetDefaultClip2( void ) const -{ - return GetWpnData().iDefaultClip2; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::UsesClipsForAmmo1( void ) const -{ - return ( GetMaxClip1() != WEAPON_NOCLIP ); -} - -bool CBaseCombatWeapon::IsMeleeWeapon() const -{ - return GetWpnData().m_bMeleeWeapon; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::UsesClipsForAmmo2( void ) const -{ - return ( GetMaxClip2() != WEAPON_NOCLIP ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBaseCombatWeapon::GetWeight( void ) const -{ - return GetWpnData().iWeight; -} - -//----------------------------------------------------------------------------- -// Purpose: Whether this weapon can be autoswitched to when the player runs out -// of ammo in their current weapon or they pick this weapon up. -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::AllowsAutoSwitchTo( void ) const -{ - return GetWpnData().bAutoSwitchTo; -} - -//----------------------------------------------------------------------------- -// Purpose: Whether this weapon can be autoswitched away from when the player -// runs out of ammo in this weapon or picks up another weapon or ammo. -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::AllowsAutoSwitchFrom( void ) const -{ - return GetWpnData().bAutoSwitchFrom; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBaseCombatWeapon::GetWeaponFlags( void ) const -{ - return GetWpnData().iFlags; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBaseCombatWeapon::GetSlot( void ) const -{ - return GetWpnData().iSlot; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBaseCombatWeapon::GetPosition( void ) const -{ - return GetWpnData().iPosition; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const char *CBaseCombatWeapon::GetName( void ) const -{ - return GetWpnData().szClassName; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CHudTexture const *CBaseCombatWeapon::GetSpriteActive( void ) const -{ - return GetWpnData().iconActive; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CHudTexture const *CBaseCombatWeapon::GetSpriteInactive( void ) const -{ - return GetWpnData().iconInactive; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CHudTexture const *CBaseCombatWeapon::GetSpriteAmmo( void ) const -{ - return GetWpnData().iconAmmo; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CHudTexture const *CBaseCombatWeapon::GetSpriteAmmo2( void ) const -{ - return GetWpnData().iconAmmo2; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CHudTexture const *CBaseCombatWeapon::GetSpriteCrosshair( void ) const -{ - return GetWpnData().iconCrosshair; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CHudTexture const *CBaseCombatWeapon::GetSpriteAutoaim( void ) const -{ - return GetWpnData().iconAutoaim; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CHudTexture const *CBaseCombatWeapon::GetSpriteZoomedCrosshair( void ) const -{ - return GetWpnData().iconZoomedCrosshair; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CHudTexture const *CBaseCombatWeapon::GetSpriteZoomedAutoaim( void ) const -{ - return GetWpnData().iconZoomedAutoaim; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const char *CBaseCombatWeapon::GetShootSound( int iIndex ) const -{ - return GetWpnData().aShootSounds[ iIndex ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBaseCombatWeapon::GetRumbleEffect() const -{ - return GetWpnData().iRumbleEffect; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseCombatCharacter *CBaseCombatWeapon::GetOwner() const -{ - return ToBaseCombatCharacter( m_hOwner.Get() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : BaseCombatCharacter - -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::SetOwner( CBaseCombatCharacter *owner ) -{ - m_hOwner = owner; - -#ifndef CLIENT_DLL - DispatchUpdateTransmitState(); -#else - UpdateVisibility(); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Return false if this weapon won't let the player switch away from it -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::IsAllowedToSwitch( void ) -{ - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if this weapon can be selected via the weapon selection -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::CanBeSelected( void ) -{ - if ( !VisibleInWeaponSelection() ) - return false; - - return HasAmmo(); -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if this weapon has some ammo -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::HasAmmo( void ) -{ - // Weapons with no ammo types can always be selected - if ( m_iPrimaryAmmoType == -1 && m_iSecondaryAmmoType == -1 ) - return true; - if ( GetWeaponFlags() & ITEM_FLAG_SELECTONEMPTY ) - return true; - - CBasePlayer *player = ToBasePlayer( GetOwner() ); - if ( !player ) - return false; - return ( m_iClip1 > 0 || player->GetAmmoCount( m_iPrimaryAmmoType ) || m_iClip2 > 0 || player->GetAmmoCount( m_iSecondaryAmmoType ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if this weapon should be seen, and hence be selectable, in the weapon selection -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::VisibleInWeaponSelection( void ) -{ - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::HasWeaponIdleTimeElapsed( void ) -{ - if ( gpGlobals->curtime > m_flTimeWeaponIdle ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : time - -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::SetWeaponIdleTime( float time ) -{ - m_flTimeWeaponIdle = time; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CBaseCombatWeapon::GetWeaponIdleTime( void ) -{ - return m_flTimeWeaponIdle; -} - -//----------------------------------------------------------------------------- -// Purpose: Drop/throw the weapon with the given velocity. -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::Drop( const Vector &vecVelocity ) -{ -#if !defined( CLIENT_DLL ) - - // Once somebody drops a gun, it's fair game for removal when/if - // a game_weapon_manager does a cleanup on surplus weapons in the - // world. - SetRemoveable( true ); - WeaponManager_AmmoMod( this ); - - //If it was dropped then there's no need to respawn it. - AddSpawnFlags( SF_NORESPAWN ); - - StopAnimation(); - StopFollowingEntity( ); - SetMoveType( MOVETYPE_FLYGRAVITY ); - // clear follow stuff, setup for collision - SetGravity(1.0); - m_iState = WEAPON_NOT_CARRIED; - RemoveEffects( EF_NODRAW ); - FallInit(); - SetGroundEntity( NULL ); - SetThink( &CBaseCombatWeapon::SetPickupTouch ); - SetTouch(NULL); - - if( hl2_episodic.GetBool() ) - { - RemoveSpawnFlags( SF_WEAPON_NO_PLAYER_PICKUP ); - } - - IPhysicsObject *pObj = VPhysicsGetObject(); - if ( pObj != NULL ) - { - AngularImpulse angImp( 200, 200, 200 ); - pObj->AddVelocity( &vecVelocity, &angImp ); - } - else - { - SetAbsVelocity( vecVelocity ); - } - - CBaseEntity *pOwner = GetOwnerEntity(); - - SetNextThink( gpGlobals->curtime + 1.0f ); - SetOwnerEntity( NULL ); - SetOwner( NULL ); - - // If we're not allowing to spawn due to the gamerules, - // remove myself when I'm dropped by an NPC. - if ( pOwner && pOwner->IsNPC() ) - { - if ( g_pGameRules->IsAllowedToSpawn( this ) == false ) - { - UTIL_Remove( this ); - return; - } - } -#endif -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPicker - -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::OnPickedUp( CBaseCombatCharacter *pNewOwner ) -{ -#if !defined( CLIENT_DLL ) - RemoveEffects( EF_ITEM_BLINK ); - - if( pNewOwner->IsPlayer() ) - { - m_OnPlayerPickup.FireOutput(pNewOwner, this); - - // Play the pickup sound for 1st-person observers - CRecipientFilter filter; - for ( int i=1; i <= gpGlobals->maxClients; ++i ) - { - CBasePlayer *player = UTIL_PlayerByIndex(i); - if ( player && !player->IsAlive() && player->GetObserverMode() == OBS_MODE_IN_EYE ) - { - filter.AddRecipient( player ); - } - } - if ( filter.GetRecipientCount() ) - { - CBaseEntity::EmitSound( filter, pNewOwner->entindex(), "Player.PickupWeapon" ); - } - - // Robin: We don't want to delete weapons the player has picked up, so - // clear the name of the weapon. This prevents wildcards that are meant - // to find NPCs finding weapons dropped by the NPCs as well. - SetName( NULL_STRING ); - } - else - { - m_OnNPCPickup.FireOutput(pNewOwner, this); - } - -#ifdef HL2MP - HL2MPRules()->RemoveLevelDesignerPlacedObject( this ); -#endif - - // Someone picked me up, so make it so that I can't be removed. - SetRemoveable( false ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &vecTracerSrc - -// &tr - -// iTracerType - -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ) -{ - CBaseEntity *pOwner = GetOwner(); - - if ( pOwner == NULL ) - { - BaseClass::MakeTracer( vecTracerSrc, tr, iTracerType ); - return; - } - - const char *pszTracerName = GetTracerType(); - - Vector vNewSrc = vecTracerSrc; - int iEntIndex = pOwner->entindex(); - - if ( g_pGameRules->IsMultiplayer() ) - { - iEntIndex = entindex(); - } - - int iAttachment = GetTracerAttachment(); - - switch ( iTracerType ) - { - case TRACER_LINE: - UTIL_Tracer( vNewSrc, tr.endpos, iEntIndex, iAttachment, 0.0f, true, pszTracerName ); - break; - - case TRACER_LINE_AND_WHIZ: - UTIL_Tracer( vNewSrc, tr.endpos, iEntIndex, iAttachment, 0.0f, true, pszTracerName ); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Default Touch function for player picking up a weapon (not AI) -// Input : pOther - the entity that touched me -// Output : -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::DefaultTouch( CBaseEntity *pOther ) -{ -#if !defined( CLIENT_DLL ) - // Can't pick up dissolving weapons - if ( IsDissolving() ) - return; - - // if it's not a player, ignore - CBasePlayer *pPlayer = ToBasePlayer(pOther); - if ( !pPlayer ) - return; - - if( UTIL_ItemCanBeTouchedByPlayer(this, pPlayer) ) - { - // This makes sure the player could potentially take the object - // before firing the cache interaction output. That doesn't mean - // the player WILL end up taking the object, but cache interactions - // are fired as soon as you prove you have found the object, not - // when you finally acquire it. - m_OnCacheInteraction.FireOutput( pOther, this ); - } - - if( HasSpawnFlags(SF_WEAPON_NO_PLAYER_PICKUP) ) - return; - - if (pPlayer->BumpWeapon(this)) - { - OnPickedUp( pPlayer ); - } -#endif -} - -//--------------------------------------------------------- -// It's OK for base classes to override this completely -// without calling up. (sjb) -//--------------------------------------------------------- -bool CBaseCombatWeapon::ShouldDisplayAltFireHUDHint() -{ - if( m_iAltFireHudHintCount >= WEAPON_RELOAD_HUD_HINT_COUNT ) - return false; - - if( UsesSecondaryAmmo() && HasSecondaryAmmo() ) - { - return true; - } - - if( !UsesSecondaryAmmo() && HasPrimaryAmmo() ) - { - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::DisplayAltFireHudHint() -{ -#if !defined( CLIENT_DLL ) - CFmtStr hint; - hint.sprintf( "#valve_hint_alt_%s", GetClassname() ); - UTIL_HudHintText( GetOwner(), hint.Access() ); - m_iAltFireHudHintCount++; - m_bAltFireHudHintDisplayed = true; - m_flHudHintMinDisplayTime = gpGlobals->curtime + MIN_HUDHINT_DISPLAY_TIME; -#endif//CLIENT_DLL -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::RescindAltFireHudHint() -{ -#if !defined( CLIENT_DLL ) - Assert(m_bAltFireHudHintDisplayed); - - UTIL_HudHintText( GetOwner(), "" ); - --m_iAltFireHudHintCount; - m_bAltFireHudHintDisplayed = false; -#endif//CLIENT_DLL -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::ShouldDisplayReloadHUDHint() -{ - if( m_iReloadHudHintCount >= WEAPON_RELOAD_HUD_HINT_COUNT ) - return false; - - CBaseCombatCharacter *pOwner = GetOwner(); - - if( pOwner != NULL && pOwner->IsPlayer() && UsesClipsForAmmo1() && m_iClip1 < (GetMaxClip1() / 2) ) - { - // I'm owned by a player, I use clips, I have less then half a clip loaded. Now, does the player have more ammo? - if ( pOwner ) - { - if ( pOwner->GetAmmoCount( m_iPrimaryAmmoType ) > 0 ) - return true; - } - } - - return false; -} -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::DisplayReloadHudHint() -{ -#if !defined( CLIENT_DLL ) - UTIL_HudHintText( GetOwner(), "valve_hint_reload" ); - m_iReloadHudHintCount++; - m_bReloadHudHintDisplayed = true; - m_flHudHintMinDisplayTime = gpGlobals->curtime + MIN_HUDHINT_DISPLAY_TIME; -#endif//CLIENT_DLL -} -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::RescindReloadHudHint() -{ -#if !defined( CLIENT_DLL ) - Assert(m_bReloadHudHintDisplayed); - - UTIL_HudHintText( GetOwner(), "" ); - --m_iReloadHudHintCount; - m_bReloadHudHintDisplayed = false; -#endif//CLIENT_DLL -} - - -void CBaseCombatWeapon::SetPickupTouch( void ) -{ -#if !defined( CLIENT_DLL ) - SetTouch(&CBaseCombatWeapon::DefaultTouch); - - if ( gpGlobals->maxClients > 1 ) - { - if ( GetSpawnFlags() & SF_NORESPAWN ) - { - SetThink( &CBaseEntity::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 30.0f ); - } - } - -#endif -} - - -//----------------------------------------------------------------------------- -// Purpose: Become a child of the owner (MOVETYPE_FOLLOW) -// disables collisions, touch functions, thinking -// Input : *pOwner - new owner/operator -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::Equip( CBaseCombatCharacter *pOwner ) -{ - // Attach the weapon to an owner - SetAbsVelocity( vec3_origin ); - RemoveSolidFlags( FSOLID_TRIGGER ); - FollowEntity( pOwner ); - SetOwner( pOwner ); - SetOwnerEntity( pOwner ); - - // Break any constraint I might have to the world. - RemoveEffects( EF_ITEM_BLINK ); - -#if !defined( CLIENT_DLL ) - if ( m_pConstraint != NULL ) - { - RemoveSpawnFlags( SF_WEAPON_START_CONSTRAINED ); - physenv->DestroyConstraint( m_pConstraint ); - m_pConstraint = NULL; - } -#endif - - - m_flNextPrimaryAttack = gpGlobals->curtime; - m_flNextSecondaryAttack = gpGlobals->curtime; - SetTouch( NULL ); - SetThink( NULL ); -#if !defined( CLIENT_DLL ) - VPhysicsDestroyObject(); -#endif - - if ( pOwner->IsPlayer() ) - { - SetModel( GetViewModel() ); - } - else - { - // Make the weapon ready as soon as any NPC picks it up. - m_flNextPrimaryAttack = gpGlobals->curtime; - m_flNextSecondaryAttack = gpGlobals->curtime; - SetModel( GetWorldModel() ); - } -} - -void CBaseCombatWeapon::SetActivity( Activity act, float duration ) -{ - //Adrian: Oh man... -#if !defined( CLIENT_DLL ) && (defined( HL2MP ) || defined( PORTAL )) - SetModel( GetWorldModel() ); -#endif - - int sequence = SelectWeightedSequence( act ); - - // FORCE IDLE on sequences we don't have (which should be many) - if ( sequence == ACTIVITY_NOT_AVAILABLE ) - sequence = SelectWeightedSequence( ACT_VM_IDLE ); - - //Adrian: Oh man again... -#if !defined( CLIENT_DLL ) && (defined( HL2MP ) || defined( PORTAL )) - SetModel( GetViewModel() ); -#endif - - if ( sequence != ACTIVITY_NOT_AVAILABLE ) - { - SetSequence( sequence ); - SetActivity( act ); - SetCycle( 0 ); - ResetSequenceInfo( ); - - if ( duration > 0 ) - { - // FIXME: does this even make sense in non-shoot animations? - m_flPlaybackRate = SequenceDuration( sequence ) / duration; - m_flPlaybackRate = fpmin( m_flPlaybackRate, 12.0); // FIXME; magic number!, network encoding range - } - else - { - m_flPlaybackRate = 1.0; - } - } -} - -//==================================================================================== -// WEAPON CLIENT HANDLING -//==================================================================================== -int CBaseCombatWeapon::UpdateClientData( CBasePlayer *pPlayer ) -{ - int iNewState = WEAPON_IS_CARRIED_BY_PLAYER; - - if ( pPlayer->GetActiveWeapon() == this ) - { - if ( pPlayer->m_fOnTarget ) - { - iNewState = WEAPON_IS_ONTARGET; - } - else - { - iNewState = WEAPON_IS_ACTIVE; - } - } - else - { - iNewState = WEAPON_IS_CARRIED_BY_PLAYER; - } - - if ( m_iState != iNewState ) - { - m_iState = iNewState; - } - return 1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::SetViewModelIndex( int index ) -{ - Assert( index >= 0 && index < MAX_VIEWMODELS ); - m_nViewModelIndex = index; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iActivity - -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::SendViewModelAnim( int nSequence ) -{ -#if defined( CLIENT_DLL ) - if ( !IsPredicted() ) - return; -#endif - - if ( nSequence < 0 ) - return; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex ); - - if ( vm == NULL ) - return; - - SetViewModel(); - Assert( vm->ViewModelIndex() == m_nViewModelIndex ); - vm->SendViewModelMatchingSequence( nSequence ); -} - -float CBaseCombatWeapon::GetViewModelSequenceDuration() -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( pOwner == NULL ) - { - Assert( false ); - return 0; - } - - CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex ); - if ( vm == NULL ) - { - Assert( false ); - return 0; - } - - SetViewModel(); - Assert( vm->ViewModelIndex() == m_nViewModelIndex ); - return vm->SequenceDuration(); -} - -bool CBaseCombatWeapon::IsViewModelSequenceFinished( void ) -{ - // These are not valid activities and always complete immediately - if ( GetActivity() == ACT_RESET || GetActivity() == ACT_INVALID ) - return true; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( pOwner == NULL ) - { - Assert( false ); - return false; - } - - CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex ); - if ( vm == NULL ) - { - Assert( false ); - return false; - } - - return vm->IsSequenceFinished(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::SetViewModel() -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( pOwner == NULL ) - return; - CBaseViewModel *vm = pOwner->GetViewModel( m_nViewModelIndex ); - if ( vm == NULL ) - return; - Assert( vm->ViewModelIndex() == m_nViewModelIndex ); - vm->SetWeaponModel( GetViewModel( m_nViewModelIndex ), this ); -} - -//----------------------------------------------------------------------------- -// Purpose: Set the desired activity for the weapon and its viewmodel counterpart -// Input : iActivity - activity to play -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::SendWeaponAnim( int iActivity ) -{ -#ifdef USES_PERSISTENT_ITEMS - iActivity = TranslateViewmodelHandActivity( (Activity)iActivity ); -#endif - - //For now, just set the ideal activity and be done with it - return SetIdealActivity( (Activity) iActivity ); -} - -//==================================================================================== -// WEAPON SELECTION -//==================================================================================== - -//----------------------------------------------------------------------------- -// Purpose: Returns true if the weapon currently has ammo or doesn't need ammo -// Output : -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::HasAnyAmmo( void ) -{ - // If I don't use ammo of any kind, I can always fire - if ( !UsesPrimaryAmmo() && !UsesSecondaryAmmo() ) - return true; - - // Otherwise, I need ammo of either type - return ( HasPrimaryAmmo() || HasSecondaryAmmo() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true if the weapon currently has ammo or doesn't need ammo -// Output : -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::HasPrimaryAmmo( void ) -{ - // If I use a clip, and have some ammo in it, then I have ammo - if ( UsesClipsForAmmo1() ) - { - if ( m_iClip1 > 0 ) - return true; - } - - // Otherwise, I have ammo if I have some in my ammo counts - CBaseCombatCharacter *pOwner = GetOwner(); - if ( pOwner ) - { - if ( pOwner->GetAmmoCount( m_iPrimaryAmmoType ) > 0 ) - return true; - } - else - { - // No owner, so return how much primary ammo I have along with me. - if( GetPrimaryAmmoCount() > 0 ) - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true if the weapon currently has ammo or doesn't need ammo -// Output : -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::HasSecondaryAmmo( void ) -{ - // If I use a clip, and have some ammo in it, then I have ammo - if ( UsesClipsForAmmo2() ) - { - if ( m_iClip2 > 0 ) - return true; - } - - // Otherwise, I have ammo if I have some in my ammo counts - CBaseCombatCharacter *pOwner = GetOwner(); - if ( pOwner ) - { - if ( pOwner->GetAmmoCount( m_iSecondaryAmmoType ) > 0 ) - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: returns true if the weapon actually uses primary ammo -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::UsesPrimaryAmmo( void ) -{ - if ( m_iPrimaryAmmoType < 0 ) - return false; - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: returns true if the weapon actually uses secondary ammo -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::UsesSecondaryAmmo( void ) -{ - if ( m_iSecondaryAmmoType < 0 ) - return false; - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Show/hide weapon and corresponding view model if any -// Input : visible - -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::SetWeaponVisible( bool visible ) -{ - CBaseViewModel *vm = NULL; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( pOwner ) - { - vm = pOwner->GetViewModel( m_nViewModelIndex ); - } - - if ( visible ) - { - RemoveEffects( EF_NODRAW ); - if ( vm ) - { - vm->RemoveEffects( EF_NODRAW ); - } - } - else - { - AddEffects( EF_NODRAW ); - if ( vm ) - { - vm->AddEffects( EF_NODRAW ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::IsWeaponVisible( void ) -{ - CBaseViewModel *vm = NULL; - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( pOwner ) - { - vm = pOwner->GetViewModel( m_nViewModelIndex ); - if ( vm ) - return ( !vm->IsEffectActive(EF_NODRAW) ); - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: If the current weapon has more ammo, reload it. Otherwise, switch -// to the next best weapon we've got. Returns true if it took any action. -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::ReloadOrSwitchWeapons( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - Assert( pOwner ); - - m_bFireOnEmpty = false; - - // If we don't have any ammo, switch to the next best weapon - if ( !HasAnyAmmo() && m_flNextPrimaryAttack < gpGlobals->curtime && m_flNextSecondaryAttack < gpGlobals->curtime ) - { - // weapon isn't useable, switch. - if ( ( (GetWeaponFlags() & ITEM_FLAG_NOAUTOSWITCHEMPTY) == false ) && ( g_pGameRules->SwitchToNextBestWeapon( pOwner, this ) ) ) - { - m_flNextPrimaryAttack = gpGlobals->curtime + 0.3; - return true; - } - } - else - { - // Weapon is useable. Reload if empty and weapon has waited as long as it has to after firing - if ( UsesClipsForAmmo1() && - (m_iClip1 == 0) && - (GetWeaponFlags() & ITEM_FLAG_NOAUTORELOAD) == false && - m_flNextPrimaryAttack < gpGlobals->curtime && - m_flNextSecondaryAttack < gpGlobals->curtime ) - { - // if we're successfully reloading, we're done - if ( Reload() ) - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *szViewModel - -// *szWeaponModel - -// iActivity - -// *szAnimExt - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::DefaultDeploy( char *szViewModel, char *szWeaponModel, int iActivity, char *szAnimExt ) -{ - // Msg( "deploy %s at %f\n", GetClassname(), gpGlobals->curtime ); - - // Weapons that don't autoswitch away when they run out of ammo - // can still be deployed when they have no ammo. - if ( !HasAnyAmmo() && AllowsAutoSwitchFrom() ) - return false; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( pOwner ) - { - // Dead men deploy no weapons - if ( pOwner->IsAlive() == false ) - return false; - - pOwner->SetAnimationExtension( szAnimExt ); - - SetViewModel(); - SendWeaponAnim( iActivity ); - - pOwner->SetNextAttack( gpGlobals->curtime + SequenceDuration() ); - } - - // Can't shoot again until we've finished deploying - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration(); - m_flHudHintMinDisplayTime = 0; - - m_bAltFireHudHintDisplayed = false; - m_bReloadHudHintDisplayed = false; - m_flHudHintPollTime = gpGlobals->curtime + 5.0f; - - SetWeaponVisible( true ); - -/* - -This code is disabled for now, because moving through the weapons in the carousel -selects and deploys each weapon as you pass it. (sjb) - -*/ - - SetContextThink( NULL, 0, HIDEWEAPON_THINK_CONTEXT ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::Deploy( ) -{ - MDLCACHE_CRITICAL_SECTION(); - return DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), GetDrawActivity(), (char*)GetAnimPrefix() ); -} - -Activity CBaseCombatWeapon::GetDrawActivity( void ) -{ - return ACT_VM_DRAW; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::Holster( CBaseCombatWeapon *pSwitchingTo ) -{ - MDLCACHE_CRITICAL_SECTION(); - - // cancel any reload in progress. - m_bInReload = false; - - // kill any think functions - SetThink(NULL); - - // Send holster animation - SendWeaponAnim( ACT_VM_HOLSTER ); - - // Some weapon's don't have holster anims yet, so detect that - float flSequenceDuration = 0; - if ( GetActivity() == ACT_VM_HOLSTER ) - { - flSequenceDuration = SequenceDuration(); - } - - CBaseCombatCharacter *pOwner = GetOwner(); - if (pOwner) - { - pOwner->SetNextAttack( gpGlobals->curtime + flSequenceDuration ); - } - - // If we don't have a holster anim, hide immediately to avoid timing issues - if ( !flSequenceDuration ) - { - SetWeaponVisible( false ); - } - else - { - // Hide the weapon when the holster animation's finished - SetContextThink( &CBaseCombatWeapon::HideThink, gpGlobals->curtime + flSequenceDuration, HIDEWEAPON_THINK_CONTEXT ); - } - - // if we were displaying a hud hint, squelch it. - if (m_flHudHintMinDisplayTime && gpGlobals->curtime < m_flHudHintMinDisplayTime) - { - if( m_bAltFireHudHintDisplayed ) - RescindAltFireHudHint(); - - if( m_bReloadHudHintDisplayed ) - RescindReloadHudHint(); - } - - return true; -} - -#ifdef CLIENT_DLL - - void CBaseCombatWeapon::BoneMergeFastCullBloat( Vector &localMins, Vector &localMaxs, const Vector &thisEntityMins, const Vector &thisEntityMaxs ) const - { - // The default behavior pushes it out by BONEMERGE_FASTCULL_BBOX_EXPAND in all directions, but we can do better - // since we know the weapon will never point behind him. - - localMaxs.x += 20; // Leaves some space in front for long weapons. - - localMins.y -= 20; // Fatten it to his left and right since he can rotate that way. - localMaxs.y += 20; - - localMaxs.z += 15; // Leave some space at the top. - } - -#else -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::InputHideWeapon( inputdata_t &inputdata ) -{ - // Only hide if we're still the active weapon. If we're not the active weapon - if ( GetOwner() && GetOwner()->GetActiveWeapon() == this ) - { - SetWeaponVisible( false ); - } -} -#endif - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::HideThink( void ) -{ - // Only hide if we're still the active weapon. If we're not the active weapon - if ( GetOwner() && GetOwner()->GetActiveWeapon() == this ) - { - SetWeaponVisible( false ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::ItemPreFrame( void ) -{ - MaintainIdealActivity(); - -#ifndef CLIENT_DLL -#ifndef HL2_EPISODIC - if ( IsX360() ) -#endif - { - // If we haven't displayed the hint enough times yet, it's time to try to - // display the hint, and the player is not standing still, try to show a hud hint. - // If the player IS standing still, assume they could change away from this weapon at - // any second. - if( (!m_bAltFireHudHintDisplayed || !m_bReloadHudHintDisplayed) && gpGlobals->curtime > m_flHudHintMinDisplayTime && gpGlobals->curtime > m_flHudHintPollTime && GetOwner() && GetOwner()->IsPlayer() ) - { - CBasePlayer *pPlayer = (CBasePlayer*)(GetOwner()); - - if( pPlayer && pPlayer->GetStickDist() > 0.0f ) - { - // If the player is moving, they're unlikely to switch away from the current weapon - // the moment this weapon displays its HUD hint. - if( ShouldDisplayReloadHUDHint() ) - { - DisplayReloadHudHint(); - } - else if( ShouldDisplayAltFireHUDHint() ) - { - DisplayAltFireHudHint(); - } - } - else - { - m_flHudHintPollTime = gpGlobals->curtime + 2.0f; - } - } - } -#endif -} - -//==================================================================================== -// WEAPON BEHAVIOUR -//==================================================================================== -void CBaseCombatWeapon::ItemPostFrame( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if (!pOwner) - return; - - //Track the duration of the fire - //FIXME: Check for IN_ATTACK2 as well? - //FIXME: What if we're calling ItemBusyFrame? - m_fFireDuration = ( pOwner->m_nButtons & IN_ATTACK ) ? ( m_fFireDuration + gpGlobals->frametime ) : 0.0f; - - if ( UsesClipsForAmmo1() ) - { - CheckReload(); - } - - bool bFired = false; - - // Secondary attack has priority - if ((pOwner->m_nButtons & IN_ATTACK2) && (m_flNextSecondaryAttack <= gpGlobals->curtime)) - { - if (UsesSecondaryAmmo() && pOwner->GetAmmoCount(m_iSecondaryAmmoType)<=0 ) - { - if (m_flNextEmptySoundTime < gpGlobals->curtime) - { - WeaponSound(EMPTY); - m_flNextSecondaryAttack = m_flNextEmptySoundTime = gpGlobals->curtime + 0.5; - } - } - else if (pOwner->GetWaterLevel() == 3 && m_bAltFiresUnderwater == false) - { - // This weapon doesn't fire underwater - WeaponSound(EMPTY); - m_flNextPrimaryAttack = gpGlobals->curtime + 0.2; - return; - } - else - { - // FIXME: This isn't necessarily true if the weapon doesn't have a secondary fire! - // For instance, the crossbow doesn't have a 'real' secondary fire, but it still - // stops the crossbow from firing on the 360 if the player chooses to hold down their - // zoom button. (sjb) Orange Box 7/25/2007 -#if !defined(CLIENT_DLL) - if( !IsX360() || !ClassMatches("weapon_crossbow") ) -#endif - { - bFired = true; - } - - SecondaryAttack(); - - // Secondary ammo doesn't have a reload animation - if ( UsesClipsForAmmo2() ) - { - // reload clip2 if empty - if (m_iClip2 < 1) - { - pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType ); - m_iClip2 = m_iClip2 + 1; - } - } - } - } - - if ( !bFired && (pOwner->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime)) - { - // Clip empty? Or out of ammo on a no-clip weapon? - if ( !IsMeleeWeapon() && - (( UsesClipsForAmmo1() && m_iClip1 <= 0) || ( !UsesClipsForAmmo1() && pOwner->GetAmmoCount(m_iPrimaryAmmoType)<=0 )) ) - { - HandleFireOnEmpty(); - } - else if (pOwner->GetWaterLevel() == 3 && m_bFiresUnderwater == false) - { - // This weapon doesn't fire underwater - WeaponSound(EMPTY); - m_flNextPrimaryAttack = gpGlobals->curtime + 0.2; - return; - } - else - { - //NOTENOTE: There is a bug with this code with regards to the way machine guns catch the leading edge trigger - // on the player hitting the attack key. It relies on the gun catching that case in the same frame. - // However, because the player can also be doing a secondary attack, the edge trigger may be missed. - // We really need to hold onto the edge trigger and only clear the condition when the gun has fired its - // first shot. Right now that's too much of an architecture change -- jdw - - // If the firing button was just pressed, or the alt-fire just released, reset the firing time - if ( ( pOwner->m_afButtonPressed & IN_ATTACK ) || ( pOwner->m_afButtonReleased & IN_ATTACK2 ) ) - { - m_flNextPrimaryAttack = gpGlobals->curtime; - } - - PrimaryAttack(); - } - } - - // ----------------------- - // Reload pressed / Clip Empty - // ----------------------- - if ( pOwner->m_nButtons & IN_RELOAD && UsesClipsForAmmo1() && !m_bInReload ) - { - // reload when reload is pressed, or if no buttons are down and weapon is empty. - Reload(); - m_fFireDuration = 0.0f; - } - - // ----------------------- - // No buttons down - // ----------------------- - if (!((pOwner->m_nButtons & IN_ATTACK) || (pOwner->m_nButtons & IN_ATTACK2) || (pOwner->m_nButtons & IN_RELOAD))) - { - // no fire buttons down or reloading - if ( !ReloadOrSwitchWeapons() && ( m_bInReload == false ) ) - { - WeaponIdle(); - } - } -} - -void CBaseCombatWeapon::HandleFireOnEmpty() -{ - // If we're already firing on empty, reload if we can - if ( m_bFireOnEmpty ) - { - ReloadOrSwitchWeapons(); - m_fFireDuration = 0.0f; - } - else - { - if (m_flNextEmptySoundTime < gpGlobals->curtime) - { - WeaponSound(EMPTY); - m_flNextEmptySoundTime = gpGlobals->curtime + 0.5; - } - m_bFireOnEmpty = true; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Called each frame by the player PostThink, if the player's not ready to attack yet -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::ItemBusyFrame( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: Base class default for getting bullet type -// Input : -// Output : -//----------------------------------------------------------------------------- -int CBaseCombatWeapon::GetBulletType( void ) -{ - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: Base class default for getting spread -// Input : -// Output : -//----------------------------------------------------------------------------- -const Vector& CBaseCombatWeapon::GetBulletSpread( void ) -{ - static Vector cone = VECTOR_CONE_15DEGREES; - return cone; -} - -//----------------------------------------------------------------------------- -const WeaponProficiencyInfo_t *CBaseCombatWeapon::GetProficiencyValues() -{ - static WeaponProficiencyInfo_t defaultWeaponProficiencyTable[] = - { - { 1.0, 1.0 }, - { 1.0, 1.0 }, - { 1.0, 1.0 }, - { 1.0, 1.0 }, - { 1.0, 1.0 }, - }; - - COMPILE_TIME_ASSERT( ARRAYSIZE(defaultWeaponProficiencyTable) == WEAPON_PROFICIENCY_PERFECT + 1); - return defaultWeaponProficiencyTable; -} - -//----------------------------------------------------------------------------- -// Purpose: Base class default for getting firerate -// Input : -// Output : -//----------------------------------------------------------------------------- -float CBaseCombatWeapon::GetFireRate( void ) -{ - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: Base class default for playing shoot sound -// Input : -// Output : -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::WeaponSound( WeaponSound_t sound_type, float soundtime /* = 0.0f */ ) -{ - // If we have some sounds from the weapon classname.txt file, play a random one of them - const char *shootsound = GetShootSound( sound_type ); - if ( !shootsound || !shootsound[0] ) - return; - - CSoundParameters params; - - if ( !GetParametersForSound( shootsound, params, NULL ) ) - return; - - if ( params.play_to_owner_only ) - { - // Am I only to play to my owner? - if ( GetOwner() && GetOwner()->IsPlayer() ) - { - CSingleUserRecipientFilter filter( ToBasePlayer( GetOwner() ) ); - if ( IsPredicted() && CBaseEntity::GetPredictionPlayer() ) - { - filter.UsePredictionRules(); - } - EmitSound( filter, GetOwner()->entindex(), shootsound, NULL, soundtime ); - } - } - else - { - // Play weapon sound from the owner - if ( GetOwner() ) - { - CPASAttenuationFilter filter( GetOwner(), params.soundlevel ); - if ( IsPredicted() && CBaseEntity::GetPredictionPlayer() ) - { - filter.UsePredictionRules(); - } - EmitSound( filter, GetOwner()->entindex(), shootsound, NULL, soundtime ); - -#if !defined( CLIENT_DLL ) - if( sound_type == EMPTY ) - { - CSoundEnt::InsertSound( SOUND_COMBAT, GetOwner()->GetAbsOrigin(), SOUNDENT_VOLUME_EMPTY, 0.2, GetOwner() ); - } -#endif - } - // If no owner play from the weapon (this is used for thrown items) - else - { - CPASAttenuationFilter filter( this, params.soundlevel ); - if ( IsPredicted() && CBaseEntity::GetPredictionPlayer() ) - { - filter.UsePredictionRules(); - } - EmitSound( filter, entindex(), shootsound, NULL, soundtime ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Stop a sound played by this weapon. -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::StopWeaponSound( WeaponSound_t sound_type ) -{ - //if ( IsPredicted() ) - // return; - - // If we have some sounds from the weapon classname.txt file, play a random one of them - const char *shootsound = GetShootSound( sound_type ); - if ( !shootsound || !shootsound[0] ) - return; - - CSoundParameters params; - if ( !GetParametersForSound( shootsound, params, NULL ) ) - return; - - // Am I only to play to my owner? - if ( params.play_to_owner_only ) - { - if ( GetOwner() ) - { - StopSound( GetOwner()->entindex(), shootsound ); - } - } - else - { - // Play weapon sound from the owner - if ( GetOwner() ) - { - StopSound( GetOwner()->entindex(), shootsound ); - } - // If no owner play from the weapon (this is used for thrown items) - else - { - StopSound( entindex(), shootsound ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::DefaultReload( int iClipSize1, int iClipSize2, int iActivity ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - if (!pOwner) - return false; - - // If I don't have any spare ammo, I can't reload - if ( pOwner->GetAmmoCount(m_iPrimaryAmmoType) <= 0 ) - return false; - - bool bReload = false; - - // If you don't have clips, then don't try to reload them. - if ( UsesClipsForAmmo1() ) - { - // need to reload primary clip? - int primary = MIN(iClipSize1 - m_iClip1, pOwner->GetAmmoCount(m_iPrimaryAmmoType)); - if ( primary != 0 ) - { - bReload = true; - } - } - - if ( UsesClipsForAmmo2() ) - { - // need to reload secondary clip? - int secondary = MIN(iClipSize2 - m_iClip2, pOwner->GetAmmoCount(m_iSecondaryAmmoType)); - if ( secondary != 0 ) - { - bReload = true; - } - } - - if ( !bReload ) - return false; - -#ifdef CLIENT_DLL - // Play reload - WeaponSound( RELOAD ); -#endif - SendWeaponAnim( iActivity ); - - // Play the player's reload animation - if ( pOwner->IsPlayer() ) - { - ( ( CBasePlayer * )pOwner)->SetAnimation( PLAYER_RELOAD ); - } - - MDLCACHE_CRITICAL_SECTION(); - float flSequenceEndTime = gpGlobals->curtime + SequenceDuration(); - pOwner->SetNextAttack( flSequenceEndTime ); - m_flNextPrimaryAttack = m_flNextSecondaryAttack = flSequenceEndTime; - - m_bInReload = true; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::Reload( void ) -{ - return DefaultReload( GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD ); -} - -//========================================================= -void CBaseCombatWeapon::WeaponIdle( void ) -{ - //Idle again if we've finished - if ( HasWeaponIdleTimeElapsed() ) - { - SendWeaponAnim( ACT_VM_IDLE ); - } -} - - -//========================================================= -Activity CBaseCombatWeapon::GetPrimaryAttackActivity( void ) -{ - return ACT_VM_PRIMARYATTACK; -} - -//========================================================= -Activity CBaseCombatWeapon::GetSecondaryAttackActivity( void ) -{ - return ACT_VM_SECONDARYATTACK; -} - -//----------------------------------------------------------------------------- -// Purpose: Adds in view kick and weapon accuracy degradation effect -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::AddViewKick( void ) -{ - //NOTENOTE: By default, weapon will not kick up (defined per weapon) -} - -//----------------------------------------------------------------------------- -// Purpose: Get the string to print death notices with -//----------------------------------------------------------------------------- -char *CBaseCombatWeapon::GetDeathNoticeName( void ) -{ -#if !defined( CLIENT_DLL ) - return (char*)STRING( m_iszName ); -#else - return "GetDeathNoticeName not implemented on client yet"; -#endif -} - -//==================================================================================== -// WEAPON RELOAD TYPES -//==================================================================================== -void CBaseCombatWeapon::CheckReload( void ) -{ - if ( m_bReloadsSingly ) - { - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( !pOwner ) - return; - - if ((m_bInReload) && (m_flNextPrimaryAttack <= gpGlobals->curtime)) - { - if ( pOwner->m_nButtons & (IN_ATTACK | IN_ATTACK2) && m_iClip1 > 0 ) - { - m_bInReload = false; - return; - } - - // If out of ammo end reload - if (pOwner->GetAmmoCount(m_iPrimaryAmmoType) <=0) - { - FinishReload(); - return; - } - // If clip not full reload again - else if (m_iClip1 < GetMaxClip1()) - { - // Add them to the clip - m_iClip1 += 1; - pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType ); - - Reload(); - return; - } - // Clip full, stop reloading - else - { - FinishReload(); - m_flNextPrimaryAttack = gpGlobals->curtime; - m_flNextSecondaryAttack = gpGlobals->curtime; - return; - } - } - } - else - { - if ( (m_bInReload) && (m_flNextPrimaryAttack <= gpGlobals->curtime)) - { - FinishReload(); - m_flNextPrimaryAttack = gpGlobals->curtime; - m_flNextSecondaryAttack = gpGlobals->curtime; - m_bInReload = false; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Reload has finished. -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::FinishReload( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - - if (pOwner) - { - // If I use primary clips, reload primary - if ( UsesClipsForAmmo1() ) - { - int primary = MIN( GetMaxClip1() - m_iClip1, pOwner->GetAmmoCount(m_iPrimaryAmmoType)); - m_iClip1 += primary; - pOwner->RemoveAmmo( primary, m_iPrimaryAmmoType); - } - - // If I use secondary clips, reload secondary - if ( UsesClipsForAmmo2() ) - { - int secondary = MIN( GetMaxClip2() - m_iClip2, pOwner->GetAmmoCount(m_iSecondaryAmmoType)); - m_iClip2 += secondary; - pOwner->RemoveAmmo( secondary, m_iSecondaryAmmoType ); - } - - if ( m_bReloadsSingly ) - { - m_bInReload = false; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Abort any reload we have in progress -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::AbortReload( void ) -{ -#ifdef CLIENT_DLL - StopWeaponSound( RELOAD ); -#endif - m_bInReload = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Primary fire button attack -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::PrimaryAttack( void ) -{ - // If my clip is empty (and I use clips) start reload - if ( UsesClipsForAmmo1() && !m_iClip1 ) - { - Reload(); - return; - } - - // Only the player fires this way so we can cast - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if (!pPlayer) - { - return; - } - - pPlayer->DoMuzzleFlash(); - - SendWeaponAnim( GetPrimaryAttackActivity() ); - - // player "shoot" animation - pPlayer->SetAnimation( PLAYER_ATTACK1 ); - - FireBulletsInfo_t info; - info.m_vecSrc = pPlayer->Weapon_ShootPosition( ); - - info.m_vecDirShooting = pPlayer->GetAutoaimVector( AUTOAIM_SCALE_DEFAULT ); - - // To make the firing framerate independent, we may have to fire more than one bullet here on low-framerate systems, - // especially if the weapon we're firing has a really fast rate of fire. - info.m_iShots = 0; - float fireRate = GetFireRate(); - - while ( m_flNextPrimaryAttack <= gpGlobals->curtime ) - { - // MUST call sound before removing a round from the clip of a CMachineGun - WeaponSound(SINGLE, m_flNextPrimaryAttack); - m_flNextPrimaryAttack = m_flNextPrimaryAttack + fireRate; - info.m_iShots++; - if ( !fireRate ) - break; - } - - // Make sure we don't fire more than the amount in the clip - if ( UsesClipsForAmmo1() ) - { - info.m_iShots = MIN( info.m_iShots, m_iClip1 ); - m_iClip1 -= info.m_iShots; - } - else - { - info.m_iShots = MIN( info.m_iShots, pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) ); - pPlayer->RemoveAmmo( info.m_iShots, m_iPrimaryAmmoType ); - } - - info.m_flDistance = MAX_TRACE_LENGTH; - info.m_iAmmoType = m_iPrimaryAmmoType; - info.m_iTracerFreq = 2; - -#if !defined( CLIENT_DLL ) - // Fire the bullets - info.m_vecSpread = pPlayer->GetAttackSpread( this ); -#else - //!!!HACKHACK - what does the client want this function for? - info.m_vecSpread = GetActiveWeapon()->GetBulletSpread(); -#endif // CLIENT_DLL - - pPlayer->FireBullets( info ); - - if (!m_iClip1 && pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0) - { - // HEV suit - indicate out of ammo condition - pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); - } - - //Add our view kick in - AddViewKick(); -} - -//----------------------------------------------------------------------------- -// Purpose: Called every frame to check if the weapon is going through transition animations -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::MaintainIdealActivity( void ) -{ - // Must be transitioning - if ( GetActivity() != ACT_TRANSITION ) - return; - - // Must not be at our ideal already - if ( ( GetActivity() == m_IdealActivity ) && ( GetSequence() == m_nIdealSequence ) ) - return; - - // Must be finished with the current animation - if ( IsViewModelSequenceFinished() == false ) - return; - - // Move to the next animation towards our ideal - SendWeaponAnim( m_IdealActivity ); -} - -//----------------------------------------------------------------------------- -// Purpose: Sets the ideal activity for the weapon to be in, allowing for transitional animations inbetween -// Input : ideal - activity to end up at, ideally -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::SetIdealActivity( Activity ideal ) -{ - MDLCACHE_CRITICAL_SECTION(); - int idealSequence = SelectWeightedSequence( ideal ); - - if ( idealSequence == -1 ) - return false; - - //Take the new activity - m_IdealActivity = ideal; - m_nIdealSequence = idealSequence; - - //Find the next sequence in the potential chain of sequences leading to our ideal one - int nextSequence = FindTransitionSequence( GetSequence(), m_nIdealSequence, NULL ); - - // Don't use transitions when we're deploying - if ( ideal != ACT_VM_DRAW && IsWeaponVisible() && nextSequence != m_nIdealSequence ) - { - //Set our activity to the next transitional animation - SetActivity( ACT_TRANSITION ); - SetSequence( nextSequence ); - SendViewModelAnim( nextSequence ); - } - else - { - //Set our activity to the ideal - SetActivity( m_IdealActivity ); - SetSequence( m_nIdealSequence ); - SendViewModelAnim( m_nIdealSequence ); - } - - //Set the next time the weapon will idle - SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() ); - return true; -} - -//----------------------------------------------------------------------------- -// Returns information about the various control panels -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::GetControlPanelInfo( int nPanelIndex, const char *&pPanelName ) -{ - pPanelName = NULL; -} - -//----------------------------------------------------------------------------- -// Returns information about the various control panels -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::GetControlPanelClassName( int nPanelIndex, const char *&pPanelName ) -{ - pPanelName = "vgui_screen"; -} - - -//----------------------------------------------------------------------------- -// Locking a weapon is an exclusive action. If you lock a weapon, that means -// you are preventing others from doing so for themselves. -//----------------------------------------------------------------------------- -void CBaseCombatWeapon::Lock( float lockTime, CBaseEntity *pLocker ) -{ - m_flUnlockTime = gpGlobals->curtime + lockTime; - m_hLocker.Set( pLocker ); -} - -//----------------------------------------------------------------------------- -// If I'm still locked for a period of time, tell everyone except the person -// that locked me that I'm not available. -//----------------------------------------------------------------------------- -bool CBaseCombatWeapon::IsLocked( CBaseEntity *pAsker ) -{ - return ( m_flUnlockTime > gpGlobals->curtime && m_hLocker != pAsker ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -Activity CBaseCombatWeapon::ActivityOverride( Activity baseAct, bool *pRequired ) -{ - acttable_t *pTable = ActivityList(); - int actCount = ActivityListCount(); - - for ( int i = 0; i < actCount; i++, pTable++ ) - { - if ( baseAct == pTable->baseAct ) - { - if (pRequired) - { - *pRequired = pTable->required; - } - return (Activity)pTable->weaponAct; - } - } - return baseAct; -} - - -#if defined( CLIENT_DLL ) - -BEGIN_PREDICTION_DATA( CBaseCombatWeapon ) - - DEFINE_PRED_FIELD( m_nNextThinkTick, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), - // Networked - DEFINE_PRED_FIELD( m_hOwner, FIELD_EHANDLE, FTYPEDESC_INSENDTABLE ), - // DEFINE_FIELD( m_hWeaponFileInfo, FIELD_SHORT ), - DEFINE_PRED_FIELD( m_iState, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_iViewModelIndex, FIELD_INTEGER, FTYPEDESC_INSENDTABLE | FTYPEDESC_MODELINDEX ), - DEFINE_PRED_FIELD( m_iWorldModelIndex, FIELD_INTEGER, FTYPEDESC_INSENDTABLE | FTYPEDESC_MODELINDEX ), - DEFINE_PRED_FIELD_TOL( m_flNextPrimaryAttack, FIELD_FLOAT, FTYPEDESC_INSENDTABLE, TD_MSECTOLERANCE ), - DEFINE_PRED_FIELD_TOL( m_flNextSecondaryAttack, FIELD_FLOAT, FTYPEDESC_INSENDTABLE, TD_MSECTOLERANCE ), - DEFINE_PRED_FIELD_TOL( m_flTimeWeaponIdle, FIELD_FLOAT, FTYPEDESC_INSENDTABLE, TD_MSECTOLERANCE ), - - DEFINE_PRED_FIELD( m_iPrimaryAmmoType, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_iSecondaryAmmoType, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_iClip1, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_iClip2, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), - - DEFINE_PRED_FIELD( m_nViewModelIndex, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), - - // Not networked - - DEFINE_PRED_FIELD( m_flTimeWeaponIdle, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), - DEFINE_FIELD( m_bInReload, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bFireOnEmpty, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flNextEmptySoundTime, FIELD_FLOAT ), - DEFINE_FIELD( m_Activity, FIELD_INTEGER ), - DEFINE_FIELD( m_fFireDuration, FIELD_FLOAT ), - DEFINE_FIELD( m_iszName, FIELD_INTEGER ), - DEFINE_FIELD( m_bFiresUnderwater, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bAltFiresUnderwater, FIELD_BOOLEAN ), - DEFINE_FIELD( m_fMinRange1, FIELD_FLOAT ), - DEFINE_FIELD( m_fMinRange2, FIELD_FLOAT ), - DEFINE_FIELD( m_fMaxRange1, FIELD_FLOAT ), - DEFINE_FIELD( m_fMaxRange2, FIELD_FLOAT ), - DEFINE_FIELD( m_bReloadsSingly, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bRemoveable, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iPrimaryAmmoCount, FIELD_INTEGER ), - DEFINE_FIELD( m_iSecondaryAmmoCount, FIELD_INTEGER ), - - //DEFINE_PHYSPTR( m_pConstraint ), - - // DEFINE_FIELD( m_iOldState, FIELD_INTEGER ), - // DEFINE_FIELD( m_bJustRestored, FIELD_BOOLEAN ), - - // DEFINE_FIELD( m_OnPlayerPickup, COutputEvent ), - // DEFINE_FIELD( m_pConstraint, FIELD_INTEGER ), - -END_PREDICTION_DATA() - -#endif // ! CLIENT_DLL - -// Special hack since we're aliasing the name C_BaseCombatWeapon with a macro on the client -IMPLEMENT_NETWORKCLASS_ALIASED( BaseCombatWeapon, DT_BaseCombatWeapon ) - -#if !defined( CLIENT_DLL ) -//----------------------------------------------------------------------------- -// Purpose: Save Data for Base Weapon object -//-----------------------------------------------------------------------------// -BEGIN_DATADESC( CBaseCombatWeapon ) - - DEFINE_FIELD( m_flNextPrimaryAttack, FIELD_TIME ), - DEFINE_FIELD( m_flNextSecondaryAttack, FIELD_TIME ), - DEFINE_FIELD( m_flTimeWeaponIdle, FIELD_TIME ), - - DEFINE_FIELD( m_bInReload, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bFireOnEmpty, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hOwner, FIELD_EHANDLE ), - - DEFINE_FIELD( m_iState, FIELD_INTEGER ), - DEFINE_FIELD( m_iszName, FIELD_STRING ), - DEFINE_FIELD( m_iPrimaryAmmoType, FIELD_INTEGER ), - DEFINE_FIELD( m_iSecondaryAmmoType, FIELD_INTEGER ), - DEFINE_FIELD( m_iClip1, FIELD_INTEGER ), - DEFINE_FIELD( m_iClip2, FIELD_INTEGER ), - DEFINE_FIELD( m_bFiresUnderwater, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bAltFiresUnderwater, FIELD_BOOLEAN ), - DEFINE_FIELD( m_fMinRange1, FIELD_FLOAT ), - DEFINE_FIELD( m_fMinRange2, FIELD_FLOAT ), - DEFINE_FIELD( m_fMaxRange1, FIELD_FLOAT ), - DEFINE_FIELD( m_fMaxRange2, FIELD_FLOAT ), - - DEFINE_FIELD( m_iPrimaryAmmoCount, FIELD_INTEGER ), - DEFINE_FIELD( m_iSecondaryAmmoCount, FIELD_INTEGER ), - - DEFINE_FIELD( m_nViewModelIndex, FIELD_INTEGER ), - -// don't save these, init to 0 and regenerate -// DEFINE_FIELD( m_flNextEmptySoundTime, FIELD_TIME ), -// DEFINE_FIELD( m_Activity, FIELD_INTEGER ), - DEFINE_FIELD( m_nIdealSequence, FIELD_INTEGER ), - DEFINE_FIELD( m_IdealActivity, FIELD_INTEGER ), - - DEFINE_FIELD( m_fFireDuration, FIELD_FLOAT ), - - DEFINE_FIELD( m_bReloadsSingly, FIELD_BOOLEAN ), - DEFINE_FIELD( m_iSubType, FIELD_INTEGER ), - DEFINE_FIELD( m_bRemoveable, FIELD_BOOLEAN ), - - DEFINE_FIELD( m_flUnlockTime, FIELD_TIME ), - DEFINE_FIELD( m_hLocker, FIELD_EHANDLE ), - - // DEFINE_FIELD( m_iViewModelIndex, FIELD_INTEGER ), - // DEFINE_FIELD( m_iWorldModelIndex, FIELD_INTEGER ), - // DEFINE_FIELD( m_hWeaponFileInfo, ???? ), - - DEFINE_PHYSPTR( m_pConstraint ), - - DEFINE_FIELD( m_iReloadHudHintCount, FIELD_INTEGER ), - DEFINE_FIELD( m_iAltFireHudHintCount, FIELD_INTEGER ), - DEFINE_FIELD( m_bReloadHudHintDisplayed, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bAltFireHudHintDisplayed, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flHudHintPollTime, FIELD_TIME ), - DEFINE_FIELD( m_flHudHintMinDisplayTime, FIELD_TIME ), - - // Just to quiet classcheck.. this field exists only on the client -// DEFINE_FIELD( m_iOldState, FIELD_INTEGER ), -// DEFINE_FIELD( m_bJustRestored, FIELD_BOOLEAN ), - - // Function pointers - DEFINE_ENTITYFUNC( DefaultTouch ), - DEFINE_THINKFUNC( FallThink ), - DEFINE_THINKFUNC( Materialize ), - DEFINE_THINKFUNC( AttemptToMaterialize ), - DEFINE_THINKFUNC( DestroyItem ), - DEFINE_THINKFUNC( SetPickupTouch ), - - DEFINE_THINKFUNC( HideThink ), - DEFINE_INPUTFUNC( FIELD_VOID, "HideWeapon", InputHideWeapon ), - - // Outputs - DEFINE_OUTPUT( m_OnPlayerUse, "OnPlayerUse"), - DEFINE_OUTPUT( m_OnPlayerPickup, "OnPlayerPickup"), - DEFINE_OUTPUT( m_OnNPCPickup, "OnNPCPickup"), - DEFINE_OUTPUT( m_OnCacheInteraction, "OnCacheInteraction" ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: Only send to local player if this weapon is the active weapon -// Input : *pStruct - -// *pVarData - -// *pRecipients - -// objectID - -// Output : void* -//----------------------------------------------------------------------------- -void* SendProxy_SendActiveLocalWeaponDataTable( const SendProp *pProp, const void *pStruct, const void *pVarData, CSendProxyRecipients *pRecipients, int objectID ) -{ - // Get the weapon entity - CBaseCombatWeapon *pWeapon = (CBaseCombatWeapon*)pVarData; - if ( pWeapon ) - { - // Only send this chunk of data to the player carrying this weapon - CBasePlayer *pPlayer = ToBasePlayer( pWeapon->GetOwner() ); - if ( pPlayer /*&& pPlayer->GetActiveWeapon() == pWeapon*/ ) - { - pRecipients->SetOnly( pPlayer->GetClientIndex() ); - return (void*)pVarData; - } - } - - return NULL; -} -REGISTER_SEND_PROXY_NON_MODIFIED_POINTER( SendProxy_SendActiveLocalWeaponDataTable ); - -//----------------------------------------------------------------------------- -// Purpose: Only send the LocalWeaponData to the player carrying the weapon -//----------------------------------------------------------------------------- -void* SendProxy_SendLocalWeaponDataTable( const SendProp *pProp, const void *pStruct, const void *pVarData, CSendProxyRecipients *pRecipients, int objectID ) -{ - // Get the weapon entity - CBaseCombatWeapon *pWeapon = (CBaseCombatWeapon*)pVarData; - if ( pWeapon ) - { - // Only send this chunk of data to the player carrying this weapon - CBasePlayer *pPlayer = ToBasePlayer( pWeapon->GetOwner() ); - if ( pPlayer ) - { - pRecipients->SetOnly( pPlayer->GetClientIndex() ); - return (void*)pVarData; - } - } - - return NULL; -} -REGISTER_SEND_PROXY_NON_MODIFIED_POINTER( SendProxy_SendLocalWeaponDataTable ); -#endif - -#if PREDICTION_ERROR_CHECK_LEVEL > 1 -#define SendPropTime SendPropFloat -#define RecvPropTime RecvPropFloat -#endif - -//----------------------------------------------------------------------------- -// Purpose: Propagation data for weapons. Only sent when a player's holding it. -//----------------------------------------------------------------------------- -BEGIN_NETWORK_TABLE_NOBASE( CBaseCombatWeapon, DT_LocalActiveWeaponData ) -#if !defined( CLIENT_DLL ) - SendPropTime( SENDINFO( m_flNextPrimaryAttack ) ), - SendPropTime( SENDINFO( m_flNextSecondaryAttack ) ), - SendPropInt( SENDINFO( m_nNextThinkTick ) ), - SendPropTime( SENDINFO( m_flTimeWeaponIdle ) ), - -#if defined( TF_DLL ) - SendPropExclude( "DT_AnimTimeMustBeFirst" , "m_flAnimTime" ), -#endif - -#else - RecvPropTime( RECVINFO( m_flNextPrimaryAttack ) ), - RecvPropTime( RECVINFO( m_flNextSecondaryAttack ) ), - RecvPropInt( RECVINFO( m_nNextThinkTick ) ), - RecvPropTime( RECVINFO( m_flTimeWeaponIdle ) ), -#endif -END_NETWORK_TABLE() - -//----------------------------------------------------------------------------- -// Purpose: Propagation data for weapons. Only sent when a player's holding it. -//----------------------------------------------------------------------------- -BEGIN_NETWORK_TABLE_NOBASE( CBaseCombatWeapon, DT_LocalWeaponData ) -#if !defined( CLIENT_DLL ) - SendPropIntWithMinusOneFlag( SENDINFO(m_iClip1 ), 8 ), - SendPropIntWithMinusOneFlag( SENDINFO(m_iClip2 ), 8 ), - SendPropInt( SENDINFO(m_iPrimaryAmmoType ), 8 ), - SendPropInt( SENDINFO(m_iSecondaryAmmoType ), 8 ), - - SendPropInt( SENDINFO( m_nViewModelIndex ), VIEWMODEL_INDEX_BITS, SPROP_UNSIGNED ), - -#if defined( TF_DLL ) - SendPropExclude( "DT_AnimTimeMustBeFirst" , "m_flAnimTime" ), -#endif - -#else - RecvPropIntWithMinusOneFlag( RECVINFO(m_iClip1 )), - RecvPropIntWithMinusOneFlag( RECVINFO(m_iClip2 )), - RecvPropInt( RECVINFO(m_iPrimaryAmmoType )), - RecvPropInt( RECVINFO(m_iSecondaryAmmoType )), - - RecvPropInt( RECVINFO( m_nViewModelIndex ) ), - -#endif -END_NETWORK_TABLE() - -BEGIN_NETWORK_TABLE(CBaseCombatWeapon, DT_BaseCombatWeapon) -#if !defined( CLIENT_DLL ) - SendPropDataTable("LocalWeaponData", 0, &REFERENCE_SEND_TABLE(DT_LocalWeaponData), SendProxy_SendLocalWeaponDataTable ), - SendPropDataTable("LocalActiveWeaponData", 0, &REFERENCE_SEND_TABLE(DT_LocalActiveWeaponData), SendProxy_SendActiveLocalWeaponDataTable ), - SendPropModelIndex( SENDINFO(m_iViewModelIndex) ), - SendPropModelIndex( SENDINFO(m_iWorldModelIndex) ), - SendPropInt( SENDINFO(m_iState ), 8, SPROP_UNSIGNED ), - SendPropEHandle( SENDINFO(m_hOwner) ), -#else - RecvPropDataTable("LocalWeaponData", 0, 0, &REFERENCE_RECV_TABLE(DT_LocalWeaponData)), - RecvPropDataTable("LocalActiveWeaponData", 0, 0, &REFERENCE_RECV_TABLE(DT_LocalActiveWeaponData)), - RecvPropInt( RECVINFO(m_iViewModelIndex)), - RecvPropInt( RECVINFO(m_iWorldModelIndex)), - RecvPropInt( RECVINFO(m_iState )), - RecvPropEHandle( RECVINFO(m_hOwner ) ), -#endif -END_NETWORK_TABLE() diff --git a/game/shared/basecombatweapon_shared.h b/game/shared/basecombatweapon_shared.h deleted file mode 100644 index 99511cbf8..000000000 --- a/game/shared/basecombatweapon_shared.h +++ /dev/null @@ -1,566 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#ifndef COMBATWEAPON_SHARED_H -#define COMBATWEAPON_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - -#include "vphysics_interface.h" -#include "predictable_entity.h" -#include "soundflags.h" -#include "weapon_parse.h" -#include "baseviewmodel_shared.h" -#include "weapon_proficiency.h" - -#if defined( CLIENT_DLL ) -#define CBaseCombatWeapon C_BaseCombatWeapon -#endif - -// Hacky -#if defined ( TF_CLIENT_DLL ) || defined ( TF_DLL ) -#include "item_base.h" -#endif // TF_CLIENT_DLL || TF_DLL - -#if !defined( CLIENT_DLL ) -extern void OnBaseCombatWeaponCreated( CBaseCombatWeapon * ); -extern void OnBaseCombatWeaponDestroyed( CBaseCombatWeapon * ); - -void *SendProxy_SendLocalWeaponDataTable( const SendProp *pProp, const void *pStruct, const void *pVarData, CSendProxyRecipients *pRecipients, int objectID ); -#endif - -class CBasePlayer; -class CBaseCombatCharacter; -class IPhysicsConstraint; -class CUserCmd; - -// How many times to display altfire hud hints (per weapon) -#define WEAPON_ALTFIRE_HUD_HINT_COUNT 1 -#define WEAPON_RELOAD_HUD_HINT_COUNT 1 - -//Start with a constraint in place (don't drop to floor) -#define SF_WEAPON_START_CONSTRAINED (1<<0) -#define SF_WEAPON_NO_PLAYER_PICKUP (1<<1) -#define SF_WEAPON_NO_PHYSCANNON_PUNT (1<<2) - -//Percent -#define CLIP_PERC_THRESHOLD 0.75f - -// Put this in your derived class definition to declare it's activity table -// UNDONE: Cascade these? -#define DECLARE_ACTTABLE() static acttable_t m_acttable[];\ - acttable_t *ActivityList( void );\ - int ActivityListCount( void ); - -// You also need to include the activity table itself in your class' implementation: -// e.g. -// acttable_t CWeaponStunstick::m_acttable[] = -// { -// { ACT_MELEE_ATTACK1, ACT_MELEE_ATTACK_SWING, TRUE }, -// }; -// -// The stunstick overrides the ACT_MELEE_ATTACK1 activity, replacing it with ACT_MELEE_ATTACK_SWING. -// This animation is required for this weapon's operation. -// - -// Put this after your derived class' definition to implement the accessors for the -// activity table. -// UNDONE: Cascade these? -#define IMPLEMENT_ACTTABLE(className) \ - acttable_t *className::ActivityList( void ) { return m_acttable; } \ - int className::ActivityListCount( void ) { return ARRAYSIZE(m_acttable); } \ - -typedef struct -{ - int baseAct; - int weaponAct; - bool required; -} acttable_t; - -class CHudTexture; -class Color; - -namespace vgui2 -{ - typedef unsigned long HFont; -} - -// ----------------------------------------- -// Vector cones -// ----------------------------------------- -// VECTOR_CONE_PRECALCULATED - this resolves to vec3_origin, but adds some -// context indicating that the person writing the code is not allowing -// FireBullets() to modify the direction of the shot because the shot direction -// being passed into the function has already been modified by another piece of -// code and should be fired as specified. See GetActualShotTrajectory(). - -// NOTE: The way these are calculated is that each component == sin (degrees/2) -#define VECTOR_CONE_PRECALCULATED vec3_origin -#define VECTOR_CONE_1DEGREES Vector( 0.00873, 0.00873, 0.00873 ) -#define VECTOR_CONE_2DEGREES Vector( 0.01745, 0.01745, 0.01745 ) -#define VECTOR_CONE_3DEGREES Vector( 0.02618, 0.02618, 0.02618 ) -#define VECTOR_CONE_4DEGREES Vector( 0.03490, 0.03490, 0.03490 ) -#define VECTOR_CONE_5DEGREES Vector( 0.04362, 0.04362, 0.04362 ) -#define VECTOR_CONE_6DEGREES Vector( 0.05234, 0.05234, 0.05234 ) -#define VECTOR_CONE_7DEGREES Vector( 0.06105, 0.06105, 0.06105 ) -#define VECTOR_CONE_8DEGREES Vector( 0.06976, 0.06976, 0.06976 ) -#define VECTOR_CONE_9DEGREES Vector( 0.07846, 0.07846, 0.07846 ) -#define VECTOR_CONE_10DEGREES Vector( 0.08716, 0.08716, 0.08716 ) -#define VECTOR_CONE_15DEGREES Vector( 0.13053, 0.13053, 0.13053 ) -#define VECTOR_CONE_20DEGREES Vector( 0.17365, 0.17365, 0.17365 ) - -//----------------------------------------------------------------------------- -// Purpose: Base weapon class, shared on client and server -//----------------------------------------------------------------------------- - -#if defined USES_PERSISTENT_ITEMS -#define BASECOMBATWEAPON_DERIVED_FROM CBaseAttributableItem -#else -#define BASECOMBATWEAPON_DERIVED_FROM CBaseAnimating -#endif - -//----------------------------------------------------------------------------- -// Purpose: Client side rep of CBaseTFCombatWeapon -//----------------------------------------------------------------------------- -// Hacky -class CBaseCombatWeapon : public BASECOMBATWEAPON_DERIVED_FROM -{ -public: - DECLARE_CLASS( CBaseCombatWeapon, BASECOMBATWEAPON_DERIVED_FROM ); - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - - CBaseCombatWeapon(); - virtual ~CBaseCombatWeapon(); - - // A derived weapon class should return true here so that weapon sounds, etc, can - // apply the proper filter - virtual bool IsPredicted( void ) const { return false; } - - virtual void Spawn( void ); - virtual void Precache( void ); - - void MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ); - - // Subtypes are used to manage multiple weapons of the same type on the player. - virtual int GetSubType( void ) { return m_iSubType; } - virtual void SetSubType( int iType ) { m_iSubType = iType; } - - virtual void Equip( CBaseCombatCharacter *pOwner ); - virtual void Drop( const Vector &vecVelocity ); - - virtual int UpdateClientData( CBasePlayer *pPlayer ); - - virtual bool IsAllowedToSwitch( void ); - virtual bool CanBeSelected( void ); - virtual bool VisibleInWeaponSelection( void ); - virtual bool HasAmmo( void ); - - // Weapon Pickup For Player - virtual void SetPickupTouch( void ); - virtual void DefaultTouch( CBaseEntity *pOther ); // default weapon touch - - // HUD Hints - virtual bool ShouldDisplayAltFireHUDHint(); - virtual void DisplayAltFireHudHint(); - virtual void RescindAltFireHudHint(); ///< undisplay the hud hint and pretend it never showed. - - virtual bool ShouldDisplayReloadHUDHint(); - virtual void DisplayReloadHudHint(); - virtual void RescindReloadHudHint(); - - // Weapon client handling - virtual void SetViewModelIndex( int index = 0 ); - virtual bool SendWeaponAnim( int iActivity ); - virtual void SendViewModelAnim( int nSequence ); - float GetViewModelSequenceDuration(); // Return how long the current view model sequence is. - bool IsViewModelSequenceFinished( void ); // Returns if the viewmodel's current animation is finished - - virtual void SetViewModel(); - - virtual bool HasWeaponIdleTimeElapsed( void ); - virtual void SetWeaponIdleTime( float time ); - virtual float GetWeaponIdleTime( void ); - - // Weapon selection - virtual bool HasAnyAmmo( void ); // Returns true is weapon has ammo - virtual bool HasPrimaryAmmo( void ); // Returns true is weapon has ammo - virtual bool HasSecondaryAmmo( void ); // Returns true is weapon has ammo - bool UsesPrimaryAmmo( void ); // returns true if the weapon actually uses primary ammo - bool UsesSecondaryAmmo( void ); // returns true if the weapon actually uses secondary ammo - void GiveDefaultAmmo( void ); - - virtual bool CanHolster( void ) { return TRUE; }; // returns true if the weapon can be holstered - virtual bool DefaultDeploy( char *szViewModel, char *szWeaponModel, int iActivity, char *szAnimExt ); - virtual bool CanDeploy( void ) { return true; } // return true if the weapon's allowed to deploy - virtual bool Deploy( void ); // returns true is deploy was successful - virtual bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); - virtual CBaseCombatWeapon *GetLastWeapon( void ) { return this; } - virtual void SetWeaponVisible( bool visible ); - virtual bool IsWeaponVisible( void ); - virtual bool ReloadOrSwitchWeapons( void ); - - // Weapon behaviour - virtual void ItemPreFrame( void ); // called each frame by the player PreThink - virtual void ItemPostFrame( void ); // called each frame by the player PostThink - virtual void ItemBusyFrame( void ); // called each frame by the player PostThink, if the player's not ready to attack yet - virtual void ItemHolsterFrame( void ) {}; // called each frame by the player PreThink, if the weapon is holstered - virtual void WeaponIdle( void ); // called when no buttons pressed - virtual void HandleFireOnEmpty(); // Called when they have the attack button down - // but they are out of ammo. The default implementation - // either reloads, switches weapons, or plays an empty sound. -#ifdef CLIENT_DLL - virtual void CreateMove( float flInputSampleTime, CUserCmd *pCmd, const QAngle &vecOldViewAngles ) {} -#endif - - virtual bool IsWeaponZoomed() { return false; } // Is this weapon in its 'zoomed in' mode? - - // Reloading - virtual void CheckReload( void ); - virtual void FinishReload( void ); - virtual void AbortReload( void ); - virtual bool Reload( void ); - bool DefaultReload( int iClipSize1, int iClipSize2, int iActivity ); - - // Weapon firing - virtual void PrimaryAttack( void ); // do "+ATTACK" - virtual void SecondaryAttack( void ) { return; } // do "+ATTACK2" - - // Firing animations - virtual Activity GetPrimaryAttackActivity( void ); - virtual Activity GetSecondaryAttackActivity( void ); - virtual Activity GetDrawActivity( void ); - virtual float GetDefaultAnimSpeed( void ) { return 1.0; } - - // Bullet launch information - virtual int GetBulletType( void ); - virtual const Vector& GetBulletSpread( void ); - virtual Vector GetBulletSpread( WeaponProficiency_t proficiency ) { return GetBulletSpread(); } - virtual float GetSpreadBias( WeaponProficiency_t proficiency ) { return 1.0; } - virtual float GetFireRate( void ); - virtual int GetMinBurst() { return 1; } - virtual int GetMaxBurst() { return 1; } - virtual float GetMinRestTime() { return 0.3; } - virtual float GetMaxRestTime() { return 0.6; } - virtual int GetRandomBurst() { return random->RandomInt( GetMinBurst(), GetMaxBurst() ); } - virtual void WeaponSound( WeaponSound_t sound_type, float soundtime = 0.0f ); - virtual void StopWeaponSound( WeaponSound_t sound_type ); - virtual const WeaponProficiencyInfo_t *GetProficiencyValues(); - - // Autoaim - virtual float GetMaxAutoAimDeflection() { return 0.99f; } - virtual float WeaponAutoAimScale() { return 1.0f; } // allows a weapon to influence the perceived size of the target's autoaim radius. - - // TF Sprinting functions - virtual bool StartSprinting( void ) { return false; }; - virtual bool StopSprinting( void ) { return false; }; - - // TF Injury functions - virtual float GetDamage( float flDistance, int iLocation ) { return 0.0; }; - - virtual void SetActivity( Activity act, float duration ); - inline void SetActivity( Activity eActivity ) { m_Activity = eActivity; } - inline Activity GetActivity( void ) { return m_Activity; } - - virtual void AddViewKick( void ); // Add in the view kick for the weapon - - virtual char *GetDeathNoticeName( void ); // Get the string to print death notices with - - CBaseCombatCharacter *GetOwner() const; - void SetOwner( CBaseCombatCharacter *owner ); - virtual void OnPickedUp( CBaseCombatCharacter *pNewOwner ); - - virtual void AddViewmodelBob( CBaseViewModel *viewmodel, Vector &origin, QAngle &angles ) {}; - virtual float CalcViewmodelBob( void ) { return 0.0f; }; - - // Returns information about the various control panels - virtual void GetControlPanelInfo( int nPanelIndex, const char *&pPanelName ); - virtual void GetControlPanelClassName( int nPanelIndex, const char *&pPanelName ); - - virtual bool ShouldShowControlPanels( void ) { return true; } - - void Lock( float lockTime, CBaseEntity *pLocker ); - bool IsLocked( CBaseEntity *pAsker ); - - //All weapons can be picked up by NPCs by default - virtual bool CanBePickedUpByNPCs( void ) { return true; } - -public: - - // Weapon info accessors for data in the weapon's data file - const FileWeaponInfo_t &GetWpnData( void ) const; - virtual const char *GetViewModel( int viewmodelindex = 0 ) const; - virtual const char *GetWorldModel( void ) const; - virtual const char *GetAnimPrefix( void ) const; - virtual int GetMaxClip1( void ) const; - virtual int GetMaxClip2( void ) const; - virtual int GetDefaultClip1( void ) const; - virtual int GetDefaultClip2( void ) const; - virtual int GetWeight( void ) const; - virtual bool AllowsAutoSwitchTo( void ) const; - virtual bool AllowsAutoSwitchFrom( void ) const; - virtual int GetWeaponFlags( void ) const; - virtual int GetSlot( void ) const; - virtual int GetPosition( void ) const; - virtual char const *GetName( void ) const; - virtual char const *GetPrintName( void ) const; - virtual char const *GetShootSound( int iIndex ) const; - virtual int GetRumbleEffect() const; - virtual bool UsesClipsForAmmo1( void ) const; - virtual bool UsesClipsForAmmo2( void ) const; - bool IsMeleeWeapon() const; - - // derive this function if you mod uses encrypted weapon info files - virtual const unsigned char *GetEncryptionKey( void ); - - virtual int GetPrimaryAmmoType( void ) const { return m_iPrimaryAmmoType; } - virtual int GetSecondaryAmmoType( void ) const { return m_iSecondaryAmmoType; } - int Clip1() const { return m_iClip1; } - int Clip2() const { return m_iClip2; } - - // Ammo quantity queries for weapons that do not use clips. These are only - // used to determine how much ammo is in a weapon that does not have an owner. - // That is, a weapon that's on the ground for the player to get ammo out of. - int GetPrimaryAmmoCount() { return m_iPrimaryAmmoCount; } - void SetPrimaryAmmoCount( int count ) { m_iPrimaryAmmoCount = count; } - - int GetSecondaryAmmoCount() { return m_iSecondaryAmmoCount; } - void SetSecondaryAmmoCount( int count ) { m_iSecondaryAmmoCount = count; } - - virtual CHudTexture const *GetSpriteActive( void ) const; - virtual CHudTexture const *GetSpriteInactive( void ) const; - virtual CHudTexture const *GetSpriteAmmo( void ) const; - virtual CHudTexture const *GetSpriteAmmo2( void ) const; - virtual CHudTexture const *GetSpriteCrosshair( void ) const; - virtual CHudTexture const *GetSpriteAutoaim( void ) const; - virtual CHudTexture const *GetSpriteZoomedCrosshair( void ) const; - virtual CHudTexture const *GetSpriteZoomedAutoaim( void ) const; - - virtual Activity ActivityOverride( Activity baseAct, bool *pRequired ); - virtual acttable_t* ActivityList( void ) { return NULL; } - virtual int ActivityListCount( void ) { return 0; } - - virtual void Activate( void ); - -public: -// Server Only Methods -#if !defined( CLIENT_DLL ) - - DECLARE_DATADESC(); - virtual void FallInit( void ); // prepare to fall to the ground - virtual void FallThink( void ); // make the weapon fall to the ground after spawning - - // Weapon spawning - bool IsConstrained() { return m_pConstraint != NULL; } - bool IsInBadPosition ( void ); // Is weapon in bad position to pickup? - bool RepositionWeapon ( void ); // Attempts to reposition the weapon in a location where it can be - virtual void Materialize( void ); // make a weapon visible and tangible - void AttemptToMaterialize( void ); // see if the game rules will let the weapon become visible and tangible - virtual void CheckRespawn( void ); // see if this weapon should respawn after being picked up - CBaseEntity *Respawn ( void ); // copy a weapon - - static int GetAvailableWeaponsInBox( CBaseCombatWeapon **pList, int listMax, const Vector &mins, const Vector &maxs ); - - // Weapon dropping / destruction - virtual void Delete( void ); - void DestroyItem( void ); - virtual void Kill( void ); - - virtual int CapabilitiesGet( void ) { return 0; } - virtual int ObjectCaps( void ); - - bool IsRemoveable() { return m_bRemoveable; } - void SetRemoveable( bool bRemoveable ) { m_bRemoveable = bRemoveable; } - - // Returns bits for weapon conditions - virtual bool WeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions ); - virtual int WeaponRangeAttack1Condition( float flDot, float flDist ); - virtual int WeaponRangeAttack2Condition( float flDot, float flDist ); - virtual int WeaponMeleeAttack1Condition( float flDot, float flDist ); - virtual int WeaponMeleeAttack2Condition( float flDot, float flDist ); - - virtual void Operator_FrameUpdate( CBaseCombatCharacter *pOperator ); - virtual void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); - virtual void Operator_ForceNPCFire( CBaseCombatCharacter *pOperator, bool bSecondary ) { return; } - // NOTE: This should never be called when a character is operating the weapon. Animation events should be - // routed through the character, and then back into CharacterAnimEvent() - void HandleAnimEvent( animevent_t *pEvent ); - - virtual int UpdateTransmitState( void ); - - void InputHideWeapon( inputdata_t &inputdata ); - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - -// Client only methods -#else - - virtual void BoneMergeFastCullBloat( Vector &localMins, Vector &localMaxs, const Vector &thisEntityMins, const Vector &thisEntityMaxs ) const; - virtual bool OnFireEvent( C_BaseViewModel *pViewModel, const Vector& origin, const QAngle& angles, int event, const char *options ) { return false; } - - // Should this object cast shadows? - virtual ShadowType_t ShadowCastType(); - virtual void SetDormant( bool bDormant ); - virtual void OnDataChanged( DataUpdateType_t updateType ); - virtual void OnRestore(); - - virtual void Redraw(void); - virtual void ViewModelDrawn( CBaseViewModel *pViewModel ); - // Get the position that bullets are seen coming out. Note: the returned values are different - // for first person and third person. - bool GetShootPosition( Vector &vOrigin, QAngle &vAngles ); - virtual void DrawCrosshair( void ); - virtual bool ShouldDrawCrosshair( void ) { return true; } - - // Weapon state checking - virtual bool IsCarriedByLocalPlayer( void ); - virtual bool IsActiveByLocalPlayer( void ); - - bool IsBeingCarried() const; - - // Is the carrier alive? - bool IsCarrierAlive() const; - - // Returns the aiment render origin + angles - virtual int DrawModel( int flags ); - virtual bool ShouldDraw( void ); - virtual bool ShouldDrawPickup( void ); - virtual void HandleInput( void ) { return; }; - virtual void OverrideMouseInput( float *x, float *y ) { return; }; - virtual int KeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding ) { return 1; } - virtual bool AddLookShift( void ) { return true; }; - - virtual void GetViewmodelBoneControllers(C_BaseViewModel *pViewModel, float controllers[MAXSTUDIOBONECTRLS]) { return; } - - virtual void NotifyShouldTransmit( ShouldTransmitState_t state ); - WEAPON_FILE_INFO_HANDLE GetWeaponFileInfoHandle() { return m_hWeaponFileInfo; } - - virtual int GetWorldModelIndex( void ); - - virtual void GetToolRecordingState( KeyValues *msg ); - void EnsureCorrectRenderingModel(); - -#if !defined USES_PERSISTENT_ITEMS - // Viewmodel overriding - virtual bool ViewModel_IsTransparent( void ) { return IsTransparent(); } - virtual bool IsOverridingViewmodel( void ) { return false; }; - virtual int DrawOverriddenViewmodel( C_BaseViewModel *pViewmodel, int flags ) { return 0; }; - bool WantsToOverrideViewmodelAttachments( void ) { return false; } -#endif - -#endif // End client-only methods - - virtual bool CanLower( void ) { return false; } - virtual bool Ready( void ) { return false; } - virtual bool Lower( void ) { return false; } - - virtual void HideThink( void ); - -private: - typedef CHandle< CBaseCombatCharacter > CBaseCombatCharacterHandle; - CNetworkVar( CBaseCombatCharacterHandle, m_hOwner ); // Player carrying this weapon - -protected: - -public: - - // Networked fields - CNetworkVar( int, m_nViewModelIndex ); - - // Weapon firing - CNetworkVar( float, m_flNextPrimaryAttack ); // soonest time ItemPostFrame will call PrimaryAttack - CNetworkVar( float, m_flNextSecondaryAttack ); // soonest time ItemPostFrame will call SecondaryAttack - CNetworkVar( float, m_flTimeWeaponIdle ); // soonest time ItemPostFrame will call WeaponIdle - // Weapon state - bool m_bInReload; // Are we in the middle of a reload; - bool m_bFireOnEmpty; // True when the gun is empty and the player is still holding down the attack key(s) - // Weapon art - CNetworkVar( int, m_iViewModelIndex ); - CNetworkVar( int, m_iWorldModelIndex ); - // Sounds - float m_flNextEmptySoundTime; // delay on empty sound playing - - Activity GetIdealActivity( void ) { return m_IdealActivity; } - int GetIdealSequence( void ) { return m_nIdealSequence; } - - bool SetIdealActivity( Activity ideal ); - void MaintainIdealActivity( void ); - -private: - Activity m_Activity; - int m_nIdealSequence; - Activity m_IdealActivity; - - bool m_bRemoveable; - - int m_iPrimaryAmmoCount; - int m_iSecondaryAmmoCount; - -public: - - IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_nNextThinkTick ); - - int WeaponState() const { return m_iState; } - - // Weapon data - CNetworkVar( int, m_iState ); // See WEAPON_* definition - string_t m_iszName; // Classname of this weapon. - CNetworkVar( int, m_iPrimaryAmmoType ); // "primary" ammo index into the ammo info array - CNetworkVar( int, m_iSecondaryAmmoType ); // "secondary" ammo index into the ammo info array - CNetworkVar( int, m_iClip1 ); // number of shots left in the primary weapon clip, -1 it not used - CNetworkVar( int, m_iClip2 ); // number of shots left in the secondary weapon clip, -1 it not used - bool m_bFiresUnderwater; // true if this weapon can fire underwater - bool m_bAltFiresUnderwater; // true if this weapon can fire underwater - float m_fMinRange1; // What's the closest this weapon can be used? - float m_fMinRange2; // What's the closest this weapon can be used? - float m_fMaxRange1; // What's the furthest this weapon can be used? - float m_fMaxRange2; // What's the furthest this weapon can be used? - bool m_bReloadsSingly; // Tryue if this weapon reloads 1 round at a time - float m_fFireDuration; // The amount of time that the weapon has sustained firing - int m_iSubType; - - float m_flUnlockTime; - EHANDLE m_hLocker; // Who locked this weapon. - -#if defined(CSTRIKE_DLL) && defined(CLIENT_DLL) - bool m_bInReloadAnimation; -#endif - - IPhysicsConstraint *GetConstraint() { return m_pConstraint; } - -private: - WEAPON_FILE_INFO_HANDLE m_hWeaponFileInfo; - IPhysicsConstraint *m_pConstraint; - - int m_iAltFireHudHintCount; // How many times has this weapon displayed its alt-fire HUD hint? - int m_iReloadHudHintCount; // How many times has this weapon displayed its reload HUD hint? - bool m_bAltFireHudHintDisplayed; // Have we displayed an alt-fire HUD hint since this weapon was deployed? - bool m_bReloadHudHintDisplayed; // Have we displayed a reload HUD hint since this weapon was deployed? - float m_flHudHintPollTime; // When to poll the weapon again for whether it should display a hud hint. - float m_flHudHintMinDisplayTime; // if the hint is squelched before this, reset my counter so we'll display it again. - - // Server only -#if !defined( CLIENT_DLL ) - - // Outputs - COutputEvent m_OnPlayerUse; // Fired when the player uses the weapon. - COutputEvent m_OnPlayerPickup; // Fired when the player picks up the weapon. - COutputEvent m_OnNPCPickup; // Fired when an NPC picks up the weapon. - COutputEvent m_OnCacheInteraction; // For awarding lambda cache achievements in HL2 on 360. See .FGD file for details - -#else // Client .dll only - bool m_bJustRestored; - - // Allow weapons resource to access m_hWeaponFileInfo directly - friend class WeaponsResource; - -protected: - int m_iOldState; - -#endif // End Client .dll only -}; - -#endif // COMBATWEAPON_SHARED_H diff --git a/game/shared/baseentity_shared.cpp b/game/shared/baseentity_shared.cpp deleted file mode 100644 index 0e75ca54d..000000000 --- a/game/shared/baseentity_shared.cpp +++ /dev/null @@ -1,2434 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -#include "decals.h" -#include "effect_dispatch_data.h" -#include "model_types.h" -#include "gamestringpool.h" -#include "ammodef.h" -#include "takedamageinfo.h" -#include "shot_manipulator.h" -#include "ai_debug_shared.h" -#include "mapentities_shared.h" -#include "debugoverlay_shared.h" -#include "coordsize.h" - -#ifdef CLIENT_DLL - #include "c_te_effect_dispatch.h" -#else - #include "te_effect_dispatch.h" - #include "soundent.h" - #include "iservervehicle.h" - #include "player_pickup.h" - #include "waterbullet.h" - #include "func_break.h" - -#ifdef HL2MP - #include "te_hl2mp_shotgun_shot.h" -#endif - - #include "GameStats.h" - -#endif - -#ifdef HL2_EPISODIC -ConVar hl2_episodic( "hl2_episodic", "1", FCVAR_REPLICATED ); -#else -ConVar hl2_episodic( "hl2_episodic", "0", FCVAR_REPLICATED ); -#endif//HL2_EPISODIC - -#ifdef PORTAL - #include "prop_portal_shared.h" -#endif - -#include "rumble_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#ifdef GAME_DLL - ConVar ent_debugkeys( "ent_debugkeys", "" ); - extern bool ParseKeyvalue( void *pObject, typedescription_t *pFields, int iNumFields, const char *szKeyName, const char *szValue ); - extern bool ExtractKeyvalue( void *pObject, typedescription_t *pFields, int iNumFields, const char *szKeyName, char *szValue, int iMaxLen ); -#endif - -bool CBaseEntity::m_bAllowPrecache = false; - - -ConVar ai_shot_bias_min( "ai_shot_bias_min", "-1.0", FCVAR_REPLICATED ); -ConVar ai_shot_bias_max( "ai_shot_bias_max", "1.0", FCVAR_REPLICATED ); -ConVar ai_debug_shoot_positions( "ai_debug_shoot_positions", "0", FCVAR_REPLICATED | FCVAR_CHEAT ); - - -//----------------------------------------------------------------------------- -// Purpose: Spawn some blood particles -//----------------------------------------------------------------------------- -void SpawnBlood(Vector vecSpot, const Vector &vecDir, int bloodColor, float flDamage) -{ - UTIL_BloodDrips( vecSpot, vecDir, bloodColor, (int)flDamage ); -} - -#if !defined( NO_ENTITY_PREDICTION ) -//----------------------------------------------------------------------------- -// The player drives simulation of this entity -//----------------------------------------------------------------------------- -void CBaseEntity::SetPlayerSimulated( CBasePlayer *pOwner ) -{ - m_bIsPlayerSimulated = true; - pOwner->AddToPlayerSimulationList( this ); - m_hPlayerSimulationOwner = pOwner; -} - -void CBaseEntity::UnsetPlayerSimulated( void ) -{ - if ( m_hPlayerSimulationOwner != NULL ) - { - m_hPlayerSimulationOwner->RemoveFromPlayerSimulationList( this ); - } - m_hPlayerSimulationOwner = NULL; - m_bIsPlayerSimulated = false; -} -#endif - -// position of eyes -Vector CBaseEntity::EyePosition( void ) -{ - return GetAbsOrigin() + m_vecViewOffset; -} - -const QAngle &CBaseEntity::EyeAngles( void ) -{ - return GetAbsAngles(); -} - -const QAngle &CBaseEntity::LocalEyeAngles( void ) -{ - return GetLocalAngles(); -} - -// position of ears -Vector CBaseEntity::EarPosition( void ) -{ - return EyePosition( ); -} - - -//----------------------------------------------------------------------------- -// center point of entity -//----------------------------------------------------------------------------- -const Vector &CBaseEntity::WorldSpaceCenter( ) const -{ - return CollisionProp()->WorldSpaceCenter(); -} - -#if !defined( CLIENT_DLL ) -#define CHANGE_FLAGS(flags,newFlags) { unsigned int old = flags; flags = (newFlags); gEntList.ReportEntityFlagsChanged( this, old, flags ); } -#else -#define CHANGE_FLAGS(flags,newFlags) (flags = (newFlags)) -#endif - -void CBaseEntity::AddFlag( int flags ) -{ - CHANGE_FLAGS( m_fFlags, m_fFlags | flags ); -} - -void CBaseEntity::RemoveFlag( int flagsToRemove ) -{ - CHANGE_FLAGS( m_fFlags, m_fFlags & ~flagsToRemove ); -} - -void CBaseEntity::ClearFlags( void ) -{ - CHANGE_FLAGS( m_fFlags, 0 ); -} - -void CBaseEntity::ToggleFlag( int flagToToggle ) -{ - CHANGE_FLAGS( m_fFlags, m_fFlags ^ flagToToggle ); -} - -void CBaseEntity::SetEffects( int nEffects ) -{ - if ( nEffects != m_fEffects ) - { -#if !defined( CLIENT_DLL ) -#ifdef HL2_EPISODIC - // Hack for now, to avoid player emitting radius with his flashlight - if ( !IsPlayer() ) - { - if ( (nEffects & (EF_BRIGHTLIGHT|EF_DIMLIGHT)) && !(m_fEffects & (EF_BRIGHTLIGHT|EF_DIMLIGHT)) ) - { - AddEntityToDarknessCheck( this ); - } - else if ( !(nEffects & (EF_BRIGHTLIGHT|EF_DIMLIGHT)) && (m_fEffects & (EF_BRIGHTLIGHT|EF_DIMLIGHT)) ) - { - RemoveEntityFromDarknessCheck( this ); - } - } -#endif // HL2_EPISODIC -#endif // !CLIENT_DLL - - m_fEffects = nEffects; - -#if !defined( CLIENT_DLL ) - if ( nEffects & ( EF_NOINTERP ) ) - { - gEntList.AddPostClientMessageEntity( this ); - } -#endif - - if ( ( nEffects & EF_NOINTERP ) && IsPlayer() ) - { - ((CBasePlayer *)this)->IncrementEFNoInterpParity(); - } - -#ifndef CLIENT_DLL - DispatchUpdateTransmitState(); -#else - UpdateVisibility(); -#endif - } -} - -void CBaseEntity::AddEffects( int nEffects ) -{ -#if !defined( CLIENT_DLL ) -#ifdef HL2_EPISODIC - if ( (nEffects & (EF_BRIGHTLIGHT|EF_DIMLIGHT)) && !(m_fEffects & (EF_BRIGHTLIGHT|EF_DIMLIGHT)) ) - { - // Hack for now, to avoid player emitting radius with his flashlight - if ( !IsPlayer() ) - { - AddEntityToDarknessCheck( this ); - } - } -#endif // HL2_EPISODIC -#endif // !CLIENT_DLL - - m_fEffects |= nEffects; -#if !defined( CLIENT_DLL ) - if ( nEffects & ( EF_NOINTERP ) ) - { - gEntList.AddPostClientMessageEntity( this ); - } -#endif - - - if ( nEffects & EF_NODRAW) - { -#ifndef CLIENT_DLL - DispatchUpdateTransmitState(); -#else - UpdateVisibility(); -#endif - } -} - -void CBaseEntity::SetBlocksLOS( bool bBlocksLOS ) -{ - if ( bBlocksLOS ) - { - RemoveEFlags( EFL_DONTBLOCKLOS ); - } - else - { - AddEFlags( EFL_DONTBLOCKLOS ); - } -} - -bool CBaseEntity::BlocksLOS( void ) -{ - return !IsEFlagSet(EFL_DONTBLOCKLOS); -} - -void CBaseEntity::SetAIWalkable( bool bBlocksLOS ) -{ - if ( bBlocksLOS ) - { - RemoveEFlags( EFL_DONTWALKON ); - } - else - { - AddEFlags( EFL_DONTWALKON ); - } -} - -bool CBaseEntity::IsAIWalkable( void ) -{ - return !IsEFlagSet(EFL_DONTWALKON); -} - - -//----------------------------------------------------------------------------- -// Purpose: Handles keys and outputs from the BSP. -// Input : mapData - Text block of keys and values from the BSP. -//----------------------------------------------------------------------------- -void CBaseEntity::ParseMapData( CEntityMapData *mapData ) -{ - char keyName[MAPKEY_MAXLENGTH]; - char value[MAPKEY_MAXLENGTH]; - - #ifdef _DEBUG - #ifdef GAME_DLL - ValidateDataDescription(); - #endif // GAME_DLL - #endif // _DEBUG - - // loop through all keys in the data block and pass the info back into the object - if ( mapData->GetFirstKey(keyName, value) ) - { - do - { - KeyValue( keyName, value ); - } - while ( mapData->GetNextKey(keyName, value) ); - } -} - -//----------------------------------------------------------------------------- -// Parse data from a map file -//----------------------------------------------------------------------------- -bool CBaseEntity::KeyValue( const char *szKeyName, const char *szValue ) -{ - //!! temp hack, until worldcraft is fixed - // strip the # tokens from (duplicate) key names - char *s = (char *)strchr( szKeyName, '#' ); - if ( s ) - { - *s = '\0'; - } - - if ( FStrEq( szKeyName, "rendercolor" ) || FStrEq( szKeyName, "rendercolor32" )) - { - color32 tmp; - UTIL_StringToColor32( &tmp, szValue ); - SetRenderColor( tmp.r, tmp.g, tmp.b ); - // don't copy alpha, legacy support uses renderamt - return true; - } - - if ( FStrEq( szKeyName, "renderamt" ) ) - { - SetRenderColorA( atoi( szValue ) ); - return true; - } - - if ( FStrEq( szKeyName, "disableshadows" )) - { - int val = atoi( szValue ); - if (val) - { - AddEffects( EF_NOSHADOW ); - } - return true; - } - - if ( FStrEq( szKeyName, "mins" )) - { - Vector mins; - UTIL_StringToVector( mins.Base(), szValue ); - CollisionProp()->SetCollisionBounds( mins, CollisionProp()->OBBMaxs() ); - return true; - } - - if ( FStrEq( szKeyName, "maxs" )) - { - Vector maxs; - UTIL_StringToVector( maxs.Base(), szValue ); - CollisionProp()->SetCollisionBounds( CollisionProp()->OBBMins(), maxs ); - return true; - } - - if ( FStrEq( szKeyName, "disablereceiveshadows" )) - { - int val = atoi( szValue ); - if (val) - { - AddEffects( EF_NORECEIVESHADOW ); - } - return true; - } - - if ( FStrEq( szKeyName, "nodamageforces" )) - { - int val = atoi( szValue ); - if (val) - { - AddEFlags( EFL_NO_DAMAGE_FORCES ); - } - return true; - } - - // Fix up single angles - if( FStrEq( szKeyName, "angle" ) ) - { - static char szBuf[64]; - - float y = atof( szValue ); - if (y >= 0) - { - Q_snprintf( szBuf,sizeof(szBuf), "%f %f %f", GetLocalAngles()[0], y, GetLocalAngles()[2] ); - } - else if ((int)y == -1) - { - Q_strncpy( szBuf, "-90 0 0", sizeof(szBuf) ); - } - else - { - Q_strncpy( szBuf, "90 0 0", sizeof(szBuf) ); - } - - // Do this so inherited classes looking for 'angles' don't have to bother with 'angle' - return KeyValue( szKeyName, szBuf ); - } - - // NOTE: Have to do these separate because they set two values instead of one - if( FStrEq( szKeyName, "angles" ) ) - { - QAngle angles; - UTIL_StringToVector( angles.Base(), szValue ); - - // If you're hitting this assert, it's probably because you're - // calling SetLocalAngles from within a KeyValues method.. use SetAbsAngles instead! - Assert( (GetMoveParent() == NULL) && !IsEFlagSet( EFL_DIRTY_ABSTRANSFORM ) ); - SetAbsAngles( angles ); - return true; - } - - if( FStrEq( szKeyName, "origin" ) ) - { - Vector vecOrigin; - UTIL_StringToVector( vecOrigin.Base(), szValue ); - - // If you're hitting this assert, it's probably because you're - // calling SetLocalOrigin from within a KeyValues method.. use SetAbsOrigin instead! - Assert( (GetMoveParent() == NULL) && !IsEFlagSet( EFL_DIRTY_ABSTRANSFORM ) ); - SetAbsOrigin( vecOrigin ); - return true; - } - -#ifdef GAME_DLL - - if ( FStrEq( szKeyName, "targetname" ) ) - { - m_iName = AllocPooledString( szValue ); - return true; - } - - // loop through the data description, and try and place the keys in - if ( !*ent_debugkeys.GetString() ) - { - for ( datamap_t *dmap = GetDataDescMap(); dmap != NULL; dmap = dmap->baseMap ) - { - if ( ::ParseKeyvalue(this, dmap->dataDesc, dmap->dataNumFields, szKeyName, szValue) ) - return true; - } - } - else - { - // debug version - can be used to see what keys have been parsed in - bool printKeyHits = false; - const char *debugName = ""; - - if ( *ent_debugkeys.GetString() && !Q_stricmp(ent_debugkeys.GetString(), STRING(m_iClassname)) ) - { - // Msg( "-- found entity of type %s\n", STRING(m_iClassname) ); - printKeyHits = true; - debugName = STRING(m_iClassname); - } - - // loop through the data description, and try and place the keys in - for ( datamap_t *dmap = GetDataDescMap(); dmap != NULL; dmap = dmap->baseMap ) - { - if ( !printKeyHits && *ent_debugkeys.GetString() && !Q_stricmp(dmap->dataClassName, ent_debugkeys.GetString()) ) - { - // Msg( "-- found class of type %s\n", dmap->dataClassName ); - printKeyHits = true; - debugName = dmap->dataClassName; - } - - if ( ::ParseKeyvalue(this, dmap->dataDesc, dmap->dataNumFields, szKeyName, szValue) ) - { - if ( printKeyHits ) - Msg( "(%s) key: %-16s value: %s\n", debugName, szKeyName, szValue ); - - return true; - } - } - - if ( printKeyHits ) - Msg( "!! (%s) key not handled: \"%s\" \"%s\"\n", STRING(m_iClassname), szKeyName, szValue ); - } - -#endif - - // key hasn't been handled - return false; -} - -bool CBaseEntity::KeyValue( const char *szKeyName, float flValue ) -{ - char string[256]; - - Q_snprintf(string,sizeof(string), "%f", flValue ); - - return KeyValue( szKeyName, string ); -} - -bool CBaseEntity::KeyValue( const char *szKeyName, const Vector &vecValue ) -{ - char string[256]; - - Q_snprintf(string,sizeof(string), "%f %f %f", vecValue.x, vecValue.y, vecValue.z ); - - return KeyValue( szKeyName, string ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- - -bool CBaseEntity::GetKeyValue( const char *szKeyName, char *szValue, int iMaxLen ) -{ - if ( FStrEq( szKeyName, "rendercolor" ) || FStrEq( szKeyName, "rendercolor32" )) - { - color32 tmp = GetRenderColor(); - Q_snprintf( szValue, iMaxLen, "%d %d %d %d", tmp.r, tmp.g, tmp.b, tmp.a ); - return true; - } - - if ( FStrEq( szKeyName, "renderamt" ) ) - { - color32 tmp = GetRenderColor(); - Q_snprintf( szValue, iMaxLen, "%d", tmp.a ); - return true; - } - - if ( FStrEq( szKeyName, "disableshadows" )) - { - Q_snprintf( szValue, iMaxLen, "%d", IsEffectActive( EF_NOSHADOW ) ); - return true; - } - - if ( FStrEq( szKeyName, "mins" )) - { - Assert( 0 ); - return false; - } - - if ( FStrEq( szKeyName, "maxs" )) - { - Assert( 0 ); - return false; - } - - if ( FStrEq( szKeyName, "disablereceiveshadows" )) - { - Q_snprintf( szValue, iMaxLen, "%d", IsEffectActive( EF_NORECEIVESHADOW ) ); - return true; - } - - if ( FStrEq( szKeyName, "nodamageforces" )) - { - Q_snprintf( szValue, iMaxLen, "%d", IsEffectActive( EFL_NO_DAMAGE_FORCES ) ); - return true; - } - - // Fix up single angles - if( FStrEq( szKeyName, "angle" ) ) - { - return false; - } - - // NOTE: Have to do these separate because they set two values instead of one - if( FStrEq( szKeyName, "angles" ) ) - { - QAngle angles = GetAbsAngles(); - - Q_snprintf( szValue, iMaxLen, "%f %f %f", angles.x, angles.y, angles.z ); - return true; - } - - if( FStrEq( szKeyName, "origin" ) ) - { - Vector vecOrigin = GetAbsOrigin(); - Q_snprintf( szValue, iMaxLen, "%f %f %f", vecOrigin.x, vecOrigin.y, vecOrigin.z ); - return true; - } - -#ifdef GAME_DLL - - if ( FStrEq( szKeyName, "targetname" ) ) - { - Q_snprintf( szValue, iMaxLen, "%s", STRING( GetEntityName() ) ); - return true; - } - - if ( FStrEq( szKeyName, "classname" ) ) - { - Q_snprintf( szValue, iMaxLen, "%s", GetClassname() ); - return true; - } - - for ( datamap_t *dmap = GetDataDescMap(); dmap != NULL; dmap = dmap->baseMap ) - { - if ( ::ExtractKeyvalue( this, dmap->dataDesc, dmap->dataNumFields, szKeyName, szValue, iMaxLen ) ) - return true; - } -#endif - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : collisionGroup - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseEntity::ShouldCollide( int collisionGroup, int contentsMask ) const -{ - if ( m_CollisionGroup == COLLISION_GROUP_DEBRIS ) - { - if ( ! (contentsMask & CONTENTS_DEBRIS) ) - return false; - } - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : seed - -//----------------------------------------------------------------------------- -void CBaseEntity::SetPredictionRandomSeed( const CUserCmd *cmd ) -{ - if ( !cmd ) - { - m_nPredictionRandomSeed = -1; - return; - } - - m_nPredictionRandomSeed = ( cmd->random_seed ); -} - - -//------------------------------------------------------------------------------ -// Purpose : Base implimentation for entity handling decals -//------------------------------------------------------------------------------ -void CBaseEntity::DecalTrace( trace_t *pTrace, char const *decalName ) -{ - int index = decalsystem->GetDecalIndexForName( decalName ); - if ( index < 0 ) - return; - - Assert( pTrace->m_pEnt ); - - CBroadcastRecipientFilter filter; - te->Decal( filter, 0.0, &pTrace->endpos, &pTrace->startpos, - pTrace->GetEntityIndex(), pTrace->hitbox, index ); -} - -//----------------------------------------------------------------------------- -// Purpose: Base handling for impacts against entities -//----------------------------------------------------------------------------- -void CBaseEntity::ImpactTrace( trace_t *pTrace, int iDamageType, const char *pCustomImpactName ) -{ - VPROF( "CBaseEntity::ImpactTrace" ); - Assert( pTrace->m_pEnt ); - - CBaseEntity *pEntity = pTrace->m_pEnt; - - // Build the impact data - CEffectData data; - data.m_vOrigin = pTrace->endpos; - data.m_vStart = pTrace->startpos; - data.m_nSurfaceProp = pTrace->surface.surfaceProps; - data.m_nDamageType = iDamageType; - data.m_nHitBox = pTrace->hitbox; -#ifdef CLIENT_DLL - data.m_hEntity = ClientEntityList().EntIndexToHandle( pEntity->entindex() ); -#else - data.m_nEntIndex = pEntity->entindex(); -#endif - - // Send it on its way - if ( !pCustomImpactName ) - { - DispatchEffect( "Impact", data ); - } - else - { - DispatchEffect( pCustomImpactName, data ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: returns the damage decal to use, given a damage type -// Input : bitsDamageType - the damage type -// Output : the index of the damage decal to use -//----------------------------------------------------------------------------- -char const *CBaseEntity::DamageDecal( int bitsDamageType, int gameMaterial ) -{ - if ( m_nRenderMode == kRenderTransAlpha ) - return ""; - - if ( m_nRenderMode != kRenderNormal && gameMaterial == 'G' ) - return "BulletProof"; - - if ( bitsDamageType == DMG_SLASH ) - return "ManhackCut"; - - // This will get translated at a lower layer based on game material - return "Impact.Concrete"; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBaseEntity::GetIndexForThinkContext( const char *pszContext ) -{ - for ( int i = 0; i < m_aThinkFunctions.Size(); i++ ) - { - if ( !Q_strncmp( STRING( m_aThinkFunctions[i].m_iszContext ), pszContext, MAX_CONTEXT_LENGTH ) ) - return i; - } - - return NO_THINK_CONTEXT; -} - -//----------------------------------------------------------------------------- -// Purpose: Get a fresh think context for this entity -//----------------------------------------------------------------------------- -int CBaseEntity::RegisterThinkContext( const char *szContext ) -{ - int iIndex = GetIndexForThinkContext( szContext ); - if ( iIndex != NO_THINK_CONTEXT ) - return iIndex; - - // Make a new think func - thinkfunc_t sNewFunc; - Q_memset( &sNewFunc, 0, sizeof( sNewFunc ) ); - sNewFunc.m_pfnThink = NULL; - sNewFunc.m_nNextThinkTick = 0; - sNewFunc.m_iszContext = AllocPooledString(szContext); - - // Insert it into our list - return m_aThinkFunctions.AddToTail( sNewFunc ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -BASEPTR CBaseEntity::ThinkSet( BASEPTR func, float thinkTime, const char *szContext ) -{ -#if !defined( CLIENT_DLL ) -#ifdef _DEBUG - COMPILE_TIME_ASSERT( sizeof(func) == MFP_SIZE ); -#endif -#endif - - // Old system? - if ( !szContext ) - { - m_pfnThink = func; -#if !defined( CLIENT_DLL ) -#ifdef _DEBUG - FunctionCheck( *(reinterpret_cast(&m_pfnThink)), "BaseThinkFunc" ); -#endif -#endif - return m_pfnThink; - } - - // Find the think function in our list, and if we couldn't find it, register it - int iIndex = GetIndexForThinkContext( szContext ); - if ( iIndex == NO_THINK_CONTEXT ) - { - iIndex = RegisterThinkContext( szContext ); - } - - m_aThinkFunctions[ iIndex ].m_pfnThink = func; -#if !defined( CLIENT_DLL ) -#ifdef _DEBUG - FunctionCheck( *(reinterpret_cast(&m_aThinkFunctions[ iIndex ].m_pfnThink)), szContext ); -#endif -#endif - - if ( thinkTime != 0 ) - { - int thinkTick = ( thinkTime == TICK_NEVER_THINK ) ? TICK_NEVER_THINK : TIME_TO_TICKS( thinkTime ); - m_aThinkFunctions[ iIndex ].m_nNextThinkTick = thinkTick; - CheckHasThinkFunction( thinkTick == TICK_NEVER_THINK ? false : true ); - } - return func; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseEntity::SetNextThink( float thinkTime, const char *szContext ) -{ - int thinkTick = ( thinkTime == TICK_NEVER_THINK ) ? TICK_NEVER_THINK : TIME_TO_TICKS( thinkTime ); - - // Are we currently in a think function with a context? - int iIndex = 0; - if ( !szContext ) - { -#ifdef _DEBUG - if ( m_iCurrentThinkContext != NO_THINK_CONTEXT ) - { - Msg( "Warning: Setting base think function within think context %s\n", STRING(m_aThinkFunctions[m_iCurrentThinkContext].m_iszContext) ); - } -#endif - - // Old system - m_nNextThinkTick = thinkTick; - CheckHasThinkFunction( thinkTick == TICK_NEVER_THINK ? false : true ); - return; - } - else - { - // Find the think function in our list, and if we couldn't find it, register it - iIndex = GetIndexForThinkContext( szContext ); - if ( iIndex == NO_THINK_CONTEXT ) - { - iIndex = RegisterThinkContext( szContext ); - } - } - - // Old system - m_aThinkFunctions[ iIndex ].m_nNextThinkTick = thinkTick; - CheckHasThinkFunction( thinkTick == TICK_NEVER_THINK ? false : true ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CBaseEntity::GetNextThink( const char *szContext ) -{ - // Are we currently in a think function with a context? - int iIndex = 0; - if ( !szContext ) - { -#ifdef _DEBUG - if ( m_iCurrentThinkContext != NO_THINK_CONTEXT ) - { - Msg( "Warning: Getting base nextthink time within think context %s\n", STRING(m_aThinkFunctions[m_iCurrentThinkContext].m_iszContext) ); - } -#endif - - if ( m_nNextThinkTick == TICK_NEVER_THINK ) - return TICK_NEVER_THINK; - - // Old system - return TICK_INTERVAL * (m_nNextThinkTick ); - } - else - { - // Find the think function in our list - iIndex = GetIndexForThinkContext( szContext ); - } - - if ( iIndex == m_aThinkFunctions.InvalidIndex() ) - return TICK_NEVER_THINK; - - if ( m_aThinkFunctions[ iIndex ].m_nNextThinkTick == TICK_NEVER_THINK ) - { - return TICK_NEVER_THINK; - } - return TICK_INTERVAL * (m_aThinkFunctions[ iIndex ].m_nNextThinkTick ); -} - -int CBaseEntity::GetNextThinkTick( const char *szContext /*= NULL*/ ) -{ - // Are we currently in a think function with a context? - int iIndex = 0; - if ( !szContext ) - { -#ifdef _DEBUG - if ( m_iCurrentThinkContext != NO_THINK_CONTEXT ) - { - Msg( "Warning: Getting base nextthink time within think context %s\n", STRING(m_aThinkFunctions[m_iCurrentThinkContext].m_iszContext) ); - } -#endif - - if ( m_nNextThinkTick == TICK_NEVER_THINK ) - return TICK_NEVER_THINK; - - // Old system - return m_nNextThinkTick; - } - else - { - // Find the think function in our list - iIndex = GetIndexForThinkContext( szContext ); - - // Looking up an invalid think context! - Assert( iIndex != -1 ); - } - - if ( ( iIndex == -1 ) || ( m_aThinkFunctions[ iIndex ].m_nNextThinkTick == TICK_NEVER_THINK ) ) - { - return TICK_NEVER_THINK; - } - - return m_aThinkFunctions[ iIndex ].m_nNextThinkTick; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CBaseEntity::GetLastThink( const char *szContext ) -{ - // Are we currently in a think function with a context? - int iIndex = 0; - if ( !szContext ) - { -#ifdef _DEBUG - if ( m_iCurrentThinkContext != NO_THINK_CONTEXT ) - { - Msg( "Warning: Getting base lastthink time within think context %s\n", STRING(m_aThinkFunctions[m_iCurrentThinkContext].m_iszContext) ); - } -#endif - // Old system - return m_nLastThinkTick * TICK_INTERVAL; - } - else - { - // Find the think function in our list - iIndex = GetIndexForThinkContext( szContext ); - } - - return m_aThinkFunctions[ iIndex ].m_nLastThinkTick * TICK_INTERVAL; -} - -int CBaseEntity::GetLastThinkTick( const char *szContext /*= NULL*/ ) -{ - // Are we currently in a think function with a context? - int iIndex = 0; - if ( !szContext ) - { -#ifdef _DEBUG - if ( m_iCurrentThinkContext != NO_THINK_CONTEXT ) - { - Msg( "Warning: Getting base lastthink time within think context %s\n", STRING(m_aThinkFunctions[m_iCurrentThinkContext].m_iszContext) ); - } -#endif - // Old system - return m_nLastThinkTick; - } - else - { - // Find the think function in our list - iIndex = GetIndexForThinkContext( szContext ); - } - - return m_aThinkFunctions[ iIndex ].m_nLastThinkTick; -} - -bool CBaseEntity::WillThink() -{ - if ( m_nNextThinkTick > 0 ) - return true; - - for ( int i = 0; i < m_aThinkFunctions.Count(); i++ ) - { - if ( m_aThinkFunctions[i].m_nNextThinkTick > 0 ) - return true; - } - - return false; -} - -// returns the first tick the entity will run any think function -// returns TICK_NEVER_THINK if no think functions are scheduled -int CBaseEntity::GetFirstThinkTick() -{ - int minTick = TICK_NEVER_THINK; - if ( m_nNextThinkTick > 0 ) - { - minTick = m_nNextThinkTick; - } - - for ( int i = 0; i < m_aThinkFunctions.Count(); i++ ) - { - int next = m_aThinkFunctions[i].m_nNextThinkTick; - if ( next > 0 ) - { - if ( next < minTick || minTick == TICK_NEVER_THINK ) - { - minTick = next; - } - } - } - return minTick; -} - -// NOTE: pass in the isThinking hint so we have to search the think functions less -void CBaseEntity::CheckHasThinkFunction( bool isThinking ) -{ - if ( IsEFlagSet( EFL_NO_THINK_FUNCTION ) && isThinking ) - { - RemoveEFlags( EFL_NO_THINK_FUNCTION ); - } - else if ( !isThinking && !IsEFlagSet( EFL_NO_THINK_FUNCTION ) && !WillThink() ) - { - AddEFlags( EFL_NO_THINK_FUNCTION ); - } -#if !defined( CLIENT_DLL ) - SimThink_EntityChanged( this ); -#endif -} - -bool CBaseEntity::WillSimulateGamePhysics() -{ - // players always simulate game physics - if ( !IsPlayer() ) - { - MoveType_t movetype = GetMoveType(); - - if ( movetype == MOVETYPE_NONE || movetype == MOVETYPE_VPHYSICS ) - return false; - -#if !defined( CLIENT_DLL ) - // MOVETYPE_PUSH not supported on the client - if ( movetype == MOVETYPE_PUSH && GetMoveDoneTime() <= 0 ) - return false; -#endif - } - - return true; -} - -void CBaseEntity::CheckHasGamePhysicsSimulation() -{ - bool isSimulating = WillSimulateGamePhysics(); - if ( isSimulating != IsEFlagSet(EFL_NO_GAME_PHYSICS_SIMULATION) ) - return; - if ( isSimulating ) - { - RemoveEFlags( EFL_NO_GAME_PHYSICS_SIMULATION ); - } - else - { - AddEFlags( EFL_NO_GAME_PHYSICS_SIMULATION ); - } -#if !defined( CLIENT_DLL ) - SimThink_EntityChanged( this ); -#endif -} - -//----------------------------------------------------------------------------- -// Sets/Gets the next think based on context index -//----------------------------------------------------------------------------- -void CBaseEntity::SetNextThink( int nContextIndex, float thinkTime ) -{ - int thinkTick = ( thinkTime == TICK_NEVER_THINK ) ? TICK_NEVER_THINK : TIME_TO_TICKS( thinkTime ); - - if (nContextIndex < 0) - { - SetNextThink( thinkTime ); - } - else - { - m_aThinkFunctions[nContextIndex].m_nNextThinkTick = thinkTick; - } - CheckHasThinkFunction( thinkTick == TICK_NEVER_THINK ? false : true ); -} - -void CBaseEntity::SetLastThink( int nContextIndex, float thinkTime ) -{ - int thinkTick = ( thinkTime == TICK_NEVER_THINK ) ? TICK_NEVER_THINK : TIME_TO_TICKS( thinkTime ); - - if (nContextIndex < 0) - { - m_nLastThinkTick = thinkTick; - } - else - { - m_aThinkFunctions[nContextIndex].m_nLastThinkTick = thinkTick; - } -} - -float CBaseEntity::GetNextThink( int nContextIndex ) const -{ - if (nContextIndex < 0) - return m_nNextThinkTick * TICK_INTERVAL; - - return m_aThinkFunctions[nContextIndex].m_nNextThinkTick * TICK_INTERVAL; -} - -int CBaseEntity::GetNextThinkTick( int nContextIndex ) const -{ - if (nContextIndex < 0) - return m_nNextThinkTick; - - return m_aThinkFunctions[nContextIndex].m_nNextThinkTick; -} - - -//----------------------------------------------------------------------------- -// Purpose: My physics object has been updated, react or extract data -//----------------------------------------------------------------------------- -void CBaseEntity::VPhysicsUpdate( IPhysicsObject *pPhysics ) -{ - switch( GetMoveType() ) - { - case MOVETYPE_VPHYSICS: - { - if ( GetMoveParent() ) - { - DevWarning("Updating physics on object in hierarchy %s!\n", GetClassname()); - return; - } - Vector origin; - QAngle angles; - - pPhysics->GetPosition( &origin, &angles ); - - if ( !IsFinite( angles.x ) || !IsFinite( angles.y ) || !IsFinite( angles.x ) ) - { - Msg( "Infinite angles from vphysics! (entity %s)\n", GetDebugName() ); - angles = vec3_angle; - } -#ifndef CLIENT_DLL - Vector prevOrigin = GetAbsOrigin(); -#endif - - if ( origin.IsValid() ) - { - SetAbsOrigin( origin ); - } - else - { - Msg( "Infinite origin from vphysics! (entity %s)\n", GetDebugName() ); - } - - for ( int i = 0; i < 3; ++i ) - { - angles[ i ] = AngleNormalize( angles[ i ] ); - } - SetAbsAngles( angles ); - - // Interactive debris converts back to debris when it comes to rest - if ( pPhysics->IsAsleep() && GetCollisionGroup() == COLLISION_GROUP_INTERACTIVE_DEBRIS ) - { - SetCollisionGroup( COLLISION_GROUP_DEBRIS ); - } - -#ifndef CLIENT_DLL - PhysicsTouchTriggers( &prevOrigin ); - PhysicsRelinkChildren(gpGlobals->frametime); -#endif - } - break; - - case MOVETYPE_STEP: - break; - - case MOVETYPE_PUSH: -#ifndef CLIENT_DLL - VPhysicsUpdatePusher( pPhysics ); -#endif - break; - - default: - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Init this object's physics as a static -//----------------------------------------------------------------------------- -IPhysicsObject *CBaseEntity::VPhysicsInitStatic( void ) -{ - if ( !VPhysicsInitSetup() ) - return NULL; - -#ifndef CLIENT_DLL - // If this entity has a move parent, it needs to be shadow, not static - if ( GetMoveParent() ) - { - // must be SOLID_VPHYSICS if in hierarchy to solve collisions correctly - if ( GetSolid() == SOLID_BSP && GetRootMoveParent()->GetSolid() != SOLID_BSP ) - { - SetSolid( SOLID_VPHYSICS ); - } - - return VPhysicsInitShadow( false, false ); - } -#endif - - // No physics - if ( GetSolid() == SOLID_NONE ) - return NULL; - - // create a static physics objct - IPhysicsObject *pPhysicsObject = NULL; - if ( GetSolid() == SOLID_BBOX ) - { - pPhysicsObject = PhysModelCreateBox( this, WorldAlignMins(), WorldAlignMaxs(), GetAbsOrigin(), true ); - } - else - { - pPhysicsObject = PhysModelCreateUnmoveable( this, GetModelIndex(), GetAbsOrigin(), GetAbsAngles() ); - } - VPhysicsSetObject( pPhysicsObject ); - return pPhysicsObject; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPhysics - -//----------------------------------------------------------------------------- -void CBaseEntity::VPhysicsSetObject( IPhysicsObject *pPhysics ) -{ - if ( m_pPhysicsObject && pPhysics ) - { - Warning( "Overwriting physics object for %s\n", GetClassname() ); - } - m_pPhysicsObject = pPhysics; - if ( pPhysics && !m_pPhysicsObject ) - { - CollisionRulesChanged(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseEntity::VPhysicsDestroyObject( void ) -{ - if ( m_pPhysicsObject ) - { -#ifndef CLIENT_DLL - PhysRemoveShadow( this ); -#endif - PhysDestroyObject( m_pPhysicsObject, this ); - m_pPhysicsObject = NULL; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseEntity::VPhysicsInitSetup() -{ -#ifndef CLIENT_DLL - // don't support logical ents - if ( !edict() || IsMarkedForDeletion() ) - return false; -#endif - - // If this entity already has a physics object, then it should have been deleted prior to making this call. - Assert(!m_pPhysicsObject); - VPhysicsDestroyObject(); - - // make sure absorigin / absangles are correct - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: This creates a normal vphysics simulated object -// physics alone determines where it goes (gravity, friction, etc) -// and the entity receives updates from vphysics. SetAbsOrigin(), etc do not affect the object! -//----------------------------------------------------------------------------- -IPhysicsObject *CBaseEntity::VPhysicsInitNormal( SolidType_t solidType, int nSolidFlags, bool createAsleep, solid_t *pSolid ) -{ - if ( !VPhysicsInitSetup() ) - return NULL; - - // NOTE: This has to occur before PhysModelCreate because that call will - // call back into ShouldCollide(), which uses solidtype for rules. - SetSolid( solidType ); - SetSolidFlags( nSolidFlags ); - - // No physics - if ( solidType == SOLID_NONE ) - { - return NULL; - } - - // create a normal physics object - IPhysicsObject *pPhysicsObject = PhysModelCreate( this, GetModelIndex(), GetAbsOrigin(), GetAbsAngles(), pSolid ); - if ( pPhysicsObject ) - { - VPhysicsSetObject( pPhysicsObject ); - SetMoveType( MOVETYPE_VPHYSICS ); - - if ( !createAsleep ) - { - pPhysicsObject->Wake(); - } - } - - return pPhysicsObject; -} - -// This creates a vphysics object with a shadow controller that follows the AI -IPhysicsObject *CBaseEntity::VPhysicsInitShadow( bool allowPhysicsMovement, bool allowPhysicsRotation, solid_t *pSolid ) -{ - if ( !VPhysicsInitSetup() ) - return NULL; - - // No physics - if ( GetSolid() == SOLID_NONE ) - return NULL; - - const Vector &origin = GetAbsOrigin(); - QAngle angles = GetAbsAngles(); - IPhysicsObject *pPhysicsObject = NULL; - - if ( GetSolid() == SOLID_BBOX ) - { - // adjust these so the game tracing epsilons match the physics minimum separation distance - // this will shrink the vphysics version of the model by the difference in epsilons - float radius = 0.25f - DIST_EPSILON; - Vector mins = WorldAlignMins() + Vector(radius, radius, radius); - Vector maxs = WorldAlignMaxs() - Vector(radius, radius, radius); - pPhysicsObject = PhysModelCreateBox( this, mins, maxs, origin, false ); - angles = vec3_angle; - } - else if ( GetSolid() == SOLID_OBB ) - { - pPhysicsObject = PhysModelCreateOBB( this, CollisionProp()->OBBMins(), CollisionProp()->OBBMaxs(), origin, angles, false ); - } - else - { - pPhysicsObject = PhysModelCreate( this, GetModelIndex(), origin, angles, pSolid ); - } - if ( !pPhysicsObject ) - return NULL; - - VPhysicsSetObject( pPhysicsObject ); - // UNDONE: Tune these speeds!!! - pPhysicsObject->SetShadow( 1e4, 1e4, allowPhysicsMovement, allowPhysicsRotation ); - pPhysicsObject->UpdateShadow( origin, angles, false, 0 ); - return pPhysicsObject; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseEntity::CreateVPhysics() -{ - return false; -} - -bool CBaseEntity::IsStandable() const -{ - if (GetSolidFlags() & FSOLID_NOT_STANDABLE) - return false; - - if ( GetSolid() == SOLID_BSP || GetSolid() == SOLID_VPHYSICS || GetSolid() == SOLID_BBOX ) - return true; - - return IsBSPModel( ); -} - -bool CBaseEntity::IsBSPModel() const -{ - if ( GetSolid() == SOLID_BSP ) - return true; - - const model_t *model = modelinfo->GetModel( GetModelIndex() ); - - if ( GetSolid() == SOLID_VPHYSICS && modelinfo->GetModelType( model ) == mod_brush ) - return true; - - return false; -} - - -//----------------------------------------------------------------------------- -// Invalidates the abs state of all children -//----------------------------------------------------------------------------- -void CBaseEntity::InvalidatePhysicsRecursive( int nChangeFlags ) -{ - // Main entry point for dirty flag setting for the 90% case - // 1) If the origin changes, then we have to update abstransform, Shadow projection, PVS, KD-tree, - // client-leaf system. - // 2) If the angles change, then we have to update abstransform, Shadow projection, - // shadow render-to-texture, client-leaf system, and surrounding bounds. - // Children have to additionally update absvelocity, KD-tree, and PVS. - // If the surrounding bounds actually update, when we also need to update the KD-tree and the PVS. - // 3) If it's due to attachment, then all children who are attached to an attachment point - // are assumed to have dirty origin + angles. - - // Other stuff: - // 1) Marking the surrounding bounds dirty will automatically mark KD tree + PVS dirty. - - int nDirtyFlags = 0; - - if ( nChangeFlags & VELOCITY_CHANGED ) - { - nDirtyFlags |= EFL_DIRTY_ABSVELOCITY; - } - - if ( nChangeFlags & POSITION_CHANGED ) - { - nDirtyFlags |= EFL_DIRTY_ABSTRANSFORM; - -#ifndef CLIENT_DLL - NetworkProp()->MarkPVSInformationDirty(); -#endif - - // NOTE: This will also mark shadow projection + client leaf dirty - CollisionProp()->MarkPartitionHandleDirty(); - } - - // NOTE: This has to be done after velocity + position are changed - // because we change the nChangeFlags for the child entities - if ( nChangeFlags & ANGLES_CHANGED ) - { - nDirtyFlags |= EFL_DIRTY_ABSTRANSFORM; - if ( CollisionProp()->DoesRotationInvalidateSurroundingBox() ) - { - // NOTE: This will handle the KD-tree, surrounding bounds, PVS - // render-to-texture shadow, shadow projection, and client leaf dirty - CollisionProp()->MarkSurroundingBoundsDirty(); - } - else - { -#ifdef CLIENT_DLL - MarkRenderHandleDirty(); - g_pClientShadowMgr->AddToDirtyShadowList( this ); - g_pClientShadowMgr->MarkRenderToTextureShadowDirty( GetShadowHandle() ); -#endif - } - - // This is going to be used for all children: children - // have position + velocity changed - nChangeFlags |= POSITION_CHANGED | VELOCITY_CHANGED; - } - - AddEFlags( nDirtyFlags ); - - // Set flags for children - bool bOnlyDueToAttachment = false; - if ( nChangeFlags & ANIMATION_CHANGED ) - { -#ifdef CLIENT_DLL - g_pClientShadowMgr->MarkRenderToTextureShadowDirty( GetShadowHandle() ); -#endif - - // Only set this flag if the only thing that changed us was the animation. - // If position or something else changed us, then we must tell all children. - if ( !( nChangeFlags & (POSITION_CHANGED | VELOCITY_CHANGED | ANGLES_CHANGED) ) ) - { - bOnlyDueToAttachment = true; - } - - nChangeFlags = POSITION_CHANGED | ANGLES_CHANGED | VELOCITY_CHANGED; - } - - for (CBaseEntity *pChild = FirstMoveChild(); pChild; pChild = pChild->NextMovePeer()) - { - // If this is due to the parent animating, only invalidate children that are parented to an attachment - // Entities that are following also access attachments points on parents and must be invalidated. - if ( bOnlyDueToAttachment ) - { -#ifdef CLIENT_DLL - if ( (pChild->GetParentAttachment() == 0) && !pChild->IsFollowingEntity() ) - continue; -#else - if ( pChild->GetParentAttachment() == 0 ) - continue; -#endif - } - pChild->InvalidatePhysicsRecursive( nChangeFlags ); - } - - // - // This code should really be in here, or the bone cache should not be in world space. - // Since the bone transforms are in world space, if we move or rotate the entity, its - // bones should be marked invalid. - // - // As it is, we're near ship, and don't have time to setup a good A/B test of how much - // overhead this fix would add. We've also only got one known case where the lack of - // this fix is screwing us, and I just fixed it, so I'm leaving this commented out for now. - // - // Hopefully, we'll put the bone cache in entity space and remove the need for this fix. - // - //#ifdef CLIENT_DLL - // if ( nChangeFlags & (POSITION_CHANGED | ANGLES_CHANGED | ANIMATION_CHANGED) ) - // { - // C_BaseAnimating *pAnim = GetBaseAnimating(); - // if ( pAnim ) - // pAnim->InvalidateBoneCache(); - // } - //#endif -} - - - -//----------------------------------------------------------------------------- -// Returns the highest parent of an entity -//----------------------------------------------------------------------------- -CBaseEntity *CBaseEntity::GetRootMoveParent() -{ - CBaseEntity *pEntity = this; - CBaseEntity *pParent = this->GetMoveParent(); - while ( pParent ) - { - pEntity = pParent; - pParent = pEntity->GetMoveParent(); - } - - return pEntity; -} - -//----------------------------------------------------------------------------- -// Purpose: static method -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseEntity::IsPrecacheAllowed() -{ - return m_bAllowPrecache; -} - -//----------------------------------------------------------------------------- -// Purpose: static method -// Input : allow - -//----------------------------------------------------------------------------- -void CBaseEntity::SetAllowPrecache( bool allow ) -{ - m_bAllowPrecache = allow; -} - -/* -================ -FireBullets - -Go to the trouble of combining multiple pellets into a single damage call. -================ -*/ - -#if defined( GAME_DLL ) -class CBulletsTraceFilter : public CTraceFilterSimpleList -{ -public: - CBulletsTraceFilter( int collisionGroup ) : CTraceFilterSimpleList( collisionGroup ) {} - - bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) - { - if ( m_PassEntities.Count() ) - { - CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); - CBaseEntity *pPassEntity = EntityFromEntityHandle( m_PassEntities[0] ); - if ( pEntity && pPassEntity && pEntity->GetOwnerEntity() == pPassEntity && - pPassEntity->IsSolidFlagSet(FSOLID_NOT_SOLID) && pPassEntity->IsSolidFlagSet( FSOLID_CUSTOMBOXTEST ) && - pPassEntity->IsSolidFlagSet( FSOLID_CUSTOMRAYTEST ) ) - { - // It's a bone follower of the entity to ignore (toml 8/3/2007) - return false; - } - } - return CTraceFilterSimpleList::ShouldHitEntity( pHandleEntity, contentsMask ); - } - -}; -#else -typedef CTraceFilterSimpleList CBulletsTraceFilter; -#endif - -void CBaseEntity::FireBullets( const FireBulletsInfo_t &info ) -{ - static int tracerCount; - trace_t tr; - CAmmoDef* pAmmoDef = GetAmmoDef(); - int nDamageType = pAmmoDef->DamageType(info.m_iAmmoType); - int nAmmoFlags = pAmmoDef->Flags(info.m_iAmmoType); - - bool bDoServerEffects = true; - -#if defined( HL2MP ) && defined( GAME_DLL ) - bDoServerEffects = false; -#endif - -#if defined( GAME_DLL ) - if( IsPlayer() ) - { - CBasePlayer *pPlayer = dynamic_cast(this); - - int rumbleEffect = pPlayer->GetActiveWeapon()->GetRumbleEffect(); - - if( rumbleEffect != RUMBLE_INVALID ) - { - if( rumbleEffect == RUMBLE_SHOTGUN_SINGLE ) - { - if( info.m_iShots == 12 ) - { - // Upgrade to double barrel rumble effect - rumbleEffect = RUMBLE_SHOTGUN_DOUBLE; - } - } - - pPlayer->RumbleEffect( rumbleEffect, 0, RUMBLE_FLAG_RESTART ); - } - } -#endif// GAME_DLL - - int iPlayerDamage = info.m_iPlayerDamage; - if ( iPlayerDamage == 0 ) - { - if ( nAmmoFlags & AMMO_INTERPRET_PLRDAMAGE_AS_DAMAGE_TO_PLAYER ) - { - iPlayerDamage = pAmmoDef->PlrDamage( info.m_iAmmoType ); - } - } - - // the default attacker is ourselves - CBaseEntity *pAttacker = info.m_pAttacker ? info.m_pAttacker : this; - - // Make sure we don't have a dangling damage target from a recursive call - if ( g_MultiDamage.GetTarget() != NULL ) - { - ApplyMultiDamage(); - } - - ClearMultiDamage(); - g_MultiDamage.SetDamageType( nDamageType | DMG_NEVERGIB ); - - Vector vecDir; - Vector vecEnd; - - // Skip multiple entities when tracing - CBulletsTraceFilter traceFilter( COLLISION_GROUP_NONE ); - traceFilter.SetPassEntity( this ); // Standard pass entity for THIS so that it can be easily removed from the list after passing through a portal - traceFilter.AddEntityToIgnore( info.m_pAdditionalIgnoreEnt ); - -#if defined( HL2_EPISODIC ) && defined( GAME_DLL ) - // FIXME: We need to emulate this same behavior on the client as well -- jdw - // Also ignore a vehicle we're a passenger in - if ( MyCombatCharacterPointer() != NULL && MyCombatCharacterPointer()->IsInAVehicle() ) - { - traceFilter.AddEntityToIgnore( MyCombatCharacterPointer()->GetVehicleEntity() ); - } -#endif // SERVER_DLL - - bool bUnderwaterBullets = ShouldDrawUnderwaterBulletBubbles(); - bool bStartedInWater = false; - if ( bUnderwaterBullets ) - { - bStartedInWater = ( enginetrace->GetPointContents( info.m_vecSrc ) & (CONTENTS_WATER|CONTENTS_SLIME) ) != 0; - } - - // Prediction is only usable on players - int iSeed = 0; - if ( IsPlayer() ) - { - iSeed = CBaseEntity::GetPredictionRandomSeed() & 255; - } - -#if defined( HL2MP ) && defined( GAME_DLL ) - int iEffectSeed = iSeed; -#endif - //----------------------------------------------------- - // Set up our shot manipulator. - //----------------------------------------------------- - CShotManipulator Manipulator( info.m_vecDirShooting ); - - bool bDoImpacts = false; - bool bDoTracers = false; - - float flCumulativeDamage = 0.0f; - - for (int iShot = 0; iShot < info.m_iShots; iShot++) - { - bool bHitWater = false; - bool bHitGlass = false; - - // Prediction is only usable on players - if ( IsPlayer() ) - { - RandomSeed( iSeed ); // init random system with this seed - } - - // If we're firing multiple shots, and the first shot has to be bang on target, ignore spread - if ( iShot == 0 && info.m_iShots > 1 && (info.m_nFlags & FIRE_BULLETS_FIRST_SHOT_ACCURATE) ) - { - vecDir = Manipulator.GetShotDirection(); - } - else - { - - // Don't run the biasing code for the player at the moment. - vecDir = Manipulator.ApplySpread( info.m_vecSpread ); - } - - vecEnd = info.m_vecSrc + vecDir * info.m_flDistance; - -#ifdef PORTAL - CProp_Portal *pShootThroughPortal = NULL; - float fPortalFraction = 2.0f; -#endif - - - if( IsPlayer() && info.m_iShots > 1 && iShot % 2 ) - { - // Half of the shotgun pellets are hulls that make it easier to hit targets with the shotgun. -#ifdef PORTAL - Ray_t rayBullet; - rayBullet.Init( info.m_vecSrc, vecEnd ); - pShootThroughPortal = UTIL_Portal_FirstAlongRay( rayBullet, fPortalFraction ); - if ( !UTIL_Portal_TraceRay_Bullets( pShootThroughPortal, rayBullet, MASK_SHOT, &traceFilter, &tr ) ) - { - pShootThroughPortal = NULL; - } -#else - AI_TraceHull( info.m_vecSrc, vecEnd, Vector( -3, -3, -3 ), Vector( 3, 3, 3 ), MASK_SHOT, &traceFilter, &tr ); -#endif //#ifdef PORTAL - } - else - { -#ifdef PORTAL - Ray_t rayBullet; - rayBullet.Init( info.m_vecSrc, vecEnd ); - pShootThroughPortal = UTIL_Portal_FirstAlongRay( rayBullet, fPortalFraction ); - if ( !UTIL_Portal_TraceRay_Bullets( pShootThroughPortal, rayBullet, MASK_SHOT, &traceFilter, &tr ) ) - { - pShootThroughPortal = NULL; - } -#else - AI_TraceLine(info.m_vecSrc, vecEnd, MASK_SHOT, &traceFilter, &tr); -#endif //#ifdef PORTAL - } - - // Tracker 70354/63250: ywb 8/2/07 - // Fixes bug where trace from turret with attachment point outside of Vcollide - // starts solid so doesn't hit anything else in the world and the final coord - // is outside of the MAX_COORD_FLOAT range. This cause trying to send the end pos - // of the tracer down to the client with an origin which is out-of-range for networking - if ( tr.startsolid ) - { - tr.endpos = tr.startpos; - tr.fraction = 0.0f; - } - - // bullet's final direction can be changed by passing through a portal -#ifdef PORTAL - if ( !tr.startsolid ) - { - vecDir = tr.endpos - tr.startpos; - VectorNormalize( vecDir ); - } -#endif - -#ifdef GAME_DLL - if ( ai_debug_shoot_positions.GetBool() ) - NDebugOverlay::Line(info.m_vecSrc, vecEnd, 255, 255, 255, false, .1 ); -#endif - - if ( bStartedInWater ) - { -#ifdef GAME_DLL - Vector vBubbleStart = info.m_vecSrc; - Vector vBubbleEnd = tr.endpos; - -#ifdef PORTAL - if ( pShootThroughPortal ) - { - vBubbleEnd = info.m_vecSrc + ( vecEnd - info.m_vecSrc ) * fPortalFraction; - } -#endif //#ifdef PORTAL - - CreateBubbleTrailTracer( vBubbleStart, vBubbleEnd, vecDir ); - -#ifdef PORTAL - if ( pShootThroughPortal ) - { - Vector vTransformedIntersection; - UTIL_Portal_PointTransform( pShootThroughPortal->MatrixThisToLinked(), vBubbleEnd, vTransformedIntersection ); - - CreateBubbleTrailTracer( vTransformedIntersection, tr.endpos, vecDir ); - } -#endif //#ifdef PORTAL - -#endif //#ifdef GAME_DLL - bHitWater = true; - } - - // Now hit all triggers along the ray that respond to shots... - // Clip the ray to the first collided solid returned from traceline - CTakeDamageInfo triggerInfo( pAttacker, pAttacker, info.m_iDamage, nDamageType ); - CalculateBulletDamageForce( &triggerInfo, info.m_iAmmoType, vecDir, tr.endpos ); - triggerInfo.ScaleDamageForce( info.m_flDamageForceScale ); - triggerInfo.SetAmmoType( info.m_iAmmoType ); -#ifdef GAME_DLL - TraceAttackToTriggers( triggerInfo, tr.startpos, tr.endpos, vecDir ); -#endif - - // Make sure given a valid bullet type - if (info.m_iAmmoType == -1) - { - DevMsg("ERROR: Undefined ammo type!\n"); - return; - } - - Vector vecTracerDest = tr.endpos; - - // do damage, paint decals - if (tr.fraction != 1.0) - { -#ifdef GAME_DLL - UpdateShotStatistics( tr ); - - // For shots that don't need persistance - int soundEntChannel = ( info.m_nFlags&FIRE_BULLETS_TEMPORARY_DANGER_SOUND ) ? SOUNDENT_CHANNEL_BULLET_IMPACT : SOUNDENT_CHANNEL_UNSPECIFIED; - - CSoundEnt::InsertSound( SOUND_BULLET_IMPACT, tr.endpos, 200, 0.5, this, soundEntChannel ); -#endif - - // See if the bullet ended up underwater + started out of the water - if ( !bHitWater && ( enginetrace->GetPointContents( tr.endpos ) & (CONTENTS_WATER|CONTENTS_SLIME) ) ) - { - bHitWater = HandleShotImpactingWater( info, vecEnd, &traceFilter, &vecTracerDest ); - } - - float flActualDamage = info.m_iDamage; - - // If we hit a player, and we have player damage specified, use that instead - // Adrian: Make sure to use the currect value if we hit a vehicle the player is currently driving. - if ( iPlayerDamage ) - { - if ( tr.m_pEnt->IsPlayer() ) - { - flActualDamage = iPlayerDamage; - } -#ifdef GAME_DLL - else if ( tr.m_pEnt->GetServerVehicle() ) - { - if ( tr.m_pEnt->GetServerVehicle()->GetPassenger() && tr.m_pEnt->GetServerVehicle()->GetPassenger()->IsPlayer() ) - { - flActualDamage = iPlayerDamage; - } - } -#endif - } - - int nActualDamageType = nDamageType; - if ( flActualDamage == 0.0 ) - { - flActualDamage = g_pGameRules->GetAmmoDamage( pAttacker, tr.m_pEnt, info.m_iAmmoType ); - } - else - { - nActualDamageType = nDamageType | ((flActualDamage > 16) ? DMG_ALWAYSGIB : DMG_NEVERGIB ); - } - - if ( !bHitWater || ((info.m_nFlags & FIRE_BULLETS_DONT_HIT_UNDERWATER) == 0) ) - { - // Damage specified by function parameter - CTakeDamageInfo dmgInfo( this, pAttacker, flActualDamage, nActualDamageType ); - CalculateBulletDamageForce( &dmgInfo, info.m_iAmmoType, vecDir, tr.endpos ); - dmgInfo.ScaleDamageForce( info.m_flDamageForceScale ); - dmgInfo.SetAmmoType( info.m_iAmmoType ); - tr.m_pEnt->DispatchTraceAttack( dmgInfo, vecDir, &tr ); - - if ( ToBaseCombatCharacter( tr.m_pEnt ) ) - { - flCumulativeDamage += dmgInfo.GetDamage(); - } - - if ( bStartedInWater || !bHitWater || (info.m_nFlags & FIRE_BULLETS_ALLOW_WATER_SURFACE_IMPACTS) ) - { - if ( bDoServerEffects == true ) - { - DoImpactEffect( tr, nDamageType ); - } - else - { - bDoImpacts = true; - } - } - else - { - // We may not impact, but we DO need to affect ragdolls on the client - CEffectData data; - data.m_vStart = tr.startpos; - data.m_vOrigin = tr.endpos; - data.m_nDamageType = nDamageType; - - DispatchEffect( "RagdollImpact", data ); - } - -#ifdef GAME_DLL - if ( nAmmoFlags & AMMO_FORCE_DROP_IF_CARRIED ) - { - // Make sure if the player is holding this, he drops it - Pickup_ForcePlayerToDropThisObject( tr.m_pEnt ); - } -#endif - } - } - - // See if we hit glass - if ( tr.m_pEnt != NULL ) - { -#ifdef GAME_DLL - surfacedata_t *psurf = physprops->GetSurfaceData( tr.surface.surfaceProps ); - if ( ( psurf != NULL ) && ( psurf->game.material == CHAR_TEX_GLASS ) && ( tr.m_pEnt->ClassMatches( "func_breakable" ) ) ) - { - // Query the func_breakable for whether it wants to allow for bullet penetration - if ( tr.m_pEnt->HasSpawnFlags( SF_BREAK_NO_BULLET_PENETRATION ) == false ) - { - bHitGlass = true; - } - } -#endif - } - - if ( ( info.m_iTracerFreq != 0 ) && ( tracerCount++ % info.m_iTracerFreq ) == 0 && ( bHitGlass == false ) ) - { - if ( bDoServerEffects == true ) - { - Vector vecTracerSrc = vec3_origin; - ComputeTracerStartPosition( info.m_vecSrc, &vecTracerSrc ); - - trace_t Tracer; - Tracer = tr; - Tracer.endpos = vecTracerDest; - -#ifdef PORTAL - if ( pShootThroughPortal ) - { - Tracer.endpos = info.m_vecSrc + ( vecEnd - info.m_vecSrc ) * fPortalFraction; - } -#endif //#ifdef PORTAL - - MakeTracer( vecTracerSrc, Tracer, pAmmoDef->TracerType(info.m_iAmmoType) ); - -#ifdef PORTAL - if ( pShootThroughPortal ) - { - Vector vTransformedIntersection; - UTIL_Portal_PointTransform( pShootThroughPortal->MatrixThisToLinked(), Tracer.endpos, vTransformedIntersection ); - ComputeTracerStartPosition( vTransformedIntersection, &vecTracerSrc ); - - Tracer.endpos = vecTracerDest; - - MakeTracer( vecTracerSrc, Tracer, pAmmoDef->TracerType(info.m_iAmmoType) ); - - // Shooting through a portal, the damage direction is translated through the passed-through portal - // so the damage indicator hud animation is correct - Vector vDmgOriginThroughPortal; - UTIL_Portal_PointTransform( pShootThroughPortal->MatrixThisToLinked(), info.m_vecSrc, vDmgOriginThroughPortal ); - g_MultiDamage.SetDamagePosition ( vDmgOriginThroughPortal ); - } - else - { - g_MultiDamage.SetDamagePosition ( info.m_vecSrc ); - } -#endif //#ifdef PORTAL - } - else - { - bDoTracers = true; - } - } - - //NOTENOTE: We could expand this to a more general solution for various material penetration types (wood, thin metal, etc) - - // See if we should pass through glass -#ifdef GAME_DLL - if ( bHitGlass ) - { - HandleShotImpactingGlass( info, tr, vecDir, &traceFilter ); - } -#endif - - iSeed++; - } - -#if defined( HL2MP ) && defined( GAME_DLL ) - if ( bDoServerEffects == false ) - { - TE_HL2MPFireBullets( entindex(), tr.startpos, info.m_vecDirShooting, info.m_iAmmoType, iEffectSeed, info.m_iShots, info.m_vecSpread.x, bDoTracers, bDoImpacts ); - } -#endif - -#ifdef GAME_DLL - ApplyMultiDamage(); - - if ( IsPlayer() && flCumulativeDamage > 0.0f ) - { - CBasePlayer *pPlayer = static_cast< CBasePlayer * >( this ); - CTakeDamageInfo dmgInfo( this, pAttacker, flCumulativeDamage, nDamageType ); - gamestats->Event_WeaponHit( pPlayer, info.m_bPrimaryAttack, pPlayer->GetActiveWeapon()->GetClassname(), dmgInfo ); - } -#endif -} - - -//----------------------------------------------------------------------------- -// Should we draw bubbles underwater? -//----------------------------------------------------------------------------- -bool CBaseEntity::ShouldDrawUnderwaterBulletBubbles() -{ -#if defined( HL2_DLL ) && defined( GAME_DLL ) - CBaseEntity *pPlayer = ( gpGlobals->maxClients == 1 ) ? UTIL_GetLocalPlayer() : NULL; - return pPlayer && (pPlayer->GetWaterLevel() == 3); -#else - return false; -#endif -} - - -//----------------------------------------------------------------------------- -// Handle shot entering water -//----------------------------------------------------------------------------- -bool CBaseEntity::HandleShotImpactingWater( const FireBulletsInfo_t &info, - const Vector &vecEnd, ITraceFilter *pTraceFilter, Vector *pVecTracerDest ) -{ - trace_t waterTrace; - - // Trace again with water enabled - AI_TraceLine( info.m_vecSrc, vecEnd, (MASK_SHOT|CONTENTS_WATER|CONTENTS_SLIME), pTraceFilter, &waterTrace ); - - // See if this is the point we entered - if ( ( enginetrace->GetPointContents( waterTrace.endpos - Vector(0,0,0.1f) ) & (CONTENTS_WATER|CONTENTS_SLIME) ) == 0 ) - return false; - - if ( ShouldDrawWaterImpacts() ) - { - int nMinSplashSize = GetAmmoDef()->MinSplashSize(info.m_iAmmoType); - int nMaxSplashSize = GetAmmoDef()->MaxSplashSize(info.m_iAmmoType); - - CEffectData data; - data.m_vOrigin = waterTrace.endpos; - data.m_vNormal = waterTrace.plane.normal; - data.m_flScale = random->RandomFloat( nMinSplashSize, nMaxSplashSize ); - if ( waterTrace.contents & CONTENTS_SLIME ) - { - data.m_fFlags |= FX_WATER_IN_SLIME; - } - DispatchEffect( "gunshotsplash", data ); - } - -#ifdef GAME_DLL - if ( ShouldDrawUnderwaterBulletBubbles() ) - { - CWaterBullet *pWaterBullet = ( CWaterBullet * )CreateEntityByName( "waterbullet" ); - if ( pWaterBullet ) - { - pWaterBullet->Spawn( waterTrace.endpos, info.m_vecDirShooting ); - - CEffectData tracerData; - tracerData.m_vStart = waterTrace.endpos; - tracerData.m_vOrigin = waterTrace.endpos + info.m_vecDirShooting * 400.0f; - tracerData.m_fFlags = TRACER_TYPE_WATERBULLET; - DispatchEffect( "TracerSound", tracerData ); - } - } -#endif - - *pVecTracerDest = waterTrace.endpos; - return true; -} - - -ITraceFilter* CBaseEntity::GetBeamTraceFilter( void ) -{ - return NULL; -} - - -void CBaseEntity::DispatchTraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ -#ifdef GAME_DLL - // Make sure our damage filter allows the damage. - if ( !PassesDamageFilter( info )) - { - return; - } -#endif - - TraceAttack( info, vecDir, ptr ); -} - -void CBaseEntity::TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr ) -{ - Vector vecOrigin = ptr->endpos - vecDir * 4; - - if ( m_takedamage ) - { - AddMultiDamage( info, this ); - - int blood = BloodColor(); - - if ( blood != DONT_BLEED ) - { - SpawnBlood( vecOrigin, vecDir, blood, info.GetDamage() );// a little surface blood. - TraceBleed( info.GetDamage(), vecDir, ptr, info.GetDamageType() ); - } - } -} - - -//----------------------------------------------------------------------------- -// Allows the shooter to change the impact effect of his bullets -//----------------------------------------------------------------------------- -void CBaseEntity::DoImpactEffect( trace_t &tr, int nDamageType ) -{ - // give shooter a chance to do a custom impact. - UTIL_ImpactTrace( &tr, nDamageType ); -} - - -//----------------------------------------------------------------------------- -// Computes the tracer start position -//----------------------------------------------------------------------------- -void CBaseEntity::ComputeTracerStartPosition( const Vector &vecShotSrc, Vector *pVecTracerStart ) -{ -#ifndef HL2MP - if ( g_pGameRules->IsMultiplayer() ) - { - // NOTE: we do this because in MakeTracer, we force it to use the attachment position - // in multiplayer, so the results from this function should never actually get used. - pVecTracerStart->Init( 999, 999, 999 ); - return; - } -#endif - - if ( IsPlayer() ) - { - // adjust tracer position for player - Vector forward, right; - CBasePlayer *pPlayer = ToBasePlayer( this ); - pPlayer->EyeVectors( &forward, &right, NULL ); - *pVecTracerStart = vecShotSrc + Vector ( 0 , 0 , -4 ) + right * 2 + forward * 16; - } - else - { - *pVecTracerStart = vecShotSrc; - - CBaseCombatCharacter *pBCC = MyCombatCharacterPointer(); - if ( pBCC != NULL ) - { - CBaseCombatWeapon *pWeapon = pBCC->GetActiveWeapon(); - - if ( pWeapon != NULL ) - { - Vector vecMuzzle; - QAngle vecMuzzleAngles; - - if ( pWeapon->GetAttachment( 1, vecMuzzle, vecMuzzleAngles ) ) - { - *pVecTracerStart = vecMuzzle; - } - } - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Virtual function allows entities to handle tracer presentation -// as they see fit. -// -// Input : vecTracerSrc - the point at which to start the tracer (not always the -// same spot as the traceline! -// -// tr - the entire trace result for the shot. -// -// Output : -//----------------------------------------------------------------------------- -void CBaseEntity::MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ) -{ - const char *pszTracerName = GetTracerType(); - - Vector vNewSrc = vecTracerSrc; - - int iAttachment = GetTracerAttachment(); - - switch ( iTracerType ) - { - case TRACER_LINE: - UTIL_Tracer( vNewSrc, tr.endpos, entindex(), iAttachment, 0.0f, false, pszTracerName ); - break; - - case TRACER_LINE_AND_WHIZ: - UTIL_Tracer( vNewSrc, tr.endpos, entindex(), iAttachment, 0.0f, true, pszTracerName ); - break; - } -} - -//----------------------------------------------------------------------------- -// Default tracer attachment -//----------------------------------------------------------------------------- -int CBaseEntity::GetTracerAttachment( void ) -{ - int iAttachment = TRACER_DONT_USE_ATTACHMENT; - - if ( g_pGameRules->IsMultiplayer() ) - { - iAttachment = 1; - } - - return iAttachment; -} - - -int CBaseEntity::BloodColor() -{ - return DONT_BLEED; -} - - -void CBaseEntity::TraceBleed( float flDamage, const Vector &vecDir, trace_t *ptr, int bitsDamageType ) -{ - if ((BloodColor() == DONT_BLEED) || (BloodColor() == BLOOD_COLOR_MECH)) - { - return; - } - - if (flDamage == 0) - return; - - if (! (bitsDamageType & (DMG_CRUSH | DMG_BULLET | DMG_SLASH | DMG_BLAST | DMG_CLUB | DMG_AIRBOAT))) - return; - - // make blood decal on the wall! - trace_t Bloodtr; - Vector vecTraceDir; - float flNoise; - int cCount; - int i; - -#ifdef GAME_DLL - if ( !IsAlive() ) - { - // dealing with a dead npc. - if ( GetMaxHealth() <= 0 ) - { - // no blood decal for a npc that has already decalled its limit. - return; - } - else - { - m_iMaxHealth -= 1; - } - } -#endif - - if (flDamage < 10) - { - flNoise = 0.1; - cCount = 1; - } - else if (flDamage < 25) - { - flNoise = 0.2; - cCount = 2; - } - else - { - flNoise = 0.3; - cCount = 4; - } - - float flTraceDist = (bitsDamageType & DMG_AIRBOAT) ? 384 : 172; - for ( i = 0 ; i < cCount ; i++ ) - { - vecTraceDir = vecDir * -1;// trace in the opposite direction the shot came from (the direction the shot is going) - - vecTraceDir.x += random->RandomFloat( -flNoise, flNoise ); - vecTraceDir.y += random->RandomFloat( -flNoise, flNoise ); - vecTraceDir.z += random->RandomFloat( -flNoise, flNoise ); - - // Don't bleed on grates. - AI_TraceLine( ptr->endpos, ptr->endpos + vecTraceDir * -flTraceDist, MASK_SOLID_BRUSHONLY & ~CONTENTS_GRATE, this, COLLISION_GROUP_NONE, &Bloodtr); - - if ( Bloodtr.fraction != 1.0 ) - { - UTIL_BloodDecalTrace( &Bloodtr, BloodColor() ); - } - } -} - - -const char* CBaseEntity::GetTracerType() -{ - return NULL; -} - - -//----------------------------------------------------------------------------- -// These methods encapsulate MOVETYPE_FOLLOW, which became obsolete -//----------------------------------------------------------------------------- -void CBaseEntity::FollowEntity( CBaseEntity *pBaseEntity, bool bBoneMerge ) -{ - if (pBaseEntity) - { - SetParent( pBaseEntity ); - SetMoveType( MOVETYPE_NONE ); - - if ( bBoneMerge ) - AddEffects( EF_BONEMERGE ); - - AddSolidFlags( FSOLID_NOT_SOLID ); - SetLocalOrigin( vec3_origin ); - SetLocalAngles( vec3_angle ); - } - else - { - StopFollowingEntity(); - } -} - -void CBaseEntity::SetEffectEntity( CBaseEntity *pEffectEnt ) -{ - if ( m_hEffectEntity.Get() != pEffectEnt ) - { - m_hEffectEntity = pEffectEnt; - } -} - -void CBaseEntity::ApplyLocalVelocityImpulse( const Vector &vecImpulse ) -{ - // NOTE: Don't have to use GetVelocity here because local values - // are always guaranteed to be correct, unlike abs values which may - // require recomputation - if (vecImpulse != vec3_origin ) - { - if ( GetMoveType() == MOVETYPE_VPHYSICS ) - { - Vector worldVel; - VPhysicsGetObject()->LocalToWorld( &worldVel, vecImpulse ); - VPhysicsGetObject()->AddVelocity( &worldVel, NULL ); - } - else - { - InvalidatePhysicsRecursive( VELOCITY_CHANGED ); - m_vecVelocity += vecImpulse; - } - } -} - -void CBaseEntity::ApplyAbsVelocityImpulse( const Vector &vecImpulse ) -{ - if (vecImpulse != vec3_origin ) - { - if ( GetMoveType() == MOVETYPE_VPHYSICS ) - { - VPhysicsGetObject()->AddVelocity( &vecImpulse, NULL ); - } - else - { - // NOTE: Have to use GetAbsVelocity here to ensure it's the correct value - Vector vecResult; - VectorAdd( GetAbsVelocity(), vecImpulse, vecResult ); - SetAbsVelocity( vecResult ); - } - } -} - -void CBaseEntity::ApplyLocalAngularVelocityImpulse( const AngularImpulse &angImpulse ) -{ - if (angImpulse != vec3_origin ) - { - if ( GetMoveType() == MOVETYPE_VPHYSICS ) - { - VPhysicsGetObject()->AddVelocity( NULL, &angImpulse ); - } - else - { - QAngle vecResult; - AngularImpulseToQAngle( angImpulse, vecResult ); - VectorAdd( GetLocalAngularVelocity(), vecResult, vecResult ); - SetLocalAngularVelocity( vecResult ); - } - } -} - -void CBaseEntity::SetCollisionGroup( int collisionGroup ) -{ - if ( (int)m_CollisionGroup != collisionGroup ) - { - m_CollisionGroup = collisionGroup; - CollisionRulesChanged(); - } -} - - -void CBaseEntity::CollisionRulesChanged() -{ - // ivp maintains state based on recent return values from the collision filter, so anything - // that can change the state that a collision filter will return (like m_Solid) needs to call RecheckCollisionFilter. - if ( VPhysicsGetObject() ) - { - extern bool PhysIsInCallback(); - if ( PhysIsInCallback() ) - { - Warning("Changing collision rules within a callback is likely to cause crashes!\n"); - Assert(0); - } - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int count = VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - for ( int i = 0; i < count; i++ ) - { - if ( pList[i] != NULL ) //this really shouldn't happen, but it does >_< - pList[i]->RecheckCollisionFilter(); - } - } -} - -int CBaseEntity::GetWaterType() const -{ - int out = 0; - if ( m_nWaterType & 1 ) - out |= CONTENTS_WATER; - if ( m_nWaterType & 2 ) - out |= CONTENTS_SLIME; - return out; -} - -void CBaseEntity::SetWaterType( int nType ) -{ - m_nWaterType = 0; - if ( nType & CONTENTS_WATER ) - m_nWaterType |= 1; - if ( nType & CONTENTS_SLIME ) - m_nWaterType |= 2; -} - -ConVar sv_alternateticks( "sv_alternateticks", ( IsX360() ) ? "1" : "0", FCVAR_SPONLY, "If set, server only simulates entities on even numbered ticks.\n" ); - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseEntity::IsSimulatingOnAlternateTicks() -{ - if ( gpGlobals->maxClients != 1 ) - { - return false; - } - - return sv_alternateticks.GetBool(); -} - -#ifdef CLIENT_DLL -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseEntity::IsToolRecording() const -{ -#ifndef NO_TOOLFRAMEWORK - return m_bToolRecording; -#else - return false; -#endif -} -#endif diff --git a/game/shared/baseentity_shared.h b/game/shared/baseentity_shared.h deleted file mode 100644 index 62108862b..000000000 --- a/game/shared/baseentity_shared.h +++ /dev/null @@ -1,253 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef BASEENTITY_SHARED_H -#define BASEENTITY_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - - -extern ConVar hl2_episodic; - -// Simple shared header file for common base entities - -// entity capabilities -// These are caps bits to indicate what an object's capabilities (currently used for +USE, save/restore and level transitions) -#define FCAP_MUST_SPAWN 0x00000001 // Spawn after restore -#define FCAP_ACROSS_TRANSITION 0x00000002 // should transfer between transitions -// UNDONE: This will ignore transition volumes (trigger_transition), but not the PVS!!! -#define FCAP_FORCE_TRANSITION 0x00000004 // ALWAYS goes across transitions -#define FCAP_NOTIFY_ON_TRANSITION 0x00000008 // Entity will receive Inside/Outside transition inputs when a transition occurs - -#define FCAP_IMPULSE_USE 0x00000010 // can be used by the player -#define FCAP_CONTINUOUS_USE 0x00000020 // can be used by the player -#define FCAP_ONOFF_USE 0x00000040 // can be used by the player -#define FCAP_DIRECTIONAL_USE 0x00000080 // Player sends +/- 1 when using (currently only tracktrains) -// NOTE: Normally +USE only works in direct line of sight. Add these caps for additional searches -#define FCAP_USE_ONGROUND 0x00000100 -#define FCAP_USE_IN_RADIUS 0x00000200 -#define FCAP_SAVE_NON_NETWORKABLE 0x00000400 - -#define FCAP_MASTER 0x10000000 // Can be used to "master" other entities (like multisource) -#define FCAP_WCEDIT_POSITION 0x40000000 // Can change position and update Hammer in edit mode -#define FCAP_DONT_SAVE 0x80000000 // Don't save this - - -// How many bits are used to transmit parent attachment indices? -#define NUM_PARENTATTACHMENT_BITS 6 - -// Maximum number of vphysics objects per entity -#define VPHYSICS_MAX_OBJECT_LIST_COUNT 1024 - -//----------------------------------------------------------------------------- -// For invalidate physics recursive -//----------------------------------------------------------------------------- -enum InvalidatePhysicsBits_t -{ - POSITION_CHANGED = 0x1, - ANGLES_CHANGED = 0x2, - VELOCITY_CHANGED = 0x4, - ANIMATION_CHANGED = 0x8, -}; - - -#if defined( CLIENT_DLL ) -#include "c_baseentity.h" -#include "c_baseanimating.h" -#else -#include "baseentity.h" - -#ifdef HL2_EPISODIC - #include "info_darknessmode_lightsource.h" -#endif // HL2_EPISODIC - -#endif - -#if !defined( NO_ENTITY_PREDICTION ) -// CBaseEntity inlines -inline bool CBaseEntity::IsPlayerSimulated( void ) const -{ - return m_bIsPlayerSimulated; -} - -inline CBasePlayer *CBaseEntity::GetSimulatingPlayer( void ) -{ - return m_hPlayerSimulationOwner; -} -#endif - -inline MoveType_t CBaseEntity::GetMoveType() const -{ - return (MoveType_t)(unsigned char)m_MoveType; -} - -inline MoveCollide_t CBaseEntity::GetMoveCollide() const -{ - return (MoveCollide_t)(unsigned char)m_MoveCollide; -} - -//----------------------------------------------------------------------------- -// Collision group accessors -//----------------------------------------------------------------------------- -inline int CBaseEntity::GetCollisionGroup() const -{ - return m_CollisionGroup; -} - -inline int CBaseEntity::GetFlags( void ) const -{ - return m_fFlags; -} - -inline bool CBaseEntity::IsAlive( void ) -{ - return m_lifeState == LIFE_ALIVE; -} - -inline CBaseEntity *CBaseEntity::GetOwnerEntity() const -{ - return m_hOwnerEntity.Get(); -} - -inline CBaseEntity *CBaseEntity::GetEffectEntity() const -{ - return m_hEffectEntity.Get(); -} - -inline int CBaseEntity::GetPredictionRandomSeed( void ) -{ - return m_nPredictionRandomSeed; -} - -inline CBasePlayer *CBaseEntity::GetPredictionPlayer( void ) -{ - return m_pPredictionPlayer; -} - -inline void CBaseEntity::SetPredictionPlayer( CBasePlayer *player ) -{ - m_pPredictionPlayer = player; -} - - -inline bool CBaseEntity::IsSimulatedEveryTick() const -{ - return m_bSimulatedEveryTick; -} - -inline bool CBaseEntity::IsAnimatedEveryTick() const -{ - return m_bAnimatedEveryTick; -} - -inline void CBaseEntity::SetSimulatedEveryTick( bool sim ) -{ - if ( m_bSimulatedEveryTick != sim ) - { - m_bSimulatedEveryTick = sim; -#ifdef CLIENT_DLL - Interp_UpdateInterpolationAmounts( GetVarMapping() ); -#endif - } -} - -inline void CBaseEntity::SetAnimatedEveryTick( bool anim ) -{ - if ( m_bAnimatedEveryTick != anim ) - { - m_bAnimatedEveryTick = anim; -#ifdef CLIENT_DLL - Interp_UpdateInterpolationAmounts( GetVarMapping() ); -#endif - } -} - -inline float CBaseEntity::GetAnimTime() const -{ - return m_flAnimTime; -} - -inline float CBaseEntity::GetSimulationTime() const -{ - return m_flSimulationTime; -} - -inline void CBaseEntity::SetAnimTime( float at ) -{ - m_flAnimTime = at; -} - -inline void CBaseEntity::SetSimulationTime( float st ) -{ - m_flSimulationTime = st; -} - -inline int CBaseEntity::GetEffects( void ) const -{ - return m_fEffects; -} - -inline void CBaseEntity::RemoveEffects( int nEffects ) -{ -#if !defined( CLIENT_DLL ) -#ifdef HL2_EPISODIC - if ( nEffects & (EF_BRIGHTLIGHT|EF_DIMLIGHT) ) - { - // Hack for now, to avoid player emitting radius with his flashlight - if ( !IsPlayer() ) - { - RemoveEntityFromDarknessCheck( this ); - } - } -#endif // HL2_EPISODIC -#endif // !CLIENT_DLL - - m_fEffects &= ~nEffects; - if ( nEffects & EF_NODRAW ) - { -#ifndef CLIENT_DLL - NetworkProp()->MarkPVSInformationDirty(); - DispatchUpdateTransmitState(); -#else - UpdateVisibility(); -#endif - } -} - -inline void CBaseEntity::ClearEffects( void ) -{ -#if !defined( CLIENT_DLL ) -#ifdef HL2_EPISODIC - if ( m_fEffects & (EF_BRIGHTLIGHT|EF_DIMLIGHT) ) - { - // Hack for now, to avoid player emitting radius with his flashlight - if ( !IsPlayer() ) - { - RemoveEntityFromDarknessCheck( this ); - } - } -#endif // HL2_EPISODIC -#endif // !CLIENT_DLL - - m_fEffects = 0; -#ifndef CLIENT_DLL - DispatchUpdateTransmitState(); -#else - UpdateVisibility(); -#endif -} - -inline bool CBaseEntity::IsEffectActive( int nEffects ) const -{ - return (m_fEffects & nEffects) != 0; -} - -// Shared EntityMessage between game and client .dlls -#define BASEENTITY_MSG_REMOVE_DECALS 1 - -#endif // BASEENTITY_SHARED_H diff --git a/game/shared/basegrenade_shared.cpp b/game/shared/basegrenade_shared.cpp deleted file mode 100644 index 9c8597f6d..000000000 --- a/game/shared/basegrenade_shared.cpp +++ /dev/null @@ -1,558 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "decals.h" -#include "basegrenade_shared.h" -#include "shake.h" -#include "engine/IEngineSound.h" - -#if !defined( CLIENT_DLL ) - -#include "soundent.h" -#include "entitylist.h" -#include "GameStats.h" - -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern short g_sModelIndexFireball; // (in combatweapon.cpp) holds the index for the fireball -extern short g_sModelIndexWExplosion; // (in combatweapon.cpp) holds the index for the underwater explosion -extern short g_sModelIndexSmoke; // (in combatweapon.cpp) holds the index for the smoke cloud -extern ConVar sk_plr_dmg_grenade; - -#if !defined( CLIENT_DLL ) - -// Global Savedata for friction modifier -BEGIN_DATADESC( CBaseGrenade ) - // nextGrenade - DEFINE_FIELD( m_hThrower, FIELD_EHANDLE ), - // m_fRegisteredSound ??? - DEFINE_FIELD( m_bIsLive, FIELD_BOOLEAN ), - DEFINE_FIELD( m_DmgRadius, FIELD_FLOAT ), - DEFINE_FIELD( m_flDetonateTime, FIELD_TIME ), - DEFINE_FIELD( m_flWarnAITime, FIELD_TIME ), - DEFINE_FIELD( m_flDamage, FIELD_FLOAT ), - DEFINE_FIELD( m_iszBounceSound, FIELD_STRING ), - DEFINE_FIELD( m_bHasWarnedAI, FIELD_BOOLEAN ), - - // Function Pointers - DEFINE_THINKFUNC( Smoke ), - DEFINE_ENTITYFUNC( BounceTouch ), - DEFINE_ENTITYFUNC( SlideTouch ), - DEFINE_ENTITYFUNC( ExplodeTouch ), - DEFINE_USEFUNC( DetonateUse ), - DEFINE_THINKFUNC( DangerSoundThink ), - DEFINE_THINKFUNC( PreDetonate ), - DEFINE_THINKFUNC( Detonate ), - DEFINE_THINKFUNC( TumbleThink ), - -END_DATADESC() - -void SendProxy_CropFlagsToPlayerFlagBitsLength( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID); - -#endif - -IMPLEMENT_NETWORKCLASS_ALIASED( BaseGrenade, DT_BaseGrenade ) - -BEGIN_NETWORK_TABLE( CBaseGrenade, DT_BaseGrenade ) -#if !defined( CLIENT_DLL ) - SendPropFloat( SENDINFO( m_flDamage ), 10, SPROP_ROUNDDOWN, 0.0, 256.0f ), - SendPropFloat( SENDINFO( m_DmgRadius ), 10, SPROP_ROUNDDOWN, 0.0, 1024.0f ), - SendPropInt( SENDINFO( m_bIsLive ), 1, SPROP_UNSIGNED ), -// SendPropTime( SENDINFO( m_flDetonateTime ) ), - SendPropEHandle( SENDINFO( m_hThrower ) ), - - SendPropVector( SENDINFO( m_vecVelocity ), 0, SPROP_NOSCALE ), - // HACK: Use same flag bits as player for now - SendPropInt ( SENDINFO(m_fFlags), PLAYER_FLAG_BITS, SPROP_UNSIGNED, SendProxy_CropFlagsToPlayerFlagBitsLength ), -#else - RecvPropFloat( RECVINFO( m_flDamage ) ), - RecvPropFloat( RECVINFO( m_DmgRadius ) ), - RecvPropInt( RECVINFO( m_bIsLive ) ), -// RecvPropTime( RECVINFO( m_flDetonateTime ) ), - RecvPropEHandle( RECVINFO( m_hThrower ) ), - - // Need velocity from grenades to make animation system work correctly when running - RecvPropVector( RECVINFO(m_vecVelocity), 0, RecvProxy_LocalVelocity ), - - RecvPropInt( RECVINFO( m_fFlags ) ), -#endif -END_NETWORK_TABLE() - -LINK_ENTITY_TO_CLASS( grenade, CBaseGrenade ); - -#if defined( CLIENT_DLL ) - -BEGIN_PREDICTION_DATA( CBaseGrenade ) - - DEFINE_PRED_FIELD( m_hThrower, FIELD_EHANDLE, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_bIsLive, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_DmgRadius, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), -// DEFINE_PRED_FIELD_TOL( m_flDetonateTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE, TD_MSECTOLERANCE ), - DEFINE_PRED_FIELD( m_flDamage, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), - - DEFINE_PRED_FIELD_TOL( m_vecVelocity, FIELD_VECTOR, FTYPEDESC_INSENDTABLE, 0.5f ), - DEFINE_PRED_FIELD_TOL( m_flNextAttack, FIELD_FLOAT, FTYPEDESC_INSENDTABLE, TD_MSECTOLERANCE ), - -// DEFINE_FIELD( m_fRegisteredSound, FIELD_BOOLEAN ), -// DEFINE_FIELD( m_iszBounceSound, FIELD_STRING ), - -END_PREDICTION_DATA() - -#endif - -// Grenades flagged with this will be triggered when the owner calls detonateSatchelCharges -#define SF_DETONATE 0x0001 - -// UNDONE: temporary scorching for PreAlpha - find a less sleazy permenant solution. -void CBaseGrenade::Explode( trace_t *pTrace, int bitsDamageType ) -{ -#if !defined( CLIENT_DLL ) - - SetModelName( NULL_STRING );//invisible - AddSolidFlags( FSOLID_NOT_SOLID ); - - m_takedamage = DAMAGE_NO; - - // Pull out of the wall a bit - if ( pTrace->fraction != 1.0 ) - { - SetAbsOrigin( pTrace->endpos + (pTrace->plane.normal * 0.6) ); - } - - Vector vecAbsOrigin = GetAbsOrigin(); - int contents = UTIL_PointContents ( vecAbsOrigin ); - -#if defined( TF_DLL ) - // Since this code only runs on the server, make sure it shows the tempents it creates. - // This solves a problem with remote detonating the pipebombs (client wasn't seeing the explosion effect) - CDisablePredictionFiltering disabler; -#endif - - if ( pTrace->fraction != 1.0 ) - { - Vector vecNormal = pTrace->plane.normal; - surfacedata_t *pdata = physprops->GetSurfaceData( pTrace->surface.surfaceProps ); - CPASFilter filter( vecAbsOrigin ); - - te->Explosion( filter, -1.0, // don't apply cl_interp delay - &vecAbsOrigin, - !( contents & MASK_WATER ) ? g_sModelIndexFireball : g_sModelIndexWExplosion, - m_DmgRadius * .03, - 25, - TE_EXPLFLAG_NONE, - m_DmgRadius, - m_flDamage, - &vecNormal, - (char) pdata->game.material ); - } - else - { - CPASFilter filter( vecAbsOrigin ); - te->Explosion( filter, -1.0, // don't apply cl_interp delay - &vecAbsOrigin, - !( contents & MASK_WATER ) ? g_sModelIndexFireball : g_sModelIndexWExplosion, - m_DmgRadius * .03, - 25, - TE_EXPLFLAG_NONE, - m_DmgRadius, - m_flDamage ); - } - -#if !defined( CLIENT_DLL ) - CSoundEnt::InsertSound ( SOUND_COMBAT, GetAbsOrigin(), BASEGRENADE_EXPLOSION_VOLUME, 3.0 ); -#endif - - // Use the thrower's position as the reported position - Vector vecReported = m_hThrower ? m_hThrower->GetAbsOrigin() : vec3_origin; - - CTakeDamageInfo info( this, m_hThrower, GetBlastForce(), GetAbsOrigin(), m_flDamage, bitsDamageType, 0, &vecReported ); - - RadiusDamage( info, GetAbsOrigin(), m_DmgRadius, CLASS_NONE, NULL ); - - UTIL_DecalTrace( pTrace, "Scorch" ); - - EmitSound( "BaseGrenade.Explode" ); - - SetThink( &CBaseGrenade::SUB_Remove ); - SetTouch( NULL ); - SetSolid( SOLID_NONE ); - - AddEffects( EF_NODRAW ); - SetAbsVelocity( vec3_origin ); - -#if HL2_EPISODIC - // Because the grenade is zipped out of the world instantly, the EXPLOSION sound that it makes for - // the AI is also immediately destroyed. For this reason, we now make the grenade entity inert and - // throw it away in 1/10th of a second instead of right away. Removing the grenade instantly causes - // intermittent bugs with env_microphones who are listening for explosions. They will 'randomly' not - // hear explosion sounds when the grenade is removed and the SoundEnt thinks (and removes the sound) - // before the env_microphone thinks and hears the sound. - SetNextThink( gpGlobals->curtime + 0.1 ); -#else - SetNextThink( gpGlobals->curtime ); -#endif//HL2_EPISODIC - -#if defined( HL2_DLL ) - CBasePlayer *pPlayer = ToBasePlayer( m_hThrower.Get() ); - if ( pPlayer ) - { - gamestats->Event_WeaponHit( pPlayer, true, "weapon_frag", info ); - } -#endif - -#endif -} - - -void CBaseGrenade::Smoke( void ) -{ - Vector vecAbsOrigin = GetAbsOrigin(); - if ( UTIL_PointContents ( vecAbsOrigin ) & MASK_WATER ) - { - UTIL_Bubbles( vecAbsOrigin - Vector( 64, 64, 64 ), vecAbsOrigin + Vector( 64, 64, 64 ), 100 ); - } - else - { - CPVSFilter filter( vecAbsOrigin ); - - te->Smoke( filter, 0.0, - &vecAbsOrigin, g_sModelIndexSmoke, - m_DmgRadius * 0.03, - 24 ); - } -#if !defined( CLIENT_DLL ) - SetThink ( &CBaseGrenade::SUB_Remove ); -#endif - SetNextThink( gpGlobals->curtime ); -} - -void CBaseGrenade::Event_Killed( const CTakeDamageInfo &info ) -{ - Detonate( ); -} - -#if !defined( CLIENT_DLL ) -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseGrenade::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - // Support player pickup - if ( useType == USE_TOGGLE ) - { - CBasePlayer *pPlayer = ToBasePlayer( pActivator ); - if ( pPlayer ) - { - pPlayer->PickupObject( this ); - return; - } - } - - // Pass up so we still call any custom Use function - BaseClass::Use( pActivator, pCaller, useType, value ); -} -#endif - -//----------------------------------------------------------------------------- -// Purpose: Timed grenade, this think is called when time runs out. -//----------------------------------------------------------------------------- -void CBaseGrenade::DetonateUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - SetThink( &CBaseGrenade::Detonate ); - SetNextThink( gpGlobals->curtime ); -} - -void CBaseGrenade::PreDetonate( void ) -{ -#if !defined( CLIENT_DLL ) - CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin(), 400, 1.5, this ); -#endif - - SetThink( &CBaseGrenade::Detonate ); - SetNextThink( gpGlobals->curtime + 1.5 ); -} - - -void CBaseGrenade::Detonate( void ) -{ - trace_t tr; - Vector vecSpot;// trace starts here! - - SetThink( NULL ); - - vecSpot = GetAbsOrigin() + Vector ( 0 , 0 , 8 ); - UTIL_TraceLine ( vecSpot, vecSpot + Vector ( 0, 0, -32 ), MASK_SHOT_HULL, this, COLLISION_GROUP_NONE, & tr); - - if( tr.startsolid ) - { - // Since we blindly moved the explosion origin vertically, we may have inadvertently moved the explosion into a solid, - // in which case nothing is going to be harmed by the grenade's explosion because all subsequent traces will startsolid. - // If this is the case, we do the downward trace again from the actual origin of the grenade. (sjb) 3/8/2007 (for ep2_outland_09) - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, -32), MASK_SHOT_HULL, this, COLLISION_GROUP_NONE, &tr ); - } - - Explode( &tr, DMG_BLAST ); - - if ( GetShakeAmplitude() ) - { - UTIL_ScreenShake( GetAbsOrigin(), GetShakeAmplitude(), 150.0, 1.0, GetShakeRadius(), SHAKE_START ); - } -} - - -// -// Contact grenade, explode when it touches something -// -void CBaseGrenade::ExplodeTouch( CBaseEntity *pOther ) -{ - trace_t tr; - Vector vecSpot;// trace starts here! - - Assert( pOther ); - if ( !pOther->IsSolid() ) - return; - - Vector velDir = GetAbsVelocity(); - VectorNormalize( velDir ); - vecSpot = GetAbsOrigin() - velDir * 32; - UTIL_TraceLine( vecSpot, vecSpot + velDir * 64, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - - Explode( &tr, DMG_BLAST ); -} - - -void CBaseGrenade::DangerSoundThink( void ) -{ - if (!IsInWorld()) - { - Remove( ); - return; - } - -#if !defined( CLIENT_DLL ) - CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin() + GetAbsVelocity() * 0.5, (int)GetAbsVelocity().Length( ), 0.2, this ); -#endif - - SetNextThink( gpGlobals->curtime + 0.2 ); - - if (GetWaterLevel() != 0) - { - SetAbsVelocity( GetAbsVelocity() * 0.5 ); - } -} - - -void CBaseGrenade::BounceTouch( CBaseEntity *pOther ) -{ - if ( pOther->IsSolidFlagSet(FSOLID_TRIGGER | FSOLID_VOLUME_CONTENTS) ) - return; - - // don't hit the guy that launched this grenade - if ( pOther == GetThrower() ) - return; - - // only do damage if we're moving fairly fast - if ( (pOther->m_takedamage != DAMAGE_NO) && (m_flNextAttack < gpGlobals->curtime && GetAbsVelocity().Length() > 100)) - { - if (m_hThrower) - { -#if !defined( CLIENT_DLL ) - trace_t tr; - tr = CBaseEntity::GetTouchTrace( ); - ClearMultiDamage( ); - Vector forward; - AngleVectors( GetLocalAngles(), &forward, NULL, NULL ); - CTakeDamageInfo info( this, m_hThrower, 1, DMG_CLUB ); - CalculateMeleeDamageForce( &info, GetAbsVelocity(), GetAbsOrigin() ); - pOther->DispatchTraceAttack( info, forward, &tr ); - ApplyMultiDamage(); -#endif - } - m_flNextAttack = gpGlobals->curtime + 1.0; // debounce - } - - Vector vecTestVelocity; - // m_vecAngVelocity = Vector (300, 300, 300); - - // this is my heuristic for modulating the grenade velocity because grenades dropped purely vertical - // or thrown very far tend to slow down too quickly for me to always catch just by testing velocity. - // trimming the Z velocity a bit seems to help quite a bit. - vecTestVelocity = GetAbsVelocity(); - vecTestVelocity.z *= 0.45; - - if ( !m_bHasWarnedAI && vecTestVelocity.Length() <= 60 ) - { - // grenade is moving really slow. It's probably very close to where it will ultimately stop moving. - // emit the danger sound. - - // register a radius louder than the explosion, so we make sure everyone gets out of the way -#if !defined( CLIENT_DLL ) - CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin(), (int)(m_flDamage / 0.4), 0.3, this ); -#endif - m_bHasWarnedAI = true; - } - - if (GetFlags() & FL_ONGROUND) - { - // add a bit of static friction -// SetAbsVelocity( GetAbsVelocity() * 0.8 ); - - // SetSequence( random->RandomInt( 1, 1 ) ); // FIXME: missing tumble animations - } - else - { - // play bounce sound - BounceSound(); - } - m_flPlaybackRate = GetAbsVelocity().Length() / 200.0; - if (m_flPlaybackRate > 1.0) - m_flPlaybackRate = 1; - else if (m_flPlaybackRate < 0.5) - m_flPlaybackRate = 0; - -} - - - -void CBaseGrenade::SlideTouch( CBaseEntity *pOther ) -{ - // don't hit the guy that launched this grenade - if ( pOther == GetThrower() ) - return; - - // m_vecAngVelocity = Vector (300, 300, 300); - - if (GetFlags() & FL_ONGROUND) - { - // add a bit of static friction -// SetAbsVelocity( GetAbsVelocity() * 0.95 ); - - if (GetAbsVelocity().x != 0 || GetAbsVelocity().y != 0) - { - // maintain sliding sound - } - } - else - { - BounceSound(); - } -} - -void CBaseGrenade ::BounceSound( void ) -{ - // Doesn't need to do anything anymore! Physics makes the sound. -} - -void CBaseGrenade ::TumbleThink( void ) -{ - if (!IsInWorld()) - { - Remove( ); - return; - } - - StudioFrameAdvance( ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - // - // Emit a danger sound one second before exploding. - // - if (m_flDetonateTime - 1 < gpGlobals->curtime) - { -#if !defined( CLIENT_DLL ) - CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin() + GetAbsVelocity() * (m_flDetonateTime - gpGlobals->curtime), 400, 0.1, this ); -#endif - } - - if (m_flDetonateTime <= gpGlobals->curtime) - { - SetThink( &CBaseGrenade::Detonate ); - } - - if (GetWaterLevel() != 0) - { - SetAbsVelocity( GetAbsVelocity() * 0.5 ); - m_flPlaybackRate = 0.2; - } -} - -void CBaseGrenade::Precache( void ) -{ - BaseClass::Precache( ); - - PrecacheScriptSound( "BaseGrenade.Explode" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CBaseCombatCharacter -//----------------------------------------------------------------------------- -CBaseCombatCharacter *CBaseGrenade::GetThrower( void ) -{ - CBaseCombatCharacter *pResult = ToBaseCombatCharacter( m_hThrower ); - if ( !pResult && GetOwnerEntity() != NULL ) - { - pResult = ToBaseCombatCharacter( GetOwnerEntity() ); - } - return pResult; -} - -//----------------------------------------------------------------------------- - -void CBaseGrenade::SetThrower( CBaseCombatCharacter *pThrower ) -{ - m_hThrower = pThrower; - - // if this is the first thrower, set it as the original thrower - if ( NULL == m_hOriginalThrower ) - { - m_hOriginalThrower = pThrower; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Destructor -// Input : -// Output : -//----------------------------------------------------------------------------- -CBaseGrenade::~CBaseGrenade(void) -{ -}; - -//----------------------------------------------------------------------------- -// Purpose: Constructor -// Input : -// Output : -//----------------------------------------------------------------------------- -CBaseGrenade::CBaseGrenade(void) -{ - m_hThrower = NULL; - m_hOriginalThrower = NULL; - m_bIsLive = false; - m_DmgRadius = 100; - m_flDetonateTime = 0; - m_bHasWarnedAI = false; - - SetSimulatedEveryTick( true ); -}; - - - - - - - - - - - - - - diff --git a/game/shared/basegrenade_shared.h b/game/shared/basegrenade_shared.h deleted file mode 100644 index 98c7909c2..000000000 --- a/game/shared/basegrenade_shared.h +++ /dev/null @@ -1,137 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef BASEGRENADE_SHARED_H -#define BASEGRENADE_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - -#if defined( CLIENT_DLL ) - -#define CBaseGrenade C_BaseGrenade - -#include "c_basecombatcharacter.h" - -#else - -#include "basecombatcharacter.h" -#include "player_pickup.h" - -#endif - -#define BASEGRENADE_EXPLOSION_VOLUME 1024 - -class CTakeDamageInfo; - -#if !defined( CLIENT_DLL ) -class CBaseGrenade : public CBaseCombatCharacter, public CDefaultPlayerPickupVPhysics -#else -class CBaseGrenade : public CBaseCombatCharacter -#endif -{ - DECLARE_CLASS( CBaseGrenade, CBaseCombatCharacter ); -public: - - CBaseGrenade(void); - ~CBaseGrenade(void); - - DECLARE_PREDICTABLE(); - DECLARE_NETWORKCLASS(); - - -#if !defined( CLIENT_DLL ) - DECLARE_DATADESC(); -#endif - - virtual void Precache( void ); - - virtual void Explode( trace_t *pTrace, int bitsDamageType ); - void Smoke( void ); - - void BounceTouch( CBaseEntity *pOther ); - void SlideTouch( CBaseEntity *pOther ); - void ExplodeTouch( CBaseEntity *pOther ); - void DangerSoundThink( void ); - void PreDetonate( void ); - virtual void Detonate( void ); - void DetonateUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - void TumbleThink( void ); - - virtual Vector GetBlastForce() { return vec3_origin; } - - virtual void BounceSound( void ); - virtual int BloodColor( void ) { return DONT_BLEED; } - virtual void Event_Killed( const CTakeDamageInfo &info ); - - virtual float GetShakeAmplitude( void ) { return 25.0; } - virtual float GetShakeRadius( void ) { return 750.0; } - - // Damage accessors. - virtual float GetDamage() - { - return m_flDamage; - } - virtual float GetDamageRadius() - { - return m_DmgRadius; - } - - virtual void SetDamage(float flDamage) - { - m_flDamage = flDamage; - } - - virtual void SetDamageRadius(float flDamageRadius) - { - m_DmgRadius = flDamageRadius; - } - - // Bounce sound accessors. - void SetBounceSound( const char *pszBounceSound ) - { - m_iszBounceSound = MAKE_STRING( pszBounceSound ); - } - - CBaseCombatCharacter *GetThrower( void ); - void SetThrower( CBaseCombatCharacter *pThrower ); - CBaseEntity *GetOriginalThrower() { return m_hOriginalThrower; } - -#if !defined( CLIENT_DLL ) - // Allow +USE pickup - int ObjectCaps() - { - return (BaseClass::ObjectCaps() | FCAP_IMPULSE_USE | FCAP_USE_IN_RADIUS); - } - - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); -#endif - -public: - IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_vecVelocity ); - IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_fFlags ); - - bool m_bHasWarnedAI; // whether or not this grenade has issued its DANGER sound to the world sound list yet. - CNetworkVar( bool, m_bIsLive ); // Is this grenade live, or can it be picked up? - CNetworkVar( float, m_DmgRadius ); // How far do I do damage? - float m_flDetonateTime; // Time at which to detonate. - float m_flWarnAITime; // Time at which to warn the AI - -protected: - - CNetworkVar( float, m_flDamage ); // Damage to inflict. - string_t m_iszBounceSound; // The sound to make on bouncing. If not NULL, overrides the BounceSound() function. - -private: - CNetworkHandle( CBaseEntity, m_hThrower ); // Who threw this grenade - EHANDLE m_hOriginalThrower; // Who was the original thrower of this grenade - - CBaseGrenade( const CBaseGrenade & ); // not defined, not accessible - -}; - -#endif // BASEGRENADE_SHARED_H diff --git a/game/shared/baseparticleentity.cpp b/game/shared/baseparticleentity.cpp deleted file mode 100644 index bec6ce310..000000000 --- a/game/shared/baseparticleentity.cpp +++ /dev/null @@ -1,115 +0,0 @@ -//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// - -#include "cbase.h" -#include "baseparticleentity.h" - -#ifdef CLIENT_DLL -#include "tier1/KeyValues.h" -#include "toolframework_client.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -IMPLEMENT_NETWORKCLASS_ALIASED( BaseParticleEntity, DT_BaseParticleEntity ) - -BEGIN_NETWORK_TABLE( CBaseParticleEntity, DT_BaseParticleEntity ) -END_NETWORK_TABLE() - -BEGIN_PREDICTION_DATA( CBaseParticleEntity ) -END_PREDICTION_DATA() - -#ifdef CLIENT_DLL -REGISTER_EFFECT( CBaseParticleEntity ); -#endif - -CBaseParticleEntity::CBaseParticleEntity( void ) -{ -#if defined( CLIENT_DLL ) - m_bSimulate = true; - m_nToolParticleEffectId = TOOLPARTICLESYSTEMID_INVALID; -#endif -} - -CBaseParticleEntity::~CBaseParticleEntity( void ) -{ -#if defined( CLIENT_DLL ) - if ( ToolsEnabled() && ( m_nToolParticleEffectId != TOOLPARTICLESYSTEMID_INVALID ) && clienttools->IsInRecordingMode() ) - { - KeyValues *msg = new KeyValues( "ParticleSystem_Destroy" ); - msg->SetInt( "id", m_nToolParticleEffectId ); - m_nToolParticleEffectId = TOOLPARTICLESYSTEMID_INVALID; - } -#endif -} - -#if !defined( CLIENT_DLL ) -int CBaseParticleEntity::UpdateTransmitState( void ) -{ - if ( IsEffectActive( EF_NODRAW ) ) - return SetTransmitState( FL_EDICT_DONTSEND ); - - if ( IsEFlagSet( EFL_IN_SKYBOX ) ) - return SetTransmitState( FL_EDICT_ALWAYS ); - - // cull against PVS - return SetTransmitState( FL_EDICT_PVSCHECK ); -} -#endif - -void CBaseParticleEntity::Activate() -{ -#if !defined( CLIENT_DLL ) - BaseClass::Activate(); -#endif -} - - -void CBaseParticleEntity::Think() -{ - Remove( ); -} - - -void CBaseParticleEntity::FollowEntity(CBaseEntity *pEntity) -{ - BaseClass::FollowEntity( pEntity ); - SetLocalOrigin( vec3_origin ); -} - - -void CBaseParticleEntity::SetLifetime(float lifetime) -{ - if(lifetime == -1) - SetNextThink( TICK_NEVER_THINK ); - else - SetNextThink( gpGlobals->curtime + lifetime ); -} - -#if defined( CLIENT_DLL ) -const Vector &CBaseParticleEntity::GetSortOrigin() -{ - // By default, we do the cheaper behavior of getting the root parent's abs origin, so we don't have to - // setup any bones along the way. If this screws anything up, we can always make it an option. - return GetRootMoveParent()->GetAbsOrigin(); -} - -void CBaseParticleEntity::SimulateParticles( CParticleSimulateIterator *pIterator ) -{ - // If you derive from CBaseParticleEntity, you must implement simulation and rendering. - Assert( false ); -} - -void CBaseParticleEntity::RenderParticles( CParticleRenderIterator *pIterator ) -{ - // If you derive from CBaseParticleEntity, you must implement simulation and rendering. - Assert( false ); -} - -#endif diff --git a/game/shared/baseparticleentity.h b/game/shared/baseparticleentity.h deleted file mode 100644 index 70b3bcb04..000000000 --- a/game/shared/baseparticleentity.h +++ /dev/null @@ -1,100 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -// Particle system entities can derive from this to handle some of the mundane -// functionality of hooking into the engine's entity system. - -#ifndef PARTICLE_BASEEFFECT_H -#define PARTICLE_BASEEFFECT_H - -#include "predictable_entity.h" -#include "baseentity_shared.h" - -#if defined( CLIENT_DLL ) -#define CBaseParticleEntity C_BaseParticleEntity - -#include "particlemgr.h" - -#endif - -class CBaseParticleEntity : public CBaseEntity -#if defined( CLIENT_DLL ) -, public IParticleEffect -#endif -{ -public: - DECLARE_CLASS( CBaseParticleEntity, CBaseEntity ); - DECLARE_PREDICTABLE(); - DECLARE_NETWORKCLASS(); - - CBaseParticleEntity(); - virtual ~CBaseParticleEntity(); - - // CBaseEntity overrides. -public: -#if !defined( CLIENT_DLL ) - virtual int UpdateTransmitState( void ); -#else -// Default IParticleEffect overrides. -public: - - virtual bool ShouldSimulate() const { return m_bSimulate; } - virtual void SetShouldSimulate( bool bSim ) { m_bSimulate = bSim; } - - virtual void SimulateParticles( CParticleSimulateIterator *pIterator ); - virtual void RenderParticles( CParticleRenderIterator *pIterator ); - virtual const Vector & GetSortOrigin(); -public: - CParticleEffectBinding m_ParticleEffect; -#endif - - virtual void Activate(); - virtual void Think(); - -#if defined( CLIENT_DLL ) - // NOTE: Ths enclosed particle effect binding will do all the drawing - virtual bool ShouldDraw() { return false; } - - int AllocateToolParticleEffectId(); - int GetToolParticleEffectId() const; - -private: - int m_nToolParticleEffectId; - bool m_bSimulate; -#endif - -public: - void FollowEntity(CBaseEntity *pEntity); - - // UTIL_Remove will be called after the specified amount of time. - // If you pass in -1, the entity will never go away automatically. - void SetLifetime(float lifetime); - -private: - CBaseParticleEntity( const CBaseParticleEntity & ); // not defined, not accessible -}; - - -#if defined( CLIENT_DLL ) - -inline int CBaseParticleEntity::GetToolParticleEffectId() const -{ - return m_nToolParticleEffectId; -} - -inline int CBaseParticleEntity::AllocateToolParticleEffectId() -{ - m_nToolParticleEffectId = ParticleMgr()->AllocateToolParticleEffectId(); - return m_nToolParticleEffectId; -} - -#endif // CLIENT_DLL - -#endif - - diff --git a/game/shared/baseplayer_shared.cpp b/game/shared/baseplayer_shared.cpp deleted file mode 100644 index b72530151..000000000 --- a/game/shared/baseplayer_shared.cpp +++ /dev/null @@ -1,1962 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements shared baseplayer class functionality -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "movevars_shared.h" -#include "util_shared.h" -#include "datacache/imdlcache.h" - -#if defined( CLIENT_DLL ) - - #include "iclientvehicle.h" - #include "prediction.h" - #include "c_basedoor.h" - #include "c_world.h" - #include "view.h" - - #define CRecipientFilter C_RecipientFilter - -#else - - #include "iservervehicle.h" - #include "trains.h" - #include "world.h" - #include "doors.h" - #include "ai_basenpc.h" - #include "env_zoom.h" - - extern int TrainSpeed(int iSpeed, int iMax); - -#endif - -#include "in_buttons.h" -#include "engine/IEngineSound.h" -#include "tier0/vprof.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" -#include "decals.h" -#include "obstacle_pushaway.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#if defined(GAME_DLL) && !defined(_XBOX) - extern ConVar sv_pushaway_max_force; - extern ConVar sv_pushaway_force; - extern ConVar sv_turbophysics; - - class CUsePushFilter : public CTraceFilterEntitiesOnly - { - public: - bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) - { - CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); - - // Static prop case... - if ( !pEntity ) - return false; - - // Only impact on physics objects - if ( !pEntity->VPhysicsGetObject() ) - return false; - - return g_pGameRules->CanEntityBeUsePushed( pEntity ); - } - }; -#endif - -#ifdef CLIENT_DLL -ConVar mp_usehwmmodels( "mp_usehwmmodels", "0", NULL, "Enable the use of the hw morph models. (-1 = never, 1 = always, 0 = based upon GPU)" ); // -1 = never, 0 = if hasfastvertextextures, 1 = always -#endif - -bool UseHWMorphModels() -{ -#ifdef CLIENT_DLL - if ( mp_usehwmmodels.GetInt() == 0 ) - return g_pMaterialSystemHardwareConfig->HasFastVertexTextures(); - - return mp_usehwmmodels.GetInt() > 0; -#else - return false; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CBasePlayer::GetTimeBase( void ) const -{ - return m_nTickBase * TICK_INTERVAL; -} - -//----------------------------------------------------------------------------- -// Purpose: Called every usercmd by the player PreThink -//----------------------------------------------------------------------------- -void CBasePlayer::ItemPreFrame() -{ - // Handle use events - PlayerUse(); - - CBaseCombatWeapon *pActive = GetActiveWeapon(); - - // Allow all the holstered weapons to update - for ( int i = 0; i < WeaponCount(); ++i ) - { - CBaseCombatWeapon *pWeapon = GetWeapon( i ); - - if ( pWeapon == NULL ) - continue; - - if ( pActive == pWeapon ) - continue; - - pWeapon->ItemHolsterFrame(); - } - - if ( gpGlobals->curtime < m_flNextAttack ) - return; - - if (!pActive) - return; - -#if defined( CLIENT_DLL ) - // Not predicting this weapon - if ( !pActive->IsPredicted() ) - return; -#endif - - pActive->ItemPreFrame(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBasePlayer::UsingStandardWeaponsInVehicle( void ) -{ - Assert( IsInAVehicle() ); -#if !defined( CLIENT_DLL ) - IServerVehicle *pVehicle = GetVehicle(); -#else - IClientVehicle *pVehicle = GetVehicle(); -#endif - Assert( pVehicle ); - if ( !pVehicle ) - return true; - - // NOTE: We *have* to do this before ItemPostFrame because ItemPostFrame - // may dump us out of the vehicle - int nRole = pVehicle->GetPassengerRole( this ); - bool bUsingStandardWeapons = pVehicle->IsPassengerUsingStandardWeapons( nRole ); - - // Fall through and check weapons, etc. if we're using them - if (!bUsingStandardWeapons ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Called every usercmd by the player PostThink -//----------------------------------------------------------------------------- -void CBasePlayer::ItemPostFrame() -{ - VPROF( "CBasePlayer::ItemPostFrame" ); - - // Put viewmodels into basically correct place based on new player origin - CalcViewModelView( EyePosition(), EyeAngles() ); - - // Don't process items while in a vehicle. - if ( GetVehicle() ) - { -#if defined( CLIENT_DLL ) - IClientVehicle *pVehicle = GetVehicle(); -#else - IServerVehicle *pVehicle = GetVehicle(); -#endif - - bool bUsingStandardWeapons = UsingStandardWeaponsInVehicle(); - -#if defined( CLIENT_DLL ) - if ( pVehicle->IsPredicted() ) -#endif - { - pVehicle->ItemPostFrame( this ); - } - - if (!bUsingStandardWeapons || !GetVehicle()) - return; - } - - - // check if the player is using something - if ( m_hUseEntity != NULL ) - { -#if !defined( CLIENT_DLL ) - Assert( !IsInAVehicle() ); - ImpulseCommands();// this will call playerUse -#endif - return; - } - - if ( gpGlobals->curtime < m_flNextAttack ) - { - if ( GetActiveWeapon() ) - { - GetActiveWeapon()->ItemBusyFrame(); - } - } - else - { - if ( GetActiveWeapon() && (!IsInAVehicle() || UsingStandardWeaponsInVehicle()) ) - { -#if defined( CLIENT_DLL ) - // Not predicting this weapon - if ( GetActiveWeapon()->IsPredicted() ) -#endif - - { - GetActiveWeapon()->ItemPostFrame( ); - } - } - } - -#if !defined( CLIENT_DLL ) - ImpulseCommands(); -#else - // NOTE: If we ever support full impulse commands on the client, - // remove this line and call ImpulseCommands instead. - m_nImpulse = 0; -#endif -} - - -//----------------------------------------------------------------------------- -// Eye angles -//----------------------------------------------------------------------------- -const QAngle &CBasePlayer::EyeAngles( ) -{ - // NOTE: Viewangles are measured *relative* to the parent's coordinate system - CBaseEntity *pMoveParent = const_cast(this)->GetMoveParent(); - - if ( !pMoveParent ) - { - return pl.v_angle; - } - - // FIXME: Cache off the angles? - matrix3x4_t eyesToParent, eyesToWorld; - AngleMatrix( pl.v_angle, eyesToParent ); - ConcatTransforms( pMoveParent->EntityToWorldTransform(), eyesToParent, eyesToWorld ); - - static QAngle angEyeWorld; - MatrixAngles( eyesToWorld, angEyeWorld ); - return angEyeWorld; -} - - -const QAngle &CBasePlayer::LocalEyeAngles() -{ - return pl.v_angle; -} - -//----------------------------------------------------------------------------- -// Actual Eye position + angles -//----------------------------------------------------------------------------- -Vector CBasePlayer::EyePosition( ) -{ - if ( GetVehicle() != NULL ) - { - // Return the cached result - CacheVehicleView(); - return m_vecVehicleViewOrigin; - } - else - { -#ifdef CLIENT_DLL - if ( IsObserver() ) - { - if ( m_iObserverMode == OBS_MODE_CHASE ) - { - if ( IsLocalPlayer() ) - { - return MainViewOrigin(); - } - } - } -#endif - return BaseClass::EyePosition(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : const Vector -//----------------------------------------------------------------------------- -const Vector CBasePlayer::GetPlayerMins( void ) const -{ - if ( IsObserver() ) - { - return VEC_OBS_HULL_MIN; - } - else - { - if ( GetFlags() & FL_DUCKING ) - { - return VEC_DUCK_HULL_MIN; - } - else - { - return VEC_HULL_MIN; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : const Vector -//----------------------------------------------------------------------------- -const Vector CBasePlayer::GetPlayerMaxs( void ) const -{ - if ( IsObserver() ) - { - return VEC_OBS_HULL_MAX; - } - else - { - if ( GetFlags() & FL_DUCKING ) - { - return VEC_DUCK_HULL_MAX; - } - else - { - return VEC_HULL_MAX; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Update the vehicle view, or simply return the cached position and angles -//----------------------------------------------------------------------------- -void CBasePlayer::CacheVehicleView( void ) -{ - // If we've calculated the view this frame, then there's no need to recalculate it - if ( m_nVehicleViewSavedFrame == gpGlobals->framecount ) - return; - -#ifdef CLIENT_DLL - IClientVehicle *pVehicle = GetVehicle(); -#else - IServerVehicle *pVehicle = GetVehicle(); -#endif - - if ( pVehicle != NULL ) - { - int nRole = pVehicle->GetPassengerRole( this ); - - // Get our view for this frame - pVehicle->GetVehicleViewPosition( nRole, &m_vecVehicleViewOrigin, &m_vecVehicleViewAngles, &m_flVehicleViewFOV ); - m_nVehicleViewSavedFrame = gpGlobals->framecount; - } -} - -//----------------------------------------------------------------------------- -// Returns eye vectors -//----------------------------------------------------------------------------- -void CBasePlayer::EyeVectors( Vector *pForward, Vector *pRight, Vector *pUp ) -{ - if ( GetVehicle() != NULL ) - { - // Cache or retrieve our calculated position in the vehicle - CacheVehicleView(); - AngleVectors( m_vecVehicleViewAngles, pForward, pRight, pUp ); - } - else - { - AngleVectors( EyeAngles(), pForward, pRight, pUp ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the eye position and angle vectors. -//----------------------------------------------------------------------------- -void CBasePlayer::EyePositionAndVectors( Vector *pPosition, Vector *pForward, - Vector *pRight, Vector *pUp ) -{ - // Handle the view in the vehicle - if ( GetVehicle() != NULL ) - { - CacheVehicleView(); - AngleVectors( m_vecVehicleViewAngles, pForward, pRight, pUp ); - - if ( pPosition != NULL ) - { - *pPosition = m_vecVehicleViewOrigin; - } - } - else - { - VectorCopy( BaseClass::EyePosition(), *pPosition ); - AngleVectors( EyeAngles(), pForward, pRight, pUp ); - } -} - -#ifdef CLIENT_DLL -surfacedata_t * CBasePlayer::GetFootstepSurface( const Vector &origin, const char *surfaceName ) -{ - return physprops->GetSurfaceData( physprops->GetSurfaceIndex( surfaceName ) ); -} -#endif - -surfacedata_t *CBasePlayer::GetLadderSurface( const Vector &origin ) -{ -#ifdef CLIENT_DLL - return GetFootstepSurface( origin, "ladder" ); -#else - return physprops->GetSurfaceData( physprops->GetSurfaceIndex( "ladder" ) ); -#endif -} - -void CBasePlayer::UpdateStepSound( surfacedata_t *psurface, const Vector &vecOrigin, const Vector &vecVelocity ) -{ - bool bWalking; - float fvol; - Vector knee; - Vector feet; - float height; - float speed; - float velrun; - float velwalk; - int fLadder; - - if ( m_flStepSoundTime > 0 ) - { - m_flStepSoundTime -= 1000.0f * gpGlobals->frametime; - if ( m_flStepSoundTime < 0 ) - { - m_flStepSoundTime = 0; - } - } - - if ( m_flStepSoundTime > 0 ) - return; - - if ( GetFlags() & (FL_FROZEN|FL_ATCONTROLS)) - return; - - if ( GetMoveType() == MOVETYPE_NOCLIP || GetMoveType() == MOVETYPE_OBSERVER ) - return; - - if ( !sv_footsteps.GetFloat() ) - return; - - speed = VectorLength( vecVelocity ); - float groundspeed = Vector2DLength( vecVelocity.AsVector2D() ); - - // determine if we are on a ladder - fLadder = ( GetMoveType() == MOVETYPE_LADDER ); - - GetStepSoundVelocities( &velwalk, &velrun ); - - bool onground = ( GetFlags() & FL_ONGROUND ); - bool movingalongground = ( groundspeed > 0.0001f ); - bool moving_fast_enough = ( speed >= velwalk ); - -#ifdef PORTAL - // In Portal we MUST play footstep sounds even when the player is moving very slowly - // This is used to count the number of footsteps they take in the challenge mode - // -Jeep - moving_fast_enough = true; -#endif - - // To hear step sounds you must be either on a ladder or moving along the ground AND - // You must be moving fast enough - - if ( !moving_fast_enough || !(fLadder || ( onground && movingalongground )) ) - return; - -// MoveHelper()->PlayerSetAnimation( PLAYER_WALK ); - - bWalking = speed < velrun; - - VectorCopy( vecOrigin, knee ); - VectorCopy( vecOrigin, feet ); - - height = GetPlayerMaxs()[ 2 ] - GetPlayerMins()[ 2 ]; - - knee[2] = vecOrigin[2] + 0.2 * height; - - // find out what we're stepping in or on... - if ( fLadder ) - { - psurface = GetLadderSurface(vecOrigin); - fvol = 0.5; - - SetStepSoundTime( STEPSOUNDTIME_ON_LADDER, bWalking ); - } - else if ( GetWaterLevel() == WL_Waist ) - { - static int iSkipStep = 0; - - if ( iSkipStep == 0 ) - { - iSkipStep++; - return; - } - - if ( iSkipStep++ == 3 ) - { - iSkipStep = 0; - } - psurface = physprops->GetSurfaceData( physprops->GetSurfaceIndex( "wade" ) ); - fvol = 0.65; - SetStepSoundTime( STEPSOUNDTIME_WATER_KNEE, bWalking ); - } - else if ( GetWaterLevel() == WL_Feet ) - { - psurface = physprops->GetSurfaceData( physprops->GetSurfaceIndex( "water" ) ); - fvol = bWalking ? 0.2 : 0.5; - - SetStepSoundTime( STEPSOUNDTIME_WATER_FOOT, bWalking ); - } - else - { - if ( !psurface ) - return; - - SetStepSoundTime( STEPSOUNDTIME_NORMAL, bWalking ); - - switch ( psurface->game.material ) - { - default: - case CHAR_TEX_CONCRETE: - fvol = bWalking ? 0.2 : 0.5; - break; - - case CHAR_TEX_METAL: - fvol = bWalking ? 0.2 : 0.5; - break; - - case CHAR_TEX_DIRT: - fvol = bWalking ? 0.25 : 0.55; - break; - - case CHAR_TEX_VENT: - fvol = bWalking ? 0.4 : 0.7; - break; - - case CHAR_TEX_GRATE: - fvol = bWalking ? 0.2 : 0.5; - break; - - case CHAR_TEX_TILE: - fvol = bWalking ? 0.2 : 0.5; - break; - - case CHAR_TEX_SLOSH: - fvol = bWalking ? 0.2 : 0.5; - break; - } - } - - // play the sound - // 65% volume if ducking - if ( GetFlags() & FL_DUCKING ) - { - fvol *= 0.65; - } - - PlayStepSound( feet, psurface, fvol, false ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : step - -// fvol - -// force - force sound to play -//----------------------------------------------------------------------------- -void CBasePlayer::PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, float fvol, bool force ) -{ - if ( gpGlobals->maxClients > 1 && !sv_footsteps.GetFloat() ) - return; - -#if defined( CLIENT_DLL ) - // during prediction play footstep sounds only once - if ( prediction->InPrediction() && !prediction->IsFirstTimePredicted() ) - return; -#endif - - if ( !psurface ) - return; - - int nSide = m_Local.m_nStepside; - unsigned short stepSoundName = nSide ? psurface->sounds.stepleft : psurface->sounds.stepright; - if ( !stepSoundName ) - return; - - m_Local.m_nStepside = !nSide; - - CSoundParameters params; - - Assert( nSide == 0 || nSide == 1 ); - - if ( m_StepSoundCache[ nSide ].m_usSoundNameIndex == stepSoundName ) - { - params = m_StepSoundCache[ nSide ].m_SoundParameters; - } - else - { - IPhysicsSurfaceProps *physprops = MoveHelper()->GetSurfaceProps(); - const char *pSoundName = physprops->GetString( stepSoundName ); - if ( !CBaseEntity::GetParametersForSound( pSoundName, params, NULL ) ) - return; - - // Only cache if there's one option. Otherwise we'd never here any other sounds - if ( params.count == 1 ) - { - m_StepSoundCache[ nSide ].m_usSoundNameIndex = stepSoundName; - m_StepSoundCache[ nSide ].m_SoundParameters = params; - } - } - - CRecipientFilter filter; - filter.AddRecipientsByPAS( vecOrigin ); - -#ifndef CLIENT_DLL - // in MP, server removes all players in the vecOrigin's PVS, these players generate the footsteps client side - if ( gpGlobals->maxClients > 1 ) - { - filter.RemoveRecipientsByPVS( vecOrigin ); - } -#endif - - EmitSound_t ep; - ep.m_nChannel = CHAN_BODY; - ep.m_pSoundName = params.soundname; - ep.m_flVolume = fvol; - ep.m_SoundLevel = params.soundlevel; - ep.m_nFlags = 0; - ep.m_nPitch = params.pitch; - ep.m_pOrigin = &vecOrigin; - - EmitSound( filter, entindex(), ep ); -} - -void CBasePlayer::UpdateButtonState( int nUserCmdButtonMask ) -{ - // Track button info so we can detect 'pressed' and 'released' buttons next frame - m_afButtonLast = m_nButtons; - - // Get button states - m_nButtons = nUserCmdButtonMask; - int buttonsChanged = m_afButtonLast ^ m_nButtons; - - // Debounced button codes for pressed/released - // UNDONE: Do we need auto-repeat? - m_afButtonPressed = buttonsChanged & m_nButtons; // The changed ones still down are "pressed" - m_afButtonReleased = buttonsChanged & (~m_nButtons); // The ones not down are "released" -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::GetStepSoundVelocities( float *velwalk, float *velrun ) -{ - // UNDONE: need defined numbers for run, walk, crouch, crouch run velocities!!!! - if ( ( GetFlags() & FL_DUCKING) || ( GetMoveType() == MOVETYPE_LADDER ) ) - { - *velwalk = 60; // These constants should be based on cl_movespeedkey * cl_forwardspeed somehow - *velrun = 80; - } - else - { - *velwalk = 90; - *velrun = 220; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::SetStepSoundTime( stepsoundtimes_t iStepSoundTime, bool bWalking ) -{ - switch ( iStepSoundTime ) - { - case STEPSOUNDTIME_NORMAL: - case STEPSOUNDTIME_WATER_FOOT: - m_flStepSoundTime = bWalking ? 400 : 300; - break; - - case STEPSOUNDTIME_ON_LADDER: - m_flStepSoundTime = 350; - break; - - case STEPSOUNDTIME_WATER_KNEE: - m_flStepSoundTime = 600; - break; - - default: - Assert(0); - break; - } - - // UNDONE: need defined numbers for run, walk, crouch, crouch run velocities!!!! - if ( ( GetFlags() & FL_DUCKING) || ( GetMoveType() == MOVETYPE_LADDER ) ) - { - m_flStepSoundTime += 100; - } -} - -Vector CBasePlayer::Weapon_ShootPosition( ) -{ - return EyePosition(); -} - -void CBasePlayer::SetAnimationExtension( const char *pExtension ) -{ - Q_strncpy( m_szAnimExtension, pExtension, sizeof(m_szAnimExtension) ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Set the weapon to switch to when the player uses the 'lastinv' command -//----------------------------------------------------------------------------- -void CBasePlayer::Weapon_SetLast( CBaseCombatWeapon *pWeapon ) -{ - m_hLastWeapon = pWeapon; -} - -//----------------------------------------------------------------------------- -// Purpose: Override base class so player can reset autoaim -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CBasePlayer::Weapon_Switch( CBaseCombatWeapon *pWeapon, int viewmodelindex /*=0*/ ) -{ - CBaseCombatWeapon *pLastWeapon = GetActiveWeapon(); - - if ( BaseClass::Weapon_Switch( pWeapon, viewmodelindex )) - { - if ( pLastWeapon && Weapon_ShouldSetLast( pLastWeapon, GetActiveWeapon() ) ) - { - Weapon_SetLast( pLastWeapon->GetLastWeapon() ); - } - - CBaseViewModel *pViewModel = GetViewModel( viewmodelindex ); - Assert( pViewModel ); - if ( pViewModel ) - pViewModel->RemoveEffects( EF_NODRAW ); - ResetAutoaim( ); - return true; - } - return false; -} - -void CBasePlayer::SelectLastItem(void) -{ - if ( m_hLastWeapon.Get() == NULL ) - return; - - if ( GetActiveWeapon() && !GetActiveWeapon()->CanHolster() ) - return; - - SelectItem( m_hLastWeapon.Get()->GetClassname(), m_hLastWeapon.Get()->GetSubType() ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Abort any reloads we're in -//----------------------------------------------------------------------------- -void CBasePlayer::AbortReload( void ) -{ - if ( GetActiveWeapon() ) - { - GetActiveWeapon()->AbortReload(); - } -} - -#if !defined( NO_ENTITY_PREDICTION ) -void CBasePlayer::AddToPlayerSimulationList( CBaseEntity *other ) -{ - CHandle< CBaseEntity > h; - h = other; - // Already in list - if ( m_SimulatedByThisPlayer.Find( h ) != m_SimulatedByThisPlayer.InvalidIndex() ) - return; - - Assert( other->IsPlayerSimulated() ); - - m_SimulatedByThisPlayer.AddToTail( h ); -} - -//----------------------------------------------------------------------------- -// Purpose: Fixme, this should occur if the player fails to drive simulation -// often enough!!! -// Input : *other - -//----------------------------------------------------------------------------- -void CBasePlayer::RemoveFromPlayerSimulationList( CBaseEntity *other ) -{ - if ( !other ) - return; - - Assert( other->IsPlayerSimulated() ); - Assert( other->GetSimulatingPlayer() == this ); - - - CHandle< CBaseEntity > h; - h = other; - - m_SimulatedByThisPlayer.FindAndRemove( h ); -} - -void CBasePlayer::SimulatePlayerSimulatedEntities( void ) -{ - int c = m_SimulatedByThisPlayer.Count(); - int i; - - for ( i = c - 1; i >= 0; i-- ) - { - CHandle< CBaseEntity > h; - - h = m_SimulatedByThisPlayer[ i ]; - CBaseEntity *e = h; - - if ( !e || !e->IsPlayerSimulated() ) - { - m_SimulatedByThisPlayer.Remove( i ); - continue; - } - -#if defined( CLIENT_DLL ) - if ( e->IsClientCreated() && prediction->InPrediction() && !prediction->IsFirstTimePredicted() ) - { - continue; - } -#endif - Assert( e->IsPlayerSimulated() ); - Assert( e->GetSimulatingPlayer() == this ); - - e->PhysicsSimulate(); - } - - // Loop through all entities again, checking their untouch if flagged to do so - c = m_SimulatedByThisPlayer.Count(); - - for ( i = c - 1; i >= 0; i-- ) - { - CHandle< CBaseEntity > h; - - h = m_SimulatedByThisPlayer[ i ]; - - CBaseEntity *e = h; - if ( !e || !e->IsPlayerSimulated() ) - { - m_SimulatedByThisPlayer.Remove( i ); - continue; - } - -#if defined( CLIENT_DLL ) - if ( e->IsClientCreated() && prediction->InPrediction() && !prediction->IsFirstTimePredicted() ) - { - continue; - } -#endif - - Assert( e->IsPlayerSimulated() ); - Assert( e->GetSimulatingPlayer() == this ); - - if ( !e->GetCheckUntouch() ) - continue; - - e->PhysicsCheckForEntityUntouch(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::ClearPlayerSimulationList( void ) -{ - int c = m_SimulatedByThisPlayer.Size(); - int i; - - for ( i = c - 1; i >= 0; i-- ) - { - CHandle< CBaseEntity > h; - - h = m_SimulatedByThisPlayer[ i ]; - CBaseEntity *e = h; - if ( e ) - { - e->UnsetPlayerSimulated(); - } - } - - m_SimulatedByThisPlayer.RemoveAll(); -} -#endif - -//----------------------------------------------------------------------------- -// Purpose: Return true if we should allow selection of the specified item -//----------------------------------------------------------------------------- -bool CBasePlayer::Weapon_ShouldSelectItem( CBaseCombatWeapon *pWeapon ) -{ - return ( pWeapon != GetActiveWeapon() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::SelectItem( const char *pstr, int iSubType ) -{ - if (!pstr) - return; - - CBaseCombatWeapon *pItem = Weapon_OwnsThisType( pstr, iSubType ); - - if (!pItem) - return; - - if( GetObserverMode() != OBS_MODE_NONE ) - return;// Observers can't select things. - - if ( !Weapon_ShouldSelectItem( pItem ) ) - return; - - // FIX, this needs to queue them up and delay - // Make sure the current weapon can be holstered - if ( GetActiveWeapon() ) - { - if ( !GetActiveWeapon()->CanHolster() ) - return; - - ResetAutoaim( ); - } - - Weapon_Switch( pItem ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -ConVar sv_debug_player_use( "sv_debug_player_use", "0", FCVAR_REPLICATED, "Visualizes +use logic. Green cross=trace success, Red cross=trace too far, Green box=radius success" ); -float IntervalDistance( float x, float x0, float x1 ) -{ - // swap so x0 < x1 - if ( x0 > x1 ) - { - float tmp = x0; - x0 = x1; - x1 = tmp; - } - - if ( x < x0 ) - return x0-x; - else if ( x > x1 ) - return x - x1; - return 0; -} - -CBaseEntity *CBasePlayer::FindUseEntity() -{ - Vector forward, up; - EyeVectors( &forward, NULL, &up ); - - trace_t tr; - // Search for objects in a sphere (tests for entities that are not solid, yet still useable) - Vector searchCenter = EyePosition(); - - // NOTE: Some debris objects are useable too, so hit those as well - // A button, etc. can be made out of clip brushes, make sure it's +useable via a traceline, too. - int useableContents = MASK_SOLID | CONTENTS_DEBRIS | CONTENTS_PLAYERCLIP; - -#ifdef CSTRIKE_DLL - useableContents = MASK_NPCSOLID_BRUSHONLY | MASK_OPAQUE_AND_NPCS; -#endif - -#ifdef HL1_DLL - useableContents = MASK_SOLID; -#endif -#ifndef CLIENT_DLL - CBaseEntity *pFoundByTrace = NULL; -#endif - - // UNDONE: Might be faster to just fold this range into the sphere query - CBaseEntity *pObject = NULL; - - float nearestDist = FLT_MAX; - // try the hit entity if there is one, or the ground entity if there isn't. - CBaseEntity *pNearest = NULL; - - const int NUM_TANGENTS = 8; - // trace a box at successive angles down - // forward, 45 deg, 30 deg, 20 deg, 15 deg, 10 deg, -10, -15 - const float tangents[NUM_TANGENTS] = { 0, 1, 0.57735026919f, 0.3639702342f, 0.267949192431f, 0.1763269807f, -0.1763269807f, -0.267949192431f }; - for ( int i = 0; i < NUM_TANGENTS; i++ ) - { - if ( i == 0 ) - { - UTIL_TraceLine( searchCenter, searchCenter + forward * 1024, useableContents, this, COLLISION_GROUP_NONE, &tr ); - } - else - { - Vector down = forward - tangents[i]*up; - VectorNormalize(down); - UTIL_TraceHull( searchCenter, searchCenter + down * 72, -Vector(16,16,16), Vector(16,16,16), useableContents, this, COLLISION_GROUP_NONE, &tr ); - } - pObject = tr.m_pEnt; - -#ifndef CLIENT_DLL - pFoundByTrace = pObject; -#endif - bool bUsable = IsUseableEntity(pObject, 0); - while ( pObject && !bUsable && pObject->GetMoveParent() ) - { - pObject = pObject->GetMoveParent(); - bUsable = IsUseableEntity(pObject, 0); - } - - if ( bUsable ) - { - Vector delta = tr.endpos - tr.startpos; - float centerZ = CollisionProp()->WorldSpaceCenter().z; - delta.z = IntervalDistance( tr.endpos.z, centerZ + CollisionProp()->OBBMins().z, centerZ + CollisionProp()->OBBMaxs().z ); - float dist = delta.Length(); - if ( dist < PLAYER_USE_RADIUS ) - { -#ifndef CLIENT_DLL - - if ( sv_debug_player_use.GetBool() ) - { - NDebugOverlay::Line( searchCenter, tr.endpos, 0, 255, 0, true, 30 ); - NDebugOverlay::Cross3D( tr.endpos, 16, 0, 255, 0, true, 30 ); - } - - if ( pObject->MyNPCPointer() && pObject->MyNPCPointer()->IsPlayerAlly( this ) ) - { - // If about to select an NPC, do a more thorough check to ensure - // that we're selecting the right one from a group. - pObject = DoubleCheckUseNPC( pObject, searchCenter, forward ); - } -#endif - if ( sv_debug_player_use.GetBool() ) - { - Msg( "Trace using: %s\n", pObject ? pObject->GetDebugName() : "no usable entity found" ); - } - - pNearest = pObject; - - // if this is directly under the cursor just return it now - if ( i == 0 ) - return pObject; - } - } - } - - // check ground entity first - // if you've got a useable ground entity, then shrink the cone of this search to 45 degrees - // otherwise, search out in a 90 degree cone (hemisphere) - if ( GetGroundEntity() && IsUseableEntity(GetGroundEntity(), FCAP_USE_ONGROUND) ) - { - pNearest = GetGroundEntity(); - } - if ( pNearest ) - { - // estimate nearest object by distance from the view vector - Vector point; - pNearest->CollisionProp()->CalcNearestPoint( searchCenter, &point ); - nearestDist = CalcDistanceToLine( point, searchCenter, forward ); - if ( sv_debug_player_use.GetBool() ) - { - Msg("Trace found %s, dist %.2f\n", pNearest->GetClassname(), nearestDist ); - } - } - - for ( CEntitySphereQuery sphere( searchCenter, PLAYER_USE_RADIUS ); ( pObject = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() ) - { - if ( !pObject ) - continue; - - if ( !IsUseableEntity( pObject, FCAP_USE_IN_RADIUS ) ) - continue; - - // see if it's more roughly in front of the player than previous guess - Vector point; - pObject->CollisionProp()->CalcNearestPoint( searchCenter, &point ); - - Vector dir = point - searchCenter; - VectorNormalize(dir); - float dot = DotProduct( dir, forward ); - - // Need to be looking at the object more or less - if ( dot < 0.8 ) - continue; - - float dist = CalcDistanceToLine( point, searchCenter, forward ); - - if ( sv_debug_player_use.GetBool() ) - { - Msg("Radius found %s, dist %.2f\n", pObject->GetClassname(), dist ); - } - - if ( dist < nearestDist ) - { - // Since this has purely been a radius search to this point, we now - // make sure the object isn't behind glass or a grate. - trace_t trCheckOccluded; - UTIL_TraceLine( searchCenter, point, useableContents, this, COLLISION_GROUP_NONE, &trCheckOccluded ); - - if ( trCheckOccluded.fraction == 1.0 || trCheckOccluded.m_pEnt == pObject ) - { - pNearest = pObject; - nearestDist = dist; - } - } - } - -#ifndef CLIENT_DLL - if ( !pNearest ) - { - // Haven't found anything near the player to use, nor any NPC's at distance. - // Check to see if the player is trying to select an NPC through a rail, fence, or other 'see-though' volume. - trace_t trAllies; - UTIL_TraceLine( searchCenter, searchCenter + forward * PLAYER_USE_RADIUS, MASK_OPAQUE_AND_NPCS, this, COLLISION_GROUP_NONE, &trAllies ); - - if ( trAllies.m_pEnt && IsUseableEntity( trAllies.m_pEnt, 0 ) && trAllies.m_pEnt->MyNPCPointer() && trAllies.m_pEnt->MyNPCPointer()->IsPlayerAlly( this ) ) - { - // This is an NPC, take it! - pNearest = trAllies.m_pEnt; - } - } - - if ( pNearest && pNearest->MyNPCPointer() && pNearest->MyNPCPointer()->IsPlayerAlly( this ) ) - { - pNearest = DoubleCheckUseNPC( pNearest, searchCenter, forward ); - } - - if ( sv_debug_player_use.GetBool() ) - { - if ( !pNearest ) - { - NDebugOverlay::Line( searchCenter, tr.endpos, 255, 0, 0, true, 30 ); - NDebugOverlay::Cross3D( tr.endpos, 16, 255, 0, 0, true, 30 ); - } - else if ( pNearest == pFoundByTrace ) - { - NDebugOverlay::Line( searchCenter, tr.endpos, 0, 255, 0, true, 30 ); - NDebugOverlay::Cross3D( tr.endpos, 16, 0, 255, 0, true, 30 ); - } - else - { - NDebugOverlay::Box( pNearest->WorldSpaceCenter(), Vector(-8, -8, -8), Vector(8, 8, 8), 0, 255, 0, true, 30 ); - } - } -#endif - - if ( sv_debug_player_use.GetBool() ) - { - Msg( "Radial using: %s\n", pNearest ? pNearest->GetDebugName() : "no usable entity found" ); - } - - return pNearest; -} - -//----------------------------------------------------------------------------- -// Purpose: Handles USE keypress -//----------------------------------------------------------------------------- -void CBasePlayer::PlayerUse ( void ) -{ -#ifdef GAME_DLL - // Was use pressed or released? - if ( ! ((m_nButtons | m_afButtonPressed | m_afButtonReleased) & IN_USE) ) - return; - - if ( IsObserver() ) - { - // do special use operation in oberserver mode - if ( m_afButtonPressed & IN_USE ) - ObserverUse( true ); - else if ( m_afButtonReleased & IN_USE ) - ObserverUse( false ); - - return; - } - -#if !defined(_XBOX) - // push objects in turbo physics mode - if ( (m_nButtons & IN_USE) && sv_turbophysics.GetBool() ) - { - Vector forward, up; - EyeVectors( &forward, NULL, &up ); - - trace_t tr; - // Search for objects in a sphere (tests for entities that are not solid, yet still useable) - Vector searchCenter = EyePosition(); - - CUsePushFilter filter; - - UTIL_TraceLine( searchCenter, searchCenter + forward * 96.0f, MASK_SOLID, &filter, &tr ); - - // try the hit entity if there is one, or the ground entity if there isn't. - CBaseEntity *entity = tr.m_pEnt; - - if ( entity ) - { - IPhysicsObject *pObj = entity->VPhysicsGetObject(); - - if ( pObj ) - { - Vector vPushAway = (entity->WorldSpaceCenter() - WorldSpaceCenter()); - vPushAway.z = 0; - - float flDist = VectorNormalize( vPushAway ); - flDist = MAX( flDist, 1 ); - - float flForce = sv_pushaway_force.GetFloat() / flDist; - flForce = MIN( flForce, sv_pushaway_max_force.GetFloat() ); - - pObj->ApplyForceOffset( vPushAway * flForce, WorldSpaceCenter() ); - } - } - } -#endif - - if ( m_afButtonPressed & IN_USE ) - { - // Controlling some latched entity? - if ( ClearUseEntity() ) - { - return; - } - else - { - if ( m_afPhysicsFlags & PFLAG_DIROVERRIDE ) - { - m_afPhysicsFlags &= ~PFLAG_DIROVERRIDE; - m_iTrain = TRAIN_NEW|TRAIN_OFF; - return; - } - else - { // Start controlling the train! - CBaseEntity *pTrain = GetGroundEntity(); - if ( pTrain && !(m_nButtons & IN_JUMP) && (GetFlags() & FL_ONGROUND) && (pTrain->ObjectCaps() & FCAP_DIRECTIONAL_USE) && pTrain->OnControls(this) ) - { - m_afPhysicsFlags |= PFLAG_DIROVERRIDE; - m_iTrain = TrainSpeed((int)pTrain->m_flSpeed, (int)((CFuncTrackTrain*)pTrain)->GetMaxSpeed()); - m_iTrain |= TRAIN_NEW; - EmitSound( "Player.UseTrain" ); - return; - } - } - } - } - - CBaseEntity *pUseEntity = FindUseEntity(); - - // Found an object - if ( pUseEntity ) - { - - //!!!UNDONE: traceline here to prevent +USEing buttons through walls - - int caps = pUseEntity->ObjectCaps(); - variant_t emptyVariant; - if ( ( (m_nButtons & IN_USE) && (caps & FCAP_CONTINUOUS_USE) ) || ( (m_afButtonPressed & IN_USE) && (caps & (FCAP_IMPULSE_USE|FCAP_ONOFF_USE)) ) ) - { - if ( caps & FCAP_CONTINUOUS_USE ) - { - m_afPhysicsFlags |= PFLAG_USING; - } - - if ( pUseEntity->ObjectCaps() & FCAP_ONOFF_USE ) - { - pUseEntity->AcceptInput( "Use", this, this, emptyVariant, USE_ON ); - } - else - { - pUseEntity->AcceptInput( "Use", this, this, emptyVariant, USE_TOGGLE ); - } - } - // UNDONE: Send different USE codes for ON/OFF. Cache last ONOFF_USE object to send 'off' if you turn away - else if ( (m_afButtonReleased & IN_USE) && (pUseEntity->ObjectCaps() & FCAP_ONOFF_USE) ) // BUGBUG This is an "off" use - { - pUseEntity->AcceptInput( "Use", this, this, emptyVariant, USE_OFF ); - } - } - else if ( m_afButtonPressed & IN_USE ) - { - PlayUseDenySound(); - } -#endif -} - -ConVar sv_suppress_viewpunch( "sv_suppress_viewpunch", "0", FCVAR_REPLICATED | FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::ViewPunch( const QAngle &angleOffset ) -{ - //See if we're suppressing the view punching - if ( sv_suppress_viewpunch.GetBool() ) - return; - - // We don't allow view kicks in the vehicle - if ( IsInAVehicle() ) - return; - - m_Local.m_vecPunchAngleVel += angleOffset * 20; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::ViewPunchReset( float tolerance ) -{ - if ( tolerance != 0 ) - { - tolerance *= tolerance; // square - float check = m_Local.m_vecPunchAngleVel->LengthSqr() + m_Local.m_vecPunchAngle->LengthSqr(); - if ( check > tolerance ) - return; - } - m_Local.m_vecPunchAngle = vec3_angle; - m_Local.m_vecPunchAngleVel = vec3_angle; -} - -#if defined( CLIENT_DLL ) - -#include "iviewrender.h" -#include "ivieweffects.h" - -#endif - -static ConVar smoothstairs( "smoothstairs", "1", FCVAR_REPLICATED, "Smooth player eye z coordinate when traversing stairs." ); - -//----------------------------------------------------------------------------- -// Handle view smoothing when going up or down stairs -//----------------------------------------------------------------------------- -void CBasePlayer::SmoothViewOnStairs( Vector& eyeOrigin ) -{ - CBaseEntity *pGroundEntity = GetGroundEntity(); - float flCurrentPlayerZ = GetLocalOrigin().z; - float flCurrentPlayerViewOffsetZ = GetViewOffset().z; - - // Smooth out stair step ups - // NOTE: Don't want to do this when the ground entity is moving the player - if ( ( pGroundEntity != NULL && pGroundEntity->GetMoveType() == MOVETYPE_NONE ) && ( flCurrentPlayerZ != m_flOldPlayerZ ) && smoothstairs.GetBool() && - m_flOldPlayerViewOffsetZ == flCurrentPlayerViewOffsetZ ) - { - int dir = ( flCurrentPlayerZ > m_flOldPlayerZ ) ? 1 : -1; - - float steptime = gpGlobals->frametime; - if (steptime < 0) - { - steptime = 0; - } - - m_flOldPlayerZ += steptime * 150 * dir; - - const float stepSize = 18.0f; - - if ( dir > 0 ) - { - if (m_flOldPlayerZ > flCurrentPlayerZ) - { - m_flOldPlayerZ = flCurrentPlayerZ; - } - if (flCurrentPlayerZ - m_flOldPlayerZ > stepSize) - { - m_flOldPlayerZ = flCurrentPlayerZ - stepSize; - } - } - else - { - if (m_flOldPlayerZ < flCurrentPlayerZ) - { - m_flOldPlayerZ = flCurrentPlayerZ; - } - if (flCurrentPlayerZ - m_flOldPlayerZ < -stepSize) - { - m_flOldPlayerZ = flCurrentPlayerZ + stepSize; - } - } - - eyeOrigin[2] += m_flOldPlayerZ - flCurrentPlayerZ; - } - else - { - m_flOldPlayerZ = flCurrentPlayerZ; - m_flOldPlayerViewOffsetZ = flCurrentPlayerViewOffsetZ; - } -} - -/*static bool IsWaterContents( int contents ) -{ - if ( contents & MASK_WATER ) - return true; - -// if ( contents & CONTENTS_TESTFOGVOLUME ) -// return true; - - return false; -}*/ - -void CBasePlayer::ResetObserverMode() -{ - - m_hObserverTarget.Set( 0 ); - m_iObserverMode = (int)OBS_MODE_NONE; - -#ifndef CLIENT_DLL - m_iObserverLastMode = OBS_MODE_ROAMING; - m_bForcedObserverMode = false; - m_afPhysicsFlags &= ~PFLAG_OBSERVER; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : eyeOrigin - -// eyeAngles - -// zNear - -// zFar - -// fov - -//----------------------------------------------------------------------------- -void CBasePlayer::CalcView( Vector &eyeOrigin, QAngle &eyeAngles, float &zNear, float &zFar, float &fov ) -{ -#if defined( CLIENT_DLL ) - IClientVehicle *pVehicle; -#else - IServerVehicle *pVehicle; -#endif - pVehicle = GetVehicle(); - - if ( !pVehicle ) - { - if ( IsObserver() ) - { - CalcObserverView( eyeOrigin, eyeAngles, fov ); - } - else - { - CalcPlayerView( eyeOrigin, eyeAngles, fov ); - } - } - else - { - CalcVehicleView( pVehicle, eyeOrigin, eyeAngles, zNear, zFar, fov ); - } -} - - -void CBasePlayer::CalcViewModelView( const Vector& eyeOrigin, const QAngle& eyeAngles) -{ - for ( int i = 0; i < MAX_VIEWMODELS; i++ ) - { - CBaseViewModel *vm = GetViewModel( i ); - if ( !vm ) - continue; - - vm->CalcViewModelView( this, eyeOrigin, eyeAngles ); - } -} - -void CBasePlayer::CalcPlayerView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov ) -{ -#if defined( CLIENT_DLL ) - if ( !prediction->InPrediction() ) - { - // FIXME: Move into prediction - view->DriftPitch(); - } -#endif - - VectorCopy( EyePosition(), eyeOrigin ); - - VectorCopy( EyeAngles(), eyeAngles ); - - -#if defined( CLIENT_DLL ) - if ( !prediction->InPrediction() ) -#endif - { - SmoothViewOnStairs( eyeOrigin ); - } - - // Snack off the origin before bob + water offset are applied - Vector vecBaseEyePosition = eyeOrigin; - - CalcViewRoll( eyeAngles ); - - // Apply punch angle - VectorAdd( eyeAngles, m_Local.m_vecPunchAngle, eyeAngles ); - -#if defined( CLIENT_DLL ) - if ( !prediction->InPrediction() ) - { - // Shake it up baby! - vieweffects->CalcShake(); - vieweffects->ApplyShake( eyeOrigin, eyeAngles, 1.0 ); - } -#endif - -#if defined( CLIENT_DLL ) - // Apply a smoothing offset to smooth out prediction errors. - Vector vSmoothOffset; - GetPredictionErrorSmoothingVector( vSmoothOffset ); - eyeOrigin += vSmoothOffset; - m_flObserverChaseDistance = 0.0; -#endif - - // calc current FOV - fov = GetFOV(); -} - -//----------------------------------------------------------------------------- -// Purpose: The main view setup function for vehicles -//----------------------------------------------------------------------------- -void CBasePlayer::CalcVehicleView( -#if defined( CLIENT_DLL ) - IClientVehicle *pVehicle, -#else - IServerVehicle *pVehicle, -#endif - Vector& eyeOrigin, QAngle& eyeAngles, - float& zNear, float& zFar, float& fov ) -{ - Assert( pVehicle ); - - // Start with our base origin and angles - CacheVehicleView(); - eyeOrigin = m_vecVehicleViewOrigin; - eyeAngles = m_vecVehicleViewAngles; - -#if defined( CLIENT_DLL ) - - fov = GetFOV(); - - // Allows the vehicle to change the clip planes - pVehicle->GetVehicleClipPlanes( zNear, zFar ); -#endif - - // Snack off the origin before bob + water offset are applied - Vector vecBaseEyePosition = eyeOrigin; - - CalcViewRoll( eyeAngles ); - - // Apply punch angle - VectorAdd( eyeAngles, m_Local.m_vecPunchAngle, eyeAngles ); - -#if defined( CLIENT_DLL ) - if ( !prediction->InPrediction() ) - { - // Shake it up baby! - vieweffects->CalcShake(); - vieweffects->ApplyShake( eyeOrigin, eyeAngles, 1.0 ); - } -#endif - -} - - -void CBasePlayer::CalcObserverView( Vector& eyeOrigin, QAngle& eyeAngles, float& fov ) -{ -#if defined( CLIENT_DLL ) - switch ( GetObserverMode() ) - { - - case OBS_MODE_DEATHCAM : CalcDeathCamView( eyeOrigin, eyeAngles, fov ); - break; - - case OBS_MODE_ROAMING : // just copy current position without view offset - case OBS_MODE_FIXED : CalcRoamingView( eyeOrigin, eyeAngles, fov ); - break; - - case OBS_MODE_IN_EYE : CalcInEyeCamView( eyeOrigin, eyeAngles, fov ); - break; - - case OBS_MODE_CHASE : CalcChaseCamView( eyeOrigin, eyeAngles, fov ); - break; - - case OBS_MODE_FREEZECAM : CalcFreezeCamView( eyeOrigin, eyeAngles, fov ); - break; - } -#else - // on server just copy target postions, final view positions will be calculated on client - VectorCopy( EyePosition(), eyeOrigin ); - VectorCopy( EyeAngles(), eyeAngles ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Compute roll angle for a particular lateral velocity -// Input : angles - -// velocity - -// rollangle - -// rollspeed - -// Output : float CViewRender::CalcRoll -//----------------------------------------------------------------------------- -float CBasePlayer::CalcRoll (const QAngle& angles, const Vector& velocity, float rollangle, float rollspeed) -{ - float sign; - float side; - float value; - - Vector forward, right, up; - - AngleVectors (angles, &forward, &right, &up); - - // Get amount of lateral movement - side = DotProduct( velocity, right ); - // Right or left side? - sign = side < 0 ? -1 : 1; - side = fabs(side); - - value = rollangle; - // Hit 100% of rollangle at rollspeed. Below that get linear approx. - if ( side < rollspeed ) - { - side = side * value / rollspeed; - } - else - { - side = value; - } - - // Scale by right/left sign - return side*sign; -} - -//----------------------------------------------------------------------------- -// Purpose: Determine view roll, including data kick -//----------------------------------------------------------------------------- -void CBasePlayer::CalcViewRoll( QAngle& eyeAngles ) -{ - if ( GetMoveType() == MOVETYPE_NOCLIP ) - return; - - float side = CalcRoll( GetAbsAngles(), GetAbsVelocity(), sv_rollangle.GetFloat(), sv_rollspeed.GetFloat() ); - eyeAngles[ROLL] += side; -} - - -void CBasePlayer::DoMuzzleFlash() -{ - for ( int i = 0; i < MAX_VIEWMODELS; i++ ) - { - CBaseViewModel *vm = GetViewModel( i ); - if ( !vm ) - continue; - - vm->DoMuzzleFlash(); - } - - BaseClass::DoMuzzleFlash(); -} - - -float CBasePlayer::GetFOVDistanceAdjustFactor() -{ - float defaultFOV = (float)GetDefaultFOV(); - float localFOV = (float)GetFOV(); - - if ( localFOV == defaultFOV || defaultFOV < 0.001f ) - { - return 1.0f; - } - - // If FOV is lower, then we're "zoomed" in and this will give a factor < 1 so apparent LOD distances can be - // shorted accordingly - return localFOV / defaultFOV; - -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &vecTracerSrc - -// &tr - -// iTracerType - -//----------------------------------------------------------------------------- -void CBasePlayer::MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ) -{ - if ( GetActiveWeapon() ) - { - GetActiveWeapon()->MakeTracer( vecTracerSrc, tr, iTracerType ); - return; - } - - BaseClass::MakeTracer( vecTracerSrc, tr, iTracerType ); -} - - -void CBasePlayer::SharedSpawn() -{ - SetMoveType( MOVETYPE_WALK ); - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_NOT_STANDABLE ); - SetFriction( 1.0f ); - - pl.deadflag = false; - m_lifeState = LIFE_ALIVE; - m_iHealth = 100; - m_takedamage = DAMAGE_YES; - - m_Local.m_bDrawViewmodel = true; - m_Local.m_flStepSize = sv_stepsize.GetFloat(); - m_Local.m_bAllowAutoMovement = true; - - m_nRenderFX = kRenderFxNone; - m_flNextAttack = gpGlobals->curtime; - m_flMaxspeed = 0.0f; - - MDLCACHE_CRITICAL_SECTION(); - SetSequence( SelectWeightedSequence( ACT_IDLE ) ); - - if ( GetFlags() & FL_DUCKING ) - SetCollisionBounds( VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX ); - else - SetCollisionBounds( VEC_HULL_MIN, VEC_HULL_MAX ); - - // dont let uninitialized value here hurt the player - m_Local.m_flFallVelocity = 0; - - SetBloodColor( BLOOD_COLOR_RED ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CBasePlayer::GetDefaultFOV( void ) const -{ -#if defined( CLIENT_DLL ) - if ( GetObserverMode() == OBS_MODE_IN_EYE ) - { - C_BasePlayer *pTargetPlayer = dynamic_cast( GetObserverTarget() ); - - if ( pTargetPlayer && !pTargetPlayer->IsObserver() ) - { - return pTargetPlayer->GetDefaultFOV(); - } - } -#endif - - int iFOV = ( m_iDefaultFOV == 0 ) ? g_pGameRules->DefaultFOV() : m_iDefaultFOV; - - return iFOV; -} - -void CBasePlayer::AvoidPhysicsProps( CUserCmd *pCmd ) -{ -#ifndef _XBOX - // Don't avoid if noclipping or in movetype none - switch ( GetMoveType() ) - { - case MOVETYPE_NOCLIP: - case MOVETYPE_NONE: - case MOVETYPE_OBSERVER: - return; - default: - break; - } - - if ( GetObserverMode() != OBS_MODE_NONE || !IsAlive() ) - return; - - AvoidPushawayProps( this, pCmd ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CBasePlayer::GetTracerType( void ) -{ - if ( GetActiveWeapon() ) - { - return GetActiveWeapon()->GetTracerType(); - } - - return BaseClass::GetTracerType(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::ClearZoomOwner( void ) -{ - m_hZoomOwner = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Sets the FOV of the client, doing interpolation between old and new if requested -// Input : FOV - New FOV -// zoomRate - Amount of time (in seconds) to move between old and new FOV -//----------------------------------------------------------------------------- -bool CBasePlayer::SetFOV( CBaseEntity *pRequester, int FOV, float zoomRate, int iZoomStart /* = 0 */ ) -{ - //NOTENOTE: You MUST specify who is requesting the zoom change - assert( pRequester != NULL ); - if ( pRequester == NULL ) - return false; - - // If we already have an owner, we only allow requests from that owner - if ( ( m_hZoomOwner.Get() != NULL ) && ( m_hZoomOwner.Get() != pRequester ) ) - { -#ifdef GAME_DLL - if ( CanOverrideEnvZoomOwner( m_hZoomOwner.Get() ) == false ) -#endif - return false; - } - else - { - //FIXME: Maybe do this is as an accessor instead - if ( FOV == 0 ) - { - m_hZoomOwner = NULL; - } - else - { - m_hZoomOwner = pRequester; - } - } - - // Setup our FOV and our scaling time - - if ( iZoomStart > 0 ) - { - m_iFOVStart = iZoomStart; - } - else - { - m_iFOVStart = GetFOV(); - } - - m_flFOVTime = gpGlobals->curtime; - m_iFOV = FOV; - - m_Local.m_flFOVRate = zoomRate; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBasePlayer::UpdateUnderwaterState( void ) -{ - if ( GetWaterLevel() == WL_Eyes ) - { - if ( IsPlayerUnderwater() == false ) - { - SetPlayerUnderwater( true ); - } - return; - } - - if ( IsPlayerUnderwater() ) - { - SetPlayerUnderwater( false ); - } - - if ( GetWaterLevel() == 0 ) - { - if ( GetFlags() & FL_INWATER ) - { -#ifndef CLIENT_DLL - if ( m_iHealth > 0 && IsAlive() ) - { - EmitSound( "Player.Wade" ); - } -#endif - RemoveFlag( FL_INWATER ); - } - } - else if ( !(GetFlags() & FL_INWATER) ) - { -#ifndef CLIENT_DLL - // player enter water sound - if (GetWaterType() == CONTENTS_WATER) - { - EmitSound( "Player.Wade" ); - } -#endif - - AddFlag( FL_INWATER ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: data accessor -// ensure that for every emitsound there is a matching stopsound -//----------------------------------------------------------------------------- -void CBasePlayer::SetPlayerUnderwater( bool state ) -{ - if ( m_bPlayerUnderwater != state ) - { - m_bPlayerUnderwater = state; - -#ifdef CLIENT_DLL - if ( state ) - EmitSound( "Player.AmbientUnderWater" ); - else - StopSound( "Player.AmbientUnderWater" ); -#endif - } -} - - -void CBasePlayer::SetPreviouslyPredictedOrigin( const Vector &vecAbsOrigin ) -{ - m_vecPreviouslyPredictedOrigin = vecAbsOrigin; -} - -const Vector &CBasePlayer::GetPreviouslyPredictedOrigin() const -{ - return m_vecPreviouslyPredictedOrigin; -} - -bool fogparams_t::operator !=( const fogparams_t& other ) const -{ - if ( this->enable != other.enable || - this->blend != other.blend || - !VectorsAreEqual(this->dirPrimary, other.dirPrimary, 0.01f ) || - this->colorPrimary.Get() != other.colorPrimary.Get() || - this->colorSecondary.Get() != other.colorSecondary.Get() || - this->start != other.start || - this->end != other.end || - this->farz != other.farz || - this->maxdensity != other.maxdensity || - this->colorPrimaryLerpTo.Get() != other.colorPrimaryLerpTo.Get() || - this->colorSecondaryLerpTo.Get() != other.colorSecondaryLerpTo.Get() || - this->startLerpTo != other.startLerpTo || - this->endLerpTo != other.endLerpTo || - this->lerptime != other.lerptime || - this->duration != other.duration ) - return true; - - return false; -} - -void CBasePlayer::IncrementEFNoInterpParity() -{ - // Only matters in multiplayer - if ( gpGlobals->maxClients == 1 ) - return; - m_ubEFNoInterpParity = (m_ubEFNoInterpParity + 1) % NOINTERP_PARITY_MAX; -} - -int CBasePlayer::GetEFNoInterpParity() const -{ - return (int)m_ubEFNoInterpParity; -} diff --git a/game/shared/baseplayer_shared.h b/game/shared/baseplayer_shared.h deleted file mode 100644 index 9001d9583..000000000 --- a/game/shared/baseplayer_shared.h +++ /dev/null @@ -1,66 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef BASEPLAYER_SHARED_H -#define BASEPLAYER_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - -// PlayerUse defines -#define PLAYER_USE_RADIUS 80.f -#define CONE_45_DEGREES 0.707f -#define CONE_15_DEGREES 0.9659258f -#define CONE_90_DEGREES 0 - -#define TRAIN_ACTIVE 0x80 -#define TRAIN_NEW 0xc0 -#define TRAIN_OFF 0x00 -#define TRAIN_NEUTRAL 0x01 -#define TRAIN_SLOW 0x02 -#define TRAIN_MEDIUM 0x03 -#define TRAIN_FAST 0x04 -#define TRAIN_BACK 0x05 - -// entity messages -#define PLAY_PLAYER_JINGLE 1 -#define UPDATE_PLAYER_RADAR 2 - -#define DEATH_ANIMATION_TIME 3.0f - -// multiplayer only -#define NOINTERP_PARITY_MAX 4 -#define NOINTERP_PARITY_MAX_BITS 2 - -typedef struct -{ - Vector m_vecAutoAimDir; // The direction autoaim wishes to point. - Vector m_vecAutoAimPoint; // The point (world space) that autoaim is aiming at. - EHANDLE m_hAutoAimEntity; // The entity that autoaim is aiming at. - bool m_bAutoAimAssisting; // If this is true, autoaim is aiming at the target. If false, the player is naturally aiming. - bool m_bOnTargetNatural; - float m_fScale; - float m_fMaxDist; -} autoaim_params_t; - -enum stepsoundtimes_t -{ - STEPSOUNDTIME_NORMAL = 0, - STEPSOUNDTIME_ON_LADDER, - STEPSOUNDTIME_WATER_KNEE, - STEPSOUNDTIME_WATER_FOOT, -}; - -// Shared header file for players -#if defined( CLIENT_DLL ) -#define CBasePlayer C_BasePlayer -#include "c_baseplayer.h" -#else -#include "player.h" -#endif - -#endif // BASEPLAYER_SHARED_H diff --git a/game/shared/baseviewmodel_shared.cpp b/game/shared/baseviewmodel_shared.cpp deleted file mode 100644 index 0d7e8b692..000000000 --- a/game/shared/baseviewmodel_shared.cpp +++ /dev/null @@ -1,641 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "baseviewmodel_shared.h" -#include "datacache/imdlcache.h" - -#if defined( CLIENT_DLL ) -#include "iprediction.h" -#include "prediction.h" -#else -#include "vguiscreen.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define VIEWMODEL_ANIMATION_PARITY_BITS 3 -#define SCREEN_OVERLAY_MATERIAL "vgui/screens/vgui_overlay" - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseViewModel::CBaseViewModel() -{ -#if defined( CLIENT_DLL ) - // NOTE: We do this here because the color is never transmitted for the view model. - m_nOldAnimationParity = 0; - m_EntClientFlags |= ENTCLIENTFLAG_ALWAYS_INTERPOLATE; -#endif - SetRenderColor( 255, 255, 255, 255 ); - - // View model of this weapon - m_sVMName = NULL_STRING; - // Prefix of the animations that should be used by the player carrying this weapon - m_sAnimationPrefix = NULL_STRING; - - m_nViewModelIndex = 0; - - m_nAnimationParity = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBaseViewModel::~CBaseViewModel() -{ -} - -void CBaseViewModel::UpdateOnRemove( void ) -{ - BaseClass::UpdateOnRemove(); - - DestroyControlPanels(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseViewModel::Precache( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseViewModel::Spawn( void ) -{ - Precache( ); - SetSize( Vector( -8, -4, -2), Vector(8, 4, 2) ); - SetSolid( SOLID_NONE ); -} - - -#if defined ( CSTRIKE_DLL ) && !defined ( CLIENT_DLL ) -#define VGUI_CONTROL_PANELS -#endif - -#if defined ( TF_DLL ) -#define VGUI_CONTROL_PANELS -#endif - -#ifdef INVASION_DLL -#define VGUI_CONTROL_PANELS -#endif - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseViewModel::SetControlPanelsActive( bool bState ) -{ -#if defined( VGUI_CONTROL_PANELS ) - // Activate control panel screens - for ( int i = m_hScreens.Count(); --i >= 0; ) - { - if (m_hScreens[i].Get()) - { - m_hScreens[i]->SetActive( bState ); - } - } -#endif -} - -//----------------------------------------------------------------------------- -// This is called by the base object when it's time to spawn the control panels -//----------------------------------------------------------------------------- -void CBaseViewModel::SpawnControlPanels() -{ -#if defined( VGUI_CONTROL_PANELS ) - char buf[64]; - - // Destroy existing panels - DestroyControlPanels(); - - CBaseCombatWeapon *weapon = m_hWeapon.Get(); - - if ( weapon == NULL ) - { - return; - } - - MDLCACHE_CRITICAL_SECTION(); - - // FIXME: Deal with dynamically resizing control panels? - - // If we're attached to an entity, spawn control panels on it instead of use - CBaseAnimating *pEntityToSpawnOn = this; - char *pOrgLL = "controlpanel%d_ll"; - char *pOrgUR = "controlpanel%d_ur"; - char *pAttachmentNameLL = pOrgLL; - char *pAttachmentNameUR = pOrgUR; - /* - if ( IsBuiltOnAttachment() ) - { - pEntityToSpawnOn = dynamic_cast((CBaseEntity*)m_hBuiltOnEntity.Get()); - if ( pEntityToSpawnOn ) - { - char sBuildPointLL[64]; - char sBuildPointUR[64]; - Q_snprintf( sBuildPointLL, sizeof( sBuildPointLL ), "bp%d_controlpanel%%d_ll", m_iBuiltOnPoint ); - Q_snprintf( sBuildPointUR, sizeof( sBuildPointUR ), "bp%d_controlpanel%%d_ur", m_iBuiltOnPoint ); - pAttachmentNameLL = sBuildPointLL; - pAttachmentNameUR = sBuildPointUR; - } - else - { - pEntityToSpawnOn = this; - } - } - */ - - Assert( pEntityToSpawnOn ); - - // Lookup the attachment point... - int nPanel; - for ( nPanel = 0; true; ++nPanel ) - { - Q_snprintf( buf, sizeof( buf ), pAttachmentNameLL, nPanel ); - int nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); - if (nLLAttachmentIndex <= 0) - { - // Try and use my panels then - pEntityToSpawnOn = this; - Q_snprintf( buf, sizeof( buf ), pOrgLL, nPanel ); - nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); - if (nLLAttachmentIndex <= 0) - return; - } - - Q_snprintf( buf, sizeof( buf ), pAttachmentNameUR, nPanel ); - int nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); - if (nURAttachmentIndex <= 0) - { - // Try and use my panels then - Q_snprintf( buf, sizeof( buf ), pOrgUR, nPanel ); - nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); - if (nURAttachmentIndex <= 0) - return; - } - - const char *pScreenName; - weapon->GetControlPanelInfo( nPanel, pScreenName ); - if (!pScreenName) - continue; - - const char *pScreenClassname; - weapon->GetControlPanelClassName( nPanel, pScreenClassname ); - if ( !pScreenClassname ) - continue; - - // Compute the screen size from the attachment points... - matrix3x4_t panelToWorld; - pEntityToSpawnOn->GetAttachment( nLLAttachmentIndex, panelToWorld ); - - matrix3x4_t worldToPanel; - MatrixInvert( panelToWorld, worldToPanel ); - - // Now get the lower right position + transform into panel space - Vector lr, lrlocal; - pEntityToSpawnOn->GetAttachment( nURAttachmentIndex, panelToWorld ); - MatrixGetColumn( panelToWorld, 3, lr ); - VectorTransform( lr, worldToPanel, lrlocal ); - - float flWidth = lrlocal.x; - float flHeight = lrlocal.y; - - CVGuiScreen *pScreen = CreateVGuiScreen( pScreenClassname, pScreenName, pEntityToSpawnOn, this, nLLAttachmentIndex ); - pScreen->ChangeTeam( GetTeamNumber() ); - pScreen->SetActualSize( flWidth, flHeight ); - pScreen->SetActive( false ); - pScreen->MakeVisibleOnlyToTeammates( false ); - -#ifdef INVASION_DLL - pScreen->SetOverlayMaterial( SCREEN_OVERLAY_MATERIAL ); -#endif - pScreen->SetAttachedToViewModel( true ); - int nScreen = m_hScreens.AddToTail( ); - m_hScreens[nScreen].Set( pScreen ); - } -#endif -} - -void CBaseViewModel::DestroyControlPanels() -{ -#if defined( VGUI_CONTROL_PANELS ) - // Kill the control panels - int i; - for ( i = m_hScreens.Count(); --i >= 0; ) - { - DestroyVGuiScreen( m_hScreens[i].Get() ); - } - m_hScreens.RemoveAll(); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEntity - -//----------------------------------------------------------------------------- -void CBaseViewModel::SetOwner( CBaseEntity *pEntity ) -{ - m_hOwner = pEntity; -#if !defined( CLIENT_DLL ) - // Make sure we're linked into hierarchy - //SetParent( pEntity ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : nIndex - -//----------------------------------------------------------------------------- -void CBaseViewModel::SetIndex( int nIndex ) -{ - m_nViewModelIndex = nIndex; - Assert( m_nViewModelIndex < (1 << VIEWMODEL_INDEX_BITS) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBaseViewModel::ViewModelIndex( ) const -{ - return m_nViewModelIndex; -} - -//----------------------------------------------------------------------------- -// Purpose: Pass our visibility on to our child screens -//----------------------------------------------------------------------------- -void CBaseViewModel::AddEffects( int nEffects ) -{ - if ( nEffects & EF_NODRAW ) - { - SetControlPanelsActive( false ); - } - - BaseClass::AddEffects( nEffects ); -} - -//----------------------------------------------------------------------------- -// Purpose: Pass our visibility on to our child screens -//----------------------------------------------------------------------------- -void CBaseViewModel::RemoveEffects( int nEffects ) -{ - if ( nEffects & EF_NODRAW ) - { - SetControlPanelsActive( true ); - } - - BaseClass::RemoveEffects( nEffects ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *modelname - -//----------------------------------------------------------------------------- -void CBaseViewModel::SetWeaponModel( const char *modelname, CBaseCombatWeapon *weapon ) -{ - m_hWeapon = weapon; - -#if defined( CLIENT_DLL ) - SetModel( modelname ); -#else - string_t str; - if ( modelname != NULL ) - { - str = MAKE_STRING( modelname ); - } - else - { - str = NULL_STRING; - } - - if ( str != m_sVMName ) - { - // Msg( "SetWeaponModel %s at %f\n", modelname, gpGlobals->curtime ); - m_sVMName = str; - SetModel( STRING( m_sVMName ) ); - - // Create any vgui control panels associated with the weapon - SpawnControlPanels(); - - bool showControlPanels = weapon && weapon->ShouldShowControlPanels(); - SetControlPanelsActive( showControlPanels ); - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CBaseCombatWeapon -//----------------------------------------------------------------------------- -CBaseCombatWeapon *CBaseViewModel::GetOwningWeapon( void ) -{ - return m_hWeapon.Get(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : sequence - -//----------------------------------------------------------------------------- -void CBaseViewModel::SendViewModelMatchingSequence( int sequence ) -{ - // since all we do is send a sequence number down to the client, - // set this here so other weapons code knows which sequence is playing. - SetSequence( sequence ); - - m_nAnimationParity = ( m_nAnimationParity + 1 ) & ( (1<curtime; -#else - CBaseCombatWeapon *weapon = m_hWeapon.Get(); - bool showControlPanels = weapon && weapon->ShouldShowControlPanels(); - SetControlPanelsActive( showControlPanels ); -#endif - - // Restart animation at frame 0 - SetCycle( 0 ); - ResetSequenceInfo(); -} - -#if defined( CLIENT_DLL ) -#include "ivieweffects.h" -#endif - -void CBaseViewModel::CalcViewModelView( CBasePlayer *owner, const Vector& eyePosition, const QAngle& eyeAngles ) -{ - // UNDONE: Calc this on the server? Disabled for now as it seems unnecessary to have this info on the server -#if defined( CLIENT_DLL ) - QAngle vmangoriginal = eyeAngles; - QAngle vmangles = eyeAngles; - Vector vmorigin = eyePosition; - - CBaseCombatWeapon *pWeapon = m_hWeapon.Get(); - //Allow weapon lagging - if ( pWeapon != NULL ) - { -#if defined( CLIENT_DLL ) - if ( !prediction->InPrediction() ) -#endif - { - // add weapon-specific bob - pWeapon->AddViewmodelBob( this, vmorigin, vmangles ); - } - } - // Add model-specific bob even if no weapon associated (for head bob for off hand models) - AddViewModelBob( owner, vmorigin, vmangles ); - // Add lag - CalcViewModelLag( vmorigin, vmangles, vmangoriginal ); - -#if defined( CLIENT_DLL ) - if ( !prediction->InPrediction() ) - { - // Let the viewmodel shake at about 10% of the amplitude of the player's view - vieweffects->ApplyShake( vmorigin, vmangles, 0.1 ); - } -#endif - - SetLocalOrigin( vmorigin ); - SetLocalAngles( vmangles ); - -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float g_fMaxViewModelLag = 1.5f; - -void CBaseViewModel::CalcViewModelLag( Vector& origin, QAngle& angles, QAngle& original_angles ) -{ - Vector vOriginalOrigin = origin; - QAngle vOriginalAngles = angles; - - // Calculate our drift - Vector forward; - AngleVectors( angles, &forward, NULL, NULL ); - - if ( gpGlobals->frametime != 0.0f ) - { - Vector vDifference; - VectorSubtract( forward, m_vecLastFacing, vDifference ); - - float flSpeed = 5.0f; - - // If we start to lag too far behind, we'll increase the "catch up" speed. Solves the problem with fast cl_yawspeed, m_yaw or joysticks - // rotating quickly. The old code would slam lastfacing with origin causing the viewmodel to pop to a new position - float flDiff = vDifference.Length(); - if ( (flDiff > g_fMaxViewModelLag) && (g_fMaxViewModelLag > 0.0f) ) - { - float flScale = flDiff / g_fMaxViewModelLag; - flSpeed *= flScale; - } - - // FIXME: Needs to be predictable? - VectorMA( m_vecLastFacing, flSpeed * gpGlobals->frametime, vDifference, m_vecLastFacing ); - // Make sure it doesn't grow out of control!!! - VectorNormalize( m_vecLastFacing ); - VectorMA( origin, 5.0f, vDifference * -1.0f, origin ); - - Assert( m_vecLastFacing.IsValid() ); - } - - Vector right, up; - AngleVectors( original_angles, &forward, &right, &up ); - - float pitch = original_angles[ PITCH ]; - if ( pitch > 180.0f ) - pitch -= 360.0f; - else if ( pitch < -180.0f ) - pitch += 360.0f; - - if ( g_fMaxViewModelLag == 0.0f ) - { - origin = vOriginalOrigin; - angles = vOriginalAngles; - } - - //FIXME: These are the old settings that caused too many exposed polys on some models - VectorMA( origin, -pitch * 0.035f, forward, origin ); - VectorMA( origin, -pitch * 0.03f, right, origin ); - VectorMA( origin, -pitch * 0.02f, up, origin); -} - -//----------------------------------------------------------------------------- -// Stub to keep networking consistent for DEM files -//----------------------------------------------------------------------------- -#if defined( CLIENT_DLL ) - extern void RecvProxy_EffectFlags( const CRecvProxyData *pData, void *pStruct, void *pOut ); - void RecvProxy_SequenceNum( const CRecvProxyData *pData, void *pStruct, void *pOut ); -#endif - -//----------------------------------------------------------------------------- -// Purpose: Resets anim cycle when the server changes the weapon on us -//----------------------------------------------------------------------------- -#if defined( CLIENT_DLL ) -static void RecvProxy_Weapon( const CRecvProxyData *pData, void *pStruct, void *pOut ) -{ - CBaseViewModel *pViewModel = ((CBaseViewModel*)pStruct); - CBaseCombatWeapon *pOldWeapon = pViewModel->GetOwningWeapon(); - - // Chain through to the default recieve proxy ... - RecvProxy_IntToEHandle( pData, pStruct, pOut ); - - // ... and reset our cycle index if the server is switching weapons on us - CBaseCombatWeapon *pNewWeapon = pViewModel->GetOwningWeapon(); - if ( pNewWeapon != pOldWeapon ) - { - // Restart animation at frame 0 - pViewModel->SetCycle( 0 ); - pViewModel->m_flAnimTime = gpGlobals->curtime; - } -} -#endif - - -LINK_ENTITY_TO_CLASS( viewmodel, CBaseViewModel ); - -IMPLEMENT_NETWORKCLASS_ALIASED( BaseViewModel, DT_BaseViewModel ) - -BEGIN_NETWORK_TABLE_NOBASE(CBaseViewModel, DT_BaseViewModel) -#if !defined( CLIENT_DLL ) - SendPropModelIndex(SENDINFO(m_nModelIndex)), - SendPropInt (SENDINFO(m_nBody), 8), - SendPropInt (SENDINFO(m_nSkin), 10), - SendPropInt (SENDINFO(m_nSequence), 8, SPROP_UNSIGNED), - SendPropInt (SENDINFO(m_nViewModelIndex), VIEWMODEL_INDEX_BITS, SPROP_UNSIGNED), - SendPropFloat (SENDINFO(m_flPlaybackRate), 8, SPROP_ROUNDUP, -4.0, 12.0f), - SendPropInt (SENDINFO(m_fEffects), 10, SPROP_UNSIGNED), - SendPropInt (SENDINFO(m_nAnimationParity), 3, SPROP_UNSIGNED ), - SendPropEHandle (SENDINFO(m_hWeapon)), - SendPropEHandle (SENDINFO(m_hOwner)), - - SendPropInt( SENDINFO( m_nNewSequenceParity ), EF_PARITY_BITS, SPROP_UNSIGNED ), - SendPropInt( SENDINFO( m_nResetEventsParity ), EF_PARITY_BITS, SPROP_UNSIGNED ), - SendPropInt( SENDINFO( m_nMuzzleFlashParity ), EF_MUZZLEFLASH_BITS, SPROP_UNSIGNED ), - -#if !defined( INVASION_DLL ) && !defined( INVASION_CLIENT_DLL ) - SendPropArray (SendPropFloat(SENDINFO_ARRAY(m_flPoseParameter), 8, 0, 0.0f, 1.0f), m_flPoseParameter), -#endif -#else - RecvPropInt (RECVINFO(m_nModelIndex)), - RecvPropInt (RECVINFO(m_nSkin)), - RecvPropInt (RECVINFO(m_nBody)), - RecvPropInt (RECVINFO(m_nSequence), 0, RecvProxy_SequenceNum ), - RecvPropInt (RECVINFO(m_nViewModelIndex)), - RecvPropFloat (RECVINFO(m_flPlaybackRate)), - RecvPropInt (RECVINFO(m_fEffects), 0, RecvProxy_EffectFlags ), - RecvPropInt (RECVINFO(m_nAnimationParity)), - RecvPropEHandle (RECVINFO(m_hWeapon), RecvProxy_Weapon ), - RecvPropEHandle (RECVINFO(m_hOwner)), - - RecvPropInt( RECVINFO( m_nNewSequenceParity )), - RecvPropInt( RECVINFO( m_nResetEventsParity )), - RecvPropInt( RECVINFO( m_nMuzzleFlashParity )), - -#if !defined( INVASION_DLL ) && !defined( INVASION_CLIENT_DLL ) - RecvPropArray(RecvPropFloat(RECVINFO(m_flPoseParameter[0]) ), m_flPoseParameter ), -#endif -#endif -END_NETWORK_TABLE() - -#ifdef CLIENT_DLL - -BEGIN_PREDICTION_DATA( CBaseViewModel ) - - // Networked - DEFINE_PRED_FIELD( m_nModelIndex, FIELD_SHORT, FTYPEDESC_INSENDTABLE | FTYPEDESC_MODELINDEX ), - DEFINE_PRED_FIELD( m_nSkin, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_nBody, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_nSequence, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_nViewModelIndex, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD_TOL( m_flPlaybackRate, FIELD_FLOAT, FTYPEDESC_INSENDTABLE, 0.125f ), - DEFINE_PRED_FIELD( m_fEffects, FIELD_INTEGER, FTYPEDESC_INSENDTABLE | FTYPEDESC_OVERRIDE ), - DEFINE_PRED_FIELD( m_nAnimationParity, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_hWeapon, FIELD_EHANDLE, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_flAnimTime, FIELD_FLOAT, 0 ), - - DEFINE_FIELD( m_hOwner, FIELD_EHANDLE ), - DEFINE_FIELD( m_flTimeWeaponIdle, FIELD_FLOAT ), - DEFINE_FIELD( m_Activity, FIELD_INTEGER ), - DEFINE_PRED_FIELD( m_flCycle, FIELD_FLOAT, FTYPEDESC_PRIVATE | FTYPEDESC_OVERRIDE | FTYPEDESC_NOERRORCHECK ), - -END_PREDICTION_DATA() - -void RecvProxy_SequenceNum( const CRecvProxyData *pData, void *pStruct, void *pOut ) -{ - CBaseViewModel *model = (CBaseViewModel *)pStruct; - if (pData->m_Value.m_Int != model->GetSequence()) - { - MDLCACHE_CRITICAL_SECTION(); - - model->SetSequence(pData->m_Value.m_Int); - model->m_flAnimTime = gpGlobals->curtime; - model->SetCycle(0); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CBaseViewModel::LookupAttachment( const char *pAttachmentName ) -{ - if ( m_hWeapon.Get() && m_hWeapon.Get()->WantsToOverrideViewmodelAttachments() ) - return m_hWeapon.Get()->LookupAttachment( pAttachmentName ); - - return BaseClass::LookupAttachment( pAttachmentName ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseViewModel::GetAttachment( int number, matrix3x4_t &matrix ) -{ - if ( m_hWeapon.Get() && m_hWeapon.Get()->WantsToOverrideViewmodelAttachments() ) - return m_hWeapon.Get()->GetAttachment( number, matrix ); - - return BaseClass::GetAttachment( number, matrix ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseViewModel::GetAttachment( int number, Vector &origin ) -{ - if ( m_hWeapon.Get() && m_hWeapon.Get()->WantsToOverrideViewmodelAttachments() ) - return m_hWeapon.Get()->GetAttachment( number, origin ); - - return BaseClass::GetAttachment( number, origin ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseViewModel::GetAttachment( int number, Vector &origin, QAngle &angles ) -{ - if ( m_hWeapon.Get() && m_hWeapon.Get()->WantsToOverrideViewmodelAttachments() ) - return m_hWeapon.Get()->GetAttachment( number, origin, angles ); - - return BaseClass::GetAttachment( number, origin, angles ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseViewModel::GetAttachmentVelocity( int number, Vector &originVel, Quaternion &angleVel ) -{ - if ( m_hWeapon.Get() && m_hWeapon.Get()->WantsToOverrideViewmodelAttachments() ) - return m_hWeapon.Get()->GetAttachmentVelocity( number, originVel, angleVel ); - - return BaseClass::GetAttachmentVelocity( number, originVel, angleVel ); -} - -#endif diff --git a/game/shared/baseviewmodel_shared.h b/game/shared/baseviewmodel_shared.h deleted file mode 100644 index c46fe0532..000000000 --- a/game/shared/baseviewmodel_shared.h +++ /dev/null @@ -1,205 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef BASEVIEWMODEL_SHARED_H -#define BASEVIEWMODEL_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - -#include "predictable_entity.h" -#include "utlvector.h" -#include "baseplayer_shared.h" -#include "shared_classnames.h" - -class CBaseCombatWeapon; -class CBaseCombatCharacter; -class CVGuiScreen; - -#if defined( CLIENT_DLL ) -#define CBaseViewModel C_BaseViewModel -#define CBaseCombatWeapon C_BaseCombatWeapon -#endif - -#define VIEWMODEL_INDEX_BITS 1 - -class CBaseViewModel : public CBaseAnimating -{ - DECLARE_CLASS( CBaseViewModel, CBaseAnimating ); -public: - - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - -#if !defined( CLIENT_DLL ) - DECLARE_DATADESC(); -#endif - - CBaseViewModel( void ); - ~CBaseViewModel( void ); - - - bool IsViewable(void) { return false; } - - virtual void UpdateOnRemove( void ); - - // Weapon client handling - virtual void SendViewModelMatchingSequence( int sequence ); - virtual void SetWeaponModel( const char *pszModelname, CBaseCombatWeapon *weapon ); - - virtual void CalcViewModelLag( Vector& origin, QAngle& angles, QAngle& original_angles ); - virtual void CalcViewModelView( CBasePlayer *owner, const Vector& eyePosition, - const QAngle& eyeAngles ); - virtual void AddViewModelBob( CBasePlayer *owner, Vector& eyePosition, QAngle& eyeAngles ) {}; - - // Initializes the viewmodel for use - void SetOwner( CBaseEntity *pEntity ); - void SetIndex( int nIndex ); - // Returns which viewmodel it is - int ViewModelIndex( ) const; - - virtual void Precache( void ); - - virtual void Spawn( void ); - - virtual CBaseEntity *GetOwner( void ) { return m_hOwner; }; - - virtual void AddEffects( int nEffects ); - virtual void RemoveEffects( int nEffects ); - - void SpawnControlPanels(); - void DestroyControlPanels(); - void SetControlPanelsActive( bool bState ); - void ShowControlPanells( bool show ); - - virtual CBaseCombatWeapon *GetOwningWeapon( void ); - - virtual bool IsSelfAnimating() - { - return true; - } - - Vector m_vecLastFacing; - - // Only support prediction in TF2 for now -#if defined( INVASION_DLL ) || defined( INVASION_CLIENT_DLL ) - // All predicted weapons need to implement and return true - virtual bool IsPredicted( void ) const - { - return true; - } -#endif - -#if !defined( CLIENT_DLL ) - virtual int UpdateTransmitState( void ); - virtual int ShouldTransmit( const CCheckTransmitInfo *pInfo ); - virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ); -#else - - virtual RenderGroup_t GetRenderGroup(); - -// Only supported in TF2 right now -#if defined( INVASION_CLIENT_DLL ) - - virtual bool ShouldPredict( void ) - { - if ( GetOwner() && GetOwner() == C_BasePlayer::GetLocalPlayer() ) - return true; - - return BaseClass::ShouldPredict(); - } - -#endif - - - virtual void FireEvent( const Vector& origin, const QAngle& angles, int event, const char *options ); - - virtual void OnDataChanged( DataUpdateType_t updateType ); - virtual void PostDataUpdate( DataUpdateType_t updateType ); - - virtual bool Interpolate( float currentTime ); - - bool ShouldFlipViewModel(); - void UpdateAnimationParity( void ); - - virtual void ApplyBoneMatrixTransform( matrix3x4_t& transform ); - - virtual bool ShouldDraw(); - virtual int DrawModel( int flags ); - int DrawOverriddenViewmodel( int flags ); - virtual int GetFxBlend( void ); - virtual bool IsTransparent( void ); - - // Should this object cast shadows? - virtual ShadowType_t ShadowCastType() { return SHADOWS_NONE; } - - // Should this object receive shadows? - virtual bool ShouldReceiveProjectedTextures( int flags ) - { - return false; - } - - // Add entity to visible view models list? - virtual void AddEntity( void ); - - virtual void GetBoneControllers(float controllers[MAXSTUDIOBONECTRLS]); - - // See C_StudioModel's definition of this. - virtual void UncorrectViewModelAttachment( Vector &vOrigin ); - - // (inherited from C_BaseAnimating) - virtual void FormatViewModelAttachment( int nAttachment, matrix3x4_t &attachmentToWorld ); - virtual bool IsViewModel() const; - - CBaseCombatWeapon *GetWeapon() const { return m_hWeapon.Get(); } - -#ifdef CLIENT_DLL - virtual bool ShouldResetSequenceOnNewModel( void ) { return false; } - - // Attachments - virtual int LookupAttachment( const char *pAttachmentName ); - virtual bool GetAttachment( int number, matrix3x4_t &matrix ); - virtual bool GetAttachment( int number, Vector &origin ); - virtual bool GetAttachment( int number, Vector &origin, QAngle &angles ); - virtual bool GetAttachmentVelocity( int number, Vector &originVel, Quaternion &angleVel ); -#endif - -private: - CBaseViewModel( const CBaseViewModel & ); // not defined, not accessible - -#endif - -private: - CNetworkVar( int, m_nViewModelIndex ); // Which viewmodel is it? - CNetworkHandle( CBaseEntity, m_hOwner ); // Player or AI carrying this weapon - - // soonest time Update will call WeaponIdle - float m_flTimeWeaponIdle; - - Activity m_Activity; - - // Used to force restart on client, only needs a few bits - CNetworkVar( int, m_nAnimationParity ); - - // Weapon art - string_t m_sVMName; // View model of this weapon - string_t m_sAnimationPrefix; // Prefix of the animations that should be used by the player carrying this weapon - -#if defined( CLIENT_DLL ) - int m_nOldAnimationParity; -#endif - - - typedef CHandle< CBaseCombatWeapon > CBaseCombatWeaponHandle; - CNetworkVar( CBaseCombatWeaponHandle, m_hWeapon ); - - // Control panel - typedef CHandle ScreenHandle_t; - CUtlVector m_hScreens; -}; - -#endif // BASEVIEWMODEL_SHARED_H diff --git a/game/shared/beam_flags.h b/game/shared/beam_flags.h deleted file mode 100644 index 8b2bb902c..000000000 --- a/game/shared/beam_flags.h +++ /dev/null @@ -1,38 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#if !defined( BEAM_FLAGS_H ) -#define BEAM_FLAGS_H -#ifdef _WIN32 -#pragma once -#endif - -enum -{ - FBEAM_STARTENTITY = 0x00000001, - FBEAM_ENDENTITY = 0x00000002, - FBEAM_FADEIN = 0x00000004, - FBEAM_FADEOUT = 0x00000008, - FBEAM_SINENOISE = 0x00000010, - FBEAM_SOLID = 0x00000020, - FBEAM_SHADEIN = 0x00000040, - FBEAM_SHADEOUT = 0x00000080, - FBEAM_ONLYNOISEONCE = 0x00000100, // Only calculate our noise once - FBEAM_NOTILE = 0x00000200, - FBEAM_USE_HITBOXES = 0x00000400, // Attachment indices represent hitbox indices instead when this is set. - FBEAM_STARTVISIBLE = 0x00000800, // Has this client actually seen this beam's start entity yet? - FBEAM_ENDVISIBLE = 0x00001000, // Has this client actually seen this beam's end entity yet? - FBEAM_ISACTIVE = 0x00002000, - FBEAM_FOREVER = 0x00004000, - FBEAM_HALOBEAM = 0x00008000, // When drawing a beam with a halo, don't ignore the segments and endwidth - FBEAM_REVERSED = 0x00010000, - NUM_BEAM_FLAGS = 17 // KEEP THIS UPDATED! -}; - -#endif // BEAM_FLAGS_H diff --git a/game/shared/beam_shared.cpp b/game/shared/beam_shared.cpp deleted file mode 100644 index b4f7d884b..000000000 --- a/game/shared/beam_shared.cpp +++ /dev/null @@ -1,1194 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements visual effects entities: sprites, beams, bubbles, etc. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "beam_shared.h" -#include "decals.h" -#include "model_types.h" -#include "IEffects.h" -#include "util_shared.h" - -#if !defined( CLIENT_DLL ) -#include "ndebugoverlay.h" -#include "sendproxy.h" -#else -#include "iviewrender_beams.h" -#include "c_pixel_visibility.h" -#include "iclientmode.h" -#include "viewrender.h" -#include "view.h" - -#ifdef PORTAL - #include "c_prop_portal.h" -#endif //ifdef PORTAL - -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define BEAM_DEFAULT_HALO_SCALE 10 - -#if !defined( CLIENT_DLL ) -// Lightning target, just alias landmark - -class CInfoTarget : public CPointEntity -{ -public: - DECLARE_CLASS( CInfoTarget, CPointEntity ); - - void Spawn( void ); -}; - -//info targets are like point entities except you can force them to spawn on the client -void CInfoTarget::Spawn( void ) -{ - BaseClass::Spawn(); - - if ( HasSpawnFlags(0x01) ) - { - SetEFlags( EFL_FORCE_CHECK_TRANSMIT ); - } -} - -LINK_ENTITY_TO_CLASS( info_target, CInfoTarget ); -#endif - - -//----------------------------------------------------------------------------- -// Purpose: Returns true if the given entity is a fixed target for lightning. -//----------------------------------------------------------------------------- -bool IsStaticPointEntity( CBaseEntity *pEnt ) -{ - if ( pEnt->GetMoveParent() ) - return false; - - if ( !pEnt->GetModelIndex() ) - return 1; - - if ( FClassnameIs( pEnt, "info_target" ) || FClassnameIs( pEnt, "info_landmark" ) || - FClassnameIs( pEnt, "path_corner" ) ) - return true; - - return false; -} - -#if defined( CLIENT_DLL ) -extern bool ComputeBeamEntPosition( CBaseEntity *pEnt, int nAttachment, bool bInterpretAttachmentIndexAsHitboxIndex, Vector& pt ); - -void RecvProxy_Beam_ScrollSpeed( const CRecvProxyData *pData, void *pStruct, void *pOut ) -{ - C_Beam *beam; - float val; - - // Unpack the data. - val = pData->m_Value.m_Float; - val *= 0.1; - - beam = ( C_Beam * )pStruct; - Assert( pOut == &beam->m_fSpeed ); - - beam->m_fSpeed = val; -} -#else -#if !defined( NO_ENTITY_PREDICTION ) -static void* SendProxy_SendPredictableId( const SendProp *pProp, const void *pStruct, const void *pVarData, CSendProxyRecipients *pRecipients, int objectID ) -{ - CBaseEntity *pEntity = (CBaseEntity *)pStruct; - if ( !pEntity || !pEntity->m_PredictableID->IsActive() ) - return NULL; - - if ( !pEntity->GetOwnerEntity() ) - return NULL; - - CBaseEntity *owner = pEntity->GetOwnerEntity(); - if ( !owner || !owner->IsPlayer() ) - return NULL; - - CBasePlayer *pOwner = static_cast< CBasePlayer * >( owner ); - if ( !pOwner ) - return NULL; - - int id_player_index = pEntity->m_PredictableID->GetPlayer(); - int owner_player_index = pOwner->entindex() - 1; - // Only send to owner player - // FIXME: Is this ever not the case due to the SetOnly call? - if ( id_player_index != owner_player_index ) - return NULL; - - pRecipients->SetOnly( owner_player_index ); - return ( void * )pVarData; -} -REGISTER_SEND_PROXY_NON_MODIFIED_POINTER( SendProxy_SendPredictableId ); -#endif -#endif - -LINK_ENTITY_TO_CLASS( beam, CBeam ); - -// This table encodes the CBeam data. -IMPLEMENT_NETWORKCLASS_ALIASED( Beam, DT_Beam ) - -#if !defined( NO_ENTITY_PREDICTION ) -BEGIN_NETWORK_TABLE_NOBASE( CBeam, DT_BeamPredictableId ) -#if !defined( CLIENT_DLL ) - SendPropPredictableId( SENDINFO( m_PredictableID ) ), - SendPropInt( SENDINFO( m_bIsPlayerSimulated ), 1, SPROP_UNSIGNED ), -#else - RecvPropPredictableId( RECVINFO( m_PredictableID ) ), - RecvPropInt( RECVINFO( m_bIsPlayerSimulated ) ), -#endif -END_NETWORK_TABLE() -#endif - -BEGIN_NETWORK_TABLE_NOBASE( CBeam, DT_Beam ) -#if !defined( CLIENT_DLL ) - SendPropInt (SENDINFO(m_nBeamType), Q_log2(NUM_BEAM_TYPES)+1, SPROP_UNSIGNED ), - SendPropInt (SENDINFO(m_nBeamFlags), NUM_BEAM_FLAGS, SPROP_UNSIGNED ), - SendPropInt (SENDINFO(m_nNumBeamEnts ), 5, SPROP_UNSIGNED ), - SendPropArray3 - ( - SENDINFO_ARRAY3(m_hAttachEntity), - SendPropEHandle( SENDINFO_ARRAY(m_hAttachEntity) ) - ), - SendPropArray3 - ( - SENDINFO_ARRAY3(m_nAttachIndex), - SendPropInt( SENDINFO_ARRAY(m_nAttachIndex), ATTACHMENT_INDEX_BITS, SPROP_UNSIGNED) - ), - SendPropInt (SENDINFO(m_nHaloIndex), 16, SPROP_UNSIGNED ), - SendPropFloat (SENDINFO(m_fHaloScale), 0, SPROP_NOSCALE ), - SendPropFloat (SENDINFO(m_fWidth), 10, SPROP_ROUNDUP, 0.0f, MAX_BEAM_WIDTH ), - SendPropFloat (SENDINFO(m_fEndWidth), 10, SPROP_ROUNDUP, 0.0f, MAX_BEAM_WIDTH ), - SendPropFloat (SENDINFO(m_fFadeLength), 0, SPROP_NOSCALE ), - SendPropFloat (SENDINFO(m_fAmplitude), 8, SPROP_ROUNDDOWN, 0.0f, MAX_BEAM_NOISEAMPLITUDE ), - SendPropFloat (SENDINFO(m_fStartFrame), 8, SPROP_ROUNDDOWN, 0.0f, 256.0f), - SendPropFloat (SENDINFO(m_fSpeed), 8, SPROP_NOSCALE, 0.0f, MAX_BEAM_SCROLLSPEED), - SendPropInt (SENDINFO(m_nRenderFX), 8, SPROP_UNSIGNED ), - SendPropInt (SENDINFO(m_nRenderMode), 8, SPROP_UNSIGNED ), - SendPropFloat (SENDINFO(m_flFrameRate), 10, SPROP_ROUNDUP, -25.0f, 25.0f ), - SendPropFloat (SENDINFO(m_flHDRColorScale), 0, SPROP_NOSCALE, 0.0f, 100.0f ), - SendPropFloat (SENDINFO(m_flFrame), 20, SPROP_ROUNDDOWN | SPROP_CHANGES_OFTEN, 0.0f, 256.0f), - SendPropInt (SENDINFO(m_clrRender), 32, SPROP_UNSIGNED | SPROP_CHANGES_OFTEN ), - SendPropVector (SENDINFO(m_vecEndPos), -1, SPROP_COORD ), -#ifdef PORTAL - SendPropBool (SENDINFO(m_bDrawInMainRender) ), - SendPropBool (SENDINFO(m_bDrawInPortalRender) ), -#endif - SendPropModelIndex(SENDINFO(m_nModelIndex) ), - SendPropVector (SENDINFO(m_vecOrigin), 19, SPROP_CHANGES_OFTEN, MIN_COORD_INTEGER, MAX_COORD_INTEGER), - SendPropEHandle(SENDINFO_NAME(m_hMoveParent, moveparent) ), - SendPropInt (SENDINFO(m_nMinDXLevel), 8, SPROP_UNSIGNED ), -#if !defined( NO_ENTITY_PREDICTION ) - SendPropDataTable( "beampredictable_id", 0, &REFERENCE_SEND_TABLE( DT_BeamPredictableId ), SendProxy_SendPredictableId ), -#endif - -#else - RecvPropInt (RECVINFO(m_nBeamType)), - RecvPropInt (RECVINFO(m_nBeamFlags)), - RecvPropInt (RECVINFO(m_nNumBeamEnts)), - RecvPropArray3 - ( - RECVINFO_ARRAY( m_hAttachEntity ), - RecvPropEHandle (RECVINFO(m_hAttachEntity[0])) - ), - RecvPropArray3 - ( - RECVINFO_ARRAY( m_nAttachIndex ), - RecvPropInt (RECVINFO(m_nAttachIndex[0])) - ), - RecvPropInt (RECVINFO(m_nHaloIndex)), - RecvPropFloat (RECVINFO(m_fHaloScale)), - RecvPropFloat (RECVINFO(m_fWidth)), - RecvPropFloat (RECVINFO(m_fEndWidth)), - RecvPropFloat (RECVINFO(m_fFadeLength)), - RecvPropFloat (RECVINFO(m_fAmplitude)), - RecvPropFloat (RECVINFO(m_fStartFrame)), - RecvPropFloat (RECVINFO(m_fSpeed), 0, RecvProxy_Beam_ScrollSpeed ), - RecvPropFloat(RECVINFO(m_flFrameRate)), - RecvPropFloat(RECVINFO(m_flHDRColorScale)), - RecvPropInt(RECVINFO(m_clrRender)), - RecvPropInt(RECVINFO(m_nRenderFX)), - RecvPropInt(RECVINFO(m_nRenderMode)), - RecvPropFloat(RECVINFO(m_flFrame)), - RecvPropVector(RECVINFO(m_vecEndPos)), -#ifdef PORTAL - RecvPropBool(RECVINFO(m_bDrawInMainRender) ), - RecvPropBool(RECVINFO(m_bDrawInPortalRender) ), -#endif - RecvPropInt(RECVINFO(m_nModelIndex)), - RecvPropInt(RECVINFO(m_nMinDXLevel)), - - RecvPropVector(RECVINFO_NAME(m_vecNetworkOrigin, m_vecOrigin)), - RecvPropInt( RECVINFO_NAME(m_hNetworkMoveParent, moveparent), 0, RecvProxy_IntToMoveParent ), -#if !defined( NO_ENTITY_PREDICTION ) - RecvPropDataTable( "beampredictable_id", 0, 0, &REFERENCE_RECV_TABLE( DT_BeamPredictableId ) ), -#endif - -#endif -END_NETWORK_TABLE() - -#if !defined( CLIENT_DLL ) -BEGIN_DATADESC( CBeam ) - DEFINE_FIELD( m_nHaloIndex, FIELD_MODELINDEX ), - DEFINE_FIELD( m_nBeamType, FIELD_INTEGER ), - DEFINE_FIELD( m_nBeamFlags, FIELD_INTEGER ), - DEFINE_FIELD( m_nNumBeamEnts, FIELD_INTEGER ), - DEFINE_ARRAY( m_hAttachEntity, FIELD_EHANDLE, MAX_BEAM_ENTS ), - DEFINE_ARRAY( m_nAttachIndex, FIELD_INTEGER, MAX_BEAM_ENTS ), - DEFINE_FIELD( m_nMinDXLevel, FIELD_INTEGER ), - - DEFINE_FIELD( m_fWidth, FIELD_FLOAT ), - DEFINE_FIELD( m_fEndWidth, FIELD_FLOAT ), - DEFINE_FIELD( m_fFadeLength, FIELD_FLOAT ), - DEFINE_FIELD( m_fHaloScale, FIELD_FLOAT ), - DEFINE_FIELD( m_fAmplitude, FIELD_FLOAT ), - DEFINE_FIELD( m_fStartFrame, FIELD_FLOAT ), - DEFINE_FIELD( m_fSpeed, FIELD_FLOAT ), - - DEFINE_FIELD( m_flFrameRate, FIELD_FLOAT ), - DEFINE_FIELD( m_flFrame, FIELD_FLOAT ), - - DEFINE_KEYFIELD( m_flHDRColorScale, FIELD_FLOAT, "HDRColorScale" ), - - DEFINE_KEYFIELD( m_flDamage, FIELD_FLOAT, "damage" ), - DEFINE_FIELD( m_flFireTime, FIELD_TIME ), - - DEFINE_FIELD( m_vecEndPos, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_hEndEntity, FIELD_EHANDLE ), - - DEFINE_KEYFIELD( m_nDissolveType, FIELD_INTEGER, "dissolvetype" ), - -#ifdef PORTAL - DEFINE_FIELD( m_bDrawInMainRender, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bDrawInPortalRender, FIELD_BOOLEAN ), -#endif - - // Inputs - DEFINE_INPUTFUNC( FIELD_FLOAT, "Width", InputWidth ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "Noise", InputNoise ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "ColorRedValue", InputColorRedValue ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "ColorGreenValue", InputColorGreenValue ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "ColorBlueValue", InputColorBlueValue ), - DEFINE_INPUT( m_fSpeed, FIELD_FLOAT, "ScrollSpeed" ), - - // don't save this - //DEFINE_FIELD( m_queryHandleHalo, FIELD_ ), - -END_DATADESC() - -#else - -BEGIN_PREDICTION_DATA( CBeam ) - - DEFINE_PRED_FIELD( m_nBeamType, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), - - DEFINE_PRED_FIELD( m_nNumBeamEnts, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_ARRAY( m_hAttachEntity, FIELD_EHANDLE, MAX_BEAM_ENTS, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_ARRAY( m_nAttachIndex, FIELD_INTEGER, MAX_BEAM_ENTS, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_nHaloIndex, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_fHaloScale, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_fWidth, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_fEndWidth, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_fFadeLength, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_fAmplitude, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_fStartFrame, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_fSpeed, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_nRenderFX, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_nRenderMode, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_flFrameRate, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_flFrame, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_clrRender, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_nMinDXLevel, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD_TOL( m_vecEndPos, FIELD_VECTOR, FTYPEDESC_INSENDTABLE, 0.125f ), -#ifdef PORTAL - DEFINE_PRED_FIELD( m_bDrawInMainRender, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_bDrawInPortalRender, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), -#endif - DEFINE_PRED_FIELD( m_nModelIndex, FIELD_INTEGER, FTYPEDESC_INSENDTABLE | FTYPEDESC_MODELINDEX ), - DEFINE_PRED_FIELD_TOL( m_vecOrigin, FIELD_VECTOR, FTYPEDESC_INSENDTABLE, 0.125f ), - - //DEFINE_PRED_FIELD( m_pMoveParent, SendProxy_MoveParent ), - //DEFINE_PRED_FIELD( m_flHDRColorScale, SendProxy_HDRColorScale ), - -END_PREDICTION_DATA() - -#endif - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CBeam::CBeam( void ) -{ -#ifdef _DEBUG - // necessary since in debug, we initialize vectors to NAN for debugging - m_vecEndPos.Init(); -#endif - - m_nMinDXLevel = 0; - m_flHDRColorScale = 1.0f; // default value. - -#if !defined( CLIENT_DLL ) - m_nDissolveType = -1; -#else - m_queryHandleHalo = 0; -#endif - -#ifdef PORTAL - m_bDrawInMainRender = true; - m_bDrawInPortalRender = true; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *szModelName - -//----------------------------------------------------------------------------- -void CBeam::SetModel( const char *szModelName ) -{ - int modelIndex = modelinfo->GetModelIndex( szModelName ); - const model_t *model = modelinfo->GetModel( modelIndex ); - if ( model && modelinfo->GetModelType( model ) != mod_sprite ) - { - Msg( "Setting CBeam to non-sprite model %s\n", szModelName ); - } -#if !defined( CLIENT_DLL ) - UTIL_SetModel( this, szModelName ); -#else - BaseClass::SetModel( szModelName ); -#endif -} - - -void CBeam::Spawn( void ) -{ - SetMoveType( MOVETYPE_NONE ); - SetSolid( SOLID_NONE ); // Remove model & collisions - SetRenderMode( kRenderTransTexture ); - - // Opt out of all shadow routines - AddEffects( EF_NOSHADOW | EF_NORECEIVESHADOW ); - - Precache( ); -} - - -void CBeam::Precache( void ) -{ - if ( GetOwnerEntity() ) - { - SetStartEntity( GetOwnerEntity() ); - } - - if ( m_hEndEntity.Get() ) - { - SetEndEntity( m_hEndEntity ); - } -} - - -void CBeam::SetType( int type ) -{ - Assert( type < NUM_BEAM_TYPES ); - m_nBeamType = type; -} - -void CBeam::SetBeamFlags( int flags ) -{ - Assert( flags < (1 << NUM_BEAM_FLAGS) ); - m_nBeamFlags = flags; -} - -void CBeam::SetBeamFlag( int flag ) -{ - m_nBeamFlags |= flag; -} - -int CBeam::GetType( void ) const -{ - return m_nBeamType; -} - -int CBeam::GetBeamFlags( void ) const -{ - return m_nBeamFlags; -} - -void CBeam::SetStartEntity( CBaseEntity *pEntity ) -{ - Assert( m_nNumBeamEnts >= 2 ); - m_hAttachEntity.Set( 0, pEntity ); - SetOwnerEntity( pEntity ); - RelinkBeam(); - pEntity->AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); -} - -void CBeam::SetEndEntity( CBaseEntity *pEntity ) -{ - Assert( m_nNumBeamEnts >= 2 ); - m_hAttachEntity.Set( m_nNumBeamEnts-1, pEntity ); - m_hEndEntity = pEntity; - RelinkBeam(); - pEntity->AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); -} - - -//----------------------------------------------------------------------------- -// This will change things so the abs position matches the requested spot -//----------------------------------------------------------------------------- -void CBeam::SetAbsStartPos( const Vector &pos ) -{ - if (!GetMoveParent()) - { - SetStartPos( pos ); - return; - } - - Vector vecLocalPos; - matrix3x4_t worldToBeam; - MatrixInvert( EntityToWorldTransform(), worldToBeam ); - VectorTransform( pos, worldToBeam, vecLocalPos ); - SetStartPos( vecLocalPos ); -} - -void CBeam::SetAbsEndPos( const Vector &pos ) -{ - if (!GetMoveParent()) - { - SetEndPos( pos ); - return; - } - - Vector vecLocalPos; - matrix3x4_t worldToBeam; - MatrixInvert( EntityToWorldTransform(), worldToBeam ); - VectorTransform( pos, worldToBeam, vecLocalPos ); - SetEndPos( vecLocalPos ); -} - -#if !defined( CLIENT_DLL ) - -// These don't take attachments into account -const Vector &CBeam::GetAbsStartPos( void ) const -{ - if ( GetType() == BEAM_ENTS && GetStartEntity() ) - { - edict_t *pent = engine->PEntityOfEntIndex( GetStartEntity() ); - CBaseEntity *ent = CBaseEntity::Instance( pent ); - if ( !ent ) - { - return GetAbsOrigin(); - } - return ent->GetAbsOrigin(); - } - return GetAbsOrigin(); -} - - -const Vector &CBeam::GetAbsEndPos( void ) const -{ - if ( GetType() != BEAM_POINTS && GetType() != BEAM_HOSE && GetEndEntity() ) - { - edict_t *pent = engine->PEntityOfEntIndex( GetEndEntity() ); - CBaseEntity *ent = CBaseEntity::Instance( pent ); - if ( ent ) - return ent->GetAbsOrigin(); - } - - if (!const_cast(this)->GetMoveParent()) - return m_vecEndPos.Get(); - - // FIXME: Cache this off? - static Vector vecAbsPos; - VectorTransform( m_vecEndPos, EntityToWorldTransform(), vecAbsPos ); - return vecAbsPos; -} - -#else - -//----------------------------------------------------------------------------- -// Unlike the server, these take attachments into account -//----------------------------------------------------------------------------- -const Vector &C_Beam::GetAbsStartPos( void ) const -{ - static Vector vecStartAbsPosition; - if ( GetType() != BEAM_POINTS && GetType() != BEAM_HOSE ) - { - if (ComputeBeamEntPosition( m_hAttachEntity[0], m_nAttachIndex[0], false, vecStartAbsPosition )) - return vecStartAbsPosition; - } - - return GetAbsOrigin(); -} - - -const Vector &C_Beam::GetAbsEndPos( void ) const -{ - static Vector vecEndAbsPosition; - if ( GetType() != BEAM_POINTS && GetType() != BEAM_HOSE ) - { - if (ComputeBeamEntPosition( m_hAttachEntity[m_nNumBeamEnts-1], m_nAttachIndex[m_nNumBeamEnts-1], false, vecEndAbsPosition )) - return vecEndAbsPosition; - } - - if (!const_cast(this)->GetMoveParent()) - return m_vecEndPos.Get(); - - // FIXME: Cache this off? - VectorTransform( m_vecEndPos, EntityToWorldTransform(), vecEndAbsPosition ); - return vecEndAbsPosition; -} -#endif - -CBeam *CBeam::BeamCreate( const char *pSpriteName, float width ) -{ - // Create a new entity with CBeam private data - CBeam *pBeam = CREATE_ENTITY( CBeam, "beam" ); - pBeam->BeamInit( pSpriteName, width ); - - return pBeam; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pSpriteName - -// &origin - -// animate - -// Output : CSprite -//----------------------------------------------------------------------------- -CBeam *CBeam::BeamCreatePredictable( const char *module, int line, bool persist, const char *pSpriteName, float width, CBasePlayer *pOwner ) -{ -#if !defined( NO_ENTITY_PREDICTION ) - CBeam *pBeam = ( CBeam * )CBaseEntity::CreatePredictedEntityByName( "beam", module, line, persist ); - if ( pBeam ) - { - pBeam->BeamInit( pSpriteName, width ); - pBeam->SetOwnerEntity( pOwner ); - pBeam->SetPlayerSimulated( pOwner ); - } - - return pBeam; -#else - return NULL; -#endif -} - -void CBeam::BeamInit( const char *pSpriteName, float width ) -{ - SetColor( 255, 255, 255 ); - SetBrightness( 255 ); - SetNoise( 0 ); - SetFrame( 0 ); - SetScrollRate( 0 ); - SetModelName( MAKE_STRING( pSpriteName ) ); - SetRenderMode( kRenderTransTexture ); - SetTexture( PrecacheModel( pSpriteName ) ); - SetWidth( width ); - SetEndWidth( width ); - SetFadeLength( 0 ); // No fade - for (int i=0;i MAX_BEAM_ENTS) - { - Msg("ERROR: Max of %i ents allowed for spline beam.\n",MAX_BEAM_ENTS); - } - SetType( BEAM_SPLINE ); - - for (int i=0;iGetBeamTraceFilter(); - - CTraceFilterChain traceFilterChain( &traceFilter, pEntityBeamTraceFilter ); - - bUseExtraPoints = UTIL_Portal_Trace_Beam( this, startPos, endPos, vecAbsExtra1, vecAbsExtra2, &traceFilterChain ); -#endif - - // UNDONE: Should we do this to make the boxes smaller? - //SetAbsOrigin( startPos ); - - Vector vecBeamMin, vecBeamMax; - VectorMin( startPos, endPos, vecBeamMin ); - VectorMax( startPos, endPos, vecBeamMax ); - - if ( bUseExtraPoints ) - { - VectorMin( vecBeamMin, vecAbsExtra1, vecBeamMin ); - VectorMin( vecBeamMin, vecAbsExtra2, vecBeamMin ); - VectorMax( vecBeamMax, vecAbsExtra1, vecBeamMax ); - VectorMax( vecBeamMax, vecAbsExtra2, vecBeamMax ); - } - - SetCollisionBounds( vecBeamMin - GetAbsOrigin(), vecBeamMax - GetAbsOrigin() ); -} - - -CBaseEntity *CBeam::RandomTargetname( const char *szName ) -{ -#if !defined( CLIENT_DLL ) - int total = 0; - - CBaseEntity *pEntity = NULL; - CBaseEntity *pNewEntity = NULL; - while ((pNewEntity = gEntList.FindEntityByName( pNewEntity, szName )) != NULL) - { - total++; - if (random->RandomInt(0,total-1) < 1) - pEntity = pNewEntity; - } - return pEntity; -#else - return NULL; -#endif -} - - -void CBeam::DoSparks( const Vector &start, const Vector &end ) -{ -#if !defined( CLIENT_DLL ) - if ( HasSpawnFlags(SF_BEAM_SPARKSTART|SF_BEAM_SPARKEND) ) - { - if ( HasSpawnFlags( SF_BEAM_SPARKSTART ) ) - { - g_pEffects->Sparks( start ); - } - if ( HasSpawnFlags( SF_BEAM_SPARKEND ) ) - { - g_pEffects->Sparks( end ); - } - } -#endif -} - - -//----------------------------------------------------------------------------- -// Purpose: Damages anything in the beam. -// Input : ptr - -//----------------------------------------------------------------------------- -void CBeam::BeamDamage( trace_t *ptr ) -{ - RelinkBeam(); -#if !defined( CLIENT_DLL ) - if ( ptr->fraction != 1.0 && ptr->m_pEnt != NULL ) - { - CBaseEntity *pHit = ptr->m_pEnt; - if ( pHit ) - { - ClearMultiDamage(); - Vector dir = ptr->endpos - GetAbsOrigin(); - VectorNormalize( dir ); - int nDamageType = DMG_ENERGYBEAM; - -#ifndef HL1_DLL - if (m_nDissolveType == 0) - { - nDamageType = DMG_DISSOLVE; - } - else if ( m_nDissolveType > 0 ) - { - nDamageType = DMG_DISSOLVE | DMG_SHOCK; - } -#endif - - CTakeDamageInfo info( this, this, m_flDamage * (gpGlobals->curtime - m_flFireTime), nDamageType ); - CalculateMeleeDamageForce( &info, dir, ptr->endpos ); - pHit->DispatchTraceAttack( info, dir, ptr ); - ApplyMultiDamage(); - if ( HasSpawnFlags( SF_BEAM_DECALS ) ) - { - if ( pHit->IsBSPModel() ) - { - UTIL_DecalTrace( ptr, GetDecalName() ); - } - } - } - } -#endif - m_flFireTime = gpGlobals->curtime; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBeam::TurnOn( void ) -{ - AddEffects( EF_NODRAW ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBeam::TurnOff( void ) -{ - RemoveEffects( EF_NODRAW ); -} - -#if !defined( CLIENT_DLL ) -//----------------------------------------------------------------------------- -// Purpose: Input handler for the beam width. Sets the end width based on the -// beam width. -// Input : Beam width in tenths of world units. -//----------------------------------------------------------------------------- -void CBeam::InputWidth( inputdata_t &inputdata ) -{ - SetWidth( inputdata.value.Float() ); - SetEndWidth( inputdata.value.Float() ); -} - -void CBeam::InputColorRedValue( inputdata_t &inputdata ) -{ - int nNewColor = clamp( inputdata.value.Int(), 0, 255 ); - SetColor( nNewColor, m_clrRender->g, m_clrRender->b ); -} - -void CBeam::InputColorGreenValue( inputdata_t &inputdata ) -{ - int nNewColor = clamp( inputdata.value.Int(), 0, 255 ); - SetColor( m_clrRender->r, nNewColor, m_clrRender->b ); -} - -void CBeam::InputColorBlueValue( inputdata_t &inputdata ) -{ - int nNewColor = clamp( inputdata.value.Int(), 0, 255 ); - SetColor( m_clrRender->r, m_clrRender->g, nNewColor ); -} - -void CBeam::InputNoise( inputdata_t &inputdata ) -{ - SetNoise( inputdata.value.Float() ); -} - -int CBeam::UpdateTransmitState( void ) -{ - // we must call ShouldTransmit() if we have a move parent - if ( GetMoveParent() ) - return SetTransmitState( FL_EDICT_FULLCHECK ); - - return BaseClass::UpdateTransmitState( ); -} - -void CBeam::SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ) -{ - // Are we already marked for transmission? - if ( pInfo->m_pTransmitEdict->Get( entindex() ) ) - return; - - BaseClass::SetTransmit( pInfo, bAlways ); - - // Force our attached entities to go too... - for ( int i=0; i < MAX_BEAM_ENTS; ++i ) - { - if ( m_hAttachEntity[i].Get() ) - { - m_hAttachEntity[i]->SetTransmit( pInfo, bAlways ); - } - } -} - -int CBeam::ShouldTransmit( const CCheckTransmitInfo *pInfo ) -{ - if ( IsEffectActive( EF_NODRAW ) ) - return FL_EDICT_DONTSEND; - - // Transmit us with the same rules as our move parent - if ( GetMoveParent() ) - { - return GetMoveParent()->ShouldTransmit( pInfo ); - } - - return BaseClass::ShouldTransmit( pInfo ); -} - -#endif - -//----------------------------------------------------------------------------- -// Purpose: Draw any debug text overlays. -// Output : Returns the new text offset from the top. -//----------------------------------------------------------------------------- -int CBeam::DrawDebugTextOverlays(void) -{ -#if !defined( CLIENT_DLL ) - int text_offset = BaseClass::DrawDebugTextOverlays(); - if (m_debugOverlays & OVERLAY_TEXT_BIT) - { - // Print state - char tempstr[512]; - Q_snprintf(tempstr, sizeof(tempstr), "start: (%.2f,%.2f,%.2f)", GetAbsOrigin().x, GetAbsOrigin().y, GetAbsOrigin().z); - EntityText(text_offset,tempstr,0); - text_offset++; - - Q_snprintf(tempstr, sizeof(tempstr), "end : (%.2f,%.2f,%.2f)", m_vecEndPos.GetX(), m_vecEndPos.GetY(), m_vecEndPos.GetZ()); - EntityText(text_offset,tempstr,0); - text_offset++; - } - - return text_offset; -#else - return 0; -#endif -} - -#if defined( CLIENT_DLL ) - -// Purpose: -// Input : isbeingremoved - -// *predicted - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBeam::OnPredictedEntityRemove( bool isbeingremoved, C_BaseEntity *predicted ) -{ - BaseClass::OnPredictedEntityRemove( isbeingremoved, predicted ); - - CBeam *beam = dynamic_cast< CBeam * >( predicted ); - if ( !beam ) - { - // Hrm, we didn't link up to correct type!!! - Assert( 0 ); - // Delete right away since it's fucked up - return true; - } - - if ( beam->IsEFlagSet( EFL_KILLME ) ) - { - // Don't delete right away - AddEFlags( EFL_KILLME ); - return false; - } - - // Go ahead and delete if it's not short-lived - return true; -} - -extern bool g_bRenderingScreenshot; -extern ConVar r_drawviewmodel; - -int CBeam::DrawModel( int flags ) -{ - if ( !m_bReadyToDraw ) - return 0; - - if ( IsMarkedForDeletion() ) - return 0; - - if ( CurrentViewID() == VIEW_SHADOW_DEPTH_TEXTURE ) - return 0; - -#ifdef PORTAL - if ( ( !g_pPortalRender->IsRenderingPortal() && !m_bDrawInMainRender ) || - ( g_pPortalRender->IsRenderingPortal() && !m_bDrawInPortalRender ) ) - { - return 0; - } -#endif //#ifdef PORTAL - - // Tracker 16432: If rendering a savegame screenshot don't draw beams - // who have viewmodels as their attached entity - if ( g_bRenderingScreenshot || !r_drawviewmodel.GetBool() ) - { - // If the beam is attached - for (int i=0;i(m_hAttachEntity[i].Get()); - if ( vm ) - { - return 0; - } - } - } - - beams->DrawBeam( this ); - return 0; -} - -void CBeam::OnDataChanged( DataUpdateType_t updateType ) -{ - MarkMessageReceived(); - - // Make sure that the correct model is referenced for this entity - SetModelPointer( modelinfo->GetModel( GetModelIndex() ) ); - - // Convert weapon world models to viewmodels if they're weapons being carried by the local player - for (int i=0;i(pEnt); - if ( pWpn && pWpn->IsCarriedByLocalPlayer() ) - { - C_BasePlayer *player = ToBasePlayer( pWpn->GetOwner() ); - - C_BaseViewModel *pViewModel = player ? player->GetViewModel( 0 ) : NULL; - if ( pViewModel ) - { - // Get the viewmodel and use it instead - m_hAttachEntity.Set( i, pViewModel ); - } - } - } - } - - // Compute the bounds here... - Vector mins, maxs; - ComputeBounds( mins, maxs ); - SetCollisionBounds( mins, maxs ); -} - -bool CBeam::IsTransparent( void ) -{ - return true; -} - -bool CBeam::ShouldDraw() -{ - if ( m_nMinDXLevel != 0 ) - { - if ( m_nMinDXLevel > g_pMaterialSystemHardwareConfig->GetDXSupportLevel() ) - return false; - } - return BaseClass::ShouldDraw(); -} - -//----------------------------------------------------------------------------- -// Purpose: Adds to beam entity list -//----------------------------------------------------------------------------- -void CBeam::AddEntity( void ) -{ - // If set to invisible, skip. Do this before resetting the entity pointer so it has - // valid data to decide whether it's visible. - if ( !ShouldDraw() ) - { - return; - } - - //FIXME: If we're hooked up to an attachment point, then recompute our bounds every frame - if ( m_hAttachEntity[0].Get() || m_hAttachEntity[1].Get() ) - { - // Compute the bounds here... - Vector mins, maxs; - ComputeBounds( mins, maxs ); - SetCollisionBounds( mins, maxs ); - } - - MoveToLastReceivedPosition(); -} - -//----------------------------------------------------------------------------- -// Computes the bounding box of a beam local to the origin of the beam -//----------------------------------------------------------------------------- -void CBeam::ComputeBounds( Vector& mins, Vector& maxs ) -{ - Vector vecAbsStart = GetAbsStartPos(); - Vector vecAbsEnd = GetAbsEndPos(); - - // May need extra points for creating the min/max bounds - bool bUseExtraPoints = false; - Vector vecAbsExtra1, vecAbsExtra2; - -#ifdef PORTAL - CBaseEntity *pStartEntity = GetStartEntityPtr(); - - CTraceFilterSkipClassname traceFilter( pStartEntity, "prop_energy_ball", COLLISION_GROUP_NONE ); - - ITraceFilter *pEntityBeamTraceFilter = NULL; - if ( pStartEntity ) - pEntityBeamTraceFilter = pStartEntity->GetBeamTraceFilter(); - - CTraceFilterChain traceFilterChain( &traceFilter, pEntityBeamTraceFilter ); - - bUseExtraPoints = UTIL_Portal_Trace_Beam( this, vecAbsStart, vecAbsEnd, vecAbsExtra1, vecAbsExtra2, &traceFilterChain ); -#endif - - switch( GetType() ) - { - case BEAM_LASER: - case BEAM_ENTS: - case BEAM_SPLINE: - case BEAM_ENTPOINT: - { - // Compute the bounds here... - Vector attachmentPoint( 0, 0, 0 ); - mins.Init( 99999, 99999, 99999 ); - maxs.Init( -99999, -99999, -99999 ); - for (int i = 0; i < m_nNumBeamEnts; ++i ) - { - C_BaseEntity *pTestEnt = m_hAttachEntity[i].Get(); - if ( pTestEnt ) - { - if ( pTestEnt == this ) - { - mins = maxs = GetAbsOrigin(); - } - else - { - // We do this so we don't have to calculate attachments (and do expensive bone-setup calculations) on our attachments. - Vector attMins, attMaxs; - m_hAttachEntity[i]->GetRenderBoundsWorldspace( attMins, attMaxs ); - - mins = mins.Min( attMins ); - mins = mins.Min( attMaxs ); - - maxs = maxs.Max( attMins ); - maxs = maxs.Max( attMaxs ); - } - - //ASSERT_COORD( mins ); - //ASSERT_COORD( maxs ); - } - else - { - if (i == 0) - { - VectorCopy( vecAbsStart, attachmentPoint ); - } - else if (i == 1) - { - VectorCopy( vecAbsEnd, attachmentPoint ); - } - else - { - Assert(0); - } - - mins = mins.Min( attachmentPoint ); - maxs = maxs.Max( attachmentPoint ); - } - } - } - break; - - case BEAM_POINTS: - default: - { - for (int i = 0; i < 3; ++i) - { - if (vecAbsStart[i] < vecAbsEnd[i]) - { - mins[i] = vecAbsStart[i]; - maxs[i] = vecAbsEnd[i]; - } - else - { - mins[i] = vecAbsEnd[i]; - maxs[i] = vecAbsStart[i]; - } - } - } - break; - } - - if ( bUseExtraPoints ) - { - mins = mins.Min( vecAbsExtra1 ); - mins = mins.Min( vecAbsExtra2 ); - maxs = maxs.Max( vecAbsExtra1 ); - maxs = maxs.Max( vecAbsExtra2 ); - } - - // Make sure the bounds are measured in *relative coords* - Vector vecAbsOrigin = GetAbsOrigin(); - mins -= vecAbsOrigin; - maxs -= vecAbsOrigin; -} -#endif diff --git a/game/shared/beam_shared.h b/game/shared/beam_shared.h deleted file mode 100644 index 761df3c64..000000000 --- a/game/shared/beam_shared.h +++ /dev/null @@ -1,475 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef BEAM_H -#define BEAM_H -#ifdef _WIN32 -#pragma once -#endif - -#include "baseentity_shared.h" -#include "baseplayer_shared.h" -#if !defined( CLIENT_DLL ) -#include "entityoutput.h" -#endif - -#include "beam_flags.h" - -#define MAX_BEAM_WIDTH 102.3f -#define MAX_BEAM_SCROLLSPEED 100.0f -#define MAX_BEAM_NOISEAMPLITUDE 64 - -#define SF_BEAM_STARTON 0x0001 -#define SF_BEAM_TOGGLE 0x0002 -#define SF_BEAM_RANDOM 0x0004 -#define SF_BEAM_RING 0x0008 -#define SF_BEAM_SPARKSTART 0x0010 -#define SF_BEAM_SPARKEND 0x0020 -#define SF_BEAM_DECALS 0x0040 -#define SF_BEAM_SHADEIN 0x0080 -#define SF_BEAM_SHADEOUT 0x0100 -#define SF_BEAM_TAPEROUT 0x0200 // Tapers to zero -#define SF_BEAM_TEMPORARY 0x8000 - -#define ATTACHMENT_INDEX_BITS 5 -#define ATTACHMENT_INDEX_MASK ((1 << ATTACHMENT_INDEX_BITS) - 1) - -#if defined( CLIENT_DLL ) -#define CBeam C_Beam -#include "c_pixel_visibility.h" -#endif - -class CBeam : public CBaseEntity -{ - DECLARE_CLASS( CBeam, CBaseEntity ); -public: - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); -#if !defined( CLIENT_DLL ) - DECLARE_DATADESC(); -#endif - - CBeam(); - - virtual void SetModel( const char *szModelName ); - - void Spawn( void ); - void Precache( void ); -#if !defined( CLIENT_DLL ) - int ObjectCaps( void ); - void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ); - int UpdateTransmitState( void ); - int ShouldTransmit( const CCheckTransmitInfo *pInfo ); -#endif - - virtual int DrawDebugTextOverlays(void); - - // These functions are here to show the way beams are encoded as entities. - // Encoding beams as entities simplifies their management in the client/server architecture - void SetType( int type ); - void SetBeamFlags( int flags ); - void SetBeamFlag( int flag ); - - // NOTE: Start + End Pos are specified in *relative* coordinates - void SetStartPos( const Vector &pos ); - void SetEndPos( const Vector &pos ); - - // This will change things so the abs position matches the requested spot - void SetAbsStartPos( const Vector &pos ); - void SetAbsEndPos( const Vector &pos ); - - const Vector &GetAbsStartPos( void ) const; - const Vector &GetAbsEndPos( void ) const; - - void SetStartEntity( CBaseEntity *pEntity ); - void SetEndEntity( CBaseEntity *pEntity ); - - void SetStartAttachment( int attachment ); - void SetEndAttachment( int attachment ); - - void SetTexture( int spriteIndex ); - void SetHaloTexture( int spriteIndex ); - void SetHaloScale( float haloScale ); - void SetWidth( float width ); - void SetEndWidth( float endWidth ); - void SetFadeLength( float fadeLength ); - void SetNoise( float amplitude ); - void SetColor( int r, int g, int b ); - void SetBrightness( int brightness ); - void SetFrame( float frame ); - void SetScrollRate( int speed ); - void SetFireTime( float flFireTime ); - void SetFrameRate( float flFrameRate ) { m_flFrameRate = flFrameRate; } - - void SetMinDXLevel( int nMinDXLevel ) { m_nMinDXLevel = nMinDXLevel; } - - void TurnOn( void ); - void TurnOff( void ); - - int GetType( void ) const; - int GetBeamFlags( void ) const; - CBaseEntity* GetStartEntityPtr( void ) const; - int GetStartEntity( void ) const; - CBaseEntity* GetEndEntityPtr( void ) const; - int GetEndEntity( void ) const; - int GetStartAttachment() const; - int GetEndAttachment() const; - - virtual const Vector &WorldSpaceCenter( void ) const; - - int GetTexture( void ); - float GetWidth( void ) const; - float GetEndWidth( void ) const; - float GetFadeLength( void ) const; - float GetNoise( void ) const; - int GetBrightness( void ) const; - float GetFrame( void ) const; - float GetScrollRate( void ) const; - float GetHDRColorScale( void ) const; - void SetHDRColorScale( float flScale ) { m_flHDRColorScale = flScale; } - - - // Call after you change start/end positions - void RelinkBeam( void ); - - void DoSparks( const Vector &start, const Vector &end ); - CBaseEntity *RandomTargetname( const char *szName ); - void BeamDamage( trace_t *ptr ); - // Init after BeamCreate() - void BeamInit( const char *pSpriteName, float width ); - void PointsInit( const Vector &start, const Vector &end ); - void PointEntInit( const Vector &start, CBaseEntity *pEndEntity ); - void EntsInit( CBaseEntity *pStartEntity, CBaseEntity *pEndEntity ); - void LaserInit( CBaseEntity *pStartEntity, CBaseEntity *pEndEntity ); - void HoseInit( const Vector &start, const Vector &direction ); - void SplineInit( int nNumEnts, CBaseEntity** pEntList, int *attachment ); - - // Input handlers - - static CBeam *BeamCreate( const char *pSpriteName, float width ); - static CBeam *BeamCreatePredictable( const char *module, int line, bool persist, const char *pSpriteName, float width, CBasePlayer *pOwner ); - - void LiveForTime( float time ); - void BeamDamageInstant( trace_t *ptr, float damage ); - -// Only supported in TF2 right now -#if defined( INVASION_CLIENT_DLL ) - virtual bool ShouldPredict( void ) - { - return true; - } -#endif - - virtual const char *GetDecalName( void ) { return "BigShot"; } - -#if defined( CLIENT_DLL ) -// IClientEntity overrides. -public: - virtual int DrawModel( int flags ); - virtual bool IsTransparent( void ); - virtual bool ShouldDraw(); - virtual void OnDataChanged( DataUpdateType_t updateType ); - - virtual bool OnPredictedEntityRemove( bool isbeingremoved, C_BaseEntity *predicted ); - - // Add beam to visible entities list? - virtual void AddEntity( void ); - virtual bool ShouldReceiveProjectedTextures( int flags ) - { - return false; - } - -// Beam Data Elements -private: - // Computes the bounding box of a beam local to the origin of the beam - void ComputeBounds( Vector& mins, Vector& maxs ); - - friend void RecvProxy_Beam_ScrollSpeed( const CRecvProxyData *pData, void *pStruct, void *pOut ); - friend class CViewRenderBeams; - -#endif - -protected: - CNetworkVar( float, m_flFrameRate ); - CNetworkVar( float, m_flHDRColorScale ); - float m_flFireTime; - float m_flDamage; // Damage per second to touchers. - CNetworkVar( int, m_nNumBeamEnts ); -#if defined( CLIENT_DLL ) - pixelvis_handle_t m_queryHandleHalo; -#endif - -private: -#if !defined( CLIENT_DLL ) - void InputNoise( inputdata_t &inputdata ); - void InputWidth( inputdata_t &inputdata ); - void InputColorRedValue( inputdata_t &inputdata ); - void InputColorBlueValue( inputdata_t &inputdata ); - void InputColorGreenValue( inputdata_t &inputdata ); -#endif - - // Beam Data Elements - CNetworkVar( int, m_nHaloIndex ); - CNetworkVar( int, m_nBeamType ); - CNetworkVar( int, m_nBeamFlags ); - CNetworkArray( EHANDLE, m_hAttachEntity, MAX_BEAM_ENTS ); - CNetworkArray( int, m_nAttachIndex, MAX_BEAM_ENTS ); - CNetworkVar( float, m_fWidth ); - CNetworkVar( float, m_fEndWidth ); - CNetworkVar( float, m_fFadeLength ); - CNetworkVar( float, m_fHaloScale ); - CNetworkVar( float, m_fAmplitude ); - CNetworkVar( float, m_fStartFrame ); - CNetworkVar( float, m_fSpeed ); - CNetworkVar( int, m_nMinDXLevel ); - CNetworkVar( float, m_flFrame ); - - CNetworkVector( m_vecEndPos ); - - EHANDLE m_hEndEntity; - -#if !defined( CLIENT_DLL ) - int m_nDissolveType; -#endif - -public: -#ifdef PORTAL - CNetworkVar( bool, m_bDrawInMainRender ); - CNetworkVar( bool, m_bDrawInPortalRender ); -#endif //#ifdef PORTAL -}; - -#if !defined( CLIENT_DLL ) -//----------------------------------------------------------------------------- -// Inline methods -//----------------------------------------------------------------------------- -inline int CBeam::ObjectCaps( void ) -{ - int flags = 0; - if ( HasSpawnFlags( SF_BEAM_TEMPORARY ) ) - flags = FCAP_DONT_SAVE; - return (BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | flags; -} -#endif - -inline void CBeam::SetFireTime( float flFireTime ) -{ - m_flFireTime = flFireTime; -} - -//----------------------------------------------------------------------------- -// NOTE: Start + End Pos are specified in *relative* coordinates -//----------------------------------------------------------------------------- -inline void CBeam::SetStartPos( const Vector &pos ) -{ -#if defined( CLIENT_DLL ) - SetNetworkOrigin( pos ); -#endif - SetLocalOrigin( pos ); -} - -inline void CBeam::SetEndPos( const Vector &pos ) -{ - m_vecEndPos = pos; -} - - // center point of beam -inline const Vector &CBeam::WorldSpaceCenter( void ) const -{ - Vector &vecResult = AllocTempVector(); - VectorAdd( GetAbsStartPos(), GetAbsEndPos(), vecResult ); - vecResult *= 0.5f; - return vecResult; -} - -inline void CBeam::SetStartAttachment( int attachment ) -{ - Assert( (attachment & ~ATTACHMENT_INDEX_MASK) == 0 ); - m_nAttachIndex.Set( 0, attachment ); -} - -inline void CBeam::SetEndAttachment( int attachment ) -{ - Assert( (attachment & ~ATTACHMENT_INDEX_MASK) == 0 ); - m_nAttachIndex.Set( m_nNumBeamEnts-1, attachment ); -} - -inline void CBeam::SetTexture( int spriteIndex ) -{ - SetModelIndex( spriteIndex ); -} - -inline void CBeam::SetHaloTexture( int spriteIndex ) -{ - m_nHaloIndex = spriteIndex; -} - -inline void CBeam::SetHaloScale( float haloScale ) -{ - m_fHaloScale = haloScale; -} - -inline void CBeam::SetWidth( float width ) -{ - Assert( width <= MAX_BEAM_WIDTH ); - m_fWidth = MIN( MAX_BEAM_WIDTH, width ); -} - -inline void CBeam::SetEndWidth( float endWidth ) -{ - Assert( endWidth <= MAX_BEAM_WIDTH ); - m_fEndWidth = MIN( MAX_BEAM_WIDTH, endWidth ); -} - -inline void CBeam::SetFadeLength( float fadeLength ) -{ - m_fFadeLength = fadeLength; -} - -inline void CBeam::SetNoise( float amplitude ) -{ - m_fAmplitude = amplitude; -} - -inline void CBeam::SetColor( int r, int g, int b ) -{ - SetRenderColor( r, g, b, GetRenderColor().a ); -} - -inline void CBeam::SetBrightness( int brightness ) -{ - SetRenderColorA( brightness ); -} - -inline void CBeam::SetFrame( float frame ) -{ - m_fStartFrame = frame; -} - -inline void CBeam::SetScrollRate( int speed ) -{ - m_fSpeed = speed; -} - -inline CBaseEntity* CBeam::GetStartEntityPtr( void ) const -{ - return m_hAttachEntity[0].Get(); -} - -inline int CBeam::GetStartEntity( void ) const -{ - CBaseEntity *pEntity = m_hAttachEntity[0].Get(); - return pEntity ? pEntity->entindex() : 0; -} - -inline CBaseEntity* CBeam::GetEndEntityPtr( void ) const -{ - return m_hAttachEntity[1].Get(); -} - -inline int CBeam::GetEndEntity( void ) const -{ - CBaseEntity *pEntity = m_hAttachEntity[m_nNumBeamEnts-1].Get(); - return pEntity ? pEntity->entindex() : 0; -} - -inline int CBeam::GetStartAttachment() const -{ - return m_nAttachIndex[0] & ATTACHMENT_INDEX_MASK; -} - -inline int CBeam::GetEndAttachment() const -{ - return m_nAttachIndex[m_nNumBeamEnts-1] & ATTACHMENT_INDEX_MASK; -} - -inline int CBeam::GetTexture( void ) -{ - return GetModelIndex(); -} - -inline float CBeam::GetWidth( void ) const -{ - return m_fWidth; -} - -inline float CBeam::GetEndWidth( void ) const -{ - return m_fEndWidth; -} - -inline float CBeam::GetFadeLength( void ) const -{ - return m_fFadeLength; -} - -inline float CBeam::GetNoise( void ) const -{ - return m_fAmplitude; -} - -inline int CBeam::GetBrightness( void ) const -{ - return GetRenderColor().a; -} - -inline float CBeam::GetFrame( void ) const -{ - return m_fStartFrame; -} - -inline float CBeam::GetScrollRate( void ) const -{ - return m_fSpeed; -} - -inline float CBeam::GetHDRColorScale( void ) const -{ - return m_flHDRColorScale; -} - -inline void CBeam::LiveForTime( float time ) -{ - SetThink(&CBeam::SUB_Remove); - SetNextThink( gpGlobals->curtime + time ); -} - -inline void CBeam::BeamDamageInstant( trace_t *ptr, float damage ) -{ - m_flDamage = damage; - m_flFireTime = gpGlobals->curtime - 1; - BeamDamage(ptr); -} - -bool IsStaticPointEntity( CBaseEntity *pEnt ); - -// Macro to wrap creation -#define BEAM_CREATE_PREDICTABLE( name, width, player ) \ - CBeam::BeamCreatePredictable( __FILE__, __LINE__, false, name, width, player ) - -#define BEAM_CREATE_PREDICTABLE_PERSIST( name, width, player ) \ - CBeam::BeamCreatePredictable( __FILE__, __LINE__, true, name, width, player ) - -// Start/End Entity is encoded as 12 bits of entity index, and 4 bits of attachment (4:12) -#define BEAMENT_ENTITY(x) ((x)&0xFFF) -#define BEAMENT_ATTACHMENT(x) (((x)>>12)&0xF) - - -// Beam types, encoded as a byte -enum -{ - BEAM_POINTS = 0, - BEAM_ENTPOINT, - BEAM_ENTS, - BEAM_HOSE, - BEAM_SPLINE, - BEAM_LASER, - NUM_BEAM_TYPES -}; - - -#endif // BEAM_H diff --git a/game/shared/choreoactor.cpp b/game/shared/choreoactor.cpp deleted file mode 100644 index cf2f76c12..000000000 --- a/game/shared/choreoactor.cpp +++ /dev/null @@ -1,294 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#include -#include -#include -#include "choreoactor.h" -#include "choreochannel.h" -#include "choreoscene.h" -#include "tier1/utlbuffer.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CChoreoActor::CChoreoActor( void ) -{ - Init(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CChoreoActor::CChoreoActor( const char *name ) -{ - Init(); - SetName( name ); -} - -//----------------------------------------------------------------------------- -// Purpose: // Assignment -// Input : src - -// Output : CChoreoActor& -//----------------------------------------------------------------------------- -CChoreoActor& CChoreoActor::operator=( const CChoreoActor& src ) -{ - m_bActive = src.m_bActive; - - Q_strncpy( m_szName, src.m_szName, sizeof( m_szName ) ); - Q_strncpy( m_szFacePoserModelName, src.m_szFacePoserModelName, sizeof( m_szFacePoserModelName ) ); - - for ( int i = 0; i < src.m_Channels.Size(); i++ ) - { - CChoreoChannel *c = src.m_Channels[ i ]; - CChoreoChannel *newChannel = new CChoreoChannel(); - newChannel->SetActor( this ); - *newChannel = *c; - AddChannel( newChannel ); - } - - return *this; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoActor::Init( void ) -{ - m_szName[ 0 ] = 0; - m_szFacePoserModelName[ 0 ] = 0; - m_bActive = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -void CChoreoActor::SetName( const char *name ) -{ - assert( strlen( name ) < MAX_ACTOR_NAME ); - Q_strncpy( m_szName, name, sizeof( m_szName ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CChoreoActor::GetName( void ) -{ - return m_szName; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CChoreoActor::GetNumChannels( void ) -{ - return m_Channels.Size(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : channel - -// Output : CChoreoChannel -//----------------------------------------------------------------------------- -CChoreoChannel *CChoreoActor::GetChannel( int channel ) -{ - if ( channel < 0 || channel >= m_Channels.Size() ) - { - return NULL; - } - - return m_Channels[ channel ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *channel - -//----------------------------------------------------------------------------- -void CChoreoActor::AddChannel( CChoreoChannel *channel ) -{ - m_Channels.AddToTail( channel ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *channel - -//----------------------------------------------------------------------------- -void CChoreoActor::RemoveChannel( CChoreoChannel *channel ) -{ - int idx = FindChannelIndex( channel ); - if ( idx == -1 ) - return; - - m_Channels.Remove( idx ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoActor::RemoveAllChannels() -{ - m_Channels.RemoveAll(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : c1 - -// c2 - -//----------------------------------------------------------------------------- -void CChoreoActor::SwapChannels( int c1, int c2 ) -{ - CChoreoChannel *temp; - - temp = m_Channels[ c1 ]; - m_Channels[ c1 ] = m_Channels[ c2 ]; - m_Channels[ c2 ] = temp; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *channel - -// Output : int -//----------------------------------------------------------------------------- -int CChoreoActor::FindChannelIndex( CChoreoChannel *channel ) -{ - for ( int i = 0; i < m_Channels.Size(); i++ ) - { - if ( channel == m_Channels[ i ] ) - { - return i; - } - } - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -void CChoreoActor::SetFacePoserModelName( const char *name ) -{ - Q_strncpy( m_szFacePoserModelName, name, sizeof( m_szFacePoserModelName ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : char const -//----------------------------------------------------------------------------- -const char *CChoreoActor::GetFacePoserModelName( void ) const -{ - return m_szFacePoserModelName; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : active - -//----------------------------------------------------------------------------- -void CChoreoActor::SetActive( bool active ) -{ - m_bActive = active; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChoreoActor::GetActive( void ) const -{ - return m_bActive; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoActor::MarkForSaveAll( bool mark ) -{ - SetMarkedForSave( mark ); - - int c = GetNumChannels(); - for ( int i = 0; i < c; i++ ) - { - CChoreoChannel *channel = GetChannel( i ); - channel->MarkForSaveAll( mark ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -// Output : CChoreoChannel -//----------------------------------------------------------------------------- -CChoreoChannel *CChoreoActor::FindChannel( const char *name ) -{ - int c = GetNumChannels(); - for ( int i = 0; i < c; i++ ) - { - CChoreoChannel *channel = GetChannel( i ); - if ( !Q_stricmp( channel->GetName(), name ) ) - return channel; - } - - return NULL; -} - -void CChoreoActor::SaveToBuffer( CUtlBuffer& buf, CChoreoScene *pScene, IChoreoStringPool *pStringPool ) -{ - buf.PutShort( pStringPool->FindOrAddString( GetName() ) ); - - int c = GetNumChannels(); - Assert( c <= 255 ); - buf.PutUnsignedChar( c ); - - for ( int i = 0; i < c; i++ ) - { - CChoreoChannel *channel = GetChannel( i ); - Assert( channel ); - channel->SaveToBuffer( buf, pScene, pStringPool ); - } - - /* - if ( Q_strlen( a->GetFacePoserModelName() ) > 0 ) - { - FilePrintf( buf, level + 1, "faceposermodel \"%s\"\n", a->GetFacePoserModelName() ); - } - */ - buf.PutChar( GetActive() ? 1 : 0 ); -} - -bool CChoreoActor::RestoreFromBuffer( CUtlBuffer& buf, CChoreoScene *pScene, IChoreoStringPool *pStringPool ) -{ - char sz[ 256 ]; - pStringPool->GetString( buf.GetShort(), sz, sizeof( sz ) ); - - SetName( sz ); - - int i; - int c = buf.GetUnsignedChar(); - for ( i = 0; i < c; i++ ) - { - CChoreoChannel *channel = pScene->AllocChannel(); - Assert( channel ); - if ( channel->RestoreFromBuffer( buf, pScene, this, pStringPool ) ) - { - AddChannel( channel ); - channel->SetActor( this ); - continue; - } - - return false; - } - - SetActive( buf.GetChar() == 1 ? true : false ); - - return true; -} - diff --git a/game/shared/choreoactor.h b/game/shared/choreoactor.h deleted file mode 100644 index f6a85d9ef..000000000 --- a/game/shared/choreoactor.h +++ /dev/null @@ -1,89 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#ifndef CHOREOACTOR_H -#define CHOREOACTOR_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/utlvector.h" - -class CChoreoChannel; -class CChoreoScene; -class CUtlBuffer; -class IChoreoStringPool; - -//----------------------------------------------------------------------------- -// Purpose: The actor is the atomic element of a scene -// A scene can have one or more actors, who have multiple events on one or -// more channels -//----------------------------------------------------------------------------- -class CChoreoActor -{ -public: - - // Construction - CChoreoActor( void ); - CChoreoActor( const char *name ); - // Assignment - CChoreoActor& operator = ( const CChoreoActor& src ); - - // Serialization - void SaveToBuffer( CUtlBuffer& buf, CChoreoScene *pScene, IChoreoStringPool *pStringPool ); - bool RestoreFromBuffer( CUtlBuffer& buf, CChoreoScene *pScene, IChoreoStringPool *pStringPool ); - - // Accessors - void SetName( const char *name ); - const char *GetName( void ); - - // Iteration - int GetNumChannels( void ); - CChoreoChannel *GetChannel( int channel ); - - CChoreoChannel *FindChannel( const char *name ); - - // Manipulate children - void AddChannel( CChoreoChannel *channel ); - void RemoveChannel( CChoreoChannel *channel ); - int FindChannelIndex( CChoreoChannel *channel ); - void SwapChannels( int c1, int c2 ); - void RemoveAllChannels(); - - void SetFacePoserModelName( const char *name ); - char const *GetFacePoserModelName( void ) const; - - void SetActive( bool active ); - bool GetActive( void ) const; - - bool IsMarkedForSave() const { return m_bMarkedForSave; } - void SetMarkedForSave( bool mark ) { m_bMarkedForSave = mark; } - - void MarkForSaveAll( bool mark ); - -private: - // Clear structure out - void Init( void ); - - enum - { - MAX_ACTOR_NAME = 128, - MAX_FACEPOSER_MODEL_NAME = 128 - }; - - char m_szName[ MAX_ACTOR_NAME ]; - char m_szFacePoserModelName[ MAX_FACEPOSER_MODEL_NAME ]; - - // Children - CUtlVector < CChoreoChannel * > m_Channels; - - bool m_bActive; - - // Purely for save/load - bool m_bMarkedForSave; -}; - -#endif // CHOREOACTOR_H diff --git a/game/shared/choreochannel.cpp b/game/shared/choreochannel.cpp deleted file mode 100644 index e5f943d6d..000000000 --- a/game/shared/choreochannel.cpp +++ /dev/null @@ -1,563 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include -#include -#include -#include "choreochannel.h" -#include "choreoevent.h" -#include "choreoscene.h" -#include "utlrbtree.h" -#include "tier1/utlbuffer.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CChoreoChannel::CChoreoChannel( void ) -{ - Init(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -CChoreoChannel::CChoreoChannel(const char *name ) -{ - Init(); - SetName( name ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Assignment -// Input : src - -//----------------------------------------------------------------------------- -CChoreoChannel& CChoreoChannel::operator=( const CChoreoChannel& src ) -{ - m_bActive = src.m_bActive; - Q_strncpy( m_szName, src.m_szName, sizeof( m_szName ) ); - for ( int i = 0; i < src.m_Events.Size(); i++ ) - { - CChoreoEvent *e = src.m_Events[ i ]; - CChoreoEvent *newEvent = new CChoreoEvent( e->GetScene() ); - *newEvent = *e; - AddEvent( newEvent ); - newEvent->SetChannel( this ); - newEvent->SetActor( m_pActor ); - } - - return *this; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -void CChoreoChannel::SetName( const char *name ) -{ - assert( Q_strlen( name ) < MAX_CHANNEL_NAME ); - Q_strncpy( m_szName, name, sizeof( m_szName ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CChoreoChannel::GetName( void ) -{ - return m_szName; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CChoreoChannel::GetNumEvents( void ) -{ - return m_Events.Size(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : event - -// Output : CChoreoEvent -//----------------------------------------------------------------------------- -CChoreoEvent *CChoreoChannel::GetEvent( int event ) -{ - if ( event < 0 || event >= m_Events.Size() ) - { - return NULL; - } - - return m_Events[ event ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *event - -//----------------------------------------------------------------------------- -void CChoreoChannel::AddEvent( CChoreoEvent *event ) -{ - m_Events.AddToTail( event ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *event - -//----------------------------------------------------------------------------- -void CChoreoChannel::RemoveEvent( CChoreoEvent *event ) -{ - int idx = FindEventIndex( event ); - if ( idx == -1 ) - return; - - m_Events.Remove( idx ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoChannel::RemoveAllEvents() -{ - m_Events.RemoveAll(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *event - -// Output : int -//----------------------------------------------------------------------------- -int CChoreoChannel::FindEventIndex( CChoreoEvent *event ) -{ - for ( int i = 0; i < m_Events.Size(); i++ ) - { - if ( event == m_Events[ i ] ) - { - return i; - } - } - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoChannel::Init( void ) -{ - m_szName[ 0 ] = 0; - SetActor( NULL ); - m_bActive = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoActor -//----------------------------------------------------------------------------- -CChoreoActor *CChoreoChannel::GetActor( void ) -{ - return m_pActor; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -//----------------------------------------------------------------------------- -void CChoreoChannel::SetActor( CChoreoActor *actor ) -{ - m_pActor = actor; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : active - -//----------------------------------------------------------------------------- -void CChoreoChannel::SetActive( bool active ) -{ - m_bActive = active; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChoreoChannel::GetActive( void ) const -{ - return m_bActive; -} - -static bool ChoreEventStartTimeLessFunc( CChoreoEvent * const &p1, CChoreoEvent * const &p2 ) -{ - CChoreoEvent *e1; - CChoreoEvent *e2; - - e1 = const_cast< CChoreoEvent * >( p1 ); - e2 = const_cast< CChoreoEvent * >( p2 ); - - return e1->GetStartTime() < e2->GetStartTime(); -} - -void CChoreoChannel::ReconcileGestureTimes() -{ - // Sort gesture events within channel by starting time - CUtlRBTree< CChoreoEvent * > sortedGestures( 0, 0, ChoreEventStartTimeLessFunc ); - int i; - // Sort items - int c = GetNumEvents(); - for ( i = 0; i < c; i++ ) - { - CChoreoEvent *e = GetEvent( i ); - Assert( e ); - if ( e->GetType() != CChoreoEvent::GESTURE ) - continue; - - sortedGestures.Insert( e ); - } - - // Now walk list of gestures - if ( !sortedGestures.Count() ) - return; - - CChoreoEvent *previous = NULL; - - for ( i = sortedGestures.FirstInorder(); i != sortedGestures.InvalidIndex(); i = sortedGestures.NextInorder( i ) ) - { - CChoreoEvent *event = sortedGestures[ i ]; - - if ( !previous ) - { - // event->SetStartTime( 0.0f ); - } - else if ( previous->GetSyncToFollowingGesture() ) - { - // TODO: ask the sequence for what tags to match - - CEventAbsoluteTag *pEntryTag = event->FindEntryTag( CChoreoEvent::PLAYBACK ); - CEventAbsoluteTag *pExitTag = previous->FindExitTag( CChoreoEvent::PLAYBACK ); - - if (pEntryTag && pExitTag) - { - float entryTime = pEntryTag->GetAbsoluteTime( ); - - // get current decay rate of previous gesture - float duration = previous->GetDuration(); - float decayTime = (1.0 - pExitTag->GetPercentage()) * duration; - - // adjust the previous gestures end time to current apex + existing decay rate - previous->RescaleGestureTimes( previous->GetStartTime(), entryTime + decayTime, true ); - previous->SetEndTime( entryTime + decayTime ); - - // set the previous gestures end tag to the current apex - pExitTag->SetAbsoluteTime( entryTime ); - - event->PreventTagOverlap( ); - previous->PreventTagOverlap( ); - } - // BUG: Tracker 3298: ywb 1/31/04 - // I think this fixes the issue with abutting past NULL gestures on paste: - // Here's the bug report: - // ------------------------- - // When copying and pasteing posture and gesture clips in face poser the beginings of the clips stretch - // to the begining of the scene even if there is a null gesture in place at the begining. - // ------------------------- - /* - else if ( pEntryTag && !Q_stricmp( previous->GetName(), "NULL" ) ) - { - // If the previous was a null event, then do a bit of fixup - event->SetStartTime( previous->GetEndTime() ); - - event->PreventTagOverlap( ); - } - */ - - // The previous event decays from it's end dispaly end time to the current event's display start time - // The next event starts just after the display end time of the previous event - } - - previous = event; - } - - if ( previous ) - { - CChoreoScene *scene = previous->GetScene(); - if ( scene ) - { - // HACK: Could probably do better by allowing user to drag the blue "end time" bar - //float finish = scene->FindStopTime(); - //previous->RescaleGestureTimes( previous->GetStartTime(), finish ); - //previous->SetEndTime( finish ); - } - } - - /* - c = 0; - for ( i = sortedGestures.FirstInorder(); i != sortedGestures.InvalidIndex(); i = sortedGestures.NextInorder( i ) ) - { - CChoreoEvent *event = sortedGestures[ i ]; - - Msg( "event %i start %f disp %f dispend %f end %f\n", - c + 1, - event->GetStartTime( CChoreoEvent::SIMULATION ), - event->GetStartTime( CChoreoEvent::DISPLAY ), - event->GetEndTime( CChoreoEvent::DISPLAY ), - event->GetEndTime( CChoreoEvent::SIMULATION ) - ); - c++; - } - */ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoChannel::MarkForSaveAll( bool mark ) -{ - SetMarkedForSave( mark ); - - int c = GetNumEvents(); - for ( int i = 0; i < c; i++ ) - { - CChoreoEvent *e = GetEvent( i ); - e->SetMarkedForSave( mark ); - } -} - - -struct EventGroup -{ - EventGroup() : - timeSortedEvents( 0, 0, ChoreEventStartTimeLessFunc ) - { - } - - EventGroup( const EventGroup& src ) - : - timeSortedEvents( 0, 0, ChoreEventStartTimeLessFunc ) - { - timeSortedEvents.RemoveAll(); - int i = src.timeSortedEvents.FirstInorder(); - while ( i != src.timeSortedEvents.InvalidIndex() ) - { - timeSortedEvents.Insert( src.timeSortedEvents[ i ] ); - - i = src.timeSortedEvents.NextInorder( i ); - } - } - - EventGroup & operator=( const EventGroup& src ) - { - if ( this == &src ) - return *this; - - timeSortedEvents.RemoveAll(); - int i = src.timeSortedEvents.FirstInorder(); - while ( i != src.timeSortedEvents.InvalidIndex() ) - { - timeSortedEvents.Insert( src.timeSortedEvents[ i ] ); - - i = src.timeSortedEvents.NextInorder( i ); - } - return *this; - } - - CUtlRBTree< CChoreoEvent * > timeSortedEvents; -}; - -// Compute master/slave, count, endtime info for close captioning data -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoChannel::ReconcileCloseCaption() -{ - // Create a dictionary based on the combined token name - CUtlDict< EventGroup, int > validSpeakEventsGroupedByName; - - int i; - // Sort items - int c = GetNumEvents(); - for ( i = 0; i < c; i++ ) - { - CChoreoEvent *e = GetEvent( i ); - Assert( e ); - if ( e->GetType() != CChoreoEvent::SPEAK ) - continue; - - CChoreoEvent::CLOSECAPTION type; - - type = e->GetCloseCaptionType(); - if ( type == CChoreoEvent::CC_DISABLED ) - { - e->SetUsingCombinedFile( false ); - e->SetRequiredCombinedChecksum( 0 ); - e->SetNumSlaves( 0 ); - e->SetLastSlaveEndTime( 0.0f ); - continue; - } - - char const *name = e->GetCloseCaptionToken(); - if ( !name || !name[0] ) - { - // Fixup invalid slave tag - if ( type == CChoreoEvent::CC_SLAVE ) - { - e->SetCloseCaptionType( CChoreoEvent::CC_MASTER ); - e->SetUsingCombinedFile( false ); - e->SetRequiredCombinedChecksum( 0 ); - e->SetNumSlaves( 0 ); - e->SetLastSlaveEndTime( 0.0f ); - } - continue; - } - - int idx = validSpeakEventsGroupedByName.Find( name ); - if ( idx == validSpeakEventsGroupedByName.InvalidIndex() ) - { - EventGroup eg; - eg.timeSortedEvents.Insert( e ); - validSpeakEventsGroupedByName.Insert( name, eg ); - } - else - { - EventGroup & eg = validSpeakEventsGroupedByName[ idx ]; - eg.timeSortedEvents.Insert( e ); - } - } - - c = validSpeakEventsGroupedByName.Count(); - // Now walk list of events by group - if ( !c ) - { - return; - } - - for ( i = 0; i < c; ++i ) - { - EventGroup & eg = validSpeakEventsGroupedByName[ i ]; - int sortedEventInGroup = eg.timeSortedEvents.Count(); - // If there's only one, just mark it valid - if ( sortedEventInGroup <= 1 ) - { - CChoreoEvent *e = eg.timeSortedEvents[ 0 ]; - Assert( e ); - // Make sure it's the master - e->SetCloseCaptionType( CChoreoEvent::CC_MASTER ); - // Since it's by itself, can't be using "combined" file - e->SetUsingCombinedFile( false ); - e->SetRequiredCombinedChecksum( 0 ); - e->SetNumSlaves( 0 ); - e->SetLastSlaveEndTime( 0.0f ); - continue; - } - - // Okay, read them back in of start time - int j = eg.timeSortedEvents.FirstInorder(); - CChoreoEvent *master = NULL; - while ( j != eg.timeSortedEvents.InvalidIndex() ) - { - CChoreoEvent *e = eg.timeSortedEvents[ j ]; - if ( !master ) - { - master = e; - e->SetCloseCaptionType( CChoreoEvent::CC_MASTER ); - //e->SetUsingCombinedFile( true ); - e->SetRequiredCombinedChecksum( 0 ); - e->SetNumSlaves( sortedEventInGroup - 1 ); - e->SetLastSlaveEndTime( e->GetEndTime() ); - } - else - { - // Keep bumping out the end time - master->SetLastSlaveEndTime( e->GetEndTime() ); - e->SetCloseCaptionType( CChoreoEvent::CC_SLAVE ); - e->SetUsingCombinedFile( master->IsUsingCombinedFile() ); - e->SetRequiredCombinedChecksum( 0 ); - e->SetLastSlaveEndTime( 0.0f ); - } - - j = eg.timeSortedEvents.NextInorder( j ); - } - } -} - -bool CChoreoChannel::GetSortedCombinedEventList( char const *cctoken, CUtlRBTree< CChoreoEvent * >& events ) -{ - events.RemoveAll(); - - int i; - // Sort items - int c = GetNumEvents(); - for ( i = 0; i < c; i++ ) - { - CChoreoEvent *e = GetEvent( i ); - Assert( e ); - if ( e->GetType() != CChoreoEvent::SPEAK ) - continue; - - if ( e->GetCloseCaptionType() == CChoreoEvent::CC_DISABLED ) - continue; - - // A master with no slaves is not a combined event - if ( e->GetCloseCaptionType() == CChoreoEvent::CC_MASTER && - e->GetNumSlaves() == 0 ) - continue; - - char const *token = e->GetCloseCaptionToken(); - if ( Q_stricmp( token, cctoken ) ) - continue; - - events.Insert( e ); - } - - return ( events.Count() > 0 ) ? true : false; -} - -void CChoreoChannel::SaveToBuffer( CUtlBuffer& buf, CChoreoScene *pScene, IChoreoStringPool *pStringPool ) -{ - buf.PutShort( pStringPool->FindOrAddString( GetName() ) ); - - int c = GetNumEvents(); - Assert( c <= 255 ); - buf.PutUnsignedChar( c ); - - for ( int i = 0; i < c; i++ ) - { - CChoreoEvent *e = GetEvent( i ); - Assert( e ); - e->SaveToBuffer( buf, pScene, pStringPool ); - } - - buf.PutChar( GetActive() ? 1 : 0 ); -} - -bool CChoreoChannel::RestoreFromBuffer( CUtlBuffer& buf, CChoreoScene *pScene, CChoreoActor *pActor, IChoreoStringPool *pStringPool ) -{ - char sz[ 256 ]; - pStringPool->GetString( buf.GetShort(), sz, sizeof( sz ) ); - SetName( sz ); - - int numEvents = (int)buf.GetUnsignedChar(); - for ( int i = 0 ; i < numEvents; ++i ) - { - CChoreoEvent *e = pScene->AllocEvent(); - if ( e->RestoreFromBuffer( buf, pScene, pStringPool ) ) - { - AddEvent( e ); - e->SetChannel( this ); - e->SetActor( pActor ); - continue; - } - return false; - } - - SetActive( buf.GetChar() == 1 ? true : false ); - - return true; -} diff --git a/game/shared/choreochannel.h b/game/shared/choreochannel.h deleted file mode 100644 index 176c21576..000000000 --- a/game/shared/choreochannel.h +++ /dev/null @@ -1,95 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef CHOREOCHANNEL_H -#define CHOREOCHANNEL_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/utlvector.h" -#include "tier1/utlrbtree.h" - -class CChoreoEvent; -class CChoreoActor; -class CChoreoScene; -class CUtlBuffer; -class IChoreoStringPool; - -//----------------------------------------------------------------------------- -// Purpose: A channel is owned by an actor and contains zero or more events -//----------------------------------------------------------------------------- -class CChoreoChannel -{ -public: - // Construction - CChoreoChannel( void ); - CChoreoChannel( const char *name ); - - // Assignment - CChoreoChannel& operator=(const CChoreoChannel& src ); - - // Serialization - void SaveToBuffer( CUtlBuffer& buf, CChoreoScene *pScene, IChoreoStringPool *pStringPool ); - bool RestoreFromBuffer( CUtlBuffer& buf, CChoreoScene *pScene, CChoreoActor *pActor, IChoreoStringPool *pStringPool ); - - // Accessors - void SetName( const char *name ); - const char *GetName( void ); - - // Iterate children - int GetNumEvents( void ); - CChoreoEvent *GetEvent( int event ); - - // Manipulate children - void AddEvent( CChoreoEvent *event ); - void RemoveEvent( CChoreoEvent *event ); - int FindEventIndex( CChoreoEvent *event ); - void RemoveAllEvents(); - - CChoreoActor *GetActor( void ); - void SetActor( CChoreoActor *actor ); - - void SetActive( bool active ); - bool GetActive( void ) const; - - // Compute true start/end times for gesture events in this channel, factoring in "null" gestures as needed - void ReconcileGestureTimes(); - // Compute master/slave, count, endtime info for close captioning data - void ReconcileCloseCaption(); - - bool IsMarkedForSave() const { return m_bMarkedForSave; } - void SetMarkedForSave( bool mark ) { m_bMarkedForSave = mark; } - - void MarkForSaveAll( bool mark ); - - bool GetSortedCombinedEventList( char const *cctoken, CUtlRBTree< CChoreoEvent * >& sorted ); - -private: - // Initialize fields - void Init( void ); - - enum - { - MAX_CHANNEL_NAME = 128, - }; - - CChoreoActor *m_pActor; - - // Channels are just named - char m_szName[ MAX_CHANNEL_NAME ]; - - // All of the events for this channel - CUtlVector < CChoreoEvent * > m_Events; - - bool m_bActive; - - // Purely for save/load - bool m_bMarkedForSave; -}; - -#endif // CHOREOCHANNEL_H diff --git a/game/shared/choreoevent.cpp b/game/shared/choreoevent.cpp deleted file mode 100644 index a8431970e..000000000 --- a/game/shared/choreoevent.cpp +++ /dev/null @@ -1,4513 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "tier0/dbg.h" -#include -#include -#include -#include "choreoevent.h" -#include "choreoactor.h" -#include "choreochannel.h" -#include "mathlib/mathlib.h" -#include "tier1/strtools.h" -#include "choreoscene.h" -#include "ichoreoeventcallback.h" -#include "tier1/utlbuffer.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -int CChoreoEvent::s_nGlobalID = 1; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *owner - -// *name - -// percentage - -//----------------------------------------------------------------------------- -CEventRelativeTag::CEventRelativeTag( CChoreoEvent *owner, const char *name, float percentage ) -{ - Assert( owner ); - Assert( name ); - Assert( percentage >= 0.0f ); - Assert( percentage <= 1.0f ); - - m_Name = name; - m_flPercentage = percentage; - m_pOwner = owner; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : src - -//----------------------------------------------------------------------------- -CEventRelativeTag::CEventRelativeTag( const CEventRelativeTag& src ) -{ - m_Name = src.m_Name; - m_flPercentage = src.m_flPercentage; - m_pOwner = src.m_pOwner; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CEventRelativeTag::GetName( void ) -{ - return m_Name.Get(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CEventRelativeTag::GetPercentage( void ) -{ - return m_flPercentage; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : percentage - -//----------------------------------------------------------------------------- -void CEventRelativeTag::SetPercentage( float percentage ) -{ - m_flPercentage = percentage; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoEvent -//----------------------------------------------------------------------------- -CChoreoEvent *CEventRelativeTag::GetOwner( void ) -{ - return m_pOwner; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *event - -//----------------------------------------------------------------------------- -void CEventRelativeTag::SetOwner( CChoreoEvent *event ) -{ - m_pOwner = event; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the corrected time based on the owner's length and start time -// Output : float -//----------------------------------------------------------------------------- -float CEventRelativeTag::GetStartTime( void ) -{ - Assert( m_pOwner ); - if ( !m_pOwner ) - { - return 0.0f; - } - - float ownerstart = m_pOwner->GetStartTime(); - float ownerduration = m_pOwner->GetDuration(); - - return ( ownerstart + ownerduration * m_flPercentage ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *owner - -// *name - -// percentage - -//----------------------------------------------------------------------------- -CFlexTimingTag::CFlexTimingTag( CChoreoEvent *owner, const char *name, float percentage, bool locked ) -: BaseClass( owner, name, percentage ) -{ - m_bLocked = locked; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : src - -//----------------------------------------------------------------------------- -CFlexTimingTag::CFlexTimingTag( const CFlexTimingTag& src ) -: BaseClass( src ) -{ - m_bLocked = src.m_bLocked; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CFlexTimingTag::GetLocked( void ) -{ - return m_bLocked; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : locked - -//----------------------------------------------------------------------------- -void CFlexTimingTag::SetLocked( bool locked ) -{ - m_bLocked = locked; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *owner - -// *name - -// percentage - -//----------------------------------------------------------------------------- -CEventAbsoluteTag::CEventAbsoluteTag( CChoreoEvent *owner, const char *name, float t ) -{ - Assert( owner ); - Assert( name ); - Assert( t >= 0.0f ); - - m_Name = name; - m_flPercentage = t; - m_pOwner = owner; - m_bLocked = false; - m_bLinear = false; - m_bEntry = false; - m_bExit = false; - -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : src - -//----------------------------------------------------------------------------- -CEventAbsoluteTag::CEventAbsoluteTag( const CEventAbsoluteTag& src ) -{ - m_Name = src.m_Name; - m_flPercentage = src.m_flPercentage; - m_pOwner = src.m_pOwner; - m_bLocked = src.m_bLocked; - m_bLinear = src.m_bLinear; - m_bEntry = src.m_bEntry; - m_bExit = src.m_bExit; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CEventAbsoluteTag::GetName( void ) -{ - return m_Name.Get(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CEventAbsoluteTag::GetPercentage( void ) -{ - return m_flPercentage; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : percentage - -//----------------------------------------------------------------------------- -void CEventAbsoluteTag::SetPercentage( float percentage ) -{ - m_flPercentage = percentage; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CEventAbsoluteTag::GetEventTime( void ) -{ - Assert( m_pOwner ); - if ( !m_pOwner ) - { - return 0.0f; - } - - float ownerduration = m_pOwner->GetDuration(); - - return (m_flPercentage * ownerduration); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : percentage - -//----------------------------------------------------------------------------- -void CEventAbsoluteTag::SetEventTime( float t ) -{ - Assert( m_pOwner ); - if ( !m_pOwner ) - { - return; - } - - float ownerduration = m_pOwner->GetDuration(); - - m_flPercentage = (t / ownerduration); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CEventAbsoluteTag::GetAbsoluteTime( void ) -{ - Assert( m_pOwner ); - if ( !m_pOwner ) - { - return 0.0f; - } - - float ownerstart = m_pOwner->GetStartTime(); - float ownerduration = m_pOwner->GetDuration(); - - return (ownerstart + m_flPercentage * ownerduration); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : percentage - -//----------------------------------------------------------------------------- -void CEventAbsoluteTag::SetAbsoluteTime( float t ) -{ - Assert( m_pOwner ); - if ( !m_pOwner ) - { - return; - } - - float ownerstart = m_pOwner->GetStartTime(); - float ownerduration = m_pOwner->GetDuration(); - - m_flPercentage = (t - ownerstart) / ownerduration; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoEvent -//----------------------------------------------------------------------------- -CChoreoEvent *CEventAbsoluteTag::GetOwner( void ) -{ - return m_pOwner; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *event - -//----------------------------------------------------------------------------- -void CEventAbsoluteTag::SetOwner( CChoreoEvent *event ) -{ - m_pOwner = event; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *event - -//----------------------------------------------------------------------------- -void CEventAbsoluteTag::SetLocked( bool bLocked ) -{ - m_bLocked = bLocked; -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoEvent -//----------------------------------------------------------------------------- -bool CEventAbsoluteTag::GetLocked( void ) -{ - return m_bLocked; -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *event - -//----------------------------------------------------------------------------- -void CEventAbsoluteTag::SetLinear( bool bLinear ) -{ - m_bLinear = bLinear; -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoEvent -//----------------------------------------------------------------------------- -bool CEventAbsoluteTag::GetLinear( void ) -{ - return m_bLinear; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *event - -//----------------------------------------------------------------------------- -void CEventAbsoluteTag::SetEntry( bool bEntry ) -{ - m_bEntry = bEntry; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoEvent -//----------------------------------------------------------------------------- -bool CEventAbsoluteTag::GetEntry( void ) -{ - return m_bEntry; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *event - -//----------------------------------------------------------------------------- -void CEventAbsoluteTag::SetExit( bool bExit ) -{ - m_bExit = bExit; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoEvent -//----------------------------------------------------------------------------- -bool CEventAbsoluteTag::GetExit( void ) -{ - return m_bExit; -} - - - - -// FLEX ANIMATIONS -//----------------------------------------------------------------------------- -// Purpose: Constructor -// Input : *event - -//----------------------------------------------------------------------------- -CFlexAnimationTrack::CFlexAnimationTrack( CChoreoEvent *event ) -{ - m_pEvent = event; - m_pControllerName = NULL; - m_bActive = false; - m_bCombo = false; - m_bServerSide = false; - m_nFlexControllerIndex[ 0 ] = m_nFlexControllerIndex[ 1 ] = -1; - m_nFlexControllerIndexRaw[ 0 ] = m_nFlexControllerIndexRaw[ 1 ] = LocalFlexController_t(-1); - - // base track has range, combo is always 0..1 - m_flMin = 0.0f; - m_flMax = 0.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : src - -//----------------------------------------------------------------------------- -CFlexAnimationTrack::CFlexAnimationTrack( const CFlexAnimationTrack* src ) -{ - m_pControllerName = NULL; - SetFlexControllerName( src->m_pControllerName ? src->m_pControllerName : "" ); - - m_bActive = src->m_bActive; - m_bCombo = src->m_bCombo; - m_bServerSide = src->m_bServerSide; - - for ( int t = 0; t < 2; t++ ) - { - m_Samples[ t ].Purge(); - for ( int i = 0 ;i < src->m_Samples[ t ].Size(); i++ ) - { - CExpressionSample s = src->m_Samples[ t ][ i ]; - m_Samples[ t ].AddToTail( s ); - } - } - - for ( int side = 0; side < 2; side++ ) - { - m_nFlexControllerIndex[ side ] = src->m_nFlexControllerIndex[ side ]; - m_nFlexControllerIndexRaw[ side ] = src->m_nFlexControllerIndexRaw[ side ]; - } - - m_flMin = src->m_flMin; - m_flMax = src->m_flMax; - - m_EdgeInfo[ 0 ] = src->m_EdgeInfo[ 0 ]; - m_EdgeInfo[ 1 ] = src->m_EdgeInfo[ 1 ]; - - m_pEvent = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CFlexAnimationTrack::~CFlexAnimationTrack( void ) -{ - delete[] m_pControllerName; - - for ( int t = 0; t < 2; t++ ) - { - m_Samples[ t ].Purge(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *event - -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::SetEvent( CChoreoEvent *event ) -{ - m_pEvent = event; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::Clear( void ) -{ - for ( int t = 0; t < 2; t++ ) - { - m_Samples[ t ].RemoveAll(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::RemoveSample( int index, int type /*=0*/ ) -{ - Assert( type == 0 || type == 1 ); - - m_Samples[ type ].Remove( index ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::SetFlexControllerName( const char *name ) -{ - delete[] m_pControllerName; - int len = Q_strlen( name ) + 1; - m_pControllerName = new char[ len ]; - Q_strncpy( m_pControllerName, name, len ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : char const -//----------------------------------------------------------------------------- -const char *CFlexAnimationTrack::GetFlexControllerName( void ) -{ - return m_pControllerName ? m_pControllerName : ""; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CFlexAnimationTrack::GetNumSamples( int type /*=0*/ ) -{ - Assert( type == 0 || type == 1 ); - - return m_Samples[ type ].Size(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -// Output : CExpressionSample -//----------------------------------------------------------------------------- -CExpressionSample *CFlexAnimationTrack::GetSample( int index, int type /*=0*/ ) -{ - Assert( type == 0 || type == 1 ); - - if ( index < 0 || index >= GetNumSamples( type ) ) - return NULL; - return &m_Samples[ type ][ index ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CFlexAnimationTrack::IsTrackActive( void ) -{ - return m_bActive; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : active - -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::SetTrackActive( bool active ) -{ - m_bActive = active; -} - -void CFlexAnimationTrack::SetEdgeInfo( bool leftEdge, int curveType, float zero ) -{ - int idx = leftEdge ? 0 : 1; - m_EdgeInfo[ idx ].m_CurveType = curveType; - m_EdgeInfo[ idx ].m_flZeroPos = zero; -} - -void CFlexAnimationTrack::GetEdgeInfo( bool leftEdge, int& curveType, float& zero ) const -{ - int idx = leftEdge ? 0 : 1; - curveType = m_EdgeInfo[ idx ].m_CurveType; - zero = m_EdgeInfo[ idx ].m_flZeroPos; -} - -void CFlexAnimationTrack::SetEdgeActive( bool leftEdge, bool state ) -{ - int idx = leftEdge ? 0 : 1; - m_EdgeInfo[ idx ].m_bActive = state; -} - -bool CFlexAnimationTrack::IsEdgeActive( bool leftEdge ) const -{ - int idx = leftEdge ? 0 : 1; - return m_EdgeInfo[ idx ].m_bActive; -} - -int CFlexAnimationTrack::GetEdgeCurveType( bool leftEdge ) const -{ - if ( !IsEdgeActive( leftEdge ) ) - { - return CURVE_DEFAULT; - } - - int idx = leftEdge ? 0 : 1; - return m_EdgeInfo[ idx ].m_CurveType; -} - -float CFlexAnimationTrack::GetEdgeZeroValue( bool leftEdge ) const -{ - if ( !IsEdgeActive( leftEdge ) ) - { - return 0.0f; - } - - int idx = leftEdge ? 0 : 1; - return m_EdgeInfo[ idx ].m_flZeroPos; -} - -float CFlexAnimationTrack::GetDefaultEdgeZeroPos() const -{ - float zero = 0.0f; - if ( m_flMin != m_flMax ) - { - zero = ( 0.0f - m_flMin ) / ( m_flMax - m_flMin ); - } - return zero; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CFlexAnimationTrack::GetZeroValue( int type, bool leftSide ) -{ - // Stereo track is always clamped to 0.5 and doesn't care about l/r settings - if ( type == 1 ) - { - return 0.5f; - } - - if ( IsEdgeActive( leftSide ) ) - { - return GetEdgeZeroValue( leftSide ); - } - - return GetDefaultEdgeZeroPos(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : number - -// Output : CExpressionSample -//----------------------------------------------------------------------------- -CExpressionSample *CFlexAnimationTrack::GetBoundedSample( int number, bool& bClamped, int type /*=0*/ ) -{ - Assert( type == 0 || type == 1 ); - - if ( number < 0 ) - { - // Search for two samples which span time f - static CExpressionSample nullstart; - nullstart.time = 0.0f; - nullstart.value = GetZeroValue( type, true ); - if ( type == 0 ) - { - nullstart.SetCurveType( GetEdgeCurveType( true ) ); - } - else - { - nullstart.SetCurveType( CURVE_DEFAULT ); - } - bClamped = true; - return &nullstart; - } - else if ( number >= GetNumSamples( type ) ) - { - static CExpressionSample nullend; - nullend.time = m_pEvent->GetDuration(); - nullend.value = GetZeroValue( type, false ); - if ( type == 0 ) - { - nullend.SetCurveType( GetEdgeCurveType( false ) ); - } - else - { - nullend.SetCurveType( CURVE_DEFAULT ); - } - bClamped = true; - return &nullend; - } - - bClamped = false; - return GetSample( number, type ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : time - -// type - -// Output : float -//----------------------------------------------------------------------------- -float CFlexAnimationTrack::GetIntensityInternal( float time, int type ) -{ - Assert( type == 0 || type == 1 ); - - float retval = 0.0f; - - // find samples that span the time - if ( !m_pEvent || !m_pEvent->HasEndTime() || time < m_pEvent->GetStartTime() ) - { - retval = GetZeroValue( type, true );; - } - else if ( time > m_pEvent->GetEndTime() ) - { - retval = GetZeroValue( type, false );; - } - else - { - float elapsed = time - m_pEvent->GetStartTime(); - retval = GetFracIntensity( elapsed, type ); - } - - // scale - if (type == 0 && m_flMin != m_flMax) - { - retval = retval * (m_flMax - m_flMin) + m_flMin; - } - return retval; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : time - -// type - -// Output : float -//----------------------------------------------------------------------------- -float CFlexAnimationTrack::GetFracIntensity( float time, int type ) -{ - float zeroValueLeft = GetZeroValue( type, true ); - - Assert( type == 0 || type == 1 ); - - // find samples that span the time - if ( !m_pEvent || !m_pEvent->HasEndTime() ) - return zeroValueLeft; - - int rampCount = GetNumSamples( type ); - if ( rampCount < 1 ) - { - return zeroValueLeft; - } - - CExpressionSample *esStart = NULL; - CExpressionSample *esEnd = NULL; - - // do binary search for sample in time period - int j = MAX( rampCount / 2, 1 ); - int i = j; - while ( i > -2 && i < rampCount + 1 ) - { - bool dummy; - esStart = GetBoundedSample( i, dummy, type ); - esEnd = GetBoundedSample( i + 1, dummy, type ); - - j = MAX( j / 2, 1 ); - if ( time < esStart->time) - { - i -= j; - } - else if ( time > esEnd->time) - { - i += j; - } - else - { - if ( time == esEnd->time ) - { - ++i; - esStart = GetBoundedSample( i, dummy, type ); - esEnd = GetBoundedSample( i + 1, dummy, type ); - } - break; - } - } - - if (!esStart) - { - return zeroValueLeft; - } - - int prev = i - 1; - int next = i + 2; - - prev = MAX( -1, prev ); - next = MIN( next, rampCount ); - - bool clamp[ 2 ]; - CExpressionSample *esPre = GetBoundedSample( prev, clamp[ 0 ], type ); - CExpressionSample *esNext = GetBoundedSample( next, clamp[ 1 ], type ); - - float dt = esEnd->time - esStart->time; - - Vector vPre( esPre->time, esPre->value, 0 ); - Vector vStart( esStart->time, esStart->value, 0 ); - Vector vEnd( esEnd->time, esEnd->value, 0 ); - Vector vNext( esNext->time, esNext->value, 0 ); - - float f2 = 0.0f; - if ( dt > 0.0f ) - { - f2 = ( time - esStart->time ) / ( dt ); - } - f2 = clamp( f2, 0.0f, 1.0f ); - - Vector vOut; - int dummy; - int earlypart, laterpart; - - // Not holding out value of previous curve... - Interpolator_CurveInterpolatorsForType( esStart->GetCurveType(), dummy, earlypart ); - Interpolator_CurveInterpolatorsForType( esEnd->GetCurveType(), laterpart, dummy ); - - if ( earlypart == INTERPOLATE_HOLD ) - { - // Hold "out" of previous sample (can cause a discontinuity) - VectorLerp( vStart, vEnd, f2, vOut ); - vOut.y = vStart.y; - } - else if ( laterpart == INTERPOLATE_HOLD ) - { - // Hold "out" of previous sample (can cause a discontinuity) - VectorLerp( vStart, vEnd, f2, vOut ); - vOut.y = vEnd.y; - } - else - { - bool sameCurveType = earlypart == laterpart ? true : false; - if ( sameCurveType ) - { - Interpolator_CurveInterpolate( laterpart, vPre, vStart, vEnd, vNext, f2, vOut ); - } - else // curves differ, sigh - { - Vector vOut1, vOut2; - - Interpolator_CurveInterpolate( earlypart, vPre, vStart, vEnd, vNext, f2, vOut1 ); - Interpolator_CurveInterpolate( laterpart, vPre, vStart, vEnd, vNext, f2, vOut2 ); - - VectorLerp( vOut1, vOut2, f2, vOut ); - } - } - - float retval = clamp( vOut.y, 0.0f, 1.0f ); - return retval; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : time - -// Output : float -//----------------------------------------------------------------------------- -float CFlexAnimationTrack::GetSampleIntensity( float time ) -{ - return GetIntensityInternal( time, 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : time - -// Output : float -//----------------------------------------------------------------------------- -float CFlexAnimationTrack::GetBalanceIntensity( float time ) -{ - if ( IsComboType() ) - { - return GetIntensityInternal( time, 1 ); - } - - return 1.0f; -} - -// For a given time, computes 0->1 intensity value for the slider -//----------------------------------------------------------------------------- -// Purpose: -// Input : time - -// Output : float -//----------------------------------------------------------------------------- -float CFlexAnimationTrack::GetIntensity( float time, int side ) -{ - float mag = GetSampleIntensity( time ); - - float scale = 1.0f; - - if ( IsComboType() ) - { - float balance = GetBalanceIntensity( time ); - - // Asking for left but balance is to right, then fall off as we go - // further right - if ( side == 0 && balance > 0.5f ) - { - scale = (1.0f - balance ) / 0.5f; - } - // Asking for right, but balance is left, fall off as we go left. - else if ( side == 1 && balance < 0.5f ) - { - scale = ( balance / 0.5f ); - } - } - - return mag * scale; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : time - -// value - -//----------------------------------------------------------------------------- -CExpressionSample *CFlexAnimationTrack::AddSample( float time, float value, int type /*=0*/ ) -{ - Assert( type == 0 || type == 1 ); - - CExpressionSample sample; - sample.time = time; - sample.value = value; - sample.selected = false; - - int idx = m_Samples[ type ].AddToTail( sample ); - - // Resort( type ); - return &m_Samples[ type ][ idx ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::Resort( int type /*=0*/ ) -{ - Assert( type == 0 || type == 1 ); - - for ( int i = 0; i < m_Samples[ type ].Size(); i++ ) - { - for ( int j = i + 1; j < m_Samples[ type ].Size(); j++ ) - { - CExpressionSample src = m_Samples[ type ][ i ]; - CExpressionSample dest = m_Samples[ type ][ j ]; - - if ( src.time > dest.time ) - { - m_Samples[ type ][ i ] = dest; - m_Samples[ type ][ j ] = src; - } - } - } - - // Make sure nothing is out of range - RemoveOutOfRangeSamples( 0 ); - RemoveOutOfRangeSamples( 1 ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoEvent -//----------------------------------------------------------------------------- -CChoreoEvent *CFlexAnimationTrack::GetEvent( void ) -{ - return m_pEvent; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : side - -// Output : int -//----------------------------------------------------------------------------- -int CFlexAnimationTrack::GetFlexControllerIndex( int side /*= 0*/ ) -{ - Assert( side == 0 || side == 1 ); - - if ( IsComboType() ) - { - return m_nFlexControllerIndex[ side ]; - } - - return m_nFlexControllerIndex[ 0 ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : side - -// Output : int -//----------------------------------------------------------------------------- -LocalFlexController_t CFlexAnimationTrack::GetRawFlexControllerIndex( int side /*= 0*/ ) -{ - Assert( side == 0 || side == 1 ); - - if ( IsComboType() ) - { - return m_nFlexControllerIndexRaw[ side ]; - } - - return m_nFlexControllerIndexRaw[ 0 ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -// side - -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::SetFlexControllerIndex( LocalFlexController_t raw, int index, int side /*= 0*/ ) -{ - Assert( side == 0 || side == 1 ); - - m_nFlexControllerIndex[ side ] = index; - // Model specific - m_nFlexControllerIndexRaw[ side ] = raw; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : combo - -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::SetComboType( bool combo ) -{ - m_bCombo = combo; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CFlexAnimationTrack::IsComboType( void ) -{ - return m_bCombo; -} - -//----------------------------------------------------------------------------- -// Purpose: True if this should be simulated on the server side always -// Input : state - -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::SetServerSide( bool state ) -{ - m_bServerSide = state; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CFlexAnimationTrack::IsServerSide() const -{ - return m_bServerSide; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::SetMin( float value ) -{ - m_flMin = value; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::SetMax( float value ) -{ - m_flMax = value; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CFlexAnimationTrack::GetMin( int type ) -{ - if (type == 0) - return m_flMin; - else - return 0.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CFlexAnimationTrack::GetMax( int type ) -{ - if (type == 0) - return m_flMax; - else - return 1.0f; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CFlexAnimationTrack::IsInverted( void ) -{ - if (m_bInverted) - return true; - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::SetInverted( bool isInverted ) -{ - m_bInverted = isInverted; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -void CFlexAnimationTrack::RemoveOutOfRangeSamples( int type ) -{ - Assert( m_pEvent ); - if ( !m_pEvent ) - return; - - Assert( m_pEvent->HasEndTime() ); - float duration = m_pEvent->GetDuration(); - - int c = m_Samples[ type ].Size(); - for ( int i = c-1; i >= 0; i-- ) - { - CExpressionSample src = m_Samples[ type ][ i ]; - if ( src.time < 0 || - src.time > duration ) - { - m_Samples[ type ].Remove( i ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CChoreoEvent::CChoreoEvent( CChoreoScene *scene ) -{ - Init( scene ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// *name - -//----------------------------------------------------------------------------- -CChoreoEvent::CChoreoEvent( CChoreoScene *scene, EVENTTYPE type, const char *name ) -{ - Init( scene ); - SetType( type ); - SetName( name ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// *name - -// *param - -//----------------------------------------------------------------------------- -CChoreoEvent::CChoreoEvent( CChoreoScene *scene, EVENTTYPE type, const char *name, const char *param ) -{ - Init( scene ); - SetType( type ); - SetName( name ); - SetParameters( param ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CChoreoEvent::~CChoreoEvent( void ) -{ - RemoveAllTracks(); - ClearEventDependencies(); - delete m_pSubScene; -} - -//----------------------------------------------------------------------------- -// Purpose: Assignment -// Input : src - -// Output : CChoreoEvent& -//----------------------------------------------------------------------------- -CChoreoEvent& CChoreoEvent::operator=( const CChoreoEvent& src ) -{ - MEM_ALLOC_CREDIT(); - - // Copy global id when copying entity - m_nGlobalID = src.m_nGlobalID; - - m_pActor = NULL; - m_pChannel = NULL; - - m_nDefaultCurveType = src.m_nDefaultCurveType; - m_fType = src.m_fType; - m_Name = src.m_Name; - m_Parameters = src.m_Parameters; - m_Parameters2= src.m_Parameters2; - m_Parameters3= src.m_Parameters3; - m_flStartTime = src.m_flStartTime; - m_flEndTime = src.m_flEndTime; - - m_bFixedLength = src.m_bFixedLength; - m_flGestureSequenceDuration = src.m_flGestureSequenceDuration; - m_bResumeCondition = src.m_bResumeCondition; - m_bLockBodyFacing = src.m_bLockBodyFacing; - m_flDistanceToTarget = src.m_flDistanceToTarget; - m_bForceShortMovement = src.m_bForceShortMovement; - m_bSyncToFollowingGesture = src.m_bSyncToFollowingGesture; - m_bPlayOverScript = src.m_bPlayOverScript; - m_bUsesTag = src.m_bUsesTag; - m_TagName = src.m_TagName; - m_TagWavName = src.m_TagWavName; - - ClearAllRelativeTags(); - ClearAllTimingTags(); - int t; - for ( t = 0; t < NUM_ABS_TAG_TYPES; t++ ) - { - ClearAllAbsoluteTags( (AbsTagType)t ); - } - - int i; - for ( i = 0; i < src.m_RelativeTags.Size(); i++ ) - { - CEventRelativeTag newtag( src.m_RelativeTags[ i ] ); - newtag.SetOwner( this ); - m_RelativeTags.AddToTail( newtag ); - } - - for ( i = 0; i < src.m_TimingTags.Size(); i++ ) - { - CFlexTimingTag newtag( src.m_TimingTags[ i ] ); - newtag.SetOwner( this ); - m_TimingTags.AddToTail( newtag ); - } - for ( t = 0; t < NUM_ABS_TAG_TYPES; t++ ) - { - for ( i = 0; i < src.m_AbsoluteTags[ t ].Size(); i++ ) - { - CEventAbsoluteTag newtag( src.m_AbsoluteTags[ t ][ i ] ); - newtag.SetOwner( this ); - m_AbsoluteTags[ t ].AddToTail( newtag ); - } - } - - RemoveAllTracks(); - - for ( i = 0 ; i < src.m_FlexAnimationTracks.Size(); i++ ) - { - CFlexAnimationTrack *newtrack = new CFlexAnimationTrack( src.m_FlexAnimationTracks[ i ] ); - newtrack->SetEvent( this ); - m_FlexAnimationTracks.AddToTail( newtrack ); - } - - m_bTrackLookupSet = src.m_bTrackLookupSet; - - // FIXME: Use a safe handle? - //m_pSubScene = src.m_pSubScene; - - m_bProcessing = src.m_bProcessing; - m_pMixer = src.m_pMixer; - - m_pScene = src.m_pScene; - - m_nPitch = src.m_nPitch; - m_nYaw = src.m_nYaw; - - m_nNumLoops = src.m_nNumLoops; - m_nLoopsRemaining = src.m_nLoopsRemaining; - - // Copy ramp over - m_Ramp = src.m_Ramp; - - m_ccType = src.m_ccType; - m_CCToken = src.m_CCToken; - m_bUsingCombinedSoundFile = src.m_bUsingCombinedSoundFile; - m_uRequiredCombinedChecksum = src.m_uRequiredCombinedChecksum; - m_nNumSlaves = src.m_nNumSlaves; - m_flLastSlaveEndTime = src.m_flLastSlaveEndTime; - m_bCCTokenValid = src.m_bCCTokenValid; - m_bCombinedUsingGenderToken = src.m_bCombinedUsingGenderToken; - - m_bSuppressCaptionAttenuation = src.m_bSuppressCaptionAttenuation; - - m_bActive = src.m_bActive; - - return *this; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoEvent::Init( CChoreoScene *scene ) -{ - m_nGlobalID = s_nGlobalID++; - m_nDefaultCurveType = CURVE_CATMULL_ROM_TO_CATMULL_ROM; - m_fType = UNSPECIFIED; - m_Name.Set(""); - m_Parameters.Set(""); - m_Parameters2.Set(""); - m_Parameters3.Set(""); - - m_flStartTime = 0.0f; - m_flEndTime = -1.0f; - - m_pActor = NULL; - m_pChannel = NULL; - m_pScene = scene; - - m_bFixedLength = false; - m_bResumeCondition = false; - SetUsingRelativeTag( false, 0, 0 ); - - m_bTrackLookupSet = false; - - m_bLockBodyFacing = false; - m_flDistanceToTarget = 0.0f; - m_bForceShortMovement = false; - m_bSyncToFollowingGesture = false; - m_bPlayOverScript = false; - - m_pSubScene = NULL; - m_bProcessing = false; - m_pMixer = NULL; - m_flGestureSequenceDuration = 0.0f; - - m_nPitch = m_nYaw = 0; - - m_nNumLoops = -1; - m_nLoopsRemaining = 0; - - // Close captioning/localization support - m_CCToken.Set(""); - m_ccType = CC_MASTER; - m_bUsingCombinedSoundFile = false; - m_uRequiredCombinedChecksum = 0; - m_nNumSlaves = 0; - m_flLastSlaveEndTime = 0.0f; - m_bCCTokenValid = false; - m_bCombinedUsingGenderToken = false; - m_bSuppressCaptionAttenuation = false; - m_bActive = true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -CChoreoEvent::EVENTTYPE CChoreoEvent::GetType( void ) -{ - return (EVENTTYPE)m_fType; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetType( EVENTTYPE type ) -{ - m_fType = type; - - if ( m_fType == SPEAK || - m_fType == SUBSCENE ) - { - m_bFixedLength = true; - } - else - { - m_bFixedLength = false; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetName( const char *name ) -{ - m_Name = name; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CChoreoEvent::GetName( void ) -{ - return m_Name.Get(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *param - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetParameters( const char *param ) -{ - m_Parameters = param; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CChoreoEvent::GetParameters( void ) -{ - return m_Parameters.Get(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *param - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetParameters2( const char *param ) -{ - int iLength = Q_strlen( param ); - m_Parameters2 = param; - - // HACK: Remove trailing " " until faceposer is fixed - if ( iLength > 0 ) - { - if ( param[iLength-1] == ' ' ) - { - char tmp[1024]; - Q_strncpy( tmp, param, sizeof(tmp) ); - tmp[iLength-1] = 0; - m_Parameters2.Set(tmp); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CChoreoEvent::GetParameters2( void ) -{ - return m_Parameters2.Get(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *param - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetParameters3( const char *param ) -{ - int iLength = Q_strlen( param ); - m_Parameters3 = param; - - // HACK: Remove trailing " " until faceposer is fixed - if ( iLength > 0 ) - { - if ( param[iLength-1] == ' ' ) - { - char tmp[1024]; - Q_strncpy( tmp, param, sizeof(tmp) ); - tmp[iLength-1] = 0; - m_Parameters3.Set(tmp); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CChoreoEvent::GetParameters3( void ) -{ - return m_Parameters3.Get(); -} - -//----------------------------------------------------------------------------- -// Purpose: debugging description -// Output : const char -//----------------------------------------------------------------------------- -const char *CChoreoEvent::GetDescription( void ) -{ - static char description[ 256 ]; - - description[ 0 ] = 0; - - if ( !GetActor() ) - { - Q_snprintf( description,sizeof(description), "global %s", m_Name.Get() ); - } - else - { - Assert( m_pChannel ); - Q_snprintf( description,sizeof(description), "%s : %s : %s -- %s \"%s\"", m_pActor->GetName(), m_pChannel->GetName(), GetName(), NameForType( GetType() ), GetParameters() ); - if ( GetType() == EXPRESSION ) - { - char sz[ 256 ]; - - Q_snprintf( sz,sizeof(sz), " \"%s\"", GetParameters2() ); - Q_strncat( description, sz, sizeof(description), COPY_ALL_CHARACTERS ); - } - } - - return description; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : starttime - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetStartTime( float starttime ) -{ - m_flStartTime = starttime; - if ( m_flEndTime != -1.0f ) - { - if ( m_flEndTime < m_flStartTime ) - { - m_flEndTime = m_flStartTime; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CChoreoEvent::GetStartTime( ) -{ - return m_flStartTime; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : endtime - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetEndTime( float endtime ) -{ - bool changed = m_flEndTime != endtime; - - m_flEndTime = endtime; - - if ( endtime != -1.0f ) - { - if ( m_flEndTime < m_flStartTime ) - { - m_flEndTime = m_flStartTime; - } - - if ( changed ) - { - OnEndTimeChanged(); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CChoreoEvent::GetEndTime( ) -{ - return m_flEndTime; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChoreoEvent::HasEndTime( void ) -{ - return m_flEndTime != -1.0f ? true : false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CChoreoEvent::GetCompletion( float time ) -{ - float t = (time - GetStartTime()) / (GetEndTime() - GetStartTime()); - - if (t < 0.0f) - return 0.0f; - else if (t > 1.0f) - return 1.0f; - - return t; -} - -// ICurveDataAccessor method -bool CChoreoEvent::CurveHasEndTime() -{ - return HasEndTime(); -} - -//----------------------------------------------------------------------------- -// Default curve type -//----------------------------------------------------------------------------- -void CChoreoEvent::SetDefaultCurveType( int nCurveType ) -{ - m_nDefaultCurveType = nCurveType; -} - -int CChoreoEvent::GetDefaultCurveType() -{ - return m_nDefaultCurveType; -} - -float CCurveData::GetIntensity( ICurveDataAccessor *data, float time ) -{ - float zeroValue = 0.0f; - - // find samples that span the time - if ( !data->CurveHasEndTime() ) - { - return zeroValue; - } - - int rampCount = GetCount(); - if ( rampCount < 1 ) - { - // Full intensity - return 1.0f; - } - - CExpressionSample *esStart = NULL; - CExpressionSample *esEnd = NULL; - - // do binary search for sample in time period - int j = MAX( rampCount / 2, 1 ); - int i = j; - while ( i > -2 && i < rampCount + 1 ) - { - bool dummy; - esStart = GetBoundedSample( data, i, dummy ); - esEnd = GetBoundedSample( data, i + 1, dummy ); - - j = MAX( j / 2, 1 ); - if ( time < esStart->time) - { - i -= j; - } - else if ( time > esEnd->time) - { - i += j; - } - else - { - break; - } - } - - if (!esStart) - { - return 1.0f; - } - - int prev = i - 1; - int next = i + 2; - - prev = MAX( -1, prev ); - next = MIN( next, rampCount ); - - bool clamp[ 2 ]; - CExpressionSample *esPre = GetBoundedSample( data, prev, clamp[ 0 ] ); - CExpressionSample *esNext = GetBoundedSample( data, next, clamp[ 1 ] ); - - float dt = esEnd->time - esStart->time; - - Vector vPre( esPre->time, esPre->value, 0 ); - Vector vStart( esStart->time, esStart->value, 0 ); - Vector vEnd( esEnd->time, esEnd->value, 0 ); - Vector vNext( esNext->time, esNext->value, 0 ); - - if ( clamp[ 0 ] ) - { - vPre.x = vStart.x; - } - - if ( clamp[ 1 ] ) - { - vNext.x = vEnd.x; - } - - float f2 = 0.0f; - if ( dt > 0.0f ) - { - f2 = ( time - esStart->time ) / ( dt ); - } - f2 = clamp( f2, 0.0f, 1.0f ); - - Vector vOut; - int dummy; - int earlypart, laterpart; - - int startCurve = esStart->GetCurveType(); - int endCurve = esEnd->GetCurveType(); - - if ( startCurve == CURVE_DEFAULT ) - { - startCurve = data->GetDefaultCurveType(); - } - if ( endCurve == CURVE_DEFAULT ) - { - endCurve = data->GetDefaultCurveType(); - } - - // Not holding out value of previous curve... - Interpolator_CurveInterpolatorsForType( startCurve, dummy, earlypart ); - Interpolator_CurveInterpolatorsForType( endCurve, laterpart, dummy ); - - if ( earlypart == INTERPOLATE_HOLD ) - { - // Hold "out" of previous sample (can cause a discontinuity) - VectorLerp( vStart, vEnd, f2, vOut ); - vOut.y = vStart.y; - } - else if ( laterpart == INTERPOLATE_HOLD ) - { - // Hold "out" of previous sample (can cause a discontinuity) - VectorLerp( vStart, vEnd, f2, vOut ); - vOut.y = vEnd.y; - } - else - { - bool sameCurveType = earlypart == laterpart ? true : false; - if ( sameCurveType ) - { - Interpolator_CurveInterpolate( laterpart, vPre, vStart, vEnd, vNext, f2, vOut ); - } - else // curves differ, sigh - { - Vector vOut1, vOut2; - - Interpolator_CurveInterpolate( earlypart, vPre, vStart, vEnd, vNext, f2, vOut1 ); - Interpolator_CurveInterpolate( laterpart, vPre, vStart, vEnd, vNext, f2, vOut2 ); - - VectorLerp( vOut1, vOut2, f2, vOut ); - } - } - - float retval = clamp( vOut.y, 0.0f, 1.0f ); - return retval; -} - -//----------------------------------------------------------------------------- -// Purpose: Get intensity for event, bounded by scene global intensity -// Output : float -//----------------------------------------------------------------------------- -float CChoreoEvent::GetIntensity( float scenetime ) -{ - float global_intensity = 1.0f; - if ( m_pScene ) - { - global_intensity = m_pScene->GetSceneRampIntensity( scenetime ); - } - else - { - Assert( 0 ); - } - - float event_intensity = _GetIntensity( scenetime ); - - return global_intensity * event_intensity; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CChoreoEvent::_GetIntensity( float scenetime ) -{ - // Convert to event local time - float time = scenetime - GetStartTime(); - return m_Ramp.GetIntensity( this, time ); -} - - -float CChoreoEvent::GetIntensityArea( float scenetime ) -{ - // Convert to event local time - float time = scenetime - GetStartTime(); - return m_Ramp.GetIntensityArea( this, time ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CCurveData::GetIntensityArea( ICurveDataAccessor *data, float time ) -{ - float zeroValue = 0.0f; - - // find samples that span the time - if ( !data->CurveHasEndTime() ) - { - return zeroValue; - } - - int rampCount = GetCount(); - if ( rampCount < 1 ) - { - // Full intensity - return 1.0f; - } - - CExpressionSample *esStart = NULL; - CExpressionSample *esEnd = NULL; - - // do binary search for sample in time period - int j = MAX( rampCount / 2, 1 ); - int i = j; - while ( i > -2 && i < rampCount + 1 ) - { - bool dummy; - esStart = GetBoundedSample( data, i, dummy ); - esEnd = GetBoundedSample( data, i + 1, dummy ); - - j = MAX( j / 2, 1 ); - if ( time < esStart->time) - { - i -= j; - } - else if ( time > esEnd->time) - { - i += j; - } - else - { - break; - } - } - - UpdateIntensityArea( data ); - - float flTotal = 0.0f; - flTotal = m_RampAccumulator[i+1]; - - int prev = i - 1; - int next = i + 2; - - prev = MAX( -1, prev ); - next = MIN( next, rampCount ); - - bool clamp[ 2 ]; - CExpressionSample *esPre = GetBoundedSample( data, prev, clamp[ 0 ] ); - CExpressionSample *esNext = GetBoundedSample( data, next, clamp[ 1 ] ); - - float dt = esEnd->time - esStart->time; - - Vector vPre( esPre->time, esPre->value, 0 ); - Vector vStart( esStart->time, esStart->value, 0 ); - Vector vEnd( esEnd->time, esEnd->value, 0 ); - Vector vNext( esNext->time, esNext->value, 0 ); - - if ( clamp[ 0 ] ) - { - vPre.x = vStart.x; - } - - if ( clamp[ 1 ] ) - { - vNext.x = vEnd.x; - } - - float f2 = 0.0f; - if ( dt > 0.0f ) - { - f2 = ( time - esStart->time ) / ( dt ); - } - f2 = clamp( f2, 0.0f, 1.0f ); - - Vector vOut; - int dummy; - int earlypart, laterpart; - - int startCurve = esStart->GetCurveType(); - int endCurve = esEnd->GetCurveType(); - - if ( startCurve == CURVE_DEFAULT ) - { - startCurve = data->GetDefaultCurveType(); - } - if ( endCurve == CURVE_DEFAULT ) - { - endCurve = data->GetDefaultCurveType(); - } - - // Not holding out value of previous curve... - Interpolator_CurveInterpolatorsForType( startCurve, dummy, earlypart ); - Interpolator_CurveInterpolatorsForType( endCurve, laterpart, dummy ); - - // FIXME: needs other curve types - Catmull_Rom_Spline_Integral_Normalize( - vPre, - vStart, - vEnd, - vNext, - f2, - vOut ); - - // Con_Printf( "Accum %f : Partial %f\n", flTotal, vOut.y * (vEnd.x - vStart.x) * f2 ); - flTotal = flTotal + clamp( vOut.y, 0.0f, 1.0f ) * (vEnd.x - vStart.x); - return flTotal; -} - - -void CCurveData::UpdateIntensityArea( ICurveDataAccessor *data ) -{ - int rampCount = GetCount();; - if ( rampCount < 1 ) - { - return; - } - - if (m_RampAccumulator.Count() == rampCount + 2) - { - return; - } - - m_RampAccumulator.SetCount( rampCount + 2 ); - - int i = -1; - - bool dummy; - CExpressionSample *esPre = GetBoundedSample( data, i - 1, dummy ); - CExpressionSample *esStart = GetBoundedSample( data, i, dummy ); - CExpressionSample *esEnd = GetBoundedSample( data, MIN( i + 1, rampCount ), dummy ); - - Vector vPre( esPre->time, esPre->value, 0 ); - Vector vStart( esStart->time, esStart->value, 0 ); - Vector vEnd( esEnd->time, esEnd->value, 0 ); - - Vector vOut; - for (i = -1; i < rampCount; i++) - { - CExpressionSample *esNext = GetBoundedSample( data, MIN( i + 2, rampCount ), dummy ); - Vector vNext( esNext->time, esNext->value, 0 ); - - Catmull_Rom_Spline_Integral_Normalize( - vPre, - vStart, - vEnd, - vNext, - 1.0f, - vOut ); - - m_RampAccumulator[i+1] = clamp( vOut.y, 0.0f, 1.0f ) * (vEnd.x - vStart.x); - - vPre = vStart; - vStart = vEnd; - vEnd = vNext; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : dt - -//----------------------------------------------------------------------------- -void CChoreoEvent::OffsetStartTime( float dt ) -{ - SetStartTime( GetStartTime() + dt ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : dt - -//----------------------------------------------------------------------------- -void CChoreoEvent::OffsetEndTime( float dt ) -{ - if ( HasEndTime() ) - { - SetEndTime( GetEndTime() + dt ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : dt - -//----------------------------------------------------------------------------- -void CChoreoEvent::OffsetTime( float dt ) -{ - if ( HasEndTime() ) - { - m_flEndTime += dt; - } - m_flStartTime += dt; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetActor( CChoreoActor *actor ) -{ - m_pActor = actor; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoActor -//----------------------------------------------------------------------------- -CChoreoActor *CChoreoEvent::GetActor( void ) -{ - return m_pActor; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *channel - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetChannel( CChoreoChannel *channel ) -{ - m_pChannel = channel; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoChannel -//----------------------------------------------------------------------------- -CChoreoChannel *CChoreoEvent::GetChannel( void ) -{ - return m_pChannel; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *scene - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetSubScene( CChoreoScene *scene ) -{ - m_pSubScene = scene; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoScene -//----------------------------------------------------------------------------- -CChoreoScene *CChoreoEvent::GetSubScene( void ) -{ - return m_pSubScene; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -struct EventNameMap_t -{ - CChoreoEvent::EVENTTYPE type; - char const *name; -}; - -static EventNameMap_t g_NameMap[] = -{ - { CChoreoEvent::UNSPECIFIED, "unspecified" }, // error condition!!! - { CChoreoEvent::SECTION, "section" }, - { CChoreoEvent::EXPRESSION, "expression" }, - { CChoreoEvent::LOOKAT, "lookat" }, - { CChoreoEvent::MOVETO, "moveto" }, - { CChoreoEvent::SPEAK, "speak" }, - { CChoreoEvent::GESTURE, "gesture" }, - { CChoreoEvent::SEQUENCE, "sequence" }, - { CChoreoEvent::FACE, "face" }, - { CChoreoEvent::FIRETRIGGER, "firetrigger" }, - { CChoreoEvent::FLEXANIMATION, "flexanimation" }, - { CChoreoEvent::SUBSCENE, "subscene" }, - { CChoreoEvent::LOOP, "loop" }, - { CChoreoEvent::INTERRUPT, "interrupt" }, - { CChoreoEvent::STOPPOINT, "stoppoint" }, - { CChoreoEvent::PERMIT_RESPONSES, "permitresponses" }, - { CChoreoEvent::GENERIC, "generic" }, -}; - -//----------------------------------------------------------------------------- -// Purpose: A simple class to verify the names data above at runtime -//----------------------------------------------------------------------------- -class CCheckEventNames -{ -public: - CCheckEventNames() - { - if ( ARRAYSIZE( g_NameMap ) != CChoreoEvent::NUM_TYPES ) - { - Error( "g_NameMap contains %i entries, CChoreoEvent::NUM_TYPES == %i!", - ARRAYSIZE( g_NameMap ), CChoreoEvent::NUM_TYPES ); - } - for ( int i = 0; i < CChoreoEvent::NUM_TYPES; ++i ) - { - if ( !g_NameMap[ i ].name ) - { - Error( "g_NameMap: Event type at %i has NULL name string!", i ); - } - - if ( (CChoreoEvent::EVENTTYPE)(i) == g_NameMap[ i ].type ) - continue; - - Error( "g_NameMap: Event type at %i has wrong value (%i)!", - i, (int)g_NameMap[ i ].type ); - } - } -}; -static CCheckEventNames g_CheckNamesSingleton; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -// Output : int -//----------------------------------------------------------------------------- -CChoreoEvent::EVENTTYPE CChoreoEvent::TypeForName( const char *name ) -{ - for ( int i = 0; i < NUM_TYPES; ++i ) - { - EventNameMap_t *slot = &g_NameMap[ i ]; - if ( !Q_stricmp( name, slot->name ) ) - return slot->type; - } - - Assert( !"CChoreoEvent::TypeForName failed!!!" ); - return UNSPECIFIED; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// Output : const char -//----------------------------------------------------------------------------- -const char *CChoreoEvent::NameForType( EVENTTYPE type ) -{ - int i = (int)type; - if ( i < 0 || i >= NUM_TYPES ) - { - Assert( "!CChoreoEvent::NameForType: bogus type!" ); - // returns "unspecified!!!"; - return g_NameMap[ 0 ].name; - } - - return g_NameMap[ i ].name; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -struct CCNameMap_t -{ - CChoreoEvent::CLOSECAPTION type; - char const *name; -}; - -static CCNameMap_t g_CCNameMap[] = -{ - { CChoreoEvent::CC_MASTER, "cc_master" }, // error condition!!! - { CChoreoEvent::CC_SLAVE, "cc_slave" }, - { CChoreoEvent::CC_DISABLED, "cc_disabled" }, -}; - -//----------------------------------------------------------------------------- -// Purpose: A simple class to verify the names data above at runtime -//----------------------------------------------------------------------------- -class CCheckCCNames -{ -public: - CCheckCCNames() - { - if ( ARRAYSIZE( g_CCNameMap ) != CChoreoEvent::NUM_CC_TYPES ) - { - Error( "g_CCNameMap contains %i entries, CChoreoEvent::NUM_CC_TYPES == %i!", - ARRAYSIZE( g_CCNameMap ), CChoreoEvent::NUM_CC_TYPES ); - } - for ( int i = 0; i < CChoreoEvent::NUM_CC_TYPES; ++i ) - { - if ( !g_CCNameMap[ i ].name ) - { - Error( "g_NameMap: CC type at %i has NULL name string!", i ); - } - - if ( (CChoreoEvent::CLOSECAPTION)(i) == g_CCNameMap[ i ].type ) - continue; - - Error( "g_CCNameMap: Event type at %i has wrong value (%i)!", - i, (int)g_CCNameMap[ i ].type ); - } - } -}; -static CCheckCCNames g_CheckCCNamesSingleton; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -// Output : CLOSECAPTION -//----------------------------------------------------------------------------- -CChoreoEvent::CLOSECAPTION CChoreoEvent::CCTypeForName( const char *name ) -{ - for ( int i = 0; i < NUM_CC_TYPES; ++i ) - { - CCNameMap_t *slot = &g_CCNameMap[ i ]; - if ( !Q_stricmp( name, slot->name ) ) - return slot->type; - } - - Assert( !"CChoreoEvent::TypeForName failed!!!" ); - return CC_MASTER; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// Output : const char -//----------------------------------------------------------------------------- -const char *CChoreoEvent::NameForCCType( CLOSECAPTION type ) -{ - int i = (int)type; - if ( i < 0 || i >= NUM_CC_TYPES ) - { - Assert( "!CChoreoEvent::NameForType: bogus type!" ); - // returns "unspecified!!!"; - return g_CCNameMap[ 0 ].name; - } - - return g_CCNameMap[ i ].name; -} - -//----------------------------------------------------------------------------- -// Purpose: Is the event something that can be sized ( a wave file, e.g. ) -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChoreoEvent::IsFixedLength( void ) -{ - return m_bFixedLength; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : isfixedlength - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetFixedLength( bool isfixedlength ) -{ - m_bFixedLength = isfixedlength; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : resumecondition - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetResumeCondition( bool resumecondition ) -{ - m_bResumeCondition = resumecondition; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChoreoEvent::IsResumeCondition( void ) -{ - return m_bResumeCondition; -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : lockbodyfacing - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetLockBodyFacing( bool lockbodyfacing ) -{ - m_bLockBodyFacing = lockbodyfacing; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChoreoEvent::IsLockBodyFacing( void ) -{ - return m_bLockBodyFacing; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : distancetotarget - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetDistanceToTarget( float distancetotarget ) -{ - m_flDistanceToTarget = distancetotarget; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns ideal distance to target -//----------------------------------------------------------------------------- -float CChoreoEvent::GetDistanceToTarget( void ) -{ - return m_flDistanceToTarget; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : set if small (sub-1/2 bbox) movements are forced -//----------------------------------------------------------------------------- - -void CChoreoEvent::SetForceShortMovement( bool bForceShortMovement ) -{ - m_bForceShortMovement = bForceShortMovement; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : get if small (sub-1/2 bbox) movements are forced -//----------------------------------------------------------------------------- - -bool CChoreoEvent::GetForceShortMovement( void ) -{ - return m_bForceShortMovement; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : set if the gesture should sync its exit tag with the following gestures entry tag -//----------------------------------------------------------------------------- - -void CChoreoEvent::SetSyncToFollowingGesture( bool bSyncToFollowingGesture ) -{ - m_bSyncToFollowingGesture = bSyncToFollowingGesture; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : get if the gesture should sync its exit tag with the following gestures entry tag -//----------------------------------------------------------------------------- - -bool CChoreoEvent::GetSyncToFollowingGesture( void ) -{ - return m_bSyncToFollowingGesture; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : set if the sequence should player overtop of an underlying SS -//----------------------------------------------------------------------------- - -void CChoreoEvent::SetPlayOverScript( bool bPlayOverScript ) -{ - m_bPlayOverScript = bPlayOverScript; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : get if the sequence should player overtop of an underlying SS -//----------------------------------------------------------------------------- - -bool CChoreoEvent::GetPlayOverScript( void ) -{ - return m_bPlayOverScript; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CChoreoEvent::GetDuration( void ) -{ - if ( HasEndTime() ) - { - return GetEndTime() - GetStartTime(); - } - - return 0.0f; -} - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoEvent::ClearAllRelativeTags( void ) -{ - m_RelativeTags.Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CChoreoEvent::GetNumRelativeTags( void ) -{ - return m_RelativeTags.Size(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : tagnum - -// Output : CEventRelativeTag -//----------------------------------------------------------------------------- -CEventRelativeTag *CChoreoEvent::GetRelativeTag( int tagnum ) -{ - Assert( tagnum >= 0 && tagnum < m_RelativeTags.Size() ); - return &m_RelativeTags[ tagnum ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *tagname - -// percentage - -//----------------------------------------------------------------------------- -void CChoreoEvent::AddRelativeTag( const char *tagname, float percentage ) -{ - CEventRelativeTag rt( this, tagname, percentage ); - m_RelativeTags.AddToTail( rt ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *tagname - -//----------------------------------------------------------------------------- -void CChoreoEvent::RemoveRelativeTag( const char *tagname ) -{ - for ( int i = 0; i < m_RelativeTags.Size(); i++ ) - { - CEventRelativeTag *prt = &m_RelativeTags[ i ]; - if ( !prt ) - continue; - - if ( !stricmp( prt->GetName(), tagname ) ) - { - m_RelativeTags.Remove( i ); - return; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *tagname - -// Output : CEventRelativeTag * -//----------------------------------------------------------------------------- -CEventRelativeTag * CChoreoEvent::FindRelativeTag( const char *tagname ) -{ - for ( int i = 0; i < m_RelativeTags.Size(); i++ ) - { - CEventRelativeTag *prt = &m_RelativeTags[ i ]; - if ( !prt ) - continue; - - if ( !stricmp( prt->GetName(), tagname ) ) - { - return prt; - } - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChoreoEvent::IsUsingRelativeTag( void ) -{ - return m_bUsesTag; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : usetag - -// 0 - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetUsingRelativeTag( bool usetag, const char *tagname /*= 0*/, - const char *wavname /* = 0 */ ) -{ - m_bUsesTag = usetag; - if ( tagname ) - { - m_TagName = tagname; - } - else - { - m_TagName.Set(""); - } - if ( wavname ) - { - m_TagWavName = wavname; - } - else - { - m_TagWavName.Set(""); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CChoreoEvent::GetRelativeTagName( void ) -{ - return m_TagName.Get(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CChoreoEvent::GetRelativeWavName( void ) -{ - return m_TagWavName.Get(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoEvent::ClearAllTimingTags( void ) -{ - m_TimingTags.Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CChoreoEvent::GetNumTimingTags( void ) -{ - return m_TimingTags.Size(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : tagnum - -// Output : CEventRelativeTag -//----------------------------------------------------------------------------- -CFlexTimingTag *CChoreoEvent::GetTimingTag( int tagnum ) -{ - Assert( tagnum >= 0 && tagnum < m_TimingTags.Size() ); - return &m_TimingTags[ tagnum ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *tagname - -// percentage - -//----------------------------------------------------------------------------- -void CChoreoEvent::AddTimingTag( const char *tagname, float percentage, bool locked ) -{ - CFlexTimingTag tt( this, tagname, percentage, locked ); - m_TimingTags.AddToTail( tt ); - - // Sort tags - CFlexTimingTag temp( (CChoreoEvent *)0x1, "", 0.0f, false ); - - // ugly bubble sort - for ( int i = 0; i < m_TimingTags.Size(); i++ ) - { - for ( int j = i + 1; j < m_TimingTags.Size(); j++ ) - { - CFlexTimingTag *t1 = &m_TimingTags[ i ]; - CFlexTimingTag *t2 = &m_TimingTags[ j ]; - - if ( t1->GetPercentage() > t2->GetPercentage() ) - { - temp = *t1; - *t1 = *t2; - *t2 = temp; - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *tagname - -//----------------------------------------------------------------------------- -void CChoreoEvent::RemoveTimingTag( const char *tagname ) -{ - for ( int i = 0; i < m_TimingTags.Size(); i++ ) - { - CFlexTimingTag *ptt = &m_TimingTags[ i ]; - if ( !ptt ) - continue; - - if ( !stricmp( ptt->GetName(), tagname ) ) - { - m_TimingTags.Remove( i ); - return; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *tagname - -// Output : CEventRelativeTag * -//----------------------------------------------------------------------------- -CFlexTimingTag * CChoreoEvent::FindTimingTag( const char *tagname ) -{ - for ( int i = 0; i < m_TimingTags.Size(); i++ ) - { - CFlexTimingTag *ptt = &m_TimingTags[ i ]; - if ( !ptt ) - continue; - - if ( !stricmp( ptt->GetName(), tagname ) ) - { - return ptt; - } - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoEvent::OnEndTimeChanged( void ) -{ - int c = GetNumFlexAnimationTracks(); - for ( int i = 0; i < c; i++ ) - { - CFlexAnimationTrack *track = GetFlexAnimationTrack( i ); - Assert( track ); - if ( !track ) - continue; - - track->Resort( 0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CChoreoEvent::GetNumFlexAnimationTracks( void ) -{ - return m_FlexAnimationTracks.Size(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -// Output : CFlexAnimationTrack -//----------------------------------------------------------------------------- -CFlexAnimationTrack *CChoreoEvent::GetFlexAnimationTrack( int index ) -{ - if ( index < 0 || index >= GetNumFlexAnimationTracks() ) - return NULL; - return m_FlexAnimationTracks[ index ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *controllername - -// Output : CFlexAnimationTrack -//----------------------------------------------------------------------------- -CFlexAnimationTrack *CChoreoEvent::AddTrack( const char *controllername ) -{ - CFlexAnimationTrack *newTrack = new CFlexAnimationTrack( this ); - newTrack->SetFlexControllerName( controllername ); - - m_FlexAnimationTracks.AddToTail( newTrack ); - - return newTrack; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -//----------------------------------------------------------------------------- -void CChoreoEvent::RemoveTrack( int index ) -{ - CFlexAnimationTrack *track = GetFlexAnimationTrack( index ); - if ( !track ) - return; - - m_FlexAnimationTracks.Remove( index ); - delete track; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoEvent::RemoveAllTracks( void ) -{ - while ( GetNumFlexAnimationTracks() > 0 ) - { - RemoveTrack( 0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *controllername - -// Output : CFlexAnimationTrack -//----------------------------------------------------------------------------- -CFlexAnimationTrack *CChoreoEvent::FindTrack( const char *controllername ) -{ - for ( int i = 0; i < GetNumFlexAnimationTracks(); i++ ) - { - CFlexAnimationTrack *t = GetFlexAnimationTrack( i ); - if ( t && !stricmp( t->GetFlexControllerName(), controllername ) ) - { - return t; - } - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChoreoEvent::GetTrackLookupSet( void ) -{ - return m_bTrackLookupSet; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : set - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetTrackLookupSet( bool set ) -{ - m_bTrackLookupSet = set; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChoreoEvent::IsProcessing( void ) const -{ - return m_bProcessing; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *cb - -// t - -//----------------------------------------------------------------------------- -void CChoreoEvent::StartProcessing( IChoreoEventCallback *cb, CChoreoScene *scene, float t ) -{ - Assert( !m_bProcessing ); - m_bProcessing = true; - if ( cb ) - { - cb->StartEvent( t, scene, this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *cb - -// t - -//----------------------------------------------------------------------------- -void CChoreoEvent::ContinueProcessing( IChoreoEventCallback *cb, CChoreoScene *scene, float t ) -{ - Assert( m_bProcessing ); - if ( cb ) - { - cb->ProcessEvent( t, scene, this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *cb - -// t - -//----------------------------------------------------------------------------- -void CChoreoEvent::StopProcessing( IChoreoEventCallback *cb, CChoreoScene *scene, float t ) -{ - Assert( m_bProcessing ); - if ( cb ) - { - cb->EndEvent( t, scene, this ); - } - m_bProcessing = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *cb - -// t - -//----------------------------------------------------------------------------- -bool CChoreoEvent::CheckProcessing( IChoreoEventCallback *cb, CChoreoScene *scene, float t ) -{ - //Assert( !m_bProcessing ); - if ( cb ) - { - return cb->CheckEvent( t, scene, this ); - } - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoEvent::ResetProcessing( void ) -{ - if ( GetType() == LOOP ) - { - m_nLoopsRemaining = m_nNumLoops; - } - - m_bProcessing = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *mixer - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetMixer( CAudioMixer *mixer ) -{ - m_pMixer = mixer; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CAudioMixer -//----------------------------------------------------------------------------- -CAudioMixer *CChoreoEvent::GetMixer( void ) const -{ - return m_pMixer; -} - -// Snap to scene framerate -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoEvent::SnapTimes() -{ - if ( HasEndTime() && !IsFixedLength() ) - { - m_flEndTime = SnapTime( m_flEndTime ); - } - float oldstart = m_flStartTime; - m_flStartTime = SnapTime( m_flStartTime ); - - // Don't snap end time for fixed length events, just set based on new start time - if ( IsFixedLength() ) - { - float dt = m_flStartTime - oldstart; - m_flEndTime += dt; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : t - -// Output : float -//----------------------------------------------------------------------------- -float CChoreoEvent::SnapTime( float t ) -{ - CChoreoScene *scene = GetScene(); - if ( !scene) - { - Assert( 0 ); - return t; - } - - return scene->SnapTime( t ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoScene -//----------------------------------------------------------------------------- -CChoreoScene *CChoreoEvent::GetScene( void ) -{ - return m_pScene; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *scene - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetScene( CChoreoScene *scene ) -{ - m_pScene = scene; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : t - -// Output : char const -//----------------------------------------------------------------------------- -const char *CChoreoEvent::NameForAbsoluteTagType( AbsTagType t ) -{ - switch ( t ) - { - case PLAYBACK: - return "playback_time"; - case ORIGINAL: - return "shifted_time"; - default: - break; - } - - return "AbsTagType(unknown)"; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -// Output : AbsTagType -//----------------------------------------------------------------------------- -CChoreoEvent::AbsTagType CChoreoEvent::TypeForAbsoluteTagName( const char *name ) -{ - if ( !Q_strcasecmp( name, "playback_time" ) ) - { - return PLAYBACK; - } - else if ( !Q_strcasecmp( name, "shifted_time" ) ) - { - return ORIGINAL; - } - - return (AbsTagType)-1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -//----------------------------------------------------------------------------- -void CChoreoEvent::ClearAllAbsoluteTags( AbsTagType type ) -{ - m_AbsoluteTags[ type ].Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// Output : int -//----------------------------------------------------------------------------- -int CChoreoEvent::GetNumAbsoluteTags( AbsTagType type ) -{ - return m_AbsoluteTags[ type ].Size(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// tagnum - -// Output : CEventAbsoluteTag -//----------------------------------------------------------------------------- -CEventAbsoluteTag *CChoreoEvent::GetAbsoluteTag( AbsTagType type, int tagnum ) -{ - Assert( tagnum >= 0 && tagnum < m_AbsoluteTags[ type ].Size() ); - return &m_AbsoluteTags[ type ][ tagnum ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// *tagname - -// Output : CEventAbsoluteTag -//----------------------------------------------------------------------------- -CEventAbsoluteTag *CChoreoEvent::FindAbsoluteTag( AbsTagType type, const char *tagname ) -{ - for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ ) - { - CEventAbsoluteTag *ptag = &m_AbsoluteTags[ type ][ i ]; - if ( !ptag ) - continue; - - if ( !stricmp( ptag->GetName(), tagname ) ) - { - return ptag; - } - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// *tagname - -// t - -//----------------------------------------------------------------------------- -void CChoreoEvent::AddAbsoluteTag( AbsTagType type, const char *tagname, float t ) -{ - CEventAbsoluteTag at( this, tagname, t ); - m_AbsoluteTags[ type ].AddToTail( at ); - - // Sort tags - CEventAbsoluteTag temp( (CChoreoEvent *)0x1, "", 0.0f ); - - // ugly bubble sort - for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ ) - { - for ( int j = i + 1; j < m_AbsoluteTags[ type ].Size(); j++ ) - { - CEventAbsoluteTag *t1 = &m_AbsoluteTags[ type ][ i ]; - CEventAbsoluteTag *t2 = &m_AbsoluteTags[ type ][ j ]; - - if ( t1->GetPercentage() > t2->GetPercentage() ) - { - temp = *t1; - *t1 = *t2; - *t2 = temp; - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// *tagname - -//----------------------------------------------------------------------------- -void CChoreoEvent::RemoveAbsoluteTag( AbsTagType type, const char *tagname ) -{ - for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ ) - { - CEventAbsoluteTag *ptag = &m_AbsoluteTags[ type ][ i ]; - if ( !ptag ) - continue; - - if ( !stricmp( ptag->GetName(), tagname ) ) - { - m_AbsoluteTags[ type ].Remove( i ); - return; - } - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: makes sure tags in PLAYBACK are in the same order as ORIGINAL -// Input : -// Output : true if they were in order, false if it has to reorder them -//----------------------------------------------------------------------------- -bool CChoreoEvent::VerifyTagOrder( ) -{ - bool bInOrder = true; - - // Sort tags - CEventAbsoluteTag temp( (CChoreoEvent *)0x1, "", 0.0f ); - - for ( int i = 0; i < m_AbsoluteTags[ CChoreoEvent::ORIGINAL ].Size(); i++ ) - { - CEventAbsoluteTag *ptag = &m_AbsoluteTags[ CChoreoEvent::ORIGINAL ][ i ]; - if ( !ptag ) - continue; - - CEventAbsoluteTag *t1 = &m_AbsoluteTags[ CChoreoEvent::PLAYBACK ][ i ]; - - if ( stricmp( ptag->GetName(), t1->GetName() ) == 0) - continue; - - bInOrder = false; - for ( int j = i + 1; j < m_AbsoluteTags[ CChoreoEvent::PLAYBACK ].Size(); j++ ) - { - CEventAbsoluteTag *t2 = &m_AbsoluteTags[ CChoreoEvent::PLAYBACK ][ j ]; - - if ( stricmp( ptag->GetName(), t2->GetName() ) == 0 ) - { - temp = *t1; - *t1 = *t2; - *t2 = temp; - break; - } - } - } - return bInOrder; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// *tagname - -//----------------------------------------------------------------------------- - -float CChoreoEvent::GetBoundedAbsoluteTagPercentage( AbsTagType type, int tagnum ) -{ - if ( tagnum <= -2 ) - { - /* - if (GetNumAbsoluteTags( type ) >= 1) - { - CEventAbsoluteTag *tag = GetAbsoluteTag( type, 0 ); - Assert( tag ); - return -tag->GetTime(); - } - */ - return 0.0f; // -0.5f; - } - else if ( tagnum == -1 ) - { - return 0.0f; - } - else if ( tagnum == GetNumAbsoluteTags( type ) ) - { - return 1.0; - } - else if ( tagnum > GetNumAbsoluteTags( type ) ) - { - /* - if (GetNumAbsoluteTags( type ) >= 1) - { - CEventAbsoluteTag *tag = GetAbsoluteTag( type, tagnum - 2 ); - Assert( tag ); - return 2.0 - tag->GetTime(); - } - */ - return 1.0; // 1.5; - } - - /* - { - float duration = GetDuration(); - - if ( type == SHIFTED ) - { - float seqduration; - GetGestureSequenceDuration( seqduration ); - return seqduration; - } - return duration; - } - */ - - CEventAbsoluteTag *tag = GetAbsoluteTag( type, tagnum ); - Assert( tag ); - return tag->GetPercentage(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : t - -// Output : float -//----------------------------------------------------------------------------- -float CChoreoEvent::GetOriginalPercentageFromPlaybackPercentage( float t ) -{ - Assert( GetType() == GESTURE ); - if ( GetType() != GESTURE ) - return t; - - int count = GetNumAbsoluteTags( PLAYBACK ); - - if ( count != GetNumAbsoluteTags( ORIGINAL ) ) - { - return t; - } - - if ( count <= 0 ) - { - return t; - } - - if ( t <= 0.0f ) - return 0.0f; - - float s = 0.0f, n = 0.0f; - - // find what tags this is between - int i; - for ( i = -1 ; i < count; i++ ) - { - s = GetBoundedAbsoluteTagPercentage( PLAYBACK, i ); - n = GetBoundedAbsoluteTagPercentage( PLAYBACK, i + 1 ); - - if ( t >= s && t <= n ) - { - break; - } - } - - int prev = i - 1; - int start = i; - int end = i + 1; - int next = i + 2; - - prev = MAX( -2, prev ); - start = MAX( -1, start ); - end = MIN( end, count ); - next = MIN( next, count + 1 ); - - CEventAbsoluteTag *pStartTag = NULL; - CEventAbsoluteTag *pEndTag = NULL; - - // check for linear portion of lookup - if (start >= 0 && start < count) - { - pStartTag = GetAbsoluteTag( PLAYBACK, start ); - } - if (end >= 0 && end < count) - { - pEndTag = GetAbsoluteTag( PLAYBACK, end ); - } - - if (pStartTag && pEndTag) - { - if (pStartTag->GetLinear() && pEndTag->GetLinear()) - { - CEventAbsoluteTag *pOrigStartTag = GetAbsoluteTag( ORIGINAL, start ); - CEventAbsoluteTag *pOrigEndTag = GetAbsoluteTag( ORIGINAL, end ); - - if (pOrigStartTag && pOrigEndTag) - { - s = ( t - pStartTag->GetPercentage() ) / (pEndTag->GetPercentage() - pStartTag->GetPercentage()); - return (1 - s) * pOrigStartTag->GetPercentage() + s * pOrigEndTag->GetPercentage(); - } - } - } - - float dt = n - s; - - Vector vPre( GetBoundedAbsoluteTagPercentage( PLAYBACK, prev ), GetBoundedAbsoluteTagPercentage( ORIGINAL, prev ), 0 ); - Vector vStart( GetBoundedAbsoluteTagPercentage( PLAYBACK, start ), GetBoundedAbsoluteTagPercentage( ORIGINAL, start ), 0 ); - Vector vEnd( GetBoundedAbsoluteTagPercentage( PLAYBACK, end ), GetBoundedAbsoluteTagPercentage( ORIGINAL, end ), 0 ); - Vector vNext( GetBoundedAbsoluteTagPercentage( PLAYBACK, next ), GetBoundedAbsoluteTagPercentage( ORIGINAL, next ), 0 ); - - // simulate sections of either side of "linear" portion of ramp as linear slope - if (pStartTag && pStartTag->GetLinear()) - { - vPre.Init( vStart.x - (vEnd.x - vStart.x), vStart.y - (vEnd.y - vStart.y), 0 ); - } - - if (pEndTag && pEndTag->GetLinear()) - { - vNext.Init( vEnd.x + (vEnd.x - vStart.x), vEnd.y + (vEnd.y - vStart.y), 0 ); - } - - - float f2 = 0.0f; - if ( dt > 0.0f ) - { - f2 = ( t - s ) / ( dt ); - } - f2 = clamp( f2, 0.0f, 1.0f ); - - Vector vOut; - Catmull_Rom_Spline_NormalizeX( - vPre, - vStart, - vEnd, - vNext, - f2, - vOut ); - - return vOut.y; - - /* - float duration; - GetGestureSequenceDuration( duration ); - - float retval = clamp( vOut.y, 0.0f, duration ); - return retval; - */ -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : t - -// Output : float -//----------------------------------------------------------------------------- -float CChoreoEvent::GetPlaybackPercentageFromOriginalPercentage( float t ) -{ - Assert( GetType() == GESTURE ); - if ( GetType() != GESTURE ) - return t; - - int count = GetNumAbsoluteTags( PLAYBACK ); - - if ( count != GetNumAbsoluteTags( ORIGINAL ) ) - { - return t; - } - - if ( count <= 0 ) - { - return t; - } - - if ( t <= 0.0f ) - return 0.0f; - - float s = 0.0f, n = 0.0f; - - // find what tags this is between - int i; - for ( i = -1 ; i < count; i++ ) - { - s = GetBoundedAbsoluteTagPercentage( PLAYBACK, i ); - n = GetBoundedAbsoluteTagPercentage( PLAYBACK, i + 1 ); - - if ( t >= s && t <= n ) - { - break; - } - } - - int prev = i - 1; - int start = i; - int end = i + 1; - int next = i + 2; - - prev = MAX( -2, prev ); - start = MAX( -1, start ); - end = MIN( end, count ); - next = MIN( next, count + 1 ); - - CEventAbsoluteTag *pStartTag = NULL; - CEventAbsoluteTag *pEndTag = NULL; - - // check for linear portion of lookup - if (start >= 0 && start < count) - { - pStartTag = GetAbsoluteTag( ORIGINAL, start ); - } - if (end >= 0 && end < count) - { - pEndTag = GetAbsoluteTag( ORIGINAL, end ); - } - - // check for linear portion of lookup - if (pStartTag && pEndTag) - { - if (pStartTag->GetLinear() && pEndTag->GetLinear()) - { - CEventAbsoluteTag *pPlaybackStartTag = GetAbsoluteTag( PLAYBACK, start ); - CEventAbsoluteTag *pPlaybackEndTag = GetAbsoluteTag( PLAYBACK, end ); - - if (pPlaybackStartTag && pPlaybackEndTag) - { - s = ( t - pStartTag->GetPercentage() ) / (pEndTag->GetPercentage() - pStartTag->GetPercentage()); - return (1 - s) * pPlaybackStartTag->GetPercentage() + s * pPlaybackEndTag->GetPercentage(); - } - } - } - - float dt = n - s; - - Vector vPre( GetBoundedAbsoluteTagPercentage( ORIGINAL, prev ), GetBoundedAbsoluteTagPercentage( PLAYBACK, prev ), 0 ); - Vector vStart( GetBoundedAbsoluteTagPercentage( ORIGINAL, start ), GetBoundedAbsoluteTagPercentage( PLAYBACK, start ), 0 ); - Vector vEnd( GetBoundedAbsoluteTagPercentage( ORIGINAL, end ), GetBoundedAbsoluteTagPercentage( PLAYBACK, end ), 0 ); - Vector vNext( GetBoundedAbsoluteTagPercentage( ORIGINAL, next ), GetBoundedAbsoluteTagPercentage( PLAYBACK, next ), 0 ); - - // simulate sections of either side of "linear" portion of ramp as linear slope - if (pStartTag && pStartTag->GetLinear()) - { - vPre.Init( vStart.x - (vEnd.x - vStart.x), vStart.y - (vEnd.y - vStart.y), 0 ); - } - - if (pEndTag && pEndTag->GetLinear()) - { - vNext.Init( vEnd.x + (vEnd.x - vStart.x), vEnd.y + (vEnd.y - vStart.y), 0 ); - } - - float f2 = 0.0f; - if ( dt > 0.0f ) - { - f2 = ( t - s ) / ( dt ); - } - f2 = clamp( f2, 0.0f, 1.0f ); - - Vector vOut; - Catmull_Rom_Spline_NormalizeX( - vPre, - vStart, - vEnd, - vNext, - f2, - vOut ); - - return vOut.y; - - /* - float duration; - GetGestureSequenceDuration( duration ); - - float retval = clamp( vOut.y, 0.0f, duration ); - return retval; - */ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : duration - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetGestureSequenceDuration( float duration ) -{ - m_flGestureSequenceDuration = duration; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : duration - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChoreoEvent::GetGestureSequenceDuration( float& duration ) -{ - bool valid = m_flGestureSequenceDuration != 0.0f; - - if ( !valid ) - { - duration = GetDuration(); - } - else - { - duration = m_flGestureSequenceDuration; - } - - return valid; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pitch - -//----------------------------------------------------------------------------- -int CChoreoEvent::GetPitch( void ) const -{ - return m_nPitch; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pitch - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetPitch( int pitch ) -{ - m_nPitch = pitch; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : yaw - -//----------------------------------------------------------------------------- -int CChoreoEvent::GetYaw( void ) const -{ - return m_nYaw; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : yaw - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetYaw( int yaw ) -{ - m_nYaw = yaw; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : t - -// -1 - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetLoopCount( int numloops ) -{ - Assert( GetType() == LOOP ); - // Never below -1 - m_nNumLoops = MAX( numloops, -1 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CChoreoEvent::GetNumLoopsRemaining( void ) -{ - Assert( GetType() == LOOP ); - - return m_nLoopsRemaining; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : loops - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetNumLoopsRemaining( int loops ) -{ - Assert( GetType() == LOOP ); - - m_nLoopsRemaining = loops; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CChoreoEvent::GetLoopCount( void ) -{ - Assert( GetType() == LOOP ); - return m_nNumLoops; -} - -EdgeInfo_t *CCurveData::GetEdgeInfo( int idx ) -{ - return &m_RampEdgeInfo[ idx ]; -} - -int CCurveData::GetCount( void ) -{ - return m_Ramp.Count(); -} - -CExpressionSample *CCurveData::Get( int index ) -{ - if ( index < 0 || index >= GetCount() ) - return NULL; - - return &m_Ramp[ index ]; -} - -CExpressionSample *CCurveData::Add( float time, float value, bool selected ) -{ - CExpressionSample sample; - - sample.time = time; - sample.value = value; - sample.selected = selected; - - int idx = m_Ramp.AddToTail( sample ); - return &m_Ramp[ idx ]; -} - -void CCurveData::Delete( int index ) -{ - if ( index < 0 || index >= GetCount() ) - return; - - m_Ramp.Remove( index ); -} - -void CCurveData::Clear( void ) -{ - m_Ramp.RemoveAll(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCurveData::Resort( ICurveDataAccessor *data ) -{ - for ( int i = 0; i < m_Ramp.Size(); i++ ) - { - for ( int j = i + 1; j < m_Ramp.Size(); j++ ) - { - CExpressionSample src = m_Ramp[ i ]; - CExpressionSample dest = m_Ramp[ j ]; - - if ( src.time > dest.time ) - { - m_Ramp[ i ] = dest; - m_Ramp[ j ] = src; - } - } - } - - RemoveOutOfRangeSamples( data ); - - // m_RampAccumulator.RemoveAll(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : number - -// Output : CExpressionSample -//----------------------------------------------------------------------------- -CExpressionSample *CCurveData::GetBoundedSample( ICurveDataAccessor *data, int number, bool& bClamped ) -{ - // Search for two samples which span time f - if ( number < 0 ) - { - static CExpressionSample nullstart; - nullstart.time = 0.0f; - nullstart.value = GetEdgeZeroValue( true ); - nullstart.SetCurveType( GetEdgeCurveType( true ) ); - bClamped = true; - return &nullstart; - } - else if ( number >= GetCount() ) - { - static CExpressionSample nullend; - nullend.time = data->GetDuration(); - nullend.value = GetEdgeZeroValue( false ); - nullend.SetCurveType( GetEdgeCurveType( false ) ); - bClamped = true; - return &nullend; - } - - bClamped = false; - return Get( number ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCurveData::RemoveOutOfRangeSamples( ICurveDataAccessor *data ) -{ - float duration = data->GetDuration(); - - int c = GetCount(); - for ( int i = c-1; i >= 0; i-- ) - { - CExpressionSample src = m_Ramp[ i ]; - if ( src.time < 0 || - src.time > duration + 0.01 ) - { - m_Ramp.Remove( i ); - } - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoEvent::RescaleGestureTimes( float newstart, float newend, bool bMaintainAbsoluteTagPositions ) -{ - if ( GetType() != CChoreoEvent::GESTURE ) - return; - - // Did it actually change - if ( newstart == GetStartTime() && - newend == GetEndTime() ) - { - return; - } - - float newduration = newend - newstart; - - float dt = 0.0f; - //If the end is moving, leave tags stay where they are (dt == 0.0f) - if ( newstart != GetStartTime() ) - { - // Otherwise, if the new start is later, then tags need to be shifted backwards - dt -= ( newstart - GetStartTime() ); - } - - if ( bMaintainAbsoluteTagPositions ) - { - int i; - int count = GetNumAbsoluteTags( CChoreoEvent::PLAYBACK ); - for ( i = 0; i < count; i++ ) - { - CEventAbsoluteTag *tag = GetAbsoluteTag( CChoreoEvent::PLAYBACK, i ); - float tagtime = tag->GetPercentage() * GetDuration(); - - tagtime += dt; - - tagtime = clamp( tagtime / newduration, 0.0f, 1.0f ); - - tag->SetPercentage( tagtime ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Make sure tags aren't co-located or out of order -//----------------------------------------------------------------------------- -bool CChoreoEvent::PreventTagOverlap( void ) -{ - bool bHadOverlap = false; - - // FIXME: limit to single frame? - float minDp = 0.01; - - float minP = 1.00; - - int count = GetNumAbsoluteTags( CChoreoEvent::PLAYBACK ); - for ( int i = count - 1; i >= 0; i-- ) - { - CEventAbsoluteTag *tag = GetAbsoluteTag( CChoreoEvent::PLAYBACK, i ); - - if (tag->GetPercentage() > minP) - { - tag->SetPercentage( minP ); - - minDp = MIN( 0.01, minP / (i + 1) ); - bHadOverlap = true; - } - else - { - minP = tag->GetPercentage(); - } - minP = MAX( minP - minDp, 0 ); - } - - return bHadOverlap; -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// Output : CEventAbsoluteTag -//----------------------------------------------------------------------------- -CEventAbsoluteTag *CChoreoEvent::FindEntryTag( AbsTagType type ) -{ - for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ ) - { - CEventAbsoluteTag *ptag = &m_AbsoluteTags[ type ][ i ]; - if ( !ptag ) - continue; - - if ( ptag->GetEntry() ) - { - return ptag; - } - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// Output : CEventAbsoluteTag -//----------------------------------------------------------------------------- -CEventAbsoluteTag *CChoreoEvent::FindExitTag( AbsTagType type ) -{ - for ( int i = 0; i < m_AbsoluteTags[ type ].Size(); i++ ) - { - CEventAbsoluteTag *ptag = &m_AbsoluteTags[ type ][ i ]; - if ( !ptag ) - continue; - - if ( ptag->GetExit() ) - { - return ptag; - } - } - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *style - -// maxlen - -//----------------------------------------------------------------------------- -void CChoreoEvent::GetMovementStyle( char *style, int maxlen ) -{ - Assert( GetType() == MOVETO ); - - style[0] = 0; - - const char *in = m_Parameters2.Get(); - char *out = style; - - while ( *in && *in != '\0' && *in != ' ' ) - { - if ( out - style >= maxlen - 1 ) - break; - *out++ = *in++; - } - - *out = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *style - -// maxlen - -//----------------------------------------------------------------------------- -void CChoreoEvent::GetDistanceStyle( char *style, int maxlen ) -{ - Assert( GetType() == MOVETO ); - - style[0]= 0; - - const char *in = Q_strstr( m_Parameters2.Get(), " " ); - if ( !in ) - return; - - in++; - char *out = style; - - while ( *in && *in != '\0' ) - { - if ( out - style >= maxlen - 1 ) - break; - *out++ = *in++; - } - - *out = 0; -} - -void CChoreoEvent::SetCloseCaptionType( CLOSECAPTION type ) -{ - Assert( m_fType == SPEAK ); - m_ccType = type; -} - -CChoreoEvent::CLOSECAPTION CChoreoEvent::GetCloseCaptionType() const -{ - Assert( m_fType == SPEAK ); - return (CLOSECAPTION)m_ccType; -} - -void CChoreoEvent::SetCloseCaptionToken( char const *token ) -{ - Assert( m_fType == SPEAK ); - Assert( token ); - m_CCToken = token; -} - -char const *CChoreoEvent::GetCloseCaptionToken() const -{ - Assert( m_fType == SPEAK ); - return m_CCToken.Get(); -} - -bool CChoreoEvent::GetPlaybackCloseCaptionToken( char *dest, int destlen ) -{ - dest[0] = 0; - - Assert( m_fType == SPEAK ); - - switch ( m_ccType ) - { - default: - case CC_DISABLED: - { - return false; - } - case CC_SLAVE: - { - // If it's a slave, then only disable if we're not using the combined wave - if ( IsUsingCombinedFile() ) - { - return false; - } - - if ( m_CCToken[ 0 ] != 0 ) - { - Q_strncpy( dest, m_CCToken.Get(), destlen ); - } - else - { - Q_strncpy( dest, m_Parameters.Get(), destlen ); - } - return true; - } - case CC_MASTER: - { - // Always use the override if we're the master, otherwise always use the default - // parameter - if ( m_CCToken[ 0 ] != 0 ) - { - Q_strncpy( dest, m_CCToken.Get(), destlen ); - } - else - { - Q_strncpy( dest, m_Parameters.Get(), destlen ); - } - return true; - } - } - - return false; -} - - -void CChoreoEvent::SetUsingCombinedFile( bool isusing ) -{ - Assert( m_fType == SPEAK ); - m_bUsingCombinedSoundFile = isusing; -} - -bool CChoreoEvent::IsUsingCombinedFile() const -{ - Assert( m_fType == SPEAK ); - return m_bUsingCombinedSoundFile; -} - -void CChoreoEvent::SetRequiredCombinedChecksum( unsigned int checksum ) -{ - Assert( m_fType == SPEAK ); - m_uRequiredCombinedChecksum = checksum; -} - -unsigned int CChoreoEvent::GetRequiredCombinedChecksum() -{ - Assert( m_fType == SPEAK ); - return m_uRequiredCombinedChecksum; -} - -void CChoreoEvent::SetNumSlaves( int num ) -{ - Assert( m_fType == SPEAK ); - Assert( num >= 0 ); - m_nNumSlaves = num; -} - -int CChoreoEvent::GetNumSlaves() const -{ - Assert( m_fType == SPEAK ); - return m_nNumSlaves; -} - -void CChoreoEvent::SetLastSlaveEndTime( float t ) -{ - Assert( m_fType == SPEAK ); - m_flLastSlaveEndTime = t; -} - -float CChoreoEvent::GetLastSlaveEndTime() const -{ - Assert( m_fType == SPEAK ); - return m_flLastSlaveEndTime; -} - -void CChoreoEvent::SetCloseCaptionTokenValid( bool valid ) -{ - Assert( m_fType == SPEAK ); - m_bCCTokenValid = valid; -} - -bool CChoreoEvent::GetCloseCaptionTokenValid() const -{ - Assert( m_fType == SPEAK ); - return m_bCCTokenValid; -} - - -//----------------------------------------------------------------------------- -// Purpose: Removes characters which can't appear in windows filenames -// Input : *in - -// *dest - -// destlen - -// Output : static void -//----------------------------------------------------------------------------- -static void CleanupTokenName( char const *in, char *dest, int destlen ) -{ - char *out = dest; - while ( *in && ( out - dest ) < destlen ) - { - if ( isalnum( *in ) || // lowercase, uppercase, digits and underscore are valid - *in == '_' ) - { - *out++ = *in; - } - else - { - *out++ = '_'; // Put underscores in for bogus characters - } - in++; - } - *out = 0; -} - -bool CChoreoEvent::ComputeCombinedBaseFileName( char *dest, int destlen, bool creategenderwildcard ) -{ - if ( m_fType != SPEAK ) - return false; - - if ( m_ccType != CC_MASTER ) - return false; - - if ( GetNumSlaves() == 0 ) - return false; - - if ( !m_pScene ) - return false; - - char vcdpath[ 512 ]; - char cleanedtoken[ MAX_CCTOKEN_STRING ]; - CleanupTokenName( m_CCToken.Get(), cleanedtoken, sizeof( cleanedtoken ) ); - - if ( Q_strlen( cleanedtoken ) <= 0 ) - return false; - - Q_strncpy( vcdpath, m_pScene->GetFilename(), sizeof( vcdpath ) ); - Q_StripFilename( vcdpath ); - Q_FixSlashes( vcdpath, '/' ); - - char *pvcd = vcdpath; - - char *offset = Q_strstr( vcdpath, "scenes" ); - if ( offset ) - { - pvcd = offset + 6; - if ( *pvcd == '/' ) - { - ++pvcd; - } - } - - size_t len = Q_strlen( pvcd ); - - if ( len > 0 && ( len + 1 ) < ( sizeof( vcdpath ) - 1 ) ) - { - pvcd[ len ] = '/'; - pvcd[ len + 1 ] = 0; - } - - Assert( !Q_strstr( pvcd, ":" ) ); - - if ( creategenderwildcard ) - { - Q_snprintf( dest, destlen, "sound/combined/%s%s_$gender.wav", pvcd, cleanedtoken ); - } - else - { - Q_snprintf( dest, destlen, "sound/combined/%s%s.wav", pvcd, cleanedtoken ); - } - return true; -} - -bool CChoreoEvent::IsCombinedUsingGenderToken() const -{ - return m_bCombinedUsingGenderToken; -} - -void CChoreoEvent::SetCombinedUsingGenderToken( bool using_gender ) -{ - m_bCombinedUsingGenderToken = using_gender; -} - - -int CChoreoEvent::ValidateCombinedFile() -{ - - return 0; -} - -bool CChoreoEvent::IsSuppressingCaptionAttenuation() const -{ - return m_bSuppressCaptionAttenuation; -} - -void CChoreoEvent::SetSuppressingCaptionAttenuation( bool suppress ) -{ - m_bSuppressCaptionAttenuation = suppress; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoEvent::ClearEventDependencies() -{ - m_Dependencies.RemoveAll(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *other - -//----------------------------------------------------------------------------- -void CChoreoEvent::AddEventDependency( CChoreoEvent *other ) -{ - if ( m_Dependencies.Find( other ) == m_Dependencies.InvalidIndex() ) - { - m_Dependencies.AddToTail( other ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : list - -//----------------------------------------------------------------------------- -void CChoreoEvent::GetEventDependencies( CUtlVector< CChoreoEvent * >& list ) -{ - int c = m_Dependencies.Count(); - for ( int i = 0; i < c; ++i ) - { - list.AddToTail( m_Dependencies[ i ] ); - } -} - -void CCurveData::SetEdgeInfo( bool leftEdge, int curveType, float zero ) -{ - int idx = leftEdge ? 0 : 1; - m_RampEdgeInfo[ idx ].m_CurveType = curveType; - m_RampEdgeInfo[ idx ].m_flZeroPos = zero; -} - -void CCurveData::GetEdgeInfo( bool leftEdge, int& curveType, float& zero ) const -{ - int idx = leftEdge ? 0 : 1; - curveType = m_RampEdgeInfo[ idx ].m_CurveType; - zero = m_RampEdgeInfo[ idx ].m_flZeroPos; -} - -void CCurveData::SetEdgeActive( bool leftEdge, bool state ) -{ - int idx = leftEdge ? 0 : 1; - m_RampEdgeInfo[ idx ].m_bActive = state; -} - -bool CCurveData::IsEdgeActive( bool leftEdge ) const -{ - int idx = leftEdge ? 0 : 1; - return m_RampEdgeInfo[ idx ].m_bActive; -} - -int CCurveData::GetEdgeCurveType( bool leftEdge ) const -{ - if ( !IsEdgeActive( leftEdge ) ) - { - return CURVE_DEFAULT; - } - - int idx = leftEdge ? 0 : 1; - return m_RampEdgeInfo[ idx ].m_CurveType; -} - -float CCurveData::GetEdgeZeroValue( bool leftEdge ) const -{ - if ( !IsEdgeActive( leftEdge ) ) - { - return 0.0f; - } - - int idx = leftEdge ? 0 : 1; - return m_RampEdgeInfo[ idx ].m_flZeroPos; -} - - -void CChoreoEvent::SaveToBuffer( CUtlBuffer& buf, CChoreoScene *pScene, IChoreoStringPool *pStringPool ) -{ - buf.PutChar( GetType() ); - buf.PutShort( pStringPool->FindOrAddString( GetName() ) ); - - float st = GetStartTime(); - buf.PutFloat( st ); - - float et = GetEndTime(); - buf.PutFloat( et ); - - buf.PutShort( pStringPool->FindOrAddString( GetParameters() ) ); - buf.PutShort( pStringPool->FindOrAddString( GetParameters2() ) ); - buf.PutShort( pStringPool->FindOrAddString( GetParameters3() ) ); - - m_Ramp.SaveToBuffer( buf, pStringPool ); - - int flags = 0; - flags |= IsResumeCondition() ? 1<<0 : 0; - flags |= IsLockBodyFacing() ? 1<<1 : 0; - flags |= IsFixedLength() ? 1<<2 : 0; - flags |= GetActive() ? 1<<3 : 0; - flags |= GetForceShortMovement() ? 1<<4 : 0; - flags |= GetPlayOverScript() ? 1<<5 : 0; - - buf.PutUnsignedChar( flags ); - - buf.PutFloat( GetDistanceToTarget() ); - - int numRelativeTags = GetNumRelativeTags(); - Assert( numRelativeTags <= 255 ); - buf.PutUnsignedChar( numRelativeTags ); - - for ( int t = 0; t < numRelativeTags; t++ ) - { - CEventRelativeTag *rt = GetRelativeTag( t ); - Assert( rt ); - buf.PutShort( pStringPool->FindOrAddString( rt->GetName() ) ); - - Assert( rt->GetPercentage() >= 0.0f && rt->GetPercentage() <= 1.0f ); - unsigned char p = static_cast(rt->GetPercentage() * 255.0f); - buf.PutUnsignedChar( p ); - } - - int numTimingTags = GetNumTimingTags(); - Assert( numTimingTags <= 255 ); - buf.PutUnsignedChar( numTimingTags ); - - for ( int t = 0; t < numTimingTags; t++ ) - { - CFlexTimingTag *tt = GetTimingTag( t ); - Assert( tt ); - buf.PutShort( pStringPool->FindOrAddString( tt->GetName() ) ); - - // save as u0.8 - Assert( tt->GetPercentage() >= 0.0f && tt->GetPercentage() <= 1.0f ); - unsigned char p = static_cast(tt->GetPercentage() * 255.0f); - buf.PutUnsignedChar( p ); - - // Don't save locked state, it's only used by the editor tt->GetLocked() - } - - int tagtype; - for ( tagtype = 0; tagtype < CChoreoEvent::NUM_ABS_TAG_TYPES; tagtype++ ) - { - int num = GetNumAbsoluteTags( (CChoreoEvent::AbsTagType)tagtype ); - Assert( num <= 255 ); - buf.PutUnsignedChar( num ); - - for ( int i = 0; i < num ; ++i ) - { - CEventAbsoluteTag *abstag = GetAbsoluteTag( (CChoreoEvent::AbsTagType)tagtype, i ); - Assert( abstag ); - buf.PutShort( pStringPool->FindOrAddString( abstag->GetName() ) ); - - // save as u4.12 - Assert( abstag->GetPercentage() >= 0.0f && abstag->GetPercentage() <= 15.0f ); - unsigned short p = static_cast(abstag->GetPercentage() * 4096.0f); - buf.PutUnsignedShort( p ); - } - } - - if ( GetType() == CChoreoEvent::GESTURE ) - { - float duration; - if ( GetGestureSequenceDuration( duration ) ) - { - buf.PutFloat( duration ); - } - else - { - buf.PutFloat( -1.0f ); - } - } - - buf.PutChar( IsUsingRelativeTag() ? 1 : 0 ); - if ( IsUsingRelativeTag() ) - { - buf.PutShort( pStringPool->FindOrAddString( GetRelativeTagName() ) ); - buf.PutShort( pStringPool->FindOrAddString( GetRelativeWavName() ) ); - } - - SaveFlexAnimationsToBuffer( buf, pStringPool ); - - if ( GetType() == LOOP ) - { - buf.PutChar( GetLoopCount() ); - } - - if ( GetType() == CChoreoEvent::SPEAK ) - { - buf.PutChar( GetCloseCaptionType() ); - buf.PutShort( pStringPool->FindOrAddString( GetCloseCaptionToken() ) ); - flags = 0; - - if ( GetCloseCaptionType() != CChoreoEvent::CC_DISABLED && - IsUsingCombinedFile() ) - { - flags |= ( 1<<0 ); - } - if ( IsCombinedUsingGenderToken() ) - { - flags |= ( 1<<1 ); - } - if ( IsSuppressingCaptionAttenuation() ) - { - flags |= ( 1<<2 ); - } - - buf.PutChar( flags ); - } -} - -bool CChoreoEvent::RestoreFromBuffer( CUtlBuffer& buf, CChoreoScene *pScene, IChoreoStringPool *pStringPool ) -{ - MEM_ALLOC_CREDIT(); - - SetType( (EVENTTYPE)buf.GetChar() ); - char sz[ 256 ]; - pStringPool->GetString( buf.GetShort(), sz, sizeof( sz ) ); - SetName( sz ); - - SetStartTime( buf.GetFloat() ); - SetEndTime( buf.GetFloat() ); - - char params[ 2048 ]; - pStringPool->GetString( buf.GetShort(), params, sizeof( params ) ); - SetParameters( params ); - pStringPool->GetString( buf.GetShort(), params, sizeof( params ) ); - SetParameters2( params ); - pStringPool->GetString( buf.GetShort(), params, sizeof( params ) ); - SetParameters3( params ); - - if ( !m_Ramp.RestoreFromBuffer( buf, pStringPool ) ) - return false; - - int flags = buf.GetUnsignedChar(); - SetResumeCondition( ( flags & ( 1<<0 ) ) ? true : false ); - SetLockBodyFacing( ( flags & ( 1<<1 ) ) ? true : false ); - SetFixedLength( ( flags & ( 1<<2 ) ) ? true : false ); - SetActive( ( flags & ( 1<<3 ) ) ? true : false ); - SetForceShortMovement( ( flags & ( 1<<4 ) ) ? true : false ); - SetPlayOverScript( ( flags & ( 1<<5 ) ) ? true : false ); - - SetDistanceToTarget( buf.GetFloat() ); - - int numRelTags = buf.GetUnsignedChar(); - for ( int i = 0; i < numRelTags; ++i ) - { - char tagName[ 256 ]; - pStringPool->GetString( buf.GetShort(), tagName, sizeof( tagName ) ); - float percentage = (float)buf.GetUnsignedChar() * 1.0f/255.0f; - AddRelativeTag( tagName, percentage ); - } - - int numTimingTags = buf.GetUnsignedChar(); - for ( int i = 0; i < numTimingTags; ++i ) - { - char tagName[ 256 ]; - pStringPool->GetString( buf.GetShort(), tagName, sizeof( tagName ) ); - float percentage = (float)buf.GetUnsignedChar() * 1.0f/255.0f; - // Don't parse locked state, only used by editors - AddTimingTag( tagName, percentage, false ); - } - - int tagtype; - for ( tagtype = 0; tagtype < CChoreoEvent::NUM_ABS_TAG_TYPES; tagtype++ ) - { - int num = buf.GetUnsignedChar(); - for ( int i = 0; i < num; ++i ) - { - char tagName[ 256 ]; - pStringPool->GetString( buf.GetShort(), tagName, sizeof( tagName ) ); - float percentage = (float)buf.GetUnsignedShort() * 1.0f/4096.0f; - - // Don't parse locked state, only used by editors - AddAbsoluteTag( (CChoreoEvent::AbsTagType)tagtype, tagName, percentage ); - } - } - - if ( GetType() == CChoreoEvent::GESTURE ) - { - float duration = buf.GetFloat(); - if ( duration != -1 ) - { - SetGestureSequenceDuration( duration ); - } - } - - if ( buf.GetChar() == 1 ) - { - char tagname[ 256 ]; - char wavname[ 256 ]; - pStringPool->GetString( buf.GetShort(), tagname, sizeof( tagname ) ); - pStringPool->GetString( buf.GetShort(), wavname, sizeof( wavname ) ); - - SetUsingRelativeTag( true, tagname, wavname ); - } - - if ( !RestoreFlexAnimationsFromBuffer( buf, pStringPool ) ) - return false; - - if ( GetType() == LOOP ) - { - SetLoopCount( buf.GetChar() ); - } - - if ( GetType() == CChoreoEvent::SPEAK ) - { - SetCloseCaptionType( (CLOSECAPTION)buf.GetChar() ); - char cctoken[ 256 ]; - pStringPool->GetString( buf.GetShort(), cctoken, sizeof( cctoken ) ); - SetCloseCaptionToken( cctoken ); - int flags = buf.GetChar(); - if ( flags & ( 1<<0 ) ) - { - SetUsingCombinedFile( true ); - } - if ( flags & ( 1<<1 ) ) - { - SetCombinedUsingGenderToken( true ); - } - if ( flags & ( 1<<2 ) ) - { - SetSuppressingCaptionAttenuation( true ); - } - } - - return true; -} - -void CCurveData::SaveToBuffer( CUtlBuffer& buf, IChoreoStringPool *pStringPool ) -{ - int c = GetCount(); - Assert( c <= 255 ); - buf.PutUnsignedChar( c ); - - for ( int i = 0; i < c; i++ ) - { - CExpressionSample *sample = Get( i ); - buf.PutFloat( sample->time ); - - Assert( sample->value >= 0.0f && sample->value <= 1.0f ); - unsigned char v = static_cast(sample->value * 255.0f); - buf.PutUnsignedChar( v ); - } -} - -bool CCurveData::RestoreFromBuffer( CUtlBuffer& buf, IChoreoStringPool *pStringPool ) -{ - int c = buf.GetUnsignedChar(); - for ( int i = 0; i < c; i++ ) - { - float t, v; - t = buf.GetFloat(); - v = (float)buf.GetUnsignedChar() * 1.0f/255.0f; - - Add( t, v, false ); - } - - return true; -} - -void CChoreoEvent::SaveFlexAnimationsToBuffer( CUtlBuffer& buf, IChoreoStringPool *pStringPool ) -{ - int numFlexAnimationTracks = GetNumFlexAnimationTracks(); - Assert( numFlexAnimationTracks <= 255 ); - buf.PutUnsignedChar( numFlexAnimationTracks ); - - for ( int i = 0; i < numFlexAnimationTracks; i++ ) - { - CFlexAnimationTrack *track = GetFlexAnimationTrack( i ); - - buf.PutShort( pStringPool->FindOrAddString( track->GetFlexControllerName() ) ); - - int flags = 0; - flags |= track->IsTrackActive() ? 1<<0 : 0; - flags |= track->IsComboType() ? 1<<1 : 0; - buf.PutUnsignedChar( flags ); - - buf.PutFloat( track->GetMin() ); - buf.PutFloat( track->GetMax() ); - - buf.PutShort( track->GetNumSamples( 0 ) ); - for ( int j = 0 ; j < track->GetNumSamples( 0 ) ; j++ ) - { - CExpressionSample *s = track->GetSample( j, 0 ); - if ( !s ) - continue; - - buf.PutFloat( s->time ); - - Assert( s->value >= 0.0f && s->value <= 1.0f ); - unsigned char v = static_cast(s->value * 255.0f); - buf.PutUnsignedChar( v ); - - buf.PutUnsignedShort( s->GetCurveType() ); - } - - // Write out combo samples - if ( track->IsComboType() ) - { - int numSamples = track->GetNumSamples( 1 ); - Assert( numSamples <= 32767 ); - buf.PutUnsignedShort( numSamples ); - - for ( int j = 0; j < numSamples; j++ ) - { - CExpressionSample *s = track->GetSample( j, 1 ); - if ( !s ) - continue; - - buf.PutFloat( s->time ); - - Assert( s->value >= 0.0f && s->value <= 1.0f ); - unsigned char v = static_cast(s->value * 255.0f); - buf.PutUnsignedChar( v ); - - buf.PutUnsignedShort( s->GetCurveType() ); - } - } - } -} - -bool CChoreoEvent::RestoreFlexAnimationsFromBuffer( CUtlBuffer& buf, IChoreoStringPool *pStringPool ) -{ - int numTracks = buf.GetUnsignedChar(); - - for ( int i = 0; i < numTracks; i++ ) - { - char name[ 256 ]; - pStringPool->GetString( buf.GetShort(), name, sizeof( name ) ); - - CFlexAnimationTrack *track = AddTrack( name ); - - int flags = buf.GetUnsignedChar(); - track->SetTrackActive( ( flags & ( 1<<0 ) ) ? true : false ); - track->SetComboType( ( flags & ( 1<<1 ) ) ? true : false ); - - track->SetMin( buf.GetFloat() ); - track->SetMax( buf.GetFloat() ); - - int s = buf.GetShort(); - for ( int j = 0; j < s; ++j ) - { - float t, v; - t = buf.GetFloat(); - v = (float)buf.GetUnsignedChar() * 1.0f/255.0f; - - CExpressionSample *pSample = track->AddSample( t, v, 0 ); - pSample->SetCurveType( buf.GetUnsignedShort() ); - } - - if ( track->IsComboType() ) - { - int s = buf.GetUnsignedShort(); - for ( int j = 0; j < s; ++j ) - { - float t, v; - t = buf.GetFloat(); - v = (float)buf.GetUnsignedChar() * 1.0f/255.0f; - - CExpressionSample *pSample = track->AddSample( t, v, 1 ); - pSample->SetCurveType( buf.GetUnsignedShort() ); - } - } - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Marks the event as enabled/disabled -// Input : state - -//----------------------------------------------------------------------------- -void CChoreoEvent::SetActive( bool state ) -{ - m_bActive = state; -} - -bool CChoreoEvent::GetActive() const -{ - return m_bActive; -} diff --git a/game/shared/choreoevent.h b/game/shared/choreoevent.h deleted file mode 100644 index cb5943b2f..000000000 --- a/game/shared/choreoevent.h +++ /dev/null @@ -1,708 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef CHOREOEVENT_H -#define CHOREOEVENT_H -#ifdef _WIN32 -#pragma once -#endif - -class CChoreoActor; -class CChoreoChannel; -class CChoreoEvent; -class CChoreoScene; -class IChoreoEventCallback; -class CAudioMixer; -class CUtlBuffer; -class IChoreoStringPool; - - -#include "tier1/utlstring.h" -#include "tier1/utlvector.h" -#include "expressionsample.h" -#include "networkvar.h" -#include "localflexcontroller.h" - -typedef CUtlString ChoreoStr_t; - -//----------------------------------------------------------------------------- -// Purpose: SPEAK events can have "relative tags" that other objects can reference -// to specify their start times off of -//----------------------------------------------------------------------------- -class CEventRelativeTag -{ -public: - DECLARE_CLASS_NOBASE( CEventRelativeTag ); - - enum - { - MAX_EVENTTAG_LENGTH = 128, - }; - - CEventRelativeTag( CChoreoEvent *owner, const char *name, float percentage ); - CEventRelativeTag( const CEventRelativeTag& src ); - - const char *GetName( void ); - float GetPercentage( void ); - void SetPercentage( float percentage ); - - // Returns the corrected time based on the owner's length and start time - float GetStartTime( void ); - CChoreoEvent *GetOwner( void ); - void SetOwner( CChoreoEvent *event ); - -protected: - - ChoreoStr_t m_Name; - float m_flPercentage; - CChoreoEvent *m_pOwner; -}; - -//----------------------------------------------------------------------------- -// Purpose: GESTURE events can have "absolute tags" (where the value is not a -// percentage, but an actual timestamp from the start of the event) -//----------------------------------------------------------------------------- -class CEventAbsoluteTag -{ -public: - enum - { - MAX_EVENTTAG_LENGTH = 128, - }; - - CEventAbsoluteTag( CChoreoEvent *owner, const char *name, float percentage ); - CEventAbsoluteTag( const CEventAbsoluteTag& src ); - - const char *GetName( void ); - - float GetPercentage( void ); - void SetPercentage( float percentage ); - - float GetEventTime( void ); - void SetEventTime( float t ); - - float GetAbsoluteTime( void ); - void SetAbsoluteTime( float t ); - - CChoreoEvent *GetOwner( void ); - void SetOwner( CChoreoEvent *event ); - - void SetLocked( bool bLocked ); - bool GetLocked( void ); - - void SetLinear( bool bLinear ); - bool GetLinear( void ); - - void SetEntry( bool bEntry ); - bool GetEntry( void ); - - void SetExit( bool bExit ); - bool GetExit( void ); - -protected: - - ChoreoStr_t m_Name; - float m_flPercentage; - bool m_bLocked:1; - bool m_bLinear:1; - bool m_bEntry:1; - bool m_bExit:1; - CChoreoEvent *m_pOwner; -}; - -//----------------------------------------------------------------------------- -// Purpose: FLEXANIMATION events can have "timing tags" that are used to align and -// manipulate flex animation curves -//----------------------------------------------------------------------------- -class CFlexTimingTag : public CEventRelativeTag -{ - DECLARE_CLASS( CFlexTimingTag, CEventRelativeTag ); - -public: - CFlexTimingTag( CChoreoEvent *owner, const char *name, float percentage, bool locked ); - CFlexTimingTag( const CFlexTimingTag& src ); - - bool GetLocked( void ); - void SetLocked( bool locked ); - -protected: - bool m_bLocked; -}; - -//----------------------------------------------------------------------------- -// Purpose: A flex controller position can be animated over a period of time -//----------------------------------------------------------------------------- -class CFlexAnimationTrack -{ -public: - enum - { - MAX_CONTROLLER_NAME = 128, - }; - - CFlexAnimationTrack( CChoreoEvent *event ); - CFlexAnimationTrack( const CFlexAnimationTrack* src ); - virtual ~CFlexAnimationTrack( void ); - - void SetEvent( CChoreoEvent *event ); - CChoreoEvent *GetEvent( void ); - - void SetFlexControllerName( const char *name ); - char const *GetFlexControllerName( void ); - - void SetComboType( bool combo ); - bool IsComboType( void ); - - void SetMin( float value ); - void SetMax( float value ); - float GetMin( int type = 0 ); - float GetMax( int type = 0 ); - - bool IsInverted( void ); - void SetInverted( bool isInverted ); - - int GetNumSamples( int type = 0 ); - CExpressionSample *GetSample( int index, int type = 0 ); - - bool IsTrackActive( void ); - void SetTrackActive( bool active ); - - // returns scaled value for absolute time per left/right side - float GetIntensity( float time, int side = 0 ); - - CExpressionSample *AddSample( float time, float value, int type = 0 ); - void RemoveSample( int index, int type = 0 ); - void Clear( void ); - - void Resort( int type = 0 ); - - // Puts in dummy start/end samples to spline to zero ( or 0.5 for - // left/right data) at the origins - CExpressionSample *GetBoundedSample( int number, bool& bClamped, int type = 0 ); - - int GetFlexControllerIndex( int side = 0 ); - LocalFlexController_t GetRawFlexControllerIndex( int side = 0 ); - void SetFlexControllerIndex( LocalFlexController_t raw, int index, int side = 0 ); - - // returns 0..1 value for 0..1 time fraction per mag/balance - float GetFracIntensity( float time, int type ); - - // retrieves raw intensity values (for mag vs. left/right slider setting) - float GetSampleIntensity( float time ); - float GetBalanceIntensity( float time ); - - void SetEdgeInfo( bool leftEdge, int curveType, float zero ); - void GetEdgeInfo( bool leftEdge, int& curveType, float& zero ) const; - void SetEdgeActive( bool leftEdge, bool state ); - bool IsEdgeActive( bool leftEdge ) const; - int GetEdgeCurveType( bool leftEdge ) const; - float GetEdgeZeroValue( bool leftEdge ) const; - - float GetDefaultEdgeZeroPos() const; - - void SetServerSide( bool state ); - bool IsServerSide() const; -private: - // remove any samples after endtime - void RemoveOutOfRangeSamples( int type ); - - // returns scaled value for absolute time per mag/balance - float GetIntensityInternal( float time, int type ); - -public: - // returns the fractional (0..1) value for "zero" based on Min/Max ranges - float GetZeroValue( int type, bool leftSide ); - - -private: - char *m_pControllerName; - - // base track has range, combo is always 0..1 - float m_flMin; - float m_flMax; - - // 0 == magnitude - // 1 == left/right - CUtlVector< CExpressionSample > m_Samples[ 2 ]; - int m_nFlexControllerIndex[ 2 ]; - LocalFlexController_t m_nFlexControllerIndexRaw[ 2 ]; - - // For left and right edge of type 0 flex data ( magnitude track ) - EdgeInfo_t m_EdgeInfo[ 2 ]; - - CChoreoEvent *m_pEvent; - - // Is track active - bool m_bActive:1; - - // Is this a combo (magnitude + stereo) track - bool m_bCombo:1; - bool m_bServerSide:1; - - bool m_bInverted; // track is displayed 1..0 instead of 0..1 -}; - - -//----------------------------------------------------------------------------- -// Purpose: The generic scene event type -//----------------------------------------------------------------------------- -class CChoreoEvent : public ICurveDataAccessor -{ -public: - // Type of event this object represents - typedef enum - { - // Don't know yet - UNSPECIFIED = 0, - - // Section start/end - SECTION, - - // Play an expression - EXPRESSION, - - // Look at another actor - LOOKAT, - - // Move to a location - MOVETO, - - // Speak/visemes a wave file - SPEAK, - - // Play a gesture - GESTURE, - - // Play a sequence - SEQUENCE, - - // Face another actor - FACE, - - // Fire a trigger - FIRETRIGGER, - - // One or more flex sliders animated over the course of the event time period - FLEXANIMATION, - - // A contained .vcd file - SUBSCENE, - - // Loop back to previous time (forever or up to N times) - LOOP, - - // A time span during which the scene may be temporarily interrupted - INTERRUPT, - - // A dummy event that is used to mark the .vcd end time - STOPPOINT, - - // A time span during which this actor can respond to events happening in the world, etc. - PERMIT_RESPONSES, - - // A string passed to the game code for interpretation - GENERIC, - - // THIS MUST BE LAST!!! - NUM_TYPES, - } EVENTTYPE; - - enum - { - MAX_TAGNAME_STRING = 128, - MAX_CCTOKEN_STRING = 64, - }; - - typedef enum - { - DEFAULT = 0, - SIMULATION, - DISPLAY, - } TIMETYPE; - - typedef enum - { - CC_MASTER = 0, // default, implied - CC_SLAVE, - CC_DISABLED, - - NUM_CC_TYPES, - } CLOSECAPTION; - - static int s_nGlobalID; - - // Construction - CChoreoEvent( CChoreoScene *scene ); - CChoreoEvent( CChoreoScene *scene, EVENTTYPE type, const char *name ); - CChoreoEvent( CChoreoScene *scene, EVENTTYPE type, const char *name, const char *param ); - - // Assignment - CChoreoEvent& operator=(const CChoreoEvent& src ); - - ~CChoreoEvent( void ); - - // ICurveDataAccessor methods - virtual bool CurveHasEndTime(); - virtual int GetDefaultCurveType(); - - // Binary serialization - void SaveToBuffer( CUtlBuffer& buf, CChoreoScene *pScene, IChoreoStringPool *pStringPool ); - bool RestoreFromBuffer( CUtlBuffer& buf, CChoreoScene *pScene, IChoreoStringPool *pStringPool ); - - // Accessors - EVENTTYPE GetType( void ); - void SetType( EVENTTYPE type ); - - void SetName( const char *name ); - const char *GetName( void ); - - void SetParameters( const char *target ); - const char *GetParameters( void ); - void SetParameters2( const char *target ); - const char *GetParameters2( void ); - void SetParameters3( const char *target ); - const char *GetParameters3( void ); - - void SetStartTime( float starttime ); - float GetStartTime( void ); - - void SetEndTime( float endtime ); - float GetEndTime( void ); - - float GetDuration( void ); - - void SetResumeCondition( bool resumecondition ); - bool IsResumeCondition( void ); - - void SetLockBodyFacing( bool lockbodyfacing ); - bool IsLockBodyFacing( void ); - - void SetDistanceToTarget( float distancetotarget ); - float GetDistanceToTarget( void ); - - void SetForceShortMovement( bool bForceShortMovement ); - bool GetForceShortMovement( void ); - - void SetSyncToFollowingGesture( bool bSyncToFollowingGesture ); - bool GetSyncToFollowingGesture( void ); - - void SetPlayOverScript( bool bPlayOverScript ); - bool GetPlayOverScript( void ); - - int GetRampCount( void ) { return m_Ramp.GetCount(); }; - CExpressionSample *GetRamp( int index ) { return m_Ramp.Get( index ); }; - CExpressionSample *AddRamp( float time, float value, bool selected ) { return m_Ramp.Add( time, value, selected ); }; - void DeleteRamp( int index ) { m_Ramp.Delete( index ); }; - void ClearRamp( void ) { m_Ramp.Clear(); }; - void ResortRamp( void ) { m_Ramp.Resort( this ); }; - CCurveData *GetRamp( void ) { return &m_Ramp; }; - - float GetRampIntensity( float time ) { return m_Ramp.GetIntensity( this, time ); }; - - // Calculates weighting for a given time - float GetIntensity( float scenetime ); - float GetIntensityArea( float scenetime ); - - // Calculates 0..1 completion for a given time - float GetCompletion( float time ); - - // An end time of -1.0f means that the events is just triggered at the leading edge - bool HasEndTime( void ); - - // Is the event something that can be sized ( a wave file, e.g. ) - bool IsFixedLength( void ); - void SetFixedLength( bool isfixedlength ); - - // Move the start/end/both times by the specified dt (fixes up -1.0f endtimes) - void OffsetStartTime( float dt ); - void OffsetEndTime( float dt ); - void OffsetTime( float dt ); - - // Snap to scene framerate - void SnapTimes( void ); - float SnapTime( float t ); - - CChoreoScene *GetScene( void ); - void SetScene( CChoreoScene *scene ); - - // The actor the event is associated with - void SetActor( CChoreoActor *actor ); - CChoreoActor *GetActor( void ); - - // The channel the event is associated with - void SetChannel( CChoreoChannel *channel ); - CChoreoChannel *GetChannel( void ); - - // Get a more involved description of the event - const char *GetDescription( void ); - - void ClearAllRelativeTags( void ); - int GetNumRelativeTags( void ); - CEventRelativeTag *GetRelativeTag( int tagnum ); - CEventRelativeTag *FindRelativeTag( const char *tagname ); - void AddRelativeTag( const char *tagname, float percentage ); - void RemoveRelativeTag( const char *tagname ); - - bool IsUsingRelativeTag( void ); - void SetUsingRelativeTag( bool usetag, const char *tagname = 0, const char *wavname = 0); - const char *GetRelativeTagName( void ); - const char *GetRelativeWavName( void ); - - // Absolute tags - typedef enum - { - PLAYBACK = 0, // new timeline - FIXME: should be stored as an absolute time - ORIGINAL, // original timeline - FIXME: should be stored at a fixed percentage of event - - NUM_ABS_TAG_TYPES, - } AbsTagType; - - void SetGestureSequenceDuration( float duration ); - bool GetGestureSequenceDuration( float& duration ); - - void ClearAllAbsoluteTags( AbsTagType type ); - int GetNumAbsoluteTags( AbsTagType type ); - CEventAbsoluteTag *GetAbsoluteTag( AbsTagType type, int tagnum ); - CEventAbsoluteTag *FindAbsoluteTag( AbsTagType type, const char *tagname ); - void AddAbsoluteTag( AbsTagType type, const char *tagname, float t ); - void RemoveAbsoluteTag( AbsTagType type, const char *tagname ); - bool VerifyTagOrder( void ); - float GetOriginalPercentageFromPlaybackPercentage( float t ); - float GetPlaybackPercentageFromOriginalPercentage( float t ); - - static const char *NameForAbsoluteTagType( AbsTagType t ); - static AbsTagType TypeForAbsoluteTagName( const char *name ); - - void RescaleGestureTimes( float newstart, float newend, bool bMaintainAbsoluteTagPositions ); - bool PreventTagOverlap( void ); - - CEventAbsoluteTag *FindEntryTag( AbsTagType type ); - CEventAbsoluteTag *FindExitTag( AbsTagType type ); - - // Flex animation type - int GetNumFlexAnimationTracks( void ); - CFlexAnimationTrack *GetFlexAnimationTrack( int index ); - CFlexAnimationTrack *AddTrack( const char *controllername ); - CFlexAnimationTrack *FindTrack( const char *controllername ); - void RemoveTrack( int index ); - void RemoveAllTracks( void ); - void OnEndTimeChanged( void ); - - bool GetTrackLookupSet( void ); - void SetTrackLookupSet( bool set ); - - // Flex Timing Tags (used by editor only) - void ClearAllTimingTags( void ); - int GetNumTimingTags( void ); - CFlexTimingTag *GetTimingTag( int tagnum ); - CFlexTimingTag *FindTimingTag( const char *tagname ); - void AddTimingTag( const char *tagname, float percentage, bool locked ); - void RemoveTimingTag( const char *tagname ); - - // Subscene ( embedded .vcd ) support - void SetSubScene( CChoreoScene *scene ); - CChoreoScene *GetSubScene( void ); - - bool IsProcessing( void ) const; - void StartProcessing( IChoreoEventCallback *cb, CChoreoScene *scene, float t ); - void ContinueProcessing( IChoreoEventCallback *cb, CChoreoScene *scene, float t ); - void StopProcessing( IChoreoEventCallback *cb, CChoreoScene *scene, float t ); - bool CheckProcessing( IChoreoEventCallback *cb, CChoreoScene *scene, float t ); - void ResetProcessing( void ); - - void SetMixer( CAudioMixer *mixer ); - CAudioMixer *GetMixer( void ) const; - - // Hack for LOOKAT in editor - int GetPitch( void ) const; - void SetPitch( int pitch ); - int GetYaw( void ) const; - void SetYaw( int yaw ); - - // For LOOP events - void SetLoopCount( int numloops ); - int GetLoopCount( void ); - int GetNumLoopsRemaining( void ); - void SetNumLoopsRemaining( int loops ); - - bool IsMarkedForSave() const { return m_bMarkedForSave; } - void SetMarkedForSave( bool mark ) { m_bMarkedForSave = mark; } - - void GetMovementStyle( char *style, int maxlen ); - void GetDistanceStyle( char *style, int maxlen ); - - int GetGlobalID() const { return m_nGlobalID; } - - // Localization/CC support (close captioning and multiple wave file recombination) - void SetCloseCaptionType( CLOSECAPTION type ); - CLOSECAPTION GetCloseCaptionType() const; - void SetCloseCaptionToken( char const *token ); - char const *GetCloseCaptionToken() const; - void SetUsingCombinedFile( bool isusing ); - bool IsUsingCombinedFile() const; - void SetRequiredCombinedChecksum( unsigned int checksum ); - unsigned int GetRequiredCombinedChecksum(); - void SetNumSlaves( int num ); - int GetNumSlaves() const; - void SetLastSlaveEndTime( float t ); - float GetLastSlaveEndTime() const; - void SetCloseCaptionTokenValid( bool valid ); - bool GetCloseCaptionTokenValid() const; - - bool ComputeCombinedBaseFileName( char *dest, int destlen, bool creategenderwildcard ); - bool IsCombinedUsingGenderToken() const; - void SetCombinedUsingGenderToken( bool using_gender ); - - bool IsSuppressingCaptionAttenuation() const; - void SetSuppressingCaptionAttenuation( bool suppress ); - - int ValidateCombinedFile(); - - // This returns false if the wave is CC_DISABLED or is a CC_SLAVE, - // otherwise it returns the actual m_szCCToken value, or if that's - // blank it'll return the sounds.txt entry name (m_szParameters) - bool GetPlaybackCloseCaptionToken( char *dest, int destlen ); - - void ClearEventDependencies(); - void AddEventDependency( CChoreoEvent *other ); - void GetEventDependencies( CUtlVector< CChoreoEvent * >& list ); - - void SetActive( bool state ); - bool GetActive() const; - - void SetDefaultCurveType( int nCurveType ); - - // Turn enum into string and vice versa - static EVENTTYPE TypeForName( const char *name ); - static const char *NameForType( EVENTTYPE type ); - - // Turn enum into string and vice versa - static CLOSECAPTION CCTypeForName( const char *name ); - static const char *NameForCCType( CLOSECAPTION type ); - -private: - - // Declare copy constructor private to prevent accidental usage... - CChoreoEvent(const CChoreoEvent& src ); - - void SaveFlexAnimationsToBuffer( CUtlBuffer& buf, IChoreoStringPool *pStringPool ); - bool RestoreFlexAnimationsFromBuffer( CUtlBuffer& buf, IChoreoStringPool *pStringPool ); - - float GetBoundedAbsoluteTagPercentage( AbsTagType type, int tagnum ); - - float _GetIntensity( float time ); - - // String bounds - enum - { - MAX_CHOREOEVENT_NAME = 128, - MAX_PARAMETERS_STRING = 128, - }; - - // Base initialization - void Init( CChoreoScene *scene ); - - // Type of event - byte m_fType; - - // Close caption type - byte m_ccType; - - // Name of event - ChoreoStr_t m_Name; - - // Event parameters - ChoreoStr_t m_Parameters; - ChoreoStr_t m_Parameters2; - ChoreoStr_t m_Parameters3; - - // Event start time - float m_flStartTime; - - // Event end time ( -1.0f means no ending, just leading edge triggered ) - float m_flEndTime; - - // Duration of underlying gesture sequence - float m_flGestureSequenceDuration; - - // For CChoreoEvent::LOOP - int m_nNumLoops; // -1 == no limit - int m_nLoopsRemaining; - - // Overall intensity curve - CCurveData m_Ramp; - - // Start time is computed based on length of item referenced by tagged name - ChoreoStr_t m_TagName; - ChoreoStr_t m_TagWavName; - - // Associated actor - CChoreoActor *m_pActor; - // Associated channel - CChoreoChannel *m_pChannel; - - CUtlVector < CEventRelativeTag > m_RelativeTags; - CUtlVector < CFlexTimingTag > m_TimingTags; - CUtlVector < CEventAbsoluteTag > m_AbsoluteTags[ NUM_ABS_TAG_TYPES ]; - - CUtlVector < CFlexAnimationTrack * > m_FlexAnimationTracks; - - CChoreoScene *m_pSubScene; - CAudioMixer *m_pMixer; - - // Scene which owns this event - CChoreoScene *m_pScene; - - int m_nPitch; - int m_nYaw; - - float m_flDistanceToTarget; - - int m_nGlobalID; - - ChoreoStr_t m_CCToken; - unsigned int m_uRequiredCombinedChecksum; - // on master only, the combined file must have the same checksum to be useable - int m_nNumSlaves; - // Only set on master, helps UI draw underbar - float m_flLastSlaveEndTime; - // true if the cc token was found in the cc manager's database - - CUtlVector< CChoreoEvent * > m_Dependencies; - - int m_nDefaultCurveType; - -public: - // used only during scrubbing of looping sequences - float m_flPrevCycle; - float m_flPrevTime; - - // Flags - - bool m_bFixedLength:1; - // True if this event must be "finished" before the next section can be started - // after playback is paused from a globalevent - bool m_bResumeCondition:1; - bool m_bUsesTag:1; - bool m_bTrackLookupSet:1; - bool m_bProcessing:1; - bool m_bLockBodyFacing:1; - // Purely for save/load - bool m_bMarkedForSave:1; - bool m_bUsingCombinedSoundFile:1; - bool m_bCCTokenValid:1; - bool m_bCombinedUsingGenderToken:1; - - bool m_bSuppressCaptionAttenuation:1; - - bool m_bForceShortMovement:1; - bool m_bSyncToFollowingGesture:1; - bool m_bActive:1; - bool m_bPlayOverScript:1; -}; - -#endif // CHOREOEVENT_H diff --git a/game/shared/choreoscene.cpp b/game/shared/choreoscene.cpp deleted file mode 100644 index 39c92e54b..000000000 --- a/game/shared/choreoscene.cpp +++ /dev/null @@ -1,3784 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - - -#if defined(_WIN32) && !defined(_X360) -#include -#endif - -#include "basetypes.h" -#include -#include "choreoscene.h" -#include "choreoevent.h" -#include "choreochannel.h" -#include "choreoactor.h" -#include "ichoreoeventcallback.h" -#include "iscenetokenprocessor.h" -#include "utlbuffer.h" -#include "filesystem.h" -#include "utlrbtree.h" -#include "mathlib/mathlib.h" -#include "tier1/strtools.h" -#include "tier2/tier2.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#ifdef _MSC_VER -#pragma warning( disable : 4127 ) -#endif - -// Let scene linger for 1/4 second so blends can finish -#define SCENE_LINGER_TIME 0.25f - -// The engine turns this to true in dlls/sceneentity.cpp at bool SceneCacheInit()!!! -bool CChoreoScene::s_bEditingDisabled = false; - -//----------------------------------------------------------------------------- -// Purpose: Creates scene from a file -// Input : *filename - -// *pfn - -// Output : CChoreoScene -//----------------------------------------------------------------------------- -CChoreoScene *ChoreoLoadScene( - char const *filename, - IChoreoEventCallback *callback, - ISceneTokenProcessor *tokenizer, - void ( *pfn ) ( const char *fmt, ... ) ) -{ - MEM_ALLOC_CREDIT(); - CChoreoScene *scene = new CChoreoScene( callback ); - Assert( scene ); - scene->ParseFromBuffer( filename, tokenizer ); - scene->SetPrintFunc( pfn ); - return scene; -} - -bool IsBufferBinaryVCD( char *pBuffer, int bufferSize ) -{ - if ( bufferSize > 4 && *(int *)pBuffer == SCENE_BINARY_TAG ) - { - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Debug printout -// Input : level - -// *fmt - -// ... - -//----------------------------------------------------------------------------- -void CChoreoScene::choreoprintf( int level, const char *fmt, ... ) -{ - char string[ 2048 ]; - va_list argptr; - va_start( argptr, fmt ); - Q_vsnprintf( string, sizeof(string), fmt, argptr ); - va_end( argptr ); - - while ( level-- > 0 ) - { - if (m_pfnPrint ) - { - (*m_pfnPrint)( " " ); - } - else - { - printf( " " ); - } - Msg( " " ); - } - - if ( m_pfnPrint ) - { - (*m_pfnPrint)( string ); - } - else - { - printf( string ); - } - - Msg( "%s", string ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CChoreoScene::CChoreoScene( IChoreoEventCallback *callback ) -{ - Init( callback ); -} - - -//----------------------------------------------------------------------------- -// Purpose: // Assignment -// Input : src - -// Output : CChoreoScene& -//----------------------------------------------------------------------------- -CChoreoScene& CChoreoScene::operator=( const CChoreoScene& src ) -{ - Init( src.m_pIChoreoEventCallback ); - - // Delete existing - int i; - for ( i = 0; i < m_Actors.Size(); i++ ) - { - CChoreoActor *a = m_Actors[ i ]; - Assert( a ); - delete a; - } - - m_Actors.RemoveAll(); - - for ( i = 0; i < m_Events.Size(); i++ ) - { - CChoreoEvent *e = m_Events[ i ]; - Assert( e ); - delete e; - } - - m_Events.RemoveAll(); - - for ( i = 0 ; i < m_Channels.Size(); i++ ) - { - CChoreoChannel *c = m_Channels[ i ]; - Assert( c ); - delete c; - } - - m_Channels.RemoveAll(); - - m_pTokenizer = src.m_pTokenizer; - - m_flCurrentTime = src.m_flCurrentTime; - m_flStartTime = src.m_flStartTime; - m_flEndTime = src.m_flEndTime; - m_flSoundSystemLatency = src.m_flSoundSystemLatency; - m_pfnPrint = src.m_pfnPrint; - m_flLastActiveTime = src.m_flLastActiveTime; - m_pTokenizer = src.m_pTokenizer; - m_bSubScene = src.m_bSubScene; - m_nSceneFPS = src.m_nSceneFPS; - m_bUseFrameSnap = src.m_bUseFrameSnap; - m_bIgnorePhonemes = src.m_bIgnorePhonemes; - - // Now copy the object tree - // First copy the global events - - for ( i = 0; i < src.m_Events.Size(); i++ ) - { - CChoreoEvent *event = src.m_Events[ i ]; - if ( event->GetActor() == NULL ) - { - MEM_ALLOC_CREDIT(); - - // Copy it - CChoreoEvent *newEvent = AllocEvent(); - *newEvent = *event; - } - } - - // Finally, push actors, channels, events onto global stacks - for ( i = 0; i < src.m_Actors.Size(); i++ ) - { - CChoreoActor *actor = src.m_Actors[ i ]; - CChoreoActor *newActor = AllocActor(); - *newActor = *actor; - - for ( int j = 0; j < newActor->GetNumChannels() ; j++ ) - { - CChoreoChannel *ch = newActor->GetChannel( j ); - m_Channels.AddToTail( ch ); - - for ( int k = 0; k < ch->GetNumEvents(); k++ ) - { - CChoreoEvent *ev = ch->GetEvent( k ); - m_Events.AddToTail( ev ); - ev->SetScene( this ); - } - } - } - - Q_strncpy( m_szMapname, src.m_szMapname, sizeof( m_szMapname ) ); - - m_SceneRamp = src.m_SceneRamp; - - m_TimeZoomLookup.RemoveAll(); - for ( i = 0; i < (int)src.m_TimeZoomLookup.Count(); i++ ) - { - m_TimeZoomLookup.Insert( src.m_TimeZoomLookup.GetElementName( i ), src.m_TimeZoomLookup[ i ] ); - } - - Q_strncpy( m_szFileName, src.m_szFileName, sizeof( m_szFileName ) ); - - m_nLastPauseEvent = src.m_nLastPauseEvent; - m_flPrecomputedStopTime = src.m_flPrecomputedStopTime; - - m_bitvecHasEventOfType = src.m_bitvecHasEventOfType; - - return *this; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoScene::Init( IChoreoEventCallback *callback ) -{ - m_flPrecomputedStopTime = 0.0f; - m_pTokenizer = NULL; - m_szMapname[ 0 ] = 0; - - m_flCurrentTime = 0.0f; - m_flStartTime = 0.0f; - m_flEndTime = 0.0f; - m_flSoundSystemLatency = 0.0f; - m_pfnPrint = NULL; - m_flLastActiveTime = 0.0f; - m_flEarliestTime = 0.0f; - m_flLatestTime = 0.0f; - m_nActiveEvents = 0; - - m_pIChoreoEventCallback = callback; - - m_bSubScene = false; - m_nSceneFPS = DEFAULT_SCENE_FPS; - m_bUseFrameSnap = false; - m_szFileName[0] = 0; - - m_bIsBackground = false; - m_bitvecHasEventOfType.ClearAll(); - m_nLastPauseEvent = -1; - m_bIgnorePhonemes = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Destroy objects and queues -//----------------------------------------------------------------------------- -CChoreoScene::~CChoreoScene( void ) -{ - int i; - for ( i = 0; i < m_Actors.Size(); i++ ) - { - CChoreoActor *a = m_Actors[ i ]; - Assert( a ); - delete a; - } - - m_Actors.RemoveAll(); - - for ( i = 0; i < m_Events.Size(); i++ ) - { - CChoreoEvent *e = m_Events[ i ]; - Assert( e ); - delete e; - } - - m_Events.RemoveAll(); - - for ( i = 0 ; i < m_Channels.Size(); i++ ) - { - CChoreoChannel *c = m_Channels[ i ]; - Assert( c ); - delete c; - } - - m_Channels.RemoveAll(); -} - - -//----------------------------------------------------------------------------- -// Ignore phonemes -//----------------------------------------------------------------------------- -void CChoreoScene::IgnorePhonemes( bool bIgnore ) -{ - m_bIgnorePhonemes = bIgnore; -} - -bool CChoreoScene::ShouldIgnorePhonemes() const -{ - return m_bIgnorePhonemes; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *callback - -//----------------------------------------------------------------------------- -void CChoreoScene::SetEventCallbackInterface( IChoreoEventCallback *callback ) -{ - m_pIChoreoEventCallback = callback; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : level - -// *e - -//----------------------------------------------------------------------------- -void CChoreoScene::PrintEvent( int level, CChoreoEvent *e ) -{ - choreoprintf( level, "event %s \"%s\"\n", CChoreoEvent::NameForType( e->GetType() ), e->GetName() ); - choreoprintf( level, "{\n" ); - choreoprintf( level + 1, "time %f %f\n", e->GetStartTime(), e->GetEndTime() ); - choreoprintf( level + 1, "param \"%s\"\n", e->GetParameters() ); - if ( strlen( e->GetParameters2() ) > 0 ) - { - choreoprintf( level + 1, "param2 \"%s\"\n", e->GetParameters2() ); - } - if ( strlen( e->GetParameters3() ) > 0 ) - { - choreoprintf( level + 1, "param3 \"%s\"\n", e->GetParameters3() ); - } - choreoprintf( level, "}\n" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : level - -// *c - -//----------------------------------------------------------------------------- -void CChoreoScene::PrintChannel( int level, CChoreoChannel *c ) -{ - choreoprintf( level, "channel \"%s\"\n", c->GetName() ); - choreoprintf( level, "{\n" ); - - for ( int i = 0; i < c->GetNumEvents(); i++ ) - { - CChoreoEvent *e = c->GetEvent( i ); - if ( e ) - { - PrintEvent( level + 1, e ); - } - } - - choreoprintf( level, "}\n" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : level - -// *a - -//----------------------------------------------------------------------------- -void CChoreoScene::PrintActor( int level, CChoreoActor *a ) -{ - choreoprintf( level, "actor \"%s\"\n", a->GetName() ); - choreoprintf( level, "{\n" ); - - for ( int i = 0; i < a->GetNumChannels(); i++ ) - { - CChoreoChannel *c = a->GetChannel( i ); - if ( c ) - { - PrintChannel( level + 1, c ); - } - } - - choreoprintf( level, "}\n\n" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoScene::Print( void ) -{ - // Look for events that don't have actor/channel set - int i; - - for ( i = 0 ; i < m_Events.Size(); i++ ) - { - CChoreoEvent *e = m_Events[ i ]; - if ( e->GetActor() ) - continue; - - PrintEvent( 0, e ); - } - - for ( i = 0 ; i < m_Actors.Size(); i++ ) - { - CChoreoActor *a = m_Actors[ i ]; - if ( !a ) - continue; - - PrintActor( 0, a ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: prints if m_pfnPrint is active -// Output : -//----------------------------------------------------------------------------- - -void CChoreoScene::SceneMsg( const char *pFormat, ... ) -{ - char string[ 2048 ]; - va_list argptr; - va_start( argptr, pFormat ); - Q_vsnprintf( string, sizeof(string), pFormat, argptr ); - va_end( argptr ); - - if ( m_pfnPrint ) - { - (*m_pfnPrint)( string ); - } - else - { - Msg( "%s", string ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoEvent -//----------------------------------------------------------------------------- -CChoreoEvent *CChoreoScene::AllocEvent( void ) -{ - MEM_ALLOC_CREDIT_CLASS(); - CChoreoEvent *e = new CChoreoEvent( this ); - Assert( e ); - m_Events.AddToTail( e ); - return e; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoChannel -//----------------------------------------------------------------------------- -CChoreoChannel *CChoreoScene::AllocChannel( void ) -{ - MEM_ALLOC_CREDIT_CLASS(); - CChoreoChannel *c = new CChoreoChannel(); - Assert( c ); - m_Channels.AddToTail( c ); - return c; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoActor -//----------------------------------------------------------------------------- -CChoreoActor *CChoreoScene::AllocActor( void ) -{ - MEM_ALLOC_CREDIT_CLASS(); - CChoreoActor *a = new CChoreoActor; - Assert( a ); - m_Actors.AddToTail( a ); - return a; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -// Output : CChoreoActor -//----------------------------------------------------------------------------- -CChoreoActor *CChoreoScene::FindActor( const char *name ) -{ - for ( int i = 0; i < m_Actors.Size(); i++ ) - { - CChoreoActor *a = m_Actors[ i ]; - if ( !a ) - continue; - - if ( !Q_stricmp( a->GetName(), name ) ) - return a; - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CChoreoScene::GetNumEvents( void ) -{ - return m_Events.Size(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : event - -// Output : CChoreoEvent -//----------------------------------------------------------------------------- -CChoreoEvent *CChoreoScene::GetEvent( int event ) -{ - if ( event < 0 || event >= m_Events.Size() ) - return NULL; - - return m_Events[ event ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CChoreoScene::GetNumActors( void ) -{ - return m_Actors.Size(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : actor - -// Output : CChoreoActor -//----------------------------------------------------------------------------- -CChoreoActor *CChoreoScene::GetActor( int actor ) -{ - if ( actor < 0 || actor >= GetNumActors() ) - return NULL; - return m_Actors[ actor ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CChoreoScene::GetNumChannels( void ) -{ - return m_Channels.Size(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : channel - -// Output : CChoreoChannel -//----------------------------------------------------------------------------- -CChoreoChannel *CChoreoScene::GetChannel( int channel ) -{ - if ( channel < 0 || channel >= GetNumChannels() ) - return NULL; - return m_Channels[ channel ]; -} - -void CChoreoScene::ParseRamp( ISceneTokenProcessor *tokenizer, CChoreoEvent *e ) -{ - e->GetRamp()->Parse( tokenizer, e ); -} - -void CChoreoScene::ParseSceneRamp( ISceneTokenProcessor *tokenizer, CChoreoScene *scene ) -{ - scene->m_SceneRamp.Parse( tokenizer, scene ); -} - -void CCurveData::Parse( ISceneTokenProcessor *tokenizer, ICurveDataAccessor *data ) -{ - Clear(); - - tokenizer->GetToken( true ); - - if ( !Q_stricmp( tokenizer->CurrentToken(), "leftedge" ) ) - { - CChoreoScene::ParseEdgeInfo( tokenizer, &m_RampEdgeInfo[ 0 ] ); - } - - if ( !Q_stricmp( tokenizer->CurrentToken(), "rightedge" ) ) - { - CChoreoScene::ParseEdgeInfo( tokenizer, &m_RampEdgeInfo[ 1 ] ); - } - - if ( stricmp( tokenizer->CurrentToken(), "{" ) ) - tokenizer->Error( "expecting {\n" ); - - while ( 1 ) - { - // Parse until } - tokenizer->GetToken( true ); - - if ( strlen( tokenizer->CurrentToken() ) <= 0 ) - { - tokenizer->Error( "expecting ramp data\n" ); - break; - } - - if ( !Q_stricmp( tokenizer->CurrentToken(), "}" ) ) - break; - - CUtlVector< CExpressionSample > samples; - - float time = (float)atof( tokenizer->CurrentToken() ); - tokenizer->GetToken( false ); - float value = (float)atof( tokenizer->CurrentToken() ); - - // Add to counter - int idx = samples.AddToTail(); - CExpressionSample *s = &samples[ idx ]; - - s->time = time; - s->value = value; - - // If there are more tokens on this line, then it's a new format curve name - if ( tokenizer->TokenAvailable() ) - { - tokenizer->GetToken( false ); - int curveType = Interpolator_CurveTypeForName( tokenizer->CurrentToken() ); - s->SetCurveType( curveType ); - } - - if ( samples.Size() >= 1 ) - { - for ( int i = 0; i < samples.Size(); i++ ) - { - CExpressionSample sample = samples[ i ]; - - CExpressionSample *newSample = Add( sample.time, sample.value, false ); - newSample->SetCurveType( sample.GetCurveType() ); - } - } - } - - Resort( data ); -} - -//----------------------------------------------------------------------------- -// Purpose: Helper for restoring edge info -// Input : *edgeinfo - -//----------------------------------------------------------------------------- -void CChoreoScene::ParseEdgeInfo( ISceneTokenProcessor *tokenizer, EdgeInfo_t *edgeinfo ) -{ - Assert( edgeinfo ); - Assert( tokenizer ); - - tokenizer->GetToken( false ); - edgeinfo->m_bActive = true; - edgeinfo->m_CurveType = Interpolator_CurveTypeForName( tokenizer->CurrentToken() ); - tokenizer->GetToken( false ); - edgeinfo->m_flZeroPos = atof( tokenizer->CurrentToken() ); - tokenizer->GetToken( true ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *tokenizer - -// *e - -//----------------------------------------------------------------------------- -void CChoreoScene::ParseFlexAnimations( ISceneTokenProcessor *tokenizer, CChoreoEvent *e, bool removeold /*= true*/ ) -{ - Assert( e ); - - if ( removeold ) - { - // Make sure there's nothing already there... - e->RemoveAllTracks(); - // Make it re-index - e->SetTrackLookupSet( false ); - } - - // BACKWARD COMPATABILITY - // in the old system the samples were 0.0 to 1.0 mapped to endtime - starttime - // if samples_use_time is true, then samples are actually offsets of time from starttime - bool samples_use_realtime = false; - // Parse tags between { } - // - tokenizer->GetToken( true ); - - Assert( e->HasEndTime() ); - - float endtime = e->GetEndTime(); - float starttime = e->GetStartTime(); - float event_time = endtime - starttime; - int nDefaultCurveType = CURVE_DEFAULT; - - // Is it the new file format? - if ( !Q_stricmp( tokenizer->CurrentToken(), "samples_use_time" ) ) - { - samples_use_realtime = true; - tokenizer->GetToken( true ); - } - - // Check for default curve type - if ( !Q_strnicmp( tokenizer->CurrentToken(), "defaultcurvetype", 16 ) ) - { - const char *pTest = tokenizer->CurrentToken() + 16; - if ( *pTest == 0 ) - { - tokenizer->GetToken( true ); - pTest = tokenizer->CurrentToken(); - } - - if ( *pTest != '=' ) - { - tokenizer->Error( "expecting =\n" ); - } - ++pTest; - if ( *pTest == 0 ) - { - tokenizer->GetToken( true ); - pTest = tokenizer->CurrentToken(); - } - - nDefaultCurveType = Interpolator_CurveTypeForName( pTest ); - tokenizer->GetToken( true ); - e->SetDefaultCurveType( nDefaultCurveType ); - } - - if ( stricmp( tokenizer->CurrentToken(), "{" ) ) - { - tokenizer->Error( "expecting {\n" ); - } - - while ( 1 ) - { - // Parse until } - tokenizer->GetToken( true ); - - if ( strlen( tokenizer->CurrentToken() ) <= 0 ) - { - tokenizer->Error( "expecting flex animation data\n" ); - break; - } - - if ( !Q_stricmp( tokenizer->CurrentToken(), "}" ) ) - break; - - char flexcontroller[ CFlexAnimationTrack::MAX_CONTROLLER_NAME ]; - Q_strncpy( flexcontroller, tokenizer->CurrentToken(), sizeof( flexcontroller ) ); - - // Animations default to active - bool active = true; - bool combo = false; - float range_min = 0.0f; - float range_max = 1.0f; - tokenizer->GetToken( true ); - - EdgeInfo_t edgeinfo[ 2 ]; - - if ( !Q_stricmp( tokenizer->CurrentToken(), "disabled" ) ) - { - active = false; - tokenizer->GetToken( true ); - } - - if ( !Q_stricmp( tokenizer->CurrentToken(), "combo" ) ) - { - combo = true; - tokenizer->GetToken( true ); - } - - if ( !Q_stricmp( tokenizer->CurrentToken(), "range" ) ) - { - tokenizer->GetToken( false ); - range_min = atof( tokenizer->CurrentToken() ); - tokenizer->GetToken( false ); - range_max = atof( tokenizer->CurrentToken() ); - tokenizer->GetToken( true ); - } - - if ( !Q_stricmp( tokenizer->CurrentToken(), "leftedge" ) ) - { - ParseEdgeInfo( tokenizer, &edgeinfo[ 0 ] ); - } - - if ( !Q_stricmp( tokenizer->CurrentToken(), "rightedge" ) ) - { - ParseEdgeInfo( tokenizer, &edgeinfo[ 1 ] ); - } - - CUtlVector< CExpressionSample > samples[2]; - - for ( int samplecount = 0; samplecount < ( combo ? 2 : 1 ); samplecount++ ) - { - if ( stricmp( tokenizer->CurrentToken(), "{" ) ) - { - tokenizer->Error( "expecting {\n" ); - } - - while ( 1 ) - { - tokenizer->GetToken( true ); - - if ( strlen( tokenizer->CurrentToken() ) <= 0 ) - { - tokenizer->Error( "expecting flex animation data\n" ); - break; - } - - if ( !Q_stricmp( tokenizer->CurrentToken(), "}" ) ) - break; - - float time = (float)atof( tokenizer->CurrentToken() ); - tokenizer->GetToken( false ); - float value = (float)atof( tokenizer->CurrentToken() ); - - // Add to counter - int idx = samples[ samplecount ].AddToTail(); - - CExpressionSample *s = &samples[ samplecount ][ idx ]; - - if ( samples_use_realtime ) - { - s->time = time; - } - else - { - // Time is an old style fraction (0 to 1) map into real time - s->time = time * event_time; - } - - s->value = value; - - // If there are more tokens on this line, then it's a new format curve name - if ( tokenizer->TokenAvailable() ) - { - tokenizer->GetToken( false ); - int curveType = Interpolator_CurveTypeForName( tokenizer->CurrentToken() ); - s->SetCurveType( curveType ); - } - else - { - s->SetCurveType( nDefaultCurveType ); - } - } - - if ( combo && samplecount == 0 ) - { - tokenizer->GetToken( true ); - } - } - - if ( active || samples[ 0 ].Size() >= 1 ) - { - // Add it in - CFlexAnimationTrack *track = e->AddTrack( flexcontroller ); - Assert( track ); - track->SetTrackActive( active ); - track->SetComboType( combo ); - - track->SetMin( range_min ); - track->SetMax( range_max ); - - for ( int t = 0; t < ( combo ? 2 : 1 ); t++ ) - { - for ( int i = 0; i < samples[ t ].Size(); i++ ) - { - CExpressionSample *sample = &samples[ t ][ i ]; - - CExpressionSample *added = track->AddSample( sample->time, sample->value, t ); - Assert( added ); - added->SetCurveType( sample->GetCurveType() ); - } - } - - for ( int edge = 0; edge < 2; ++edge ) - { - if ( !edgeinfo[ edge ].m_bActive ) - continue; - - track->SetEdgeActive( edge == 0 ? true : false, true ); - track->SetEdgeInfo( edge == 0 ? true : false, edgeinfo[ edge ].m_CurveType, edgeinfo[ edge ].m_flZeroPos ); - } - - track->Resort( 0 ); - track->Resort( 1 ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -// *channel - -// Output : CChoreoEvent -//----------------------------------------------------------------------------- -CChoreoEvent *CChoreoScene::ParseEvent( CChoreoActor *actor, CChoreoChannel *channel ) -{ - // For conversion of old style attack/sustain/decay ramps - bool hadramp = false; - float attack = 1.0f, sustain = 1.0f, decay = 1.0f; - - CChoreoEvent *e; - { - MEM_ALLOC_CREDIT(); - e = AllocEvent(); - } - - MEM_ALLOC_CREDIT(); - - Assert( e ); - - // read event type - m_pTokenizer->GetToken( false ); - - e->SetType( CChoreoEvent::TypeForName( m_pTokenizer->CurrentToken() ) ); - - m_pTokenizer->GetToken( false ); - e->SetName( m_pTokenizer->CurrentToken() ); - - m_pTokenizer->GetToken( true ); - if ( stricmp( m_pTokenizer->CurrentToken(), "{" ) ) - m_pTokenizer->Error( "expecting {\n" ); - - while ( 1 ) - { - m_pTokenizer->GetToken( true ); - if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "}" ) ) - break; - - if ( strlen( m_pTokenizer->CurrentToken() ) <= 0 ) - { - m_pTokenizer->Error( "expecting more tokens!" ); - break; - } - - if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "time" ) ) - { - float start, end = 1.0f; - - m_pTokenizer->GetToken( false ); - start = (float)atof( m_pTokenizer->CurrentToken() ); - if ( m_pTokenizer->TokenAvailable() ) - { - m_pTokenizer->GetToken( false ); - end = (float)atof( m_pTokenizer->CurrentToken() ); - } - - e->SetStartTime( start ); - e->SetEndTime( end ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "ramp" ) ) - { - hadramp = true; - - m_pTokenizer->GetToken( false ); - attack = (float)atof( m_pTokenizer->CurrentToken() ); - if ( m_pTokenizer->TokenAvailable() ) - { - m_pTokenizer->GetToken( false ); - sustain = (float)atof( m_pTokenizer->CurrentToken() ); - } - if ( m_pTokenizer->TokenAvailable() ) - { - m_pTokenizer->GetToken( false ); - decay = (float)atof( m_pTokenizer->CurrentToken() ); - } - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "param" ) ) - { - m_pTokenizer->GetToken( false ); - - e->SetParameters( m_pTokenizer->CurrentToken() ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "param2" ) ) - { - m_pTokenizer->GetToken( false ); - - e->SetParameters2( m_pTokenizer->CurrentToken() ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "param3" ) ) - { - m_pTokenizer->GetToken( false ); - - e->SetParameters3( m_pTokenizer->CurrentToken() ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "pitch" ) ) - { - m_pTokenizer->GetToken( false ); - e->SetPitch( atoi( m_pTokenizer->CurrentToken() ) ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "yaw" ) ) - { - m_pTokenizer->GetToken( false ); - e->SetYaw( atoi( m_pTokenizer->CurrentToken() ) ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "loopcount" ) ) - { - m_pTokenizer->GetToken( false ); - e->SetLoopCount( atoi( m_pTokenizer->CurrentToken() ) ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "resumecondition" ) ) - { - e->SetResumeCondition( true ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "fixedlength" ) ) - { - e->SetFixedLength( true ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "lockbodyfacing" ) ) - { - e->SetLockBodyFacing( true ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "distancetotarget" ) ) - { - m_pTokenizer->GetToken( false ); - e->SetDistanceToTarget( atof( m_pTokenizer->CurrentToken() ) ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "forceshortmovement" ) ) - { - e->SetForceShortMovement( true ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "synctofollowinggesture" ) ) - { - e->SetSyncToFollowingGesture( true ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "active" ) ) - { - m_pTokenizer->GetToken( false ); - e->SetActive( atoi( m_pTokenizer->CurrentToken() ) ? true : false ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "playoverscript" ) ) - { - e->SetPlayOverScript( true ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "tags" ) ) - { - // Parse tags between { } - // - m_pTokenizer->GetToken( true ); - if ( stricmp( m_pTokenizer->CurrentToken(), "{" ) ) - m_pTokenizer->Error( "expecting {\n" ); - - while ( 1 ) - { - // Parse until } - m_pTokenizer->GetToken( true ); - - if ( strlen( m_pTokenizer->CurrentToken() ) <= 0 ) - { - m_pTokenizer->Error( "expecting relative tag\n" ); - break; - } - - if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "}" ) ) - break; - - char tagname[ CEventRelativeTag::MAX_EVENTTAG_LENGTH ]; - float percentage; - - Q_strncpy( tagname, m_pTokenizer->CurrentToken(), sizeof( tagname ) ); - m_pTokenizer->GetToken( false ); - percentage = (float)atof( m_pTokenizer->CurrentToken() ); - - e->AddRelativeTag( tagname, percentage ); - } - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "sequenceduration" ) ) - { - float duration = 0.0f; - - m_pTokenizer->GetToken( false ); - duration = (float)atof( m_pTokenizer->CurrentToken() ); - - e->SetGestureSequenceDuration( duration ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "absolutetags" ) ) - { - m_pTokenizer->GetToken( true ); - CChoreoEvent::AbsTagType tagtype; - - tagtype = CChoreoEvent::TypeForAbsoluteTagName( m_pTokenizer->CurrentToken() ); - - if ( tagtype == (CChoreoEvent::AbsTagType) -1 ) - { - m_pTokenizer->Error( "expecting valid tag type!!!" ); - } - - // Parse tags between { } - // - m_pTokenizer->GetToken( true ); - if ( stricmp( m_pTokenizer->CurrentToken(), "{" ) ) - m_pTokenizer->Error( "expecting {\n" ); - - while ( 1 ) - { - // Parse until } - m_pTokenizer->GetToken( true ); - - if ( strlen( m_pTokenizer->CurrentToken() ) <= 0 ) - { - m_pTokenizer->Error( "expecting relative tag\n" ); - break; - } - - if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "}" ) ) - break; - - char tagname[ CFlexTimingTag::MAX_EVENTTAG_LENGTH ]; - float t; - - Q_strncpy( tagname, m_pTokenizer->CurrentToken(), sizeof( tagname ) ); - m_pTokenizer->GetToken( false ); - t = (float)atof( m_pTokenizer->CurrentToken() ); - - e->AddAbsoluteTag( tagtype, tagname, t ); - } - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "flextimingtags" ) ) - { - // Parse tags between { } - // - m_pTokenizer->GetToken( true ); - if ( stricmp( m_pTokenizer->CurrentToken(), "{" ) ) - m_pTokenizer->Error( "expecting {\n" ); - - while ( 1 ) - { - // Parse until } - m_pTokenizer->GetToken( true ); - - if ( strlen( m_pTokenizer->CurrentToken() ) <= 0 ) - { - m_pTokenizer->Error( "expecting relative tag\n" ); - break; - } - - if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "}" ) ) - break; - - char tagname[ CFlexTimingTag::MAX_EVENTTAG_LENGTH ]; - float percentage; - bool locked; - - Q_strncpy( tagname, m_pTokenizer->CurrentToken(), sizeof( tagname ) ); - m_pTokenizer->GetToken( false ); - percentage = (float)atof( m_pTokenizer->CurrentToken() ); - - m_pTokenizer->GetToken( false ); - locked = atoi( m_pTokenizer->CurrentToken() ) ? true : false; - - e->AddTimingTag( tagname, percentage, locked ); - } - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "relativetag" ) ) - { - char tagname[ CChoreoEvent::MAX_TAGNAME_STRING ]; - char wavname[ CChoreoEvent::MAX_TAGNAME_STRING ]; - - m_pTokenizer->GetToken( false ); - Q_strncpy( tagname, m_pTokenizer->CurrentToken(), sizeof( tagname ) ); - m_pTokenizer->GetToken( false ); - Q_strncpy( wavname, m_pTokenizer->CurrentToken(), sizeof( wavname ) ); - - e->SetUsingRelativeTag( true, tagname, wavname ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "flexanimations" ) ) - { - ParseFlexAnimations( m_pTokenizer, e ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "event_ramp" ) ) - { - ParseRamp( m_pTokenizer, e ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "cctype" ) ) - { - m_pTokenizer->GetToken( false ); - e->SetCloseCaptionType( CChoreoEvent::CCTypeForName( m_pTokenizer->CurrentToken() ) ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "cctoken" ) ) - { - m_pTokenizer->GetToken( false ); - e->SetCloseCaptionToken( m_pTokenizer->CurrentToken() ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "cc_usingcombinedfile" ) ) - { - e->SetUsingCombinedFile( true ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "cc_combinedusesgender" ) ) - { - e->SetCombinedUsingGenderToken( true ); - } - else if( !Q_stricmp( m_pTokenizer->CurrentToken(), "cc_noattenuate" ) ) - { - e->SetSuppressingCaptionAttenuation( true ); - } - } - - if ( channel ) - { - channel->AddEvent( e ); - } - - e->SetActor( actor ); - e->SetChannel( channel ); - - // It had old sytle ramp and none of the new style stuff - // Convert it - if ( hadramp && !e->GetRampCount() ) - { - // Only retrofit if something was changed by user - if ( attack != 1.0f || - sustain != 1.0f || - decay != 1.0f ) - { - float attacktime = ( 1.0f - attack ) * e->GetDuration(); - float decaytime = decay * e->GetDuration(); - float midpoint = ( attacktime + decaytime ) * 0.5f; - - e->AddRamp( attacktime, sustain, false ); - e->AddRamp( midpoint, sustain, false ); - e->AddRamp( decaytime, sustain, false ); - e->ResortRamp(); - } - } - - return e; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CChoreoActor -//----------------------------------------------------------------------------- -CChoreoActor *CChoreoScene::ParseActor( void ) -{ - CChoreoActor *a = AllocActor(); - Assert( a ); - - m_pTokenizer->GetToken( false ); - a->SetName( m_pTokenizer->CurrentToken() ); - - m_pTokenizer->GetToken( true ); - if ( stricmp( m_pTokenizer->CurrentToken(), "{" ) ) - m_pTokenizer->Error( "expecting {" ); - - // Parse channels - while ( 1 ) - { - m_pTokenizer->GetToken( true ); - if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "}" ) ) - break; - - if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "channel" ) ) - { - ParseChannel( a ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "faceposermodel" ) ) - { - ParseFacePoserModel( a ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "active" ) ) - { - m_pTokenizer->GetToken( true ); - a->SetActive( atoi( m_pTokenizer->CurrentToken() ) ? true : false ); - } - else - { - m_pTokenizer->Error( "expecting channel got %s\n", m_pTokenizer->CurrentToken() ); - } - } - - return a; -} - -//----------------------------------------------------------------------------- -// Output : char const -//----------------------------------------------------------------------------- -const char *CChoreoScene::GetMapname( void ) -{ - return m_szMapname; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -//----------------------------------------------------------------------------- -void CChoreoScene::SetMapname( const char *name ) -{ - Q_strncpy( m_szMapname, name, sizeof( m_szMapname ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoScene::ParseMapname( void ) -{ - m_szMapname[ 0 ] = 0; - - m_pTokenizer->GetToken( true ); - Q_strncpy( m_szMapname, m_pTokenizer->CurrentToken(), sizeof( m_szMapname ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoScene::ParseFPS( void ) -{ - m_pTokenizer->GetToken( true ); - m_nSceneFPS = atoi( m_pTokenizer->CurrentToken() ); - // Clamp to valid range - m_nSceneFPS = clamp( m_nSceneFPS, MIN_SCENE_FPS, MAX_SCENE_FPS); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoScene::ParseSnap( void ) -{ - m_pTokenizer->GetToken( true ); - m_bUseFrameSnap = !Q_stricmp( m_pTokenizer->CurrentToken(), "on" ) ? true : false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoScene::ParseIgnorePhonemes( void ) -{ - m_pTokenizer->GetToken( true ); - m_bIgnorePhonemes = !Q_stricmp( m_pTokenizer->CurrentToken(), "on" ) ? true : false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -//----------------------------------------------------------------------------- -void CChoreoScene::ParseFacePoserModel( CChoreoActor *actor ) -{ - m_pTokenizer->GetToken( true ); - actor->SetFacePoserModelName( m_pTokenizer->CurrentToken() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -// Output : CChoreoChannel -//----------------------------------------------------------------------------- -CChoreoChannel *CChoreoScene::ParseChannel( CChoreoActor *actor ) -{ - CChoreoChannel *c = AllocChannel(); - Assert( c ); - - m_pTokenizer->GetToken( false ); - c->SetName( m_pTokenizer->CurrentToken() ); - - m_pTokenizer->GetToken( true ); - if ( stricmp( m_pTokenizer->CurrentToken(), "{" ) ) - m_pTokenizer->Error( "expecting {" ); - - // Parse channels - while ( 1 ) - { - m_pTokenizer->GetToken( true ); - if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "}" ) ) - break; - - if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "event" ) ) - { - ParseEvent( actor, c ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "active" ) ) - { - m_pTokenizer->GetToken( true ); - c->SetActive( atoi( m_pTokenizer->CurrentToken() ) ? true : false ); - } - else - { - m_pTokenizer->Error( "expecting event got %s\n", m_pTokenizer->CurrentToken() ); - } - } - - Assert( actor ); - if ( actor ) - { - actor->AddChannel( c ); - c->SetActor( actor ); - } - - return c; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChoreoScene::ParseFromBuffer( const char *pFilename, ISceneTokenProcessor *tokenizer ) -{ - Q_strncpy( m_szFileName, pFilename, sizeof(m_szFileName) ); - m_pTokenizer = tokenizer; - - while ( 1 ) - { - if ( !m_pTokenizer->GetToken( true ) ) - { - break; - } - - if ( strlen( m_pTokenizer->CurrentToken() ) <= 0 ) - break; - - if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "event" ) ) - { - ParseEvent( NULL, NULL ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "actor" ) ) - { - ParseActor(); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "mapname" ) ) - { - ParseMapname(); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "fps" ) ) - { - ParseFPS(); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "snap" ) ) - { - ParseSnap(); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "ignorePhonemes" ) ) - { - ParseIgnorePhonemes(); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "scene_ramp" ) ) - { - ParseSceneRamp( m_pTokenizer, this ); - } - else if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "scalesettings" ) ) - { - ParseScaleSettings( m_pTokenizer, this ); - } - else - { - m_pTokenizer->Error( "%s: unexpected token %s\n", m_szFileName, m_pTokenizer->CurrentToken() ); - break; - } - } - - // Fixup time tags - ReconcileTags(); - - ReconcileGestureTimes(); - - ReconcileCloseCaption(); - - InternalDetermineEventTypes(); - - if ( CChoreoScene::s_bEditingDisabled ) - { - m_flPrecomputedStopTime = FindStopTime(); - } - - return true; -} - -void CChoreoScene::RemoveEventsExceptTypes( int* typeList, int count ) -{ - int i; - for ( i = 0 ; i < m_Actors.Count(); i++ ) - { - CChoreoActor *a = m_Actors[ i ]; - if ( !a ) - continue; - - for ( int j = 0; j < a->GetNumChannels(); j++ ) - { - CChoreoChannel *c = a->GetChannel( j ); - if ( !c ) - continue; - - int num = c->GetNumEvents(); - for ( int k = num - 1 ; k >= 0; --k ) - { - CChoreoEvent *e = c->GetEvent( k ); - if ( !e ) - continue; - - bool found = false; - for ( int idx = 0; idx < count; ++idx ) - { - if ( e->GetType() == ( CChoreoEvent::EVENTTYPE )typeList[ idx ] ) - { - found = true; - break; - } - } - - if ( !found ) - { - c->RemoveEvent( e ); - DeleteReferencedObjects( e ); - } - } - } - } - - // Remvoe non-matching global events, too - for ( i = m_Events.Count() - 1 ; i >= 0; --i ) - { - CChoreoEvent *e = m_Events[ i ]; - - // This was already dealt with above... - if ( e->GetActor() ) - continue; - - bool found = false; - for ( int idx = 0; idx < count; ++idx ) - { - if ( e->GetType() == ( CChoreoEvent::EVENTTYPE )typeList[ idx ] ) - { - found = true; - break; - } - } - - if ( !found ) - { - DeleteReferencedObjects( e ); - } - } -} - -void CChoreoScene::InternalDetermineEventTypes() -{ - m_bitvecHasEventOfType.ClearAll(); - - for ( int i = 0 ; i < m_Actors.Size(); i++ ) - { - CChoreoActor *a = m_Actors[ i ]; - if ( !a ) - continue; - - for ( int j = 0; j < a->GetNumChannels(); j++ ) - { - CChoreoChannel *c = a->GetChannel( j ); - if ( !c ) - continue; - - for ( int k = 0 ; k < c->GetNumEvents(); k++ ) - { - CChoreoEvent *e = c->GetEvent( k ); - if ( !e ) - continue; - - m_bitvecHasEventOfType.Set( e->GetType(), true ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CChoreoScene::FindStopTime( void ) -{ - if ( m_flPrecomputedStopTime != 0.0f ) - { - return m_flPrecomputedStopTime; - } - - float lasttime = 0.0f; - - int c = m_Events.Count(); - for ( int i = 0; i < c ; i++ ) - { - CChoreoEvent *e = m_Events[ i ]; - Assert( e ); - - float checktime = e->HasEndTime() ? e->GetEndTime() : e->GetStartTime(); - if ( checktime > lasttime ) - { - lasttime = checktime; - } - } - - return lasttime; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *fp - -// level - -// *fmt - -// ... - -//----------------------------------------------------------------------------- -void CChoreoScene::FilePrintf( CUtlBuffer& buf, int level, const char *fmt, ... ) -{ - va_list argptr; - va_start( argptr, fmt ); - - while ( level-- > 0 ) - { - buf.Printf( " " ); - } - - buf.VaPrintf( fmt, argptr ); - va_end( argptr ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *fp - -//----------------------------------------------------------------------------- -void CChoreoScene::FileSaveHeader( CUtlBuffer& buf ) -{ - FilePrintf( buf, 0, "// Choreo version 1\n" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : mark - -//----------------------------------------------------------------------------- -void CChoreoScene::MarkForSaveAll( bool mark ) -{ - int i; - - // Mark global events - for ( i = 0 ; i < m_Events.Size(); i++ ) - { - CChoreoEvent *e = m_Events[ i ]; - if ( e->GetActor() ) - continue; - - e->SetMarkedForSave( mark ); - } - - // Recursively mark everything else - for ( i = 0 ; i < m_Actors.Size(); i++ ) - { - CChoreoActor *a = m_Actors[ i ]; - if ( !a ) - continue; - - a->MarkForSaveAll( mark ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *filename - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChoreoScene::ExportMarkedToFile( const char *filename ) -{ - // Create a serialization buffer - CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); - FileSaveHeader( buf ); - - // Look for events that don't have actor/channel set - int i; - for ( i = 0 ; i < m_Events.Size(); i++ ) - { - CChoreoEvent *e = m_Events[ i ]; - if ( e->GetActor() ) - continue; - - FileSaveEvent( buf, 0, e ); - } - - for ( i = 0 ; i < m_Actors.Size(); i++ ) - { - CChoreoActor *a = m_Actors[ i ]; - if ( !a ) - continue; - - FileSaveActor( buf, 0, a ); - } - - // Write it out baby - FileHandle_t fh = g_pFullFileSystem->Open( filename, "wt" ); - if (fh) - { - g_pFullFileSystem->Write( buf.Base(), buf.TellPut(), fh ); - g_pFullFileSystem->Close(fh); - return true; - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *filename - -//----------------------------------------------------------------------------- -bool CChoreoScene::SaveToFile( const char *filename ) -{ - // Create a serialization buffer - CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); - FileSaveHeader( buf ); - - MarkForSaveAll( true ); - - // Look for events that don't have actor/channel set - int i; - for ( i = 0 ; i < m_Events.Size(); i++ ) - { - CChoreoEvent *e = m_Events[ i ]; - if ( e->GetActor() ) - continue; - - FileSaveEvent( buf, 0, e ); - } - - for ( i = 0 ; i < m_Actors.Size(); i++ ) - { - CChoreoActor *a = m_Actors[ i ]; - if ( !a ) - continue; - - FileSaveActor( buf, 0, a ); - } - - if ( m_szMapname[ 0 ] ) - { - FilePrintf( buf, 0, "mapname \"%s\"\n", m_szMapname ); - } - - FileSaveSceneRamp( buf, 0 ); - FileSaveScaleSettings( buf, 0, this ); - - FilePrintf( buf, 0, "fps %i\n", m_nSceneFPS ); - FilePrintf( buf, 0, "snap %s\n", m_bUseFrameSnap ? "on" : "off" ); - FilePrintf( buf, 0, "ignorePhonemes %s\n", m_bIgnorePhonemes ? "on" : "off" ); - - // Write it out baby - FileHandle_t fh = g_pFullFileSystem->Open( filename, "wt" ); - if (fh) - { - g_pFullFileSystem->Write( buf.Base(), buf.TellPut(), fh ); - g_pFullFileSystem->Close(fh); - return true; - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : buf - -// level - -// *e - -//----------------------------------------------------------------------------- -void CChoreoScene::FileSaveRamp( CUtlBuffer& buf, int level, CChoreoEvent *e ) -{ - e->GetRamp()->FileSave( buf, level, "event_ramp" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : buf - -// level - -// *e - -//----------------------------------------------------------------------------- -void CChoreoScene::FileSaveSceneRamp( CUtlBuffer& buf, int level ) -{ - m_SceneRamp.FileSave( buf, level, "scene_ramp" ); -} - - -void CCurveData::FileSave( CUtlBuffer& buf, int level, const char *name ) -{ - // Nothing to save? - int c = GetCount(); - if ( c <= 0 && - !IsEdgeActive( true ) && - !IsEdgeActive( false ) ) - return; - - char line[ 1024 ]; - Q_strncpy( line, name, sizeof( line ) ); - - if ( IsEdgeActive( true ) || IsEdgeActive( false ) ) - { - if ( IsEdgeActive( true ) ) - { - char sz[ 256 ]; - Q_snprintf( sz, sizeof( sz ), " leftedge %s %.3f", Interpolator_NameForCurveType( GetEdgeCurveType( true ), false ), GetEdgeZeroValue( true ) ); - Q_strncat( line, sz, sizeof( line ), COPY_ALL_CHARACTERS ); - } - if ( IsEdgeActive( false ) ) - { - char sz[ 256 ]; - Q_snprintf( sz, sizeof( sz )," rightedge %s %.3f", Interpolator_NameForCurveType( GetEdgeCurveType( false ), false ), GetEdgeZeroValue( false ) ); - Q_strncat( line, sz, sizeof( line ), COPY_ALL_CHARACTERS ); - } - } - - CChoreoScene::FilePrintf( buf, level, "%s\n", line ); - CChoreoScene::FilePrintf( buf, level, "{\n" ); - - for ( int i = 0; i < c; i++ ) - { - CExpressionSample *sample = Get( i ); - if ( sample->GetCurveType() != CURVE_DEFAULT ) - { - CChoreoScene::FilePrintf( buf, level + 1, "%.4f %.4f \"%s\"\n", - sample->time, - sample->value, - Interpolator_NameForCurveType( sample->GetCurveType(), false ) ); - } - else - { - CChoreoScene::FilePrintf( buf, level + 1, "%.4f %.4f\n", - sample->time, - sample->value ); - } - } - - CChoreoScene::FilePrintf( buf, level, "}\n" ); -} - -void CChoreoScene::FileSaveScaleSettings( CUtlBuffer& buf, int level, CChoreoScene *scene ) -{ - // Nothing to save? - int c = scene->m_TimeZoomLookup.Count(); - if ( c <= 0 ) - return; - - FilePrintf( buf, level, "scalesettings\n" ); - FilePrintf( buf, level, "{\n" ); - - for ( int i = 0; i < c; i++ ) - { - int value = scene->m_TimeZoomLookup[ i ]; - - FilePrintf( buf, level + 1, "\"%s\" \"%i\"\n", - scene->m_TimeZoomLookup.GetElementName( i ), - value ); - } - - FilePrintf( buf, level, "}\n" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : buf - -// level - -// *track - -//----------------------------------------------------------------------------- -void CChoreoScene::FileSaveFlexAnimationTrack( CUtlBuffer& buf, int level, CFlexAnimationTrack *track, int nDefaultCurveType ) -{ - if ( !track ) - return; - - if ( !track->IsTrackActive() && track->GetNumSamples() <= 0 ) - return; - - char line[ 1024 ]; - Q_snprintf( line, sizeof( line ), "\"%s\" ", track->GetFlexControllerName() ); - if ( !track->IsTrackActive() ) - { - char sz[ 256 ]; - Q_snprintf( sz, sizeof( sz ), "disabled " ); - Q_strncat( line, sz, sizeof( line ), COPY_ALL_CHARACTERS ); - } - if ( track->IsComboType() ) - { - char sz[ 256 ]; - Q_snprintf( sz, sizeof( sz ), "combo " ); - Q_strncat( line, sz, sizeof( line ), COPY_ALL_CHARACTERS ); - } - if ( track->GetMin() != 0.0f || track->GetMax() != 1.0f) - { - char sz[ 256 ]; - Q_snprintf( sz, sizeof( sz ), "range %.1f %.1f ", track->GetMin(), track->GetMax() ); - Q_strncat( line, sz, sizeof( line ), COPY_ALL_CHARACTERS ); - } - if ( track->IsEdgeActive( true ) || track->IsEdgeActive( false ) ) - { - char edgestr[ 512 ]; - edgestr[ 0 ] = 0; - - if ( track->IsEdgeActive( true ) ) - { - char sz[ 256 ]; - Q_snprintf( sz, sizeof( sz ), "leftedge %s %.3f ", Interpolator_NameForCurveType( track->GetEdgeCurveType( true ), false ), track->GetEdgeZeroValue( true ) ); - Q_strncat( edgestr, sz, sizeof( edgestr ), COPY_ALL_CHARACTERS ); - } - if ( track->IsEdgeActive( false ) ) - { - char sz[ 256 ]; - Q_snprintf( sz, sizeof( sz ), "rightedge %s %.3f ", Interpolator_NameForCurveType( track->GetEdgeCurveType( false ), false ), track->GetEdgeZeroValue( false ) ); - Q_strncat( edgestr, sz, sizeof( edgestr ), COPY_ALL_CHARACTERS ); - } - - Q_strncat( line, edgestr, sizeof( line ), COPY_ALL_CHARACTERS ); - } - - - FilePrintf( buf, level + 2, "%s\n", line ); - - // Write out samples - FilePrintf( buf, level + 2, "{\n" ); - - for ( int j = 0 ; j < track->GetNumSamples( 0 ) ; j++ ) - { - CExpressionSample *s = track->GetSample( j, 0 ); - if ( !s ) - continue; - - if ( s->GetCurveType() != nDefaultCurveType && s->GetCurveType() != CURVE_DEFAULT ) - { - FilePrintf( buf, level + 3, "%.4f %.4f \"%s\"\n", - s->time, - s->value, - Interpolator_NameForCurveType( s->GetCurveType(), false ) ); - } - else - { - FilePrintf( buf, level + 3, "%.4f %.4f\n", - s->time, - s->value ); - } - } - - FilePrintf( buf, level + 2, "}\n" ); - - // Write out combo samples - if ( track->IsComboType() ) - { - FilePrintf( buf, level + 2, "{\n" ); - - for ( int j = 0 ; j < track->GetNumSamples( 1) ; j++ ) - { - CExpressionSample *s = track->GetSample( j, 1 ); - if ( !s ) - continue; - - if ( s->GetCurveType() != nDefaultCurveType && s->GetCurveType() != CURVE_DEFAULT ) - { - FilePrintf( buf, level + 3, "%.4f %.4f \"%s\"\n", - s->time, - s->value, - Interpolator_NameForCurveType( s->GetCurveType(), false ) ); - } - else - { - FilePrintf( buf, level + 3, "%.4f %.4f\n", - s->time, - s->value ); - } - } - - FilePrintf( buf, level + 2, "}\n" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : buf - -// level - -// *e - -//----------------------------------------------------------------------------- -void CChoreoScene::FileSaveFlexAnimations( CUtlBuffer& buf, int level, CChoreoEvent *e ) -{ - // Nothing to save - if ( e->GetNumFlexAnimationTracks() <= 0 ) - return; - - if ( e->GetDefaultCurveType() != CURVE_DEFAULT ) - { - FilePrintf( buf, level + 1, "flexanimations samples_use_time defaultcurvetype=%s\n", - Interpolator_NameForCurveType( e->GetDefaultCurveType(), false ) ); - } - else - { - FilePrintf( buf, level + 1, "flexanimations samples_use_time\n" ); - } - FilePrintf( buf, level + 1, "{\n" ); - - for ( int i = 0; i < e->GetNumFlexAnimationTracks(); i++ ) - { - CFlexAnimationTrack *track = e->GetFlexAnimationTrack( i ); - FileSaveFlexAnimationTrack( buf, level, track, e->GetDefaultCurveType() ); - } - - FilePrintf( buf, level + 1, "}\n" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *fp - -// level - -// *e - -//----------------------------------------------------------------------------- -void CChoreoScene::FileSaveEvent( CUtlBuffer& buf, int level, CChoreoEvent *e ) -{ - if ( !e->IsMarkedForSave() ) - return; - - FilePrintf( buf, level, "event %s \"%s\"\n", CChoreoEvent::NameForType( e->GetType() ), e->GetName() ); - FilePrintf( buf, level, "{\n" ); - - float st, et; - st = e->GetStartTime(); - et = e->GetEndTime(); - - FilePrintf( buf, level + 1, "time %f %f\n", st, et ); - FilePrintf( buf, level + 1, "param \"%s\"\n", e->GetParameters() ); - if ( strlen( e->GetParameters2() ) > 0 ) - { - FilePrintf( buf, level + 1, "param2 \"%s\"\n", e->GetParameters2() ); - } - if ( strlen( e->GetParameters3() ) > 0 ) - { - FilePrintf( buf, level + 1, "param3 \"%s\"\n", e->GetParameters3() ); - } - if ( e->GetRampCount() > 0 ) - { - FileSaveRamp( buf, level + 1, e ); - } - if ( e->GetPitch() != 0 ) - { - FilePrintf( buf, level + 1, "pitch \"%i\"\n", e->GetPitch() ); - } - if ( e->GetYaw() != 0 ) - { - FilePrintf( buf, level + 1, "yaw \"%i\"\n", e->GetYaw() ); - } - if ( e->IsResumeCondition() ) - { - FilePrintf( buf, level + 1, "resumecondition\n" ); - } - if ( e->IsLockBodyFacing() ) - { - FilePrintf( buf, level + 1, "lockbodyfacing\n" ); - } - if ( e->GetDistanceToTarget() > 0.0f ) - { - FilePrintf( buf, level + 1, "distancetotarget %.2f\n", e->GetDistanceToTarget() ); - } - if ( e->GetForceShortMovement() ) - { - FilePrintf( buf, level + 1, "forceshortmovement\n" ); - } - if ( e->GetSyncToFollowingGesture() ) - { - FilePrintf( buf, level + 1, "synctofollowinggesture\n" ); - } - if ( !e->GetActive() ) - { - FilePrintf( buf, level + 1, "active 0\n" ); - } - if ( e->GetPlayOverScript() ) - { - FilePrintf( buf, level + 1, "playoverscript\n" ); - } - if ( e->IsFixedLength() ) - { - FilePrintf( buf, level + 1, "fixedlength\n" ); - } - if ( e->GetNumRelativeTags() > 0 ) - { - FilePrintf( buf, level + 1, "tags\n" ); - FilePrintf( buf, level + 1, "{\n" ); - for ( int t = 0; t < e->GetNumRelativeTags(); t++ ) - { - CEventRelativeTag *rt = e->GetRelativeTag( t ); - Assert( rt ); - FilePrintf( buf, level + 2, "\"%s\" %f\n", rt->GetName(), rt->GetPercentage() ); - } - FilePrintf( buf, level + 1, "}\n" ); - } - if ( e->GetNumTimingTags() > 0 ) - { - FilePrintf( buf, level + 1, "flextimingtags\n" ); - FilePrintf( buf, level + 1, "{\n" ); - for ( int t = 0; t < e->GetNumTimingTags(); t++ ) - { - CFlexTimingTag *tt = e->GetTimingTag( t ); - Assert( tt ); - FilePrintf( buf, level + 2, "\"%s\" %f %i\n", tt->GetName(), tt->GetPercentage(), tt->GetLocked() ? 1 : 0 ); - } - FilePrintf( buf, level + 1, "}\n" ); - } - int tagtype; - for ( tagtype = 0; tagtype < CChoreoEvent::NUM_ABS_TAG_TYPES; tagtype++ ) - { - if ( e->GetNumAbsoluteTags( (CChoreoEvent::AbsTagType)tagtype ) > 0 ) - { - FilePrintf( buf, level + 1, "absolutetags %s\n", CChoreoEvent::NameForAbsoluteTagType( (CChoreoEvent::AbsTagType)tagtype ) ); - FilePrintf( buf, level + 1, "{\n" ); - for ( int t = 0; t < e->GetNumAbsoluteTags( (CChoreoEvent::AbsTagType)tagtype ); t++ ) - { - CEventAbsoluteTag *abstag = e->GetAbsoluteTag( (CChoreoEvent::AbsTagType)tagtype, t ); - Assert( abstag ); - FilePrintf( buf, level + 2, "\"%s\" %f\n", abstag->GetName(), abstag->GetPercentage() ); - } - FilePrintf( buf, level + 1, "}\n" ); - } - } - - if ( e->GetType() == CChoreoEvent::GESTURE ) - { - float duration; - if ( e->GetGestureSequenceDuration( duration ) ) - { - FilePrintf( buf, level + 1, "sequenceduration %f\n", duration ); - } - } - - if ( e->IsUsingRelativeTag() ) - { - FilePrintf( buf, level + 1, "relativetag \"%s\" \"%s\"\n", - e->GetRelativeTagName(), e->GetRelativeWavName() ); - } - - if ( e->GetNumFlexAnimationTracks() > 0 ) - { - FileSaveFlexAnimations( buf, level, e ); - } - - if ( e->GetType() == CChoreoEvent::LOOP ) - { - FilePrintf( buf, level + 1, "loopcount \"%i\"\n", e->GetLoopCount() ); - } - - if ( e->GetType() == CChoreoEvent::SPEAK ) - { - FilePrintf( buf, level + 1, "cctype \"%s\"\n", CChoreoEvent::NameForCCType( e->GetCloseCaptionType() ) ); - FilePrintf( buf, level + 1, "cctoken \"%s\"\n", e->GetCloseCaptionToken() ); - if ( e->GetCloseCaptionType() != CChoreoEvent::CC_DISABLED && - e->IsUsingCombinedFile() ) - { - FilePrintf( buf, level + 1, "cc_usingcombinedfile\n" ); - } - if ( e->IsCombinedUsingGenderToken() ) - { - FilePrintf( buf, level + 1, "cc_combinedusesgender\n" ); - } - if ( e->IsSuppressingCaptionAttenuation() ) - { - FilePrintf( buf, level + 1, "cc_noattenuate\n" ); - } - } - - FilePrintf( buf, level, "}\n" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *fp - -// level - -// *c - -//----------------------------------------------------------------------------- -void CChoreoScene::FileSaveChannel( CUtlBuffer& buf, int level, CChoreoChannel *c ) -{ - if ( !c->IsMarkedForSave() ) - return; - - FilePrintf( buf, level, "channel \"%s\"\n", c->GetName() ); - FilePrintf( buf, level, "{\n" ); - - for ( int i = 0; i < c->GetNumEvents(); i++ ) - { - CChoreoEvent *e = c->GetEvent( i ); - if ( e ) - { - FileSaveEvent( buf, level + 1, e ); - } - } - - if ( !c->GetActive() ) - { - // Only write out inactive - FilePrintf( buf, level + 1, "active \"0\"\n" ); - } - - FilePrintf( buf, level, "}\n" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *fp - -// level - -// *a - -//----------------------------------------------------------------------------- -void CChoreoScene::FileSaveActor( CUtlBuffer& buf, int level, CChoreoActor *a ) -{ - if ( !a->IsMarkedForSave() ) - return; - - FilePrintf( buf, level, "actor \"%s\"\n", a->GetName() ); - FilePrintf( buf, level, "{\n" ); - - for ( int i = 0; i < a->GetNumChannels(); i++ ) - { - CChoreoChannel *c = a->GetChannel( i ); - if ( c ) - { - FileSaveChannel( buf, level + 1, c ); - } - } - - if ( Q_strlen( a->GetFacePoserModelName() ) > 0 ) - { - FilePrintf( buf, level + 1, "faceposermodel \"%s\"\n", a->GetFacePoserModelName() ); - } - - if ( !a->GetActive() ) - { - // Only write out inactive - FilePrintf( buf, level + 1, "active \"0\"\n" ); - } - - FilePrintf( buf, level, "}\n\n" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CChoreoScene::FindAdjustedStartTime( void ) -{ - float earliest_time = 0.0f; - - CChoreoEvent *e; - - for ( int i = 0; i < m_Events.Size(); i++ ) - { - e = m_Events[ i ]; - - float starttime = e->GetStartTime(); - - // If it's a wav file, pre-queue the starting time by the sound system's - // current latency - if ( e->GetType() == CChoreoEvent::SPEAK ) - { - starttime -= m_flSoundSystemLatency; - } - - if ( starttime < earliest_time ) - { - earliest_time = starttime; - } - } - - return earliest_time; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CChoreoScene::FindAdjustedEndTime( void ) -{ - float latest_time = 0.0f; - - CChoreoEvent *e; - - for ( int i = 0; i < m_Events.Size(); i++ ) - { - e = m_Events[ i ]; - - float endtime = e->GetStartTime(); - if ( e->HasEndTime() ) - { - endtime = e->GetEndTime(); - } - - // If it's a wav file, pre-queue the starting time by the sound system's - // current latency - if ( e->GetType() == CChoreoEvent::SPEAK ) - { - endtime += m_flSoundSystemLatency; - } - - if ( endtime > latest_time ) - { - latest_time = endtime; - } - } - - return latest_time; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoScene::ResetSimulation( bool forward /*= true*/, float starttime /*= 0.0f*/, float endtime /*= 0.0f*/ ) -{ - CChoreoEvent *e; - - m_ActiveResumeConditions.RemoveAll(); - m_ResumeConditions.RemoveAll(); - m_PauseEvents.RemoveAll(); - - // Put all items into the pending queue - for ( int i = 0; i < m_Events.Size(); i++ ) - { - e = m_Events[ i ]; - e->ResetProcessing(); - - if ( e->GetType() == CChoreoEvent::SECTION ) - { - m_PauseEvents.AddToTail( e ); - continue; - } - - if ( e->IsResumeCondition() ) - { - m_ResumeConditions.AddToTail( e ); - continue; - } - } - - // Find earliest adjusted start time - m_flEarliestTime = FindAdjustedStartTime(); - m_flLatestTime = FindAdjustedEndTime(); - - m_flCurrentTime = forward ? m_flEarliestTime : m_flLatestTime; - - // choreoprintf( 0, "Start time %f\n", m_flCurrentTime ); - - m_flLastActiveTime = 0.0f; - m_nActiveEvents = m_Events.Size(); - - m_flStartTime = starttime; - m_flEndTime = endtime; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CChoreoScene::CheckEventCompletion( void ) -{ - CChoreoEvent *e; - - bool bAllCompleted = true; - // check all items in the active pending queue - for ( int i = 0; i < m_ActiveResumeConditions.Size(); i++ ) - { - e = m_ActiveResumeConditions[ i ]; - - bAllCompleted = bAllCompleted && e->CheckProcessing( m_pIChoreoEventCallback, this, m_flCurrentTime ); - } - return bAllCompleted; -} - - - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChoreoScene::SimulationFinished( void ) -{ - // Scene's linger for a little bit to allow things to settle - // check for events that are still active... - - if ( m_flCurrentTime > m_flLatestTime ) - { - if ( m_nActiveEvents != 0 ) - { - return false; - } - - return true; - } - if ( m_flCurrentTime < m_flEarliestTime ) - { - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CChoreoEvent *CChoreoScene::FindPauseBetweenTimes( float starttime, float endtime ) -{ - CChoreoEvent *e; - - // Iterate through all events in the scene - for ( int i = 0; i < m_PauseEvents.Size(); i++ ) - { - e = m_PauseEvents[ i ]; - if ( !e ) - continue; - - Assert( e->GetType() == CChoreoEvent::SECTION ); - - int time_is = IsTimeInRange( e->GetStartTime(), starttime, endtime ); - if ( IN_RANGE != time_is ) - continue; - - // Found a pause in between start and end time - return e; - } - - // No pause inside the specified time span - return NULL; -} - -int CChoreoScene::IsTimeInRange( float t, float starttime, float endtime ) -{ - if ( t > endtime ) - { - return AFTER_RANGE; - } - else if ( t < starttime ) - { - return BEFORE_RANGE; - } - - return IN_RANGE; -} - -int CChoreoScene::EventThink( CChoreoEvent *e, float frame_start_time, float frame_end_time, bool playing_forward, PROCESSING_TYPE& disposition ) -{ - disposition = PROCESSING_TYPE_IGNORE; - int iret = 0; - - bool hasend = e->HasEndTime(); - float starttime, endtime; - - starttime = e->GetStartTime(); - endtime = hasend ? e->GetEndTime() : e->GetStartTime(); - - if ( !playing_forward ) - { - // Swap intervals - float temp = frame_start_time; - frame_start_time = frame_end_time; - frame_end_time = temp; - } - - bool suppressed = false; - - // Special processing - switch ( e->GetType() ) - { - default: - break; - case CChoreoEvent::SPEAK: - // If it's a wav file, pre-queue the starting/endtime time by the sound system's - // current latency - { - if ( playing_forward ) - { - starttime -= m_flSoundSystemLatency; - - - // Search for pause condition in between the original time and the - // adjusted start time, but make sure that the pause event hasn't already triggered... - CChoreoEvent *pauseEvent = FindPauseBetweenTimes( starttime, starttime + m_flSoundSystemLatency ); - if ( pauseEvent && - ( frame_start_time <= pauseEvent->GetStartTime() ) ) - { - pauseEvent->AddEventDependency( e ); - - suppressed = true; - } - } - /* - else - // Don't bother if playing backward!!! - { - endtime += m_flSoundSystemLatency; - - // Search for pause condition in between the original time and the - // adjusted start time - CChoreoEvent *pauseEvent = FindPauseBetweenTimes( endtime - m_flSoundSystemLatency, endtime ); - if ( pauseEvent ) - { - pauseEvent->AddEventDependency( e ); - - suppressed = true; - } - } - */ - } - break; - case CChoreoEvent::SUBSCENE: - { - if ( IsSubScene() ) - { - suppressed = true; - } - } - break; - } - - if ( suppressed ) - { - if ( e->IsProcessing() ) - { - disposition = PROCESSING_TYPE_STOP; - } - return iret; - } - - int where_is_event; - - if ( e->IsProcessing() ) - { - where_is_event = IsTimeInRange( frame_start_time, starttime, endtime ); - if ( IN_RANGE == where_is_event ) - { - disposition = PROCESSING_TYPE_CONTINUE; - iret = 1; - } - else - { - disposition = PROCESSING_TYPE_STOP; - } - } - else - { - - // Is the event supposed to be active at this time - where_is_event = IsTimeInRange( frame_start_time, starttime, endtime ); - - if ( IN_RANGE == where_is_event ) - { - if ( e->IsResumeCondition() ) - { - disposition = PROCESSING_TYPE_START_RESUMECONDITION; - } - else - { - disposition = PROCESSING_TYPE_START; - } - iret = 1; - } - // See if it's a single fire event which should occur during this frame - else if ( !hasend ) - { - where_is_event = IsTimeInRange( starttime, frame_start_time, frame_end_time ); - if ( IN_RANGE == where_is_event ) - { - disposition = PROCESSING_TYPE_START; - iret = 1; - } - - } - } - - return iret; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &e0 - -// &e1 - -// Output : static bool -//----------------------------------------------------------------------------- -bool CChoreoScene::EventLess( const CChoreoScene::ActiveList &al0, const CChoreoScene::ActiveList &al1 ) -{ - CChoreoEvent *event0, *event1; - event0 = const_cast< CChoreoEvent * >( al0.e ); - event1 = const_cast< CChoreoEvent * >( al1.e ); - - if ( event0->GetStartTime() < event1->GetStartTime() ) - { - return true; - } - - if ( event0->GetStartTime() > event1->GetStartTime() ) - { - return false; - } - - // Check for end time overlap - if ( event0->HasEndTime() && event1->HasEndTime() ) - { - if ( event0->GetEndTime() > event1->GetEndTime() ) - return true; - else if ( event0->GetEndTime() < event1->GetEndTime() ) - return false; - } - - CChoreoActor *a0, *a1; - a0 = event0->GetActor(); - a1 = event1->GetActor(); - - // Start time equal, go to order in channel - if ( !a0 || !a1 || a0 != a1 ) - { - return strcmp( event0->GetName(), event1->GetName() ) == -1; - } - - CChoreoChannel *c0 = event0->GetChannel(); - CChoreoChannel *c1 = event1->GetChannel(); - - if ( !c0 || !c1 || c0 != c1 ) - { - return strcmp( event0->GetName(), event1->GetName() ) == -1; - } - - // Go by slot within channel - int index0 = a0->FindChannelIndex( c0 ); - int index1 = a1->FindChannelIndex( c1 ); - - return ( index0 < index1 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoScene::ClearPauseEventDependencies() -{ - int c = m_PauseEvents.Count(); - for ( int i = 0 ; i < c; ++i ) - { - CChoreoEvent *pause = m_PauseEvents[ i ]; - Assert( pause ); - pause->ClearEventDependencies(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pauseEvent - -// *suppressed - -//----------------------------------------------------------------------------- -void CChoreoScene::AddPauseEventDependency( CChoreoEvent *pauseEvent, CChoreoEvent *suppressed ) -{ - Assert( pauseEvent ); - Assert( pauseEvent != suppressed ); - pauseEvent->AddEventDependency( suppressed ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : dt - -//----------------------------------------------------------------------------- -void CChoreoScene::Think( float curtime ) -{ - CChoreoEvent *e; - - float oldt = m_flCurrentTime; - float dt = curtime - oldt; - - bool playing_forward = ( dt >= 0.0f ) ? true : false; - - m_nActiveEvents = 0; - - ClearPauseEventDependencies(); - - CUtlRBTree< ActiveList, int > pending(0,0,EventLess); - - // Iterate through all events in the scene - int i; - for ( i = 0; i < m_Events.Size(); i++ ) - { - e = m_Events[ i ]; - if ( !e ) - continue; - - PROCESSING_TYPE disposition; - m_nActiveEvents += EventThink( e, m_flCurrentTime, curtime, playing_forward, disposition ); - - if ( disposition != PROCESSING_TYPE_IGNORE ) - { - - ActiveList entry; - - entry.e = e; - entry.pt = disposition; - - pending.Insert( entry ); - } - } - - // Events are sorted start time and then by channel and actor slot or by name if those aren't equal - bool dump = false; - - i = pending.FirstInorder(); - while ( i != pending.InvalidIndex() ) - { - ActiveList *entry = &pending[ i ]; - - Assert( entry->e ); - - if ( dump ) - { - Msg( "%f == %s starting at %f (actor %p channel %p)\n", - m_flCurrentTime, entry->e->GetName(), entry->e->GetStartTime(), - entry->e->GetActor(), entry->e->GetChannel() ); - } - - switch ( entry->pt ) - { - default: - case PROCESSING_TYPE_IGNORE: - { - Assert( 0 ); - } - break; - case PROCESSING_TYPE_START: - case PROCESSING_TYPE_START_RESUMECONDITION: - { - entry->e->StartProcessing( m_pIChoreoEventCallback, this, m_flCurrentTime ); - - if ( entry->pt == PROCESSING_TYPE_START_RESUMECONDITION ) - { - Assert( entry->e->IsResumeCondition() ); - m_ActiveResumeConditions.AddToTail( entry->e ); - } - - // This event can "pause" the scene, so we need to remember who "paused" the scene so that - // when we resume we can resume any suppressed events dependent on this pauser... - if ( entry->e->GetType() == CChoreoEvent::SECTION ) - { - // So this event should be in the pauseevents list, otherwise this'll be -1 - m_nLastPauseEvent = m_PauseEvents.Find( entry->e ); - } - } - break; - case PROCESSING_TYPE_CONTINUE: - { - entry->e->ContinueProcessing( m_pIChoreoEventCallback, this, m_flCurrentTime ); - } - break; - case PROCESSING_TYPE_STOP: - { - entry->e->StopProcessing( m_pIChoreoEventCallback, this, m_flCurrentTime ); - } - break; - } - - i = pending.NextInorder( i ); - } - - if ( dump ) - { - Msg( "\n" ); - } - - // If a Process call slams this time, don't override it!!! - if ( oldt == m_flCurrentTime ) - { - m_flCurrentTime = curtime; - } - - // Still processing? - if ( m_nActiveEvents ) - { - m_flLastActiveTime = m_flCurrentTime; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CChoreoScene::GetTime( void ) -{ - return m_flCurrentTime; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : t - -//----------------------------------------------------------------------------- -void CChoreoScene::SetTime( float t ) -{ - m_flCurrentTime = t; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : t - -//----------------------------------------------------------------------------- -void CChoreoScene::LoopToTime( float t ) -{ - m_flCurrentTime = t; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pfn - -//----------------------------------------------------------------------------- -void CChoreoScene::SetPrintFunc( void ( *pfn ) ( const char *fmt, ... ) ) -{ - m_pfnPrint = pfn; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -//----------------------------------------------------------------------------- -void CChoreoScene::RemoveActor( CChoreoActor *actor ) -{ - int idx = FindActorIndex( actor ); - if ( idx == -1 ) - return; - - m_Actors.Remove( idx ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -// Output : int -//----------------------------------------------------------------------------- -int CChoreoScene::FindActorIndex( CChoreoActor *actor ) -{ - for ( int i = 0; i < m_Actors.Size(); i++ ) - { - if ( actor == m_Actors[ i ] ) - { - return i; - } - } - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : a1 - -// a2 - -//----------------------------------------------------------------------------- -void CChoreoScene::SwapActors( int a1, int a2 ) -{ - CChoreoActor *temp; - - temp = m_Actors[ a1 ]; - m_Actors[ a1 ] = m_Actors[ a2 ]; - m_Actors[ a2 ] = temp; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -//----------------------------------------------------------------------------- -void CChoreoScene::DeleteReferencedObjects( CChoreoActor *actor ) -{ - for ( int i = 0; i < actor->GetNumChannels(); i++ ) - { - CChoreoChannel *channel = actor->GetChannel( i ); - actor->RemoveChannel( channel ); - - DeleteReferencedObjects( channel ); - } - - DestroyActor( actor ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *channel - -//----------------------------------------------------------------------------- -void CChoreoScene::DeleteReferencedObjects( CChoreoChannel *channel ) -{ - for ( int i = 0; i < channel->GetNumEvents(); i++ ) - { - CChoreoEvent *event = channel->GetEvent( i ); - channel->RemoveEvent( event ); - - DeleteReferencedObjects( event ); - } - - DestroyChannel( channel ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *event - -//----------------------------------------------------------------------------- -void CChoreoScene::DeleteReferencedObjects( CChoreoEvent *event ) -{ - int idx = m_PauseEvents.Find( event ); - if ( idx != m_PauseEvents.InvalidIndex() ) - { - m_PauseEvents.Remove( idx ); - } - // Events don't reference anything lower - DestroyEvent( event ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -//----------------------------------------------------------------------------- -void CChoreoScene::DestroyActor( CChoreoActor *actor ) -{ - int size = m_Actors.Size(); - for ( int i = size - 1; i >= 0; i-- ) - { - CChoreoActor *a = m_Actors[ i ]; - if ( a == actor ) - { - m_Actors.Remove( i ); - } - } - - delete actor; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *channel - -//----------------------------------------------------------------------------- -void CChoreoScene::DestroyChannel( CChoreoChannel *channel ) -{ - int size = m_Channels.Size(); - for ( int i = size - 1; i >= 0; i-- ) - { - CChoreoChannel *c = m_Channels[ i ]; - if ( c == channel ) - { - m_Channels.Remove( i ); - } - } - - delete channel; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *event - -//----------------------------------------------------------------------------- -void CChoreoScene::DestroyEvent( CChoreoEvent *event ) -{ - int size = m_Events.Size(); - for ( int i = size - 1; i >= 0; i-- ) - { - CChoreoEvent *e = m_Events[ i ]; - if ( e == event ) - { - m_Events.Remove( i ); - } - } - - delete event; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoScene::ResumeSimulation( void ) -{ - // If the thing that paused us was a SECTION pause event, then this will be set - if ( m_nLastPauseEvent >= 0 && - m_nLastPauseEvent < m_PauseEvents.Count() ) - { - // Start any suppressed dependencies immediately, should only be .wav files!!! - // These are .wav files which are placed at or just after the SECTION pause event - // in the .vcd, but due to the user's sound system latency, they would have triggered before the - // pause (we pre-queue sounds). Since we suppressed that, we need to unsupress / start these sounds - // now that the SECTION pause is being resumed from - CUtlVector< CChoreoEvent * > deps; - CChoreoEvent *pauseEvent = m_PauseEvents[ m_nLastPauseEvent ]; - Assert( pauseEvent ); - - // Sanity check ( this should be about 1 tick usually 15 msec) - float timeSincePaused = m_flCurrentTime - pauseEvent->GetStartTime(); - if ( fabs( timeSincePaused ) > 1.0f ) - { - Assert( !"Resume simulation with unexpected pause event" ); - } - - // Snag any sounds which were suppressed by this issue - pauseEvent->GetEventDependencies( deps ); - for ( int j = 0; j < deps.Count(); ++j ) - { - CChoreoEvent *startEvent = deps[ j ]; - Assert( startEvent ); - // Start them now. Yes, they won't pre-queue, but it's better than totally skipping the sound!!! - startEvent->StartProcessing( m_pIChoreoEventCallback, this, m_flCurrentTime ); - } - } - - // Reset section pause signal - m_nLastPauseEvent = -1; - - m_ActiveResumeConditions.RemoveAll(); -} - -// Sound system needs to have sounds pre-queued by this much time -void CChoreoScene::SetSoundFileStartupLatency( float time ) -{ - Assert( time >= 0 ); - m_flSoundSystemLatency = time; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : start - -// end - -//----------------------------------------------------------------------------- -void CChoreoScene::GetSceneTimes( float& start, float& end ) -{ - start = m_flStartTime; - end = m_flEndTime; -} - -//----------------------------------------------------------------------------- -// Purpose: Do housekeeping on times that are relative to tags -//----------------------------------------------------------------------------- -void CChoreoScene::ReconcileTags( void ) -{ - for ( int i = 0 ; i < m_Actors.Size(); i++ ) - { - CChoreoActor *a = m_Actors[ i ]; - if ( !a ) - continue; - - for ( int j = 0; j < a->GetNumChannels(); j++ ) - { - CChoreoChannel *c = a->GetChannel( j ); - if ( !c ) - continue; - - for ( int k = 0 ; k < c->GetNumEvents(); k++ ) - { - CChoreoEvent *e = c->GetEvent( k ); - if ( !e ) - continue; - - if ( !e->IsUsingRelativeTag() ) - continue; - - CEventRelativeTag *tag = FindTagByName( - e->GetRelativeWavName(), - e->GetRelativeTagName() ); - - if ( tag ) - { - // Determine correct starting time based on tag - float starttime = tag->GetStartTime(); - - // Figure out delta - float dt = starttime - e->GetStartTime(); - - // Fix up start and possible end time - e->OffsetTime( dt ); - } - else - { - // The tag was missing!!! unflag it - choreoprintf( 0, "Event %s was missing tag %s for wav %s\n", - e->GetName(), e->GetRelativeWavName(), e->GetRelativeTagName() ); - - e->SetUsingRelativeTag( false, "", "" ); - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *wavname - -// *name - -// Output : CChoreoEvent -//----------------------------------------------------------------------------- -CChoreoEvent *CChoreoScene::FindTargetingEvent( const char *wavname, const char *name ) -{ - for ( int i = 0 ; i < m_Actors.Size(); i++ ) - { - CChoreoActor *a = m_Actors[ i ]; - if ( !a ) - continue; - - for ( int j = 0; j < a->GetNumChannels(); j++ ) - { - CChoreoChannel *c = a->GetChannel( j ); - if ( !c ) - continue; - - for ( int k = 0 ; k < c->GetNumEvents(); k++ ) - { - CChoreoEvent *e = c->GetEvent( k ); - if ( !e ) - continue; - - if ( !e->IsUsingRelativeTag() ) - continue; - - if ( stricmp( wavname, e->GetRelativeWavName() ) ) - continue; - - if ( stricmp( name, e->GetRelativeTagName() ) ) - continue; - - return e; - } - } - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *wavname - -// *name - -// Output : CEventRelativeTag -//----------------------------------------------------------------------------- -CEventRelativeTag *CChoreoScene::FindTagByName( const char *wavname, const char *name ) -{ - for ( int i = 0 ; i < m_Actors.Size(); i++ ) - { - CChoreoActor *a = m_Actors[ i ]; - if ( !a ) - continue; - - for ( int j = 0; j < a->GetNumChannels(); j++ ) - { - CChoreoChannel *c = a->GetChannel( j ); - if ( !c ) - continue; - - for ( int k = 0 ; k < c->GetNumEvents(); k++ ) - { - CChoreoEvent *e = c->GetEvent( k ); - if ( !e ) - continue; - - if ( e->GetType() != CChoreoEvent::SPEAK ) - continue; - - // Search for tag by name - if ( !strstr( e->GetParameters(), wavname ) ) - continue; - - CEventRelativeTag *tag = e->FindRelativeTag( name ); - if ( !tag ) - continue; - - return tag; - } - } - } - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *filename - -//----------------------------------------------------------------------------- -void CChoreoScene::ExportEvents( const char *filename, CUtlVector< CChoreoEvent * >& events ) -{ - if ( events.Size() <= 0 ) - return; - - // Create a serialization buffer - CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); - FilePrintf( buf, 0, "// Choreo version 1: <%i> Exported Events\n", events.Size() ); - - // Save out the selected events. - int i; - for ( i = 0 ; i < events.Size(); i++ ) - { - CChoreoEvent *e = events[ i ]; - if ( !e->GetActor() ) - continue; - - FileSaveEvent( buf, 0, e ); - } - - // Write it out baby - FileHandle_t fh = g_pFullFileSystem->Open( filename, "wt" ); - if (fh) - { - g_pFullFileSystem->Write( buf.Base(), buf.TellPut(), fh ); - g_pFullFileSystem->Close(fh); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *actor - -// *channel - -// starttime - -//----------------------------------------------------------------------------- -void CChoreoScene::ImportEvents( ISceneTokenProcessor *tokenizer, CChoreoActor *actor, CChoreoChannel *channel ) -{ - m_pTokenizer = tokenizer; - - while ( 1 ) - { - if ( !m_pTokenizer->GetToken( true ) ) - { - break; - } - - if ( strlen( m_pTokenizer->CurrentToken() ) <= 0 ) - break; - - if ( !Q_stricmp( m_pTokenizer->CurrentToken(), "event" ) ) - { - ParseEvent( actor, channel ); - } - else - { - m_pTokenizer->Error( "unexpected token %s\n", m_pTokenizer->CurrentToken() ); - break; - } - } - - // Fixup time tags - ReconcileTags(); -} - -void CChoreoScene::SetSubScene( bool sub ) -{ - m_bSubScene = sub; -} - -bool CChoreoScene::IsSubScene( void ) const -{ - return m_bSubScene; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CChoreoScene::GetSceneFPS( void ) const -{ - return m_nSceneFPS; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : fps - -//----------------------------------------------------------------------------- -void CChoreoScene::SetSceneFPS( int fps ) -{ - m_nSceneFPS = fps; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChoreoScene::IsUsingFrameSnap( void ) const -{ - return m_bUseFrameSnap; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : snap - -//----------------------------------------------------------------------------- -void CChoreoScene::SetUsingFrameSnap( bool snap ) -{ - m_bUseFrameSnap = snap; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : t - -// Output : float -//----------------------------------------------------------------------------- -float CChoreoScene::SnapTime( float t ) -{ - if ( !IsUsingFrameSnap() ) - return t; - - float fps = (float)GetSceneFPS(); - Assert( fps > 0 ); - - int itime = (int)( t * fps + 0.5f ); - - t = (float)itime / fps; - - // FIXME: If FPS is set and "using grid", snap to proper fractional time value - return t; -} - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoScene::ReconcileGestureTimes() -{ - for ( int i = 0 ; i < m_Actors.Size(); i++ ) - { - CChoreoActor *a = m_Actors[ i ]; - if ( !a ) - continue; - - for ( int j = 0; j < a->GetNumChannels(); j++ ) - { - CChoreoChannel *c = a->GetChannel( j ); - if ( !c ) - continue; - - c->ReconcileGestureTimes(); - } - } -} - -int CChoreoScene::TimeZoomFirst() -{ - return m_TimeZoomLookup.First(); -} - -int CChoreoScene::TimeZoomNext( int i ) -{ - return m_TimeZoomLookup.Next( i ); -} -int CChoreoScene::TimeZoomInvalid() const -{ - return m_TimeZoomLookup.InvalidIndex(); -} -char const *CChoreoScene::TimeZoomName( int i ) -{ - return m_TimeZoomLookup.GetElementName( i ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *tool - -// Output : int -//----------------------------------------------------------------------------- -int CChoreoScene::GetTimeZoom( char const *tool ) -{ - // If not present add it - int idx = m_TimeZoomLookup.Find( tool ); - if ( idx == m_TimeZoomLookup.InvalidIndex() ) - { - idx = m_TimeZoomLookup.Insert( tool, 100 ); - } - - return m_TimeZoomLookup[ idx ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *tool - -// tz - -//----------------------------------------------------------------------------- -void CChoreoScene::SetTimeZoom( char const *tool, int tz ) -{ - // If not present add it - int idx = m_TimeZoomLookup.Find( tool ); - if ( idx == m_TimeZoomLookup.InvalidIndex() ) - { - idx = m_TimeZoomLookup.Insert( tool, 100 ); - } - - m_TimeZoomLookup[ idx ] = tz; -} - -void CChoreoScene::ParseScaleSettings( ISceneTokenProcessor *tokenizer, CChoreoScene *scene ) -{ - tokenizer->GetToken( true ); - - if ( stricmp( tokenizer->CurrentToken(), "{" ) ) - tokenizer->Error( "expecting {\n" ); - - while ( 1 ) - { - // Parse until } - tokenizer->GetToken( true ); - - if ( strlen( tokenizer->CurrentToken() ) <= 0 ) - { - tokenizer->Error( "expecting scalesettings data\n" ); - break; - } - - if ( !Q_stricmp( tokenizer->CurrentToken(), "}" ) ) - break; - - char tool[ 256 ]; - Q_strncpy( tool, tokenizer->CurrentToken(), sizeof( tool ) ); - - tokenizer->GetToken( false ); - - int tz = Q_atoi( tokenizer->CurrentToken() ); - if ( tz <= 0 ) - tz = 100; - - scene->SetTimeZoom( tool, tz ); - } -} - -// Merges two .vcd's together -bool CChoreoScene::Merge( CChoreoScene *other ) -{ - int acount = 0; - int ccount = 0; - int ecount = 0; - - // Look for events that don't have actor/channel set - int i; - for ( i = 0 ; i < other->m_Events.Size(); i++ ) - { - CChoreoEvent *e = other->m_Events[ i ]; - if ( e->GetActor() ) - continue; - - MEM_ALLOC_CREDIT(); - // Make a copy of the other event and add it to this scene - CChoreoEvent *newEvent = AllocEvent(); - *newEvent = *e; - newEvent->SetScene( this ); - ecount++; - } - - for ( i = 0 ; i < other->m_Actors.Size(); i++ ) - { - CChoreoActor *a = other->m_Actors[ i ]; - - // See if that actor already exists - bool newActor = false; - CChoreoActor *destActor = FindActor( a->GetName() ); - if ( !destActor ) - { - newActor = true; - destActor = AllocActor(); - *destActor = *a; - destActor->RemoveAllChannels(); - acount++; - } - - // Now we have a destination actor, work on channels - for ( int j = 0; j < a->GetNumChannels(); j++ ) - { - CChoreoChannel *ch = a->GetChannel( j ); - - bool newChannel = false; - CChoreoChannel *destChannel = NULL; - destChannel = destActor->FindChannel( ch->GetName() ); - if ( !destChannel ) - { - destChannel = AllocChannel(); - *destChannel = *ch; - destChannel->RemoveAllEvents(); - newChannel = true; - ccount++; - } - - if ( newChannel ) - { - destActor->AddChannel( destChannel ); - destChannel->SetActor( destActor ); - } - - // Now we have a destination channel, work on events themselves - for ( int k = 0 ; k < ch->GetNumEvents(); k++ ) - { - CChoreoEvent *e = ch->GetEvent( k ); - - // Just import them wholesale, no checking - MEM_ALLOC_CREDIT(); - CChoreoEvent *newEvent = AllocEvent(); - *newEvent = *e; - newEvent->SetScene( this ); - - destChannel->AddEvent( newEvent ); - - newEvent->SetChannel( destChannel ); - newEvent->SetActor( destActor ); - - ecount++; - } - } - } - - Msg( "Merged in (%i) actors, (%i) channels, and (%i) events\n", - acount, ccount, ecount ); - - return ( ecount || acount || ccount ); -} - -//----------------------------------------------------------------------------- -// Purpose: Updates master/slave status info per channel -//----------------------------------------------------------------------------- -void CChoreoScene::ReconcileCloseCaption() -{ - for ( int i = 0 ; i < m_Actors.Size(); i++ ) - { - CChoreoActor *a = m_Actors[ i ]; - if ( !a ) - continue; - - for ( int j = 0; j < a->GetNumChannels(); j++ ) - { - CChoreoChannel *c = a->GetChannel( j ); - if ( !c ) - continue; - - c->ReconcileCloseCaption(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : char const -//----------------------------------------------------------------------------- -char const *CChoreoScene::GetFilename() const -{ - return m_szFileName; -} - - -void CChoreoScene::SetFileName( char const *fn ) -{ - Q_strncpy( m_szFileName, fn, sizeof( m_szFileName ) ); -} - - -bool CChoreoScene::GetPlayingSoundName( char *pchBuff, int iBuffLength ) -{ - for ( int i = 0; i < m_Events.Size(); i++ ) - { - CChoreoEvent *e = m_Events[ i ]; - if ( e->GetType() == CChoreoEvent::SPEAK && e->IsProcessing() ) - { - Q_strncpy( pchBuff, e->GetParameters(), iBuffLength ); - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true if this scene has speech events that haven't played yet -//----------------------------------------------------------------------------- -bool CChoreoScene::HasUnplayedSpeech() -{ - for ( int i = 0; i < m_Events.Size(); i++ ) - { - CChoreoEvent *e = m_Events[ i ]; - if ( e->GetType() == CChoreoEvent::SPEAK ) - { - // Have we played it yet? - if ( m_flCurrentTime < e->GetStartTime() ) - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true if this scene has flex animation events that are playing -//----------------------------------------------------------------------------- -bool CChoreoScene::HasFlexAnimation() -{ - for ( int i = 0; i < m_Events.Size(); i++ ) - { - CChoreoEvent *e = m_Events[ i ]; - if ( e->GetType() == CChoreoEvent::FLEXANIMATION ) - { - // Have we played it yet? - if ( m_flCurrentTime >= e->GetStartTime() && m_flCurrentTime <= e->GetEndTime() ) - return true; - } - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChoreoScene::SetBackground( bool bIsBackground ) -{ - m_bIsBackground = bIsBackground; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CChoreoScene::IsBackground( ) -{ - return m_bIsBackground; -} - -bool CChoreoScene::HasEventsOfType( CChoreoEvent::EVENTTYPE type ) const -{ - return m_bitvecHasEventOfType.IsBitSet( type ); -} - -// ICurveDataAccessor method -bool CChoreoScene::CurveHasEndTime() -{ - return true; -} - -int CChoreoScene::GetDefaultCurveType() -{ - return CURVE_CATMULL_ROM_TO_CATMULL_ROM; -} - -bool CChoreoScene::SaveBinary( char const *pszBinaryFileName, char const *pPathID, unsigned int nTextVersionCRC, IChoreoStringPool *pStringPool ) -{ - bool bret = false; - - CUtlBuffer buf; - SaveToBinaryBuffer( buf, nTextVersionCRC, pStringPool ); - - if ( g_pFullFileSystem->FileExists( pszBinaryFileName, pPathID ) && - !g_pFullFileSystem->IsFileWritable( pszBinaryFileName, pPathID ) ) - { - Warning( "Forcing '%s' to be writable!!!\n", pszBinaryFileName ); - g_pFullFileSystem->SetFileWritable( pszBinaryFileName, true, pPathID ); - } - - FileHandle_t fh = g_pFullFileSystem->Open( pszBinaryFileName, "wb", pPathID ); - if ( FILESYSTEM_INVALID_HANDLE != fh ) - { - g_pFullFileSystem->Write( buf.Base(), buf.TellPut(), fh ); - g_pFullFileSystem->Close( fh ); - - // Success - bret = true; - } - else - { - Warning( "Unable to open '%s' for writing!!!\n", pszBinaryFileName ); - } - - return bret; -} - -void CChoreoScene::SaveToBinaryBuffer( CUtlBuffer& buf, unsigned int nTextVersionCRC, IChoreoStringPool *pStringPool ) -{ - buf.PutInt( SCENE_BINARY_TAG ); - buf.PutChar( SCENE_BINARY_VERSION ); - buf.PutInt( nTextVersionCRC ); - - // Look for events that don't have actor/channel set - CUtlVector< CChoreoEvent * > eventList; - int i; - for ( i = 0 ; i < m_Events.Size(); i++ ) - { - CChoreoEvent *e = m_Events[ i ]; - if ( e->GetActor() ) - continue; - - eventList.AddToTail( e ); - } - - int c = eventList.Count(); - Assert( c <= 255 ); - buf.PutUnsignedChar( c ); - for ( i = 0; i < c; ++i ) - { - CChoreoEvent *e = eventList[ i ]; - e->SaveToBuffer( buf, this, pStringPool ); - } - - // Now serialize the actors themselves - CUtlVector< CChoreoActor * > actorList; - for ( i = 0 ; i < m_Actors.Size(); i++ ) - { - CChoreoActor *a = m_Actors[ i ]; - if ( !a ) - continue; - - actorList.AddToTail( a ); - } - - c = actorList.Count(); - Assert( c <= 255 ); - buf.PutUnsignedChar( c ); - for ( i = 0; i < c; ++i ) - { - CChoreoActor *a = actorList[ i ]; - a->SaveToBuffer( buf, this, pStringPool ); - } - - /* - // compiled version strips out map name, only used by editor - if ( m_szMapname[ 0 ] ) - { - FilePrintf( buf, 0, "mapname \"%s\"\n", m_szMapname ); - } - */ - - m_SceneRamp.SaveToBuffer( buf, pStringPool ); - - /* - // compiled version strips out scale settings fps and snap, only used by editor - FileSaveScaleSettings( buf, 0, this ); - FilePrintf( buf, 0, "fps %i\n", m_nSceneFPS ); - FilePrintf( buf, 0, "snap %s\n", m_bUseFrameSnap ? "on" : "off" ); - */ - buf.PutUnsignedChar( m_bIgnorePhonemes ); -} - -//----------------------------------------------------------------------------- -// Purpose: Static method to extract just the CRC from a binary .xcd file -// Input : buf - -// crc - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChoreoScene::GetCRCFromBinaryBuffer( CUtlBuffer& buf, unsigned int& crc ) -{ - bool bret = false; - - int pos = buf.TellGet(); - - int tag = buf.GetInt(); - if ( tag == SCENE_BINARY_TAG ) - { - byte ver = buf.GetChar(); - if ( ver == SCENE_BINARY_VERSION ) - { - bret = true; - crc = (unsigned int)buf.GetInt(); - } - } - - buf.SeekGet( CUtlBuffer::SEEK_HEAD, pos ); - - return bret; -} - -bool CChoreoScene::RestoreFromBinaryBuffer( CUtlBuffer& buf, char const *filename, IChoreoStringPool *pStringPool ) -{ - Q_strncpy( m_szFileName, filename, sizeof( m_szFileName ) ); - - int tag = buf.GetInt(); - if ( tag != SCENE_BINARY_TAG ) - return false; - - byte ver = buf.GetChar(); - if ( ver != SCENE_BINARY_VERSION ) - return false; - - // Skip the CRC - buf.GetInt(); - - int i; - int eventCount = buf.GetUnsignedChar(); - for ( i = 0; i < eventCount; ++i ) - { - MEM_ALLOC_CREDIT(); - CChoreoEvent *e = AllocEvent(); - Assert( e ); - - if ( e->RestoreFromBuffer( buf, this, pStringPool ) ) - { - continue; - } - - return false; - } - - int actorCount = buf.GetUnsignedChar(); - for ( i = 0; i < actorCount; ++i ) - { - CChoreoActor *a = AllocActor(); - Assert( a ); - if ( a->RestoreFromBuffer( buf, this, pStringPool ) ) - { - continue; - } - - return false; - } - - if ( !m_SceneRamp.RestoreFromBuffer( buf, pStringPool ) ) - { - return false; - } - - m_bIgnorePhonemes = ( buf.GetUnsignedChar( ) != 0 ); - -// FIXME: Are these ever needed on restore? -// ReconcileTags(); -// ReconcileGestureTimes(); - - ReconcileCloseCaption(); - - InternalDetermineEventTypes(); - - if ( CChoreoScene::s_bEditingDisabled ) - { - m_flPrecomputedStopTime = FindStopTime(); - } - - return true; -} diff --git a/game/shared/choreoscene.h b/game/shared/choreoscene.h deleted file mode 100644 index 507faa2b7..000000000 --- a/game/shared/choreoscene.h +++ /dev/null @@ -1,404 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef CHOREOSCENE_H -#define CHOREOSCENE_H -#ifdef _WIN32 -#pragma once -#endif - -class CChoreoEvent; -class CChoreoChannel; -class CChoreoActor; -class IChoreoEventCallback; -class CEventRelativeTag; -class CUtlBuffer; -class CFlexAnimationTrack; -class ISceneTokenProcessor; -class IChoreoStringPool; - -#include "tier1/utlvector.h" -#include "tier1/utldict.h" -#include "bitvec.h" -#include "expressionsample.h" -#include "choreoevent.h" - -#define DEFAULT_SCENE_FPS 60 -#define MIN_SCENE_FPS 10 -#define MAX_SCENE_FPS 240 - -#define SCENE_BINARY_TAG MAKEID( 'b', 'v', 'c', 'd' ) -#define SCENE_BINARY_VERSION 0x04 - -//----------------------------------------------------------------------------- -// Purpose: Container for choreographed scene of events for actors -//----------------------------------------------------------------------------- -class CChoreoScene : public ICurveDataAccessor -{ -public: - // Construction - CChoreoScene( IChoreoEventCallback *callback ); - ~CChoreoScene( void ); - - // Assignment - CChoreoScene& operator=(const CChoreoScene& src ); - - // ICurveDataAccessor methods - virtual float GetDuration() { return FindStopTime(); }; - virtual bool CurveHasEndTime(); - virtual int GetDefaultCurveType(); - - // Binary serialization - bool SaveBinary( char const *pszBinaryFileName, char const *pPathID, unsigned int nTextVersionCRC, IChoreoStringPool *pStringPool ); - void SaveToBinaryBuffer( CUtlBuffer& buf, unsigned int nTextVersionCRC, IChoreoStringPool *pStringPool ); - bool RestoreFromBinaryBuffer( CUtlBuffer& buf, char const *filename, IChoreoStringPool *pStringPool ); - static bool GetCRCFromBinaryBuffer( CUtlBuffer& buf, unsigned int& crc ); - - // We do some things differently while restoring from a save. - inline void SetRestoring( bool bRestoring ); - inline bool IsRestoring(); - - enum - { - MAX_SCENE_FILENAME = 128, - }; - - // Event callback handler - void SetEventCallbackInterface( IChoreoEventCallback *callback ); - - // Loading - bool ParseFromBuffer( char const *pFilename, ISceneTokenProcessor *tokenizer ); - void SetPrintFunc( void ( *pfn )( const char *fmt, ... ) ); - - // Saving - bool SaveToFile( const char *filename ); - bool ExportMarkedToFile( const char *filename ); - void MarkForSaveAll( bool mark ); - - // Merges two .vcd's together, returns true if any data was merged - bool Merge( CChoreoScene *other ); - - static void FileSaveFlexAnimationTrack( CUtlBuffer& buf, int level, CFlexAnimationTrack *track, int nDefaultCurveType ); - static void FileSaveFlexAnimations( CUtlBuffer& buf, int level, CChoreoEvent *e ); - static void FileSaveRamp( CUtlBuffer& buf, int level, CChoreoEvent *e ); - void FileSaveSceneRamp( CUtlBuffer& buf, int level ); - static void FileSaveScaleSettings( CUtlBuffer& buf, int level, CChoreoScene *scene ); - - static void ParseFlexAnimations( ISceneTokenProcessor *tokenizer, CChoreoEvent *e, bool removeold = true ); - static void ParseRamp( ISceneTokenProcessor *tokenizer, CChoreoEvent *e ); - static void ParseSceneRamp( ISceneTokenProcessor *tokenizer, CChoreoScene *scene ); - static void ParseScaleSettings( ISceneTokenProcessor *tokenizer, CChoreoScene *scene ); - static void ParseEdgeInfo( ISceneTokenProcessor *tokenizer, EdgeInfo_t *edgeinfo ); - - // Debugging - void SceneMsg( const char *pFormat, ... ); - void Print( void ); - - // Sound system needs to have sounds pre-queued by this much time - void SetSoundFileStartupLatency( float time ); - - // Simulation - void Think( float curtime ); - // Retrieves time in simulation - float GetTime( void ); - // Retrieves start/stop time for looped/debug scene - void GetSceneTimes( float& start, float& end ); - - void SetTime( float t ); - void LoopToTime( float t ); - - // Has simulation finished - bool SimulationFinished( void ); - // Reset simulation - void ResetSimulation( bool forward = true, float starttime = 0.0f, float endtime = 0.0f ); - // Find time at which last simulation event is triggered - float FindStopTime( void ); - - void ResumeSimulation( void ); - - // Have all the pause events happened - bool CheckEventCompletion( void ); - - // Find named actor in scene data - CChoreoActor *FindActor( const char *name ); - // Remove actor from scene - void RemoveActor( CChoreoActor *actor ); - // Find index for actor - int FindActorIndex( CChoreoActor *actor ); - - // Swap actors in the data - void SwapActors( int a1, int a2 ); - - // General data access - int GetNumEvents( void ); - CChoreoEvent *GetEvent( int event ); - - int GetNumActors( void ); - CChoreoActor *GetActor( int actor ); - - int GetNumChannels( void ); - CChoreoChannel *GetChannel( int channel ); - - // Object allocation/destruction - void DeleteReferencedObjects( CChoreoActor *actor ); - void DeleteReferencedObjects( CChoreoChannel *channel ); - void DeleteReferencedObjects( CChoreoEvent *event ); - - CChoreoActor *AllocActor( void ); - CChoreoChannel *AllocChannel( void ); - CChoreoEvent *AllocEvent( void ); - - void AddEventToScene( CChoreoEvent *event ); - void AddActorToScene( CChoreoActor *actor ); - void AddChannelToScene( CChoreoChannel *channel ); - - // Fixup simulation times for channel gestures - void ReconcileGestureTimes( void ); - - // Go through all elements and update relative tags, removing any orphaned - // tags and updating the timestamp of normal tags - void ReconcileTags( void ); - CEventRelativeTag *FindTagByName( const char *wavname, const char *name ); - CChoreoEvent *FindTargetingEvent( const char *wavname, const char *name ); - - // Used by UI to provide target actor names - char const *GetMapname( void ); - void SetMapname( const char *name ); - - void ExportEvents( const char *filename, CUtlVector< CChoreoEvent * >& events ); - void ImportEvents( ISceneTokenProcessor *tokenizer, CChoreoActor *actor, CChoreoChannel *channel ); - - // Subscene support - void SetSubScene( bool sub ); - bool IsSubScene( void ) const; - - int GetSceneFPS( void ) const; - void SetSceneFPS( int fps ); - bool IsUsingFrameSnap( void ) const; - void SetUsingFrameSnap( bool snap ); - - float SnapTime( float t ); - - int GetSceneRampCount( void ) { return m_SceneRamp.GetCount(); }; - CExpressionSample *GetSceneRamp( int index ) { return m_SceneRamp.Get( index ); }; - CExpressionSample *AddSceneRamp( float time, float value, bool selected ) { return m_SceneRamp.Add( time, value, selected ); }; - void DeleteSceneRamp( int index ) { m_SceneRamp.Delete( index ); }; - void ClearSceneRamp( void ) { m_SceneRamp.Clear(); }; - void ResortSceneRamp( void ) { m_SceneRamp.Resort( this ); }; - - CCurveData *GetSceneRamp( void ) { return &m_SceneRamp; }; - - - // Global intensity for scene - float GetSceneRampIntensity( float time ) { return m_SceneRamp.GetIntensity( this, time ); } - - int GetTimeZoom( char const *tool ); - void SetTimeZoom( char const *tool, int tz ); - int TimeZoomFirst(); - int TimeZoomNext( int i ); - int TimeZoomInvalid() const; - char const *TimeZoomName( int i ); - - void ReconcileCloseCaption(); - - char const *GetFilename() const; - void SetFileName( char const *fn ); - - bool GetPlayingSoundName( char *pchBuff, int iBuffLength ); - bool HasUnplayedSpeech(); - bool HasFlexAnimation(); - void SetBackground( bool bIsBackground ); - bool IsBackground( void ); - - void ClearPauseEventDependencies(); - - bool HasEventsOfType( CChoreoEvent::EVENTTYPE type ) const; - void RemoveEventsExceptTypes( int* typeList, int count ); - - void IgnorePhonemes( bool bIgnore ); - bool ShouldIgnorePhonemes() const; - - // This is set by the engine to signify that we're not modifying the data and - // therefore we can precompute the end time - static bool s_bEditingDisabled; - -private: - - // Simulation stuff - enum - { - IN_RANGE = 0, - BEFORE_RANGE, - AFTER_RANGE - }; - - int IsTimeInRange( float t, float starttime, float endtime ); - - typedef enum - { - PROCESSING_TYPE_IGNORE = 0, - PROCESSING_TYPE_START, - PROCESSING_TYPE_START_RESUMECONDITION, - PROCESSING_TYPE_CONTINUE, - PROCESSING_TYPE_STOP, - } PROCESSING_TYPE; - - struct ActiveList - { - PROCESSING_TYPE pt; - CChoreoEvent *e; - }; - - static bool EventLess( const CChoreoScene::ActiveList &al0, const CChoreoScene::ActiveList &al1 ); - - int EventThink( CChoreoEvent *e, - float frame_start_time, - float frame_end_time, - bool playing_forward, PROCESSING_TYPE& disposition ); - - // Prints to debug console, etc - void choreoprintf( int level, const char *fmt, ... ); - - // Initialize scene - void Init( IChoreoEventCallback *callback ); - - float FindAdjustedStartTime( void ); - float FindAdjustedEndTime( void ); - - CChoreoEvent *FindPauseBetweenTimes( float starttime, float endtime ); - - // Parse scenes from token buffer - CChoreoEvent *ParseEvent( CChoreoActor *actor, CChoreoChannel *channel ); - CChoreoChannel *ParseChannel( CChoreoActor *actor ); - CChoreoActor *ParseActor( void ); - - void ParseFPS( void ); - void ParseSnap( void ); - void ParseIgnorePhonemes( void ); - - // Map file for retrieving named objects - void ParseMapname( void ); - // When previewing actor in hlfaceposer, this is the model to associate - void ParseFacePoserModel( CChoreoActor *actor ); - - // Print to printfunc - void PrintEvent( int level, CChoreoEvent *e ); - void PrintChannel( int level, CChoreoChannel *c ); - void PrintActor( int level, CChoreoActor *a ); - - // File I/O -public: - static void FilePrintf( CUtlBuffer& buf, int level, const char *fmt, ... ); -private: - void FileSaveEvent( CUtlBuffer& buf, int level, CChoreoEvent *e ); - void FileSaveChannel( CUtlBuffer& buf, int level, CChoreoChannel *c ); - void FileSaveActor( CUtlBuffer& buf, int level, CChoreoActor *a ); - void FileSaveHeader( CUtlBuffer& buf ); - - // Object destruction - void DestroyActor( CChoreoActor *actor ); - void DestroyChannel( CChoreoChannel *channel ); - void DestroyEvent( CChoreoEvent *event ); - - - void AddPauseEventDependency( CChoreoEvent *pauseEvent, CChoreoEvent *suppressed ); - - void InternalDetermineEventTypes(); - - // Global object storage - CUtlVector < CChoreoEvent * > m_Events; - CUtlVector < CChoreoActor * > m_Actors; - CUtlVector < CChoreoChannel * > m_Channels; - - // These are just pointers, the actual objects are in m_Events - CUtlVector < CChoreoEvent * > m_ResumeConditions; - // These are just pointers, the actual objects are in m_Events - CUtlVector < CChoreoEvent * > m_ActiveResumeConditions; - // These are just pointers, the actual objects are in m_Events - CUtlVector < CChoreoEvent * > m_PauseEvents; - - // Current simulation time - float m_flCurrentTime; - - float m_flStartTime; - float m_flEndTime; - - float m_flEarliestTime; - float m_flLatestTime; - int m_nActiveEvents; - - // Wave file playback needs to issue play commands a bit ahead of time - // in order to hit exact marks - float m_flSoundSystemLatency; - - // Scene's linger a bit after finishing to let blends reset themselves - float m_flLastActiveTime; - - // Print callback function - void ( *m_pfnPrint )( const char *fmt, ... ); - - IChoreoEventCallback *m_pIChoreoEventCallback; - - ISceneTokenProcessor *m_pTokenizer; - - enum - { - MAX_MAPNAME = 128 - }; - - char m_szMapname[ MAX_MAPNAME ]; - - int m_nSceneFPS; - - CCurveData m_SceneRamp; - - CUtlDict< int, int > m_TimeZoomLookup; - char m_szFileName[ MAX_SCENE_FILENAME ]; - - CBitVec< CChoreoEvent::NUM_TYPES > m_bitvecHasEventOfType; - - // tag to suppress vcd when others are playing - bool m_bIsBackground : 1; - bool m_bIgnorePhonemes : 1; - bool m_bSubScene : 1; - bool m_bUseFrameSnap : 1; - bool m_bRestoring : 1; - - int m_nLastPauseEvent; - // This only gets updated if it's loaded from a buffer which means we're not in an editor - float m_flPrecomputedStopTime; -}; - - -bool CChoreoScene::IsRestoring() -{ - return m_bRestoring; -} - - -void CChoreoScene::SetRestoring( bool bRestoring ) -{ - m_bRestoring = bRestoring; -} - - -abstract_class IChoreoStringPool -{ -public: - virtual short FindOrAddString( const char *pString ) = 0; - virtual bool GetString( short stringId, char *buff, int buffSize ) = 0; -}; - -CChoreoScene *ChoreoLoadScene( - char const *filename, - IChoreoEventCallback *callback, - ISceneTokenProcessor *tokenizer, - void ( *pfn ) ( const char *fmt, ... ) ); - -bool IsBufferBinaryVCD( char *pBuffer, int bufferSize ); - -#endif // CHOREOSCENE_H diff --git a/game/shared/collisionproperty.cpp b/game/shared/collisionproperty.cpp deleted file mode 100644 index 2ccb457a7..000000000 --- a/game/shared/collisionproperty.cpp +++ /dev/null @@ -1,1345 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "collisionproperty.h" -#include "igamesystem.h" -#include "utlvector.h" -#include "tier0/threadtools.h" -#include "tier0/tslist.h" - -#ifdef CLIENT_DLL - -#include "c_baseentity.h" -#include "c_baseanimating.h" -#include "recvproxy.h" - -#else - -#include "baseentity.h" -#include "baseanimating.h" -#include "sendproxy.h" -#include "hierarchy.h" -#endif - -#include "predictable_entity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// KD tree query callbacks -//----------------------------------------------------------------------------- -class CDirtySpatialPartitionEntityList : public CAutoGameSystem, public IPartitionQueryCallback -{ -public: - CDirtySpatialPartitionEntityList( char const *name ); - - // Members of IGameSystem - virtual bool Init(); - virtual void Shutdown(); - virtual void LevelShutdownPostEntity(); - - // Members of IPartitionQueryCallback - virtual void OnPreQuery_V1() { Assert( 0 ); } - virtual void OnPreQuery( SpatialPartitionListMask_t listMask ); - virtual void OnPostQuery( SpatialPartitionListMask_t listMask ); - - void AddEntity( CBaseEntity *pEntity ); - - ~CDirtySpatialPartitionEntityList(); - void LockPartitionForRead() - { - if ( m_readLockCount == 0 ) - { - m_partitionMutex.LockForRead(); - } - m_readLockCount++; - } - void UnlockPartitionForRead() - { - m_readLockCount--; - if ( m_readLockCount == 0 ) - { - m_partitionMutex.UnlockRead(); - } - } - - -private: - CTSListWithFreeList m_DirtyEntities; - CThreadSpinRWLock m_partitionMutex; - uint32 m_partitionWriteId; - CThreadLocalInt<> m_readLockCount; -}; - - -//----------------------------------------------------------------------------- -// Singleton instance -//----------------------------------------------------------------------------- -static CDirtySpatialPartitionEntityList s_DirtyKDTree( "CDirtySpatialPartitionEntityList" ); - - -//----------------------------------------------------------------------------- -// Force spatial partition updates (to avoid threading problems caused by lazy update) -//----------------------------------------------------------------------------- -void UpdateDirtySpatialPartitionEntities() -{ - SpatialPartitionListMask_t listMask; -#ifdef CLIENT_DLL - listMask = PARTITION_CLIENT_GAME_EDICTS; -#else - listMask = PARTITION_SERVER_GAME_EDICTS; -#endif - s_DirtyKDTree.OnPreQuery( listMask ); - s_DirtyKDTree.OnPostQuery( listMask ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Constructor. -//----------------------------------------------------------------------------- -CDirtySpatialPartitionEntityList::CDirtySpatialPartitionEntityList( char const *name ) : CAutoGameSystem( name ) -{ - m_DirtyEntities.Purge(); - m_readLockCount = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: Deconstructor. -//----------------------------------------------------------------------------- -CDirtySpatialPartitionEntityList::~CDirtySpatialPartitionEntityList() -{ - m_DirtyEntities.Purge(); -} - -//----------------------------------------------------------------------------- -// Initialization, shutdown -//----------------------------------------------------------------------------- -bool CDirtySpatialPartitionEntityList::Init() -{ - partition->InstallQueryCallback( this ); - return true; -} - -void CDirtySpatialPartitionEntityList::Shutdown() -{ - partition->RemoveQueryCallback( this ); -} - - -//----------------------------------------------------------------------------- -// Makes sure all entries in the KD tree are in the correct position -//----------------------------------------------------------------------------- -void CDirtySpatialPartitionEntityList::AddEntity( CBaseEntity *pEntity ) -{ - m_DirtyEntities.PushItem( pEntity->GetRefEHandle() ); -} - - -//----------------------------------------------------------------------------- -// Members of IGameSystem -//----------------------------------------------------------------------------- -void CDirtySpatialPartitionEntityList::LevelShutdownPostEntity() -{ - m_DirtyEntities.RemoveAll(); -} - - -//----------------------------------------------------------------------------- -// Makes sure all entries in the KD tree are in the correct position -//----------------------------------------------------------------------------- -void CDirtySpatialPartitionEntityList::OnPreQuery( SpatialPartitionListMask_t listMask ) -{ -#ifdef CLIENT_DLL - const int validMask = PARTITION_CLIENT_GAME_EDICTS; -#else - const int validMask = PARTITION_SERVER_GAME_EDICTS; -#endif - - if ( !( listMask & validMask ) ) - return; - - if ( m_partitionWriteId != 0 && m_partitionWriteId == ThreadGetCurrentId() ) - return; - -#ifdef CLIENT_DLL - // FIXME: This should really be an assertion... feh! - if ( !C_BaseEntity::IsAbsRecomputationsEnabled() ) - { - LockPartitionForRead(); - return; - } -#endif - - // if you're holding a read lock, then these are entities that were still dirty after your trace started - // or became dirty due to some other thread or callback. Updating them may cause corruption further up the - // stack (e.g. partition iterator). Ignoring the state change should be safe since it happened after the - // trace was requested or was unable to be resolved in a previous attempt (still dirty). - if ( m_DirtyEntities.Count() && !m_readLockCount ) - { - CUtlVector< CBaseHandle > vecStillDirty; - m_partitionMutex.LockForWrite(); - m_partitionWriteId = ThreadGetCurrentId(); - CTSListWithFreeList::Node_t *pCurrent, *pNext; - while ( ( pCurrent = m_DirtyEntities.Detach() ) != NULL ) - { - while ( pCurrent ) - { - CBaseHandle handle = pCurrent->elem; - pNext = (CTSListWithFreeList::Node_t *)pCurrent->Next; - m_DirtyEntities.FreeNode( pCurrent ); - pCurrent = pNext; - -#ifndef CLIENT_DLL - CBaseEntity *pEntity = gEntList.GetBaseEntity( handle ); -#else - CBaseEntity *pEntity = cl_entitylist->GetBaseEntityFromHandle( handle ); -#endif - - if ( pEntity ) - { - // If an entity is in the middle of bone setup, don't call UpdatePartition - // which can cause it to redo bone setup on the same frame causing a recursive - // call to bone setup. - if ( !pEntity->IsEFlagSet( EFL_SETTING_UP_BONES ) ) - { - pEntity->CollisionProp()->UpdatePartition(); - } - else - { - vecStillDirty.AddToTail( handle ); - } - } - } - } - if ( vecStillDirty.Count() > 0 ) - { - for ( int i = 0; i < vecStillDirty.Count(); i++ ) - { - m_DirtyEntities.PushItem( vecStillDirty[i] ); - } - } - m_partitionWriteId = 0; - m_partitionMutex.UnlockWrite(); - } - LockPartitionForRead(); -} - -//----------------------------------------------------------------------------- -// Makes sure all entries in the KD tree are in the correct position -//----------------------------------------------------------------------------- -void CDirtySpatialPartitionEntityList::OnPostQuery( SpatialPartitionListMask_t listMask ) -{ -#ifdef CLIENT_DLL - if ( !( listMask & PARTITION_CLIENT_GAME_EDICTS ) ) - return; -#else - if ( !( listMask & PARTITION_SERVER_GAME_EDICTS ) ) - return; -#endif - - if ( m_partitionWriteId != 0 ) - return; - - UnlockPartitionForRead(); -} - - -//----------------------------------------------------------------------------- -// Save/load -//----------------------------------------------------------------------------- - -#ifndef CLIENT_DLL - - BEGIN_DATADESC_NO_BASE( CCollisionProperty ) - -// DEFINE_FIELD( m_pOuter, FIELD_CLASSPTR ), - DEFINE_GLOBAL_FIELD( m_vecMins, FIELD_VECTOR ), - DEFINE_GLOBAL_FIELD( m_vecMaxs, FIELD_VECTOR ), - DEFINE_KEYFIELD( m_nSolidType, FIELD_CHARACTER, "solid" ), - DEFINE_FIELD( m_usSolidFlags, FIELD_SHORT ), - DEFINE_FIELD( m_nSurroundType, FIELD_CHARACTER ), - DEFINE_FIELD( m_flRadius, FIELD_FLOAT ), - DEFINE_FIELD( m_triggerBloat, FIELD_CHARACTER ), - DEFINE_FIELD( m_vecSpecifiedSurroundingMins, FIELD_VECTOR ), - DEFINE_FIELD( m_vecSpecifiedSurroundingMaxs, FIELD_VECTOR ), - DEFINE_FIELD( m_vecSurroundingMins, FIELD_VECTOR ), - DEFINE_FIELD( m_vecSurroundingMaxs, FIELD_VECTOR ), -// DEFINE_FIELD( m_Partition, FIELD_SHORT ), -// DEFINE_PHYSPTR( m_pPhysicsObject ), - - END_DATADESC() - -#else - -//----------------------------------------------------------------------------- -// Prediction -//----------------------------------------------------------------------------- -BEGIN_PREDICTION_DATA_NO_BASE( CCollisionProperty ) - - DEFINE_PRED_FIELD( m_vecMins, FIELD_VECTOR, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_vecMaxs, FIELD_VECTOR, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_nSolidType, FIELD_CHARACTER, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_usSolidFlags, FIELD_SHORT, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_triggerBloat, FIELD_CHARACTER, FTYPEDESC_INSENDTABLE ), - -END_PREDICTION_DATA() - -#endif - -//----------------------------------------------------------------------------- -// Networking -//----------------------------------------------------------------------------- -#ifdef CLIENT_DLL - -static void RecvProxy_Solid( const CRecvProxyData *pData, void *pStruct, void *pOut ) -{ - ((CCollisionProperty*)pStruct)->SetSolid( (SolidType_t)pData->m_Value.m_Int ); -} - -static void RecvProxy_SolidFlags( const CRecvProxyData *pData, void *pStruct, void *pOut ) -{ - ((CCollisionProperty*)pStruct)->SetSolidFlags( pData->m_Value.m_Int ); -} - -static void RecvProxy_OBBMins( const CRecvProxyData *pData, void *pStruct, void *pOut ) -{ - CCollisionProperty *pProp = ((CCollisionProperty*)pStruct); - Vector &vecMins = *((Vector*)pData->m_Value.m_Vector); - pProp->SetCollisionBounds( vecMins, pProp->OBBMaxs() ); -} - -static void RecvProxy_OBBMaxs( const CRecvProxyData *pData, void *pStruct, void *pOut ) -{ - CCollisionProperty *pProp = ((CCollisionProperty*)pStruct); - Vector &vecMaxs = *((Vector*)pData->m_Value.m_Vector); - pProp->SetCollisionBounds( pProp->OBBMins(), vecMaxs ); -} - -static void RecvProxy_VectorDirtySurround( const CRecvProxyData *pData, void *pStruct, void *pOut ) -{ - Vector &vecold = *((Vector*)pOut); - Vector vecnew( pData->m_Value.m_Vector[0], pData->m_Value.m_Vector[1], pData->m_Value.m_Vector[2] ); - - if ( vecold != vecnew ) - { - vecold = vecnew; - ((CCollisionProperty*)pStruct)->MarkSurroundingBoundsDirty(); - } -} - -static void RecvProxy_IntDirtySurround( const CRecvProxyData *pData, void *pStruct, void *pOut ) -{ - if ( *((unsigned char*)pOut) != pData->m_Value.m_Int ) - { - *((unsigned char*)pOut) = pData->m_Value.m_Int; - ((CCollisionProperty*)pStruct)->MarkSurroundingBoundsDirty(); - } -} - -#else - -static void SendProxy_Solid( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ) -{ - pOut->m_Int = ((CCollisionProperty*)pStruct)->GetSolid(); -} - -static void SendProxy_SolidFlags( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ) -{ - pOut->m_Int = ((CCollisionProperty*)pStruct)->GetSolidFlags(); -} - -#endif - -BEGIN_NETWORK_TABLE_NOBASE( CCollisionProperty, DT_CollisionProperty ) - -#ifdef CLIENT_DLL - RecvPropVector( RECVINFO(m_vecMins), 0, RecvProxy_OBBMins ), - RecvPropVector( RECVINFO(m_vecMaxs), 0, RecvProxy_OBBMaxs ), - RecvPropInt( RECVINFO( m_nSolidType ), 0, RecvProxy_Solid ), - RecvPropInt( RECVINFO( m_usSolidFlags ), 0, RecvProxy_SolidFlags ), - RecvPropInt( RECVINFO(m_nSurroundType), 0, RecvProxy_IntDirtySurround ), - RecvPropInt( RECVINFO(m_triggerBloat), 0, RecvProxy_IntDirtySurround ), - RecvPropVector( RECVINFO(m_vecSpecifiedSurroundingMins), 0, RecvProxy_VectorDirtySurround ), - RecvPropVector( RECVINFO(m_vecSpecifiedSurroundingMaxs), 0, RecvProxy_VectorDirtySurround ), -#else - SendPropVector( SENDINFO(m_vecMins), 0, SPROP_NOSCALE), - SendPropVector( SENDINFO(m_vecMaxs), 0, SPROP_NOSCALE), - SendPropInt( SENDINFO( m_nSolidType ), 3, SPROP_UNSIGNED, SendProxy_Solid ), - SendPropInt( SENDINFO( m_usSolidFlags ), FSOLID_MAX_BITS, SPROP_UNSIGNED, SendProxy_SolidFlags ), - SendPropInt( SENDINFO( m_nSurroundType ), SURROUNDING_TYPE_BIT_COUNT, SPROP_UNSIGNED ), - SendPropInt( SENDINFO(m_triggerBloat), 0, SPROP_UNSIGNED), - SendPropVector( SENDINFO(m_vecSpecifiedSurroundingMins), 0, SPROP_NOSCALE), - SendPropVector( SENDINFO(m_vecSpecifiedSurroundingMaxs), 0, SPROP_NOSCALE), -#endif - -END_NETWORK_TABLE() - - -//----------------------------------------------------------------------------- -// Constructor, destructor -//----------------------------------------------------------------------------- -CCollisionProperty::CCollisionProperty() -{ - m_Partition = PARTITION_INVALID_HANDLE; - Init( NULL ); -} - -CCollisionProperty::~CCollisionProperty() -{ - DestroyPartitionHandle(); -} - - -//----------------------------------------------------------------------------- -// Initialization -//----------------------------------------------------------------------------- -void CCollisionProperty::Init( CBaseEntity *pEntity ) -{ - m_pOuter = pEntity; - m_vecMins.GetForModify().Init(); - m_vecMaxs.GetForModify().Init(); - m_flRadius = 0.0f; - m_triggerBloat = 0; - m_usSolidFlags = 0; - m_nSolidType = SOLID_NONE; - - // NOTE: This replicates previous behavior; we may always want to use BEST_COLLISION_BOUNDS - m_nSurroundType = USE_OBB_COLLISION_BOUNDS; - m_vecSurroundingMins = vec3_origin; - m_vecSurroundingMaxs = vec3_origin; - m_vecSpecifiedSurroundingMins.GetForModify().Init(); - m_vecSpecifiedSurroundingMaxs.GetForModify().Init(); -} - - -//----------------------------------------------------------------------------- -// EntityHandle -//----------------------------------------------------------------------------- -IHandleEntity *CCollisionProperty::GetEntityHandle() -{ - return m_pOuter; -} - - -//----------------------------------------------------------------------------- -// Collision group -//----------------------------------------------------------------------------- -int CCollisionProperty::GetCollisionGroup() const -{ - return m_pOuter->GetCollisionGroup(); -} - - -bool CCollisionProperty::ShouldTouchTrigger( int triggerSolidFlags ) const -{ - // debris only touches certain triggers - if ( GetCollisionGroup() == COLLISION_GROUP_DEBRIS ) - { - if ( triggerSolidFlags & FSOLID_TRIGGER_TOUCH_DEBRIS ) - return true; - - return false; - } - - // triggers don't touch other triggers (might be solid to other ents as well as trigger) - if ( IsSolidFlagSet( FSOLID_TRIGGER ) ) - return false; - - return true; -} - -const matrix3x4_t *CCollisionProperty::GetRootParentToWorldTransform() const -{ - if ( IsSolidFlagSet( FSOLID_ROOT_PARENT_ALIGNED ) ) - { - CBaseEntity *pEntity = m_pOuter->GetRootMoveParent(); - Assert(pEntity); - if ( pEntity ) - { - return &pEntity->CollisionProp()->CollisionToWorldTransform(); - } - } - return NULL; -} - -//----------------------------------------------------------------------------- -// IClientUnknown -//----------------------------------------------------------------------------- -IClientUnknown* CCollisionProperty::GetIClientUnknown() -{ -#ifdef CLIENT_DLL - return m_pOuter->GetIClientUnknown(); -#else - return NULL; -#endif -} - - - -//----------------------------------------------------------------------------- -// Check for untouch -//----------------------------------------------------------------------------- -void CCollisionProperty::CheckForUntouch() -{ -#ifndef CLIENT_DLL - if ( !IsSolid() && !IsSolidFlagSet(FSOLID_TRIGGER)) - { - // If this ent's touch list isn't empty, it's transitioning to not solid - if ( m_pOuter->IsCurrentlyTouching() ) - { - // mark ent so that at the end of frame it will check to - // see if it's no longer touching ents - m_pOuter->SetCheckUntouch( true ); - } - } -#endif -} - - -//----------------------------------------------------------------------------- -// Sets the solid type -//----------------------------------------------------------------------------- -void CCollisionProperty::SetSolid( SolidType_t val ) -{ - if ( m_nSolidType == val ) - return; - -#ifndef CLIENT_DLL - bool bWasNotSolid = IsSolid(); -#endif - - MarkSurroundingBoundsDirty(); - - // OBB is not yet implemented - if ( val == SOLID_BSP ) - { - if ( GetOuter()->GetMoveParent() ) - { - if ( GetOuter()->GetRootMoveParent()->GetSolid() != SOLID_BSP ) - { - // must be SOLID_VPHYSICS because parent might rotate - val = SOLID_VPHYSICS; - } - } -#ifndef CLIENT_DLL - // UNDONE: This should be fine in the client DLL too. Move GetAllChildren() into shared code. - // If the root of the hierarchy is SOLID_BSP, then assume that the designer - // wants the collisions to rotate with this hierarchy so that the player can - // move while riding the hierarchy. - if ( !GetOuter()->GetMoveParent() ) - { - // NOTE: This assumes things don't change back from SOLID_BSP - // NOTE: This is 100% true for HL2 - need to support removing the flag to support changing from SOLID_BSP - CUtlVector list; - GetAllChildren( GetOuter(), list ); - for ( int i = list.Count()-1; i>=0; --i ) - { - list[i]->AddSolidFlags( FSOLID_ROOT_PARENT_ALIGNED ); - } - } -#endif - } - - m_nSolidType = val; - -#ifndef CLIENT_DLL - m_pOuter->CollisionRulesChanged(); - - UpdateServerPartitionMask( ); - - if ( bWasNotSolid != IsSolid() ) - { - CheckForUntouch(); - } -#endif -} - -SolidType_t CCollisionProperty::GetSolid() const -{ - return (SolidType_t)m_nSolidType.Get(); -} - - -//----------------------------------------------------------------------------- -// Sets the solid flags -//----------------------------------------------------------------------------- -void CCollisionProperty::SetSolidFlags( int flags ) -{ - int oldFlags = m_usSolidFlags; - m_usSolidFlags = (unsigned short)(flags & 0xFFFF); - if ( oldFlags == m_usSolidFlags ) - return; - - // These two flags, if changed, can produce different surrounding bounds - if ( (oldFlags & (FSOLID_FORCE_WORLD_ALIGNED | FSOLID_USE_TRIGGER_BOUNDS)) != - (m_usSolidFlags & (FSOLID_FORCE_WORLD_ALIGNED | FSOLID_USE_TRIGGER_BOUNDS)) ) - { - MarkSurroundingBoundsDirty(); - } - - if ( (oldFlags & (FSOLID_NOT_SOLID|FSOLID_TRIGGER)) != (m_usSolidFlags & (FSOLID_NOT_SOLID|FSOLID_TRIGGER)) ) - { - m_pOuter->CollisionRulesChanged(); - } - -#ifndef CLIENT_DLL - if ( (oldFlags & (FSOLID_NOT_SOLID | FSOLID_TRIGGER)) != (m_usSolidFlags & (FSOLID_NOT_SOLID | FSOLID_TRIGGER)) ) - { - UpdateServerPartitionMask( ); - CheckForUntouch(); - } -#endif -} - - -//----------------------------------------------------------------------------- -// Coordinate system of the collision model -//----------------------------------------------------------------------------- -const Vector& CCollisionProperty::GetCollisionOrigin() const -{ - return m_pOuter->GetAbsOrigin(); -} - -const QAngle& CCollisionProperty::GetCollisionAngles() const -{ - if ( IsBoundsDefinedInEntitySpace() ) - { - return m_pOuter->GetAbsAngles(); - } - - return vec3_angle; -} - -const matrix3x4_t& CCollisionProperty::CollisionToWorldTransform() const -{ - static matrix3x4_t s_matTemp[4]; - static int s_nIndex = 0; - - matrix3x4_t &matResult = s_matTemp[s_nIndex]; - s_nIndex = (s_nIndex+1) & 0x3; - - if ( IsBoundsDefinedInEntitySpace() ) - { - return m_pOuter->EntityToWorldTransform(); - } - - SetIdentityMatrix( matResult ); - MatrixSetColumn( GetCollisionOrigin(), 3, matResult ); - return matResult; -} - - -//----------------------------------------------------------------------------- -// Sets the collision bounds + the size -//----------------------------------------------------------------------------- -void CCollisionProperty::SetCollisionBounds( const Vector& mins, const Vector &maxs ) -{ - if ( (m_vecMins == mins) && (m_vecMaxs == maxs) ) - return; - - m_vecMins = mins; - m_vecMaxs = maxs; - - //ASSERT_COORD( mins ); - //ASSERT_COORD( maxs ); - - Vector vecSize; - VectorSubtract( maxs, mins, vecSize ); - m_flRadius = vecSize.Length() * 0.5f; - - MarkSurroundingBoundsDirty(); -} - - -//----------------------------------------------------------------------------- -// Lazily calculates the 2D bounding radius. If we do this enough, we should -// calculate this in SetCollisionBounds above and cache the results in a data member! -//----------------------------------------------------------------------------- -float CCollisionProperty::BoundingRadius2D() const -{ - Vector vecSize; - VectorSubtract( m_vecMaxs, m_vecMins, vecSize ); - - vecSize.z = 0; - return vecSize.Length() * 0.5f; -} - - -//----------------------------------------------------------------------------- -// Bounding representation (OBB) -//----------------------------------------------------------------------------- -const Vector& CCollisionProperty::OBBMins( ) const -{ - return m_vecMins.Get(); -} - -const Vector& CCollisionProperty::OBBMaxs( ) const -{ - return m_vecMaxs.Get(); -} - - -//----------------------------------------------------------------------------- -// Special trigger representation (OBB) -//----------------------------------------------------------------------------- -void CCollisionProperty::WorldSpaceTriggerBounds( Vector *pVecWorldMins, Vector *pVecWorldMaxs ) const -{ - WorldSpaceAABB( pVecWorldMins, pVecWorldMaxs ); - if ( ( GetSolidFlags() & FSOLID_USE_TRIGGER_BOUNDS ) == 0 ) - return; - - // Don't bloat below, we don't want to trigger it with our heads - pVecWorldMins->x -= m_triggerBloat; - pVecWorldMins->y -= m_triggerBloat; - - pVecWorldMaxs->x += m_triggerBloat; - pVecWorldMaxs->y += m_triggerBloat; - pVecWorldMaxs->z += (float)m_triggerBloat * 0.5f; -} - -void CCollisionProperty::UseTriggerBounds( bool bEnable, float flBloat ) -{ - Assert( flBloat <= 127.0f ); - m_triggerBloat = (char )flBloat; - if ( bEnable ) - { - AddSolidFlags( FSOLID_USE_TRIGGER_BOUNDS ); - Assert( flBloat > 0.0f ); - } - else - { - RemoveSolidFlags( FSOLID_USE_TRIGGER_BOUNDS ); - } -} - - -//----------------------------------------------------------------------------- -// Collision model (BSP) -//----------------------------------------------------------------------------- -int CCollisionProperty::GetCollisionModelIndex() -{ - return m_pOuter->GetModelIndex(); -} - -const model_t* CCollisionProperty::GetCollisionModel() -{ - return m_pOuter->GetModel(); -} - - -//----------------------------------------------------------------------------- -// Collision methods implemented in the entity -// FIXME: This shouldn't happen there!! -//----------------------------------------------------------------------------- -bool CCollisionProperty::TestCollision( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ) -{ - return m_pOuter->TestCollision( ray, fContentsMask, tr ); -} - -bool CCollisionProperty::TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ) -{ - return m_pOuter->TestHitboxes( ray, fContentsMask, tr ); -} - - -//----------------------------------------------------------------------------- -// Computes a "normalized" point (range 0,0,0 - 1,1,1) in collision space -//----------------------------------------------------------------------------- -const Vector & CCollisionProperty::NormalizedToCollisionSpace( const Vector &in, Vector *pResult ) const -{ - pResult->x = Lerp( in.x, m_vecMins.Get().x, m_vecMaxs.Get().x ); - pResult->y = Lerp( in.y, m_vecMins.Get().y, m_vecMaxs.Get().y ); - pResult->z = Lerp( in.z, m_vecMins.Get().z, m_vecMaxs.Get().z ); - return *pResult; -} - - -//----------------------------------------------------------------------------- -// Transforms a point in collision space to normalized space -//----------------------------------------------------------------------------- -const Vector & CCollisionProperty::CollisionToNormalizedSpace( const Vector &in, Vector *pResult ) const -{ - Vector vecSize = OBBSize( ); - pResult->x = ( vecSize.x != 0.0f ) ? ( in.x - m_vecMins.Get().x ) / vecSize.x : 0.5f; - pResult->y = ( vecSize.y != 0.0f ) ? ( in.y - m_vecMins.Get().y ) / vecSize.y : 0.5f; - pResult->z = ( vecSize.z != 0.0f ) ? ( in.z - m_vecMins.Get().z ) / vecSize.z : 0.5f; - return *pResult; -} - - -//----------------------------------------------------------------------------- -// Computes a "normalized" point (range 0,0,0 - 1,1,1) in world space -//----------------------------------------------------------------------------- -const Vector & CCollisionProperty::NormalizedToWorldSpace( const Vector &in, Vector *pResult ) const -{ - Vector vecCollisionSpace; - NormalizedToCollisionSpace( in, &vecCollisionSpace ); - CollisionToWorldSpace( vecCollisionSpace, pResult ); - return *pResult; -} - - -//----------------------------------------------------------------------------- -// Transforms a point in world space to normalized space -//----------------------------------------------------------------------------- -const Vector & CCollisionProperty::WorldToNormalizedSpace( const Vector &in, Vector *pResult ) const -{ - Vector vecCollisionSpace; - WorldToCollisionSpace( in, &vecCollisionSpace ); - CollisionToNormalizedSpace( vecCollisionSpace, pResult ); - return *pResult; -} - - -//----------------------------------------------------------------------------- -// Selects a random point in the bounds given the normalized 0-1 bounds -//----------------------------------------------------------------------------- -void CCollisionProperty::RandomPointInBounds( const Vector &vecNormalizedMins, const Vector &vecNormalizedMaxs, Vector *pPoint) const -{ - Vector vecNormalizedSpace; - vecNormalizedSpace.x = random->RandomFloat( vecNormalizedMins.x, vecNormalizedMaxs.x ); - vecNormalizedSpace.y = random->RandomFloat( vecNormalizedMins.y, vecNormalizedMaxs.y ); - vecNormalizedSpace.z = random->RandomFloat( vecNormalizedMins.z, vecNormalizedMaxs.z ); - NormalizedToWorldSpace( vecNormalizedSpace, pPoint ); -} - - -//----------------------------------------------------------------------------- -// Transforms an AABB measured in entity space to a box that surrounds it in world space -//----------------------------------------------------------------------------- -void CCollisionProperty::CollisionAABBToWorldAABB( const Vector &entityMins, - const Vector &entityMaxs, Vector *pWorldMins, Vector *pWorldMaxs ) const -{ - if ( !IsBoundsDefinedInEntitySpace() || (GetCollisionAngles() == vec3_angle) ) - { - VectorAdd( entityMins, GetCollisionOrigin(), *pWorldMins ); - VectorAdd( entityMaxs, GetCollisionOrigin(), *pWorldMaxs ); - } - else - { - TransformAABB( CollisionToWorldTransform(), entityMins, entityMaxs, *pWorldMins, *pWorldMaxs ); - } -} - -/* -void CCollisionProperty::WorldAABBToCollisionAABB( const Vector &worldMins, const Vector &worldMaxs, Vector *pEntityMins, Vector *pEntityMaxs ) const -{ - if ( !IsBoundsDefinedInEntitySpace() || (GetCollisionAngles() == vec3_angle) ) - { - VectorSubtract( worldMins, GetAbsOrigin(), *pEntityMins ); - VectorSubtract( worldMaxs, GetAbsOrigin(), *pEntityMaxs ); - } - else - { - ITransformAABB( CollisionToWorldTransform(), worldMins, worldMaxs, *pEntityMins, *pEntityMaxs ); - } -} -*/ - - -//----------------------------------------------------------------------------- -// Is a worldspace point within the bounds of the OBB? -//----------------------------------------------------------------------------- -bool CCollisionProperty::IsPointInBounds( const Vector &vecWorldPt ) const -{ - Vector vecLocalSpace; - WorldToCollisionSpace( vecWorldPt, &vecLocalSpace ); - return ( ( vecLocalSpace.x >= m_vecMins.Get().x && vecLocalSpace.x <= m_vecMaxs.Get().x ) && - ( vecLocalSpace.y >= m_vecMins.Get().y && vecLocalSpace.y <= m_vecMaxs.Get().y ) && - ( vecLocalSpace.z >= m_vecMins.Get().z && vecLocalSpace.z <= m_vecMaxs.Get().z ) ); -} - - -//----------------------------------------------------------------------------- -// Computes the nearest point in the OBB to a point specified in world space -//----------------------------------------------------------------------------- -void CCollisionProperty::CalcNearestPoint( const Vector &vecWorldPt, Vector *pVecNearestWorldPt ) const -{ - // Calculate physics force - Vector localPt, localClosestPt; - WorldToCollisionSpace( vecWorldPt, &localPt ); - CalcClosestPointOnAABB( m_vecMins.Get(), m_vecMaxs.Get(), localPt, localClosestPt ); - CollisionToWorldSpace( localClosestPt, pVecNearestWorldPt ); -} - - -//----------------------------------------------------------------------------- -// Computes the nearest point in the OBB to a point specified in world space -//----------------------------------------------------------------------------- -float CCollisionProperty::CalcDistanceFromPoint( const Vector &vecWorldPt ) const -{ - // Calculate physics force - Vector localPt, localClosestPt; - WorldToCollisionSpace( vecWorldPt, &localPt ); - CalcClosestPointOnAABB( m_vecMins.Get(), m_vecMaxs.Get(), localPt, localClosestPt ); - return localPt.DistTo( localClosestPt ); -} - - -//----------------------------------------------------------------------------- -// Compute the largest dot product of the OBB and the specified direction vector -//----------------------------------------------------------------------------- -float CCollisionProperty::ComputeSupportMap( const Vector &vecDirection ) const -{ - Vector vecCollisionDir; - WorldDirectionToCollisionSpace( vecDirection, &vecCollisionDir ); - - float flResult = DotProduct( GetCollisionOrigin(), vecDirection ); - flResult += (( vecCollisionDir.x >= 0.0f ) ? m_vecMaxs.Get().x : m_vecMins.Get().x) * vecCollisionDir.x; - flResult += (( vecCollisionDir.y >= 0.0f ) ? m_vecMaxs.Get().y : m_vecMins.Get().y) * vecCollisionDir.y; - flResult += (( vecCollisionDir.z >= 0.0f ) ? m_vecMaxs.Get().z : m_vecMins.Get().z) * vecCollisionDir.z; - - return flResult; -} - - -//----------------------------------------------------------------------------- -// Expand trigger bounds.. -//----------------------------------------------------------------------------- -void CCollisionProperty::ComputeVPhysicsSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs ) -{ - bool bSetBounds = false; - IPhysicsObject *pPhysicsObject = GetOuter()->VPhysicsGetObject(); - if ( pPhysicsObject ) - { - if ( pPhysicsObject->GetCollide() ) - { - physcollision->CollideGetAABB( pVecWorldMins, pVecWorldMaxs, - pPhysicsObject->GetCollide(), GetCollisionOrigin(), GetCollisionAngles() ); - bSetBounds = true; - } - else if ( pPhysicsObject->GetSphereRadius( ) ) - { - float flRadius = pPhysicsObject->GetSphereRadius( ); - Vector vecExtents( flRadius, flRadius, flRadius ); - VectorSubtract( GetCollisionOrigin(), vecExtents, *pVecWorldMins ); - VectorAdd( GetCollisionOrigin(), vecExtents, *pVecWorldMaxs ); - bSetBounds = true; - } - } - - if ( !bSetBounds ) - { - *pVecWorldMins = GetCollisionOrigin(); - *pVecWorldMaxs = *pVecWorldMins; - } - - // Also, lets expand for the trigger bounds also - if ( IsSolidFlagSet( FSOLID_USE_TRIGGER_BOUNDS ) ) - { - Vector vecWorldTriggerMins, vecWorldTriggerMaxs; - WorldSpaceTriggerBounds( &vecWorldTriggerMins, &vecWorldTriggerMaxs ); - VectorMin( vecWorldTriggerMins, *pVecWorldMins, *pVecWorldMins ); - VectorMax( vecWorldTriggerMaxs, *pVecWorldMaxs, *pVecWorldMaxs ); - } -} - - -//----------------------------------------------------------------------------- -// Expand trigger bounds.. -//----------------------------------------------------------------------------- -bool CCollisionProperty::ComputeHitboxSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs ) -{ - CBaseAnimating *pAnim = GetOuter()->GetBaseAnimating(); - if (pAnim) - { - return pAnim->ComputeHitboxSurroundingBox( pVecWorldMins, pVecWorldMaxs ); - } - - return false; -} - -//----------------------------------------------------------------------------- -// Expand trigger bounds.. -//----------------------------------------------------------------------------- -bool CCollisionProperty::ComputeEntitySpaceHitboxSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs ) -{ - CBaseAnimating *pAnim = GetOuter()->GetBaseAnimating(); - if (pAnim) - { - return pAnim->ComputeEntitySpaceHitboxSurroundingBox( pVecWorldMins, pVecWorldMaxs ); - } - - return false; -} - -//----------------------------------------------------------------------------- -// Computes the surrounding collision bounds from the the OBB (not vphysics) -//----------------------------------------------------------------------------- -void CCollisionProperty::ComputeRotationExpandedBounds( Vector *pVecWorldMins, Vector *pVecWorldMaxs ) -{ - if ( !IsBoundsDefinedInEntitySpace() ) - { - *pVecWorldMins = m_vecMins; - *pVecWorldMaxs = m_vecMaxs; - } - else - { - float flMaxVal; - flMaxVal = MAX( FloatMakePositive(m_vecMins.Get().x), FloatMakePositive(m_vecMaxs.Get().x) ); - pVecWorldMins->x = -flMaxVal; - pVecWorldMaxs->x = flMaxVal; - - flMaxVal = MAX( FloatMakePositive(m_vecMins.Get().y), FloatMakePositive(m_vecMaxs.Get().y) ); - pVecWorldMins->y = -flMaxVal; - pVecWorldMaxs->y = flMaxVal; - - flMaxVal = MAX( FloatMakePositive(m_vecMins.Get().z), FloatMakePositive(m_vecMaxs.Get().z) ); - pVecWorldMins->z = -flMaxVal; - pVecWorldMaxs->z = flMaxVal; - } -} - - -//----------------------------------------------------------------------------- -// Computes the surrounding collision bounds based on whatever algorithm we want... -//----------------------------------------------------------------------------- -void CCollisionProperty::ComputeCollisionSurroundingBox( bool bUseVPhysics, Vector *pVecWorldMins, Vector *pVecWorldMaxs ) -{ - Assert( GetSolid() != SOLID_CUSTOM ); - - // NOTE: For solid none, we are still going to use the bounds; necessary because - // the surrounding box is used for the PVS... - // FIXME: Should we make some other call for the PVS stuff?? If so, we should return - // a point bounds for SOLID_NONE... -// if ( GetSolid() == SOLID_NONE ) -// { -// *pVecWorldMins = GetCollisionOrigin(); -// *pVecWorldMaxs = *pVecWorldMins; -// return; -// } - - if ( bUseVPhysics ) - { - ComputeVPhysicsSurroundingBox( pVecWorldMins, pVecWorldMaxs ); - } - else - { - // Will expand the bounds for the trigger, if it is a trigger - WorldSpaceTriggerBounds( pVecWorldMins, pVecWorldMaxs ); - } -} - - -//----------------------------------------------------------------------------- -// Computes the surrounding collision bounds based on whatever algorithm we want... -//----------------------------------------------------------------------------- -void CCollisionProperty::ComputeSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs ) -{ - if (( GetSolid() == SOLID_CUSTOM ) && (m_nSurroundType != USE_GAME_CODE )) - { - // NOTE: This can only happen in transition periods, say during network - // reception on the client. We expect USE_GAME_CODE to be used with SOLID_CUSTOM - *pVecWorldMins = GetCollisionOrigin(); - *pVecWorldMaxs = *pVecWorldMins; - return; - } - - switch( m_nSurroundType ) - { - case USE_OBB_COLLISION_BOUNDS: - { - Assert( GetSolid() != SOLID_CUSTOM ); - bool bUseVPhysics = false; - if ( ( GetSolid() == SOLID_VPHYSICS ) && ( GetOuter()->GetMoveType() == MOVETYPE_VPHYSICS ) ) - { - // UNDONE: This may not be necessary any more. - IPhysicsObject *pPhysics = GetOuter()->VPhysicsGetObject(); - bUseVPhysics = pPhysics && pPhysics->IsAsleep(); - } - ComputeCollisionSurroundingBox( bUseVPhysics, pVecWorldMins, pVecWorldMaxs ); - } - break; - - case USE_BEST_COLLISION_BOUNDS: - Assert( GetSolid() != SOLID_CUSTOM ); - ComputeCollisionSurroundingBox( (GetSolid() == SOLID_VPHYSICS), pVecWorldMins, pVecWorldMaxs ); - break; - - case USE_COLLISION_BOUNDS_NEVER_VPHYSICS: - Assert( GetSolid() != SOLID_CUSTOM ); - ComputeCollisionSurroundingBox( false, pVecWorldMins, pVecWorldMaxs ); - break; - - case USE_HITBOXES: - ComputeHitboxSurroundingBox( pVecWorldMins, pVecWorldMaxs ); - break; - - case USE_ROTATION_EXPANDED_BOUNDS: - ComputeRotationExpandedBounds( pVecWorldMins, pVecWorldMaxs ); - break; - - case USE_SPECIFIED_BOUNDS: - VectorAdd( GetCollisionOrigin(), m_vecSpecifiedSurroundingMins, *pVecWorldMins ); - VectorAdd( GetCollisionOrigin(), m_vecSpecifiedSurroundingMaxs, *pVecWorldMaxs ); - break; - - case USE_GAME_CODE: - GetOuter()->ComputeWorldSpaceSurroundingBox( pVecWorldMins, pVecWorldMaxs ); - Assert( pVecWorldMins->x <= pVecWorldMaxs->x ); - Assert( pVecWorldMins->y <= pVecWorldMaxs->y ); - Assert( pVecWorldMins->z <= pVecWorldMaxs->z ); - return; - } - -#ifdef DEBUG - /* - // For debugging purposes, make sure the bounds actually does surround the thing. - // Otherwise the optimization we were using isn't really all that great, is it? - Vector vecTestMins, vecTestMaxs; - ComputeCollisionSurroundingBox( (GetSolid() == SOLID_VPHYSICS), &vecTestMins, &vecTestMaxs ); - - // Now that we have the basics, let's expand for hitboxes if appropriate - Vector vecWorldHitboxMins, vecWorldHitboxMaxs; - if ( ComputeHitboxSurroundingBox( &vecWorldHitboxMins, &vecWorldHitboxMaxs ) ) - { - VectorMin( vecWorldHitboxMaxs, vecTestMins, vecTestMins ); - VectorMax( vecWorldHitboxMaxs, vecTestMaxs, vecTestMaxs ); - } - - Assert( vecTestMins.x >= pVecWorldMins->x && vecTestMins.y >= pVecWorldMins->y && vecTestMins.z >= pVecWorldMins->z ); - Assert( vecTestMaxs.x <= pVecWorldMaxs->x && vecTestMaxs.y <= pVecWorldMaxs->y && vecTestMaxs.z <= pVecWorldMaxs->z ); - */ -#endif -} - - -//----------------------------------------------------------------------------- -// Sets the method by which the surrounding collision bounds is set -//----------------------------------------------------------------------------- -void CCollisionProperty::SetSurroundingBoundsType( SurroundingBoundsType_t type, const Vector *pMins, const Vector *pMaxs ) -{ - m_nSurroundType = type; - if (type != USE_SPECIFIED_BOUNDS) - { - Assert( !pMins && !pMaxs ); - MarkSurroundingBoundsDirty(); - } - else - { - Assert( pMins && pMaxs ); - m_vecSpecifiedSurroundingMins = *pMins; - m_vecSpecifiedSurroundingMaxs = *pMaxs; - m_vecSurroundingMins = *pMins; - m_vecSurroundingMaxs = *pMaxs; - - ASSERT_COORD( m_vecSurroundingMins ); - ASSERT_COORD( m_vecSurroundingMaxs ); - } -} - - -//----------------------------------------------------------------------------- -// Marks the entity has having a dirty surrounding box -//----------------------------------------------------------------------------- -void CCollisionProperty::MarkSurroundingBoundsDirty() -{ - GetOuter()->AddEFlags( EFL_DIRTY_SURROUNDING_COLLISION_BOUNDS ); - MarkPartitionHandleDirty(); - -#ifdef CLIENT_DLL - g_pClientShadowMgr->MarkRenderToTextureShadowDirty( GetOuter()->GetShadowHandle() ); -#else - GetOuter()->NetworkProp()->MarkPVSInformationDirty(); -#endif -} - - -//----------------------------------------------------------------------------- -// Does VPhysicsUpdate make us need to recompute the surrounding box? -//----------------------------------------------------------------------------- -bool CCollisionProperty::DoesVPhysicsInvalidateSurroundingBox( ) const -{ - switch ( m_nSurroundType ) - { - case USE_BEST_COLLISION_BOUNDS: - return true; - - case USE_OBB_COLLISION_BOUNDS: - return (GetSolid() == SOLID_VPHYSICS) && (GetOuter()->GetMoveType() == MOVETYPE_VPHYSICS) && GetOuter()->VPhysicsGetObject(); - - // In the case of game code, we don't really know, so we have to assume it does - case USE_GAME_CODE: - return true; - - case USE_COLLISION_BOUNDS_NEVER_VPHYSICS: - case USE_HITBOXES: - case USE_ROTATION_EXPANDED_BOUNDS: - case USE_SPECIFIED_BOUNDS: - return false; - - default: - Assert(0); - return true; - } -} - - -//----------------------------------------------------------------------------- -// Computes the surrounding collision bounds based on whatever algorithm we want... -//----------------------------------------------------------------------------- -void CCollisionProperty::WorldSpaceSurroundingBounds( Vector *pVecMins, Vector *pVecMaxs ) -{ - const Vector &vecAbsOrigin = GetCollisionOrigin(); - if ( GetOuter()->IsEFlagSet( EFL_DIRTY_SURROUNDING_COLLISION_BOUNDS )) - { - GetOuter()->RemoveEFlags( EFL_DIRTY_SURROUNDING_COLLISION_BOUNDS ); - ComputeSurroundingBox( pVecMins, pVecMaxs ); - VectorSubtract( *pVecMins, vecAbsOrigin, m_vecSurroundingMins ); - VectorSubtract( *pVecMaxs, vecAbsOrigin, m_vecSurroundingMaxs ); - - ASSERT_COORD( m_vecSurroundingMins ); - ASSERT_COORD( m_vecSurroundingMaxs ); - } - else - { - VectorAdd( m_vecSurroundingMins, vecAbsOrigin, *pVecMins ); - VectorAdd( m_vecSurroundingMaxs, vecAbsOrigin, *pVecMaxs ); - } -} - - -//----------------------------------------------------------------------------- -// Spatial partition -//----------------------------------------------------------------------------- -void CCollisionProperty::CreatePartitionHandle() -{ - // Put the entity into the spatial partition. - Assert( m_Partition == PARTITION_INVALID_HANDLE ); - m_Partition = partition->CreateHandle( GetEntityHandle() ); -} - -void CCollisionProperty::DestroyPartitionHandle() -{ - if ( m_Partition != PARTITION_INVALID_HANDLE ) - { - partition->DestroyHandle( m_Partition ); - m_Partition = PARTITION_INVALID_HANDLE; - } -} - - -//----------------------------------------------------------------------------- -// Updates the spatial partition -//----------------------------------------------------------------------------- -void CCollisionProperty::UpdateServerPartitionMask( ) -{ -#ifndef CLIENT_DLL - SpatialPartitionHandle_t handle = GetPartitionHandle(); - if ( handle == PARTITION_INVALID_HANDLE ) - return; - - // Remove it from whatever lists it may be in at the moment - // We'll re-add it below if we need to. - partition->Remove( handle ); - - // Don't bother with deleted things - if ( !m_pOuter->edict() ) - return; - - // don't add the world - if ( m_pOuter->entindex() == 0 ) - return; - - // Make sure it's in the list of all entities - bool bIsSolid = IsSolid() || IsSolidFlagSet(FSOLID_TRIGGER); - if ( bIsSolid || m_pOuter->IsEFlagSet(EFL_USE_PARTITION_WHEN_NOT_SOLID) ) - { - partition->Insert( PARTITION_ENGINE_NON_STATIC_EDICTS, handle ); - } - - if ( !bIsSolid ) - return; - - // Insert it into the appropriate lists. - // We have to continually reinsert it because its solid type may have changed - SpatialPartitionListMask_t mask = 0; - if ( !IsSolidFlagSet(FSOLID_NOT_SOLID) ) - { - mask |= PARTITION_ENGINE_SOLID_EDICTS; - } - if ( IsSolidFlagSet(FSOLID_TRIGGER) ) - { - mask |= PARTITION_ENGINE_TRIGGER_EDICTS; - } - Assert( mask != 0 ); - partition->Insert( mask, handle ); -#endif -} - - -//----------------------------------------------------------------------------- -// Marks the spatial partition dirty -//----------------------------------------------------------------------------- -void CCollisionProperty::MarkPartitionHandleDirty() -{ - // don't bother with the world - if ( m_pOuter->entindex() == 0 ) - return; - - if ( !m_pOuter->IsEFlagSet( EFL_DIRTY_SPATIAL_PARTITION ) ) - { - m_pOuter->AddEFlags( EFL_DIRTY_SPATIAL_PARTITION ); - s_DirtyKDTree.AddEntity( m_pOuter ); - } - -#ifdef CLIENT_DLL - GetOuter()->MarkRenderHandleDirty(); - g_pClientShadowMgr->AddToDirtyShadowList( GetOuter() ); -#endif -} - - -//----------------------------------------------------------------------------- -// Updates the spatial partition -//----------------------------------------------------------------------------- -void CCollisionProperty::UpdatePartition( ) -{ - if ( m_pOuter->IsEFlagSet( EFL_DIRTY_SPATIAL_PARTITION ) ) - { - m_pOuter->RemoveEFlags( EFL_DIRTY_SPATIAL_PARTITION ); - -#ifndef CLIENT_DLL - Assert( m_pOuter->entindex() != 0 ); - - // Don't bother with deleted things - if ( !m_pOuter->edict() ) - return; - - if ( GetPartitionHandle() == PARTITION_INVALID_HANDLE ) - { - CreatePartitionHandle(); - UpdateServerPartitionMask(); - } -#else - if ( GetPartitionHandle() == PARTITION_INVALID_HANDLE ) - return; -#endif - - // We don't need to bother if it's not a trigger or solid - if ( IsSolid() || IsSolidFlagSet( FSOLID_TRIGGER ) || m_pOuter->IsEFlagSet( EFL_USE_PARTITION_WHEN_NOT_SOLID ) ) - { - // Bloat a little bit... - if ( BoundingRadius() != 0.0f ) - { - Vector vecSurroundMins, vecSurroundMaxs; - WorldSpaceSurroundingBounds( &vecSurroundMins, &vecSurroundMaxs ); - vecSurroundMins -= Vector( 1, 1, 1 ); - vecSurroundMaxs += Vector( 1, 1, 1 ); - partition->ElementMoved( GetPartitionHandle(), vecSurroundMins, vecSurroundMaxs ); - } - else - { - partition->ElementMoved( GetPartitionHandle(), GetCollisionOrigin(), GetCollisionOrigin() ); - } - } - } -} - - diff --git a/game/shared/collisionproperty.h b/game/shared/collisionproperty.h deleted file mode 100644 index 9793be117..000000000 --- a/game/shared/collisionproperty.h +++ /dev/null @@ -1,503 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef COLLISIONPROPERTY_H -#define COLLISIONPROPERTY_H -#ifdef _WIN32 -#pragma once -#endif - -#include "networkvar.h" -#include "engine/ICollideable.h" -#include "mathlib/vector.h" -#include "ispatialpartition.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class CBaseEntity; -class IHandleEntity; -class QAngle; -class Vector; -struct Ray_t; -class IPhysicsObject; - - -//----------------------------------------------------------------------------- -// Force spatial partition updates (to avoid threading problems caused by lazy update) -//----------------------------------------------------------------------------- -void UpdateDirtySpatialPartitionEntities(); - - -//----------------------------------------------------------------------------- -// Specifies how to compute the surrounding box -//----------------------------------------------------------------------------- -enum SurroundingBoundsType_t -{ - USE_OBB_COLLISION_BOUNDS = 0, - USE_BEST_COLLISION_BOUNDS, // Always use the best bounds (most expensive) - USE_HITBOXES, - USE_SPECIFIED_BOUNDS, - USE_GAME_CODE, - USE_ROTATION_EXPANDED_BOUNDS, - USE_COLLISION_BOUNDS_NEVER_VPHYSICS, - - SURROUNDING_TYPE_BIT_COUNT = 3 -}; - - -//----------------------------------------------------------------------------- -// Encapsulates collision representation for an entity -//----------------------------------------------------------------------------- -class CCollisionProperty : public ICollideable -{ - DECLARE_CLASS_NOBASE( CCollisionProperty ); - DECLARE_EMBEDDED_NETWORKVAR(); - DECLARE_PREDICTABLE(); - -#ifdef GAME_DLL - DECLARE_DATADESC(); -#endif - -public: - CCollisionProperty(); - ~CCollisionProperty(); - - void Init( CBaseEntity *pEntity ); - - // Methods of ICollideable - virtual IHandleEntity *GetEntityHandle(); - virtual const Vector& OBBMinsPreScaled() const { return m_vecMinsPreScaled.Get(); } - virtual const Vector& OBBMaxsPreScaled() const { return m_vecMaxsPreScaled.Get(); } - virtual const Vector& OBBMins() const { return m_vecMins.Get(); } - virtual const Vector& OBBMaxs() const { return m_vecMaxs.Get(); } - virtual void WorldSpaceTriggerBounds( Vector *pVecWorldMins, Vector *pVecWorldMaxs ) const; - virtual bool TestCollision( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ); - virtual bool TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ); - virtual int GetCollisionModelIndex(); - virtual const model_t* GetCollisionModel(); - virtual const Vector& GetCollisionOrigin() const; - virtual const QAngle& GetCollisionAngles() const; - virtual const matrix3x4_t& CollisionToWorldTransform() const; - virtual SolidType_t GetSolid() const; - virtual int GetSolidFlags() const; - virtual IClientUnknown* GetIClientUnknown(); - virtual int GetCollisionGroup() const; - virtual void WorldSpaceSurroundingBounds( Vector *pVecMins, Vector *pVecMaxs ); - virtual bool ShouldTouchTrigger( int triggerSolidFlags ) const; - virtual const matrix3x4_t *GetRootParentToWorldTransform() const; - -public: - // Spatial partition management - void CreatePartitionHandle(); - void DestroyPartitionHandle(); - unsigned short GetPartitionHandle() const; - - // Marks the spatial partition dirty - void MarkPartitionHandleDirty(); - - // Sets the collision bounds + the size (OBB) - void SetCollisionBounds( const Vector& mins, const Vector &maxs ); - - // Rebuilds the scaled bounds from the pre-scaled bounds after a model's scale has changed - void RefreshScaledCollisionBounds( void ); - - // Sets special trigger bounds. The bloat amount indicates how much bigger the - // trigger bounds should be beyond the bounds set in SetCollisionBounds - // This method will also set the FSOLID flag FSOLID_USE_TRIGGER_BOUNDS - void UseTriggerBounds( bool bEnable, float flBloat = 0.0f ); - - // Sets the method by which the surrounding collision bounds is set - // You must pass in values for mins + maxs if you select the USE_SPECIFIED_BOUNDS type. - void SetSurroundingBoundsType( SurroundingBoundsType_t type, const Vector *pMins = NULL, const Vector *pMaxs = NULL ); - - // Sets the solid type (which type of collision representation) - void SetSolid( SolidType_t val ); - - // Methods related to size. The OBB here is measured in CollisionSpace - // (specified by GetCollisionToWorld) - const Vector& OBBSize( ) const; - - // Returns a radius (or the square of the radius) of a sphere - // *centered at the world space center* bounding the collision representation - // of the entity. NOTE: The world space center *may* move when the entity rotates. - float BoundingRadius() const; - float BoundingRadius2D() const; - - // Returns the center of the OBB in collision space - const Vector & OBBCenter( ) const; - - // center point of entity measured in world space - // NOTE: This point *may* move when the entity moves depending on - // which solid type is being used. - const Vector & WorldSpaceCenter( ) const; - - // Methods related to solid flags - void ClearSolidFlags( void ); - void RemoveSolidFlags( int flags ); - void AddSolidFlags( int flags ); - bool IsSolidFlagSet( int flagMask ) const; - void SetSolidFlags( int flags ); - bool IsSolid() const; - - // Updates the spatial partition - void UpdatePartition( ); - - // Are the bounds defined in entity space? - bool IsBoundsDefinedInEntitySpace() const; - - // Transforms a point in OBB space to world space - const Vector & CollisionToWorldSpace( const Vector &in, Vector *pResult ) const; - - // Transforms a point in world space to OBB space - const Vector & WorldToCollisionSpace( const Vector &in, Vector *pResult ) const; - - // Transforms a direction in world space to OBB space - const Vector & WorldDirectionToCollisionSpace( const Vector &in, Vector *pResult ) const; - - // Selects a random point in the bounds given the normalized 0-1 bounds - void RandomPointInBounds( const Vector &vecNormalizedMins, const Vector &vecNormalizedMaxs, Vector *pPoint) const; - - // Is a worldspace point within the bounds of the OBB? - bool IsPointInBounds( const Vector &vecWorldPt ) const; - - // Computes a bounding box in world space surrounding the collision bounds - void WorldSpaceAABB( Vector *pWorldMins, Vector *pWorldMaxs ) const; - - // Get the collision space mins directly - const Vector & CollisionSpaceMins( void ) const; - - // Get the collision space maxs directly - const Vector & CollisionSpaceMaxs( void ) const; - - // Computes a "normalized" point (range 0,0,0 - 1,1,1) in collision space - // Useful for things like getting a point 75% of the way along z on the OBB, for example - const Vector & NormalizedToCollisionSpace( const Vector &in, Vector *pResult ) const; - - // Computes a "normalized" point (range 0,0,0 - 1,1,1) in world space - const Vector & NormalizedToWorldSpace( const Vector &in, Vector *pResult ) const; - - // Transforms a point in world space to normalized space - const Vector & WorldToNormalizedSpace( const Vector &in, Vector *pResult ) const; - - // Transforms a point in collision space to normalized space - const Vector & CollisionToNormalizedSpace( const Vector &in, Vector *pResult ) const; - - // Computes the nearest point in the OBB to a point specified in world space - void CalcNearestPoint( const Vector &vecWorldPt, Vector *pVecNearestWorldPt ) const; - - // Computes the distance from a point in world space to the OBB - float CalcDistanceFromPoint( const Vector &vecWorldPt ) const; - - // Does a rotation make us need to recompute the surrounding box? - bool DoesRotationInvalidateSurroundingBox( ) const; - - // Does VPhysicsUpdate make us need to recompute the surrounding box? - bool DoesVPhysicsInvalidateSurroundingBox( ) const; - - // Marks the entity has having a dirty surrounding box - void MarkSurroundingBoundsDirty(); - - // Compute the largest dot product of the OBB and the specified direction vector - float ComputeSupportMap( const Vector &vecDirection ) const; - -private: - // Transforms an AABB measured in collision space to a box that surrounds it in world space - void CollisionAABBToWorldAABB( const Vector &entityMins, const Vector &entityMaxs, Vector *pWorldMins, Vector *pWorldMaxs ) const; - - // Expand trigger bounds.. - void ComputeVPhysicsSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs ); - - // Expand trigger bounds.. - bool ComputeHitboxSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs ); - bool ComputeEntitySpaceHitboxSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs ); - - // Computes the surrounding collision bounds based on whatever algorithm we want... - void ComputeCollisionSurroundingBox( bool bUseVPhysics, Vector *pVecWorldMins, Vector *pVecWorldMaxs ); - - // Computes the surrounding collision bounds from the the OBB (not vphysics) - void ComputeRotationExpandedBounds( Vector *pVecWorldMins, Vector *pVecWorldMaxs ); - - // Computes the surrounding collision bounds based on whatever algorithm we want... - void ComputeSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs ); - - // Check for untouch - void CheckForUntouch(); - - // Updates the spatial partition - void UpdateServerPartitionMask( ); - - // Outer - CBaseEntity *GetOuter(); - const CBaseEntity *GetOuter() const; - -private: - CBaseEntity *m_pOuter; - - CNetworkVector( m_vecMinsPreScaled ); - CNetworkVector( m_vecMaxsPreScaled ); - CNetworkVector( m_vecMins ); - CNetworkVector( m_vecMaxs ); - float m_flRadius; - - CNetworkVar( unsigned short, m_usSolidFlags ); - - // Spatial partition - SpatialPartitionHandle_t m_Partition; - CNetworkVar( unsigned char, m_nSurroundType ); - - // One of the SOLID_ defines. Use GetSolid/SetSolid. - CNetworkVar( unsigned char, m_nSolidType ); - CNetworkVar( unsigned char , m_triggerBloat ); - - // SUCKY: We didn't use to have to store this previously - // but storing it here means that we can network it + avoid a ton of - // client-side mismatch problems - CNetworkVector( m_vecSpecifiedSurroundingMinsPreScaled ); - CNetworkVector( m_vecSpecifiedSurroundingMaxsPreScaled ); - CNetworkVector( m_vecSpecifiedSurroundingMins ); - CNetworkVector( m_vecSpecifiedSurroundingMaxs ); - - // Cached off world-aligned surrounding bounds -#if 0 - short m_surroundingMins[3]; - short m_surroundingMaxs[3]; -#else - Vector m_vecSurroundingMins; - Vector m_vecSurroundingMaxs; -#endif - - // pointer to the entity's physics object (vphysics.dll) - //IPhysicsObject *m_pPhysicsObject; - - friend class CBaseEntity; -}; - - -//----------------------------------------------------------------------------- -// For networking this bad boy -//----------------------------------------------------------------------------- -#ifdef CLIENT_DLL -EXTERN_RECV_TABLE( DT_CollisionProperty ); -#else -EXTERN_SEND_TABLE( DT_CollisionProperty ); -#endif - - -//----------------------------------------------------------------------------- -// Inline methods -//----------------------------------------------------------------------------- -inline CBaseEntity *CCollisionProperty::GetOuter() -{ - return m_pOuter; -} - -inline const CBaseEntity *CCollisionProperty::GetOuter() const -{ - return m_pOuter; -} - - -//----------------------------------------------------------------------------- -// Spatial partition -//----------------------------------------------------------------------------- -inline unsigned short CCollisionProperty::GetPartitionHandle() const -{ - return m_Partition; -} - - -//----------------------------------------------------------------------------- -// Methods related to size -//----------------------------------------------------------------------------- -inline const Vector& CCollisionProperty::OBBSize( ) const -{ - // NOTE: Could precache this, but it's not used that often.. - Vector &temp = AllocTempVector(); - VectorSubtract( m_vecMaxs, m_vecMins, temp ); - return temp; -} - - -//----------------------------------------------------------------------------- -// Bounding radius size -//----------------------------------------------------------------------------- -inline float CCollisionProperty::BoundingRadius() const -{ - return m_flRadius; -} - - -//----------------------------------------------------------------------------- -// Methods relating to solid flags -//----------------------------------------------------------------------------- -inline bool CCollisionProperty::IsBoundsDefinedInEntitySpace() const -{ - return (( m_usSolidFlags & FSOLID_FORCE_WORLD_ALIGNED ) == 0 ) && - ( m_nSolidType != SOLID_BBOX ) && ( m_nSolidType != SOLID_NONE ); -} - -inline void CCollisionProperty::ClearSolidFlags( void ) -{ - SetSolidFlags( 0 ); -} - -inline void CCollisionProperty::RemoveSolidFlags( int flags ) -{ - SetSolidFlags( m_usSolidFlags & ~flags ); -} - -inline void CCollisionProperty::AddSolidFlags( int flags ) -{ - SetSolidFlags( m_usSolidFlags | flags ); -} - -inline int CCollisionProperty::GetSolidFlags( void ) const -{ - return m_usSolidFlags; -} - -inline bool CCollisionProperty::IsSolidFlagSet( int flagMask ) const -{ - return (m_usSolidFlags & flagMask) != 0; -} - -inline bool CCollisionProperty::IsSolid() const -{ - return ::IsSolid( (SolidType_t)(unsigned char)m_nSolidType, m_usSolidFlags ); -} - - -//----------------------------------------------------------------------------- -// Returns the center in OBB space -//----------------------------------------------------------------------------- -inline const Vector& CCollisionProperty::OBBCenter( ) const -{ - Vector &vecResult = AllocTempVector(); - VectorLerp( m_vecMins, m_vecMaxs, 0.5f, vecResult ); - return vecResult; -} - - -//----------------------------------------------------------------------------- -// center point of entity -//----------------------------------------------------------------------------- -inline const Vector &CCollisionProperty::WorldSpaceCenter( ) const -{ - Vector &vecResult = AllocTempVector(); - CollisionToWorldSpace( OBBCenter(), &vecResult ); - return vecResult; -} - - -//----------------------------------------------------------------------------- -// Transforms a point in OBB space to world space -//----------------------------------------------------------------------------- -inline const Vector &CCollisionProperty::CollisionToWorldSpace( const Vector &in, Vector *pResult ) const -{ - // Makes sure we don't re-use the same temp twice - if ( !IsBoundsDefinedInEntitySpace() || ( GetCollisionAngles() == vec3_angle ) ) - { - VectorAdd( in, GetCollisionOrigin(), *pResult ); - } - else - { - VectorTransform( in, CollisionToWorldTransform(), *pResult ); - } - return *pResult; -} - - -//----------------------------------------------------------------------------- -// Transforms a point in world space to OBB space -//----------------------------------------------------------------------------- -inline const Vector &CCollisionProperty::WorldToCollisionSpace( const Vector &in, Vector *pResult ) const -{ - if ( !IsBoundsDefinedInEntitySpace() || ( GetCollisionAngles() == vec3_angle ) ) - { - VectorSubtract( in, GetCollisionOrigin(), *pResult ); - } - else - { - VectorITransform( in, CollisionToWorldTransform(), *pResult ); - } - return *pResult; -} - - -//----------------------------------------------------------------------------- -// Transforms a direction in world space to OBB space -//----------------------------------------------------------------------------- -inline const Vector & CCollisionProperty::WorldDirectionToCollisionSpace( const Vector &in, Vector *pResult ) const -{ - if ( !IsBoundsDefinedInEntitySpace() || ( GetCollisionAngles() == vec3_angle ) ) - { - *pResult = in; - } - else - { - VectorIRotate( in, CollisionToWorldTransform(), *pResult ); - } - return *pResult; -} - - -//----------------------------------------------------------------------------- -// Computes a bounding box in world space surrounding the collision bounds -//----------------------------------------------------------------------------- -inline void CCollisionProperty::WorldSpaceAABB( Vector *pWorldMins, Vector *pWorldMaxs ) const -{ - CollisionAABBToWorldAABB( m_vecMins, m_vecMaxs, pWorldMins, pWorldMaxs ); -} - - -// Get the collision space mins directly -inline const Vector & CCollisionProperty::CollisionSpaceMins( void ) const -{ - return m_vecMins; -} - -// Get the collision space maxs directly -inline const Vector & CCollisionProperty::CollisionSpaceMaxs( void ) const -{ - return m_vecMaxs; -} - - -//----------------------------------------------------------------------------- -// Does a rotation make us need to recompute the surrounding box? -//----------------------------------------------------------------------------- -inline bool CCollisionProperty::DoesRotationInvalidateSurroundingBox( ) const -{ - if ( IsSolidFlagSet(FSOLID_ROOT_PARENT_ALIGNED) ) - return true; - - switch ( m_nSurroundType ) - { - case USE_COLLISION_BOUNDS_NEVER_VPHYSICS: - case USE_OBB_COLLISION_BOUNDS: - case USE_BEST_COLLISION_BOUNDS: - return IsBoundsDefinedInEntitySpace(); - - // In the case of game code, we don't really know, so we have to assume it does - case USE_HITBOXES: - case USE_GAME_CODE: - return true; - - case USE_ROTATION_EXPANDED_BOUNDS: - case USE_SPECIFIED_BOUNDS: - return false; - - default: - Assert(0); - return true; - } -} - - -#endif // COLLISIONPROPERTY_H diff --git a/game/shared/death_pose.cpp b/game/shared/death_pose.cpp deleted file mode 100644 index 4620874fd..000000000 --- a/game/shared/death_pose.cpp +++ /dev/null @@ -1,170 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#include "death_pose.h" - -#ifdef CLIENT_DLL - -void GetRagdollCurSequenceWithDeathPose( C_BaseAnimating *entity, matrix3x4_t *curBones, float flTime, int activity, int frame ) -{ - // blow the cached prev bones - entity->InvalidateBoneCache(); - - Vector vPrevOrigin = entity->GetAbsOrigin(); - - entity->Interpolate( flTime ); - - if ( activity != ACT_INVALID ) - { - Vector vNewOrigin = entity->GetAbsOrigin(); - Vector vDirection = vNewOrigin - vPrevOrigin; - - float flVelocity = VectorNormalize( vDirection ); - - Vector vAdjustedOrigin = vNewOrigin + vDirection * ( ( flVelocity * flVelocity ) * gpGlobals->frametime ); - - int iTempSequence = entity->GetSequence(); - float flTempCycle = entity->GetCycle(); - - entity->SetEffects( EF_NOINTERP ); - - entity->SetSequence( activity ); - - entity->SetCycle( (float)frame / MAX_DEATHPOSE_FRAMES ); - - entity->SetAbsOrigin( vAdjustedOrigin ); - - // Now do the current bone setup - entity->SetupBones( curBones, MAXSTUDIOBONES, BONE_USED_BY_ANYTHING, flTime ); - - entity->SetAbsOrigin( vNewOrigin ); - - // blow the cached prev bones - entity->InvalidateBoneCache(); - - entity->SetSequence( iTempSequence ); - entity->SetCycle( flTempCycle ); - - entity->Interpolate( gpGlobals->curtime ); - - entity->SetupBones( NULL, -1, BONE_USED_BY_ANYTHING, gpGlobals->curtime ); - - entity->RemoveEffects( EF_NOINTERP ); - } - else - { - entity->SetupBones( curBones, MAXSTUDIOBONES, BONE_USED_BY_ANYTHING, flTime ); - - // blow the cached prev bones - entity->InvalidateBoneCache(); - - entity->SetupBones( NULL, -1, BONE_USED_BY_ANYTHING, flTime ); - } -} - -#else // !CLIENT_DLL - -Activity GetDeathPoseActivity( CBaseAnimating *entity, const CTakeDamageInfo &info ) -{ - if ( !entity ) - { - return ACT_INVALID; - } - - Activity aActivity; - - Vector vForward, vRight; - entity->GetVectors( &vForward, &vRight, NULL ); - - Vector vDir = -info.GetDamageForce(); - VectorNormalize( vDir ); - - float flDotForward = DotProduct( vForward, vDir ); - float flDotRight = DotProduct( vRight, vDir ); - - bool bNegativeForward = false; - bool bNegativeRight = false; - - if ( flDotForward < 0.0f ) - { - bNegativeForward = true; - flDotForward = flDotForward * -1; - } - - if ( flDotRight < 0.0f ) - { - bNegativeRight = true; - flDotRight = flDotRight * -1; - } - - if ( flDotRight > flDotForward ) - { - if ( bNegativeRight == true ) - aActivity = ACT_DIE_LEFTSIDE; - else - aActivity = ACT_DIE_RIGHTSIDE; - } - else - { - if ( bNegativeForward == true ) - aActivity = ACT_DIE_BACKSIDE; - else - aActivity = ACT_DIE_FRONTSIDE; - } - - return aActivity; -} - -void SelectDeathPoseActivityAndFrame( CBaseAnimating *entity, const CTakeDamageInfo &info, int hitgroup, Activity& activity, int& frame ) -{ - activity = ACT_INVALID; - frame = 0; - - if ( !entity->GetModelPtr() ) - return; - - activity = GetDeathPoseActivity( entity, info ); - frame = DEATH_FRAME_HEAD; - - switch( hitgroup ) - { - //Do normal ragdoll stuff if no specific hitgroup was hit. - case HITGROUP_GENERIC: - default: - { - return; - } - - case HITGROUP_HEAD: - { - frame = DEATH_FRAME_HEAD; - break; - } - case HITGROUP_LEFTARM: - frame = DEATH_FRAME_LEFTARM; - break; - - case HITGROUP_RIGHTARM: - frame = DEATH_FRAME_RIGHTARM; - break; - - case HITGROUP_CHEST: - case HITGROUP_STOMACH: - frame = DEATH_FRAME_STOMACH; - break; - - case HITGROUP_LEFTLEG: - frame = DEATH_FRAME_LEFTLEG; - break; - - case HITGROUP_RIGHTLEG: - frame = DEATH_FRAME_RIGHTLEG; - break; - } -} - -#endif // !CLIENT_DLL diff --git a/game/shared/death_pose.h b/game/shared/death_pose.h deleted file mode 100644 index 8c298913b..000000000 --- a/game/shared/death_pose.h +++ /dev/null @@ -1,35 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef DEATH_POSE_H -#define DEATH_POSE_H -#ifdef _WIN32 -#pragma once -#endif - -enum -{ - DEATH_FRAME_HEAD = 1, - DEATH_FRAME_STOMACH, - DEATH_FRAME_LEFTARM, - DEATH_FRAME_RIGHTARM, - DEATH_FRAME_LEFTLEG, - DEATH_FRAME_RIGHTLEG, - MAX_DEATHPOSE_FRAMES = DEATH_FRAME_RIGHTLEG -}; - -#ifdef CLIENT_DLL - -void GetRagdollCurSequenceWithDeathPose( C_BaseAnimating *entity, matrix3x4_t *curBones, float flTime, int activity, int frame ); - -#else // !CLIENT_DLL - -/// Calculates death pose activity and frame -void SelectDeathPoseActivityAndFrame( CBaseAnimating *entity, const CTakeDamageInfo &info, int hitgroup, Activity& activity, int& frame ); - -#endif // !CLIENT_DLL - -#endif // DEATH_POSE_H diff --git a/game/shared/debugoverlay_null.cpp b/game/shared/debugoverlay_null.cpp deleted file mode 100644 index 47b756f82..000000000 --- a/game/shared/debugoverlay_null.cpp +++ /dev/null @@ -1,47 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// -#ifdef _WIN32 -#pragma once -#endif - -#include "cbase.h" -#include "engine/ivdebugoverlay.h" -#include "mathlib/vector.h" - -#include "mathlib/mathlib.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//============================================================================= -// NDebugOverlay -//============================================================================= -namespace NDebugOverlay -{ - void Box(const Vector &origin, const Vector &mins, const Vector &maxs, int r, int g, int b, int a, float flDuration) {} - void BoxDirection(const Vector &origin, const Vector &mins, const Vector &maxs, const Vector &forward, int r, int g, int b, int a, float flDuration) {} - void BoxAngles(const Vector &origin, const Vector &mins, const Vector &maxs, const QAngle &angles, int r, int g, int b, int a, float flDuration) {} - void SweptBox(const Vector& start, const Vector& end, const Vector& mins, const Vector& maxs, const QAngle & angles, int r, int g, int b, int a, float flDuration) {} - void EntityBounds( const CBaseEntity *pEntity, int r, int g, int b, int a, float flDuration ) {} - void Line( const Vector &origin, const Vector &target, int r, int g, int b, bool noDepthTest, float flDuration ) {} - void Triangle( const Vector &p1, const Vector &p2, const Vector &p3, int r, int g, int b, int a, bool noDepthTest, float duration ) {} - void EntityText( int entityID, int text_offset, const char *text, float flDuration, int r, int g, int b, int a) {} - void EntityTextAtPosition( const Vector &origin, int text_offset, const char *text, float flDuration, int r, int g, int b, int a) {} - void Grid( const Vector &vPosition ) {} - void Text( const Vector &origin, const char *text, bool bViewCheck, float flDuration ) {} - void ScreenText( float fXpos, float fYpos, const char *text, int r, int g, int b, int a, float flDuration) {} - void Cross3D(const Vector &position, const Vector &mins, const Vector &maxs, int r, int g, int b, bool noDepthTest, float flDuration ) {} - void Cross3D(const Vector &position, float size, int r, int g, int b, bool noDepthTest, float flDuration ) {} - void Cross3DOriented( const Vector &position, const QAngle &angles, float size, int r, int g, int b, bool noDepthTest, float flDuration ) {} - void Cross3DOriented( const matrix3x4_t &m, float size, int c, bool noDepthTest, float flDuration ) {} - void DrawOverlayLines(void){} - void DrawTickMarkedLine(const Vector &startPos, const Vector &endPos, float tickDist, int tickTextDist, int r, int g, int b, bool noDepthTest, float flDuration ) {} - void DrawGroundCrossHairOverlay() {} - void HorzArrow( const Vector &startPos, const Vector &endPos, float width, int r, int g, int b, int a, bool noDepthTest, float flDuration) {} - void YawArrow( const Vector &startPos, float yaw, float length, float width, int r, int g, int b, int a, bool noDepthTest, float flDuration) {} - void VertArrow( const Vector &startPos, const Vector &endPos, float width, int r, int g, int b, int a, bool noDepthTest, float flDuration) {} -}; - diff --git a/game/shared/debugoverlay_shared.cpp b/game/shared/debugoverlay_shared.cpp deleted file mode 100644 index c2c07a113..000000000 --- a/game/shared/debugoverlay_shared.cpp +++ /dev/null @@ -1,611 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Utility functions for using debug overlays to visualize information -// in the world. Uses the IVDebugOverlay interface. -// -//=============================================================================// - -#include "cbase.h" -#include "debugoverlay_shared.h" -#include "mathlib/mathlib.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define MAX_OVERLAY_DIST_SQR 90000000 - -//----------------------------------------------------------------------------- -// Purpose: Local player on the server or client -//----------------------------------------------------------------------------- -CBasePlayer *GetLocalPlayer( void ) -{ -#if defined( CLIENT_DLL) - return C_BasePlayer::GetLocalPlayer(); -#else - return UTIL_GetListenServerHost(); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Debug player by index -//----------------------------------------------------------------------------- -CBasePlayer *GetDebugPlayer( void ) -{ -#if defined( CLIENT_DLL ) - //NOTENOTE: This doesn't necessarily make sense on the client - return GetLocalPlayer(); -#else - return UTIL_PlayerByIndex(CBaseEntity::m_nDebugPlayer); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Draw a box with no orientation -//----------------------------------------------------------------------------- -void NDebugOverlay::Box(const Vector &origin, const Vector &mins, const Vector &maxs, int r, int g, int b, int a, float flDuration) -{ - BoxAngles( origin, mins, maxs, vec3_angle, r, g, b, a, flDuration ); -} - -//----------------------------------------------------------------------------- -// Purpose: Draw box oriented to a Vector direction -//----------------------------------------------------------------------------- -void NDebugOverlay::BoxDirection(const Vector &origin, const Vector &mins, const Vector &maxs, const Vector &orientation, int r, int g, int b, int a, float duration) -{ - // convert forward vector to angles - QAngle f_angles = vec3_angle; - f_angles.y = UTIL_VecToYaw( orientation ); - - BoxAngles( origin, mins, maxs, f_angles, r, g, b, a, duration ); -} - -//----------------------------------------------------------------------------- -// Purpose: Draw box oriented to a QAngle direction -//----------------------------------------------------------------------------- -void NDebugOverlay::BoxAngles(const Vector &origin, const Vector &mins, const Vector &maxs, const QAngle &angles, int r, int g, int b, int a, float duration) -{ - if ( debugoverlay ) - { - debugoverlay->AddBoxOverlay( origin, mins, maxs, angles, r, g, b, a, duration ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draws a swept box -//----------------------------------------------------------------------------- -void NDebugOverlay::SweptBox( const Vector& start, const Vector& end, const Vector& mins, const Vector& maxs, const QAngle & angles, int r, int g, int b, int a, float flDuration) -{ - if ( debugoverlay ) - { - debugoverlay->AddSweptBoxOverlay( start, end, mins, maxs, angles, r, g, b, a, flDuration ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draws a box around an entity -//----------------------------------------------------------------------------- -void NDebugOverlay::EntityBounds( const CBaseEntity *pEntity, int r, int g, int b, int a, float flDuration ) -{ - const CCollisionProperty *pCollide = pEntity->CollisionProp(); - BoxAngles( pCollide->GetCollisionOrigin(), pCollide->OBBMins(), pCollide->OBBMaxs(), pCollide->GetCollisionAngles(), r, g, b, a, flDuration ); -} - -//----------------------------------------------------------------------------- -// Purpose: Draws a line from one position to another -//----------------------------------------------------------------------------- -void NDebugOverlay::Line( const Vector &origin, const Vector &target, int r, int g, int b, bool noDepthTest, float duration ) -{ - // -------------------------------------------------------------- - // Clip the line before sending so we - // don't overflow the client message buffer - // -------------------------------------------------------------- - CBasePlayer *player = GetLocalPlayer(); - - if ( player == NULL ) - return; - - // Clip line that is far away - if (((player->GetAbsOrigin() - origin).LengthSqr() > MAX_OVERLAY_DIST_SQR) && - ((player->GetAbsOrigin() - target).LengthSqr() > MAX_OVERLAY_DIST_SQR) ) - return; - - // Clip line that is behind the client - Vector clientForward; - player->EyeVectors( &clientForward ); - - Vector toOrigin = origin - player->GetAbsOrigin(); - Vector toTarget = target - player->GetAbsOrigin(); - float dotOrigin = DotProduct(clientForward,toOrigin); - float dotTarget = DotProduct(clientForward,toTarget); - - if (dotOrigin < 0 && dotTarget < 0) - return; - - if ( debugoverlay ) - { - debugoverlay->AddLineOverlay( origin, target, r, g, b, noDepthTest, duration ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Draw triangle -//----------------------------------------------------------------------------- -void NDebugOverlay::Triangle( const Vector &p1, const Vector &p2, const Vector &p3, int r, int g, int b, int a, bool noDepthTest, float duration ) -{ - CBasePlayer *player = GetLocalPlayer(); - if ( !player ) - return; - - // Clip triangles that are far away - Vector to1 = p1 - player->GetAbsOrigin(); - Vector to2 = p2 - player->GetAbsOrigin(); - Vector to3 = p3 - player->GetAbsOrigin(); - - if ((to1.LengthSqr() > MAX_OVERLAY_DIST_SQR) && - (to2.LengthSqr() > MAX_OVERLAY_DIST_SQR) && - (to3.LengthSqr() > MAX_OVERLAY_DIST_SQR)) - { - return; - } - - // Clip triangles that are behind the client - Vector clientForward; - player->EyeVectors( &clientForward ); - - float dot1 = DotProduct(clientForward, to1); - float dot2 = DotProduct(clientForward, to2); - float dot3 = DotProduct(clientForward, to3); - - if (dot1 < 0 && dot2 < 0 && dot3 < 0) - return; - - if ( debugoverlay ) - { - debugoverlay->AddTriangleOverlay( p1, p2, p3, r, g, b, a, noDepthTest, duration ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draw entity text overlay -//----------------------------------------------------------------------------- -void NDebugOverlay::EntityText( int entityID, int text_offset, const char *text, float duration, int r, int g, int b, int a ) -{ - if ( debugoverlay ) - { - debugoverlay->AddEntityTextOverlay( entityID, text_offset, duration, - (int)clamp(r * 255.f,0.f,255.f), (int)clamp(g * 255.f,0.f,255.f), (int)clamp(b * 255.f,0.f,255.f), - (int)clamp(a * 255.f,0.f,255.f), text ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draw entity text overlay at a specific position -//----------------------------------------------------------------------------- -void NDebugOverlay::EntityTextAtPosition( const Vector &origin, int text_offset, const char *text, float duration, int r, int g, int b, int a ) -{ - if ( debugoverlay ) - { - debugoverlay->AddTextOverlayRGB( origin, text_offset, duration, r, g, b, a, text ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Add grid overlay -//----------------------------------------------------------------------------- -void NDebugOverlay::Grid( const Vector &vPosition ) -{ - if ( debugoverlay ) - { - debugoverlay->AddGridOverlay( vPosition ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draw debug text at a position -//----------------------------------------------------------------------------- -void NDebugOverlay::Text( const Vector &origin, const char *text, bool bViewCheck, float duration ) -{ - CBasePlayer *player = GetLocalPlayer(); - - if ( !player ) - return; - - // Clip text that is far away - if ( ( player->GetAbsOrigin() - origin ).LengthSqr() > MAX_OVERLAY_DIST_SQR ) - return; - - // Clip text that is behind the client - Vector clientForward; - player->EyeVectors( &clientForward ); - - Vector toText = origin - player->GetAbsOrigin(); - float dotPr = DotProduct(clientForward,toText); - - if (dotPr < 0) - return; - - // Clip text that is obscured - if (bViewCheck) - { - trace_t tr; - UTIL_TraceLine(player->GetAbsOrigin(), origin, MASK_OPAQUE, NULL, COLLISION_GROUP_NONE, &tr); - - if ((tr.endpos - origin).Length() > 10) - return; - } - - if ( debugoverlay ) - { - debugoverlay->AddTextOverlay( origin, duration, text ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Add debug overlay text with screen position -//----------------------------------------------------------------------------- -void NDebugOverlay::ScreenText( float flXpos, float flYpos, const char *text, int r, int g, int b, int a, float duration ) -{ - if ( debugoverlay ) - { - debugoverlay->AddScreenTextOverlay( flXpos, flYpos, duration, r, g, b, a, text ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draw a colored 3D cross of the given hull size at the given position -//----------------------------------------------------------------------------- -void NDebugOverlay::Cross3D(const Vector &position, const Vector &mins, const Vector &maxs, int r, int g, int b, bool noDepthTest, float fDuration ) -{ - Vector start = mins + position; - Vector end = maxs + position; - Line(start,end, r, g, b, noDepthTest,fDuration); - - start.x += (maxs.x - mins.x); - end.x -= (maxs.x - mins.x); - Line(start,end, r, g, b, noDepthTest,fDuration); - - start.y += (maxs.y - mins.y); - end.y -= (maxs.y - mins.y); - Line(start,end, r, g, b, noDepthTest,fDuration); - - start.x -= (maxs.x - mins.x); - end.x += (maxs.x - mins.x); - Line(start,end, r, g, b, noDepthTest,fDuration); -} - -//----------------------------------------------------------------------------- -// Purpose: Draw a colored 3D cross of the given size at the given position -//----------------------------------------------------------------------------- -void NDebugOverlay::Cross3D(const Vector &position, float size, int r, int g, int b, bool noDepthTest, float flDuration ) -{ - Line( position + Vector(size,0,0), position - Vector(size,0,0), r, g, b, noDepthTest, flDuration ); - Line( position + Vector(0,size,0), position - Vector(0,size,0), r, g, b, noDepthTest, flDuration ); - Line( position + Vector(0,0,size), position - Vector(0,0,size), r, g, b, noDepthTest, flDuration ); -} - -//----------------------------------------------------------------------------- -// Purpose: Draw an oriented, colored 3D cross of the given size at the given position (via a vector) -//----------------------------------------------------------------------------- -void NDebugOverlay::Cross3DOriented( const Vector &position, const QAngle &angles, float size, int r, int g, int b, bool noDepthTest, float flDuration ) -{ - Vector forward, right, up; - AngleVectors( angles, &forward, &right, &up ); - - forward *= size; - right *= size; - up *= size; - - Line( position + right, position - right, r, g, b, noDepthTest, flDuration ); - Line( position + forward, position - forward, r, g, b, noDepthTest, flDuration ); - Line( position + up, position - up, r, g, b, noDepthTest, flDuration ); -} - -//----------------------------------------------------------------------------- -// Purpose: Draw an oriented, colored 3D cross of the given size at the given position (via a matrix) -//----------------------------------------------------------------------------- -void NDebugOverlay::Cross3DOriented( const matrix3x4_t &m, float size, int c, bool noDepthTest, float flDuration ) -{ - Vector forward, left, up, position; - - MatrixGetColumn( m, 0, forward ); - MatrixGetColumn( m, 1, left ); - MatrixGetColumn( m, 2, up ); - MatrixGetColumn( m, 3, position ); - - forward *= size; - left *= size; - up *= size; - - Line( position + left, position - left, 0, c, 0, noDepthTest, flDuration ); - Line( position + forward, position - forward, c, 0, 0, noDepthTest, flDuration ); - Line( position + up, position - up, 0, 0, c, noDepthTest, flDuration ); -} - -//-------------------------------------------------------------------------------- -// Purpose : Draw tick marks between start and end position of the given distance -// with text every tickTextDist steps apart. -//-------------------------------------------------------------------------------- -void NDebugOverlay::DrawTickMarkedLine(const Vector &startPos, const Vector &endPos, float tickDist, int tickTextDist, int r, int g, int b, bool noDepthTest, float duration ) -{ - CBasePlayer* pPlayer = GetDebugPlayer(); - - if ( !pPlayer ) - return; - - Vector lineDir = (endPos - startPos); - float lineDist = VectorNormalize( lineDir ); - int numTicks = (int)(lineDist / tickDist); - Vector vBodyDir; - -#if defined( CLIENT_DLL ) - AngleVectors( pPlayer->LocalEyeAngles(), &vBodyDir ); -#else - vBodyDir = pPlayer->BodyDirection2D( ); -#endif - - Vector upVec = 4*vBodyDir; - Vector sideDir; - Vector tickPos = startPos; - int tickTextCnt = 0; - - CrossProduct(lineDir, upVec, sideDir); - - // First draw the line - Line(startPos, endPos, r,g,b,noDepthTest,duration); - - // Now draw the ticks - for (int i=0;iEyePosition(); - pPlayer->EyeVectors( &vForward ); - - trace_t tr; - UTIL_TraceLine ( vSource, vSource + vForward * 2048, MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &tr); - float dotPr = DotProduct(Vector(0,0,1),tr.plane.normal); - if (tr.fraction != 1.0 && dotPr > 0.5) - { - tr.endpos.z += 1; - float scale = 6; - Vector startPos = tr.endpos + Vector (-scale,0,0); - Vector endPos = tr.endpos + Vector ( scale,0,0); - Line(startPos, endPos, 255, 0, 0,false,0); - - startPos = tr.endpos + Vector (0,-scale,0); - endPos = tr.endpos + Vector (0, scale,0); - Line(startPos, endPos, 255, 0, 0,false,0); - } -} - -//-------------------------------------------------------------------------------- -// Purpose : Draw a horizontal arrow pointing in the specified direction -//-------------------------------------------------------------------------------- -void NDebugOverlay::HorzArrow( const Vector &startPos, const Vector &endPos, float width, int r, int g, int b, int a, bool noDepthTest, float flDuration) -{ - Vector lineDir = (endPos - startPos); - VectorNormalize( lineDir ); - Vector upVec = Vector( 0, 0, 1 ); - Vector sideDir; - float radius = width / 2.0; - - CrossProduct(lineDir, upVec, sideDir); - - Vector p1 = startPos - sideDir * radius; - Vector p2 = endPos - lineDir * width - sideDir * radius; - Vector p3 = endPos - lineDir * width - sideDir * width; - Vector p4 = endPos; - Vector p5 = endPos - lineDir * width + sideDir * width; - Vector p6 = endPos - lineDir * width + sideDir * radius; - Vector p7 = startPos + sideDir * radius; - - // Outline the arrow - Line(p1, p2, r,g,b,noDepthTest,flDuration); - Line(p2, p3, r,g,b,noDepthTest,flDuration); - Line(p3, p4, r,g,b,noDepthTest,flDuration); - Line(p4, p5, r,g,b,noDepthTest,flDuration); - Line(p5, p6, r,g,b,noDepthTest,flDuration); - Line(p6, p7, r,g,b,noDepthTest,flDuration); - - if ( a > 0 ) - { - // Fill us in with triangles - Triangle( p5, p4, p3, r, g, b, a, noDepthTest, flDuration ); // Tip - Triangle( p1, p7, p6, r, g, b, a, noDepthTest, flDuration ); // Shaft - Triangle( p6, p2, p1, r, g, b, a, noDepthTest, flDuration ); - - // And backfaces - Triangle( p3, p4, p5, r, g, b, a, noDepthTest, flDuration ); // Tip - Triangle( p6, p7, p1, r, g, b, a, noDepthTest, flDuration ); // Shaft - Triangle( p1, p2, p6, r, g, b, a, noDepthTest, flDuration ); - } -} - -//----------------------------------------------------------------------------- -// Purpose : Draw a horizontal arrow pointing in the specified direction by yaw value -//----------------------------------------------------------------------------- -void NDebugOverlay::YawArrow( const Vector &startPos, float yaw, float length, float width, int r, int g, int b, int a, bool noDepthTest, float flDuration) -{ - Vector forward = UTIL_YawToVector( yaw ); - - HorzArrow( startPos, startPos + forward * length, width, r, g, b, a, noDepthTest, flDuration ); -} - -//-------------------------------------------------------------------------------- -// Purpose : Draw a vertical arrow at a position -//-------------------------------------------------------------------------------- -void NDebugOverlay::VertArrow( const Vector &startPos, const Vector &endPos, float width, int r, int g, int b, int a, bool noDepthTest, float flDuration) -{ - Vector lineDir = (endPos - startPos); - VectorNormalize( lineDir ); - Vector upVec; - Vector sideDir; - float radius = width / 2.0; - - VectorVectors( lineDir, sideDir, upVec ); - - Vector p1 = startPos - upVec * radius; - Vector p2 = endPos - lineDir * width - upVec * radius; - Vector p3 = endPos - lineDir * width - upVec * width; - Vector p4 = endPos; - Vector p5 = endPos - lineDir * width + upVec * width; - Vector p6 = endPos - lineDir * width + upVec * radius; - Vector p7 = startPos + upVec * radius; - - // Outline the arrow - Line(p1, p2, r,g,b,noDepthTest,flDuration); - Line(p2, p3, r,g,b,noDepthTest,flDuration); - Line(p3, p4, r,g,b,noDepthTest,flDuration); - Line(p4, p5, r,g,b,noDepthTest,flDuration); - Line(p5, p6, r,g,b,noDepthTest,flDuration); - Line(p6, p7, r,g,b,noDepthTest,flDuration); - - if ( a > 0 ) - { - // Fill us in with triangles - Triangle( p5, p4, p3, r, g, b, a, noDepthTest, flDuration ); // Tip - Triangle( p1, p7, p6, r, g, b, a, noDepthTest, flDuration ); // Shaft - Triangle( p6, p2, p1, r, g, b, a, noDepthTest, flDuration ); - - // And backfaces - Triangle( p3, p4, p5, r, g, b, a, noDepthTest, flDuration ); // Tip - Triangle( p6, p7, p1, r, g, b, a, noDepthTest, flDuration ); // Shaft - Triangle( p1, p2, p6, r, g, b, a, noDepthTest, flDuration ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draw an axis -//----------------------------------------------------------------------------- -void NDebugOverlay::Axis( const Vector &position, const QAngle &angles, float size, bool noDepthTest, float flDuration ) -{ - Vector xvec, yvec, zvec; - AngleVectors( angles, &xvec, &yvec, &zvec ); - - xvec = position + (size * xvec); - yvec = position - (size * yvec); // Left is positive - zvec = position + (size * zvec); - - Line( position, xvec, 255, 0, 0, noDepthTest, flDuration ); - Line( position, yvec, 0, 255, 0, noDepthTest, flDuration ); - Line( position, zvec, 0, 0, 255, noDepthTest, flDuration ); -} - -//----------------------------------------------------------------------------- -// Purpose: Draw a circle whose center is at a position, facing the camera -//----------------------------------------------------------------------------- -void NDebugOverlay::Circle( const Vector &position, float radius, int r, int g, int b, int a, bool bNoDepthTest, float flDuration ) -{ - CBasePlayer *player = GetLocalPlayer(); - if ( player == NULL ) - return; - - Vector clientForward; - player->EyeVectors( &clientForward ); - - QAngle vecAngles; - VectorAngles( clientForward, vecAngles ); - - Circle( position, vecAngles, radius, r, g, b, a, bNoDepthTest, flDuration ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Draw a circle whose center is at a position and is facing a specified direction -//----------------------------------------------------------------------------- -void NDebugOverlay::Circle( const Vector &position, const QAngle &angles, float radius, int r, int g, int b, int a, bool bNoDepthTest, float flDuration ) -{ - // Setup our transform matrix - matrix3x4_t xform; - AngleMatrix( angles, position, xform ); - Vector xAxis, yAxis; - // default draws circle in the y/z plane - MatrixGetColumn( xform, 2, xAxis ); - MatrixGetColumn( xform, 1, yAxis ); - Circle( position, xAxis, yAxis, radius, r, g, b, a, bNoDepthTest, flDuration ); -} - -void NDebugOverlay::Circle( const Vector &position, const Vector &xAxis, const Vector &yAxis, float radius, int r, int g, int b, int a, bool bNoDepthTest, float flDuration ) -{ - const int nSegments = 16; - const float flRadStep = (M_PI*2.0f) / (float) nSegments; - - Vector vecLastPosition; - - // Find our first position - // Retained for triangle fanning - Vector vecStart = position + xAxis * radius; - Vector vecPosition = vecStart; - - // Draw out each segment (fanning triangles if we have an alpha amount) - for ( int i = 1; i <= nSegments; i++ ) - { - // Store off our last position - vecLastPosition = vecPosition; - - // Calculate the new one - float flSin, flCos; - SinCos( flRadStep*i, &flSin, &flCos ); - vecPosition = position + (xAxis * flCos * radius) + (yAxis * flSin * radius); - - // Draw the line - Line( vecLastPosition, vecPosition, r, g, b, bNoDepthTest, flDuration ); - - // If we have an alpha value, then draw the fan - if ( a && i > 1 ) - { - debugoverlay->AddTriangleOverlay( vecStart, vecLastPosition, vecPosition, r, g, b, a, bNoDepthTest, flDuration ); - } - } -} - -void NDebugOverlay::Sphere( const Vector &position, const QAngle &angles, float radius, int r, int g, int b, int a, bool bNoDepthTest, float flDuration ) -{ - // Setup our transform matrix - matrix3x4_t xform; - AngleMatrix( angles, position, xform ); - Vector xAxis, yAxis, zAxis; - // default draws circle in the y/z plane - MatrixGetColumn( xform, 0, xAxis ); - MatrixGetColumn( xform, 1, yAxis ); - MatrixGetColumn( xform, 2, zAxis ); - Circle( position, xAxis, yAxis, radius, r, g, b, a, bNoDepthTest, flDuration ); // xy plane - Circle( position, yAxis, zAxis, radius, r, g, b, a, bNoDepthTest, flDuration ); // yz plane - Circle( position, xAxis, zAxis, radius, r, g, b, a, bNoDepthTest, flDuration ); // xz plane -} diff --git a/game/shared/debugoverlay_shared.h b/game/shared/debugoverlay_shared.h deleted file mode 100644 index b1cac63e0..000000000 --- a/game/shared/debugoverlay_shared.h +++ /dev/null @@ -1,50 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef DEBUGOVERLAY_SHARED_H -#define DEBUGOVERLAY_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - -#include "engine/ivdebugoverlay.h" -#include "mathlib/vector.h" - -//============================================================================= -// NDebugOverlay -//============================================================================= -namespace NDebugOverlay -{ - void Box(const Vector &origin, const Vector &mins, const Vector &maxs, int r, int g, int b, int a, float flDuration); - void BoxDirection(const Vector &origin, const Vector &mins, const Vector &maxs, const Vector &forward, int r, int g, int b, int a, float flDuration); - void BoxAngles(const Vector &origin, const Vector &mins, const Vector &maxs, const QAngle &angles, int r, int g, int b, int a, float flDuration); - void SweptBox(const Vector& start, const Vector& end, const Vector& mins, const Vector& maxs, const QAngle & angles, int r, int g, int b, int a, float flDuration); - void EntityBounds( const CBaseEntity *pEntity, int r, int g, int b, int a, float flDuration ); - void Line( const Vector &origin, const Vector &target, int r, int g, int b, bool noDepthTest, float flDuration ); - void Triangle( const Vector &p1, const Vector &p2, const Vector &p3, int r, int g, int b, int a, bool noDepthTest, float duration ); - void EntityText( int entityID, int text_offset, const char *text, float flDuration, int r = 255, int g = 255, int b = 255, int a = 255); - void EntityTextAtPosition( const Vector &origin, int text_offset, const char *text, float flDuration, int r = 255, int g = 255, int b = 255, int a = 255); - void Grid( const Vector &vPosition ); - void Text( const Vector &origin, const char *text, bool bViewCheck, float flDuration ); - void ScreenText( float fXpos, float fYpos, const char *text, int r, int g, int b, int a, float flDuration); - void Cross3D(const Vector &position, const Vector &mins, const Vector &maxs, int r, int g, int b, bool noDepthTest, float flDuration ); - void Cross3D(const Vector &position, float size, int r, int g, int b, bool noDepthTest, float flDuration ); - void Cross3DOriented( const Vector &position, const QAngle &angles, float size, int r, int g, int b, bool noDepthTest, float flDuration ); - void Cross3DOriented( const matrix3x4_t &m, float size, int c, bool noDepthTest, float flDuration ); - void DrawOverlayLines(void); - void DrawTickMarkedLine(const Vector &startPos, const Vector &endPos, float tickDist, int tickTextDist, int r, int g, int b, bool noDepthTest, float flDuration ); - void DrawGroundCrossHairOverlay(); - void HorzArrow( const Vector &startPos, const Vector &endPos, float width, int r, int g, int b, int a, bool noDepthTest, float flDuration); - void YawArrow( const Vector &startPos, float yaw, float length, float width, int r, int g, int b, int a, bool noDepthTest, float flDuration); - void VertArrow( const Vector &startPos, const Vector &endPos, float width, int r, int g, int b, int a, bool noDepthTest, float flDuration); - void Axis( const Vector &position, const QAngle &angles, float size, bool noDepthTest, float flDuration ); - void Circle( const Vector &position, float radius, int r, int g, int b, int a, bool bNoDepthTest, float flDuration ); - void Circle( const Vector &position, const QAngle &angles, float radius, int r, int g, int b, int a, bool bNoDepthTest, float flDuration ); - void Circle( const Vector &position, const Vector &xAxis, const Vector &yAxis, float radius, int r, int g, int b, int a, bool bNoDepthTest, float flDuration ); - void Sphere( const Vector &position, const QAngle &angles, float radius, int r, int g, int b, int a, bool bNoDepthTest, float flDuration ); -}; - -#endif // DEBUGOVERLAY_SHARED_H diff --git a/game/shared/decals.cpp b/game/shared/decals.cpp deleted file mode 100644 index f3d02748b..000000000 --- a/game/shared/decals.cpp +++ /dev/null @@ -1,331 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// -#include "cbase.h" -#include "decals.h" -#include "igamesystem.h" -#include "utlsymbol.h" -#include "utldict.h" -#include "KeyValues.h" -#include "filesystem.h" - -#ifdef CLIENT_DLL -#include "iefx.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define DECAL_LIST_FILE "scripts/decals_subrect.txt" -//#define DECAL_LIST_FILE "scripts/decals.txt" -#define TRANSLATION_DATA_SECTION "TranslationData" - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CDecalEmitterSystem : public IDecalEmitterSystem, public CAutoGameSystem -{ -public: - CDecalEmitterSystem( char const *name ) : CAutoGameSystem( name ) - { - } - - virtual bool Init(); - virtual void Shutdown(); - virtual void LevelInitPreEntity(); - - // Public interface - virtual int GetDecalIndexForName( char const *decalname ); - virtual char const *TranslateDecalForGameMaterial( char const *decalName, unsigned char gamematerial ); - -private: - char const *ImpactDecalForGameMaterial( int gamematerial ); - void LoadDecalsFromScript( char const *filename ); - void Clear(); - - struct DecalListEntry - { - DecalListEntry() - { - name = UTL_INVAL_SYMBOL; - precache_index = -1; - weight = 1.0f; - } - - CUtlSymbol name; - int precache_index; - float weight; - }; - - struct DecalEntry - { - DecalEntry() - { - } - - DecalEntry( const DecalEntry& src ) - { - int c = src.indices.Count(); - for ( int i = 0; i < c; i++ ) - { - indices.AddToTail( src.indices[ i ] ); - } - } - - DecalEntry& operator = ( const DecalEntry& src ) - { - if ( this == &src ) - return *this; - - int c = src.indices.Count(); - for ( int i = 0; i < c; i++ ) - { - indices.AddToTail( src.indices[ i ] ); - } - - return *this; - } - - CUtlVector< int > indices; - }; - - CUtlVector< DecalListEntry > m_AllDecals; - CUtlDict< DecalEntry, int > m_Decals; - CUtlSymbolTable m_DecalFileNames; - CUtlDict< int, int > m_GameMaterialTranslation; -}; - -static CDecalEmitterSystem g_DecalSystem( "CDecalEmitterSystem" ); -IDecalEmitterSystem *decalsystem = &g_DecalSystem; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *decalname - -// Output : int -//----------------------------------------------------------------------------- -int CDecalEmitterSystem::GetDecalIndexForName( char const *decalname ) -{ - if ( !decalname || !decalname[ 0 ] ) - return -1; - - int idx = m_Decals.Find( decalname ); - if ( idx == m_Decals.InvalidIndex() ) - return -1; - - DecalEntry *e = &m_Decals[ idx ]; - Assert( e ); - int count = e->indices.Count(); - if ( count <= 0 ) - return -1; - - float totalweight = 0.0f; - int slot = 0; - - for ( int i = 0; i < count; i++ ) - { - int idx = e->indices[ i ]; - DecalListEntry *item = &m_AllDecals[ idx ]; - Assert( item ); - - if ( !totalweight ) - { - slot = idx; - } - - // Always assume very first slot will match - totalweight += item->weight; - if ( !totalweight || random->RandomFloat(0,totalweight) < item->weight ) - { - slot = idx; - } - } - - return m_AllDecals[ slot ].precache_index; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CDecalEmitterSystem::Init() -{ - LoadDecalsFromScript( DECAL_LIST_FILE ); - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDecalEmitterSystem::LevelInitPreEntity() -{ - // Precache all entries - int c = m_AllDecals.Count(); - for ( int i = 0 ; i < c; i++ ) - { - DecalListEntry& e = m_AllDecals[ i ]; -#if defined( CLIENT_DLL ) - e.precache_index = effects->Draw_DecalIndexFromName( (char *)m_DecalFileNames.String( e.name ) ); -#else - e.precache_index = engine->PrecacheDecal( m_DecalFileNames.String( e.name ) ); -#endif - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *filename - -//----------------------------------------------------------------------------- -void CDecalEmitterSystem::LoadDecalsFromScript( char const *filename ) -{ - KeyValues *kv = new KeyValues( filename ); - Assert( kv ); - if ( kv ) - { - KeyValues *translation = NULL; -#ifndef _XBOX - if ( kv->LoadFromFile( filesystem, filename ) ) -#else - if ( kv->LoadFromFile( filesystem, filename, "GAME" ) ) -#endif - { - KeyValues *p = kv; - while ( p ) - { - if ( p->GetFirstSubKey() ) - { - char const *keyname = p->GetName(); - - if ( !Q_stricmp( keyname, TRANSLATION_DATA_SECTION ) ) - { - translation = p; - } - else - { - DecalEntry entry; - - for ( KeyValues *sub = p->GetFirstSubKey(); sub != NULL; sub = sub->GetNextKey() ) - { - MEM_ALLOC_CREDIT(); - - DecalListEntry decal; - decal.precache_index = -1; - decal.name = m_DecalFileNames.AddString( sub->GetName() ); - decal.weight = sub->GetFloat(); - - // Add to global list - int idx = m_AllDecals.AddToTail( decal ); - - // Add index only to local list - entry.indices.AddToTail( idx ); - } - - // Add entry to main dictionary - m_Decals.Insert( keyname, entry ); - } - } - p = p->GetNextKey(); - } - } - else - { - Msg( "CDecalEmitterSystem::LoadDecalsFromScript: Unable to load '%s'\n", filename ); - } - - if ( !translation ) - { - Msg( "CDecalEmitterSystem::LoadDecalsFromScript: Script '%s' missing section '%s'\n", - filename, - TRANSLATION_DATA_SECTION ); - } - else - { - // Now parse game material to entry translation table - for ( KeyValues *sub = translation->GetFirstSubKey(); sub != NULL; sub = sub->GetNextKey() ) - { - // Don't add NULL string to list - if ( !Q_stricmp( sub->GetString(), "" ) ) - continue; - - int idx = m_Decals.Find( sub->GetString() ); - if ( idx != m_Decals.InvalidIndex() ) - { - m_GameMaterialTranslation.Insert( sub->GetName(), idx ); - } - else - { - Msg( "CDecalEmitterSystem::LoadDecalsFromScript: Translation for game material type '%s' references unknown decal '%s'\n", - sub->GetName(), sub->GetString() ); - } - } - } - - kv->deleteThis(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : gamematerial - -// Output : char const -//----------------------------------------------------------------------------- -char const *CDecalEmitterSystem::ImpactDecalForGameMaterial( int gamematerial ) -{ - char gm[ 2 ]; - gm[0] = (char)gamematerial; - gm[1] = 0; - - int idx = m_GameMaterialTranslation.Find( gm ); - if ( idx == m_GameMaterialTranslation.InvalidIndex() ) - return NULL; - - return m_Decals.GetElementName( m_GameMaterialTranslation.Element(idx) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDecalEmitterSystem::Shutdown() -{ - Clear(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDecalEmitterSystem::Clear() -{ - m_DecalFileNames.RemoveAll(); - m_Decals.Purge(); - m_AllDecals.Purge(); - m_GameMaterialTranslation.Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *decalName - -// gamematerial - -// Output : char const -//----------------------------------------------------------------------------- -char const *CDecalEmitterSystem::TranslateDecalForGameMaterial( char const *decalName, unsigned char gamematerial ) -{ - if ( gamematerial == CHAR_TEX_CONCRETE ) - return decalName; - - if ( !Q_stricmp( decalName, "Impact.Concrete" ) ) - { - if ( gamematerial == '-' ) - return ""; - - char const *d = ImpactDecalForGameMaterial( gamematerial ); - if ( d ) - { - return d; - } - } - - return decalName; -} - - diff --git a/game/shared/decals.h b/game/shared/decals.h deleted file mode 100644 index c28139fb3..000000000 --- a/game/shared/decals.h +++ /dev/null @@ -1,51 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#ifndef DECALS_H -#define DECALS_H -#ifdef _WIN32 -#pragma once -#endif - -// NOTE: If you add a tex type, be sure to modify the s_pImpactEffect -// array in fx_impact.cpp to get an effect when that surface is shot. -#define CHAR_TEX_ANTLION 'A' -#define CHAR_TEX_BLOODYFLESH 'B' -#define CHAR_TEX_CONCRETE 'C' -#define CHAR_TEX_DIRT 'D' -#define CHAR_TEX_EGGSHELL 'E' ///< the egg sacs in the tunnels in ep2. -#define CHAR_TEX_FLESH 'F' -#define CHAR_TEX_GRATE 'G' -#define CHAR_TEX_ALIENFLESH 'H' -#define CHAR_TEX_CLIP 'I' -//#define CHAR_TEX_UNUSED 'J' -//#define CHAR_TEX_UNUSED 'K' -#define CHAR_TEX_PLASTIC 'L' -#define CHAR_TEX_METAL 'M' -#define CHAR_TEX_SAND 'N' -#define CHAR_TEX_FOLIAGE 'O' -#define CHAR_TEX_COMPUTER 'P' -//#define CHAR_TEX_UNUSED 'Q' -//#define CHAR_TEX_UNUSED 'R' -#define CHAR_TEX_SLOSH 'S' -#define CHAR_TEX_TILE 'T' -//#define CHAR_TEX_UNUSED 'U' -#define CHAR_TEX_VENT 'V' -#define CHAR_TEX_WOOD 'W' -//#define CHAR_TEX_UNUSED 'X' -#define CHAR_TEX_GLASS 'Y' -#define CHAR_TEX_WARPSHIELD 'Z' ///< wierd-looking jello effect for advisor shield. - -abstract_class IDecalEmitterSystem -{ -public: - virtual int GetDecalIndexForName( char const *decalname ) = 0; - virtual char const *TranslateDecalForGameMaterial( char const *decalName, unsigned char gamematerial ) = 0; -}; - -extern IDecalEmitterSystem *decalsystem; - -#endif // DECALS_H diff --git a/game/shared/effect_color_tables.h b/game/shared/effect_color_tables.h deleted file mode 100644 index daab41175..000000000 --- a/game/shared/effect_color_tables.h +++ /dev/null @@ -1,51 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef EFFECT_COLOR_TABLES_H -#define EFFECT_COLOR_TABLES_H -#ifdef _WIN32 -#pragma once -#endif - -struct colorentry_t -{ - unsigned char index; - - unsigned char r; - unsigned char g; - unsigned char b; -}; - -#define COLOR_TABLE_SIZE(ct) sizeof(ct)/sizeof(colorentry_t) - -// Commander mode indicators (HL2) -enum -{ - COMMAND_POINT_RED = 0, - COMMAND_POINT_BLUE, - COMMAND_POINT_GREEN, - COMMAND_POINT_YELLOW, -}; - -// Commander mode table -#ifdef CLIENT_DLL -static colorentry_t commandercolors[] = -{ - { COMMAND_POINT_RED, 1.0, 0.0, 0.0 }, - { COMMAND_POINT_BLUE, 0.0, 0.0, 1.0 }, - { COMMAND_POINT_GREEN, 0.0, 1.0, 0.0 }, - { COMMAND_POINT_YELLOW, 1.0, 1.0, 0.0 }, -}; - -static colorentry_t bloodcolors[] = -{ - { BLOOD_COLOR_RED, 72, 0, 0 }, - { BLOOD_COLOR_YELLOW, 195, 195, 0 }, - { BLOOD_COLOR_MECH, 20, 20, 20 }, -}; -#endif - -#endif // EFFECT_COLOR_TABLES_H diff --git a/game/shared/effect_dispatch_data.cpp b/game/shared/effect_dispatch_data.cpp deleted file mode 100644 index 5d000271c..000000000 --- a/game/shared/effect_dispatch_data.cpp +++ /dev/null @@ -1,156 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "effect_dispatch_data.h" -#include "coordsize.h" - -#ifdef CLIENT_DLL -#include "cliententitylist.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -#define SUBINCH_PRECISION 3 - -// Note, must match common/qlimits.h!!! -#define MAX_MODEL_INDEX_BITS 10 - - -#ifdef CLIENT_DLL - - #include "dt_recv.h" - - static void RecvProxy_EntIndex( const CRecvProxyData *pData, void *pStruct, void *pOut ) - { - int nEntIndex = pData->m_Value.m_Int; - ((CEffectData*)pStruct)->m_hEntity = (nEntIndex < 0) ? INVALID_EHANDLE_INDEX : ClientEntityList().EntIndexToHandle( nEntIndex ); - } - - BEGIN_RECV_TABLE_NOBASE( CEffectData, DT_EffectData ) - - RecvPropFloat( RECVINFO( m_vOrigin[0] ) ), - RecvPropFloat( RECVINFO( m_vOrigin[1] ) ), - RecvPropFloat( RECVINFO( m_vOrigin[2] ) ), - - RecvPropFloat( RECVINFO( m_vStart[0] ) ), - RecvPropFloat( RECVINFO( m_vStart[1] ) ), - RecvPropFloat( RECVINFO( m_vStart[2] ) ), - - RecvPropQAngles( RECVINFO( m_vAngles ) ), - - RecvPropVector( RECVINFO( m_vNormal ) ), - - RecvPropInt( RECVINFO( m_fFlags ) ), - RecvPropFloat( RECVINFO( m_flMagnitude ) ), - RecvPropFloat( RECVINFO( m_flScale ) ), - RecvPropInt( RECVINFO( m_nAttachmentIndex ) ), - RecvPropIntWithMinusOneFlag( RECVINFO( m_nSurfaceProp ), RecvProxy_ShortSubOne ), - RecvPropInt( RECVINFO( m_iEffectName ) ), - - RecvPropInt( RECVINFO( m_nMaterial ) ), - RecvPropInt( RECVINFO( m_nDamageType ) ), - RecvPropInt( RECVINFO( m_nHitBox ) ), - - RecvPropInt( "entindex", 0, SIZEOF_IGNORE, 0, RecvProxy_EntIndex ), - - RecvPropInt( RECVINFO( m_nColor ) ), - - RecvPropFloat( RECVINFO( m_flRadius ) ), - END_RECV_TABLE() - -#else - - #include "dt_send.h" - - BEGIN_SEND_TABLE_NOBASE( CEffectData, DT_EffectData ) - - // Everything uses _NOCHECK here since this is not an entity and we don't need - // the functionality of CNetworkVars. - - // Get half-inch precision here. -#ifdef HL2_DLL - SendPropFloat( SENDINFO_NOCHECK_VECTORELEM( m_vOrigin, 0, x ), COORD_INTEGER_BITS+SUBINCH_PRECISION, 0, MIN_COORD_INTEGER, MAX_COORD_INTEGER ), - SendPropFloat( SENDINFO_NOCHECK_VECTORELEM( m_vOrigin, 1, y ), COORD_INTEGER_BITS+SUBINCH_PRECISION, 0, MIN_COORD_INTEGER, MAX_COORD_INTEGER ), - SendPropFloat( SENDINFO_NOCHECK_VECTORELEM( m_vOrigin, 2, z ), COORD_INTEGER_BITS+SUBINCH_PRECISION, 0, MIN_COORD_INTEGER, MAX_COORD_INTEGER ), - SendPropFloat( SENDINFO_NOCHECK_VECTORELEM( m_vStart, 0, x ), COORD_INTEGER_BITS+SUBINCH_PRECISION, 0, MIN_COORD_INTEGER, MAX_COORD_INTEGER ), - SendPropFloat( SENDINFO_NOCHECK_VECTORELEM( m_vStart, 1, y ), COORD_INTEGER_BITS+SUBINCH_PRECISION, 0, MIN_COORD_INTEGER, MAX_COORD_INTEGER ), - SendPropFloat( SENDINFO_NOCHECK_VECTORELEM( m_vStart, 2, z ), COORD_INTEGER_BITS+SUBINCH_PRECISION, 0, MIN_COORD_INTEGER, MAX_COORD_INTEGER ), -#else - SendPropFloat( SENDINFO_NOCHECK_VECTORELEM( m_vOrigin, 0, x ), -1, SPROP_COORD_MP_INTEGRAL ), - SendPropFloat( SENDINFO_NOCHECK_VECTORELEM( m_vOrigin, 1, y ), -1, SPROP_COORD_MP_INTEGRAL ), - SendPropFloat( SENDINFO_NOCHECK_VECTORELEM( m_vOrigin, 2, z ), -1, SPROP_COORD_MP_INTEGRAL ), - SendPropFloat( SENDINFO_NOCHECK_VECTORELEM( m_vStart, 0, x ), -1, SPROP_COORD_MP_INTEGRAL ), - SendPropFloat( SENDINFO_NOCHECK_VECTORELEM( m_vStart, 1, y ), -1, SPROP_COORD_MP_INTEGRAL ), - SendPropFloat( SENDINFO_NOCHECK_VECTORELEM( m_vStart, 2, z ), -1, SPROP_COORD_MP_INTEGRAL ), -#endif - SendPropQAngles( SENDINFO_NOCHECK( m_vAngles ), 7 ), - -#if defined( TF_DLL ) - SendPropVector( SENDINFO_NOCHECK( m_vNormal ), 6, 0, -1.0f, 1.0f ), -#else - SendPropVector( SENDINFO_NOCHECK( m_vNormal ), 0, SPROP_NORMAL ), -#endif - - SendPropInt( SENDINFO_NOCHECK( m_fFlags ), MAX_EFFECT_FLAG_BITS, SPROP_UNSIGNED ), - SendPropFloat( SENDINFO_NOCHECK( m_flMagnitude ), 12, SPROP_ROUNDDOWN, 0.0f, 1023.0f ), - SendPropFloat( SENDINFO_NOCHECK( m_flScale ), 0, SPROP_NOSCALE ), - SendPropInt( SENDINFO_NOCHECK( m_nAttachmentIndex ), 5, SPROP_UNSIGNED ), - SendPropIntWithMinusOneFlag( SENDINFO_NOCHECK( m_nSurfaceProp ), 8, SendProxy_ShortAddOne ), - SendPropInt( SENDINFO_NOCHECK( m_iEffectName ), MAX_EFFECT_DISPATCH_STRING_BITS, SPROP_UNSIGNED ), - - SendPropInt( SENDINFO_NOCHECK( m_nMaterial ), MAX_MODEL_INDEX_BITS, SPROP_UNSIGNED ), - SendPropInt( SENDINFO_NOCHECK( m_nDamageType ), 32, SPROP_UNSIGNED ), - SendPropInt( SENDINFO_NOCHECK( m_nHitBox ), 11, SPROP_UNSIGNED ), - - SendPropInt( SENDINFO_NAME( m_nEntIndex, entindex ), MAX_EDICT_BITS, SPROP_UNSIGNED ), - - SendPropInt( SENDINFO_NOCHECK( m_nColor ), 8, SPROP_UNSIGNED ), - - SendPropFloat( SENDINFO_NOCHECK( m_flRadius ), 10, SPROP_ROUNDDOWN, 0.0f, 1023.0f ), - - END_SEND_TABLE() - -#endif - -#ifdef CLIENT_DLL - -IClientRenderable *CEffectData::GetRenderable() const -{ - return ClientEntityList().GetClientRenderableFromHandle( m_hEntity ); -} - -C_BaseEntity *CEffectData::GetEntity() const -{ - return ClientEntityList().GetBaseEntityFromHandle( m_hEntity ); -} - -int CEffectData::entindex() const -{ - C_BaseEntity *pEnt = ClientEntityList().GetBaseEntityFromHandle( m_hEntity ); - return pEnt ? pEnt->entindex() : -1; -} - -#endif - -#ifdef CLIENT_DLL - -bool g_bSuppressParticleEffects = false; - -bool SuppressingParticleEffects() -{ - return g_bSuppressParticleEffects; -} - -void SuppressParticleEffects( bool bSuppress ) -{ - g_bSuppressParticleEffects = bSuppress; -} - -#endif diff --git a/game/shared/effect_dispatch_data.h b/game/shared/effect_dispatch_data.h deleted file mode 100644 index 7bf3d5095..000000000 --- a/game/shared/effect_dispatch_data.h +++ /dev/null @@ -1,120 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef EFFECT_DISPATCH_DATA_H -#define EFFECT_DISPATCH_DATA_H -#ifdef _WIN32 -#pragma once -#endif - - -#ifdef CLIENT_DLL - - #include "dt_recv.h" - #include "client_class.h" - - EXTERN_RECV_TABLE( DT_EffectData ); - -#else - - #include "dt_send.h" - #include "server_class.h" - - EXTERN_SEND_TABLE( DT_EffectData ); - -#endif - -// NOTE: These flags are specifically *not* networked; so it's placed above the max effect flag bits -#define EFFECTDATA_NO_RECORD 0x80000000 - -#define MAX_EFFECT_FLAG_BITS 8 - -// This is the class that holds whatever data we're sending down to the client to make the effect. -class CEffectData -{ -public: - Vector m_vOrigin; - Vector m_vStart; - Vector m_vNormal; - QAngle m_vAngles; - int m_fFlags; -#ifdef CLIENT_DLL - ClientEntityHandle_t m_hEntity; -#else - int m_nEntIndex; -#endif - float m_flScale; - float m_flMagnitude; - float m_flRadius; - int m_nAttachmentIndex; - short m_nSurfaceProp; - - // Some TF2 specific things - int m_nMaterial; - int m_nDamageType; - int m_nHitBox; - - unsigned char m_nColor; - -// Don't mess with stuff below here. DispatchEffect handles all of this. -public: - CEffectData() - { - m_vOrigin.Init(); - m_vStart.Init(); - m_vNormal.Init(); - m_vAngles.Init(); - - m_fFlags = 0; -#ifdef CLIENT_DLL - m_hEntity = INVALID_EHANDLE_INDEX; -#else - m_nEntIndex = 0; -#endif - m_flScale = 1.f; - m_nAttachmentIndex = 0; - m_nSurfaceProp = 0; - - m_flMagnitude = 0.0f; - m_flRadius = 0.0f; - - m_nMaterial = 0; - m_nDamageType = 0; - m_nHitBox = 0; - - m_nColor = 0; - } - - int GetEffectNameIndex() { return m_iEffectName; } - -#ifdef CLIENT_DLL - IClientRenderable *GetRenderable() const; - C_BaseEntity *GetEntity() const; - int entindex() const; -#endif - -private: - - #ifdef CLIENT_DLL - DECLARE_CLIENTCLASS_NOBASE() - #else - DECLARE_SERVERCLASS_NOBASE() - #endif - - int m_iEffectName; // Entry in the EffectDispatch network string table. The is automatically handled by DispatchEffect(). -}; - - -#define MAX_EFFECT_DISPATCH_STRING_BITS 10 -#define MAX_EFFECT_DISPATCH_STRINGS ( 1 << MAX_EFFECT_DISPATCH_STRING_BITS ) - -#ifdef CLIENT_DLL -bool SuppressingParticleEffects(); -void SuppressParticleEffects( bool bSuppress ); -#endif - -#endif // EFFECT_DISPATCH_DATA_H diff --git a/game/shared/ehandle.cpp b/game/shared/ehandle.cpp deleted file mode 100644 index eea72795b..000000000 --- a/game/shared/ehandle.cpp +++ /dev/null @@ -1,32 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: This module implements functions to support ehandles. -// -//=============================================================================// - -#include "cbase.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#if defined( GAME_DLL ) - - #include "entitylist.h" - - - void DebugCheckEHandleAccess( void *pEnt ) - { - extern bool g_bDisableEhandleAccess; - - if ( g_bDisableEhandleAccess ) - { - Msg( "Access of EHANDLE/CHandle for class %s:%p in destructor!\n", - STRING(((CBaseEntity*)pEnt)->m_iClassname ), pEnt ); - } - } - -#else - -#endif - - diff --git a/game/shared/ehandle.h b/game/shared/ehandle.h deleted file mode 100644 index 3aa7c967a..000000000 --- a/game/shared/ehandle.h +++ /dev/null @@ -1,169 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef EHANDLE_H -#define EHANDLE_H -#ifdef _WIN32 -#pragma once -#endif - -#if defined( _DEBUG ) && defined( GAME_DLL ) -#include "tier0/dbg.h" -#include "cbase.h" -#endif - - -#include "const.h" -#include "basehandle.h" -#include "entitylist_base.h" - - -class IHandleEntity; - - -// -------------------------------------------------------------------------------------------------- // -// Game-code CBaseHandle implementation. -// -------------------------------------------------------------------------------------------------- // - -inline IHandleEntity* CBaseHandle::Get() const -{ - extern CBaseEntityList *g_pEntityList; - return g_pEntityList->LookupEntity( *this ); -} - - -// -------------------------------------------------------------------------------------------------- // -// CHandle. -// -------------------------------------------------------------------------------------------------- // -template< class T > -class CHandle : public CBaseHandle -{ -public: - - CHandle(); - CHandle( int iEntry, int iSerialNumber ); - CHandle( const CBaseHandle &handle ); - CHandle( T *pVal ); - - // The index should have come from a call to ToInt(). If it hasn't, you're in trouble. - static CHandle FromIndex( int index ); - - T* Get() const; - void Set( const T* pVal ); - - operator T*(); - operator T*() const; - - bool operator !() const; - bool operator==( T *val ) const; - bool operator!=( T *val ) const; - const CBaseHandle& operator=( const T *val ); - - T* operator->() const; -}; - - -// ----------------------------------------------------------------------- // -// Inlines. -// ----------------------------------------------------------------------- // - -template -CHandle::CHandle() -{ -} - - -template -CHandle::CHandle( int iEntry, int iSerialNumber ) -{ - Init( iEntry, iSerialNumber ); -} - - -template -CHandle::CHandle( const CBaseHandle &handle ) - : CBaseHandle( handle ) -{ -} - - -template -CHandle::CHandle( T *pObj ) -{ - Term(); - Set( pObj ); -} - - -template -inline CHandle CHandle::FromIndex( int index ) -{ - CHandle ret; - ret.m_Index = index; - return ret; -} - - -template -inline T* CHandle::Get() const -{ - return (T*)CBaseHandle::Get(); -} - - -template -inline CHandle::operator T *() -{ - return Get( ); -} - -template -inline CHandle::operator T *() const -{ - return Get( ); -} - - -template -inline bool CHandle::operator !() const -{ - return !Get(); -} - -template -inline bool CHandle::operator==( T *val ) const -{ - return Get() == val; -} - -template -inline bool CHandle::operator!=( T *val ) const -{ - return Get() != val; -} - -template -void CHandle::Set( const T* pVal ) -{ - CBaseHandle::Set( reinterpret_cast(pVal) ); -} - -template -inline const CBaseHandle& CHandle::operator=( const T *val ) -{ - Set( val ); - return *this; -} - -template -T* CHandle::operator -> () const -{ - return Get(); -} - - -#endif // EHANDLE_H diff --git a/game/shared/entitydatainstantiator.h b/game/shared/entitydatainstantiator.h deleted file mode 100644 index 2fec177b5..000000000 --- a/game/shared/entitydatainstantiator.h +++ /dev/null @@ -1,126 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ENTITYDATAINSTANTIATOR_H -#define ENTITYDATAINSTANTIATOR_H -#ifdef _WIN32 -#pragma once -#endif - -#include "utlhash.h" - -#include "tier0/memdbgon.h" - -// This is the hash key type, but it could just as easily be and int or void * -class CBaseEntity; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -abstract_class IEntityDataInstantiator -{ -public: - virtual ~IEntityDataInstantiator() {}; - - virtual void *GetDataObject( const CBaseEntity *instance ) = 0; - virtual void *CreateDataObject( const CBaseEntity *instance ) = 0; - virtual void DestroyDataObject( const CBaseEntity *instance ) = 0; -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -template -class CEntityDataInstantiator : public IEntityDataInstantiator -{ -public: - CEntityDataInstantiator() : - m_HashTable( 64, 0, 0, CompareFunc, KeyFunc ) - { - } - - virtual void *GetDataObject( const CBaseEntity *instance ) - { - UtlHashHandle_t handle; - HashEntry entry; - entry.key = instance; - handle = m_HashTable.Find( entry ); - - if ( handle != m_HashTable.InvalidHandle() ) - { - return (void *)m_HashTable[ handle ].data; - } - - return NULL; - } - - virtual void *CreateDataObject( const CBaseEntity *instance ) - { - UtlHashHandle_t handle; - HashEntry entry; - entry.key = instance; - handle = m_HashTable.Find( entry ); - - // Create it if not already present - if ( handle == m_HashTable.InvalidHandle() ) - { - handle = m_HashTable.Insert( entry ); - Assert( handle != m_HashTable.InvalidHandle() ); - m_HashTable[ handle ].data = new T; - - // FIXME: We'll have to remove this if any objects we instance have vtables!!! - Q_memset( m_HashTable[ handle ].data, 0, sizeof( T ) ); - } - - return (void *)m_HashTable[ handle ].data; - } - - virtual void DestroyDataObject( const CBaseEntity *instance ) - { - UtlHashHandle_t handle; - HashEntry entry; - entry.key = instance; - handle = m_HashTable.Find( entry ); - - if ( handle != m_HashTable.InvalidHandle() ) - { - delete m_HashTable[ handle ].data; - m_HashTable.Remove( handle ); - } - } - -private: - - struct HashEntry - { - HashEntry() - { - key = NULL; - data = NULL; - } - - const CBaseEntity *key; - T *data; - }; - - static bool CompareFunc( const HashEntry &src1, const HashEntry &src2 ) - { - return ( src1.key == src2.key ); - } - - - static unsigned int KeyFunc( const HashEntry &src ) - { - // Shift right to get rid of alignment bits and border the struct on a 16 byte boundary - return (unsigned int)src.key; - } - - CUtlHash< HashEntry > m_HashTable; -}; - -#include "tier0/memdbgoff.h" - -#endif // ENTITYDATAINSTANTIATOR_H diff --git a/game/shared/entitylist_base.cpp b/game/shared/entitylist_base.cpp deleted file mode 100644 index 7e56e71be..000000000 --- a/game/shared/entitylist_base.cpp +++ /dev/null @@ -1,273 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "entitylist_base.h" -#include "ihandleentity.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -enum -{ - SERIAL_MASK = 0x7fff // the max value of a serial number, rolls back to 0 when it hits this limit -}; - -void CEntInfo::ClearLinks() -{ - m_pPrev = m_pNext = this; -} - -CBaseEntityList::CEntInfoList::CEntInfoList() -{ - m_pHead = NULL; - m_pTail = NULL; -} - -// NOTE: Cut from UtlFixedLinkedList<>, UNDONE: Find a way to share this code -void CBaseEntityList::CEntInfoList::LinkBefore( CEntInfo *pBefore, CEntInfo *pElement ) -{ - Assert( pElement ); - - // Unlink it if it's in the list at the moment - Unlink(pElement); - - // The element *after* our newly linked one is the one we linked before. - pElement->m_pNext = pBefore; - - if (pBefore == NULL) - { - // In this case, we're linking to the end of the list, so reset the tail - pElement->m_pPrev = m_pTail; - m_pTail = pElement; - } - else - { - // Here, we're not linking to the end. Set the prev pointer to point to - // the element we're linking. - Assert( IsInList(pBefore) ); - pElement->m_pPrev = pBefore->m_pPrev; - pBefore->m_pPrev = pElement; - } - - // Reset the head if we linked to the head of the list - if (pElement->m_pPrev == NULL) - { - m_pHead = pElement; - } - else - { - pElement->m_pPrev->m_pNext = pElement; - } -} - -void CBaseEntityList::CEntInfoList::LinkAfter( CEntInfo *pAfter, CEntInfo *pElement ) -{ - Assert( pElement ); - - // Unlink it if it's in the list at the moment - if ( IsInList(pElement) ) - Unlink(pElement); - - // The element *before* our newly linked one is the one we linked after - pElement->m_pPrev = pAfter; - if (pAfter == NULL) - { - // In this case, we're linking to the head of the list, reset the head - pElement->m_pNext = m_pHead; - m_pHead = pElement; - } - else - { - // Here, we're not linking to the end. Set the next pointer to point to - // the element we're linking. - Assert( IsInList(pAfter) ); - pElement->m_pNext = pAfter->m_pNext; - pAfter->m_pNext = pElement; - } - - // Reset the tail if we linked to the tail of the list - if (pElement->m_pNext == NULL ) - { - m_pTail = pElement; - } - else - { - pElement->m_pNext->m_pPrev = pElement; - } -} - -void CBaseEntityList::CEntInfoList::Unlink( CEntInfo *pElement ) -{ - if (IsInList(pElement)) - { - // If we're the first guy, reset the head - // otherwise, make our previous node's next pointer = our next - if ( pElement->m_pPrev ) - { - pElement->m_pPrev->m_pNext = pElement->m_pNext; - } - else - { - m_pHead = pElement->m_pNext; - } - - // If we're the last guy, reset the tail - // otherwise, make our next node's prev pointer = our prev - if ( pElement->m_pNext ) - { - pElement->m_pNext->m_pPrev = pElement->m_pPrev; - } - else - { - m_pTail = pElement->m_pPrev; - } - - // This marks this node as not in the list, - // but not in the free list either - pElement->ClearLinks(); - } -} - -bool CBaseEntityList::CEntInfoList::IsInList( CEntInfo *pElement ) -{ - return pElement->m_pPrev != pElement; -} - -CBaseEntityList::CBaseEntityList() -{ - // These are not in any list (yet) - int i; - for ( i = 0; i < NUM_ENT_ENTRIES; i++ ) - { - m_EntPtrArray[i].ClearLinks(); - m_EntPtrArray[i].m_SerialNumber = (rand()& SERIAL_MASK); // generate random starting serial number - m_EntPtrArray[i].m_pEntity = NULL; - } - - // make a free list of the non-networkable entities - // Initially, all the slots are free. - for ( i=MAX_EDICTS+1; i < NUM_ENT_ENTRIES; i++ ) - { - CEntInfo *pList = &m_EntPtrArray[i]; - m_freeNonNetworkableList.AddToTail( pList ); - } -} - - -CBaseEntityList::~CBaseEntityList() -{ - CEntInfo *pList = m_activeList.Head(); - - while ( pList ) - { - CEntInfo *pNext = pList->m_pNext; - RemoveEntityAtSlot( GetEntInfoIndex( pList ) ); - pList = pNext; - } -} - - -CBaseHandle CBaseEntityList::AddNetworkableEntity( IHandleEntity *pEnt, int index, int iForcedSerialNum ) -{ - Assert( index >= 0 && index < MAX_EDICTS ); - return AddEntityAtSlot( pEnt, index, iForcedSerialNum ); -} - - -CBaseHandle CBaseEntityList::AddNonNetworkableEntity( IHandleEntity *pEnt ) -{ - // Find a slot for it. - CEntInfo *pSlot = m_freeNonNetworkableList.Head(); - if ( !pSlot ) - { - Warning( "CBaseEntityList::AddNonNetworkableEntity: no free slots!\n" ); - AssertMsg( 0, ( "CBaseEntityList::AddNonNetworkableEntity: no free slots!\n" ) ); - return CBaseHandle(); - } - - // Move from the free list into the allocated list. - m_freeNonNetworkableList.Unlink( pSlot ); - int iSlot = GetEntInfoIndex( pSlot ); - - return AddEntityAtSlot( pEnt, iSlot, -1 ); -} - - -void CBaseEntityList::RemoveEntity( CBaseHandle handle ) -{ - RemoveEntityAtSlot( handle.GetEntryIndex() ); -} - - -CBaseHandle CBaseEntityList::AddEntityAtSlot( IHandleEntity *pEnt, int iSlot, int iForcedSerialNum ) -{ - // Init the CSerialEntity. - CEntInfo *pSlot = &m_EntPtrArray[iSlot]; - Assert( pSlot->m_pEntity == NULL ); - pSlot->m_pEntity = pEnt; - - // Force the serial number (client-only)? - if ( iForcedSerialNum != -1 ) - { - pSlot->m_SerialNumber = iForcedSerialNum; - - #if !defined( CLIENT_DLL ) - // Only the client should force the serial numbers. - Assert( false ); - #endif - } - - // Update our list of active entities. - m_activeList.AddToTail( pSlot ); - CBaseHandle retVal( iSlot, pSlot->m_SerialNumber ); - - // Tell the entity to store its handle. - pEnt->SetRefEHandle( retVal ); - - // Notify any derived class. - OnAddEntity( pEnt, retVal ); - return retVal; -} - - -void CBaseEntityList::RemoveEntityAtSlot( int iSlot ) -{ - Assert( iSlot >= 0 && iSlot < NUM_ENT_ENTRIES ); - - CEntInfo *pInfo = &m_EntPtrArray[iSlot]; - - if ( pInfo->m_pEntity ) - { - pInfo->m_pEntity->SetRefEHandle( INVALID_EHANDLE_INDEX ); - - // Notify the derived class that we're about to remove this entity. - OnRemoveEntity( pInfo->m_pEntity, CBaseHandle( iSlot, pInfo->m_SerialNumber ) ); - - // Increment the serial # so ehandles go invalid. - pInfo->m_pEntity = NULL; - pInfo->m_SerialNumber = ( pInfo->m_SerialNumber+1)& SERIAL_MASK; - - m_activeList.Unlink( pInfo ); - - // Add the slot back to the free list if it's a non-networkable entity. - if ( iSlot >= MAX_EDICTS ) - { - m_freeNonNetworkableList.AddToTail( pInfo ); - } - } -} - - -void CBaseEntityList::OnAddEntity( IHandleEntity *pEnt, CBaseHandle handle ) -{ -} - - - -void CBaseEntityList::OnRemoveEntity( IHandleEntity *pEnt, CBaseHandle handle ) -{ -} diff --git a/game/shared/entitylist_base.h b/game/shared/entitylist_base.h deleted file mode 100644 index 045bde379..000000000 --- a/game/shared/entitylist_base.h +++ /dev/null @@ -1,209 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ENTITYLIST_BASE_H -#define ENTITYLIST_BASE_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "const.h" -#include "basehandle.h" -#include "utllinkedlist.h" -#include "ihandleentity.h" - - -class CEntInfo -{ -public: - IHandleEntity *m_pEntity; - int m_SerialNumber; - CEntInfo *m_pPrev; - CEntInfo *m_pNext; - - void ClearLinks(); -}; - - -class CBaseEntityList -{ -public: - CBaseEntityList(); - ~CBaseEntityList(); - - // Add and remove entities. iForcedSerialNum should only be used on the client. The server - // gets to dictate what the networkable serial numbers are on the client so it can send - // ehandles over and they work. - CBaseHandle AddNetworkableEntity( IHandleEntity *pEnt, int index, int iForcedSerialNum = -1 ); - CBaseHandle AddNonNetworkableEntity( IHandleEntity *pEnt ); - void RemoveEntity( CBaseHandle handle ); - - // Get an ehandle from a networkable entity's index (note: if there is no entity in that slot, - // then the ehandle will be invalid and produce NULL). - CBaseHandle GetNetworkableHandle( int iEntity ) const; - - // ehandles use this in their Get() function to produce a pointer to the entity. - IHandleEntity* LookupEntity( const CBaseHandle &handle ) const; - IHandleEntity* LookupEntityByNetworkIndex( int edictIndex ) const; - - // Use these to iterate over all the entities. - CBaseHandle FirstHandle() const; - CBaseHandle NextHandle( CBaseHandle hEnt ) const; - static CBaseHandle InvalidHandle(); - - const CEntInfo *FirstEntInfo() const; - const CEntInfo *NextEntInfo( const CEntInfo *pInfo ) const; - const CEntInfo *GetEntInfoPtr( const CBaseHandle &hEnt ) const; - const CEntInfo *GetEntInfoPtrByIndex( int index ) const; - -// Overridables. -protected: - - // These are notifications to the derived class. It can cache info here if it wants. - virtual void OnAddEntity( IHandleEntity *pEnt, CBaseHandle handle ); - - // It is safe to delete the entity here. We won't be accessing the pointer after - // calling OnRemoveEntity. - virtual void OnRemoveEntity( IHandleEntity *pEnt, CBaseHandle handle ); - - -private: - - CBaseHandle AddEntityAtSlot( IHandleEntity *pEnt, int iSlot, int iForcedSerialNum ); - void RemoveEntityAtSlot( int iSlot ); - - -private: - - class CEntInfoList - { - public: - CEntInfoList(); - - const CEntInfo *Head() const { return m_pHead; } - const CEntInfo *Tail() const { return m_pTail; } - CEntInfo *Head() { return m_pHead; } - CEntInfo *Tail() { return m_pTail; } - void AddToHead( CEntInfo *pElement ) { LinkAfter( NULL, pElement ); } - void AddToTail( CEntInfo *pElement ) { LinkBefore( NULL, pElement ); } - - void LinkBefore( CEntInfo *pBefore, CEntInfo *pElement ); - void LinkAfter( CEntInfo *pBefore, CEntInfo *pElement ); - void Unlink( CEntInfo *pElement ); - bool IsInList( CEntInfo *pElement ); - - private: - CEntInfo *m_pHead; - CEntInfo *m_pTail; - }; - - int GetEntInfoIndex( const CEntInfo *pEntInfo ) const; - - - // The first MAX_EDICTS entities are networkable. The rest are client-only or server-only. - CEntInfo m_EntPtrArray[NUM_ENT_ENTRIES]; - CEntInfoList m_activeList; - CEntInfoList m_freeNonNetworkableList; -}; - - -// ------------------------------------------------------------------------------------ // -// Inlines. -// ------------------------------------------------------------------------------------ // - -inline int CBaseEntityList::GetEntInfoIndex( const CEntInfo *pEntInfo ) const -{ - Assert( pEntInfo ); - int index = (int)(pEntInfo - m_EntPtrArray); - Assert( index >= 0 && index < NUM_ENT_ENTRIES ); - return index; -} - -inline CBaseHandle CBaseEntityList::GetNetworkableHandle( int iEntity ) const -{ - Assert( iEntity >= 0 && iEntity < MAX_EDICTS ); - if ( m_EntPtrArray[iEntity].m_pEntity ) - return CBaseHandle( iEntity, m_EntPtrArray[iEntity].m_SerialNumber ); - else - return CBaseHandle(); -} - - -inline IHandleEntity* CBaseEntityList::LookupEntity( const CBaseHandle &handle ) const -{ - if ( handle.m_Index == INVALID_EHANDLE_INDEX ) - return NULL; - - const CEntInfo *pInfo = &m_EntPtrArray[ handle.GetEntryIndex() ]; - if ( pInfo->m_SerialNumber == handle.GetSerialNumber() ) - return (IHandleEntity*)pInfo->m_pEntity; - else - return NULL; -} - - -inline IHandleEntity* CBaseEntityList::LookupEntityByNetworkIndex( int edictIndex ) const -{ - // (Legacy support). - if ( edictIndex < 0 ) - return NULL; - - Assert( edictIndex < NUM_ENT_ENTRIES ); - return (IHandleEntity*)m_EntPtrArray[edictIndex].m_pEntity; -} - - -inline CBaseHandle CBaseEntityList::FirstHandle() const -{ - if ( !m_activeList.Head() ) - return INVALID_EHANDLE_INDEX; - - int index = GetEntInfoIndex( m_activeList.Head() ); - return CBaseHandle( index, m_EntPtrArray[index].m_SerialNumber ); -} - -inline CBaseHandle CBaseEntityList::NextHandle( CBaseHandle hEnt ) const -{ - int iSlot = hEnt.GetEntryIndex(); - CEntInfo *pNext = m_EntPtrArray[iSlot].m_pNext; - if ( !pNext ) - return INVALID_EHANDLE_INDEX; - - int index = GetEntInfoIndex( pNext ); - - return CBaseHandle( index, m_EntPtrArray[index].m_SerialNumber ); -} - -inline CBaseHandle CBaseEntityList::InvalidHandle() -{ - return INVALID_EHANDLE_INDEX; -} - -inline const CEntInfo *CBaseEntityList::FirstEntInfo() const -{ - return m_activeList.Head(); -} - -inline const CEntInfo *CBaseEntityList::NextEntInfo( const CEntInfo *pInfo ) const -{ - return pInfo->m_pNext; -} - -inline const CEntInfo *CBaseEntityList::GetEntInfoPtr( const CBaseHandle &hEnt ) const -{ - int iSlot = hEnt.GetEntryIndex(); - return &m_EntPtrArray[iSlot]; -} - -inline const CEntInfo *CBaseEntityList::GetEntInfoPtrByIndex( int index ) const -{ - return &m_EntPtrArray[index]; -} - -extern CBaseEntityList *g_pEntityList; - -#endif // ENTITYLIST_BASE_H diff --git a/game/shared/entityparticletrail_shared.h b/game/shared/entityparticletrail_shared.h deleted file mode 100644 index ff3a88f80..000000000 --- a/game/shared/entityparticletrail_shared.h +++ /dev/null @@ -1,44 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ENTITYPARTICLETRAIL_SHARED_H -#define ENTITYPARTICLETRAIL_SHARED_H - -#ifdef _WIN32 -#pragma once -#endif - - -//----------------------------------------------------------------------------- -// For networking this bad boy -//----------------------------------------------------------------------------- -#ifdef CLIENT_DLL -EXTERN_RECV_TABLE( DT_EntityParticleTrailInfo ); -#else -EXTERN_SEND_TABLE( DT_EntityParticleTrailInfo ); -#endif - - -//----------------------------------------------------------------------------- -// Particle trail info -//----------------------------------------------------------------------------- -struct EntityParticleTrailInfo_t -{ - EntityParticleTrailInfo_t(); - - DECLARE_CLASS_NOBASE( EntityParticleTrailInfo_t ); - DECLARE_SIMPLE_DATADESC(); - DECLARE_EMBEDDED_NETWORKVAR(); - - string_t m_strMaterialName; - CNetworkVar( float, m_flLifetime ); - CNetworkVar( float, m_flStartSize ); - CNetworkVar( float, m_flEndSize ); -}; - - - -#endif // ENTITYPARTICLETRAIL_SHARED_H diff --git a/game/shared/env_detail_controller.cpp b/game/shared/env_detail_controller.cpp deleted file mode 100644 index 9161eaede..000000000 --- a/game/shared/env_detail_controller.cpp +++ /dev/null @@ -1,75 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -#include "env_detail_controller.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -LINK_ENTITY_TO_CLASS(env_detail_controller, CEnvDetailController); - -IMPLEMENT_NETWORKCLASS_ALIASED( EnvDetailController, DT_DetailController ) - -BEGIN_NETWORK_TABLE_NOBASE( CEnvDetailController, DT_DetailController ) - #ifdef CLIENT_DLL - RecvPropFloat( RECVINFO( m_flFadeStartDist ) ), - RecvPropFloat( RECVINFO( m_flFadeEndDist ) ), - #else - SendPropFloat( SENDINFO( m_flFadeStartDist ) ), - SendPropFloat( SENDINFO( m_flFadeEndDist ) ), - #endif -END_NETWORK_TABLE() - -static CEnvDetailController *s_detailController = NULL; -CEnvDetailController * GetDetailController() -{ - return s_detailController; -} - -CEnvDetailController::CEnvDetailController() -{ - s_detailController = this; -} - -CEnvDetailController::~CEnvDetailController() -{ - if ( s_detailController == this ) - { - s_detailController = NULL; - } -} - -//-------------------------------------------------------------------------------------------------------------- -int CEnvDetailController::UpdateTransmitState() -{ -#ifndef CLIENT_DLL - // ALWAYS transmit to all clients. - return SetTransmitState( FL_EDICT_ALWAYS ); -#else - return 0; -#endif -} - -#ifndef CLIENT_DLL - - bool CEnvDetailController::KeyValue( const char *szKeyName, const char *szValue ) - { - if (FStrEq(szKeyName, "fademindist")) - { - m_flFadeStartDist = atof(szValue); - } - else if (FStrEq(szKeyName, "fademaxdist")) - { - m_flFadeEndDist = atof(szValue); - } - - return true; - } - -#endif // !CLIENT_DLL diff --git a/game/shared/env_detail_controller.h b/game/shared/env_detail_controller.h deleted file mode 100644 index 731571d28..000000000 --- a/game/shared/env_detail_controller.h +++ /dev/null @@ -1,35 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifdef CLIENT_DLL - #define CEnvDetailController C_EnvDetailController -#endif // CLIENT_DLL - -//----------------------------------------------------------------------------- -// Implementation of the class that controls detail prop fade distances -//----------------------------------------------------------------------------- -class CEnvDetailController : public CBaseEntity -{ -public: - DECLARE_CLASS( CEnvDetailController, CBaseEntity ); - DECLARE_NETWORKCLASS(); - - CEnvDetailController(); - virtual ~CEnvDetailController(); - -#ifndef CLIENT_DLL - virtual bool KeyValue( const char *szKeyName, const char *szValue ); -#endif // !CLIENT_DLL - - CNetworkVar( float, m_flFadeStartDist ); - CNetworkVar( float, m_flFadeEndDist ); - - // ALWAYS transmit to all clients. - virtual int UpdateTransmitState( void ); -}; - -CEnvDetailController * GetDetailController(); diff --git a/game/shared/env_meteor_shared.cpp b/game/shared/env_meteor_shared.cpp deleted file mode 100644 index 5328dedad..000000000 --- a/game/shared/env_meteor_shared.cpp +++ /dev/null @@ -1,399 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "env_meteor_shared.h" -#include "mapdata_shared.h" -#include "sharedInterface.h" - -//============================================================================= -// -// Meteor Functions. -// - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CEnvMeteorShared::CEnvMeteorShared() -{ - m_nID = 0; - m_vecStartPosition.Init(); - m_vecDirection.Init(); - m_flSpeed = 0.0f; - m_flDamageRadius = 0.0f; - m_flStartTime = METEOR_INVALID_TIME; - m_flPassiveTime = METEOR_INVALID_TIME; - m_flWorldEnterTime = METEOR_INVALID_TIME; - m_flWorldExitTime = METEOR_INVALID_TIME; - m_nLocation = METEOR_LOCATION_INVALID; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CEnvMeteorShared::Init( int nID, float flStartTime, float flPassiveTime, - const Vector &vecStartPosition, - const Vector &vecDirection, float flSpeed, float flDamageRadius, - const Vector &vecTriggerMins, const Vector &vecTriggerMaxs ) -{ - // Setup initial parametric state. - m_nID = nID; - VectorCopy( vecStartPosition, m_vecStartPosition ); - VectorCopy( vecStartPosition, m_vecPos ); - VectorCopy( vecDirection, m_vecDirection ); - m_flSpeed = flSpeed; - m_flDamageRadius = flDamageRadius; - m_flStartTime = flPassiveTime + flStartTime; - m_flPassiveTime = flPassiveTime; - m_flPosTime = m_flStartTime; - - // Calculate the enter/exit times. - CalcEnterAndExitTimes( vecTriggerMins, vecTriggerMaxs ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CEnvMeteorShared::GetPositionAtTime( float flTime, Vector &vecPosition ) -{ - float flDeltaTime = flTime - m_flPosTime; - Vector vecVelocity( m_vecDirection.x * m_flSpeed, m_vecDirection.y * m_flSpeed, m_vecDirection.z * m_flSpeed ); - VectorMA( m_vecPos, flDeltaTime, vecVelocity, vecPosition ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CEnvMeteorShared::ConvertFromSkyboxToWorld( void ) -{ - // The new start position is the position at which the meteor enters - // the skybox. - Vector vecSkyboxOrigin; - g_pMapData->Get3DSkyboxOrigin( vecSkyboxOrigin ); - float flSkyboxScale = g_pMapData->Get3DSkyboxScale(); - - m_vecPos += ( m_flSpeed * m_vecDirection ) * ( m_flWorldEnterTime - m_flStartTime ); - m_vecPos -= vecSkyboxOrigin; - m_vecPos *= flSkyboxScale; - - // Scale the speed. - m_flSpeed *= flSkyboxScale; - - // Reset the start time. - m_flPosTime = m_flWorldEnterTime; - - // Set the location to world. - m_nLocation = METEOR_LOCATION_WORLD; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CEnvMeteorShared::ConvertFromWorldToSkybox( void ) -{ - // Scale the speed. - float flSkyboxScale = g_pMapData->Get3DSkyboxScale(); - m_flSpeed /= flSkyboxScale; - - float flDeltaTime = m_flWorldExitTime - m_flStartTime; - Vector vecVelocity( m_vecDirection.x * m_flSpeed, m_vecDirection.y * m_flSpeed, m_vecDirection.z * m_flSpeed ); - VectorMA( m_vecStartPosition, flDeltaTime, vecVelocity, m_vecPos ); - - // Reset the start time. - m_flPosTime = m_flWorldExitTime; - - // Set the location to skybox. - m_nLocation = METEOR_LOCATION_SKYBOX; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CEnvMeteorShared::IsInSkybox( float flTime ) -{ - // Check to see if we are always in the skybox! - if ( m_flWorldEnterTime == METEOR_INVALID_TIME ) - return true; - - return ( ( flTime < m_flWorldEnterTime ) || ( flTime > m_flWorldExitTime ) ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CEnvMeteorShared::IsPassive( float flTime ) -{ - return ( flTime < m_flPassiveTime ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CEnvMeteorShared::WillTransition( void ) -{ - return ( m_flWorldEnterTime == METEOR_INVALID_TIME ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -float CEnvMeteorShared::GetDamageRadius( void ) -{ - return m_flDamageRadius; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CEnvMeteorShared::CalcEnterAndExitTimes( const Vector &vecTriggerMins, - const Vector &vecTriggerMaxs ) -{ -#define METEOR_TRIGGER_EPSILON 0.001f - - // Initialize the enter/exit fractions. - float flEnterFrac = 0.0f; - float flExitFrac = 1.0f; - - // Create an arbitrarily large end position. - Vector vecEndPosition; - VectorMA( m_vecStartPosition, 32000.0f, m_vecDirection, vecEndPosition ); - - float flFrac, flDistStart, flDistEnd; - for( int iAxis = 0; iAxis < 3; iAxis++ ) - { - // Negative Axis - flDistStart = -m_vecStartPosition[iAxis] + vecTriggerMins[iAxis]; - flDistEnd = -vecEndPosition[iAxis] + vecTriggerMins[iAxis]; - - if ( ( flDistStart > 0.0f ) && ( flDistEnd < 0.0f ) ) - { - flFrac = ( flDistStart - METEOR_TRIGGER_EPSILON ) / ( flDistStart - flDistEnd ); - if ( flFrac > flEnterFrac ) { flEnterFrac = flFrac; } - } - - if ( ( flDistStart < 0.0f ) && ( flDistEnd > 0.0f ) ) - { - flFrac = ( flDistStart + METEOR_TRIGGER_EPSILON ) / ( flDistStart - flDistEnd ); - if( flFrac < flExitFrac ) { flExitFrac = flFrac; } - } - - if ( ( flDistStart > 0.0f ) && ( flDistEnd > 0.0f ) ) - return; - - // Positive Axis - flDistStart = m_vecStartPosition[iAxis] - vecTriggerMaxs[iAxis]; - flDistEnd = vecEndPosition[iAxis] - vecTriggerMaxs[iAxis]; - - if ( ( flDistStart > 0.0f ) && ( flDistEnd < 0.0f ) ) - { - flFrac = ( flDistStart - METEOR_TRIGGER_EPSILON ) / ( flDistStart - flDistEnd ); - if ( flFrac > flEnterFrac ) { flEnterFrac = flFrac; } - } - - if ( ( flDistStart < 0.0f ) && ( flDistEnd > 0.0f ) ) - { - flFrac = ( flDistStart + METEOR_TRIGGER_EPSILON ) / ( flDistStart - flDistEnd ); - if( flFrac < flExitFrac ) { flExitFrac = flFrac; } - } - - if ( ( flDistStart > 0.0f ) && ( flDistEnd > 0.0f ) ) - return; - } - - // Check for intersection. - if ( flExitFrac >= flEnterFrac ) - { - // Check to see if we start in the world or the skybox! - if ( flEnterFrac == 0.0f ) - { - m_nLocation = METEOR_LOCATION_WORLD; - } - else - { - m_nLocation = METEOR_LOCATION_SKYBOX; - } - - // Calculate the enter/exit times. - Vector vecEnterPoint, vecExitPoint, vecDeltaPosition; - VectorSubtract( vecEndPosition, m_vecStartPosition, vecDeltaPosition ); - VectorScale( vecDeltaPosition, flEnterFrac, vecEnterPoint ); - VectorScale( vecDeltaPosition, flExitFrac, vecExitPoint ); - - m_flWorldEnterTime = vecEnterPoint.Length() / m_flSpeed; - m_flWorldExitTime = vecExitPoint.Length() / m_flSpeed; - m_flWorldEnterTime += m_flStartTime; - m_flWorldExitTime += m_flStartTime; - } - -#undef METEOR_TRIGGER_EPSILON -} - -//============================================================================= -// -// Meteor Spawner Functions. -// - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CEnvMeteorSpawnerShared::CEnvMeteorSpawnerShared() -{ - m_pFactory = NULL; - m_nMeteorCount = 0; - - m_flStartTime = 0.0f; - m_nRandomSeed = 0; - - m_iMeteorType = -1; - m_flMeteorDamageRadius = 0.0f; - m_bSkybox = true; - - m_flMinSpawnTime = 0.0f; - m_flMaxSpawnTime = 0.0f; - m_nMinSpawnCount = 0; - m_nMaxSpawnCount = 0; - m_vecMinBounds.Init(); - m_vecMaxBounds.Init(); - m_flMinSpeed = 0.0f; - m_flMaxSpeed = 0.0f; - - m_flNextSpawnTime = 0.0f; - - m_vecTriggerMins.Init(); - m_vecTriggerMaxs.Init(); - m_vecTriggerCenter.Init(); - - // Debug! - m_nRandomCallCount = 0; - - m_aTargets.Purge(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CEnvMeteorSpawnerShared::Init( IMeteorFactory *pFactory, int nRandomSeed, float flTime, - const Vector &vecMinBounds, const Vector &vecMaxBounds, - const Vector &vecTriggerMins, const Vector &vecTriggerMaxs ) -{ - // Factory. - m_pFactory = pFactory; - - // Setup the random number stream. - m_nRandomSeed = nRandomSeed; - m_NumberStream.SetSeed( nRandomSeed ); - - // Start time. - m_flStartTime = flTime; - - // Copy the spawner bounds. - m_vecMinBounds = vecMinBounds; - m_vecMaxBounds = vecMaxBounds; - - // Copy the trigger bounds. - m_vecTriggerMins = vecTriggerMins; - m_vecTriggerMaxs = vecTriggerMaxs; - - // Get the center of the trigger bounds. - m_vecTriggerCenter = ( m_vecTriggerMins + m_vecTriggerMaxs ) * 0.5f; - - // Setup spawn time. - m_flNextSpawnTime = m_flStartTime + m_flMaxSpawnTime; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CEnvMeteorSpawnerShared::GetRandomInt( int nMin, int nMax ) -{ - m_nRandomCallCount++; - return m_NumberStream.RandomInt( nMin, nMax ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -float CEnvMeteorSpawnerShared::GetRandomFloat( float flMin, float flMax ) -{ - m_nRandomCallCount++; - return m_NumberStream.RandomFloat( flMin, flMax ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -float CEnvMeteorSpawnerShared::MeteorThink( float flTime ) -{ - // Check for spawn. - if ( flTime < m_flNextSpawnTime ) - return m_flNextSpawnTime; - - while ( m_flNextSpawnTime < flTime ) - { - // Get a random number of meteors to spawn and spawn them. - int nMeteorCount = GetRandomInt( m_nMinSpawnCount, m_nMaxSpawnCount ); - for ( int iMeteor = 0; iMeteor < nMeteorCount; iMeteor++ ) - { - // Increment the number of meteors created (starting with 1). - m_nMeteorCount++; - - // Get a random meteor position. - Vector meteorOrigin( GetRandomFloat( m_vecMinBounds.GetX(), m_vecMaxBounds.GetX() ) /* x */, - GetRandomFloat( m_vecMinBounds.GetY(), m_vecMaxBounds.GetY() ) /* y */, - GetRandomFloat( m_vecMinBounds.GetZ(), m_vecMaxBounds.GetZ() ) /* z */ ); - - // Calculate the direction of the meteor based on "targets." - Vector vecDirection( 0.0f, 0.0f, -1.0f ); - if ( m_aTargets.Count() > 0 ) - { - float flFreq = 1.0f / m_aTargets.Count(); - float flFreqAccum = flFreq; - - int iTarget; - for( iTarget = 0; iTarget < m_aTargets.Count(); ++iTarget ) - { - float flRandom = GetRandomFloat( 0.0f, 1.0f ); - if ( flRandom < flFreqAccum ) - break; - - flFreqAccum += flFreq; - } - - // Should ever be here! - if ( iTarget == m_aTargets.Count() ) - { - iTarget--; - } - - // Just set it to the first target for now!!! - // NOTE: Will randomly generate from list of targets when more than 1 in - // the future. - - // Move the meteor into the "world." - Vector vecPositionInWorld; - Vector vecSkyboxOrigin; - g_pMapData->Get3DSkyboxOrigin( vecSkyboxOrigin ); - vecPositionInWorld = ( meteorOrigin - vecSkyboxOrigin ); - vecPositionInWorld *= g_pMapData->Get3DSkyboxScale(); - - Vector vecTargetPos = m_aTargets[iTarget].m_vecPosition; - vecTargetPos.x += GetRandomFloat( -m_aTargets[iTarget].m_flRadius, m_aTargets[iTarget].m_flRadius ); - vecTargetPos.y += GetRandomFloat( -m_aTargets[iTarget].m_flRadius, m_aTargets[iTarget].m_flRadius ); - vecTargetPos.z += GetRandomFloat( -m_aTargets[iTarget].m_flRadius, m_aTargets[iTarget].m_flRadius ); - - vecDirection = vecTargetPos - vecPositionInWorld; - VectorNormalize( vecDirection ); - } - - // Pass in the randomized position, randomized speed, and start time. - m_pFactory->CreateMeteor( m_nMeteorCount, m_iMeteorType, meteorOrigin, - vecDirection /* direction */, - GetRandomFloat( m_flMinSpeed, m_flMaxSpeed ) /* speed */, - m_flNextSpawnTime, m_flMeteorDamageRadius, - m_vecTriggerMins, m_vecTriggerMaxs ); - } - - // Set next spawn time. - m_flNextSpawnTime += GetRandomFloat( m_flMinSpawnTime, m_flMaxSpawnTime ); - } - - // Return the next spawn time. - return ( m_flNextSpawnTime - gpGlobals->curtime ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CEnvMeteorSpawnerShared::AddToTargetList( const Vector &vecPosition, float flRadius ) -{ - int iTarget = m_aTargets.AddToTail(); - m_aTargets[iTarget].m_vecPosition = vecPosition; - m_aTargets[iTarget].m_flRadius = flRadius; -} diff --git a/game/shared/env_meteor_shared.h b/game/shared/env_meteor_shared.h deleted file mode 100644 index 876d8bd56..000000000 --- a/game/shared/env_meteor_shared.h +++ /dev/null @@ -1,202 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ENV_METEOR_SHARED_H -#define ENV_METEOR_SHARED_H -#pragma once - -#include "vstdlib/random.h" -#include "mathlib/vector.h" -#include "utlvector.h" - -//============================================================================= -// -// Shared Meteor Class -// -#define METEOR_INVALID_TIME -9999.9f -#define METEOR_PASSIVE_TIME 0.0f -#define METEOR_MAX_LIFETIME 60.0f -#define METEOR_MIN_SIZE Vector( -100, -100, -100 ) -#define METEOR_MAX_SIZE Vector( 100, 100, 100 ) - -#define METEOR_LOCATION_INVALID -1 -#define METEOR_LOCATION_WORLD 0 -#define METEOR_LOCATION_SKYBOX 1 - -class CEnvMeteorShared -{ -public: - - //------------------------------------------------------------------------- - // Initialization. - //------------------------------------------------------------------------- - CEnvMeteorShared(); - void Init( int nID, float flStartTime, float flPassiveTime, - const Vector &vecStartPosition, - const Vector &vecDirection, float flSpeed, float flDamageRadius, - const Vector &vecTriggerMins, const Vector &vecTriggerMaxs ); - - //------------------------------------------------------------------------- - // Returns the position of the object at a given time. - //------------------------------------------------------------------------- - void GetPositionAtTime( float flTime, Vector &vecPosition ); - - //------------------------------------------------------------------------- - // Changes an objects paramters from "skybox space" to "world space." - //------------------------------------------------------------------------- - void ConvertFromSkyboxToWorld( void ); - - //------------------------------------------------------------------------- - // Changes an objects paramters from "world space" to "skybox space." - //------------------------------------------------------------------------- - void ConvertFromWorldToSkybox( void ); - - //------------------------------------------------------------------------- - // Returns whether or not the object is the the skybox given the time. - //------------------------------------------------------------------------- - bool IsInSkybox( float flTime ); - - //------------------------------------------------------------------------- - // Returns whether or not the object is moving in the skybox (or passive). - //------------------------------------------------------------------------- - bool IsPassive( float flTime ); - - //------------------------------------------------------------------------- - // Returns whether or not the object will ever transition from skybox to world. - //------------------------------------------------------------------------- - bool WillTransition( void ); - - //------------------------------------------------------------------------- - // Returns the splash damage radius of the object. - //------------------------------------------------------------------------- - float GetDamageRadius( void ); - -public: - - int m_nID; // unique identifier - - // The objects initial parametric conditions. - Vector m_vecStartPosition; - Vector m_vecDirection; - float m_flSpeed; // (units/sec), unit = 1 inch - float m_flStartTime; - - // NOTE: All times are absolute - ie m_flStartTime has been added in. - - // The time after the starting time in which it object starts to "move." - float m_flPassiveTime; - - // The enter and exit times define the times at which the object enters and - // exits the world. In other words, m_flEnterTime is the time at which the - // object leaves the skybox and enters the world. m_flExitTime is the opposite. - float m_flWorldEnterTime; - float m_flWorldExitTime; - - float m_flPosTime; // Timer used to find the position of the meteor. - Vector m_vecPos; - - // - int m_nLocation; // 0 = Skybox, 1 = World - - float m_flDamageRadius; // - -private: - - // Calculate the enter/exit times. (called from Init) - void CalcEnterAndExitTimes( const Vector &vecTriggerMins, const Vector &vecTriggerMaxs ); -}; - -//============================================================================= -// -// Meteor Factory Interface -// -abstract_class IMeteorFactory -{ -public: - - virtual void CreateMeteor( int nID, int iType, - const Vector &vecPosition, const Vector &vecDirection, - float flSpeed, float flStartTime, float flDamageRadius, - const Vector &vecTriggerMins, const Vector &vecTriggerMaxs ) = 0; -}; - -//============================================================================= -// -// Shared Meteor Spawner Class -// -class CEnvMeteorSpawnerShared -{ -public: - DECLARE_CLASS_NOBASE( CEnvMeteorSpawnerShared ); - DECLARE_EMBEDDED_NETWORKVAR(); - - //------------------------------------------------------------------------- - // Initialization. - //------------------------------------------------------------------------- - CEnvMeteorSpawnerShared(); - void Init( IMeteorFactory *pFactory, int nRandomSeed, float flTime, - const Vector &vecMinBounds, const Vector &vecMaxBounds, - const Vector &vecTriggerMins, const Vector &vecTriggerMaxs ); - - //------------------------------------------------------------------------- - // Method to generate meteors. - // Time passed in here is global time, not delta time. - // The function returns the time at which it must be called again. - //------------------------------------------------------------------------- - float MeteorThink( float flTime ); - - //------------------------------------------------------------------------- - // Add meteor target data, used to determine meteor travel direction. - //------------------------------------------------------------------------- - void AddToTargetList( const Vector &vecPosition, float flRadius ); - - // Debugging! - int GetRandomInt( int nMin, int nMax ); - float GetRandomFloat( float flMin, float flMax ); - -public: - - // Factory. - IMeteorFactory *m_pFactory; // Meteor creation factory. - - int m_nMeteorCount; // Number of meteors created - used as IDs - - // Initial spawner data. - CNetworkVar( float, m_flStartTime ); // Start time. - CNetworkVar( int, m_nRandomSeed ); // The random number stream seed. - - CNetworkVar( int, m_iMeteorType ); // Type of meteor. - float m_flMeteorDamageRadius; // Meteor damage radius. - CNetworkVar( bool, m_bSkybox ); // Is the spawner in the skybox? - - CNetworkVar( float, m_flMinSpawnTime ); // Spawn time - Min - CNetworkVar( float, m_flMaxSpawnTime ); // Max - CNetworkVar( int, m_nMinSpawnCount ); // Number of meteors to spawn - Min - CNetworkVar( int, m_nMaxSpawnCount ); // Max - CNetworkVector( m_vecMinBounds ); // Spawner volume (space) - Min - CNetworkVector( m_vecMaxBounds ); // Max - CNetworkVar( float, m_flMinSpeed ); // Meteor speed - Min - CNetworkVar( float, m_flMaxSpeed ); // Max - CNetworkVector( m_vecTriggerMins ); // World Bounds (Trigger) in 3D Skybox - Min - CNetworkVector( m_vecTriggerMaxs ); // Max - Vector m_vecTriggerCenter; - - // Generated data. - int m_nRandomCallCount; // Debug! Keep track of number steam calls. - float m_flNextSpawnTime; // Next meteor spawn time (random). - CUniformRandomStream m_NumberStream; // Used to generate random numbers. - - // Use "Targets" to determine meteor direction(s). - struct meteortarget_t - { - Vector m_vecPosition; - float m_flRadius; - }; - CUtlVector m_aTargets; -}; - -#endif // ENV_METEOR_SHARED_H diff --git a/game/shared/env_wind_shared.cpp b/game/shared/env_wind_shared.cpp deleted file mode 100644 index 499da241a..000000000 --- a/game/shared/env_wind_shared.cpp +++ /dev/null @@ -1,293 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// Information about algorithmic stuff that can occur on both client + server -// -// In order to reduce network traffic, it's possible to create a algorithms -// that will work on both the client and the server and be totally repeatable. -// All we need do is to send down initial conditions and let the algorithm -// compute the values at various times. Note that this algorithm will be called -// at different times with different frequencies on the client and server. -// -// The trick here is that in order for it to be repeatable, the algorithm either -// cannot depend on random numbers, or, if it does, we need to make sure that -// the random numbers generated are effectively done at the beginning of time, -// so that differences in frame rate on client and server won't matter. It also -// is important that the initial state sent across the network is identical -// bitwise so that we produce the exact same results. Therefore no compression -// should be used in the datatables. -// -// Note also that each algorithm must have its own random number stream so that -// it cannot possibly interact with other code using random numbers that will -// be called at various different intervals on the client + server. Use the -// CUniformRandomStream class for this. -// -// There are two types of client-server neutral code: Code that doesn't interact -// with player prediction, and code that does. The code that doesn't interact -// with player prediction simply has to be able to produce the result f(time) -// where time is monotonically increasing. For prediction, we have to produce -// the result f(time) where time does *not* monotonically increase (time can be -// anywhere between the "current" time and the prior 10 seconds). -// -// Code that is not used by player prediction can maintain state because later -// calls will always compute the value at some future time. This computation can -// use random number generation, but with the following restriction: Your code -// must generate exactly the same number of random numbers regardless of how -// frequently the code is called. -// -// In specific, this means that all random numbers used must either be computed -// at init time, or must be used in an 'event-based form'. Namely, use random -// numbers to compute the time at which events occur and the random inputs for -// those events. When simulating forward, you must simulate all intervening -// time and generate the same number of random numbers. -// -// For functions planned to be used by player prediction, one method is to use -// some sort of stateless computation (where the only states are the initial -// state and time). Note that random number generators have state implicit in -// the number of calls made to that random number generator, and therefore you -// cannot call a random number generator unless you are able to -// -// 1) Use a random number generator that can return the ith random number, namely: -// -// float r = random( i ); // i == the ith number in the random sequence -// -// 2) Be able to accurately know at any given time t how many random numbers -// have already been generated (namely, compute the i in part 1 above). -// -// There is another alternative for code meant to be used by player prediction: -// you could just store a history of 'events' from which you could completely -// determine the value of f(time). That history would need to be at least 10 -// seconds long, which is guaranteed to be longer than the amount of time that -// prediction would need. I've written a class which I haven't tested yet (but -// will be using soon) called CTimedEventQueue (currently located in -// env_wind_shared.h) which I plan to use to solve my problem (getting wind to -// blow players). -// -//=============================================================================// -#include "cbase.h" -#include "env_wind_shared.h" -#include "soundenvelope.h" -#include "IEffects.h" -#include "engine/IEngineSound.h" -#include "sharedInterface.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// globals -//----------------------------------------------------------------------------- -static Vector s_vecWindVelocity( 0, 0, 0 ); - - -CEnvWindShared::CEnvWindShared() : m_WindAveQueue(10), m_WindVariationQueue(10) -{ - m_pWindSound = NULL; -} - -CEnvWindShared::~CEnvWindShared() -{ - if (m_pWindSound) - { - CSoundEnvelopeController::GetController().Shutdown( m_pWindSound ); - } -} - -void CEnvWindShared::Init( int nEntIndex, int iRandomSeed, float flTime, - int iInitialWindYaw, float flInitialWindSpeed ) -{ - m_iEntIndex = nEntIndex; - m_flWindAngleVariation = m_flWindSpeedVariation = 1.0f; - m_flStartTime = m_flSimTime = m_flSwitchTime = m_flVariationTime = flTime; - m_iWindSeed = iRandomSeed; - m_Stream.SetSeed( iRandomSeed ); - m_WindVariationStream.SetSeed( iRandomSeed ); - m_iWindDir = m_iInitialWindDir = iInitialWindYaw; - - m_flAveWindSpeed = m_flWindSpeed = m_flInitialWindSpeed = flInitialWindSpeed; - - /* - // Cache in the wind sound... - if (!g_pEffects->IsServer()) - { - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - m_pWindSound = controller.SoundCreate( -1, CHAN_STATIC, - "EnvWind.Loop", ATTN_NONE ); - controller.Play( m_pWindSound, 0.0f, 100 ); - } - */ - - // Next time a change happens (which will happen immediately), it'll stop gusting - m_bGusting = true; -} - - -//----------------------------------------------------------------------------- -// Computes wind variation -//----------------------------------------------------------------------------- - -#define WIND_VARIATION_UPDATE_TIME 0.1f - -void CEnvWindShared::ComputeWindVariation( float flTime ) -{ - // The wind variation is updated every 10th of a second.. - while( flTime >= m_flVariationTime ) - { - m_flWindAngleVariation = m_WindVariationStream.RandomFloat( -10, 10 ); - m_flWindSpeedVariation = 1.0 + m_WindVariationStream.RandomFloat( -0.2, 0.2 ); - m_flVariationTime += WIND_VARIATION_UPDATE_TIME; - } -} - - - -//----------------------------------------------------------------------------- -// Updates the wind sound -//----------------------------------------------------------------------------- -void CEnvWindShared::UpdateWindSound( float flTotalWindSpeed ) -{ - if (!g_pEffects->IsServer()) - { - float flDuration = random->RandomFloat( 1.0f, 2.0f ); - CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); - - // FIXME: Tweak with these numbers - float flNormalizedWindSpeed = flTotalWindSpeed / 150.0f; - if (flNormalizedWindSpeed > 1.0f) - flNormalizedWindSpeed = 1.0f; - float flPitch = 120 * Bias( flNormalizedWindSpeed, 0.3f ) + 100; - float flVolume = 0.3f * Bias( flNormalizedWindSpeed, 0.3f ) + 0.7f; - controller.SoundChangePitch( m_pWindSound, flPitch, flDuration ); - controller.SoundChangeVolume( m_pWindSound, flVolume, flDuration ); - } -} - - -//----------------------------------------------------------------------------- -// Updates the wind speed -//----------------------------------------------------------------------------- - -#define WIND_ACCELERATION 150.0f // wind speed can accelerate this many units per second -#define WIND_DECELERATION 15.0f // wind speed can decelerate this many units per second - -float CEnvWindShared::WindThink( float flTime ) -{ - // NOTE: This algorithm can be client-server neutal because we're using - // the random number generator to generate *time* at which the wind changes. - // We therefore need to structure the algorithm so that no matter the - // frequency of calls to this function we produce the same wind speeds... - - ComputeWindVariation( flTime ); - - while (true) - { - // First, simulate up to the next switch time... - float flTimeToSwitch = m_flSwitchTime - m_flSimTime; - float flMaxDeltaTime = flTime - m_flSimTime; - - bool bGotToSwitchTime = (flMaxDeltaTime > flTimeToSwitch); - - float flSimDeltaTime = bGotToSwitchTime ? flTimeToSwitch : flMaxDeltaTime; - - // Now that we've chosen - // either ramp up, or sleep till change - bool bReachedSteadyState = true; - if ( m_flAveWindSpeed > m_flWindSpeed ) - { - m_flWindSpeed += WIND_ACCELERATION * flSimDeltaTime; - if (m_flWindSpeed > m_flAveWindSpeed) - m_flWindSpeed = m_flAveWindSpeed; - else - bReachedSteadyState = false; - } - else if ( m_flAveWindSpeed < m_flWindSpeed ) - { - m_flWindSpeed -= WIND_DECELERATION * flSimDeltaTime; - if (m_flWindSpeed < m_flAveWindSpeed) - m_flWindSpeed = m_flAveWindSpeed; - else - bReachedSteadyState = false; - } - - // Update the sim time - - // If we didn't get to a switch point, then we're done simulating for now - if (!bGotToSwitchTime) - { - m_flSimTime = flTime; - - // We're about to exit, let's set the wind velocity... - QAngle vecWindAngle( 0, m_iWindDir + m_flWindAngleVariation, 0 ); - AngleVectors( vecWindAngle, &s_vecWindVelocity ); - float flTotalWindSpeed = m_flWindSpeed * m_flWindSpeedVariation; - s_vecWindVelocity *= flTotalWindSpeed; - - // If we reached a steady state, we don't need to be called until the switch time - // Otherwise, we should be called immediately - - // FIXME: If we ever call this from prediction, we'll need - // to only update the sound if it's a new time - // Or, we'll need to update the sound elsewhere. - // Update the sound.... -// UpdateWindSound( flTotalWindSpeed ); - - // Always immediately call, the wind is forever varying - return ( flTime + 0.01f ); - } - - m_flSimTime = m_flSwitchTime; - - // Switch gusting state.. - if( m_bGusting ) - { - // wind is gusting, so return to normal wind - m_flAveWindSpeed = m_Stream.RandomInt( m_iMinWind, m_iMaxWind ); - - // set up for another gust later - m_bGusting = false; - m_flSwitchTime += m_flMinGustDelay + m_Stream.RandomFloat( 0, m_flMaxGustDelay ); - -#ifndef CLIENT_DLL - m_OnGustEnd.FireOutput( NULL, NULL ); -#endif - } - else - { - // time for a gust. - m_flAveWindSpeed = m_Stream.RandomInt( m_iMinGust, m_iMaxGust ); - - // change wind direction, maybe a lot - m_iWindDir = (int)anglemod( m_iWindDir + m_Stream.RandomInt(-m_iGustDirChange, m_iGustDirChange) ); - - // set up to stop the gust in a short while - m_bGusting = true; - -#ifndef CLIENT_DLL - m_OnGustStart.FireOutput( NULL, NULL ); -#endif - - // !!!HACKHACK - gust duration tied to the length of a particular wave file - m_flSwitchTime += m_flGustDuration; - } - } -} - - -//----------------------------------------------------------------------------- -// Method to reset windspeed.. -//----------------------------------------------------------------------------- -void ResetWindspeed() -{ - s_vecWindVelocity.Init( 0, 0, 0 ); -} - - -//----------------------------------------------------------------------------- -// Method to sample the windspeed at a particular time -//----------------------------------------------------------------------------- -void GetWindspeedAtTime( float flTime, Vector &vecVelocity ) -{ - // For now, ignore history and time.. fix later when we use wind to affect - // client-side prediction - VectorCopy( s_vecWindVelocity, vecVelocity ); -} diff --git a/game/shared/env_wind_shared.h b/game/shared/env_wind_shared.h deleted file mode 100644 index 4a371beea..000000000 --- a/game/shared/env_wind_shared.h +++ /dev/null @@ -1,244 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements visual effects entities: sprites, beams, bubbles, etc. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ENV_WIND_SHARED_H -#define ENV_WIND_SHARED_H - -#include "utllinkedlist.h" -#include "vstdlib/random.h" -#include "tier0/dbg.h" -#include "mathlib/vector.h" -#include - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class CSoundPatch; - -//----------------------------------------------------------------------------- -// Class used to help store events that occurred over time -//----------------------------------------------------------------------------- -template -class CTimedEventQueue -{ -public: - // The time passed in here represents the amount of time the queue stores - CTimedEventQueue( float flMaxTime ); - - // Adds an event to the queue, will pop off stale events from the queue - // NOTE: All events added to the queue must monotonically increase in time! - I PushEvent( float flTime, const T &data ); - - // Grabs the last event that happened before or at the specified time - I GetEventIndex( float flTime ) const; - - // Gets event information - float GetEventTime( I i ) const; - const T &GetEventData( I i ) const; - -private: - struct QueueEntry_t - { - float m_flTime; - T m_Data; - }; - - float m_flQueueHeadTime; - float m_flMaxTime; - CUtlLinkedList< T, I > m_Queue; -}; - - -//----------------------------------------------------------------------------- -// The time passed in here represents the amount of time the queue stores -//----------------------------------------------------------------------------- -template -CTimedEventQueue::CTimedEventQueue( float flMaxTime ) : m_flMaxTime(flMaxTime) -{ - // The length of time of events in the queue must be reasonable - Assert( m_flMaxTime > 0.0f ); - m_flQueueHeadTime = -FLT_MAX; -} - - -//----------------------------------------------------------------------------- -// Adds an event to the queue, will pop off stale events from the queue -//----------------------------------------------------------------------------- -template -I CTimedEventQueue::PushEvent( float flTime, const T &data ) -{ - Assert( m_flQueueHeadTime <= flTime ); - m_flQueueHeadTime = flTime; - - // First push the event... - I idx = m_Queue.AddToHead(); - m_Queue[idx].m_flTime = flTime; - m_Queue[idx].m_Data = data; - - // Then retire stale events... - I i = m_Queue.Tail(); - while (m_Queue[i].m_flTime < m_flQueueHeadTime - m_flMaxTime ) - { - I prev = m_Queue.Prev(i); - Assert( prev != m_Queue.InvalidIndex() ); - m_Queue.Remove(i); - i = prev; - } - - return idx; -} - - -//----------------------------------------------------------------------------- -// Grabs the last event that happened before or at the specified time -//----------------------------------------------------------------------------- -template -I CTimedEventQueue::GetEventIndex( float flTime ) const -{ - // This checks for a request that fell off the queue - Assert( (flTime >= m_flQueueHeadTime - m_flMaxTime) && (flTime <= m_flQueueHeadTime) ); - - // Then retire stale events... - I i = m_Queue.Head(); - while( m_Queue[i].m_flTime > flTime ) - { - i = m_Queue.Next(i); - Assert( i != m_Queue.InvalidIndex() ); - } - - return i; -} - - -//----------------------------------------------------------------------------- -// Gets event information -//----------------------------------------------------------------------------- -template -inline float CTimedEventQueue::GetEventTime( I i ) const -{ - return m_Queue[i].m_flTime; -} - -template -inline const T &CTimedEventQueue::GetEventData( I i ) const -{ - return m_Queue[i].m_Data; -} - - -//----------------------------------------------------------------------------- -// Implementation of the class that computes windspeed -//----------------------------------------------------------------------------- -class CEnvWindShared -{ -public: - DECLARE_CLASS_NOBASE( CEnvWindShared ); - DECLARE_EMBEDDED_NETWORKVAR(); - - CEnvWindShared(); - ~CEnvWindShared(); - - void Init( int iEntIndex, int iRandomSeed, float flTime, int iWindDir, float flInitialWindSpeed ); - - // Method to update the wind speed - // Time passed in here is global time, not delta time - // The function returns the time at which it must be called again - float WindThink( float flTime ); - - // FIXME: These really should be private - CNetworkVar( float, m_flStartTime ); - - CNetworkVar( int, m_iWindSeed ); // random number seed... - - CNetworkVar( int, m_iMinWind ); // the slowest the wind can normally blow - CNetworkVar( int, m_iMaxWind ); // the fastest the wind can normally blow - CNetworkVar( int, m_iMinGust ); // the slowest that a gust can be - CNetworkVar( int, m_iMaxGust ); // the fastest that a gust can be - - CNetworkVar( float, m_flMinGustDelay ); // min time between gusts - CNetworkVar( float, m_flMaxGustDelay ); // max time between gusts - - CNetworkVar( float, m_flGustDuration ); // max time between gusts - - CNetworkVar( int, m_iGustDirChange ); // max number of degrees wind dir changes on gusts. - int m_iszGustSound; // name of the wind sound to play for gusts. - int m_iWindDir; // wind direction (yaw) - float m_flWindSpeed; // the wind speed - - CNetworkVar( int, m_iInitialWindDir ); - CNetworkVar( float, m_flInitialWindSpeed ); - -#ifndef CLIENT_DLL - COutputEvent m_OnGustStart; - COutputEvent m_OnGustEnd; -#endif - -private: - struct WindAveEvent_t - { - float m_flStartWindSpeed; // the wind speed at the time of the event - float m_flAveWindSpeed; // the average wind speed of the event - }; - - struct WindVariationEvent_t - { - float m_flWindAngleVariation; - float m_flWindSpeedVariation; - }; - - void ComputeWindVariation( float flTime ); - - // Updates the wind sound - void UpdateWindSound( float flTotalWindSpeed ); - - float m_flVariationTime; - float m_flSimTime; // What's the time I last simulated up to? - float m_flSwitchTime; // when do I actually switch from gust to not gust - float m_flAveWindSpeed; // the average wind speed - bool m_bGusting; // is the wind gusting right now? - - float m_flWindAngleVariation; - float m_flWindSpeedVariation; - - int m_iEntIndex; - - // Used to generate random numbers - CUniformRandomStream m_Stream; - - // NOTE: In order to make this algorithm independent of calling frequency - // I have to decouple the stream used to generate average wind speed - // and the stream used to generate wind variation since they are - // simulated using different timesteps - CUniformRandomStream m_WindVariationStream; - - // Used to generate the wind sound... - CSoundPatch *m_pWindSound; - - // Event history required for prediction - CTimedEventQueue< WindAveEvent_t, unsigned short > m_WindAveQueue; - CTimedEventQueue< WindVariationEvent_t, unsigned short > m_WindVariationQueue; - -private: - CEnvWindShared( const CEnvWindShared & ); // not defined, not accessible -}; - - -//----------------------------------------------------------------------------- -// Method to sample the windspeed at a particular time -//----------------------------------------------------------------------------- -void GetWindspeedAtTime( float flTime, Vector &vecVelocity ); - - -//----------------------------------------------------------------------------- -// Method to reset windspeed.. -//----------------------------------------------------------------------------- -void ResetWindspeed(); - - -#endif // ENV_WIND_SHARED_H - diff --git a/game/shared/episodic/npc_advisor_shared.h b/game/shared/episodic/npc_advisor_shared.h deleted file mode 100644 index b657be5c0..000000000 --- a/game/shared/episodic/npc_advisor_shared.h +++ /dev/null @@ -1,32 +0,0 @@ -//========= Copyright 1996-2007, Valve Corporation, All rights reserved. ============// -// -// Purpose: Shared data between client and server side npc_advisor classes. -// -// Catchphrase: "It's advising us!!!" -// -//=============================================================================// - -#ifndef NPC_ADVISOR_SHARED_H -#define NPC_ADVISOR_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - - -// Set this to 0 to disable the advisor's special AI behavior (all that object chucking), -// which we did in Ep2 to make him a scripted creature. -#define NPC_ADVISOR_HAS_BEHAVIOR 0 - -#if NPC_ADVISOR_HAS_BEHAVIOR -// Message ID constants used for communciation between client and server. -enum -{ - ADVISOR_MSG_START_BEAM = 10, - ADVISOR_MSG_STOP_BEAM, - ADVISOR_MSG_STOP_ALL_BEAMS, - ADVISOR_MSG_START_ELIGHT, - ADVISOR_MSG_STOP_ELIGHT, -}; -#endif - -#endif // NPC_ADVISOR_SHARED_H diff --git a/game/shared/eventlist.cpp b/game/shared/eventlist.cpp deleted file mode 100644 index 30b63186c..000000000 --- a/game/shared/eventlist.cpp +++ /dev/null @@ -1,250 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" -#include "eventlist.h" -#include "stringregistry.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// NOTE: If CStringRegistry allowed storing arbitrary data, we could just use that. -// in this case we have the "isPrivate" member and the replacement rules -// (eventIndex can be reused by private activities), so a custom table is necessary -struct eventlist_t -{ - int eventIndex; - int iType; - unsigned short stringKey; - short isPrivate; -}; - -CUtlVector g_EventList; - -// This stores the actual event names. Also, the string ID in the registry is simply an index -// into the g_EventList array. -CStringRegistry g_EventStrings; - -// this is just here to accelerate adds -static int g_HighestEvent = 0; - -int g_nEventListVersion = 1; - - -void EventList_Init( void ) -{ - g_HighestEvent = 0; -} - -void EventList_Free( void ) -{ - g_EventStrings.ClearStrings(); - g_EventList.Purge(); - - // So studiohdrs can reindex event indices - ++g_nEventListVersion; -} - -// add a new event to the database -eventlist_t *EventList_AddEventEntry( const char *pName, int iEventIndex, bool isPrivate, int iType ) -{ - MEM_ALLOC_CREDIT(); - int index = g_EventList.AddToTail(); - eventlist_t *pList = &g_EventList[index]; - pList->eventIndex = iEventIndex; - pList->stringKey = g_EventStrings.AddString( pName, index ); - pList->isPrivate = isPrivate; - pList->iType = iType; - - // UNDONE: This implies that ALL shared activities are added before ANY custom activities - // UNDONE: Segment these instead? It's a 32-bit int, how many activities do we need? - if ( iEventIndex > g_HighestEvent ) - { - g_HighestEvent = iEventIndex; - } - - return pList; -} - -// get the database entry from a string -static eventlist_t *ListFromString( const char *pString ) -{ - // just use the string registry to do this search/map - int stringID = g_EventStrings.GetStringID( pString ); - if ( stringID < 0 ) - return NULL; - - return &g_EventList[stringID]; -} - -// Get the database entry for an index -static eventlist_t *ListFromEvent( int eventIndex ) -{ - // ugly linear search - for ( int i = 0; i < g_EventList.Size(); i++ ) - { - if ( g_EventList[i].eventIndex == eventIndex ) - { - return &g_EventList[i]; - } - } - - return NULL; -} - -int EventList_GetEventType( int eventIndex ) -{ - eventlist_t *pEvent = ListFromEvent( eventIndex ); - - if ( pEvent ) - { - return pEvent->iType; - } - - return -1; -} - - -bool EventList_RegisterSharedEvent( const char *pszEventName, int iEventIndex, int iType ) -{ - // UNDONE: Do we want to do these checks when not in developer mode? or maybe DEBUG only? - // They really only matter when you change the list of code controlled activities. IDs - // for content controlled activities never collide because they are generated. - - // first, check to make sure the slot we're asking for is free. It must be for - // a shared event. - eventlist_t *pList = ListFromString( pszEventName ); - if ( !pList ) - { - pList = ListFromEvent( iEventIndex ); - } - - //Already in list. - if ( pList ) - { - return false; - } - // ---------------------------------------------------------------- - - EventList_AddEventEntry( pszEventName, iEventIndex, false, iType ); - return true; -} - -Animevent EventList_RegisterPrivateEvent( const char *pszEventName ) -{ - eventlist_t *pList = ListFromString( pszEventName ); - if ( pList ) - { - // this activity is already in the list. If the activity we collided with is also private, - // then the collision is OK. Otherwise, it's a bug. - if ( pList->isPrivate ) - { - return (Animevent)pList->eventIndex; - } - else - { - // this private activity collides with a shared activity. That is not allowed. - Warning( "***\nShared<->Private Event collision!\n***\n" ); - Assert(0); - return AE_INVALID; - } - } - - pList = EventList_AddEventEntry( pszEventName, g_HighestEvent+1, true, AE_TYPE_SERVER ); - return (Animevent)pList->eventIndex; -} - -// Get the index for a given Event name -// Done at load time for all models -int EventList_IndexForName( const char *pszEventName ) -{ - // this is a fast O(lgn) search (actually does 2 O(lgn) searches) - eventlist_t *pList = ListFromString( pszEventName ); - - if ( pList ) - { - return pList->eventIndex; - } - - return -1; -} - -// Get the name for a given index -// This should only be used in debug code, it does a linear search -// But at least it only compares integers -const char *EventList_NameForIndex( int eventIndex ) -{ - eventlist_t *pList = ListFromEvent( eventIndex ); - if ( pList ) - { - return g_EventStrings.GetStringForKey( pList->stringKey ); - } - return NULL; -} - -void EventList_RegisterSharedEvents( void ) -{ - REGISTER_SHARED_ANIMEVENT( AE_EMPTY, AE_TYPE_SERVER ); - - REGISTER_SHARED_ANIMEVENT( AE_NPC_LEFTFOOT, AE_TYPE_SERVER ); - REGISTER_SHARED_ANIMEVENT( AE_NPC_RIGHTFOOT, AE_TYPE_SERVER ); - REGISTER_SHARED_ANIMEVENT( AE_NPC_BODYDROP_LIGHT, AE_TYPE_SERVER ); - REGISTER_SHARED_ANIMEVENT( AE_NPC_BODYDROP_HEAVY, AE_TYPE_SERVER ); - REGISTER_SHARED_ANIMEVENT( AE_NPC_SWISHSOUND, AE_TYPE_SERVER ); - REGISTER_SHARED_ANIMEVENT( AE_NPC_180TURN, AE_TYPE_SERVER ); - REGISTER_SHARED_ANIMEVENT( AE_NPC_ITEM_PICKUP, AE_TYPE_SERVER ); - REGISTER_SHARED_ANIMEVENT( AE_NPC_WEAPON_DROP, AE_TYPE_SERVER ); - REGISTER_SHARED_ANIMEVENT( AE_NPC_WEAPON_SET_SEQUENCE_NAME, AE_TYPE_SERVER ); - REGISTER_SHARED_ANIMEVENT( AE_NPC_WEAPON_SET_SEQUENCE_NUMBER, AE_TYPE_SERVER ); - REGISTER_SHARED_ANIMEVENT( AE_NPC_WEAPON_SET_ACTIVITY, AE_TYPE_SERVER ); - REGISTER_SHARED_ANIMEVENT( AE_NPC_HOLSTER, AE_TYPE_SERVER ); - REGISTER_SHARED_ANIMEVENT( AE_NPC_DRAW, AE_TYPE_SERVER ); - REGISTER_SHARED_ANIMEVENT( AE_NPC_WEAPON_FIRE, AE_TYPE_SERVER | AE_TYPE_WEAPON ); - - REGISTER_SHARED_ANIMEVENT( AE_CL_PLAYSOUND, AE_TYPE_CLIENT ); - REGISTER_SHARED_ANIMEVENT( AE_SV_PLAYSOUND, AE_TYPE_SERVER ); - REGISTER_SHARED_ANIMEVENT( AE_CL_STOPSOUND, AE_TYPE_CLIENT ); - - REGISTER_SHARED_ANIMEVENT( AE_START_SCRIPTED_EFFECT, AE_TYPE_SERVER ); - REGISTER_SHARED_ANIMEVENT( AE_STOP_SCRIPTED_EFFECT, AE_TYPE_SERVER ); - - REGISTER_SHARED_ANIMEVENT( AE_CLIENT_EFFECT_ATTACH, AE_TYPE_CLIENT ); - - REGISTER_SHARED_ANIMEVENT( AE_MUZZLEFLASH, AE_TYPE_CLIENT ); - REGISTER_SHARED_ANIMEVENT( AE_NPC_MUZZLEFLASH, AE_TYPE_CLIENT ); - - REGISTER_SHARED_ANIMEVENT( AE_THUMPER_THUMP, AE_TYPE_SERVER ); - REGISTER_SHARED_ANIMEVENT( AE_AMMOCRATE_PICKUP_AMMO, AE_TYPE_SERVER ); - - REGISTER_SHARED_ANIMEVENT( AE_NPC_RAGDOLL, AE_TYPE_SERVER ); - - REGISTER_SHARED_ANIMEVENT( AE_NPC_ADDGESTURE, AE_TYPE_SERVER ); - REGISTER_SHARED_ANIMEVENT( AE_NPC_RESTARTGESTURE, AE_TYPE_SERVER ); - - REGISTER_SHARED_ANIMEVENT( AE_NPC_ATTACK_BROADCAST, AE_TYPE_SERVER ); - - REGISTER_SHARED_ANIMEVENT( AE_NPC_HURT_INTERACTION_PARTNER, AE_TYPE_SERVER ); - REGISTER_SHARED_ANIMEVENT( AE_NPC_SET_INTERACTION_CANTDIE, AE_TYPE_SERVER ); - - REGISTER_SHARED_ANIMEVENT( AE_SV_DUSTTRAIL, AE_TYPE_SERVER ); - - REGISTER_SHARED_ANIMEVENT( AE_CL_CREATE_PARTICLE_EFFECT, AE_TYPE_CLIENT ); - - REGISTER_SHARED_ANIMEVENT( AE_RAGDOLL, AE_TYPE_SERVER ); - - REGISTER_SHARED_ANIMEVENT( AE_CL_ENABLE_BODYGROUP, AE_TYPE_CLIENT ); - REGISTER_SHARED_ANIMEVENT( AE_CL_DISABLE_BODYGROUP, AE_TYPE_CLIENT ); - REGISTER_SHARED_ANIMEVENT( AE_CL_BODYGROUP_SET_VALUE, AE_TYPE_CLIENT ); - - REGISTER_SHARED_ANIMEVENT( AE_WPN_PRIMARYATTACK, AE_TYPE_CLIENT | AE_TYPE_SERVER ); - REGISTER_SHARED_ANIMEVENT( AE_WPN_INCREMENTAMMO, AE_TYPE_CLIENT | AE_TYPE_SERVER ); - - REGISTER_SHARED_ANIMEVENT( AE_WPN_HIDE, AE_TYPE_CLIENT | AE_TYPE_SERVER ); - REGISTER_SHARED_ANIMEVENT( AE_WPN_UNHIDE, AE_TYPE_CLIENT | AE_TYPE_SERVER ); - - REGISTER_SHARED_ANIMEVENT( AE_WPN_PLAYWPNSOUND, AE_TYPE_CLIENT | AE_TYPE_SERVER ); -} diff --git a/game/shared/eventlist.h b/game/shared/eventlist.h deleted file mode 100644 index 41fc37fe3..000000000 --- a/game/shared/eventlist.h +++ /dev/null @@ -1,114 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef EVENTLIST_H -#define EVENTLIST_H -#ifdef _WIN32 -#pragma once -#endif - -#define AE_TYPE_SERVER ( 1 << 0 ) -#define AE_TYPE_SCRIPTED ( 1 << 1 ) // see scriptevent.h -#define AE_TYPE_SHARED ( 1 << 2 ) -#define AE_TYPE_WEAPON ( 1 << 3 ) -#define AE_TYPE_CLIENT ( 1 << 4 ) -#define AE_TYPE_FACEPOSER ( 1 << 5 ) - -#define AE_TYPE_NEWEVENTSYSTEM ( 1 << 10 ) //Temporary flag. - -#define AE_NOT_AVAILABLE -1 - -typedef enum -{ - AE_INVALID = -1, // So we have something more succint to check for than '-1' - AE_EMPTY, - AE_NPC_LEFTFOOT, // #define NPC_EVENT_LEFTFOOT 2050 - AE_NPC_RIGHTFOOT, // #define NPC_EVENT_RIGHTFOOT 2051 - AE_NPC_BODYDROP_LIGHT, //#define NPC_EVENT_BODYDROP_LIGHT 2001 - AE_NPC_BODYDROP_HEAVY, //#define NPC_EVENT_BODYDROP_HEAVY 2002 - AE_NPC_SWISHSOUND, //#define NPC_EVENT_SWISHSOUND 2010 - AE_NPC_180TURN, //#define NPC_EVENT_180TURN 2020 - AE_NPC_ITEM_PICKUP, //#define NPC_EVENT_ITEM_PICKUP 2040 - AE_NPC_WEAPON_DROP, //#define NPC_EVENT_WEAPON_DROP 2041 - AE_NPC_WEAPON_SET_SEQUENCE_NAME, //#define NPC_EVENT_WEAPON_SET_SEQUENCE_NAME 2042 - AE_NPC_WEAPON_SET_SEQUENCE_NUMBER, //#define NPC_EVENT_WEAPON_SET_SEQUENCE_NUMBER 2043 - AE_NPC_WEAPON_SET_ACTIVITY, //#define NPC_EVENT_WEAPON_SET_ACTIVITY 2044 - AE_NPC_HOLSTER, - AE_NPC_DRAW, - AE_NPC_WEAPON_FIRE, - - AE_CL_PLAYSOUND, // #define CL_EVENT_SOUND 5004 // Emit a sound - AE_SV_PLAYSOUND, - AE_CL_STOPSOUND, - - AE_START_SCRIPTED_EFFECT, - AE_STOP_SCRIPTED_EFFECT, - - AE_CLIENT_EFFECT_ATTACH, - - AE_MUZZLEFLASH, // Muzzle flash from weapons held by the player - AE_NPC_MUZZLEFLASH, // Muzzle flash from weapons held by NPCs - - AE_THUMPER_THUMP, //Thumper Thump! - AE_AMMOCRATE_PICKUP_AMMO, //Ammo crate pick up ammo! - - AE_NPC_RAGDOLL, - - AE_NPC_ADDGESTURE, - AE_NPC_RESTARTGESTURE, - - AE_NPC_ATTACK_BROADCAST, - - AE_NPC_HURT_INTERACTION_PARTNER, - AE_NPC_SET_INTERACTION_CANTDIE, - - AE_SV_DUSTTRAIL, - - AE_CL_CREATE_PARTICLE_EFFECT, - - AE_RAGDOLL, - - AE_CL_ENABLE_BODYGROUP, - AE_CL_DISABLE_BODYGROUP, - AE_CL_BODYGROUP_SET_VALUE, - - AE_WPN_PRIMARYATTACK, // Used by weapons that want their primary attack to occur during an attack anim (i.e. grenade throwing) - AE_WPN_INCREMENTAMMO, - - AE_WPN_HIDE, // Used to hide player weapons - AE_WPN_UNHIDE, // Used to unhide player weapons - - AE_WPN_PLAYWPNSOUND, // Play a weapon sound from the weapon script file - - LAST_SHARED_ANIMEVENT, -} Animevent; - - -typedef struct evententry_s evententry_t; - -//========================================================= -//========================================================= -extern void EventList_Init( void ); -extern void EventList_Free( void ); -extern bool EventList_RegisterSharedEvent( const char *pszEventName, int iEventIndex, int iType = 0 ); -extern Animevent EventList_RegisterPrivateEvent( const char *pszEventName ); -extern int EventList_IndexForName( const char *pszEventName ); -extern const char *EventList_NameForIndex( int iEventIndex ); -Animevent EventList_RegisterPrivateEvent( const char *pszEventName ); - -// This macro guarantees that the names of each event and the constant used to -// reference it in the code are identical. -#define REGISTER_SHARED_ANIMEVENT( _n, b ) EventList_RegisterSharedEvent(#_n, _n, b ); -#define REGISTER_PRIVATE_ANIMEVENT( _n ) _n = EventList_RegisterPrivateEvent( #_n ); - -// Implemented in shared code -extern void EventList_RegisterSharedEvents( void ); -extern int EventList_GetEventType( int eventIndex ); - - - -#endif // EVENTLIST_H diff --git a/game/shared/expressionsample.h b/game/shared/expressionsample.h deleted file mode 100644 index 746da5e89..000000000 --- a/game/shared/expressionsample.h +++ /dev/null @@ -1,141 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef EXPRESSIONSAMPLE_H -#define EXPRESSIONSAMPLE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "interpolatortypes.h" - -class CUtlBuffer; -class ISceneTokenProcessor; -class IChoreoStringPool; - -#pragma pack(1) -struct EdgeInfo_t -{ - EdgeInfo_t() : - m_bActive( false ), - m_CurveType( CURVE_DEFAULT ), - m_flZeroPos( 0.0f ) - { - } - - bool m_bActive; - unsigned short m_CurveType; - float m_flZeroPos; -}; - -struct CExpressionSample -{ - CExpressionSample() : - value( 0.0f ), - time( 0.0f ) - { - selected = 0; - m_curvetype = CURVE_DEFAULT; - } - - void SetCurveType( int curveType ) - { - m_curvetype = curveType; - } - - int GetCurveType() const - { - return m_curvetype; - } - - // Height - float value; - // time from start of event - float time; - - unsigned short selected : 1; -private: - unsigned short m_curvetype : 15; -}; -#pragma pack() - -//----------------------------------------------------------------------------- -// Purpose: Provides generic access to scene or event ramp data -//----------------------------------------------------------------------------- -class ICurveDataAccessor -{ -public: - virtual float GetDuration() = 0; - virtual bool CurveHasEndTime() = 0; // only matters for events - virtual int GetDefaultCurveType() = 0; -}; - -//----------------------------------------------------------------------------- -// Purpose: The generic curve data -//----------------------------------------------------------------------------- - -class CCurveData -{ -public: - int GetCount( void ); - CExpressionSample *Get( int index ); - CExpressionSample *Add( float time, float value, bool selected ); - void Delete( int index ); - void Clear( void ); - void Resort( ICurveDataAccessor *data ); - - EdgeInfo_t *GetEdgeInfo( int idx ); - - void SetEdgeInfo( bool leftEdge, int curveType, float zero ); - void GetEdgeInfo( bool leftEdge, int& curveType, float& zero ) const; - void SetEdgeActive( bool leftEdge, bool state ); - bool IsEdgeActive( bool leftEdge ) const; - int GetEdgeCurveType( bool leftEdge ) const; - float GetEdgeZeroValue( bool leftEdge ) const; - void RemoveOutOfRangeSamples( ICurveDataAccessor *data ); - - void SaveToBuffer( CUtlBuffer& buf, IChoreoStringPool *pStringPool ); - bool RestoreFromBuffer( CUtlBuffer& buf, IChoreoStringPool *pStringPool ); - - void Parse( ISceneTokenProcessor *tokenizer, ICurveDataAccessor *data ); - void FileSave( CUtlBuffer& buf, int level, const char *name ); - - float GetIntensity( ICurveDataAccessor *data, float time ); - CExpressionSample *GetBoundedSample( ICurveDataAccessor *data, int number, bool& bClamped ); - - CCurveData & operator = (const CCurveData &src) - { - // Copy ramp over - m_Ramp.RemoveAll(); - int i; - for ( i = 0; i < src.m_Ramp.Count(); i++ ) - { - CExpressionSample sample = src.m_Ramp[ i ]; - CExpressionSample *newSample = Add( sample.time, sample.value, sample.selected ); - newSample->SetCurveType( sample.GetCurveType() ); - } - m_RampEdgeInfo[ 0 ] = src.m_RampEdgeInfo[ 0 ]; - m_RampEdgeInfo[ 1 ] = src.m_RampEdgeInfo[ 1 ]; - - return *this; - - }; - -private: - CUtlVector< CExpressionSample > m_Ramp; - EdgeInfo_t m_RampEdgeInfo[ 2 ]; - -public: - float GetIntensityArea( ICurveDataAccessor *data, float time ); - -private: - void UpdateIntensityArea( ICurveDataAccessor *data ); - CUtlVector< float > m_RampAccumulator; -}; - - -#endif // EXPRESSIONSAMPLE_H diff --git a/game/shared/forcefeedback.h b/game/shared/forcefeedback.h deleted file mode 100644 index 8a2e3807a..000000000 --- a/game/shared/forcefeedback.h +++ /dev/null @@ -1,71 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef FORCEFEEDBACK_H -#define FORCEFEEDBACK_H -#ifdef _WIN32 -#pragma once -#endif - -enum -{ - FFMSG_START = 0, - FFMSG_STOP, - FFMSG_STOPALL, - FFMSG_PAUSE, - FFMSG_RESUME -}; - -typedef enum -{ - FORCE_FEEDBACK_SHOT_SINGLE, - FORCE_FEEDBACK_SHOT_DOUBLE, - - FORCE_FEEDBACK_TAKEDAMAGE, - - FORCE_FEEDBACK_SCREENSHAKE, - - FORCE_FEEDBACK_SKIDDING, - FORCE_FEEDBACK_BREAKING, - - NUM_FORCE_FEEDBACK_PRESETS -} FORCEFEEDBACK_t; - -class CBasePlayer; - -struct FFBaseParams_t -{ - FFBaseParams_t() : - m_flDirection( 0.0f ), - m_flDuration( 0.0f ), - m_flGain( 1.0f ), - m_nPriority( 0 ), - m_bSolo( false ) - { - } - - float m_flDirection; // yaw - float m_flDuration; // seconds (-1 == INFINITE, 0.0 == use duration from .ffe file) - float m_flGain; // 0 -> 1 global scale - int m_nPriority; // Higher is more important - bool m_bSolo; // Temporarily suppress all other FF effects while playing -}; - -abstract_class IForceFeedback -{ -public: - // API - virtual void StopAllEffects( CBasePlayer *player ) = 0; - virtual void StopEffect( CBasePlayer *player, FORCEFEEDBACK_t effect ) = 0; - virtual void StartEffect( CBasePlayer *player, FORCEFEEDBACK_t effect, const FFBaseParams_t& params ) = 0; - - virtual void PauseAll( CBasePlayer *player ) = 0; - virtual void ResumeAll( CBasePlayer *player ) = 0; -}; - -extern IForceFeedback *forcefeedback; - -#endif // FORCEFEEDBACK_H diff --git a/game/shared/func_dust_shared.h b/game/shared/func_dust_shared.h deleted file mode 100644 index 0f1241910..000000000 --- a/game/shared/func_dust_shared.h +++ /dev/null @@ -1,22 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef FUNC_DUST_SHARED_H -#define FUNC_DUST_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - - -// Flags for m_DustFlags. -#define DUSTFLAGS_ON (1<<0) // emit particles.. -#define DUSTFLAGS_SCALEMOTES (1<<1) // scale to keep the same size on screen -#define DUSTFLAGS_FROZEN (1<<2) // just emit m_SpawnRate # of particles and freeze -#define DUST_NUMFLAGS 3 - - -#endif // FUNC_DUST_SHARED_H diff --git a/game/shared/func_ladder.cpp b/game/shared/func_ladder.cpp deleted file mode 100644 index 84fb46598..000000000 --- a/game/shared/func_ladder.cpp +++ /dev/null @@ -1,513 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// -#include "cbase.h" -#include "func_ladder.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#if !defined( CLIENT_DLL ) -static ConVar sv_showladders( "sv_showladders", "0", 0, "Show bbox and dismount points for all ladders (must be set before level load.)\n" ); -#endif - -CUtlVector< CFuncLadder * > CFuncLadder::s_Ladders; -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CFuncLadder::CFuncLadder() : - m_bDisabled( false ) -{ - s_Ladders.AddToTail( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CFuncLadder::~CFuncLadder() -{ - s_Ladders.FindAndRemove( this ); -} - -int CFuncLadder::GetLadderCount() -{ - return s_Ladders.Count(); -} - -CFuncLadder *CFuncLadder::GetLadder( int index ) -{ - if ( index < 0 || index >= s_Ladders.Count() ) - return NULL; - - return s_Ladders[ index ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncLadder::Spawn() -{ - BaseClass::Spawn(); - - // Entity is symbolid - SetSolid( SOLID_NONE ); - SetMoveType( MOVETYPE_NONE ); - SetCollisionGroup( COLLISION_GROUP_NONE ); - - //AddFlag( FL_WORLDBRUSH ); - SetModelName( NULL_STRING ); - - // Make entity invisible - AddEffects( EF_NODRAW ); - // No model but should still network - AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); - - Vector playerMins = VEC_HULL_MIN; - Vector playerMaxs = VEC_HULL_MAX; - - // This will swap them if they are inverted - SetEndPoints( m_vecPlayerMountPositionTop, m_vecPlayerMountPositionBottom ); - -#if !defined( CLIENT_DLL ) - trace_t bottomtrace, toptrace; - UTIL_TraceHull( m_vecPlayerMountPositionBottom, m_vecPlayerMountPositionBottom, - playerMins, playerMaxs, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_PLAYER_MOVEMENT, &bottomtrace ); - UTIL_TraceHull( m_vecPlayerMountPositionTop, m_vecPlayerMountPositionTop, - playerMins, playerMaxs, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_PLAYER_MOVEMENT, &toptrace ); - - if ( bottomtrace.startsolid || toptrace.startsolid ) - { - if ( bottomtrace.startsolid ) - { - DevMsg( 1, "Warning, funcladder with blocked bottom point (%.2f %.2f %.2f) stuck in (%s)\n", - m_vecPlayerMountPositionBottom.GetX(), - m_vecPlayerMountPositionBottom.GetY(), - m_vecPlayerMountPositionBottom.GetZ(), - bottomtrace.m_pEnt - ? - UTIL_VarArgs( "%s/%s", bottomtrace.m_pEnt->GetClassname(), bottomtrace.m_pEnt->GetEntityName().ToCStr() ) - : - "NULL" ); - } - if ( toptrace.startsolid ) - { - DevMsg( 1, "Warning, funcladder with blocked top point (%.2f %.2f %.2f) stuck in (%s)\n", - m_vecPlayerMountPositionTop.GetX(), - m_vecPlayerMountPositionTop.GetY(), - m_vecPlayerMountPositionTop.GetZ(), - toptrace.m_pEnt - ? - UTIL_VarArgs( "%s/%s", toptrace.m_pEnt->GetClassname(), toptrace.m_pEnt->GetEntityName().ToCStr() ) - : - "NULL" ); - } - - // Force geometry overlays on, but only if developer 2 is set... - if ( developer.GetInt() > 1 ) - { - m_debugOverlays |= OVERLAY_TEXT_BIT; - } - } - - m_vecPlayerMountPositionTop -= GetAbsOrigin(); - m_vecPlayerMountPositionBottom -= GetAbsOrigin(); - - // Compute mins, maxs of points - // - Vector mins( MAX_COORD_INTEGER, MAX_COORD_INTEGER, MAX_COORD_INTEGER ); - Vector maxs( -MAX_COORD_INTEGER, -MAX_COORD_INTEGER, -MAX_COORD_INTEGER ); - int i; - for ( i = 0; i < 3; i++ ) - { - if ( m_vecPlayerMountPositionBottom.m_Value[ i ] < mins[ i ] ) - { - mins[ i ] = m_vecPlayerMountPositionBottom.m_Value[ i ]; - } - if ( m_vecPlayerMountPositionBottom.m_Value[ i ] > maxs[ i ] ) - { - maxs[ i ] = m_vecPlayerMountPositionBottom.m_Value[ i ]; - } - if ( m_vecPlayerMountPositionTop.m_Value[ i ] < mins[ i ] ) - { - mins[ i ] = m_vecPlayerMountPositionTop.m_Value[ i ]; - } - if ( m_vecPlayerMountPositionTop.m_Value[ i ] > maxs[ i ] ) - { - maxs[ i ] = m_vecPlayerMountPositionTop.m_Value[ i ]; - } - } - - // Expand mins/maxs by player hull size - mins += playerMins; - maxs += playerMaxs; - - UTIL_SetSize( this, mins, maxs ); - - m_bFakeLadder = HasSpawnFlags(SF_LADDER_DONTGETON); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Called after all entities have spawned or after reload from .sav file -//----------------------------------------------------------------------------- -void CFuncLadder::Activate() -{ - // Chain to base class - BaseClass::Activate(); - -#if !defined( CLIENT_DLL ) - // Re-hook up ladder dismount points - SearchForDismountPoints(); - - // Show debugging UI if it's active - if ( sv_showladders.GetBool() ) - { - m_debugOverlays |= OVERLAY_TEXT_BIT; - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncLadder::SearchForDismountPoints() -{ -#if !defined( CLIENT_DLL ) - CUtlVector< CInfoLadderDismountHandle > allNodes; - - Vector topPos; - Vector bottomPos; - - GetTopPosition( topPos ); - GetBottomPosition( bottomPos ); - - float dismount_radius = 100.0f; - - Vector vecBottomToTop = topPos - bottomPos; - float ladderLength = VectorNormalize( vecBottomToTop ); - - float recheck = 40.0f; - - // add both sets of nodes - FindNearbyDismountPoints( topPos, dismount_radius, m_Dismounts ); - FindNearbyDismountPoints( bottomPos, dismount_radius, m_Dismounts ); - - while ( 1 ) - { - ladderLength -= recheck; - if ( ladderLength <= 0.0f ) - break; - bottomPos += recheck * vecBottomToTop; - FindNearbyDismountPoints( bottomPos, dismount_radius, m_Dismounts ); - } -#endif -} - -void CFuncLadder::SetEndPoints( const Vector& p1, const Vector& p2 ) -{ - m_vecPlayerMountPositionTop = p1; - m_vecPlayerMountPositionBottom = p2; - - if ( m_vecPlayerMountPositionBottom.GetZ() > m_vecPlayerMountPositionTop.GetZ() ) - { - Vector temp = m_vecPlayerMountPositionBottom; - m_vecPlayerMountPositionBottom = m_vecPlayerMountPositionTop; - m_vecPlayerMountPositionTop = temp; - } - -#if !defined( CLIENT_DLL) - Vector playerMins = VEC_HULL_MIN; - Vector playerMaxs = VEC_HULL_MAX; - - trace_t result; - UTIL_TraceHull( m_vecPlayerMountPositionTop + Vector( 0, 0, 4 ), m_vecPlayerMountPositionTop, - playerMins, playerMaxs, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_PLAYER_MOVEMENT, &result ); - - if ( !result.startsolid ) - { - m_vecPlayerMountPositionTop = result.endpos; - } - - UTIL_TraceHull( m_vecPlayerMountPositionBottom + Vector( 0, 0, 4 ), m_vecPlayerMountPositionBottom, - playerMins, playerMaxs, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_PLAYER_MOVEMENT, &result ); - - if ( !result.startsolid ) - { - m_vecPlayerMountPositionBottom = result.endpos; - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CFuncLadder::DrawDebugGeometryOverlays() -{ -#if !defined( CLIENT_DLL ) - - BaseClass::DrawDebugGeometryOverlays(); - - Vector playerMins = VEC_HULL_MIN; - Vector playerMaxs = VEC_HULL_MAX; - - Vector topPosition; - Vector bottomPosition; - - GetTopPosition( topPosition ); - GetBottomPosition( bottomPosition ); - - NDebugOverlay::Box( topPosition, playerMins, playerMaxs, 255,0,0,127, 0 ); - NDebugOverlay::Box( bottomPosition, playerMins, playerMaxs, 0,0,255,127, 0 ); - - NDebugOverlay::EntityBounds(this, 200, 180, 63, 63, 0); - - trace_t bottomtrace; - UTIL_TraceHull( m_vecPlayerMountPositionBottom, m_vecPlayerMountPositionBottom, - playerMins, playerMaxs, MASK_PLAYERSOLID_BRUSHONLY, NULL, COLLISION_GROUP_PLAYER_MOVEMENT, &bottomtrace ); - - int c = m_Dismounts.Count(); - for ( int i = 0 ; i < c ; i++ ) - { - CInfoLadderDismount *pt = m_Dismounts[ i ]; - if ( !pt ) - continue; - - NDebugOverlay::Box(pt->GetAbsOrigin(),Vector( -16, -16, 0 ), Vector( 16, 16, 8 ), 150,0,0, 63, 0); - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : org - -//----------------------------------------------------------------------------- -void CFuncLadder::GetTopPosition( Vector& org ) -{ - ComputeAbsPosition( m_vecPlayerMountPositionTop + GetLocalOrigin(), &org ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : org - -//----------------------------------------------------------------------------- -void CFuncLadder::GetBottomPosition( Vector& org ) -{ - ComputeAbsPosition( m_vecPlayerMountPositionBottom + GetLocalOrigin(), &org ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : bottomToTopVec - -//----------------------------------------------------------------------------- -void CFuncLadder::ComputeLadderDir( Vector& bottomToTopVec ) -{ - Vector top; - Vector bottom; - - GetTopPosition( top ); - GetBottomPosition( bottom ); - - bottomToTopVec = top - bottom; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CFuncLadder::GetDismountCount() const -{ - return m_Dismounts.Count(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -// Output : CInfoLadderDismountHandle -//----------------------------------------------------------------------------- -CInfoLadderDismount *CFuncLadder::GetDismount( int index ) -{ - if ( index < 0 || index >= m_Dismounts.Count() ) - return NULL; - return m_Dismounts[ index ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : origin - -// radius - -// list - -//----------------------------------------------------------------------------- -void CFuncLadder::FindNearbyDismountPoints( const Vector& origin, float radius, CUtlVector< CInfoLadderDismountHandle >& list ) -{ -#if !defined( CLIENT_DLL ) - CBaseEntity *pEntity = NULL; - while ( (pEntity = gEntList.FindEntityByClassnameWithin( pEntity, "info_ladder_dismount", origin, radius)) != NULL ) - { - CInfoLadderDismount *landingspot = static_cast< CInfoLadderDismount * >( pEntity ); - Assert( landingspot ); - - // If spot has a target, then if the target is not this ladder, don't add to our list. - if ( landingspot->m_target != NULL_STRING ) - { - if ( landingspot->GetNextTarget() != this ) - { - continue; - } - } - - CInfoLadderDismountHandle handle; - handle = landingspot; - if ( list.Find( handle ) == list.InvalidIndex() ) - { - list.AddToTail( handle ); - } - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CFuncLadder::InputEnable( inputdata_t &inputdata ) -{ - m_bDisabled = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &inputdata - -//----------------------------------------------------------------------------- -void CFuncLadder::InputDisable( inputdata_t &inputdata ) -{ - m_bDisabled = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -//----------------------------------------------------------------------------- -void CFuncLadder::PlayerGotOn( CBasePlayer *pPlayer ) -{ -#if !defined( CLIENT_DLL ) - m_OnPlayerGotOnLadder.FireOutput(this, pPlayer); - pPlayer->EmitSound( "Ladder.StepRight" ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -//----------------------------------------------------------------------------- -void CFuncLadder::PlayerGotOff( CBasePlayer *pPlayer ) -{ -#if !defined( CLIENT_DLL ) - m_OnPlayerGotOffLadder.FireOutput(this, pPlayer); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CFuncLadder::DontGetOnLadder( void ) const -{ - return m_bFakeLadder; -} - -#if !defined(CLIENT_DLL) -const char *CFuncLadder::GetSurfacePropName() -{ - if ( !m_surfacePropName ) - return NULL; - return m_surfacePropName.ToCStr(); -} -#endif - -IMPLEMENT_NETWORKCLASS_ALIASED( FuncLadder, DT_FuncLadder ); - -BEGIN_NETWORK_TABLE( CFuncLadder, DT_FuncLadder ) -#if !defined( CLIENT_DLL ) - SendPropVector( SENDINFO( m_vecPlayerMountPositionTop ), SPROP_COORD ), - SendPropVector( SENDINFO( m_vecPlayerMountPositionBottom ), SPROP_COORD ), - SendPropVector( SENDINFO( m_vecLadderDir ), SPROP_COORD ), - SendPropBool( SENDINFO( m_bFakeLadder ) ), -// SendPropStringT( SENDINFO(m_surfacePropName) ), -#else - RecvPropVector( RECVINFO( m_vecPlayerMountPositionTop ) ), - RecvPropVector( RECVINFO( m_vecPlayerMountPositionBottom )), - RecvPropVector( RECVINFO( m_vecLadderDir )), - RecvPropBool( RECVINFO( m_bFakeLadder ) ), -#endif -END_NETWORK_TABLE() - -LINK_ENTITY_TO_CLASS( func_useableladder, CFuncLadder ); - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CFuncLadder ) - DEFINE_KEYFIELD( m_vecPlayerMountPositionTop, FIELD_VECTOR, "point0" ), - DEFINE_KEYFIELD( m_vecPlayerMountPositionBottom, FIELD_VECTOR, "point1" ), - - DEFINE_FIELD( m_vecLadderDir, FIELD_VECTOR ), - // DEFINE_FIELD( m_Dismounts, FIELD_UTLVECTOR ), - - DEFINE_FIELD( m_bFakeLadder, FIELD_BOOLEAN ), - DEFINE_KEYFIELD( m_bDisabled, FIELD_BOOLEAN, "StartDisabled" ), - -#if !defined( CLIENT_DLL ) - DEFINE_KEYFIELD( m_surfacePropName,FIELD_STRING, "ladderSurfaceProperties" ), - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - - DEFINE_OUTPUT( m_OnPlayerGotOnLadder, "OnPlayerGotOnLadder" ), - DEFINE_OUTPUT( m_OnPlayerGotOffLadder, "OnPlayerGotOffLadder" ), -#endif - -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CInfoLadderDismount::DrawDebugGeometryOverlays() -{ -#if !defined( CLIENT_DLL ) - BaseClass::DrawDebugGeometryOverlays(); - - if ( developer.GetBool() ) - { - NDebugOverlay::Box( GetAbsOrigin(), Vector( -16, -16, 0 ), Vector( 16, 16, 8 ), 127, 127, 127, 127, 0 ); - } -#endif -} - -#if defined( GAME_DLL ) -int CFuncLadder::UpdateTransmitState() -{ - // transmit if in PVS for clientside prediction - return SetTransmitState( FL_EDICT_PVSCHECK ); -} -#endif - -IMPLEMENT_NETWORKCLASS_ALIASED( InfoLadderDismount, DT_InfoLadderDismount ); - -BEGIN_NETWORK_TABLE( CInfoLadderDismount, DT_InfoLadderDismount ) -END_NETWORK_TABLE() - -LINK_ENTITY_TO_CLASS( info_ladder_dismount, CInfoLadderDismount ); - -#if defined(GAME_DLL) -const char *FuncLadder_GetSurfaceprops(CBaseEntity *pLadderEntity) -{ - CFuncLadder *pLadder = dynamic_cast(pLadderEntity); - if ( pLadder ) - { - if ( pLadder->GetSurfacePropName() ) - return pLadder->GetSurfacePropName(); - } - return "ladder"; -} -#endif diff --git a/game/shared/func_ladder.h b/game/shared/func_ladder.h deleted file mode 100644 index dbb7df8e6..000000000 --- a/game/shared/func_ladder.h +++ /dev/null @@ -1,116 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef FUNC_LADDER_H -#define FUNC_LADDER_H -#ifdef _WIN32 -#pragma once -#endif - -#if defined( CLIENT_DLL ) -#define CFuncLadder C_FuncLadder -#define CInfoLadderDismount C_InfoLadderDismount -#endif - -class CInfoLadderDismount : public CBaseEntity -{ -public: - DECLARE_CLASS( CInfoLadderDismount, CBaseEntity ); - DECLARE_NETWORKCLASS(); - - virtual void DrawDebugGeometryOverlays(); -}; - -typedef CHandle< CInfoLadderDismount > CInfoLadderDismountHandle; - -// Spawnflags -#define SF_LADDER_DONTGETON 1 // Set for ladders that are acting as automount points, but not really ladders - -//----------------------------------------------------------------------------- -// Purpose: A player-climbable ladder -//----------------------------------------------------------------------------- -class CFuncLadder : public CBaseEntity -{ -public: - - DECLARE_CLASS( CFuncLadder, CBaseEntity ); - DECLARE_NETWORKCLASS(); - DECLARE_DATADESC(); - - CFuncLadder(); - ~CFuncLadder(); - - virtual void Spawn(); - - virtual void DrawDebugGeometryOverlays(void); - - int GetDismountCount() const; - CInfoLadderDismount *GetDismount( int index ); - - void GetTopPosition( Vector& org ); - void GetBottomPosition( Vector& org ); - void ComputeLadderDir( Vector& bottomToTopVec ); - - void SetEndPoints( const Vector& p1, const Vector& p2 ); - - void InputEnable( inputdata_t &inputdata ); - void InputDisable( inputdata_t &inputdata ); - - bool IsEnabled() const; - - void PlayerGotOn( CBasePlayer *pPlayer ); - void PlayerGotOff( CBasePlayer *pPlayer ); - - virtual void Activate(); - - bool DontGetOnLadder( void ) const; - - static int GetLadderCount(); - static CFuncLadder *GetLadder( int index ); - static CUtlVector< CFuncLadder * > s_Ladders; -public: - - void FindNearbyDismountPoints( const Vector& origin, float radius, CUtlVector< CInfoLadderDismountHandle >& list ); - const char *GetSurfacePropName(); - -private: - - - void SearchForDismountPoints(); - - // Movement vector from "bottom" to "top" of ladder - CNetworkVector( m_vecLadderDir ); - - // Dismount points near top/bottom of ladder, precomputed - CUtlVector< CInfoLadderDismountHandle > m_Dismounts; - - // Endpoints for checking for mount/dismount - CNetworkVector( m_vecPlayerMountPositionTop ); - CNetworkVector( m_vecPlayerMountPositionBottom ); - - bool m_bDisabled; - CNetworkVar( bool, m_bFakeLadder ); - -#if defined( GAME_DLL ) - string_t m_surfacePropName; - //----------------------------------------------------- - // Outputs - //----------------------------------------------------- - COutputEvent m_OnPlayerGotOnLadder; - COutputEvent m_OnPlayerGotOffLadder; - - virtual int UpdateTransmitState(); -#endif -}; - -inline bool CFuncLadder::IsEnabled() const -{ - return !m_bDisabled; -} - -const char *FuncLadder_GetSurfaceprops(CBaseEntity *pLadderEntity); - -#endif // FUNC_LADDER_H diff --git a/game/shared/gameeventdefs.h b/game/shared/gameeventdefs.h deleted file mode 100644 index 620e0d965..000000000 --- a/game/shared/gameeventdefs.h +++ /dev/null @@ -1,21 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef GAMEEVENTDEFS_H -#define GAMEEVENTDEFS_H - -#ifdef _WIN32 -#pragma once -#endif - -// Make sure your gameevents.res and this file is in sync -// Event names may be 32 characters long and are case sensitive -// 256 is the maximum number of game events - -#define GAME_EVENT_PLAYER_DEATH "player_death" -#define GAME_EVENT_SAY_TEXT "say_text" - -#endif // GAMEEVENTDEFS_H diff --git a/game/shared/gamemovement.cpp b/game/shared/gamemovement.cpp deleted file mode 100644 index dbee48308..000000000 --- a/game/shared/gamemovement.cpp +++ /dev/null @@ -1,4751 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "gamemovement.h" -#include "in_buttons.h" -#include -#include "movevars_shared.h" -#include "engine/IEngineTrace.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" -#include "decals.h" -#include "coordsize.h" -#include "rumble_shared.h" - -#if defined(HL2_DLL) || defined(HL2_CLIENT_DLL) - #include "hl_movedata.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define STOP_EPSILON 0.1 -#define MAX_CLIP_PLANES 5 - -#include "filesystem.h" -#include - -extern IFileSystem *filesystem; - -#ifndef CLIENT_DLL - #include "env_player_surface_trigger.h" - static ConVar dispcoll_drawplane( "dispcoll_drawplane", "0" ); -#endif - - -// tickcount currently isn't set during prediction, although gpGlobals->curtime and -// gpGlobals->frametime are. We should probably set tickcount (to player->m_nTickBase), -// but we're REALLY close to shipping, so we can change that later and people can use -// player->CurrentCommandNumber() in the meantime. -#define tickcount USE_PLAYER_CURRENT_COMMAND_NUMBER__INSTEAD_OF_TICKCOUNT - -#if defined( HL2_DLL ) -ConVar xc_uncrouch_on_jump( "xc_uncrouch_on_jump", "1", FCVAR_ARCHIVE, "Uncrouch when jump occurs" ); -#endif - -#if defined( HL2_DLL ) || defined( HL2_CLIENT_DLL ) -ConVar player_limit_jump_speed( "player_limit_jump_speed", "1", FCVAR_REPLICATED ); -#endif - -// option_duck_method is a carrier convar. Its sole purpose is to serve an easy-to-flip -// convar which is ONLY set by the X360 controller menu to tell us which way to bind the -// duck controls. Its value is meaningless anytime we don't have the options window open. -ConVar option_duck_method("option_duck_method", "1", FCVAR_REPLICATED|FCVAR_ARCHIVE );// 0 = HOLD to duck, 1 = Duck is a toggle - -// [MD] I'll remove this eventually. For now, I want the ability to A/B the optimizations. -bool g_bMovementOptimizations = true; - -// Roughly how often we want to update the info about the ground surface we're on. -// We don't need to do this very often. -#define CATEGORIZE_GROUND_SURFACE_INTERVAL 0.3f -#define CATEGORIZE_GROUND_SURFACE_TICK_INTERVAL ( (int)( CATEGORIZE_GROUND_SURFACE_INTERVAL / TICK_INTERVAL ) ) - -#define CHECK_STUCK_INTERVAL 1.0f -#define CHECK_STUCK_TICK_INTERVAL ( (int)( CHECK_STUCK_INTERVAL / TICK_INTERVAL ) ) - -#define CHECK_STUCK_INTERVAL_SP 0.2f -#define CHECK_STUCK_TICK_INTERVAL_SP ( (int)( CHECK_STUCK_INTERVAL_SP / TICK_INTERVAL ) ) - -#define CHECK_LADDER_INTERVAL 0.2f -#define CHECK_LADDER_TICK_INTERVAL ( (int)( CHECK_LADDER_INTERVAL / TICK_INTERVAL ) ) - -#define NUM_CROUCH_HINTS 3 - -extern IGameMovement *g_pGameMovement; - -#if defined( PLAYER_GETTING_STUCK_TESTING ) - -// If you ever get stuck walking around, then you can run this code to find the code which would leave the player in a bad spot -void CMoveData::SetAbsOrigin( const Vector &vec ) -{ - CGameMovement *gm = dynamic_cast< CGameMovement * >( g_pGameMovement ); - if ( gm && gm->GetMoveData() && - gm->player && - gm->player->entindex() == 1 && - gm->player->GetMoveType() == MOVETYPE_WALK ) - { - trace_t pm; - gm->TracePlayerBBox( vec, vec, gm->PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, pm ); - if ( pm.startsolid || pm.allsolid || pm.fraction != 1.0f ) - { - Msg( "Player will become stuck at %f %f %f\n", VectorExpand( vec ) ); - } - } - - m_vecAbsOrigin = vec; -} - -#endif - -// See shareddefs.h -#if PREDICTION_ERROR_CHECK_LEVEL > 0 - -static ConVar diffcheck( "diffcheck", "0", FCVAR_REPLICATED ); - -class IDiffMgr -{ -public: - virtual void StartCommand( bool bServer, int nCommandNumber ) = 0; - virtual void AddToDiff( bool bServer, int nCommandNumber, char const *string ) = 0; - virtual void Validate( bool bServer, int nCommandNumber ) = 0; -}; - -static IDiffMgr *g_pDiffMgr = NULL; - -class CDiffStr -{ -public: - CDiffStr() - { - m_str[ 0 ] = 0; - } - - CDiffStr( char const *str ) - { - Q_strncpy( m_str, str, sizeof( m_str ) ); - } - - CDiffStr( const CDiffStr &src ) - { - Q_strncpy( m_str, src.m_str, sizeof( m_str ) ); - } - - char const *String() - { - return m_str; - } -private: - - char m_str[ 128 ]; -}; - -// Per tick data -class CDiffInfo -{ -public: - CDiffInfo() : m_nCommandNumber( 0 ) {} - CDiffInfo( const CDiffInfo& src ) - { - m_nCommandNumber = src.m_nCommandNumber; - for ( int i = 0; i < src.m_Lines.Count(); ++i ) - { - m_Lines.AddToTail( src.m_Lines[ i ] ); - } - } - - static bool Less( const CDiffInfo& lhs, const CDiffInfo& rhs ) - { - return lhs.m_nCommandNumber < rhs.m_nCommandNumber; - } - int m_nCommandNumber; - CUtlVector< CDiffStr > m_Lines; - bool m_bChecked; -}; - -class CDiffManager : public IDiffMgr -{ -public: - CDiffManager() : - m_Client( 0, 0, CDiffInfo::Less ), - m_Server( 0, 0, CDiffInfo::Less ), - m_flLastSpew( -1.0f ) - { - g_pDiffMgr = this; - } - - virtual void StartCommand( bool bServer, int nCommandNumber ) - { -#if defined( CLIENT_DLL ) - - if ( !diffcheck.GetInt() ) - return; - - g_pDiffMgr = reinterpret_cast< IDiffMgr * >( diffcheck.GetInt() ); - g_pDiffMgr->StartCommand( bServer, nCommandNumber ); - return; -#endif - - // Msg( "%s Startcommand %d\n", bServer ? "sv" : "cl", nCommandNumber ); - - diffcheck.SetValue( reinterpret_cast< int >( this ) ); - - Assert( CBaseEntity::IsServer() ); - - CUtlRBTree< CDiffInfo, int >& rb = bServer ? m_Server : m_Client; - - CDiffInfo search; - search.m_nCommandNumber = nCommandNumber; - int idx = rb.Find( search ); - if ( idx == rb.InvalidIndex() ) - { - idx = rb.Insert( search ); - } - - CDiffInfo *slot = &rb[ idx ]; - slot->m_Lines.RemoveAll(); - } - - virtual void AddToDiff( bool bServer, int nCommandNumber, char const *string ) - { -#if defined( CLIENT_DLL ) - - if ( !diffcheck.GetInt() ) - return; - - g_pDiffMgr = reinterpret_cast< IDiffMgr * >( diffcheck.GetInt() ); - g_pDiffMgr->AddToDiff( bServer, nCommandNumber, string ); - return; -#endif - Assert( CBaseEntity::IsServer() ); - - // Msg( "%s Add %d %s\n", bServer ? "sv" : "cl", nCommandNumber, string ); - - CUtlRBTree< CDiffInfo, int >& rb = bServer ? m_Server : m_Client; - - CDiffInfo search; - search.m_nCommandNumber = nCommandNumber; - int idx = rb.Find( search ); - if ( idx == rb.InvalidIndex() ) - { - Assert( 0 ); - idx = rb.Insert( search ); - } - - CDiffInfo *slot = &rb[ idx ]; - CDiffStr line( string ); - slot->m_Lines.AddToTail( line ); - } - - enum EMismatched - { - DIFFCHECK_NOTREADY = 0, - DIFFCHECK_MATCHED, - DIFFCHECK_DIFFERS - }; - - bool ClientRecordExists( int cmd ) - { - CDiffInfo clsearch; - clsearch.m_nCommandNumber = cmd; - int clidx = m_Client.Find( clsearch ); - return m_Client.IsValidIndex( clidx ); - } - - EMismatched IsMismatched( int svidx ) - { - CDiffInfo *serverslot = &m_Server[ svidx ]; - - // Now find the client version of this one - CDiffInfo clsearch; - clsearch.m_nCommandNumber = serverslot->m_nCommandNumber; - int clidx = m_Client.Find( clsearch ); - if ( clidx == m_Client.InvalidIndex() ) - return DIFFCHECK_NOTREADY; - - // Now compare them - CDiffInfo *clientslot = &m_Client[ clidx ]; - - bool bSpew = false; - if ( serverslot->m_Lines.Count() != - clientslot->m_Lines.Count() ) - { - return DIFFCHECK_DIFFERS; - } - - int maxSlot = MAX( serverslot->m_Lines.Count(), clientslot->m_Lines.Count() ); - if ( !bSpew ) - { - for ( int i = 0; i < maxSlot; ++i ) - { - CDiffStr *sv = NULL; - CDiffStr *cl = NULL; - if ( i < serverslot->m_Lines.Count() ) - { - sv = &serverslot->m_Lines[ i ]; - } - if ( i < clientslot->m_Lines.Count() ) - { - cl = &clientslot->m_Lines[ i ]; - } - - if ( Q_stricmp( sv ? sv->String() : "(missing)", cl ? cl->String() : "(missing)" ) ) - { - return DIFFCHECK_DIFFERS; - } - } - } - - return DIFFCHECK_MATCHED; - } - - virtual void Validate( bool bServer, int nCommandNumber ) - { -#if defined( CLIENT_DLL ) - - if ( !diffcheck.GetInt() ) - return; - - g_pDiffMgr = reinterpret_cast< IDiffMgr * >( diffcheck.GetInt() ); - g_pDiffMgr->Validate( bServer, nCommandNumber ); - return; -#endif - Assert( CBaseEntity::IsServer() ); - - // Only do this on the client - if ( !bServer ) - return; - - // Find the last server command number - if ( m_Server.Count() <= 0 ) - return; - - int svidx = m_Server.LastInorder(); - EMismatched eMisMatched = IsMismatched( svidx ); - if ( eMisMatched == DIFFCHECK_NOTREADY ) - { - return; - } - - if ( eMisMatched == DIFFCHECK_DIFFERS ) - { - CUtlVector< int > vecPrev; - - int nCur = svidx; - do - { - int prev = m_Server.PrevInorder( nCur ); - if ( m_Server.IsValidIndex( prev ) && - ClientRecordExists( m_Server[ prev ].m_nCommandNumber ) ) - { - //SpewRecords( "prev", prev ); - vecPrev.AddToHead( prev ); - } - else - { - break; - } - - nCur = prev; - } while ( vecPrev.Count() < 10 ); - - Msg( "-----\n" ); - - for ( int p = 0; p < vecPrev.Count(); ++p ) - { - SpewRecords( "prev", vecPrev[ p ] ); - } - - SpewRecords( "bad ", svidx ); - } - } - - void SpewRecords( char const *prefix, int svidx ) - { - CDiffInfo *serverslot = &m_Server[ svidx ]; - - // Now find the client version of this one - CDiffInfo clsearch; - clsearch.m_nCommandNumber = serverslot->m_nCommandNumber; - int clidx = m_Client.Find( clsearch ); - if ( clidx == m_Client.InvalidIndex() ) - return; - - // Now compare them - CDiffInfo *clientslot = &m_Client[ clidx ]; - - int maxSlot = MAX( serverslot->m_Lines.Count(), clientslot->m_Lines.Count() ); - - for ( int i = 0; i < maxSlot; ++i ) - { - char const *sv = "(missing)"; - char const *cl = "(missing)"; - - if ( i < serverslot->m_Lines.Count() ) - { - sv = serverslot->m_Lines[ i ].String(); - } - if ( i < clientslot->m_Lines.Count() ) - { - cl = clientslot->m_Lines[ i ].String(); - } - - bool bDiffers = Q_stricmp( sv, cl ) ? true : false; - - Msg( "%s%s%d: sv[%50.50s] cl[%50.50s]\n", - prefix, - bDiffers ? "+++" : " ", - serverslot->m_nCommandNumber, - sv, - cl ); - } - } -private: - - CUtlRBTree< CDiffInfo, int > m_Server; - CUtlRBTree< CDiffInfo, int > m_Client; - float m_flLastSpew; -}; - -static CDiffManager g_DiffMgr; - -void DiffPrint( bool bServer, int nCommandNumber, char const *fmt, ... ) -{ - // Only track stuff for local player - CBasePlayer *pPlayer = CBaseEntity::GetPredictionPlayer(); - if ( pPlayer && pPlayer->entindex() != 1 ) - { - return; - } - - va_list argptr; - char string[1024]; - va_start (argptr,fmt); - int len = Q_vsnprintf(string, sizeof( string ), fmt,argptr); - va_end (argptr); - - if ( g_pDiffMgr ) - { - // Strip any \n at the end that the user accidently put int - if ( len > 0 && string[ len -1 ] == '\n' ) - { - string[ len - 1 ] = 0; - } - - g_pDiffMgr->AddToDiff( bServer, nCommandNumber, string ); - } -} - -void _CheckV( int tick, char const *ctx, const Vector &vel ) -{ - DiffPrint( CBaseEntity::IsServer(), tick, "%20.20s %f %f %f", ctx, vel.x, vel.y, vel.z ); -} - -#define CheckV( tick, ctx, vel ) _CheckV( tick, ctx, vel ); - -static void StartCommand( bool bServer, int nCommandNumber ) -{ - // Only track stuff for local player - CBasePlayer *pPlayer = CBaseEntity::GetPredictionPlayer(); - if ( pPlayer && pPlayer->entindex() != 1 ) - { - return; - } - - if ( g_pDiffMgr ) - { - g_pDiffMgr->StartCommand( bServer, nCommandNumber ); - } -} - -static void Validate( bool bServer, int nCommandNumber ) -{ - // Only track stuff for local player - CBasePlayer *pPlayer = CBaseEntity::GetPredictionPlayer(); - if ( pPlayer && pPlayer->entindex() != 1 ) - { - return; - } - - - if ( g_pDiffMgr ) - { - g_pDiffMgr->Validate( bServer, nCommandNumber ); - } -} - -void CGameMovement::DiffPrint( char const *fmt, ... ) -{ - if ( !player ) - return; - - va_list argptr; - char string[1024]; - va_start (argptr,fmt); - Q_vsnprintf(string, sizeof( string ), fmt,argptr); - va_end (argptr); - - ::DiffPrint( CBaseEntity::IsServer(), player->CurrentCommandNumber(), "%s", string ); -} - -#else -/*static void DiffPrint( bool bServer, int nCommandNumber, char const *fmt, ... ) -{ - // Nothing -} -static void StartCommand( bool bServer, int nCommandNumber ) -{ -} - -static void Validate( bool bServer, int nCommandNumber ) -{ -}*/ - -#define CheckV( tick, ctx, vel ) - -void CGameMovement::DiffPrint( char const *fmt, ... ) -{ -} - -#endif // !PREDICTION_ERROR_CHECK_LEVEL - -#ifndef _XBOX -void COM_Log( const char *pszFile, const char *fmt, ...) -{ - va_list argptr; - char string[1024]; - FileHandle_t fp; - const char *pfilename; - - if ( !pszFile ) - { - pfilename = "hllog.txt"; - } - else - { - pfilename = pszFile; - } - va_start (argptr,fmt); - Q_vsnprintf(string, sizeof( string ), fmt,argptr); - va_end (argptr); - - fp = filesystem->Open( pfilename, "a+t"); - if (fp) - { - filesystem->FPrintf(fp, "%s", string); - filesystem->Close(fp); - } -} -#endif - -#ifndef CLIENT_DLL -//----------------------------------------------------------------------------- -// Purpose: Debug - draw the displacement collision plane. -//----------------------------------------------------------------------------- -void DrawDispCollPlane( CBaseTrace *pTrace ) -{ - float flLength = 30.0f; - - // Create a basis, based on the impact normal. - int nMajorAxis = 0; - Vector vecBasisU, vecBasisV, vecNormal; - vecNormal = pTrace->plane.normal; - float flAxisValue = vecNormal[0]; - if ( fabs( vecNormal[1] ) > fabs( flAxisValue ) ) { nMajorAxis = 1; flAxisValue = vecNormal[1]; } - if ( fabs( vecNormal[2] ) > fabs( flAxisValue ) ) { nMajorAxis = 2; } - if ( ( nMajorAxis == 1 ) || ( nMajorAxis == 2 ) ) - { - vecBasisU.Init( 1.0f, 0.0f, 0.0f ); - } - else - { - vecBasisU.Init( 0.0f, 1.0f, 0.0f ); - } - - vecBasisV = vecNormal.Cross( vecBasisU ); - VectorNormalize( vecBasisV ); - - vecBasisU = vecBasisV.Cross( vecNormal ); - VectorNormalize( vecBasisU ); - - // Create the impact point. Push off the surface a bit. - Vector vecImpactPoint = pTrace->startpos + pTrace->fraction * ( pTrace->endpos - pTrace->startpos ); - vecImpactPoint += vecNormal; - - // Generate a quad to represent the plane. - Vector vecPlanePoints[4]; - vecPlanePoints[0] = vecImpactPoint + ( vecBasisU * -flLength ) + ( vecBasisV * -flLength ); - vecPlanePoints[1] = vecImpactPoint + ( vecBasisU * -flLength ) + ( vecBasisV * flLength ); - vecPlanePoints[2] = vecImpactPoint + ( vecBasisU * flLength ) + ( vecBasisV * flLength ); - vecPlanePoints[3] = vecImpactPoint + ( vecBasisU * flLength ) + ( vecBasisV * -flLength ); - -#if 0 - // Test facing. - Vector vecEdges[2]; - vecEdges[0] = vecPlanePoints[1] - vecPlanePoints[0]; - vecEdges[1] = vecPlanePoints[2] - vecPlanePoints[0]; - Vector vecCross = vecEdges[0].Cross( vecEdges[1] ); - if ( vecCross.Dot( vecNormal ) < 0.0f ) - { - // Reverse winding. - } -#endif - - // Draw the plane. - NDebugOverlay::Triangle( vecPlanePoints[0], vecPlanePoints[1], vecPlanePoints[2], 125, 125, 125, 125, false, 5.0f ); - NDebugOverlay::Triangle( vecPlanePoints[0], vecPlanePoints[2], vecPlanePoints[3], 125, 125, 125, 125, false, 5.0f ); - - NDebugOverlay::Line( vecPlanePoints[0], vecPlanePoints[1], 255, 255, 255, false, 5.0f ); - NDebugOverlay::Line( vecPlanePoints[1], vecPlanePoints[2], 255, 255, 255, false, 5.0f ); - NDebugOverlay::Line( vecPlanePoints[2], vecPlanePoints[3], 255, 255, 255, false, 5.0f ); - NDebugOverlay::Line( vecPlanePoints[3], vecPlanePoints[0], 255, 255, 255, false, 5.0f ); - - // Draw the normal. - NDebugOverlay::Line( vecImpactPoint, vecImpactPoint + ( vecNormal * flLength ), 255, 0, 0, false, 5.0f ); -} -#endif - -//----------------------------------------------------------------------------- -// Purpose: Constructs GameMovement interface -//----------------------------------------------------------------------------- -CGameMovement::CGameMovement( void ) -{ - m_nOldWaterLevel = WL_NotInWater; - m_flWaterEntryTime = 0; - m_nOnLadder = 0; - - mv = NULL; - - memset( m_flStuckCheckTime, 0, sizeof(m_flStuckCheckTime) ); -} - -//----------------------------------------------------------------------------- -// Purpose: Destructor -//----------------------------------------------------------------------------- -CGameMovement::~CGameMovement( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: Allow bots etc to use slightly different solid masks -//----------------------------------------------------------------------------- -unsigned int CGameMovement::PlayerSolidMask( bool brushOnly ) -{ - return ( brushOnly ) ? MASK_PLAYERSOLID_BRUSHONLY : MASK_PLAYERSOLID; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// Output : int -//----------------------------------------------------------------------------- -int CGameMovement::GetCheckInterval( IntervalType_t type ) -{ - int tickInterval = 1; - switch ( type ) - { - default: - tickInterval = 1; - break; - case GROUND: - tickInterval = CATEGORIZE_GROUND_SURFACE_TICK_INTERVAL; - break; - case STUCK: - // If we are in the process of being "stuck", then try a new position every command tick until m_StuckLast gets reset back down to zero - if ( player->m_StuckLast != 0 ) - { - tickInterval = 1; - } - else - { - if ( gpGlobals->maxClients == 1 ) - { - tickInterval = CHECK_STUCK_TICK_INTERVAL_SP; - } - else - { - tickInterval = CHECK_STUCK_TICK_INTERVAL; - } - } - break; - case LADDER: - tickInterval = CHECK_LADDER_TICK_INTERVAL; - break; - } - return tickInterval; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CGameMovement::CheckInterval( IntervalType_t type ) -{ - int tickInterval = GetCheckInterval( type ); - - if ( g_bMovementOptimizations ) - { - return (player->CurrentCommandNumber() + player->entindex()) % tickInterval == 0; - } - else - { - return true; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : ducked - -// Output : const Vector -//----------------------------------------------------------------------------- -const Vector& CGameMovement::GetPlayerMins( bool ducked ) const -{ - return ducked ? VEC_DUCK_HULL_MIN : VEC_HULL_MIN; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : ducked - -// Output : const Vector -//----------------------------------------------------------------------------- -const Vector& CGameMovement::GetPlayerMaxs( bool ducked ) const -{ - return ducked ? VEC_DUCK_HULL_MAX : VEC_HULL_MAX; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : const Vector -//----------------------------------------------------------------------------- -const Vector& CGameMovement::GetPlayerMins( void ) const -{ - if ( player->IsObserver() ) - { - return VEC_OBS_HULL_MIN; - } - else - { - return player->m_Local.m_bDucked ? VEC_DUCK_HULL_MIN : VEC_HULL_MIN; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : const Vector -//----------------------------------------------------------------------------- -const Vector& CGameMovement::GetPlayerMaxs( void ) const -{ - if ( player->IsObserver() ) - { - return VEC_OBS_HULL_MAX; - } - else - { - return player->m_Local.m_bDucked ? VEC_DUCK_HULL_MAX : VEC_HULL_MAX; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : ducked - -// Output : const Vector -//----------------------------------------------------------------------------- -const Vector& CGameMovement::GetPlayerViewOffset( bool ducked ) const -{ - return ducked ? VEC_DUCK_VIEW : VEC_VIEW; -} - -#if 0 -//----------------------------------------------------------------------------- -// Traces player movement + position -//----------------------------------------------------------------------------- -inline void CGameMovement::TracePlayerBBox( const Vector& start, const Vector& end, unsigned int fMask, int collisionGroup, trace_t& pm ) -{ - VPROF( "CGameMovement::TracePlayerBBox" ); - - Ray_t ray; - ray.Init( start, end, GetPlayerMins(), GetPlayerMaxs() ); - UTIL_TraceRay( ray, fMask, mv->m_nPlayerHandle.Get(), collisionGroup, &pm ); -} -#endif - -CBaseHandle CGameMovement::TestPlayerPosition( const Vector& pos, int collisionGroup, trace_t& pm ) -{ - Ray_t ray; - ray.Init( pos, pos, GetPlayerMins(), GetPlayerMaxs() ); - UTIL_TraceRay( ray, PlayerSolidMask(), mv->m_nPlayerHandle.Get(), collisionGroup, &pm ); - if ( (pm.contents & PlayerSolidMask()) && pm.m_pEnt ) - { - return pm.m_pEnt->GetRefEHandle(); - } - else - { - return INVALID_EHANDLE_INDEX; - } -} - - -/* - -// FIXME FIXME: Does this need to be hooked up? -bool CGameMovement::IsWet() const -{ - return ((pev->flags & FL_INRAIN) != 0) || (m_WetTime >= gpGlobals->time); -} - -//----------------------------------------------------------------------------- -// Plants player footprint decals -//----------------------------------------------------------------------------- - -#define PLAYER_HALFWIDTH 12 -void CGameMovement::PlantFootprint( surfacedata_t *psurface ) -{ - // Can't plant footprints on fake materials (ladders, wading) - if ( psurface->gameMaterial != 'X' ) - { - int footprintDecal = -1; - - // Figure out which footprint type to plant... - // Use the wet footprint if we're wet... - if (IsWet()) - { - footprintDecal = DECAL_FOOTPRINT_WET; - } - else - { - // FIXME: Activate this once we decide to pull the trigger on it. - // NOTE: We could add in snow, mud, others here -// switch(psurface->gameMaterial) -// { -// case 'D': -// footprintDecal = DECAL_FOOTPRINT_DIRT; -// break; -// } - } - - if (footprintDecal != -1) - { - Vector right; - AngleVectors( pev->angles, 0, &right, 0 ); - - // Figure out where the top of the stepping leg is - trace_t tr; - Vector hipOrigin; - VectorMA( pev->origin, - m_IsFootprintOnLeft ? -PLAYER_HALFWIDTH : PLAYER_HALFWIDTH, - right, hipOrigin ); - - // Find where that leg hits the ground - UTIL_TraceLine( hipOrigin, hipOrigin + Vector(0, 0, -COORD_EXTENT * 1.74), - MASK_SOLID_BRUSHONLY, edict(), COLLISION_GROUP_NONE, &tr); - - unsigned char mType = TEXTURETYPE_Find( &tr ); - - // Splat a decal - CPVSFilter filter( tr.endpos ); - te->FootprintDecal( filter, 0.0f, &tr.endpos, &right, ENTINDEX(tr.u.ent), - gDecals[footprintDecal].index, mType ); - - } - } - - // Switch feet for next time - m_IsFootprintOnLeft = !m_IsFootprintOnLeft; -} - -#define WET_TIME 5.f // how many seconds till we're completely wet/dry -#define DRY_TIME 20.f // how many seconds till we're completely wet/dry - -void CBasePlayer::UpdateWetness() -{ - // BRJ 1/7/01 - // Check for whether we're in a rainy area.... - // Do this by tracing a line straight down with a size guaranteed to - // be larger than the map - // Update wetness based on whether we're in rain or not... - - trace_t tr; - UTIL_TraceLine( pev->origin, pev->origin + Vector(0, 0, -COORD_EXTENT * 1.74), - MASK_SOLID_BRUSHONLY, edict(), COLLISION_GROUP_NONE, &tr); - if (tr.surface.flags & SURF_WET) - { - if (! (pev->flags & FL_INRAIN) ) - { - // Transition... - // Figure out how wet we are now (we were drying off...) - float wetness = (m_WetTime - gpGlobals->time) / DRY_TIME; - if (wetness < 0.0f) - wetness = 0.0f; - - // Here, wet time represents the time at which we get totally wet - m_WetTime = gpGlobals->time + (1.0 - wetness) * WET_TIME; - - pev->flags |= FL_INRAIN; - } - } - else - { - if ((pev->flags & FL_INRAIN) != 0) - { - // Transition... - // Figure out how wet we are now (we were getting more wet...) - float wetness = 1.0f + (gpGlobals->time - m_WetTime) / WET_TIME; - if (wetness > 1.0f) - wetness = 1.0f; - - // Here, wet time represents the time at which we get totally dry - m_WetTime = gpGlobals->time + wetness * DRY_TIME; - - pev->flags &= ~FL_INRAIN; - } - } -} -*/ - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGameMovement::CategorizeGroundSurface( trace_t &pm ) -{ - IPhysicsSurfaceProps *physprops = MoveHelper()->GetSurfaceProps(); - player->m_surfaceProps = pm.surface.surfaceProps; - player->m_pSurfaceData = physprops->GetSurfaceData( player->m_surfaceProps ); - physprops->GetPhysicsProperties( player->m_surfaceProps, NULL, NULL, &player->m_surfaceFriction, NULL ); - - // HACKHACK: Scale this to fudge the relationship between vphysics friction values and player friction values. - // A value of 0.8f feels pretty normal for vphysics, whereas 1.0f is normal for players. - // This scaling trivially makes them equivalent. REVISIT if this affects low friction surfaces too much. - player->m_surfaceFriction *= 1.25f; - if ( player->m_surfaceFriction > 1.0f ) - player->m_surfaceFriction = 1.0f; - - player->m_chTextureType = player->m_pSurfaceData->game.material; -} - -bool CGameMovement::IsDead( void ) const -{ - return ( player->m_iHealth <= 0 ) ? true : false; -} - -//----------------------------------------------------------------------------- -// Figures out how the constraint should slow us down -//----------------------------------------------------------------------------- -float CGameMovement::ComputeConstraintSpeedFactor( void ) -{ - // If we have a constraint, slow down because of that too. - if ( !mv || mv->m_flConstraintRadius == 0.0f ) - return 1.0f; - - float flDistSq = mv->GetAbsOrigin().DistToSqr( mv->m_vecConstraintCenter ); - - float flOuterRadiusSq = mv->m_flConstraintRadius * mv->m_flConstraintRadius; - float flInnerRadiusSq = mv->m_flConstraintRadius - mv->m_flConstraintWidth; - flInnerRadiusSq *= flInnerRadiusSq; - - // Only slow us down if we're inside the constraint ring - if ((flDistSq <= flInnerRadiusSq) || (flDistSq >= flOuterRadiusSq)) - return 1.0f; - - // Only slow us down if we're running away from the center - Vector vecDesired; - VectorMultiply( m_vecForward, mv->m_flForwardMove, vecDesired ); - VectorMA( vecDesired, mv->m_flSideMove, m_vecRight, vecDesired ); - VectorMA( vecDesired, mv->m_flUpMove, m_vecUp, vecDesired ); - - Vector vecDelta; - VectorSubtract( mv->GetAbsOrigin(), mv->m_vecConstraintCenter, vecDelta ); - VectorNormalize( vecDelta ); - VectorNormalize( vecDesired ); - if (DotProduct( vecDelta, vecDesired ) < 0.0f) - return 1.0f; - - float flFrac = (sqrt(flDistSq) - (mv->m_flConstraintRadius - mv->m_flConstraintWidth)) / mv->m_flConstraintWidth; - - float flSpeedFactor = Lerp( flFrac, 1.0f, mv->m_flConstraintSpeedFactor ); - return flSpeedFactor; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGameMovement::CheckParameters( void ) -{ - QAngle v_angle; - - if ( player->GetMoveType() != MOVETYPE_ISOMETRIC && - player->GetMoveType() != MOVETYPE_NOCLIP && - player->GetMoveType() != MOVETYPE_OBSERVER ) - { - float spd; - float maxspeed; - - spd = ( mv->m_flForwardMove * mv->m_flForwardMove ) + - ( mv->m_flSideMove * mv->m_flSideMove ) + - ( mv->m_flUpMove * mv->m_flUpMove ); - - maxspeed = mv->m_flClientMaxSpeed; - if ( maxspeed != 0.0 ) - { - mv->m_flMaxSpeed = MIN( maxspeed, mv->m_flMaxSpeed ); - } - - // Slow down by the speed factor - float flSpeedFactor = 1.0f; - if (player->m_pSurfaceData) - { - flSpeedFactor = player->m_pSurfaceData->game.maxSpeedFactor; - } - - // If we have a constraint, slow down because of that too. - float flConstraintSpeedFactor = ComputeConstraintSpeedFactor(); - if (flConstraintSpeedFactor < flSpeedFactor) - flSpeedFactor = flConstraintSpeedFactor; - - mv->m_flMaxSpeed *= flSpeedFactor; - - if ( g_bMovementOptimizations ) - { - // Same thing but only do the sqrt if we have to. - if ( ( spd != 0.0 ) && ( spd > mv->m_flMaxSpeed*mv->m_flMaxSpeed ) ) - { - float fRatio = mv->m_flMaxSpeed / sqrt( spd ); - mv->m_flForwardMove *= fRatio; - mv->m_flSideMove *= fRatio; - mv->m_flUpMove *= fRatio; - } - } - else - { - spd = sqrt( spd ); - if ( ( spd != 0.0 ) && ( spd > mv->m_flMaxSpeed ) ) - { - float fRatio = mv->m_flMaxSpeed / spd; - mv->m_flForwardMove *= fRatio; - mv->m_flSideMove *= fRatio; - mv->m_flUpMove *= fRatio; - } - } - } - - if ( player->GetFlags() & FL_FROZEN || - player->GetFlags() & FL_ONTRAIN || - IsDead() ) - { - mv->m_flForwardMove = 0; - mv->m_flSideMove = 0; - mv->m_flUpMove = 0; - } - - DecayPunchAngle(); - - // Take angles from command. - if ( !IsDead() ) - { - v_angle = mv->m_vecAngles; - v_angle = v_angle + player->m_Local.m_vecPunchAngle; - - // Now adjust roll angle - if ( player->GetMoveType() != MOVETYPE_ISOMETRIC && - player->GetMoveType() != MOVETYPE_NOCLIP ) - { - mv->m_vecAngles[ROLL] = CalcRoll( v_angle, mv->m_vecVelocity, sv_rollangle.GetFloat(), sv_rollspeed.GetFloat() ); - } - else - { - mv->m_vecAngles[ROLL] = 0.0; // v_angle[ ROLL ]; - } - mv->m_vecAngles[PITCH] = v_angle[PITCH]; - mv->m_vecAngles[YAW] = v_angle[YAW]; - } - else - { - mv->m_vecAngles = mv->m_vecOldAngles; - } - - // Set dead player view_offset - if ( IsDead() ) - { - player->SetViewOffset( VEC_DEAD_VIEWHEIGHT ); - } - - // Adjust client view angles to match values used on server. - if ( mv->m_vecAngles[YAW] > 180.0f ) - { - mv->m_vecAngles[YAW] -= 360.0f; - } -} - -void CGameMovement::ReduceTimers( void ) -{ - float frame_msec = 1000.0f * gpGlobals->frametime; - - if ( player->m_Local.m_flDucktime > 0 ) - { - player->m_Local.m_flDucktime -= frame_msec; - if ( player->m_Local.m_flDucktime < 0 ) - { - player->m_Local.m_flDucktime = 0; - } - } - if ( player->m_Local.m_flDuckJumpTime > 0 ) - { - player->m_Local.m_flDuckJumpTime -= frame_msec; - if ( player->m_Local.m_flDuckJumpTime < 0 ) - { - player->m_Local.m_flDuckJumpTime = 0; - } - } - if ( player->m_Local.m_flJumpTime > 0 ) - { - player->m_Local.m_flJumpTime -= frame_msec; - if ( player->m_Local.m_flJumpTime < 0 ) - { - player->m_Local.m_flJumpTime = 0; - } - } - if ( player->m_flSwimSoundTime > 0 ) - { - player->m_flSwimSoundTime -= frame_msec; - if ( player->m_flSwimSoundTime < 0 ) - { - player->m_flSwimSoundTime = 0; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pMove - -//----------------------------------------------------------------------------- -void CGameMovement::ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMove ) -{ - Assert( pMove && pPlayer ); - - float flStoreFrametime = gpGlobals->frametime; - - //!!HACK HACK: Adrian - slow down all player movement by this factor. - //!!Blame Yahn for this one. - gpGlobals->frametime *= pPlayer->GetLaggedMovementValue(); - - ResetGetPointContentsCache(); - - // Cropping movement speed scales mv->m_fForwardSpeed etc. globally - // Once we crop, we don't want to recursively crop again, so we set the crop - // flag globally here once per usercmd cycle. - m_bSpeedCropped = false; - - // StartTrackPredictionErrors should have set this - Assert( player == pPlayer ); - player = pPlayer; - - mv = pMove; - mv->m_flMaxSpeed = sv_maxspeed.GetFloat(); - - // CheckV( player->CurrentCommandNumber(), "StartPos", mv->GetAbsOrigin() ); - - DiffPrint( "start %f %f %f", mv->GetAbsOrigin().x, mv->GetAbsOrigin().y, mv->GetAbsOrigin().z ); - - // Run the command. - PlayerMove(); - - FinishMove(); - - DiffPrint( "end %f %f %f", mv->GetAbsOrigin().x, mv->GetAbsOrigin().y, mv->GetAbsOrigin().z ); - - // CheckV( player->CurrentCommandNumber(), "EndPos", mv->GetAbsOrigin() ); - - //This is probably not needed, but just in case. - gpGlobals->frametime = flStoreFrametime; - - player = NULL; -} - -void CGameMovement::StartTrackPredictionErrors( CBasePlayer *pPlayer ) -{ - player = pPlayer; - -#if PREDICTION_ERROR_CHECK_LEVEL > 0 - StartCommand( CBaseEntity::IsServer(), player->CurrentCommandNumber() ); -#endif -} - -void CGameMovement::FinishTrackPredictionErrors( CBasePlayer *pPlayer ) -{ -#if PREDICTION_ERROR_CHECK_LEVEL > 0 - Assert( player == pPlayer ); - - // DiffPrint( "end %f", player->m_Local.m_vecPunchAngleVel.m_Value.x ); - - // Call validate at end of checking - Validate( CBaseEntity::IsServer(), player->CurrentCommandNumber() ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Sets ground entity -//----------------------------------------------------------------------------- -void CGameMovement::FinishMove( void ) -{ - mv->m_nOldButtons = mv->m_nButtons; -} - -#define PUNCH_DAMPING 9.0f // bigger number makes the response more damped, smaller is less damped - // currently the system will overshoot, with larger damping values it won't -#define PUNCH_SPRING_CONSTANT 65.0f // bigger number increases the speed at which the view corrects - -//----------------------------------------------------------------------------- -// Purpose: Decays the punchangle toward 0,0,0. -// Modelled as a damped spring -//----------------------------------------------------------------------------- -void CGameMovement::DecayPunchAngle( void ) -{ - if ( player->m_Local.m_vecPunchAngle->LengthSqr() > 0.001 || player->m_Local.m_vecPunchAngleVel->LengthSqr() > 0.001 ) - { - player->m_Local.m_vecPunchAngle += player->m_Local.m_vecPunchAngleVel * gpGlobals->frametime; - float damping = 1 - (PUNCH_DAMPING * gpGlobals->frametime); - - if ( damping < 0 ) - { - damping = 0; - } - player->m_Local.m_vecPunchAngleVel *= damping; - - // torsional spring - // UNDONE: Per-axis spring constant? - float springForceMagnitude = PUNCH_SPRING_CONSTANT * gpGlobals->frametime; - springForceMagnitude = clamp(springForceMagnitude, 0, 2 ); - player->m_Local.m_vecPunchAngleVel -= player->m_Local.m_vecPunchAngle * springForceMagnitude; - - // don't wrap around - player->m_Local.m_vecPunchAngle.Init( - clamp(player->m_Local.m_vecPunchAngle->x, -89, 89 ), - clamp(player->m_Local.m_vecPunchAngle->y, -179, 179 ), - clamp(player->m_Local.m_vecPunchAngle->z, -89, 89 ) ); - } - else - { - player->m_Local.m_vecPunchAngle.Init( 0, 0, 0 ); - player->m_Local.m_vecPunchAngleVel.Init( 0, 0, 0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGameMovement::StartGravity( void ) -{ - float ent_gravity; - - if (player->GetGravity()) - ent_gravity = player->GetGravity(); - else - ent_gravity = 1.0; - - // Add gravity so they'll be in the correct position during movement - // yes, this 0.5 looks wrong, but it's not. - mv->m_vecVelocity[2] -= (ent_gravity * sv_gravity.GetFloat() * 0.5 * gpGlobals->frametime ); - mv->m_vecVelocity[2] += player->GetBaseVelocity()[2] * gpGlobals->frametime; - - Vector temp = player->GetBaseVelocity(); - temp[ 2 ] = 0; - player->SetBaseVelocity( temp ); - - CheckVelocity(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGameMovement::CheckWaterJump( void ) -{ - Vector flatforward; - Vector forward; - Vector flatvelocity; - float curspeed; - - AngleVectors( mv->m_vecViewAngles, &forward ); // Determine movement angles - - // Already water jumping. - if (player->m_flWaterJumpTime) - return; - - // Don't hop out if we just jumped in - if (mv->m_vecVelocity[2] < -180) - return; // only hop out if we are moving up - - // See if we are backing up - flatvelocity[0] = mv->m_vecVelocity[0]; - flatvelocity[1] = mv->m_vecVelocity[1]; - flatvelocity[2] = 0; - - // Must be moving - curspeed = VectorNormalize( flatvelocity ); - - // see if near an edge - flatforward[0] = forward[0]; - flatforward[1] = forward[1]; - flatforward[2] = 0; - VectorNormalize (flatforward); - - // Are we backing into water from steps or something? If so, don't pop forward - if ( curspeed != 0.0 && ( DotProduct( flatvelocity, flatforward ) < 0.0 ) ) - return; - - Vector vecStart; - // Start line trace at waist height (using the center of the player for this here) - vecStart= mv->GetAbsOrigin() + (GetPlayerMins() + GetPlayerMaxs() ) * 0.5; - - Vector vecEnd; - VectorMA( vecStart, 24.0f, flatforward, vecEnd ); - - trace_t tr; - TracePlayerBBox( vecStart, vecEnd, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, tr ); - if ( tr.fraction < 1.0 ) // solid at waist - { - IPhysicsObject *pPhysObj = tr.m_pEnt->VPhysicsGetObject(); - if ( pPhysObj ) - { - if ( pPhysObj->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - return; - } - - vecStart.z = mv->GetAbsOrigin().z + player->GetViewOffset().z + WATERJUMP_HEIGHT; - VectorMA( vecStart, 24.0f, flatforward, vecEnd ); - VectorMA( vec3_origin, -50.0f, tr.plane.normal, player->m_vecWaterJumpVel ); - - TracePlayerBBox( vecStart, vecEnd, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, tr ); - if ( tr.fraction == 1.0 ) // open at eye level - { - // Now trace down to see if we would actually land on a standable surface. - VectorCopy( vecEnd, vecStart ); - vecEnd.z -= 1024.0f; - TracePlayerBBox( vecStart, vecEnd, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, tr ); - if ( ( tr.fraction < 1.0f ) && ( tr.plane.normal.z >= 0.7 ) ) - { - mv->m_vecVelocity[2] = 256.0f; // Push up - mv->m_nOldButtons |= IN_JUMP; // Don't jump again until released - player->AddFlag( FL_WATERJUMP ); - player->m_flWaterJumpTime = 2000.0f; // Do this for 2 seconds - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGameMovement::WaterJump( void ) -{ - if (player->m_flWaterJumpTime > 10000) - player->m_flWaterJumpTime = 10000; - - if (!player->m_flWaterJumpTime) - return; - - player->m_flWaterJumpTime -= 1000.0f * gpGlobals->frametime; - - if (player->m_flWaterJumpTime <= 0 || !player->GetWaterLevel()) - { - player->m_flWaterJumpTime = 0; - player->RemoveFlag( FL_WATERJUMP ); - } - - mv->m_vecVelocity[0] = player->m_vecWaterJumpVel[0]; - mv->m_vecVelocity[1] = player->m_vecWaterJumpVel[1]; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGameMovement::WaterMove( void ) -{ - int i; - Vector wishvel; - float wishspeed; - Vector wishdir; - Vector start, dest; - Vector temp; - trace_t pm; - float speed, newspeed, addspeed, accelspeed; - Vector forward, right, up; - - AngleVectors (mv->m_vecViewAngles, &forward, &right, &up); // Determine movement angles - - // - // user intentions - // - for (i=0 ; i<3 ; i++) - { - wishvel[i] = forward[i]*mv->m_flForwardMove + right[i]*mv->m_flSideMove; - } - - // if we have the jump key down, move us up as well - if (mv->m_nButtons & IN_JUMP) - { - wishvel[2] += mv->m_flClientMaxSpeed; - } - // Sinking after no other movement occurs - else if (!mv->m_flForwardMove && !mv->m_flSideMove && !mv->m_flUpMove) - { - wishvel[2] -= 60; // drift towards bottom - } - else // Go straight up by upmove amount. - { - // exaggerate upward movement along forward as well - float upwardMovememnt = mv->m_flForwardMove * forward.z * 2; - upwardMovememnt = clamp( upwardMovememnt, 0, mv->m_flClientMaxSpeed ); - wishvel[2] += mv->m_flUpMove + upwardMovememnt; - } - - // Copy it over and determine speed - VectorCopy (wishvel, wishdir); - wishspeed = VectorNormalize(wishdir); - - // Cap speed. - if (wishspeed > mv->m_flMaxSpeed) - { - VectorScale (wishvel, mv->m_flMaxSpeed/wishspeed, wishvel); - wishspeed = mv->m_flMaxSpeed; - } - - // Slow us down a bit. - wishspeed *= 0.8; - - // Water friction - VectorCopy(mv->m_vecVelocity, temp); - speed = VectorNormalize(temp); - if (speed) - { - newspeed = speed - gpGlobals->frametime * speed * sv_friction.GetFloat() * player->m_surfaceFriction; - if (newspeed < 0.1f) - { - newspeed = 0; - } - - VectorScale (mv->m_vecVelocity, newspeed/speed, mv->m_vecVelocity); - } - else - { - newspeed = 0; - } - - // water acceleration - if (wishspeed >= 0.1f) // old ! - { - addspeed = wishspeed - newspeed; - if (addspeed > 0) - { - VectorNormalize(wishvel); - accelspeed = sv_accelerate.GetFloat() * wishspeed * gpGlobals->frametime * player->m_surfaceFriction; - if (accelspeed > addspeed) - { - accelspeed = addspeed; - } - - for (i = 0; i < 3; i++) - { - float deltaSpeed = accelspeed * wishvel[i]; - mv->m_vecVelocity[i] += deltaSpeed; - mv->m_outWishVel[i] += deltaSpeed; - } - } - } - - VectorAdd (mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity); - - // Now move - // assume it is a stair or a slope, so press down from stepheight above - VectorMA (mv->GetAbsOrigin(), gpGlobals->frametime, mv->m_vecVelocity, dest); - - TracePlayerBBox( mv->GetAbsOrigin(), dest, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, pm ); - if ( pm.fraction == 1.0f ) - { - VectorCopy( dest, start ); - if ( player->m_Local.m_bAllowAutoMovement ) - { - start[2] += player->m_Local.m_flStepSize + 1; - } - - TracePlayerBBox( start, dest, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, pm ); - - if (!pm.startsolid && !pm.allsolid) - { - float stepDist = pm.endpos.z - mv->GetAbsOrigin().z; - mv->m_outStepHeight += stepDist; - // walked up the step, so just keep result and exit - mv->SetAbsOrigin( pm.endpos ); - VectorSubtract( mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity ); - return; - } - - // Try moving straight along out normal path. - TryPlayerMove(); - } - else - { - if ( !player->GetGroundEntity() ) - { - TryPlayerMove(); - VectorSubtract( mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity ); - return; - } - - StepMove( dest, pm ); - } - - VectorSubtract( mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity ); -} - -//----------------------------------------------------------------------------- -// Purpose: Does the basic move attempting to climb up step heights. It uses -// the mv->GetAbsOrigin() and mv->m_vecVelocity. It returns a new -// new mv->GetAbsOrigin(), mv->m_vecVelocity, and mv->m_outStepHeight. -//----------------------------------------------------------------------------- -void CGameMovement::StepMove( Vector &vecDestination, trace_t &trace ) -{ - Vector vecEndPos; - VectorCopy( vecDestination, vecEndPos ); - - // Try sliding forward both on ground and up 16 pixels - // take the move that goes farthest - Vector vecPos, vecVel; - VectorCopy( mv->GetAbsOrigin(), vecPos ); - VectorCopy( mv->m_vecVelocity, vecVel ); - - // Slide move down. - TryPlayerMove( &vecEndPos, &trace ); - - // Down results. - Vector vecDownPos, vecDownVel; - VectorCopy( mv->GetAbsOrigin(), vecDownPos ); - VectorCopy( mv->m_vecVelocity, vecDownVel ); - - // Reset original values. - mv->SetAbsOrigin( vecPos ); - VectorCopy( vecVel, mv->m_vecVelocity ); - - // Move up a stair height. - VectorCopy( mv->GetAbsOrigin(), vecEndPos ); - if ( player->m_Local.m_bAllowAutoMovement ) - { - vecEndPos.z += player->m_Local.m_flStepSize + DIST_EPSILON; - } - - TracePlayerBBox( mv->GetAbsOrigin(), vecEndPos, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, trace ); - if ( !trace.startsolid && !trace.allsolid ) - { - mv->SetAbsOrigin( trace.endpos ); - } - - // Slide move up. - TryPlayerMove(); - - // Move down a stair (attempt to). - VectorCopy( mv->GetAbsOrigin(), vecEndPos ); - if ( player->m_Local.m_bAllowAutoMovement ) - { - vecEndPos.z -= player->m_Local.m_flStepSize + DIST_EPSILON; - } - - TracePlayerBBox( mv->GetAbsOrigin(), vecEndPos, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, trace ); - - // If we are not on the ground any more then use the original movement attempt. - if ( trace.plane.normal[2] < 0.7 ) - { - mv->SetAbsOrigin( vecDownPos ); - VectorCopy( vecDownVel, mv->m_vecVelocity ); - float flStepDist = mv->GetAbsOrigin().z - vecPos.z; - if ( flStepDist > 0.0f ) - { - mv->m_outStepHeight += flStepDist; - } - return; - } - - // If the trace ended up in empty space, copy the end over to the origin. - if ( !trace.startsolid && !trace.allsolid ) - { - mv->SetAbsOrigin( trace.endpos ); - } - - // Copy this origin to up. - Vector vecUpPos; - VectorCopy( mv->GetAbsOrigin(), vecUpPos ); - - // decide which one went farther - float flDownDist = ( vecDownPos.x - vecPos.x ) * ( vecDownPos.x - vecPos.x ) + ( vecDownPos.y - vecPos.y ) * ( vecDownPos.y - vecPos.y ); - float flUpDist = ( vecUpPos.x - vecPos.x ) * ( vecUpPos.x - vecPos.x ) + ( vecUpPos.y - vecPos.y ) * ( vecUpPos.y - vecPos.y ); - if ( flDownDist > flUpDist ) - { - mv->SetAbsOrigin( vecDownPos ); - VectorCopy( vecDownVel, mv->m_vecVelocity ); - } - else - { - // copy z value from slide move - mv->m_vecVelocity.z = vecDownVel.z; - } - - float flStepDist = mv->GetAbsOrigin().z - vecPos.z; - if ( flStepDist > 0 ) - { - mv->m_outStepHeight += flStepDist; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGameMovement::Friction( void ) -{ - float speed, newspeed, control; - float friction; - float drop; - - // If we are in water jump cycle, don't apply friction - if (player->m_flWaterJumpTime) - return; - - // Calculate speed - speed = VectorLength( mv->m_vecVelocity ); - - // If too slow, return - if (speed < 0.1f) - { - return; - } - - drop = 0; - - // apply ground friction - if (player->GetGroundEntity() != NULL) // On an entity that is the ground - { - friction = sv_friction.GetFloat() * player->m_surfaceFriction; - - // Bleed off some speed, but if we have less than the bleed - // threshold, bleed the threshold amount. - - if ( IsX360() ) - { - if( player->m_Local.m_bDucked ) - { - control = (speed < sv_stopspeed.GetFloat()) ? sv_stopspeed.GetFloat() : speed; - } - else - { -#if defined ( TF_DLL ) || defined ( TF_CLIENT_DLL ) - control = (speed < sv_stopspeed.GetFloat()) ? sv_stopspeed.GetFloat() : speed; -#else - control = (speed < sv_stopspeed.GetFloat()) ? (sv_stopspeed.GetFloat() * 2.0f) : speed; -#endif - } - } - else - { - control = (speed < sv_stopspeed.GetFloat()) ? sv_stopspeed.GetFloat() : speed; - } - - // Add the amount to the drop amount. - drop += control*friction*gpGlobals->frametime; - } - - // scale the velocity - newspeed = speed - drop; - if (newspeed < 0) - newspeed = 0; - - if ( newspeed != speed ) - { - // Determine proportion of old speed we are using. - newspeed /= speed; - // Adjust velocity according to proportion. - VectorScale( mv->m_vecVelocity, newspeed, mv->m_vecVelocity ); - } - - mv->m_outWishVel -= (1.f-newspeed) * mv->m_vecVelocity; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGameMovement::FinishGravity( void ) -{ - float ent_gravity; - - if ( player->m_flWaterJumpTime ) - return; - - if ( player->GetGravity() ) - ent_gravity = player->GetGravity(); - else - ent_gravity = 1.0; - - // Get the correct velocity for the end of the dt - mv->m_vecVelocity[2] -= (ent_gravity * sv_gravity.GetFloat() * gpGlobals->frametime * 0.5); - - CheckVelocity(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : wishdir - -// accel - -//----------------------------------------------------------------------------- -void CGameMovement::AirAccelerate( Vector& wishdir, float wishspeed, float accel ) -{ - int i; - float addspeed, accelspeed, currentspeed; - float wishspd; - - wishspd = wishspeed; - - if (player->pl.deadflag) - return; - - if (player->m_flWaterJumpTime) - return; - - // Cap speed - if (wishspd > 30) - wishspd = 30; - - // Determine veer amount - currentspeed = mv->m_vecVelocity.Dot(wishdir); - - // See how much to add - addspeed = wishspd - currentspeed; - - // If not adding any, done. - if (addspeed <= 0) - return; - - // Determine acceleration speed after acceleration - accelspeed = accel * wishspeed * gpGlobals->frametime * player->m_surfaceFriction; - - // Cap it - if (accelspeed > addspeed) - accelspeed = addspeed; - - // Adjust pmove vel. - for (i=0 ; i<3 ; i++) - { - mv->m_vecVelocity[i] += accelspeed * wishdir[i]; - mv->m_outWishVel[i] += accelspeed * wishdir[i]; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGameMovement::AirMove( void ) -{ - int i; - Vector wishvel; - float fmove, smove; - Vector wishdir; - float wishspeed; - Vector forward, right, up; - - AngleVectors (mv->m_vecViewAngles, &forward, &right, &up); // Determine movement angles - - // Copy movement amounts - fmove = mv->m_flForwardMove; - smove = mv->m_flSideMove; - - // Zero out z components of movement vectors - forward[2] = 0; - right[2] = 0; - VectorNormalize(forward); // Normalize remainder of vectors - VectorNormalize(right); // - - for (i=0 ; i<2 ; i++) // Determine x and y parts of velocity - wishvel[i] = forward[i]*fmove + right[i]*smove; - wishvel[2] = 0; // Zero out z part of velocity - - VectorCopy (wishvel, wishdir); // Determine maginitude of speed of move - wishspeed = VectorNormalize(wishdir); - - // - // clamp to server defined max speed - // - if ( wishspeed != 0 && (wishspeed > mv->m_flMaxSpeed)) - { - VectorScale (wishvel, mv->m_flMaxSpeed/wishspeed, wishvel); - wishspeed = mv->m_flMaxSpeed; - } - - AirAccelerate( wishdir, wishspeed, sv_airaccelerate.GetFloat() ); - - // Add in any base velocity to the current velocity. - VectorAdd(mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity ); - - TryPlayerMove(); - - // Now pull the base velocity back out. Base velocity is set if you are on a moving object, like a conveyor (or maybe another monster?) - VectorSubtract( mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity ); -} - - -bool CGameMovement::CanAccelerate() -{ - // Dead players don't accelerate. - if (player->pl.deadflag) - return false; - - // If waterjumping, don't accelerate - if (player->m_flWaterJumpTime) - return false; - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : wishdir - -// wishspeed - -// accel - -//----------------------------------------------------------------------------- -void CGameMovement::Accelerate( Vector& wishdir, float wishspeed, float accel ) -{ - int i; - float addspeed, accelspeed, currentspeed; - - // This gets overridden because some games (CSPort) want to allow dead (observer) players - // to be able to move around. - if ( !CanAccelerate() ) - return; - - // See if we are changing direction a bit - currentspeed = mv->m_vecVelocity.Dot(wishdir); - - // Reduce wishspeed by the amount of veer. - addspeed = wishspeed - currentspeed; - - // If not going to add any speed, done. - if (addspeed <= 0) - return; - - // Determine amount of accleration. - accelspeed = accel * gpGlobals->frametime * wishspeed * player->m_surfaceFriction; - - // Cap at addspeed - if (accelspeed > addspeed) - accelspeed = addspeed; - - // Adjust velocity. - for (i=0 ; i<3 ; i++) - { - mv->m_vecVelocity[i] += accelspeed * wishdir[i]; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Try to keep a walking player on the ground when running down slopes etc -//----------------------------------------------------------------------------- -void CGameMovement::StayOnGround( void ) -{ - trace_t trace; - Vector start( mv->GetAbsOrigin() ); - Vector end( mv->GetAbsOrigin() ); - start.z += 2; - end.z -= player->GetStepSize(); - - // See how far up we can go without getting stuck - - TracePlayerBBox( mv->GetAbsOrigin(), start, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, trace ); - start = trace.endpos; - - // using trace.startsolid is unreliable here, it doesn't get set when - // tracing bounding box vs. terrain - - // Now trace down from a known safe position - TracePlayerBBox( start, end, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, trace ); - if ( trace.fraction > 0.0f && // must go somewhere - trace.fraction < 1.0f && // must hit something - !trace.startsolid && // can't be embedded in a solid - trace.plane.normal[2] >= 0.7 ) // can't hit a steep slope that we can't stand on anyway - { - float flDelta = fabs(mv->GetAbsOrigin().z - trace.endpos.z); - - //This is incredibly hacky. The real problem is that trace returning that strange value we can't network over. - if ( flDelta > 0.5f * COORD_RESOLUTION) - { - mv->SetAbsOrigin( trace.endpos ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGameMovement::WalkMove( void ) -{ - int i; - - Vector wishvel; - float spd; - float fmove, smove; - Vector wishdir; - float wishspeed; - - Vector dest; - trace_t pm; - Vector forward, right, up; - - AngleVectors (mv->m_vecViewAngles, &forward, &right, &up); // Determine movement angles - - CHandle< CBaseEntity > oldground; - oldground = player->GetGroundEntity(); - - // Copy movement amounts - fmove = mv->m_flForwardMove; - smove = mv->m_flSideMove; - - // Zero out z components of movement vectors - if ( g_bMovementOptimizations ) - { - if ( forward[2] != 0 ) - { - forward[2] = 0; - VectorNormalize( forward ); - } - - if ( right[2] != 0 ) - { - right[2] = 0; - VectorNormalize( right ); - } - } - else - { - forward[2] = 0; - right[2] = 0; - - VectorNormalize (forward); // Normalize remainder of vectors. - VectorNormalize (right); // - } - - for (i=0 ; i<2 ; i++) // Determine x and y parts of velocity - wishvel[i] = forward[i]*fmove + right[i]*smove; - - wishvel[2] = 0; // Zero out z part of velocity - - VectorCopy (wishvel, wishdir); // Determine maginitude of speed of move - wishspeed = VectorNormalize(wishdir); - - // - // Clamp to server defined max speed - // - if ((wishspeed != 0.0f) && (wishspeed > mv->m_flMaxSpeed)) - { - VectorScale (wishvel, mv->m_flMaxSpeed/wishspeed, wishvel); - wishspeed = mv->m_flMaxSpeed; - } - - // Set pmove velocity - mv->m_vecVelocity[2] = 0; - Accelerate ( wishdir, wishspeed, sv_accelerate.GetFloat() ); - mv->m_vecVelocity[2] = 0; - - // Add in any base velocity to the current velocity. - VectorAdd (mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity ); - - spd = VectorLength( mv->m_vecVelocity ); - - if ( spd < 1.0f ) - { - mv->m_vecVelocity.Init(); - // Now pull the base velocity back out. Base velocity is set if you are on a moving object, like a conveyor (or maybe another monster?) - VectorSubtract( mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity ); - return; - } - - // first try just moving to the destination - dest[0] = mv->GetAbsOrigin()[0] + mv->m_vecVelocity[0]*gpGlobals->frametime; - dest[1] = mv->GetAbsOrigin()[1] + mv->m_vecVelocity[1]*gpGlobals->frametime; - dest[2] = mv->GetAbsOrigin()[2]; - - // first try moving directly to the next spot - TracePlayerBBox( mv->GetAbsOrigin(), dest, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, pm ); - - // If we made it all the way, then copy trace end as new player position. - mv->m_outWishVel += wishdir * wishspeed; - - if ( pm.fraction == 1 ) - { - mv->SetAbsOrigin( pm.endpos ); - // Now pull the base velocity back out. Base velocity is set if you are on a moving object, like a conveyor (or maybe another monster?) - VectorSubtract( mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity ); - - StayOnGround(); - return; - } - - // Don't walk up stairs if not on ground. - if ( oldground == NULL && player->GetWaterLevel() == 0 ) - { - // Now pull the base velocity back out. Base velocity is set if you are on a moving object, like a conveyor (or maybe another monster?) - VectorSubtract( mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity ); - return; - } - - // If we are jumping out of water, don't do anything more. - if ( player->m_flWaterJumpTime ) - { - // Now pull the base velocity back out. Base velocity is set if you are on a moving object, like a conveyor (or maybe another monster?) - VectorSubtract( mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity ); - return; - } - - StepMove( dest, pm ); - - // Now pull the base velocity back out. Base velocity is set if you are on a moving object, like a conveyor (or maybe another monster?) - VectorSubtract( mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity ); - - StayOnGround(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGameMovement::FullWalkMove( ) -{ - if ( !CheckWater() ) - { - StartGravity(); - } - - // If we are leaping out of the water, just update the counters. - if (player->m_flWaterJumpTime) - { - WaterJump(); - TryPlayerMove(); - // See if we are still in water? - CheckWater(); - return; - } - - // If we are swimming in the water, see if we are nudging against a place we can jump up out - // of, and, if so, start out jump. Otherwise, if we are not moving up, then reset jump timer to 0 - if ( player->GetWaterLevel() >= WL_Waist ) - { - if ( player->GetWaterLevel() == WL_Waist ) - { - CheckWaterJump(); - } - - // If we are falling again, then we must not trying to jump out of water any more. - if ( mv->m_vecVelocity[2] < 0 && - player->m_flWaterJumpTime ) - { - player->m_flWaterJumpTime = 0; - } - - // Was jump button pressed? - if (mv->m_nButtons & IN_JUMP) - { - CheckJumpButton(); - } - else - { - mv->m_nOldButtons &= ~IN_JUMP; - } - - // Perform regular water movement - WaterMove(); - - // Redetermine position vars - CategorizePosition(); - - // If we are on ground, no downward velocity. - if ( player->GetGroundEntity() != NULL ) - { - mv->m_vecVelocity[2] = 0; - } - } - else - // Not fully underwater - { - // Was jump button pressed? - if (mv->m_nButtons & IN_JUMP) - { - CheckJumpButton(); - } - else - { - mv->m_nOldButtons &= ~IN_JUMP; - } - - // Fricion is handled before we add in any base velocity. That way, if we are on a conveyor, - // we don't slow when standing still, relative to the conveyor. - if (player->GetGroundEntity() != NULL) - { - mv->m_vecVelocity[2] = 0.0; - Friction(); - } - - // Make sure velocity is valid. - CheckVelocity(); - - if (player->GetGroundEntity() != NULL) - { - WalkMove(); - } - else - { - AirMove(); // Take into account movement when in air. - } - - // Set final flags. - CategorizePosition(); - - // Make sure velocity is valid. - CheckVelocity(); - - // Add any remaining gravitational component. - if ( !CheckWater() ) - { - FinishGravity(); - } - - // If we are on ground, no downward velocity. - if ( player->GetGroundEntity() != NULL ) - { - mv->m_vecVelocity[2] = 0; - } - CheckFalling(); - } - - if ( ( m_nOldWaterLevel == WL_NotInWater && player->GetWaterLevel() != WL_NotInWater ) || - ( m_nOldWaterLevel != WL_NotInWater && player->GetWaterLevel() == WL_NotInWater ) ) - { - PlaySwimSound(); -#if !defined( CLIENT_DLL ) - player->Splash(); -#endif - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGameMovement::FullObserverMove( void ) -{ - int mode = player->GetObserverMode(); - - if ( mode == OBS_MODE_IN_EYE || mode == OBS_MODE_CHASE ) - { - CBaseEntity * target = player->GetObserverTarget(); - - if ( target != NULL ) - { - mv->SetAbsOrigin( target->GetAbsOrigin() ); - mv->m_vecViewAngles = target->GetAbsAngles(); - mv->m_vecVelocity = target->GetAbsVelocity(); - } - - return; - } - - if ( mode != OBS_MODE_ROAMING ) - { - // don't move in fixed or death cam mode - return; - } - - if ( sv_specnoclip.GetBool() ) - { - // roam in noclip mode - FullNoClipMove( sv_specspeed.GetFloat(), sv_specaccelerate.GetFloat() ); - return; - } - - // do a full clipped free roam move: - - Vector wishvel; - Vector forward, right, up; - Vector wishdir, wishend; - float wishspeed; - - AngleVectors (mv->m_vecViewAngles, &forward, &right, &up); // Determine movement angles - - // Copy movement amounts - - float factor = sv_specspeed.GetFloat(); - - if ( mv->m_nButtons & IN_SPEED ) - { - factor /= 2.0f; - } - - float fmove = mv->m_flForwardMove * factor; - float smove = mv->m_flSideMove * factor; - - VectorNormalize (forward); // Normalize remainder of vectors - VectorNormalize (right); // - - for (int i=0 ; i<3 ; i++) // Determine x and y parts of velocity - wishvel[i] = forward[i]*fmove + right[i]*smove; - wishvel[2] += mv->m_flUpMove; - - VectorCopy (wishvel, wishdir); // Determine maginitude of speed of move - wishspeed = VectorNormalize(wishdir); - - // - // Clamp to server defined max speed - // - - float maxspeed = sv_maxvelocity.GetFloat(); - - - if (wishspeed > maxspeed ) - { - VectorScale (wishvel, mv->m_flMaxSpeed/wishspeed, wishvel); - wishspeed = maxspeed; - } - - // Set pmove velocity, give observer 50% acceration bonus - Accelerate ( wishdir, wishspeed, sv_specaccelerate.GetFloat() ); - - float spd = VectorLength( mv->m_vecVelocity ); - if (spd < 1.0f) - { - mv->m_vecVelocity.Init(); - return; - } - - float friction = sv_friction.GetFloat(); - - // Add the amount to the drop amount. - float drop = spd * friction * gpGlobals->frametime; - - // scale the velocity - float newspeed = spd - drop; - - if (newspeed < 0) - newspeed = 0; - - // Determine proportion of old speed we are using. - newspeed /= spd; - - VectorScale( mv->m_vecVelocity, newspeed, mv->m_vecVelocity ); - - CheckVelocity(); - - TryPlayerMove(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGameMovement::FullNoClipMove( float factor, float maxacceleration ) -{ - Vector wishvel; - Vector forward, right, up; - Vector wishdir; - float wishspeed; - float maxspeed = sv_maxspeed.GetFloat() * factor; - - AngleVectors (mv->m_vecViewAngles, &forward, &right, &up); // Determine movement angles - - if ( mv->m_nButtons & IN_SPEED ) - { - factor /= 2.0f; - } - - // Copy movement amounts - float fmove = mv->m_flForwardMove * factor; - float smove = mv->m_flSideMove * factor; - - VectorNormalize (forward); // Normalize remainder of vectors - VectorNormalize (right); // - - for (int i=0 ; i<3 ; i++) // Determine x and y parts of velocity - wishvel[i] = forward[i]*fmove + right[i]*smove; - wishvel[2] += mv->m_flUpMove * factor; - - VectorCopy (wishvel, wishdir); // Determine maginitude of speed of move - wishspeed = VectorNormalize(wishdir); - - // - // Clamp to server defined max speed - // - if (wishspeed > maxspeed ) - { - VectorScale (wishvel, maxspeed/wishspeed, wishvel); - wishspeed = maxspeed; - } - - if ( maxacceleration > 0.0 ) - { - // Set pmove velocity - Accelerate ( wishdir, wishspeed, maxacceleration ); - - float spd = VectorLength( mv->m_vecVelocity ); - if (spd < 1.0f) - { - mv->m_vecVelocity.Init(); - return; - } - - // Bleed off some speed, but if we have less than the bleed - // threshhold, bleed the theshold amount. - float control = (spd < maxspeed/4.0) ? maxspeed/4.0 : spd; - - float friction = sv_friction.GetFloat() * player->m_surfaceFriction; - - // Add the amount to the drop amount. - float drop = control * friction * gpGlobals->frametime; - - // scale the velocity - float newspeed = spd - drop; - if (newspeed < 0) - newspeed = 0; - - // Determine proportion of old speed we are using. - newspeed /= spd; - VectorScale( mv->m_vecVelocity, newspeed, mv->m_vecVelocity ); - } - else - { - VectorCopy( wishvel, mv->m_vecVelocity ); - } - - // Just move ( don't clip or anything ) - Vector out; - VectorMA( mv->GetAbsOrigin(), gpGlobals->frametime, mv->m_vecVelocity, out ); - mv->SetAbsOrigin( out ); - - // Zero out velocity if in noaccel mode - if ( maxacceleration < 0.0f ) - { - mv->m_vecVelocity.Init(); - } -} - - -//----------------------------------------------------------------------------- -// Checks to see if we should actually jump -//----------------------------------------------------------------------------- -void CGameMovement::PlaySwimSound() -{ - MoveHelper()->StartSound( mv->GetAbsOrigin(), "Player.Swim" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CGameMovement::CheckJumpButton( void ) -{ - if (player->pl.deadflag) - { - mv->m_nOldButtons |= IN_JUMP ; // don't jump again until released - return false; - } - - // See if we are waterjumping. If so, decrement count and return. - if (player->m_flWaterJumpTime) - { - player->m_flWaterJumpTime -= gpGlobals->frametime; - if (player->m_flWaterJumpTime < 0) - player->m_flWaterJumpTime = 0; - - return false; - } - - // If we are in the water most of the way... - if ( player->GetWaterLevel() >= 2 ) - { - // swimming, not jumping - SetGroundEntity( NULL ); - - if(player->GetWaterType() == CONTENTS_WATER) // We move up a certain amount - mv->m_vecVelocity[2] = 100; - else if (player->GetWaterType() == CONTENTS_SLIME) - mv->m_vecVelocity[2] = 80; - - // play swiming sound - if ( player->m_flSwimSoundTime <= 0 ) - { - // Don't play sound again for 1 second - player->m_flSwimSoundTime = 1000; - PlaySwimSound(); - } - - return false; - } - - // No more effect - if (player->GetGroundEntity() == NULL) - { - mv->m_nOldButtons |= IN_JUMP; - return false; // in air, so no effect - } - - // Don't allow jumping when the player is in a stasis field. -#ifndef HL2_EPISODIC - if ( player->m_Local.m_bSlowMovement ) - return false; -#endif - - if ( mv->m_nOldButtons & IN_JUMP ) - return false; // don't pogo stick - - // Cannot jump will in the unduck transition. - if ( player->m_Local.m_bDucking && ( player->GetFlags() & FL_DUCKING ) ) - return false; - - // Still updating the eye position. - if ( player->m_Local.m_flDuckJumpTime > 0.0f ) - return false; - - - // In the air now. - SetGroundEntity( NULL ); - - player->PlayStepSound( (Vector &)mv->GetAbsOrigin(), player->m_pSurfaceData, 1.0, true ); - - MoveHelper()->PlayerSetAnimation( PLAYER_JUMP ); - - float flGroundFactor = 1.0f; - if (player->m_pSurfaceData) - { - flGroundFactor = player->m_pSurfaceData->game.jumpFactor; - } - - float flMul; - if ( g_bMovementOptimizations ) - { -#if defined(HL2_DLL) || defined(HL2_CLIENT_DLL) - Assert( sv_gravity.GetFloat() == 600.0f ); - flMul = 160.0f; // approx. 21 units. -#else - Assert( sv_gravity.GetFloat() == 800.0f ); - flMul = 268.3281572999747f; -#endif - - } - else - { - flMul = sqrt(2 * sv_gravity.GetFloat() * GAMEMOVEMENT_JUMP_HEIGHT); - } - - // Acclerate upward - // If we are ducking... - float startz = mv->m_vecVelocity[2]; - if ( ( player->m_Local.m_bDucking ) || ( player->GetFlags() & FL_DUCKING ) ) - { - // d = 0.5 * g * t^2 - distance traveled with linear accel - // t = sqrt(2.0 * 45 / g) - how long to fall 45 units - // v = g * t - velocity at the end (just invert it to jump up that high) - // v = g * sqrt(2.0 * 45 / g ) - // v^2 = g * g * 2.0 * 45 / g - // v = sqrt( g * 2.0 * 45 ) - mv->m_vecVelocity[2] = flGroundFactor * flMul; // 2 * gravity * height - } - else - { - mv->m_vecVelocity[2] += flGroundFactor * flMul; // 2 * gravity * height - } - - // Add a little forward velocity based on your current forward velocity - if you are not sprinting. -#if defined( HL2_DLL ) || defined( HL2_CLIENT_DLL ) - if ( gpGlobals->maxClients == 1 ) - { - CHLMoveData *pMoveData = ( CHLMoveData* )mv; - Vector vecForward; - AngleVectors( mv->m_vecViewAngles, &vecForward ); - vecForward.z = 0; - VectorNormalize( vecForward ); - - // We give a certain percentage of the current forward movement as a bonus to the jump speed. That bonus is clipped - // to not accumulate over time. - float flSpeedBoostPerc = ( !pMoveData->m_bIsSprinting && !player->m_Local.m_bDucked ) ? 0.5f : 0.1f; - float flSpeedAddition = fabs( mv->m_flForwardMove * flSpeedBoostPerc ); - float flMaxSpeed = mv->m_flMaxSpeed + ( mv->m_flMaxSpeed * flSpeedBoostPerc ); - float flNewSpeed = ( flSpeedAddition + mv->m_vecVelocity.Length2D() ); - - // If we're over the maximum, we want to only boost as much as will get us to the goal speed - if ( flNewSpeed > flMaxSpeed ) - { - flSpeedAddition -= flNewSpeed - flMaxSpeed; - } - - if ( mv->m_flForwardMove < 0.0f ) - flSpeedAddition *= -1.0f; - - // Add it on - VectorAdd( (vecForward*flSpeedAddition), mv->m_vecVelocity, mv->m_vecVelocity ); - } -#endif - - FinishGravity(); - - CheckV( player->CurrentCommandNumber(), "CheckJump", mv->m_vecVelocity ); - - mv->m_outJumpVel.z += mv->m_vecVelocity[2] - startz; - mv->m_outStepHeight += 0.15f; - - // Set jump time. - if ( gpGlobals->maxClients == 1 ) - { - player->m_Local.m_flJumpTime = GAMEMOVEMENT_JUMP_TIME; - player->m_Local.m_bInDuckJump = true; - } - -#if defined( HL2_DLL ) - - if ( xc_uncrouch_on_jump.GetBool() ) - { - // Uncrouch when jumping - if ( player->GetToggledDuckState() ) - { - player->ToggleDuck(); - } - } - -#endif - - // Flag that we jumped. - mv->m_nOldButtons |= IN_JUMP; // don't jump again until released - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGameMovement::FullLadderMove() -{ - CheckWater(); - - // Was jump button pressed? If so, set velocity to 270 away from ladder. - if ( mv->m_nButtons & IN_JUMP ) - { - CheckJumpButton(); - } - else - { - mv->m_nOldButtons &= ~IN_JUMP; - } - - // Perform the move accounting for any base velocity. - VectorAdd (mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity); - TryPlayerMove(); - VectorSubtract (mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CGameMovement::TryPlayerMove( Vector *pFirstDest, trace_t *pFirstTrace ) -{ - int bumpcount, numbumps; - Vector dir; - float d; - int numplanes; - Vector planes[MAX_CLIP_PLANES]; - Vector primal_velocity, original_velocity; - Vector new_velocity; - int i, j; - trace_t pm; - Vector end; - float time_left, allFraction; - int blocked; - - numbumps = 4; // Bump up to four times - - blocked = 0; // Assume not blocked - numplanes = 0; // and not sliding along any planes - - VectorCopy (mv->m_vecVelocity, original_velocity); // Store original velocity - VectorCopy (mv->m_vecVelocity, primal_velocity); - - allFraction = 0; - time_left = gpGlobals->frametime; // Total time for this movement operation. - - new_velocity.Init(); - - for (bumpcount=0 ; bumpcount < numbumps; bumpcount++) - { - if ( mv->m_vecVelocity.Length() == 0.0 ) - break; - - // Assume we can move all the way from the current origin to the - // end point. - VectorMA( mv->GetAbsOrigin(), time_left, mv->m_vecVelocity, end ); - - // See if we can make it from origin to end point. - if ( g_bMovementOptimizations ) - { - // If their velocity Z is 0, then we can avoid an extra trace here during WalkMove. - if ( pFirstDest && end == *pFirstDest ) - pm = *pFirstTrace; - else - { -#if defined( PLAYER_GETTING_STUCK_TESTING ) - trace_t foo; - TracePlayerBBox( mv->GetAbsOrigin(), mv->GetAbsOrigin(), PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, foo ); - if ( foo.startsolid || foo.fraction != 1.0f ) - { - Msg( "bah\n" ); - } -#endif - TracePlayerBBox( mv->GetAbsOrigin(), end, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, pm ); - } - } - else - { - TracePlayerBBox( mv->GetAbsOrigin(), end, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, pm ); - } - - allFraction += pm.fraction; - - // If we started in a solid object, or we were in solid space - // the whole way, zero out our velocity and return that we - // are blocked by floor and wall. - if (pm.allsolid) - { - // entity is trapped in another solid - VectorCopy (vec3_origin, mv->m_vecVelocity); - return 4; - } - - // If we moved some portion of the total distance, then - // copy the end position into the pmove.origin and - // zero the plane counter. - if( pm.fraction > 0 ) - { - if ( numbumps > 0 && pm.fraction == 1 ) - { - // There's a precision issue with terrain tracing that can cause a swept box to successfully trace - // when the end position is stuck in the triangle. Re-run the test with an uswept box to catch that - // case until the bug is fixed. - // If we detect getting stuck, don't allow the movement - trace_t stuck; - TracePlayerBBox( pm.endpos, pm.endpos, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, stuck ); - if ( stuck.startsolid || stuck.fraction != 1.0f ) - { - //Msg( "Player will become stuck!!!\n" ); - VectorCopy (vec3_origin, mv->m_vecVelocity); - break; - } - } - -#if defined( PLAYER_GETTING_STUCK_TESTING ) - trace_t foo; - TracePlayerBBox( pm.endpos, pm.endpos, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, foo ); - if ( foo.startsolid || foo.fraction != 1.0f ) - { - Msg( "Player will become stuck!!!\n" ); - } -#endif - // actually covered some distance - mv->SetAbsOrigin( pm.endpos); - VectorCopy (mv->m_vecVelocity, original_velocity); - numplanes = 0; - } - - // If we covered the entire distance, we are done - // and can return. - if (pm.fraction == 1) - { - break; // moved the entire distance - } - - // Save entity that blocked us (since fraction was < 1.0) - // for contact - // Add it if it's not already in the list!!! - MoveHelper( )->AddToTouched( pm, mv->m_vecVelocity ); - - // If the plane we hit has a high z component in the normal, then - // it's probably a floor - if (pm.plane.normal[2] > 0.7) - { - blocked |= 1; // floor - } - // If the plane has a zero z component in the normal, then it's a - // step or wall - if (!pm.plane.normal[2]) - { - blocked |= 2; // step / wall - } - - // Reduce amount of m_flFrameTime left by total time left * fraction - // that we covered. - time_left -= time_left * pm.fraction; - - // Did we run out of planes to clip against? - if (numplanes >= MAX_CLIP_PLANES) - { - // this shouldn't really happen - // Stop our movement if so. - VectorCopy (vec3_origin, mv->m_vecVelocity); - //Con_DPrintf("Too many planes 4\n"); - - break; - } - - // Set up next clipping plane - VectorCopy (pm.plane.normal, planes[numplanes]); - numplanes++; - - // modify original_velocity so it parallels all of the clip planes - // - - // reflect player velocity - // Only give this a try for first impact plane because you can get yourself stuck in an acute corner by jumping in place - // and pressing forward and nobody was really using this bounce/reflection feature anyway... - if ( numplanes == 1 && - player->GetMoveType() == MOVETYPE_WALK && - player->GetGroundEntity() == NULL ) - { - for ( i = 0; i < numplanes; i++ ) - { - if ( planes[i][2] > 0.7 ) - { - // floor or slope - ClipVelocity( original_velocity, planes[i], new_velocity, 1 ); - VectorCopy( new_velocity, original_velocity ); - } - else - { - ClipVelocity( original_velocity, planes[i], new_velocity, 1.0 + sv_bounce.GetFloat() * (1 - player->m_surfaceFriction) ); - } - } - - VectorCopy( new_velocity, mv->m_vecVelocity ); - VectorCopy( new_velocity, original_velocity ); - } - else - { - for (i=0 ; i < numplanes ; i++) - { - ClipVelocity ( - original_velocity, - planes[i], - mv->m_vecVelocity, - 1); - - for (j=0 ; jm_vecVelocity.Dot(planes[j]) < 0) - break; // not ok - } - if (j == numplanes) // Didn't have to clip, so we're ok - break; - } - - // Did we go all the way through plane set - if (i != numplanes) - { // go along this plane - // pmove.velocity is set in clipping call, no need to set again. - ; - } - else - { // go along the crease - if (numplanes != 2) - { - VectorCopy (vec3_origin, mv->m_vecVelocity); - break; - } - CrossProduct (planes[0], planes[1], dir); - dir.NormalizeInPlace(); - d = dir.Dot(mv->m_vecVelocity); - VectorScale (dir, d, mv->m_vecVelocity ); - } - - // - // if original velocity is against the original velocity, stop dead - // to avoid tiny occilations in sloping corners - // - d = mv->m_vecVelocity.Dot(primal_velocity); - if (d <= 0) - { - //Con_DPrintf("Back\n"); - VectorCopy (vec3_origin, mv->m_vecVelocity); - break; - } - } - } - - if ( allFraction == 0 ) - { - VectorCopy (vec3_origin, mv->m_vecVelocity); - } - - // Check if they slammed into a wall - float fSlamVol = 0.0f; - - float fLateralStoppingAmount = primal_velocity.Length2D() - mv->m_vecVelocity.Length2D(); - if ( fLateralStoppingAmount > PLAYER_MAX_SAFE_FALL_SPEED * 2.0f ) - { - fSlamVol = 1.0f; - } - else if ( fLateralStoppingAmount > PLAYER_MAX_SAFE_FALL_SPEED ) - { - fSlamVol = 0.85f; - } - - PlayerRoughLandingEffects( fSlamVol ); - - return blocked; -} - - -//----------------------------------------------------------------------------- -// Purpose: Determine whether or not the player is on a ladder (physprop or world). -//----------------------------------------------------------------------------- -inline bool CGameMovement::OnLadder( trace_t &trace ) -{ - if ( trace.contents & CONTENTS_LADDER ) - return true; - - IPhysicsSurfaceProps *pPhysProps = MoveHelper( )->GetSurfaceProps(); - if ( pPhysProps ) - { - const surfacedata_t *pSurfaceData = pPhysProps->GetSurfaceData( trace.surface.surfaceProps ); - if ( pSurfaceData ) - { - if ( pSurfaceData->game.climbable != 0 ) - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CGameMovement::LadderMove( void ) -{ - trace_t pm; - bool onFloor; - Vector floor; - Vector wishdir; - Vector end; - - if ( player->GetMoveType() == MOVETYPE_NOCLIP ) - return false; - - if ( !GameHasLadders() ) - return false; - - // If I'm already moving on a ladder, use the previous ladder direction - if ( player->GetMoveType() == MOVETYPE_LADDER ) - { - wishdir = -player->m_vecLadderNormal; - } - else - { - // otherwise, use the direction player is attempting to move - if ( mv->m_flForwardMove || mv->m_flSideMove ) - { - for (int i=0 ; i<3 ; i++) // Determine x and y parts of velocity - wishdir[i] = m_vecForward[i]*mv->m_flForwardMove + m_vecRight[i]*mv->m_flSideMove; - - VectorNormalize(wishdir); - } - else - { - // Player is not attempting to move, no ladder behavior - return false; - } - } - - // wishdir points toward the ladder if any exists - VectorMA( mv->GetAbsOrigin(), LadderDistance(), wishdir, end ); - TracePlayerBBox( mv->GetAbsOrigin(), end, LadderMask(), COLLISION_GROUP_PLAYER_MOVEMENT, pm ); - - // no ladder in that direction, return - if ( pm.fraction == 1.0f || !OnLadder( pm ) ) - return false; - - player->SetMoveType( MOVETYPE_LADDER ); - player->SetMoveCollide( MOVECOLLIDE_DEFAULT ); - - player->m_vecLadderNormal = pm.plane.normal; - - // On ladder, convert movement to be relative to the ladder - - VectorCopy( mv->GetAbsOrigin(), floor ); - floor[2] += GetPlayerMins()[2] - 1; - - if( enginetrace->GetPointContents( floor ) == CONTENTS_SOLID || player->GetGroundEntity() != NULL ) - { - onFloor = true; - } - else - { - onFloor = false; - } - - player->SetGravity( 0 ); - - float climbSpeed = ClimbSpeed(); - - float forwardSpeed = 0, rightSpeed = 0; - if ( mv->m_nButtons & IN_BACK ) - forwardSpeed -= climbSpeed; - - if ( mv->m_nButtons & IN_FORWARD ) - forwardSpeed += climbSpeed; - - if ( mv->m_nButtons & IN_MOVELEFT ) - rightSpeed -= climbSpeed; - - if ( mv->m_nButtons & IN_MOVERIGHT ) - rightSpeed += climbSpeed; - - if ( mv->m_nButtons & IN_JUMP ) - { - player->SetMoveType( MOVETYPE_WALK ); - player->SetMoveCollide( MOVECOLLIDE_DEFAULT ); - - VectorScale( pm.plane.normal, 270, mv->m_vecVelocity ); - } - else - { - if ( forwardSpeed != 0 || rightSpeed != 0 ) - { - Vector velocity, perp, cross, lateral, tmp; - - //ALERT(at_console, "pev %.2f %.2f %.2f - ", - // pev->velocity.x, pev->velocity.y, pev->velocity.z); - // Calculate player's intended velocity - //Vector velocity = (forward * gpGlobals->v_forward) + (right * gpGlobals->v_right); - VectorScale( m_vecForward, forwardSpeed, velocity ); - VectorMA( velocity, rightSpeed, m_vecRight, velocity ); - - // Perpendicular in the ladder plane - VectorCopy( vec3_origin, tmp ); - tmp[2] = 1; - CrossProduct( tmp, pm.plane.normal, perp ); - VectorNormalize( perp ); - - // decompose velocity into ladder plane - float normal = DotProduct( velocity, pm.plane.normal ); - - // This is the velocity into the face of the ladder - VectorScale( pm.plane.normal, normal, cross ); - - // This is the player's additional velocity - VectorSubtract( velocity, cross, lateral ); - - // This turns the velocity into the face of the ladder into velocity that - // is roughly vertically perpendicular to the face of the ladder. - // NOTE: It IS possible to face up and move down or face down and move up - // because the velocity is a sum of the directional velocity and the converted - // velocity through the face of the ladder -- by design. - CrossProduct( pm.plane.normal, perp, tmp ); - VectorMA( lateral, -normal, tmp, mv->m_vecVelocity ); - - if ( onFloor && normal > 0 ) // On ground moving away from the ladder - { - VectorMA( mv->m_vecVelocity, MAX_CLIMB_SPEED, pm.plane.normal, mv->m_vecVelocity ); - } - //pev->velocity = lateral - (CrossProduct( trace.vecPlaneNormal, perp ) * normal); - } - else - { - mv->m_vecVelocity.Init(); - } - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : axis - -// Output : const char -//----------------------------------------------------------------------------- -#if !defined(_STATIC_LINKED) || defined(CLIENT_DLL) -const char *DescribeAxis( int axis ) -{ - static char sz[ 32 ]; - - switch ( axis ) - { - case 0: - Q_strncpy( sz, "X", sizeof( sz ) ); - break; - case 1: - Q_strncpy( sz, "Y", sizeof( sz ) ); - break; - case 2: - default: - Q_strncpy( sz, "Z", sizeof( sz ) ); - break; - } - - return sz; -} -#else -const char *DescribeAxis( int axis ); -#endif - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGameMovement::CheckVelocity( void ) -{ - int i; - - // - // bound velocity - // - - Vector org = mv->GetAbsOrigin(); - - for (i=0; i < 3; i++) - { - // See if it's bogus. - if (IS_NAN(mv->m_vecVelocity[i])) - { - DevMsg( 1, "PM Got a NaN velocity %s\n", DescribeAxis( i ) ); - mv->m_vecVelocity[i] = 0; - } - - if (IS_NAN(org[i])) - { - DevMsg( 1, "PM Got a NaN origin on %s\n", DescribeAxis( i ) ); - org[ i ] = 0; - mv->SetAbsOrigin( org ); - } - - // Bound it. - if (mv->m_vecVelocity[i] > sv_maxvelocity.GetFloat()) - { - DevMsg( 1, "PM Got a velocity too high on %s\n", DescribeAxis( i ) ); - mv->m_vecVelocity[i] = sv_maxvelocity.GetFloat(); - } - else if (mv->m_vecVelocity[i] < -sv_maxvelocity.GetFloat()) - { - DevMsg( 1, "PM Got a velocity too low on %s\n", DescribeAxis( i ) ); - mv->m_vecVelocity[i] = -sv_maxvelocity.GetFloat(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGameMovement::AddGravity( void ) -{ - float ent_gravity; - - if ( player->m_flWaterJumpTime ) - return; - - if (player->GetGravity()) - ent_gravity = player->GetGravity(); - else - ent_gravity = 1.0; - - // Add gravity incorrectly - mv->m_vecVelocity[2] -= (ent_gravity * sv_gravity.GetFloat() * gpGlobals->frametime); - mv->m_vecVelocity[2] += player->GetBaseVelocity()[2] * gpGlobals->frametime; - Vector temp = player->GetBaseVelocity(); - temp[2] = 0; - player->SetBaseVelocity( temp ); - - CheckVelocity(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : push - -// Output : trace_t -//----------------------------------------------------------------------------- -void CGameMovement::PushEntity( Vector& push, trace_t *pTrace ) -{ - Vector end; - - VectorAdd (mv->GetAbsOrigin(), push, end); - TracePlayerBBox( mv->GetAbsOrigin(), end, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, *pTrace ); - mv->SetAbsOrigin( pTrace->endpos ); - - // So we can run impact function afterwards. - // If - if ( pTrace->fraction < 1.0 && !pTrace->allsolid ) - { - MoveHelper( )->AddToTouched( *pTrace, mv->m_vecVelocity ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : in - -// normal - -// out - -// overbounce - -// Output : int -//----------------------------------------------------------------------------- -int CGameMovement::ClipVelocity( Vector& in, Vector& normal, Vector& out, float overbounce ) -{ - float backoff; - float change; - float angle; - int i, blocked; - - angle = normal[ 2 ]; - - blocked = 0x00; // Assume unblocked. - if (angle > 0) // If the plane that is blocking us has a positive z component, then assume it's a floor. - blocked |= 0x01; // - if (!angle) // If the plane has no Z, it is vertical (wall/step) - blocked |= 0x02; // - - - // Determine how far along plane to slide based on incoming direction. - backoff = DotProduct (in, normal) * overbounce; - - for (i=0 ; i<3 ; i++) - { - change = normal[i]*backoff; - out[i] = in[i] - change; - } - - // iterate once to make sure we aren't still moving through the plane - float adjust = DotProduct( out, normal ); - if( adjust < 0.0f ) - { - out -= ( normal * adjust ); -// Msg( "Adjustment = %lf\n", adjust ); - } - - // Return blocking flags. - return blocked; -} - -//----------------------------------------------------------------------------- -// Purpose: Computes roll angle for a certain movement direction and velocity -// Input : angles - -// velocity - -// rollangle - -// rollspeed - -// Output : float -//----------------------------------------------------------------------------- -float CGameMovement::CalcRoll ( const QAngle &angles, const Vector &velocity, float rollangle, float rollspeed ) -{ - float sign; - float side; - float value; - Vector forward, right, up; - - AngleVectors (angles, &forward, &right, &up); - - side = DotProduct (velocity, right); - sign = side < 0 ? -1 : 1; - side = fabs(side); - value = rollangle; - if (side < rollspeed) - { - side = side * value / rollspeed; - } - else - { - side = value; - } - return side*sign; -} - -#define CHECKSTUCK_MINTIME 0.05 // Don't check again too quickly. - -#if !defined(_STATIC_LINKED) || defined(CLIENT_DLL) -Vector rgv3tStuckTable[54]; -#else -extern Vector rgv3tStuckTable[54]; -#endif - -#if !defined(_STATIC_LINKED) || defined(CLIENT_DLL) -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CreateStuckTable( void ) -{ - float x, y, z; - size_t idx; - int i; - float zi[3]; - static int firsttime = 1; - - if ( !firsttime ) - return; - - firsttime = 0; - - memset(rgv3tStuckTable, 0, sizeof(rgv3tStuckTable)); - - idx = 0; - // Little Moves. - x = y = 0; - // Z moves - for (z = -0.125 ; z <= 0.125 ; z += 0.125) - { - rgv3tStuckTable[idx][0] = x; - rgv3tStuckTable[idx][1] = y; - rgv3tStuckTable[idx][2] = z; - idx++; - } - x = z = 0; - // Y moves - for (y = -0.125 ; y <= 0.125 ; y += 0.125) - { - rgv3tStuckTable[idx][0] = x; - rgv3tStuckTable[idx][1] = y; - rgv3tStuckTable[idx][2] = z; - idx++; - } - y = z = 0; - // X moves - for (x = -0.125 ; x <= 0.125 ; x += 0.125) - { - rgv3tStuckTable[idx][0] = x; - rgv3tStuckTable[idx][1] = y; - rgv3tStuckTable[idx][2] = z; - idx++; - } - - // Remaining multi axis nudges. - for ( x = - 0.125; x <= 0.125; x += 0.250 ) - { - for ( y = - 0.125; y <= 0.125; y += 0.250 ) - { - for ( z = - 0.125; z <= 0.125; z += 0.250 ) - { - rgv3tStuckTable[idx][0] = x; - rgv3tStuckTable[idx][1] = y; - rgv3tStuckTable[idx][2] = z; - idx++; - } - } - } - - // Big Moves. - x = y = 0; - zi[0] = 0.0f; - zi[1] = 1.0f; - zi[2] = 6.0f; - - for (i = 0; i < 3; i++) - { - // Z moves - z = zi[i]; - rgv3tStuckTable[idx][0] = x; - rgv3tStuckTable[idx][1] = y; - rgv3tStuckTable[idx][2] = z; - idx++; - } - - x = z = 0; - - // Y moves - for (y = -2.0f ; y <= 2.0f ; y += 2.0) - { - rgv3tStuckTable[idx][0] = x; - rgv3tStuckTable[idx][1] = y; - rgv3tStuckTable[idx][2] = z; - idx++; - } - y = z = 0; - // X moves - for (x = -2.0f ; x <= 2.0f ; x += 2.0f) - { - rgv3tStuckTable[idx][0] = x; - rgv3tStuckTable[idx][1] = y; - rgv3tStuckTable[idx][2] = z; - idx++; - } - - // Remaining multi axis nudges. - for (i = 0 ; i < 3; i++) - { - z = zi[i]; - - for (x = -2.0f ; x <= 2.0f ; x += 2.0f) - { - for (y = -2.0f ; y <= 2.0f ; y += 2.0) - { - rgv3tStuckTable[idx][0] = x; - rgv3tStuckTable[idx][1] = y; - rgv3tStuckTable[idx][2] = z; - idx++; - } - } - } - Assert( idx < sizeof(rgv3tStuckTable)/sizeof(rgv3tStuckTable[0])); -} -#else -extern void CreateStuckTable( void ); -#endif - -//----------------------------------------------------------------------------- -// Purpose: -// Input : nIndex - -// server - -// offset - -// Output : int -//----------------------------------------------------------------------------- -int GetRandomStuckOffsets( CBasePlayer *pPlayer, Vector& offset) -{ - // Last time we did a full - int idx; - idx = pPlayer->m_StuckLast++; - - VectorCopy(rgv3tStuckTable[idx % 54], offset); - - return (idx % 54); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : nIndex - -// server - -//----------------------------------------------------------------------------- -void ResetStuckOffsets( CBasePlayer *pPlayer ) -{ - pPlayer->m_StuckLast = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &input - -// Output : int -//----------------------------------------------------------------------------- -int CGameMovement::CheckStuck( void ) -{ - Vector base; - Vector offset; - Vector test; - EntityHandle_t hitent; - int idx; - float fTime; - trace_t traceresult; - - CreateStuckTable(); - - hitent = TestPlayerPosition( mv->GetAbsOrigin(), COLLISION_GROUP_PLAYER_MOVEMENT, traceresult ); - if ( hitent == INVALID_ENTITY_HANDLE ) - { - ResetStuckOffsets( player ); - return 0; - } - - // Deal with stuckness... -#ifndef _LINUX - if ( developer.GetBool() ) - { - bool isServer = player->IsServer(); - engine->Con_NPrintf( isServer, "%s stuck on object %i/%s", - isServer ? "server" : "client", - hitent.GetEntryIndex(), MoveHelper()->GetName(hitent) ); - } -#endif - - VectorCopy( mv->GetAbsOrigin(), base ); - - // - // Deal with precision error in network. - // - // World or BSP model - if ( !player->IsServer() ) - { - if ( MoveHelper()->IsWorldEntity( hitent ) ) - { - int nReps = 0; - ResetStuckOffsets( player ); - do - { - GetRandomStuckOffsets( player, offset ); - VectorAdd( base, offset, test ); - - if ( TestPlayerPosition( test, COLLISION_GROUP_PLAYER_MOVEMENT, traceresult ) == INVALID_ENTITY_HANDLE ) - { - ResetStuckOffsets( player ); - mv->SetAbsOrigin( test ); - return 0; - } - nReps++; - } while (nReps < 54); - } - } - - // Only an issue on the client. - idx = player->IsServer() ? 0 : 1; - - fTime = engine->Time(); - // Too soon? - if ( m_flStuckCheckTime[ player->entindex() ][ idx ] >= fTime - CHECKSTUCK_MINTIME ) - { - return 1; - } - m_flStuckCheckTime[ player->entindex() ][ idx ] = fTime; - - MoveHelper( )->AddToTouched( traceresult, mv->m_vecVelocity ); - GetRandomStuckOffsets( player, offset ); - VectorAdd( base, offset, test ); - - if ( TestPlayerPosition( test, COLLISION_GROUP_PLAYER_MOVEMENT, traceresult ) == INVALID_ENTITY_HANDLE) - { - ResetStuckOffsets( player ); - mv->SetAbsOrigin( test ); - return 0; - } - - return 1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : bool -//----------------------------------------------------------------------------- -bool CGameMovement::InWater( void ) -{ - return ( player->GetWaterLevel() > WL_Feet ); -} - - -void CGameMovement::ResetGetPointContentsCache() -{ - for ( int slot = 0; slot < MAX_PC_CACHE_SLOTS; ++slot ) - { - for ( int i = 0; i < MAX_PLAYERS; ++i ) - { - m_CachedGetPointContents[ i ][ slot ] = -9999; - } - } -} - - -int CGameMovement::GetPointContentsCached( const Vector &point, int slot ) -{ - if ( g_bMovementOptimizations ) - { - Assert( player ); - Assert( slot >= 0 && slot < MAX_PC_CACHE_SLOTS ); - - int idx = player->entindex() - 1; - - if ( m_CachedGetPointContents[ idx ][ slot ] == -9999 || point.DistToSqr( m_CachedGetPointContentsPoint[ idx ][ slot ] ) > 1 ) - { - m_CachedGetPointContents[ idx ][ slot ] = enginetrace->GetPointContents ( point ); - m_CachedGetPointContentsPoint[ idx ][ slot ] = point; - } - - return m_CachedGetPointContents[ idx ][ slot ]; - } - else - { - return enginetrace->GetPointContents ( point ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &input - -// Output : bool -//----------------------------------------------------------------------------- -bool CGameMovement::CheckWater( void ) -{ - Vector point; - int cont; - - // Pick a spot just above the players feet. - point[0] = mv->GetAbsOrigin()[0] + (GetPlayerMins()[0] + GetPlayerMaxs()[0]) * 0.5; - point[1] = mv->GetAbsOrigin()[1] + (GetPlayerMins()[1] + GetPlayerMaxs()[1]) * 0.5; - point[2] = mv->GetAbsOrigin()[2] + GetPlayerMins()[2] + 1; - - // Assume that we are not in water at all. - player->SetWaterLevel( WL_NotInWater ); - player->SetWaterType( CONTENTS_EMPTY ); - - // Grab point contents. - cont = GetPointContentsCached( point, 0 ); - - // Are we under water? (not solid and not empty?) - if ( cont & MASK_WATER ) - { - // Set water type - player->SetWaterType( cont ); - - // We are at least at level one - player->SetWaterLevel( WL_Feet ); - - // Now check a point that is at the player hull midpoint. - point[2] = mv->GetAbsOrigin()[2] + (GetPlayerMins()[2] + GetPlayerMaxs()[2])*0.5; - cont = GetPointContentsCached( point, 1 ); - // If that point is also under water... - if ( cont & MASK_WATER ) - { - // Set a higher water level. - player->SetWaterLevel( WL_Waist ); - - // Now check the eye position. (view_ofs is relative to the origin) - point[2] = mv->GetAbsOrigin()[2] + player->GetViewOffset()[2]; - cont = GetPointContentsCached( point, 2 ); - if ( cont & MASK_WATER ) - player->SetWaterLevel( WL_Eyes ); // In over our eyes - } - - // Adjust velocity based on water current, if any. - if ( cont & MASK_CURRENT ) - { - Vector v; - VectorClear(v); - if ( cont & CONTENTS_CURRENT_0 ) - v[0] += 1; - if ( cont & CONTENTS_CURRENT_90 ) - v[1] += 1; - if ( cont & CONTENTS_CURRENT_180 ) - v[0] -= 1; - if ( cont & CONTENTS_CURRENT_270 ) - v[1] -= 1; - if ( cont & CONTENTS_CURRENT_UP ) - v[2] += 1; - if ( cont & CONTENTS_CURRENT_DOWN ) - v[2] -= 1; - - // BUGBUG -- this depends on the value of an unspecified enumerated type - // The deeper we are, the stronger the current. - Vector temp; - VectorMA( player->GetBaseVelocity(), 50.0*player->GetWaterLevel(), v, temp ); - player->SetBaseVelocity( temp ); - } - } - - // if we just transitioned from not in water to in water, record the time it happened - if ( ( WL_NotInWater == m_nOldWaterLevel ) && ( player->GetWaterLevel() > WL_NotInWater ) ) - { - m_flWaterEntryTime = gpGlobals->curtime; - } - - return ( player->GetWaterLevel() > WL_Feet ); -} - -void CGameMovement::SetGroundEntity( trace_t *pm ) -{ - CBaseEntity *newGround = pm ? pm->m_pEnt : NULL; - - CBaseEntity *oldGround = player->GetGroundEntity(); - Vector vecBaseVelocity = player->GetBaseVelocity(); - - if ( !oldGround && newGround ) - { - // Subtract ground velocity at instant we hit ground jumping - vecBaseVelocity -= newGround->GetAbsVelocity(); - vecBaseVelocity.z = newGround->GetAbsVelocity().z; - } - else if ( oldGround && !newGround ) - { - // Add in ground velocity at instant we started jumping - vecBaseVelocity += oldGround->GetAbsVelocity(); - vecBaseVelocity.z = oldGround->GetAbsVelocity().z; - } - - player->SetBaseVelocity( vecBaseVelocity ); - player->SetGroundEntity( newGround ); - - // If we are on something... - - if ( newGround ) - { - CategorizeGroundSurface( *pm ); - - // Then we are not in water jump sequence - player->m_flWaterJumpTime = 0; - - // Standing on an entity other than the world, so signal that we are touching something. - if ( !pm->DidHitWorld() ) - { - MoveHelper()->AddToTouched( *pm, mv->m_vecVelocity ); - } - } -} - -//----------------------------------------------------------------------------- -// Traces the player's collision bounds in quadrants, looking for a plane that -// can be stood upon (normal's z >= 0.7f). Regardless of success or failure, -// replace the fraction and endpos with the original ones, so we don't try to -// move the player down to the new floor and get stuck on a leaning wall that -// the original trace hit first. -//----------------------------------------------------------------------------- -void TracePlayerBBoxForGround( const Vector& start, const Vector& end, const Vector& minsSrc, - const Vector& maxsSrc, IHandleEntity *player, unsigned int fMask, - int collisionGroup, trace_t& pm ) -{ - VPROF( "TracePlayerBBoxForGround" ); - - Ray_t ray; - Vector mins, maxs; - - float fraction = pm.fraction; - Vector endpos = pm.endpos; - - // Check the -x, -y quadrant - mins = minsSrc; - maxs.Init( MIN( 0, maxsSrc.x ), MIN( 0, maxsSrc.y ), maxsSrc.z ); - ray.Init( start, end, mins, maxs ); - UTIL_TraceRay( ray, fMask, player, collisionGroup, &pm ); - if ( pm.m_pEnt && pm.plane.normal[2] >= 0.7) - { - pm.fraction = fraction; - pm.endpos = endpos; - return; - } - - // Check the +x, +y quadrant - mins.Init( MAX( 0, minsSrc.x ), MAX( 0, minsSrc.y ), minsSrc.z ); - maxs = maxsSrc; - ray.Init( start, end, mins, maxs ); - UTIL_TraceRay( ray, fMask, player, collisionGroup, &pm ); - if ( pm.m_pEnt && pm.plane.normal[2] >= 0.7) - { - pm.fraction = fraction; - pm.endpos = endpos; - return; - } - - // Check the -x, +y quadrant - mins.Init( minsSrc.x, MAX( 0, minsSrc.y ), minsSrc.z ); - maxs.Init( MIN( 0, maxsSrc.x ), maxsSrc.y, maxsSrc.z ); - ray.Init( start, end, mins, maxs ); - UTIL_TraceRay( ray, fMask, player, collisionGroup, &pm ); - if ( pm.m_pEnt && pm.plane.normal[2] >= 0.7) - { - pm.fraction = fraction; - pm.endpos = endpos; - return; - } - - // Check the +x, -y quadrant - mins.Init( MAX( 0, minsSrc.x ), minsSrc.y, minsSrc.z ); - maxs.Init( maxsSrc.x, MIN( 0, maxsSrc.y ), maxsSrc.z ); - ray.Init( start, end, mins, maxs ); - UTIL_TraceRay( ray, fMask, player, collisionGroup, &pm ); - if ( pm.m_pEnt && pm.plane.normal[2] >= 0.7) - { - pm.fraction = fraction; - pm.endpos = endpos; - return; - } - - pm.fraction = fraction; - pm.endpos = endpos; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &input - -//----------------------------------------------------------------------------- -void CGameMovement::CategorizePosition( void ) -{ - Vector point; - trace_t pm; - - // Reset this each time we-recategorize, otherwise we have bogus friction when we jump into water and plunge downward really quickly - player->m_surfaceFriction = 1.0f; - - // if the player hull point one unit down is solid, the player - // is on ground - - // see if standing on something solid - - // Doing this before we move may introduce a potential latency in water detection, but - // doing it after can get us stuck on the bottom in water if the amount we move up - // is less than the 1 pixel 'threshold' we're about to snap to. Also, we'll call - // this several times per frame, so we really need to avoid sticking to the bottom of - // water on each call, and the converse case will correct itself if called twice. - CheckWater(); - - // observers don't have a ground entity - if ( player->IsObserver() ) - return; - - float flOffset = 2.0f; - - point[0] = mv->GetAbsOrigin()[0]; - point[1] = mv->GetAbsOrigin()[1]; - point[2] = mv->GetAbsOrigin()[2] - flOffset; - - Vector bumpOrigin; - bumpOrigin = mv->GetAbsOrigin(); - - // Shooting up really fast. Definitely not on ground. - // On ladder moving up, so not on ground either - // NOTE: 145 is a jump. -#define NON_JUMP_VELOCITY 140.0f - - float zvel = mv->m_vecVelocity[2]; - bool bMovingUp = zvel > 0.0f; - bool bMovingUpRapidly = zvel > NON_JUMP_VELOCITY; - float flGroundEntityVelZ = 0.0f; - if ( bMovingUpRapidly ) - { - // Tracker 73219, 75878: ywb 8/2/07 - // After save/restore (and maybe at other times), we can get a case where we were saved on a lift and - // after restore we'll have a high local velocity due to the lift making our abs velocity appear high. - // We need to account for standing on a moving ground object in that case in order to determine if we really - // are moving away from the object we are standing on at too rapid a speed. Note that CheckJump already sets - // ground entity to NULL, so this wouldn't have any effect unless we are moving up rapidly not from the jump button. - CBaseEntity *ground = player->GetGroundEntity(); - if ( ground ) - { - flGroundEntityVelZ = ground->GetAbsVelocity().z; - bMovingUpRapidly = ( zvel - flGroundEntityVelZ ) > NON_JUMP_VELOCITY; - } - } - - // Was on ground, but now suddenly am not - if ( bMovingUpRapidly || - ( bMovingUp && player->GetMoveType() == MOVETYPE_LADDER ) ) - { - SetGroundEntity( NULL ); - } - else - { - // Try and move down. - TracePlayerBBox( bumpOrigin, point, MASK_PLAYERSOLID, COLLISION_GROUP_PLAYER_MOVEMENT, pm ); - - // Was on ground, but now suddenly am not. If we hit a steep plane, we are not on ground - if ( !pm.m_pEnt || pm.plane.normal[2] < 0.7 ) - { - // Test four sub-boxes, to see if any of them would have found shallower slope we could actually stand on - TracePlayerBBoxForGround( bumpOrigin, point, GetPlayerMins(), GetPlayerMaxs(), mv->m_nPlayerHandle.Get(), MASK_PLAYERSOLID, COLLISION_GROUP_PLAYER_MOVEMENT, pm ); - if ( !pm.m_pEnt || pm.plane.normal[2] < 0.7 ) - { - SetGroundEntity( NULL ); - // probably want to add a check for a +z velocity too! - if ( ( mv->m_vecVelocity.z > 0.0f ) && - ( player->GetMoveType() != MOVETYPE_NOCLIP ) ) - { - player->m_surfaceFriction = 0.25f; - } - } - else - { - SetGroundEntity( &pm ); - } - } - else - { - SetGroundEntity( &pm ); // Otherwise, point to index of ent under us. - } - -#ifndef CLIENT_DLL - - //Adrian: vehicle code handles for us. - if ( player->IsInAVehicle() == false ) - { - // If our gamematerial has changed, tell any player surface triggers that are watching - IPhysicsSurfaceProps *physprops = MoveHelper()->GetSurfaceProps(); - surfacedata_t *pSurfaceProp = physprops->GetSurfaceData( pm.surface.surfaceProps ); - char cCurrGameMaterial = pSurfaceProp->game.material; - if ( !player->GetGroundEntity() ) - { - cCurrGameMaterial = 0; - } - - // Changed? - if ( player->m_chPreviousTextureType != cCurrGameMaterial ) - { - CEnvPlayerSurfaceTrigger::SetPlayerSurface( player, cCurrGameMaterial ); - } - - player->m_chPreviousTextureType = cCurrGameMaterial; - } -#endif - } -} - -//----------------------------------------------------------------------------- -// Purpose: Determine if the player has hit the ground while falling, apply -// damage, and play the appropriate impact sound. -//----------------------------------------------------------------------------- -void CGameMovement::CheckFalling( void ) -{ - if ( player->GetGroundEntity() != NULL && - !IsDead() && - player->m_Local.m_flFallVelocity >= PLAYER_FALL_PUNCH_THRESHOLD ) - { - bool bAlive = true; - float fvol = 0.5; - - if ( player->GetWaterLevel() > 0 ) - { - // They landed in water. - } - else - { - // Scale it down if we landed on something that's floating... - if ( player->GetGroundEntity()->IsFloating() ) - { - player->m_Local.m_flFallVelocity -= PLAYER_LAND_ON_FLOATING_OBJECT; - } - - // - // They hit the ground. - // - if( player->GetGroundEntity()->GetAbsVelocity().z < 0.0f ) - { - // Player landed on a descending object. Subtract the velocity of the ground entity. - player->m_Local.m_flFallVelocity += player->GetGroundEntity()->GetAbsVelocity().z; - player->m_Local.m_flFallVelocity = MAX( 0.1f, player->m_Local.m_flFallVelocity ); - } - - if ( player->m_Local.m_flFallVelocity > PLAYER_MAX_SAFE_FALL_SPEED ) - { - // - // If they hit the ground going this fast they may take damage (and die). - // - bAlive = MoveHelper( )->PlayerFallingDamage(); - fvol = 1.0; - } - else if ( player->m_Local.m_flFallVelocity > PLAYER_MAX_SAFE_FALL_SPEED / 2 ) - { - fvol = 0.85; - } - else if ( player->m_Local.m_flFallVelocity < PLAYER_MIN_BOUNCE_SPEED ) - { - fvol = 0; - } - } - - PlayerRoughLandingEffects( fvol ); - - if (bAlive) - { - MoveHelper( )->PlayerSetAnimation( PLAYER_WALK ); - } - } - - // - // Clear the fall velocity so the impact doesn't happen again. - // - if ( player->GetGroundEntity() != NULL ) - { - player->m_Local.m_flFallVelocity = 0; - } -} - -void CGameMovement::PlayerRoughLandingEffects( float fvol ) -{ - if ( fvol > 0.0 ) - { - // - // Play landing sound right away. - player->m_flStepSoundTime = 400; - - // Play step sound for current texture. - player->PlayStepSound( (Vector &)mv->GetAbsOrigin(), player->m_pSurfaceData, fvol, true ); - - // - // Knock the screen around a little bit, temporary effect. - // - player->m_Local.m_vecPunchAngle.Set( ROLL, player->m_Local.m_flFallVelocity * 0.013 ); - - if ( player->m_Local.m_vecPunchAngle[PITCH] > 8 ) - { - player->m_Local.m_vecPunchAngle.Set( PITCH, 8 ); - } - -#if !defined( CLIENT_DLL ) - player->RumbleEffect( ( fvol > 0.85f ) ? ( RUMBLE_FALL_LONG ) : ( RUMBLE_FALL_SHORT ), 0, RUMBLE_FLAGS_NONE ); -#endif - } -} - -//----------------------------------------------------------------------------- -// Purpose: Use for ease-in, ease-out style interpolation (accel/decel) Used by ducking code. -// Input : value - -// scale - -// Output : float -//----------------------------------------------------------------------------- -float CGameMovement::SplineFraction( float value, float scale ) -{ - float valueSquared; - - value = scale * value; - valueSquared = value * value; - - // Nice little ease-in, ease-out spline-like curve - return 3 * valueSquared - 2 * valueSquared * value; -} - -//----------------------------------------------------------------------------- -// Purpose: Determine if crouch/uncrouch caused player to get stuck in world -// Input : direction - -//----------------------------------------------------------------------------- -void CGameMovement::FixPlayerCrouchStuck( bool upward ) -{ - EntityHandle_t hitent; - int i; - Vector test; - trace_t dummy; - - int direction = upward ? 1 : 0; - - hitent = TestPlayerPosition( mv->GetAbsOrigin(), COLLISION_GROUP_PLAYER_MOVEMENT, dummy ); - if (hitent == INVALID_ENTITY_HANDLE ) - return; - - VectorCopy( mv->GetAbsOrigin(), test ); - for ( i = 0; i < 36; i++ ) - { - Vector org = mv->GetAbsOrigin(); - org.z += direction; - mv->SetAbsOrigin( org ); - hitent = TestPlayerPosition( mv->GetAbsOrigin(), COLLISION_GROUP_PLAYER_MOVEMENT, dummy ); - if (hitent == INVALID_ENTITY_HANDLE ) - return; - } - - mv->SetAbsOrigin( test ); // Failed -} - -bool CGameMovement::CanUnduck() -{ - int i; - trace_t trace; - Vector newOrigin; - - VectorCopy( mv->GetAbsOrigin(), newOrigin ); - - if ( player->GetGroundEntity() != NULL ) - { - for ( i = 0; i < 3; i++ ) - { - newOrigin[i] += ( VEC_DUCK_HULL_MIN[i] - VEC_HULL_MIN[i] ); - } - } - else - { - // If in air an letting go of crouch, make sure we can offset origin to make - // up for uncrouching - Vector hullSizeNormal = VEC_HULL_MAX - VEC_HULL_MIN; - Vector hullSizeCrouch = VEC_DUCK_HULL_MAX - VEC_DUCK_HULL_MIN; - Vector viewDelta = ( hullSizeNormal - hullSizeCrouch ); - viewDelta.Negate(); - VectorAdd( newOrigin, viewDelta, newOrigin ); - } - - bool saveducked = player->m_Local.m_bDucked; - player->m_Local.m_bDucked = false; - TracePlayerBBox( mv->GetAbsOrigin(), newOrigin, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, trace ); - player->m_Local.m_bDucked = saveducked; - if ( trace.startsolid || ( trace.fraction != 1.0f ) ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Stop ducking -//----------------------------------------------------------------------------- -void CGameMovement::FinishUnDuck( void ) -{ - int i; - trace_t trace; - Vector newOrigin; - - VectorCopy( mv->GetAbsOrigin(), newOrigin ); - - if ( player->GetGroundEntity() != NULL ) - { - for ( i = 0; i < 3; i++ ) - { - newOrigin[i] += ( VEC_DUCK_HULL_MIN[i] - VEC_HULL_MIN[i] ); - } - } - else - { - // If in air an letting go of crouch, make sure we can offset origin to make - // up for uncrouching - Vector hullSizeNormal = VEC_HULL_MAX - VEC_HULL_MIN; - Vector hullSizeCrouch = VEC_DUCK_HULL_MAX - VEC_DUCK_HULL_MIN; - Vector viewDelta = ( hullSizeNormal - hullSizeCrouch ); - viewDelta.Negate(); - VectorAdd( newOrigin, viewDelta, newOrigin ); - } - - player->m_Local.m_bDucked = false; - player->RemoveFlag( FL_DUCKING ); - player->m_Local.m_bDucking = false; - player->m_Local.m_bInDuckJump = false; - player->SetViewOffset( GetPlayerViewOffset( false ) ); - player->m_Local.m_flDucktime = 0; - - mv->SetAbsOrigin( newOrigin ); - - // Recategorize position since ducking can change origin - CategorizePosition(); -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -void CGameMovement::UpdateDuckJumpEyeOffset( void ) -{ - if ( player->m_Local.m_flDuckJumpTime != 0.0f ) - { - float flDuckMilliseconds = MAX( 0.0f, GAMEMOVEMENT_DUCK_TIME - ( float )player->m_Local.m_flDuckJumpTime ); - float flDuckSeconds = flDuckMilliseconds / GAMEMOVEMENT_DUCK_TIME; - if ( flDuckSeconds > TIME_TO_UNDUCK ) - { - player->m_Local.m_flDuckJumpTime = 0.0f; - SetDuckedEyeOffset( 0.0f ); - } - else - { - float flDuckFraction = SimpleSpline( 1.0f - ( flDuckSeconds / TIME_TO_UNDUCK ) ); - SetDuckedEyeOffset( flDuckFraction ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGameMovement::FinishUnDuckJump( trace_t &trace ) -{ - Vector vecNewOrigin; - VectorCopy( mv->GetAbsOrigin(), vecNewOrigin ); - - // Up for uncrouching. - Vector hullSizeNormal = VEC_HULL_MAX - VEC_HULL_MIN; - Vector hullSizeCrouch = VEC_DUCK_HULL_MAX - VEC_DUCK_HULL_MIN; - Vector viewDelta = ( hullSizeNormal - hullSizeCrouch ); - - float flDeltaZ = viewDelta.z; - viewDelta.z *= trace.fraction; - flDeltaZ -= viewDelta.z; - - player->RemoveFlag( FL_DUCKING ); - player->m_Local.m_bDucked = false; - player->m_Local.m_bDucking = false; - player->m_Local.m_bInDuckJump = false; - player->m_Local.m_flDucktime = 0.0f; - player->m_Local.m_flDuckJumpTime = 0.0f; - player->m_Local.m_flJumpTime = 0.0f; - - Vector vecViewOffset = GetPlayerViewOffset( false ); - vecViewOffset.z -= flDeltaZ; - player->SetViewOffset( vecViewOffset ); - - VectorSubtract( vecNewOrigin, viewDelta, vecNewOrigin ); - mv->SetAbsOrigin( vecNewOrigin ); - - // Recategorize position since ducking can change origin - CategorizePosition(); -} - -//----------------------------------------------------------------------------- -// Purpose: Finish ducking -//----------------------------------------------------------------------------- -void CGameMovement::FinishDuck( void ) -{ - int i; - - player->AddFlag( FL_DUCKING ); - player->m_Local.m_bDucked = true; - player->m_Local.m_bDucking = false; - - player->SetViewOffset( GetPlayerViewOffset( true ) ); - - // HACKHACK - Fudge for collision bug - no time to fix this properly - if ( player->GetGroundEntity() != NULL ) - { - for ( i = 0; i < 3; i++ ) - { - Vector org = mv->GetAbsOrigin(); - org[ i ]-= ( VEC_DUCK_HULL_MIN[i] - VEC_HULL_MIN[i] ); - mv->SetAbsOrigin( org ); - } - } - else - { - Vector hullSizeNormal = VEC_HULL_MAX - VEC_HULL_MIN; - Vector hullSizeCrouch = VEC_DUCK_HULL_MAX - VEC_DUCK_HULL_MIN; - Vector viewDelta = ( hullSizeNormal - hullSizeCrouch ); - Vector out; - VectorAdd( mv->GetAbsOrigin(), viewDelta, out ); - mv->SetAbsOrigin( out ); - } - - // See if we are stuck? - FixPlayerCrouchStuck( true ); - - // Recategorize position since ducking can change origin - CategorizePosition(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGameMovement::StartUnDuckJump( void ) -{ - player->AddFlag( FL_DUCKING ); - player->m_Local.m_bDucked = true; - player->m_Local.m_bDucking = false; - - player->SetViewOffset( GetPlayerViewOffset( true ) ); - - Vector hullSizeNormal = VEC_HULL_MAX - VEC_HULL_MIN; - Vector hullSizeCrouch = VEC_DUCK_HULL_MAX - VEC_DUCK_HULL_MIN; - Vector viewDelta = ( hullSizeNormal - hullSizeCrouch ); - Vector out; - VectorAdd( mv->GetAbsOrigin(), viewDelta, out ); - mv->SetAbsOrigin( out ); - - // See if we are stuck? - FixPlayerCrouchStuck( true ); - - // Recategorize position since ducking can change origin - CategorizePosition(); -} - -// -//----------------------------------------------------------------------------- -// Purpose: -// Input : duckFraction - -//----------------------------------------------------------------------------- -void CGameMovement::SetDuckedEyeOffset( float duckFraction ) -{ - Vector vDuckHullMin = GetPlayerMins( true ); - Vector vStandHullMin = GetPlayerMins( false ); - - float fMore = ( vDuckHullMin.z - vStandHullMin.z ); - - Vector vecDuckViewOffset = GetPlayerViewOffset( true ); - Vector vecStandViewOffset = GetPlayerViewOffset( false ); - Vector temp = player->GetViewOffset(); - temp.z = ( ( vecDuckViewOffset.z - fMore ) * duckFraction ) + - ( vecStandViewOffset.z * ( 1 - duckFraction ) ); - player->SetViewOffset( temp ); -} - -//----------------------------------------------------------------------------- -// Purpose: Crop the speed of the player when ducking and on the ground. -// Input: bInDuck - is the player already ducking -// bInAir - is the player in air -// NOTE: Only crop player speed once. -//----------------------------------------------------------------------------- -void CGameMovement::HandleDuckingSpeedCrop( void ) -{ - if ( !m_bSpeedCropped && ( player->GetFlags() & FL_DUCKING ) && ( player->GetGroundEntity() != NULL ) ) - { - float frac = 0.33333333f; - mv->m_flForwardMove *= frac; - mv->m_flSideMove *= frac; - mv->m_flUpMove *= frac; - m_bSpeedCropped = true; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Check to see if we are in a situation where we can unduck jump. -//----------------------------------------------------------------------------- -bool CGameMovement::CanUnDuckJump( trace_t &trace ) -{ - // Trace down to the stand position and see if we can stand. - Vector vecEnd( mv->GetAbsOrigin() ); - vecEnd.z -= 36.0f; // This will have to change if bounding hull change! - TracePlayerBBox( mv->GetAbsOrigin(), vecEnd, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, trace ); - if ( trace.fraction < 1.0f ) - { - // Find the endpoint. - vecEnd.z = mv->GetAbsOrigin().z + ( -36.0f * trace.fraction ); - - // Test a normal hull. - trace_t traceUp; - bool bWasDucked = player->m_Local.m_bDucked; - player->m_Local.m_bDucked = false; - TracePlayerBBox( vecEnd, vecEnd, PlayerSolidMask(), COLLISION_GROUP_PLAYER_MOVEMENT, traceUp ); - player->m_Local.m_bDucked = bWasDucked; - if ( !traceUp.startsolid ) - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: See if duck button is pressed and do the appropriate things -//----------------------------------------------------------------------------- -void CGameMovement::Duck( void ) -{ - int buttonsChanged = ( mv->m_nOldButtons ^ mv->m_nButtons ); // These buttons have changed this frame - int buttonsPressed = buttonsChanged & mv->m_nButtons; // The changed ones still down are "pressed" - int buttonsReleased = buttonsChanged & mv->m_nOldButtons; // The changed ones which were previously down are "released" - - // Check to see if we are in the air. - bool bInAir = ( player->GetGroundEntity() == NULL ); - bool bInDuck = ( player->GetFlags() & FL_DUCKING ) ? true : false; - bool bDuckJump = ( player->m_Local.m_flJumpTime > 0.0f ); - bool bDuckJumpTime = ( player->m_Local.m_flDuckJumpTime > 0.0f ); - - if ( mv->m_nButtons & IN_DUCK ) - { - mv->m_nOldButtons |= IN_DUCK; - } - else - { - mv->m_nOldButtons &= ~IN_DUCK; - } - - // Handle death. - if ( IsDead() ) - return; - - // Slow down ducked players. - HandleDuckingSpeedCrop(); - - // If the player is holding down the duck button, the player is in duck transition, ducking, or duck-jumping. - if ( ( mv->m_nButtons & IN_DUCK ) || player->m_Local.m_bDucking || bInDuck || bDuckJump ) - { - // DUCK - if ( ( mv->m_nButtons & IN_DUCK ) || bDuckJump ) - { -// XBOX SERVER ONLY -#if !defined(CLIENT_DLL) - if ( IsX360() && buttonsPressed & IN_DUCK ) - { - // Hinting logic - if ( player->GetToggledDuckState() && player->m_nNumCrouches < NUM_CROUCH_HINTS ) - { - UTIL_HudHintText( player, "#Valve_Hint_Crouch" ); - player->m_nNumCrouches++; - } - } -#endif - // Have the duck button pressed, but the player currently isn't in the duck position. - if ( ( buttonsPressed & IN_DUCK ) && !bInDuck && !bDuckJump && !bDuckJumpTime ) - { - player->m_Local.m_flDucktime = GAMEMOVEMENT_DUCK_TIME; - player->m_Local.m_bDucking = true; - } - - // The player is in duck transition and not duck-jumping. - if ( player->m_Local.m_bDucking && !bDuckJump && !bDuckJumpTime ) - { - float flDuckMilliseconds = MAX( 0.0f, GAMEMOVEMENT_DUCK_TIME - ( float )player->m_Local.m_flDucktime ); - float flDuckSeconds = flDuckMilliseconds * 0.001f; - - // Finish in duck transition when transition time is over, in "duck", in air. - if ( ( flDuckSeconds > TIME_TO_DUCK ) || bInDuck || bInAir ) - { - FinishDuck(); - } - else - { - // Calc parametric time - float flDuckFraction = SimpleSpline( flDuckSeconds / TIME_TO_DUCK ); - SetDuckedEyeOffset( flDuckFraction ); - } - } - - if ( bDuckJump ) - { - // Make the bounding box small immediately. - if ( !bInDuck ) - { - StartUnDuckJump(); - } - else - { - // Check for a crouch override. - if ( !( mv->m_nButtons & IN_DUCK ) ) - { - trace_t trace; - if ( CanUnDuckJump( trace ) ) - { - FinishUnDuckJump( trace ); - player->m_Local.m_flDuckJumpTime = ( GAMEMOVEMENT_TIME_TO_UNDUCK * ( 1.0f - trace.fraction ) ) + GAMEMOVEMENT_TIME_TO_UNDUCK_INV; - } - } - } - } - } - // UNDUCK (or attempt to...) - else - { - if ( player->m_Local.m_bInDuckJump ) - { - // Check for a crouch override. - if ( !( mv->m_nButtons & IN_DUCK ) ) - { - trace_t trace; - if ( CanUnDuckJump( trace ) ) - { - FinishUnDuckJump( trace ); - - if ( trace.fraction < 1.0f ) - { - player->m_Local.m_flDuckJumpTime = ( GAMEMOVEMENT_TIME_TO_UNDUCK * ( 1.0f - trace.fraction ) ) + GAMEMOVEMENT_TIME_TO_UNDUCK_INV; - } - } - } - else - { - player->m_Local.m_bInDuckJump = false; - } - } - - if ( bDuckJumpTime ) - return; - - // Try to unduck unless automovement is not allowed - // NOTE: When not onground, you can always unduck - if ( player->m_Local.m_bAllowAutoMovement || bInAir || player->m_Local.m_bDucking ) - { - // We released the duck button, we aren't in "duck" and we are not in the air - start unduck transition. - if ( ( buttonsReleased & IN_DUCK ) ) - { - if ( bInDuck && !bDuckJump ) - { - player->m_Local.m_flDucktime = GAMEMOVEMENT_DUCK_TIME; - } - else if ( player->m_Local.m_bDucking && !player->m_Local.m_bDucked ) - { - // Invert time if release before fully ducked!!! - float unduckMilliseconds = 1000.0f * TIME_TO_UNDUCK; - float duckMilliseconds = 1000.0f * TIME_TO_DUCK; - float elapsedMilliseconds = GAMEMOVEMENT_DUCK_TIME - player->m_Local.m_flDucktime; - - float fracDucked = elapsedMilliseconds / duckMilliseconds; - float remainingUnduckMilliseconds = fracDucked * unduckMilliseconds; - - player->m_Local.m_flDucktime = GAMEMOVEMENT_DUCK_TIME - unduckMilliseconds + remainingUnduckMilliseconds; - } - } - - - // Check to see if we are capable of unducking. - if ( CanUnduck() ) - { - // or unducking - if ( ( player->m_Local.m_bDucking || player->m_Local.m_bDucked ) ) - { - float flDuckMilliseconds = MAX( 0.0f, GAMEMOVEMENT_DUCK_TIME - (float)player->m_Local.m_flDucktime ); - float flDuckSeconds = flDuckMilliseconds * 0.001f; - - // Finish ducking immediately if duck time is over or not on ground - if ( flDuckSeconds > TIME_TO_UNDUCK || ( bInAir && !bDuckJump ) ) - { - FinishUnDuck(); - } - else - { - // Calc parametric time - float flDuckFraction = SimpleSpline( 1.0f - ( flDuckSeconds / TIME_TO_UNDUCK ) ); - SetDuckedEyeOffset( flDuckFraction ); - player->m_Local.m_bDucking = true; - } - } - } - else - { - // Still under something where we can't unduck, so make sure we reset this timer so - // that we'll unduck once we exit the tunnel, etc. - if ( player->m_Local.m_flDucktime != GAMEMOVEMENT_DUCK_TIME ) - { - SetDuckedEyeOffset(1.0f); - player->m_Local.m_flDucktime = GAMEMOVEMENT_DUCK_TIME; - player->m_Local.m_bDucked = true; - player->m_Local.m_bDucking = false; - player->AddFlag( FL_DUCKING ); - } - } - } - } - } - // HACK: (jimd 5/25/2006) we have a reoccuring bug (#50063 in Tracker) where the player's - // view height gets left at the ducked height while the player is standing, but we haven't - // been able to repro it to find the cause. It may be fixed now due to a change I'm - // also making in UpdateDuckJumpEyeOffset but just in case, this code will sense the - // problem and restore the eye to the proper position. It doesn't smooth the transition, - // but it is preferable to leaving the player's view too low. - // - // If the player is still alive and not an observer, check to make sure that - // his view height is at the standing height. - else if ( !IsDead() && !player->IsObserver() && !player->IsInAVehicle() ) - { - if ( ( player->m_Local.m_flDuckJumpTime == 0.0f ) && ( fabs(player->GetViewOffset().z - GetPlayerViewOffset( false ).z) > 0.1 ) ) - { - // we should rarely ever get here, so assert so a coder knows when it happens - Assert(0); - DevMsg( 1, "Restoring player view height\n" ); - - // set the eye height to the non-ducked height - SetDuckedEyeOffset(0.0f); - } - } -} - -static ConVar sv_optimizedmovement( "sv_optimizedmovement", "1", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGameMovement::PlayerMove( void ) -{ - VPROF( "CGameMovement::PlayerMove" ); - - CheckParameters(); - - // clear output applied velocity - mv->m_outWishVel.Init(); - mv->m_outJumpVel.Init(); - - MoveHelper( )->ResetTouchList(); // Assume we don't touch anything - - ReduceTimers(); - - AngleVectors (mv->m_vecViewAngles, &m_vecForward, &m_vecRight, &m_vecUp ); // Determine movement angles - - // Always try and unstick us unless we are using a couple of the movement modes - if ( player->GetMoveType() != MOVETYPE_NOCLIP && - player->GetMoveType() != MOVETYPE_NONE && - player->GetMoveType() != MOVETYPE_ISOMETRIC && - player->GetMoveType() != MOVETYPE_OBSERVER && - !player->pl.deadflag ) - { - if ( CheckInterval( STUCK ) ) - { - if ( CheckStuck() ) - { - // Can't move, we're stuck - return; - } - } - } - - // Now that we are "unstuck", see where we are (player->GetWaterLevel() and type, player->GetGroundEntity()). - if ( player->GetMoveType() != MOVETYPE_WALK || - mv->m_bGameCodeMovedPlayer || - !sv_optimizedmovement.GetBool() ) - { - CategorizePosition(); - } - else - { - if ( mv->m_vecVelocity.z > 250.0f ) - { - SetGroundEntity( NULL ); - } - } - - // Store off the starting water level - m_nOldWaterLevel = player->GetWaterLevel(); - - // If we are not on ground, store off how fast we are moving down - if ( player->GetGroundEntity() == NULL ) - { - player->m_Local.m_flFallVelocity = -mv->m_vecVelocity[ 2 ]; - } - - m_nOnLadder = 0; - - player->UpdateStepSound( player->m_pSurfaceData, mv->GetAbsOrigin(), mv->m_vecVelocity ); - - UpdateDuckJumpEyeOffset(); - Duck(); - - // Don't run ladder code if dead on on a train - if ( !player->pl.deadflag && !(player->GetFlags() & FL_ONTRAIN) ) - { - // If was not on a ladder now, but was on one before, - // get off of the ladder - - // TODO: this causes lots of weirdness. - //bool bCheckLadder = CheckInterval( LADDER ); - //if ( bCheckLadder || player->GetMoveType() == MOVETYPE_LADDER ) - { - if ( !LadderMove() && - ( player->GetMoveType() == MOVETYPE_LADDER ) ) - { - // Clear ladder stuff unless player is dead or riding a train - // It will be reset immediately again next frame if necessary - player->SetMoveType( MOVETYPE_WALK ); - player->SetMoveCollide( MOVECOLLIDE_DEFAULT ); - } - } - } - - // Handle movement modes. - switch (player->GetMoveType()) - { - case MOVETYPE_NONE: - break; - - case MOVETYPE_NOCLIP: - FullNoClipMove( sv_noclipspeed.GetFloat(), sv_noclipaccelerate.GetFloat() ); - break; - - case MOVETYPE_FLY: - case MOVETYPE_FLYGRAVITY: - FullTossMove(); - break; - - case MOVETYPE_LADDER: - FullLadderMove(); - break; - - case MOVETYPE_WALK: - FullWalkMove(); - break; - - case MOVETYPE_ISOMETRIC: - //IsometricMove(); - // Could also try: FullTossMove(); - FullWalkMove(); - break; - - case MOVETYPE_OBSERVER: - FullObserverMove(); // clips against world&players - break; - - default: - DevMsg( 1, "Bogus pmove player movetype %i on (%i) 0=cl 1=sv\n", player->GetMoveType(), player->IsServer()); - break; - } -} - - -//----------------------------------------------------------------------------- -// Performs the collision resolution for fliers. -//----------------------------------------------------------------------------- -void CGameMovement::PerformFlyCollisionResolution( trace_t &pm, Vector &move ) -{ - Vector base; - float vel; - float backoff; - - switch (player->GetMoveCollide()) - { - case MOVECOLLIDE_FLY_CUSTOM: - // Do nothing; the velocity should have been modified by touch - // FIXME: It seems wrong for touch to modify velocity - // given that it can be called in a number of places - // where collision resolution do *not* in fact occur - - // Should this ever occur for players!? - Assert(0); - break; - - case MOVECOLLIDE_FLY_BOUNCE: - case MOVECOLLIDE_DEFAULT: - { - if (player->GetMoveCollide() == MOVECOLLIDE_FLY_BOUNCE) - backoff = 2.0 - player->m_surfaceFriction; - else - backoff = 1; - - ClipVelocity (mv->m_vecVelocity, pm.plane.normal, mv->m_vecVelocity, backoff); - } - break; - - default: - // Invalid collide type! - Assert(0); - break; - } - - // stop if on ground - if (pm.plane.normal[2] > 0.7) - { - base.Init(); - if (mv->m_vecVelocity[2] < sv_gravity.GetFloat() * gpGlobals->frametime) - { - // we're rolling on the ground, add static friction. - SetGroundEntity( &pm ); - mv->m_vecVelocity[2] = 0; - } - - vel = DotProduct( mv->m_vecVelocity, mv->m_vecVelocity ); - - // Con_DPrintf("%f %f: %.0f %.0f %.0f\n", vel, trace.fraction, ent->velocity[0], ent->velocity[1], ent->velocity[2] ); - - if (vel < (30 * 30) || (player->GetMoveCollide() != MOVECOLLIDE_FLY_BOUNCE)) - { - SetGroundEntity( &pm ); - mv->m_vecVelocity.Init(); - } - else - { - VectorScale (mv->m_vecVelocity, (1.0 - pm.fraction) * gpGlobals->frametime * 0.9, move); - PushEntity( move, &pm ); - } - VectorSubtract( mv->m_vecVelocity, base, mv->m_vecVelocity ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CGameMovement::FullTossMove( void ) -{ - trace_t pm; - Vector move; - - CheckWater(); - - // add velocity if player is moving - if ( (mv->m_flForwardMove != 0.0f) || (mv->m_flSideMove != 0.0f) || (mv->m_flUpMove != 0.0f)) - { - Vector forward, right, up; - float fmove, smove; - Vector wishdir, wishvel; - float wishspeed; - int i; - - AngleVectors (mv->m_vecViewAngles, &forward, &right, &up); // Determine movement angles - - // Copy movement amounts - fmove = mv->m_flForwardMove; - smove = mv->m_flSideMove; - - VectorNormalize (forward); // Normalize remainder of vectors. - VectorNormalize (right); // - - for (i=0 ; i<3 ; i++) // Determine x and y parts of velocity - wishvel[i] = forward[i]*fmove + right[i]*smove; - - wishvel[2] += mv->m_flUpMove; - - VectorCopy (wishvel, wishdir); // Determine maginitude of speed of move - wishspeed = VectorNormalize(wishdir); - - // - // Clamp to server defined max speed - // - if (wishspeed > mv->m_flMaxSpeed) - { - VectorScale (wishvel, mv->m_flMaxSpeed/wishspeed, wishvel); - wishspeed = mv->m_flMaxSpeed; - } - - // Set pmove velocity - Accelerate ( wishdir, wishspeed, sv_accelerate.GetFloat() ); - } - - if ( mv->m_vecVelocity[2] > 0 ) - { - SetGroundEntity( NULL ); - } - - // If on ground and not moving, return. - if ( player->GetGroundEntity() != NULL ) - { - if (VectorCompare(player->GetBaseVelocity(), vec3_origin) && - VectorCompare(mv->m_vecVelocity, vec3_origin)) - return; - } - - CheckVelocity(); - - // add gravity - if ( player->GetMoveType() == MOVETYPE_FLYGRAVITY ) - { - AddGravity(); - } - - // move origin - // Base velocity is not properly accounted for since this entity will move again after the bounce without - // taking it into account - VectorAdd (mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity); - - CheckVelocity(); - - VectorScale (mv->m_vecVelocity, gpGlobals->frametime, move); - VectorSubtract (mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity); - - PushEntity( move, &pm ); // Should this clear basevelocity - - CheckVelocity(); - - if (pm.allsolid) - { - // entity is trapped in another solid - SetGroundEntity( &pm ); - mv->m_vecVelocity.Init(); - return; - } - - if (pm.fraction != 1) - { - PerformFlyCollisionResolution( pm, move ); - } - - // check for in water - CheckWater(); -} - -//----------------------------------------------------------------------------- -// Purpose: TF2 commander mode movement logic -//----------------------------------------------------------------------------- - -#ifdef _MSC_VER -#pragma warning (disable : 4701) -#endif - -void CGameMovement::IsometricMove( void ) -{ - int i; - Vector wishvel; - float fmove, smove; - Vector forward, right, up; - - AngleVectors (mv->m_vecViewAngles, &forward, &right, &up); // Determine movement angles - - // Copy movement amounts - fmove = mv->m_flForwardMove; - smove = mv->m_flSideMove; - - // No up / down movement - forward[2] = 0; - right[2] = 0; - - VectorNormalize (forward); // Normalize remainder of vectors - VectorNormalize (right); // - - for (i=0 ; i<3 ; i++) // Determine x and y parts of velocity - wishvel[i] = forward[i]*fmove + right[i]*smove; - //wishvel[2] += mv->m_flUpMove; - - Vector out; - VectorMA (mv->GetAbsOrigin(), gpGlobals->frametime, wishvel, out ); - mv->SetAbsOrigin( out ); - - // Zero out the velocity so that we don't accumulate a huge downward velocity from - // gravity, etc. - mv->m_vecVelocity.Init(); -} - -#ifdef _MSC_VER -#pragma warning (default : 4701) -#endif - -bool CGameMovement::GameHasLadders() const -{ - return true; -} diff --git a/game/shared/gamemovement.h b/game/shared/gamemovement.h deleted file mode 100644 index 1abf5a386..000000000 --- a/game/shared/gamemovement.h +++ /dev/null @@ -1,284 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// -#if !defined( GAMEMOVEMENT_H ) -#define GAMEMOVEMENT_H -#ifdef _WIN32 -#pragma once -#endif - -#include "igamemovement.h" -#include "cmodel.h" -#include "tier0/vprof.h" - -#define CTEXTURESMAX 512 // max number of textures loaded -#define CBTEXTURENAMEMAX 13 // only load first n chars of name - -#define GAMEMOVEMENT_DUCK_TIME 1000.0f // ms -#define GAMEMOVEMENT_JUMP_TIME 510.0f // ms approx - based on the 21 unit height jump -#define GAMEMOVEMENT_JUMP_HEIGHT 21.0f // units -#define GAMEMOVEMENT_TIME_TO_UNDUCK ( TIME_TO_UNDUCK * 1000.0f ) // ms -#define GAMEMOVEMENT_TIME_TO_UNDUCK_INV ( GAMEMOVEMENT_DUCK_TIME - GAMEMOVEMENT_TIME_TO_UNDUCK ) - -struct surfacedata_t; - -class CBasePlayer; - -class CGameMovement : public IGameMovement -{ -public: - DECLARE_CLASS_NOBASE( CGameMovement ); - - CGameMovement( void ); - virtual ~CGameMovement( void ); - - virtual void ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMove ); - - virtual void StartTrackPredictionErrors( CBasePlayer *pPlayer ); - virtual void FinishTrackPredictionErrors( CBasePlayer *pPlayer ); - virtual void DiffPrint( char const *fmt, ... ); - virtual const Vector& GetPlayerMins( bool ducked ) const; - virtual const Vector& GetPlayerMaxs( bool ducked ) const; - virtual const Vector& GetPlayerViewOffset( bool ducked ) const; - -// For sanity checking getting stuck on CMoveData::SetAbsOrigin - virtual void TracePlayerBBox( const Vector& start, const Vector& end, unsigned int fMask, int collisionGroup, trace_t& pm ); -#define BRUSH_ONLY true - virtual unsigned int PlayerSolidMask( bool brushOnly = false ); ///< returns the solid mask for the given player, so bots can have a more-restrictive set - CBasePlayer *player; - CMoveData *GetMoveData() { return mv; } -protected: - // Input/Output for this movement - CMoveData *mv; - - int m_nOldWaterLevel; - float m_flWaterEntryTime; - int m_nOnLadder; - - Vector m_vecForward; - Vector m_vecRight; - Vector m_vecUp; - - - // Does most of the player movement logic. - // Returns with origin, angles, and velocity modified in place. - // were contacted during the move. - virtual void PlayerMove( void ); - - // Set ground data, etc. - void FinishMove( void ); - - virtual float CalcRoll( const QAngle &angles, const Vector &velocity, float rollangle, float rollspeed ); - - virtual void DecayPunchAngle( void ); - - virtual void CheckWaterJump(void ); - - virtual void WaterMove( void ); - - void WaterJump( void ); - - // Handles both ground friction and water friction - void Friction( void ); - - virtual void AirAccelerate( Vector& wishdir, float wishspeed, float accel ); - - virtual void AirMove( void ); - - virtual bool CanAccelerate(); - virtual void Accelerate( Vector& wishdir, float wishspeed, float accel); - - // Only used by players. Moves along the ground when player is a MOVETYPE_WALK. - virtual void WalkMove( void ); - - // Try to keep a walking player on the ground when running down slopes etc - void StayOnGround( void ); - - // Handle MOVETYPE_WALK. - virtual void FullWalkMove(); - - // Implement this if you want to know when the player collides during OnPlayerMove - virtual void OnTryPlayerMoveCollision( trace_t &tr ) {} - - virtual const Vector& GetPlayerMins( void ) const; // uses local player - virtual const Vector& GetPlayerMaxs( void ) const; // uses local player - - typedef enum - { - GROUND = 0, - STUCK, - LADDER - } IntervalType_t; - - virtual int GetCheckInterval( IntervalType_t type ); - - // Useful for things that happen periodically. This lets things happen on the specified interval, but - // spaces the events onto different frames for different players so they don't all hit their spikes - // simultaneously. - bool CheckInterval( IntervalType_t type ); - - - // Decompoosed gravity - void StartGravity( void ); - void FinishGravity( void ); - - // Apply normal ( undecomposed ) gravity - void AddGravity( void ); - - // Handle movement in noclip mode. - void FullNoClipMove( float factor, float maxacceleration ); - - // Returns true if he started a jump (ie: should he play the jump animation)? - virtual bool CheckJumpButton( void ); // Overridden by each game. - - // Dead player flying through air., e.g. - virtual void FullTossMove( void ); - - // Player is a Observer chasing another player - void FullObserverMove( void ); - - // Handle movement when in MOVETYPE_LADDER mode. - virtual void FullLadderMove(); - - // The basic solid body movement clip that slides along multiple planes - virtual int TryPlayerMove( Vector *pFirstDest=NULL, trace_t *pFirstTrace=NULL ); - - virtual bool LadderMove( void ); - virtual bool OnLadder( trace_t &trace ); - virtual float LadderDistance( void ) const { return 2.0f; } ///< Returns the distance a player can be from a ladder and still attach to it - virtual unsigned int LadderMask( void ) const { return MASK_PLAYERSOLID; } - virtual float ClimbSpeed( void ) const { return MAX_CLIMB_SPEED; } - virtual float LadderLateralMultiplier( void ) const { return 1.0f; } - - // See if the player has a bogus velocity value. - void CheckVelocity( void ); - - // Does not change the entities velocity at all - void PushEntity( Vector& push, trace_t *pTrace ); - - // Slide off of the impacting object - // returns the blocked flags: - // 0x01 == floor - // 0x02 == step / wall - int ClipVelocity( Vector& in, Vector& normal, Vector& out, float overbounce ); - - // If pmove.origin is in a solid position, - // try nudging slightly on all axis to - // allow for the cut precision of the net coordinates -#ifdef PORTAL - virtual -#endif - int CheckStuck( void ); - - // Check if the point is in water. - // Sets refWaterLevel and refWaterType appropriately. - // If in water, applies current to baseVelocity, and returns true. - virtual bool CheckWater( void ); - - // Determine if player is in water, on ground, etc. - virtual void CategorizePosition( void ); - - virtual void CheckParameters( void ); - - virtual void ReduceTimers( void ); - - virtual void CheckFalling( void ); - - virtual void PlayerRoughLandingEffects( float fvol ); - - void PlayerWaterSounds( void ); - - void ResetGetPointContentsCache(); - int GetPointContentsCached( const Vector &point, int slot ); - - // Ducking - virtual void Duck( void ); - virtual void HandleDuckingSpeedCrop(); - virtual void FinishUnDuck( void ); - virtual void FinishDuck( void ); - virtual bool CanUnduck(); - void UpdateDuckJumpEyeOffset( void ); - bool CanUnDuckJump( trace_t &trace ); - void StartUnDuckJump( void ); - void FinishUnDuckJump( trace_t &trace ); - void SetDuckedEyeOffset( float duckFraction ); - void FixPlayerCrouchStuck( bool moveup ); - - float SplineFraction( float value, float scale ); - - void CategorizeGroundSurface( trace_t &pm ); - - bool InWater( void ); - - // Commander view movement - void IsometricMove( void ); - - // Traces the player bbox as it is swept from start to end - virtual CBaseHandle TestPlayerPosition( const Vector& pos, int collisionGroup, trace_t& pm ); - - // Checks to see if we should actually jump - void PlaySwimSound(); - - bool IsDead( void ) const; - - // Figures out how the constraint should slow us down - float ComputeConstraintSpeedFactor( void ); - - virtual void SetGroundEntity( trace_t *pm ); - - virtual void StepMove( Vector &vecDestination, trace_t &trace ); - -protected: - - // Performs the collision resolution for fliers. - void PerformFlyCollisionResolution( trace_t &pm, Vector &move ); - - virtual bool GameHasLadders() const; - - enum - { - // eyes, waist, feet points (since they are all deterministic - MAX_PC_CACHE_SLOTS = 3, - }; - - // Cache used to remove redundant calls to GetPointContents(). - int m_CachedGetPointContents[ MAX_PLAYERS ][ MAX_PC_CACHE_SLOTS ]; - Vector m_CachedGetPointContentsPoint[ MAX_PLAYERS ][ MAX_PC_CACHE_SLOTS ]; - - Vector m_vecProximityMins; // Used to be globals in sv_user.cpp. - Vector m_vecProximityMaxs; - - float m_fFrameTime; - -//private: - bool m_bSpeedCropped; - - float m_flStuckCheckTime[MAX_PLAYERS+1][2]; // Last time we did a full test - - // special function for teleport-with-duck for episodic -#ifdef HL2_EPISODIC -public: - void ForceDuck( void ); - -#endif -}; - - -//----------------------------------------------------------------------------- -// Traces player movement + position -//----------------------------------------------------------------------------- -inline void CGameMovement::TracePlayerBBox( const Vector& start, const Vector& end, unsigned int fMask, int collisionGroup, trace_t& pm ) -{ - VPROF( "CGameMovement::TracePlayerBBox" ); - - Ray_t ray; - ray.Init( start, end, GetPlayerMins(), GetPlayerMaxs() ); - UTIL_TraceRay( ray, fMask, mv->m_nPlayerHandle.Get(), collisionGroup, &pm ); -} - -#endif // GAMEMOVEMENT_H diff --git a/game/shared/gamerules.cpp b/game/shared/gamerules.cpp deleted file mode 100644 index 015c635dc..000000000 --- a/game/shared/gamerules.cpp +++ /dev/null @@ -1,826 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "gamerules.h" -#include "ammodef.h" -#include "tier0/vprof.h" -#include "KeyValues.h" -#include "achievementmgr.h" - -#ifdef CLIENT_DLL - - #include "usermessages.h" - -#else - - #include "player.h" - #include "teamplay_gamerules.h" - #include "game.h" - #include "entitylist.h" - #include "basecombatweapon.h" - #include "voice_gamemgr.h" - #include "globalstate.h" - #include "player_resource.h" -#include "GameStats.h" - -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -ConVar g_Language( "g_Language", "0", FCVAR_REPLICATED ); -ConVar sk_autoaim_mode( "sk_autoaim_mode", "1", FCVAR_ARCHIVE | FCVAR_REPLICATED ); - -static CViewVectors g_DefaultViewVectors( - Vector( 0, 0, 64 ), //VEC_VIEW (m_vView) - - Vector(-16, -16, 0 ), //VEC_HULL_MIN (m_vHullMin) - Vector( 16, 16, 72 ), //VEC_HULL_MAX (m_vHullMax) - - Vector(-16, -16, 0 ), //VEC_DUCK_HULL_MIN (m_vDuckHullMin) - Vector( 16, 16, 36 ), //VEC_DUCK_HULL_MAX (m_vDuckHullMax) - Vector( 0, 0, 28 ), //VEC_DUCK_VIEW (m_vDuckView) - - Vector(-10, -10, -10 ), //VEC_OBS_HULL_MIN (m_vObsHullMin) - Vector( 10, 10, 10 ), //VEC_OBS_HULL_MAX (m_vObsHullMax) - - Vector( 0, 0, 14 ) //VEC_DEAD_VIEWHEIGHT (m_vDeadViewHeight) -); - - -// ------------------------------------------------------------------------------------ // -// CGameRulesProxy implementation. -// ------------------------------------------------------------------------------------ // - -CGameRulesProxy *CGameRulesProxy::s_pGameRulesProxy = NULL; - -IMPLEMENT_NETWORKCLASS_ALIASED( GameRulesProxy, DT_GameRulesProxy ) - -// Don't send any of the CBaseEntity stuff.. -BEGIN_NETWORK_TABLE_NOBASE( CGameRulesProxy, DT_GameRulesProxy ) -END_NETWORK_TABLE() - - -CGameRulesProxy::CGameRulesProxy() -{ - // allow map placed proxy entities to overwrite the static one - if ( s_pGameRulesProxy ) - { -#ifndef CLIENT_DLL - UTIL_Remove( s_pGameRulesProxy ); -#endif - s_pGameRulesProxy = NULL; - } - s_pGameRulesProxy = this; -} - -CGameRulesProxy::~CGameRulesProxy() -{ - if ( s_pGameRulesProxy == this ) - { - s_pGameRulesProxy = NULL; - } -} - -int CGameRulesProxy::UpdateTransmitState() -{ -#ifndef CLIENT_DLL - // ALWAYS transmit to all clients. - return SetTransmitState( FL_EDICT_ALWAYS ); -#else - return 0; -#endif - -} - -void CGameRulesProxy::NotifyNetworkStateChanged() -{ - if ( s_pGameRulesProxy ) - s_pGameRulesProxy->NetworkStateChanged(); -} - - - -ConVar old_radius_damage( "old_radiusdamage", "0.0", FCVAR_REPLICATED ); - -#ifdef CLIENT_DLL //{ - -bool CGameRules::IsBonusChallengeTimeBased( void ) -{ - return true; -} - -CGameRules::CGameRules() : CAutoGameSystemPerFrame( "CGameRules" ) -{ - Assert( !g_pGameRules ); - g_pGameRules = this; -} - -#else //}{ - -// In tf_gamerules.cpp or hl_gamerules.cpp. -extern IVoiceGameMgrHelper *g_pVoiceGameMgrHelper; - - -CGameRules* g_pGameRules = NULL; -extern bool g_fGameOver; - -//----------------------------------------------------------------------------- -// constructor, destructor -//----------------------------------------------------------------------------- -CGameRules::CGameRules() : CAutoGameSystemPerFrame( "CGameRules" ) -{ - Assert( !g_pGameRules ); - g_pGameRules = this; - - GetVoiceGameMgr()->Init( g_pVoiceGameMgrHelper, gpGlobals->maxClients ); - ClearMultiDamage(); -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if the specified player can carry any more of the ammo type -//----------------------------------------------------------------------------- -bool CGameRules::CanHaveAmmo( CBaseCombatCharacter *pPlayer, int iAmmoIndex ) -{ - if ( iAmmoIndex > -1 ) - { - // Get the max carrying capacity for this ammo - int iMaxCarry = GetAmmoDef()->MaxCarry( iAmmoIndex ); - - // Does the player have room for more of this type of ammo? - if ( pPlayer->GetAmmoCount( iAmmoIndex ) < iMaxCarry ) - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if the specified player can carry any more of the ammo type -//----------------------------------------------------------------------------- -bool CGameRules::CanHaveAmmo( CBaseCombatCharacter *pPlayer, const char *szName ) -{ - return CanHaveAmmo( pPlayer, GetAmmoDef()->Index(szName) ); -} - -//========================================================= -//========================================================= -CBaseEntity *CGameRules::GetPlayerSpawnSpot( CBasePlayer *pPlayer ) -{ - CBaseEntity *pSpawnSpot = pPlayer->EntSelectSpawnPoint(); - Assert( pSpawnSpot ); - - pPlayer->SetLocalOrigin( pSpawnSpot->GetAbsOrigin() + Vector(0,0,1) ); - pPlayer->SetAbsVelocity( vec3_origin ); - pPlayer->SetLocalAngles( pSpawnSpot->GetLocalAngles() ); - pPlayer->m_Local.m_vecPunchAngle = vec3_angle; - pPlayer->m_Local.m_vecPunchAngleVel = vec3_angle; - pPlayer->SnapEyeAngles( pSpawnSpot->GetLocalAngles() ); - - return pSpawnSpot; -} - -// checks if the spot is clear of players -bool CGameRules::IsSpawnPointValid( CBaseEntity *pSpot, CBasePlayer *pPlayer ) -{ - CBaseEntity *ent = NULL; - - if ( !pSpot->IsTriggered( pPlayer ) ) - { - return false; - } - - for ( CEntitySphereQuery sphere( pSpot->GetAbsOrigin(), 128 ); (ent = sphere.GetCurrentEntity()) != NULL; sphere.NextEntity() ) - { - // if ent is a client, don't spawn on 'em - if ( ent->IsPlayer() && ent != pPlayer ) - return false; - } - - return true; -} - -//========================================================= -//========================================================= -bool CGameRules::CanHavePlayerItem( CBasePlayer *pPlayer, CBaseCombatWeapon *pWeapon ) -{ -/* - if ( pWeapon->m_pszAmmo1 ) - { - if ( !CanHaveAmmo( pPlayer, pWeapon->m_iPrimaryAmmoType ) ) - { - // we can't carry anymore ammo for this gun. We can only - // have the gun if we aren't already carrying one of this type - if ( pPlayer->Weapon_OwnsThisType( pWeapon ) ) - { - return FALSE; - } - } - } - else - { - // weapon doesn't use ammo, don't take another if you already have it. - if ( pPlayer->Weapon_OwnsThisType( pWeapon ) ) - { - return FALSE; - } - } -*/ - // note: will fall through to here if GetItemInfo doesn't fill the struct! - return TRUE; -} - -//========================================================= -// load the SkillData struct with the proper values based on the skill level. -//========================================================= -void CGameRules::RefreshSkillData ( bool forceUpdate ) -{ -#ifndef CLIENT_DLL - if ( !forceUpdate ) - { - if ( GlobalEntity_IsInTable( "skill.cfg" ) ) - return; - } - GlobalEntity_Add( "skill.cfg", STRING(gpGlobals->mapname), GLOBAL_ON ); - char szExec[256]; - - ConVarRef skill( "skill" ); - - SetSkillLevel( skill.IsValid() ? skill.GetInt() : 1 ); - -#ifdef HL2_DLL - // HL2 current only uses one skill config file that represents MEDIUM skill level and - // synthesizes EASY and HARD. (sjb) - Q_snprintf( szExec,sizeof(szExec), "exec skill_manifest.cfg\n" ); - - engine->ServerCommand( szExec ); - engine->ServerExecute(); -#else - Q_snprintf( szExec,sizeof(szExec), "exec skill%d.cfg\n", GetSkillLevel() ); - - engine->ServerCommand( szExec ); - engine->ServerExecute(); -#endif // HL2_DLL -#endif // CLIENT_DLL -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool IsExplosionTraceBlocked( trace_t *ptr ) -{ - if( ptr->DidHitWorld() ) - return true; - - if( ptr->m_pEnt == NULL ) - return false; - - if( ptr->m_pEnt->GetMoveType() == MOVETYPE_PUSH ) - { - // All doors are push, but not all things that push are doors. This - // narrows the search before we start to do classname compares. - if( FClassnameIs(ptr->m_pEnt, "prop_door_rotating") || - FClassnameIs(ptr->m_pEnt, "func_door") || - FClassnameIs(ptr->m_pEnt, "func_door_rotating") ) - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Default implementation of radius damage -//----------------------------------------------------------------------------- -#define ROBUST_RADIUS_PROBE_DIST 16.0f // If a solid surface blocks the explosion, this is how far to creep along the surface looking for another way to the target -void CGameRules::RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore, CBaseEntity *pEntityIgnore ) -{ - const int MASK_RADIUS_DAMAGE = MASK_SHOT&(~CONTENTS_HITBOX); - CBaseEntity *pEntity = NULL; - trace_t tr; - float flAdjustedDamage, falloff; - Vector vecSpot; - - Vector vecSrc = vecSrcIn; - - if ( flRadius ) - falloff = info.GetDamage() / flRadius; - else - falloff = 1.0; - - int bInWater = (UTIL_PointContents ( vecSrc ) & MASK_WATER) ? true : false; - -#ifdef HL2_DLL - if( bInWater ) - { - // Only muffle the explosion if deeper than 2 feet in water. - if( !(UTIL_PointContents(vecSrc + Vector(0, 0, 24)) & MASK_WATER) ) - { - bInWater = false; - } - } -#endif // HL2_DLL - - vecSrc.z += 1;// in case grenade is lying on the ground - - float flHalfRadiusSqr = Square( flRadius / 2.0f ); - - // iterate on all entities in the vicinity. - for ( CEntitySphereQuery sphere( vecSrc, flRadius ); (pEntity = sphere.GetCurrentEntity()) != NULL; sphere.NextEntity() ) - { - // This value is used to scale damage when the explosion is blocked by some other object. - float flBlockedDamagePercent = 0.0f; - - if ( pEntity == pEntityIgnore ) - continue; - - if ( pEntity->m_takedamage == DAMAGE_NO ) - continue; - - // UNDONE: this should check a damage mask, not an ignore - if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore ) - {// houndeyes don't hurt other houndeyes with their attack - continue; - } - - // blast's don't tavel into or out of water - if (bInWater && pEntity->GetWaterLevel() == 0) - continue; - - if (!bInWater && pEntity->GetWaterLevel() == 3) - continue; - - // Check that the explosion can 'see' this entity. - vecSpot = pEntity->BodyTarget( vecSrc, false ); - UTIL_TraceLine( vecSrc, vecSpot, MASK_RADIUS_DAMAGE, info.GetInflictor(), COLLISION_GROUP_NONE, &tr ); - - if( old_radius_damage.GetBool() ) - { - if ( tr.fraction != 1.0 && tr.m_pEnt != pEntity ) - continue; - } - else - { - if ( tr.fraction != 1.0 ) - { - if ( IsExplosionTraceBlocked(&tr) ) - { - if( ShouldUseRobustRadiusDamage( pEntity ) ) - { - if( vecSpot.DistToSqr( vecSrc ) > flHalfRadiusSqr ) - { - // Only use robust model on a target within one-half of the explosion's radius. - continue; - } - - Vector vecToTarget = vecSpot - tr.endpos; - VectorNormalize( vecToTarget ); - - // We're going to deflect the blast along the surface that - // interrupted a trace from explosion to this target. - Vector vecUp, vecDeflect; - CrossProduct( vecToTarget, tr.plane.normal, vecUp ); - CrossProduct( tr.plane.normal, vecUp, vecDeflect ); - VectorNormalize( vecDeflect ); - - // Trace along the surface that intercepted the blast... - UTIL_TraceLine( tr.endpos, tr.endpos + vecDeflect * ROBUST_RADIUS_PROBE_DIST, MASK_RADIUS_DAMAGE, info.GetInflictor(), COLLISION_GROUP_NONE, &tr ); - //NDebugOverlay::Line( tr.startpos, tr.endpos, 255, 255, 0, false, 10 ); - - // ...to see if there's a nearby edge that the explosion would 'spill over' if the blast were fully simulated. - UTIL_TraceLine( tr.endpos, vecSpot, MASK_RADIUS_DAMAGE, info.GetInflictor(), COLLISION_GROUP_NONE, &tr ); - //NDebugOverlay::Line( tr.startpos, tr.endpos, 255, 0, 0, false, 10 ); - - if( tr.fraction != 1.0 && tr.DidHitWorld() ) - { - // Still can't reach the target. - continue; - } - // else fall through - } - else - { - continue; - } - } - - // UNDONE: Probably shouldn't let children block parents either? Or maybe those guys should set their owner if they want this behavior? - // HL2 - Dissolve damage is not reduced by interposing non-world objects - if( tr.m_pEnt && tr.m_pEnt != pEntity && tr.m_pEnt->GetOwnerEntity() != pEntity ) - { - // Some entity was hit by the trace, meaning the explosion does not have clear - // line of sight to the entity that it's trying to hurt. If the world is also - // blocking, we do no damage. - CBaseEntity *pBlockingEntity = tr.m_pEnt; - //Msg( "%s may be blocked by %s...", pEntity->GetClassname(), pBlockingEntity->GetClassname() ); - - UTIL_TraceLine( vecSrc, vecSpot, CONTENTS_SOLID, info.GetInflictor(), COLLISION_GROUP_NONE, &tr ); - - if( tr.fraction != 1.0 ) - { - continue; - } - - // Now, if the interposing object is physics, block some explosion force based on its mass. - if( pBlockingEntity->VPhysicsGetObject() ) - { - const float MASS_ABSORB_ALL_DAMAGE = 350.0f; - float flMass = pBlockingEntity->VPhysicsGetObject()->GetMass(); - float scale = flMass / MASS_ABSORB_ALL_DAMAGE; - - // Absorbed all the damage. - if( scale >= 1.0f ) - { - continue; - } - - ASSERT( scale > 0.0f ); - flBlockedDamagePercent = scale; - //Msg(" Object (%s) weighing %fkg blocked %f percent of explosion damage\n", pBlockingEntity->GetClassname(), flMass, scale * 100.0f); - } - else - { - // Some object that's not the world and not physics. Generically block 25% damage - flBlockedDamagePercent = 0.25f; - } - } - } - } - // decrease damage for an ent that's farther from the bomb. - flAdjustedDamage = ( vecSrc - tr.endpos ).Length() * falloff; - flAdjustedDamage = info.GetDamage() - flAdjustedDamage; - - if ( flAdjustedDamage <= 0 ) - { - continue; - } - - // the explosion can 'see' this entity, so hurt them! - if (tr.startsolid) - { - // if we're stuck inside them, fixup the position and distance - tr.endpos = vecSrc; - tr.fraction = 0.0; - } - - CTakeDamageInfo adjustedInfo = info; - //Msg("%s: Blocked damage: %f percent (in:%f out:%f)\n", pEntity->GetClassname(), flBlockedDamagePercent * 100, flAdjustedDamage, flAdjustedDamage - (flAdjustedDamage * flBlockedDamagePercent) ); - adjustedInfo.SetDamage( flAdjustedDamage - (flAdjustedDamage * flBlockedDamagePercent) ); - - // Now make a consideration for skill level! - if( info.GetAttacker() && info.GetAttacker()->IsPlayer() && pEntity->IsNPC() ) - { - // An explosion set off by the player is harming an NPC. Adjust damage accordingly. - adjustedInfo.AdjustPlayerDamageInflictedForSkillLevel(); - } - - Vector dir = vecSpot - vecSrc; - VectorNormalize( dir ); - - // If we don't have a damage force, manufacture one - if ( adjustedInfo.GetDamagePosition() == vec3_origin || adjustedInfo.GetDamageForce() == vec3_origin ) - { - if ( !( adjustedInfo.GetDamageType() & DMG_PREVENT_PHYSICS_FORCE ) ) - { - CalculateExplosiveDamageForce( &adjustedInfo, dir, vecSrc ); - } - } - else - { - // Assume the force passed in is the maximum force. Decay it based on falloff. - float flForce = adjustedInfo.GetDamageForce().Length() * falloff; - adjustedInfo.SetDamageForce( dir * flForce ); - adjustedInfo.SetDamagePosition( vecSrc ); - } - - if ( tr.fraction != 1.0 && pEntity == tr.m_pEnt ) - { - ClearMultiDamage( ); - pEntity->DispatchTraceAttack( adjustedInfo, dir, &tr ); - ApplyMultiDamage(); - } - else - { - pEntity->TakeDamage( adjustedInfo ); - } - - // Now hit all triggers along the way that respond to damage... - pEntity->TraceAttackToTriggers( adjustedInfo, vecSrc, tr.endpos, dir ); - -#if defined( GAME_DLL ) - if ( info.GetAttacker() && info.GetAttacker()->IsPlayer() && ToBaseCombatCharacter( tr.m_pEnt ) ) - { - - // This is a total hack!!! - bool bIsPrimary = true; - CBasePlayer *player = ToBasePlayer( info.GetAttacker() ); - CBaseCombatWeapon *pWeapon = player->GetActiveWeapon(); - if ( pWeapon && FClassnameIs( pWeapon, "weapon_smg1" ) ) - { - bIsPrimary = false; - } - - gamestats->Event_WeaponHit( player, bIsPrimary, (pWeapon != NULL) ? player->GetActiveWeapon()->GetClassname() : "NULL", info ); - } -#endif - } -} - - -bool CGameRules::ClientCommand( CBaseEntity *pEdict, const CCommand &args ) -{ - if( pEdict->IsPlayer() ) - { - if( GetVoiceGameMgr()->ClientCommand( static_cast(pEdict), args ) ) - return true; - } - - return false; -} - - -void CGameRules::FrameUpdatePostEntityThink() -{ - VPROF( "CGameRules::FrameUpdatePostEntityThink" ); - Think(); -} - -// Hook into the convar from the engine -ConVar skill( "skill", "1" ); - -void CGameRules::Think() -{ - GetVoiceGameMgr()->Update( gpGlobals->frametime ); - SetSkillLevel( skill.GetInt() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Called at the end of GameFrame (i.e. after all game logic has run this frame) -//----------------------------------------------------------------------------- -void CGameRules::EndGameFrame( void ) -{ - // If you hit this assert, it means something called AddMultiDamage() and didn't ApplyMultiDamage(). - // The g_MultiDamage.m_hAttacker & g_MultiDamage.m_hInflictor should give help you figure out the culprit. - Assert( g_MultiDamage.IsClear() ); - if ( !g_MultiDamage.IsClear() ) - { - Warning("Unapplied multidamage left in the system:\nTarget: %s\nInflictor: %s\nAttacker: %s\nDamage: %.2f\n", - g_MultiDamage.GetTarget()->GetDebugName(), - g_MultiDamage.GetInflictor()->GetDebugName(), - g_MultiDamage.GetAttacker()->GetDebugName(), - g_MultiDamage.GetDamage() ); - ApplyMultiDamage(); - } -} - -//----------------------------------------------------------------------------- -// trace line rules -//----------------------------------------------------------------------------- -float CGameRules::WeaponTraceEntity( CBaseEntity *pEntity, const Vector &vecStart, const Vector &vecEnd, - unsigned int mask, trace_t *ptr ) -{ - UTIL_TraceEntity( pEntity, vecStart, vecEnd, mask, ptr ); - return 1.0f; -} - - -void CGameRules::CreateStandardEntities() -{ - g_pPlayerResource = (CPlayerResource*)CBaseEntity::Create( "player_manager", vec3_origin, vec3_angle ); - g_pPlayerResource->AddEFlags( EFL_KEEP_ON_RECREATE_ENTITIES ); -} - -//----------------------------------------------------------------------------- -// Purpose: Inform client(s) they can mark the indicated achievement as completed (SERVER VERSION) -// Input : filter - which client(s) to send this to -// iAchievementID - The enumeration value of the achievement to mark (see TODO:Kerry, what file will have the mod's achievement enum?) -//----------------------------------------------------------------------------- -void CGameRules::MarkAchievement( IRecipientFilter& filter, char const *pchAchievementName ) -{ - gamestats->Event_IncrementCountedStatistic( vec3_origin, pchAchievementName, 1.0f ); - - IAchievementMgr *pAchievementMgr = engine->GetAchievementMgr(); - if ( !pAchievementMgr ) - return; - pAchievementMgr->OnMapEvent( pchAchievementName ); -} - -#endif //} !CLIENT_DLL - - -// ----------------------------------------------------------------------------- // -// Shared CGameRules implementation. -// ----------------------------------------------------------------------------- // - -CGameRules::~CGameRules() -{ - Assert( g_pGameRules == this ); - g_pGameRules = NULL; -} - -bool CGameRules::SwitchToNextBestWeapon( CBaseCombatCharacter *pPlayer, CBaseCombatWeapon *pCurrentWeapon ) -{ - return false; -} - -CBaseCombatWeapon *CGameRules::GetNextBestWeapon( CBaseCombatCharacter *pPlayer, CBaseCombatWeapon *pCurrentWeapon ) -{ - return NULL; -} - -bool CGameRules::ShouldCollide( int collisionGroup0, int collisionGroup1 ) -{ - if ( collisionGroup0 > collisionGroup1 ) - { - // swap so that lowest is always first - swap(collisionGroup0,collisionGroup1); - } - -#ifndef HL2MP - if ( (collisionGroup0 == COLLISION_GROUP_PLAYER || collisionGroup0 == COLLISION_GROUP_PLAYER_MOVEMENT) && - collisionGroup1 == COLLISION_GROUP_PUSHAWAY ) - { - return false; - } -#endif - - if ( collisionGroup0 == COLLISION_GROUP_DEBRIS && collisionGroup1 == COLLISION_GROUP_PUSHAWAY ) - { - // let debris and multiplayer objects collide - return true; - } - - // -------------------------------------------------------------------------- - // NOTE: All of this code assumes the collision groups have been sorted!!!! - // NOTE: Don't change their order without rewriting this code !!! - // -------------------------------------------------------------------------- - - // Don't bother if either is in a vehicle... - if (( collisionGroup0 == COLLISION_GROUP_IN_VEHICLE ) || ( collisionGroup1 == COLLISION_GROUP_IN_VEHICLE )) - return false; - - if ( ( collisionGroup1 == COLLISION_GROUP_DOOR_BLOCKER ) && ( collisionGroup0 != COLLISION_GROUP_NPC ) ) - return false; - - if ( ( collisionGroup0 == COLLISION_GROUP_PLAYER ) && ( collisionGroup1 == COLLISION_GROUP_PASSABLE_DOOR ) ) - return false; - - if ( collisionGroup0 == COLLISION_GROUP_DEBRIS || collisionGroup0 == COLLISION_GROUP_DEBRIS_TRIGGER ) - { - // put exceptions here, right now this will only collide with COLLISION_GROUP_NONE - return false; - } - - // Dissolving guys only collide with COLLISION_GROUP_NONE - if ( (collisionGroup0 == COLLISION_GROUP_DISSOLVING) || (collisionGroup1 == COLLISION_GROUP_DISSOLVING) ) - { - if ( collisionGroup0 != COLLISION_GROUP_NONE ) - return false; - } - - // doesn't collide with other members of this group - // or debris, but that's handled above - if ( collisionGroup0 == COLLISION_GROUP_INTERACTIVE_DEBRIS && collisionGroup1 == COLLISION_GROUP_INTERACTIVE_DEBRIS ) - return false; - -#ifndef HL2MP - // This change was breaking HL2DM - // Adrian: TEST! Interactive Debris doesn't collide with the player. - if ( collisionGroup0 == COLLISION_GROUP_INTERACTIVE_DEBRIS && ( collisionGroup1 == COLLISION_GROUP_PLAYER_MOVEMENT || collisionGroup1 == COLLISION_GROUP_PLAYER ) ) - return false; -#endif - - if ( collisionGroup0 == COLLISION_GROUP_BREAKABLE_GLASS && collisionGroup1 == COLLISION_GROUP_BREAKABLE_GLASS ) - return false; - - // interactive objects collide with everything except debris & interactive debris - if ( collisionGroup1 == COLLISION_GROUP_INTERACTIVE && collisionGroup0 != COLLISION_GROUP_NONE ) - return false; - - // Projectiles hit everything but debris, weapons, + other projectiles - if ( collisionGroup1 == COLLISION_GROUP_PROJECTILE ) - { - if ( collisionGroup0 == COLLISION_GROUP_DEBRIS || - collisionGroup0 == COLLISION_GROUP_WEAPON || - collisionGroup0 == COLLISION_GROUP_PROJECTILE ) - { - return false; - } - } - - // Don't let vehicles collide with weapons - // Don't let players collide with weapons... - // Don't let NPCs collide with weapons - // Weapons are triggers, too, so they should still touch because of that - if ( collisionGroup1 == COLLISION_GROUP_WEAPON ) - { - if ( collisionGroup0 == COLLISION_GROUP_VEHICLE || - collisionGroup0 == COLLISION_GROUP_PLAYER || - collisionGroup0 == COLLISION_GROUP_NPC ) - { - return false; - } - } - - // collision with vehicle clip entity?? - if ( collisionGroup0 == COLLISION_GROUP_VEHICLE_CLIP || collisionGroup1 == COLLISION_GROUP_VEHICLE_CLIP ) - { - // yes then if it's a vehicle, collide, otherwise no collision - // vehicle sorts lower than vehicle clip, so must be in 0 - if ( collisionGroup0 == COLLISION_GROUP_VEHICLE ) - return true; - // vehicle clip against non-vehicle, no collision - return false; - } - - return true; -} - - -const CViewVectors* CGameRules::GetViewVectors() const -{ - return &g_DefaultViewVectors; -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns how much damage the given ammo type should do to the victim -// when fired by the attacker. -// Input : pAttacker - Dude what shot the gun. -// pVictim - Dude what done got shot. -// nAmmoType - What been shot out. -// Output : How much hurt to put on dude what done got shot (pVictim). -//----------------------------------------------------------------------------- -float CGameRules::GetAmmoDamage( CBaseEntity *pAttacker, CBaseEntity *pVictim, int nAmmoType ) -{ - float flDamage = 0; - CAmmoDef *pAmmoDef = GetAmmoDef(); - - if ( pAttacker->IsPlayer() ) - { - flDamage = pAmmoDef->PlrDamage( nAmmoType ); - } - else - { - flDamage = pAmmoDef->NPCDamage( nAmmoType ); - } - - return flDamage; -} - - -#ifndef CLIENT_DLL -const char *CGameRules::GetChatPrefix( bool bTeamOnly, CBasePlayer *pPlayer ) -{ - if ( pPlayer && pPlayer->IsAlive() == false ) - { - if ( bTeamOnly ) - return "*DEAD*(TEAM)"; - else - return "*DEAD*"; - } - - return ""; -} - -void CGameRules::ClientSettingsChanged( CBasePlayer *pPlayer ) -{ - const char *pszName = engine->GetClientConVarValue( pPlayer->entindex(), "name" ); - - const char *pszOldName = pPlayer->GetPlayerName(); - - // msg everyone if someone changes their name, and it isn't the first time (changing no name to current name) - // Note, not using FStrEq so that this is case sensitive - if ( pszOldName[0] != 0 && Q_strcmp( pszOldName, pszName ) ) - { - char text[256]; - Q_snprintf( text,sizeof(text), "%s changed name to %s\n", pszOldName, pszName ); - - UTIL_ClientPrintAll( HUD_PRINTTALK, text ); - - IGameEvent * event = gameeventmanager->CreateEvent( "player_changename" ); - if ( event ) - { - event->SetInt( "userid", pPlayer->GetUserID() ); - event->SetString( "oldname", pszOldName ); - event->SetString( "newname", pszName ); - gameeventmanager->FireEvent( event ); - } - - pPlayer->SetPlayerName( pszName ); - } - - const char *pszFov = engine->GetClientConVarValue( pPlayer->entindex(), "fov_desired" ); - if ( pszFov ) - { - int iFov = atoi(pszFov); - iFov = clamp( iFov, 75, 90 ); - pPlayer->SetDefaultFOV( iFov ); - } -} - -#endif diff --git a/game/shared/gamerules.h b/game/shared/gamerules.h deleted file mode 100644 index c416f4987..000000000 --- a/game/shared/gamerules.h +++ /dev/null @@ -1,399 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef GAMERULES_H -#define GAMERULES_H -#ifdef _WIN32 -#pragma once -#endif - -// Debug history should be disabled in release builds -//#define DISABLE_DEBUG_HISTORY - -#ifdef CLIENT_DLL - - #include "c_baseentity.h" - - #define CGameRules C_GameRules - #define CGameRulesProxy C_GameRulesProxy - -#else - - #include "baseentity.h" - #include "recipientfilter.h" - -#endif - -#include "igamesystem.h" -#include "gamerules_register.h" - - -//#include "items.h" -class CBaseCombatWeapon; -class CBaseCombatCharacter; -class CBasePlayer; -class CItem; -class CAmmoDef; - -extern ConVar sk_autoaim_mode; - -// Autoaiming modes -enum -{ - AUTOAIM_NONE = 0, // No autoaim at all. - AUTOAIM_ON, // Autoaim is on. - AUTOAIM_ON_CONSOLE, // Autoaim is on, including enhanced features for Console gaming (more assistance, etc) -}; - -// weapon respawning return codes -enum -{ - GR_NONE = 0, - - GR_WEAPON_RESPAWN_YES, - GR_WEAPON_RESPAWN_NO, - - GR_AMMO_RESPAWN_YES, - GR_AMMO_RESPAWN_NO, - - GR_ITEM_RESPAWN_YES, - GR_ITEM_RESPAWN_NO, - - GR_PLR_DROP_GUN_ALL, - GR_PLR_DROP_GUN_ACTIVE, - GR_PLR_DROP_GUN_NO, - - GR_PLR_DROP_AMMO_ALL, - GR_PLR_DROP_AMMO_ACTIVE, - GR_PLR_DROP_AMMO_NO, -}; - -// Player relationship return codes -enum -{ - GR_NOTTEAMMATE = 0, - GR_TEAMMATE, - GR_ENEMY, - GR_ALLY, - GR_NEUTRAL, -}; - - -// This class has the data tables and gets the CGameRules data to the client. -class CGameRulesProxy : public CBaseEntity -{ -public: - DECLARE_CLASS( CGameRulesProxy, CBaseEntity ); - DECLARE_NETWORKCLASS(); - - CGameRulesProxy(); - ~CGameRulesProxy(); - - // UNDONE: Is this correct, Mike? - // Don't carry these across a transition, they are recreated. - virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } - - // ALWAYS transmit to all clients. - virtual int UpdateTransmitState( void ); - - // CGameRules chains its NetworkStateChanged calls to here, since this - // is the actual entity that will send the data. - static void NotifyNetworkStateChanged(); - -private: - - static CGameRulesProxy *s_pGameRulesProxy; -}; - - -abstract_class CGameRules : public CAutoGameSystemPerFrame -{ -public: - DECLARE_CLASS_GAMEROOT( CGameRules, CAutoGameSystemPerFrame ); - - virtual char const *Name() { return "CGameRules"; } - - // Stuff shared between client and server. - - CGameRules(void); - virtual ~CGameRules( void ); - - // Damage Queries - these need to be implemented by the various subclasses (single-player, multi-player, etc). - // The queries represent queries against damage types and properties. - virtual bool Damage_IsTimeBased( int iDmgType ) = 0; // Damage types that are time-based. - virtual bool Damage_ShouldGibCorpse( int iDmgType ) = 0; // Damage types that gib the corpse. - virtual bool Damage_ShowOnHUD( int iDmgType ) = 0; // Damage types that have client HUD art. - virtual bool Damage_NoPhysicsForce( int iDmgType ) = 0; // Damage types that don't have to supply a physics force & position. - virtual bool Damage_ShouldNotBleed( int iDmgType ) = 0; // Damage types that don't make the player bleed. - //Temp: These will go away once DamageTypes become enums. - virtual int Damage_GetTimeBased( void ) = 0; // Actual bit-fields. - virtual int Damage_GetShouldGibCorpse( void ) = 0; - virtual int Damage_GetShowOnHud( void ) = 0; - virtual int Damage_GetNoPhysicsForce( void )= 0; - virtual int Damage_GetShouldNotBleed( void ) = 0; - -// Ammo Definitions - //CAmmoDef* GetAmmoDef(); - - virtual bool SwitchToNextBestWeapon( CBaseCombatCharacter *pPlayer, CBaseCombatWeapon *pCurrentWeapon ); // Switch to the next best weapon - virtual CBaseCombatWeapon *GetNextBestWeapon( CBaseCombatCharacter *pPlayer, CBaseCombatWeapon *pCurrentWeapon ); // I can't use this weapon anymore, get me the next best one. - virtual bool ShouldCollide( int collisionGroup0, int collisionGroup1 ); - - virtual int DefaultFOV( void ) { return 90; } - - // This function is here for our CNetworkVars. - inline void NetworkStateChanged() - { - // Forward the call to the entity that will send the data. - CGameRulesProxy::NotifyNetworkStateChanged(); - } - - inline void NetworkStateChanged( void *pVar ) - { - // Forward the call to the entity that will send the data. - CGameRulesProxy::NotifyNetworkStateChanged(); - } - - // Get the view vectors for this mod. - virtual const CViewVectors* GetViewVectors() const; - -// Damage rules for ammo types - virtual float GetAmmoDamage( CBaseEntity *pAttacker, CBaseEntity *pVictim, int nAmmoType ); - virtual float GetDamageMultiplier( void ) { return 1.0f; } - -// Functions to verify the single/multiplayer status of a game - virtual bool IsMultiplayer( void ) = 0;// is this a multiplayer game? (either coop or deathmatch) - - virtual const unsigned char *GetEncryptionKey() { return NULL; } - - virtual bool InRoundRestart( void ) { return false; } - -#ifdef CLIENT_DLL - - virtual bool IsBonusChallengeTimeBased( void ); - -#else - - virtual void GetTaggedConVarList( KeyValues *pCvarTagList ) {} - - -// CBaseEntity overrides. -public: - -// Setup - - // Called when game rules are destroyed by CWorld - virtual void LevelShutdown( void ) { return; }; - - virtual void Precache( void ) { return; }; - - virtual void RefreshSkillData( bool forceUpdate );// fill skill data struct with proper values - - // Called each frame. This just forwards the call to Think(). - virtual void FrameUpdatePostEntityThink(); - - virtual void Think( void ) = 0;// GR_Think - runs every server frame, should handle any timer tasks, periodic events, etc. - virtual bool IsAllowedToSpawn( CBaseEntity *pEntity ) = 0; // Can this item spawn (eg NPCs don't spawn in deathmatch). - - // Called at the end of GameFrame (i.e. after all game logic has run this frame) - virtual void EndGameFrame( void ); - - virtual bool IsSkillLevel( int iLevel ) { return GetSkillLevel() == iLevel; } - virtual int GetSkillLevel() { return g_iSkillLevel; } - virtual void OnSkillLevelChanged( int iNewLevel ) {}; - virtual void SetSkillLevel( int iLevel ) - { - int oldLevel = g_iSkillLevel; - - if ( iLevel < 1 ) - { - iLevel = 1; - } - else if ( iLevel > 3 ) - { - iLevel = 3; - } - - g_iSkillLevel = iLevel; - - if( g_iSkillLevel != oldLevel ) - { - OnSkillLevelChanged( g_iSkillLevel ); - } - } - - virtual bool FAllowFlashlight( void ) = 0;// Are players allowed to switch on their flashlight? - virtual bool FShouldSwitchWeapon( CBasePlayer *pPlayer, CBaseCombatWeapon *pWeapon ) = 0;// should the player switch to this weapon? - -// Functions to verify the single/multiplayer status of a game - virtual bool IsDeathmatch( void ) = 0;//is this a deathmatch game? - virtual bool IsTeamplay( void ) { return FALSE; };// is this deathmatch game being played with team rules? - virtual bool IsCoOp( void ) = 0;// is this a coop game? - virtual const char *GetGameDescription( void ) { return "Half-Life 2"; } // this is the game name that gets seen in the server browser - -// Client connection/disconnection - virtual bool ClientConnected( edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen ) = 0;// a client just connected to the server (player hasn't spawned yet) - virtual void InitHUD( CBasePlayer *pl ) = 0; // the client dll is ready for updating - virtual void ClientDisconnected( edict_t *pClient ) = 0;// a client just disconnected from the server - -// Client damage rules - virtual float FlPlayerFallDamage( CBasePlayer *pPlayer ) = 0;// this client just hit the ground after a fall. How much damage? - virtual bool FPlayerCanTakeDamage( CBasePlayer *pPlayer, CBaseEntity *pAttacker ) {return TRUE;};// can this player take damage from this attacker? - virtual bool ShouldAutoAim( CBasePlayer *pPlayer, edict_t *target ) { return TRUE; } - virtual float GetAutoAimScale( CBasePlayer *pPlayer ) { return 1.0f; } - virtual int GetAutoAimMode() { return AUTOAIM_ON; } - - virtual bool ShouldUseRobustRadiusDamage(CBaseEntity *pEntity) { return false; } - virtual void RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrc, float flRadius, int iClassIgnore, CBaseEntity *pEntityIgnore ); - // Let the game rules specify if fall death should fade screen to black - virtual bool FlPlayerFallDeathDoesScreenFade( CBasePlayer *pl ) { return TRUE; } - - virtual bool AllowDamage( CBaseEntity *pVictim, const CTakeDamageInfo &info ) = 0; - - -// Client spawn/respawn control - virtual void PlayerSpawn( CBasePlayer *pPlayer ) = 0;// called by CBasePlayer::Spawn just before releasing player into the game - virtual void PlayerThink( CBasePlayer *pPlayer ) = 0; // called by CBasePlayer::PreThink every frame, before physics are run and after keys are accepted - virtual bool FPlayerCanRespawn( CBasePlayer *pPlayer ) = 0;// is this player allowed to respawn now? - virtual float FlPlayerSpawnTime( CBasePlayer *pPlayer ) = 0;// When in the future will this player be able to spawn? - virtual CBaseEntity *GetPlayerSpawnSpot( CBasePlayer *pPlayer );// Place this player on their spawnspot and face them the proper direction. - virtual bool IsSpawnPointValid( CBaseEntity *pSpot, CBasePlayer *pPlayer ); - - virtual bool AllowAutoTargetCrosshair( void ) { return TRUE; }; - virtual bool ClientCommand( CBaseEntity *pEdict, const CCommand &args ); // handles the user commands; returns TRUE if command handled properly - virtual void ClientSettingsChanged( CBasePlayer *pPlayer ); // the player has changed cvars - -// Client kills/scoring - virtual int IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *pKilled ) = 0;// how many points do I award whoever kills this player? - virtual void PlayerKilled( CBasePlayer *pVictim, const CTakeDamageInfo &info ) = 0;// Called each time a player dies - virtual void DeathNotice( CBasePlayer *pVictim, const CTakeDamageInfo &info )= 0;// Call this from within a GameRules class to report an obituary. - virtual const char *GetDamageCustomString( const CTakeDamageInfo &info ) { return NULL; } - -// Weapon Damage - // Determines how much damage Player's attacks inflict, based on skill level. - virtual float AdjustPlayerDamageInflicted( float damage ) { return damage; } - virtual void AdjustPlayerDamageTaken( CTakeDamageInfo *pInfo ) {}; // Base class does nothing. - -// Weapon retrieval - virtual bool CanHavePlayerItem( CBasePlayer *pPlayer, CBaseCombatWeapon *pWeapon );// The player is touching an CBaseCombatWeapon, do I give it to him? - -// Weapon spawn/respawn control - virtual int WeaponShouldRespawn( CBaseCombatWeapon *pWeapon ) = 0;// should this weapon respawn? - virtual float FlWeaponRespawnTime( CBaseCombatWeapon *pWeapon ) = 0;// when may this weapon respawn? - virtual float FlWeaponTryRespawn( CBaseCombatWeapon *pWeapon ) = 0; // can i respawn now, and if not, when should i try again? - virtual Vector VecWeaponRespawnSpot( CBaseCombatWeapon *pWeapon ) = 0;// where in the world should this weapon respawn? - -// Item retrieval - virtual bool CanHaveItem( CBasePlayer *pPlayer, CItem *pItem ) = 0;// is this player allowed to take this item? - virtual void PlayerGotItem( CBasePlayer *pPlayer, CItem *pItem ) = 0;// call each time a player picks up an item (battery, healthkit) - -// Item spawn/respawn control - virtual int ItemShouldRespawn( CItem *pItem ) = 0;// Should this item respawn? - virtual float FlItemRespawnTime( CItem *pItem ) = 0;// when may this item respawn? - virtual Vector VecItemRespawnSpot( CItem *pItem ) = 0;// where in the world should this item respawn? - virtual QAngle VecItemRespawnAngles( CItem *pItem ) = 0;// what angles should this item use when respawing? - -// Ammo retrieval - virtual bool CanHaveAmmo( CBaseCombatCharacter *pPlayer, int iAmmoIndex ); // can this player take more of this ammo? - virtual bool CanHaveAmmo( CBaseCombatCharacter *pPlayer, const char *szName ); - virtual void PlayerGotAmmo( CBaseCombatCharacter *pPlayer, char *szName, int iCount ) = 0;// called each time a player picks up some ammo in the world - virtual float GetAmmoQuantityScale( int iAmmoIndex ) { return 1.0f; } - -// AI Definitions - virtual void InitDefaultAIRelationships( void ) { return; } - virtual const char* AIClassText(int classType) { return NULL; } - -// Healthcharger respawn control - virtual float FlHealthChargerRechargeTime( void ) = 0;// how long until a depleted HealthCharger recharges itself? - virtual float FlHEVChargerRechargeTime( void ) { return 0; }// how long until a depleted HealthCharger recharges itself? - -// What happens to a dead player's weapons - virtual int DeadPlayerWeapons( CBasePlayer *pPlayer ) = 0;// what do I do with a player's weapons when he's killed? - -// What happens to a dead player's ammo - virtual int DeadPlayerAmmo( CBasePlayer *pPlayer ) = 0;// Do I drop ammo when the player dies? How much? - -// Teamplay stuff - virtual const char *GetTeamID( CBaseEntity *pEntity ) = 0;// what team is this entity on? - virtual int PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget ) = 0;// What is the player's relationship with this entity? - virtual bool PlayerCanHearChat( CBasePlayer *pListener, CBasePlayer *pSpeaker ) = 0; - virtual void CheckChatText( CBasePlayer *pPlayer, char *pText ) { return; } - - virtual int GetTeamIndex( const char *pTeamName ) { return -1; } - virtual const char *GetIndexedTeamName( int teamIndex ) { return ""; } - virtual bool IsValidTeam( const char *pTeamName ) { return true; } - virtual void ChangePlayerTeam( CBasePlayer *pPlayer, const char *pTeamName, bool bKill, bool bGib ) {} - virtual const char *SetDefaultPlayerTeam( CBasePlayer *pPlayer ) { return ""; } - virtual void UpdateClientData( CBasePlayer *pPlayer ) { }; - -// Sounds - virtual bool PlayTextureSounds( void ) { return TRUE; } - virtual bool PlayFootstepSounds( CBasePlayer *pl ) { return TRUE; } - -// NPCs - virtual bool FAllowNPCs( void ) = 0;//are NPCs allowed - - // Immediately end a multiplayer game - virtual void EndMultiplayerGame( void ) {} - - // trace line rules - virtual float WeaponTraceEntity( CBaseEntity *pEntity, const Vector &vecStart, const Vector &vecEnd, unsigned int mask, trace_t *ptr ); - - // Setup g_pPlayerResource (some mods use a different entity type here). - virtual void CreateStandardEntities(); - - // Team name, etc shown in chat and dedicated server console - virtual const char *GetChatPrefix( bool bTeamOnly, CBasePlayer *pPlayer ); - - // Location name shown in chat - virtual const char *GetChatLocation( bool bTeamOnly, CBasePlayer *pPlayer ) { return NULL; } - - // VGUI format string for chat, if desired - virtual const char *GetChatFormat( bool bTeamOnly, CBasePlayer *pPlayer ) { return NULL; } - - // Whether props that are on fire should get a DLIGHT. - virtual bool ShouldBurningPropsEmitLight() { return false; } - - virtual bool CanEntityBeUsePushed( CBaseEntity *pEnt ) { return true; } - - virtual void CreateCustomNetworkStringTables( void ) { } - - // Game Achievements (server version) - virtual void MarkAchievement ( IRecipientFilter& filter, char const *pchAchievementName ); - - virtual void ResetMapCycleTimeStamp( void ){ return; } - -#endif - - virtual const char *GetGameTypeName( void ){ return NULL; } - virtual int GetGameType( void ){ return 0; } -}; - - -#ifndef CLIENT_DLL - void InstallGameRules(); - - // Create user messages for game here, calls into static player class creation functions - void RegisterUserMessages( void ); -#endif - - -extern ConVar g_Language; - - -//----------------------------------------------------------------------------- -// Gets us at the game rules -//----------------------------------------------------------------------------- - -extern CGameRules *g_pGameRules; - -inline CGameRules* GameRules() -{ - return g_pGameRules; -} - -#endif // GAMERULES_H diff --git a/game/shared/gamerules_register.cpp b/game/shared/gamerules_register.cpp deleted file mode 100644 index 3194ba0e7..000000000 --- a/game/shared/gamerules_register.cpp +++ /dev/null @@ -1,139 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "gamerules_register.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// ------------------------------------------------------------------------------------------ // -// CGameRulesRegister implementation. -// ------------------------------------------------------------------------------------------ // - -CGameRulesRegister* CGameRulesRegister::s_pHead = NULL; - - -CGameRulesRegister::CGameRulesRegister( const char *pClassName, CreateGameRulesFn fn ) -{ - m_pClassName = pClassName; - m_pFn = fn; - - m_pNext = s_pHead; // Add us to the global list. - s_pHead = this; -} - -void CGameRulesRegister::CreateGameRules() -{ - m_pFn(); -} - -CGameRulesRegister* CGameRulesRegister::FindByName( const char *pName ) -{ - for ( CGameRulesRegister *pCur=s_pHead; pCur; pCur=pCur->m_pNext ) - { - if ( Q_stricmp( pName, pCur->m_pClassName ) == 0 ) - return pCur; - } - return NULL; -} - - -// ------------------------------------------------------------------------------------------ // -// Functions to dispatch the messages to create the game rules object on the client. -// ------------------------------------------------------------------------------------------ // - -#define GAMERULES_STRINGTABLE_NAME "GameRulesCreation" - - -#ifdef CLIENT_DLL - - #include "networkstringtable_clientdll.h" - - INetworkStringTable *g_StringTableGameRules = NULL; - - void OnGameRulesCreationStringChanged( - void *object, - INetworkStringTable *stringTable, - int stringNumber, - const char *newString, - void const *newData ) - { - // The server has created a new CGameRules object. - delete g_pGameRules; - g_pGameRules = NULL; - - const char *pClassName = (const char*)newData; - CGameRulesRegister *pReg = CGameRulesRegister::FindByName( pClassName ); - if ( !pReg ) - Error( "OnGameRulesCreationStringChanged: missing gamerules class '%s' on the client", pClassName ); - - // Create the new game rules object. - pReg->CreateGameRules(); - - if ( !g_pGameRules ) - { - Error( "OnGameRulesCreationStringChanged: game rules entity (%s) not created", pClassName ); - } - } - - // On the client, we respond to string table changes on the server. - void InstallStringTableCallback_GameRules() - { - if ( !g_StringTableGameRules ) - { - g_StringTableGameRules = networkstringtable->FindTable( GAMERULES_STRINGTABLE_NAME ); - if ( g_StringTableGameRules ) - g_StringTableGameRules->SetStringChangedCallback( NULL, OnGameRulesCreationStringChanged ); - } - } - -#else - - #include "networkstringtable_gamedll.h" - - INetworkStringTable *g_StringTableGameRules = NULL; - - void CreateNetworkStringTables_GameRules() - { - // Create the string table used by - g_StringTableGameRules = networkstringtable->CreateStringTable( GAMERULES_STRINGTABLE_NAME, 1 ); - -#ifdef CSTRIKE_DLL - void CreateBlackMarketString( void ); - CreateBlackMarketString(); -#endif - } - - void CreateGameRulesObject( const char *pClassName ) - { - // Delete the old game rules object. - delete g_pGameRules; - g_pGameRules = NULL; - - // Create a new game rules object. - CGameRulesRegister *pReg = CGameRulesRegister::FindByName( pClassName ); - if ( !pReg ) - Error( "InitGameRules: missing gamerules class '%s' on the server", pClassName ); - - pReg->CreateGameRules(); - if ( !g_pGameRules ) - { - Error( "InitGameRules: game rules entity (%s) not created", pClassName ); - } - - // Make sure the client gets notification to make a new game rules object. - Assert( g_StringTableGameRules ); - g_StringTableGameRules->AddString( true, "classname", strlen( pClassName ) + 1, pClassName ); - - if ( g_pGameRules ) - { - g_pGameRules->CreateCustomNetworkStringTables(); - } - } - -#endif - diff --git a/game/shared/gamerules_register.h b/game/shared/gamerules_register.h deleted file mode 100644 index 76fdca990..000000000 --- a/game/shared/gamerules_register.h +++ /dev/null @@ -1,71 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef GAMERULES_REGISTER_H -#define GAMERULES_REGISTER_H -#ifdef _WIN32 -#pragma once -#endif - - -// Each game rules class must register using this in it's .cpp file. -#if !defined(_STATIC_LINKED) -#define REGISTER_GAMERULES_CLASS( className ) \ - void __CreateGameRules_##className() { new className; } \ - static CGameRulesRegister __g_GameRulesRegister_##className( #className, __CreateGameRules_##className ); -#else -#define REGISTER_GAMERULES_CLASS( className ) \ - void MAKE_NAME_UNIQUE(__CreateGameRules_)##className() { new className; } \ - static CGameRulesRegister __g_GameRulesRegister_##className( #className, MAKE_NAME_UNIQUE(__CreateGameRules_)##className ); -#endif - -#ifdef _XBOX -// force symbol expansion -#define REGISTER_GAMERULES_CLASS2( className ) REGISTER_GAMERULES_CLASS( className ) -#endif - -class CGameRulesRegister -{ -public: - typedef void (*CreateGameRulesFn)(); - - CGameRulesRegister( const char *pClassName, CreateGameRulesFn fn ); - - // Allocates the gamerules object associated with this class. - void CreateGameRules(); - - static CGameRulesRegister* FindByName( const char *pName ); - -private: - const char *m_pClassName; - CreateGameRulesFn m_pFn; - CGameRulesRegister *m_pNext; // Links it into the global list. - - static CGameRulesRegister *s_pHead; - -}; - - - -#ifdef CLIENT_DLL - - // The client forwards this call so the game rules manager can create the appropriate - // game rules class. - void InstallStringTableCallback_GameRules(); - -#else - - // Server calls this at startup. - void CreateNetworkStringTables_GameRules(); - - // Server calls this to install a specific game rules object. The class should have been registered - // with REGISTER_GAMERULES_CLASS. - void CreateGameRulesObject( const char *pClassName ); - -#endif - - -#endif // GAMERULES_REGISTER_H diff --git a/game/shared/gamestringpool.cpp b/game/shared/gamestringpool.cpp deleted file mode 100644 index 859a37cdb..000000000 --- a/game/shared/gamestringpool.cpp +++ /dev/null @@ -1,77 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -#include "stringpool.h" -#include "igamesystem.h" -#include "gamestringpool.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: The actual storage for pooled per-level strings -//----------------------------------------------------------------------------- -class CGameStringPool : public CStringPool, public CBaseGameSystem -{ - virtual char const *Name() { return "CGameStringPool"; } - - virtual void LevelShutdownPostEntity() - { - FreeAll(); - } - -public: - void Dump( void ) - { - for ( int i = m_Strings.FirstInorder(); i != m_Strings.InvalidIndex(); i = m_Strings.NextInorder(i) ) - { - DevMsg( " %d (0x%x) : %s\n", i, m_Strings[i], m_Strings[i] ); - } - DevMsg( "\n" ); - DevMsg( "Size: %d items\n", m_Strings.Count() ); - } -}; - -static CGameStringPool g_GameStringPool; - - -//----------------------------------------------------------------------------- -// String system accessor -//----------------------------------------------------------------------------- -IGameSystem *GameStringSystem() -{ - return &g_GameStringPool; -} - - -//----------------------------------------------------------------------------- -// Purpose: The public accessor for the level-global pooled strings -//----------------------------------------------------------------------------- -string_t AllocPooledString( const char * pszValue ) -{ - if (pszValue && *pszValue) - return MAKE_STRING( g_GameStringPool.Allocate( pszValue ) ); - return NULL_STRING; -} - -string_t FindPooledString( const char *pszValue ) -{ - return MAKE_STRING( g_GameStringPool.Find( pszValue ) ); -} - -#ifndef CLIENT_DLL -//------------------------------------------------------------------------------ -// Purpose: -//------------------------------------------------------------------------------ -void CC_DumpGameStringTable( void ) -{ - g_GameStringPool.Dump(); -} -static ConCommand dumpgamestringtable("dumpgamestringtable", CC_DumpGameStringTable, "Dump the contents of the game string table to the console.", FCVAR_CHEAT); -#endif diff --git a/game/shared/gamestringpool.h b/game/shared/gamestringpool.h deleted file mode 100644 index cad9884b6..000000000 --- a/game/shared/gamestringpool.h +++ /dev/null @@ -1,32 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Pool of all per-level strings. Allocates memory for strings, -// consolodating duplicates. The memory is freed on behalf of clients -// at level transition. Strings are of type string_t. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef GAMESTRINGPOOL_H -#define GAMESTRINGPOOL_H - -#if defined( _WIN32 ) -#pragma once -#endif - -class IGameSystem; - -//----------------------------------------------------------------------------- -// String allocation -//----------------------------------------------------------------------------- -string_t AllocPooledString( const char *pszValue ); -string_t FindPooledString( const char *pszValue ); - -#define AssertIsValidString( s ) AssertMsg( s == NULL_STRING || s == FindPooledString( STRING(s) ), "Invalid string " #s ); - -//----------------------------------------------------------------------------- -// String system accessor -//----------------------------------------------------------------------------- -IGameSystem *GameStringSystem(); - -#endif // GAMESTRINGPOOL_H diff --git a/game/shared/gamevars_shared.cpp b/game/shared/gamevars_shared.cpp deleted file mode 100644 index 512c47761..000000000 --- a/game/shared/gamevars_shared.cpp +++ /dev/null @@ -1,51 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "gamevars_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#ifdef GAME_DLL -void MPForceCameraCallback( IConVar *var, const char *pOldString, float flOldValue ) -{ - if ( mp_forcecamera.GetInt() < OBS_ALLOW_ALL || mp_forcecamera.GetInt() >= OBS_ALLOW_NUM_MODES ) - { - mp_forcecamera.SetValue( OBS_ALLOW_TEAM ); - } -} -#endif - -// some shared cvars used by game rules -ConVar mp_forcecamera( - "mp_forcecamera", - "1", - FCVAR_REPLICATED, - "Restricts spectator modes for dead players" -#ifdef GAME_DLL - , MPForceCameraCallback -#endif - ); - -ConVar mp_allowspectators( - "mp_allowspectators", - "1.0", - FCVAR_REPLICATED, - "toggles whether the server allows spectator mode or not" ); - -ConVar friendlyfire( - "mp_friendlyfire", - "0", - FCVAR_REPLICATED | FCVAR_NOTIFY, - "Allows team members to injure other members of their team" - ); - -ConVar mp_fadetoblack( - "mp_fadetoblack", - "0", - FCVAR_REPLICATED | FCVAR_NOTIFY, - "fade a player's screen to black when he dies" ); diff --git a/game/shared/gamevars_shared.h b/game/shared/gamevars_shared.h deleted file mode 100644 index e300843fb..000000000 --- a/game/shared/gamevars_shared.h +++ /dev/null @@ -1,21 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef CS_GAMEVARS_SHARED_H -#define CS_GAMEVARS_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - -#include "convar.h" - -extern ConVar mp_forcecamera; -extern ConVar mp_allowspectators; -extern ConVar friendlyfire; -extern ConVar mp_fadetoblack; - -#endif // CS_GAMEVARS_SHARED_H diff --git a/game/shared/groundlink.h b/game/shared/groundlink.h deleted file mode 100644 index a34162efc..000000000 --- a/game/shared/groundlink.h +++ /dev/null @@ -1,23 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef GROUNDLINK_H -#define GROUNDLINK_H -#ifdef _WIN32 -#pragma once -#endif - -//----------------------------------------------------------------------------- -// Purpose: Used for tracking many to one ground entity chains ( many ents can share a single ground entity ) -//----------------------------------------------------------------------------- -struct groundlink_t -{ - EHANDLE entity; - groundlink_t *nextLink; - groundlink_t *prevLink; -}; - -#endif // GROUNDLINK_H diff --git a/game/shared/hintmessage.cpp b/game/shared/hintmessage.cpp deleted file mode 100644 index f130fcf6d..000000000 --- a/game/shared/hintmessage.cpp +++ /dev/null @@ -1,296 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#include "hintmessage.h" -#include "hintsystem.h" - -#ifdef GAME_DLL - #include "util.h" -#endif - -//-------------------------------------------------------------------------------------------------------- -/** -* Simple utility function to allocate memory and duplicate a string -*/ -inline char *CloneString( const char *str ) -{ - char *cloneStr = new char [ strlen(str)+1 ]; - strcpy( cloneStr, str ); - return cloneStr; -} - -extern int gmsgHudText; - -enum { HMQ_SIZE = 8 }; // Maximum number of messages queue can hold - // If the limit is reached, no more can be - // added. - -//-------------------------------------------------------------------------------------------------------------- -CHintMessage::CHintMessage( const char * hintString, CUtlVector< const char * > * args, float duration ) -{ - m_hintString = hintString; - m_duration = duration; - - if ( args ) - { - for ( int i=0; iCount(); ++i ) - { - m_args.AddToTail( CloneString( (*args)[i] ) ); - } - } -} - -//-------------------------------------------------------------------------------------------------------------- -CHintMessage::~CHintMessage() -{ - for ( int i=0; i * args ) const -{ - if ( FStrEq( hintString, m_hintString ) ) - { - if ( !args && !m_args.Count() ) - { - return true; - } - - if ( !args ) - return false; - - if ( args->Count() != m_args.Count() ) - return false; - - for ( int i=0; iCount(); ++i ) - { - if ( !FStrEq( (*args)[i], m_args[i] ) ) - { - return false; - } - } - } - return false; -} - -//-------------------------------------------------------------------------------------------------------------- -void CHintMessage::Send( CBasePlayer * client ) -{ - if ( !client ) - return; - -#ifdef GAME_DLL - // Custom hint text sending to allow for arguments. This is OK because the client has a custom - // message parser for hint text that can read the arguments. - CSingleUserRecipientFilter user( (CBasePlayer *)client ); - user.MakeReliable(); - - // client can handle 1 string only - UserMessageBegin( user, "HintText" ); - WRITE_STRING( m_hintString ); - MessageEnd(); -#endif -} - -//-------------------------------------------------------------------------------------------------------------- -CHintMessageQueue::CHintMessageQueue( CBasePlayer *pPlayer ) -{ - m_pPlayer = pPlayer; -} - -//-------------------------------------------------------------------------------------------------------------- -void CHintMessageQueue::Reset() -{ - m_tmMessageEnd = 0; - for ( int i=0; icurtime > m_tmMessageEnd ) - { - if ( m_messages.Count() ) - { - CHintMessage *msg = m_messages[0]; - m_tmMessageEnd = gpGlobals->curtime + msg->GetDuration(); - msg->Send( m_pPlayer ); - delete msg; - m_messages.Remove( 0 ); - } - } -} - -//-------------------------------------------------------------------------------------------------------------- -bool CHintMessageQueue::AddMessage( const char* message, float duration, CUtlVector< const char * > * args ) -{ - if ( !m_pPlayer ) - return false; - - for ( int i=0; iIsEquivalent( message, args ) ) - { - return true; - } - } - - // 'message' is not copied, so the pointer must remain valid forever - CHintMessage *msg = new CHintMessage( message, args, duration ); - m_messages.AddToTail( msg ); - return true; -} - -//-------------------------------------------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -//----------------------------------------------------------------------------- -CHintMessageTimers::CHintMessageTimers( CHintSystem *pSystem, CHintMessageQueue *pQueue ) -{ - m_pHintSystem = pSystem; - m_pQueue = pQueue; -} - -//----------------------------------------------------------------------------- -// Purpose: Clear out all registered timers -//----------------------------------------------------------------------------- -void CHintMessageTimers::Reset() -{ - for ( int i=0; itimer.Expired() ) - { - if ( m_pHintSystem->TimerShouldFire( m_Timers[i]->iHintID ) ) - { - //Warning("TIMER FIRED: %s\n", m_pszHintMessages[m_Timers[i]->iHintID] ); - - m_pHintSystem->HintMessage( m_Timers[i]->iHintID ); - - // Remove and return. No reason to bring up multiple hints. - RemoveTimer( m_Timers[i]->iHintID ); - return; - } - else - { - // Push the timer out again - m_Timers[i]->timer.Start(); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Register a new timer that the system should should keep track of. -// Input : iHintID - The ID of the hint message -// timer_duration - the total time the timer should run for until it fires the hint message -// message_duration - the duration passed into the hint message system when the hint fires -// args - the arguments passed into the hint message system when the hint fires -//----------------------------------------------------------------------------- -void CHintMessageTimers::AddTimer( int iHintID, float timer_duration, float message_duration, CUtlVector< const char * > * args ) -{ - if ( GetTimerIndex(iHintID) != m_Timers.InvalidIndex() ) - return; - - // 'message' is not copied, so the pointer must remain valid forever - hintmessagetime_t *newTimer = new hintmessagetime_t( timer_duration ); - newTimer->iHintID = iHintID; - newTimer->flMessageDuration = message_duration; - if ( args ) - { - for ( int i=0; iCount(); ++i ) - { - newTimer->args.AddToTail( CloneString( (*args)[i] ) ); - } - } - m_Timers.AddToTail( newTimer ); - - //Warning("TIMER ADDED: %s\n", m_pszHintMessages[iHintID] ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHintMessageTimers::RemoveTimer( int iHintID ) -{ - int iIndex = GetTimerIndex(iHintID); - if ( iIndex != m_Timers.InvalidIndex() ) - { - //Warning("TIMER REMOVED: %s\n", m_pszHintMessages[iHintID] ); - m_Timers.Remove( iIndex ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHintMessageTimers::StartTimer( int iHintID ) -{ - int iIndex = GetTimerIndex(iHintID); - if ( iIndex != m_Timers.InvalidIndex() ) - { - //Warning("TIMER STARTED: %s\n", m_pszHintMessages[iHintID] ); - m_Timers[iIndex]->timer.Start(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHintMessageTimers::StopTimer( int iHintID ) -{ - int iIndex = GetTimerIndex(iHintID); - if ( iIndex != m_Timers.InvalidIndex() ) - { - //Warning("TIMER STOPPED: %s\n", m_pszHintMessages[iHintID] ); - m_Timers[iIndex]->timer.Stop(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Return the index of the hint message in the timer list, if any -//----------------------------------------------------------------------------- -int CHintMessageTimers::GetTimerIndex( int iHintID ) -{ - for ( int i = 0; i < m_Timers.Count(); i++ ) - { - if ( m_Timers[i]->iHintID == iHintID ) - return i; - } - - return m_Timers.InvalidIndex(); -} diff --git a/game/shared/hintmessage.h b/game/shared/hintmessage.h deleted file mode 100644 index 941463f39..000000000 --- a/game/shared/hintmessage.h +++ /dev/null @@ -1,113 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef HINTMESSAGE_H -#define HINTMESSAGE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "utlvector.h" -#include "simtimer.h" - -#ifdef GAME_DLL - #include "player.h" -#else - #include "c_baseplayer.h" -#endif - -class CHintSystem; - -//-------------------------------------------------------------------------------------------------------------- -class CHintMessage -{ -public: - CHintMessage( const char * hintString, CUtlVector< const char * > * args, float duration ); - ~CHintMessage(); - - float GetDuration() const { return m_duration; } - void Send( CBasePlayer *client ); - - bool IsEquivalent( const char *hintString, CUtlVector< const char * > * args ) const; - -private: - const char * m_hintString; ///< hintString is a pointer to a string that should never be deleted. - CUtlVector< char * > m_args; ///< list of arguments. The memory for these strings is internal to the CHintMessage. - float m_duration; ///< time until the next message can be displayed -}; - - -//-------------------------------------------------------------------------------------------------------------- -class CHintMessageQueue -{ -public: - CHintMessageQueue( CBasePlayer *pPlayer ); - void Reset(); - void Update(); - bool AddMessage( const char* message, float duration = 6.0f, CUtlVector< const char * > * args = NULL ); - inline bool IsEmpty() { return m_messages.Count() == 0; } - -private: - float m_tmMessageEnd; - CUtlVector< CHintMessage * > m_messages; - CBasePlayer *m_pPlayer; -}; - -//-------------------------------------------------------------------------------------------------------------- - -//-------------------------------------------------------------------------------------------------------------- -// Timers that manage hint messages that should be displayed after some time. -class CHintMessageTimers -{ -public: - CHintMessageTimers( void ); - CHintMessageTimers( CHintSystem *pSystem, CHintMessageQueue *pQueue ); - - void Reset(); - void Update(); - - // Add / Register timers that will be started/stopped during play - void AddTimer( int iHintID, float timer_duration, float message_duration = 6.0f, CUtlVector< const char * > * args = NULL ); - void RemoveTimer( int iHintID ); - - // Start / Stop timers that were previously registered via AddTimer() - void StartTimer( int iHintID ); - void StopTimer( int iHintID ); - -private: - int GetTimerIndex( int iHintID ); - -private: - struct hintmessagetime_t - { - hintmessagetime_t( float flTimerDuration ) : - timer(flTimerDuration) - { - iHintID = 0; - flMessageDuration = 6.0; - } - - ~hintmessagetime_t() - { - for ( int i=0; i args; - }; - - CUtlVector< hintmessagetime_t* > m_Timers; - CHintMessageQueue *m_pQueue; - CHintSystem *m_pHintSystem; -}; - -#endif // HINTMESSAGE_H diff --git a/game/shared/hintsystem.cpp b/game/shared/hintsystem.cpp deleted file mode 100644 index 77b205deb..000000000 --- a/game/shared/hintsystem.cpp +++ /dev/null @@ -1,323 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#include "hintsystem.h" -#include "hintmessage.h" - -#ifdef GAME_DLL -#else - #include -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#ifdef CLIENT_DLL -ConVar cl_showhelp( "cl_showhelp", "1", FCVAR_USERINFO | FCVAR_ARCHIVE, "Set to 0 to not show on-screen help" ); -#endif - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CHintSystem::CHintSystem( void ) -{ - Init( NULL, 0, NULL ); - m_pHintMessageQueue = NULL; - m_pHintMessageTimers = NULL; - m_flLastHintPlayedAt = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CHintSystem::~CHintSystem( void ) -{ - if ( m_pHintMessageTimers ) - { - delete m_pHintMessageTimers; - m_pHintMessageTimers = NULL; - } - - if ( m_pHintMessageQueue ) - { - delete m_pHintMessageQueue; - m_pHintMessageQueue = NULL; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHintSystem::Init( CBasePlayer *pPlayer, int iMaxHintTypes, const char **pszHintStrings ) -{ - m_pPlayer = pPlayer; - m_bShowHints = true; - - m_HintHistory.Resize( iMaxHintTypes ); - m_HintHistory.ClearAll(); - - m_pszHintMessages = pszHintStrings; - - if ( m_pPlayer ) - { - m_pHintMessageQueue = new CHintMessageQueue( m_pPlayer ); - m_pHintMessageTimers = new CHintMessageTimers( this, m_pHintMessageQueue ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHintSystem::Update( void ) -{ - if ( m_pHintMessageQueue ) - { - m_pHintMessageQueue->Update(); - } - if ( m_pHintMessageTimers ) - { - m_pHintMessageTimers->Update(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Displays a hint message to the player -// Input : hint - enum'd hint to show -// bForce - always play this hint even if they have seen it before -//----------------------------------------------------------------------------- -bool CHintSystem::HintMessage( int hint, bool bForce /* = false */, bool bOnlyIfClear /* = false */ ) -{ - Assert( m_pPlayer ); - Assert( hint < m_HintHistory.GetNumBits() ); - - // Not really an optimal solution, but saves us querying the hud element, - // which wouldn't be easy with derived versions in different mods. - if ( bOnlyIfClear && (gpGlobals->curtime - m_flLastHintPlayedAt < 11 ) ) - return false; - - if ( bForce || !HasPlayedHint(hint) ) - { - PlayedAHint(); - HintMessage( m_pszHintMessages[hint] ); - m_HintHistory.Set(hint); - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Displays a hint message to the player -// Input : *pMessage - -//----------------------------------------------------------------------------- -void CHintSystem::HintMessage( const char *pMessage ) -{ - Assert( m_pPlayer ); - -#ifdef GAME_DLL - // On the server, we send it down to the queue who sends it to the client - if ( !m_pPlayer->IsNetClient() || !m_pHintMessageQueue ) - return; - - if ( !m_bShowHints ) - return; - - m_pHintMessageQueue->AddMessage( pMessage ); -#else - // On the client, we just send it straight to the hint hud element - if ( cl_showhelp.GetBool() ) - { - IGameEvent *event = gameeventmanager->CreateEvent( "player_hintmessage" ); - if ( event ) - { - event->SetString( "hintmessage", pMessage ); - gameeventmanager->FireEventClientSide( event ); - } - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Clear out the existing timers, and register new ones for any -// hints that haven't been displayed yet. -//----------------------------------------------------------------------------- -void CHintSystem::ResetHints( void ) -{ - if ( !m_pHintMessageTimers ) - return; - - m_pHintMessageTimers->Reset(); - - // Readd registered hints - for (int i = 0; i < m_RegisteredResetHints.Count(); i++ ) - { - ReAddHintTimerIfNotDisplayed( m_RegisteredResetHints[i].iHintID, m_RegisteredResetHints[i].flTimer ); - } - - // Reset our queue - if ( m_pHintMessageQueue ) - { - m_pHintMessageQueue->Reset(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Call this to add a hint message that should be re-added -// everytime we're reset, if it hasn't been displayed yet. -//----------------------------------------------------------------------------- -void CHintSystem::RegisterHintTimer( int iHintID, float flTimerDuration, bool bOnlyIfClear /* = false */, HintTimerCallback pfnCallback ) -{ - Assert( m_pPlayer ); - Assert( iHintID < m_HintHistory.GetNumBits() ); - - onresethints_t newHint; - newHint.iHintID = iHintID; - newHint.flTimer = flTimerDuration; - newHint.bOnlyIfClear = bOnlyIfClear; - newHint.pfnCallback = pfnCallback; - m_RegisteredResetHints.AddToTail( newHint ); -} - -//----------------------------------------------------------------------------- -// Purpose: If the hint hasn't been displayed, start a timer for it -//----------------------------------------------------------------------------- -void CHintSystem::ReAddHintTimerIfNotDisplayed( int iHintID, float flTimerDuration ) -{ - Assert( iHintID < m_HintHistory.GetNumBits() ); - if ( m_HintHistory[iHintID] == 0 ) - { - m_pHintMessageTimers->AddTimer( iHintID, flTimerDuration ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHintSystem::StartHintTimer( int iHintID ) -{ - Assert( m_pPlayer ); - Assert( iHintID < m_HintHistory.GetNumBits() ); - Assert(m_pHintMessageTimers); - m_pHintMessageTimers->StartTimer( iHintID ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHintSystem::StopHintTimer( int iHintID ) -{ - Assert( m_pPlayer ); - Assert( iHintID < m_HintHistory.GetNumBits() ); - Assert(m_pHintMessageTimers); - m_pHintMessageTimers->StopTimer( iHintID ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHintSystem::ResetHintTimers( void ) -{ - Assert( m_pPlayer ); - Assert(m_pHintMessageTimers); - m_pHintMessageTimers->Reset(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHintSystem::RemoveHintTimer( int iHintID ) -{ - Assert( m_pPlayer ); - Assert( iHintID < m_HintHistory.GetNumBits() ); - Assert(m_pHintMessageTimers); - m_pHintMessageTimers->RemoveTimer( iHintID ); - - // Mark us as having heard this hint - m_HintHistory.Set(iHintID); -} - -//----------------------------------------------------------------------------- -// Purpose: See if there's a callback registered for the specified hint. -// If so, see if it wants to allow the hint to fire. -//----------------------------------------------------------------------------- -bool CHintSystem::TimerShouldFire( int iHintID ) -{ - for (int i = 0; i < m_RegisteredResetHints.Count(); i++ ) - { - if ( m_RegisteredResetHints[i].iHintID != iHintID ) - continue; - - if ( m_RegisteredResetHints[i].bOnlyIfClear && HintIsCurrentlyVisible() ) - return false; - - if ( m_RegisteredResetHints[i].pfnCallback ) - return m_RegisteredResetHints[i].pfnCallback( m_pPlayer ); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CHintSystem::ShouldShowHints( void ) -{ -#ifdef GAME_DLL - return m_bShowHints; -#else - return cl_showhelp.GetBool(); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHintSystem::PlayedAHint( void ) -{ - m_flLastHintPlayedAt = gpGlobals->curtime; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CHintSystem::HasPlayedHint( int iHintID ) -{ - Assert( m_pPlayer ); - Assert( iHintID < m_HintHistory.GetNumBits() ); - return ( m_HintHistory[iHintID] > 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHintSystem::SetHintPlayed( int iHintID ) -{ - Assert( m_pPlayer ); - Assert( iHintID < m_HintHistory.GetNumBits() ); - m_HintHistory.Set(iHintID); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void HintClear( void ) -{ -#ifdef CLIENT_DLL - C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); -#else - CBasePlayer* pPlayer = UTIL_GetCommandClient(); -#endif - if ( pPlayer && pPlayer->Hints() ) - { - pPlayer->Hints()->ClearHintHistory(); - } -} -#ifdef CLIENT_DLL -ConCommand cl_clearhinthistory( "cl_clearhinthistory", HintClear, "Clear memory of client side hints displayed to the player." ); -#else -ConCommand sv_clearhinthistory( "sv_clearhinthistory", HintClear, "Clear memory of server side hints displayed to the player." ); -#endif diff --git a/game/shared/hintsystem.h b/game/shared/hintsystem.h deleted file mode 100644 index 9d7845a96..000000000 --- a/game/shared/hintsystem.h +++ /dev/null @@ -1,116 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: A class embedded in players to provide hints to that player -// -//============================================================================= - -#ifndef HINTSYSTEM_H -#define HINTSYSTEM_H -#ifdef _WIN32 -#pragma once -#endif - -#ifdef CLIENT_DLL - #include "c_baseplayer.h" -#else - #include "player.h" -#endif - -#include "bitvec.h" - -class CHintMessageQueue; -class CHintMessageTimers; - -typedef bool (*HintTimerCallback)( CBasePlayer *pOnPlayer ); - -//----------------------------------------------------------------------------- -// Purpose: A class embedded in players to provide hints to that player -//----------------------------------------------------------------------------- -class CHintSystem -{ - DECLARE_CLASS_NOBASE( CHintSystem ); - -public: - CHintSystem(); - ~CHintSystem(); - - //----------------------------------------------------- - // Call this from your player constructor - void Init( CBasePlayer *pPlayer, int iMaxHintTypes, const char **pszHintStrings ); - - //----------------------------------------------------- - // CBasePlayer calls these for you, if you fall back to its - // versions of Spawn(), Event_Killed(), and PreThink(). - // Call this when your player respawns - void ResetHints( void ); - - // Call this when your player dies - void ResetHintTimers( void ); - - // Call this when in your player PreThink() - void Update( void ); - - //----------------------------------------------------- - // Hint addition - // Call these to add a hint directly onscreen - bool HintMessage( int hint, bool bForce = false, bool bOnlyIfClear = false ); - void HintMessage( const char *pMessage ); - - // Call this to add a hint timer. It'll be reset for you automatically - // everytime ResetHintTimers() is called. - void RegisterHintTimer( int iHintID, float flTimerDuration, bool bOnlyIfClear = false, HintTimerCallback pfnCallback = NULL ); - - // Call these to start & stop registered hint timers - void StartHintTimer( int iHintID ); - void StopHintTimer( int iHintID ); - void RemoveHintTimer( int iHintID ); - bool TimerShouldFire( int iHintID ); - - // Set whether a player should see any hints at all - void SetShowHints( bool bShowHints ) { m_bShowHints = bShowHints; } - void SetHintPlayed( int iHintID ); - bool ShouldShowHints( void ); - - // Returns true if the hint has been played already - bool HasPlayedHint( int iHintID ); - void PlayedAHint( void ); - void ClearHintHistory( void ) { m_HintHistory.ClearAll(); } - - // Not really an optimal solution, but saves us querying the hud element, - // which wouldn't be easy with derived versions in different mods. - bool HintIsCurrentlyVisible( void ) { return (gpGlobals->curtime - m_flLastHintPlayedAt < 11 ); } - -private: - void ReAddHintTimerIfNotDisplayed( int iHintID, float flTimerDuration ); - -private: - CBasePlayer *m_pPlayer; - - float m_flLastHintPlayedAt; - bool m_bShowHints; - CVarBitVec m_HintHistory; - const char **m_pszHintMessages; - CHintMessageQueue *m_pHintMessageQueue; - CHintMessageTimers *m_pHintMessageTimers; - - struct onresethints_t - { - int iHintID; - float flTimer; - bool bOnlyIfClear; - HintTimerCallback pfnCallback; - }; - CUtlVector m_RegisteredResetHints; -}; - -#ifdef CLIENT_DLL -// Derive from this if you have an entity that wants to display a hint -// when the player waves his target ID over it on the client. -abstract_class ITargetIDProvidesHint -{ -public: - virtual void DisplayHintTo( C_BasePlayer *pPlayer ) = 0; -}; -#endif - -#endif // HINTSYSTEM_H diff --git a/game/shared/hl2/achievements_hl2.cpp b/game/shared/hl2/achievements_hl2.cpp deleted file mode 100644 index 4fdd044dc..000000000 --- a/game/shared/hl2/achievements_hl2.cpp +++ /dev/null @@ -1,271 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - - -#include "cbase.h" - -#if GAME_DLL - -#include "achievementmgr.h" -#include "baseachievement.h" - -CAchievementMgr g_AchievementMgrHL2; // global achievement mgr for HL2 - -class CAchievementHL2KillBarnaclesWithOneBarrel : public CBaseAchievement -{ -protected: - virtual void Init() - { - SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_WITH_GAME ); - SetInflictorFilter( "prop_physics" ); - SetVictimFilter( "npc_barnacle" ); - SetGoal( 1 ); - m_pLastInflictor = NULL; - m_iBarnacleCount = 0; - } - - virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event ) - { - int iDamageBits = event->GetInt( "damagebits" ); - // only interested blast damage. (Barrels or other explosive phys objects are all OK) - if ( !( iDamageBits & DMG_BLAST ) ) - return; - - if ( m_pLastInflictor != NULL && pInflictor != m_pLastInflictor ) - { - m_iBarnacleCount = 1; - } - else - { - m_iBarnacleCount++; - if ( 5 == m_iBarnacleCount ) - { - IncrementCount(); - } - } - m_pLastInflictor = pInflictor; - } - - CBaseEntity *m_pLastInflictor; - int m_iBarnacleCount; -}; -DECLARE_ACHIEVEMENT( CAchievementHL2KillBarnaclesWithOneBarrel, ACHIEVEMENT_HL2_KILL_BARNACLESWITHBARREL, "HL2_KILL_BARNACLESWITHBARREL", 5 ); - -extern int CalcPlayerAttacks( bool bBulletOnly ); - -class CAchievementHL2BeatRavenholmNoWeapons : public CFailableAchievement -{ - DECLARE_CLASS( CAchievementHL2BeatRavenholmNoWeapons, CFailableAchievement ); - - void Init() - { - SetFlags( ACH_LISTEN_MAP_EVENTS | ACH_SAVE_WITH_GAME ); - SetGoal( 1 ); - m_iInitialAttackCount = 0; - } - - // map event where achievement is activated - virtual const char *GetActivationEventName() { return "HL2_BEAT_RAVENHOLM_NOWEAPONS_START"; } - // map event where achievement is evaluated for success - virtual const char *GetEvaluationEventName() { return "HL2_BEAT_RAVENHOLM_NOWEAPONS_END"; } - - virtual void PreRestoreSavedGame() - { - m_iInitialAttackCount = 0; - BaseClass::PreRestoreSavedGame(); - } - - virtual void OnActivationEvent() - { - // get current # of attacks by player w/all weapons (except grav gun) and store that - m_iInitialAttackCount = CalcPlayerAttacks( false ); - BaseClass::OnActivationEvent(); - } - - virtual void OnEvaluationEvent() - { - // get current # of attacks by player w/all weapons (except grav gun) - int iCurAttackCount = CalcPlayerAttacks( false ); - // compare to # of attacks when we started - if ( iCurAttackCount > m_iInitialAttackCount ) - { - // if there have been any more weapon attacks, achievement fails - SetFailed(); - } - BaseClass::OnEvaluationEvent(); - } - - // additional status for debugging - virtual void PrintAdditionalStatus() - { - if ( m_bActivated ) - { - Msg( "Starting wpn attacks: %d Current wpn attacks: %d\n", m_iInitialAttackCount, CalcPlayerAttacks( false ) ); - } - } - - int m_iInitialAttackCount; -public: - DECLARE_DATADESC() -}; -DECLARE_ACHIEVEMENT( CAchievementHL2BeatRavenholmNoWeapons, ACHIEVEMENT_HL2_BEAT_RAVENHOLM_NOWEAPONS, "HL2_BEAT_RAVENHOLM_NOWEAPONS", 25 ); - -BEGIN_DATADESC( CAchievementHL2BeatRavenholmNoWeapons ) -DEFINE_FIELD( m_iInitialAttackCount, FIELD_INTEGER ), -END_DATADESC() - - -class CAchievementHL2KillGunships : public CBaseAchievement -{ - void Init() - { - SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_WITH_GAME ); - SetVictimFilter( "npc_combinegunship" ); - SetGoal( 6 ); // note: goal is really six, although #define is "THREEGUNSHIPS" - } -}; -DECLARE_ACHIEVEMENT( CAchievementHL2KillGunships, ACHIEVEMENT_HL2_KILL_THREEGUNSHIPS, "HL2_KILL_THREEGUNSHIPS", 5 ); - -class CAchievementHL2KillEnemiesWithAntlions : public CBaseAchievement -{ - void Init() - { - SetFlags( ACH_LISTEN_KILL_ENEMY_EVENTS | ACH_SAVE_WITH_GAME ); - SetInflictorFilter( "npc_antlion" ); - SetGoal( 50 ); - } - - virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event ) - { - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - if ( pPlayer ) - { - // Only count antlion kills once player owns bugbait. - if ( pPlayer->Weapon_OwnsThisType( "weapon_bugbait" ) ) - { - IncrementCount(); - } - } - } -}; -DECLARE_ACHIEVEMENT( CAchievementHL2KillEnemiesWithAntlions, ACHIEVEMENT_HL2_KILL_ENEMIES_WITHANTLIONS, "HL2_KILL_ENEMIES_WITHANTLIONS", 10 ); - -class CAchievementHL2KillEnemyWithToilet : public CBaseAchievement -{ - void Init() - { - SetFlags( ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS | ACH_SAVE_WITH_GAME ); - SetInflictorFilter( "prop_physics" ); - SetGoal( 1 ); - } - - virtual void Event_EntityKilled( CBaseEntity *pVictim, CBaseEntity *pAttacker, CBaseEntity *pInflictor, IGameEvent *event ) - { - const char *pszName = GetModelName( pInflictor ); - - // skip past any directories and get just the file name - pszName = V_UnqualifiedFileName( pszName ); - // if model name matches one of the toilets, this counts - if ( ( 0 == Q_stricmp( pszName, "FurnitureToilet001a.mdl" ) ) || ( 0 == Q_stricmp( pszName, "prison_toilet01.mdl" ) ) ) - { - IncrementCount(); - } - } -}; -DECLARE_ACHIEVEMENT( CAchievementHL2KillEnemyWithToilet, ACHIEVEMENT_HL2_KILL_ENEMY_WITHTOILET, "HL2_KILL_ENEMY_WITHTOILET", 5 ); - -class CAchievementHL2DisintegrateSoldiersInField : public CBaseAchievement -{ - void Init() - { - SetFlags( ACH_SAVE_WITH_GAME ); - SetGoal( 15 ); - } - - virtual void ListenForEvents() - { - ListenForGameEvent( "ragdoll_dissolved" ); - } - - void FireGameEvent_Internal( IGameEvent *event ) - { - if ( 0 == Q_strcmp( event->GetName(), "ragdoll_dissolved" ) ) - { - CBaseEntity *pRagdoll = UTIL_EntityByIndex( event->GetInt( "entindex", 0 ) ); - if ( pRagdoll ) - { - const char *pszName = GetModelName( pRagdoll ); - - // skip past any directories and get just the file name - pszName = V_UnqualifiedFileName( pszName ); - - if ( ( 0 == Q_stricmp( pszName, "combine_soldier.mdl" ) ) || - ( 0 == Q_stricmp( pszName, "combine_super_soldier.mdl" ) ) ) - { - IncrementCount(); - } - } - } - } -}; -DECLARE_ACHIEVEMENT( CAchievementHL2DisintegrateSoldiersInField, ACHIEVEMENT_HL2_DISINTEGRATE_SOLDIERSINFIELD, "HL2_DISINTEGRATE_SOLDIERSINFIELD", 10 ); - -class CAchievementHL2FindAllLambdas : public CBaseAchievement -{ - virtual void Init() - { - static const char *szComponents[] = - { - "HL2_LAMDACACHE_KLEINERSLAB", "HL2_LAMDACACHE_CANALSSTATION", "HL2_LAMDACACHE_VENTCRAWL", "HL2_LAMDACACHE_CANALSTUNNEL", - "HL2_LAMDACACHE_SEWERGRATE", "HL2_LAMDACACHE_STEAMPIPE", "HL2_LAMDACACHE_CURVEDROOM", "HL2_LAMDACACHE_SHANTYTOWN", - "HL2_LAMDACACHE_TUNNELLADDER", "HL2_LAMDACACHE_REDBARN", "HL2_LAMDACACHE_ZOMBIEAMBUSH", "HL2_LAMDACACHE_BELOWAPCS", - "HL2_LAMDACACHE_COUNTERWEIGHT", "HL2_LAMDACACHE_RAILWAYBRIDGE", "HL2_LAMDACACHE_TUNNELPLATFORMS", "HL2_LAMDACACHE_BANKEDCANAL", - "HL2_LAMDACACHE_CANALWALL", "HL2_LAMDACACHE_CHANNELSPLIT", "HL2_LAMDACACHE_BMEDOCK", "HL2_LAMDACACHE_GENERATORS", - "HL2_LAMDACACHE_CARCRUSHERARENA", "HL2_LAMDACACHE_RAVENHOLMATTIC", "HL2_LAMDACACHE_MINETUNNELEXIT", - "HL2_LAMDACACHE_COASTSHACK", "HL2_LAMDACACHE_POISONSHACK", "HL2_LAMDACACHE_GUNSHIPVAN", "HL2_LAMDACACHE_SUICIDECITIZEN", - "HL2_LAMDACACHE_RAILROADSHACK", "HL2_LAMDACACHE_COASTABOVEBATTERY", "HL2_LAMDACACHE_SANDSHACK", "HL2_LAMDACACHE_GMANCACHE", - "HL2_LAMDACACHE_CELLCACHE", "HL2_LAMDACACHE_POISONLAUNDRY", "HL2_LAMDACACHE_SODAMACHINE", - "HL2_LAMDACACHE_STREETWARDOGWALL", "HL2_LAMDACACHE_STREETWARSHACK", "HL2_LAMDACACHE_STREETWARFENCE", "HL2_LAMDACACHE_FREEWAYTUNNEL", "HL2_LAMDACACHE_DRAWBRIDGE", - "HL2_LAMDACACHE_PLAZAFENCE", "HL2_LAMDACACHE_SEWERSCATWALKS", "HL2_LAMDACACHE_POISONZOMBIEALCOVE", "HL2_LAMDACACHE_PIPEHOPTUNNEL", - "HL2_LAMDACACHE_ENDOFC1712B", "HL2_LAMDACACHE_EXITCATWALK" - }; - SetFlags( ACH_HAS_COMPONENTS | ACH_LISTEN_COMPONENT_EVENTS | ACH_SAVE_GLOBAL ); - m_pszComponentNames = szComponents; - m_iNumComponents = ARRAYSIZE( szComponents ); - SetComponentPrefix( "HL2_LAMDACACHE" ); - SetGoal( m_iNumComponents ); - } -}; -DECLARE_ACHIEVEMENT( CAchievementHL2FindAllLambdas, ACHIEVEMENT_HL2_FIND_ALLLAMBDAS, "HL2_FIND_ALLLAMBDAS", 15 ); - -// achievements which are won by a map event firing once -DECLARE_MAP_EVENT_ACHIEVEMENT_HIDDEN( ACHIEVEMENT_HL2_HIT_CANCOP_WITHCAN, "HL2_HIT_CANCOP_WITHCAN", 5 ); -DECLARE_MAP_EVENT_ACHIEVEMENT_HIDDEN( ACHIEVEMENT_HL2_PUT_CANINTRASH, "HL2_PUT_CANINTRASH", 5 ); -DECLARE_MAP_EVENT_ACHIEVEMENT( ACHIEVEMENT_HL2_ESCAPE_APARTMENTRAID, "HL2_ESCAPE_APARTMENTRAID", 5 ); -DECLARE_MAP_EVENT_ACHIEVEMENT( ACHIEVEMENT_HL2_BREAK_MINITELEPORTER, "HL2_BREAK_MINITELEPORTER", 5 ); -DECLARE_MAP_EVENT_ACHIEVEMENT( ACHIEVEMENT_HL2_GET_CROWBAR, "HL2_GET_CROWBAR", 5 ); -DECLARE_MAP_EVENT_ACHIEVEMENT( ACHIEVEMENT_HL2_GET_AIRBOAT, "HL2_GET_AIRBOAT", 5 ); -DECLARE_MAP_EVENT_ACHIEVEMENT( ACHIEVEMENT_HL2_GET_AIRBOATGUN, "HL2_GET_AIRBOATGUN", 5 ); -DECLARE_MAP_EVENT_ACHIEVEMENT( ACHIEVEMENT_HL2_FIND_VORTIGAUNTCAVE, "HL2_FIND_VORTIGAUNTCAVE", 13 ); -DECLARE_MAP_EVENT_ACHIEVEMENT( ACHIEVEMENT_HL2_KILL_CHOPPER, "HL2_KILL_CHOPPER", 10 ); -DECLARE_MAP_EVENT_ACHIEVEMENT( ACHIEVEMENT_HL2_FIND_HEVFACEPLATE, "HL2_FIND_HEVFACEPLATE", 10 ); -DECLARE_MAP_EVENT_ACHIEVEMENT( ACHIEVEMENT_HL2_GET_GRAVITYGUN, "HL2_GET_GRAVITYGUN", 5 ); -DECLARE_MAP_EVENT_ACHIEVEMENT( ACHIEVEMENT_HL2_MAKEABASKET, "HL2_MAKEABASKET", 2 ); -DECLARE_MAP_EVENT_ACHIEVEMENT_HIDDEN( ACHIEVEMENT_HL2_BEAT_CEMETERY, "HL2_BEAT_CEMETERY", 5 ); -DECLARE_MAP_EVENT_ACHIEVEMENT( ACHIEVEMENT_HL2_KILL_ENEMIES_WITHCRANE, "HL2_KILL_ENEMIES_WITHCRANE", 5 ); -DECLARE_MAP_EVENT_ACHIEVEMENT( ACHIEVEMENT_HL2_PIN_SOLDIER_TOBILLBOARD, "HL2_PIN_SOLDIER_TOBILLBOARD", 5 ); -DECLARE_MAP_EVENT_ACHIEVEMENT_HIDDEN( ACHIEVEMENT_HL2_KILL_ODESSAGUNSHIP, "HL2_KILL_ODESSAGUNSHIP", 5 ); -DECLARE_MAP_EVENT_ACHIEVEMENT( ACHIEVEMENT_HL2_BEAT_DONTTOUCHSAND, "HL2_BEAT_DONTTOUCHSAND", 20 ); -DECLARE_MAP_EVENT_ACHIEVEMENT( ACHIEVEMENT_HL2_BEAT_TURRETSTANDOFF2, "HL2_BEAT_TURRETSTANDOFF2", 10 ); -DECLARE_MAP_EVENT_ACHIEVEMENT( ACHIEVEMENT_HL2_FOLLOW_FREEMAN, "HL2_FOLLOWFREEMAN", 10 ); -DECLARE_MAP_EVENT_ACHIEVEMENT( ACHIEVEMENT_HL2_BEAT_TOXICTUNNEL, "HL2_BEAT_TOXICTUNNEL", 5 ); -DECLARE_MAP_EVENT_ACHIEVEMENT( ACHIEVEMENT_HL2_BEAT_PLAZASTANDOFF, "HL2_BEAT_PLAZASTANDOFF", 10 ); -DECLARE_MAP_EVENT_ACHIEVEMENT( ACHIEVEMENT_HL2_KILL_ALLC1709SNIPERS, "HL2_KILL_ALLC1709SNIPERS", 5 ); -DECLARE_MAP_EVENT_ACHIEVEMENT( ACHIEVEMENT_HL2_BEAT_SUPRESSIONDEVICE, "HL2_BEAT_SUPRESSIONDEVICE", 10 ); -DECLARE_MAP_EVENT_ACHIEVEMENT( ACHIEVEMENT_HL2_BEAT_C1713STRIDERSTANDOFF, "HL2_BEAT_C1713STRIDERSTANDOFF", 10 ); -DECLARE_MAP_EVENT_ACHIEVEMENT_HIDDEN( ACHIEVEMENT_HL2_BEAT_GAME, "HL2_BEAT_GAME", 25 ); - -#endif // GAME_DLL diff --git a/game/shared/hl2/basehlcombatweapon_shared.cpp b/game/shared/hl2/basehlcombatweapon_shared.cpp deleted file mode 100644 index 8e8a6f983..000000000 --- a/game/shared/hl2/basehlcombatweapon_shared.cpp +++ /dev/null @@ -1,431 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "basehlcombatweapon_shared.h" - -#include "hl2_player_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -LINK_ENTITY_TO_CLASS( basehlcombatweapon, CBaseHLCombatWeapon ); - -IMPLEMENT_NETWORKCLASS_ALIASED( BaseHLCombatWeapon , DT_BaseHLCombatWeapon ) - -BEGIN_NETWORK_TABLE( CBaseHLCombatWeapon , DT_BaseHLCombatWeapon ) -#if !defined( CLIENT_DLL ) -// SendPropInt( SENDINFO( m_bReflectViewModelAnimations ), 1, SPROP_UNSIGNED ), -#else -// RecvPropInt( RECVINFO( m_bReflectViewModelAnimations ) ), -#endif -END_NETWORK_TABLE() - - -#if !defined( CLIENT_DLL ) - -#include "globalstate.h" - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CBaseHLCombatWeapon ) - - DEFINE_FIELD( m_bLowered, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flRaiseTime, FIELD_TIME ), - DEFINE_FIELD( m_flHolsterTime, FIELD_TIME ), - DEFINE_FIELD( m_iPrimaryAttacks, FIELD_INTEGER ), - DEFINE_FIELD( m_iSecondaryAttacks, FIELD_INTEGER ), - -END_DATADESC() - -#endif - -BEGIN_PREDICTION_DATA( CBaseHLCombatWeapon ) -END_PREDICTION_DATA() - -ConVar sk_auto_reload_time( "sk_auto_reload_time", "3", FCVAR_REPLICATED ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseHLCombatWeapon::ItemHolsterFrame( void ) -{ - BaseClass::ItemHolsterFrame(); - - // Must be player held - if ( GetOwner() && GetOwner()->IsPlayer() == false ) - return; - - // We can't be active - if ( GetOwner()->GetActiveWeapon() == this ) - return; - - // If it's been longer than three seconds, reload - if ( ( gpGlobals->curtime - m_flHolsterTime ) > sk_auto_reload_time.GetFloat() ) - { - // Just load the clip with no animations - FinishReload(); - m_flHolsterTime = gpGlobals->curtime; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CBaseHLCombatWeapon::CanLower() -{ - if ( SelectWeightedSequence( ACT_VM_IDLE_LOWERED ) == ACTIVITY_NOT_AVAILABLE ) - return false; - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Drops the weapon into a lowered pose -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseHLCombatWeapon::Lower( void ) -{ - //Don't bother if we don't have the animation - if ( SelectWeightedSequence( ACT_VM_IDLE_LOWERED ) == ACTIVITY_NOT_AVAILABLE ) - return false; - - m_bLowered = true; - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Brings the weapon up to the ready position -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseHLCombatWeapon::Ready( void ) -{ - //Don't bother if we don't have the animation - if ( SelectWeightedSequence( ACT_VM_LOWERED_TO_IDLE ) == ACTIVITY_NOT_AVAILABLE ) - return false; - - m_bLowered = false; - m_flRaiseTime = gpGlobals->curtime + 0.5f; - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseHLCombatWeapon::Deploy( void ) -{ - // If we should be lowered, deploy in the lowered position - // We have to ask the player if the last time it checked, the weapon was lowered - if ( GetOwner() && GetOwner()->IsPlayer() ) - { - CHL2_Player *pPlayer = assert_cast( GetOwner() ); - if ( pPlayer->IsWeaponLowered() ) - { - if ( SelectWeightedSequence( ACT_VM_IDLE_LOWERED ) != ACTIVITY_NOT_AVAILABLE ) - { - if ( DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), ACT_VM_IDLE_LOWERED, (char*)GetAnimPrefix() ) ) - { - m_bLowered = true; - - // Stomp the next attack time to fix the fact that the lower idles are long - pPlayer->SetNextAttack( gpGlobals->curtime + 1.0 ); - m_flNextPrimaryAttack = gpGlobals->curtime + 1.0; - m_flNextSecondaryAttack = gpGlobals->curtime + 1.0; - return true; - } - } - } - } - - m_bLowered = false; - return BaseClass::Deploy(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseHLCombatWeapon::Holster( CBaseCombatWeapon *pSwitchingTo ) -{ - if ( BaseClass::Holster( pSwitchingTo ) ) - { - m_flHolsterTime = gpGlobals->curtime; - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseHLCombatWeapon::WeaponShouldBeLowered( void ) -{ - // Can't be in the middle of another animation - if ( GetIdealActivity() != ACT_VM_IDLE_LOWERED && GetIdealActivity() != ACT_VM_IDLE && - GetIdealActivity() != ACT_VM_IDLE_TO_LOWERED && GetIdealActivity() != ACT_VM_LOWERED_TO_IDLE ) - return false; - - if ( m_bLowered ) - return true; - -#if !defined( CLIENT_DLL ) - - if ( GlobalEntity_GetState( "friendly_encounter" ) == GLOBAL_ON ) - return true; - -#endif - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Allows the weapon to choose proper weapon idle animation -//----------------------------------------------------------------------------- -void CBaseHLCombatWeapon::WeaponIdle( void ) -{ - //See if we should idle high or low - if ( WeaponShouldBeLowered() ) - { -#if !defined( CLIENT_DLL ) - CHL2_Player *pPlayer = dynamic_cast(GetOwner()); - - if( pPlayer ) - { - pPlayer->Weapon_Lower(); - } -#endif - - // Move to lowered position if we're not there yet - if ( GetActivity() != ACT_VM_IDLE_LOWERED && GetActivity() != ACT_VM_IDLE_TO_LOWERED - && GetActivity() != ACT_TRANSITION ) - { - SendWeaponAnim( ACT_VM_IDLE_LOWERED ); - } - else if ( HasWeaponIdleTimeElapsed() ) - { - // Keep idling low - SendWeaponAnim( ACT_VM_IDLE_LOWERED ); - } - } - else - { - // See if we need to raise immediately - if ( m_flRaiseTime < gpGlobals->curtime && GetActivity() == ACT_VM_IDLE_LOWERED ) - { - SendWeaponAnim( ACT_VM_IDLE ); - } - else if ( HasWeaponIdleTimeElapsed() ) - { - SendWeaponAnim( ACT_VM_IDLE ); - } - } -} - -float g_lateralBob; -float g_verticalBob; - -#if defined( CLIENT_DLL ) && ( !defined( HL2MP ) && !defined( PORTAL ) ) - -#define HL2_BOB_CYCLE_MIN 1.0f -#define HL2_BOB_CYCLE_MAX 0.45f -#define HL2_BOB 0.002f -#define HL2_BOB_UP 0.5f - - -static ConVar cl_bobcycle( "cl_bobcycle","0.8" ); -static ConVar cl_bob( "cl_bob","0.002" ); -static ConVar cl_bobup( "cl_bobup","0.5" ); - -// Register these cvars if needed for easy tweaking -static ConVar v_iyaw_cycle( "v_iyaw_cycle", "2"/*, FCVAR_UNREGISTERED*/ ); -static ConVar v_iroll_cycle( "v_iroll_cycle", "0.5"/*, FCVAR_UNREGISTERED*/ ); -static ConVar v_ipitch_cycle( "v_ipitch_cycle", "1"/*, FCVAR_UNREGISTERED*/ ); -static ConVar v_iyaw_level( "v_iyaw_level", "0.3"/*, FCVAR_UNREGISTERED*/ ); -static ConVar v_iroll_level( "v_iroll_level", "0.1"/*, FCVAR_UNREGISTERED*/ ); -static ConVar v_ipitch_level( "v_ipitch_level", "0.3"/*, FCVAR_UNREGISTERED*/ ); - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CBaseHLCombatWeapon::CalcViewmodelBob( void ) -{ - static float bobtime; - static float lastbobtime; - float cycle; - - CBasePlayer *player = ToBasePlayer( GetOwner() ); - //Assert( player ); - - //NOTENOTE: For now, let this cycle continue when in the air, because it snaps badly without it - - if ( ( !gpGlobals->frametime ) || ( player == NULL ) ) - { - //NOTENOTE: We don't use this return value in our case (need to restructure the calculation function setup!) - return 0.0f;// just use old value - } - - //Find the speed of the player - float speed = player->GetLocalVelocity().Length2D(); - - //FIXME: This maximum speed value must come from the server. - // MaxSpeed() is not sufficient for dealing with sprinting - jdw - - speed = clamp( speed, -320, 320 ); - - float bob_offset = RemapVal( speed, 0, 320, 0.0f, 1.0f ); - - bobtime += ( gpGlobals->curtime - lastbobtime ) * bob_offset; - lastbobtime = gpGlobals->curtime; - - //Calculate the vertical bob - cycle = bobtime - (int)(bobtime/HL2_BOB_CYCLE_MAX)*HL2_BOB_CYCLE_MAX; - cycle /= HL2_BOB_CYCLE_MAX; - - if ( cycle < HL2_BOB_UP ) - { - cycle = M_PI * cycle / HL2_BOB_UP; - } - else - { - cycle = M_PI + M_PI*(cycle-HL2_BOB_UP)/(1.0 - HL2_BOB_UP); - } - - g_verticalBob = speed*0.005f; - g_verticalBob = g_verticalBob*0.3 + g_verticalBob*0.7*sin(cycle); - - g_verticalBob = clamp( g_verticalBob, -7.0f, 4.0f ); - - //Calculate the lateral bob - cycle = bobtime - (int)(bobtime/HL2_BOB_CYCLE_MAX*2)*HL2_BOB_CYCLE_MAX*2; - cycle /= HL2_BOB_CYCLE_MAX*2; - - if ( cycle < HL2_BOB_UP ) - { - cycle = M_PI * cycle / HL2_BOB_UP; - } - else - { - cycle = M_PI + M_PI*(cycle-HL2_BOB_UP)/(1.0 - HL2_BOB_UP); - } - - g_lateralBob = speed*0.005f; - g_lateralBob = g_lateralBob*0.3 + g_lateralBob*0.7*sin(cycle); - g_lateralBob = clamp( g_lateralBob, -7.0f, 4.0f ); - - //NOTENOTE: We don't use this return value in our case (need to restructure the calculation function setup!) - return 0.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &origin - -// &angles - -// viewmodelindex - -//----------------------------------------------------------------------------- -void CBaseHLCombatWeapon::AddViewmodelBob( CBaseViewModel *viewmodel, Vector &origin, QAngle &angles ) -{ - Vector forward, right; - AngleVectors( angles, &forward, &right, NULL ); - - CalcViewmodelBob(); - - // Apply bob, but scaled down to 40% - VectorMA( origin, g_verticalBob * 0.1f, forward, origin ); - - // Z bob a bit more - origin[2] += g_verticalBob * 0.1f; - - // bob the angles - angles[ ROLL ] += g_verticalBob * 0.5f; - angles[ PITCH ] -= g_verticalBob * 0.4f; - - angles[ YAW ] -= g_lateralBob * 0.3f; - - VectorMA( origin, g_lateralBob * 0.8f, right, origin ); -} - -//----------------------------------------------------------------------------- -Vector CBaseHLCombatWeapon::GetBulletSpread( WeaponProficiency_t proficiency ) -{ - return BaseClass::GetBulletSpread( proficiency ); -} - -//----------------------------------------------------------------------------- -float CBaseHLCombatWeapon::GetSpreadBias( WeaponProficiency_t proficiency ) -{ - return BaseClass::GetSpreadBias( proficiency ); -} -//----------------------------------------------------------------------------- - -const WeaponProficiencyInfo_t *CBaseHLCombatWeapon::GetProficiencyValues() -{ - return NULL; -} - -#else - -// Server stubs -float CBaseHLCombatWeapon::CalcViewmodelBob( void ) -{ - return 0.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &origin - -// &angles - -// viewmodelindex - -//----------------------------------------------------------------------------- -void CBaseHLCombatWeapon::AddViewmodelBob( CBaseViewModel *viewmodel, Vector &origin, QAngle &angles ) -{ -} - - -//----------------------------------------------------------------------------- -Vector CBaseHLCombatWeapon::GetBulletSpread( WeaponProficiency_t proficiency ) -{ - Vector baseSpread = BaseClass::GetBulletSpread( proficiency ); - - const WeaponProficiencyInfo_t *pProficiencyValues = GetProficiencyValues(); - float flModifier = (pProficiencyValues)[ proficiency ].spreadscale; - return ( baseSpread * flModifier ); -} - -//----------------------------------------------------------------------------- -float CBaseHLCombatWeapon::GetSpreadBias( WeaponProficiency_t proficiency ) -{ - const WeaponProficiencyInfo_t *pProficiencyValues = GetProficiencyValues(); - return (pProficiencyValues)[ proficiency ].bias; -} - -//----------------------------------------------------------------------------- -const WeaponProficiencyInfo_t *CBaseHLCombatWeapon::GetProficiencyValues() -{ - return GetDefaultProficiencyValues(); -} - -//----------------------------------------------------------------------------- -const WeaponProficiencyInfo_t *CBaseHLCombatWeapon::GetDefaultProficiencyValues() -{ - // Weapon proficiency table. Keep this in sync with WeaponProficiency_t enum in the header!! - static WeaponProficiencyInfo_t g_BaseWeaponProficiencyTable[] = - { - { 2.50, 1.0 }, - { 2.00, 1.0 }, - { 1.50, 1.0 }, - { 1.25, 1.0 }, - { 1.00, 1.0 }, - }; - - COMPILE_TIME_ASSERT( ARRAYSIZE(g_BaseWeaponProficiencyTable) == WEAPON_PROFICIENCY_PERFECT + 1); - - return g_BaseWeaponProficiencyTable; -} - -#endif diff --git a/game/shared/hl2/basehlcombatweapon_shared.h b/game/shared/hl2/basehlcombatweapon_shared.h deleted file mode 100644 index d46b18b44..000000000 --- a/game/shared/hl2/basehlcombatweapon_shared.h +++ /dev/null @@ -1,66 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "basecombatweapon_shared.h" - -#ifndef BASEHLCOMBATWEAPON_SHARED_H -#define BASEHLCOMBATWEAPON_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - -#if defined( CLIENT_DLL ) -#define CBaseHLCombatWeapon C_BaseHLCombatWeapon -#endif - -class CBaseHLCombatWeapon : public CBaseCombatWeapon -{ -#if !defined( CLIENT_DLL ) -#ifndef _XBOX - DECLARE_DATADESC(); -#else -protected: - DECLARE_DATADESC(); -private: -#endif -#endif - - DECLARE_CLASS( CBaseHLCombatWeapon, CBaseCombatWeapon ); -public: - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - - virtual bool WeaponShouldBeLowered( void ); - - bool CanLower(); - virtual bool Ready( void ); - virtual bool Lower( void ); - virtual bool Deploy( void ); - virtual bool Holster( CBaseCombatWeapon *pSwitchingTo ); - virtual void WeaponIdle( void ); - - virtual void AddViewmodelBob( CBaseViewModel *viewmodel, Vector &origin, QAngle &angles ); - virtual float CalcViewmodelBob( void ); - - virtual Vector GetBulletSpread( WeaponProficiency_t proficiency ); - virtual float GetSpreadBias( WeaponProficiency_t proficiency ); - - virtual const WeaponProficiencyInfo_t *GetProficiencyValues(); - static const WeaponProficiencyInfo_t *GetDefaultProficiencyValues(); - - virtual void ItemHolsterFrame( void ); - - int m_iPrimaryAttacks; // # of primary attacks performed with this weapon - int m_iSecondaryAttacks; // # of secondary attacks performed with this weapon - -protected: - - bool m_bLowered; // Whether the viewmodel is raised or lowered - float m_flRaiseTime; // If lowered, the time we should raise the viewmodel - float m_flHolsterTime; // When the weapon was holstered -}; - -#endif // BASEHLCOMBATWEAPON_SHARED_H diff --git a/game/shared/hl2/citadel_effects_shared.h b/game/shared/hl2/citadel_effects_shared.h deleted file mode 100644 index e28f82cf5..000000000 --- a/game/shared/hl2/citadel_effects_shared.h +++ /dev/null @@ -1,62 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef CITADEL_EFFECTS_SHARED_H -#define CITADEL_EFFECTS_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - -#define SF_ENERGYCORE_NO_PARTICLES (1<<0) -#define SF_ENERGYCORE_START_ON (1<<1) - -enum -{ - ENERGYCORE_STATE_OFF, - ENERGYCORE_STATE_CHARGING, - ENERGYCORE_STATE_DISCHARGING, -}; - -#ifndef CLIENT_DLL - -// ============================================================================ -// -// Energy core - charges up and then releases energy from its position -// -// ============================================================================ - -class CCitadelEnergyCore : public CBaseEntity -{ - DECLARE_CLASS( CCitadelEnergyCore, CBaseEntity ); - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - -public: - void InputStartCharge( inputdata_t &inputdata ); - void InputStartDischarge( inputdata_t &inputdata ); - void InputStop( inputdata_t &inputdata ); - void SetScale( float flScale ) { m_flScale = flScale; } - - void StartCharge( float flWarmUpTime ); - void StartDischarge(); - void StopDischarge( float flCoolDownTime ); - - virtual int ShouldTransmit( const CCheckTransmitInfo *pInfo ); - virtual int UpdateTransmitState( void ); - - virtual void Precache(); - void Spawn( void ); - -private: - CNetworkVar( float, m_flScale ); - CNetworkVar( int, m_nState ); - CNetworkVar( float, m_flDuration ); - CNetworkVar( float, m_flStartTime ); -}; - -#endif - -#endif // CITADEL_EFFECTS_SHARED_H diff --git a/game/shared/hl2/env_alyxemp_shared.h b/game/shared/hl2/env_alyxemp_shared.h deleted file mode 100644 index d9c9e012c..000000000 --- a/game/shared/hl2/env_alyxemp_shared.h +++ /dev/null @@ -1,63 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ENV_ALYXEMP_SHARED_H -#define ENV_ALYXEMP_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - -#include "beam_shared.h" - -enum -{ - ALYXEMP_STATE_OFF, - ALYXEMP_STATE_CHARGING, - ALYXEMP_STATE_DISCHARGING, -}; - -class CAlyxEmpEffect : public CBaseEntity -{ - DECLARE_CLASS( CAlyxEmpEffect, CBaseEntity ); - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - -public: - - void InputStartCharge( inputdata_t &inputdata ); - void InputStartDischarge( inputdata_t &inputdata ); - void InputStop( inputdata_t &inputdata ); - void InputSetTargetEnt( inputdata_t &inputdata ); - - void StartCharge( float flDuration ); - void StartDischarge(); - void Stop( float flDuration ); - void SetTargetEntity( CBaseEntity *pTarget ); - - void ActivateAutomatic( CBaseEntity *pAlyx, CBaseEntity *pTarget ); - void AutomaticThink(); - - void Spawn( void ); - void Precache( void ); - void Activate( void ); - -private: - - void SetTargetEntity( const char *szEntityName ); - CHandle m_hBeam; - CHandle m_hTargetEnt; - string_t m_strTargetName; - int m_nType; // What type of effect this is (small, large) - int m_iState; - bool m_bAutomated; - - CNetworkVar( int, m_nState ); - CNetworkVar( float, m_flDuration ); - CNetworkVar( float, m_flStartTime ); -}; - - -#endif // ENV_ALYXEMP_SHARED_H diff --git a/game/shared/hl2/env_headcrabcanister_shared.cpp b/game/shared/hl2/env_headcrabcanister_shared.cpp deleted file mode 100644 index 5d774d566..000000000 --- a/game/shared/hl2/env_headcrabcanister_shared.cpp +++ /dev/null @@ -1,393 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "env_headcrabcanister_shared.h" -#include "mapdata_shared.h" -#include "sharedInterface.h" -#include "mathlib/vmatrix.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define ROTATION_SPEED 90.0f - - -BEGIN_SIMPLE_DATADESC( CEnvHeadcrabCanisterShared ) - DEFINE_FIELD( m_vecStartPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecEnterWorldPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( m_vecDirection, FIELD_VECTOR ), - DEFINE_FIELD( m_vecStartAngles, FIELD_VECTOR ), - DEFINE_KEYFIELD( m_flLaunchHeight, FIELD_FLOAT, "StartingHeight" ), - DEFINE_KEYFIELD( m_flFlightSpeed, FIELD_FLOAT, "FlightSpeed" ), - DEFINE_KEYFIELD( m_flFlightTime, FIELD_FLOAT, "FlightTime" ), - DEFINE_FIELD( m_flLaunchTime, FIELD_TIME ), - DEFINE_FIELD( m_flWorldEnterTime, FIELD_FLOAT ), - DEFINE_FIELD( m_flInitialZSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_flZAcceleration, FIELD_FLOAT ), - DEFINE_FIELD( m_flHorizSpeed, FIELD_FLOAT ), - DEFINE_FIELD( m_bLaunchedFromWithinWorld, FIELD_BOOLEAN ), - DEFINE_FIELD( m_vecSkyboxOrigin, FIELD_VECTOR ), - DEFINE_FIELD( m_vecParabolaDirection, FIELD_VECTOR ), - DEFINE_FIELD( m_flSkyboxScale, FIELD_FLOAT ), - DEFINE_FIELD( m_bInSkybox, FIELD_BOOLEAN ), -END_DATADESC() - - -BEGIN_NETWORK_TABLE_NOBASE( CEnvHeadcrabCanisterShared, DT_EnvHeadcrabCanisterShared ) - -#if !defined( CLIENT_DLL ) - SendPropFloat ( SENDINFO( m_flFlightSpeed ), 0, SPROP_NOSCALE ), - SendPropTime ( SENDINFO( m_flLaunchTime ) ), - SendPropVector ( SENDINFO( m_vecParabolaDirection ), 0, SPROP_NOSCALE ), - - SendPropFloat ( SENDINFO( m_flFlightTime ), 0, SPROP_NOSCALE ), - SendPropFloat ( SENDINFO( m_flWorldEnterTime ), 0, SPROP_NOSCALE ), - - SendPropFloat ( SENDINFO( m_flInitialZSpeed ), 0, SPROP_NOSCALE ), - SendPropFloat ( SENDINFO( m_flZAcceleration ), 0, SPROP_NOSCALE ), - SendPropFloat ( SENDINFO( m_flHorizSpeed ), 0, SPROP_NOSCALE ), - SendPropBool ( SENDINFO( m_bLaunchedFromWithinWorld ) ), - - SendPropVector ( SENDINFO( m_vecStartPosition ), 0, SPROP_NOSCALE ), - SendPropVector ( SENDINFO( m_vecEnterWorldPosition ), 0, SPROP_NOSCALE ), - SendPropVector ( SENDINFO( m_vecDirection ), 0, SPROP_NOSCALE ), - SendPropVector ( SENDINFO( m_vecStartAngles ), 0, SPROP_NOSCALE ), - - SendPropVector ( SENDINFO( m_vecSkyboxOrigin ), 0, SPROP_NOSCALE ), - SendPropFloat ( SENDINFO( m_flSkyboxScale ), 0, SPROP_NOSCALE ), - SendPropBool ( SENDINFO( m_bInSkybox ) ), -#else - RecvPropFloat ( RECVINFO( m_flFlightSpeed ) ), - RecvPropTime ( RECVINFO( m_flLaunchTime ) ), - RecvPropVector ( RECVINFO( m_vecParabolaDirection ) ), - - RecvPropFloat ( RECVINFO( m_flFlightTime ) ), - RecvPropFloat ( RECVINFO( m_flWorldEnterTime ) ), - - RecvPropFloat ( RECVINFO( m_flInitialZSpeed ) ), - RecvPropFloat ( RECVINFO( m_flZAcceleration ) ), - RecvPropFloat ( RECVINFO( m_flHorizSpeed ) ), - RecvPropBool ( RECVINFO( m_bLaunchedFromWithinWorld ) ), - - RecvPropVector ( RECVINFO( m_vecStartPosition ) ), - RecvPropVector ( RECVINFO( m_vecEnterWorldPosition ) ), - RecvPropVector ( RECVINFO( m_vecDirection ) ), - RecvPropVector ( RECVINFO( m_vecStartAngles ) ), - - RecvPropVector ( RECVINFO( m_vecSkyboxOrigin ) ), - RecvPropFloat ( RECVINFO( m_flSkyboxScale ) ), - RecvPropBool ( RECVINFO( m_bInSkybox ) ), -#endif - -END_NETWORK_TABLE() - - - -//============================================================================= -// -// HeadcrabCanister Functions. -// - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CEnvHeadcrabCanisterShared::CEnvHeadcrabCanisterShared() -{ - m_vecStartPosition.Init(); - m_vecDirection.Init(); - m_flFlightSpeed = 0.0f; - - // This tells the client DLL to not draw trails, etc. - m_flLaunchTime = -1.0f; - - m_flWorldEnterTime = 0.0f; - m_flFlightTime = 0.0f; - m_bInSkybox = false; -} - - -//----------------------------------------------------------------------------- -// Creates a headcrab canister in the world -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanisterShared::InitInWorld( float flLaunchTime, - const Vector &vecStartPosition, const QAngle &vecStartAngles, - const Vector &vecDirection, const Vector &vecImpactPosition, bool bLaunchedFromWithinWorld ) -{ - Vector vecActualStartPosition = vecStartPosition; - if ( !bLaunchedFromWithinWorld ) - { - // Move the start position inward if it's too close - Vector vecDelta; - VectorSubtract( vecStartPosition, vecImpactPosition, vecDelta ); - VectorNormalize( vecDelta ); - - VectorMA( vecImpactPosition, m_flFlightTime * m_flFlightSpeed, vecDelta, vecActualStartPosition ); - } - - // Setup initial parametric state. - m_flLaunchTime = flLaunchTime; - m_vecStartPosition = vecActualStartPosition; - m_vecEnterWorldPosition = vecActualStartPosition; - m_vecDirection = vecDirection; - m_vecStartAngles = vecStartAngles; - m_flWorldEnterTime = 0.0f; - m_bInSkybox = false; - m_bLaunchedFromWithinWorld = bLaunchedFromWithinWorld; - - if ( m_bLaunchedFromWithinWorld ) - { - m_flSkyboxScale = 1; - m_vecSkyboxOrigin = vec3_origin; - - float flLength = m_vecDirection.Get().AsVector2D().Length(); - VectorSubtract(vecImpactPosition, vecStartPosition, m_vecParabolaDirection.GetForModify()); - m_vecParabolaDirection.GetForModify().z = 0; - float flTotalDistance = VectorNormalize( m_vecParabolaDirection.GetForModify() ); - m_vecDirection.GetForModify().x = flLength * m_vecParabolaDirection.Get().x; - m_vecDirection.GetForModify().y = flLength * m_vecParabolaDirection.Get().y; - - m_flHorizSpeed = flTotalDistance / m_flFlightTime; - m_flWorldEnterTime = 0; - - float flFinalZSpeed = m_vecDirection.Get().z * m_flHorizSpeed; - m_flFlightSpeed = sqrt( m_flHorizSpeed * m_flHorizSpeed + flFinalZSpeed * flFinalZSpeed ); - m_flInitialZSpeed = (2.0f * ( vecImpactPosition.z - vecStartPosition.z ) - flFinalZSpeed * m_flFlightTime) / m_flFlightTime; - m_flZAcceleration = (flFinalZSpeed - m_flInitialZSpeed) / m_flFlightTime; - } -} - - -//----------------------------------------------------------------------------- -// Creates a headcrab canister in the skybox -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanisterShared::InitInSkybox( float flLaunchTime, - const Vector &vecStartPosition, const QAngle &vecStartAngles, const Vector &vecDirection, - const Vector &vecImpactPosition, const Vector &vecSkyboxOrigin, float flSkyboxScale ) -{ - // Compute a horizontal speed (constant) - m_vecParabolaDirection.Init( vecDirection.x, vecDirection.y, 0.0f ); - float flLength = VectorNormalize( m_vecParabolaDirection.GetForModify() ); - m_flHorizSpeed = flLength * m_flFlightSpeed; - - // compute total distance to travel - float flTotalDistance = m_flFlightTime * m_flHorizSpeed; - flTotalDistance -= vecStartPosition.AsVector2D().DistTo( vecImpactPosition.AsVector2D() ); - if ( flTotalDistance <= 0.0f ) - { - InitInWorld( flLaunchTime, vecStartPosition, vecStartAngles, vecDirection, vecImpactPosition ); - return; - } - - // Setup initial parametric state. - m_flLaunchTime = flLaunchTime; - m_flWorldEnterTime = flTotalDistance / m_flHorizSpeed; - m_vecSkyboxOrigin = vecSkyboxOrigin; - m_flSkyboxScale = flSkyboxScale; - - m_vecEnterWorldPosition = vecStartPosition; - m_vecDirection = vecDirection; - m_vecStartAngles = vecStartAngles; - m_bInSkybox = true; - m_bLaunchedFromWithinWorld = false; - - // Compute parabolic course - // Assume the x velocity remains constant. - // Z moves ballistically, as if under gravity - // zf + lh = zo - // vf = vo + a*t - // zf = zo + vo*t + 0.5 * a * t*t - // a*t = vf - vo - // zf = zo + vo*t + 0.5f * (vf - vo) * t - // zf - zo = 0.5f *vo*t + 0.5f * vf * t - // -lh - 0.5f * vf * t = 0.5f * vo * t - // vo = -2.0f * lh / t - vf - // a = (vf - vo) / t - m_flHorizSpeed /= flSkyboxScale; - - VectorMA( vecSkyboxOrigin, 1.0f / m_flSkyboxScale, vecStartPosition, m_vecStartPosition.GetForModify() ); - VectorMA( m_vecStartPosition.Get(), -m_flHorizSpeed * m_flWorldEnterTime, m_vecParabolaDirection, m_vecStartPosition.GetForModify() ); - - float flLaunchHeight = m_flLaunchHeight / flSkyboxScale; - float flFinalZSpeed = m_vecDirection.Get().z * m_flFlightSpeed / flSkyboxScale; - m_vecStartPosition.GetForModify().z += flLaunchHeight; - m_flZAcceleration = 2.0f * ( flLaunchHeight + flFinalZSpeed * m_flWorldEnterTime ) / ( m_flWorldEnterTime * m_flWorldEnterTime ); - m_flInitialZSpeed = flFinalZSpeed - m_flZAcceleration * m_flWorldEnterTime; -} - - -//----------------------------------------------------------------------------- -// Convert from skybox to world -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanisterShared::ConvertFromSkyboxToWorld() -{ - Assert( m_bInSkybox ); - m_bInSkybox = false; -} - - -//----------------------------------------------------------------------------- -// Returns the time at which it enters the world -//----------------------------------------------------------------------------- -float CEnvHeadcrabCanisterShared::GetEnterWorldTime() const -{ - return m_flWorldEnterTime; -} - - -//----------------------------------------------------------------------------- -// Did we impact? -//----------------------------------------------------------------------------- -bool CEnvHeadcrabCanisterShared::DidImpact( float flTime ) const -{ - return (flTime - m_flLaunchTime) >= m_flFlightTime; -} - - -//----------------------------------------------------------------------------- -// Computes the position of the canister -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanisterShared::GetPositionAtTime( float flTime, Vector &vecPosition, QAngle &vecAngles ) -{ - float flDeltaTime = flTime - m_flLaunchTime; - if ( flDeltaTime > m_flFlightTime ) - { - flDeltaTime = m_flFlightTime; - } - - VMatrix initToWorld; - if ( m_bLaunchedFromWithinWorld || m_bInSkybox ) - { - VectorMA( m_vecStartPosition, flDeltaTime * m_flHorizSpeed, m_vecParabolaDirection, vecPosition ); - vecPosition.z += m_flInitialZSpeed * flDeltaTime + 0.5f * m_flZAcceleration * flDeltaTime * flDeltaTime; - - Vector vecLeft; - CrossProduct( m_vecParabolaDirection, Vector( 0, 0, 1 ), vecLeft ); - - Vector vecForward; - VectorMultiply( m_vecParabolaDirection, -1.0f, vecForward ); - vecForward.z = -(m_flInitialZSpeed + m_flZAcceleration * flDeltaTime) / m_flHorizSpeed; // This is -dz/dx. - VectorNormalize( vecForward ); - - Vector vecUp; - CrossProduct( vecForward, vecLeft, vecUp ); - - initToWorld.SetBasisVectors( vecForward, vecLeft, vecUp ); - } - else - { - flDeltaTime -= m_flWorldEnterTime; - Vector vecVelocity; - VectorMultiply( m_vecDirection, m_flFlightSpeed, vecVelocity ); - VectorMA( m_vecEnterWorldPosition, flDeltaTime, vecVelocity, vecPosition ); - - MatrixFromAngles( m_vecStartAngles.Get(), initToWorld ); - } - - VMatrix rotation; - MatrixBuildRotationAboutAxis( rotation, Vector( 1, 0, 0 ), flDeltaTime * ROTATION_SPEED ); - - VMatrix newAngles; - MatrixMultiply( initToWorld, rotation, newAngles ); - MatrixToAngles( newAngles, vecAngles ); -} - - -//----------------------------------------------------------------------------- -// Are we in the skybox? -//----------------------------------------------------------------------------- -bool CEnvHeadcrabCanisterShared::IsInSkybox( ) -{ - // Check to see if we are always in the world! - return m_bInSkybox; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CEnvHeadcrabCanisterShared::CalcEnterTime( const Vector &vecTriggerMins, - const Vector &vecTriggerMaxs ) -{ - /* -#define HEADCRABCANISTER_TRIGGER_EPSILON 0.001f - - // Initialize the enter/exit fractions. - float flEnterFrac = 0.0f; - float flExitFrac = 1.0f; - - // Create an arbitrarily large end position. - Vector vecEndPosition; - VectorMA( m_vecStartPosition, 32000.0f, m_vecDirection, vecEndPosition ); - - float flFrac, flDistStart, flDistEnd; - for( int iAxis = 0; iAxis < 3; iAxis++ ) - { - // Negative Axis - flDistStart = -m_vecStartPosition[iAxis] + vecTriggerMins[iAxis]; - flDistEnd = -vecEndPosition[iAxis] + vecTriggerMins[iAxis]; - - if ( ( flDistStart > 0.0f ) && ( flDistEnd < 0.0f ) ) - { - flFrac = ( flDistStart - HEADCRABCANISTER_TRIGGER_EPSILON ) / ( flDistStart - flDistEnd ); - if ( flFrac > flEnterFrac ) { flEnterFrac = flFrac; } - } - - if ( ( flDistStart < 0.0f ) && ( flDistEnd > 0.0f ) ) - { - flFrac = ( flDistStart + HEADCRABCANISTER_TRIGGER_EPSILON ) / ( flDistStart - flDistEnd ); - if( flFrac < flExitFrac ) { flExitFrac = flFrac; } - } - - if ( ( flDistStart > 0.0f ) && ( flDistEnd > 0.0f ) ) - return; - - // Positive Axis - flDistStart = m_vecStartPosition[iAxis] - vecTriggerMaxs[iAxis]; - flDistEnd = vecEndPosition[iAxis] - vecTriggerMaxs[iAxis]; - - if ( ( flDistStart > 0.0f ) && ( flDistEnd < 0.0f ) ) - { - flFrac = ( flDistStart - HEADCRABCANISTER_TRIGGER_EPSILON ) / ( flDistStart - flDistEnd ); - if ( flFrac > flEnterFrac ) { flEnterFrac = flFrac; } - } - - if ( ( flDistStart < 0.0f ) && ( flDistEnd > 0.0f ) ) - { - flFrac = ( flDistStart + HEADCRABCANISTER_TRIGGER_EPSILON ) / ( flDistStart - flDistEnd ); - if( flFrac < flExitFrac ) { flExitFrac = flFrac; } - } - - if ( ( flDistStart > 0.0f ) && ( flDistEnd > 0.0f ) ) - return; - } - - // Check for intersection. - if ( flExitFrac >= flEnterFrac ) - { - // Check to see if we start in the world or the skybox! - if ( flEnterFrac == 0.0f ) - { - m_nLocation = HEADCRABCANISTER_LOCATION_WORLD; - } - else - { - m_nLocation = HEADCRABCANISTER_LOCATION_SKYBOX; - } - - // Calculate the enter/exit times. - Vector vecEnterPoint, vecExitPoint, vecDeltaPosition; - VectorSubtract( vecEndPosition, m_vecStartPosition, vecDeltaPosition ); - VectorScale( vecDeltaPosition, flEnterFrac, vecEnterPoint ); - VectorScale( vecDeltaPosition, flExitFrac, vecExitPoint ); - - m_flWorldEnterTime = vecEnterPoint.Length() / m_flFlightSpeed; - m_flWorldEnterTime += m_flLaunchTime; - } - */ - -#undef HEADCRABCANISTER_TRIGGER_EPSILON -} - diff --git a/game/shared/hl2/env_headcrabcanister_shared.h b/game/shared/hl2/env_headcrabcanister_shared.h deleted file mode 100644 index b6360ffc5..000000000 --- a/game/shared/hl2/env_headcrabcanister_shared.h +++ /dev/null @@ -1,180 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ENV_HEADCRABCANISTER_SHARED_H -#define ENV_HEADCRABCANISTER_SHARED_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "vstdlib/random.h" -#include "mathlib/vector.h" -#include "utlvector.h" -#include "networkvar.h" - -//============================================================================= -// -// Shared HeadcrabCanister Class -// -class CEnvHeadcrabCanisterShared -{ - DECLARE_CLASS_NOBASE( CEnvHeadcrabCanisterShared ); - DECLARE_EMBEDDED_NETWORKVAR(); - DECLARE_SIMPLE_DATADESC(); - -public: - CEnvHeadcrabCanisterShared(); - - // Initialization. - void InitInWorld( float flLaunchTime, const Vector &vecStartPosition, const QAngle &vecStartAngles, const Vector &vecDirection, const Vector &vecImpactPosition, bool bLaunchedFromWithinWorld = false ); - void InitInSkybox( float flLaunchTime, const Vector &vecStartPosition, const QAngle &vecStartAngles, const Vector &vecDirection, const Vector &vecImpactPosition, const Vector &vecSkyboxOrigin, float flSkyboxScale ); - - // Returns the position of the object at a given time. - void GetPositionAtTime( float flTime, Vector &vecPosition, QAngle &vecAngles ); - - // Returns whether or not the object is the the skybox - bool IsInSkybox( ); - - // Returns the time at which it enters the world - float GetEnterWorldTime() const; - - // Convert from skybox to world - void ConvertFromSkyboxToWorld(); - - // Did we impact? - bool DidImpact( float flTime ) const; - -public: - // The objects initial parametric conditions. - CNetworkVector( m_vecStartPosition ); - CNetworkVector( m_vecEnterWorldPosition ); - CNetworkVector( m_vecDirection ); - CNetworkQAngle( m_vecStartAngles ); - - CNetworkVar( float, m_flFlightTime ); - CNetworkVar( float, m_flFlightSpeed ); - CNetworkVar( float, m_flLaunchTime ); - - CNetworkVar( float, m_flInitialZSpeed ); - CNetworkVar( float, m_flZAcceleration ); - CNetworkVar( float, m_flHorizSpeed ); - - CNetworkVar( bool, m_bLaunchedFromWithinWorld ); - - CNetworkVector( m_vecParabolaDirection ); - - // The time at which the canister enters the skybox - CNetworkVar( float, m_flWorldEnterTime ); - - // Skybox data - CNetworkVector( m_vecSkyboxOrigin ); - CNetworkVar( float, m_flSkyboxScale ); - CNetworkVar( bool, m_bInSkybox ); - -private: - float m_flLaunchHeight; - - // Calculate the enter time. (called from Init) - void CalcEnterTime( const Vector &vecTriggerMins, const Vector &vecTriggerMaxs ); - - friend class CEnvHeadcrabCanister; - friend class C_EnvHeadcrabCanister; -}; - -/* -//============================================================================= -// -// HeadcrabCanister Factory Interface -// -abstract_class IHeadcrabCanisterFactory -{ -public: - - virtual void CreateHeadcrabCanister( int nID, int iType, - const Vector &vecPosition, const Vector &vecDirection, - float flSpeed, float flStartTime, float flDamageRadius, - const Vector &vecTriggerMins, const Vector &vecTriggerMaxs ) = 0; -}; - -//============================================================================= -// -// Shared HeadcrabCanister Spawner Class -// -class CEnvHeadcrabCanisterSpawnerShared -{ -public: - DECLARE_CLASS_NOBASE( CEnvHeadcrabCanisterSpawnerShared ); - DECLARE_EMBEDDED_NETWORKVAR(); - - //------------------------------------------------------------------------- - // Initialization. - //------------------------------------------------------------------------- - CEnvHeadcrabCanisterSpawnerShared(); - void Init( IHeadcrabCanisterFactory *pFactory, int nRandomSeed, float flTime, - const Vector &vecMinBounds, const Vector &vecMaxBounds, - const Vector &vecTriggerMins, const Vector &vecTriggerMaxs ); - - //------------------------------------------------------------------------- - // Method to generate HeadcrabCanisters. - // Time passed in here is global time, not delta time. - // The function returns the time at which it must be called again. - //------------------------------------------------------------------------- - float HeadcrabCanisterThink( float flTime ); - - //------------------------------------------------------------------------- - // Add HeadcrabCanister target data, used to determine HeadcrabCanister travel direction. - //------------------------------------------------------------------------- - void AddToTargetList( const Vector &vecPosition, float flRadius ); - - // Debugging! - int GetRandomInt( int nMin, int nMax ); - float GetRandomFloat( float flMin, float flMax ); - -public: - - // Factory. - IHeadcrabCanisterFactory *m_pFactory; // HeadcrabCanister creation factory. - - int m_nHeadcrabCanisterCount; // Number of HeadcrabCanisters created - used as IDs - - // Initial spawner data. - CNetworkVar( float, m_flStartTime ); // Start time. - CNetworkVar( int, m_nRandomSeed ); // The random number stream seed. - - CNetworkVar( int, m_iHeadcrabCanisterType ); // Type of HeadcrabCanister. - float m_flHeadcrabCanisterDamageRadius; // HeadcrabCanister damage radius. - CNetworkVar( bool, m_bSkybox ); // Is the spawner in the skybox? - - CNetworkVar( float, m_flMinSpawnTime ); // Spawn time - Min - CNetworkVar( float, m_flMaxSpawnTime ); // Max - CNetworkVar( int, m_nMinSpawnCount ); // Number of HeadcrabCanisters to spawn - Min - CNetworkVar( int, m_nMaxSpawnCount ); // Max - CNetworkVector( m_vecMinBounds ); // Spawner volume (space) - Min - CNetworkVector( m_vecMaxBounds ); // Max - CNetworkVar( float, m_flMinSpeed ); // HeadcrabCanister speed - Min - CNetworkVar( float, m_flMaxSpeed ); // Max - CNetworkVector( m_vecTriggerMins ); // World Bounds (Trigger) in 3D Skybox - Min - CNetworkVector( m_vecTriggerMaxs ); // Max - Vector m_vecTriggerCenter; - - // Generated data. - int m_nRandomCallCount; // Debug! Keep track of number steam calls. - float m_flNextSpawnTime; // Next HeadcrabCanister spawn time (random). - CUniformRandomStream m_NumberStream; // Used to generate random numbers. - - // Use "Targets" to determine HeadcrabCanister direction(s). - struct HeadcrabCanistertarget_t - { - Vector m_vecPosition; - float m_flRadius; - }; - CUtlVector m_aTargets; -}; -*/ - -#endif // ENV_HEADCRAB_CANISTER_SHARED_H diff --git a/game/shared/hl2/hl2_gamerules.cpp b/game/shared/hl2/hl2_gamerules.cpp deleted file mode 100644 index 3e2be4218..000000000 --- a/game/shared/hl2/hl2_gamerules.cpp +++ /dev/null @@ -1,1880 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ==== -// -// Purpose: The Half-Life 2 game rules, such as the relationship tables and ammo -// damage cvars. -// -//============================================================================= - -#include "cbase.h" -#include "hl2_gamerules.h" -#include "ammodef.h" -#include "hl2_shareddefs.h" - -#ifdef CLIENT_DLL - -#else - #include "player.h" - #include "game.h" - #include "gamerules.h" - #include "teamplay_gamerules.h" - #include "hl2_player.h" - #include "voice_gamemgr.h" - #include "globalstate.h" - #include "ai_basenpc.h" - #include "weapon_physcannon.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -REGISTER_GAMERULES_CLASS( CHalfLife2 ); - -BEGIN_NETWORK_TABLE_NOBASE( CHalfLife2, DT_HL2GameRules ) - #ifdef CLIENT_DLL - RecvPropBool( RECVINFO( m_bMegaPhysgun ) ), - #else - SendPropBool( SENDINFO( m_bMegaPhysgun ) ), - #endif -END_NETWORK_TABLE() - - -LINK_ENTITY_TO_CLASS( hl2_gamerules, CHalfLife2Proxy ); -IMPLEMENT_NETWORKCLASS_ALIASED( HalfLife2Proxy, DT_HalfLife2Proxy ) - - -#ifdef CLIENT_DLL - void RecvProxy_HL2GameRules( const RecvProp *pProp, void **pOut, void *pData, int objectID ) - { - CHalfLife2 *pRules = HL2GameRules(); - Assert( pRules ); - *pOut = pRules; - } - - BEGIN_RECV_TABLE( CHalfLife2Proxy, DT_HalfLife2Proxy ) - RecvPropDataTable( "hl2_gamerules_data", 0, 0, &REFERENCE_RECV_TABLE( DT_HL2GameRules ), RecvProxy_HL2GameRules ) - END_RECV_TABLE() -#else - void* SendProxy_HL2GameRules( const SendProp *pProp, const void *pStructBase, const void *pData, CSendProxyRecipients *pRecipients, int objectID ) - { - CHalfLife2 *pRules = HL2GameRules(); - Assert( pRules ); - pRecipients->SetAllRecipients(); - return pRules; - } - - BEGIN_SEND_TABLE( CHalfLife2Proxy, DT_HalfLife2Proxy ) - SendPropDataTable( "hl2_gamerules_data", 0, &REFERENCE_SEND_TABLE( DT_HL2GameRules ), SendProxy_HL2GameRules ) - END_SEND_TABLE() -#endif - -ConVar physcannon_mega_enabled( "physcannon_mega_enabled", "0", FCVAR_CHEAT | FCVAR_REPLICATED ); - -// Controls the application of the robus radius damage model. -ConVar sv_robust_explosions( "sv_robust_explosions","1", FCVAR_REPLICATED ); - -// Damage scale for damage inflicted by the player on each skill level. -ConVar sk_dmg_inflict_scale1( "sk_dmg_inflict_scale1", "1.50", FCVAR_REPLICATED ); -ConVar sk_dmg_inflict_scale2( "sk_dmg_inflict_scale2", "1.00", FCVAR_REPLICATED ); -ConVar sk_dmg_inflict_scale3( "sk_dmg_inflict_scale3", "0.75", FCVAR_REPLICATED ); - -// Damage scale for damage taken by the player on each skill level. -ConVar sk_dmg_take_scale1( "sk_dmg_take_scale1", "0.50", FCVAR_REPLICATED ); -ConVar sk_dmg_take_scale2( "sk_dmg_take_scale2", "1.00", FCVAR_REPLICATED ); -#ifdef HL2_EPISODIC - ConVar sk_dmg_take_scale3( "sk_dmg_take_scale3", "2.0", FCVAR_REPLICATED ); -#else - ConVar sk_dmg_take_scale3( "sk_dmg_take_scale3", "1.50", FCVAR_REPLICATED ); -#endif//HL2_EPISODIC - -ConVar sk_allow_autoaim( "sk_allow_autoaim", "1", FCVAR_REPLICATED | FCVAR_ARCHIVE_XBOX ); - -// Autoaim scale -ConVar sk_autoaim_scale1( "sk_autoaim_scale1", "1.0", FCVAR_REPLICATED ); -ConVar sk_autoaim_scale2( "sk_autoaim_scale2", "1.0", FCVAR_REPLICATED ); -//ConVar sk_autoaim_scale3( "sk_autoaim_scale3", "0.0", FCVAR_REPLICATED ); NOT CURRENTLY OFFERED ON SKILL 3 - -// Quantity scale for ammo received by the player. -ConVar sk_ammo_qty_scale1 ( "sk_ammo_qty_scale1", "1.20", FCVAR_REPLICATED ); -ConVar sk_ammo_qty_scale2 ( "sk_ammo_qty_scale2", "1.00", FCVAR_REPLICATED ); -ConVar sk_ammo_qty_scale3 ( "sk_ammo_qty_scale3", "0.60", FCVAR_REPLICATED ); - -ConVar sk_plr_health_drop_time ( "sk_plr_health_drop_time", "30", FCVAR_REPLICATED ); -ConVar sk_plr_grenade_drop_time ( "sk_plr_grenade_drop_time", "30", FCVAR_REPLICATED ); - -ConVar sk_plr_dmg_ar2 ( "sk_plr_dmg_ar2","0", FCVAR_REPLICATED ); -ConVar sk_npc_dmg_ar2 ( "sk_npc_dmg_ar2","0", FCVAR_REPLICATED); -ConVar sk_max_ar2 ( "sk_max_ar2","0", FCVAR_REPLICATED); -ConVar sk_max_ar2_altfire ( "sk_max_ar2_altfire","0", FCVAR_REPLICATED); - -ConVar sk_plr_dmg_alyxgun ( "sk_plr_dmg_alyxgun","0", FCVAR_REPLICATED ); -ConVar sk_npc_dmg_alyxgun ( "sk_npc_dmg_alyxgun","0", FCVAR_REPLICATED); -ConVar sk_max_alyxgun ( "sk_max_alyxgun","0", FCVAR_REPLICATED); - -ConVar sk_plr_dmg_pistol ( "sk_plr_dmg_pistol","0", FCVAR_REPLICATED ); -ConVar sk_npc_dmg_pistol ( "sk_npc_dmg_pistol","0", FCVAR_REPLICATED); -ConVar sk_max_pistol ( "sk_max_pistol","0", FCVAR_REPLICATED); - -ConVar sk_plr_dmg_smg1 ( "sk_plr_dmg_smg1","0", FCVAR_REPLICATED ); -ConVar sk_npc_dmg_smg1 ( "sk_npc_dmg_smg1","0", FCVAR_REPLICATED); -ConVar sk_max_smg1 ( "sk_max_smg1","0", FCVAR_REPLICATED); - -// FIXME: remove these -//ConVar sk_plr_dmg_flare_round ( "sk_plr_dmg_flare_round","0", FCVAR_REPLICATED); -//ConVar sk_npc_dmg_flare_round ( "sk_npc_dmg_flare_round","0", FCVAR_REPLICATED); -//ConVar sk_max_flare_round ( "sk_max_flare_round","0", FCVAR_REPLICATED); - -ConVar sk_plr_dmg_buckshot ( "sk_plr_dmg_buckshot","0", FCVAR_REPLICATED); -ConVar sk_npc_dmg_buckshot ( "sk_npc_dmg_buckshot","0", FCVAR_REPLICATED); -ConVar sk_max_buckshot ( "sk_max_buckshot","0", FCVAR_REPLICATED); -ConVar sk_plr_num_shotgun_pellets( "sk_plr_num_shotgun_pellets","7", FCVAR_REPLICATED); - -ConVar sk_plr_dmg_rpg_round ( "sk_plr_dmg_rpg_round","0", FCVAR_REPLICATED); -ConVar sk_npc_dmg_rpg_round ( "sk_npc_dmg_rpg_round","0", FCVAR_REPLICATED); -ConVar sk_max_rpg_round ( "sk_max_rpg_round","0", FCVAR_REPLICATED); - -ConVar sk_plr_dmg_sniper_round ( "sk_plr_dmg_sniper_round","0", FCVAR_REPLICATED); -ConVar sk_npc_dmg_sniper_round ( "sk_npc_dmg_sniper_round","0", FCVAR_REPLICATED); -ConVar sk_max_sniper_round ( "sk_max_sniper_round","0", FCVAR_REPLICATED); - -//ConVar sk_max_slam ( "sk_max_slam","0", FCVAR_REPLICATED); -//ConVar sk_max_tripwire ( "sk_max_tripwire","0", FCVAR_REPLICATED); - -//ConVar sk_plr_dmg_molotov ( "sk_plr_dmg_molotov","0", FCVAR_REPLICATED); -//ConVar sk_npc_dmg_molotov ( "sk_npc_dmg_molotov","0", FCVAR_REPLICATED); -//ConVar sk_max_molotov ( "sk_max_molotov","0", FCVAR_REPLICATED); - -ConVar sk_plr_dmg_grenade ( "sk_plr_dmg_grenade","0", FCVAR_REPLICATED); -ConVar sk_npc_dmg_grenade ( "sk_npc_dmg_grenade","0", FCVAR_REPLICATED); -ConVar sk_max_grenade ( "sk_max_grenade","0", FCVAR_REPLICATED); - -#ifdef HL2_EPISODIC -ConVar sk_max_hopwire ( "sk_max_hopwire", "3", FCVAR_REPLICATED); -ConVar sk_max_striderbuster ( "sk_max_striderbuster", "3", FCVAR_REPLICATED); -#endif - -//ConVar sk_plr_dmg_brickbat ( "sk_plr_dmg_brickbat","0", FCVAR_REPLICATED); -//ConVar sk_npc_dmg_brickbat ( "sk_npc_dmg_brickbat","0", FCVAR_REPLICATED); -//ConVar sk_max_brickbat ( "sk_max_brickbat","0", FCVAR_REPLICATED); - -ConVar sk_plr_dmg_smg1_grenade ( "sk_plr_dmg_smg1_grenade","0", FCVAR_REPLICATED); -ConVar sk_npc_dmg_smg1_grenade ( "sk_npc_dmg_smg1_grenade","0", FCVAR_REPLICATED); -ConVar sk_max_smg1_grenade ( "sk_max_smg1_grenade","0", FCVAR_REPLICATED ); - -ConVar sk_plr_dmg_357 ( "sk_plr_dmg_357", "0", FCVAR_REPLICATED ); -ConVar sk_npc_dmg_357 ( "sk_npc_dmg_357", "0", FCVAR_REPLICATED ); -ConVar sk_max_357 ( "sk_max_357", "0", FCVAR_REPLICATED ); - -ConVar sk_plr_dmg_crossbow ( "sk_plr_dmg_crossbow", "0", FCVAR_REPLICATED ); -ConVar sk_npc_dmg_crossbow ( "sk_npc_dmg_crossbow", "0", FCVAR_REPLICATED ); -ConVar sk_max_crossbow ( "sk_max_crossbow", "0", FCVAR_REPLICATED ); - -ConVar sk_dmg_sniper_penetrate_plr( "sk_dmg_sniper_penetrate_plr","0", FCVAR_REPLICATED); -ConVar sk_dmg_sniper_penetrate_npc( "sk_dmg_sniper_penetrate_npc","0", FCVAR_REPLICATED); - -ConVar sk_plr_dmg_airboat ( "sk_plr_dmg_airboat", "0", FCVAR_REPLICATED ); -ConVar sk_npc_dmg_airboat ( "sk_npc_dmg_airboat", "0", FCVAR_REPLICATED ); - -ConVar sk_max_gauss_round ( "sk_max_gauss_round", "0", FCVAR_REPLICATED ); - -// Gunship & Dropship cannons -ConVar sk_npc_dmg_gunship ( "sk_npc_dmg_gunship", "0", FCVAR_REPLICATED ); -ConVar sk_npc_dmg_gunship_to_plr ( "sk_npc_dmg_gunship_to_plr", "0", FCVAR_REPLICATED ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iDmgType - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -int CHalfLife2::Damage_GetTimeBased( void ) -{ -#ifdef HL2_EPISODIC - int iDamage = ( DMG_PARALYZE | DMG_NERVEGAS | DMG_POISON | DMG_RADIATION | DMG_DROWNRECOVER | DMG_ACID | DMG_SLOWBURN ); - return iDamage; -#else - return BaseClass::Damage_GetTimeBased(); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iDmgType - -// Output : bool -//----------------------------------------------------------------------------- -bool CHalfLife2::Damage_IsTimeBased( int iDmgType ) -{ - // Damage types that are time-based. -#ifdef HL2_EPISODIC - // This makes me think EP2 should have its own rules, but they are #ifdef all over in here. - return ( ( iDmgType & ( DMG_PARALYZE | DMG_NERVEGAS | DMG_POISON | DMG_RADIATION | DMG_DROWNRECOVER | DMG_SLOWBURN ) ) != 0 ); -#else - return BaseClass::Damage_IsTimeBased( iDmgType ); -#endif -} - -#ifdef CLIENT_DLL -#else - -#ifdef HL2_EPISODIC -ConVar alyx_darkness_force( "alyx_darkness_force", "0", FCVAR_CHEAT | FCVAR_REPLICATED ); -#endif // HL2_EPISODIC - -#endif // CLIENT_DLL - - -#ifdef CLIENT_DLL //{ - - -#else //}{ - - extern bool g_fGameOver; - -#ifndef HL2MP - class CVoiceGameMgrHelper : public IVoiceGameMgrHelper - { - public: - virtual bool CanPlayerHearPlayer( CBasePlayer *pListener, CBasePlayer *pTalker, bool &bProximity ) - { - return true; - } - }; - CVoiceGameMgrHelper g_VoiceGameMgrHelper; - IVoiceGameMgrHelper *g_pVoiceGameMgrHelper = &g_VoiceGameMgrHelper; -#endif - - //----------------------------------------------------------------------------- - // Purpose: - // Input : - // Output : - //----------------------------------------------------------------------------- - CHalfLife2::CHalfLife2() - { - m_bMegaPhysgun = false; - - m_flLastHealthDropTime = 0.0f; - m_flLastGrenadeDropTime = 0.0f; - } - - //----------------------------------------------------------------------------- - // Purpose: called each time a player uses a "cmd" command - // Input : *pEdict - the player who issued the command - // Use engine.Cmd_Argv, engine.Cmd_Argv, and engine.Cmd_Argc to get - // pointers the character string command. - //----------------------------------------------------------------------------- - bool CHalfLife2::ClientCommand( CBaseEntity *pEdict, const CCommand &args ) - { - if( BaseClass::ClientCommand( pEdict, args ) ) - return true; - - CHL2_Player *pPlayer = (CHL2_Player *) pEdict; - - if ( pPlayer->ClientCommand( args ) ) - return true; - - return false; - } - - //----------------------------------------------------------------------------- - // Purpose: Player has just spawned. Equip them. - //----------------------------------------------------------------------------- - void CHalfLife2::PlayerSpawn( CBasePlayer *pPlayer ) - { - } - - //----------------------------------------------------------------------------- - // Purpose: MULTIPLAYER BODY QUE HANDLING - //----------------------------------------------------------------------------- - class CCorpse : public CBaseAnimating - { - public: - DECLARE_CLASS( CCorpse, CBaseAnimating ); - DECLARE_SERVERCLASS(); - - virtual int ObjectCaps( void ) { return FCAP_DONT_SAVE; } - - public: - CNetworkVar( int, m_nReferencePlayer ); - }; - - IMPLEMENT_SERVERCLASS_ST(CCorpse, DT_Corpse) - SendPropInt( SENDINFO(m_nReferencePlayer), 10, SPROP_UNSIGNED ) - END_SEND_TABLE() - - LINK_ENTITY_TO_CLASS( bodyque, CCorpse ); - - - CCorpse *g_pBodyQueueHead; - - void InitBodyQue(void) - { - CCorpse *pEntity = ( CCorpse * )CreateEntityByName( "bodyque" ); - pEntity->AddEFlags( EFL_KEEP_ON_RECREATE_ENTITIES ); - g_pBodyQueueHead = pEntity; - CCorpse *p = g_pBodyQueueHead; - - // Reserve 3 more slots for dead bodies - for ( int i = 0; i < 3; i++ ) - { - CCorpse *next = ( CCorpse * )CreateEntityByName( "bodyque" ); - next->AddEFlags( EFL_KEEP_ON_RECREATE_ENTITIES ); - p->SetOwnerEntity( next ); - p = next; - } - - p->SetOwnerEntity( g_pBodyQueueHead ); - } - - //----------------------------------------------------------------------------- - // Purpose: make a body que entry for the given ent so the ent can be respawned elsewhere - // GLOBALS ASSUMED SET: g_eoBodyQueueHead - //----------------------------------------------------------------------------- - void CopyToBodyQue( CBaseAnimating *pCorpse ) - { - if ( pCorpse->IsEffectActive( EF_NODRAW ) ) - return; - - CCorpse *pHead = g_pBodyQueueHead; - - pHead->CopyAnimationDataFrom( pCorpse ); - - pHead->SetMoveType( MOVETYPE_FLYGRAVITY ); - pHead->SetAbsVelocity( pCorpse->GetAbsVelocity() ); - pHead->ClearFlags(); - pHead->m_nReferencePlayer = ENTINDEX( pCorpse ); - - pHead->SetLocalAngles( pCorpse->GetAbsAngles() ); - UTIL_SetOrigin(pHead, pCorpse->GetAbsOrigin()); - - UTIL_SetSize(pHead, pCorpse->WorldAlignMins(), pCorpse->WorldAlignMaxs()); - g_pBodyQueueHead = (CCorpse *)pHead->GetOwnerEntity(); - } - - //------------------------------------------------------------------------------ - // Purpose : Initialize all default class relationships - // Input : - // Output : - //------------------------------------------------------------------------------ - void CHalfLife2::InitDefaultAIRelationships( void ) - { - int i, j; - - // Allocate memory for default relationships - CBaseCombatCharacter::AllocateDefaultRelationships(); - - // -------------------------------------------------------------- - // First initialize table so we can report missing relationships - // -------------------------------------------------------------- - for (i=0;i CLASS_ANTLION - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_PLAYER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_BARNACLE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_BULLSQUID, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_CITIZEN_PASSIVE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_CITIZEN_REBEL, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_COMBINE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_COMBINE_GUNSHIP, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_COMBINE_HUNTER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_CONSCRIPT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_HEADCRAB, D_HT, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_HOUNDEYE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_MANHACK, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_METROPOLICE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_MILITARY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_MISSILE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_SCANNER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_STALKER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_VORTIGAUNT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_ZOMBIE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_PROTOSNIPER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_ANTLION, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_PLAYER_ALLY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ANTLION, CLASS_HACKED_ROLLERMINE,D_HT, 0); - - // ------------------------------------------------------------ - // > CLASS_BARNACLE - // - // In this case, the relationship D_HT indicates which characters - // the barnacle will try to eat. - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_PLAYER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_BARNACLE, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_BULLSQUID, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_CITIZEN_PASSIVE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_CITIZEN_REBEL, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_COMBINE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_COMBINE_GUNSHIP, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_COMBINE_HUNTER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_CONSCRIPT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_HEADCRAB, D_HT, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_HOUNDEYE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_MANHACK, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_METROPOLICE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_MILITARY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_MISSILE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_SCANNER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_STALKER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_VORTIGAUNT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_ZOMBIE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_PROTOSNIPER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_EARTH_FAUNA, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_PLAYER_ALLY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BARNACLE, CLASS_HACKED_ROLLERMINE,D_HT, 0); - - // ------------------------------------------------------------ - // > CLASS_BULLSEYE - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_PLAYER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_ANTLION, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_BARNACLE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_BULLSQUID, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_CITIZEN_PASSIVE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_CITIZEN_REBEL, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_COMBINE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_COMBINE_GUNSHIP, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_COMBINE_HUNTER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_CONSCRIPT, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_HEADCRAB, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_HOUNDEYE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_MANHACK, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_METROPOLICE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_MILITARY, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_MISSILE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_SCANNER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_STALKER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_VORTIGAUNT, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_ZOMBIE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_PROTOSNIPER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_PLAYER_ALLY, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_PLAYER_ALLY_VITAL,D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSEYE, CLASS_HACKED_ROLLERMINE,D_NU, 0); - - // ------------------------------------------------------------ - // > CLASS_BULLSQUID - // ------------------------------------------------------------ - /* - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_PLAYER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_BARNACLE, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_BULLSEYE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_BULLSQUID, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_CITIZEN_PASSIVE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_CITIZEN_REBEL, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_COMBINE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_COMBINE_GUNSHIP, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_COMBINE_HUNTER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_CONSCRIPT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_HEADCRAB, D_HT, 1); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_HOUNDEYE, D_HT, 1); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_MANHACK, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_METROPOLICE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_MILITARY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_MISSILE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_SCANNER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_STALKER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_VORTIGAUNT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_ZOMBIE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_PROTOSNIPER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_PLAYER_ALLY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_BULLSQUID, CLASS_HACKED_ROLLERMINE,D_HT, 0); - */ - // ------------------------------------------------------------ - // > CLASS_CITIZEN_PASSIVE - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_PLAYER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_BARNACLE, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_BULLSQUID, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_CITIZEN_PASSIVE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_CITIZEN_REBEL, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_COMBINE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_COMBINE_GUNSHIP, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_COMBINE_HUNTER, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_CONSCRIPT, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_HEADCRAB, D_FR, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_HOUNDEYE, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_MANHACK, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_METROPOLICE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_MILITARY, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_MISSILE, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_SCANNER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_STALKER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_VORTIGAUNT, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_ZOMBIE, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_PROTOSNIPER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_PLAYER_ALLY, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_PLAYER_ALLY_VITAL,D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_PASSIVE, CLASS_HACKED_ROLLERMINE,D_NU, 0); - - // ------------------------------------------------------------ - // > CLASS_CITIZEN_REBEL - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_PLAYER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_BARNACLE, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_BULLSQUID, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_CITIZEN_PASSIVE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_CITIZEN_REBEL, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_COMBINE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_COMBINE_GUNSHIP, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_COMBINE_HUNTER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_CONSCRIPT, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_HEADCRAB, D_HT, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_HOUNDEYE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_MANHACK, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_METROPOLICE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_MILITARY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_MISSILE, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_SCANNER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_STALKER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_VORTIGAUNT, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_ZOMBIE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_PROTOSNIPER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_PLAYER_ALLY, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_PLAYER_ALLY_VITAL,D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CITIZEN_REBEL, CLASS_HACKED_ROLLERMINE,D_NU, 0); - - // ------------------------------------------------------------ - // > CLASS_COMBINE - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_PLAYER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_BARNACLE, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_BULLSQUID, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_CITIZEN_PASSIVE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_CITIZEN_REBEL, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_COMBINE, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_COMBINE_GUNSHIP, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_COMBINE_HUNTER, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_CONSCRIPT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_HEADCRAB, D_HT, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_HOUNDEYE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_MANHACK, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_METROPOLICE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_MILITARY, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_MISSILE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_SCANNER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_STALKER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_VORTIGAUNT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_ZOMBIE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_PROTOSNIPER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_PLAYER_ALLY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE, CLASS_HACKED_ROLLERMINE,D_HT, 0); - - // ------------------------------------------------------------ - // > CLASS_COMBINE_GUNSHIP - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_PLAYER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_BARNACLE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_BULLSQUID, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_CITIZEN_PASSIVE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_CITIZEN_REBEL, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_COMBINE, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_COMBINE_GUNSHIP, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_COMBINE_HUNTER, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_CONSCRIPT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_HEADCRAB, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_HOUNDEYE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_MANHACK, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_METROPOLICE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_MILITARY, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_MISSILE, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_SCANNER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_STALKER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_VORTIGAUNT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_ZOMBIE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_PROTOSNIPER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_PLAYER_ALLY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_GUNSHIP, CLASS_HACKED_ROLLERMINE,D_HT, 0); - - // ------------------------------------------------------------ - // > CLASS_COMBINE_HUNTER - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_PLAYER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_BARNACLE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_BULLSQUID, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_CITIZEN_PASSIVE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_CITIZEN_REBEL, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_COMBINE, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_COMBINE_GUNSHIP, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_COMBINE_HUNTER, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_CONSCRIPT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_HEADCRAB, D_HT, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_HOUNDEYE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_MANHACK, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_METROPOLICE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_MILITARY, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_MISSILE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_SCANNER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_STALKER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_VORTIGAUNT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_ZOMBIE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_PROTOSNIPER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_PLAYER_ALLY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_COMBINE_HUNTER, CLASS_HACKED_ROLLERMINE,D_HT, 0); - - // ------------------------------------------------------------ - // > CLASS_CONSCRIPT - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_PLAYER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_BARNACLE, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_BULLSQUID, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_CITIZEN_PASSIVE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_CITIZEN_REBEL, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_COMBINE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_COMBINE_GUNSHIP, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_COMBINE_HUNTER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_CONSCRIPT, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_HEADCRAB, D_HT, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_HOUNDEYE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_MANHACK, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_METROPOLICE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_MILITARY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_MISSILE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_SCANNER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_STALKER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_VORTIGAUNT, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_ZOMBIE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_PROTOSNIPER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_PLAYER_ALLY, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_PLAYER_ALLY_VITAL,D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_CONSCRIPT, CLASS_HACKED_ROLLERMINE,D_NU, 0); - - // ------------------------------------------------------------ - // > CLASS_FLARE - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_PLAYER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_ANTLION, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_BARNACLE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_BULLSQUID, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_CITIZEN_PASSIVE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_CITIZEN_REBEL, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_COMBINE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_COMBINE_GUNSHIP, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_COMBINE_HUNTER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_CONSCRIPT, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_HEADCRAB, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_HOUNDEYE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_MANHACK, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_METROPOLICE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_MILITARY, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_MISSILE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_SCANNER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_STALKER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_VORTIGAUNT, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_ZOMBIE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_PROTOSNIPER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_PLAYER_ALLY, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_PLAYER_ALLY_VITAL,D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_FLARE, CLASS_HACKED_ROLLERMINE,D_NU, 0); - - // ------------------------------------------------------------ - // > CLASS_HEADCRAB - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_PLAYER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_BARNACLE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_BULLSQUID, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_CITIZEN_PASSIVE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_CITIZEN_REBEL, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_COMBINE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_COMBINE_GUNSHIP, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_COMBINE_HUNTER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_CONSCRIPT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_HEADCRAB, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_HOUNDEYE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_MANHACK, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_METROPOLICE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_MILITARY, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_MISSILE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_SCANNER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_STALKER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_VORTIGAUNT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_ZOMBIE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_PROTOSNIPER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_PLAYER_ALLY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HEADCRAB, CLASS_HACKED_ROLLERMINE,D_FR, 0); - - // ------------------------------------------------------------ - // > CLASS_HOUNDEYE - // ------------------------------------------------------------ - /* - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_PLAYER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_BARNACLE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_BULLSQUID, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_CITIZEN_PASSIVE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_CITIZEN_REBEL, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_COMBINE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_COMBINE_GUNSHIP, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_COMBINE_HUNTER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_CONSCRIPT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_HEADCRAB, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_HOUNDEYE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_MANHACK, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_METROPOLICE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_MILITARY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_MISSILE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_SCANNER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_STALKER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_VORTIGAUNT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_ZOMBIE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_PROTOSNIPER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_PLAYER_ALLY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HOUNDEYE, CLASS_HACKED_ROLLERMINE,D_HT, 0); - */ - - // ------------------------------------------------------------ - // > CLASS_MANHACK - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_PLAYER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_BARNACLE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_BULLSQUID, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_CITIZEN_PASSIVE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_CITIZEN_REBEL, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_COMBINE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_COMBINE_GUNSHIP, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_COMBINE_HUNTER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_CONSCRIPT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_HEADCRAB, D_HT,-1); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_HOUNDEYE, D_HT,-1); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_MANHACK, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_METROPOLICE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_MILITARY, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_MISSILE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_SCANNER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_STALKER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_VORTIGAUNT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_ZOMBIE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_PROTOSNIPER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_PLAYER_ALLY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MANHACK, CLASS_HACKED_ROLLERMINE,D_HT, 0); - - // ------------------------------------------------------------ - // > CLASS_METROPOLICE - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_PLAYER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_BARNACLE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_BULLSQUID, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_CITIZEN_PASSIVE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_CITIZEN_REBEL, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_COMBINE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_COMBINE_GUNSHIP, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_COMBINE_HUNTER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_CONSCRIPT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_HEADCRAB, D_HT, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_HOUNDEYE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_MANHACK, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_METROPOLICE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_MILITARY, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_MISSILE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_SCANNER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_STALKER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_VORTIGAUNT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_ZOMBIE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_PROTOSNIPER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_PLAYER_ALLY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_METROPOLICE, CLASS_HACKED_ROLLERMINE,D_HT, 0); - - // ------------------------------------------------------------ - // > CLASS_MILITARY - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_PLAYER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_BARNACLE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_BULLSQUID, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_CITIZEN_PASSIVE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_CITIZEN_REBEL, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_COMBINE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_COMBINE_GUNSHIP, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_COMBINE_HUNTER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_CONSCRIPT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_HEADCRAB, D_HT, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_HOUNDEYE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_MANHACK, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_METROPOLICE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_MILITARY, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_MISSILE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_SCANNER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_STALKER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_VORTIGAUNT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_ZOMBIE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_PROTOSNIPER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_PLAYER_ALLY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MILITARY, CLASS_HACKED_ROLLERMINE,D_HT, 0); - - // ------------------------------------------------------------ - // > CLASS_MISSILE - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_PLAYER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_BARNACLE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_BULLSQUID, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_CITIZEN_PASSIVE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_CITIZEN_REBEL, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_COMBINE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_COMBINE_GUNSHIP, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_COMBINE_HUNTER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_CONSCRIPT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_HEADCRAB, D_HT, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_HOUNDEYE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_MANHACK, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_METROPOLICE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_MILITARY, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_MISSILE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_SCANNER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_STALKER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_VORTIGAUNT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_ZOMBIE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_PROTOSNIPER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_PLAYER_ALLY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_MISSILE, CLASS_HACKED_ROLLERMINE,D_HT, 0); - - // ------------------------------------------------------------ - // > CLASS_NONE - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_PLAYER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_ANTLION, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_BARNACLE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_BULLSQUID, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_CITIZEN_PASSIVE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_CITIZEN_REBEL, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_COMBINE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_COMBINE_GUNSHIP, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_COMBINE_HUNTER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_CONSCRIPT, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_HEADCRAB, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_HOUNDEYE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_MANHACK, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_METROPOLICE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_MILITARY, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_SCANNER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_STALKER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_VORTIGAUNT, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_ZOMBIE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_PROTOSNIPER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_PLAYER_ALLY, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_PLAYER_ALLY_VITAL,D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_NONE, CLASS_HACKED_ROLLERMINE,D_NU, 0); - - // ------------------------------------------------------------ - // > CLASS_PLAYER - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_PLAYER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_BARNACLE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_BULLSEYE, D_HT, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_BULLSQUID, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_CITIZEN_PASSIVE, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_CITIZEN_REBEL, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_COMBINE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_COMBINE_GUNSHIP, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_COMBINE_HUNTER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_CONSCRIPT, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_HEADCRAB, D_HT, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_HOUNDEYE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_MANHACK, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_METROPOLICE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_MILITARY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_MISSILE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_SCANNER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_STALKER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_VORTIGAUNT, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_ZOMBIE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_PROTOSNIPER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_PLAYER_ALLY, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_PLAYER_ALLY_VITAL,D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER, CLASS_HACKED_ROLLERMINE,D_LI, 0); - - // ------------------------------------------------------------ - // > CLASS_PLAYER_ALLY - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_PLAYER, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_BARNACLE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_BULLSQUID, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_CITIZEN_PASSIVE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_CITIZEN_REBEL, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_COMBINE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_COMBINE_GUNSHIP, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_COMBINE_HUNTER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_CONSCRIPT, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_HEADCRAB, D_FR, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_HOUNDEYE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_MANHACK, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_METROPOLICE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_MILITARY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_MISSILE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_SCANNER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_STALKER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_VORTIGAUNT, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_ZOMBIE, D_FR, 1); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_PROTOSNIPER, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_PLAYER_ALLY, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_PLAYER_ALLY_VITAL,D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY, CLASS_HACKED_ROLLERMINE,D_LI, 0); - - // ------------------------------------------------------------ - // > CLASS_PLAYER_ALLY_VITAL - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_PLAYER, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_BARNACLE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_BULLSQUID, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_CITIZEN_PASSIVE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_CITIZEN_REBEL, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_COMBINE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_COMBINE_GUNSHIP, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_COMBINE_HUNTER, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_CONSCRIPT, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_HEADCRAB, D_HT, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_HOUNDEYE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_MANHACK, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_METROPOLICE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_MILITARY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_MISSILE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_SCANNER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_STALKER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_VORTIGAUNT, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_ZOMBIE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_PROTOSNIPER, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_PLAYER_ALLY, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_PLAYER_ALLY_VITAL,D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PLAYER_ALLY_VITAL, CLASS_HACKED_ROLLERMINE,D_LI, 0); - - // ------------------------------------------------------------ - // > CLASS_SCANNER - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_PLAYER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_BARNACLE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_BULLSQUID, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_CITIZEN_PASSIVE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_CITIZEN_REBEL, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_COMBINE, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_COMBINE_GUNSHIP, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_COMBINE_HUNTER, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_CONSCRIPT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_HEADCRAB, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_HOUNDEYE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_MANHACK, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_METROPOLICE, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_MILITARY, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_MISSILE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_SCANNER, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_STALKER, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_VORTIGAUNT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_ZOMBIE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_PROTOSNIPER, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_PLAYER_ALLY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_SCANNER, CLASS_HACKED_ROLLERMINE,D_HT, 0); - - // ------------------------------------------------------------ - // > CLASS_STALKER - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_PLAYER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_BARNACLE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_BULLSQUID, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_CITIZEN_PASSIVE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_CITIZEN_REBEL, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_COMBINE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_COMBINE_GUNSHIP, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_COMBINE_HUNTER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_CONSCRIPT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_HEADCRAB, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_HOUNDEYE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_MANHACK, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_METROPOLICE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_MILITARY, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_MISSILE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_SCANNER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_STALKER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_VORTIGAUNT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_ZOMBIE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_PROTOSNIPER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_PLAYER_ALLY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_STALKER, CLASS_HACKED_ROLLERMINE,D_HT, 0); - - // ------------------------------------------------------------ - // > CLASS_VORTIGAUNT - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_PLAYER, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_BARNACLE, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_BULLSQUID, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_CITIZEN_PASSIVE, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_CITIZEN_REBEL, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_COMBINE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_COMBINE_GUNSHIP, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_COMBINE_HUNTER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_CONSCRIPT, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_HEADCRAB, D_HT, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_HOUNDEYE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_MANHACK, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_METROPOLICE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_MILITARY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_MISSILE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_SCANNER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_STALKER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_VORTIGAUNT, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_ZOMBIE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_PROTOSNIPER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_PLAYER_ALLY, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_PLAYER_ALLY_VITAL,D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_VORTIGAUNT, CLASS_HACKED_ROLLERMINE,D_LI, 0); - - // ------------------------------------------------------------ - // > CLASS_ZOMBIE - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_PLAYER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_BARNACLE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_BULLSQUID, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_CITIZEN_PASSIVE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_CITIZEN_REBEL, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_COMBINE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_COMBINE_GUNSHIP, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_COMBINE_HUNTER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_CONSCRIPT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_HEADCRAB, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_HOUNDEYE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_MANHACK, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_METROPOLICE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_MILITARY, D_FR, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_MISSILE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_SCANNER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_STALKER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_VORTIGAUNT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_ZOMBIE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_PROTOSNIPER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_PLAYER_ALLY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_ZOMBIE, CLASS_HACKED_ROLLERMINE,D_HT, 0); - - // ------------------------------------------------------------ - // > CLASS_PROTOSNIPER - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_PLAYER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_BARNACLE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_BULLSQUID, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_CITIZEN_PASSIVE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_CITIZEN_REBEL, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_COMBINE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_COMBINE_GUNSHIP, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_COMBINE_HUNTER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_CONSCRIPT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_HEADCRAB, D_HT, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_HOUNDEYE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_MANHACK, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_METROPOLICE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_MILITARY, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_MISSILE, D_NU, 5); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_SCANNER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_STALKER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_VORTIGAUNT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_ZOMBIE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_PROTOSNIPER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_PLAYER_ALLY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_PROTOSNIPER, CLASS_HACKED_ROLLERMINE,D_HT, 0); - - // ------------------------------------------------------------ - // > CLASS_EARTH_FAUNA - // - // Hates pretty much everything equally except other earth fauna. - // This will make the critter choose the nearest thing as its enemy. - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_NONE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_PLAYER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_BARNACLE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_BULLSQUID, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_CITIZEN_PASSIVE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_CITIZEN_REBEL, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_COMBINE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_COMBINE_GUNSHIP, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_COMBINE_HUNTER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_CONSCRIPT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_FLARE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_HEADCRAB, D_HT, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_HOUNDEYE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_MANHACK, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_METROPOLICE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_MILITARY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_MISSILE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_SCANNER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_STALKER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_VORTIGAUNT, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_ZOMBIE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_PROTOSNIPER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_EARTH_FAUNA, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_PLAYER_ALLY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_PLAYER_ALLY_VITAL,D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_EARTH_FAUNA, CLASS_HACKED_ROLLERMINE,D_NU, 0); - - // ------------------------------------------------------------ - // > CLASS_HACKED_ROLLERMINE - // ------------------------------------------------------------ - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_NONE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_PLAYER, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_ANTLION, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_BARNACLE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_BULLSEYE, D_NU, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_BULLSQUID, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_CITIZEN_PASSIVE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_CITIZEN_REBEL, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_COMBINE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_COMBINE_GUNSHIP, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_COMBINE_HUNTER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_CONSCRIPT, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_FLARE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_HEADCRAB, D_HT, 0); - //CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_HOUNDEYE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_MANHACK, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_METROPOLICE, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_MILITARY, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_MISSILE, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_SCANNER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_STALKER, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_VORTIGAUNT, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_ZOMBIE, D_HT, 1); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_PROTOSNIPER, D_NU, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_EARTH_FAUNA, D_HT, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_PLAYER_ALLY, D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_PLAYER_ALLY_VITAL,D_LI, 0); - CBaseCombatCharacter::SetDefaultRelationship(CLASS_HACKED_ROLLERMINE, CLASS_HACKED_ROLLERMINE,D_LI, 0); - } - - - //------------------------------------------------------------------------------ - // Purpose : Return classify text for classify type - // Input : - // Output : - //------------------------------------------------------------------------------ - const char* CHalfLife2::AIClassText(int classType) - { - switch (classType) - { - case CLASS_NONE: return "CLASS_NONE"; - case CLASS_PLAYER: return "CLASS_PLAYER"; - case CLASS_ANTLION: return "CLASS_ANTLION"; - case CLASS_BARNACLE: return "CLASS_BARNACLE"; - case CLASS_BULLSEYE: return "CLASS_BULLSEYE"; - //case CLASS_BULLSQUID: return "CLASS_BULLSQUID"; - case CLASS_CITIZEN_PASSIVE: return "CLASS_CITIZEN_PASSIVE"; - case CLASS_CITIZEN_REBEL: return "CLASS_CITIZEN_REBEL"; - case CLASS_COMBINE: return "CLASS_COMBINE"; - case CLASS_COMBINE_GUNSHIP: return "CLASS_COMBINE_GUNSHIP"; - case CLASS_COMBINE_HUNTER: return "CLASS_COMBINE_HUNTER"; - case CLASS_CONSCRIPT: return "CLASS_CONSCRIPT"; - case CLASS_HEADCRAB: return "CLASS_HEADCRAB"; - //case CLASS_HOUNDEYE: return "CLASS_HOUNDEYE"; - case CLASS_MANHACK: return "CLASS_MANHACK"; - case CLASS_METROPOLICE: return "CLASS_METROPOLICE"; - case CLASS_MILITARY: return "CLASS_MILITARY"; - case CLASS_SCANNER: return "CLASS_SCANNER"; - case CLASS_STALKER: return "CLASS_STALKER"; - case CLASS_VORTIGAUNT: return "CLASS_VORTIGAUNT"; - case CLASS_ZOMBIE: return "CLASS_ZOMBIE"; - case CLASS_PROTOSNIPER: return "CLASS_PROTOSNIPER"; - case CLASS_MISSILE: return "CLASS_MISSILE"; - case CLASS_FLARE: return "CLASS_FLARE"; - case CLASS_EARTH_FAUNA: return "CLASS_EARTH_FAUNA"; - - default: return "MISSING CLASS in ClassifyText()"; - } - } - - void CHalfLife2::PlayerThink( CBasePlayer *pPlayer ) - { - } - - void CHalfLife2::Think( void ) - { - BaseClass::Think(); - - if( physcannon_mega_enabled.GetBool() == true ) - { - m_bMegaPhysgun = true; - } - else - { - // FIXME: Is there a better place for this? - m_bMegaPhysgun = ( GlobalEntity_GetState("super_phys_gun") == GLOBAL_ON ); - } - } - - //----------------------------------------------------------------------------- - // Purpose: Returns how much damage the given ammo type should do to the victim - // when fired by the attacker. - // Input : pAttacker - Dude what shot the gun. - // pVictim - Dude what done got shot. - // nAmmoType - What been shot out. - // Output : How much hurt to put on dude what done got shot (pVictim). - //----------------------------------------------------------------------------- - float CHalfLife2::GetAmmoDamage( CBaseEntity *pAttacker, CBaseEntity *pVictim, int nAmmoType ) - { - float flDamage = 0.0f; - CAmmoDef *pAmmoDef = GetAmmoDef(); - - if ( pAmmoDef->DamageType( nAmmoType ) & DMG_SNIPER ) - { - // If this damage is from a SNIPER, we do damage based on what the bullet - // HITS, not who fired it. All other bullets have their damage values - // arranged according to the owner of the bullet, not the recipient. - if ( pVictim->IsPlayer() ) - { - // Player - flDamage = pAmmoDef->PlrDamage( nAmmoType ); - } - else - { - // NPC or breakable - flDamage = pAmmoDef->NPCDamage( nAmmoType ); - } - } - else - { - flDamage = BaseClass::GetAmmoDamage( pAttacker, pVictim, nAmmoType ); - } - - if( pAttacker->IsPlayer() && pVictim->IsNPC() ) - { - if( pVictim->MyCombatCharacterPointer() ) - { - // Player is shooting an NPC. Adjust the damage! This protects breakables - // and other 'non-living' entities from being easier/harder to break - // in different skill levels. - flDamage = pAmmoDef->PlrDamage( nAmmoType ); - flDamage = AdjustPlayerDamageInflicted( flDamage ); - } - } - - return flDamage; - } - - //----------------------------------------------------------------------------- - //----------------------------------------------------------------------------- - bool CHalfLife2::AllowDamage( CBaseEntity *pVictim, const CTakeDamageInfo &info ) - { -#ifndef CLIENT_DLL - if( (info.GetDamageType() & DMG_CRUSH) && info.GetInflictor() && pVictim->MyNPCPointer() ) - { - if( pVictim->MyNPCPointer()->IsPlayerAlly() ) - { - // A physics object has struck a player ally. Don't allow damage if it - // came from the player's physcannon. - CBasePlayer *pPlayer = UTIL_PlayerByIndex(1); - - if( pPlayer ) - { - CBaseEntity *pWeapon = pPlayer->HasNamedPlayerItem("weapon_physcannon"); - - if( pWeapon ) - { - CBaseCombatWeapon *pCannon = assert_cast (pWeapon); - - if( pCannon ) - { - if( PhysCannonAccountableForObject(pCannon, info.GetInflictor() ) ) - { - // Antlions can always be squashed! - if ( pVictim->Classify() == CLASS_ANTLION ) - return true; - - return false; - } - } - } - } - } - } -#endif - return true; - } - //----------------------------------------------------------------------------- - // Purpose: Whether or not the NPC should drop a health vial - // Output : Returns true on success, false on failure. - //----------------------------------------------------------------------------- - bool CHalfLife2::NPC_ShouldDropHealth( CBasePlayer *pRecipient ) - { - // Can only do this every so often - if ( m_flLastHealthDropTime > gpGlobals->curtime ) - return false; - - //Try to throw dynamic health - float healthPerc = ( (float) pRecipient->m_iHealth / (float) pRecipient->m_iMaxHealth ); - - if ( random->RandomFloat( 0.0f, 1.0f ) > healthPerc*1.5f ) - return true; - - return false; - } - - //----------------------------------------------------------------------------- - // Purpose: Whether or not the NPC should drop a health vial - // Output : Returns true on success, false on failure. - //----------------------------------------------------------------------------- - bool CHalfLife2::NPC_ShouldDropGrenade( CBasePlayer *pRecipient ) - { - // Can only do this every so often - if ( m_flLastGrenadeDropTime > gpGlobals->curtime ) - return false; - - int grenadeIndex = GetAmmoDef()->Index( "grenade" ); - int numGrenades = pRecipient->GetAmmoCount( grenadeIndex ); - - // If we're not maxed out on grenades and we've randomly okay'd it - if ( ( numGrenades < GetAmmoDef()->MaxCarry( grenadeIndex ) ) && ( random->RandomInt( 0, 2 ) == 0 ) ) - return true; - - return false; - } - - //----------------------------------------------------------------------------- - // Purpose: Update the drop counter for health - //----------------------------------------------------------------------------- - void CHalfLife2::NPC_DroppedHealth( void ) - { - m_flLastHealthDropTime = gpGlobals->curtime + sk_plr_health_drop_time.GetFloat(); - } - - //----------------------------------------------------------------------------- - // Purpose: Update the drop counter for grenades - //----------------------------------------------------------------------------- - void CHalfLife2::NPC_DroppedGrenade( void ) - { - m_flLastGrenadeDropTime = gpGlobals->curtime + sk_plr_grenade_drop_time.GetFloat(); - } - -#endif //} !CLIENT_DLL - - -// ------------------------------------------------------------------------------------ // -// Shared CHalfLife2 implementation. -// ------------------------------------------------------------------------------------ // -bool CHalfLife2::ShouldCollide( int collisionGroup0, int collisionGroup1 ) -{ - // The smaller number is always first - if ( collisionGroup0 > collisionGroup1 ) - { - // swap so that lowest is always first - int tmp = collisionGroup0; - collisionGroup0 = collisionGroup1; - collisionGroup1 = tmp; - } - - // Prevent the player movement from colliding with spit globs (caused the player to jump on top of globs while in water) - if ( collisionGroup0 == COLLISION_GROUP_PLAYER_MOVEMENT && collisionGroup1 == HL2COLLISION_GROUP_SPIT ) - return false; - - // HL2 treats movement and tracing against players the same, so just remap here - if ( collisionGroup0 == COLLISION_GROUP_PLAYER_MOVEMENT ) - { - collisionGroup0 = COLLISION_GROUP_PLAYER; - } - - if( collisionGroup1 == COLLISION_GROUP_PLAYER_MOVEMENT ) - { - collisionGroup1 = COLLISION_GROUP_PLAYER; - } - - //If collisionGroup0 is not a player then NPC_ACTOR behaves just like an NPC. - if ( collisionGroup1 == COLLISION_GROUP_NPC_ACTOR && collisionGroup0 != COLLISION_GROUP_PLAYER ) - { - collisionGroup1 = COLLISION_GROUP_NPC; - } - - // This is only for the super physcannon - if ( m_bMegaPhysgun ) - { - if ( collisionGroup0 == COLLISION_GROUP_INTERACTIVE_DEBRIS && collisionGroup1 == COLLISION_GROUP_PLAYER ) - return false; - } - - if ( collisionGroup0 == HL2COLLISION_GROUP_COMBINE_BALL ) - { - if ( collisionGroup1 == HL2COLLISION_GROUP_COMBINE_BALL ) - return false; - } - - if ( collisionGroup0 == HL2COLLISION_GROUP_COMBINE_BALL && collisionGroup1 == HL2COLLISION_GROUP_COMBINE_BALL_NPC ) - return false; - - if ( ( collisionGroup0 == COLLISION_GROUP_WEAPON ) || - ( collisionGroup0 == COLLISION_GROUP_PLAYER ) || - ( collisionGroup0 == COLLISION_GROUP_PROJECTILE ) ) - { - if ( collisionGroup1 == HL2COLLISION_GROUP_COMBINE_BALL ) - return false; - } - - if ( collisionGroup0 == COLLISION_GROUP_DEBRIS ) - { - if ( collisionGroup1 == HL2COLLISION_GROUP_COMBINE_BALL ) - return true; - } - - if (collisionGroup0 == HL2COLLISION_GROUP_HOUNDEYE && collisionGroup1 == HL2COLLISION_GROUP_HOUNDEYE ) - return false; - - if (collisionGroup0 == HL2COLLISION_GROUP_HOMING_MISSILE && collisionGroup1 == HL2COLLISION_GROUP_HOMING_MISSILE ) - return false; - - if ( collisionGroup1 == HL2COLLISION_GROUP_CROW ) - { - if ( collisionGroup0 == COLLISION_GROUP_PLAYER || collisionGroup0 == COLLISION_GROUP_NPC || - collisionGroup0 == HL2COLLISION_GROUP_CROW ) - return false; - } - - if ( ( collisionGroup0 == HL2COLLISION_GROUP_HEADCRAB ) && ( collisionGroup1 == HL2COLLISION_GROUP_HEADCRAB ) ) - return false; - - // striders don't collide with other striders - if ( collisionGroup0 == HL2COLLISION_GROUP_STRIDER && collisionGroup1 == HL2COLLISION_GROUP_STRIDER ) - return false; - - // gunships don't collide with other gunships - if ( collisionGroup0 == HL2COLLISION_GROUP_GUNSHIP && collisionGroup1 == HL2COLLISION_GROUP_GUNSHIP ) - return false; - - // weapons and NPCs don't collide - if ( collisionGroup0 == COLLISION_GROUP_WEAPON && (collisionGroup1 >= HL2COLLISION_GROUP_FIRST_NPC && collisionGroup1 <= HL2COLLISION_GROUP_LAST_NPC ) ) - return false; - - //players don't collide against NPC Actors. - //I could've done this up where I check if collisionGroup0 is NOT a player but I decided to just - //do what the other checks are doing in this function for consistency sake. - if ( collisionGroup1 == COLLISION_GROUP_NPC_ACTOR && collisionGroup0 == COLLISION_GROUP_PLAYER ) - return false; - - // In cases where NPCs are playing a script which causes them to interpenetrate while riding on another entity, - // such as a train or elevator, you need to disable collisions between the actors so the mover can move them. - if ( collisionGroup0 == COLLISION_GROUP_NPC_SCRIPTED && collisionGroup1 == COLLISION_GROUP_NPC_SCRIPTED ) - return false; - - // Spit doesn't touch other spit - if ( collisionGroup0 == HL2COLLISION_GROUP_SPIT && collisionGroup1 == HL2COLLISION_GROUP_SPIT ) - return false; - - return BaseClass::ShouldCollide( collisionGroup0, collisionGroup1 ); -} - -#ifndef CLIENT_DLL -//--------------------------------------------------------- -//--------------------------------------------------------- -void CHalfLife2::AdjustPlayerDamageTaken( CTakeDamageInfo *pInfo ) -{ - if( pInfo->GetDamageType() & (DMG_DROWN|DMG_CRUSH|DMG_FALL|DMG_POISON|DMG_SNIPER) ) - { - // Skill level doesn't affect these types of damage. - return; - } - - switch( GetSkillLevel() ) - { - case SKILL_EASY: - pInfo->ScaleDamage( sk_dmg_take_scale1.GetFloat() ); - break; - - case SKILL_MEDIUM: - pInfo->ScaleDamage( sk_dmg_take_scale2.GetFloat() ); - break; - - case SKILL_HARD: - pInfo->ScaleDamage( sk_dmg_take_scale3.GetFloat() ); - break; - } -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -float CHalfLife2::AdjustPlayerDamageInflicted( float damage ) -{ - switch( GetSkillLevel() ) - { - case SKILL_EASY: - return damage * sk_dmg_inflict_scale1.GetFloat(); - break; - - case SKILL_MEDIUM: - return damage * sk_dmg_inflict_scale2.GetFloat(); - break; - - case SKILL_HARD: - return damage * sk_dmg_inflict_scale3.GetFloat(); - break; - - default: - return damage; - break; - } -} -#endif//CLIENT_DLL - -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CHalfLife2::ShouldUseRobustRadiusDamage(CBaseEntity *pEntity) -{ -#ifdef CLIENT_DLL - return false; -#endif - - if( !sv_robust_explosions.GetBool() ) - return false; - - if( !pEntity->IsNPC() ) - { - // Only NPC's - return false; - } - -#ifndef CLIENT_DLL - CAI_BaseNPC *pNPC = pEntity->MyNPCPointer(); - if( pNPC->CapabilitiesGet() & bits_CAP_SIMPLE_RADIUS_DAMAGE ) - { - // This NPC only eligible for simple radius damage. - return false; - } -#endif//CLIENT_DLL - - return true; -} - -#ifndef CLIENT_DLL -//--------------------------------------------------------- -//--------------------------------------------------------- -bool CHalfLife2::ShouldAutoAim( CBasePlayer *pPlayer, edict_t *target ) -{ - return sk_allow_autoaim.GetBool() != 0; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -float CHalfLife2::GetAutoAimScale( CBasePlayer *pPlayer ) -{ -#ifdef _X360 - return 1.0f; -#else - switch( GetSkillLevel() ) - { - case SKILL_EASY: - return sk_autoaim_scale1.GetFloat(); - - case SKILL_MEDIUM: - return sk_autoaim_scale2.GetFloat(); - - default: - return 0.0f; - } -#endif -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -float CHalfLife2::GetAmmoQuantityScale( int iAmmoIndex ) -{ - switch( GetSkillLevel() ) - { - case SKILL_EASY: - return sk_ammo_qty_scale1.GetFloat(); - - case SKILL_MEDIUM: - return sk_ammo_qty_scale2.GetFloat(); - - case SKILL_HARD: - return sk_ammo_qty_scale3.GetFloat(); - - default: - return 0.0f; - } -} - -void CHalfLife2::LevelInitPreEntity() -{ - // Remove this if you fix the bug in ep1 where the striders need to touch - // triggers using their absbox instead of their bbox -#ifdef HL2_EPISODIC - if ( !Q_strnicmp( gpGlobals->mapname.ToCStr(), "ep1_", 4 ) ) - { - // episode 1 maps use the surrounding box trigger behavior - CBaseEntity::sm_bAccurateTriggerBboxChecks = false; - } -#endif - BaseClass::LevelInitPreEntity(); -} - -//----------------------------------------------------------------------------- -// Returns whether or not Alyx cares about light levels in order to see. -//----------------------------------------------------------------------------- -bool CHalfLife2::IsAlyxInDarknessMode() -{ -#ifdef HL2_EPISODIC - if ( alyx_darkness_force.GetBool() ) - return true; - - return ( GlobalEntity_GetState( "ep_alyx_darknessmode" ) == GLOBAL_ON ); -#else - return false; -#endif // HL2_EPISODIC -} - - -//----------------------------------------------------------------------------- -// This takes the long way around to see if a prop should emit a DLIGHT when it -// ignites, to avoid having Alyx-related code in props.cpp. -//----------------------------------------------------------------------------- -bool CHalfLife2::ShouldBurningPropsEmitLight() -{ -#ifdef HL2_EPISODIC - return IsAlyxInDarknessMode(); -#else - return false; -#endif // HL2_EPISODIC -} - - -#endif//CLIENT_DLL - -// ------------------------------------------------------------------------------------ // -// Global functions. -// ------------------------------------------------------------------------------------ // - -#ifndef HL2MP -#ifndef PORTAL - -// shared ammo definition -// JAY: Trying to make a more physical bullet response -#define BULLET_MASS_GRAINS_TO_LB(grains) (0.002285*(grains)/16.0f) -#define BULLET_MASS_GRAINS_TO_KG(grains) lbs2kg(BULLET_MASS_GRAINS_TO_LB(grains)) - -// exaggerate all of the forces, but use real numbers to keep them consistent -#define BULLET_IMPULSE_EXAGGERATION 3.5 -// convert a velocity in ft/sec and a mass in grains to an impulse in kg in/s -#define BULLET_IMPULSE(grains, ftpersec) ((ftpersec)*12*BULLET_MASS_GRAINS_TO_KG(grains)*BULLET_IMPULSE_EXAGGERATION) - - -CAmmoDef *GetAmmoDef() -{ - static CAmmoDef def; - static bool bInitted = false; - - if ( !bInitted ) - { - bInitted = true; - - def.AddAmmoType("AR2", DMG_BULLET, TRACER_LINE_AND_WHIZ, "sk_plr_dmg_ar2", "sk_npc_dmg_ar2", "sk_max_ar2", BULLET_IMPULSE(200, 1225), 0 ); - def.AddAmmoType("AlyxGun", DMG_BULLET, TRACER_LINE, "sk_plr_dmg_alyxgun", "sk_npc_dmg_alyxgun", "sk_max_alyxgun", BULLET_IMPULSE(200, 1225), 0 ); - def.AddAmmoType("Pistol", DMG_BULLET, TRACER_LINE_AND_WHIZ, "sk_plr_dmg_pistol", "sk_npc_dmg_pistol", "sk_max_pistol", BULLET_IMPULSE(200, 1225), 0 ); - def.AddAmmoType("SMG1", DMG_BULLET, TRACER_LINE_AND_WHIZ, "sk_plr_dmg_smg1", "sk_npc_dmg_smg1", "sk_max_smg1", BULLET_IMPULSE(200, 1225), 0 ); - def.AddAmmoType("357", DMG_BULLET, TRACER_LINE_AND_WHIZ, "sk_plr_dmg_357", "sk_npc_dmg_357", "sk_max_357", BULLET_IMPULSE(800, 5000), 0 ); - def.AddAmmoType("XBowBolt", DMG_BULLET, TRACER_LINE, "sk_plr_dmg_crossbow", "sk_npc_dmg_crossbow", "sk_max_crossbow", BULLET_IMPULSE(800, 8000), 0 ); - - def.AddAmmoType("Buckshot", DMG_BULLET | DMG_BUCKSHOT, TRACER_LINE, "sk_plr_dmg_buckshot", "sk_npc_dmg_buckshot", "sk_max_buckshot", BULLET_IMPULSE(400, 1200), 0 ); - def.AddAmmoType("RPG_Round", DMG_BURN, TRACER_NONE, "sk_plr_dmg_rpg_round", "sk_npc_dmg_rpg_round", "sk_max_rpg_round", 0, 0 ); - def.AddAmmoType("SMG1_Grenade", DMG_BURN, TRACER_NONE, "sk_plr_dmg_smg1_grenade", "sk_npc_dmg_smg1_grenade", "sk_max_smg1_grenade", 0, 0 ); - def.AddAmmoType("SniperRound", DMG_BULLET | DMG_SNIPER, TRACER_NONE, "sk_plr_dmg_sniper_round", "sk_npc_dmg_sniper_round", "sk_max_sniper_round", BULLET_IMPULSE(650, 6000), 0 ); - def.AddAmmoType("SniperPenetratedRound", DMG_BULLET | DMG_SNIPER, TRACER_NONE, "sk_dmg_sniper_penetrate_plr", "sk_dmg_sniper_penetrate_npc", "sk_max_sniper_round", BULLET_IMPULSE(150, 6000), 0 ); - def.AddAmmoType("Grenade", DMG_BURN, TRACER_NONE, "sk_plr_dmg_grenade", "sk_npc_dmg_grenade", "sk_max_grenade", 0, 0); - def.AddAmmoType("Thumper", DMG_SONIC, TRACER_NONE, 10, 10, 2, 0, 0 ); - def.AddAmmoType("Gravity", DMG_CLUB, TRACER_NONE, 0, 0, 8, 0, 0 ); -// def.AddAmmoType("Extinguisher", DMG_BURN, TRACER_NONE, 0, 0, 100, 0, 0 ); - def.AddAmmoType("Battery", DMG_CLUB, TRACER_NONE, 0, 0, 0, 0, 0 ); - def.AddAmmoType("GaussEnergy", DMG_SHOCK, TRACER_NONE, "sk_jeep_gauss_damage", "sk_jeep_gauss_damage", "sk_max_gauss_round", BULLET_IMPULSE(650, 8000), 0 ); // hit like a 10kg weight at 400 in/s - def.AddAmmoType("CombineCannon", DMG_BULLET, TRACER_LINE, "sk_npc_dmg_gunship_to_plr", "sk_npc_dmg_gunship", NULL, 1.5 * 750 * 12, 0 ); // hit like a 1.5kg weight at 750 ft/s - def.AddAmmoType("AirboatGun", DMG_AIRBOAT, TRACER_LINE, "sk_plr_dmg_airboat", "sk_npc_dmg_airboat", NULL, BULLET_IMPULSE(10, 600), 0 ); - - //===================================================================== - // STRIDER MINIGUN DAMAGE - Pull up a chair and I'll tell you a tale. - // - // When we shipped Half-Life 2 in 2004, we were unaware of a bug in - // CAmmoDef::NPCDamage() which was returning the MaxCarry field of - // an ammotype as the amount of damage that should be done to a NPC - // by that type of ammo. Thankfully, the bug only affected Ammo Types - // that DO NOT use ConVars to specify their parameters. As you can see, - // all of the important ammotypes use ConVars, so the effect of the bug - // was limited. The Strider Minigun was affected, though. - // - // According to my perforce Archeology, we intended to ship the Strider - // Minigun ammo type to do 15 points of damage per shot, and we did. - // To achieve this we, unaware of the bug, set the Strider Minigun ammo - // type to have a maxcarry of 15, since our observation was that the - // number that was there before (8) was indeed the amount of damage being - // done to NPC's at the time. So we changed the field that was incorrectly - // being used as the NPC Damage field. - // - // The bug was fixed during Episode 1's development. The result of the - // bug fix was that the Strider was reduced to doing 5 points of damage - // to NPC's, since 5 is the value that was being assigned as NPC damage - // even though the code was returning 15 up to that point. - // - // Now as we go to ship Orange Box, we discover that the Striders in - // Half-Life 2 are hugely ineffective against citizens, causing big - // problems in maps 12 and 13. - // - // In order to restore balance to HL2 without upsetting the delicate - // balance of ep2_outland_12, I have chosen to build Episodic binaries - // with 5 as the Strider->NPC damage, since that's the value that has - // been in place for all of Episode 2's development. Half-Life 2 will - // build with 15 as the Strider->NPC damage, which is how HL2 shipped - // originally, only this time the 15 is located in the correct field - // now that the AmmoDef code is behaving correctly. - // - //===================================================================== -#ifdef HL2_EPISODIC - def.AddAmmoType("StriderMinigun", DMG_BULLET, TRACER_LINE, 5, 5, 15, 1.0 * 750 * 12, AMMO_FORCE_DROP_IF_CARRIED ); // hit like a 1.0kg weight at 750 ft/s -#else - def.AddAmmoType("StriderMinigun", DMG_BULLET, TRACER_LINE, 5, 15,15, 1.0 * 750 * 12, AMMO_FORCE_DROP_IF_CARRIED ); // hit like a 1.0kg weight at 750 ft/s -#endif//HL2_EPISODIC - - def.AddAmmoType("StriderMinigunDirect", DMG_BULLET, TRACER_LINE, 2, 2, 15, 1.0 * 750 * 12, AMMO_FORCE_DROP_IF_CARRIED ); // hit like a 1.0kg weight at 750 ft/s - def.AddAmmoType("HelicopterGun", DMG_BULLET, TRACER_LINE_AND_WHIZ, "sk_npc_dmg_helicopter_to_plr", "sk_npc_dmg_helicopter", "sk_max_smg1", BULLET_IMPULSE(400, 1225), AMMO_FORCE_DROP_IF_CARRIED | AMMO_INTERPRET_PLRDAMAGE_AS_DAMAGE_TO_PLAYER ); - def.AddAmmoType("AR2AltFire", DMG_DISSOLVE, TRACER_NONE, 0, 0, "sk_max_ar2_altfire", 0, 0 ); - def.AddAmmoType("Grenade", DMG_BURN, TRACER_NONE, "sk_plr_dmg_grenade", "sk_npc_dmg_grenade", "sk_max_grenade", 0, 0); -#ifdef HL2_EPISODIC - def.AddAmmoType("Hopwire", DMG_BLAST, TRACER_NONE, "sk_plr_dmg_grenade", "sk_npc_dmg_grenade", "sk_max_hopwire", 0, 0); - def.AddAmmoType("CombineHeavyCannon", DMG_BULLET, TRACER_LINE, 40, 40, 0, 10 * 750 * 12, AMMO_FORCE_DROP_IF_CARRIED ); // hit like a 10 kg weight at 750 ft/s - def.AddAmmoType("ammo_proto1", DMG_BULLET, TRACER_LINE, 0, 0, 10, 0, 0 ); -#endif // HL2_EPISODIC - } - - return &def; -} - -#endif -#endif diff --git a/game/shared/hl2/hl2_gamerules.h b/game/shared/hl2/hl2_gamerules.h deleted file mode 100644 index b3d3ef28c..000000000 --- a/game/shared/hl2/hl2_gamerules.h +++ /dev/null @@ -1,114 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Game rules for Half-Life 2. -// -//=============================================================================// - -#ifndef HL2_GAMERULES_H -#define HL2_GAMERULES_H -#ifdef _WIN32 -#pragma once -#endif - -#include "gamerules.h" -#include "singleplay_gamerules.h" -#include "hl2_shareddefs.h" - -#ifdef CLIENT_DLL - #define CHalfLife2 C_HalfLife2 - #define CHalfLife2Proxy C_HalfLife2Proxy -#endif - - -class CHalfLife2Proxy : public CGameRulesProxy -{ -public: - DECLARE_CLASS( CHalfLife2Proxy, CGameRulesProxy ); - DECLARE_NETWORKCLASS(); -}; - - -class CHalfLife2 : public CSingleplayRules -{ -public: - DECLARE_CLASS( CHalfLife2, CSingleplayRules ); - - // Damage Query Overrides. - virtual bool Damage_IsTimeBased( int iDmgType ); - // TEMP: - virtual int Damage_GetTimeBased( void ); - - virtual bool ShouldCollide( int collisionGroup0, int collisionGroup1 ); - virtual bool ShouldUseRobustRadiusDamage(CBaseEntity *pEntity); -#ifndef CLIENT_DLL - virtual bool ShouldAutoAim( CBasePlayer *pPlayer, edict_t *target ); - virtual float GetAutoAimScale( CBasePlayer *pPlayer ); - virtual float GetAmmoQuantityScale( int iAmmoIndex ); - virtual void LevelInitPreEntity(); -#endif - -private: - // Rules change for the mega physgun - CNetworkVar( bool, m_bMegaPhysgun ); - -#ifdef CLIENT_DLL - - DECLARE_CLIENTCLASS_NOBASE(); // This makes datatables able to access our private vars. - -#else - - DECLARE_SERVERCLASS_NOBASE(); // This makes datatables able to access our private vars. - - CHalfLife2(); - virtual ~CHalfLife2() {} - - virtual void Think( void ); - - virtual bool ClientCommand( CBaseEntity *pEdict, const CCommand &args ); - virtual void PlayerSpawn( CBasePlayer *pPlayer ); - - virtual void InitDefaultAIRelationships( void ); - virtual const char* AIClassText(int classType); - virtual const char *GetGameDescription( void ) { return "Half-Life 2"; } - - // Ammo - virtual void PlayerThink( CBasePlayer *pPlayer ); - virtual float GetAmmoDamage( CBaseEntity *pAttacker, CBaseEntity *pVictim, int nAmmoType ); - - virtual bool ShouldBurningPropsEmitLight(); -public: - - bool AllowDamage( CBaseEntity *pVictim, const CTakeDamageInfo &info ); - - bool NPC_ShouldDropGrenade( CBasePlayer *pRecipient ); - bool NPC_ShouldDropHealth( CBasePlayer *pRecipient ); - void NPC_DroppedHealth( void ); - void NPC_DroppedGrenade( void ); - bool MegaPhyscannonActive( void ) { return m_bMegaPhysgun; } - - virtual bool IsAlyxInDarknessMode(); - -private: - - float m_flLastHealthDropTime; - float m_flLastGrenadeDropTime; - - void AdjustPlayerDamageTaken( CTakeDamageInfo *pInfo ); - float AdjustPlayerDamageInflicted( float damage ); - - int DefaultFOV( void ) { return 75; } -#endif -}; - - -//----------------------------------------------------------------------------- -// Gets us at the Half-Life 2 game rules -//----------------------------------------------------------------------------- -inline CHalfLife2* HL2GameRules() -{ - return static_cast(g_pGameRules); -} - - - -#endif // HL2_GAMERULES_H diff --git a/game/shared/hl2/hl2_player_shared.h b/game/shared/hl2/hl2_player_shared.h deleted file mode 100644 index cb8bca6b6..000000000 --- a/game/shared/hl2/hl2_player_shared.h +++ /dev/null @@ -1,21 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef HL2_PLAYER_SHARED_H -#define HL2_PLAYER_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - -// Shared header file for players -#if defined( CLIENT_DLL ) -#define CHL2_Player C_BaseHLPlayer //FIXME: Lovely naming job between server and client here... -#include "c_basehlplayer.h" -#else -#include "hl2_player.h" -#endif - -#endif // HL2_PLAYER_SHARED_H diff --git a/game/shared/hl2/hl2_shareddefs.h b/game/shared/hl2/hl2_shareddefs.h deleted file mode 100644 index 2a50fe255..000000000 --- a/game/shared/hl2/hl2_shareddefs.h +++ /dev/null @@ -1,49 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef HL2_SHAREDDEFS_H -#define HL2_SHAREDDEFS_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "const.h" - - -//-------------------------------------------------------------------------- -// Collision groups -//-------------------------------------------------------------------------- - -enum -{ - HL2COLLISION_GROUP_PLASMANODE = LAST_SHARED_COLLISION_GROUP, - HL2COLLISION_GROUP_SPIT, - HL2COLLISION_GROUP_HOMING_MISSILE, - HL2COLLISION_GROUP_COMBINE_BALL, - - HL2COLLISION_GROUP_FIRST_NPC, - HL2COLLISION_GROUP_HOUNDEYE, - HL2COLLISION_GROUP_CROW, - HL2COLLISION_GROUP_HEADCRAB, - HL2COLLISION_GROUP_STRIDER, - HL2COLLISION_GROUP_GUNSHIP, - HL2COLLISION_GROUP_ANTLION, - HL2COLLISION_GROUP_LAST_NPC, - HL2COLLISION_GROUP_COMBINE_BALL_NPC, -}; - - -//-------------- -// HL2 SPECIFIC -//-------------- -#define DMG_SNIPER (DMG_LASTGENERICFLAG<<1) // This is sniper damage -#define DMG_MISSILEDEFENSE (DMG_LASTGENERICFLAG<<2) // The only kind of damage missiles take. (special missile defense) - - - -#endif // HL2_SHAREDDEFS_H diff --git a/game/shared/hl2/hl2_usermessages.cpp b/game/shared/hl2/hl2_usermessages.cpp deleted file mode 100644 index 19f891efa..000000000 --- a/game/shared/hl2/hl2_usermessages.cpp +++ /dev/null @@ -1,45 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "usermessages.h" -#include "shake.h" -#include "voice_gamemgr.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -void RegisterUserMessages( void ) -{ - usermessages->Register( "Geiger", 1 ); - usermessages->Register( "Train", 1 ); - usermessages->Register( "HudText", -1 ); - usermessages->Register( "SayText", -1 ); - usermessages->Register( "SayText2", -1 ); - usermessages->Register( "TextMsg", -1 ); - usermessages->Register( "HudMsg", -1 ); - usermessages->Register( "ResetHUD", 1); // called every respawn - usermessages->Register( "GameTitle", 0 ); - usermessages->Register( "ItemPickup", -1 ); - usermessages->Register( "ShowMenu", -1 ); - usermessages->Register( "Shake", 13 ); - usermessages->Register( "Fade", 10 ); - usermessages->Register( "VGUIMenu", -1 ); // Show VGUI menu - usermessages->Register( "Rumble", 3 ); // Send a rumble to a controller - usermessages->Register( "Battery", 2 ); - usermessages->Register( "Damage", 18 ); // BUG: floats are sent for coords, no variable bitfields in hud & fixed size Msg - usermessages->Register( "VoiceMask", VOICE_MAX_PLAYERS_DW*4 * 2 + 1 ); - usermessages->Register( "RequestState", 0 ); - usermessages->Register( "CloseCaption", -1 ); // Show a caption (by string id number)(duration in 10th of a second) - usermessages->Register( "HintText", -1 ); // Displays hint text display - usermessages->Register( "KeyHintText", -1 ); // Displays hint text display - usermessages->Register( "SquadMemberDied", 0 ); - usermessages->Register( "AmmoDenied", 2 ); - usermessages->Register( "CreditsMsg", 1 ); - usermessages->Register( "LogoTimeMsg", 4 ); - usermessages->Register( "AchievementEvent", -1 ); - usermessages->Register( "UpdateJalopyRadar", -1 ); -} diff --git a/game/shared/hl2/hl2_vehicle_radar.h b/game/shared/hl2/hl2_vehicle_radar.h deleted file mode 100644 index 7fa64f996..000000000 --- a/game/shared/hl2/hl2_vehicle_radar.h +++ /dev/null @@ -1,27 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef HL2_VEHICLE_RADAR_H -#define HL2_VEHICLE_RADAR_H - -#define RADAR_MAX_CONTACTS 24 -#define RADAR_CONTACT_TYPE_BITS 3 // Max 8 types of contacts (for networking) -#define RADAR_UPDATE_FREQUENCY 1.5f -#define RADAR_UPDATE_FREQUENCY_FAST 0.5f - -enum // If we have more than 16 types of contacts, RADAR_CONTACT_TYPE_BITS -{ - RADAR_CONTACT_NONE = -1, - RADAR_CONTACT_GENERIC = 0, - RADAR_CONTACT_MAGNUSSEN_RDU, - RADAR_CONTACT_DOG, - RADAR_CONTACT_ALLY_INSTALLATION, - RADAR_CONTACT_ENEMY, // 'regular' sized enemy (Hunter) - RADAR_CONTACT_LARGE_ENEMY, // Large enemy (Strider) -}; - -#endif diff --git a/game/shared/hl2/hl_gamemovement.cpp b/game/shared/hl2/hl_gamemovement.cpp deleted file mode 100644 index 1c1d65c64..000000000 --- a/game/shared/hl2/hl_gamemovement.cpp +++ /dev/null @@ -1,1152 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Special handling for hl2 usable ladders -// -//=============================================================================// -#include "cbase.h" -#include "hl_gamemovement.h" -#include "in_buttons.h" -#include "utlrbtree.h" -#include "hl2_shareddefs.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -static ConVar sv_autoladderdismount( "sv_autoladderdismount", "1", FCVAR_REPLICATED, "Automatically dismount from ladders when you reach the end (don't have to +USE)." ); -static ConVar sv_ladderautomountdot( "sv_ladderautomountdot", "0.4", FCVAR_REPLICATED, "When auto-mounting a ladder by looking up its axis, this is the tolerance for looking now directly along the ladder axis." ); - -static ConVar sv_ladder_useonly( "sv_ladder_useonly", "0", FCVAR_REPLICATED, "If set, ladders can only be mounted by pressing +USE" ); - -#define USE_DISMOUNT_SPEED 100 - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CHL2GameMovement::CHL2GameMovement() -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : type - -// Output : int -//----------------------------------------------------------------------------- -int CHL2GameMovement::GetCheckInterval( IntervalType_t type ) -{ - // HL2 ladders need to check every frame!!! - if ( type == LADDER ) - return 1; - - return BaseClass::GetCheckInterval( type ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CHL2GameMovement::IsForceMoveActive() -{ - LadderMove_t *lm = GetLadderMove(); - return lm->m_bForceLadderMove; -} - -//----------------------------------------------------------------------------- -// Purpose: Debounce the USE button -//----------------------------------------------------------------------------- -void CHL2GameMovement::SwallowUseKey() -{ - mv->m_nOldButtons |= IN_USE; - player->m_afButtonPressed &= ~IN_USE; - - GetHL2Player()->m_bPlayUseDenySound = false; -} - -#if !defined( CLIENT_DLL ) -// This is a simple helper class to reserver a player sized hull at a spot, owned by the current player so that nothing -// can move into this spot and cause us to get stuck when we get there -class CReservePlayerSpot : public CBaseEntity -{ - DECLARE_CLASS( CReservePlayerSpot, CBaseEntity ) -public: - static CReservePlayerSpot *ReserveSpot( CBasePlayer *owner, const Vector& org, const Vector& mins, const Vector& maxs, bool& validspot ); - - virtual void Spawn(); -}; - -CReservePlayerSpot *CReservePlayerSpot::ReserveSpot( - CBasePlayer *owner, const Vector& org, const Vector& mins, const Vector& maxs, bool& validspot ) -{ - CReservePlayerSpot *spot = ( CReservePlayerSpot * )CreateEntityByName( "reserved_spot" ); - Assert( spot ); - - spot->SetAbsOrigin( org ); - UTIL_SetSize( spot, mins, maxs ); - spot->SetOwnerEntity( owner ); - spot->Spawn(); - - // See if spot is valid - trace_t tr; - UTIL_TraceHull( - org, - org, - mins, - maxs, - MASK_PLAYERSOLID, - owner, - COLLISION_GROUP_PLAYER_MOVEMENT, - &tr ); - - validspot = !tr.startsolid; - - if ( !validspot ) - { - Vector org2 = org + Vector( 0, 0, 1 ); - - // See if spot is valid - trace_t tr; - UTIL_TraceHull( - org2, - org2, - mins, - maxs, - MASK_PLAYERSOLID, - owner, - COLLISION_GROUP_PLAYER_MOVEMENT, - &tr ); - validspot = !tr.startsolid; - } - - return spot; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CReservePlayerSpot::Spawn() -{ - BaseClass::Spawn(); - - SetSolid( SOLID_BBOX ); - SetMoveType( MOVETYPE_NONE ); - // Make entity invisible - AddEffects( EF_NODRAW ); -} - -LINK_ENTITY_TO_CLASS( reserved_spot, CReservePlayerSpot ); - -#endif -//----------------------------------------------------------------------------- -// Purpose: -// Input : mounting - -// transit_speed - -// goalpos - -// *ladder - -//----------------------------------------------------------------------------- -void CHL2GameMovement::StartForcedMove( bool mounting, float transit_speed, const Vector& goalpos, CFuncLadder *ladder ) -{ - LadderMove_t* lm = GetLadderMove(); - Assert( lm ); - // Already active, just ignore - if ( lm->m_bForceLadderMove ) - { - return; - } - -#if !defined( CLIENT_DLL ) - if ( ladder ) - { - ladder->PlayerGotOn( GetHL2Player() ); - - // If the Ladder only wants to be there for automount checking, abort now - if ( ladder->DontGetOnLadder() ) - return; - } - - // Reserve goal slot here - bool valid = false; - lm->m_hReservedSpot = CReservePlayerSpot::ReserveSpot( - player, - goalpos, - GetPlayerMins( ( player->GetFlags() & FL_DUCKING ) ? true : false ), - GetPlayerMaxs( ( player->GetFlags() & FL_DUCKING ) ? true : false ), - valid ); - if ( !valid ) - { - // FIXME: Play a deny sound? - if ( lm->m_hReservedSpot ) - { - UTIL_Remove( lm->m_hReservedSpot ); - lm->m_hReservedSpot = NULL; - } - return; - } -#endif - - // Use current player origin as start and new origin as dest - lm->m_vecGoalPosition = goalpos; - lm->m_vecStartPosition = mv->GetAbsOrigin(); - - // Figure out how long it will take to make the gap based on transit_speed - Vector delta = lm->m_vecGoalPosition - lm->m_vecStartPosition; - - float distance = delta.Length(); - - Assert( transit_speed > 0.001f ); - - // Compute time required to move that distance - float transit_time = distance / transit_speed; - if ( transit_time < 0.001f ) - { - transit_time = 0.001f; - } - - lm->m_bForceLadderMove = true; - lm->m_bForceMount = mounting; - - lm->m_flStartTime = gpGlobals->curtime; - lm->m_flArrivalTime = lm->m_flStartTime + transit_time; - - lm->m_hForceLadder = ladder; - - // Don't get stuck during this traversal since we'll just be slamming the player origin - player->SetMoveType( MOVETYPE_NONE ); - player->SetMoveCollide( MOVECOLLIDE_DEFAULT ); - player->SetSolid( SOLID_NONE ); - SetLadder( ladder ); - - // Debounce the use key - SwallowUseKey(); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns false when finished -//----------------------------------------------------------------------------- -bool CHL2GameMovement::ContinueForcedMove() -{ - LadderMove_t* lm = GetLadderMove(); - Assert( lm ); - Assert( lm->m_bForceLadderMove ); - - // Suppress regular motion - mv->m_flForwardMove = 0.0f; - mv->m_flSideMove = 0.0f; - mv->m_flUpMove = 0.0f; - - // How far along are we - float frac = ( gpGlobals->curtime - lm->m_flStartTime ) / ( lm->m_flArrivalTime - lm->m_flStartTime ); - if ( frac > 1.0f ) - { - lm->m_bForceLadderMove = false; -#if !defined( CLIENT_DLL ) - // Remove "reservation entity" - if ( lm->m_hReservedSpot ) - { - UTIL_Remove( lm->m_hReservedSpot ); - lm->m_hReservedSpot = NULL; - } -#endif - } - - frac = clamp( frac, 0.0f, 1.0f ); - - // Move origin part of the way - Vector delta = lm->m_vecGoalPosition - lm->m_vecStartPosition; - - // Compute interpolated position - Vector org; - VectorMA( lm->m_vecStartPosition, frac, delta, org ); - mv->SetAbsOrigin( org ); - - // If finished moving, reset player to correct movetype (or put them on the ladder) - if ( !lm->m_bForceLadderMove ) - { - player->SetSolid( SOLID_BBOX ); - player->SetMoveType( MOVETYPE_WALK ); - - if ( lm->m_bForceMount && lm->m_hForceLadder != NULL ) - { - player->SetMoveType( MOVETYPE_LADDER ); - SetLadder( lm->m_hForceLadder ); - } - - // Zero out any velocity - mv->m_vecVelocity.Init(); - } - - // Stil active - return lm->m_bForceLadderMove; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true if the player is on a ladder -// Input : &trace - ignored -//----------------------------------------------------------------------------- -bool CHL2GameMovement::OnLadder( trace_t &trace ) -{ - return ( GetLadder() != NULL ) ? true : false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : ladders - -// maxdist - -// **ppLadder - -// ladderOrigin - -//----------------------------------------------------------------------------- -void CHL2GameMovement::Findladder( float maxdist, CFuncLadder **ppLadder, Vector& ladderOrigin, const CFuncLadder *skipLadder ) -{ - CFuncLadder *bestLadder = NULL; - float bestDist = MAX_COORD_INTEGER; - Vector bestOrigin; - - bestOrigin.Init(); - - float maxdistSqr = maxdist * maxdist; - - - int c = CFuncLadder::GetLadderCount(); - for ( int i = 0 ; i < c; i++ ) - { - CFuncLadder *ladder = CFuncLadder::GetLadder( i ); - - if ( !ladder->IsEnabled() ) - continue; - - if ( skipLadder && ladder == skipLadder ) - continue; - - Vector topPosition; - Vector bottomPosition; - - ladder->GetTopPosition( topPosition ); - ladder->GetBottomPosition( bottomPosition ); - - Vector closest; - CalcClosestPointOnLineSegment( mv->GetAbsOrigin(), bottomPosition, topPosition, closest, NULL ); - - float distSqr = ( closest - mv->GetAbsOrigin() ).LengthSqr(); - - // Too far away - if ( distSqr > maxdistSqr ) - { - continue; - } - - // Need to trace to see if it's clear - trace_t tr; - - UTIL_TraceLine( mv->GetAbsOrigin(), closest, - MASK_PLAYERSOLID, - player, - COLLISION_GROUP_NONE, - &tr ); - - if ( tr.fraction != 1.0f && - tr.m_pEnt && - tr.m_pEnt != ladder ) - { - // Try a trace stepped up from the ground a bit, in case there's something at ground level blocking us. - float sizez = GetPlayerMaxs().z - GetPlayerMins().z; - - UTIL_TraceLine( mv->GetAbsOrigin() + Vector( 0, 0, sizez * 0.5f ), closest, - MASK_PLAYERSOLID, - player, - COLLISION_GROUP_NONE, - &tr ); - - if ( tr.fraction != 1.0f && - tr.m_pEnt && - tr.m_pEnt != ladder && - !tr.m_pEnt->IsSolidFlagSet( FSOLID_TRIGGER ) ) - { - continue; - } - } - - // See if this is the best one so far - if ( distSqr < bestDist ) - { - bestDist = distSqr; - bestLadder = ladder; - bestOrigin = closest; - } - } - - // Return best ladder spot - *ppLadder = bestLadder; - ladderOrigin = bestOrigin; - -} - -static bool NearbyDismountLessFunc( const NearbyDismount_t& lhs, const NearbyDismount_t& rhs ) -{ - return lhs.distSqr < rhs.distSqr; -} - -void CHL2GameMovement::GetSortedDismountNodeList( const Vector &org, float radius, CFuncLadder *ladder, CUtlRBTree< NearbyDismount_t, int >& list ) -{ - float radiusSqr = radius * radius; - - int i; - int c = ladder->GetDismountCount(); - for ( i = 0; i < c; i++ ) - { - CInfoLadderDismount *spot = ladder->GetDismount( i ); - if ( !spot ) - continue; - - float distSqr = ( spot->GetAbsOrigin() - org ).LengthSqr(); - if ( distSqr > radiusSqr ) - continue; - - NearbyDismount_t nd; - nd.dismount = spot; - nd.distSqr = distSqr; - - list.Insert( nd ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// *ladder - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CHL2GameMovement::ExitLadderViaDismountNode( CFuncLadder *ladder, bool strict, bool useAlternate ) -{ - // Find the best ladder exit node - float bestDot = -99999.0f; - float bestDistance = 99999.0f; - Vector bestDest; - bool found = false; - - // For 'alternate' dismount - bool foundAlternate = false; - Vector alternateDest; - float alternateDist = 99999.0f; - - CUtlRBTree< NearbyDismount_t, int > nearbyDismounts( 0, 0, NearbyDismountLessFunc ); - - GetSortedDismountNodeList( mv->GetAbsOrigin(), 100.0f, ladder, nearbyDismounts ); - - int i; - - for ( i = nearbyDismounts.FirstInorder(); i != nearbyDismounts.InvalidIndex() ; i = nearbyDismounts.NextInorder( i ) ) - { - CInfoLadderDismount *spot = nearbyDismounts[ i ].dismount; - if ( !spot ) - { - Assert( !"What happened to the spot!!!" ); - continue; - } - - // See if it's valid to put the player there... - Vector org = spot->GetAbsOrigin() + Vector( 0, 0, 1 ); - - trace_t tr; - UTIL_TraceHull( - org, - org, - GetPlayerMins( ( player->GetFlags() & FL_DUCKING ) ? true : false ), - GetPlayerMaxs( ( player->GetFlags() & FL_DUCKING ) ? true : false ), - MASK_PLAYERSOLID, - player, - COLLISION_GROUP_PLAYER_MOVEMENT, - &tr ); - - // Nope... - if ( tr.startsolid ) - { - continue; - } - - // Find the best dot product - Vector vecToSpot = org - ( mv->GetAbsOrigin() + player->GetViewOffset() ); - vecToSpot.z = 0.0f; - float d = VectorNormalize( vecToSpot ); - - float dot = vecToSpot.Dot( m_vecForward ); - - // We're not facing at it...ignore - if ( dot < 0.5f ) - { - if( useAlternate && d < alternateDist ) - { - alternateDest = org; - alternateDist = d; - foundAlternate = true; - } - - continue; - } - - if ( dot > bestDot ) - { - bestDest = org; - bestDistance = d; - bestDot = dot; - found = true; - } - } - - if ( found ) - { - // Require a more specific - if ( strict && - ( ( bestDot < 0.7f ) || ( bestDistance > 40.0f ) ) ) - { - return false; - } - - StartForcedMove( false, player->MaxSpeed(), bestDest, NULL ); - return true; - } - - if( useAlternate ) - { - // Desperate. Don't refuse to let a person off of a ladder if it can be helped. Use the - // alternate dismount if there is one. - if( foundAlternate && alternateDist <= 60.0f ) - { - StartForcedMove( false, player->MaxSpeed(), alternateDest, NULL ); - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : bOnLadder - -//----------------------------------------------------------------------------- -void CHL2GameMovement::FullLadderMove() -{ -#if !defined( CLIENT_DLL ) - CFuncLadder *ladder = GetLadder(); - Assert( ladder ); - if ( !ladder ) - { - return; - } - - CheckWater(); - - // Was jump button pressed? If so, don't do anything here - if ( mv->m_nButtons & IN_JUMP ) - { - CheckJumpButton(); - return; - } - else - { - mv->m_nOldButtons &= ~IN_JUMP; - } - - player->SetGroundEntity( NULL ); - - // Remember old positions in case we cancel this movement - Vector oldVelocity = mv->m_vecVelocity; - Vector oldOrigin = mv->GetAbsOrigin(); - - Vector topPosition; - Vector bottomPosition; - - ladder->GetTopPosition( topPosition ); - ladder->GetBottomPosition( bottomPosition ); - - // Compute parametric distance along ladder vector... - float oldt; - CalcDistanceSqrToLine( mv->GetAbsOrigin(), topPosition, bottomPosition, &oldt ); - - // Perform the move accounting for any base velocity. - VectorAdd (mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity); - TryPlayerMove(); - VectorSubtract (mv->m_vecVelocity, player->GetBaseVelocity(), mv->m_vecVelocity); - - // Pressed buttons are "changed(xor)" and'ed with the mask of currently held buttons - int buttonsChanged = ( mv->m_nOldButtons ^ mv->m_nButtons ); // These buttons have changed this frame - int buttonsPressed = buttonsChanged & mv->m_nButtons; - bool pressed_use = ( buttonsPressed & IN_USE ) ? true : false; - bool pressing_forward_or_side = mv->m_flForwardMove != 0.0f || mv->m_flSideMove != 0.0f; - - Vector ladderVec = topPosition - bottomPosition; - float LadderLength = VectorNormalize( ladderVec ); - // This test is not perfect by any means, but should help a bit - bool moving_along_ladder = false; - if ( pressing_forward_or_side ) - { - float fwdDot = m_vecForward.Dot( ladderVec ); - if ( fabs( fwdDot ) > 0.9f ) - { - moving_along_ladder = true; - } - } - - // Compute parametric distance along ladder vector... - float newt; - CalcDistanceSqrToLine( mv->GetAbsOrigin(), topPosition, bottomPosition, &newt ); - - // Fudge of 2 units - float tolerance = 1.0f / LadderLength; - - bool wouldleaveladder = false; - // Moving pPast top or bottom? - if ( newt < -tolerance ) - { - wouldleaveladder = newt < oldt; - } - else if ( newt > ( 1.0f + tolerance ) ) - { - wouldleaveladder = newt > oldt; - } - - // See if we are near the top or bottom but not moving - float dist1sqr, dist2sqr; - - dist1sqr = ( topPosition - mv->GetAbsOrigin() ).LengthSqr(); - dist2sqr = ( bottomPosition - mv->GetAbsOrigin() ).LengthSqr(); - - float dist = MIN( dist1sqr, dist2sqr ); - bool neardismountnode = ( dist < 16.0f * 16.0f ) ? true : false; - float ladderUnitsPerTick = ( MAX_CLIMB_SPEED * gpGlobals->interval_per_tick ); - bool neardismountnode2 = ( dist < ladderUnitsPerTick * ladderUnitsPerTick ) ? true : false; - - // Really close to node, cvar is set, and pressing a key, then simulate a +USE - bool auto_dismount_use = ( neardismountnode2 && - sv_autoladderdismount.GetBool() && - pressing_forward_or_side && - !moving_along_ladder ); - - bool fully_underwater = ( player->GetWaterLevel() == WL_Eyes ) ? true : false; - - // If the user manually pressed use or we're simulating it, then use_dismount will occur - bool use_dismount = pressed_use || auto_dismount_use; - - if ( fully_underwater && !use_dismount ) - { - // If fully underwater, we require looking directly at a dismount node - /// to "float off" a ladder mid way... - if ( ExitLadderViaDismountNode( ladder, true ) ) - { - // See if they +used a dismount point mid-span.. - return; - } - } - - // If the movement would leave the ladder and they're not automated or pressing use, disallow the movement - if ( !use_dismount ) - { - if ( wouldleaveladder ) - { - // Don't let them leave the ladder if they were on it - mv->m_vecVelocity = oldVelocity; - mv->SetAbsOrigin( oldOrigin ); - } - return; - } - - // If the move would not leave the ladder and we're near close to the end, then just accept the move - if ( !wouldleaveladder && !neardismountnode ) - { - // Otherwise, if the move would leave the ladder, disallow it. - if ( pressed_use ) - { - if ( ExitLadderViaDismountNode( ladder, false, IsX360() ) ) - { - // See if they +used a dismount point mid-span.. - return; - } - - player->SetMoveType( MOVETYPE_WALK ); - player->SetMoveCollide( MOVECOLLIDE_DEFAULT ); - SetLadder( NULL ); - GetHL2Player()->m_bPlayUseDenySound = false; - - // Dismount with a bit of velocity in facing direction - VectorScale( m_vecForward, USE_DISMOUNT_SPEED, mv->m_vecVelocity ); - mv->m_vecVelocity.z = 50; - } - return; - } - - // Debounce the use key - if ( pressed_use ) - { - SwallowUseKey(); - } - - // Try auto exit, if possible - if ( ExitLadderViaDismountNode( ladder, false, pressed_use ) ) - { - return; - } - - if ( wouldleaveladder ) - { - // Otherwise, if the move would leave the ladder, disallow it. - if ( pressed_use ) - { - player->SetMoveType( MOVETYPE_WALK ); - player->SetMoveCollide( MOVECOLLIDE_DEFAULT ); - SetLadder( NULL ); - - // Dismount with a bit of velocity in facing direction - VectorScale( m_vecForward, USE_DISMOUNT_SPEED, mv->m_vecVelocity ); - mv->m_vecVelocity.z = 50; - } - else - { - mv->m_vecVelocity = oldVelocity; - mv->SetAbsOrigin( oldOrigin ); - } - } -#endif -} - -bool CHL2GameMovement::CheckLadderAutoMountEndPoint( CFuncLadder *ladder, const Vector& bestOrigin ) -{ - // See if we're really near an endpoint - if ( !ladder ) - return false; - - Vector top, bottom; - ladder->GetTopPosition( top ); - ladder->GetBottomPosition( bottom ); - - float d1, d2; - - d1 = ( top - mv->GetAbsOrigin() ).LengthSqr(); - d2 = ( bottom - mv->GetAbsOrigin() ).LengthSqr(); - - if ( d1 > 16 * 16 && d2 > 16 * 16 ) - return false; - - Vector ladderAxis; - - if ( d1 < 16 * 16 ) - { - // Close to top - ladderAxis = bottom - top; - } - else - { - ladderAxis = top - bottom; - } - - VectorNormalize( ladderAxis ); - - if ( ladderAxis.Dot( m_vecForward ) > sv_ladderautomountdot.GetFloat() ) - { - StartForcedMove( true, player->MaxSpeed(), bestOrigin, ladder ); - return true; - } - - return false; -} - -bool CHL2GameMovement::CheckLadderAutoMountCone( CFuncLadder *ladder, const Vector& bestOrigin, float maxAngleDelta, float maxDistToLadder ) -{ - // Never 'back' onto ladders or stafe onto ladders - if ( ladder != NULL && - ( mv->m_flForwardMove > 0.0f ) ) - { - Vector top, bottom; - ladder->GetTopPosition( top ); - ladder->GetBottomPosition( bottom ); - - Vector ladderAxis = top - bottom; - VectorNormalize( ladderAxis ); - - Vector probe = mv->GetAbsOrigin(); - - Vector closest; - CalcClosestPointOnLineSegment( probe, bottom, top, closest, NULL ); - - Vector vecToLadder = closest - probe; - - float dist = VectorNormalize( vecToLadder ); - - Vector flatLadder = vecToLadder; - flatLadder.z = 0.0f; - Vector flatForward = m_vecForward; - flatForward.z = 0.0f; - - VectorNormalize( flatLadder ); - VectorNormalize( flatForward ); - - float facingDot = flatForward.Dot( flatLadder ); - float angle = acos( facingDot ) * 180 / M_PI; - - bool closetoladder = ( dist != 0.0f && dist < maxDistToLadder ) ? true : false; - bool reallyclosetoladder = ( dist != 0.0f && dist < 4.0f ) ? true : false; - - bool facingladderaxis = ( angle < maxAngleDelta ) ? true : false; - bool facingalongaxis = ( (float)fabs( ladderAxis.Dot( m_vecForward ) ) > sv_ladderautomountdot.GetFloat() ) ? true : false; -#if 0 - Msg( "close %i length %.3f maxdist %.3f facing %.3f dot %.3f ang %.3f\n", - closetoladder ? 1 : 0, - dist, - maxDistToLadder, - (float)fabs( ladderAxis.Dot( m_vecForward ) ), - facingDot, - angle); -#endif - - // Tracker 21776: Don't mount ladders this way if strafing - bool strafing = ( fabs( mv->m_flSideMove ) < 1.0f ) ? false : true; - - if ( ( ( facingDot > 0.0f && !strafing ) || facingalongaxis ) && - ( facingladderaxis || reallyclosetoladder ) && - closetoladder ) - { - StartForcedMove( true, player->MaxSpeed(), bestOrigin, ladder ); - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Must be facing toward ladder -// Input : *ladder - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CHL2GameMovement::LookingAtLadder( CFuncLadder *ladder ) -{ - if ( !ladder ) - { - return false; - } - - // Get ladder end points - Vector top, bottom; - ladder->GetTopPosition( top ); - ladder->GetBottomPosition( bottom ); - - // Find closest point on ladder to player (could be an endpoint) - Vector closest; - CalcClosestPointOnLineSegment( mv->GetAbsOrigin(), bottom, top, closest, NULL ); - - // Flatten our view direction to 2D - Vector flatForward = m_vecForward; - flatForward.z = 0.0f; - - // Because the ladder itself is not a solid, the player's origin may actually be - // permitted to pass it, and that will screw up our dot product. - // So back up the player's origin a bit to do the facing calculation. - Vector vecAdjustedOrigin = mv->GetAbsOrigin() - 8.0f * flatForward; - - // Figure out vector from player to closest point on ladder - Vector vecToLadder = closest - vecAdjustedOrigin; - - // Flatten it to 2D - Vector flatLadder = vecToLadder; - flatLadder.z = 0.0f; - - // Normalize the vectors (unnecessary) - VectorNormalize( flatLadder ); - VectorNormalize( flatForward ); - - // Compute dot product to see if forward is in same direction as vec to ladder - float facingDot = flatForward.Dot( flatLadder ); - - float requiredDot = ( sv_ladder_useonly.GetBool() ) ? -0.99 : 0.0; - - // Facing same direction if dot > = requiredDot... - bool facingladder = ( facingDot >= requiredDot ); - - return facingladder; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &trace - -//----------------------------------------------------------------------------- -bool CHL2GameMovement::CheckLadderAutoMount( CFuncLadder *ladder, const Vector& bestOrigin ) -{ -#if !defined( CLIENT_DLL ) - - if ( ladder != NULL ) - { - StartForcedMove( true, player->MaxSpeed(), bestOrigin, ladder ); - return true; - } - -#endif - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CHL2GameMovement::LadderMove( void ) -{ - - if ( player->GetMoveType() == MOVETYPE_NOCLIP ) - { - SetLadder( NULL ); - return false; - } - - // If being forced to mount/dismount continue to act like we are on the ladder - if ( IsForceMoveActive() && ContinueForcedMove() ) - { - return true; - } - - CFuncLadder *bestLadder = NULL; - Vector bestOrigin( 0, 0, 0 ); - - CFuncLadder *ladder = GetLadder(); - - // Something 1) deactivated the ladder... or 2) something external applied - // a force to us. In either case make the player fall, etc. - if ( ladder && - ( !ladder->IsEnabled() || - ( player->GetBaseVelocity().LengthSqr() > 1.0f ) ) ) - { - GetHL2Player()->ExitLadder(); - ladder = NULL; - } - - if ( !ladder ) - { - Findladder( 64.0f, &bestLadder, bestOrigin, NULL ); - } - -#if !defined (CLIENT_DLL) - if( !ladder && bestLadder && sv_ladder_useonly.GetBool() ) - { - GetHL2Player()->DisplayLadderHudHint(); - } -#endif - - int buttonsChanged = ( mv->m_nOldButtons ^ mv->m_nButtons ); // These buttons have changed this frame - int buttonsPressed = buttonsChanged & mv->m_nButtons; - bool pressed_use = ( buttonsPressed & IN_USE ) ? true : false; - - // If I'm already moving on a ladder, use the previous ladder direction - if ( !ladder && !pressed_use ) - { - // If flying through air, allow mounting ladders if we are facing < 15 degress from the ladder and we are close - if ( !ladder && !sv_ladder_useonly.GetBool() ) - { - // Tracker 6625: Don't need to be leaping to auto mount using this method... - // But if we are on the ground, then we must not be backing into the ladder (Tracker 12961) - bool onground = player->GetGroundEntity() ? true : false; - if ( !onground || ( mv->m_flForwardMove > 0.0f ) ) - { - if ( CheckLadderAutoMountCone( bestLadder, bestOrigin, 15.0f, 32.0f ) ) - { - return true; - } - } - - // Pressing forward while looking at ladder and standing (or floating) near a mounting point - if ( mv->m_flForwardMove > 0.0f ) - { - if ( CheckLadderAutoMountEndPoint( bestLadder, bestOrigin ) ) - { - return true; - } - } - } - - return false; - } - - if ( !ladder && - LookingAtLadder( bestLadder ) && - CheckLadderAutoMount( bestLadder, bestOrigin ) ) - { - return true; - } - - // Reassign the ladder - ladder = GetLadder(); - if ( !ladder ) - { - return false; - } - - // Don't play the deny sound - if ( pressed_use ) - { - GetHL2Player()->m_bPlayUseDenySound = false; - } - - // Make sure we are on the ladder - player->SetMoveType( MOVETYPE_LADDER ); - player->SetMoveCollide( MOVECOLLIDE_DEFAULT ); - - player->SetGravity( 0.0f ); - - float forwardSpeed = 0.0f; - float rightSpeed = 0.0f; - - float speed = player->MaxSpeed(); - - - if ( mv->m_nButtons & IN_BACK ) - { - forwardSpeed -= speed; - } - - if ( mv->m_nButtons & IN_FORWARD ) - { - forwardSpeed += speed; - } - - if ( mv->m_nButtons & IN_MOVELEFT ) - { - rightSpeed -= speed; - } - - if ( mv->m_nButtons & IN_MOVERIGHT ) - { - rightSpeed += speed; - } - - if ( mv->m_nButtons & IN_JUMP ) - { - player->SetMoveType( MOVETYPE_WALK ); - // Remove from ladder - SetLadder( NULL ); - - // Jump in view direction - Vector jumpDir = m_vecForward; - - // unless pressing backward or something like that - if ( mv->m_flForwardMove < 0.0f ) - { - jumpDir = -jumpDir; - } - - VectorNormalize( jumpDir ); - - VectorScale( jumpDir, MAX_CLIMB_SPEED, mv->m_vecVelocity ); - // Tracker 13558: Don't add any extra z velocity if facing downward at all - if ( m_vecForward.z >= 0.0f ) - { - mv->m_vecVelocity.z = mv->m_vecVelocity.z + 50; - } - return false; - } - - if ( forwardSpeed != 0 || rightSpeed != 0 ) - { - // See if the player is looking toward the top or the bottom - Vector velocity; - - VectorScale( m_vecForward, forwardSpeed, velocity ); - VectorMA( velocity, rightSpeed, m_vecRight, velocity ); - - VectorNormalize( velocity ); - - Vector ladderUp; - ladder->ComputeLadderDir( ladderUp ); - VectorNormalize( ladderUp ); - - Vector topPosition; - Vector bottomPosition; - - ladder->GetTopPosition( topPosition ); - ladder->GetBottomPosition( bottomPosition ); - - // Check to see if we've mounted the ladder in a bogus spot and, if so, just fall off the ladder... - float dummyt = 0.0f; - float distFromLadderSqr = CalcDistanceSqrToLine( mv->GetAbsOrigin(), topPosition, bottomPosition, &dummyt ); - if ( distFromLadderSqr > 36.0f ) - { - // Uh oh, we fell off zee ladder... - player->SetMoveType( MOVETYPE_WALK ); - // Remove from ladder - SetLadder( NULL ); - return false; - } - - bool ishorizontal = fabs( topPosition.z - bottomPosition.z ) < 64.0f ? true : false; - - float changeover = ishorizontal ? 0.0f : 0.3f; - - float factor = 1.0f; - if ( velocity.z >= 0 ) - { - float dotTop = ladderUp.Dot( velocity ); - if ( dotTop < -changeover ) - { - // Aimed at bottom - factor = -1.0f; - } - } - else - { - float dotBottom = -ladderUp.Dot( velocity ); - if ( dotBottom > changeover ) - { - factor = -1.0f; - } - } - -#ifdef _XBOX - if( sv_ladders_useonly.GetBool() ) - { - // Stick up climbs up, stick down climbs down. No matter which way you're looking. - if ( mv->m_nButtons & IN_FORWARD ) - { - factor = 1.0f; - } - else if( mv->m_nButtons & IN_BACK ) - { - factor = -1.0f; - } - } -#endif//_XBOX - - mv->m_vecVelocity = MAX_CLIMB_SPEED * factor * ladderUp; - } - else - { - mv->m_vecVelocity.Init(); - } - - return true; -} - -void CHL2GameMovement::SetGroundEntity( trace_t *pm ) -{ - CBaseEntity *newGround = pm ? pm->m_pEnt : NULL; - - //Adrian: Special case for combine balls. - if ( newGround && newGround->GetCollisionGroup() == HL2COLLISION_GROUP_COMBINE_BALL_NPC ) - { - return; - } - - BaseClass::SetGroundEntity( pm ); -} - -bool CHL2GameMovement::CanAccelerate() -{ -#ifdef HL2MP - if ( player->IsObserver() ) - { - return true; - } -#endif - - BaseClass::CanAccelerate(); - - return true; -} - - -#ifndef PORTAL // Portal inherits from this but needs to declare it's own global interface - // Expose our interface. - static CHL2GameMovement g_GameMovement; - IGameMovement *g_pGameMovement = ( IGameMovement * )&g_GameMovement; - - EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CGameMovement, IGameMovement,INTERFACENAME_GAMEMOVEMENT, g_GameMovement ); -#endif diff --git a/game/shared/hl2/hl_gamemovement.h b/game/shared/hl2/hl_gamemovement.h deleted file mode 100644 index 27e062bd7..000000000 --- a/game/shared/hl2/hl_gamemovement.h +++ /dev/null @@ -1,129 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Special handling for hl2 usable ladders -// -//=============================================================================// - -#include "gamemovement.h" -#include "func_ladder.h" - -#if defined( CLIENT_DLL ) - -#include "c_basehlplayer.h" -#define CHL2_Player C_BaseHLPlayer -#else - -#include "hl2_player.h" - -#endif - -struct LadderMove_t; -class CInfoLadderDismount; - -struct NearbyDismount_t -{ - CInfoLadderDismount *dismount; - float distSqr; -}; - -//----------------------------------------------------------------------------- -// Purpose: HL2 specific movement code -//----------------------------------------------------------------------------- -class CHL2GameMovement : public CGameMovement -{ - typedef CGameMovement BaseClass; -public: - - CHL2GameMovement(); - -// Overrides - virtual void FullLadderMove(); - virtual bool LadderMove( void ); - virtual bool OnLadder( trace_t &trace ); - virtual int GetCheckInterval( IntervalType_t type ); - virtual void SetGroundEntity( trace_t *pm ); - virtual bool CanAccelerate( void ); - -private: - - // See if we are pressing use near a ladder "mount" point and if so, latch us onto the ladder - bool CheckLadderAutoMount( CFuncLadder *ladder, const Vector& bestOrigin ); - - bool CheckLadderAutoMountCone( CFuncLadder *ladder, const Vector& bestOrigin, float maxAngleDelta, float maxDistToLadder ); - bool CheckLadderAutoMountEndPoint(CFuncLadder *ladder, const Vector& bestOrigin ); - - - bool LookingAtLadder( CFuncLadder *ladder ); - - // Are we forcing the user's position to a new spot - bool IsForceMoveActive(); - // Start forcing player position - void StartForcedMove( bool mounting, float transit_speed, const Vector& goalpos, CFuncLadder *ladder ); - // Returns false when finished - bool ContinueForcedMove(); - - // Given a list of nearby ladders, find the best ladder and the "mount" origin - void Findladder( float maxdist, CFuncLadder **ppLadder, Vector& ladderOrigin, const CFuncLadder *skipLadder ); - - // Debounce the +USE key - void SwallowUseKey(); - - // Returns true if the player will auto-exit the ladder via a dismount node - bool ExitLadderViaDismountNode( CFuncLadder *ladder, bool strict, bool useAlternate = false ); - void GetSortedDismountNodeList( const Vector &org, float radius, CFuncLadder *ladder, CUtlRBTree< NearbyDismount_t, int >& list ); - - LadderMove_t *GetLadderMove(); - CHL2_Player *GetHL2Player(); - - void SetLadder( CFuncLadder *ladder ); - CFuncLadder *GetLadder(); -}; - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline CHL2_Player *CHL2GameMovement::GetHL2Player() -{ - return static_cast< CHL2_Player * >( player ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : inline LadderMove* -//----------------------------------------------------------------------------- -inline LadderMove_t *CHL2GameMovement::GetLadderMove() -{ - CHL2_Player *p = GetHL2Player(); - if ( !p ) - { - return NULL; - } - return p->GetLadderMove(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *ladder - -//----------------------------------------------------------------------------- -inline void CHL2GameMovement::SetLadder( CFuncLadder *ladder ) -{ - CFuncLadder* oldLadder = GetLadder(); - - if ( !ladder && oldLadder ) - { - oldLadder->PlayerGotOff( GetHL2Player() ); - } - - - GetHL2Player()->m_HL2Local.m_hLadder.Set( ladder ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CFuncLadder -//----------------------------------------------------------------------------- -inline CFuncLadder *CHL2GameMovement::GetLadder() -{ - return static_cast( static_cast( GetHL2Player()->m_HL2Local.m_hLadder.Get() ) ); -} diff --git a/game/shared/hl2/hl_movedata.h b/game/shared/hl2/hl_movedata.h deleted file mode 100644 index e7a5bb8ab..000000000 --- a/game/shared/hl2/hl_movedata.h +++ /dev/null @@ -1,51 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef HL_MOVEDATA_H -#define HL_MOVEDATA_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "igamemovement.h" - - -// This class contains HL2-specific prediction data. -class CHLMoveData : public CMoveData -{ -public: - bool m_bIsSprinting; -}; - -class CFuncLadder; -class CReservePlayerSpot; - -//----------------------------------------------------------------------------- -// Purpose: Data related to automatic mounting/dismounting from ladders -//----------------------------------------------------------------------------- -struct LadderMove_t -{ - DECLARE_SIMPLE_DATADESC(); - - // Are we forcing player movement during mount/dismount - bool m_bForceLadderMove; - // Is the forced move getting on or off the ladder - bool m_bForceMount; - - // Simulation info for forcing the player move - float m_flStartTime; - float m_flArrivalTime; - Vector m_vecGoalPosition; - Vector m_vecStartPosition; - - // The ladder entity owning the forced move (for marking us "on" the ladder after automounting it) - CHandle< CFuncLadder > m_hForceLadder; - CHandle< CReservePlayerSpot > m_hReservedSpot; -}; - -#endif // HL_MOVEDATA_H diff --git a/game/shared/hl2/survival_gamerules.cpp b/game/shared/hl2/survival_gamerules.cpp deleted file mode 100644 index bca8709cc..000000000 --- a/game/shared/hl2/survival_gamerules.cpp +++ /dev/null @@ -1,272 +0,0 @@ -#include "cbase.h" - -#ifdef HL2_EPISODIC - -#include "hl2_gamerules.h" -#include "ammodef.h" -#include "hl2_shareddefs.h" -#include "filesystem.h" -#include - -#ifdef CLIENT_DLL - -#else -#include "player.h" -#include "game.h" -#include "gamerules.h" -#include "teamplay_gamerules.h" -#include "hl2_player.h" -#include "voice_gamemgr.h" -#include "globalstate.h" -#include "ai_basenpc.h" -#include "weapon_physcannon.h" -#include "ammodef.h" -#endif - -#ifdef CLIENT_DLL -#define CHalfLife2Survival C_HalfLife2Survival -#define CHalfLife2SurvivalProxy C_HalfLife2SurvivalProxy -#endif - -ConVar gamerules_survival( "gamerules_survival", "0", FCVAR_REPLICATED ); - -class CHalfLife2SurvivalProxy : public CGameRulesProxy -{ -public: - DECLARE_CLASS( CHalfLife2SurvivalProxy, CGameRulesProxy ); - DECLARE_NETWORKCLASS(); -}; - -class CSurvivalAmmo -{ -public: - - char m_szAmmoName[256]; - int m_iAmount; -}; - -class CSurvivalSettings -{ -public: - - CSurvivalSettings(); - - CUtlVector > m_Loadout; - int m_iSpawnHealth; - string_t m_szPickups; - CUtlVector m_Ammo; -}; - -CSurvivalSettings::CSurvivalSettings() -{ - m_iSpawnHealth = 100; -} - -class CHalfLife2Survival : public CHalfLife2 -{ -public: - DECLARE_CLASS( CHalfLife2Survival, CHalfLife2 ); - -#ifdef CLIENT_DLL - - DECLARE_CLIENTCLASS_NOBASE(); // This makes datatables able to access our private vars. - -#else - - DECLARE_SERVERCLASS_NOBASE(); // This makes datatables able to access our private vars. - - CHalfLife2Survival(); - virtual ~CHalfLife2Survival() {} - - virtual void Think( void ); - virtual void PlayerSpawn( CBasePlayer *pPlayer ); - virtual bool IsAllowedToSpawn( CBaseEntity *pEntity ); - virtual void CreateStandardEntities(); - - void ReadSurvivalScriptFile( void ); - void ParseSurvivalSettings( KeyValues *pSubKey ); - void ParseSurvivalAmmo( KeyValues *pSubKey ); - -private: - bool m_bActive; - CSurvivalSettings m_SurvivalSettings; -#endif - -}; - -//----------------------------------------------------------------------------- -// Gets us at the Half-Life 2 game rules -//----------------------------------------------------------------------------- -inline CHalfLife2Survival* HL2SurvivalGameRules() -{ - return static_cast(g_pGameRules); -} - -REGISTER_GAMERULES_CLASS( CHalfLife2Survival ); - -BEGIN_NETWORK_TABLE_NOBASE( CHalfLife2Survival, DT_HL2SurvivalGameRules ) -END_NETWORK_TABLE() - - -LINK_ENTITY_TO_CLASS( hl2_survival_gamerules, CHalfLife2SurvivalProxy ); -IMPLEMENT_NETWORKCLASS_ALIASED( HalfLife2SurvivalProxy, DT_HalfLife2SurvivalProxy ) - -#ifdef CLIENT_DLL - void RecvProxy_HL2SurvivalGameRules( const RecvProp *pProp, void **pOut, void *pData, int objectID ) - { - CHalfLife2Survival *pRules = HL2SurvivalGameRules(); - Assert( pRules ); - *pOut = pRules; - } - - BEGIN_RECV_TABLE( CHalfLife2SurvivalProxy, DT_HalfLife2SurvivalProxy ) - RecvPropDataTable( "hl2_survival_gamerules_data", 0, 0, &REFERENCE_RECV_TABLE( DT_HL2SurvivalGameRules ), RecvProxy_HL2SurvivalGameRules ) - END_RECV_TABLE() - #else - void* SendProxy_HL2SurvivalGameRules( const SendProp *pProp, const void *pStructBase, const void *pData, CSendProxyRecipients *pRecipients, int objectID ) - { - CHalfLife2Survival *pRules = HL2SurvivalGameRules(); - Assert( pRules ); - pRecipients->SetAllRecipients(); - return pRules; - } - - BEGIN_SEND_TABLE( CHalfLife2SurvivalProxy, DT_HalfLife2SurvivalProxy ) - SendPropDataTable( "hl2_survival_gamerules_data", 0, &REFERENCE_SEND_TABLE( DT_HL2SurvivalGameRules ), SendProxy_HL2SurvivalGameRules ) - END_SEND_TABLE() -#endif - -#ifndef CLIENT_DLL - -CHalfLife2Survival::CHalfLife2Survival() -{ - m_bActive = false; -} - -void CHalfLife2Survival::Think( void ) -{ - -} - -bool CHalfLife2Survival::IsAllowedToSpawn( CBaseEntity *pEntity ) -{ - if ( !m_bActive ) - return BaseClass::IsAllowedToSpawn( pEntity ); - - const char *pPickups = STRING( m_SurvivalSettings.m_szPickups ); - if ( !pPickups ) - return false; - - if ( Q_stristr( pPickups, "everything" ) ) - return true; - - if ( Q_stristr( pPickups, pEntity->GetClassname() ) || Q_stristr( pPickups, STRING( pEntity->GetEntityName() ) ) ) - return true; - - return false; -} - -void CHalfLife2Survival::PlayerSpawn( CBasePlayer *pPlayer ) -{ - BaseClass::PlayerSpawn( pPlayer ); - - if ( !m_bActive ) - return; - - pPlayer->EquipSuit(); - pPlayer->SetHealth( m_SurvivalSettings.m_iSpawnHealth ); - - for ( int i = 0; i < m_SurvivalSettings.m_Loadout.Count(); ++i ) - { - pPlayer->GiveNamedItem( m_SurvivalSettings.m_Loadout[i] ); - } - - for ( int i = 0; i < m_SurvivalSettings.m_Ammo.Count(); ++i ) - { - pPlayer->CBasePlayer::GiveAmmo( m_SurvivalSettings.m_Ammo[i].m_iAmount , m_SurvivalSettings.m_Ammo[i].m_szAmmoName ); - } -} - -void CHalfLife2Survival::ParseSurvivalSettings( KeyValues *pSubKey ) -{ - if ( pSubKey == NULL ) - return; - - m_SurvivalSettings.m_szPickups = NULL_STRING; - m_SurvivalSettings.m_iSpawnHealth = 100; - - KeyValues *pTestKey = pSubKey->GetFirstSubKey(); - - while ( pTestKey ) - { - if ( !stricmp( pTestKey->GetName(), "weapons" ) ) - { - const char *pLoadout = pTestKey->GetString(); - Q_SplitString( pLoadout, ";", m_SurvivalSettings.m_Loadout ); - } - else if ( !stricmp( pTestKey->GetName(), "spawnhealth" ) ) - { - m_SurvivalSettings.m_iSpawnHealth = pTestKey->GetInt( 0, 100 ); - } - else if ( !stricmp( pTestKey->GetName(), "allowedpickups" ) ) - { - m_SurvivalSettings.m_szPickups = MAKE_STRING( pTestKey->GetString() ); - } - - pTestKey = pTestKey->GetNextKey(); - } -} - -void CHalfLife2Survival::ParseSurvivalAmmo( KeyValues *pSubKey ) -{ - if ( pSubKey ) - { - KeyValues *pAmmoKey = pSubKey->GetFirstSubKey(); - - while ( pAmmoKey ) - { - CSurvivalAmmo ammo; - - Q_strcpy( ammo.m_szAmmoName, pAmmoKey->GetName() ); - ammo.m_iAmount = pAmmoKey->GetInt(); - - m_SurvivalSettings.m_Ammo.AddToTail( ammo ); - - pAmmoKey = pAmmoKey->GetNextKey(); - } - } -} - -void CHalfLife2Survival::ReadSurvivalScriptFile( void ) -{ - char szFullName[512]; - Q_snprintf( szFullName, sizeof( szFullName ), "maps/%s_survival.txt", STRING(gpGlobals->mapname) ); - - KeyValues *pkvFile = new KeyValues( "Survival" ); - if ( pkvFile->LoadFromFile( filesystem, szFullName, "MOD" ) ) - { - ParseSurvivalSettings( pkvFile->FindKey( "settings" ) ); - ParseSurvivalAmmo( pkvFile->FindKey( "ammo" ) ); - - CUtlVector entities; - UTIL_LoadAndSpawnEntitiesFromScript( entities, szFullName, "Survival", true ); - - // It's important to turn on survival mode after we create all the entities - // in the script, so that we don't remove them if they violate survival rules. - // i.e. we want the player to start with a shotgun, but prevent all future shotguns from spawning. - m_bActive = true; - } - else - { - m_bActive = false; - } -} - -void CHalfLife2Survival::CreateStandardEntities( void ) -{ - ReadSurvivalScriptFile(); -} - -#endif - -#endif diff --git a/game/shared/hl2mp/hl2mp_gamerules.cpp b/game/shared/hl2mp/hl2mp_gamerules.cpp deleted file mode 100644 index ea6ea57a7..000000000 --- a/game/shared/hl2mp/hl2mp_gamerules.cpp +++ /dev/null @@ -1,1271 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "hl2mp_gamerules.h" -#include "viewport_panel_names.h" -#include "gameeventdefs.h" -#include -#include "ammodef.h" - -#ifdef CLIENT_DLL - #include "c_hl2mp_player.h" -#else - - #include "eventqueue.h" - #include "player.h" - #include "gamerules.h" - #include "game.h" - #include "items.h" - #include "entitylist.h" - #include "mapentities.h" - #include "in_buttons.h" - #include - #include "voice_gamemgr.h" - #include "iscorer.h" - #include "hl2mp_player.h" - #include "weapon_hl2mpbasehlmpcombatweapon.h" - #include "team.h" - #include "voice_gamemgr.h" - #include "hl2mp_gameinterface.h" - #include "hl2mp_cvars.h" - -#ifdef DEBUG - #include "hl2mp_bot_temp.h" -#endif - -extern void respawn(CBaseEntity *pEdict, bool fCopyCorpse); - -extern bool FindInList( const char **pStrings, const char *pToFind ); - -ConVar sv_hl2mp_weapon_respawn_time( "sv_hl2mp_weapon_respawn_time", "20", FCVAR_GAMEDLL | FCVAR_NOTIFY ); -ConVar sv_hl2mp_item_respawn_time( "sv_hl2mp_item_respawn_time", "30", FCVAR_GAMEDLL | FCVAR_NOTIFY ); -ConVar sv_report_client_settings("sv_report_client_settings", "0", FCVAR_GAMEDLL | FCVAR_NOTIFY ); - -extern ConVar mp_chattime; - -extern CBaseEntity *g_pLastCombineSpawn; -extern CBaseEntity *g_pLastRebelSpawn; - -#define WEAPON_MAX_DISTANCE_FROM_SPAWN 64 - -#endif - - -REGISTER_GAMERULES_CLASS( CHL2MPRules ); - -BEGIN_NETWORK_TABLE_NOBASE( CHL2MPRules, DT_HL2MPRules ) - - #ifdef CLIENT_DLL - RecvPropBool( RECVINFO( m_bTeamPlayEnabled ) ), - #else - SendPropBool( SENDINFO( m_bTeamPlayEnabled ) ), - #endif - -END_NETWORK_TABLE() - - -LINK_ENTITY_TO_CLASS( hl2mp_gamerules, CHL2MPGameRulesProxy ); -IMPLEMENT_NETWORKCLASS_ALIASED( HL2MPGameRulesProxy, DT_HL2MPGameRulesProxy ) - -static HL2MPViewVectors g_HL2MPViewVectors( - Vector( 0, 0, 64 ), //VEC_VIEW (m_vView) - - Vector(-16, -16, 0 ), //VEC_HULL_MIN (m_vHullMin) - Vector( 16, 16, 72 ), //VEC_HULL_MAX (m_vHullMax) - - Vector(-16, -16, 0 ), //VEC_DUCK_HULL_MIN (m_vDuckHullMin) - Vector( 16, 16, 36 ), //VEC_DUCK_HULL_MAX (m_vDuckHullMax) - Vector( 0, 0, 28 ), //VEC_DUCK_VIEW (m_vDuckView) - - Vector(-10, -10, -10 ), //VEC_OBS_HULL_MIN (m_vObsHullMin) - Vector( 10, 10, 10 ), //VEC_OBS_HULL_MAX (m_vObsHullMax) - - Vector( 0, 0, 14 ), //VEC_DEAD_VIEWHEIGHT (m_vDeadViewHeight) - - Vector(-16, -16, 0 ), //VEC_CROUCH_TRACE_MIN (m_vCrouchTraceMin) - Vector( 16, 16, 60 ) //VEC_CROUCH_TRACE_MAX (m_vCrouchTraceMax) -); - -static const char *s_PreserveEnts[] = -{ - "ai_network", - "ai_hint", - "hl2mp_gamerules", - "team_manager", - "player_manager", - "env_soundscape", - "env_soundscape_proxy", - "env_soundscape_triggerable", - "env_sun", - "env_wind", - "env_fog_controller", - "func_brush", - "func_wall", - "func_buyzone", - "func_illusionary", - "infodecal", - "info_projecteddecal", - "info_node", - "info_target", - "info_node_hint", - "info_player_deathmatch", - "info_player_combine", - "info_player_rebel", - "info_map_parameters", - "keyframe_rope", - "move_rope", - "info_ladder", - "player", - "point_viewcontrol", - "scene_manager", - "shadow_control", - "sky_camera", - "soundent", - "trigger_soundscape", - "viewmodel", - "predicted_viewmodel", - "worldspawn", - "point_devshot_camera", - "", // END Marker -}; - - - -#ifdef CLIENT_DLL - void RecvProxy_HL2MPRules( const RecvProp *pProp, void **pOut, void *pData, int objectID ) - { - CHL2MPRules *pRules = HL2MPRules(); - Assert( pRules ); - *pOut = pRules; - } - - BEGIN_RECV_TABLE( CHL2MPGameRulesProxy, DT_HL2MPGameRulesProxy ) - RecvPropDataTable( "hl2mp_gamerules_data", 0, 0, &REFERENCE_RECV_TABLE( DT_HL2MPRules ), RecvProxy_HL2MPRules ) - END_RECV_TABLE() -#else - void* SendProxy_HL2MPRules( const SendProp *pProp, const void *pStructBase, const void *pData, CSendProxyRecipients *pRecipients, int objectID ) - { - CHL2MPRules *pRules = HL2MPRules(); - Assert( pRules ); - return pRules; - } - - BEGIN_SEND_TABLE( CHL2MPGameRulesProxy, DT_HL2MPGameRulesProxy ) - SendPropDataTable( "hl2mp_gamerules_data", 0, &REFERENCE_SEND_TABLE( DT_HL2MPRules ), SendProxy_HL2MPRules ) - END_SEND_TABLE() -#endif - -#ifndef CLIENT_DLL - - class CVoiceGameMgrHelper : public IVoiceGameMgrHelper - { - public: - virtual bool CanPlayerHearPlayer( CBasePlayer *pListener, CBasePlayer *pTalker, bool &bProximity ) - { - return ( pListener->GetTeamNumber() == pTalker->GetTeamNumber() ); - } - }; - CVoiceGameMgrHelper g_VoiceGameMgrHelper; - IVoiceGameMgrHelper *g_pVoiceGameMgrHelper = &g_VoiceGameMgrHelper; - -#endif - -// NOTE: the indices here must match TEAM_TERRORIST, TEAM_CT, TEAM_SPECTATOR, etc. -const char *sTeamNames[] = -{ - "Unassigned", - "Spectator", - "Combine", - "Rebels", -}; - -CHL2MPRules::CHL2MPRules() -{ -#ifndef CLIENT_DLL - // Create the team managers - for ( size_t i = 0; i < ARRAYSIZE( sTeamNames ); i++ ) - { - CTeam *pTeam = static_cast(CreateEntityByName( "team_manager" )); - pTeam->Init( sTeamNames[i], i ); - - g_Teams.AddToTail( pTeam ); - } - - m_bTeamPlayEnabled = teamplay.GetBool(); - m_flIntermissionEndTime = 0.0f; - m_flGameStartTime = 0; - - m_hRespawnableItemsAndWeapons.RemoveAll(); - m_tmNextPeriodicThink = 0; - m_flRestartGameTime = 0; - m_bCompleteReset = false; - m_bHeardAllPlayersReady = false; - m_bAwaitingReadyRestart = false; - -#endif -} - -const CViewVectors* CHL2MPRules::GetViewVectors()const -{ - return &g_HL2MPViewVectors; -} - -const HL2MPViewVectors* CHL2MPRules::GetHL2MPViewVectors()const -{ - return &g_HL2MPViewVectors; -} - -CHL2MPRules::~CHL2MPRules( void ) -{ -#ifndef CLIENT_DLL - // Note, don't delete each team since they are in the gEntList and will - // automatically be deleted from there, instead. - g_Teams.Purge(); -#endif -} - -void CHL2MPRules::CreateStandardEntities( void ) -{ - -#ifndef CLIENT_DLL - // Create the entity that will send our data to the client. - - BaseClass::CreateStandardEntities(); - - g_pLastCombineSpawn = NULL; - g_pLastRebelSpawn = NULL; - -#ifdef _DEBUG - CBaseEntity *pEnt = -#endif - CBaseEntity::Create( "hl2mp_gamerules", vec3_origin, vec3_angle ); - Assert( pEnt ); -#endif -} - -//========================================================= -// FlWeaponRespawnTime - what is the time in the future -// at which this weapon may spawn? -//========================================================= -float CHL2MPRules::FlWeaponRespawnTime( CBaseCombatWeapon *pWeapon ) -{ -#ifndef CLIENT_DLL - if ( weaponstay.GetInt() > 0 ) - { - // make sure it's only certain weapons - if ( !(pWeapon->GetWeaponFlags() & ITEM_FLAG_LIMITINWORLD) ) - { - return 0; // weapon respawns almost instantly - } - } - - return sv_hl2mp_weapon_respawn_time.GetFloat(); -#endif - - return 0; // weapon respawns almost instantly -} - - -bool CHL2MPRules::IsIntermission( void ) -{ -#ifndef CLIENT_DLL - return m_flIntermissionEndTime > gpGlobals->curtime; -#endif - - return false; -} - -void CHL2MPRules::PlayerKilled( CBasePlayer *pVictim, const CTakeDamageInfo &info ) -{ -#ifndef CLIENT_DLL - if ( IsIntermission() ) - return; - BaseClass::PlayerKilled( pVictim, info ); -#endif -} - - -void CHL2MPRules::Think( void ) -{ - -#ifndef CLIENT_DLL - - CGameRules::Think(); - - if ( g_fGameOver ) // someone else quit the game already - { - // check to see if we should change levels now - if ( m_flIntermissionEndTime < gpGlobals->curtime ) - { - ChangeLevel(); // intermission is over - } - - return; - } - -// float flTimeLimit = mp_timelimit.GetFloat() * 60; - float flFragLimit = fraglimit.GetFloat(); - - if ( GetMapRemainingTime() < 0 ) - { - GoToIntermission(); - return; - } - - if ( flFragLimit ) - { - if( IsTeamplay() == true ) - { - CTeam *pCombine = g_Teams[TEAM_COMBINE]; - CTeam *pRebels = g_Teams[TEAM_REBELS]; - - if ( pCombine->GetScore() >= flFragLimit || pRebels->GetScore() >= flFragLimit ) - { - GoToIntermission(); - return; - } - } - else - { - // check if any player is over the frag limit - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - - if ( pPlayer && pPlayer->FragCount() >= flFragLimit ) - { - GoToIntermission(); - return; - } - } - } - } - - if ( gpGlobals->curtime > m_tmNextPeriodicThink ) - { - CheckAllPlayersReady(); - CheckRestartGame(); - m_tmNextPeriodicThink = gpGlobals->curtime + 1.0; - } - - if ( m_flRestartGameTime > 0.0f && m_flRestartGameTime <= gpGlobals->curtime ) - { - RestartGame(); - } - - if( m_bAwaitingReadyRestart && m_bHeardAllPlayersReady ) - { - UTIL_ClientPrintAll( HUD_PRINTCENTER, "All players ready. Game will restart in 5 seconds" ); - UTIL_ClientPrintAll( HUD_PRINTCONSOLE, "All players ready. Game will restart in 5 seconds" ); - - m_flRestartGameTime = gpGlobals->curtime + 5; - m_bAwaitingReadyRestart = false; - } - - ManageObjectRelocation(); - -#endif -} - -void CHL2MPRules::GoToIntermission( void ) -{ -#ifndef CLIENT_DLL - if ( g_fGameOver ) - return; - - g_fGameOver = true; - - m_flIntermissionEndTime = gpGlobals->curtime + mp_chattime.GetInt(); - - for ( int i = 0; i < MAX_PLAYERS; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - - if ( !pPlayer ) - continue; - - pPlayer->ShowViewPortPanel( PANEL_SCOREBOARD ); - pPlayer->AddFlag( FL_FROZEN ); - } -#endif - -} - -bool CHL2MPRules::CheckGameOver() -{ -#ifndef CLIENT_DLL - if ( g_fGameOver ) // someone else quit the game already - { - // check to see if we should change levels now - if ( m_flIntermissionEndTime < gpGlobals->curtime ) - { - ChangeLevel(); // intermission is over - } - - return true; - } -#endif - - return false; -} - -// when we are within this close to running out of entities, items -// marked with the ITEM_FLAG_LIMITINWORLD will delay their respawn -#define ENTITY_INTOLERANCE 100 - -//========================================================= -// FlWeaponRespawnTime - Returns 0 if the weapon can respawn -// now, otherwise it returns the time at which it can try -// to spawn again. -//========================================================= -float CHL2MPRules::FlWeaponTryRespawn( CBaseCombatWeapon *pWeapon ) -{ -#ifndef CLIENT_DLL - if ( pWeapon && (pWeapon->GetWeaponFlags() & ITEM_FLAG_LIMITINWORLD) ) - { - if ( gEntList.NumberOfEntities() < (gpGlobals->maxEntities - ENTITY_INTOLERANCE) ) - return 0; - - // we're past the entity tolerance level, so delay the respawn - return FlWeaponRespawnTime( pWeapon ); - } -#endif - return 0; -} - -//========================================================= -// VecWeaponRespawnSpot - where should this weapon spawn? -// Some game variations may choose to randomize spawn locations -//========================================================= -Vector CHL2MPRules::VecWeaponRespawnSpot( CBaseCombatWeapon *pWeapon ) -{ -#ifndef CLIENT_DLL - CWeaponHL2MPBase *pHL2Weapon = dynamic_cast< CWeaponHL2MPBase*>( pWeapon ); - - if ( pHL2Weapon ) - { - return pHL2Weapon->GetOriginalSpawnOrigin(); - } -#endif - - return pWeapon->GetAbsOrigin(); -} - -#ifndef CLIENT_DLL - -CItem* IsManagedObjectAnItem( CBaseEntity *pObject ) -{ - return dynamic_cast< CItem*>( pObject ); -} - -CWeaponHL2MPBase* IsManagedObjectAWeapon( CBaseEntity *pObject ) -{ - return dynamic_cast< CWeaponHL2MPBase*>( pObject ); -} - -bool GetObjectsOriginalParameters( CBaseEntity *pObject, Vector &vOriginalOrigin, QAngle &vOriginalAngles ) -{ - if ( CItem *pItem = IsManagedObjectAnItem( pObject ) ) - { - if ( pItem->m_flNextResetCheckTime > gpGlobals->curtime ) - return false; - - vOriginalOrigin = pItem->GetOriginalSpawnOrigin(); - vOriginalAngles = pItem->GetOriginalSpawnAngles(); - - pItem->m_flNextResetCheckTime = gpGlobals->curtime + sv_hl2mp_item_respawn_time.GetFloat(); - return true; - } - else if ( CWeaponHL2MPBase *pWeapon = IsManagedObjectAWeapon( pObject )) - { - if ( pWeapon->m_flNextResetCheckTime > gpGlobals->curtime ) - return false; - - vOriginalOrigin = pWeapon->GetOriginalSpawnOrigin(); - vOriginalAngles = pWeapon->GetOriginalSpawnAngles(); - - pWeapon->m_flNextResetCheckTime = gpGlobals->curtime + sv_hl2mp_weapon_respawn_time.GetFloat(); - return true; - } - - return false; -} - -void CHL2MPRules::ManageObjectRelocation( void ) -{ - int iTotal = m_hRespawnableItemsAndWeapons.Count(); - - if ( iTotal > 0 ) - { - for ( int i = 0; i < iTotal; i++ ) - { - CBaseEntity *pObject = m_hRespawnableItemsAndWeapons[i].Get(); - - if ( pObject ) - { - Vector vSpawOrigin; - QAngle vSpawnAngles; - - if ( GetObjectsOriginalParameters( pObject, vSpawOrigin, vSpawnAngles ) == true ) - { - float flDistanceFromSpawn = (pObject->GetAbsOrigin() - vSpawOrigin ).Length(); - - if ( flDistanceFromSpawn > WEAPON_MAX_DISTANCE_FROM_SPAWN ) - { - bool shouldReset = false; - IPhysicsObject *pPhysics = pObject->VPhysicsGetObject(); - - if ( pPhysics ) - { - shouldReset = pPhysics->IsAsleep(); - } - else - { - shouldReset = (pObject->GetFlags() & FL_ONGROUND) ? true : false; - } - - if ( shouldReset ) - { - pObject->Teleport( &vSpawOrigin, &vSpawnAngles, NULL ); - pObject->EmitSound( "AlyxEmp.Charge" ); - - IPhysicsObject *pPhys = pObject->VPhysicsGetObject(); - - if ( pPhys ) - { - pPhys->Wake(); - } - } - } - } - } - } - } -} - -//========================================================= -//AddLevelDesignerPlacedWeapon -//========================================================= -void CHL2MPRules::AddLevelDesignerPlacedObject( CBaseEntity *pEntity ) -{ - if ( m_hRespawnableItemsAndWeapons.Find( pEntity ) == -1 ) - { - m_hRespawnableItemsAndWeapons.AddToTail( pEntity ); - } -} - -//========================================================= -//RemoveLevelDesignerPlacedWeapon -//========================================================= -void CHL2MPRules::RemoveLevelDesignerPlacedObject( CBaseEntity *pEntity ) -{ - if ( m_hRespawnableItemsAndWeapons.Find( pEntity ) != -1 ) - { - m_hRespawnableItemsAndWeapons.FindAndRemove( pEntity ); - } -} - -//========================================================= -// Where should this item respawn? -// Some game variations may choose to randomize spawn locations -//========================================================= -Vector CHL2MPRules::VecItemRespawnSpot( CItem *pItem ) -{ - return pItem->GetOriginalSpawnOrigin(); -} - -//========================================================= -// What angles should this item use to respawn? -//========================================================= -QAngle CHL2MPRules::VecItemRespawnAngles( CItem *pItem ) -{ - return pItem->GetOriginalSpawnAngles(); -} - -//========================================================= -// At what time in the future may this Item respawn? -//========================================================= -float CHL2MPRules::FlItemRespawnTime( CItem *pItem ) -{ - return sv_hl2mp_item_respawn_time.GetFloat(); -} - - -//========================================================= -// CanHaveWeapon - returns false if the player is not allowed -// to pick up this weapon -//========================================================= -bool CHL2MPRules::CanHavePlayerItem( CBasePlayer *pPlayer, CBaseCombatWeapon *pItem ) -{ - if ( weaponstay.GetInt() > 0 ) - { - if ( pPlayer->Weapon_OwnsThisType( pItem->GetClassname(), pItem->GetSubType() ) ) - return false; - } - - return BaseClass::CanHavePlayerItem( pPlayer, pItem ); -} - -#endif - -//========================================================= -// WeaponShouldRespawn - any conditions inhibiting the -// respawning of this weapon? -//========================================================= -int CHL2MPRules::WeaponShouldRespawn( CBaseCombatWeapon *pWeapon ) -{ -#ifndef CLIENT_DLL - if ( pWeapon->HasSpawnFlags( SF_NORESPAWN ) ) - { - return GR_WEAPON_RESPAWN_NO; - } -#endif - - return GR_WEAPON_RESPAWN_YES; -} - -//----------------------------------------------------------------------------- -// Purpose: Player has just left the game -//----------------------------------------------------------------------------- -void CHL2MPRules::ClientDisconnected( edict_t *pClient ) -{ -#ifndef CLIENT_DLL - // Msg( "CLIENT DISCONNECTED, REMOVING FROM TEAM.\n" ); - - CBasePlayer *pPlayer = (CBasePlayer *)CBaseEntity::Instance( pClient ); - if ( pPlayer ) - { - // Remove the player from his team - if ( pPlayer->GetTeam() ) - { - pPlayer->GetTeam()->RemovePlayer( pPlayer ); - } - } - - BaseClass::ClientDisconnected( pClient ); - -#endif -} - - -//========================================================= -// Deathnotice. -//========================================================= -void CHL2MPRules::DeathNotice( CBasePlayer *pVictim, const CTakeDamageInfo &info ) -{ -#ifndef CLIENT_DLL - // Work out what killed the player, and send a message to all clients about it - const char *killer_weapon_name = "world"; // by default, the player is killed by the world - int killer_ID = 0; - - // Find the killer & the scorer - CBaseEntity *pInflictor = info.GetInflictor(); - CBaseEntity *pKiller = info.GetAttacker(); - CBasePlayer *pScorer = GetDeathScorer( pKiller, pInflictor ); - - // Custom kill type? - if ( info.GetDamageCustom() ) - { - killer_weapon_name = GetDamageCustomString( info ); - if ( pScorer ) - { - killer_ID = pScorer->GetUserID(); - } - } - else - { - // Is the killer a client? - if ( pScorer ) - { - killer_ID = pScorer->GetUserID(); - - if ( pInflictor ) - { - if ( pInflictor == pScorer ) - { - // If the inflictor is the killer, then it must be their current weapon doing the damage - if ( pScorer->GetActiveWeapon() ) - { - killer_weapon_name = pScorer->GetActiveWeapon()->GetClassname(); - } - } - else - { - killer_weapon_name = pInflictor->GetClassname(); // it's just that easy - } - } - } - else - { - killer_weapon_name = pInflictor->GetClassname(); - } - - // strip the NPC_* or weapon_* from the inflictor's classname - if ( strncmp( killer_weapon_name, "weapon_", 7 ) == 0 ) - { - killer_weapon_name += 7; - } - else if ( strncmp( killer_weapon_name, "npc_", 4 ) == 0 ) - { - killer_weapon_name += 4; - } - else if ( strncmp( killer_weapon_name, "func_", 5 ) == 0 ) - { - killer_weapon_name += 5; - } - else if ( strstr( killer_weapon_name, "physics" ) ) - { - killer_weapon_name = "physics"; - } - - if ( strcmp( killer_weapon_name, "prop_combine_ball" ) == 0 ) - { - killer_weapon_name = "combine_ball"; - } - else if ( strcmp( killer_weapon_name, "grenade_ar2" ) == 0 ) - { - killer_weapon_name = "smg1_grenade"; - } - else if ( strcmp( killer_weapon_name, "satchel" ) == 0 || strcmp( killer_weapon_name, "tripmine" ) == 0) - { - killer_weapon_name = "slam"; - } - - - } - - IGameEvent *event = gameeventmanager->CreateEvent( "player_death" ); - if( event ) - { - event->SetInt("userid", pVictim->GetUserID() ); - event->SetInt("attacker", killer_ID ); - event->SetString("weapon", killer_weapon_name ); - event->SetInt( "priority", 7 ); - gameeventmanager->FireEvent( event ); - } -#endif - -} - -void CHL2MPRules::ClientSettingsChanged( CBasePlayer *pPlayer ) -{ -#ifndef CLIENT_DLL - - CHL2MP_Player *pHL2Player = ToHL2MPPlayer( pPlayer ); - - if ( pHL2Player == NULL ) - return; - - const char *pCurrentModel = modelinfo->GetModelName( pPlayer->GetModel() ); - const char *szModelName = engine->GetClientConVarValue( engine->IndexOfEdict( pPlayer->edict() ), "cl_playermodel" ); - - //If we're different. - if ( stricmp( szModelName, pCurrentModel ) ) - { - //Too soon, set the cvar back to what it was. - //Note: this will make this function be called again - //but since our models will match it'll just skip this whole dealio. - if ( pHL2Player->GetNextModelChangeTime() >= gpGlobals->curtime ) - { - char szReturnString[512]; - - Q_snprintf( szReturnString, sizeof (szReturnString ), "cl_playermodel %s\n", pCurrentModel ); - engine->ClientCommand ( pHL2Player->edict(), szReturnString ); - - Q_snprintf( szReturnString, sizeof( szReturnString ), "Please wait %d more seconds before trying to switch.\n", (int)(pHL2Player->GetNextModelChangeTime() - gpGlobals->curtime) ); - ClientPrint( pHL2Player, HUD_PRINTTALK, szReturnString ); - return; - } - - if ( HL2MPRules()->IsTeamplay() == false ) - { - pHL2Player->SetPlayerModel(); - - const char *pszCurrentModelName = modelinfo->GetModelName( pHL2Player->GetModel() ); - - char szReturnString[128]; - Q_snprintf( szReturnString, sizeof( szReturnString ), "Your player model is: %s\n", pszCurrentModelName ); - - ClientPrint( pHL2Player, HUD_PRINTTALK, szReturnString ); - } - else - { - if ( Q_stristr( szModelName, "models/human") ) - { - pHL2Player->ChangeTeam( TEAM_REBELS ); - } - else - { - pHL2Player->ChangeTeam( TEAM_COMBINE ); - } - } - } - if ( sv_report_client_settings.GetInt() == 1 ) - { - UTIL_LogPrintf( "\"%s\" cl_cmdrate = \"%s\"\n", pHL2Player->GetPlayerName(), engine->GetClientConVarValue( pHL2Player->entindex(), "cl_cmdrate" )); - } - - BaseClass::ClientSettingsChanged( pPlayer ); -#endif - -} - -int CHL2MPRules::PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget ) -{ -#ifndef CLIENT_DLL - // half life multiplay has a simple concept of Player Relationships. - // you are either on another player's team, or you are not. - if ( !pPlayer || !pTarget || !pTarget->IsPlayer() || IsTeamplay() == false ) - return GR_NOTTEAMMATE; - - if ( (*GetTeamID(pPlayer) != '\0') && (*GetTeamID(pTarget) != '\0') && !stricmp( GetTeamID(pPlayer), GetTeamID(pTarget) ) ) - { - return GR_TEAMMATE; - } -#endif - - return GR_NOTTEAMMATE; -} - -const char *CHL2MPRules::GetGameDescription( void ) -{ - if ( IsTeamplay() ) - return "Team Deathmatch"; - - return "Deathmatch"; -} - - -float CHL2MPRules::GetMapRemainingTime() -{ - // if timelimit is disabled, return 0 - if ( mp_timelimit.GetInt() <= 0 ) - return 0; - - // timelimit is in minutes - - float timeleft = (m_flGameStartTime + mp_timelimit.GetInt() * 60.0f ) - gpGlobals->curtime; - - return timeleft; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHL2MPRules::Precache( void ) -{ - CBaseEntity::PrecacheScriptSound( "AlyxEmp.Charge" ); -} - -bool CHL2MPRules::ShouldCollide( int collisionGroup0, int collisionGroup1 ) -{ - if ( collisionGroup0 > collisionGroup1 ) - { - // swap so that lowest is always first - swap(collisionGroup0,collisionGroup1); - } - - if ( (collisionGroup0 == COLLISION_GROUP_PLAYER || collisionGroup0 == COLLISION_GROUP_PLAYER_MOVEMENT) && - collisionGroup1 == COLLISION_GROUP_WEAPON ) - { - return false; - } - - return BaseClass::ShouldCollide( collisionGroup0, collisionGroup1 ); - -} - -bool CHL2MPRules::ClientCommand( CBaseEntity *pEdict, const CCommand &args ) -{ -#ifndef CLIENT_DLL - if( BaseClass::ClientCommand( pEdict, args ) ) - return true; - - - CHL2MP_Player *pPlayer = (CHL2MP_Player *) pEdict; - - if ( pPlayer->ClientCommand( args ) ) - return true; -#endif - - return false; -} - -// shared ammo definition -// JAY: Trying to make a more physical bullet response -#define BULLET_MASS_GRAINS_TO_LB(grains) (0.002285*(grains)/16.0f) -#define BULLET_MASS_GRAINS_TO_KG(grains) lbs2kg(BULLET_MASS_GRAINS_TO_LB(grains)) - -// exaggerate all of the forces, but use real numbers to keep them consistent -#define BULLET_IMPULSE_EXAGGERATION 3.5 -// convert a velocity in ft/sec and a mass in grains to an impulse in kg in/s -#define BULLET_IMPULSE(grains, ftpersec) ((ftpersec)*12*BULLET_MASS_GRAINS_TO_KG(grains)*BULLET_IMPULSE_EXAGGERATION) - - -CAmmoDef *GetAmmoDef() -{ - static CAmmoDef def; - static bool bInitted = false; - - if ( !bInitted ) - { - bInitted = true; - - def.AddAmmoType("AR2", DMG_BULLET, TRACER_LINE_AND_WHIZ, 0, 0, 60, BULLET_IMPULSE(200, 1225), 0 ); - def.AddAmmoType("AR2AltFire", DMG_DISSOLVE, TRACER_NONE, 0, 0, 3, 0, 0 ); - def.AddAmmoType("Pistol", DMG_BULLET, TRACER_LINE_AND_WHIZ, 0, 0, 150, BULLET_IMPULSE(200, 1225), 0 ); - def.AddAmmoType("SMG1", DMG_BULLET, TRACER_LINE_AND_WHIZ, 0, 0, 225, BULLET_IMPULSE(200, 1225), 0 ); - def.AddAmmoType("357", DMG_BULLET, TRACER_LINE_AND_WHIZ, 0, 0, 12, BULLET_IMPULSE(800, 5000), 0 ); - def.AddAmmoType("XBowBolt", DMG_BULLET, TRACER_LINE, 0, 0, 10, BULLET_IMPULSE(800, 8000), 0 ); - def.AddAmmoType("Buckshot", DMG_BULLET | DMG_BUCKSHOT, TRACER_LINE, 0, 0, 30, BULLET_IMPULSE(400, 1200), 0 ); - def.AddAmmoType("RPG_Round", DMG_BURN, TRACER_NONE, 0, 0, 3, 0, 0 ); - def.AddAmmoType("SMG1_Grenade", DMG_BURN, TRACER_NONE, 0, 0, 3, 0, 0 ); - def.AddAmmoType("Grenade", DMG_BURN, TRACER_NONE, 0, 0, 5, 0, 0 ); - def.AddAmmoType("slam", DMG_BURN, TRACER_NONE, 0, 0, 5, 0, 0 ); - } - - return &def; -} - -#ifdef CLIENT_DLL - - ConVar cl_autowepswitch( - "cl_autowepswitch", - "1", - FCVAR_ARCHIVE | FCVAR_USERINFO, - "Automatically switch to picked up weapons (if more powerful)" ); - -#else - -#ifdef DEBUG - - // Handler for the "bot" command. - void Bot_f() - { - // Look at -count. - int count = 1; - count = clamp( count, 1, 16 ); - - int iTeam = TEAM_COMBINE; - - // Look at -frozen. - bool bFrozen = false; - - // Ok, spawn all the bots. - while ( --count >= 0 ) - { - BotPutInServer( bFrozen, iTeam ); - } - } - - - ConCommand cc_Bot( "bot", Bot_f, "Add a bot.", FCVAR_CHEAT ); - -#endif - - bool CHL2MPRules::FShouldSwitchWeapon( CBasePlayer *pPlayer, CBaseCombatWeapon *pWeapon ) - { - if ( pPlayer->GetActiveWeapon() && pPlayer->IsNetClient() ) - { - // Player has an active item, so let's check cl_autowepswitch. - const char *cl_autowepswitch = engine->GetClientConVarValue( engine->IndexOfEdict( pPlayer->edict() ), "cl_autowepswitch" ); - if ( cl_autowepswitch && atoi( cl_autowepswitch ) <= 0 ) - { - return false; - } - } - - return BaseClass::FShouldSwitchWeapon( pPlayer, pWeapon ); - } - -#endif - -#ifndef CLIENT_DLL - -void CHL2MPRules::RestartGame() -{ - // bounds check - if ( mp_timelimit.GetInt() < 0 ) - { - mp_timelimit.SetValue( 0 ); - } - m_flGameStartTime = gpGlobals->curtime; - if ( !IsFinite( m_flGameStartTime.Get() ) ) - { - Warning( "Trying to set a NaN game start time\n" ); - m_flGameStartTime.GetForModify() = 0.0f; - } - - CleanUpMap(); - - // now respawn all players - for (int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CHL2MP_Player *pPlayer = (CHL2MP_Player*) UTIL_PlayerByIndex( i ); - - if ( !pPlayer ) - continue; - - if ( pPlayer->GetActiveWeapon() ) - { - pPlayer->GetActiveWeapon()->Holster(); - } - pPlayer->RemoveAllItems( true ); - respawn( pPlayer, false ); - pPlayer->Reset(); - } - - // Respawn entities (glass, doors, etc..) - - CTeam *pRebels = GetGlobalTeam( TEAM_REBELS ); - CTeam *pCombine = GetGlobalTeam( TEAM_COMBINE ); - - if ( pRebels ) - { - pRebels->SetScore( 0 ); - } - - if ( pCombine ) - { - pCombine->SetScore( 0 ); - } - - m_flIntermissionEndTime = 0; - m_flRestartGameTime = 0.0; - m_bCompleteReset = false; - - IGameEvent * event = gameeventmanager->CreateEvent( "round_start" ); - if ( event ) - { - event->SetInt("fraglimit", 0 ); - event->SetInt( "priority", 6 ); // HLTV event priority, not transmitted - - event->SetString("objective","DEATHMATCH"); - - gameeventmanager->FireEvent( event ); - } -} - -void CHL2MPRules::CleanUpMap() -{ - // Recreate all the map entities from the map data (preserving their indices), - // then remove everything else except the players. - - // Get rid of all entities except players. - CBaseEntity *pCur = gEntList.FirstEnt(); - while ( pCur ) - { - CBaseHL2MPCombatWeapon *pWeapon = dynamic_cast< CBaseHL2MPCombatWeapon* >( pCur ); - // Weapons with owners don't want to be removed.. - if ( pWeapon ) - { - if ( !pWeapon->GetPlayerOwner() ) - { - UTIL_Remove( pCur ); - } - } - // remove entities that has to be restored on roundrestart (breakables etc) - else if ( !FindInList( s_PreserveEnts, pCur->GetClassname() ) ) - { - UTIL_Remove( pCur ); - } - - pCur = gEntList.NextEnt( pCur ); - } - - // Really remove the entities so we can have access to their slots below. - gEntList.CleanupDeleteList(); - - // Cancel all queued events, in case a func_bomb_target fired some delayed outputs that - // could kill respawning CTs - g_EventQueue.Clear(); - - // Now reload the map entities. - class CHL2MPMapEntityFilter : public IMapEntityFilter - { - public: - virtual bool ShouldCreateEntity( const char *pClassname ) - { - // Don't recreate the preserved entities. - if ( !FindInList( s_PreserveEnts, pClassname ) ) - { - return true; - } - else - { - // Increment our iterator since it's not going to call CreateNextEntity for this ent. - if ( m_iIterator != g_MapEntityRefs.InvalidIndex() ) - m_iIterator = g_MapEntityRefs.Next( m_iIterator ); - - return false; - } - } - - - virtual CBaseEntity* CreateNextEntity( const char *pClassname ) - { - if ( m_iIterator == g_MapEntityRefs.InvalidIndex() ) - { - // This shouldn't be possible. When we loaded the map, it should have used - // CCSMapLoadEntityFilter, which should have built the g_MapEntityRefs list - // with the same list of entities we're referring to here. - Assert( false ); - return NULL; - } - else - { - CMapEntityRef &ref = g_MapEntityRefs[m_iIterator]; - m_iIterator = g_MapEntityRefs.Next( m_iIterator ); // Seek to the next entity. - - if ( ref.m_iEdict == -1 || engine->PEntityOfEntIndex( ref.m_iEdict ) ) - { - // Doh! The entity was delete and its slot was reused. - // Just use any old edict slot. This case sucks because we lose the baseline. - return CreateEntityByName( pClassname ); - } - else - { - // Cool, the slot where this entity was is free again (most likely, the entity was - // freed above). Now create an entity with this specific index. - return CreateEntityByName( pClassname, ref.m_iEdict ); - } - } - } - - public: - int m_iIterator; // Iterator into g_MapEntityRefs. - }; - CHL2MPMapEntityFilter filter; - filter.m_iIterator = g_MapEntityRefs.Head(); - - // DO NOT CALL SPAWN ON info_node ENTITIES! - - MapEntity_ParseAllEntities( engine->GetMapEntitiesString(), &filter, true ); -} - -void CHL2MPRules::CheckChatForReadySignal( CHL2MP_Player *pPlayer, const char *chatmsg ) -{ - if( m_bAwaitingReadyRestart && FStrEq( chatmsg, mp_ready_signal.GetString() ) ) - { - if( !pPlayer->IsReady() ) - { - pPlayer->SetReady( true ); - } - } -} - -void CHL2MPRules::CheckRestartGame( void ) -{ - // Restart the game if specified by the server - int iRestartDelay = mp_restartgame.GetInt(); - - if ( iRestartDelay > 0 ) - { - if ( iRestartDelay > 60 ) - iRestartDelay = 60; - - - // let the players know - char strRestartDelay[64]; - Q_snprintf( strRestartDelay, sizeof( strRestartDelay ), "%d", iRestartDelay ); - UTIL_ClientPrintAll( HUD_PRINTCENTER, "Game will restart in %s1 %s2", strRestartDelay, iRestartDelay == 1 ? "SECOND" : "SECONDS" ); - UTIL_ClientPrintAll( HUD_PRINTCONSOLE, "Game will restart in %s1 %s2", strRestartDelay, iRestartDelay == 1 ? "SECOND" : "SECONDS" ); - - m_flRestartGameTime = gpGlobals->curtime + iRestartDelay; - m_bCompleteReset = true; - mp_restartgame.SetValue( 0 ); - } - - if( mp_readyrestart.GetBool() ) - { - m_bAwaitingReadyRestart = true; - m_bHeardAllPlayersReady = false; - - - const char *pszReadyString = mp_ready_signal.GetString(); - - - // Don't let them put anything malicious in there - if( pszReadyString == NULL || Q_strlen(pszReadyString) > 16 ) - { - pszReadyString = "ready"; - } - - IGameEvent *event = gameeventmanager->CreateEvent( "hl2mp_ready_restart" ); - if ( event ) - gameeventmanager->FireEvent( event ); - - mp_readyrestart.SetValue( 0 ); - - // cancel any restart round in progress - m_flRestartGameTime = -1; - } -} - -void CHL2MPRules::CheckAllPlayersReady( void ) -{ - for (int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CHL2MP_Player *pPlayer = (CHL2MP_Player*) UTIL_PlayerByIndex( i ); - - if ( !pPlayer ) - continue; - if ( !pPlayer->IsReady() ) - return; - } - m_bHeardAllPlayersReady = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const char *CHL2MPRules::GetChatFormat( bool bTeamOnly, CBasePlayer *pPlayer ) -{ - if ( !pPlayer ) // dedicated server output - { - return NULL; - } - - const char *pszFormat = NULL; - - // team only - if ( bTeamOnly == TRUE ) - { - if ( pPlayer->GetTeamNumber() == TEAM_SPECTATOR ) - { - pszFormat = "HL2MP_Chat_Spec"; - } - else - { - const char *chatLocation = GetChatLocation( bTeamOnly, pPlayer ); - if ( chatLocation && *chatLocation ) - { - pszFormat = "HL2MP_Chat_Team_Loc"; - } - else - { - pszFormat = "HL2MP_Chat_Team"; - } - } - } - // everyone - else - { - if ( pPlayer->GetTeamNumber() != TEAM_SPECTATOR ) - { - pszFormat = "HL2MP_Chat_All"; - } - else - { - pszFormat = "HL2MP_Chat_AllSpec"; - } - } - - return pszFormat; -} - -#endif diff --git a/game/shared/hl2mp/hl2mp_gamerules.h b/game/shared/hl2mp/hl2mp_gamerules.h deleted file mode 100644 index 8f2052214..000000000 --- a/game/shared/hl2mp/hl2mp_gamerules.h +++ /dev/null @@ -1,168 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef HL2MP_GAMERULES_H -#define HL2MP_GAMERULES_H -#pragma once - -#include "gamerules.h" -#include "teamplay_gamerules.h" -#include "gamevars_shared.h" - -#ifndef CLIENT_DLL -#include "hl2mp_player.h" -#endif - -#define VEC_CROUCH_TRACE_MIN HL2MPRules()->GetHL2MPViewVectors()->m_vCrouchTraceMin -#define VEC_CROUCH_TRACE_MAX HL2MPRules()->GetHL2MPViewVectors()->m_vCrouchTraceMax - -enum -{ - TEAM_COMBINE = 2, - TEAM_REBELS, -}; - - -#ifdef CLIENT_DLL - #define CHL2MPRules C_HL2MPRules - #define CHL2MPGameRulesProxy C_HL2MPGameRulesProxy -#endif - -class CHL2MPGameRulesProxy : public CGameRulesProxy -{ -public: - DECLARE_CLASS( CHL2MPGameRulesProxy, CGameRulesProxy ); - DECLARE_NETWORKCLASS(); -}; - -class HL2MPViewVectors : public CViewVectors -{ -public: - HL2MPViewVectors( - Vector vView, - Vector vHullMin, - Vector vHullMax, - Vector vDuckHullMin, - Vector vDuckHullMax, - Vector vDuckView, - Vector vObsHullMin, - Vector vObsHullMax, - Vector vDeadViewHeight, - Vector vCrouchTraceMin, - Vector vCrouchTraceMax ) : - CViewVectors( - vView, - vHullMin, - vHullMax, - vDuckHullMin, - vDuckHullMax, - vDuckView, - vObsHullMin, - vObsHullMax, - vDeadViewHeight ) - { - m_vCrouchTraceMin = vCrouchTraceMin; - m_vCrouchTraceMax = vCrouchTraceMax; - } - - Vector m_vCrouchTraceMin; - Vector m_vCrouchTraceMax; -}; - -class CHL2MPRules : public CTeamplayRules -{ -public: - DECLARE_CLASS( CHL2MPRules, CTeamplayRules ); - -#ifdef CLIENT_DLL - - DECLARE_CLIENTCLASS_NOBASE(); // This makes datatables able to access our private vars. - -#else - - DECLARE_SERVERCLASS_NOBASE(); // This makes datatables able to access our private vars. -#endif - - CHL2MPRules(); - virtual ~CHL2MPRules(); - - virtual void Precache( void ); - virtual bool ShouldCollide( int collisionGroup0, int collisionGroup1 ); - virtual bool ClientCommand( CBaseEntity *pEdict, const CCommand &args ); - - virtual float FlWeaponRespawnTime( CBaseCombatWeapon *pWeapon ); - virtual float FlWeaponTryRespawn( CBaseCombatWeapon *pWeapon ); - virtual Vector VecWeaponRespawnSpot( CBaseCombatWeapon *pWeapon ); - virtual int WeaponShouldRespawn( CBaseCombatWeapon *pWeapon ); - virtual void Think( void ); - virtual void CreateStandardEntities( void ); - virtual void ClientSettingsChanged( CBasePlayer *pPlayer ); - virtual int PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget ); - virtual void GoToIntermission( void ); - virtual void DeathNotice( CBasePlayer *pVictim, const CTakeDamageInfo &info ); - virtual const char *GetGameDescription( void ); - // derive this function if you mod uses encrypted weapon info files - virtual const unsigned char *GetEncryptionKey( void ) { return (unsigned char *)"x9Ke0BY7"; } - virtual const CViewVectors* GetViewVectors() const; - const HL2MPViewVectors* GetHL2MPViewVectors() const; - - float GetMapRemainingTime(); - void CleanUpMap(); - void CheckRestartGame(); - void RestartGame(); - -#ifndef CLIENT_DLL - virtual Vector VecItemRespawnSpot( CItem *pItem ); - virtual QAngle VecItemRespawnAngles( CItem *pItem ); - virtual float FlItemRespawnTime( CItem *pItem ); - virtual bool CanHavePlayerItem( CBasePlayer *pPlayer, CBaseCombatWeapon *pItem ); - virtual bool FShouldSwitchWeapon( CBasePlayer *pPlayer, CBaseCombatWeapon *pWeapon ); - - void AddLevelDesignerPlacedObject( CBaseEntity *pEntity ); - void RemoveLevelDesignerPlacedObject( CBaseEntity *pEntity ); - void ManageObjectRelocation( void ); - void CheckChatForReadySignal( CHL2MP_Player *pPlayer, const char *chatmsg ); - const char *GetChatFormat( bool bTeamOnly, CBasePlayer *pPlayer ); - -#endif - virtual void ClientDisconnected( edict_t *pClient ); - - bool CheckGameOver( void ); - bool IsIntermission( void ); - - void PlayerKilled( CBasePlayer *pVictim, const CTakeDamageInfo &info ); - - - bool IsTeamplay( void ) { return m_bTeamPlayEnabled; } - void CheckAllPlayersReady( void ); - -private: - - CNetworkVar( bool, m_bTeamPlayEnabled ); - CNetworkVar( float, m_flGameStartTime ); - CUtlVector m_hRespawnableItemsAndWeapons; - float m_tmNextPeriodicThink; - float m_flRestartGameTime; - bool m_bCompleteReset; - bool m_bAwaitingReadyRestart; - bool m_bHeardAllPlayersReady; - - -}; - -inline CHL2MPRules* HL2MPRules() -{ - return static_cast(g_pGameRules); -} - -#endif //HL2MP_GAMERULES_H diff --git a/game/shared/hl2mp/hl2mp_player_shared.cpp b/game/shared/hl2mp/hl2mp_player_shared.cpp deleted file mode 100644 index a6ec6cb6c..000000000 --- a/game/shared/hl2mp/hl2mp_player_shared.cpp +++ /dev/null @@ -1,573 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" - -#ifdef CLIENT_DLL -#include "c_hl2mp_player.h" -#include "prediction.h" -#define CRecipientFilter C_RecipientFilter -#else -#include "hl2mp_player.h" -#endif - -#include "engine/IEngineSound.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" - -extern ConVar sv_footsteps; - -const char *g_ppszPlayerSoundPrefixNames[PLAYER_SOUNDS_MAX] = -{ - "NPC_Citizen", - "NPC_CombineS", - "NPC_MetroPolice", -}; - -const char *CHL2MP_Player::GetPlayerModelSoundPrefix( void ) -{ - return g_ppszPlayerSoundPrefixNames[m_iPlayerSoundType]; -} - -void CHL2MP_Player::PrecacheFootStepSounds( void ) -{ - int iFootstepSounds = ARRAYSIZE( g_ppszPlayerSoundPrefixNames ); - int i; - - for ( i = 0; i < iFootstepSounds; ++i ) - { - char szFootStepName[128]; - - Q_snprintf( szFootStepName, sizeof( szFootStepName ), "%s.RunFootstepLeft", g_ppszPlayerSoundPrefixNames[i] ); - PrecacheScriptSound( szFootStepName ); - - Q_snprintf( szFootStepName, sizeof( szFootStepName ), "%s.RunFootstepRight", g_ppszPlayerSoundPrefixNames[i] ); - PrecacheScriptSound( szFootStepName ); - } -} - -//----------------------------------------------------------------------------- -// Consider the weapon's built-in accuracy, this character's proficiency with -// the weapon, and the status of the target. Use this information to determine -// how accurately to shoot at the target. -//----------------------------------------------------------------------------- -Vector CHL2MP_Player::GetAttackSpread( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget ) -{ - if ( pWeapon ) - return pWeapon->GetBulletSpread( WEAPON_PROFICIENCY_PERFECT ); - - return VECTOR_CONE_15DEGREES; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : step - -// fvol - -// force - force sound to play -//----------------------------------------------------------------------------- -void CHL2MP_Player::PlayStepSound( Vector &vecOrigin, surfacedata_t *psurface, float fvol, bool force ) -{ - if ( gpGlobals->maxClients > 1 && !sv_footsteps.GetFloat() ) - return; - -#if defined( CLIENT_DLL ) - // during prediction play footstep sounds only once - if ( !prediction->IsFirstTimePredicted() ) - return; -#endif - - if ( GetFlags() & FL_DUCKING ) - return; - - m_Local.m_nStepside = !m_Local.m_nStepside; - - char szStepSound[128]; - - if ( m_Local.m_nStepside ) - { - Q_snprintf( szStepSound, sizeof( szStepSound ), "%s.RunFootstepLeft", g_ppszPlayerSoundPrefixNames[m_iPlayerSoundType] ); - } - else - { - Q_snprintf( szStepSound, sizeof( szStepSound ), "%s.RunFootstepRight", g_ppszPlayerSoundPrefixNames[m_iPlayerSoundType] ); - } - - CSoundParameters params; - if ( GetParametersForSound( szStepSound, params, NULL ) == false ) - return; - - CRecipientFilter filter; - filter.AddRecipientsByPAS( vecOrigin ); - -#ifndef CLIENT_DLL - // im MP, server removed all players in origins PVS, these players - // generate the footsteps clientside - if ( gpGlobals->maxClients > 1 ) - filter.RemoveRecipientsByPVS( vecOrigin ); -#endif - - EmitSound_t ep; - ep.m_nChannel = CHAN_BODY; - ep.m_pSoundName = params.soundname; - ep.m_flVolume = fvol; - ep.m_SoundLevel = params.soundlevel; - ep.m_nFlags = 0; - ep.m_nPitch = params.pitch; - ep.m_pOrigin = &vecOrigin; - - EmitSound( filter, entindex(), ep ); -} - - -//========================== -// ANIMATION CODE -//========================== - - -// Below this many degrees, slow down turning rate linearly -#define FADE_TURN_DEGREES 45.0f -// After this, need to start turning feet -#define MAX_TORSO_ANGLE 90.0f -// Below this amount, don't play a turning animation/perform IK -#define MIN_TURN_ANGLE_REQUIRING_TURN_ANIMATION 15.0f - -static ConVar tf2_feetyawrunscale( "tf2_feetyawrunscale", "2", FCVAR_REPLICATED, "Multiplier on tf2_feetyawrate to allow turning faster when running." ); -extern ConVar sv_backspeed; -extern ConVar mp_feetyawrate; -extern ConVar mp_facefronttime; -extern ConVar mp_ik; - -CPlayerAnimState::CPlayerAnimState( CHL2MP_Player *outer ) - : m_pOuter( outer ) -{ - m_flGaitYaw = 0.0f; - m_flGoalFeetYaw = 0.0f; - m_flCurrentFeetYaw = 0.0f; - m_flCurrentTorsoYaw = 0.0f; - m_flLastYaw = 0.0f; - m_flLastTurnTime = 0.0f; - m_flTurnCorrectionTime = 0.0f; -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPlayerAnimState::Update() -{ - m_angRender = GetOuter()->GetLocalAngles(); - - ComputePoseParam_BodyYaw(); - ComputePoseParam_BodyPitch(GetOuter()->GetModelPtr()); - ComputePoseParam_BodyLookYaw(); - - ComputePlaybackRate(); - -#ifdef CLIENT_DLL - GetOuter()->UpdateLookAt(); -#endif - -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPlayerAnimState::ComputePlaybackRate() -{ - // Determine ideal playback rate - Vector vel; - GetOuterAbsVelocity( vel ); - - float speed = vel.Length2D(); - - bool isMoving = ( speed > 0.5f ) ? true : false; - - float maxspeed = GetOuter()->GetSequenceGroundSpeed( GetOuter()->GetSequence() ); - - if ( isMoving && ( maxspeed > 0.0f ) ) - { - float flFactor = 1.0f; - - // Note this gets set back to 1.0 if sequence changes due to ResetSequenceInfo below - GetOuter()->SetPlaybackRate( ( speed * flFactor ) / maxspeed ); - - // BUG BUG: - // This stuff really should be m_flPlaybackRate = speed / m_flGroundSpeed - } - else - { - GetOuter()->SetPlaybackRate( 1.0f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CBasePlayer -//----------------------------------------------------------------------------- -CHL2MP_Player *CPlayerAnimState::GetOuter() -{ - return m_pOuter; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : dt - -//----------------------------------------------------------------------------- -void CPlayerAnimState::EstimateYaw( void ) -{ - float dt = gpGlobals->frametime; - - if ( !dt ) - { - return; - } - - Vector est_velocity; - QAngle angles; - - GetOuterAbsVelocity( est_velocity ); - - angles = GetOuter()->GetLocalAngles(); - - if ( est_velocity[1] == 0 && est_velocity[0] == 0 ) - { - float flYawDiff = angles[YAW] - m_flGaitYaw; - flYawDiff = flYawDiff - (int)(flYawDiff / 360) * 360; - if (flYawDiff > 180) - flYawDiff -= 360; - if (flYawDiff < -180) - flYawDiff += 360; - - if (dt < 0.25) - flYawDiff *= dt * 4; - else - flYawDiff *= dt; - - m_flGaitYaw += flYawDiff; - m_flGaitYaw = m_flGaitYaw - (int)(m_flGaitYaw / 360) * 360; - } - else - { - m_flGaitYaw = (atan2(est_velocity[1], est_velocity[0]) * 180 / M_PI); - - if (m_flGaitYaw > 180) - m_flGaitYaw = 180; - else if (m_flGaitYaw < -180) - m_flGaitYaw = -180; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Override for backpeddling -// Input : dt - -//----------------------------------------------------------------------------- -void CPlayerAnimState::ComputePoseParam_BodyYaw( void ) -{ - int iYaw = GetOuter()->LookupPoseParameter( "move_yaw" ); - if ( iYaw < 0 ) - return; - - // view direction relative to movement - float flYaw; - - EstimateYaw(); - - QAngle angles = GetOuter()->GetLocalAngles(); - float ang = angles[ YAW ]; - if ( ang > 180.0f ) - { - ang -= 360.0f; - } - else if ( ang < -180.0f ) - { - ang += 360.0f; - } - - // calc side to side turning - flYaw = ang - m_flGaitYaw; - // Invert for mapping into 8way blend - flYaw = -flYaw; - flYaw = flYaw - (int)(flYaw / 360) * 360; - - if (flYaw < -180) - { - flYaw = flYaw + 360; - } - else if (flYaw > 180) - { - flYaw = flYaw - 360; - } - - GetOuter()->SetPoseParameter( iYaw, flYaw ); - -#ifndef CLIENT_DLL - //Adrian: Make the model's angle match the legs so the hitboxes match on both sides. - GetOuter()->SetLocalAngles( QAngle( GetOuter()->GetAnimEyeAngles().x, m_flCurrentFeetYaw, 0 ) ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPlayerAnimState::ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr ) -{ - // Get pitch from v_angle - float flPitch = GetOuter()->GetLocalAngles()[ PITCH ]; - - if ( flPitch > 180.0f ) - { - flPitch -= 360.0f; - } - flPitch = clamp( flPitch, -90, 90 ); - - QAngle absangles = GetOuter()->GetAbsAngles(); - absangles.x = 0.0f; - m_angRender = absangles; - - // See if we have a blender for pitch - GetOuter()->SetPoseParameter( pStudioHdr, "aim_pitch", flPitch ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : goal - -// maxrate - -// dt - -// current - -// Output : int -//----------------------------------------------------------------------------- -int CPlayerAnimState::ConvergeAngles( float goal,float maxrate, float dt, float& current ) -{ - int direction = TURN_NONE; - - float anglediff = goal - current; - float anglediffabs = fabs( anglediff ); - - anglediff = AngleNormalize( anglediff ); - - float scale = 1.0f; - if ( anglediffabs <= FADE_TURN_DEGREES ) - { - scale = anglediffabs / FADE_TURN_DEGREES; - // Always do at least a bit of the turn ( 1% ) - scale = clamp( scale, 0.01f, 1.0f ); - } - - float maxmove = maxrate * dt * scale; - - if ( fabs( anglediff ) < maxmove ) - { - current = goal; - } - else - { - if ( anglediff > 0 ) - { - current += maxmove; - direction = TURN_LEFT; - } - else - { - current -= maxmove; - direction = TURN_RIGHT; - } - } - - current = AngleNormalize( current ); - - return direction; -} - -void CPlayerAnimState::ComputePoseParam_BodyLookYaw( void ) -{ - QAngle absangles = GetOuter()->GetAbsAngles(); - absangles.y = AngleNormalize( absangles.y ); - m_angRender = absangles; - - // See if we even have a blender for pitch - int upper_body_yaw = GetOuter()->LookupPoseParameter( "aim_yaw" ); - if ( upper_body_yaw < 0 ) - { - return; - } - - // Assume upper and lower bodies are aligned and that we're not turning - float flGoalTorsoYaw = 0.0f; - int turning = TURN_NONE; - float turnrate = 360.0f; - - Vector vel; - - GetOuterAbsVelocity( vel ); - - bool isMoving = ( vel.Length() > 1.0f ) ? true : false; - - if ( !isMoving ) - { - // Just stopped moving, try and clamp feet - if ( m_flLastTurnTime <= 0.0f ) - { - m_flLastTurnTime = gpGlobals->curtime; - m_flLastYaw = GetOuter()->GetAnimEyeAngles().y; - // Snap feet to be perfectly aligned with torso/eyes - m_flGoalFeetYaw = GetOuter()->GetAnimEyeAngles().y; - m_flCurrentFeetYaw = m_flGoalFeetYaw; - m_nTurningInPlace = TURN_NONE; - } - - // If rotating in place, update stasis timer - if ( m_flLastYaw != GetOuter()->GetAnimEyeAngles().y ) - { - m_flLastTurnTime = gpGlobals->curtime; - m_flLastYaw = GetOuter()->GetAnimEyeAngles().y; - } - - if ( m_flGoalFeetYaw != m_flCurrentFeetYaw ) - { - m_flLastTurnTime = gpGlobals->curtime; - } - - turning = ConvergeAngles( m_flGoalFeetYaw, turnrate, gpGlobals->frametime, m_flCurrentFeetYaw ); - - QAngle eyeAngles = GetOuter()->GetAnimEyeAngles(); - QAngle vAngle = GetOuter()->GetLocalAngles(); - - // See how far off current feetyaw is from true yaw - float yawdelta = GetOuter()->GetAnimEyeAngles().y - m_flCurrentFeetYaw; - yawdelta = AngleNormalize( yawdelta ); - - bool rotated_too_far = false; - - float yawmagnitude = fabs( yawdelta ); - - // If too far, then need to turn in place - if ( yawmagnitude > 45 ) - { - rotated_too_far = true; - } - - // Standing still for a while, rotate feet around to face forward - // Or rotated too far - // FIXME: Play an in place turning animation - if ( rotated_too_far || - ( gpGlobals->curtime > m_flLastTurnTime + mp_facefronttime.GetFloat() ) ) - { - m_flGoalFeetYaw = GetOuter()->GetAnimEyeAngles().y; - m_flLastTurnTime = gpGlobals->curtime; - - /* float yd = m_flCurrentFeetYaw - m_flGoalFeetYaw; - if ( yd > 0 ) - { - m_nTurningInPlace = TURN_RIGHT; - } - else if ( yd < 0 ) - { - m_nTurningInPlace = TURN_LEFT; - } - else - { - m_nTurningInPlace = TURN_NONE; - } - - turning = ConvergeAngles( m_flGoalFeetYaw, turnrate, gpGlobals->frametime, m_flCurrentFeetYaw ); - yawdelta = GetOuter()->GetAnimEyeAngles().y - m_flCurrentFeetYaw;*/ - - } - - // Snap upper body into position since the delta is already smoothed for the feet - flGoalTorsoYaw = yawdelta; - m_flCurrentTorsoYaw = flGoalTorsoYaw; - } - else - { - m_flLastTurnTime = 0.0f; - m_nTurningInPlace = TURN_NONE; - m_flCurrentFeetYaw = m_flGoalFeetYaw = GetOuter()->GetAnimEyeAngles().y; - flGoalTorsoYaw = 0.0f; - m_flCurrentTorsoYaw = GetOuter()->GetAnimEyeAngles().y - m_flCurrentFeetYaw; - } - - - if ( turning == TURN_NONE ) - { - m_nTurningInPlace = turning; - } - - if ( m_nTurningInPlace != TURN_NONE ) - { - // If we're close to finishing the turn, then turn off the turning animation - if ( fabs( m_flCurrentFeetYaw - m_flGoalFeetYaw ) < MIN_TURN_ANGLE_REQUIRING_TURN_ANIMATION ) - { - m_nTurningInPlace = TURN_NONE; - } - } - - // Rotate entire body into position - absangles = GetOuter()->GetAbsAngles(); - absangles.y = m_flCurrentFeetYaw; - m_angRender = absangles; - - GetOuter()->SetPoseParameter( upper_body_yaw, clamp( m_flCurrentTorsoYaw, -60.0f, 60.0f ) ); - - /* - // FIXME: Adrian, what is this? - int body_yaw = GetOuter()->LookupPoseParameter( "body_yaw" ); - - if ( body_yaw >= 0 ) - { - GetOuter()->SetPoseParameter( body_yaw, 30 ); - } - */ - -} - - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : activity - -// Output : Activity -//----------------------------------------------------------------------------- -Activity CPlayerAnimState::BodyYawTranslateActivity( Activity activity ) -{ - // Not even standing still, sigh - if ( activity != ACT_IDLE ) - return activity; - - // Not turning - switch ( m_nTurningInPlace ) - { - default: - case TURN_NONE: - return activity; - /* - case TURN_RIGHT: - return ACT_TURNRIGHT45; - case TURN_LEFT: - return ACT_TURNLEFT45; - */ - case TURN_RIGHT: - case TURN_LEFT: - return mp_ik.GetBool() ? ACT_TURN : activity; - } - - Assert( 0 ); - return activity; -} - -const QAngle& CPlayerAnimState::GetRenderAngles() -{ - return m_angRender; -} - - -void CPlayerAnimState::GetOuterAbsVelocity( Vector& vel ) -{ -#if defined( CLIENT_DLL ) - GetOuter()->EstimateAbsVelocity( vel ); -#else - vel = GetOuter()->GetAbsVelocity(); -#endif -} diff --git a/game/shared/hl2mp/hl2mp_player_shared.h b/game/shared/hl2mp/hl2mp_player_shared.h deleted file mode 100644 index b0e18760c..000000000 --- a/game/shared/hl2mp/hl2mp_player_shared.h +++ /dev/null @@ -1,97 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef HL2MP_PLAYER_SHARED_H -#define HL2MP_PLAYER_SHARED_H -#pragma once - -#define HL2MP_PUSHAWAY_THINK_INTERVAL (1.0f / 20.0f) -#include "studio.h" - - -enum -{ - PLAYER_SOUNDS_CITIZEN = 0, - PLAYER_SOUNDS_COMBINESOLDIER, - PLAYER_SOUNDS_METROPOLICE, - PLAYER_SOUNDS_MAX, -}; - -enum HL2MPPlayerState -{ - // Happily running around in the game. - STATE_ACTIVE=0, - STATE_OBSERVER_MODE, // Noclipping around, watching players, etc. - NUM_PLAYER_STATES -}; - - -#if defined( CLIENT_DLL ) -#define CHL2MP_Player C_HL2MP_Player -#endif - -class CPlayerAnimState -{ -public: - enum - { - TURN_NONE = 0, - TURN_LEFT, - TURN_RIGHT - }; - - CPlayerAnimState( CHL2MP_Player *outer ); - - Activity BodyYawTranslateActivity( Activity activity ); - - void Update(); - - const QAngle& GetRenderAngles(); - - void GetPoseParameters( CStudioHdr *pStudioHdr, float poseParameter[MAXSTUDIOPOSEPARAM] ); - - CHL2MP_Player *GetOuter(); - -private: - void GetOuterAbsVelocity( Vector& vel ); - - int ConvergeAngles( float goal,float maxrate, float dt, float& current ); - - void EstimateYaw( void ); - void ComputePoseParam_BodyYaw( void ); - void ComputePoseParam_BodyPitch( CStudioHdr *pStudioHdr ); - void ComputePoseParam_BodyLookYaw( void ); - - void ComputePlaybackRate(); - - CHL2MP_Player *m_pOuter; - - float m_flGaitYaw; - float m_flStoredCycle; - - // The following variables are used for tweaking the yaw of the upper body when standing still and - // making sure that it smoothly blends in and out once the player starts moving - // Direction feet were facing when we stopped moving - float m_flGoalFeetYaw; - float m_flCurrentFeetYaw; - - float m_flCurrentTorsoYaw; - - // To check if they are rotating in place - float m_flLastYaw; - // Time when we stopped moving - float m_flLastTurnTime; - - // One of the above enums - int m_nTurningInPlace; - - QAngle m_angRender; - - float m_flTurnCorrectionTime; -}; - -#endif //HL2MP_PLAYER_SHARED_h diff --git a/game/shared/hl2mp/hl2mp_weapon_parse.cpp b/game/shared/hl2mp/hl2mp_weapon_parse.cpp deleted file mode 100644 index 8edccd98d..000000000 --- a/game/shared/hl2mp/hl2mp_weapon_parse.cpp +++ /dev/null @@ -1,32 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include -#include "hl2mp_weapon_parse.h" -#include "ammodef.h" - -FileWeaponInfo_t* CreateWeaponInfo() -{ - return new CHL2MPSWeaponInfo; -} - - - -CHL2MPSWeaponInfo::CHL2MPSWeaponInfo() -{ - m_iPlayerDamage = 0; -} - - -void CHL2MPSWeaponInfo::Parse( KeyValues *pKeyValuesData, const char *szWeaponName ) -{ - BaseClass::Parse( pKeyValuesData, szWeaponName ); - - m_iPlayerDamage = pKeyValuesData->GetInt( "damage", 0 ); -} - - diff --git a/game/shared/hl2mp/hl2mp_weapon_parse.h b/game/shared/hl2mp/hl2mp_weapon_parse.h deleted file mode 100644 index e5c9124d1..000000000 --- a/game/shared/hl2mp/hl2mp_weapon_parse.h +++ /dev/null @@ -1,35 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef HL2MP_WEAPON_PARSE_H -#define HL2MP_WEAPON_PARSE_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "weapon_parse.h" -#include "networkvar.h" - - -//-------------------------------------------------------------------------------------------------------- -class CHL2MPSWeaponInfo : public FileWeaponInfo_t -{ -public: - DECLARE_CLASS_GAMEROOT( CHL2MPSWeaponInfo, FileWeaponInfo_t ); - - CHL2MPSWeaponInfo(); - - virtual void Parse( ::KeyValues *pKeyValuesData, const char *szWeaponName ); - - -public: - - int m_iPlayerDamage; -}; - - -#endif // HL2MP_WEAPON_PARSE_H diff --git a/game/shared/hl2mp/weapon_357.cpp b/game/shared/hl2mp/weapon_357.cpp deleted file mode 100644 index df824ce2a..000000000 --- a/game/shared/hl2mp/weapon_357.cpp +++ /dev/null @@ -1,154 +0,0 @@ - -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" -#include "in_buttons.h" - -#ifdef CLIENT_DLL - #include "c_hl2mp_player.h" -#else - #include "hl2mp_player.h" -#endif - -#include "weapon_hl2mpbasehlmpcombatweapon.h" - -#ifdef CLIENT_DLL -#define CWeapon357 C_Weapon357 -#endif - -//----------------------------------------------------------------------------- -// CWeapon357 -//----------------------------------------------------------------------------- - -class CWeapon357 : public CBaseHL2MPCombatWeapon -{ - DECLARE_CLASS( CWeapon357, CBaseHL2MPCombatWeapon ); -public: - - CWeapon357( void ); - - void PrimaryAttack( void ); - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - -#ifndef CLIENT_DLL - DECLARE_ACTTABLE(); -#endif - -private: - - CWeapon357( const CWeapon357 & ); -}; - -IMPLEMENT_NETWORKCLASS_ALIASED( Weapon357, DT_Weapon357 ) - -BEGIN_NETWORK_TABLE( CWeapon357, DT_Weapon357 ) -END_NETWORK_TABLE() - -BEGIN_PREDICTION_DATA( CWeapon357 ) -END_PREDICTION_DATA() - -LINK_ENTITY_TO_CLASS( weapon_357, CWeapon357 ); -PRECACHE_WEAPON_REGISTER( weapon_357 ); - - -#ifndef CLIENT_DLL -acttable_t CWeapon357::m_acttable[] = -{ - { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_PISTOL, false }, - { ACT_HL2MP_RUN, ACT_HL2MP_RUN_PISTOL, false }, - { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_PISTOL, false }, - { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_PISTOL, false }, - { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_PISTOL, false }, - { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_PISTOL, false }, - { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_PISTOL, false }, - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_PISTOL, false }, -}; - - - -IMPLEMENT_ACTTABLE( CWeapon357 ); - -#endif - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -CWeapon357::CWeapon357( void ) -{ - m_bReloadsSingly = false; - m_bFiresUnderwater = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeapon357::PrimaryAttack( void ) -{ - // Only the player fires this way so we can cast - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if ( !pPlayer ) - { - return; - } - - if ( m_iClip1 <= 0 ) - { - if ( !m_bFireOnEmpty ) - { - Reload(); - } - else - { - WeaponSound( EMPTY ); - m_flNextPrimaryAttack = 0.15; - } - - return; - } - - WeaponSound( SINGLE ); - pPlayer->DoMuzzleFlash(); - - SendWeaponAnim( ACT_VM_PRIMARYATTACK ); - pPlayer->SetAnimation( PLAYER_ATTACK1 ); - - m_flNextPrimaryAttack = gpGlobals->curtime + 0.75; - m_flNextSecondaryAttack = gpGlobals->curtime + 0.75; - - m_iClip1--; - - Vector vecSrc = pPlayer->Weapon_ShootPosition(); - Vector vecAiming = pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES ); - - FireBulletsInfo_t info( 1, vecSrc, vecAiming, vec3_origin, MAX_TRACE_LENGTH, m_iPrimaryAmmoType ); - info.m_pAttacker = pPlayer; - - // Fire the bullets, and force the first shot to be perfectly accuracy - pPlayer->FireBullets( info ); - - //Disorient the player - QAngle angles = pPlayer->GetLocalAngles(); - - angles.x += random->RandomInt( -1, 1 ); - angles.y += random->RandomInt( -1, 1 ); - angles.z = 0; - -#ifndef CLIENT_DLL - pPlayer->SnapEyeAngles( angles ); -#endif - - pPlayer->ViewPunch( QAngle( -8, random->RandomFloat( -2, 2 ), 0 ) ); - - if ( !m_iClip1 && pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 ) - { - // HEV suit - indicate out of ammo condition - pPlayer->SetSuitUpdate( "!HEV_AMO0", FALSE, 0 ); - } -} diff --git a/game/shared/hl2mp/weapon_ar2.cpp b/game/shared/hl2mp/weapon_ar2.cpp deleted file mode 100644 index 29678869d..000000000 --- a/game/shared/hl2mp/weapon_ar2.cpp +++ /dev/null @@ -1,312 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" - -#ifdef CLIENT_DLL - #include "c_hl2mp_player.h" - #include "c_te_effect_dispatch.h" -#else - #include "hl2mp_player.h" - #include "te_effect_dispatch.h" - #include "prop_combine_ball.h" -#endif - -#include "weapon_ar2.h" -#include "effect_dispatch_data.h" - - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#ifndef CLIENT_DLL -ConVar sk_weapon_ar2_alt_fire_radius( "sk_weapon_ar2_alt_fire_radius", "10" ); -ConVar sk_weapon_ar2_alt_fire_duration( "sk_weapon_ar2_alt_fire_duration", "4" ); -ConVar sk_weapon_ar2_alt_fire_mass( "sk_weapon_ar2_alt_fire_mass", "150" ); -#endif - -//========================================================= -//========================================================= - - -IMPLEMENT_NETWORKCLASS_ALIASED( WeaponAR2, DT_WeaponAR2 ) - -BEGIN_NETWORK_TABLE( CWeaponAR2, DT_WeaponAR2 ) -END_NETWORK_TABLE() - -BEGIN_PREDICTION_DATA( CWeaponAR2 ) -END_PREDICTION_DATA() - -LINK_ENTITY_TO_CLASS( weapon_ar2, CWeaponAR2 ); -PRECACHE_WEAPON_REGISTER(weapon_ar2); - - -#ifndef CLIENT_DLL - -acttable_t CWeaponAR2::m_acttable[] = -{ - { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_AR2, false }, - { ACT_HL2MP_RUN, ACT_HL2MP_RUN_AR2, false }, - { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_AR2, false }, - { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_AR2, false }, - { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_AR2, false }, - { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_AR2, false }, - { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_AR2, false }, - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_AR2, false }, -}; - -IMPLEMENT_ACTTABLE(CWeaponAR2); - -#endif - -CWeaponAR2::CWeaponAR2( ) -{ - m_fMinRange1 = 65; - m_fMaxRange1 = 2048; - - m_fMinRange2 = 256; - m_fMaxRange2 = 1024; - - m_nShotsFired = 0; - m_nVentPose = -1; -} - -void CWeaponAR2::Precache( void ) -{ - BaseClass::Precache(); - -#ifndef CLIENT_DLL - - UTIL_PrecacheOther( "prop_combine_ball" ); - UTIL_PrecacheOther( "env_entity_dissolver" ); -#endif - -} - -//----------------------------------------------------------------------------- -// Purpose: Handle grenade detonate in-air (even when no ammo is left) -//----------------------------------------------------------------------------- -void CWeaponAR2::ItemPostFrame( void ) -{ - // See if we need to fire off our secondary round - if ( m_bShotDelayed && gpGlobals->curtime > m_flDelayedFire ) - { - DelayedAttack(); - } - - // Update our pose parameter for the vents - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner ) - { - CBaseViewModel *pVM = pOwner->GetViewModel(); - - if ( pVM ) - { - if ( m_nVentPose == -1 ) - { - m_nVentPose = pVM->LookupPoseParameter( "VentPoses" ); - } - - float flVentPose = RemapValClamped( m_nShotsFired, 0, 5, 0.0f, 1.0f ); - pVM->SetPoseParameter( m_nVentPose, flVentPose ); - } - } - - BaseClass::ItemPostFrame(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Activity -//----------------------------------------------------------------------------- -Activity CWeaponAR2::GetPrimaryAttackActivity( void ) -{ - if ( m_nShotsFired < 2 ) - return ACT_VM_PRIMARYATTACK; - - if ( m_nShotsFired < 3 ) - return ACT_VM_RECOIL1; - - if ( m_nShotsFired < 4 ) - return ACT_VM_RECOIL2; - - return ACT_VM_RECOIL3; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &tr - -// nDamageType - -//----------------------------------------------------------------------------- -void CWeaponAR2::DoImpactEffect( trace_t &tr, int nDamageType ) -{ - CEffectData data; - - data.m_vOrigin = tr.endpos + ( tr.plane.normal * 1.0f ); - data.m_vNormal = tr.plane.normal; - - DispatchEffect( "AR2Impact", data ); - - BaseClass::DoImpactEffect( tr, nDamageType ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponAR2::DelayedAttack( void ) -{ - m_bShotDelayed = false; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - // Deplete the clip completely - SendWeaponAnim( ACT_VM_SECONDARYATTACK ); - m_flNextSecondaryAttack = pOwner->m_flNextAttack = gpGlobals->curtime + SequenceDuration(); - - // Register a muzzleflash for the AI - pOwner->DoMuzzleFlash(); - - WeaponSound( WPN_DOUBLE ); - - // Fire the bullets - Vector vecSrc = pOwner->Weapon_ShootPosition( ); - Vector vecAiming = pOwner->GetAutoaimVector( AUTOAIM_2DEGREES ); - Vector impactPoint = vecSrc + ( vecAiming * MAX_TRACE_LENGTH ); - - // Fire the bullets - Vector vecVelocity = vecAiming * 1000.0f; - -#ifndef CLIENT_DLL - // Fire the combine ball - CreateCombineBall( vecSrc, - vecVelocity, - sk_weapon_ar2_alt_fire_radius.GetFloat(), - sk_weapon_ar2_alt_fire_mass.GetFloat(), - sk_weapon_ar2_alt_fire_duration.GetFloat(), - pOwner ); - - // View effects - color32 white = {255, 255, 255, 64}; - UTIL_ScreenFade( pOwner, white, 0.1, 0, FFADE_IN ); -#endif - - //Disorient the player - QAngle angles = pOwner->GetLocalAngles(); - - angles.x += random->RandomInt( -4, 4 ); - angles.y += random->RandomInt( -4, 4 ); - angles.z = 0; - -// pOwner->SnapEyeAngles( angles ); - - pOwner->ViewPunch( QAngle( SharedRandomInt( "ar2pax", -8, -12 ), SharedRandomInt( "ar2pay", 1, 2 ), 0 ) ); - - // Decrease ammo - pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType ); - - // Can shoot again immediately - m_flNextPrimaryAttack = gpGlobals->curtime + 0.5f; - - // Can blow up after a short delay (so have time to release mouse button) - m_flNextSecondaryAttack = gpGlobals->curtime + 1.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponAR2::SecondaryAttack( void ) -{ - if ( m_bShotDelayed ) - return; - - // Cannot fire underwater - if ( GetOwner() && GetOwner()->GetWaterLevel() == 3 ) - { - SendWeaponAnim( ACT_VM_DRYFIRE ); - BaseClass::WeaponSound( EMPTY ); - m_flNextSecondaryAttack = gpGlobals->curtime + 0.5f; - return; - } - - m_bShotDelayed = true; - m_flNextPrimaryAttack = m_flNextSecondaryAttack = m_flDelayedFire = gpGlobals->curtime + 0.5f; - - SendWeaponAnim( ACT_VM_FIDGET ); - WeaponSound( SPECIAL1 ); -} - -//----------------------------------------------------------------------------- -// Purpose: Override if we're waiting to release a shot -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponAR2::CanHolster( void ) -{ - if ( m_bShotDelayed ) - return false; - - return BaseClass::CanHolster(); -} - - -bool CWeaponAR2::Deploy( void ) -{ - m_bShotDelayed = false; - m_flDelayedFire = 0.0f; - - return BaseClass::Deploy(); -} - -//----------------------------------------------------------------------------- -// Purpose: Override if we're waiting to release a shot -//----------------------------------------------------------------------------- -bool CWeaponAR2::Reload( void ) -{ - if ( m_bShotDelayed ) - return false; - - return BaseClass::Reload(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponAR2::AddViewKick( void ) -{ - #define EASY_DAMPEN 0.5f - #define MAX_VERTICAL_KICK 8.0f //Degrees - #define SLIDE_LIMIT 5.0f //Seconds - - //Get the view kick - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if (!pPlayer) - return; - - DoMachineGunKick( pPlayer, EASY_DAMPEN, MAX_VERTICAL_KICK, m_fFireDuration, SLIDE_LIMIT ); -} - -//----------------------------------------------------------------------------- -const WeaponProficiencyInfo_t *CWeaponAR2::GetProficiencyValues() -{ - static WeaponProficiencyInfo_t proficiencyTable[] = - { - { 7.0, 0.75 }, - { 5.00, 0.75 }, - { 3.0, 0.85 }, - { 5.0/3.0, 0.75 }, - { 1.00, 1.0 }, - }; - - COMPILE_TIME_ASSERT( ARRAYSIZE(proficiencyTable) == WEAPON_PROFICIENCY_PERFECT + 1); - - return proficiencyTable; -} diff --git a/game/shared/hl2mp/weapon_ar2.h b/game/shared/hl2mp/weapon_ar2.h deleted file mode 100644 index 8d748f190..000000000 --- a/game/shared/hl2mp/weapon_ar2.h +++ /dev/null @@ -1,84 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Projectile shot from the AR2 -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef WEAPONAR2_H -#define WEAPONAR2_H - -#include "basegrenade_shared.h" -#include "weapon_hl2mpbase_machinegun.h" - -#ifdef CLIENT_DLL -#define CWeaponAR2 C_WeaponAR2 -#endif - -class CWeaponAR2 : public CHL2MPMachineGun -{ -public: - DECLARE_CLASS( CWeaponAR2, CHL2MPMachineGun ); - - CWeaponAR2(); - - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - - void ItemPostFrame( void ); - void Precache( void ); - - void SecondaryAttack( void ); - void DelayedAttack( void ); - - const char *GetTracerType( void ) { return "AR2Tracer"; } - - void AddViewKick( void ); - - int GetMinBurst( void ) { return 2; } - int GetMaxBurst( void ) { return 5; } - float GetFireRate( void ) { return 0.1f; } - - bool CanHolster( void ); - bool Reload( void ); - - Activity GetPrimaryAttackActivity( void ); - - void DoImpactEffect( trace_t &tr, int nDamageType ); - - virtual bool Deploy( void ); - - - virtual const Vector& GetBulletSpread( void ) - { - static Vector cone; - - cone = VECTOR_CONE_3DEGREES; - - return cone; - } - - const WeaponProficiencyInfo_t *GetProficiencyValues(); - -private: - CWeaponAR2( const CWeaponAR2 & ); - -protected: - - float m_flDelayedFire; - bool m_bShotDelayed; - int m_nVentPose; - -#ifndef CLIENT_DLL - DECLARE_ACTTABLE(); -#endif -}; - - -#endif //WEAPONAR2_H diff --git a/game/shared/hl2mp/weapon_crossbow.cpp b/game/shared/hl2mp/weapon_crossbow.cpp deleted file mode 100644 index e35f75e89..000000000 --- a/game/shared/hl2mp/weapon_crossbow.cpp +++ /dev/null @@ -1,956 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" -#include "in_buttons.h" - -#ifdef CLIENT_DLL - #include "c_hl2mp_player.h" - #include "c_te_effect_dispatch.h" -#else - #include "hl2mp_player.h" - #include "te_effect_dispatch.h" - #include "IEffects.h" - #include "Sprite.h" - #include "SpriteTrail.h" - #include "beam_shared.h" -#endif - -#include "weapon_hl2mpbasehlmpcombatweapon.h" -#include "effect_dispatch_data.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//#define BOLT_MODEL "models/crossbow_bolt.mdl" -#define BOLT_MODEL "models/weapons/w_missile_closed.mdl" - -#define BOLT_AIR_VELOCITY 3500 -#define BOLT_WATER_VELOCITY 1500 -#define BOLT_SKIN_NORMAL 0 -#define BOLT_SKIN_GLOW 1 - - -#ifndef CLIENT_DLL - -extern ConVar sk_plr_dmg_crossbow; -extern ConVar sk_npc_dmg_crossbow; - -void TE_StickyBolt( IRecipientFilter& filter, float delay, Vector vecDirection, const Vector *origin ); - -//----------------------------------------------------------------------------- -// Crossbow Bolt -//----------------------------------------------------------------------------- -class CCrossbowBolt : public CBaseCombatCharacter -{ - DECLARE_CLASS( CCrossbowBolt, CBaseCombatCharacter ); - -public: - CCrossbowBolt() { }; - ~CCrossbowBolt(); - - Class_T Classify( void ) { return CLASS_NONE; } - -public: - void Spawn( void ); - void Precache( void ); - void BubbleThink( void ); - void BoltTouch( CBaseEntity *pOther ); - bool CreateVPhysics( void ); - unsigned int PhysicsSolidMaskForEntity() const; - static CCrossbowBolt *BoltCreate( const Vector &vecOrigin, const QAngle &angAngles, int iDamage, CBasePlayer *pentOwner = NULL ); - -protected: - - bool CreateSprites( void ); - - CHandle m_pGlowSprite; - //CHandle m_pGlowTrail; - - int m_iDamage; - - DECLARE_DATADESC(); - DECLARE_SERVERCLASS(); -}; -LINK_ENTITY_TO_CLASS( crossbow_bolt, CCrossbowBolt ); - -BEGIN_DATADESC( CCrossbowBolt ) - // Function Pointers - DEFINE_FUNCTION( BubbleThink ), - DEFINE_FUNCTION( BoltTouch ), - - // These are recreated on reload, they don't need storage - DEFINE_FIELD( m_pGlowSprite, FIELD_EHANDLE ), - //DEFINE_FIELD( m_pGlowTrail, FIELD_EHANDLE ), - -END_DATADESC() - -IMPLEMENT_SERVERCLASS_ST( CCrossbowBolt, DT_CrossbowBolt ) -END_SEND_TABLE() - -CCrossbowBolt *CCrossbowBolt::BoltCreate( const Vector &vecOrigin, const QAngle &angAngles, int iDamage, CBasePlayer *pentOwner ) -{ - // Create a new entity with CCrossbowBolt private data - CCrossbowBolt *pBolt = (CCrossbowBolt *)CreateEntityByName( "crossbow_bolt" ); - UTIL_SetOrigin( pBolt, vecOrigin ); - pBolt->SetAbsAngles( angAngles ); - pBolt->Spawn(); - pBolt->SetOwnerEntity( pentOwner ); - - pBolt->m_iDamage = iDamage; - - return pBolt; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CCrossbowBolt::~CCrossbowBolt( void ) -{ - if ( m_pGlowSprite ) - { - UTIL_Remove( m_pGlowSprite ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CCrossbowBolt::CreateVPhysics( void ) -{ - // Create the object in the physics system - VPhysicsInitNormal( SOLID_BBOX, FSOLID_NOT_STANDABLE, false ); - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -unsigned int CCrossbowBolt::PhysicsSolidMaskForEntity() const -{ - return ( BaseClass::PhysicsSolidMaskForEntity() | CONTENTS_HITBOX ) & ~CONTENTS_GRATE; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CCrossbowBolt::CreateSprites( void ) -{ - // Start up the eye glow - m_pGlowSprite = CSprite::SpriteCreate( "sprites/light_glow02_noz.vmt", GetLocalOrigin(), false ); - - if ( m_pGlowSprite != NULL ) - { - m_pGlowSprite->FollowEntity( this ); - m_pGlowSprite->SetTransparency( kRenderGlow, 255, 255, 255, 128, kRenderFxNoDissipation ); - m_pGlowSprite->SetScale( 0.2f ); - m_pGlowSprite->TurnOff(); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCrossbowBolt::Spawn( void ) -{ - Precache( ); - - SetModel( "models/crossbow_bolt.mdl" ); - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_CUSTOM ); - UTIL_SetSize( this, -Vector(1,1,1), Vector(1,1,1) ); - SetSolid( SOLID_BBOX ); - SetGravity( 0.05f ); - - // Make sure we're updated if we're underwater - UpdateWaterState(); - - SetTouch( &CCrossbowBolt::BoltTouch ); - - SetThink( &CCrossbowBolt::BubbleThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); - - CreateSprites(); - - // Make us glow until we've hit the wall - m_nSkin = BOLT_SKIN_GLOW; -} - - -void CCrossbowBolt::Precache( void ) -{ - PrecacheModel( BOLT_MODEL ); - - // This is used by C_TEStickyBolt, despte being different from above!!! - PrecacheModel( "models/crossbow_bolt.mdl" ); - - PrecacheModel( "sprites/light_glow02_noz.vmt" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOther - -//----------------------------------------------------------------------------- -void CCrossbowBolt::BoltTouch( CBaseEntity *pOther ) -{ - if ( !pOther->IsSolid() || pOther->IsSolidFlagSet(FSOLID_VOLUME_CONTENTS) ) - return; - - if ( pOther->m_takedamage != DAMAGE_NO ) - { - trace_t tr, tr2; - tr = BaseClass::GetTouchTrace(); - Vector vecNormalizedVel = GetAbsVelocity(); - - ClearMultiDamage(); - VectorNormalize( vecNormalizedVel ); - - if( GetOwnerEntity() && GetOwnerEntity()->IsPlayer() && pOther->IsNPC() ) - { - CTakeDamageInfo dmgInfo( this, GetOwnerEntity(), m_iDamage, DMG_NEVERGIB ); - dmgInfo.AdjustPlayerDamageInflictedForSkillLevel(); - CalculateMeleeDamageForce( &dmgInfo, vecNormalizedVel, tr.endpos, 0.7f ); - dmgInfo.SetDamagePosition( tr.endpos ); - pOther->DispatchTraceAttack( dmgInfo, vecNormalizedVel, &tr ); - } - else - { - CTakeDamageInfo dmgInfo( this, GetOwnerEntity(), m_iDamage, DMG_BULLET | DMG_NEVERGIB ); - CalculateMeleeDamageForce( &dmgInfo, vecNormalizedVel, tr.endpos, 0.7f ); - dmgInfo.SetDamagePosition( tr.endpos ); - pOther->DispatchTraceAttack( dmgInfo, vecNormalizedVel, &tr ); - } - - ApplyMultiDamage(); - - //Adrian: keep going through the glass. - if ( pOther->GetCollisionGroup() == COLLISION_GROUP_BREAKABLE_GLASS ) - return; - - SetAbsVelocity( Vector( 0, 0, 0 ) ); - - // play body "thwack" sound - EmitSound( "Weapon_Crossbow.BoltHitBody" ); - - Vector vForward; - - AngleVectors( GetAbsAngles(), &vForward ); - VectorNormalize ( vForward ); - - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + vForward * 128, MASK_OPAQUE, pOther, COLLISION_GROUP_NONE, &tr2 ); - - if ( tr2.fraction != 1.0f ) - { -// NDebugOverlay::Box( tr2.endpos, Vector( -16, -16, -16 ), Vector( 16, 16, 16 ), 0, 255, 0, 0, 10 ); -// NDebugOverlay::Box( GetAbsOrigin(), Vector( -16, -16, -16 ), Vector( 16, 16, 16 ), 0, 0, 255, 0, 10 ); - - if ( tr2.m_pEnt == NULL || ( tr2.m_pEnt && tr2.m_pEnt->GetMoveType() == MOVETYPE_NONE ) ) - { - CEffectData data; - - data.m_vOrigin = tr2.endpos; - data.m_vNormal = vForward; - data.m_nEntIndex = tr2.fraction != 1.0f; - - DispatchEffect( "BoltImpact", data ); - } - } - - SetTouch( NULL ); - SetThink( NULL ); - - UTIL_Remove( this ); - } - else - { - trace_t tr; - tr = BaseClass::GetTouchTrace(); - - // See if we struck the world - if ( pOther->GetMoveType() == MOVETYPE_NONE && !( tr.surface.flags & SURF_SKY ) ) - { - EmitSound( "Weapon_Crossbow.BoltHitWorld" ); - - // if what we hit is static architecture, can stay around for a while. - Vector vecDir = GetAbsVelocity(); - float speed = VectorNormalize( vecDir ); - - // See if we should reflect off this surface - float hitDot = DotProduct( tr.plane.normal, -vecDir ); - - if ( ( hitDot < 0.5f ) && ( speed > 100 ) ) - { - Vector vReflection = 2.0f * tr.plane.normal * hitDot + vecDir; - - QAngle reflectAngles; - - VectorAngles( vReflection, reflectAngles ); - - SetLocalAngles( reflectAngles ); - - SetAbsVelocity( vReflection * speed * 0.75f ); - - // Start to sink faster - SetGravity( 1.0f ); - } - else - { - SetThink( &CCrossbowBolt::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 2.0f ); - - //FIXME: We actually want to stick (with hierarchy) to what we've hit - SetMoveType( MOVETYPE_NONE ); - - Vector vForward; - - AngleVectors( GetAbsAngles(), &vForward ); - VectorNormalize ( vForward ); - - CEffectData data; - - data.m_vOrigin = tr.endpos; - data.m_vNormal = vForward; - data.m_nEntIndex = 0; - - DispatchEffect( "BoltImpact", data ); - - UTIL_ImpactTrace( &tr, DMG_BULLET ); - - AddEffects( EF_NODRAW ); - SetTouch( NULL ); - SetThink( &CCrossbowBolt::SUB_Remove ); - SetNextThink( gpGlobals->curtime + 2.0f ); - - if ( m_pGlowSprite != NULL ) - { - m_pGlowSprite->TurnOn(); - m_pGlowSprite->FadeAndDie( 3.0f ); - } - } - - // Shoot some sparks - if ( UTIL_PointContents( GetAbsOrigin() ) != CONTENTS_WATER) - { - g_pEffects->Sparks( GetAbsOrigin() ); - } - } - else - { - // Put a mark unless we've hit the sky - if ( ( tr.surface.flags & SURF_SKY ) == false ) - { - UTIL_ImpactTrace( &tr, DMG_BULLET ); - } - - UTIL_Remove( this ); - } - } - - if ( g_pGameRules->IsMultiplayer() ) - { -// SetThink( &CCrossbowBolt::ExplodeThink ); -// SetNextThink( gpGlobals->curtime + 0.1f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCrossbowBolt::BubbleThink( void ) -{ - QAngle angNewAngles; - - VectorAngles( GetAbsVelocity(), angNewAngles ); - SetAbsAngles( angNewAngles ); - - SetNextThink( gpGlobals->curtime + 0.1f ); - - if ( GetWaterLevel() == 0 ) - return; - - UTIL_BubbleTrail( GetAbsOrigin() - GetAbsVelocity() * 0.1f, GetAbsOrigin(), 5 ); -} - -#endif - -//----------------------------------------------------------------------------- -// CWeaponCrossbow -//----------------------------------------------------------------------------- - -#ifdef CLIENT_DLL -#define CWeaponCrossbow C_WeaponCrossbow -#endif - -class CWeaponCrossbow : public CBaseHL2MPCombatWeapon -{ - DECLARE_CLASS( CWeaponCrossbow, CBaseHL2MPCombatWeapon ); -public: - - CWeaponCrossbow( void ); - - virtual void Precache( void ); - virtual void PrimaryAttack( void ); - virtual void SecondaryAttack( void ); - virtual bool Deploy( void ); - virtual bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); - virtual bool Reload( void ); - virtual void ItemPostFrame( void ); - virtual void ItemBusyFrame( void ); - virtual bool SendWeaponAnim( int iActivity ); - -#ifndef CLIENT_DLL - virtual void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); -#endif - - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - -private: - - void SetSkin( int skinNum ); - void CheckZoomToggle( void ); - void FireBolt( void ); - void ToggleZoom( void ); - - // Various states for the crossbow's charger - enum ChargerState_t - { - CHARGER_STATE_START_LOAD, - CHARGER_STATE_START_CHARGE, - CHARGER_STATE_READY, - CHARGER_STATE_DISCHARGE, - CHARGER_STATE_OFF, - }; - - void CreateChargerEffects( void ); - void SetChargerState( ChargerState_t state ); - void DoLoadEffect( void ); - -#ifndef CLIENT_DLL - DECLARE_ACTTABLE(); -#endif - -private: - - // Charger effects - ChargerState_t m_nChargeState; - -#ifndef CLIENT_DLL - CHandle m_hChargerSprite; -#endif - - CNetworkVar( bool, m_bInZoom ); - CNetworkVar( bool, m_bMustReload ); - - CWeaponCrossbow( const CWeaponCrossbow & ); -}; - -IMPLEMENT_NETWORKCLASS_ALIASED( WeaponCrossbow, DT_WeaponCrossbow ) - -BEGIN_NETWORK_TABLE( CWeaponCrossbow, DT_WeaponCrossbow ) -#ifdef CLIENT_DLL - RecvPropBool( RECVINFO( m_bInZoom ) ), - RecvPropBool( RECVINFO( m_bMustReload ) ), -#else - SendPropBool( SENDINFO( m_bInZoom ) ), - SendPropBool( SENDINFO( m_bMustReload ) ), -#endif -END_NETWORK_TABLE() - -#ifdef CLIENT_DLL -BEGIN_PREDICTION_DATA( CWeaponCrossbow ) - DEFINE_PRED_FIELD( m_bInZoom, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_bMustReload, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), -END_PREDICTION_DATA() -#endif - -LINK_ENTITY_TO_CLASS( weapon_crossbow, CWeaponCrossbow ); - -PRECACHE_WEAPON_REGISTER( weapon_crossbow ); - -#ifndef CLIENT_DLL - -acttable_t CWeaponCrossbow::m_acttable[] = -{ - { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_CROSSBOW, false }, - { ACT_HL2MP_RUN, ACT_HL2MP_RUN_CROSSBOW, false }, - { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_CROSSBOW, false }, - { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_CROSSBOW, false }, - { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_CROSSBOW, false }, - { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_CROSSBOW, false }, - { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_CROSSBOW, false }, -}; - -IMPLEMENT_ACTTABLE(CWeaponCrossbow); - -#endif - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -CWeaponCrossbow::CWeaponCrossbow( void ) -{ - m_bReloadsSingly = true; - m_bFiresUnderwater = true; - m_bInZoom = false; - m_bMustReload = false; -} - -#define CROSSBOW_GLOW_SPRITE "sprites/light_glow02_noz.vmt" -#define CROSSBOW_GLOW_SPRITE2 "sprites/blueflare1.vmt" - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCrossbow::Precache( void ) -{ -#ifndef CLIENT_DLL - UTIL_PrecacheOther( "crossbow_bolt" ); -#endif - - PrecacheScriptSound( "Weapon_Crossbow.BoltHitBody" ); - PrecacheScriptSound( "Weapon_Crossbow.BoltHitWorld" ); - PrecacheScriptSound( "Weapon_Crossbow.BoltSkewer" ); - - PrecacheModel( CROSSBOW_GLOW_SPRITE ); - PrecacheModel( CROSSBOW_GLOW_SPRITE2 ); - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCrossbow::PrimaryAttack( void ) -{ - if ( m_bInZoom && g_pGameRules->IsMultiplayer() ) - { -// FireSniperBolt(); - FireBolt(); - } - else - { - FireBolt(); - } - - // Signal a reload - m_bMustReload = true; - - SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration( ACT_VM_PRIMARYATTACK ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCrossbow::SecondaryAttack( void ) -{ - //NOTENOTE: The zooming is handled by the post/busy frames -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponCrossbow::Reload( void ) -{ - if ( BaseClass::Reload() ) - { - m_bMustReload = false; - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCrossbow::CheckZoomToggle( void ) -{ - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if ( pPlayer->m_afButtonPressed & IN_ATTACK2 ) - { - ToggleZoom(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCrossbow::ItemBusyFrame( void ) -{ - // Allow zoom toggling even when we're reloading - CheckZoomToggle(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCrossbow::ItemPostFrame( void ) -{ - // Allow zoom toggling - CheckZoomToggle(); - - if ( m_bMustReload && HasWeaponIdleTimeElapsed() ) - { - Reload(); - } - - BaseClass::ItemPostFrame(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCrossbow::FireBolt( void ) -{ - if ( m_iClip1 <= 0 ) - { - if ( !m_bFireOnEmpty ) - { - Reload(); - } - else - { - WeaponSound( EMPTY ); - m_flNextPrimaryAttack = 0.15; - } - - return; - } - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - -#ifndef CLIENT_DLL - Vector vecAiming = pOwner->GetAutoaimVector( 0 ); - Vector vecSrc = pOwner->Weapon_ShootPosition(); - - QAngle angAiming; - VectorAngles( vecAiming, angAiming ); - - CCrossbowBolt *pBolt = CCrossbowBolt::BoltCreate( vecSrc, angAiming, GetHL2MPWpnData().m_iPlayerDamage, pOwner ); - - if ( pOwner->GetWaterLevel() == 3 ) - { - pBolt->SetAbsVelocity( vecAiming * BOLT_WATER_VELOCITY ); - } - else - { - pBolt->SetAbsVelocity( vecAiming * BOLT_AIR_VELOCITY ); - } - -#endif - - m_iClip1--; - - pOwner->ViewPunch( QAngle( -2, 0, 0 ) ); - - WeaponSound( SINGLE ); - WeaponSound( SPECIAL2 ); - - SendWeaponAnim( ACT_VM_PRIMARYATTACK ); - - if ( !m_iClip1 && pOwner->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 ) - { - // HEV suit - indicate out of ammo condition - pOwner->SetSuitUpdate("!HEV_AMO0", FALSE, 0); - } - - m_flNextPrimaryAttack = m_flNextSecondaryAttack = gpGlobals->curtime + 0.75; - - DoLoadEffect(); - SetChargerState( CHARGER_STATE_DISCHARGE ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponCrossbow::Deploy( void ) -{ - if ( m_iClip1 <= 0 ) - { - return DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), ACT_CROSSBOW_DRAW_UNLOADED, (char*)GetAnimPrefix() ); - } - - SetSkin( BOLT_SKIN_GLOW ); - - return BaseClass::Deploy(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pSwitchingTo - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponCrossbow::Holster( CBaseCombatWeapon *pSwitchingTo ) -{ - if ( m_bInZoom ) - { - ToggleZoom(); - } - - SetChargerState( CHARGER_STATE_OFF ); - - return BaseClass::Holster( pSwitchingTo ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCrossbow::ToggleZoom( void ) -{ - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if ( pPlayer == NULL ) - return; - -#ifndef CLIENT_DLL - - if ( m_bInZoom ) - { - if ( pPlayer->SetFOV( this, 0, 0.2f ) ) - { - m_bInZoom = false; - } - } - else - { - if ( pPlayer->SetFOV( this, 20, 0.1f ) ) - { - m_bInZoom = true; - } - } -#endif -} - -#define BOLT_TIP_ATTACHMENT 2 - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCrossbow::CreateChargerEffects( void ) -{ -#ifndef CLIENT_DLL - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( m_hChargerSprite != NULL ) - return; - - m_hChargerSprite = CSprite::SpriteCreate( CROSSBOW_GLOW_SPRITE, GetAbsOrigin(), false ); - - if ( m_hChargerSprite ) - { - m_hChargerSprite->SetAttachment( pOwner->GetViewModel(), BOLT_TIP_ATTACHMENT ); - m_hChargerSprite->SetTransparency( kRenderTransAdd, 255, 128, 0, 255, kRenderFxNoDissipation ); - m_hChargerSprite->SetBrightness( 0 ); - m_hChargerSprite->SetScale( 0.1f ); - m_hChargerSprite->TurnOff(); - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : skinNum - -//----------------------------------------------------------------------------- -void CWeaponCrossbow::SetSkin( int skinNum ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - CBaseViewModel *pViewModel = pOwner->GetViewModel(); - - if ( pViewModel == NULL ) - return; - - pViewModel->m_nSkin = skinNum; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCrossbow::DoLoadEffect( void ) -{ - SetSkin( BOLT_SKIN_GLOW ); - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - CBaseViewModel *pViewModel = pOwner->GetViewModel(); - - if ( pViewModel == NULL ) - return; - - CEffectData data; - -#ifdef CLIENT_DLL - data.m_hEntity = pViewModel->GetRefEHandle(); -#else - data.m_nEntIndex = pViewModel->entindex(); -#endif - data.m_nAttachmentIndex = 1; - - DispatchEffect( "CrossbowLoad", data ); - -#ifndef CLIENT_DLL - - CSprite *pBlast = CSprite::SpriteCreate( CROSSBOW_GLOW_SPRITE2, GetAbsOrigin(), false ); - - if ( pBlast ) - { - pBlast->SetAttachment( pOwner->GetViewModel(), 1 ); - pBlast->SetTransparency( kRenderTransAdd, 255, 255, 255, 255, kRenderFxNone ); - pBlast->SetBrightness( 128 ); - pBlast->SetScale( 0.2f ); - pBlast->FadeOutFromSpawn(); - } -#endif - -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : state - -//----------------------------------------------------------------------------- -void CWeaponCrossbow::SetChargerState( ChargerState_t state ) -{ - // Make sure we're setup - CreateChargerEffects(); - - // Don't do this twice - if ( state == m_nChargeState ) - return; - - m_nChargeState = state; - - switch( m_nChargeState ) - { - case CHARGER_STATE_START_LOAD: - - WeaponSound( SPECIAL1 ); - - // Shoot some sparks and draw a beam between the two outer points - DoLoadEffect(); - - break; -#ifndef CLIENT_DLL - case CHARGER_STATE_START_CHARGE: - { - if ( m_hChargerSprite == NULL ) - break; - - m_hChargerSprite->SetBrightness( 32, 0.5f ); - m_hChargerSprite->SetScale( 0.025f, 0.5f ); - m_hChargerSprite->TurnOn(); - } - - break; - - case CHARGER_STATE_READY: - { - // Get fully charged - if ( m_hChargerSprite == NULL ) - break; - - m_hChargerSprite->SetBrightness( 80, 1.0f ); - m_hChargerSprite->SetScale( 0.1f, 0.5f ); - m_hChargerSprite->TurnOn(); - } - - break; - - case CHARGER_STATE_DISCHARGE: - { - SetSkin( BOLT_SKIN_NORMAL ); - - if ( m_hChargerSprite == NULL ) - break; - - m_hChargerSprite->SetBrightness( 0 ); - m_hChargerSprite->TurnOff(); - } - - break; -#endif - case CHARGER_STATE_OFF: - { - SetSkin( BOLT_SKIN_NORMAL ); - -#ifndef CLIENT_DLL - if ( m_hChargerSprite == NULL ) - break; - - m_hChargerSprite->SetBrightness( 0 ); - m_hChargerSprite->TurnOff(); -#endif - } - break; - - default: - break; - } -} - -#ifndef CLIENT_DLL -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEvent - -// *pOperator - -//----------------------------------------------------------------------------- -void CWeaponCrossbow::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - switch( pEvent->event ) - { - case EVENT_WEAPON_THROW: - SetChargerState( CHARGER_STATE_START_LOAD ); - break; - - case EVENT_WEAPON_THROW2: - SetChargerState( CHARGER_STATE_START_CHARGE ); - break; - - case EVENT_WEAPON_THROW3: - SetChargerState( CHARGER_STATE_READY ); - break; - - default: - BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); - break; - } -} - -#endif - -//----------------------------------------------------------------------------- -// Purpose: Set the desired activity for the weapon and its viewmodel counterpart -// Input : iActivity - activity to play -//----------------------------------------------------------------------------- -bool CWeaponCrossbow::SendWeaponAnim( int iActivity ) -{ - int newActivity = iActivity; - - // The last shot needs a non-loaded activity - if ( ( newActivity == ACT_VM_IDLE ) && ( m_iClip1 <= 0 ) ) - { - newActivity = ACT_VM_FIDGET; - } - - //For now, just set the ideal activity and be done with it - return BaseClass::SendWeaponAnim( newActivity ); -} diff --git a/game/shared/hl2mp/weapon_crowbar.cpp b/game/shared/hl2mp/weapon_crowbar.cpp deleted file mode 100644 index 9133cacbb..000000000 --- a/game/shared/hl2mp/weapon_crowbar.cpp +++ /dev/null @@ -1,228 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Crowbar - an old favorite -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "hl2mp/weapon_crowbar.h" -#include "weapon_hl2mpbasehlmpcombatweapon.h" -#include "gamerules.h" -#include "ammodef.h" -#include "mathlib/mathlib.h" -#include "in_buttons.h" -#include "vstdlib/random.h" -#include "npcevent.h" - -#if defined( CLIENT_DLL ) - #include "c_hl2mp_player.h" -#else - #include "hl2mp_player.h" - #include "ai_basenpc.h" -#endif - - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define CROWBAR_RANGE 75.0f -#define CROWBAR_REFIRE 0.4f - - -//----------------------------------------------------------------------------- -// CWeaponCrowbar -//----------------------------------------------------------------------------- - -IMPLEMENT_NETWORKCLASS_ALIASED( WeaponCrowbar, DT_WeaponCrowbar ) - -BEGIN_NETWORK_TABLE( CWeaponCrowbar, DT_WeaponCrowbar ) -END_NETWORK_TABLE() - -BEGIN_PREDICTION_DATA( CWeaponCrowbar ) -END_PREDICTION_DATA() - -LINK_ENTITY_TO_CLASS( weapon_crowbar, CWeaponCrowbar ); -PRECACHE_WEAPON_REGISTER( weapon_crowbar ); - -#ifndef CLIENT_DLL - -acttable_t CWeaponCrowbar::m_acttable[] = -{ - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SLAM, true }, - { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_MELEE, false }, - { ACT_HL2MP_RUN, ACT_HL2MP_RUN_MELEE, false }, - { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_MELEE, false }, - { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_MELEE, false }, - { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE, false }, - { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_MELEE, false }, - { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_MELEE, false }, -}; - -IMPLEMENT_ACTTABLE(CWeaponCrowbar); - -#endif - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CWeaponCrowbar::CWeaponCrowbar( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: Get the damage amount for the animation we're doing -// Input : hitActivity - currently played activity -// Output : Damage amount -//----------------------------------------------------------------------------- -float CWeaponCrowbar::GetDamageForActivity( Activity hitActivity ) -{ - return 25.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: Add in a view kick for this weapon -//----------------------------------------------------------------------------- -void CWeaponCrowbar::AddViewKick( void ) -{ - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if ( pPlayer == NULL ) - return; - - QAngle punchAng; - - punchAng.x = SharedRandomFloat( "crowbarpax", 1.0f, 2.0f ); - punchAng.y = SharedRandomFloat( "crowbarpay", -2.0f, -1.0f ); - punchAng.z = 0.0f; - - pPlayer->ViewPunch( punchAng ); -} - - -#ifndef CLIENT_DLL -//----------------------------------------------------------------------------- -// Animation event handlers -//----------------------------------------------------------------------------- -void CWeaponCrowbar::HandleAnimEventMeleeHit( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - // Trace up or down based on where the enemy is... - // But only if we're basically facing that direction - Vector vecDirection; - AngleVectors( GetAbsAngles(), &vecDirection ); - - Vector vecEnd; - VectorMA( pOperator->Weapon_ShootPosition(), 50, vecDirection, vecEnd ); - CBaseEntity *pHurt = pOperator->CheckTraceHullAttack( pOperator->Weapon_ShootPosition(), vecEnd, - Vector(-16,-16,-16), Vector(36,36,36), (int)GetDamageForActivity( GetActivity() ), DMG_CLUB, 0.75 ); - - // did I hit someone? - if ( pHurt ) - { - // play sound - WeaponSound( MELEE_HIT ); - - // Fake a trace impact, so the effects work out like a player's crowbaw - trace_t traceHit; - UTIL_TraceLine( pOperator->Weapon_ShootPosition(), pHurt->GetAbsOrigin(), MASK_SHOT_HULL, pOperator, COLLISION_GROUP_NONE, &traceHit ); - ImpactEffect( traceHit ); - } - else - { - WeaponSound( MELEE_MISS ); - } -} - - -//----------------------------------------------------------------------------- -// Animation event -//----------------------------------------------------------------------------- -void CWeaponCrowbar::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - switch( pEvent->event ) - { - case EVENT_WEAPON_MELEE_HIT: - HandleAnimEventMeleeHit( pEvent, pOperator ); - break; - - default: - BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); - break; - } -} - -//----------------------------------------------------------------------------- -// Attempt to lead the target (needed because citizens can't hit manhacks with the crowbar!) -//----------------------------------------------------------------------------- -ConVar sk_crowbar_lead_time( "sk_crowbar_lead_time", "0.9" ); - -int CWeaponCrowbar::WeaponMeleeAttack1Condition( float flDot, float flDist ) -{ - // Attempt to lead the target (needed because citizens can't hit manhacks with the crowbar!) - CAI_BaseNPC *pNPC = GetOwner()->MyNPCPointer(); - CBaseEntity *pEnemy = pNPC->GetEnemy(); - if (!pEnemy) - return COND_NONE; - - Vector vecVelocity; - vecVelocity = pEnemy->GetSmoothedVelocity( ); - - // Project where the enemy will be in a little while - float dt = sk_crowbar_lead_time.GetFloat(); - dt += SharedRandomFloat( "crowbarmelee1", -0.3f, 0.2f ); - if ( dt < 0.0f ) - dt = 0.0f; - - Vector vecExtrapolatedPos; - VectorMA( pEnemy->WorldSpaceCenter(), dt, vecVelocity, vecExtrapolatedPos ); - - Vector vecDelta; - VectorSubtract( vecExtrapolatedPos, pNPC->WorldSpaceCenter(), vecDelta ); - - if ( fabs( vecDelta.z ) > 70 ) - { - return COND_TOO_FAR_TO_ATTACK; - } - - Vector vecForward = pNPC->BodyDirection2D( ); - vecDelta.z = 0.0f; - float flExtrapolatedDist = Vector2DNormalize( vecDelta.AsVector2D() ); - if ((flDist > 64) && (flExtrapolatedDist > 64)) - { - return COND_TOO_FAR_TO_ATTACK; - } - - float flExtrapolatedDot = DotProduct2D( vecDelta.AsVector2D(), vecForward.AsVector2D() ); - if ((flDot < 0.7) && (flExtrapolatedDot < 0.7)) - { - return COND_NOT_FACING_ATTACK; - } - - return COND_CAN_MELEE_ATTACK1; -} - -#endif - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponCrowbar::Drop( const Vector &vecVelocity ) -{ -#ifndef CLIENT_DLL - UTIL_Remove( this ); -#endif -} - -float CWeaponCrowbar::GetRange( void ) -{ - return CROWBAR_RANGE; -} - -float CWeaponCrowbar::GetFireRate( void ) -{ - return CROWBAR_REFIRE; -} - - diff --git a/game/shared/hl2mp/weapon_crowbar.h b/game/shared/hl2mp/weapon_crowbar.h deleted file mode 100644 index e7787989b..000000000 --- a/game/shared/hl2mp/weapon_crowbar.h +++ /dev/null @@ -1,70 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef HL2MP_WEAPON_CROWBAR_H -#define HL2MP_WEAPON_CROWBAR_H -#pragma once - - -#include "weapon_hl2mpbasehlmpcombatweapon.h" -#include "weapon_hl2mpbasebasebludgeon.h" - - -#ifdef CLIENT_DLL -#define CWeaponCrowbar C_WeaponCrowbar -#endif - -//----------------------------------------------------------------------------- -// CWeaponCrowbar -//----------------------------------------------------------------------------- - -class CWeaponCrowbar : public CBaseHL2MPBludgeonWeapon -{ -public: - DECLARE_CLASS( CWeaponCrowbar, CBaseHL2MPBludgeonWeapon ); - - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - -#ifndef CLIENT_DLL - DECLARE_ACTTABLE(); -#endif - - CWeaponCrowbar(); - - float GetRange( void ); - float GetFireRate( void ); - - void AddViewKick( void ); - float GetDamageForActivity( Activity hitActivity ); - void SecondaryAttack( void ) { return; } - - void Drop( const Vector &vecVelocity ); - - - // Animation event -#ifndef CLIENT_DLL - virtual void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); - void HandleAnimEventMeleeHit( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); - int WeaponMeleeAttack1Condition( float flDot, float flDist ); -#endif - - CWeaponCrowbar( const CWeaponCrowbar & ); - -private: - -}; - - -#endif // HL2MP_WEAPON_CROWBAR_H - diff --git a/game/shared/hl2mp/weapon_frag.cpp b/game/shared/hl2mp/weapon_frag.cpp deleted file mode 100644 index 50e15988a..000000000 --- a/game/shared/hl2mp/weapon_frag.cpp +++ /dev/null @@ -1,552 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" -#include "in_buttons.h" - -#ifdef CLIENT_DLL - #include "c_hl2mp_player.h" - #include "c_te_effect_dispatch.h" -#else - #include "hl2mp_player.h" - #include "te_effect_dispatch.h" - #include "grenade_frag.h" -#endif - -#include "weapon_ar2.h" -#include "effect_dispatch_data.h" -#include "weapon_hl2mpbasehlmpcombatweapon.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define GRENADE_TIMER 2.5f //Seconds - -#define GRENADE_PAUSED_NO 0 -#define GRENADE_PAUSED_PRIMARY 1 -#define GRENADE_PAUSED_SECONDARY 2 - -#define GRENADE_RADIUS 4.0f // inches - -#define GRENADE_DAMAGE_RADIUS 250.0f - -#ifdef CLIENT_DLL -#define CWeaponFrag C_WeaponFrag -#endif - -//----------------------------------------------------------------------------- -// Fragmentation grenades -//----------------------------------------------------------------------------- -class CWeaponFrag: public CBaseHL2MPCombatWeapon -{ - DECLARE_CLASS( CWeaponFrag, CBaseHL2MPCombatWeapon ); -public: - - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - - CWeaponFrag(); - - void Precache( void ); - void PrimaryAttack( void ); - void SecondaryAttack( void ); - void DecrementAmmo( CBaseCombatCharacter *pOwner ); - void ItemPostFrame( void ); - - bool Deploy( void ); - bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); - - bool Reload( void ); - -#ifndef CLIENT_DLL - void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); -#endif - - void ThrowGrenade( CBasePlayer *pPlayer ); - bool IsPrimed( bool ) { return ( m_AttackPaused != 0 ); } - -private: - - void RollGrenade( CBasePlayer *pPlayer ); - void LobGrenade( CBasePlayer *pPlayer ); - // check a throw from vecSrc. If not valid, move the position back along the line to vecEye - void CheckThrowPosition( CBasePlayer *pPlayer, const Vector &vecEye, Vector &vecSrc ); - - CNetworkVar( bool, m_bRedraw ); //Draw the weapon again after throwing a grenade - - CNetworkVar( int, m_AttackPaused ); - CNetworkVar( bool, m_fDrawbackFinished ); - - CWeaponFrag( const CWeaponFrag & ); - -#ifndef CLIENT_DLL - DECLARE_ACTTABLE(); -#endif -}; - -#ifndef CLIENT_DLL - -acttable_t CWeaponFrag::m_acttable[] = -{ - { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_GRENADE, false }, - { ACT_HL2MP_RUN, ACT_HL2MP_RUN_GRENADE, false }, - { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_GRENADE, false }, - { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_GRENADE, false }, - { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_GRENADE, false }, - { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_GRENADE, false }, - { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_GRENADE, false }, -}; - -IMPLEMENT_ACTTABLE(CWeaponFrag); - -#endif - -IMPLEMENT_NETWORKCLASS_ALIASED( WeaponFrag, DT_WeaponFrag ) - -BEGIN_NETWORK_TABLE( CWeaponFrag, DT_WeaponFrag ) - -#ifdef CLIENT_DLL - RecvPropBool( RECVINFO( m_bRedraw ) ), - RecvPropBool( RECVINFO( m_fDrawbackFinished ) ), - RecvPropInt( RECVINFO( m_AttackPaused ) ), -#else - SendPropBool( SENDINFO( m_bRedraw ) ), - SendPropBool( SENDINFO( m_fDrawbackFinished ) ), - SendPropInt( SENDINFO( m_AttackPaused ) ), -#endif - -END_NETWORK_TABLE() - -#ifdef CLIENT_DLL -BEGIN_PREDICTION_DATA( CWeaponFrag ) - DEFINE_PRED_FIELD( m_bRedraw, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_fDrawbackFinished, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_AttackPaused, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), -END_PREDICTION_DATA() -#endif - -LINK_ENTITY_TO_CLASS( weapon_frag, CWeaponFrag ); -PRECACHE_WEAPON_REGISTER(weapon_frag); - -CWeaponFrag::CWeaponFrag( void ) : - CBaseHL2MPCombatWeapon() -{ - m_bRedraw = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponFrag::Precache( void ) -{ - BaseClass::Precache(); - -#ifndef CLIENT_DLL - UTIL_PrecacheOther( "npc_grenade_frag" ); -#endif - - PrecacheScriptSound( "WeaponFrag.Throw" ); - PrecacheScriptSound( "WeaponFrag.Roll" ); -} - -#ifndef CLIENT_DLL -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEvent - -// *pOperator - -//----------------------------------------------------------------------------- -void CWeaponFrag::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - bool fThrewGrenade = false; - - switch( pEvent->event ) - { - case EVENT_WEAPON_SEQUENCE_FINISHED: - m_fDrawbackFinished = true; - break; - - case EVENT_WEAPON_THROW: - ThrowGrenade( pOwner ); - DecrementAmmo( pOwner ); - fThrewGrenade = true; - break; - - case EVENT_WEAPON_THROW2: - RollGrenade( pOwner ); - DecrementAmmo( pOwner ); - fThrewGrenade = true; - break; - - case EVENT_WEAPON_THROW3: - LobGrenade( pOwner ); - DecrementAmmo( pOwner ); - fThrewGrenade = true; - break; - - default: - BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); - break; - } - -#define RETHROW_DELAY 0.5 - if( fThrewGrenade ) - { - m_flNextPrimaryAttack = gpGlobals->curtime + RETHROW_DELAY; - m_flNextSecondaryAttack = gpGlobals->curtime + RETHROW_DELAY; - m_flTimeWeaponIdle = FLT_MAX; //NOTE: This is set once the animation has finished up! - } -} - -#endif - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CWeaponFrag::Deploy( void ) -{ - m_bRedraw = false; - m_fDrawbackFinished = false; - - return BaseClass::Deploy(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponFrag::Holster( CBaseCombatWeapon *pSwitchingTo ) -{ - m_bRedraw = false; - m_fDrawbackFinished = false; - - return BaseClass::Holster( pSwitchingTo ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponFrag::Reload( void ) -{ - if ( !HasPrimaryAmmo() ) - return false; - - if ( ( m_bRedraw ) && ( m_flNextPrimaryAttack <= gpGlobals->curtime ) && ( m_flNextSecondaryAttack <= gpGlobals->curtime ) ) - { - //Redraw the weapon - SendWeaponAnim( ACT_VM_DRAW ); - - //Update our times - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration(); - m_flTimeWeaponIdle = gpGlobals->curtime + SequenceDuration(); - - //Mark this as done - m_bRedraw = false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponFrag::SecondaryAttack( void ) -{ - if ( m_bRedraw ) - return; - - if ( !HasPrimaryAmmo() ) - return; - - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - return; - - CBasePlayer *pPlayer = ToBasePlayer( pOwner ); - - if ( pPlayer == NULL ) - return; - - // Note that this is a secondary attack and prepare the grenade attack to pause. - m_AttackPaused = GRENADE_PAUSED_SECONDARY; - SendWeaponAnim( ACT_VM_PULLBACK_LOW ); - - // Don't let weapon idle interfere in the middle of a throw! - m_flTimeWeaponIdle = FLT_MAX; - m_flNextSecondaryAttack = FLT_MAX; - - // If I'm now out of ammo, switch away - if ( !HasPrimaryAmmo() ) - { - pPlayer->SwitchToNextBestWeapon( this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponFrag::PrimaryAttack( void ) -{ - if ( m_bRedraw ) - return; - - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - { - return; - } - - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );; - - if ( !pPlayer ) - return; - - // Note that this is a primary attack and prepare the grenade attack to pause. - m_AttackPaused = GRENADE_PAUSED_PRIMARY; - SendWeaponAnim( ACT_VM_PULLBACK_HIGH ); - - // Put both of these off indefinitely. We do not know how long - // the player will hold the grenade. - m_flTimeWeaponIdle = FLT_MAX; - m_flNextPrimaryAttack = FLT_MAX; - - // If I'm now out of ammo, switch away - if ( !HasPrimaryAmmo() ) - { - pPlayer->SwitchToNextBestWeapon( this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOwner - -//----------------------------------------------------------------------------- -void CWeaponFrag::DecrementAmmo( CBaseCombatCharacter *pOwner ) -{ - pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponFrag::ItemPostFrame( void ) -{ - if( m_fDrawbackFinished ) - { - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if (pOwner) - { - switch( m_AttackPaused ) - { - case GRENADE_PAUSED_PRIMARY: - if( !(pOwner->m_nButtons & IN_ATTACK) ) - { - SendWeaponAnim( ACT_VM_THROW ); - m_fDrawbackFinished = false; - } - break; - - case GRENADE_PAUSED_SECONDARY: - if( !(pOwner->m_nButtons & IN_ATTACK2) ) - { - //See if we're ducking - if ( pOwner->m_nButtons & IN_DUCK ) - { - //Send the weapon animation - SendWeaponAnim( ACT_VM_SECONDARYATTACK ); - } - else - { - //Send the weapon animation - SendWeaponAnim( ACT_VM_HAULBACK ); - } - - m_fDrawbackFinished = false; - } - break; - - default: - break; - } - } - } - - BaseClass::ItemPostFrame(); - - if ( m_bRedraw ) - { - if ( IsViewModelSequenceFinished() ) - { - Reload(); - } - } -} - - // check a throw from vecSrc. If not valid, move the position back along the line to vecEye -void CWeaponFrag::CheckThrowPosition( CBasePlayer *pPlayer, const Vector &vecEye, Vector &vecSrc ) -{ - trace_t tr; - - UTIL_TraceHull( vecEye, vecSrc, -Vector(GRENADE_RADIUS+2,GRENADE_RADIUS+2,GRENADE_RADIUS+2), Vector(GRENADE_RADIUS+2,GRENADE_RADIUS+2,GRENADE_RADIUS+2), - pPlayer->PhysicsSolidMaskForEntity(), pPlayer, pPlayer->GetCollisionGroup(), &tr ); - - if ( tr.DidHit() ) - { - vecSrc = tr.endpos; - } -} - -void DropPrimedFragGrenade( CHL2MP_Player *pPlayer, CBaseCombatWeapon *pGrenade ) -{ - CWeaponFrag *pWeaponFrag = dynamic_cast( pGrenade ); - - if ( pWeaponFrag ) - { - pWeaponFrag->ThrowGrenade( pPlayer ); - pWeaponFrag->DecrementAmmo( pPlayer ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -//----------------------------------------------------------------------------- -void CWeaponFrag::ThrowGrenade( CBasePlayer *pPlayer ) -{ -#ifndef CLIENT_DLL - Vector vecEye = pPlayer->EyePosition(); - Vector vForward, vRight; - - pPlayer->EyeVectors( &vForward, &vRight, NULL ); - Vector vecSrc = vecEye + vForward * 18.0f + vRight * 8.0f; - CheckThrowPosition( pPlayer, vecEye, vecSrc ); -// vForward[0] += 0.1f; - vForward[2] += 0.1f; - - Vector vecThrow; - pPlayer->GetVelocity( &vecThrow, NULL ); - vecThrow += vForward * 1200; - CBaseGrenade *pGrenade = Fraggrenade_Create( vecSrc, vec3_angle, vecThrow, AngularImpulse(600,random->RandomInt(-1200,1200),0), pPlayer, GRENADE_TIMER, false ); - - if ( pGrenade ) - { - if ( pPlayer && pPlayer->m_lifeState != LIFE_ALIVE ) - { - pPlayer->GetVelocity( &vecThrow, NULL ); - - IPhysicsObject *pPhysicsObject = pGrenade->VPhysicsGetObject(); - if ( pPhysicsObject ) - { - pPhysicsObject->SetVelocity( &vecThrow, NULL ); - } - } - - pGrenade->SetDamage( GetHL2MPWpnData().m_iPlayerDamage ); - pGrenade->SetDamageRadius( GRENADE_DAMAGE_RADIUS ); - } -#endif - - m_bRedraw = true; - - WeaponSound( SINGLE ); - - // player "shoot" animation - pPlayer->SetAnimation( PLAYER_ATTACK1 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -//----------------------------------------------------------------------------- -void CWeaponFrag::LobGrenade( CBasePlayer *pPlayer ) -{ -#ifndef CLIENT_DLL - Vector vecEye = pPlayer->EyePosition(); - Vector vForward, vRight; - - pPlayer->EyeVectors( &vForward, &vRight, NULL ); - Vector vecSrc = vecEye + vForward * 18.0f + vRight * 8.0f + Vector( 0, 0, -8 ); - CheckThrowPosition( pPlayer, vecEye, vecSrc ); - - Vector vecThrow; - pPlayer->GetVelocity( &vecThrow, NULL ); - vecThrow += vForward * 350 + Vector( 0, 0, 50 ); - CBaseGrenade *pGrenade = Fraggrenade_Create( vecSrc, vec3_angle, vecThrow, AngularImpulse(200,random->RandomInt(-600,600),0), pPlayer, GRENADE_TIMER, false ); - - if ( pGrenade ) - { - pGrenade->SetDamage( GetHL2MPWpnData().m_iPlayerDamage ); - pGrenade->SetDamageRadius( GRENADE_DAMAGE_RADIUS ); - } -#endif - - WeaponSound( WPN_DOUBLE ); - - // player "shoot" animation - pPlayer->SetAnimation( PLAYER_ATTACK1 ); - - m_bRedraw = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -//----------------------------------------------------------------------------- -void CWeaponFrag::RollGrenade( CBasePlayer *pPlayer ) -{ -#ifndef CLIENT_DLL - // BUGBUG: Hardcoded grenade width of 4 - better not change the model :) - Vector vecSrc; - pPlayer->CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 0.0f ), &vecSrc ); - vecSrc.z += GRENADE_RADIUS; - - Vector vecFacing = pPlayer->BodyDirection2D( ); - // no up/down direction - vecFacing.z = 0; - VectorNormalize( vecFacing ); - trace_t tr; - UTIL_TraceLine( vecSrc, vecSrc - Vector(0,0,16), MASK_PLAYERSOLID, pPlayer, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction != 1.0 ) - { - // compute forward vec parallel to floor plane and roll grenade along that - Vector tangent; - CrossProduct( vecFacing, tr.plane.normal, tangent ); - CrossProduct( tr.plane.normal, tangent, vecFacing ); - } - vecSrc += (vecFacing * 18.0); - CheckThrowPosition( pPlayer, pPlayer->WorldSpaceCenter(), vecSrc ); - - Vector vecThrow; - pPlayer->GetVelocity( &vecThrow, NULL ); - vecThrow += vecFacing * 700; - // put it on its side - QAngle orientation(0,pPlayer->GetLocalAngles().y,-90); - // roll it - AngularImpulse rotSpeed(0,0,720); - CBaseGrenade *pGrenade = Fraggrenade_Create( vecSrc, orientation, vecThrow, rotSpeed, pPlayer, GRENADE_TIMER, false ); - - if ( pGrenade ) - { - pGrenade->SetDamage( GetHL2MPWpnData().m_iPlayerDamage ); - pGrenade->SetDamageRadius( GRENADE_DAMAGE_RADIUS ); - } - -#endif - - WeaponSound( SPECIAL1 ); - - // player "shoot" animation - pPlayer->SetAnimation( PLAYER_ATTACK1 ); - - m_bRedraw = true; -} - diff --git a/game/shared/hl2mp/weapon_hl2mpbase.cpp b/game/shared/hl2mp/weapon_hl2mpbase.cpp deleted file mode 100644 index 4315b8992..000000000 --- a/game/shared/hl2mp/weapon_hl2mpbase.cpp +++ /dev/null @@ -1,330 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "in_buttons.h" -#include "takedamageinfo.h" -#include "ammodef.h" -#include "hl2mp_gamerules.h" - - -#ifdef CLIENT_DLL -extern IVModelInfoClient* modelinfo; -#else -extern IVModelInfo* modelinfo; -#endif - - -#if defined( CLIENT_DLL ) - - #include "vgui/ISurface.h" - #include "vgui_controls/controls.h" - #include "c_hl2mp_player.h" - #include "hud_crosshair.h" - -#else - - #include "hl2mp_player.h" - #include "vphysics/constraints.h" - -#endif - -#include "weapon_hl2mpbase.h" - - -// ----------------------------------------------------------------------------- // -// Global functions. -// ----------------------------------------------------------------------------- // - -bool IsAmmoType( int iAmmoType, const char *pAmmoName ) -{ - return GetAmmoDef()->Index( pAmmoName ) == iAmmoType; -} - -/*static const char * s_WeaponAliasInfo[] = -{ - "none", // WEAPON_NONE = 0, - - //Melee - "shotgun", //WEAPON_AMERKNIFE, - - NULL, // end of list marker -};*/ - - -// ----------------------------------------------------------------------------- // -// CWeaponHL2MPBase tables. -// ----------------------------------------------------------------------------- // - -IMPLEMENT_NETWORKCLASS_ALIASED( WeaponHL2MPBase, DT_WeaponHL2MPBase ) - -BEGIN_NETWORK_TABLE( CWeaponHL2MPBase, DT_WeaponHL2MPBase ) - -#ifdef CLIENT_DLL - -#else - // world weapon models have no aminations - // SendPropExclude( "DT_AnimTimeMustBeFirst", "m_flAnimTime" ), -// SendPropExclude( "DT_BaseAnimating", "m_nSequence" ), -// SendPropExclude( "DT_LocalActiveWeaponData", "m_flTimeWeaponIdle" ), -#endif - -END_NETWORK_TABLE() - -BEGIN_PREDICTION_DATA( CWeaponHL2MPBase ) -END_PREDICTION_DATA() - -LINK_ENTITY_TO_CLASS( weapon_hl2mp_base, CWeaponHL2MPBase ); - - -#ifdef GAME_DLL - - BEGIN_DATADESC( CWeaponHL2MPBase ) - - END_DATADESC() - -#endif - -// ----------------------------------------------------------------------------- // -// CWeaponHL2MPBase implementation. -// ----------------------------------------------------------------------------- // -CWeaponHL2MPBase::CWeaponHL2MPBase() -{ - SetPredictionEligible( true ); - AddSolidFlags( FSOLID_TRIGGER ); // Nothing collides with these but it gets touches. - - m_flNextResetCheckTime = 0.0f; -} - - -bool CWeaponHL2MPBase::IsPredicted() const -{ - return true; -} - -void CWeaponHL2MPBase::WeaponSound( WeaponSound_t sound_type, float soundtime /* = 0.0f */ ) -{ -#ifdef CLIENT_DLL - - // If we have some sounds from the weapon classname.txt file, play a random one of them - const char *shootsound = GetWpnData().aShootSounds[ sound_type ]; - if ( !shootsound || !shootsound[0] ) - return; - - CBroadcastRecipientFilter filter; // this is client side only - if ( !te->CanPredict() ) - return; - - CBaseEntity::EmitSound( filter, GetPlayerOwner()->entindex(), shootsound, &GetPlayerOwner()->GetAbsOrigin() ); -#else - BaseClass::WeaponSound( sound_type, soundtime ); -#endif -} - - -CBasePlayer* CWeaponHL2MPBase::GetPlayerOwner() const -{ - return dynamic_cast< CBasePlayer* >( GetOwner() ); -} - -CHL2MP_Player* CWeaponHL2MPBase::GetHL2MPPlayerOwner() const -{ - return dynamic_cast< CHL2MP_Player* >( GetOwner() ); -} - -#ifdef CLIENT_DLL - -void CWeaponHL2MPBase::OnDataChanged( DataUpdateType_t type ) -{ - BaseClass::OnDataChanged( type ); - - if ( GetPredictable() && !ShouldPredict() ) - ShutdownPredictable(); -} - - -bool CWeaponHL2MPBase::ShouldPredict() -{ - if ( GetOwner() && GetOwner() == C_BasePlayer::GetLocalPlayer() ) - return true; - - return BaseClass::ShouldPredict(); -} - - -#else - -void CWeaponHL2MPBase::Spawn() -{ - BaseClass::Spawn(); - - // Set this here to allow players to shoot dropped weapons - SetCollisionGroup( COLLISION_GROUP_WEAPON ); -} - -void CWeaponHL2MPBase::Materialize( void ) -{ - if ( IsEffectActive( EF_NODRAW ) ) - { - // changing from invisible state to visible. - EmitSound( "AlyxEmp.Charge" ); - - RemoveEffects( EF_NODRAW ); - DoMuzzleFlash(); - } - - if ( HasSpawnFlags( SF_NORESPAWN ) == false ) - { - VPhysicsInitNormal( SOLID_BBOX, GetSolidFlags() | FSOLID_TRIGGER, false ); - SetMoveType( MOVETYPE_VPHYSICS ); - - HL2MPRules()->AddLevelDesignerPlacedObject( this ); - } - - if ( HasSpawnFlags( SF_NORESPAWN ) == false ) - { - if ( GetOriginalSpawnOrigin() == vec3_origin ) - { - m_vOriginalSpawnOrigin = GetAbsOrigin(); - m_vOriginalSpawnAngles = GetAbsAngles(); - } - } - - SetPickupTouch(); - - SetThink (NULL); -} - -int CWeaponHL2MPBase::ObjectCaps() -{ - return BaseClass::ObjectCaps() & ~FCAP_IMPULSE_USE; -} - -#endif - -void CWeaponHL2MPBase::FallInit( void ) -{ -#ifndef CLIENT_DLL - SetModel( GetWorldModel() ); - VPhysicsDestroyObject(); - - if ( HasSpawnFlags( SF_NORESPAWN ) == false ) - { - SetMoveType( MOVETYPE_NONE ); - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_TRIGGER ); - - UTIL_DropToFloor( this, MASK_SOLID ); - } - else - { - if ( !VPhysicsInitNormal( SOLID_BBOX, GetSolidFlags() | FSOLID_TRIGGER, false ) ) - { - SetMoveType( MOVETYPE_NONE ); - SetSolid( SOLID_BBOX ); - AddSolidFlags( FSOLID_TRIGGER ); - } - else - { - #if !defined( CLIENT_DLL ) - // Constrained start? - if ( HasSpawnFlags( SF_WEAPON_START_CONSTRAINED ) ) - { - //Constrain the weapon in place - IPhysicsObject *pReferenceObject, *pAttachedObject; - - pReferenceObject = g_PhysWorldObject; - pAttachedObject = VPhysicsGetObject(); - - if ( pReferenceObject && pAttachedObject ) - { - constraint_fixedparams_t fixed; - fixed.Defaults(); - fixed.InitWithCurrentObjectState( pReferenceObject, pAttachedObject ); - - fixed.constraint.forceLimit = lbs2kg( 10000 ); - fixed.constraint.torqueLimit = lbs2kg( 10000 ); - - IPhysicsConstraint *pConstraint = GetConstraint(); - - pConstraint = physenv->CreateFixedConstraint( pReferenceObject, pAttachedObject, NULL, fixed ); - - pConstraint->SetGameData( (void *) this ); - } - } - #endif //CLIENT_DLL - } - } - - SetPickupTouch(); - - SetThink( &CBaseCombatWeapon::FallThink ); - - SetNextThink( gpGlobals->curtime + 0.1f ); - -#endif -} - -const CHL2MPSWeaponInfo &CWeaponHL2MPBase::GetHL2MPWpnData() const -{ - const FileWeaponInfo_t *pWeaponInfo = &GetWpnData(); - const CHL2MPSWeaponInfo *pHL2MPInfo; - - #ifdef _DEBUG - pHL2MPInfo = dynamic_cast< const CHL2MPSWeaponInfo* >( pWeaponInfo ); - Assert( pHL2MPInfo ); - #else - pHL2MPInfo = static_cast< const CHL2MPSWeaponInfo* >( pWeaponInfo ); - #endif - - return *pHL2MPInfo; -} -void CWeaponHL2MPBase::FireBullets( const FireBulletsInfo_t &info ) -{ - FireBulletsInfo_t modinfo = info; - - modinfo.m_iPlayerDamage = GetHL2MPWpnData().m_iPlayerDamage; - - BaseClass::FireBullets( modinfo ); -} - - -#if defined( CLIENT_DLL ) - -#include "c_te_effect_dispatch.h" - -#define NUM_MUZZLE_FLASH_TYPES 4 - -bool CWeaponHL2MPBase::OnFireEvent( C_BaseViewModel *pViewModel, const Vector& origin, const QAngle& angles, int event, const char *options ) -{ - return BaseClass::OnFireEvent( pViewModel, origin, angles, event, options ); -} - - -void UTIL_ClipPunchAngleOffset( QAngle &in, const QAngle &punch, const QAngle &clip ) -{ - QAngle final = in + punch; - - //Clip each component - for ( int i = 0; i < 3; i++ ) - { - if ( final[i] > clip[i] ) - { - final[i] = clip[i]; - } - else if ( final[i] < -clip[i] ) - { - final[i] = -clip[i]; - } - - //Return the result - in[i] = final[i] - punch[i]; - } -} - -#endif - diff --git a/game/shared/hl2mp/weapon_hl2mpbase.h b/game/shared/hl2mp/weapon_hl2mpbase.h deleted file mode 100644 index a2a3ce5ff..000000000 --- a/game/shared/hl2mp/weapon_hl2mpbase.h +++ /dev/null @@ -1,93 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef WEAPON_HL2MPBASE_H -#define WEAPON_HL2MPBASE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "hl2mp_player_shared.h" -#include "basecombatweapon_shared.h" -#include "hl2mp_weapon_parse.h" - -#if defined( CLIENT_DLL ) - #define CWeaponHL2MPBase C_WeaponHL2MPBase - void UTIL_ClipPunchAngleOffset( QAngle &in, const QAngle &punch, const QAngle &clip ); -#endif - -class CHL2MP_Player; - -// These are the names of the ammo types that go in the CAmmoDefs and that the -// weapon script files reference. - -// Given an ammo type (like from a weapon's GetPrimaryAmmoType()), this compares it -// against the ammo name you specify. -// MIKETODO: this should use indexing instead of searching and strcmp()'ing all the time. -bool IsAmmoType( int iAmmoType, const char *pAmmoName ); - -class CWeaponHL2MPBase : public CBaseCombatWeapon -{ -public: - DECLARE_CLASS( CWeaponHL2MPBase, CBaseCombatWeapon ); - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - - CWeaponHL2MPBase(); - - #ifdef GAME_DLL - DECLARE_DATADESC(); - - void SendReloadSoundEvent( void ); - - void Materialize( void ); - virtual int ObjectCaps( void ); - #endif - - // All predicted weapons need to implement and return true - virtual bool IsPredicted() const; - - CBasePlayer* GetPlayerOwner() const; - CHL2MP_Player* GetHL2MPPlayerOwner() const; - - void WeaponSound( WeaponSound_t sound_type, float soundtime = 0.0f ); - - CHL2MPSWeaponInfo const &GetHL2MPWpnData() const; - - - virtual void FireBullets( const FireBulletsInfo_t &info ); - virtual void FallInit( void ); - -public: - #if defined( CLIENT_DLL ) - - virtual bool ShouldPredict(); - virtual void OnDataChanged( DataUpdateType_t type ); - - virtual bool OnFireEvent( C_BaseViewModel *pViewModel, const Vector& origin, const QAngle& angles, int event, const char *options ); - - #else - - virtual void Spawn(); - - #endif - - float m_flPrevAnimTime; - float m_flNextResetCheckTime; - - Vector GetOriginalSpawnOrigin( void ) { return m_vOriginalSpawnOrigin; } - QAngle GetOriginalSpawnAngles( void ) { return m_vOriginalSpawnAngles; } - -private: - - CWeaponHL2MPBase( const CWeaponHL2MPBase & ); - - Vector m_vOriginalSpawnOrigin; - QAngle m_vOriginalSpawnAngles; -}; - - -#endif // WEAPON_HL2MPBASE_H diff --git a/game/shared/hl2mp/weapon_hl2mpbase_machinegun.cpp b/game/shared/hl2mp/weapon_hl2mpbase_machinegun.cpp deleted file mode 100644 index 52a946db8..000000000 --- a/game/shared/hl2mp/weapon_hl2mpbase_machinegun.cpp +++ /dev/null @@ -1,242 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" - -#if defined( CLIENT_DLL ) - #include "c_hl2mp_player.h" -#else - #include "hl2mp_player.h" -#endif - -#include "weapon_hl2mpbase_machinegun.h" -#include "in_buttons.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -IMPLEMENT_NETWORKCLASS_ALIASED( HL2MPMachineGun, DT_HL2MPMachineGun ) - -BEGIN_NETWORK_TABLE( CHL2MPMachineGun, DT_HL2MPMachineGun ) -END_NETWORK_TABLE() - -BEGIN_PREDICTION_DATA( CHL2MPMachineGun ) -END_PREDICTION_DATA() - -//========================================================= -// >> CHLSelectFireMachineGun -//========================================================= -BEGIN_DATADESC( CHL2MPMachineGun ) - - DEFINE_FIELD( m_nShotsFired, FIELD_INTEGER ), - DEFINE_FIELD( m_flNextSoundTime, FIELD_TIME ), - -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CHL2MPMachineGun::CHL2MPMachineGun( void ) -{ -} - -const Vector &CHL2MPMachineGun::GetBulletSpread( void ) -{ - static Vector cone = VECTOR_CONE_3DEGREES; - return cone; -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CHL2MPMachineGun::PrimaryAttack( void ) -{ - // Only the player fires this way so we can cast - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - if (!pPlayer) - return; - - // Abort here to handle burst and auto fire modes - if ( (UsesClipsForAmmo1() && m_iClip1 == 0) || ( !UsesClipsForAmmo1() && !pPlayer->GetAmmoCount(m_iPrimaryAmmoType) ) ) - return; - - m_nShotsFired++; - - pPlayer->DoMuzzleFlash(); - - // To make the firing framerate independent, we may have to fire more than one bullet here on low-framerate systems, - // especially if the weapon we're firing has a really fast rate of fire. - int iBulletsToFire = 0; - float fireRate = GetFireRate(); - - while ( m_flNextPrimaryAttack <= gpGlobals->curtime ) - { - // MUST call sound before removing a round from the clip of a CHLMachineGun - WeaponSound(SINGLE, m_flNextPrimaryAttack); - m_flNextPrimaryAttack = m_flNextPrimaryAttack + fireRate; - iBulletsToFire++; - } - - // Make sure we don't fire more than the amount in the clip, if this weapon uses clips - if ( UsesClipsForAmmo1() ) - { - if ( iBulletsToFire > m_iClip1 ) - iBulletsToFire = m_iClip1; - m_iClip1 -= iBulletsToFire; - } - - CHL2MP_Player *pHL2MPPlayer = ToHL2MPPlayer( pPlayer ); - - // Fire the bullets - FireBulletsInfo_t info; - info.m_iShots = iBulletsToFire; - info.m_vecSrc = pHL2MPPlayer->Weapon_ShootPosition( ); - info.m_vecDirShooting = pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES ); - info.m_vecSpread = pHL2MPPlayer->GetAttackSpread( this ); - info.m_flDistance = MAX_TRACE_LENGTH; - info.m_iAmmoType = m_iPrimaryAmmoType; - info.m_iTracerFreq = 2; - FireBullets( info ); - - //Factor in the view kick - AddViewKick(); - - if (!m_iClip1 && pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0) - { - // HEV suit - indicate out of ammo condition - pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); - } - - SendWeaponAnim( GetPrimaryAttackActivity() ); - pPlayer->SetAnimation( PLAYER_ATTACK1 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &info - -//----------------------------------------------------------------------------- -void CHL2MPMachineGun::FireBullets( const FireBulletsInfo_t &info ) -{ - if(CBasePlayer *pPlayer = ToBasePlayer ( GetOwner() ) ) - { - pPlayer->FireBullets(info); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHL2MPMachineGun::DoMachineGunKick( CBasePlayer *pPlayer, float dampEasy, float maxVerticleKickAngle, float fireDurationTime, float slideLimitTime ) -{ - #define KICK_MIN_X 0.2f //Degrees - #define KICK_MIN_Y 0.2f //Degrees - #define KICK_MIN_Z 0.1f //Degrees - - QAngle vecScratch; - int iSeed = CBaseEntity::GetPredictionRandomSeed() & 255; - - //Find how far into our accuracy degradation we are - float duration = ( fireDurationTime > slideLimitTime ) ? slideLimitTime : fireDurationTime; - float kickPerc = duration / slideLimitTime; - - // do this to get a hard discontinuity, clear out anything under 10 degrees punch - pPlayer->ViewPunchReset( 10 ); - - //Apply this to the view angles as well - vecScratch.x = -( KICK_MIN_X + ( maxVerticleKickAngle * kickPerc ) ); - vecScratch.y = -( KICK_MIN_Y + ( maxVerticleKickAngle * kickPerc ) ) / 3; - vecScratch.z = KICK_MIN_Z + ( maxVerticleKickAngle * kickPerc ) / 8; - - RandomSeed( iSeed ); - - //Wibble left and right - if ( RandomInt( -1, 1 ) >= 0 ) - vecScratch.y *= -1; - - iSeed++; - - //Wobble up and down - if ( RandomInt( -1, 1 ) >= 0 ) - vecScratch.z *= -1; - - //Clip this to our desired min/max - UTIL_ClipPunchAngleOffset( vecScratch, pPlayer->m_Local.m_vecPunchAngle, QAngle( 24.0f, 3.0f, 1.0f ) ); - - //Add it to the view punch - // NOTE: 0.5 is just tuned to match the old effect before the punch became simulated - pPlayer->ViewPunch( vecScratch * 0.5 ); -} - -//----------------------------------------------------------------------------- -// Purpose: Reset our shots fired -//----------------------------------------------------------------------------- -bool CHL2MPMachineGun::Deploy( void ) -{ - m_nShotsFired = 0; - - return BaseClass::Deploy(); -} - - - -//----------------------------------------------------------------------------- -// Purpose: Make enough sound events to fill the estimated think interval -// returns: number of shots needed -//----------------------------------------------------------------------------- -int CHL2MPMachineGun::WeaponSoundRealtime( WeaponSound_t shoot_type ) -{ - int numBullets = 0; - - // ran out of time, clamp to current - if (m_flNextSoundTime < gpGlobals->curtime) - { - m_flNextSoundTime = gpGlobals->curtime; - } - - // make enough sound events to fill up the next estimated think interval - float dt = clamp( m_flAnimTime - m_flPrevAnimTime, 0, 0.2 ); - if (m_flNextSoundTime < gpGlobals->curtime + dt) - { - WeaponSound( SINGLE_NPC, m_flNextSoundTime ); - m_flNextSoundTime += GetFireRate(); - numBullets++; - } - if (m_flNextSoundTime < gpGlobals->curtime + dt) - { - WeaponSound( SINGLE_NPC, m_flNextSoundTime ); - m_flNextSoundTime += GetFireRate(); - numBullets++; - } - - return numBullets; -} - - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHL2MPMachineGun::ItemPostFrame( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - // Debounce the recoiling counter - if ( ( pOwner->m_nButtons & IN_ATTACK ) == false ) - { - m_nShotsFired = 0; - } - - BaseClass::ItemPostFrame(); -} - - diff --git a/game/shared/hl2mp/weapon_hl2mpbase_machinegun.h b/game/shared/hl2mp/weapon_hl2mpbase_machinegun.h deleted file mode 100644 index 74645ad4f..000000000 --- a/game/shared/hl2mp/weapon_hl2mpbase_machinegun.h +++ /dev/null @@ -1,58 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "weapon_hl2mpbase.h" - -#ifndef BASEHLCOMBATWEAPON_H -#define BASEHLCOMBATWEAPON_H -#ifdef _WIN32 -#pragma once -#endif - -#if defined( CLIENT_DLL ) - #define CHL2MPMachineGun C_HL2MPMachineGun -#endif - -//========================================================= -// Machine gun base class -//========================================================= -class CHL2MPMachineGun : public CWeaponHL2MPBase -{ -public: - DECLARE_CLASS( CHL2MPMachineGun, CWeaponHL2MPBase ); - DECLARE_DATADESC(); - - CHL2MPMachineGun(); - - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - - void PrimaryAttack( void ); - - // Default calls through to m_hOwner, but plasma weapons can override and shoot projectiles here. - virtual void ItemPostFrame( void ); - virtual void FireBullets( const FireBulletsInfo_t &info ); - virtual bool Deploy( void ); - - virtual const Vector &GetBulletSpread( void ); - - int WeaponSoundRealtime( WeaponSound_t shoot_type ); - - // utility function - static void DoMachineGunKick( CBasePlayer *pPlayer, float dampEasy, float maxVerticleKickAngle, float fireDurationTime, float slideLimitTime ); - -private: - - CHL2MPMachineGun( const CHL2MPMachineGun & ); - -protected: - - int m_nShotsFired; // Number of consecutive shots fired - - float m_flNextSoundTime; // real-time clock of when to make next sound -}; - -#endif // BASEHLCOMBATWEAPON_H diff --git a/game/shared/hl2mp/weapon_hl2mpbasebasebludgeon.cpp b/game/shared/hl2mp/weapon_hl2mpbasebasebludgeon.cpp deleted file mode 100644 index 136b29204..000000000 --- a/game/shared/hl2mp/weapon_hl2mpbasebasebludgeon.cpp +++ /dev/null @@ -1,363 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include "cbase.h" -#include "weapon_hl2mpbasebasebludgeon.h" -#include "gamerules.h" -#include "ammodef.h" -#include "mathlib/mathlib.h" -#include "in_buttons.h" -#include "animation.h" - -#if defined( CLIENT_DLL ) - #include "c_hl2mp_player.h" -#else - #include "hl2mp_player.h" - #include "ndebugoverlay.h" - #include "te_effect_dispatch.h" - #include "ilagcompensationmanager.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -IMPLEMENT_NETWORKCLASS_ALIASED( BaseHL2MPBludgeonWeapon, DT_BaseHL2MPBludgeonWeapon ) - -BEGIN_NETWORK_TABLE( CBaseHL2MPBludgeonWeapon, DT_BaseHL2MPBludgeonWeapon ) -END_NETWORK_TABLE() - -BEGIN_PREDICTION_DATA( CBaseHL2MPBludgeonWeapon ) -END_PREDICTION_DATA() - -#define BLUDGEON_HULL_DIM 16 - -static const Vector g_bludgeonMins(-BLUDGEON_HULL_DIM,-BLUDGEON_HULL_DIM,-BLUDGEON_HULL_DIM); -static const Vector g_bludgeonMaxs(BLUDGEON_HULL_DIM,BLUDGEON_HULL_DIM,BLUDGEON_HULL_DIM); - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CBaseHL2MPBludgeonWeapon::CBaseHL2MPBludgeonWeapon() -{ - m_bFiresUnderwater = true; -} - -//----------------------------------------------------------------------------- -// Purpose: Spawn the weapon -//----------------------------------------------------------------------------- -void CBaseHL2MPBludgeonWeapon::Spawn( void ) -{ - m_fMinRange1 = 0; - m_fMinRange2 = 0; - m_fMaxRange1 = 64; - m_fMaxRange2 = 64; - //Call base class first - BaseClass::Spawn(); -} - -//----------------------------------------------------------------------------- -// Purpose: Precache the weapon -//----------------------------------------------------------------------------- -void CBaseHL2MPBludgeonWeapon::Precache( void ) -{ - //Call base class first - BaseClass::Precache(); -} - -//------------------------------------------------------------------------------ -// Purpose : Update weapon -//------------------------------------------------------------------------------ -void CBaseHL2MPBludgeonWeapon::ItemPostFrame( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - if ( (pOwner->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime) ) - { - PrimaryAttack(); - } - else if ( (pOwner->m_nButtons & IN_ATTACK2) && (m_flNextSecondaryAttack <= gpGlobals->curtime) ) - { - SecondaryAttack(); - } - else - { - WeaponIdle(); - return; - } -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBaseHL2MPBludgeonWeapon::PrimaryAttack() -{ - -#ifndef CLIENT_DLL - CHL2MP_Player *pPlayer = ToHL2MPPlayer( GetPlayerOwner() ); - // Move other players back to history positions based on local player's lag - lagcompensation->StartLagCompensation( pPlayer, pPlayer->GetCurrentCommand() ); -#endif - Swing( false ); -#ifndef CLIENT_DLL - // Move other players back to history positions based on local player's lag - lagcompensation->FinishLagCompensation( pPlayer ); -#endif - -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -void CBaseHL2MPBludgeonWeapon::SecondaryAttack() -{ - Swing( true ); -} - - -//------------------------------------------------------------------------------ -// Purpose: Implement impact function -//------------------------------------------------------------------------------ -void CBaseHL2MPBludgeonWeapon::Hit( trace_t &traceHit, Activity nHitActivity ) -{ - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - //Do view kick -// AddViewKick(); - - CBaseEntity *pHitEntity = traceHit.m_pEnt; - - //Apply damage to a hit target - if ( pHitEntity != NULL ) - { - Vector hitDirection; - pPlayer->EyeVectors( &hitDirection, NULL, NULL ); - VectorNormalize( hitDirection ); - -#ifndef CLIENT_DLL - CTakeDamageInfo info( GetOwner(), GetOwner(), GetDamageForActivity( nHitActivity ), DMG_CLUB ); - - if( pPlayer && pHitEntity->IsNPC() ) - { - // If bonking an NPC, adjust damage. - info.AdjustPlayerDamageInflictedForSkillLevel(); - } - - CalculateMeleeDamageForce( &info, hitDirection, traceHit.endpos ); - - pHitEntity->DispatchTraceAttack( info, hitDirection, &traceHit ); - ApplyMultiDamage(); - - // Now hit all triggers along the ray that... - TraceAttackToTriggers( info, traceHit.startpos, traceHit.endpos, hitDirection ); -#endif - WeaponSound( MELEE_HIT ); - } - - // Apply an impact effect - ImpactEffect( traceHit ); -} - -Activity CBaseHL2MPBludgeonWeapon::ChooseIntersectionPointAndActivity( trace_t &hitTrace, const Vector &mins, const Vector &maxs, CBasePlayer *pOwner ) -{ - int i, j, k; - float distance; - const float *minmaxs[2] = {mins.Base(), maxs.Base()}; - trace_t tmpTrace; - Vector vecHullEnd = hitTrace.endpos; - Vector vecEnd; - - distance = 1e6f; - Vector vecSrc = hitTrace.startpos; - - vecHullEnd = vecSrc + ((vecHullEnd - vecSrc)*2); - UTIL_TraceLine( vecSrc, vecHullEnd, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &tmpTrace ); - if ( tmpTrace.fraction == 1.0 ) - { - for ( i = 0; i < 2; i++ ) - { - for ( j = 0; j < 2; j++ ) - { - for ( k = 0; k < 2; k++ ) - { - vecEnd.x = vecHullEnd.x + minmaxs[i][0]; - vecEnd.y = vecHullEnd.y + minmaxs[j][1]; - vecEnd.z = vecHullEnd.z + minmaxs[k][2]; - - UTIL_TraceLine( vecSrc, vecEnd, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &tmpTrace ); - if ( tmpTrace.fraction < 1.0 ) - { - float thisDistance = (tmpTrace.endpos - vecSrc).Length(); - if ( thisDistance < distance ) - { - hitTrace = tmpTrace; - distance = thisDistance; - } - } - } - } - } - } - else - { - hitTrace = tmpTrace; - } - - - return ACT_VM_HITCENTER; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &traceHit - -//----------------------------------------------------------------------------- -bool CBaseHL2MPBludgeonWeapon::ImpactWater( const Vector &start, const Vector &end ) -{ - //FIXME: This doesn't handle the case of trying to splash while being underwater, but that's not going to look good - // right now anyway... - - // We must start outside the water - if ( UTIL_PointContents( start ) & (CONTENTS_WATER|CONTENTS_SLIME)) - return false; - - // We must end inside of water - if ( !(UTIL_PointContents( end ) & (CONTENTS_WATER|CONTENTS_SLIME))) - return false; - - trace_t waterTrace; - - UTIL_TraceLine( start, end, (CONTENTS_WATER|CONTENTS_SLIME), GetOwner(), COLLISION_GROUP_NONE, &waterTrace ); - - if ( waterTrace.fraction < 1.0f ) - { -#ifndef CLIENT_DLL - CEffectData data; - - data.m_fFlags = 0; - data.m_vOrigin = waterTrace.endpos; - data.m_vNormal = waterTrace.plane.normal; - data.m_flScale = 8.0f; - - // See if we hit slime - if ( waterTrace.contents & CONTENTS_SLIME ) - { - data.m_fFlags |= FX_WATER_IN_SLIME; - } - - DispatchEffect( "watersplash", data ); -#endif - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseHL2MPBludgeonWeapon::ImpactEffect( trace_t &traceHit ) -{ - // See if we hit water (we don't do the other impact effects in this case) - if ( ImpactWater( traceHit.startpos, traceHit.endpos ) ) - return; - - //FIXME: need new decals - UTIL_ImpactTrace( &traceHit, DMG_CLUB ); -} - - -//------------------------------------------------------------------------------ -// Purpose : Starts the swing of the weapon and determines the animation -// Input : bIsSecondary - is this a secondary attack? -//------------------------------------------------------------------------------ -void CBaseHL2MPBludgeonWeapon::Swing( int bIsSecondary ) -{ - trace_t traceHit; - - // Try a ray - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( !pOwner ) - return; - - Vector swingStart = pOwner->Weapon_ShootPosition( ); - Vector forward; - - pOwner->EyeVectors( &forward, NULL, NULL ); - - Vector swingEnd = swingStart + forward * GetRange(); - UTIL_TraceLine( swingStart, swingEnd, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &traceHit ); - Activity nHitActivity = ACT_VM_HITCENTER; - -#ifndef CLIENT_DLL - // Like bullets, bludgeon traces have to trace against triggers. - CTakeDamageInfo triggerInfo( GetOwner(), GetOwner(), GetDamageForActivity( nHitActivity ), DMG_CLUB ); - TraceAttackToTriggers( triggerInfo, traceHit.startpos, traceHit.endpos, vec3_origin ); -#endif - - if ( traceHit.fraction == 1.0 ) - { - float bludgeonHullRadius = 1.732f * BLUDGEON_HULL_DIM; // hull is +/- 16, so use cuberoot of 2 to determine how big the hull is from center to the corner point - - // Back off by hull "radius" - swingEnd -= forward * bludgeonHullRadius; - - UTIL_TraceHull( swingStart, swingEnd, g_bludgeonMins, g_bludgeonMaxs, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &traceHit ); - if ( traceHit.fraction < 1.0 && traceHit.m_pEnt ) - { - Vector vecToTarget = traceHit.m_pEnt->GetAbsOrigin() - swingStart; - VectorNormalize( vecToTarget ); - - float dot = vecToTarget.Dot( forward ); - - // YWB: Make sure they are sort of facing the guy at least... - if ( dot < 0.70721f ) - { - // Force amiss - traceHit.fraction = 1.0f; - } - else - { - nHitActivity = ChooseIntersectionPointAndActivity( traceHit, g_bludgeonMins, g_bludgeonMaxs, pOwner ); - } - } - } - - WeaponSound( SINGLE ); - - // ------------------------- - // Miss - // ------------------------- - if ( traceHit.fraction == 1.0f ) - { - nHitActivity = bIsSecondary ? ACT_VM_MISSCENTER2 : ACT_VM_MISSCENTER; - - // We want to test the first swing again - Vector testEnd = swingStart + forward * GetRange(); - - // See if we happened to hit water - ImpactWater( swingStart, testEnd ); - } - else - { - Hit( traceHit, nHitActivity ); - } - - // Send the anim - SendWeaponAnim( nHitActivity ); - - pOwner->SetAnimation( PLAYER_ATTACK1 ); - - //Setup our next attack times - m_flNextPrimaryAttack = gpGlobals->curtime + GetFireRate(); - m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration(); -} diff --git a/game/shared/hl2mp/weapon_hl2mpbasebasebludgeon.h b/game/shared/hl2mp/weapon_hl2mpbasebasebludgeon.h deleted file mode 100644 index b4b3301e9..000000000 --- a/game/shared/hl2mp/weapon_hl2mpbasebasebludgeon.h +++ /dev/null @@ -1,66 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: The class from which all bludgeon melee -// weapons are derived. -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#include "weapon_hl2mpbasehlmpcombatweapon.h" - -#ifndef BASEBLUDGEONWEAPON_H -#define BASEBLUDGEONWEAPON_H - -#ifdef _WIN32 -#pragma once -#endif - - -#if defined( CLIENT_DLL ) -#define CBaseHL2MPBludgeonWeapon C_BaseHL2MPBludgeonWeapon -#endif - -//========================================================= -// CBaseHLBludgeonWeapon -//========================================================= -class CBaseHL2MPBludgeonWeapon : public CBaseHL2MPCombatWeapon -{ - DECLARE_CLASS( CBaseHL2MPBludgeonWeapon, CBaseHL2MPCombatWeapon ); -public: - CBaseHL2MPBludgeonWeapon(); - - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - - virtual void Spawn( void ); - virtual void Precache( void ); - - //Attack functions - virtual void PrimaryAttack( void ); - virtual void SecondaryAttack( void ); - - virtual void ItemPostFrame( void ); - - //Functions to select animation sequences - virtual Activity GetPrimaryAttackActivity( void ) { return ACT_VM_HITCENTER; } - virtual Activity GetSecondaryAttackActivity( void ) { return ACT_VM_HITCENTER2; } - - virtual float GetFireRate( void ) { return 0.2f; } - virtual float GetRange( void ) { return 32.0f; } - virtual float GetDamageForActivity( Activity hitActivity ) { return 1.0f; } - - CBaseHL2MPBludgeonWeapon( const CBaseHL2MPBludgeonWeapon & ); - -protected: - virtual void ImpactEffect( trace_t &trace ); - -private: - bool ImpactWater( const Vector &start, const Vector &end ); - void Swing( int bIsSecondary ); - void Hit( trace_t &traceHit, Activity nHitActivity ); - Activity ChooseIntersectionPointAndActivity( trace_t &hitTrace, const Vector &mins, const Vector &maxs, CBasePlayer *pOwner ); -}; - -#endif diff --git a/game/shared/hl2mp/weapon_hl2mpbasehlmpcombatweapon.cpp b/game/shared/hl2mp/weapon_hl2mpbasehlmpcombatweapon.cpp deleted file mode 100644 index b69e314a0..000000000 --- a/game/shared/hl2mp/weapon_hl2mpbasehlmpcombatweapon.cpp +++ /dev/null @@ -1,416 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "weapon_hl2mpbasehlmpcombatweapon.h" - -#include "hl2mp_player_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -LINK_ENTITY_TO_CLASS( basehl2mpcombatweapon, CBaseHL2MPCombatWeapon ); - -IMPLEMENT_NETWORKCLASS_ALIASED( BaseHL2MPCombatWeapon , DT_BaseHL2MPCombatWeapon ) - -BEGIN_NETWORK_TABLE( CBaseHL2MPCombatWeapon , DT_BaseHL2MPCombatWeapon ) -#if !defined( CLIENT_DLL ) -// SendPropInt( SENDINFO( m_bReflectViewModelAnimations ), 1, SPROP_UNSIGNED ), -#else -// RecvPropInt( RECVINFO( m_bReflectViewModelAnimations ) ), -#endif -END_NETWORK_TABLE() - - -#if !defined( CLIENT_DLL ) - -#include "globalstate.h" - -//--------------------------------------------------------- -// Save/Restore -//--------------------------------------------------------- -BEGIN_DATADESC( CBaseHL2MPCombatWeapon ) - - DEFINE_FIELD( m_bLowered, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flRaiseTime, FIELD_TIME ), - DEFINE_FIELD( m_flHolsterTime, FIELD_TIME ), - -END_DATADESC() - -#endif - -BEGIN_PREDICTION_DATA( CBaseHL2MPCombatWeapon ) -END_PREDICTION_DATA() - -extern ConVar sk_auto_reload_time; - -CBaseHL2MPCombatWeapon::CBaseHL2MPCombatWeapon( void ) -{ - -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseHL2MPCombatWeapon::ItemHolsterFrame( void ) -{ - BaseClass::ItemHolsterFrame(); - - // Must be player held - if ( GetOwner() && GetOwner()->IsPlayer() == false ) - return; - - // We can't be active - if ( GetOwner()->GetActiveWeapon() == this ) - return; - - // If it's been longer than three seconds, reload - if ( ( gpGlobals->curtime - m_flHolsterTime ) > sk_auto_reload_time.GetFloat() ) - { - // Just load the clip with no animations - FinishReload(); - m_flHolsterTime = gpGlobals->curtime; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Drops the weapon into a lowered pose -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseHL2MPCombatWeapon::Lower( void ) -{ - //Don't bother if we don't have the animation - if ( SelectWeightedSequence( ACT_VM_IDLE_LOWERED ) == ACTIVITY_NOT_AVAILABLE ) - return false; - - m_bLowered = true; - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Brings the weapon up to the ready position -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseHL2MPCombatWeapon::Ready( void ) -{ - //Don't bother if we don't have the animation - if ( SelectWeightedSequence( ACT_VM_LOWERED_TO_IDLE ) == ACTIVITY_NOT_AVAILABLE ) - return false; - - m_bLowered = false; - m_flRaiseTime = gpGlobals->curtime + 0.5f; - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseHL2MPCombatWeapon::Deploy( void ) -{ - // If we should be lowered, deploy in the lowered position - // We have to ask the player if the last time it checked, the weapon was lowered - if ( GetOwner() && GetOwner()->IsPlayer() ) - { - CHL2MP_Player *pPlayer = assert_cast( GetOwner() ); - if ( pPlayer->IsWeaponLowered() ) - { - if ( SelectWeightedSequence( ACT_VM_IDLE_LOWERED ) != ACTIVITY_NOT_AVAILABLE ) - { - if ( DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), ACT_VM_IDLE_LOWERED, (char*)GetAnimPrefix() ) ) - { - m_bLowered = true; - - // Stomp the next attack time to fix the fact that the lower idles are long - pPlayer->SetNextAttack( gpGlobals->curtime + 1.0 ); - m_flNextPrimaryAttack = gpGlobals->curtime + 1.0; - m_flNextSecondaryAttack = gpGlobals->curtime + 1.0; - return true; - } - } - } - } - - m_bLowered = false; - return BaseClass::Deploy(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseHL2MPCombatWeapon::Holster( CBaseCombatWeapon *pSwitchingTo ) -{ - if ( BaseClass::Holster( pSwitchingTo ) ) - { - SetWeaponVisible( false ); - m_flHolsterTime = gpGlobals->curtime; - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseHL2MPCombatWeapon::WeaponShouldBeLowered( void ) -{ - // Can't be in the middle of another animation - if ( GetIdealActivity() != ACT_VM_IDLE_LOWERED && GetIdealActivity() != ACT_VM_IDLE && - GetIdealActivity() != ACT_VM_IDLE_TO_LOWERED && GetIdealActivity() != ACT_VM_LOWERED_TO_IDLE ) - return false; - - if ( m_bLowered ) - return true; - -#if !defined( CLIENT_DLL ) - - if ( GlobalEntity_GetState( "friendly_encounter" ) == GLOBAL_ON ) - return true; - -#endif - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Allows the weapon to choose proper weapon idle animation -//----------------------------------------------------------------------------- -void CBaseHL2MPCombatWeapon::WeaponIdle( void ) -{ - //See if we should idle high or low - if ( WeaponShouldBeLowered() ) - { - // Move to lowered position if we're not there yet - if ( GetActivity() != ACT_VM_IDLE_LOWERED && GetActivity() != ACT_VM_IDLE_TO_LOWERED - && GetActivity() != ACT_TRANSITION ) - { - SendWeaponAnim( ACT_VM_IDLE_LOWERED ); - } - else if ( HasWeaponIdleTimeElapsed() ) - { - // Keep idling low - SendWeaponAnim( ACT_VM_IDLE_LOWERED ); - } - } - else - { - // See if we need to raise immediately - if ( m_flRaiseTime < gpGlobals->curtime && GetActivity() == ACT_VM_IDLE_LOWERED ) - { - SendWeaponAnim( ACT_VM_IDLE ); - } - else if ( HasWeaponIdleTimeElapsed() ) - { - SendWeaponAnim( ACT_VM_IDLE ); - } - } -} - -#if defined( CLIENT_DLL ) - -#define HL2_BOB_CYCLE_MIN 1.0f -#define HL2_BOB_CYCLE_MAX 0.45f -#define HL2_BOB 0.002f -#define HL2_BOB_UP 0.5f - -extern float g_lateralBob; -extern float g_verticalBob; - -static ConVar cl_bobcycle( "cl_bobcycle","0.8" ); -static ConVar cl_bob( "cl_bob","0.002" ); -static ConVar cl_bobup( "cl_bobup","0.5" ); - -// Register these cvars if needed for easy tweaking -static ConVar v_iyaw_cycle( "v_iyaw_cycle", "2", FCVAR_REPLICATED | FCVAR_CHEAT ); -static ConVar v_iroll_cycle( "v_iroll_cycle", "0.5", FCVAR_REPLICATED | FCVAR_CHEAT ); -static ConVar v_ipitch_cycle( "v_ipitch_cycle", "1", FCVAR_REPLICATED | FCVAR_CHEAT ); -static ConVar v_iyaw_level( "v_iyaw_level", "0.3", FCVAR_REPLICATED | FCVAR_CHEAT ); -static ConVar v_iroll_level( "v_iroll_level", "0.1", FCVAR_REPLICATED | FCVAR_CHEAT ); -static ConVar v_ipitch_level( "v_ipitch_level", "0.3", FCVAR_REPLICATED | FCVAR_CHEAT ); - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CBaseHL2MPCombatWeapon::CalcViewmodelBob( void ) -{ - static float bobtime; - static float lastbobtime; - float cycle; - - CBasePlayer *player = ToBasePlayer( GetOwner() ); - //Assert( player ); - - //NOTENOTE: For now, let this cycle continue when in the air, because it snaps badly without it - - if ( ( !gpGlobals->frametime ) || ( player == NULL ) ) - { - //NOTENOTE: We don't use this return value in our case (need to restructure the calculation function setup!) - return 0.0f;// just use old value - } - - //Find the speed of the player - float speed = player->GetLocalVelocity().Length2D(); - - //FIXME: This maximum speed value must come from the server. - // MaxSpeed() is not sufficient for dealing with sprinting - jdw - - speed = clamp( speed, -320, 320 ); - - float bob_offset = RemapVal( speed, 0, 320, 0.0f, 1.0f ); - - bobtime += ( gpGlobals->curtime - lastbobtime ) * bob_offset; - lastbobtime = gpGlobals->curtime; - - //Calculate the vertical bob - cycle = bobtime - (int)(bobtime/HL2_BOB_CYCLE_MAX)*HL2_BOB_CYCLE_MAX; - cycle /= HL2_BOB_CYCLE_MAX; - - if ( cycle < HL2_BOB_UP ) - { - cycle = M_PI * cycle / HL2_BOB_UP; - } - else - { - cycle = M_PI + M_PI*(cycle-HL2_BOB_UP)/(1.0 - HL2_BOB_UP); - } - - g_verticalBob = speed*0.005f; - g_verticalBob = g_verticalBob*0.3 + g_verticalBob*0.7*sin(cycle); - - g_verticalBob = clamp( g_verticalBob, -7.0f, 4.0f ); - - //Calculate the lateral bob - cycle = bobtime - (int)(bobtime/HL2_BOB_CYCLE_MAX*2)*HL2_BOB_CYCLE_MAX*2; - cycle /= HL2_BOB_CYCLE_MAX*2; - - if ( cycle < HL2_BOB_UP ) - { - cycle = M_PI * cycle / HL2_BOB_UP; - } - else - { - cycle = M_PI + M_PI*(cycle-HL2_BOB_UP)/(1.0 - HL2_BOB_UP); - } - - g_lateralBob = speed*0.005f; - g_lateralBob = g_lateralBob*0.3 + g_lateralBob*0.7*sin(cycle); - g_lateralBob = clamp( g_lateralBob, -7.0f, 4.0f ); - - //NOTENOTE: We don't use this return value in our case (need to restructure the calculation function setup!) - return 0.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &origin - -// &angles - -// viewmodelindex - -//----------------------------------------------------------------------------- -void CBaseHL2MPCombatWeapon::AddViewmodelBob( CBaseViewModel *viewmodel, Vector &origin, QAngle &angles ) -{ - Vector forward, right; - AngleVectors( angles, &forward, &right, NULL ); - - CalcViewmodelBob(); - - // Apply bob, but scaled down to 40% - VectorMA( origin, g_verticalBob * 0.1f, forward, origin ); - - // Z bob a bit more - origin[2] += g_verticalBob * 0.1f; - - // bob the angles - angles[ ROLL ] += g_verticalBob * 0.5f; - angles[ PITCH ] -= g_verticalBob * 0.4f; - - angles[ YAW ] -= g_lateralBob * 0.3f; - - VectorMA( origin, g_lateralBob * 0.8f, right, origin ); -} - -//----------------------------------------------------------------------------- -Vector CBaseHL2MPCombatWeapon::GetBulletSpread( WeaponProficiency_t proficiency ) -{ - return BaseClass::GetBulletSpread( proficiency ); -} - -//----------------------------------------------------------------------------- -float CBaseHL2MPCombatWeapon::GetSpreadBias( WeaponProficiency_t proficiency ) -{ - return BaseClass::GetSpreadBias( proficiency ); -} -//----------------------------------------------------------------------------- - -const WeaponProficiencyInfo_t *CBaseHL2MPCombatWeapon::GetProficiencyValues() -{ - return NULL; -} - -#else - -// Server stubs -float CBaseHL2MPCombatWeapon::CalcViewmodelBob( void ) -{ - return 0.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &origin - -// &angles - -// viewmodelindex - -//----------------------------------------------------------------------------- -void CBaseHL2MPCombatWeapon::AddViewmodelBob( CBaseViewModel *viewmodel, Vector &origin, QAngle &angles ) -{ -} - - -//----------------------------------------------------------------------------- -Vector CBaseHL2MPCombatWeapon::GetBulletSpread( WeaponProficiency_t proficiency ) -{ - Vector baseSpread = BaseClass::GetBulletSpread( proficiency ); - - const WeaponProficiencyInfo_t *pProficiencyValues = GetProficiencyValues(); - float flModifier = (pProficiencyValues)[ proficiency ].spreadscale; - return ( baseSpread * flModifier ); -} - -//----------------------------------------------------------------------------- -float CBaseHL2MPCombatWeapon::GetSpreadBias( WeaponProficiency_t proficiency ) -{ - const WeaponProficiencyInfo_t *pProficiencyValues = GetProficiencyValues(); - return (pProficiencyValues)[ proficiency ].bias; -} - -//----------------------------------------------------------------------------- -const WeaponProficiencyInfo_t *CBaseHL2MPCombatWeapon::GetProficiencyValues() -{ - return GetDefaultProficiencyValues(); -} - -//----------------------------------------------------------------------------- -const WeaponProficiencyInfo_t *CBaseHL2MPCombatWeapon::GetDefaultProficiencyValues() -{ - // Weapon proficiency table. Keep this in sync with WeaponProficiency_t enum in the header!! - static WeaponProficiencyInfo_t g_BaseWeaponProficiencyTable[] = - { - { 2.50, 1.0 }, - { 2.00, 1.0 }, - { 1.50, 1.0 }, - { 1.25, 1.0 }, - { 1.00, 1.0 }, - }; - - COMPILE_TIME_ASSERT( ARRAYSIZE(g_BaseWeaponProficiencyTable) == WEAPON_PROFICIENCY_PERFECT + 1); - - return g_BaseWeaponProficiencyTable; -} - -#endif diff --git a/game/shared/hl2mp/weapon_hl2mpbasehlmpcombatweapon.h b/game/shared/hl2mp/weapon_hl2mpbasehlmpcombatweapon.h deleted file mode 100644 index a5f5c85cf..000000000 --- a/game/shared/hl2mp/weapon_hl2mpbasehlmpcombatweapon.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef WEAPON_BASEHL2MPCOMBATWEAPON_SHARED_H -#define WEAPON_BASEHL2MPCOMBATWEAPON_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - -#ifdef CLIENT_DLL - #include "c_hl2mp_player.h" -#else - #include "hl2mp_player.h" -#endif - -#include "weapon_hl2mpbase.h" - -#if defined( CLIENT_DLL ) -#define CBaseHL2MPCombatWeapon C_BaseHL2MPCombatWeapon -#endif - -class CBaseHL2MPCombatWeapon : public CWeaponHL2MPBase -{ -#if !defined( CLIENT_DLL ) - DECLARE_DATADESC(); -#endif - - DECLARE_CLASS( CBaseHL2MPCombatWeapon, CWeaponHL2MPBase ); -public: - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - - CBaseHL2MPCombatWeapon(); - - virtual bool WeaponShouldBeLowered( void ); - - virtual bool Ready( void ); - virtual bool Lower( void ); - virtual bool Deploy( void ); - virtual bool Holster( CBaseCombatWeapon *pSwitchingTo ); - virtual void WeaponIdle( void ); - - virtual void AddViewmodelBob( CBaseViewModel *viewmodel, Vector &origin, QAngle &angles ); - virtual float CalcViewmodelBob( void ); - - virtual Vector GetBulletSpread( WeaponProficiency_t proficiency ); - virtual float GetSpreadBias( WeaponProficiency_t proficiency ); - - virtual const WeaponProficiencyInfo_t *GetProficiencyValues(); - static const WeaponProficiencyInfo_t *GetDefaultProficiencyValues(); - - virtual void ItemHolsterFrame( void ); - -protected: - - bool m_bLowered; // Whether the viewmodel is raised or lowered - float m_flRaiseTime; // If lowered, the time we should raise the viewmodel - float m_flHolsterTime; // When the weapon was holstered - -private: - - CBaseHL2MPCombatWeapon( const CBaseHL2MPCombatWeapon & ); -}; - -#endif // WEAPON_BASEHL2MPCOMBATWEAPON_SHARED_H diff --git a/game/shared/hl2mp/weapon_physcannon.cpp b/game/shared/hl2mp/weapon_physcannon.cpp deleted file mode 100644 index 59b064539..000000000 --- a/game/shared/hl2mp/weapon_physcannon.cpp +++ /dev/null @@ -1,3685 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Physics cannon -// -//=============================================================================// - -#include "cbase.h" - -#ifdef CLIENT_DLL - #include "c_hl2mp_player.h" - #include "vcollide_parse.h" - #include "engine/IVDebugOverlay.h" - #include "iviewrender_beams.h" - #include "beamdraw.h" - #include "c_te_effect_dispatch.h" - #include "model_types.h" - #include "ClientEffectPrecacheSystem.h" - #include "fx_interpvalue.h" -#else - #include "hl2mp_player.h" - #include "soundent.h" - #include "ndebugoverlay.h" - #include "ai_basenpc.h" - #include "player_pickup.h" - #include "physics_prop_ragdoll.h" - #include "globalstate.h" - #include "props.h" - #include "te_effect_dispatch.h" - #include "util.h" -#endif - -#include "gamerules.h" -#include "soundenvelope.h" -#include "engine/IEngineSound.h" -#include "physics.h" -#include "in_buttons.h" -#include "IEffects.h" -#include "shake.h" -#include "beam_shared.h" -#include "Sprite.h" -#include "weapon_physcannon.h" -#include "physics_saverestore.h" -#include "movevars_shared.h" -#include "weapon_hl2mpbasehlmpcombatweapon.h" -#include "vphysics/friction.h" -#include "debugoverlay_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SPRITE_SCALE 128.0f - -//static const char *s_pWaitForUpgradeContext = "WaitForUpgrade"; - -ConVar g_debug_physcannon( "g_debug_physcannon", "0", FCVAR_REPLICATED | FCVAR_CHEAT ); - -ConVar physcannon_minforce( "physcannon_minforce", "700", FCVAR_REPLICATED | FCVAR_CHEAT ); -ConVar physcannon_maxforce( "physcannon_maxforce", "1500", FCVAR_REPLICATED | FCVAR_CHEAT ); -ConVar physcannon_maxmass( "physcannon_maxmass", "250", FCVAR_REPLICATED | FCVAR_CHEAT ); -ConVar physcannon_tracelength( "physcannon_tracelength", "250", FCVAR_REPLICATED | FCVAR_CHEAT ); -ConVar physcannon_chargetime("physcannon_chargetime", "2", FCVAR_REPLICATED | FCVAR_CHEAT ); -ConVar physcannon_pullforce( "physcannon_pullforce", "4000", FCVAR_REPLICATED | FCVAR_CHEAT ); -ConVar physcannon_cone( "physcannon_cone", "0.97", FCVAR_REPLICATED | FCVAR_CHEAT ); -ConVar physcannon_ball_cone( "physcannon_ball_cone", "0.997", FCVAR_REPLICATED | FCVAR_CHEAT ); -ConVar player_throwforce( "player_throwforce", "1000", FCVAR_REPLICATED | FCVAR_CHEAT ); - -#ifndef CLIENT_DLL -extern ConVar hl2_normspeed; -extern ConVar hl2_walkspeed; -#endif - -#define PHYSCANNON_BEAM_SPRITE "sprites/orangelight1.vmt" -#define PHYSCANNON_BEAM_SPRITE_NOZ "sprites/orangelight1_noz.vmt" -#define PHYSCANNON_GLOW_SPRITE "sprites/glow04_noz" -#define PHYSCANNON_ENDCAP_SPRITE "sprites/orangeflare1" -#define PHYSCANNON_CENTER_GLOW "sprites/orangecore1" -#define PHYSCANNON_BLAST_SPRITE "sprites/orangecore2" - -#ifdef CLIENT_DLL - - //Precahce the effects - CLIENTEFFECT_REGISTER_BEGIN( PrecacheEffectPhysCannon ) - CLIENTEFFECT_MATERIAL( "sprites/orangelight1" ) - CLIENTEFFECT_MATERIAL( "sprites/orangelight1_noz" ) - CLIENTEFFECT_MATERIAL( PHYSCANNON_GLOW_SPRITE ) - CLIENTEFFECT_MATERIAL( PHYSCANNON_ENDCAP_SPRITE ) - CLIENTEFFECT_MATERIAL( PHYSCANNON_CENTER_GLOW ) - CLIENTEFFECT_MATERIAL( PHYSCANNON_BLAST_SPRITE ) - CLIENTEFFECT_REGISTER_END() - -#endif // CLIENT_DLL - -#ifndef CLIENT_DLL - -void PhysCannonBeginUpgrade( CBaseAnimating *pAnim ) -{ - -} - -bool PlayerHasMegaPhysCannon( void ) -{ - return false; -} - -bool PhysCannonAccountableForObject( CBaseCombatWeapon *pPhysCannon, CBaseEntity *pObject ) -{ - // BRJ: FIXME! This can't be implemented trivially, so I'm leaving it to Steve or Adrian - Assert( 0 ); - return false; -} - -#endif - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// this will hit skip the pass entity, but not anything it owns -// (lets player grab own grenades) -class CTraceFilterNoOwnerTest : public CTraceFilterSimple -{ -public: - DECLARE_CLASS( CTraceFilterNoOwnerTest, CTraceFilterSimple ); - - CTraceFilterNoOwnerTest( const IHandleEntity *passentity, int collisionGroup ) - : CTraceFilterSimple( NULL, collisionGroup ), m_pPassNotOwner(passentity) - { - } - - virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) - { - if ( pHandleEntity != m_pPassNotOwner ) - return BaseClass::ShouldHitEntity( pHandleEntity, contentsMask ); - - return false; - } - -protected: - const IHandleEntity *m_pPassNotOwner; -}; - -static void MatrixOrthogonalize( matrix3x4_t &matrix, int column ) -{ - Vector columns[3]; - int i; - - for ( i = 0; i < 3; i++ ) - { - MatrixGetColumn( matrix, i, columns[i] ); - } - - int index0 = column; - int index1 = (column+1)%3; - int index2 = (column+2)%3; - - columns[index2] = CrossProduct( columns[index0], columns[index1] ); - columns[index1] = CrossProduct( columns[index2], columns[index0] ); - VectorNormalize( columns[index2] ); - VectorNormalize( columns[index1] ); - MatrixSetColumn( columns[index1], index1, matrix ); - MatrixSetColumn( columns[index2], index2, matrix ); -} - -#define SIGN(x) ( (x) < 0 ? -1 : 1 ) - -static QAngle AlignAngles( const QAngle &angles, float cosineAlignAngle ) -{ - matrix3x4_t alignMatrix; - AngleMatrix( angles, alignMatrix ); - - // NOTE: Must align z first - for ( int j = 3; --j >= 0; ) - { - Vector vec; - MatrixGetColumn( alignMatrix, j, vec ); - for ( int i = 0; i < 3; i++ ) - { - if ( fabs(vec[i]) > cosineAlignAngle ) - { - vec[i] = SIGN(vec[i]); - vec[(i+1)%3] = 0; - vec[(i+2)%3] = 0; - MatrixSetColumn( vec, j, alignMatrix ); - MatrixOrthogonalize( alignMatrix, j ); - break; - } - } - } - - QAngle out; - MatrixAngles( alignMatrix, out ); - return out; -} - - -/*static void TraceCollideAgainstBBox( const CPhysCollide *pCollide, const Vector &start, const Vector &end, const QAngle &angles, const Vector &boxOrigin, const Vector &mins, const Vector &maxs, trace_t *ptr ) -{ - physcollision->TraceBox( boxOrigin, boxOrigin + (start-end), mins, maxs, pCollide, start, angles, ptr ); - - if ( ptr->DidHit() ) - { - ptr->endpos = start * (1-ptr->fraction) + end * ptr->fraction; - ptr->startpos = start; - ptr->plane.dist = -ptr->plane.dist; - ptr->plane.normal *= -1; - } -}*/ - -//----------------------------------------------------------------------------- -// Purpose: Computes a local matrix for the player clamped to valid carry ranges -//----------------------------------------------------------------------------- -// when looking level, hold bottom of object 8 inches below eye level -#define PLAYER_HOLD_LEVEL_EYES -8 - -// when looking down, hold bottom of object 0 inches from feet -#define PLAYER_HOLD_DOWN_FEET 2 - -// when looking up, hold bottom of object 24 inches above eye level -#define PLAYER_HOLD_UP_EYES 24 - -// use a +/-30 degree range for the entire range of motion of pitch -#define PLAYER_LOOK_PITCH_RANGE 30 - -// player can reach down 2ft below his feet (otherwise he'll hold the object above the bottom) -#define PLAYER_REACH_DOWN_DISTANCE 24 - -static void ComputePlayerMatrix( CBasePlayer *pPlayer, matrix3x4_t &out ) -{ - if ( !pPlayer ) - return; - - QAngle angles = pPlayer->EyeAngles(); - Vector origin = pPlayer->EyePosition(); - - // 0-360 / -180-180 - //angles.x = init ? 0 : AngleDistance( angles.x, 0 ); - //angles.x = clamp( angles.x, -PLAYER_LOOK_PITCH_RANGE, PLAYER_LOOK_PITCH_RANGE ); - angles.x = 0; - - float feet = pPlayer->GetAbsOrigin().z + pPlayer->WorldAlignMins().z; - float eyes = origin.z; - float zoffset = 0; - // moving up (negative pitch is up) - if ( angles.x < 0 ) - { - zoffset = RemapVal( angles.x, 0, -PLAYER_LOOK_PITCH_RANGE, PLAYER_HOLD_LEVEL_EYES, PLAYER_HOLD_UP_EYES ); - } - else - { - zoffset = RemapVal( angles.x, 0, PLAYER_LOOK_PITCH_RANGE, PLAYER_HOLD_LEVEL_EYES, PLAYER_HOLD_DOWN_FEET + (feet - eyes) ); - } - origin.z += zoffset; - angles.x = 0; - AngleMatrix( angles, origin, out ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -// derive from this so we can add save/load data to it -struct game_shadowcontrol_params_t : public hlshadowcontrol_params_t -{ - DECLARE_SIMPLE_DATADESC(); -}; - -BEGIN_SIMPLE_DATADESC( game_shadowcontrol_params_t ) - - DEFINE_FIELD( targetPosition, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( targetRotation, FIELD_VECTOR ), - DEFINE_FIELD( maxAngular, FIELD_FLOAT ), - DEFINE_FIELD( maxDampAngular, FIELD_FLOAT ), - DEFINE_FIELD( maxSpeed, FIELD_FLOAT ), - DEFINE_FIELD( maxDampSpeed, FIELD_FLOAT ), - DEFINE_FIELD( dampFactor, FIELD_FLOAT ), - DEFINE_FIELD( teleportDistance, FIELD_FLOAT ), - -END_DATADESC() - -//----------------------------------------------------------------------------- -class CGrabController : public IMotionEvent -{ -public: - - CGrabController( void ); - ~CGrabController( void ); - void AttachEntity( CBasePlayer *pPlayer, CBaseEntity *pEntity, IPhysicsObject *pPhys, bool bIsMegaPhysCannon, const Vector &vGrabPosition, bool bUseGrabPosition ); - void DetachEntity( bool bClearVelocity ); - void OnRestore(); - - bool UpdateObject( CBasePlayer *pPlayer, float flError ); - - void SetTargetPosition( const Vector &target, const QAngle &targetOrientation ); - float ComputeError(); - float GetLoadWeight( void ) const { return m_flLoadWeight; } - void SetAngleAlignment( float alignAngleCosine ) { m_angleAlignment = alignAngleCosine; } - void SetIgnorePitch( bool bIgnore ) { m_bIgnoreRelativePitch = bIgnore; } - QAngle TransformAnglesToPlayerSpace( const QAngle &anglesIn, CBasePlayer *pPlayer ); - QAngle TransformAnglesFromPlayerSpace( const QAngle &anglesIn, CBasePlayer *pPlayer ); - - CBaseEntity *GetAttached() { return (CBaseEntity *)m_attachedEntity; } - - IMotionEvent::simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ); - float GetSavedMass( IPhysicsObject *pObject ); - - QAngle m_attachedAnglesPlayerSpace; - Vector m_attachedPositionObjectSpace; - -private: - // Compute the max speed for an attached object - void ComputeMaxSpeed( CBaseEntity *pEntity, IPhysicsObject *pPhysics ); - - game_shadowcontrol_params_t m_shadow; - float m_timeToArrive; - float m_errorTime; - float m_error; - float m_contactAmount; - float m_angleAlignment; - bool m_bCarriedEntityBlocksLOS; - bool m_bIgnoreRelativePitch; - - float m_flLoadWeight; - float m_savedRotDamping[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - float m_savedMass[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - EHANDLE m_attachedEntity; - QAngle m_vecPreferredCarryAngles; - bool m_bHasPreferredCarryAngles; - - - IPhysicsMotionController *m_controller; - int m_frameCount; - friend class CWeaponPhysCannon; -}; - -const float DEFAULT_MAX_ANGULAR = 360.0f * 10.0f; -const float REDUCED_CARRY_MASS = 1.0f; - -CGrabController::CGrabController( void ) -{ - m_shadow.dampFactor = 1.0; - m_shadow.teleportDistance = 0; - m_errorTime = 0; - m_error = 0; - // make this controller really stiff! - m_shadow.maxSpeed = 1000; - m_shadow.maxAngular = DEFAULT_MAX_ANGULAR; - m_shadow.maxDampSpeed = m_shadow.maxSpeed*2; - m_shadow.maxDampAngular = m_shadow.maxAngular; - m_attachedEntity = NULL; - m_vecPreferredCarryAngles = vec3_angle; - m_bHasPreferredCarryAngles = false; -} - -CGrabController::~CGrabController( void ) -{ - DetachEntity( false ); -} - -void CGrabController::OnRestore() -{ - if ( m_controller ) - { - m_controller->SetEventHandler( this ); - } -} - -void CGrabController::SetTargetPosition( const Vector &target, const QAngle &targetOrientation ) -{ - m_shadow.targetPosition = target; - m_shadow.targetRotation = targetOrientation; - - m_timeToArrive = gpGlobals->frametime; - - CBaseEntity *pAttached = GetAttached(); - if ( pAttached ) - { - IPhysicsObject *pObj = pAttached->VPhysicsGetObject(); - - if ( pObj != NULL ) - { - pObj->Wake(); - } - else - { - DetachEntity( false ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CGrabController::ComputeError() -{ - if ( m_errorTime <= 0 ) - return 0; - - CBaseEntity *pAttached = GetAttached(); - if ( pAttached ) - { - Vector pos; - IPhysicsObject *pObj = pAttached->VPhysicsGetObject(); - - if ( pObj ) - { - pObj->GetShadowPosition( &pos, NULL ); - - float error = (m_shadow.targetPosition - pos).Length(); - if ( m_errorTime > 0 ) - { - if ( m_errorTime > 1 ) - { - m_errorTime = 1; - } - float speed = error / m_errorTime; - if ( speed > m_shadow.maxSpeed ) - { - error *= 0.5; - } - m_error = (1-m_errorTime) * m_error + error * m_errorTime; - } - } - else - { - DevMsg( "Object attached to Physcannon has no physics object\n" ); - DetachEntity( false ); - return 9999; // force detach - } - } - - if ( pAttached->IsEFlagSet( EFL_IS_BEING_LIFTED_BY_BARNACLE ) ) - { - m_error *= 3.0f; - } - - m_errorTime = 0; - - return m_error; -} - - -#define MASS_SPEED_SCALE 60 -#define MAX_MASS 40 - -void CGrabController::ComputeMaxSpeed( CBaseEntity *pEntity, IPhysicsObject *pPhysics ) -{ -#ifndef CLIENT_DLL - m_shadow.maxSpeed = 1000; - m_shadow.maxAngular = DEFAULT_MAX_ANGULAR; - - // Compute total mass... - float flMass = PhysGetEntityMass( pEntity ); - float flMaxMass = physcannon_maxmass.GetFloat(); - if ( flMass <= flMaxMass ) - return; - - float flLerpFactor = clamp( flMass, flMaxMass, 500.0f ); - flLerpFactor = SimpleSplineRemapVal( flLerpFactor, flMaxMass, 500.0f, 0.0f, 1.0f ); - - float invMass = pPhysics->GetInvMass(); - float invInertia = pPhysics->GetInvInertia().Length(); - - float invMaxMass = 1.0f / MAX_MASS; - float ratio = invMaxMass / invMass; - invMass = invMaxMass; - invInertia *= ratio; - - float maxSpeed = invMass * MASS_SPEED_SCALE * 200; - float maxAngular = invInertia * MASS_SPEED_SCALE * 360; - - m_shadow.maxSpeed = Lerp( flLerpFactor, m_shadow.maxSpeed, maxSpeed ); - m_shadow.maxAngular = Lerp( flLerpFactor, m_shadow.maxAngular, maxAngular ); -#endif -} - - -QAngle CGrabController::TransformAnglesToPlayerSpace( const QAngle &anglesIn, CBasePlayer *pPlayer ) -{ - if ( m_bIgnoreRelativePitch ) - { - matrix3x4_t test; - QAngle angleTest = pPlayer->EyeAngles(); - angleTest.x = 0; - AngleMatrix( angleTest, test ); - return TransformAnglesToLocalSpace( anglesIn, test ); - } - return TransformAnglesToLocalSpace( anglesIn, pPlayer->EntityToWorldTransform() ); -} - -QAngle CGrabController::TransformAnglesFromPlayerSpace( const QAngle &anglesIn, CBasePlayer *pPlayer ) -{ - if ( m_bIgnoreRelativePitch ) - { - matrix3x4_t test; - QAngle angleTest = pPlayer->EyeAngles(); - angleTest.x = 0; - AngleMatrix( angleTest, test ); - return TransformAnglesToWorldSpace( anglesIn, test ); - } - return TransformAnglesToWorldSpace( anglesIn, pPlayer->EntityToWorldTransform() ); -} - - -void CGrabController::AttachEntity( CBasePlayer *pPlayer, CBaseEntity *pEntity, IPhysicsObject *pPhys, bool bIsMegaPhysCannon, const Vector &vGrabPosition, bool bUseGrabPosition ) -{ - // play the impact sound of the object hitting the player - // used as feedback to let the player know he picked up the object -#ifndef CLIENT_DLL - PhysicsImpactSound( pPlayer, pPhys, CHAN_STATIC, pPhys->GetMaterialIndex(), pPlayer->VPhysicsGetObject()->GetMaterialIndex(), 1.0, 64 ); -#endif - Vector position; - QAngle angles; - pPhys->GetPosition( &position, &angles ); - // If it has a preferred orientation, use that instead. -#ifndef CLIENT_DLL - Pickup_GetPreferredCarryAngles( pEntity, pPlayer, pPlayer->EntityToWorldTransform(), angles ); -#endif - -// ComputeMaxSpeed( pEntity, pPhys ); - - // Carried entities can never block LOS - m_bCarriedEntityBlocksLOS = pEntity->BlocksLOS(); - pEntity->SetBlocksLOS( false ); - m_controller = physenv->CreateMotionController( this ); - m_controller->AttachObject( pPhys, true ); - // Don't do this, it's causing trouble with constraint solvers. - //m_controller->SetPriority( IPhysicsMotionController::HIGH_PRIORITY ); - - pPhys->Wake(); - PhysSetGameFlags( pPhys, FVPHYSICS_PLAYER_HELD ); - SetTargetPosition( position, angles ); - m_attachedEntity = pEntity; - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int count = pEntity->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - m_flLoadWeight = 0; - float damping = 10; - float flFactor = count / 7.5f; - if ( flFactor < 1.0f ) - { - flFactor = 1.0f; - } - for ( int i = 0; i < count; i++ ) - { - float mass = pList[i]->GetMass(); - pList[i]->GetDamping( NULL, &m_savedRotDamping[i] ); - m_flLoadWeight += mass; - m_savedMass[i] = mass; - - // reduce the mass to prevent the player from adding crazy amounts of energy to the system - pList[i]->SetMass( REDUCED_CARRY_MASS / flFactor ); - pList[i]->SetDamping( NULL, &damping ); - } - - // Give extra mass to the phys object we're actually picking up - pPhys->SetMass( REDUCED_CARRY_MASS ); - pPhys->EnableDrag( false ); - - m_errorTime = -1.0f; // 1 seconds until error starts accumulating - m_error = 0; - m_contactAmount = 0; - - m_attachedAnglesPlayerSpace = TransformAnglesToPlayerSpace( angles, pPlayer ); - if ( m_angleAlignment != 0 ) - { - m_attachedAnglesPlayerSpace = AlignAngles( m_attachedAnglesPlayerSpace, m_angleAlignment ); - } - - VectorITransform( pEntity->WorldSpaceCenter(), pEntity->EntityToWorldTransform(), m_attachedPositionObjectSpace ); - -#ifndef CLIENT_DLL - // If it's a prop, see if it has desired carry angles - CPhysicsProp *pProp = dynamic_cast(pEntity); - if ( pProp ) - { - m_bHasPreferredCarryAngles = pProp->GetPropDataAngles( "preferred_carryangles", m_vecPreferredCarryAngles ); - } - else - { - m_bHasPreferredCarryAngles = false; - } -#else - - m_bHasPreferredCarryAngles = false; -#endif - -} - -static void ClampPhysicsVelocity( IPhysicsObject *pPhys, float linearLimit, float angularLimit ) -{ - Vector vel; - AngularImpulse angVel; - pPhys->GetVelocity( &vel, &angVel ); - float speed = VectorNormalize(vel) - linearLimit; - float angSpeed = VectorNormalize(angVel) - angularLimit; - speed = speed < 0 ? 0 : -speed; - angSpeed = angSpeed < 0 ? 0 : -angSpeed; - vel *= speed; - angVel *= angSpeed; - pPhys->AddVelocity( &vel, &angVel ); -} - -void CGrabController::DetachEntity( bool bClearVelocity ) -{ - CBaseEntity *pEntity = GetAttached(); - if ( pEntity ) - { - // Restore the LS blocking state - pEntity->SetBlocksLOS( m_bCarriedEntityBlocksLOS ); - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int count = pEntity->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - - for ( int i = 0; i < count; i++ ) - { - IPhysicsObject *pPhys = pList[i]; - if ( !pPhys ) - continue; - - // on the odd chance that it's gone to sleep while under anti-gravity - pPhys->EnableDrag( true ); - pPhys->Wake(); - pPhys->SetMass( m_savedMass[i] ); - pPhys->SetDamping( NULL, &m_savedRotDamping[i] ); - PhysClearGameFlags( pPhys, FVPHYSICS_PLAYER_HELD ); - if ( bClearVelocity ) - { - PhysForceClearVelocity( pPhys ); - } - else - { -#ifndef CLIENT_DLL - ClampPhysicsVelocity( pPhys, hl2_normspeed.GetFloat() * 1.5f, 2.0f * 360.0f ); -#endif - } - - } - } - - m_attachedEntity = NULL; - if ( physenv ) - { - physenv->DestroyMotionController( m_controller ); - } - m_controller = NULL; -} - -static bool InContactWithHeavyObject( IPhysicsObject *pObject, float heavyMass ) -{ - bool contact = false; - IPhysicsFrictionSnapshot *pSnapshot = pObject->CreateFrictionSnapshot(); - while ( pSnapshot->IsValid() ) - { - IPhysicsObject *pOther = pSnapshot->GetObject( 1 ); - if ( !pOther->IsMoveable() || pOther->GetMass() > heavyMass ) - { - contact = true; - break; - } - pSnapshot->NextFrictionData(); - } - pObject->DestroyFrictionSnapshot( pSnapshot ); - return contact; -} - -IMotionEvent::simresult_e CGrabController::Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) -{ - game_shadowcontrol_params_t shadowParams = m_shadow; - if ( InContactWithHeavyObject( pObject, GetLoadWeight() ) ) - { - m_contactAmount = Approach( 0.1f, m_contactAmount, deltaTime*2.0f ); - } - else - { - m_contactAmount = Approach( 1.0f, m_contactAmount, deltaTime*2.0f ); - } - shadowParams.maxAngular = m_shadow.maxAngular * m_contactAmount * m_contactAmount * m_contactAmount; -#ifndef CLIENT_DLL - m_timeToArrive = pObject->ComputeShadowControl( shadowParams, m_timeToArrive, deltaTime ); -#else - m_timeToArrive = pObject->ComputeShadowControl( shadowParams, (TICK_INTERVAL*2), deltaTime ); -#endif - - // Slide along the current contact points to fix bouncing problems - Vector velocity; - AngularImpulse angVel; - pObject->GetVelocity( &velocity, &angVel ); - PhysComputeSlideDirection( pObject, velocity, angVel, &velocity, &angVel, GetLoadWeight() ); - pObject->SetVelocityInstantaneous( &velocity, NULL ); - - linear.Init(); - angular.Init(); - m_errorTime += deltaTime; - - return SIM_LOCAL_ACCELERATION; -} - -float CGrabController::GetSavedMass( IPhysicsObject *pObject ) -{ - CBaseEntity *pHeld = m_attachedEntity; - if ( pHeld ) - { - if ( pObject->GetGameData() == (void*)pHeld ) - { - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int count = pHeld->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - for ( int i = 0; i < count; i++ ) - { - if ( pList[i] == pObject ) - return m_savedMass[i]; - } - } - } - return 0.0f; -} - -//----------------------------------------------------------------------------- -// Player pickup controller -//----------------------------------------------------------------------------- - -class CPlayerPickupController : public CBaseEntity -{ - DECLARE_CLASS( CPlayerPickupController, CBaseEntity ); -public: - void Init( CBasePlayer *pPlayer, CBaseEntity *pObject ); - void Shutdown( bool bThrown = false ); - bool OnControls( CBaseEntity *pControls ) { return true; } - void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); - void OnRestore() - { - m_grabController.OnRestore(); - } - void VPhysicsUpdate( IPhysicsObject *pPhysics ){} - void VPhysicsShadowUpdate( IPhysicsObject *pPhysics ) {} - - bool IsHoldingEntity( CBaseEntity *pEnt ); - CGrabController &GetGrabController() { return m_grabController; } - -private: - CGrabController m_grabController; - CBasePlayer *m_pPlayer; -}; - -LINK_ENTITY_TO_CLASS( player_pickup, CPlayerPickupController ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pPlayer - -// *pObject - -//----------------------------------------------------------------------------- -void CPlayerPickupController::Init( CBasePlayer *pPlayer, CBaseEntity *pObject ) -{ -#ifndef CLIENT_DLL - // Holster player's weapon - if ( pPlayer->GetActiveWeapon() ) - { - if ( !pPlayer->GetActiveWeapon()->Holster() ) - { - Shutdown(); - return; - } - } - - - CHL2MP_Player *pOwner = (CHL2MP_Player *)ToBasePlayer( pPlayer ); - if ( pOwner ) - { - pOwner->EnableSprint( false ); - } - - // If the target is debris, convert it to non-debris - if ( pObject->GetCollisionGroup() == COLLISION_GROUP_DEBRIS ) - { - // Interactive debris converts back to debris when it comes to rest - pObject->SetCollisionGroup( COLLISION_GROUP_INTERACTIVE_DEBRIS ); - } - - // done so I'll go across level transitions with the player - SetParent( pPlayer ); - m_grabController.SetIgnorePitch( true ); - m_grabController.SetAngleAlignment( DOT_30DEGREE ); - m_pPlayer = pPlayer; - IPhysicsObject *pPhysics = pObject->VPhysicsGetObject(); - Pickup_OnPhysGunPickup( pObject, m_pPlayer ); - - m_grabController.AttachEntity( pPlayer, pObject, pPhysics, false, vec3_origin, false ); - - m_pPlayer->m_Local.m_iHideHUD |= HIDEHUD_WEAPONSELECTION; - m_pPlayer->SetUseEntity( this ); -#endif -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : bool - -//----------------------------------------------------------------------------- -void CPlayerPickupController::Shutdown( bool bThrown ) -{ -#ifndef CLIENT_DLL - CBaseEntity *pObject = m_grabController.GetAttached(); - - bool bClearVelocity = false; - if ( !bThrown && pObject && pObject->VPhysicsGetObject() && pObject->VPhysicsGetObject()->GetContactPoint(NULL,NULL) ) - { - bClearVelocity = true; - } - - m_grabController.DetachEntity( bClearVelocity ); - - if ( pObject != NULL ) - { - Pickup_OnPhysGunDrop( pObject, m_pPlayer, bThrown ? THROWN_BY_PLAYER : DROPPED_BY_PLAYER ); - } - - if ( m_pPlayer ) - { - CHL2MP_Player *pOwner = (CHL2MP_Player *)ToBasePlayer( m_pPlayer ); - if ( pOwner ) - { - pOwner->EnableSprint( true ); - } - - m_pPlayer->SetUseEntity( NULL ); - if ( m_pPlayer->GetActiveWeapon() ) - { - if ( !m_pPlayer->GetActiveWeapon()->Deploy() ) - { - // We tried to restore the player's weapon, but we couldn't. - // This usually happens when they're holding an empty weapon that doesn't - // autoswitch away when out of ammo. Switch to next best weapon. - m_pPlayer->SwitchToNextBestWeapon( NULL ); - } - } - - m_pPlayer->m_Local.m_iHideHUD &= ~HIDEHUD_WEAPONSELECTION; - } - Remove(); - -#endif - -} - - -void CPlayerPickupController::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ) -{ - if ( ToBasePlayer(pActivator) == m_pPlayer ) - { - CBaseEntity *pAttached = m_grabController.GetAttached(); - - // UNDONE: Use vphysics stress to decide to drop objects - // UNDONE: Must fix case of forcing objects into the ground you're standing on (causes stress) before that will work - if ( !pAttached || useType == USE_OFF || (m_pPlayer->m_nButtons & IN_ATTACK2) || m_grabController.ComputeError() > 12 ) - { - Shutdown(); - return; - } - - //Adrian: Oops, our object became motion disabled, let go! - IPhysicsObject *pPhys = pAttached->VPhysicsGetObject(); - if ( pPhys && pPhys->IsMoveable() == false ) - { - Shutdown(); - return; - } - -#if STRESS_TEST - vphysics_objectstress_t stress; - CalculateObjectStress( pPhys, pAttached, &stress ); - if ( stress.exertedStress > 250 ) - { - Shutdown(); - return; - } -#endif - // +ATTACK will throw phys objects - if ( m_pPlayer->m_nButtons & IN_ATTACK ) - { - Shutdown( true ); - Vector vecLaunch; - m_pPlayer->EyeVectors( &vecLaunch ); - // JAY: Scale this with mass because some small objects really go flying - float massFactor = clamp( pPhys->GetMass(), 0.5, 15 ); - massFactor = RemapVal( massFactor, 0.5, 15, 0.5, 4 ); - vecLaunch *= player_throwforce.GetFloat() * massFactor; - - pPhys->ApplyForceCenter( vecLaunch ); - AngularImpulse aVel = RandomAngularImpulse( -10, 10 ) * massFactor; - pPhys->ApplyTorqueCenter( aVel ); - return; - } - - if ( useType == USE_SET ) - { - // update position - m_grabController.UpdateObject( m_pPlayer, 12 ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEnt - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CPlayerPickupController::IsHoldingEntity( CBaseEntity *pEnt ) -{ - return ( m_grabController.GetAttached() == pEnt ); -} - -void PlayerPickupObject( CBasePlayer *pPlayer, CBaseEntity *pObject ) -{ - -#ifndef CLIENT_DLL - - //Don't pick up if we don't have a phys object. - if ( pObject->VPhysicsGetObject() == NULL ) - return; - - CPlayerPickupController *pController = (CPlayerPickupController *)CBaseEntity::Create( "player_pickup", pObject->GetAbsOrigin(), vec3_angle, pPlayer ); - - if ( !pController ) - return; - - pController->Init( pPlayer, pObject ); - -#endif - -} - -//---------------------------------------------------------------------------------------------------------------------------------------------------------- -// CInterpolatedValue class -//---------------------------------------------------------------------------------------------------------------------------------------------------------- - -#ifdef CLIENT_DLL - -//---------------------------------------------------------------------------------------------------------------------------------------------------------- -// CPhysCannonEffect class -//---------------------------------------------------------------------------------------------------------------------------------------------------------- - -class CPhysCannonEffect -{ -public: - CPhysCannonEffect( void ) : m_vecColor( 255, 255, 255 ), m_bVisible( true ), m_nAttachment( -1 ) {}; - - void SetAttachment( int attachment ) { m_nAttachment = attachment; } - int GetAttachment( void ) const { return m_nAttachment; } - - void SetVisible( bool visible = true ) { m_bVisible = visible; } - int IsVisible( void ) const { return m_bVisible; } - - void SetColor( const Vector &color ) { m_vecColor = color; } - const Vector &GetColor( void ) const { return m_vecColor; } - - bool SetMaterial( const char *materialName ) - { - m_hMaterial.Init( materialName, TEXTURE_GROUP_CLIENT_EFFECTS ); - return ( m_hMaterial != NULL ); - } - - CMaterialReference &GetMaterial( void ) { return m_hMaterial; } - - CInterpolatedValue &GetAlpha( void ) { return m_Alpha; } - CInterpolatedValue &GetScale( void ) { return m_Scale; } - -private: - CInterpolatedValue m_Alpha; - CInterpolatedValue m_Scale; - - Vector m_vecColor; - bool m_bVisible; - int m_nAttachment; - CMaterialReference m_hMaterial; -}; - -//---------------------------------------------------------------------------------------------------------------------------------------------------------- -// CPhysCannonEffectBeam class -//---------------------------------------------------------------------------------------------------------------------------------------------------------- - -class CPhysCannonEffectBeam -{ -public: - CPhysCannonEffectBeam( void ) : m_pBeam( NULL ) {}; - - ~CPhysCannonEffectBeam( void ) - { - Release(); - } - - void Release( void ) - { - if ( m_pBeam != NULL ) - { - m_pBeam->flags = 0; - m_pBeam->die = gpGlobals->curtime - 1; - - m_pBeam = NULL; - } - } - - void Init( int startAttachment, int endAttachment, CBaseEntity *pEntity, bool firstPerson ) - { - if ( m_pBeam != NULL ) - return; - - BeamInfo_t beamInfo; - - beamInfo.m_pStartEnt = pEntity; - beamInfo.m_nStartAttachment = startAttachment; - beamInfo.m_pEndEnt = pEntity; - beamInfo.m_nEndAttachment = endAttachment; - beamInfo.m_nType = TE_BEAMPOINTS; - beamInfo.m_vecStart = vec3_origin; - beamInfo.m_vecEnd = vec3_origin; - - beamInfo.m_pszModelName = ( firstPerson ) ? PHYSCANNON_BEAM_SPRITE_NOZ : PHYSCANNON_BEAM_SPRITE; - - beamInfo.m_flHaloScale = 0.0f; - beamInfo.m_flLife = 0.0f; - - if ( firstPerson ) - { - beamInfo.m_flWidth = 0.0f; - beamInfo.m_flEndWidth = 4.0f; - } - else - { - beamInfo.m_flWidth = 0.5f; - beamInfo.m_flEndWidth = 2.0f; - } - - beamInfo.m_flFadeLength = 0.0f; - beamInfo.m_flAmplitude = 16; - beamInfo.m_flBrightness = 255.0; - beamInfo.m_flSpeed = 150.0f; - beamInfo.m_nStartFrame = 0.0; - beamInfo.m_flFrameRate = 30.0; - beamInfo.m_flRed = 255.0; - beamInfo.m_flGreen = 255.0; - beamInfo.m_flBlue = 255.0; - beamInfo.m_nSegments = 8; - beamInfo.m_bRenderable = true; - beamInfo.m_nFlags = FBEAM_FOREVER; - - m_pBeam = beams->CreateBeamEntPoint( beamInfo ); - } - - void SetVisible( bool state = true ) - { - if ( m_pBeam == NULL ) - return; - - m_pBeam->brightness = ( state ) ? 255.0f : 0.0f; - } - -private: - Beam_t *m_pBeam; -}; - -#endif - -//---------------------------------------------------------------------------------------------------------------------------------------------------------- -// CWeaponPhysCannon class -//---------------------------------------------------------------------------------------------------------------------------------------------------------- - -#ifdef CLIENT_DLL -#define CWeaponPhysCannon C_WeaponPhysCannon -#endif - -class CWeaponPhysCannon : public CBaseHL2MPCombatWeapon -{ -public: - DECLARE_CLASS( CWeaponPhysCannon, CBaseHL2MPCombatWeapon ); - - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - - CWeaponPhysCannon( void ); - - void Drop( const Vector &vecVelocity ); - void Precache(); - virtual void OnRestore(); - virtual void StopLoopingSounds(); - virtual void UpdateOnRemove(void); - void PrimaryAttack(); - void SecondaryAttack(); - void WeaponIdle(); - void ItemPreFrame(); - void ItemPostFrame(); - - void ForceDrop( void ); - bool DropIfEntityHeld( CBaseEntity *pTarget ); // Drops its held entity if it matches the entity passed in - CGrabController &GetGrabController() { return m_grabController; } - - bool CanHolster( void ); - bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); - bool Deploy( void ); - - bool HasAnyAmmo( void ) { return true; } - - virtual void SetViewModel( void ); - virtual const char *GetShootSound( int iIndex ) const; - -#ifndef CLIENT_DLL - CNetworkQAngle ( m_attachedAnglesPlayerSpace ); -#else - QAngle m_attachedAnglesPlayerSpace; -#endif - - CNetworkVector ( m_attachedPositionObjectSpace ); - - CNetworkHandle( CBaseEntity, m_hAttachedObject ); - - EHANDLE m_hOldAttachedObject; - -protected: - enum FindObjectResult_t - { - OBJECT_FOUND = 0, - OBJECT_NOT_FOUND, - OBJECT_BEING_DETACHED, - }; - - void DoEffect( int effectType, Vector *pos = NULL ); - - void OpenElements( void ); - void CloseElements( void ); - - // Pickup and throw objects. - bool CanPickupObject( CBaseEntity *pTarget ); - void CheckForTarget( void ); - -#ifndef CLIENT_DLL - bool AttachObject( CBaseEntity *pObject, const Vector &vPosition ); - FindObjectResult_t FindObject( void ); - CBaseEntity *FindObjectInCone( const Vector &vecOrigin, const Vector &vecDir, float flCone ); -#endif // !CLIENT_DLL - - void UpdateObject( void ); - void DetachObject( bool playSound = true, bool wasLaunched = false ); - void LaunchObject( const Vector &vecDir, float flForce ); - void StartEffects( void ); // Initialize all sprites and beams - void StopEffects( bool stopSound = true ); // Hide all effects temporarily - void DestroyEffects( void ); // Destroy all sprites and beams - - // Punt objects - this is pointing at an object in the world and applying a force to it. - void PuntNonVPhysics( CBaseEntity *pEntity, const Vector &forward, trace_t &tr ); - void PuntVPhysics( CBaseEntity *pEntity, const Vector &forward, trace_t &tr ); - - // Velocity-based throw common to punt and launch code. - void ApplyVelocityBasedForce( CBaseEntity *pEntity, const Vector &forward ); - - // Physgun effects - void DoEffectClosed( void ); - void DoEffectReady( void ); - void DoEffectHolding( void ); - void DoEffectLaunch( Vector *pos ); - void DoEffectNone( void ); - void DoEffectIdle( void ); - - // Trace length - float TraceLength(); - - // Sprite scale factor - float SpriteScaleFactor(); - - float GetLoadPercentage(); - CSoundPatch *GetMotorSound( void ); - - void DryFire( void ); - void PrimaryFireEffect( void ); - -#ifndef CLIENT_DLL - // What happens when the physgun picks up something - void Physgun_OnPhysGunPickup( CBaseEntity *pEntity, CBasePlayer *pOwner, PhysGunPickup_t reason ); -#endif // !CLIENT_DLL - -#ifdef CLIENT_DLL - - enum EffectType_t - { - PHYSCANNON_CORE = 0, - - PHYSCANNON_BLAST, - - PHYSCANNON_GLOW1, // Must be in order! - PHYSCANNON_GLOW2, - PHYSCANNON_GLOW3, - PHYSCANNON_GLOW4, - PHYSCANNON_GLOW5, - PHYSCANNON_GLOW6, - - PHYSCANNON_ENDCAP1, // Must be in order! - PHYSCANNON_ENDCAP2, - PHYSCANNON_ENDCAP3, // Only used in third-person! - - NUM_PHYSCANNON_PARAMETERS // Must be last! - }; - -#define NUM_GLOW_SPRITES ((CWeaponPhysCannon::PHYSCANNON_GLOW6-CWeaponPhysCannon::PHYSCANNON_GLOW1)+1) -#define NUM_ENDCAP_SPRITES ((CWeaponPhysCannon::PHYSCANNON_ENDCAP3-CWeaponPhysCannon::PHYSCANNON_ENDCAP1)+1) - -#define NUM_PHYSCANNON_BEAMS 3 - - virtual int DrawModel( int flags ); - virtual void ViewModelDrawn( C_BaseViewModel *pBaseViewModel ); - virtual bool IsTransparent( void ); - virtual void OnDataChanged( DataUpdateType_t type ); - virtual void ClientThink( void ); - - void ManagePredictedObject( void ); - void DrawEffects( void ); - void GetEffectParameters( EffectType_t effectID, color32 &color, float &scale, IMaterial **pMaterial, Vector &vecAttachment ); - void DrawEffectSprite( EffectType_t effectID ); - inline bool IsEffectVisible( EffectType_t effectID ); - void UpdateElementPosition( void ); - - // We need to render opaque and translucent pieces - RenderGroup_t GetRenderGroup( void ) { return RENDER_GROUP_TWOPASS; } - - CInterpolatedValue m_ElementParameter; // Used to interpolate the position of the articulated elements - CPhysCannonEffect m_Parameters[NUM_PHYSCANNON_PARAMETERS]; // Interpolated parameters for the effects - CPhysCannonEffectBeam m_Beams[NUM_PHYSCANNON_BEAMS]; // Beams - - int m_nOldEffectState; // Used for parity checks - bool m_bOldOpen; // Used for parity checks - - void NotifyShouldTransmit( ShouldTransmitState_t state ); - -#endif // CLIENT_DLL - - int m_nChangeState; // For delayed state change of elements - float m_flCheckSuppressTime; // Amount of time to suppress the checking for targets - bool m_flLastDenySoundPlayed; // Debounce for deny sound - int m_nAttack2Debounce; - - CNetworkVar( bool, m_bActive ); - CNetworkVar( int, m_EffectState ); // Current state of the effects on the gun - CNetworkVar( bool, m_bOpen ); - - bool m_bResetOwnerEntity; - - float m_flElementDebounce; - - CSoundPatch *m_sndMotor; // Whirring sound for the gun - - CGrabController m_grabController; - - float m_flRepuntObjectTime; - EHANDLE m_hLastPuntedObject; - -private: - CWeaponPhysCannon( const CWeaponPhysCannon & ); - -#ifndef CLIENT_DLL - DECLARE_ACTTABLE(); -#endif -}; - -IMPLEMENT_NETWORKCLASS_ALIASED( WeaponPhysCannon, DT_WeaponPhysCannon ) - -BEGIN_NETWORK_TABLE( CWeaponPhysCannon, DT_WeaponPhysCannon ) -#ifdef CLIENT_DLL - RecvPropBool( RECVINFO( m_bActive ) ), - RecvPropEHandle( RECVINFO( m_hAttachedObject ) ), - RecvPropVector( RECVINFO( m_attachedPositionObjectSpace ) ), - RecvPropFloat( RECVINFO( m_attachedAnglesPlayerSpace[0] ) ), - RecvPropFloat( RECVINFO( m_attachedAnglesPlayerSpace[1] ) ), - RecvPropFloat( RECVINFO( m_attachedAnglesPlayerSpace[2] ) ), - RecvPropInt( RECVINFO( m_EffectState ) ), - RecvPropBool( RECVINFO( m_bOpen ) ), -#else - SendPropBool( SENDINFO( m_bActive ) ), - SendPropEHandle( SENDINFO( m_hAttachedObject ) ), - SendPropVector(SENDINFO( m_attachedPositionObjectSpace ), -1, SPROP_COORD), - SendPropAngle( SENDINFO_VECTORELEM2(m_attachedAnglesPlayerSpace, 0, x ), 11 ), - SendPropAngle( SENDINFO_VECTORELEM2(m_attachedAnglesPlayerSpace, 1, y ), 11 ), - SendPropAngle( SENDINFO_VECTORELEM2(m_attachedAnglesPlayerSpace, 2, z ), 11 ), - SendPropInt( SENDINFO( m_EffectState ) ), - SendPropBool( SENDINFO( m_bOpen ) ), -#endif -END_NETWORK_TABLE() - -#ifdef CLIENT_DLL -BEGIN_PREDICTION_DATA( CWeaponPhysCannon ) - DEFINE_PRED_FIELD( m_EffectState, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_bOpen, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), -END_PREDICTION_DATA() -#endif - -LINK_ENTITY_TO_CLASS( weapon_physcannon, CWeaponPhysCannon ); -PRECACHE_WEAPON_REGISTER( weapon_physcannon ); - -#ifndef CLIENT_DLL - -acttable_t CWeaponPhysCannon::m_acttable[] = -{ - { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_PHYSGUN, false }, - { ACT_HL2MP_RUN, ACT_HL2MP_RUN_PHYSGUN, false }, - { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_PHYSGUN, false }, - { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_PHYSGUN, false }, - { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_PHYSGUN, false }, - { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_PHYSGUN, false }, - { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_PHYSGUN, false }, -}; - -IMPLEMENT_ACTTABLE(CWeaponPhysCannon); - -#endif - - -enum -{ - ELEMENT_STATE_NONE = -1, - ELEMENT_STATE_OPEN, - ELEMENT_STATE_CLOSED, -}; - -enum -{ - EFFECT_NONE, - EFFECT_CLOSED, - EFFECT_READY, - EFFECT_HOLDING, - EFFECT_LAUNCH, -}; - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CWeaponPhysCannon::CWeaponPhysCannon( void ) -{ - m_bOpen = false; - m_nChangeState = ELEMENT_STATE_NONE; - m_flCheckSuppressTime = 0.0f; - m_EffectState = (int)EFFECT_NONE; - m_flLastDenySoundPlayed = false; - -#ifdef CLIENT_DLL - m_nOldEffectState = EFFECT_NONE; - m_bOldOpen = false; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Precache -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::Precache( void ) -{ - PrecacheModel( PHYSCANNON_BEAM_SPRITE ); - PrecacheModel( PHYSCANNON_BEAM_SPRITE_NOZ ); - - PrecacheScriptSound( "Weapon_PhysCannon.HoldSound" ); - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: Restore -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::OnRestore() -{ - BaseClass::OnRestore(); - m_grabController.OnRestore(); - - // Tracker 8106: Physcannon effects disappear through level transition, so - // just recreate any effects here - if ( m_EffectState != EFFECT_NONE ) - { - DoEffect( m_EffectState, NULL ); - } -} - - -//----------------------------------------------------------------------------- -// On Remove -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::UpdateOnRemove(void) -{ - DestroyEffects( ); - BaseClass::UpdateOnRemove(); -} - -#ifdef CLIENT_DLL -void CWeaponPhysCannon::OnDataChanged( DataUpdateType_t type ) -{ - BaseClass::OnDataChanged( type ); - - if ( type == DATA_UPDATE_CREATED ) - { - SetNextClientThink( CLIENT_THINK_ALWAYS ); - - C_BaseAnimating::AutoAllowBoneAccess boneaccess( true, false ); - StartEffects(); - } - - if ( GetOwner() == NULL ) - { - if ( m_hAttachedObject ) - { - m_hAttachedObject->VPhysicsDestroyObject(); - } - - if ( m_hOldAttachedObject ) - { - m_hOldAttachedObject->VPhysicsDestroyObject(); - } - } - - // Update effect state when out of parity with the server - if ( m_nOldEffectState != m_EffectState ) - { - DoEffect( m_EffectState ); - m_nOldEffectState = m_EffectState; - } - - // Update element state when out of parity - if ( m_bOldOpen != m_bOpen ) - { - if ( m_bOpen ) - { - m_ElementParameter.InitFromCurrent( 1.0f, 0.2f, INTERP_SPLINE ); - } - else - { - m_ElementParameter.InitFromCurrent( 0.0f, 0.5f, INTERP_SPLINE ); - } - - m_bOldOpen = (bool) m_bOpen; - } -} -#endif - -//----------------------------------------------------------------------------- -// Sprite scale factor -//----------------------------------------------------------------------------- -inline float CWeaponPhysCannon::SpriteScaleFactor() -{ - return 1.0f; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponPhysCannon::Deploy( void ) -{ - CloseElements(); - DoEffect( EFFECT_READY ); - - bool bReturn = BaseClass::Deploy(); - - m_flNextSecondaryAttack = m_flNextPrimaryAttack = gpGlobals->curtime; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner ) - { - pOwner->SetNextAttack( gpGlobals->curtime ); - } - - return bReturn; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::SetViewModel( void ) -{ - BaseClass::SetViewModel(); -} - -//----------------------------------------------------------------------------- -// Purpose: Force the cannon to drop anything it's carrying -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::ForceDrop( void ) -{ - CloseElements(); - DetachObject(); - StopEffects(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Drops its held entity if it matches the entity passed in -// Input : *pTarget - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponPhysCannon::DropIfEntityHeld( CBaseEntity *pTarget ) -{ - if ( pTarget == NULL ) - return false; - - CBaseEntity *pHeld = m_grabController.GetAttached(); - - if ( pHeld == NULL ) - return false; - - if ( pHeld == pTarget ) - { - ForceDrop(); - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::Drop( const Vector &vecVelocity ) -{ - ForceDrop(); - -#ifndef CLIENT_DLL - UTIL_Remove( this ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CWeaponPhysCannon::CanHolster( void ) -{ - //Don't holster this weapon if we're holding onto something - if ( m_bActive ) - return false; - - return BaseClass::CanHolster(); -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponPhysCannon::Holster( CBaseCombatWeapon *pSwitchingTo ) -{ - //Don't holster this weapon if we're holding onto something - if ( m_bActive ) - return false; - - ForceDrop(); - DestroyEffects(); - - return BaseClass::Holster( pSwitchingTo ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DryFire( void ) -{ - SendWeaponAnim( ACT_VM_PRIMARYATTACK ); - - WeaponSound( EMPTY ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::PrimaryFireEffect( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - pOwner->ViewPunch( QAngle(-6, SharedRandomInt( "physcannonfire", -2,2) ,0) ); - -#ifndef CLIENT_DLL - color32 white = { 245, 245, 255, 32 }; - UTIL_ScreenFade( pOwner, white, 0.1f, 0.0f, FFADE_IN ); -#endif - - WeaponSound( SINGLE ); -} - -#define MAX_KNOCKBACK_FORCE 128 - -//----------------------------------------------------------------------------- -// Punt non-physics -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::PuntNonVPhysics( CBaseEntity *pEntity, const Vector &forward, trace_t &tr ) -{ - if ( m_hLastPuntedObject == pEntity && gpGlobals->curtime < m_flRepuntObjectTime ) - return; - -#ifndef CLIENT_DLL - CTakeDamageInfo info; - - info.SetAttacker( GetOwner() ); - info.SetInflictor( this ); - info.SetDamage( 1.0f ); - info.SetDamageType( DMG_CRUSH | DMG_PHYSGUN ); - info.SetDamageForce( forward ); // Scale? - info.SetDamagePosition( tr.endpos ); - - m_hLastPuntedObject = pEntity; - m_flRepuntObjectTime = gpGlobals->curtime + 0.5f; - - pEntity->DispatchTraceAttack( info, forward, &tr ); - - ApplyMultiDamage(); - - //Explosion effect - DoEffect( EFFECT_LAUNCH, &tr.endpos ); -#endif - - PrimaryFireEffect(); - SendWeaponAnim( ACT_VM_SECONDARYATTACK ); - - m_nChangeState = ELEMENT_STATE_CLOSED; - m_flElementDebounce = gpGlobals->curtime + 0.5f; - m_flCheckSuppressTime = gpGlobals->curtime + 0.25f; -} - - -#ifndef CLIENT_DLL -//----------------------------------------------------------------------------- -// What happens when the physgun picks up something -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::Physgun_OnPhysGunPickup( CBaseEntity *pEntity, CBasePlayer *pOwner, PhysGunPickup_t reason ) -{ - // If the target is debris, convert it to non-debris - if ( pEntity->GetCollisionGroup() == COLLISION_GROUP_DEBRIS ) - { - // Interactive debris converts back to debris when it comes to rest - pEntity->SetCollisionGroup( COLLISION_GROUP_INTERACTIVE_DEBRIS ); - } - - Pickup_OnPhysGunPickup( pEntity, pOwner, reason ); -} -#endif - -//----------------------------------------------------------------------------- -// Punt vphysics -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::PuntVPhysics( CBaseEntity *pEntity, const Vector &vecForward, trace_t &tr ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - - if ( m_hLastPuntedObject == pEntity && gpGlobals->curtime < m_flRepuntObjectTime ) - return; - - m_hLastPuntedObject = pEntity; - m_flRepuntObjectTime = gpGlobals->curtime + 0.5f; - -#ifndef CLIENT_DLL - CTakeDamageInfo info; - - Vector forward = vecForward; - - info.SetAttacker( GetOwner() ); - info.SetInflictor( this ); - info.SetDamage( 0.0f ); - info.SetDamageType( DMG_PHYSGUN ); - pEntity->DispatchTraceAttack( info, forward, &tr ); - ApplyMultiDamage(); - - - if ( Pickup_OnAttemptPhysGunPickup( pEntity, pOwner, PUNTED_BY_CANNON ) ) - { - IPhysicsObject *pList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; - int listCount = pEntity->VPhysicsGetObjectList( pList, ARRAYSIZE(pList) ); - if ( !listCount ) - { - //FIXME: Do we want to do this if there's no physics object? - Physgun_OnPhysGunPickup( pEntity, pOwner, PUNTED_BY_CANNON ); - DryFire(); - return; - } - - if( forward.z < 0 ) - { - //reflect, but flatten the trajectory out a bit so it's easier to hit standing targets - forward.z *= -0.65f; - } - - // NOTE: Do this first to enable motion (if disabled) - so forces will work - // Tell the object it's been punted - Physgun_OnPhysGunPickup( pEntity, pOwner, PUNTED_BY_CANNON ); - - // don't push vehicles that are attached to the world via fixed constraints - // they will just wiggle... - if ( (pList[0]->GetGameFlags() & FVPHYSICS_CONSTRAINT_STATIC) && pEntity->GetServerVehicle() ) - { - forward.Init(); - } - - if ( !Pickup_ShouldPuntUseLaunchForces( pEntity, PHYSGUN_FORCE_PUNTED ) ) - { - int i; - - // limit mass to avoid punting REALLY huge things - float totalMass = 0; - for ( i = 0; i < listCount; i++ ) - { - totalMass += pList[i]->GetMass(); - } - float maxMass = 250; - IServerVehicle *pVehicle = pEntity->GetServerVehicle(); - if ( pVehicle ) - { - maxMass *= 2.5; // 625 for vehicles - } - float mass = MIN(totalMass, maxMass); // max 250kg of additional force - - // Put some spin on the object - for ( i = 0; i < listCount; i++ ) - { - const float hitObjectFactor = 0.5f; - const float otherObjectFactor = 1.0f - hitObjectFactor; - // Must be light enough - float ratio = pList[i]->GetMass() / totalMass; - if ( pList[i] == pEntity->VPhysicsGetObject() ) - { - ratio += hitObjectFactor; - ratio = MIN(ratio,1.0f); - } - else - { - ratio *= otherObjectFactor; - } - pList[i]->ApplyForceCenter( forward * 15000.0f * ratio ); - pList[i]->ApplyForceOffset( forward * mass * 600.0f * ratio, tr.endpos ); - } - } - else - { - ApplyVelocityBasedForce( pEntity, vecForward ); - } - } - -#endif - // Add recoil - QAngle recoil = QAngle( random->RandomFloat( 1.0f, 2.0f ), random->RandomFloat( -1.0f, 1.0f ), 0 ); - pOwner->ViewPunch( recoil ); - - //Explosion effect - DoEffect( EFFECT_LAUNCH, &tr.endpos ); - - PrimaryFireEffect(); - SendWeaponAnim( ACT_VM_SECONDARYATTACK ); - - m_nChangeState = ELEMENT_STATE_CLOSED; - m_flElementDebounce = gpGlobals->curtime + 0.5f; - m_flCheckSuppressTime = gpGlobals->curtime + 0.25f; - - // Don't allow the gun to regrab a thrown object!! - m_flNextSecondaryAttack = m_flNextPrimaryAttack = gpGlobals->curtime + 0.5f; -} - -//----------------------------------------------------------------------------- -// Purpose: Applies velocity-based forces to throw the entity. This code is -// called from both punt and launch carried code. -// ASSUMES: that pEntity is a vphysics entity. -// Input : - -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::ApplyVelocityBasedForce( CBaseEntity *pEntity, const Vector &forward ) -{ -#ifndef CLIENT_DLL - IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject(); - Assert(pPhysicsObject); // Shouldn't ever get here with a non-vphysics object. - if (!pPhysicsObject) - return; - - float flForceMax = physcannon_maxforce.GetFloat(); - float flForce = flForceMax; - - float mass = pPhysicsObject->GetMass(); - if (mass > 100) - { - mass = MIN(mass, 1000); - float flForceMin = physcannon_minforce.GetFloat(); - flForce = SimpleSplineRemapVal(mass, 100, 600, flForceMax, flForceMin); - } - - Vector vVel = forward * flForce; - // FIXME: Josh needs to put a real value in for PHYSGUN_FORCE_PUNTED - AngularImpulse aVel = Pickup_PhysGunLaunchAngularImpulse( pEntity, PHYSGUN_FORCE_PUNTED ); - - pPhysicsObject->AddVelocity( &vVel, &aVel ); - -#endif - -} - - -//----------------------------------------------------------------------------- -// Trace length -//----------------------------------------------------------------------------- -float CWeaponPhysCannon::TraceLength() -{ - return physcannon_tracelength.GetFloat(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -// This mode is a toggle. Primary fire one time to pick up a physics object. -// With an object held, click primary fire again to drop object. -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::PrimaryAttack( void ) -{ - if( m_flNextPrimaryAttack > gpGlobals->curtime ) - return; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - if( m_bActive ) - { - // Punch the object being held!! - Vector forward; - pOwner->EyeVectors( &forward ); - - // Validate the item is within punt range - CBaseEntity *pHeld = m_grabController.GetAttached(); - Assert( pHeld != NULL ); - - if ( pHeld != NULL ) - { - float heldDist = ( pHeld->WorldSpaceCenter() - pOwner->WorldSpaceCenter() ).Length(); - - if ( heldDist > physcannon_tracelength.GetFloat() ) - { - // We can't punt this yet - DryFire(); - return; - } - } - - LaunchObject( forward, physcannon_maxforce.GetFloat() ); - - PrimaryFireEffect(); - SendWeaponAnim( ACT_VM_SECONDARYATTACK ); - return; - } - - // If not active, just issue a physics punch in the world. - m_flNextPrimaryAttack = gpGlobals->curtime + 0.5f; - - Vector forward; - pOwner->EyeVectors( &forward ); - - // NOTE: Notice we're *not* using the mega tracelength here - // when you have the mega cannon. Punting has shorter range. - Vector start, end; - start = pOwner->Weapon_ShootPosition(); - float flPuntDistance = physcannon_tracelength.GetFloat(); - VectorMA( start, flPuntDistance, forward, end ); - - CTraceFilterNoOwnerTest filter( pOwner, COLLISION_GROUP_NONE ); - trace_t tr; - UTIL_TraceHull( start, end, -Vector(8,8,8), Vector(8,8,8), MASK_SHOT|CONTENTS_GRATE, &filter, &tr ); - bool bValid = true; - CBaseEntity *pEntity = tr.m_pEnt; - if ( tr.fraction == 1 || !tr.m_pEnt || tr.m_pEnt->IsEFlagSet( EFL_NO_PHYSCANNON_INTERACTION ) ) - { - bValid = false; - } - else if ( (pEntity->GetMoveType() != MOVETYPE_VPHYSICS) && ( pEntity->m_takedamage == DAMAGE_NO ) ) - { - bValid = false; - } - - // If the entity we've hit is invalid, try a traceline instead - if ( !bValid ) - { - UTIL_TraceLine( start, end, MASK_SHOT|CONTENTS_GRATE, &filter, &tr ); - if ( tr.fraction == 1 || !tr.m_pEnt || tr.m_pEnt->IsEFlagSet( EFL_NO_PHYSCANNON_INTERACTION ) ) - { - // Play dry-fire sequence - DryFire(); - return; - } - - pEntity = tr.m_pEnt; - } - - // See if we hit something - if ( pEntity->GetMoveType() != MOVETYPE_VPHYSICS ) - { - if ( pEntity->m_takedamage == DAMAGE_NO ) - { - DryFire(); - return; - } - - if( GetOwner()->IsPlayer() ) - { - // Don't let the player zap any NPC's except regular antlions and headcrabs. - if( pEntity->IsPlayer() ) - { - DryFire(); - return; - } - } - - PuntNonVPhysics( pEntity, forward, tr ); - } - else - { - if ( pEntity->VPhysicsIsFlesh( ) ) - { - DryFire(); - return; - } - PuntVPhysics( pEntity, forward, tr ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Click secondary attack whilst holding an object to hurl it. -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::SecondaryAttack( void ) -{ -#ifndef CLIENT_DLL - if ( m_flNextSecondaryAttack > gpGlobals->curtime ) - return; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - // See if we should drop a held item - if ( ( m_bActive ) && ( pOwner->m_afButtonPressed & IN_ATTACK2 ) ) - { - // Drop the held object - m_flNextPrimaryAttack = gpGlobals->curtime + 0.5; - m_flNextSecondaryAttack = gpGlobals->curtime + 0.5; - - DetachObject(); - - DoEffect( EFFECT_READY ); - - SendWeaponAnim( ACT_VM_PRIMARYATTACK ); - } - else - { - // Otherwise pick it up - FindObjectResult_t result = FindObject(); - switch ( result ) - { - case OBJECT_FOUND: - WeaponSound( SPECIAL1 ); - SendWeaponAnim( ACT_VM_PRIMARYATTACK ); - m_flNextSecondaryAttack = gpGlobals->curtime + 0.5f; - - // We found an object. Debounce the button - m_nAttack2Debounce |= pOwner->m_nButtons; - break; - - case OBJECT_NOT_FOUND: - m_flNextSecondaryAttack = gpGlobals->curtime + 0.1f; - CloseElements(); - break; - - case OBJECT_BEING_DETACHED: - m_flNextSecondaryAttack = gpGlobals->curtime + 0.01f; - break; - } - - DoEffect( EFFECT_HOLDING ); - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::WeaponIdle( void ) -{ - if ( HasWeaponIdleTimeElapsed() ) - { - if ( m_bActive ) - { - //Shake when holding an item - SendWeaponAnim( ACT_VM_RELOAD ); - } - else - { - //Otherwise idle simply - SendWeaponAnim( ACT_VM_IDLE ); - } - } -} - -#ifndef CLIENT_DLL - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pObject - -//----------------------------------------------------------------------------- -bool CWeaponPhysCannon::AttachObject( CBaseEntity *pObject, const Vector &vPosition ) -{ - - if ( m_bActive ) - return false; - - if ( CanPickupObject( pObject ) == false ) - return false; - - m_grabController.SetIgnorePitch( false ); - m_grabController.SetAngleAlignment( 0 ); - - IPhysicsObject *pPhysics = pObject->VPhysicsGetObject(); - - // Must be valid - if ( !pPhysics ) - return false; - - CHL2MP_Player *pOwner = (CHL2MP_Player *)ToBasePlayer( GetOwner() ); - - m_bActive = true; - if( pOwner ) - { - // NOTE: This can change the mass; so it must be done before max speed setting - Physgun_OnPhysGunPickup( pObject, pOwner, PICKED_UP_BY_CANNON ); - } - - // NOTE :This must happen after OnPhysGunPickup because that can change the mass - m_grabController.AttachEntity( pOwner, pObject, pPhysics, false, vPosition, false ); - m_hAttachedObject = pObject; - m_attachedPositionObjectSpace = m_grabController.m_attachedPositionObjectSpace; - m_attachedAnglesPlayerSpace = m_grabController.m_attachedAnglesPlayerSpace; - - m_bResetOwnerEntity = false; - - if ( m_hAttachedObject->GetOwnerEntity() == NULL ) - { - m_hAttachedObject->SetOwnerEntity( pOwner ); - m_bResetOwnerEntity = true; - } - -/* if( pOwner ) - { - pOwner->EnableSprint( false ); - - float loadWeight = ( 1.0f - GetLoadPercentage() ); - float maxSpeed = hl2_walkspeed.GetFloat() + ( ( hl2_normspeed.GetFloat() - hl2_walkspeed.GetFloat() ) * loadWeight ); - - //Msg( "Load perc: %f -- Movement speed: %f/%f\n", loadWeight, maxSpeed, hl2_normspeed.GetFloat() ); - pOwner->SetMaxSpeed( maxSpeed ); - }*/ - - // Don't drop again for a slight delay, in case they were pulling objects near them - m_flNextSecondaryAttack = gpGlobals->curtime + 0.4f; - - DoEffect( EFFECT_HOLDING ); - OpenElements(); - - if ( GetMotorSound() ) - { - (CSoundEnvelopeController::GetController()).Play( GetMotorSound(), 0.0f, 50 ); - (CSoundEnvelopeController::GetController()).SoundChangePitch( GetMotorSound(), 100, 0.5f ); - (CSoundEnvelopeController::GetController()).SoundChangeVolume( GetMotorSound(), 0.8f, 0.5f ); - } - - - - return true; -} - -CWeaponPhysCannon::FindObjectResult_t CWeaponPhysCannon::FindObject( void ) -{ - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - Assert( pPlayer ); - if ( pPlayer == NULL ) - return OBJECT_NOT_FOUND; - - Vector forward; - pPlayer->EyeVectors( &forward ); - - // Setup our positions - Vector start = pPlayer->Weapon_ShootPosition(); - float testLength = TraceLength() * 4.0f; - Vector end = start + forward * testLength; - - // Try to find an object by looking straight ahead - trace_t tr; - CTraceFilterNoOwnerTest filter( pPlayer, COLLISION_GROUP_NONE ); - UTIL_TraceLine( start, end, MASK_SHOT|CONTENTS_GRATE, &filter, &tr ); - - // Try again with a hull trace - if ( ( tr.fraction == 1.0 ) || ( tr.m_pEnt == NULL ) || ( tr.m_pEnt->IsWorld() ) ) - { - UTIL_TraceHull( start, end, -Vector(4,4,4), Vector(4,4,4), MASK_SHOT|CONTENTS_GRATE, &filter, &tr ); - } - - CBaseEntity *pEntity = tr.m_pEnt ? tr.m_pEnt->GetRootMoveParent() : NULL; - bool bAttach = false; - bool bPull = false; - - // If we hit something, pick it up or pull it - if ( ( tr.fraction != 1.0f ) && ( tr.m_pEnt ) && ( tr.m_pEnt->IsWorld() == false ) ) - { - // Attempt to attach if within range - if ( tr.fraction <= 0.25f ) - { - bAttach = true; - } - else if ( tr.fraction > 0.25f ) - { - bPull = true; - } - } - - // Find anything within a general cone in front - CBaseEntity *pConeEntity = NULL; - - if (!bAttach && !bPull) - { - pConeEntity = FindObjectInCone( start, forward, physcannon_cone.GetFloat() ); - } - - if ( pConeEntity ) - { - pEntity = pConeEntity; - - // If the object is near, grab it. Else, pull it a bit. - if ( pEntity->WorldSpaceCenter().DistToSqr( start ) <= (testLength * testLength) ) - { - bAttach = true; - } - else - { - bPull = true; - } - } - - if ( CanPickupObject( pEntity ) == false ) - { - // Make a noise to signify we can't pick this up - if ( !m_flLastDenySoundPlayed ) - { - m_flLastDenySoundPlayed = true; - WeaponSound( SPECIAL3 ); - } - - return OBJECT_NOT_FOUND; - } - - // Check to see if the object is constrained + needs to be ripped off... - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( !Pickup_OnAttemptPhysGunPickup( pEntity, pOwner, PICKED_UP_BY_CANNON ) ) - return OBJECT_BEING_DETACHED; - - if ( bAttach ) - { - return AttachObject( pEntity, tr.endpos ) ? OBJECT_FOUND : OBJECT_NOT_FOUND; - } - - if ( !bPull ) - return OBJECT_NOT_FOUND; - - // FIXME: This needs to be run through the CanPickupObject logic - IPhysicsObject *pObj = pEntity->VPhysicsGetObject(); - if ( !pObj ) - return OBJECT_NOT_FOUND; - - // If we're too far, simply start to pull the object towards us - Vector pullDir = start - pEntity->WorldSpaceCenter(); - VectorNormalize( pullDir ); - pullDir *= physcannon_pullforce.GetFloat(); - - float mass = PhysGetEntityMass( pEntity ); - if ( mass < 50.0f ) - { - pullDir *= (mass + 0.5) * (1/50.0f); - } - - // Nudge it towards us - pObj->ApplyForceCenter( pullDir ); - return OBJECT_NOT_FOUND; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CBaseEntity *CWeaponPhysCannon::FindObjectInCone( const Vector &vecOrigin, const Vector &vecDir, float flCone ) -{ - // Find the nearest physics-based item in a cone in front of me. - CBaseEntity *list[256]; - float flNearestDist = TraceLength() + 1.0; - Vector mins = vecOrigin - Vector( flNearestDist, flNearestDist, flNearestDist ); - Vector maxs = vecOrigin + Vector( flNearestDist, flNearestDist, flNearestDist ); - - CBaseEntity *pNearest = NULL; - - int count = UTIL_EntitiesInBox( list, 256, mins, maxs, 0 ); - for( int i = 0 ; i < count ; i++ ) - { - if ( !list[ i ]->VPhysicsGetObject() ) - continue; - - // Closer than other objects - Vector los = ( list[ i ]->WorldSpaceCenter() - vecOrigin ); - float flDist = VectorNormalize( los ); - if( flDist >= flNearestDist ) - continue; - - // Cull to the cone - if ( DotProduct( los, vecDir ) <= flCone ) - continue; - - // Make sure it isn't occluded! - trace_t tr; - CTraceFilterNoOwnerTest filter( GetOwner(), COLLISION_GROUP_NONE ); - UTIL_TraceLine( vecOrigin, list[ i ]->WorldSpaceCenter(), MASK_SHOT|CONTENTS_GRATE, &filter, &tr ); - if( tr.m_pEnt == list[ i ] ) - { - flNearestDist = flDist; - pNearest = list[ i ]; - } - } - - return pNearest; -} - -#endif - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CGrabController::UpdateObject( CBasePlayer *pPlayer, float flError ) -{ - CBaseEntity *pEntity = GetAttached(); - if ( !pEntity ) - return false; - if ( ComputeError() > flError ) - return false; - if ( pPlayer->GetGroundEntity() == pEntity ) - return false; - if (!pEntity->VPhysicsGetObject() ) - return false; - - //Adrian: Oops, our object became motion disabled, let go! - IPhysicsObject *pPhys = pEntity->VPhysicsGetObject(); - if ( pPhys && pPhys->IsMoveable() == false ) - { - return false; - } - - if ( m_frameCount == gpGlobals->framecount ) - { - return true; - } - m_frameCount = gpGlobals->framecount; - Vector forward, right, up; - QAngle playerAngles = pPlayer->EyeAngles(); - - float pitch = AngleDistance(playerAngles.x,0); - playerAngles.x = clamp( pitch, -75, 75 ); - AngleVectors( playerAngles, &forward, &right, &up ); - - // Now clamp a sphere of object radius at end to the player's bbox - Vector radial = physcollision->CollideGetExtent( pPhys->GetCollide(), vec3_origin, pEntity->GetAbsAngles(), -forward ); - Vector player2d = pPlayer->CollisionProp()->OBBMaxs(); - float playerRadius = player2d.Length2D(); - float flDot = DotProduct( forward, radial ); - - float radius = playerRadius + fabs( flDot ); - - float distance = 24 + ( radius * 2.0f ); - - Vector start = pPlayer->Weapon_ShootPosition(); - Vector end = start + ( forward * distance ); - - trace_t tr; - CTraceFilterSkipTwoEntities traceFilter( pPlayer, pEntity, COLLISION_GROUP_NONE ); - Ray_t ray; - ray.Init( start, end ); - enginetrace->TraceRay( ray, MASK_SOLID_BRUSHONLY, &traceFilter, &tr ); - - if ( tr.fraction < 0.5 ) - { - end = start + forward * (radius*0.5f); - } - else if ( tr.fraction <= 1.0f ) - { - end = start + forward * ( distance - radius ); - } - - Vector playerMins, playerMaxs, nearest; - pPlayer->CollisionProp()->WorldSpaceAABB( &playerMins, &playerMaxs ); - Vector playerLine = pPlayer->CollisionProp()->WorldSpaceCenter(); - CalcClosestPointOnLine( end, playerLine+Vector(0,0,playerMins.z), playerLine+Vector(0,0,playerMaxs.z), nearest, NULL ); - - Vector delta = end - nearest; - float len = VectorNormalize(delta); - if ( len < radius ) - { - end = nearest + radius * delta; - } - - QAngle angles = TransformAnglesFromPlayerSpace( m_attachedAnglesPlayerSpace, pPlayer ); - - //Show overlays of radius - if ( g_debug_physcannon.GetBool() ) - { - -#ifdef CLIENT_DLL - - debugoverlay->AddBoxOverlay( end, -Vector( 2,2,2 ), Vector(2,2,2), angles, 0, 255, 255, true, 0 ); - - debugoverlay->AddBoxOverlay( GetAttached()->WorldSpaceCenter(), - -Vector( radius, radius, radius), - Vector( radius, radius, radius ), - angles, - 255, 255, 0, - true, - 0.0f ); - -#else - - NDebugOverlay::Box( end, -Vector( 2,2,2 ), Vector(2,2,2), 0, 255, 0, true, 0 ); - - NDebugOverlay::Box( GetAttached()->WorldSpaceCenter(), - -Vector( radius+5, radius+5, radius+5), - Vector( radius+5, radius+5, radius+5 ), - 255, 0, 0, - true, - 0.0f ); -#endif - } - -#ifndef CLIENT_DLL - // If it has a preferred orientation, update to ensure we're still oriented correctly. - Pickup_GetPreferredCarryAngles( pEntity, pPlayer, pPlayer->EntityToWorldTransform(), angles ); - - - // We may be holding a prop that has preferred carry angles - if ( m_bHasPreferredCarryAngles ) - { - matrix3x4_t tmp; - ComputePlayerMatrix( pPlayer, tmp ); - angles = TransformAnglesToWorldSpace( m_vecPreferredCarryAngles, tmp ); - } - -#endif - - matrix3x4_t attachedToWorld; - Vector offset; - AngleMatrix( angles, attachedToWorld ); - VectorRotate( m_attachedPositionObjectSpace, attachedToWorld, offset ); - - SetTargetPosition( end - offset, angles ); - - return true; -} - -void CWeaponPhysCannon::UpdateObject( void ) -{ - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - Assert( pPlayer ); - - float flError = 12; - if ( !m_grabController.UpdateObject( pPlayer, flError ) ) - { - DetachObject(); - return; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DetachObject( bool playSound, bool wasLaunched ) -{ -#ifndef CLIENT_DLL - if ( m_bActive == false ) - return; - - CHL2MP_Player *pOwner = (CHL2MP_Player *)ToBasePlayer( GetOwner() ); - if( pOwner != NULL ) - { - pOwner->EnableSprint( true ); - pOwner->SetMaxSpeed( hl2_normspeed.GetFloat() ); - } - - CBaseEntity *pObject = m_grabController.GetAttached(); - - m_grabController.DetachEntity( wasLaunched ); - - if ( pObject != NULL ) - { - Pickup_OnPhysGunDrop( pObject, pOwner, wasLaunched ? LAUNCHED_BY_CANNON : DROPPED_BY_CANNON ); - } - - // Stop our looping sound - if ( GetMotorSound() ) - { - (CSoundEnvelopeController::GetController()).SoundChangeVolume( GetMotorSound(), 0.0f, 1.0f ); - (CSoundEnvelopeController::GetController()).SoundChangePitch( GetMotorSound(), 50, 1.0f ); - } - - if ( pObject && m_bResetOwnerEntity == true ) - { - pObject->SetOwnerEntity( NULL ); - } - - m_bActive = false; - m_hAttachedObject = NULL; - - - if ( playSound ) - { - //Play the detach sound - WeaponSound( MELEE_MISS ); - } - -#else - - m_grabController.DetachEntity( wasLaunched ); - - if ( m_hAttachedObject ) - { - m_hAttachedObject->VPhysicsDestroyObject(); - } -#endif -} - - -#ifdef CLIENT_DLL -void CWeaponPhysCannon::ManagePredictedObject( void ) -{ - CBaseEntity *pAttachedObject = m_hAttachedObject.Get(); - - if ( m_hAttachedObject ) - { - // NOTE :This must happen after OnPhysGunPickup because that can change the mass - if ( pAttachedObject != GetGrabController().GetAttached() ) - { - IPhysicsObject *pPhysics = pAttachedObject->VPhysicsGetObject(); - - if ( pPhysics == NULL ) - { - solid_t tmpSolid; - PhysModelParseSolid( tmpSolid, m_hAttachedObject, pAttachedObject->GetModelIndex() ); - - pAttachedObject->VPhysicsInitNormal( SOLID_VPHYSICS, 0, false, &tmpSolid ); - } - - pPhysics = pAttachedObject->VPhysicsGetObject(); - - if ( pPhysics ) - { - m_grabController.SetIgnorePitch( false ); - m_grabController.SetAngleAlignment( 0 ); - - GetGrabController().AttachEntity( ToBasePlayer( GetOwner() ), pAttachedObject, pPhysics, false, vec3_origin, false ); - GetGrabController().m_attachedPositionObjectSpace = m_attachedPositionObjectSpace; - GetGrabController().m_attachedAnglesPlayerSpace = m_attachedAnglesPlayerSpace; - } - } - } - else - { - if ( m_hOldAttachedObject && m_hOldAttachedObject->VPhysicsGetObject() ) - { - GetGrabController().DetachEntity( false ); - - m_hOldAttachedObject->VPhysicsDestroyObject(); - } - } - - m_hOldAttachedObject = m_hAttachedObject; -} - -#endif - -#ifdef CLIENT_DLL - -//----------------------------------------------------------------------------- -// Purpose: Update the pose parameter for the gun -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::UpdateElementPosition( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - float flElementPosition = m_ElementParameter.Interp( gpGlobals->curtime ); - - if ( IsCarriedByLocalPlayer() ) - { - if ( pOwner != NULL ) - { - CBaseViewModel *vm = pOwner->GetViewModel(); - - if ( vm != NULL ) - { - vm->SetPoseParameter( "active", flElementPosition ); - } - } - } - else - { - SetPoseParameter( "active", flElementPosition ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Think function for the client -//----------------------------------------------------------------------------- - -void CWeaponPhysCannon::ClientThink( void ) -{ - // Update our elements visually - UpdateElementPosition(); - - // Update our effects - DoEffectIdle(); -} - -#endif // CLIENT_DLL - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::ItemPreFrame() -{ - BaseClass::ItemPreFrame(); - -#ifdef CLIENT_DLL - C_BasePlayer *localplayer = C_BasePlayer::GetLocalPlayer(); - - if ( localplayer && !localplayer->IsObserver() ) - ManagePredictedObject(); -#endif - - // Update the object if the weapon is switched on. - if( m_bActive ) - { - UpdateObject(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::CheckForTarget( void ) -{ -#ifndef CLIENT_DLL - //See if we're suppressing this - if ( m_flCheckSuppressTime > gpGlobals->curtime ) - return; - - // holstered - if ( IsEffectActive( EF_NODRAW ) ) - return; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - if ( m_bActive ) - return; - - Vector aimDir; - pOwner->EyeVectors( &aimDir ); - - Vector startPos = pOwner->Weapon_ShootPosition(); - Vector endPos; - VectorMA( startPos, TraceLength(), aimDir, endPos ); - - trace_t tr; - UTIL_TraceHull( startPos, endPos, -Vector(4,4,4), Vector(4,4,4), MASK_SHOT|CONTENTS_GRATE, pOwner, COLLISION_GROUP_NONE, &tr ); - - if ( ( tr.fraction != 1.0f ) && ( tr.m_pEnt != NULL ) ) - { - // FIXME: Try just having the elements always open when pointed at a physics object - if ( CanPickupObject( tr.m_pEnt ) || Pickup_ForcePhysGunOpen( tr.m_pEnt, pOwner ) ) - // if ( ( tr.m_pEnt->VPhysicsGetObject() != NULL ) && ( tr.m_pEnt->GetMoveType() == MOVETYPE_VPHYSICS ) ) - { - m_nChangeState = ELEMENT_STATE_NONE; - OpenElements(); - return; - } - } - - // Close the elements after a delay to prevent overact state switching - if ( ( m_flElementDebounce < gpGlobals->curtime ) && ( m_nChangeState == ELEMENT_STATE_NONE ) ) - { - m_nChangeState = ELEMENT_STATE_CLOSED; - m_flElementDebounce = gpGlobals->curtime + 0.5f; - } -#endif -} - - -//----------------------------------------------------------------------------- -// Purpose: Idle effect (pulsing) -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DoEffectIdle( void ) -{ -#ifdef CLIENT_DLL - - StartEffects(); - - //if ( IsCarriedByLocalPlayer() ) - { - // Turn on the glow sprites - for ( int i = PHYSCANNON_GLOW1; i < (PHYSCANNON_GLOW1+NUM_GLOW_SPRITES); i++ ) - { - m_Parameters[i].GetScale().SetAbsolute( random->RandomFloat( 0.075f, 0.05f ) * SPRITE_SCALE ); - m_Parameters[i].GetAlpha().SetAbsolute( random->RandomInt( 24, 32 ) ); - } - - // Turn on the glow sprites - for ( int i = PHYSCANNON_ENDCAP1; i < (PHYSCANNON_ENDCAP1+NUM_ENDCAP_SPRITES); i++ ) - { - m_Parameters[i].GetScale().SetAbsolute( random->RandomFloat( 3, 5 ) ); - m_Parameters[i].GetAlpha().SetAbsolute( random->RandomInt( 200, 255 ) ); - } - - if ( m_EffectState != EFFECT_HOLDING ) - { - // Turn beams off - m_Beams[0].SetVisible( false ); - m_Beams[1].SetVisible( false ); - m_Beams[2].SetVisible( false ); - } - } - /* - else - { - // Turn on the glow sprites - for ( int i = PHYSCANNON_GLOW1; i < (PHYSCANNON_GLOW1+NUM_GLOW_SPRITES); i++ ) - { - m_Parameters[i].GetScale().SetAbsolute( random->RandomFloat( 0.075f, 0.05f ) * SPRITE_SCALE ); - m_Parameters[i].GetAlpha().SetAbsolute( random->RandomInt( 24, 32 ) ); - } - - // Turn on the glow sprites - for ( i = PHYSCANNON_ENDCAP1; i < (PHYSCANNON_ENDCAP1+NUM_ENDCAP_SPRITES); i++ ) - { - m_Parameters[i].GetScale().SetAbsolute( random->RandomFloat( 3, 5 ) ); - m_Parameters[i].GetAlpha().SetAbsolute( random->RandomInt( 200, 255 ) ); - } - - if ( m_EffectState != EFFECT_HOLDING ) - { - // Turn beams off - m_Beams[0].SetVisible( false ); - m_Beams[1].SetVisible( false ); - m_Beams[2].SetVisible( false ); - } - } - */ -#endif -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::ItemPostFrame() -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( pOwner == NULL ) - { - // We found an object. Debounce the button - m_nAttack2Debounce = 0; - return; - } - - //Check for object in pickup range - if ( m_bActive == false ) - { - CheckForTarget(); - - if ( ( m_flElementDebounce < gpGlobals->curtime ) && ( m_nChangeState != ELEMENT_STATE_NONE ) ) - { - if ( m_nChangeState == ELEMENT_STATE_OPEN ) - { - OpenElements(); - } - else if ( m_nChangeState == ELEMENT_STATE_CLOSED ) - { - CloseElements(); - } - - m_nChangeState = ELEMENT_STATE_NONE; - } - } - - // NOTE: Attack2 will be considered to be pressed until the first item is picked up. - int nAttack2Mask = pOwner->m_nButtons & (~m_nAttack2Debounce); - if ( nAttack2Mask & IN_ATTACK2 ) - { - SecondaryAttack(); - } - else - { - // Reset our debouncer - m_flLastDenySoundPlayed = false; - - if ( m_bActive == false ) - { - DoEffect( EFFECT_READY ); - } - } - - if (( pOwner->m_nButtons & IN_ATTACK2 ) == 0 ) - { - m_nAttack2Debounce = 0; - } - - if ( pOwner->m_nButtons & IN_ATTACK ) - { - PrimaryAttack(); - } - else - { - WeaponIdle(); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -#define PHYSCANNON_DANGER_SOUND_RADIUS 128 - -void CWeaponPhysCannon::LaunchObject( const Vector &vecDir, float flForce ) -{ - CBaseEntity *pObject = m_grabController.GetAttached(); - - if ( !(m_hLastPuntedObject == pObject && gpGlobals->curtime < m_flRepuntObjectTime) ) - { - // FIRE!!! - if( pObject != NULL ) - { - DetachObject( false, true ); - - m_hLastPuntedObject = pObject; - m_flRepuntObjectTime = gpGlobals->curtime + 0.5f; - - // Launch - ApplyVelocityBasedForce( pObject, vecDir ); - - // Don't allow the gun to regrab a thrown object!! - m_flNextSecondaryAttack = m_flNextPrimaryAttack = gpGlobals->curtime + 0.5; - - Vector center = pObject->WorldSpaceCenter(); - - //Do repulse effect - DoEffect( EFFECT_LAUNCH, ¢er ); - - m_hAttachedObject = NULL; - m_bActive = false; - } - } - - // Stop our looping sound - if ( GetMotorSound() ) - { - (CSoundEnvelopeController::GetController()).SoundChangeVolume( GetMotorSound(), 0.0f, 1.0f ); - (CSoundEnvelopeController::GetController()).SoundChangePitch( GetMotorSound(), 50, 1.0f ); - } - - //Close the elements and suppress checking for a bit - m_nChangeState = ELEMENT_STATE_CLOSED; - m_flElementDebounce = gpGlobals->curtime + 0.1f; - m_flCheckSuppressTime = gpGlobals->curtime + 0.25f; -} - -bool UTIL_IsCombineBall( CBaseEntity *pEntity ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pTarget - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponPhysCannon::CanPickupObject( CBaseEntity *pTarget ) -{ -#ifndef CLIENT_DLL - if ( pTarget == NULL ) - return false; - - if ( pTarget->GetBaseAnimating() && pTarget->GetBaseAnimating()->IsDissolving() ) - return false; - - if ( pTarget->IsEFlagSet( EFL_NO_PHYSCANNON_INTERACTION ) ) - return false; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner && pOwner->GetGroundEntity() == pTarget ) - return false; - - if ( pTarget->VPhysicsIsFlesh( ) ) - return false; - - IPhysicsObject *pObj = pTarget->VPhysicsGetObject(); - - if ( pObj && pObj->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - return false; - - if ( UTIL_IsCombineBall( pTarget ) ) - { - return CBasePlayer::CanPickupObject( pTarget, 0, 0 ); - } - - return CBasePlayer::CanPickupObject( pTarget, physcannon_maxmass.GetFloat(), 0 ); -#else - return false; -#endif - -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::OpenElements( void ) -{ - if ( m_bOpen ) - return; - - WeaponSound( SPECIAL2 ); - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - SendWeaponAnim( ACT_VM_IDLE ); - - m_bOpen = true; - - DoEffect( EFFECT_READY ); - -#ifdef CLIENT - // Element prediction - m_ElementParameter.InitFromCurrent( 1.0f, 0.2f, INTERP_SPLINE ); - m_bOldOpen = true; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::CloseElements( void ) -{ - if ( m_bOpen == false ) - return; - - WeaponSound( MELEE_HIT ); - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - SendWeaponAnim( ACT_VM_IDLE ); - - m_bOpen = false; - - if ( GetMotorSound() ) - { - (CSoundEnvelopeController::GetController()).SoundChangeVolume( GetMotorSound(), 0.0f, 1.0f ); - (CSoundEnvelopeController::GetController()).SoundChangePitch( GetMotorSound(), 50, 1.0f ); - } - - DoEffect( EFFECT_CLOSED ); - -#ifdef CLIENT - // Element prediction - m_ElementParameter.InitFromCurrent( 0.0f, 0.5f, INTERP_SPLINE ); - m_bOldOpen = false; -#endif -} - -#define PHYSCANNON_MAX_MASS 500 - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : float -//----------------------------------------------------------------------------- -float CWeaponPhysCannon::GetLoadPercentage( void ) -{ - float loadWeight = m_grabController.GetLoadWeight(); - loadWeight /= physcannon_maxmass.GetFloat(); - loadWeight = clamp( loadWeight, 0.0f, 1.0f ); - return loadWeight; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CSoundPatch -//----------------------------------------------------------------------------- -CSoundPatch *CWeaponPhysCannon::GetMotorSound( void ) -{ - if ( m_sndMotor == NULL ) - { - CPASAttenuationFilter filter( this ); - - m_sndMotor = (CSoundEnvelopeController::GetController()).SoundCreate( filter, entindex(), CHAN_STATIC, "Weapon_PhysCannon.HoldSound", ATTN_NORM ); - } - - return m_sndMotor; -} - - -//----------------------------------------------------------------------------- -// Shuts down sounds -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::StopLoopingSounds() -{ - if ( m_sndMotor != NULL ) - { - (CSoundEnvelopeController::GetController()).SoundDestroy( m_sndMotor ); - m_sndMotor = NULL; - } - -#ifndef CLIENT_DLL - BaseClass::StopLoopingSounds(); -#endif - -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DestroyEffects( void ) -{ -#ifdef CLIENT_DLL - - // Free our beams - m_Beams[0].Release(); - m_Beams[1].Release(); - m_Beams[2].Release(); - -#endif - - // Stop everything - StopEffects(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::StopEffects( bool stopSound ) -{ - // Turn off our effect state - DoEffect( EFFECT_NONE ); - -#ifndef CLIENT_DLL - //Shut off sounds - if ( stopSound && GetMotorSound() != NULL ) - { - (CSoundEnvelopeController::GetController()).SoundFadeOut( GetMotorSound(), 0.1f ); - } -#endif // !CLIENT_DLL -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::StartEffects( void ) -{ -#ifdef CLIENT_DLL - - // ------------------------------------------ - // Core - // ------------------------------------------ - - if ( m_Parameters[PHYSCANNON_CORE].GetMaterial() == NULL ) - { - m_Parameters[PHYSCANNON_CORE].GetScale().Init( 0.0f, 1.0f, 0.1f ); - m_Parameters[PHYSCANNON_CORE].GetAlpha().Init( 255.0f, 255.0f, 0.1f ); - m_Parameters[PHYSCANNON_CORE].SetAttachment( 1 ); - - if ( m_Parameters[PHYSCANNON_CORE].SetMaterial( PHYSCANNON_CENTER_GLOW ) == false ) - { - // This means the texture was not found - Assert( 0 ); - } - } - - // ------------------------------------------ - // Blast - // ------------------------------------------ - - if ( m_Parameters[PHYSCANNON_BLAST].GetMaterial() == NULL ) - { - m_Parameters[PHYSCANNON_BLAST].GetScale().Init( 0.0f, 1.0f, 0.1f ); - m_Parameters[PHYSCANNON_BLAST].GetAlpha().Init( 255.0f, 255.0f, 0.1f ); - m_Parameters[PHYSCANNON_BLAST].SetAttachment( 1 ); - m_Parameters[PHYSCANNON_BLAST].SetVisible( false ); - - if ( m_Parameters[PHYSCANNON_BLAST].SetMaterial( PHYSCANNON_BLAST_SPRITE ) == false ) - { - // This means the texture was not found - Assert( 0 ); - } - } - - // ------------------------------------------ - // Glows - // ------------------------------------------ - - const char *attachNamesGlowThirdPerson[NUM_GLOW_SPRITES] = - { - "fork1m", - "fork1t", - "fork2m", - "fork2t", - "fork3m", - "fork3t", - }; - - const char *attachNamesGlow[NUM_GLOW_SPRITES] = - { - "fork1b", - "fork1m", - "fork1t", - "fork2b", - "fork2m", - "fork2t" - }; - - //Create the glow sprites - for ( int i = PHYSCANNON_GLOW1; i < (PHYSCANNON_GLOW1+NUM_GLOW_SPRITES); i++ ) - { - if ( m_Parameters[i].GetMaterial() != NULL ) - continue; - - m_Parameters[i].GetScale().SetAbsolute( 0.05f * SPRITE_SCALE ); - m_Parameters[i].GetAlpha().SetAbsolute( 64.0f ); - - // Different for different views - if ( IsCarriedByLocalPlayer() ) - { - m_Parameters[i].SetAttachment( LookupAttachment( attachNamesGlow[i-PHYSCANNON_GLOW1] ) ); - } - else - { - m_Parameters[i].SetAttachment( LookupAttachment( attachNamesGlowThirdPerson[i-PHYSCANNON_GLOW1] ) ); - } - m_Parameters[i].SetColor( Vector( 255, 128, 0 ) ); - - if ( m_Parameters[i].SetMaterial( PHYSCANNON_GLOW_SPRITE ) == false ) - { - // This means the texture was not found - Assert( 0 ); - } - } - - // ------------------------------------------ - // End caps - // ------------------------------------------ - - const char *attachNamesEndCap[NUM_ENDCAP_SPRITES] = - { - "fork1t", - "fork2t", - "fork3t" - }; - - //Create the glow sprites - for ( int i = PHYSCANNON_ENDCAP1; i < (PHYSCANNON_ENDCAP1+NUM_ENDCAP_SPRITES); i++ ) - { - if ( m_Parameters[i].GetMaterial() != NULL ) - continue; - - m_Parameters[i].GetScale().SetAbsolute( 0.05f * SPRITE_SCALE ); - m_Parameters[i].GetAlpha().SetAbsolute( 255.0f ); - m_Parameters[i].SetAttachment( LookupAttachment( attachNamesEndCap[i-PHYSCANNON_ENDCAP1] ) ); - m_Parameters[i].SetVisible( false ); - - if ( m_Parameters[i].SetMaterial( PHYSCANNON_ENDCAP_SPRITE ) == false ) - { - // This means the texture was not found - Assert( 0 ); - } - } - -#endif - -} - -//----------------------------------------------------------------------------- -// Purpose: Closing effects -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DoEffectClosed( void ) -{ - -#ifdef CLIENT_DLL - - // Turn off the end-caps - for ( int i = PHYSCANNON_ENDCAP1; i < (PHYSCANNON_ENDCAP1+NUM_ENDCAP_SPRITES); i++ ) - { - m_Parameters[i].SetVisible( false ); - } - -#endif - -} - -//----------------------------------------------------------------------------- -// Purpose: Ready effects -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DoEffectReady( void ) -{ - -#ifdef CLIENT_DLL - - // Special POV case - if ( IsCarriedByLocalPlayer() ) - { - //Turn on the center sprite - m_Parameters[PHYSCANNON_CORE].GetScale().InitFromCurrent( 14.0f, 0.2f ); - m_Parameters[PHYSCANNON_CORE].GetAlpha().InitFromCurrent( 128.0f, 0.2f ); - m_Parameters[PHYSCANNON_CORE].SetVisible(); - } - else - { - //Turn off the center sprite - m_Parameters[PHYSCANNON_CORE].GetScale().InitFromCurrent( 8.0f, 0.2f ); - m_Parameters[PHYSCANNON_CORE].GetAlpha().InitFromCurrent( 0.0f, 0.2f ); - m_Parameters[PHYSCANNON_CORE].SetVisible(); - } - - // Turn on the glow sprites - for ( int i = PHYSCANNON_GLOW1; i < (PHYSCANNON_GLOW1+NUM_GLOW_SPRITES); i++ ) - { - m_Parameters[i].GetScale().InitFromCurrent( 0.4f * SPRITE_SCALE, 0.2f ); - m_Parameters[i].GetAlpha().InitFromCurrent( 64.0f, 0.2f ); - m_Parameters[i].SetVisible(); - } - - // Turn on the glow sprites - for ( int i = PHYSCANNON_ENDCAP1; i < (PHYSCANNON_ENDCAP1+NUM_ENDCAP_SPRITES); i++ ) - { - m_Parameters[i].SetVisible( false ); - } - -#endif - -} - - -//----------------------------------------------------------------------------- -// Holding effects -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DoEffectHolding( void ) -{ - -#ifdef CLIENT_DLL - - if ( IsCarriedByLocalPlayer() ) - { - // Scale up the center sprite - m_Parameters[PHYSCANNON_CORE].GetScale().InitFromCurrent( 16.0f, 0.2f ); - m_Parameters[PHYSCANNON_CORE].GetAlpha().InitFromCurrent( 255.0f, 0.1f ); - m_Parameters[PHYSCANNON_CORE].SetVisible(); - - // Prepare for scale up - m_Parameters[PHYSCANNON_BLAST].SetVisible( false ); - - // Turn on the glow sprites - for ( int i = PHYSCANNON_GLOW1; i < (PHYSCANNON_GLOW1+NUM_GLOW_SPRITES); i++ ) - { - m_Parameters[i].GetScale().InitFromCurrent( 0.5f * SPRITE_SCALE, 0.2f ); - m_Parameters[i].GetAlpha().InitFromCurrent( 64.0f, 0.2f ); - m_Parameters[i].SetVisible(); - } - - // Turn on the glow sprites - // NOTE: The last glow is left off for first-person - for ( int i = PHYSCANNON_ENDCAP1; i < (PHYSCANNON_ENDCAP1+NUM_ENDCAP_SPRITES-1); i++ ) - { - m_Parameters[i].SetVisible(); - } - - // Create our beams - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - CBaseEntity *pBeamEnt = pOwner->GetViewModel(); - - // Setup the beams - m_Beams[0].Init( LookupAttachment( "fork1t" ), 1, pBeamEnt, true ); - m_Beams[1].Init( LookupAttachment( "fork2t" ), 1, pBeamEnt, true ); - - // Set them visible - m_Beams[0].SetVisible(); - m_Beams[1].SetVisible(); - } - else - { - // Scale up the center sprite - m_Parameters[PHYSCANNON_CORE].GetScale().InitFromCurrent( 14.0f, 0.2f ); - m_Parameters[PHYSCANNON_CORE].GetAlpha().InitFromCurrent( 255.0f, 0.1f ); - m_Parameters[PHYSCANNON_CORE].SetVisible(); - - // Prepare for scale up - m_Parameters[PHYSCANNON_BLAST].SetVisible( false ); - - // Turn on the glow sprites - for ( int i = PHYSCANNON_GLOW1; i < (PHYSCANNON_GLOW1+NUM_GLOW_SPRITES); i++ ) - { - m_Parameters[i].GetScale().InitFromCurrent( 0.5f * SPRITE_SCALE, 0.2f ); - m_Parameters[i].GetAlpha().InitFromCurrent( 64.0f, 0.2f ); - m_Parameters[i].SetVisible(); - } - - // Turn on the glow sprites - for ( int i = PHYSCANNON_ENDCAP1; i < (PHYSCANNON_ENDCAP1+NUM_ENDCAP_SPRITES); i++ ) - { - m_Parameters[i].SetVisible(); - } - - // Setup the beams - m_Beams[0].Init( LookupAttachment( "fork1t" ), 1, this, false ); - m_Beams[1].Init( LookupAttachment( "fork2t" ), 1, this, false ); - m_Beams[2].Init( LookupAttachment( "fork3t" ), 1, this, false ); - - // Set them visible - m_Beams[0].SetVisible(); - m_Beams[1].SetVisible(); - m_Beams[2].SetVisible(); - } - -#endif - -} - - -//----------------------------------------------------------------------------- -// Launch effects -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DoEffectLaunch( Vector *pos ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if ( pOwner == NULL ) - return; - - Vector endPos; - Vector shotDir; - - // See if we need to predict this position - if ( pos == NULL ) - { - // Hit an entity if we're holding one - if ( m_hAttachedObject ) - { - endPos = m_hAttachedObject->WorldSpaceCenter(); - - shotDir = endPos - pOwner->Weapon_ShootPosition(); - VectorNormalize( shotDir ); - } - else - { - // Otherwise try and find the right spot - endPos = pOwner->Weapon_ShootPosition(); - pOwner->EyeVectors( &shotDir ); - - trace_t tr; - UTIL_TraceLine( endPos, endPos + ( shotDir * MAX_TRACE_LENGTH ), MASK_SHOT, pOwner, COLLISION_GROUP_NONE, &tr ); - - endPos = tr.endpos; - shotDir = endPos - pOwner->Weapon_ShootPosition(); - VectorNormalize( shotDir ); - } - } - else - { - // Use what is supplied - endPos = *pos; - shotDir = ( endPos - pOwner->Weapon_ShootPosition() ); - VectorNormalize( shotDir ); - } - - // End hit - CPVSFilter filter( endPos ); - - // Don't send this to the owning player, they already had it predicted - if ( IsPredicted() ) - { - filter.UsePredictionRules(); - } - - // Do an impact hit - CEffectData data; - data.m_vOrigin = endPos; -#ifdef CLIENT_DLL - data.m_hEntity = GetRefEHandle(); -#else - data.m_nEntIndex = entindex(); -#endif - - te->DispatchEffect( filter, 0.0, data.m_vOrigin, "PhyscannonImpact", data ); - -#ifdef CLIENT_DLL - - //Turn on the blast sprite and scale - m_Parameters[PHYSCANNON_BLAST].GetScale().Init( 8.0f, 64.0f, 0.1f ); - m_Parameters[PHYSCANNON_BLAST].GetAlpha().Init( 255.0f, 0.0f, 0.2f ); - m_Parameters[PHYSCANNON_BLAST].SetVisible(); - -#endif - -} - -//----------------------------------------------------------------------------- -// Purpose: Shutdown for the weapon when it's holstered -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DoEffectNone( void ) -{ -#ifdef CLIENT_DLL - - //Turn off main glows - m_Parameters[PHYSCANNON_CORE].SetVisible( false ); - m_Parameters[PHYSCANNON_BLAST].SetVisible( false ); - - for ( int i = PHYSCANNON_GLOW1; i < (PHYSCANNON_GLOW1+NUM_GLOW_SPRITES); i++ ) - { - m_Parameters[i].SetVisible( false ); - } - - // Turn on the glow sprites - for ( int i = PHYSCANNON_ENDCAP1; i < (PHYSCANNON_ENDCAP1+NUM_ENDCAP_SPRITES); i++ ) - { - m_Parameters[i].SetVisible( false ); - } - - m_Beams[0].SetVisible( false ); - m_Beams[1].SetVisible( false ); - m_Beams[2].SetVisible( false ); - -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : effectType - -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DoEffect( int effectType, Vector *pos ) -{ - m_EffectState = effectType; - -#ifdef CLIENT_DLL - // Save predicted state - m_nOldEffectState = m_EffectState; -#endif - - switch( effectType ) - { - case EFFECT_CLOSED: - DoEffectClosed( ); - break; - - case EFFECT_READY: - DoEffectReady( ); - break; - - case EFFECT_HOLDING: - DoEffectHolding(); - break; - - case EFFECT_LAUNCH: - DoEffectLaunch( pos ); - break; - - default: - case EFFECT_NONE: - DoEffectNone(); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iIndex - -// Output : const char -//----------------------------------------------------------------------------- -const char *CWeaponPhysCannon::GetShootSound( int iIndex ) const -{ - return BaseClass::GetShootSound( iIndex ); -} - -#ifdef CLIENT_DLL - -extern void FormatViewModelAttachment( Vector &vOrigin, bool bInverse ); - -//----------------------------------------------------------------------------- -// Purpose: Gets the complete list of values needed to render an effect from an -// effect parameter -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::GetEffectParameters( EffectType_t effectID, color32 &color, float &scale, IMaterial **pMaterial, Vector &vecAttachment ) -{ - const float dt = gpGlobals->curtime; - - // Get alpha - float alpha = m_Parameters[effectID].GetAlpha().Interp( dt ); - - // Get scale - scale = m_Parameters[effectID].GetScale().Interp( dt ); - - // Get material - *pMaterial = (IMaterial *) m_Parameters[effectID].GetMaterial(); - - // Setup the color - color.r = (int) m_Parameters[effectID].GetColor().x; - color.g = (int) m_Parameters[effectID].GetColor().y; - color.b = (int) m_Parameters[effectID].GetColor().z; - color.a = (int) alpha; - - // Setup the attachment - int attachment = m_Parameters[effectID].GetAttachment(); - QAngle angles; - - // Format for first-person - if ( IsCarriedByLocalPlayer() ) - { - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner != NULL ) - { - pOwner->GetViewModel()->GetAttachment( attachment, vecAttachment, angles ); - ::FormatViewModelAttachment( vecAttachment, true ); - } - } - else - { - GetAttachment( attachment, vecAttachment, angles ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Whether or not an effect is set to display -//----------------------------------------------------------------------------- -bool CWeaponPhysCannon::IsEffectVisible( EffectType_t effectID ) -{ - return m_Parameters[effectID].IsVisible(); -} - -//----------------------------------------------------------------------------- -// Purpose: Draws the effect sprite, given an effect parameter ID -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DrawEffectSprite( EffectType_t effectID ) -{ - color32 color; - float scale; - IMaterial *pMaterial; - Vector vecAttachment; - - // Don't draw invisible effects - if ( IsEffectVisible( effectID ) == false ) - return; - - // Get all of our parameters - GetEffectParameters( effectID, color, scale, &pMaterial, vecAttachment ); - - // Msg( "Scale: %.2f\tAlpha: %.2f\n", scale, alpha ); - - // Don't render fully translucent objects - if ( color.a <= 0.0f ) - return; - - // Draw the sprite - CMatRenderContextPtr pRenderContext( materials ); - pRenderContext->Bind( pMaterial, this ); - DrawSprite( vecAttachment, scale, scale, color ); -} - -//----------------------------------------------------------------------------- -// Purpose: Render our third-person effects -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::DrawEffects( void ) -{ - // Draw the core effects - DrawEffectSprite( PHYSCANNON_CORE ); - DrawEffectSprite( PHYSCANNON_BLAST ); - - // Draw the glows - for ( int i = PHYSCANNON_GLOW1; i < (PHYSCANNON_GLOW1+NUM_GLOW_SPRITES); i++ ) - { - DrawEffectSprite( (EffectType_t) i ); - } - - // Draw the endcaps - for ( int i = PHYSCANNON_ENDCAP1; i < (PHYSCANNON_ENDCAP1+NUM_ENDCAP_SPRITES); i++ ) - { - DrawEffectSprite( (EffectType_t) i ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Third-person function call to render world model -//----------------------------------------------------------------------------- -int CWeaponPhysCannon::DrawModel( int flags ) -{ - // Only render these on the transparent pass - if ( flags & STUDIO_TRANSPARENCY ) - { - DrawEffects(); - return 1; - } - - // Only do this on the opaque pass - return BaseClass::DrawModel( flags ); -} - -//----------------------------------------------------------------------------- -// Purpose: First-person function call after viewmodel has been drawn -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::ViewModelDrawn( C_BaseViewModel *pBaseViewModel ) -{ - // Render our effects - DrawEffects(); - - // Pass this back up - BaseClass::ViewModelDrawn( pBaseViewModel ); -} - -//----------------------------------------------------------------------------- -// Purpose: We are always considered transparent -//----------------------------------------------------------------------------- -bool CWeaponPhysCannon::IsTransparent( void ) -{ - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPhysCannon::NotifyShouldTransmit( ShouldTransmitState_t state ) -{ - BaseClass::NotifyShouldTransmit(state); - - if ( state == SHOULDTRANSMIT_END ) - { - DoEffect( EFFECT_NONE ); - } -} - -#endif - -//----------------------------------------------------------------------------- -// EXTERNAL API -//----------------------------------------------------------------------------- -void PhysCannonForceDrop( CBaseCombatWeapon *pActiveWeapon, CBaseEntity *pOnlyIfHoldingThis ) -{ - CWeaponPhysCannon *pCannon = dynamic_cast(pActiveWeapon); - if ( pCannon ) - { - if ( pOnlyIfHoldingThis ) - { - pCannon->DropIfEntityHeld( pOnlyIfHoldingThis ); - } - else - { - pCannon->ForceDrop(); - } - } -} - -bool PlayerPickupControllerIsHoldingEntity( CBaseEntity *pPickupControllerEntity, CBaseEntity *pHeldEntity ) -{ - CPlayerPickupController *pController = dynamic_cast(pPickupControllerEntity); - - return pController ? pController->IsHoldingEntity( pHeldEntity ) : false; -} - - -float PhysCannonGetHeldObjectMass( CBaseCombatWeapon *pActiveWeapon, IPhysicsObject *pHeldObject ) -{ - float mass = 0.0f; - CWeaponPhysCannon *pCannon = dynamic_cast(pActiveWeapon); - if ( pCannon ) - { - CGrabController &grab = pCannon->GetGrabController(); - mass = grab.GetSavedMass( pHeldObject ); - } - - return mass; -} - -CBaseEntity *PhysCannonGetHeldEntity( CBaseCombatWeapon *pActiveWeapon ) -{ - CWeaponPhysCannon *pCannon = dynamic_cast(pActiveWeapon); - if ( pCannon ) - { - CGrabController &grab = pCannon->GetGrabController(); - return grab.GetAttached(); - } - - return NULL; -} - -float PlayerPickupGetHeldObjectMass( CBaseEntity *pPickupControllerEntity, IPhysicsObject *pHeldObject ) -{ - float mass = 0.0f; - CPlayerPickupController *pController = dynamic_cast(pPickupControllerEntity); - if ( pController ) - { - CGrabController &grab = pController->GetGrabController(); - mass = grab.GetSavedMass( pHeldObject ); - } - return mass; -} - -#ifdef CLIENT_DLL - -extern void FX_GaussExplosion( const Vector &pos, const Vector &dir, int type ); - -void CallbackPhyscannonImpact( const CEffectData &data ) -{ - C_BaseEntity *pEnt = data.GetEntity(); - if ( pEnt == NULL ) - return; - - Vector vecAttachment; - QAngle vecAngles; - - C_BaseCombatWeapon *pWeapon = dynamic_cast(pEnt); - - if ( pWeapon == NULL ) - return; - - pWeapon->GetAttachment( 1, vecAttachment, vecAngles ); - - Vector dir = ( data.m_vOrigin - vecAttachment ); - VectorNormalize( dir ); - - // Do special first-person fix-up - if ( pWeapon->GetOwner() == CBasePlayer::GetLocalPlayer() ) - { - // Translate the attachment entity to the viewmodel - C_BasePlayer *pPlayer = dynamic_cast(pWeapon->GetOwner()); - - if ( pPlayer ) - { - pEnt = pPlayer->GetViewModel(); - } - - // Format attachment for first-person view! - ::FormatViewModelAttachment( vecAttachment, true ); - - // Explosions at the impact point - FX_GaussExplosion( data.m_vOrigin, -dir, 0 ); - - // Draw a beam - BeamInfo_t beamInfo; - - beamInfo.m_pStartEnt = pEnt; - beamInfo.m_nStartAttachment = 1; - beamInfo.m_pEndEnt = NULL; - beamInfo.m_nEndAttachment = -1; - beamInfo.m_vecStart = vec3_origin; - beamInfo.m_vecEnd = data.m_vOrigin; - beamInfo.m_pszModelName = PHYSCANNON_BEAM_SPRITE; - beamInfo.m_flHaloScale = 0.0f; - beamInfo.m_flLife = 0.1f; - beamInfo.m_flWidth = 12.0f; - beamInfo.m_flEndWidth = 4.0f; - beamInfo.m_flFadeLength = 0.0f; - beamInfo.m_flAmplitude = 0; - beamInfo.m_flBrightness = 255.0; - beamInfo.m_flSpeed = 0.0f; - beamInfo.m_nStartFrame = 0.0; - beamInfo.m_flFrameRate = 30.0; - beamInfo.m_flRed = 255.0; - beamInfo.m_flGreen = 255.0; - beamInfo.m_flBlue = 255.0; - beamInfo.m_nSegments = 16; - beamInfo.m_bRenderable = true; - beamInfo.m_nFlags = FBEAM_ONLYNOISEONCE; - - beams->CreateBeamEntPoint( beamInfo ); - } - else - { - // Explosion at the starting point - FX_GaussExplosion( vecAttachment, dir, 0 ); - } -} - -DECLARE_CLIENT_EFFECT( "PhyscannonImpact", CallbackPhyscannonImpact ); - -#endif diff --git a/game/shared/hl2mp/weapon_physcannon.h b/game/shared/hl2mp/weapon_physcannon.h deleted file mode 100644 index 622b0526a..000000000 --- a/game/shared/hl2mp/weapon_physcannon.h +++ /dev/null @@ -1,30 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef WEAPON_PHYSCANNON_H -#define WEAPON_PHYSCANNON_H -#ifdef _WIN32 -#pragma once -#endif - - - -//----------------------------------------------------------------------------- -// Do we have the super-phys gun? -//----------------------------------------------------------------------------- -bool PlayerHasMegaPhysCannon(); - -// force the physcannon to drop an object (if carried) -void PhysCannonForceDrop( CBaseCombatWeapon *pActiveWeapon, CBaseEntity *pOnlyIfHoldingThis ); -void PhysCannonBeginUpgrade( CBaseAnimating *pAnim ); - -bool PlayerPickupControllerIsHoldingEntity( CBaseEntity *pPickupController, CBaseEntity *pHeldEntity ); -float PlayerPickupGetHeldObjectMass( CBaseEntity *pPickupControllerEntity, IPhysicsObject *pHeldObject ); -float PhysCannonGetHeldObjectMass( CBaseCombatWeapon *pActiveWeapon, IPhysicsObject *pHeldObject ); - -CBaseEntity *PhysCannonGetHeldEntity( CBaseCombatWeapon *pActiveWeapon ); - -#endif // WEAPON_PHYSCANNON_H diff --git a/game/shared/hl2mp/weapon_pistol.cpp b/game/shared/hl2mp/weapon_pistol.cpp deleted file mode 100644 index 1b835578a..000000000 --- a/game/shared/hl2mp/weapon_pistol.cpp +++ /dev/null @@ -1,339 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" -#include "in_buttons.h" - -#ifdef CLIENT_DLL - #include "c_hl2mp_player.h" -#else - #include "hl2mp_player.h" -#endif - -#include "weapon_hl2mpbasehlmpcombatweapon.h" - -#define PISTOL_FASTEST_REFIRE_TIME 0.1f -#define PISTOL_FASTEST_DRY_REFIRE_TIME 0.2f - -#define PISTOL_ACCURACY_SHOT_PENALTY_TIME 0.2f // Applied amount of time each shot adds to the time we must recover from -#define PISTOL_ACCURACY_MAXIMUM_PENALTY_TIME 1.5f // Maximum penalty to deal out - -#ifdef CLIENT_DLL -#define CWeaponPistol C_WeaponPistol -#endif - -//----------------------------------------------------------------------------- -// CWeaponPistol -//----------------------------------------------------------------------------- - -class CWeaponPistol : public CBaseHL2MPCombatWeapon -{ -public: - DECLARE_CLASS( CWeaponPistol, CBaseHL2MPCombatWeapon ); - - CWeaponPistol(void); - - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - - void Precache( void ); - void ItemPostFrame( void ); - void ItemPreFrame( void ); - void ItemBusyFrame( void ); - void PrimaryAttack( void ); - void AddViewKick( void ); - void DryFire( void ); - - void UpdatePenaltyTime( void ); - - Activity GetPrimaryAttackActivity( void ); - - virtual bool Reload( void ); - - virtual const Vector& GetBulletSpread( void ) - { - static Vector cone; - - float ramp = RemapValClamped( m_flAccuracyPenalty, - 0.0f, - PISTOL_ACCURACY_MAXIMUM_PENALTY_TIME, - 0.0f, - 1.0f ); - - // We lerp from very accurate to inaccurate over time - VectorLerp( VECTOR_CONE_1DEGREES, VECTOR_CONE_6DEGREES, ramp, cone ); - - return cone; - } - - virtual int GetMinBurst() - { - return 1; - } - - virtual int GetMaxBurst() - { - return 3; - } - - virtual float GetFireRate( void ) - { - return 0.5f; - } - -#ifndef CLIENT_DLL - DECLARE_ACTTABLE(); -#endif - -private: - CNetworkVar( float, m_flSoonestPrimaryAttack ); - CNetworkVar( float, m_flLastAttackTime ); - CNetworkVar( float, m_flAccuracyPenalty ); - CNetworkVar( int, m_nNumShotsFired ); - -private: - CWeaponPistol( const CWeaponPistol & ); -}; - -IMPLEMENT_NETWORKCLASS_ALIASED( WeaponPistol, DT_WeaponPistol ) - -BEGIN_NETWORK_TABLE( CWeaponPistol, DT_WeaponPistol ) -#ifdef CLIENT_DLL - RecvPropTime( RECVINFO( m_flSoonestPrimaryAttack ) ), - RecvPropTime( RECVINFO( m_flLastAttackTime ) ), - RecvPropFloat( RECVINFO( m_flAccuracyPenalty ) ), - RecvPropInt( RECVINFO( m_nNumShotsFired ) ), -#else - SendPropTime( SENDINFO( m_flSoonestPrimaryAttack ) ), - SendPropTime( SENDINFO( m_flLastAttackTime ) ), - SendPropFloat( SENDINFO( m_flAccuracyPenalty ) ), - SendPropInt( SENDINFO( m_nNumShotsFired ) ), -#endif -END_NETWORK_TABLE() - -#ifdef CLIENT_DLL -BEGIN_PREDICTION_DATA( CWeaponPistol ) - DEFINE_PRED_FIELD( m_flSoonestPrimaryAttack, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_flLastAttackTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_flAccuracyPenalty, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_nNumShotsFired, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), -END_PREDICTION_DATA() -#endif - -LINK_ENTITY_TO_CLASS( weapon_pistol, CWeaponPistol ); -PRECACHE_WEAPON_REGISTER( weapon_pistol ); - -#ifndef CLIENT_DLL -acttable_t CWeaponPistol::m_acttable[] = -{ - { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_PISTOL, false }, - { ACT_HL2MP_RUN, ACT_HL2MP_RUN_PISTOL, false }, - { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_PISTOL, false }, - { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_PISTOL, false }, - { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_PISTOL, false }, - { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_PISTOL, false }, - { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_PISTOL, false }, - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_PISTOL, false }, -}; - - -IMPLEMENT_ACTTABLE( CWeaponPistol ); - -#endif - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -CWeaponPistol::CWeaponPistol( void ) -{ - m_flSoonestPrimaryAttack = gpGlobals->curtime; - m_flAccuracyPenalty = 0.0f; - - m_fMinRange1 = 24; - m_fMaxRange1 = 1500; - m_fMinRange2 = 24; - m_fMaxRange2 = 200; - - m_bFiresUnderwater = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPistol::Precache( void ) -{ - BaseClass::Precache(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPistol::DryFire( void ) -{ - WeaponSound( EMPTY ); - SendWeaponAnim( ACT_VM_DRYFIRE ); - - m_flSoonestPrimaryAttack = gpGlobals->curtime + PISTOL_FASTEST_DRY_REFIRE_TIME; - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPistol::PrimaryAttack( void ) -{ - if ( ( gpGlobals->curtime - m_flLastAttackTime ) > 0.5f ) - { - m_nNumShotsFired = 0; - } - else - { - m_nNumShotsFired++; - } - - m_flLastAttackTime = gpGlobals->curtime; - m_flSoonestPrimaryAttack = gpGlobals->curtime + PISTOL_FASTEST_REFIRE_TIME; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if( pOwner ) - { - // Each time the player fires the pistol, reset the view punch. This prevents - // the aim from 'drifting off' when the player fires very quickly. This may - // not be the ideal way to achieve this, but it's cheap and it works, which is - // great for a feature we're evaluating. (sjb) - pOwner->ViewPunchReset(); - } - - BaseClass::PrimaryAttack(); - - // Add an accuracy penalty which can move past our maximum penalty time if we're really spastic - m_flAccuracyPenalty += PISTOL_ACCURACY_SHOT_PENALTY_TIME; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPistol::UpdatePenaltyTime( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - // Check our penalty time decay - if ( ( ( pOwner->m_nButtons & IN_ATTACK ) == false ) && ( m_flSoonestPrimaryAttack < gpGlobals->curtime ) ) - { - m_flAccuracyPenalty -= gpGlobals->frametime; - m_flAccuracyPenalty = clamp( m_flAccuracyPenalty, 0.0f, PISTOL_ACCURACY_MAXIMUM_PENALTY_TIME ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPistol::ItemPreFrame( void ) -{ - UpdatePenaltyTime(); - - BaseClass::ItemPreFrame(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPistol::ItemBusyFrame( void ) -{ - UpdatePenaltyTime(); - - BaseClass::ItemBusyFrame(); -} - -//----------------------------------------------------------------------------- -// Purpose: Allows firing as fast as button is pressed -//----------------------------------------------------------------------------- -void CWeaponPistol::ItemPostFrame( void ) -{ - BaseClass::ItemPostFrame(); - - if ( m_bInReload ) - return; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - if ( pOwner->m_nButtons & IN_ATTACK2 ) - { - m_flLastAttackTime = gpGlobals->curtime + PISTOL_FASTEST_REFIRE_TIME; - m_flSoonestPrimaryAttack = gpGlobals->curtime + PISTOL_FASTEST_REFIRE_TIME; - m_flNextPrimaryAttack = gpGlobals->curtime + PISTOL_FASTEST_REFIRE_TIME; - } - - //Allow a refire as fast as the player can click - if ( ( ( pOwner->m_nButtons & IN_ATTACK ) == false ) && ( m_flSoonestPrimaryAttack < gpGlobals->curtime ) ) - { - m_flNextPrimaryAttack = gpGlobals->curtime - 0.1f; - } - else if ( ( pOwner->m_nButtons & IN_ATTACK ) && ( m_flNextPrimaryAttack < gpGlobals->curtime ) && ( m_iClip1 <= 0 ) ) - { - DryFire(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -Activity CWeaponPistol::GetPrimaryAttackActivity( void ) -{ - if ( m_nNumShotsFired < 1 ) - return ACT_VM_PRIMARYATTACK; - - if ( m_nNumShotsFired < 2 ) - return ACT_VM_RECOIL1; - - if ( m_nNumShotsFired < 3 ) - return ACT_VM_RECOIL2; - - return ACT_VM_RECOIL3; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CWeaponPistol::Reload( void ) -{ - bool fRet = DefaultReload( GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD ); - if ( fRet ) - { - WeaponSound( RELOAD ); - m_flAccuracyPenalty = 0.0f; - } - return fRet; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponPistol::AddViewKick( void ) -{ - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if ( pPlayer == NULL ) - return; - - QAngle viewPunch; - - viewPunch.x = SharedRandomFloat( "pistolpax", 0.25f, 0.5f ); - viewPunch.y = SharedRandomFloat( "pistolpay", -.6f, .6f ); - viewPunch.z = 0.0f; - - //Add it to the view punch - pPlayer->ViewPunch( viewPunch ); -} diff --git a/game/shared/hl2mp/weapon_rpg.cpp b/game/shared/hl2mp/weapon_rpg.cpp deleted file mode 100644 index 08835c2ab..000000000 --- a/game/shared/hl2mp/weapon_rpg.cpp +++ /dev/null @@ -1,2283 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" -#include "in_buttons.h" -#include "weapon_rpg.h" - -#ifdef CLIENT_DLL - #include "c_hl2mp_player.h" - #include "model_types.h" - #include "beamdraw.h" - #include "fx_line.h" - #include "view.h" -#else - #include "basecombatcharacter.h" - #include "movie_explosion.h" - #include "soundent.h" - #include "player.h" - #include "rope.h" - #include "vstdlib/random.h" - #include "engine/IEngineSound.h" - #include "explode.h" - #include "util.h" - #include "in_buttons.h" - #include "shake.h" - #include "te_effect_dispatch.h" - #include "triggers.h" - #include "smoke_trail.h" - #include "collisionutils.h" - #include "hl2_shareddefs.h" -#endif - -#include "debugoverlay_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define RPG_SPEED 1500 - -#ifndef CLIENT_DLL -const char *g_pLaserDotThink = "LaserThinkContext"; - -static ConVar sk_apc_missile_damage("sk_apc_missile_damage", "15"); -#define APC_MISSILE_DAMAGE sk_apc_missile_damage.GetInt() - -#endif - -#ifdef CLIENT_DLL -#define CLaserDot C_LaserDot -#endif - -//----------------------------------------------------------------------------- -// Laser Dot -//----------------------------------------------------------------------------- -class CLaserDot : public CBaseEntity -{ - DECLARE_CLASS( CLaserDot, CBaseEntity ); -public: - - CLaserDot( void ); - ~CLaserDot( void ); - - static CLaserDot *Create( const Vector &origin, CBaseEntity *pOwner = NULL, bool bVisibleDot = true ); - - void SetTargetEntity( CBaseEntity *pTarget ) { m_hTargetEnt = pTarget; } - CBaseEntity *GetTargetEntity( void ) { return m_hTargetEnt; } - - void SetLaserPosition( const Vector &origin, const Vector &normal ); - Vector GetChasePosition(); - void TurnOn( void ); - void TurnOff( void ); - bool IsOn() const { return m_bIsOn; } - - void Toggle( void ); - - int ObjectCaps() { return (BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION) | FCAP_DONT_SAVE; } - - void MakeInvisible( void ); - -#ifdef CLIENT_DLL - - virtual bool IsTransparent( void ) { return true; } - virtual RenderGroup_t GetRenderGroup( void ) { return RENDER_GROUP_TRANSLUCENT_ENTITY; } - virtual int DrawModel( int flags ); - virtual void OnDataChanged( DataUpdateType_t updateType ); - virtual bool ShouldDraw( void ) { return (IsEffectActive(EF_NODRAW)==false); } - - CMaterialReference m_hSpriteMaterial; -#endif - -protected: - Vector m_vecSurfaceNormal; - EHANDLE m_hTargetEnt; - bool m_bVisibleLaserDot; - bool m_bIsOn; - - DECLARE_NETWORKCLASS(); - DECLARE_DATADESC(); -public: - CLaserDot *m_pNext; -}; - -IMPLEMENT_NETWORKCLASS_ALIASED( LaserDot, DT_LaserDot ) - -BEGIN_NETWORK_TABLE( CLaserDot, DT_LaserDot ) -END_NETWORK_TABLE() - -#ifndef CLIENT_DLL - -// a list of laser dots to search quickly -CEntityClassList g_LaserDotList; -template <> CLaserDot *CEntityClassList::m_pClassList = NULL; -CLaserDot *GetLaserDotList() -{ - return g_LaserDotList.m_pClassList; -} - -BEGIN_DATADESC( CMissile ) - - DEFINE_FIELD( m_hOwner, FIELD_EHANDLE ), - DEFINE_FIELD( m_hRocketTrail, FIELD_EHANDLE ), - DEFINE_FIELD( m_flAugerTime, FIELD_TIME ), - DEFINE_FIELD( m_flMarkDeadTime, FIELD_TIME ), - DEFINE_FIELD( m_flGracePeriodEndsAt, FIELD_TIME ), - DEFINE_FIELD( m_flDamage, FIELD_FLOAT ), - - // Function Pointers - DEFINE_FUNCTION( MissileTouch ), - DEFINE_FUNCTION( AccelerateThink ), - DEFINE_FUNCTION( AugerThink ), - DEFINE_FUNCTION( IgniteThink ), - DEFINE_FUNCTION( SeekThink ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( rpg_missile, CMissile ); - -class CWeaponRPG; - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CMissile::CMissile() -{ - m_hRocketTrail = NULL; -} - -CMissile::~CMissile() -{ -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CMissile::Precache( void ) -{ - PrecacheModel( "models/weapons/w_missile.mdl" ); - PrecacheModel( "models/weapons/w_missile_launch.mdl" ); - PrecacheModel( "models/weapons/w_missile_closed.mdl" ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CMissile::Spawn( void ) -{ - Precache(); - - SetSolid( SOLID_BBOX ); - SetModel("models/weapons/w_missile_launch.mdl"); - UTIL_SetSize( this, -Vector(4,4,4), Vector(4,4,4) ); - - SetTouch( &CMissile::MissileTouch ); - - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); - SetThink( &CMissile::IgniteThink ); - - SetNextThink( gpGlobals->curtime + 0.3f ); - - m_takedamage = DAMAGE_YES; - m_iHealth = m_iMaxHealth = 100; - m_bloodColor = DONT_BLEED; - m_flGracePeriodEndsAt = 0; - - AddFlag( FL_OBJECT ); -} - - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CMissile::Event_Killed( const CTakeDamageInfo &info ) -{ - m_takedamage = DAMAGE_NO; - - ShotDown(); -} - -unsigned int CMissile::PhysicsSolidMaskForEntity( void ) const -{ - return BaseClass::PhysicsSolidMaskForEntity() | CONTENTS_HITBOX; -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -int CMissile::OnTakeDamage_Alive( const CTakeDamageInfo &info ) -{ - if ( ( info.GetDamageType() & (DMG_MISSILEDEFENSE | DMG_AIRBOAT) ) == false ) - return 0; - - bool bIsDamaged; - if( m_iHealth <= AugerHealth() ) - { - // This missile is already damaged (i.e., already running AugerThink) - bIsDamaged = true; - } - else - { - // This missile isn't damaged enough to wobble in flight yet - bIsDamaged = false; - } - - int nRetVal = BaseClass::OnTakeDamage_Alive( info ); - - if( !bIsDamaged ) - { - if ( m_iHealth <= AugerHealth() ) - { - ShotDown(); - } - } - - return nRetVal; -} - - -//----------------------------------------------------------------------------- -// Purpose: Stops any kind of tracking and shoots dumb -//----------------------------------------------------------------------------- -void CMissile::DumbFire( void ) -{ - SetThink( NULL ); - SetMoveType( MOVETYPE_FLY ); - - SetModel("models/weapons/w_missile.mdl"); - UTIL_SetSize( this, vec3_origin, vec3_origin ); - - EmitSound( "Missile.Ignite" ); - - // Smoke trail. - CreateSmokeTrail(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMissile::SetGracePeriod( float flGracePeriod ) -{ - m_flGracePeriodEndsAt = gpGlobals->curtime + flGracePeriod; - - // Go non-solid until the grace period ends - AddSolidFlags( FSOLID_NOT_SOLID ); -} - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CMissile::AccelerateThink( void ) -{ - Vector vecForward; - - // !!!UNDONE - make this work exactly the same as HL1 RPG, lest we have looping sound bugs again! - EmitSound( "Missile.Accelerate" ); - - // SetEffects( EF_LIGHT ); - - AngleVectors( GetLocalAngles(), &vecForward ); - SetAbsVelocity( vecForward * RPG_SPEED ); - - SetThink( &CMissile::SeekThink ); - SetNextThink( gpGlobals->curtime + 0.1f ); -} - -#define AUGER_YDEVIANCE 20.0f -#define AUGER_XDEVIANCEUP 8.0f -#define AUGER_XDEVIANCEDOWN 1.0f - -//--------------------------------------------------------- -//--------------------------------------------------------- -void CMissile::AugerThink( void ) -{ - // If we've augered long enough, then just explode - if ( m_flAugerTime < gpGlobals->curtime ) - { - Explode(); - return; - } - - if ( m_flMarkDeadTime < gpGlobals->curtime ) - { - m_lifeState = LIFE_DYING; - } - - QAngle angles = GetLocalAngles(); - - angles.y += random->RandomFloat( -AUGER_YDEVIANCE, AUGER_YDEVIANCE ); - angles.x += random->RandomFloat( -AUGER_XDEVIANCEDOWN, AUGER_XDEVIANCEUP ); - - SetLocalAngles( angles ); - - Vector vecForward; - - AngleVectors( GetLocalAngles(), &vecForward ); - - SetAbsVelocity( vecForward * 1000.0f ); - - SetNextThink( gpGlobals->curtime + 0.05f ); -} - -//----------------------------------------------------------------------------- -// Purpose: Causes the missile to spiral to the ground and explode, due to damage -//----------------------------------------------------------------------------- -void CMissile::ShotDown( void ) -{ - CEffectData data; - data.m_vOrigin = GetAbsOrigin(); - - DispatchEffect( "RPGShotDown", data ); - - if ( m_hRocketTrail != NULL ) - { - m_hRocketTrail->m_bDamaged = true; - } - - SetThink( &CMissile::AugerThink ); - SetNextThink( gpGlobals->curtime ); - m_flAugerTime = gpGlobals->curtime + 1.5f; - m_flMarkDeadTime = gpGlobals->curtime + 0.75; - - // Let the RPG start reloading immediately - if ( m_hOwner != NULL ) - { - m_hOwner->NotifyRocketDied(); - m_hOwner = NULL; - } -} - - -//----------------------------------------------------------------------------- -// The actual explosion -//----------------------------------------------------------------------------- -void CMissile::DoExplosion( void ) -{ - // Explode - ExplosionCreate( GetAbsOrigin(), GetAbsAngles(), GetOwnerEntity(), (int)GetDamage(), (int)(GetDamage() * 2), - SF_ENVEXPLOSION_NOSPARKS | SF_ENVEXPLOSION_NODLIGHTS | SF_ENVEXPLOSION_NOSMOKE, 0.0f, this); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMissile::Explode( void ) -{ - // Don't explode against the skybox. Just pretend that - // the missile flies off into the distance. - Vector forward; - - GetVectors( &forward, NULL, NULL ); - - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + forward * 16, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - - m_takedamage = DAMAGE_NO; - SetSolid( SOLID_NONE ); - if( tr.fraction == 1.0 || !(tr.surface.flags & SURF_SKY) ) - { - DoExplosion(); - } - - if( m_hRocketTrail ) - { - m_hRocketTrail->SetLifetime(0.1f); - m_hRocketTrail = NULL; - } - - if ( m_hOwner != NULL ) - { - m_hOwner->NotifyRocketDied(); - m_hOwner = NULL; - } - - StopSound( "Missile.Ignite" ); - UTIL_Remove( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOther - -//----------------------------------------------------------------------------- -void CMissile::MissileTouch( CBaseEntity *pOther ) -{ - Assert( pOther ); - - // Don't touch triggers (but DO hit weapons) - if ( pOther->IsSolidFlagSet(FSOLID_TRIGGER|FSOLID_VOLUME_CONTENTS) && pOther->GetCollisionGroup() != COLLISION_GROUP_WEAPON ) - return; - - Explode(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMissile::CreateSmokeTrail( void ) -{ - if ( m_hRocketTrail ) - return; - - // Smoke trail. - if ( (m_hRocketTrail = RocketTrail::CreateRocketTrail()) != NULL ) - { - m_hRocketTrail->m_Opacity = 0.2f; - m_hRocketTrail->m_SpawnRate = 100; - m_hRocketTrail->m_ParticleLifetime = 0.5f; - m_hRocketTrail->m_StartColor.Init( 0.65f, 0.65f , 0.65f ); - m_hRocketTrail->m_EndColor.Init( 0.0, 0.0, 0.0 ); - m_hRocketTrail->m_StartSize = 8; - m_hRocketTrail->m_EndSize = 32; - m_hRocketTrail->m_SpawnRadius = 4; - m_hRocketTrail->m_MinSpeed = 2; - m_hRocketTrail->m_MaxSpeed = 16; - - m_hRocketTrail->SetLifetime( 999 ); - m_hRocketTrail->FollowEntity( this, "0" ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMissile::IgniteThink( void ) -{ - SetMoveType( MOVETYPE_FLY ); - SetModel("models/weapons/w_missile.mdl"); - UTIL_SetSize( this, vec3_origin, vec3_origin ); - RemoveSolidFlags( FSOLID_NOT_SOLID ); - - //TODO: Play opening sound - - Vector vecForward; - - EmitSound( "Missile.Ignite" ); - - AngleVectors( GetLocalAngles(), &vecForward ); - SetAbsVelocity( vecForward * RPG_SPEED ); - - SetThink( &CMissile::SeekThink ); - SetNextThink( gpGlobals->curtime ); - - if ( m_hOwner && m_hOwner->GetOwner() ) - { - CBasePlayer *pPlayer = ToBasePlayer( m_hOwner->GetOwner() ); - - color32 white = { 255,225,205,64 }; - UTIL_ScreenFade( pPlayer, white, 0.1f, 0.0f, FFADE_IN ); - } - - CreateSmokeTrail(); -} - - -//----------------------------------------------------------------------------- -// Gets the shooting position -//----------------------------------------------------------------------------- -void CMissile::GetShootPosition( CLaserDot *pLaserDot, Vector *pShootPosition ) -{ - if ( pLaserDot->GetOwnerEntity() != NULL ) - { - //FIXME: Do we care this isn't exactly the muzzle position? - *pShootPosition = pLaserDot->GetOwnerEntity()->WorldSpaceCenter(); - } - else - { - *pShootPosition = pLaserDot->GetChasePosition(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -#define RPG_HOMING_SPEED 0.125f - -void CMissile::ComputeActualDotPosition( CLaserDot *pLaserDot, Vector *pActualDotPosition, float *pHomingSpeed ) -{ - *pHomingSpeed = RPG_HOMING_SPEED; - if ( pLaserDot->GetTargetEntity() ) - { - *pActualDotPosition = pLaserDot->GetChasePosition(); - return; - } - - Vector vLaserStart; - GetShootPosition( pLaserDot, &vLaserStart ); - - //Get the laser's vector - Vector vLaserDir; - VectorSubtract( pLaserDot->GetChasePosition(), vLaserStart, vLaserDir ); - - //Find the length of the current laser - float flLaserLength = VectorNormalize( vLaserDir ); - - //Find the length from the missile to the laser's owner - float flMissileLength = GetAbsOrigin().DistTo( vLaserStart ); - - //Find the length from the missile to the laser's position - Vector vecTargetToMissile; - VectorSubtract( GetAbsOrigin(), pLaserDot->GetChasePosition(), vecTargetToMissile ); - float flTargetLength = VectorNormalize( vecTargetToMissile ); - - // See if we should chase the line segment nearest us - if ( ( flMissileLength < flLaserLength ) || ( flTargetLength <= 512.0f ) ) - { - *pActualDotPosition = UTIL_PointOnLineNearestPoint( vLaserStart, pLaserDot->GetChasePosition(), GetAbsOrigin() ); - *pActualDotPosition += ( vLaserDir * 256.0f ); - } - else - { - // Otherwise chase the dot - *pActualDotPosition = pLaserDot->GetChasePosition(); - } - -// NDebugOverlay::Line( pLaserDot->GetChasePosition(), vLaserStart, 0, 255, 0, true, 0.05f ); -// NDebugOverlay::Line( GetAbsOrigin(), *pActualDotPosition, 255, 0, 0, true, 0.05f ); -// NDebugOverlay::Cross3D( *pActualDotPosition, -Vector(4,4,4), Vector(4,4,4), 255, 0, 0, true, 0.05f ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMissile::SeekThink( void ) -{ - CBaseEntity *pBestDot = NULL; - float flBestDist = MAX_TRACE_LENGTH; - float dotDist; - - // If we have a grace period, go solid when it ends - if ( m_flGracePeriodEndsAt ) - { - if ( m_flGracePeriodEndsAt < gpGlobals->curtime ) - { - RemoveSolidFlags( FSOLID_NOT_SOLID ); - m_flGracePeriodEndsAt = 0; - } - } - - //Search for all dots relevant to us - for( CLaserDot *pEnt = GetLaserDotList(); pEnt != NULL; pEnt = pEnt->m_pNext ) - { - if ( !pEnt->IsOn() ) - continue; - - if ( pEnt->GetOwnerEntity() != GetOwnerEntity() ) - continue; - - dotDist = (GetAbsOrigin() - pEnt->GetAbsOrigin()).Length(); - - //Find closest - if ( dotDist < flBestDist ) - { - pBestDot = pEnt; - flBestDist = dotDist; - } - } - - //If we have a dot target - if ( pBestDot == NULL ) - { - //Think as soon as possible - SetNextThink( gpGlobals->curtime ); - return; - } - - CLaserDot *pLaserDot = (CLaserDot *)pBestDot; - Vector targetPos; - - float flHomingSpeed; - Vector vecLaserDotPosition; - ComputeActualDotPosition( pLaserDot, &targetPos, &flHomingSpeed ); - - if ( IsSimulatingOnAlternateTicks() ) - flHomingSpeed *= 2; - - Vector vTargetDir; - VectorSubtract( targetPos, GetAbsOrigin(), vTargetDir ); - float flDist = VectorNormalize( vTargetDir ); - - Vector vDir = GetAbsVelocity(); - float flSpeed = VectorNormalize( vDir ); - Vector vNewVelocity = vDir; - if ( gpGlobals->frametime > 0.0f ) - { - if ( flSpeed != 0 ) - { - vNewVelocity = ( flHomingSpeed * vTargetDir ) + ( ( 1 - flHomingSpeed ) * vDir ); - - // This computation may happen to cancel itself out exactly. If so, slam to targetdir. - if ( VectorNormalize( vNewVelocity ) < 1e-3 ) - { - vNewVelocity = (flDist != 0) ? vTargetDir : vDir; - } - } - else - { - vNewVelocity = vTargetDir; - } - } - - QAngle finalAngles; - VectorAngles( vNewVelocity, finalAngles ); - SetAbsAngles( finalAngles ); - - vNewVelocity *= flSpeed; - SetAbsVelocity( vNewVelocity ); - - if( GetAbsVelocity() == vec3_origin ) - { - // Strange circumstances have brought this missile to halt. Just blow it up. - Explode(); - return; - } - - // Think as soon as possible - SetNextThink( gpGlobals->curtime ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// -// Input : &vecOrigin - -// &vecAngles - -// NULL - -// -// Output : CMissile -//----------------------------------------------------------------------------- -CMissile *CMissile::Create( const Vector &vecOrigin, const QAngle &vecAngles, edict_t *pentOwner = NULL ) -{ - //CMissile *pMissile = (CMissile *)CreateEntityByName("rpg_missile" ); - CMissile *pMissile = (CMissile *) CBaseEntity::Create( "rpg_missile", vecOrigin, vecAngles, CBaseEntity::Instance( pentOwner ) ); - pMissile->SetOwnerEntity( Instance( pentOwner ) ); - pMissile->Spawn(); - pMissile->AddEffects( EF_NOSHADOW ); - - Vector vecForward; - AngleVectors( vecAngles, &vecForward ); - - pMissile->SetAbsVelocity( vecForward * 300 + Vector( 0,0, 128 ) ); - - return pMissile; -} - - - -//----------------------------------------------------------------------------- -// This entity is used to create little force boxes that the helicopter -// should avoid. -//----------------------------------------------------------------------------- -class CInfoAPCMissileHint : public CBaseEntity -{ - DECLARE_DATADESC(); - -public: - DECLARE_CLASS( CInfoAPCMissileHint, CBaseEntity ); - - virtual void Spawn( ); - virtual void Activate(); - virtual void UpdateOnRemove(); - - static CBaseEntity *FindAimTarget( CBaseEntity *pMissile, const char *pTargetName, - const Vector &vecCurrentTargetPos, const Vector &vecCurrentTargetVel ); - -private: - EHANDLE m_hTarget; - - typedef CHandle APCMissileHintHandle_t; - static CUtlVector< APCMissileHintHandle_t > s_APCMissileHints; -}; - - -//----------------------------------------------------------------------------- -// -// This entity is used to create little force boxes that the helicopters should avoid. -// -//----------------------------------------------------------------------------- -CUtlVector< CInfoAPCMissileHint::APCMissileHintHandle_t > CInfoAPCMissileHint::s_APCMissileHints; - -LINK_ENTITY_TO_CLASS( info_apc_missile_hint, CInfoAPCMissileHint ); - -BEGIN_DATADESC( CInfoAPCMissileHint ) - DEFINE_FIELD( m_hTarget, FIELD_EHANDLE ), -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Spawn, remove -//----------------------------------------------------------------------------- -void CInfoAPCMissileHint::Spawn( ) -{ - SetModel( STRING( GetModelName() ) ); - SetSolid( SOLID_BSP ); - AddSolidFlags( FSOLID_NOT_SOLID ); - AddEffects( EF_NODRAW ); -} - -void CInfoAPCMissileHint::Activate( ) -{ - BaseClass::Activate(); - - m_hTarget = gEntList.FindEntityByName( NULL, m_target ); - if ( m_hTarget == NULL ) - { - DevWarning( "%s: Could not find target '%s'!\n", GetClassname(), STRING( m_target ) ); - } - else - { - s_APCMissileHints.AddToTail( this ); - } -} - -void CInfoAPCMissileHint::UpdateOnRemove( ) -{ - s_APCMissileHints.FindAndRemove( this ); - BaseClass::UpdateOnRemove(); -} - - -//----------------------------------------------------------------------------- -// Where are how should we avoid? -//----------------------------------------------------------------------------- -#define HINT_PREDICTION_TIME 3.0f - -CBaseEntity *CInfoAPCMissileHint::FindAimTarget( CBaseEntity *pMissile, const char *pTargetName, - const Vector &vecCurrentEnemyPos, const Vector &vecCurrentEnemyVel ) -{ - if ( !pTargetName ) - return NULL; - - float flOOSpeed = pMissile->GetAbsVelocity().Length(); - if ( flOOSpeed != 0.0f ) - { - flOOSpeed = 1.0f / flOOSpeed; - } - - for ( int i = s_APCMissileHints.Count(); --i >= 0; ) - { - CInfoAPCMissileHint *pHint = s_APCMissileHints[i]; - if ( !pHint->NameMatches( pTargetName ) ) - continue; - - if ( !pHint->m_hTarget ) - continue; - - Vector vecMissileToHint, vecMissileToEnemy; - VectorSubtract( pHint->m_hTarget->WorldSpaceCenter(), pMissile->GetAbsOrigin(), vecMissileToHint ); - VectorSubtract( vecCurrentEnemyPos, pMissile->GetAbsOrigin(), vecMissileToEnemy ); - float flDistMissileToHint = VectorNormalize( vecMissileToHint ); - VectorNormalize( vecMissileToEnemy ); - if ( DotProduct( vecMissileToHint, vecMissileToEnemy ) < 0.866f ) - continue; - - // Determine when the target will be inside the volume. - // Project at most 3 seconds in advance - Vector vecRayDelta; - VectorMultiply( vecCurrentEnemyVel, HINT_PREDICTION_TIME, vecRayDelta ); - - BoxTraceInfo_t trace; - if ( !IntersectRayWithOBB( vecCurrentEnemyPos, vecRayDelta, pHint->CollisionProp()->CollisionToWorldTransform(), - pHint->CollisionProp()->OBBMins(), pHint->CollisionProp()->OBBMaxs(), 0.0f, &trace )) - { - continue; - } - - // Determine the amount of time it would take the missile to reach the target - // If we can reach the target within the time it takes for the enemy to reach the - float tSqr = flDistMissileToHint * flOOSpeed / HINT_PREDICTION_TIME; - if ( (tSqr < (trace.t1 * trace.t1)) || (tSqr > (trace.t2 * trace.t2)) ) - continue; - - return pHint->m_hTarget; - } - - return NULL; -} - - -//----------------------------------------------------------------------------- -// a list of missiles to search quickly -//----------------------------------------------------------------------------- -CEntityClassList g_APCMissileList; -template <> CAPCMissile *CEntityClassList::m_pClassList = NULL; -CAPCMissile *GetAPCMissileList() -{ - return g_APCMissileList.m_pClassList; -} - -//----------------------------------------------------------------------------- -// Finds apc missiles in cone -//----------------------------------------------------------------------------- -CAPCMissile *FindAPCMissileInCone( const Vector &vecOrigin, const Vector &vecDirection, float flAngle ) -{ - float flCosAngle = cos( DEG2RAD( flAngle ) ); - for( CAPCMissile *pEnt = GetAPCMissileList(); pEnt != NULL; pEnt = pEnt->m_pNext ) - { - if ( !pEnt->IsSolid() ) - continue; - - Vector vecDelta; - VectorSubtract( pEnt->GetAbsOrigin(), vecOrigin, vecDelta ); - VectorNormalize( vecDelta ); - float flDot = DotProduct( vecDelta, vecDirection ); - if ( flDot > flCosAngle ) - return pEnt; - } - - return NULL; -} - - -//----------------------------------------------------------------------------- -// -// Specialized version of the missile -// -//----------------------------------------------------------------------------- -#define MAX_HOMING_DISTANCE 2250.0f -#define MIN_HOMING_DISTANCE 1250.0f -#define MAX_NEAR_HOMING_DISTANCE 1750.0f -#define MIN_NEAR_HOMING_DISTANCE 1000.0f -#define DOWNWARD_BLEND_TIME_START 0.2f -#define MIN_HEIGHT_DIFFERENCE 250.0f -#define MAX_HEIGHT_DIFFERENCE 550.0f -#define CORRECTION_TIME 0.2f -#define APC_LAUNCH_HOMING_SPEED 0.1f -#define APC_HOMING_SPEED 0.025f -#define HOMING_SPEED_ACCEL 0.01f - -BEGIN_DATADESC( CAPCMissile ) - - DEFINE_FIELD( m_flReachedTargetTime, FIELD_TIME ), - DEFINE_FIELD( m_flIgnitionTime, FIELD_TIME ), - DEFINE_FIELD( m_bGuidingDisabled, FIELD_BOOLEAN ), - DEFINE_FIELD( m_hSpecificTarget, FIELD_EHANDLE ), - DEFINE_FIELD( m_strHint, FIELD_STRING ), - DEFINE_FIELD( m_flLastHomingSpeed, FIELD_FLOAT ), -// DEFINE_FIELD( m_pNext, FIELD_CLASSPTR ), - - DEFINE_THINKFUNC( BeginSeekThink ), - DEFINE_THINKFUNC( AugerStartThink ), - DEFINE_THINKFUNC( ExplodeThink ), - - DEFINE_FUNCTION( APCMissileTouch ), - -END_DATADESC() - -LINK_ENTITY_TO_CLASS( apc_missile, CAPCMissile ); - -CAPCMissile *CAPCMissile::Create( const Vector &vecOrigin, const QAngle &vecAngles, const Vector &vecVelocity, CBaseEntity *pOwner ) -{ - CAPCMissile *pMissile = (CAPCMissile *)CBaseEntity::Create( "apc_missile", vecOrigin, vecAngles, pOwner ); - pMissile->SetOwnerEntity( pOwner ); - pMissile->Spawn(); - pMissile->SetAbsVelocity( vecVelocity ); - pMissile->AddFlag( FL_NOTARGET ); - pMissile->AddEffects( EF_NOSHADOW ); - return pMissile; -} - - -//----------------------------------------------------------------------------- -// Constructor, destructor -//----------------------------------------------------------------------------- -CAPCMissile::CAPCMissile() -{ - g_APCMissileList.Insert( this ); -} - -CAPCMissile::~CAPCMissile() -{ - g_APCMissileList.Remove( this ); -} - - -//----------------------------------------------------------------------------- -// Shared initialization code -//----------------------------------------------------------------------------- -void CAPCMissile::Init() -{ - SetMoveType( MOVETYPE_FLY ); - SetModel("models/weapons/w_missile.mdl"); - UTIL_SetSize( this, vec3_origin, vec3_origin ); - CreateSmokeTrail(); - SetTouch( &CAPCMissile::APCMissileTouch ); - m_flLastHomingSpeed = APC_HOMING_SPEED; -} - - -//----------------------------------------------------------------------------- -// For hitting a specific target -//----------------------------------------------------------------------------- -void CAPCMissile::AimAtSpecificTarget( CBaseEntity *pTarget ) -{ - m_hSpecificTarget = pTarget; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOther - -//----------------------------------------------------------------------------- -void CAPCMissile::APCMissileTouch( CBaseEntity *pOther ) -{ - Assert( pOther ); - if ( !pOther->IsSolid() && !pOther->IsSolidFlagSet(FSOLID_VOLUME_CONTENTS) ) - return; - - Explode(); -} - - -//----------------------------------------------------------------------------- -// Specialized version of the missile -//----------------------------------------------------------------------------- -void CAPCMissile::IgniteDelay( void ) -{ - m_flIgnitionTime = gpGlobals->curtime + 0.3f; - - SetThink( &CAPCMissile::BeginSeekThink ); - SetNextThink( m_flIgnitionTime ); - Init(); - AddSolidFlags( FSOLID_NOT_SOLID ); -} - -void CAPCMissile::AugerDelay( float flDelay ) -{ - m_flIgnitionTime = gpGlobals->curtime; - SetThink( &CAPCMissile::AugerStartThink ); - SetNextThink( gpGlobals->curtime + flDelay ); - Init(); - DisableGuiding(); -} - -void CAPCMissile::AugerStartThink() -{ - if ( m_hRocketTrail != NULL ) - { - m_hRocketTrail->m_bDamaged = true; - } - m_flAugerTime = gpGlobals->curtime + random->RandomFloat( 1.0f, 2.0f ); - SetThink( &CAPCMissile::AugerThink ); - SetNextThink( gpGlobals->curtime ); -} - -void CAPCMissile::ExplodeDelay( float flDelay ) -{ - m_flIgnitionTime = gpGlobals->curtime; - SetThink( &CAPCMissile::ExplodeThink ); - SetNextThink( gpGlobals->curtime + flDelay ); - Init(); - DisableGuiding(); -} - - -void CAPCMissile::BeginSeekThink( void ) -{ - RemoveSolidFlags( FSOLID_NOT_SOLID ); - SetThink( &CAPCMissile::SeekThink ); - SetNextThink( gpGlobals->curtime ); -} - -void CAPCMissile::ExplodeThink() -{ - DoExplosion(); -} - -//----------------------------------------------------------------------------- -// Health lost at which augering starts -//----------------------------------------------------------------------------- -int CAPCMissile::AugerHealth() -{ - return m_iMaxHealth - 25; -} - - -//----------------------------------------------------------------------------- -// Health lost at which augering starts -//----------------------------------------------------------------------------- -void CAPCMissile::DisableGuiding() -{ - m_bGuidingDisabled = true; -} - - -//----------------------------------------------------------------------------- -// Guidance hints -//----------------------------------------------------------------------------- -void CAPCMissile::SetGuidanceHint( const char *pHintName ) -{ - m_strHint = MAKE_STRING( pHintName ); -} - - -//----------------------------------------------------------------------------- -// The actual explosion -//----------------------------------------------------------------------------- -void CAPCMissile::DoExplosion( void ) -{ - if ( GetWaterLevel() != 0 ) - { - CEffectData data; - data.m_vOrigin = WorldSpaceCenter(); - data.m_flMagnitude = 128; - data.m_flScale = 128; - data.m_fFlags = 0; - DispatchEffect( "WaterSurfaceExplosion", data ); - } - else - { - ExplosionCreate( GetAbsOrigin(), GetAbsAngles(), GetOwnerEntity(), - APC_MISSILE_DAMAGE, 100, true, 20000 ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAPCMissile::ComputeLeadingPosition( const Vector &vecShootPosition, CBaseEntity *pTarget, Vector *pLeadPosition ) -{ - Vector vecTarget = pTarget->BodyTarget( vecShootPosition, false ); - float flShotSpeed = GetAbsVelocity().Length(); - if ( flShotSpeed == 0 ) - { - *pLeadPosition = vecTarget; - return; - } - - Vector vecVelocity = pTarget->GetSmoothedVelocity(); - vecVelocity.z = 0.0f; - float flTargetSpeed = VectorNormalize( vecVelocity ); - Vector vecDelta; - VectorSubtract( vecShootPosition, vecTarget, vecDelta ); - float flTargetToShooter = VectorNormalize( vecDelta ); - float flCosTheta = DotProduct( vecDelta, vecVelocity ); - - // Law of cosines... z^2 = x^2 + y^2 - 2xy cos Theta - // where z = flShooterToPredictedTargetPosition = flShotSpeed * predicted time - // x = flTargetSpeed * predicted time - // y = flTargetToShooter - // solve for predicted time using at^2 + bt + c = 0, t = (-b +/- sqrt( b^2 - 4ac )) / 2a - float a = flTargetSpeed * flTargetSpeed - flShotSpeed * flShotSpeed; - float b = -2.0f * flTargetToShooter * flCosTheta * flTargetSpeed; - float c = flTargetToShooter * flTargetToShooter; - - float flDiscrim = b*b - 4*a*c; - if (flDiscrim < 0) - { - *pLeadPosition = vecTarget; - return; - } - - flDiscrim = sqrt(flDiscrim); - float t = (-b + flDiscrim) / (2.0f * a); - float t2 = (-b - flDiscrim) / (2.0f * a); - if ( t < t2 ) - { - t = t2; - } - - if ( t <= 0.0f ) - { - *pLeadPosition = vecTarget; - return; - } - - VectorMA( vecTarget, flTargetSpeed * t, vecVelocity, *pLeadPosition ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CAPCMissile::ComputeActualDotPosition( CLaserDot *pLaserDot, Vector *pActualDotPosition, float *pHomingSpeed ) -{ - if ( m_bGuidingDisabled ) - { - *pActualDotPosition = GetAbsOrigin(); - *pHomingSpeed = 0.0f; - m_flLastHomingSpeed = *pHomingSpeed; - return; - } - - if ( ( m_strHint != NULL_STRING ) && (!m_hSpecificTarget) ) - { - Vector vecOrigin, vecVelocity; - CBaseEntity *pTarget = pLaserDot->GetTargetEntity(); - if ( pTarget ) - { - vecOrigin = pTarget->BodyTarget( GetAbsOrigin(), false ); - vecVelocity = pTarget->GetSmoothedVelocity(); - } - else - { - vecOrigin = pLaserDot->GetChasePosition(); - vecVelocity = vec3_origin; - } - - m_hSpecificTarget = CInfoAPCMissileHint::FindAimTarget( this, STRING( m_strHint ), vecOrigin, vecVelocity ); - } - - CBaseEntity *pLaserTarget = m_hSpecificTarget ? m_hSpecificTarget.Get() : pLaserDot->GetTargetEntity(); - if ( !pLaserTarget ) - { - BaseClass::ComputeActualDotPosition( pLaserDot, pActualDotPosition, pHomingSpeed ); - m_flLastHomingSpeed = *pHomingSpeed; - return; - } - - if ( pLaserTarget->ClassMatches( "npc_bullseye" ) ) - { - if ( m_flLastHomingSpeed != RPG_HOMING_SPEED ) - { - if (m_flLastHomingSpeed > RPG_HOMING_SPEED) - { - m_flLastHomingSpeed -= HOMING_SPEED_ACCEL * UTIL_GetSimulationInterval(); - if ( m_flLastHomingSpeed < RPG_HOMING_SPEED ) - { - m_flLastHomingSpeed = RPG_HOMING_SPEED; - } - } - else - { - m_flLastHomingSpeed += HOMING_SPEED_ACCEL * UTIL_GetSimulationInterval(); - if ( m_flLastHomingSpeed > RPG_HOMING_SPEED ) - { - m_flLastHomingSpeed = RPG_HOMING_SPEED; - } - } - } - *pHomingSpeed = m_flLastHomingSpeed; - *pActualDotPosition = pLaserTarget->WorldSpaceCenter(); - return; - } - - Vector vLaserStart; - GetShootPosition( pLaserDot, &vLaserStart ); - *pHomingSpeed = APC_LAUNCH_HOMING_SPEED; - - //Get the laser's vector - Vector vecTargetPosition = pLaserTarget->BodyTarget( GetAbsOrigin(), false ); - - // Compute leading position - Vector vecLeadPosition; - ComputeLeadingPosition( GetAbsOrigin(), pLaserTarget, &vecLeadPosition ); - - Vector vecTargetToMissile, vecTargetToShooter; - VectorSubtract( GetAbsOrigin(), vecTargetPosition, vecTargetToMissile ); - VectorSubtract( vLaserStart, vecTargetPosition, vecTargetToShooter ); - - *pActualDotPosition = vecLeadPosition; - - float flMinHomingDistance = MIN_HOMING_DISTANCE; - float flMaxHomingDistance = MAX_HOMING_DISTANCE; - float flBlendTime = gpGlobals->curtime - m_flIgnitionTime; - if ( flBlendTime > DOWNWARD_BLEND_TIME_START ) - { - if ( m_flReachedTargetTime != 0.0f ) - { - *pHomingSpeed = APC_HOMING_SPEED; - float flDeltaTime = clamp( gpGlobals->curtime - m_flReachedTargetTime, 0.0f, CORRECTION_TIME ); - *pHomingSpeed = SimpleSplineRemapVal( flDeltaTime, 0.0f, CORRECTION_TIME, 0.2f, *pHomingSpeed ); - flMinHomingDistance = SimpleSplineRemapVal( flDeltaTime, 0.0f, CORRECTION_TIME, MIN_NEAR_HOMING_DISTANCE, flMinHomingDistance ); - flMaxHomingDistance = SimpleSplineRemapVal( flDeltaTime, 0.0f, CORRECTION_TIME, MAX_NEAR_HOMING_DISTANCE, flMaxHomingDistance ); - } - else - { - flMinHomingDistance = MIN_NEAR_HOMING_DISTANCE; - flMaxHomingDistance = MAX_NEAR_HOMING_DISTANCE; - Vector vecDelta; - VectorSubtract( GetAbsOrigin(), *pActualDotPosition, vecDelta ); - if ( vecDelta.z > MIN_HEIGHT_DIFFERENCE ) - { - float flClampedHeight = clamp( vecDelta.z, MIN_HEIGHT_DIFFERENCE, MAX_HEIGHT_DIFFERENCE ); - float flHeightAdjustFactor = SimpleSplineRemapVal( flClampedHeight, MIN_HEIGHT_DIFFERENCE, MAX_HEIGHT_DIFFERENCE, 0.0f, 1.0f ); - - vecDelta.z = 0.0f; - float flDist = VectorNormalize( vecDelta ); - - float flForwardOffset = 2000.0f; - if ( flDist > flForwardOffset ) - { - Vector vecNewPosition; - VectorMA( GetAbsOrigin(), -flForwardOffset, vecDelta, vecNewPosition ); - vecNewPosition.z = pActualDotPosition->z; - - VectorLerp( *pActualDotPosition, vecNewPosition, flHeightAdjustFactor, *pActualDotPosition ); - } - } - else - { - m_flReachedTargetTime = gpGlobals->curtime; - } - } - - // Allows for players right at the edge of rocket range to be threatened - if ( flBlendTime > 0.6f ) - { - float flTargetLength = GetAbsOrigin().DistTo( pLaserTarget->WorldSpaceCenter() ); - flTargetLength = clamp( flTargetLength, flMinHomingDistance, flMaxHomingDistance ); - *pHomingSpeed = SimpleSplineRemapVal( flTargetLength, flMaxHomingDistance, flMinHomingDistance, *pHomingSpeed, 0.01f ); - } - } - - float flDot = DotProduct2D( vecTargetToShooter.AsVector2D(), vecTargetToMissile.AsVector2D() ); - if ( ( flDot < 0 ) || m_bGuidingDisabled ) - { - *pHomingSpeed = 0.0f; - } - - m_flLastHomingSpeed = *pHomingSpeed; - -// NDebugOverlay::Line( vecLeadPosition, GetAbsOrigin(), 0, 255, 0, true, 0.05f ); -// NDebugOverlay::Line( GetAbsOrigin(), *pActualDotPosition, 255, 0, 0, true, 0.05f ); -// NDebugOverlay::Cross3D( *pActualDotPosition, -Vector(4,4,4), Vector(4,4,4), 255, 0, 0, true, 0.05f ); -} - -#endif - -#define RPG_BEAM_SPRITE "effects/laser1.vmt" -#define RPG_BEAM_SPRITE_NOZ "effects/laser1_noz.vmt" -#define RPG_LASER_SPRITE "sprites/redglow1" - -//============================================================================= -// RPG -//============================================================================= - -LINK_ENTITY_TO_CLASS( weapon_rpg, CWeaponRPG ); -PRECACHE_WEAPON_REGISTER(weapon_rpg); - -IMPLEMENT_NETWORKCLASS_ALIASED( WeaponRPG, DT_WeaponRPG ) - -#ifdef CLIENT_DLL -void RecvProxy_MissileDied( const CRecvProxyData *pData, void *pStruct, void *pOut ) -{ - CWeaponRPG *pRPG = ((CWeaponRPG*)pStruct); - - RecvProxy_IntToEHandle( pData, pStruct, pOut ); - - CBaseEntity *pNewMissile = pRPG->GetMissile(); - - if ( pNewMissile == NULL ) - { - if ( pRPG->GetOwner() && pRPG->GetOwner()->GetActiveWeapon() == pRPG ) - { - pRPG->NotifyRocketDied(); - } - } -} - -#endif - -BEGIN_NETWORK_TABLE( CWeaponRPG, DT_WeaponRPG ) -#ifdef CLIENT_DLL - RecvPropBool( RECVINFO( m_bInitialStateUpdate ) ), - RecvPropBool( RECVINFO( m_bGuiding ) ), - RecvPropBool( RECVINFO( m_bHideGuiding ) ), - RecvPropEHandle( RECVINFO( m_hMissile ), RecvProxy_MissileDied ), - RecvPropVector( RECVINFO( m_vecLaserDot ) ), -#else - SendPropBool( SENDINFO( m_bInitialStateUpdate ) ), - SendPropBool( SENDINFO( m_bGuiding ) ), - SendPropBool( SENDINFO( m_bHideGuiding ) ), - SendPropEHandle( SENDINFO( m_hMissile ) ), - SendPropVector( SENDINFO( m_vecLaserDot ) ), -#endif -END_NETWORK_TABLE() - -#ifdef CLIENT_DLL - -BEGIN_PREDICTION_DATA( CWeaponRPG ) - DEFINE_PRED_FIELD( m_bInitialStateUpdate, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_bGuiding, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_bHideGuiding, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), -END_PREDICTION_DATA() - -#endif - -#ifndef CLIENT_DLL -acttable_t CWeaponRPG::m_acttable[] = -{ - { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_RPG, false }, - { ACT_HL2MP_RUN, ACT_HL2MP_RUN_RPG, false }, - { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_RPG, false }, - { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_RPG, false }, - { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_RPG, false }, - { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_RPG, false }, - { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_RPG, false }, - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_RPG, false }, -}; - -IMPLEMENT_ACTTABLE(CWeaponRPG); - -#endif - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CWeaponRPG::CWeaponRPG() -{ - m_bReloadsSingly = true; - m_bInitialStateUpdate= false; - m_bHideGuiding = false; - m_bGuiding = false; - - m_fMinRange1 = m_fMinRange2 = 40*12; - m_fMaxRange1 = m_fMaxRange2 = 500*12; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CWeaponRPG::~CWeaponRPG() -{ -#ifndef CLIENT_DLL - if ( m_hLaserDot != NULL ) - { - UTIL_Remove( m_hLaserDot ); - m_hLaserDot = NULL; - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponRPG::Precache( void ) -{ - BaseClass::Precache(); - - PrecacheScriptSound( "Missile.Ignite" ); - PrecacheScriptSound( "Missile.Accelerate" ); - - // Laser dot... - PrecacheModel( "sprites/redglow1.vmt" ); - PrecacheModel( RPG_LASER_SPRITE ); - PrecacheModel( RPG_BEAM_SPRITE ); - PrecacheModel( RPG_BEAM_SPRITE_NOZ ); - -#ifndef CLIENT_DLL - UTIL_PrecacheOther( "rpg_missile" ); -#endif - -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponRPG::Activate( void ) -{ - BaseClass::Activate(); - - // Restore the laser pointer after transition - if ( m_bGuiding ) - { - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - if ( pOwner->GetActiveWeapon() == this ) - { - StartGuiding(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CWeaponRPG::HasAnyAmmo( void ) -{ - if ( m_hMissile != NULL ) - return true; - - return BaseClass::HasAnyAmmo(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponRPG::WeaponShouldBeLowered( void ) -{ - // Lower us if we're out of ammo - if ( !HasAnyAmmo() ) - return true; - - return BaseClass::WeaponShouldBeLowered(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponRPG::PrimaryAttack( void ) -{ - // Only the player fires this way so we can cast - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if (!pPlayer) - return; - - // Can't have an active missile out - if ( m_hMissile != NULL ) - return; - - // Can't be reloading - if ( GetActivity() == ACT_VM_RELOAD ) - return; - - Vector vecOrigin; - Vector vecForward; - - m_flNextPrimaryAttack = gpGlobals->curtime + 0.5f; - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner == NULL ) - return; - - Vector vForward, vRight, vUp; - - pOwner->EyeVectors( &vForward, &vRight, &vUp ); - - Vector muzzlePoint = pOwner->Weapon_ShootPosition() + vForward * 12.0f + vRight * 6.0f + vUp * -3.0f; - -#ifndef CLIENT_DLL - QAngle vecAngles; - VectorAngles( vForward, vecAngles ); - - CMissile *pMissile = CMissile::Create( muzzlePoint, vecAngles, GetOwner()->edict() ); - pMissile->m_hOwner = this; - - // If the shot is clear to the player, give the missile a grace period - trace_t tr; - Vector vecEye = pOwner->EyePosition(); - UTIL_TraceLine( vecEye, vecEye + vForward * 128, MASK_SHOT, this, COLLISION_GROUP_NONE, &tr ); - if ( tr.fraction == 1.0 ) - { - pMissile->SetGracePeriod( 0.3 ); - } - - pMissile->SetDamage( GetHL2MPWpnData().m_iPlayerDamage ); - - m_hMissile = pMissile; -#endif - - DecrementAmmo( GetOwner() ); - SendWeaponAnim( ACT_VM_PRIMARYATTACK ); - WeaponSound( SINGLE ); - - // player "shoot" animation - pPlayer->SetAnimation( PLAYER_ATTACK1 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pOwner - -//----------------------------------------------------------------------------- -void CWeaponRPG::DecrementAmmo( CBaseCombatCharacter *pOwner ) -{ - // Take away our primary ammo type - pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : state - -//----------------------------------------------------------------------------- -void CWeaponRPG::SuppressGuiding( bool state ) -{ - m_bHideGuiding = state; - -#ifndef CLIENT_DLL - - if ( m_hLaserDot == NULL ) - { - StartGuiding(); - - //STILL!? - if ( m_hLaserDot == NULL ) - return; - } - - if ( state ) - { - m_hLaserDot->TurnOff(); - } - else - { - m_hLaserDot->TurnOn(); - } -#endif - -} - -//----------------------------------------------------------------------------- -// Purpose: Override this if we're guiding a missile currently -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponRPG::Lower( void ) -{ - if ( m_hMissile != NULL ) - return false; - - return BaseClass::Lower(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponRPG::ItemPostFrame( void ) -{ - BaseClass::ItemPostFrame(); - - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if ( pPlayer == NULL ) - return; - - //If we're pulling the weapon out for the first time, wait to draw the laser - if ( ( m_bInitialStateUpdate ) && ( GetActivity() != ACT_VM_DRAW ) ) - { - StartGuiding(); - m_bInitialStateUpdate = false; - } - - // Supress our guiding effects if we're lowered - if ( GetIdealActivity() == ACT_VM_IDLE_LOWERED ) - { - SuppressGuiding(); - } - else - { - SuppressGuiding( false ); - } - - //Move the laser - UpdateLaserPosition(); - - if ( pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0 && m_hMissile == NULL ) - { - StopGuiding(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Vector -//----------------------------------------------------------------------------- -Vector CWeaponRPG::GetLaserPosition( void ) -{ -#ifndef CLIENT_DLL - CreateLaserPointer(); - - if ( m_hLaserDot != NULL ) - return m_hLaserDot->GetAbsOrigin(); - - //FIXME: The laser dot sprite is not active, this code should not be allowed! - assert(0); -#endif - return vec3_origin; -} - -//----------------------------------------------------------------------------- -// Purpose: NPC RPG users cheat and directly set the laser pointer's origin -// Input : &vecTarget - -//----------------------------------------------------------------------------- -void CWeaponRPG::UpdateNPCLaserPosition( const Vector &vecTarget ) -{ - -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponRPG::SetNPCLaserPosition( const Vector &vecTarget ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const Vector &CWeaponRPG::GetNPCLaserPosition( void ) -{ - return vec3_origin; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true if the rocket is being guided, false if it's dumb -//----------------------------------------------------------------------------- -bool CWeaponRPG::IsGuiding( void ) -{ - return m_bGuiding; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponRPG::Deploy( void ) -{ - m_bInitialStateUpdate = true; - - return BaseClass::Deploy(); -} - -bool CWeaponRPG::CanHolster( void ) -{ - //Can't have an active missile out - if ( m_hMissile != NULL ) - return false; - - return BaseClass::CanHolster(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CWeaponRPG::Holster( CBaseCombatWeapon *pSwitchingTo ) -{ - StopGuiding(); - - return BaseClass::Holster( pSwitchingTo ); -} - -//----------------------------------------------------------------------------- -// Purpose: Turn on the guiding laser -//----------------------------------------------------------------------------- -void CWeaponRPG::StartGuiding( void ) -{ - // Don't start back up if we're overriding this - if ( m_bHideGuiding ) - return; - - m_bGuiding = true; - -#ifndef CLIENT_DLL - WeaponSound(SPECIAL1); - - CreateLaserPointer(); -#endif - -} - -//----------------------------------------------------------------------------- -// Purpose: Turn off the guiding laser -//----------------------------------------------------------------------------- -void CWeaponRPG::StopGuiding( void ) -{ - m_bGuiding = false; - -#ifndef CLIENT_DLL - - WeaponSound( SPECIAL2 ); - - // Kill the dot completely - if ( m_hLaserDot != NULL ) - { - m_hLaserDot->TurnOff(); - UTIL_Remove( m_hLaserDot ); - m_hLaserDot = NULL; - } -#else - if ( m_pBeam ) - { - //Tell it to die right away and let the beam code free it. - m_pBeam->brightness = 0.0f; - m_pBeam->flags &= ~FBEAM_FOREVER; - m_pBeam->die = gpGlobals->curtime - 0.1; - m_pBeam = NULL; - } -#endif - -} - -//----------------------------------------------------------------------------- -// Purpose: Toggle the guiding laser -//----------------------------------------------------------------------------- -void CWeaponRPG::ToggleGuiding( void ) -{ - if ( IsGuiding() ) - { - StopGuiding(); - } - else - { - StartGuiding(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponRPG::Drop( const Vector &vecVelocity ) -{ - StopGuiding(); - - BaseClass::Drop( vecVelocity ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponRPG::UpdateLaserPosition( Vector vecMuzzlePos, Vector vecEndPos ) -{ - -#ifndef CLIENT_DLL - if ( vecMuzzlePos == vec3_origin || vecEndPos == vec3_origin ) - { - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - if ( !pPlayer ) - return; - - vecMuzzlePos = pPlayer->Weapon_ShootPosition(); - Vector forward; - pPlayer->EyeVectors( &forward ); - vecEndPos = vecMuzzlePos + ( forward * MAX_TRACE_LENGTH ); - } - - //Move the laser dot, if active - trace_t tr; - - // Trace out for the endpoint - UTIL_TraceLine( vecMuzzlePos, vecEndPos, (MASK_SHOT & ~CONTENTS_WINDOW), GetOwner(), COLLISION_GROUP_NONE, &tr ); - - // Move the laser sprite - if ( m_hLaserDot != NULL ) - { - Vector laserPos = tr.endpos; - m_hLaserDot->SetLaserPosition( laserPos, tr.plane.normal ); - - if ( tr.DidHitNonWorldEntity() ) - { - CBaseEntity *pHit = tr.m_pEnt; - - if ( ( pHit != NULL ) && ( pHit->m_takedamage ) ) - { - m_hLaserDot->SetTargetEntity( pHit ); - } - else - { - m_hLaserDot->SetTargetEntity( NULL ); - } - } - else - { - m_hLaserDot->SetTargetEntity( NULL ); - } - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponRPG::CreateLaserPointer( void ) -{ -#ifndef CLIENT_DLL - if ( m_hLaserDot != NULL ) - return; - - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - return; - - if ( pOwner->GetAmmoCount(m_iPrimaryAmmoType) <= 0 ) - return; - - m_hLaserDot = CLaserDot::Create( GetAbsOrigin(), GetOwner() ); - m_hLaserDot->TurnOff(); - - UpdateLaserPosition(); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponRPG::NotifyRocketDied( void ) -{ - m_hMissile = NULL; - - if ( GetActivity() == ACT_VM_RELOAD ) - return; - - Reload(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CWeaponRPG::Reload( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - return false; - - if ( pOwner->GetAmmoCount(m_iPrimaryAmmoType) <= 0 ) - return false; - - WeaponSound( RELOAD ); - - SendWeaponAnim( ACT_VM_RELOAD ); - - return true; -} - -#ifdef CLIENT_DLL - -#define RPG_MUZZLE_ATTACHMENT 1 -#define RPG_GUIDE_ATTACHMENT 2 -#define RPG_GUIDE_TARGET_ATTACHMENT 3 - -#define RPG_GUIDE_ATTACHMENT_3RD 4 -#define RPG_GUIDE_TARGET_ATTACHMENT_3RD 5 - -#define RPG_LASER_BEAM_LENGTH 128 - -extern void FormatViewModelAttachment( Vector &vOrigin, bool bInverse ); - -//----------------------------------------------------------------------------- -// Purpose: Returns the attachment point on either the world or viewmodel -// This should really be worked into the CBaseCombatWeapon class! -//----------------------------------------------------------------------------- -void CWeaponRPG::GetWeaponAttachment( int attachmentId, Vector &outVector, Vector *dir /*= NULL*/ ) -{ - QAngle angles; - - if ( IsCarriedByLocalPlayer() ) - { - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner != NULL ) - { - pOwner->GetViewModel()->GetAttachment( attachmentId, outVector, angles ); - ::FormatViewModelAttachment( outVector, true ); - } - } - else - { - // We offset the IDs to make them correct for our world model - BaseClass::GetAttachment( attachmentId, outVector, angles ); - } - - // Supply the direction, if requested - if ( dir != NULL ) - { - AngleVectors( angles, dir, NULL, NULL ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Setup our laser beam -//----------------------------------------------------------------------------- -void CWeaponRPG::InitBeam( void ) -{ - if ( m_pBeam != NULL ) - return; - - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - return; - - if ( pOwner->GetAmmoCount(m_iPrimaryAmmoType) <= 0 ) - return; - - - BeamInfo_t beamInfo; - - CBaseEntity *pEntity = NULL; - - if ( IsCarriedByLocalPlayer() ) - { - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - - if ( pOwner != NULL ) - { - pEntity = pOwner->GetViewModel(); - } - } - else - { - pEntity = this; - } - - beamInfo.m_pStartEnt = pEntity; - beamInfo.m_pEndEnt = pEntity; - beamInfo.m_nType = TE_BEAMPOINTS; - beamInfo.m_vecStart = vec3_origin; - beamInfo.m_vecEnd = vec3_origin; - - beamInfo.m_pszModelName = ( IsCarriedByLocalPlayer() ) ? RPG_BEAM_SPRITE_NOZ : RPG_BEAM_SPRITE; - - beamInfo.m_flHaloScale = 0.0f; - beamInfo.m_flLife = 0.0f; - - if ( IsCarriedByLocalPlayer() ) - { - beamInfo.m_flWidth = 2.0f; - beamInfo.m_flEndWidth = 2.0f; - beamInfo.m_nStartAttachment = RPG_GUIDE_ATTACHMENT; - beamInfo.m_nEndAttachment = RPG_GUIDE_TARGET_ATTACHMENT; - } - else - { - beamInfo.m_flWidth = 1.0f; - beamInfo.m_flEndWidth = 1.0f; - beamInfo.m_nStartAttachment = RPG_GUIDE_ATTACHMENT_3RD; - beamInfo.m_nEndAttachment = RPG_GUIDE_TARGET_ATTACHMENT_3RD; - } - - beamInfo.m_flFadeLength = 0.0f; - beamInfo.m_flAmplitude = 0; - beamInfo.m_flBrightness = 255.0; - beamInfo.m_flSpeed = 1.0f; - beamInfo.m_nStartFrame = 0.0; - beamInfo.m_flFrameRate = 30.0; - beamInfo.m_flRed = 255.0; - beamInfo.m_flGreen = 0.0; - beamInfo.m_flBlue = 0.0; - beamInfo.m_nSegments = 4; - beamInfo.m_bRenderable = true; - beamInfo.m_nFlags = (FBEAM_FOREVER|FBEAM_SHADEOUT); - - m_pBeam = beams->CreateBeamEntPoint( beamInfo ); -} - -//----------------------------------------------------------------------------- -// Purpose: Draw effects for our weapon -//----------------------------------------------------------------------------- -void CWeaponRPG::DrawEffects( void ) -{ - // Must be guiding and not hidden - if ( !m_bGuiding || m_bHideGuiding ) - { - if ( m_pBeam != NULL ) - { - m_pBeam->brightness = 0; - } - - return; - } - - // Setup our sprite - if ( m_hSpriteMaterial == NULL ) - { - m_hSpriteMaterial.Init( RPG_LASER_SPRITE, TEXTURE_GROUP_CLIENT_EFFECTS ); - } - - // Setup our beam - if ( m_hBeamMaterial == NULL ) - { - m_hBeamMaterial.Init( RPG_BEAM_SPRITE, TEXTURE_GROUP_CLIENT_EFFECTS ); - } - - color32 color={255,255,255,255}; - Vector vecAttachment, vecDir; - QAngle angles; - - float scale = 8.0f + random->RandomFloat( -2.0f, 2.0f ); - - int attachmentID = ( IsCarriedByLocalPlayer() ) ? RPG_GUIDE_ATTACHMENT : RPG_GUIDE_ATTACHMENT_3RD; - - GetWeaponAttachment( attachmentID, vecAttachment, &vecDir ); - - // Draw the sprite - CMatRenderContextPtr pRenderContext( materials ); - pRenderContext->Bind( m_hSpriteMaterial, this ); - DrawSprite( vecAttachment, scale, scale, color ); - - // Get the beam's run - trace_t tr; - UTIL_TraceLine( vecAttachment, vecAttachment + ( vecDir * RPG_LASER_BEAM_LENGTH ), MASK_SHOT, GetOwner(), COLLISION_GROUP_NONE, &tr ); - - InitBeam(); - - if ( m_pBeam != NULL ) - { - m_pBeam->fadeLength = RPG_LASER_BEAM_LENGTH * tr.fraction; - m_pBeam->brightness = random->RandomInt( 128, 200 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Called on third-person weapon drawing -//----------------------------------------------------------------------------- -int CWeaponRPG::DrawModel( int flags ) -{ - // Only render these on the transparent pass - if ( flags & STUDIO_TRANSPARENCY ) - { - DrawEffects(); - return 1; - } - - // Draw the model as normal - return BaseClass::DrawModel( flags ); -} - -//----------------------------------------------------------------------------- -// Purpose: Called after first-person viewmodel is drawn -//----------------------------------------------------------------------------- -void CWeaponRPG::ViewModelDrawn( C_BaseViewModel *pBaseViewModel ) -{ - // Draw our laser effects - DrawEffects(); - - BaseClass::ViewModelDrawn( pBaseViewModel ); -} - -//----------------------------------------------------------------------------- -// Purpose: Used to determine sorting of model when drawn -//----------------------------------------------------------------------------- -bool CWeaponRPG::IsTranslucent( void ) -{ - // Must be guiding and not hidden - if ( m_bGuiding && !m_bHideGuiding ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Turns off effects when leaving the PVS -//----------------------------------------------------------------------------- -void CWeaponRPG::NotifyShouldTransmit( ShouldTransmitState_t state ) -{ - BaseClass::NotifyShouldTransmit(state); - - if ( state == SHOULDTRANSMIT_END ) - { - if ( m_pBeam != NULL ) - { - m_pBeam->brightness = 0.0f; - } - } -} - -#endif //CLIENT_DLL - - -//============================================================================= -// Laser Dot -//============================================================================= - -LINK_ENTITY_TO_CLASS( env_laserdot, CLaserDot ); - -BEGIN_DATADESC( CLaserDot ) - DEFINE_FIELD( m_vecSurfaceNormal, FIELD_VECTOR ), - DEFINE_FIELD( m_hTargetEnt, FIELD_EHANDLE ), - DEFINE_FIELD( m_bVisibleLaserDot, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bIsOn, FIELD_BOOLEAN ), - - //DEFINE_FIELD( m_pNext, FIELD_CLASSPTR ), // don't save - regenerated by constructor -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Finds missiles in cone -//----------------------------------------------------------------------------- -CBaseEntity *CreateLaserDot( const Vector &origin, CBaseEntity *pOwner, bool bVisibleDot ) -{ - return CLaserDot::Create( origin, pOwner, bVisibleDot ); -} - -void SetLaserDotTarget( CBaseEntity *pLaserDot, CBaseEntity *pTarget ) -{ - CLaserDot *pDot = assert_cast< CLaserDot* >(pLaserDot ); - pDot->SetTargetEntity( pTarget ); -} - -void EnableLaserDot( CBaseEntity *pLaserDot, bool bEnable ) -{ - CLaserDot *pDot = assert_cast< CLaserDot* >(pLaserDot ); - if ( bEnable ) - { - pDot->TurnOn(); - } - else - { - pDot->TurnOff(); - } -} - -CLaserDot::CLaserDot( void ) -{ - m_hTargetEnt = NULL; - m_bIsOn = true; -#ifndef CLIENT_DLL - g_LaserDotList.Insert( this ); -#endif -} - -CLaserDot::~CLaserDot( void ) -{ -#ifndef CLIENT_DLL - g_LaserDotList.Remove( this ); -#endif -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &origin - -// Output : CLaserDot -//----------------------------------------------------------------------------- -CLaserDot *CLaserDot::Create( const Vector &origin, CBaseEntity *pOwner, bool bVisibleDot ) -{ -#ifndef CLIENT_DLL - CLaserDot *pLaserDot = (CLaserDot *) CBaseEntity::Create( "env_laserdot", origin, QAngle(0,0,0) ); - - if ( pLaserDot == NULL ) - return NULL; - - pLaserDot->m_bVisibleLaserDot = bVisibleDot; - pLaserDot->SetMoveType( MOVETYPE_NONE ); - pLaserDot->AddSolidFlags( FSOLID_NOT_SOLID ); - pLaserDot->AddEffects( EF_NOSHADOW ); - UTIL_SetSize( pLaserDot, -Vector(4,4,4), Vector(4,4,4) ); - - pLaserDot->SetOwnerEntity( pOwner ); - - pLaserDot->AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); - - if ( !bVisibleDot ) - { - pLaserDot->MakeInvisible(); - } - - return pLaserDot; -#else - return NULL; -#endif -} - -void CLaserDot::SetLaserPosition( const Vector &origin, const Vector &normal ) -{ - SetAbsOrigin( origin ); - m_vecSurfaceNormal = normal; -} - -Vector CLaserDot::GetChasePosition() -{ - return GetAbsOrigin() - m_vecSurfaceNormal * 10; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CLaserDot::TurnOn( void ) -{ - m_bIsOn = true; - if ( m_bVisibleLaserDot ) - { - //BaseClass::TurnOn(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CLaserDot::TurnOff( void ) -{ - m_bIsOn = false; - if ( m_bVisibleLaserDot ) - { - //BaseClass::TurnOff(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CLaserDot::MakeInvisible( void ) -{ -} - -#ifdef CLIENT_DLL - -//----------------------------------------------------------------------------- -// Purpose: Draw our sprite -//----------------------------------------------------------------------------- -int CLaserDot::DrawModel( int flags ) -{ - color32 color={255,255,255,255}; - Vector vecAttachment, vecDir; - QAngle angles; - - float scale; - Vector endPos; - - C_HL2MP_Player *pOwner = ToHL2MPPlayer( GetOwnerEntity() ); - - if ( pOwner != NULL && pOwner->IsDormant() == false ) - { - // Always draw the dot in front of our faces when in first-person - if ( pOwner->IsLocalPlayer() ) - { - // Take our view position and orientation - vecAttachment = CurrentViewOrigin(); - vecDir = CurrentViewForward(); - } - else - { - // Take the eye position and direction - vecAttachment = pOwner->EyePosition(); - - QAngle angles = pOwner->GetAnimEyeAngles(); - AngleVectors( angles, &vecDir ); - } - - trace_t tr; - UTIL_TraceLine( vecAttachment, vecAttachment + ( vecDir * MAX_TRACE_LENGTH ), MASK_SHOT, pOwner, COLLISION_GROUP_NONE, &tr ); - - // Backup off the hit plane - endPos = tr.endpos + ( tr.plane.normal * 4.0f ); - } - else - { - // Just use our position if we can't predict it otherwise - endPos = GetAbsOrigin(); - } - - // Randomly flutter - scale = 16.0f + random->RandomFloat( -4.0f, 4.0f ); - - // Draw our laser dot in space - CMatRenderContextPtr pRenderContext( materials ); - pRenderContext->Bind( m_hSpriteMaterial, this ); - DrawSprite( endPos, scale, scale, color ); - - return 1; -} - -//----------------------------------------------------------------------------- -// Purpose: Setup our sprite reference -//----------------------------------------------------------------------------- -void CLaserDot::OnDataChanged( DataUpdateType_t updateType ) -{ - if ( updateType == DATA_UPDATE_CREATED ) - { - m_hSpriteMaterial.Init( RPG_LASER_SPRITE, TEXTURE_GROUP_CLIENT_EFFECTS ); - } -} - -#endif //CLIENT_DLL diff --git a/game/shared/hl2mp/weapon_rpg.h b/game/shared/hl2mp/weapon_rpg.h deleted file mode 100644 index d1fb211ae..000000000 --- a/game/shared/hl2mp/weapon_rpg.h +++ /dev/null @@ -1,267 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef WEAPON_RPG_H -#define WEAPON_RPG_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "weapon_hl2mpbasehlmpcombatweapon.h" - -#ifdef CLIENT_DLL - - #include "iviewrender_beams.h" - -#endif - -#ifndef CLIENT_DLL -#include "Sprite.h" -#include "npcevent.h" -#include "beam_shared.h" - -class CWeaponRPG; -class CLaserDot; -class RocketTrail; - -//########################################################################### -// >> CMissile (missile launcher class is below this one!) -//########################################################################### -class CMissile : public CBaseCombatCharacter -{ - DECLARE_CLASS( CMissile, CBaseCombatCharacter ); - -public: - CMissile(); - ~CMissile(); - -#ifdef HL1_DLL - Class_T Classify( void ) { return CLASS_NONE; } -#else - Class_T Classify( void ) { return CLASS_MISSILE; } -#endif - - void Spawn( void ); - void Precache( void ); - void MissileTouch( CBaseEntity *pOther ); - void Explode( void ); - void ShotDown( void ); - void AccelerateThink( void ); - void AugerThink( void ); - void IgniteThink( void ); - void SeekThink( void ); - void DumbFire( void ); - void SetGracePeriod( float flGracePeriod ); - - int OnTakeDamage_Alive( const CTakeDamageInfo &info ); - void Event_Killed( const CTakeDamageInfo &info ); - - virtual float GetDamage() { return m_flDamage; } - virtual void SetDamage(float flDamage) { m_flDamage = flDamage; } - - unsigned int PhysicsSolidMaskForEntity( void ) const; - - CHandle m_hOwner; - - static CMissile *Create( const Vector &vecOrigin, const QAngle &vecAngles, edict_t *pentOwner ); - -protected: - virtual void DoExplosion(); - virtual void ComputeActualDotPosition( CLaserDot *pLaserDot, Vector *pActualDotPosition, float *pHomingSpeed ); - virtual int AugerHealth() { return m_iMaxHealth - 20; } - - // Creates the smoke trail - void CreateSmokeTrail( void ); - - // Gets the shooting position - void GetShootPosition( CLaserDot *pLaserDot, Vector *pShootPosition ); - - CHandle m_hRocketTrail; - float m_flAugerTime; // Amount of time to auger before blowing up anyway - float m_flMarkDeadTime; - float m_flDamage; - -private: - float m_flGracePeriodEndsAt; - - DECLARE_DATADESC(); -}; - - -//----------------------------------------------------------------------------- -// Laser dot control -//----------------------------------------------------------------------------- -CBaseEntity *CreateLaserDot( const Vector &origin, CBaseEntity *pOwner, bool bVisibleDot ); -void SetLaserDotTarget( CBaseEntity *pLaserDot, CBaseEntity *pTarget ); -void EnableLaserDot( CBaseEntity *pLaserDot, bool bEnable ); - - -//----------------------------------------------------------------------------- -// Specialized mizzizzile -//----------------------------------------------------------------------------- -class CAPCMissile : public CMissile -{ - DECLARE_CLASS( CMissile, CMissile ); - DECLARE_DATADESC(); - -public: - static CAPCMissile *Create( const Vector &vecOrigin, const QAngle &vecAngles, const Vector &vecVelocity, CBaseEntity *pOwner ); - - CAPCMissile(); - ~CAPCMissile(); - void IgniteDelay( void ); - void AugerDelay( float flDelayTime ); - void ExplodeDelay( float flDelayTime ); - void DisableGuiding(); -#if defined( HL2_DLL ) - virtual Class_T Classify ( void ) { return CLASS_COMBINE; } -#endif - - void AimAtSpecificTarget( CBaseEntity *pTarget ); - void SetGuidanceHint( const char *pHintName ); - - CAPCMissile *m_pNext; - -protected: - virtual void DoExplosion(); - virtual void ComputeActualDotPosition( CLaserDot *pLaserDot, Vector *pActualDotPosition, float *pHomingSpeed ); - virtual int AugerHealth(); - -private: - void Init(); - void ComputeLeadingPosition( const Vector &vecShootPosition, CBaseEntity *pTarget, Vector *pLeadPosition ); - void BeginSeekThink(); - void AugerStartThink(); - void ExplodeThink(); - void APCMissileTouch( CBaseEntity *pOther ); - - float m_flReachedTargetTime; - float m_flIgnitionTime; - bool m_bGuidingDisabled; - float m_flLastHomingSpeed; - EHANDLE m_hSpecificTarget; - string_t m_strHint; -}; - - -//----------------------------------------------------------------------------- -// Finds apc missiles in cone -//----------------------------------------------------------------------------- -CAPCMissile *FindAPCMissileInCone( const Vector &vecOrigin, const Vector &vecDirection, float flAngle ); - -#endif - -//----------------------------------------------------------------------------- -// RPG -//----------------------------------------------------------------------------- - -#ifdef CLIENT_DLL -#define CWeaponRPG C_WeaponRPG -#endif - -class CWeaponRPG : public CBaseHL2MPCombatWeapon -{ - DECLARE_CLASS( CWeaponRPG, CBaseHL2MPCombatWeapon ); -public: - - CWeaponRPG(); - ~CWeaponRPG(); - - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - - void Precache( void ); - - void PrimaryAttack( void ); - virtual float GetFireRate( void ) { return 1; }; - void ItemPostFrame( void ); - - void Activate( void ); - void DecrementAmmo( CBaseCombatCharacter *pOwner ); - - bool Deploy( void ); - bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); - bool Reload( void ); - bool WeaponShouldBeLowered( void ); - bool Lower( void ); - - bool CanHolster( void ); - - virtual void Drop( const Vector &vecVelocity ); - - int GetMinBurst() { return 1; } - int GetMaxBurst() { return 1; } - float GetMinRestTime() { return 4.0; } - float GetMaxRestTime() { return 4.0; } - - void StartGuiding( void ); - void StopGuiding( void ); - void ToggleGuiding( void ); - bool IsGuiding( void ); - - void NotifyRocketDied( void ); - - bool HasAnyAmmo( void ); - - void SuppressGuiding( bool state = true ); - - void CreateLaserPointer( void ); - void UpdateLaserPosition( Vector vecMuzzlePos = vec3_origin, Vector vecEndPos = vec3_origin ); - Vector GetLaserPosition( void ); - - // NPC RPG users cheat and directly set the laser pointer's origin - void UpdateNPCLaserPosition( const Vector &vecTarget ); - void SetNPCLaserPosition( const Vector &vecTarget ); - const Vector &GetNPCLaserPosition( void ); - -#ifdef CLIENT_DLL - - // We need to render opaque and translucent pieces - virtual RenderGroup_t GetRenderGroup( void ) { return RENDER_GROUP_TWOPASS; } - - virtual void NotifyShouldTransmit( ShouldTransmitState_t state ); - virtual int DrawModel( int flags ); - virtual void ViewModelDrawn( C_BaseViewModel *pBaseViewModel ); - virtual bool IsTranslucent( void ); - - void InitBeam( void ); - void GetWeaponAttachment( int attachmentId, Vector &outVector, Vector *dir = NULL ); - void DrawEffects( void ); -// void DrawLaserDot( void ); - - CMaterialReference m_hSpriteMaterial; // Used for the laser glint - CMaterialReference m_hBeamMaterial; // Used for the laser beam - Beam_t *m_pBeam; // Laser beam temp entity - -#endif //CLIENT_DLL - - CBaseEntity *GetMissile( void ) { return m_hMissile; } - -#ifndef CLIENT_DLL - DECLARE_ACTTABLE(); -#endif - -protected: - - CNetworkVar( bool, m_bInitialStateUpdate ); - CNetworkVar( bool, m_bGuiding ); - CNetworkVar( bool, m_bHideGuiding ); - - CNetworkHandle( CBaseEntity, m_hMissile ); - CNetworkVar( Vector, m_vecLaserDot ); - -#ifndef CLIENT_DLL - CHandle m_hLaserDot; -#endif - -private: - - CWeaponRPG( const CWeaponRPG & ); -}; - -#endif // WEAPON_RPG_H diff --git a/game/shared/hl2mp/weapon_shotgun.cpp b/game/shared/hl2mp/weapon_shotgun.cpp deleted file mode 100644 index 87a89b7d8..000000000 --- a/game/shared/hl2mp/weapon_shotgun.cpp +++ /dev/null @@ -1,634 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" -#include "in_buttons.h" - -#ifdef CLIENT_DLL - #include "c_hl2mp_player.h" -#else - #include "hl2mp_player.h" -#endif - -#include "weapon_hl2mpbasehlmpcombatweapon.h" - -#ifdef CLIENT_DLL -#define CWeaponShotgun C_WeaponShotgun -#endif - -extern ConVar sk_auto_reload_time; -extern ConVar sk_plr_num_shotgun_pellets; - -class CWeaponShotgun : public CBaseHL2MPCombatWeapon -{ -public: - DECLARE_CLASS( CWeaponShotgun, CBaseHL2MPCombatWeapon ); - - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - -private: - CNetworkVar( bool, m_bNeedPump ); // When emptied completely - CNetworkVar( bool, m_bDelayedFire1 ); // Fire primary when finished reloading - CNetworkVar( bool, m_bDelayedFire2 ); // Fire secondary when finished reloading - CNetworkVar( bool, m_bDelayedReload ); // Reload when finished pump - -public: - virtual const Vector& GetBulletSpread( void ) - { - static Vector cone = VECTOR_CONE_10DEGREES; - return cone; - } - - virtual int GetMinBurst() { return 1; } - virtual int GetMaxBurst() { return 3; } - - bool StartReload( void ); - bool Reload( void ); - void FillClip( void ); - void FinishReload( void ); - void CheckHolsterReload( void ); - void Pump( void ); -// void WeaponIdle( void ); - void ItemHolsterFrame( void ); - void ItemPostFrame( void ); - void PrimaryAttack( void ); - void SecondaryAttack( void ); - void DryFire( void ); - virtual float GetFireRate( void ) { return 0.7; }; - -#ifndef CLIENT_DLL - DECLARE_ACTTABLE(); -#endif - - CWeaponShotgun(void); - -private: - CWeaponShotgun( const CWeaponShotgun & ); -}; - -IMPLEMENT_NETWORKCLASS_ALIASED( WeaponShotgun, DT_WeaponShotgun ) - -BEGIN_NETWORK_TABLE( CWeaponShotgun, DT_WeaponShotgun ) -#ifdef CLIENT_DLL - RecvPropBool( RECVINFO( m_bNeedPump ) ), - RecvPropBool( RECVINFO( m_bDelayedFire1 ) ), - RecvPropBool( RECVINFO( m_bDelayedFire2 ) ), - RecvPropBool( RECVINFO( m_bDelayedReload ) ), -#else - SendPropBool( SENDINFO( m_bNeedPump ) ), - SendPropBool( SENDINFO( m_bDelayedFire1 ) ), - SendPropBool( SENDINFO( m_bDelayedFire2 ) ), - SendPropBool( SENDINFO( m_bDelayedReload ) ), -#endif -END_NETWORK_TABLE() - -#ifdef CLIENT_DLL -BEGIN_PREDICTION_DATA( CWeaponShotgun ) - DEFINE_PRED_FIELD( m_bNeedPump, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_bDelayedFire1, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_bDelayedFire2, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_bDelayedReload, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), -END_PREDICTION_DATA() -#endif - -LINK_ENTITY_TO_CLASS( weapon_shotgun, CWeaponShotgun ); -PRECACHE_WEAPON_REGISTER(weapon_shotgun); - -#ifndef CLIENT_DLL -acttable_t CWeaponShotgun::m_acttable[] = -{ - { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_SHOTGUN, false }, - { ACT_HL2MP_RUN, ACT_HL2MP_RUN_SHOTGUN, false }, - { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_SHOTGUN, false }, - { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_SHOTGUN, false }, - { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_SHOTGUN, false }, - { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_SHOTGUN, false }, - { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_SHOTGUN, false }, - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SHOTGUN, false }, -}; - -IMPLEMENT_ACTTABLE(CWeaponShotgun); - -#endif - - -//----------------------------------------------------------------------------- -// Purpose: Override so only reload one shell at a time -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CWeaponShotgun::StartReload( void ) -{ - if ( m_bNeedPump ) - return false; - - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - return false; - - if (pOwner->GetAmmoCount(m_iPrimaryAmmoType) <= 0) - return false; - - if (m_iClip1 >= GetMaxClip1()) - return false; - - - int j = MIN(1, pOwner->GetAmmoCount(m_iPrimaryAmmoType)); - - if (j <= 0) - return false; - - SendWeaponAnim( ACT_SHOTGUN_RELOAD_START ); - - // Make shotgun shell visible - SetBodygroup(1,0); - - pOwner->m_flNextAttack = gpGlobals->curtime; - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - - m_bInReload = true; - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Override so only reload one shell at a time -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CWeaponShotgun::Reload( void ) -{ - // Check that StartReload was called first - if (!m_bInReload) - { - Warning("ERROR: Shotgun Reload called incorrectly!\n"); - } - - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - return false; - - if (pOwner->GetAmmoCount(m_iPrimaryAmmoType) <= 0) - return false; - - if (m_iClip1 >= GetMaxClip1()) - return false; - - int j = MIN(1, pOwner->GetAmmoCount(m_iPrimaryAmmoType)); - - if (j <= 0) - return false; - - FillClip(); - // Play reload on different channel as otherwise steals channel away from fire sound - WeaponSound(RELOAD); - SendWeaponAnim( ACT_VM_RELOAD ); - - pOwner->m_flNextAttack = gpGlobals->curtime; - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Play finish reload anim and fill clip -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeaponShotgun::FinishReload( void ) -{ - // Make shotgun shell invisible - SetBodygroup(1,1); - - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - return; - - m_bInReload = false; - - // Finish reload animation - SendWeaponAnim( ACT_SHOTGUN_RELOAD_FINISH ); - - pOwner->m_flNextAttack = gpGlobals->curtime; - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); -} - -//----------------------------------------------------------------------------- -// Purpose: Play finish reload anim and fill clip -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeaponShotgun::FillClip( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - return; - - // Add them to the clip - if ( pOwner->GetAmmoCount( m_iPrimaryAmmoType ) > 0 ) - { - if ( Clip1() < GetMaxClip1() ) - { - m_iClip1++; - pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Play weapon pump anim -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeaponShotgun::Pump( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( pOwner == NULL ) - return; - - m_bNeedPump = false; - - if ( m_bDelayedReload ) - { - m_bDelayedReload = false; - StartReload(); - } - - WeaponSound( SPECIAL1 ); - - // Finish reload animation - SendWeaponAnim( ACT_SHOTGUN_PUMP ); - - pOwner->m_flNextAttack = gpGlobals->curtime + SequenceDuration(); - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CWeaponShotgun::DryFire( void ) -{ - WeaponSound(EMPTY); - SendWeaponAnim( ACT_VM_DRYFIRE ); - - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CWeaponShotgun::PrimaryAttack( void ) -{ - // Only the player fires this way so we can cast - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if (!pPlayer) - { - return; - } - - // MUST call sound before removing a round from the clip of a CMachineGun - WeaponSound(SINGLE); - - pPlayer->DoMuzzleFlash(); - - SendWeaponAnim( ACT_VM_PRIMARYATTACK ); - - // Don't fire again until fire animation has completed - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - m_iClip1 -= 1; - - // player "shoot" animation - pPlayer->SetAnimation( PLAYER_ATTACK1 ); - - Vector vecSrc = pPlayer->Weapon_ShootPosition( ); - Vector vecAiming = pPlayer->GetAutoaimVector( AUTOAIM_10DEGREES ); - - FireBulletsInfo_t info( 7, vecSrc, vecAiming, GetBulletSpread(), MAX_TRACE_LENGTH, m_iPrimaryAmmoType ); - info.m_pAttacker = pPlayer; - - // Fire the bullets, and force the first shot to be perfectly accuracy - pPlayer->FireBullets( info ); - - QAngle punch; - punch.Init( SharedRandomFloat( "shotgunpax", -2, -1 ), SharedRandomFloat( "shotgunpay", -2, 2 ), 0 ); - pPlayer->ViewPunch( punch ); - - if (!m_iClip1 && pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0) - { - // HEV suit - indicate out of ammo condition - pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); - } - - m_bNeedPump = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// -// -//----------------------------------------------------------------------------- -void CWeaponShotgun::SecondaryAttack( void ) -{ - // Only the player fires this way so we can cast - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if (!pPlayer) - { - return; - } - - pPlayer->m_nButtons &= ~IN_ATTACK2; - // MUST call sound before removing a round from the clip of a CMachineGun - WeaponSound(WPN_DOUBLE); - - pPlayer->DoMuzzleFlash(); - - SendWeaponAnim( ACT_VM_SECONDARYATTACK ); - - // Don't fire again until fire animation has completed - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - m_iClip1 -= 2; // Shotgun uses same clip for primary and secondary attacks - - // player "shoot" animation - pPlayer->SetAnimation( PLAYER_ATTACK1 ); - - Vector vecSrc = pPlayer->Weapon_ShootPosition(); - Vector vecAiming = pPlayer->GetAutoaimVector( AUTOAIM_10DEGREES ); - - FireBulletsInfo_t info( 12, vecSrc, vecAiming, GetBulletSpread(), MAX_TRACE_LENGTH, m_iPrimaryAmmoType ); - info.m_pAttacker = pPlayer; - - // Fire the bullets, and force the first shot to be perfectly accuracy - pPlayer->FireBullets( info ); - pPlayer->ViewPunch( QAngle(SharedRandomFloat( "shotgunsax", -5, 5 ),0,0) ); - - if (!m_iClip1 && pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0) - { - // HEV suit - indicate out of ammo condition - pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, 0); - } - - m_bNeedPump = true; -} - -//----------------------------------------------------------------------------- -// Purpose: Override so shotgun can do mulitple reloads in a row -//----------------------------------------------------------------------------- -void CWeaponShotgun::ItemPostFrame( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if (!pOwner) - { - return; - } - - if ( m_bNeedPump && ( pOwner->m_nButtons & IN_RELOAD ) ) - { - m_bDelayedReload = true; - } - - if (m_bInReload) - { - // If I'm primary firing and have one round stop reloading and fire - if ((pOwner->m_nButtons & IN_ATTACK ) && (m_iClip1 >=1) && !m_bNeedPump ) - { - m_bInReload = false; - m_bNeedPump = false; - m_bDelayedFire1 = true; - } - // If I'm secondary firing and have two rounds stop reloading and fire - else if ((pOwner->m_nButtons & IN_ATTACK2 ) && (m_iClip1 >=2) && !m_bNeedPump ) - { - m_bInReload = false; - m_bNeedPump = false; - m_bDelayedFire2 = true; - } - else if (m_flNextPrimaryAttack <= gpGlobals->curtime) - { - // If out of ammo end reload - if (pOwner->GetAmmoCount(m_iPrimaryAmmoType) <=0) - { - FinishReload(); - return; - } - // If clip not full reload again - if (m_iClip1 < GetMaxClip1()) - { - Reload(); - return; - } - // Clip full, stop reloading - else - { - FinishReload(); - return; - } - } - } - else - { - // Make shotgun shell invisible - SetBodygroup(1,1); - } - - if ((m_bNeedPump) && (m_flNextPrimaryAttack <= gpGlobals->curtime)) - { - Pump(); - return; - } - - // Shotgun uses same timing and ammo for secondary attack - if ((m_bDelayedFire2 || pOwner->m_nButtons & IN_ATTACK2)&&(m_flNextPrimaryAttack <= gpGlobals->curtime)) - { - m_bDelayedFire2 = false; - - if ( (m_iClip1 <= 1 && UsesClipsForAmmo1())) - { - // If only one shell is left, do a single shot instead - if ( m_iClip1 == 1 ) - { - PrimaryAttack(); - } - else if (!pOwner->GetAmmoCount(m_iPrimaryAmmoType)) - { - DryFire(); - } - else - { - StartReload(); - } - } - - // Fire underwater? - else if (GetOwner()->GetWaterLevel() == 3 && m_bFiresUnderwater == false) - { - WeaponSound(EMPTY); - m_flNextPrimaryAttack = gpGlobals->curtime + 0.2; - return; - } - else - { - // If the firing button was just pressed, reset the firing time - if ( pOwner->m_afButtonPressed & IN_ATTACK ) - { - m_flNextPrimaryAttack = gpGlobals->curtime; - } - SecondaryAttack(); - } - } - else if ( (m_bDelayedFire1 || pOwner->m_nButtons & IN_ATTACK) && m_flNextPrimaryAttack <= gpGlobals->curtime) - { - m_bDelayedFire1 = false; - if ( (m_iClip1 <= 0 && UsesClipsForAmmo1()) || ( !UsesClipsForAmmo1() && !pOwner->GetAmmoCount(m_iPrimaryAmmoType) ) ) - { - if (!pOwner->GetAmmoCount(m_iPrimaryAmmoType)) - { - DryFire(); - } - else - { - StartReload(); - } - } - // Fire underwater? - else if (pOwner->GetWaterLevel() == 3 && m_bFiresUnderwater == false) - { - WeaponSound(EMPTY); - m_flNextPrimaryAttack = gpGlobals->curtime + 0.2; - return; - } - else - { - // If the firing button was just pressed, reset the firing time - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - if ( pPlayer && pPlayer->m_afButtonPressed & IN_ATTACK ) - { - m_flNextPrimaryAttack = gpGlobals->curtime; - } - PrimaryAttack(); - } - } - - if ( pOwner->m_nButtons & IN_RELOAD && UsesClipsForAmmo1() && !m_bInReload ) - { - // reload when reload is pressed, or if no buttons are down and weapon is empty. - StartReload(); - } - else - { - // no fire buttons down - m_bFireOnEmpty = false; - - if ( !HasAnyAmmo() && m_flNextPrimaryAttack < gpGlobals->curtime ) - { - // weapon isn't useable, switch. - if ( !(GetWeaponFlags() & ITEM_FLAG_NOAUTOSWITCHEMPTY) && pOwner->SwitchToNextBestWeapon( this ) ) - { - m_flNextPrimaryAttack = gpGlobals->curtime + 0.3; - return; - } - } - else - { - // weapon is useable. Reload if empty and weapon has waited as long as it has to after firing - if ( m_iClip1 <= 0 && !(GetWeaponFlags() & ITEM_FLAG_NOAUTORELOAD) && m_flNextPrimaryAttack < gpGlobals->curtime ) - { - if (StartReload()) - { - // if we've successfully started to reload, we're done - return; - } - } - } - - WeaponIdle( ); - return; - } - -} - - - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -CWeaponShotgun::CWeaponShotgun( void ) -{ - m_bReloadsSingly = true; - - m_bNeedPump = false; - m_bDelayedFire1 = false; - m_bDelayedFire2 = false; - - m_fMinRange1 = 0.0; - m_fMaxRange1 = 500; - m_fMinRange2 = 0.0; - m_fMaxRange2 = 200; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponShotgun::ItemHolsterFrame( void ) -{ - // Must be player held - if ( GetOwner() && GetOwner()->IsPlayer() == false ) - return; - - // We can't be active - if ( GetOwner()->GetActiveWeapon() == this ) - return; - - // If it's been longer than three seconds, reload - if ( ( gpGlobals->curtime - m_flHolsterTime ) > sk_auto_reload_time.GetFloat() ) - { - // Reset the timer - m_flHolsterTime = gpGlobals->curtime; - - if ( GetOwner() == NULL ) - return; - - if ( m_iClip1 == GetMaxClip1() ) - return; - - // Just load the clip with no animations - int ammoFill = MIN( (GetMaxClip1() - m_iClip1), GetOwner()->GetAmmoCount( GetPrimaryAmmoType() ) ); - - GetOwner()->RemoveAmmo( ammoFill, GetPrimaryAmmoType() ); - m_iClip1 += ammoFill; - } -} - -//================================================== -// Purpose: -//================================================== -/* -void CWeaponShotgun::WeaponIdle( void ) -{ - //Only the player fires this way so we can cast - CBasePlayer *pPlayer = GetOwner() - - if ( pPlayer == NULL ) - return; - - //If we're on a target, play the new anim - if ( pPlayer->IsOnTarget() ) - { - SendWeaponAnim( ACT_VM_IDLE_ACTIVE ); - } -} -*/ diff --git a/game/shared/hl2mp/weapon_slam.cpp b/game/shared/hl2mp/weapon_slam.cpp deleted file mode 100644 index 6d4ddf3c0..000000000 --- a/game/shared/hl2mp/weapon_slam.cpp +++ /dev/null @@ -1,1052 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "gamerules.h" -#include "npcevent.h" -#include "in_buttons.h" -#include "engine/IEngineSound.h" - -#if defined( CLIENT_DLL ) - #include "c_hl2mp_player.h" -#else - #include "hl2mp_player.h" - #include "grenade_tripmine.h" - #include "grenade_satchel.h" - #include "entitylist.h" - #include "eventqueue.h" -#endif - -#include "hl2mp/weapon_slam.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SLAM_PRIMARY_VOLUME 450 - -IMPLEMENT_NETWORKCLASS_ALIASED( Weapon_SLAM, DT_Weapon_SLAM ) - -BEGIN_NETWORK_TABLE( CWeapon_SLAM, DT_Weapon_SLAM ) -#ifdef CLIENT_DLL - RecvPropInt( RECVINFO( m_tSlamState ) ), - RecvPropBool( RECVINFO( m_bDetonatorArmed ) ), - RecvPropBool( RECVINFO( m_bNeedDetonatorDraw ) ), - RecvPropBool( RECVINFO( m_bNeedDetonatorHolster ) ), - RecvPropBool( RECVINFO( m_bNeedReload ) ), - RecvPropBool( RECVINFO( m_bClearReload ) ), - RecvPropBool( RECVINFO( m_bThrowSatchel ) ), - RecvPropBool( RECVINFO( m_bAttachSatchel ) ), - RecvPropBool( RECVINFO( m_bAttachTripmine ) ), -#else - SendPropInt( SENDINFO( m_tSlamState ) ), - SendPropBool( SENDINFO( m_bDetonatorArmed ) ), - SendPropBool( SENDINFO( m_bNeedDetonatorDraw ) ), - SendPropBool( SENDINFO( m_bNeedDetonatorHolster ) ), - SendPropBool( SENDINFO( m_bNeedReload ) ), - SendPropBool( SENDINFO( m_bClearReload ) ), - SendPropBool( SENDINFO( m_bThrowSatchel ) ), - SendPropBool( SENDINFO( m_bAttachSatchel ) ), - SendPropBool( SENDINFO( m_bAttachTripmine ) ), -#endif -END_NETWORK_TABLE() - -#ifdef CLIENT_DLL - -BEGIN_PREDICTION_DATA( CWeapon_SLAM ) - DEFINE_PRED_FIELD( m_tSlamState, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_bDetonatorArmed, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_bNeedDetonatorDraw, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_bNeedDetonatorHolster, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_bNeedReload, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_bClearReload, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_bThrowSatchel, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_bAttachSatchel, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_bAttachTripmine, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), -END_PREDICTION_DATA() - -#endif - -LINK_ENTITY_TO_CLASS( weapon_slam, CWeapon_SLAM ); -PRECACHE_WEAPON_REGISTER(weapon_slam); - -#ifndef CLIENT_DLL - -BEGIN_DATADESC( CWeapon_SLAM ) - - DEFINE_FIELD( m_tSlamState, FIELD_INTEGER ), - DEFINE_FIELD( m_bDetonatorArmed, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bNeedDetonatorDraw, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bNeedDetonatorHolster, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bNeedReload, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bClearReload, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bThrowSatchel, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bAttachSatchel, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bAttachTripmine, FIELD_BOOLEAN ), - DEFINE_FIELD( m_flWallSwitchTime, FIELD_TIME ), - - // Function Pointers - DEFINE_FUNCTION( SlamTouch ), - -END_DATADESC() - -acttable_t CWeapon_SLAM::m_acttable[] = -{ - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SLAM, true }, - { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_SLAM, false }, - { ACT_HL2MP_RUN, ACT_HL2MP_RUN_SLAM, false }, - { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_SLAM, false }, - { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_SLAM, false }, - { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_SLAM, false }, - { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_SLAM, false }, - { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_SLAM, false }, -}; - -IMPLEMENT_ACTTABLE(CWeapon_SLAM); -#endif - - -void CWeapon_SLAM::Spawn( ) -{ - BaseClass::Spawn(); - - Precache( ); - - FallInit();// get ready to fall down - - m_tSlamState = (int)SLAM_SATCHEL_THROW; - m_flWallSwitchTime = 0; - - // Give 1 piece of default ammo when first picked up - m_iClip2 = 1; -} - -void CWeapon_SLAM::Precache( void ) -{ - BaseClass::Precache(); - -#ifndef CLIENT_DLL - UTIL_PrecacheOther( "npc_tripmine" ); - UTIL_PrecacheOther( "npc_satchel" ); -#endif - - PrecacheScriptSound( "Weapon_SLAM.TripMineMode" ); - PrecacheScriptSound( "Weapon_SLAM.SatchelDetonate" ); - PrecacheScriptSound( "Weapon_SLAM.SatchelThrow" ); -} - -//------------------------------------------------------------------------------ -// Purpose : Override to use slam's pickup touch function -// Input : -// Output : -//------------------------------------------------------------------------------ -void CWeapon_SLAM::SetPickupTouch( void ) -{ - SetTouch(&CWeapon_SLAM::SlamTouch); -} - -//----------------------------------------------------------------------------- -// Purpose: Override so give correct ammo -// Input : pOther - the entity that touched me -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::SlamTouch( CBaseEntity *pOther ) -{ -#ifdef GAME_DLL - CBaseCombatCharacter* pBCC = ToBaseCombatCharacter( pOther ); - - // Can I even pick stuff up? - if ( pBCC && !pBCC->IsAllowedToPickupWeapons() ) - return; -#endif - - // --------------------------------------------------- - // First give weapon to touching entity if allowed - // --------------------------------------------------- - BaseClass::DefaultTouch(pOther); -} - -//------------------------------------------------------------------------------ -// Purpose : -// Input : -// Output : -//------------------------------------------------------------------------------ -bool CWeapon_SLAM::Holster( CBaseCombatWeapon *pSwitchingTo ) -{ - SetThink(NULL); - return BaseClass::Holster(pSwitchingTo); -} - -//----------------------------------------------------------------------------- -// Purpose: SLAM has no reload, but must call weapon idle to update state -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CWeapon_SLAM::Reload( void ) -{ - WeaponIdle( ); - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::PrimaryAttack( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - if (!pOwner) - { - return; - } - - if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0) - { - return; - } - - switch (m_tSlamState) - { - case SLAM_TRIPMINE_READY: - if (CanAttachSLAM()) - { - StartTripmineAttach(); - } - break; - case SLAM_SATCHEL_THROW: - StartSatchelThrow(); - break; - case SLAM_SATCHEL_ATTACH: - StartSatchelAttach(); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Secondary attack switches between satchel charge and tripmine mode -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::SecondaryAttack( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - if (!pOwner) - { - return; - } - - if (m_bDetonatorArmed) - { - StartSatchelDetonate(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::SatchelDetonate() -{ -#ifndef CLIENT_DLL - CBaseEntity *pEntity = NULL; - - while ((pEntity = gEntList.FindEntityByClassname( pEntity, "npc_satchel" )) != NULL) - { - CSatchelCharge *pSatchel = dynamic_cast(pEntity); - if (pSatchel->m_bIsLive && pSatchel->GetThrower() && GetOwner() && pSatchel->GetThrower() == GetOwner()) - { - //pSatchel->Use( GetOwner(), GetOwner(), USE_ON, 0 ); - //variant_t emptyVariant; - //pSatchel->AcceptInput( "Explode", NULL, NULL, emptyVariant, 5 ); - g_EventQueue.AddEvent( pSatchel, "Explode", 0.20, GetOwner(), GetOwner() ); - } - } -#endif - // Play sound for pressing the detonator - EmitSound( "Weapon_SLAM.SatchelDetonate" ); - - m_bDetonatorArmed = false; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns true if there are any undetonated charges in the world -// that belong to this player -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CWeapon_SLAM::AnyUndetonatedCharges(void) -{ -#ifndef CLIENT_DLL - CBaseEntity *pEntity = NULL; - - while ((pEntity = gEntList.FindEntityByClassname( pEntity, "npc_satchel" )) != NULL) - { - CSatchelCharge* pSatchel = dynamic_cast(pEntity); - if (pSatchel->m_bIsLive && pSatchel->GetThrower() && pSatchel->GetThrower() == GetOwner()) - { - return true; - } - } -#endif - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::StartSatchelDetonate() -{ - - if ( GetActivity() != ACT_SLAM_DETONATOR_IDLE && GetActivity() != ACT_SLAM_THROW_IDLE ) - return; - - // ----------------------------------------- - // Play detonate animation - // ----------------------------------------- - if (m_bNeedReload) - { - SendWeaponAnim(ACT_SLAM_DETONATOR_DETONATE); - } - else if (m_tSlamState == SLAM_SATCHEL_ATTACH) - { - SendWeaponAnim(ACT_SLAM_STICKWALL_DETONATE); - } - else if (m_tSlamState == SLAM_SATCHEL_THROW) - { - SendWeaponAnim(ACT_SLAM_THROW_DETONATE); - } - else - { - return; - } - SatchelDetonate(); - - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::TripmineAttach( void ) -{ - CHL2MP_Player *pOwner = ToHL2MPPlayer( GetOwner() ); - if (!pOwner) - { - return; - } - - m_bAttachTripmine = false; - - Vector vecSrc, vecAiming; - - // Take the eye position and direction - vecSrc = pOwner->EyePosition(); - - QAngle angles = pOwner->GetLocalAngles(); - - AngleVectors( angles, &vecAiming ); - - trace_t tr; - - UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); - - if (tr.fraction < 1.0) - { - CBaseEntity *pEntity = tr.m_pEnt; - if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR)) - { - -#ifndef CLIENT_DLL - QAngle angles; - VectorAngles(tr.plane.normal, angles); - - angles.x += 90; - - CBaseEntity *pEnt = CBaseEntity::Create( "npc_tripmine", tr.endpos + tr.plane.normal * 3, angles, NULL ); - - CTripmineGrenade *pMine = (CTripmineGrenade *)pEnt; - pMine->m_hOwner = GetOwner(); - -#endif - - pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::StartTripmineAttach( void ) -{ - // Only the player fires this way so we can cast - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - if (!pPlayer) - { - return; - } - - Vector vecSrc, vecAiming; - - // Take the eye position and direction - vecSrc = pPlayer->EyePosition(); - - QAngle angles = pPlayer->GetLocalAngles(); - - AngleVectors( angles, &vecAiming ); - - trace_t tr; - - UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pPlayer, COLLISION_GROUP_NONE, &tr ); - - if (tr.fraction < 1.0) - { - // ALERT( at_console, "hit %f\n", tr.flFraction ); - - CBaseEntity *pEntity = tr.m_pEnt; - if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR)) - { - // player "shoot" animation - pPlayer->SetAnimation( PLAYER_ATTACK1 ); - - // ----------------------------------------- - // Play attach animation - // ----------------------------------------- - - if (m_bDetonatorArmed) - { - SendWeaponAnim(ACT_SLAM_STICKWALL_ATTACH); - } - else - { - SendWeaponAnim(ACT_SLAM_TRIPMINE_ATTACH); - } - - m_bNeedReload = true; - m_bAttachTripmine = true; - m_bNeedDetonatorDraw = m_bDetonatorArmed; - } - else - { - // ALERT( at_console, "no deploy\n" ); - } - } - - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration(); -// SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::SatchelThrow( void ) -{ -#ifndef CLIENT_DLL - m_bThrowSatchel = false; - - // Only the player fires this way so we can cast - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - Vector vecSrc = pPlayer->WorldSpaceCenter(); - Vector vecFacing = pPlayer->BodyDirection3D( ); - vecSrc = vecSrc + vecFacing * 18.0; - // BUGBUG: is this because vecSrc is not from Weapon_ShootPosition()??? - vecSrc.z += 24.0f; - - Vector vecThrow; - GetOwner()->GetVelocity( &vecThrow, NULL ); - vecThrow += vecFacing * 500; - - // Player may have turned to face a wall during the throw anim in which case - // we don't want to throw the SLAM into the wall - if (CanAttachSLAM()) - { - vecThrow = vecFacing; - vecSrc = pPlayer->WorldSpaceCenter() + vecFacing * 5.0; - } - - CSatchelCharge *pSatchel = (CSatchelCharge*)Create( "npc_satchel", vecSrc, vec3_angle, GetOwner() ); - - if ( pSatchel ) - { - pSatchel->SetThrower( GetOwner() ); - pSatchel->ApplyAbsVelocityImpulse( vecThrow ); - pSatchel->SetLocalAngularVelocity( QAngle( 0, 400, 0 ) ); - pSatchel->m_bIsLive = true; - pSatchel->m_pMyWeaponSLAM = this; - } - - pPlayer->RemoveAmmo( 1, m_iSecondaryAmmoType ); - pPlayer->SetAnimation( PLAYER_ATTACK1 ); - -#endif - - // Play throw sound - EmitSound( "Weapon_SLAM.SatchelThrow" ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::StartSatchelThrow( void ) -{ - // ----------------------------------------- - // Play throw animation - // ----------------------------------------- - if (m_bDetonatorArmed) - { - SendWeaponAnim(ACT_SLAM_THROW_THROW); - } - else - { - SendWeaponAnim(ACT_SLAM_THROW_THROW_ND); - if (!m_bDetonatorArmed) - { - m_bDetonatorArmed = true; - m_bNeedDetonatorDraw = true; - } - } - - m_bNeedReload = true; - m_bThrowSatchel = true; - - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::SatchelAttach( void ) -{ -#ifndef CLIENT_DLL - CBaseCombatCharacter *pOwner = GetOwner(); - if (!pOwner) - { - return; - } - - m_bAttachSatchel = false; - - Vector vecSrc = pOwner->Weapon_ShootPosition( ); - Vector vecAiming = pOwner->BodyDirection2D( ); - - trace_t tr; - - UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); - - if (tr.fraction < 1.0) - { - CBaseEntity *pEntity = tr.m_pEnt; - if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR)) - { - QAngle angles; - VectorAngles(tr.plane.normal, angles); - angles.y -= 90; - angles.z -= 90; - tr.endpos.z -= 6.0f; - - CSatchelCharge *pSatchel = (CSatchelCharge*)CBaseEntity::Create( "npc_satchel", tr.endpos + tr.plane.normal * 3, angles, NULL ); - pSatchel->SetMoveType( MOVETYPE_FLY ); // no gravity - pSatchel->m_bIsAttached = true; - pSatchel->m_bIsLive = true; - pSatchel->SetThrower( GetOwner() ); - pSatchel->SetOwnerEntity( ((CBaseEntity*)GetOwner()) ); - pSatchel->m_pMyWeaponSLAM = this; - - pOwner->RemoveAmmo( 1, m_iSecondaryAmmoType ); - } - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::StartSatchelAttach( void ) -{ -#ifndef CLIENT_DLL - CBaseCombatCharacter *pOwner = GetOwner(); - if (!pOwner) - { - return; - } - - Vector vecSrc = pOwner->Weapon_ShootPosition( ); - Vector vecAiming = pOwner->BodyDirection2D( ); - - trace_t tr; - - UTIL_TraceLine( vecSrc, vecSrc + (vecAiming * 128), MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); - - if (tr.fraction < 1.0) - { - CBaseEntity *pEntity = tr.m_pEnt; - if (pEntity && !(pEntity->GetFlags() & FL_CONVEYOR)) - { - // Only the player fires this way so we can cast - CBasePlayer *pPlayer = ToBasePlayer( pOwner ); - - // player "shoot" animation - pPlayer->SetAnimation( PLAYER_ATTACK1 ); - - // ----------------------------------------- - // Play attach animation - // ----------------------------------------- - if (m_bDetonatorArmed) - { - SendWeaponAnim(ACT_SLAM_STICKWALL_ATTACH); - } - else - { - SendWeaponAnim(ACT_SLAM_STICKWALL_ND_ATTACH); - if (!m_bDetonatorArmed) - { - m_bDetonatorArmed = true; - m_bNeedDetonatorDraw = true; - } - } - - m_bNeedReload = true; - m_bAttachSatchel = true; - - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - } - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::SetSlamState( int newState ) -{ - // Set set and set idle time so animation gets updated with state change - m_tSlamState = newState; - SetWeaponIdleTime( gpGlobals->curtime ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::SLAMThink( void ) -{ - if ( m_flWallSwitchTime > gpGlobals->curtime ) - return; - - - // If not in tripmine mode we need to check to see if we are close to - // a wall. If we are we go into satchel_attach mode - CBaseCombatCharacter *pOwner = GetOwner(); - - if ( (pOwner && pOwner->GetAmmoCount(m_iSecondaryAmmoType) > 0)) - { - if (CanAttachSLAM()) - { - if (m_tSlamState == SLAM_SATCHEL_THROW) - { - SetSlamState(SLAM_TRIPMINE_READY); - int iAnim = m_bDetonatorArmed ? ACT_SLAM_THROW_TO_STICKWALL : ACT_SLAM_THROW_TO_TRIPMINE_ND; - SendWeaponAnim( iAnim ); - m_flWallSwitchTime = gpGlobals->curtime + SequenceDuration(); - m_bNeedReload = false; - } - } - else - { - if (m_tSlamState == SLAM_TRIPMINE_READY) - { - SetSlamState(SLAM_SATCHEL_THROW); - int iAnim = m_bDetonatorArmed ? ACT_SLAM_STICKWALL_TO_THROW : ACT_SLAM_TRIPMINE_TO_THROW_ND; - SendWeaponAnim( iAnim ); - m_flWallSwitchTime = gpGlobals->curtime + SequenceDuration(); - m_bNeedReload = false; - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -bool CWeapon_SLAM::CanAttachSLAM( void ) -{ - CHL2MP_Player *pOwner = ToHL2MPPlayer( GetOwner() ); - - if (!pOwner) - { - return false; - } - - Vector vecSrc, vecAiming; - - // Take the eye position and direction - vecSrc = pOwner->EyePosition(); - - QAngle angles = pOwner->GetLocalAngles(); - - AngleVectors( angles, &vecAiming ); - - trace_t tr; - - Vector vecEnd = vecSrc + (vecAiming * 42); - UTIL_TraceLine( vecSrc, vecEnd, MASK_SOLID, pOwner, COLLISION_GROUP_NONE, &tr ); - - if (tr.fraction < 1.0) - { - // Don't attach to a living creature - if (tr.m_pEnt) - { - CBaseEntity *pEntity = tr.m_pEnt; - CBaseCombatCharacter *pBCC = ToBaseCombatCharacter( pEntity ); - if (pBCC) - { - return false; - } - } - return true; - } - else - { - return false; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Override so SLAM to so secondary attack when no secondary ammo -// but satchel is in the world -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::ItemPostFrame( void ) -{ - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - if (!pOwner) - { - return; - } - - SLAMThink(); - - if ((pOwner->m_nButtons & IN_ATTACK2) && (m_flNextSecondaryAttack <= gpGlobals->curtime)) - { - SecondaryAttack(); - } - else if (!m_bNeedReload && (pOwner->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime)) - { - PrimaryAttack(); - } - - // ----------------------- - // No buttons down - // ----------------------- - else - { - WeaponIdle( ); - return; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Switch to next best weapon -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::Weapon_Switch( void ) -{ - // Note that we may pick the SLAM again, when we switch - // weapons, in which case we have to save and restore the - // detonator armed state. - // The SLAMs may be about to blow up, but haven't done so yet - // and the deploy function will find the undetonated charges - // and we are armed - bool saveState = m_bDetonatorArmed; - CBaseCombatCharacter *pOwner = GetOwner(); - pOwner->SwitchToNextBestWeapon( pOwner->GetActiveWeapon() ); - if (pOwner->GetActiveWeapon() == this) - { - m_bDetonatorArmed = saveState; - } - -#ifndef CLIENT_DLL - // If not armed and have no ammo - if (!m_bDetonatorArmed && pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0) - { - pOwner->ClearActiveWeapon(); - } -#endif - -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -void CWeapon_SLAM::WeaponIdle( void ) -{ - // Ready to switch animations? - if ( HasWeaponIdleTimeElapsed() ) - { - // Don't allow throw to attach switch unless in idle - if (m_bClearReload) - { - m_bNeedReload = false; - m_bClearReload = false; - } - CBaseCombatCharacter *pOwner = GetOwner(); - if (!pOwner) - { - return; - } - - int iAnim = 0; - - if (m_bThrowSatchel) - { - SatchelThrow(); - if (m_bDetonatorArmed && !m_bNeedDetonatorDraw) - { - iAnim = ACT_SLAM_THROW_THROW2; - } - else - { - iAnim = ACT_SLAM_THROW_THROW_ND2; - } - } - else if (m_bAttachSatchel) - { - SatchelAttach(); - if (m_bDetonatorArmed && !m_bNeedDetonatorDraw) - { - iAnim = ACT_SLAM_STICKWALL_ATTACH2; - } - else - { - iAnim = ACT_SLAM_STICKWALL_ND_ATTACH2; - } - } - else if (m_bAttachTripmine) - { - TripmineAttach(); - iAnim = m_bNeedDetonatorDraw ? ACT_SLAM_STICKWALL_ATTACH2 : ACT_SLAM_TRIPMINE_ATTACH2; - } - else if ( m_bNeedReload ) - { - // If owner had ammo draw the correct SLAM type - if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) > 0) - { - switch( m_tSlamState) - { - case SLAM_TRIPMINE_READY: - { - iAnim = m_bNeedDetonatorDraw ? ACT_SLAM_STICKWALL_DRAW : ACT_SLAM_TRIPMINE_DRAW; - } - break; - case SLAM_SATCHEL_ATTACH: - { - if (m_bNeedDetonatorHolster) - { - iAnim = ACT_SLAM_STICKWALL_DETONATOR_HOLSTER; - m_bNeedDetonatorHolster = false; - } - else if (m_bDetonatorArmed) - { - iAnim = m_bNeedDetonatorDraw ? ACT_SLAM_DETONATOR_STICKWALL_DRAW : ACT_SLAM_STICKWALL_DRAW; - m_bNeedDetonatorDraw = false; - } - else - { - iAnim = ACT_SLAM_STICKWALL_ND_DRAW; - } - } - break; - case SLAM_SATCHEL_THROW: - { - if (m_bNeedDetonatorHolster) - { - iAnim = ACT_SLAM_THROW_DETONATOR_HOLSTER; - m_bNeedDetonatorHolster = false; - } - else if (m_bDetonatorArmed) - { - iAnim = m_bNeedDetonatorDraw ? ACT_SLAM_DETONATOR_THROW_DRAW : ACT_SLAM_THROW_DRAW; - m_bNeedDetonatorDraw = false; - } - else - { - iAnim = ACT_SLAM_THROW_ND_DRAW; - } - } - break; - } - m_bClearReload = true; - } - // If no ammo and armed, idle with only the detonator - else if (m_bDetonatorArmed) - { - iAnim = m_bNeedDetonatorDraw ? ACT_SLAM_DETONATOR_DRAW : ACT_SLAM_DETONATOR_IDLE; - m_bNeedDetonatorDraw = false; - } - else - { -#ifndef CLIENT_DLL - pOwner->Weapon_Drop( this ); - UTIL_Remove(this); -#endif - } - } - else if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0) - { -#ifndef CLIENT_DLL - pOwner->Weapon_Drop( this ); - UTIL_Remove(this); -#endif - } - - // If I don't need to reload just do the appropriate idle - else - { - switch( m_tSlamState) - { - case SLAM_TRIPMINE_READY: - { - iAnim = m_bDetonatorArmed ? ACT_SLAM_STICKWALL_IDLE : ACT_SLAM_TRIPMINE_IDLE; - m_flWallSwitchTime = 0; - } - break; - case SLAM_SATCHEL_THROW: - { - if (m_bNeedDetonatorHolster) - { - iAnim = ACT_SLAM_THROW_DETONATOR_HOLSTER; - m_bNeedDetonatorHolster = false; - } - else - { - iAnim = m_bDetonatorArmed ? ACT_SLAM_THROW_IDLE : ACT_SLAM_THROW_ND_IDLE; - m_flWallSwitchTime = 0; - } - } - break; - case SLAM_SATCHEL_ATTACH: - { - if (m_bNeedDetonatorHolster) - { - iAnim = ACT_SLAM_STICKWALL_DETONATOR_HOLSTER; - m_bNeedDetonatorHolster = false; - } - else - { - iAnim = m_bDetonatorArmed ? ACT_SLAM_STICKWALL_IDLE : ACT_SLAM_TRIPMINE_IDLE; - m_flWallSwitchTime = 0; - } - } - break; - } - } - SendWeaponAnim( iAnim ); - } -} - -bool CWeapon_SLAM::Deploy( void ) -{ - CBaseCombatCharacter *pOwner = GetOwner(); - if (!pOwner) - { - return false; - } - - m_bDetonatorArmed = AnyUndetonatedCharges(); - - - SetModel( GetViewModel() ); - - m_tSlamState = (int)SLAM_SATCHEL_THROW; - - // ------------------------------ - // Pick the right draw animation - // ------------------------------ - int iActivity; - - // If detonator is already armed - m_bNeedReload = false; - if (m_bDetonatorArmed) - { - if (pOwner->GetAmmoCount(m_iSecondaryAmmoType) <= 0) - { - iActivity = ACT_SLAM_DETONATOR_DRAW; - m_bNeedReload = true; - } - else if (CanAttachSLAM()) - { - iActivity = ACT_SLAM_DETONATOR_STICKWALL_DRAW; - SetSlamState(SLAM_TRIPMINE_READY); - } - else - { - iActivity = ACT_SLAM_DETONATOR_THROW_DRAW; - SetSlamState(SLAM_SATCHEL_THROW); - } - } - else - { - if (CanAttachSLAM()) - { - iActivity = ACT_SLAM_TRIPMINE_DRAW; - SetSlamState(SLAM_TRIPMINE_READY); - } - else - { - iActivity = ACT_SLAM_THROW_ND_DRAW; - SetSlamState(SLAM_SATCHEL_THROW); - } - } - - return DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), iActivity, (char*)GetAnimPrefix() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Constructor -// Input : -// Output : -//----------------------------------------------------------------------------- -CWeapon_SLAM::CWeapon_SLAM(void) -{ - m_tSlamState = (int)SLAM_SATCHEL_THROW; - m_bDetonatorArmed = false; - m_bNeedReload = true; - m_bClearReload = false; - m_bThrowSatchel = false; - m_bAttachSatchel = false; - m_bAttachTripmine = false; - m_bNeedDetonatorDraw = false; - m_bNeedDetonatorHolster = false; -} diff --git a/game/shared/hl2mp/weapon_slam.h b/game/shared/hl2mp/weapon_slam.h deleted file mode 100644 index 3f47c6391..000000000 --- a/game/shared/hl2mp/weapon_slam.h +++ /dev/null @@ -1,91 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: SLAM -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef WEAPONSLAM_H -#define WEAPONSLAM_H - -#include "basegrenade_shared.h" -#include "weapon_hl2mpbasehlmpcombatweapon.h" - -enum -{ - SLAM_TRIPMINE_READY, - SLAM_SATCHEL_THROW, - SLAM_SATCHEL_ATTACH, -}; - -#ifdef CLIENT_DLL -#define CWeapon_SLAM C_Weapon_SLAM -#endif - -class CWeapon_SLAM : public CBaseHL2MPCombatWeapon -{ -public: - DECLARE_CLASS( CWeapon_SLAM, CBaseHL2MPCombatWeapon ); - - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - - CNetworkVar( int, m_tSlamState ); - CNetworkVar( bool, m_bDetonatorArmed ); - CNetworkVar( bool, m_bNeedDetonatorDraw); - CNetworkVar( bool, m_bNeedDetonatorHolster); - CNetworkVar( bool, m_bNeedReload); - CNetworkVar( bool, m_bClearReload); - CNetworkVar( bool, m_bThrowSatchel); - CNetworkVar( bool, m_bAttachSatchel); - CNetworkVar( bool, m_bAttachTripmine); - float m_flWallSwitchTime; - - void Spawn( void ); - void Precache( void ); - - void PrimaryAttack( void ); - void SecondaryAttack( void ); - void WeaponIdle( void ); - void Weapon_Switch( void ); - void SLAMThink( void ); - - void SetPickupTouch( void ); - void SlamTouch( CBaseEntity *pOther ); // default weapon touch - void ItemPostFrame( void ); - bool Reload( void ); - void SetSlamState( int newState ); - bool CanAttachSLAM(void); // In position where can attach SLAM? - bool AnyUndetonatedCharges(void); - void StartTripmineAttach( void ); - void TripmineAttach( void ); - - void StartSatchelDetonate( void ); - void SatchelDetonate( void ); - void StartSatchelThrow( void ); - void StartSatchelAttach( void ); - void SatchelThrow( void ); - void SatchelAttach( void ); - bool Deploy( void ); - bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); - - - CWeapon_SLAM(); - -#ifndef CLIENT_DLL - DECLARE_ACTTABLE(); - DECLARE_DATADESC(); -#endif - -private: - CWeapon_SLAM( const CWeapon_SLAM & ); -}; - - -#endif //WEAPONSLAM_H diff --git a/game/shared/hl2mp/weapon_smg1.cpp b/game/shared/hl2mp/weapon_smg1.cpp deleted file mode 100644 index 0d21cc409..000000000 --- a/game/shared/hl2mp/weapon_smg1.cpp +++ /dev/null @@ -1,264 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" -#include "in_buttons.h" - -#ifdef CLIENT_DLL - #include "c_hl2mp_player.h" -#else - #include "grenade_ar2.h" - #include "hl2mp_player.h" - #include "basegrenade_shared.h" -#endif - -#include "weapon_hl2mpbase.h" -#include "weapon_hl2mpbase_machinegun.h" - -#ifdef CLIENT_DLL -#define CWeaponSMG1 C_WeaponSMG1 -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define SMG1_GRENADE_DAMAGE 100.0f -#define SMG1_GRENADE_RADIUS 250.0f - -class CWeaponSMG1 : public CHL2MPMachineGun -{ -public: - DECLARE_CLASS( CWeaponSMG1, CHL2MPMachineGun ); - - CWeaponSMG1(); - - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - - - void Precache( void ); - void AddViewKick( void ); - void SecondaryAttack( void ); - - int GetMinBurst() { return 2; } - int GetMaxBurst() { return 5; } - - virtual void Equip( CBaseCombatCharacter *pOwner ); - bool Reload( void ); - - float GetFireRate( void ) { return 0.075f; } // 13.3hz - Activity GetPrimaryAttackActivity( void ); - - virtual const Vector& GetBulletSpread( void ) - { - static const Vector cone = VECTOR_CONE_5DEGREES; - return cone; - } - - const WeaponProficiencyInfo_t *GetProficiencyValues(); - -#ifndef CLIENT_DLL - DECLARE_ACTTABLE(); -#endif - -protected: - - Vector m_vecTossVelocity; - float m_flNextGrenadeCheck; - -private: - CWeaponSMG1( const CWeaponSMG1 & ); -}; - -IMPLEMENT_NETWORKCLASS_ALIASED( WeaponSMG1, DT_WeaponSMG1 ) - -BEGIN_NETWORK_TABLE( CWeaponSMG1, DT_WeaponSMG1 ) -END_NETWORK_TABLE() - -BEGIN_PREDICTION_DATA( CWeaponSMG1 ) -END_PREDICTION_DATA() - -LINK_ENTITY_TO_CLASS( weapon_smg1, CWeaponSMG1 ); -PRECACHE_WEAPON_REGISTER(weapon_smg1); - -#ifndef CLIENT_DLL -acttable_t CWeaponSMG1::m_acttable[] = -{ - { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_SMG1, false }, - { ACT_HL2MP_RUN, ACT_HL2MP_RUN_SMG1, false }, - { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_SMG1, false }, - { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_SMG1, false }, - { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_SMG1, false }, - { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_SMG1, false }, - { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_SMG1, false }, - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SMG1, false }, -}; - -IMPLEMENT_ACTTABLE(CWeaponSMG1); -#endif - -//========================================================= -CWeaponSMG1::CWeaponSMG1( ) -{ - m_fMinRange1 = 0;// No minimum range. - m_fMaxRange1 = 1400; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponSMG1::Precache( void ) -{ -#ifndef CLIENT_DLL - UTIL_PrecacheOther("grenade_ar2"); -#endif - - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: Give this weapon longer range when wielded by an ally NPC. -//----------------------------------------------------------------------------- -void CWeaponSMG1::Equip( CBaseCombatCharacter *pOwner ) -{ - m_fMaxRange1 = 1400; - - BaseClass::Equip( pOwner ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Activity -//----------------------------------------------------------------------------- -Activity CWeaponSMG1::GetPrimaryAttackActivity( void ) -{ - if ( m_nShotsFired < 2 ) - return ACT_VM_PRIMARYATTACK; - - if ( m_nShotsFired < 3 ) - return ACT_VM_RECOIL1; - - if ( m_nShotsFired < 4 ) - return ACT_VM_RECOIL2; - - return ACT_VM_RECOIL3; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CWeaponSMG1::Reload( void ) -{ - bool fRet; - float fCacheTime = m_flNextSecondaryAttack; - - fRet = DefaultReload( GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD ); - if ( fRet ) - { - // Undo whatever the reload process has done to our secondary - // attack timer. We allow you to interrupt reloading to fire - // a grenade. - m_flNextSecondaryAttack = GetOwner()->m_flNextAttack = fCacheTime; - - WeaponSound( RELOAD ); - } - - return fRet; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponSMG1::AddViewKick( void ) -{ - #define EASY_DAMPEN 0.5f - #define MAX_VERTICAL_KICK 1.0f //Degrees - #define SLIDE_LIMIT 2.0f //Seconds - - //Get the view kick - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if ( pPlayer == NULL ) - return; - - DoMachineGunKick( pPlayer, EASY_DAMPEN, MAX_VERTICAL_KICK, m_fFireDuration, SLIDE_LIMIT ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponSMG1::SecondaryAttack( void ) -{ - // Only the player fires this way so we can cast - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - - if ( pPlayer == NULL ) - return; - - //Must have ammo - if ( ( pPlayer->GetAmmoCount( m_iSecondaryAmmoType ) <= 0 ) || ( pPlayer->GetWaterLevel() == 3 ) ) - { - SendWeaponAnim( ACT_VM_DRYFIRE ); - BaseClass::WeaponSound( EMPTY ); - m_flNextSecondaryAttack = gpGlobals->curtime + 0.5f; - return; - } - - if( m_bInReload ) - m_bInReload = false; - - // MUST call sound before removing a round from the clip of a CMachineGun - BaseClass::WeaponSound( WPN_DOUBLE ); - - Vector vecSrc = pPlayer->Weapon_ShootPosition(); - Vector vecThrow; - // Don't autoaim on grenade tosses - AngleVectors( pPlayer->EyeAngles() + pPlayer->GetPunchAngle(), &vecThrow ); - VectorScale( vecThrow, 1000.0f, vecThrow ); - -#ifndef CLIENT_DLL - //Create the grenade - CGrenadeAR2 *pGrenade = (CGrenadeAR2*)Create( "grenade_ar2", vecSrc, vec3_angle, pPlayer ); - pGrenade->SetAbsVelocity( vecThrow ); - - pGrenade->SetLocalAngularVelocity( RandomAngle( -400, 400 ) ); - pGrenade->SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE ); - pGrenade->SetThrower( GetOwner() ); - pGrenade->SetDamage( SMG1_GRENADE_DAMAGE ); - pGrenade->SetDamageRadius( SMG1_GRENADE_RADIUS ); -#endif - - SendWeaponAnim( ACT_VM_SECONDARYATTACK ); - - // player "shoot" animation - pPlayer->SetAnimation( PLAYER_ATTACK1 ); - - // Decrease ammo - pPlayer->RemoveAmmo( 1, m_iSecondaryAmmoType ); - - // Can shoot again immediately - m_flNextPrimaryAttack = gpGlobals->curtime + 0.5f; - - // Can blow up after a short delay (so have time to release mouse button) - m_flNextSecondaryAttack = gpGlobals->curtime + 1.0f; -} - -//----------------------------------------------------------------------------- -const WeaponProficiencyInfo_t *CWeaponSMG1::GetProficiencyValues() -{ - static WeaponProficiencyInfo_t proficiencyTable[] = - { - { 7.0, 0.75 }, - { 5.00, 0.75 }, - { 10.0/3.0, 0.75 }, - { 5.0/3.0, 0.75 }, - { 1.00, 1.0 }, - }; - - COMPILE_TIME_ASSERT( ARRAYSIZE(proficiencyTable) == WEAPON_PROFICIENCY_PERFECT + 1); - - return proficiencyTable; -} diff --git a/game/shared/hl2mp/weapon_stunstick.cpp b/game/shared/hl2mp/weapon_stunstick.cpp deleted file mode 100644 index f8cf97e71..000000000 --- a/game/shared/hl2mp/weapon_stunstick.cpp +++ /dev/null @@ -1,899 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Stun Stick- beating stick with a zappy end -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "npcevent.h" -#include "weapon_hl2mpbasebasebludgeon.h" -#include "IEffects.h" -#include "debugoverlay_shared.h" - -#ifndef CLIENT_DLL - #include "npc_metropolice.h" - #include "te_effect_dispatch.h" -#endif - -#ifdef CLIENT_DLL - - #include "iviewrender_beams.h" - #include "beam_shared.h" - #include "materialsystem/IMaterial.h" - #include "model_types.h" - #include "c_te_effect_dispatch.h" - #include "fx_quad.h" - #include "fx.h" - - extern void DrawHalo( IMaterial* pMaterial, const Vector &source, float scale, float const *color, float flHDRColorScale ); - extern void FormatViewModelAttachment( Vector &vOrigin, bool bInverse ); - -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern ConVar metropolice_move_and_melee; - -#define STUNSTICK_RANGE 75.0f -#define STUNSTICK_REFIRE 0.8f -#define STUNSTICK_BEAM_MATERIAL "sprites/lgtning.vmt" -#define STUNSTICK_GLOW_MATERIAL "sprites/light_glow02_add" -#define STUNSTICK_GLOW_MATERIAL2 "effects/blueflare1" -#define STUNSTICK_GLOW_MATERIAL_NOZ "sprites/light_glow02_add_noz" - -#ifdef CLIENT_DLL -#define CWeaponStunStick C_WeaponStunStick -#endif - -class CWeaponStunStick : public CBaseHL2MPBludgeonWeapon -{ - DECLARE_CLASS( CWeaponStunStick, CBaseHL2MPBludgeonWeapon ); - -public: - - CWeaponStunStick(); - - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - -#ifndef CLIENT_DLL - DECLARE_ACTTABLE(); -#endif - -#ifdef CLIENT_DLL - virtual int DrawModel( int flags ); - virtual void ClientThink( void ); - virtual void OnDataChanged( DataUpdateType_t updateType ); - virtual RenderGroup_t GetRenderGroup( void ); - virtual void ViewModelDrawn( C_BaseViewModel *pBaseViewModel ); - -#endif - - virtual void Precache(); - - void Spawn(); - - float GetRange( void ) { return STUNSTICK_RANGE; } - float GetFireRate( void ) { return STUNSTICK_REFIRE; } - - - bool Deploy( void ); - bool Holster( CBaseCombatWeapon *pSwitchingTo = NULL ); - - void Drop( const Vector &vecVelocity ); - void ImpactEffect( trace_t &traceHit ); - void SecondaryAttack( void ) {} - void SetStunState( bool state ); - bool GetStunState( void ); - -#ifndef CLIENT_DLL - void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ); - int WeaponMeleeAttack1Condition( float flDot, float flDist ); -#endif - - float GetDamageForActivity( Activity hitActivity ); - - CWeaponStunStick( const CWeaponStunStick & ); - -private: - -#ifdef CLIENT_DLL - - #define NUM_BEAM_ATTACHMENTS 9 - - struct stunstickBeamInfo_t - { - int IDs[2]; // 0 - top, 1 - bottom - }; - - stunstickBeamInfo_t m_BeamAttachments[NUM_BEAM_ATTACHMENTS]; // Lookup for arc attachment points on the head of the stick - int m_BeamCenterAttachment; // "Core" of the effect (center of the head) - - void SetupAttachmentPoints( void ); - void DrawFirstPersonEffects( void ); - void DrawThirdPersonEffects( void ); - void DrawEffects( void ); - bool InSwing( void ); - - bool m_bSwungLastFrame; - - #define FADE_DURATION 0.25f - - float m_flFadeTime; - -#endif - - CNetworkVar( bool, m_bActive ); -}; - -//----------------------------------------------------------------------------- -// CWeaponStunStick -//----------------------------------------------------------------------------- -IMPLEMENT_NETWORKCLASS_ALIASED( WeaponStunStick, DT_WeaponStunStick ) - -BEGIN_NETWORK_TABLE( CWeaponStunStick, DT_WeaponStunStick ) -#ifdef CLIENT_DLL - RecvPropInt( RECVINFO( m_bActive ) ), -#else - SendPropInt( SENDINFO( m_bActive ), 1, SPROP_UNSIGNED ), -#endif - -END_NETWORK_TABLE() - -BEGIN_PREDICTION_DATA( CWeaponStunStick ) -END_PREDICTION_DATA() - -LINK_ENTITY_TO_CLASS( weapon_stunstick, CWeaponStunStick ); -PRECACHE_WEAPON_REGISTER( weapon_stunstick ); - - -#ifndef CLIENT_DLL - -acttable_t CWeaponStunStick::m_acttable[] = -{ - { ACT_RANGE_ATTACK1, ACT_RANGE_ATTACK_SLAM, true }, - { ACT_HL2MP_IDLE, ACT_HL2MP_IDLE_MELEE, false }, - { ACT_HL2MP_RUN, ACT_HL2MP_RUN_MELEE, false }, - { ACT_HL2MP_IDLE_CROUCH, ACT_HL2MP_IDLE_CROUCH_MELEE, false }, - { ACT_HL2MP_WALK_CROUCH, ACT_HL2MP_WALK_CROUCH_MELEE, false }, - { ACT_HL2MP_GESTURE_RANGE_ATTACK, ACT_HL2MP_GESTURE_RANGE_ATTACK_MELEE, false }, - { ACT_HL2MP_GESTURE_RELOAD, ACT_HL2MP_GESTURE_RELOAD_MELEE, false }, - { ACT_HL2MP_JUMP, ACT_HL2MP_JUMP_MELEE, false }, -}; - -IMPLEMENT_ACTTABLE(CWeaponStunStick); - -#endif - - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -CWeaponStunStick::CWeaponStunStick( void ) -{ - // HACK: Don't call SetStunState because this tried to Emit a sound before - // any players are connected which is a bug - m_bActive = false; - -#ifdef CLIENT_DLL - m_bSwungLastFrame = false; - m_flFadeTime = FADE_DURATION; // Start off past the fade point -#endif -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CWeaponStunStick::Spawn() -{ - Precache(); - - BaseClass::Spawn(); - AddSolidFlags( FSOLID_NOT_STANDABLE ); -} - -void CWeaponStunStick::Precache() -{ - BaseClass::Precache(); - - PrecacheScriptSound( "Weapon_StunStick.Activate" ); - PrecacheScriptSound( "Weapon_StunStick.Deactivate" ); - - PrecacheModel( STUNSTICK_BEAM_MATERIAL ); -} - -//----------------------------------------------------------------------------- -// Purpose: Get the damage amount for the animation we're doing -// Input : hitActivity - currently played activity -// Output : Damage amount -//----------------------------------------------------------------------------- -float CWeaponStunStick::GetDamageForActivity( Activity hitActivity ) -{ - return 40.0f; -} - -//----------------------------------------------------------------------------- -// Attempt to lead the target (needed because citizens can't hit manhacks with the crowbar!) -//----------------------------------------------------------------------------- -extern ConVar sk_crowbar_lead_time; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CWeaponStunStick::ImpactEffect( trace_t &traceHit ) -{ - -//#ifndef CLIENT_DLL - - CEffectData data; - - data.m_vNormal = traceHit.plane.normal; - data.m_vOrigin = traceHit.endpos + ( data.m_vNormal * 4.0f ); - - DispatchEffect( "StunstickImpact", data ); - -//#endif - - //FIXME: need new decals - UTIL_ImpactTrace( &traceHit, DMG_CLUB ); -} - -#ifndef CLIENT_DLL - - -int CWeaponStunStick::WeaponMeleeAttack1Condition( float flDot, float flDist ) -{ - // Attempt to lead the target (needed because citizens can't hit manhacks with the crowbar!) - CAI_BaseNPC *pNPC = GetOwner()->MyNPCPointer(); - CBaseEntity *pEnemy = pNPC->GetEnemy(); - if (!pEnemy) - return COND_NONE; - - Vector vecVelocity; - AngularImpulse angVelocity; - pEnemy->GetVelocity( &vecVelocity, &angVelocity ); - - // Project where the enemy will be in a little while, add some randomness so he doesn't always hit - float dt = sk_crowbar_lead_time.GetFloat(); - dt += random->RandomFloat( -0.3f, 0.2f ); - if ( dt < 0.0f ) - dt = 0.0f; - - Vector vecExtrapolatedPos; - VectorMA( pEnemy->WorldSpaceCenter(), dt, vecVelocity, vecExtrapolatedPos ); - - Vector vecDelta; - VectorSubtract( vecExtrapolatedPos, pNPC->WorldSpaceCenter(), vecDelta ); - - if ( fabs( vecDelta.z ) > 70 ) - { - return COND_TOO_FAR_TO_ATTACK; - } - - Vector vecForward = pNPC->BodyDirection2D( ); - vecDelta.z = 0.0f; - float flExtrapolatedDot = DotProduct2D( vecDelta.AsVector2D(), vecForward.AsVector2D() ); - if ((flDot < 0.7) && (flExtrapolatedDot < 0.7)) - { - return COND_NOT_FACING_ATTACK; - } - - float flExtrapolatedDist = Vector2DNormalize( vecDelta.AsVector2D() ); - - if( pEnemy->IsPlayer() ) - { - //Vector vecDir = pEnemy->GetSmoothedVelocity(); - //float flSpeed = VectorNormalize( vecDir ); - - // If player will be in front of me in one-half second, clock his arse. - Vector vecProjectEnemy = pEnemy->GetAbsOrigin() + (pEnemy->GetAbsVelocity() * 0.35); - Vector vecProjectMe = GetAbsOrigin(); - - if( (vecProjectMe - vecProjectEnemy).Length2D() <= 48.0f ) - { - return COND_CAN_MELEE_ATTACK1; - } - } -/* - if( metropolice_move_and_melee.GetBool() ) - { - if( pNPC->IsMoving() ) - { - flTargetDist *= 1.5f; - } - } -*/ - float flTargetDist = 48.0f; - if ((flDist > flTargetDist) && (flExtrapolatedDist > flTargetDist)) - { - return COND_TOO_FAR_TO_ATTACK; - } - - return COND_CAN_MELEE_ATTACK1; -} - - -void CWeaponStunStick::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator ) -{ - switch( pEvent->event ) - { - case EVENT_WEAPON_MELEE_HIT: - { - // Trace up or down based on where the enemy is... - // But only if we're basically facing that direction - Vector vecDirection; - AngleVectors( GetAbsAngles(), &vecDirection ); - - CBaseEntity *pEnemy = pOperator->MyNPCPointer() ? pOperator->MyNPCPointer()->GetEnemy() : NULL; - if ( pEnemy ) - { - Vector vecDelta; - VectorSubtract( pEnemy->WorldSpaceCenter(), pOperator->Weapon_ShootPosition(), vecDelta ); - VectorNormalize( vecDelta ); - - Vector2D vecDelta2D = vecDelta.AsVector2D(); - Vector2DNormalize( vecDelta2D ); - if ( DotProduct2D( vecDelta2D, vecDirection.AsVector2D() ) > 0.8f ) - { - vecDirection = vecDelta; - } - } - - Vector vecEnd; - VectorMA( pOperator->Weapon_ShootPosition(), 32, vecDirection, vecEnd ); - // Stretch the swing box down to catch low level physics objects - CBaseEntity *pHurt = pOperator->CheckTraceHullAttack( pOperator->Weapon_ShootPosition(), vecEnd, - Vector(-16,-16,-40), Vector(16,16,16), (int)GetDamageForActivity( GetActivity() ), DMG_CLUB, 0.5f, false ); - - // did I hit someone? - if ( pHurt ) - { - // play sound - WeaponSound( MELEE_HIT ); - - CBasePlayer *pPlayer = ToBasePlayer( pHurt ); - - bool bFlashed = false; - - // Punch angles - if ( pPlayer != NULL && !(pPlayer->GetFlags() & FL_GODMODE) ) - { - float yawKick = random->RandomFloat( -48, -24 ); - - //Kick the player angles - pPlayer->ViewPunch( QAngle( -16, yawKick, 2 ) ); - - Vector dir = pHurt->GetAbsOrigin() - GetAbsOrigin(); - - // If the player's on my head, don't knock him up - if ( pPlayer->GetGroundEntity() == pOperator ) - { - dir = vecDirection; - dir.z = 0; - } - - VectorNormalize(dir); - - dir *= 500.0f; - - //If not on ground, then don't make them fly! - if ( !(pPlayer->GetFlags() & FL_ONGROUND ) ) - dir.z = 0.0f; - - //Push the target back - pHurt->ApplyAbsVelocityImpulse( dir ); - - if ( !bFlashed ) - { - color32 red = {128,0,0,128}; - UTIL_ScreenFade( pPlayer, red, 0.5f, 0.1f, FFADE_IN ); - } - - // Force the player to drop anyting they were holding - pPlayer->ForceDropOfCarriedPhysObjects(); - } - - // do effect? - } - else - { - WeaponSound( MELEE_MISS ); - } - } - break; - default: - BaseClass::Operator_HandleAnimEvent( pEvent, pOperator ); - break; - } -} - -#endif - -//----------------------------------------------------------------------------- -// Purpose: Sets the state of the stun stick -//----------------------------------------------------------------------------- -void CWeaponStunStick::SetStunState( bool state ) -{ - m_bActive = state; - - if ( m_bActive ) - { - //FIXME: START - Move to client-side - - Vector vecAttachment; - QAngle vecAttachmentAngles; - - GetAttachment( 1, vecAttachment, vecAttachmentAngles ); - g_pEffects->Sparks( vecAttachment ); - - //FIXME: END - Move to client-side - - EmitSound( "Weapon_StunStick.Activate" ); - } - else - { - EmitSound( "Weapon_StunStick.Deactivate" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponStunStick::Deploy( void ) -{ - SetStunState( true ); - - return BaseClass::Deploy(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CWeaponStunStick::Holster( CBaseCombatWeapon *pSwitchingTo ) -{ - if ( BaseClass::Holster( pSwitchingTo ) == false ) - return false; - - SetStunState( false ); - SetWeaponVisible( false ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &vecVelocity - -//----------------------------------------------------------------------------- -void CWeaponStunStick::Drop( const Vector &vecVelocity ) -{ - SetStunState( false ); - -#ifndef CLIENT_DLL - UTIL_Remove( this ); -#endif - -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CWeaponStunStick::GetStunState( void ) -{ - return m_bActive; -} - -#ifdef CLIENT_DLL - -//----------------------------------------------------------------------------- -// Purpose: Get the attachment point on a viewmodel that a base weapon is using -//----------------------------------------------------------------------------- -bool UTIL_GetWeaponAttachment( C_BaseCombatWeapon *pWeapon, int attachmentID, Vector &absOrigin, QAngle &absAngles ) -{ - // This is already correct in third-person - if ( pWeapon && pWeapon->IsCarriedByLocalPlayer() == false ) - { - return pWeapon->GetAttachment( attachmentID, absOrigin, absAngles ); - } - - // Otherwise we need to translate the attachment to the viewmodel's version and reformat it - CBasePlayer *pOwner = ToBasePlayer( pWeapon->GetOwner() ); - - if ( pOwner != NULL ) - { - int ret = pOwner->GetViewModel()->GetAttachment( attachmentID, absOrigin, absAngles ); - FormatViewModelAttachment( absOrigin, true ); - - return ret; - } - - // Wasn't found - return false; -} - -#define BEAM_ATTACH_CORE_NAME "sparkrear" - -//----------------------------------------------------------------------------- -// Purpose: Sets up the attachment point lookup for the model -//----------------------------------------------------------------------------- -void C_WeaponStunStick::SetupAttachmentPoints( void ) -{ - // Setup points for both types of views - if ( IsCarriedByLocalPlayer() ) - { - const char *szBeamAttachNamesTop[NUM_BEAM_ATTACHMENTS] = - { - "spark1a","spark2a","spark3a","spark4a", - "spark5a","spark6a","spark7a","spark8a", - "spark9a", - }; - - const char *szBeamAttachNamesBottom[NUM_BEAM_ATTACHMENTS] = - { - "spark1b","spark2b","spark3b","spark4b", - "spark5b","spark6b","spark7b","spark8b", - "spark9b", - }; - - // Lookup and store all connections - for ( int i = 0; i < NUM_BEAM_ATTACHMENTS; i++ ) - { - m_BeamAttachments[i].IDs[0] = LookupAttachment( szBeamAttachNamesTop[i] ); - m_BeamAttachments[i].IDs[1] = LookupAttachment( szBeamAttachNamesBottom[i] ); - } - - // Setup the center beam point - m_BeamCenterAttachment = LookupAttachment( BEAM_ATTACH_CORE_NAME ); - } - else - { - // Setup the center beam point - m_BeamCenterAttachment = 1; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draws the stunstick model (with extra effects) -//----------------------------------------------------------------------------- -int C_WeaponStunStick::DrawModel( int flags ) -{ - if ( ShouldDraw() == false ) - return 0; - - // Only render these on the transparent pass - if ( flags & STUDIO_TRANSPARENCY ) - { - DrawEffects(); - return 1; - } - - return BaseClass::DrawModel( flags ); -} - -//----------------------------------------------------------------------------- -// Purpose: Randomly adds extra effects -//----------------------------------------------------------------------------- -void C_WeaponStunStick::ClientThink( void ) -{ - if ( InSwing() == false ) - { - if ( m_bSwungLastFrame ) - { - // Start fading - m_flFadeTime = gpGlobals->curtime; - m_bSwungLastFrame = false; - } - - return; - } - - // Remember if we were swinging last frame - m_bSwungLastFrame = InSwing(); - - if ( IsEffectActive( EF_NODRAW ) ) - return; - - if ( IsCarriedByLocalPlayer() ) - { - // Update our effects - if ( gpGlobals->frametime != 0.0f && ( random->RandomInt( 0, 3 ) == 0 ) ) - { - Vector vecOrigin; - QAngle vecAngles; - - // Inner beams - BeamInfo_t beamInfo; - - int attachment = random->RandomInt( 0, 15 ); - - UTIL_GetWeaponAttachment( this, attachment, vecOrigin, vecAngles ); - ::FormatViewModelAttachment( vecOrigin, false ); - - CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); - CBaseEntity *pBeamEnt = pOwner->GetViewModel(); - - beamInfo.m_vecStart = vec3_origin; - beamInfo.m_pStartEnt= pBeamEnt; - beamInfo.m_nStartAttachment = attachment; - - beamInfo.m_pEndEnt = NULL; - beamInfo.m_nEndAttachment = -1; - beamInfo.m_vecEnd = vecOrigin + RandomVector( -8, 8 ); - - beamInfo.m_pszModelName = STUNSTICK_BEAM_MATERIAL; - beamInfo.m_flHaloScale = 0.0f; - beamInfo.m_flLife = 0.05f; - beamInfo.m_flWidth = random->RandomFloat( 1.0f, 2.0f ); - beamInfo.m_flEndWidth = 0; - beamInfo.m_flFadeLength = 0.0f; - beamInfo.m_flAmplitude = random->RandomFloat( 16, 32 ); - beamInfo.m_flBrightness = 255.0; - beamInfo.m_flSpeed = 0.0; - beamInfo.m_nStartFrame = 0.0; - beamInfo.m_flFrameRate = 1.0f; - beamInfo.m_flRed = 255.0f;; - beamInfo.m_flGreen = 255.0f; - beamInfo.m_flBlue = 255.0f; - beamInfo.m_nSegments = 16; - beamInfo.m_bRenderable = true; - beamInfo.m_nFlags = 0; - - beams->CreateBeamEntPoint( beamInfo ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Starts the client-side version thinking -//----------------------------------------------------------------------------- -void C_WeaponStunStick::OnDataChanged( DataUpdateType_t updateType ) -{ - BaseClass::OnDataChanged( updateType ); - if ( updateType == DATA_UPDATE_CREATED ) - { - SetNextClientThink( CLIENT_THINK_ALWAYS ); - SetupAttachmentPoints(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Tells us we're always a translucent entity -//----------------------------------------------------------------------------- -RenderGroup_t C_WeaponStunStick::GetRenderGroup( void ) -{ - return RENDER_GROUP_TWOPASS; -} - -//----------------------------------------------------------------------------- -// Purpose: Tells us we're always a translucent entity -//----------------------------------------------------------------------------- -bool C_WeaponStunStick::InSwing( void ) -{ - int activity = GetActivity(); - - // FIXME: This is needed until the actual animation works - if ( IsCarriedByLocalPlayer() == false ) - return true; - - // These are the swing activities this weapon can play - if ( activity == GetPrimaryAttackActivity() || - activity == GetSecondaryAttackActivity() || - activity == ACT_VM_MISSCENTER || - activity == ACT_VM_MISSCENTER2 ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Draw our special effects -//----------------------------------------------------------------------------- -void C_WeaponStunStick::DrawThirdPersonEffects( void ) -{ - Vector vecOrigin; - QAngle vecAngles; - float color[3]; - float scale; - - CMatRenderContextPtr pRenderContext( materials ); - IMaterial *pMaterial = materials->FindMaterial( STUNSTICK_GLOW_MATERIAL, NULL, false ); - pRenderContext->Bind( pMaterial ); - - // Get bright when swung - if ( InSwing() ) - { - color[0] = color[1] = color[2] = 0.4f; - scale = 22.0f; - } - else - { - color[0] = color[1] = color[2] = 0.1f; - scale = 20.0f; - } - - // Draw an all encompassing glow around the entire head - UTIL_GetWeaponAttachment( this, m_BeamCenterAttachment, vecOrigin, vecAngles ); - DrawHalo( pMaterial, vecOrigin, scale, color ); - - if ( InSwing() ) - { - pMaterial = materials->FindMaterial( STUNSTICK_GLOW_MATERIAL2, NULL, false ); - pRenderContext->Bind( pMaterial ); - - color[0] = color[1] = color[2] = random->RandomFloat( 0.6f, 0.8f ); - scale = random->RandomFloat( 4.0f, 6.0f ); - - // Draw an all encompassing glow around the entire head - UTIL_GetWeaponAttachment( this, m_BeamCenterAttachment, vecOrigin, vecAngles ); - DrawHalo( pMaterial, vecOrigin, scale, color ); - - // Update our effects - if ( gpGlobals->frametime != 0.0f && ( random->RandomInt( 0, 5 ) == 0 ) ) - { - Vector vecOrigin; - QAngle vecAngles; - - GetAttachment( 1, vecOrigin, vecAngles ); - - Vector vForward; - AngleVectors( vecAngles, &vForward ); - - Vector vEnd = vecOrigin - vForward * 1.0f; - - // Inner beams - BeamInfo_t beamInfo; - - beamInfo.m_vecStart = vEnd; - Vector offset = RandomVector( -12, 8 ); - - offset += Vector(4,4,4); - beamInfo.m_vecEnd = vecOrigin + offset; - - beamInfo.m_pStartEnt= cl_entitylist->GetEnt( BEAMENT_ENTITY( entindex() ) ); - beamInfo.m_pEndEnt = cl_entitylist->GetEnt( BEAMENT_ENTITY( entindex() ) ); - beamInfo.m_nStartAttachment = 1; - beamInfo.m_nEndAttachment = -1; - - beamInfo.m_nType = TE_BEAMTESLA; - beamInfo.m_pszModelName = STUNSTICK_BEAM_MATERIAL; - beamInfo.m_flHaloScale = 0.0f; - beamInfo.m_flLife = 0.01f; - beamInfo.m_flWidth = random->RandomFloat( 1.0f, 3.0f ); - beamInfo.m_flEndWidth = 0; - beamInfo.m_flFadeLength = 0.0f; - beamInfo.m_flAmplitude = random->RandomFloat( 1, 2 ); - beamInfo.m_flBrightness = 255.0; - beamInfo.m_flSpeed = 0.0; - beamInfo.m_nStartFrame = 0.0; - beamInfo.m_flFrameRate = 1.0f; - beamInfo.m_flRed = 255.0f;; - beamInfo.m_flGreen = 255.0f; - beamInfo.m_flBlue = 255.0f; - beamInfo.m_nSegments = 16; - beamInfo.m_bRenderable = true; - beamInfo.m_nFlags = FBEAM_SHADEOUT; - - beams->CreateBeamPoints( beamInfo ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draw our special effects -//----------------------------------------------------------------------------- -void C_WeaponStunStick::DrawFirstPersonEffects( void ) -{ - Vector vecOrigin; - QAngle vecAngles; - float color[3]; - float scale; - - CMatRenderContextPtr pRenderContext( materials ); - IMaterial *pMaterial = materials->FindMaterial( STUNSTICK_GLOW_MATERIAL_NOZ, NULL, false ); - // FIXME: Needs to work with new IMaterial system! - pRenderContext->Bind( pMaterial ); - - // Find where we are in the fade - float fadeAmount = RemapValClamped( gpGlobals->curtime, m_flFadeTime, m_flFadeTime + FADE_DURATION, 1.0f, 0.1f ); - - // Get bright when swung - if ( InSwing() ) - { - color[0] = color[1] = color[2] = 0.4f; - scale = 22.0f; - } - else - { - color[0] = color[1] = color[2] = 0.4f * fadeAmount; - scale = 20.0f; - } - - if ( color[0] > 0.0f ) - { - // Draw an all encompassing glow around the entire head - UTIL_GetWeaponAttachment( this, m_BeamCenterAttachment, vecOrigin, vecAngles ); - DrawHalo( pMaterial, vecOrigin, scale, color ); - } - - // Draw bright points at each attachment location - for ( int i = 0; i < (NUM_BEAM_ATTACHMENTS*2)+1; i++ ) - { - if ( InSwing() ) - { - color[0] = color[1] = color[2] = random->RandomFloat( 0.05f, 0.5f ); - scale = random->RandomFloat( 4.0f, 5.0f ); - } - else - { - color[0] = color[1] = color[2] = random->RandomFloat( 0.05f, 0.5f ) * fadeAmount; - scale = random->RandomFloat( 4.0f, 5.0f ) * fadeAmount; - } - - if ( color[0] > 0.0f ) - { - UTIL_GetWeaponAttachment( this, i, vecOrigin, vecAngles ); - DrawHalo( pMaterial, vecOrigin, scale, color ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Draw our special effects -//----------------------------------------------------------------------------- -void C_WeaponStunStick::DrawEffects( void ) -{ - if ( IsCarriedByLocalPlayer() ) - { - DrawFirstPersonEffects(); - } - else - { - DrawThirdPersonEffects(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Viewmodel was drawn -//----------------------------------------------------------------------------- -void C_WeaponStunStick::ViewModelDrawn( C_BaseViewModel *pBaseViewModel ) -{ - // Don't bother when we're not deployed - if ( IsWeaponVisible() ) - { - // Do all our special effects - DrawEffects(); - } - - BaseClass::ViewModelDrawn( pBaseViewModel ); -} - -//----------------------------------------------------------------------------- -// Purpose: Draw a cheap glow quad at our impact point (with sparks) -//----------------------------------------------------------------------------- -void StunstickImpactCallback( const CEffectData &data ) -{ - float scale = random->RandomFloat( 16, 32 ); - - FX_AddQuad( data.m_vOrigin, - data.m_vNormal, - scale, - scale*2.0f, - 1.0f, - 1.0f, - 0.0f, - 0.0f, - random->RandomInt( 0, 360 ), - 0, - Vector( 1.0f, 1.0f, 1.0f ), - 0.1f, - "sprites/light_glow02_add", - 0 ); - - FX_Sparks( data.m_vOrigin, 1, 2, data.m_vNormal, 6, 64, 256 ); -} - -DECLARE_CLIENT_EFFECT( "StunstickImpact", StunstickImpactCallback ); - -#endif diff --git a/game/shared/ichoreoeventcallback.h b/game/shared/ichoreoeventcallback.h deleted file mode 100644 index e928f58f4..000000000 --- a/game/shared/ichoreoeventcallback.h +++ /dev/null @@ -1,34 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#ifndef ICHOREOEVENTCALLBACK_H -#define ICHOREOEVENTCALLBACK_H -#ifdef _WIN32 -#pragma once -#endif - -class CChoreoEvent; -class CChoreoChannel; -class CChoreoActor; -class CChoreoScene; - -//----------------------------------------------------------------------------- -// Purpose: During choreo playback, events are triggered by calling back from -// the scene through this interface. -//----------------------------------------------------------------------------- -abstract_class IChoreoEventCallback -{ -public: - virtual void StartEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event ) = 0; - // Only called for events with HasEndTime() == true - virtual void EndEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event ) = 0; - // Called for events which have been started but aren't done yet - virtual void ProcessEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event ) = 0; - // Called for events that are part of a pause condition - virtual bool CheckEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event ) = 0; -}; - -#endif // ICHOREOEVENTCALLBACK_H diff --git a/game/shared/igamemovement.h b/game/shared/igamemovement.h deleted file mode 100644 index 66ec5d54e..000000000 --- a/game/shared/igamemovement.h +++ /dev/null @@ -1,129 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#if !defined( IGAMEMOVEMENT_H ) -#define IGAMEMOVEMENT_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "mathlib/vector.h" -#include "interface.h" -#include "imovehelper.h" -#include "const.h" - -//----------------------------------------------------------------------------- -// Name of the class implementing the game movement. -//----------------------------------------------------------------------------- - -#define INTERFACENAME_GAMEMOVEMENT "GameMovement001" - -//----------------------------------------------------------------------------- -// Forward declarations. -//----------------------------------------------------------------------------- - -class IMoveHelper; - -//----------------------------------------------------------------------------- -// Purpose: Encapsulated input parameters to player movement. -//----------------------------------------------------------------------------- - -class CMoveData -{ -public: - bool m_bFirstRunOfFunctions : 1; - bool m_bGameCodeMovedPlayer : 1; - - EntityHandle_t m_nPlayerHandle; // edict index on server, client entity handle on client - - int m_nImpulseCommand; // Impulse command issued. - QAngle m_vecViewAngles; // Command view angles (local space) - QAngle m_vecAbsViewAngles; // Command view angles (world space) - int m_nButtons; // Attack buttons. - int m_nOldButtons; // From host_client->oldbuttons; - float m_flForwardMove; - float m_flSideMove; - float m_flUpMove; - - float m_flMaxSpeed; - float m_flClientMaxSpeed; - - // Variables from the player edict (sv_player) or entvars on the client. - // These are copied in here before calling and copied out after calling. - Vector m_vecVelocity; // edict::velocity // Current movement direction. - QAngle m_vecAngles; // edict::angles - QAngle m_vecOldAngles; - -// Output only - float m_outStepHeight; // how much you climbed this move - Vector m_outWishVel; // This is where you tried - Vector m_outJumpVel; // This is your jump velocity - - // Movement constraints (radius 0 means no constraint) - Vector m_vecConstraintCenter; - float m_flConstraintRadius; - float m_flConstraintWidth; - float m_flConstraintSpeedFactor; - - void SetAbsOrigin( const Vector &vec ); - const Vector &GetAbsOrigin() const; - -private: - Vector m_vecAbsOrigin; // edict::origin -}; - -inline const Vector &CMoveData::GetAbsOrigin() const -{ - return m_vecAbsOrigin; -} - -#if !defined( CLIENT_DLL ) && defined( _DEBUG ) -// We only ever want this code path on the server side in a debug build -// and you have to uncomment the code below and rebuild to have the test operate. -//#define PLAYER_GETTING_STUCK_TESTING - -#endif - -#if !defined( PLAYER_GETTING_STUCK_TESTING ) - -// This is implemented with a more exhaustive test in gamemovement.cpp. We check if the origin being requested is -// inside solid, which it never should be -inline void CMoveData::SetAbsOrigin( const Vector &vec ) -{ - m_vecAbsOrigin = vec; -} - -#endif - - -//----------------------------------------------------------------------------- -// Purpose: The basic player movement interface -//----------------------------------------------------------------------------- - -abstract_class IGameMovement -{ -public: - virtual ~IGameMovement( void ) {} - - // Process the current movement command - virtual void ProcessMovement( CBasePlayer *pPlayer, CMoveData *pMove ) = 0; - virtual void StartTrackPredictionErrors( CBasePlayer *pPlayer ) = 0; - virtual void FinishTrackPredictionErrors( CBasePlayer *pPlayer ) = 0; - virtual void DiffPrint( char const *fmt, ... ) = 0; - - // Allows other parts of the engine to find out the normal and ducked player bbox sizes - virtual Vector GetPlayerMins( bool ducked ) const = 0; - virtual Vector GetPlayerMaxs( bool ducked ) const = 0; - virtual Vector GetPlayerViewOffset( bool ducked ) const = 0; - -}; - - -#endif // IGAMEMOVEMENT_H diff --git a/game/shared/igamesystem.cpp b/game/shared/igamesystem.cpp deleted file mode 100644 index 818320741..000000000 --- a/game/shared/igamesystem.cpp +++ /dev/null @@ -1,399 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Deals with singleton -// -// $Revision: $ -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "igamesystem.h" -#include "datacache/imdlcache.h" -#include "utlvector.h" -#include "vprof.h" -#if defined( _X360 ) -#include "xbox/xbox_console.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// Pointer to a member method of IGameSystem -typedef void (IGameSystem::*GameSystemFunc_t)(); - -// Pointer to a member method of IGameSystem -typedef void (IGameSystemPerFrame::*PerFrameGameSystemFunc_t)(); - -// Used to invoke a method of all added Game systems in order -static void InvokeMethod( GameSystemFunc_t f, char const *timed = 0 ); -// Used to invoke a method of all added Game systems in reverse order -static void InvokeMethodReverseOrder( GameSystemFunc_t f ); - -// Used to invoke a method of all added Game systems in order -static void InvokePerFrameMethod( PerFrameGameSystemFunc_t f, char const *timed = 0 ); - -static bool s_bSystemsInitted = false; - -// List of all installed Game systems -static CUtlVector s_GameSystems( 0, 4 ); -// List of all installed Game systems -static CUtlVector s_GameSystemsPerFrame( 0, 4 ); - -// The map name -static char* s_pMapName = 0; - -static CBasePlayer *s_pRunCommandPlayer = NULL; -static CUserCmd *s_pRunCommandUserCmd = NULL; - -//----------------------------------------------------------------------------- -// Auto-registration of game systems -//----------------------------------------------------------------------------- -static CAutoGameSystem *s_pSystemList = NULL; - -CAutoGameSystem::CAutoGameSystem( char const *name ) : - m_pszName( name ) -{ - // If s_GameSystems hasn't been initted yet, then add ourselves to the global list - // because we don't know if the constructor for s_GameSystems has happened yet. - // Otherwise, we can add ourselves right into that list. - if ( s_bSystemsInitted ) - { - Add( this ); - } - else - { - m_pNext = s_pSystemList; - s_pSystemList = this; - } -} - -static CAutoGameSystemPerFrame *s_pPerFrameSystemList = NULL; - -//----------------------------------------------------------------------------- -// Purpose: This is a CAutoGameSystem which also cares about the "per frame" hooks -//----------------------------------------------------------------------------- -CAutoGameSystemPerFrame::CAutoGameSystemPerFrame( char const *name ) : - m_pszName( name ) -{ - // If s_GameSystems hasn't been initted yet, then add ourselves to the global list - // because we don't know if the constructor for s_GameSystems has happened yet. - // Otherwise, we can add ourselves right into that list. - if ( s_bSystemsInitted ) - { - Add( this ); - } - else - { - m_pNext = s_pPerFrameSystemList; - s_pPerFrameSystemList = this; - } -} - -//----------------------------------------------------------------------------- -// destructor, cleans up automagically.... -//----------------------------------------------------------------------------- -IGameSystem::~IGameSystem() -{ - Remove( this ); -} - -//----------------------------------------------------------------------------- -// destructor, cleans up automagically.... -//----------------------------------------------------------------------------- -IGameSystemPerFrame::~IGameSystemPerFrame() -{ - Remove( this ); -} - - -//----------------------------------------------------------------------------- -// Adds a system to the list of systems to run -//----------------------------------------------------------------------------- -void IGameSystem::Add( IGameSystem* pSys ) -{ - s_GameSystems.AddToTail( pSys ); - if ( dynamic_cast< IGameSystemPerFrame * >( pSys ) != NULL ) - { - s_GameSystemsPerFrame.AddToTail( static_cast< IGameSystemPerFrame * >( pSys ) ); - } -} - - -//----------------------------------------------------------------------------- -// Removes a system from the list of systems to update -//----------------------------------------------------------------------------- -void IGameSystem::Remove( IGameSystem* pSys ) -{ - s_GameSystems.FindAndRemove( pSys ); - if ( dynamic_cast< IGameSystemPerFrame * >( pSys ) != NULL ) - { - s_GameSystemsPerFrame.FindAndRemove( static_cast< IGameSystemPerFrame * >( pSys ) ); - } -} - -//----------------------------------------------------------------------------- -// Removes *all* systems from the list of systems to update -//----------------------------------------------------------------------------- -void IGameSystem::RemoveAll( ) -{ - s_GameSystems.RemoveAll(); - s_GameSystemsPerFrame.RemoveAll(); -} - - -//----------------------------------------------------------------------------- -// Client systems can use this to get at the map name -//----------------------------------------------------------------------------- -char const* IGameSystem::MapName() -{ - return s_pMapName; -} - -#ifndef CLIENT_DLL -CBasePlayer *IGameSystem::RunCommandPlayer() -{ - return s_pRunCommandPlayer; -} - -CUserCmd *IGameSystem::RunCommandUserCmd() -{ - return s_pRunCommandUserCmd; -} -#endif - -//----------------------------------------------------------------------------- -// Invokes methods on all installed game systems -//----------------------------------------------------------------------------- -bool IGameSystem::InitAllSystems() -{ - int i; - - { - // first add any auto systems to the end - CAutoGameSystem *pSystem = s_pSystemList; - while ( pSystem ) - { - if ( s_GameSystems.Find( pSystem ) == s_GameSystems.InvalidIndex() ) - { - Add( pSystem ); - } - else - { - DevWarning( 1, "AutoGameSystem already added to game system list!!!\n" ); - } - pSystem = pSystem->m_pNext; - } - s_pSystemList = NULL; - } - - { - CAutoGameSystemPerFrame *pSystem = s_pPerFrameSystemList; - while ( pSystem ) - { - if ( s_GameSystems.Find( pSystem ) == s_GameSystems.InvalidIndex() ) - { - Add( pSystem ); - } - else - { - DevWarning( 1, "AutoGameSystem already added to game system list!!!\n" ); - } - - pSystem = pSystem->m_pNext; - } - s_pSystemList = NULL; - } - // Now remember that we are initted so new CAutoGameSystems will add themselves automatically. - s_bSystemsInitted = true; - - for ( i = 0; i < s_GameSystems.Count(); ++i ) - { - MDLCACHE_CRITICAL_SECTION(); - - IGameSystem *sys = s_GameSystems[i]; - -#if defined( _X360 ) - char sz[128]; - Q_snprintf( sz, sizeof( sz ), "%s->Init():Start", sys->Name() ); - XBX_rTimeStampLog( Plat_FloatTime(), sz ); -#endif - bool valid = sys->Init(); - -#if defined( _X360 ) - Q_snprintf( sz, sizeof( sz ), "%s->Init():Finish", sys->Name() ); - XBX_rTimeStampLog( Plat_FloatTime(), sz ); -#endif - if ( !valid ) - return false; - } - - return true; -} - -void IGameSystem::PostInitAllSystems( void ) -{ - InvokeMethod( &IGameSystem::PostInit, "PostInit" ); -} - -void IGameSystem::ShutdownAllSystems() -{ - InvokeMethodReverseOrder( &IGameSystem::Shutdown ); -} - -void IGameSystem::LevelInitPreEntityAllSystems( char const* pMapName ) -{ - // Store off the map name - if ( s_pMapName ) - { - delete[] s_pMapName; - } - - int len = Q_strlen(pMapName) + 1; - s_pMapName = new char [ len ]; - Q_strncpy( s_pMapName, pMapName, len ); - - InvokeMethod( &IGameSystem::LevelInitPreEntity, "LevelInitPreEntity" ); -} - -void IGameSystem::LevelInitPostEntityAllSystems( void ) -{ - InvokeMethod( &IGameSystem::LevelInitPostEntity, "LevelInitPostEntity" ); -} - -void IGameSystem::LevelShutdownPreClearSteamAPIContextAllSystems() -{ - InvokeMethodReverseOrder( &IGameSystem::LevelShutdownPreClearSteamAPIContext ); -} - -void IGameSystem::LevelShutdownPreEntityAllSystems() -{ - InvokeMethodReverseOrder( &IGameSystem::LevelShutdownPreEntity ); -} - -void IGameSystem::LevelShutdownPostEntityAllSystems() -{ - InvokeMethodReverseOrder( &IGameSystem::LevelShutdownPostEntity ); - - if ( s_pMapName ) - { - delete[] s_pMapName; - s_pMapName = 0; - } -} - -void IGameSystem::OnSaveAllSystems() -{ - InvokeMethod( &IGameSystem::OnSave ); -} - -void IGameSystem::OnRestoreAllSystems() -{ - InvokeMethod( &IGameSystem::OnRestore ); -} - -void IGameSystem::SafeRemoveIfDesiredAllSystems() -{ - InvokeMethodReverseOrder( &IGameSystem::SafeRemoveIfDesired ); -} - -#ifdef CLIENT_DLL - -void IGameSystem::PreRenderAllSystems() -{ - VPROF("IGameSystem::PreRenderAllSystems"); - InvokePerFrameMethod( &IGameSystemPerFrame::PreRender ); -} - -void IGameSystem::UpdateAllSystems( float frametime ) -{ - SafeRemoveIfDesiredAllSystems(); - - int i; - int c = s_GameSystemsPerFrame.Count(); - for ( i = 0; i < c; ++i ) - { - IGameSystemPerFrame *sys = s_GameSystemsPerFrame[i]; - MDLCACHE_CRITICAL_SECTION(); - sys->Update( frametime ); - } -} - -void IGameSystem::PostRenderAllSystems() -{ - InvokePerFrameMethod( &IGameSystemPerFrame::PostRender ); -} - -#else - -void IGameSystem::FrameUpdatePreEntityThinkAllSystems() -{ - InvokePerFrameMethod( &IGameSystemPerFrame::FrameUpdatePreEntityThink ); -} - -void IGameSystem::FrameUpdatePostEntityThinkAllSystems() -{ - SafeRemoveIfDesiredAllSystems(); - - InvokePerFrameMethod( &IGameSystemPerFrame::FrameUpdatePostEntityThink ); -} - -void IGameSystem::PreClientUpdateAllSystems() -{ - InvokePerFrameMethod( &IGameSystemPerFrame::PreClientUpdate ); -} - -#endif - - -//----------------------------------------------------------------------------- -// Invokes a method on all installed game systems in proper order -//----------------------------------------------------------------------------- -void InvokeMethod( GameSystemFunc_t f, char const *timed /*=0*/ ) -{ - NOTE_UNUSED( timed ); - - int i; - int c = s_GameSystems.Count(); - for ( i = 0; i < c ; ++i ) - { - IGameSystem *sys = s_GameSystems[i]; - - MDLCACHE_CRITICAL_SECTION(); - - (sys->*f)(); - } -} - -//----------------------------------------------------------------------------- -// Invokes a method on all installed game systems in proper order -//----------------------------------------------------------------------------- -void InvokePerFrameMethod( PerFrameGameSystemFunc_t f, char const *timed /*=0*/ ) -{ - NOTE_UNUSED( timed ); - - int i; - int c = s_GameSystemsPerFrame.Count(); - for ( i = 0; i < c ; ++i ) - { - IGameSystemPerFrame *sys = s_GameSystemsPerFrame[i]; - MDLCACHE_CRITICAL_SECTION(); - (sys->*f)(); - } -} - -//----------------------------------------------------------------------------- -// Invokes a method on all installed game systems in reverse order -//----------------------------------------------------------------------------- -void InvokeMethodReverseOrder( GameSystemFunc_t f ) -{ - int i; - int c = s_GameSystems.Count(); - for ( i = c; --i >= 0; ) - { - IGameSystem *sys = s_GameSystems[i]; - MDLCACHE_CRITICAL_SECTION(); - (sys->*f)(); - } -} - - diff --git a/game/shared/igamesystem.h b/game/shared/igamesystem.h deleted file mode 100644 index ce02f2aa0..000000000 --- a/game/shared/igamesystem.h +++ /dev/null @@ -1,259 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IGAMESYSTEM_H -#define IGAMESYSTEM_H -#ifdef _WIN32 -#pragma once -#endif - -//----------------------------------------------------------------------------- -// Game systems are singleton objects in the client + server codebase responsible for -// various tasks -// The order in which the server systems appear in this list are the -// order in which they are initialized and updated. They are shut down in -// reverse order from which they are initialized. -//----------------------------------------------------------------------------- - - -// UNDONE: Do these need GameInit/GameShutdown as well? -// UNDONE: Remove the Pre/Post entity semantics and rely on system ordering? -// FIXME: Remove all ifdef CLIENT_DLL if we can... -abstract_class IGameSystem -{ -public: - // GameSystems are expected to implement these methods. - virtual char const *Name() = 0; - - // Init, shutdown - // return true on success. false to abort DLL init! - virtual bool Init() = 0; - virtual void PostInit() = 0; - virtual void Shutdown() = 0; - - // Level init, shutdown - virtual void LevelInitPreEntity() = 0; - // entities are created / spawned / precached here - virtual void LevelInitPostEntity() = 0; - - virtual void LevelShutdownPreClearSteamAPIContext() {}; - virtual void LevelShutdownPreEntity() = 0; - // Entities are deleted / released here... - virtual void LevelShutdownPostEntity() = 0; - // end of level shutdown - - // Called during game save - virtual void OnSave() = 0; - - // Called during game restore, after the local player has connected and entities have been fully restored - virtual void OnRestore() = 0; - - // Called every frame. It's safe to remove an igamesystem from within this callback. - virtual void SafeRemoveIfDesired() = 0; - - virtual bool IsPerFrame() = 0; - - // destructor, cleans up automagically.... - virtual ~IGameSystem(); - - // Client systems can use this to get at the map name - static char const* MapName(); - - // These methods are used to add and remove server systems from the - // main server loop. The systems are invoked in the order in which - // they are added. - static void Add ( IGameSystem* pSys ); - static void Remove ( IGameSystem* pSys ); - static void RemoveAll ( ); - - // These methods are used to initialize, shutdown, etc all systems - static bool InitAllSystems(); - static void PostInitAllSystems(); - static void ShutdownAllSystems(); - static void LevelInitPreEntityAllSystems( char const* pMapName ); - static void LevelInitPostEntityAllSystems(); - static void LevelShutdownPreClearSteamAPIContextAllSystems(); - static void LevelShutdownPreEntityAllSystems(); - static void LevelShutdownPostEntityAllSystems(); - - static void OnSaveAllSystems(); - static void OnRestoreAllSystems(); - - static void SafeRemoveIfDesiredAllSystems(); - -#ifdef CLIENT_DLL - static void PreRenderAllSystems(); - static void UpdateAllSystems( float frametime ); - static void PostRenderAllSystems(); -#else - static void FrameUpdatePreEntityThinkAllSystems(); - static void FrameUpdatePostEntityThinkAllSystems(); - static void PreClientUpdateAllSystems(); - - // Accessors for the above function - static CBasePlayer *RunCommandPlayer(); - static CUserCmd *RunCommandUserCmd(); -#endif -}; - -class IGameSystemPerFrame : public IGameSystem -{ -public: - // destructor, cleans up automagically.... - virtual ~IGameSystemPerFrame(); - -#ifdef CLIENT_DLL - // Called before rendering - virtual void PreRender() = 0; - - // Gets called each frame - virtual void Update( float frametime ) = 0; - - // Called after rendering - virtual void PostRender() = 0; -#else - // Called each frame before entities think - virtual void FrameUpdatePreEntityThink() = 0; - // called after entities think - virtual void FrameUpdatePostEntityThink() = 0; - virtual void PreClientUpdate() = 0; -#endif -}; - -// Quick and dirty server system for users who don't care about precise ordering -// and usually only want to implement a few of the callbacks -class CBaseGameSystem : public IGameSystem -{ -public: - - virtual char const *Name() { return "unnamed"; } - - // Init, shutdown - // return true on success. false to abort DLL init! - virtual bool Init() { return true; } - virtual void PostInit() {} - virtual void Shutdown() {} - - // Level init, shutdown - virtual void LevelInitPreEntity() {} - virtual void LevelInitPostEntity() {} - virtual void LevelShutdownPreClearSteamAPIContext() {} - virtual void LevelShutdownPreEntity() {} - virtual void LevelShutdownPostEntity() {} - - virtual void OnSave() {} - virtual void OnRestore() {} - virtual void SafeRemoveIfDesired() {} - - virtual bool IsPerFrame() { return false; } -private: - - // Prevent anyone derived from CBaseGameSystem from implementing these, they need - // to derive from CBaseGameSystemPerFrame below!!! -#ifdef CLIENT_DLL - // Called before rendering - virtual void PreRender() {} - - // Gets called each frame - virtual void Update( float frametime ) {} - - // Called after rendering - virtual void PostRender() {} -#else - // Called each frame before entities think - virtual void FrameUpdatePreEntityThink() {} - // called after entities think - virtual void FrameUpdatePostEntityThink() {} - virtual void PreClientUpdate() {} -#endif -}; - -// Quick and dirty server system for users who don't care about precise ordering -// and usually only want to implement a few of the callbacks -class CBaseGameSystemPerFrame : public IGameSystemPerFrame -{ -public: - virtual char const *Name() { return "unnamed"; } - - // Init, shutdown - // return true on success. false to abort DLL init! - virtual bool Init() { return true; } - virtual void PostInit() {} - virtual void Shutdown() {} - - // Level init, shutdown - virtual void LevelInitPreEntity() {} - virtual void LevelInitPostEntity() {} - virtual void LevelShutdownPreClearSteamAPIContext() {} - virtual void LevelShutdownPreEntity() {} - virtual void LevelShutdownPostEntity() {} - - virtual void OnSave() {} - virtual void OnRestore() {} - virtual void SafeRemoveIfDesired() {} - - virtual bool IsPerFrame() { return true; } - -#ifdef CLIENT_DLL - // Called before rendering - virtual void PreRender () { } - - // Gets called each frame - virtual void Update( float frametime ) { } - - // Called after rendering - virtual void PostRender () { } -#else - // Called each frame before entities think - virtual void FrameUpdatePreEntityThink() { } - // called after entities think - virtual void FrameUpdatePostEntityThink() { } - virtual void PreClientUpdate() { } -#endif -}; - -// Quick and dirty server system for users who don't care about precise ordering -// and usually only want to implement a few of the callbacks -class CAutoGameSystem : public CBaseGameSystem -{ -public: - CAutoGameSystem( char const *name = NULL ); // hooks in at startup, no need to explicitly add - CAutoGameSystem *m_pNext; - - virtual char const *Name() { return m_pszName ? m_pszName : "unnamed"; } - -private: - char const *m_pszName; -}; - -//----------------------------------------------------------------------------- -// Purpose: This is a CAutoGameSystem which also cares about the "per frame" hooks -//----------------------------------------------------------------------------- -class CAutoGameSystemPerFrame : public CBaseGameSystemPerFrame -{ -public: - CAutoGameSystemPerFrame( char const *name = NULL ); - CAutoGameSystemPerFrame *m_pNext; - - virtual char const *Name() { return m_pszName ? m_pszName : "unnamed"; } - -private: - char const *m_pszName; -}; - - -//----------------------------------------------------------------------------- -// Purpose: This interface is here to add more hooks than IGameSystemPerFrame exposes, -// so we don't pollute it with hooks that only the tool cares about -//----------------------------------------------------------------------------- -class IToolFrameworkServer -{ -public: - virtual void PreSetupVisibility() = 0; -}; - -#endif // IGAMESYSTEM_H diff --git a/game/shared/imovehelper.h b/game/shared/imovehelper.h deleted file mode 100644 index f250f03a7..000000000 --- a/game/shared/imovehelper.h +++ /dev/null @@ -1,115 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IMOVEHELPER_H -#define IMOVEHELPER_H - -#ifdef _WIN32 -#pragma once -#endif - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- - -enum PLAYER_ANIM; -class IPhysicsSurfaceProps; -class Vector; -struct model_t; -struct cmodel_t; -struct vcollide_t; -class CGameTrace; -enum soundlevel_t; - -//----------------------------------------------------------------------------- -// Purpose: Identifies how submerged in water a player is. -//----------------------------------------------------------------------------- - -enum -{ - WL_NotInWater=0, - WL_Feet, - WL_Waist, - WL_Eyes -}; - - -//----------------------------------------------------------------------------- -// An entity identifier that works in both game + client dlls -//----------------------------------------------------------------------------- - -typedef CBaseHandle EntityHandle_t; - - -#define INVALID_ENTITY_HANDLE INVALID_EHANDLE_INDEX - -//----------------------------------------------------------------------------- -// Functions the engine provides to IGameMovement to assist in its movement. -//----------------------------------------------------------------------------- - -abstract_class IMoveHelper -{ -public: - // Call this to set the singleton - static IMoveHelper* GetSingleton( ) { return sm_pSingleton; } - - // Methods associated with a particular entity - virtual char const* GetName( EntityHandle_t handle ) const = 0; - - // Adds the trace result to touch list, if contact is not already in list. - virtual void ResetTouchList( void ) = 0; - virtual bool AddToTouched( const CGameTrace& tr, const Vector& impactvelocity ) = 0; - virtual void ProcessImpacts( void ) = 0; - - // Numbered line printf - virtual void Con_NPrintf( int idx, char const* fmt, ... ) = 0; - - // These have separate server vs client impementations - virtual void StartSound( const Vector& origin, int channel, char const* sample, float volume, soundlevel_t soundlevel, int fFlags, int pitch ) = 0; - virtual void StartSound( const Vector& origin, const char *soundname ) = 0; - virtual void PlaybackEventFull( int flags, int clientindex, unsigned short eventindex, float delay, Vector& origin, Vector& angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 ) = 0; - - // Apply falling damage to m_pHostPlayer based on m_pHostPlayer->m_flFallVelocity. - virtual bool PlayerFallingDamage( void ) = 0; - - // Apply falling damage to m_pHostPlayer based on m_pHostPlayer->m_flFallVelocity. - virtual void PlayerSetAnimation( PLAYER_ANIM playerAnim ) = 0; - - virtual IPhysicsSurfaceProps *GetSurfaceProps( void ) = 0; - - virtual bool IsWorldEntity( const CBaseHandle &handle ) = 0; - -protected: - // Inherited classes can call this to set the singleton - static void SetSingleton( IMoveHelper* pMoveHelper ) { sm_pSingleton = pMoveHelper; } - - // Clients shouldn't call delete directly - virtual ~IMoveHelper() {} - - // The global instance - static IMoveHelper* sm_pSingleton; -}; - -//----------------------------------------------------------------------------- -// Add this to the CPP file that implements the IMoveHelper -//----------------------------------------------------------------------------- - -#define IMPLEMENT_MOVEHELPER() \ - IMoveHelper* IMoveHelper::sm_pSingleton = 0 - -//----------------------------------------------------------------------------- -// Call this to set the singleton -//----------------------------------------------------------------------------- - -inline IMoveHelper* MoveHelper( ) -{ - return IMoveHelper::GetSingleton(); -} - - -#endif // IMOVEHELPER_H diff --git a/game/shared/in_buttons.h b/game/shared/in_buttons.h deleted file mode 100644 index 3d4622966..000000000 --- a/game/shared/in_buttons.h +++ /dev/null @@ -1,40 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef IN_BUTTONS_H -#define IN_BUTTONS_H -#ifdef _WIN32 -#pragma once -#endif - -#define IN_ATTACK (1 << 0) -#define IN_JUMP (1 << 1) -#define IN_DUCK (1 << 2) -#define IN_FORWARD (1 << 3) -#define IN_BACK (1 << 4) -#define IN_USE (1 << 5) -#define IN_CANCEL (1 << 6) -#define IN_LEFT (1 << 7) -#define IN_RIGHT (1 << 8) -#define IN_MOVELEFT (1 << 9) -#define IN_MOVERIGHT (1 << 10) -#define IN_ATTACK2 (1 << 11) -#define IN_RUN (1 << 12) -#define IN_RELOAD (1 << 13) -#define IN_ALT1 (1 << 14) -#define IN_ALT2 (1 << 15) -#define IN_SCORE (1 << 16) // Used by client.dll for when scoreboard is held down -#define IN_SPEED (1 << 17) // Player is holding the speed key -#define IN_WALK (1 << 18) // Player holding walk key -#define IN_ZOOM (1 << 19) // Zoom key for HUD zoom -#define IN_WEAPON1 (1 << 20) // weapon defines these bits -#define IN_WEAPON2 (1 << 21) // weapon defines these bits -#define IN_BULLRUSH (1 << 22) -#define IN_GRENADE1 (1 << 23) // grenade 1 -#define IN_GRENADE2 (1 << 24) // grenade 2 - -#endif // IN_BUTTONS_H diff --git a/game/shared/interval.cpp b/game/shared/interval.cpp deleted file mode 100644 index 168c6006a..000000000 --- a/game/shared/interval.cpp +++ /dev/null @@ -1,59 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "tier0/platform.h" -#include "interval.h" -#include "tier1/strtools.h" -#include "vstdlib/random.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pString - -// Output : interval_t -//----------------------------------------------------------------------------- -interval_t ReadInterval( const char *pString ) -{ - interval_t tmp; - - tmp.start = 0; - tmp.range = 0; - - char tempString[128]; - Q_strncpy( tempString, pString, sizeof(tempString) ); - - char *token = strtok( tempString, "," ); - if ( token ) - { - tmp.start = atof( token ); - token = strtok( NULL, "," ); - if ( token ) - { - tmp.range = atof( token ) - tmp.start; - } - } - - return tmp; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &interval - -// Output : float -//----------------------------------------------------------------------------- -float RandomInterval( const interval_t &interval ) -{ - float out = interval.start; - if ( interval.range != 0 ) - { - out += RandomFloat( 0, interval.range ); - } - - return out; -} diff --git a/game/shared/interval.h b/game/shared/interval.h deleted file mode 100644 index b7155c2f5..000000000 --- a/game/shared/interval.h +++ /dev/null @@ -1,20 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef INTERVAL_H -#define INTERVAL_H -#ifdef _WIN32 -#pragma once -#endif - -#include "basetypes.h" - - -interval_t ReadInterval( const char *pString ); -float RandomInterval( const interval_t &interval ); - -#endif // INTERVAL_H diff --git a/game/shared/iplayeranimstate.h b/game/shared/iplayeranimstate.h deleted file mode 100644 index 6aac29af6..000000000 --- a/game/shared/iplayeranimstate.h +++ /dev/null @@ -1,47 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef IPLAYERANIMSTATE_H -#define IPLAYERANIMSTATE_H -#ifdef _WIN32 -#pragma once -#endif - - - -typedef enum -{ - LEGANIM_9WAY, // Legs use a 9-way blend, with "move_x" and "move_y" pose parameters. - LEGANIM_8WAY, // Legs use an 8-way blend with "move_yaw" pose param. - LEGANIM_GOLDSRC // Legs always point in the direction he's running and the torso rotates. -} LegAnimType_t; - - - -abstract_class IPlayerAnimState -{ -public: - virtual void Release() = 0; - - // Update() and DoAnimationEvent() together maintain the entire player's animation state. - // - // Update() maintains the the lower body animation (the player's m_nSequence) - // and the upper body overlay based on the player's velocity and look direction. - // - // It also modulates these based on events triggered by DoAnimationEvent. - virtual void Update( float eyeYaw, float eyePitch ) = 0; - - // This is called by the client when a new player enters the PVS to clear any events - // the dormant version of the entity may have been playing. - virtual void ClearAnimationState() = 0; - - // The client uses this to figure out what angles to render the entity with (since as the guy turns, - // it will change his body_yaw pose parameter before changing his rendered angle). - virtual const QAngle& GetRenderAngles() = 0; -}; - - -#endif // IPLAYERANIMSTATE_H diff --git a/game/shared/ipredictionsystem.h b/game/shared/ipredictionsystem.h deleted file mode 100644 index f6f424184..000000000 --- a/game/shared/ipredictionsystem.h +++ /dev/null @@ -1,164 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IPREDICTIONSYSTEM_H -#define IPREDICTIONSYSTEM_H -#ifdef _WIN32 -#pragma once -#endif - -#include "predictable_entity.h" - -class CBaseEntity; - -//----------------------------------------------------------------------------- -// Purpose: Interfaces derived from this are able to filter out the local player -// when doing prediction on the client, this includes not sending network data to -// the local player from the server if needed. -//----------------------------------------------------------------------------- -class IPredictionSystem -{ -public: - IPredictionSystem() - { - m_pNextSystem = g_pPredictionSystems; - g_pPredictionSystems = this; - - m_bSuppressEvent = false; - m_pSuppressHost = NULL; - - m_nStatusPushed = 0; - }; - - virtual ~IPredictionSystem() {}; - - IPredictionSystem *GetNext() - { - return m_pNextSystem; - } - - void SetSuppressEvent( bool state ) - { - m_bSuppressEvent = state; - } - - void SetSuppressHost( CBaseEntity *host ) - { - m_pSuppressHost = host; - } - - CBaseEntity const *GetSuppressHost( void ) - { - if ( DisableFiltering() ) - { - return NULL; - } - - return m_pSuppressHost; - } - - bool CanPredict( void ) const - { - if ( DisableFiltering() ) - { - return false; - } - - return !m_bSuppressEvent; - } - - static IPredictionSystem *g_pPredictionSystems; - - static void SuppressEvents( bool state ) - { - IPredictionSystem *sys = g_pPredictionSystems; - while ( sys ) - { - sys->SetSuppressEvent( state ); - sys = sys->GetNext(); - } - } - - static void SuppressHostEvents( CBaseEntity *host ) - { - IPredictionSystem *sys = g_pPredictionSystems; - while ( sys ) - { - sys->SetSuppressHost( host ); - sys = sys->GetNext(); - } - } - -private: - - static void Push( void ) - { - IPredictionSystem *sys = g_pPredictionSystems; - while ( sys ) - { - sys->_Push(); - sys = sys->GetNext(); - } - } - - static void Pop( void ) - { - IPredictionSystem *sys = g_pPredictionSystems; - while ( sys ) - { - sys->_Pop(); - sys = sys->GetNext(); - } - } - - void _Push( void ) - { - ++m_nStatusPushed; - } - void _Pop( void ) - { - --m_nStatusPushed; - } - - bool DisableFiltering( void ) const - { - return ( m_nStatusPushed > 0 ) ? true : false; - } - - IPredictionSystem *m_pNextSystem; - bool m_bSuppressEvent; - CBaseEntity *m_pSuppressHost; - - int m_nStatusPushed; - - friend class CDisablePredictionFiltering; -}; - -class CDisablePredictionFiltering -{ -public: - CDisablePredictionFiltering( bool disable = true ) - { - m_bDisabled = disable; - if ( m_bDisabled ) - { - IPredictionSystem::Push(); - } - } - - ~CDisablePredictionFiltering( void ) - { - if ( m_bDisabled ) - { - IPredictionSystem::Pop(); - } - } -private: - bool m_bDisabled; -}; - -#endif // IPREDICTIONSYSTEM_H diff --git a/game/shared/iscenetokenprocessor.h b/game/shared/iscenetokenprocessor.h deleted file mode 100644 index cfa7c14df..000000000 --- a/game/shared/iscenetokenprocessor.h +++ /dev/null @@ -1,23 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ISCENETOKENPROCESSOR_H -#define ISCENETOKENPROCESSOR_H -#ifdef _WIN32 -#pragma once -#endif - -abstract_class ISceneTokenProcessor -{ -public: - virtual const char *CurrentToken( void ) = 0; - virtual bool GetToken( bool crossline ) = 0; - virtual bool TokenAvailable( void ) = 0; - virtual void Error( const char *fmt, ... ) = 0; -}; - -#endif // ISCENETOKENPROCESSOR_H diff --git a/game/shared/itempents.h b/game/shared/itempents.h deleted file mode 100644 index 9497b9c7b..000000000 --- a/game/shared/itempents.h +++ /dev/null @@ -1,131 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $Workfile: $ -// $NoKeywords: $ -//===========================================================================// - -#if !defined( ITEMPENTS_H ) -#define ITEMPENTS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ipredictionsystem.h" -#include "shattersurfacetypes.h" -#include "irecipientfilter.h" - -class CEffectData; -class KeyValues; - - -//----------------------------------------------------------------------------- -// Purpose: Shared interface to temp entities -//----------------------------------------------------------------------------- -abstract_class ITempEntsSystem : public IPredictionSystem -{ -public: - virtual void ArmorRicochet( IRecipientFilter& filer, float delay, - const Vector* pos, const Vector* dir ) = 0; - virtual void BeamEntPoint( IRecipientFilter& filer, float delay, - int nStartEntity, const Vector *start, int nEndEntity, const Vector* end, - int modelindex, int haloindex, int startframe, int framerate, - float life, float width, float endWidth, int fadeLength, float amplitude, - int r, int g, int b, int a, int speed ) = 0; - virtual void BeamEnts( IRecipientFilter& filer, float delay, - int start, int end, int modelindex, int haloindex, int startframe, int framerate, - float life, float width, float endWidth, int fadeLength, float amplitude, - int r, int g, int b, int a, int speed ) = 0; - virtual void BeamFollow( IRecipientFilter& filter, float delay, - int iEntIndex, int modelIndex, int haloIndex, float life, float width, float endWidth, - float fadeLength, float r, float g, float b, float a ) = 0; - virtual void BeamPoints( IRecipientFilter& filer, float delay, - const Vector* start, const Vector* end, int modelindex, int haloindex, int startframe, int framerate, - float life, float width, float endWidth, int fadeLength, float amplitude, - int r, int g, int b, int a, int speed ) = 0; - virtual void BeamLaser( IRecipientFilter& filer, float delay, - int start, int end, int modelindex, int haloindex, int startframe, int framerate, - float life, float width, float endWidth, int fadeLength, float amplitude, int r, int g, int b, int a, int speed ) = 0; - virtual void BeamRing( IRecipientFilter& filer, float delay, - int start, int end, int modelindex, int haloindex, int startframe, int framerate, - float life, float width, int spread, float amplitude, int r, int g, int b, int a, int speed, int flags = 0 ) = 0; - virtual void BeamRingPoint( IRecipientFilter& filer, float delay, - const Vector& center, float start_radius, float end_radius, int modelindex, int haloindex, int startframe, int framerate, - float life, float width, int spread, float amplitude, int r, int g, int b, int a, int speed, int flags = 0 ) = 0; - virtual void BeamSpline( IRecipientFilter& filer, float delay, - int points, Vector* rgPoints ) = 0; - virtual void BloodStream( IRecipientFilter& filer, float delay, - const Vector* org, const Vector* dir, int r, int g, int b, int a, int amount ) = 0; - virtual void BloodSprite( IRecipientFilter& filer, float delay, - const Vector* org, const Vector *dir, int r, int g, int b, int a, int size ) = 0; - virtual void BreakModel( IRecipientFilter& filer, float delay, - const Vector& pos, const QAngle &angle, const Vector& size, const Vector& vel, - int modelindex, int randomization, int count, float time, int flags ) = 0; - virtual void BSPDecal( IRecipientFilter& filer, float delay, - const Vector* pos, int entity, int index ) = 0; - virtual void ProjectDecal( IRecipientFilter& filter, float delay, - const Vector* pos, const QAngle *angles, float distance, int index ) = 0; - virtual void Bubbles( IRecipientFilter& filer, float delay, - const Vector* mins, const Vector* maxs, float height, int modelindex, int count, float speed ) = 0; - virtual void BubbleTrail( IRecipientFilter& filer, float delay, - const Vector* mins, const Vector* maxs, float height, int modelindex, int count, float speed ) = 0; - virtual void Decal( IRecipientFilter& filer, float delay, - const Vector* pos, const Vector* start, int entity, int hitbox, int index ) = 0; - virtual void DynamicLight( IRecipientFilter& filer, float delay, - const Vector* org, int r, int g, int b, int exponent, float radius, float time, float decay ) = 0; - virtual void Explosion( IRecipientFilter& filer, float delay, - const Vector* pos, int modelindex, float scale, int framerate, int flags, int radius, int magnitude, const Vector* normal = NULL, unsigned char materialType = 'C' ) = 0; - virtual void ShatterSurface( IRecipientFilter& filer, float delay, - const Vector* pos, const QAngle* angle, const Vector* vForce, const Vector* vForcePos, - float width, float height, float shardsize, ShatterSurface_t surfacetype, - int front_r, int front_g, int front_b, int back_r, int back_g, int back_b) = 0; - virtual void GlowSprite( IRecipientFilter& filer, float delay, - const Vector* pos, int modelindex, float life, float size, int brightness ) = 0; - virtual void FootprintDecal( IRecipientFilter& filer, float delay, const Vector *origin, const Vector* right, - int entity, int index, unsigned char materialType ) = 0; - virtual void Fizz( IRecipientFilter& filer, float delay, - const CBaseEntity *ed, int modelindex, int density, int current ) = 0; - virtual void KillPlayerAttachments( IRecipientFilter& filer, float delay, - int player ) = 0; - virtual void LargeFunnel( IRecipientFilter& filer, float delay, - const Vector* pos, int modelindex, int reversed ) = 0; - virtual void MetalSparks( IRecipientFilter& filer, float delay, - const Vector* pos, const Vector* dir ) = 0; - virtual void EnergySplash( IRecipientFilter& filer, float delay, - const Vector* pos, const Vector* dir, bool bExplosive ) = 0; - virtual void PlayerDecal( IRecipientFilter& filer, float delay, - const Vector* pos, int player, int entity ) = 0; - virtual void ShowLine( IRecipientFilter& filer, float delay, - const Vector* start, const Vector* end ) = 0; - virtual void Smoke( IRecipientFilter& filer, float delay, - const Vector* pos, int modelindex, float scale, int framerate ) = 0; - virtual void Sparks( IRecipientFilter& filer, float delay, - const Vector* pos, int nMagnitude, int nTrailLength, const Vector *pDir ) = 0; - virtual void Sprite( IRecipientFilter& filer, float delay, - const Vector* pos, int modelindex, float size, int brightness ) = 0; - virtual void SpriteSpray( IRecipientFilter& filer, float delay, - const Vector* pos, const Vector* dir, int modelindex, int speed, float noise, int count ) = 0; - virtual void WorldDecal( IRecipientFilter& filer, float delay, - const Vector* pos, int index ) = 0; - virtual void MuzzleFlash( IRecipientFilter& filer, float delay, - const Vector &start, const QAngle &angles, float scale, int type ) = 0; - virtual void Dust( IRecipientFilter& filer, float delay, - const Vector &pos, const Vector &dir, float size, float speed ) = 0; - virtual void GaussExplosion( IRecipientFilter& filer, float delay, - const Vector &pos, const Vector &dir, int type ) = 0; - virtual void DispatchEffect( IRecipientFilter& filter, float delay, - const Vector &pos, const char *pName, const CEffectData &data ) = 0; - virtual void PhysicsProp( IRecipientFilter& filter, float delay, int modelindex, int skin, - const Vector& pos, const QAngle &angles, const Vector& vel, int flags, int effects ) = 0; - - // For playback from external tools - virtual void TriggerTempEntity( KeyValues *pKeyValues ) = 0; - - virtual void ClientProjectile( IRecipientFilter& filter, float delay, - const Vector* vecOrigin, const Vector* vecVelocity, int modelindex, int lifetime, CBaseEntity *pOwner ) = 0; -}; - -extern ITempEntsSystem *te; - -#endif // ITEMPENTS_H diff --git a/game/shared/mapdata_shared.h b/game/shared/mapdata_shared.h deleted file mode 100644 index d370c1dcb..000000000 --- a/game/shared/mapdata_shared.h +++ /dev/null @@ -1,33 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef MAPDATA_SHARED_H -#define MAPDATA_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - -#include "interface.h" -#include "mathlib/vector.h" - -#define INTERFACEVERSION_MAPDATA "MapData001" - -abstract_class IMapData -{ -public: - - // World data queries. - virtual void GetMapBounds( Vector &vecMins, Vector &vecMaxs ) = 0; - virtual void GetMapOrigin( Vector &vecOrigin ) = 0; - virtual void GetMapSize( Vector &vecSize ) = 0; - - // 3D Skybox data queries. - virtual void Get3DSkyboxOrigin( Vector &vecOrigin ) = 0; - virtual float Get3DSkyboxScale( void ) = 0; -}; - -#endif // MAPDATA_SHARED_H diff --git a/game/shared/mapentities_shared.cpp b/game/shared/mapentities_shared.cpp deleted file mode 100644 index ffb34b45d..000000000 --- a/game/shared/mapentities_shared.cpp +++ /dev/null @@ -1,339 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Controls the loading, parsing and creation of the entities from the BSP. -// -//=============================================================================// - - -#include "cbase.h" -#include "mapentities_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#if !defined(_STATIC_LINKED) || defined(CLIENT_DLL) - -static const char *s_BraceChars = "{}()\'"; -static bool s_BraceCharacters[256]; -static bool s_BuildReverseMap = true; - -bool MapEntity_ExtractValue( const char *pEntData, const char *keyName, char Value[MAPKEY_MAXLENGTH] ) -{ - char token[MAPKEY_MAXLENGTH]; - const char *inputData = pEntData; - - while ( inputData ) - { - inputData = MapEntity_ParseToken( inputData, token ); // get keyname - if ( token[0] == '}' ) // end of entity? - break; // must not have seen the classname - - // is this the right key? - if ( !strcmp(token, keyName) ) - { - inputData = MapEntity_ParseToken( inputData, token ); // get value and return it - Q_strncpy( Value, token, MAPKEY_MAXLENGTH ); - return true; - } - - inputData = MapEntity_ParseToken( inputData, token ); // skip over value - } - - return false; -} - -int MapEntity_GetNumKeysInEntity( const char *pEntData ) -{ - char token[MAPKEY_MAXLENGTH]; - const char *inputData = pEntData; - int iNumKeys = 0; - - while ( inputData ) - { - inputData = MapEntity_ParseToken( inputData, token ); // get keyname - if ( token[0] == '}' ) // end of entity? - break; // must not have seen the classname - - iNumKeys++; - - inputData = MapEntity_ParseToken( inputData, token ); // skip over value - } - - return iNumKeys; -} - - -// skips to the beginning of the next entity in the data block -// returns NULL if no more entities -const char *MapEntity_SkipToNextEntity( const char *pMapData, char *pWorkBuffer ) -{ - if ( !pMapData ) - return NULL; - - // search through the map string for the next matching '{' - int openBraceCount = 1; - while ( pMapData != NULL ) - { - pMapData = MapEntity_ParseToken( pMapData, pWorkBuffer ); - - if ( FStrEq(pWorkBuffer, "{") ) - { - openBraceCount++; - } - else if ( FStrEq(pWorkBuffer, "}") ) - { - if ( --openBraceCount == 0 ) - { - // we've found the closing brace, so return the next character - return pMapData; - } - } - } - - // eof hit - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: parses a token out of a char data block -// the token gets fully read no matter what the length, but only MAPKEY_MAXLENGTH -// characters are written into newToken -// Input : char *data - the data to parse -// char *newToken - the buffer into which the new token is written -// char *braceChars - a string of characters that constitute braces. this pointer needs to be -// distince for each set of braceChars, since the usage is cached. -// Output : const char * - returns a pointer to the position in the data following the newToken -//----------------------------------------------------------------------------- -const char *MapEntity_ParseToken( const char *data, char *newToken ) -{ - int c; - int len; - - len = 0; - newToken[0] = 0; - - if (!data) - return NULL; - - // build the new table if we have to - if ( s_BuildReverseMap ) - { - s_BuildReverseMap = false; - - Q_memset( s_BraceCharacters, 0, sizeof(s_BraceCharacters) ); - - for ( const char *c = s_BraceChars; *c; c++ ) - { - s_BraceCharacters[static_cast(*c)] = true; - } - } - -// skip whitespace -skipwhite: - while ( (c = *data) <= ' ') - { - if (c == 0) - return NULL; // end of file; - data++; - } - -// skip // comments - if (c=='/' && data[1] == '/') - { - while (*data && *data != '\n') - data++; - goto skipwhite; - } - - -// handle quoted strings specially - if (c == '\"') - { - data++; - while ( len < MAPKEY_MAXLENGTH ) - { - c = *data++; - if (c=='\"' || !c) - { - newToken[len] = 0; - return data; - } - newToken[len] = c; - len++; - } - - if ( len >= MAPKEY_MAXLENGTH ) - { - len--; - newToken[len] = 0; - } - } - -// parse single characters - if ( s_BraceCharacters[c]/*c=='{' || c=='}'|| c==')'|| c=='(' || c=='\''*/ ) - { - newToken[len] = c; - len++; - newToken[len] = 0; - return data+1; - } - -// parse a regular word - do - { - newToken[len] = c; - data++; - len++; - c = *data; - if ( s_BraceCharacters[c] /*c=='{' || c=='}'|| c==')'|| c=='(' || c=='\''*/ ) - break; - - if ( len >= MAPKEY_MAXLENGTH ) - { - len--; - newToken[len] = 0; - } - - } while (c>32); - - newToken[len] = 0; - return data; -} - -#endif // !STATIC_LINKED || CLIENT_DLL - -/* ================= CEntityMapData definition ================ */ - -bool CEntityMapData::ExtractValue( const char *keyName, char *value ) -{ - return MapEntity_ExtractValue( m_pEntData, keyName, value ); -} - -bool CEntityMapData::GetFirstKey( char *keyName, char *value ) -{ - m_pCurrentKey = m_pEntData; // reset the status pointer - return GetNextKey( keyName, value ); -} - -const char *CEntityMapData::CurrentBufferPosition( void ) -{ - return m_pCurrentKey; -} - -bool CEntityMapData::GetNextKey( char *keyName, char *value ) -{ - char token[MAPKEY_MAXLENGTH]; - - // parse key - char *pPrevKey = m_pCurrentKey; - m_pCurrentKey = (char*)MapEntity_ParseToken( m_pCurrentKey, token ); - if ( token[0] == '}' ) - { - // step back - m_pCurrentKey = pPrevKey; - return false; - } - - if ( !m_pCurrentKey ) - { - Warning( "CEntityMapData::GetNextKey: EOF without closing brace\n" ); - Assert(0); - return false; - } - - Q_strncpy( keyName, token, MAPKEY_MAXLENGTH ); - - // fix up keynames with trailing spaces - int n = strlen(keyName); - while (n && keyName[n-1] == ' ') - { - keyName[n-1] = 0; - n--; - } - - // parse value - m_pCurrentKey = (char*)MapEntity_ParseToken( m_pCurrentKey, token ); - if ( !m_pCurrentKey ) - { - Warning( "CEntityMapData::GetNextKey: EOF without closing brace\n" ); - Assert(0); - return false; - } - if ( token[0] == '}' ) - { - Warning( "CEntityMapData::GetNextKey: closing brace without data\n" ); - Assert(0); - return false; - } - - // value successfully found - Q_strncpy( value, token, MAPKEY_MAXLENGTH ); - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: find the keyName in the endata and change its value to specified one -//----------------------------------------------------------------------------- -bool CEntityMapData::SetValue( const char *keyName, char *NewValue, int nKeyInstance ) -{ - // If this is -1, the size of the string is unknown and cannot be safely modified! - Assert( m_nEntDataSize != -1 ); - if ( m_nEntDataSize == -1 ) - return false; - - char token[MAPKEY_MAXLENGTH]; - char *inputData = m_pEntData; - char *prevData; - - char newvaluebuf[ 1024 ]; - int nCurrKeyInstance = 0; - - while ( inputData ) - { - inputData = (char*)MapEntity_ParseToken( inputData, token ); // get keyname - if ( token[0] == '}' ) // end of entity? - break; // must not have seen the classname - - // is this the right key? - if ( !strcmp(token, keyName) ) - { - ++nCurrKeyInstance; - if ( nCurrKeyInstance > nKeyInstance ) - { - // Find the start & end of the token we're going to replace - int entLen = strlen(m_pEntData); - char *postData = new char[entLen]; - prevData = inputData; - inputData = (char*)MapEntity_ParseToken( inputData, token ); // get keyname - Q_strncpy( postData, inputData, entLen ); - - // Insert quotes if caller didn't - if ( NewValue[0] != '\"' ) - { - Q_snprintf( newvaluebuf, sizeof( newvaluebuf ), "\"%s\"", NewValue ); - } - else - { - Q_strncpy( newvaluebuf, NewValue, sizeof( newvaluebuf ) ); - } - - int iNewValueLen = Q_strlen(newvaluebuf); - int iPadding = iNewValueLen - Q_strlen( token ) - 2; // -2 for the quotes (token doesn't have them) - - // prevData has a space at the start, seperating the value from the key. - // Add 1 to prevData when pasting in the new Value, to account for the space. - Q_strncpy( prevData+1, newvaluebuf, iNewValueLen+1 ); // +1 for the null terminator - Q_strcat( prevData, postData, m_nEntDataSize - ((prevData-m_pEntData)+1) ); - - m_pCurrentKey += iPadding; - delete [] postData; - return true; - } - } - - inputData = (char*)MapEntity_ParseToken( inputData, token ); // skip over value - } - - return false; -} diff --git a/game/shared/mapentities_shared.h b/game/shared/mapentities_shared.h deleted file mode 100644 index 673ef5d30..000000000 --- a/game/shared/mapentities_shared.h +++ /dev/null @@ -1,50 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef MAPENTITIES_SHARED_H -#define MAPENTITIES_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - -#define MAPKEY_MAXLENGTH 2048 - - -//----------------------------------------------------------------------------- -// Purpose: encapsulates the data string in the map file -// that is used to initialise entities. The data -// string contains a set of key/value pairs. -//----------------------------------------------------------------------------- -class CEntityMapData -{ -private: - char *m_pEntData; - int m_nEntDataSize; - char *m_pCurrentKey; - -public: - explicit CEntityMapData( char *entBlock, int nEntBlockSize = -1 ) : - m_pEntData(entBlock), m_nEntDataSize(nEntBlockSize), m_pCurrentKey(entBlock) {} - - // find the keyName in the entdata and puts it's value into Value. returns false if key is not found - bool ExtractValue( const char *keyName, char *Value ); - - // find the nth keyName in the endata and change its value to specified one - // where n == nKeyInstance - bool SetValue( const char *keyName, char *NewValue, int nKeyInstance = 0 ); - - bool GetFirstKey( char *keyName, char *Value ); - bool GetNextKey( char *keyName, char *Value ); - - const char *CurrentBufferPosition( void ); -}; - -const char *MapEntity_ParseToken( const char *data, char *newToken ); -const char *MapEntity_SkipToNextEntity( const char *pMapData, char *pWorkBuffer ); -bool MapEntity_ExtractValue( const char *pEntData, const char *keyName, char Value[MAPKEY_MAXLENGTH] ); - - -#endif // MAPENTITIES_SHARED_H diff --git a/game/shared/movetype_push.h b/game/shared/movetype_push.h deleted file mode 100644 index df87af608..000000000 --- a/game/shared/movetype_push.h +++ /dev/null @@ -1,24 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef MOVETYPE_PUSH_H -#define MOVETYPE_PUSH_H -#ifdef _WIN32 -#pragma once -#endif - -const int MAX_PUSHED_ENTITIES = 32; -struct physicspushlist_t -{ - float localMoveTime; - Vector localOrigin; - QAngle localAngles; - int pushedCount; - EHANDLE pushedEnts[MAX_PUSHED_ENTITIES]; - Vector pushVec[MAX_PUSHED_ENTITIES]; -}; - -#endif // MOVETYPE_PUSH_H diff --git a/game/shared/movevars_shared.cpp b/game/shared/movevars_shared.cpp deleted file mode 100644 index a2f992dfb..000000000 --- a/game/shared/movevars_shared.cpp +++ /dev/null @@ -1,73 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - - -#include "cbase.h" -#include "movevars_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// some cvars used by player movement system -#if defined(HL2_DLL) || defined(HL2_CLIENT_DLL) -#define DEFAULT_GRAVITY_STRING "600" -#else -#define DEFAULT_GRAVITY_STRING "800" -#endif - -ConVar sv_gravity ( "sv_gravity",DEFAULT_GRAVITY_STRING, FCVAR_NOTIFY | FCVAR_REPLICATED, "World gravity." ); - -#if defined(DOD_DLL) -ConVar sv_stopspeed ( "sv_stopspeed","100", FCVAR_NOTIFY | FCVAR_REPLICATED, "Minimum stopping speed when on ground." ); -#else -ConVar sv_stopspeed ( "sv_stopspeed","100", FCVAR_NOTIFY | FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Minimum stopping speed when on ground." ); -#endif - -ConVar sv_noclipaccelerate( "sv_noclipaccelerate", "5", FCVAR_NOTIFY | FCVAR_ARCHIVE | FCVAR_REPLICATED); -ConVar sv_noclipspeed ( "sv_noclipspeed", "5", FCVAR_ARCHIVE | FCVAR_NOTIFY | FCVAR_REPLICATED); -ConVar sv_specaccelerate( "sv_specaccelerate", "5", FCVAR_NOTIFY | FCVAR_ARCHIVE | FCVAR_REPLICATED); -ConVar sv_specspeed ( "sv_specspeed", "3", FCVAR_ARCHIVE | FCVAR_NOTIFY | FCVAR_REPLICATED); -ConVar sv_specnoclip ( "sv_specnoclip", "1", FCVAR_ARCHIVE | FCVAR_NOTIFY | FCVAR_REPLICATED); -ConVar sv_maxspeed ( "sv_maxspeed", "320", FCVAR_NOTIFY | FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY); - -#ifdef _XBOX - ConVar sv_accelerate ( "sv_accelerate", "7", FCVAR_NOTIFY | FCVAR_REPLICATED); -#else - ConVar sv_accelerate ( "sv_accelerate", "10", FCVAR_NOTIFY | FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY); -#endif//_XBOX - -ConVar sv_airaccelerate( "sv_airaccelerate", "10", FCVAR_NOTIFY | FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY ); -ConVar sv_wateraccelerate( "sv_wateraccelerate", "10", FCVAR_NOTIFY | FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY ); -ConVar sv_waterfriction( "sv_waterfriction", "1", FCVAR_NOTIFY | FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY ); -ConVar sv_footsteps ( "sv_footsteps", "1", FCVAR_NOTIFY | FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Play footstep sound for players" ); -ConVar sv_rollspeed ( "sv_rollspeed", "200", FCVAR_NOTIFY | FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY); -ConVar sv_rollangle ( "sv_rollangle", "0", FCVAR_NOTIFY | FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Max view roll angle"); - -#if defined(DOD_DLL) -ConVar sv_friction ( "sv_friction","4", FCVAR_NOTIFY | FCVAR_REPLICATED, "World friction." ); -#else -ConVar sv_friction ( "sv_friction","4", FCVAR_NOTIFY | FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "World friction." ); -#endif - -ConVar sv_bounce ( "sv_bounce","0", FCVAR_NOTIFY | FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Bounce multiplier for when physically simulated objects collide with other objects." ); -ConVar sv_maxvelocity ( "sv_maxvelocity","3500", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Maximum speed any ballistically moving object is allowed to attain per axis." ); -ConVar sv_stepsize ( "sv_stepsize","18", FCVAR_NOTIFY | FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY ); -ConVar sv_skyname ( "sv_skyname", "sky_urb01", FCVAR_ARCHIVE | FCVAR_REPLICATED, "Current name of the skybox texture" ); -ConVar sv_backspeed ( "sv_backspeed", "0.6", FCVAR_ARCHIVE | FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "How much to slow down backwards motion" ); -ConVar sv_waterdist ( "sv_waterdist","12", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Vertical view fixup when eyes are near water plane." ); - -// Vehicle convars -ConVar r_VehicleViewDampen( "r_VehicleViewDampen", "1", FCVAR_CHEAT | FCVAR_NOTIFY | FCVAR_REPLICATED ); - -// Jeep convars -ConVar r_JeepViewDampenFreq( "r_JeepViewDampenFreq", "7.0", FCVAR_CHEAT | FCVAR_NOTIFY | FCVAR_REPLICATED ); -ConVar r_JeepViewDampenDamp( "r_JeepViewDampenDamp", "1.0", FCVAR_CHEAT | FCVAR_NOTIFY | FCVAR_REPLICATED); -ConVar r_JeepViewZHeight( "r_JeepViewZHeight", "10.0", FCVAR_CHEAT | FCVAR_NOTIFY | FCVAR_REPLICATED ); - -// Airboat convars -ConVar r_AirboatViewDampenFreq( "r_AirboatViewDampenFreq", "7.0", FCVAR_CHEAT | FCVAR_NOTIFY | FCVAR_REPLICATED ); -ConVar r_AirboatViewDampenDamp( "r_AirboatViewDampenDamp", "1.0", FCVAR_CHEAT | FCVAR_NOTIFY | FCVAR_REPLICATED); -ConVar r_AirboatViewZHeight( "r_AirboatViewZHeight", "0.0", FCVAR_CHEAT | FCVAR_NOTIFY | FCVAR_REPLICATED ); diff --git a/game/shared/movevars_shared.h b/game/shared/movevars_shared.h deleted file mode 100644 index 10d049d64..000000000 --- a/game/shared/movevars_shared.h +++ /dev/null @@ -1,51 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef MOVEVARS_SHARED_H -#define MOVEVARS_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - -#include "convar.h" - -extern ConVar sv_gravity; -extern ConVar sv_stopspeed; -extern ConVar sv_noclipaccelerate; -extern ConVar sv_noclipspeed; -extern ConVar sv_maxspeed; -extern ConVar sv_accelerate; -extern ConVar sv_airaccelerate; -extern ConVar sv_wateraccelerate; -extern ConVar sv_waterfriction; -extern ConVar sv_footsteps; -extern ConVar sv_rollspeed; -extern ConVar sv_rollangle; -extern ConVar sv_friction; -extern ConVar sv_bounce; -extern ConVar sv_maxvelocity; -extern ConVar sv_stepsize; -extern ConVar sv_skyname; -extern ConVar sv_backspeed; -extern ConVar sv_waterdist; -extern ConVar sv_specaccelerate; -extern ConVar sv_specspeed; -extern ConVar sv_specnoclip; - -// Vehicle convars -extern ConVar r_VehicleViewDampen; - -// Jeep convars -extern ConVar r_JeepViewDampenFreq; -extern ConVar r_JeepViewDampenDamp; -extern ConVar r_JeepViewZHeight; - -// Airboat convars -extern ConVar r_AirboatViewDampenFreq; -extern ConVar r_AirboatViewDampenDamp; -extern ConVar r_AirboatViewZHeight; - -#endif // MOVEVARS_SHARED_H diff --git a/game/shared/mp_shareddefs.cpp b/game/shared/mp_shareddefs.cpp deleted file mode 100644 index 6dc533fae..000000000 --- a/game/shared/mp_shareddefs.cpp +++ /dev/null @@ -1,91 +0,0 @@ -//====== Copyright 1996-2007, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#include "mp_shareddefs.h" - -const char *g_pszMPConcepts[] = -{ - "TLK_FIREWEAPON", // MP_CONCEPT_FIREWEAPON - "TLK_HURT", // MP_CONCEPT_HURT - "TLK_PLAYER_EXPRESSION", // MP_CONCEPT_PLAYER_EXPRESSION - "TLK_WINDMINIGUN", // MP_CONCEPT_WINDMINIGUN - "TLK_FIREMINIGUN", // MP_CONCEPT_FIREMINIGUN - "TLK_PLAYER_MEDIC", // MP_CONCEPT_PLAYER_MEDIC - "TLK_DETONATED_OBJECT", // MP_CONCEPT_DETONATED_OBJECT - "TLK_KILLED_PLAYER", // MP_CONCEPT_KILLED_PLAYER - "TLK_KILLED_OBJECT", // MP_CONCEPT_KILLED_OBJECT - "TLK_PLAYER_PAIN", // MP_CONCEPT_PLAYER_PAIN - "TLK_PLAYER_ATTACKER_PAIN", // MP_CONCEPT_PLAYER_ATTACKER_PAIN - "TLK_PLAYER_TAUNT", // MP_CONCEPT_PLAYER_TAUNT - "TLK_PLAYER_HELP", // MP_CONCEPT_PLAYER_HELP - "TLK_PLAYER_GO", // MP_CONCEPT_PLAYER_GO - "TLK_PLAYER_MOVEUP", // MP_CONCEPT_PLAYER_MOVEUP - "TLK_PLAYER_LEFT", // MP_CONCEPT_PLAYER_LEFT - "TLK_PLAYER_RIGHT", // MP_CONCEPT_PLAYER_RIGHT - "TLK_PLAYER_YES", // MP_CONCEPT_PLAYER_YES - "TLK_PLAYER_NO", // MP_CONCEPT_PLAYER_NO - "TLK_PLAYER_INCOMING", // MP_CONCEPT_PLAYER_INCOMING - "TLK_PLAYER_CLOAKEDSPY", // MP_CONCEPT_PLAYER_CLOAKEDSPY - "TLK_PLAYER_SENTRYAHEAD", // MP_CONCEPT_PLAYER_SENTRYAHEAD - "TLK_PLAYER_TELEPORTERHERE", // MP_CONCEPT_PLAYER_TELEPORTERHERE - "TLK_PLAYER_DISPENSERHERE", // MP_CONCEPT_PLAYER_DISPENSERHERE - "TLK_PLAYER_SENTRYHERE", // MP_CONCEPT_PLAYER_SENTRYHERE - "TLK_PLAYER_ACTIVATECHARGE", // MP_CONCEPT_PLAYER_ACTIVATECHARGE - "TLK_PLAYER_CHARGEREADY", // MP_CONCEPT_PLAYER_CHARGEREADY - "TLK_PLAYER_TAUNTS" , // MP_CONCEPT_PLAYER_TAUNTS - "TLK_PLAYER_BATTLECRY", // MP_CONCEPT_PLAYER_BATTLECRY - "TLK_PLAYER_CHEERS", // MP_CONCEPT_PLAYER_CHEERS - "TLK_PLAYER_JEERS", // MP_CONCEPT_PLAYER_JEERS - "TLK_PLAYER_POSITIVE", // MP_CONCEPT_PLAYER_POSITIVE - "TLK_PLAYER_NEGATIVE", // MP_CONCEPT_PLAYER_NEGATIVE - "TLK_PLAYER_NICESHOT", // MP_CONCEPT_PLAYER_NICESHOT - "TLK_PLAYER_GOODJOB", // MP_CONCEPT_PLAYER_GOODJOB - "TLK_MEDIC_STARTEDHEALING", // MP_CONCEPT_MEDIC_STARTEDHEALING - "TLK_MEDIC_CHARGEREADY", // MP_CONCEPT_MEDIC_CHARGEREADY - "TLK_MEDIC_STOPPEDHEALING", // MP_CONCEPT_MEDIC_STOPPEDHEALING - "TLK_MEDIC_CHARGEDEPLOYED", // MP_CONCEPT_MEDIC_CHARGEDEPLOYED - "TLK_FLAGPICKUP", // MP_CONCEPT_FLAGPICKUP - "TLK_FLAGCAPTURED", // MP_CONCEPT_FLAGCAPTURED - "TLK_ROUND_START", // MP_CONCEPT_ROUND_START - "TLK_SUDDENDEATH_START", // MP_CONCEPT_SUDDENDEATH_START - "TLK_ONFIRE", // MP_CONCEPT_ONFIRE - "TLK_STALEMATE", // MP_CONCEPT_STALEMATE - "TLK_BUILDING_OBJECT", // MP_CONCEPT_BUILDING_OBJECT - "TLK_LOST_OBJECT", // MP_CONCEPT_LOST_OBJECT - "TLK_SPY_SAPPER", // MP_CONCEPT_SPY_SAPPER - "TLK_TELEPORTED", // MP_CONCEPT_TELEPORTED - "TLK_LOST_CONTROL_POINT", // MP_CONCEPT_LOST_CONTROL_POINT - "TLK_CAPTURED_POINT", // MP_CONCEPT_CAPTURED_POINT - "TLK_CAPTURE_BLOCKED", // MP_CONCEPT_CAPTURE_BLOCKED - "TLK_HEALTARGET_STARTEDHEALING",// MP_CONCEPT_HEALTARGET_STARTEDHEALING - "TLK_HEALTARGET_CHARGEREADY", // MP_CONCEPT_HEALTARGET_CHARGEREADY - "TLK_HEALTARGET_STOPPEDHEALING",// MP_CONCEPT_HEALTARGET_STOPPEDHEALING - "TLK_HEALTARGET_CHARGEDEPLOYED",// MP_CONCEPT_HEALTARGET_CHARGEDEPLOYED - "TLK_MINIGUN_FIREWEAPON", // MP_CONCEPT_MINIGUN_FIREWEAPON - "TLK_DIED", // MP_CONCEPT_DIED - "TLK_PLAYER_THANKS", // MP_CONCEPT_PLAYER_THANKS - "TLK_CART_MOVING_FORWARD", // MP_CONCEPT_CART_MOVING_FORWARD - "TLK_CART_MOVING_BACKWARD", // MP_CONCEPT_CART_MOVING_BACKWARD - "TLK_CART_STOP", // MP_CONCEPT_CART_STOP -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int GetMPConceptIndexFromString( const char *pszConcept ) -{ - // Make sure our concept string and enum arrays are the same length - Assert( ARRAYSIZE( g_pszMPConcepts ) == MP_TF_CONCEPT_COUNT ); - - for ( size_t iConcept = 0; iConcept < ARRAYSIZE( g_pszMPConcepts ); ++iConcept ) - { - if ( !Q_stricmp( pszConcept, g_pszMPConcepts[iConcept] ) ) - return iConcept; - } - - return MP_CONCEPT_NONE; -} diff --git a/game/shared/mp_shareddefs.h b/game/shared/mp_shareddefs.h deleted file mode 100644 index e615d2a7c..000000000 --- a/game/shared/mp_shareddefs.h +++ /dev/null @@ -1,91 +0,0 @@ -//====== Copyright 1996-2007, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= -#ifndef MP_SHAREDDEFS_H -#define MP_SHAREDDEFS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "shareddefs.h" - -//----------------------------------------------------------------------------- -// TF Concepts -//----------------------------------------------------------------------------- -#define MP_CONCEPT_NONE -1 - -enum -{ - MP_CONCEPT_FIREWEAPON = 0, // "TLK_FIREWEAPON" - MP_CONCEPT_HURT, // "TLK_HURT" - MP_CONCEPT_PLAYER_EXPRESSION, // "TLK_PLAYER_EXPRESSION" - MP_CONCEPT_WINDMINIGUN, // "TLK_WINDMINIGUN" - MP_CONCEPT_FIREMINIGUN, // "TLK_FIREMINIGUN" - MP_CONCEPT_PLAYER_MEDIC, // "TLK_PLAYER_MEDIC" - MP_CONCEPT_DETONATED_OBJECT, // "TLK_DETONATED_OBJECT" - MP_CONCEPT_KILLED_PLAYER, // "TLK_KILLED_PLAYER" - MP_CONCEPT_KILLED_OBJECT, // "TLK_KILLED_OBJECT" - MP_CONCEPT_PLAYER_PAIN, // "TLK_PLAYER_PAIN" - MP_CONCEPT_PLAYER_ATTACKER_PAIN, // "TLK_PLAYER_ATTACKER_PAIN" - MP_CONCEPT_PLAYER_TAUNT, // "TLK_PLAYER_TAUNT" - MP_CONCEPT_PLAYER_HELP, // "TLK_PLAYER_HELP" - MP_CONCEPT_PLAYER_GO, // "TLK_PLAYER_GO" - MP_CONCEPT_PLAYER_MOVEUP, // "TLK_PLAYER_MOVEUP" - MP_CONCEPT_PLAYER_LEFT, // "TLK_PLAYER_LEFT" - MP_CONCEPT_PLAYER_RIGHT, // "TLK_PLAYER_RIGHT" - MP_CONCEPT_PLAYER_YES, // "TLK_PLAYER_YES" - MP_CONCEPT_PLAYER_NO, // "TLK_PLAYER_NO" - MP_CONCEPT_PLAYER_INCOMING, // "TLK_PLAYER_INCOMING" - MP_CONCEPT_PLAYER_CLOAKEDSPY, // "TLK_PLAYER_CLOAKEDSPY" - MP_CONCEPT_PLAYER_SENTRYAHEAD, // "TLK_PLAYER_SENTRYAHEAD" - MP_CONCEPT_PLAYER_TELEPORTERHERE, // "TLK_PLAYER_TELEPORTERHERE" - MP_CONCEPT_PLAYER_DISPENSERHERE, // "TLK_PLAYER_DISPENSERHERE" - MP_CONCEPT_PLAYER_SENTRYHERE, // "TLK_PLAYER_SENTRYHERE" - MP_CONCEPT_PLAYER_ACTIVATECHARGE, // "TLK_PLAYER_ACTIVATECHARGE" - MP_CONCEPT_PLAYER_CHARGEREADY, // "TLK_PLAYER_CHARGEREADY" - MP_CONCEPT_PLAYER_TAUNTS, // "TLK_PLAYER_TAUNTS" - MP_CONCEPT_PLAYER_BATTLECRY, // "TLK_PLAYER_BATTLECRY" - MP_CONCEPT_PLAYER_CHEERS, // "TLK_PLAYER_CHEERS" - MP_CONCEPT_PLAYER_JEERS, // "TLK_PLAYER_JEERS" - MP_CONCEPT_PLAYER_POSITIVE, // "TLK_PLAYER_POSITIVE" - MP_CONCEPT_PLAYER_NEGATIVE, // "TLK_PLAYER_NEGATIVE" - MP_CONCEPT_PLAYER_NICESHOT, // "TLK_PLAYER_NICESHOT" - MP_CONCEPT_PLAYER_GOODJOB, // "TLK_PLAYER_GOODJOB" - MP_CONCEPT_MEDIC_STARTEDHEALING, // "TLK_MEDIC_STARTEDHEALING" - MP_CONCEPT_MEDIC_CHARGEREADY, // "TLK_MEDIC_CHARGEREADY" - MP_CONCEPT_MEDIC_STOPPEDHEALING, // "TLK_MEDIC_STOPPEDHEALING" - MP_CONCEPT_MEDIC_CHARGEDEPLOYED, // "TLK_MEDIC_CHARGEDEPLOYED" - MP_CONCEPT_FLAGPICKUP, // "TLK_FLAGPICKUP" - MP_CONCEPT_FLAGCAPTURED, // "TLK_FLAGCAPTURED" - MP_CONCEPT_ROUND_START, // "TLK_ROUND_START" - MP_CONCEPT_SUDDENDEATH_START, // "TLK_SUDDENDEATH_START" - MP_CONCEPT_ONFIRE, // "TLK_ONFIRE" - MP_CONCEPT_STALEMATE, // "TLK_STALEMATE" - MP_CONCEPT_BUILDING_OBJECT, // "TLK_BUILDING_OBJECT" - MP_CONCEPT_LOST_OBJECT, // "TLK_LOST_OBJECT" - MP_CONCEPT_SPY_SAPPER, // "TLK_SPY_SAPPER" - MP_CONCEPT_TELEPORTED, // "TLK_TELEPORTED" - MP_CONCEPT_LOST_CONTROL_POINT, // "TLK_LOST_CONTROL_POINT" - MP_CONCEPT_CAPTURED_POINT, // "TLK_CAPTURED_POINT" - MP_CONCEPT_CAPTURE_BLOCKED, // "TLK_CAPTURE_BLOCKED" - MP_CONCEPT_HEALTARGET_STARTEDHEALING, // "TLK_HEALTARGET_STARTEDHEALING" - MP_CONCEPT_HEALTARGET_CHARGEREADY, // "TLK_HEALTARGET_CHARGEREADY" - MP_CONCEPT_HEALTARGET_STOPPEDHEALING, // "TLK_HEALTARGET_STOPPEDHEALING" - MP_CONCEPT_HEALTARGET_CHARGEDEPLOYED, // "TLK_HEALTARGET_CHARGEDEPLOYED" - MP_CONCEPT_MINIGUN_FIREWEAPON, // "TLK_MINIGUN_FIREWEAPON" - MP_CONCEPT_DIED, // "TLK_DIED" - MP_CONCEPT_PLAYER_THANKS, // "TLK_PLAYER_THANKS" - MP_CONCEPT_CART_MOVING_FORWARD, // "TLK_CART_MOVING_FORWARD" - MP_CONCEPT_CART_MOVING_BACKWARD, // "TLK_CART_MOVING_BACKWARD" - MP_CONCEPT_CART_STOP, // "TLK_CART_STOP" - MP_TF_CONCEPT_COUNT - - // Other MP_CONCEPT_* start he using MP_TF_CONCEPT_COUNT + 1 as start. -}; - -extern const char *g_pszMPConcepts[]; -int GetMPConceptIndexFromString( const char *pszConcept ); - -#endif // MP_SHAREDDEFS_H diff --git a/game/shared/multiplay_gamerules.cpp b/game/shared/multiplay_gamerules.cpp deleted file mode 100644 index c81004ec7..000000000 --- a/game/shared/multiplay_gamerules.cpp +++ /dev/null @@ -1,1448 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Contains the implementation of game rules for multiplayer. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "multiplay_gamerules.h" -#include "viewport_panel_names.h" -#include "gameeventdefs.h" -#include -#include "filesystem.h" -#include "mp_shareddefs.h" - -#ifdef CLIENT_DLL - -#else - - #include "eventqueue.h" - #include "player.h" - #include "basecombatweapon.h" - #include "gamerules.h" - #include "game.h" - #include "items.h" - #include "entitylist.h" - #include "in_buttons.h" - #include - #include "voice_gamemgr.h" - #include "iscorer.h" - #include "hltvdirector.h" - #include "AI_Criteria.h" - #include "sceneentity.h" - #include "basemultiplayerplayer.h" - #include "team.h" - #include "usermessages.h" - #include "tier0/icommandline.h" - -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -REGISTER_GAMERULES_CLASS( CMultiplayRules ); - -ConVar mp_chattime( - "mp_chattime", - "10", - FCVAR_REPLICATED, - "amount of time players can chat after the game is over", - true, 1, - true, 120 ); - -#ifdef GAME_DLL -void MPTimeLimitCallback( IConVar *var, const char *pOldString, float flOldValue ) -{ - if ( mp_timelimit.GetInt() < 0 ) - { - mp_timelimit.SetValue( 0 ); - } - - if ( MultiplayRules() ) - { - MultiplayRules()->HandleTimeLimitChange(); - } -} -#endif - -ConVar mp_timelimit( "mp_timelimit", "0", FCVAR_NOTIFY|FCVAR_REPLICATED, "game time per map in minutes" -#ifdef GAME_DLL - , MPTimeLimitCallback -#endif - ); - -#ifdef GAME_DLL - -ConVar tv_delaymapchange( "tv_delaymapchange", "0", 0, "Delays map change until broadcast is complete" ); - -ConVar mp_restartgame( "mp_restartgame", "0", FCVAR_GAMEDLL, "If non-zero, game will restart in the specified number of seconds" ); - -#ifndef TF_DLL // TF overrides the default value of this convar -ConVar mp_waitingforplayers_time( "mp_waitingforplayers_time", "0", FCVAR_GAMEDLL, "WaitingForPlayers time length in seconds" ); -#endif - -ConVar mp_waitingforplayers_restart( "mp_waitingforplayers_restart", "0", FCVAR_GAMEDLL, "Set to 1 to start or restart the WaitingForPlayers period." ); -ConVar mp_waitingforplayers_cancel( "mp_waitingforplayers_cancel", "0", FCVAR_GAMEDLL, "Set to 1 to end the WaitingForPlayers period." ); -ConVar mp_clan_readyrestart( "mp_clan_readyrestart", "0", FCVAR_GAMEDLL, "If non-zero, game will restart once someone from each team gives the ready signal" ); -ConVar mp_clan_ready_signal( "mp_clan_ready_signal", "ready", FCVAR_GAMEDLL, "Text that team leader from each team must speak for the match to begin" ); - -ConVar nextlevel( "nextlevel", - "", - FCVAR_GAMEDLL | FCVAR_NOTIFY, -#if defined( CSTRIKE_DLL ) || defined( TF_DLL ) - "If set to a valid map name, will trigger a changelevel to the specified map at the end of the round" ); -#else - "If set to a valid map name, will change to this map during the next changelevel" ); -#endif // CSTRIKE_DLL || TF_DLL - -#endif - -#ifndef CLIENT_DLL -int CMultiplayRules::m_nMapCycleTimeStamp = 0; -int CMultiplayRules::m_nMapCycleindex = 0; -CUtlVector CMultiplayRules::m_MapList; -#endif - -//========================================================= -//========================================================= -bool CMultiplayRules::IsMultiplayer( void ) -{ - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CMultiplayRules::Damage_GetTimeBased( void ) -{ - int iDamage = ( DMG_PARALYZE | DMG_NERVEGAS | DMG_POISON | DMG_RADIATION | DMG_DROWNRECOVER | DMG_ACID | DMG_SLOWBURN ); - return iDamage; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CMultiplayRules::Damage_GetShouldGibCorpse( void ) -{ - int iDamage = ( DMG_CRUSH | DMG_FALL | DMG_BLAST | DMG_SONIC | DMG_CLUB ); - return iDamage; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CMultiplayRules::Damage_GetShowOnHud( void ) -{ - int iDamage = ( DMG_POISON | DMG_ACID | DMG_DROWN | DMG_BURN | DMG_SLOWBURN | DMG_NERVEGAS | DMG_RADIATION | DMG_SHOCK ); - return iDamage; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CMultiplayRules::Damage_GetNoPhysicsForce( void ) -{ - int iTimeBasedDamage = Damage_GetTimeBased(); - int iDamage = ( DMG_FALL | DMG_BURN | DMG_PLASMA | DMG_DROWN | iTimeBasedDamage | DMG_CRUSH | DMG_PHYSGUN | DMG_PREVENT_PHYSICS_FORCE ); - return iDamage; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CMultiplayRules::Damage_GetShouldNotBleed( void ) -{ - int iDamage = ( DMG_POISON | DMG_ACID ); - return iDamage; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iDmgType - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CMultiplayRules::Damage_IsTimeBased( int iDmgType ) -{ - // Damage types that are time-based. - return ( ( iDmgType & ( DMG_PARALYZE | DMG_NERVEGAS | DMG_POISON | DMG_RADIATION | DMG_DROWNRECOVER | DMG_ACID | DMG_SLOWBURN ) ) != 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iDmgType - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CMultiplayRules::Damage_ShouldGibCorpse( int iDmgType ) -{ - // Damage types that gib the corpse. - return ( ( iDmgType & ( DMG_CRUSH | DMG_FALL | DMG_BLAST | DMG_SONIC | DMG_CLUB ) ) != 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iDmgType - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CMultiplayRules::Damage_ShowOnHUD( int iDmgType ) -{ - // Damage types that have client HUD art. - return ( ( iDmgType & ( DMG_POISON | DMG_ACID | DMG_DROWN | DMG_BURN | DMG_SLOWBURN | DMG_NERVEGAS | DMG_RADIATION | DMG_SHOCK ) ) != 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iDmgType - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CMultiplayRules::Damage_NoPhysicsForce( int iDmgType ) -{ - // Damage types that don't have to supply a physics force & position. - int iTimeBasedDamage = Damage_GetTimeBased(); - return ( ( iDmgType & ( DMG_FALL | DMG_BURN | DMG_PLASMA | DMG_DROWN | iTimeBasedDamage | DMG_CRUSH | DMG_PHYSGUN | DMG_PREVENT_PHYSICS_FORCE ) ) != 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iDmgType - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CMultiplayRules::Damage_ShouldNotBleed( int iDmgType ) -{ - // Damage types that don't make the player bleed. - return ( ( iDmgType & ( DMG_POISON | DMG_ACID ) ) != 0 ); -} - -//********************************************************* -// Rules for the half-life multiplayer game. -//********************************************************* -CMultiplayRules::CMultiplayRules() -{ -#ifndef CLIENT_DLL - RefreshSkillData( true ); - - // 11/8/98 - // Modified by YWB: Server .cfg file is now a cvar, so that - // server ops can run multiple game servers, with different server .cfg files, - // from a single installed directory. - // Mapcyclefile is already a cvar. - - // 3/31/99 - // Added lservercfg file cvar, since listen and dedicated servers should not - // share a single config file. (sjb) - if ( engine->IsDedicatedServer() ) - { - // dedicated server - const char *cfgfile = servercfgfile.GetString(); - - if ( cfgfile && cfgfile[0] ) - { - char szCommand[256]; - - Msg( "Executing dedicated server config file\n" ); - Q_snprintf( szCommand,sizeof(szCommand), "exec %s\n", cfgfile ); - engine->ServerCommand( szCommand ); - } - } - else - { - // listen server - const char *cfgfile = lservercfgfile.GetString(); - - if ( cfgfile && cfgfile[0] ) - { - char szCommand[256]; - - Msg( "Executing listen server config file\n" ); - Q_snprintf( szCommand,sizeof(szCommand), "exec %s\n", cfgfile ); - engine->ServerCommand( szCommand ); - } - } - - nextlevel.SetValue( "" ); -#endif - - LoadVoiceCommandScript(); -} - -bool CMultiplayRules::Init() -{ -#ifdef GAME_DLL - - // Initialize the custom response rule dictionaries. - InitCustomResponseRulesDicts(); - -#endif - - return BaseClass::Init(); -} - - -#ifdef CLIENT_DLL - - -#else - - extern bool g_fGameOver; - - #define ITEM_RESPAWN_TIME 30 - #define WEAPON_RESPAWN_TIME 20 - #define AMMO_RESPAWN_TIME 20 - - //========================================================= - //========================================================= - void CMultiplayRules::RefreshSkillData( bool forceUpdate ) - { - // load all default values - BaseClass::RefreshSkillData( forceUpdate ); - - // override some values for multiplay. - - // suitcharger -#ifndef TF_DLL - ConVarRef suitcharger( "sk_suitcharger" ); - suitcharger.SetValue( 30 ); -#endif - } - - - //========================================================= - //========================================================= - void CMultiplayRules::Think ( void ) - { - BaseClass::Think(); - - ///// Check game rules ///// - - if ( g_fGameOver ) // someone else quit the game already - { - ChangeLevel(); // intermission is over - return; - } - - float flTimeLimit = mp_timelimit.GetFloat() * 60; - float flFragLimit = fraglimit.GetFloat(); - - if ( flTimeLimit != 0 && gpGlobals->curtime >= flTimeLimit ) - { - GoToIntermission(); - return; - } - - if ( flFragLimit ) - { - // check if any player is over the frag limit - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - - if ( pPlayer && pPlayer->FragCount() >= flFragLimit ) - { - GoToIntermission(); - return; - } - } - } - } - - - //========================================================= - //========================================================= - bool CMultiplayRules::IsDeathmatch( void ) - { - return true; - } - - //========================================================= - //========================================================= - bool CMultiplayRules::IsCoOp( void ) - { - return false; - } - - //========================================================= - //========================================================= - bool CMultiplayRules::FShouldSwitchWeapon( CBasePlayer *pPlayer, CBaseCombatWeapon *pWeapon ) - { - if ( !pPlayer->Weapon_CanSwitchTo( pWeapon ) ) - { - // Can't switch weapons for some reason. - return false; - } - - if ( !pPlayer->GetActiveWeapon() ) - { - // Player doesn't have an active item, might as well switch. - return true; - } - - if ( !pWeapon->AllowsAutoSwitchTo() ) - { - // The given weapon should not be auto switched to from another weapon. - return false; - } - - if ( !pPlayer->GetActiveWeapon()->AllowsAutoSwitchFrom() ) - { - // The active weapon does not allow autoswitching away from it. - return false; - } - - if ( pWeapon->GetWeight() > pPlayer->GetActiveWeapon()->GetWeight() ) - { - return true; - } - - return false; - } - - //----------------------------------------------------------------------------- - // Purpose: Returns the weapon in the player's inventory that would be better than - // the given weapon. - //----------------------------------------------------------------------------- - CBaseCombatWeapon *CMultiplayRules::GetNextBestWeapon( CBaseCombatCharacter *pPlayer, CBaseCombatWeapon *pCurrentWeapon ) - { - CBaseCombatWeapon *pCheck; - CBaseCombatWeapon *pBest;// this will be used in the event that we don't find a weapon in the same category. - - int iCurrentWeight = -1; - int iBestWeight = -1;// no weapon lower than -1 can be autoswitched to - pBest = NULL; - - // If I have a weapon, make sure I'm allowed to holster it - if ( pCurrentWeapon ) - { - if ( !pCurrentWeapon->AllowsAutoSwitchFrom() || !pCurrentWeapon->CanHolster() ) - { - // Either this weapon doesn't allow autoswitching away from it or I - // can't put this weapon away right now, so I can't switch. - return NULL; - } - - iCurrentWeight = pCurrentWeapon->GetWeight(); - } - - for ( int i = 0 ; i < pPlayer->WeaponCount(); ++i ) - { - pCheck = pPlayer->GetWeapon( i ); - if ( !pCheck ) - continue; - - // If we have an active weapon and this weapon doesn't allow autoswitching away - // from another weapon, skip it. - if ( pCurrentWeapon && !pCheck->AllowsAutoSwitchTo() ) - continue; - - if ( pCheck->GetWeight() > -1 && pCheck->GetWeight() == iCurrentWeight && pCheck != pCurrentWeapon ) - { - // this weapon is from the same category. - if ( pCheck->HasAnyAmmo() ) - { - if ( pPlayer->Weapon_CanSwitchTo( pCheck ) ) - { - return pCheck; - } - } - } - else if ( pCheck->GetWeight() > iBestWeight && pCheck != pCurrentWeapon )// don't reselect the weapon we're trying to get rid of - { - //Msg( "Considering %s\n", STRING( pCheck->GetClassname() ); - // we keep updating the 'best' weapon just in case we can't find a weapon of the same weight - // that the player was using. This will end up leaving the player with his heaviest-weighted - // weapon. - if ( pCheck->HasAnyAmmo() ) - { - // if this weapon is useable, flag it as the best - iBestWeight = pCheck->GetWeight(); - pBest = pCheck; - } - } - } - - // if we make it here, we've checked all the weapons and found no useable - // weapon in the same catagory as the current weapon. - - // if pBest is null, we didn't find ANYTHING. Shouldn't be possible- should always - // at least get the crowbar, but ya never know. - return pBest; - } - - //----------------------------------------------------------------------------- - // Purpose: - // Output : Returns true on success, false on failure. - //----------------------------------------------------------------------------- - bool CMultiplayRules::SwitchToNextBestWeapon( CBaseCombatCharacter *pPlayer, CBaseCombatWeapon *pCurrentWeapon ) - { - CBaseCombatWeapon *pWeapon = GetNextBestWeapon( pPlayer, pCurrentWeapon ); - - if ( pWeapon != NULL ) - return pPlayer->Weapon_Switch( pWeapon ); - - return false; - } - - //========================================================= - //========================================================= - bool CMultiplayRules::ClientConnected( edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen ) - { - GetVoiceGameMgr()->ClientConnected( pEntity ); - return true; - } - - void CMultiplayRules::InitHUD( CBasePlayer *pl ) - { - } - - //========================================================= - //========================================================= - void CMultiplayRules::ClientDisconnected( edict_t *pClient ) - { - if ( pClient ) - { - CBasePlayer *pPlayer = (CBasePlayer *)CBaseEntity::Instance( pClient ); - - if ( pPlayer ) - { - FireTargets( "game_playerleave", pPlayer, pPlayer, USE_TOGGLE, 0 ); - - pPlayer->RemoveAllItems( true );// destroy all of the players weapons and items - - // Kill off view model entities - pPlayer->DestroyViewModels(); - - pPlayer->SetConnected( PlayerDisconnected ); - } - } - } - - //========================================================= - //========================================================= - float CMultiplayRules::FlPlayerFallDamage( CBasePlayer *pPlayer ) - { - int iFallDamage = (int)falldamage.GetFloat(); - - switch ( iFallDamage ) - { - case 1://progressive - pPlayer->m_Local.m_flFallVelocity -= PLAYER_MAX_SAFE_FALL_SPEED; - return pPlayer->m_Local.m_flFallVelocity * DAMAGE_FOR_FALL_SPEED; - break; - default: - case 0:// fixed - return 10; - break; - } - } - - //========================================================= - //========================================================= - bool CMultiplayRules::AllowDamage( CBaseEntity *pVictim, const CTakeDamageInfo &info ) - { - return true; - } - - //========================================================= - //========================================================= - bool CMultiplayRules::FPlayerCanTakeDamage( CBasePlayer *pPlayer, CBaseEntity *pAttacker ) - { - return true; - } - - //========================================================= - //========================================================= - void CMultiplayRules::PlayerThink( CBasePlayer *pPlayer ) - { - if ( g_fGameOver ) - { - // clear attack/use commands from player - pPlayer->m_afButtonPressed = 0; - pPlayer->m_nButtons = 0; - pPlayer->m_afButtonReleased = 0; - } - } - - //========================================================= - //========================================================= - void CMultiplayRules::PlayerSpawn( CBasePlayer *pPlayer ) - { - bool addDefault; - CBaseEntity *pWeaponEntity = NULL; - - pPlayer->EquipSuit(); - - addDefault = true; - - while ( (pWeaponEntity = gEntList.FindEntityByClassname( pWeaponEntity, "game_player_equip" )) != NULL) - { - pWeaponEntity->Touch( pPlayer ); - addDefault = false; - } - } - - //========================================================= - //========================================================= - bool CMultiplayRules::FPlayerCanRespawn( CBasePlayer *pPlayer ) - { - return true; - } - - //========================================================= - //========================================================= - float CMultiplayRules::FlPlayerSpawnTime( CBasePlayer *pPlayer ) - { - return gpGlobals->curtime;//now! - } - - bool CMultiplayRules::AllowAutoTargetCrosshair( void ) - { - return ( aimcrosshair.GetInt() != 0 ); - } - - //========================================================= - // IPointsForKill - how many points awarded to anyone - // that kills this player? - //========================================================= - int CMultiplayRules::IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *pKilled ) - { - return 1; - } - - //----------------------------------------------------------------------------- - // Purpose: - //----------------------------------------------------------------------------- - CBasePlayer *CMultiplayRules::GetDeathScorer( CBaseEntity *pKiller, CBaseEntity *pInflictor ) - { - if ( pKiller) - { - if ( pKiller->Classify() == CLASS_PLAYER ) - return (CBasePlayer*)pKiller; - - // Killing entity might be specifying a scorer player - IScorer *pScorerInterface = dynamic_cast( pKiller ); - if ( pScorerInterface ) - { - CBasePlayer *pPlayer = pScorerInterface->GetScorer(); - if ( pPlayer ) - return pPlayer; - } - - // Inflicting entity might be specifying a scoring player - pScorerInterface = dynamic_cast( pInflictor ); - if ( pScorerInterface ) - { - CBasePlayer *pPlayer = pScorerInterface->GetScorer(); - if ( pPlayer ) - return pPlayer; - } - } - - return NULL; - } - - //----------------------------------------------------------------------------- - // Purpose: Returns player who should receive credit for kill - //----------------------------------------------------------------------------- - CBasePlayer *CMultiplayRules::GetDeathScorer( CBaseEntity *pKiller, CBaseEntity *pInflictor, CBaseEntity *pVictim ) - { - // if this method not overridden by subclass, just call our default implementation - return GetDeathScorer( pKiller, pInflictor ); - } - - //========================================================= - // PlayerKilled - someone/something killed this player - //========================================================= - void CMultiplayRules::PlayerKilled( CBasePlayer *pVictim, const CTakeDamageInfo &info ) - { - DeathNotice( pVictim, info ); - - // Find the killer & the scorer - CBaseEntity *pInflictor = info.GetInflictor(); - CBaseEntity *pKiller = info.GetAttacker(); - CBasePlayer *pScorer = GetDeathScorer( pKiller, pInflictor, pVictim ); - - pVictim->IncrementDeathCount( 1 ); - - // dvsents2: uncomment when removing all FireTargets - // variant_t value; - // g_EventQueue.AddEvent( "game_playerdie", "Use", value, 0, pVictim, pVictim ); - FireTargets( "game_playerdie", pVictim, pVictim, USE_TOGGLE, 0 ); - - // Did the player kill himself? - if ( pVictim == pScorer ) - { - if ( UseSuicidePenalty() ) - { - // Players lose a frag for killing themselves - pVictim->IncrementFragCount( -1 ); - } - } - else if ( pScorer ) - { - // if a player dies in a deathmatch game and the killer is a client, award the killer some points - pScorer->IncrementFragCount( IPointsForKill( pScorer, pVictim ) ); - - // Allow the scorer to immediately paint a decal - pScorer->AllowImmediateDecalPainting(); - - // dvsents2: uncomment when removing all FireTargets - //variant_t value; - //g_EventQueue.AddEvent( "game_playerkill", "Use", value, 0, pScorer, pScorer ); - FireTargets( "game_playerkill", pScorer, pScorer, USE_TOGGLE, 0 ); - } - else - { - if ( UseSuicidePenalty() ) - { - // Players lose a frag for letting the world kill them - pVictim->IncrementFragCount( -1 ); - } - } - } - - //========================================================= - // Deathnotice. - //========================================================= - void CMultiplayRules::DeathNotice( CBasePlayer *pVictim, const CTakeDamageInfo &info ) - { - // Work out what killed the player, and send a message to all clients about it - const char *killer_weapon_name = "world"; // by default, the player is killed by the world - int killer_ID = 0; - - // Find the killer & the scorer - CBaseEntity *pInflictor = info.GetInflictor(); - CBaseEntity *pKiller = info.GetAttacker(); - CBasePlayer *pScorer = GetDeathScorer( pKiller, pInflictor, pVictim ); - - // Custom damage type? - if ( info.GetDamageCustom() ) - { - killer_weapon_name = GetDamageCustomString( info ); - if ( pScorer ) - { - killer_ID = pScorer->GetUserID(); - } - } - else - { - // Is the killer a client? - if ( pScorer ) - { - killer_ID = pScorer->GetUserID(); - - if ( pInflictor ) - { - if ( pInflictor == pScorer ) - { - // If the inflictor is the killer, then it must be their current weapon doing the damage - if ( pScorer->GetActiveWeapon() ) - { - killer_weapon_name = pScorer->GetActiveWeapon()->GetDeathNoticeName(); - } - } - else - { - killer_weapon_name = STRING( pInflictor->m_iClassname ); // it's just that easy - } - } - } - else - { - killer_weapon_name = STRING( pInflictor->m_iClassname ); - } - - // strip the NPC_* or weapon_* from the inflictor's classname - if ( strncmp( killer_weapon_name, "weapon_", 7 ) == 0 ) - { - killer_weapon_name += 7; - } - else if ( strncmp( killer_weapon_name, "NPC_", 8 ) == 0 ) - { - killer_weapon_name += 8; - } - else if ( strncmp( killer_weapon_name, "func_", 5 ) == 0 ) - { - killer_weapon_name += 5; - } - } - - IGameEvent * event = gameeventmanager->CreateEvent( "player_death" ); - if ( event ) - { - event->SetInt("userid", pVictim->GetUserID() ); - event->SetInt("attacker", killer_ID ); - event->SetInt("customkill", info.GetDamageCustom() ); - event->SetInt("priority", 7 ); // HLTV event priority, not transmitted - - gameeventmanager->FireEvent( event ); - } - - } - - //========================================================= - // FlWeaponRespawnTime - what is the time in the future - // at which this weapon may spawn? - //========================================================= - float CMultiplayRules::FlWeaponRespawnTime( CBaseCombatWeapon *pWeapon ) - { - if ( weaponstay.GetInt() > 0 ) - { - // make sure it's only certain weapons - if ( !(pWeapon->GetWeaponFlags() & ITEM_FLAG_LIMITINWORLD) ) - { - return gpGlobals->curtime + 0; // weapon respawns almost instantly - } - } - - return gpGlobals->curtime + WEAPON_RESPAWN_TIME; - } - - // when we are within this close to running out of entities, items - // marked with the ITEM_FLAG_LIMITINWORLD will delay their respawn - #define ENTITY_INTOLERANCE 100 - - //========================================================= - // FlWeaponRespawnTime - Returns 0 if the weapon can respawn - // now, otherwise it returns the time at which it can try - // to spawn again. - //========================================================= - float CMultiplayRules::FlWeaponTryRespawn( CBaseCombatWeapon *pWeapon ) - { - if ( pWeapon && (pWeapon->GetWeaponFlags() & ITEM_FLAG_LIMITINWORLD) ) - { - if ( gEntList.NumberOfEntities() < (gpGlobals->maxEntities - ENTITY_INTOLERANCE) ) - return 0; - - // we're past the entity tolerance level, so delay the respawn - return FlWeaponRespawnTime( pWeapon ); - } - - return 0; - } - - //========================================================= - // VecWeaponRespawnSpot - where should this weapon spawn? - // Some game variations may choose to randomize spawn locations - //========================================================= - Vector CMultiplayRules::VecWeaponRespawnSpot( CBaseCombatWeapon *pWeapon ) - { - return pWeapon->GetAbsOrigin(); - } - - //========================================================= - // WeaponShouldRespawn - any conditions inhibiting the - // respawning of this weapon? - //========================================================= - int CMultiplayRules::WeaponShouldRespawn( CBaseCombatWeapon *pWeapon ) - { - if ( pWeapon->HasSpawnFlags( SF_NORESPAWN ) ) - { - return GR_WEAPON_RESPAWN_NO; - } - - return GR_WEAPON_RESPAWN_YES; - } - - //========================================================= - // CanHaveWeapon - returns false if the player is not allowed - // to pick up this weapon - //========================================================= - bool CMultiplayRules::CanHavePlayerItem( CBasePlayer *pPlayer, CBaseCombatWeapon *pItem ) - { - if ( weaponstay.GetInt() > 0 ) - { - if ( pItem->GetWeaponFlags() & ITEM_FLAG_LIMITINWORLD ) - return BaseClass::CanHavePlayerItem( pPlayer, pItem ); - - // check if the player already has this weapon - for ( int i = 0 ; i < pPlayer->WeaponCount() ; i++ ) - { - if ( pPlayer->GetWeapon(i) == pItem ) - { - return false; - } - } - } - - return BaseClass::CanHavePlayerItem( pPlayer, pItem ); - } - - //========================================================= - //========================================================= - bool CMultiplayRules::CanHaveItem( CBasePlayer *pPlayer, CItem *pItem ) - { - return true; - } - - //========================================================= - //========================================================= - void CMultiplayRules::PlayerGotItem( CBasePlayer *pPlayer, CItem *pItem ) - { - } - - //========================================================= - //========================================================= - int CMultiplayRules::ItemShouldRespawn( CItem *pItem ) - { - if ( pItem->HasSpawnFlags( SF_NORESPAWN ) ) - { - return GR_ITEM_RESPAWN_NO; - } - - return GR_ITEM_RESPAWN_YES; - } - - - //========================================================= - // At what time in the future may this Item respawn? - //========================================================= - float CMultiplayRules::FlItemRespawnTime( CItem *pItem ) - { - return gpGlobals->curtime + ITEM_RESPAWN_TIME; - } - - //========================================================= - // Where should this item respawn? - // Some game variations may choose to randomize spawn locations - //========================================================= - Vector CMultiplayRules::VecItemRespawnSpot( CItem *pItem ) - { - return pItem->GetAbsOrigin(); - } - - //========================================================= - // What angles should this item use to respawn? - //========================================================= - QAngle CMultiplayRules::VecItemRespawnAngles( CItem *pItem ) - { - return pItem->GetAbsAngles(); - } - - //========================================================= - //========================================================= - void CMultiplayRules::PlayerGotAmmo( CBaseCombatCharacter *pPlayer, char *szName, int iCount ) - { - } - - //========================================================= - //========================================================= - bool CMultiplayRules::IsAllowedToSpawn( CBaseEntity *pEntity ) - { - // if ( pEntity->GetFlags() & FL_NPC ) - // return false; - - return true; - } - - - //========================================================= - //========================================================= - float CMultiplayRules::FlHealthChargerRechargeTime( void ) - { - return 60; - } - - - float CMultiplayRules::FlHEVChargerRechargeTime( void ) - { - return 30; - } - - //========================================================= - //========================================================= - int CMultiplayRules::DeadPlayerWeapons( CBasePlayer *pPlayer ) - { - return GR_PLR_DROP_GUN_ACTIVE; - } - - //========================================================= - //========================================================= - int CMultiplayRules::DeadPlayerAmmo( CBasePlayer *pPlayer ) - { - return GR_PLR_DROP_AMMO_ACTIVE; - } - - CBaseEntity *CMultiplayRules::GetPlayerSpawnSpot( CBasePlayer *pPlayer ) - { - CBaseEntity *pentSpawnSpot = BaseClass::GetPlayerSpawnSpot( pPlayer ); - - //!! replace this with an Event - /* - if ( IsMultiplayer() && pentSpawnSpot->m_target ) - { - FireTargets( STRING(pentSpawnSpot->m_target), pPlayer, pPlayer, USE_TOGGLE, 0 ); // dvsents2: what is this code supposed to do? - } - */ - - return pentSpawnSpot; - } - - - //========================================================= - //========================================================= - bool CMultiplayRules::PlayerCanHearChat( CBasePlayer *pListener, CBasePlayer *pSpeaker ) - { - return ( PlayerRelationship( pListener, pSpeaker ) == GR_TEAMMATE ); - } - - int CMultiplayRules::PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget ) - { - // half life deathmatch has only enemies - return GR_NOTTEAMMATE; - } - - bool CMultiplayRules::PlayFootstepSounds( CBasePlayer *pl ) - { - if ( footsteps.GetInt() == 0 ) - return false; - - if ( pl->IsOnLadder() || pl->GetAbsVelocity().Length2D() > 220 ) - return true; // only make step sounds in multiplayer if the player is moving fast enough - - return false; - } - - bool CMultiplayRules::FAllowFlashlight( void ) - { - return flashlight.GetInt() != 0; - } - - //========================================================= - //========================================================= - bool CMultiplayRules::FAllowNPCs( void ) - { - return true; // E3 hack - return ( allowNPCs.GetInt() != 0 ); - } - - //========================================================= - //======== CMultiplayRules private functions =========== - - void CMultiplayRules::GoToIntermission( void ) - { - if ( g_fGameOver ) - return; - - g_fGameOver = true; - - float flWaitTime = mp_chattime.GetInt(); - - if ( tv_delaymapchange.GetBool() && HLTVDirector()->IsActive() ) - { - flWaitTime = MAX ( flWaitTime, HLTVDirector()->GetDelay() ); - } - - m_flIntermissionEndTime = gpGlobals->curtime + flWaitTime; - - for ( int i = 1; i <= MAX_PLAYERS; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - - if ( !pPlayer ) - continue; - - pPlayer->ShowViewPortPanel( PANEL_SCOREBOARD ); - } - } - - void StripChar(char *szBuffer, const char cWhiteSpace ) - { - - while ( char *pSpace = strchr( szBuffer, cWhiteSpace ) ) - { - char *pNextChar = pSpace + sizeof(char); - V_strcpy( pSpace, pNextChar ); - } - } - - void CMultiplayRules::GetNextLevelName( char *pszNextMap, int bufsize, bool bRandom /* = false */ ) - { - const char *mapcfile = mapcyclefile.GetString(); - Assert( mapcfile != NULL ); - - // Check the time of the mapcycle file and re-populate the list of level names if the file has been modified - const int nMapCycleTimeStamp = filesystem->GetPathTime( mapcfile, "GAME" ); - - if ( 0 == nMapCycleTimeStamp ) - { - // Map cycle file does not exist, make a list containing only the current map - char *szCurrentMapName = new char[32]; - Q_strncpy( szCurrentMapName, STRING(gpGlobals->mapname), 32 ); - m_MapList.AddToTail( szCurrentMapName ); - } - else - { - // If map cycle file has changed or this is the first time through ... - if ( m_nMapCycleTimeStamp != nMapCycleTimeStamp ) - { - // Reset map index and map cycle timestamp - m_nMapCycleTimeStamp = nMapCycleTimeStamp; - m_nMapCycleindex = 0; - - // Clear out existing map list. Not using Purge() because I don't think that it will do a 'delete []' - for ( int i = 0; i < m_MapList.Count(); i++ ) - { - delete [] m_MapList[i]; - } - - m_MapList.RemoveAll(); - - // Repopulate map list from mapcycle file - int nFileLength; - char *aFileList = (char*)UTIL_LoadFileForMe( mapcfile, &nFileLength ); - if ( aFileList && nFileLength ) - { - V_SplitString( aFileList, "\n", m_MapList ); - - for ( int i = 0; i < m_MapList.Count(); i++ ) - { - bool bIgnore = false; - - // Strip out the spaces in the name - StripChar( m_MapList[i] , '\r'); - StripChar( m_MapList[i] , ' '); - - if ( !engine->IsMapValid( m_MapList[i] ) ) - { - bIgnore = true; - - // If the engine doesn't consider it a valid map remove it from the lists - char szWarningMessage[MAX_PATH]; - V_snprintf( szWarningMessage, MAX_PATH, "Invalid map '%s' included in map cycle file. Ignored.\n", m_MapList[i] ); - Warning( szWarningMessage ); - } - else if ( !Q_strncmp( m_MapList[i], "//", 2 ) ) - { - bIgnore = true; - } - - if ( bIgnore ) - { - delete [] m_MapList[i]; - m_MapList.Remove( i ); - --i; - } - } - - UTIL_FreeFile( (byte *)aFileList ); - } - } - } - - // If somehow we have no maps in the list then add the current one - if ( 0 == m_MapList.Count() ) - { - char *szDefaultMapName = new char[32]; - Q_strncpy( szDefaultMapName, STRING(gpGlobals->mapname), 32 ); - m_MapList.AddToTail( szDefaultMapName ); - } - - if ( bRandom ) - { - m_nMapCycleindex = RandomInt( 0, m_MapList.Count() - 1 ); - } - - // Here's the return value - Q_strncpy( pszNextMap, m_MapList[m_nMapCycleindex], bufsize); - } - - void CMultiplayRules::ChangeLevel( void ) - { - char szNextMap[32]; - - if ( nextlevel.GetString() && *nextlevel.GetString() && engine->IsMapValid( nextlevel.GetString() ) ) - { - Q_strncpy( szNextMap, nextlevel.GetString(), sizeof( szNextMap ) ); - } - else - { - GetNextLevelName( szNextMap, sizeof(szNextMap) ); - IncrementMapCycleIndex(); - } - - g_fGameOver = true; - Msg( "CHANGE LEVEL: %s\n", szNextMap ); - engine->ChangeLevel( szNextMap, NULL ); - } - -#endif - - - //----------------------------------------------------------------------------- - // Purpose: Shared script resource of voice menu commands and hud strings - //----------------------------------------------------------------------------- - void CMultiplayRules::LoadVoiceCommandScript( void ) - { - KeyValues *pKV = new KeyValues( "VoiceCommands" ); - - if ( pKV->LoadFromFile( filesystem, "scripts/voicecommands.txt", "GAME" ) ) - { - for ( KeyValues *menu = pKV->GetFirstSubKey(); menu != NULL; menu = menu->GetNextKey() ) - { - int iMenuIndex = m_VoiceCommandMenus.AddToTail(); - - int iNumItems = 0; - - // for each subkey of this menu, add a menu item - for ( KeyValues *menuitem = menu->GetFirstSubKey(); menuitem != NULL; menuitem = menuitem->GetNextKey() ) - { - iNumItems++; - - if ( iNumItems > 9 ) - { - Warning( "Trying to load more than 9 menu items in voicecommands.txt, extras ignored" ); - continue; - } - - VoiceCommandMenuItem_t item; - -#ifndef CLIENT_DLL - int iConcept = GetMPConceptIndexFromString( menuitem->GetString( "concept", "" ) ); - if ( iConcept == MP_CONCEPT_NONE ) - { - Warning( "Voicecommand script attempting to use unknown concept. Need to define new concepts in code. ( %s )\n", menuitem->GetString( "concept", "" ) ); - } - item.m_iConcept = iConcept; - - item.m_bShowSubtitle = ( menuitem->GetInt( "show_subtitle", 0 ) > 0 ); - item.m_bDistanceBasedSubtitle = ( menuitem->GetInt( "distance_check_subtitle", 0 ) > 0 ); - - Q_strncpy( item.m_szGestureActivity, menuitem->GetString( "activity", "" ), sizeof( item.m_szGestureActivity ) ); -#else - Q_strncpy( item.m_szSubtitle, menuitem->GetString( "subtitle", "" ), MAX_VOICE_COMMAND_SUBTITLE ); - Q_strncpy( item.m_szMenuLabel, menuitem->GetString( "menu_label", "" ), MAX_VOICE_COMMAND_SUBTITLE ); - -#endif - m_VoiceCommandMenus.Element( iMenuIndex ).AddToTail( item ); - } - } - } - - pKV->deleteThis(); - } - -#ifndef CLIENT_DLL - void CMultiplayRules::IncrementMapCycleIndex() - { - // Reset index if we've passed the end of the map list - if ( ++m_nMapCycleindex >= m_MapList.Count() ) - { - m_nMapCycleindex = 0; - } - } - - bool CMultiplayRules::ClientCommand( CBaseEntity *pEdict, const CCommand &args ) - { - CBasePlayer *pPlayer = ToBasePlayer( pEdict ); - - const char *pcmd = args[0]; - if ( FStrEq( pcmd, "voicemenu" ) ) - { - if ( args.ArgC() < 3 ) - return true; - - CBaseMultiplayerPlayer *pMultiPlayerPlayer = dynamic_cast< CBaseMultiplayerPlayer * >( pPlayer ); - - if ( pMultiPlayerPlayer ) - { - int iMenu = atoi( args[1] ); - int iItem = atoi( args[2] ); - - VoiceCommand( pMultiPlayerPlayer, iMenu, iItem ); - } - - return true; - } - else if ( FStrEq( pcmd, "achievement_earned" ) ) - { - CBaseMultiplayerPlayer *pPlayer = static_cast( pEdict ); - if ( pPlayer && pPlayer->ShouldAnnounceAchievement() ) - { - // let's check this came from the client .dll and not the console - unsigned short mask = UTIL_GetAchievementEventMask(); - int iPlayerID = pPlayer->GetUserID(); - - int iAchievement = atoi( args[1] ) ^ mask; - int code = ( iPlayerID ^ iAchievement ) ^ mask; - - if ( code == atoi( args[2] ) ) - { - IGameEvent * event = gameeventmanager->CreateEvent( "achievement_earned" ); - if ( event ) - { - event->SetInt( "player", pEdict->entindex() ); - event->SetInt( "achievement", iAchievement ); - gameeventmanager->FireEvent( event ); - } - - pPlayer->OnAchievementEarned( iAchievement ); - } - } - - return true; - } - - return BaseClass::ClientCommand( pEdict, args ); - - } - - VoiceCommandMenuItem_t *CMultiplayRules::VoiceCommand( CBaseMultiplayerPlayer *pPlayer, int iMenu, int iItem ) - { - // have the player speak the concept that is in a particular menu slot - if ( !pPlayer ) - return NULL; - - if ( iMenu < 0 || iMenu >= m_VoiceCommandMenus.Count() ) - return NULL; - - if ( iItem < 0 || iItem >= m_VoiceCommandMenus.Element( iMenu ).Count() ) - return NULL; - - VoiceCommandMenuItem_t *pItem = &m_VoiceCommandMenus.Element( iMenu ).Element( iItem ); - - Assert( pItem ); - - char szResponse[AI_Response::MAX_RESPONSE_NAME]; - - if ( pPlayer->CanSpeakVoiceCommand() ) - { - CMultiplayer_Expresser *pExpresser = pPlayer->GetMultiplayerExpresser(); - Assert( pExpresser ); - pExpresser->AllowMultipleScenes(); - - if ( pPlayer->SpeakConceptIfAllowed( pItem->m_iConcept, NULL, szResponse, AI_Response::MAX_RESPONSE_NAME ) ) - { - // show a subtitle if we need to - if ( pItem->m_bShowSubtitle ) - { - CRecipientFilter filter; - - if ( pItem->m_bDistanceBasedSubtitle ) - { - filter.AddRecipientsByPAS( pPlayer->WorldSpaceCenter() ); - - // further reduce the range to a certain radius - int i; - for ( i = filter.GetRecipientCount()-1; i >= 0; i-- ) - { - int index = filter.GetRecipientIndex(i); - - CBasePlayer *pListener = UTIL_PlayerByIndex( index ); - - if ( pListener && pListener != pPlayer ) - { - float flDist = ( pListener->WorldSpaceCenter() - pPlayer->WorldSpaceCenter() ).Length2D(); - - if ( flDist > VOICE_COMMAND_MAX_SUBTITLE_DIST ) - filter.RemoveRecipientByPlayerIndex( index ); - } - } - } - else - { - filter.AddAllPlayers(); - } - - // if we aren't a disguised spy - if ( !pPlayer->ShouldShowVoiceSubtitleToEnemy() ) - { - // remove players on other teams - filter.RemoveRecipientsNotOnTeam( pPlayer->GetTeam() ); - } - - // Register this event in the mod-specific usermessages .cpp file if you hit this assert - Assert( usermessages->LookupUserMessage( "VoiceSubtitle" ) != -1 ); - - // Send a subtitle to anyone in the PAS - UserMessageBegin( filter, "VoiceSubtitle" ); - WRITE_BYTE( pPlayer->entindex() ); - WRITE_BYTE( iMenu ); - WRITE_BYTE( iItem ); - MessageEnd(); - } - - pPlayer->NoteSpokeVoiceCommand( szResponse ); - } - else - { - pItem = NULL; - } - - pExpresser->DisallowMultipleScenes(); - return pItem; - } - - return NULL; - } - - bool CMultiplayRules::IsLoadingBugBaitReport() - { - return ( !engine->IsDedicatedServer()&& CommandLine()->CheckParm( "-bugbait" ) && sv_cheats->GetBool() ); - } - - void CMultiplayRules::HaveAllPlayersSpeakConceptIfAllowed( int iConcept ) - { - CBaseMultiplayerPlayer *pPlayer; - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - pPlayer = ToBaseMultiplayerPlayer( UTIL_PlayerByIndex( i ) ); - - if ( !pPlayer ) - continue; - - pPlayer->SpeakConceptIfAllowed( iConcept ); - } - } - - void CMultiplayRules::GetTaggedConVarList( KeyValues *pCvarTagList ) - { - BaseClass::GetTaggedConVarList( pCvarTagList ); - - KeyValues *pGravity = new KeyValues( "sv_gravity" ); - pGravity->SetString( "convar", "sv_gravity" ); - pGravity->SetString( "tag", "gravity" ); - - pCvarTagList->AddSubKey( pGravity ); - } - -#else - - const char *CMultiplayRules::GetVoiceCommandSubtitle( int iMenu, int iItem ) - { - Assert( iMenu >= 0 && iMenu < m_VoiceCommandMenus.Count() ); - if ( iMenu < 0 || iMenu >= m_VoiceCommandMenus.Count() ) - return ""; - - Assert( iItem >= 0 && iItem < m_VoiceCommandMenus.Element( iMenu ).Count() ); - if ( iItem < 0 || iItem >= m_VoiceCommandMenus.Element( iMenu ).Count() ) - return ""; - - VoiceCommandMenuItem_t *pItem = &m_VoiceCommandMenus.Element( iMenu ).Element( iItem ); - - Assert( pItem ); - - return pItem->m_szSubtitle; - } - - // Returns false if no such menu is declared or if it's an empty menu - bool CMultiplayRules::GetVoiceMenuLabels( int iMenu, KeyValues *pKV ) - { - Assert( iMenu >= 0 && iMenu < m_VoiceCommandMenus.Count() ); - if ( iMenu < 0 || iMenu >= m_VoiceCommandMenus.Count() ) - return false; - - int iNumItems = m_VoiceCommandMenus.Element( iMenu ).Count(); - - for ( int i=0; im_szMenuLabel ); - - pKV->AddSubKey( pLabelKV ); - } - - return iNumItems > 0; - } - -#endif diff --git a/game/shared/multiplay_gamerules.h b/game/shared/multiplay_gamerules.h deleted file mode 100644 index 901ee1042..000000000 --- a/game/shared/multiplay_gamerules.h +++ /dev/null @@ -1,242 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef MULTIPLAY_GAMERULES_H -#define MULTIPLAY_GAMERULES_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "gamerules.h" - - -#ifdef CLIENT_DLL - - #define CMultiplayRules C_MultiplayRules - -#else - -extern ConVar mp_restartgame; -extern ConVar mp_waitingforplayers_time; -extern ConVar mp_waitingforplayers_restart; -extern ConVar mp_waitingforplayers_cancel; -extern ConVar mp_clan_readyrestart; -extern ConVar mp_clan_ready_signal; -extern ConVar nextlevel; - -#define VOICE_COMMAND_MAX_SUBTITLE_DIST 1900 - -class CBaseMultiplayerPlayer; - -#endif - -#define MAX_SPEAK_CONCEPT_LEN 64 -#define MAX_VOICE_COMMAND_SUBTITLE 256 - -typedef struct -{ -#ifndef CLIENT_DLL - // concept to speak - int m_iConcept; - - // play subtitle? - bool m_bShowSubtitle; - bool m_bDistanceBasedSubtitle; - - char m_szGestureActivity[64]; - -#else - // localizable subtitle - char m_szSubtitle[MAX_VOICE_COMMAND_SUBTITLE]; - - // localizable string for menu - char m_szMenuLabel[MAX_VOICE_COMMAND_SUBTITLE]; -#endif - -} VoiceCommandMenuItem_t; - -extern ConVar mp_timelimit; - -//========================================================= -// CMultiplayRules - rules for the basic half life multiplayer -// competition -//========================================================= -class CMultiplayRules : public CGameRules -{ -public: - DECLARE_CLASS( CMultiplayRules, CGameRules ); - -// Functions to verify the single/multiplayer status of a game - virtual bool IsMultiplayer( void ); - - virtual bool Init(); - - // Damage query implementations. - virtual bool Damage_IsTimeBased( int iDmgType ); // Damage types that are time-based. - virtual bool Damage_ShouldGibCorpse( int iDmgType ); // Damage types that gib the corpse. - virtual bool Damage_ShowOnHUD( int iDmgType ); // Damage types that have client HUD art. - virtual bool Damage_NoPhysicsForce( int iDmgType ); // Damage types that don't have to supply a physics force & position. - virtual bool Damage_ShouldNotBleed( int iDmgType ); // Damage types that don't make the player bleed. - // TEMP: These will go away once DamageTypes become enums. - virtual int Damage_GetTimeBased( void ); - virtual int Damage_GetShouldGibCorpse( void ); - virtual int Damage_GetShowOnHud( void ); - virtual int Damage_GetNoPhysicsForce( void ); - virtual int Damage_GetShouldNotBleed( void ); - - CMultiplayRules(); - virtual ~CMultiplayRules() {} - - void LoadVoiceCommandScript( void ); - -#ifndef CLIENT_DLL - -// GR_Think - virtual void Think( void ); - virtual void RefreshSkillData( bool forceUpdate ); - virtual bool IsAllowedToSpawn( CBaseEntity *pEntity ); - virtual bool FAllowFlashlight( void ); - - virtual bool FShouldSwitchWeapon( CBasePlayer *pPlayer, CBaseCombatWeapon *pWeapon ); - virtual CBaseCombatWeapon *GetNextBestWeapon( CBaseCombatCharacter *pPlayer, CBaseCombatWeapon *pCurrentWeapon ); - bool SwitchToNextBestWeapon( CBaseCombatCharacter *pPlayer, CBaseCombatWeapon *pCurrentWeapon ); - -// Functions to verify the single/multiplayer status of a game - virtual bool IsDeathmatch( void ); - virtual bool IsCoOp( void ); - -// Client connection/disconnection - // If ClientConnected returns FALSE, the connection is rejected and the user is provided the reason specified in - // svRejectReason - // Only the client's name and remote address are provided to the dll for verification. - virtual bool ClientConnected( edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen ); - virtual void InitHUD( CBasePlayer *pl ); // the client dll is ready for updating - virtual void ClientDisconnected( edict_t *pClient ); - -// Client damage rules - virtual float FlPlayerFallDamage( CBasePlayer *pPlayer ); - virtual bool FPlayerCanTakeDamage( CBasePlayer *pPlayer, CBaseEntity *pAttacker ); - virtual bool AllowDamage( CBaseEntity *pVictim, const CTakeDamageInfo &info ); - -// Client spawn/respawn control - virtual void PlayerSpawn( CBasePlayer *pPlayer ); - virtual void PlayerThink( CBasePlayer *pPlayer ); - virtual bool FPlayerCanRespawn( CBasePlayer *pPlayer ); - virtual float FlPlayerSpawnTime( CBasePlayer *pPlayer ); - virtual CBaseEntity *GetPlayerSpawnSpot( CBasePlayer *pPlayer ); - - virtual bool AllowAutoTargetCrosshair( void ); - -// Client kills/scoring - virtual int IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *pKilled ); - virtual void PlayerKilled( CBasePlayer *pVictim, const CTakeDamageInfo &info ); - virtual void DeathNotice( CBasePlayer *pVictim, const CTakeDamageInfo &info ); - CBasePlayer *GetDeathScorer( CBaseEntity *pKiller, CBaseEntity *pInflictor ); // old version of method - kept for backward compat - virtual CBasePlayer *GetDeathScorer( CBaseEntity *pKiller, CBaseEntity *pInflictor, CBaseEntity *pVictim ); // new version of method - -// Weapon retrieval - virtual bool CanHavePlayerItem( CBasePlayer *pPlayer, CBaseCombatWeapon *pWeapon );// The player is touching an CBaseCombatWeapon, do I give it to him? - -// Weapon spawn/respawn control - virtual int WeaponShouldRespawn( CBaseCombatWeapon *pWeapon ); - virtual float FlWeaponRespawnTime( CBaseCombatWeapon *pWeapon ); - virtual float FlWeaponTryRespawn( CBaseCombatWeapon *pWeapon ); - virtual Vector VecWeaponRespawnSpot( CBaseCombatWeapon *pWeapon ); - -// Item retrieval - virtual bool CanHaveItem( CBasePlayer *pPlayer, CItem *pItem ); - virtual void PlayerGotItem( CBasePlayer *pPlayer, CItem *pItem ); - -// Item spawn/respawn control - virtual int ItemShouldRespawn( CItem *pItem ); - virtual float FlItemRespawnTime( CItem *pItem ); - virtual Vector VecItemRespawnSpot( CItem *pItem ); - virtual QAngle VecItemRespawnAngles( CItem *pItem ); - -// Ammo retrieval - virtual void PlayerGotAmmo( CBaseCombatCharacter *pPlayer, char *szName, int iCount ); - -// Healthcharger respawn control - virtual float FlHealthChargerRechargeTime( void ); - virtual float FlHEVChargerRechargeTime( void ); - -// What happens to a dead player's weapons - virtual int DeadPlayerWeapons( CBasePlayer *pPlayer ); - -// What happens to a dead player's ammo - virtual int DeadPlayerAmmo( CBasePlayer *pPlayer ); - -// Teamplay stuff - virtual const char *GetTeamID( CBaseEntity *pEntity ) {return "";} - virtual int PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget ); - virtual bool PlayerCanHearChat( CBasePlayer *pListener, CBasePlayer *pSpeaker ); - - virtual bool PlayTextureSounds( void ) { return FALSE; } - virtual bool PlayFootstepSounds( CBasePlayer *pl ); - -// NPCs - virtual bool FAllowNPCs( void ); - - // Immediately end a multiplayer game - virtual void EndMultiplayerGame( void ) { GoToIntermission(); } - -// Voice commands - virtual bool ClientCommand( CBaseEntity *pEdict, const CCommand &args ); - virtual VoiceCommandMenuItem_t *VoiceCommand( CBaseMultiplayerPlayer *pPlayer, int iMenu, int iItem ); - -// Bugbait report - bool IsLoadingBugBaitReport( void ); - - virtual void ResetMapCycleTimeStamp( void ){ m_nMapCycleTimeStamp = 0; } - - virtual void HandleTimeLimitChange( void ){ return; } - - void IncrementMapCycleIndex(); - - void HaveAllPlayersSpeakConceptIfAllowed( int iConcept ); - - virtual void GetTaggedConVarList( KeyValues *pCvarTagList ); - -public: - - struct ResponseRules_t - { - CUtlVector m_ResponseSystems; - }; - CUtlVector m_ResponseRules; - - virtual void InitCustomResponseRulesDicts() {} - virtual void ShutdownCustomResponseRulesDicts() {} - -protected: - virtual bool UseSuicidePenalty() { return true; } // apply point penalty for suicide? - virtual void GetNextLevelName( char *szNextMap, int bufsize, bool bRandom = false ); - virtual void ChangeLevel( void ); - virtual void GoToIntermission( void ); - float m_flIntermissionEndTime; - static int m_nMapCycleTimeStamp; - static int m_nMapCycleindex; - static CUtlVector m_MapList; - -#else - - public: - const char *GetVoiceCommandSubtitle( int iMenu, int iItem ); - bool GetVoiceMenuLabels( int iMenu, KeyValues *pKV ); - -#endif - - private: - CUtlVector< CUtlVector< VoiceCommandMenuItem_t > > m_VoiceCommandMenus; -}; - -inline CMultiplayRules* MultiplayRules() -{ - return static_cast(g_pGameRules); -} - -#endif // MULTIPLAY_GAMERULES_H diff --git a/game/shared/npcevent.h b/game/shared/npcevent.h deleted file mode 100644 index 241c417c7..000000000 --- a/game/shared/npcevent.h +++ /dev/null @@ -1,77 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef NPCEVENT_H -#define NPCEVENT_H -#ifdef _WIN32 -#pragma once -#endif - -class CBaseAnimating; - -struct animevent_t -{ - int event; - const char *options; - float cycle; - float eventtime; - int type; - CBaseAnimating *pSource; -}; -#define EVENT_SPECIFIC 0 -#define EVENT_SCRIPTED 1000 // see scriptevent.h -#define EVENT_SHARED 2000 -#define EVENT_WEAPON 3000 -#define EVENT_CLIENT 5000 - -#define NPC_EVENT_BODYDROP_LIGHT 2001 -#define NPC_EVENT_BODYDROP_HEAVY 2002 - -#define NPC_EVENT_SWISHSOUND 2010 - -#define NPC_EVENT_180TURN 2020 - -#define NPC_EVENT_ITEM_PICKUP 2040 -#define NPC_EVENT_WEAPON_DROP 2041 -#define NPC_EVENT_WEAPON_SET_SEQUENCE_NAME 2042 -#define NPC_EVENT_WEAPON_SET_SEQUENCE_NUMBER 2043 -#define NPC_EVENT_WEAPON_SET_ACTIVITY 2044 - -#define NPC_EVENT_LEFTFOOT 2050 -#define NPC_EVENT_RIGHTFOOT 2051 - -#define NPC_EVENT_OPEN_DOOR 2060 - -// !! DON'T CHANGE TO ORDER OF THESE. THEY ARE HARD CODED IN THE WEAPON QC FILES (YUCK!) !! -#define EVENT_WEAPON_MELEE_HIT 3001 -#define EVENT_WEAPON_SMG1 3002 -#define EVENT_WEAPON_MELEE_SWISH 3003 -#define EVENT_WEAPON_SHOTGUN_FIRE 3004 -#define EVENT_WEAPON_THROW 3005 -#define EVENT_WEAPON_AR1 3006 -#define EVENT_WEAPON_AR2 3007 -#define EVENT_WEAPON_HMG1 3008 -#define EVENT_WEAPON_SMG2 3009 -#define EVENT_WEAPON_MISSILE_FIRE 3010 -#define EVENT_WEAPON_SNIPER_RIFLE_FIRE 3011 -#define EVENT_WEAPON_AR2_GRENADE 3012 -#define EVENT_WEAPON_THROW2 3013 -#define EVENT_WEAPON_PISTOL_FIRE 3014 -#define EVENT_WEAPON_RELOAD 3015 -#define EVENT_WEAPON_THROW3 3016 -#define EVENT_WEAPON_RELOAD_SOUND 3017 // Use this + EVENT_WEAPON_RELOAD_FILL_CLIP to prevent shooting during the reload animation -#define EVENT_WEAPON_RELOAD_FILL_CLIP 3018 -#define EVENT_WEAPON_SMG1_BURST1 3101 // first round in a 3-round burst -#define EVENT_WEAPON_SMG1_BURSTN 3102 // 2, 3 rounds -#define EVENT_WEAPON_AR2_ALTFIRE 3103 - -#define EVENT_WEAPON_SEQUENCE_FINISHED 3900 - -// NOTE: MUST BE THE LAST WEAPON EVENT -- ONLY WEAPON EVENTS BETWEEN EVENT_WEAPON AND THIS -#define EVENT_WEAPON_LAST 3999 - -#endif // NPCEVENT_H diff --git a/game/shared/obstacle_pushaway.cpp b/game/shared/obstacle_pushaway.cpp deleted file mode 100644 index 97d5cba60..000000000 --- a/game/shared/obstacle_pushaway.cpp +++ /dev/null @@ -1,329 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "obstacle_pushaway.h" -#include "props_shared.h" - -//----------------------------------------------------------------------------------------------------- -ConVar sv_pushaway_force( "sv_pushaway_force", "30000", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "How hard physics objects are pushed away from the players on the server." ); -ConVar sv_pushaway_min_player_speed( "sv_pushaway_min_player_speed", "75", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "If a player is moving slower than this, don't push away physics objects (enables ducking behind things)." ); -ConVar sv_pushaway_max_force( "sv_pushaway_max_force", "1000", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Maximum amount of force applied to physics objects by players." ); -ConVar sv_pushaway_clientside( "sv_pushaway_clientside", "0", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Clientside physics push away (0=off, 1=only localplayer, 1=all players)" ); - -ConVar sv_pushaway_player_force( "sv_pushaway_player_force", "200000", FCVAR_REPLICATED | FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "How hard the player is pushed away from physics objects (falls off with inverse square of distance)." ); -ConVar sv_pushaway_max_player_force( "sv_pushaway_max_player_force", "10000", FCVAR_REPLICATED | FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "Maximum of how hard the player is pushed away from physics objects." ); - -#ifdef CLIENT_DLL -ConVar sv_turbophysics( "sv_turbophysics", "0", FCVAR_REPLICATED, "Turns on turbo physics" ); -#else -extern ConVar sv_turbophysics; -#endif - -//----------------------------------------------------------------------------------------------------- -bool IsPushAwayEntity( CBaseEntity *pEnt ) -{ - if ( pEnt == NULL ) - return false; - - if ( pEnt->GetCollisionGroup() != COLLISION_GROUP_PUSHAWAY ) - { - // Try backing away from doors that are currently rotating, to prevent blocking them -#ifndef CLIENT_DLL - if ( FClassnameIs( pEnt, "func_door_rotating" ) ) - { - CBaseDoor *door = dynamic_cast(pEnt); - if ( !door ) - { - return false; - } - - if ( door->m_toggle_state != TS_GOING_UP && door->m_toggle_state != TS_GOING_DOWN ) - { - return false; - } - } - else if ( FClassnameIs( pEnt, "prop_door_rotating" ) ) - { - CBasePropDoor *door = dynamic_cast(pEnt); - if ( !door ) - { - return false; - } - - if ( !door->IsDoorOpening() && !door->IsDoorClosing() ) - { - return false; - } - } - else -#endif // !CLIENT_DLL - { - return false; - } - } - - return true; -} - -//----------------------------------------------------------------------------------------------------- -bool IsPushableEntity( CBaseEntity *pEnt ) -{ - if ( pEnt == NULL ) - return false; - - if ( sv_turbophysics.GetBool() ) - { - if ( pEnt->GetCollisionGroup() == COLLISION_GROUP_NONE ) - { -#ifdef CLIENT_DLL - if ( FClassnameIs( pEnt, "class CPhysicsPropMultiplayer" ) ) -#else - if ( FClassnameIs( pEnt, "prop_physics_multiplayer" ) ) -#endif // CLIENT_DLL - { - return true; - } - } - } - - return false; -} - -//----------------------------------------------------------------------------------------------------- -#ifndef CLIENT_DLL -bool IsBreakableEntity( CBaseEntity *pEnt ) -{ - if ( pEnt == NULL ) - return false; - - // If we won't be able to break it, don't try - if ( pEnt->m_takedamage != DAMAGE_YES ) - return false; - - if ( pEnt->GetCollisionGroup() != COLLISION_GROUP_PUSHAWAY && pEnt->GetCollisionGroup() != COLLISION_GROUP_BREAKABLE_GLASS && pEnt->GetCollisionGroup() != COLLISION_GROUP_NONE ) - return false; - - if ( pEnt->m_iHealth > 200 ) - return false; - - IMultiplayerPhysics *pPhysicsInterface = dynamic_cast< IMultiplayerPhysics * >( pEnt ); - if ( pPhysicsInterface ) - { - if ( pPhysicsInterface->GetMultiplayerPhysicsMode() != PHYSICS_MULTIPLAYER_SOLID ) - return false; - } - else - { - if ((FClassnameIs( pEnt, "func_breakable" ) || FClassnameIs( pEnt, "func_breakable_surf" ))) - { - if (FClassnameIs( pEnt, "func_breakable_surf" )) - { - // don't try to break it if it has already been broken - CBreakableSurface *surf = static_cast< CBreakableSurface * >( pEnt ); - - if ( surf->m_bIsBroken ) - return false; - } - } - else if ( pEnt->PhysicsSolidMaskForEntity() & CONTENTS_PLAYERCLIP ) - { - // hostages and players use CONTENTS_PLAYERCLIP, so we can use it to ignore them - return false; - } - } - - IBreakableWithPropData *pBreakableInterface = dynamic_cast< IBreakableWithPropData * >( pEnt ); - if ( pBreakableInterface ) - { - // Bullets don't damage it - ignore - if ( pBreakableInterface->GetDmgModBullet() <= 0.0f ) - { - return false; - } - } - - CBreakableProp *pProp = dynamic_cast< CBreakableProp * >( pEnt ); - if ( pProp ) - { - // It takes a large amount of damage to even scratch it - ignore - if ( pProp->m_iMinHealthDmg >= 50 ) - { - return false; - } - } - - return true; -} -#endif // !CLIENT_DLL - -//----------------------------------------------------------------------------------------------------- -int GetPushawayEnts( CBaseCombatCharacter *pPushingEntity, CBaseEntity **ents, int nMaxEnts, float flPlayerExpand, int PartitionMask, CPushAwayEnumerator *enumerator ) -{ - - Vector vExpand( flPlayerExpand, flPlayerExpand, flPlayerExpand ); - - Ray_t ray; - ray.Init( pPushingEntity->GetAbsOrigin(), pPushingEntity->GetAbsOrigin(), pPushingEntity->GetCollideable()->OBBMins() - vExpand, pPushingEntity->GetCollideable()->OBBMaxs() + vExpand ); - - CPushAwayEnumerator *physPropEnum = NULL; - if ( !enumerator ) - { - physPropEnum = new CPushAwayEnumerator( ents, nMaxEnts ); - enumerator = physPropEnum; - } - - partition->EnumerateElementsAlongRay( PartitionMask, ray, false, enumerator ); - - int numHit = enumerator->m_nAlreadyHit; - - if ( physPropEnum ) - delete physPropEnum; - - return numHit; -} - -void AvoidPushawayProps( CBaseCombatCharacter *pPlayer, CUserCmd *pCmd ) -{ - // Figure out what direction we're moving and the extents of the box we're going to sweep - // against physics objects. - Vector currentdir; - Vector rightdir; - AngleVectors( pCmd->viewangles, ¤tdir, &rightdir, NULL ); - - CBaseEntity *props[512]; -#ifdef CLIENT_DLL - int nEnts = GetPushawayEnts( pPlayer, props, ARRAYSIZE( props ), 0.0f, PARTITION_CLIENT_SOLID_EDICTS, NULL ); -#else - int nEnts = GetPushawayEnts( pPlayer, props, ARRAYSIZE( props ), 0.0f, PARTITION_ENGINE_SOLID_EDICTS, NULL ); -#endif - - const Vector & ourCenter = pPlayer->WorldSpaceCenter(); - Vector nearestPropPoint; - Vector nearestPlayerPoint; - - for ( int i=0; i < nEnts; i++ ) - { - // Don't respond to this entity on the client unless it has PHYSICS_MULTIPLAYER_FULL set. - IMultiplayerPhysics *pInterface = dynamic_cast( props[i] ); - if ( pInterface && pInterface->GetMultiplayerPhysicsMode() != PHYSICS_MULTIPLAYER_SOLID ) - continue; - - const float minMass = 10.0f; // minimum mass that can push a player back - const float maxMass = 30.0f; // cap at a decently large value - float mass = maxMass; - if ( pInterface ) - { - mass = pInterface->GetMass(); - } - mass = clamp( mass, minMass, maxMass ); - - mass = MAX( mass, 0 ); - mass /= maxMass; // bring into a 0..1 range - - // Push away from the collision point. The closer our center is to the collision point, - // the harder we push away. - props[i]->CollisionProp()->CalcNearestPoint( ourCenter, &nearestPropPoint ); - pPlayer->CollisionProp()->CalcNearestPoint( nearestPropPoint, &nearestPlayerPoint ); - Vector vPushAway = (nearestPlayerPoint - nearestPropPoint); - float flDist = VectorNormalize( vPushAway ); - - const float MaxPushawayDistance = 5.0f; - if ( flDist > MaxPushawayDistance && !pPlayer->CollisionProp()->IsPointInBounds( nearestPropPoint ) ) - { - continue; - } - - // If we're not pushing, try from our center to the nearest edge of the prop - if ( vPushAway.IsZero() ) - { - vPushAway = (ourCenter - nearestPropPoint); - flDist = VectorNormalize( vPushAway ); - } - - // If we're still not pushing, try from our center to the center of the prop - if ( vPushAway.IsZero() ) - { - vPushAway = (ourCenter - props[i]->WorldSpaceCenter()); - flDist = VectorNormalize( vPushAway ); - } - - flDist = MAX( flDist, 1 ); - - float flForce = sv_pushaway_player_force.GetFloat() / flDist * mass; - flForce = MIN( flForce, sv_pushaway_max_player_force.GetFloat() ); - -#ifndef CLIENT_DLL - pPlayer->PushawayTouch( props[i] ); - - // We can get right up next to rotating doors before they start to move, so scale back our force so we don't go flying - if ( FClassnameIs( props[i], "func_door_rotating" ) || FClassnameIs( props[i], "prop_door_rotating" ) ) -#endif - { - flForce *= 0.25f; - } - - vPushAway *= flForce; - - pCmd->forwardmove += vPushAway.Dot( currentdir ); - pCmd->sidemove += vPushAway.Dot( rightdir ); - } -} - -//----------------------------------------------------------------------------------------------------- -void PerformObstaclePushaway( CBaseCombatCharacter *pPushingEntity ) -{ - if ( pPushingEntity->m_lifeState != LIFE_ALIVE ) - return; - - // Give a push to any barrels that we're touching. - // The client handles adjusting our usercmd to push us away. - CBaseEntity *props[256]; - -#ifdef CLIENT_DLL - // if sv_pushaway_clientside is disabled, clientside phys objects don't bounce away - if ( sv_pushaway_clientside.GetInt() == 0 ) - return; - - // if sv_pushaway_clientside is 1, only local player can push them - CBasePlayer *pPlayer = pPushingEntity->IsPlayer() ? (dynamic_cast< CBasePlayer * >(pPushingEntity)) : NULL; - if ( (sv_pushaway_clientside.GetInt() == 1) && (!pPlayer || !pPlayer->IsLocalPlayer()) ) - return; - - int nEnts = GetPushawayEnts( pPushingEntity, props, ARRAYSIZE( props ), 3.0f, PARTITION_CLIENT_RESPONSIVE_EDICTS, NULL ); -#else - int nEnts = GetPushawayEnts( pPushingEntity, props, ARRAYSIZE( props ), 3.0f, PARTITION_ENGINE_SOLID_EDICTS, NULL ); -#endif - - for ( int i=0; i < nEnts; i++ ) - { - // If this entity uas PHYSICS_MULTIPLAYER_FULL set (ie: it's not just debris), and we're moving too slow, don't push it away. - // Instead, let the client bounce off it. This allows players to get close to and duck behind things without knocking them over. - IMultiplayerPhysics *pInterface = dynamic_cast( props[i] ); - - if ( pInterface && pInterface->GetMultiplayerPhysicsMode() == PHYSICS_MULTIPLAYER_SOLID ) - { - if ( pPushingEntity->GetAbsVelocity().Length2D() < sv_pushaway_min_player_speed.GetFloat() ) - continue; - } - - IPhysicsObject *pObj = props[i]->VPhysicsGetObject(); - - if ( pObj ) - { - Vector vPushAway = (props[i]->WorldSpaceCenter() - pPushingEntity->WorldSpaceCenter()); - vPushAway.z = 0; - - float flDist = VectorNormalize( vPushAway ); - flDist = MAX( flDist, 1 ); - - float flForce = sv_pushaway_force.GetFloat() / flDist; - flForce = MIN( flForce, sv_pushaway_max_force.GetFloat() ); - - pObj->ApplyForceOffset( vPushAway * flForce, pPushingEntity->WorldSpaceCenter() ); - } - } -} diff --git a/game/shared/obstacle_pushaway.h b/game/shared/obstacle_pushaway.h deleted file mode 100644 index 25036d462..000000000 --- a/game/shared/obstacle_pushaway.h +++ /dev/null @@ -1,187 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef OBSTACLE_PUSHAWAY_H -#define OBSTACLE_PUSHAWAY_H -#ifdef _WIN32 -#pragma once -#endif - -#include "props_shared.h" -#ifndef CLIENT_DLL -#include "func_breakablesurf.h" -#include "BasePropDoor.h" -#include "doors.h" -#endif // CLIENT_DLL - -//-------------------------------------------------------------------------------------------------------------- -bool IsPushAwayEntity( CBaseEntity *pEnt ); -bool IsPushableEntity( CBaseEntity *pEnt ); - -//-------------------------------------------------------------------------------------------------------------- -#ifndef CLIENT_DLL -bool IsBreakableEntity( CBaseEntity *pEnt ); -#endif // !CLIENT_DLL - -//-------------------------------------------------------------------------------------------------------------- -class CPushAwayEnumerator : public IPartitionEnumerator -{ -public: - // Forced constructor - CPushAwayEnumerator(CBaseEntity **ents, int nMaxEnts) - { - m_nAlreadyHit = 0; - m_AlreadyHit = ents; - m_nMaxHits = nMaxEnts; - } - - // Actual work code - virtual IterationRetval_t EnumElement( IHandleEntity *pHandleEntity ) - { -#ifdef CLIENT_DLL - CBaseEntity *pEnt = ClientEntityList().GetBaseEntityFromHandle( pHandleEntity->GetRefEHandle() ); -#else - CBaseEntity *pEnt = gEntList.GetBaseEntity( pHandleEntity->GetRefEHandle() ); -#endif // CLIENT_DLL - - if ( IsPushAwayEntity( pEnt ) && m_nAlreadyHit < m_nMaxHits ) - { - m_AlreadyHit[m_nAlreadyHit] = pEnt; - m_nAlreadyHit++; - } - - return ITERATION_CONTINUE; - } - -public: - - CBaseEntity **m_AlreadyHit; - int m_nAlreadyHit; - int m_nMaxHits; -}; - - -#ifndef CLIENT_DLL -//-------------------------------------------------------------------------------------------------------------- -/** - * This class will collect breakable objects in a volume. Physics props that can be damaged, func_breakable*, etc - * are all collected by this class. - */ -class CBotBreakableEnumerator : public CPushAwayEnumerator -{ -public: - CBotBreakableEnumerator(CBaseEntity **ents, int nMaxEnts) : CPushAwayEnumerator(ents, nMaxEnts) - { - } - - virtual IterationRetval_t EnumElement( IHandleEntity *pHandleEntity ) - { - CBaseEntity *pEnt = gEntList.GetBaseEntity( pHandleEntity->GetRefEHandle() ); - - if ( !IsBreakableEntity( pEnt ) ) - return ITERATION_CONTINUE; - - // ignore breakables parented to doors - if ( pEnt->GetParent() && - ( FClassnameIs( pEnt->GetParent(), "func_door*" ) || - FClassnameIs( pEnt, "prop_door*" ) ) ) - return ITERATION_CONTINUE; - - if ( m_nAlreadyHit < m_nMaxHits ) - { - m_AlreadyHit[m_nAlreadyHit] = pEnt; - m_nAlreadyHit++; - } - - return ITERATION_CONTINUE; - } -}; - - -//-------------------------------------------------------------------------------------------------------------- -/** - * This class will collect door objects in a volume. - */ -class CBotDoorEnumerator : public CPushAwayEnumerator -{ -public: - CBotDoorEnumerator(CBaseEntity **ents, int nMaxEnts) : CPushAwayEnumerator(ents, nMaxEnts) - { - } - - virtual IterationRetval_t EnumElement( IHandleEntity *pHandleEntity ) - { - CBaseEntity *pEnt = gEntList.GetBaseEntity( pHandleEntity->GetRefEHandle() ); - - if ( pEnt == NULL ) - return ITERATION_CONTINUE; - - if ( ( pEnt->ObjectCaps() & FCAP_IMPULSE_USE ) == 0 ) - { - return ITERATION_CONTINUE; - } - - if ( FClassnameIs( pEnt, "func_door*" ) ) - { - CBaseDoor *door = dynamic_cast(pEnt); - if ( !door ) - { - return ITERATION_CONTINUE; - } - - if ( door->m_toggle_state == TS_GOING_UP || door->m_toggle_state == TS_GOING_DOWN ) - { - return ITERATION_CONTINUE; - } - } - else if ( FClassnameIs( pEnt, "prop_door*" ) ) - { - CBasePropDoor *door = dynamic_cast(pEnt); - if ( !door ) - { - return ITERATION_CONTINUE; - } - - if ( door->IsDoorOpening() || door->IsDoorClosing() ) - { - return ITERATION_CONTINUE; - } - } - else - { - return ITERATION_CONTINUE; - } - - if ( m_nAlreadyHit < m_nMaxHits ) - { - m_AlreadyHit[m_nAlreadyHit] = pEnt; - m_nAlreadyHit++; - } - - return ITERATION_CONTINUE; - } -}; - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Returns an entity that matches the filter that is along the line segment - */ -CBaseEntity * CheckForEntitiesAlongSegment( const Vector &start, const Vector &end, const Vector &mins, const Vector &maxs, CPushAwayEnumerator *enumerator ); -#endif // CLIENT_DLL - - -//-------------------------------------------------------------------------------------------------------------- -// Retrieves physics objects near pPushingEntity -void AvoidPushawayProps( CBaseCombatCharacter *pPlayer, CUserCmd *pCmd ); -int GetPushawayEnts( CBaseCombatCharacter *pPushingEntity, CBaseEntity **ents, int nMaxEnts, float flPlayerExpand, int PartitionMask, CPushAwayEnumerator *enumerator = NULL ); - -//-------------------------------------------------------------------------------------------------------------- -// Pushes physics objects away from the entity -void PerformObstaclePushaway( CBaseCombatCharacter *pPushingEntity ); - - -#endif // OBSTACLE_PUSHAWAY_H diff --git a/game/shared/particle_parse.cpp b/game/shared/particle_parse.cpp deleted file mode 100644 index af122f3d7..000000000 --- a/game/shared/particle_parse.cpp +++ /dev/null @@ -1,315 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#include "filesystem.h" -#include -#include "particle_parse.h" -#include "particles/particles.h" - -#ifdef GAME_DLL -#include "te_effect_dispatch.h" -#include "networkstringtable_gamedll.h" -#else -#include "c_te_effect_dispatch.h" -#include "networkstringtable_clientdll.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define PARTICLES_MANIFEST_FILE "particles/particles_manifest.txt" - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int GetAttachTypeFromString( const char *pszString ) -{ - if ( !pszString || !pszString[0] ) - return -1; - - // If you add new attach types, you need to add them to this list - static const char *pAttachmentNames[MAX_PATTACH_TYPES] = - { - "start_at_origin", // PATTACH_ABSORIGIN = 0, - "follow_origin", // PATTACH_ABSORIGIN_FOLLOW, - "start_at_customorigin",// PATTACH_CUSTOMORIGIN, - "start_at_attachment", // PATTACH_POINT, - "follow_attachment", // PATTACH_POINT_FOLLOW, - }; - - for ( int i = 0; i < MAX_PATTACH_TYPES; i++ ) - { - if ( FStrEq( pAttachmentNames[i], pszString ) ) - return i; - } - - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : list - -//----------------------------------------------------------------------------- -void GetParticleManifest( CUtlVector& list ) -{ - // Open the manifest file, and read the particles specified inside it - KeyValues *manifest = new KeyValues( PARTICLES_MANIFEST_FILE ); - if ( manifest->LoadFromFile( filesystem, PARTICLES_MANIFEST_FILE, "GAME" ) ) - { - for ( KeyValues *sub = manifest->GetFirstSubKey(); sub != NULL; sub = sub->GetNextKey() ) - { - if ( !Q_stricmp( sub->GetName(), "file" ) ) - { - list.AddToTail( sub->GetString() ); - continue; - } - - Warning( "CParticleMgr::Init: Manifest '%s' with bogus file type '%s', expecting 'file'\n", PARTICLES_MANIFEST_FILE, sub->GetName() ); - } - } - else - { - Warning( "PARTICLE SYSTEM: Unable to load manifest file '%s'\n", PARTICLES_MANIFEST_FILE ); - } - - manifest->deleteThis(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void ParseParticleEffects( bool bLoadSheets ) -{ - MEM_ALLOC_CREDIT(); - - g_pParticleSystemMgr->ShouldLoadSheets( bLoadSheets ); - - CUtlVector files; - GetParticleManifest( files ); - - int nCount = files.Count(); - for ( int i = 0; i < nCount; ++i ) - { - g_pParticleSystemMgr->ReadParticleConfigFile( files[i], false, false ); - } - - g_pParticleSystemMgr->DecommitTempMemory(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void PrecacheStandardParticleSystems( ) -{ -#ifdef GAME_DLL - // Now add each particle system name to the network string pool, so we can send string_t's - // down to the client instead of full particle system names. - for ( int i = 0; i < g_pParticleSystemMgr->GetParticleSystemCount(); i++ ) - { - const char *pParticleSystemName = g_pParticleSystemMgr->GetParticleSystemNameFromIndex(i); - CParticleSystemDefinition *pParticleSystem = g_pParticleSystemMgr->FindParticleSystem( pParticleSystemName ); - if ( pParticleSystem->ShouldAlwaysPrecache() ) - { - PrecacheParticleSystem( pParticleSystemName ); - } - } -#endif -} - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void DispatchParticleEffect( const char *pszParticleName, ParticleAttachment_t iAttachType, CBaseEntity *pEntity, const char *pszAttachmentName, bool bResetAllParticlesOnEntity ) -{ - int iAttachment = -1; - if ( pEntity && pEntity->GetBaseAnimating() ) - { - // Find the attachment point index - iAttachment = pEntity->GetBaseAnimating()->LookupAttachment( pszAttachmentName ); - if ( iAttachment == -1 ) - { - Warning("Model '%s' doesn't have attachment '%s' to attach particle system '%s' to.\n", STRING(pEntity->GetBaseAnimating()->GetModelName()), pszAttachmentName, pszParticleName ); - return; - } - } - - DispatchParticleEffect( pszParticleName, iAttachType, pEntity, iAttachment, bResetAllParticlesOnEntity ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void DispatchParticleEffect( const char *pszParticleName, ParticleAttachment_t iAttachType, CBaseEntity *pEntity, int iAttachmentPoint, bool bResetAllParticlesOnEntity ) -{ - CEffectData data; - - data.m_nHitBox = GetParticleSystemIndex( pszParticleName ); - if ( pEntity ) - { -#ifdef CLIENT_DLL - data.m_hEntity = pEntity; -#else - data.m_nEntIndex = pEntity->entindex(); -#endif - data.m_fFlags |= PARTICLE_DISPATCH_FROM_ENTITY; - } - data.m_nDamageType = iAttachType; - data.m_nAttachmentIndex = iAttachmentPoint; - - if ( bResetAllParticlesOnEntity ) - { - data.m_fFlags |= PARTICLE_DISPATCH_RESET_PARTICLES; - } - - DispatchEffect( "ParticleEffect", data ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void DispatchParticleEffect( int iEffectIndex, Vector vecOrigin, Vector vecStart, QAngle vecAngles, CBaseEntity *pEntity ) -{ - CEffectData data; - - data.m_nHitBox = iEffectIndex; - data.m_vOrigin = vecOrigin; - data.m_vStart = vecStart; - data.m_vAngles = vecAngles; - - if ( pEntity ) - { -#ifdef CLIENT_DLL - data.m_hEntity = pEntity; -#else - data.m_nEntIndex = pEntity->entindex(); -#endif - data.m_fFlags |= PARTICLE_DISPATCH_FROM_ENTITY; - data.m_nDamageType = PATTACH_CUSTOMORIGIN; - } - else - { -#ifdef CLIENT_DLL - data.m_hEntity = NULL; -#else - data.m_nEntIndex = 0; -#endif - } - - DispatchEffect( "ParticleEffect", data ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void DispatchParticleEffect( const char *pszParticleName, Vector vecOrigin, QAngle vecAngles, CBaseEntity *pEntity ) -{ - int iIndex = GetParticleSystemIndex( pszParticleName ); - DispatchParticleEffect( iIndex, vecOrigin, vecOrigin, vecAngles, pEntity ); -} - -//----------------------------------------------------------------------------- -// Purpose: Yet another overload, lets us supply vecStart -//----------------------------------------------------------------------------- -void DispatchParticleEffect( const char *pszParticleName, Vector vecOrigin, Vector vecStart, QAngle vecAngles, CBaseEntity *pEntity ) -{ - int iIndex = GetParticleSystemIndex( pszParticleName ); - DispatchParticleEffect( iIndex, vecOrigin, vecStart, vecAngles, pEntity ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void StopParticleEffects( CBaseEntity *pEntity ) -{ - CEffectData data; - - if ( pEntity ) - { -#ifdef CLIENT_DLL - data.m_hEntity = pEntity; -#else - data.m_nEntIndex = pEntity->entindex(); -#endif - } - - DispatchEffect( "ParticleEffectStop", data ); -} - -#ifndef CLIENT_DLL - - extern CBaseEntity *GetNextCommandEntity( CBasePlayer *pPlayer, const char *name, CBaseEntity *ent ); - - ConVar particle_test_file( "particle_test_file", "", FCVAR_CHEAT, "Name of the particle system to dynamically spawn" ); - ConVar particle_test_attach_mode( "particle_test_attach_mode", "follow_attachment", FCVAR_CHEAT, "Possible Values: 'start_at_attachment', 'follow_attachment', 'start_at_origin', 'follow_origin'" ); - ConVar particle_test_attach_attachment( "particle_test_attach_attachment", "0", FCVAR_CHEAT, "Attachment index for attachment mode" ); - - void Particle_Test_Start( CBasePlayer* pPlayer, const char *name, bool bStart ) - { - if ( !pPlayer ) - return; - - int iAttachType = GetAttachTypeFromString( particle_test_attach_mode.GetString() ); - - if ( iAttachType < 0 ) - { - Warning( "Invalid attach type specified for particle_test in cvar 'particle_test_attach_mode.\n" ); - return; - } - - int iAttachmentIndex = particle_test_attach_attachment.GetInt(); - - const char *pszParticleFile = particle_test_file.GetString(); - - CBaseEntity *pEntity = NULL; - while ( (pEntity = GetNextCommandEntity( pPlayer, name, pEntity )) != NULL ) - { - /* - Fire the test particle system on this entity - */ - - DispatchParticleEffect( - pszParticleFile, - (ParticleAttachment_t)iAttachType, - pEntity, - iAttachmentIndex, - true ); // stops existing particle systems - } - } - - void CC_Particle_Test_Start( const CCommand& args ) - { - Particle_Test_Start( UTIL_GetCommandClient(), args[1], true ); - } - static ConCommand particle_test_start("particle_test_start", CC_Particle_Test_Start, "Dispatches the test particle system with the parameters specified in particle_test_file,\n particle_test_attach_mode and particle_test_attach_param on the entity the player is looking at.\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at ", FCVAR_CHEAT); - - - void Particle_Test_Stop( CBasePlayer* pPlayer, const char *name, bool bStart ) - { - if ( !pPlayer ) - return; - - CBaseEntity *pEntity = NULL; - while ( (pEntity = GetNextCommandEntity( pPlayer, name, pEntity )) != NULL ) - { - //Stop all particle systems on the selected entity - DispatchParticleEffect( "", PATTACH_ABSORIGIN, pEntity, 0, true ); - } - } - - void CC_Particle_Test_Stop( const CCommand& args ) - { - Particle_Test_Stop( UTIL_GetCommandClient(), args[1], false ); - } - static ConCommand particle_test_stop("particle_test_stop", CC_Particle_Test_Stop, "Stops all particle systems on the selected entities.\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at ", FCVAR_CHEAT); - -#endif //CLIENT_DLL diff --git a/game/shared/particle_parse.h b/game/shared/particle_parse.h deleted file mode 100644 index 340af84f4..000000000 --- a/game/shared/particle_parse.h +++ /dev/null @@ -1,62 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef PARTICLE_PARSE_H -#define PARTICLE_PARSE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "utlvector.h" -#include "utlstring.h" - -//----------------------------------------------------------------------------- -// Particle attachment methods -//----------------------------------------------------------------------------- -enum ParticleAttachment_t -{ - PATTACH_ABSORIGIN = 0, // Create at absorigin, but don't follow - PATTACH_ABSORIGIN_FOLLOW, // Create at absorigin, and update to follow the entity - PATTACH_CUSTOMORIGIN, // Create at a custom origin, but don't follow - PATTACH_POINT, // Create on attachment point, but don't follow - PATTACH_POINT_FOLLOW, // Create on attachment point, and update to follow the entity - - PATTACH_WORLDORIGIN, // Used for control points that don't attach to an entity - - MAX_PATTACH_TYPES, -}; - -extern int GetAttachTypeFromString( const char *pszString ); - -#define PARTICLE_DISPATCH_FROM_ENTITY (1<<0) -#define PARTICLE_DISPATCH_RESET_PARTICLES (1<<1) - -//----------------------------------------------------------------------------- -// Particle parsing methods -//----------------------------------------------------------------------------- -// Parse the particle manifest file & register the effects within it -// Only needs to be called once per game, unless tools change particle definitions -void ParseParticleEffects( bool bLoadSheets ); - -// Get a list of the files inside the particle manifest file -void GetParticleManifest( CUtlVector& list ); - -// Precaches standard particle systems (only necessary on server) -// Should be called once per level -void PrecacheStandardParticleSystems( ); - -//----------------------------------------------------------------------------- -// Particle spawning methods -//----------------------------------------------------------------------------- -void DispatchParticleEffect( const char *pszParticleName, ParticleAttachment_t iAttachType, CBaseEntity *pEntity, const char *pszAttachmentName, bool bResetAllParticlesOnEntity = false ); -void DispatchParticleEffect( const char *pszParticleName, ParticleAttachment_t iAttachType, CBaseEntity *pEntity = NULL, int iAttachmentPoint = -1, bool bResetAllParticlesOnEntity = false ); -void DispatchParticleEffect( const char *pszParticleName, Vector vecOrigin, QAngle vecAngles, CBaseEntity *pEntity = NULL ); -void DispatchParticleEffect( const char *pszParticleName, Vector vecOrigin, Vector vecStart, QAngle vecAngles, CBaseEntity *pEntity = NULL ); -void DispatchParticleEffect( int iEffectIndex, Vector vecOrigin, Vector vecStart, QAngle vecAngles, CBaseEntity *pEntity = NULL ); -void StopParticleEffects( CBaseEntity *pEntity ); - - -#endif // PARTICLE_PARSE_H diff --git a/game/shared/particle_property.cpp b/game/shared/particle_property.cpp deleted file mode 100644 index a4d1d6adb..000000000 --- a/game/shared/particle_property.cpp +++ /dev/null @@ -1,555 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#include "particle_property.h" -#include "utlvector.h" - -#ifdef CLIENT_DLL - -#include "c_baseentity.h" -#include "c_baseanimating.h" -#include "recvproxy.h" -#include "particles_new.h" -#include "engine/ivdebugoverlay.h" - -#else - -#include "baseentity.h" -#include "baseanimating.h" -#include "sendproxy.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Save/load -//----------------------------------------------------------------------------- -BEGIN_DATADESC_NO_BASE( CParticleProperty ) - // DEFINE_FIELD( m_pOuter, FIELD_CLASSPTR ), -END_DATADESC() - -#ifdef CLIENT_DLL -//----------------------------------------------------------------------------- -// Prediction -//----------------------------------------------------------------------------- -BEGIN_PREDICTION_DATA_NO_BASE( CParticleProperty ) - //DEFINE_PRED_FIELD( m_vecMins, FIELD_VECTOR, FTYPEDESC_INSENDTABLE ), -END_PREDICTION_DATA() -#endif - -//----------------------------------------------------------------------------- -// Networking -//----------------------------------------------------------------------------- -BEGIN_NETWORK_TABLE_NOBASE( CParticleProperty, DT_ParticleProperty ) -#ifdef CLIENT_DLL -//RecvPropVector( RECVINFO(m_vecMins), 0, RecvProxy_OBBMins ), -#else -//SendPropVector( SENDINFO(m_vecMins), 0, SPROP_NOSCALE), -#endif -END_NETWORK_TABLE() - - -//----------------------------------------------------------------------------- -// Constructor, destructor -//----------------------------------------------------------------------------- -CParticleProperty::CParticleProperty() -{ - Init( NULL ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CParticleProperty::~CParticleProperty() -{ - // We're being removed. Call StopEmission() on any particle system - // that has an unlimited number of particles to emit. - StopEmission( NULL, false, true ); -} - -//----------------------------------------------------------------------------- -// Initialization -//----------------------------------------------------------------------------- -void CParticleProperty::Init( CBaseEntity *pEntity ) -{ - m_pOuter = pEntity; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CParticleProperty::GetParticleAttachment( C_BaseEntity *pEntity, const char *pszAttachmentName, const char *pszParticleName ) -{ - Assert( pEntity && pEntity->GetBaseAnimating() ); - if ( !pEntity || !pEntity->GetBaseAnimating() ) - return -1; - - // Find the attachment point index - int iAttachment = pEntity->GetBaseAnimating()->LookupAttachment( pszAttachmentName ); - if ( iAttachment == -1 ) - { - Warning("Model '%s' doesn't have attachment '%s' to attach particle system '%s' to.\n", STRING(pEntity->GetBaseAnimating()->GetModelName()), pszAttachmentName, pszParticleName ); - } - - return iAttachment; -} - -//----------------------------------------------------------------------------- -// Purpose: Create a new particle system and attach it to our owner -//----------------------------------------------------------------------------- -CNewParticleEffect *CParticleProperty::Create( const char *pszParticleName, ParticleAttachment_t iAttachType, const char *pszAttachmentName ) -{ - int iAttachment = GetParticleAttachment( GetOuter(), pszAttachmentName, pszParticleName ); - if ( iAttachment == -1 ) - return NULL; - - // Create the system - return Create( pszParticleName, iAttachType, iAttachment ); -} - -//----------------------------------------------------------------------------- -// Purpose: Create a new particle system and attach it to our owner -//----------------------------------------------------------------------------- -static ConVar cl_particle_batch_mode( "cl_particle_batch_mode", "1" ); -CNewParticleEffect *CParticleProperty::Create( const char *pszParticleName, ParticleAttachment_t iAttachType, int iAttachmentPoint, Vector vecOriginOffset ) -{ - int nBatchMode = cl_particle_batch_mode.GetInt(); - CParticleSystemDefinition *pDef = g_pParticleSystemMgr->FindParticleSystem( pszParticleName ); - bool bRequestedBatch = ( nBatchMode == 2 ) || ( ( nBatchMode == 1 ) && pDef && pDef->ShouldBatch() ); - if ( ( iAttachType == PATTACH_CUSTOMORIGIN ) && bRequestedBatch ) - { - int iIndex = FindEffect( pszParticleName ); - if ( iIndex >= 0 ) - { - CNewParticleEffect *pEffect = m_ParticleEffects[iIndex].pParticleEffect.GetObject(); - pEffect->Restart(); - return pEffect; - } - } - - if ( !pDef ) - { - AssertMsg( 0, "Attempting to create unknown particle system" ); - Warning( "Attempting to create unknown particle system '%s' \n", pszParticleName ); - return NULL; - } - - int iIndex = m_ParticleEffects.AddToTail(); - ParticleEffectList_t *newEffect = &m_ParticleEffects[iIndex]; - newEffect->pParticleEffect = CNewParticleEffect::Create( m_pOuter, pDef ); - - if ( !newEffect->pParticleEffect->IsValid() ) - { - // Caused by trying to spawn an unregistered particle effect. Remove it. - ParticleMgr()->RemoveEffect( newEffect->pParticleEffect.GetObject() ); - return NULL; - } - - AddControlPoint( iIndex, 0, GetOuter(), iAttachType, iAttachmentPoint, vecOriginOffset ); - - if ( m_pOuter ) - { - m_pOuter->OnNewParticleEffect( pszParticleName, newEffect->pParticleEffect.GetObject() ); - } - - return newEffect->pParticleEffect.GetObject(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CParticleProperty::AddControlPoint( CNewParticleEffect *pEffect, int iPoint, C_BaseEntity *pEntity, ParticleAttachment_t iAttachType, const char *pszAttachmentName, Vector vecOriginOffset ) -{ - int iAttachment = -1; - if ( pszAttachmentName ) - { - iAttachment = GetParticleAttachment( pEntity, pszAttachmentName, pEffect->GetEffectName() ); - } - - for ( int i = 0; i < m_ParticleEffects.Count(); i++ ) - { - if ( m_ParticleEffects[i].pParticleEffect == pEffect ) - { - AddControlPoint( i, iPoint, pEntity, iAttachType, iAttachment, vecOriginOffset ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CParticleProperty::AddControlPoint( int iEffectIndex, int iPoint, C_BaseEntity *pEntity, ParticleAttachment_t iAttachType, int iAttachmentPoint, Vector vecOriginOffset ) -{ - Assert( iEffectIndex >= 0 && iEffectIndex < m_ParticleEffects.Count() ); - ParticleEffectList_t *pEffect = &m_ParticleEffects[iEffectIndex]; - Assert( pEffect->pControlPoints.Count() < MAX_PARTICLE_CONTROL_POINTS ); - - int iIndex = pEffect->pControlPoints.AddToTail(); - ParticleControlPoint_t *pNewPoint = &pEffect->pControlPoints[iIndex]; - pNewPoint->iControlPoint = iPoint; - pNewPoint->hEntity = pEntity; - pNewPoint->iAttachType = iAttachType; - pNewPoint->iAttachmentPoint = iAttachmentPoint; - pNewPoint->vecOriginOffset = vecOriginOffset; - - UpdateParticleEffect( pEffect, true, iIndex ); -} - - -//----------------------------------------------------------------------------- -// Used to replace a particle effect with a different one; attaches the control point updating to the new one -//----------------------------------------------------------------------------- -void CParticleProperty::ReplaceParticleEffect( CNewParticleEffect *pOldEffect, CNewParticleEffect *pNewEffect ) -{ - int nCount = m_ParticleEffects.Count(); - for ( int i = 0; i < nCount; ++i ) - { - if ( pOldEffect != m_ParticleEffects[i].pParticleEffect.GetObject() ) - continue; - - m_ParticleEffects[i].pParticleEffect = pNewEffect; - UpdateParticleEffect( &m_ParticleEffects[i], true ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Set the parent of a given control point to the index of some other -// control point. -//----------------------------------------------------------------------------- -void CParticleProperty::SetControlPointParent( int iEffectIndex, int whichControlPoint, int parentIdx ) -{ - -} - -//----------------------------------------------------------------------------- -// Purpose: Stop effects from emitting more particles. If no effect is -// specified, all effects attached to this entity are stopped. -//----------------------------------------------------------------------------- -void CParticleProperty::StopEmission( CNewParticleEffect *pEffect, bool bWakeOnStop, bool bDestroyAsleepSystems ) -{ - // If we return from dormancy and are then told to stop emitting, - // we should have died while dormant. Remove ourselves immediately. - bool bRemoveInstantly = (m_iDormancyChangedAtFrame == gpGlobals->framecount); - - if ( pEffect ) - { - if ( FindEffect( pEffect ) != -1 ) - { - pEffect->StopEmission( false, bRemoveInstantly, bWakeOnStop ); - } - } - else - { - // Stop all effects - float flNow = g_pParticleSystemMgr->GetLastSimulationTime(); - int nCount = m_ParticleEffects.Count(); - for ( int i = nCount-1; i >= 0; i-- ) - { - CNewParticleEffect *pTmp = m_ParticleEffects[i].pParticleEffect.GetObject(); - bool bRemoveSystem = bRemoveInstantly || ( bDestroyAsleepSystems && ( flNow >= pTmp->m_flNextSleepTime ) ); - if ( bRemoveSystem ) - { - m_ParticleEffects.Remove( i ); - pTmp->SetOwner( NULL ); - } - pTmp->StopEmission( false, bRemoveSystem, !bRemoveSystem && bWakeOnStop ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Remove effects immediately, including all current particles. If no -// effect is specified, all effects attached to this entity are removed. -//----------------------------------------------------------------------------- -void CParticleProperty::StopEmissionAndDestroyImmediately( CNewParticleEffect *pEffect ) -{ - if ( pEffect ) - { - int iIndex = FindEffect( pEffect ); - Assert( iIndex != -1 ); - if ( iIndex != -1 ) - { - m_ParticleEffects.Remove( iIndex ); - - // Clear the owner so it doesn't try to call back to us on deletion - pEffect->SetOwner( NULL ); - pEffect->StopEmission( false, true ); - } - } - else - { - // Immediately destroy all effects - int nCount = m_ParticleEffects.Count(); - for ( int i = nCount-1; i >= 0; i-- ) - { - CNewParticleEffect *pTmp = m_ParticleEffects[i].pParticleEffect.GetObject(); - m_ParticleEffects.Remove( i ); - - // Clear the owner so it doesn't try to call back to us on deletion - pTmp->SetOwner( NULL ); - pTmp->StopEmission( false, true ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Stop all effects that have a control point associated with the given -// entity. -//----------------------------------------------------------------------------- -void CParticleProperty::StopParticlesInvolving( CBaseEntity *pEntity ) -{ - Assert( pEntity ); - - EHANDLE entHandle(pEntity); - - // If we return from dormancy and are then told to stop emitting, - // we should have died while dormant. Remove ourselves immediately. - bool bRemoveInstantly = (m_iDormancyChangedAtFrame == gpGlobals->framecount); - - int nCount = m_ParticleEffects.Count(); - for ( int i = 0; i < nCount; ++i ) - { - // for each effect... - ParticleEffectList_t &part = m_ParticleEffects[i]; - // look through all the control points to see if any mention the given object - int cpCount = part.pControlPoints.Count(); - for (int j = 0; j < cpCount ; ++j ) - { - // if any control points respond to the given handle... - if (part.pControlPoints[j].hEntity == entHandle) - { - part.pParticleEffect->StopEmission( false, bRemoveInstantly ); - break; // break out of the inner loop (to where it says BREAK TO HERE) - } - } - // BREAK TO HERE - } -} - -//g_pParticleSystemMgr->FindParticleSystem( pParticleSystemName ); - -//----------------------------------------------------------------------------- -// Purpose: Stop all effects that were created using the given definition -// name. -//----------------------------------------------------------------------------- -void CParticleProperty::StopParticlesNamed( const char *pszEffectName, bool bForceRemoveInstantly /* =false */ ) -{ - CParticleSystemDefinition *pDef = g_pParticleSystemMgr->FindParticleSystem( pszEffectName ); - AssertMsg1(pDef, "Could not find particle definition %s", pszEffectName ); - if (!pDef) - return; - - - // If we return from dormancy and are then told to stop emitting, - // we should have died while dormant. Remove ourselves immediately. - bool bRemoveInstantly = (m_iDormancyChangedAtFrame == gpGlobals->framecount); - // force remove particles instantly if caller specified - bRemoveInstantly |= bForceRemoveInstantly; - - int nCount = m_ParticleEffects.Count(); - for ( int i = 0; i < nCount; ++i ) - { - // for each effect... - CNewParticleEffect *pParticleEffect = m_ParticleEffects[i].pParticleEffect.GetObject(); - if (pParticleEffect->m_pDef() == pDef) - { - pParticleEffect->StopEmission( false, bRemoveInstantly ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CParticleProperty::OnParticleSystemUpdated( CNewParticleEffect *pEffect, float flTimeDelta ) -{ - int iIndex = FindEffect( pEffect ); - Assert( iIndex != -1 ); - if ( iIndex == -1 ) - return; - - UpdateParticleEffect( &m_ParticleEffects[iIndex] ); - - /* - // Display the bounding box of the particle effect - Vector vecMins, vecMaxs; - pEffect->GetRenderBounds( vecMins, vecMaxs ); - debugoverlay->AddBoxOverlay( pEffect->GetRenderOrigin(), vecMins, vecMaxs, QAngle( 0, 0, 0 ), 0, 255, 255, 0, 0 ); - */ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CParticleProperty::OnParticleSystemDeleted( CNewParticleEffect *pEffect ) -{ - int iIndex = FindEffect( pEffect ); - if ( iIndex == -1 ) - return; - - m_ParticleEffects[iIndex].pParticleEffect.MarkDeleted(); - m_ParticleEffects.Remove( iIndex ); -} - -#ifdef CLIENT_DLL -//----------------------------------------------------------------------------- -// Purpose: The entity we're attached to has change dormancy state on our client -//----------------------------------------------------------------------------- -void CParticleProperty::OwnerSetDormantTo( bool bDormant ) -{ - m_iDormancyChangedAtFrame = gpGlobals->framecount; - - int nCount = m_ParticleEffects.Count(); - for ( int i = 0; i < nCount; i++ ) - { - //m_ParticleEffects[i].pParticleEffect->SetShouldSimulate( !bDormant ); - m_ParticleEffects[i].pParticleEffect->SetDormant( bDormant ); - } -} -#endif - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CParticleProperty::FindEffect( CNewParticleEffect *pEffect ) -{ - for ( int i = 0; i < m_ParticleEffects.Count(); i++ ) - { - if ( m_ParticleEffects[i].pParticleEffect == pEffect ) - return i; - } - - return -1; -} - -int CParticleProperty::FindEffect( const char *pEffectName ) -{ - for ( int i = 0; i < m_ParticleEffects.Count(); i++ ) - { - if ( !Q_stricmp( m_ParticleEffects[i].pParticleEffect->GetName(), pEffectName ) ) - return i; - } - - return -1; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CParticleProperty::UpdateParticleEffect( ParticleEffectList_t *pEffect, bool bInitializing, int iOnlyThisControlPoint ) -{ - if ( iOnlyThisControlPoint != -1 ) - { - UpdateControlPoint( pEffect, iOnlyThisControlPoint, bInitializing ); - return; - } - - // Loop through our control points and update them all - for ( int i = 0; i < pEffect->pControlPoints.Count(); i++ ) - { - UpdateControlPoint( pEffect, i, bInitializing ); - } -} - -extern void FormatViewModelAttachment( Vector &vOrigin, bool bInverse ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CParticleProperty::UpdateControlPoint( ParticleEffectList_t *pEffect, int iPoint, bool bInitializing ) -{ - ParticleControlPoint_t *pPoint = &pEffect->pControlPoints[iPoint]; - - if ( !pPoint->hEntity.Get() ) - { - if ( pPoint->iAttachType == PATTACH_WORLDORIGIN && bInitializing ) - { - pEffect->pParticleEffect->SetControlPointOrientation( pPoint->iControlPoint, Vector(1,0,0), Vector(0,1,0), Vector(0,0,1) ); - pEffect->pParticleEffect->SetControlPoint( pPoint->iControlPoint, pPoint->vecOriginOffset ); - pEffect->pParticleEffect->SetSortOrigin( pPoint->vecOriginOffset ); - } - - pEffect->pParticleEffect->SetControlPointEntity( pPoint->iControlPoint, NULL ); - return; - } - - // Only update non-follow particles when we're initializing, - // unless we're parented to something, in which case we should always update - if ( !bInitializing && !pPoint->hEntity->GetMoveParent() && (pPoint->iAttachType == PATTACH_ABSORIGIN || pPoint->iAttachType == PATTACH_POINT ) ) - return; - - if ( pPoint->iAttachType == PATTACH_CUSTOMORIGIN ) - return; - - Vector vecOrigin, vecForward, vecRight, vecUp; - - switch ( pPoint->iAttachType ) - { - case PATTACH_POINT: - case PATTACH_POINT_FOLLOW: - { - C_BaseAnimating *pAnimating = pPoint->hEntity->GetBaseAnimating(); - - Assert( pAnimating ); - if ( pAnimating ) - { - matrix3x4_t attachmentToWorld; - - pAnimating->GetAttachment( pPoint->iAttachmentPoint, attachmentToWorld ); - - - MatrixVectors( attachmentToWorld, &vecForward, &vecRight, &vecUp ); - MatrixPosition( attachmentToWorld, vecOrigin ); - - if ( pEffect->pParticleEffect->m_pDef->IsViewModelEffect() ) - { - FormatViewModelAttachment( vecOrigin, true ); - } - - } - } - break; - - case PATTACH_ABSORIGIN: - case PATTACH_ABSORIGIN_FOLLOW: - default: - { - vecOrigin = pPoint->hEntity->GetAbsOrigin() + pPoint->vecOriginOffset; - pPoint->hEntity->GetVectors( &vecForward, &vecRight, &vecUp ); - } - break; - } - pEffect->pParticleEffect->SetControlPointOrientation( pPoint->iControlPoint, vecForward, vecRight, vecUp ); - pEffect->pParticleEffect->SetControlPointEntity( pPoint->iControlPoint, pPoint->hEntity ); - pEffect->pParticleEffect->SetControlPoint( pPoint->iControlPoint, vecOrigin ); - pEffect->pParticleEffect->SetSortOrigin( vecOrigin ); -} - -//----------------------------------------------------------------------------- -// Purpose: Output all active effects -//----------------------------------------------------------------------------- -void CParticleProperty::DebugPrintEffects( void ) -{ - int nCount = m_ParticleEffects.Count(); - for ( int i = 0; i < nCount; ++i ) - { - // for each effect... - CNewParticleEffect *pParticleEffect = m_ParticleEffects[i].pParticleEffect.GetObject(); - - if ( !pParticleEffect ) - continue; - - Msg( "(%d) EffectName \"%s\" Dormant? %s Emission Stopped? %s \n", - i, - pParticleEffect->GetEffectName(), - ( pParticleEffect->m_bDormant ) ? "yes" : "no", - ( pParticleEffect->m_bEmissionStopped ) ? "yes" : "no" ); - } -} diff --git a/game/shared/particle_property.h b/game/shared/particle_property.h deleted file mode 100644 index 5dd86ba61..000000000 --- a/game/shared/particle_property.h +++ /dev/null @@ -1,120 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef PARTICLEPROPERTY_H -#define PARTICLEPROPERTY_H -#ifdef _WIN32 -#pragma once -#endif - -#include "smartptr.h" -#include "globalvars_base.h" -#include "particles_new.h" -#include "particle_parse.h" - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class CBaseEntity; -class CNewParticleEffect; - -struct ParticleControlPoint_t -{ - ParticleControlPoint_t() - { - iControlPoint = 0; - iAttachType = PATTACH_ABSORIGIN_FOLLOW; - iAttachmentPoint = 0; - vecOriginOffset = vec3_origin; - } - - int iControlPoint; - ParticleAttachment_t iAttachType; - int iAttachmentPoint; - Vector vecOriginOffset; - EHANDLE hEntity; -}; - -struct ParticleEffectList_t -{ - ParticleEffectList_t() - { - pParticleEffect = NULL; - } - - CUtlVector pControlPoints; - CSmartPtr pParticleEffect; -}; - -extern int GetAttachTypeFromString( const char *pszString ); - -//----------------------------------------------------------------------------- -// Encapsulates particle handling for an entity -//----------------------------------------------------------------------------- -class CParticleProperty -{ - DECLARE_CLASS_NOBASE( CParticleProperty ); - DECLARE_EMBEDDED_NETWORKVAR(); - DECLARE_PREDICTABLE(); - DECLARE_DATADESC(); - -public: - CParticleProperty(); - ~CParticleProperty(); - - void Init( CBaseEntity *pEntity ); - CBaseEntity *GetOuter( void ) { return m_pOuter; } - - // Effect Creation - CNewParticleEffect *Create( const char *pszParticleName, ParticleAttachment_t iAttachType, const char *pszAttachmentName ); - CNewParticleEffect *Create( const char *pszParticleName, ParticleAttachment_t iAttachType, int iAttachmentPoint = -1, Vector vecOriginOffset = vec3_origin ); - void AddControlPoint( CNewParticleEffect *pEffect, int iPoint, C_BaseEntity *pEntity, ParticleAttachment_t iAttachType, const char *pszAttachmentName = NULL, Vector vecOriginOffset = vec3_origin ); - void AddControlPoint( int iEffectIndex, int iPoint, C_BaseEntity *pEntity, ParticleAttachment_t iAttachType, int iAttachmentPoint = -1, Vector vecOriginOffset = vec3_origin ); - - inline void SetControlPointParent( CNewParticleEffect *pEffect, int whichControlPoint, int parentIdx ); - void SetControlPointParent( int iEffectIndex, int whichControlPoint, int parentIdx ); - - // Commands - void StopEmission( CNewParticleEffect *pEffect = NULL, bool bWakeOnStop = false, bool bDestroyAsleepSystems = false ); - void StopEmissionAndDestroyImmediately( CNewParticleEffect *pEffect = NULL ); - - // kill all particle systems involving a given entity for their control points - void StopParticlesInvolving( CBaseEntity *pEntity ); - void StopParticlesNamed( const char *pszEffectName, bool bForceRemoveInstantly = false ); ///< kills all particles using the given definition name - - // Particle System hooks - void OnParticleSystemUpdated( CNewParticleEffect *pEffect, float flTimeDelta ); - void OnParticleSystemDeleted( CNewParticleEffect *pEffect ); - -#ifdef CLIENT_DLL - void OwnerSetDormantTo( bool bDormant ); -#endif - - // Used to replace a particle effect with a different one; attaches the control point updating to the new one - void ReplaceParticleEffect( CNewParticleEffect *pOldEffect, CNewParticleEffect *pNewEffect ); - - // Debugging - void DebugPrintEffects( void ); - -private: - int GetParticleAttachment( C_BaseEntity *pEntity, const char *pszAttachmentName, const char *pszParticleName ); - int FindEffect( CNewParticleEffect *pEffect ); - int FindEffect( const char *pEffectName ); - void UpdateParticleEffect( ParticleEffectList_t *pEffect, bool bInitializing = false, int iOnlyThisControlPoint = -1 ); - void UpdateControlPoint( ParticleEffectList_t *pEffect, int iPoint, bool bInitializing ); - inline CNewParticleEffect *GetParticleEffectFromIdx( int idx ); - -private: - CBaseEntity *m_pOuter; - CUtlVector m_ParticleEffects; - int m_iDormancyChangedAtFrame; - - friend class CBaseEntity; -}; - -#include "particle_property_inlines.h" - -#endif // PARTICLEPROPERTY_H diff --git a/game/shared/particle_property_inlines.h b/game/shared/particle_property_inlines.h deleted file mode 100644 index 52c06b730..000000000 --- a/game/shared/particle_property_inlines.h +++ /dev/null @@ -1,38 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: Define inline functions for the CParticleProperty class. The -// definitions exist in this include file to avoid cluttering up -// particle_property.h, but this file should not be included from any- -// where else. -// -//============================================================================= - -#ifndef PARTICLEPROPERTY_H -#pragma message("Do not include particle_property_inlines.h from anywhere other than particle_property.h!") -#pragma error -#endif - -#ifndef PARTICLEPROPERTY_INLINES_H -#define PARTICLEPROPERTY_INLINES_H -#ifdef _WIN32 -#pragma once -#endif - - -/// Set the parent of a given control point on a given effect to the index of another control point. This is -/// in fact entirely redundant given the function is actually on the CNewParticleEffect, but is included here -/// for uniformity of interface. -void CParticleProperty::SetControlPointParent( CNewParticleEffect *pEffect, int whichControlPoint, int parentIdx ) -{ - pEffect->SetControlPointParent(whichControlPoint, parentIdx); -} - -/// Given an index, return a pointer to the relevant particle effect structure. For convenience. -CNewParticleEffect *CParticleProperty::GetParticleEffectFromIdx( int idx ) -{ - return m_ParticleEffects[idx].pParticleEffect.GetObject(); -} - - - -#endif // #ifndef PARTICLEPROPERTY_INLINES_H diff --git a/game/shared/particlesystemquery.cpp b/game/shared/particlesystemquery.cpp deleted file mode 100644 index ecc793293..000000000 --- a/game/shared/particlesystemquery.cpp +++ /dev/null @@ -1,621 +0,0 @@ -//===== Copyright 1996-2006, Valve Corporation, All rights reserved. ======// -// -// Purpose: particle system definitions -// -//===========================================================================// - -#include "cbase.h" -#include "particles/particles.h" -#include "baseparticleentity.h" -#include "entityparticletrail_shared.h" -#include "collisionutils.h" - -#if defined( CLIENT_DLL ) -#include "c_pixel_visibility.h" -#endif - -#ifdef TF_CLIENT_DLL -#include "tf_shareddefs.h" -#endif - -#ifdef GAME_DLL -#include "ai_utils.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -//----------------------------------------------------------------------------- -// Interface to allow the particle system to call back into the game code -//----------------------------------------------------------------------------- -class CParticleSystemQuery : public CBaseAppSystem< IParticleSystemQuery > -{ -public: - // Inherited from IParticleSystemQuery - virtual void GetLightingAtPoint( const Vector& vecOrigin, Color &cTint ); - virtual void TraceLine( const Vector& vecAbsStart, - const Vector& vecAbsEnd, unsigned int mask, - const IHandleEntity *ignore, - int collisionGroup, CBaseTrace *ptr ); - - virtual bool MovePointInsideControllingObject( CParticleCollection *pParticles, - void *pObject, - Vector *pPnt ); - virtual void GetRandomPointsOnControllingObjectHitBox( - CParticleCollection *pParticles, - int nControlPointNumber, - int nNumPtsOut, - float flBBoxScale, - int nNumTrysToGetAPointInsideTheModel, - Vector *pPntsOut, - Vector vecDirectionalBias, - Vector *pHitBoxRelativeCoordOut, - int *pHitBoxIndexOut - ); - - virtual int GetCollisionGroupFromName( const char *pszCollisionGroupName ); - - - virtual int GetControllingObjectHitBoxInfo( - CParticleCollection *pParticles, - int nControlPointNumber, - int nBufSize, // # of output slots available - ModelHitBoxInfo_t *pHitBoxOutputBuffer ); - - virtual bool IsPointInControllingObjectHitBox( - CParticleCollection *pParticles, - int nControlPointNumber, Vector vecPos, bool bBBoxOnly ); - - virtual Vector GetLocalPlayerPos( void ); - virtual void GetLocalPlayerEyeVectors( Vector *pForward, Vector *pRight = NULL, Vector *pUp = NULL ); - - virtual float GetPixelVisibility( int *pQueryHandle, const Vector &vecOrigin, float flScale ); - virtual void SetUpLightingEnvironment( const Vector& pos ); -}; - - -static CParticleSystemQuery s_ParticleSystemQuery; -IParticleSystemQuery *g_pParticleSystemQuery = &s_ParticleSystemQuery; - - -//----------------------------------------------------------------------------- -// Exposes the interface (so tools can get at it) -//----------------------------------------------------------------------------- -#ifdef CLIENT_DLL -EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CParticleSystemQuery, IParticleSystemQuery, PARTICLE_SYSTEM_QUERY_INTERFACE_VERSION, s_ParticleSystemQuery ); -#endif - -static CThreadFastMutex s_LightMutex; -static CThreadFastMutex s_BoneMutex; - -//----------------------------------------------------------------------------- -// Inherited from IParticleSystemQuery -//----------------------------------------------------------------------------- -void CParticleSystemQuery::GetLightingAtPoint( const Vector& vecOrigin, Color &cTint ) -{ -#ifdef GAME_DLL - - // FIXME: Go through to the engine from the server to get these values - cTint.SetColor( 255, 255, 255, 255 ); - -#else - - if ( engine->IsInGame() ) - { - s_LightMutex.Lock(); - // Compute our lighting at our position - Vector totalColor = engine->GetLightForPoint( vecOrigin, true ); - s_LightMutex.Unlock(); - - // Get our lighting information - cTint.SetColor( totalColor.x*255, totalColor.y*255, totalColor.z*255, 0 ); - } - else - { - // FIXME: Go through to the engine from the server to get these values - cTint.SetColor( 255, 255, 255, 255 ); - } - -#endif -} - -void CParticleSystemQuery::SetUpLightingEnvironment( const Vector& pos ) -{ -#ifndef GAME_DLL - if ( !engine->IsInGame() ) - return; - - s_LightMutex.Lock(); - modelrender->SetupLighting( pos ); - s_LightMutex.Unlock(); -#endif -} - -void CParticleSystemQuery::TraceLine( const Vector& vecAbsStart, - const Vector& vecAbsEnd, unsigned int mask, - const IHandleEntity *ignore, - int collisionGroup, CBaseTrace *ptr ) -{ - bool bDoTrace = false; -#ifndef GAME_DLL - bDoTrace = engine->IsInGame(); -#endif - if ( bDoTrace ) - { - trace_t tempTrace; - UTIL_TraceLine( vecAbsStart, vecAbsEnd, mask, ignore, collisionGroup, &tempTrace ); - memcpy( ptr, &tempTrace, sizeof ( CBaseTrace ) ); - } - else - { - ptr->startsolid = 0; - ptr->fraction = 1.0; - } - -} - -bool CParticleSystemQuery::MovePointInsideControllingObject( - CParticleCollection *pParticles, void *pObject, Vector *pPnt ) -{ -#ifdef GAME_DLL - return true; -#else - if (! pObject ) - return true; // accept the input point unmodified - - Ray_t ray; - trace_t tr; - ray.Init( *pPnt, *pPnt ); - enginetrace->ClipRayToEntity( ray, MASK_ALL, (CBaseEntity *) pObject, &tr ); - - return ( tr.startsolid ); -#endif -} - -#ifndef GAME_DLL -static float GetSurfaceCoord( float flRand, float flMinX, float flMaxX ) -{ - return Lerp( flRand, flMinX, flMaxX ); -} -#endif - -void CParticleSystemQuery::GetRandomPointsOnControllingObjectHitBox( - CParticleCollection *pParticles, - int nControlPointNumber, - int nNumPtsOut, - float flBBoxScale, - int nNumTrysToGetAPointInsideTheModel, - Vector *pPntsOut, - Vector vecDirectionalBias, - Vector *pHitBoxRelativeCoordOut, - int *pHitBoxIndexOut - ) -{ - - bool bSucesss = false; - - -#ifndef GAME_DLL - - EHANDLE *phMoveParent = reinterpret_cast ( pParticles->m_ControlPoints[nControlPointNumber].m_pObject ); - CBaseEntity *pMoveParent = NULL; - if ( phMoveParent ) - { - pMoveParent = *( phMoveParent ); - } - if ( pMoveParent ) - { - float flRandMax = flBBoxScale; - float flRandMin = 1.0 - flBBoxScale; - Vector vecBasePos; - pParticles->GetControlPointAtTime( nControlPointNumber, pParticles->m_flCurTime, &vecBasePos ); - - s_BoneMutex.Lock(); - C_BaseAnimating *pAnimating = pMoveParent->GetBaseAnimating(); - if ( pAnimating ) - { - - matrix3x4_t *hitboxbones[MAXSTUDIOBONES]; - - if ( pAnimating->HitboxToWorldTransforms( hitboxbones ) ) - { - - studiohdr_t *pStudioHdr = modelinfo->GetStudiomodel( pAnimating->GetModel() ); - - if ( pStudioHdr ) - { - mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( pAnimating->GetHitboxSet() ); - - if ( set ) - { - bSucesss = true; - - Vector vecWorldPosition; - float u = 0, v = 0, w = 0; - int nHitbox = 0; - int nNumIters = nNumTrysToGetAPointInsideTheModel; - if (! vecDirectionalBias.IsZero( 0.0001 ) ) - nNumIters = MAX( nNumIters, 5 ); - - for( int i=0 ; i < nNumPtsOut; i++) - { - int nTryCnt = nNumIters; - float flBestPointGoodness = -1.0e20; - do - { - int nTryHitbox = pParticles->RandomInt( 0, set->numhitboxes - 1 ); - mstudiobbox_t *pBox = set->pHitbox(nTryHitbox); - - float flTryU = pParticles->RandomFloat( flRandMin, flRandMax ); - float flTryV = pParticles->RandomFloat( flRandMin, flRandMax ); - float flTryW = pParticles->RandomFloat( flRandMin, flRandMax ); - - Vector vecLocalPosition; - vecLocalPosition.x = GetSurfaceCoord( flTryU, pBox->bbmin.x, pBox->bbmax.x ); - vecLocalPosition.y = GetSurfaceCoord( flTryV, pBox->bbmin.y, pBox->bbmax.y ); - vecLocalPosition.z = GetSurfaceCoord( flTryW, pBox->bbmin.z, pBox->bbmax.z ); - - Vector vecTryWorldPosition; - - VectorTransform( vecLocalPosition, *hitboxbones[pBox->bone], vecTryWorldPosition ); - - - float flPointGoodness = pParticles->RandomFloat( 0, 72 ) - + DotProduct( vecTryWorldPosition - vecBasePos, - vecDirectionalBias ); - - if ( nNumTrysToGetAPointInsideTheModel ) - { - // do a point in solid test - Ray_t ray; - trace_t tr; - ray.Init( vecTryWorldPosition, vecTryWorldPosition ); - enginetrace->ClipRayToEntity( ray, MASK_ALL, pMoveParent, &tr ); - if ( tr.startsolid ) - flPointGoodness += 1000.; // got a point inside! - } - if ( flPointGoodness > flBestPointGoodness ) - { - u = flTryU; - v = flTryV; - w = flTryW; - vecWorldPosition = vecTryWorldPosition; - nHitbox = nTryHitbox; - flBestPointGoodness = flPointGoodness; - } - } while ( nTryCnt-- ); - *( pPntsOut++ ) = vecWorldPosition; - if ( pHitBoxRelativeCoordOut ) - ( pHitBoxRelativeCoordOut++ )->Init( u, v, w ); - if ( pHitBoxIndexOut ) - *( pHitBoxIndexOut++ ) = nHitbox; - } - } - } - } - } - - if ( pMoveParent->IsBrushModel() ) - { - Vector vecMin; - Vector vecMax; - matrix3x4_t matOrientation; - Vector VecOrigin; - pMoveParent->GetRenderBounds( vecMin, vecMax ); - VecOrigin = pMoveParent->GetRenderOrigin(); - matOrientation = pMoveParent->EntityToWorldTransform(); - - - - Vector vecWorldPosition; - float u = 0, v = 0, w = 0; - int nHitbox = 0; - int nNumIters = nNumTrysToGetAPointInsideTheModel; - if (! vecDirectionalBias.IsZero( 0.0001 ) ) - nNumIters = MAX( nNumIters, 5 ); - - for( int i=0 ; i < nNumPtsOut; i++) - { - int nTryCnt = nNumIters; - float flBestPointGoodness = -1.0e20; - do - { - float flTryU = pParticles->RandomFloat( flRandMin, flRandMax ); - float flTryV = pParticles->RandomFloat( flRandMin, flRandMax ); - float flTryW = pParticles->RandomFloat( flRandMin, flRandMax ); - - Vector vecLocalPosition; - vecLocalPosition.x = GetSurfaceCoord( flTryU, vecMin.x, vecMax.x ); - vecLocalPosition.y = GetSurfaceCoord( flTryV, vecMin.y, vecMax.y ); - vecLocalPosition.z = GetSurfaceCoord( flTryW, vecMin.z, vecMax.z ); - - Vector vecTryWorldPosition; - VectorTransform( vecLocalPosition, matOrientation, vecTryWorldPosition ); - - float flPointGoodness = pParticles->RandomFloat( 0, 72 ) - + DotProduct( vecTryWorldPosition - vecBasePos, - vecDirectionalBias ); - - if ( nNumTrysToGetAPointInsideTheModel ) - { - // do a point in solid test - Ray_t ray; - trace_t tr; - ray.Init( vecTryWorldPosition, vecTryWorldPosition ); - enginetrace->ClipRayToEntity( ray, MASK_ALL, pMoveParent, &tr ); - if ( tr.startsolid ) - flPointGoodness += 1000.; // got a point inside! - } - if ( flPointGoodness > flBestPointGoodness ) - { - u = flTryU; - v = flTryV; - w = flTryW; - vecWorldPosition = vecTryWorldPosition; - nHitbox = 0; - flBestPointGoodness = flPointGoodness; - } - } while ( nTryCnt-- ); - *( pPntsOut++ ) = vecWorldPosition; - if ( pHitBoxRelativeCoordOut ) - ( pHitBoxRelativeCoordOut++ )->Init( u, v, w ); - if ( pHitBoxIndexOut ) - *( pHitBoxIndexOut++ ) = nHitbox; - } - } - - s_BoneMutex.Unlock(); - } -#endif - if (! bSucesss ) - { - // don't have a model or am in editor or something - fill return with control point - for( int i=0 ; i < nNumPtsOut; i++) - { - pPntsOut[i] = pParticles->m_ControlPoints[nControlPointNumber].m_Position; // fallback if anything goes wrong - - if ( pHitBoxIndexOut ) - pHitBoxIndexOut[i] = 0; - - if ( pHitBoxRelativeCoordOut ) - pHitBoxRelativeCoordOut[i].Init(); - } - } -} - - -int CParticleSystemQuery::GetControllingObjectHitBoxInfo( - CParticleCollection *pParticles, - int nControlPointNumber, - int nBufSize, // # of output slots available - ModelHitBoxInfo_t *pHitBoxOutputBuffer ) -{ - int nRet = 0; - -#ifndef GAME_DLL - s_BoneMutex.Lock(); - - EHANDLE *phMoveParent = reinterpret_cast ( pParticles->m_ControlPoints[nControlPointNumber].m_pObject ); - CBaseEntity *pMoveParent = NULL; - if ( phMoveParent ) - { - pMoveParent = *( phMoveParent ); - } - - if ( pMoveParent ) - { - C_BaseAnimating *pAnimating = pMoveParent->GetBaseAnimating(); - if ( pAnimating ) - { - matrix3x4_t *hitboxbones[MAXSTUDIOBONES]; - - if ( pAnimating->HitboxToWorldTransforms( hitboxbones ) ) - { - - studiohdr_t *pStudioHdr = modelinfo->GetStudiomodel( pAnimating->GetModel() ); - - if ( pStudioHdr ) - { - mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( pAnimating->GetHitboxSet() ); - - if ( set ) - { - nRet = MIN( nBufSize, set->numhitboxes ); - for( int i=0 ; i < nRet; i++ ) - { - mstudiobbox_t *pBox = set->pHitbox( i ); - pHitBoxOutputBuffer[i].m_vecBoxMins.x = pBox->bbmin.x; - pHitBoxOutputBuffer[i].m_vecBoxMins.y = pBox->bbmin.y; - pHitBoxOutputBuffer[i].m_vecBoxMins.z = pBox->bbmin.z; - - pHitBoxOutputBuffer[i].m_vecBoxMaxes.x = pBox->bbmax.x; - pHitBoxOutputBuffer[i].m_vecBoxMaxes.y = pBox->bbmax.y; - pHitBoxOutputBuffer[i].m_vecBoxMaxes.z = pBox->bbmax.z; - - pHitBoxOutputBuffer[i].m_Transform = *hitboxbones[pBox->bone]; - } - } - } - } - } - if ( pMoveParent->IsBrushModel() ) - { - Vector vecMin; - Vector vecMax; - matrix3x4_t matOrientation; - pMoveParent->GetRenderBounds( vecMin, vecMax ); - matOrientation = pMoveParent->EntityToWorldTransform(); - pHitBoxOutputBuffer[0].m_vecBoxMins = vecMin; - pHitBoxOutputBuffer[0].m_vecBoxMaxes = vecMax; - pHitBoxOutputBuffer[0].m_Transform = matOrientation; - nRet = 1; - } - } - s_BoneMutex.Unlock(); -#endif - return nRet; -} - - - -bool CParticleSystemQuery::IsPointInControllingObjectHitBox( - CParticleCollection *pParticles, - int nControlPointNumber, Vector vecPos, bool bBBoxOnly ) -{ - bool bSuccess = false; -#ifndef GAME_DLL - - EHANDLE *phMoveParent = reinterpret_cast ( pParticles->m_ControlPoints[nControlPointNumber].m_pObject ); - CBaseEntity *pMoveParent = NULL; - if ( phMoveParent ) - { - pMoveParent = *( phMoveParent ); - } - if ( pMoveParent ) - { - s_BoneMutex.Lock(); - C_BaseAnimating *pAnimating = pMoveParent->GetBaseAnimating(); - - bool bInBBox = false; - Vector vecBBoxMin; - Vector vecBBoxMax; - Vector vecOrigin; - - vecBBoxMin = pMoveParent->CollisionProp()->OBBMins(); - vecBBoxMax = pMoveParent->CollisionProp()->OBBMaxs(); - - matrix3x4_t matOrientation; - matOrientation = pMoveParent->EntityToWorldTransform(); - Vector vecLocalPos; - VectorITransform( vecPos, matOrientation, vecLocalPos ); - if ( IsPointInBox( vecLocalPos, vecBBoxMin, vecBBoxMax ) ) - bInBBox = true; - - if ( bInBBox && bBBoxOnly ) - bSuccess = true; - else if ( pAnimating && bInBBox ) - { - matrix3x4_t *hitboxbones[MAXSTUDIOBONES]; - if ( pAnimating->HitboxToWorldTransforms( hitboxbones ) ) - { - - studiohdr_t *pStudioHdr = modelinfo->GetStudiomodel( pAnimating->GetModel() ); - - if ( pStudioHdr ) - { - mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( pAnimating->GetHitboxSet() ); - - if ( set ) - { - // do a point in solid test - Ray_t ray; - trace_t tr; - ray.Init( vecPos, vecPos ); - enginetrace->ClipRayToEntity( ray, MASK_ALL, pMoveParent, &tr ); - if ( tr.startsolid ) - bSuccess = true; - } - } - } - } - else if ( pMoveParent->IsBrushModel() && bInBBox ) - { - // do a point in solid test - Ray_t ray; - trace_t tr; - ray.Init( vecPos, vecPos ); - enginetrace->ClipRayToEntity( ray, MASK_ALL, pMoveParent, &tr ); - if ( tr.startsolid ) - bSuccess = true; - } - - s_BoneMutex.Unlock(); - } -#endif - return bSuccess; -} - - -struct CollisionGroupNameRecord_t -{ - const char *m_pszGroupName; - int m_nGroupID; -}; - - -static CollisionGroupNameRecord_t s_NameMap[]={ - { "NONE", COLLISION_GROUP_NONE }, - { "DEBRIS", COLLISION_GROUP_DEBRIS }, - { "INTERACTIVE", COLLISION_GROUP_INTERACTIVE }, - { "NPC", COLLISION_GROUP_NPC }, - { "ACTOR", COLLISION_GROUP_NPC_ACTOR }, - { "PASSABLE", COLLISION_GROUP_PASSABLE_DOOR }, -#if defined( TF_CLIENT_DLL ) - { "ROCKETS", TFCOLLISION_GROUP_ROCKETS }, -#endif -}; - - -int CParticleSystemQuery::GetCollisionGroupFromName( const char *pszCollisionGroupName ) -{ - for(size_t i = 0; i < ARRAYSIZE( s_NameMap ); i++ ) - { - if ( ! stricmp( s_NameMap[i].m_pszGroupName, pszCollisionGroupName ) ) - return s_NameMap[i].m_nGroupID; - } - return COLLISION_GROUP_NONE; -} - -Vector CParticleSystemQuery::GetLocalPlayerPos( void ) -{ -#ifdef CLIENT_DLL - C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); - if ( !pPlayer ) - return vec3_origin; - return pPlayer->WorldSpaceCenter(); -#else - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( !pPlayer ) - return vec3_origin; - return pPlayer->WorldSpaceCenter(); -#endif -} - -void CParticleSystemQuery::GetLocalPlayerEyeVectors( Vector *pForward, Vector *pRight, Vector *pUp ) -{ -#ifdef CLIENT_DLL - C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); - if ( !pPlayer ) - { - *pForward = vec3_origin; - *pRight = vec3_origin; - *pUp = vec3_origin; - return; - } - pPlayer->EyeVectors( pForward, pRight, pUp ); -#else - CBasePlayer *pPlayer = AI_GetSinglePlayer(); - if ( !pPlayer ) - { - *pForward = vec3_origin; - *pRight = vec3_origin; - *pUp = vec3_origin; - return; - } - pPlayer->EyeVectors( pForward, pRight, pUp ); -#endif -} - -float CParticleSystemQuery::GetPixelVisibility( int *pQueryHandle, const Vector &vecOrigin, float flScale ) -{ -#ifdef CLIENT_DLL - pixelvis_queryparams_t params; - params.Init( vecOrigin, flScale, 1.0 ); - float flVisibility = PixelVisibility_FractionVisible( params, pQueryHandle ); - flVisibility = MAX( 0.0f, flVisibility ); - return flVisibility; -#else - return 0.0f; -#endif -} diff --git a/game/shared/physics_main_shared.cpp b/game/shared/physics_main_shared.cpp deleted file mode 100644 index 7230dfbc8..000000000 --- a/game/shared/physics_main_shared.cpp +++ /dev/null @@ -1,2213 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#include "cbase.h" -#include "engine/IEngineSound.h" -#include "mempool.h" -#include "movevars_shared.h" -#include "utlrbtree.h" -#include "tier0/vprof.h" -#include "entitydatainstantiator.h" -#include "positionwatcher.h" -#include "movetype_push.h" -#include "vphysicsupdateai.h" -#include "igamesystem.h" -#include "utlmultilist.h" -#include "tier1/callqueue.h" - -#ifdef PORTAL - #include "portal_util_shared.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// memory pool for storing links between entities -static CMemoryPool g_EdictTouchLinks( sizeof(touchlink_t), MAX_EDICTS, CMemoryPool::GROW_NONE, "g_EdictTouchLinks"); -static CMemoryPool g_EntityGroundLinks( sizeof( groundlink_t ), MAX_EDICTS, CMemoryPool::GROW_NONE, "g_EntityGroundLinks"); - -struct watcher_t -{ - EHANDLE hWatcher; - IWatcherCallback *pWatcherCallback; -}; - -static CUtlMultiList g_WatcherList; -class CWatcherList -{ -public: - //CWatcherList(); NOTE: Dataobj doesn't support constructors - it zeros the memory - ~CWatcherList(); // frees the positionwatcher_t's to the pool - void Init(); - - void NotifyPositionChanged( CBaseEntity *pEntity ); - void NotifyVPhysicsStateChanged( IPhysicsObject *pPhysics, CBaseEntity *pEntity, bool bAwake ); - - void AddToList( CBaseEntity *pWatcher ); - void RemoveWatcher( CBaseEntity *pWatcher ); - -private: - int GetCallbackObjects( IWatcherCallback **pList, int listMax ); - - unsigned short Find( CBaseEntity *pEntity ); - unsigned short m_list; -}; - -int linksallocated = 0; -int groundlinksallocated = 0; - -// Prints warnings if any entity think functions take longer than this many milliseconds -#ifdef _DEBUG -#define DEF_THINK_LIMIT "20" -#else -#define DEF_THINK_LIMIT "10" -#endif - -ConVar think_limit( "think_limit", DEF_THINK_LIMIT, FCVAR_REPLICATED, "Maximum think time in milliseconds, warning is printed if this is exceeded." ); -#ifndef CLIENT_DLL -ConVar debug_touchlinks( "debug_touchlinks", "0", 0, "Spew touch link activity" ); -#define DebugTouchlinks() debug_touchlinks.GetBool() -#else -#define DebugTouchlinks() false -#endif - - - -//----------------------------------------------------------------------------- -// Portal-specific hack designed to eliminate re-entrancy in touch functions -//----------------------------------------------------------------------------- -class CPortalTouchScope -{ -public: - CPortalTouchScope(); - ~CPortalTouchScope(); - -public: - static int m_nDepth; - static CCallQueue m_CallQueue; -}; - -int CPortalTouchScope::m_nDepth = 0; -CCallQueue CPortalTouchScope::m_CallQueue; - -CCallQueue *GetPortalCallQueue() -{ - return ( CPortalTouchScope::m_nDepth > 0 ) ? &CPortalTouchScope::m_CallQueue : NULL; -} - -CPortalTouchScope::CPortalTouchScope() -{ - ++m_nDepth; -} - -CPortalTouchScope::~CPortalTouchScope() -{ - Assert( m_nDepth >= 1 ); - if ( --m_nDepth == 0 ) - { - m_CallQueue.CallQueued(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: System for hanging objects off of CBaseEntity, etc. -// Externalized data objects ( see sharreddefs.h for enum ) -//----------------------------------------------------------------------------- -class CDataObjectAccessSystem : public CAutoGameSystem -{ -public: - - enum - { - MAX_ACCESSORS = 32, - }; - - CDataObjectAccessSystem() - { - COMPILE_TIME_ASSERT( (int)NUM_DATAOBJECT_TYPES <= (int)MAX_ACCESSORS ); - - Q_memset( m_Accessors, 0, sizeof( m_Accessors ) ); - } - - virtual bool Init() - { - AddDataAccessor( TOUCHLINK, new CEntityDataInstantiator< touchlink_t > ); - AddDataAccessor( GROUNDLINK, new CEntityDataInstantiator< groundlink_t > ); - AddDataAccessor( STEPSIMULATION, new CEntityDataInstantiator< StepSimulationData > ); - AddDataAccessor( MODELWIDTHSCALE, new CEntityDataInstantiator< ModelWidthScale > ); - AddDataAccessor( POSITIONWATCHER, new CEntityDataInstantiator< CWatcherList > ); - AddDataAccessor( PHYSICSPUSHLIST, new CEntityDataInstantiator< physicspushlist_t > ); - AddDataAccessor( VPHYSICSUPDATEAI, new CEntityDataInstantiator< vphysicsupdateai_t > ); - AddDataAccessor( VPHYSICSWATCHER, new CEntityDataInstantiator< CWatcherList > ); - - return true; - } - - virtual void Shutdown() - { - for ( int i = 0; i < MAX_ACCESSORS; i++ ) - { - delete m_Accessors[ i ]; - m_Accessors[ i ] = 0; - } - } - - void *GetDataObject( int type, const CBaseEntity *instance ) - { - if ( !IsValidType( type ) ) - { - Assert( !"Bogus type" ); - return NULL; - } - return m_Accessors[ type ]->GetDataObject( instance ); - } - - void *CreateDataObject( int type, CBaseEntity *instance ) - { - if ( !IsValidType( type ) ) - { - Assert( !"Bogus type" ); - return NULL; - } - - return m_Accessors[ type ]->CreateDataObject( instance ); - } - - void DestroyDataObject( int type, CBaseEntity *instance ) - { - if ( !IsValidType( type ) ) - { - Assert( !"Bogus type" ); - return; - } - - m_Accessors[ type ]->DestroyDataObject( instance ); - } - -private: - - bool IsValidType( int type ) const - { - if ( type < 0 || type >= MAX_ACCESSORS ) - return false; - - if ( m_Accessors[ type ] == NULL ) - return false; - return true; - } - - void AddDataAccessor( int type, IEntityDataInstantiator *instantiator ) - { - if ( type < 0 || type >= MAX_ACCESSORS ) - { - Assert( !"AddDataAccessor with out of range type!!!\n" ); - return; - } - - Assert( instantiator ); - - if ( m_Accessors[ type ] != NULL ) - { - Assert( !"AddDataAccessor, duplicate adds!!!\n" ); - return; - } - - m_Accessors[ type ] = instantiator; - } - - IEntityDataInstantiator *m_Accessors[ MAX_ACCESSORS ]; -}; - -static CDataObjectAccessSystem g_DataObjectAccessSystem; - -bool CBaseEntity::HasDataObjectType( int type ) const -{ - Assert( type >= 0 && type < NUM_DATAOBJECT_TYPES ); - return ( m_fDataObjectTypes & (1<= 0 && type < NUM_DATAOBJECT_TYPES ); - m_fDataObjectTypes |= (1<= 0 && type < NUM_DATAOBJECT_TYPES ); - m_fDataObjectTypes &= ~(1<= 0 && type < NUM_DATAOBJECT_TYPES ); - if ( !HasDataObjectType( type ) ) - return NULL; - return g_DataObjectAccessSystem.GetDataObject( type, this ); -} - -void *CBaseEntity::CreateDataObject( int type ) -{ - Assert( type >= 0 && type < NUM_DATAOBJECT_TYPES ); - AddDataObjectType( type ); - return g_DataObjectAccessSystem.CreateDataObject( type, this ); -} - -void CBaseEntity::DestroyDataObject( int type ) -{ - Assert( type >= 0 && type < NUM_DATAOBJECT_TYPES ); - if ( !HasDataObjectType( type ) ) - return; - g_DataObjectAccessSystem.DestroyDataObject( type, this ); - RemoveDataObjectType( type ); -} - -void CWatcherList::Init() -{ - m_list = g_WatcherList.CreateList(); -} - -CWatcherList::~CWatcherList() -{ - g_WatcherList.DestroyList( m_list ); -} - -int CWatcherList::GetCallbackObjects( IWatcherCallback **pList, int listMax ) -{ - int index = 0; - unsigned short next = g_WatcherList.InvalidIndex(); - for ( unsigned short node = g_WatcherList.Head( m_list ); node != g_WatcherList.InvalidIndex(); node = next ) - { - next = g_WatcherList.Next( node ); - watcher_t *pNode = &g_WatcherList.Element(node); - if ( pNode->hWatcher.Get() ) - { - pList[index] = pNode->pWatcherCallback; - index++; - if ( index >= listMax ) - { - Assert(0); - return index; - } - } - else - { - g_WatcherList.Remove( m_list, node ); - } - } - return index; -} - -void CWatcherList::NotifyPositionChanged( CBaseEntity *pEntity ) -{ - IWatcherCallback *pCallbacks[1024]; // HACKHACK: Assumes this list is big enough - int count = GetCallbackObjects( pCallbacks, ARRAYSIZE(pCallbacks) ); - for ( int i = 0; i < count; i++ ) - { - IPositionWatcher *pWatcher = assert_cast(pCallbacks[i]); - if ( pWatcher ) - { - pWatcher->NotifyPositionChanged(pEntity); - } - } -} - -void CWatcherList::NotifyVPhysicsStateChanged( IPhysicsObject *pPhysics, CBaseEntity *pEntity, bool bAwake ) -{ - IWatcherCallback *pCallbacks[1024]; // HACKHACK: Assumes this list is big enough! - int count = GetCallbackObjects( pCallbacks, ARRAYSIZE(pCallbacks) ); - for ( int i = 0; i < count; i++ ) - { - IVPhysicsWatcher *pWatcher = assert_cast(pCallbacks[i]); - if ( pWatcher ) - { - pWatcher->NotifyVPhysicsStateChanged(pPhysics, pEntity, bAwake); - } - } -} - -unsigned short CWatcherList::Find( CBaseEntity *pEntity ) -{ - unsigned short next = g_WatcherList.InvalidIndex(); - for ( unsigned short node = g_WatcherList.Head( m_list ); node != g_WatcherList.InvalidIndex(); node = next ) - { - next = g_WatcherList.Next( node ); - watcher_t *pNode = &g_WatcherList.Element(node); - if ( pNode->hWatcher.Get() == pEntity ) - { - return node; - } - } - return g_WatcherList.InvalidIndex(); -} - -void CWatcherList::RemoveWatcher( CBaseEntity *pEntity ) -{ - unsigned short node = Find( pEntity ); - if ( node != g_WatcherList.InvalidIndex() ) - { - g_WatcherList.Remove( m_list, node ); - } -} - - -void CWatcherList::AddToList( CBaseEntity *pWatcher ) -{ - unsigned short node = Find( pWatcher ); - if ( node == g_WatcherList.InvalidIndex() ) - { - watcher_t watcher; - watcher.hWatcher = pWatcher; - // save this separately so we can use the EHANDLE to test for deletion - watcher.pWatcherCallback = dynamic_cast (pWatcher); - - if ( watcher.pWatcherCallback ) - { - g_WatcherList.AddToTail( m_list, watcher ); - } - } -} - -static void AddWatcherToEntity( CBaseEntity *pWatcher, CBaseEntity *pEntity, int watcherType ) -{ - CWatcherList *pList = (CWatcherList *)pEntity->GetDataObject(watcherType); - if ( !pList ) - { - pList = ( CWatcherList * )pEntity->CreateDataObject( watcherType ); - pList->Init(); - } - - pList->AddToList( pWatcher ); -} - -static void RemoveWatcherFromEntity( CBaseEntity *pWatcher, CBaseEntity *pEntity, int watcherType ) -{ - CWatcherList *pList = (CWatcherList *)pEntity->GetDataObject(watcherType); - if ( pList ) - { - pList->RemoveWatcher( pWatcher ); - } -} - -void WatchPositionChanges( CBaseEntity *pWatcher, CBaseEntity *pMovingEntity ) -{ - AddWatcherToEntity( pWatcher, pMovingEntity, POSITIONWATCHER ); -} - -void RemovePositionWatcher( CBaseEntity *pWatcher, CBaseEntity *pMovingEntity ) -{ - RemoveWatcherFromEntity( pWatcher, pMovingEntity, POSITIONWATCHER ); -} - -void ReportPositionChanged( CBaseEntity *pMovedEntity ) -{ - CWatcherList *pList = (CWatcherList *)pMovedEntity->GetDataObject(POSITIONWATCHER); - if ( pList ) - { - pList->NotifyPositionChanged( pMovedEntity ); - } -} - -void WatchVPhysicsStateChanges( CBaseEntity *pWatcher, CBaseEntity *pPhysicsEntity ) -{ - AddWatcherToEntity( pWatcher, pPhysicsEntity, VPHYSICSWATCHER ); -} - -void RemoveVPhysicsStateWatcher( CBaseEntity *pWatcher, CBaseEntity *pPhysicsEntity ) -{ - AddWatcherToEntity( pWatcher, pPhysicsEntity, VPHYSICSWATCHER ); -} - -void ReportVPhysicsStateChanged( IPhysicsObject *pPhysics, CBaseEntity *pEntity, bool bAwake ) -{ - CWatcherList *pList = (CWatcherList *)pEntity->GetDataObject(VPHYSICSWATCHER); - if ( pList ) - { - pList->NotifyVPhysicsStateChanged( pPhysics, pEntity, bAwake ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseEntity::DestroyAllDataObjects( void ) -{ - int i; - for ( i = 0; i < NUM_DATAOBJECT_TYPES; i++ ) - { - if ( HasDataObjectType( i ) ) - { - DestroyDataObject( i ); - } - } -} - -//----------------------------------------------------------------------------- -// For debugging -//----------------------------------------------------------------------------- - -#ifdef GAME_DLL - -void SpewLinks() -{ - int nCount = 0; - for ( CBaseEntity *pClass = gEntList.FirstEnt(); pClass != NULL; pClass = gEntList.NextEnt(pClass) ) - { - if ( pClass /*&& !pClass->IsDormant()*/ ) - { - touchlink_t *root = ( touchlink_t * )pClass->GetDataObject( TOUCHLINK ); - if ( root ) - { - - // check if the edict is already in the list - for ( touchlink_t *link = root->nextLink; link != root; link = link->nextLink ) - { - ++nCount; - Msg("[%d] (%d) Link %d (%s) -> %d (%s)\n", nCount, pClass->IsDormant(), - pClass->entindex(), pClass->GetClassname(), - link->entityTouched->entindex(), link->entityTouched->GetClassname() ); - } - } - } - } -} - -#endif - -//----------------------------------------------------------------------------- -// Returns the actual gravity -//----------------------------------------------------------------------------- -static inline float GetActualGravity( CBaseEntity *pEnt ) -{ - float ent_gravity = pEnt->GetGravity(); - if ( ent_gravity == 0.0f ) - { - ent_gravity = 1.0f; - } - - return ent_gravity * sv_gravity.GetFloat(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : inline touchlink_t -//----------------------------------------------------------------------------- -inline touchlink_t *AllocTouchLink( void ) -{ - touchlink_t *link = (touchlink_t*)g_EdictTouchLinks.Alloc( sizeof(touchlink_t) ); - if ( link ) - { - ++linksallocated; - } - else - { - DevWarning( "AllocTouchLink: failed to allocate touchlink_t.\n" ); - } - - return link; -} - -static touchlink_t *g_pNextLink = NULL; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *link - -// Output : inline void -//----------------------------------------------------------------------------- -inline void FreeTouchLink( touchlink_t *link ) -{ - if ( link ) - { - if ( link == g_pNextLink ) - { - g_pNextLink = link->nextLink; - } - --linksallocated; - link->prevLink = link->nextLink = NULL; - } - - // Necessary to catch crashes - g_EdictTouchLinks.Free( link ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : inline groundlink_t -//----------------------------------------------------------------------------- -inline groundlink_t *AllocGroundLink( void ) -{ - groundlink_t *link = (groundlink_t*)g_EntityGroundLinks.Alloc( sizeof(groundlink_t) ); - if ( link ) - { - ++groundlinksallocated; - } - else - { - DevMsg( "AllocGroundLink: failed to allocate groundlink_t.!!!\n" ); - } - - return link; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *link - -// Output : inline void -//----------------------------------------------------------------------------- -inline void FreeGroundLink( groundlink_t *link ) -{ - if ( link ) - { - --groundlinksallocated; - } - - g_EntityGroundLinks.Free( link ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseEntity::IsCurrentlyTouching( void ) const -{ - if ( HasDataObjectType( TOUCHLINK ) ) - { - return true; - } - - return false; -} - -static bool g_bCleanupDatObject = true; - -//----------------------------------------------------------------------------- -// Purpose: Checks to see if any entities that have been touching this one -// have stopped touching it, and notify the entity if so. -// Called at the end of a frame, after all the entities have run -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsCheckForEntityUntouch( void ) -{ - Assert( g_pNextLink == NULL ); - - touchlink_t *link; - - touchlink_t *root = ( touchlink_t * )GetDataObject( TOUCHLINK ); - if ( root ) - { -#ifdef PORTAL - CPortalTouchScope scope; -#endif - bool saveCleanup = g_bCleanupDatObject; - g_bCleanupDatObject = false; - - link = root->nextLink; - while ( link != root ) - { - g_pNextLink = link->nextLink; - - // these touchlinks are not polled. The ents are touching due to an outside - // system that will add/delete them as necessary (vphysics in this case) - if ( link->touchStamp == TOUCHSTAMP_EVENT_DRIVEN ) - { - // refresh the touch call - PhysicsTouch( link->entityTouched ); - } - else - { - // check to see if the touch stamp is up to date - if ( link->touchStamp != touchStamp ) - { - // stamp is out of data, so entities are no longer touching - // remove self from other entities touch list - PhysicsNotifyOtherOfUntouch( this, link->entityTouched ); - - // remove other entity from this list - PhysicsRemoveToucher( this, link ); - } - } - - link = g_pNextLink; - } - - g_bCleanupDatObject = saveCleanup; - - // Nothing left in list, destroy root - if ( root->nextLink == root && - root->prevLink == root ) - { - DestroyDataObject( TOUCHLINK ); - } - } - - g_pNextLink = NULL; - - SetCheckUntouch( false ); -} - -//----------------------------------------------------------------------------- -// Purpose: notifies an entity than another touching entity has moved out of contact. -// Input : *other - the entity to be acted upon -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsNotifyOtherOfUntouch( CBaseEntity *ent, CBaseEntity *other ) -{ - if ( !other ) - return; - - // loop through ed's touch list, looking for the notifier - // remove and call untouch if found - touchlink_t *root = ( touchlink_t * )other->GetDataObject( TOUCHLINK ); - if ( root ) - { - touchlink_t *link = root->nextLink; - while ( link != root ) - { - if ( link->entityTouched == ent ) - { - PhysicsRemoveToucher( other, link ); - - // Check for complete removal - if ( g_bCleanupDatObject && - root->nextLink == root && - root->prevLink == root ) - { - other->DestroyDataObject( TOUCHLINK ); - } - return; - } - - link = link->nextLink; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: removes a toucher from the list -// Input : *link - the link to remove -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsRemoveToucher( CBaseEntity *otherEntity, touchlink_t *link ) -{ - // Every start Touch gets a corresponding end touch - if ( (link->flags & FTOUCHLINK_START_TOUCH) && - link->entityTouched != NULL && - otherEntity != NULL ) - { - otherEntity->EndTouch( link->entityTouched ); - } - - link->nextLink->prevLink = link->prevLink; - link->prevLink->nextLink = link->nextLink; - - if ( DebugTouchlinks() ) - Msg( "remove 0x%x: %s-%s (%d-%d) [%d in play, %d max]\n", link, link->entityTouched->GetDebugName(), otherEntity->GetDebugName(), link->entityTouched->entindex(), otherEntity->entindex(), linksallocated, g_EdictTouchLinks.PeakCount() ); - FreeTouchLink( link ); -} - -//----------------------------------------------------------------------------- -// Purpose: Clears all touches from the list -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsRemoveTouchedList( CBaseEntity *ent ) -{ -#ifdef PORTAL - CPortalTouchScope scope; -#endif - - touchlink_t *link, *nextLink; - - touchlink_t *root = ( touchlink_t * )ent->GetDataObject( TOUCHLINK ); - if ( root ) - { - link = root->nextLink; - bool saveCleanup = g_bCleanupDatObject; - g_bCleanupDatObject = false; - while ( link && link != root ) - { - nextLink = link->nextLink; - - // notify the other entity that this ent has gone away - PhysicsNotifyOtherOfUntouch( ent, link->entityTouched ); - - // kill it - if ( DebugTouchlinks() ) - Msg( "remove 0x%x: %s-%s (%d-%d) [%d in play, %d max]\n", link, ent->GetDebugName(), link->entityTouched->GetDebugName(), ent->entindex(), link->entityTouched->entindex(), linksallocated, g_EdictTouchLinks.PeakCount() ); - FreeTouchLink( link ); - link = nextLink; - } - - g_bCleanupDatObject = saveCleanup; - ent->DestroyDataObject( TOUCHLINK ); - } - - ent->touchStamp = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *other - -// Output : groundlink_t -//----------------------------------------------------------------------------- -groundlink_t *CBaseEntity::AddEntityToGroundList( CBaseEntity *other ) -{ - groundlink_t *link; - - if ( this == other ) - return NULL; - - // check if the edict is already in the list - groundlink_t *root = ( groundlink_t * )GetDataObject( GROUNDLINK ); - if ( root ) - { - for ( link = root->nextLink; link != root; link = link->nextLink ) - { - if ( link->entity == other ) - { - // no more to do - return link; - } - } - } - else - { - root = ( groundlink_t * )CreateDataObject( GROUNDLINK ); - root->prevLink = root->nextLink = root; - } - - // entity is not in list, so it's a new touch - // add it to the touched list and then call the touch function - - // build new link - link = AllocGroundLink(); - if ( !link ) - return NULL; - - link->entity = other; - // add it to the list - link->nextLink = root->nextLink; - link->prevLink = root; - link->prevLink->nextLink = link; - link->nextLink->prevLink = link; - - PhysicsStartGroundContact( other ); - - return link; -} - -//----------------------------------------------------------------------------- -// Purpose: Called whenever two entities come in contact -// Input : *pentOther - the entity who it has touched -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsStartGroundContact( CBaseEntity *pentOther ) -{ - if ( !pentOther ) - return; - - if ( !(IsMarkedForDeletion() || pentOther->IsMarkedForDeletion()) ) - { - pentOther->StartGroundContact( this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: notifies an entity than another touching entity has moved out of contact. -// Input : *other - the entity to be acted upon -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsNotifyOtherOfGroundRemoval( CBaseEntity *ent, CBaseEntity *other ) -{ - if ( !other ) - return; - - // loop through ed's touch list, looking for the notifier - // remove and call untouch if found - groundlink_t *root = ( groundlink_t * )other->GetDataObject( GROUNDLINK ); - if ( root ) - { - groundlink_t *link = root->nextLink; - while ( link != root ) - { - if ( link->entity == ent ) - { - PhysicsRemoveGround( other, link ); - - if ( root->nextLink == root && - root->prevLink == root ) - { - other->DestroyDataObject( GROUNDLINK ); - } - return; - } - - link = link->nextLink; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: removes a toucher from the list -// Input : *link - the link to remove -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsRemoveGround( CBaseEntity *other, groundlink_t *link ) -{ - // Every start Touch gets a corresponding end touch - if ( link->entity != NULL ) - { - CBaseEntity *linkEntity = link->entity; - CBaseEntity *otherEntity = other; - if ( linkEntity && otherEntity ) - { - linkEntity->EndGroundContact( otherEntity ); - } - } - - link->nextLink->prevLink = link->prevLink; - link->prevLink->nextLink = link->nextLink; - FreeGroundLink( link ); -} - -//----------------------------------------------------------------------------- -// Purpose: static method to remove ground list for an entity -// Input : *ent - -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsRemoveGroundList( CBaseEntity *ent ) -{ - groundlink_t *link, *nextLink; - - groundlink_t *root = ( groundlink_t * )ent->GetDataObject( GROUNDLINK ); - if ( root ) - { - link = root->nextLink; - while ( link && link != root ) - { - nextLink = link->nextLink; - - // notify the other entity that this ent has gone away - PhysicsNotifyOtherOfGroundRemoval( ent, link->entity ); - - // kill it - FreeGroundLink( link ); - - link = nextLink; - } - - ent->DestroyDataObject( GROUNDLINK ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Called every frame that two entities are touching -// Input : *pentOther - the entity who it has touched -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsTouch( CBaseEntity *pentOther ) -{ - if ( pentOther ) - { - if ( !(IsMarkedForDeletion() || pentOther->IsMarkedForDeletion()) ) - { - Touch( pentOther ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Called whenever two entities come in contact -// Input : *pentOther - the entity who it has touched -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsStartTouch( CBaseEntity *pentOther ) -{ - if ( pentOther ) - { - if ( !(IsMarkedForDeletion() || pentOther->IsMarkedForDeletion()) ) - { - StartTouch( pentOther ); - Touch( pentOther ); - } - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: Marks in an entity that it is touching another entity, and calls -// it's Touch() function if it is a new touch. -// Stamps the touch link with the new time so that when we check for -// untouch we know things haven't changed. -// Input : *other - entity that it is in contact with -//----------------------------------------------------------------------------- -touchlink_t *CBaseEntity::PhysicsMarkEntityAsTouched( CBaseEntity *other ) -{ - touchlink_t *link; - - if ( this == other ) - return NULL; - - // Entities in hierarchy should not interact - if ( (this->GetMoveParent() == other) || (this == other->GetMoveParent()) ) - return NULL; - - // check if either entity doesn't generate touch functions - if ( (GetFlags() | other->GetFlags()) & FL_DONTTOUCH ) - return NULL; - - // Pure triggers should not touch each other - if ( IsSolidFlagSet( FSOLID_TRIGGER ) && other->IsSolidFlagSet( FSOLID_TRIGGER ) ) - { - if (!IsSolid() && !other->IsSolid()) - return NULL; - } - - // Don't do touching if marked for deletion - if ( other->IsMarkedForDeletion() ) - { - return NULL; - } - - if ( IsMarkedForDeletion() ) - { - return NULL; - } - -#ifdef PORTAL - CPortalTouchScope scope; -#endif - - // check if the edict is already in the list - touchlink_t *root = ( touchlink_t * )GetDataObject( TOUCHLINK ); - if ( root ) - { - for ( link = root->nextLink; link != root; link = link->nextLink ) - { - if ( link->entityTouched == other ) - { - // update stamp - link->touchStamp = touchStamp; - - if ( !CBaseEntity::sm_bDisableTouchFuncs ) - { - PhysicsTouch( other ); - } - - // no more to do - return link; - } - } - } - else - { - // Allocate the root object - root = ( touchlink_t * )CreateDataObject( TOUCHLINK ); - root->nextLink = root->prevLink = root; - } - - // entity is not in list, so it's a new touch - // add it to the touched list and then call the touch function - - // build new link - link = AllocTouchLink(); - if ( DebugTouchlinks() ) - Msg( "add 0x%x: %s-%s (%d-%d) [%d in play, %d max]\n", link, GetDebugName(), other->GetDebugName(), entindex(), other->entindex(), linksallocated, g_EdictTouchLinks.PeakCount() ); - if ( !link ) - return NULL; - - link->touchStamp = touchStamp; - link->entityTouched = other; - link->flags = 0; - // add it to the list - link->nextLink = root->nextLink; - link->prevLink = root; - link->prevLink->nextLink = link; - link->nextLink->prevLink = link; - - // non-solid entities don't get touched - bool bShouldTouch = (IsSolid() && !IsSolidFlagSet(FSOLID_VOLUME_CONTENTS)) || IsSolidFlagSet(FSOLID_TRIGGER); - if ( bShouldTouch && !other->IsSolidFlagSet(FSOLID_TRIGGER) ) - { - link->flags |= FTOUCHLINK_START_TOUCH; - if ( !CBaseEntity::sm_bDisableTouchFuncs ) - { - PhysicsStartTouch( other ); - } - } - - return link; -} - -static trace_t g_TouchTrace; -const trace_t &CBaseEntity::GetTouchTrace( void ) -{ - return g_TouchTrace; -} - - -//----------------------------------------------------------------------------- -// Purpose: Marks the fact that two edicts are in contact -// Input : *other - other entity -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsMarkEntitiesAsTouching( CBaseEntity *other, trace_t &trace ) -{ - g_TouchTrace = trace; - PhysicsMarkEntityAsTouched( other ); - other->PhysicsMarkEntityAsTouched( this ); -} - -void CBaseEntity::PhysicsMarkEntitiesAsTouchingEventDriven( CBaseEntity *other, trace_t &trace ) -{ - g_TouchTrace = trace; - g_TouchTrace.m_pEnt = other; - - touchlink_t *link; - link = this->PhysicsMarkEntityAsTouched( other ); - if ( link ) - { - // mark these links as event driven so they aren't untouched the next frame - // when the physics doesn't refresh them - link->touchStamp = TOUCHSTAMP_EVENT_DRIVEN; - } - g_TouchTrace.m_pEnt = this; - link = other->PhysicsMarkEntityAsTouched( this ); - if ( link ) - { - link->touchStamp = TOUCHSTAMP_EVENT_DRIVEN; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Two entities have touched, so run their touch functions -// Input : *other - -// *ptrace - -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsImpact( CBaseEntity *other, trace_t &trace ) -{ - if ( !other ) - { - return; - } - - // If either of the entities is flagged to be deleted, - // don't call the touch functions - if ( ( GetFlags() | other->GetFlags() ) & FL_KILLME ) - { - return; - } - - PhysicsMarkEntitiesAsTouching( other, trace ); -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the mask of what is solid for the given entity -// Output : unsigned int -//----------------------------------------------------------------------------- -unsigned int CBaseEntity::PhysicsSolidMaskForEntity( void ) const -{ - return MASK_SOLID; -} - - -//----------------------------------------------------------------------------- -// Computes the water level + type -//----------------------------------------------------------------------------- -void CBaseEntity::UpdateWaterState() -{ - // FIXME: This computation is nonsensical for rigid child attachments - // Should we just grab the type + level of the parent? - // Probably for rigid children anyways... - - // Compute the point to check for water state - Vector point; - CollisionProp()->NormalizedToWorldSpace( Vector( 0.5f, 0.5f, 0.0f ), &point ); - - SetWaterLevel( 0 ); - SetWaterType( CONTENTS_EMPTY ); - int cont = UTIL_PointContents (point); - - if (( cont & MASK_WATER ) == 0) - return; - - SetWaterType( cont ); - SetWaterLevel( 1 ); - - // point sized entities are always fully submerged - if ( IsPointSized() ) - { - SetWaterLevel( 3 ); - } - else - { - // Check the exact center of the box - point[2] = WorldSpaceCenter().z; - - int midcont = UTIL_PointContents (point); - if ( midcont & MASK_WATER ) - { - // Now check where the eyes are... - SetWaterLevel( 2 ); - point[2] = EyePosition().z; - - int eyecont = UTIL_PointContents (point); - if ( eyecont & MASK_WATER ) - { - SetWaterLevel( 3 ); - } - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Check if entity is in the water and applies any current to velocity -// and sets appropriate water flags -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseEntity::PhysicsCheckWater( void ) -{ - if (GetMoveParent()) - return GetWaterLevel() > 1; - - int cont = GetWaterType(); - - // If we're not in water + don't have a current, we're done - if ( ( cont & (MASK_WATER | MASK_CURRENT) ) != (MASK_WATER | MASK_CURRENT) ) - return GetWaterLevel() > 1; - - // Compute current direction - Vector v( 0, 0, 0 ); - if ( cont & CONTENTS_CURRENT_0 ) - { - v[0] += 1; - } - if ( cont & CONTENTS_CURRENT_90 ) - { - v[1] += 1; - } - if ( cont & CONTENTS_CURRENT_180 ) - { - v[0] -= 1; - } - if ( cont & CONTENTS_CURRENT_270 ) - { - v[1] -= 1; - } - if ( cont & CONTENTS_CURRENT_UP ) - { - v[2] += 1; - } - if ( cont & CONTENTS_CURRENT_DOWN ) - { - v[2] -= 1; - } - - // The deeper we are, the stronger the current. - Vector newBaseVelocity; - VectorMA (GetBaseVelocity(), 50.0*GetWaterLevel(), v, newBaseVelocity); - SetBaseVelocity( newBaseVelocity ); - - return GetWaterLevel() > 1; -} - - -//----------------------------------------------------------------------------- -// Purpose: Bounds velocity -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsCheckVelocity( void ) -{ - Vector origin = GetAbsOrigin(); - Vector vecAbsVelocity = GetAbsVelocity(); - - bool bReset = false; - for ( int i=0 ; i<3 ; i++ ) - { - if ( IS_NAN(vecAbsVelocity[i]) ) - { - Msg( "Got a NaN velocity on %s\n", GetClassname() ); - vecAbsVelocity[i] = 0; - bReset = true; - } - if ( IS_NAN(origin[i]) ) - { - Msg( "Got a NaN origin on %s\n", GetClassname() ); - origin[i] = 0; - bReset = true; - } - - if ( vecAbsVelocity[i] > sv_maxvelocity.GetFloat() ) - { -#ifdef _DEBUG - DevWarning( 2, "Got a velocity too high on %s\n", GetClassname() ); -#endif - vecAbsVelocity[i] = sv_maxvelocity.GetFloat(); - bReset = true; - } - else if ( vecAbsVelocity[i] < -sv_maxvelocity.GetFloat() ) - { -#ifdef _DEBUG - DevWarning( 2, "Got a velocity too low on %s\n", GetClassname() ); -#endif - vecAbsVelocity[i] = -sv_maxvelocity.GetFloat(); - bReset = true; - } - } - - if (bReset) - { - SetAbsOrigin( origin ); - SetAbsVelocity( vecAbsVelocity ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Applies gravity to falling objects -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsAddGravityMove( Vector &move ) -{ - Vector vecAbsVelocity = GetAbsVelocity(); - - move.x = (vecAbsVelocity.x + GetBaseVelocity().x ) * gpGlobals->frametime; - move.y = (vecAbsVelocity.y + GetBaseVelocity().y ) * gpGlobals->frametime; - - if ( GetFlags() & FL_ONGROUND ) - { - move.z = GetBaseVelocity().z * gpGlobals->frametime; - return; - } - - // linear acceleration due to gravity - float newZVelocity = vecAbsVelocity.z - GetActualGravity( this ) * gpGlobals->frametime; - - move.z = ((vecAbsVelocity.z + newZVelocity) / 2.0 + GetBaseVelocity().z ) * gpGlobals->frametime; - - Vector vecBaseVelocity = GetBaseVelocity(); - vecBaseVelocity.z = 0.0f; - SetBaseVelocity( vecBaseVelocity ); - - vecAbsVelocity.z = newZVelocity; - SetAbsVelocity( vecAbsVelocity ); - - // Bound velocity - PhysicsCheckVelocity(); -} - - -#define STOP_EPSILON 0.1 -//----------------------------------------------------------------------------- -// Purpose: Slide off of the impacting object. Returns the blocked flags (1 = floor, 2 = step / wall) -// Input : in - -// normal - -// out - -// overbounce - -// Output : int -//----------------------------------------------------------------------------- -int CBaseEntity::PhysicsClipVelocity( const Vector& in, const Vector& normal, Vector& out, float overbounce ) -{ - float backoff; - float change; - float angle; - int i, blocked; - - blocked = 0; - - angle = normal[ 2 ]; - - if ( angle > 0 ) - { - blocked |= 1; // floor - } - if ( !angle ) - { - blocked |= 2; // step - } - - backoff = DotProduct (in, normal) * overbounce; - - for ( i=0 ; i<3 ; i++ ) - { - change = normal[i]*backoff; - out[i] = in[i] - change; - if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON) - { - out[i] = 0; - } - } - - return blocked; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseEntity::ResolveFlyCollisionBounce( trace_t &trace, Vector &vecVelocity, float flMinTotalElasticity ) -{ -#ifdef HL1_DLL - flMinTotalElasticity = 0.3f; -#endif//HL1_DLL - - // Get the impact surface's elasticity. - float flSurfaceElasticity; - physprops->GetPhysicsProperties( trace.surface.surfaceProps, NULL, NULL, NULL, &flSurfaceElasticity ); - - float flTotalElasticity = GetElasticity() * flSurfaceElasticity; - if ( flMinTotalElasticity > 0.9f ) - { - flMinTotalElasticity = 0.9f; - } - flTotalElasticity = clamp( flTotalElasticity, flMinTotalElasticity, 0.9f ); - - // NOTE: A backoff of 2.0f is a reflection - Vector vecAbsVelocity; - PhysicsClipVelocity( GetAbsVelocity(), trace.plane.normal, vecAbsVelocity, 2.0f ); - vecAbsVelocity *= flTotalElasticity; - - // Get the total velocity (player + conveyors, etc.) - VectorAdd( vecAbsVelocity, GetBaseVelocity(), vecVelocity ); - float flSpeedSqr = DotProduct( vecVelocity, vecVelocity ); - - // Stop if on ground. - if ( trace.plane.normal.z > 0.7f ) // Floor - { - // Verify that we have an entity. - CBaseEntity *pEntity = trace.m_pEnt; - Assert( pEntity ); - - // Are we on the ground? - if ( vecVelocity.z < ( GetActualGravity( this ) * gpGlobals->frametime ) ) - { - vecAbsVelocity.z = 0.0f; - - // Recompute speedsqr based on the new absvel - VectorAdd( vecAbsVelocity, GetBaseVelocity(), vecVelocity ); - flSpeedSqr = DotProduct( vecVelocity, vecVelocity ); - } - - SetAbsVelocity( vecAbsVelocity ); - - if ( flSpeedSqr < ( 30 * 30 ) ) - { - if ( pEntity->IsStandable() ) - { - SetGroundEntity( pEntity ); - } - - // Reset velocities. - SetAbsVelocity( vec3_origin ); - SetLocalAngularVelocity( vec3_angle ); - } - else - { - Vector vecDelta = GetBaseVelocity() - vecAbsVelocity; - Vector vecBaseDir = GetBaseVelocity(); - VectorNormalize( vecBaseDir ); - float flScale = vecDelta.Dot( vecBaseDir ); - - VectorScale( vecAbsVelocity, ( 1.0f - trace.fraction ) * gpGlobals->frametime, vecVelocity ); - VectorMA( vecVelocity, ( 1.0f - trace.fraction ) * gpGlobals->frametime, GetBaseVelocity() * flScale, vecVelocity ); - PhysicsPushEntity( vecVelocity, &trace ); - } - } - else - { - // If we get *too* slow, we'll stick without ever coming to rest because - // we'll get pushed down by gravity faster than we can escape from the wall. - if ( flSpeedSqr < ( 30 * 30 ) ) - { - // Reset velocities. - SetAbsVelocity( vec3_origin ); - SetLocalAngularVelocity( vec3_angle ); - } - else - { - SetAbsVelocity( vecAbsVelocity ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseEntity::ResolveFlyCollisionSlide( trace_t &trace, Vector &vecVelocity ) -{ - // Get the impact surface's friction. - float flSurfaceFriction; - physprops->GetPhysicsProperties( trace.surface.surfaceProps, NULL, NULL, &flSurfaceFriction, NULL ); - - // A backoff of 1.0 is a slide. - float flBackOff = 1.0f; - Vector vecAbsVelocity; - PhysicsClipVelocity( GetAbsVelocity(), trace.plane.normal, vecAbsVelocity, flBackOff ); - - if ( trace.plane.normal.z <= 0.7 ) // Floor - { - SetAbsVelocity( vecAbsVelocity ); - return; - } - - // Stop if on ground. - // Get the total velocity (player + conveyors, etc.) - VectorAdd( vecAbsVelocity, GetBaseVelocity(), vecVelocity ); - float flSpeedSqr = DotProduct( vecVelocity, vecVelocity ); - - // Verify that we have an entity. - CBaseEntity *pEntity = trace.m_pEnt; - Assert( pEntity ); - - // Are we on the ground? - if ( vecVelocity.z < ( GetActualGravity( this ) * gpGlobals->frametime ) ) - { - vecAbsVelocity.z = 0.0f; - - // Recompute speedsqr based on the new absvel - VectorAdd( vecAbsVelocity, GetBaseVelocity(), vecVelocity ); - flSpeedSqr = DotProduct( vecVelocity, vecVelocity ); - } - SetAbsVelocity( vecAbsVelocity ); - - if ( flSpeedSqr < ( 30 * 30 ) ) - { - if ( pEntity->IsStandable() ) - { - SetGroundEntity( pEntity ); - } - - // Reset velocities. - SetAbsVelocity( vec3_origin ); - SetLocalAngularVelocity( vec3_angle ); - } - else - { - vecAbsVelocity += GetBaseVelocity(); - vecAbsVelocity *= ( 1.0f - trace.fraction ) * gpGlobals->frametime * flSurfaceFriction; - PhysicsPushEntity( vecAbsVelocity, &trace ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseEntity::ResolveFlyCollisionCustom( trace_t &trace, Vector &vecVelocity ) -{ - // Stop if on ground. - if ( trace.plane.normal.z > 0.7 ) // Floor - { - // Get the total velocity (player + conveyors, etc.) - VectorAdd( GetAbsVelocity(), GetBaseVelocity(), vecVelocity ); - - // Verify that we have an entity. - CBaseEntity *pEntity = trace.m_pEnt; - Assert( pEntity ); - - // Are we on the ground? - if ( vecVelocity.z < ( GetActualGravity( this ) * gpGlobals->frametime ) ) - { - Vector vecAbsVelocity = GetAbsVelocity(); - vecAbsVelocity.z = 0.0f; - SetAbsVelocity( vecAbsVelocity ); - } - - if ( pEntity->IsStandable() ) - { - SetGroundEntity( pEntity ); - } - } -} - -//----------------------------------------------------------------------------- -// Performs the collision resolution for fliers. -//----------------------------------------------------------------------------- -void CBaseEntity::PerformFlyCollisionResolution( trace_t &trace, Vector &move ) -{ - switch( GetMoveCollide() ) - { - case MOVECOLLIDE_FLY_CUSTOM: - { - ResolveFlyCollisionCustom( trace, move ); - break; - } - - case MOVECOLLIDE_FLY_BOUNCE: - { - ResolveFlyCollisionBounce( trace, move ); - break; - } - - case MOVECOLLIDE_FLY_SLIDE: - case MOVECOLLIDE_DEFAULT: - // NOTE: The default fly collision state is the same as a slide (for backward capatability). - { - ResolveFlyCollisionSlide( trace, move ); - break; - } - - default: - { - // Invalid MOVECOLLIDE_ - Assert( 0 ); - break; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Checks if an object has passed into or out of water and sets water info, alters velocity, plays splash sounds, etc. -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsCheckWaterTransition( void ) -{ - int oldcont = GetWaterType(); - UpdateWaterState(); - int cont = GetWaterType(); - - // We can exit right out if we're a child... don't bother with this... - if (GetMoveParent()) - return; - - if ( cont & MASK_WATER ) - { - if (oldcont == CONTENTS_EMPTY) - { -#ifndef CLIENT_DLL - Splash(); -#endif // !CLIENT_DLL - - // just crossed into water - EmitSound( "BaseEntity.EnterWater" ); - - if ( !IsEFlagSet( EFL_NO_WATER_VELOCITY_CHANGE ) ) - { - Vector vecAbsVelocity = GetAbsVelocity(); - vecAbsVelocity[2] *= 0.5; - SetAbsVelocity( vecAbsVelocity ); - } - } - } - else - { - if ( oldcont != CONTENTS_EMPTY ) - { - // just crossed out of water - EmitSound( "BaseEntity.ExitWater" ); - } - } -} - -//----------------------------------------------------------------------------- -// Computes new angles based on the angular velocity -//----------------------------------------------------------------------------- -void CBaseEntity::SimulateAngles( float flFrameTime ) -{ - // move angles - QAngle angles; - VectorMA ( GetLocalAngles(), flFrameTime, GetLocalAngularVelocity(), angles ); - SetLocalAngles( angles ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Toss, bounce, and fly movement. When onground, do nothing. -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsToss( void ) -{ - trace_t trace; - Vector move; - - PhysicsCheckWater(); - - // regular thinking - if ( !PhysicsRunThink() ) - return; - - // Moving upward, off the ground, or resting on a client/monster, remove FL_ONGROUND - if ( GetAbsVelocity()[2] > 0 || !GetGroundEntity() || !GetGroundEntity()->IsStandable() ) - { - SetGroundEntity( NULL ); - } - - // Check to see if entity is on the ground at rest - if ( GetFlags() & FL_ONGROUND ) - { - if ( VectorCompare( GetAbsVelocity(), vec3_origin ) ) - { - // Clear rotation if not moving (even if on a conveyor) - SetLocalAngularVelocity( vec3_angle ); - if ( VectorCompare( GetBaseVelocity(), vec3_origin ) ) - return; - } - } - - PhysicsCheckVelocity(); - - // add gravity - if ( GetMoveType() == MOVETYPE_FLYGRAVITY && !(GetFlags() & FL_FLY) ) - { - PhysicsAddGravityMove( move ); - } - else - { - // Base velocity is not properly accounted for since this entity will move again after the bounce without - // taking it into account - Vector vecAbsVelocity = GetAbsVelocity(); - vecAbsVelocity += GetBaseVelocity(); - VectorScale(vecAbsVelocity, gpGlobals->frametime, move); - PhysicsCheckVelocity( ); - } - - // move angles - SimulateAngles( gpGlobals->frametime ); - - // move origin - PhysicsPushEntity( move, &trace ); - -#if !defined( CLIENT_DLL ) - if ( VPhysicsGetObject() ) - { - VPhysicsGetObject()->UpdateShadow( GetAbsOrigin(), vec3_angle, true, gpGlobals->frametime ); - } -#endif - - PhysicsCheckVelocity(); - - if (trace.allsolid ) - { - // entity is trapped in another solid - // UNDONE: does this entity needs to be removed? - SetAbsVelocity(vec3_origin); - SetLocalAngularVelocity(vec3_angle); - return; - } - -#if !defined( CLIENT_DLL ) - if (IsEdictFree()) - return; -#endif - - if (trace.fraction != 1.0f) - { - PerformFlyCollisionResolution( trace, move ); - } - - // check for in water - PhysicsCheckWaterTransition(); -} - - -//----------------------------------------------------------------------------- -// Simulation in local space of rigid children -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsRigidChild( void ) -{ - VPROF("CBaseEntity::PhysicsRigidChild"); - // NOTE: rigidly attached children do simulation in local space - // Collision impulses will be handled either not at all, or by - // forwarding the information to the highest move parent - - Vector vecPrevOrigin = GetAbsOrigin(); - - // regular thinking - if ( !PhysicsRunThink() ) - return; - - VPROF_SCOPE_BEGIN("CBaseEntity::PhysicsRigidChild-2"); - -#if !defined( CLIENT_DLL ) - // Cause touch functions to be called - PhysicsTouchTriggers( &vecPrevOrigin ); - - // We have to do this regardless owing to hierarchy - if ( VPhysicsGetObject() ) - { - int solidType = GetSolid(); - bool bAxisAligned = ( solidType == SOLID_BBOX || solidType == SOLID_NONE ) ? true : false; - VPhysicsGetObject()->UpdateShadow( GetAbsOrigin(), bAxisAligned ? vec3_angle : GetAbsAngles(), true, gpGlobals->frametime ); - } -#endif - - VPROF_SCOPE_END(); -} - - -//----------------------------------------------------------------------------- -// Computes the base velocity -//----------------------------------------------------------------------------- -void CBaseEntity::UpdateBaseVelocity( void ) -{ -#if !defined( CLIENT_DLL ) - if ( GetFlags() & FL_ONGROUND ) - { - CBaseEntity *groundentity = GetGroundEntity(); - if ( groundentity ) - { - // On conveyor belt that's moving? - if ( groundentity->GetFlags() & FL_CONVEYOR ) - { - Vector vecNewBaseVelocity; - groundentity->GetGroundVelocityToApply( vecNewBaseVelocity ); - if ( GetFlags() & FL_BASEVELOCITY ) - { - vecNewBaseVelocity += GetBaseVelocity(); - } - AddFlag( FL_BASEVELOCITY ); - SetBaseVelocity( vecNewBaseVelocity ); - } - } - } -#endif -} - - -//----------------------------------------------------------------------------- -// Purpose: Runs a frame of physics for a specific edict (and all it's children) -// Input : *ent - the thinking edict -//----------------------------------------------------------------------------- -void CBaseEntity::PhysicsSimulate( void ) -{ - VPROF( "CBaseEntity::PhysicsSimulate" ); - // NOTE: Players override PhysicsSimulate and drive through their CUserCmds at that point instead of - // processng through this function call!!! They shouldn't chain to here ever. - // Make sure not to simulate this guy twice per frame - if (m_nSimulationTick == gpGlobals->tickcount) - return; - - m_nSimulationTick = gpGlobals->tickcount; - - Assert( !IsPlayer() ); - - // If we've got a moveparent, we must simulate that first. - CBaseEntity *pMoveParent = GetMoveParent(); - - if ( (GetMoveType() == MOVETYPE_NONE && !pMoveParent) || (GetMoveType() == MOVETYPE_VPHYSICS ) ) - { - PhysicsNone(); - return; - } - - // If ground entity goes away, make sure FL_ONGROUND is valid - if ( !GetGroundEntity() ) - { - RemoveFlag( FL_ONGROUND ); - } - - if (pMoveParent) - { - VPROF( "CBaseEntity::PhysicsSimulate-MoveParent" ); - pMoveParent->PhysicsSimulate(); - } - else - { - VPROF( "CBaseEntity::PhysicsSimulate-BaseVelocity" ); - - UpdateBaseVelocity(); - - if ( ((GetFlags() & FL_BASEVELOCITY) == 0) && (GetBaseVelocity() != vec3_origin) ) - { - // Apply momentum (add in half of the previous frame of velocity first) - // BUGBUG: This will break with PhysicsStep() because of the timestep difference - Vector vecAbsVelocity; - VectorMA( GetAbsVelocity(), 1.0 + (gpGlobals->frametime*0.5), GetBaseVelocity(), vecAbsVelocity ); - SetAbsVelocity( vecAbsVelocity ); - SetBaseVelocity( vec3_origin ); - } - RemoveFlag( FL_BASEVELOCITY ); - } - - switch( GetMoveType() ) - { - case MOVETYPE_PUSH: - { - VPROF( "CBaseEntity::PhysicsSimulate-MOVETYPE_PUSH" ); - PhysicsPusher(); - } - break; - - - case MOVETYPE_VPHYSICS: - { - } - break; - - case MOVETYPE_NONE: - { - VPROF( "CBaseEntity::PhysicsSimulate-MOVETYPE_NONE" ); - Assert(pMoveParent); - PhysicsRigidChild(); - } - break; - - case MOVETYPE_NOCLIP: - { - VPROF( "CBaseEntity::PhysicsSimulate-MOVETYPE_NOCLIP" ); - PhysicsNoclip(); - } - break; - - case MOVETYPE_STEP: - { - VPROF( "CBaseEntity::PhysicsSimulate-MOVETYPE_STEP" ); - PhysicsStep(); - } - break; - - case MOVETYPE_FLY: - case MOVETYPE_FLYGRAVITY: - { - VPROF( "CBaseEntity::PhysicsSimulate-MOVETYPE_FLY" ); - PhysicsToss(); - } - break; - - case MOVETYPE_CUSTOM: - { - VPROF( "CBaseEntity::PhysicsSimulate-MOVETYPE_CUSTOM" ); - PhysicsCustom(); - } - break; - - default: - Warning( "PhysicsSimulate: %s bad movetype %d", GetClassname(), GetMoveType() ); - Assert(0); - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Runs thinking code if time. There is some play in the exact time the think -// function will be called, because it is called before any movement is done -// in a frame. Not used for pushmove objects, because they must be exact. -// Returns false if the entity removed itself. -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseEntity::PhysicsRunThink( thinkmethods_t thinkMethod ) -{ - if ( IsEFlagSet( EFL_NO_THINK_FUNCTION ) ) - return true; - - bool bAlive = true; - - // Don't fire the base if we're avoiding it - if ( thinkMethod != THINK_FIRE_ALL_BUT_BASE ) - { - bAlive = PhysicsRunSpecificThink( -1, &CBaseEntity::Think ); - if ( !bAlive ) - return false; - } - - // Are we just firing the base think? - if ( thinkMethod == THINK_FIRE_BASE_ONLY ) - return bAlive; - - // Fire the rest of 'em - for ( int i = 0; i < m_aThinkFunctions.Count(); i++ ) - { -#ifdef _DEBUG - // Set the context - m_iCurrentThinkContext = i; -#endif - - bAlive = PhysicsRunSpecificThink( i, m_aThinkFunctions[i].m_pfnThink ); - -#ifdef _DEBUG - // Clear our context - m_iCurrentThinkContext = NO_THINK_CONTEXT; -#endif - - if ( !bAlive ) - return false; - } - - return bAlive; -} - -//----------------------------------------------------------------------------- -// Purpose: For testing if all thinks are occuring at the same time -//----------------------------------------------------------------------------- -struct ThinkSync -{ - float thinktime; - int thinktick; - CUtlVector< EHANDLE > entities; - - ThinkSync() - { - thinktime = 0; - } - - ThinkSync( const ThinkSync& src ) - { - thinktime = src.thinktime; - thinktick = src.thinktick; - int c = src.entities.Count(); - for ( int i = 0; i < c; i++ ) - { - entities.AddToTail( src.entities[ i ] ); - } - } -}; - -#if !defined( CLIENT_DLL ) -static ConVar sv_thinktimecheck( "sv_thinktimecheck", "0", 0, "Check for thinktimes all on same timestamp." ); -#endif - -//----------------------------------------------------------------------------- -// Purpose: For testing if all thinks are occuring at the same time -//----------------------------------------------------------------------------- -class CThinkSyncTester -{ -public: - CThinkSyncTester() : - m_Thinkers( 0, 0, ThinkLessFunc ) - { - m_nLastFrameCount = -1; - m_bShouldCheck = false; - } - - void EntityThinking( int framecount, CBaseEntity *ent, float thinktime, int thinktick ) - { -#if !defined( CLIENT_DLL ) - if ( m_nLastFrameCount != framecount ) - { - if ( m_bShouldCheck ) - { - // Report - Report(); - m_Thinkers.RemoveAll(); - m_nLastFrameCount = framecount; - } - - m_bShouldCheck = sv_thinktimecheck.GetBool(); - } - - if ( !m_bShouldCheck ) - return; - - ThinkSync *p = FindOrAddItem( ent, thinktime ); - if ( !p ) - { - Assert( 0 ); - } - - p->thinktime = thinktime; - p->thinktick = thinktick; - EHANDLE h; - h = ent; - p->entities.AddToTail( h ); -#endif - } - -private: - - static bool ThinkLessFunc( const ThinkSync& item1, const ThinkSync& item2 ) - { - return item1.thinktime < item2.thinktime; - } - - ThinkSync *FindOrAddItem( CBaseEntity *ent, float thinktime ) - { - ThinkSync item; - item.thinktime = thinktime; - - int idx = m_Thinkers.Find( item ); - if ( idx == m_Thinkers.InvalidIndex() ) - { - idx = m_Thinkers.Insert( item ); - } - - return &m_Thinkers[ idx ]; - } - - void Report() - { - if ( m_Thinkers.Count() == 0 ) - return; - - Msg( "-----------------\nThink report frame %i\n", gpGlobals->tickcount ); - - for ( int i = m_Thinkers.FirstInorder(); - i != m_Thinkers.InvalidIndex(); - i = m_Thinkers.NextInorder( i ) ) - { - ThinkSync *p = &m_Thinkers[ i ]; - Assert( p ); - if ( !p ) - continue; - - int ecount = p->entities.Count(); - if ( !ecount ) - { - continue; - } - - Msg( "thinktime %f, %i entities\n", p->thinktime, ecount ); - for ( int j =0; j < ecount; j++ ) - { - EHANDLE h = p->entities[ j ]; - int lastthinktick = 0; - int nextthinktick = 0; - CBaseEntity *e = h.Get(); - if ( e ) - { - lastthinktick = e->m_nLastThinkTick; - nextthinktick = e->m_nNextThinkTick; - } - - Msg( " %p : %30s (last %5i/next %5i)\n", h.Get(), h.Get() ? h->GetClassname() : "NULL", - lastthinktick, nextthinktick ); - } - } - } - - CUtlRBTree< ThinkSync > m_Thinkers; - int m_nLastFrameCount; - bool m_bShouldCheck; -}; - -static CThinkSyncTester g_ThinkChecker; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseEntity::PhysicsRunSpecificThink( int nContextIndex, BASEPTR thinkFunc ) -{ - int thinktick = GetNextThinkTick( nContextIndex ); - - if ( thinktick <= 0 || thinktick > gpGlobals->tickcount ) - return true; - - float thinktime = thinktick * TICK_INTERVAL; - - // Don't let things stay in the past. - // it is possible to start that way - // by a trigger with a local time. - if ( thinktime < gpGlobals->curtime ) - { - thinktime = gpGlobals->curtime; - } - - // Only do this on the game server -#if !defined( CLIENT_DLL ) - g_ThinkChecker.EntityThinking( gpGlobals->tickcount, this, thinktime, m_nNextThinkTick ); -#endif - - SetNextThink( nContextIndex, TICK_NEVER_THINK ); - - PhysicsDispatchThink( thinkFunc ); - - SetLastThink( nContextIndex, gpGlobals->curtime ); - - // Return whether entity is still valid - return ( !IsMarkedForDeletion() ); -} - -void CBaseEntity::SetGroundEntity( CBaseEntity *ground ) -{ - if ( m_hGroundEntity.Get() == ground ) - return; - -#ifdef GAME_DLL - // this can happen in-between updates to the held object controller (physcannon, +USE) - // so trap it here and release held objects when they become player ground - if ( ground && IsPlayer() && ground->GetMoveType()== MOVETYPE_VPHYSICS ) - { - CBasePlayer *pPlayer = ToBasePlayer(this); - IPhysicsObject *pPhysGround = ground->VPhysicsGetObject(); - if ( pPhysGround && pPlayer ) - { - if ( pPhysGround->GetGameFlags() & FVPHYSICS_PLAYER_HELD ) - { - pPlayer->ForceDropOfCarriedPhysObjects( ground ); - } - } - } -#endif - - CBaseEntity *oldGround = m_hGroundEntity; - m_hGroundEntity = ground; - - // Just starting to touch - if ( !oldGround && ground ) - { - ground->AddEntityToGroundList( this ); - } - // Just stopping touching - else if ( oldGround && !ground ) - { - PhysicsNotifyOtherOfGroundRemoval( this, oldGround ); - } - // Changing out to new ground entity - else - { - PhysicsNotifyOtherOfGroundRemoval( this, oldGround ); - ground->AddEntityToGroundList( this ); - } - - // HACK/PARANOID: This is redundant with the code above, but in case we get out of sync groundlist entries ever, - // this will force the appropriate flags - if ( ground ) - { - AddFlag( FL_ONGROUND ); - } - else - { - RemoveFlag( FL_ONGROUND ); - } -} - -CBaseEntity *CBaseEntity::GetGroundEntity( void ) -{ - return m_hGroundEntity; -} - -void CBaseEntity::StartGroundContact( CBaseEntity *ground ) -{ - AddFlag( FL_ONGROUND ); -// Msg( "+++ %s starting contact with ground %s\n", GetClassname(), ground->GetClassname() ); -} - -void CBaseEntity::EndGroundContact( CBaseEntity *ground ) -{ - RemoveFlag( FL_ONGROUND ); -// Msg( "--- %s ending contact with ground %s\n", GetClassname(), ground->GetClassname() ); -} - - -void CBaseEntity::SetGroundChangeTime( float flTime ) -{ - m_flGroundChangeTime = flTime; -} - -float CBaseEntity::GetGroundChangeTime( void ) -{ - return m_flGroundChangeTime; -} - - - -// Remove this as ground entity for all object resting on this object -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseEntity::WakeRestingObjects() -{ - // Unset this as ground entity for everything resting on this object - // This calls endgroundcontact for everything on the list - PhysicsRemoveGroundList( this ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *ent - -//----------------------------------------------------------------------------- -bool CBaseEntity::HasNPCsOnIt( void ) -{ - groundlink_t *link; - groundlink_t *root = ( groundlink_t * )GetDataObject( GROUNDLINK ); - if ( root ) - { - for ( link = root->nextLink; link != root; link = link->nextLink ) - { - if ( link->entity && link->entity->MyNPCPointer() ) - return true; - } - } - - return false; -} diff --git a/game/shared/physics_saverestore.cpp b/game/shared/physics_saverestore.cpp deleted file mode 100644 index 160560a00..000000000 --- a/game/shared/physics_saverestore.cpp +++ /dev/null @@ -1,828 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" - -#include "utlpriorityqueue.h" -#include "utlmap.h" -#include "isaverestore.h" -#include "physics.h" -#include "physics_saverestore.h" -#include "saverestoretypes.h" -#include "gamestringpool.h" -#include "datacache/imdlcache.h" - -#if !defined( CLIENT_DLL ) -#include "entitylist.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- - -static short PHYS_SAVE_RESTORE_VERSION = 5; - -struct PhysBlockHeader_t -{ - int nSaved; - IPhysicsObject *pWorldObject; - - inline void Clear() - { - nSaved = 0; - pWorldObject = 0; - } - - DECLARE_SIMPLE_DATADESC(); -}; -BEGIN_SIMPLE_DATADESC( PhysBlockHeader_t ) - DEFINE_FIELD( nSaved, FIELD_INTEGER ), - // NOTE: We want to save the actual address here for remapping, so use an integer - DEFINE_FIELD( pWorldObject, FIELD_INTEGER ), -END_DATADESC() - -#if defined(_STATIC_LINKED) && defined(CLIENT_DLL) -const char *g_ppszPhysTypeNames[PIID_NUM_TYPES] = -{ - "Unknown", - "IPhysicsObject", - "IPhysicsFluidController", - "IPhysicsSpring", - "IPhysicsConstraintGroup", - "IPhysicsConstraint", - "IPhysicsShadowController", - "IPhysicsPlayerController", - "IPhysicsMotionController", - "IPhysicsVehicleController", -}; -#endif - -//----------------------------------------------------------------------------- - -struct BBox_t -{ - Vector mins, maxs; -}; - -struct Sphere_t -{ - float radius; -}; - - -struct PhysObjectHeader_t -{ - PhysObjectHeader_t() - { - memset( this, 0, sizeof(*this) ); - } - - PhysInterfaceId_t type; - EHANDLE hEntity; - string_t fieldName; - int nObjects; - string_t modelName; - BBox_t bbox; - Sphere_t sphere; - int iCollide; - - DECLARE_SIMPLE_DATADESC(); -}; - -BEGIN_SIMPLE_DATADESC( PhysObjectHeader_t ) - DEFINE_FIELD( type, FIELD_INTEGER ), - DEFINE_FIELD( hEntity, FIELD_EHANDLE ), - DEFINE_FIELD( fieldName, FIELD_STRING ), - DEFINE_FIELD( nObjects, FIELD_INTEGER ), - DEFINE_FIELD( modelName, FIELD_STRING ), - - // Silence, Classcheck! - // DEFINE_FIELD( bbox, BBox_t ), - // DEFINE_FIELD( sphere, Sphere_t ), - - DEFINE_FIELD( bbox.mins, FIELD_VECTOR ), - DEFINE_FIELD( bbox.maxs, FIELD_VECTOR ), - DEFINE_FIELD( sphere.radius, FIELD_FLOAT ), - DEFINE_FIELD( iCollide, FIELD_INTEGER ), -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: The central manager of physics save/load -// - -class CPhysSaveRestoreBlockHandler : public CDefSaveRestoreBlockHandler, - public IPhysSaveRestoreManager -#if !defined( CLIENT_DLL ) - , public IEntityListener -#endif -{ - struct QueuedItem_t; -public: - CPhysSaveRestoreBlockHandler() - { - m_QueuedSaves.SetLessFunc( SaveQueueFunc ); - SetDefLessFunc( m_QueuedRestores ); - SetDefLessFunc( m_PhysObjectModels ); - SetDefLessFunc( m_PhysObjectCustomModels ); - SetDefLessFunc( m_PhysCollideBBoxModels ); - } - - const char *GetBlockName() - { - return "Physics"; - } - - //--------------------------------- - - virtual void PreSave( CSaveRestoreData * ) - { - m_blockHeader.Clear(); - } - - //--------------------------------- - - virtual void Save( ISave *pSave ) - { - m_blockHeader.pWorldObject = g_PhysWorldObject; - m_blockHeader.nSaved = m_QueuedSaves.Count(); - - while ( m_QueuedSaves.Count() ) - { - const QueuedItem_t &item = m_QueuedSaves.ElementAtHead(); - - CBaseEntity *pOwner = item.header.hEntity.Get(); - - if ( pOwner ) - { - pSave->WriteAll( &item.header ); - pSave->StartBlock(); // Need block here in case entity is NULL on load - if ( item.header.nObjects ) - { - for ( int i = 0; i < item.header.nObjects; i++ ) - { - // Starting a block here allows the implementation of any individual physics - // class save/load to change non-trivially while retaining the overall - // integrity of the savefile. - pSave->StartBlock(); - SavePhysicsObject( pSave, pOwner, item.ppPhysObj[i], item.header.type ); - pSave->EndBlock(); - } - } - // else, it will simply be recreated on restore - pSave->EndBlock(); - } - m_QueuedSaves.RemoveAtHead(); - } - } - - //--------------------------------- - - virtual void WriteSaveHeaders( ISave *pSave ) - { - pSave->WriteShort( &PHYS_SAVE_RESTORE_VERSION ); - pSave->WriteAll( &m_blockHeader ); - } - - //--------------------------------- - - virtual void PostSave() - { - m_QueuedSaves.Purge(); - } - - //--------------------------------- - - virtual void PreRestore() - { -#if !defined( CLIENT_DLL ) - gEntList.AddListenerEntity( this ); -#endif - - // UNDONE: This never runs!!!! - if ( physenv ) - { - physprerestoreparams_t params; - params.recreatedObjectCount = 0; - physenv->PreRestore( params ); - } - } - - //--------------------------------- - - virtual void ReadRestoreHeaders( IRestore *pRestore ) - { - // No reason why any future version shouldn't try to retain backward compatability. The default here is to not do so. - short version = pRestore->ReadShort(); - m_fDoLoad = ( version == PHYS_SAVE_RESTORE_VERSION ); - - pRestore->ReadAll( &m_blockHeader ); - } - - //--------------------------------- - - virtual void Restore( IRestore *pRestore, bool ) - { - if ( m_fDoLoad ) - { - if ( physenv ) - { - physprerestoreparams_t params; - params.recreatedObjectCount = 1; - params.recreatedObjectList[0].pNewObject = g_PhysWorldObject; - params.recreatedObjectList[0].pOldObject = m_blockHeader.pWorldObject; - physenv->PreRestore( params ); - } - - PhysObjectHeader_t header; - - while ( m_blockHeader.nSaved-- ) - { - pRestore->ReadAll( &header ); - pRestore->StartBlock(); - - if ( header.hEntity != NULL ) - { - RestoreBlock( pRestore, header ); - } - - pRestore->EndBlock(); - } - } - } - - //--------------------------------- - - void RestoreBlock( IRestore *pRestore, const PhysObjectHeader_t &header ) - { - CBaseEntity * pOwner = header.hEntity.Get(); - unsigned short iQueued = m_QueuedRestores.Find( pOwner ); - - if ( iQueued != m_QueuedRestores.InvalidIndex() ) - { - MDLCACHE_CRITICAL_SECTION(); - if ( pOwner->ShouldSavePhysics() && header.nObjects > 0 ) - { - QueuedItem_t *pItem = m_QueuedRestores[iQueued]->FindItem( header.fieldName ); - - if ( pItem ) - { - int nObjects = MIN( header.nObjects, pItem->header.nObjects ); - if ( pItem->header.type == PIID_IPHYSICSOBJECT && nObjects == 1 ) - { - RestorePhysicsObjectAndModel( pRestore, header, pItem, nObjects ); - } - else - { - void **ppPhysObj = pItem->ppPhysObj; - - for ( int i = 0; i < nObjects; i++ ) - { - pRestore->StartBlock(); - RestorePhysicsObject( pRestore, header, ppPhysObj + i ); - pRestore->EndBlock(); - if ( header.type == PIID_IPHYSICSMOTIONCONTROLLER ) - { - void *pObj = ppPhysObj[i]; - IPhysicsMotionController *pController = (IPhysicsMotionController *)pObj; - if ( pController ) - { - // If the entity is the motion callback handler, then automatically set it - // NOTE: This is usually the case - IMotionEvent *pEvent = dynamic_cast(pOwner); - if ( pEvent ) - { - pController->SetEventHandler( pEvent ); - } - } - } - } - } - } - } - else - pOwner->CreateVPhysics(); - } - } - - - //--------------------------------- - - void RestorePhysicsObjectAndModel( IRestore *pRestore, const PhysObjectHeader_t &header, CPhysSaveRestoreBlockHandler::QueuedItem_t *pItem, int nObjects ) - { - if ( nObjects == 1 ) - { - pRestore->StartBlock(); - - CPhysCollide *pPhysCollide = NULL; - int modelIndex = -1; - bool fCustomCollide = false; - - if ( header.modelName != NULL_STRING ) - { - CBaseEntity *pGlobalEntity = header.hEntity; -#if !defined( CLIENT_DLL ) - if ( NULL_STRING != pGlobalEntity->m_iGlobalname ) - { - modelIndex = pGlobalEntity->GetModelIndex(); - } - else -#endif - { - modelIndex = modelinfo->GetModelIndex( STRING( header.modelName ) ); - pGlobalEntity = NULL; - } - - if ( modelIndex != -1 ) - { - vcollide_t *pCollide = modelinfo->GetVCollide( modelIndex ); - if ( pCollide ) - { - if ( pCollide->solidCount > 0 && pCollide->solids && header.iCollide < pCollide->solidCount ) - pPhysCollide = pCollide->solids[header.iCollide]; - } - } - } - else if ( header.bbox.mins != vec3_origin || header.bbox.maxs != vec3_origin ) - { - pPhysCollide = PhysCreateBbox( header.bbox.mins, header.bbox.maxs ); - fCustomCollide = true; - } - else if ( header.sphere.radius != 0 ) - { - // HACKHACK: Handle spheres here!!! - if ( !(*pItem->ppPhysObj) ) - { - RestorePhysicsObject( pRestore, header, pItem->ppPhysObj, NULL ); - } - return; - } - - if ( pPhysCollide ) - { - if ( !(*pItem->ppPhysObj) ) - { - RestorePhysicsObject( pRestore, header, pItem->ppPhysObj, pPhysCollide ); - if ( (*pItem->ppPhysObj) ) - { - IPhysicsObject *pObject = (IPhysicsObject *)(*pItem->ppPhysObj); - if ( !fCustomCollide ) - { - AssociateModel( pObject, modelIndex ); - } - else - { - AssociateModel( pObject, pPhysCollide ); - } - } - else - DevMsg( "Failed to restore physics object\n" ); - } - else - DevMsg( "Physics object pointer unexpectedly non-null before restore. Should be creating physics object in CreatePhysics()?\n" ); - } - else - DevMsg( "Failed to reestablish collision model for object\n" ); - - pRestore->EndBlock(); - } - else - DevMsg( "Don't know how to reconsitite models for physobj array \n" ); - } - - //--------------------------------- - - virtual void PostRestore() - { - if ( physenv ) - physenv->PostRestore(); - - unsigned short i = m_QueuedRestores.FirstInorder(); - while ( i != m_QueuedRestores.InvalidIndex() ) - { - delete m_QueuedRestores[i]; - i = m_QueuedRestores.NextInorder( i ); - } - - m_QueuedRestores.RemoveAll(); -#if !defined( CLIENT_DLL ) - gEntList.RemoveListenerEntity( this ); -#endif - } - - //--------------------------------- - - void QueueSave( CBaseEntity *pOwner, typedescription_t *pTypeDesc, void **ppPhysObj, PhysInterfaceId_t type ) - { - if ( !pOwner ) - return; - - bool fOnlyNotingExistence = !pOwner->ShouldSavePhysics(); - - QueuedItem_t item; - - item.ppPhysObj = ppPhysObj; - item.header.hEntity = pOwner; - item.header.type = type; - item.header.nObjects = ( !fOnlyNotingExistence ) ? pTypeDesc->fieldSize : 0; - item.header.fieldName = AllocPooledString( pTypeDesc->fieldName ); - // A pooled string is used here because there is no way - // right now to save a non-string_t string and have it - // compressed in the save symbol tables. Furthermore, - // the field name would normally be in the string - // pool anyway. (toml 12-10-02) - item.header.modelName = NULL_STRING; - memset( &item.header.bbox, 0, sizeof( item.header.bbox ) ); - item.header.sphere.radius = 0; - - if ( !fOnlyNotingExistence && type == PIID_IPHYSICSOBJECT ) - { - // Don't doing the box thing for things like wheels on cars - IPhysicsObject *pPhysObj = (IPhysicsObject *)(*ppPhysObj); - - if ( pPhysObj ) - { - item.header.modelName = GetModelName( pPhysObj ); - item.header.iCollide = physcollision->CollideIndex( pPhysObj->GetCollide() ); - if ( item.header.modelName == NULL_STRING ) - { - BBox_t *pBBox = GetBBox( pPhysObj ); - if ( pBBox != NULL ) - { - item.header.bbox = *pBBox; - } - else - { - if ( pPhysObj && pPhysObj->GetSphereRadius() != 0 ) - { - item.header.sphere.radius = pPhysObj->GetSphereRadius(); - } - else - { - DevMsg( "Don't know how to save model for physics object (class \"%s\")\n", pOwner->GetClassname() ); - } - } - } - } - } - - m_QueuedSaves.Insert( item ); - } - - //--------------------------------- - - void QueueRestore( CBaseEntity *pOwner, typedescription_t *pTypeDesc, void **ppPhysObj, PhysInterfaceId_t type ) - { - CEntityRestoreSet *pEntitySet = NULL; - unsigned short iEntitySet = m_QueuedRestores.Find( pOwner ); - - if ( iEntitySet != m_QueuedRestores.InvalidIndex() ) - { - pEntitySet = m_QueuedRestores[iEntitySet]; - } - else - { - pEntitySet = new CEntityRestoreSet; - m_QueuedRestores.Insert( pOwner, pEntitySet ); - } - - pEntitySet->Add( pOwner, pTypeDesc, ppPhysObj, type ); - - memset( ppPhysObj, 0, pTypeDesc->fieldSize * sizeof( void * ) ); - } - - //--------------------------------- - - void SavePhysicsObject( ISave *pSave, CBaseEntity *pOwner, void *pObject, PhysInterfaceId_t type ) - { - if ( physenv ) - { - if ( !pObject ) - return; - physsaveparams_t params = { pSave, pObject, type }; - physenv->Save( params ); - } - } - - //--------------------------------- - - void RestorePhysicsObject( IRestore *pRestore, const PhysObjectHeader_t &header, void **ppObject, const CPhysCollide *pCollide = NULL ) - { - if ( physenv ) - { - physrestoreparams_t params = { pRestore, ppObject, header.type, header.hEntity.Get(), STRING(header.modelName), pCollide, physenv, physgametrace }; - physenv->Restore( params ); - } - } -#if !defined( CLIENT_DLL ) - //----------------------------------------------------- - // IEntityListener methods - // This object is only a listener during restore - virtual void OnEntityCreated( CBaseEntity *pEntity ) - { - } - - //--------------------------------- - - virtual void OnEntityDeleted( CBaseEntity *pEntity ) - { - unsigned short iEntitySet = m_QueuedRestores.Find( pEntity ); - - if ( iEntitySet != m_QueuedRestores.InvalidIndex() ) - { - delete m_QueuedRestores[iEntitySet]; - m_QueuedRestores.RemoveAt( iEntitySet ); - } - } -#endif - - //----------------------------------------------------- - // IPhysSaveRestoreManager methods - - virtual void NoteBBox( const Vector &mins, const Vector &maxs, CPhysCollide *pCollide ) - { - if ( pCollide && m_PhysCollideBBoxModels.Find( pCollide ) == m_PhysCollideBBoxModels.InvalidIndex() ) - { - BBox_t box; - box.mins = mins; - box.maxs = maxs; - m_PhysCollideBBoxModels.Insert( pCollide, box ); - } - } - - //--------------------------------- - - virtual void AssociateModel( IPhysicsObject *pObject, int modelIndex ) - { - Assert( m_PhysObjectModels.Find( pObject ) == m_PhysObjectModels.InvalidIndex() ); - m_PhysObjectModels.Insert( pObject, modelIndex ); - } - - //--------------------------------- - - virtual void AssociateModel( IPhysicsObject *pObject, const CPhysCollide *pModel ) - { - Assert( m_PhysObjectCustomModels.Find( pObject ) == m_PhysObjectCustomModels.InvalidIndex() ); - m_PhysObjectCustomModels.Insert( pObject, pModel ); - } - - //--------------------------------- - - virtual void ForgetModel( IPhysicsObject *pObject ) - { - if ( !m_PhysObjectModels.Remove( pObject ) ) - m_PhysObjectCustomModels.Remove( pObject ); - } - - //--------------------------------- - - virtual void ForgetAllModels() - { - m_PhysObjectModels.RemoveAll(); - m_PhysObjectCustomModels.RemoveAll(); - m_PhysCollideBBoxModels.RemoveAll(); - } - - //--------------------------------- - - string_t GetModelName( IPhysicsObject *pObject ) - { - int i = m_PhysObjectModels.Find( pObject ); - if ( i == m_PhysObjectModels.InvalidIndex() ) - return NULL_STRING; - return AllocPooledString( modelinfo->GetModelName( modelinfo->GetModel( m_PhysObjectModels[i] ) ) ); - } - - //--------------------------------- - - BBox_t * GetBBox( IPhysicsObject *pObject ) - { - int i = m_PhysObjectCustomModels.Find( pObject ); - if ( i == m_PhysObjectCustomModels.InvalidIndex() ) - return NULL; - i = m_PhysCollideBBoxModels.Find( m_PhysObjectCustomModels[i] ); - if ( i == m_PhysCollideBBoxModels.InvalidIndex() ) - return NULL; - return &(m_PhysCollideBBoxModels[i]); - } - - //--------------------------------- - -private: - struct QueuedItem_t - { - PhysObjectHeader_t header; - void ** ppPhysObj; - }; - - class CEntityRestoreSet : public CUtlVector - { - public: - int Add( CBaseEntity *pOwner, typedescription_t *pTypeDesc, void **ppPhysObj, PhysInterfaceId_t type ) - { - int i = AddToTail(); - - Assert( ppPhysObj ); - Assert( *ppPhysObj == NULL ); // expected field to have been cleared - Assert( pOwner ); - - QueuedItem_t &item = Element( i ); - - item.ppPhysObj = ppPhysObj; - item.header.hEntity = pOwner; - item.header.type = type; - item.header.nObjects = pTypeDesc->fieldSize; - item.header.fieldName = AllocPooledString( pTypeDesc->fieldName ); // See comment in CPhysSaveRestoreBlockHandler::QueueSave() - - return i; - } - - QueuedItem_t *FindItem( string_t itemFieldName ) - { - // generally, the set is very small, usually one, so linear search is not too gruesome; - for ( int i = 0; i < Count(); i++ ) - { - string_t testName = Element(i).header.fieldName; - Assert( ( testName == itemFieldName && strcmp( STRING( testName ), STRING( itemFieldName ) ) == 0 ) || - ( testName != itemFieldName && strcmp( STRING( testName ), STRING( itemFieldName ) ) != 0 ) ); - - if ( testName == itemFieldName ) - return &(Element(i)); - } - return NULL; - } - }; - - //--------------------------------- - - static bool SaveQueueFunc( const QueuedItem_t &left, const QueuedItem_t &right ) - { - if ( left.header.type == right.header.type ) - return ( left.header.hEntity->entindex() > right.header.hEntity->entindex() ); - - return ( left.header.type > right.header.type ); - } - - //--------------------------------- - - CUtlPriorityQueue m_QueuedSaves; - CUtlMap m_QueuedRestores; - bool m_fDoLoad; - - //--------------------------------- - - CUtlMap m_PhysObjectModels; - CUtlMap m_PhysObjectCustomModels; - CUtlMap m_PhysCollideBBoxModels; - - //--------------------------------- - - PhysBlockHeader_t m_blockHeader; -}; - -//----------------------------------------------------------------------------- - -CPhysSaveRestoreBlockHandler g_PhysSaveRestoreBlockHandler; - -IPhysSaveRestoreManager *g_pPhysSaveRestoreManager = &g_PhysSaveRestoreBlockHandler; - -//------------------------------------- - -ISaveRestoreBlockHandler *GetPhysSaveRestoreBlockHandler() -{ - return &g_PhysSaveRestoreBlockHandler; -} - -static bool IsValidEntityPointer( void *ptr ) -{ -#if !defined( CLIENT_DLL ) - return gEntList.IsEntityPtr( ptr ); -#else - // Walk entities looking for pointer - int c = ClientEntityList().GetHighestEntityIndex(); - for ( int i = 0; i <= c; i++ ) - { - CBaseEntity *e = ClientEntityList().GetBaseEntity( i ); - if ( !e ) - continue; - - if ( e == ptr ) - return true; - } - return false; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Classifies field and queues it up for physics save/restore. -// - -class CPhysObjSaveRestoreOps : public CDefSaveRestoreOps -{ -public: - virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave ) - { - CBaseEntity *pOwnerEntity = pSave->GetGameSaveRestoreInfo()->GetCurrentEntityContext(); - - bool bFoundEntity = true; - - if ( IsValidEntityPointer(pOwnerEntity) == false ) - { - bFoundEntity = false; - -#if defined( CLIENT_DLL ) - pOwnerEntity = ClientEntityList().GetBaseEntityFromHandle( pOwnerEntity->GetRefEHandle() ); - - if ( pOwnerEntity ) - { - bFoundEntity = true; - } -#endif - } - - AssertMsg( pOwnerEntity && bFoundEntity == true, "Physics save/load is only suitable for entities" ); - - if ( m_type == PIID_UNKNOWN ) - { - AssertMsg( 0, "Unknown physics save/load type"); - return; - } - g_PhysSaveRestoreBlockHandler.QueueSave( pOwnerEntity, fieldInfo.pTypeDesc, (void **)fieldInfo.pField, m_type ); - } - - virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore ) - { - CBaseEntity *pOwnerEntity = pRestore->GetGameSaveRestoreInfo()->GetCurrentEntityContext(); - - bool bFoundEntity = true; - - if ( IsValidEntityPointer(pOwnerEntity) == false ) - { - bFoundEntity = false; - -#if defined( CLIENT_DLL ) - pOwnerEntity = ClientEntityList().GetBaseEntityFromHandle( pOwnerEntity->GetRefEHandle() ); - - if ( pOwnerEntity ) - { - bFoundEntity = true; - } -#endif - } - - AssertMsg( pOwnerEntity && bFoundEntity == true, "Physics save/load is only suitable for entities" ); - - if ( m_type == PIID_UNKNOWN ) - { - AssertMsg( 0, "Unknown physics save/load type"); - return; - } - - g_PhysSaveRestoreBlockHandler.QueueRestore( pOwnerEntity, fieldInfo.pTypeDesc, (void **)fieldInfo.pField, m_type ); - } - - virtual void MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - memset( fieldInfo.pField, 0, fieldInfo.pTypeDesc->fieldSize * sizeof( void * ) ); - } - - virtual bool IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - void **ppPhysObj = (void **)fieldInfo.pField; - int nObjects = fieldInfo.pTypeDesc->fieldSize; - for ( int i = 0; i < nObjects; i++ ) - { - if ( ppPhysObj[i] != NULL ) - return false; - } - return true; - } - - PhysInterfaceId_t m_type; -}; - -//----------------------------------------------------------------------------- - -CPhysObjSaveRestoreOps g_PhysObjSaveRestoreOps[PIID_NUM_TYPES]; - -//------------------------------------- - -ISaveRestoreOps *GetPhysObjSaveRestoreOps( PhysInterfaceId_t type ) -{ - static bool inited; - if ( !inited ) - { - inited = true; - for ( int i = 0; i < PIID_NUM_TYPES; i++ ) - { - g_PhysObjSaveRestoreOps[i].m_type = (PhysInterfaceId_t)i; - } - } - return &g_PhysObjSaveRestoreOps[type]; -} - -//============================================================================= diff --git a/game/shared/physics_saverestore.h b/game/shared/physics_saverestore.h deleted file mode 100644 index 0ea0bd841..000000000 --- a/game/shared/physics_saverestore.h +++ /dev/null @@ -1,52 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PHYSICS_SAVERESTORE_H -#define PHYSICS_SAVERESTORE_H - -#if defined( _WIN32 ) -#pragma once -#endif - -#include "vphysics_interface.h" - -class ISaveRestoreBlockHandler; -class IPhysicsObject; -class CPhysCollide; - -//----------------------------------------------------------------------------- - -ISaveRestoreBlockHandler *GetPhysSaveRestoreBlockHandler(); -ISaveRestoreOps *GetPhysObjSaveRestoreOps( PhysInterfaceId_t ); - -//------------------------------------- - -#define DEFINE_PHYSPTR(name) \ - { FIELD_CUSTOM, #name, { offsetof(classNameTypedef,name), 0 }, 1, FTYPEDESC_SAVE, NULL, GetPhysObjSaveRestoreOps( GetPhysIID( &(((classNameTypedef *)0)->name) ) ), NULL } - -#define DEFINE_PHYSPTR_ARRAY(name) \ - { FIELD_CUSTOM, #name, { offsetof(classNameTypedef,name), 0 }, ARRAYSIZE(((classNameTypedef *)0)->name), FTYPEDESC_SAVE, NULL, GetPhysObjSaveRestoreOps( GetPhysIID( &(((classNameTypedef *)0)->name[0]) ) ), NULL } - -//----------------------------------------------------------------------------- - -abstract_class IPhysSaveRestoreManager -{ -public: - virtual void NoteBBox( const Vector &mins, const Vector &maxs, CPhysCollide * ) = 0; - - virtual void AssociateModel( IPhysicsObject *, int modelIndex ) = 0; - virtual void AssociateModel( IPhysicsObject *, const CPhysCollide *pModel ) = 0; - virtual void ForgetModel( IPhysicsObject * ) = 0; - - virtual void ForgetAllModels() = 0; -}; - -extern IPhysSaveRestoreManager *g_pPhysSaveRestoreManager; - -//============================================================================= - -#endif // PHYSICS_SAVERESTORE_H diff --git a/game/shared/physics_shared.cpp b/game/shared/physics_shared.cpp deleted file mode 100644 index d116603d6..000000000 --- a/game/shared/physics_shared.cpp +++ /dev/null @@ -1,1033 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Game & Client shared functions moved from physics.cpp -// -//=============================================================================// -#include "cbase.h" -#include "vcollide_parse.h" -#include "filesystem.h" -#include "movevars_shared.h" -#include "engine/ivmodelinfo.h" -#include "physics_shared.h" -#include "solidsetdefaults.h" -#include "model_types.h" -#include "bone_setup.h" -#include "vphysics/object_hash.h" -#include "vphysics/friction.h" -#include "coordsize.h" -#include -#include "decals.h" -#include "IEffects.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" - -#include "physics_saverestore.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// -IPhysics *physics = NULL; -IPhysicsObject *g_PhysWorldObject = NULL; -IPhysicsCollision *physcollision = NULL; -IPhysicsEnvironment *physenv = NULL; -#ifdef PORTAL -IPhysicsEnvironment *physenv_main = NULL; -#endif -IPhysicsSurfaceProps *physprops = NULL; -// UNDONE: This hash holds both entity & IPhysicsObject pointer pairs -// UNDONE: Split into separate hashes? -IPhysicsObjectPairHash *g_EntityCollisionHash = NULL; - -const char *SURFACEPROP_MANIFEST_FILE = "scripts/surfaceproperties_manifest.txt"; - -const objectparams_t g_PhysDefaultObjectParams = -{ - NULL, - 1.0, //mass - 1.0, // inertia - 0.1f, // damping - 0.1f, // rotdamping - 0.05f, // rotIntertiaLimit - "DEFAULT", - NULL,// game data - 0.f, // volume (leave 0 if you don't have one or call physcollision->CollideVolume() to compute it) - 1.0f, // drag coefficient - true,// enable collisions? -}; - - -void CSolidSetDefaults::ParseKeyValue( void *pData, const char *pKey, const char *pValue ) -{ - if ( !Q_stricmp( pKey, "contents" ) ) - { - m_contentsMask = atoi( pValue ); - } -} - -void CSolidSetDefaults::SetDefaults( void *pData ) -{ - solid_t *pSolid = (solid_t *)pData; - pSolid->params = g_PhysDefaultObjectParams; - m_contentsMask = CONTENTS_SOLID; -} - -CSolidSetDefaults g_SolidSetup; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &mins - -// &maxs - -// Output : CPhysCollide -//----------------------------------------------------------------------------- -CPhysCollide *PhysCreateBbox( const Vector &minsIn, const Vector &maxsIn ) -{ - // UNDONE: Track down why this causes errors for the player controller and adjust/enable - //float radius = 0.5 - DIST_EPSILON; - Vector mins = minsIn;// + Vector(radius, radius, radius); - Vector maxs = maxsIn;// - Vector(radius, radius, radius); - - // VPHYSICS caches/cleans up these - CPhysCollide *pResult = physcollision->BBoxToCollide( mins, maxs ); - - g_pPhysSaveRestoreManager->NoteBBox( mins, maxs, pResult ); - - return pResult; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEntity - -// &mins - -// &maxs - -// &origin - -// isStatic - -// Output : static IPhysicsObject -//----------------------------------------------------------------------------- -IPhysicsObject *PhysModelCreateBox( CBaseEntity *pEntity, const Vector &mins, const Vector &maxs, const Vector &origin, bool isStatic ) -{ - int modelIndex = pEntity->GetModelIndex(); - const char *pSurfaceProps = "flesh"; - solid_t solid; - PhysGetDefaultAABBSolid( solid ); - Vector dims = maxs - mins; - solid.params.volume = dims.x * dims.y * dims.z; - - if ( modelIndex ) - { - const model_t *model = modelinfo->GetModel( modelIndex ); - if ( model ) - { - CStudioHdr studioHdr( modelinfo->GetStudiomodel( model ), mdlcache ); - if ( studioHdr.IsValid() ) - { - pSurfaceProps = Studio_GetDefaultSurfaceProps( &studioHdr ); - } - } - } - Q_strncpy( solid.surfaceprop, pSurfaceProps, sizeof( solid.surfaceprop ) ); - - CPhysCollide *pCollide = PhysCreateBbox( mins, maxs ); - if ( !pCollide ) - return NULL; - - return PhysModelCreateCustom( pEntity, pCollide, origin, vec3_angle, STRING(pEntity->GetModelName()), isStatic, &solid ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEntity - -// &mins - -// &maxs - -// &origin - -// isStatic - -// Output : static IPhysicsObject -//----------------------------------------------------------------------------- -IPhysicsObject *PhysModelCreateOBB( CBaseEntity *pEntity, const Vector &mins, const Vector &maxs, const Vector &origin, const QAngle &angle, bool isStatic ) -{ - int modelIndex = pEntity->GetModelIndex(); - const char *pSurfaceProps = "flesh"; - solid_t solid; - PhysGetDefaultAABBSolid( solid ); - Vector dims = maxs - mins; - solid.params.volume = dims.x * dims.y * dims.z; - - if ( modelIndex ) - { - const model_t *model = modelinfo->GetModel( modelIndex ); - if ( model ) - { - CStudioHdr studioHdr( modelinfo->GetStudiomodel( model ), mdlcache ); - if (studioHdr.IsValid()) - { - pSurfaceProps = Studio_GetDefaultSurfaceProps( &studioHdr ); - } - } - } - Q_strncpy( solid.surfaceprop, pSurfaceProps, sizeof( solid.surfaceprop ) ); - - CPhysCollide *pCollide = PhysCreateBbox( mins, maxs ); - if ( !pCollide ) - return NULL; - - return PhysModelCreateCustom( pEntity, pCollide, origin, angle, STRING(pEntity->GetModelName()), isStatic, &solid ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &solid - -// *pEntity - -// modelIndex - -// solidIndex - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool PhysModelParseSolidByIndex( solid_t &solid, CBaseEntity *pEntity, int modelIndex, int solidIndex ) -{ - vcollide_t *pCollide = modelinfo->GetVCollide( modelIndex ); - if ( !pCollide ) - return false; - - bool parsed = false; - - memset( &solid, 0, sizeof(solid) ); - solid.params = g_PhysDefaultObjectParams; - - IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pCollide->pKeyValues ); - while ( !pParse->Finished() ) - { - const char *pBlock = pParse->GetCurrentBlockName(); - if ( !strcmpi( pBlock, "solid" ) ) - { - solid_t tmpSolid; - memset( &tmpSolid, 0, sizeof(tmpSolid) ); - tmpSolid.params = g_PhysDefaultObjectParams; - - pParse->ParseSolid( &tmpSolid, &g_SolidSetup ); - - if ( solidIndex < 0 || tmpSolid.index == solidIndex ) - { - parsed = true; - solid = tmpSolid; - // just to be sure we aren't ever getting a non-zero solid by accident - Assert( solidIndex >= 0 || solid.index == 0 ); - break; - } - } - else - { - pParse->SkipBlock(); - } - } - physcollision->VPhysicsKeyParserDestroy( pParse ); - - // collisions are off by default - solid.params.enableCollisions = true; - - solid.params.pGameData = static_cast(pEntity); - solid.params.pName = STRING(pEntity->GetModelName()); - return parsed; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &solid - -// *pEntity - -// modelIndex - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool PhysModelParseSolid( solid_t &solid, CBaseEntity *pEntity, int modelIndex ) -{ - return PhysModelParseSolidByIndex( solid, pEntity, modelIndex, -1 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &solid - -// *pEntity - -// *pCollide - -// solidIndex - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool PhysModelParseSolidByIndex( solid_t &solid, CBaseEntity *pEntity, vcollide_t *pCollide, int solidIndex ) -{ - bool parsed = false; - - memset( &solid, 0, sizeof(solid) ); - solid.params = g_PhysDefaultObjectParams; - - IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pCollide->pKeyValues ); - while ( !pParse->Finished() ) - { - const char *pBlock = pParse->GetCurrentBlockName(); - if ( !strcmpi( pBlock, "solid" ) ) - { - solid_t tmpSolid; - memset( &tmpSolid, 0, sizeof(tmpSolid) ); - tmpSolid.params = g_PhysDefaultObjectParams; - - pParse->ParseSolid( &tmpSolid, &g_SolidSetup ); - - if ( solidIndex < 0 || tmpSolid.index == solidIndex ) - { - parsed = true; - solid = tmpSolid; - // just to be sure we aren't ever getting a non-zero solid by accident - Assert( solidIndex >= 0 || solid.index == 0 ); - break; - } - } - else - { - pParse->SkipBlock(); - } - } - physcollision->VPhysicsKeyParserDestroy( pParse ); - - // collisions are off by default - solid.params.enableCollisions = true; - - solid.params.pGameData = static_cast(pEntity); - solid.params.pName = STRING(pEntity->GetModelName()); - return parsed; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEntity - -// modelIndex - -// &origin - -// &angles - -// *pSolid - -// Output : IPhysicsObject -//----------------------------------------------------------------------------- -IPhysicsObject *PhysModelCreate( CBaseEntity *pEntity, int modelIndex, const Vector &origin, const QAngle &angles, solid_t *pSolid ) -{ - vcollide_t *pCollide = modelinfo->GetVCollide( modelIndex ); - if ( !pCollide || !pCollide->solidCount ) - return NULL; - - solid_t tmpSolid; - if ( !pSolid ) - { - pSolid = &tmpSolid; - if ( !PhysModelParseSolidByIndex( tmpSolid, pEntity, pCollide, -1 ) ) - return NULL; - } - - int surfaceProp = -1; - if ( pSolid->surfaceprop[0] ) - { - surfaceProp = physprops->GetSurfaceIndex( pSolid->surfaceprop ); - } - IPhysicsObject *pObject = physenv->CreatePolyObject( pCollide->solids[pSolid->index], surfaceProp, origin, angles, &pSolid->params ); - //PhysCheckAdd( pObject, STRING(pEntity->m_iClassname) ); - - if ( pObject ) - { - if ( modelinfo->GetModelType(modelinfo->GetModel(modelIndex)) == mod_brush ) - { - unsigned int contents = modelinfo->GetModelContents( modelIndex ); - Assert(contents!=0); - // HACKHACK: contents is used to filter collisions - // HACKHACK: So keep solid on for water brushes since they should pass collision rules (as triggers) - if ( contents & MASK_WATER ) - { - contents |= CONTENTS_SOLID; - } - if ( contents != pObject->GetContents() && contents != 0 ) - { - pObject->SetContents( contents ); - pObject->RecheckCollisionFilter(); - } - } - - g_pPhysSaveRestoreManager->AssociateModel( pObject, modelIndex); - } - - return pObject; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEntity - -// modelIndex - -// &origin - -// &angles - -// Output : IPhysicsObject -//----------------------------------------------------------------------------- -IPhysicsObject *PhysModelCreateUnmoveable( CBaseEntity *pEntity, int modelIndex, const Vector &origin, const QAngle &angles ) -{ - vcollide_t *pCollide = modelinfo->GetVCollide( modelIndex ); - if ( !pCollide || !pCollide->solidCount ) - return NULL; - - solid_t solid; - - if ( !PhysModelParseSolidByIndex( solid, pEntity, pCollide, -1 ) ) - return NULL; - - // collisions are off by default - solid.params.enableCollisions = true; - //solid.params.mass = 1.0; - int surfaceProp = -1; - if ( solid.surfaceprop[0] ) - { - surfaceProp = physprops->GetSurfaceIndex( solid.surfaceprop ); - } - solid.params.pGameData = static_cast(pEntity); - solid.params.pName = STRING(pEntity->GetModelName()); - IPhysicsObject *pObject = physenv->CreatePolyObjectStatic( pCollide->solids[0], surfaceProp, origin, angles, &solid.params ); - - //PhysCheckAdd( pObject, STRING(pEntity->m_iClassname) ); - if ( pObject ) - { - if ( modelinfo->GetModelType(modelinfo->GetModel(modelIndex)) == mod_brush ) - { - unsigned int contents = modelinfo->GetModelContents( modelIndex ); - Assert(contents!=0); - if ( contents != pObject->GetContents() && contents != 0 ) - { - pObject->SetContents( contents ); - pObject->RecheckCollisionFilter(); - } - } - g_pPhysSaveRestoreManager->AssociateModel( pObject, modelIndex); - } - - return pObject; -} - - -//----------------------------------------------------------------------------- -// Purpose: Create a vphysics object based on an existing collision model -// Input : *pEntity - -// *pModel - -// &origin - -// &angles - -// *pName - -// isStatic - -// *pSolid - -// Output : IPhysicsObject -//----------------------------------------------------------------------------- -IPhysicsObject *PhysModelCreateCustom( CBaseEntity *pEntity, const CPhysCollide *pModel, const Vector &origin, const QAngle &angles, const char *pName, bool isStatic, solid_t *pSolid ) -{ - solid_t tmpSolid; - if ( !pSolid ) - { - PhysGetDefaultAABBSolid( tmpSolid ); - pSolid = &tmpSolid; - } - int surfaceProp = physprops->GetSurfaceIndex( pSolid->surfaceprop ); - pSolid->params.pGameData = static_cast(pEntity); - pSolid->params.pName = pName; - IPhysicsObject *pObject = NULL; - if ( isStatic ) - { - pObject = physenv->CreatePolyObjectStatic( pModel, surfaceProp, origin, angles, &pSolid->params ); - } - else - { - pObject = physenv->CreatePolyObject( pModel, surfaceProp, origin, angles, &pSolid->params ); - } - - if ( pObject ) - g_pPhysSaveRestoreManager->AssociateModel( pObject, pModel); - - return pObject; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pEntity - -// radius - -// &origin - -// &solid - -// Output : IPhysicsObject -//----------------------------------------------------------------------------- -IPhysicsObject *PhysSphereCreate( CBaseEntity *pEntity, float radius, const Vector &origin, solid_t &solid ) -{ - int surfaceProp = -1; - if ( solid.surfaceprop[0] ) - { - surfaceProp = physprops->GetSurfaceIndex( solid.surfaceprop ); - } - - solid.params.pGameData = static_cast(pEntity); - IPhysicsObject *pObject = physenv->CreateSphereObject( radius, surfaceProp, origin, vec3_angle, &solid.params, false ); - - return pObject; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void PhysGetDefaultAABBSolid( solid_t &solid ) -{ - solid.params = g_PhysDefaultObjectParams; - solid.params.mass = 85.0f; - solid.params.inertia = 1e24f; - Q_strncpy( solid.surfaceprop, "default", sizeof( solid.surfaceprop ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: Destroy a physics object -// Input : *pObject - -//----------------------------------------------------------------------------- -void PhysDestroyObject( IPhysicsObject *pObject, CBaseEntity *pEntity ) -{ - g_pPhysSaveRestoreManager->ForgetModel( pObject ); - - - if ( pObject ) - pObject->SetGameData( NULL ); - - g_EntityCollisionHash->RemoveAllPairsForObject( pObject ); - if ( pEntity && pEntity->IsMarkedForDeletion() ) - { - g_EntityCollisionHash->RemoveAllPairsForObject( pEntity ); - } - physenv->DestroyObject( pObject ); -} - -void AddSurfacepropFile( const char *pFileName, IPhysicsSurfaceProps *pProps, IFileSystem *pFileSystem ) -{ - // Load file into memory - FileHandle_t file = pFileSystem->Open( pFileName, "rb", "GAME" ); - - if ( file ) - { - int len = pFileSystem->Size( file ); - - // read the file - int nBufSize = len+1; - if ( IsXbox() ) - { - nBufSize = AlignValue( nBufSize , 512 ); - } - char *buffer = (char *)stackalloc( nBufSize ); - pFileSystem->ReadEx( buffer, nBufSize, len, file ); - pFileSystem->Close( file ); - buffer[len] = 0; - pProps->ParseSurfaceData( pFileName, buffer ); - // buffer is on the stack, no need to free - } - else - { - Error( "Unable to load surface prop file '%s' (referenced by manifest file '%s')\n", pFileName, SURFACEPROP_MANIFEST_FILE ); - } -} - -void PhysParseSurfaceData( IPhysicsSurfaceProps *pProps, IFileSystem *pFileSystem ) -{ - KeyValues *manifest = new KeyValues( SURFACEPROP_MANIFEST_FILE ); - if ( manifest->LoadFromFile( pFileSystem, SURFACEPROP_MANIFEST_FILE, "GAME" ) ) - { - for ( KeyValues *sub = manifest->GetFirstSubKey(); sub != NULL; sub = sub->GetNextKey() ) - { - if ( !Q_stricmp( sub->GetName(), "file" ) ) - { - // Add - AddSurfacepropFile( sub->GetString(), pProps, pFileSystem ); - continue; - } - - Warning( "surfaceprops::Init: Manifest '%s' with bogus file type '%s', expecting 'file'\n", - SURFACEPROP_MANIFEST_FILE, sub->GetName() ); - } - } - else - { - Error( "Unable to load manifest file '%s'\n", SURFACEPROP_MANIFEST_FILE ); - } - - manifest->deleteThis(); -} - -void PhysCreateVirtualTerrain( CBaseEntity *pWorld, const objectparams_t &defaultParams ) -{ - char nameBuf[1024]; - for ( int i = 0; i < MAX_MAP_DISPINFO; i++ ) - { - CPhysCollide *pCollide = modelinfo->GetCollideForVirtualTerrain( i ); - if ( pCollide ) - { - solid_t solid; - solid.params = defaultParams; - solid.params.enableCollisions = true; - solid.params.pGameData = static_cast(pWorld); - Q_snprintf(nameBuf, sizeof(nameBuf), "vdisp_%04d", i ); - solid.params.pName = nameBuf; - int surfaceData = physprops->GetSurfaceIndex( "default" ); - // create this as part of the world - IPhysicsObject *pObject = physenv->CreatePolyObjectStatic( pCollide, surfaceData, vec3_origin, vec3_angle, &solid.params ); - pObject->SetCallbackFlags( pObject->GetCallbackFlags() | CALLBACK_NEVER_DELETED ); - } - } -} - -IPhysicsObject *PhysCreateWorld_Shared( CBaseEntity *pWorld, vcollide_t *pWorldCollide, const objectparams_t &defaultParams ) -{ - solid_t solid; - fluid_t fluid; - - int surfaceData = physprops->GetSurfaceIndex( "default" ); - - objectparams_t params = defaultParams; - params.pGameData = static_cast(pWorld); - params.pName = "world"; - - IPhysicsObject *pWorldPhysics = physenv->CreatePolyObjectStatic( - pWorldCollide->solids[0], surfaceData, vec3_origin, vec3_angle, ¶ms ); - - // hint - saves vphysics some work - pWorldPhysics->SetCallbackFlags( pWorldPhysics->GetCallbackFlags() | CALLBACK_NEVER_DELETED ); - - //PhysCheckAdd( world, "World" ); - // walk the world keys in case there are some fluid volumes to create - IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pWorldCollide->pKeyValues ); - - bool bCreateVirtualTerrain = false; - while ( !pParse->Finished() ) - { - const char *pBlock = pParse->GetCurrentBlockName(); - - if ( !strcmpi( pBlock, "solid" ) || !strcmpi( pBlock, "staticsolid" ) ) - { - solid.params = defaultParams; - pParse->ParseSolid( &solid, &g_SolidSetup ); - solid.params.enableCollisions = true; - solid.params.pGameData = static_cast(pWorld); - solid.params.pName = "world"; - int surfaceData = physprops->GetSurfaceIndex( "default" ); - - // already created world above - if ( solid.index == 0 ) - continue; - - if ( !pWorldCollide->solids[solid.index] ) - { - // this implies that the collision model is a mopp and the physics DLL doesn't support that. - bCreateVirtualTerrain = true; - continue; - } - // create this as part of the world - IPhysicsObject *pObject = physenv->CreatePolyObjectStatic( pWorldCollide->solids[solid.index], - surfaceData, vec3_origin, vec3_angle, &solid.params ); - - // invalid collision model or can't create, ignore - if (!pObject) - continue; - - pObject->SetCallbackFlags( pObject->GetCallbackFlags() | CALLBACK_NEVER_DELETED ); - Assert( g_SolidSetup.GetContentsMask() != 0 ); - pObject->SetContents( g_SolidSetup.GetContentsMask() ); - - if ( !pWorldPhysics ) - { - pWorldPhysics = pObject; - } - } - else if ( !strcmpi( pBlock, "fluid" ) ) - { - pParse->ParseFluid( &fluid, NULL ); - - // create a fluid for floating - if ( fluid.index > 0 ) - { - solid.params = defaultParams; // copy world's params - solid.params.enableCollisions = true; - solid.params.pName = "fluid"; - solid.params.pGameData = static_cast(pWorld); - fluid.params.pGameData = static_cast(pWorld); - int surfaceData = physprops->GetSurfaceIndex( fluid.surfaceprop ); - // create this as part of the world - IPhysicsObject *pWater = physenv->CreatePolyObjectStatic( pWorldCollide->solids[fluid.index], - surfaceData, vec3_origin, vec3_angle, &solid.params ); - - pWater->SetCallbackFlags( pWater->GetCallbackFlags() | CALLBACK_NEVER_DELETED ); - physenv->CreateFluidController( pWater, &fluid.params ); - } - } - else if ( !strcmpi( pBlock, "materialtable" ) ) - { - int surfaceTable[128]; - memset( surfaceTable, 0, sizeof(surfaceTable) ); - - pParse->ParseSurfaceTable( surfaceTable, NULL ); - physprops->SetWorldMaterialIndexTable( surfaceTable, 128 ); - } - else if ( !strcmpi(pBlock, "virtualterrain" ) ) - { - bCreateVirtualTerrain = true; - pParse->SkipBlock(); - } - else - { - // unknown chunk??? - pParse->SkipBlock(); - } - } - physcollision->VPhysicsKeyParserDestroy( pParse ); - - if ( bCreateVirtualTerrain && physcollision->SupportsVirtualMesh() ) - { - PhysCreateVirtualTerrain( pWorld, defaultParams ); - } - return pWorldPhysics; -} - - -//============================================================================= -// -// Physics Game Trace -// -class CPhysicsGameTrace : public IPhysicsGameTrace -{ -public: - - void VehicleTraceRay( const Ray_t &ray, void *pVehicle, trace_t *pTrace ); - void VehicleTraceRayWithWater( const Ray_t &ray, void *pVehicle, trace_t *pTrace ); - bool VehiclePointInWater( const Vector &vecPoint ); -}; - -CPhysicsGameTrace g_PhysGameTrace; -IPhysicsGameTrace *physgametrace = &g_PhysGameTrace; - -//----------------------------------------------------------------------------- -// Purpose: Game ray-traces in vphysics. -//----------------------------------------------------------------------------- -void CPhysicsGameTrace::VehicleTraceRay( const Ray_t &ray, void *pVehicle, trace_t *pTrace ) -{ - CBaseEntity *pBaseEntity = static_cast( pVehicle ); - UTIL_TraceRay( ray, MASK_SOLID, pBaseEntity, COLLISION_GROUP_NONE, pTrace ); -} - -//----------------------------------------------------------------------------- -// Purpose: Game ray-traces in vphysics. -//----------------------------------------------------------------------------- -void CPhysicsGameTrace::VehicleTraceRayWithWater( const Ray_t &ray, void *pVehicle, trace_t *pTrace ) -{ - CBaseEntity *pBaseEntity = static_cast( pVehicle ); - UTIL_TraceRay( ray, MASK_SOLID|MASK_WATER, pBaseEntity, COLLISION_GROUP_NONE, pTrace ); -} - -//----------------------------------------------------------------------------- -// Purpose: Test to see if a vehicle point is in water. -//----------------------------------------------------------------------------- -bool CPhysicsGameTrace::VehiclePointInWater( const Vector &vecPoint ) -{ - return ( ( UTIL_PointContents( vecPoint ) & MASK_WATER ) != 0 ); -} - -void PhysRecheckObjectPair( IPhysicsObject *pObject0, IPhysicsObject *pObject1 ) -{ - if ( !pObject0->IsStatic() ) - { - pObject0->RecheckCollisionFilter(); - } - if ( !pObject1->IsStatic() ) - { - pObject1->RecheckCollisionFilter(); - } -} - -void PhysEnableEntityCollisions( IPhysicsObject *pObject0, IPhysicsObject *pObject1 ) -{ - if ( !pObject0 || !pObject1 ) - return; - - g_EntityCollisionHash->RemoveObjectPair( pObject0->GetGameData(), pObject1->GetGameData() ); - PhysRecheckObjectPair( pObject0, pObject1 ); -} - -// disables collisions between entities (each entity may contain multiple objects) -void PhysDisableEntityCollisions( IPhysicsObject *pObject0, IPhysicsObject *pObject1 ) -{ - if ( !pObject0 || !pObject1 ) - return; - - g_EntityCollisionHash->AddObjectPair( pObject0->GetGameData(), pObject1->GetGameData() ); - PhysRecheckObjectPair( pObject0, pObject1 ); -} - -void PhysDisableEntityCollisions( CBaseEntity *pEntity0, CBaseEntity *pEntity1 ) -{ - if ( !pEntity0 || !pEntity1 ) - return; - - g_EntityCollisionHash->AddObjectPair( pEntity0, pEntity1 ); -#ifndef CLIENT_DLL - pEntity0->CollisionRulesChanged(); - pEntity1->CollisionRulesChanged(); -#endif -} - - -void PhysEnableEntityCollisions( CBaseEntity *pEntity0, CBaseEntity *pEntity1 ) -{ - if ( !pEntity0 || !pEntity1 ) - return; - - g_EntityCollisionHash->RemoveObjectPair( pEntity0, pEntity1 ); -#ifndef CLIENT_DLL - pEntity0->CollisionRulesChanged(); - pEntity1->CollisionRulesChanged(); -#endif -} - -bool PhysEntityCollisionsAreDisabled( CBaseEntity *pEntity0, CBaseEntity *pEntity1 ) -{ - return g_EntityCollisionHash->IsObjectPairInHash( pEntity0, pEntity1 ); -} - -void PhysEnableObjectCollisions( IPhysicsObject *pObject0, IPhysicsObject *pObject1 ) -{ - if ( !pObject0 || !pObject1 ) - return; - - g_EntityCollisionHash->RemoveObjectPair( pObject0, pObject1 ); - PhysRecheckObjectPair( pObject0, pObject1 ); -} - -// disables collisions between entities (each entity may contain multiple objects) -void PhysDisableObjectCollisions( IPhysicsObject *pObject0, IPhysicsObject *pObject1 ) -{ - if ( !pObject0 || !pObject1 ) - return; - - g_EntityCollisionHash->AddObjectPair( pObject0, pObject1 ); - PhysRecheckObjectPair( pObject0, pObject1 ); -} - -void PhysComputeSlideDirection( IPhysicsObject *pPhysics, const Vector &inputVelocity, const AngularImpulse &inputAngularVelocity, - Vector *pOutputVelocity, Vector *pOutputAngularVelocity, float minMass ) -{ - Vector velocity = inputVelocity; - AngularImpulse angVel = inputAngularVelocity; - Vector pos; - - IPhysicsFrictionSnapshot *pSnapshot = pPhysics->CreateFrictionSnapshot(); - while ( pSnapshot->IsValid() ) - { - IPhysicsObject *pOther = pSnapshot->GetObject( 1 ); - if ( !pOther->IsMoveable() || pOther->GetMass() > minMass ) - { - Vector normal; - pSnapshot->GetSurfaceNormal( normal ); - - // BUGBUG: Figure out the correct rotation clipping equation - if ( pOutputAngularVelocity ) - { - angVel = normal * DotProduct( angVel, normal ); -#if 0 - pSnapshot->GetContactPoint( point ); - Vector point, dummy; - AngularImpulse angularClip, clip2; - - pPhysics->CalculateVelocityOffset( normal, point, dummy, angularClip ); - VectorNormalize( angularClip ); - float proj = DotProduct( angVel, angularClip ); - if ( proj > 0 ) - { - angVel -= angularClip * proj; - } - CrossProduct( angularClip, normal, clip2 ); - proj = DotProduct( angVel, clip2 ); - if ( proj > 0 ) - { - angVel -= clip2 * proj; - } - //NDebugOverlay::Line( point, point - normal * 20, 255, 0, 0, true, 0.1 ); -#endif - } - - // Determine how far along plane to slide based on incoming direction. - // NOTE: Normal points away from this object - float proj = DotProduct( velocity, normal ); - if ( proj > 0.0f ) - { - velocity -= normal * proj; - } - } - pSnapshot->NextFrictionData(); - } - pPhysics->DestroyFrictionSnapshot( pSnapshot ); - - //NDebugOverlay::Line( pos, pos + unitVel * 20, 0, 0, 255, true, 0.1 ); - - if ( pOutputVelocity ) - { - *pOutputVelocity = velocity; - } - if ( pOutputAngularVelocity ) - { - *pOutputAngularVelocity = angVel; - } -} - -bool PhysHasContactWithOtherInDirection( IPhysicsObject *pPhysics, const Vector &dir ) -{ - bool hit = false; - void *pGameData = pPhysics->GetGameData(); - IPhysicsFrictionSnapshot *pSnapshot = pPhysics->CreateFrictionSnapshot(); - while ( pSnapshot->IsValid() ) - { - IPhysicsObject *pOther = pSnapshot->GetObject( 1 ); - if ( pOther->GetGameData() != pGameData ) - { - Vector normal; - pSnapshot->GetSurfaceNormal( normal ); - if ( DotProduct(normal,dir) > 0 ) - { - hit = true; - break; - } - } - pSnapshot->NextFrictionData(); - } - pPhysics->DestroyFrictionSnapshot( pSnapshot ); - - return hit; -} - - -void PhysForceClearVelocity( IPhysicsObject *pPhys ) -{ - IPhysicsFrictionSnapshot *pSnapshot = pPhys->CreateFrictionSnapshot(); - // clear the velocity of the rigid body - Vector vel; - AngularImpulse angVel; - vel.Init(); - angVel.Init(); - pPhys->SetVelocity( &vel, &angVel ); - // now clear the "strain" stored in the contact points - while ( pSnapshot->IsValid() ) - { - pSnapshot->ClearFrictionForce(); - pSnapshot->RecomputeFriction(); - pSnapshot->NextFrictionData(); - } - pPhys->DestroyFrictionSnapshot( pSnapshot ); -} - - -void PhysFrictionEffect( Vector &vecPos, Vector vecVel, float energy, int surfaceProps, int surfacePropsHit ) -{ - Vector invVecVel = -vecVel; - VectorNormalize( invVecVel ); - - surfacedata_t *psurf = physprops->GetSurfaceData( surfaceProps ); - surfacedata_t *phit = physprops->GetSurfaceData( surfacePropsHit ); - - switch ( phit->game.material ) - { - case CHAR_TEX_DIRT: - - if ( energy < MASS10_SPEED2ENERGY(15) ) - break; - - g_pEffects->Dust( vecPos, invVecVel, 1, 16 ); - break; - - case CHAR_TEX_CONCRETE: - - if ( energy < MASS10_SPEED2ENERGY(28) ) - break; - - g_pEffects->Dust( vecPos, invVecVel, 1, 16 ); - break; - } - - //Metal sparks - if ( energy > MASS10_SPEED2ENERGY(50) ) - { - // make sparks for metal/concrete scrapes with enough energy - if ( psurf->game.material == CHAR_TEX_METAL || psurf->game.material == CHAR_TEX_GRATE ) - { - switch ( phit->game.material ) - { - case CHAR_TEX_CONCRETE: - case CHAR_TEX_METAL: - - g_pEffects->MetalSparks( vecPos, invVecVel ); - break; - } - } - } -} - -void PhysFrictionSound( CBaseEntity *pEntity, IPhysicsObject *pObject, float energy, int surfaceProps, int surfacePropsHit ) -{ - if ( !pEntity || energy < 75.0f || surfaceProps < 0 ) - return; - - // don't make noise for hidden/invisible/sky materials - surfacedata_t *phit = physprops->GetSurfaceData( surfacePropsHit ); - surfacedata_t *psurf = physprops->GetSurfaceData( surfaceProps ); - - if ( phit->game.material == 'X' || psurf->game.material == 'X' ) - return; - - // rescale the incoming energy - energy *= ENERGY_VOLUME_SCALE; - - // volume of scrape is proportional to square of energy (steeper rolloff at low energies) - float volume = energy * energy; - - unsigned short soundName = psurf->sounds.scrapeRough; - short *soundHandle = &psurf->soundhandles.scrapeRough; - - if ( psurf->sounds.scrapeSmooth && phit->audio.roughnessFactor < psurf->audio.roughThreshold ) - { - soundName = psurf->sounds.scrapeSmooth; - soundHandle = &psurf->soundhandles.scrapeRough; - } - - const char *pSoundName = physprops->GetString( soundName ); - - PhysFrictionSound( pEntity, pObject, pSoundName, *soundHandle, volume ); -} - -//----------------------------------------------------------------------------- -// Purpose: Precaches a surfaceproperties string name if it's set. -// Input : idx - -// Output : static void -//----------------------------------------------------------------------------- -static HSOUNDSCRIPTHANDLE PrecachePhysicsSoundByStringIndex( int idx ) -{ - // Only precache if a value was set in the script file... - if ( idx != 0 ) - { - return CBaseEntity::PrecacheScriptSound( physprops->GetString( idx ) ); - } - - return SOUNDEMITTER_INVALID_HANDLE; -} - -//----------------------------------------------------------------------------- -// Purpose: Iterates all surfacedata sounds and precaches them -// Output : static void -//----------------------------------------------------------------------------- -void PrecachePhysicsSounds() -{ - // precache the surface prop sounds - for ( int i = 0; i < physprops->SurfacePropCount(); i++ ) - { - surfacedata_t *pprop = physprops->GetSurfaceData( i ); - Assert( pprop ); - - pprop->soundhandles.stepleft = PrecachePhysicsSoundByStringIndex( pprop->sounds.stepleft ); - pprop->soundhandles.stepright = PrecachePhysicsSoundByStringIndex( pprop->sounds.stepright ); - pprop->soundhandles.impactSoft = PrecachePhysicsSoundByStringIndex( pprop->sounds.impactSoft ); - pprop->soundhandles.impactHard = PrecachePhysicsSoundByStringIndex( pprop->sounds.impactHard ); - pprop->soundhandles.scrapeSmooth = PrecachePhysicsSoundByStringIndex( pprop->sounds.scrapeSmooth ); - pprop->soundhandles.scrapeRough = PrecachePhysicsSoundByStringIndex( pprop->sounds.scrapeRough ); - pprop->soundhandles.bulletImpact = PrecachePhysicsSoundByStringIndex( pprop->sounds.bulletImpact ); - pprop->soundhandles.rolling = PrecachePhysicsSoundByStringIndex( pprop->sounds.rolling ); - pprop->soundhandles.breakSound = PrecachePhysicsSoundByStringIndex( pprop->sounds.breakSound ); - pprop->soundhandles.strainSound = PrecachePhysicsSoundByStringIndex( pprop->sounds.strainSound ); - } -} - - diff --git a/game/shared/physics_shared.h b/game/shared/physics_shared.h deleted file mode 100644 index e32245343..000000000 --- a/game/shared/physics_shared.h +++ /dev/null @@ -1,175 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef PHYSICS_SHARED_H -#define PHYSICS_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - -class IPhysics; -class IPhysicsEnvironment; -class IPhysicsSurfaceProps; -class IPhysicsCollision; -class IPhysicsObject; -class IPhysicsObjectPairHash; -class CSoundPatch; - - -extern IPhysicsObject *g_PhysWorldObject; -extern IPhysics *physics; -extern IPhysicsCollision *physcollision; -extern IPhysicsEnvironment *physenv; -#ifdef PORTAL -extern IPhysicsEnvironment *physenv_main; -#endif -extern IPhysicsSurfaceProps *physprops; -extern IPhysicsObjectPairHash *g_EntityCollisionHash; - -extern const objectparams_t g_PhysDefaultObjectParams; - -// Compute enough energy of a reference mass travelling at speed -// makes numbers more intuitive -#define MASS_SPEED2ENERGY(mass, speed) ((speed)*(speed)*(mass)) - -// energy of a 10kg mass moving at speed -#define MASS10_SPEED2ENERGY(speed) MASS_SPEED2ENERGY(10,speed) - -#define MASS_ENERGY2SPEED(mass,energy) (FastSqrt((energy)/mass)) - -#define ENERGY_VOLUME_SCALE (1.0f / 15500.0f) - -#define FLUID_TIME_MAX 2.0f // keep track of last time hitting fluid for up to 2 seconds - -// VPHYSICS object game-specific flags -#define FVPHYSICS_DMG_SLICE 0x0001 // does slice damage, not just blunt damage -#define FVPHYSICS_CONSTRAINT_STATIC 0x0002 // object is constrained to the world, so it should behave like a static -#define FVPHYSICS_PLAYER_HELD 0x0004 // object is held by the player, so have a very inelastic collision response -#define FVPHYSICS_PART_OF_RAGDOLL 0x0008 // object is part of a client or server ragdoll -#define FVPHYSICS_MULTIOBJECT_ENTITY 0x0010 // object is part of a multi-object entity -#define FVPHYSICS_HEAVY_OBJECT 0x0020 // HULK SMASH! (Do large damage even if the mass is small) -#define FVPHYSICS_PENETRATING 0x0040 // This object is currently stuck inside another object -#define FVPHYSICS_NO_PLAYER_PICKUP 0x0080 // Player can't pick this up for some game rule reason -#define FVPHYSICS_WAS_THROWN 0x0100 // Player threw this object -#define FVPHYSICS_DMG_DISSOLVE 0x0200 // does dissolve damage, not just blunt damage -#define FVPHYSICS_NO_IMPACT_DMG 0x0400 // don't do impact damage to anything -#define FVPHYSICS_NO_NPC_IMPACT_DMG 0x0800 // Don't do impact damage to NPC's. This is temporary for NPC's shooting combine balls (sjb) -#define FVPHYSICS_NO_SELF_COLLISIONS 0x8000 // don't collide with other objects that are part of the same entity - -//----------------------------------------------------------------------------- -// Purpose: A little cache of current objects making noises -//----------------------------------------------------------------------------- -struct friction_t -{ - CSoundPatch *patch; - CBaseEntity *pObject; - float flLastUpdateTime; - float flLastEffectTime; -}; - -enum -{ - TOUCH_START=0, - TOUCH_END, -}; - -struct touchevent_t -{ - CBaseEntity *pEntity0; - CBaseEntity *pEntity1; - int touchType; - Vector endPoint; //sv - Vector normal; //sv -}; - -struct fluidevent_t -{ - EHANDLE hEntity; - float impactTime; -}; - -void PhysFrictionSound( CBaseEntity *pEntity, IPhysicsObject *pObject, float energy, int surfaceProps, int surfacePropsHit ); -void PhysFrictionSound( CBaseEntity *pEntity, IPhysicsObject *pObject, const char *pSoundName, HSOUNDSCRIPTHANDLE& handle, float flVolume ); -void PhysCleanupFrictionSounds( CBaseEntity *pEntity ); -void PhysFrictionEffect( Vector &vecPos, Vector vecVel, float energy, int surfaceProps, int surfacePropsHit ); - -// Convenience routine -// ORs gameFlags with the physics object's current game flags -inline unsigned short PhysSetGameFlags( IPhysicsObject *pPhys, unsigned short gameFlags ) -{ - unsigned short flags = pPhys->GetGameFlags(); - flags |= gameFlags; - pPhys->SetGameFlags( flags ); - - return flags; -} -// mask off gameFlags -inline unsigned short PhysClearGameFlags( IPhysicsObject *pPhys, unsigned short gameFlags ) -{ - unsigned short flags = pPhys->GetGameFlags(); - flags &= ~gameFlags; - pPhys->SetGameFlags( flags ); - - return flags; -} - - -// Create a vphysics object based on a model -IPhysicsObject *PhysModelCreate( CBaseEntity *pEntity, int modelIndex, const Vector &origin, const QAngle &angles, solid_t *pSolid = NULL ); - -IPhysicsObject *PhysModelCreateBox( CBaseEntity *pEntity, const Vector &mins, const Vector &maxs, const Vector &origin, bool isStatic ); -IPhysicsObject *PhysModelCreateOBB( CBaseEntity *pEntity, const Vector &mins, const Vector &maxs, const Vector &origin, const QAngle &angle, bool isStatic ); - -// Create a vphysics object based on a BSP model (unmoveable) -IPhysicsObject *PhysModelCreateUnmoveable( CBaseEntity *pEntity, int modelIndex, const Vector &origin, const QAngle &angles ); - -// Create a vphysics object based on an existing collision model -IPhysicsObject *PhysModelCreateCustom( CBaseEntity *pEntity, const CPhysCollide *pModel, const Vector &origin, const QAngle &angles, const char *pName, bool isStatic, solid_t *pSolid = NULL ); - -// Create a bbox collision model (these may be shared among entities, they are auto-deleted at end of level. do not manage) -CPhysCollide *PhysCreateBbox( const Vector &mins, const Vector &maxs ); - -// Create a vphysics sphere object -IPhysicsObject *PhysSphereCreate( CBaseEntity *pEntity, float radius, const Vector &origin, solid_t &solid ); - -// Destroy a physics object created using PhysModelCreate...() -void PhysDestroyObject( IPhysicsObject *pObject, CBaseEntity *pEntity = NULL ); - -void PhysDisableObjectCollisions( IPhysicsObject *pObject0, IPhysicsObject *pObject1 ); -void PhysDisableEntityCollisions( IPhysicsObject *pObject0, IPhysicsObject *pObject1 ); -void PhysDisableEntityCollisions( CBaseEntity *pEntity0, CBaseEntity *pEntity1 ); -void PhysEnableObjectCollisions( IPhysicsObject *pObject0, IPhysicsObject *pObject1 ); -void PhysEnableEntityCollisions( IPhysicsObject *pObject0, IPhysicsObject *pObject1 ); -void PhysEnableEntityCollisions( CBaseEntity *pEntity0, CBaseEntity *pEntity1 ); -bool PhysEntityCollisionsAreDisabled( CBaseEntity *pEntity0, CBaseEntity *pEntity1 ); - -// create the world physics objects -IPhysicsObject *PhysCreateWorld_Shared( CBaseEntity *pWorld, vcollide_t *pWorldCollide, const objectparams_t &defaultParams ); - -// parse the parameters for a single solid from the model's collision data -bool PhysModelParseSolid( solid_t &solid, CBaseEntity *pEntity, int modelIndex ); -// parse the parameters for a solid matching a particular index -bool PhysModelParseSolidByIndex( solid_t &solid, CBaseEntity *pEntity, int modelIndex, int solidIndex ); - -void PhysParseSurfaceData( class IPhysicsSurfaceProps *pProps, class IFileSystem *pFileSystem ); - -// fill out this solid_t with the AABB defaults (high inertia/no rotation) -void PhysGetDefaultAABBSolid( solid_t &solid ); - -// Compute an output velocity based on sliding along the current contact points -// in the closest direction toward inputVelocity. -void PhysComputeSlideDirection( IPhysicsObject *pPhysics, const Vector &inputVelocity, const AngularImpulse &inputAngularVelocity, - Vector *pOutputVelocity, Vector *pOutputAngularVelocity, float minMass ); - -void PhysForceClearVelocity( IPhysicsObject *pPhys ); -bool PhysHasContactWithOtherInDirection( IPhysicsObject *pPhysics, const Vector &dir ); - -//----------------------------------------------------------------------------- -// Singleton access -//----------------------------------------------------------------------------- -IGameSystem* PhysicsGameSystem(); - -#endif // PHYSICS_SHARED_H diff --git a/game/shared/playerclass_info_parse.cpp b/game/shared/playerclass_info_parse.cpp deleted file mode 100644 index 668c84479..000000000 --- a/game/shared/playerclass_info_parse.cpp +++ /dev/null @@ -1,247 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Weapon data file parsing, shared by game & client dlls. -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include -#include -#include "filesystem.h" -#include "utldict.h" -#include "ammodef.h" - -#include "playerclass_info_parse.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -static CUtlDict< FilePlayerClassInfo_t*, unsigned short > m_PlayerClassInfoDatabase; - -#define MAX_PLAYERCLASSES 32 - -#ifdef _DEBUG - -// used to track whether or not two player classes have been mistakenly assigned the same slot -bool g_bUsedPlayerClassSlots[MAX_PLAYERCLASSES] = { 0 }; - -#endif - - -#ifdef DEBUG - -void CC_ReloadPlayerClasses_f (void) -{ - //ResetFilePlayerClassInfoDatabase(); -} - -static ConCommand dod_reloadplayerclasses("dod_reloadplayerclasses", CC_ReloadPlayerClasses_f, "Reset player class info cache" ); - -#endif - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -// Output : FilePlayerClassInfo_t -//----------------------------------------------------------------------------- -static PLAYERCLASS_FILE_INFO_HANDLE FindPlayerClassInfoSlot( const char *name ) -{ - // Complain about duplicately defined metaclass names... - unsigned short lookup = m_PlayerClassInfoDatabase.Find( name ); - if ( lookup != m_PlayerClassInfoDatabase.InvalidIndex() ) - { - return lookup; - } - - FilePlayerClassInfo_t *insert = CreatePlayerClassInfo(); - - lookup = m_PlayerClassInfoDatabase.Insert( name, insert ); - Assert( lookup != m_PlayerClassInfoDatabase.InvalidIndex() ); - return lookup; -} - -// Find a class slot, assuming the weapon's data has already been loaded. -PLAYERCLASS_FILE_INFO_HANDLE LookupPlayerClassInfoSlot( const char *name ) -{ - return m_PlayerClassInfoDatabase.Find( name ); -} - - - -// FIXME, handle differently? -static FilePlayerClassInfo_t gNullPlayerClassInfo; - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : handle - -// Output : FilePlayerClassInfo_t -//----------------------------------------------------------------------------- -FilePlayerClassInfo_t *GetFilePlayerClassInfoFromHandle( PLAYERCLASS_FILE_INFO_HANDLE handle ) -{ - if ( handle == GetInvalidPlayerClassInfoHandle() ) - { - Assert( !"bad index into playerclass info UtlDict" ); - return &gNullPlayerClassInfo; - } - - return m_PlayerClassInfoDatabase[ handle ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : PLAYERCLASS_FILE_INFO_HANDLE -//----------------------------------------------------------------------------- -PLAYERCLASS_FILE_INFO_HANDLE GetInvalidPlayerClassInfoHandle( void ) -{ - return (PLAYERCLASS_FILE_INFO_HANDLE)m_PlayerClassInfoDatabase.InvalidIndex(); -} - -void ResetFilePlayerClassInfoDatabase( void ) -{ - m_PlayerClassInfoDatabase.PurgeAndDeleteElements(); - -#ifdef _DEBUG - memset(g_bUsedPlayerClassSlots, 0, sizeof(g_bUsedPlayerClassSlots)); -#endif -} - -#ifndef _XBOX -KeyValues* ReadEncryptedKVPlayerClassFile( IFileSystem *filesystem, const char *szFilenameWithoutExtension, const unsigned char *pICEKey ) -{ - Assert( strchr( szFilenameWithoutExtension, '.' ) == NULL ); - char szFullName[512]; - - // Open the weapon data file, and abort if we can't - KeyValues *pKV = new KeyValues( "PlayerClassDatafile" ); - - Q_snprintf(szFullName,sizeof(szFullName), "%s.txt", szFilenameWithoutExtension); - - if ( !pKV->LoadFromFile( filesystem, szFullName, "GAME" ) ) // try to load the normal .txt file first - { - if ( pICEKey ) - { - Q_snprintf(szFullName,sizeof(szFullName), "%s.ctx", szFilenameWithoutExtension); // fall back to the .ctx file - - FileHandle_t f = filesystem->Open( szFullName, "rb", "GAME"); - - if (!f) - { - pKV->deleteThis(); - return NULL; - } - // load file into a null-terminated buffer - int fileSize = filesystem->Size(f); - char *buffer = (char*)MemAllocScratch(fileSize + 1); - - Assert(buffer); - - filesystem->Read(buffer, fileSize, f); // read into local buffer - buffer[fileSize] = 0; // null terminate file as EOF - filesystem->Close( f ); // close file after reading - - UTIL_DecodeICE( (unsigned char*)buffer, fileSize, pICEKey ); - - bool retOK = pKV->LoadFromBuffer( szFullName, buffer, filesystem ); - - MemFreeScratch(); - - if ( !retOK ) - { - pKV->deleteThis(); - return NULL; - } - } - else - { - pKV->deleteThis(); - return NULL; - } - } - - return pKV; -} -#endif - -//----------------------------------------------------------------------------- -// Purpose: Read data on weapon from script file -// Output: true - if data2 successfully read -// false - if data load fails -//----------------------------------------------------------------------------- -bool ReadPlayerClassDataFromFileForSlot( IFileSystem* filesystem, const char *szPlayerClassName, PLAYERCLASS_FILE_INFO_HANDLE *phandle, const unsigned char *pICEKey ) -{ - if ( !phandle ) - { - Assert( 0 ); - return false; - } - - *phandle = FindPlayerClassInfoSlot( szPlayerClassName ); - FilePlayerClassInfo_t *pFileInfo = GetFilePlayerClassInfoFromHandle( *phandle ); - Assert( pFileInfo ); - - if ( pFileInfo->m_bParsedScript ) - return true; - - char sz[128]; - Q_snprintf( sz, sizeof( sz ), "scripts/playerclass_%s", szPlayerClassName ); - KeyValues *pKV = ReadEncryptedKVFile( filesystem, sz, pICEKey ); - if ( !pKV ) - return false; - - pFileInfo->Parse( pKV, szPlayerClassName ); - - pKV->deleteThis(); - - return true; -} - - -//----------------------------------------------------------------------------- -// FilePlayerClassInfo_t implementation. -//----------------------------------------------------------------------------- - -FilePlayerClassInfo_t::FilePlayerClassInfo_t() -{ - m_bParsedScript = false; - - m_szPlayerClassName[0] = 0; - m_szPrintName[0] = 0; - m_szPlayerModel[0] = 0; - m_szSelectCmd[0] = 0; -} - -void FilePlayerClassInfo_t::Parse( KeyValues *pKeyValuesData, const char *szPlayerClassName ) -{ - // Okay, we tried at least once to look this up... - m_bParsedScript = true; - - // Classname - Q_strncpy( m_szPlayerClassName, szPlayerClassName, MAX_WEAPON_STRING ); - - // Printable name - Q_strncpy( m_szPrintName, pKeyValuesData->GetString( "printname", "!! Missing printname on Player Class" ), MAX_PLAYERCLASS_NAME_LENGTH ); - - // Player Model - Q_strncpy( m_szPlayerModel, pKeyValuesData->GetString( "playermodel", "!! Missing playermodel on Player Class" ), MAX_PLAYERCLASS_NAME_LENGTH ); - - // Select command - Q_strncpy( m_szSelectCmd, pKeyValuesData->GetString( "selectcmd", "!! Missing selectcmd on Player Class" ), 32 ); - - -#if defined(_DEBUG) && defined(HL2_CLIENT_DLL) - - // Use this for class select keys - - /* - // make sure two weapons aren't in the same slot & position - if (g_bUsedPlayerClassSlots[iSlot]) - { - Msg( "Weapon slot info: %s (%d, %d)\n", szPrintName, iSlot, iPosition ); - Warning( "Duplicately assigned weapon to slots in selection hud\n" ); - } - g_bUsedPlayerClassSlots[iSlot][iPosition] = true; - */ -#endif -} - diff --git a/game/shared/playerclass_info_parse.h b/game/shared/playerclass_info_parse.h deleted file mode 100644 index 3652b2d28..000000000 --- a/game/shared/playerclass_info_parse.h +++ /dev/null @@ -1,84 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Player class data file parsing, shared by game & client dlls. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PLAYERCLASS_INFO_PARSE_H -#define PLAYERCLASS_INFO_PARSE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "shareddefs.h" - -class IFileSystem; -class KeyValues; - -typedef unsigned short PLAYERCLASS_FILE_INFO_HANDLE; - -#define MAX_PLAYERCLASS_NAME_LENGTH 128 - -//----------------------------------------------------------------------------- -// Purpose: Contains the data read from the player class script files. -// It's cached so we only read each script file once. -// Each game provides a CreatePlayerClassInfo function so it can have game-specific -// data in the player class scripts. -//----------------------------------------------------------------------------- -class FilePlayerClassInfo_t -{ -public: - - FilePlayerClassInfo_t(); - - // Each game can override this to get whatever values it wants from the script. - virtual void Parse( KeyValues *pKeyValuesData, const char *szClassName ); - - -public: - bool m_bParsedScript; - -public: - // Class properties - - // todo : better lengths for these arrays ? - - char m_szPlayerClassName[MAX_PLAYERCLASS_NAME_LENGTH]; - char m_szPrintName[MAX_PLAYERCLASS_NAME_LENGTH]; // localization key for print name - char m_szPlayerModel[MAX_PLAYERCLASS_NAME_LENGTH]; - char m_szSelectCmd[32]; //command the player can issue to switch to this class -}; - -// The weapon parse function -bool ReadPlayerClassDataFromFileForSlot( IFileSystem* filesystem, const char *szClassName, - PLAYERCLASS_FILE_INFO_HANDLE *phandle, const unsigned char *pICEKey = NULL ); - -// If player class info has been loaded for the specified class name, this returns it. -PLAYERCLASS_FILE_INFO_HANDLE LookupPlayerClassInfoSlot( const char *name ); - -// Given a handle to the player class info, return the class data -FilePlayerClassInfo_t *GetFilePlayerClassInfoFromHandle( PLAYERCLASS_FILE_INFO_HANDLE handle ); - -// Get the null Player Class object -PLAYERCLASS_FILE_INFO_HANDLE GetInvalidPlayerClassInfoHandle( void ); - -// Initialize all player class info -void ResetFilePlayerClassInfoDatabase( void ); - - -// -// Read a possibly-encrypted KeyValues file in. -// If pICEKey is NULL, then it appends .txt to the filename and loads it as an unencrypted file. -// If pICEKey is non-NULL, then it appends .ctx to the filename and loads it as an encrypted file. -// -// (This should be moved into a more appropriate place). -// -extern KeyValues* ReadEncryptedKVPlayerClassFile( IFileSystem *filesystem, const char *szFilenameWithoutExtension, const unsigned char *pICEKey ); - - -// Each game implements this. It can return a derived class and override Parse() if it wants. -extern FilePlayerClassInfo_t* CreatePlayerClassInfo(); - - -#endif // PLAYERCLASS_INFO_PARSE_H diff --git a/game/shared/playernet_vars.h b/game/shared/playernet_vars.h deleted file mode 100644 index 32dd01053..000000000 --- a/game/shared/playernet_vars.h +++ /dev/null @@ -1,123 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PLAYERNET_VARS_H -#define PLAYERNET_VARS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "shared_classnames.h" - -#define NUM_AUDIO_LOCAL_SOUNDS 8 - -// These structs are contained in each player's local data and shared by the client & server - -struct fogparams_t -{ - DECLARE_CLASS_NOBASE( fogparams_t ); - DECLARE_EMBEDDED_NETWORKVAR(); - -#ifndef CLIENT_DLL - DECLARE_SIMPLE_DATADESC(); -#endif - - bool operator !=( const fogparams_t& other ) const; - - CNetworkVector( dirPrimary ); - CNetworkColor32( colorPrimary ); - CNetworkColor32( colorSecondary ); - CNetworkColor32( colorPrimaryLerpTo ); - CNetworkColor32( colorSecondaryLerpTo ); - CNetworkVar( float, start ); - CNetworkVar( float, end ); - CNetworkVar( float, farz ); - CNetworkVar( float, maxdensity ); - - CNetworkVar( float, startLerpTo ); - CNetworkVar( float, endLerpTo ); - CNetworkVar( float, lerptime ); - CNetworkVar( float, duration ); - CNetworkVar( bool, enable ); - CNetworkVar( bool, blend ); -}; - -// Crappy. Needs to be here because it wants to use -#ifdef CLIENT_DLL -#define CFogController C_FogController -#endif - -class CFogController; - -struct fogplayerparams_t -{ - DECLARE_CLASS_NOBASE( fogplayerparams_t ); - DECLARE_EMBEDDED_NETWORKVAR(); - -#ifndef CLIENT_DLL - DECLARE_SIMPLE_DATADESC(); -#endif - - CNetworkHandle( CFogController, m_hCtrl ); - float m_flTransitionTime; - - color32 m_OldColor; - float m_flOldStart; - float m_flOldEnd; - - color32 m_NewColor; - float m_flNewStart; - float m_flNewEnd; - - fogplayerparams_t() - { - m_hCtrl.Set( NULL ); - m_flTransitionTime = -1.0f; - m_OldColor.r = m_OldColor.g = m_OldColor.b = m_OldColor.a = 0; - m_flOldStart = 0.0f; - m_flOldEnd = 0.0f; - m_NewColor.r = m_NewColor.g = m_NewColor.b = m_NewColor.a = 0; - m_flNewStart = 0.0f; - m_flNewEnd = 0.0f; - } -}; - -struct sky3dparams_t -{ - DECLARE_CLASS_NOBASE( sky3dparams_t ); - DECLARE_EMBEDDED_NETWORKVAR(); - -#ifndef CLIENT_DLL - DECLARE_SIMPLE_DATADESC(); -#endif - - // 3d skybox camera data - CNetworkVar( int, scale ); - CNetworkVector( origin ); - CNetworkVar( int, area ); - - // 3d skybox fog data - CNetworkVarEmbedded( fogparams_t, fog ); -}; - -struct audioparams_t -{ - DECLARE_CLASS_NOBASE( audioparams_t ); - DECLARE_EMBEDDED_NETWORKVAR(); - -#ifndef CLIENT_DLL - DECLARE_SIMPLE_DATADESC(); -#endif - - CNetworkArray( Vector, localSound, NUM_AUDIO_LOCAL_SOUNDS ) - CNetworkVar( int, soundscapeIndex ); // index of the current soundscape from soundscape.txt - CNetworkVar( int, localBits ); // if bits 0,1,2,3 are set then position 0,1,2,3 are valid/used - CNetworkHandle( CBaseEntity, ent ); // the entity setting the soundscape -}; - - -#endif // PLAYERNET_VARS_H diff --git a/game/shared/point_bonusmaps_accessor.cpp b/game/shared/point_bonusmaps_accessor.cpp deleted file mode 100644 index f1c6b0e9b..000000000 --- a/game/shared/point_bonusmaps_accessor.cpp +++ /dev/null @@ -1,147 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include "cbase.h" - -#include "GameUI/IGameUI.h" -#include "fmtstr.h" -#include "igameevents.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// See interface.h/.cpp for specifics: basically this ensures that we actually Sys_UnloadModule the dll and that we don't call Sys_LoadModule -// over and over again. -static CDllDemandLoader g_GameUI( "gameui" ); - -#ifndef CLIENT_DLL - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CPointBonusMapsAccessor : public CPointEntity -{ -public: - DECLARE_CLASS( CPointBonusMapsAccessor, CPointEntity ); - DECLARE_DATADESC(); - - virtual void Activate( void ); - - void InputUnlock( inputdata_t& inputdata ); - void InputComplete( inputdata_t& inputdata ); - void InputSave( inputdata_t& inputdata ); - -private: - string_t m_String_tFileName; - string_t m_String_tMapName; - IGameUI *m_pGameUI; -}; - -BEGIN_DATADESC( CPointBonusMapsAccessor ) - DEFINE_KEYFIELD( m_String_tFileName, FIELD_STRING, "filename" ), - DEFINE_KEYFIELD( m_String_tMapName, FIELD_STRING, "mapname" ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Unlock", InputUnlock ), - DEFINE_INPUTFUNC( FIELD_VOID, "Complete", InputComplete ), - DEFINE_INPUTFUNC( FIELD_VOID, "Save", InputSave ), -END_DATADESC() - -LINK_ENTITY_TO_CLASS( point_bonusmaps_accessor, CPointBonusMapsAccessor ); - -void CPointBonusMapsAccessor::Activate( void ) -{ - BaseClass::Activate(); - - CreateInterfaceFn gameUIFactory = g_GameUI.GetFactory(); - if ( gameUIFactory ) - { - m_pGameUI = (IGameUI *) gameUIFactory(GAMEUI_INTERFACE_VERSION, NULL ); - } -} - -void CPointBonusMapsAccessor::InputUnlock( inputdata_t& inputdata ) -{ - if ( m_pGameUI ) - m_pGameUI->BonusMapUnlock( m_String_tFileName.ToCStr(), m_String_tMapName.ToCStr() ); -} - -void CPointBonusMapsAccessor::InputComplete( inputdata_t& inputdata ) -{ - if ( m_pGameUI ) - { - m_pGameUI->BonusMapComplete( m_String_tFileName.ToCStr(), m_String_tMapName.ToCStr() ); - - int iNumAdvancedComplete = m_pGameUI->BonusMapNumAdvancedCompleted(); - - IGameEvent *event = gameeventmanager->CreateEvent( "advanced_map_complete" ); - if ( event ) - { - event->SetInt( "numadvanced", iNumAdvancedComplete ); - gameeventmanager->FireEvent( event ); - } - } -} - -void CPointBonusMapsAccessor::InputSave( inputdata_t& inputdata ) -{ - if ( m_pGameUI ) - m_pGameUI->BonusMapDatabaseSave(); -} - -#endif - -void BonusMapChallengeUpdate( const char *pchFileName, const char *pchMapName, const char *pchChallengeName, int iBest ) -{ - CreateInterfaceFn gameUIFactory = g_GameUI.GetFactory(); - if ( gameUIFactory ) - { - IGameUI *pGameUI = (IGameUI *) gameUIFactory(GAMEUI_INTERFACE_VERSION, NULL ); - if ( pGameUI ) - { - pGameUI->BonusMapChallengeUpdate( pchFileName, pchMapName, pchChallengeName, iBest ); - - int piNumMedals[ 3 ]; - pGameUI->BonusMapNumMedals( piNumMedals ); - - IGameEvent *event = gameeventmanager->CreateEvent( "challenge_map_complete" ); - if ( event ) - { - event->SetInt( "numbronze", piNumMedals[ 0 ] ); - event->SetInt( "numsilver", piNumMedals[ 1 ] ); - event->SetInt( "numgold", piNumMedals[ 2 ] ); - gameeventmanager->FireEvent( event ); - } - } - } -} - -void BonusMapChallengeNames( char *pchFileName, char *pchMapName, char *pchChallengeName ) -{ - CreateInterfaceFn gameUIFactory = g_GameUI.GetFactory(); - if ( gameUIFactory ) - { - IGameUI *pGameUI = (IGameUI *) gameUIFactory(GAMEUI_INTERFACE_VERSION, NULL ); - if ( pGameUI ) - { - pGameUI->BonusMapChallengeNames( pchFileName, pchMapName, pchChallengeName ); - } - } -} - -void BonusMapChallengeObjectives( int &iBronze, int &iSilver, int &iGold ) -{ - CreateInterfaceFn gameUIFactory = g_GameUI.GetFactory(); - if ( gameUIFactory ) - { - IGameUI *pGameUI = (IGameUI *) gameUIFactory(GAMEUI_INTERFACE_VERSION, NULL ); - if ( pGameUI ) - { - pGameUI->BonusMapChallengeObjectives( iBronze, iSilver, iGold ); - } - } -} diff --git a/game/shared/point_bonusmaps_accessor.h b/game/shared/point_bonusmaps_accessor.h deleted file mode 100644 index 4fbd62ca1..000000000 --- a/game/shared/point_bonusmaps_accessor.h +++ /dev/null @@ -1,21 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef POINT_BONUSMAPS_ACCESSOR_H -#define POINT_BONUSMAPS_ACCESSOR_H - -#ifdef _WIN32 -#pragma once -#endif - - -void BonusMapChallengeUpdate( const char *pchFileName, const char *pchMapName, const char *pchChallengeName, int iBest ); -void BonusMapChallengeNames( char *pchFileName, char *pchMapName, char *pchChallengeName ); -void BonusMapChallengeObjectives( int &iBronze, int &iSilver, int &iGold ); - - -#endif // POINT_BONUSMAPS_ACCESSOR_H diff --git a/game/shared/point_posecontroller.cpp b/game/shared/point_posecontroller.cpp deleted file mode 100644 index 4d45595d1..000000000 --- a/game/shared/point_posecontroller.cpp +++ /dev/null @@ -1,545 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: Controls the pose parameters of a model -// -//===========================================================================// - - -#include "cbase.h" -#include "point_posecontroller.h" - - -#ifndef CLIENT_DLL -//----------------------------------------------------------------------------- -// SERVER CLASS -//----------------------------------------------------------------------------- - -#include "baseanimating.h" -#include "props.h" - - -#define MAX_POSE_INTERPOLATION_TIME 10.0f -#define MAX_POSE_CYCLE_FREQUENCY 10.0f -#define MAX_POSE_FMOD_RATE 10.0f -#define MAX_POSE_FMOD_AMPLITUDE 10.0f - - -LINK_ENTITY_TO_CLASS( point_posecontroller, CPoseController ); - - -BEGIN_DATADESC( CPoseController ) - DEFINE_AUTO_ARRAY( m_hProps, FIELD_EHANDLE ), - DEFINE_AUTO_ARRAY( m_chPoseIndex, FIELD_CHARACTER ), - DEFINE_FIELD( m_bDisablePropLookup, FIELD_BOOLEAN ), - DEFINE_FIELD( m_bPoseValueParity, FIELD_BOOLEAN ), - // Keys - DEFINE_KEYFIELD( m_iszPropName, FIELD_STRING, "PropName" ), - DEFINE_KEYFIELD( m_iszPoseParameterName, FIELD_STRING, "PoseParameterName" ), - DEFINE_KEYFIELD( m_fPoseValue, FIELD_FLOAT, "PoseValue" ), - DEFINE_KEYFIELD( m_fInterpolationTime, FIELD_FLOAT, "InterpolationTime" ), - DEFINE_KEYFIELD( m_bInterpolationWrap, FIELD_BOOLEAN, "InterpolationWrap" ), - DEFINE_KEYFIELD( m_fCycleFrequency, FIELD_FLOAT, "CycleFrequency" ), - DEFINE_KEYFIELD( m_nFModType, FIELD_INTEGER, "FModType" ), - DEFINE_KEYFIELD( m_fFModTimeOffset, FIELD_FLOAT, "FModTimeOffset" ), - DEFINE_KEYFIELD( m_fFModRate, FIELD_FLOAT, "FModRate" ), - DEFINE_KEYFIELD( m_fFModAmplitude, FIELD_FLOAT, "FModAmplitude" ), - // Functions - DEFINE_FUNCTION( Think ), - // Inputs - DEFINE_INPUTFUNC( FIELD_STRING, "SetPoseParameterName", InputSetPoseParameterName ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetPoseValue", InputSetPoseValue ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetInterpolationTime", InputSetInterpolationTime ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetCycleFrequency", InputSetCycleFrequency ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetFModType", InputSetFModType ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFModTimeOffset", InputSetFModTimeOffset ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFModRate", InputSetFModRate ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "SetFModAmplitude", InputSetFModAmplitude ), - DEFINE_INPUTFUNC( FIELD_FLOAT, "RandomizeFMod", InputRandomizeFMod ), - DEFINE_INPUTFUNC( FIELD_VOID, "GetFMod", InputGetFMod ), -END_DATADESC() - - -IMPLEMENT_SERVERCLASS_ST(CPoseController, DT_PoseController) - SendPropArray3( SENDINFO_ARRAY3(m_hProps), SendPropEHandle( SENDINFO_ARRAY(m_hProps) ) ), - SendPropArray3( SENDINFO_ARRAY3(m_chPoseIndex), SendPropInt( SENDINFO_ARRAY(m_chPoseIndex), 5, SPROP_UNSIGNED ) ), // bits sent must be enough to represent MAXSTUDIOPOSEPARAM - SendPropBool( SENDINFO(m_bPoseValueParity) ), - SendPropFloat( SENDINFO(m_fPoseValue), 11, 0, 0.0f, 1.0f ), - SendPropFloat( SENDINFO(m_fInterpolationTime), 11, 0, 0.0f, MAX_POSE_INTERPOLATION_TIME ), - SendPropBool( SENDINFO(m_bInterpolationWrap) ), - SendPropFloat( SENDINFO(m_fCycleFrequency), 11, 0, -MAX_POSE_CYCLE_FREQUENCY, MAX_POSE_CYCLE_FREQUENCY ), - SendPropInt( SENDINFO(m_nFModType), 3, SPROP_UNSIGNED ), - SendPropFloat( SENDINFO(m_fFModTimeOffset), 11, 0, -1.0f, 1.0f ), - SendPropFloat( SENDINFO(m_fFModRate), 11, 0, -MAX_POSE_FMOD_RATE, MAX_POSE_FMOD_RATE ), - SendPropFloat( SENDINFO(m_fFModAmplitude), 11, 0, 0.0f, MAX_POSE_FMOD_AMPLITUDE ), -END_SEND_TABLE() - - -void CPoseController::Spawn( void ) -{ - BaseClass::Spawn(); - - // Talk to the client class when data changes - AddEFlags( EFL_FORCE_CHECK_TRANSMIT ); - - // Think to refresh the list of models - SetThink( &CPoseController::Think ); - SetNextThink( gpGlobals->curtime + 1.0 ); -} - -void CPoseController::Think( void ) -{ - if ( !m_bDisablePropLookup ) - { - // Refresh the list of models - BuildPropList(); - - SetCurrentPose( m_fPoseValue ); - - m_bDisablePropLookup = true; - - SetNextThink( gpGlobals->curtime + 1.0 ); - } -} - -void CPoseController::BuildPropList( void ) -{ - int iPropNum = 0; - CBaseEntity *pEnt = gEntList.FindEntityByName( NULL, m_iszPropName ); - - while ( pEnt && iPropNum < MAX_POSE_CONTROLLED_PROPS ) - { - CBaseAnimating *pProp = dynamic_cast( pEnt ); - if ( pProp ) - { - CDynamicProp *pDynamicProp = dynamic_cast( pProp ); - if ( pDynamicProp ) - pDynamicProp->PropSetSequence( 0 ); - - if ( m_hProps[ iPropNum ] != pProp ) - { - // Only set new handles (to avoid network spam) - m_hProps.Set( iPropNum, pProp ); - } - - // Update the pose parameter index - SetPoseIndex( iPropNum, pProp->LookupPoseParameter( m_iszPoseParameterName.ToCStr() ) ); - - ++iPropNum; - } - - // Get the next entity with specified targetname - pEnt = gEntList.FindEntityByName( pEnt, m_iszPropName ); - } - - // Nullify the remaining handles - while ( iPropNum < MAX_POSE_CONTROLLED_PROPS ) - { - if ( m_hProps[ iPropNum ] != NULL ) - m_hProps.Set( iPropNum, NULL ); - - ++iPropNum; - } - - SetNextThink( gpGlobals->curtime + 1.0 ); -} - -void CPoseController::BuildPoseIndexList( void ) -{ - for ( int iPropNum = 0; iPropNum < MAX_POSE_CONTROLLED_PROPS; ++iPropNum ) - { - CBaseAnimating *pProp = dynamic_cast( m_hProps[ iPropNum ].Get() ); - - if ( pProp ) - { - // Update the pose parameter index - SetPoseIndex( iPropNum, pProp->LookupPoseParameter( m_iszPoseParameterName.ToCStr() ) ); - } - } -} - -void CPoseController::SetPoseIndex( int i, int iValue ) -{ - if ( iValue == -1 ) - { - // Using this as invalid lets us network less bits - iValue = MAXSTUDIOPOSEPARAM; - } - - if ( m_chPoseIndex[ i ] != iValue ) - { - // Only set a new index (to avoid network spam) - m_chPoseIndex.Set( i, iValue ); - } -} - -float CPoseController::GetPoseValue( void ) -{ - return m_fPoseValue; -} - -void CPoseController::SetProp( CBaseAnimating *pProp ) -{ - // Control a prop directly by pointer - if ( m_hProps[ 0 ] != pProp ) - { - // Only set new handles (to avoid network spam) - m_hProps.Set( 0, pProp ); - } - - // Update the pose parameter index - SetPoseIndex( 0, pProp->LookupPoseParameter( m_iszPoseParameterName.ToCStr() ) ); - - // Nullify the remaining handles - for ( int iPropNum = 1; iPropNum < MAX_POSE_CONTROLLED_PROPS; ++iPropNum ) - { - if ( m_hProps[ iPropNum ] != NULL ) - m_hProps.Set( iPropNum, NULL ); - } - - m_bDisablePropLookup = false; -} - -void CPoseController::SetPropName( const char *pName ) -{ - m_iszPropName = MAKE_STRING( pName ); - - BuildPropList(); -} - -void CPoseController::SetPoseParameterName( const char *pName ) -{ - m_iszPoseParameterName = MAKE_STRING( pName ); - - BuildPoseIndexList(); -} - -void CPoseController::SetPoseValue( float fValue ) -{ - m_fPoseValue = clamp( fValue, 0.0f, 1.0f ); - - // Force the client to set the current pose - m_bPoseValueParity = !m_bPoseValueParity; - - SetCurrentPose( m_fPoseValue ); -} - -void CPoseController::SetInterpolationTime( float fValue ) -{ - m_fInterpolationTime = clamp( fValue, 0.0f, MAX_POSE_INTERPOLATION_TIME ); -} - -void CPoseController::SetInterpolationWrap( bool bWrap ) -{ - m_bInterpolationWrap = bWrap; -} - -void CPoseController::SetCycleFrequency( float fValue ) -{ - m_fCycleFrequency = clamp( fValue, -MAX_POSE_CYCLE_FREQUENCY, MAX_POSE_CYCLE_FREQUENCY ); -} - -void CPoseController::SetFModType( int nType ) -{ - if ( nType < 0 || nType >= POSECONTROLLER_FMODTYPE_TOTAL ) - return; - - m_nFModType = static_cast(nType); -} - -void CPoseController::SetFModTimeOffset( float fValue ) -{ - m_fFModTimeOffset = clamp( fValue, -1.0f, 1.0f ); -} - -void CPoseController::SetFModRate( float fValue ) -{ - m_fFModRate = clamp( fValue, -MAX_POSE_FMOD_RATE, MAX_POSE_FMOD_RATE ); -} - -void CPoseController::SetFModAmplitude( float fValue ) -{ - m_fFModAmplitude = clamp( fValue, 0.0f, MAX_POSE_FMOD_AMPLITUDE ); -} - -void CPoseController::RandomizeFMod( float fExtremeness ) -{ - fExtremeness = clamp( fExtremeness, 0.0f, 1.0f ); - - SetFModType( RandomInt( 1, POSECONTROLLER_FMODTYPE_TOTAL - 1 ) ); - SetFModTimeOffset( RandomFloat( -1.0, 1.0f ) ); - SetFModRate( RandomFloat( fExtremeness * -MAX_POSE_FMOD_RATE, fExtremeness * MAX_POSE_FMOD_RATE ) ); - SetFModAmplitude( RandomFloat( 0.0f, fExtremeness * MAX_POSE_FMOD_AMPLITUDE ) ); -} - -void CPoseController::InputSetPoseParameterName( inputdata_t &inputdata ) -{ - SetPoseParameterName( inputdata.value.String() ); -} - -void CPoseController::InputSetPoseValue( inputdata_t &inputdata ) -{ - SetPoseValue( inputdata.value.Float() ); -} - -void CPoseController::InputSetInterpolationTime( inputdata_t &inputdata ) -{ - SetInterpolationTime( inputdata.value.Float() ); -} - -void CPoseController::InputSetCycleFrequency( inputdata_t &inputdata ) -{ - SetCycleFrequency( inputdata.value.Float() ); -} - -void CPoseController::InputSetFModType( inputdata_t &inputdata ) -{ - SetFModType( inputdata.value.Int() ); -} - -void CPoseController::InputSetFModTimeOffset( inputdata_t &inputdata ) -{ - SetFModTimeOffset( inputdata.value.Float() ); -} - -void CPoseController::InputSetFModRate( inputdata_t &inputdata ) -{ - SetFModRate( inputdata.value.Float() ); -} - -void CPoseController::InputSetFModAmplitude( inputdata_t &inputdata ) -{ - SetFModAmplitude( inputdata.value.Float() ); -} - -void CPoseController::InputRandomizeFMod( inputdata_t &inputdata ) -{ - RandomizeFMod( inputdata.value.Float() ); -} - -void CPoseController::InputGetFMod( inputdata_t &inputdata ) -{ - DevMsg( "FMod values for pose controller %s\nTYPE: %i\nTIME OFFSET: %f\nRATE: %f\nAMPLITUDE: %f\n", - STRING(GetEntityName()), - m_nFModType.Get(), - m_fFModTimeOffset.Get(), - m_fFModRate.Get(), - m_fFModAmplitude.Get() ); -} - - -#else //#ifndef CLIENT_DLL -//----------------------------------------------------------------------------- -// CLIENT CLASS -//----------------------------------------------------------------------------- - - -IMPLEMENT_CLIENTCLASS_DT( C_PoseController, DT_PoseController, CPoseController ) - RecvPropArray3( RECVINFO_ARRAY(m_hProps), RecvPropEHandle( RECVINFO(m_hProps[0]) ) ), - RecvPropArray3( RECVINFO_ARRAY(m_chPoseIndex), RecvPropInt( RECVINFO(m_chPoseIndex[0]) ) ), - RecvPropBool( RECVINFO(m_bPoseValueParity) ), - RecvPropFloat( RECVINFO(m_fPoseValue) ), - RecvPropFloat( RECVINFO(m_fInterpolationTime) ), - RecvPropBool( RECVINFO(m_bInterpolationWrap) ), - RecvPropFloat( RECVINFO(m_fCycleFrequency) ), - RecvPropInt( RECVINFO(m_nFModType) ), - RecvPropFloat( RECVINFO(m_fFModTimeOffset) ), - RecvPropFloat( RECVINFO(m_fFModRate) ), - RecvPropFloat( RECVINFO(m_fFModAmplitude) ), -END_RECV_TABLE() - - -void C_PoseController::Spawn( void ) -{ - SetThink( &C_PoseController::ClientThink ); - SetNextClientThink( CLIENT_THINK_ALWAYS ); - - m_fCurrentFMod = 0.0f; - m_PoseTransitionValue.Init( 0.0f, 0.0f, 0.0f ); - - BaseClass::Spawn(); -} - -void C_PoseController::OnDataChanged( DataUpdateType_t updateType ) -{ - BaseClass::OnDataChanged( updateType ); - - if ( updateType == DATA_UPDATE_CREATED ) - { - // Start thinking (Baseclass stops it) - SetNextClientThink( CLIENT_THINK_ALWAYS ); - - m_bOldPoseValueParity = m_bPoseValueParity; - m_fCurrentPoseValue = m_fPoseValue; - - SetCurrentPose( m_fCurrentPoseValue ); - } - - if ( m_bOldPoseValueParity != m_bPoseValueParity ) - { - // If the pose value was set directly set the actual pose value - float fClientPoseValue = m_fCurrentPoseValue + m_PoseTransitionValue.Interp( gpGlobals->curtime ); - - if ( fClientPoseValue < 0.0f ) - fClientPoseValue += 1.0f; - else if ( fClientPoseValue > 1.0f ) - fClientPoseValue -= 1.0f; - - float fInterpForward = fClientPoseValue - m_fPoseValue; - - if ( m_bInterpolationWrap ) - { - float fInterpBackward = ( fClientPoseValue + ( ( fClientPoseValue < 0.5f ) ? ( 1.0f ) : ( -1.0f ) ) ) - m_fPoseValue; - - m_PoseTransitionValue.Init( ( ( fabsf( fInterpForward ) < fabsf( fInterpBackward ) ) ? ( fInterpForward ) : ( fInterpBackward ) ), 0.0f, m_fInterpolationTime ); - } - else - { - m_PoseTransitionValue.Init( fInterpForward, 0.0f, m_fInterpolationTime ); - } - - m_bOldPoseValueParity = m_bPoseValueParity; - m_fCurrentPoseValue = m_fPoseValue; - } -} - -void C_PoseController::ClientThink( void ) -{ - UpdateModulation(); - - UpdatePoseCycle( m_fCycleFrequency + m_fCurrentFMod ); -} - -void C_PoseController::UpdateModulation( void ) -{ - switch ( m_nFModType ) - { - case POSECONTROLLER_FMODTYPE_NONE: - { - // No modulation - m_fCurrentFMod = 0.0f; - break; - } - - case POSECONTROLLER_FMODTYPE_SINE: - { - float fCycleTime = m_fFModRate * ( gpGlobals->curtime + m_fFModTimeOffset ); - - m_fCurrentFMod = m_fFModAmplitude * sinf( fCycleTime * ( 2.0f * M_PI ) ); - break; - } - - case POSECONTROLLER_FMODTYPE_SQUARE: - { - float fCycleTime = fabsf( m_fFModRate * 2.0f * ( gpGlobals->curtime + m_fFModTimeOffset ) ); - - // Separate the current time into integer and decimal - int iIntegerPortion = static_cast( fCycleTime ); - - // Find if it's going up or down - if ( ( iIntegerPortion % 2 ) == 0 ) - m_fCurrentFMod = m_fFModAmplitude; - else - m_fCurrentFMod = -m_fFModAmplitude; - - break; - } - - case POSECONTROLLER_FMODTYPE_TRIANGLE: - { - float fCycleTime = fabsf( m_fFModRate * 4.0f * ( gpGlobals->curtime + m_fFModTimeOffset ) ); - - // Separate the current time into integer and decimal - int iIntegerPortion = static_cast( fCycleTime ); - float fDecimalPortion = fCycleTime - static_cast( iIntegerPortion ); - - // Find if it's going up from 0, down from 1, down from 0, or up from -1 - switch ( iIntegerPortion % 4 ) - { - case 0: - m_fCurrentFMod = fDecimalPortion * m_fFModAmplitude; - break; - case 1: - m_fCurrentFMod = ( 1.0f - fDecimalPortion ) * m_fFModAmplitude; - break; - case 2: - m_fCurrentFMod = -fDecimalPortion * m_fFModAmplitude; - break; - case 3: - m_fCurrentFMod = ( -1.0f + fDecimalPortion ) * m_fFModAmplitude; - break; - } - - break; - } - - case POSECONTROLLER_FMODTYPE_SAWTOOTH: - { - float fCycleTime = fabsf( m_fFModRate * 2.0f * ( gpGlobals->curtime + m_fFModTimeOffset ) ); - - // Separate the current time into integer and decimal - int iIntegerPortion = static_cast( fCycleTime ); - float fDecimalPortion = fCycleTime - static_cast( iIntegerPortion ); - - // Find if it's going up from 0 or up from -1 - if ( ( iIntegerPortion % 2 ) == 0 ) - m_fCurrentFMod = fDecimalPortion * m_fFModAmplitude; - else - m_fCurrentFMod = ( -1.0f + fDecimalPortion ) * m_fFModAmplitude; - - break; - } - - case POSECONTROLLER_FMODTYPE_NOISE: - { - // Randomly increase or decrease by the rate - if ( RandomInt( 0, 1 ) == 0 ) - m_fCurrentFMod += m_fFModRate * gpGlobals->frametime; - else - m_fCurrentFMod -= m_fFModRate * gpGlobals->frametime; - - m_fCurrentFMod = clamp( m_fCurrentFMod, -m_fFModAmplitude, m_fFModAmplitude ); - - break; - } - } -} - -void C_PoseController::UpdatePoseCycle( float fCycleAmount ) -{ - m_fCurrentPoseValue += fCycleAmount * gpGlobals->frametime; - - float fNewPoseValue = m_fCurrentPoseValue + m_PoseTransitionValue.Interp( gpGlobals->curtime ); - - if ( fNewPoseValue < 0.0f ) - fNewPoseValue += 1.0f; - else if ( fNewPoseValue > 1.0f ) - fNewPoseValue -= 1.0f; - - SetCurrentPose( fNewPoseValue ); -} - -#define CPoseController C_PoseController -#define CBaseAnimating C_BaseAnimating - - -#endif //#ifndef CLIENT_DLL - - -void CPoseController::SetCurrentPose( float fCurrentPoseValue ) -{ - for ( int iPropNum = 0; iPropNum < MAX_POSE_CONTROLLED_PROPS; ++iPropNum ) - { - // Control each model's pose parameter - CBaseAnimating *pProp = dynamic_cast( m_hProps[ iPropNum ].Get() ); - - if ( pProp ) - { - float fPoseValueMin; - float fPoseValueMax; - - // Map to the pose parameter's range - pProp->GetPoseParameterRange( m_chPoseIndex[ iPropNum ], fPoseValueMin, fPoseValueMax ); - pProp->SetPoseParameter( m_chPoseIndex[ iPropNum ], fPoseValueMin + fCurrentPoseValue * ( fPoseValueMax - fPoseValueMin ) ); - } - } -} diff --git a/game/shared/point_posecontroller.h b/game/shared/point_posecontroller.h deleted file mode 100644 index b8fd5b1cd..000000000 --- a/game/shared/point_posecontroller.h +++ /dev/null @@ -1,150 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: Controls the pose parameters of a model -// -//===========================================================================// - - -#define MAX_POSE_CONTROLLED_PROPS 4 // Number of entities by the same name that can be controlled - - -// Type of frequency modulations -enum PoseController_FModType_t -{ - POSECONTROLLER_FMODTYPE_NONE = 0, - POSECONTROLLER_FMODTYPE_SINE, - POSECONTROLLER_FMODTYPE_SQUARE, - POSECONTROLLER_FMODTYPE_TRIANGLE, - POSECONTROLLER_FMODTYPE_SAWTOOTH, - POSECONTROLLER_FMODTYPE_NOISE, - - POSECONTROLLER_FMODTYPE_TOTAL, -}; - - -#ifndef CLIENT_DLL -//----------------------------------------------------------------------------- -// SERVER CLASS -//----------------------------------------------------------------------------- - -#include "baseentity.h" - - -class CPoseController : public CBaseEntity -{ -public: - DECLARE_CLASS( CPoseController, CBaseEntity ); - DECLARE_SERVERCLASS(); - DECLARE_DATADESC(); - - virtual void Spawn( void ); - - void Think( void ); - - void BuildPropList( void ); - void BuildPoseIndexList( void ); - void SetPoseIndex( int i, int iValue ); - void SetCurrentPose( float fCurrentPoseValue ); - - float GetPoseValue( void ); - - void SetProp( CBaseAnimating *pProp ); - void SetPropName( const char *pName ); - void SetPoseParameterName( const char *pName ); - void SetPoseValue( float fValue ); - void SetInterpolationTime( float fValue ); - void SetInterpolationWrap( bool bWrap ); - void SetCycleFrequency( float fValue ); - void SetFModType( int nType ); - void SetFModTimeOffset( float fValue ); - void SetFModRate( float fValue ); - void SetFModAmplitude( float fValue ); - void RandomizeFMod( float fExtremeness ); - - // Input handlers - void InputSetPoseParameterName( inputdata_t &inputdata ); - void InputSetPoseValue( inputdata_t &inputdata ); - void InputSetInterpolationTime( inputdata_t &inputdata ); - void InputSetCycleFrequency( inputdata_t &inputdata ); - void InputSetFModType( inputdata_t &inputdata ); - void InputSetFModTimeOffset( inputdata_t &inputdata ); - void InputSetFModRate( inputdata_t &inputdata ); - void InputSetFModAmplitude( inputdata_t &inputdata ); - void InputRandomizeFMod( inputdata_t &inputdata ); - void InputGetFMod( inputdata_t &inputdata ); - -private: - - CNetworkArray( EHANDLE, m_hProps, MAX_POSE_CONTROLLED_PROPS ); // Handles to controlled models - CNetworkArray( unsigned char, m_chPoseIndex, MAX_POSE_CONTROLLED_PROPS ); // Pose parameter indices for each model - - bool m_bDisablePropLookup; - - CNetworkVar( bool, m_bPoseValueParity ); - - string_t m_iszPropName; // Targetname of the models to control - string_t m_iszPoseParameterName; // Pose parameter name to control - - CNetworkVar( float, m_fPoseValue ); // Normalized pose parameter value (maps to each pose parameter's min and max range) - CNetworkVar( float, m_fInterpolationTime ); // Interpolation speed for client matching absolute pose values - CNetworkVar( bool, m_bInterpolationWrap ); // Interpolation for the client wraps 0 to 1. - - CNetworkVar( float, m_fCycleFrequency ); // Cycles per second - - // Frequency modulation variables - CNetworkVar( PoseController_FModType_t, m_nFModType ); - CNetworkVar( float, m_fFModTimeOffset ); - CNetworkVar( float, m_fFModRate ); - CNetworkVar( float, m_fFModAmplitude ); -}; - - -#else //#ifndef CLIENT_DLL -//----------------------------------------------------------------------------- -// CLIENT CLASS -//----------------------------------------------------------------------------- - -#include "c_baseentity.h" -#include "fx_interpvalue.h" - - -class C_PoseController : public C_BaseEntity -{ -public: - DECLARE_CLASS( C_PoseController, C_BaseEntity ); - DECLARE_CLIENTCLASS(); - - virtual void Spawn( void ); - virtual void OnDataChanged( DataUpdateType_t updateType ); - - virtual void ClientThink( void ); - -private: - - void UpdateModulation( void ); - void UpdatePoseCycle( float fCycleAmount ); - void SetCurrentPose( float fCurrentPoseValue ); - - - // Networked variables - EHANDLE m_hProps[MAX_POSE_CONTROLLED_PROPS]; - unsigned char m_chPoseIndex[MAX_POSE_CONTROLLED_PROPS]; - bool m_bPoseValueParity; - float m_fPoseValue; - float m_fInterpolationTime; - bool m_bInterpolationWrap; - float m_fCycleFrequency; - PoseController_FModType_t m_nFModType; - float m_fFModTimeOffset; - float m_fFModRate; - float m_fFModAmplitude; - bool m_bOldPoseValueParity; - - float m_fCurrentPoseValue; // Actual pose value cycled by the frequency and modulation - float m_fCurrentFMod; // The current fequency modulation amount (stored for noise walk) - - CInterpolatedValue m_PoseTransitionValue; -}; - - -#endif //#ifndef CLIENT_DLL diff --git a/game/shared/positionwatcher.h b/game/shared/positionwatcher.h deleted file mode 100644 index d2abe1c9a..000000000 --- a/game/shared/positionwatcher.h +++ /dev/null @@ -1,47 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef POSITIONWATCHER_H -#define POSITIONWATCHER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "ehandle.h" - -// inherit from this interface to be able to call WatchPositionChanges -abstract_class IWatcherCallback -{ -public: - virtual ~IWatcherCallback() {} -}; - -abstract_class IPositionWatcher : public IWatcherCallback -{ -public: - virtual void NotifyPositionChanged( CBaseEntity *pEntity ) = 0; -}; - -// NOTE: The table of watchers is NOT saved/loaded! Recreate these links on restore -void ReportPositionChanged( CBaseEntity *pMovedEntity ); -void WatchPositionChanges( CBaseEntity *pWatcher, CBaseEntity *pMovingEntity ); -void RemovePositionWatcher( CBaseEntity *pWatcher, CBaseEntity *pMovingEntity ); - - -// inherit from this interface to be able to call WatchPositionChanges -abstract_class IVPhysicsWatcher : public IWatcherCallback -{ -public: - virtual void NotifyVPhysicsStateChanged( IPhysicsObject *pPhysics, CBaseEntity *pEntity, bool bAwake ) = 0; -}; - -// NOTE: The table of watchers is NOT saved/loaded! Recreate these links on restore -void ReportVPhysicsStateChanged( IPhysicsObject *pPhysics, CBaseEntity *pEntity, bool bAwake ); -void WatchVPhysicsStateChanges( CBaseEntity *pWatcher, CBaseEntity *pPhysicsEntity ); -void RemoveVPhysicsStateWatcher( CBaseEntity *pWatcher, CBaseEntity *pPhysicsEntity ); - - -#endif // POSITIONWATCHER_H diff --git a/game/shared/precache_register.cpp b/game/shared/precache_register.cpp deleted file mode 100644 index c78e1ada3..000000000 --- a/game/shared/precache_register.cpp +++ /dev/null @@ -1,39 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "precache_register.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -static CPrecacheRegister *g_pPrecacheRegisters = 0; - -CPrecacheRegister::CPrecacheRegister(PrecacheFn fn, const void *pUser) -{ - m_Fn = fn; - m_pUser = const_cast(pUser); - - m_pNext = g_pPrecacheRegisters; - g_pPrecacheRegisters = this; -} - - -void CPrecacheRegister::Precache() -{ - for(CPrecacheRegister *pCur=g_pPrecacheRegisters; pCur; pCur=pCur->m_pNext) - { - pCur->m_Fn(pCur->m_pUser); - } -} - - -void CPrecacheRegister::PrecacheFn_Other(void *pUser) -{ - UTIL_PrecacheOther((const char*)pUser); -} - - diff --git a/game/shared/precache_register.h b/game/shared/precache_register.h deleted file mode 100644 index d58a9e4d1..000000000 --- a/game/shared/precache_register.h +++ /dev/null @@ -1,38 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PRECACHE_REGISTER_H -#define PRECACHE_REGISTER_H -#pragma once - - -// Use these macros to register something to be precached. -#define PRECACHE_REGISTER_FN(functionName) static CPrecacheRegister precache_function_##functionName(functionName, 0); -#define PRECACHE_WEAPON_REGISTER(className) static CPrecacheRegister precache_weapon_##className(&CPrecacheRegister::PrecacheFn_Other, #className) -#define PRECACHE_REGISTER(className) static CPrecacheRegister precache_other_##className( &CPrecacheRegister::PrecacheFn_Other, #className) - -class CPrecacheRegister -{ -public: - - typedef void (*PrecacheFn)(void *pUser); // Prototype for a custom precache function. - - CPrecacheRegister(PrecacheFn fn, const void *pUser); - - PrecacheFn m_Fn; - void *m_pUser; - CPrecacheRegister *m_pNext; - - static void Precache(); // Calls everything that has registered to precache. - -// Don't call these. -public: - static void PrecacheFn_Other(void *pUser); -}; - - -#endif // PRECACHE_REGISTER_H diff --git a/game/shared/precipitation_shared.h b/game/shared/precipitation_shared.h deleted file mode 100644 index ca93c10a0..000000000 --- a/game/shared/precipitation_shared.h +++ /dev/null @@ -1,25 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef PRECIPITATION_SHARED_H -#define PRECIPITATION_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - - -// Types of precipitation -enum PrecipitationType_t -{ - PRECIPITATION_TYPE_RAIN = 0, - PRECIPITATION_TYPE_SNOW, - PRECIPITATION_TYPE_ASH, - PRECIPITATION_TYPE_SNOWFALL, - NUM_PRECIPITATION_TYPES -}; - - -#endif // PRECIPITATION_SHARED_H diff --git a/game/shared/predictable_entity.h b/game/shared/predictable_entity.h deleted file mode 100644 index 3e6cd7e65..000000000 --- a/game/shared/predictable_entity.h +++ /dev/null @@ -1,203 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PREDICTABLE_ENTITY_H -#define PREDICTABLE_ENTITY_H -#ifdef _WIN32 -#pragma once -#endif - -// For introspection -#include "tier0/platform.h" -#include "predictioncopy.h" -#include "shared_classnames.h" - -#ifndef NO_ENTITY_PREDICTION -#define UsePrediction() 1 -#else -#define UsePrediction() 0 -#endif - -// CLIENT DLL includes -#if defined( CLIENT_DLL ) - -#include "iclassmap.h" -#include "recvproxy.h" - -class SendTable; - -// Game DLL includes -#else - -#include "sendproxy.h" - -#endif // !CLIENT_DLL - -#if defined( CLIENT_DLL ) - -#define DECLARE_NETWORKCLASS() \ - DECLARE_CLIENTCLASS() - -#define DECLARE_NETWORKCLASS_NOBASE() \ - DECLARE_CLIENTCLASS_NOBASE() - -#else - -#define DECLARE_NETWORKCLASS() \ - DECLARE_SERVERCLASS() - -#define DECLARE_NETWORKCLASS_NOBASE() \ - DECLARE_SERVERCLASS_NOBASE() - -#endif - -#if defined( CLIENT_DLL ) - -#ifndef NO_ENTITY_PREDICTION -#define DECLARE_PREDICTABLE() \ - public: \ - static typedescription_t m_PredDesc[]; \ - static datamap_t m_PredMap; \ - virtual datamap_t *GetPredDescMap( void ); \ - template friend datamap_t *PredMapInit(T *) -#else -#define DECLARE_PREDICTABLE() template friend datamap_t *PredMapInit(T *) -#endif - -#ifndef NO_ENTITY_PREDICTION -#define BEGIN_PREDICTION_DATA( className ) \ - datamap_t className::m_PredMap = { 0, 0, #className, &BaseClass::m_PredMap }; \ - datamap_t *className::GetPredDescMap( void ) { return &m_PredMap; } \ - BEGIN_PREDICTION_DATA_GUTS( className ) - -#define BEGIN_PREDICTION_DATA_NO_BASE( className ) \ - datamap_t className::m_PredMap = { 0, 0, #className, NULL }; \ - datamap_t *className::GetPredDescMap( void ) { return &m_PredMap; } \ - BEGIN_PREDICTION_DATA_GUTS( className ) - -#define BEGIN_PREDICTION_DATA_GUTS( className ) \ - template datamap_t *PredMapInit(T *); \ - template <> datamap_t *PredMapInit( className * ); \ - namespace className##_PredDataDescInit \ - { \ - datamap_t *g_PredMapHolder = PredMapInit( (className *)NULL ); /* This can/will be used for some clean up duties later */ \ - } \ - \ - template <> datamap_t *PredMapInit( className * ) \ - { \ - typedef className classNameTypedef; \ - static typedescription_t predDesc[] = \ - { \ - { FIELD_VOID,0, {0,0},0,0,0,0,0,0}, /* so you can define "empty" tables */ - -#define END_PREDICTION_DATA() \ - }; \ - \ - if ( sizeof( predDesc ) > sizeof( predDesc[0] ) ) \ - { \ - classNameTypedef::m_PredMap.dataNumFields = ARRAYSIZE( predDesc ) - 1; \ - classNameTypedef::m_PredMap.dataDesc = &predDesc[1]; \ - } \ - else \ - { \ - classNameTypedef::m_PredMap.dataNumFields = 1; \ - classNameTypedef::m_PredMap.dataDesc = predDesc; \ - } \ - return &classNameTypedef::m_PredMap; \ - } -#else -#define BEGIN_PREDICTION_DATA( className ) \ - template <> inline datamap_t *PredMapInit( className * ) \ - { \ - if ( 0 ) \ - { \ - typedef className classNameTypedef; \ - typedescription_t predDesc[] = \ - { \ - { FIELD_VOID,0, {0,0},0,0,0,0,0,0}, - -#define BEGIN_PREDICTION_DATA_NO_BASE( className ) BEGIN_PREDICTION_DATA( className ) - -#define END_PREDICTION_DATA() \ - }; \ - predDesc[0].flags = 0; /* avoid compiler warning of unused data */ \ - } \ - } -#endif - -#else - - // nothing, only client has a prediction system - #define DECLARE_PREDICTABLE() - #define BEGIN_PREDICTION_DATA( className ) - #define END_PREDICTION_DATA() - -#endif - -#if defined( CLIENT_DLL ) - -// On the client .dll this creates a mapping between a classname and -// a client side class. Probably could be templatized at some point. - -#define LINK_ENTITY_TO_CLASS( localName, className ) \ - static C_BaseEntity *C##className##Factory( void ) \ - { \ - return static_cast< C_BaseEntity * >( new className ); \ - }; \ - class C##localName##Foo \ - { \ - public: \ - C##localName##Foo( void ) \ - { \ - GetClassMap().Add( #localName, #className, sizeof( className ), \ - &C##className##Factory ); \ - } \ - }; \ - static C##localName##Foo g_C##localName##Foo; - -#define BEGIN_NETWORK_TABLE( className, tableName ) BEGIN_RECV_TABLE( className, tableName ) -#define BEGIN_NETWORK_TABLE_NOBASE( className, tableName ) BEGIN_RECV_TABLE_NOBASE( className, tableName ) - -#define END_NETWORK_TABLE END_RECV_TABLE - -#define IMPLEMENT_NETWORKCLASS_ALIASED(className, dataTable) \ - IMPLEMENT_CLIENTCLASS( C_##className, dataTable, C##className ) -#define IMPLEMENT_NETWORKCLASS(className, dataTable) \ - IMPLEMENT_CLIENTCLASS(className, dataTable, className) -#define IMPLEMENT_NETWORKCLASS_DT(className, dataTable) \ - IMPLEMENT_CLIENTCLASS_DT(className, dataTable, className) - -#else - -#define BEGIN_NETWORK_TABLE( className, tableName ) BEGIN_SEND_TABLE( className, tableName ) -#define BEGIN_NETWORK_TABLE_NOBASE( className, tableName ) BEGIN_SEND_TABLE_NOBASE( className, tableName ) - -#define END_NETWORK_TABLE END_SEND_TABLE - -#define IMPLEMENT_NETWORKCLASS_ALIASED(className, dataTable) \ - IMPLEMENT_SERVERCLASS( C##className, dataTable ) -#define IMPLEMENT_NETWORKCLASS(className, dataTable) \ - IMPLEMENT_SERVERCLASS(className, dataTable) -#define IMPLEMENT_NETWORKCLASS_DT(className, dataTable) \ - IMPLEMENT_SERVERCLASS_ST(className, dataTable) - -#endif - -// Interface used by client and server to track predictable entities -abstract_class IPredictableList -{ -public: - // Get predictables by index - virtual CBaseEntity *GetPredictable( int slot ) = 0; - // Get count of predictables - virtual int GetPredictableCount( void ) = 0; -}; - -// Expose interface to rest of .dll -extern IPredictableList *predictables; - -#endif // PREDICTABLE_ENTITY_H diff --git a/game/shared/predictableid.cpp b/game/shared/predictableid.cpp deleted file mode 100644 index 96227300a..000000000 --- a/game/shared/predictableid.cpp +++ /dev/null @@ -1,325 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "checksum_crc.h" -#include "tier1/strtools.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#if !defined( NO_ENTITY_PREDICTION ) -//----------------------------------------------------------------------------- -// Purpose: Helper class for resetting instance numbers, etc. -//----------------------------------------------------------------------------- -class CPredictableIdHelper -{ -public: - CPredictableIdHelper() - { - Reset( -1 ); - } - - void Reset( int command ) - { - m_nCurrentCommand = command; - m_nCount = 0; - memset( m_Entries, 0, sizeof( m_Entries ) ); - } - - int AddEntry( int command, int hash ) - { - // Clear list if command number changes - if ( command != m_nCurrentCommand ) - { - Reset( command ); - } - - entry *e = FindOrAddEntry( hash ); - if ( !e ) - return 0; - e->count++; - return e->count-1; - } - -private: - - enum - { - MAX_ENTRIES = 256, - }; - - struct entry - { - int hash; - int count; - }; - - entry *FindOrAddEntry( int hash ) - { - int i; - for ( i = 0; i < m_nCount; i++ ) - { - entry *e = &m_Entries[ i ]; - if ( e->hash == hash ) - return e; - } - - if ( m_nCount >= MAX_ENTRIES ) - { - // assert( 0 ); - return NULL; - } - - entry *e = &m_Entries[ m_nCount++ ]; - e->hash = hash; - e->count = 0; - return e; - } - - int m_nCurrentCommand; - int m_nCount; - entry m_Entries[ MAX_ENTRIES ]; -}; - -static CPredictableIdHelper g_Helper; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CPredictableId::CPredictableId( void ) -{ - memset( &m_PredictableID, 0, sizeof( m_PredictableID ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPredictableId::ResetInstanceCounters( void ) -{ - g_Helper.Reset( -1 ); -} - -//----------------------------------------------------------------------------- -// Purpose: Is the Id being used -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CPredictableId::IsActive( void ) const -{ - if ( *(const int *)&m_PredictableID == 0 ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : playerIndex - -//----------------------------------------------------------------------------- -void CPredictableId::SetPlayer( int playerIndex ) -{ - m_PredictableID.player = (unsigned int)playerIndex; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CPredictableId::GetPlayer( void ) const -{ - return (int)m_PredictableID.player; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CPredictableId::GetCommandNumber( void ) const -{ - return (int)m_PredictableID.command; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : commandNumber - -//----------------------------------------------------------------------------- -void CPredictableId::SetCommandNumber( int commandNumber ) -{ - m_PredictableID.command = (unsigned int)commandNumber; -} - -/* -bool CPredictableId::IsCommandNumberEqual( int testNumber ) const -{ - if ( ( testNumber & ((1<<10) - 1) ) == m_PredictableID.command ) - return true; - - return false; -} -*/ - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *classname - -// *module - -// line - -// Output : static int -//----------------------------------------------------------------------------- -static int ClassFileLineHash( const char *classname, const char *module, int line ) -{ - CRC32_t retval; - - CRC32_Init( &retval ); - - char tempbuffer[ 512 ]; - - // ACK, have to go lower case due to issues with .dsp having different cases of drive - // letters, etc.!!! - Q_strncpy( tempbuffer, classname, sizeof( tempbuffer ) ); - Q_strlower( tempbuffer ); - CRC32_ProcessBuffer( &retval, (void *)tempbuffer, Q_strlen( tempbuffer ) ); - - Q_strncpy( tempbuffer, module, sizeof( tempbuffer ) ); - Q_strlower( tempbuffer ); - CRC32_ProcessBuffer( &retval, (void *)tempbuffer, Q_strlen( tempbuffer ) ); - - CRC32_ProcessBuffer( &retval, (void *)&line, sizeof( int ) ); - - CRC32_Final( &retval ); - - return (int)retval; -} - -//----------------------------------------------------------------------------- -// Purpose: Create a predictable id of the specified parameter set -// Input : player - -// command - -// *classname - -// *module - -// line - -//----------------------------------------------------------------------------- -void CPredictableId::Init( int player, int command, const char *classname, const char *module, int line ) -{ - SetPlayer( player ); - SetCommandNumber( command ); - - m_PredictableID.hash = ClassFileLineHash( classname, module, line ); - - // Use helper to determine instance number this command - int instance = g_Helper.AddEntry( command, m_PredictableID.hash ); - - // Set appropriate instance number - SetInstanceNumber( instance ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CPredictableId::GetHash( void ) const -{ - return (int)m_PredictableID.hash; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : counter - -//----------------------------------------------------------------------------- -void CPredictableId::SetInstanceNumber( int counter ) -{ - m_PredictableID.instance = (unsigned int)counter; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CPredictableId::GetInstanceNumber( void ) const -{ - return (int)m_PredictableID.instance; -} - -// Client only -//----------------------------------------------------------------------------- -// Purpose: -// Input : ack - -//----------------------------------------------------------------------------- -void CPredictableId::SetAcknowledged( bool ack ) -{ - m_PredictableID.ack = ack ? 1 : 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CPredictableId::GetAcknowledged( void ) const -{ - return m_PredictableID.ack ? true : false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CPredictableId::GetRaw( void ) const -{ - return *(int *)&m_PredictableID; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : raw - -//----------------------------------------------------------------------------- -void CPredictableId::SetRaw( int raw ) -{ - *(int *)&m_PredictableID = raw; -} - -//----------------------------------------------------------------------------- -// Purpose: Determine if one id is == another, ignores Acknowledged state -// Input : other - -// Output : bool CPredictableId::operator -//----------------------------------------------------------------------------- -bool CPredictableId::operator ==( const CPredictableId& other ) const -{ - if ( this == &other ) - return true; - - if ( GetPlayer() != other.GetPlayer() ) - return false; - if ( GetCommandNumber() != other.GetCommandNumber() ) - return false; - if ( GetHash() != other.GetHash() ) - return false; - if ( GetInstanceNumber() != other.GetInstanceNumber() ) - return false; - return true; -} - -bool CPredictableId::operator !=( const CPredictableId& other ) const -{ - return !(*this == other); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : char const -//----------------------------------------------------------------------------- -const char *CPredictableId::Describe( void ) const -{ - static char desc[ 128 ]; - - Q_snprintf( desc, sizeof( desc ), "pl(%i) cmd(%i) hash(%i) inst(%i) ack(%s)", - GetPlayer(), - GetCommandNumber(), - GetHash(), - GetInstanceNumber() , - GetAcknowledged() ? "true" : "false" ); - - return desc; -} -#endif diff --git a/game/shared/predictableid.h b/game/shared/predictableid.h deleted file mode 100644 index f1c7ff7aa..000000000 --- a/game/shared/predictableid.h +++ /dev/null @@ -1,75 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PREDICTABLEID_H -#define PREDICTABLEID_H -#ifdef _WIN32 -#pragma once -#endif - -#if !defined( NO_ENTITY_PREDICTION ) -//----------------------------------------------------------------------------- -// Purpose: Wraps 32bit predictID to allow access and creation -//----------------------------------------------------------------------------- -class CPredictableId -{ -public: - // Construction - CPredictableId( void ); - - static void ResetInstanceCounters( void ); - - // Is the Id being used - bool IsActive( void ) const; - - // Call this to set from data - void Init( int player, int command, const char *classname, const char *module, int line ); - - // Get player index - int GetPlayer( void ) const; - // Get hash value - int GetHash( void ) const; - // Get index number - int GetInstanceNumber( void ) const; - // Get command number - int GetCommandNumber( void ) const; - - // Check command number -// bool IsCommandNumberEqual( int testNumber ) const; - - // Client only - void SetAcknowledged( bool ack ); - bool GetAcknowledged( void ) const; - - // For conversion to/from integer - int GetRaw( void ) const; - void SetRaw( int raw ); - - char const *Describe( void ) const; - - // Equality test - bool operator ==( const CPredictableId& other ) const; - bool operator !=( const CPredictableId& other ) const; -private: - void SetCommandNumber( int commandNumber ); - void SetPlayer( int playerIndex ); - void SetInstanceNumber( int counter ); - - // Encoding bits, should total 32 - struct bitfields - { - unsigned int ack : 1; // 1 - unsigned int player : 5; // 6 - unsigned int command : 10; // 16 - unsigned int hash : 12; // 28 - unsigned int instance : 4; // 32 - } m_PredictableID; -}; - -#endif - -#endif // PREDICTABLEID_H diff --git a/game/shared/predicted_viewmodel.cpp b/game/shared/predicted_viewmodel.cpp deleted file mode 100644 index a8b1941e4..000000000 --- a/game/shared/predicted_viewmodel.cpp +++ /dev/null @@ -1,71 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// -#include "cbase.h" -#include "predicted_viewmodel.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -LINK_ENTITY_TO_CLASS( predicted_viewmodel, CPredictedViewModel ); - -IMPLEMENT_NETWORKCLASS_ALIASED( PredictedViewModel, DT_PredictedViewModel ) - -BEGIN_NETWORK_TABLE( CPredictedViewModel, DT_PredictedViewModel ) -END_NETWORK_TABLE() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -#ifdef CLIENT_DLL -CPredictedViewModel::CPredictedViewModel() : m_LagAnglesHistory("CPredictedViewModel::m_LagAnglesHistory") -{ - m_vLagAngles.Init(); - m_LagAnglesHistory.Setup( &m_vLagAngles, 0 ); -} -#else -CPredictedViewModel::CPredictedViewModel() -{ -} -#endif - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CPredictedViewModel::~CPredictedViewModel() -{ -} - -#ifdef CLIENT_DLL -ConVar cl_wpn_sway_interp( "cl_wpn_sway_interp", "0.1", FCVAR_CLIENTDLL ); -ConVar cl_wpn_sway_scale( "cl_wpn_sway_scale", "1.0", FCVAR_CLIENTDLL|FCVAR_CHEAT ); -#endif - -void CPredictedViewModel::CalcViewModelLag( Vector& origin, QAngle& angles, QAngle& original_angles ) -{ - #ifdef CLIENT_DLL - // Calculate our drift - Vector forward, right, up; - AngleVectors( angles, &forward, &right, &up ); - - // Add an entry to the history. - m_vLagAngles = angles; - m_LagAnglesHistory.NoteChanged( gpGlobals->curtime, cl_wpn_sway_interp.GetFloat(), false ); - - // Interpolate back 100ms. - m_LagAnglesHistory.Interpolate( gpGlobals->curtime, cl_wpn_sway_interp.GetFloat() ); - - // Now take the 100ms angle difference and figure out how far the forward vector moved in local space. - Vector vLaggedForward; - QAngle angleDiff = m_vLagAngles - angles; - AngleVectors( -angleDiff, &vLaggedForward, 0, 0 ); - Vector vForwardDiff = Vector(1,0,0) - vLaggedForward; - - // Now offset the origin using that. - vForwardDiff *= cl_wpn_sway_scale.GetFloat(); - origin += forward*vForwardDiff.x + right*-vForwardDiff.y + up*vForwardDiff.z; - #endif -} diff --git a/game/shared/predicted_viewmodel.h b/game/shared/predicted_viewmodel.h deleted file mode 100644 index 9355431dc..000000000 --- a/game/shared/predicted_viewmodel.h +++ /dev/null @@ -1,58 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PREDICTED_VIEWMODEL_H -#define PREDICTED_VIEWMODEL_H -#ifdef _WIN32 -#pragma once -#endif - -#include "predictable_entity.h" -#include "utlvector.h" -#include "baseplayer_shared.h" -#include "shared_classnames.h" - -#if defined( CLIENT_DLL ) -#define CPredictedViewModel C_PredictedViewModel -#endif - -class CPredictedViewModel : public CBaseViewModel -{ - DECLARE_CLASS( CPredictedViewModel, CBaseViewModel ); -public: - - DECLARE_NETWORKCLASS(); - - CPredictedViewModel( void ); - virtual ~CPredictedViewModel( void ); - - virtual void CalcViewModelLag( Vector& origin, QAngle& angles, QAngle& original_angles ); - -#if defined( CLIENT_DLL ) - virtual bool ShouldPredict( void ) - { - if ( GetOwner() && GetOwner() == C_BasePlayer::GetLocalPlayer() ) - return true; - - return BaseClass::ShouldPredict(); - } -#endif - -private: - -#if defined( CLIENT_DLL ) - - // This is used to lag the angles. - CInterpolatedVar m_LagAnglesHistory; - QAngle m_vLagAngles; - - CPredictedViewModel( const CPredictedViewModel & ); // not defined, not accessible - -#endif -}; - -#endif // PREDICTED_VIEWMODEL_H diff --git a/game/shared/predictioncopy.cpp b/game/shared/predictioncopy.cpp deleted file mode 100644 index d09668e12..000000000 --- a/game/shared/predictioncopy.cpp +++ /dev/null @@ -1,2243 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "cbase.h" - -#if !defined( NO_ENTITY_PREDICTION ) - -#if defined( CLIENT_DLL ) - -#include "IGameSystem.h" -#include - -#endif -#include -#include -#include "tier0/dbg.h" -#include "tier1/strtools.h" -#include "predictioncopy.h" -#include "engine/ivmodelinfo.h" -#include "tier1/fmtstr.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// -------------------------------------------------------------- -// -// CSave -// -// -------------------------------------------------------------- -static const char *g_FieldTypes[ FIELD_TYPECOUNT ] = -{ - "FIELD_VOID", // FIELD_VOID - "FIELD_FLOAT", // FIELD_FLOAT - "FIELD_STRING", // FIELD_STRING - "FIELD_VECTOR", // FIELD_VECTOR - "FIELD_QUATERNION", // FIELD_QUATERNION - "FIELD_INTEGER", // FIELD_INTEGER - "FIELD_BOOLEAN", // FIELD_BOOLEAN - "FIELD_SHORT", // FIELD_SHORT - "FIELD_CHARACTER", // FIELD_CHARACTER - "FIELD_COLOR32", // FIELD_COLOR32 - "FIELD_EMBEDDED", // FIELD_EMBEDDED (handled specially) - "FIELD_CUSTOM", // FIELD_CUSTOM (handled specially) - "FIELD_CLASSPTR", // FIELD_CLASSPTR - "FIELD_EHANDLE", // FIELD_EHANDLE - "FIELD_EDICT", // FIELD_EDICT - "FIELD_POSITION_VECTOR",// FIELD_POSITION_VECTOR - "FIELD_TIME", // FIELD_TIME - "FIELD_TICK", // FIELD_TICK - "FIELD_MODELNAME", // FIELD_MODELNAME - "FIELD_SOUNDNAME", // FIELD_SOUNDNAME - "FIELD_INPUT", // FIELD_INPUT (uses custom type) - "FIELD_FUNCTION", // FIELD_FUNCTION - "FIELD_VMATRIX", - "FIELD_VMATRIX_WORLDSPACE", - "FIELD_MATRIX3X4_WORLDSPACE", - "FIELD_INTERVAL" // FIELD_INTERVAL - "FIELD_MODELINDEX" // FIELD_MODELINDEX -}; - -CPredictionCopy::CPredictionCopy( int type, void *dest, bool dest_packed, void const *src, bool src_packed, - bool counterrors /*= false*/, bool reporterrors /*= false*/, bool performcopy /*= true*/, - bool describefields /*= false*/, FN_FIELD_COMPARE func /*= NULL*/ ) -{ - m_nType = type; - m_pDest = dest; - m_pSrc = src; - m_nDestOffsetIndex = dest_packed ? TD_OFFSET_PACKED : TD_OFFSET_NORMAL; - m_nSrcOffsetIndex = src_packed ? TD_OFFSET_PACKED : TD_OFFSET_NORMAL; - m_bErrorCheck = counterrors; - m_bReportErrors = reporterrors; - m_bPerformCopy = performcopy; - m_bDescribeFields = describefields; - - m_pCurrentField = NULL; - m_pCurrentMap = NULL; - m_pCurrentClassName = NULL; - m_bShouldReport = false; - m_bShouldDescribe = false; - m_nErrorCount = 0; - - m_FieldCompareFunc = func; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *fmt - -// ... - -//----------------------------------------------------------------------------- -void CPredictionCopy::ReportFieldsDiffer( const char *fmt, ... ) -{ - ++m_nErrorCount; - - if ( !m_bShouldReport ) - return; - - if ( m_bDescribeFields && m_FieldCompareFunc ) - return; - - Assert( m_pCurrentMap ); - Assert( m_pCurrentClassName ); - - const char *fieldname = "empty"; - int flags = 0; - - if ( m_pCurrentField ) - { - flags = m_pCurrentField->flags; - fieldname = m_pCurrentField->fieldName ? m_pCurrentField->fieldName : "NULL"; - } - - va_list argptr; - char data[ 4096 ]; - int len; - va_start(argptr, fmt); - len = Q_vsnprintf(data, sizeof( data ), fmt, argptr); - va_end(argptr); - - if ( m_nErrorCount == 1 ) - { - Msg( "\n" ); - } - - Msg( "%03i %s::%s - %s", - m_nErrorCount, - m_pCurrentClassName, - fieldname, - data ); - - m_bShouldReport = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *fmt - -// ... - -//----------------------------------------------------------------------------- -void CPredictionCopy::DescribeFields( difftype_t dt, const char *fmt, ... ) -{ - if ( !m_bShouldDescribe ) - return; - - if ( !m_FieldCompareFunc ) - return; - - Assert( m_pCurrentMap ); - Assert( m_pCurrentClassName ); - - const char *fieldname = "empty"; - int flags = 0; - - if ( m_pCurrentField ) - { - flags = m_pCurrentField->flags; - fieldname = m_pCurrentField->fieldName ? m_pCurrentField->fieldName : "NULL"; - } - - va_list argptr; - char data[ 4096 ]; - int len; - va_start(argptr, fmt); - len = Q_vsnprintf(data, sizeof( data ), fmt, argptr); - va_end(argptr); - - bool isnetworked = ( flags & FTYPEDESC_INSENDTABLE ) ? true : false; - bool isnoterrorchecked = ( flags & FTYPEDESC_NOERRORCHECK ) ? true : false; - - ( *m_FieldCompareFunc )( - m_pCurrentClassName, - fieldname, - g_FieldTypes[ m_pCurrentField->fieldType ], - isnetworked, - isnoterrorchecked, - dt != IDENTICAL ? true : false, - dt == WITHINTOLERANCE ? true : false, - data - ); - - m_bShouldDescribe = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CPredictionCopy::CanCheck( void ) -{ - Assert( m_pCurrentField ); - - if ( m_pCurrentField->flags & FTYPEDESC_NOERRORCHECK ) - { - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : size - -// *outdata - -// *indata - -//----------------------------------------------------------------------------- -/* -void CPredictionCopy::CopyData( difftype_t dt, int size, char *outdata, const char *indata ) -{ - if ( !m_bPerformCopy ) - return; - - if ( dt == IDENTICAL ) - return; - - memcpy( outdata, indata, size ); -} -*/ - -CPredictionCopy::difftype_t CPredictionCopy::CompareData( int size, char *outdata, const char *indata ) -{ - if ( !m_bErrorCheck ) - return DIFFERS; - - if ( CanCheck() ) - { - if ( memcmp( outdata, indata, size ) ) - { - return DIFFERS; - } - else - { - // No difference, so no need to copy - return IDENTICAL; - } - } - - // Fields differ - return IDENTICAL; -} - -void CPredictionCopy::DescribeData( difftype_t dt, int size, char *outdata, const char *indata ) -{ - if ( !m_bErrorCheck ) - return; - - if ( dt == DIFFERS ) - { - ReportFieldsDiffer( "binary data differs (%i bytes)\n", size ); - } - - DescribeFields( dt, "binary (%i bytes)\n", size ); -} - -void CPredictionCopy::WatchData( difftype_t dt, int size, char *outdata, const char *indata ) -{ - if ( m_pWatchField != m_pCurrentField ) - return; - - WatchMsg( "binary (%i bytes)", size ); -} - -void CPredictionCopy::DescribeShort( difftype_t dt, short *outvalue, const short *invalue, int count ) -{ - if ( !m_bErrorCheck ) - return; - - if ( dt == DIFFERS ) - { - int i = 0; - ReportFieldsDiffer( "short differs (net %i pred %i) diff(%i)\n", (int)(invalue[i]), (int)(outvalue[i]), (int)(outvalue[i] - invalue[i]) ); - } - - DescribeFields( dt, "short (%i)\n", (int)(outvalue[0]) ); -} - -void CPredictionCopy::WatchShort( difftype_t dt, short *outvalue, const short *invalue, int count ) -{ - if ( m_pWatchField != m_pCurrentField ) - return; - - WatchMsg( "short (%i)", (int)(outvalue[0]) ); -} - -#if defined( CLIENT_DLL ) -#include "cdll_int.h" - -#endif - -void CPredictionCopy::DescribeInt( difftype_t dt, int *outvalue, const int *invalue, int count ) -{ - if ( !m_bErrorCheck ) - return; - - if ( dt == DIFFERS ) - { - int i = 0; - ReportFieldsDiffer( "int differs (net %i pred %i) diff(%i)\n", invalue[i], outvalue[i], outvalue[i] - invalue[i] ); - } - -#if defined( CLIENT_DLL ) - bool described = false; - if ( m_pCurrentField->flags & FTYPEDESC_MODELINDEX ) - { - int modelindex = outvalue[0]; - model_t const *m = modelinfo->GetModel( modelindex ); - if ( m ) - { - described = true; - char shortfile[ 512 ]; - shortfile[ 0 ] = 0; - Q_FileBase( modelinfo->GetModelName( m ), shortfile, sizeof( shortfile ) ); - - DescribeFields( dt, "integer (%i->%s)\n", outvalue[0], shortfile ); - } - } - - if ( !described ) - { - DescribeFields( dt, "integer (%i)\n", outvalue[0] ); - } -#else - DescribeFields( dt, "integer (%i)\n", outvalue[0] ); -#endif -} - -void CPredictionCopy::WatchInt( difftype_t dt, int *outvalue, const int *invalue, int count ) -{ - if ( m_pWatchField != m_pCurrentField ) - return; - -#if defined( CLIENT_DLL ) - bool described = false; - if ( m_pCurrentField->flags & FTYPEDESC_MODELINDEX ) - { - int modelindex = outvalue[0]; - model_t const *m = modelinfo->GetModel( modelindex ); - if ( m ) - { - described = true; - char shortfile[ 512 ]; - shortfile[ 0 ] = 0; - Q_FileBase( modelinfo->GetModelName( m ), shortfile, sizeof( shortfile ) ); - - WatchMsg( "integer (%i->%s)", outvalue[0], shortfile ); - } - } - - if ( !described ) - { - WatchMsg( "integer (%i)", outvalue[0] ); - } -#else - WatchMsg( "integer (%i)", outvalue[0] ); -#endif -} - -void CPredictionCopy::DescribeBool( difftype_t dt, bool *outvalue, const bool *invalue, int count ) -{ - if ( !m_bErrorCheck ) - return; - - if ( dt == DIFFERS ) - { - int i = 0; - ReportFieldsDiffer( "bool differs (net %s pred %s)\n", (invalue[i]) ? "true" : "false", (outvalue[i]) ? "true" : "false" ); - } - - DescribeFields( dt, "bool (%s)\n", (outvalue[0]) ? "true" : "false" ); -} - - -void CPredictionCopy::WatchBool( difftype_t dt, bool *outvalue, const bool *invalue, int count ) -{ - if ( m_pWatchField != m_pCurrentField ) - return; - - WatchMsg( "bool (%s)", (outvalue[0]) ? "true" : "false" ); -} - -void CPredictionCopy::DescribeFloat( difftype_t dt, float *outvalue, const float *invalue, int count ) -{ - if ( !m_bErrorCheck ) - return; - - if ( dt == DIFFERS ) - { - int i = 0; - ReportFieldsDiffer( "float differs (net %f pred %f) diff(%f)\n", invalue[ i ], outvalue[ i ], outvalue[ i ] - invalue[ i ] ); - } - - DescribeFields( dt, "float (%f)\n", outvalue[ 0 ] ); -} - -void CPredictionCopy::WatchFloat( difftype_t dt, float *outvalue, const float *invalue, int count ) -{ - if ( m_pWatchField != m_pCurrentField ) - return; - - WatchMsg( "float (%f)", outvalue[ 0 ] ); -} - -void CPredictionCopy::DescribeString( difftype_t dt, char *outstring, const char *instring ) -{ - if ( !m_bErrorCheck ) - return; - - if ( dt == DIFFERS ) - { - ReportFieldsDiffer( "string differs (net %s pred %s)\n", instring, outstring ); - } - - DescribeFields( dt, "string (%s)\n", outstring ); -} - -void CPredictionCopy::WatchString( difftype_t dt, char *outstring, const char *instring ) -{ - if ( m_pWatchField != m_pCurrentField ) - return; - - WatchMsg( "string (%s)", outstring ); -} - -void CPredictionCopy::DescribeVector( difftype_t dt, Vector& outValue, const Vector &inValue ) -{ - if ( !m_bErrorCheck ) - return; - - if ( dt == DIFFERS ) - { - Vector delta = outValue - inValue; - - ReportFieldsDiffer( "vec differs (net %f %f %f - pred %f %f %f) delta(%f %f %f)\n", - inValue.x, inValue.y, inValue.z, - outValue.x, outValue.y, outValue.z, - delta.x, delta.y, delta.z ); - } - - DescribeFields( dt, "vector (%f %f %f)\n", - outValue.x, outValue.y, outValue.z ); -} - -void CPredictionCopy::DescribeVector( difftype_t dt, Vector* outValue, const Vector *inValue, int count ) -{ - if ( !m_bErrorCheck ) - return; - - if ( dt == DIFFERS ) - { - int i = 0; - Vector delta = outValue[ i ] - inValue[ i ]; - - ReportFieldsDiffer( "vec[] differs (1st diff) (net %f %f %f - pred %f %f %f) delta(%f %f %f)\n", - inValue[i].x, inValue[i].y, inValue[i].z, - outValue[i].x, outValue[i].y, outValue[i].z, - delta.x, delta.y, delta.z ); - } - - DescribeFields( dt, "vector (%f %f %f)\n", - outValue[0].x, outValue[0].y, outValue[0].z ); -} - -void CPredictionCopy::WatchVector( difftype_t dt, Vector& outValue, const Vector &inValue ) -{ - if ( m_pWatchField != m_pCurrentField ) - return; - - WatchMsg( "vector (%f %f %f)", outValue.x, outValue.y, outValue.z ); -} - -void CPredictionCopy::WatchVector( difftype_t dt, Vector* outValue, const Vector *inValue, int count ) -{ - if ( m_pWatchField != m_pCurrentField ) - return; - - WatchMsg( "vector (%f %f %f)", outValue[0].x, outValue[0].y, outValue[0].z ); -} - - - -void CPredictionCopy::DescribeQuaternion( difftype_t dt, Quaternion& outValue, const Quaternion &inValue ) -{ - if ( !m_bErrorCheck ) - return; - - if ( dt == DIFFERS ) - { - Quaternion delta; - - for ( int i = 0; i < 4; i++ ) - { - delta[i] = outValue[i] - inValue[i]; - } - - ReportFieldsDiffer( "quaternion differs (net %f %f %f %f - pred %f %f %f %f) delta(%f %f %f %f)\n", - inValue[0], inValue[1], inValue[2], inValue[3], - outValue[0], outValue[1], outValue[2], outValue[3], - delta[0], delta[1], delta[2], delta[3] ); - } - - DescribeFields( dt, "quaternion (%f %f %f %f)\n", - outValue[0], outValue[1], outValue[2], outValue[3] ); -} - -void CPredictionCopy::DescribeQuaternion( difftype_t dt, Quaternion* outValue, const Quaternion *inValue, int count ) -{ - if ( !m_bErrorCheck ) - return; - - if ( dt == DIFFERS ) - { - int i = 0; - Quaternion delta; - - for ( int j = 0; j < 4; j++ ) - { - delta[i] = outValue[i][j] - inValue[i][j]; - } - - ReportFieldsDiffer( "quaternion[] differs (1st diff) (net %f %f %f %f - pred %f %f %f %f) delta(%f %f %f %f)\n", - inValue->x, inValue->y, inValue->z, inValue->w, - outValue->x, outValue->y, outValue->z, outValue->w, - delta.x, delta.y, delta.z, delta.w ); - } - - DescribeFields( dt, "quaternion (%f %f %f %f)\n", - outValue->x, outValue->y, outValue->z, outValue->w ); -} - -void CPredictionCopy::WatchQuaternion( difftype_t dt, Quaternion& outValue, const Quaternion &inValue ) -{ - if ( m_pWatchField != m_pCurrentField ) - return; - - WatchMsg( "quaternion (%f %f %f %f)", outValue[0], outValue[1], outValue[2], outValue[3] ); -} - -void CPredictionCopy::WatchQuaternion( difftype_t dt, Quaternion* outValue, const Quaternion *inValue, int count ) -{ - if ( m_pWatchField != m_pCurrentField ) - return; - - WatchMsg( "quaternion (%f %f %f %f)", outValue[0][0], outValue[0][1], outValue[0][2], outValue[0][3] ); -} - - - -void CPredictionCopy::DescribeEHandle( difftype_t dt, EHANDLE *outvalue, EHANDLE const *invalue, int count ) -{ - if ( !m_bErrorCheck ) - return; - - if ( dt == DIFFERS ) - { - int i = 0; - ReportFieldsDiffer( "EHandles differ (net) 0x%p (pred) 0x%p\n", (void const *)invalue[ i ].Get(), (void *)outvalue[ i ].Get() ); - } - -#if defined( CLIENT_DLL ) - C_BaseEntity *ent = outvalue[0].Get(); - if ( ent ) - { - const char *classname = ent->GetClassname(); - if ( !classname[0] ) - { - classname = typeid( *ent ).name(); - } - - DescribeFields( dt, "EHandle (0x%p->%s)", (void *)outvalue[ 0 ], classname ); - } - else - { - DescribeFields( dt, "EHandle (NULL)" ); - } - -#else - DescribeFields( dt, "EHandle (0x%p)", (void *)outvalue[ 0 ] ); -#endif - -} - -void CPredictionCopy::WatchEHandle( difftype_t dt, EHANDLE *outvalue, EHANDLE const *invalue, int count ) -{ - if ( m_pWatchField != m_pCurrentField ) - return; - -#if defined( CLIENT_DLL ) - C_BaseEntity *ent = outvalue[0].Get(); - if ( ent ) - { - const char *classname = ent->GetClassname(); - if ( !classname[0] ) - { - classname = typeid( *ent ).name(); - } - - WatchMsg( "EHandle (0x%p->%s)", (void *)outvalue[ 0 ], classname ); - } - else - { - WatchMsg( "EHandle (NULL)" ); - } - -#else - WatchMsg( "EHandle (0x%p)", (void *)outvalue[ 0 ] ); -#endif - -} - -void CPredictionCopy::CopyShort( difftype_t dt, short *outvalue, const short *invalue, int count ) -{ - if ( !m_bPerformCopy ) - return; - - if ( dt == IDENTICAL ) - return; - - CopyData( dt, sizeof(short) * count, (char *)outvalue, (const char *)invalue ); -} - -CPredictionCopy::difftype_t CPredictionCopy::CompareShort( short *outvalue, const short *invalue, int count ) -{ - if ( !m_bErrorCheck ) - return DIFFERS; - - if ( CanCheck() ) - { - for ( int i = 0; i < count; i++ ) - { - if ( outvalue[ i ] == invalue[ i ] ) - continue; - - return DIFFERS; - } - } - - return IDENTICAL; -} - - -void CPredictionCopy::CopyInt( difftype_t dt, int *outvalue, const int *invalue, int count ) -{ - if ( !m_bPerformCopy ) - return; - - if ( dt == IDENTICAL ) - return; - - CopyData( dt, sizeof(int) * count, (char *)outvalue, (const char *)invalue ); -} - -CPredictionCopy::difftype_t CPredictionCopy::CompareInt( int *outvalue, const int *invalue, int count ) -{ - if ( !m_bErrorCheck ) - return DIFFERS; - - if ( CanCheck() ) - { - for ( int i = 0; i < count; i++ ) - { - if ( outvalue[ i ] == invalue[ i ] ) - continue; - - ReportFieldsDiffer( "int differs (net %i pred %i) diff(%i)\n", invalue[i], outvalue[i], outvalue[i] - invalue[i] ); - return DIFFERS; - } - } - - return IDENTICAL; -} - -void CPredictionCopy::CopyBool( difftype_t dt, bool *outvalue, const bool *invalue, int count ) -{ - if ( !m_bPerformCopy ) - return; - - if ( dt == IDENTICAL ) - return; - - CopyData( dt, sizeof( bool ) * count, (char *)outvalue, (const char *)invalue ); -} - -CPredictionCopy::difftype_t CPredictionCopy::CompareBool( bool *outvalue, const bool *invalue, int count ) -{ - if ( !m_bErrorCheck ) - return DIFFERS; - - if ( CanCheck() ) - { - for ( int i = 0; i < count; i++ ) - { - if ( outvalue[ i ] == invalue[ i ] ) - continue; - - return DIFFERS; - } - } - - return IDENTICAL; -} - -void CPredictionCopy::CopyFloat( difftype_t dt, float *outvalue, const float *invalue, int count ) -{ - if ( !m_bPerformCopy ) - return; - - if ( dt == IDENTICAL ) - return; - - CopyData( dt, sizeof( float ) * count, (char *)outvalue, (const char *)invalue ); -} - -CPredictionCopy::difftype_t CPredictionCopy::CompareFloat( float *outvalue, const float *invalue, int count ) -{ - if ( !m_bErrorCheck ) - return DIFFERS; - - difftype_t retval = IDENTICAL; - - if ( CanCheck() ) - { - float tolerance = m_pCurrentField->fieldTolerance; - Assert( tolerance >= 0.0f ); - bool usetolerance = tolerance > 0.0f; - - for ( int i = 0; i < count; i++ ) - { - if ( outvalue[ i ] == invalue[ i ] ) - continue; - - if ( usetolerance && - ( fabs( outvalue[ i ] - invalue[ i ] ) <= tolerance ) ) - { - retval = WITHINTOLERANCE; - continue; - } - - return DIFFERS; - } - } - - return retval; -} - -void CPredictionCopy::CopyString( difftype_t dt, char *outstring, const char *instring ) -{ - if ( !m_bPerformCopy ) - return; - - if ( dt == IDENTICAL ) - return; - - CopyData( dt, Q_strlen( instring ) + 1, (char *)outstring, (const char *)instring ); -} - -CPredictionCopy::difftype_t CPredictionCopy::CompareString( char *outstring, const char *instring ) -{ - if ( !m_bErrorCheck ) - return DIFFERS; - - if ( CanCheck() ) - { - if ( Q_strcmp( outstring, instring ) ) - { - return DIFFERS; - } - } - - return IDENTICAL; -} - -void CPredictionCopy::CopyVector( difftype_t dt, Vector& outValue, const Vector &inValue ) -{ - CopyVector( dt, &outValue, &inValue, 1 ); -} - -void CPredictionCopy::CopyQuaternion( difftype_t dt, Quaternion& outValue, const Quaternion &inValue ) -{ - CopyQuaternion( dt, &outValue, &inValue, 1 ); -} - -CPredictionCopy::difftype_t CPredictionCopy::CompareVector( Vector& outValue, const Vector &inValue ) -{ - if ( !m_bErrorCheck ) - return DIFFERS; - - if ( CanCheck() ) - { - float tolerance = m_pCurrentField->fieldTolerance; - Assert( tolerance >= 0.0f ); - - if ( outValue != inValue && ( tolerance > 0.0f ) ) - { - Vector delta = outValue - inValue; - - if ( fabs( delta.x ) <= tolerance && - fabs( delta.y ) <= tolerance && - fabs( delta.z ) <= tolerance ) - { - return WITHINTOLERANCE; - } - } - - return DIFFERS; - } - - return IDENTICAL; -} - -static int QuaternionCompare (const Quaternion& q1, const Quaternion& q2 ) -{ - for ( int i = 0; i < 4; i++ ) - { - if ( q1[i] != q2[i] ) - return 0; - } - - return 1; -} - -CPredictionCopy::difftype_t CPredictionCopy::CompareQuaternion( Quaternion& outValue, const Quaternion &inValue ) -{ - if ( !m_bErrorCheck ) - return DIFFERS; - - if ( CanCheck() ) - { - float tolerance = m_pCurrentField->fieldTolerance; - Assert( tolerance >= 0.0f ); - - if ( QuaternionCompare( outValue, inValue ) == 0 - && ( tolerance > 0.0f ) ) - { - Quaternion delta; - - for ( int j = 0; j < 4; j++ ) - { - delta[j] = outValue[j] - inValue[j]; - } - - if ( fabs( delta[0] ) <= tolerance && - fabs( delta[1] ) <= tolerance && - fabs( delta[2] ) <= tolerance && - fabs( delta[3] ) <= tolerance ) - { - return WITHINTOLERANCE; - } - } - - return DIFFERS; - } - - return IDENTICAL; -} - -void CPredictionCopy::CopyVector( difftype_t dt, Vector* outValue, const Vector *inValue, int count ) -{ - if ( !m_bPerformCopy ) - return; - - if ( dt == IDENTICAL ) - return; - - CopyData( dt, sizeof( Vector ) * count, (char *)outValue, (const char *)inValue ); -} - -void CPredictionCopy::CopyQuaternion( difftype_t dt, Quaternion* outValue, const Quaternion *inValue, int count ) -{ - if ( !m_bPerformCopy ) - return; - - if ( dt == IDENTICAL ) - return; - - CopyData( dt, sizeof( Quaternion ) * count, (char *)outValue, (const char *)inValue ); -} - - -CPredictionCopy::difftype_t CPredictionCopy::CompareVector( Vector* outValue, const Vector *inValue, int count ) -{ - if ( !m_bErrorCheck ) - return DIFFERS; - - difftype_t retval = IDENTICAL; - - if ( CanCheck() ) - { - float tolerance = m_pCurrentField->fieldTolerance; - Assert( tolerance >= 0.0f ); - - for ( int i = 0; i < count; i++ ) - { - if ( outValue[ i ] == inValue[ i ] ) - continue; - - Vector delta = outValue[ i ] - inValue[ i ]; - - if ( tolerance > 0.0f ) - { - if ( fabs( delta.x ) <= tolerance && - fabs( delta.y ) <= tolerance && - fabs( delta.z ) <= tolerance ) - { - retval = WITHINTOLERANCE; - continue; - } - } - return DIFFERS; - } - } - - return retval; -} - -CPredictionCopy::difftype_t CPredictionCopy::CompareQuaternion( Quaternion* outValue, const Quaternion *inValue, int count ) -{ - if ( !m_bErrorCheck ) - return DIFFERS; - - difftype_t retval = IDENTICAL; - - if ( CanCheck() ) - { - float tolerance = m_pCurrentField->fieldTolerance; - Assert( tolerance >= 0.0f ); - - for ( int i = 0; i < count; i++ ) - { - if ( QuaternionCompare( outValue[ i ], inValue[ i ] ) ) - continue; - - Quaternion delta; - - for ( int j = 0; j < 4; j++ ) - { - delta[i] = outValue[i][j] - inValue[i][j]; - } - - if ( tolerance > 0.0f ) - { - if ( fabs( delta[0] ) <= tolerance && - fabs( delta[1] ) <= tolerance && - fabs( delta[2] ) <= tolerance && - fabs( delta[3] ) <= tolerance ) - { - retval = WITHINTOLERANCE; - continue; - } - } - return DIFFERS; - } - } - - return retval; -} - -void CPredictionCopy::CopyEHandle( difftype_t dt, EHANDLE *outvalue, EHANDLE const *invalue, int count ) -{ - if ( !m_bPerformCopy ) - return; - - if ( dt == IDENTICAL ) - return; - - for ( int i = 0; i < count; i++ ) - { - outvalue[ i ] = invalue[ i ]; - } -} - -CPredictionCopy::difftype_t CPredictionCopy::CompareEHandle( EHANDLE *outvalue, EHANDLE const *invalue, int count ) -{ - if ( !m_bErrorCheck ) - return DIFFERS; - - int i; - if ( CanCheck() ) - { - for ( i = 0; i < count; i++ ) - { - if ( outvalue[ i ].Get() == invalue[ i ].Get() ) - continue; - - return DIFFERS; - } - } - - return IDENTICAL; -} - -void CPredictionCopy::CopyFields( int chain_count, datamap_t *pRootMap, typedescription_t *pFields, int fieldCount ) -{ - int i; - int flags; - int fieldOffsetSrc; - int fieldOffsetDest; - int fieldSize; - - m_pCurrentMap = pRootMap; - if ( !m_pCurrentClassName ) - { - m_pCurrentClassName = pRootMap->dataClassName; - } - - for ( i = 0; i < fieldCount; i++ ) - { - m_pCurrentField = &pFields[ i ]; - flags = m_pCurrentField->flags; - - // Mark any subchains first - if ( m_pCurrentField->override_field != NULL ) - { - m_pCurrentField->override_field->override_count = chain_count; - } - - // Skip this field? - if ( m_pCurrentField->override_count == chain_count ) - { - continue; - } - - // Always recurse into embeddeds - if ( m_pCurrentField->fieldType != FIELD_EMBEDDED ) - { - // Don't copy fields that are private to server or client - if ( flags & FTYPEDESC_PRIVATE ) - continue; - - // For PC_NON_NETWORKED_ONLYs skip any fields that are present in the network send tables - if ( m_nType == PC_NON_NETWORKED_ONLY && ( flags & FTYPEDESC_INSENDTABLE ) ) - continue; - - // For PC_NETWORKED_ONLYs skip any fields that are not present in the network send tables - if ( m_nType == PC_NETWORKED_ONLY && !( flags & FTYPEDESC_INSENDTABLE ) ) - continue; - } - - void *pOutputData; - void const *pInputData; - - fieldOffsetDest = m_pCurrentField->fieldOffset[ m_nDestOffsetIndex ]; - fieldOffsetSrc = m_pCurrentField->fieldOffset[ m_nSrcOffsetIndex ]; - fieldSize = m_pCurrentField->fieldSize; - - pOutputData = (void *)((char *)m_pDest + fieldOffsetDest ); - pInputData = (void const *)((char *)m_pSrc + fieldOffsetSrc ); - - // Assume we can report - m_bShouldReport = m_bReportErrors; - m_bShouldDescribe = true; - - bool bShouldWatch = m_pWatchField == m_pCurrentField; - - difftype_t difftype; - - switch( m_pCurrentField->fieldType ) - { - case FIELD_EMBEDDED: - { - typedescription_t *save = m_pCurrentField; - void *saveDest = m_pDest; - void const *saveSrc = m_pSrc; - const char *saveName = m_pCurrentClassName; - - m_pCurrentClassName = m_pCurrentField->td->dataClassName; - - // FIXME: Should this be done outside the FIELD_EMBEDDED case?? - // Don't follow the pointer if we're reading from a compressed packet - m_pSrc = pInputData; - if ( ( flags & FTYPEDESC_PTR ) && (m_nSrcOffsetIndex == PC_DATA_NORMAL) ) - { - m_pSrc = *((void**)m_pSrc); - } - - m_pDest = pOutputData; - if ( ( flags & FTYPEDESC_PTR ) && (m_nDestOffsetIndex == PC_DATA_NORMAL) ) - { - m_pDest = *((void**)m_pDest); - } - - CopyFields( chain_count, pRootMap, m_pCurrentField->td->dataDesc, m_pCurrentField->td->dataNumFields ); - - m_pCurrentClassName = saveName; - m_pCurrentField = save; - m_pDest = saveDest; - m_pSrc = saveSrc; - } - break; - case FIELD_FLOAT: - { - difftype = CompareFloat( (float *)pOutputData, (float const *)pInputData, fieldSize ); - CopyFloat( difftype, (float *)pOutputData, (float const *)pInputData, fieldSize ); - if ( m_bErrorCheck && m_bShouldDescribe ) DescribeFloat( difftype, (float *)pOutputData, (float const *)pInputData, fieldSize ); - if ( bShouldWatch ) WatchFloat( difftype, (float *)pOutputData, (float const *)pInputData, fieldSize ); - } - break; - - case FIELD_TIME: - case FIELD_TICK: - Assert( 0 ); - break; - - case FIELD_STRING: - { - difftype = CompareString( (char *)pOutputData, (char const*)pInputData ); - CopyString( difftype, (char *)pOutputData, (char const*)pInputData ); - if ( m_bErrorCheck && m_bShouldDescribe ) DescribeString( difftype,(char *)pOutputData, (char const*)pInputData ); - if ( bShouldWatch ) WatchString( difftype,(char *)pOutputData, (char const*)pInputData ); - } - break; - - case FIELD_MODELINDEX: - Assert( 0 ); - break; - - case FIELD_MODELNAME: - case FIELD_SOUNDNAME: - Assert( 0 ); - break; - - case FIELD_CUSTOM: - Assert( 0 ); - break; - - case FIELD_CLASSPTR: - case FIELD_EDICT: - Assert( 0 ); - break; - - case FIELD_POSITION_VECTOR: - Assert( 0 ); - break; - - case FIELD_VECTOR: - { - difftype = CompareVector( (Vector *)pOutputData, (Vector const *)pInputData, fieldSize ); - CopyVector( difftype, (Vector *)pOutputData, (Vector const *)pInputData, fieldSize ); - if ( m_bErrorCheck && m_bShouldDescribe ) DescribeVector( difftype, (Vector *)pOutputData, (Vector const *)pInputData, fieldSize ); - if ( bShouldWatch ) WatchVector( difftype, (Vector *)pOutputData, (Vector const *)pInputData, fieldSize ); - } - break; - - case FIELD_QUATERNION: - { - difftype = CompareQuaternion( (Quaternion *)pOutputData, (Quaternion const *)pInputData, fieldSize ); - CopyQuaternion( difftype, (Quaternion *)pOutputData, (Quaternion const *)pInputData, fieldSize ); - if ( m_bErrorCheck && m_bShouldDescribe ) DescribeQuaternion( difftype, (Quaternion *)pOutputData, (Quaternion const *)pInputData, fieldSize ); - if ( bShouldWatch ) WatchQuaternion( difftype, (Quaternion *)pOutputData, (Quaternion const *)pInputData, fieldSize ); - } - break; - - case FIELD_COLOR32: - { - difftype = CompareData( 4*fieldSize, (char *)pOutputData, (const char *)pInputData ); - CopyData( difftype, 4*fieldSize, (char *)pOutputData, (const char *)pInputData ); - if ( m_bErrorCheck && m_bShouldDescribe ) DescribeData( difftype, 4*fieldSize, (char *)pOutputData, (const char *)pInputData ); - if ( bShouldWatch ) WatchData( difftype, 4*fieldSize, (char *)pOutputData, (const char *)pInputData ); - } - break; - - case FIELD_BOOLEAN: - { - difftype = CompareBool( (bool *)pOutputData, (bool const *)pInputData, fieldSize ); - CopyBool( difftype, (bool *)pOutputData, (bool const *)pInputData, fieldSize ); - if ( m_bErrorCheck && m_bShouldDescribe ) DescribeBool( difftype, (bool *)pOutputData, (bool const *)pInputData, fieldSize ); - if ( bShouldWatch ) WatchBool( difftype, (bool *)pOutputData, (bool const *)pInputData, fieldSize ); - } - break; - - case FIELD_INTEGER: - { - difftype = CompareInt( (int *)pOutputData, (int const *)pInputData, fieldSize ); - CopyInt( difftype, (int *)pOutputData, (int const *)pInputData, fieldSize ); - if ( m_bErrorCheck && m_bShouldDescribe ) DescribeInt( difftype, (int *)pOutputData, (int const *)pInputData, fieldSize ); - if ( bShouldWatch ) WatchInt( difftype, (int *)pOutputData, (int const *)pInputData, fieldSize ); - } - break; - - case FIELD_SHORT: - { - difftype = CompareShort( (short *)pOutputData, (short const *)pInputData, fieldSize ); - CopyShort( difftype, (short *)pOutputData, (short const *)pInputData, fieldSize ); - if ( m_bErrorCheck && m_bShouldDescribe ) DescribeShort( difftype, (short *)pOutputData, (short const *)pInputData, fieldSize ); - if ( bShouldWatch ) WatchShort( difftype, (short *)pOutputData, (short const *)pInputData, fieldSize ); - } - break; - - case FIELD_CHARACTER: - { - difftype = CompareData( fieldSize, ((char *)pOutputData), (const char *)pInputData ); - CopyData( difftype, fieldSize, ((char *)pOutputData), (const char *)pInputData ); - - int valOut = *((char *)pOutputData); - int valIn = *((const char *)pInputData); - - if ( m_bErrorCheck && m_bShouldDescribe ) DescribeInt( difftype, &valOut, &valIn, fieldSize ); - if ( bShouldWatch ) WatchData( difftype, fieldSize, ((char *)pOutputData), (const char *)pInputData ); - } - break; - case FIELD_EHANDLE: - { - difftype = CompareEHandle( (EHANDLE *)pOutputData, (EHANDLE const *)pInputData, fieldSize ); - CopyEHandle( difftype, (EHANDLE *)pOutputData, (EHANDLE const *)pInputData, fieldSize ); - if ( m_bErrorCheck && m_bShouldDescribe ) DescribeEHandle( difftype, (EHANDLE *)pOutputData, (EHANDLE const *)pInputData, fieldSize ); - if ( bShouldWatch ) WatchEHandle( difftype, (EHANDLE *)pOutputData, (EHANDLE const *)pInputData, fieldSize ); - } - break; - case FIELD_FUNCTION: - { - Assert( 0 ); - } - break; - case FIELD_VOID: - { - // Don't do anything, it's an empty data description - } - break; - default: - { - Warning( "Bad field type\n" ); - Assert(0); - } - break; - } - } - - m_pCurrentClassName = NULL; -} - -void CPredictionCopy::TransferData_R( int chaincount, datamap_t *dmap ) -{ - // Copy from here first, then baseclasses - CopyFields( chaincount, dmap, dmap->dataDesc, dmap->dataNumFields ); - - if ( dmap->baseMap ) - { - TransferData_R( chaincount, dmap->baseMap ); - } -} - -static int g_nChainCount = 1; - -static typedescription_t *FindFieldByName_R( const char *fieldname, datamap_t *dmap ) -{ - int c = dmap->dataNumFields; - for ( int i = 0; i < c; i++ ) - { - typedescription_t *td = &dmap->dataDesc[ i ]; - if ( td->fieldType == FIELD_VOID ) - continue; - - if ( td->fieldType == FIELD_EMBEDDED ) - { - // TODO: this will only find the first subclass with the variable of the specified name - // At some point we might want to support multiple levels of overriding automatically - typedescription_t *ret = FindFieldByName_R( fieldname, td->td ); - if ( ret ) - { - return ret; - } - } - - if ( !stricmp( td->fieldName, fieldname ) ) - { - return td; - } - } - - if ( dmap->baseMap ) - { - return FindFieldByName_R( fieldname, dmap->baseMap ); - } - return NULL; -} - -void ValidateChains_R( datamap_t *dmap ) -{ - dmap->chains_validated = true; - - int c = dmap->dataNumFields; - for ( int i = 0; i < c; i++ ) - { - typedescription_t *td = &dmap->dataDesc[ i ]; - if ( td->fieldType == FIELD_VOID ) - continue; - - if ( td->fieldType == FIELD_EMBEDDED ) - { - ValidateChains_R( td->td ); - continue; - } - - if ( !( td->flags & FTYPEDESC_OVERRIDE ) ) - continue; - - if ( dmap->baseMap ) - { - typedescription_t *basefield = FindFieldByName_R( td->fieldName, dmap->baseMap ); - if ( basefield ) - { - td->override_field = basefield; - } - } - } - - if ( dmap->baseMap ) - { - if ( !dmap->baseMap->chains_validated ) - { - ValidateChains_R( dmap->baseMap ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *fieldname - -// *dmap - -// Output : typedescription_t -//----------------------------------------------------------------------------- -typedescription_t *FindFieldByName( const char *fieldname, datamap_t *dmap ) -{ - return FindFieldByName_R( fieldname, dmap ); -} - -static ConVar pwatchent( "pwatchent", "-1", FCVAR_CHEAT, "Entity to watch for prediction system changes." ); -static ConVar pwatchvar( "pwatchvar", "", FCVAR_CHEAT, "Entity variable to watch in prediction system for changes." ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *fmt - -// ... - -//----------------------------------------------------------------------------- -void CPredictionCopy::WatchMsg( const char *fmt, ... ) -{ - Assert( m_pCurrentField && (m_pCurrentField == m_pWatchField) ); - Assert( m_pOperation ); - - va_list argptr; - char data[ 4096 ]; - int len; - va_start(argptr, fmt); - len = Q_vsnprintf(data, sizeof( data ), fmt, argptr); - va_end(argptr); - - Msg( "%i %s %s : %s\n", gpGlobals->tickcount, m_pOperation, m_pCurrentField->fieldName, data ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *operation - -// entindex - -// *dmap - -//----------------------------------------------------------------------------- -void CPredictionCopy::DetermineWatchField( const char *operation, int entindex, datamap_t *dmap ) -{ - m_pWatchField = NULL; - m_pOperation = operation; - if ( !m_pOperation || !m_pOperation[0] ) - return; - - int enttowatch = pwatchent.GetInt(); - if ( enttowatch < 0 ) - return; - - if ( entindex != enttowatch ) - return; - - // See if they specified a field - if ( pwatchvar.GetString()[0] == 0 ) - return; - - m_pWatchField = FindFieldByName( pwatchvar.GetString(), dmap ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *operation - -// entindex - -// *dmap - -// Output : int -//----------------------------------------------------------------------------- -int CPredictionCopy::TransferData( const char *operation, int entindex, datamap_t *dmap ) -{ - ++g_nChainCount; - - if ( !dmap->chains_validated ) - { - ValidateChains_R( dmap ); - } - - DetermineWatchField( operation, entindex, dmap ); - - TransferData_R( g_nChainCount, dmap ); - - return m_nErrorCount; -} - -/* -//----------------------------------------------------------------------------- -// Purpose: Simply dumps all data fields in object -//----------------------------------------------------------------------------- -class CPredictionDescribeData -{ -public: - CPredictionDescribeData( void const *src ); - - void DescribeShort( const short *invalue, int count ); - void DescribeInt( const int *invalue, int count ); - void DescribeBool( const bool *invalue, int count ); - void DescribeFloat( const float *invalue, int count ); - void DescribeData( int size, const char *indata ); - void DescribeString( const char *instring ); - void DescribeVector( const Vector &inValue ); - void DescribeVector( const Vector *inValue, int count ); - void DescribeEHandle( EHANDLE const *invalue, int count ); - - void DescribeFields( datamap_t *pMap, typedescription_t *pFields, int fieldCount ); - -private: - - void const *m_pSrc; - void Describe( const char *fmt, ... ); - - typedescription_t *m_pCurrentField; - char const *m_pCurrentClassName; - datamap_t *m_pCurrentMap; -}; -*/ - -CPredictionDescribeData::CPredictionDescribeData( void const *src, bool src_packed, FN_FIELD_DESCRIPTION func /*= 0*/ ) -{ - m_pSrc = src; - m_nSrcOffsetIndex = src_packed ? TD_OFFSET_PACKED : TD_OFFSET_NORMAL; - - m_pCurrentField = NULL; - m_pCurrentMap = NULL; - m_pCurrentClassName = NULL; - m_bShouldReport = false; - - m_FieldDescFunc = func; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *fmt - -// ... - -//----------------------------------------------------------------------------- -void CPredictionDescribeData::Describe( const char *fmt, ... ) -{ -// if ( !m_bShouldReport ) -// return; - - Assert( m_pCurrentMap ); - Assert( m_pCurrentClassName ); - - const char *fieldname = "empty"; - int flags = 0; - - if ( m_pCurrentField ) - { - flags = m_pCurrentField->flags; - fieldname = m_pCurrentField->fieldName ? m_pCurrentField->fieldName : "NULL"; - } - - va_list argptr; - char data[ 4096 ]; - int len; - va_start(argptr, fmt); - len = Q_vsnprintf(data, sizeof( data ), fmt, argptr); - va_end(argptr); - - bool isprivate = ( flags & FTYPEDESC_PRIVATE ) ? true : false; - bool isnetworked = ( flags & FTYPEDESC_INSENDTABLE ) ? true : false; - - if ( m_FieldDescFunc ) - { - (*m_FieldDescFunc)( - m_pCurrentClassName, - m_pCurrentField->fieldName, - g_FieldTypes[ m_pCurrentField->fieldType ], - isnetworked, - data ); - } - else - { - char suffix[ 128 ]; - - suffix[ 0 ] = 0; - if ( isprivate ) - { - Q_strncat( suffix, "private", sizeof( suffix ), COPY_ALL_CHARACTERS ); - } - if ( isnetworked ) - { - if ( suffix[ 0 ] ) - { - Q_strncat( suffix, " - ", sizeof( suffix ), COPY_ALL_CHARACTERS ); - } - Q_strncat( suffix, "net", sizeof( suffix ), COPY_ALL_CHARACTERS ); - } - - if ( suffix[ 0 ] ) - { - Msg( "%s::%s(%s) - %s", - m_pCurrentClassName, - fieldname, - suffix, - data ); - } - else - { - Msg( "%s::%s - %s", - m_pCurrentClassName, - fieldname, - data ); - } - } - - m_bShouldReport = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : size - -// *outdata - -// *indata - -//----------------------------------------------------------------------------- -void CPredictionDescribeData::DescribeData( int size, const char *indata ) -{ - if ( !indata ) - return; - - Describe( "binary (%i bytes)\n", size ); -} - - -void CPredictionDescribeData::DescribeShort( const short *invalue, int count ) -{ - Describe( "short (%i)\n", (int)(invalue[0]) ); -} - - -void CPredictionDescribeData::DescribeInt( const int *invalue, int count ) -{ - for ( int i = 0; i < count; ++i ) - { - Describe( "[%i] integer (%i)\n", i, invalue[i] ); - } -} - -void CPredictionDescribeData::DescribeBool( const bool *invalue, int count ) -{ - Describe( "bool (%s)\n", (invalue[0]) ? "true" : "false" ); -} - -void CPredictionDescribeData::DescribeFloat( const float *invalue, int count ) -{ - Describe( "float (%f)\n", invalue[ 0 ] ); -} - -void CPredictionDescribeData::DescribeString( const char *instring ) -{ - Describe( "string (%s)\n", instring ); -} - -void CPredictionDescribeData::DescribeVector( const Vector &inValue ) -{ - Describe( "vector (%f %f %f)\n", - inValue.x, inValue.y, inValue.z ); -} - - -void CPredictionDescribeData::DescribeVector( const Vector *inValue, int count ) -{ - Describe( "vector (%f %f %f)\n", - inValue[0].x, inValue[0].y, inValue[0].z ); -} - -void CPredictionDescribeData::DescribeQuaternion( const Quaternion &inValue ) -{ - Describe( "quaternion (%f %f %f %f)\n", - inValue[0], inValue[1], inValue[2], inValue[3] ); -} - - -void CPredictionDescribeData::DescribeQuaternion( const Quaternion *inValue, int count ) -{ - Describe( "quaternion (%f %f %f %f)\n", - inValue[0][0], inValue[0][1], inValue[0][2], inValue[0][3] ); -} - -void CPredictionDescribeData::DescribeEHandle( EHANDLE const *invalue, int count ) -{ - Describe( "EHandle (%p)\n", invalue->Get() ); -} - -void CPredictionDescribeData::DescribeFields_R( int chain_count, datamap_t *pRootMap, typedescription_t *pFields, int fieldCount ) -{ - int i; - int flags; - int fieldOffsetSrc; - int fieldSize; - - m_pCurrentMap = pRootMap; - if ( !m_pCurrentClassName ) - { - m_pCurrentClassName = pRootMap->dataClassName; - } - - for ( i = 0; i < fieldCount; i++ ) - { - m_pCurrentField = &pFields[ i ]; - flags = m_pCurrentField->flags; - - // Mark any subchains first - if ( m_pCurrentField->override_field != NULL ) - { - m_pCurrentField->override_field->override_count = chain_count; - } - - // Skip this field? - if ( m_pCurrentField->override_count == chain_count ) - { - continue; - } - - void const *pInputData; - - fieldOffsetSrc = m_pCurrentField->fieldOffset[ m_nSrcOffsetIndex ]; - fieldSize = m_pCurrentField->fieldSize; - - pInputData = (void const *)((char *)m_pSrc + fieldOffsetSrc ); - - // Assume we can report - m_bShouldReport = true; - - switch( m_pCurrentField->fieldType ) - { - case FIELD_EMBEDDED: - { - typedescription_t *save = m_pCurrentField; - void const *saveSrc = m_pSrc; - const char *saveName = m_pCurrentClassName; - - m_pCurrentClassName = m_pCurrentField->td->dataClassName; - - m_pSrc = pInputData; - if ( ( flags & FTYPEDESC_PTR ) && (m_nSrcOffsetIndex == PC_DATA_NORMAL) ) - { - m_pSrc = *((void**)m_pSrc); - } - - DescribeFields_R( chain_count, pRootMap, m_pCurrentField->td->dataDesc, m_pCurrentField->td->dataNumFields ); - - m_pCurrentClassName = saveName; - m_pCurrentField = save; - m_pSrc = saveSrc; - } - break; - case FIELD_FLOAT: - DescribeFloat( (float const *)pInputData, fieldSize ); - break; - case FIELD_TIME: - case FIELD_TICK: - Assert( 0 ); - break; - case FIELD_STRING: - DescribeString( (char const*)pInputData ); - break; - - case FIELD_MODELNAME: - case FIELD_SOUNDNAME: - Assert( 0 ); - break; - - case FIELD_MODELINDEX: - Assert( 0 ); - break; - - case FIELD_CUSTOM: - Assert( 0 ); - break; - - case FIELD_CLASSPTR: - case FIELD_EDICT: - break; - case FIELD_POSITION_VECTOR: - Assert( 0 ); - break; - case FIELD_VECTOR: - DescribeVector( (const Vector *)pInputData, fieldSize ); - break; - case FIELD_QUATERNION: - DescribeQuaternion( ( const Quaternion * )pInputData, fieldSize ); - break; - - case FIELD_COLOR32: - DescribeData( 4*fieldSize, (const char *)pInputData ); - break; - - case FIELD_BOOLEAN: - DescribeBool( (bool const *)pInputData, fieldSize ); - break; - case FIELD_INTEGER: - DescribeInt( (int const *)pInputData, fieldSize ); - break; - - case FIELD_SHORT: - DescribeShort( (short const *)pInputData, fieldSize ); - break; - - case FIELD_CHARACTER: - DescribeData( fieldSize, (const char *)pInputData ); - break; - - case FIELD_EHANDLE: - DescribeEHandle( (EHANDLE const *)pInputData, fieldSize ); - break; - case FIELD_FUNCTION: - Assert( 0 ); - break; - case FIELD_VOID: - Describe( "FIELD_VOID: empty field\n" ); - break; - default: - Warning( "Bad field type\n" ); - Assert(0); - break; - } - } - - m_pCurrentClassName = NULL; -} - -void CPredictionDescribeData::DumpDescription( datamap_t *pMap ) -{ - ++g_nChainCount; - - if ( !pMap->chains_validated ) - { - ValidateChains_R( pMap ); - } - - while ( pMap ) - { - DescribeFields_R( g_nChainCount, pMap, pMap->dataDesc, pMap->dataNumFields ); - pMap = pMap->baseMap; - } -} - -#if defined( CLIENT_DLL ) -CValueChangeTracker::CValueChangeTracker() : - m_bActive( false ), - m_bTracking( false ) -{ - Q_memset( m_OrigValueBuf, 0, sizeof( m_OrigValueBuf ) ); -} - -C_BaseEntity *CValueChangeTracker::GetEntity() -{ - return m_hEntityToTrack.Get(); -} - -void CValueChangeTracker::GetValue( char *buf, size_t bufsize ) -{ - buf[ 0 ] = 0; - - Assert( IsActive() ); - - if ( !m_hEntityToTrack.Get() ) - return; - - void const *pInputData = ( const void * )m_hEntityToTrack.Get(); - typedescription_t *td = NULL; - for ( int i = 0; i < m_FieldStack.Count(); ++i ) - { - td = m_FieldStack[ i ]; - Assert( ( i == ( m_FieldStack.Count() -1 ) ) || - ( td->fieldType & FIELD_EMBEDDED ) ); - int fieldOffsetSrc = td->fieldOffset[ TD_OFFSET_NORMAL ]; - const void *pSaveSrc = (const void *)( (char *)pInputData + fieldOffsetSrc ); - if ( ( td->flags & FTYPEDESC_PTR ) && - ( td->fieldType & FIELD_EMBEDDED ) ) - { - pInputData = *(const void **)pSaveSrc; - } - else - { - pInputData = (void const *)((char *)pSaveSrc ); - } - } - - if ( !td || !pInputData ) - return; - - int fieldType = td->fieldType; - - switch( fieldType ) - { - default: - case FIELD_EMBEDDED: - case FIELD_MODELNAME: - case FIELD_SOUNDNAME: - case FIELD_CUSTOM: - case FIELD_CLASSPTR: - case FIELD_EDICT: - case FIELD_POSITION_VECTOR: - case FIELD_VOID: - case FIELD_FUNCTION: - { - Assert( 0 ); - } - break; - case FIELD_FLOAT: - case FIELD_TIME: - Q_snprintf( buf, bufsize, "%f", *(float const *)pInputData ); - break; - case FIELD_STRING: - Q_snprintf( buf, bufsize, "%s", (char const*)pInputData ); - break; - case FIELD_VECTOR: - { - const Vector *pVec = (const Vector *)pInputData; - Q_snprintf( buf, bufsize, "%f %f %f", pVec->x, pVec->y, pVec->z ); - } - break; - case FIELD_QUATERNION: - { - const Quaternion *p = ( const Quaternion * )pInputData; - Q_snprintf( buf, bufsize, "%f %f %f %f", p->x, p->y, p->z, p->w ); - } - break; - - case FIELD_COLOR32: - { - const Color *color = ( const Color * )pInputData; - Q_snprintf( buf, bufsize, "%d %d %d %d", color->r(), color->g(), color->b(), color->a() ); - } - break; - - case FIELD_BOOLEAN: - Q_snprintf( buf, bufsize, "%s", (*(const bool *)pInputData) ? "true" : "false" ); - break; - case FIELD_INTEGER: - case FIELD_TICK: - case FIELD_MODELINDEX: - Q_snprintf( buf, bufsize, "%i", *(const int*)pInputData ); - break; - - case FIELD_SHORT: - Q_snprintf( buf, bufsize, "%i", (int)*(const short*)pInputData ); - break; - - case FIELD_CHARACTER: - Q_snprintf( buf, bufsize, "%c", *(const char *)pInputData ); - break; - - case FIELD_EHANDLE: - Q_snprintf( buf, bufsize, "eh 0x%p", (void const *)((const EHANDLE *)pInputData)->Get() ); - break; - } -} - -void CValueChangeTracker::StartTrack( char const *pchContext ) -{ - if ( !IsActive() ) - return; - - m_strContext = pchContext; - - // Grab current value into scratch buffer - GetValue( m_OrigValueBuf, sizeof( m_OrigValueBuf ) ); - - m_bTracking = true; -} - -void CValueChangeTracker::EndTrack() -{ - if ( !IsActive() ) - return; - - if ( !m_bTracking ) - return; - m_bTracking = false; - - char final[ eChangeTrackerBufSize ]; - GetValue( final, sizeof( final ) ); - - CUtlString *history = &m_History[ m_History.AddToTail() ]; - if ( Q_stricmp( final, m_OrigValueBuf ) ) - { - history->Set( CFmtStr( "+++ %-20.20s: %s (was %s)", m_strContext.String(), final, m_OrigValueBuf ) ); - } - else - { - history->Set( CFmtStr( " %-20.20s: %s", m_strContext.String(), final ) ); - } - - Msg( ":%s\n", history->String() ); -} - -void CValueChangeTracker::ClearTracking() -{ - m_bActive = false; - m_bTracking = false; - m_hEntityToTrack = NULL; - m_strFieldName = ""; - m_History.RemoveAll(); - m_FieldStack.RemoveAll(); -} - -static bool FindFieldStackByName_R( const char *fieldname, datamap_t *dmap, CUtlVector< typedescription_t * >& stack ) -{ - int c = dmap->dataNumFields; - for ( int i = 0; i < c; i++ ) - { - typedescription_t *td = &dmap->dataDesc[ i ]; - - if ( td->fieldType == FIELD_VOID ) - continue; - - stack.AddToTail( td ); - - if ( td->fieldType == FIELD_EMBEDDED ) - { - // TODO: this will only find the first subclass with the variable of the specified name - // At some point we might want to support multiple levels of overriding automatically - bool ret = FindFieldStackByName_R( fieldname, td->td, stack ); - if ( ret ) - { - return ret; - } - } - - if ( !Q_stricmp( td->fieldName, fieldname ) ) - { - return true; - } - - stack.FindAndRemove( td ); - } - - if ( dmap->baseMap ) - { - return FindFieldStackByName_R( fieldname, dmap->baseMap, stack ); - } - return false; -} - -void CValueChangeTracker::SetupTracking( C_BaseEntity *ent, char const *pchFieldName ) -{ - ClearTracking(); - - // Find the field - datamap_t *dmap = ent->GetPredDescMap(); - if ( !dmap ) - { - Msg( "No prediction datamap_t for entity %d/%s\n", ent->index, ent->GetClassname() ); - return; - } - - bool bFound = FindFieldStackByName_R( pchFieldName, dmap, m_FieldStack ); - if ( !bFound || !m_FieldStack.Count() ) - { - Msg( "No field '%s' in datamap_t for entity %d/%s\n", pchFieldName, ent->index, ent->GetClassname() ); - return; - } - - m_hEntityToTrack = ent; - m_strFieldName = pchFieldName; - m_bActive = true; -} - -void CValueChangeTracker::Reset() -{ - m_History.RemoveAll(); -} - -bool CValueChangeTracker::IsActive() const -{ - return m_bActive; -} - -void CValueChangeTracker::Spew() -{ - if ( IsActive() ) - { - for ( int i = 0 ; i < m_History.Count(); ++i ) - { - Msg( "%s\n", m_History[ i ].String() ); - } - } - - Reset(); -} - -static CValueChangeTracker g_ChangeTracker; -CValueChangeTracker *g_pChangeTracker = &g_ChangeTracker; - -CON_COMMAND_F( cl_pred_track, " : Track changes to entity index entindex, for field fieldname.", 0 ) -{ - g_pChangeTracker->ClearTracking(); - - if ( args.ArgC() != 3 ) - { - Msg( "cl_pred_track \n" ); - return; - } - - int iEntIndex = Q_atoi( args[1] ); - - C_BaseEntity *ent = cl_entitylist->GetBaseEntity( iEntIndex ); - if ( !ent ) - { - Msg( "cl_pred_track: Unknown ent index %d\n", iEntIndex ); - return; - } - - g_pChangeTracker->SetupTracking( ent, args[2] ); -} - -#endif - -#if defined( CLIENT_DLL ) && defined( COPY_CHECK_STRESSTEST ) - -class CPredictionCopyTester : public IGameSystem -{ -public: - - // Init, shutdown - virtual void Init() - { - RunTests(); - Remove( this ); - } - - virtual void Shutdown() {} - - // Level init, shutdown - virtual void LevelInit() {} - // The level is shutdown in two parts - virtual void LevelShutdownPreEntity() {} - // Entities are deleted / released here... - virtual void LevelShutdownPostEntity() {} - // end of level shutdown - - // Called before rendering - virtual void PreRender ( ) {} - - // Called after rendering - virtual void PostRender() {} - - // Gets called each frame - virtual void Update( float frametime ) {} - -private: - - void RunTests( void ); -}; - -IGameSystem* GetPredictionCopyTester( void ) -{ - static CPredictionCopyTester s_PredictionCopyTesterSystem; - return &s_PredictionCopyTesterSystem; -} - -class CCopyTesterData -{ -public: - - CCopyTesterData() - { - m_CharValue = 'a'; - m_ShortValue = (short)100; - m_IntValue = (int)100; - m_FloatValue = 1.0f; - Q_strncpy( m_szValue, "primarydata", sizeof( m_szValue ) ); - m_Vector = Vector( 100, 100, 100 ); - m_Bool = false; - m_Clr.r = m_Clr.g = m_Clr.b = m_Clr.a = 255; - - m_Ptr = (void *)0xfedcba98; - // m_hEHandle = NULL; - } - - void MakeDifferent( void ) - { - m_CharValue = 'd'; - m_ShortValue = (short)400; - m_IntValue = (int)400; - m_FloatValue = 4.0f; - Q_strncpy( m_szValue, "secondarydata", sizeof( m_szValue ) ); - m_Vector = Vector( 400, 400, 400 ); - m_Bool = true; - m_Clr.r = m_Clr.g = m_Clr.b = m_Clr.a = 1; - m_Ptr = (void *)0x00000001; - // m_hEHandle = (C_BaseEntity *)0x00000001; - } - - DECLARE_PREDICTABLE(); - - char m_CharValue; - short m_ShortValue; - int m_IntValue; - float m_FloatValue; - char m_szValue[ 128 ]; - Vector m_Vector; - bool m_Bool; - color32 m_Clr; - void *m_Ptr; -// EHANDLE m_hEHandle; - -}; - -BEGIN_PREDICTION_DATA_NO_BASE( CCopyTesterData ) - - DEFINE_FIELD( CCopyTesterData, m_CharValue, FIELD_CHARACTER ), - DEFINE_FIELD( CCopyTesterData, m_ShortValue, FIELD_SHORT ), - DEFINE_FIELD( CCopyTesterData, m_IntValue, FIELD_INTEGER ), - DEFINE_FIELD( CCopyTesterData, m_FloatValue, FIELD_FLOAT ), - DEFINE_FIELD( CCopyTesterData, m_szValue, FIELD_STRING ), - DEFINE_FIELD( CCopyTesterData, m_Vector, FIELD_VECTOR ), - DEFINE_FIELD( CCopyTesterData, m_Bool, FIELD_BOOLEAN ), - DEFINE_FIELD( CCopyTesterData, m_Clr, FIELD_COLOR32 ), -// DEFINE_FIELD( CCopyTesterData, m_hEHandle, FIELD_EHANDLE ), - -END_PREDICTION_DATA() - -class CCopyTesterData2 : public C_BaseEntity -{ - DECLARE_CLASS( CCopyTesterData2, C_BaseEntity ); - -public: - CCopyTesterData2() - { - CONSTRUCT_PREDICTABLE( CCopyTesterData2 ); - - m_CharValue = 'b'; - m_ShortValue = (short)200; - m_IntValue = (int)200; - m_FloatValue = 2.0f; - } - - void MakeDifferent( void ) - { - m_CharValue = 'e'; - m_ShortValue = (short)500; - m_IntValue = (int)500; - m_FloatValue = 5.0f; - m_FooData.MakeDifferent(); - } - - DECLARE_PREDICTABLE(); - - char m_CharValue; - short m_ShortValue; - int m_IntValue; - float m_FloatValue; - - CCopyTesterData m_FooData; -}; - -BEGIN_PREDICTION_DATA_NO_BASE( CCopyTesterData2 ) - - DEFINE_FIELD( CCopyTesterData2, m_CharValue, FIELD_CHARACTER ), - DEFINE_FIELD( CCopyTesterData2, m_ShortValue, FIELD_SHORT ), - DEFINE_PRED_TYPEDESCRIPTION( CCopyTesterData2, m_FooData, CCopyTesterData ), - DEFINE_FIELD( CCopyTesterData2, m_IntValue, FIELD_INTEGER ), - DEFINE_FIELD( CCopyTesterData2, m_FloatValue, FIELD_FLOAT ), - -END_PREDICTION_DATA() - -void CPredictionCopyTester::RunTests( void ) -{ - CCopyTesterData2 *foo1, *foo2, *foo3; - - foo1 = new CCopyTesterData2; - foo2 = new CCopyTesterData2; - foo3 = new CCopyTesterData2; - - foo2->MakeDifferent(); - - - { - Msg( "Comparing and copying == objects, should have zero diffcount\n" ); - - CPredictionCopy tester( PC_NON_NETWORKED_ONLY, foo1, false, foo3, false, true ); - int diff_count = 0; - diff_count = tester.TransferData( foo3->GetPredDescMap(), foo1->GetPredDescMap()->dataDesc, foo1->GetPredDescMap()->dataNumFields ); - - Msg( "diff_count == %i\n", diff_count ); - Assert( !diff_count ); - } - - { - Msg( "Simple compare of != objects, should spew and have non-zero diffcount\n" ); - - CPredictionCopy tester( PC_NON_NETWORKED_ONLY, foo1, false, foo2, false, true, false ); - int diff_count = 0; - diff_count = tester.TransferData( foo2->GetPredDescMap(), foo1->GetPredDescMap()->dataDesc, foo1->GetPredDescMap()->dataNumFields ); - - Msg( "diff_count == %i (should be 12)\n", diff_count ); - Assert( diff_count == 12 ); - } - - { - Msg( "Comparing and coyping same != objects, should spew and have non-zero diffcount\n" ); - - CPredictionCopy tester( PC_NON_NETWORKED_ONLY, foo1, false, foo2, false, true ); - int diff_count = 0; - diff_count = tester.TransferData( foo2->GetPredDescMap(), foo1->GetPredDescMap()->dataDesc, foo1->GetPredDescMap()->dataNumFields ); - - Msg( "diff_count == %i (should be 12)\n", diff_count ); - Assert( diff_count == 12 ); - } - - { - Msg( "Comparing and copying objects which were just made to coincide, should have zero diffcount\n" ); - - - CPredictionCopy tester( PC_NON_NETWORKED_ONLY, foo1, false, foo2, false, true ); - int diff_count = 0; - diff_count = tester.TransferData( foo2->GetPredDescMap(), foo1->GetPredDescMap()->dataDesc, foo1->GetPredDescMap()->dataNumFields ); - - Msg( "diff_count == %i\n", diff_count ); - Assert( !diff_count ); - } - - { - CPredictionDescribeData describe( foo1, false ); - describe.DumpDescription( foo1->GetPredDescMap(), foo1->GetPredDescMap()->dataDesc, foo1->GetPredDescMap()->dataNumFields ); - } - - delete foo3; - delete foo2; - delete foo1; - -} - -#endif // CLIENT_DLL -#endif // !NO_ENTITY_PREDICTION ) diff --git a/game/shared/predictioncopy.h b/game/shared/predictioncopy.h deleted file mode 100644 index fec718f15..000000000 --- a/game/shared/predictioncopy.h +++ /dev/null @@ -1,293 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PREDICTIONCOPY_H -#define PREDICTIONCOPY_H -#ifdef _WIN32 -#pragma once -#endif - -#include -#include "datamap.h" -#include "ehandle.h" -#include "tier1/utlstring.h" - -#if defined( CLIENT_DLL ) -class C_BaseEntity; -typedef CHandle EHANDLE; - -#if defined( _DEBUG ) -// #define COPY_CHECK_STRESSTEST -class IGameSystem; -IGameSystem* GetPredictionCopyTester( void ); -#endif - -#else -class CBaseEntity; -typedef CHandle EHANDLE; -#endif - -enum -{ - PC_EVERYTHING = 0, - PC_NON_NETWORKED_ONLY, - PC_NETWORKED_ONLY, -}; - -#define PC_DATA_PACKED true -#define PC_DATA_NORMAL false - -typedef void ( *FN_FIELD_COMPARE )( const char *classname, const char *fieldname, const char *fieldtype, - bool networked, bool noterrorchecked, bool differs, bool withintolerance, const char *value ); - -class CPredictionCopy -{ -public: - typedef enum - { - DIFFERS = 0, - IDENTICAL, - WITHINTOLERANCE, - } difftype_t; - - CPredictionCopy( int type, void *dest, bool dest_packed, void const *src, bool src_packed, - bool counterrors = false, bool reporterrors = false, bool performcopy = true, - bool describefields = false, FN_FIELD_COMPARE func = NULL ); - - void CopyShort( difftype_t dt, short *outvalue, const short *invalue, int count ); - void CopyInt( difftype_t dt, int *outvalue, const int *invalue, int count ); // Copy an int - void CopyBool( difftype_t dt, bool *outvalue, const bool *invalue, int count ); // Copy a bool - void CopyFloat( difftype_t dt, float *outvalue, const float *invalue, int count ); // Copy a float - void CopyString( difftype_t dt, char *outstring, const char *instring ); // Copy a null-terminated string - void CopyVector( difftype_t dt, Vector& outValue, const Vector &inValue ); // Copy a vector - void CopyVector( difftype_t dt, Vector* outValue, const Vector *inValue, int count ); // Copy a vector array - void CopyQuaternion( difftype_t dt, Quaternion& outValue, const Quaternion &inValue ); // Copy a quaternion - void CopyQuaternion( difftype_t dt, Quaternion* outValue, const Quaternion *inValue, int count ); // Copy a quaternion array - void CopyEHandle( difftype_t dt, EHANDLE *outvalue, EHANDLE const *invalue, int count ); - - void FORCEINLINE CopyData( difftype_t dt, int size, char *outdata, const char *indata ) // Copy a binary data block - { - if ( !m_bPerformCopy ) - return; - - if ( dt == IDENTICAL ) - return; - - memcpy( outdata, indata, size ); - } - - int TransferData( const char *operation, int entindex, datamap_t *dmap ); - -private: - void TransferData_R( int chaincount, datamap_t *dmap ); - - void DetermineWatchField( const char *operation, int entindex, datamap_t *dmap ); - void DumpWatchField( typedescription_t *field ); - void WatchMsg( const char *fmt, ... ); - - difftype_t CompareShort( short *outvalue, const short *invalue, int count ); - difftype_t CompareInt( int *outvalue, const int *invalue, int count ); // Compare an int - difftype_t CompareBool( bool *outvalue, const bool *invalue, int count ); // Compare a bool - difftype_t CompareFloat( float *outvalue, const float *invalue, int count ); // Compare a float - difftype_t CompareData( int size, char *outdata, const char *indata ); // Compare a binary data block - difftype_t CompareString( char *outstring, const char *instring ); // Compare a null-terminated string - difftype_t CompareVector( Vector& outValue, const Vector &inValue ); // Compare a vector - difftype_t CompareVector( Vector* outValue, const Vector *inValue, int count ); // Compare a vector array - difftype_t CompareQuaternion( Quaternion& outValue, const Quaternion &inValue ); // Compare a Quaternion - difftype_t CompareQuaternion( Quaternion* outValue, const Quaternion *inValue, int count ); // Compare a Quaternion array - difftype_t CompareEHandle( EHANDLE *outvalue, EHANDLE const *invalue, int count ); - - void DescribeShort( difftype_t dt, short *outvalue, const short *invalue, int count ); - void DescribeInt( difftype_t dt, int *outvalue, const int *invalue, int count ); // Compare an int - void DescribeBool( difftype_t dt, bool *outvalue, const bool *invalue, int count ); // Compare a bool - void DescribeFloat( difftype_t dt, float *outvalue, const float *invalue, int count ); // Compare a float - void DescribeData( difftype_t dt, int size, char *outdata, const char *indata ); // Compare a binary data block - void DescribeString( difftype_t dt, char *outstring, const char *instring ); // Compare a null-terminated string - void DescribeVector( difftype_t dt, Vector& outValue, const Vector &inValue ); // Compare a vector - void DescribeVector( difftype_t dt, Vector* outValue, const Vector *inValue, int count ); // Compare a vector array - void DescribeQuaternion( difftype_t dt, Quaternion& outValue, const Quaternion &inValue ); // Compare a Quaternion - void DescribeQuaternion( difftype_t dt, Quaternion* outValue, const Quaternion *inValue, int count ); // Compare a Quaternion array - void DescribeEHandle( difftype_t dt, EHANDLE *outvalue, EHANDLE const *invalue, int count ); - - void WatchShort( difftype_t dt, short *outvalue, const short *invalue, int count ); - void WatchInt( difftype_t dt, int *outvalue, const int *invalue, int count ); // Compare an int - void WatchBool( difftype_t dt, bool *outvalue, const bool *invalue, int count ); // Compare a bool - void WatchFloat( difftype_t dt, float *outvalue, const float *invalue, int count ); // Compare a float - void WatchData( difftype_t dt, int size, char *outdata, const char *indata ); // Compare a binary data block - void WatchString( difftype_t dt, char *outstring, const char *instring ); // Compare a null-terminated string - void WatchVector( difftype_t dt, Vector& outValue, const Vector &inValue ); // Compare a vector - void WatchVector( difftype_t dt, Vector* outValue, const Vector *inValue, int count ); // Compare a vector array - void WatchQuaternion( difftype_t dt, Quaternion& outValue, const Quaternion &inValue ); // Compare a Quaternion - void WatchQuaternion( difftype_t dt, Quaternion* outValue, const Quaternion *inValue, int count ); // Compare a Quaternion array - void WatchEHandle( difftype_t dt, EHANDLE *outvalue, EHANDLE const *invalue, int count ); - - // Report function - void ReportFieldsDiffer( const char *fmt, ... ); - void DescribeFields( difftype_t dt, const char *fmt, ... ); - - bool CanCheck( void ); - - void CopyFields( int chaincount, datamap_t *pMap, typedescription_t *pFields, int fieldCount ); - -private: - - int m_nType; - void *m_pDest; - void const *m_pSrc; - int m_nDestOffsetIndex; - int m_nSrcOffsetIndex; - - - bool m_bErrorCheck; - bool m_bReportErrors; - bool m_bDescribeFields; - typedescription_t *m_pCurrentField; - char const *m_pCurrentClassName; - datamap_t *m_pCurrentMap; - bool m_bShouldReport; - bool m_bShouldDescribe; - int m_nErrorCount; - bool m_bPerformCopy; - - FN_FIELD_COMPARE m_FieldCompareFunc; - - typedescription_t *m_pWatchField; - char const *m_pOperation; -}; - -typedef void (*FN_FIELD_DESCRIPTION)( const char *classname, const char *fieldname, const char *fieldtype, - bool networked, const char *value ); - -//----------------------------------------------------------------------------- -// Purpose: Simply dumps all data fields in object -//----------------------------------------------------------------------------- -class CPredictionDescribeData -{ -public: - CPredictionDescribeData( void const *src, bool src_packed, FN_FIELD_DESCRIPTION func = 0 ); - - void DescribeShort( const short *invalue, int count ); - void DescribeInt( const int *invalue, int count ); - void DescribeBool( const bool *invalue, int count ); - void DescribeFloat( const float *invalue, int count ); - void DescribeData( int size, const char *indata ); - void DescribeString( const char *instring ); - void DescribeVector( const Vector &inValue ); - void DescribeVector( const Vector *inValue, int count ); - void DescribeQuaternion( const Quaternion &inValue ); - void DescribeQuaternion( const Quaternion *inValue, int count ); - void DescribeEHandle( EHANDLE const *invalue, int count ); - - void DumpDescription( datamap_t *pMap ); - -private: - void DescribeFields_R( int chain_count, datamap_t *pMap, typedescription_t *pFields, int fieldCount ); - - void const *m_pSrc; - int m_nSrcOffsetIndex; - - void Describe( const char *fmt, ... ); - - typedescription_t *m_pCurrentField; - char const *m_pCurrentClassName; - datamap_t *m_pCurrentMap; - - bool m_bShouldReport; - - FN_FIELD_DESCRIPTION m_FieldDescFunc; -}; - -#if defined( CLIENT_DLL ) -class CValueChangeTracker -{ -public: - CValueChangeTracker(); - - void Reset(); - - void StartTrack( char const *pchContext ); - void EndTrack(); - - bool IsActive() const; - - void SetupTracking( C_BaseEntity *ent, char const *pchFieldName ); - void ClearTracking(); - - void Spew(); - - C_BaseEntity *GetEntity(); - -private: - - enum - { - eChangeTrackerBufSize = 128, - }; - - // Returns field size - void GetValue( char *buf, size_t bufsize ); - - bool m_bActive : 1; - bool m_bTracking : 1; - EHANDLE m_hEntityToTrack; - CUtlVector< typedescription_t * > m_FieldStack; - CUtlString m_strFieldName; - CUtlString m_strContext; - // First 128 bytes of data is all we will consider - char m_OrigValueBuf[ eChangeTrackerBufSize ]; - CUtlVector< CUtlString > m_History; -}; - -extern CValueChangeTracker *g_pChangeTracker; - -class CValueChangeTrackerScope -{ -public: - CValueChangeTrackerScope( char const *pchContext ) - { - m_bCallEndTrack = true; - g_pChangeTracker->StartTrack( pchContext ); - } - - // Only calls Start/End if passed in entity matches entity to track - CValueChangeTrackerScope( C_BaseEntity *pEntity, char const *pchContext ) - { - m_bCallEndTrack = g_pChangeTracker->GetEntity() == pEntity; - if ( m_bCallEndTrack ) - { - g_pChangeTracker->StartTrack( pchContext ); - } - } - - ~CValueChangeTrackerScope() - { - if ( m_bCallEndTrack ) - { - g_pChangeTracker->EndTrack(); - } - } -private: - - bool m_bCallEndTrack; -}; - -#if defined( _DEBUG ) -#define PREDICTION_TRACKVALUECHANGESCOPE( context ) CValueChangeTrackerScope scope( context ); -#define PREDICTION_TRACKVALUECHANGESCOPE_ENTITY( entity, context ) CValueChangeTrackerScope scope( entity, context ); -#define PREDICTION_STARTTRACKVALUE( context ) g_pChangeTracker->StartTrack( context ); -#define PREDICTION_ENDTRACKVALUE() g_pChangeTracker->EndTrack(); -#define PREDICTION_SPEWVALUECHANGES() g_pChangeTracker->Spew(); -#else -#define PREDICTION_TRACKVALUECHANGESCOPE( context ) -#define PREDICTION_TRACKVALUECHANGESCOPE_ENTITY( entity, context ) -#define PREDICTION_STARTTRACKVALUE( context ) -#define PREDICTION_ENDTRACKVALUE() -#define PREDICTION_SPEWVALUECHANGES() -#endif - -#endif // !CLIENT_DLL -#endif // PREDICTIONCOPY_H diff --git a/game/shared/props_shared.cpp b/game/shared/props_shared.cpp deleted file mode 100644 index 2a59a1ed5..000000000 --- a/game/shared/props_shared.cpp +++ /dev/null @@ -1,1628 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: static_prop - don't move, don't animate, don't do anything. -// physics_prop - move, take damage, but don't animate -// -//=============================================================================// - - -#include "cbase.h" -#include "props_shared.h" -#include "filesystem.h" -#include "animation.h" -#include -#include - -#ifdef CLIENT_DLL -#include "gamestringpool.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar sv_pushaway_clientside_size( "sv_pushaway_clientside_size", "15", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Minimum size of pushback objects" ); -ConVar props_break_max_pieces( "props_break_max_pieces", "-1", 0, "Maximum prop breakable piece count (-1 = model default)" ); -ConVar props_break_max_pieces_perframe( "props_break_max_pieces_perframe", "-1", FCVAR_REPLICATED, "Maximum prop breakable piece count per frame (-1 = model default)" ); -#ifdef GAME_DLL -extern ConVar breakable_multiplayer; -#endif // GAME_DLL - -extern bool PropBreakableCapEdictsOnCreateAll(int modelindex, IPhysicsObject *pPhysics, const breakablepropparams_t ¶ms, CBaseEntity *pEntity, int iPrecomputedBreakableCount = -1 ); -extern CBaseEntity *BreakModelCreateSingle( CBaseEntity *pOwner, breakmodel_t *pModel, const Vector &position, - const QAngle &angles, const Vector &velocity, const AngularImpulse &angVelocity, int nSkin, const breakablepropparams_t ¶ms ); - -static int nPropBreakablesPerFrameCount = 0; -static int nFrameNumber = 0; - -//============================================================================================================= -// UTILITY FUNCS -//============================================================================================================= -//----------------------------------------------------------------------------- -// Purpose: returns the axis index with the greatest size -// Input : &vec - -// Output : static int -//----------------------------------------------------------------------------- -static int GreatestAxis( const Vector &vec ) -{ - if ( vec.x > vec.y ) - { - if ( vec.x > vec.z ) - return 0; - return 2; - } - if ( vec.y > vec.z ) - return 1; - return 2; -} - -//----------------------------------------------------------------------------- -// Purpose: returns the axis index with the smallest size -// Input : &vec - -// Output : static int -//----------------------------------------------------------------------------- -static int SmallestAxis( const Vector &vec ) -{ - if ( vec.x < vec.y ) - { - if ( vec.x < vec.z ) - return 0; - return 2; - } - if ( vec.y < vec.z ) - return 1; - return 2; -} - -//----------------------------------------------------------------------------- -// Purpose: Rotates a matrix by 90 degrees in the plane of axis0/axis1 -// Input : &matrix - -// axis0 - -// axis1 - -// Output : static void -//----------------------------------------------------------------------------- -static void MatrixRot90( matrix3x4_t &matrix, int axis0, int axis1 ) -{ - Vector col0, col1; - MatrixGetColumn( matrix, axis0, col0 ); - MatrixGetColumn( matrix, axis1, col1 ); - MatrixSetColumn( col1, axis0, matrix ); - MatrixSetColumn( -col0, axis1, matrix ); -} - -//----------------------------------------------------------------------------- -// Purpose: Given two symmetric boxes, rotate the coordinate frame by the necessary -// 90 degree rotations to approximately align them -// Input : *pInOutMatrix - -// &boxExtents1 - -// &boxExtents2 - -//----------------------------------------------------------------------------- -static void AlignBoxes( matrix3x4_t *pInOutMatrix, const Vector &boxExtents1, const Vector &boxExtents2 ) -{ - int rotCount = 0; - struct - { - int axis0; - int axis1; - } rotations[2]; - Vector ext1 = boxExtents1; - Vector ext2 = boxExtents2; - - int axis0 = GreatestAxis( ext1 ); - int axis1 = GreatestAxis( ext2 ); - if ( axis0 != axis1 ) - { - rotations[rotCount].axis0 = axis0; - rotations[rotCount].axis1 = axis1; - rotCount++; - ext2[axis1] = ext2[axis0]; - } - ext1[axis0] = 0; - ext2[axis0] = 0; - - axis0 = GreatestAxis(ext1); - axis1 = GreatestAxis(ext2); - if ( axis0 != axis1 ) - { - rotations[rotCount].axis0 = axis0; - rotations[rotCount].axis1 = axis1; - rotCount++; - } - - while ( rotCount > 0 ) - { - rotCount--; - MatrixRot90( *pInOutMatrix, rotations[rotCount].axis0, rotations[rotCount].axis1 ); - } -} - -//============================================================================================================= -// PROP DATA -//============================================================================================================= -CPropData g_PropDataSystem; - -// Parsing details for each of the propdata interactions -struct propdata_interaction_s -{ - const char *pszSectionName; - const char *pszKeyName; - const char *pszValue; -}; - -#if !defined(_STATIC_LINKED) || defined(CLIENT_DLL) -propdata_interaction_s sPropdataInteractionSections[PROPINTER_NUM_INTERACTIONS] = -{ - { "physgun_interactions", "onworldimpact", "stick" }, // PROPINTER_PHYSGUN_WORLD_STICK, - { "physgun_interactions", "onfirstimpact", "break" }, // PROPINTER_PHYSGUN_FIRST_BREAK, - { "physgun_interactions", "onfirstimpact", "paintsplat" }, // PROPINTER_PHYSGUN_FIRST_PAINT, - { "physgun_interactions", "onfirstimpact", "impale" }, // PROPINTER_PHYSGUN_FIRST_IMPALE, - { "physgun_interactions", "onlaunch", "spin_none" }, // PROPINTER_PHYSGUN_LAUNCH_SPIN_NONE, - { "physgun_interactions", "onlaunch", "spin_zaxis" }, // PROPINTER_PHYSGUN_LAUNCH_SPIN_Z, - { "physgun_interactions", "onbreak", "explode_fire" }, // PROPINTER_PHYSGUN_BREAK_EXPLODE, - { "physgun_interactions", "damage", "none" }, // PROPINTER_PHYSGUN_DAMAGE_NONE, - - { "fire_interactions", "flammable", "yes" }, // PROPINTER_FIRE_FLAMMABLE, - { "fire_interactions", "explosive_resist", "yes" }, // PROPINTER_FIRE_EXPLOSIVE_RESIST, - { "fire_interactions", "ignite", "halfhealth" }, // PROPINTER_FIRE_IGNITE_HALFHEALTH, - - { "physgun_interactions", "onpickup", "create_flare" }, // PROPINTER_PHYSGUN_CREATE_FLARE, - - { "physgun_interactions", "allow_overhead", "yes" }, // PROPINTER_PHYSGUN_ALLOW_OVERHEAD, - - { "world_interactions", "onworldimpact", "bloodsplat" }, // PROPINTER_WORLD_BLOODSPLAT, -}; -#else -extern propdata_interaction_s sPropdataInteractionSections[PROPINTER_NUM_INTERACTIONS]; -#endif - -//----------------------------------------------------------------------------- -// Constructor, destructor -//----------------------------------------------------------------------------- -CPropData::CPropData( void ) : - CAutoGameSystem( "CPropData" ) -{ - m_bPropDataLoaded = false; - m_pKVPropData = NULL; -} - -//----------------------------------------------------------------------------- -// Inherited from IAutoServerSystem -//----------------------------------------------------------------------------- -void CPropData::LevelInitPreEntity( void ) -{ - m_BreakableChunks.RemoveAll(); - ParsePropDataFile(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CPropData::LevelShutdownPostEntity( void ) -{ - if ( m_pKVPropData ) - { - m_pKVPropData->deleteThis(); - m_pKVPropData = NULL; - } -} - -//----------------------------------------------------------------------------- -// Clear out the stats + their history -//----------------------------------------------------------------------------- -void CPropData::ParsePropDataFile( void ) -{ - m_pKVPropData = new KeyValues( "PropDatafile" ); - if ( !m_pKVPropData->LoadFromFile( filesystem, "scripts/propdata.txt" ) ) - { - m_pKVPropData->deleteThis(); - m_pKVPropData = NULL; - return; - } - - m_bPropDataLoaded = true; - - // Now try and parse out the breakable section - KeyValues *pBreakableSection = m_pKVPropData->FindKey( "BreakableModels" ); - if ( pBreakableSection ) - { - KeyValues *pChunkSection = pBreakableSection->GetFirstSubKey(); - while ( pChunkSection ) - { - // Create a new chunk section and add it to our list - int index = m_BreakableChunks.AddToTail(); - propdata_breakablechunk_t *pBreakableChunk = &m_BreakableChunks[index]; - pBreakableChunk->iszChunkType = AllocPooledString( pChunkSection->GetName() ); - - // Read in all the model names - KeyValues *pModelName = pChunkSection->GetFirstSubKey(); - while ( pModelName ) - { - const char *pModel = pModelName->GetName(); - string_t pooledName = AllocPooledString( pModel ); - pBreakableChunk->iszChunkModels.AddToTail( pooledName ); - CBaseEntity::PrecacheModel( STRING( pooledName ) ); - - pModelName = pModelName->GetNextKey(); - } - - pChunkSection = pChunkSection->GetNextKey(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Parse a keyvalues section into the prop -// -// pInteractionSection is a bit of jiggery-pokery to get around the unfortunate -// fact that the interaction KV sections ("physgun_interactions", "fire_interactions", etc) -// are OUTSIDE the "prop_data" KV section in the model, but may be contained WITHIN the -// specified Base's "prop_data" section (i.e. in propdata.txt) -//----------------------------------------------------------------------------- -int CPropData::ParsePropFromKV( CBaseEntity *pProp, KeyValues *pSection, KeyValues *pInteractionSection ) -{ - IBreakableWithPropData *pBreakableInterface = dynamic_cast(pProp); - if ( !pBreakableInterface ) - return PARSE_FAILED_BAD_DATA; - - if ( !pBreakableInterface ) - return PARSE_FAILED_BAD_DATA; - - int iBaseResult = PARSE_SUCCEEDED; - - // Do we have a base? - char const *pszBase = pSection->GetString( "base" ); - if ( pszBase && pszBase[0] ) - { - iBaseResult = ParsePropFromBase( pProp, pszBase ); - if ( (iBaseResult != PARSE_SUCCEEDED) && (iBaseResult != PARSE_SUCCEEDED_ALLOWED_STATIC) ) - return iBaseResult; - } - - // Allow overriding of Block LOS - int iBlockLOS = pSection->GetInt( "blockLOS", -1 ); - if ( iBlockLOS != -1 ) - { - pBreakableInterface->SetPropDataBlocksLOS( iBlockLOS != 0 ); - } - - // Set whether AI can walk on this prop - int iIsWalkable = pSection->GetInt( "AIWalkable", -1 ); - if ( iIsWalkable != -1 ) - { - pBreakableInterface->SetPropDataIsAIWalkable( iIsWalkable != 0 ); - } - - // Set custom damage table - const char *pszTableName; - if ( pBreakableInterface->GetPhysicsDamageTable() == NULL_STRING ) - { - pszTableName = pSection->GetString( "damage_table", NULL ); - } - else - { - pszTableName = pSection->GetString( "damage_table", STRING(pBreakableInterface->GetPhysicsDamageTable()) ); - } - if ( pszTableName && pszTableName[0] ) - { - pBreakableInterface->SetPhysicsDamageTable( AllocPooledString( pszTableName ) ); - } - else - { - pBreakableInterface->SetPhysicsDamageTable( NULL_STRING ); - } - - // Get multiplayer physics mode if not set by map - pBreakableInterface->SetPhysicsMode( pSection->GetInt( "physicsmode", - pBreakableInterface->GetPhysicsMode() ) ); - - const char *multiplayer_break = pSection->GetString( "multiplayer_break", NULL ); - if ( multiplayer_break ) - { - mp_break_t mode = MULTIPLAYER_BREAK_DEFAULT; - if ( FStrEq( multiplayer_break, "server" ) ) - { - mode = MULTIPLAYER_BREAK_SERVERSIDE; - } - else if ( FStrEq( multiplayer_break, "client" ) ) - { - mode = MULTIPLAYER_BREAK_CLIENTSIDE; - } - else if ( FStrEq( multiplayer_break, "both" ) ) - { - mode = MULTIPLAYER_BREAK_BOTH; - } - pBreakableInterface->SetMultiplayerBreakMode( mode ); - } - - // Get damage modifiers, but only if they're specified, because our base may have already overridden them. - pBreakableInterface->SetDmgModBullet( pSection->GetFloat( "dmg.bullets", pBreakableInterface->GetDmgModBullet() ) ); - pBreakableInterface->SetDmgModClub( pSection->GetFloat( "dmg.club", pBreakableInterface->GetDmgModClub() ) ); - pBreakableInterface->SetDmgModExplosive( pSection->GetFloat( "dmg.explosive", pBreakableInterface->GetDmgModExplosive() ) ); - - // Get the health (unless this is an override prop) - if ( !FClassnameIs( pProp, "prop_physics_override" ) && !FClassnameIs( pProp, "prop_dynamic_override" ) ) - { - pProp->SetHealth( pSection->GetInt( "health", pProp->GetHealth() ) ); - - // Explosive? - pBreakableInterface->SetExplosiveDamage( pSection->GetFloat( "explosive_damage", pBreakableInterface->GetExplosiveDamage() ) ); - pBreakableInterface->SetExplosiveRadius( pSection->GetFloat( "explosive_radius", pBreakableInterface->GetExplosiveRadius() ) ); - -#ifdef GAME_DLL - // If we now have health, we're not allowed to ignore physics damage - if ( pProp->GetHealth() ) - { - pProp->RemoveSpawnFlags( SF_PHYSPROP_DONT_TAKE_PHYSICS_DAMAGE ); - } -#endif - } - - const char *pszBreakableModel; - if ( pBreakableInterface->GetBreakableModel() == NULL_STRING ) - { - pszBreakableModel = pSection->GetString( "breakable_model", NULL ); - } - else - { - pszBreakableModel = pSection->GetString( "breakable_model", STRING(pBreakableInterface->GetBreakableModel()) ); - } - if ( pszBreakableModel && pszBreakableModel[0] ) - { - pBreakableInterface->SetBreakableModel( AllocPooledString( pszBreakableModel ) ); - } - else - { - pBreakableInterface->SetBreakableModel( NULL_STRING ); - } - pBreakableInterface->SetBreakableSkin( pSection->GetInt( "breakable_skin", pBreakableInterface->GetBreakableSkin() ) ); - pBreakableInterface->SetBreakableCount( pSection->GetInt( "breakable_count", pBreakableInterface->GetBreakableCount() ) ); - - // Calculate the maximum size of the breakables this breakable will produce - Vector vecSize = pProp->CollisionProp()->OBBSize(); - // Throw away the smallest coord - int iSmallest = SmallestAxis(vecSize); - vecSize[iSmallest] = 1; - float flVolume = vecSize.x * vecSize.y * vecSize.z; - int iMaxSize = (int)floor( flVolume / (32.0*32.0) ); - pBreakableInterface->SetMaxBreakableSize( iMaxSize ); - - // Now parse our interactions - for ( int i = 0; i < PROPINTER_NUM_INTERACTIONS; i++ ) - { - // If we hit this assert, we have too many interactions for our current storage solution to handle - Assert( i < 32 ); - - propdata_interaction_s *pInteraction = &sPropdataInteractionSections[i]; - - KeyValues *pkvCurrentInter = pInteractionSection->FindKey( pInteraction->pszSectionName ); - if ( pkvCurrentInter ) - { - char const *pszInterBase = pkvCurrentInter->GetString( pInteraction->pszKeyName ); - if ( pszInterBase && pszInterBase[0] && !stricmp( pszInterBase, pInteraction->pszValue ) ) - { - pBreakableInterface->SetInteraction( (propdata_interactions_t)i ); - } - } - } - - // If the base said we're allowed to be static, return that - if ( iBaseResult == PARSE_SUCCEEDED_ALLOWED_STATIC ) - return PARSE_SUCCEEDED_ALLOWED_STATIC; - - // Otherwise, see if our propdata says we are allowed to be static - if ( pSection->GetInt( "allowstatic", 0 ) ) - return PARSE_SUCCEEDED_ALLOWED_STATIC; - - return PARSE_SUCCEEDED; -} - -//----------------------------------------------------------------------------- -// Purpose: Fill out a prop's with base data parsed from the propdata file -//----------------------------------------------------------------------------- -int CPropData::ParsePropFromBase( CBaseEntity *pProp, const char *pszPropData ) -{ - if ( !m_bPropDataLoaded ) - return PARSE_FAILED_NO_DATA; - - IBreakableWithPropData *pBreakableInterface = dynamic_cast(pProp); - - if ( !pBreakableInterface ) - { - return PARSE_FAILED_BAD_DATA; - } - - if ( !m_pKVPropData ) - { - return PARSE_FAILED_BAD_DATA; - } - - // Find the specified propdata - KeyValues *pSection = m_pKVPropData->FindKey( pszPropData ); - if ( !pSection ) - { - Warning("%s '%s' has a base specified as '%s', but there is no matching entry in propdata.txt.\n", pProp->GetClassname(), STRING( pProp->GetModelName() ), pszPropData ); - return PARSE_FAILED_BAD_DATA; - } - - // Store off the first base data for debugging - if ( pBreakableInterface->GetBasePropData() == NULL_STRING ) - { - pBreakableInterface->SetBasePropData( AllocPooledString( pszPropData ) ); - } - - return ParsePropFromKV( pProp, pSection, pSection ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const char *CPropData::GetRandomChunkModel( const char *pszBreakableSection, int iMaxSize ) -{ - if ( !m_bPropDataLoaded ) - return NULL; - - // Find the right section - int iCount = m_BreakableChunks.Count(); - int i; - for ( i = 0; i < iCount; i++ ) - { - if ( !Q_strncmp( STRING(m_BreakableChunks[i].iszChunkType), pszBreakableSection, strlen(pszBreakableSection) ) ) - break; - } - if ( i == iCount ) - return NULL; - - // Now pick a random one and return it - int iRandom; - if ( iMaxSize == -1 ) - { - iRandom = RandomInt( 0, m_BreakableChunks[i].iszChunkModels.Count()-1 ); - } - else - { - // Don't pick anything over the specified size - iRandom = RandomInt( 0, MIN(iMaxSize, m_BreakableChunks[i].iszChunkModels.Count()-1) ); - } - - return STRING(m_BreakableChunks[i].iszChunkModels[iRandom]); -} - - -// ensure that a model name from a qc file is properly formatted -static const char *FixupModelName( char *pOut, int sizeOut, const char *pModelNameIn ) -{ - char tmp[1024]; - - Q_strncpy( tmp, pModelNameIn, sizeof(tmp) ); - if ( Q_strnicmp( tmp, "models/", 7 ) ) - { - Q_snprintf( pOut, sizeOut, "models/%s" , tmp ); - } - else - { - Q_strncpy( pOut, tmp, sizeOut); - } - int len = Q_strlen(pOut); - if ( len < 4 || Q_stricmp( pOut + (len-4), ".mdl" ) ) - { - Q_strncat( pOut, ".mdl", sizeOut, COPY_ALL_CHARACTERS ); - } - - return pOut; -} - - -//----------------------------------------------------------------------------- -// breakable prop functions -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -// list of models to break into -class CBreakParser : public IVPhysicsKeyHandler -{ -public: - CBreakParser( float defaultBurstScale, int defaultCollisionGroup ) - : m_defaultCollisionGroup(defaultCollisionGroup), m_defaultBurstScale(defaultBurstScale) {} - - void ParseModelName( breakmodel_t *pModel, const char *pValue ) - { - FixupModelName( pModel->modelName, sizeof(pModel->modelName), pValue ); - } - virtual void ParseKeyValue( void *pData, const char *pKey, const char *pValue ) - { - breakmodel_t *pModel = (breakmodel_t *)pData; - if ( !strcmpi( pKey, "model" ) ) - { - ParseModelName( pModel, pValue ); - } - else if (!strcmpi( pKey, "ragdoll" ) ) - { - ParseModelName( pModel, pValue ); - pModel->isRagdoll = true; - } - else if (!strcmpi( pKey, "motiondisabled" ) ) - { - pModel->isMotionDisabled = true; - } - else if ( !strcmpi( pKey, "offset" ) ) - { - UTIL_StringToVector( pModel->offset.Base(), pValue ); - } - else if ( !strcmpi( pKey, "health" ) ) - { - pModel->health = atof(pValue); - } - else if ( !strcmpi( pKey, "fadetime" ) ) - { - pModel->fadeTime = atof(pValue); - if ( !m_wroteCollisionGroup ) - { - pModel->collisionGroup = COLLISION_GROUP_DEBRIS; - } - } - else if ( !strcmpi( pKey, "fademindist" ) ) - { - pModel->fadeMinDist = atof(pValue); - } - else if ( !strcmpi( pKey, "fademaxdist" ) ) - { - pModel->fadeMaxDist = atof(pValue); - } - else if ( !strcmpi( pKey, "debris" ) ) - { - pModel->collisionGroup = atoi(pValue) > 0 ? COLLISION_GROUP_DEBRIS : COLLISION_GROUP_INTERACTIVE; - m_wroteCollisionGroup = true; - } - else if ( !strcmpi( pKey, "burst" ) ) - { - pModel->burstScale = atof( pValue ); - } - else if ( !strcmpi( pKey, "placementbone" ) ) - { - Q_strncpy( pModel->placementName, pValue, sizeof(pModel->placementName) ); - pModel->placementIsBone = true; - } - else if ( !strcmpi( pKey, "placementattachment" ) ) - { - Q_strncpy( pModel->placementName, pValue, sizeof(pModel->placementName) ); - pModel->placementIsBone = false; - } - else if ( !strcmpi( pKey, "multiplayer_break" ) ) - { - if ( FStrEq( pValue, "server" ) ) - { - pModel->mpBreakMode = MULTIPLAYER_BREAK_SERVERSIDE; - } - else if ( FStrEq( pValue, "client" ) ) - { - pModel->mpBreakMode = MULTIPLAYER_BREAK_CLIENTSIDE; - } - } - } - virtual void SetDefaults( void *pData ) - { - breakmodel_t *pModel = (breakmodel_t *)pData; - pModel->modelName[0] = 0; - pModel->offset = vec3_origin; - pModel->health = 1; - pModel->fadeTime = 20.0f; - pModel->fadeMinDist = 0.0f; - pModel->fadeMaxDist = 0.0f; - pModel->burstScale = m_defaultBurstScale; - pModel->collisionGroup = m_defaultCollisionGroup; - pModel->isRagdoll = false; - pModel->isMotionDisabled = false; - pModel->placementName[0] = 0; - pModel->placementIsBone = false; - pModel->mpBreakMode = MULTIPLAYER_BREAK_DEFAULT; - m_wroteCollisionGroup = false; - } - -private: - int m_defaultCollisionGroup; - float m_defaultBurstScale; - bool m_wroteCollisionGroup; -}; - -void BreakModelList( CUtlVector &list, int modelindex, float defBurstScale, int defCollisionGroup ) -{ - vcollide_t *pCollide = modelinfo->GetVCollide( modelindex ); - if ( !pCollide ) - return; - - IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pCollide->pKeyValues ); - while ( !pParse->Finished() ) - { - CBreakParser breakParser( defBurstScale, defCollisionGroup ); - - const char *pBlock = pParse->GetCurrentBlockName(); - if ( !strcmpi( pBlock, "break" ) ) - { - int index = list.AddToTail(); - breakmodel_t &breakModel = list[index]; - pParse->ParseCustom( &breakModel, &breakParser ); - } - else - { - pParse->SkipBlock(); - } - } - physcollision->VPhysicsKeyParserDestroy( pParse ); -} - -#if !defined(_STATIC_LINKED) || defined(CLIENT_DLL) -int GetAutoMultiplayerPhysicsMode( Vector size, float mass ) -{ - float volume = size.x * size.y * size.z; - - float minsize = sv_pushaway_clientside_size.GetFloat(); - - // if it's too small, client side only - if ( volume < (minsize*minsize*minsize) ) - return PHYSICS_MULTIPLAYER_CLIENTSIDE; - - // if it's too light, no player pushback - if ( mass < 8.0 ) - return PHYSICS_MULTIPLAYER_NON_SOLID; - - // full pushbackmode - return PHYSICS_MULTIPLAYER_SOLID; -} -#else -extern int GetAutoMultiplayerPhysicsMode( Vector size, float mass ); -#endif - -//----------------------------------------------------------------------------- -// Purpose: Returns a string describing a real-world equivalent mass. -// Input : flMass - mass in kg -//----------------------------------------------------------------------------- -#if !defined(_STATIC_LINKED) || defined(CLIENT_DLL) -const char *GetMassEquivalent(float flMass) -{ - static struct - { - float flMass; - const char *sz; - } masstext[] = - { - { 5e-6, "snowflake" }, - { 2.5e-3, "ping-pong ball" }, - { 5e-3, "penny" }, - { 0.05, "golf ball" }, - { 0.17, "billard ball" }, - { 2, "bag of sugar" }, - { 7, "male cat" }, - { 10, "bowling ball" }, - { 30, "dog" }, - { 60, "cheetah" }, - { 90, "adult male human" }, - { 250, "refrigerator" }, - { 600, "race horse" }, - { 1000, "small car" }, - { 1650, "medium car" }, - { 2500, "large car" }, - { 6000, "t-rex" }, - { 7200, "elephant" }, - { 8e4, "space shuttle" }, - { 7e5, "locomotive" }, - { 9.2e6, "Eiffel tower" }, - { 6e24, "the Earth" }, - { 7e24, "really freaking heavy" }, - }; - - for (size_t i = 0; i < sizeof(masstext) / sizeof(masstext[0]) - 1; i++) - { - if (flMass < masstext[i].flMass) - { - return masstext[i].sz; - } - } - - return masstext[ sizeof(masstext) / sizeof(masstext[0]) - 1 ].sz; -} -#else -extern const char *GetMassEquivalent(float flMass); -#endif - -#ifdef GAME_DLL -//========================================================= -//========================================================= -class CGameGibManager : public CBaseEntity -{ - DECLARE_CLASS( CGameGibManager, CBaseEntity ); - DECLARE_DATADESC(); - -public: - - CGameGibManager() : m_iCurrentMaxPieces(-1), m_iMaxPieces(-1), m_iMaxPiecesDX8(-1) {} - - void Activate( void ); - void AddGibToLRU( CBaseAnimating *pEntity ); - - inline bool AllowedToSpawnGib( void ); - -private: - - void UpdateMaxPieces(); - - void InputSetMaxPieces( inputdata_t &inputdata ); - void InputSetMaxPiecesDX8( inputdata_t &inputdata ); - - typedef CHandle CGibHandle; - CUtlLinkedList< CGibHandle > m_LRU; - - bool m_bAllowNewGibs; - - int m_iDXLevel; - int m_iCurrentMaxPieces; - int m_iMaxPieces; - int m_iMaxPiecesDX8; - int m_iLastFrame; -}; - -BEGIN_DATADESC( CGameGibManager ) - // Silence perfidous classcheck! - //DEFINE_FIELD( m_iCurrentMaxPieces, FIELD_INTEGER ), - //DEFINE_FIELD( m_iLastFrame, FIELD_INTEGER ), - //DEFINE_FIELD( m_iDXLevel, FIELD_INTEGER ), - DEFINE_KEYFIELD( m_iMaxPieces, FIELD_INTEGER, "maxpieces" ), - DEFINE_KEYFIELD( m_iMaxPiecesDX8, FIELD_INTEGER, "maxpiecesdx8" ), - DEFINE_KEYFIELD( m_bAllowNewGibs, FIELD_BOOLEAN, "allownewgibs" ), - - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetMaxPieces", InputSetMaxPieces ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetMaxPiecesDX8", InputSetMaxPiecesDX8 ), -END_DATADESC() - -LINK_ENTITY_TO_CLASS( game_gib_manager, CGameGibManager ); - - -void CGameGibManager::Activate( void ) -{ - m_LRU.Purge(); - - // Cache off the DX level for use later. - ConVarRef mat_dxlevel( "mat_dxlevel" ); - m_iDXLevel = mat_dxlevel.GetInt(); - - UpdateMaxPieces(); - - BaseClass::Activate(); -} - - -void CGameGibManager::UpdateMaxPieces() -{ - // If we're running DX8, use the DX8 gib limit if set. - if ( ( m_iDXLevel < 90 ) && ( m_iMaxPiecesDX8 >= 0 ) ) - { - m_iCurrentMaxPieces = m_iMaxPiecesDX8; - } - else - { - m_iCurrentMaxPieces = m_iMaxPieces; - } -} - - -bool CGameGibManager::AllowedToSpawnGib( void ) -{ - if ( m_bAllowNewGibs ) - return true; - - // We're not tracking gibs at the moment - if ( m_iCurrentMaxPieces < 0 ) - return true; - - if ( m_iCurrentMaxPieces == 0 ) - return false; - - if ( m_iLastFrame == gpGlobals->framecount ) - { - if ( m_LRU.Count() >= m_iCurrentMaxPieces ) - { - return false; - } - } - - return true; -} - -void CGameGibManager::InputSetMaxPieces( inputdata_t &inputdata ) -{ - m_iMaxPieces = inputdata.value.Int(); - UpdateMaxPieces(); -} - -void CGameGibManager::InputSetMaxPiecesDX8( inputdata_t &inputdata ) -{ - m_iMaxPiecesDX8 = inputdata.value.Int(); - UpdateMaxPieces(); -} - -void CGameGibManager::AddGibToLRU( CBaseAnimating *pEntity ) -{ - int i, next; - - if ( pEntity == NULL ) - return; - - //Find stale gibs. - for ( i = m_LRU.Head(); i < m_LRU.InvalidIndex(); i = next ) - { - next = m_LRU.Next(i); - - if ( m_LRU[i].Get() == NULL ) - { - m_LRU.Remove(i); - } - } - - // We're not tracking gibs at the moment - if ( m_iCurrentMaxPieces <= 0 ) - return; - - while ( m_LRU.Count() >= m_iCurrentMaxPieces ) - { - i = m_LRU.Head(); - - //TODO: Make this fade out instead of pop. - UTIL_Remove( m_LRU[i] ); - m_LRU.Remove(i); - } - - m_LRU.AddToTail( pEntity ); - m_iLastFrame = gpGlobals->framecount; -} - -EHANDLE g_hGameGibManager; - -CGameGibManager *GetGibManager( void ) -{ -#ifndef HL2_EPISODIC - return NULL; -#endif - - if ( g_hGameGibManager == NULL ) - { - g_hGameGibManager = (CGameGibManager *)gEntList.FindEntityByClassname( NULL, "game_gib_manager" ); - } - - return (CGameGibManager *)g_hGameGibManager.Get(); -} - -#endif - -void PropBreakableCreateAll( int modelindex, IPhysicsObject *pPhysics, const breakablepropparams_t ¶ms, CBaseEntity *pEntity, int iPrecomputedBreakableCount, bool bIgnoreGibLimit, bool defaultLocation ) -{ - // Check for prop breakable count reset. - int nPropCount = props_break_max_pieces_perframe.GetInt(); - if ( nPropCount != -1 ) - { - if ( nFrameNumber != gpGlobals->framecount ) - { - nPropBreakablesPerFrameCount = 0; - nFrameNumber = gpGlobals->framecount; - } - - // Check for max breakable count for the frame. - if ( nPropBreakablesPerFrameCount >= nPropCount ) - return; - } - - int iMaxBreakCount = bIgnoreGibLimit ? -1 : props_break_max_pieces.GetInt(); - if ( iMaxBreakCount != -1 ) - { - if ( iPrecomputedBreakableCount != -1 ) - { - iPrecomputedBreakableCount = MIN( iMaxBreakCount, iPrecomputedBreakableCount ); - } - else - { - iPrecomputedBreakableCount = iMaxBreakCount; - } - } - -#ifdef GAME_DLL - // On server limit break model creation - if ( !PropBreakableCapEdictsOnCreateAll(modelindex, pPhysics, params, pEntity, iPrecomputedBreakableCount ) ) - { - DevMsg( "Failed to create PropBreakable: would exceed MAX_EDICTS\n" ); - return; - } -#endif - - vcollide_t *pCollide = modelinfo->GetVCollide( modelindex ); - if ( !pCollide ) - return; - - int nSkin = 0; - CBaseEntity *pOwnerEntity = pEntity; - CBaseAnimating *pOwnerAnim = NULL; - if ( pPhysics ) - { - pOwnerEntity = static_cast(pPhysics->GetGameData()); - } - if ( pOwnerEntity ) - { - pOwnerAnim = pOwnerEntity->GetBaseAnimating(); - if ( pOwnerAnim ) - { - nSkin = pOwnerAnim->m_nSkin; - } - } - matrix3x4_t localToWorld; - - CStudioHdr studioHdr; - const model_t *model = modelinfo->GetModel( modelindex ); - if ( model ) - { - studioHdr.Init( modelinfo->GetStudiomodel( model ) ); - } - - Vector parentOrigin = vec3_origin; - int parentAttachment = Studio_FindAttachment( &studioHdr, "placementOrigin" ) + 1; - if ( parentAttachment > 0 ) - { - GetAttachmentLocalSpace( &studioHdr, parentAttachment-1, localToWorld ); - MatrixGetColumn( localToWorld, 3, parentOrigin ); - } - else - { - AngleMatrix( vec3_angle, localToWorld ); - } - - CUtlVector list; - - BreakModelList( list, modelindex, params.defBurstScale, params.defCollisionGroup ); - - if ( list.Count() ) - { - for ( int i = 0; i < list.Count(); i++ ) - { - int modelIndex = modelinfo->GetModelIndex( list[i].modelName ); - if ( modelIndex <= 0 ) - continue; - - // Skip multiplayer pieces that should be spawning on the other dll -#ifdef GAME_DLL - if ( gpGlobals->maxClients > 1 && breakable_multiplayer.GetBool() ) -#else - if ( gpGlobals->maxClients > 1 ) -#endif - { -#ifdef GAME_DLL - if ( list[i].mpBreakMode == MULTIPLAYER_BREAK_CLIENTSIDE ) - continue; -#else - if ( list[i].mpBreakMode == MULTIPLAYER_BREAK_SERVERSIDE ) - continue; -#endif - - if ( !defaultLocation && list[i].mpBreakMode == MULTIPLAYER_BREAK_DEFAULT ) - continue; - } - - if ( ( nPropCount != -1 ) && ( nPropBreakablesPerFrameCount > nPropCount ) ) - break; - - if ( ( iPrecomputedBreakableCount != -1 ) && ( i >= iPrecomputedBreakableCount ) ) - break; - - matrix3x4_t matrix; - AngleMatrix( params.angles, params.origin, matrix ); - - CStudioHdr studioHdr; - const model_t *model = modelinfo->GetModel( modelIndex ); - if ( model ) - { - studioHdr.Init( modelinfo->GetStudiomodel( model ) ); - } - - // Increment the number of breakable props this frame. - ++nPropBreakablesPerFrameCount; - - Vector position = vec3_origin; - QAngle angles = params.angles; - if ( pOwnerAnim && list[i].placementName[0] ) - { - if ( list[i].placementIsBone ) - { - int boneIndex = pOwnerAnim->LookupBone( list[i].placementName ); - if ( boneIndex >= 0 ) - { - pOwnerAnim->GetBonePosition( boneIndex, position, angles ); - AngleMatrix( angles, position, matrix ); - } - } - else - { - int attachmentIndex = Studio_FindAttachment( &studioHdr, list[i].placementName ) + 1; - if ( attachmentIndex > 0 ) - { - pOwnerAnim->GetAttachment( attachmentIndex, matrix ); - MatrixAngles( matrix, angles ); - } - } - } - else - { - int placementIndex = Studio_FindAttachment( &studioHdr, "placementOrigin" ) + 1; - Vector placementOrigin = parentOrigin; - if ( placementIndex > 0 ) - { - GetAttachmentLocalSpace( &studioHdr, placementIndex-1, localToWorld ); - MatrixGetColumn( localToWorld, 3, placementOrigin ); - placementOrigin -= parentOrigin; - } - - VectorTransform( list[i].offset - placementOrigin, matrix, position ); - } - Vector objectVelocity = params.velocity; - - if (pPhysics) - { - pPhysics->GetVelocityAtPoint( position, &objectVelocity ); - } - - int nActualSkin = nSkin; - if ( nActualSkin > studioHdr.numskinfamilies() ) - nActualSkin = 0; - - CBaseEntity *pBreakable = NULL; - -#ifdef GAME_DLL - if ( GetGibManager() == NULL || GetGibManager()->AllowedToSpawnGib() ) -#endif - { - pBreakable = BreakModelCreateSingle( pOwnerEntity, &list[i], position, angles, objectVelocity, params.angularVelocity, nActualSkin, params ); - } - - if ( pBreakable ) - { -#ifdef GAME_DLL - if ( GetGibManager() ) - { - GetGibManager()->AddGibToLRU( pBreakable->GetBaseAnimating() ); - } -#endif - if ( pOwnerEntity && pOwnerEntity->IsEffectActive( EF_NOSHADOW ) ) - { - pBreakable->AddEffects( EF_NOSHADOW ); - } - - // If burst scale is set, this piece should 'burst' away from - // the origin in addition to travelling in the wished velocity. - if ( list[i].burstScale != 0.0 ) - { - Vector vecBurstDir = position - params.origin; - - // If $autocenter wasn't used, try the center of the piece - if ( vecBurstDir == vec3_origin ) - { - vecBurstDir = pBreakable->WorldSpaceCenter() - params.origin; - } - - VectorNormalize( vecBurstDir ); - - pBreakable->ApplyAbsVelocityImpulse( vecBurstDir * list[i].burstScale ); - } - - // If this piece is supposed to be motion disabled, disable it - if ( list[i].isMotionDisabled ) - { - IPhysicsObject *pPhysicsObject = pBreakable->VPhysicsGetObject(); - if ( pPhysicsObject != NULL ) - { - pPhysicsObject->EnableMotion( false ); - } - } - } - } - } - // Then see if the propdata specifies any breakable pieces - else if ( pEntity ) - { - IBreakableWithPropData *pBreakableInterface = dynamic_cast(pEntity); - if ( pBreakableInterface && pBreakableInterface->GetBreakableModel() != NULL_STRING && pBreakableInterface->GetBreakableCount() ) - { - breakmodel_t breakModel; - - for ( int i = 0; i < pBreakableInterface->GetBreakableCount(); i++ ) - { - if ( ( iPrecomputedBreakableCount != -1 ) && ( i >= iPrecomputedBreakableCount ) ) - break; - - Q_strncpy( breakModel.modelName, g_PropDataSystem.GetRandomChunkModel(STRING(pBreakableInterface->GetBreakableModel()), pBreakableInterface->GetMaxBreakableSize()), sizeof(breakModel.modelName) ); - - breakModel.health = 1; - breakModel.fadeTime = RandomFloat(5,10); - breakModel.fadeMinDist = 0.0f; - breakModel.fadeMaxDist = 0.0f; - breakModel.burstScale = params.defBurstScale; - breakModel.collisionGroup = COLLISION_GROUP_DEBRIS; - breakModel.isRagdoll = false; - breakModel.isMotionDisabled = false; - breakModel.placementName[0] = 0; - breakModel.placementIsBone = false; - - Vector vecObbSize = pEntity->CollisionProp()->OBBSize(); - - // Find a random point on the plane of the original's two largest axis - int smallestAxis = SmallestAxis( vecObbSize ); - Vector vecMins(0,0,0); - Vector vecMaxs(1,1,1); - vecMins[smallestAxis] = 0.5; - vecMaxs[smallestAxis] = 0.5; - pEntity->CollisionProp()->RandomPointInBounds( vecMins, vecMaxs, &breakModel.offset ); - - // Push all chunks away from the center - Vector vecBurstDir = breakModel.offset - params.origin; - VectorNormalize( vecBurstDir ); - Vector vecVelocity = vecBurstDir * params.defBurstScale; - - QAngle vecAngles = pEntity->GetAbsAngles(); - int iSkin = pBreakableInterface->GetBreakableSkin(); - - CBaseEntity *pBreakable = NULL; - -#ifdef GAME_DLL - if ( GetGibManager() == NULL || GetGibManager()->AllowedToSpawnGib() ) -#endif - { - pBreakable = BreakModelCreateSingle( pOwnerEntity, &breakModel, breakModel.offset, vecAngles, vecVelocity, vec3_origin/*params.angularVelocity*/, iSkin, params ); - if ( !pBreakable ) - { - DevWarning( "PropBreakableCreateAll: Could not create model %s\n", breakModel.modelName ); - } - } - - if ( pBreakable ) - { -#ifdef GAME_DLL - if ( GetGibManager() ) - { - GetGibManager()->AddGibToLRU( pBreakable->GetBaseAnimating() ); - } -#endif - Vector vecBreakableObbSize = pBreakable->CollisionProp()->OBBSize(); - - // Try to align the gibs along the original axis - matrix3x4_t matrix; - AngleMatrix( vecAngles, matrix ); - AlignBoxes( &matrix, vecObbSize, vecBreakableObbSize ); - MatrixAngles( matrix, vecAngles ); - - if ( pBreakable->VPhysicsGetObject() ) - { - Vector pos; - pBreakable->VPhysicsGetObject()->GetPosition( &pos, NULL ); - pBreakable->VPhysicsGetObject()->SetPosition( pos, vecAngles, true ); - } - - pBreakable->SetAbsAngles( vecAngles ); - - if ( pOwnerEntity->IsEffectActive( EF_NOSHADOW ) ) - { - pBreakable->AddEffects( EF_NOSHADOW ); - } - } - } - } - } -} - - -void PropBreakableCreateAll( int modelindex, IPhysicsObject *pPhysics, const Vector &origin, const QAngle &angles, const Vector &velocity, const AngularImpulse &angularVelocity, float impactEnergyScale, float defBurstScale, int defCollisionGroup, CBaseEntity *pEntity, bool defaultLocation ) -{ - breakablepropparams_t params( origin, angles, velocity, angularVelocity ); - params.impactEnergyScale = impactEnergyScale; - params.defBurstScale = defBurstScale; - params.defCollisionGroup = defCollisionGroup; - PropBreakableCreateAll( modelindex, pPhysics, params, pEntity, -1, false, defaultLocation ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : modelindex - -//----------------------------------------------------------------------------- -void PrecacheGibsForModel( int iModel ) -{ - vcollide_t *pCollide = modelinfo->GetVCollide( iModel ); - if ( !pCollide ) - return; - - // The scale and group doesn't really matter at the moment, we are just using the parser to get the model name to cache. - CBreakParser breakParser( 1.0, COLLISION_GROUP_NONE ); - - // Create a parser. - IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pCollide->pKeyValues ); - while ( !pParse->Finished() ) - { - const char *pBlock = pParse->GetCurrentBlockName(); - if ( !strcmpi( pBlock, "break" ) ) - { - breakmodel_t breakModel; - pParse->ParseCustom( &breakModel, &breakParser ); - CBaseEntity::PrecacheModel( breakModel.modelName ); - } - else - { - pParse->SkipBlock(); - } - } - - // Destroy the parser. - physcollision->VPhysicsKeyParserDestroy( pParse ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &list - -// modelindex - -// defBurstScale - -// defCollisionGroup - -//----------------------------------------------------------------------------- -void BuildGibList( CUtlVector &list, int modelindex, float defBurstScale, int defCollisionGroup ) -{ - BreakModelList( list, modelindex, defBurstScale, defCollisionGroup ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &list - -// modelindex - -// *pPhysics - -// ¶ms - -// *pEntity - -// iPrecomputedBreakableCount - -// bIgnoreGibLImit - -// defaultLocation - -//----------------------------------------------------------------------------- -CBaseEntity *CreateGibsFromList( CUtlVector &list, int modelindex, IPhysicsObject *pPhysics, const breakablepropparams_t ¶ms, CBaseEntity *pEntity, int iPrecomputedBreakableCount, bool bIgnoreGibLimit, bool defaultLocation, CUtlVector *pGibList ) -{ - // Check for prop breakable count reset. - int nPropCount = props_break_max_pieces_perframe.GetInt(); - if ( nPropCount != -1 ) - { - if ( nFrameNumber != gpGlobals->framecount ) - { - nPropBreakablesPerFrameCount = 0; - nFrameNumber = gpGlobals->framecount; - } - - // Check for max breakable count for the frame. - if ( nPropBreakablesPerFrameCount >= nPropCount ) - return NULL; - } - - int iMaxBreakCount = bIgnoreGibLimit ? -1 : props_break_max_pieces.GetInt(); - if ( iMaxBreakCount != -1 ) - { - if ( iPrecomputedBreakableCount != -1 ) - { - iPrecomputedBreakableCount = MIN( iMaxBreakCount, iPrecomputedBreakableCount ); - } - else - { - iPrecomputedBreakableCount = iMaxBreakCount; - } - } - -#ifdef GAME_DLL - // On server limit break model creation - if ( !PropBreakableCapEdictsOnCreateAll(modelindex, pPhysics, params, pEntity, iPrecomputedBreakableCount ) ) - { - DevMsg( "Failed to create PropBreakable: would exceed MAX_EDICTS\n" ); - return NULL; - } -#endif - - vcollide_t *pCollide = modelinfo->GetVCollide( modelindex ); - if ( !pCollide ) - return NULL; - - int nSkin = 0; - CBaseEntity *pOwnerEntity = pEntity; - CBaseAnimating *pOwnerAnim = NULL; - if ( pPhysics ) - { - pOwnerEntity = static_cast(pPhysics->GetGameData()); - } - if ( pOwnerEntity ) - { - pOwnerAnim = dynamic_cast(pOwnerEntity); - if ( pOwnerAnim ) - { - nSkin = pOwnerAnim->m_nSkin; - } - } - matrix3x4_t localToWorld; - - CStudioHdr studioHdr; - const model_t *model = modelinfo->GetModel( modelindex ); - if ( model ) - { - studioHdr.Init( modelinfo->GetStudiomodel( model ) ); - } - - Vector parentOrigin = vec3_origin; - int parentAttachment = Studio_FindAttachment( &studioHdr, "placementOrigin" ) + 1; - if ( parentAttachment > 0 ) - { - GetAttachmentLocalSpace( &studioHdr, parentAttachment-1, localToWorld ); - MatrixGetColumn( localToWorld, 3, parentOrigin ); - } - else - { - AngleMatrix( vec3_angle, localToWorld ); - } - -// CUtlVector list; -// BreakModelList( list, modelindex, params.defBurstScale, params.defCollisionGroup ); - - CBaseEntity *pFirstBreakable = NULL; - - if ( list.Count() ) - { - for ( int i = 0; i < list.Count(); i++ ) - { - int modelIndex = modelinfo->GetModelIndex( list[i].modelName ); - if ( modelIndex <= 0 ) - continue; - - // Skip multiplayer pieces that should be spawning on the other dll -#ifdef GAME_DLL - if ( gpGlobals->maxClients > 1 && breakable_multiplayer.GetBool() ) -#else - if ( gpGlobals->maxClients > 1 ) -#endif - { -#ifdef GAME_DLL - if ( list[i].mpBreakMode == MULTIPLAYER_BREAK_CLIENTSIDE ) - continue; -#else - if ( list[i].mpBreakMode == MULTIPLAYER_BREAK_SERVERSIDE ) - continue; -#endif - - if ( !defaultLocation && list[i].mpBreakMode == MULTIPLAYER_BREAK_DEFAULT ) - continue; - } - - if ( ( nPropCount != -1 ) && ( nPropBreakablesPerFrameCount > nPropCount ) ) - break; - - if ( ( iPrecomputedBreakableCount != -1 ) && ( i >= iPrecomputedBreakableCount ) ) - break; - - matrix3x4_t matrix; - AngleMatrix( params.angles, params.origin, matrix ); - - CStudioHdr studioHdr; - const model_t *model = modelinfo->GetModel( modelIndex ); - if ( model ) - { - studioHdr.Init( modelinfo->GetStudiomodel( model ) ); - } - - // Increment the number of breakable props this frame. - ++nPropBreakablesPerFrameCount; - - Vector position = vec3_origin; - QAngle angles = params.angles; - if ( pOwnerAnim && list[i].placementName[0] ) - { - if ( list[i].placementIsBone ) - { - int boneIndex = pOwnerAnim->LookupBone( list[i].placementName ); - if ( boneIndex >= 0 ) - { - pOwnerAnim->GetBonePosition( boneIndex, position, angles ); - AngleMatrix( angles, position, matrix ); - } - } - else - { - int attachmentIndex = Studio_FindAttachment( &studioHdr, list[i].placementName ) + 1; - if ( attachmentIndex > 0 ) - { - pOwnerAnim->GetAttachment( attachmentIndex, matrix ); - MatrixAngles( matrix, angles ); - } - } - } - else - { - int placementIndex = Studio_FindAttachment( &studioHdr, "placementOrigin" ) + 1; - Vector placementOrigin = parentOrigin; - if ( placementIndex > 0 ) - { - GetAttachmentLocalSpace( &studioHdr, placementIndex-1, localToWorld ); - MatrixGetColumn( localToWorld, 3, placementOrigin ); - placementOrigin -= parentOrigin; - } - - VectorTransform( list[i].offset - placementOrigin, matrix, position ); - } - Vector objectVelocity = params.velocity; - - float flScale = VectorNormalize( objectVelocity ); - objectVelocity.x += RandomFloat( -1.f, 1.0f ); - objectVelocity.y += RandomFloat( -1.0f, 1.0f ); - objectVelocity.z += RandomFloat( 0.0f, 1.0f ); - VectorNormalize( objectVelocity ); - objectVelocity *= flScale; - - if (pPhysics) - { - pPhysics->GetVelocityAtPoint( position, &objectVelocity ); - } - - int nActualSkin = nSkin; - if ( nActualSkin > studioHdr.numskinfamilies() ) - nActualSkin = 0; - - CBaseEntity *pBreakable = NULL; - -#ifdef GAME_DLL - if ( GetGibManager() == NULL || GetGibManager()->AllowedToSpawnGib() ) -#endif - { - pBreakable = BreakModelCreateSingle( pOwnerEntity, &list[i], position, angles, objectVelocity, params.angularVelocity, nActualSkin, params ); - } - - if ( pBreakable ) - { -#ifdef GAME_DLL - if ( GetGibManager() ) - { - GetGibManager()->AddGibToLRU( pBreakable->GetBaseAnimating() ); - } -#endif - if ( pOwnerEntity && pOwnerEntity->IsEffectActive( EF_NOSHADOW ) ) - { - pBreakable->AddEffects( EF_NOSHADOW ); - } - - // If burst scale is set, this piece should 'burst' away from - // the origin in addition to travelling in the wished velocity. - if ( list[i].burstScale != 0.0 ) - { - Vector vecBurstDir = position - params.origin; - - // If $autocenter wasn't used, try the center of the piece - if ( vecBurstDir == vec3_origin ) - { - vecBurstDir = pBreakable->WorldSpaceCenter() - params.origin; - } - - VectorNormalize( vecBurstDir ); - - pBreakable->ApplyAbsVelocityImpulse( vecBurstDir * list[i].burstScale ); - } - - // If this piece is supposed to be motion disabled, disable it - if ( list[i].isMotionDisabled ) - { - IPhysicsObject *pPhysicsObject = pBreakable->VPhysicsGetObject(); - if ( pPhysicsObject != NULL ) - { - pPhysicsObject->EnableMotion( false ); - } - } - - if ( !pFirstBreakable ) - { - pFirstBreakable = pBreakable; - } - - if ( pGibList ) - { - pGibList->AddToTail( pBreakable ); - } - } - } - } - // Then see if the propdata specifies any breakable pieces - else if ( pEntity ) - { - IBreakableWithPropData *pBreakableInterface = dynamic_cast(pEntity); - if ( pBreakableInterface && pBreakableInterface->GetBreakableModel() != NULL_STRING && pBreakableInterface->GetBreakableCount() ) - { - breakmodel_t breakModel; - - for ( int i = 0; i < pBreakableInterface->GetBreakableCount(); i++ ) - { - if ( ( iPrecomputedBreakableCount != -1 ) && ( i >= iPrecomputedBreakableCount ) ) - break; - - Q_strncpy( breakModel.modelName, g_PropDataSystem.GetRandomChunkModel(STRING(pBreakableInterface->GetBreakableModel()), pBreakableInterface->GetMaxBreakableSize()), sizeof(breakModel.modelName) ); - - breakModel.health = 1; - breakModel.fadeTime = RandomFloat(5,10); - breakModel.fadeMinDist = 0.0f; - breakModel.fadeMaxDist = 0.0f; - breakModel.burstScale = params.defBurstScale; - breakModel.collisionGroup = COLLISION_GROUP_DEBRIS; - breakModel.isRagdoll = false; - breakModel.isMotionDisabled = false; - breakModel.placementName[0] = 0; - breakModel.placementIsBone = false; - - Vector vecObbSize = pEntity->CollisionProp()->OBBSize(); - - // Find a random point on the plane of the original's two largest axis - int smallestAxis = SmallestAxis( vecObbSize ); - Vector vecMins(0,0,0); - Vector vecMaxs(1,1,1); - vecMins[smallestAxis] = 0.5; - vecMaxs[smallestAxis] = 0.5; - pEntity->CollisionProp()->RandomPointInBounds( vecMins, vecMaxs, &breakModel.offset ); - - // Push all chunks away from the center - Vector vecBurstDir = breakModel.offset - params.origin; - VectorNormalize( vecBurstDir ); - Vector vecVelocity = vecBurstDir * params.defBurstScale; - - QAngle vecAngles = pEntity->GetAbsAngles(); - int iSkin = pBreakableInterface->GetBreakableSkin(); - - CBaseEntity *pBreakable = NULL; - -#ifdef GAME_DLL - if ( GetGibManager() == NULL || GetGibManager()->AllowedToSpawnGib() ) -#endif - { - pBreakable = BreakModelCreateSingle( pOwnerEntity, &breakModel, breakModel.offset, vecAngles, vecVelocity, vec3_origin/*params.angularVelocity*/, iSkin, params ); - } - - if( pBreakable ) - { -#ifdef GAME_DLL - if ( GetGibManager() ) - { - GetGibManager()->AddGibToLRU( pBreakable->GetBaseAnimating() ); - } -#endif - Vector vecBreakableObbSize = pBreakable->CollisionProp()->OBBSize(); - - // Try to align the gibs along the original axis - matrix3x4_t matrix; - AngleMatrix( vecAngles, matrix ); - AlignBoxes( &matrix, vecObbSize, vecBreakableObbSize ); - MatrixAngles( matrix, vecAngles ); - - if ( pBreakable->VPhysicsGetObject() ) - { - Vector pos; - pBreakable->VPhysicsGetObject()->GetPosition( &pos, NULL ); - pBreakable->VPhysicsGetObject()->SetPosition( pos, vecAngles, true ); - } - - pBreakable->SetAbsAngles( vecAngles ); - - if ( pOwnerEntity->IsEffectActive( EF_NOSHADOW ) ) - { - pBreakable->AddEffects( EF_NOSHADOW ); - } - - if ( !pFirstBreakable ) - { - pFirstBreakable = pBreakable; - } - - if ( pGibList ) - { - pGibList->AddToTail( pBreakable ); - } - } - else - { - DevWarning( "PropBreakableCreateAll: Could not create model %s\n", breakModel.modelName ); - } - } - } - } - - return pFirstBreakable; -} - diff --git a/game/shared/props_shared.h b/game/shared/props_shared.h deleted file mode 100644 index b2c21434c..000000000 --- a/game/shared/props_shared.h +++ /dev/null @@ -1,252 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef PROPS_SHARED_H -#define PROPS_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - -#include "igamesystem.h" -#include - -// Phys prop spawnflags -#define SF_PHYSPROP_START_ASLEEP 0x000001 -#define SF_PHYSPROP_DONT_TAKE_PHYSICS_DAMAGE 0x000002 // this prop can't be damaged by physics collisions -#define SF_PHYSPROP_DEBRIS 0x000004 -#define SF_PHYSPROP_MOTIONDISABLED 0x000008 // motion disabled at startup (flag only valid in spawn - motion can be enabled via input) -#define SF_PHYSPROP_TOUCH 0x000010 // can be 'crashed through' by running player (plate glass) -#define SF_PHYSPROP_PRESSURE 0x000020 // can be broken by a player standing on it -#define SF_PHYSPROP_ENABLE_ON_PHYSCANNON 0x000040 // enable motion only if the player grabs it with the physcannon -#define SF_PHYSPROP_NO_ROTORWASH_PUSH 0x000080 // The rotorwash doesn't push these -#define SF_PHYSPROP_ENABLE_PICKUP_OUTPUT 0x000100 // If set, allow the player to +USE this for the purposes of generating an output -#define SF_PHYSPROP_PREVENT_PICKUP 0x000200 // If set, prevent +USE/Physcannon pickup of this prop -#define SF_PHYSPROP_PREVENT_PLAYER_TOUCH_ENABLE 0x000400 // If set, the player will not cause the object to enable its motion when bumped into -#define SF_PHYSPROP_HAS_ATTACHED_RAGDOLLS 0x000800 // Need to remove attached ragdolls on enable motion/etc -#define SF_PHYSPROP_FORCE_TOUCH_TRIGGERS 0x001000 // Override normal debris behavior and respond to triggers anyway -#define SF_PHYSPROP_FORCE_SERVER_SIDE 0x002000 // Force multiplayer physics object to be serverside -#define SF_PHYSPROP_RADIUS_PICKUP 0x004000 // For Xbox, makes small objects easier to pick up by allowing them to be found -#define SF_PHYSPROP_ALWAYS_PICK_UP 0x100000 // Physcannon can always pick this up, no matter what mass or constraints may apply. -#define SF_PHYSPROP_NO_COLLISIONS 0x200000 // Don't enable collisions on spawn -#define SF_PHYSPROP_IS_GIB 0x400000 // Limit # of active gibs - -// Any barrel farther away than this is ignited rather than exploded. -#define PROP_EXPLOSION_IGNITE_RADIUS 32.0f - -// ParsePropData returns -enum -{ - PARSE_SUCCEEDED, // Parsed propdata. Prop must be a prop_physics. - PARSE_SUCCEEDED_ALLOWED_STATIC, // Parsed propdata. Prop allowed to be prop_physics or prop_dynamic/prop_static. - PARSE_FAILED_NO_DATA, // Parse failed, no propdata in model. Prop must be prop_dynamic/prop_static. - PARSE_FAILED_BAD_DATA, // Parse failed, found propdata but it had bad data. -}; - -// Propdata defined interactions -enum propdata_interactions_t -{ - PROPINTER_PHYSGUN_WORLD_STICK, // "onworldimpact" "stick" - PROPINTER_PHYSGUN_FIRST_BREAK, // "onfirstimpact" "break" - PROPINTER_PHYSGUN_FIRST_PAINT, // "onfirstimpact" "paintsplat" - PROPINTER_PHYSGUN_FIRST_IMPALE, // "onfirstimpact" "impale" - PROPINTER_PHYSGUN_LAUNCH_SPIN_NONE, // "onlaunch" "spin_none" - PROPINTER_PHYSGUN_LAUNCH_SPIN_Z, // "onlaunch" "spin_zaxis" - PROPINTER_PHYSGUN_BREAK_EXPLODE, // "onbreak" "explode_fire" - PROPINTER_PHYSGUN_DAMAGE_NONE, // "damage" "none" - - PROPINTER_FIRE_FLAMMABLE, // "flammable" "yes" - PROPINTER_FIRE_EXPLOSIVE_RESIST, // "explosive_resist" "yes" - PROPINTER_FIRE_IGNITE_HALFHEALTH, // "ignite" "halfhealth" - - PROPINTER_PHYSGUN_CREATE_FLARE, // "onpickup" "create_flare" - - PROPINTER_PHYSGUN_ALLOW_OVERHEAD, // "allow_overhead" "yes" - - PROPINTER_WORLD_BLOODSPLAT, // "onworldimpact", "bloodsplat" - - PROPINTER_PHYSGUN_NOTIFY_CHILDREN, // "onfirstimpact" cause attached flechettes to explode - - // If we get more than 32 of these, we'll need a different system - - PROPINTER_NUM_INTERACTIONS, -}; - -// Entities using COLLISION_GROUP_SPECIAL_PHYSICS should support this interface. -abstract_class IMultiplayerPhysics -{ -public: - virtual int GetMultiplayerPhysicsMode() = 0; - virtual float GetMass() = 0; - virtual bool IsAsleep() = 0; -}; - -#define PHYSICS_MULTIPLAYER_AUTODETECT 0 // use multiplayer physics mode as defined in model prop data -#define PHYSICS_MULTIPLAYER_SOLID 1 // soild, pushes player away -#define PHYSICS_MULTIPLAYER_NON_SOLID 2 // nonsolid, but pushed by player -#define PHYSICS_MULTIPLAYER_CLIENTSIDE 3 // Clientside only, nonsolid - -enum mp_break_t -{ - MULTIPLAYER_BREAK_DEFAULT, - MULTIPLAYER_BREAK_SERVERSIDE, - MULTIPLAYER_BREAK_CLIENTSIDE, - MULTIPLAYER_BREAK_BOTH -}; - - -enum PerformanceMode_t -{ - PM_NORMAL, - PM_NO_GIBS, - PM_FULL_GIBS, - PM_REDUCED_GIBS, -}; - - -//============================================================================================================= -// PROP DATA -//============================================================================================================= -//----------------------------------------------------------------------------- -// Purpose: Derive your entity from this if you want your entity to parse propdata -//----------------------------------------------------------------------------- -abstract_class IBreakableWithPropData -{ -public: - // Damage modifiers - virtual void SetDmgModBullet( float flDmgMod ) = 0; - virtual void SetDmgModClub( float flDmgMod ) = 0; - virtual void SetDmgModExplosive( float flDmgMod ) = 0; - virtual float GetDmgModBullet( void ) = 0; - virtual float GetDmgModClub( void ) = 0; - virtual float GetDmgModExplosive( void ) = 0; - - // Explosive - virtual void SetExplosiveRadius( float flRadius ) = 0; - virtual void SetExplosiveDamage( float flDamage ) = 0; - virtual float GetExplosiveRadius( void ) = 0; - virtual float GetExplosiveDamage( void ) = 0; - - // Physics damage tables - virtual void SetPhysicsDamageTable( string_t iszTableName ) = 0; - virtual string_t GetPhysicsDamageTable( void ) = 0; - - // Breakable chunks - virtual void SetBreakableModel( string_t iszModel ) = 0; - virtual string_t GetBreakableModel( void ) = 0; - virtual void SetBreakableSkin( int iSkin ) = 0; - virtual int GetBreakableSkin( void ) = 0; - virtual void SetBreakableCount( int iCount ) = 0; - virtual int GetBreakableCount( void ) = 0; - virtual void SetMaxBreakableSize( int iSize ) = 0; - virtual int GetMaxBreakableSize( void ) = 0; - - // LOS blocking - virtual void SetPropDataBlocksLOS( bool bBlocksLOS ) = 0; - virtual void SetPropDataIsAIWalkable( bool bBlocksLOS ) = 0; - - // Interactions - virtual void SetInteraction( propdata_interactions_t Interaction ) = 0; - virtual bool HasInteraction( propdata_interactions_t Interaction ) = 0; - - // Multiplayer physics mode - virtual void SetPhysicsMode(int iMode) = 0; - virtual int GetPhysicsMode() = 0; - - // Multiplayer breakable spawn behavior - virtual void SetMultiplayerBreakMode( mp_break_t mode ) = 0; - virtual mp_break_t GetMultiplayerBreakMode( void ) const = 0; - - // Used for debugging - virtual void SetBasePropData( string_t iszBase ) = 0; - virtual string_t GetBasePropData( void ) = 0; -}; - -//----------------------------------------------------------------------------- -// Purpose: Gamesystem that parses the prop data file -//----------------------------------------------------------------------------- -class CPropData : public CAutoGameSystem -{ -public: - CPropData( void ); - - // Inherited from IAutoServerSystem - virtual void LevelInitPreEntity( void ); - virtual void LevelShutdownPostEntity( void ); - - // Read in the data from the prop data file - void ParsePropDataFile( void ); - - // Parse a keyvalues section into the prop - int ParsePropFromKV( CBaseEntity *pProp, KeyValues *pSection, KeyValues *pInteractionSection ); - - // Fill out a prop's with base data parsed from the propdata file - int ParsePropFromBase( CBaseEntity *pProp, const char *pszPropData ); - - // Get a random chunk in the specified breakable section - const char *GetRandomChunkModel( const char *pszBreakableSection, int iMaxSize = -1 ); - -protected: - KeyValues *m_pKVPropData; - bool m_bPropDataLoaded; - - struct propdata_breakablechunk_t - { - string_t iszChunkType; - CUtlVector iszChunkModels; - }; - CUtlVector m_BreakableChunks; -}; - -extern CPropData g_PropDataSystem; - -struct breakmodel_t -{ - Vector offset; - char modelName[512]; - char placementName[512]; - float fadeTime; - float fadeMinDist; - float fadeMaxDist; - float health; - float burstScale; - int collisionGroup; - bool isRagdoll; - bool placementIsBone; - bool isMotionDisabled; - mp_break_t mpBreakMode; -}; - -struct breakablepropparams_t -{ - breakablepropparams_t( const Vector &_origin, const QAngle &_angles, const Vector &_velocity, const AngularImpulse &_angularVelocity ) - : origin(_origin), angles(_angles), velocity(_velocity), angularVelocity(_angularVelocity) - { - impactEnergyScale = 0; - defBurstScale = 0; - defCollisionGroup = COLLISION_GROUP_NONE; - } - - const Vector &origin; - const QAngle &angles; - const Vector &velocity; - const AngularImpulse &angularVelocity; - float impactEnergyScale; - float defBurstScale; - int defCollisionGroup; -}; - -const char *GetMassEquivalent(float flMass); -int GetAutoMultiplayerPhysicsMode( Vector size, float mass ); -void BreakModelList( CUtlVector &list, int modelindex, float defBurstScale, int defCollisionGroup ); -void PropBreakableCreateAll( int modelindex, IPhysicsObject *pPhysics, const breakablepropparams_t ¶ms, CBaseEntity *pEntity, int iPrecomputedBreakableCount, bool bIgnoreGibLImit, bool defaultLocation = true ); -void PropBreakableCreateAll( int modelindex, IPhysicsObject *pPhysics, const Vector &origin, const QAngle &angles, const Vector &velocity, const AngularImpulse &angularVelocity, float impactEnergyScale, float burstScale, int collisionGroup, CBaseEntity *pEntity = NULL, bool defaultLocation = true ); - -// Player gibs. -void PrecacheGibsForModel( int iModel ); -void BuildGibList( CUtlVector &list, int modelindex, float defBurstScale, int defCollisionGroup ); -CBaseEntity *CreateGibsFromList( CUtlVector &list, int modelindex, IPhysicsObject *pPhysics, const breakablepropparams_t ¶ms, CBaseEntity *pEntity, int iPrecomputedBreakableCount, bool bIgnoreGibLImit, bool defaultLocation = true, CUtlVector *pGibList = NULL ); - -#endif // PROPS_SHARED_H diff --git a/game/shared/ragdoll_shared.cpp b/game/shared/ragdoll_shared.cpp deleted file mode 100644 index 17758d2eb..000000000 --- a/game/shared/ragdoll_shared.cpp +++ /dev/null @@ -1,1249 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "ragdoll_shared.h" -#include "bone_setup.h" -#include "vphysics/constraints.h" -#include "vphysics/collision_set.h" -#include "vcollide_parse.h" -#include "vphysics_interface.h" -#include "tier0/vprof.h" -#include "engine/ivdebugoverlay.h" -#include "solidsetdefaults.h" -//CLIENT -#ifdef CLIENT_DLL -#include "c_fire_smoke.h" -#include "c_entitydissolve.h" -#include "engine/IEngineSound.h" -#endif - -//SERVER -#if !defined( CLIENT_DLL ) -#include "util.h" -#include "EntityFlame.h" -#include "EntityDissolve.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -CRagdollLowViolenceManager g_RagdollLVManager; - -void CRagdollLowViolenceManager::SetLowViolence( const char *pMapName ) -{ - // set the value using the engine's low violence settings - m_bLowViolence = UTIL_IsLowViolence(); - -#if !defined( CLIENT_DLL ) - // the server doesn't worry about low violence during multiplayer games - if ( g_pGameRules->IsMultiplayer() ) - { - m_bLowViolence = false; - } -#endif - - // Turn the low violence ragdoll stuff off if we're in the HL2 Citadel maps because - // the player has the super gravity gun and fading ragdolls will break things. - if( hl2_episodic.GetBool() ) - { - if ( Q_stricmp( pMapName, "ep1_citadel_02" ) == 0 || - Q_stricmp( pMapName, "ep1_citadel_02b" ) == 0 || - Q_stricmp( pMapName, "ep1_citadel_03" ) == 0 ) - { - m_bLowViolence = false; - } - } - else - { - if ( Q_stricmp( pMapName, "d3_citadel_03" ) == 0 || - Q_stricmp( pMapName, "d3_citadel_04" ) == 0 || - Q_stricmp( pMapName, "d3_citadel_05" ) == 0 || - Q_stricmp( pMapName, "d3_breen_01" ) == 0 ) - { - m_bLowViolence = false; - } - } -} - -class CRagdollCollisionRules : public IVPhysicsKeyHandler -{ -public: - CRagdollCollisionRules( IPhysicsCollisionSet *pSet ) - { - m_pSet = pSet; - m_bSelfCollisions = true; - } - virtual void ParseKeyValue( void *pData, const char *pKey, const char *pValue ) - { - if ( !strcmpi( pKey, "selfcollisions" ) ) - { - // keys disabled by default - Assert( atoi(pValue) == 0 ); - m_bSelfCollisions = false; - } - else if ( !strcmpi( pKey, "collisionpair" ) ) - { - if ( m_bSelfCollisions ) - { - char szToken[256]; - const char *pStr = nexttoken(szToken, pValue, ','); - int index0 = atoi(szToken); - nexttoken( szToken, pStr, ',' ); - int index1 = atoi(szToken); - - m_pSet->EnableCollisions( index0, index1 ); - } - else - { - Assert(0); - } - } - } - virtual void SetDefaults( void *pData ) {} - -private: - IPhysicsCollisionSet *m_pSet; - bool m_bSelfCollisions; -}; - -class CRagdollAnimatedFriction : public IVPhysicsKeyHandler -{ -public: - CRagdollAnimatedFriction( ragdoll_t *ragdoll ) - { - m_ragdoll = ragdoll; - } - virtual void ParseKeyValue( void *pData, const char *pKey, const char *pValue ) - { - if ( !strcmpi( pKey, "animfrictionmin" ) ) - { - m_ragdoll->animfriction.iMinAnimatedFriction = atoi( pValue ); - } - else if ( !strcmpi( pKey, "animfrictionmax" ) ) - { - m_ragdoll->animfriction.iMaxAnimatedFriction = atoi( pValue ); - } - else if ( !strcmpi( pKey, "animfrictiontimein" ) ) - { - m_ragdoll->animfriction.flFrictionTimeIn = atof( pValue ); - } - else if ( !strcmpi( pKey, "animfrictiontimeout" ) ) - { - m_ragdoll->animfriction.flFrictionTimeOut = atof( pValue ); - } - else if ( !strcmpi( pKey, "animfrictiontimehold" ) ) - { - m_ragdoll->animfriction.flFrictionTimeHold = atof( pValue ); - } - } - - virtual void SetDefaults( void *pData ) {} - -private: - ragdoll_t *m_ragdoll; -}; - -void RagdollSetupAnimatedFriction( IPhysicsEnvironment *pPhysEnv, ragdoll_t *ragdoll, int iModelIndex ) -{ - vcollide_t* pCollide = modelinfo->GetVCollide( iModelIndex ); - - if ( pCollide ) - { - IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pCollide->pKeyValues ); - - while ( !pParse->Finished() ) - { - const char *pBlock = pParse->GetCurrentBlockName(); - - if ( !strcmpi( pBlock, "animatedfriction") ) - { - CRagdollAnimatedFriction friction( ragdoll ); - pParse->ParseCustom( (void*)&friction, &friction ); - } - else - { - pParse->SkipBlock(); - } - } - - physcollision->VPhysicsKeyParserDestroy( pParse ); - } -} - -static void RagdollAddSolid( IPhysicsEnvironment *pPhysEnv, ragdoll_t &ragdoll, const ragdollparams_t ¶ms, solid_t &solid ) -{ - if ( solid.index >= 0 && solid.index < params.pCollide->solidCount) - { - Assert( ragdoll.listCount == solid.index ); - int boneIndex = Studio_BoneIndexByName( params.pStudioHdr, solid.name ); - ragdoll.boneIndex[ragdoll.listCount] = boneIndex; - - if ( boneIndex >= 0 ) - { - solid.params.rotInertiaLimit = 0.1; - solid.params.pGameData = params.pGameData; - int surfaceData = physprops->GetSurfaceIndex( solid.surfaceprop ); - - if ( surfaceData < 0 ) - surfaceData = physprops->GetSurfaceIndex( "default" ); - - solid.params.pName = params.pStudioHdr->pszName(); - ragdoll.list[ragdoll.listCount].pObject = pPhysEnv->CreatePolyObject( params.pCollide->solids[solid.index], surfaceData, vec3_origin, vec3_angle, &solid.params ); - ragdoll.list[ragdoll.listCount].pObject->SetPositionMatrix( params.pCurrentBones[boneIndex], true ); - ragdoll.list[ragdoll.listCount].parentIndex = -1; - ragdoll.list[ragdoll.listCount].pObject->SetGameIndex( ragdoll.listCount ); - - ragdoll.listCount++; - } - else - { - Msg( "CRagdollProp::CreateObjects: Couldn't Lookup Bone %s\n", solid.name ); - } - } -} - - -static void RagdollAddConstraint( IPhysicsEnvironment *pPhysEnv, ragdoll_t &ragdoll, const ragdollparams_t ¶ms, constraint_ragdollparams_t &constraint ) -{ - if( constraint.childIndex == constraint.parentIndex ) - { - DevMsg( 1, "Bogus constraint on ragdoll %s\n", params.pStudioHdr->pszName() ); - constraint.childIndex = -1; - constraint.parentIndex = -1; - } - if ( constraint.childIndex >= 0 && constraint.parentIndex >= 0 ) - { - Assert(constraint.childIndex 0 ) - { - for ( int k = 0; k < 3; k++ ) - { - constraint.axes[k].torque *= params.jointFrictionScale; - } - } - // this parent/child pair is not usually a parent/child pair in the skeleton. There - // are often bones in between that are collapsed for simulation. So we need to compute - // the transform. - Studio_CalcBoneToBoneTransform( params.pStudioHdr, ragdoll.boneIndex[constraint.childIndex], ragdoll.boneIndex[constraint.parentIndex], constraint.constraintToAttached ); - MatrixGetColumn( constraint.constraintToAttached, 3, childElement.originParentSpace ); - // UNDONE: We could transform the constraint limit axes relative to the bone space - // using this data. Do we need that feature? - SetIdentityMatrix( constraint.constraintToReference ); - childElement.pConstraint = pPhysEnv->CreateRagdollConstraint( childElement.pObject, ragdoll.list[constraint.parentIndex].pObject, ragdoll.pGroup, constraint ); - } -} - - -static void RagdollCreateObjects( IPhysicsEnvironment *pPhysEnv, ragdoll_t &ragdoll, const ragdollparams_t ¶ms ) -{ - ragdoll.listCount = 0; - ragdoll.pGroup = NULL; - ragdoll.allowStretch = params.allowStretch; - memset( ragdoll.list, 0, sizeof(ragdoll.list) ); - memset( &ragdoll.animfriction, 0, sizeof(ragdoll.animfriction) ); - - if ( !params.pCollide || params.pCollide->solidCount > RAGDOLL_MAX_ELEMENTS ) - return; - - constraint_groupparams_t group; - group.Defaults(); - ragdoll.pGroup = pPhysEnv->CreateConstraintGroup( group ); - - IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( params.pCollide->pKeyValues ); - while ( !pParse->Finished() ) - { - const char *pBlock = pParse->GetCurrentBlockName(); - if ( !strcmpi( pBlock, "solid" ) ) - { - solid_t solid; - - pParse->ParseSolid( &solid, &g_SolidSetup ); - RagdollAddSolid( pPhysEnv, ragdoll, params, solid ); - } - else if ( !strcmpi( pBlock, "ragdollconstraint" ) ) - { - constraint_ragdollparams_t constraint; - pParse->ParseRagdollConstraint( &constraint, NULL ); - RagdollAddConstraint( pPhysEnv, ragdoll, params, constraint ); - } - else if ( !strcmpi( pBlock, "collisionrules" ) ) - { - IPhysicsCollisionSet *pSet = physics->FindOrCreateCollisionSet( params.modelIndex, ragdoll.listCount ); - CRagdollCollisionRules rules(pSet); - pParse->ParseCustom( (void *)&rules, &rules ); - } - else if ( !strcmpi( pBlock, "animatedfriction") ) - { - CRagdollAnimatedFriction friction( &ragdoll ); - pParse->ParseCustom( (void*)&friction, &friction ); - } - else - { - pParse->SkipBlock(); - } - } - physcollision->VPhysicsKeyParserDestroy( pParse ); -} - -void RagdollSetupCollisions( ragdoll_t &ragdoll, vcollide_t *pCollide, int modelIndex ) -{ - Assert(pCollide); - if (!pCollide) - return; - - IPhysicsCollisionSet *pSet = physics->FindCollisionSet( modelIndex ); - if ( !pSet ) - { - pSet = physics->FindOrCreateCollisionSet( modelIndex, ragdoll.listCount ); - if ( !pSet ) - return; - - bool bFoundRules = false; - - IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pCollide->pKeyValues ); - while ( !pParse->Finished() ) - { - const char *pBlock = pParse->GetCurrentBlockName(); - if ( !strcmpi( pBlock, "collisionrules" ) ) - { - IPhysicsCollisionSet *pSet = physics->FindOrCreateCollisionSet( modelIndex, ragdoll.listCount ); - CRagdollCollisionRules rules(pSet); - pParse->ParseCustom( (void *)&rules, &rules ); - bFoundRules = true; - } - else - { - pParse->SkipBlock(); - } - } - physcollision->VPhysicsKeyParserDestroy( pParse ); - - if ( !bFoundRules ) - { - // these are the default rules - each piece collides with everything - // except immediate parent/constrained object. - int i; - for ( i = 0; i < ragdoll.listCount; i++ ) - { - for ( int j = i+1; j < ragdoll.listCount; j++ ) - { - pSet->EnableCollisions( i, j ); - } - } - for ( i = 0; i < ragdoll.listCount; i++ ) - { - int parent = ragdoll.list[i].parentIndex; - if ( parent >= 0 ) - { - Assert( ragdoll.list[i].pObject ); - Assert( ragdoll.list[i].pConstraint ); - pSet->DisableCollisions( i, parent ); - } - } - } - } -} - -void RagdollActivate( ragdoll_t &ragdoll, vcollide_t *pCollide, int modelIndex, bool bForceWake ) -{ - RagdollSetupCollisions( ragdoll, pCollide, modelIndex ); - for ( int i = 0; i < ragdoll.listCount; i++ ) - { - ragdoll.list[i].pObject->SetGameIndex( i ); - PhysSetGameFlags( ragdoll.list[i].pObject, FVPHYSICS_MULTIOBJECT_ENTITY ); - // now that the relationships are set, activate the collision system - ragdoll.list[i].pObject->EnableCollisions( true ); - - if ( bForceWake == true ) - { - ragdoll.list[i].pObject->Wake(); - } - } - if ( ragdoll.pGroup ) - { - // NOTE: This also wakes the objects - ragdoll.pGroup->Activate(); - // so if we didn't want that, we'll need to put them back to sleep here - if ( !bForceWake ) - { - for ( int i = 0; i < ragdoll.listCount; i++ ) - { - ragdoll.list[i].pObject->Sleep(); - } - - } - } -} - - -bool RagdollCreate( ragdoll_t &ragdoll, const ragdollparams_t ¶ms, IPhysicsEnvironment *pPhysEnv ) -{ - RagdollCreateObjects( pPhysEnv, ragdoll, params ); - - if ( !ragdoll.listCount ) - return false; - - int forceBone = params.forceBoneIndex; - - int i; - float totalMass = 0; - for ( i = 0; i < ragdoll.listCount; i++ ) - { - totalMass += ragdoll.list[i].pObject->GetMass(); - } - totalMass = MAX(totalMass,1); - - // apply force to the model - Vector nudgeForce = params.forceVector; - Vector forcePosition = params.forcePosition; - // UNDONE: Test scaling the force by total mass on all bones - - Assert( forceBone < ragdoll.listCount ); - - if ( forceBone >= 0 && forceBone < ragdoll.listCount ) - { - ragdoll.list[forceBone].pObject->ApplyForceCenter( nudgeForce ); - //nudgeForce *= 0.5; - ragdoll.list[forceBone].pObject->GetPosition( &forcePosition, NULL ); - } - - for ( i = 0; i < ragdoll.listCount; i++ ) - { - PhysSetGameFlags( ragdoll.list[i].pObject, FVPHYSICS_PART_OF_RAGDOLL ); - } - - if ( forcePosition != vec3_origin ) - { - for ( i = 0; i < ragdoll.listCount; i++ ) - { - if ( forceBone != i ) - { - float scale = ragdoll.list[i].pObject->GetMass() / totalMass; - ragdoll.list[i].pObject->ApplyForceOffset( scale * nudgeForce, forcePosition ); - } - } - } - - return true; -} - - -void RagdollApplyAnimationAsVelocity( ragdoll_t &ragdoll, const matrix3x4_t *pPrevBones, const matrix3x4_t *pCurrentBones, float dt ) -{ - for ( int i = 0; i < ragdoll.listCount; i++ ) - { - Vector velocity; - AngularImpulse angVel; - int boneIndex = ragdoll.boneIndex[i]; - CalcBoneDerivatives( velocity, angVel, pPrevBones[boneIndex], pCurrentBones[boneIndex], dt ); - - AngularImpulse localAngVelocity; - - // Angular velocity is always applied in local space in vphysics - ragdoll.list[i].pObject->WorldToLocalVector( &localAngVelocity, angVel ); - ragdoll.list[i].pObject->AddVelocity( &velocity, &localAngVelocity ); - } -} - -void RagdollApplyAnimationAsVelocity( ragdoll_t &ragdoll, const matrix3x4_t *pBoneToWorld ) -{ - for ( int i = 0; i < ragdoll.listCount; i++ ) - { - matrix3x4_t inverse; - MatrixInvert( pBoneToWorld[i], inverse ); - Quaternion q; - Vector pos; - MatrixAngles( inverse, q, pos ); - - Vector velocity; - AngularImpulse angVel; - float flSpin; - - Vector localVelocity; - AngularImpulse localAngVelocity; - - QuaternionAxisAngle( q, localAngVelocity, flSpin ); - localAngVelocity *= flSpin; - localVelocity = pos; - - // move those bone-local coords back to world space using the ragdoll transform - ragdoll.list[i].pObject->LocalToWorldVector( &velocity, localVelocity ); - - ragdoll.list[i].pObject->AddVelocity( &velocity, &localAngVelocity ); - } -} - - -void RagdollDestroy( ragdoll_t &ragdoll ) -{ - if ( !ragdoll.listCount ) - return; - - int i; - for ( i = 0; i < ragdoll.listCount; i++ ) - { - physenv->DestroyConstraint( ragdoll.list[i].pConstraint ); - ragdoll.list[i].pConstraint = NULL; - } - for ( i = 0; i < ragdoll.listCount; i++ ) - { - // during level transitions these can get temporarily loaded without physics objects - // purely for the purpose of testing for PVS of transition. If they fail they get - // deleted before the physics objects are loaded. The list count will be nonzero - // since that is saved separately. - if ( ragdoll.list[i].pObject ) - { - physenv->DestroyObject( ragdoll.list[i].pObject ); - } - ragdoll.list[i].pObject = NULL; - } - physenv->DestroyConstraintGroup( ragdoll.pGroup ); - ragdoll.pGroup = NULL; - ragdoll.listCount = 0; -} - -// Parse the ragdoll and obtain the mapping from each physics element index to a bone index -// returns num phys elements -int RagdollExtractBoneIndices( int *boneIndexOut, CStudioHdr *pStudioHdr, vcollide_t *pCollide ) -{ - int elementCount = 0; - - IVPhysicsKeyParser *pParse = physcollision->VPhysicsKeyParserCreate( pCollide->pKeyValues ); - while ( !pParse->Finished() ) - { - const char *pBlock = pParse->GetCurrentBlockName(); - if ( !strcmpi( pBlock, "solid" ) ) - { - solid_t solid; - pParse->ParseSolid( &solid, NULL ); - if ( elementCount < RAGDOLL_MAX_ELEMENTS ) - { - boneIndexOut[elementCount] = Studio_BoneIndexByName( pStudioHdr, solid.name ); - elementCount++; - } - } - else - { - pParse->SkipBlock(); - } - } - physcollision->VPhysicsKeyParserDestroy( pParse ); - - return elementCount; -} - -bool RagdollGetBoneMatrix( const ragdoll_t &ragdoll, CBoneAccessor &pBoneToWorld, int objectIndex ) -{ - int boneIndex = ragdoll.boneIndex[objectIndex]; - if ( boneIndex < 0 ) - return false; - - const ragdollelement_t &element = ragdoll.list[objectIndex]; - - // during restore if a model has changed since the file was saved, this could be NULL - if ( !element.pObject ) - return false; - element.pObject->GetPositionMatrix( &pBoneToWorld.GetBoneForWrite( boneIndex ) ); - if ( element.parentIndex >= 0 && !ragdoll.allowStretch ) - { - // overwrite the position from physics to force rigid attachment - // UNDONE: If we support other types of constraints (or multiple constraints per object) - // make sure these don't fight ! - int parentBoneIndex = ragdoll.boneIndex[element.parentIndex]; - Vector out; - VectorTransform( element.originParentSpace, pBoneToWorld.GetBone( parentBoneIndex ), out ); - MatrixSetColumn( out, 3, pBoneToWorld.GetBoneForWrite( boneIndex ) ); - } - return true; -} - -void RagdollComputeExactBbox( const ragdoll_t &ragdoll, const Vector &origin, Vector &outMins, Vector &outMaxs ) -{ - outMins = origin; - outMaxs = origin; - - for ( int i = 0; i < ragdoll.listCount; i++ ) - { - Vector mins, maxs; - Vector objectOrg; - QAngle objectAng; - IPhysicsObject *pObject = ragdoll.list[i].pObject; - pObject->GetPosition( &objectOrg, &objectAng ); - physcollision->CollideGetAABB( &mins, &maxs, pObject->GetCollide(), objectOrg, objectAng ); - for ( int j = 0; j < 3; j++ ) - { - if ( mins[j] < outMins[j] ) - { - outMins[j] = mins[j]; - } - if ( maxs[j] > outMaxs[j] ) - { - outMaxs[j] = maxs[j]; - } - } - } -} - -bool RagdollIsAsleep( const ragdoll_t &ragdoll ) -{ - for ( int i = 0; i < ragdoll.listCount; i++ ) - { - if ( ragdoll.list[i].pObject && !ragdoll.list[i].pObject->IsAsleep() ) - return false; - } - - return true; -} - -void RagdollSolveSeparation( ragdoll_t &ragdoll, CBaseEntity *pEntity ) -{ - byte needsFix[256]; - int fixCount = 0; - Assert(ragdoll.listCount <= (int)ARRAYSIZE(needsFix)); - for ( int i = 0; i < ragdoll.listCount; i++ ) - { - needsFix[i] = 0; - const ragdollelement_t &element = ragdoll.list[i]; - if ( element.pConstraint && element.parentIndex >= 0 ) - { - Vector start, target; - element.pObject->GetPosition( &start, NULL ); - ragdoll.list[element.parentIndex].pObject->LocalToWorld( &target, element.originParentSpace ); - if ( needsFix[element.parentIndex] ) - { - needsFix[i] = 1; - ++fixCount; - continue; - } - Vector dir = target-start; - if ( dir.LengthSqr() > 1.0f ) - { - // this fixes a bug in ep2 with antlion grubs, but causes problems in TF2 - revisit, but disable for TF now -#if !defined(TF_CLIENT_DLL) - // heuristic: guess that anything separated and small mass ratio is in some state that's - // keeping the solver from fixing it - float mass = element.pObject->GetMass(); - float massParent = ragdoll.list[element.parentIndex].pObject->GetMass(); - - if ( mass*2.0f < massParent ) - { - // if this is <0.5 mass of parent and still separated it's attached to something heavy or - // in a bad state - needsFix[i] = 1; - ++fixCount; - continue; - } -#endif - - if ( PhysHasContactWithOtherInDirection(element.pObject, dir) ) - { - Ray_t ray; - trace_t tr; - ray.Init( target, start ); - UTIL_TraceRay( ray, MASK_SOLID, pEntity, COLLISION_GROUP_NONE, &tr ); - if ( tr.DidHit() ) - { - needsFix[i] = 1; - ++fixCount; - } - } - } - } - } - - if ( fixCount ) - { - for ( int i = 0; i < ragdoll.listCount; i++ ) - { - if ( !needsFix[i] ) - continue; - - const ragdollelement_t &element = ragdoll.list[i]; - Vector target, velocity; - ragdoll.list[element.parentIndex].pObject->LocalToWorld( &target, element.originParentSpace ); - ragdoll.list[element.parentIndex].pObject->GetVelocityAtPoint( target, &velocity ); - matrix3x4_t xform; - element.pObject->GetPositionMatrix( &xform ); - MatrixSetColumn( target, 3, xform ); - element.pObject->SetPositionMatrix( xform, true ); - element.pObject->SetVelocity( &velocity, &vec3_origin ); - } - DevMsg(2, "TICK:%5d:Ragdoll separation count: %d\n", gpGlobals->tickcount, fixCount ); - } - else - { - ragdoll.pGroup->ClearErrorState(); - } -} - -//----------------------------------------------------------------------------- -// LRU -//----------------------------------------------------------------------------- -#ifdef _XBOX -// xbox defaults to 4 ragdolls max -ConVar g_ragdoll_maxcount("g_ragdoll_maxcount", "4", FCVAR_REPLICATED ); -#else -ConVar g_ragdoll_maxcount("g_ragdoll_maxcount", "8", FCVAR_REPLICATED ); -#endif -ConVar g_debug_ragdoll_removal("g_debug_ragdoll_removal", "0", FCVAR_REPLICATED |FCVAR_CHEAT ); - -CRagdollLRURetirement s_RagdollLRU( "CRagdollLRURetirement" ); - -void CRagdollLRURetirement::LevelInitPreEntity( void ) -{ - m_iMaxRagdolls = -1; - m_LRUImportantRagdolls.RemoveAll(); - m_LRU.RemoveAll(); -} - -bool ShouldRemoveThisRagdoll( CBaseAnimating *pRagdoll ) -{ - if ( g_RagdollLVManager.IsLowViolence() ) - { - return true; - } - -#ifdef CLIENT_DLL - - /* we no longer ignore enemies just because they are on fire -- a ragdoll in front of me - is always a higher priority for retention than a flaming zombie behind me. At the - time I put this in, the ragdolls do clean up their own effects if culled via SUB_Remove(). - If you're encountering trouble with ragdolls leaving effects behind, try renabling the code below. - ///////////////////// - //Just ignore it until we're done burning/dissolving. - if ( pRagdoll->GetEffectEntity() ) - return false; - */ - - Vector vMins, vMaxs; - - Vector origin = pRagdoll->m_pRagdoll->GetRagdollOrigin(); - pRagdoll->m_pRagdoll->GetRagdollBounds( vMins, vMaxs ); - - if( engine->IsBoxInViewCluster( vMins + origin, vMaxs + origin) == false ) - { - if ( g_debug_ragdoll_removal.GetBool() ) - { - debugoverlay->AddBoxOverlay( origin, vMins, vMaxs, QAngle( 0, 0, 0 ), 0, 255, 0, 16, 5 ); - debugoverlay->AddLineOverlay( origin, origin + Vector( 0, 0, 64 ), 0, 255, 0, true, 5 ); - } - - return true; - } - else if( engine->CullBox( vMins + origin, vMaxs + origin ) == true ) - { - if ( g_debug_ragdoll_removal.GetBool() ) - { - debugoverlay->AddBoxOverlay( origin, vMins, vMaxs, QAngle( 0, 0, 0 ), 0, 0, 255, 16, 5 ); - debugoverlay->AddLineOverlay( origin, origin + Vector( 0, 0, 64 ), 0, 0, 255, true, 5 ); - } - - return true; - } - -#else - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - - if( !UTIL_FindClientInPVS( pRagdoll->edict() ) ) - { - if ( g_debug_ragdoll_removal.GetBool() ) - NDebugOverlay::Line( pRagdoll->GetAbsOrigin(), pRagdoll->GetAbsOrigin() + Vector( 0, 0, 64 ), 0, 255, 0, true, 5 ); - - return true; - } - else if( !pPlayer->FInViewCone( pRagdoll ) ) - { - if ( g_debug_ragdoll_removal.GetBool() ) - NDebugOverlay::Line( pRagdoll->GetAbsOrigin(), pRagdoll->GetAbsOrigin() + Vector( 0, 0, 64 ), 0, 0, 255, true, 5 ); - - return true; - } - -#endif - - return false; -} - - - - -//----------------------------------------------------------------------------- -// Cull stale ragdolls. There is an ifdef here: one version for episodic, -// one for everything else. -//----------------------------------------------------------------------------- -#if HL2_EPISODIC - -void CRagdollLRURetirement::Update( float frametime ) // EPISODIC VERSION -{ - VPROF( "CRagdollLRURetirement::Update" ); - // Compress out dead items - int i, next; - - int iMaxRagdollCount = m_iMaxRagdolls; - - if ( iMaxRagdollCount == -1 ) - { - iMaxRagdollCount = g_ragdoll_maxcount.GetInt(); - } - - // fade them all for the low violence version - if ( g_RagdollLVManager.IsLowViolence() ) - { - iMaxRagdollCount = 0; - } - m_iRagdollCount = 0; - m_iSimulatedRagdollCount = 0; - - // First, find ragdolls that are good candidates for deletion because they are not - // visible at all, or are in a culled visibility box - for ( i = m_LRU.Head(); i < m_LRU.InvalidIndex(); i = next ) - { - next = m_LRU.Next(i); - CBaseAnimating *pRagdoll = m_LRU[i].Get(); - if ( pRagdoll ) - { - m_iRagdollCount++; - IPhysicsObject *pObject = pRagdoll->VPhysicsGetObject(); - if (pObject && !pObject->IsAsleep()) - { - m_iSimulatedRagdollCount++; - } - if ( m_LRU.Count() > iMaxRagdollCount ) - { - //Found one, we're done. - if ( ShouldRemoveThisRagdoll( m_LRU[i] ) == true ) - { -#ifdef CLIENT_DLL - m_LRU[ i ]->SUB_Remove(); -#else - m_LRU[ i ]->SUB_StartFadeOut( 0 ); -#endif - - m_LRU.Remove(i); - return; - } - } - } - else - { - m_LRU.Remove(i); - } - } - - ////////////////////////////// - /// EPISODIC ALGORITHM /// - ////////////////////////////// - // If we get here, it means we couldn't find a suitable ragdoll to remove, - // so just remove the furthest one. - int furthestOne = m_LRU.Head(); - float furthestDistSq = 0; -#ifdef CLIENT_DLL - C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); -#else - CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); -#endif - - if (pPlayer && m_LRU.Count() > iMaxRagdollCount) // find the furthest one algorithm - { - Vector PlayerOrigin = pPlayer->GetAbsOrigin(); - // const CBasePlayer *pPlayer = UTIL_GetLocalPlayer(); - - for ( i = m_LRU.Head(); i < m_LRU.InvalidIndex(); i = next ) - { - CBaseAnimating *pRagdoll = m_LRU[i].Get(); - - next = m_LRU.Next(i); - IPhysicsObject *pObject = pRagdoll->VPhysicsGetObject(); - if ( pRagdoll && (pRagdoll->GetEffectEntity() || ( pObject && !pObject->IsAsleep()) ) ) - continue; - - if ( pRagdoll ) - { - // float distToPlayer = (pPlayer->GetAbsOrigin() - pRagdoll->GetAbsOrigin()).LengthSqr(); - float distToPlayer = (PlayerOrigin - pRagdoll->GetAbsOrigin()).LengthSqr(); - - if (distToPlayer > furthestDistSq) - { - furthestOne = i; - furthestDistSq = distToPlayer; - } - } - else // delete bad rags first. - { - furthestOne = i; - break; - } - } - -#ifdef CLIENT_DLL - m_LRU[ furthestOne ]->SUB_Remove(); -#else - m_LRU[ furthestOne ]->SUB_StartFadeOut( 0 ); -#endif - - } - else // fall back on old-style pick the oldest one algorithm - { - for ( i = m_LRU.Head(); i < m_LRU.InvalidIndex(); i = next ) - { - if ( m_LRU.Count() <= iMaxRagdollCount ) - break; - - next = m_LRU.Next(i); - - CBaseAnimating *pRagdoll = m_LRU[i].Get(); - - //Just ignore it until we're done burning/dissolving. - IPhysicsObject *pObject = pRagdoll->VPhysicsGetObject(); - if ( pRagdoll && (pRagdoll->GetEffectEntity() || ( pObject && !pObject->IsAsleep()) ) ) - continue; - - #ifdef CLIENT_DLL - m_LRU[ i ]->SUB_Remove(); - #else - m_LRU[ i ]->SUB_StartFadeOut( 0 ); - #endif - m_LRU.Remove(i); - } - } -} - -#else - -void CRagdollLRURetirement::Update( float frametime ) // Non-episodic version -{ - VPROF( "CRagdollLRURetirement::Update" ); - // Compress out dead items - int i, next; - - int iMaxRagdollCount = m_iMaxRagdolls; - - if ( iMaxRagdollCount == -1 ) - { - iMaxRagdollCount = g_ragdoll_maxcount.GetInt(); - } - - // fade them all for the low violence version - if ( g_RagdollLVManager.IsLowViolence() ) - { - iMaxRagdollCount = 0; - } - m_iRagdollCount = 0; - m_iSimulatedRagdollCount = 0; - - for ( i = m_LRU.Head(); i < m_LRU.InvalidIndex(); i = next ) - { - next = m_LRU.Next(i); - CBaseAnimating *pRagdoll = m_LRU[i].Get(); - if ( pRagdoll ) - { - m_iRagdollCount++; - IPhysicsObject *pObject = pRagdoll->VPhysicsGetObject(); - if (pObject && !pObject->IsAsleep()) - { - m_iSimulatedRagdollCount++; - } - if ( m_LRU.Count() > iMaxRagdollCount ) - { - //Found one, we're done. - if ( ShouldRemoveThisRagdoll( m_LRU[i] ) == true ) - { -#ifdef CLIENT_DLL - m_LRU[ i ]->SUB_Remove(); -#else - m_LRU[ i ]->SUB_StartFadeOut( 0 ); -#endif - - m_LRU.Remove(i); - return; - } - } - } - else - { - m_LRU.Remove(i); - } - } - - - ////////////////////////////// - /// ORIGINAL ALGORITHM /// - ////////////////////////////// - // not episodic -- this is the original mechanism - - for ( i = m_LRU.Head(); i < m_LRU.InvalidIndex(); i = next ) - { - if ( m_LRU.Count() <= iMaxRagdollCount ) - break; - - next = m_LRU.Next(i); - - CBaseAnimating *pRagdoll = m_LRU[i].Get(); - - //Just ignore it until we're done burning/dissolving. - if ( pRagdoll && pRagdoll->GetEffectEntity() ) - continue; - -#ifdef CLIENT_DLL - m_LRU[ i ]->SUB_Remove(); -#else - m_LRU[ i ]->SUB_StartFadeOut( 0 ); -#endif - m_LRU.Remove(i); - } -} - -#endif // HL2_EPISODIC - -//This is pretty hacky, it's only called on the server so it just calls the update method. -void CRagdollLRURetirement::FrameUpdatePostEntityThink( void ) -{ - Update( 0 ); -} - -ConVar g_ragdoll_important_maxcount( "g_ragdoll_important_maxcount", "2", FCVAR_REPLICATED ); - -//----------------------------------------------------------------------------- -// Move it to the top of the LRU -//----------------------------------------------------------------------------- -void CRagdollLRURetirement::MoveToTopOfLRU( CBaseAnimating *pRagdoll, bool bImportant ) -{ - if ( bImportant ) - { - m_LRUImportantRagdolls.AddToTail( pRagdoll ); - - if ( m_LRUImportantRagdolls.Count() > g_ragdoll_important_maxcount.GetInt() ) - { - int iIndex = m_LRUImportantRagdolls.Head(); - - CBaseAnimating *pRagdoll = m_LRUImportantRagdolls[iIndex].Get(); - - if ( pRagdoll ) - { -#ifdef CLIENT_DLL - pRagdoll->SUB_Remove(); -#else - pRagdoll->SUB_StartFadeOut( 0 ); -#endif - m_LRUImportantRagdolls.Remove(iIndex); - } - - } - return; - } - for ( int i = m_LRU.Head(); i < m_LRU.InvalidIndex(); i = m_LRU.Next(i) ) - { - if ( m_LRU[i].Get() == pRagdoll ) - { - m_LRU.Remove(i); - break; - } - } - - m_LRU.AddToTail( pRagdoll ); -} - - -//EFFECT/ENTITY TRANSFERS - -//CLIENT -#ifdef CLIENT_DLL - -#define DEFAULT_FADE_START 2.0f -#define DEFAULT_MODEL_FADE_START 1.9f -#define DEFAULT_MODEL_FADE_LENGTH 0.1f -#define DEFAULT_FADEIN_LENGTH 1.0f - - - -C_EntityDissolve *DissolveEffect( C_BaseAnimating *pTarget, float flTime ) -{ - C_EntityDissolve *pDissolve = new C_EntityDissolve; - - if ( pDissolve->InitializeAsClientEntity( "sprites/blueglow1.vmt", RENDER_GROUP_TRANSLUCENT_ENTITY ) == false ) - { - pDissolve->Release(); - return NULL; - } - - if ( pDissolve != NULL ) - { - pTarget->AddFlag( FL_DISSOLVING ); - pDissolve->SetParent( pTarget ); - pDissolve->OnDataChanged( DATA_UPDATE_CREATED ); - pDissolve->SetAbsOrigin( pTarget->GetAbsOrigin() ); - - pDissolve->m_flStartTime = flTime; - pDissolve->m_flFadeOutStart = DEFAULT_FADE_START; - pDissolve->m_flFadeOutModelStart = DEFAULT_MODEL_FADE_START; - pDissolve->m_flFadeOutModelLength = DEFAULT_MODEL_FADE_LENGTH; - pDissolve->m_flFadeInLength = DEFAULT_FADEIN_LENGTH; - - pDissolve->m_nDissolveType = 0; - pDissolve->m_flNextSparkTime = 0.0f; - pDissolve->m_flFadeOutLength = 0.0f; - pDissolve->m_flFadeInStart = 0.0f; - - // Let this entity know it needs to delete itself when it's done - pDissolve->SetServerLinkState( false ); - pTarget->SetEffectEntity( pDissolve ); - } - - return pDissolve; - -} - -C_EntityFlame *FireEffect( C_BaseAnimating *pTarget, C_BaseEntity *pServerFire, float *flScaleEnd, float *flTimeStart, float *flTimeEnd ) -{ - C_EntityFlame *pFire = new C_EntityFlame; - - if ( pFire->InitializeAsClientEntity( NULL, RENDER_GROUP_TRANSLUCENT_ENTITY ) == false ) - { - pFire->Release(); - return NULL; - } - - if ( pFire != NULL ) - { - pFire->RemoveFromLeafSystem(); - - pTarget->AddFlag( FL_ONFIRE ); - pFire->SetParent( pTarget ); - pFire->m_hEntAttached = (C_BaseEntity *) pTarget; - - pFire->OnDataChanged( DATA_UPDATE_CREATED ); - pFire->SetAbsOrigin( pTarget->GetAbsOrigin() ); - -#ifdef HL2_EPISODIC - if ( pServerFire ) - { - if ( pServerFire->IsEffectActive(EF_DIMLIGHT) ) - { - pFire->AddEffects( EF_DIMLIGHT ); - } - if ( pServerFire->IsEffectActive(EF_BRIGHTLIGHT) ) - { - pFire->AddEffects( EF_BRIGHTLIGHT ); - } - } -#endif - - //Play a sound - CPASAttenuationFilter filter( pTarget ); - pTarget->EmitSound( filter, pTarget->GetSoundSourceIndex(), "General.BurningFlesh" ); - - pFire->SetNextClientThink( gpGlobals->curtime + 7.0f ); - } - - return pFire; -} - -void C_BaseAnimating::IgniteRagdoll( C_BaseAnimating *pSource ) -{ - C_BaseEntity *pChild = pSource->GetEffectEntity(); - - if ( pChild ) - { - C_EntityFlame *pFireChild = dynamic_cast( pChild ); - C_ClientRagdoll *pRagdoll = dynamic_cast< C_ClientRagdoll * > ( this ); - - if ( pFireChild ) - { - pRagdoll->SetEffectEntity ( FireEffect( pRagdoll, pFireChild, NULL, NULL, NULL ) ); - } - } -} - - - -void C_BaseAnimating::TransferDissolveFrom( C_BaseAnimating *pSource ) -{ - C_BaseEntity *pChild = pSource->GetEffectEntity(); - - if ( pChild ) - { - C_EntityDissolve *pDissolveChild = dynamic_cast( pChild ); - - if ( pDissolveChild ) - { - C_ClientRagdoll *pRagdoll = dynamic_cast< C_ClientRagdoll * > ( this ); - - if ( pRagdoll ) - { - pRagdoll->m_flEffectTime = pDissolveChild->m_flStartTime; - - C_EntityDissolve *pDissolve = DissolveEffect( pRagdoll, pRagdoll->m_flEffectTime ); - - if ( pDissolve ) - { - pDissolve->SetRenderMode( pDissolveChild->GetRenderMode() ); - pDissolve->m_nRenderFX = pDissolveChild->m_nRenderFX; - pDissolve->SetRenderColor( 255, 255, 255, 255 ); - pDissolveChild->SetRenderColorA( 0 ); - - pDissolve->m_vDissolverOrigin = pDissolveChild->m_vDissolverOrigin; - pDissolve->m_nDissolveType = pDissolveChild->m_nDissolveType; - - if ( pDissolve->m_nDissolveType == ENTITY_DISSOLVE_CORE ) - { - pDissolve->m_nMagnitude = pDissolveChild->m_nMagnitude; - pDissolve->m_flFadeOutStart = CORE_DISSOLVE_FADE_START; - pDissolve->m_flFadeOutModelStart = CORE_DISSOLVE_MODEL_FADE_START; - pDissolve->m_flFadeOutModelLength = CORE_DISSOLVE_MODEL_FADE_LENGTH; - pDissolve->m_flFadeInLength = CORE_DISSOLVE_FADEIN_LENGTH; - } - } - } - } - } -} - -#endif - -//SERVER -#if !defined( CLIENT_DLL ) - -//----------------------------------------------------------------------------- -// Transfer dissolve -//----------------------------------------------------------------------------- -void CBaseAnimating::TransferDissolveFrom( CBaseAnimating *pAnim ) -{ - if ( !pAnim || !pAnim->IsDissolving() ) - return; - - CEntityDissolve *pDissolve = CEntityDissolve::Create( this, pAnim ); - if (pDissolve) - { - AddFlag( FL_DISSOLVING ); - m_flDissolveStartTime = pAnim->m_flDissolveStartTime; - - CEntityDissolve *pDissolveFrom = dynamic_cast < CEntityDissolve * > (pAnim->GetEffectEntity()); - - if ( pDissolveFrom ) - { - pDissolve->SetDissolverOrigin( pDissolveFrom->GetDissolverOrigin() ); - pDissolve->SetDissolveType( pDissolveFrom->GetDissolveType() ); - - if ( pDissolveFrom->GetDissolveType() == ENTITY_DISSOLVE_CORE ) - { - pDissolve->SetMagnitude( pDissolveFrom->GetMagnitude() ); - pDissolve->m_flFadeOutStart = CORE_DISSOLVE_FADE_START; - pDissolve->m_flFadeOutModelStart = CORE_DISSOLVE_MODEL_FADE_START; - pDissolve->m_flFadeOutModelLength = CORE_DISSOLVE_MODEL_FADE_LENGTH; - pDissolve->m_flFadeInLength = CORE_DISSOLVE_FADEIN_LENGTH; - } - } - } -} - -#endif diff --git a/game/shared/ragdoll_shared.h b/game/shared/ragdoll_shared.h deleted file mode 100644 index 52f6b2d24..000000000 --- a/game/shared/ragdoll_shared.h +++ /dev/null @@ -1,156 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef RAGDOLL_SHARED_H -#define RAGDOLL_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - -class IPhysicsObject; -class IPhysicsConstraint; -class IPhysicsConstraintGroup; -class IPhysicsCollision; -class IPhysicsEnvironment; -class IPhysicsSurfaceProps; -struct matrix3x4_t; - -struct vcollide_t; -struct studiohdr_t; -class CStudioHdr; -class CBoneAccessor; - -#include "mathlib/vector.h" -#include "bone_accessor.h" - -// UNDONE: Remove and make dynamic? -#define RAGDOLL_MAX_ELEMENTS 24 -#define RAGDOLL_INDEX_BITS 5 // NOTE 1<= RAGDOLL_MAX_ELEMENTS - -#define CORE_DISSOLVE_FADE_START 0.2f -#define CORE_DISSOLVE_MODEL_FADE_START 0.1f -#define CORE_DISSOLVE_MODEL_FADE_LENGTH 0.05f -#define CORE_DISSOLVE_FADEIN_LENGTH 0.1f - -struct ragdollelement_t -{ - Vector originParentSpace; - IPhysicsObject *pObject; // all valid elements have an object - IPhysicsConstraint *pConstraint; // all valid elements have a constraint (except the root) - int parentIndex; -}; - -struct ragdollanimatedfriction_t -{ - float flFrictionTimeIn; - float flFrictionTimeOut; - float flFrictionTimeHold; - int iMinAnimatedFriction; - int iMaxAnimatedFriction; -}; - -struct ragdoll_t -{ - int listCount; - bool allowStretch; - bool unused; - IPhysicsConstraintGroup *pGroup; - // store these in separate arrays for save/load - ragdollelement_t list[RAGDOLL_MAX_ELEMENTS]; - int boneIndex[RAGDOLL_MAX_ELEMENTS]; - ragdollanimatedfriction_t animfriction; -}; - -struct ragdollparams_t -{ - void *pGameData; - vcollide_t *pCollide; - CStudioHdr *pStudioHdr; - int modelIndex; - Vector forcePosition; - Vector forceVector; - int forceBoneIndex; - const matrix3x4_t *pCurrentBones; - float jointFrictionScale; - bool allowStretch; -}; - -//----------------------------------------------------------------------------- -// This hooks the main game systems callbacks to allow the AI system to manage memory -//----------------------------------------------------------------------------- -class CRagdollLRURetirement : public CAutoGameSystemPerFrame -{ -public: - CRagdollLRURetirement( char const *name ) : CAutoGameSystemPerFrame( name ) - { - } - - // Methods of IGameSystem - virtual void Update( float frametime ); - virtual void FrameUpdatePostEntityThink( void ); - - // Move it to the top of the LRU - void MoveToTopOfLRU( CBaseAnimating *pRagdoll, bool bImportant = false ); - void SetMaxRagdollCount( int iMaxCount ){ m_iMaxRagdolls = iMaxCount; } - - virtual void LevelInitPreEntity( void ); - int CountRagdolls( bool bOnlySimulatingRagdolls ) { return bOnlySimulatingRagdolls ? m_iSimulatedRagdollCount : m_iRagdollCount; } - -private: - typedef CHandle CRagdollHandle; - CUtlLinkedList< CRagdollHandle > m_LRU; - CUtlLinkedList< CRagdollHandle > m_LRUImportantRagdolls; - - int m_iMaxRagdolls; - int m_iSimulatedRagdollCount; - int m_iRagdollCount; -}; - -extern CRagdollLRURetirement s_RagdollLRU; - -// Manages ragdolls fading for the low violence versions -class CRagdollLowViolenceManager -{ -public: - CRagdollLowViolenceManager(){ m_bLowViolence = false; } - // Turn the low violence ragdoll stuff off if we're in the HL2 Citadel maps because - // the player has the super gravity gun and fading ragdolls will break things. - void SetLowViolence( const char *pMapName ); - bool IsLowViolence( void ){ return m_bLowViolence; } - -private: - bool m_bLowViolence; -}; - -extern CRagdollLowViolenceManager g_RagdollLVManager; - - -bool RagdollCreate( ragdoll_t &ragdoll, const ragdollparams_t ¶ms, IPhysicsEnvironment *pPhysEnv ); - -void RagdollActivate( ragdoll_t &ragdoll, vcollide_t *pCollide, int modelIndex, bool bForceWake = true ); -void RagdollSetupCollisions( ragdoll_t &ragdoll, vcollide_t *pCollide, int modelIndex ); -void RagdollDestroy( ragdoll_t &ragdoll ); - -// Gets the bone matrix for a ragdoll object -// NOTE: This is different than the object's position because it is -// forced to be rigidly attached in parent space -bool RagdollGetBoneMatrix( const ragdoll_t &ragdoll, CBoneAccessor &pBoneToWorld, int objectIndex ); - -// Parse the ragdoll and obtain the mapping from each physics element index to a bone index -// returns num phys elements -int RagdollExtractBoneIndices( int *boneIndexOut, CStudioHdr *pStudioHdr, vcollide_t *pCollide ); - -// computes an exact bbox of the ragdoll's physics objects -void RagdollComputeExactBbox( const ragdoll_t &ragdoll, const Vector &origin, Vector &outMins, Vector &outMaxs ); -bool RagdollIsAsleep( const ragdoll_t &ragdoll ); -void RagdollSetupAnimatedFriction( IPhysicsEnvironment *pPhysEnv, ragdoll_t *ragdoll, int iModelIndex ); - -void RagdollApplyAnimationAsVelocity( ragdoll_t &ragdoll, const matrix3x4_t *pBoneToWorld ); -void RagdollApplyAnimationAsVelocity( ragdoll_t &ragdoll, const matrix3x4_t *pPrevBones, const matrix3x4_t *pCurrentBones, float dt ); - -void RagdollSolveSeparation( ragdoll_t &ragdoll, CBaseEntity *pEntity ); - -#endif // RAGDOLL_SHARED_H diff --git a/game/shared/rope_helpers.cpp b/game/shared/rope_helpers.cpp deleted file mode 100644 index 6ba95a523..000000000 --- a/game/shared/rope_helpers.cpp +++ /dev/null @@ -1,140 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "rope_helpers.h" -#include "basetypes.h" -#include "mathlib/mathlib.h" -#include "rope_shared.h" -#include "rope_physics.h" -#include "networkvar.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CHangRope : public CRopePhysics<512> -{ -DECLARE_CLASS( CHangRope, CRopePhysics<512> ); - -// CRopePhysics overrides. -public: - - virtual void GetNodeForces( CSimplePhysics::CNode *pNodes, int iNode, Vector *pAccel ) - { - pAccel->Init( ROPE_GRAVITY ); - } - - - virtual void ApplyConstraints( CSimplePhysics::CNode *pNodes, int nNodes ) - { - // Apply spring forces. - BaseClass::ApplyConstraints( pNodes, nNodes ); - - - // Lock the endpoints. - pNodes[0].m_vPos = m_vEndPoints[0]; - pNodes[nNodes-1].m_vPos = m_vEndPoints[1]; - - - // Calculate how far it is hanging down and adjust if necessary. - float flCurHangDist = 0; - for ( int i=0; i < NumNodes(); i++ ) - { - float hang = fabs( m_flStartZ - GetNode(i)->m_vPos.z ); - if ( hang > flCurHangDist ) - flCurHangDist = hang; - } - - // Adjust our spring length accordingly. - if ( flCurHangDist < m_flWantedHangDist ) - m_flCurSlack += 1; - else - m_flCurSlack -= 1; - - ApplyNewSpringLength(); - } - - -// Helpers. -public: - - void ApplyNewSpringLength() - { - ResetSpringLength( (m_flRopeLength + m_flCurSlack + ROPESLACK_FUDGEFACTOR) / (NumNodes() - 1) ); - } - - -// Variables used to adjust the rope slack. -public: - - Vector m_vEndPoints[2]; - bool m_bAdjustSlack; - - float m_flRopeLength; - float m_flCurSlack; - - float m_flWantedHangDist; - float m_flStartZ; - -}; - - - -void CalcRopeStartingConditions( - const Vector &vStartPos, - const Vector &vEndPos, - int const nNodes, - float const desiredHang, - float *pOutputLength, - float *pOutputSlack - ) -{ - CHangRope rope; - - // Initialize the rope as a straight line with no slack as our first approximation. - // We then relax the rope by adding slack until it hangs to the desired height. - // - // The spring length equation is: - // springLength = (ropeLength + slack + ROPESLACK_FUDGEFACTOR) / (nNodes - 1) - // - // We want our rope to be a straight line, so: - // springLength = ropeLength / (nNodes-1) - // - // Therefore our initial slack is -ROPESLACK_FUDGEFACTOR - rope.m_flCurSlack = -ROPESLACK_FUDGEFACTOR; - - rope.m_vEndPoints[0] = vStartPos; - rope.m_vEndPoints[1] = vEndPos; - - rope.m_flRopeLength = (vEndPos - vStartPos).Length(); - rope.m_flWantedHangDist = desiredHang; - - rope.m_flStartZ = MIN( vStartPos.z, vEndPos.z ); // Calculate hang as the Z distance from the - // lowest endpoint to the bottom of the rope. - - rope.SetNumNodes( nNodes ); - - // Set the node positions. - for ( int i=0; i < rope.NumNodes(); i++ ) - { - CSimplePhysics::CNode *pNode = rope.GetNode( i ); - - float t = (float)i / (rope.NumNodes() - 1); - VectorLerp( vStartPos, vEndPos, t, pNode->m_vPos ); - pNode->m_vPrevPos = pNode->m_vPos; - } - - // Now simulate a little and stretch out to let it hang down. - rope.Restart(); - rope.Simulate( 3 ); - - // Set outputs. - *pOutputLength = rope.m_flRopeLength; - *pOutputSlack = rope.m_flCurSlack; -} - - diff --git a/game/shared/rope_helpers.h b/game/shared/rope_helpers.h deleted file mode 100644 index fb04e1e84..000000000 --- a/game/shared/rope_helpers.h +++ /dev/null @@ -1,42 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ROPE_HELPERS_H -#define ROPE_HELPERS_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "mathlib/vector.h" - - -// -// This function can help you choose starting conditions for your rope. It is fairly -// expensive (slightly less than 0.5ms for a 10-node rope), but it's within reason for the -// frequency we create ropes at. -// -// Input: -// - rope endpoints -// - the number of nodes the client will be simulating (CRopeKeyframe::m_nSegments) -// - how low you want the rope to hang (below the lowest of the two endpoints) -// -// Output: -// - pOutputLength = length of the rope -// - pOutputSlack = slack you should set to produce the desired hang -// -void CalcRopeStartingConditions( - const Vector &vStartPos, - const Vector &vEndPos, - int const nNodes, - float const desiredHang, - float *pOutputLength, - float *pOutputSlack - ); - - -#endif // ROPE_HELPERS_H diff --git a/game/shared/rumble_shared.h b/game/shared/rumble_shared.h deleted file mode 100644 index 2b0c9779f..000000000 --- a/game/shared/rumble_shared.h +++ /dev/null @@ -1,73 +0,0 @@ -//======= Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: Shared code for XBox Rumble Effects -// -// $NoKeywords: $ -// -//=============================================================================// -#pragma once -#ifndef RUMBLE_SHARED_H -#define RUMBLE_SHARED_H - -#define RUMBLE_FLAGS_NONE 0x0000 -#define RUMBLE_FLAG_STOP 0x0001 // Stop any instance of this type of effect that's already playing. -#define RUMBLE_FLAG_LOOP 0x0002 // Make this effect loop. -#define RUMBLE_FLAG_RESTART 0x0004 // If this effect is already playing, restart it. -#define RUMBLE_FLAG_UPDATE_SCALE 0x0008 // Apply DATA to this effect if already playing, but don't restart. -#define RUMBLE_FLAG_ONLYONE 0x0010 // Don't play this effect if it is already playing. -#define RUMBLE_FLAG_RANDOM_AMPLITUDE 0x0020 // Amplitude scale will be randomly chosen. Between 10% and 100% -#define RUMBLE_FLAG_INITIAL_SCALE 0x0040 // Data is the initial scale to start this effect ( * 100 ) - -enum -{ -// DO NOT CHANGE THE ORDER OF ANY OF THESE ENUMS -// DO NOT INSERT ANY ITEMS - RUMBLE_INVALID = -1, - - RUMBLE_STOP_ALL = 0, // Cease all current rumbling effects. - - // Weapons - RUMBLE_PISTOL, - RUMBLE_357, - RUMBLE_SMG1, - RUMBLE_AR2, - RUMBLE_SHOTGUN_SINGLE, - RUMBLE_SHOTGUN_DOUBLE, - RUMBLE_AR2_ALT_FIRE, - -// YOU MAY INSERT/REARRANGE ITEMS FROM HERE DOWN, AS YOU SEE FIT - RUMBLE_RPG_MISSILE, - - RUMBLE_CROWBAR_SWING, - - // Vehicles - RUMBLE_AIRBOAT_GUN, - RUMBLE_JEEP_ENGINE_LOOP, - - RUMBLE_FLAT_LEFT, - RUMBLE_FLAT_RIGHT, - RUMBLE_FLAT_BOTH, - - // Damage - RUMBLE_DMG_LOW, - RUMBLE_DMG_MED, - RUMBLE_DMG_HIGH, - - // Fall damage - RUMBLE_FALL_LONG, - RUMBLE_FALL_SHORT, - - RUMBLE_PHYSCANNON_OPEN, - RUMBLE_PHYSCANNON_PUNT, - RUMBLE_PHYSCANNON_LOW, - RUMBLE_PHYSCANNON_MEDIUM, - RUMBLE_PHYSCANNON_HIGH, - - RUMBLE_PORTALGUN_LEFT, - RUMBLE_PORTALGUN_RIGHT, - RUMBLE_PORTAL_PLACEMENT_FAILURE, - - NUM_RUMBLE_EFFECTS, // THIS MUST BE LAST!!! -}; - -#endif//RUMBLE_SHARED_H diff --git a/game/shared/saverestore.cpp b/game/shared/saverestore.cpp deleted file mode 100644 index 66034a7eb..000000000 --- a/game/shared/saverestore.cpp +++ /dev/null @@ -1,3428 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Helper classes and functions for the save/restore system. -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include -#include "isaverestore.h" -#include "saverestore.h" -#include -#include "shake.h" -#include "decals.h" -#include "gamerules.h" -#include "bspfile.h" -#include "mathlib/mathlib.h" -#include "engine/IEngineSound.h" -#include "saverestoretypes.h" -#include "saverestore_utlvector.h" -#include "model_types.h" -#include "igamesystem.h" -#include "interval.h" -#include "vphysics/object_hash.h" -#include "datacache/imdlcache.h" -#include "tier0/vprof.h" - -#if !defined( CLIENT_DLL ) - -#include "globalstate.h" -#include "entitylist.h" - -#else - -#include "gamestringpool.h" - -#endif - -// HACKHACK: Builds a global list of entities that were restored from all levels -#if !defined( CLIENT_DLL ) -void AddRestoredEntity( CBaseEntity *pEntity ); -#else -void AddRestoredEntity( C_BaseEntity *pEntity ); -#endif - - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define MAX_ENTITYARRAY 1024 -#define ZERO_TIME ((FLT_MAX*-0.5)) -// A bit arbitrary, but unlikely to collide with any saved games... -#define TICK_NEVER_THINK_ENCODE ( INT_MAX - 3 ) - -ASSERT_INVARIANT( sizeof(EHandlePlaceholder_t) == sizeof(EHANDLE) ); - -//----------------------------------------------------------------------------- - -static int gSizes[FIELD_TYPECOUNT] = -{ - FIELD_SIZE( FIELD_VOID ), - FIELD_SIZE( FIELD_FLOAT ), - FIELD_SIZE( FIELD_STRING ), - FIELD_SIZE( FIELD_VECTOR ), - FIELD_SIZE( FIELD_QUATERNION ), - FIELD_SIZE( FIELD_INTEGER ), - FIELD_SIZE( FIELD_BOOLEAN ), - FIELD_SIZE( FIELD_SHORT ), - FIELD_SIZE( FIELD_CHARACTER ), - FIELD_SIZE( FIELD_COLOR32 ), - FIELD_SIZE( FIELD_EMBEDDED ), - FIELD_SIZE( FIELD_CUSTOM ), - - FIELD_SIZE( FIELD_CLASSPTR ), - FIELD_SIZE( FIELD_EHANDLE ), - FIELD_SIZE( FIELD_EDICT ), - - FIELD_SIZE( FIELD_POSITION_VECTOR ), - FIELD_SIZE( FIELD_TIME ), - FIELD_SIZE( FIELD_TICK ), - FIELD_SIZE( FIELD_MODELNAME ), - FIELD_SIZE( FIELD_SOUNDNAME ), - - FIELD_SIZE( FIELD_INPUT ), - FIELD_SIZE( FIELD_FUNCTION ), - FIELD_SIZE( FIELD_VMATRIX ), - FIELD_SIZE( FIELD_VMATRIX_WORLDSPACE ), - FIELD_SIZE( FIELD_MATRIX3X4_WORLDSPACE ), - FIELD_SIZE( FIELD_INTERVAL ), - FIELD_SIZE( FIELD_MODELINDEX ), - FIELD_SIZE( FIELD_MATERIALINDEX ), - - FIELD_SIZE( FIELD_VECTOR2D ), -}; - - -// helpers to offset worldspace matrices -static void VMatrixOffset( VMatrix &dest, const VMatrix &matrixIn, const Vector &offset ) -{ - dest = matrixIn; - dest.PostTranslate( offset ); -} - -static void Matrix3x4Offset( matrix3x4_t& dest, const matrix3x4_t& matrixIn, const Vector &offset ) -{ - MatrixCopy( matrixIn, dest ); - Vector out; - MatrixGetColumn( matrixIn, 3, out ); - out += offset; - MatrixSetColumn( out, 3, dest ); -} - -// This does the necessary casting / extract to grab a pointer to a member function as a void * -// UNDONE: Cast to BASEPTR or something else here? -#define EXTRACT_VOID_FUNCTIONPTR(x) (*(void **)(&(x))) -//----------------------------------------------------------------------------- -// Purpose: Search this datamap for the name of this member function -// This is used to save/restore function pointers (convert pointer to text) -// Input : *function - pointer to member function -// Output : const char * - function name -//----------------------------------------------------------------------------- -const char *UTIL_FunctionToName( datamap_t *pMap, void *function ) -{ - while ( pMap ) - { - for ( int i = 0; i < pMap->dataNumFields; i++ ) - { - if ( pMap->dataDesc[i].flags & FTYPEDESC_FUNCTIONTABLE ) - { - Assert( sizeof(pMap->dataDesc[i].inputFunc) == sizeof(void *) ); - void *pTest = EXTRACT_VOID_FUNCTIONPTR(pMap->dataDesc[i].inputFunc); - if ( pTest == function ) - return pMap->dataDesc[i].fieldName; - } - } - pMap = pMap->baseMap; - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Search the datamap for a function named pName -// This is used to save/restore function pointers (convert text back to pointer) -// Input : *pName - name of the member function -//----------------------------------------------------------------------------- -void *UTIL_FunctionFromName( datamap_t *pMap, const char *pName ) -{ - while ( pMap ) - { - for ( int i = 0; i < pMap->dataNumFields; i++ ) - { - Assert( sizeof(pMap->dataDesc[i].inputFunc) == sizeof(void *) ); - - if ( pMap->dataDesc[i].flags & FTYPEDESC_FUNCTIONTABLE ) - { - if ( FStrEq( pName, pMap->dataDesc[i].fieldName ) ) - { - return EXTRACT_VOID_FUNCTIONPTR(pMap->dataDesc[i].inputFunc); - } - } - } - pMap = pMap->baseMap; - } - - Msg( "Failed to find function %s\n", pName ); - - return NULL; -} - -//----------------------------------------------------------------------------- -// -// CSave -// -//----------------------------------------------------------------------------- - -CSave::CSave( CSaveRestoreData *pdata ) - : m_pData(pdata), - m_pGameInfo( pdata ), - m_bAsync( pdata->bAsync ) -{ - m_BlockStartStack.EnsureCapacity( 32 ); - - // Logging. - m_hLogFile = NULL; -} - -//------------------------------------- - -inline int CSave::DataEmpty( const char *pdata, int size ) -{ - if ( size != 4 ) - { - const char *pLimit = pdata + size; - while ( pdata < pLimit ) - { - if ( *pdata++ ) - return 0; - } - return 1; - } - - return ( *((int *)pdata) == 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: Start logging save data. -//----------------------------------------------------------------------------- -void CSave::StartLogging( const char *pszLogName ) -{ - m_hLogFile = filesystem->Open( pszLogName, "w" ); -} - -//----------------------------------------------------------------------------- -// Purpose: Stop logging save data. -//----------------------------------------------------------------------------- -void CSave::EndLogging( void ) -{ - if ( m_hLogFile ) - { - filesystem->Close( m_hLogFile ); - } - m_hLogFile = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Check to see if we are logging data. -//----------------------------------------------------------------------------- -bool CSave::IsLogging( void ) -{ - return ( m_hLogFile != NULL ); -} - -//----------------------------------------------------------------------------- -// Purpose: Log data. -//----------------------------------------------------------------------------- -void CSave::Log( const char *pName, fieldtype_t fieldType, void *value, int count ) -{ - // Check to see if we are logging. - if ( !IsLogging() ) - return; - - static char szBuf[1024]; - static char szTempBuf[256]; - - // Save the name. - Q_snprintf( szBuf, sizeof( szBuf ), "%s ", pName ); - - for ( int iCount = 0; iCount < count; ++iCount ) - { - switch ( fieldType ) - { - case FIELD_SHORT: - { - short *pValue = ( short* )( value ); - short nValue = pValue[iCount]; - Q_snprintf( szTempBuf, sizeof( szTempBuf ), "%d", nValue ); - Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS ); - break; - } - case FIELD_FLOAT: - { - float *pValue = ( float* )( value ); - float flValue = pValue[iCount]; - Q_snprintf( szTempBuf, sizeof( szTempBuf ), "%f", flValue ); - Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS ); - break; - } - case FIELD_BOOLEAN: - { - bool *pValue = ( bool* )( value ); - bool bValue = pValue[iCount]; - Q_snprintf( szTempBuf, sizeof( szTempBuf ), "%d", ( int )( bValue ) ); - Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS ); - break; - } - case FIELD_INTEGER: - { - int *pValue = ( int* )( value ); - int nValue = pValue[iCount]; - Q_snprintf( szTempBuf, sizeof( szTempBuf ), "%d", nValue ); - Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS ); - break; - } - case FIELD_STRING: - { - string_t *pValue = ( string_t* )( value ); - Q_snprintf( szTempBuf, sizeof( szTempBuf ), "%s", ( char* )STRING( *pValue ) ); - Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS ); - break; - } - case FIELD_VECTOR: - { - Vector *pValue = ( Vector* )( value ); - Vector vecValue = pValue[iCount]; - Q_snprintf( szTempBuf, sizeof( szTempBuf ), "(%f %f %f)", vecValue.x, vecValue.y, vecValue.z ); - Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS ); - break; - } - case FIELD_QUATERNION: - { - Quaternion *pValue = ( Quaternion* )( value ); - Quaternion q = pValue[iCount]; - Q_snprintf( szTempBuf, sizeof( szTempBuf ), "(%f %f %f %f)", q[0], q[1], q[2], q[3] ); - Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS ); - break; - } - case FIELD_CHARACTER: - { - char *pValue = ( char* )( value ); - char chValue = pValue[iCount]; - Q_snprintf( szTempBuf, sizeof( szTempBuf ), "%c", chValue ); - Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS ); - } - case FIELD_COLOR32: - { - byte *pValue = ( byte* )( value ); - byte *pColor = &pValue[iCount*4]; - Q_snprintf( szTempBuf, sizeof( szTempBuf ), "(%d %d %d %d)", ( int )pColor[0], ( int )pColor[1], ( int )pColor[2], ( int )pColor[3] ); - Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS ); - } - case FIELD_EMBEDDED: - case FIELD_CUSTOM: - default: - { - break; - } - } - - // Add space data. - if ( ( iCount + 1 ) != count ) - { - Q_strncpy( szTempBuf, " ", sizeof( szTempBuf ) ); - Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS ); - } - else - { - Q_strncpy( szTempBuf, "\n", sizeof( szTempBuf ) ); - Q_strncat( szBuf, szTempBuf, sizeof( szTempBuf ), COPY_ALL_CHARACTERS ); - } - } - - int nLength = strlen( szBuf ) + 1; - filesystem->Write( szBuf, nLength, m_hLogFile ); -} - -//------------------------------------- - -bool CSave::IsAsync() -{ - return m_bAsync; -} - -//------------------------------------- - -int CSave::GetWritePos() const -{ - return m_pData->GetCurPos(); -} - -//------------------------------------- - -void CSave::SetWritePos(int pos) -{ - m_pData->Seek(pos); -} - -//------------------------------------- - -void CSave::WriteShort( const short *value, int count ) -{ - BufferData( (const char *)value, sizeof(short) * count ); -} - -//------------------------------------- - -void CSave::WriteInt( const int *value, int count ) -{ - BufferData( (const char *)value, sizeof(int) * count ); -} - -//------------------------------------- - -void CSave::WriteBool( const bool *value, int count ) -{ - COMPILE_TIME_ASSERT( sizeof(bool) == sizeof(char) ); - BufferData( (const char *)value, sizeof(bool) * count ); -} - -//------------------------------------- - -void CSave::WriteFloat( const float *value, int count ) -{ - BufferData( (const char *)value, sizeof(float) * count ); -} - -//------------------------------------- - -void CSave::WriteData( const char *pdata , int size ) -{ - BufferData( pdata, size ); -} - -//------------------------------------- - -void CSave::WriteString( const char *pstring ) -{ - BufferData( pstring, strlen(pstring) + 1 ); -} - -//------------------------------------- - -void CSave::WriteString( const string_t *stringId, int count ) -{ - for ( int i = 0; i < count; i++ ) - { - const char *pString = STRING(stringId[i]); - BufferData( pString, strlen(pString)+1 ); - } -} - -//------------------------------------- - -void CSave::WriteVector( const Vector &value ) -{ - BufferData( (const char *)&value, sizeof(Vector) ); -} - -//------------------------------------- - -void CSave::WriteVector( const Vector *value, int count ) -{ - BufferData( (const char *)value, sizeof(Vector) * count ); -} - -void CSave::WriteQuaternion( const Quaternion &value ) -{ - BufferData( (const char *)&value, sizeof(Quaternion) ); -} - -//------------------------------------- - -void CSave::WriteQuaternion( const Quaternion *value, int count ) -{ - BufferData( (const char *)value, sizeof(Quaternion) * count ); -} - - -//------------------------------------- - -void CSave::WriteData( const char *pname, int size, const char *pdata ) -{ - BufferField( pname, size, pdata ); -} - -//------------------------------------- - -void CSave::WriteShort( const char *pname, const short *data, int count ) -{ - BufferField( pname, sizeof(short) * count, (const char *)data ); -} - -//------------------------------------- - -void CSave::WriteInt( const char *pname, const int *data, int count ) -{ - BufferField( pname, sizeof(int) * count, (const char *)data ); -} - -//------------------------------------- - -void CSave::WriteBool( const char *pname, const bool *data, int count ) -{ - COMPILE_TIME_ASSERT( sizeof(bool) == sizeof(char) ); - BufferField( pname, sizeof(bool) * count, (const char *)data ); -} - -//------------------------------------- - -void CSave::WriteFloat( const char *pname, const float *data, int count ) -{ - BufferField( pname, sizeof(float) * count, (const char *)data ); -} - -//------------------------------------- - -void CSave::WriteString( const char *pname, const char *pdata ) -{ - BufferField( pname, strlen(pdata) + 1, pdata ); -} - -//------------------------------------- - -void CSave::WriteString( const char *pname, const string_t *stringId, int count ) -{ - int i, size; - - size = 0; - for ( i = 0; i < count; i++ ) - size += strlen( STRING( stringId[i] ) ) + 1; - - WriteHeader( pname, size ); - WriteString( stringId, count ); -} - -//------------------------------------- - -void CSave::WriteVector( const char *pname, const Vector &value ) -{ - WriteVector( pname, &value, 1 ); -} - -//------------------------------------- - -void CSave::WriteVector( const char *pname, const Vector *value, int count ) -{ - WriteHeader( pname, sizeof(Vector) * count ); - BufferData( (const char *)value, sizeof(Vector) * count ); -} - -void CSave::WriteQuaternion( const char *pname, const Quaternion &value ) -{ - WriteQuaternion( pname, &value, 1 ); -} - -//------------------------------------- - -void CSave::WriteQuaternion( const char *pname, const Quaternion *value, int count ) -{ - WriteHeader( pname, sizeof(Quaternion) * count ); - BufferData( (const char *)value, sizeof(Quaternion) * count ); -} - - -//------------------------------------- - -void CSave::WriteVMatrix( const VMatrix *value, int count ) -{ - BufferData( (const char *)value, sizeof(VMatrix) * count ); -} - -//------------------------------------- - -void CSave::WriteVMatrix( const char *pname, const VMatrix *value, int count ) -{ - WriteHeader( pname, sizeof(VMatrix) * count ); - BufferData( (const char *)value, sizeof(VMatrix) * count ); -} - -//------------------------------------- - -void CSave::WriteVMatrixWorldspace( const VMatrix *value, int count ) -{ - for ( int i = 0; i < count; i++ ) - { - VMatrix tmp; - VMatrixOffset( tmp, value[i], -m_pGameInfo->GetLandmark() ); - BufferData( (const char *)&tmp, sizeof(VMatrix) ); - } -} - -//------------------------------------- - -void CSave::WriteVMatrixWorldspace( const char *pname, const VMatrix *value, int count ) -{ - WriteHeader( pname, sizeof(VMatrix) * count ); - WriteVMatrixWorldspace( value, count ); -} - -void CSave::WriteMatrix3x4Worldspace( const matrix3x4_t *value, int count ) -{ - Vector offset = -m_pGameInfo->GetLandmark(); - for ( int i = 0; i < count; i++ ) - { - matrix3x4_t tmp; - Matrix3x4Offset( tmp, value[i], offset ); - BufferData( (const char *)value, sizeof(matrix3x4_t) ); - } -} - -//------------------------------------- - -void CSave::WriteMatrix3x4Worldspace( const char *pname, const matrix3x4_t *value, int count ) -{ - WriteHeader( pname, sizeof(matrix3x4_t) * count ); - WriteMatrix3x4Worldspace( value, count ); -} - -void CSave::WriteInterval( const char *pname, const interval_t *value, int count ) -{ - WriteHeader( pname, sizeof( interval_t ) * count ); - WriteInterval( value, count ); -} - -void CSave::WriteInterval( const interval_t *value, int count ) -{ - BufferData( (const char *)value, count * sizeof( interval_t ) ); -} - -//------------------------------------- - -bool CSave::ShouldSaveField( const void *pData, typedescription_t *pField ) -{ - if ( !(pField->flags & FTYPEDESC_SAVE) || pField->fieldType == FIELD_VOID ) - return false; - - switch ( pField->fieldType ) - { - case FIELD_EMBEDDED: - { - if ( pField->flags & FTYPEDESC_PTR ) - { - AssertMsg( pField->fieldSize == 1, "Arrays of embedded pointer types presently unsupported by save/restore" ); - if ( pField->fieldSize != 1 ) - return false; - } - - AssertMsg( pField->td != NULL, "Embedded type appears to have not had type description implemented" ); - if ( pField->td == NULL ) - return false; - - if ( (pField->flags & FTYPEDESC_PTR) && !*((void **)pData) ) - return false; - - // @TODO: need real logic for handling embedded types with base classes - if ( pField->td->baseMap ) - { - return true; - } - - int nFieldCount = pField->fieldSize; - char *pTestData = (char *)( ( !(pField->flags & FTYPEDESC_PTR) ) ? pData : *((void **)pData) ); - while ( --nFieldCount >= 0 ) - { - typedescription_t *pTestField = pField->td->dataDesc; - typedescription_t *pLimit = pField->td->dataDesc + pField->td->dataNumFields; - - for ( ; pTestField < pLimit; ++pTestField ) - { - if ( ShouldSaveField( pTestData + pTestField->fieldOffset[ TD_OFFSET_NORMAL ], pTestField ) ) - return true; - } - - pTestData += pField->fieldSizeInBytes; - } - return false; - } - - case FIELD_CUSTOM: - { - // ask the data if it's empty - SaveRestoreFieldInfo_t fieldInfo = - { - const_cast(pData), - ((char *)pData) - pField->fieldOffset[ TD_OFFSET_NORMAL ], - pField - }; - if ( pField->pSaveRestoreOps->IsEmpty( fieldInfo ) ) - return false; - } - return true; - - case FIELD_EHANDLE: - { - if ( (pField->fieldSizeInBytes != pField->fieldSize * gSizes[pField->fieldType]) ) - { - Warning("WARNING! Field %s is using the wrong FIELD_ type!\nFix this or you'll see a crash.\n", pField->fieldName ); - Assert( 0 ); - } - - int *pEHandle = (int *)pData; - for ( int i = 0; i < pField->fieldSize; ++i, ++pEHandle ) - { - if ( (*pEHandle) != (int)0xFFFFFFFF ) - return true; - } - } - return false; - - default: - { - if ( (pField->fieldSizeInBytes != pField->fieldSize * gSizes[pField->fieldType]) ) - { - Warning("WARNING! Field %s is using the wrong FIELD_ type!\nFix this or you'll see a crash.\n", pField->fieldName ); - Assert( 0 ); - } - - // old byte-by-byte null check - if ( DataEmpty( (const char *)pData, pField->fieldSize * gSizes[pField->fieldType] ) ) - return false; - } - return true; - } -} - -//------------------------------------- -// Purpose: Writes all the fields that are client neutral. In the event of -// a librarization of save/restore, these would reside in the library -// - -bool CSave::WriteBasicField( const char *pname, void *pData, datamap_t *pRootMap, typedescription_t *pField ) -{ - switch( pField->fieldType ) - { - case FIELD_FLOAT: - WriteFloat( pField->fieldName, (float *)pData, pField->fieldSize ); - break; - - case FIELD_STRING: - WriteString( pField->fieldName, (string_t *)pData, pField->fieldSize ); - break; - - case FIELD_VECTOR: - WriteVector( pField->fieldName, (Vector *)pData, pField->fieldSize ); - break; - - case FIELD_QUATERNION: - WriteQuaternion( pField->fieldName, (Quaternion *)pData, pField->fieldSize ); - break; - - case FIELD_INTEGER: - WriteInt( pField->fieldName, (int *)pData, pField->fieldSize ); - break; - - case FIELD_BOOLEAN: - WriteBool( pField->fieldName, (bool *)pData, pField->fieldSize ); - break; - - case FIELD_SHORT: - WriteData( pField->fieldName, 2 * pField->fieldSize, ((char *)pData) ); - break; - - case FIELD_CHARACTER: - WriteData( pField->fieldName, pField->fieldSize, ((char *)pData) ); - break; - - case FIELD_COLOR32: - WriteData( pField->fieldName, 4*pField->fieldSize, (char *)pData ); - break; - - case FIELD_EMBEDDED: - { - AssertMsg( ( (pField->flags & FTYPEDESC_PTR) == 0 ) || (pField->fieldSize == 1), "Arrays of embedded pointer types presently unsupported by save/restore" ); - Assert( !(pField->flags & FTYPEDESC_PTR) || *((void **)pData) ); - int nFieldCount = pField->fieldSize; - char *pFieldData = (char *)( ( !(pField->flags & FTYPEDESC_PTR) ) ? pData : *((void **)pData) ); - - StartBlock( pField->fieldName ); - - while ( --nFieldCount >= 0 ) - { - WriteAll( pFieldData, pField->td ); - pFieldData += pField->fieldSizeInBytes; - } - - EndBlock(); - break; - } - - case FIELD_CUSTOM: - { - // Note it is up to the custom type implementor to handle arrays - StartBlock( pField->fieldName ); - - SaveRestoreFieldInfo_t fieldInfo = - { - pData, - ((char *)pData) - pField->fieldOffset[ TD_OFFSET_NORMAL ], - pField - }; - pField->pSaveRestoreOps->Save( fieldInfo, this ); - - EndBlock(); - break; - } - - default: - Warning( "Bad field type\n" ); - Assert(0); - return false; - } - - return true; -} - -//------------------------------------- - -bool CSave::WriteField( const char *pname, void *pData, datamap_t *pRootMap, typedescription_t *pField ) -{ -#ifdef _DEBUG - Log( pname, (fieldtype_t)pField->fieldType, pData, pField->fieldSize ); -#endif - - if ( pField->fieldType <= FIELD_CUSTOM ) - { - return WriteBasicField( pname, pData, pRootMap, pField ); - } - return WriteGameField( pname, pData, pRootMap, pField ); -} - -//------------------------------------- - -int CSave::WriteFields( const char *pname, const void *pBaseData, datamap_t *pRootMap, typedescription_t *pFields, int fieldCount ) -{ - typedescription_t *pTest; - int iHeaderPos = m_pData->GetCurPos(); - int count = -1; - WriteInt( pname, &count, 1 ); - - count = 0; - -#ifdef _X360 - __dcbt( 0, pBaseData ); - __dcbt( 128, pBaseData ); - __dcbt( 256, pBaseData ); - __dcbt( 512, pBaseData ); - void *pDest = m_pData->AccessCurPos(); - __dcbt( 0, pDest ); - __dcbt( 128, pDest ); - __dcbt( 256, pDest ); - __dcbt( 512, pDest ); -#endif - - for ( int i = 0; i < fieldCount; i++ ) - { - pTest = &pFields[ i ]; - void *pOutputData = ( (char *)pBaseData + pTest->fieldOffset[ TD_OFFSET_NORMAL ] ); - - if ( !ShouldSaveField( pOutputData, pTest ) ) - continue; - - if ( !WriteField( pname, pOutputData, pRootMap, pTest ) ) - break; - count++; - } - - int iCurPos = m_pData->GetCurPos(); - int iRewind = iCurPos - iHeaderPos; - m_pData->Rewind( iRewind ); - WriteInt( pname, &count, 1 ); - iCurPos = m_pData->GetCurPos(); - m_pData->MoveCurPos( iRewind - ( iCurPos - iHeaderPos ) ); - - return 1; -} - -//------------------------------------- -// Purpose: Recursively saves all the classes in an object, in reverse order (top down) -// Output : int 0 on failure, 1 on success - -int CSave::DoWriteAll( const void *pLeafObject, datamap_t *pLeafMap, datamap_t *pCurMap ) -{ - // save base classes first - if ( pCurMap->baseMap ) - { - int status = DoWriteAll( pLeafObject, pLeafMap, pCurMap->baseMap ); - if ( !status ) - return status; - } - - return WriteFields( pCurMap->dataClassName, pLeafObject, pLeafMap, pCurMap->dataDesc, pCurMap->dataNumFields ); -} - -//------------------------------------- - -void CSave::StartBlock( const char *pszBlockName ) -{ - WriteHeader( pszBlockName, 0 ); // placeholder - m_BlockStartStack.AddToTail( GetWritePos() ); -} - -//------------------------------------- - -void CSave::StartBlock() -{ - StartBlock( "" ); -} - -//------------------------------------- - -void CSave::EndBlock() -{ - int endPos = GetWritePos(); - int startPos = m_BlockStartStack[ m_BlockStartStack.Count() - 1 ]; - short sizeBlock = endPos - startPos; - - m_BlockStartStack.Remove( m_BlockStartStack.Count() - 1 ); - - // Move to the the location where the size of the block was written & rewrite the size - SetWritePos( startPos - sizeof(SaveRestoreRecordHeader_t) ); - BufferData( (const char *)&sizeBlock, sizeof(short) ); - - SetWritePos( endPos ); -} - -//------------------------------------- - -void CSave::BufferString( char *pdata, int len ) -{ - char c = 0; - - BufferData( pdata, len ); // Write the string - BufferData( &c, 1 ); // Write a null terminator -} - -//------------------------------------- - -void CSave::BufferField( const char *pname, int size, const char *pdata ) -{ - WriteHeader( pname, size ); - BufferData( pdata, size ); -} - -//------------------------------------- - -void CSave::WriteHeader( const char *pname, int size ) -{ - short shortSize = size; - short hashvalue = m_pData->FindCreateSymbol( pname ); - if ( size > SHRT_MAX || size < 0 ) - { - Warning( "CSave::WriteHeader() size parameter exceeds 'short'!\n" ); - Assert(0); - } - - BufferData( (const char *)&shortSize, sizeof(short) ); - BufferData( (const char *)&hashvalue, sizeof(short) ); -} - -//------------------------------------- - -void CSave::BufferData( const char *pdata, int size ) -{ - if ( !m_pData ) - return; - - if ( !m_pData->Write( pdata, size ) ) - { - Warning( "Save/Restore overflow!\n" ); - Assert(0); - } -} - -//--------------------------------------------------------- -// -// Game centric save methods. -// -int CSave::EntityIndex( const edict_t *pentLookup ) -{ -#if !defined( CLIENT_DLL ) - if ( pentLookup == NULL ) - return -1; - return EntityIndex( CBaseEntity::Instance(pentLookup) ); -#else - Assert( !"CSave::EntityIndex( edict_t * ) not valid on client!" ); - return -1; -#endif -} - - -//------------------------------------- - -int CSave::EntityIndex( const CBaseEntity *pEntity ) -{ - return m_pGameInfo->GetEntityIndex( pEntity ); -} - -//------------------------------------- - -int CSave::EntityFlagsSet( int entityIndex, int flags ) -{ - if ( !m_pGameInfo || entityIndex < 0 ) - return 0; - if ( entityIndex > m_pGameInfo->NumEntities() ) - return 0; - - m_pGameInfo->GetEntityInfo( entityIndex )->flags |= flags; - - return m_pGameInfo->GetEntityInfo( entityIndex )->flags; -} - -//------------------------------------- - -void CSave::WriteTime( const char *pname, const float *data, int count ) -{ - int i; - float tmp; - - WriteHeader( pname, sizeof(float) * count ); - for ( i = 0; i < count; i++ ) - { - // Always encode time as a delta from the current time so it can be re-based if loaded in a new level - // Times of 0 are never written to the file, so they will be restored as 0, not a relative time - Assert( data[i] != ZERO_TIME ); - - if ( data[i] == 0.0 ) - { - tmp = ZERO_TIME; - } - else if ( data[i] == INVALID_TIME || data[i] == FLT_MAX ) - { - tmp = data[i]; - } - else - { - tmp = data[i] - m_pGameInfo->GetBaseTime(); - if ( fabsf( tmp ) < 0.001 ) // never allow a time to become zero due to rebasing - tmp = 0.001; - } - - WriteData( (const char *)&tmp, sizeof(float) ); - } -} - -//------------------------------------- - -void CSave::WriteTime( const float *data, int count ) -{ - int i; - float tmp; - - for ( i = 0; i < count; i++ ) - { - // Always encode time as a delta from the current time so it can be re-based if loaded in a new level - // Times of 0 are never written to the file, so they will be restored as 0, not a relative time - if ( data[i] == 0.0 ) - { - tmp = ZERO_TIME; - } - else if ( data[i] == INVALID_TIME || data[i] == FLT_MAX ) - { - tmp = data[i]; - } - else - { - tmp = data[i] - m_pGameInfo->GetBaseTime(); - if ( fabsf( tmp ) < 0.001 ) // never allow a time to become zero due to rebasing - tmp = 0.001; - } - - WriteData( (const char *)&tmp, sizeof(float) ); - } -} - -void CSave::WriteTick( const char *pname, const int *data, int count ) -{ - WriteHeader( pname, sizeof(int) * count ); - WriteTick( data, count ); -} - -//------------------------------------- - -void CSave::WriteTick( const int *data, int count ) -{ - int i; - int tmp; - - int baseTick = TIME_TO_TICKS( m_pGameInfo->GetBaseTime() ); - - for ( i = 0; i < count; i++ ) - { - // Always encode time as a delta from the current time so it can be re-based if loaded in a new level - // Times of 0 are never written to the file, so they will be restored as 0, not a relative time - tmp = data[ i ]; - if ( data[ i ] == TICK_NEVER_THINK ) - { - tmp = TICK_NEVER_THINK_ENCODE; - } - else - { - // Rebase it... - tmp -= baseTick; - } - WriteData( (const char *)&tmp, sizeof(int) ); - } -} -//------------------------------------- - -void CSave::WritePositionVector( const char *pname, const Vector &value ) -{ - Vector tmp = value; - - if ( tmp != vec3_invalid ) - tmp -= m_pGameInfo->GetLandmark(); - - WriteVector( pname, tmp ); -} - -//------------------------------------- - -void CSave::WritePositionVector( const Vector &value ) -{ - Vector tmp = value; - - if ( tmp != vec3_invalid ) - tmp -= m_pGameInfo->GetLandmark(); - - WriteVector( tmp ); -} - -//------------------------------------- - -void CSave::WritePositionVector( const char *pname, const Vector *value, int count ) -{ - WriteHeader( pname, sizeof(Vector) * count ); - WritePositionVector( value, count ); -} - -//------------------------------------- - -void CSave::WritePositionVector( const Vector *value, int count ) -{ - int i; - Vector tmp; - for ( i = 0; i < count; i++ ) - { - Vector tmp = value[i]; - - if ( tmp != vec3_invalid ) - tmp -= m_pGameInfo->GetLandmark(); - - WriteData( (const char *)&tmp.x, sizeof(Vector) ); - } -} - -//------------------------------------- - -void CSave::WriteFunction( datamap_t *pRootMap, const char *pname, const int *data, int count ) -{ - AssertMsg( count == 1, "Arrays of functions not presently supported" ); - const char *functionName = UTIL_FunctionToName( pRootMap, (void *)(*data) ); - if ( !functionName ) - { - Warning( "Invalid function pointer in entity!\n" ); - Assert(0); - functionName = "BADFUNCTIONPOINTER"; - } - - BufferField( pname, strlen(functionName) + 1, functionName ); -} - -//------------------------------------- - -void CSave::WriteEntityPtr( const char *pname, CBaseEntity **ppEntity, int count ) -{ - AssertMsg( count <= MAX_ENTITYARRAY, "Array of entities or ehandles exceeds limit supported by save/restore" ); - int entityArray[MAX_ENTITYARRAY]; - for ( int i = 0; i < count && i < MAX_ENTITYARRAY; i++ ) - { - entityArray[i] = EntityIndex( ppEntity[i] ); - } - WriteInt( pname, entityArray, count ); -} - -//------------------------------------- - -void CSave::WriteEntityPtr( CBaseEntity **ppEntity, int count ) -{ - AssertMsg( count <= MAX_ENTITYARRAY, "Array of entities or ehandles exceeds limit supported by save/restore" ); - int entityArray[MAX_ENTITYARRAY]; - for ( int i = 0; i < count && i < MAX_ENTITYARRAY; i++ ) - { - entityArray[i] = EntityIndex( ppEntity[i] ); - } - WriteInt( entityArray, count ); -} - -//------------------------------------- - -void CSave::WriteEdictPtr( const char *pname, edict_t **ppEdict, int count ) -{ - AssertMsg( count <= MAX_ENTITYARRAY, "Array of entities or ehandles exceeds limit supported by save/restore" ); - int entityArray[MAX_ENTITYARRAY]; - for ( int i = 0; i < count && i < MAX_ENTITYARRAY; i++ ) - { - entityArray[i] = EntityIndex( ppEdict[i] ); - } - WriteInt( pname, entityArray, count ); -} - -//------------------------------------- - -void CSave::WriteEdictPtr( edict_t **ppEdict, int count ) -{ - AssertMsg( count <= MAX_ENTITYARRAY, "Array of entities or ehandles exceeds limit supported by save/restore" ); - int entityArray[MAX_ENTITYARRAY]; - for ( int i = 0; i < count && i < MAX_ENTITYARRAY; i++ ) - { - entityArray[i] = EntityIndex( ppEdict[i] ); - } - WriteInt( entityArray, count ); -} - -//------------------------------------- - -void CSave::WriteEHandle( const char *pname, const EHANDLE *pEHandle, int count ) -{ - AssertMsg( count <= MAX_ENTITYARRAY, "Array of entities or ehandles exceeds limit supported by save/restore" ); - int entityArray[MAX_ENTITYARRAY]; - for ( int i = 0; i < count && i < MAX_ENTITYARRAY; i++ ) - { - entityArray[i] = EntityIndex( (CBaseEntity *)(const_cast(pEHandle)[i]) ); - } - WriteInt( pname, entityArray, count ); -} - -//------------------------------------- - -void CSave::WriteEHandle( const EHANDLE *pEHandle, int count ) -{ - AssertMsg( count <= MAX_ENTITYARRAY, "Array of entities or ehandles exceeds limit supported by save/restore" ); - int entityArray[MAX_ENTITYARRAY]; - for ( int i = 0; i < count && i < MAX_ENTITYARRAY; i++ ) - { - entityArray[i] = EntityIndex( (CBaseEntity *)(const_cast(pEHandle)[i]) ); - } - WriteInt( entityArray, count ); -} - -//------------------------------------- -// Purpose: Writes all the fields that are not client neutral. In the event of -// a librarization of save/restore, these would not reside in the library - -bool CSave::WriteGameField( const char *pname, void *pData, datamap_t *pRootMap, typedescription_t *pField ) -{ - switch( pField->fieldType ) - { - case FIELD_CLASSPTR: - WriteEntityPtr( pField->fieldName, (CBaseEntity **)pData, pField->fieldSize ); - break; - - case FIELD_EDICT: - WriteEdictPtr( pField->fieldName, (edict_t **)pData, pField->fieldSize ); - break; - - case FIELD_EHANDLE: - WriteEHandle( pField->fieldName, (EHANDLE *)pData, pField->fieldSize ); - break; - - case FIELD_POSITION_VECTOR: - WritePositionVector( pField->fieldName, (Vector *)pData, pField->fieldSize ); - break; - - case FIELD_TIME: - WriteTime( pField->fieldName, (float *)pData, pField->fieldSize ); - break; - - case FIELD_TICK: - WriteTick( pField->fieldName, (int *)pData, pField->fieldSize ); - break; - - case FIELD_MODELINDEX: - { - int nModelIndex = *(int*)pData; - string_t strModelName = NULL_STRING; - const model_t *pModel = modelinfo->GetModel( nModelIndex ); - if ( pModel ) - { - strModelName = AllocPooledString( modelinfo->GetModelName( pModel ) ); - } - WriteString( pField->fieldName, (string_t *)&strModelName, pField->fieldSize ); - } - break; - - case FIELD_MATERIALINDEX: - { - int nMateralIndex = *(int*)pData; - string_t strMaterialName = NULL_STRING; - const char *pMaterialName = GetMaterialNameFromIndex( nMateralIndex ); - if ( pMaterialName ) - { - strMaterialName = MAKE_STRING( pMaterialName ); - } - WriteString( pField->fieldName, (string_t *)&strMaterialName, pField->fieldSize ); - } - break; - - case FIELD_MODELNAME: - case FIELD_SOUNDNAME: - WriteString( pField->fieldName, (string_t *)pData, pField->fieldSize ); - break; - - // For now, just write the address out, we're not going to change memory while doing this yet! - case FIELD_FUNCTION: - WriteFunction( pRootMap, pField->fieldName, (int *)(char *)pData, pField->fieldSize ); - break; - - case FIELD_VMATRIX: - WriteVMatrix( pField->fieldName, (VMatrix *)pData, pField->fieldSize ); - break; - case FIELD_VMATRIX_WORLDSPACE: - WriteVMatrixWorldspace( pField->fieldName, (VMatrix *)pData, pField->fieldSize ); - break; - - case FIELD_MATRIX3X4_WORLDSPACE: - WriteMatrix3x4Worldspace( pField->fieldName, (const matrix3x4_t *)pData, pField->fieldSize ); - break; - - case FIELD_INTERVAL: - WriteInterval( pField->fieldName, (interval_t *)pData, pField->fieldSize ); - break; - - default: - Warning( "Bad field type\n" ); - Assert(0); - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// -// CRestore -// -//----------------------------------------------------------------------------- - -CRestore::CRestore( CSaveRestoreData *pdata ) - : m_pData( pdata ), - m_pGameInfo( pdata ), - m_global( 0 ), - m_precache( true ) -{ - m_BlockEndStack.EnsureCapacity( 32 ); -} - -//------------------------------------- - -int CRestore::GetReadPos() const -{ - return m_pData->GetCurPos(); -} - -//------------------------------------- - -void CRestore::SetReadPos( int pos ) -{ - m_pData->Seek(pos); -} - -//------------------------------------- - -const char *CRestore::StringFromHeaderSymbol( int symbol ) -{ - const char *pszResult = m_pData->StringFromSymbol( symbol ); - return ( pszResult ) ? pszResult : ""; -} - -//------------------------------------- -// Purpose: Reads all the fields that are client neutral. In the event of -// a librarization of save/restore, these would reside in the library - -void CRestore::ReadBasicField( const SaveRestoreRecordHeader_t &header, void *pDest, datamap_t *pRootMap, typedescription_t *pField ) -{ - switch( pField->fieldType ) - { - case FIELD_FLOAT: - { - ReadFloat( (float *)pDest, pField->fieldSize, header.size ); - break; - } - case FIELD_STRING: - { - ReadString( (string_t *)pDest, pField->fieldSize, header.size ); - break; - } - - case FIELD_VECTOR: - { - ReadVector( (Vector *)pDest, pField->fieldSize, header.size ); - break; - } - - case FIELD_QUATERNION: - { - ReadQuaternion( (Quaternion *)pDest, pField->fieldSize, header.size ); - break; - } - - case FIELD_INTEGER: - { - ReadInt( (int *)pDest, pField->fieldSize, header.size ); - break; - } - - case FIELD_BOOLEAN: - { - ReadBool( (bool *)pDest, pField->fieldSize, header.size ); - break; - } - - case FIELD_SHORT: - { - ReadShort( (short *)pDest, pField->fieldSize, header.size ); - break; - } - - case FIELD_CHARACTER: - { - ReadData( (char *)pDest, pField->fieldSize, header.size ); - break; - } - - case FIELD_COLOR32: - { - COMPILE_TIME_ASSERT( sizeof(color32) == sizeof(int) ); - ReadInt( (int *)pDest, pField->fieldSize, header.size ); - break; - } - - case FIELD_EMBEDDED: - { - AssertMsg( (( pField->flags & FTYPEDESC_PTR ) == 0) || (pField->fieldSize == 1), "Arrays of embedded pointer types presently unsupported by save/restore" ); -#ifdef _DEBUG - int startPos = GetReadPos(); -#endif - if ( !(pField->flags & FTYPEDESC_PTR) || *((void **)pDest) ) - { - int nFieldCount = pField->fieldSize; - char *pFieldData = (char *)( ( !(pField->flags & FTYPEDESC_PTR) ) ? pDest : *((void **)pDest) ); - while ( --nFieldCount >= 0 ) - { - // No corresponding "block" (see write) as it was used as the header of the field - ReadAll( pFieldData, pField->td ); - pFieldData += pField->fieldSizeInBytes; - } - Assert( GetReadPos() - startPos == header.size ); - } - else - { - SetReadPos( GetReadPos() + header.size ); - Warning( "Attempted to restore FIELD_EMBEDDEDBYREF %s but there is no destination memory\n", pField->fieldName ); - } - break; - - } - case FIELD_CUSTOM: - { - // No corresponding "block" (see write) as it was used as the header of the field - int posNextField = GetReadPos() + header.size; - - SaveRestoreFieldInfo_t fieldInfo = - { - pDest, - ((char *)pDest) - pField->fieldOffset[ TD_OFFSET_NORMAL ], - pField - }; - - pField->pSaveRestoreOps->Restore( fieldInfo, this ); - - Assert( posNextField >= GetReadPos() ); - SetReadPos( posNextField ); - break; - } - - default: - Warning( "Bad field type\n" ); - Assert(0); - } -} - -//------------------------------------- - -void CRestore::ReadField( const SaveRestoreRecordHeader_t &header, void *pDest, datamap_t *pRootMap, typedescription_t *pField ) -{ - if ( pField->fieldType <= FIELD_CUSTOM ) - ReadBasicField( header, pDest, pRootMap, pField ); - else - ReadGameField( header, pDest, pRootMap, pField ); -} - -//------------------------------------- - -bool CRestore::ShouldReadField( typedescription_t *pField ) -{ - if ( (pField->flags & FTYPEDESC_SAVE) == 0 ) - return false; - - if ( m_global && (pField->flags & FTYPEDESC_GLOBAL) ) - return false; - - return true; -} - -//------------------------------------- - -typedescription_t *CRestore::FindField( const char *pszFieldName, typedescription_t *pFields, int fieldCount, int *pCookie ) -{ - int &fieldNumber = *pCookie; - if ( pszFieldName ) - { - typedescription_t *pTest; - - for ( int i = 0; i < fieldCount; i++ ) - { - pTest = &pFields[fieldNumber]; - - ++fieldNumber; - if ( fieldNumber == fieldCount ) - fieldNumber = 0; - - if ( stricmp( pTest->fieldName, pszFieldName ) == 0 ) - return pTest; - } - } - - fieldNumber = 0; - return NULL; -} - -//------------------------------------- - -bool CRestore::ShouldEmptyField( typedescription_t *pField ) -{ - // don't clear out fields that don't get saved, or that are handled specially - if ( !( pField->flags & FTYPEDESC_SAVE ) ) - return false; - - // Don't clear global fields - if ( m_global && (pField->flags & FTYPEDESC_GLOBAL) ) - return false; - - return true; -} - -//------------------------------------- - -void CRestore::EmptyFields( void *pBaseData, typedescription_t *pFields, int fieldCount ) -{ - int i; - for ( i = 0; i < fieldCount; i++ ) - { - typedescription_t *pField = &pFields[i]; - if ( !ShouldEmptyField( pField ) ) - continue; - - void *pFieldData = (char *)pBaseData + pField->fieldOffset[ TD_OFFSET_NORMAL ]; - switch( pField->fieldType ) - { - case FIELD_CUSTOM: - { - SaveRestoreFieldInfo_t fieldInfo = - { - pFieldData, - pBaseData, - pField - }; - pField->pSaveRestoreOps->MakeEmpty( fieldInfo ); - } - break; - - case FIELD_EMBEDDED: - { - if ( (pField->flags & FTYPEDESC_PTR) && !*((void **)pFieldData) ) - break; - - int nFieldCount = pField->fieldSize; - char *pFieldMemory = (char *)( ( !(pField->flags & FTYPEDESC_PTR) ) ? pFieldData : *((void **)pFieldData) ); - while ( --nFieldCount >= 0 ) - { - EmptyFields( pFieldMemory, pField->td->dataDesc, pField->td->dataNumFields ); - pFieldMemory += pField->fieldSizeInBytes; - } - } - break; - - default: - // NOTE: If you hit this assertion, you've got a bug where you're using - // the wrong field type for your field - if ( pField->fieldSizeInBytes != pField->fieldSize * gSizes[pField->fieldType] ) - { - Warning("WARNING! Field %s is using the wrong FIELD_ type!\nFix this or you'll see a crash.\n", pField->fieldName ); - Assert( 0 ); - } - memset( pFieldData, (pField->fieldType != FIELD_EHANDLE) ? 0 : 0xFF, pField->fieldSize * gSizes[pField->fieldType] ); - break; - } - } -} - -//------------------------------------- - -void CRestore::StartBlock( SaveRestoreRecordHeader_t *pHeader ) -{ - ReadHeader( pHeader ); - m_BlockEndStack.AddToTail( GetReadPos() + pHeader->size ); -} - -//------------------------------------- - -void CRestore::StartBlock( char szBlockName[] ) -{ - SaveRestoreRecordHeader_t header; - StartBlock( &header ); - Q_strncpy( szBlockName, StringFromHeaderSymbol( header.symbol ), SIZE_BLOCK_NAME_BUF ); -} - -//------------------------------------- - -void CRestore::StartBlock() -{ - char szBlockName[SIZE_BLOCK_NAME_BUF]; - StartBlock( szBlockName ); -} - -//------------------------------------- - -void CRestore::EndBlock() -{ - int endPos = m_BlockEndStack[ m_BlockEndStack.Count() - 1 ]; - m_BlockEndStack.Remove( m_BlockEndStack.Count() - 1 ); - SetReadPos( endPos ); -} - -//------------------------------------- - -int CRestore::ReadFields( const char *pname, void *pBaseData, datamap_t *pRootMap, typedescription_t *pFields, int fieldCount ) -{ - static int lastName = -1; - Verify( ReadShort() == sizeof(int) ); // First entry should be an int - int symName = m_pData->FindCreateSymbol(pname); - - // Check the struct name - int curSym = ReadShort(); - if ( curSym != symName ) // Field Set marker - { - const char *pLastName = m_pData->StringFromSymbol( lastName ); - const char *pCurName = m_pData->StringFromSymbol( curSym ); - Msg( "Expected %s found %s ( raw '%s' )! (prev: %s)\n", pname, pCurName, BufferPointer(), pLastName ); - Msg( "Field type name may have changed or inheritance graph changed, save file is suspect\n" ); - m_pData->Rewind( 2*sizeof(short) ); - return 0; - } - lastName = symName; - - // Clear out base data - EmptyFields( pBaseData, pFields, fieldCount ); - - // Skip over the struct name - int i; - int nFieldsSaved = ReadInt(); // Read field count - int searchCookie = 0; // Make searches faster, most data is read/written in the same order - SaveRestoreRecordHeader_t header; - - for ( i = 0; i < nFieldsSaved; i++ ) - { - ReadHeader( &header ); - - typedescription_t *pField = FindField( m_pData->StringFromSymbol( header.symbol ), pFields, fieldCount, &searchCookie); - if ( pField && ShouldReadField( pField ) ) - { - ReadField( header, ((char *)pBaseData + pField->fieldOffset[ TD_OFFSET_NORMAL ]), pRootMap, pField ); - } - else - { - BufferSkipBytes( header.size ); // Advance to next field - } - } - - return 1; -} - -//------------------------------------- - -void CRestore::ReadHeader( SaveRestoreRecordHeader_t *pheader ) -{ - if ( pheader != NULL ) - { - Assert( pheader!=NULL ); - pheader->size = ReadShort(); // Read field size - pheader->symbol = ReadShort(); // Read field name token - } - else - { - BufferSkipBytes( sizeof(short) * 2 ); - } -} - -//------------------------------------- - -short CRestore::ReadShort( void ) -{ - short tmp = 0; - - BufferReadBytes( (char *)&tmp, sizeof(short) ); - - return tmp; -} - -//------------------------------------- - -int CRestore::ReadInt( void ) -{ - int tmp = 0; - - BufferReadBytes( (char *)&tmp, sizeof(int) ); - - return tmp; -} - -//------------------------------------- -// Purpose: Recursively restores all the classes in an object, in reverse order (top down) -// Output : int 0 on failure, 1 on success - -int CRestore::DoReadAll( void *pLeafObject, datamap_t *pLeafMap, datamap_t *pCurMap ) -{ - // restore base classes first - if ( pCurMap->baseMap ) - { - int status = DoReadAll( pLeafObject, pLeafMap, pCurMap->baseMap ); - if ( !status ) - return status; - } - - return ReadFields( pCurMap->dataClassName, pLeafObject, pLeafMap, pCurMap->dataDesc, pCurMap->dataNumFields ); -} - -//------------------------------------- - -char *CRestore::BufferPointer( void ) -{ - if ( !m_pData ) - return NULL; - - return m_pData->AccessCurPos(); -} - -//------------------------------------- - -void CRestore::BufferReadBytes( char *pOutput, int size ) -{ - Assert( m_pData !=NULL ); - - if ( !m_pData || m_pData->BytesAvailable() == 0 ) - return; - - if ( !m_pData->Read( pOutput, size ) ) - { - Warning( "Restore underflow!\n" ); - Assert(0); - } -} - -//------------------------------------- - -void CRestore::BufferSkipBytes( int bytes ) -{ - BufferReadBytes( NULL, bytes ); -} - -//------------------------------------- - -int CRestore::ReadShort( short *pValue, int nElems, int nBytesAvailable ) -{ - return ReadSimple( pValue, nElems, nBytesAvailable ); -} - -//------------------------------------- - -int CRestore::ReadInt( int *pValue, int nElems, int nBytesAvailable ) -{ - return ReadSimple( pValue, nElems, nBytesAvailable ); -} - -//------------------------------------- - -int CRestore::ReadBool( bool *pValue, int nElems, int nBytesAvailable ) -{ - COMPILE_TIME_ASSERT( sizeof(bool) == sizeof(char) ); - return ReadSimple( pValue, nElems, nBytesAvailable ); -} - -//------------------------------------- - -int CRestore::ReadFloat( float *pValue, int nElems, int nBytesAvailable ) -{ - return ReadSimple( pValue, nElems, nBytesAvailable ); -} - -//------------------------------------- - -int CRestore::ReadData( char *pData, int size, int nBytesAvailable ) -{ - return ReadSimple( pData, size, nBytesAvailable ); -} - -//------------------------------------- - -void CRestore::ReadString( char *pDest, int nSizeDest, int nBytesAvailable ) -{ - const char *pString = BufferPointer(); - if ( !nBytesAvailable ) - nBytesAvailable = strlen( pString ) + 1; - BufferSkipBytes( nBytesAvailable ); - - Q_strncpy(pDest, pString, nSizeDest ); -} - -//------------------------------------- - -int CRestore::ReadString( string_t *pValue, int nElems, int nBytesAvailable ) -{ - AssertMsg( nBytesAvailable > 0, "CRestore::ReadString() implementation does not currently support unspecified bytes available"); - - int i; - char *pString = BufferPointer(); - char *pLimit = pString + nBytesAvailable; - for ( i = 0; i < nElems && pString < pLimit; i++ ) - { - if ( *((char *)pString) == 0 ) - pValue[i] = NULL_STRING; - else - pValue[i] = AllocPooledString( (char *)pString ); - - while (*pString) - pString++; - pString++; - } - - BufferSkipBytes( nBytesAvailable ); - - return i; -} - -//------------------------------------- - -int CRestore::ReadVector( Vector *pValue) -{ - BufferReadBytes( (char *)pValue, sizeof(Vector) ); - return 1; -} - -//------------------------------------- - -int CRestore::ReadVector( Vector *pValue, int nElems, int nBytesAvailable ) -{ - return ReadSimple( pValue, nElems, nBytesAvailable ); -} - -int CRestore::ReadQuaternion( Quaternion *pValue) -{ - BufferReadBytes( (char *)pValue, sizeof(Quaternion) ); - return 1; -} - -//------------------------------------- - -int CRestore::ReadQuaternion( Quaternion *pValue, int nElems, int nBytesAvailable ) -{ - return ReadSimple( pValue, nElems, nBytesAvailable ); -} - -//------------------------------------- -int CRestore::ReadVMatrix( VMatrix *pValue, int nElems, int nBytesAvailable ) -{ - return ReadSimple( pValue, nElems, nBytesAvailable ); -} - - -int CRestore::ReadVMatrixWorldspace( VMatrix *pValue, int nElems, int nBytesAvailable ) -{ - Vector basePosition = m_pGameInfo->GetLandmark(); - VMatrix tmp; - - for ( int i = 0; i < nElems; i++ ) - { - BufferReadBytes( (char *)&tmp, sizeof(float)*16 ); - - VMatrixOffset( pValue[i], tmp, basePosition ); - } - return nElems; -} - - -int CRestore::ReadMatrix3x4Worldspace( matrix3x4_t *pValue, int nElems, int nBytesAvailable ) -{ - Vector basePosition = m_pGameInfo->GetLandmark(); - matrix3x4_t tmp; - - for ( int i = 0; i < nElems; i++ ) - { - BufferReadBytes( (char *)&tmp, sizeof(matrix3x4_t) ); - - Matrix3x4Offset( pValue[i], tmp, basePosition ); - } - return nElems; -} - -int CRestore::ReadInterval( interval_t *interval, int count, int nBytesAvailable ) -{ - return ReadSimple( interval, count, nBytesAvailable ); -} - -//--------------------------------------------------------- -// -// Game centric restore methods -// - -CBaseEntity *CRestore::EntityFromIndex( int entityIndex ) -{ - if ( !m_pGameInfo || entityIndex < 0 ) - return NULL; - - int i; - entitytable_t *pTable; - - for ( i = 0; i < m_pGameInfo->NumEntities(); i++ ) - { - pTable = m_pGameInfo->GetEntityInfo( i ); - if ( pTable->id == entityIndex ) - return pTable->hEnt; - } - return NULL; -} - -//------------------------------------- - -int CRestore::ReadEntityPtr( CBaseEntity **ppEntity, int count, int nBytesAvailable ) -{ - AssertMsg( count <= MAX_ENTITYARRAY, "Array of entities or ehandles exceeds limit supported by save/restore" ); - int entityArray[MAX_ENTITYARRAY]; - - int nRead = ReadInt( entityArray, count, nBytesAvailable ); - - for ( int i = 0; i < nRead; i++ ) // nRead is never greater than count - { - ppEntity[i] = EntityFromIndex( entityArray[i] ); - } - - if ( nRead < count) - { - memset( &ppEntity[nRead], 0, ( count - nRead ) * sizeof(ppEntity[0]) ); - } - - return nRead; -} - -//------------------------------------- -int CRestore::ReadEdictPtr( edict_t **ppEdict, int count, int nBytesAvailable ) -{ -#if !defined( CLIENT_DLL ) - AssertMsg( count <= MAX_ENTITYARRAY, "Array of entities or ehandles exceeds limit supported by save/restore" ); - int entityArray[MAX_ENTITYARRAY]; - CBaseEntity *pEntity; - - int nRead = ReadInt( entityArray, count, nBytesAvailable ); - - for ( int i = 0; i < nRead; i++ ) // nRead is never greater than count - { - pEntity = EntityFromIndex( entityArray[i] ); - ppEdict[i] = (pEntity) ? pEntity->edict() : NULL; - } - - if ( nRead < count) - { - memset( &ppEdict[nRead], 0, ( count - nRead ) * sizeof(ppEdict[0]) ); - } - - return nRead; -#else - return 0; -#endif -} - - -//------------------------------------- - -int CRestore::ReadEHandle( EHANDLE *pEHandle, int count, int nBytesAvailable ) -{ - AssertMsg( count <= MAX_ENTITYARRAY, "Array of entities or ehandles exceeds limit supported by save/restore" ); - int entityArray[MAX_ENTITYARRAY]; - - int nRead = ReadInt( entityArray, count, nBytesAvailable ); - - for ( int i = 0; i < nRead; i++ ) // nRead is never greater than count - { - pEHandle[i] = EntityFromIndex( entityArray[i] ); - } - - if ( nRead < count) - { - memset( &pEHandle[nRead], 0xFF, ( count - nRead ) * sizeof(pEHandle[0]) ); - } - - return nRead; -} - -//------------------------------------- -// Purpose: Reads all the fields that are not client neutral. In the event of -// a librarization of save/restore, these would NOT reside in the library - -void CRestore::ReadGameField( const SaveRestoreRecordHeader_t &header, void *pDest, datamap_t *pRootMap, typedescription_t *pField ) -{ - switch( pField->fieldType ) - { - case FIELD_POSITION_VECTOR: - { - ReadPositionVector( (Vector *)pDest, pField->fieldSize, header.size ); - break; - } - - case FIELD_TIME: - { - ReadTime( (float *)pDest, pField->fieldSize, header.size ); - break; - } - - case FIELD_TICK: - { - ReadTick( (int *)pDest, pField->fieldSize, header.size ); - break; - } - - case FIELD_FUNCTION: - { - ReadFunction( pRootMap, (void **)pDest, pField->fieldSize, header.size ); - break; - } - - case FIELD_MODELINDEX: - { - int *pModelIndex = (int*)pDest; - string_t *pModelName = (string_t *)stackalloc( pField->fieldSize * sizeof(string_t) ); - int nRead = ReadString( pModelName, pField->fieldSize, header.size ); - - for ( int i = 0; i < nRead; i++ ) - { - if ( pModelName[i] == NULL_STRING ) - { - pModelIndex[i] = -1; - continue; - } - - pModelIndex[i] = modelinfo->GetModelIndex( STRING( pModelName[i] ) ); - -#if !defined( CLIENT_DLL ) - if ( m_precache ) - { - CBaseEntity::PrecacheModel( STRING( pModelName[i] ) ); - } -#endif - } - break; - } - - case FIELD_MATERIALINDEX: - { - int *pMaterialIndex = (int*)pDest; - string_t *pMaterialName = (string_t *)stackalloc( pField->fieldSize * sizeof(string_t) ); - int nRead = ReadString( pMaterialName, pField->fieldSize, header.size ); - - for ( int i = 0; i < nRead; i++ ) - { - if ( pMaterialName[i] == NULL_STRING ) - { - pMaterialIndex[i] = 0; - continue; - } - - pMaterialIndex[i] = GetMaterialIndex( STRING( pMaterialName[i] ) ); - -#if !defined( CLIENT_DLL ) - if ( m_precache ) - { - PrecacheMaterial( STRING( pMaterialName[i] ) ); - } -#endif - } - break; - } - - case FIELD_MODELNAME: - case FIELD_SOUNDNAME: - { - string_t *pStringDest = (string_t *)pDest; - int nRead = ReadString( pStringDest, pField->fieldSize, header.size ); - if ( m_precache ) - { -#if !defined( CLIENT_DLL ) - // HACKHACK: Rewrite the .bsp models to match the map name in case the bugreporter renamed it - if ( pField->fieldType == FIELD_MODELNAME && Q_stristr(pStringDest->ToCStr(), ".bsp") ) - { - char buf[MAX_PATH]; - Q_strncpy( buf, "maps/", sizeof(buf) ); - Q_strncat( buf, gpGlobals->mapname.ToCStr(), sizeof(buf) ); - Q_strncat( buf, ".bsp", sizeof(buf) ); - *pStringDest = AllocPooledString( buf ); - } -#endif - for ( int i = 0; i < nRead; i++ ) - { - if ( pStringDest[i] != NULL_STRING ) - { -#if !defined( CLIENT_DLL ) - if ( pField->fieldType == FIELD_MODELNAME ) - { - CBaseEntity::PrecacheModel( STRING( pStringDest[i] ) ); - } - else if ( pField->fieldType == FIELD_SOUNDNAME ) - { - CBaseEntity::PrecacheScriptSound( STRING( pStringDest[i] ) ); - } -#endif - } - } - } - break; - } - - case FIELD_CLASSPTR: - ReadEntityPtr( (CBaseEntity **)pDest, pField->fieldSize, header.size ); - break; - - case FIELD_EDICT: -#if !defined( CLIENT_DLL ) - ReadEdictPtr( (edict_t **)pDest, pField->fieldSize, header.size ); -#else - Assert( !"FIELD_EDICT not valid for client .dll" ); -#endif - break; - case FIELD_EHANDLE: - ReadEHandle( (EHANDLE *)pDest, pField->fieldSize, header.size ); - break; - - case FIELD_VMATRIX: - { - ReadVMatrix( (VMatrix *)pDest, pField->fieldSize, header.size ); - break; - } - - case FIELD_VMATRIX_WORLDSPACE: - ReadVMatrixWorldspace( (VMatrix *)pDest, pField->fieldSize, header.size ); - break; - - case FIELD_MATRIX3X4_WORLDSPACE: - ReadMatrix3x4Worldspace( (matrix3x4_t *)pDest, pField->fieldSize, header.size ); - break; - - case FIELD_INTERVAL: - ReadInterval( (interval_t *)pDest, pField->fieldSize, header.size ); - break; - - default: - Warning( "Bad field type\n" ); - Assert(0); - } -} - -//------------------------------------- - -int CRestore::ReadTime( float *pValue, int count, int nBytesAvailable ) -{ - float baseTime = m_pGameInfo->GetBaseTime(); - int nRead = ReadFloat( pValue, count, nBytesAvailable ); - - for ( int i = nRead - 1; i >= 0; i-- ) - { - if ( pValue[i] == ZERO_TIME ) - pValue[i] = 0.0; - else if ( pValue[i] != INVALID_TIME && pValue[i] != FLT_MAX ) - pValue[i] += baseTime; - } - - return nRead; -} - -int CRestore::ReadTick( int *pValue, int count, int nBytesAvailable ) -{ - // HACK HACK: Adding 0.1f here makes sure that all tick times read - // from .sav file which are near the basetime will end up just ahead of - // the base time, because we are restoring we'll have a slow frame of the - // max frametime of 0.1 seconds and that could otherwise cause all of our - // think times to get synchronized to each other... sigh. ywb... - int baseTick = TIME_TO_TICKS( m_pGameInfo->GetBaseTime() + 0.1f ); - int nRead = ReadInt( pValue, count, nBytesAvailable ); - - for ( int i = nRead - 1; i >= 0; i-- ) - { - if ( pValue[ i ] != TICK_NEVER_THINK_ENCODE ) - { - // Rebase it - pValue[i] += baseTick; - } - else - { - // Slam to -1 value - pValue[ i ] = TICK_NEVER_THINK; - } - } - - return nRead; -} - -//------------------------------------- - -int CRestore::ReadPositionVector( Vector *pValue ) -{ - return ReadPositionVector( pValue, 1, sizeof(Vector) ); -} - -//------------------------------------- - -int CRestore::ReadPositionVector( Vector *pValue, int count, int nBytesAvailable ) -{ - Vector basePosition = m_pGameInfo->GetLandmark(); - int nRead = ReadVector( pValue, count, nBytesAvailable ); - - for ( int i = nRead - 1; i >= 0; i-- ) - { - if ( pValue[i] != vec3_invalid ) - pValue[i] += basePosition; - } - - return nRead; -} - -//------------------------------------- - -int CRestore::ReadFunction( datamap_t *pMap, void **pValue, int count, int nBytesAvailable ) -{ - AssertMsg( nBytesAvailable > 0, "CRestore::ReadFunction() implementation does not currently support unspecified bytes available"); - - char *pszFunctionName = BufferPointer(); - BufferSkipBytes( nBytesAvailable ); - - AssertMsg( count == 1, "Arrays of functions not presently supported" ); - - if ( *pszFunctionName == 0 ) - *pValue = NULL; - else - *pValue = UTIL_FunctionFromName( pMap, pszFunctionName ); - - return 0; -} - -//----------------------------------------------------------------------------- -// -// Entity data saving routines -// -//----------------------------------------------------------------------------- - -BEGIN_SIMPLE_DATADESC(entitytable_t) - DEFINE_FIELD( id, FIELD_INTEGER ), - DEFINE_FIELD( edictindex, FIELD_INTEGER ), - DEFINE_FIELD( saveentityindex, FIELD_INTEGER ), -// DEFINE_FIELD( restoreentityindex, FIELD_INTEGER ), - // hEnt (not saved, this is the fixup) - DEFINE_FIELD( location, FIELD_INTEGER ), - DEFINE_FIELD( size, FIELD_INTEGER ), - DEFINE_FIELD( flags, FIELD_INTEGER ), - DEFINE_FIELD( classname, FIELD_STRING ), - DEFINE_FIELD( globalname, FIELD_STRING ), - DEFINE_FIELD( landmarkModelSpace, FIELD_VECTOR ), - DEFINE_FIELD( modelname, FIELD_STRING ), -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Utilities entities can use when saving -//----------------------------------------------------------------------------- -class CEntitySaveUtils : public IEntitySaveUtils -{ -public: - // Call these in pre-save + post save - void PreSave(); - void PostSave(); - - // Methods of IEntitySaveUtils - virtual void AddLevelTransitionSaveDependency( CBaseEntity *pEntity1, CBaseEntity *pEntity2 ); - virtual int GetEntityDependencyCount( CBaseEntity *pEntity ); - virtual int GetEntityDependencies( CBaseEntity *pEntity, int nCount, CBaseEntity **ppEntList ); - -private: - IPhysicsObjectPairHash *m_pLevelAdjacencyDependencyHash; -}; - - -//----------------------------------------------------------------------------- -// Call these in pre-save + post save -//----------------------------------------------------------------------------- -void CEntitySaveUtils::PreSave() -{ - Assert( !m_pLevelAdjacencyDependencyHash ); - MEM_ALLOC_CREDIT(); - m_pLevelAdjacencyDependencyHash = physics->CreateObjectPairHash(); -} - -void CEntitySaveUtils::PostSave() -{ - physics->DestroyObjectPairHash( m_pLevelAdjacencyDependencyHash ); - m_pLevelAdjacencyDependencyHash = NULL; -} - - -//----------------------------------------------------------------------------- -// Gets the # of dependencies for a particular entity -//----------------------------------------------------------------------------- -int CEntitySaveUtils::GetEntityDependencyCount( CBaseEntity *pEntity ) -{ - return m_pLevelAdjacencyDependencyHash->GetPairCountForObject( pEntity ); -} - - -//----------------------------------------------------------------------------- -// Gets all dependencies for a particular entity -//----------------------------------------------------------------------------- -int CEntitySaveUtils::GetEntityDependencies( CBaseEntity *pEntity, int nCount, CBaseEntity **ppEntList ) -{ - return m_pLevelAdjacencyDependencyHash->GetPairListForObject( pEntity, nCount, (void**)ppEntList ); -} - - -//----------------------------------------------------------------------------- -// Methods of IEntitySaveUtils -//----------------------------------------------------------------------------- -void CEntitySaveUtils::AddLevelTransitionSaveDependency( CBaseEntity *pEntity1, CBaseEntity *pEntity2 ) -{ - if ( pEntity1 != pEntity2 ) - { - m_pLevelAdjacencyDependencyHash->AddObjectPair( pEntity1, pEntity2 ); - } -} - - -//----------------------------------------------------------------------------- -// Block handler for save/restore of entities -//----------------------------------------------------------------------------- -class CEntitySaveRestoreBlockHandler : public ISaveRestoreBlockHandler -{ -public: - const char *GetBlockName(); - void PreSave( CSaveRestoreData *pSaveData ); - void Save( ISave *pSave ); - void WriteSaveHeaders( ISave *pSave ); - virtual void PostSave(); - virtual void PreRestore(); - void ReadRestoreHeaders( IRestore *pRestore ); - - void Restore( IRestore *pRestore, bool createPlayers ); - virtual void PostRestore(); - - inline IEntitySaveUtils * GetEntitySaveUtils() { return &m_EntitySaveUtils; } - -private: - friend int CreateEntityTransitionList( CSaveRestoreData *pSaveData, int levelMask ); - bool SaveInitEntities( CSaveRestoreData *pSaveData ); - bool DoRestoreEntity( CBaseEntity *pEntity, IRestore *pRestore ); - Vector ModelSpaceLandmark( int modelIndex ); - int RestoreEntity( CBaseEntity *pEntity, IRestore *pRestore, entitytable_t *pEntInfo ); - -#if !defined( CLIENT_DLL ) - // Find the matching global entity. Spit out an error if the designer made entities of - // different classes with the same global name - CBaseEntity *FindGlobalEntity( string_t classname, string_t globalname ); - - int RestoreGlobalEntity( CBaseEntity *pEntity, CSaveRestoreData *pSaveData, entitytable_t *pEntInfo ); -#endif - -private: - CEntitySaveUtils m_EntitySaveUtils; -}; - - -//----------------------------------------------------------------------------- - -CEntitySaveRestoreBlockHandler g_EntitySaveRestoreBlockHandler; - -//------------------------------------- - -ISaveRestoreBlockHandler *GetEntitySaveRestoreBlockHandler() -{ - return &g_EntitySaveRestoreBlockHandler; -} - -IEntitySaveUtils *GetEntitySaveUtils() -{ - return g_EntitySaveRestoreBlockHandler.GetEntitySaveUtils(); -} - - -//----------------------------------------------------------------------------- -// Implementation of the block handler for save/restore of entities -//----------------------------------------------------------------------------- -const char *CEntitySaveRestoreBlockHandler::GetBlockName() -{ - return "Entities"; -} - -//--------------------------------- - -void CEntitySaveRestoreBlockHandler::PreSave( CSaveRestoreData *pSaveData ) -{ - MDLCACHE_CRITICAL_SECTION(); - IGameSystem::OnSaveAllSystems(); - - m_EntitySaveUtils.PreSave(); - - // Allow the entities to do some work - CBaseEntity *pEnt = NULL; -#if !defined( CLIENT_DLL ) - while ( (pEnt = gEntList.NextEnt( pEnt )) != NULL ) - { - pEnt->OnSave( &m_EntitySaveUtils ); - } -#else - // Do this because it'll force entities to figure out their origins, and that requires - // SetupBones in the case of aiments. - { - C_BaseAnimating::AutoAllowBoneAccess boneaccess( true, true ); - - int last = ClientEntityList().GetHighestEntityIndex(); - ClientEntityHandle_t iter = ClientEntityList().FirstHandle(); - - for ( int e = 0; e <= last; e++ ) - { - pEnt = ClientEntityList().GetBaseEntity( e ); - - if( !pEnt ) - continue; - - pEnt->OnSave(); - } - - while ( iter != ClientEntityList().InvalidHandle() ) - { - pEnt = ClientEntityList().GetBaseEntityFromHandle( iter ); - - if ( pEnt && pEnt->ObjectCaps() & FCAP_SAVE_NON_NETWORKABLE ) - { - pEnt->OnSave(); - } - - iter = ClientEntityList().NextHandle( iter ); - } - } -#endif - SaveInitEntities( pSaveData ); -} - -//--------------------------------- - -void CEntitySaveRestoreBlockHandler::Save( ISave *pSave ) -{ - CGameSaveRestoreInfo *pSaveData = pSave->GetGameSaveRestoreInfo(); - - // write entity list that was previously built by SaveInitEntities() - for ( int i = 0; i < pSaveData->NumEntities(); i++ ) - { - entitytable_t *pEntInfo = pSaveData->GetEntityInfo( i ); - pEntInfo->location = pSave->GetWritePos(); - pEntInfo->size = 0; - - CBaseEntity *pEnt = pEntInfo->hEnt; - if ( pEnt && !( pEnt->ObjectCaps() & FCAP_DONT_SAVE ) ) - { - MDLCACHE_CRITICAL_SECTION(); -#if !defined( CLIENT_DLL ) - AssertMsg( !pEnt->edict() || ( pEnt->m_iClassname != NULL_STRING && - (STRING(pEnt->m_iClassname)[0] != 0) && - FStrEq( STRING(pEnt->m_iClassname), pEnt->GetClassname()) ), - "Saving entity with invalid classname" ); -#endif - - pSaveData->SetCurrentEntityContext( pEnt ); - pEnt->Save( *pSave ); - pSaveData->SetCurrentEntityContext( NULL ); - - pEntInfo->size = pSave->GetWritePos() - pEntInfo->location; // Size of entity block is data size written to block - - pEntInfo->classname = pEnt->m_iClassname; // Remember entity class for respawn - -#if !defined( CLIENT_DLL ) - pEntInfo->globalname = pEnt->m_iGlobalname; // remember global name - pEntInfo->landmarkModelSpace = ModelSpaceLandmark( pEnt->GetModelIndex() ); - int nEntIndex = pEnt->edict() ? ENTINDEX(pEnt->edict()) : -1; - bool bIsPlayer = ( ( nEntIndex >= 1 ) && ( nEntIndex <= gpGlobals->maxClients ) ) ? true : false; - if ( bIsPlayer ) - { - pEntInfo->flags |= FENTTABLE_PLAYER; - } -#endif - } - } -} - -//--------------------------------- - -void CEntitySaveRestoreBlockHandler::WriteSaveHeaders( ISave *pSave ) -{ - CGameSaveRestoreInfo *pSaveData = pSave->GetGameSaveRestoreInfo(); - - int nEntities = pSaveData->NumEntities(); - pSave->WriteInt( &nEntities ); - - for ( int i = 0; i < pSaveData->NumEntities(); i++ ) - pSave->WriteFields( "ETABLE", pSaveData->GetEntityInfo( i ), NULL, entitytable_t::m_DataMap.dataDesc, entitytable_t::m_DataMap.dataNumFields ); -} - -//--------------------------------- - -void CEntitySaveRestoreBlockHandler::PostSave() -{ - m_EntitySaveUtils.PostSave(); -} - -//--------------------------------- - -void CEntitySaveRestoreBlockHandler::PreRestore() -{ -} - -//--------------------------------- - -void CEntitySaveRestoreBlockHandler::ReadRestoreHeaders( IRestore *pRestore ) -{ - CGameSaveRestoreInfo *pSaveData = pRestore->GetGameSaveRestoreInfo(); - - int nEntities; - pRestore->ReadInt( &nEntities ); - - entitytable_t *pEntityTable = ( entitytable_t *)engine->SaveAllocMemory( (sizeof(entitytable_t) * nEntities), sizeof(char) ); - if ( !pEntityTable ) - { - return; - } - - pSaveData->InitEntityTable( pEntityTable, nEntities ); - - for ( int i = 0; i < pSaveData->NumEntities(); i++ ) - pRestore->ReadFields( "ETABLE", pSaveData->GetEntityInfo( i ), NULL, entitytable_t::m_DataMap.dataDesc, entitytable_t::m_DataMap.dataNumFields ); - -} - -//--------------------------------- - -#if !defined( CLIENT_DLL ) - -void CEntitySaveRestoreBlockHandler::Restore( IRestore *pRestore, bool createPlayers ) -{ - entitytable_t *pEntInfo; - CBaseEntity *pent; - - CGameSaveRestoreInfo *pSaveData = pRestore->GetGameSaveRestoreInfo(); - - bool restoredWorld = false; - - // Create entity list - int i; - for ( i = 0; i < pSaveData->NumEntities(); i++ ) - { - pEntInfo = pSaveData->GetEntityInfo( i ); - - if ( pEntInfo->classname != NULL_STRING && pEntInfo->size && !(pEntInfo->flags & FENTTABLE_REMOVED) ) - { - if ( pEntInfo->edictindex == 0 ) // worldspawn - { - Assert( i == 0 ); - pent = CreateEntityByName( STRING(pEntInfo->classname) ); - pRestore->SetReadPos( pEntInfo->location ); - if ( RestoreEntity( pent, pRestore, pEntInfo ) < 0 ) - { - pEntInfo->hEnt = NULL; - pEntInfo->restoreentityindex = -1; - UTIL_RemoveImmediate( pent ); - } - else - { - // force the entity to be relinked - AddRestoredEntity( pent ); - } - } - else if ( (pEntInfo->edictindex > 0) && (pEntInfo->edictindex <= gpGlobals->maxClients) ) - { - if ( !(pEntInfo->flags & FENTTABLE_PLAYER) ) - { - Warning( "ENTITY IS NOT A PLAYER: %d\n" , i ); - Assert(0); - } - - edict_t *ed = INDEXENT( pEntInfo->edictindex ); - - if ( ed && createPlayers ) - { - // create the player - pent = CBasePlayer::CreatePlayer( STRING(pEntInfo->classname), ed ); - } - else - pent = NULL; - } - else - { - pent = CreateEntityByName( STRING(pEntInfo->classname) ); - } - pEntInfo->hEnt = pent; - pEntInfo->restoreentityindex = pent ? pent->entindex() : - 1; - if ( pent && pEntInfo->restoreentityindex == 0 ) - { - if ( !FClassnameIs( pent, "worldspawn" ) ) - { - pEntInfo->restoreentityindex = -1; - } - } - - if ( pEntInfo->restoreentityindex == 0 ) - { - Assert( !restoredWorld ); - restoredWorld = true; - } - } - else - { - pEntInfo->hEnt = NULL; - pEntInfo->restoreentityindex = -1; - } - } - - // Now spawn entities - for ( i = 0; i < pSaveData->NumEntities(); i++ ) - { - pEntInfo = pSaveData->GetEntityInfo( i ); - if ( pEntInfo->edictindex != 0 ) - { - pent = pEntInfo->hEnt; - pRestore->SetReadPos( pEntInfo->location ); - if ( pent ) - { - if ( RestoreEntity( pent, pRestore, pEntInfo ) < 0 ) - { - pEntInfo->hEnt = NULL; - pEntInfo->restoreentityindex = -1; - UTIL_RemoveImmediate( pent ); - } - else - { - AddRestoredEntity( pent ); - } - } - } - } -} - -#else // CLIENT DLL VERSION - -void CEntitySaveRestoreBlockHandler::Restore( IRestore *pRestore, bool createPlayers ) -{ - entitytable_t *pEntInfo; - CBaseEntity *pent; - - CGameSaveRestoreInfo *pSaveData = pRestore->GetGameSaveRestoreInfo(); - - // Create entity list - int i; - bool restoredWorld = false; - - for ( i = 0; i < pSaveData->NumEntities(); i++ ) - { - pEntInfo = pSaveData->GetEntityInfo( i ); - pent = ClientEntityList().GetBaseEntity( pEntInfo->restoreentityindex ); - pEntInfo->hEnt = pent; - } - - // Blast saved data into entities - for ( i = 0; i < pSaveData->NumEntities(); i++ ) - { - pEntInfo = pSaveData->GetEntityInfo( i ); - - bool bRestoredCorrectly = false; - // FIXME, need to translate save spot to real index here using lookup table transmitted from server - //Assert( !"Need translation still" ); - if ( pEntInfo->restoreentityindex >= 0 ) - { - if ( pEntInfo->restoreentityindex == 0 ) - { - Assert( !restoredWorld ); - restoredWorld = true; - } - - pent = ClientEntityList().GetBaseEntity( pEntInfo->restoreentityindex ); - pRestore->SetReadPos( pEntInfo->location ); - if ( pent ) - { - if ( RestoreEntity( pent, pRestore, pEntInfo ) >= 0 ) - { - // Call the OnRestore method - AddRestoredEntity( pent ); - bRestoredCorrectly = true; - } - } - } - // BUGBUG: JAY: Disable ragdolls across transitions until PVS/solid check & client entity patch file are implemented - else if ( !pSaveData->levelInfo.fUseLandmark ) - { - if ( pEntInfo->classname != NULL_STRING ) - { - pent = CreateEntityByName( STRING(pEntInfo->classname) ); - pent->InitializeAsClientEntity( NULL, RENDER_GROUP_OPAQUE_ENTITY ); - - pRestore->SetReadPos( pEntInfo->location ); - - if ( pent ) - { - if ( RestoreEntity( pent, pRestore, pEntInfo ) >= 0 ) - { - pEntInfo->hEnt = pent; - AddRestoredEntity( pent ); - bRestoredCorrectly = true; - } - } - } - } - - if ( !bRestoredCorrectly ) - { - pEntInfo->hEnt = NULL; - pEntInfo->restoreentityindex = -1; - } - } - - // Note, server does this after local player connects fully - IGameSystem::OnRestoreAllSystems(); - - // Tell hud elements to modify behavior based on game restoration, if applicable - gHUD.OnRestore(); -} -#endif - -void CEntitySaveRestoreBlockHandler::PostRestore() -{ -} - -void SaveEntityOnTable( CBaseEntity *pEntity, CSaveRestoreData *pSaveData, int &iSlot ) -{ - entitytable_t *pEntInfo = pSaveData->GetEntityInfo( iSlot ); - pEntInfo->id = iSlot; -#if !defined( CLIENT_DLL ) - pEntInfo->edictindex = pEntity->RequiredEdictIndex(); -#else - pEntInfo->edictindex = -1; -#endif - pEntInfo->modelname = pEntity->GetModelName(); - pEntInfo->restoreentityindex = -1; - pEntInfo->saveentityindex = pEntity ? pEntity->entindex() : -1; - pEntInfo->hEnt = pEntity; - pEntInfo->flags = 0; - pEntInfo->location = 0; - pEntInfo->size = 0; - pEntInfo->classname = NULL_STRING; - - iSlot++; -} - - -//--------------------------------- - -bool CEntitySaveRestoreBlockHandler::SaveInitEntities( CSaveRestoreData *pSaveData ) -{ - int number_of_entities; - -#if !defined( CLIENT_DLL ) - number_of_entities = gEntList.NumberOfEntities(); -#else - number_of_entities = ClientEntityList().NumberOfEntities( true ); -#endif - entitytable_t *pEntityTable = ( entitytable_t *)engine->SaveAllocMemory( (sizeof(entitytable_t) * number_of_entities), sizeof(char) ); - if ( !pEntityTable ) - return false; - - pSaveData->InitEntityTable( pEntityTable, number_of_entities ); - - // build the table of entities - // this is used to turn pointers into savable indices - // build up ID numbers for each entity, for use in pointer conversions - // if an entity requires a certain edict number upon restore, save that as well - CBaseEntity *pEnt = NULL; - int i = 0; - -#if !defined( CLIENT_DLL ) - while ( (pEnt = gEntList.NextEnt( pEnt )) != NULL ) - { -#else - int last = ClientEntityList().GetHighestEntityIndex(); - - for ( int e = 0; e <= last; e++ ) - { - pEnt = ClientEntityList().GetBaseEntity( e ); - if( !pEnt ) - continue; -#endif - SaveEntityOnTable( pEnt, pSaveData, i ); - } - -#if defined( CLIENT_DLL ) - ClientEntityHandle_t iter = ClientEntityList().FirstHandle(); - - while ( iter != ClientEntityList().InvalidHandle() ) - { - pEnt = ClientEntityList().GetBaseEntityFromHandle( iter ); - - if ( pEnt && pEnt->ObjectCaps() & FCAP_SAVE_NON_NETWORKABLE ) - { - SaveEntityOnTable( pEnt, pSaveData, i ); - } - - iter = ClientEntityList().NextHandle( iter ); - } -#endif - - pSaveData->BuildEntityHash(); - - Assert( i == pSaveData->NumEntities() ); - return ( i == pSaveData->NumEntities() ); -} - -//--------------------------------- - -#if !defined( CLIENT_DLL ) - -// Find the matching global entity. Spit out an error if the designer made entities of -// different classes with the same global name -CBaseEntity *CEntitySaveRestoreBlockHandler::FindGlobalEntity( string_t classname, string_t globalname ) -{ - CBaseEntity *pReturn = NULL; - - while ( (pReturn = gEntList.NextEnt( pReturn )) != NULL ) - { - if ( FStrEq( STRING(pReturn->m_iGlobalname), STRING(globalname)) ) - break; - } - - if ( pReturn ) - { - if ( !FClassnameIs( pReturn, STRING(classname) ) ) - { - Warning( "Global entity found %s, wrong class %s [expects class %s]\n", STRING(globalname), STRING(pReturn->m_iClassname), STRING(classname) ); - pReturn = NULL; - } - } - - return pReturn; -} - -#endif // !defined( CLIENT_DLL ) - -//--------------------------------- - -bool CEntitySaveRestoreBlockHandler::DoRestoreEntity( CBaseEntity *pEntity, IRestore *pRestore ) -{ - MDLCACHE_CRITICAL_SECTION(); - - EHANDLE hEntity; - - hEntity = pEntity; - - pRestore->GetGameSaveRestoreInfo()->SetCurrentEntityContext( pEntity ); - pEntity->Restore( *pRestore ); - pRestore->GetGameSaveRestoreInfo()->SetCurrentEntityContext( NULL ); - -#if !defined( CLIENT_DLL ) - if ( pEntity->ObjectCaps() & FCAP_MUST_SPAWN ) - { - pEntity->Spawn(); - } - else - { - pEntity->Precache( ); - } -#endif - - // Above calls may have resulted in self destruction - return ( hEntity != NULL ); -} - -//--------------------------------- -// Get a reference position in model space to compute -// changes in model space for global brush entities (designer models them in different coords!) -Vector CEntitySaveRestoreBlockHandler::ModelSpaceLandmark( int modelIndex ) -{ - const model_t *pModel = modelinfo->GetModel( modelIndex ); - if ( modelinfo->GetModelType( pModel ) != mod_brush ) - return vec3_origin; - - Vector mins, maxs; - modelinfo->GetModelBounds( pModel, mins, maxs ); - return mins; -} - - -int CEntitySaveRestoreBlockHandler::RestoreEntity( CBaseEntity *pEntity, IRestore *pRestore, entitytable_t *pEntInfo ) -{ - if ( !DoRestoreEntity( pEntity, pRestore ) ) - return 0; - -#if !defined( CLIENT_DLL ) - if ( pEntity->m_iGlobalname != NULL_STRING ) - { - int globalIndex = GlobalEntity_GetIndex( pEntity->m_iGlobalname ); - if ( globalIndex >= 0 ) - { - // Already dead? delete - if ( GlobalEntity_GetState( globalIndex ) == GLOBAL_DEAD ) - return -1; - else if ( !FStrEq( STRING(gpGlobals->mapname), GlobalEntity_GetMap(globalIndex) ) ) - { - pEntity->MakeDormant(); // Hasn't been moved to this level yet, wait but stay alive - } - // In this level & not dead, continue on as normal - } - else - { - Warning( "Global Entity %s (%s) not in table!!!\n", STRING(pEntity->m_iGlobalname), STRING(pEntity->m_iClassname) ); - // Spawned entities default to 'On' - GlobalEntity_Add( pEntity->m_iGlobalname, gpGlobals->mapname, GLOBAL_ON ); - } - } -#endif - - return 0; -} - -//--------------------------------- - -#if !defined( CLIENT_DLL ) - -int CEntitySaveRestoreBlockHandler::RestoreGlobalEntity( CBaseEntity *pEntity, CSaveRestoreData *pSaveData, entitytable_t *pEntInfo ) -{ - Vector oldOffset; - EHANDLE hEntitySafeHandle; - hEntitySafeHandle = pEntity; - - oldOffset.Init(); - CRestore restoreHelper( pSaveData ); - - string_t globalName = pEntInfo->globalname, className = pEntInfo->classname; - - // ------------------- - - int globalIndex = GlobalEntity_GetIndex( globalName ); - - // Don't overlay any instance of the global that isn't the latest - // pSaveData->szCurrentMapName is the level this entity is coming from - // pGlobal->levelName is the last level the global entity was active in. - // If they aren't the same, then this global update is out of date. - if ( !FStrEq( pSaveData->levelInfo.szCurrentMapName, GlobalEntity_GetMap(globalIndex) ) ) - { - return 0; - } - - // Compute the new global offset - CBaseEntity *pNewEntity = FindGlobalEntity( className, globalName ); - if ( pNewEntity ) - { -// Msg( "Overlay %s with %s\n", pNewEntity->GetClassname(), STRING(tmpEnt->classname) ); - // Tell the restore code we're overlaying a global entity from another level - restoreHelper.SetGlobalMode( 1 ); // Don't overwrite global fields - - pSaveData->modelSpaceOffset = pEntInfo->landmarkModelSpace - ModelSpaceLandmark( pNewEntity->GetModelIndex() ); - - UTIL_Remove( pEntity ); - pEntity = pNewEntity;// we're going to restore this data OVER the old entity - pEntInfo->hEnt = pEntity; - // HACKHACK: Do we need system-wide support for removing non-global spawn allocated resources? - pEntity->VPhysicsDestroyObject(); - Assert( pEntInfo->edictindex == -1 ); - // Update the global table to say that the global definition of this entity should come from this level - GlobalEntity_SetMap( globalIndex, gpGlobals->mapname ); - } - else - { - // This entity will be freed automatically by the engine-> If we don't do a restore on a matching entity (below) - // or call EntityUpdate() to move it to this level, we haven't changed global state at all. - DevMsg( "Warning: No match for global entity %s found in destination level\n", STRING(globalName) ); - return 0; - } - - if ( !DoRestoreEntity( pEntity, &restoreHelper ) ) - { - pEntity = NULL; - } - - // Is this an overriding global entity (coming over the transition) - pSaveData->modelSpaceOffset.Init(); - if ( pEntity ) - return 1; - return 0; -} - -#endif // !defined( CLIENT_DLL ) - - - -//----------------------------------------------------------------------------- - -CSaveRestoreData *SaveInit( int size ) -{ - CSaveRestoreData *pSaveData; - -#if ( defined( CLIENT_DLL ) || defined( DISABLE_DEBUG_HISTORY ) ) - if ( size <= 0 ) - size = 2*1024*1024; // Reserve 2048K for now, UNDONE: Shrink this after compressing strings -#else - if ( size <= 0 ) - size = 3*1024*1024; // Reserve 3096K for now, UNDONE: Shrink this after compressing strings -#endif - - int numentities; - -#if !defined( CLIENT_DLL ) - numentities = gEntList.NumberOfEntities(); -#else - numentities = ClientEntityList().NumberOfEntities(); -#endif - - void *pSaveMemory = engine->SaveAllocMemory( sizeof(CSaveRestoreData) + (sizeof(entitytable_t) * numentities) + size, sizeof(char) ); - if ( !pSaveMemory ) - { - return NULL; - } - - pSaveData = MakeSaveRestoreData( pSaveMemory ); - pSaveData->Init( (char *)(pSaveData + 1), size ); // skip the save structure - - const int nTokens = 0xfff; // Assume a maximum of 4K-1 symbol table entries(each of some length) - pSaveMemory = engine->SaveAllocMemory( nTokens, sizeof( char * ) ); - if ( !pSaveMemory ) - { - engine->SaveFreeMemory( pSaveMemory ); - return NULL; - } - - pSaveData->InitSymbolTable( (char **)pSaveMemory, nTokens ); - - //--------------------------------- - - pSaveData->levelInfo.time = gpGlobals->curtime; // Use DLL time - pSaveData->levelInfo.vecLandmarkOffset = vec3_origin; - pSaveData->levelInfo.fUseLandmark = false; - pSaveData->levelInfo.connectionCount = 0; - - //--------------------------------- - - gpGlobals->pSaveData = pSaveData; - - return pSaveData; -} - - - -//----------------------------------------------------------------------------- -// -// ISaveRestoreBlockSet -// -// Purpose: Serves as holder for a group of sibling save sections. Takes -// care of iterating over them, making sure read points are -// queued up to the right spot (in case one section due to datadesc -// changes reads less than expected, or doesn't leave the -// read pointer at the right point), and ensuring the read pointer -// is at the end of the entire set when the set read is done. -//----------------------------------------------------------------------------- - -struct SaveRestoreBlockHeader_t -{ - char szName[MAX_BLOCK_NAME_LEN + 1]; - int locHeader; - int locBody; - - DECLARE_SIMPLE_DATADESC(); -}; - - -//------------------------------------- - -class CSaveRestoreBlockSet : public ISaveRestoreBlockSet -{ -public: - CSaveRestoreBlockSet( const char *pszName ) - { - Q_strncpy( m_Name, pszName, sizeof(m_Name) ); - } - - const char *GetBlockName() - { - return m_Name; - } - - //--------------------------------- - - void PreSave( CSaveRestoreData *pData ) - { - m_BlockHeaders.SetCount( m_Handlers.Count() ); - for ( int i = 0; i < m_Handlers.Count(); i++ ) - { - Q_strncpy( m_BlockHeaders[i].szName, m_Handlers[i]->GetBlockName(), MAX_BLOCK_NAME_LEN + 1 ); - m_Handlers[i]->PreSave( pData ); - } - } - - void Save( ISave *pSave ) - { - int base = pSave->GetWritePos(); - for ( int i = 0; i < m_Handlers.Count(); i++ ) - { - m_BlockHeaders[i].locBody = pSave->GetWritePos() - base; - m_Handlers[i]->Save( pSave ); - } - m_SizeBodies = pSave->GetWritePos() - base; - } - - void WriteSaveHeaders( ISave *pSave ) - { - int base = pSave->GetWritePos(); - - // - // Reserve space for a fully populated header - // - int dummyInt = -1; - CUtlVector dummyArr; - - dummyArr.SetCount( m_BlockHeaders.Count() ); - memset( &dummyArr[0], 0xff, dummyArr.Count() * sizeof(SaveRestoreBlockHeader_t) ); - - pSave->WriteInt( &dummyInt ); // size all headers - pSave->WriteInt( &dummyInt ); // size all bodies - SaveUtlVector( pSave, &dummyArr, FIELD_EMBEDDED ); - - // - // Write the data - // - for ( int i = 0; i < m_Handlers.Count(); i++ ) - { - m_BlockHeaders[i].locHeader = pSave->GetWritePos() - base; - m_Handlers[i]->WriteSaveHeaders( pSave ); - } - - m_SizeHeaders = pSave->GetWritePos() - base; - - // - // Write the actual header - // - int savedPos = pSave->GetWritePos(); - pSave->SetWritePos(base); - - pSave->WriteInt( &m_SizeHeaders ); - pSave->WriteInt( &m_SizeBodies ); - SaveUtlVector( pSave, &m_BlockHeaders, FIELD_EMBEDDED ); - - pSave->SetWritePos(savedPos); - } - - void PostSave() - { - for ( int i = 0; i < m_Handlers.Count(); i++ ) - { - m_Handlers[i]->PostSave(); - } - m_BlockHeaders.Purge(); - } - - //--------------------------------- - - void PreRestore() - { - for ( int i = 0; i < m_Handlers.Count(); i++ ) - { - m_Handlers[i]->PreRestore(); - } - } - - void ReadRestoreHeaders( IRestore *pRestore ) - { - int base = pRestore->GetReadPos(); - - pRestore->ReadInt( &m_SizeHeaders ); - pRestore->ReadInt( &m_SizeBodies ); - RestoreUtlVector( pRestore, &m_BlockHeaders, FIELD_EMBEDDED ); - - for ( int i = 0; i < m_Handlers.Count(); i++ ) - { - int location = GetBlockHeaderLoc( m_Handlers[i]->GetBlockName() ); - if ( location != -1 ) - { - pRestore->SetReadPos( base + location ); - m_Handlers[i]->ReadRestoreHeaders( pRestore ); - } - } - - pRestore->SetReadPos( base + m_SizeHeaders ); - } - - void CallBlockHandlerRestore( ISaveRestoreBlockHandler *pHandler, int baseFilePos, IRestore *pRestore, bool fCreatePlayers ) - { - int location = GetBlockBodyLoc( pHandler->GetBlockName() ); - if ( location != -1 ) - { - pRestore->SetReadPos( baseFilePos + location ); - pHandler->Restore( pRestore, fCreatePlayers ); - } - } - - void Restore( IRestore *pRestore, bool fCreatePlayers ) - { - int base = pRestore->GetReadPos(); - - for ( int i = 0; i < m_Handlers.Count(); i++ ) - { - CallBlockHandlerRestore( m_Handlers[i], base, pRestore, fCreatePlayers ); - } - pRestore->SetReadPos( base + m_SizeBodies ); - } - - void PostRestore() - { - for ( int i = 0; i < m_Handlers.Count(); i++ ) - { - m_Handlers[i]->PostRestore(); - } - m_BlockHeaders.Purge(); - } - - //--------------------------------- - - void AddBlockHandler( ISaveRestoreBlockHandler *pHandler ) - { - // Grody, but... while this class is still isolated in saverestore.cpp, this seems like a fine time to assert: - AssertMsg( pHandler == &g_EntitySaveRestoreBlockHandler || (m_Handlers.Count() >= 1 && m_Handlers[0] == &g_EntitySaveRestoreBlockHandler), "Expected entity save load to always be first" ); - - Assert( pHandler != this ); - m_Handlers.AddToTail( pHandler ); - } - - void RemoveBlockHandler( ISaveRestoreBlockHandler *pHandler ) - { - m_Handlers.FindAndRemove( pHandler ); - } - - //--------------------------------- - -private: - int GetBlockBodyLoc( const char *pszName ) - { - for ( int i = 0; i < m_BlockHeaders.Count(); i++ ) - { - if ( strcmp( m_BlockHeaders[i].szName, pszName ) == 0 ) - return m_BlockHeaders[i].locBody; - } - return -1; - } - - int GetBlockHeaderLoc( const char *pszName ) - { - for ( int i = 0; i < m_BlockHeaders.Count(); i++ ) - { - if ( strcmp( m_BlockHeaders[i].szName, pszName ) == 0 ) - return m_BlockHeaders[i].locHeader; - } - return -1; - } - - char m_Name[MAX_BLOCK_NAME_LEN + 1]; - CUtlVector m_Handlers; - - int m_SizeHeaders; - int m_SizeBodies; - CUtlVector m_BlockHeaders; -}; - -//------------------------------------- - -BEGIN_SIMPLE_DATADESC( SaveRestoreBlockHeader_t ) - DEFINE_ARRAY(szName, FIELD_CHARACTER, MAX_BLOCK_NAME_LEN + 1), - DEFINE_FIELD(locHeader, FIELD_INTEGER), - DEFINE_FIELD(locBody, FIELD_INTEGER), -END_DATADESC() - -//------------------------------------- - -CSaveRestoreBlockSet g_SaveRestoreBlockSet("Game"); -ISaveRestoreBlockSet *g_pGameSaveRestoreBlockSet = &g_SaveRestoreBlockSet; - -//============================================================================= -#if !defined( CLIENT_DLL ) - -//------------------------------------------------------------------------------ -// Creates all entities that lie in the transition list -//------------------------------------------------------------------------------ -void CreateEntitiesInTransitionList( CSaveRestoreData *pSaveData, int levelMask ) -{ - CBaseEntity *pent; - int i; - for ( i = 0; i < pSaveData->NumEntities(); i++ ) - { - entitytable_t *pEntInfo = pSaveData->GetEntityInfo( i ); - pEntInfo->hEnt = NULL; - - if ( pEntInfo->size == 0 || pEntInfo->edictindex == 0 ) - continue; - - if ( pEntInfo->classname == NULL_STRING ) - { - Warning( "Entity with data saved, but with no classname\n" ); - Assert(0); - continue; - } - - bool active = (pEntInfo->flags & levelMask) ? 1 : 0; - - // spawn players - pent = NULL; - if ( (pEntInfo->edictindex > 0) && (pEntInfo->edictindex <= gpGlobals->maxClients) ) - { - edict_t *ed = INDEXENT( pEntInfo->edictindex ); - - if ( active && ed && !ed->IsFree() ) - { - if ( !(pEntInfo->flags & FENTTABLE_PLAYER) ) - { - Warning( "ENTITY IS NOT A PLAYER: %d\n" , i ); - Assert(0); - } - - pent = CBasePlayer::CreatePlayer( STRING(pEntInfo->classname), ed ); - } - } - else if ( active ) - { - pent = CreateEntityByName( STRING(pEntInfo->classname) ); - } - - pEntInfo->hEnt = pent; - } -} - - -//----------------------------------------------------------------------------- -int CreateEntityTransitionList( CSaveRestoreData *pSaveData, int levelMask ) -{ - CBaseEntity *pent; - entitytable_t *pEntInfo; - - // Create entity list - CreateEntitiesInTransitionList( pSaveData, levelMask ); - - // Now spawn entities - CUtlVector checkList; - - int i; - int movedCount = 0; - for ( i = 0; i < pSaveData->NumEntities(); i++ ) - { - pEntInfo = pSaveData->GetEntityInfo( i ); - pent = pEntInfo->hEnt; -// pSaveData->currentIndex = i; - pSaveData->Seek( pEntInfo->location ); - - // clear this out - it must be set on a per-entity basis - pSaveData->modelSpaceOffset.Init(); - - if ( pent && (pEntInfo->flags & levelMask) ) // Screen out the player if he's not to be spawned - { - if ( pEntInfo->flags & FENTTABLE_GLOBAL ) - { - DevMsg( 2, "Merging changes for global: %s\n", STRING(pEntInfo->classname) ); - - // ------------------------------------------------------------------------- - // Pass the "global" flag to the DLL to indicate this entity should only override - // a matching entity, not be spawned - if ( g_EntitySaveRestoreBlockHandler.RestoreGlobalEntity( pent, pSaveData, pEntInfo ) > 0 ) - { - movedCount++; - pEntInfo->restoreentityindex = pEntInfo->hEnt.Get()->entindex(); - AddRestoredEntity( pEntInfo->hEnt.Get() ); - } - else - { - UTIL_RemoveImmediate( pEntInfo->hEnt.Get() ); - } - // ------------------------------------------------------------------------- - } - else - { - DevMsg( 2, "Transferring %s (%d)\n", STRING(pEntInfo->classname), pent->edict() ? ENTINDEX(pent->edict()) : -1 ); - CRestore restoreHelper( pSaveData ); - if ( g_EntitySaveRestoreBlockHandler.RestoreEntity( pent, &restoreHelper, pEntInfo ) < 0 ) - { - UTIL_RemoveImmediate( pent ); - } - else - { - // needs to be checked. Do this in a separate pass so that pointers & hierarchy can be traversed - checkList.AddToTail(i); - } - } - - // Remove any entities that were removed using UTIL_Remove() as a result of the above calls to UTIL_RemoveImmediate() - gEntList.CleanupDeleteList(); - } - } - - for ( i = checkList.Count()-1; i >= 0; --i ) - { - pEntInfo = pSaveData->GetEntityInfo( checkList[i] ); - pent = pEntInfo->hEnt; - - // NOTE: pent can be NULL because UTIL_RemoveImmediate (called below) removes all in hierarchy - if ( !pent ) - continue; - - MDLCACHE_CRITICAL_SECTION(); - - if ( !(pEntInfo->flags & FENTTABLE_PLAYER) && UTIL_EntityInSolid( pent ) ) - { - // this can happen during normal processing - PVS is just a guess, some map areas won't exist in the new map - DevMsg( 2, "Suppressing %s\n", STRING(pEntInfo->classname) ); - UTIL_RemoveImmediate( pent ); - // Remove any entities that were removed using UTIL_Remove() as a result of the above calls to UTIL_RemoveImmediate() - gEntList.CleanupDeleteList(); - } - else - { - movedCount++; - pEntInfo->flags = FENTTABLE_REMOVED; - pEntInfo->restoreentityindex = pent->entindex(); - AddRestoredEntity( pent ); - } - } - - return movedCount; -} -#endif diff --git a/game/shared/saverestore.h b/game/shared/saverestore.h deleted file mode 100644 index b06dbe3be..000000000 --- a/game/shared/saverestore.h +++ /dev/null @@ -1,355 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Helper classes and functions for the save/restore system. These -// classes are internally structured to distinguish simple from -// complex types. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SAVERESTORE_H -#define SAVERESTORE_H - -#include "isaverestore.h" -#include "utlvector.h" -#include "filesystem.h" - -#ifdef _WIN32 -#pragma once -#endif - -//------------------------------------- - -class CSaveRestoreData; -class CSaveRestoreSegment; -class CGameSaveRestoreInfo; -struct typedescription_t; -struct edict_t; -struct datamap_t; -class CBaseEntity; -struct interval_t; - -//----------------------------------------------------------------------------- -// -// CSave -// -//----------------------------------------------------------------------------- - -class CSave : public ISave -{ -public: - CSave( CSaveRestoreData *pdata ); - - //--------------------------------- - // Logging - void StartLogging( const char *pszLogName ); - void EndLogging( void ); - - //--------------------------------- - bool IsAsync(); - - //--------------------------------- - - int GetWritePos() const; - void SetWritePos(int pos); - - //--------------------------------- - // Datamap based writing - // - - int WriteAll( const void *pLeafObject, datamap_t *pLeafMap ) { return DoWriteAll( pLeafObject, pLeafMap, pLeafMap ); } - - int WriteFields( const char *pname, const void *pBaseData, datamap_t *pMap, typedescription_t *pFields, int fieldCount ); - - //--------------------------------- - // Block support - // - - virtual void StartBlock( const char *pszBlockName ); - virtual void StartBlock(); - virtual void EndBlock(); - - //--------------------------------- - // Primitive types - // - - void WriteShort( const short *value, int count = 1 ); - void WriteInt( const int *value, int count = 1 ); // Save an int - void WriteBool( const bool *value, int count = 1 ); // Save a bool - void WriteFloat( const float *value, int count = 1 ); // Save a float - void WriteData( const char *pdata, int size ); // Save a binary data block - void WriteString( const char *pstring ); // Save a null-terminated string - void WriteString( const string_t *stringId, int count = 1 ); // Save a null-terminated string (engine string) - void WriteVector( const Vector &value ); // Save a vector - void WriteVector( const Vector *value, int count = 1 ); // Save a vector array - void WriteQuaternion( const Quaternion &value ); // Save a Quaternion - void WriteQuaternion( const Quaternion *value, int count = 1 ); // Save a Quaternion array - void WriteVMatrix( const VMatrix *value, int count = 1 ); // Save a vmatrix array - - // Note: All of the following will write out both a header and the data. On restore, - // this needs to be cracked - void WriteShort( const char *pname, const short *value, int count = 1 ); - void WriteInt( const char *pname, const int *value, int count = 1 ); // Save an int - void WriteBool( const char *pname, const bool *value, int count = 1 ); // Save a bool - void WriteFloat( const char *pname, const float *value, int count = 1 ); // Save a float - void WriteData( const char *pname, int size, const char *pdata ); // Save a binary data block - void WriteString( const char *pname, const char *pstring ); // Save a null-terminated string - void WriteString( const char *pname, const string_t *stringId, int count = 1 ); // Save a null-terminated string (engine string) - void WriteVector( const char *pname, const Vector &value ); // Save a vector - void WriteVector( const char *pname, const Vector *value, int count = 1 ); // Save a vector array - void WriteQuaternion( const char *pname, const Quaternion &value ); // Save a Quaternion - void WriteQuaternion( const char *pname, const Quaternion *value, int count = 1 ); // Save a Quaternion array - void WriteVMatrix( const char *pname, const VMatrix *value, int count = 1 ); - //--------------------------------- - // Game types - // - - void WriteTime( const char *pname, const float *value, int count = 1 ); // Save a float (timevalue) - void WriteTick( const char *pname, const int *value, int count = 1 ); // Save a int (timevalue) - void WritePositionVector( const char *pname, const Vector &value ); // Offset for landmark if necessary - void WritePositionVector( const char *pname, const Vector *value, int count = 1 ); // array of pos vectors - void WriteFunction( datamap_t *pMap, const char *pname, const int *value, int count = 1 ); // Save a function pointer - - void WriteEntityPtr( const char *pname, CBaseEntity **ppEntity, int count = 1 ); - void WriteEdictPtr( const char *pname, edict_t **ppEdict, int count = 1 ); - void WriteEHandle( const char *pname, const EHANDLE *pEHandle, int count = 1 ); - - virtual void WriteTime( const float *value, int count = 1 ); // Save a float (timevalue) - virtual void WriteTick( const int *value, int count = 1 ); // Save a int (timevalue) - virtual void WritePositionVector( const Vector &value ); // Offset for landmark if necessary - virtual void WritePositionVector( const Vector *value, int count = 1 ); // array of pos vectors - - virtual void WriteEntityPtr( CBaseEntity **ppEntity, int count = 1 ); - virtual void WriteEdictPtr( edict_t **ppEdict, int count = 1 ); - virtual void WriteEHandle( const EHANDLE *pEHandle, int count = 1 ); - void WriteVMatrixWorldspace( const char *pname, const VMatrix *value, int count = 1 ); // Save a vmatrix array - void WriteVMatrixWorldspace( const VMatrix *value, int count = 1 ); // Save a vmatrix array - void WriteMatrix3x4Worldspace( const matrix3x4_t *value, int count ); - void WriteMatrix3x4Worldspace( const char *pname, const matrix3x4_t *value, int count ); - - void WriteInterval( const interval_t *value, int count = 1 ); // Save an interval - void WriteInterval( const char *pname, const interval_t *value, int count = 1 ); - - //--------------------------------- - - int EntityIndex( const CBaseEntity *pEntity ); - int EntityFlagsSet( int entityIndex, int flags ); - - CGameSaveRestoreInfo *GetGameSaveRestoreInfo() { return m_pGameInfo; } - -private: - - //--------------------------------- - bool IsLogging( void ); - void Log( const char *pName, fieldtype_t fieldType, void *value, int count ); - - //--------------------------------- - - void BufferField( const char *pname, int size, const char *pdata ); - void BufferData( const char *pdata, int size ); - void WriteHeader( const char *pname, int size ); - - int DoWriteAll( const void *pLeafObject, datamap_t *pLeafMap, datamap_t *pCurMap ); - bool WriteField( const char *pname, void *pData, datamap_t *pRootMap, typedescription_t *pField ); - - bool WriteBasicField( const char *pname, void *pData, datamap_t *pRootMap, typedescription_t *pField ); - - int DataEmpty( const char *pdata, int size ); - void BufferString( char *pdata, int len ); - - int CountFieldsToSave( const void *pBaseData, typedescription_t *pFields, int fieldCount ); - bool ShouldSaveField( const void *pData, typedescription_t *pField ); - - //--------------------------------- - // Game info methods - // - - bool WriteGameField( const char *pname, void *pData, datamap_t *pRootMap, typedescription_t *pField ); - int EntityIndex( const edict_t *pentLookup ); - - //--------------------------------- - - CUtlVector m_BlockStartStack; - - // Stream data - CSaveRestoreSegment *m_pData; - - // Game data - CGameSaveRestoreInfo *m_pGameInfo; - - FileHandle_t m_hLogFile; - bool m_bAsync; -}; - -//----------------------------------------------------------------------------- -// -// CRestore -// -//----------------------------------------------------------------------------- - -class CRestore : public IRestore -{ -public: - CRestore( CSaveRestoreData *pdata ); - - int GetReadPos() const; - void SetReadPos( int pos ); - - //--------------------------------- - // Datamap based reading - // - - int ReadAll( void *pLeafObject, datamap_t *pLeafMap ) { return DoReadAll( pLeafObject, pLeafMap, pLeafMap ); } - - int ReadFields( const char *pname, void *pBaseData, datamap_t *pMap, typedescription_t *pFields, int fieldCount ); - void EmptyFields( void *pBaseData, typedescription_t *pFields, int fieldCount ); - - //--------------------------------- - // Block support - // - - virtual void StartBlock( SaveRestoreRecordHeader_t *pHeader ); - virtual void StartBlock( char szBlockName[SIZE_BLOCK_NAME_BUF] ); - virtual void StartBlock(); - virtual void EndBlock(); - - //--------------------------------- - // Field header cracking - // - - void ReadHeader( SaveRestoreRecordHeader_t *pheader ); - int SkipHeader() { SaveRestoreRecordHeader_t header; ReadHeader( &header ); return header.size; } - const char * StringFromHeaderSymbol( int symbol ); - - //--------------------------------- - // Primitive types - // - - short ReadShort( void ); - int ReadShort( short *pValue, int count = 1, int nBytesAvailable = 0); - int ReadInt( int *pValue, int count = 1, int nBytesAvailable = 0); - int ReadInt( void ); - int ReadBool( bool *pValue, int count = 1, int nBytesAvailable = 0); - int ReadFloat( float *pValue, int count = 1, int nBytesAvailable = 0); - int ReadData( char *pData, int size, int nBytesAvailable ); - void ReadString( char *pDest, int nSizeDest, int nBytesAvailable ); // A null-terminated string - int ReadString( string_t *pString, int count = 1, int nBytesAvailable = 0); - int ReadVector( Vector *pValue ); - int ReadVector( Vector *pValue, int count = 1, int nBytesAvailable = 0); - int ReadQuaternion( Quaternion *pValue ); - int ReadQuaternion( Quaternion *pValue, int count = 1, int nBytesAvailable = 0); - int ReadVMatrix( VMatrix *pValue, int count = 1, int nBytesAvailable = 0); - - //--------------------------------- - // Game types - // - - int ReadTime( float *pValue, int count = 1, int nBytesAvailable = 0); - int ReadTick( int *pValue, int count = 1, int nBytesAvailable = 0); - int ReadPositionVector( Vector *pValue ); - int ReadPositionVector( Vector *pValue, int count = 1, int nBytesAvailable = 0); - int ReadFunction( datamap_t *pMap, void **pValue, int count = 1, int nBytesAvailable = 0); - - int ReadEntityPtr( CBaseEntity **ppEntity, int count = 1, int nBytesAvailable = 0 ); - int ReadEdictPtr( edict_t **ppEdict, int count = 1, int nBytesAvailable = 0 ); - int ReadEHandle( EHANDLE *pEHandle, int count = 1, int nBytesAvailable = 0 ); - int ReadVMatrixWorldspace( VMatrix *pValue, int count = 1, int nBytesAvailable = 0); - int ReadMatrix3x4Worldspace( matrix3x4_t *pValue, int nElems = 1, int nBytesAvailable = 0 ); - int ReadInterval( interval_t *interval, int count = 1, int nBytesAvailable = 0 ); - - //--------------------------------- - - void SetGlobalMode( int global ) { m_global = global; } - void PrecacheMode( bool mode ) { m_precache = mode; } - bool GetPrecacheMode( void ) { return m_precache; } - - CGameSaveRestoreInfo *GetGameSaveRestoreInfo() { return m_pGameInfo; } - -private: - //--------------------------------- - // Read primitives - // - - char * BufferPointer( void ); - void BufferSkipBytes( int bytes ); - - int DoReadAll( void *pLeafObject, datamap_t *pLeafMap, datamap_t *pCurMap ); - - typedescription_t *FindField( const char *pszFieldName, typedescription_t *pFields, int fieldCount, int *pIterator ); - void ReadField( const SaveRestoreRecordHeader_t &header, void *pDest, datamap_t *pRootMap, typedescription_t *pField ); - - void ReadBasicField( const SaveRestoreRecordHeader_t &header, void *pDest, datamap_t *pRootMap, typedescription_t *pField ); - - void BufferReadBytes( char *pOutput, int size ); - - template - int ReadSimple( T *pValue, int nElems, int nBytesAvailable ) // must be inline in class to keep MSVS happy - { - int desired = nElems * sizeof(T); - int actual; - - if ( nBytesAvailable == 0 ) - actual = desired; - else - { - Assert( nBytesAvailable % sizeof(T) == 0 ); - actual = MIN( desired, nBytesAvailable ); - } - - BufferReadBytes( (char *)pValue, actual ); - - if ( actual < nBytesAvailable ) - BufferSkipBytes( nBytesAvailable - actual ); - - return ( actual / sizeof(T) ); - } - - bool ShouldReadField( typedescription_t *pField ); - bool ShouldEmptyField( typedescription_t *pField ); - - //--------------------------------- - // Game info methods - // - CBaseEntity * EntityFromIndex( int entityIndex ); - void ReadGameField( const SaveRestoreRecordHeader_t &header, void *pDest, datamap_t *pRootMap, typedescription_t *pField ); - - //--------------------------------- - - CUtlVector m_BlockEndStack; - - // Stream data - CSaveRestoreSegment *m_pData; - - // Game data - CGameSaveRestoreInfo * m_pGameInfo; - int m_global; // Restoring a global entity? - bool m_precache; -}; - - -//----------------------------------------------------------------------------- -// An interface passed into the OnSave method of all entities -//----------------------------------------------------------------------------- -abstract_class IEntitySaveUtils -{ -public: - // Adds a level transition save dependency - virtual void AddLevelTransitionSaveDependency( CBaseEntity *pEntity1, CBaseEntity *pEntity2 ) = 0; - - // Gets the # of dependencies for a particular entity - virtual int GetEntityDependencyCount( CBaseEntity *pEntity ) = 0; - - // Gets all dependencies for a particular entity - virtual int GetEntityDependencies( CBaseEntity *pEntity, int nCount, CBaseEntity **ppEntList ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Singleton interface -//----------------------------------------------------------------------------- -IEntitySaveUtils *GetEntitySaveUtils(); - - -//============================================================================= - -#endif // SAVERESTORE_H diff --git a/game/shared/saverestore_bitstring.h b/game/shared/saverestore_bitstring.h deleted file mode 100644 index b8a490fe1..000000000 --- a/game/shared/saverestore_bitstring.h +++ /dev/null @@ -1,95 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SAVERESTORE_BITSTRING_H -#define SAVERESTORE_BITSTRING_H - -#include "isaverestore.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -//------------------------------------- - -template -class CVarBitVecSaveRestoreOps : public CDefSaveRestoreOps -{ -public: - CVarBitVecSaveRestoreOps() - { - } - - // save data type interface - virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave ) - { - BITSTRING *pBitString = (BITSTRING *)fieldInfo.pField; - int numBits = pBitString->GetNumBits(); - pSave->WriteInt( &numBits ); - pSave->WriteInt( pBitString->Base(), pBitString->GetNumDWords() ); - } - - virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore ) - { - BITSTRING *pBitString = (BITSTRING *)fieldInfo.pField; - int numBits = pRestore->ReadInt(); - if ( !pBitString->IsFixedSize() ) - pBitString->Resize( numBits ); - else - { - Assert( pBitString->GetNumBits() >= numBits ); - pBitString->ClearAll(); - } - int numIntsInStream = CalcNumIntsForBits( numBits ); - int readSize = MIN( pBitString->GetNumDWords(), numIntsInStream ); - pRestore->ReadInt( pBitString->Base(), numIntsInStream ); - - numIntsInStream -= readSize; - while ( numIntsInStream-- > 0 ) - { - int ignored; - pRestore->ReadInt( &ignored, 1 ); - } - } - - virtual void MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - BITSTRING *pBitString = (BITSTRING *)fieldInfo.pField; - pBitString->ClearAll(); - } - - virtual bool IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - BITSTRING *pBitString = (BITSTRING *)fieldInfo.pField; - return pBitString->IsAllClear(); - } -}; - -//------------------------------------- - -template -ISaveRestoreOps *GetBitstringDataOps(BITSTRING *) -{ - static CVarBitVecSaveRestoreOps ops; - return &ops; -} - -//------------------------------------- - -#define SaveBitString( pSave, pBitString, fieldtype) \ - CDataopsInstantiator::GetDataOps( pBitString )->Save( pBitString, pSave ); - -#define RestoreBitString( pRestore, pBitString, fieldtype) \ - CDataopsInstantiator::GetDataOps( pBitString )->Restore( pBitString, pRestore ); - -//------------------------------------- - -#define DEFINE_BITSTRING(name) \ - { FIELD_CUSTOM, #name, { offsetof(classNameTypedef,name), 0 }, 1, FTYPEDESC_SAVE, NULL, GetBitstringDataOps(&(((classNameTypedef *)0)->name)), NULL } - -#endif // SAVERESTORE_BITSTRING_H - diff --git a/game/shared/saverestore_stringtable.h b/game/shared/saverestore_stringtable.h deleted file mode 100644 index 44ebe0e5a..000000000 --- a/game/shared/saverestore_stringtable.h +++ /dev/null @@ -1,65 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SAVERESTORE_STRINGTABLE_H -#define SAVERESTORE_STRINGTABLE_H - -#if defined( _WIN32 ) -#pragma once -#endif - - -#include "isaverestore.h" -#include "networkstringtabledefs.h" - - -//------------------------------------- - -class CStringTableSaveRestoreOps : public CDefSaveRestoreOps -{ -public: - void Init( INetworkStringTable* pNetworkStringTable ) - { - m_pStringTable = pNetworkStringTable; - } - - // save data type interface - virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave ) - { - int *pStringIndex = (int *)fieldInfo.pField; - const char *pString = m_pStringTable->GetString( *pStringIndex ); - int nLen = Q_strlen( pString ) + 1; - pSave->WriteInt( &nLen ); - pSave->WriteString( pString ); - } - - virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore ) - { - int *pStringIndex = (int *)fieldInfo.pField; - int nLen = pRestore->ReadInt(); - char *pTemp = (char *)stackalloc( nLen ); - pRestore->ReadString( pTemp, nLen, nLen ); - *pStringIndex = m_pStringTable->AddString( CBaseEntity::IsServer(), pTemp ); - } - - virtual void MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - int *pStringIndex = (int *)fieldInfo.pField; - *pStringIndex = INVALID_STRING_INDEX; - } - - virtual bool IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - int *pStringIndex = (int *)fieldInfo.pField; - return *pStringIndex == INVALID_STRING_INDEX; - } - -private: - INetworkStringTable *m_pStringTable; -}; - -#endif // SAVERESTORE_STRINGTABLE_H diff --git a/game/shared/saverestore_utlclass.h b/game/shared/saverestore_utlclass.h deleted file mode 100644 index 7fe0366f7..000000000 --- a/game/shared/saverestore_utlclass.h +++ /dev/null @@ -1,66 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef SAVERESTORE_UTLCLASS_H -#define SAVERESTORE_UTLCLASS_H - -#if defined( _WIN32 ) -#pragma once -#endif - -//------------------------------------- - -template -class CTypedescDeducer -{ -public: - template - static datamap_t *Deduce( UTLCLASS *p ) - { - return NULL; - } - -}; - -template<> -class CTypedescDeducer -{ -public: - template - static datamap_t *Deduce( UTLCLASS *p ) - { - return &UTLCLASS::ElemType_t::m_DataMap; - } - -}; - -#define UTLCLASS_SAVERESTORE_VALIDATE_TYPE( type ) \ - COMPILE_TIME_ASSERT( \ - type == FIELD_FLOAT ||\ - type == FIELD_STRING ||\ - type == FIELD_CLASSPTR ||\ - type == FIELD_EHANDLE ||\ - type == FIELD_EDICT ||\ - type == FIELD_VECTOR ||\ - type == FIELD_QUATERNION ||\ - type == FIELD_POSITION_VECTOR ||\ - type == FIELD_INTEGER ||\ - type == FIELD_BOOLEAN ||\ - type == FIELD_SHORT ||\ - type == FIELD_CHARACTER ||\ - type == FIELD_TIME ||\ - type == FIELD_TICK ||\ - type == FIELD_MODELNAME ||\ - type == FIELD_SOUNDNAME ||\ - type == FIELD_COLOR32 ||\ - type == FIELD_EMBEDDED ||\ - type == FIELD_MODELINDEX ||\ - type == FIELD_MATERIALINDEX\ - ) - -//------------------------------------- - -#endif // SAVERESTORE_UTLCLASS_H diff --git a/game/shared/saverestore_utlmap.h b/game/shared/saverestore_utlmap.h deleted file mode 100644 index 1c57997b0..000000000 --- a/game/shared/saverestore_utlmap.h +++ /dev/null @@ -1,198 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef SAVERESTORE_UTLMAP_H -#define SAVERESTORE_UTLMAP_H - -#include "utlmap.h" -#include "saverestore_utlrbtree.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -template -class CUtlMapDataOps : public CDefSaveRestoreOps -{ -public: - CUtlMapDataOps() - { - UTLCLASS_SAVERESTORE_VALIDATE_TYPE( KEY_TYPE ); - UTLCLASS_SAVERESTORE_VALIDATE_TYPE( FIELD_TYPE ); - } - - virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave ) - { - datamap_t *pKeyDatamap = CTypedescDeducer::Deduce( (UTLMAP *)NULL ); - datamap_t *pFieldDatamap = CTypedescDeducer::Deduce( (UTLMAP *)NULL ); - typedescription_t dataDesc[] = - { - { - (fieldtype_t)KEY_TYPE, - "K", - { 0, 0 }, - 1, - FTYPEDESC_SAVE, - NULL, - NULL, - NULL, - pKeyDatamap, - sizeof(KEY_TYPE), - }, - - { - (fieldtype_t)FIELD_TYPE, - "T", - { offsetof(typename UTLMAP::Node_t, elem), 0 }, - 1, - FTYPEDESC_SAVE, - NULL, - NULL, - NULL, - pFieldDatamap, - sizeof(FIELD_TYPE), - } - }; - - datamap_t dataMap = - { - dataDesc, - 2, - "um", - NULL, - false, - false, - 0, -#ifdef _DEBUG - true -#endif - }; - - typename UTLMAP::CTree *pUtlRBTree = ((UTLMAP *)fieldInfo.pField)->AccessTree(); - - pSave->StartBlock(); - - int nElems = pUtlRBTree->Count(); - pSave->WriteInt( &nElems, 1 ); - - typename UTLMAP::CTree::IndexType_t i = pUtlRBTree->FirstInorder(); - while ( i != pUtlRBTree->InvalidIndex() ) - { - typename UTLMAP::CTree::ElemType_t &elem = pUtlRBTree->Element( i ); - - pSave->WriteAll( &elem, &dataMap ); - - i = pUtlRBTree->NextInorder( i ); - } - pSave->EndBlock(); - } - - virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore ) - { - datamap_t *pKeyDatamap = CTypedescDeducer::Deduce( (UTLMAP *)NULL ); - datamap_t *pFieldDatamap = CTypedescDeducer::Deduce( (UTLMAP *)NULL ); - typedescription_t dataDesc[] = - { - { - (fieldtype_t)KEY_TYPE, - "K", - { 0, 0 }, - 1, - FTYPEDESC_SAVE, - NULL, - NULL, - NULL, - pKeyDatamap, - sizeof(KEY_TYPE), - }, - - { - (fieldtype_t)FIELD_TYPE, - "T", - { offsetof(typename UTLMAP::Node_t, elem), 0 }, - 1, - FTYPEDESC_SAVE, - NULL, - NULL, - NULL, - pFieldDatamap, - sizeof(FIELD_TYPE), - } - }; - - datamap_t dataMap = - { - dataDesc, - 2, - "um", - NULL, - false, - false, - 0, -#ifdef _DEBUG - true -#endif - }; - - UTLMAP *pUtlMap = ((UTLMAP *)fieldInfo.pField); - - pRestore->StartBlock(); - - int nElems = pRestore->ReadInt(); - typename UTLMAP::CTree::ElemType_t temp; - - while ( nElems-- ) - { - pRestore->ReadAll( &temp, &dataMap ); - pUtlMap->Insert( temp.key, temp.elem ); - } - - pRestore->EndBlock(); - } - - virtual void MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - UTLMAP *pUtlMap = (UTLMAP *)fieldInfo.pField; - pUtlMap->RemoveAll(); - } - - virtual bool IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - UTLMAP *pUtlMap = (UTLMAP *)fieldInfo.pField; - return ( pUtlMap->Count() == 0 ); - } - -}; - -//------------------------------------- - -template -class CUtlMapDataopsInstantiator -{ -public: - template - static ISaveRestoreOps *GetDataOps(UTLMAP *) - { - static CUtlMapDataOps ops; - return &ops; - } -}; - -//------------------------------------- - -#define SaveUtlMap( pSave, pUtlMap, fieldtype) \ - CUtlMapDataopsInstantiator::GetDataOps( pUtlMap )->Save( pUtlMap, pSave ); - -#define RestoreUtlMap( pRestore, pUtlMap, fieldtype) \ - CUtlMapDataopsInstantiator::GetDataOps( pUtlMap )->Restore( pUtlMap, pRestore ); - -//------------------------------------- - -#define DEFINE_UTLMAP(name,keyType,fieldtype) \ - { FIELD_CUSTOM, #name, { offsetof(classNameTypedef,name), 0 }, 1, FTYPEDESC_SAVE, NULL, CUtlMapDataopsInstantiator::GetDataOps(&(((classNameTypedef *)0)->name)), NULL } - - -#endif // SAVERESTORE_UTLMAP_H diff --git a/game/shared/saverestore_utlrbtree.h b/game/shared/saverestore_utlrbtree.h deleted file mode 100644 index 5da3ac428..000000000 --- a/game/shared/saverestore_utlrbtree.h +++ /dev/null @@ -1,167 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef SAVERESTORE_UTLRBTREE_H -#define SAVERESTORE_UTLRBTREE_H - -#include "utlrbtree.h" -#include "isaverestore.h" -#include "saverestore_utlclass.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -//------------------------------------- - -template -class CUtlRBTreeDataOps : public CDefSaveRestoreOps -{ -public: - CUtlRBTreeDataOps() - { - UTLCLASS_SAVERESTORE_VALIDATE_TYPE( FIELD_TYPE ); - } - - virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave ) - { - datamap_t *pTreeTypeDatamap = CTypedescDeducer::Deduce( (UTLRBTREE *)NULL ); - typedescription_t dataDesc = - { - (fieldtype_t)FIELD_TYPE, - "elem", - { 0, 0 }, - 1, - FTYPEDESC_SAVE, - NULL, - NULL, - NULL, - pTreeTypeDatamap, - -1, - }; - - datamap_t dataMap = - { - &dataDesc, - 1, - "urb", - NULL, - false, - false, - 0, -#ifdef _DEBUG - true -#endif - }; - - UTLRBTREE *pUtlRBTree = (UTLRBTREE *)fieldInfo.pField; - - pSave->StartBlock(); - - int nElems = pUtlRBTree->Count(); - pSave->WriteInt( &nElems, 1 ); - - typename UTLRBTREE::IndexType_t i = pUtlRBTree->FirstInorder(); - while ( i != pUtlRBTree->InvalidIndex() ) - { - typename UTLRBTREE::ElemType_t &elem = pUtlRBTree->Element( i ); - - pSave->WriteAll( &elem, &dataMap ); - - i = pUtlRBTree->NextInorder( i ); - } - pSave->EndBlock(); - } - - virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore ) - { - datamap_t *pTreeTypeDatamap = CTypedescDeducer::Deduce( (UTLRBTREE *)NULL ); - typedescription_t dataDesc = - { - (fieldtype_t)FIELD_TYPE, - "elems", - { 0, 0 }, - 1, - FTYPEDESC_SAVE, - NULL, - NULL, - NULL, - pTreeTypeDatamap, - -1, - }; - - datamap_t dataMap = - { - &dataDesc, - 1, - "uv", - NULL, - false, - false, - 0, -#ifdef _DEBUG - true -#endif - }; - - UTLRBTREE *pUtlRBTree = (UTLRBTREE *)fieldInfo.pField; - - pRestore->StartBlock(); - - int nElems = pRestore->ReadInt(); - typename UTLRBTREE::ElemType_t temp; - - while ( nElems-- ) - { - pRestore->ReadAll( &temp, &dataMap ); - pUtlRBTree->Insert( temp ); - } - - pRestore->EndBlock(); - } - - virtual void MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - UTLRBTREE *pUtlRBTree = (UTLRBTREE *)fieldInfo.pField; - pUtlRBTree->RemoveAll(); - } - - virtual bool IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - UTLRBTREE *pUtlRBTree = (UTLRBTREE *)fieldInfo.pField; - return ( pUtlRBTree->Count() == 0 ); - } - -}; - -//------------------------------------- - -template -class CUtlRBTreeDataopsInstantiator -{ -public: - template - static ISaveRestoreOps *GetDataOps(UTLRBTREE *) - { - static CUtlRBTreeDataOps ops; - return &ops; - } -}; - -//------------------------------------- - -#define SaveUtlRBTree( pSave, pUtlRBTree, fieldtype) \ - CUtlRBTreeDataopsInstantiator::GetDataOps( pUtlRBTree )->Save( pUtlRBTree, pSave ); - -#define RestoreUtlRBTree( pRestore, pUtlRBTree, fieldtype) \ - CUtlRBTreeDataopsInstantiator::GetDataOps( pUtlRBTree )->Restore( pUtlRBTree, pRestore ); - -//------------------------------------- - -#define DEFINE_UTLRBTREE(name,fieldtype) \ - { FIELD_CUSTOM, #name, { offsetof(classNameTypedef,name), 0 }, 1, FTYPEDESC_SAVE, NULL, CUtlRBTreeDataopsInstantiator::GetDataOps(&(((classNameTypedef *)0)->name)), NULL } - -#endif // SAVERESTORE_UTLRBTREE_H diff --git a/game/shared/saverestore_utlsymbol.h b/game/shared/saverestore_utlsymbol.h deleted file mode 100644 index 0f6008581..000000000 --- a/game/shared/saverestore_utlsymbol.h +++ /dev/null @@ -1,53 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef SAVERESTORE_UTLSYMBOL_H -#define SAVERESTORE_UTLSYMBOL_H -#ifdef _WIN32 -#pragma once -#endif - -#include "utlsymbol.h" - -class CUtlSymbolDataOps : public CDefSaveRestoreOps -{ -public: - CUtlSymbolDataOps( CUtlSymbolTable &masterTable ) : m_symbolTable(masterTable) {} - - virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave ) - { - CUtlSymbol *sym = ((CUtlSymbol *)fieldInfo.pField); - - pSave->WriteString( m_symbolTable.String( *sym ) ); - } - - virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore ) - { - CUtlSymbol *sym = ((CUtlSymbol *)fieldInfo.pField); - - char tmp[1024]; - pRestore->ReadString( tmp, sizeof(tmp), 0 ); - *sym = m_symbolTable.AddString( tmp ); - } - - virtual void MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - CUtlSymbol *sym = ((CUtlSymbol *)fieldInfo.pField); - *sym = UTL_INVAL_SYMBOL; - } - - virtual bool IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - CUtlSymbol *sym = ((CUtlSymbol *)fieldInfo.pField); - return (*sym).IsValid() ? false : true; - } - -private: - CUtlSymbolTable &m_symbolTable; - -}; - -#endif // SAVERESTORE_UTLSYMBOL_H diff --git a/game/shared/saverestore_utlvector.h b/game/shared/saverestore_utlvector.h deleted file mode 100644 index 541eb1ba4..000000000 --- a/game/shared/saverestore_utlvector.h +++ /dev/null @@ -1,182 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SAVERESTORE_UTLVECTOR_H -#define SAVERESTORE_UTLVECTOR_H - -#include "utlvector.h" -#include "isaverestore.h" -#include "saverestore_utlclass.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -//------------------------------------- - -template -class CUtlVectorDataOps : public CDefSaveRestoreOps -{ -public: - CUtlVectorDataOps() - { - UTLCLASS_SAVERESTORE_VALIDATE_TYPE( FIELD_TYPE ); - } - - virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave ) - { - datamap_t *pArrayTypeDatamap = CTypedescDeducer::Deduce( (UTLVECTOR *)NULL ); - typedescription_t dataDesc = - { - (fieldtype_t)FIELD_TYPE, - "elems", - { 0, 0 }, - 1, - FTYPEDESC_SAVE, - NULL, - NULL, - NULL, - pArrayTypeDatamap, - -1, - }; - - datamap_t dataMap = - { - &dataDesc, - 1, - "uv", - NULL, - false, - false, - 0, -#ifdef _DEBUG - true -#endif - }; - - UTLVECTOR *pUtlVector = (UTLVECTOR *)fieldInfo.pField; - int nElems = pUtlVector->Count(); - - pSave->WriteInt( &nElems, 1 ); - if ( pArrayTypeDatamap == NULL ) - { - if ( nElems ) - { - dataDesc.fieldSize = nElems; - dataDesc.fieldSizeInBytes = nElems * CDatamapFieldSizeDeducer::FieldSize(); - pSave->WriteFields("elems", &((*pUtlVector)[0]), &dataMap, &dataDesc, 1 ); - } - } - else - { - // @Note (toml 11-21-02): Save load does not support arrays of user defined types (embedded) - dataDesc.fieldSizeInBytes = CDatamapFieldSizeDeducer::FieldSize(); - for ( int i = 0; i < nElems; i++ ) - pSave->WriteAll( &((*pUtlVector)[i]), &dataMap ); - } - } - - virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore ) - { - datamap_t *pArrayTypeDatamap = CTypedescDeducer::Deduce( (UTLVECTOR *)NULL ); - typedescription_t dataDesc = - { - (fieldtype_t)FIELD_TYPE, - "elems", - { 0, 0 }, - 1, - FTYPEDESC_SAVE, - NULL, - NULL, - NULL, - pArrayTypeDatamap, - -1, - }; - - datamap_t dataMap = - { - &dataDesc, - 1, - "uv", - NULL, - false, - false, - 0, -#ifdef _DEBUG - true -#endif - }; - - UTLVECTOR *pUtlVector = (UTLVECTOR *)fieldInfo.pField; - - int nElems = pRestore->ReadInt(); - - pUtlVector->SetCount( nElems ); - if ( pArrayTypeDatamap == NULL ) - { - if ( nElems ) - { - dataDesc.fieldSize = nElems; - dataDesc.fieldSizeInBytes = nElems * CDatamapFieldSizeDeducer::FieldSize(); - pRestore->ReadFields("elems", &((*pUtlVector)[0]), &dataMap, &dataDesc, 1 ); - } - } - else - { - // @Note (toml 11-21-02): Save load does not support arrays of user defined types (embedded) - dataDesc.fieldSizeInBytes = CDatamapFieldSizeDeducer::FieldSize(); - for ( int i = 0; i < nElems; i++ ) - pRestore->ReadAll( &((*pUtlVector)[i]), &dataMap ); - } - } - - virtual void MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - UTLVECTOR *pUtlVector = (UTLVECTOR *)fieldInfo.pField; - pUtlVector->SetCount( 0 ); - } - - virtual bool IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - UTLVECTOR *pUtlVector = (UTLVECTOR *)fieldInfo.pField; - return ( pUtlVector->Count() == 0 ); - } - -}; - -//------------------------------------- - -template -class CUtlVectorDataopsInstantiator -{ -public: - template - static ISaveRestoreOps *GetDataOps(UTLVECTOR *) - { - static CUtlVectorDataOps ops; - return &ops; - } -}; - -//------------------------------------- - -#define SaveUtlVector( pSave, pUtlVector, fieldtype) \ - CUtlVectorDataopsInstantiator::GetDataOps( pUtlVector )->Save( pUtlVector, pSave ); - -#define RestoreUtlVector( pRestore, pUtlVector, fieldtype) \ - CUtlVectorDataopsInstantiator::GetDataOps( pUtlVector )->Restore( pUtlVector, pRestore ); - -//------------------------------------- - -#define DEFINE_UTLVECTOR(name,fieldtype) \ - { FIELD_CUSTOM, #name, { offsetof(classNameTypedef,name), 0 }, 1, FTYPEDESC_SAVE, NULL, CUtlVectorDataopsInstantiator::GetDataOps(&(((classNameTypedef *)0)->name)), NULL } - -#define DEFINE_GLOBAL_UTLVECTOR(name,fieldtype) \ -{ FIELD_CUSTOM, #name, { offsetof(classNameTypedef,name), 0 }, 1, FTYPEDESC_SAVE|FTYPEDESC_GLOBAL, NULL, CUtlVectorDataopsInstantiator::GetDataOps(&(((classNameTypedef *)0)->name)), NULL } - - -#endif // SAVERESTORE_UTLVECTOR_H diff --git a/game/shared/sceneentity_shared.cpp b/game/shared/sceneentity_shared.cpp deleted file mode 100644 index 909bfeff3..000000000 --- a/game/shared/sceneentity_shared.cpp +++ /dev/null @@ -1,124 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#include "sceneentity_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -static ConVar scene_print( "scene_print", "0", FCVAR_REPLICATED, "When playing back a scene, print timing and event info to console." ); -ConVar scene_clientflex( "scene_clientflex", "1", FCVAR_REPLICATED, "Do client side flex animation." ); - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pFormat - -// ... - -// Output : static void -//----------------------------------------------------------------------------- -void Scene_Printf( const char *pFormat, ... ) -{ - int val = scene_print.GetInt(); - if ( !val ) - return; - - if ( val >= 2 ) - { - if ( CBaseEntity::IsServer() && val != 2 ) - { - return; - } - else if ( !CBaseEntity::IsServer() && val != 3 ) - { - return; - } - } - - va_list marker; - char msg[8192]; - - va_start(marker, pFormat); - Q_vsnprintf(msg, sizeof(msg), pFormat, marker); - va_end(marker); - - Msg( "%8.3f[%d] %s: %s", gpGlobals->curtime, gpGlobals->tickcount, CBaseEntity::IsServer() ? "sv" : "cl", msg ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CSceneTokenProcessor::CurrentToken( void ) -{ - return m_szToken; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : crossline - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CSceneTokenProcessor::GetToken( bool crossline ) -{ - // NOTE: crossline is ignored here, may need to implement if needed - m_pBuffer = engine->ParseFile( m_pBuffer, m_szToken, sizeof( m_szToken ) ); - if ( strlen( m_szToken ) >= 0 ) - return true; - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CSceneTokenProcessor::TokenAvailable( void ) -{ - char const *search_p = m_pBuffer; - - while ( *search_p <= 32) - { - if (*search_p == '\n') - return false; - search_p++; - if ( !*search_p ) - return false; - - } - - if (*search_p == ';' || *search_p == '#' || // semicolon and # is comment field - (*search_p == '/' && *((search_p)+1) == '/')) // also make // a comment field - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *fmt - -// ... - -//----------------------------------------------------------------------------- -void CSceneTokenProcessor::Error( const char *fmt, ... ) -{ - char string[ 2048 ]; - va_list argptr; - va_start( argptr, fmt ); - Q_vsnprintf( string, sizeof(string), fmt, argptr ); - va_end( argptr ); - - Warning( "%s", string ); - Assert(0); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *buffer - -//----------------------------------------------------------------------------- -void CSceneTokenProcessor::SetBuffer( char *buffer ) -{ - m_pBuffer = buffer; -} - -CSceneTokenProcessor g_TokenProcessor; diff --git a/game/shared/sceneentity_shared.h b/game/shared/sceneentity_shared.h deleted file mode 100644 index 40c78af58..000000000 --- a/game/shared/sceneentity_shared.h +++ /dev/null @@ -1,120 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef SCENEENTITY_SHARED_H -#define SCENEENTITY_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - -#if defined( CLIENT_DLL ) -#define CBaseFlex C_BaseFlex -#define CSceneEntity C_SceneEntity -#endif - -#include "iscenetokenprocessor.h" - -class CBaseFlex; - -class CChoreoEvent; -class CChoreoScene; -class CChoreoActor; -class CSceneEntity; - -//----------------------------------------------------------------------------- -// Purpose: One of a number of currently playing scene events for this actor -//----------------------------------------------------------------------------- -// FIXME: move this, it's only used in in baseflex and baseactor -class CSceneEventInfo -{ -public: - CSceneEventInfo() - : - m_pEvent( 0 ), - m_pScene( 0 ), - m_pActor( 0 ), - m_bStarted( false ), - m_iLayer( -1 ), - m_iPriority( 0 ), - m_nSequence( 0 ), - m_bIsGesture( false ), - m_flWeight( 0.0f ), - m_hTarget(), - m_bIsMoving( false ), - m_bHasArrived( false ), - m_flInitialYaw( 0.0f ), - m_flTargetYaw( 0.0f ), - m_flFacingYaw( 0.0f ), - m_nType( 0 ), - m_flNext( 0.0f ), - m_bClientSide( false ) - { - } - - // The event handle of the current scene event - CChoreoEvent *m_pEvent; - - // Current Scene - CChoreoScene *m_pScene; - - // Current actor - CChoreoActor *m_pActor; - - // Set after the first time the event has been configured ( allows - // bumping markov index only at start of event playback, not every frame ) - bool m_bStarted; - -public: - // EVENT local data... - // FIXME: Evil, make accessors or figure out better place - // FIXME: This won't work, scenes don't save and restore... - int m_iLayer; - int m_iPriority; - int m_nSequence; - bool m_bIsGesture; - float m_flWeight; // used for suppressions of posture while moving - - // movement, faceto targets? - EHANDLE m_hTarget; - bool m_bIsMoving; - bool m_bHasArrived; - float m_flInitialYaw; - float m_flTargetYaw; - float m_flFacingYaw; - - // generic AI events - int m_nType; - float m_flNext; - - // is this event only client side? - bool m_bClientSide; - - void InitWeight( CBaseFlex *pActor ); - float UpdateWeight( CBaseFlex *pActor ); -}; - -//----------------------------------------------------------------------------- -// Purpose: Helper for parsing scene data file -//----------------------------------------------------------------------------- -class CSceneTokenProcessor : public ISceneTokenProcessor -{ -public: - const char *CurrentToken( void ); - bool GetToken( bool crossline ); - bool TokenAvailable( void ); - void Error( const char *fmt, ... ); - void SetBuffer( char *buffer ); -private: - const char *m_pBuffer; - char m_szToken[ 1024 ]; -}; - -extern CSceneTokenProcessor g_TokenProcessor; - -void Scene_Printf( const char *pFormat, ... ); -extern ConVar scene_clientflex; - -#endif // SCENEENTITY_SHARED_H diff --git a/game/shared/sceneimage.cpp b/game/shared/sceneimage.cpp deleted file mode 100644 index 6bbaf2642..000000000 --- a/game/shared/sceneimage.cpp +++ /dev/null @@ -1,535 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#include "sceneimage.h" -#include "choreoscene.h" -#include "iscenetokenprocessor.h" -#include "scenefilecache/SceneImageFile.h" - -//#include "lzma/lzma.h" -extern unsigned char *LZMA_Compress(unsigned char *buffer, unsigned int bufsize, unsigned int *outsize, unsigned int unk = 18); - -#include "tier1/utlbuffer.h" -#include "tier1/UtlStringMap.h" -#include "tier1/utlvector.h" -#include "tier1/UtlSortVector.h" - -#include "scriplib.h" -#include "cmdlib.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CSceneImage : public ISceneImage -{ -public: - virtual bool CreateSceneImageFile( CUtlBuffer &targetBuffer, char const *pchModPath, bool bLittleEndian, bool bQuiet, ISceneCompileStatus *Status ); -}; - -static CSceneImage g_SceneImage; -ISceneImage *g_pSceneImage = &g_SceneImage; - -struct SceneFile_t -{ - SceneFile_t() - { - msecs = 0; - } - - CUtlString fileName; - CUtlBuffer compiledBuffer; - - unsigned int msecs; - CUtlVector< short > soundList; -}; -CUtlVector< SceneFile_t > g_SceneFiles; - -//----------------------------------------------------------------------------- -// Helper for parsing scene data file -//----------------------------------------------------------------------------- -class CSceneTokenProcessor : public ISceneTokenProcessor -{ -public: - const char *CurrentToken( void ) - { - return token; - } - - bool GetToken( bool crossline ) - { - return ::GetToken( crossline ) ? true : false; - } - - bool TokenAvailable( void ) - { - return ::TokenAvailable() ? true : false; - } - - void Error( const char *fmt, ... ) - { - char string[2048]; - va_list argptr; - va_start( argptr, fmt ); - Q_vsnprintf( string, sizeof(string), fmt, argptr ); - va_end( argptr ); - - Warning( "%s", string ); - Assert( 0 ); - } -}; -static CSceneTokenProcessor g_SceneTokenProcessor; -ISceneTokenProcessor *tokenprocessor = &g_SceneTokenProcessor; - -// a simple case insensitive string pool -// the final pool contains all the unique strings seperated by a null -class CChoreoStringPool : public IChoreoStringPool -{ -public: - CChoreoStringPool() : m_StringMap( true ) - { - m_nOffset = 0; - } - - // Returns a valid id into the string table - virtual short FindOrAddString( const char *pString ) - { - int stringId = m_StringMap.Find( pString ); - if ( stringId != m_StringMap.InvalidIndex() ) - { - // found in pool - return stringId; - } - - int &nOffset = m_StringMap[pString]; - nOffset = m_nOffset; - // advance by string and null - m_nOffset += strlen( pString ) + 1; - - stringId = m_StringMap.Find( pString ); - Assert( stringId >= 0 && stringId <= 32767 ); - - return stringId; - } - - virtual bool GetString( short stringId, char *buff, int buffSize ) - { - if ( stringId < 0 || stringId >= m_StringMap.GetNumStrings() ) - { - V_strncpy( buff, "", buffSize ); - return false; - } - V_strncpy( buff, m_StringMap.String( stringId ), buffSize ); - return true; - } - - int GetNumStrings() - { - return m_StringMap.GetNumStrings(); - } - - unsigned int GetPoolSize() - { - return m_nOffset; - } - - // build the final pool - void GetTableAndPool( CUtlVector< unsigned int > &offsets, CUtlBuffer &buffer ) - { - offsets.Purge(); - buffer.Purge(); - - offsets.EnsureCapacity( m_StringMap.GetNumStrings() ); - buffer.EnsureCapacity( m_nOffset ); - - unsigned int currentOffset = 0; - for ( int i = 0; i < m_StringMap.GetNumStrings(); i++ ) - { - offsets.AddToTail( currentOffset ); - - const char *pString = m_StringMap.String( i ); - buffer.Put( pString, strlen( pString ) + 1 ); - - currentOffset += strlen( pString ) + 1; - } - Assert( currentOffset == m_nOffset ); - - // align string pool to end on dword boundary - while ( buffer.TellMaxPut() & 0x03 ) - { - buffer.PutChar( '\0' ); - m_nOffset++; - } - } - - void DumpPool() - { - for ( int i = 0; i < m_StringMap.GetNumStrings(); i++ ) - { - const char *pString = m_StringMap.String( i ); - Msg( "%s\n", pString ); - } - } - - void Reset() - { - m_StringMap.Purge(); - m_nOffset = 0; - } - -private: - CUtlStringMap< int > m_StringMap; - unsigned int m_nOffset; -}; -CChoreoStringPool g_ChoreoStringPool; - -//----------------------------------------------------------------------------- -// Helper for crawling events to determine sounds -//----------------------------------------------------------------------------- -void FindSoundsInEvent( CChoreoEvent *pEvent, CUtlVector< short >& soundList ) -{ - if ( !pEvent || pEvent->GetType() != CChoreoEvent::SPEAK ) - return; - - unsigned short stringId = g_ChoreoStringPool.FindOrAddString( pEvent->GetParameters() ); - if ( soundList.Find( stringId ) == soundList.InvalidIndex() ) - { - soundList.AddToTail( stringId ); - } - - if ( pEvent->GetCloseCaptionType() == CChoreoEvent::CC_MASTER ) - { - char tok[ CChoreoEvent::MAX_CCTOKEN_STRING ]; - if ( pEvent->GetPlaybackCloseCaptionToken( tok, sizeof( tok ) ) ) - { - stringId = g_ChoreoStringPool.FindOrAddString( tok ); - if ( soundList.Find( stringId ) == soundList.InvalidIndex() ) - { - soundList.AddToTail( stringId ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Create binary compiled version of VCD. Stores to a dictionary for later -// post processing -//----------------------------------------------------------------------------- -bool CreateTargetFile_VCD( const char *pSourceName, const char *pTargetName, bool bWriteToZip, bool bLittleEndian ) -{ - CUtlBuffer sourceBuf; - if ( !scriptlib->ReadFileToBuffer( pSourceName, sourceBuf ) ) - { - return false; - } - - CRC32_t crcSource; - CRC32_Init( &crcSource ); - CRC32_ProcessBuffer( &crcSource, sourceBuf.Base(), sourceBuf.TellMaxPut() ); - CRC32_Final( &crcSource ); - - ParseFromMemory( (char *)sourceBuf.Base(), sourceBuf.TellMaxPut() ); - - CChoreoScene *pChoreoScene = ChoreoLoadScene( pSourceName, NULL, &g_SceneTokenProcessor, Msg ); - if ( !pChoreoScene ) - { - return false; - } - - int iScene = g_SceneFiles.AddToTail(); - - g_SceneFiles[iScene].fileName.Set( pSourceName ); - - // Walk all events looking for SPEAK events - CChoreoEvent *pEvent; - for ( int i = 0; i < pChoreoScene->GetNumEvents(); ++i ) - { - pEvent = pChoreoScene->GetEvent( i ); - FindSoundsInEvent( pEvent, g_SceneFiles[iScene].soundList ); - } - - // calc duration - g_SceneFiles[iScene].msecs = (unsigned int)( pChoreoScene->FindStopTime() * 1000.0f + 0.5f ); - - // compile to binary buffer - g_SceneFiles[iScene].compiledBuffer.SetBigEndian( !bLittleEndian ); - pChoreoScene->SaveToBinaryBuffer( g_SceneFiles[iScene].compiledBuffer, crcSource, &g_ChoreoStringPool ); - - unsigned int compressedSize; - unsigned char *pCompressedBuffer = LZMA_Compress( (unsigned char *)g_SceneFiles[iScene].compiledBuffer.Base(), g_SceneFiles[iScene].compiledBuffer.TellMaxPut(), &compressedSize ); - if ( pCompressedBuffer ) - { - // replace the compiled buffer with the compressed version - g_SceneFiles[iScene].compiledBuffer.Purge(); - g_SceneFiles[iScene].compiledBuffer.EnsureCapacity( compressedSize ); - g_SceneFiles[iScene].compiledBuffer.Put( pCompressedBuffer, compressedSize ); - free( pCompressedBuffer ); - } - - delete pChoreoScene; - - return true; -} - -class CSceneImageEntryLessFunc -{ -public: - bool Less( const SceneImageEntry_t &entryLHS, const SceneImageEntry_t &entryRHS, void *pCtx ) - { - return entryLHS.crcFilename < entryRHS.crcFilename; - } -}; - - - -//----------------------------------------------------------------------------- -// A Scene image file contains all the compiled .XCD -//----------------------------------------------------------------------------- -bool CSceneImage::CreateSceneImageFile( CUtlBuffer &targetBuffer, char const *pchModPath, bool bLittleEndian, bool bQuiet, ISceneCompileStatus *pStatus ) -{ - CUtlVector vcdFileList; - CUtlSymbolTable vcdSymbolTable( 0, 32, true ); - - Msg( "\n" ); - - // get all the VCD files according to the seacrh paths - char searchPaths[512]; - g_pFullFileSystem->GetSearchPath( "GAME", false, searchPaths, sizeof( searchPaths ) ); - char *pPath = strtok( searchPaths, ";" ); - while ( pPath ) - { - int currentCount = vcdFileList.Count(); - - char szPath[MAX_PATH]; - V_ComposeFileName( pPath, "scenes/*.vcd", szPath, sizeof( szPath ) ); - - scriptlib->FindFiles( szPath, true, vcdFileList ); - - Msg( "Scenes: Searching '%s' - Found %d scenes.\n", szPath, vcdFileList.Count() - currentCount ); - - pPath = strtok( NULL, ";" ); - } - - if ( !vcdFileList.Count() ) - { - Msg( "Scenes: No Scene Files found!\n" ); - return false; - } - - // iterate and convert all the VCD files - bool bGameIsTF = V_stristr( pchModPath, "\\tf" ) != NULL; - for ( int i=0; iUpdateStatus( pFilename, bQuiet, i, vcdFileList.Count() ); - - if ( !CreateTargetFile_VCD( pFilename, "", false, bLittleEndian ) ) - { - Error( "CreateSceneImageFile: Failed on '%s' conversion!\n", pFilename ); - } - - - } - } - - if ( !g_SceneFiles.Count() ) - { - // nothing to do - return true; - } - - Msg( "Scenes: Finalizing %d unique scenes.\n", g_SceneFiles.Count() ); - - - // get the string pool - CUtlVector< unsigned int > stringOffsets; - CUtlBuffer stringPool; - g_ChoreoStringPool.GetTableAndPool( stringOffsets, stringPool ); - - if ( !bQuiet ) - { - Msg( "Scenes: String Table: %d bytes\n", stringOffsets.Count() * sizeof( int ) ); - Msg( "Scenes: String Pool: %d bytes\n", stringPool.TellMaxPut() ); - } - - // first header, then lookup table, then string pool blob - int stringPoolStart = sizeof( SceneImageHeader_t ) + stringOffsets.Count() * sizeof( int ); - // then directory - int sceneEntryStart = stringPoolStart + stringPool.TellMaxPut(); - // then variable sized summaries - int sceneSummaryStart = sceneEntryStart + g_SceneFiles.Count() * sizeof( SceneImageEntry_t ); - // then variable sized compiled binary scene data - int sceneDataStart = 0; - - // construct header - SceneImageHeader_t imageHeader = { 0 }; - imageHeader.nId = SCENE_IMAGE_ID; - imageHeader.nVersion = SCENE_IMAGE_VERSION; - imageHeader.nNumScenes = g_SceneFiles.Count(); - imageHeader.nNumStrings = stringOffsets.Count(); - imageHeader.nSceneEntryOffset = sceneEntryStart; - if ( !bLittleEndian ) - { - imageHeader.nId = BigLong( imageHeader.nId ); - imageHeader.nVersion = BigLong( imageHeader.nVersion ); - imageHeader.nNumScenes = BigLong( imageHeader.nNumScenes ); - imageHeader.nNumStrings = BigLong( imageHeader.nNumStrings ); - imageHeader.nSceneEntryOffset = BigLong( imageHeader.nSceneEntryOffset ); - } - targetBuffer.Put( &imageHeader, sizeof( imageHeader ) ); - - // header is immediately followed by string table and pool - for ( int i = 0; i < stringOffsets.Count(); i++ ) - { - unsigned int offset = stringPoolStart + stringOffsets[i]; - if ( !bLittleEndian ) - { - offset = BigLong( offset ); - } - targetBuffer.PutInt( offset ); - } - Assert( stringPoolStart == targetBuffer.TellMaxPut() ); - targetBuffer.Put( stringPool.Base(), stringPool.TellMaxPut() ); - - // construct directory - CUtlSortVector< SceneImageEntry_t, CSceneImageEntryLessFunc > imageDirectory; - imageDirectory.EnsureCapacity( g_SceneFiles.Count() ); - - // build directory - // directory is linear sorted by filename checksum for later binary search - for ( int i = 0; i < g_SceneFiles.Count(); i++ ) - { - SceneImageEntry_t imageEntry = { 0 }; - - // name needs to be normalized for determinstic later CRC name calc - // calc crc based on scenes\anydir\anyscene.vcd - char szCleanName[MAX_PATH]; - V_strncpy( szCleanName, g_SceneFiles[i].fileName.String(), sizeof( szCleanName ) ); - V_strlower( szCleanName ); - V_FixSlashes( szCleanName ); - char *pName = V_stristr( szCleanName, "scenes\\" ); - if ( !pName ) - { - // must have scenes\ in filename - Error( "CreateSceneImageFile: Unexpected lack of scenes prefix on %s\n", g_SceneFiles[i].fileName.String() ); - } - - CRC32_t crcFilename = CRC32_ProcessSingleBuffer( pName, strlen( pName ) ); - imageEntry.crcFilename = crcFilename; - - // temp store an index to its file, fixup later, necessary to access post sort - imageEntry.nDataOffset = i; - if ( imageDirectory.Find( imageEntry ) != imageDirectory.InvalidIndex() ) - { - // filename checksums must be unique or runtime binary search would be bogus - Error( "CreateSceneImageFile: Unexpected filename checksum collision!\n" ); - } - - imageDirectory.Insert( imageEntry ); - } - - // determine sort order and start of data after dynamic summaries - CUtlVector< int > writeOrder; - writeOrder.EnsureCapacity( g_SceneFiles.Count() ); - sceneDataStart = sceneSummaryStart; - for ( int i = 0; i < imageDirectory.Count(); i++ ) - { - // reclaim offset, indicates write order of scene file - int iScene = imageDirectory[i].nDataOffset; - writeOrder.AddToTail( iScene ); - - // march past each variable sized summary to determine start of scene data - int numSounds = g_SceneFiles[iScene].soundList.Count(); - sceneDataStart += sizeof( SceneImageSummary_t ) + ( numSounds - 1 ) * sizeof( int ); - } - - // finalize and write directory - Assert( sceneEntryStart == targetBuffer.TellMaxPut() ); - int nSummaryOffset = sceneSummaryStart; - int nDataOffset = sceneDataStart; - for ( int i = 0; i < imageDirectory.Count(); i++ ) - { - int iScene = writeOrder[i]; - - imageDirectory[i].nDataOffset = nDataOffset; - imageDirectory[i].nDataLength = g_SceneFiles[iScene].compiledBuffer.TellMaxPut(); - imageDirectory[i].nSceneSummaryOffset = nSummaryOffset; - if ( !bLittleEndian ) - { - imageDirectory[i].crcFilename = BigLong( imageDirectory[i].crcFilename ); - imageDirectory[i].nDataOffset = BigLong( imageDirectory[i].nDataOffset ); - imageDirectory[i].nDataLength = BigLong( imageDirectory[i].nDataLength ); - imageDirectory[i].nSceneSummaryOffset = BigLong( imageDirectory[i].nSceneSummaryOffset ); - } - targetBuffer.Put( &imageDirectory[i], sizeof( SceneImageEntry_t ) ); - - int numSounds = g_SceneFiles[iScene].soundList.Count(); - nSummaryOffset += sizeof( SceneImageSummary_t ) + (numSounds - 1) * sizeof( int ); - - nDataOffset += g_SceneFiles[iScene].compiledBuffer.TellMaxPut(); - } - - // finalize and write summaries - Assert( sceneSummaryStart == targetBuffer.TellMaxPut() ); - for ( int i = 0; i < imageDirectory.Count(); i++ ) - { - int iScene = writeOrder[i]; - int msecs = g_SceneFiles[iScene].msecs; - int soundCount = g_SceneFiles[iScene].soundList.Count(); - if ( !bLittleEndian ) - { - msecs = BigLong( msecs ); - soundCount = BigLong( soundCount ); - } - targetBuffer.PutInt( msecs ); - targetBuffer.PutInt( soundCount ); - for ( int j = 0; j < g_SceneFiles[iScene].soundList.Count(); j++ ) - { - int soundId = g_SceneFiles[iScene].soundList[j]; - if ( !bLittleEndian ) - { - soundId = BigLong( soundId ); - } - targetBuffer.PutInt( soundId ); - } - } - - // finalize and write data - Assert( sceneDataStart == targetBuffer.TellMaxPut() ); - for ( int i = 0; i < imageDirectory.Count(); i++ ) - { - int iScene = writeOrder[i]; - targetBuffer.Put( g_SceneFiles[iScene].compiledBuffer.Base(), g_SceneFiles[iScene].compiledBuffer.TellMaxPut() ); - } - - if ( !bQuiet ) - { - Msg( "Scenes: Final size: %.2f MB\n", targetBuffer.TellMaxPut() / (1024.0f * 1024.0f ) ); - } - - // cleanup - g_SceneFiles.Purge(); - - return true; -} diff --git a/game/shared/sceneimage.h b/game/shared/sceneimage.h deleted file mode 100644 index 0c0b57846..000000000 --- a/game/shared/sceneimage.h +++ /dev/null @@ -1,33 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SCENEIMAGE_H -#define SCENEIMAGE_H -#ifdef _WIN32 -#pragma once -#endif - -class ISceneTokenProcessor; - -class ISceneCompileStatus -{ -public: - virtual void UpdateStatus( char const *pchSceneName, bool bQuiet, int nIndex, int nCount ) = 0; -}; - -class CUtlBuffer; - -class ISceneImage -{ -public: - virtual bool CreateSceneImageFile( CUtlBuffer &targetBuffer, char const *pchModPath, bool bLittleEndian, bool bQuiet, ISceneCompileStatus *Status ) = 0; -}; - -extern ISceneImage *g_pSceneImage; -extern ISceneTokenProcessor *tokenprocessor; - -#endif // SCENEIMAGE_H diff --git a/game/shared/script_intro_shared.cpp b/game/shared/script_intro_shared.cpp deleted file mode 100644 index bf1c630f6..000000000 --- a/game/shared/script_intro_shared.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "cbase.h" - -//----------------------------------------------------------------------------- -// Purpose: Calculate the FOV for the intro sequence (needed by both server and client) -//----------------------------------------------------------------------------- -float ScriptInfo_CalculateFOV( float flFOVBlendStartTime, float flNextFOVBlendTime, int nFOV, int nNextFOV, bool bSplineRamp ) -{ - // Handle the spline case - if ( bSplineRamp ) - { - //If we're past the zoom time, just take the new value and stop transitioning - float deltaTime = (float)( gpGlobals->curtime - flFOVBlendStartTime ) / ( flNextFOVBlendTime - flFOVBlendStartTime ); - if ( deltaTime >= 1.0f ) - return nNextFOV; - - float flResult = SimpleSplineRemapVal( deltaTime, 0.0f, 1.0f, (float) nFOV, (float) nNextFOV ); - - // Msg("FOV BLENDING: curtime %.2f StartedAt %.2f FinishAt: %.2f\n", gpGlobals->curtime, flFOVBlendStartTime, flNextFOVBlendTime ); - // Msg(" Perc: %.2f Start: %d End: %d FOV: %.2f\n", SimpleSplineRemapVal( deltaTime, 0.0f, 1.0f, nFOV, nNextFOV ), nFOV, nNextFOV, flResult ); - - return flResult; - } - - // Common, linear blend - if ( (flNextFOVBlendTime - flFOVBlendStartTime) != 0 ) - { - float flResult = RemapValClamped( gpGlobals->curtime, flFOVBlendStartTime, flNextFOVBlendTime, (float) nFOV, (float) nNextFOV ); - - // Msg("FOV BLENDING: curtime %.2f StartedAt %.2f FinishAt: %.2f\n", gpGlobals->curtime, flFOVBlendStartTime, flNextFOVBlendTime ); - // Msg(" Perc: %.2f Start: %d End: %d FOV: %.2f\n", RemapValClamped( gpGlobals->curtime, flFOVBlendStartTime, flNextFOVBlendTime, 0.0, 1.0 ), nFOV, nNextFOV, flResult ); - - return flResult; - } - - - // Msg("FOV BLENDING: JUMPED TO NEXT FOV (%d)\n", nNextFOV ); - return nNextFOV; -} diff --git a/game/shared/scriptevent.h b/game/shared/scriptevent.h deleted file mode 100644 index bcdf4d48c..000000000 --- a/game/shared/scriptevent.h +++ /dev/null @@ -1,30 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef SCRIPTEVENT_H -#define SCRIPTEVENT_H - -#define SCRIPT_EVENT_DEAD 1000 // character is now dead -#define SCRIPT_EVENT_NOINTERRUPT 1001 // does not allow interrupt -#define SCRIPT_EVENT_CANINTERRUPT 1002 // will allow interrupt -#define SCRIPT_EVENT_FIREEVENT 1003 // Fires OnScriptEventXX output in the script entity, where XX is the event number from the options data. -#define SCRIPT_EVENT_SOUND 1004 // Play named wave file (on CHAN_BODY) -#define SCRIPT_EVENT_SENTENCE 1005 // Play named sentence -#define SCRIPT_EVENT_INAIR 1006 // Leave the character in air at the end of the sequence (don't find the floor) -#define SCRIPT_EVENT_ENDANIMATION 1007 // Set the animation by name after the sequence completes -#define SCRIPT_EVENT_SOUND_VOICE 1008 // Play named wave file (on CHAN_VOICE) -#define SCRIPT_EVENT_SENTENCE_RND1 1009 // Play sentence group 25% of the time -#define SCRIPT_EVENT_NOT_DEAD 1010 // Bring back to life (for life/death sequences) -#define SCRIPT_EVENT_EMPHASIS 1011 // Emphasis point for gestures - -#define SCRIPT_EVENT_BODYGROUPON 1020 // Turn a bodygroup on -#define SCRIPT_EVENT_BODYGROUPOFF 1021 // Turn a bodygroup off -#define SCRIPT_EVENT_BODYGROUPTEMP 1022 // Turn a bodygroup on until this sequence ends - -#define SCRIPT_EVENT_FIRE_INPUT 1100 // Fires named input on the event handler - -#endif //SCRIPTEVENT_H diff --git a/game/shared/sdk/sdk_basegrenade_projectile.cpp b/game/shared/sdk/sdk_basegrenade_projectile.cpp deleted file mode 100644 index c7fe71502..000000000 --- a/game/shared/sdk/sdk_basegrenade_projectile.cpp +++ /dev/null @@ -1,263 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "sdk_basegrenade_projectile.h" - -extern ConVar sv_gravity; - - -#ifdef CLIENT_DLL - - #include "c_sdk_player.h" - -#else - - #include "soundent.h" - - BEGIN_DATADESC( CBaseGrenadeProjectile ) - DEFINE_THINKFUNC( DangerSoundThink ), - END_DATADESC() - -#endif - - -IMPLEMENT_NETWORKCLASS_ALIASED( BaseGrenadeProjectile, DT_BaseGrenadeProjectile ) - -BEGIN_NETWORK_TABLE( CBaseGrenadeProjectile, DT_BaseGrenadeProjectile ) - #ifdef CLIENT_DLL - RecvPropVector( RECVINFO( m_vInitialVelocity ) ) - #else - SendPropVector( SENDINFO( m_vInitialVelocity ), - 20, // nbits - 0, // flags - -3000, // low value - 3000 // high value - ) - #endif -END_NETWORK_TABLE() - - -#ifdef CLIENT_DLL - - - void CBaseGrenadeProjectile::PostDataUpdate( DataUpdateType_t type ) - { - BaseClass::PostDataUpdate( type ); - - if ( type == DATA_UPDATE_CREATED ) - { - // Now stick our initial velocity into the interpolation history - CInterpolatedVar< Vector > &interpolator = GetOriginInterpolator(); - - interpolator.ClearHistory(); - float changeTime = GetLastChangeTime( LATCH_SIMULATION_VAR ); - - // Add a sample 1 second back. - Vector vCurOrigin = GetLocalOrigin() - m_vInitialVelocity; - interpolator.AddToHead( changeTime - 1.0, &vCurOrigin, false ); - - // Add the current sample. - vCurOrigin = GetLocalOrigin(); - interpolator.AddToHead( changeTime, &vCurOrigin, false ); - } - } - - int CBaseGrenadeProjectile::DrawModel( int flags ) - { - // During the first half-second of our life, don't draw ourselves if he's - // still playing his throw animation. - // (better yet, we could draw ourselves in his hand). - if ( GetThrower() != C_BasePlayer::GetLocalPlayer() ) - { - if ( gpGlobals->curtime - m_flSpawnTime < 0.5 ) - { - C_SDKPlayer *pPlayer = dynamic_cast( GetThrower() ); - if ( pPlayer && pPlayer->m_PlayerAnimState->IsThrowingGrenade() ) - { - return 0; - } - } - } - - return BaseClass::DrawModel( flags ); - } - - void CBaseGrenadeProjectile::Spawn() - { - m_flSpawnTime = gpGlobals->curtime; - BaseClass::Spawn(); - } - -#else - - void CBaseGrenadeProjectile::Spawn( void ) - { - BaseClass::Spawn(); - - SetSolidFlags( FSOLID_NOT_STANDABLE ); - SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_CUSTOM ); - SetSolid( SOLID_BBOX ); // So it will collide with physics props! - - // smaller, cube bounding box so we rest on the ground - SetSize( Vector ( -2, -2, -2 ), Vector ( 2, 2, 2 ) ); - } - - void CBaseGrenadeProjectile::DangerSoundThink( void ) - { - if (!IsInWorld()) - { - Remove( ); - return; - } - - if( gpGlobals->curtime > m_flDetonateTime ) - { - Detonate(); - return; - } - - CSoundEnt::InsertSound ( SOUND_DANGER, GetAbsOrigin() + GetAbsVelocity() * 0.5, (int)GetAbsVelocity().Length( ), 0.2 ); - - SetNextThink( gpGlobals->curtime + 0.2 ); - - if (GetWaterLevel() != 0) - { - SetAbsVelocity( GetAbsVelocity() * 0.5 ); - } - } - - //Sets the time at which the grenade will explode - void CBaseGrenadeProjectile::SetDetonateTimerLength( float timer ) - { - m_flDetonateTime = gpGlobals->curtime + timer; - } - - void CBaseGrenadeProjectile::ResolveFlyCollisionCustom( trace_t &trace, Vector &vecVelocity ) - { - //Assume all surfaces have the same elasticity - float flSurfaceElasticity = 1.0; - - //Don't bounce off of players with perfect elasticity - if( trace.m_pEnt && trace.m_pEnt->IsPlayer() ) - { - flSurfaceElasticity = 0.3; - } - - // if its breakable glass and we kill it, don't bounce. - // give some damage to the glass, and if it breaks, pass - // through it. - bool breakthrough = false; - - if( trace.m_pEnt && FClassnameIs( trace.m_pEnt, "func_breakable" ) ) - { - breakthrough = true; - } - - if( trace.m_pEnt && FClassnameIs( trace.m_pEnt, "func_breakable_surf" ) ) - { - breakthrough = true; - } - - if (breakthrough) - { - CTakeDamageInfo info( this, this, 10, DMG_CLUB ); - trace.m_pEnt->DispatchTraceAttack( info, GetAbsVelocity(), &trace ); - - ApplyMultiDamage(); - - if( trace.m_pEnt->m_iHealth <= 0 ) - { - // slow our flight a little bit - Vector vel = GetAbsVelocity(); - - vel *= 0.4; - - SetAbsVelocity( vel ); - return; - } - } - - float flTotalElasticity = GetElasticity() * flSurfaceElasticity; - flTotalElasticity = clamp( flTotalElasticity, 0.0f, 0.9f ); - - // NOTE: A backoff of 2.0f is a reflection - Vector vecAbsVelocity; - PhysicsClipVelocity( GetAbsVelocity(), trace.plane.normal, vecAbsVelocity, 2.0f ); - vecAbsVelocity *= flTotalElasticity; - - // Get the total velocity (player + conveyors, etc.) - VectorAdd( vecAbsVelocity, GetBaseVelocity(), vecVelocity ); - float flSpeedSqr = DotProduct( vecVelocity, vecVelocity ); - - // Stop if on ground. - if ( trace.plane.normal.z > 0.7f ) // Floor - { - // Verify that we have an entity. - CBaseEntity *pEntity = trace.m_pEnt; - Assert( pEntity ); - - SetAbsVelocity( vecAbsVelocity ); - - if ( flSpeedSqr < ( 30 * 30 ) ) - { - if ( pEntity->IsStandable() ) - { - SetGroundEntity( pEntity ); - } - - // Reset velocities. - SetAbsVelocity( vec3_origin ); - SetLocalAngularVelocity( vec3_angle ); - - //align to the ground so we're not standing on end - QAngle angle; - VectorAngles( trace.plane.normal, angle ); - - // rotate randomly in yaw - angle[1] = random->RandomFloat( 0, 360 ); - - // TODO: rotate around trace.plane.normal - - SetAbsAngles( angle ); - } - else - { - Vector vecDelta = GetBaseVelocity() - vecAbsVelocity; - Vector vecBaseDir = GetBaseVelocity(); - VectorNormalize( vecBaseDir ); - float flScale = vecDelta.Dot( vecBaseDir ); - - VectorScale( vecAbsVelocity, ( 1.0f - trace.fraction ) * gpGlobals->frametime, vecVelocity ); - VectorMA( vecVelocity, ( 1.0f - trace.fraction ) * gpGlobals->frametime, GetBaseVelocity() * flScale, vecVelocity ); - PhysicsPushEntity( vecVelocity, &trace ); - } - } - else - { - // If we get *too* slow, we'll stick without ever coming to rest because - // we'll get pushed down by gravity faster than we can escape from the wall. - if ( flSpeedSqr < ( 30 * 30 ) ) - { - // Reset velocities. - SetAbsVelocity( vec3_origin ); - SetLocalAngularVelocity( vec3_angle ); - } - else - { - SetAbsVelocity( vecAbsVelocity ); - } - } - - BounceSound(); - } - - void CBaseGrenadeProjectile::SetupInitialTransmittedGrenadeVelocity( const Vector &velocity ) - { - m_vInitialVelocity = velocity; - } - -#endif diff --git a/game/shared/sdk/sdk_basegrenade_projectile.h b/game/shared/sdk/sdk_basegrenade_projectile.h deleted file mode 100644 index 57f9fbdfd..000000000 --- a/game/shared/sdk/sdk_basegrenade_projectile.h +++ /dev/null @@ -1,78 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef BASECSGRENADE_PROJECTILE_H -#define BASECSGRENADE_PROJECTILE_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "basegrenade_shared.h" - - -#ifdef CLIENT_DLL - #define CBaseGrenadeProjectile C_BaseGrenadeProjectile -#endif - - -class CBaseGrenadeProjectile : public CBaseGrenade -{ -public: - DECLARE_CLASS( CBaseGrenadeProjectile, CBaseGrenade ); - DECLARE_NETWORKCLASS(); - - virtual void Spawn(); - - -public: - - // This gets sent to the client and placed in the client's interpolation history - // so the projectile starts out moving right off the bat. - CNetworkVector( m_vInitialVelocity ); - - -#ifdef CLIENT_DLL - CBaseGrenadeProjectile() {} - CBaseGrenadeProjectile( const CBaseGrenadeProjectile& ) {} - virtual int DrawModel( int flags ); - virtual void PostDataUpdate( DataUpdateType_t type ); - - float m_flSpawnTime; -#else - DECLARE_DATADESC(); - - //Constants for all CS Grenades - static inline float GetGrenadeGravity() { return 0.4f; } - static inline const float GetGrenadeFriction() { return 0.2f; } - static inline const float GetGrenadeElasticity() { return 0.45f; } - - //Think function to emit danger sounds for the AI - void DangerSoundThink( void ); - - virtual float GetShakeAmplitude( void ) { return 0.0f; } - - // Specify what velocity we want the grenade to have on the client immediately. - // Without this, the entity wouldn't have an interpolation history initially, so it would - // sit still until it had gotten a few updates from the server. - void SetupInitialTransmittedGrenadeVelocity( const Vector &velocity ); - -protected: - - //Set the time to detonate ( now + timer ) - void SetDetonateTimerLength( float timer ); - -private: - - //Custom collision to allow for constant elasticity on hit surfaces - virtual void ResolveFlyCollisionCustom( trace_t &trace, Vector &vecVelocity ); - - float m_flDetonateTime; -#endif -}; - - -#endif // BASECSGRENADE_PROJECTILE_H diff --git a/game/shared/sdk/sdk_fx_shared.cpp b/game/shared/sdk/sdk_fx_shared.cpp deleted file mode 100644 index c5ea34ddf..000000000 --- a/game/shared/sdk/sdk_fx_shared.cpp +++ /dev/null @@ -1,224 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "sdk_fx_shared.h" -#include "weapon_sdkbase.h" - -#ifndef CLIENT_DLL - #include "ilagcompensationmanager.h" -#endif - -#ifdef CLIENT_DLL - -#include "fx_impact.h" -#include "c_sdk_player.h" - - // this is a cheap ripoff from CBaseCombatWeapon::WeaponSound(): - void FX_WeaponSound( - int iPlayerIndex, - WeaponSound_t sound_type, - const Vector &vOrigin, - CSDKWeaponInfo *pWeaponInfo ) - { - - // If we have some sounds from the weapon classname.txt file, play a random one of them - const char *shootsound = pWeaponInfo->aShootSounds[ sound_type ]; - if ( !shootsound || !shootsound[0] ) - return; - - CBroadcastRecipientFilter filter; // this is client side only - if ( !te->CanPredict() ) - return; - - CBaseEntity::EmitSound( filter, iPlayerIndex, shootsound, &vOrigin ); - } - - class CGroupedSound - { - public: - string_t m_SoundName; - Vector m_vPos; - }; - - CUtlVector g_GroupedSounds; - - - // Called by the ImpactSound function. - void ShotgunImpactSoundGroup( const char *pSoundName, const Vector &vEndPos ) - { - // Don't play the sound if it's too close to another impact sound. - for ( int i=0; i < g_GroupedSounds.Count(); i++ ) - { - CGroupedSound *pSound = &g_GroupedSounds[i]; - - if ( vEndPos.DistToSqr( pSound->m_vPos ) < 300*300 ) - { - if ( Q_stricmp( pSound->m_SoundName, pSoundName ) == 0 ) - return; - } - } - - // Ok, play the sound and add it to the list. - CLocalPlayerFilter filter; - C_BaseEntity::EmitSound( filter, NULL, pSoundName, &vEndPos ); - - int j = g_GroupedSounds.AddToTail(); - g_GroupedSounds[j].m_SoundName = pSoundName; - g_GroupedSounds[j].m_vPos = vEndPos; - } - - - void StartGroupingSounds() - { - Assert( g_GroupedSounds.Count() == 0 ); - SetImpactSoundRoute( ShotgunImpactSoundGroup ); - } - - - void EndGroupingSounds() - { - g_GroupedSounds.Purge(); - SetImpactSoundRoute( NULL ); - } - -#else - - #include "sdk_player.h" - #include "te_firebullets.h" - - // Server doesn't play sounds anyway. - void StartGroupingSounds() {} - void EndGroupingSounds() {} - void FX_WeaponSound ( int iPlayerIndex, - WeaponSound_t sound_type, - const Vector &vOrigin, - CSDKWeaponInfo *pWeaponInfo ) {}; - -#endif - - - -// This runs on both the client and the server. -// On the server, it only does the damage calculations. -// On the client, it does all the effects. -void FX_FireBullets( - int iPlayerIndex, - const Vector &vOrigin, - const QAngle &vAngles, - int iWeaponID, - int iMode, - int iSeed, - float flSpread - ) -{ - bool bDoEffects = true; - -#ifdef CLIENT_DLL - C_SDKPlayer *pPlayer = ToSDKPlayer( ClientEntityList().GetBaseEntity( iPlayerIndex ) ); -#else - CSDKPlayer *pPlayer = ToSDKPlayer( UTIL_PlayerByIndex( iPlayerIndex) ); -#endif - - const char * weaponAlias = WeaponIDToAlias( iWeaponID ); - - if ( !weaponAlias ) - { - DevMsg("FX_FireBullets: weapon alias for ID %i not found\n", iWeaponID ); - return; - } - - char wpnName[128]; - Q_snprintf( wpnName, sizeof( wpnName ), "weapon_%s", weaponAlias ); - WEAPON_FILE_INFO_HANDLE hWpnInfo = LookupWeaponInfoSlot( wpnName ); - - if ( hWpnInfo == GetInvalidWeaponInfoHandle() ) - { - DevMsg("FX_FireBullets: LookupWeaponInfoSlot failed for weapon %s\n", wpnName ); - return; - } - - CSDKWeaponInfo *pWeaponInfo = static_cast< CSDKWeaponInfo* >( GetFileWeaponInfoFromHandle( hWpnInfo ) ); - -#ifdef CLIENT_DLL - // Do the firing animation event. - if ( pPlayer && !pPlayer->IsDormant() ) - { - if ( iMode == Primary_Mode ) - pPlayer->m_PlayerAnimState->DoAnimationEvent( PLAYERANIMEVENT_FIRE_GUN_PRIMARY ); - else - pPlayer->m_PlayerAnimState->DoAnimationEvent( PLAYERANIMEVENT_FIRE_GUN_SECONDARY ); - } -#else - // if this is server code, send the effect over to client as temp entity - // Dispatch one message for all the bullet impacts and sounds. - TE_FireBullets( - iPlayerIndex, - vOrigin, - vAngles, - iWeaponID, - iMode, - iSeed, - flSpread - ); - - bDoEffects = false; // no effects on server -#endif - - iSeed++; - - int iDamage = pWeaponInfo->m_iDamage; - int iAmmoType = pWeaponInfo->iAmmoType; - - WeaponSound_t sound_type = SINGLE; - - if ( bDoEffects) - { - FX_WeaponSound( iPlayerIndex, sound_type, vOrigin, pWeaponInfo ); - } - - - // Fire bullets, calculate impacts & effects - - if ( !pPlayer ) - return; - - StartGroupingSounds(); - -#if !defined (CLIENT_DLL) - // Move other players back to history positions based on local player's lag - lagcompensation->StartLagCompensation( pPlayer, pPlayer->GetCurrentCommand() ); -#endif - - for ( int iBullet=0; iBullet < pWeaponInfo->m_iBullets; iBullet++ ) - { - RandomSeed( iSeed ); // init random system with this seed - - // Get circular gaussian spread. - float x, y; - x = RandomFloat( -0.5, 0.5 ) + RandomFloat( -0.5, 0.5 ); - y = RandomFloat( -0.5, 0.5 ) + RandomFloat( -0.5, 0.5 ); - - iSeed++; // use new seed for next bullet - - pPlayer->FireBullet( - vOrigin, - vAngles, - flSpread, - iDamage, - iAmmoType, - pPlayer, - bDoEffects, - x,y ); - } - -#if !defined (CLIENT_DLL) - lagcompensation->FinishLagCompensation( pPlayer ); -#endif - - EndGroupingSounds(); -} - diff --git a/game/shared/sdk/sdk_fx_shared.h b/game/shared/sdk/sdk_fx_shared.h deleted file mode 100644 index a875d0954..000000000 --- a/game/shared/sdk/sdk_fx_shared.h +++ /dev/null @@ -1,27 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef FX_CS_SHARED_H -#define FX_CS_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - -// This runs on both the client and the server. -// On the server, it only does the damage calculations. -// On the client, it does all the effects. -void FX_FireBullets( - int iPlayer, - const Vector &vOrigin, - const QAngle &vAngles, - int iWeaponID, - int iMode, - int iSeed, - float flSpread - ); - - -#endif // FX_CS_SHARED_H diff --git a/game/shared/sdk/sdk_gamemovement.cpp b/game/shared/sdk/sdk_gamemovement.cpp deleted file mode 100644 index eed94bb98..000000000 --- a/game/shared/sdk/sdk_gamemovement.cpp +++ /dev/null @@ -1,53 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -//========= Copyright 1996-2001, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= -#include "cbase.h" -#include "gamemovement.h" -#include "sdk_gamerules.h" -#include "sdk_shareddefs.h" -#include "in_buttons.h" -#include "movevars_shared.h" - - -#ifdef CLIENT_DLL - #include "c_sdk_player.h" -#else - #include "sdk_player.h" -#endif - - -class CSDKGameMovement : public CGameMovement -{ -public: - DECLARE_CLASS( CSDKGameMovement, CGameMovement ); - - CSDKGameMovement(); -}; - - -// Expose our interface. -static CSDKGameMovement g_GameMovement; -IGameMovement *g_pGameMovement = ( IGameMovement * )&g_GameMovement; - -EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CGameMovement, IGameMovement,INTERFACENAME_GAMEMOVEMENT, g_GameMovement ); - - -// ---------------------------------------------------------------------------------------- // -// CSDKGameMovement. -// ---------------------------------------------------------------------------------------- // - -CSDKGameMovement::CSDKGameMovement() -{ - //m_vecViewOffsetNormal = SDK_PLAYER_VIEW_OFFSET; -} - diff --git a/game/shared/sdk/sdk_gamerules.cpp b/game/shared/sdk/sdk_gamerules.cpp deleted file mode 100644 index b3899ff4e..000000000 --- a/game/shared/sdk/sdk_gamerules.cpp +++ /dev/null @@ -1,373 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: The TF Game rules -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "sdk_gamerules.h" -#include "ammodef.h" -#include "KeyValues.h" -#include "weapon_sdkbase.h" - - -#ifdef CLIENT_DLL - - -#else - - #include "voice_gamemgr.h" - #include "team.h" - -#endif - - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -#ifndef CLIENT_DLL -LINK_ENTITY_TO_CLASS(info_player_terrorist, CPointEntity); -LINK_ENTITY_TO_CLASS(info_player_counterterrorist,CPointEntity); -#endif - -REGISTER_GAMERULES_CLASS( CSDKGameRules ); - - -BEGIN_NETWORK_TABLE_NOBASE( CSDKGameRules, DT_SDKGameRules ) -END_NETWORK_TABLE() - - -LINK_ENTITY_TO_CLASS( sdk_gamerules, CSDKGameRulesProxy ); -IMPLEMENT_NETWORKCLASS_ALIASED( SDKGameRulesProxy, DT_SDKGameRulesProxy ) - - -#ifdef CLIENT_DLL - void RecvProxy_SDKGameRules( const RecvProp *pProp, void **pOut, void *pData, int objectID ) - { - CSDKGameRules *pRules = SDKGameRules(); - Assert( pRules ); - *pOut = pRules; - } - - BEGIN_RECV_TABLE( CSDKGameRulesProxy, DT_SDKGameRulesProxy ) - RecvPropDataTable( "sdk_gamerules_data", 0, 0, &REFERENCE_RECV_TABLE( DT_SDKGameRules ), RecvProxy_SDKGameRules ) - END_RECV_TABLE() -#else - void *SendProxy_SDKGameRules( const SendProp *pProp, const void *pStructBase, const void *pData, CSendProxyRecipients *pRecipients, int objectID ) - { - CSDKGameRules *pRules = SDKGameRules(); - Assert( pRules ); - pRecipients->SetAllRecipients(); - return pRules; - } - - BEGIN_SEND_TABLE( CSDKGameRulesProxy, DT_SDKGameRulesProxy ) - SendPropDataTable( "sdk_gamerules_data", 0, &REFERENCE_SEND_TABLE( DT_SDKGameRules ), SendProxy_SDKGameRules ) - END_SEND_TABLE() -#endif - -#ifndef CLIENT_DLL - ConVar sk_plr_dmg_grenade( "sk_plr_dmg_grenade","0"); -#endif - -#ifdef CLIENT_DLL - - -#else - - // --------------------------------------------------------------------------------------------------- // - // Voice helper - // --------------------------------------------------------------------------------------------------- // - - class CVoiceGameMgrHelper : public IVoiceGameMgrHelper - { - public: - virtual bool CanPlayerHearPlayer( CBasePlayer *pListener, CBasePlayer *pTalker, bool &bProximity ) - { - // Dead players can only be heard by other dead team mates - if ( pTalker->IsAlive() == false ) - { - if ( pListener->IsAlive() == false ) - return ( pListener->InSameTeam( pTalker ) ); - - return false; - } - - return ( pListener->InSameTeam( pTalker ) ); - } - }; - CVoiceGameMgrHelper g_VoiceGameMgrHelper; - IVoiceGameMgrHelper *g_pVoiceGameMgrHelper = &g_VoiceGameMgrHelper; - - - - // --------------------------------------------------------------------------------------------------- // - // Globals. - // --------------------------------------------------------------------------------------------------- // - - // NOTE: the indices here must match TEAM_TERRORIST, TEAM_CT, TEAM_SPECTATOR, etc. - const char *sTeamNames[] = - { - "Unassigned", - "Spectator", - "Terrorist", - "Counter-Terrorist" - }; - - - // --------------------------------------------------------------------------------------------------- // - // Global helper functions. - // --------------------------------------------------------------------------------------------------- // - - // World.cpp calls this but we don't use it in SDK. - void InitBodyQue() - { - } - - - // --------------------------------------------------------------------------------------------------- // - // CSDKGameRules implementation. - // --------------------------------------------------------------------------------------------------- // - - CSDKGameRules::CSDKGameRules() - { - // Create the team managers - for ( int i = 0; i < (int)ARRAYSIZE( sTeamNames ); i++ ) - { - CTeam *pTeam = static_cast(CreateEntityByName( "sdk_team_manager" )); - pTeam->Init( sTeamNames[i], i ); - - g_Teams.AddToTail( pTeam ); - } - } - - //----------------------------------------------------------------------------- - // Purpose: - //----------------------------------------------------------------------------- - CSDKGameRules::~CSDKGameRules() - { - // Note, don't delete each team since they are in the gEntList and will - // automatically be deleted from there, instead. - g_Teams.Purge(); - } - - //----------------------------------------------------------------------------- - // Purpose: TF2 Specific Client Commands - // Input : - // Output : - //----------------------------------------------------------------------------- - bool CSDKGameRules::ClientCommand( CBaseEntity *pEdict, const CCommand &args ) - { - return BaseClass::ClientCommand( pEdict, args ); - } - - //----------------------------------------------------------------------------- - // Purpose: Player has just spawned. Equip them. - //----------------------------------------------------------------------------- - - void CSDKGameRules::RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore ) - { - RadiusDamage( info, vecSrcIn, flRadius, iClassIgnore, false ); - } - - // Add the ability to ignore the world trace - void CSDKGameRules::RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore, bool bIgnoreWorld ) - { - CBaseEntity *pEntity = NULL; - trace_t tr; - float flAdjustedDamage, falloff; - Vector vecSpot; - Vector vecToTarget; - Vector vecEndPos; - - Vector vecSrc = vecSrcIn; - - if ( flRadius ) - falloff = info.GetDamage() / flRadius; - else - falloff = 1.0; - - int bInWater = (UTIL_PointContents ( vecSrc ) & MASK_WATER) ? true : false; - - vecSrc.z += 1;// in case grenade is lying on the ground - - // iterate on all entities in the vicinity. - for ( CEntitySphereQuery sphere( vecSrc, flRadius ); ( pEntity = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() ) - { - if ( pEntity->m_takedamage != DAMAGE_NO ) - { - // UNDONE: this should check a damage mask, not an ignore - if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore ) - {// houndeyes don't hurt other houndeyes with their attack - continue; - } - - // blast's don't tavel into or out of water - if (bInWater && pEntity->GetWaterLevel() == 0) - continue; - if (!bInWater && pEntity->GetWaterLevel() == 3) - continue; - - // radius damage can only be blocked by the world - vecSpot = pEntity->BodyTarget( vecSrc ); - - - - bool bHit = false; - - if( bIgnoreWorld ) - { - vecEndPos = vecSpot; - bHit = true; - } - else - { - UTIL_TraceLine( vecSrc, vecSpot, MASK_SOLID_BRUSHONLY, info.GetInflictor(), COLLISION_GROUP_NONE, &tr ); - - if (tr.startsolid) - { - // if we're stuck inside them, fixup the position and distance - tr.endpos = vecSrc; - tr.fraction = 0.0; - } - - vecEndPos = tr.endpos; - - if( tr.fraction == 1.0 || tr.m_pEnt == pEntity ) - { - bHit = true; - } - } - - if ( bHit ) - { - // the explosion can 'see' this entity, so hurt them! - //vecToTarget = ( vecSrc - vecEndPos ); - vecToTarget = ( vecEndPos - vecSrc ); - - // decrease damage for an ent that's farther from the bomb. - flAdjustedDamage = vecToTarget.Length() * falloff; - flAdjustedDamage = info.GetDamage() - flAdjustedDamage; - - if ( flAdjustedDamage > 0 ) - { - CTakeDamageInfo adjustedInfo = info; - adjustedInfo.SetDamage( flAdjustedDamage ); - - Vector dir = vecToTarget; - VectorNormalize( dir ); - - // If we don't have a damage force, manufacture one - if ( adjustedInfo.GetDamagePosition() == vec3_origin || adjustedInfo.GetDamageForce() == vec3_origin ) - { - CalculateExplosiveDamageForce( &adjustedInfo, dir, vecSrc, 1.5 /* explosion scale! */ ); - } - else - { - // Assume the force passed in is the maximum force. Decay it based on falloff. - float flForce = adjustedInfo.GetDamageForce().Length() * falloff; - adjustedInfo.SetDamageForce( dir * flForce ); - adjustedInfo.SetDamagePosition( vecSrc ); - } - - pEntity->TakeDamage( adjustedInfo ); - - // Now hit all triggers along the way that respond to damage... - pEntity->TraceAttackToTriggers( adjustedInfo, vecSrc, vecEndPos, dir ); - } - } - } - } - } - - void CSDKGameRules::Think() - { - BaseClass::Think(); - } - -#endif - - -bool CSDKGameRules::ShouldCollide( int collisionGroup0, int collisionGroup1 ) -{ - if ( collisionGroup0 > collisionGroup1 ) - { - // swap so that lowest is always first - swap(collisionGroup0,collisionGroup1); - } - - //Don't stand on COLLISION_GROUP_WEAPON - if( collisionGroup0 == COLLISION_GROUP_PLAYER_MOVEMENT && - collisionGroup1 == COLLISION_GROUP_WEAPON ) - { - return false; - } - - return BaseClass::ShouldCollide( collisionGroup0, collisionGroup1 ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Init CS ammo definitions -//----------------------------------------------------------------------------- - -// shared ammo definition -// JAY: Trying to make a more physical bullet response -#define BULLET_MASS_GRAINS_TO_LB(grains) (0.002285*(grains)/16.0f) -#define BULLET_MASS_GRAINS_TO_KG(grains) lbs2kg(BULLET_MASS_GRAINS_TO_LB(grains)) - -// exaggerate all of the forces, but use real numbers to keep them consistent -#define BULLET_IMPULSE_EXAGGERATION 1 - -// convert a velocity in ft/sec and a mass in grains to an impulse in kg in/s -#define BULLET_IMPULSE(grains, ftpersec) ((ftpersec)*12*BULLET_MASS_GRAINS_TO_KG(grains)*BULLET_IMPULSE_EXAGGERATION) - - -CAmmoDef* GetAmmoDef() -{ - static CAmmoDef def; - static bool bInitted = false; - - if ( !bInitted ) - { - bInitted = true; - - // def.AddAmmoType( BULLET_PLAYER_50AE, DMG_BULLET, TRACER_LINE, 0, 0, "ammo_50AE_max", 2400, 0, 10, 14 ); - def.AddAmmoType( AMMO_GRENADE, DMG_BLAST, TRACER_LINE, 0, 0, 1/*max carry*/, 1, 0 ); - def.AddAmmoType( AMMO_BULLETS, DMG_BULLET, TRACER_LINE, 0, 0, 1/*max carry*/, 1, 0 ); - def.AddAmmoType( AMMO_GAUSS, DMG_SHOCK, TRACER_NONE, "sdk_jeep_weapon_damage", "sdk_jeep_weapon_damage", "sdk_jeep_max_rounds", BULLET_IMPULSE(650, 8000), 0 ); - } - - return &def; -} - - -#ifndef CLIENT_DLL - -const char *CSDKGameRules::GetChatPrefix( bool bTeamOnly, CBasePlayer *pPlayer ) -{ - return "(chat prefix)"; -} - -#endif - -//----------------------------------------------------------------------------- -// Purpose: Find the relationship between players (teamplay vs. deathmatch) -//----------------------------------------------------------------------------- -int CSDKGameRules::PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget ) -{ -#ifndef CLIENT_DLL - // half life multiplay has a simple concept of Player Relationships. - // you are either on another player's team, or you are not. - if ( !pPlayer || !pTarget || !pTarget->IsPlayer() || IsTeamplay() == false ) - return GR_NOTTEAMMATE; - - if ( (*GetTeamID(pPlayer) != '\0') && (*GetTeamID(pTarget) != '\0') && !stricmp( GetTeamID(pPlayer), GetTeamID(pTarget) ) ) - return GR_TEAMMATE; - -#endif - - return GR_NOTTEAMMATE; -} diff --git a/game/shared/sdk/sdk_gamerules.h b/game/shared/sdk/sdk_gamerules.h deleted file mode 100644 index 08ab30e62..000000000 --- a/game/shared/sdk/sdk_gamerules.h +++ /dev/null @@ -1,88 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: The TF Game rules object -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef SDK_GAMERULES_H -#define SDK_GAMERULES_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "teamplay_gamerules.h" -#include "convar.h" -#include "gamevars_shared.h" - -#ifdef CLIENT_DLL - #include "c_baseplayer.h" -#else - #include "player.h" -#endif - - -#ifdef CLIENT_DLL - #define CSDKGameRules C_SDKGameRules - #define CSDKGameRulesProxy C_SDKGameRulesProxy -#endif - - -class CSDKGameRulesProxy : public CGameRulesProxy -{ -public: - DECLARE_CLASS( CSDKGameRulesProxy, CGameRulesProxy ); - DECLARE_NETWORKCLASS(); -}; - - -class CSDKGameRules : public CTeamplayRules -{ -public: - DECLARE_CLASS( CSDKGameRules, CTeamplayRules ); - - virtual bool ShouldCollide( int collisionGroup0, int collisionGroup1 ); - - virtual int PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget ); - virtual bool IsTeamplay( void ) { return false; } - -#ifdef CLIENT_DLL - - DECLARE_CLIENTCLASS_NOBASE(); // This makes datatables able to access our private vars. - -#else - - DECLARE_SERVERCLASS_NOBASE(); // This makes datatables able to access our private vars. - - CSDKGameRules(); - virtual ~CSDKGameRules(); - - virtual bool ClientCommand( CBaseEntity *pEdict, const CCommand &args ); - virtual void RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore ); - virtual void Think(); - - virtual const char *GetChatPrefix( bool bTeamOnly, CBasePlayer *pPlayer ); - -private: - - void RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore, bool bIgnoreWorld ); - - -#endif -}; - -//----------------------------------------------------------------------------- -// Gets us at the team fortress game rules -//----------------------------------------------------------------------------- - -inline CSDKGameRules* SDKGameRules() -{ - return static_cast(g_pGameRules); -} - - -#endif // SDK_GAMERULES_H diff --git a/game/shared/sdk/sdk_player_shared.cpp b/game/shared/sdk/sdk_player_shared.cpp deleted file mode 100644 index 4efff5a1c..000000000 --- a/game/shared/sdk/sdk_player_shared.cpp +++ /dev/null @@ -1,160 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" - -#ifdef CLIENT_DLL - - #include "c_sdk_player.h" - -#else - - #include "sdk_player.h" - -#endif - -#include "gamevars_shared.h" -#include "takedamageinfo.h" -#include "effect_dispatch_data.h" -#include "engine/ivdebugoverlay.h" - -ConVar sv_showimpacts("sv_showimpacts", "0", FCVAR_REPLICATED, "Shows client (red) and server (blue) bullet impact point" ); - -void DispatchEffect( const char *pName, const CEffectData &data ); - -CWeaponSDKBase* CSDKPlayer::SDKAnim_GetActiveWeapon() -{ - return GetActiveSDKWeapon(); -} - -bool CSDKPlayer::SDKAnim_CanMove() -{ - return true; -} - -void CSDKPlayer::FireBullet( - Vector vecSrc, // shooting postion - const QAngle &shootAngles, //shooting angle - float vecSpread, // spread vector - int iDamage, // base damage - int iBulletType, // ammo type - CBaseEntity *pevAttacker, // shooter - bool bDoEffects, // create impact effect ? - float x, // spread x factor - float y // spread y factor - ) -{ - float fCurrentDamage = iDamage; // damage of the bullet at it's current trajectory - float flCurrentDistance = 0.0; //distance that the bullet has traveled so far - - Vector vecDirShooting, vecRight, vecUp; - AngleVectors( shootAngles, &vecDirShooting, &vecRight, &vecUp ); - - if ( !pevAttacker ) - pevAttacker = this; // the default attacker is ourselves - - // add the spray - Vector vecDir = vecDirShooting + - x * vecSpread * vecRight + - y * vecSpread * vecUp; - - VectorNormalize( vecDir ); - - float flMaxRange = 8000; - - Vector vecEnd = vecSrc + vecDir * flMaxRange; // max bullet range is 10000 units - - trace_t tr; // main enter bullet trace - - UTIL_TraceLine( vecSrc, vecEnd, MASK_SOLID|CONTENTS_DEBRIS|CONTENTS_HITBOX, this, COLLISION_GROUP_NONE, &tr ); - - if ( tr.fraction == 1.0f ) - return; // we didn't hit anything, stop tracing shoot - - if ( sv_showimpacts.GetBool() ) - { -#ifdef CLIENT_DLL - // draw red client impact markers - debugoverlay->AddBoxOverlay( tr.endpos, Vector(-2,-2,-2), Vector(2,2,2), QAngle( 0, 0, 0), 255,0,0,127, 4 ); - - if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() ) - { - C_BasePlayer *player = ToBasePlayer( tr.m_pEnt ); - player->DrawClientHitboxes( 4, true ); - } -#else - // draw blue server impact markers - NDebugOverlay::Box( tr.endpos, Vector(-2,-2,-2), Vector(2,2,2), 0,0,255,127, 4 ); - - if ( tr.m_pEnt && tr.m_pEnt->IsPlayer() ) - { - CBasePlayer *player = ToBasePlayer( tr.m_pEnt ); - player->DrawServerHitboxes( 4, true ); - } -#endif - } - - //calculate the damage based on the distance the bullet travelled. - flCurrentDistance += tr.fraction * flMaxRange; - - // damage get weaker of distance - fCurrentDamage *= pow ( 0.85f, (flCurrentDistance / 500)); - - int iDamageType = DMG_BULLET | DMG_NEVERGIB; - - if( bDoEffects ) - { - // See if the bullet ended up underwater + started out of the water - if ( enginetrace->GetPointContents( tr.endpos ) & (CONTENTS_WATER|CONTENTS_SLIME) ) - { - trace_t waterTrace; - UTIL_TraceLine( vecSrc, tr.endpos, (MASK_SHOT|CONTENTS_WATER|CONTENTS_SLIME), this, COLLISION_GROUP_NONE, &waterTrace ); - - if( waterTrace.allsolid != 1 ) - { - CEffectData data; - data.m_vOrigin = waterTrace.endpos; - data.m_vNormal = waterTrace.plane.normal; - data.m_flScale = random->RandomFloat( 8, 12 ); - - if ( waterTrace.contents & CONTENTS_SLIME ) - { - data.m_fFlags |= FX_WATER_IN_SLIME; - } - - DispatchEffect( "gunshotsplash", data ); - } - } - else - { - //Do Regular hit effects - - // Don't decal nodraw surfaces - if ( !( tr.surface.flags & (SURF_SKY|SURF_NODRAW|SURF_HINT|SURF_SKIP) ) ) - { - CBaseEntity *pEntity = tr.m_pEnt; - if ( !( !friendlyfire.GetBool() && pEntity && pEntity->IsPlayer() && pEntity->GetTeamNumber() == GetTeamNumber() ) ) - { - UTIL_ImpactTrace( &tr, iDamageType ); - } - } - } - } // bDoEffects - - // add damage to entity that we hit - -#ifdef GAME_DLL - ClearMultiDamage(); - - CTakeDamageInfo info( pevAttacker, pevAttacker, fCurrentDamage, iDamageType ); - CalculateBulletDamageForce( &info, iBulletType, vecDir, tr.endpos ); - tr.m_pEnt->DispatchTraceAttack( info, vecDir, &tr ); - - TraceAttackToTriggers( info, tr.startpos, tr.endpos, vecDir ); - - ApplyMultiDamage(); -#endif -} diff --git a/game/shared/sdk/sdk_playeranimstate.cpp b/game/shared/sdk/sdk_playeranimstate.cpp deleted file mode 100644 index 1d303356b..000000000 --- a/game/shared/sdk/sdk_playeranimstate.cpp +++ /dev/null @@ -1,621 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "base_playeranimstate.h" -#include "tier0/vprof.h" -#include "animation.h" -#include "studio.h" -#include "apparent_velocity_helper.h" -#include "utldict.h" - -#include "sdk_playeranimstate.h" -#include "weapon_sdkbase.h" -#include "weapon_basesdkgrenade.h" - -#ifdef CLIENT_DLL - #include "c_sdk_player.h" - #include "bone_setup.h" - #include "interpolatedvar.h" -#else - #include "sdk_player.h" -#endif - -#define ANIM_TOPSPEED_WALK 100 -#define ANIM_TOPSPEED_RUN 250 -#define ANIM_TOPSPEED_RUN_CROUCH 85 - -#define DEFAULT_IDLE_NAME "idle_upper_" -#define DEFAULT_CROUCH_IDLE_NAME "crouch_idle_upper_" -#define DEFAULT_CROUCH_WALK_NAME "crouch_walk_upper_" -#define DEFAULT_WALK_NAME "walk_upper_" -#define DEFAULT_RUN_NAME "run_upper_" - -#define DEFAULT_FIRE_IDLE_NAME "idle_shoot_" -#define DEFAULT_FIRE_CROUCH_NAME "crouch_idle_shoot_" -#define DEFAULT_FIRE_CROUCH_WALK_NAME "crouch_walk_shoot_" -#define DEFAULT_FIRE_WALK_NAME "walk_shoot_" -#define DEFAULT_FIRE_RUN_NAME "run_shoot_" - - -#define FIRESEQUENCE_LAYER (AIMSEQUENCE_LAYER+NUM_AIMSEQUENCE_LAYERS) -#define RELOADSEQUENCE_LAYER (FIRESEQUENCE_LAYER + 1) -#define GRENADESEQUENCE_LAYER (RELOADSEQUENCE_LAYER + 1) -#define NUM_LAYERS_WANTED (GRENADESEQUENCE_LAYER + 1) - - - -// ------------------------------------------------------------------------------------------------ // -// CSDKPlayerAnimState declaration. -// ------------------------------------------------------------------------------------------------ // - -class CSDKPlayerAnimState : public CBasePlayerAnimState, public ISDKPlayerAnimState -{ -public: - DECLARE_CLASS( CSDKPlayerAnimState, CBasePlayerAnimState ); - friend ISDKPlayerAnimState* CreatePlayerAnimState( CBaseAnimatingOverlay *pEntity, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences ); - - CSDKPlayerAnimState(); - - virtual void DoAnimationEvent( PlayerAnimEvent_t event, int nData ); - virtual bool IsThrowingGrenade(); - virtual int CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle ); - virtual void ClearAnimationState(); - virtual bool CanThePlayerMove(); - virtual float GetCurrentMaxGroundSpeed(); - virtual Activity CalcMainActivity(); - virtual void DebugShowAnimState( int iStartLine ); - virtual void ComputeSequences( CStudioHdr *pStudioHdr ); - virtual void ClearAnimationLayers(); - - - void InitSDK( CBaseAnimatingOverlay *pPlayer, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences ); - -protected: - - int CalcFireLayerSequence(PlayerAnimEvent_t event); - void ComputeFireSequence(CStudioHdr *pStudioHdr); - - void ComputeReloadSequence(CStudioHdr *pStudioHdr); - int CalcReloadLayerSequence(); - - bool IsOuterGrenadePrimed(); - void ComputeGrenadeSequence( CStudioHdr *pStudioHdr ); - int CalcGrenadePrimeSequence(); - int CalcGrenadeThrowSequence(); - int GetOuterGrenadeThrowCounter(); - - const char* GetWeaponSuffix(); - bool HandleJumping(); - - void UpdateLayerSequenceGeneric( CStudioHdr *pStudioHdr, int iLayer, bool &bEnabled, float &flCurCycle, int &iSequence, bool bWaitAtEnd ); - -private: - - // Current state variables. - bool m_bJumping; // Set on a jump event. - float m_flJumpStartTime; - bool m_bFirstJumpFrame; - - // Aim sequence plays reload while this is on. - bool m_bReloading; - float m_flReloadCycle; - int m_iReloadSequence; - - // This is set to true if ANY animation is being played in the fire layer. - bool m_bFiring; // If this is on, then it'll continue the fire animation in the fire layer - // until it completes. - int m_iFireSequence; // (For any sequences in the fire layer, including grenade throw). - float m_flFireCycle; - - // These control grenade animations. - bool m_bThrowingGrenade; - bool m_bPrimingGrenade; - float m_flGrenadeCycle; - int m_iGrenadeSequence; - int m_iLastThrowGrenadeCounter; // used to detect when the guy threw the grenade. - - ISDKPlayerAnimStateHelpers *m_pHelpers; -}; - - -ISDKPlayerAnimState* CreatePlayerAnimState( CBaseAnimatingOverlay *pEntity, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences ) -{ - CSDKPlayerAnimState *pRet = new CSDKPlayerAnimState; - pRet->InitSDK( pEntity, pHelpers, legAnimType, bUseAimSequences ); - return pRet; -} - -// ------------------------------------------------------------------------------------------------ // -// CSDKPlayerAnimState implementation. -// ------------------------------------------------------------------------------------------------ // - -CSDKPlayerAnimState::CSDKPlayerAnimState() -{ - m_pOuter = NULL; - m_bReloading = false; -} - - -void CSDKPlayerAnimState::InitSDK( CBaseAnimatingOverlay *pEntity, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences ) -{ - CModAnimConfig config; - config.m_flMaxBodyYawDegrees = 90; - config.m_LegAnimType = legAnimType; - config.m_bUseAimSequences = bUseAimSequences; - - m_pHelpers = pHelpers; - - BaseClass::Init( pEntity, config ); -} - - -void CSDKPlayerAnimState::ClearAnimationState() -{ - m_bJumping = false; - m_bFiring = false; - m_bReloading = false; - m_bThrowingGrenade = m_bPrimingGrenade = false; - m_iLastThrowGrenadeCounter = GetOuterGrenadeThrowCounter(); - - BaseClass::ClearAnimationState(); -} - - -void CSDKPlayerAnimState::DoAnimationEvent( PlayerAnimEvent_t event, int nData ) -{ - Assert( event != PLAYERANIMEVENT_THROW_GRENADE ); - - if ( event == PLAYERANIMEVENT_FIRE_GUN_PRIMARY || - event == PLAYERANIMEVENT_FIRE_GUN_SECONDARY ) - { - // Regardless of what we're doing in the fire layer, restart it. - m_flFireCycle = 0; - m_iFireSequence = CalcFireLayerSequence( event ); - m_bFiring = m_iFireSequence != -1; - } - else if ( event == PLAYERANIMEVENT_JUMP ) - { - // Play the jump animation. - m_bJumping = true; - m_bFirstJumpFrame = true; - m_flJumpStartTime = gpGlobals->curtime; - } - else if ( event == PLAYERANIMEVENT_RELOAD ) - { - m_iReloadSequence = CalcReloadLayerSequence(); - if ( m_iReloadSequence != -1 ) - { - m_bReloading = true; - m_flReloadCycle = 0; - } - } - else - { - Assert( !"CSDKPlayerAnimState::DoAnimationEvent" ); - } -} - - -float g_flThrowGrenadeFraction = 0.25; -bool CSDKPlayerAnimState::IsThrowingGrenade() -{ - if ( m_bThrowingGrenade ) - { - // An animation event would be more appropriate here. - return m_flGrenadeCycle < g_flThrowGrenadeFraction; - } - else - { - bool bThrowPending = (m_iLastThrowGrenadeCounter != GetOuterGrenadeThrowCounter()); - return bThrowPending || IsOuterGrenadePrimed(); - } -} - - -int CSDKPlayerAnimState::CalcReloadLayerSequence() -{ - const char *pSuffix = GetWeaponSuffix(); - if ( !pSuffix ) - return -1; - - CWeaponSDKBase *pWeapon = m_pHelpers->SDKAnim_GetActiveWeapon(); - if ( !pWeapon ) - return -1; - - // First, look for reload_. - char szName[512]; - Q_snprintf( szName, sizeof( szName ), "reload_%s", pSuffix ); - int iReloadSequence = m_pOuter->LookupSequence( szName ); - if ( iReloadSequence != -1 ) - return iReloadSequence; - - //SDKTODO -/* - // Ok, look for generic categories.. pistol, shotgun, rifle, etc. - if ( pWeapon->GetSDKWpnData().m_WeaponType == WEAPONTYPE_PISTOL ) - { - Q_snprintf( szName, sizeof( szName ), "reload_pistol" ); - iReloadSequence = m_pOuter->LookupSequence( szName ); - if ( iReloadSequence != -1 ) - return iReloadSequence; - } - */ - - // Fall back to reload_m4. - iReloadSequence = CalcSequenceIndex( "reload_m4" ); - if ( iReloadSequence > 0 ) - return iReloadSequence; - - return -1; -} - - -#ifdef CLIENT_DLL - void CSDKPlayerAnimState::UpdateLayerSequenceGeneric( CStudioHdr *pStudioHdr, int iLayer, bool &bEnabled, float &flCurCycle, int &iSequence, bool bWaitAtEnd ) - { - if ( !bEnabled ) - return; - - // Increment the fire sequence's cycle. - flCurCycle += m_pOuter->GetSequenceCycleRate( pStudioHdr, iSequence ) * gpGlobals->frametime; - if ( flCurCycle > 1 ) - { - if ( bWaitAtEnd ) - { - flCurCycle = 1; - } - else - { - // Not firing anymore. - bEnabled = false; - iSequence = 0; - return; - } - } - - // Now dump the state into its animation layer. - C_AnimationLayer *pLayer = m_pOuter->GetAnimOverlay( iLayer ); - - pLayer->m_flCycle = flCurCycle; - pLayer->m_nSequence = iSequence; - - pLayer->m_flPlaybackRate = 1.0; - pLayer->m_flWeight = 1.0f; - pLayer->m_nOrder = iLayer; - } -#endif - - - -bool CSDKPlayerAnimState::IsOuterGrenadePrimed() -{ - CBaseCombatCharacter *pChar = m_pOuter->MyCombatCharacterPointer(); - if ( pChar ) - { - CBaseSDKGrenade *pGren = dynamic_cast( pChar->GetActiveWeapon() ); - return pGren && pGren->IsPinPulled(); - } - else - { - return false; - } -} - - -void CSDKPlayerAnimState::ComputeGrenadeSequence( CStudioHdr *pStudioHdr ) -{ -#ifdef CLIENT_DLL - if ( m_bThrowingGrenade ) - { - UpdateLayerSequenceGeneric( pStudioHdr, GRENADESEQUENCE_LAYER, m_bThrowingGrenade, m_flGrenadeCycle, m_iGrenadeSequence, false ); - } - else - { - // Priming the grenade isn't an event.. we just watch the player for it. - // Also play the prime animation first if he wants to throw the grenade. - bool bThrowPending = (m_iLastThrowGrenadeCounter != GetOuterGrenadeThrowCounter()); - if ( IsOuterGrenadePrimed() || bThrowPending ) - { - if ( !m_bPrimingGrenade ) - { - // If this guy just popped into our PVS, and he's got his grenade primed, then - // let's assume that it's all the way primed rather than playing the prime - // animation from the start. - if ( TimeSinceLastAnimationStateClear() < 0.4f ) - m_flGrenadeCycle = 1; - else - m_flGrenadeCycle = 0; - - m_iGrenadeSequence = CalcGrenadePrimeSequence(); - } - - m_bPrimingGrenade = true; - UpdateLayerSequenceGeneric( pStudioHdr, GRENADESEQUENCE_LAYER, m_bPrimingGrenade, m_flGrenadeCycle, m_iGrenadeSequence, true ); - - // If we're waiting to throw and we're done playing the prime animation... - if ( bThrowPending && m_flGrenadeCycle == 1 ) - { - m_iLastThrowGrenadeCounter = GetOuterGrenadeThrowCounter(); - - // Now play the throw animation. - m_iGrenadeSequence = CalcGrenadeThrowSequence(); - if ( m_iGrenadeSequence != -1 ) - { - // Configure to start playing - m_bThrowingGrenade = true; - m_bPrimingGrenade = false; - m_flGrenadeCycle = 0; - } - } - } - else - { - m_bPrimingGrenade = false; - } - } -#endif -} - - -int CSDKPlayerAnimState::CalcGrenadePrimeSequence() -{ - return CalcSequenceIndex( "idle_shoot_gren1" ); -} - - -int CSDKPlayerAnimState::CalcGrenadeThrowSequence() -{ - return CalcSequenceIndex( "idle_shoot_gren2" ); -} - - -int CSDKPlayerAnimState::GetOuterGrenadeThrowCounter() -{ - CSDKPlayer *pPlayer = dynamic_cast( m_pOuter ); - if ( pPlayer ) - return pPlayer->m_iThrowGrenadeCounter; - else - return 0; -} - - -void CSDKPlayerAnimState::ComputeReloadSequence( CStudioHdr *pStudioHdr ) -{ -#ifdef CLIENT_DLL - UpdateLayerSequenceGeneric( pStudioHdr, RELOADSEQUENCE_LAYER, m_bReloading, m_flReloadCycle, m_iReloadSequence, false ); -#else - // Server doesn't bother with different fire sequences. -#endif -} - - -int CSDKPlayerAnimState::CalcAimLayerSequence( float *flCycle, float *flAimSequenceWeight, bool bForceIdle ) -{ - const char *pSuffix = GetWeaponSuffix(); - if ( !pSuffix ) - return 0; - - if ( bForceIdle ) - { - switch ( GetCurrentMainSequenceActivity() ) - { - case ACT_CROUCHIDLE: - return CalcSequenceIndex( "%s%s", DEFAULT_CROUCH_IDLE_NAME, pSuffix ); - - default: - return CalcSequenceIndex( "%s%s", DEFAULT_IDLE_NAME, pSuffix ); - } - } - else - { - switch ( GetCurrentMainSequenceActivity() ) - { - case ACT_RUN: - return CalcSequenceIndex( "%s%s", DEFAULT_RUN_NAME, pSuffix ); - - case ACT_WALK: - case ACT_RUNTOIDLE: - case ACT_IDLETORUN: - return CalcSequenceIndex( "%s%s", DEFAULT_WALK_NAME, pSuffix ); - - case ACT_CROUCHIDLE: - return CalcSequenceIndex( "%s%s", DEFAULT_CROUCH_IDLE_NAME, pSuffix ); - - case ACT_RUN_CROUCH: - return CalcSequenceIndex( "%s%s", DEFAULT_CROUCH_WALK_NAME, pSuffix ); - - case ACT_IDLE: - default: - return CalcSequenceIndex( "%s%s", DEFAULT_IDLE_NAME, pSuffix ); - } - } -} - - -const char* CSDKPlayerAnimState::GetWeaponSuffix() -{ - // Figure out the weapon suffix. - CWeaponSDKBase *pWeapon = m_pHelpers->SDKAnim_GetActiveWeapon(); - if ( !pWeapon ) - return "Pistol"; - - const char *pSuffix = pWeapon->GetSDKWpnData().m_szAnimExtension; - - return pSuffix; -} - - -int CSDKPlayerAnimState::CalcFireLayerSequence(PlayerAnimEvent_t event) -{ - // Figure out the weapon suffix. - CWeaponSDKBase *pWeapon = m_pHelpers->SDKAnim_GetActiveWeapon(); - if ( !pWeapon ) - return 0; - - const char *pSuffix = GetWeaponSuffix(); - if ( !pSuffix ) - return 0; - - // Don't rely on their weapon here because the player has usually switched to their - // pistol or rifle by the time the PLAYERANIMEVENT_THROW_GRENADE message gets to the client. - if ( event == PLAYERANIMEVENT_THROW_GRENADE ) - { - pSuffix = "Gren"; - } - - switch ( GetCurrentMainSequenceActivity() ) - { - case ACT_PLAYER_RUN_FIRE: - case ACT_RUN: - return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_RUN_NAME, pSuffix ); - - case ACT_PLAYER_WALK_FIRE: - case ACT_WALK: - return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_WALK_NAME, pSuffix ); - - case ACT_PLAYER_CROUCH_FIRE: - case ACT_CROUCHIDLE: - return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_CROUCH_NAME, pSuffix ); - - case ACT_PLAYER_CROUCH_WALK_FIRE: - case ACT_RUN_CROUCH: - return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_CROUCH_WALK_NAME, pSuffix ); - - default: - case ACT_PLAYER_IDLE_FIRE: - return CalcSequenceIndex( "%s%s", DEFAULT_FIRE_IDLE_NAME, pSuffix ); - } -} - - -bool CSDKPlayerAnimState::CanThePlayerMove() -{ - return m_pHelpers->SDKAnim_CanMove(); -} - - -float CSDKPlayerAnimState::GetCurrentMaxGroundSpeed() -{ - Activity currentActivity = m_pOuter->GetSequenceActivity( m_pOuter->GetSequence() ); - if ( currentActivity == ACT_WALK || currentActivity == ACT_IDLE ) - return ANIM_TOPSPEED_WALK; - else if ( currentActivity == ACT_RUN ) - return ANIM_TOPSPEED_RUN; - else if ( currentActivity == ACT_RUN_CROUCH ) - return ANIM_TOPSPEED_RUN_CROUCH; - else - return 0; -} - - -bool CSDKPlayerAnimState::HandleJumping() -{ - if ( m_bJumping ) - { - if ( m_bFirstJumpFrame ) - { - m_bFirstJumpFrame = false; - RestartMainSequence(); // Reset the animation. - } - - // Don't check if he's on the ground for a sec.. sometimes the client still has the - // on-ground flag set right when the message comes in. - if ( gpGlobals->curtime - m_flJumpStartTime > 0.2f ) - { - if ( m_pOuter->GetFlags() & FL_ONGROUND ) - { - m_bJumping = false; - RestartMainSequence(); // Reset the animation. - } - } - } - - // Are we still jumping? If so, keep playing the jump animation. - return m_bJumping; -} - - -Activity CSDKPlayerAnimState::CalcMainActivity() -{ - float flOuterSpeed = GetOuterXYSpeed(); - - if ( HandleJumping() ) - { - return ACT_HOP; - } - else - { - Activity idealActivity = ACT_IDLE; - - if ( m_pOuter->GetFlags() & FL_DUCKING ) - { - if ( flOuterSpeed > MOVING_MINIMUM_SPEED ) - idealActivity = ACT_RUN_CROUCH; - else - idealActivity = ACT_CROUCHIDLE; - } - else - { - if ( flOuterSpeed > MOVING_MINIMUM_SPEED ) - { - if ( flOuterSpeed > ARBITRARY_RUN_SPEED ) - idealActivity = ACT_RUN; - else - idealActivity = ACT_WALK; - } - else - { - idealActivity = ACT_IDLE; - } - } - - return idealActivity; - } -} - - -void CSDKPlayerAnimState::DebugShowAnimState( int iStartLine ) -{ -#ifdef CLIENT_DLL - engine->Con_NPrintf( iStartLine++, "fire : %s, cycle: %.2f\n", m_bFiring ? GetSequenceName( m_pOuter->GetModelPtr(), m_iFireSequence ) : "[not firing]", m_flFireCycle ); - engine->Con_NPrintf( iStartLine++, "reload: %s, cycle: %.2f\n", m_bReloading ? GetSequenceName( m_pOuter->GetModelPtr(), m_iReloadSequence ) : "[not reloading]", m_flReloadCycle ); - BaseClass::DebugShowAnimState( iStartLine ); -#endif -} - - -void CSDKPlayerAnimState::ComputeSequences( CStudioHdr *pStudioHdr ) -{ - BaseClass::ComputeSequences( pStudioHdr ); - - ComputeFireSequence( pStudioHdr ); - ComputeReloadSequence( pStudioHdr ); - ComputeGrenadeSequence( pStudioHdr ); -} - - -void CSDKPlayerAnimState::ClearAnimationLayers() -{ - if ( !m_pOuter ) - return; - - m_pOuter->SetNumAnimOverlays( NUM_LAYERS_WANTED ); - for ( int i=0; i < m_pOuter->GetNumAnimOverlays(); i++ ) - { - m_pOuter->GetAnimOverlay( i )->SetOrder( CBaseAnimatingOverlay::MAX_OVERLAYS ); - } -} - - -void CSDKPlayerAnimState::ComputeFireSequence( CStudioHdr *pStudioHdr ) -{ -#ifdef CLIENT_DLL - UpdateLayerSequenceGeneric( pStudioHdr, FIRESEQUENCE_LAYER, m_bFiring, m_flFireCycle, m_iFireSequence, false ); -#else - // Server doesn't bother with different fire sequences. -#endif -} diff --git a/game/shared/sdk/sdk_playeranimstate.h b/game/shared/sdk/sdk_playeranimstate.h deleted file mode 100644 index d0f7d4eae..000000000 --- a/game/shared/sdk/sdk_playeranimstate.h +++ /dev/null @@ -1,76 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef SDK_PLAYERANIMSTATE_H -#define SDK_PLAYERANIMSTATE_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "convar.h" -#include "iplayeranimstate.h" -#include "base_playeranimstate.h" - - -#ifdef CLIENT_DLL - class C_BaseAnimatingOverlay; - class C_WeaponSDKBase; - #define CBaseAnimatingOverlay C_BaseAnimatingOverlay - #define CWeaponSDKBase C_WeaponSDKBase - #define CSDKPlayer C_SDKPlayer -#else - class CBaseAnimatingOverlay; - class CWeaponSDKBase; - class CSDKPlayer; -#endif - - -// When moving this fast, he plays run anim. -#define ARBITRARY_RUN_SPEED 175.0f - - -enum PlayerAnimEvent_t -{ - PLAYERANIMEVENT_FIRE_GUN_PRIMARY=0, - PLAYERANIMEVENT_FIRE_GUN_SECONDARY, - PLAYERANIMEVENT_THROW_GRENADE, - PLAYERANIMEVENT_JUMP, - PLAYERANIMEVENT_RELOAD, - - PLAYERANIMEVENT_COUNT -}; - - -class ISDKPlayerAnimState : virtual public IPlayerAnimState -{ -public: - // This is called by both the client and the server in the same way to trigger events for - // players firing, jumping, throwing grenades, etc. - virtual void DoAnimationEvent( PlayerAnimEvent_t event, int nData = 0 ) = 0; - - // Returns true if we're playing the grenade prime or throw animation. - virtual bool IsThrowingGrenade() = 0; -}; - - -// This abstracts the differences between SDK players and hostages. -class ISDKPlayerAnimStateHelpers -{ -public: - virtual CWeaponSDKBase* SDKAnim_GetActiveWeapon() = 0; - virtual bool SDKAnim_CanMove() = 0; -}; - - -ISDKPlayerAnimState* CreatePlayerAnimState( CBaseAnimatingOverlay *pEntity, ISDKPlayerAnimStateHelpers *pHelpers, LegAnimType_t legAnimType, bool bUseAimSequences ); - -// If this is set, then the game code needs to make sure to send player animation events -// to the local player if he's the one being watched. -extern ConVar cl_showanimstate; - - -#endif // SDK_PLAYERANIMSTATE_H diff --git a/game/shared/sdk/sdk_shareddefs.h b/game/shared/sdk/sdk_shareddefs.h deleted file mode 100644 index 1bb9f8bac..000000000 --- a/game/shared/sdk/sdk_shareddefs.h +++ /dev/null @@ -1,17 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef SDK_SHAREDDEFS_H -#define SDK_SHAREDDEFS_H -#ifdef _WIN32 -#pragma once -#endif - - -#define SDK_PLAYER_VIEW_OFFSET Vector( 0, 0, 53.5 ) - - -#endif // SDK_SHAREDDEFS_H diff --git a/game/shared/sdk/sdk_usermessages.cpp b/game/shared/sdk/sdk_usermessages.cpp deleted file mode 100644 index 7c5cac19e..000000000 --- a/game/shared/sdk/sdk_usermessages.cpp +++ /dev/null @@ -1,49 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "usermessages.h" -#include "shake.h" -#include "voice_gamemgr.h" - -void RegisterUserMessages() -{ - usermessages->Register( "Geiger", 1 ); // geiger info data - usermessages->Register( "Train", 1 ); // train control data - usermessages->Register( "HudText", -1 ); - usermessages->Register( "SayText", -1 ); - usermessages->Register( "TextMsg", -1 ); - usermessages->Register( "HudMsg", -1 ); - usermessages->Register( "ResetHUD", 1 ); // called every respawn - usermessages->Register( "GameTitle", 0 ); // show game title - usermessages->Register( "ItemPickup", -1 ); // for item history on screen - usermessages->Register( "ShowMenu", -1 ); // show hud menu - usermessages->Register( "Shake", 13 ); // shake view - usermessages->Register( "Fade", 10 ); // fade HUD in/out - usermessages->Register( "VGUIMenu", -1 ); // Show VGUI menu - usermessages->Register( "CloseCaption", -1 ); // Show a caption (by string id number)(duration in 10th of a second) - - usermessages->Register( "SendAudio", -1 ); // play radion command - - usermessages->Register( "VoiceMask", VOICE_MAX_PLAYERS_DW*4 * 2 + 1 ); - usermessages->Register( "RequestState", 0 ); - - usermessages->Register( "BarTime", -1 ); // For the C4 progress bar. - usermessages->Register( "Damage", -1 ); // for HUD damage indicators - usermessages->Register( "RadioText", -1 ); // for HUD damage indicators - usermessages->Register( "HintText", -1 ); // Displays hint text display - usermessages->Register( "KeyHintText", -1 ); // Displays hint text display - - usermessages->Register( "ReloadEffect", 2 ); // a player reloading.. - usermessages->Register( "PlayerAnimEvent", -1 ); // jumping, firing, reload, etc. - - usermessages->Register( "AmmoDenied", 2 ); - usermessages->Register( "UpdateRadar", -1 ); - - // Used to send a sample HUD message - usermessages->Register( "GameMessage", -1 ); -} - diff --git a/game/shared/sdk/sdk_weapon_parse.cpp b/game/shared/sdk/sdk_weapon_parse.cpp deleted file mode 100644 index 18ba37a89..000000000 --- a/game/shared/sdk/sdk_weapon_parse.cpp +++ /dev/null @@ -1,35 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include -#include "sdk_weapon_parse.h" - - -FileWeaponInfo_t* CreateWeaponInfo() -{ - return new CSDKWeaponInfo; -} - - -CSDKWeaponInfo::CSDKWeaponInfo() -{ -} - - -void CSDKWeaponInfo::Parse( KeyValues *pKeyValuesData, const char *szWeaponName ) -{ - BaseClass::Parse( pKeyValuesData, szWeaponName ); - - m_iDamage = pKeyValuesData->GetInt( "Damage", 42 ); // Douglas Adams 1952 - 2001 - m_iBullets = pKeyValuesData->GetInt( "Bullets", 1 ); - m_flCycleTime = pKeyValuesData->GetFloat( "CycleTime", 0.15 ); - - const char *pAnimEx = pKeyValuesData->GetString( "PlayerAnimationExtension", "mp5" ); - Q_strncpy( m_szAnimExtension, pAnimEx, sizeof( m_szAnimExtension ) ); -} - - diff --git a/game/shared/sdk/sdk_weapon_parse.h b/game/shared/sdk/sdk_weapon_parse.h deleted file mode 100644 index cf15ccb01..000000000 --- a/game/shared/sdk/sdk_weapon_parse.h +++ /dev/null @@ -1,37 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef SDK_WEAPON_PARSE_H -#define SDK_WEAPON_PARSE_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "weapon_parse.h" -#include "networkvar.h" - - -//-------------------------------------------------------------------------------------------------------- -class CSDKWeaponInfo : public FileWeaponInfo_t -{ -public: - DECLARE_CLASS_GAMEROOT( CSDKWeaponInfo, FileWeaponInfo_t ); - - CSDKWeaponInfo(); - - virtual void Parse( ::KeyValues *pKeyValuesData, const char *szWeaponName ); - - char m_szAnimExtension[16]; // string used to generate player animations with this weapon - - // Parameters for FX_FireBullets: - int m_iDamage; - int m_iBullets; - float m_flCycleTime; -}; - - -#endif // SDK_WEAPON_PARSE_H diff --git a/game/shared/sdk/weapon_basesdkgrenade.cpp b/game/shared/sdk/weapon_basesdkgrenade.cpp deleted file mode 100644 index 9c7bbc11d..000000000 --- a/game/shared/sdk/weapon_basesdkgrenade.cpp +++ /dev/null @@ -1,363 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "weapon_sdkbase.h" -#include "gamerules.h" -#include "npcevent.h" -#include "engine/IEngineSound.h" -#include "weapon_basesdkgrenade.h" -#include "in_buttons.h" - - -#ifdef CLIENT_DLL - - #include "c_sdk_player.h" - -#else - - #include "sdk_player.h" - #include "items.h" - -#endif - - -#define GRENADE_TIMER 1.5f //Seconds - - -IMPLEMENT_NETWORKCLASS_ALIASED( BaseSDKGrenade, DT_BaseSDKGrenade ) - -BEGIN_NETWORK_TABLE(CBaseSDKGrenade, DT_BaseSDKGrenade) - -#ifndef CLIENT_DLL - SendPropBool( SENDINFO(m_bRedraw) ), - SendPropBool( SENDINFO(m_bPinPulled) ), - SendPropFloat( SENDINFO(m_fThrowTime), 0, SPROP_NOSCALE ), -#else - RecvPropBool( RECVINFO(m_bRedraw) ), - RecvPropBool( RECVINFO(m_bPinPulled) ), - RecvPropFloat( RECVINFO(m_fThrowTime) ), -#endif - -END_NETWORK_TABLE() - -#ifdef CLIENT_DLL -BEGIN_PREDICTION_DATA( CBaseSDKGrenade ) - DEFINE_PRED_FIELD( m_bRedraw, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), - DEFINE_PRED_FIELD( m_bRedraw, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), -END_PREDICTION_DATA() -#endif - -LINK_ENTITY_TO_CLASS( weapon_basesdkgrenade, CBaseSDKGrenade ); - - -CBaseSDKGrenade::CBaseSDKGrenade() -{ - m_bRedraw = false; - m_bPinPulled = false; - m_fThrowTime = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseSDKGrenade::Precache() -{ - BaseClass::Precache(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CBaseSDKGrenade::Deploy() -{ - m_bRedraw = false; - m_bPinPulled = false; - m_fThrowTime = 0; - - return BaseClass::Deploy(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseSDKGrenade::Holster( CBaseCombatWeapon *pSwitchingTo ) -{ - m_bRedraw = false; - m_bPinPulled = false; // when this is holstered make sure the pin isnt pulled. - m_fThrowTime = 0; - -#ifndef CLIENT_DLL - // If they attempt to switch weapons before the throw animation is done, - // allow it, but kill the weapon if we have to. - CSDKPlayer *pPlayer = GetPlayerOwner(); - - if( pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0 ) - { - CBaseCombatCharacter *pOwner = (CBaseCombatCharacter *)pPlayer; - pOwner->Weapon_Drop( this ); - UTIL_Remove(this); - } -#endif - - return BaseClass::Holster( pSwitchingTo ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseSDKGrenade::PrimaryAttack() -{ - if ( m_bRedraw || m_bPinPulled ) - return; - - CSDKPlayer *pPlayer = GetPlayerOwner(); - if ( !pPlayer || pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 ) - return; - - // The pull pin animation has to finish, then we wait until they aren't holding the primary - // attack button, then throw the grenade. - SendWeaponAnim( ACT_VM_PULLPIN ); - m_bPinPulled = true; - - // Don't let weapon idle interfere in the middle of a throw! - SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() ); - - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseSDKGrenade::SecondaryAttack() -{ - if ( m_bRedraw ) - return; - - CSDKPlayer *pPlayer = GetPlayerOwner(); - - if ( pPlayer == NULL ) - return; - - //See if we're ducking - if ( pPlayer->GetFlags() & FL_DUCKING ) - { - //Send the weapon animation - SendWeaponAnim( ACT_VM_SECONDARYATTACK ); - } - else - { - //Send the weapon animation - SendWeaponAnim( ACT_VM_HAULBACK ); - } - - // Don't let weapon idle interfere in the middle of a throw! - SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() ); - - m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CBaseSDKGrenade::Reload() -{ - if ( ( m_bRedraw ) && ( m_flNextPrimaryAttack <= gpGlobals->curtime ) && ( m_flNextSecondaryAttack <= gpGlobals->curtime ) ) - { - //Redraw the weapon - SendWeaponAnim( ACT_VM_DRAW ); - - //Update our times - m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration(); - m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration(); - - SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() ); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CBaseSDKGrenade::ItemPostFrame() -{ - CSDKPlayer *pPlayer = GetPlayerOwner(); - if ( !pPlayer ) - return; - - CBaseViewModel *vm = pPlayer->GetViewModel( m_nViewModelIndex ); - if ( !vm ) - return; - - // If they let go of the fire button, they want to throw the grenade. - if ( m_bPinPulled && !(pPlayer->m_nButtons & IN_ATTACK) ) - { - pPlayer->DoAnimationEvent( PLAYERANIMEVENT_THROW_GRENADE ); - - StartGrenadeThrow(); - - DecrementAmmo( pPlayer ); - - m_bPinPulled = false; - SendWeaponAnim( ACT_VM_THROW ); - SetWeaponIdleTime( gpGlobals->curtime + SequenceDuration() ); - } - else if ((m_fThrowTime > 0) && (m_fThrowTime < gpGlobals->curtime)) - { - ThrowGrenade(); - } - else if( m_bRedraw ) - { - // Has the throw animation finished playing - if( m_flTimeWeaponIdle < gpGlobals->curtime ) - { -#ifdef GAME_DLL - // if we're officially out of grenades, ditch this weapon - if( pPlayer->GetAmmoCount(m_iPrimaryAmmoType) <= 0 ) - { - pPlayer->Weapon_Drop( this, NULL, NULL ); - UTIL_Remove(this); - } - else - { - pPlayer->SwitchToNextBestWeapon( this ); - } -#endif - return; //don't animate this grenade any more! - } - } - else if( !m_bRedraw ) - { - BaseClass::ItemPostFrame(); - } -} - - - -#ifdef CLIENT_DLL - - void CBaseSDKGrenade::DecrementAmmo( CBaseCombatCharacter *pOwner ) - { - } - - void CBaseSDKGrenade::DropGrenade() - { - m_bRedraw = true; - m_fThrowTime = 0.0f; - } - - void CBaseSDKGrenade::ThrowGrenade() - { - m_bRedraw = true; - m_fThrowTime = 0.0f; - } - - void CBaseSDKGrenade::StartGrenadeThrow() - { - m_fThrowTime = gpGlobals->curtime + 0.1f; - } - -#else - - BEGIN_DATADESC( CBaseSDKGrenade ) - DEFINE_FIELD( m_bRedraw, FIELD_BOOLEAN ), - END_DATADESC() - - int CBaseSDKGrenade::CapabilitiesGet() - { - return bits_CAP_WEAPON_RANGE_ATTACK1; - } - - //----------------------------------------------------------------------------- - // Purpose: - // Input : *pOwner - - //----------------------------------------------------------------------------- - void CBaseSDKGrenade::DecrementAmmo( CBaseCombatCharacter *pOwner ) - { - pOwner->RemoveAmmo( 1, m_iPrimaryAmmoType ); - } - - void CBaseSDKGrenade::StartGrenadeThrow() - { - m_fThrowTime = gpGlobals->curtime + 0.1f; - } - - void CBaseSDKGrenade::ThrowGrenade() - { - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - if ( !pPlayer ) - { - Assert( false ); - return; - } - - QAngle angThrow = pPlayer->LocalEyeAngles(); - - Vector vForward, vRight, vUp; - - if (angThrow.x < 90 ) - angThrow.x = -10 + angThrow.x * ((90 + 10) / 90.0); - else - { - angThrow.x = 360.0f - angThrow.x; - angThrow.x = -10 + angThrow.x * -((90 - 10) / 90.0); - } - - float flVel = (90 - angThrow.x) * 6; - - if (flVel > 750) - flVel = 750; - - AngleVectors( angThrow, &vForward, &vRight, &vUp ); - - Vector vecSrc = pPlayer->GetAbsOrigin() + pPlayer->GetViewOffset(); - - vecSrc += vForward * 16; - - Vector vecThrow = vForward * flVel + pPlayer->GetAbsVelocity(); - - EmitGrenade( vecSrc, vec3_angle, vecThrow, AngularImpulse(600,random->RandomInt(-1200,1200),0), pPlayer ); - - m_bRedraw = true; - m_fThrowTime = 0.0f; - } - - void CBaseSDKGrenade::DropGrenade() - { - CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); - if ( !pPlayer ) - { - Assert( false ); - return; - } - - Vector vForward; - pPlayer->EyeVectors( &vForward ); - Vector vecSrc = pPlayer->GetAbsOrigin() + pPlayer->GetViewOffset() + vForward * 16; - - Vector vecVel = pPlayer->GetAbsVelocity(); - - EmitGrenade( vecSrc, vec3_angle, vecVel, AngularImpulse(600,random->RandomInt(-1200,1200),0), pPlayer ); - - m_bRedraw = true; - m_fThrowTime = 0.0f; - } - - void CBaseSDKGrenade::EmitGrenade( Vector vecSrc, QAngle vecAngles, Vector vecVel, AngularImpulse angImpulse, CBasePlayer *pPlayer ) - { - Assert( 0 && "CBaseSDKGrenade::EmitGrenade should not be called. Make sure to implement this in your subclass!\n" ); - } - - bool CBaseSDKGrenade::AllowsAutoSwitchFrom( void ) const - { - return !m_bPinPulled; - } - -#endif - diff --git a/game/shared/sdk/weapon_basesdkgrenade.h b/game/shared/sdk/weapon_basesdkgrenade.h deleted file mode 100644 index ef081dae0..000000000 --- a/game/shared/sdk/weapon_basesdkgrenade.h +++ /dev/null @@ -1,79 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef WEAPON_BASESDKGRENADE_H -#define WEAPON_BASESDKGRENADE_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "weapon_sdkbase.h" - - -#ifdef CLIENT_DLL - - #define CBaseSDKGrenade C_BaseSDKGrenade - -#endif - - -class CBaseSDKGrenade : public CWeaponSDKBase -{ -public: - DECLARE_CLASS( CBaseSDKGrenade, CWeaponSDKBase ); - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - - CBaseSDKGrenade(); - - virtual void Precache(); - - bool Deploy(); - bool Holster( CBaseCombatWeapon *pSwitchingTo ); - - void PrimaryAttack(); - void SecondaryAttack(); - - bool Reload(); - - virtual void ItemPostFrame(); - - void DecrementAmmo( CBaseCombatCharacter *pOwner ); - virtual void StartGrenadeThrow(); - virtual void ThrowGrenade(); - virtual void DropGrenade(); - - bool IsPinPulled() const; - -#ifndef CLIENT_DLL - DECLARE_DATADESC(); - - virtual bool AllowsAutoSwitchFrom( void ) const; - - int CapabilitiesGet(); - - // Each derived grenade class implements this. - virtual void EmitGrenade( Vector vecSrc, QAngle vecAngles, Vector vecVel, AngularImpulse angImpulse, CBasePlayer *pPlayer ); -#endif - -protected: - CNetworkVar( bool, m_bRedraw ); // Draw the weapon again after throwing a grenade - CNetworkVar( bool, m_bPinPulled ); // Set to true when the pin has been pulled but the grenade hasn't been thrown yet. - CNetworkVar( float, m_fThrowTime ); // the time at which the grenade will be thrown. If this value is 0 then the time hasn't been set yet. - -private: - CBaseSDKGrenade( const CBaseSDKGrenade & ) {} -}; - - -inline bool CBaseSDKGrenade::IsPinPulled() const -{ - return m_bPinPulled; -} - - -#endif // WEAPON_BASESDKGRENADE_H diff --git a/game/shared/sdk/weapon_grenade.cpp b/game/shared/sdk/weapon_grenade.cpp deleted file mode 100644 index 1ede4c8ab..000000000 --- a/game/shared/sdk/weapon_grenade.cpp +++ /dev/null @@ -1,114 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "weapon_sdkbase.h" -#include "gamerules.h" -#include "npcevent.h" -#include "engine/IEngineSound.h" -#include "weapon_grenade.h" - - -#ifdef CLIENT_DLL - -#else - - #include "sdk_player.h" - #include "items.h" - #include "sdk_basegrenade_projectile.h" - -#endif - - -#define GRENADE_TIMER 3.0f //Seconds - -IMPLEMENT_NETWORKCLASS_ALIASED( SDKGrenade, DT_SDKGrenade ) - -BEGIN_NETWORK_TABLE(CSDKGrenade, DT_SDKGrenade) -END_NETWORK_TABLE() - -BEGIN_PREDICTION_DATA( CSDKGrenade ) -END_PREDICTION_DATA() - -LINK_ENTITY_TO_CLASS( weapon_grenade, CSDKGrenade ); -PRECACHE_WEAPON_REGISTER( weapon_grenade ); - - -#ifdef GAME_DLL - -#define GRENADE_MODEL "models/Weapons/w_eq_fraggrenade_thrown.mdl" - -class CGrenadeProjectile : public CBaseGrenadeProjectile -{ -public: - DECLARE_CLASS( CGrenadeProjectile, CBaseGrenadeProjectile ); - - - // Overrides. -public: - virtual void Spawn() - { - SetModel( GRENADE_MODEL ); - BaseClass::Spawn(); - } - - virtual void Precache() - { - PrecacheModel( GRENADE_MODEL ); - BaseClass::Precache(); - } - - // Grenade stuff. -public: - - static CGrenadeProjectile* Create( - const Vector &position, - const QAngle &angles, - const Vector &velocity, - const AngularImpulse &angVelocity, - CBaseCombatCharacter *pOwner, - float timer ) - { - CGrenadeProjectile *pGrenade = (CGrenadeProjectile*)CBaseEntity::Create( "grenade_projectile", position, angles, pOwner ); - - // Set the timer for 1 second less than requested. We're going to issue a SOUND_DANGER - // one second before detonation. - - pGrenade->SetDetonateTimerLength( 1.5 ); - pGrenade->SetAbsVelocity( velocity ); - pGrenade->SetupInitialTransmittedGrenadeVelocity( velocity ); - pGrenade->SetThrower( pOwner ); - - pGrenade->SetGravity( BaseClass::GetGrenadeGravity() ); - pGrenade->SetFriction( BaseClass::GetGrenadeFriction() ); - pGrenade->SetElasticity( BaseClass::GetGrenadeElasticity() ); - - pGrenade->m_flDamage = 100; - pGrenade->m_DmgRadius = pGrenade->m_flDamage * 3.5f; - pGrenade->ChangeTeam( pOwner->GetTeamNumber() ); - pGrenade->ApplyLocalAngularVelocityImpulse( angVelocity ); - - // make NPCs afaid of it while in the air - pGrenade->SetThink( &CGrenadeProjectile::DangerSoundThink ); - pGrenade->SetNextThink( gpGlobals->curtime ); - - return pGrenade; - } -}; - -LINK_ENTITY_TO_CLASS( grenade_projectile, CGrenadeProjectile ); -PRECACHE_WEAPON_REGISTER( grenade_projectile ); - -BEGIN_DATADESC( CSDKGrenade ) -END_DATADESC() - -void CSDKGrenade::EmitGrenade( Vector vecSrc, QAngle vecAngles, Vector vecVel, AngularImpulse angImpulse, CBasePlayer *pPlayer ) -{ - CGrenadeProjectile::Create( vecSrc, vecAngles, vecVel, angImpulse, pPlayer, GRENADE_TIMER ); -} - -#endif - diff --git a/game/shared/sdk/weapon_grenade.h b/game/shared/sdk/weapon_grenade.h deleted file mode 100644 index 71ec80ada..000000000 --- a/game/shared/sdk/weapon_grenade.h +++ /dev/null @@ -1,49 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef WEAPON_GRENADE_H -#define WEAPON_GRENADE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "weapon_basesdkgrenade.h" - - -#ifdef CLIENT_DLL - - #define CSDKGrenade C_SDKGrenade - -#endif - -//----------------------------------------------------------------------------- -// Fragmentation grenades -//----------------------------------------------------------------------------- -class CSDKGrenade : public CBaseSDKGrenade -{ -public: - DECLARE_CLASS( CSDKGrenade, CBaseSDKGrenade ); - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - - CSDKGrenade() {} - - virtual SDKWeaponID GetWeaponID( void ) const { return WEAPON_GRENADE; } - -#ifdef CLIENT_DLL - -#else - DECLARE_DATADESC(); - - virtual void EmitGrenade( Vector vecSrc, QAngle vecAngles, Vector vecVel, AngularImpulse angImpulse, CBasePlayer *pPlayer ); - -#endif - - CSDKGrenade( const CSDKGrenade & ) {} -}; - - -#endif // WEAPON_GRENADE_H diff --git a/game/shared/sdk/weapon_mp5.cpp b/game/shared/sdk/weapon_mp5.cpp deleted file mode 100644 index a02ec0987..000000000 --- a/game/shared/sdk/weapon_mp5.cpp +++ /dev/null @@ -1,168 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "weapon_sdkbase.h" -#include "sdk_fx_shared.h" - - -#if defined( CLIENT_DLL ) - - #define CWeaponMP5 C_WeaponMP5 - #include "c_sdk_player.h" - -#else - - #include "sdk_player.h" - -#endif - - -class CWeaponMP5 : public CWeaponSDKBase -{ -public: - DECLARE_CLASS( CWeaponMP5, CWeaponSDKBase ); - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - - CWeaponMP5(); - - virtual void PrimaryAttack(); - virtual bool Deploy(); - virtual bool Reload(); - virtual void WeaponIdle(); - - virtual SDKWeaponID GetWeaponID( void ) const { return WEAPON_MP5; } - - -private: - - CWeaponMP5( const CWeaponMP5 & ); - - void Fire( float flSpread ); -}; - -IMPLEMENT_NETWORKCLASS_ALIASED( WeaponMP5, DT_WeaponMP5 ) - -BEGIN_NETWORK_TABLE( CWeaponMP5, DT_WeaponMP5 ) -END_NETWORK_TABLE() - -BEGIN_PREDICTION_DATA( CWeaponMP5 ) -END_PREDICTION_DATA() - -LINK_ENTITY_TO_CLASS( weapon_mp5, CWeaponMP5 ); -PRECACHE_WEAPON_REGISTER( weapon_mp5 ); - - - -CWeaponMP5::CWeaponMP5() -{ -} - -bool CWeaponMP5::Deploy( ) -{ - CSDKPlayer *pPlayer = GetPlayerOwner(); - pPlayer->m_iShotsFired = 0; - - return BaseClass::Deploy(); -} - -bool CWeaponMP5::Reload( ) -{ - CSDKPlayer *pPlayer = GetPlayerOwner(); - - if (pPlayer->GetAmmoCount( GetPrimaryAmmoType() ) <= 0) - return false; - - int iResult = DefaultReload( GetMaxClip1(), GetMaxClip2(), ACT_VM_RELOAD ); - if ( !iResult ) - return false; - - pPlayer->SetAnimation( PLAYER_RELOAD ); - -#ifndef CLIENT_DLL - if ((iResult) && (pPlayer->GetFOV() != pPlayer->GetDefaultFOV())) - { - pPlayer->SetFOV( pPlayer, pPlayer->GetDefaultFOV() ); - } -#endif - - pPlayer->m_iShotsFired = 0; - - return true; -} - -void CWeaponMP5::PrimaryAttack( void ) -{ - const CSDKWeaponInfo &pWeaponInfo = GetSDKWpnData(); - CSDKPlayer *pPlayer = GetPlayerOwner(); - - float flCycleTime = pWeaponInfo.m_flCycleTime; - - bool bPrimaryMode = true; - - float flSpread = 0.01f; - - // more spread when jumping - if ( !FBitSet( pPlayer->GetFlags(), FL_ONGROUND ) ) - flSpread = 0.05f; - - pPlayer->m_iShotsFired++; - - // Out of ammo? - if ( m_iClip1 <= 0 ) - { - if (m_bFireOnEmpty) - { - PlayEmptySound(); - m_flNextPrimaryAttack = gpGlobals->curtime + 0.2; - } - } - - SendWeaponAnim( ACT_VM_PRIMARYATTACK ); - - m_iClip1--; - - // player "shoot" animation - pPlayer->SetAnimation( PLAYER_ATTACK1 ); - - FX_FireBullets( - pPlayer->entindex(), - pPlayer->Weapon_ShootPosition(), - pPlayer->EyeAngles() + pPlayer->GetPunchAngle(), - GetWeaponID(), - bPrimaryMode?Primary_Mode:Secondary_Mode, - CBaseEntity::GetPredictionRandomSeed() & 255, - flSpread ); - - pPlayer->DoMuzzleFlash(); - - m_flNextPrimaryAttack = m_flNextSecondaryAttack = gpGlobals->curtime + flCycleTime; - - if (!m_iClip1 && pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0) - { - // HEV suit - indicate out of ammo condition - pPlayer->SetSuitUpdate("!HEV_AMO0", false, 0); - } - - // start idle animation in 5 seconds - SetWeaponIdleTime( gpGlobals->curtime + 5.0 ); -} - -void CWeaponMP5::WeaponIdle() -{ - if (m_flTimeWeaponIdle > gpGlobals->curtime) - return; - - // only idle if the slid isn't back - if ( m_iClip1 != 0 ) - { - SetWeaponIdleTime( gpGlobals->curtime + 5.0f ); - SendWeaponAnim( ACT_VM_IDLE ); - } -} - - diff --git a/game/shared/sdk/weapon_sdkbase.cpp b/game/shared/sdk/weapon_sdkbase.cpp deleted file mode 100644 index 035c805de..000000000 --- a/game/shared/sdk/weapon_sdkbase.cpp +++ /dev/null @@ -1,172 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "in_buttons.h" -#include "takedamageinfo.h" -#include "weapon_sdkbase.h" -#include "ammodef.h" - - -#if defined( CLIENT_DLL ) - - #include "c_sdk_player.h" - -#else - - #include "sdk_player.h" - -#endif - - -// ----------------------------------------------------------------------------- // -// Global functions. -// ----------------------------------------------------------------------------- // - -//-------------------------------------------------------------------------------------------------------- -static const char * s_WeaponAliasInfo[] = -{ - "none", // WEAPON_NONE - "mp5", // WEAPON_MP5 - "shotgun", // WEAPON_SHOTGUN - "grenade", // WEAPON_GRENADE - NULL, // WEAPON_NONE -}; - -//-------------------------------------------------------------------------------------------------------- -// -// Given an alias, return the associated weapon ID -// -int AliasToWeaponID( const char *alias ) -{ - if (alias) - { - for( int i=0; s_WeaponAliasInfo[i] != NULL; ++i ) - if (!Q_stricmp( s_WeaponAliasInfo[i], alias )) - return i; - } - - return WEAPON_NONE; -} - -//-------------------------------------------------------------------------------------------------------- -// -// Given a weapon ID, return its alias -// -const char *WeaponIDToAlias( int id ) -{ - if ( (id >= WEAPON_MAX) || (id < 0) ) - return NULL; - - return s_WeaponAliasInfo[id]; -} - -// ----------------------------------------------------------------------------- // -// CWeaponSDKBase tables. -// ----------------------------------------------------------------------------- // - -IMPLEMENT_NETWORKCLASS_ALIASED( WeaponSDKBase, DT_WeaponSDKBase ) - -BEGIN_NETWORK_TABLE( CWeaponSDKBase, DT_WeaponSDKBase ) -#ifdef CLIENT_DLL - -#else - // world weapon models have no animations - SendPropExclude( "DT_AnimTimeMustBeFirst", "m_flAnimTime" ), - SendPropExclude( "DT_BaseAnimating", "m_nSequence" ), -#endif -END_NETWORK_TABLE() - -#ifdef CLIENT_DLL -BEGIN_PREDICTION_DATA( CWeaponSDKBase ) - DEFINE_PRED_FIELD( m_flTimeWeaponIdle, FIELD_FLOAT, FTYPEDESC_OVERRIDE | FTYPEDESC_NOERRORCHECK ), -END_PREDICTION_DATA() -#endif - -LINK_ENTITY_TO_CLASS( weapon_sdk_base, CWeaponSDKBase ); - - -#ifdef GAME_DLL - - BEGIN_DATADESC( CWeaponSDKBase ) - - // New weapon Think and Touch Functions go here.. - - END_DATADESC() - -#endif - -#ifdef CLIENT_DLL -bool CWeaponSDKBase::ShouldPredict() -{ - if ( GetOwner() && GetOwner() == C_BasePlayer::GetLocalPlayer()) - return true; - - return BaseClass::ShouldPredict(); -} -#endif -// ----------------------------------------------------------------------------- // -// CWeaponCSBase implementation. -// ----------------------------------------------------------------------------- // -CWeaponSDKBase::CWeaponSDKBase() -{ - SetPredictionEligible( true ); - - AddSolidFlags( FSOLID_TRIGGER ); // Nothing collides with these but it gets touches. -} - -const CSDKWeaponInfo &CWeaponSDKBase::GetSDKWpnData() const -{ - const FileWeaponInfo_t *pWeaponInfo = &GetWpnData(); - const CSDKWeaponInfo *pSDKInfo; - - #ifdef _DEBUG - pSDKInfo = dynamic_cast< const CSDKWeaponInfo* >( pWeaponInfo ); - Assert( pSDKInfo ); - #else - pSDKInfo = static_cast< const CSDKWeaponInfo* >( pWeaponInfo ); - #endif - - return *pSDKInfo; -} - -bool CWeaponSDKBase::PlayEmptySound() -{ - CPASAttenuationFilter filter( this ); - filter.UsePredictionRules(); - - EmitSound( filter, entindex(), "Default.ClipEmpty_Rifle" ); - - return 0; -} - -CSDKPlayer* CWeaponSDKBase::GetPlayerOwner() const -{ - return dynamic_cast< CSDKPlayer* >( GetOwner() ); -} - -#ifdef GAME_DLL - -void CWeaponSDKBase::SendReloadEvents() -{ - CSDKPlayer *pPlayer = dynamic_cast< CSDKPlayer* >( GetOwner() ); - if ( !pPlayer ) - return; - - // Send a message to any clients that have this entity to play the reload. - CPASFilter filter( pPlayer->GetAbsOrigin() ); - filter.RemoveRecipient( pPlayer ); - - UserMessageBegin( filter, "ReloadEffect" ); - WRITE_SHORT( pPlayer->entindex() ); - MessageEnd(); - - // Make the player play his reload animation. - pPlayer->DoAnimationEvent( PLAYERANIMEVENT_RELOAD ); -} - -#endif diff --git a/game/shared/sdk/weapon_sdkbase.h b/game/shared/sdk/weapon_sdkbase.h deleted file mode 100644 index c054d0b59..000000000 --- a/game/shared/sdk/weapon_sdkbase.h +++ /dev/null @@ -1,88 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef WEAPON_SDKBASE_H -#define WEAPON_SDKBASE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "sdk_playeranimstate.h" -#include "sdk_weapon_parse.h" - -#if defined( CLIENT_DLL ) - #define CWeaponSDKBase C_WeaponSDKBase -#endif - -class CSDKPlayer; - -// These are the names of the ammo types that the weapon script files reference. -#define AMMO_BULLETS "AMMO_BULLETS" -#define AMMO_ROCKETS "AMMO_ROCKETS" -#define AMMO_GRENADE "AMMO_GRENADE" -#define AMMO_GAUSS "AMMO_GAUSS" - -//-------------------------------------------------------------------------------------------------------- -// -// Weapon IDs for all SDK Game weapons -// -typedef enum -{ - WEAPON_NONE = 0, - - WEAPON_MP5, - WEAPON_SHOTGUN, - WEAPON_GRENADE, - - WEAPON_MAX, // number of weapons weapon index -} SDKWeaponID; - -typedef enum -{ - Primary_Mode = 0, - Secondary_Mode, -} SDKWeaponMode; - -const char *WeaponIDToAlias( int id ); - -class CWeaponSDKBase : public CBaseCombatWeapon -{ -public: - DECLARE_CLASS( CWeaponSDKBase, CBaseCombatWeapon ); - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - - CWeaponSDKBase(); - - #ifdef GAME_DLL - DECLARE_DATADESC(); - #endif - #ifdef CLIENT_DLL - virtual bool ShouldPredict(); - #endif - // All predicted weapons need to implement and return true - virtual bool IsPredicted() const { return true; } - virtual SDKWeaponID GetWeaponID( void ) const { return WEAPON_NONE; } - - // Get SDK weapon specific weapon data. - CSDKWeaponInfo const &GetSDKWpnData() const; - - // Get a pointer to the player that owns this weapon - CSDKPlayer* GetPlayerOwner() const; - - // override to play custom empty sounds - virtual bool PlayEmptySound(); - -#ifdef GAME_DLL - virtual void SendReloadEvents(); -#endif - -private: - CWeaponSDKBase( const CWeaponSDKBase & ); -}; - - -#endif // WEAPON_SDKBASE_H diff --git a/game/shared/sdk/weapon_shotgun.cpp b/game/shared/sdk/weapon_shotgun.cpp deleted file mode 100644 index 9a70fccf9..000000000 --- a/game/shared/sdk/weapon_shotgun.cpp +++ /dev/null @@ -1,246 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "weapon_sdkbase.h" -#include "sdk_fx_shared.h" - - -#if defined( CLIENT_DLL ) - - #define CWeaponShotgun C_WeaponShotgun - #include "c_sdk_player.h" - -#else - - #include "sdk_player.h" - #include "te_firebullets.h" - -#endif - - -class CWeaponShotgun : public CWeaponSDKBase -{ -public: - DECLARE_CLASS( CWeaponShotgun, CWeaponSDKBase ); - DECLARE_NETWORKCLASS(); - DECLARE_PREDICTABLE(); - - CWeaponShotgun(); - - virtual void PrimaryAttack(); - virtual bool Reload(); - virtual void WeaponIdle(); - - virtual SDKWeaponID GetWeaponID( void ) const { return WEAPON_SHOTGUN; } - - -private: - - CWeaponShotgun( const CWeaponShotgun & ); - - float m_flPumpTime; - CNetworkVar( int, m_fInSpecialReload ); - -}; - -IMPLEMENT_NETWORKCLASS_ALIASED( WeaponShotgun, DT_WeaponShotgun ) - -BEGIN_NETWORK_TABLE( CWeaponShotgun, DT_WeaponShotgun ) - - #ifdef CLIENT_DLL - RecvPropInt( RECVINFO( m_fInSpecialReload ) ) - #else - SendPropInt( SENDINFO( m_fInSpecialReload ), 2, SPROP_UNSIGNED ) - #endif - -END_NETWORK_TABLE() - -BEGIN_PREDICTION_DATA( CWeaponShotgun ) -END_PREDICTION_DATA() - -LINK_ENTITY_TO_CLASS( weapon_shotgun, CWeaponShotgun ); -PRECACHE_WEAPON_REGISTER( weapon_shotgun ); - - - -CWeaponShotgun::CWeaponShotgun() -{ - m_flPumpTime = 0; -} - -void CWeaponShotgun::PrimaryAttack() -{ - CSDKPlayer *pPlayer = GetPlayerOwner(); - if ( !pPlayer ) - return; - - // don't fire underwater - if (pPlayer->GetWaterLevel() == 3) - { - PlayEmptySound( ); - m_flNextPrimaryAttack = gpGlobals->curtime + 0.15; - return; - } - - // Out of ammo? - if ( m_iClip1 <= 0 ) - { - Reload(); - if ( m_iClip1 == 0 ) - { - PlayEmptySound(); - m_flNextPrimaryAttack = gpGlobals->curtime + 0.2; - } - - return; - } - - SendWeaponAnim( ACT_VM_PRIMARYATTACK ); - - m_iClip1--; - pPlayer->DoMuzzleFlash(); - - // player "shoot" animation - pPlayer->SetAnimation( PLAYER_ATTACK1 ); - - // Dispatch the FX right away with full accuracy. - FX_FireBullets( - pPlayer->entindex(), - pPlayer->Weapon_ShootPosition(), - pPlayer->EyeAngles() + 2.0f * pPlayer->GetPunchAngle(), - GetWeaponID(), - Primary_Mode, - CBaseEntity::GetPredictionRandomSeed() & 255, // wrap it for network traffic so it's the same between client and server - 0.0675 ); - - if (!m_iClip1 && pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0) - { - // HEV suit - indicate out of ammo condition - pPlayer->SetSuitUpdate("!HEV_AMO0", false, 0); - } - - if (m_iClip1 != 0) - m_flPumpTime = gpGlobals->curtime + 0.5; - - m_flNextPrimaryAttack = gpGlobals->curtime + 0.875; - m_flNextSecondaryAttack = gpGlobals->curtime + 0.875; - if (m_iClip1 != 0) - SetWeaponIdleTime( gpGlobals->curtime + 2.5 ); - else - SetWeaponIdleTime( gpGlobals->curtime + 0.875 ); - m_fInSpecialReload = 0; - - // Update punch angles. - QAngle angle = pPlayer->GetPunchAngle(); - - if ( pPlayer->GetFlags() & FL_ONGROUND ) - { - angle.x -= SharedRandomInt( "ShotgunPunchAngleGround", 4, 6 ); - } - else - { - angle.x -= SharedRandomInt( "ShotgunPunchAngleAir", 8, 11 ); - } - - pPlayer->SetPunchAngle( angle ); -} - - -bool CWeaponShotgun::Reload() -{ - CSDKPlayer *pPlayer = GetPlayerOwner(); - - if (pPlayer->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 || m_iClip1 == GetMaxClip1()) - return true; - - // don't reload until recoil is done - if (m_flNextPrimaryAttack > gpGlobals->curtime) - return true; - - // check to see if we're ready to reload - if (m_fInSpecialReload == 0) - { - pPlayer->SetAnimation( PLAYER_RELOAD ); - - SendWeaponAnim( ACT_SHOTGUN_RELOAD_START ); - m_fInSpecialReload = 1; - pPlayer->m_flNextAttack = gpGlobals->curtime + 0.5; - m_flNextPrimaryAttack = gpGlobals->curtime + 0.5; - m_flNextSecondaryAttack = gpGlobals->curtime + 0.5; - SetWeaponIdleTime( gpGlobals->curtime + 0.5 ); - return true; - } - else if (m_fInSpecialReload == 1) - { - if (m_flTimeWeaponIdle > gpGlobals->curtime) - return true; - // was waiting for gun to move to side - m_fInSpecialReload = 2; - - SendWeaponAnim( ACT_VM_RELOAD ); - SetWeaponIdleTime( gpGlobals->curtime + 0.45 ); - } - else - { - // Add them to the clip - m_iClip1 += 1; - -#ifdef GAME_DLL - SendReloadEvents(); -#endif - - CSDKPlayer *pPlayer = GetPlayerOwner(); - - if ( pPlayer ) - pPlayer->RemoveAmmo( 1, m_iPrimaryAmmoType ); - - m_fInSpecialReload = 1; - } - - return true; -} - - -void CWeaponShotgun::WeaponIdle() -{ - CSDKPlayer *pPlayer = GetPlayerOwner(); - - if (m_flPumpTime && m_flPumpTime < gpGlobals->curtime) - { - // play pumping sound - m_flPumpTime = 0; - } - - if (m_flTimeWeaponIdle < gpGlobals->curtime) - { - if (m_iClip1 == 0 && m_fInSpecialReload == 0 && pPlayer->GetAmmoCount( m_iPrimaryAmmoType )) - { - Reload( ); - } - else if (m_fInSpecialReload != 0) - { - if (m_iClip1 != 8 && pPlayer->GetAmmoCount( m_iPrimaryAmmoType )) - { - Reload( ); - } - else - { - // reload debounce has timed out - //MIKETODO: shotgun anims - SendWeaponAnim( ACT_SHOTGUN_RELOAD_FINISH ); - - // play cocking sound - m_fInSpecialReload = 0; - SetWeaponIdleTime( gpGlobals->curtime + 1.5 ); - } - } - else - { - SendWeaponAnim( ACT_VM_IDLE ); - } - } -} diff --git a/game/shared/sequence_Transitioner.cpp b/game/shared/sequence_Transitioner.cpp deleted file mode 100644 index f1b4cd018..000000000 --- a/game/shared/sequence_Transitioner.cpp +++ /dev/null @@ -1,115 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "sequence_Transitioner.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// ----------------------------------------------------------------------------- -// CSequenceTransitioner implementation. -// ----------------------------------------------------------------------------- - -void CSequenceTransitioner::CheckForSequenceChange( - CStudioHdr *hdr, - int nCurSequence, - bool bForceNewSequence, - bool bInterpolate ) -{ - // sequence may be set before model is initialized - if ( hdr == NULL) - return; - - // FIXME?: this should detect that what's been asked to be drawn isn't what was expected - // due to not only sequence change, by frame index, rate, or whatever. When that happens, - // it should insert the previous rules. - - if (m_animationQueue.Count() == 0) - { - m_animationQueue.AddToTail(); - } - - CAnimationLayer *currentblend = &m_animationQueue[m_animationQueue.Count()-1]; - - if (currentblend->m_flLayerAnimtime && - (currentblend->m_nSequence != nCurSequence || bForceNewSequence )) - { - mstudioseqdesc_t &seqdesc = hdr->pSeqdesc( nCurSequence ); - // sequence changed - if ((seqdesc.flags & STUDIO_SNAP) || !bInterpolate ) - { - // remove all entries - m_animationQueue.RemoveAll(); - } - else - { - mstudioseqdesc_t &prevseqdesc = hdr->pSeqdesc( currentblend->m_nSequence ); - currentblend->m_flLayerFadeOuttime = MIN( prevseqdesc.fadeouttime, seqdesc.fadeintime ); - /* - // clip blends to time remaining - if ( !IsSequenceLooping(hdr, currentblend->m_nSequence) ) - { - float length = Studio_Duration( hdr, currentblend->m_nSequence, flPoseParameter ) / currentblend->m_flPlaybackRate; - float timeLeft = (1.0 - currentblend->m_flCycle) * length; - if (timeLeft < currentblend->m_flLayerFadeOuttime) - currentblend->m_flLayerFadeOuttime = timeLeft; - } - */ - } - // push previously set sequence - m_animationQueue.AddToTail(); - currentblend = &m_animationQueue[m_animationQueue.Count()-1]; - - } - - currentblend->m_nSequence = -1; - currentblend->m_flLayerAnimtime = 0.0; - currentblend->m_flLayerFadeOuttime = 0.0; -} - - -void CSequenceTransitioner::UpdateCurrent( - CStudioHdr *hdr, - int nCurSequence, - float flCurCycle, - float flCurPlaybackRate, - float flCurTime ) -{ - // sequence may be set before model is initialized - if ( hdr == NULL) - return; - - if (m_animationQueue.Count() == 0) - { - m_animationQueue.AddToTail(); - } - - CAnimationLayer *currentblend = &m_animationQueue[m_animationQueue.Count()-1]; - - // keep track of current sequence - currentblend->m_nSequence = nCurSequence; - currentblend->m_flLayerAnimtime = flCurTime; - currentblend->m_flCycle = flCurCycle; - currentblend->m_flPlaybackRate = flCurPlaybackRate; - - // calc blending weights for previous sequences - int i; - for (i = 0; i < m_animationQueue.Count() - 1;) - { - float s = m_animationQueue[i].GetFadeout( flCurTime ); - - if (s > 0) - { - m_animationQueue[i].m_flWeight = s; - i++; - } - else - { - m_animationQueue.Remove( i ); - } - } -} diff --git a/game/shared/sequence_Transitioner.h b/game/shared/sequence_Transitioner.h deleted file mode 100644 index 60bc4eb74..000000000 --- a/game/shared/sequence_Transitioner.h +++ /dev/null @@ -1,48 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef SEQUENCE_TRANSITIONER_H -#define SEQUENCE_TRANSITIONER_H -#ifdef _WIN32 -#pragma once -#endif - - -// ------------------------------------------------------------------------------------------------ // -// CSequenceTransitioner declaration. -// ------------------------------------------------------------------------------------------------ // -class CSequenceTransitioner -{ -public: - void CheckForSequenceChange( - // Describe the current animation state with these parameters. - CStudioHdr *hdr, - int nCurSequence, - - // Even if the sequence hasn't changed, you can force it to interpolate from the previous - // spot in the same sequence to the current spot in the same sequence by setting this to true. - bool bForceNewSequence, - - // Follows EF_NOINTERP. - bool bInterpolate - ); - - void UpdateCurrent( - // Describe the current animation state with these parameters. - CStudioHdr *hdr, - int nCurSequence, - float flCurCycle, - float flCurPlaybackRate, - float flCurTime - ); - - void RemoveAll( void ) { m_animationQueue.RemoveAll(); }; - -public: - CUtlVector< CAnimationLayer > m_animationQueue; -}; - -#endif // SEQUENCE_TRANSITIONER_H diff --git a/game/shared/sharedInterface.h b/game/shared/sharedInterface.h deleted file mode 100644 index 5b470e478..000000000 --- a/game/shared/sharedInterface.h +++ /dev/null @@ -1,31 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Exposes client-server neutral interfaces implemented in both places -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SHAREDINTERFACE_H -#define SHAREDINTERFACE_H - -class IFileSystem; -class IUniformRandomStream; -class IEngineSound; -class IMapData; - -extern IFileSystem *filesystem; -#if defined(_STATIC_LINKED) && defined(_SUBSYSTEM) && (defined(CLIENT_DLL) || defined(GAME_DLL)) -namespace _SUBSYSTEM -{ -extern IUniformRandomStream *random; -} -#else -extern IUniformRandomStream *random; -#endif -extern IEngineSound *enginesound; -extern IMapData *g_pMapData; // TODO: current implementations of the - // interface are in TF2, should probably move - // to TF2/HL2 neutral territory - -#endif // SHAREDINTERFACE_H - diff --git a/game/shared/shared_classnames.h b/game/shared/shared_classnames.h deleted file mode 100644 index b9cc4c56e..000000000 --- a/game/shared/shared_classnames.h +++ /dev/null @@ -1,25 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SHARED_CLASSNAMES_H -#define SHARED_CLASSNAMES_H -#ifdef _WIN32 -#pragma once -#endif - -// Hacky macros to allow shared code to work without even worse macro-izing -#if defined( CLIENT_DLL ) - -#define CBaseEntity C_BaseEntity -#define CBaseCombatCharacter C_BaseCombatCharacter -#define CBaseAnimating C_BaseAnimating -#define CBasePlayer C_BasePlayer - -#endif - - -#endif // SHARED_CLASSNAMES_H diff --git a/game/shared/shareddefs.h b/game/shared/shareddefs.h deleted file mode 100644 index fab4609e1..000000000 --- a/game/shared/shareddefs.h +++ /dev/null @@ -1,806 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Definitions that are shared by the game DLL and the client DLL. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SHAREDDEFS_H -#define SHAREDDEFS_H -#ifdef _WIN32 -#pragma once -#endif - -#define TICK_INTERVAL (gpGlobals->interval_per_tick) - - -#define TIME_TO_TICKS( dt ) ( (int)( 0.5f + (float)(dt) / TICK_INTERVAL ) ) -#define TICKS_TO_TIME( t ) ( TICK_INTERVAL *( t ) ) -#define ROUND_TO_TICKS( t ) ( TICK_INTERVAL * TIME_TO_TICKS( t ) ) -#define TICK_NEVER_THINK (-1) - -#if defined( TF_DLL ) -#define ANIMATION_CYCLE_BITS 10 -#else -#define ANIMATION_CYCLE_BITS 15 -#endif -#define ANIMATION_CYCLE_MINFRAC (1.0f / (1<GetViewVectors()->m_vView -#define VEC_HULL_MIN g_pGameRules->GetViewVectors()->m_vHullMin -#define VEC_HULL_MAX g_pGameRules->GetViewVectors()->m_vHullMax - -#define VEC_DUCK_HULL_MIN g_pGameRules->GetViewVectors()->m_vDuckHullMin -#define VEC_DUCK_HULL_MAX g_pGameRules->GetViewVectors()->m_vDuckHullMax -#define VEC_DUCK_VIEW g_pGameRules->GetViewVectors()->m_vDuckView - -#define VEC_OBS_HULL_MIN g_pGameRules->GetViewVectors()->m_vObsHullMin -#define VEC_OBS_HULL_MAX g_pGameRules->GetViewVectors()->m_vObsHullMax - -#define VEC_DEAD_VIEWHEIGHT g_pGameRules->GetViewVectors()->m_vDeadViewHeight - - -#define WATERJUMP_HEIGHT 8 - -#define MAX_CLIMB_SPEED 200 - -#if defined(TF_DLL) || defined(TF_CLIENT_DLL) - #define TIME_TO_DUCK 0.2 -#else - #define TIME_TO_DUCK 0.4 -#endif -#define TIME_TO_UNDUCK 0.2 - -#define MAX_WEAPON_SLOTS 6 // hud item selection slots -#define MAX_WEAPON_POSITIONS 20 // max number of items within a slot -#define MAX_ITEM_TYPES 6 // hud item selection slots -#define MAX_WEAPONS 48 // Max number of weapons available - -#define MAX_ITEMS 5 // hard coded item types - -#define WEAPON_NOCLIP -1 // clip sizes set to this tell the weapon it doesn't use a clip - -#define MAX_AMMO_TYPES 32 // ??? -#define MAX_AMMO_SLOTS 32 // not really slots - -#define HUD_PRINTNOTIFY 1 -#define HUD_PRINTCONSOLE 2 -#define HUD_PRINTTALK 3 -#define HUD_PRINTCENTER 4 - -//=================================================================================================================== -// Close caption flags -#define CLOSE_CAPTION_WARNIFMISSING ( 1<<0 ) -#define CLOSE_CAPTION_FROMPLAYER ( 1<<1 ) -#define CLOSE_CAPTION_GENDER_MALE ( 1<<2 ) -#define CLOSE_CAPTION_GENDER_FEMALE ( 1<<3 ) - -//=================================================================================================================== -// Hud Element hiding flags -#define HIDEHUD_WEAPONSELECTION ( 1<<0 ) // Hide ammo count & weapon selection -#define HIDEHUD_FLASHLIGHT ( 1<<1 ) -#define HIDEHUD_ALL ( 1<<2 ) -#define HIDEHUD_HEALTH ( 1<<3 ) // Hide health & armor / suit battery -#define HIDEHUD_PLAYERDEAD ( 1<<4 ) // Hide when local player's dead -#define HIDEHUD_NEEDSUIT ( 1<<5 ) // Hide when the local player doesn't have the HEV suit -#define HIDEHUD_MISCSTATUS ( 1<<6 ) // Hide miscellaneous status elements (trains, pickup history, death notices, etc) -#define HIDEHUD_CHAT ( 1<<7 ) // Hide all communication elements (saytext, voice icon, etc) -#define HIDEHUD_CROSSHAIR ( 1<<8 ) // Hide crosshairs -#define HIDEHUD_VEHICLE_CROSSHAIR ( 1<<9 ) // Hide vehicle crosshair -#define HIDEHUD_INVEHICLE ( 1<<10 ) -#define HIDEHUD_BONUS_PROGRESS ( 1<<11 ) // Hide bonus progress display (for bonus map challenges) - -#define HIDEHUD_BITCOUNT 12 - -//=================================================================================================================== -// suit usage bits -#define bits_SUIT_DEVICE_SPRINT 0x00000001 -#define bits_SUIT_DEVICE_FLASHLIGHT 0x00000002 -#define bits_SUIT_DEVICE_BREATHER 0x00000004 - -#define MAX_SUIT_DEVICES 3 - - -//=================================================================================================================== -// Player Defines - -// Max number of players in a game ( see const.h for ABSOLUTE_PLAYER_LIMIT (256 ) ) -// The Source engine is really designed for 32 or less players. If you raise this number above 32, you better know what you are doing -// and have a good answer for a bunch of perf question related to player simulation, thinking logic, tracelines, networking overhead, etc. -// But if you are brave or are doing something interesting, go for it... ywb 9/22/03 -#if defined( CSTRIKE_DLL ) - #define MAX_PLAYERS 65 // Absolute max players supported -#else - #define MAX_PLAYERS 33 // Absolute max players supported -#endif - -#define MAX_PLACE_NAME_LENGTH 18 - -//=================================================================================================================== -// Team Defines -#define TEAM_INVALID -1 -#define TEAM_UNASSIGNED 0 // not assigned to a team -#define TEAM_SPECTATOR 1 // spectator team -// Start your team numbers after this -#define LAST_SHARED_TEAM TEAM_SPECTATOR - -// The first team that's game specific (i.e. not unassigned / spectator) -#define FIRST_GAME_TEAM (LAST_SHARED_TEAM+1) - -#define MAX_TEAMS 32 // Max number of teams in a game -#define MAX_TEAM_NAME_LENGTH 32 // Max length of a team's name - -// Weapon m_iState -#define WEAPON_IS_ONTARGET 0x40 - -#define WEAPON_NOT_CARRIED 0 // Weapon is on the ground -#define WEAPON_IS_CARRIED_BY_PLAYER 1 // This client is carrying this weapon. -#define WEAPON_IS_ACTIVE 2 // This client is carrying this weapon and it's the currently held weapon - -// ----------------------------------------- -// Skill Level -// ----------------------------------------- -#define SKILL_EASY 1 -#define SKILL_MEDIUM 2 -#define SKILL_HARD 3 - - -// Weapon flags -// ----------------------------------------- -// Flags - NOTE: KEEP g_ItemFlags IN WEAPON_PARSE.CPP UPDATED WITH THESE -// ----------------------------------------- -#define ITEM_FLAG_SELECTONEMPTY (1<<0) -#define ITEM_FLAG_NOAUTORELOAD (1<<1) -#define ITEM_FLAG_NOAUTOSWITCHEMPTY (1<<2) -#define ITEM_FLAG_LIMITINWORLD (1<<3) -#define ITEM_FLAG_EXHAUSTIBLE (1<<4) // A player can totally exhaust their ammo supply and lose this weapon -#define ITEM_FLAG_DOHITLOCATIONDMG (1<<5) // This weapon take hit location into account when applying damage -#define ITEM_FLAG_NOAMMOPICKUPS (1<<6) // Don't draw ammo pickup sprites/sounds when ammo is received -#define ITEM_FLAG_NOITEMPICKUP (1<<7) // Don't draw weapon pickup when this weapon is picked up by the player -// NOTE: KEEP g_ItemFlags IN WEAPON_PARSE.CPP UPDATED WITH THESE - - -// Humans only have left and right hands, though we might have aliens with more -// than two, sigh -#define MAX_VIEWMODELS 2 - -#define MAX_BEAM_ENTS 10 - -#define TRACER_TYPE_DEFAULT 0x00000001 -#define TRACER_TYPE_GUNSHIP 0x00000002 -#define TRACER_TYPE_STRIDER 0x00000004 // Here ya go, Jay! -#define TRACER_TYPE_GAUSS 0x00000008 -#define TRACER_TYPE_WATERBULLET 0x00000010 - -#define MUZZLEFLASH_TYPE_DEFAULT 0x00000001 -#define MUZZLEFLASH_TYPE_GUNSHIP 0x00000002 -#define MUZZLEFLASH_TYPE_STRIDER 0x00000004 - -// Muzzle flash definitions (for the flags field of the "MuzzleFlash" DispatchEffect) -enum -{ - MUZZLEFLASH_AR2 = 0, - MUZZLEFLASH_SHOTGUN, - MUZZLEFLASH_SMG1, - MUZZLEFLASH_SMG2, - MUZZLEFLASH_PISTOL, - MUZZLEFLASH_COMBINE, - MUZZLEFLASH_357, - MUZZLEFLASH_RPG, - MUZZLEFLASH_COMBINE_TURRET, - - MUZZLEFLASH_FIRSTPERSON = 0x100, -}; - -// Tracer Flags -#define TRACER_FLAG_WHIZ 0x0001 -#define TRACER_FLAG_USEATTACHMENT 0x0002 - -#define TRACER_DONT_USE_ATTACHMENT -1 - -// Entity Dissolve types -enum -{ - ENTITY_DISSOLVE_NORMAL = 0, - ENTITY_DISSOLVE_ELECTRICAL, - ENTITY_DISSOLVE_ELECTRICAL_LIGHT, - ENTITY_DISSOLVE_CORE, - - // NOTE: Be sure to up the bits if you make more dissolve types - ENTITY_DISSOLVE_BITS = 3 -}; - -// --------------------------- -// Hit Group standards -// --------------------------- -#define HITGROUP_GENERIC 0 -#define HITGROUP_HEAD 1 -#define HITGROUP_CHEST 2 -#define HITGROUP_STOMACH 3 -#define HITGROUP_LEFTARM 4 -#define HITGROUP_RIGHTARM 5 -#define HITGROUP_LEFTLEG 6 -#define HITGROUP_RIGHTLEG 7 -#define HITGROUP_GEAR 10 // alerts NPC, but doesn't do damage or bleed (1/100th damage) - -// -// Enumerations for setting player animation. -// -enum PLAYER_ANIM -{ - PLAYER_IDLE, - PLAYER_WALK, - PLAYER_JUMP, - PLAYER_SUPERJUMP, - PLAYER_DIE, - PLAYER_ATTACK1, - PLAYER_IN_VEHICLE, - - // TF Player animations - PLAYER_RELOAD, - PLAYER_START_AIMING, - PLAYER_LEAVE_AIMING, -}; - -#ifdef HL2_DLL -// HL2 has 600 gravity by default -// NOTE: The discrete ticks can have quantization error, so these numbers are biased a little to -// make the heights more exact -#define PLAYER_FATAL_FALL_SPEED 922.5f // approx 60 feet sqrt( 2 * gravity * 60 * 12 ) -#define PLAYER_MAX_SAFE_FALL_SPEED 526.5f // approx 20 feet sqrt( 2 * gravity * 20 * 12 ) -#define PLAYER_LAND_ON_FLOATING_OBJECT 173 // Can fall another 173 in/sec without getting hurt -#define PLAYER_MIN_BOUNCE_SPEED 173 -#define PLAYER_FALL_PUNCH_THRESHOLD 303.0f // won't punch player's screen/make scrape noise unless player falling at least this fast - at least a 76" fall (sqrt( 2 * g * 76)) -#else -#define PLAYER_FATAL_FALL_SPEED 1024 // approx 60 feet -#define PLAYER_MAX_SAFE_FALL_SPEED 580 // approx 20 feet -#define PLAYER_LAND_ON_FLOATING_OBJECT 200 // Can go another 200 units without getting hurt -#define PLAYER_MIN_BOUNCE_SPEED 200 -#define PLAYER_FALL_PUNCH_THRESHOLD (float)350 // won't punch player's screen/make scrape noise unless player falling at least this fast. -#endif -#define DAMAGE_FOR_FALL_SPEED 100.0f / ( PLAYER_FATAL_FALL_SPEED - PLAYER_MAX_SAFE_FALL_SPEED ) // damage per unit per second. - - -#define AUTOAIM_2DEGREES 0.0348994967025 -#define AUTOAIM_5DEGREES 0.08715574274766 -#define AUTOAIM_8DEGREES 0.1391731009601 -#define AUTOAIM_10DEGREES 0.1736481776669 -#define AUTOAIM_20DEGREES 0.3490658503989 - -#define AUTOAIM_SCALE_DEFAULT 1.0f -#define AUTOAIM_SCALE_DIRECT_ONLY 0.0f - -// instant damage - -// For a means of resolving these consts into debug string text, see function -// CTakeDamageInfo::DebugGetDamageTypeString(unsigned int DamageType, char *outbuf, unsigned int outbuflength ) -#define DMG_GENERIC 0 // generic damage was done -#define DMG_CRUSH (1 << 0) // crushed by falling or moving object. - // NOTE: It's assumed crush damage is occurring as a result of physics collision, so no extra physics force is generated by crush damage. - // DON'T use DMG_CRUSH when damaging entities unless it's the result of a physics collision. You probably want DMG_CLUB instead. -#define DMG_BULLET (1 << 1) // shot -#define DMG_SLASH (1 << 2) // cut, clawed, stabbed -#define DMG_BURN (1 << 3) // heat burned -#define DMG_VEHICLE (1 << 4) // hit by a vehicle -#define DMG_FALL (1 << 5) // fell too far -#define DMG_BLAST (1 << 6) // explosive blast damage -#define DMG_CLUB (1 << 7) // crowbar, punch, headbutt -#define DMG_SHOCK (1 << 8) // electric shock -#define DMG_SONIC (1 << 9) // sound pulse shockwave -#define DMG_ENERGYBEAM (1 << 10) // laser or other high energy beam -#define DMG_PREVENT_PHYSICS_FORCE (1 << 11) // Prevent a physics force -#define DMG_NEVERGIB (1 << 12) // with this bit OR'd in, no damage type will be able to gib victims upon death -#define DMG_ALWAYSGIB (1 << 13) // with this bit OR'd in, any damage type can be made to gib victims upon death. -#define DMG_DROWN (1 << 14) // Drowning - - -#define DMG_PARALYZE (1 << 15) // slows affected creature down -#define DMG_NERVEGAS (1 << 16) // nerve toxins, very bad -#define DMG_POISON (1 << 17) // blood poisoning - heals over time like drowning damage -#define DMG_RADIATION (1 << 18) // radiation exposure -#define DMG_DROWNRECOVER (1 << 19) // drowning recovery -#define DMG_ACID (1 << 20) // toxic chemicals or acid burns -#define DMG_SLOWBURN (1 << 21) // in an oven - -#define DMG_REMOVENORAGDOLL (1<<22) // with this bit OR'd in, no ragdoll will be created, and the target will be quietly removed. - // use this to kill an entity that you've already got a server-side ragdoll for - -#define DMG_PHYSGUN (1<<23) // Hit by manipulator. Usually doesn't do any damage. -#define DMG_PLASMA (1<<24) // Shot by Cremator -#define DMG_AIRBOAT (1<<25) // Hit by the airboat's gun - -#define DMG_DISSOLVE (1<<26) // Dissolving! -#define DMG_BLAST_SURFACE (1<<27) // A blast on the surface of water that cannot harm things underwater -#define DMG_DIRECT (1<<28) -#define DMG_BUCKSHOT (1<<29) // not quite a bullet. Little, rounder, different. - -// NOTE: DO NOT ADD ANY MORE CUSTOM DMG_ TYPES. MODS USE THE DMG_LASTGENERICFLAG BELOW, AND -// IF YOU ADD NEW DMG_ TYPES, THEIR TYPES WILL BE HOSED. WE NEED A BETTER SOLUTION. - -// TODO: keep this up to date so all the mod-specific flags don't overlap anything. -#define DMG_LASTGENERICFLAG DMG_BUCKSHOT - - - -// settings for m_takedamage -#define DAMAGE_NO 0 -#define DAMAGE_EVENTS_ONLY 1 // Call damage functions, but don't modify health -#define DAMAGE_YES 2 -#define DAMAGE_AIM 3 - -// Spectator Movement modes -enum { - OBS_MODE_NONE = 0, // not in spectator mode - OBS_MODE_DEATHCAM, // special mode for death cam animation - OBS_MODE_FREEZECAM, // zooms to a target, and freeze-frames on them - OBS_MODE_FIXED, // view from a fixed camera position - OBS_MODE_IN_EYE, // follow a player in first person view - OBS_MODE_CHASE, // follow a player in third person view - OBS_MODE_ROAMING, // free roaming - - NUM_OBSERVER_MODES, -}; - -#define LAST_PLAYER_OBSERVERMODE OBS_MODE_ROAMING - -// Force Camera Restrictions with mp_forcecamera -enum { - OBS_ALLOW_ALL = 0, // allow all modes, all targets - OBS_ALLOW_TEAM, // allow only own team & first person, no PIP - OBS_ALLOW_NONE, // don't allow any spectating after death (fixed & fade to black) - - OBS_ALLOW_NUM_MODES, -}; - -enum -{ - TYPE_TEXT = 0, // just display this plain text - TYPE_INDEX, // lookup text & title in stringtable - TYPE_URL, // show this URL - TYPE_FILE, // show this local file -} ; - -// VGui Screen Flags -enum -{ - VGUI_SCREEN_ACTIVE = 0x1, - VGUI_SCREEN_VISIBLE_TO_TEAMMATES = 0x2, - VGUI_SCREEN_ATTACHED_TO_VIEWMODEL = 0x4, - VGUI_SCREEN_TRANSPARENT = 0x8, - VGUI_SCREEN_ONLY_USABLE_BY_OWNER = 0x10, - - VGUI_SCREEN_MAX_BITS = 5 -}; - -typedef enum -{ - USE_OFF = 0, - USE_ON = 1, - USE_SET = 2, - USE_TOGGLE = 3 -} USE_TYPE; - -// basic team colors -#define COLOR_RED Color(255, 64, 64, 255) -#define COLOR_BLUE Color(153, 204, 255, 255) -#define COLOR_YELLOW Color(255, 178, 0, 255) -#define COLOR_GREEN Color(153, 255, 153, 255) -#define COLOR_GREY Color(204, 204, 204, 255) - -// All NPCs need this data -enum -{ - DONT_BLEED = -1, - - BLOOD_COLOR_RED = 0, - BLOOD_COLOR_YELLOW, - BLOOD_COLOR_GREEN, - BLOOD_COLOR_MECH, - -#if defined( HL2_EPISODIC ) - BLOOD_COLOR_ANTLION, // FIXME: Move to Base HL2 - BLOOD_COLOR_ZOMBIE, // FIXME: Move to Base HL2 - BLOOD_COLOR_ANTLION_WORKER, -#endif // HL2_EPISODIC -}; - -//----------------------------------------------------------------------------- -// Vehicles may have more than one passenger. -// This enum may be expanded by derived classes -//----------------------------------------------------------------------------- -enum PassengerRole_t -{ - VEHICLE_ROLE_NONE = -1, - - VEHICLE_ROLE_DRIVER = 0, // Only one driver - - LAST_SHARED_VEHICLE_ROLE, -}; - -//----------------------------------------------------------------------------- -// Water splash effect flags -//----------------------------------------------------------------------------- -enum -{ - FX_WATER_IN_SLIME = 0x1, -}; - - -// Shared think context stuff -#define MAX_CONTEXT_LENGTH 32 -#define NO_THINK_CONTEXT -1 - -// entity flags, CBaseEntity::m_iEFlags -enum -{ - EFL_KILLME = (1<<0), // This entity is marked for death -- This allows the game to actually delete ents at a safe time - EFL_DORMANT = (1<<1), // Entity is dormant, no updates to client - EFL_NOCLIP_ACTIVE = (1<<2), // Lets us know when the noclip command is active. - EFL_SETTING_UP_BONES = (1<<3), // Set while a model is setting up its bones. - EFL_KEEP_ON_RECREATE_ENTITIES = (1<<4), // This is a special entity that should not be deleted when we restart entities only - - EFL_HAS_PLAYER_CHILD= (1<<4), // One of the child entities is a player. - - EFL_DIRTY_SHADOWUPDATE = (1<<5), // Client only- need shadow manager to update the shadow... - EFL_NOTIFY = (1<<6), // Another entity is watching events on this entity (used by teleport) - - // The default behavior in ShouldTransmit is to not send an entity if it doesn't - // have a model. Certain entities want to be sent anyway because all the drawing logic - // is in the client DLL. They can set this flag and the engine will transmit them even - // if they don't have a model. - EFL_FORCE_CHECK_TRANSMIT = (1<<7), - - EFL_BOT_FROZEN = (1<<8), // This is set on bots that are frozen. - EFL_SERVER_ONLY = (1<<9), // Non-networked entity. - EFL_NO_AUTO_EDICT_ATTACH = (1<<10), // Don't attach the edict; we're doing it explicitly - - // Some dirty bits with respect to abs computations - EFL_DIRTY_ABSTRANSFORM = (1<<11), - EFL_DIRTY_ABSVELOCITY = (1<<12), - EFL_DIRTY_ABSANGVELOCITY = (1<<13), - EFL_DIRTY_SURROUNDING_COLLISION_BOUNDS = (1<<14), - EFL_DIRTY_SPATIAL_PARTITION = (1<<15), -// UNUSED = (1<<16), - - EFL_IN_SKYBOX = (1<<17), // This is set if the entity detects that it's in the skybox. - // This forces it to pass the "in PVS" for transmission. - EFL_USE_PARTITION_WHEN_NOT_SOLID = (1<<18), // Entities with this flag set show up in the partition even when not solid - EFL_TOUCHING_FLUID = (1<<19), // Used to determine if an entity is floating - - // FIXME: Not really sure where I should add this... - EFL_IS_BEING_LIFTED_BY_BARNACLE = (1<<20), - EFL_NO_ROTORWASH_PUSH = (1<<21), // I shouldn't be pushed by the rotorwash - EFL_NO_THINK_FUNCTION = (1<<22), - EFL_NO_GAME_PHYSICS_SIMULATION = (1<<23), - - EFL_CHECK_UNTOUCH = (1<<24), - EFL_DONTBLOCKLOS = (1<<25), // I shouldn't block NPC line-of-sight - EFL_DONTWALKON = (1<<26), // NPC;s should not walk on this entity - EFL_NO_DISSOLVE = (1<<27), // These guys shouldn't dissolve - EFL_NO_MEGAPHYSCANNON_RAGDOLL = (1<<28), // Mega physcannon can't ragdoll these guys. - EFL_NO_WATER_VELOCITY_CHANGE = (1<<29), // Don't adjust this entity's velocity when transitioning into water - EFL_NO_PHYSCANNON_INTERACTION = (1<<30), // Physcannon can't pick these up or punt them - EFL_NO_DAMAGE_FORCES = (1<<31), // Doesn't accept forces from physics damage -}; - -//----------------------------------------------------------------------------- -// EFFECTS -//----------------------------------------------------------------------------- -const int FX_BLOODSPRAY_DROPS = 0x01; -const int FX_BLOODSPRAY_GORE = 0x02; -const int FX_BLOODSPRAY_CLOUD = 0x04; -const int FX_BLOODSPRAY_ALL = 0xFF; - -//----------------------------------------------------------------------------- -#define MAX_SCREEN_OVERLAYS 10 - -// These are the types of data that hang off of CBaseEntities and the flag bits used to mark their presence -enum -{ - GROUNDLINK = 0, - TOUCHLINK, - STEPSIMULATION, - MODELWIDTHSCALE, - POSITIONWATCHER, - PHYSICSPUSHLIST, - VPHYSICSUPDATEAI, - VPHYSICSWATCHER, - - // Must be last and <= 32 - NUM_DATAOBJECT_TYPES, -}; - -class CBaseEntity; - -//----------------------------------------------------------------------------- -// Bullet firing information -//----------------------------------------------------------------------------- -class CBaseEntity; - -enum FireBulletsFlags_t -{ - FIRE_BULLETS_FIRST_SHOT_ACCURATE = 0x1, // Pop the first shot with perfect accuracy - FIRE_BULLETS_DONT_HIT_UNDERWATER = 0x2, // If the shot hits its target underwater, don't damage it - FIRE_BULLETS_ALLOW_WATER_SURFACE_IMPACTS = 0x4, // If the shot hits water surface, still call DoImpactEffect - FIRE_BULLETS_TEMPORARY_DANGER_SOUND = 0x8, // Danger sounds added from this impact can be stomped immediately if another is queued -}; - - -struct FireBulletsInfo_t -{ - FireBulletsInfo_t() - { - m_iShots = 1; - m_vecSpread.Init( 0, 0, 0 ); - m_flDistance = 8192; - m_iTracerFreq = 4; - m_iDamage = 0; - m_iPlayerDamage = 0; - m_pAttacker = NULL; - m_nFlags = 0; - m_pAdditionalIgnoreEnt = NULL; - m_flDamageForceScale = 1.0f; - -#ifdef _DEBUG - m_iAmmoType = -1; - m_vecSrc.Init( VEC_T_NAN, VEC_T_NAN, VEC_T_NAN ); - m_vecDirShooting.Init( VEC_T_NAN, VEC_T_NAN, VEC_T_NAN ); -#endif - m_bPrimaryAttack = true; - } - - FireBulletsInfo_t( int nShots, const Vector &vecSrc, const Vector &vecDir, const Vector &vecSpread, float flDistance, int nAmmoType, bool bPrimaryAttack = true ) - { - m_iShots = nShots; - m_vecSrc = vecSrc; - m_vecDirShooting = vecDir; - m_vecSpread = vecSpread; - m_flDistance = flDistance; - m_iAmmoType = nAmmoType; - m_iTracerFreq = 4; - m_iDamage = 0; - m_iPlayerDamage = 0; - m_pAttacker = NULL; - m_nFlags = 0; - m_pAdditionalIgnoreEnt = NULL; - m_flDamageForceScale = 1.0f; - m_bPrimaryAttack = bPrimaryAttack; - } - - int m_iShots; - Vector m_vecSrc; - Vector m_vecDirShooting; - Vector m_vecSpread; - float m_flDistance; - int m_iAmmoType; - int m_iTracerFreq; - int m_iDamage; - int m_iPlayerDamage; // Damage to be used instead of m_iDamage if we hit a player - int m_nFlags; // See FireBulletsFlags_t - float m_flDamageForceScale; - CBaseEntity *m_pAttacker; - CBaseEntity *m_pAdditionalIgnoreEnt; - bool m_bPrimaryAttack; -}; - -//----------------------------------------------------------------------------- -// Purpose: Data for making the MOVETYPE_STEP entities appear to simulate every frame -// We precompute the simulation and then meter it out each tick during networking of the -// entities origin and orientation. Uses a bit more bandwidth, but it solves the NPCs interacting -// with elevators/lifts bugs. -//----------------------------------------------------------------------------- -struct StepSimulationStep -{ - int nTickCount; - Vector vecOrigin; - Quaternion qRotation; -}; - -struct StepSimulationData -{ - // Are we using the Step Simulation Data - bool m_bOriginActive; - bool m_bAnglesActive; - - // This is the pre-pre-Think position, orientation (Quaternion) and tick count - StepSimulationStep m_Previous2; - - // This is the pre-Think position, orientation (Quaternion) and tick count - StepSimulationStep m_Previous; - - // This is a potential mid-think position, orientation (Quaternion) and tick count - // Used to mark motion discontinuities that happen between thinks - StepSimulationStep m_Discontinuity; - - // This is the goal or post-Think position and orientation (and Quaternion for blending) and next think time tick - StepSimulationStep m_Next; - QAngle m_angNextRotation; - - // This variable is used so that we only compute networked origin/angles once per tick - int m_nLastProcessTickCount; - // The computed/interpolated network origin/angles to use - Vector m_vecNetworkOrigin; - QAngle m_angNetworkAngles; -}; - -//----------------------------------------------------------------------------- -// Purpose: Simple state tracking for changing model sideways shrinkage during barnacle swallow -//----------------------------------------------------------------------------- -struct ModelWidthScale -{ - float m_flModelWidthScaleStart; - float m_flModelWidthScaleGoal; - float m_flModelWidthScaleFinishTime; - float m_flModelWidthScaleStartTime; -}; - -#include "soundflags.h" - -struct CSoundParameters; -typedef short HSOUNDSCRIPTHANDLE; -//----------------------------------------------------------------------------- -// Purpose: Aggregates and sets default parameters for EmitSound function calls -//----------------------------------------------------------------------------- -struct EmitSound_t -{ - EmitSound_t() : - m_nChannel( 0 ), - m_pSoundName( 0 ), - m_flVolume( VOL_NORM ), - m_SoundLevel( SNDLVL_NONE ), - m_nFlags( 0 ), - m_nPitch( PITCH_NORM ), - m_nSpecialDSP( 0 ), - m_pOrigin( 0 ), - m_flSoundTime( 0.0f ), - m_pflSoundDuration( 0 ), - m_bEmitCloseCaption( true ), - m_bWarnOnMissingCloseCaption( false ), - m_bWarnOnDirectWaveReference( false ), - m_nSpeakerEntity( -1 ), - m_UtlVecSoundOrigin(), - m_hSoundScriptHandle( -1 ) - { - } - - EmitSound_t( const CSoundParameters &src ); - - int m_nChannel; - char const *m_pSoundName; - float m_flVolume; - soundlevel_t m_SoundLevel; - int m_nFlags; - int m_nPitch; - int m_nSpecialDSP; - const Vector *m_pOrigin; - float m_flSoundTime; ///< NOT DURATION, but rather, some absolute time in the future until which this sound should be delayed - float *m_pflSoundDuration; - bool m_bEmitCloseCaption; - bool m_bWarnOnMissingCloseCaption; - bool m_bWarnOnDirectWaveReference; - int m_nSpeakerEntity; - mutable CUtlVector< Vector > m_UtlVecSoundOrigin; ///< Actual sound origin(s) (can be multiple if sound routed through speaker entity(ies) ) - mutable HSOUNDSCRIPTHANDLE m_hSoundScriptHandle; -}; - -#define MAX_ACTORS_IN_SCENE 16 - -//----------------------------------------------------------------------------- -// Multiplayer specific defines -//----------------------------------------------------------------------------- -#define MAX_CONTROL_POINTS 8 -#define MAX_CONTROL_POINT_GROUPS 8 - -// Maximum number of points that a control point may need owned to be cappable -#define MAX_PREVIOUS_POINTS 3 - -// The maximum number of teams the control point system knows how to deal with -#define MAX_CONTROL_POINT_TEAMS 8 - -// Maximum length of the cap layout string -#define MAX_CAPLAYOUT_LENGTH 32 - -// Maximum length of the current round printname -#define MAX_ROUND_NAME 32 - -// Maximum length of the current round name -#define MAX_ROUND_IMAGE_NAME 64 - -// Score added to the team score for a round win -#define TEAMPLAY_ROUND_WIN_SCORE 1 - -enum -{ - CP_WARN_NORMAL = 0, - CP_WARN_FINALCAP, - CP_WARN_NO_ANNOUNCEMENTS -}; - -// YWB: 3/12/2007 -// Changing the following #define for Prediction Error checking (See gamemovement.cpp for overview) will to 1 or 2 enables the system, 0 turns it off -// Level 1 enables it, but doesn't force "full precision" networking, so you can still get lots of errors in position/velocity/etc. -// Level 2 enables it but also forces origins/angles to be sent full precision, so other fields can be error / tolerance checked -// NOTE: This stuff only works on a listen server since it punches a hole from the client .dll to server .dll!!! -#define PREDICTION_ERROR_CHECK_LEVEL 0 - -//----------------------------------------------------------------------------- -// Round timer states -//----------------------------------------------------------------------------- -enum -{ - RT_STATE_SETUP, // Timer is in setup mode - RT_STATE_NORMAL, // Timer is in normal mode -}; - -enum -{ - SIMULATION_TIME_WINDOW_BITS = 8, -}; - -//----------------------------------------------------------------------------- -// Commentary Mode -//----------------------------------------------------------------------------- -#if defined(TF_DLL) || defined(TF_CLIENT_DLL) -#define GAME_HAS_NO_USE_KEY - -#if defined( SPROP_COORD ) -#undef SPROP_COORD -#endif - -#define SPROP_COORD SPROP_COORD_MP - -#endif - -// The player's method of starting / stopping commentary -#ifdef GAME_HAS_NO_USE_KEY -#define COMMENTARY_BUTTONS (IN_ATTACK | IN_ATTACK2 | IN_USE) -#else -#define COMMENTARY_BUTTONS (IN_USE) -#endif - -#endif // SHAREDDEFS_H diff --git a/game/shared/sheetsimulator.cpp b/game/shared/sheetsimulator.cpp deleted file mode 100644 index 4feacabc0..000000000 --- a/game/shared/sheetsimulator.cpp +++ /dev/null @@ -1,675 +0,0 @@ -//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: The Escort's Shield weapon effect -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#include "sheetsimulator.h" -#include "edict.h" -#include "collisionutils.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define COLLISION_PLANE_OFFSET 6.0f - -//----------------------------------------------------------------------------- -// constructor, destructor -//----------------------------------------------------------------------------- - -CSheetSimulator::CSheetSimulator( TraceLineFunc_t traceline, - TraceHullFunc_t traceHull ) : - m_pFixedPoint(0), m_ControlPoints(0), - m_TraceLine(traceline), m_TraceHull(traceHull) -{ -} - -CSheetSimulator::~CSheetSimulator() -{ - if (m_pFixedPoint) - { - delete[] m_pFixedPoint; - delete[] m_ControlPoints; - delete[] m_pCollisionPlanes; - delete[] m_pValidCollisionPlane; - } - delete[] m_Particle; -} - -//----------------------------------------------------------------------------- -// Initialization -//----------------------------------------------------------------------------- - -void CSheetSimulator::Init( int w, int h, int fixedPointCount ) -{ - m_ControlPointOffset.Init( 0, 0, 0 ); - m_HorizontalCount = w; - m_VerticalCount = h; - m_Particle = new Particle_t[w * h]; - m_FixedPointCount = fixedPointCount; - if (fixedPointCount) - { - m_pFixedPoint = new Vector[fixedPointCount]; - m_ControlPoints = new Vector[fixedPointCount]; - m_pCollisionPlanes = new cplane_t[fixedPointCount]; - m_pValidCollisionPlane = new bool[fixedPointCount]; - } - - // Initialize distances and such - m_Origin = Vector(0, 0, 0); - for ( int i = 0; i < NumParticles(); ++i ) - { - m_Particle[i].m_Mass = 1.0f; - m_Particle[i].m_Collided = false; - m_Particle[i].m_Position = Vector(0,0,0); - m_Particle[i].m_Velocity = Vector(0,0,0); - } -} - -//----------------------------------------------------------------------------- -// adds springs -//----------------------------------------------------------------------------- - -void CSheetSimulator::AddSpring( int p1, int p2, float restLength ) -{ - int spring = m_Springs.AddToTail(); - m_Springs[spring].m_Particle1 = p1; - m_Springs[spring].m_Particle2 = p2; - m_Springs[spring].m_RestLength = restLength; -} - -void CSheetSimulator::AddFixedPointSpring( int fixedPoint, int p, float restLength ) -{ - assert( fixedPoint < m_FixedPointCount ); - int spring = m_Springs.AddToTail(); - m_Springs[spring].m_Particle1 = p; - m_Springs[spring].m_Particle2 = -(fixedPoint+1); - m_Springs[spring].m_RestLength = restLength; -} - -//----------------------------------------------------------------------------- -// Gravity -//----------------------------------------------------------------------------- - -void CSheetSimulator::SetGravityConstant( float g ) -{ - m_GravityConstant = g; -} - -void CSheetSimulator::AddGravityForce( int particle ) -{ - m_Gravity.AddToTail( particle ); -} - -//----------------------------------------------------------------------------- -// spring constants.... -//----------------------------------------------------------------------------- - -void CSheetSimulator::SetPointSpringConstant( float constant ) -{ - m_PointSpringConstant = constant; -} - -void CSheetSimulator::SetFixedSpringConstant( float constant ) -{ - m_FixedSpringConstant = constant; -} - -void CSheetSimulator::SetViscousDrag( float drag ) -{ - m_ViscousDrag = drag; -} - -void CSheetSimulator::SetSpringDampConstant( float damp ) -{ - m_DampConstant = damp; -} - - -//----------------------------------------------------------------------------- -// Sets the collision group -//----------------------------------------------------------------------------- - -void CSheetSimulator::SetCollisionGroup( int group ) -{ - m_CollisionGroup = group; -} - - -//----------------------------------------------------------------------------- -// bounding box for collision -//----------------------------------------------------------------------------- - -void CSheetSimulator::SetBoundingBox( Vector& mins, Vector& maxs ) -{ - m_FrustumBoxMin = mins; - m_FrustumBoxMax = maxs; -} - -//----------------------------------------------------------------------------- -// bounding box for collision -//----------------------------------------------------------------------------- - -void CSheetSimulator::ComputeBounds( Vector& mins, Vector& maxs ) -{ - VectorCopy( m_Particle[0].m_Position, mins ); - VectorCopy( m_Particle[0].m_Position, maxs ); - - for (int i = 1; i < NumParticles(); ++i) - { - VectorMin( mins, m_Particle[i].m_Position, mins ); - VectorMax( maxs, m_Particle[i].m_Position, maxs ); - } - mins -= m_Origin; - maxs -= m_Origin; -} - -//----------------------------------------------------------------------------- -// Set the shield position -//----------------------------------------------------------------------------- - -void CSheetSimulator::SetPosition( const Vector& origin, const QAngle& angles ) -{ - // FIXME: Need a better metric for position reset - if (m_Origin.DistToSqr(origin) > 1e3) - { - for ( int i = 0; i < NumParticles(); ++i ) - { - m_Particle[i].m_Position = origin; - m_Particle[i].m_Velocity = Vector(0,0,0); - } - } - - m_Origin = origin; - m_Angles = angles; - ComputeControlPoints(); -} - -//----------------------------------------------------------------------------- -// get at the points -//----------------------------------------------------------------------------- - -int CSheetSimulator::NumHorizontal() const -{ - return m_HorizontalCount; -} - -int CSheetSimulator::NumVertical() const -{ - return m_VerticalCount; -} - -int CSheetSimulator::PointCount() const -{ - return m_HorizontalCount * m_VerticalCount; -} - -const Vector& CSheetSimulator::GetPoint( int x, int y ) const -{ - return m_Particle[y * NumHorizontal() + x].m_Position; -} - -const Vector& CSheetSimulator::GetPoint( int i ) const -{ - return m_Particle[i].m_Position; -} - -// Fixed points -Vector& CSheetSimulator::GetFixedPoint( int i ) -{ - assert( i < m_FixedPointCount ); - return m_pFixedPoint[i]; -} - -//----------------------------------------------------------------------------- -// For offseting the control points -//----------------------------------------------------------------------------- - -void CSheetSimulator::SetControlPointOffset( const Vector& offset ) -{ - VectorCopy( offset, m_ControlPointOffset ); -} - -//----------------------------------------------------------------------------- -// Compute the position of the fixed points -//----------------------------------------------------------------------------- - -void CSheetSimulator::ComputeControlPoints() -{ - //trace_t tr; - Vector forward, right, up; - AngleVectors(m_Angles, &forward, &right, &up); - - for (int i = 0; i < m_FixedPointCount; ++i) - { - VectorAdd( m_Origin, m_ControlPointOffset, m_ControlPoints[i] ); - m_ControlPoints[i] += right * m_pFixedPoint[i].x; - m_ControlPoints[i] += up * m_pFixedPoint[i].z; - m_ControlPoints[i] += forward * m_pFixedPoint[i].y; - } -} - -//----------------------------------------------------------------------------- -// Clear forces + velocities affecting each point -//----------------------------------------------------------------------------- - -void CSheetSimulator::ClearForces() -{ - int i; - for ( i = 0; i < NumParticles(); ++i) - { - m_Particle[i].m_Force = Vector(0,0,0); - } -} - -//----------------------------------------------------------------------------- -// Update the shield positions -//----------------------------------------------------------------------------- - -void CSheetSimulator::ComputeForces() -{ - - float springConstant; - int i; - for ( i = 0; i < m_Springs.Size(); ++i ) - { - // Hook's law for a damped spring: - // got two particles, a and b with positions xa and xb and velocities va and vb - // and l = xa - xb - // fa = -( ks * (|l| - r) + kd * (va - vb) dot (l) / |l|) * l/|l| - - Vector dx, dv, force; - if (m_Springs[i].m_Particle2 < 0) - { - // Case where we're connected to a control point - dx = m_Particle[m_Springs[i].m_Particle1].m_Position - - m_ControlPoints[- m_Springs[i].m_Particle2 - 1]; - dv = m_Particle[m_Springs[i].m_Particle1].m_Velocity; - - springConstant = m_FixedSpringConstant; - } - else - { - // Case where we're connected to another part of the shield - dx = m_Particle[m_Springs[i].m_Particle1].m_Position - - m_Particle[m_Springs[i].m_Particle2].m_Position; - dv = m_Particle[m_Springs[i].m_Particle1].m_Velocity - - m_Particle[m_Springs[i].m_Particle2].m_Velocity; - - springConstant = m_PointSpringConstant; - } - - float length = dx.Length(); - if (length < 1e-6) - continue; - - dx /= length; - - float springfactor = springConstant * ( length - m_Springs[i].m_RestLength); - float dampfactor = m_DampConstant * DotProduct( dv, dx ); - force = dx * -( springfactor + dampfactor ); - - m_Particle[m_Springs[i].m_Particle1].m_Force += force; - if (m_Springs[i].m_Particle2 >= 0) - m_Particle[m_Springs[i].m_Particle2].m_Force -= force; - - assert( IsFinite( m_Particle[m_Springs[i].m_Particle1].m_Force.x ) && - IsFinite( m_Particle[m_Springs[i].m_Particle1].m_Force.y) && - IsFinite( m_Particle[m_Springs[i].m_Particle1].m_Force.z) ); - } - - // gravity term - for (i = 0; i < m_Gravity.Count(); ++i) - { - m_Particle[m_Gravity[i]].m_Force.z -= m_Particle[m_Gravity[i]].m_Mass * m_GravityConstant; - } - - // viscous drag term - for (i = 0; i < NumParticles(); ++i) - { - // Factor out bad forces for surface contact - // Do this before the drag term otherwise the drag will be too large - if ((m_Particle[i].m_CollisionPlane) >= 0) - { - const Vector& planeNormal = m_pCollisionPlanes[m_Particle[i].m_CollisionPlane].normal; - float perp = DotProduct( m_Particle[i].m_Force, planeNormal ); - if (perp < 0) - m_Particle[i].m_Force -= planeNormal * perp; - } - - Vector drag = m_Particle[i].m_Velocity * m_ViscousDrag; - m_Particle[i].m_Force -= drag; - } -} - - -//----------------------------------------------------------------------------- -// Used for testing neighbors against a particular plane -//----------------------------------------------------------------------------- -void CSheetSimulator::TestVertAgainstPlane( int vert, int plane, bool bFarTest ) -{ - if (!m_pValidCollisionPlane[plane]) - return; - - // Compute distance to the plane under consideration - cplane_t* pPlane = &m_pCollisionPlanes[plane]; - - Ray_t ray; - ray.Init( m_Origin, m_Particle[vert].m_Position ); - float t = IntersectRayWithPlane( ray, *pPlane ); - - if (!bFarTest || (t <= 1.0f)) - { - if ((t < m_Particle[vert].m_CollisionDist) && (t >= 0.0f)) - { - m_Particle[vert].m_CollisionDist = t; - m_Particle[vert].m_CollisionPlane = plane; - } - } -} - - - -//----------------------------------------------------------------------------- -// Collision detect -//----------------------------------------------------------------------------- -void CSheetSimulator::InitPosition( int i ) -{ - // Collision test... - // Check a line that goes farther out than our current point... - // This will let us check for resting contact - trace_t tr; - m_TraceHull(m_Origin, m_ControlPoints[i], m_FrustumBoxMin, m_FrustumBoxMax, - MASK_SOLID_BRUSHONLY, m_CollisionGroup, &tr ); - if ( tr.fraction - 1.0 < 0 ) - { - memcpy( &m_pCollisionPlanes[i], &tr.plane, sizeof(cplane_t) ); - m_pCollisionPlanes[i].dist += COLLISION_PLANE_OFFSET; - - // The trace endpos represents where the center of the box - // ends up being. We actually want to choose a point which is on the - // collision plane - Vector delta; - VectorSubtract( m_ControlPoints[i], m_Origin, delta ); - int maxdist = (int)VectorNormalize( delta ); - float dist = (m_pCollisionPlanes[i].dist - DotProduct( m_Origin, m_pCollisionPlanes[i].normal )) / - DotProduct( delta, m_pCollisionPlanes[i].normal ); - - if (dist > maxdist) - dist = maxdist; - - VectorMA( m_Origin, dist, delta, m_Particle[i].m_Position ); - - m_pValidCollisionPlane[i] = true; - } - else if (tr.allsolid || tr.startsolid) - { - m_pValidCollisionPlane[i] = true; - VectorSubtract( m_Origin, m_ControlPoints[i], m_pCollisionPlanes[i].normal ); - VectorNormalize( m_pCollisionPlanes[i].normal ); - m_pCollisionPlanes[i].dist = DotProduct( m_Origin, m_pCollisionPlanes[i].normal ) - COLLISION_PLANE_OFFSET; - m_pCollisionPlanes[i].type = 3; - } - else - { - VectorCopy( m_ControlPoints[i], m_Particle[i].m_Position ); - m_pValidCollisionPlane[i] = false; - } -} - -//----------------------------------------------------------------------------- -// Collision detect -//----------------------------------------------------------------------------- -void CSheetSimulator::DetectCollision( int i, float flPlaneOffset ) -{ - // Collision test... - // Check a line that goes farther out than our current point... - // This will let us check for resting contact -// Vector endpt = m_Particle[i].m_Position; - - trace_t tr; - m_TraceHull(m_Origin, m_ControlPoints[i], m_FrustumBoxMin, m_FrustumBoxMax, - MASK_SOLID_BRUSHONLY, m_CollisionGroup, &tr ); - if ( tr.fraction - 1.0 < 0 ) - { - m_pValidCollisionPlane[i] = true; - memcpy( &m_pCollisionPlanes[i], &tr.plane, sizeof(cplane_t) ); - m_pCollisionPlanes[i].dist += flPlaneOffset; - } - else if (tr.allsolid || tr.startsolid) - { - m_pValidCollisionPlane[i] = true; - VectorSubtract( m_Origin, m_ControlPoints[i], m_pCollisionPlanes[i].normal ); - VectorNormalize( m_pCollisionPlanes[i].normal ); - m_pCollisionPlanes[i].dist = DotProduct( m_Origin, m_pCollisionPlanes[i].normal ) - flPlaneOffset; - m_pCollisionPlanes[i].type = 3; - } - else - { - m_pValidCollisionPlane[i] = false; - } -} - - -//----------------------------------------------------------------------------- -// Collision plane fixup -//----------------------------------------------------------------------------- -void CSheetSimulator::DetermineBestCollisionPlane( bool bFarTest ) -{ - // Check neighbors for violation of collision plane constraints - for ( int i = 0; i < NumVertical(); ++i) - { - for ( int j = 0; j < NumHorizontal(); ++j) - { - // Here's the particle we're making springs for - int idx = i * NumHorizontal() + j; - - // Now that we've seen all collisions, find the best collision plane - // to use (look at myself and all neighbors). The best plane - // is the one that comes closest to the origin. - m_Particle[idx].m_CollisionDist = FLT_MAX; - m_Particle[idx].m_CollisionPlane = -1; - TestVertAgainstPlane( idx, idx, bFarTest ); - if (j > 0) - { - TestVertAgainstPlane( idx, idx-1, bFarTest ); - } - if (j < NumHorizontal() - 1) - { - TestVertAgainstPlane( idx, idx+1, bFarTest ); - } - if (i > 0) - TestVertAgainstPlane( idx, idx-NumHorizontal(), bFarTest ); - if (i < NumVertical() - 1) - TestVertAgainstPlane( idx, idx+NumHorizontal(), bFarTest ); - } - } -} - -//----------------------------------------------------------------------------- -// satify collision constraints -//----------------------------------------------------------------------------- - -void CSheetSimulator::SatisfyCollisionConstraints() -{ - // Eliminate velocity perp to a collision plane - for ( int i = 0; i < NumParticles(); ++i ) - { - // The actual collision plane - if (m_Particle[i].m_CollisionPlane >= 0) - { - cplane_t* pPlane = &m_pCollisionPlanes[m_Particle[i].m_CollisionPlane]; - - // Fix up position so it lies on the plane - Vector delta = m_Particle[i].m_Position - m_Origin; - m_Particle[i].m_Position = m_Origin + delta * m_Particle[i].m_CollisionDist; - - float perp = DotProduct( m_Particle[i].m_Velocity, pPlane->normal ); - if (perp < 0) - m_Particle[i].m_Velocity -= pPlane->normal * perp; - } - } -} - -//----------------------------------------------------------------------------- -// integrator -//----------------------------------------------------------------------------- - -void CSheetSimulator::EulerStep( float dt ) -{ - ClearForces(); - ComputeForces(); - - // Update positions and velocities - for ( int i = 0; i < NumParticles(); ++i) - { - m_Particle[i].m_Position += m_Particle[i].m_Velocity * dt; - m_Particle[i].m_Velocity += m_Particle[i].m_Force * dt / m_Particle[i].m_Mass; - - assert( IsFinite( m_Particle[i].m_Velocity.x ) && - IsFinite( m_Particle[i].m_Velocity.y) && - IsFinite( m_Particle[i].m_Velocity.z) ); - - // clamp for stability - float lensq = m_Particle[i].m_Velocity.LengthSqr(); - if (lensq > 1e6) - { - m_Particle[i].m_Velocity *= 1e3 / sqrt(lensq); - } - } - SatisfyCollisionConstraints(); -} - -//----------------------------------------------------------------------------- -// Update the shield position: -//----------------------------------------------------------------------------- - -void CSheetSimulator::Simulate( float dt ) -{ - // Initialize positions if necessary - EulerStep(dt); -} - - -void CSheetSimulator::Simulate( float dt, int steps ) -{ - ComputeControlPoints(); - - // Initialize positions if necessary - dt /= steps; - for (int i = 0; i < steps; ++i) - { - // Each step, we want to re-select the best collision planes to constrain - // the movement by - DetermineBestCollisionPlane(); - - EulerStep(dt); - } -} - - -#define CLAMP_DIST 6.0 - -void CSheetSimulator::ClampPointsToCollisionPlanes() -{ - // Find collision planes to clamp to - DetermineBestCollisionPlane( false ); - - // Eliminate velocity perp to a collision plane - for ( int i = 0; i < NumParticles(); ++i ) - { - // The actual collision plane - if (m_Particle[i].m_CollisionPlane >= 0) - { - cplane_t* pPlane = &m_pCollisionPlanes[m_Particle[i].m_CollisionPlane]; - - // Make sure we have a close enough perpendicular distance to the plane... - float flPerpDist = fabs ( DotProduct( m_Particle[i].m_Position, pPlane->normal ) - pPlane->dist ); - if (flPerpDist >= CLAMP_DIST) - continue; - - // Drop it along the perp - VectorMA( m_Particle[i].m_Position, -flPerpDist, pPlane->normal, m_Particle[i].m_Position ); - } - } -} - - -//----------------------------------------------------------------------------- -// Class to help dealing with the iterative computation -//----------------------------------------------------------------------------- -CIterativeSheetSimulator::CIterativeSheetSimulator( TraceLineFunc_t traceline, TraceHullFunc_t traceHull ) : - CSheetSimulator( traceline, traceHull ), - m_SimulationSteps(0) -{ -} - -void CIterativeSheetSimulator::BeginSimulation( float dt, int steps, int substeps, int collisionCount ) -{ - m_CurrentCollisionPt = 0; - m_TimeStep = dt; - m_SimulationSteps = steps; - m_TotalSteps = steps; - m_SubSteps = substeps; - m_InitialPass = true; - m_CollisionCount = collisionCount; -} - -bool CIterativeSheetSimulator::Think( ) -{ - assert( m_SimulationSteps >= 0 ); - - // Need to iteratively perform collision detection - if (m_CurrentCollisionPt >= 0) - { - DetectCollisions(); - return false; - } - else - { - // Simulate it a bunch of times - Simulate(m_TimeStep, (int)m_SubSteps); - - // Reset the collision point for collision detect - m_CurrentCollisionPt = 0; - --m_SimulationSteps; - - if ( m_SimulationSteps == 0 ) - { - ClampPointsToCollisionPlanes(); - } - - return true; - } -} - -// Iterative collision detection -void CIterativeSheetSimulator::DetectCollisions( void ) -{ - for ( int i = 0; i < m_CollisionCount; ++i ) - { - if (m_InitialPass) - { - InitPosition( m_CurrentCollisionPt ); - } - else - { - float flOffset = COLLISION_PLANE_OFFSET * ( (float)(m_SimulationSteps - 1) / (float)(m_TotalSteps - 1) ); - DetectCollision( m_CurrentCollisionPt, flOffset ); - } - - if (++m_CurrentCollisionPt >= NumParticles()) - { - m_CurrentCollisionPt = -1; - m_InitialPass = false; - break; - } - } -} diff --git a/game/shared/sheetsimulator.h b/game/shared/sheetsimulator.h deleted file mode 100644 index c19e75c3b..000000000 --- a/game/shared/sheetsimulator.h +++ /dev/null @@ -1,213 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SHEETSIMULATOR_H -#define SHEETSIMULATOR_H -#ifdef _WIN32 -#pragma once -#endif - -#include "mathlib/mathlib.h" -#include "mathlib/vector.h" -#include "utlvector.h" - - -// Uncomment this for client-side simulation -//#define CLIENT_SIDE_SIMULATION 1 - -//----------------------------------------------------------------------------- -// Simulates a sheet -//----------------------------------------------------------------------------- - -class CGameTrace; -typedef CGameTrace trace_t; -//struct trace_t; -typedef void (*TraceLineFunc_t)(const Vector &vecStart, const Vector &vecEnd, - unsigned int mask, int collisionGroup, trace_t *ptr); -typedef void (*TraceHullFunc_t)(const Vector &vecStart, const Vector &vecEnd, - const Vector &hullMin, const Vector &hullMax, - unsigned int mask, int collisionGroup, trace_t *ptr); - - -class CSheetSimulator -{ -public: - CSheetSimulator( TraceLineFunc_t traceline, TraceHullFunc_t traceHull ); - ~CSheetSimulator(); - - void Init( int w, int h, int fixedPointCount ); - - // orientation - void SetPosition( const Vector& origin, const QAngle& angles ); - - // Makes a spring - void AddSpring( int p1, int p2, float restLength ); - void AddFixedPointSpring( int fixedPoint, int p, float restLength ); - - // spring constants.... - void SetPointSpringConstant( float constant ); - void SetFixedSpringConstant( float constant ); - - // Used for both kinds of springs - void SetSpringDampConstant( float damp ); - void SetViscousDrag( float drag ); - - // Sets the collision group - void SetCollisionGroup( int group ); - - // Sets the bounding box used for collision vs world - void SetBoundingBox( Vector& mins, Vector& maxs ); - - // Computes the bounding box - void ComputeBounds( Vector& mins, Vector& maxs ); - - // simulation - void Simulate( float dt ); - void Simulate( float dt, int steps ); - - // get at the points - int NumHorizontal() const; - int NumVertical() const; - int PointCount() const; - - // Fixed points - Vector& GetFixedPoint( int i ); - - // Point masses - const Vector& GetPoint( int x, int y ) const; - const Vector& GetPoint( int i ) const; - - // For iterative collision detection - void DetectCollision( int i, float flOffset ); - void InitPosition( int i ); - - // For offseting the control points - void SetControlPointOffset( const Vector& offset ); - - // Gravity - void SetGravityConstant( float g ); - void AddGravityForce( int particle ); - -protected: - struct Particle_t - { - float m_Mass; - Vector m_Position; - Vector m_Velocity; - Vector m_Force; - int m_Collided; - int m_CollisionPlane; - float m_CollisionDist; - }; - - struct Spring_t - { - int m_Particle1; - int m_Particle2; - float m_RestLength; - }; - - inline int NumParticles() const - { - return m_HorizontalCount * m_VerticalCount; - } - - // simulator - void EulerStep( float dt ); - void ComputeControlPoints(); - void ClearForces(); - void ComputeForces(); - void TestVertAgainstPlane( int vert, int plane, bool bFarTest = true ); - void SatisfyCollisionConstraints(); - void DetermineBestCollisionPlane( bool bFarTest = true ); - void ClampPointsToCollisionPlanes(); - - // How many particles horiz + vert? - int m_HorizontalCount; - int m_VerticalCount; - - // The particles - Particle_t* m_Particle; - - // Output position after simulation - Vector* m_OutputPosition; - - // fixed points - int m_FixedPointCount; - Vector* m_pFixedPoint; - Vector* m_ControlPoints; - - CUtlVector m_Springs; - CUtlVector m_Gravity; - - // raycasting methods - TraceLineFunc_t m_TraceLine; - TraceHullFunc_t m_TraceHull; - - // Spring constants - float m_FixedSpringConstant; - float m_PointSpringConstant; - float m_DampConstant; - float m_ViscousDrag; - - // Collision group - int m_CollisionGroup; - - // position + orientation - Vector m_Origin; - QAngle m_Angles; - - // collision box - Vector m_FrustumBoxMin; - Vector m_FrustumBoxMax; - - // Collision planes - cplane_t* m_pCollisionPlanes; - bool* m_pValidCollisionPlane; - - // Control point offset - Vector m_ControlPointOffset; - - // Gravity - float m_GravityConstant; -}; - - -//----------------------------------------------------------------------------- -// Class to help dealing with the iterative computation -//----------------------------------------------------------------------------- - -class CIterativeSheetSimulator : public CSheetSimulator -{ -public: - CIterativeSheetSimulator( TraceLineFunc_t traceline, TraceHullFunc_t traceHull ); - - void BeginSimulation( float dt, int steps, int substeps, int collisionCount ); - - // Returns true if it just did a simulation step - bool Think( ); - bool IsDone() const { return m_SimulationSteps == 0; } - - int StepsRemaining( ) const { return m_SimulationSteps; } - -private: - CIterativeSheetSimulator( const CIterativeSheetSimulator & ); // not defined, not accessible - - // Iterative collision detection - void DetectCollisions( void ); - - float m_TimeStep; - float m_SubSteps; - char m_TotalSteps; - char m_SimulationSteps; - char m_CollisionCount; - char m_CurrentCollisionPt; - bool m_InitialPass; -}; - - -#endif // TF_SHIELD_SHARED_H diff --git a/game/shared/shot_manipulator.h b/game/shared/shot_manipulator.h deleted file mode 100644 index 0f804d1f8..000000000 --- a/game/shared/shot_manipulator.h +++ /dev/null @@ -1,95 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef SHOT_MANIPULATOR_H -#define SHOT_MANIPULATOR_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "mathlib/vector.h" - - -extern ConVar ai_shot_bias_min; -extern ConVar ai_shot_bias_max; - - -//--------------------------------------------------------- -// Caches off a shot direction and allows you to perform -// various operations on it without having to recalculate -// vecRight and vecUp each time. -//--------------------------------------------------------- -class CShotManipulator -{ -public: - CShotManipulator( const Vector &vecForward ) - { - SetShootDir( vecForward ); - }; - - void SetShootDir( const Vector &vecForward ) - { - m_vecShotDirection = vecForward; - VectorVectors( m_vecShotDirection, m_vecRight, m_vecUp ); - } - - const Vector &ApplySpread( const Vector &vecSpread, float bias = 1.0 ); - - const Vector &GetShotDirection() { return m_vecShotDirection; } - const Vector &GetResult() { return m_vecResult; } - const Vector &GetRightVector() { return m_vecRight; } - const Vector &GetUpVector() { return m_vecUp;} - -private: - Vector m_vecShotDirection; - Vector m_vecRight; - Vector m_vecUp; - Vector m_vecResult; -}; - -//--------------------------------------------------------- -// Take a vector (direction) and another vector (spread) -// and modify the direction to point somewhere within the -// spread. This used to live inside FireBullets. -//--------------------------------------------------------- -inline const Vector &CShotManipulator::ApplySpread( const Vector &vecSpread, float bias ) -{ - // get circular gaussian spread - float x, y, z; - - if ( bias > 1.0 ) - bias = 1.0; - else if ( bias < 0.0 ) - bias = 0.0; - - float shotBiasMin = ai_shot_bias_min.GetFloat(); - float shotBiasMax = ai_shot_bias_max.GetFloat(); - - // 1.0 gaussian, 0.0 is flat, -1.0 is inverse gaussian - float shotBias = ( ( shotBiasMax - shotBiasMin ) * bias ) + shotBiasMin; - - float flatness = ( fabsf(shotBias) * 0.5 ); - - do - { - x = random->RandomFloat(-1,1) * flatness + random->RandomFloat(-1,1) * (1 - flatness); - y = random->RandomFloat(-1,1) * flatness + random->RandomFloat(-1,1) * (1 - flatness); - if ( shotBias < 0 ) - { - x = ( x >= 0 ) ? 1.0 - x : -1.0 - x; - y = ( y >= 0 ) ? 1.0 - y : -1.0 - y; - } - z = x*x+y*y; - } while (z > 1); - - m_vecResult = m_vecShotDirection + x * vecSpread.x * m_vecRight + y * vecSpread.y * m_vecUp; - - return m_vecResult; -} - - -#endif // SHOT_MANIPULATOR_H diff --git a/game/shared/simtimer.cpp b/game/shared/simtimer.cpp deleted file mode 100644 index 02cc22af2..000000000 --- a/game/shared/simtimer.cpp +++ /dev/null @@ -1,41 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "simtimer.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- - -BEGIN_SIMPLE_DATADESC( CSimpleSimTimer ) - DEFINE_FIELD( m_next, FIELD_TIME ), -END_DATADESC() - -BEGIN_SIMPLE_DATADESC_( CSimTimer, CSimpleSimTimer ) - DEFINE_FIELD( m_interval, FIELD_FLOAT ), -END_DATADESC() - -BEGIN_SIMPLE_DATADESC_( CRandSimTimer, CSimpleSimTimer ) - DEFINE_FIELD( m_minInterval, FIELD_FLOAT ), - DEFINE_FIELD( m_maxInterval, FIELD_FLOAT ), -END_DATADESC() - -BEGIN_SIMPLE_DATADESC_( CStopwatchBase, CSimpleSimTimer ) - DEFINE_FIELD( m_fIsRunning, FIELD_BOOLEAN ), -END_DATADESC() - -BEGIN_SIMPLE_DATADESC_( CStopwatch, CStopwatchBase ) - DEFINE_FIELD( m_interval, FIELD_FLOAT ), -END_DATADESC() - -BEGIN_SIMPLE_DATADESC_( CRandStopwatch, CStopwatchBase ) - DEFINE_FIELD( m_minInterval, FIELD_FLOAT ), - DEFINE_FIELD( m_maxInterval, FIELD_FLOAT ), -END_DATADESC() - -//----------------------------------------------------------------------------- diff --git a/game/shared/simtimer.h b/game/shared/simtimer.h deleted file mode 100644 index b1549f335..000000000 --- a/game/shared/simtimer.h +++ /dev/null @@ -1,346 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SIMTIMER_H -#define SIMTIMER_H - -#if defined( _WIN32 ) -#pragma once -#endif - -#define ST_EPS 0.001 - -#define DEFINE_SIMTIMER( type, name ) DEFINE_EMBEDDED( type, name ) - -//----------------------------------------------------------------------------- - -class CSimpleSimTimer -{ -public: - CSimpleSimTimer() - : m_next( -1 ) - { - } - - void Force() - { - m_next = -1; - } - - bool Expired() const - { - return ( gpGlobals->curtime - m_next > -ST_EPS ); - } - - float Delay( float delayTime ) - { - return (m_next += delayTime); - } - - float GetNext() const - { - return m_next; - } - - void Set( float interval ) - { - m_next = gpGlobals->curtime + interval; - } - - void Set( float minInterval, float maxInterval ) - { - if ( maxInterval > 0.0 ) - m_next = gpGlobals->curtime + random->RandomFloat( minInterval, maxInterval ); - else - m_next = gpGlobals->curtime + minInterval; - } - - float GetRemaining() const - { - float result = m_next - gpGlobals->curtime; - if (result < 0 ) - return 0; - return result; - } - - DECLARE_SIMPLE_DATADESC(); - -protected: - float m_next; -}; - -//----------------------------------------------------------------------------- - -class CSimTimer : public CSimpleSimTimer -{ -public: - CSimTimer( float interval = 0.0, bool startExpired = true ) - { - Set( interval, startExpired ); - } - - void Set( float interval, bool startExpired = true ) - { - m_interval = interval; - m_next = (startExpired) ? -1.0 : gpGlobals->curtime + m_interval; - } - - void Reset( float interval = -1.0 ) - { - if ( interval == -1.0 ) - { - m_next = gpGlobals->curtime + m_interval; - } - else - { - m_next = gpGlobals->curtime + interval; - } - } - - float GetInterval() const - { - return m_interval; - } - - DECLARE_SIMPLE_DATADESC(); - -private: - float m_interval; -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -class CRandSimTimer : public CSimpleSimTimer -{ -public: - CRandSimTimer( float minInterval = 0.0, float maxInterval = 0.0, bool startExpired = true ) - { - Set( minInterval, maxInterval, startExpired ); - } - - void Set( float minInterval, float maxInterval = 0.0, bool startExpired = true ) - { - m_minInterval = minInterval; - m_maxInterval = maxInterval; - - if (startExpired) - { - m_next = -1; - } - else - { - if ( m_maxInterval == 0 ) - m_next = gpGlobals->curtime + m_minInterval; - else - m_next = gpGlobals->curtime + random->RandomFloat( m_minInterval, m_maxInterval ); - } - } - - void Reset() - { - if ( m_maxInterval == 0 ) - m_next = gpGlobals->curtime + m_minInterval; - else - m_next = gpGlobals->curtime + random->RandomFloat( m_minInterval, m_maxInterval ); - } - - float GetMinInterval() const - { - return m_minInterval; - } - - float GetMaxInterval() const - { - return m_maxInterval; - } - - DECLARE_SIMPLE_DATADESC(); - -private: - float m_minInterval; - float m_maxInterval; -}; - -//----------------------------------------------------------------------------- - -class CStopwatchBase : public CSimpleSimTimer -{ -public: - CStopwatchBase() - { - m_fIsRunning = false; - } - - bool IsRunning() const - { - return m_fIsRunning; - } - - void Stop() - { - m_fIsRunning = false; - } - - bool Expired() const - { - return ( m_fIsRunning && CSimpleSimTimer::Expired() ); - } - - DECLARE_SIMPLE_DATADESC(); - -protected: - bool m_fIsRunning; - -}; - -//------------------------------------- -class CSimpleStopwatch : public CStopwatchBase -{ -public: - void Start( float minCountdown, float maxCountdown = 0.0 ) - { - m_fIsRunning = true; - CSimpleSimTimer::Set( minCountdown, maxCountdown ); - } - - void Stop() - { - m_fIsRunning = false; - } - - bool Expired() const - { - return ( m_fIsRunning && CSimpleSimTimer::Expired() ); - } -}; -//------------------------------------- - -class CStopwatch : public CStopwatchBase -{ -public: - CStopwatch ( float interval = 0.0 ) - { - Set( interval ); - } - - void Set( float interval ) - { - m_interval = interval; - } - - void Start( float intervalOverride ) - { - m_fIsRunning = true; - m_next = gpGlobals->curtime + intervalOverride; - } - - void Start() - { - Start( m_interval ); - } - - float GetInterval() const - { - return m_interval; - } - - DECLARE_SIMPLE_DATADESC(); - -private: - float m_interval; -}; - -//------------------------------------- - -class CRandStopwatch : public CStopwatchBase -{ -public: - CRandStopwatch( float minInterval = 0.0, float maxInterval = 0.0 ) - { - Set( minInterval, maxInterval ); - } - - void Set( float minInterval, float maxInterval = 0.0 ) - { - m_minInterval = minInterval; - m_maxInterval = maxInterval; - } - - void Start( float minOverride, float maxOverride = 0.0 ) - { - m_fIsRunning = true; - if ( maxOverride == 0 ) - m_next = gpGlobals->curtime + minOverride; - else - m_next = gpGlobals->curtime + random->RandomFloat( minOverride, maxOverride ); - } - - void Start() - { - Start( m_minInterval, m_maxInterval ); - } - - float GetInterval() const - { - return m_minInterval; - } - - float GetMinInterval() const - { - return m_minInterval; - } - - float GetMaxInterval() const - { - return m_maxInterval; - } - - DECLARE_SIMPLE_DATADESC(); - -private: - float m_minInterval; - float m_maxInterval; -}; - -//----------------------------------------------------------------------------- - -class CThinkOnceSemaphore -{ -public: - CThinkOnceSemaphore() - : m_lastTime( -1 ) - { - } - - bool EnterThink() - { - if ( m_lastTime == gpGlobals->curtime ) - return false; - m_lastTime = gpGlobals->curtime; - return true; - } - - bool DidThink() const - { - return ( gpGlobals->curtime == m_lastTime ); - - } - - void SetDidThink() - { - m_lastTime = gpGlobals->curtime; - } - -private: - float m_lastTime; -}; - -//----------------------------------------------------------------------------- - -#endif // SIMTIMER_H diff --git a/game/shared/singleplay_gamerules.cpp b/game/shared/singleplay_gamerules.cpp deleted file mode 100644 index 9ffb25ab3..000000000 --- a/game/shared/singleplay_gamerules.cpp +++ /dev/null @@ -1,500 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "singleplay_gamerules.h" - -#ifdef CLIENT_DLL - -#else - - #include "player.h" - #include "basecombatweapon.h" - #include "gamerules.h" - #include "game.h" - #include "items.h" - -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - - -//========================================================= -//========================================================= -bool CSingleplayRules::IsMultiplayer( void ) -{ - return false; -} - -// Needed during the conversion, but once DMG_* types have been fixed, this isn't used anymore. -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CSingleplayRules::Damage_GetTimeBased( void ) -{ - int iDamage = ( DMG_PARALYZE | DMG_NERVEGAS | DMG_POISON | DMG_RADIATION | DMG_DROWNRECOVER | DMG_ACID | DMG_SLOWBURN ); - return iDamage; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CSingleplayRules::Damage_GetShouldGibCorpse( void ) -{ - int iDamage = ( DMG_CRUSH | DMG_FALL | DMG_BLAST | DMG_SONIC | DMG_CLUB ); - return iDamage; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CSingleplayRules::Damage_GetShowOnHud( void ) -{ - int iDamage = ( DMG_POISON | DMG_ACID | DMG_DROWN | DMG_BURN | DMG_SLOWBURN | DMG_NERVEGAS | DMG_RADIATION | DMG_SHOCK ); - return iDamage; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CSingleplayRules::Damage_GetNoPhysicsForce( void ) -{ - int iTimeBasedDamage = Damage_GetTimeBased(); - int iDamage = ( DMG_FALL | DMG_BURN | DMG_PLASMA | DMG_DROWN | iTimeBasedDamage | DMG_CRUSH | DMG_PHYSGUN | DMG_PREVENT_PHYSICS_FORCE ); - return iDamage; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CSingleplayRules::Damage_GetShouldNotBleed( void ) -{ - int iDamage = ( DMG_POISON | DMG_ACID ); - return iDamage; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iDmgType - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CSingleplayRules::Damage_IsTimeBased( int iDmgType ) -{ - // Damage types that are time-based. - return ( ( iDmgType & ( DMG_PARALYZE | DMG_NERVEGAS | DMG_POISON | DMG_RADIATION | DMG_DROWNRECOVER | DMG_ACID | DMG_SLOWBURN ) ) != 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iDmgType - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CSingleplayRules::Damage_ShouldGibCorpse( int iDmgType ) -{ - // Damage types that gib the corpse. - return ( ( iDmgType & ( DMG_CRUSH | DMG_FALL | DMG_BLAST | DMG_SONIC | DMG_CLUB ) ) != 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iDmgType - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CSingleplayRules::Damage_ShowOnHUD( int iDmgType ) -{ - // Damage types that have client HUD art. - return ( ( iDmgType & ( DMG_POISON | DMG_ACID | DMG_DROWN | DMG_BURN | DMG_SLOWBURN | DMG_NERVEGAS | DMG_RADIATION | DMG_SHOCK ) ) != 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iDmgType - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CSingleplayRules::Damage_NoPhysicsForce( int iDmgType ) -{ - // Damage types that don't have to supply a physics force & position. - int iTimeBasedDamage = Damage_GetTimeBased(); - return ( ( iDmgType & ( DMG_FALL | DMG_BURN | DMG_PLASMA | DMG_DROWN | iTimeBasedDamage | DMG_CRUSH | DMG_PHYSGUN | DMG_PREVENT_PHYSICS_FORCE ) ) != 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iDmgType - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CSingleplayRules::Damage_ShouldNotBleed( int iDmgType ) -{ - // Damage types that don't make the player bleed. - return ( ( iDmgType & ( DMG_POISON | DMG_ACID ) ) != 0 ); -} - -#ifdef CLIENT_DLL - -#else - - extern CGameRules *g_pGameRules; - extern bool g_fGameOver; - - //========================================================= - //========================================================= - CSingleplayRules::CSingleplayRules( void ) - { - RefreshSkillData( true ); - } - - //========================================================= - //========================================================= - void CSingleplayRules::Think ( void ) - { - BaseClass::Think(); - } - - //========================================================= - //========================================================= - bool CSingleplayRules::IsDeathmatch ( void ) - { - return false; - } - - //========================================================= - //========================================================= - bool CSingleplayRules::IsCoOp( void ) - { - return false; - } - - //----------------------------------------------------------------------------- - // Purpose: Determine whether the player should switch to the weapon passed in - // Output : Returns true on success, false on failure. - //----------------------------------------------------------------------------- - bool CSingleplayRules::FShouldSwitchWeapon( CBasePlayer *pPlayer, CBaseCombatWeapon *pWeapon ) - { - //Must have ammo - if ( ( pWeapon->HasAnyAmmo() == false ) && ( pPlayer->GetAmmoCount( pWeapon->m_iPrimaryAmmoType ) <= 0 ) ) - return false; - - //Always take a loaded gun if we have nothing else - if ( pPlayer->GetActiveWeapon() == NULL ) - return true; - - // The given weapon must allow autoswitching to it from another weapon. - if ( !pWeapon->AllowsAutoSwitchTo() ) - return false; - - // The active weapon must allow autoswitching from it. - if ( !pPlayer->GetActiveWeapon()->AllowsAutoSwitchFrom() ) - return false; - - //Don't switch if our current gun doesn't want to be holstered - if ( pPlayer->GetActiveWeapon()->CanHolster() == false ) - return false; - - //Only switch if the weapon is better than what we're using - if ( ( pWeapon != pPlayer->GetActiveWeapon() ) && ( pWeapon->GetWeight() <= pPlayer->GetActiveWeapon()->GetWeight() ) ) - return false; - - return true; - } - - //----------------------------------------------------------------------------- - // Purpose: Find the next best weapon to use and return it. - //----------------------------------------------------------------------------- - CBaseCombatWeapon *CSingleplayRules::GetNextBestWeapon( CBaseCombatCharacter *pPlayer, CBaseCombatWeapon *pCurrentWeapon ) - { - if ( pCurrentWeapon && !pCurrentWeapon->AllowsAutoSwitchFrom() ) - return NULL; - - CBaseCombatWeapon *pBestWeapon = NULL; - CBaseCombatWeapon *pWeapon; - - int nBestWeight = -1; - - //Search for the best weapon to use next based on its weight - for ( int i = 0; i < pPlayer->WeaponCount(); i++ ) - { - pWeapon = pPlayer->GetWeapon(i); - - if ( pWeapon == NULL ) - continue; - - // If we have an active weapon and this weapon doesn't allow autoswitching away - // from another weapon, skip it. - if ( pCurrentWeapon && !pWeapon->AllowsAutoSwitchTo() ) - continue; - - // Must be eligible for switching to. - if (!pPlayer->Weapon_CanSwitchTo(pWeapon)) - continue; - - // Must be of higher quality. - if ( pWeapon->GetWeight() <= nBestWeight ) - continue; - - // We must have primary ammo - if ( pWeapon->UsesClipsForAmmo1() && pWeapon->Clip1() <= 0 && !pPlayer->GetAmmoCount( pWeapon->GetPrimaryAmmoType() ) ) - continue; - - // This is a better candidate than what we had. - nBestWeight = pWeapon->GetWeight(); - pBestWeapon = pWeapon; - } - - return pBestWeapon; - } - - //----------------------------------------------------------------------------- - // Purpose: - // Output : Returns true on success, false on failure. - //----------------------------------------------------------------------------- - bool CSingleplayRules::SwitchToNextBestWeapon( CBaseCombatCharacter *pPlayer, CBaseCombatWeapon *pCurrentWeapon ) - { - CBaseCombatWeapon *pWeapon = GetNextBestWeapon( pPlayer, pCurrentWeapon ); - - if ( pWeapon != NULL ) - return pPlayer->Weapon_Switch( pWeapon ); - - return false; - } - - //========================================================= - //========================================================= - bool CSingleplayRules::ClientConnected( edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen ) - { - return true; - } - - void CSingleplayRules::InitHUD( CBasePlayer *pl ) - { - } - - //========================================================= - //========================================================= - void CSingleplayRules::ClientDisconnected( edict_t *pClient ) - { - } - - //========================================================= - //========================================================= - float CSingleplayRules::FlPlayerFallDamage( CBasePlayer *pPlayer ) - { - // subtract off the speed at which a player is allowed to fall without being hurt, - // so damage will be based on speed beyond that, not the entire fall - pPlayer->m_Local.m_flFallVelocity -= PLAYER_MAX_SAFE_FALL_SPEED; - return pPlayer->m_Local.m_flFallVelocity * DAMAGE_FOR_FALL_SPEED; - } - - //========================================================= - //========================================================= - bool CSingleplayRules::AllowDamage( CBaseEntity *pVictim, const CTakeDamageInfo &info ) - { - return true; - } - - //========================================================= - //========================================================= - void CSingleplayRules::PlayerSpawn( CBasePlayer *pPlayer ) - { - // Player no longer gets all weapons to start. - // He has to pick them up now. Use impulse 101 - // to give him all weapons - } - - //========================================================= - //========================================================= - bool CSingleplayRules::AllowAutoTargetCrosshair( void ) - { - return ( IsSkillLevel(SKILL_EASY) ); - } - - //========================================================= - //========================================================= - int CSingleplayRules::GetAutoAimMode() - { - return sk_autoaim_mode.GetInt(); - } - - //========================================================= - //========================================================= - bool CSingleplayRules::FPlayerCanRespawn( CBasePlayer *pPlayer ) - { - return true; - } - - //========================================================= - //========================================================= - float CSingleplayRules::FlPlayerSpawnTime( CBasePlayer *pPlayer ) - { - return gpGlobals->curtime;//now! - } - - //========================================================= - // IPointsForKill - how many points awarded to anyone - // that kills this player? - //========================================================= - int CSingleplayRules::IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *pKilled ) - { - return 1; - } - - //========================================================= - // PlayerKilled - someone/something killed this player - //========================================================= - void CSingleplayRules::PlayerKilled( CBasePlayer *pVictim, const CTakeDamageInfo &info ) - { - } - - //========================================================= - // Deathnotice - //========================================================= - void CSingleplayRules::DeathNotice( CBasePlayer *pVictim, const CTakeDamageInfo &info ) - { - } - - //========================================================= - // FlWeaponRespawnTime - what is the time in the future - // at which this weapon may spawn? - //========================================================= - float CSingleplayRules::FlWeaponRespawnTime( CBaseCombatWeapon *pWeapon ) - { - return -1; - } - - //========================================================= - // FlWeaponRespawnTime - Returns 0 if the weapon can respawn - // now, otherwise it returns the time at which it can try - // to spawn again. - //========================================================= - float CSingleplayRules::FlWeaponTryRespawn( CBaseCombatWeapon *pWeapon ) - { - return 0; - } - - //========================================================= - // VecWeaponRespawnSpot - where should this weapon spawn? - // Some game variations may choose to randomize spawn locations - //========================================================= - Vector CSingleplayRules::VecWeaponRespawnSpot( CBaseCombatWeapon *pWeapon ) - { - return pWeapon->GetAbsOrigin(); - } - - //========================================================= - // WeaponShouldRespawn - any conditions inhibiting the - // respawning of this weapon? - //========================================================= - int CSingleplayRules::WeaponShouldRespawn( CBaseCombatWeapon *pWeapon ) - { - return GR_WEAPON_RESPAWN_NO; - } - - //========================================================= - //========================================================= - bool CSingleplayRules::CanHaveItem( CBasePlayer *pPlayer, CItem *pItem ) - { - return true; - } - - //========================================================= - //========================================================= - void CSingleplayRules::PlayerGotItem( CBasePlayer *pPlayer, CItem *pItem ) - { - } - - //========================================================= - //========================================================= - int CSingleplayRules::ItemShouldRespawn( CItem *pItem ) - { - return GR_ITEM_RESPAWN_NO; - } - - - //========================================================= - // At what time in the future may this Item respawn? - //========================================================= - float CSingleplayRules::FlItemRespawnTime( CItem *pItem ) - { - return -1; - } - - //========================================================= - // Where should this item respawn? - // Some game variations may choose to randomize spawn locations - //========================================================= - Vector CSingleplayRules::VecItemRespawnSpot( CItem *pItem ) - { - return pItem->GetAbsOrigin(); - } - - //========================================================= - // What angles should this item use to respawn? - //========================================================= - QAngle CSingleplayRules::VecItemRespawnAngles( CItem *pItem ) - { - return pItem->GetAbsAngles(); - } - - //========================================================= - //========================================================= - bool CSingleplayRules::IsAllowedToSpawn( CBaseEntity *pEntity ) - { - return true; - } - - //========================================================= - //========================================================= - void CSingleplayRules::PlayerGotAmmo( CBaseCombatCharacter *pPlayer, char *szName, int iCount ) - { - } - - //========================================================= - //========================================================= - float CSingleplayRules::FlHealthChargerRechargeTime( void ) - { - return 0;// don't recharge - } - - //========================================================= - //========================================================= - int CSingleplayRules::DeadPlayerWeapons( CBasePlayer *pPlayer ) - { - return GR_PLR_DROP_GUN_NO; - } - - //========================================================= - //========================================================= - int CSingleplayRules::DeadPlayerAmmo( CBasePlayer *pPlayer ) - { - return GR_PLR_DROP_AMMO_NO; - } - - //========================================================= - //========================================================= - int CSingleplayRules::PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget ) - { - // why would a single player in half life need this? - return GR_NOTTEAMMATE; - } - - //========================================================= - //========================================================= - bool CSingleplayRules::PlayerCanHearChat( CBasePlayer *pListener, CBasePlayer *pSpeaker ) - { - return ( PlayerRelationship( pListener, pSpeaker ) == GR_TEAMMATE ); - } - - //========================================================= - //========================================================= - bool CSingleplayRules::FAllowNPCs( void ) - { - return true; - } - -#endif - diff --git a/game/shared/singleplay_gamerules.h b/game/shared/singleplay_gamerules.h deleted file mode 100644 index b5234cadd..000000000 --- a/game/shared/singleplay_gamerules.h +++ /dev/null @@ -1,132 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef SINGLEPLAY_GAMERULES_H -#define SINGLEPLAY_GAMERULES_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "gamerules.h" - - -#ifdef CLIENT_DLL - - #define CSingleplayRules C_SingleplayRules - -#endif - - -//========================================================= -// CSingleplayRules - rules for the single player Half-Life -// game. -//========================================================= -class CSingleplayRules : public CGameRules -{ -public: - - DECLARE_CLASS( CSingleplayRules, CGameRules ); - - -// Functions to verify the single/multiplayer status of a game - virtual bool IsMultiplayer( void ); - - // Damage query implementations. - virtual bool Damage_IsTimeBased( int iDmgType ); // Damage types that are time-based. - virtual bool Damage_ShouldGibCorpse( int iDmgType ); // Damage types that gib the corpse. - virtual bool Damage_ShowOnHUD( int iDmgType ); // Damage types that have client HUD art. - virtual bool Damage_NoPhysicsForce( int iDmgType ); // Damage types that don't have to supply a physics force & position. - virtual bool Damage_ShouldNotBleed( int iDmgType ); // Damage types that don't make the player bleed. - // TEMP: These will go away once DamageTypes become enums. - virtual int Damage_GetTimeBased( void ); - virtual int Damage_GetShouldGibCorpse( void ); - virtual int Damage_GetShowOnHud( void ); - virtual int Damage_GetNoPhysicsForce( void ); - virtual int Damage_GetShouldNotBleed( void ); - -#ifdef CLIENT_DLL - -#else - - CSingleplayRules(); - virtual ~CSingleplayRules() {} - -// GR_Think - virtual void Think( void ); - virtual bool IsAllowedToSpawn( CBaseEntity *pEntity ); - virtual bool FAllowFlashlight( void ) { return TRUE; }; - - virtual bool FShouldSwitchWeapon( CBasePlayer *pPlayer, CBaseCombatWeapon *pWeapon ); - virtual CBaseCombatWeapon *GetNextBestWeapon( CBaseCombatCharacter *pPlayer, CBaseCombatWeapon *pCurrentWeapon ); - bool SwitchToNextBestWeapon( CBaseCombatCharacter *pPlayer, CBaseCombatWeapon *pCurrentWeapon ); - -// Functions to verify the single/multiplayer status of a game - virtual bool IsDeathmatch( void ); - virtual bool IsCoOp( void ); - -// Client connection/disconnection - virtual bool ClientConnected( edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen ); - virtual void InitHUD( CBasePlayer *pl ); // the client dll is ready for updating - virtual void ClientDisconnected( edict_t *pClient ); - -// Client damage rules - virtual float FlPlayerFallDamage( CBasePlayer *pPlayer ); - virtual bool AllowDamage( CBaseEntity *pVictim, const CTakeDamageInfo &info ); - -// Client spawn/respawn control - virtual void PlayerSpawn( CBasePlayer *pPlayer ); - virtual bool FPlayerCanRespawn( CBasePlayer *pPlayer ); - virtual float FlPlayerSpawnTime( CBasePlayer *pPlayer ); - - virtual bool AllowAutoTargetCrosshair( void ); - virtual int GetAutoAimMode(); - -// Client kills/scoring - virtual int IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *pKilled ); - virtual void PlayerKilled( CBasePlayer *pVictim, const CTakeDamageInfo &info ); - virtual void DeathNotice( CBasePlayer *pVictim, const CTakeDamageInfo &info ); - -// Weapon spawn/respawn control - virtual int WeaponShouldRespawn( CBaseCombatWeapon *pWeapon ); - virtual float FlWeaponRespawnTime( CBaseCombatWeapon *pWeapon ); - virtual float FlWeaponTryRespawn( CBaseCombatWeapon *pWeapon ); - virtual Vector VecWeaponRespawnSpot( CBaseCombatWeapon *pWeapon ); - -// Item retrieval - virtual bool CanHaveItem( CBasePlayer *pPlayer, CItem *pItem ); - virtual void PlayerGotItem( CBasePlayer *pPlayer, CItem *pItem ); - -// Item spawn/respawn control - virtual int ItemShouldRespawn( CItem *pItem ); - virtual float FlItemRespawnTime( CItem *pItem ); - virtual Vector VecItemRespawnSpot( CItem *pItem ); - virtual QAngle VecItemRespawnAngles( CItem *pItem ); - -// Ammo retrieval - virtual void PlayerGotAmmo( CBaseCombatCharacter *pPlayer, char *szName, int iCount ); - -// Healthcharger respawn control - virtual float FlHealthChargerRechargeTime( void ); - -// What happens to a dead player's weapons - virtual int DeadPlayerWeapons( CBasePlayer *pPlayer ); - -// What happens to a dead player's ammo - virtual int DeadPlayerAmmo( CBasePlayer *pPlayer ); - -// NPCs - virtual bool FAllowNPCs( void ); - -// Teamplay stuff - virtual const char *GetTeamID( CBaseEntity *pEntity ) {return "";}; - virtual int PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget ); - virtual bool PlayerCanHearChat( CBasePlayer *pListener, CBasePlayer *pSpeaker ); -#endif -}; - - -#endif // SINGLEPLAY_GAMERULES_H diff --git a/game/shared/solidsetdefaults.h b/game/shared/solidsetdefaults.h deleted file mode 100644 index 0f39268ba..000000000 --- a/game/shared/solidsetdefaults.h +++ /dev/null @@ -1,28 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef SOLIDSETDEFAULTS_H -#define SOLIDSETDEFAULTS_H -#ifdef _WIN32 -#pragma once -#endif - -// solid_t parsing -class CSolidSetDefaults : public IVPhysicsKeyHandler -{ -public: - virtual void ParseKeyValue( void *pData, const char *pKey, const char *pValue ); - virtual void SetDefaults( void *pData ); - - unsigned int GetContentsMask() { return m_contentsMask; } - -private: - unsigned int m_contentsMask; -}; - -extern CSolidSetDefaults g_SolidSetup; - -#endif // SOLIDSETDEFAULTS_H diff --git a/game/shared/soundenvelope.cpp b/game/shared/soundenvelope.cpp deleted file mode 100644 index 391918cc2..000000000 --- a/game/shared/soundenvelope.cpp +++ /dev/null @@ -1,1285 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "sharedInterface.h" -#include "soundenvelope.h" -#include "engine/IEngineSound.h" -#include "IEffects.h" -#include "isaverestore.h" -#include "saverestore_utlvector.h" -#include "gamestringpool.h" -#include "igamesystem.h" -#include "utlpriorityqueue.h" -#include "mempool.h" -#include "SoundEmitterSystem/isoundemittersystembase.h" -#include "tier0/vprof.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -static ConVar soundpatch_captionlength( "soundpatch_captionlength", "2.0", FCVAR_REPLICATED, "How long looping soundpatch captions should display for." ); - -// Envelope -// This is a class that controls a ramp for a sound (pitch / volume / etc) -class CSoundEnvelope -{ -public: - DECLARE_SIMPLE_DATADESC(); - - CSoundEnvelope() - { - m_current = 0.0f; - m_target = 0.0f; - m_rate = 0.0f; - m_forceupdate = false; - } - - void SetTarget( float target, float deltaTime ); - void SetValue( float value ); - bool ShouldUpdate( void ); - void Update( float time ); - inline float Value( void ) { return m_current; } - -private: - float m_current; - float m_target; - float m_rate; - bool m_forceupdate; -}; - - -BEGIN_SIMPLE_DATADESC( CSoundEnvelope ) - DEFINE_FIELD( m_current, FIELD_FLOAT ), - DEFINE_FIELD( m_target, FIELD_FLOAT ), - DEFINE_FIELD( m_rate, FIELD_FLOAT ), - DEFINE_FIELD( m_forceupdate, FIELD_BOOLEAN ), -END_DATADESC() - - -//----------------------------------------------------------------------------- -// Purpose: Set the new target value for this ramp. Reach this target in deltaTime -// seconds from now -// Input : target - new target value -// deltaTime - time to reach target -//----------------------------------------------------------------------------- -void CSoundEnvelope::SetTarget( float target, float deltaTime ) -{ - float deltaValue = target - m_current; - - if ( deltaValue && deltaTime > 0 ) - { - m_target = target; - m_rate = MAX( 0.1, fabs(deltaValue / deltaTime) ); - } - else - { - if ( target != m_current ) - { - m_forceupdate = true; - } - - SetValue( target ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Instantaneously set the value of this ramp -// Input : value - new value -//----------------------------------------------------------------------------- -void CSoundEnvelope::SetValue( float value ) -{ - if ( m_target != value ) - { - m_forceupdate = true; - } - - m_current = m_target = value; - m_rate = 0; -} - - -//----------------------------------------------------------------------------- -// Purpose: Check to see if I need to update this envelope -// Output : Returns true if this envelope is changing -//----------------------------------------------------------------------------- -bool CSoundEnvelope::ShouldUpdate( void ) -{ - if ( m_forceupdate ) - { - m_forceupdate = false; - return true; - } - - if ( m_current != m_target ) - { - return true; - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: Update the envelope for the current frame time -// Input : time - amount of time that has passed -//----------------------------------------------------------------------------- -void CSoundEnvelope::Update( float deltaTime ) -{ - m_current = Approach( m_target, m_current, m_rate * deltaTime ); -} - -class CCopyRecipientFilter : public IRecipientFilter -{ -public: - DECLARE_SIMPLE_DATADESC(); - - CCopyRecipientFilter() : m_Flags(0) {} - - void Init( IRecipientFilter *pSrc ) - { - m_Flags = FLAG_ACTIVE; - if ( pSrc->IsReliable() ) - { - m_Flags |= FLAG_RELIABLE; - } - - if ( pSrc->IsInitMessage() ) - { - m_Flags |= FLAG_INIT_MESSAGE; - } - - for ( int i = 0; i < pSrc->GetRecipientCount(); i++ ) - { - int index = pSrc->GetRecipientIndex( i ); - - if ( index >= 0 ) - m_Recipients.AddToTail( index ); - } - } - - bool IsActive() const - { - return (m_Flags & FLAG_ACTIVE) != 0; - } - - virtual bool IsReliable( void ) const - { - return (m_Flags & FLAG_RELIABLE) != 0; - } - - virtual int GetRecipientCount( void ) const - { - return m_Recipients.Count(); - } - - virtual int GetRecipientIndex( int slot ) const - { - return m_Recipients[ slot ]; - } - - virtual bool IsInitMessage( void ) const - { - return (m_Flags & FLAG_INIT_MESSAGE) != 0; - } - - virtual bool AddRecipient( CBasePlayer *player ) - { - Assert( player ); - - int index = player->entindex(); - - if ( index < 0 ) - return false; - - // Already in list - if ( m_Recipients.Find( index ) != m_Recipients.InvalidIndex() ) - return false; - - m_Recipients.AddToTail( index ); - return true; - } - -private: - enum - { - FLAG_ACTIVE = 0x1, - FLAG_RELIABLE = 0x2, - FLAG_INIT_MESSAGE = 0x4, - }; - - int m_Flags; - CUtlVector< int > m_Recipients; -}; - -BEGIN_SIMPLE_DATADESC( CCopyRecipientFilter ) - - DEFINE_FIELD( m_Flags, FIELD_INTEGER ), - DEFINE_UTLVECTOR( m_Recipients, FIELD_INTEGER ), - -END_DATADESC() - - -#include "tier0/memdbgoff.h" -// This is the a basic sound controller, a "patch" -// It has envelopes for pitch and volume and can manage state changes to those -class CSoundPatch -{ -public: - DECLARE_SIMPLE_DATADESC(); - - static int g_SoundPatchCount; - CSoundPatch() - { - g_SoundPatchCount++; - m_iszSoundName = NULL_STRING; - m_iszSoundScriptName = NULL_STRING; - m_flCloseCaptionDuration = soundpatch_captionlength.GetFloat(); - } - ~CSoundPatch() - { - g_SoundPatchCount--; - } - - void Init( IRecipientFilter *pFilter, CBaseEntity *pEnt, int channel, const char *pSoundName, - soundlevel_t iSoundLevel ); - void ChangePitch( float pitchTarget, float deltaTime ); - void ChangeVolume( float volumeTarget, float deltaTime ); - void FadeOut( float deltaTime, bool destroyOnFadeout ); - float GetPitch( void ); - float GetVolume( void ); - string_t GetName() { return m_iszSoundName; }; - string_t GetScriptName() { return m_iszSoundScriptName; } - // UNDONE: Don't call this, use the controller to shut down - void Shutdown( void ); - bool Update( float time, float deltaTime ); - void Reset( void ); - void StartSound( float flStartTime = 0 ); - void ResumeSound( void ); - int IsPlaying( void ) { return m_isPlaying; } - void AddPlayerPost( CBasePlayer *pPlayer ); - void SetCloseCaptionDuration( float flDuration ) { m_flCloseCaptionDuration = flDuration; } - - void SetBaseFlags( int iFlags ) { m_baseFlags = iFlags; } - - // Returns the ent index - int EntIndex() const; - -private: - // SoundPatches take volumes between 0 & 1, and use that to multiply the sounds.txt specified volume. - // This function is an internal method of accessing the real volume passed into the engine (i.e. post multiply) - float GetVolumeForEngine( void ); - -private: - CSoundEnvelope m_pitch; - CSoundEnvelope m_volume; - - soundlevel_t m_soundlevel; - float m_shutdownTime; - float m_flLastTime; - string_t m_iszSoundName; - string_t m_iszSoundScriptName; - EHANDLE m_hEnt; - int m_entityChannel; - int m_flags; - int m_baseFlags; - int m_isPlaying; - float m_flScriptVolume; // Volume for this sound in sounds.txt - CCopyRecipientFilter m_Filter; - - float m_flCloseCaptionDuration; - -#ifdef _DEBUG - // Used to get the classname of the entity associated with the sound - string_t m_iszClassName; -#endif - - DECLARE_FIXEDSIZE_ALLOCATOR(CSoundPatch); -}; -#include "tier0/memdbgon.h" - -int CSoundPatch::g_SoundPatchCount = 0; - -CON_COMMAND( report_soundpatch, "reports sound patch count" ) -{ - Msg("Current sound patches: %d\n", CSoundPatch::g_SoundPatchCount ); -} -DEFINE_FIXEDSIZE_ALLOCATOR( CSoundPatch, 64, CMemoryPool::GROW_FAST ); - -BEGIN_SIMPLE_DATADESC( CSoundPatch ) - - DEFINE_EMBEDDED( m_pitch ), - DEFINE_EMBEDDED( m_volume ), - DEFINE_FIELD( m_soundlevel, FIELD_INTEGER ), - DEFINE_FIELD( m_shutdownTime, FIELD_TIME ), - DEFINE_FIELD( m_flLastTime, FIELD_TIME ), - DEFINE_FIELD( m_iszSoundName, FIELD_STRING ), - DEFINE_FIELD( m_iszSoundScriptName, FIELD_STRING ), - DEFINE_FIELD( m_hEnt, FIELD_EHANDLE ), - DEFINE_FIELD( m_entityChannel, FIELD_INTEGER ), - DEFINE_FIELD( m_flags, FIELD_INTEGER ), - DEFINE_FIELD( m_baseFlags, FIELD_INTEGER ), - DEFINE_FIELD( m_isPlaying, FIELD_INTEGER ), - DEFINE_FIELD( m_flScriptVolume, FIELD_FLOAT ), - DEFINE_EMBEDDED( m_Filter ), - DEFINE_FIELD( m_flCloseCaptionDuration, FIELD_FLOAT ), - - // Not saved, it's debug only -// DEFINE_FIELD( m_iszClassName, FIELD_STRING ), - -END_DATADESC() - - - -//----------------------------------------------------------------------------- -// Purpose: Setup the patch -// Input : nEntIndex - index of the edict that owns the sound channel -// channel - This is a sound channel (CHAN_ITEM, CHAN_STATIC) -// *pSoundName - sound script string name -// attenuation - attenuation of this sound (not animated) -//----------------------------------------------------------------------------- -void CSoundPatch::Init( IRecipientFilter *pFilter, CBaseEntity *pEnt, int channel, const char *pSoundName, - soundlevel_t soundlevel ) -{ - m_hEnt = pEnt; - m_entityChannel = channel; - // Get the volume from the script - CSoundParameters params; - if ( !Q_stristr( pSoundName, ".wav" ) && !Q_stristr( pSoundName, ".mp3" ) && - CBaseEntity::GetParametersForSound( pSoundName, params, NULL ) ) - { - m_flScriptVolume = params.volume; - // This has to be the actual .wav because rndwave would cause a bunch of new .wavs to play... bad... - // e.g., when you pitch shift it would start a different wav instead. - - m_iszSoundScriptName = AllocPooledString( pSoundName ); - - pSoundName = params.soundname; - m_soundlevel = params.soundlevel; - - m_entityChannel = params.channel; - } - else - { - - m_iszSoundScriptName = AllocPooledString( pSoundName ); - - m_flScriptVolume = 1.0; - m_soundlevel = soundlevel; - } - - m_iszSoundName = AllocPooledString( pSoundName ); - m_volume.SetValue( 0 ); - m_pitch.SetValue( 0 ); - m_isPlaying = false; - m_shutdownTime = 0; - m_flLastTime = 0; - m_Filter.Init( pFilter ); - m_baseFlags = 0; - -#ifdef _DEBUG - if ( pEnt ) - { - m_iszClassName = AllocPooledString( pEnt->GetClassname() ); - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Ramps the pitch to a new value -// Input : pitchTarget - new value -// deltaTime - seconds to reach the value -//----------------------------------------------------------------------------- -void CSoundPatch::ChangePitch( float pitchTarget, float deltaTime ) -{ - m_flags |= SND_CHANGE_PITCH; - m_pitch.SetTarget( pitchTarget, deltaTime ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Ramps the volume to a new value -// Input : volumeTarget - new volume -// deltaTime - seconds to reach the new volume -//----------------------------------------------------------------------------- -void CSoundPatch::ChangeVolume( float volumeTarget, float deltaTime ) -{ - m_flags |= SND_CHANGE_VOL; - if ( volumeTarget > 1.0 ) - volumeTarget = 1.0; - m_volume.SetTarget( volumeTarget, deltaTime ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Fade volume to zero AND SHUT DOWN THIS SOUND -// Input : deltaTime - seconds before done/shutdown -//----------------------------------------------------------------------------- -void CSoundPatch::FadeOut( float deltaTime, bool destroyOnFadeout ) -{ - ChangeVolume( 0, deltaTime ); - if ( !destroyOnFadeout ) - { - m_shutdownTime = g_pEffects->Time() + deltaTime; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Get the sound's current pitch -//----------------------------------------------------------------------------- -float CSoundPatch::GetPitch( void ) -{ - return m_pitch.Value(); -} - -//----------------------------------------------------------------------------- -// Purpose: Get the sound's current volume -//----------------------------------------------------------------------------- -float CSoundPatch::GetVolume( void ) -{ - return m_volume.Value(); -} - -//----------------------------------------------------------------------------- -// Returns the ent index -//----------------------------------------------------------------------------- -inline int CSoundPatch::EntIndex() const -{ - Assert( !m_hEnt.IsValid() || m_hEnt.Get() ); - return m_hEnt.Get() ? m_hEnt->entindex() : -1; -} - -//----------------------------------------------------------------------------- -// Purpose: SoundPatches take volumes between 0 & 1, and use that to multiply the sounds.txt specified volume. -// This function is an internal method of accessing the real volume passed into the engine (i.e. post multiply) -// Output : float -//----------------------------------------------------------------------------- -float CSoundPatch::GetVolumeForEngine( void ) -{ - return ( m_flScriptVolume * m_volume.Value() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Stop the sound -//----------------------------------------------------------------------------- -void CSoundPatch::Shutdown( void ) -{ -// Msg( "Removing sound %s\n", m_pszSoundName ); - if ( m_isPlaying ) - { - int entIndex = EntIndex(); - Assert( entIndex >= 0 ); - // BUGBUG: Don't crash in release mode - if ( entIndex >= 0 ) - { - CBaseEntity::StopSound( entIndex, m_entityChannel, STRING( m_iszSoundName ) ); - } - m_isPlaying = false; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Update all envelopes and send appropriate data to the client -// Input : time - new global clock -// deltaTime - amount of time that has passed -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CSoundPatch::Update( float time, float deltaTime ) -{ - VPROF( "CSoundPatch::Update" ); - if ( m_shutdownTime && time > m_shutdownTime ) - { - Shutdown(); - return false; - } - - if ( EntIndex() < 0 ) - { - // FIXME: The pointer to this soundpatch is probably leaked since no entity is around to clean it up (ywb) - DevWarning( "CSoundPatch::Update: Removing CSoundPatch (%s) with NULL EHandle\n", STRING(m_iszSoundName) ); - return false; - } - - if ( m_pitch.ShouldUpdate() ) - { - m_pitch.Update( deltaTime ); - m_flags |= SND_CHANGE_PITCH; - } - else - { - m_flags &= ~SND_CHANGE_PITCH; - } - - if ( m_volume.ShouldUpdate() ) - { - m_volume.Update( deltaTime ); - m_flags |= SND_CHANGE_VOL; - } - else - { - m_flags &= ~SND_CHANGE_VOL; - } - - if ( m_flags && m_Filter.IsActive() ) - { - // SoundPatches take volumes between 0 & 1, and use that to multiply the sounds.txt specified volume. - // Because of this, we need to always set the SND_CHANGE_VOL flag when we emit sound, or it'll use the scriptfile's instead. - m_flags |= SND_CHANGE_VOL; - - EmitSound_t ep; - ep.m_nChannel = m_entityChannel; - ep.m_pSoundName = STRING(m_iszSoundName); - ep.m_flVolume = GetVolumeForEngine(); - ep.m_SoundLevel = m_soundlevel; - ep.m_nFlags = m_flags; - ep.m_nPitch = (int)m_pitch.Value(); - - CBaseEntity::EmitSound( m_Filter, EntIndex(), ep ); - - m_flags = 0; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Sound is going to start playing again, clear any shutdown time -//----------------------------------------------------------------------------- -void CSoundPatch::Reset( void ) -{ - m_shutdownTime = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: Start playing the sound - send updates to the client -//----------------------------------------------------------------------------- -void CSoundPatch::StartSound( float flStartTime ) -{ -// Msg( "Start sound %s\n", m_pszSoundName ); - m_flags = 0; - if ( m_Filter.IsActive() ) - { - EmitSound_t ep; - ep.m_nChannel = m_entityChannel; - ep.m_pSoundName = STRING(m_iszSoundName); - ep.m_flVolume = GetVolumeForEngine(); - ep.m_SoundLevel = m_soundlevel; - ep.m_nFlags = (SND_CHANGE_VOL | m_baseFlags); - ep.m_nPitch = (int)m_pitch.Value(); - ep.m_bEmitCloseCaption = false; - - if ( flStartTime ) - { - ep.m_flSoundTime = flStartTime; - } - - CBaseEntity::EmitSound( m_Filter, EntIndex(), ep ); - CBaseEntity::EmitCloseCaption( m_Filter, EntIndex(), STRING( m_iszSoundScriptName ), ep.m_UtlVecSoundOrigin, m_flCloseCaptionDuration, true ); - } - m_isPlaying = true; -} - - -//----------------------------------------------------------------------------- -// Purpose: resumes playing the sound on restore -//----------------------------------------------------------------------------- -void CSoundPatch::ResumeSound( void ) -{ - if ( IsPlaying() && m_Filter.IsActive() ) - { - if ( EntIndex() >= 0 ) - { - EmitSound_t ep; - ep.m_nChannel = m_entityChannel; - ep.m_pSoundName = STRING(m_iszSoundName); - ep.m_flVolume = GetVolumeForEngine(); - ep.m_SoundLevel = m_soundlevel; - ep.m_nFlags = (SND_CHANGE_VOL | SND_CHANGE_PITCH | m_baseFlags); - ep.m_nPitch = (int)m_pitch.Value(); - - CBaseEntity::EmitSound( m_Filter, EntIndex(), ep ); - } - else - { - // FIXME: Lost the entity on restore. It might have been suppressed by the save/restore system. - // This will probably leak the sound patch since there's no one to delete it, but the next - // call to CSoundPatch::Update should at least remove it from the list of sound patches. - DevWarning( "CSoundPatch::ResumeSound: Lost EHAndle on restore - destroy the sound patch in your entity's StopLoopingSounds! (%s)\n", STRING( m_iszSoundName ) ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: A new player's entered the game. See if we need to restart our sound. -//----------------------------------------------------------------------------- -void CSoundPatch::AddPlayerPost( CBasePlayer *pPlayer ) -{ - if ( m_Filter.IsActive() && m_Filter.AddRecipient(pPlayer) ) - { - // Alrighty, he's new. We need to restart our sound just to him. - // Create a new filter just to him. - CSingleUserRecipientFilter filter( pPlayer ); - - EmitSound_t ep; - ep.m_nChannel = m_entityChannel; - ep.m_pSoundName = STRING(m_iszSoundName); - ep.m_flVolume = GetVolumeForEngine(); - ep.m_SoundLevel = m_soundlevel; - ep.m_nFlags = (SND_CHANGE_VOL | m_baseFlags); - ep.m_nPitch = (int)m_pitch.Value(); - - CBaseEntity::EmitSound( filter, EntIndex(), ep ); - } -} - -// This is an entry in the command queue. It's used to queue up various pitch and volume changes -// so you can define an envelope without writing timing code in an entity. Existing queued commands -// can be deleted later if the envelope changes dynamically. -#include "tier0/memdbgoff.h" -struct SoundCommand_t -{ - SoundCommand_t( void ) { memset( this, 0, sizeof(*this) ); } - SoundCommand_t( CSoundPatch *pSound, float executeTime, soundcommands_t command, float deltaTime, float value ) : m_pPatch(pSound), m_time(executeTime), m_deltaTime(deltaTime), m_command(command), m_value(value) {} - - CSoundPatch *m_pPatch; - float m_time; - float m_deltaTime; - soundcommands_t m_command; - float m_value; - - SoundCommand_t *m_pNext; - - DECLARE_SIMPLE_DATADESC(); - DECLARE_FIXEDSIZE_ALLOCATOR(SoundCommand_t); -}; -#include "tier0/memdbgon.h" - -DEFINE_FIXEDSIZE_ALLOCATOR( SoundCommand_t, 32, CMemoryPool::GROW_FAST ); - - -BEGIN_SIMPLE_DATADESC( SoundCommand_t ) - -// NOTE: This doesn't need to be saved, sound commands are saved right after the patch -// they are associated with -// DEFINE_FIELD( m_pPatch, FIELD_????? ) - DEFINE_FIELD( m_time, FIELD_TIME ), - DEFINE_FIELD( m_deltaTime, FIELD_FLOAT ), - DEFINE_FIELD( m_command, FIELD_INTEGER ), - DEFINE_FIELD( m_value, FIELD_FLOAT ), -// DEFINE_FIELD( m_pNext, FIELD_????? ) - -END_DATADESC() - -typedef SoundCommand_t *SOUNDCOMMANDPTR; - -bool SoundCommandLessFunc( const SOUNDCOMMANDPTR &lhs, const SOUNDCOMMANDPTR &rhs ) -{ - // NOTE: A greater time means "less" priority - return ( lhs->m_time > rhs->m_time ); -} - - -// This implements the sound controller -class CSoundControllerImp : public CSoundEnvelopeController, public CAutoGameSystemPerFrame -{ - //----------------------------------------------------------------------------- - // internal functions, private to this file - //----------------------------------------------------------------------------- -public: - CSoundControllerImp( void ) : CAutoGameSystemPerFrame( "CSoundControllerImp" ) - { - m_commandList.SetLessFunc( SoundCommandLessFunc ); - } - - void ProcessCommand( SoundCommand_t *pCmd ); - void RemoveFromList( CSoundPatch *pSound ); - void SaveSoundPatch( CSoundPatch *pSound, ISave *pSave ); - void RestoreSoundPatch( CSoundPatch **ppSound, IRestore *pRestore ); - - virtual void OnRestore(); - - //----------------------------------------------------------------------------- - // external interface functions (from CSoundEnvelopeController) - //----------------------------------------------------------------------------- -public: - - // Start this sound playing, or reset if already playing with new volume/pitch - void Play( CSoundPatch *pSound, float volume, float pitch, float flStartTime = 0 ); - void CommandAdd( CSoundPatch *pSound, float executeDeltaTime, soundcommands_t command, float commandTime, float commandValue ); - - void SystemReset( void ); - void SystemUpdate( void ); - void CommandClear( CSoundPatch *pSound ); - void Shutdown( CSoundPatch *pSound ); - - CSoundPatch *SoundCreate( IRecipientFilter& filter, int nEntIndex, const char *pSoundName ); - CSoundPatch *SoundCreate( IRecipientFilter& filter, int nEntIndex, int channel, const char *pSoundName, - float attenuation ); - CSoundPatch *SoundCreate( IRecipientFilter& filter, int nEntIndex, int channel, const char *pSoundName, - soundlevel_t soundlevel ); - CSoundPatch *SoundCreate( IRecipientFilter& filter, int nEntIndex, const EmitSound_t &es ); - void SoundDestroy( CSoundPatch *pSound ); - void SoundChangePitch( CSoundPatch *pSound, float pitchTarget, float deltaTime ); - void SoundChangeVolume( CSoundPatch *pSound, float volumeTarget, float deltaTime ); - void SoundFadeOut( CSoundPatch *pSound, float deltaTime, bool destroyOnFadeout ); - float SoundGetPitch( CSoundPatch *pSound ); - float SoundGetVolume( CSoundPatch *pSound ); - string_t SoundGetName( CSoundPatch *pSound ) { return pSound->GetName(); } - void SoundSetCloseCaptionDuration( CSoundPatch *pSound, float flDuration ) { pSound->SetCloseCaptionDuration(flDuration); } - - float SoundPlayEnvelope( CSoundPatch *pSound, soundcommands_t soundCommand, envelopePoint_t *points, int numPoints ); - float SoundPlayEnvelope( CSoundPatch *pSound, soundcommands_t soundCommand, envelopeDescription_t *envelope ); - - void CheckLoopingSoundsForPlayer( CBasePlayer *pPlayer ); - - // Inserts the command into the list, sorted by time - void CommandInsert( SoundCommand_t *pCommand ); - -#ifdef CLIENT_DLL - // CAutoClientSystem - virtual void Update( float frametime ) - { - SystemUpdate(); - } -#else - virtual void PreClientUpdate() - { - SystemUpdate(); - } -#endif - - virtual void LevelShutdownPreEntity() - { - SystemReset(); - } - -private: - CUtlVector m_soundList; - CUtlPriorityQueue m_commandList; - float m_flLastTime; -}; - -// Execute a command from the list -// currently only 3 commands -// UNDONE: Add start command? -void CSoundControllerImp::ProcessCommand( SoundCommand_t *pCmd ) -{ - switch( pCmd->m_command ) - { - case SOUNDCTRL_CHANGE_VOLUME: - pCmd->m_pPatch->ChangeVolume( pCmd->m_value, pCmd->m_deltaTime ); - break; - - case SOUNDCTRL_CHANGE_PITCH: - pCmd->m_pPatch->ChangePitch( pCmd->m_value, pCmd->m_deltaTime ); - break; - - case SOUNDCTRL_STOP: - pCmd->m_pPatch->Shutdown(); - break; - - case SOUNDCTRL_DESTROY: - RemoveFromList( pCmd->m_pPatch ); - delete pCmd->m_pPatch; - pCmd->m_pPatch = NULL; - break; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Remove this sound from the sound list & shutdown (not in external interface) -// Input : *pSound - patch to remove -//----------------------------------------------------------------------------- -void CSoundControllerImp::RemoveFromList( CSoundPatch *pSound ) -{ - m_soundList.FindAndRemove( pSound ); - pSound->Shutdown(); -} - - -//----------------------------------------------------------------------------- -// Start this sound playing, or reset if already playing with new volume/pitch -//----------------------------------------------------------------------------- -void CSoundControllerImp::Play( CSoundPatch *pSound, float volume, float pitch, float flStartTime ) -{ - // reset the vars - pSound->Reset(); - - pSound->ChangeVolume( volume, 0 ); - pSound->ChangePitch( pitch, 0 ); - - if ( pSound->IsPlaying() ) - { - // remove any previous commands in the queue - CommandClear( pSound ); - } - else - { - m_soundList.AddToTail( pSound ); - pSound->StartSound( flStartTime ); - } -} - - -//----------------------------------------------------------------------------- -// Inserts the command into the list, sorted by time -//----------------------------------------------------------------------------- -void CSoundControllerImp::CommandInsert( SoundCommand_t *pCommand ) -{ - m_commandList.Insert( pCommand ); -} - - -//----------------------------------------------------------------------------- -// Purpose: puts a command into the queue -// Input : *pSound - patch this command affects -// executeDeltaTime - relative time to execute this command -// command - command to execute (SOUNDCTRL_*) -// commandTime - commands have 2 parameters, a time and a value -// value - -// Output : void -//----------------------------------------------------------------------------- -void CSoundControllerImp::CommandAdd( CSoundPatch *pSound, float executeDeltaTime, soundcommands_t command, float commandTime, float commandValue ) -{ - SoundCommand_t *pCommand = new SoundCommand_t( pSound, g_pEffects->Time() + executeDeltaTime, command, commandTime, commandValue ); - CommandInsert( pCommand ); -} - -// Reset the whole system (level change, etc.) -void CSoundControllerImp::SystemReset( void ) -{ - for ( int i = m_soundList.Count()-1; i >=0; i-- ) - { - CSoundPatch *pNode = m_soundList[i]; - - // shutdown all active sounds - pNode->Shutdown(); - } - - // clear the list - m_soundList.Purge(); - - // clear the command queue - m_commandList.RemoveAll(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Update the active sounds, dequeue any events and move the ramps -//----------------------------------------------------------------------------- -void CSoundControllerImp::SystemUpdate( void ) -{ - VPROF( "CSoundControllerImp::SystemUpdate" ); - float time = g_pEffects->Time(); - float deltaTime = time - m_flLastTime; - - // handle clock resets - if ( deltaTime < 0 ) - deltaTime = 0; - - m_flLastTime = time; - - { - VPROF( "CSoundControllerImp::SystemUpdate:processcommandlist" ); - while ( m_commandList.Count() ) - { - SoundCommand_t *pCmd = m_commandList.ElementAtHead(); - // Commands are sorted by time. - // process any that should occur by the current time - if ( time >= pCmd->m_time ) - { - m_commandList.RemoveAtHead(); - ProcessCommand( pCmd ); - delete pCmd; - } - else - { - break; - } - } - } - - // NOTE: Because this loop goes from the end to the beginning - // we can fast remove inside it without breaking the indexing - { - VPROF( "CSoundControllerImp::SystemUpdate:removesounds" ); - for ( int i = m_soundList.Count()-1; i >=0; i-- ) - { - CSoundPatch *pNode = m_soundList[i]; - if ( !pNode->Update( time, deltaTime ) ) - { - pNode->Reset(); - m_soundList.FastRemove( i ); - } - } - } -} - -// Remove any envelope commands from the list (dynamically changing envelope) -void CSoundControllerImp::CommandClear( CSoundPatch *pSound ) -{ - for ( int i = m_commandList.Count()-1; i >= 0; i-- ) - { - SoundCommand_t *pCmd = m_commandList.Element( i ); - if ( pCmd->m_pPatch == pSound ) - { - m_commandList.RemoveAt(i); - delete pCmd; - } - } -} - - -//----------------------------------------------------------------------------- -// Saves the sound patch + associated commands -//----------------------------------------------------------------------------- -void CSoundControllerImp::SaveSoundPatch( CSoundPatch *pSoundPatch, ISave *pSave ) -{ - int i; - - // Write out the sound patch - pSave->StartBlock(); - pSave->WriteAll( pSoundPatch ); - pSave->EndBlock(); - - // Count the number of commands that refer to the sound patch - int nCount = 0; - for ( i = m_commandList.Count()-1; i >= 0; i-- ) - { - SoundCommand_t *pCmd = m_commandList.Element( i ); - if ( pCmd->m_pPatch == pSoundPatch ) - { - nCount++; - } - } - - // Write out the number of commands, followed by each command itself - pSave->StartBlock(); - pSave->WriteInt( &nCount ); - - for ( i = m_commandList.Count()-1; i >= 0; i-- ) - { - SoundCommand_t *pCmd = m_commandList.Element( i ); - if ( pCmd->m_pPatch == pSoundPatch ) - { - pSave->StartBlock(); - pSave->WriteAll( pCmd ); - pSave->EndBlock(); - } - } - - pSave->EndBlock(); -} - -//----------------------------------------------------------------------------- -// Restores the sound patch + associated commands -//----------------------------------------------------------------------------- -void CSoundControllerImp::RestoreSoundPatch( CSoundPatch **ppSoundPatch, IRestore *pRestore ) -{ - CSoundPatch *pPatch = new CSoundPatch; - - // read the sound patch data from the memory block - pRestore->StartBlock(); - bool bOk = ( pRestore->ReadAll( pPatch ) != 0 ); - pRestore->EndBlock(); - bOk = (bOk && pPatch->IsPlaying()) ? true : false; - - if (bOk) - { - m_soundList.AddToTail( pPatch ); - } - - // Count the number of commands that refer to the sound patch - pRestore->StartBlock(); - - if ( bOk ) - { - int nCount; - pRestore->ReadInt( &nCount ); - while ( --nCount >= 0 ) - { - SoundCommand_t *pCommand = new SoundCommand_t; - - pRestore->StartBlock(); - if ( pRestore->ReadAll( pCommand ) ) - { - pCommand->m_pPatch = pPatch; - CommandInsert( pCommand ); - } - - pRestore->EndBlock(); - } - } - - pRestore->EndBlock(); - *ppSoundPatch = pPatch; -} - - -//----------------------------------------------------------------------------- -// Purpose: immediately stop playing this sound -// Input : *pSound - Patch to shut down -//----------------------------------------------------------------------------- -void CSoundControllerImp::Shutdown( CSoundPatch *pSound ) -{ - if ( !pSound ) - return; - - pSound->Shutdown(); - CommandClear( pSound ); - RemoveFromList( pSound ); -} - -CSoundPatch *CSoundControllerImp::SoundCreate( IRecipientFilter& filter, int nEntIndex, const char *pSoundName ) -{ - CSoundPatch *pSound = new CSoundPatch; - - // FIXME: This is done so we don't have to futz with the public interface - EHANDLE hEnt = (nEntIndex != -1) ? g_pEntityList->GetNetworkableHandle( nEntIndex ) : 0; - pSound->Init( &filter, hEnt.Get(), CHAN_AUTO, pSoundName, SNDLVL_NORM ); - - return pSound; -} - -CSoundPatch *CSoundControllerImp::SoundCreate( IRecipientFilter& filter, int nEntIndex, int channel, - const char *pSoundName, float attenuation ) -{ - CSoundPatch *pSound = new CSoundPatch; - EHANDLE hEnt = (nEntIndex != -1) ? g_pEntityList->GetNetworkableHandle( nEntIndex ) : 0; - pSound->Init( &filter, hEnt.Get(), channel, pSoundName, ATTN_TO_SNDLVL( attenuation ) ); - - return pSound; -} - -CSoundPatch *CSoundControllerImp::SoundCreate( IRecipientFilter& filter, int nEntIndex, int channel, - const char *pSoundName, soundlevel_t soundlevel ) -{ - CSoundPatch *pSound = new CSoundPatch; - EHANDLE hEnt = (nEntIndex != -1) ? g_pEntityList->GetNetworkableHandle( nEntIndex ) : 0; - pSound->Init( &filter, hEnt.Get(), channel, pSoundName, soundlevel ); - - return pSound; -} - -CSoundPatch *CSoundControllerImp::SoundCreate( IRecipientFilter& filter, int nEntIndex, const EmitSound_t &es ) -{ - CSoundPatch *pSound = new CSoundPatch; - - // FIXME: This is done so we don't have to futz with the public interface - EHANDLE hEnt = (nEntIndex != -1) ? g_pEntityList->GetNetworkableHandle( nEntIndex ) : 0; - pSound->Init( &filter, hEnt.Get(), es.m_nChannel, es.m_pSoundName, es.m_SoundLevel ); - pSound->ChangeVolume( es.m_flVolume, 0 ); - pSound->ChangePitch( es.m_nPitch, 0 ); - - if ( es.m_nFlags & SND_SHOULDPAUSE ) - { - pSound->SetBaseFlags( SND_SHOULDPAUSE ); - } - - return pSound; -} - -void CSoundControllerImp::SoundDestroy( CSoundPatch *pSound ) -{ - if ( !pSound ) - return; - - Shutdown( pSound ); - delete pSound; -} - -void CSoundControllerImp::SoundChangePitch( CSoundPatch *pSound, float pitchTarget, float deltaTime ) -{ - pSound->ChangePitch( pitchTarget, deltaTime ); -} - - -void CSoundControllerImp::SoundChangeVolume( CSoundPatch *pSound, float volumeTarget, float deltaTime ) -{ - pSound->ChangeVolume( volumeTarget, deltaTime ); -} - -float CSoundControllerImp::SoundGetPitch( CSoundPatch *pSound ) -{ - return pSound->GetPitch(); -} - -float CSoundControllerImp::SoundGetVolume( CSoundPatch *pSound ) -{ - return pSound->GetVolume(); -} - -void CSoundControllerImp::SoundFadeOut( CSoundPatch *pSound, float deltaTime, bool destroyOnFadeout ) -{ - if ( destroyOnFadeout && (deltaTime == 0.0f) ) - { - SoundDestroy( pSound ); - return; - } - - pSound->FadeOut( deltaTime, destroyOnFadeout ); - if ( destroyOnFadeout ) - { - CommandAdd( pSound, deltaTime, SOUNDCTRL_DESTROY, 0.0f, 0.0f ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Queue a list of envelope points into a sound patch's event list -// Input : *pSound - The sound patch to be operated on -// soundCommand - Type of operation the envelope describes -// *points - List of enevelope points -// numPoints - Number of points provided -// Output : float - Returns the total duration of the envelope -//----------------------------------------------------------------------------- -float CSoundControllerImp::SoundPlayEnvelope( CSoundPatch *pSound, soundcommands_t soundCommand, envelopePoint_t *points, int numPoints ) -{ - float amplitude = 0.0f; - float duration = 0.0f; - float totalDuration = 0.0f; - - Assert( points ); - - // Clear out all previously acting commands - CommandClear( pSound ); - - // Evaluate and queue all points - for ( int i = 0; i < numPoints; i++ ) - { - // See if we're keeping our last amplitude for this new point - if ( ( points[i].amplitudeMin != -1.0f ) || ( points[i].amplitudeMax != -1.0f ) ) - { - amplitude = random->RandomFloat( points[i].amplitudeMin, points[i].amplitudeMax ); - } - else if ( i == 0 ) - { - // Can't do this on the first entry - Msg( "Invalid starting amplitude value in envelope! (Cannot be -1)\n" ); - } - - // See if we're keeping our last duration for this new point - if ( ( points[i].durationMin != -1.0f ) || ( points[i].durationMax != -1.0f ) ) - { - duration = random->RandomFloat( points[i].durationMin, points[i].durationMax ); - //duration = points[i].durationMin; - } - else if ( i == 0 ) - { - // Can't do this on the first entry - Msg( "Invalid starting duration value in envelope! (Cannot be -1)\n" ); - } - - // Queue the command - CommandAdd( pSound, totalDuration, soundCommand, duration, amplitude ); - - // Tack this command's duration onto the running duration - totalDuration += duration; - } - - return totalDuration; -} - -//----------------------------------------------------------------------------- -// Purpose: Queue a list of envelope points into a sound patch's event list -// Input : *pSound - The sound patch to be operated on -// soundCommand - Type of operation the envelope describes -// *envelope - The envelope description to be queued -// Output : float - Returns the total duration of the envelope -//----------------------------------------------------------------------------- -float CSoundControllerImp::SoundPlayEnvelope( CSoundPatch *pSound, soundcommands_t soundCommand, envelopeDescription_t *envelope ) -{ - return SoundPlayEnvelope( pSound, soundCommand, envelope->pPoints, envelope->nNumPoints ); -} - -//----------------------------------------------------------------------------- -// Purpose: Looping sounds are often started in entity spawn/activate functions. -// In singleplayer, the player's not ready to receive sounds then, so restart -// and SoundPatches that are active and have no receivers. -//----------------------------------------------------------------------------- -void CSoundControllerImp::CheckLoopingSoundsForPlayer( CBasePlayer *pPlayer ) -{ - for ( int i = m_soundList.Count()-1; i >=0; i-- ) - { - CSoundPatch *pNode = m_soundList[i]; - pNode->AddPlayerPost( pPlayer ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Resumes saved soundpatches -//----------------------------------------------------------------------------- -void CSoundControllerImp::OnRestore() -{ - for ( int i = m_soundList.Count()-1; i >=0; i-- ) - { - CSoundPatch *pNode = m_soundList[i]; - if ( pNode && pNode->IsPlaying() ) - { - pNode->ResumeSound(); - } - } -} - - -//----------------------------------------------------------------------------- -// Singleton accessors -//----------------------------------------------------------------------------- -static CSoundControllerImp g_Controller; -CSoundEnvelopeController &CSoundEnvelopeController::GetController( void ) -{ - return g_Controller; -} - - -//----------------------------------------------------------------------------- -// Queues up sound patches to save/load -//----------------------------------------------------------------------------- -class CSoundPatchSaveRestoreOps : public CClassPtrSaveRestoreOps -{ -public: - virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave ) - { - pSave->StartBlock(); - - int nSoundPatchCount = fieldInfo.pTypeDesc->fieldSize; - CSoundPatch **ppSoundPatch = (CSoundPatch**)fieldInfo.pField; - while ( --nSoundPatchCount >= 0 ) - { - // Write out commands associated with this sound patch - g_Controller.SaveSoundPatch( *ppSoundPatch, pSave ); - ++ppSoundPatch; - } - - pSave->EndBlock(); - } - - virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore ) - { - pRestore->StartBlock(); - - int nSoundPatchCount = fieldInfo.pTypeDesc->fieldSize; - CSoundPatch **ppSoundPatch = (CSoundPatch**)fieldInfo.pField; - while ( --nSoundPatchCount >= 0 ) - { - // Write out commands associated with this sound patch - g_Controller.RestoreSoundPatch( ppSoundPatch, pRestore ); - ++ppSoundPatch; - } - - pRestore->EndBlock(); - } -}; - -static CSoundPatchSaveRestoreOps s_SoundPatchSaveRestoreOps; -ISaveRestoreOps *GetSoundSaveRestoreOps( ) -{ - return &s_SoundPatchSaveRestoreOps; -} diff --git a/game/shared/soundenvelope.h b/game/shared/soundenvelope.h deleted file mode 100644 index b32d18407..000000000 --- a/game/shared/soundenvelope.h +++ /dev/null @@ -1,91 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef SOUNDENVELOPE_H -#define SOUNDENVELOPE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "engine/IEngineSound.h" - -class CSoundPatch; - -enum soundcommands_t -{ - SOUNDCTRL_CHANGE_VOLUME, - SOUNDCTRL_CHANGE_PITCH, - SOUNDCTRL_STOP, - SOUNDCTRL_DESTROY, -}; - -//Envelope point -struct envelopePoint_t -{ - float amplitudeMin, amplitudeMax; - float durationMin, durationMax; -}; - -//Envelope description -struct envelopeDescription_t -{ - envelopePoint_t *pPoints; - int nNumPoints; -}; - -class IRecipientFilter; - -abstract_class CSoundEnvelopeController -{ -public: - virtual void SystemReset( void ) = 0; - virtual void SystemUpdate( void ) = 0; - virtual void Play( CSoundPatch *pSound, float volume, float pitch, float flStartTime = 0 ) = 0; - virtual void CommandAdd( CSoundPatch *pSound, float executeDeltaTime, soundcommands_t command, float commandTime, float value ) = 0; - virtual void CommandClear( CSoundPatch *pSound ) = 0; - virtual void Shutdown( CSoundPatch *pSound ) = 0; - - virtual CSoundPatch *SoundCreate( IRecipientFilter& filter, int nEntIndex, const char *pSoundName ) = 0; - virtual CSoundPatch *SoundCreate( IRecipientFilter& filter, int nEntIndex, int channel, const char *pSoundName, - float attenuation ) = 0; - virtual CSoundPatch *SoundCreate( IRecipientFilter& filter, int nEntIndex, int channel, const char *pSoundName, - soundlevel_t soundlevel ) = 0; - virtual CSoundPatch *SoundCreate( IRecipientFilter& filter, int nEntIndex, const EmitSound_t &es ) = 0; - virtual void SoundDestroy( CSoundPatch * ) = 0; - virtual void SoundChangePitch( CSoundPatch *pSound, float pitchTarget, float deltaTime ) = 0; - virtual void SoundChangeVolume( CSoundPatch *pSound, float volumeTarget, float deltaTime ) = 0; - virtual void SoundFadeOut( CSoundPatch *pSound, float deltaTime, bool destroyOnFadeout = false ) = 0; - virtual float SoundGetPitch( CSoundPatch *pSound ) = 0; - virtual float SoundGetVolume( CSoundPatch *pSound ) = 0; - - virtual float SoundPlayEnvelope( CSoundPatch *pSound, soundcommands_t soundCommand, envelopePoint_t *points, int numPoints ) = 0; - virtual float SoundPlayEnvelope( CSoundPatch *pSound, soundcommands_t soundCommand, envelopeDescription_t *envelope ) = 0; - - virtual void CheckLoopingSoundsForPlayer( CBasePlayer *pPlayer ) = 0; - - virtual string_t SoundGetName( CSoundPatch *pSound ) = 0; - static CSoundEnvelopeController &GetController( void ); - - virtual void SoundSetCloseCaptionDuration( CSoundPatch *pSound, float flDuration ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Save/restore -//----------------------------------------------------------------------------- -class ISaveRestoreOps; - -ISaveRestoreOps *GetSoundSaveRestoreOps( ); - -#define DEFINE_SOUNDPATCH(name) \ - { FIELD_CUSTOM, #name, { offsetof(classNameTypedef,name), 0 }, 1, FTYPEDESC_SAVE, NULL, GetSoundSaveRestoreOps( ), NULL } - - -#endif // SOUNDENVELOPE_H diff --git a/game/shared/studio_shared.cpp b/game/shared/studio_shared.cpp deleted file mode 100644 index f26b256f4..000000000 --- a/game/shared/studio_shared.cpp +++ /dev/null @@ -1,42 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "studio.h" -#include "engine/ivmodelinfo.h" -#include "utlsymbol.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//////////////////////////////////////////////////////////////////////// -const studiohdr_t *studiohdr_t::FindModel( void **cache, char const *modelname ) const -{ - return modelinfo->FindModel( this, cache, modelname ); -} - -virtualmodel_t *studiohdr_t::GetVirtualModel( void ) const -{ - if ( numincludemodels == 0 ) - return NULL; - return modelinfo->GetVirtualModel( this ); -} - -const studiohdr_t *virtualgroup_t::GetStudioHdr( ) const -{ - return modelinfo->FindModel( this->cache ); -} - - -byte *studiohdr_t::GetAnimBlock( int iBlock ) const -{ - return modelinfo->GetAnimBlock( this, iBlock ); -} - -int studiohdr_t::GetAutoplayList( unsigned short **pOut ) const -{ - return modelinfo->GetAutoplayList( this, pOut ); -} diff --git a/game/shared/sun_shared.h b/game/shared/sun_shared.h deleted file mode 100644 index 066086ddf..000000000 --- a/game/shared/sun_shared.h +++ /dev/null @@ -1,20 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef SUN_SHARED_H -#define SUN_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - -//FIXME: It strikes me that the usefulness of this header file is now diminished - -#define MAX_SUN_LAYERS 4 - -#define SF_LIGHTGLOW_DIRECTIONAL (1<<0) -#define SF_MODULATE_BY_DIRECTION (1<<1) - -#endif // SUN_SHARED_H diff --git a/game/shared/takedamageinfo.cpp b/game/shared/takedamageinfo.cpp deleted file mode 100644 index b7424a019..000000000 --- a/game/shared/takedamageinfo.cpp +++ /dev/null @@ -1,490 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "takedamageinfo.h" -#include "ammodef.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar phys_pushscale( "phys_pushscale", "1", FCVAR_REPLICATED ); - -BEGIN_SIMPLE_DATADESC( CTakeDamageInfo ) - DEFINE_FIELD( m_vecDamageForce, FIELD_VECTOR ), - DEFINE_FIELD( m_vecDamagePosition, FIELD_POSITION_VECTOR), - DEFINE_FIELD( m_vecReportedPosition, FIELD_POSITION_VECTOR), - DEFINE_FIELD( m_hInflictor, FIELD_EHANDLE), - DEFINE_FIELD( m_hAttacker, FIELD_EHANDLE), - DEFINE_FIELD( m_hWeapon, FIELD_EHANDLE), - DEFINE_FIELD( m_flDamage, FIELD_FLOAT), - DEFINE_FIELD( m_flMaxDamage, FIELD_FLOAT), - DEFINE_FIELD( m_flBaseDamage, FIELD_FLOAT ), - DEFINE_FIELD( m_bitsDamageType, FIELD_INTEGER), - DEFINE_FIELD( m_iDamageCustom, FIELD_INTEGER), - DEFINE_FIELD( m_iDamageStats, FIELD_INTEGER), - DEFINE_FIELD( m_iAmmoType, FIELD_INTEGER), - DEFINE_FIELD( m_iDamagedOtherPlayers, FIELD_INTEGER), -END_DATADESC() - -void CTakeDamageInfo::Init( CBaseEntity *pInflictor, CBaseEntity *pAttacker, CBaseEntity *pWeapon, const Vector &damageForce, const Vector &damagePosition, const Vector &reportedPosition, float flDamage, int bitsDamageType, int iCustomDamage ) -{ - m_hInflictor = pInflictor; - if ( pAttacker ) - { - m_hAttacker = pAttacker; - } - else - { - m_hAttacker = pInflictor; - } - - m_hWeapon = pWeapon; - - m_flDamage = flDamage; - - m_flBaseDamage = BASEDAMAGE_NOT_SPECIFIED; - - m_bitsDamageType = bitsDamageType; - m_iDamageCustom = iCustomDamage; - - m_flMaxDamage = flDamage; - m_vecDamageForce = damageForce; - m_vecDamagePosition = damagePosition; - m_vecReportedPosition = reportedPosition; - m_iAmmoType = -1; - - m_iDamagedOtherPlayers = 0; - m_iPlayerPenetrateCount = 0; - m_flUnknown = 0.0f; -} - -CTakeDamageInfo::CTakeDamageInfo() -{ - Init( NULL, NULL, NULL, vec3_origin, vec3_origin, vec3_origin, 0, 0, 0 ); -} - -CTakeDamageInfo::CTakeDamageInfo( CBaseEntity *pInflictor, CBaseEntity *pAttacker, float flDamage, int bitsDamageType, int iKillType ) -{ - Set( pInflictor, pAttacker, flDamage, bitsDamageType, iKillType ); -} - -CTakeDamageInfo::CTakeDamageInfo( CBaseEntity *pInflictor, CBaseEntity *pAttacker, CBaseEntity *pWeapon, float flDamage, int bitsDamageType, int iKillType ) -{ - Set( pInflictor, pAttacker, pWeapon, flDamage, bitsDamageType, iKillType ); -} - -CTakeDamageInfo::CTakeDamageInfo( CBaseEntity *pInflictor, CBaseEntity *pAttacker, const Vector &damageForce, const Vector &damagePosition, float flDamage, int bitsDamageType, int iKillType, Vector *reportedPosition ) -{ - Set( pInflictor, pAttacker, damageForce, damagePosition, flDamage, bitsDamageType, iKillType, reportedPosition ); -} - -CTakeDamageInfo::CTakeDamageInfo( CBaseEntity *pInflictor, CBaseEntity *pAttacker, CBaseEntity *pWeapon, const Vector &damageForce, const Vector &damagePosition, float flDamage, int bitsDamageType, int iKillType, Vector *reportedPosition ) -{ - Set( pInflictor, pAttacker, pWeapon, damageForce, damagePosition, flDamage, bitsDamageType, iKillType, reportedPosition ); -} - -void CTakeDamageInfo::Set( CBaseEntity *pInflictor, CBaseEntity *pAttacker, float flDamage, int bitsDamageType, int iKillType ) -{ - Init( pInflictor, pAttacker, NULL, vec3_origin, vec3_origin, vec3_origin, flDamage, bitsDamageType, iKillType ); -} - -void CTakeDamageInfo::Set( CBaseEntity *pInflictor, CBaseEntity *pAttacker, CBaseEntity *pWeapon, float flDamage, int bitsDamageType, int iKillType ) -{ - Init( pInflictor, pAttacker, pWeapon, vec3_origin, vec3_origin, vec3_origin, flDamage, bitsDamageType, iKillType ); -} - -void CTakeDamageInfo::Set( CBaseEntity *pInflictor, CBaseEntity *pAttacker, const Vector &damageForce, const Vector &damagePosition, float flDamage, int bitsDamageType, int iKillType, Vector *reportedPosition ) -{ - Set( pInflictor, pAttacker, NULL, damageForce, damagePosition, flDamage, bitsDamageType, iKillType, reportedPosition ); -} - -void CTakeDamageInfo::Set( CBaseEntity *pInflictor, CBaseEntity *pAttacker, CBaseEntity *pWeapon, const Vector &damageForce, const Vector &damagePosition, float flDamage, int bitsDamageType, int iKillType, Vector *reportedPosition ) -{ - Vector vecReported = vec3_origin; - if ( reportedPosition ) - { - vecReported = *reportedPosition; - } - Init( pInflictor, pAttacker, pWeapon, damageForce, damagePosition, vecReported, flDamage, bitsDamageType, iKillType ); -} - -//----------------------------------------------------------------------------- -// Squirrel the damage value away as BaseDamage, which will later be used to -// calculate damage force. -//----------------------------------------------------------------------------- -void CTakeDamageInfo::AdjustPlayerDamageInflictedForSkillLevel() -{ -#ifndef CLIENT_DLL - CopyDamageToBaseDamage(); - SetDamage( g_pGameRules->AdjustPlayerDamageInflicted(GetDamage()) ); -#endif -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CTakeDamageInfo::AdjustPlayerDamageTakenForSkillLevel() -{ -#ifndef CLIENT_DLL - CopyDamageToBaseDamage(); - g_pGameRules->AdjustPlayerDamageTaken(this); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: get the name of the ammo that caused damage -// Note: returns the ammo name, or the classname of the object, or the model name in the case of physgun ammo. -//----------------------------------------------------------------------------- -const char *CTakeDamageInfo::GetAmmoName() const -{ - const char *pszAmmoType; - - if ( m_iAmmoType >= 0 ) - { - pszAmmoType = GetAmmoDef()->GetAmmoOfIndex( m_iAmmoType )->pName; - } - // no ammoType, so get the ammo name from the inflictor - else if ( m_hInflictor != NULL ) - { - pszAmmoType = m_hInflictor->GetClassname(); - - // check for physgun ammo. unfortunate that this is in game_shared. - if ( Q_strcmp( pszAmmoType, "prop_physics" ) == 0 ) - { - pszAmmoType = STRING( m_hInflictor->GetModelName() ); - } - } - else - { - pszAmmoType = "Unknown"; - } - - return pszAmmoType; -} - -// -------------------------------------------------------------------------------------------------- // -// MultiDamage -// Collects multiple small damages into a single damage -// -------------------------------------------------------------------------------------------------- // -BEGIN_SIMPLE_DATADESC_( CMultiDamage, CTakeDamageInfo ) - DEFINE_FIELD( m_hTarget, FIELD_EHANDLE), -END_DATADESC() - -CMultiDamage g_MultiDamage; - -CMultiDamage::CMultiDamage() -{ - m_hTarget = NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMultiDamage::Init( CBaseEntity *pTarget, CBaseEntity *pInflictor, CBaseEntity *pAttacker, CBaseEntity *pWeapon, const Vector &damageForce, const Vector &damagePosition, const Vector &reportedPosition, float flDamage, int bitsDamageType, int iKillType ) -{ - m_hTarget = pTarget; - BaseClass::Init( pInflictor, pAttacker, pWeapon, damageForce, damagePosition, reportedPosition, flDamage, bitsDamageType, iKillType ); -} - -//----------------------------------------------------------------------------- -// Purpose: Resets the global multi damage accumulator -//----------------------------------------------------------------------------- -void ClearMultiDamage( void ) -{ - g_MultiDamage.Init( NULL, NULL, NULL, NULL, vec3_origin, vec3_origin, vec3_origin, 0, 0, 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: inflicts contents of global multi damage register on gMultiDamage.pEntity -//----------------------------------------------------------------------------- -void ApplyMultiDamage( void ) -{ - Vector vecSpot1;//where blood comes from - Vector vecDir;//direction blood should go - trace_t tr; - - if ( !g_MultiDamage.GetTarget() ) - return; - -#ifndef CLIENT_DLL - const CBaseEntity *host = te->GetSuppressHost(); - te->SetSuppressHost( NULL ); - - g_MultiDamage.GetTarget()->TakeDamage( g_MultiDamage ); - - te->SetSuppressHost( (CBaseEntity*)host ); -#endif - - // Damage is done, clear it out - ClearMultiDamage(); -} - -//----------------------------------------------------------------------------- -// Purpose: Add damage to the existing multidamage, and apply if it won't fit -//----------------------------------------------------------------------------- -void AddMultiDamage( const CTakeDamageInfo &info, CBaseEntity *pEntity ) -{ - if ( !pEntity ) - return; - - if ( pEntity != g_MultiDamage.GetTarget() ) - { - ApplyMultiDamage(); - g_MultiDamage.Init( pEntity, info.GetInflictor(), info.GetAttacker(), info.GetWeapon(), vec3_origin, vec3_origin, vec3_origin, 0.0, info.GetDamageType(), info.GetDamageCustom() ); - } - - g_MultiDamage.AddDamageType( info.GetDamageType() ); - g_MultiDamage.SetDamage( g_MultiDamage.GetDamage() + info.GetDamage() ); - g_MultiDamage.SetDamageForce( g_MultiDamage.GetDamageForce() + info.GetDamageForce() ); - g_MultiDamage.SetDamagePosition( info.GetDamagePosition() ); - g_MultiDamage.SetReportedPosition( info.GetReportedPosition() ); - g_MultiDamage.SetMaxDamage( MAX( g_MultiDamage.GetMaxDamage(), info.GetDamage() ) ); - g_MultiDamage.SetAmmoType( info.GetAmmoType() ); - - bool bHasPhysicsForceDamage = !g_pGameRules->Damage_NoPhysicsForce( info.GetDamageType() ); - if ( bHasPhysicsForceDamage && g_MultiDamage.GetDamageType() != DMG_GENERIC ) - { - // If you hit this assert, you've called TakeDamage with a damage type that requires a physics damage - // force & position without specifying one or both of them. Decide whether your damage that's causing - // this is something you believe should impart physics force on the receiver. If it is, you need to - // setup the damage force & position inside the CTakeDamageInfo (Utility functions for this are in - // takedamageinfo.cpp. If you think the damage shouldn't cause force (unlikely!) then you can set the - // damage type to DMG_GENERIC, or | DMG_CRUSH if you need to preserve the damage type for purposes of HUD display. - if ( g_MultiDamage.GetDamageForce() == vec3_origin || g_MultiDamage.GetDamagePosition() == vec3_origin ) - { - static int warningCount = 0; - if ( ++warningCount < 10 ) - { - if ( g_MultiDamage.GetDamageForce() == vec3_origin ) - { - Warning( "AddMultiDamage: g_MultiDamage.GetDamageForce() == vec3_origin\n" ); - } - - if ( g_MultiDamage.GetDamagePosition() == vec3_origin) - { - Warning( "AddMultiDamage: g_MultiDamage.GetDamagePosition() == vec3_origin\n" ); - } - } - } - } -} - - -//============================================================================================================ -// Utility functions for physics damage force calculation -//============================================================================================================ -//----------------------------------------------------------------------------- -// Purpose: Returns an impulse scale required to push an object. -// Input : flTargetMass - Mass of the target object, in kg -// flDesiredSpeed - Desired speed of the target, in inches/sec. -//----------------------------------------------------------------------------- -float ImpulseScale( float flTargetMass, float flDesiredSpeed ) -{ - return (flTargetMass * flDesiredSpeed); -} - -//----------------------------------------------------------------------------- -// Purpose: Fill out a takedamageinfo with a damage force for an explosive -//----------------------------------------------------------------------------- -void CalculateExplosiveDamageForce( CTakeDamageInfo *info, const Vector &vecDir, const Vector &vecForceOrigin, float flScale ) -{ - info->SetDamagePosition( vecForceOrigin ); - - float flClampForce = ImpulseScale( 75, 400 ); - - // Calculate an impulse large enough to push a 75kg man 4 in/sec per point of damage - float flForceScale = info->GetBaseDamage() * ImpulseScale( 75, 4 ); - - if( flForceScale > flClampForce ) - flForceScale = flClampForce; - - // Fudge blast forces a little bit, so that each - // victim gets a slightly different trajectory. - // This simulates features that usually vary from - // person-to-person variables such as bodyweight, - // which are all indentical for characters using the same model. - flForceScale *= random->RandomFloat( 0.85, 1.15 ); - - // Calculate the vector and stuff it into the takedamageinfo - Vector vecForce = vecDir; - VectorNormalize( vecForce ); - vecForce *= flForceScale; - vecForce *= phys_pushscale.GetFloat(); - vecForce *= flScale; - info->SetDamageForce( vecForce ); -} - -//----------------------------------------------------------------------------- -// Purpose: Fill out a takedamageinfo with a damage force for a bullet impact -//----------------------------------------------------------------------------- -void CalculateBulletDamageForce( CTakeDamageInfo *info, int iBulletType, const Vector &vecBulletDir, const Vector &vecForceOrigin, float flScale ) -{ - info->SetDamagePosition( vecForceOrigin ); - Vector vecForce = vecBulletDir; - VectorNormalize( vecForce ); - vecForce *= GetAmmoDef()->DamageForce( iBulletType ); - vecForce *= phys_pushscale.GetFloat(); - vecForce *= flScale; - info->SetDamageForce( vecForce ); - Assert(vecForce!=vec3_origin); -} - -//----------------------------------------------------------------------------- -// Purpose: Fill out a takedamageinfo with a damage force for a melee impact -//----------------------------------------------------------------------------- -void CalculateMeleeDamageForce( CTakeDamageInfo *info, const Vector &vecMeleeDir, const Vector &vecForceOrigin, float flScale ) -{ - info->SetDamagePosition( vecForceOrigin ); - - // Calculate an impulse large enough to push a 75kg man 4 in/sec per point of damage - float flForceScale = info->GetBaseDamage() * ImpulseScale( 75, 4 ); - Vector vecForce = vecMeleeDir; - VectorNormalize( vecForce ); - vecForce *= flForceScale; - vecForce *= phys_pushscale.GetFloat(); - vecForce *= flScale; - info->SetDamageForce( vecForce ); -} - -//----------------------------------------------------------------------------- -// Purpose: Try and guess the physics force to use. -// This shouldn't be used for any damage where the damage force is unknown. -// i.e. only use it for mapmaker specified damages. -//----------------------------------------------------------------------------- -void GuessDamageForce( CTakeDamageInfo *info, const Vector &vecForceDir, const Vector &vecForceOrigin, float flScale ) -{ - if ( info->GetDamageType() & DMG_BULLET ) - { - CalculateBulletDamageForce( info, GetAmmoDef()->Index("SMG1"), vecForceDir, vecForceOrigin, flScale ); - } - else if ( info->GetDamageType() & DMG_BLAST ) - { - CalculateExplosiveDamageForce( info, vecForceDir, vecForceOrigin, flScale ); - } - else - { - CalculateMeleeDamageForce( info, vecForceDir, vecForceOrigin, flScale ); - } -} - - -// Debug functions for printing out damage types - -// This table maps the DMG_* defines to their strings such that -// for DMG_XXX = i << x then table[i] = string for DMG_XXX - -static const char * const s_DamageTypeToStrTable[] = -{ - "GENERIC", - "CRUSH", - "BULLET", - "SLASH", - "BURN", - "VEHICLE", - "FALL", - "BLAST", - "CLUB", - "SHOCK", - "SONIC", - "ENERGYBEAM", - "PREVENT_PHYSICS_FORCE", - "NEVERGIB", - "ALWAYSGIB", - "DROWN", - "PARALYZE", - "NERVEGAS", - "POISON", - "RADIATION", - "DROWNRECOVER", - "ACID", - "SLOWBURN", - "REMOVENORAGDOLL", - "PHYSGUN", - "PLASMA", - "AIRBOAT", - "DISSOLVE", - "BLAST_SURFACE", - "DIRECT", - "BUCKSHOT" -}; -#define DAMAGE_TYPE_STR_TABLE_ENTRIES 31 // number of entries in table above - -void CTakeDamageInfo::DebugGetDamageTypeString(unsigned int damageType, char *outbuf, int outbuflength ) -{ - Assert(outbuflength > 0); - - // we need to use snprintf to actually copy out the strings here because that's the only function that returns - // how much text was output - if ( damageType == 0 ) - { - int charsWrit = Q_snprintf(outbuf, outbuflength, "%s", s_DamageTypeToStrTable[0]); - - outbuflength -= charsWrit; - outbuf += charsWrit; // advance the output pointer (now it sits on the null terminator) - } - - // loop through the other entries in the table - for (int i = 0; - outbuflength > 0 && i < (DAMAGE_TYPE_STR_TABLE_ENTRIES - 1); - ++i ) - { - if ( damageType & (1 << i) ) - { - // this bit was set. Print the corresponding entry from the table - // (the index is +1 because entry 1 in the table corresponds to 1 << 0) - int charsWrit = Q_snprintf(outbuf, outbuflength, "%s ", s_DamageTypeToStrTable[i + 1]); - - outbuflength -= charsWrit; // reduce the chars left - outbuf += charsWrit; // advance the output pointer (now it sits on the null terminator) - } - } -} - - -/* -// instant damage - -#define DMG_GENERIC 0 // generic damage was done -#define DMG_CRUSH (1 << 0) // crushed by falling or moving object. -// NOTE: It's assumed crush damage is occurring as a result of physics collision, so no extra physics force is generated by crush damage. -// DON'T use DMG_CRUSH when damaging entities unless it's the result of a physics collision. You probably want DMG_CLUB instead. -#define DMG_BULLET (1 << 1) // shot -#define DMG_SLASH (1 << 2) // cut, clawed, stabbed -#define DMG_BURN (1 << 3) // heat burned -#define DMG_VEHICLE (1 << 4) // hit by a vehicle -#define DMG_FALL (1 << 5) // fell too far -#define DMG_BLAST (1 << 6) // explosive blast damage -#define DMG_CLUB (1 << 7) // crowbar, punch, headbutt -#define DMG_SHOCK (1 << 8) // electric shock -#define DMG_SONIC (1 << 9) // sound pulse shockwave -#define DMG_ENERGYBEAM (1 << 10) // laser or other high energy beam -#define DMG_PREVENT_PHYSICS_FORCE (1 << 11) // Prevent a physics force -#define DMG_NEVERGIB (1 << 12) // with this bit OR'd in, no damage type will be able to gib victims upon death -#define DMG_ALWAYSGIB (1 << 13) // with this bit OR'd in, any damage type can be made to gib victims upon death. -#define DMG_DROWN (1 << 14) // Drowning - - -#define DMG_PARALYZE (1 << 15) // slows affected creature down -#define DMG_NERVEGAS (1 << 16) // nerve toxins, very bad -#define DMG_POISON (1 << 17) // blood poisoning - heals over time like drowning damage -#define DMG_RADIATION (1 << 18) // radiation exposure -#define DMG_DROWNRECOVER (1 << 19) // drowning recovery -#define DMG_ACID (1 << 20) // toxic chemicals or acid burns -#define DMG_SLOWBURN (1 << 21) // in an oven - -#define DMG_REMOVENORAGDOLL (1<<22) // with this bit OR'd in, no ragdoll will be created, and the target will be quietly removed. -// use this to kill an entity that you've already got a server-side ragdoll for - -#define DMG_PHYSGUN (1<<23) // Hit by manipulator. Usually doesn't do any damage. -#define DMG_PLASMA (1<<24) // Shot by Cremator -#define DMG_AIRBOAT (1<<25) // Hit by the airboat's gun - -#define DMG_DISSOLVE (1<<26) // Dissolving! -#define DMG_BLAST_SURFACE (1<<27) // A blast on the surface of water that cannot harm things underwater -#define DMG_DIRECT (1<<28) -#define DMG_BUCKSHOT (1<<29) // not quite a bullet. Little, rounder, different. -*/ diff --git a/game/shared/takedamageinfo.h b/game/shared/takedamageinfo.h deleted file mode 100644 index 1a7b84a19..000000000 --- a/game/shared/takedamageinfo.h +++ /dev/null @@ -1,351 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef TAKEDAMAGEINFO_H -#define TAKEDAMAGEINFO_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "networkvar.h" // todo: change this when DECLARE_CLASS is moved into a better location. - -// Used to initialize m_flBaseDamage to something that we know pretty much for sure -// hasn't been modified by a user. -#define BASEDAMAGE_NOT_SPECIFIED FLT_MAX - -class CBaseEntity; - - -class CTakeDamageInfo -{ -public: - DECLARE_CLASS_NOBASE( CTakeDamageInfo ); - - CTakeDamageInfo(); - CTakeDamageInfo( CBaseEntity *pInflictor, CBaseEntity *pAttacker, float flDamage, int bitsDamageType, int iKillType = 0 ); - CTakeDamageInfo( CBaseEntity *pInflictor, CBaseEntity *pAttacker, CBaseEntity *pWeapon, float flDamage, int bitsDamageType, int iKillType = 0 ); - CTakeDamageInfo( CBaseEntity *pInflictor, CBaseEntity *pAttacker, const Vector &damageForce, const Vector &damagePosition, float flDamage, int bitsDamageType, int iKillType = 0, Vector *reportedPosition = NULL ); - CTakeDamageInfo( CBaseEntity *pInflictor, CBaseEntity *pAttacker, CBaseEntity *pWeapon, const Vector &damageForce, const Vector &damagePosition, float flDamage, int bitsDamageType, int iKillType = 0, Vector *reportedPosition = NULL ); - - - // Inflictor is the weapon or rocket (or player) that is dealing the damage. - CBaseEntity* GetInflictor() const; - void SetInflictor( CBaseEntity *pInflictor ); - - // Weapon is the weapon that did the attack. - // For hitscan weapons, it'll be the same as the inflictor. For projectile weapons, the projectile - // is the inflictor, and this contains the weapon that created the projectile. - CBaseEntity* GetWeapon() const; - void SetWeapon( CBaseEntity *pWeapon ); - - // Attacker is the character who originated the attack (like a player or an AI). - CBaseEntity* GetAttacker() const; - void SetAttacker( CBaseEntity *pAttacker ); - - float GetDamage() const; - void SetDamage( float flDamage ); - float GetMaxDamage() const; - void SetMaxDamage( float flMaxDamage ); - void ScaleDamage( float flScaleAmount ); - void AddDamage( float flAddAmount ); - void SubtractDamage( float flSubtractAmount ); - - float GetBaseDamage() const; - bool BaseDamageIsValid() const; - - Vector GetDamageForce() const; - void SetDamageForce( const Vector &damageForce ); - void ScaleDamageForce( float flScaleAmount ); - - Vector GetDamagePosition() const; - void SetDamagePosition( const Vector &damagePosition ); - - Vector GetReportedPosition() const; - void SetReportedPosition( const Vector &reportedPosition ); - - int GetDamageType() const; - void SetDamageType( int bitsDamageType ); - void AddDamageType( int bitsDamageType ); - int GetDamageCustom( void ) const; - void SetDamageCustom( int iDamageCustom ); - int GetDamageStats( void ) const; - void SetDamageStats( int iDamageStats ); - - int GetAmmoType() const; - void SetAmmoType( int iAmmoType ); - const char * GetAmmoName() const; - - void Set( CBaseEntity *pInflictor, CBaseEntity *pAttacker, float flDamage, int bitsDamageType, int iKillType = 0 ); - void Set( CBaseEntity *pInflictor, CBaseEntity *pAttacker, CBaseEntity *pWeapon, float flDamage, int bitsDamageType, int iKillType = 0 ); - void Set( CBaseEntity *pInflictor, CBaseEntity *pAttacker, const Vector &damageForce, const Vector &damagePosition, float flDamage, int bitsDamageType, int iKillType = 0, Vector *reportedPosition = NULL ); - void Set( CBaseEntity *pInflictor, CBaseEntity *pAttacker, CBaseEntity *pWeapon, const Vector &damageForce, const Vector &damagePosition, float flDamage, int bitsDamageType, int iKillType = 0, Vector *reportedPosition = NULL ); - - void AdjustPlayerDamageInflictedForSkillLevel(); - void AdjustPlayerDamageTakenForSkillLevel(); - - // Given a damage type (composed of the #defines above), fill out a string with the appropriate text. - // For designer debug output. - static void DebugGetDamageTypeString(unsigned int DamageType, char *outbuf, int outbuflength ); - - -//private: - void CopyDamageToBaseDamage(); - -protected: - void Init( CBaseEntity *pInflictor, CBaseEntity *pAttacker, CBaseEntity *pWeapon, const Vector &damageForce, const Vector &damagePosition, const Vector &reportedPosition, float flDamage, int bitsDamageType, int iKillType ); - - Vector m_vecDamageForce; - Vector m_vecDamagePosition; - Vector m_vecReportedPosition; // Position players are told damage is coming from - EHANDLE m_hInflictor; - EHANDLE m_hAttacker; - EHANDLE m_hWeapon; - float m_flDamage; - float m_flMaxDamage; - float m_flBaseDamage; // The damage amount before skill leve adjustments are made. Used to get uniform damage forces. - int m_bitsDamageType; - int m_iDamageCustom; - int m_iDamageStats; - int m_iAmmoType; // AmmoType of the weapon used to cause this damage, if any - int m_iDamagedOtherPlayers; - int m_iPlayerPenetrateCount; - float m_flUnknown; - - DECLARE_SIMPLE_DATADESC(); -}; - -//----------------------------------------------------------------------------- -// Purpose: Multi damage. Used to collect multiple damages in the same frame (i.e. shotgun pellets) -//----------------------------------------------------------------------------- -class CMultiDamage : public CTakeDamageInfo -{ - DECLARE_CLASS( CMultiDamage, CTakeDamageInfo ); -public: - CMultiDamage(); - - bool IsClear( void ) { return (m_hTarget == NULL); } - CBaseEntity *GetTarget() const; - void SetTarget( CBaseEntity *pTarget ); - - void Init( CBaseEntity *pTarget, CBaseEntity *pInflictor, CBaseEntity *pAttacker, CBaseEntity *pWeapon, const Vector &damageForce, const Vector &damagePosition, const Vector &reportedPosition, float flDamage, int bitsDamageType, int iKillType ); - -protected: - EHANDLE m_hTarget; - - DECLARE_SIMPLE_DATADESC(); -}; - -extern CMultiDamage g_MultiDamage; - -// Multidamage accessors -void ClearMultiDamage( void ); -void ApplyMultiDamage( void ); -void AddMultiDamage( const CTakeDamageInfo &info, CBaseEntity *pEntity ); - -//----------------------------------------------------------------------------- -// Purpose: Utility functions for physics damage force calculation -//----------------------------------------------------------------------------- -float ImpulseScale( float flTargetMass, float flDesiredSpeed ); -void CalculateExplosiveDamageForce( CTakeDamageInfo *info, const Vector &vecDir, const Vector &vecForceOrigin, float flScale = 1.0 ); -void CalculateBulletDamageForce( CTakeDamageInfo *info, int iBulletType, const Vector &vecBulletDir, const Vector &vecForceOrigin, float flScale = 1.0 ); -void CalculateMeleeDamageForce( CTakeDamageInfo *info, const Vector &vecMeleeDir, const Vector &vecForceOrigin, float flScale = 1.0 ); -void GuessDamageForce( CTakeDamageInfo *info, const Vector &vecForceDir, const Vector &vecForceOrigin, float flScale = 1.0 ); - - -// -------------------------------------------------------------------------------------------------- // -// Inlines. -// -------------------------------------------------------------------------------------------------- // - -inline CBaseEntity* CTakeDamageInfo::GetInflictor() const -{ - return m_hInflictor; -} - - -inline void CTakeDamageInfo::SetInflictor( CBaseEntity *pInflictor ) -{ - m_hInflictor = pInflictor; -} - - -inline CBaseEntity* CTakeDamageInfo::GetAttacker() const -{ - return m_hAttacker; -} - - -inline void CTakeDamageInfo::SetAttacker( CBaseEntity *pAttacker ) -{ - m_hAttacker = pAttacker; -} - -inline CBaseEntity* CTakeDamageInfo::GetWeapon() const -{ - return m_hWeapon; -} - - -inline void CTakeDamageInfo::SetWeapon( CBaseEntity *pWeapon ) -{ - m_hWeapon = pWeapon; -} - - -inline float CTakeDamageInfo::GetDamage() const -{ - return m_flDamage; -} - -inline void CTakeDamageInfo::SetDamage( float flDamage ) -{ - m_flDamage = flDamage; -} - -inline float CTakeDamageInfo::GetMaxDamage() const -{ - return m_flMaxDamage; -} - -inline void CTakeDamageInfo::SetMaxDamage( float flMaxDamage ) -{ - m_flMaxDamage = flMaxDamage; -} - -inline void CTakeDamageInfo::ScaleDamage( float flScaleAmount ) -{ - m_flDamage *= flScaleAmount; -} - -inline void CTakeDamageInfo::AddDamage( float flAddAmount ) -{ - m_flDamage += flAddAmount; -} - -inline void CTakeDamageInfo::SubtractDamage( float flSubtractAmount ) -{ - m_flDamage -= flSubtractAmount; -} - -inline float CTakeDamageInfo::GetBaseDamage() const -{ - if( BaseDamageIsValid() ) - return m_flBaseDamage; - - // No one ever specified a base damage, so just return damage. - return m_flDamage; -} - -inline bool CTakeDamageInfo::BaseDamageIsValid() const -{ - return (m_flBaseDamage != BASEDAMAGE_NOT_SPECIFIED); -} - -inline Vector CTakeDamageInfo::GetDamageForce() const -{ - return m_vecDamageForce; -} - -inline void CTakeDamageInfo::SetDamageForce( const Vector &damageForce ) -{ - m_vecDamageForce = damageForce; -} - -inline void CTakeDamageInfo::ScaleDamageForce( float flScaleAmount ) -{ - m_vecDamageForce *= flScaleAmount; -} - -inline Vector CTakeDamageInfo::GetDamagePosition() const -{ - return m_vecDamagePosition; -} - - -inline void CTakeDamageInfo::SetDamagePosition( const Vector &damagePosition ) -{ - m_vecDamagePosition = damagePosition; -} - -inline Vector CTakeDamageInfo::GetReportedPosition() const -{ - return m_vecReportedPosition; -} - - -inline void CTakeDamageInfo::SetReportedPosition( const Vector &reportedPosition ) -{ - m_vecReportedPosition = reportedPosition; -} - -inline int CTakeDamageInfo::GetDamageType() const -{ - return m_bitsDamageType; -} - - -inline void CTakeDamageInfo::SetDamageType( int bitsDamageType ) -{ - m_bitsDamageType = bitsDamageType; -} - -inline void CTakeDamageInfo::AddDamageType( int bitsDamageType ) -{ - m_bitsDamageType |= bitsDamageType; -} - -inline int CTakeDamageInfo::GetDamageCustom() const -{ - return m_iDamageCustom; -} - -inline void CTakeDamageInfo::SetDamageCustom( int iDamageCustom ) -{ - m_iDamageCustom = iDamageCustom; -} - -inline int CTakeDamageInfo::GetDamageStats() const -{ - return m_iDamageCustom; -} - -inline void CTakeDamageInfo::SetDamageStats( int iDamageCustom ) -{ - m_iDamageCustom = iDamageCustom; -} - -inline int CTakeDamageInfo::GetAmmoType() const -{ - return m_iAmmoType; -} - -inline void CTakeDamageInfo::SetAmmoType( int iAmmoType ) -{ - m_iAmmoType = iAmmoType; -} - -inline void CTakeDamageInfo::CopyDamageToBaseDamage() -{ - m_flBaseDamage = m_flDamage; -} - - -// -------------------------------------------------------------------------------------------------- // -// Inlines. -// -------------------------------------------------------------------------------------------------- // -inline CBaseEntity *CMultiDamage::GetTarget() const -{ - return m_hTarget; -} - -inline void CMultiDamage::SetTarget( CBaseEntity *pTarget ) -{ - m_hTarget = pTarget; -} - - -#endif // TAKEDAMAGEINFO_H diff --git a/game/shared/teamplay_gamerules.cpp b/game/shared/teamplay_gamerules.cpp deleted file mode 100644 index debad8731..000000000 --- a/game/shared/teamplay_gamerules.cpp +++ /dev/null @@ -1,566 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "KeyValues.h" -#include "gamerules.h" -#include "teamplay_gamerules.h" - -#ifdef CLIENT_DLL - #include "c_baseplayer.h" - #include "c_team.h" -#else - #include "player.h" - #include "game.h" - #include "gamevars_shared.h" - #include "team.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#ifdef GAME_DLL -static char team_names[MAX_TEAMS][MAX_TEAMNAME_LENGTH]; -static int team_scores[MAX_TEAMS]; -static int num_teams = 0; - -extern bool g_fGameOver; - -REGISTER_GAMERULES_CLASS( CTeamplayRules ); - -CTeamplayRules::CTeamplayRules() -{ - m_DisableDeathMessages = false; - m_DisableDeathPenalty = false; - m_bSwitchTeams = false; - m_bScrambleTeams = false; - - memset( team_names, 0, sizeof(team_names) ); - memset( team_scores, 0, sizeof(team_scores) ); - num_teams = 0; - - // Copy over the team from the server config - m_szTeamList[0] = 0; - - RecountTeams(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRules::Precache( void ) -{ - // Call the Team Manager's precaches - for ( int i = 0; i < GetNumberOfTeams(); i++ ) - { - CTeam *pTeam = GetGlobalTeam( i ); - pTeam->Precache(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRules::Think ( void ) -{ - BaseClass::Think(); - - ///// Check game rules ///// - - if ( g_fGameOver ) // someone else quit the game already - { - BaseClass::Think(); - return; - } - - float flTimeLimit = mp_timelimit.GetFloat() * 60; - - if ( flTimeLimit != 0 && gpGlobals->curtime >= flTimeLimit ) - { - ChangeLevel(); - return; - } - - float flFragLimit = fraglimit.GetFloat(); - if ( flFragLimit ) - { - // check if any team is over the frag limit - for ( int i = 0; i < num_teams; i++ ) - { - if ( team_scores[i] >= flFragLimit ) - { - ChangeLevel(); - return; - } - } - } -} - -//========================================================= -// ClientCommand -// the user has typed a command which is unrecognized by everything else; -// this check to see if the gamerules knows anything about the command -//========================================================= -bool CTeamplayRules::ClientCommand( CBaseEntity *pEdict, const CCommand &args ) -{ - if( BaseClass::ClientCommand( pEdict, args ) ) - return true; - - if ( FStrEq( args[0], "menuselect" ) ) - { - if ( args.ArgC() < 2 ) - return true; - - //int slot = atoi( args[1] ); - - // select the item from the current menu - - return true; - } - - return false; -} - -const char *CTeamplayRules::SetDefaultPlayerTeam( CBasePlayer *pPlayer ) -{ - // copy out the team name from the model - int clientIndex = pPlayer->entindex(); - const char *team = (!pPlayer->IsNetClient())?"default":engine->GetClientConVarValue( clientIndex, "cl_team" ); - - /* TODO - - pPlayer->SetTeamName( team ); - - RecountTeams(); - - // update the current player of the team he is joining - if ( (pPlayer->TeamName())[0] == '\0' || !IsValidTeam( pPlayer->TeamName() ) || defaultteam.GetFloat() ) - { - const char *pTeamName = NULL; - - if ( defaultteam.GetFloat() ) - { - pTeamName = team_names[0]; - } - else - { - pTeamName = TeamWithFewestPlayers(); - } - pPlayer->SetTeamName( pTeamName ); - } */ - - return team; //pPlayer->TeamName(); -} - - -//========================================================= -// InitHUD -//========================================================= -void CTeamplayRules::InitHUD( CBasePlayer *pPlayer ) -{ - SetDefaultPlayerTeam( pPlayer ); - BaseClass::InitHUD( pPlayer ); - - RecountTeams(); - - /* TODO this has to be rewritten, maybe add a new USERINFO cvar "team" - const char *team = engine->GetClientConVarValue( pPlayer->entindex(), "cl_team" ); - - // update the current player of the team he is joining - char text[1024]; - if ( !strcmp( mdls, pPlayer->TeamName() ) ) - { - Q_snprintf( text,sizeof(text), "You are on team \'%s\'\n", pPlayer->TeamName() ); - } - else - { - Q_snprintf( text,sizeof(text), "You were assigned to team %s\n", pPlayer->TeamName() ); - } - - ChangePlayerTeam( pPlayer, pPlayer->TeamName(), false, false ); - if ( Q_strlen( pPlayer->TeamName() ) > 0 ) - { - UTIL_SayText( text, pPlayer ); - } - RecountTeams(); */ -} - - -void CTeamplayRules::ChangePlayerTeam( CBasePlayer *pPlayer, const char *pTeamName, bool bKill, bool bGib ) -{ - int damageFlags = DMG_GENERIC; - // int clientIndex = pPlayer->entindex(); - - if ( !bGib ) - { - damageFlags |= DMG_NEVERGIB; - } - else - { - damageFlags |= DMG_ALWAYSGIB; - } - - - // copy out the team name from the model - // pPlayer->SetTeamName( pTeamName ); -} - -//----------------------------------------------------------------------------- -// Purpose: Player has just left the game -//----------------------------------------------------------------------------- -void CTeamplayRules::ClientDisconnected( edict_t *pClient ) -{ - // Msg( "CLIENT DISCONNECTED, REMOVING FROM TEAM.\n" ); - - CBasePlayer *pPlayer = (CBasePlayer *)CBaseEntity::Instance( pClient ); - if ( pPlayer ) - { - pPlayer->SetConnected( PlayerDisconnecting ); - - // Remove the player from his team - if ( pPlayer->GetTeam() ) - { - pPlayer->ChangeTeam( 0 ); - } - } - - BaseClass::ClientDisconnected( pClient ); -} - -//========================================================= -// ClientUserInfoChanged -//========================================================= -void CTeamplayRules::ClientSettingsChanged( CBasePlayer *pPlayer ) -{ - /* TODO: handle skin, model & team changes - - char text[1024]; - - // skin/color/model changes - int iTeam = Q_atoi( engine->GetClientConVarValue( pPlayer->entindex(), "cl_team" ) ); - int iClass = Q_atoi( engine->GetClientConVarValue( pPlayer->entindex(), "cl_class" ) ); - - if ( defaultteam.GetBool() ) - { - // int clientIndex = pPlayer->entindex(); - - // engine->SetClientKeyValue( clientIndex, "model", pPlayer->TeamName() ); - // engine->SetClientKeyValue( clientIndex, "team", pPlayer->TeamName() ); - UTIL_SayText( "Not allowed to change teams in this game!\n", pPlayer ); - return; - } - - if ( defaultteam.GetFloat() || !IsValidTeam( mdls ) ) - { - // int clientIndex = pPlayer->entindex(); - - // engine->SetClientKeyValue( clientIndex, "model", pPlayer->TeamName() ); - Q_snprintf( text,sizeof(text), "Can't change team to \'%s\'\n", mdls ); - UTIL_SayText( text, pPlayer ); - Q_snprintf( text,sizeof(text), "Server limits teams to \'%s\'\n", m_szTeamList ); - UTIL_SayText( text, pPlayer ); - return; - } - - ChangePlayerTeam( pPlayer, mdls, true, true ); - // recound stuff - RecountTeams(); */ - - const char *pszName = engine->GetClientConVarValue( pPlayer->entindex(), "name" ); - - const char *pszOldName = pPlayer->GetPlayerName(); - - // msg everyone if someone changes their name, and it isn't the first time (changing no name to current name) - // Note, not using FStrEq so that this is case sensitive - if ( pszOldName[0] != 0 && Q_strcmp( pszOldName, pszName ) ) - { - IGameEvent * event = gameeventmanager->CreateEvent( "player_changename" ); - if ( event ) - { - event->SetInt( "userid", pPlayer->GetUserID() ); - event->SetString( "oldname", pszOldName ); - event->SetString( "newname", pszName ); - gameeventmanager->FireEvent( event ); - } - - pPlayer->SetPlayerName( pszName ); - } -} - -//========================================================= -// Deathnotice. -//========================================================= -void CTeamplayRules::DeathNotice( CBasePlayer *pVictim, const CTakeDamageInfo &info ) -{ - if ( m_DisableDeathMessages ) - return; - - CBaseEntity *pKiller = info.GetAttacker(); - if ( pVictim && pKiller && pKiller->IsPlayer() ) - { - CBasePlayer *pk = (CBasePlayer*)pKiller; - - if ( pk ) - { - if ( (pk != pVictim) && (PlayerRelationship( pVictim, pk ) == GR_TEAMMATE) ) - { - IGameEvent * event = gameeventmanager->CreateEvent( "player_death" ); - if ( event ) - { - event->SetInt("killer", pk->GetUserID() ); - event->SetInt("victim", pVictim->GetUserID() ); - event->SetInt("priority", 7 ); // HLTV event priority, not transmitted - - gameeventmanager->FireEvent( event ); - } - return; - } - } - } - - BaseClass::DeathNotice( pVictim, info ); -} - -//========================================================= -//========================================================= -void CTeamplayRules::PlayerKilled( CBasePlayer *pVictim, const CTakeDamageInfo &info ) -{ - if ( !m_DisableDeathPenalty ) - { - BaseClass::PlayerKilled( pVictim, info ); - RecountTeams(); - } -} - - -//========================================================= -// IsTeamplay -//========================================================= -bool CTeamplayRules::IsTeamplay( void ) -{ - return true; -} - -bool CTeamplayRules::FPlayerCanTakeDamage( CBasePlayer *pPlayer, CBaseEntity *pAttacker ) -{ - if ( pAttacker && PlayerRelationship( pPlayer, pAttacker ) == GR_TEAMMATE ) - { - // my teammate hit me. - if ( (friendlyfire.GetInt() == 0) && (pAttacker != pPlayer) ) - { - // friendly fire is off, and this hit came from someone other than myself, then don't get hurt - return false; - } - } - - return BaseClass::FPlayerCanTakeDamage( pPlayer, pAttacker ); -} - -//========================================================= -//========================================================= -int CTeamplayRules::PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget ) -{ - // half life multiplay has a simple concept of Player Relationships. - // you are either on another player's team, or you are not. - if ( !pPlayer || !pTarget || !pTarget->IsPlayer() ) - return GR_NOTTEAMMATE; - - if ( (*GetTeamID(pPlayer) != '\0') && (*GetTeamID(pTarget) != '\0') && !stricmp( GetTeamID(pPlayer), GetTeamID(pTarget) ) ) - { - return GR_TEAMMATE; - } - - return GR_NOTTEAMMATE; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pListener - -// *pSpeaker - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CTeamplayRules::PlayerCanHearChat( CBasePlayer *pListener, CBasePlayer *pSpeaker ) -{ - return ( PlayerRelationship( pListener, pSpeaker ) == GR_TEAMMATE ); -} - -//========================================================= -//========================================================= -bool CTeamplayRules::ShouldAutoAim( CBasePlayer *pPlayer, edict_t *target ) -{ - // always autoaim, unless target is a teammate - CBaseEntity *pTgt = CBaseEntity::Instance( target ); - if ( pTgt && pTgt->IsPlayer() ) - { - if ( PlayerRelationship( pPlayer, pTgt ) == GR_TEAMMATE ) - return false; // don't autoaim at teammates - } - - return BaseClass::ShouldAutoAim( pPlayer, target ); -} - -//========================================================= -//========================================================= -int CTeamplayRules::IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *pKilled ) -{ - if ( !pKilled ) - return 0; - - if ( !pAttacker ) - return 1; - - if ( pAttacker != pKilled && PlayerRelationship( pAttacker, pKilled ) == GR_TEAMMATE ) - return -1; - - return 1; -} - -//========================================================= -//========================================================= -const char *CTeamplayRules::GetTeamID( CBaseEntity *pEntity ) -{ - if ( pEntity == NULL || pEntity->edict() == NULL ) - return ""; - - // return their team name - return pEntity->TeamID(); -} - - -int CTeamplayRules::GetTeamIndex( const char *pTeamName ) -{ - if ( pTeamName && *pTeamName != 0 ) - { - // try to find existing team - for ( int tm = 0; tm < num_teams; tm++ ) - { - if ( !stricmp( team_names[tm], pTeamName ) ) - return tm; - } - } - - return -1; // No match -} - - -const char *CTeamplayRules::GetIndexedTeamName( int teamIndex ) -{ - if ( teamIndex < 0 || teamIndex >= num_teams ) - return ""; - - return team_names[ teamIndex ]; -} - - -bool CTeamplayRules::IsValidTeam( const char *pTeamName ) -{ - if ( !m_teamLimit ) // Any team is valid if the teamlist isn't set - return true; - - return ( GetTeamIndex( pTeamName ) != -1 ) ? true : false; -} - -const char *CTeamplayRules::TeamWithFewestPlayers( void ) -{ - int i; - int minPlayers = MAX_TEAMS; - int teamCount[ MAX_TEAMS ]; - char *pTeamName = NULL; - - memset( teamCount, 0, MAX_TEAMS * sizeof(int) ); - - // loop through all clients, count number of players on each team - for ( i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBaseEntity *plr = UTIL_PlayerByIndex( i ); - - if ( plr ) - { - int team = GetTeamIndex( plr->TeamID() ); - if ( team >= 0 ) - teamCount[team] ++; - } - } - - // Find team with least players - for ( i = 0; i < num_teams; i++ ) - { - if ( teamCount[i] < minPlayers ) - { - minPlayers = teamCount[i]; - pTeamName = team_names[i]; - } - } - - return pTeamName; -} - - -//========================================================= -//========================================================= -void CTeamplayRules::RecountTeams( void ) -{ - char *pName; - char teamlist[TEAMPLAY_TEAMLISTLENGTH]; - - // loop through all teams, recounting everything - num_teams = 0; - - // Copy all of the teams from the teamlist - // make a copy because strtok is destructive - Q_strncpy( teamlist, m_szTeamList, sizeof(teamlist) ); - pName = teamlist; - pName = strtok( pName, ";" ); - while ( pName != NULL && *pName ) - { - if ( GetTeamIndex( pName ) < 0 ) - { - Q_strncpy( team_names[num_teams], pName, sizeof(team_names[num_teams])); - num_teams++; - } - pName = strtok( NULL, ";" ); - } - - if ( num_teams < 2 ) - { - num_teams = 0; - m_teamLimit = false; - } - - // Sanity check - memset( team_scores, 0, sizeof(team_scores) ); - - // loop through all clients - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBasePlayer *plr = UTIL_PlayerByIndex( i ); - - if ( plr ) - { - const char *pTeamName = plr->TeamID(); - // try add to existing team - int tm = GetTeamIndex( pTeamName ); - - if ( tm < 0 ) // no team match found - { - if ( !m_teamLimit ) - { - // add to new team - tm = num_teams; - num_teams++; - team_scores[tm] = 0; - Q_strncpy( team_names[tm], pTeamName, MAX_TEAMNAME_LENGTH ); - } - } - - if ( tm >= 0 ) - { - team_scores[tm] += plr->FragCount(); - } - } - } -} -#endif // GAME_DLL diff --git a/game/shared/teamplay_gamerules.h b/game/shared/teamplay_gamerules.h deleted file mode 100644 index 16ebb0bdf..000000000 --- a/game/shared/teamplay_gamerules.h +++ /dev/null @@ -1,124 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef TEAMPLAY_GAMERULES_H -#define TEAMPLAY_GAMERULES_H -#pragma once - -#include "gamerules.h" -#include "multiplay_gamerules.h" - -#ifdef CLIENT_DLL - - #define CTeamplayRules C_TeamplayRules - -#else - - #include "takedamageinfo.h" - -#endif - - -// -// teamplay_gamerules.h -// - - -#define MAX_TEAMNAME_LENGTH 16 -#define MAX_TEAMS 32 - -#define TEAMPLAY_TEAMLISTLENGTH MAX_TEAMS*MAX_TEAMNAME_LENGTH - - -class CTeamplayRules : public CMultiplayRules -{ -public: - DECLARE_CLASS( CTeamplayRules, CMultiplayRules ); - - // Return the value of this player towards capturing a point - virtual int GetCaptureValueForPlayer( CBasePlayer *pPlayer ) { return 1; } - virtual bool TeamMayCapturePoint( int iTeam, int iPointIndex ) { return true; } - virtual bool PlayerMayCapturePoint( CBasePlayer *pPlayer, int iPointIndex, char *pszReason = NULL, int iMaxReasonLength = 0 ) { return true; } - virtual bool PlayerMayBlockPoint( CBasePlayer *pPlayer, int iPointIndex, char *pszReason = NULL, int iMaxReasonLength = 0 ) { return false; } - - // Return false if players aren't allowed to cap points at this time (i.e. in WaitingForPlayers) - virtual bool PointsMayBeCaptured( void ) { return true; } - virtual void SetLastCapPointChanged( int iIndex ) { return; } - -#ifdef CLIENT_DLL - -#else - - CTeamplayRules(); - virtual ~CTeamplayRules() {}; - - virtual void Precache( void ); - - virtual bool ClientCommand( CBaseEntity *pEdict, const CCommand &args ); - virtual void ClientSettingsChanged( CBasePlayer *pPlayer ); - virtual bool IsTeamplay( void ); - virtual bool FPlayerCanTakeDamage( CBasePlayer *pPlayer, CBaseEntity *pAttacker ); - virtual int PlayerRelationship( CBaseEntity *pPlayer, CBaseEntity *pTarget ); - virtual bool PlayerCanHearChat( CBasePlayer *pListener, CBasePlayer *pSpeaker ); - virtual const char *GetTeamID( CBaseEntity *pEntity ); - virtual bool ShouldAutoAim( CBasePlayer *pPlayer, edict_t *target ); - virtual int IPointsForKill( CBasePlayer *pAttacker, CBasePlayer *pKilled ); - virtual void InitHUD( CBasePlayer *pl ); - virtual void DeathNotice( CBasePlayer *pVictim, const CTakeDamageInfo &info ); - virtual const char *GetGameDescription( void ) { return "Teamplay"; } // this is the game name that gets seen in the server browser - virtual void PlayerKilled( CBasePlayer *pVictim, const CTakeDamageInfo &info ); - virtual void Think ( void ); - virtual int GetTeamIndex( const char *pTeamName ); - virtual const char *GetIndexedTeamName( int teamIndex ); - virtual bool IsValidTeam( const char *pTeamName ); - virtual const char *SetDefaultPlayerTeam( CBasePlayer *pPlayer ); - virtual void ChangePlayerTeam( CBasePlayer *pPlayer, const char *pTeamName, bool bKill, bool bGib ); - virtual void ClientDisconnected( edict_t *pClient ); - virtual bool TimerMayExpire( void ) { return true; } - - // A game has been won by the specified team - virtual void SetWinningTeam( int team, int iWinReason, bool bForceMapReset = true, bool bSwitchTeams = false, bool bDontAddScore = false ) { return; } - virtual void SetStalemate( int iReason, bool bForceMapReset = true, bool bSwitchTeams = false ) { return; } - - // Used to determine if all players should switch teams - virtual void SetSwitchTeams( bool bSwitch ){ m_bSwitchTeams = bSwitch; } - virtual bool ShouldSwitchTeams( void ){ return m_bSwitchTeams; } - virtual void HandleSwitchTeams( void ){ return; } - - // Used to determine if we should scramble the teams - virtual void SetScrambleTeams( bool bScramble ){ m_bScrambleTeams = bScramble; } - virtual bool ShouldScrambleTeams( void ){ return m_bScrambleTeams; } - virtual void HandleScrambleTeams( void ){ return; } - -protected: - bool m_DisableDeathMessages; - -private: - void RecountTeams( void ); - const char *TeamWithFewestPlayers( void ); - - bool m_DisableDeathPenalty; - bool m_teamLimit; // This means the server set only some teams as valid - char m_szTeamList[TEAMPLAY_TEAMLISTLENGTH]; - bool m_bSwitchTeams; - bool m_bScrambleTeams; - -#endif -}; - -inline CTeamplayRules* TeamplayGameRules() -{ - return static_cast(g_pGameRules); -} - -#endif // TEAMPLAY_GAMERULES_H diff --git a/game/shared/teamplay_round_timer.cpp b/game/shared/teamplay_round_timer.cpp deleted file mode 100644 index 06dbde550..000000000 --- a/game/shared/teamplay_round_timer.cpp +++ /dev/null @@ -1,1350 +0,0 @@ -//========= Copyright © 1996-2006, Valve Corporation, All rights reserved. ============// -// -// Purpose: Team gamerules round timer -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "teamplay_round_timer.h" -#include "teamplayroundbased_gamerules.h" - -#ifdef CLIENT_DLL -#include "IClientMode.h" -#include "vgui_controls/AnimationController.h" -#include "c_playerresource.h" -#include "c_team_objectiveresource.h" -#else -#include "team.h" -#include "team_objectiveresource.h" -#endif - -#define ROUND_TIMER_60SECS "Announcer.RoundEnds60seconds" -#define ROUND_TIMER_30SECS "Announcer.RoundEnds30seconds" -#define ROUND_TIMER_10SECS "Announcer.RoundEnds10seconds" -#define ROUND_TIMER_5SECS "Announcer.RoundEnds5seconds" -#define ROUND_TIMER_4SECS "Announcer.RoundEnds4seconds" -#define ROUND_TIMER_3SECS "Announcer.RoundEnds3seconds" -#define ROUND_TIMER_2SECS "Announcer.RoundEnds2seconds" -#define ROUND_TIMER_1SECS "Announcer.RoundEnds1seconds" - -#define ROUND_SETUP_60SECS "Announcer.RoundBegins60Seconds" -#define ROUND_SETUP_30SECS "Announcer.RoundBegins30Seconds" -#define ROUND_SETUP_10SECS "Announcer.RoundBegins10Seconds" -#define ROUND_SETUP_5SECS "Announcer.RoundBegins5Seconds" -#define ROUND_SETUP_4SECS "Announcer.RoundBegins4Seconds" -#define ROUND_SETUP_3SECS "Announcer.RoundBegins3Seconds" -#define ROUND_SETUP_2SECS "Announcer.RoundBegins2Seconds" -#define ROUND_SETUP_1SECS "Announcer.RoundBegins1Seconds" - -#define ROUND_START_BELL "Ambient.Siren" - -#define ROUND_TIMER_TIME_ADDED "Announcer.TimeAdded" -#define ROUND_TIMER_TIME_ADDED_LOSER "Announcer.TimeAddedForEnemy" -#define ROUND_TIMER_TIME_ADDED_WINNER "Announcer.TimeAwardedForTeam" - -enum -{ - RT_THINK_SETUP, - RT_THINK_NORMAL, -}; - -enum -{ - RT_WARNING_60SECS, - RT_WARNING_30SECS, - RT_WARNING_10SECS, - RT_WARNING_5SECS, - RT_WARNING_4SECS, - RT_WARNING_3SECS, - RT_WARNING_2SECS, - RT_WARNING_1SECS, - RT_WARNING_TIME_START, -}; - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern bool IsInCommentaryMode(); - -#ifdef CLIENT_DLL - -// Use this proxy to flash the round timer whenever the timer is restarted -// because trapping the round start event doesn't work ( the event also flushes -// all hud events and obliterates our TimerFlash event ) -static void RecvProxy_TimerPaused( const CRecvProxyData *pData, void *pStruct, void *pOut ) -{ - CTeamRoundTimer *pTimer = (CTeamRoundTimer *) pStruct; - - bool bTimerPaused = ( pData->m_Value.m_Int > 0 ); - - if ( bTimerPaused == false ) - { - g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "TimerFlash" ); - } - - if ( pTimer ) - { - pTimer->InternalSetPaused( bTimerPaused ); - } -} - -#endif - -LINK_ENTITY_TO_CLASS( team_round_timer, CTeamRoundTimer ); - -IMPLEMENT_NETWORKCLASS_ALIASED( TeamRoundTimer, DT_TeamRoundTimer ) - -BEGIN_NETWORK_TABLE_NOBASE( CTeamRoundTimer, DT_TeamRoundTimer ) -#ifdef CLIENT_DLL - - RecvPropInt( RECVINFO( m_bTimerPaused ), 0, RecvProxy_TimerPaused ), - RecvPropTime( RECVINFO( m_flTimeRemaining ) ), - RecvPropTime( RECVINFO( m_flTimerEndTime ) ), - RecvPropInt( RECVINFO( m_nTimerMaxLength ) ), - RecvPropBool( RECVINFO( m_bIsDisabled ) ), - RecvPropBool( RECVINFO( m_bShowInHUD ) ), - RecvPropInt( RECVINFO( m_nTimerLength ) ), - RecvPropInt( RECVINFO( m_nTimerInitialLength ) ), - RecvPropBool( RECVINFO( m_bAutoCountdown ) ), - RecvPropInt( RECVINFO( m_nSetupTimeLength ) ), - RecvPropInt( RECVINFO( m_nState ) ), - RecvPropBool( RECVINFO( m_bStartPaused ) ), - RecvPropBool( RECVINFO( m_bInCaptureWatchState ) ), - RecvPropBool( RECVINFO( m_bStopWatchTimer ) ), - RecvPropTime( RECVINFO( m_flTotalTime ) ), - -#else - - SendPropBool( SENDINFO( m_bTimerPaused ) ), - SendPropTime( SENDINFO( m_flTimeRemaining ) ), - SendPropTime( SENDINFO( m_flTimerEndTime ) ), - SendPropInt( SENDINFO( m_nTimerMaxLength ) ), - SendPropBool( SENDINFO( m_bIsDisabled ) ), - SendPropBool( SENDINFO( m_bShowInHUD ) ), - SendPropInt( SENDINFO( m_nTimerLength ) ), - SendPropInt( SENDINFO( m_nTimerInitialLength ) ), - SendPropBool( SENDINFO( m_bAutoCountdown ) ), - SendPropInt( SENDINFO( m_nSetupTimeLength ) ), - SendPropInt( SENDINFO( m_nState ) ), - SendPropBool( SENDINFO( m_bStartPaused ) ), - SendPropBool( SENDINFO( m_bStopWatchTimer ) ), - SendPropBool( SENDINFO( m_bInCaptureWatchState ) ), - SendPropTime( SENDINFO( m_flTotalTime ) ), - -#endif -END_NETWORK_TABLE() - -#ifndef CLIENT_DLL -BEGIN_DATADESC(CTeamRoundTimer) - DEFINE_KEYFIELD( m_nTimerInitialLength, FIELD_INTEGER, "timer_length" ), - DEFINE_KEYFIELD( m_nTimerMaxLength, FIELD_INTEGER, "max_length" ), - DEFINE_KEYFIELD( m_bShowInHUD, FIELD_BOOLEAN, "show_in_hud" ), - DEFINE_KEYFIELD( m_bIsDisabled, FIELD_BOOLEAN, "StartDisabled" ), - DEFINE_KEYFIELD( m_bAutoCountdown, FIELD_BOOLEAN, "auto_countdown" ), - DEFINE_KEYFIELD( m_nSetupTimeLength, FIELD_INTEGER, "setup_length" ), - DEFINE_KEYFIELD( m_bResetTimeOnRoundStart, FIELD_BOOLEAN, "reset_time" ), - DEFINE_KEYFIELD( m_bStartPaused, FIELD_BOOLEAN, "start_paused" ), - - DEFINE_FUNCTION( RoundTimerSetupThink ), - DEFINE_FUNCTION( RoundTimerThink ), - - DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ), - DEFINE_INPUTFUNC( FIELD_VOID, "Pause", InputPause ), - DEFINE_INPUTFUNC( FIELD_VOID, "Resume", InputResume ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetTime", InputSetTime ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "AddTime", InputAddTime ), - DEFINE_INPUTFUNC( FIELD_VOID, "Restart", InputRestart ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "ShowInHUD", InputShowInHUD ), - DEFINE_INPUTFUNC( FIELD_VOID, "RoundSpawn", InputRoundSpawn ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "SetMaxTime", InputSetMaxTime ), - DEFINE_INPUTFUNC( FIELD_INTEGER, "AutoCountdown", InputAutoCountdown ), - DEFINE_INPUTFUNC( FIELD_STRING, "AddTeamTime", InputAddTeamTime ), - - DEFINE_OUTPUT( m_OnRoundStart, "OnRoundStart" ), - DEFINE_OUTPUT( m_OnFinished, "OnFinished" ), - DEFINE_OUTPUT( m_On5MinRemain, "On5MinRemain" ), - DEFINE_OUTPUT( m_On4MinRemain, "On4MinRemain" ), - DEFINE_OUTPUT( m_On3MinRemain, "On3MinRemain" ), - DEFINE_OUTPUT( m_On2MinRemain, "On2MinRemain" ), - DEFINE_OUTPUT( m_On1MinRemain, "On1MinRemain" ), - DEFINE_OUTPUT( m_On30SecRemain, "On30SecRemain" ), - DEFINE_OUTPUT( m_On10SecRemain, "On10SecRemain" ), - DEFINE_OUTPUT( m_On5SecRemain, "On5SecRemain" ), - DEFINE_OUTPUT( m_On4SecRemain, "On4SecRemain" ), - DEFINE_OUTPUT( m_On3SecRemain, "On3SecRemain" ), - DEFINE_OUTPUT( m_On2SecRemain, "On2SecRemain" ), - DEFINE_OUTPUT( m_On1SecRemain, "On1SecRemain" ), - DEFINE_OUTPUT( m_OnSetupStart, "OnSetupStart" ), - DEFINE_OUTPUT( m_OnSetupFinished, "OnSetupFinished" ), - -END_DATADESC(); -#endif - -#ifndef CLIENT_DLL -#define ROUND_TIMER_THINK "CTeamplayRoundTimerThink" -#define ROUND_TIMER_SETUP_THINK "CTeamplayRoundTimerSetupThink" -#endif - -//----------------------------------------------------------------------------- -// Purpose: constructor -//----------------------------------------------------------------------------- -CTeamRoundTimer::CTeamRoundTimer( void ) -{ - m_bTimerPaused = false; - m_flTimeRemaining = 0; - m_nTimerLength = 0; - m_nTimerInitialLength = 0; - m_nTimerMaxLength = 0; - m_flTimerEndTime = 0; - m_bIsDisabled = false; - m_bAutoCountdown = true; - m_nState.Set( RT_STATE_NORMAL ); // we'll assume no setup time for now - m_bStartPaused = true; - - m_bFireFinished = true; - m_bFire5MinRemain = true; - m_bFire4MinRemain = true; - m_bFire3MinRemain = true; - m_bFire2MinRemain = true; - m_bFire1MinRemain = true; - m_bFire30SecRemain = true; - m_bFire10SecRemain = true; - m_bFire5SecRemain = true; - m_bFire4SecRemain = true; - m_bFire3SecRemain = true; - m_bFire2SecRemain = true; - m_bFire1SecRemain = true; - - m_bStopWatchTimer = false; - - m_flTotalTime = 0.0f; - -#ifndef CLIENT_DLL - m_bPauseDueToWin = false; - m_bResetTimeOnRoundStart = false; - m_nTimeToUseAfterSetupFinished = 0; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: destructor -//----------------------------------------------------------------------------- -CTeamRoundTimer::~CTeamRoundTimer( void ) -{ - -} - -//----------------------------------------------------------------------------- -// Purpose: destructor -//----------------------------------------------------------------------------- -void CTeamRoundTimer::Precache( void ) -{ - PrecacheScriptSound( ROUND_TIMER_60SECS ); - PrecacheScriptSound( ROUND_TIMER_30SECS ); - PrecacheScriptSound( ROUND_TIMER_10SECS ); - PrecacheScriptSound( ROUND_TIMER_5SECS ); - PrecacheScriptSound( ROUND_TIMER_4SECS ); - PrecacheScriptSound( ROUND_TIMER_3SECS ); - PrecacheScriptSound( ROUND_TIMER_2SECS ); - PrecacheScriptSound( ROUND_TIMER_1SECS ); - PrecacheScriptSound( ROUND_SETUP_60SECS ); - PrecacheScriptSound( ROUND_SETUP_30SECS ); - PrecacheScriptSound( ROUND_SETUP_10SECS ); - PrecacheScriptSound( ROUND_SETUP_5SECS ); - PrecacheScriptSound( ROUND_SETUP_4SECS ); - PrecacheScriptSound( ROUND_SETUP_3SECS ); - PrecacheScriptSound( ROUND_SETUP_2SECS ); - PrecacheScriptSound( ROUND_SETUP_1SECS ); - PrecacheScriptSound( ROUND_TIMER_TIME_ADDED ); - PrecacheScriptSound( ROUND_TIMER_TIME_ADDED_LOSER ); - PrecacheScriptSound( ROUND_TIMER_TIME_ADDED_WINNER ); - PrecacheScriptSound( ROUND_START_BELL ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::Activate( void ) -{ - BaseClass::Activate(); - -#ifndef CLIENT_DLL - if ( m_bShowInHUD ) - { - SetActiveTimer( this ); - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::Spawn( void ) -{ - Precache(); - -#ifdef CLIENT_DLL - SetNextClientThink( CLIENT_THINK_ALWAYS ); -#else - - int nTimerTime = 0; - - // do we have a setup time? - if ( m_nSetupTimeLength > 0 ) - { - nTimerTime = m_nSetupTimeLength; - SetState( RT_STATE_SETUP ); - } - else - { - nTimerTime = m_nTimerInitialLength; - SetState( RT_STATE_NORMAL ); - } - - m_nTimeToUseAfterSetupFinished = m_nTimerInitialLength; - - if ( IsDisabled() ) // we need to get the data initialized before actually become disabled - { - m_bIsDisabled = false; - PauseTimer(); // start paused - SetTimeRemaining( nTimerTime ); - m_bIsDisabled = true; - } - else - { - PauseTimer(); // start paused - SetTimeRemaining( nTimerTime ); - } - - m_nTimerLength = nTimerTime; - - BaseClass::Spawn(); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamRoundTimer::ShowInHud( void ) -{ - return m_bShowInHUD; -} - -//----------------------------------------------------------------------------- -// Purpose: Gets the seconds left on the timer, paused or not. -//----------------------------------------------------------------------------- -float CTeamRoundTimer::GetTimeRemaining( void ) -{ - float flSecondsRemaining; - - if ( IsStopWatchTimer() == true && m_bInCaptureWatchState == true ) - { - flSecondsRemaining = m_flTotalTime; - } - else - { - if ( m_bTimerPaused ) - { - flSecondsRemaining = m_flTimeRemaining; - } - else - { - flSecondsRemaining = m_flTimerEndTime - gpGlobals->curtime; - } - } - - if ( flSecondsRemaining < 0 ) - { - flSecondsRemaining = 0.0f; - } - - return flSecondsRemaining; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::SetCaptureWatchState( bool bCaptureWatch ) -{ - m_bInCaptureWatchState = bCaptureWatch; - -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CTeamRoundTimer::GetTimerMaxLength( void ) -{ - if ( m_nState == RT_STATE_SETUP ) - { - return m_nSetupTimeLength; - } - else - { - if ( m_nTimerMaxLength ) - return m_nTimerMaxLength; - - return m_nTimerLength; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::CalculateOutputMessages( void ) -{ - float flTime = GetTimeRemaining(); - -#ifndef GAME_DLL - // We need to add a couple seconds to the time remaining because we've probably lost ~0.5 seconds from the timer while - // waiting for the update to arrive from the server and we don't want to miss any critical countdown messages. If the time - // remaining is over 10 seconds...adding 2 seconds to the total when calculating our output messages won't affect anything - if ( flTime > 10.0f ) - { - flTime += 2.0f; - } -#endif - - m_bFireFinished = ( flTime > 0.0f ); - m_bFire5MinRemain = ( flTime >= 300.0f ); - m_bFire4MinRemain = ( flTime >= 240.0f ); - m_bFire3MinRemain = ( flTime >= 180.0f ); - m_bFire2MinRemain = ( flTime >= 120.0f ); - m_bFire1MinRemain = ( flTime >= 60.0f ); - m_bFire30SecRemain = ( flTime >= 30.0f ); - m_bFire10SecRemain = ( flTime >= 10.0f ); - m_bFire5SecRemain = ( flTime >= 5.0f ); - m_bFire4SecRemain = ( flTime >= 4.0f ); - m_bFire3SecRemain = ( flTime >= 3.0f ); - m_bFire2SecRemain = ( flTime >= 2.0f ); - m_bFire1SecRemain = ( flTime >= 1.0f ); -} - -#ifdef CLIENT_DLL - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::ClientThink() -{ - if ( IsDisabled() || m_bTimerPaused || IsInCommentaryMode() ) - return; - - if ( IsStopWatchTimer() == true && IsWatchingTimeStamps() == true ) - return; - - float flTime = GetTimeRemaining(); - - if ( flTime <= 61.0 && m_bFire1MinRemain ) - { - m_bFire1MinRemain = false; - SendTimeWarning( RT_WARNING_60SECS ); - } - else if ( flTime <= 31.0 && m_bFire30SecRemain ) - { - m_bFire30SecRemain = false; - SendTimeWarning( RT_WARNING_30SECS ); - } - else if ( flTime <= 11.0 && m_bFire10SecRemain ) - { - m_bFire10SecRemain = false; - SendTimeWarning( RT_WARNING_10SECS ); - } - else if ( flTime <= 6.0 && m_bFire5SecRemain ) - { - m_bFire5SecRemain = false; - SendTimeWarning( RT_WARNING_5SECS ); - } - else if ( flTime <= 5.0 && m_bFire4SecRemain ) - { - m_bFire4SecRemain = false; - SendTimeWarning( RT_WARNING_4SECS ); - } - else if ( flTime <= 4.0 && m_bFire3SecRemain ) - { - m_bFire3SecRemain = false; - SendTimeWarning( RT_WARNING_3SECS ); - } - else if ( flTime <= 3.0 && m_bFire2SecRemain ) - { - m_bFire2SecRemain = false; - SendTimeWarning( RT_WARNING_2SECS ); - } - else if ( flTime <= 2.0 && m_bFire1SecRemain ) - { - m_bFire1SecRemain = false; - SendTimeWarning( RT_WARNING_1SECS ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::OnPreDataChanged( DataUpdateType_t updateType ) -{ - BaseClass::OnPreDataChanged( updateType ); - - m_nOldTimerLength = m_nTimerLength; - m_nOldTimerState = m_nState; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::OnDataChanged( DataUpdateType_t updateType ) -{ - BaseClass::OnDataChanged( updateType ); - - if ( m_nOldTimerLength != m_nTimerLength ) - { - // recalculate our output messages because the timer length has changed - CalculateOutputMessages(); - } - - // if we were in state_setup and now we're in state_normal, play the bell sound - if ( ( m_nOldTimerState == RT_STATE_SETUP ) && ( m_nState == RT_STATE_NORMAL ) ) - { - SendTimeWarning( RT_WARNING_TIME_START ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -const char *CTeamRoundTimer::GetTimeWarningSound( int nWarning ) -{ - const char *pszRetVal; - - switch( nWarning ) - { - case RT_WARNING_60SECS: - if ( m_nState == RT_STATE_SETUP ) - { - pszRetVal = ROUND_SETUP_60SECS; - } - else - { - pszRetVal = ROUND_TIMER_60SECS; - } - break; - case RT_WARNING_30SECS: - if ( m_nState == RT_STATE_SETUP ) - { - pszRetVal = ROUND_SETUP_30SECS; - } - else - { - pszRetVal = ROUND_TIMER_30SECS; - } - break; - case RT_WARNING_10SECS: - if ( m_nState == RT_STATE_SETUP ) - { - pszRetVal = ROUND_SETUP_10SECS; - } - else - { - pszRetVal = ROUND_TIMER_10SECS; - } - break; - case RT_WARNING_5SECS: - if ( m_nState == RT_STATE_SETUP ) - { - pszRetVal = ROUND_SETUP_5SECS; - } - else - { - pszRetVal = ROUND_TIMER_5SECS; - } - break; - case RT_WARNING_4SECS: - if ( m_nState == RT_STATE_SETUP ) - { - pszRetVal = ROUND_SETUP_4SECS; - } - else - { - pszRetVal = ROUND_TIMER_4SECS; - } - break; - case RT_WARNING_3SECS: - if ( m_nState == RT_STATE_SETUP ) - { - pszRetVal = ROUND_SETUP_3SECS; - } - else - { - pszRetVal = ROUND_TIMER_3SECS; - } - break; - case RT_WARNING_2SECS: - if ( m_nState == RT_STATE_SETUP ) - { - pszRetVal = ROUND_SETUP_2SECS; - } - else - { - pszRetVal = ROUND_TIMER_2SECS; - } - break; - case RT_WARNING_1SECS: - if ( m_nState == RT_STATE_SETUP ) - { - pszRetVal = ROUND_SETUP_1SECS; - } - else - { - pszRetVal = ROUND_TIMER_1SECS; - } - break; - case RT_WARNING_TIME_START: - pszRetVal = ROUND_START_BELL; - break; - default: - pszRetVal = ""; - } - - return pszRetVal; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::SendTimeWarning( int nWarning ) -{ - // don't play sounds if the level designer has turned them off or if it's during the WaitingForPlayers time - if ( !m_bTimerPaused && m_bAutoCountdown && !TeamplayRoundBasedRules()->IsInWaitingForPlayers() ) - { - C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); - if ( pPlayer ) - { - if ( ObjectiveResource() ) - { - bool bShouldPlaySound = false; - - if ( TeamplayRoundBasedRules()->IsInTournamentMode() == true && TeamplayRoundBasedRules()->IsInStopWatch() == true ) - { - int iActiveTimer = ObjectiveResource()->GetTimerToShowInHUD(); - int iStopWatchTimer = ObjectiveResource()->GetStopWatchTimer(); - - if ( IsStopWatchTimer() == true && IsWatchingTimeStamps() == false ) - { - CTeamRoundTimer *pTimer = dynamic_cast< CTeamRoundTimer* >( ClientEntityList().GetEnt( iActiveTimer ) ); - - if ( pTimer && pTimer->IsTimerPaused() == false && pTimer->GetTimeRemaining() > GetTimeRemaining() ) - { - bShouldPlaySound = true; - } - } - else - { - CTeamRoundTimer *pStopWatch = dynamic_cast< CTeamRoundTimer* >( ClientEntityList().GetEnt( iStopWatchTimer ) ); - - if ( ObjectiveResource()->GetTimerToShowInHUD() == entindex() ) - { - if ( pStopWatch ) - { - if ( pStopWatch->IsTimerPaused() == true ) - { - bShouldPlaySound = true; - } - - if ( pStopWatch->GetTimeRemaining() > GetTimeRemaining() && pStopWatch->IsWatchingTimeStamps() == false ) - { - bShouldPlaySound = true; - } - - if ( pStopWatch->IsWatchingTimeStamps() == true ) - { - bShouldPlaySound = true; - } - } - else - { - bShouldPlaySound = true; - } - } - } - } - else - { - if( ObjectiveResource()->GetTimerToShowInHUD() == entindex()) - { - bShouldPlaySound = true; - } - } - - if ( bShouldPlaySound == true ) - { - pPlayer->EmitSound( GetTimeWarningSound( nWarning ) ); - } - } - } - } -} - -#else - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::SetState( int nState ) -{ - m_nState = nState; - - if ( nState == RT_STATE_SETUP ) - { - if ( IsStopWatchTimer() == false ) - { - TeamplayRoundBasedRules()->SetSetup( true ); - } - - SetTimerThink( RT_THINK_SETUP ); - m_OnSetupStart.FireOutput( this, this ); - } - else - { - if ( IsStopWatchTimer() == false ) - { - TeamplayRoundBasedRules()->SetSetup( false ); - } - - SetTimerThink( RT_THINK_NORMAL ); - m_OnRoundStart.FireOutput( this, this ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::SetTimerThink( int nType ) -{ - if ( nType == RT_THINK_SETUP ) - { - SetContextThink( &CTeamRoundTimer::RoundTimerSetupThink, gpGlobals->curtime + 0.05, ROUND_TIMER_SETUP_THINK ); - SetContextThink( NULL, 0, ROUND_TIMER_THINK ); - } - else - { - SetContextThink( &CTeamRoundTimer::RoundTimerThink, gpGlobals->curtime + 0.05, ROUND_TIMER_THINK ); - SetContextThink( NULL, 0, ROUND_TIMER_SETUP_THINK ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::RoundTimerSetupThink( void ) -{ - if ( TeamplayRoundBasedRules()->IsInPreMatch() == true && IsDisabled() == false ) - { - inputdata_t data; - InputDisable( data ); - m_OnSetupFinished.FireOutput( this, this ); - } - - if ( IsDisabled() || m_bTimerPaused ) - { - SetContextThink( &CTeamRoundTimer::RoundTimerSetupThink, gpGlobals->curtime + 0.05, ROUND_TIMER_SETUP_THINK ); - return; - } - - float flTime = GetTimeRemaining(); - TeamplayRoundBasedRules()->SetOvertime( false ); - - if ( flTime <= 0.0f && m_bFireFinished ) - { - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_setup_finished" ); - if ( event ) - { - gameeventmanager->FireEvent( event ); - } - - m_OnSetupFinished.FireOutput( this, this ); - m_bFireFinished = false; - - SetTimeRemaining( m_nTimeToUseAfterSetupFinished ); - SetState( RT_STATE_NORMAL ); - - if ( ShowInHud() && !TeamplayRoundBasedRules()->IsInWaitingForPlayers() ) - { - UTIL_LogPrintf( "World triggered \"Round_Setup_End\"\n" ); - } - return; - } - else if ( flTime <= 60.0 && m_bFire1MinRemain ) - { - m_On1MinRemain.FireOutput( this, this ); - m_bFire1MinRemain = false; - } - else if ( flTime <= 30.0 && m_bFire30SecRemain ) - { - m_On30SecRemain.FireOutput( this, this ); - m_bFire30SecRemain = false; - } - else if ( flTime <= 10.0 && m_bFire10SecRemain ) - { - m_On10SecRemain.FireOutput( this, this ); - m_bFire10SecRemain = false; - } - else if ( flTime <= 5.0 && m_bFire5SecRemain ) - { - m_On5SecRemain.FireOutput( this, this ); - m_bFire5SecRemain = false; - } - else if ( flTime <= 4.0 && m_bFire4SecRemain ) - { - m_On4SecRemain.FireOutput( this, this ); - m_bFire4SecRemain = false; - } - else if ( flTime <= 3.0 && m_bFire3SecRemain ) - { - m_On3SecRemain.FireOutput( this, this ); - m_bFire3SecRemain = false; - } - else if ( flTime <= 2.0 && m_bFire2SecRemain ) - { - m_On2SecRemain.FireOutput( this, this ); - m_bFire2SecRemain = false; - } - else if ( flTime <= 1.0 && m_bFire1SecRemain ) - { - m_On1SecRemain.FireOutput( this, this ); - m_bFire1SecRemain = false; - } - - SetContextThink( &CTeamRoundTimer::RoundTimerSetupThink, gpGlobals->curtime + 0.05, ROUND_TIMER_SETUP_THINK ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::RoundTimerThink( void ) -{ - if ( TeamplayRoundBasedRules()->IsInPreMatch() == true && IsDisabled() == false ) - { - inputdata_t data; - InputDisable( data ); - } - - if ( IsDisabled() || m_bTimerPaused || IsInCommentaryMode() || gpGlobals->eLoadType == MapLoad_Background ) - { - SetContextThink( &CTeamRoundTimer::RoundTimerThink, gpGlobals->curtime + 0.05, ROUND_TIMER_THINK ); - return; - } - - // Don't do anything when the game has been won or if we're loading a bugbait report - if ( TeamplayRoundBasedRules()->RoundHasBeenWon() || - TeamplayRoundBasedRules()->IsLoadingBugBaitReport() ) - { - // We want to stop timers when the round has been won, but we don't want to - // force mapmakers to deal with having to unpause it. This little hack works around that. - if ( !m_bTimerPaused ) - { - PauseTimer(); - m_bPauseDueToWin = true; - } - - SetContextThink( &CTeamRoundTimer::RoundTimerThink, gpGlobals->curtime + 0.05, ROUND_TIMER_THINK ); - return; - } - else if ( m_bPauseDueToWin ) - { - ResumeTimer(); - m_bPauseDueToWin = false; - } - - float flTime = GetTimeRemaining(); - - if ( flTime > 0 && ShowInHud() ) // is this the timer we're showing in the HUD? - { - TeamplayRoundBasedRules()->SetOvertime( false ); - } - - if ( flTime <= 0.0f && m_bFireFinished ) - { - // Allow the gamerules to prevent timer expiration (i.e. while a control point is contested) - if ( !TeamplayGameRules()->TimerMayExpire() ) - { - // we don't want the timer to keep going (negative time) - m_flTimerEndTime = gpGlobals->curtime; - - // is this the timer we're showing in the HUD? - if ( ShowInHud() ) - { - TeamplayRoundBasedRules()->SetOvertime( true ); - } - - // Think slower - SetContextThink( &CTeamRoundTimer::RoundTimerThink, gpGlobals->curtime + 1.0, ROUND_TIMER_THINK ); - return; - } - - m_OnFinished.FireOutput( this, this ); - m_bFireFinished = false; - } - else if ( flTime <= 300.0 && m_bFire5MinRemain ) - { - m_On5MinRemain.FireOutput( this, this ); - m_bFire5MinRemain = false; - } - else if ( flTime <= 240.0 && m_bFire4MinRemain ) - { - m_On4MinRemain.FireOutput( this, this ); - m_bFire4MinRemain = false; - } - else if ( flTime <= 180.0 && m_bFire3MinRemain ) - { - m_On3MinRemain.FireOutput( this, this ); - m_bFire3MinRemain = false; - } - else if ( flTime <= 120.0 && m_bFire2MinRemain ) - { - m_On2MinRemain.FireOutput( this, this ); - m_bFire2MinRemain = false; - } - else if ( flTime <= 60.0 && m_bFire1MinRemain ) - { - m_On1MinRemain.FireOutput( this, this ); - m_bFire1MinRemain = false; - } - else if ( flTime <= 30.0 && m_bFire30SecRemain ) - { - m_On30SecRemain.FireOutput( this, this ); - m_bFire30SecRemain = false; - } - else if ( flTime <= 10.0 && m_bFire10SecRemain ) - { - m_On10SecRemain.FireOutput( this, this ); - m_bFire10SecRemain = false; - } - else if ( flTime <= 5.0 && m_bFire5SecRemain ) - { - m_On5SecRemain.FireOutput( this, this ); - m_bFire5SecRemain = false; - } - else if ( flTime <= 4.0 && m_bFire4SecRemain ) - { - m_On4SecRemain.FireOutput( this, this ); - m_bFire4SecRemain = false; - } - else if ( flTime <= 3.0 && m_bFire3SecRemain ) - { - m_On3SecRemain.FireOutput( this, this ); - m_bFire3SecRemain = false; - } - else if ( flTime <= 2.0 && m_bFire2SecRemain ) - { - m_On2SecRemain.FireOutput( this, this ); - m_bFire2SecRemain = false; - } - else if ( flTime <= 1.0 && m_bFire1SecRemain ) - { - m_On1SecRemain.FireOutput( this, this ); - m_bFire1SecRemain = false; - } - - SetContextThink( &CTeamRoundTimer::RoundTimerThink, gpGlobals->curtime + 0.05, ROUND_TIMER_THINK ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::InputRoundSpawn( inputdata_t &input ) -{ - if ( !m_bResetTimeOnRoundStart && ( m_nState == RT_STATE_NORMAL ) ) - { - m_nTimeToUseAfterSetupFinished = (int)GetTimeRemaining(); - } - else - { - m_nTimeToUseAfterSetupFinished = m_nTimerInitialLength; - } - - if ( m_nSetupTimeLength > 0 ) - { - SetTimeRemaining( m_nSetupTimeLength ); - SetState( RT_STATE_SETUP ); - - if ( ShowInHud() && !TeamplayRoundBasedRules()->IsInWaitingForPlayers() ) - { - UTIL_LogPrintf( "World triggered \"Round_Setup_Begin\"\n" ); - } - } - else - { - SetTimeRemaining( m_nTimeToUseAfterSetupFinished ); - SetState( RT_STATE_NORMAL ); - } - - if ( !m_bStartPaused && !TeamplayRoundBasedRules()->IsInWaitingForPlayers() ) - { - ResumeTimer(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: To set the initial timer duration -//----------------------------------------------------------------------------- -void CTeamRoundTimer::SetTimeRemaining( int iTimerSeconds ) -{ - if ( IsDisabled() ) - return; - - // make sure we don't go over our max length - if ( m_nTimerMaxLength > 0 ) - { - if ( iTimerSeconds > m_nTimerMaxLength ) - { - iTimerSeconds = m_nTimerMaxLength; - } - } - - m_flTimeRemaining = (float)iTimerSeconds; - m_flTimerEndTime = gpGlobals->curtime + m_flTimeRemaining; - m_nTimerLength = iTimerSeconds; - - CalculateOutputMessages(); -} - -//----------------------------------------------------------------------------- -// Purpose: To set the initial timer duration -//----------------------------------------------------------------------------- -void CTeamRoundTimer::SetStopWatchTimeStamp( void ) -{ - if ( IsDisabled() ) - return; - - if ( IsWatchingTimeStamps() == false ) - return; - - m_flTotalTime = m_flTotalTime + (gpGlobals->curtime - m_flTimerEndTime); - m_flTimerEndTime = gpGlobals->curtime; - - CalculateOutputMessages(); -} - -//----------------------------------------------------------------------------- -// Purpose: Timer is paused at round end, stops the countdown -//----------------------------------------------------------------------------- -void CTeamRoundTimer::PauseTimer( void ) -{ - if ( IsDisabled() ) - return; - - if ( m_bTimerPaused == false ) - { - m_bTimerPaused = true; - - m_flTimeRemaining = m_flTimerEndTime - gpGlobals->curtime; - } - - // Clear pause on win flag, because we've been set by the mapmaker - m_bPauseDueToWin = false; -} - -//----------------------------------------------------------------------------- -// Purpose: To start or re-start the timer after a pause -//----------------------------------------------------------------------------- -void CTeamRoundTimer::ResumeTimer( void ) -{ - if ( IsDisabled() ) - return; - - if ( m_bTimerPaused == true ) - { - m_bTimerPaused = false; - - if ( IsStopWatchTimer() == true && m_bInCaptureWatchState == true ) - { - m_flTimerEndTime = gpGlobals->curtime; - } - else - { - m_flTimerEndTime = gpGlobals->curtime + m_flTimeRemaining; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Add seconds to the timer while it is running or paused -//----------------------------------------------------------------------------- -void CTeamRoundTimer::AddTimerSeconds( int iSecondsToAdd, int iTeamResponsible /* = TEAM_UNASSIGNED*/ ) -{ - if ( IsDisabled() ) - return; - - if ( TeamplayRoundBasedRules()->InStalemate() ) - return; - - // we only want to add time if we're round_running or team_win so the control points - // don't add time when they try to set their default owner when the map is first loading - if ( TeamplayRoundBasedRules()->State_Get() != GR_STATE_RND_RUNNING && TeamplayRoundBasedRules()->State_Get() != GR_STATE_TEAM_WIN ) - return; - - if ( m_nTimerMaxLength > 0 ) - { - // will adding this many seconds push us over our max length? - if ( GetTimeRemaining() + iSecondsToAdd > m_nTimerMaxLength ) - { - // adjust to only add up to our max length - iSecondsToAdd = (int)(m_nTimerMaxLength - GetTimeRemaining()); - } - } - - if ( m_bTimerPaused ) - { - m_flTimeRemaining += (float)iSecondsToAdd; - } - else - { - m_flTimerEndTime += (float)iSecondsToAdd; - } - - m_nTimerLength += iSecondsToAdd; - CalculateOutputMessages(); - - if ( ObjectiveResource() && ObjectiveResource()->GetTimerInHUD() == entindex() ) - { - if ( !TeamplayRoundBasedRules()->InStalemate() && !TeamplayRoundBasedRules()->RoundHasBeenWon() ) - { - if ( iTeamResponsible >= LAST_SHARED_TEAM+1 ) - { - for ( int iTeam = LAST_SHARED_TEAM+1 ; iTeam < GetNumberOfTeams(); iTeam++ ) - { - if ( iTeam == iTeamResponsible ) - { - CTeamRecipientFilter filter( iTeam, true ); - EmitSound( filter, entindex(), ROUND_TIMER_TIME_ADDED_WINNER ); - } - else - { - CTeamRecipientFilter filter( iTeam, true ); - EmitSound( filter, entindex(), ROUND_TIMER_TIME_ADDED_LOSER ); - } - } - } - else - { - CReliableBroadcastRecipientFilter filter; - EmitSound( filter, entindex(), ROUND_TIMER_TIME_ADDED ); - } - } - - // is this the timer we're showing in the HUD? - if ( m_bShowInHUD ) - { - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_timer_time_added" ); - if ( event ) - { - event->SetInt( "timer", entindex() ); - event->SetInt( "seconds_added", iSecondsToAdd ); - gameeventmanager->FireEvent( event ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: The timer is always transmitted to clients -//----------------------------------------------------------------------------- -int CTeamRoundTimer::UpdateTransmitState() -{ - // ALWAYS transmit to all clients. - return SetTransmitState( FL_EDICT_ALWAYS ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::InputPause( inputdata_t &input ) -{ - PauseTimer(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::InputResume( inputdata_t &input ) -{ - ResumeTimer(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::InputSetTime( inputdata_t &input ) -{ - if ( IsStopWatchTimer() == true && IsWatchingTimeStamps() == true ) - { - SetStopWatchTimeStamp(); - } - else - { - int nSeconds = input.value.Int(); - SetTimeRemaining( nSeconds ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::InputSetMaxTime( inputdata_t &input ) -{ - int nSeconds = input.value.Int(); - m_nTimerMaxLength = nSeconds; - - if ( m_nTimerMaxLength > 0 ) - { - // make sure our current time is not above the max length - if ( GetTimeRemaining() > m_nTimerMaxLength ) - { - SetTimeRemaining( m_nTimerMaxLength ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::InputAddTime( inputdata_t &input ) -{ - int nSeconds = input.value.Int(); - AddTimerSeconds( nSeconds ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::InputAddTeamTime( inputdata_t &input ) -{ - char token[128]; - const char *p = STRING( input.value.StringID() ); - int nTeam = TEAM_UNASSIGNED; - int nSeconds = 0; - - // get the team - p = nexttoken( token, p, ' ' ); - if ( token[0] != '\0' ) - { - nTeam = Q_atoi( token ); - } - - // get the time - p = nexttoken( token, p, ' ' ); - if ( token[0] != '\0' ) - { - nSeconds = Q_atoi( token ); - } - - if ( nSeconds != 0 ) - { - AddTimerSeconds( nSeconds, nTeam ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::InputRestart( inputdata_t &input ) -{ - SetTimeRemaining( m_nTimerInitialLength ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::InputEnable( inputdata_t &input ) -{ - m_bIsDisabled = false; - ResumeTimer(); - - if ( m_bShowInHUD ) - { - SetActiveTimer( this ); - } - - if ( IsStopWatchTimer() == true && IsWatchingTimeStamps() == true ) - { - m_flTimerEndTime = gpGlobals->curtime; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::InputDisable( inputdata_t &input ) -{ - PauseTimer(); - m_bIsDisabled = true; - - if ( m_bShowInHUD ) - { - SetActiveTimer( NULL ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::InputShowInHUD( inputdata_t &input ) -{ - int nShow = input.value.Int(); - - if ( m_bShowInHUD && !nShow ) - { - SetActiveTimer( NULL ); - } - else if ( nShow == 1 ) - { - SetActiveTimer( this ); - } - - m_bShowInHUD = ( nShow == 1 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::InputAutoCountdown( inputdata_t &input ) -{ - int nAuto = input.value.Int(); - SetAutoCountdown( nAuto == 1 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamRoundTimer::SetActiveTimer( CTeamRoundTimer *pNewlyActive ) -{ - CBaseEntity *pChosenTimer = pNewlyActive; - - // Ensure all other timers are off. - CBaseEntity *pEntity = NULL; - while ((pEntity = gEntList.FindEntityByClassname( pEntity, "team_round_timer" )) != NULL) - { - if ( pEntity == pNewlyActive ) - continue; - - CTeamRoundTimer *pTimer = assert_cast< CTeamRoundTimer* >( pEntity ); - if ( !pTimer->IsDisabled() && pTimer->ShowInHud() ) - { - if ( pChosenTimer ) - { - // Turn off all other hud timers - pTimer->SetShowInHud( false ); - } - else - { - // Found a timer. Use it. - pChosenTimer = pTimer; - } - } - } - - ObjectiveResource()->SetTimerInHUD( pChosenTimer ); -} - -#endif diff --git a/game/shared/teamplay_round_timer.h b/game/shared/teamplay_round_timer.h deleted file mode 100644 index fc1c1f4d7..000000000 --- a/game/shared/teamplay_round_timer.h +++ /dev/null @@ -1,168 +0,0 @@ -//========= Copyright 1996-2006, Valve Corporation, All rights reserved. ============// -// -// Purpose: Round timer for team gamerules -// -//=============================================================================// - -#ifndef TEAM_ROUND_TIMER_H -#define TEAM_ROUND_TIMER_H - -#ifdef _WIN32 -#pragma once -#endif - -#ifdef CLIENT_DLL -#define CTeamRoundTimer C_TeamRoundTimer -#endif - -class CTeamRoundTimer : public CBaseEntity -{ -public: - DECLARE_CLASS( CTeamRoundTimer, CBaseEntity ); - DECLARE_NETWORKCLASS(); - - CTeamRoundTimer(); - virtual ~CTeamRoundTimer(); - - virtual void Spawn( void ); - virtual void Precache( void ); - virtual void Activate( void ); - - // Returns seconds to display. - // When paused shows amount of time left once the timer is resumed - virtual float GetTimeRemaining( void ); - virtual int GetTimerMaxLength( void ); - virtual bool ShowInHud( void ); - virtual bool StartPaused( void ){ return m_bStartPaused; } - - bool IsDisabled( void ) { return m_bIsDisabled; } - int GetTimerState( void ){ return m_nState; } - - bool IsTimerPaused( void ) { return m_bTimerPaused; } - -#ifdef CLIENT_DLL - - void InternalSetPaused( bool bPaused ) { m_bTimerPaused = bPaused; } - -#else - - void SetStopWatchTimeStamp( void ); - virtual void SetTimeRemaining( int iTimerSeconds ); // Set the initial length of the timer - virtual void AddTimerSeconds( int iSecondsToAdd, int iTeamResponsible = TEAM_UNASSIGNED ); // Add time to an already running ( or paused ) timer - virtual void PauseTimer( void ); - virtual void ResumeTimer( void ); - virtual void SetAutoCountdown( bool bAuto ){ m_bAutoCountdown = bAuto; } - - void SetShowInHud( bool bShowInHUD ) { m_bShowInHUD = bShowInHUD; } - - int UpdateTransmitState(); - - void InputEnable( inputdata_t &input ); - void InputDisable( inputdata_t &input ); - void InputPause( inputdata_t &input ); - void InputResume( inputdata_t &input ); - void InputSetTime( inputdata_t &input ); - void InputAddTime( inputdata_t &input ); - void InputRestart( inputdata_t &input ); - void InputShowInHUD( inputdata_t &input ); - void InputRoundSpawn( inputdata_t &inputdata ); - void InputSetMaxTime( inputdata_t &input ); - void InputAutoCountdown( inputdata_t &input ); - void InputAddTeamTime( inputdata_t &input ); - -#endif - - void SetCaptureWatchState( bool bCaptureWatch ); - bool IsWatchingTimeStamps( void ) { return m_bInCaptureWatchState; } - void SetStopWatch( bool bState ) { m_bStopWatchTimer = bState; } - bool IsStopWatchTimer( void ) { return m_bStopWatchTimer; } - float GetStopWatchTotalTime( void ) { return m_flTotalTime; } - - -private: - void CalculateOutputMessages( void ); - -#ifdef CLIENT_DLL - virtual void ClientThink(); - void OnPreDataChanged( DataUpdateType_t updateType ); - void OnDataChanged( DataUpdateType_t updateType ); - void SendTimeWarning( int nWarning ); - const char *GetTimeWarningSound( int nWarning ); - -#else - void SetState( int nState ); - void SetTimerThink( int nType ); - void EXPORT RoundTimerThink( void ); - void EXPORT RoundTimerSetupThink( void ); - - static void SetActiveTimer( CTeamRoundTimer *pNewlyActive ); -#endif - -private: - CNetworkVar( bool, m_bTimerPaused ); - CNetworkVar( float, m_flTimeRemaining ); - CNetworkVar( float, m_flTimerEndTime ); - CNetworkVar( bool, m_bIsDisabled ); - CNetworkVar( bool, m_bShowInHUD ); - CNetworkVar( int, m_nTimerLength ); // current timer's length (used in the timer panel if no max length is set) - CNetworkVar( int, m_nTimerInitialLength ); // initial length of the timer - CNetworkVar( int, m_nTimerMaxLength ); // max time the timer can have (0 is no max) - CNetworkVar( bool, m_bAutoCountdown ); // automatically count down the end of a round - CNetworkVar( int, m_nSetupTimeLength ); // current timer's setup time length (setup time is the time before the round begins) - CNetworkVar( int, m_nState ); // RT_STATE_SETUP or RT_STATE_NORMAL - CNetworkVar( bool, m_bStartPaused ); // start the timer paused when it spawns - CNetworkVar( bool, m_bInCaptureWatchState ); - CNetworkVar( float, m_flTotalTime ); - CNetworkVar( bool, m_bStopWatchTimer ); - - bool m_bFireFinished; - bool m_bFire5MinRemain; - bool m_bFire4MinRemain; - bool m_bFire3MinRemain; - bool m_bFire2MinRemain; - bool m_bFire1MinRemain; - bool m_bFire30SecRemain; - bool m_bFire10SecRemain; - bool m_bFire5SecRemain; - bool m_bFire4SecRemain; - bool m_bFire3SecRemain; - bool m_bFire2SecRemain; - bool m_bFire1SecRemain; - -#ifdef CLIENT_DLL - - int m_nOldTimerLength; - int m_nOldTimerState; - -#else - COutputEvent m_OnRoundStart; - COutputEvent m_OnFinished; - COutputEvent m_On5MinRemain; - COutputEvent m_On4MinRemain; - COutputEvent m_On3MinRemain; - COutputEvent m_On2MinRemain; - COutputEvent m_On1MinRemain; - COutputEvent m_On30SecRemain; - COutputEvent m_On10SecRemain; - COutputEvent m_On5SecRemain; - COutputEvent m_On4SecRemain; - COutputEvent m_On3SecRemain; - COutputEvent m_On2SecRemain; - COutputEvent m_On1SecRemain; - - COutputEvent m_OnSetupStart; - COutputEvent m_OnSetupFinished; - - DECLARE_DATADESC(); - - bool m_bPauseDueToWin; - bool m_bResetTimeOnRoundStart; - int m_nTimeToUseAfterSetupFinished; -#endif -}; - -#ifdef CLIENT_DLL -extern CTeamRoundTimer *g_TeamRoundTimer; -#endif - -#endif //TEAM_ROUND_TIMER_H diff --git a/game/shared/teamplayroundbased_gamerules.cpp b/game/shared/teamplayroundbased_gamerules.cpp deleted file mode 100644 index 89f9faa3d..000000000 --- a/game/shared/teamplayroundbased_gamerules.cpp +++ /dev/null @@ -1,2705 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#include "mp_shareddefs.h" -#include "teamplayroundbased_gamerules.h" - -#ifdef CLIENT_DLL - #include "iclientmode.h" - #include - #include - #include "c_team.h" - - #define CTeam C_Team - -#else - #include "viewport_panel_names.h" - #include "team.h" - #include "mapentities.h" - #include "gameinterface.h" - #include "eventqueue.h" - #include "team_control_point_master.h" - #include "team_train_watcher.h" - #include "serverbenchmark_base.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#ifndef CLIENT_DLL -CUtlVector< CHandle > g_hControlPointMasters; - -extern bool IsInCommentaryMode( void ); -#endif - -extern ConVar spec_freeze_time; -extern ConVar spec_freeze_traveltime; - -#ifdef CLIENT_DLL -void RecvProxy_TeamplayRoundState( const CRecvProxyData *pData, void *pStruct, void *pOut ) -{ - CTeamplayRoundBasedRules *pGamerules = ( CTeamplayRoundBasedRules *)pStruct; - int iRoundState = pData->m_Value.m_Int; - pGamerules->SetRoundState( iRoundState ); -} -#endif - -BEGIN_NETWORK_TABLE_NOBASE( CTeamplayRoundBasedRules, DT_TeamplayRoundBasedRules ) -#ifdef CLIENT_DLL - RecvPropInt( RECVINFO( m_iRoundState ), 0, RecvProxy_TeamplayRoundState ), - RecvPropBool( RECVINFO( m_bInWaitingForPlayers ) ), - RecvPropInt( RECVINFO( m_iWinningTeam ) ), - RecvPropInt( RECVINFO( m_bInOvertime ) ), - RecvPropInt( RECVINFO( m_bInSetup ) ), - RecvPropInt( RECVINFO( m_bSwitchedTeamsThisRound ) ), - RecvPropBool( RECVINFO( m_bAwaitingReadyRestart ) ), - RecvPropTime( RECVINFO( m_flRestartRoundTime ) ), - RecvPropTime( RECVINFO( m_flMapResetTime ) ), - RecvPropArray3( RECVINFO_ARRAY(m_flNextRespawnWave), RecvPropTime( RECVINFO(m_flNextRespawnWave[0]) ) ), - RecvPropArray3( RECVINFO_ARRAY(m_TeamRespawnWaveTimes), RecvPropFloat( RECVINFO(m_TeamRespawnWaveTimes[0]) ) ), - RecvPropArray3( RECVINFO_ARRAY(m_bTeamReady), RecvPropBool( RECVINFO(m_bTeamReady[0]) ) ), - RecvPropBool( RECVINFO( m_bStopWatch ) ), - -#else - SendPropInt( SENDINFO( m_iRoundState ), 5 ), - SendPropBool( SENDINFO( m_bInWaitingForPlayers ) ), - SendPropInt( SENDINFO( m_iWinningTeam ), 3, SPROP_UNSIGNED ), - SendPropBool( SENDINFO( m_bInOvertime ) ), - SendPropBool( SENDINFO( m_bInSetup ) ), - SendPropBool( SENDINFO( m_bSwitchedTeamsThisRound ) ), - SendPropBool( SENDINFO( m_bAwaitingReadyRestart ) ), - SendPropTime( SENDINFO( m_flRestartRoundTime ) ), - SendPropTime( SENDINFO( m_flMapResetTime ) ), - SendPropArray3( SENDINFO_ARRAY3(m_flNextRespawnWave), SendPropTime( SENDINFO_ARRAY(m_flNextRespawnWave) ) ), - SendPropArray3( SENDINFO_ARRAY3(m_TeamRespawnWaveTimes), SendPropFloat( SENDINFO_ARRAY(m_TeamRespawnWaveTimes) ) ), - SendPropArray3( SENDINFO_ARRAY3(m_bTeamReady), SendPropBool( SENDINFO_ARRAY(m_bTeamReady) ) ), - SendPropBool( SENDINFO( m_bStopWatch ) ), -#endif -END_NETWORK_TABLE() - -IMPLEMENT_NETWORKCLASS_ALIASED( TeamplayRoundBasedRulesProxy, DT_TeamplayRoundBasedRulesProxy ) - -#ifdef CLIENT_DLL -void RecvProxy_TeamplayRoundBasedRules( const RecvProp *pProp, void **pOut, void *pData, int objectID ) -{ - CTeamplayRoundBasedRules *pRules = dynamic_cast( GameRules() ); - Assert( pRules ); - *pOut = pRules; -} - -BEGIN_RECV_TABLE( CTeamplayRoundBasedRulesProxy, DT_TeamplayRoundBasedRulesProxy ) - RecvPropDataTable( "teamplayroundbased_gamerules_data", 0, 0, &REFERENCE_RECV_TABLE( DT_TeamplayRoundBasedRules ), RecvProxy_TeamplayRoundBasedRules ) -END_RECV_TABLE() - -void CTeamplayRoundBasedRulesProxy::OnPreDataChanged( DataUpdateType_t updateType ) -{ - BaseClass::OnPreDataChanged( updateType ); - // Reroute data changed calls to the non-entity gamerules - CTeamplayRoundBasedRules *pRules = dynamic_cast( GameRules() ); - Assert( pRules ); - pRules->OnPreDataChanged(updateType); -} -void CTeamplayRoundBasedRulesProxy::OnDataChanged( DataUpdateType_t updateType ) -{ - BaseClass::OnDataChanged( updateType ); - // Reroute data changed calls to the non-entity gamerules - CTeamplayRoundBasedRules *pRules = dynamic_cast( GameRules() ); - Assert( pRules ); - pRules->OnDataChanged(updateType); -} - -#else -void* SendProxy_TeamplayRoundBasedRules( const SendProp *pProp, const void *pStructBase, const void *pData, CSendProxyRecipients *pRecipients, int objectID ) -{ - CTeamplayRoundBasedRules *pRules = dynamic_cast( GameRules() ); - Assert( pRules ); - pRecipients->SetAllRecipients(); - return pRules; -} - -BEGIN_SEND_TABLE( CTeamplayRoundBasedRulesProxy, DT_TeamplayRoundBasedRulesProxy ) - SendPropDataTable( "teamplayroundbased_gamerules_data", 0, &REFERENCE_SEND_TABLE( DT_TeamplayRoundBasedRules ), SendProxy_TeamplayRoundBasedRules ) -END_SEND_TABLE() - -BEGIN_DATADESC( CTeamplayRoundBasedRulesProxy ) - // Inputs. - DEFINE_INPUTFUNC( FIELD_BOOLEAN, "SetStalemateOnTimelimit", InputSetStalemateOnTimelimit ), -END_DATADESC() - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRulesProxy::InputSetStalemateOnTimelimit( inputdata_t &inputdata ) -{ - TeamplayRoundBasedRules()->SetStalemateOnTimelimit( inputdata.value.Bool() ); -} -#endif - -ConVar mp_capstyle( "mp_capstyle", "1", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Sets the style of capture points used. 0 = Fixed players required to cap. 1 = More players cap faster, but longer cap times." ); -ConVar mp_blockstyle( "mp_blockstyle", "1", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Sets the style of capture point blocking used. 0 = Blocks break captures completely. 1 = Blocks only pause captures." ); -ConVar mp_respawnwavetime( "mp_respawnwavetime", "10.0", FCVAR_NOTIFY | FCVAR_REPLICATED, "Time between respawn waves." ); -ConVar mp_capdeteriorate_time( "mp_capdeteriorate_time", "90.0", FCVAR_REPLICATED | FCVAR_DEVELOPMENTONLY, "Time it takes for a full capture point to deteriorate." ); -ConVar mp_tournament ( "mp_tournament", "0", FCVAR_REPLICATED | FCVAR_NOTIFY ); - -ConVar mp_teams_unbalance_limit( "mp_teams_unbalance_limit", "1", FCVAR_REPLICATED | FCVAR_NOTIFY, - "Teams are unbalanced when one team has this many more players than the other team. (0 disables check)", - true, 0, // min value - true, 30 // max value - ); - -ConVar mp_maxrounds( "mp_maxrounds", "0", FCVAR_REPLICATED | FCVAR_NOTIFY, "max number of rounds to play before server changes maps", true, 0, false, 0 ); -ConVar mp_winlimit( "mp_winlimit", "0", FCVAR_REPLICATED | FCVAR_NOTIFY, "Max score one team can reach before server changes maps", true, 0, false, 0 ); -ConVar mp_disable_respawn_times( "mp_disable_respawn_times", "0", FCVAR_NOTIFY | FCVAR_REPLICATED ); - -#ifdef GAME_DLL -ConVar mp_showroundtransitions( "mp_showroundtransitions", "0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "Show gamestate round transitions." ); -ConVar mp_enableroundwaittime( "mp_enableroundwaittime", "1", FCVAR_REPLICATED, "Enable timers to wait between rounds." ); -ConVar mp_showcleanedupents( "mp_showcleanedupents", "0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "Show entities that are removed on round respawn." ); -ConVar mp_bonusroundtime( "mp_bonusroundtime", "15", FCVAR_REPLICATED, "Time after round win until round restarts", true, 5, true, 15 ); -ConVar mp_restartround( "mp_restartround", "0", FCVAR_GAMEDLL, "If non-zero, the current round will restart in the specified number of seconds" ); - -ConVar mp_stalemate_timelimit( "mp_stalemate_timelimit", "240", FCVAR_REPLICATED, "Timelimit (in seconds) of the stalemate round." ); -ConVar mp_autoteambalance( "mp_autoteambalance", "1", FCVAR_NOTIFY ); - -ConVar mp_stalemate_enable( "mp_stalemate_enable", "0", FCVAR_NOTIFY, "Enable/Disable stalemate mode." ); -ConVar mp_stalemate_at_timelimit( "mp_stalemate_at_timelimit", "0", FCVAR_NOTIFY, "Allow the match to end when mp_timelimit hits instead of waiting for the end of the current round." ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void cc_SwitchTeams( const CCommand& args ) -{ - if ( UTIL_IsCommandIssuedByServerAdmin() ) - { - CTeamplayRoundBasedRules *pRules = dynamic_cast( GameRules() ); - - if ( pRules ) - { - pRules->SetSwitchTeams( true ); - mp_restartgame.SetValue( 5 ); - pRules->ShouldResetScores( false, false ); - pRules->ShouldResetRoundsPlayed( false ); - } - } -} - -static ConCommand mp_switchteams( "mp_switchteams", cc_SwitchTeams, "Switch teams and restart the game" ); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void cc_ScrambleTeams( const CCommand& args ) -{ - if ( UTIL_IsCommandIssuedByServerAdmin() ) - { - CTeamplayRoundBasedRules *pRules = dynamic_cast( GameRules() ); - - if ( pRules ) - { - pRules->SetScrambleTeams( true ); - mp_restartgame.SetValue( 5 ); - pRules->ShouldResetScores( true, false ); - } - } -} - -static ConCommand mp_scrambleteams( "mp_scrambleteams", cc_ScrambleTeams, "Scramble the teams and restart the game" ); - -// Classnames of entities that are preserved across round restarts -static const char *s_PreserveEnts[] = -{ - "player", - "viewmodel", - "worldspawn", - "soundent", - "ai_network", - "ai_hint", - "env_soundscape", - "env_soundscape_proxy", - "env_soundscape_triggerable", - "env_sprite", - "env_sun", - "env_wind", - "env_fog_controller", - "func_wall", - "func_illusionary", - "info_node", - "info_target", - "info_node_hint", - "point_commentary_node", - "point_viewcontrol", - "func_precipitation", - "func_team_wall", - "shadow_control", - "sky_camera", - "scene_manager", - "trigger_soundscape", - "commentary_auto", - "point_commentary_node", - "point_commentary_viewpoint", - "", // END Marker -}; - -CON_COMMAND_F( mp_forcewin, "Forces team to win", FCVAR_CHEAT ) -{ - if ( !UTIL_IsCommandIssuedByServerAdmin() ) - return; - - CTeamplayRoundBasedRules *pRules = dynamic_cast( GameRules() ); - if ( pRules ) - { - int iTeam = TEAM_UNASSIGNED; - if ( args.ArgC() == 1 ) - { - // if no team specified, use player 1's team - iTeam = UTIL_PlayerByIndex( 1 )->GetTeamNumber(); - } - else if ( args.ArgC() == 2 ) - { - // if team # specified, use that - iTeam = atoi( args[1] ); - } - else - { - Msg( "Usage: mp_forcewin " ); - return; - } - - int iWinReason = ( TEAM_UNASSIGNED == iTeam ? WINREASON_STALEMATE : WINREASON_ALL_POINTS_CAPTURED ); - pRules->SetWinningTeam( iTeam, iWinReason ); - } -} - -#endif // GAME_DLL - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTeamplayRoundBasedRules::CTeamplayRoundBasedRules( void ) -{ - for ( int i = 0; i < MAX_TEAMS; i++ ) - { - m_flNextRespawnWave.Set( i, 0 ); - m_TeamRespawnWaveTimes.Set( i, -1.0f ); - - m_bTeamReady.Set( i, false ); - -#ifdef GAME_DLL - m_flOriginalTeamRespawnWaveTime[i] = -1.0f; -#endif - } - - m_bInOvertime = false; - m_bInSetup = false; - m_bSwitchedTeamsThisRound = false; - m_flStopWatchTotalTime = -1.0f; - -#ifdef GAME_DLL - m_pCurStateInfo = NULL; - State_Transition( GR_STATE_PREGAME ); - - InitTeams(); - ResetMapTime(); - ResetScores(); - SetForceMapReset( true ); - SetRoundToPlayNext( NULL_STRING ); - m_bInWaitingForPlayers = false; - m_bAwaitingReadyRestart = false; - m_flRestartRoundTime = -1; - m_flMapResetTime = 0; - m_bPrevRoundWasWaitingForPlayers = false; - m_bResetTeamScores = true; - m_bResetPlayerScores = true; - m_bResetRoundsPlayed = true; - m_iWinningTeam = TEAM_UNASSIGNED; - - m_iszPreviousRounds.RemoveAll(); - SetFirstRoundPlayed( NULL_STRING ); - - m_bAllowStalemateAtTimelimit = false; - m_bChangelevelAfterStalemate = false; - m_flRoundStartTime = 0; - m_flStartBalancingTeamsAt = 0; - m_bPrintedUnbalanceWarning = false; - m_flFoundUnbalancedTeamsTime = -1; - - m_nRoundsPlayed = 0; - m_bUseAddScoreAnim = false; - - m_bStopWatch = false; - m_bAwaitingReadyRestart = false; - - if ( IsInTournamentMode() == true ) - { - m_bAwaitingReadyRestart = true; - } - -#endif -} - -#ifdef GAME_DLL -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::SetTeamRespawnWaveTime( int iTeam, float flValue ) -{ - if ( flValue < 0 ) - { - flValue = 0; - } - - // initialized to -1 so we can try to determine if this is the first spawn time we have received for this team - if ( m_flOriginalTeamRespawnWaveTime[iTeam] < 0 ) - { - m_flOriginalTeamRespawnWaveTime[iTeam] = flValue; - } - - m_TeamRespawnWaveTimes.Set( iTeam, flValue ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::AddTeamRespawnWaveTime( int iTeam, float flValue ) -{ - float flAddAmount = flValue; - float flCurrentSetting = m_TeamRespawnWaveTimes[iTeam]; - float flNewValue; - - if ( flCurrentSetting < 0 ) - { - flCurrentSetting = mp_respawnwavetime.GetFloat(); - } - - // initialized to -1 so we can try to determine if this is the first spawn time we have received for this team - if ( m_flOriginalTeamRespawnWaveTime[iTeam] < 0 ) - { - m_flOriginalTeamRespawnWaveTime[iTeam] = flCurrentSetting; - } - - flNewValue = flCurrentSetting + flAddAmount; - - if ( flNewValue < 0 ) - { - flNewValue = 0; - } - - m_TeamRespawnWaveTimes.Set( iTeam, flNewValue ); -} -#endif - -//----------------------------------------------------------------------------- -// Purpose: don't let us spawn before our freezepanel time would have ended, even if we skip it -//----------------------------------------------------------------------------- -float CTeamplayRoundBasedRules::GetNextRespawnWave( int iTeam, CBasePlayer *pPlayer ) -{ - if ( State_Get() == GR_STATE_STALEMATE ) - return 0; - - // If we are purely checking when the next respawn wave is for this team - if ( pPlayer == NULL ) - { - return m_flNextRespawnWave[iTeam]; - } - - // The soonest this player may spawn - float flMinSpawnTime = GetMinTimeWhenPlayerMaySpawn( pPlayer ); - - // the next scheduled respawn wave time - float flNextRespawnTime = m_flNextRespawnWave[iTeam]; - - // the length of one respawn wave. We'll check in increments of this - float flRespawnWaveMaxLen = GetRespawnWaveMaxLength( iTeam ); - - if ( flRespawnWaveMaxLen <= 0 ) - { - return flNextRespawnTime; - } - - // Keep adding the length of one respawn until we find a wave that - // this player will be eligible to spawn in. - while ( flNextRespawnTime < flMinSpawnTime ) - { - flNextRespawnTime += flRespawnWaveMaxLen; - } - - return flNextRespawnTime; -} - -//----------------------------------------------------------------------------- -// Purpose: Is the player past the required delays for spawning -//----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::HasPassedMinRespawnTime( CBasePlayer *pPlayer ) -{ - float flMinSpawnTime = GetMinTimeWhenPlayerMaySpawn( pPlayer ); - - return ( gpGlobals->curtime > flMinSpawnTime ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CTeamplayRoundBasedRules::GetMinTimeWhenPlayerMaySpawn( CBasePlayer *pPlayer ) -{ - // Min respawn time is the sum of - // - // a) the length of one full *unscaled* respawn wave for their team - // and - // b) death anim length + freeze panel length - - float flDeathAnimLength = 2.0 + spec_freeze_traveltime.GetFloat() + spec_freeze_time.GetFloat(); - - float fMinDelay = flDeathAnimLength + GetRespawnWaveMaxLength( pPlayer->GetTeamNumber(), false ); - - return pPlayer->GetDeathTime() + fMinDelay; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -float CTeamplayRoundBasedRules::GetRespawnTimeScalar( int iTeam ) -{ - // For long respawn times, scale the time as the number of players drops - int iOptimalPlayers = 8; // 16 players total, 8 per team - - int iNumPlayers = GetGlobalTeam(iTeam)->GetNumPlayers(); - - float flScale = RemapValClamped( iNumPlayers, 1, iOptimalPlayers, 0.25, 1.0 ); - return flScale; -} - -#ifdef GAME_DLL -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::SetForceMapReset( bool reset ) -{ - m_bForceMapReset = reset; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::Think( void ) -{ - if ( g_fGameOver ) // someone else quit the game already - { - // check to see if we should change levels now - if ( m_flIntermissionEndTime && ( m_flIntermissionEndTime < gpGlobals->curtime ) ) - { - if ( !IsX360() ) - { - ChangeLevel(); // intermission is over - } - else - { - IGameEvent * event = gameeventmanager->CreateEvent( "player_stats_updated" ); - if ( event ) - { - event->SetBool( "forceupload", true ); - gameeventmanager->FireEvent( event ); - } - engine->MultiplayerEndGame(); - } - - // Don't run this code again - m_flIntermissionEndTime = 0.f; - } - - return; - } - - State_Think(); - - if ( m_hWaitingForPlayersTimer ) - { - Assert( m_bInWaitingForPlayers ); - } - - if ( gpGlobals->curtime > m_flNextPeriodicThink ) - { - // Don't end the game during win or stalemate states - if ( State_Get() != GR_STATE_TEAM_WIN && State_Get() != GR_STATE_STALEMATE && State_Get() != GR_STATE_GAME_OVER ) - { - if ( CheckWinLimit() ) - return; - - if ( CheckMaxRounds() ) - return; - } - - CheckRestartRound(); - CheckWaitingForPlayers(); - - m_flNextPeriodicThink = gpGlobals->curtime + 1.0; - } - - // Bypass teamplay think. - CGameRules::Think(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::TimerMayExpire( void ) -{ - // team_train_watchers can also prevent timer expiring ( overtime ) - CTeamTrainWatcher *pWatcher = dynamic_cast( gEntList.FindEntityByClassname( NULL, "team_train_watcher" ) ); - while ( pWatcher ) - { - if ( !pWatcher->TimerMayExpire() ) - { - return false; - } - - pWatcher = dynamic_cast( gEntList.FindEntityByClassname( pWatcher, "team_train_watcher" ) ); - } - - return BaseClass::TimerMayExpire(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::CheckChatText( CBasePlayer *pPlayer, char *pText ) -{ - CheckChatForReadySignal( pPlayer, pText ); - - BaseClass::CheckChatText( pPlayer, pText ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::CheckChatForReadySignal( CBasePlayer *pPlayer, const char *chatmsg ) -{ - if ( IsInTournamentMode() == false ) - { - if( m_bAwaitingReadyRestart && FStrEq( chatmsg, mp_clan_ready_signal.GetString() ) ) - { - int iTeam = pPlayer->GetTeamNumber(); - if ( iTeam > LAST_SHARED_TEAM && iTeam < GetNumberOfTeams() ) - { - m_bTeamReady.Set( iTeam, true ); - - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_team_ready" ); - if ( event ) - { - event->SetInt( "team", iTeam ); - gameeventmanager->FireEvent( event ); - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::GoToIntermission( void ) -{ - if ( IsInTournamentMode() == true ) - return; - - BaseClass::GoToIntermission(); - - // set all players to FL_FROZEN - for ( int i = 1; i <= MAX_PLAYERS; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - - if ( pPlayer ) - { - pPlayer->AddFlag( FL_FROZEN ); - } - } - - // Print out map stats to a text file - //WriteStatsFile( "stats.xml" ); - - State_Enter( GR_STATE_GAME_OVER ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::SetInWaitingForPlayers( bool bWaitingForPlayers ) -{ - // never waiting for players when loading a bug report - if ( IsLoadingBugBaitReport() || gpGlobals->eLoadType == MapLoad_Background ) - { - m_bInWaitingForPlayers = false; - return; - } - - if( m_bInWaitingForPlayers == bWaitingForPlayers ) - return; - - m_bInWaitingForPlayers = bWaitingForPlayers; - - if( m_bInWaitingForPlayers ) - { - m_flWaitingForPlayersTimeEnds = gpGlobals->curtime + mp_waitingforplayers_time.GetFloat(); - } - else - { - m_flWaitingForPlayersTimeEnds = -1; - - if ( m_hWaitingForPlayersTimer ) - { - UTIL_Remove( m_hWaitingForPlayersTimer ); - } - RestoreActiveTimer(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::SetOvertime( bool bOvertime ) -{ - if ( m_bInOvertime == bOvertime ) - return; - - if ( bOvertime ) - { - UTIL_LogPrintf( "World triggered \"Round_Overtime\"\n" ); - } - - m_bInOvertime = bOvertime; - - if ( m_bInOvertime ) - { - // tell train watchers that we've transitioned to overtime - - CTeamTrainWatcher *pWatcher = dynamic_cast( gEntList.FindEntityByClassname( NULL, "team_train_watcher" ) ); - while ( pWatcher ) - { - variant_t emptyVariant; - pWatcher->AcceptInput( "OnStartOvertime", NULL, NULL, emptyVariant, 0 ); - - pWatcher = dynamic_cast( gEntList.FindEntityByClassname( pWatcher, "team_train_watcher" ) ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::SetSetup( bool bSetup ) -{ - if ( m_bInSetup == bSetup ) - return; - - m_bInSetup = bSetup; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::CheckWaitingForPlayers( void ) -{ - // never waiting for players when loading a bug report - if ( IsLoadingBugBaitReport() || gpGlobals->eLoadType == MapLoad_Background ) - return; - - if( mp_waitingforplayers_restart.GetBool() ) - { - if( m_bInWaitingForPlayers ) - { - m_flWaitingForPlayersTimeEnds = gpGlobals->curtime + mp_waitingforplayers_time.GetFloat(); - - if ( m_hWaitingForPlayersTimer ) - { - variant_t sVariant; - sVariant.SetInt( (int)(m_flWaitingForPlayersTimeEnds - gpGlobals->curtime) ); - m_hWaitingForPlayersTimer->AcceptInput( "SetTime", NULL, NULL, sVariant, 0 ); - } - } - else - { - SetInWaitingForPlayers( true ); - } - - mp_waitingforplayers_restart.SetValue( 0 ); - } - - if( mp_waitingforplayers_cancel.GetBool() && IsInTournamentMode() == false ) - { - // Cancel the wait period and manually Resume() the timer if - // it's not supposed to start paused at the beginning of a round. - // We must do this before SetInWaitingForPlayers() is called because it will - // restore the timer in the HUD and set the handle to NULL - if ( m_hPreviousActiveTimer.Get() ) - { - CTeamRoundTimer *pTimer = dynamic_cast( m_hPreviousActiveTimer.Get() ); - if ( pTimer && !pTimer->StartPaused() ) - { - pTimer->ResumeTimer(); - } - } - - SetInWaitingForPlayers( false ); - mp_waitingforplayers_cancel.SetValue( 0 ); - } - - if( m_bInWaitingForPlayers ) - { - if ( IsInTournamentMode() == true ) - return; - - // only exit the waitingforplayers if the time is up, and we are not in a round - // restart countdown already, and we are not waiting for a ready restart - if( gpGlobals->curtime > m_flWaitingForPlayersTimeEnds && m_flRestartRoundTime < 0 && !m_bAwaitingReadyRestart ) - { - m_flRestartRoundTime = gpGlobals->curtime; // reset asap - - // if "waiting for players" is ending and we're restarting... - // keep the current round that we're already running around in as the first round after the restart - CTeamControlPointMaster *pMaster = g_hControlPointMasters.Count() ? g_hControlPointMasters[0] : NULL; - if ( pMaster && pMaster->PlayingMiniRounds() && pMaster->GetCurrentRound() ) - { - SetRoundToPlayNext( pMaster->GetRoundToUseAfterRestart() ); - } - } - else - { - if ( !m_hWaitingForPlayersTimer ) - { - // Stop any timers, and bring up a new one - HideActiveTimer(); - - variant_t sVariant; - m_hWaitingForPlayersTimer = (CTeamRoundTimer*)CBaseEntity::Create( "team_round_timer", vec3_origin, vec3_angle ); - m_hWaitingForPlayersTimer->SetName( MAKE_STRING("zz_teamplay_waiting_timer") ); - m_hWaitingForPlayersTimer->KeyValue( "show_in_hud", "1" ); - sVariant.SetInt( (int)(m_flWaitingForPlayersTimeEnds - gpGlobals->curtime) ); - m_hWaitingForPlayersTimer->AcceptInput( "SetTime", NULL, NULL, sVariant, 0 ); - m_hWaitingForPlayersTimer->AcceptInput( "Resume", NULL, NULL, sVariant, 0 ); - m_hWaitingForPlayersTimer->AcceptInput( "Enable", NULL, NULL, sVariant, 0 ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::CheckRestartRound( void ) -{ - if( mp_clan_readyrestart.GetBool() && IsInTournamentMode() == false ) - { - m_bAwaitingReadyRestart = true; - - for ( int i = LAST_SHARED_TEAM+1; i < GetNumberOfTeams(); i++ ) - { - m_bTeamReady.Set( i, false ); - } - - const char *pszReadyString = mp_clan_ready_signal.GetString(); - - UTIL_ClientPrintAll( HUD_PRINTCONSOLE, "#clan_ready_rules", pszReadyString ); - UTIL_ClientPrintAll( HUD_PRINTTALK, "#clan_ready_rules", pszReadyString ); - - // Don't let them put anything malicious in there - if( pszReadyString == NULL || Q_strlen(pszReadyString) > 16 ) - { - pszReadyString = "ready"; - } - - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_ready_restart" ); - if ( event ) - { - gameeventmanager->FireEvent( event ); - } - - mp_clan_readyrestart.SetValue( 0 ); - - // cancel any restart round in progress - m_flRestartRoundTime = -1; - } - - // Restart the game if specified by the server - int iRestartDelay = mp_restartround.GetInt(); - if ( iRestartDelay == 0 ) - { - iRestartDelay = mp_restartgame.GetInt(); - } - - if ( iRestartDelay > 0 ) - { - if ( iRestartDelay > 60 ) - iRestartDelay = 60; - - if ( mp_restartgame.GetInt() > 0 ) - { - SetForceMapReset( true ); - } - else - { - SetForceMapReset( false ); - } - - SetInStopWatch( false ); - - m_flRestartRoundTime = gpGlobals->curtime + iRestartDelay; - - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_round_restart_seconds" ); - if ( event ) - { - event->SetInt( "seconds", iRestartDelay ); - gameeventmanager->FireEvent( event ); - } - - if ( IsInTournamentMode() == false ) - { - // let the players know - const char *pFormat = NULL; - - if ( mp_restartgame.GetInt() > 0 ) - { - if ( ShouldSwitchTeams() ) - { - pFormat = ( iRestartDelay > 1 ) ? "#game_switch_in_secs" : "#game_switch_in_sec"; - } - else if ( ShouldScrambleTeams() ) - { - pFormat = ( iRestartDelay > 1 ) ? "#game_scramble_in_secs" : "#game_scramble_in_sec"; - } - else - { - pFormat = ( iRestartDelay > 1 ) ? "#game_restart_in_secs" : "#game_restart_in_sec"; - } - } - else if ( mp_restartround.GetInt() > 0 ) - { - pFormat = ( iRestartDelay > 1 ) ? "#round_restart_in_secs" : "#round_restart_in_sec"; - } - - if ( pFormat ) - { - char strRestartDelay[64]; - Q_snprintf( strRestartDelay, sizeof( strRestartDelay ), "%d", iRestartDelay ); - UTIL_ClientPrintAll( HUD_PRINTCENTER, pFormat, strRestartDelay ); - UTIL_ClientPrintAll( HUD_PRINTCONSOLE, pFormat, strRestartDelay ); - } - } - - mp_restartround.SetValue( 0 ); - mp_restartgame.SetValue( 0 ); - - // cancel any ready restart in progress - m_bAwaitingReadyRestart = false; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::CheckTimeLimit( void ) -{ - if ( IsInPreMatch() == true ) - return false; - - if ( ( mp_timelimit.GetInt() > 0 && CanChangelevelBecauseOfTimeLimit() ) || m_bChangelevelAfterStalemate ) - { - // If there's less than 5 minutes to go, just switch now. This avoids the problem - // of sudden death modes starting shortly after a new round starts. - const int iMinTime = 5; - bool bSwitchDueToTime = ( mp_timelimit.GetInt() > iMinTime && GetTimeLeft() < (iMinTime * 60) ); - - if ( IsInTournamentMode() == true ) - { - bSwitchDueToTime = false; - } - - if( GetTimeLeft() <= 0 || m_bChangelevelAfterStalemate || bSwitchDueToTime ) - { - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_game_over" ); - if ( event ) - { - event->SetString( "reason", "Reached Time Limit" ); - gameeventmanager->FireEvent( event ); - } - - SendTeamScoresEvent(); - - GoToIntermission(); - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::IsGameUnderTimeLimit( void ) -{ - return ( mp_timelimit.GetInt() > 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CTeamplayRoundBasedRules::GetTimeLeft( void ) -{ - float flTimeLimit = mp_timelimit.GetInt() * 60; - float flMapChangeTime = m_flMapResetTime + flTimeLimit; - - // If the round timer is longer, let the round complete - // TFTODO: Do we need to worry about the timelimit running our during a round? - - int iTime = (int)(flMapChangeTime - gpGlobals->curtime); - if ( iTime < 0 ) - { - iTime = 0; - } - - return ( iTime ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::CheckNextLevelCvar( void ) -{ - if ( m_bForceMapReset ) - { - if ( nextlevel.GetString() && *nextlevel.GetString() && engine->IsMapValid( nextlevel.GetString() ) ) - { - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_game_over" ); - if ( event ) - { - event->SetString( "reason", "NextLevel CVAR" ); - gameeventmanager->FireEvent( event ); - } - - GoToIntermission(); - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::CheckWinLimit( void ) -{ - // has one team won the specified number of rounds? - int iWinLimit = mp_winlimit.GetInt(); - - if ( iWinLimit > 0 ) - { - for ( int i = LAST_SHARED_TEAM+1; i < GetNumberOfTeams(); i++ ) - { - CTeam *pTeam = GetGlobalTeam(i); - Assert( pTeam ); - - if ( pTeam->GetScore() >= iWinLimit ) - { - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_game_over" ); - if ( event ) - { - event->SetString( "reason", "Reached Win Limit" ); - gameeventmanager->FireEvent( event ); - } - - GoToIntermission(); - return true; - } - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::CheckMaxRounds() -{ - if ( mp_maxrounds.GetInt() > 0 && IsInPreMatch() == false ) - { - if ( m_nRoundsPlayed >= mp_maxrounds.GetInt() ) - { - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_game_over" ); - if ( event ) - { - event->SetString( "reason", "Reached Round Limit" ); - gameeventmanager->FireEvent( event ); - } - - GoToIntermission(); - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::State_Transition( gamerules_roundstate_t newState ) -{ - State_Leave(); - State_Enter( newState ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::State_Enter( gamerules_roundstate_t newState ) -{ - m_iRoundState = newState; - m_pCurStateInfo = State_LookupInfo( newState ); - - if ( mp_showroundtransitions.GetInt() > 0 ) - { - if ( m_pCurStateInfo ) - Msg( "Gamerules: entering state '%s'\n", m_pCurStateInfo->m_pStateName ); - else - Msg( "Gamerules: entering state #%d\n", newState ); - } - - // Initialize the new state. - if ( m_pCurStateInfo && m_pCurStateInfo->pfnEnterState ) - { - (this->*m_pCurStateInfo->pfnEnterState)(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::State_Leave() -{ - if ( m_pCurStateInfo && m_pCurStateInfo->pfnLeaveState ) - { - (this->*m_pCurStateInfo->pfnLeaveState)(); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::State_Think() -{ - if ( m_pCurStateInfo && m_pCurStateInfo->pfnThink ) - { - (this->*m_pCurStateInfo->pfnThink)(); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CGameRulesRoundStateInfo* CTeamplayRoundBasedRules::State_LookupInfo( gamerules_roundstate_t state ) -{ - static CGameRulesRoundStateInfo playerStateInfos[] = - { - { GR_STATE_INIT, "GR_STATE_INIT", &CTeamplayRoundBasedRules::State_Enter_INIT, NULL, &CTeamplayRoundBasedRules::State_Think_INIT }, - { GR_STATE_PREGAME, "GR_STATE_PREGAME", &CTeamplayRoundBasedRules::State_Enter_PREGAME, NULL, &CTeamplayRoundBasedRules::State_Think_PREGAME }, - { GR_STATE_STARTGAME, "GR_STATE_STARTGAME", &CTeamplayRoundBasedRules::State_Enter_STARTGAME, NULL, &CTeamplayRoundBasedRules::State_Think_STARTGAME }, - { GR_STATE_PREROUND, "GR_STATE_PREROUND", &CTeamplayRoundBasedRules::State_Enter_PREROUND, NULL, &CTeamplayRoundBasedRules::State_Think_PREROUND }, - { GR_STATE_RND_RUNNING, "GR_STATE_RND_RUNNING", &CTeamplayRoundBasedRules::State_Enter_RND_RUNNING, NULL, &CTeamplayRoundBasedRules::State_Think_RND_RUNNING }, - { GR_STATE_TEAM_WIN, "GR_STATE_TEAM_WIN", &CTeamplayRoundBasedRules::State_Enter_TEAM_WIN, NULL, &CTeamplayRoundBasedRules::State_Think_TEAM_WIN }, - { GR_STATE_RESTART, "GR_STATE_RESTART", &CTeamplayRoundBasedRules::State_Enter_RESTART, NULL, &CTeamplayRoundBasedRules::State_Think_RESTART }, - { GR_STATE_STALEMATE, "GR_STATE_STALEMATE", &CTeamplayRoundBasedRules::State_Enter_STALEMATE, &CTeamplayRoundBasedRules::State_Leave_STALEMATE, &CTeamplayRoundBasedRules::State_Think_STALEMATE }, - { GR_STATE_GAME_OVER, "GR_STATE_GAME_OVER", NULL, NULL, NULL }, - }; - - for ( size_t i=0; i < ARRAYSIZE( playerStateInfos ); i++ ) - { - if ( playerStateInfos[i].m_iRoundState == state ) - return &playerStateInfos[i]; - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::State_Enter_INIT( void ) -{ - InitTeams(); - ResetMapTime(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::State_Think_INIT( void ) -{ - State_Transition( GR_STATE_PREGAME ); -} - -//----------------------------------------------------------------------------- -// Purpose: The server is idle and waiting for enough players to start up again. -// When we find an active player go to GR_STATE_STARTGAME. -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::State_Enter_PREGAME( void ) -{ - m_flNextPeriodicThink = gpGlobals->curtime + 0.1; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::State_Think_PREGAME( void ) -{ - CheckRespawnWaves(); - - // we'll just stay in pregame for the bugbait reports - if ( IsLoadingBugBaitReport() || gpGlobals->eLoadType == MapLoad_Background ) - return; - - // Commentary stays in this mode too - if ( IsInCommentaryMode() ) - return; - - if( CountActivePlayers() > 0 ) - { - State_Transition( GR_STATE_STARTGAME ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Wait a bit and then spawn everyone into the preround -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::State_Enter_STARTGAME( void ) -{ - m_flStateTransitionTime = gpGlobals->curtime; - - m_bInitialSpawn = true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::State_Think_STARTGAME() -{ - if( gpGlobals->curtime > m_flStateTransitionTime ) - { - if ( mp_waitingforplayers_time.GetFloat() > 0 ) - { - // go into waitingforplayers, reset at end of it - SetInWaitingForPlayers( true ); - } - - State_Transition( GR_STATE_PREROUND ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::State_Enter_PREROUND( void ) -{ - m_flStateTransitionTime = gpGlobals->curtime + 5 * mp_enableroundwaittime.GetFloat(); - - BalanceTeams( false ); - - m_flStartBalancingTeamsAt = gpGlobals->curtime + 60.0; - - // Reset everything in the level - RoundRespawn(); - - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_round_start" ); - if ( event ) - { - event->SetBool( "full_reset", m_bForceMapReset ); - gameeventmanager->FireEvent( event ); - } - - StopWatchModeThink(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::State_Think_PREROUND( void ) -{ - if( gpGlobals->curtime > m_flStateTransitionTime ) - { - State_Transition( GR_STATE_RND_RUNNING ); - } - - CheckRespawnWaves(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::State_Enter_RND_RUNNING( void ) -{ - SetupOnRoundRunning(); - - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_round_active" ); - if ( event ) - { - gameeventmanager->FireEvent( event ); - } - - if( !IsInWaitingForPlayers() ) - { - PlayStartRoundVoice(); - } - - m_bChangeLevelOnRoundEnd = false; - m_bPrevRoundWasWaitingForPlayers = false; - - m_flNextBalanceTeamsTime = gpGlobals->curtime + 1.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::State_Think_RND_RUNNING( void ) -{ - //if we don't find any active players, return to GR_STATE_PREGAME - if( CountActivePlayers() <= 0 ) - { - State_Transition( GR_STATE_PREGAME ); - return; - } - - if ( m_flNextBalanceTeamsTime < gpGlobals->curtime ) - { - BalanceTeams( true ); - m_flNextBalanceTeamsTime = gpGlobals->curtime + 1.0f; - } - - CheckRespawnWaves(); - - // check round restart - if( m_flRestartRoundTime > 0 && m_flRestartRoundTime < gpGlobals->curtime && !g_pServerBenchmark->IsBenchmarkRunning() ) - { - // time to restart! - State_Transition( GR_STATE_RESTART ); - m_flRestartRoundTime = -1; - } - - // check ready restart - if( m_bAwaitingReadyRestart ) - { - bool bTeamNotReady = false; - for ( int i = LAST_SHARED_TEAM+1; i < GetNumberOfTeams(); i++ ) - { - if ( !m_bTeamReady[i] ) - { - bTeamNotReady = true; - break; - } - } - - if ( !bTeamNotReady ) - { - //State_Transition( GR_STATE_RESTART ); - mp_restartgame.SetValue( 5 ); - m_bAwaitingReadyRestart = false; - - ShouldResetScores( true, true ); - ShouldResetRoundsPlayed( true ); - } - } - - bool bAllowStalemateAtTimelimit = m_bAllowStalemateAtTimelimit || ( !IsValveMap() && mp_stalemate_at_timelimit.GetBool() ); - - // See if we're coming up to the server timelimit, in which case force a stalemate immediately. - if ( State_Get() == GR_STATE_RND_RUNNING && bAllowStalemateAtTimelimit && mp_timelimit.GetInt() > 0 && IsInPreMatch() == false ) - { - if ( GetTimeLeft() <= 0.5 ) - { - int iDrawScoreCheck = -1; - int iWinningTeam = 0; - bool bTeamsAreDrawn = true; - for ( int i = FIRST_GAME_TEAM; (i < GetNumberOfTeams()) && bTeamsAreDrawn; i++ ) - { - int iTeamScore = GetGlobalTeam(i)->GetScore(); - - if ( iTeamScore > iDrawScoreCheck ) - { - iWinningTeam = i; - } - - if ( iTeamScore != iDrawScoreCheck ) - { - if ( iDrawScoreCheck == -1 ) - { - iDrawScoreCheck = iTeamScore; - } - else - { - bTeamsAreDrawn = false; - } - } - } - - if ( bTeamsAreDrawn ) - { - if ( CanGoToStalemate() ) - { - m_bChangelevelAfterStalemate = true; - SetStalemate( STALEMATE_SERVER_TIMELIMIT, m_bForceMapReset ); - } - else - { - SetOvertime( true ); - } - } - else - { - SetWinningTeam( iWinningTeam, WINREASON_TIMELIMIT, true, false, true ); - } - } - } - - StopWatchModeThink(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::State_Enter_TEAM_WIN( void ) -{ - float flTime = MAX( 5, mp_bonusroundtime.GetFloat() ); - - m_flStateTransitionTime = gpGlobals->curtime + flTime * mp_enableroundwaittime.GetFloat(); - - // if we're forcing the map to reset it must be the end of a "full" round not a mini-round - if ( m_bForceMapReset ) - { - m_nRoundsPlayed++; - } - - InternalHandleTeamWin( m_iWinningTeam ); - - SendWinPanelInfo(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::State_Think_TEAM_WIN( void ) -{ - if( gpGlobals->curtime > m_flStateTransitionTime ) - { - bool bDone = !(!CheckTimeLimit() && !CheckWinLimit() && !CheckMaxRounds() && !CheckNextLevelCvar()); - - // check the win limit, max rounds, time limit and nextlevel cvar before starting the next round - if ( bDone == false ) - { - PreviousRoundEnd(); - State_Transition( GR_STATE_PREROUND ); - } - else if ( IsInTournamentMode() == true ) - { - for ( int i = 1; i <= MAX_PLAYERS; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); - - if ( !pPlayer ) - continue; - - pPlayer->ShowViewPortPanel( PANEL_SCOREBOARD ); - } - - RestartTournament(); - State_Transition( GR_STATE_RND_RUNNING ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::State_Enter_STALEMATE( void ) -{ - SetupOnStalemateStart(); - m_flStalemateStartTime = gpGlobals->curtime; - - // Stop any timers, and bring up a new one - HideActiveTimer(); - - variant_t sVariant; - if ( !m_hStalemateTimer ) - { - m_hStalemateTimer = (CTeamRoundTimer*)CBaseEntity::Create( "team_round_timer", vec3_origin, vec3_angle ); - } - m_hStalemateTimer->KeyValue( "show_in_hud", "1" ); - sVariant.SetInt( mp_stalemate_timelimit.GetInt() ); - m_hStalemateTimer->AcceptInput( "SetTime", NULL, NULL, sVariant, 0 ); - m_hStalemateTimer->AcceptInput( "Resume", NULL, NULL, sVariant, 0 ); - m_hStalemateTimer->AcceptInput( "Enable", NULL, NULL, sVariant, 0 ); - - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_update_timer" ); - if ( event ) - { - gameeventmanager->FireEvent( event ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::State_Leave_STALEMATE( void ) -{ - SetupOnStalemateEnd(); - - if ( m_hStalemateTimer ) - { - UTIL_Remove( m_hStalemateTimer ); - } - - RestoreActiveTimer(); - - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_update_timer" ); - if ( event ) - { - gameeventmanager->FireEvent( event ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::HideActiveTimer( void ) -{ - // We can't handle this, because we won't be able to restore multiple timers - Assert( m_hPreviousActiveTimer.Get() == NULL ); - - m_hPreviousActiveTimer = NULL; - CBaseEntity *pEntity = NULL; - variant_t sVariant; - sVariant.SetInt( false ); - while ((pEntity = gEntList.FindEntityByClassname( pEntity, "team_round_timer" )) != NULL) - { - CTeamRoundTimer *pTimer = assert_cast(pEntity); - if ( pTimer && pTimer->ShowInHud() ) - { - Assert( !m_hPreviousActiveTimer ); - m_hPreviousActiveTimer = pTimer; - pEntity->AcceptInput( "ShowInHUD", NULL, NULL, sVariant, 0 ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::RestoreActiveTimer( void ) -{ - if ( m_hPreviousActiveTimer ) - { - variant_t sVariant; - sVariant.SetInt( true ); - m_hPreviousActiveTimer->AcceptInput( "ShowInHUD", NULL, NULL, sVariant, 0 ); - m_hPreviousActiveTimer = NULL; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::State_Think_STALEMATE( void ) -{ - //if we don't find any active players, return to GR_STATE_PREGAME - if( CountActivePlayers() <= 0 ) - { - State_Transition( GR_STATE_PREGAME ); - return; - } - - int iDeadTeam = TEAM_UNASSIGNED; - int iAliveTeam = TEAM_UNASSIGNED; - - // If a team is fully killed, the other team has won - for ( int i = LAST_SHARED_TEAM+1; i < GetNumberOfTeams(); i++ ) - { - CTeam *pTeam = GetGlobalTeam(i); - Assert( pTeam ); - - int iPlayers = pTeam->GetNumPlayers(); - if ( iPlayers ) - { - bool bFoundLiveOne = false; - for ( int player = 0; player < iPlayers; player++ ) - { - if ( pTeam->GetPlayer(player) && pTeam->GetPlayer(player)->IsAlive() ) - { - bFoundLiveOne = true; - break; - } - } - - if ( bFoundLiveOne ) - { - iAliveTeam = i; - } - else - { - iDeadTeam = i; - } - } - } - - if ( iDeadTeam && iAliveTeam ) - { - // The live team has won. - bool bMasterHandled = false; - if ( !m_bForceMapReset ) - { - // We're not resetting the map, so give the winners control - // of all the points that were in play this round. - // Find the control point master. - CTeamControlPointMaster *pMaster = g_hControlPointMasters.Count() ? g_hControlPointMasters[0] : NULL; - if ( pMaster ) - { - variant_t sVariant; - sVariant.SetInt( iAliveTeam ); - pMaster->AcceptInput( "SetWinnerAndForceCaps", NULL, NULL, sVariant, 0 ); - bMasterHandled = true; - } - } - - if ( !bMasterHandled ) - { - SetWinningTeam( iAliveTeam, WINREASON_OPPONENTS_DEAD, m_bForceMapReset ); - } - } - else if ( iDeadTeam && iAliveTeam == TEAM_UNASSIGNED || - ( m_hStalemateTimer && TimerMayExpire() && m_hStalemateTimer->GetTimeRemaining() <= 0 ) ) - { - bool bFullReset = true; - - CTeamControlPointMaster *pMaster = g_hControlPointMasters.Count() ? g_hControlPointMasters[0] : NULL; - - if ( pMaster && pMaster->PlayingMiniRounds() ) - { - // we don't need to do a full map reset for maps with mini-rounds - bFullReset = false; - } - - // Both teams are dead. Pure stalemate. - SetWinningTeam( TEAM_UNASSIGNED, WINREASON_STALEMATE, bFullReset, false ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: manual restart -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::State_Enter_RESTART( void ) -{ - // send scores - SendTeamScoresEvent(); - - // send restart event - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_restart_round" ); - if ( event ) - { - gameeventmanager->FireEvent( event ); - } - - m_bPrevRoundWasWaitingForPlayers = m_bInWaitingForPlayers; - SetInWaitingForPlayers( false ); - - ResetScores(); - - // reset the round time - ResetMapTime(); - - State_Transition( GR_STATE_PREROUND ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::State_Think_RESTART( void ) -{ - // should never get here, State_Enter_RESTART sets us into a different state - Assert( 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: Input for other entities to declare a round winner. -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::SetWinningTeam( int team, int iWinReason, bool bForceMapReset /* = true */, bool bSwitchTeams /* = false*/, bool bDontAddScore /* = false*/ ) -{ - // Commentary doesn't let anyone win - if ( IsInCommentaryMode() ) - return; - - if ( ( team != TEAM_UNASSIGNED ) && ( team <= LAST_SHARED_TEAM || team >= GetNumberOfTeams() ) ) - { - Assert( !"SetWinningTeam() called with invalid team." ); - return; - } - - // are we already in this state? - if ( State_Get() == GR_STATE_TEAM_WIN ) - return; - - SetForceMapReset( bForceMapReset ); - SetSwitchTeams( bSwitchTeams ); - - m_iWinningTeam = team; - m_iWinReason = iWinReason; - - PlayWinSong( team ); - - // only reward the team if they have won the map and we're going to do a full reset or the time has run out and we're changing maps - bool bRewardTeam = bForceMapReset || ( IsGameUnderTimeLimit() && ( GetTimeLeft() <= 0 ) ); - - if ( bDontAddScore == true ) - { - bRewardTeam = false; - } - - m_bUseAddScoreAnim = false; - if ( bRewardTeam && ( team != TEAM_UNASSIGNED ) && ShouldScorePerRound() ) - { - GetGlobalTeam( team )->AddScore( TEAMPLAY_ROUND_WIN_SCORE ); - m_bUseAddScoreAnim = true; - } - - // this was a sudden death win if we were in stalemate then a team won it - bool bWasSuddenDeath = ( InStalemate() && m_iWinningTeam >= FIRST_GAME_TEAM ); - - State_Transition( GR_STATE_TEAM_WIN ); - - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_round_win" ); - if ( event ) - { - event->SetInt( "team", team ); - event->SetBool( "full_round", bForceMapReset ); - event->SetFloat( "round_time", gpGlobals->curtime - m_flRoundStartTime ); - event->SetBool( "was_sudden_death", bWasSuddenDeath ); - // let derived classes add more fields to the event - FillOutTeamplayRoundWinEvent( event ); - gameeventmanager->FireEvent( event ); - } - - // send team scores - SendTeamScoresEvent(); - - if ( team == TEAM_UNASSIGNED ) - { - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - CBaseMultiplayerPlayer *pPlayer = ToBaseMultiplayerPlayer( UTIL_PlayerByIndex( i ) ); - if ( !pPlayer ) - continue; - - pPlayer->SpeakConceptIfAllowed( MP_CONCEPT_STALEMATE ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Input for other entities to declare a stalemate -// Most often a team_control_point_master saying that the -// round timer expired -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::SetStalemate( int iReason, bool bForceMapReset /* = true */, bool bSwitchTeams /* = false */ ) -{ - if ( IsInTournamentMode() == true && IsInPreMatch() == true ) - return; - - if ( !mp_stalemate_enable.GetBool() ) - { - SetWinningTeam( TEAM_UNASSIGNED, WINREASON_STALEMATE, bForceMapReset, bSwitchTeams ); - return; - } - - if ( InStalemate() ) - return; - - SetForceMapReset( bForceMapReset ); - - m_iWinningTeam = TEAM_UNASSIGNED; - - PlaySuddenDeathSong(); - - State_Transition( GR_STATE_STALEMATE ); - - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_round_stalemate" ); - if ( event ) - { - event->SetInt( "reason", iReason ); - gameeventmanager->FireEvent( event ); - } -} - -#ifdef GAME_DLL -void CC_CH_ForceRespawn( void ) -{ - CTeamplayRoundBasedRules *pRules = dynamic_cast( GameRules() ); - if ( pRules ) - { - pRules->RespawnPlayers( true ); - } -} -static ConCommand mp_forcerespawnplayers("mp_forcerespawnplayers", CC_CH_ForceRespawn, "Force all players to respawn.", FCVAR_CHEAT ); - -void CC_CH_TournamentRestart( void ) -{ - CTeamplayRoundBasedRules *pRules = dynamic_cast( GameRules() ); - if ( pRules ) - { - pRules->RestartTournament(); - } -} -static ConCommand mp_tournament_restart("mp_tournament_restart", CC_CH_TournamentRestart, "Restart Tournament Mode on the current level." ); - -void CTeamplayRoundBasedRules::RestartTournament( void ) -{ - if ( IsInTournamentMode() == false ) - return; - - SetInWaitingForPlayers( true ); - m_bAwaitingReadyRestart = true; - m_flStopWatchTotalTime = -1.0f; - m_bStopWatch = false; - - for ( int i = 0; i < MAX_TEAMS; i++ ) - { - m_bTeamReady.Set( i, false ); - } -} - -#endif - -//----------------------------------------------------------------------------- -// Purpose: -// Input : bForceRespawn - respawn player even if dead or dying -// bTeam - if true, only respawn the passed team -// iTeam - team to respawn -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::RespawnPlayers( bool bForceRespawn, bool bTeam /* = false */, int iTeam/* = TEAM_UNASSIGNED */ ) -{ - if ( bTeam ) - { - Assert( iTeam > LAST_SHARED_TEAM && iTeam < GetNumberOfTeams() ); - } - - int iPlayersSpawned = 0; - - CBasePlayer *pPlayer; - for ( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - pPlayer = ToBasePlayer( UTIL_PlayerByIndex( i ) ); - - if ( !pPlayer ) - continue; - - // Check for team specific spawn - if ( bTeam && pPlayer->GetTeamNumber() != iTeam ) - continue; - - // players that haven't chosen a team/class can never spawn - if ( !pPlayer->IsReadyToPlay() ) - { - // Let the player spawn immediately when they do pick a class - if ( pPlayer->ShouldGainInstantSpawn() ) - { - pPlayer->AllowInstantSpawn(); - } - - continue; - } - - // If we aren't force respawning, don't respawn players that: - // - are alive - // - are still in the death anim stage of dying - if ( !bForceRespawn ) - { - if ( pPlayer->IsAlive() ) - continue; - - if ( m_iRoundState != GR_STATE_PREROUND ) - { - // If the player hasn't been dead the minimum respawn time, he - // waits until the next wave. - if ( bTeam && !HasPassedMinRespawnTime( pPlayer ) ) - continue; - - if ( !pPlayer->IsReadyToSpawn() ) - { - // Let the player spawn immediately when they do pick a class - if ( pPlayer->ShouldGainInstantSpawn() ) - { - pPlayer->AllowInstantSpawn(); - } - - continue; - } - - - } - } - - // Respawn this player - pPlayer->ForceRespawn(); - iPlayersSpawned++; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::InitTeams( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CTeamplayRoundBasedRules::CountActivePlayers( void ) -{ - int i; - int count = 0; - CBasePlayer *pPlayer; - - for (i = 1; i <= gpGlobals->maxClients; i++ ) - { - pPlayer = ToBasePlayer( UTIL_PlayerByIndex( i ) ); - - if ( pPlayer ) - { - if( pPlayer->IsReadyToPlay() ) - { - count++; - } - } - } - - return count; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::HandleTimeLimitChange( void ) -{ - - // check that we have an active timer in the HUD and use mp_timelimit if we don't - if ( !MapHasActiveTimer() && ( mp_timelimit.GetInt() > 0 && GetTimeLeft() > 0 ) ) - { - CreateTimeLimitTimer(); - } - else - { - if ( m_hTimeLimitTimer ) - { - UTIL_Remove( m_hTimeLimitTimer ); - m_hTimeLimitTimer = NULL; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::MapHasActiveTimer( void ) -{ - CBaseEntity *pEntity = NULL; - - while ( ( pEntity = gEntList.FindEntityByClassname( pEntity, "team_round_timer" ) ) != NULL ) - { - CTeamRoundTimer *pTimer = assert_cast( pEntity ); - if ( pTimer && pTimer->ShowInHud() && ( Q_stricmp( STRING( pTimer->GetEntityName() ), "zz_teamplay_timelimit_timer" ) != 0 ) ) - { - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::CreateTimeLimitTimer( void ) -{ - if ( !m_hTimeLimitTimer ) - { - m_hTimeLimitTimer = (CTeamRoundTimer*)CBaseEntity::Create( "team_round_timer", vec3_origin, vec3_angle ); - m_hTimeLimitTimer->SetName( MAKE_STRING( "zz_teamplay_timelimit_timer" ) ); - } - - variant_t sVariant; - m_hTimeLimitTimer->KeyValue( "show_in_hud", "1" ); - sVariant.SetInt( GetTimeLeft() ); - m_hTimeLimitTimer->AcceptInput( "SetTime", NULL, NULL, sVariant, 0 ); - m_hTimeLimitTimer->AcceptInput( "Resume", NULL, NULL, sVariant, 0 ); - m_hTimeLimitTimer->AcceptInput( "Enable", NULL, NULL, sVariant, 0 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::RoundRespawn( void ) -{ - m_flRoundStartTime = gpGlobals->curtime; - - if ( m_bForceMapReset || m_bPrevRoundWasWaitingForPlayers ) - { - CleanUpMap(); - - // clear out the previously played rounds - m_iszPreviousRounds.RemoveAll(); - - if ( mp_timelimit.GetInt() > 0 && GetTimeLeft() > 0 ) - { - // check that we have an active timer in the HUD and use mp_timelimit if we don't - if ( !MapHasActiveTimer() ) - { - CreateTimeLimitTimer(); - } - } - - m_iLastCapPointChanged = 0; - } - - // reset our spawn times to the original values - for ( int i = 0; i < MAX_TEAMS; i++ ) - { - if ( m_flOriginalTeamRespawnWaveTime[i] >= 0 ) - { - m_TeamRespawnWaveTimes.Set( i, m_flOriginalTeamRespawnWaveTime[i] ); - } - } - - if ( !IsInWaitingForPlayers() ) - { - if ( m_bForceMapReset ) - { - UTIL_LogPrintf( "World triggered \"Round_Start\"\n" ); - } - } - - // Setup before respawning players, so we can mess with spawnpoints - SetupOnRoundStart(); - - // Do we need to switch the teams? - m_bSwitchedTeamsThisRound = false; - if ( ShouldSwitchTeams() ) - { - m_bSwitchedTeamsThisRound = true; - HandleSwitchTeams(); - SetSwitchTeams( false ); - } - - // Do we need to switch the teams? - if ( ShouldScrambleTeams() ) - { - HandleScrambleTeams(); - SetScrambleTeams( false ); - } - - RespawnPlayers( true ); - - // reset per-round scores for each player - for ( int i = 1; i <= MAX_PLAYERS; i++ ) - { - CBasePlayer *pPlayer = ToBasePlayer( UTIL_PlayerByIndex( i ) ); - - if ( pPlayer ) - { - pPlayer->ResetPerRoundStats(); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Recreate all the map entities from the map data (preserving their indices), -// then remove everything else except the players. -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::CleanUpMap() -{ - if( mp_showcleanedupents.GetInt() ) - { - Msg( "CleanUpMap\n===============\n" ); - Msg( " Entities: %d (%d edicts)\n", gEntList.NumberOfEntities(), gEntList.NumberOfEdicts() ); - } - - // Get rid of all entities except players. - CBaseEntity *pCur = gEntList.FirstEnt(); - while ( pCur ) - { - if ( !RoundCleanupShouldIgnore( pCur ) ) - { - if( mp_showcleanedupents.GetInt() & 1 ) - { - Msg( "Removed Entity: %s\n", pCur->GetClassname() ); - } - UTIL_Remove( pCur ); - } - - pCur = gEntList.NextEnt( pCur ); - } - - // Clear out the event queue - g_EventQueue.Clear(); - - // Really remove the entities so we can have access to their slots below. - gEntList.CleanupDeleteList(); - - engine->AllowImmediateEdictReuse(); - - if ( mp_showcleanedupents.GetInt() & 2 ) - { - Msg( " Entities Left:\n" ); - pCur = gEntList.FirstEnt(); - while ( pCur ) - { - Msg( " %s (%d)\n", pCur->GetClassname(), pCur->entindex() ); - pCur = gEntList.NextEnt( pCur ); - } - } - - // Now reload the map entities. - class CTeamplayMapEntityFilter : public IMapEntityFilter - { - public: - CTeamplayMapEntityFilter() - { - m_pRules = assert_cast( GameRules() ); - } - - virtual bool ShouldCreateEntity( const char *pClassname ) - { - // Don't recreate the preserved entities. - if ( m_pRules->ShouldCreateEntity( pClassname ) ) - return true; - - // Increment our iterator since it's not going to call CreateNextEntity for this ent. - if ( m_iIterator != g_MapEntityRefs.InvalidIndex() ) - { - m_iIterator = g_MapEntityRefs.Next( m_iIterator ); - } - - return false; - } - - - virtual CBaseEntity* CreateNextEntity( const char *pClassname ) - { - if ( m_iIterator == g_MapEntityRefs.InvalidIndex() ) - { - // This shouldn't be possible. When we loaded the map, it should have used - // CTeamplayMapEntityFilter, which should have built the g_MapEntityRefs list - // with the same list of entities we're referring to here. - Assert( false ); - return NULL; - } - else - { - CMapEntityRef &ref = g_MapEntityRefs[m_iIterator]; - m_iIterator = g_MapEntityRefs.Next( m_iIterator ); // Seek to the next entity. - - if ( ref.m_iEdict == -1 || engine->PEntityOfEntIndex( ref.m_iEdict ) ) - { - // Doh! The entity was delete and its slot was reused. - // Just use any old edict slot. This case sucks because we lose the baseline. - return CreateEntityByName( pClassname ); - } - else - { - // Cool, the slot where this entity was is free again (most likely, the entity was - // freed above). Now create an entity with this specific index. - return CreateEntityByName( pClassname, ref.m_iEdict ); - } - } - } - - public: - int m_iIterator; // Iterator into g_MapEntityRefs. - CTeamplayRoundBasedRules *m_pRules; - }; - CTeamplayMapEntityFilter filter; - filter.m_iIterator = g_MapEntityRefs.Head(); - - // DO NOT CALL SPAWN ON info_node ENTITIES! - - MapEntity_ParseAllEntities( engine->GetMapEntitiesString(), &filter, true ); -} - -// Utility function -bool FindInList( const char **pStrings, const char *pToFind ) -{ - int i = 0; - while ( pStrings[i][0] != 0 ) - { - if ( Q_stricmp( pStrings[i], pToFind ) == 0 ) - return true; - i++; - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::ShouldCreateEntity( const char *pszClassName ) -{ - return !FindInList( s_PreserveEnts, pszClassName ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::RoundCleanupShouldIgnore( CBaseEntity *pEnt ) -{ - return FindInList( s_PreserveEnts, pEnt->GetClassname() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Sort function for sorting players by time spent connected ( user ID ) -//----------------------------------------------------------------------------- -static int SwitchPlayersSort( CBaseMultiplayerPlayer * const *p1, CBaseMultiplayerPlayer * const *p2 ) -{ - // sort by score - return ( (*p2)->GetTeamBalanceScore() - (*p1)->GetTeamBalanceScore() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::CheckRespawnWaves( void ) -{ - for ( int team = LAST_SHARED_TEAM+1; team < GetNumberOfTeams(); team++ ) - { - if ( m_flNextRespawnWave[team] > gpGlobals->curtime ) - continue; - - RespawnTeam( team ); - - m_flNextRespawnWave.Set( team, gpGlobals->curtime + GetRespawnWaveMaxLength( team ) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Return true if the teams are balanced after this function -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::BalanceTeams( bool bRequireSwitcheesToBeDead ) -{ - if ( mp_autoteambalance.GetBool() == false ) - { - return; - } - - // we don't balance for a period of time at the start of the game - if ( gpGlobals->curtime < m_flStartBalancingTeamsAt ) - { - return; - } - - // wrap with this bool, indicates it's a round running switch and not a between rounds insta-switch - if ( bRequireSwitcheesToBeDead ) - { - // we don't balance if there is less than 60 seconds on the active timer - CTeamRoundTimer *pActiveTimer = GetActiveRoundTimer(); - if ( pActiveTimer && pActiveTimer->GetTimeRemaining() < 60 ) - { - return; - } - } - - int iHeaviestTeam = TEAM_UNASSIGNED, iLightestTeam = TEAM_UNASSIGNED; - - // Figure out if we're unbalanced - if ( !AreTeamsUnbalanced( iHeaviestTeam, iLightestTeam ) ) - { - m_flFoundUnbalancedTeamsTime = -1; - m_bPrintedUnbalanceWarning = false; - return; - } - - if ( m_flFoundUnbalancedTeamsTime < 0 ) - { - m_flFoundUnbalancedTeamsTime = gpGlobals->curtime; - } - - // if teams have been unbalanced for X seconds, play a warning - if ( !m_bPrintedUnbalanceWarning && ( ( gpGlobals->curtime - m_flFoundUnbalancedTeamsTime ) > 1.0 ) ) - { - // print unbalance warning - UTIL_ClientPrintAll( HUD_PRINTTALK, "#game_auto_team_balance_in", "5" ); - m_bPrintedUnbalanceWarning = true; - } - - // teams are unblanced, figure out some players that need to be switched - - CTeam *pHeavyTeam = GetGlobalTeam( iHeaviestTeam ); - CTeam *pLightTeam = GetGlobalTeam( iLightestTeam ); - - Assert( pHeavyTeam && pLightTeam ); - - int iNumSwitchesRequired = ( pHeavyTeam->GetNumPlayers() - pLightTeam->GetNumPlayers() ) / 2; - - // sort the eligible players and switch the n best candidates - CUtlVector vecPlayers; - - CBaseMultiplayerPlayer *pPlayer; - - int iScore; - - int i; - for ( i = 0; i < pHeavyTeam->GetNumPlayers(); i++ ) - { - pPlayer = ToBaseMultiplayerPlayer( pHeavyTeam->GetPlayer(i) ); - - if ( !pPlayer ) - continue; - - // calculate a score for this player. higher is more likely to be switched - iScore = pPlayer->CalculateTeamBalanceScore(); - - pPlayer->SetTeamBalanceScore( iScore ); - - vecPlayers.AddToTail( pPlayer ); - } - - // sort the vector - vecPlayers.Sort( SwitchPlayersSort ); - - int iNumEligibleSwitchees = iNumSwitchesRequired + 2; - - for ( int i=0; i 0 && i < iNumEligibleSwitchees; i++ ) - { - pPlayer = vecPlayers.Element(i); - - Assert( pPlayer ); - - if ( !pPlayer ) - continue; - - if ( bRequireSwitcheesToBeDead == false || !pPlayer->IsAlive() ) - { - pPlayer->ChangeTeam( iLightestTeam ); - pPlayer->SetLastForcedChangeTeamTimeToNow(); - - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_teambalanced_player" ); - if ( event ) - { - event->SetInt( "player", pPlayer->entindex() ); - event->SetInt( "team", iLightestTeam ); - gameeventmanager->FireEvent( event ); - } - - // tell people that we've switched this player - UTIL_ClientPrintAll( HUD_PRINTTALK, "#game_player_was_team_balanced", pPlayer->GetPlayerName() ); - - iNumSwitchesRequired--; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::ResetScores( void ) -{ - if ( m_bResetTeamScores ) - { - for ( int i = 0; i < GetNumberOfTeams(); i++ ) - { - GetGlobalTeam( i )->ResetScores(); - } - } - - if ( m_bResetPlayerScores ) - { - CBasePlayer *pPlayer; - - for( int i = 1; i <= gpGlobals->maxClients; i++ ) - { - pPlayer = ToBasePlayer( UTIL_PlayerByIndex( i ) ); - - if (pPlayer == NULL) - continue; - - if (FNullEnt( pPlayer->edict() )) - continue; - - pPlayer->ResetScores(); - } - } - - if ( m_bResetRoundsPlayed ) - { - m_nRoundsPlayed = 0; - } - - // assume we always want to reset the scores - // unless someone tells us not to for the next reset - m_bResetTeamScores = true; - m_bResetPlayerScores = true; - m_bResetRoundsPlayed = true; - //m_flStopWatchTime = -1.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::ResetMapTime( void ) -{ - m_flMapResetTime = gpGlobals->curtime; - - // send an event with the time remaining until map change - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_map_time_remaining" ); - if ( event ) - { - event->SetInt( "seconds", GetTimeLeft() ); - gameeventmanager->FireEvent( event ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::PlayStartRoundVoice( void ) -{ - for ( int i = LAST_SHARED_TEAM+1; i < GetNumberOfTeams(); i++ ) - { - BroadcastSound( i, UTIL_VarArgs("Game.TeamRoundStart%d", i ) ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::PlayWinSong( int team ) -{ - if ( team == TEAM_UNASSIGNED ) - { - PlayStalemateSong(); - } - else - { - BroadcastSound( TEAM_UNASSIGNED, UTIL_VarArgs("Game.TeamWin%d", team ) ); - - for ( int i = FIRST_GAME_TEAM; i < GetNumberOfTeams(); i++ ) - { - if ( i == team ) - { - BroadcastSound( i, "Game.YourTeamWon" ); - } - else - { - BroadcastSound( i, "Game.YourTeamLost" ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::PlaySuddenDeathSong( void ) -{ - BroadcastSound( TEAM_UNASSIGNED, "Game.SuddenDeath" ); - - for ( int i = FIRST_GAME_TEAM; i < GetNumberOfTeams(); i++ ) - { - BroadcastSound( i, "Game.SuddenDeath" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::PlayStalemateSong( void ) -{ - BroadcastSound( TEAM_UNASSIGNED, "Game.Stalemate" ); - - for ( int i = FIRST_GAME_TEAM; i < GetNumberOfTeams(); i++ ) - { - BroadcastSound( i, "Game.Stalemate" ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::BroadcastSound( int iTeam, const char *sound ) -{ - //send it to everyone - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_broadcast_audio" ); - if ( event ) - { - event->SetInt( "team", iTeam ); - event->SetString( "sound", sound ); - gameeventmanager->FireEvent( event ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::AddPlayedRound( string_t strName ) -{ - if ( strName != NULL_STRING ) - { - m_iszPreviousRounds.AddToHead( strName ); - - // we only need to store the last two rounds that we've played - if ( m_iszPreviousRounds.Count() > 2 ) - { - // remove all but two of the entries (should only ever have to remove 1 when we're at 3) - for ( int i = m_iszPreviousRounds.Count() - 1 ; i > 1 ; i-- ) - { - m_iszPreviousRounds.Remove( i ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::IsPreviouslyPlayedRound( string_t strName ) -{ - return ( m_iszPreviousRounds.Find( strName ) != m_iszPreviousRounds.InvalidIndex() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -string_t CTeamplayRoundBasedRules::GetLastPlayedRound( void ) -{ - return ( m_iszPreviousRounds.Count() ? m_iszPreviousRounds[0] : NULL_STRING ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CTeamRoundTimer *CTeamplayRoundBasedRules::GetActiveRoundTimer( void ) -{ -#ifdef TF_DLL - int iTimerEntIndex = ObjectiveResource()->GetTimerInHUD(); - return ( dynamic_cast( UTIL_EntityByIndex( iTimerEntIndex ) ) ); -#else - return NULL; -#endif -} - -#endif // GAME_DLL - -//----------------------------------------------------------------------------- -// Purpose: How long are the respawn waves for this team currently? -//----------------------------------------------------------------------------- -float CTeamplayRoundBasedRules::GetRespawnWaveMaxLength( int iTeam, bool bScaleWithNumPlayers /* = true */ ) -{ - if (State_Get() != GR_STATE_RND_RUNNING) - return 0; - - if ( mp_disable_respawn_times.GetBool() == true ) - return 0.0f; - - //Let's just turn off respawn times while players are messing around waiting for the tournament to start - if ( IsInTournamentMode() == true && IsInPreMatch() == true ) - return 0.0f; - - float flTime = ( ( m_TeamRespawnWaveTimes[iTeam] >= 0 ) ? m_TeamRespawnWaveTimes[iTeam] : mp_respawnwavetime.GetFloat() ); - - // For long respawn times, scale the time as the number of players drops - if ( bScaleWithNumPlayers && flTime > 5 ) - { - flTime = MAX( 5, flTime * GetRespawnTimeScalar(iTeam) ); - } - - return flTime; -} - -//----------------------------------------------------------------------------- -// Purpose: returns true if we are running tournament mode -//----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::IsInTournamentMode( void ) -{ - return mp_tournament.GetBool(); -} - -//----------------------------------------------------------------------------- -// Purpose: returns true if we should even bother to do balancing stuff -//----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::ShouldBalanceTeams( void ) -{ - if ( IsInTournamentMode() == true ) - return false; - - if ( mp_teams_unbalance_limit.GetInt() <= 0 ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: returns true if the passed team change would cause unbalanced teams -//----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::WouldChangeUnbalanceTeams( int iNewTeam, int iCurrentTeam ) -{ - // players are allowed to change to their own team - if( iNewTeam == iCurrentTeam ) - return false; - - // if mp_teams_unbalance_limit is 0, don't check - if ( ShouldBalanceTeams() == false ) - return false; - - // if they are joining a non-playing team, allow - if ( iNewTeam < FIRST_GAME_TEAM ) - return false; - - CTeam *pNewTeam = GetGlobalTeam( iNewTeam ); - - if ( !pNewTeam ) - { - Assert( 0 ); - return true; - } - - // add one because we're joining this team - int iNewTeamPlayers = pNewTeam->GetNumPlayers() + 1; - - // for each game team - int i = FIRST_GAME_TEAM; - - CTeam *pTeam; - - for ( pTeam = GetGlobalTeam(i); pTeam != NULL; pTeam = GetGlobalTeam(++i) ) - { - if ( pTeam == pNewTeam ) - continue; - - int iNumPlayers = pTeam->GetNumPlayers(); - - if ( i == iCurrentTeam ) - { - iNumPlayers = MAX( 0, iNumPlayers-1 ); - } - - if ( ( iNewTeamPlayers - iNumPlayers ) > mp_teams_unbalance_limit.GetInt() ) - { - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::AreTeamsUnbalanced( int &iHeaviestTeam, int &iLightestTeam ) -{ - if ( mp_teams_unbalance_limit.GetInt() <= 0 || IsInTournamentMode() == true ) - { - return false; - } - -#ifndef CLIENT_DLL - if ( IsInCommentaryMode() ) - return false; -#endif - - int iMostPlayers = 0; - int iLeastPlayers = MAX_PLAYERS + 1; - - int i = FIRST_GAME_TEAM; - - for ( CTeam *pTeam = GetGlobalTeam(i); pTeam != NULL; pTeam = GetGlobalTeam(++i) ) - { - int iNumPlayers = pTeam->GetNumPlayers(); - - if ( iNumPlayers < iLeastPlayers ) - { - iLeastPlayers = iNumPlayers; - iLightestTeam = i; - } - - if ( iNumPlayers > iMostPlayers ) - { - iMostPlayers = iNumPlayers; - iHeaviestTeam = i; - } - } - - if ( ( iMostPlayers - iLeastPlayers ) > mp_teams_unbalance_limit.GetInt() ) - { - return true; - } - - return false; -} - -#ifdef CLIENT_DLL -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::SetRoundState( int iRoundState ) -{ - m_iRoundState = iRoundState; - m_flLastRoundStateChangeTime = gpGlobals->curtime; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::OnPreDataChanged( DataUpdateType_t updateType ) -{ - m_bOldInWaitingForPlayers = m_bInWaitingForPlayers; - m_bOldInOvertime = m_bInOvertime; - m_bOldInSetup = m_bInSetup; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::OnDataChanged( DataUpdateType_t updateType ) -{ - if ( updateType == DATA_UPDATE_CREATED || - m_bOldInWaitingForPlayers != m_bInWaitingForPlayers || - m_bOldInOvertime != m_bInOvertime || - m_bOldInSetup != m_bInSetup ) - { - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_update_timer" ); - if ( event ) - { - gameeventmanager->FireEventClientSide( event ); - } - } - - if ( updateType == DATA_UPDATE_CREATED ) - { - if ( State_Get() == GR_STATE_STALEMATE ) - { - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_round_stalemate" ); - if ( event ) - { - event->SetInt( "reason", STALEMATE_JOIN_MID ); - gameeventmanager->FireEventClientSide( event ); - } - } - } - - if ( m_bInOvertime && ( m_bOldInOvertime != m_bInOvertime ) ) - { - HandleOvertimeBegin(); - } -} - -#endif // CLIENT_DLL diff --git a/game/shared/teamplayroundbased_gamerules.h b/game/shared/teamplayroundbased_gamerules.h deleted file mode 100644 index c9b48378c..000000000 --- a/game/shared/teamplayroundbased_gamerules.h +++ /dev/null @@ -1,458 +0,0 @@ -//====== Copyright 1996-2006, Valve Corporation, All rights reserved. ======= -// -// Purpose: Teamplay game rules that manage a round based structure for you -// -//============================================================================= - -#ifndef TEAMPLAYROUNDBASED_GAMERULES_H -#define TEAMPLAYROUNDBASED_GAMERULES_H -#ifdef _WIN32 -#pragma once -#endif - -#include "teamplay_gamerules.h" -#include "teamplay_round_timer.h" - -#ifdef GAME_DLL -#include "team_control_point.h" - extern ConVar mp_respawnwavetime; - extern ConVar mp_showroundtransitions; - extern ConVar mp_enableroundwaittime; - extern ConVar mp_showcleanedupents; - extern ConVar mp_bonusroundtime; - extern ConVar mp_restartround; - extern ConVar mp_winlimit; - extern ConVar mp_stalemate_timelimit; - extern ConVar mp_stalemate_enable; -#else - #define CTeamplayRoundBasedRules C_TeamplayRoundBasedRules - #define CTeamplayRoundBasedRulesProxy C_TeamplayRoundBasedRulesProxy -#endif - -class CTeamplayRoundBasedRules; - -//----------------------------------------------------------------------------- -// Round states -//----------------------------------------------------------------------------- -enum gamerules_roundstate_t -{ - // initialize the game, create teams - GR_STATE_INIT = 0, - - //Before players have joined the game. Periodically checks to see if enough players are ready - //to start a game. Also reverts to this when there are no active players - GR_STATE_PREGAME, - - //The game is about to start, wait a bit and spawn everyone - GR_STATE_STARTGAME, - - //All players are respawned, frozen in place - GR_STATE_PREROUND, - - //Round is on, playing normally - GR_STATE_RND_RUNNING, - - //Someone has won the round - GR_STATE_TEAM_WIN, - - //Noone has won, manually restart the game, reset scores - GR_STATE_RESTART, - - //Noone has won, restart the game - GR_STATE_STALEMATE, - - //Game is over, showing the scoreboard etc - GR_STATE_GAME_OVER, - - GR_NUM_ROUND_STATES -}; - -enum { - WINREASON_NONE =0, - WINREASON_ALL_POINTS_CAPTURED, - WINREASON_OPPONENTS_DEAD, - WINREASON_FLAG_CAPTURE_LIMIT, - WINREASON_DEFEND_UNTIL_TIME_LIMIT, - WINREASON_STALEMATE, - WINREASON_TIMELIMIT, - WINREASON_WINLIMIT, -}; - -enum stalemate_reasons_t -{ - STALEMATE_JOIN_MID, - STALEMATE_TIMER, - STALEMATE_SERVER_TIMELIMIT, - - NUM_STALEMATE_REASONS, -}; - -//----------------------------------------------------------------------------- -// Purpose: Per-state data -//----------------------------------------------------------------------------- -class CGameRulesRoundStateInfo -{ -public: - gamerules_roundstate_t m_iRoundState; - const char *m_pStateName; - - void (CTeamplayRoundBasedRules::*pfnEnterState)(); // Init and deinit the state. - void (CTeamplayRoundBasedRules::*pfnLeaveState)(); - void (CTeamplayRoundBasedRules::*pfnThink)(); // Do a PreThink() in this state. -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CTeamplayRoundBasedRulesProxy : public CGameRulesProxy -{ -public: - DECLARE_CLASS( CTeamplayRoundBasedRulesProxy, CGameRulesProxy ); - DECLARE_NETWORKCLASS(); - -#ifdef GAME_DLL - DECLARE_DATADESC(); - void InputSetStalemateOnTimelimit( inputdata_t &inputdata ); -#endif - - //---------------------------------------------------------------------------------- - // Client specific -#ifdef CLIENT_DLL - void OnPreDataChanged( DataUpdateType_t updateType ); - void OnDataChanged( DataUpdateType_t updateType ); -#endif // CLIENT_DLL -}; - -//----------------------------------------------------------------------------- -// Purpose: Teamplay game rules that manage a round based structure for you -//----------------------------------------------------------------------------- -class CTeamplayRoundBasedRules : public CTeamplayRules -{ - DECLARE_CLASS( CTeamplayRoundBasedRules, CTeamplayRules ); -public: - CTeamplayRoundBasedRules(); - -#ifdef CLIENT_DLL - DECLARE_CLIENTCLASS_NOBASE(); // This makes datatables able to access our private vars. - - void SetRoundState( int iRoundState ); - float m_flLastRoundStateChangeTime; -#else - DECLARE_SERVERCLASS_NOBASE(); // This makes datatables able to access our private vars. -#endif - - // Data accessors - inline gamerules_roundstate_t State_Get( void ) { return m_iRoundState; } - bool IsInWaitingForPlayers( void ) { return m_bInWaitingForPlayers; } - virtual bool InRoundRestart( void ) { return State_Get() == GR_STATE_PREROUND; } - bool InStalemate( void ) { return State_Get() == GR_STATE_STALEMATE; } - bool RoundHasBeenWon( void ) { return State_Get() == GR_STATE_TEAM_WIN; } - - float GetNextRespawnWave( int iTeam, CBasePlayer *pPlayer ); - virtual bool HasPassedMinRespawnTime( CBasePlayer *pPlayer ); - float GetRespawnTimeScalar( int iTeam ); - float GetRespawnWaveMaxLength( int iTeam, bool bScaleWithNumPlayers = true ); - float GetMinTimeWhenPlayerMaySpawn( CBasePlayer *pPlayer ); - - // Return false if players aren't allowed to cap points at this time (i.e. in WaitingForPlayers) - virtual bool PointsMayBeCaptured( void ) { return ((State_Get() == GR_STATE_RND_RUNNING || State_Get() == GR_STATE_STALEMATE) && !IsInWaitingForPlayers()); } - virtual void SetLastCapPointChanged( int iIndex ) { m_iLastCapPointChanged = iIndex; } - int GetLastCapPointChanged( void ) { return m_iLastCapPointChanged; } - - virtual int GetWinningTeam( void ){ return m_iWinningTeam; } - int GetWinReason() { return m_iWinReason; } - - bool InOvertime( void ){ return m_bInOvertime; } - void SetOvertime( bool bOvertime ); - - bool InSetup( void ){ return m_bInSetup; } - - void BalanceTeams( bool bRequireSwitcheesToBeDead ); - - bool SwitchedTeamsThisRound( void ) { return m_bSwitchedTeamsThisRound; } - - bool ShouldBalanceTeams( void ); - bool IsInTournamentMode( void ); - bool IsInPreMatch( void ) { return (IsInTournamentMode() && IsInWaitingForPlayers()); } - bool IsWaitingForTeams( void ) { return m_bAwaitingReadyRestart; } - bool IsInStopWatch( void ) { return m_bStopWatch; } - void SetInStopWatch( bool bState ) { m_bStopWatch = bState; } - virtual void StopWatchModeThink( void ) { }; - - bool IsTeamReady( int iTeamNumber ) - { - return m_bTeamReady[iTeamNumber]; - } - - virtual void HandleTeamScoreModify( int iTeam, int iScore) { }; - - - float GetRoundRestartTime( void ) { return m_flRestartRoundTime; } - - //---------------------------------------------------------------------------------- - // Server specific -#ifdef GAME_DLL - // Derived game rules class should override these -public: - // Override this to prevent removal of game specific entities that need to persist - virtual bool RoundCleanupShouldIgnore( CBaseEntity *pEnt ); - virtual bool ShouldCreateEntity( const char *pszClassName ); - - // Called when a new round is being initialized - virtual void SetupOnRoundStart( void ) { return; } - - // Called when a new round is off and running - virtual void SetupOnRoundRunning( void ) { return; } - - // Called before a new round is started (so the previous round can end) - virtual void PreviousRoundEnd( void ) { return; } - - // Send the team scores down to the client - virtual void SendTeamScoresEvent( void ) { return; } - - // Send the end of round info displayed in the win panel - virtual void SendWinPanelInfo( void ) { return; } - - // Setup spawn points for the current round before it starts - virtual void SetupSpawnPointsForRound( void ) { return; } - - // Called when a round has entered stalemate mode (timer has run out) - virtual void SetupOnStalemateStart( void ) { return; } - virtual void SetupOnStalemateEnd( void ) { return; } - virtual void SetSetup( bool bSetup ); - - bool PrevRoundWasWaitingForPlayers() { return m_bPrevRoundWasWaitingForPlayers; } - - virtual bool ShouldScorePerRound( void ){ return true; } - - bool CheckNextLevelCvar( void ); - - virtual bool TimerMayExpire( void ); - - virtual bool IsValveMap( void ){ return false; } - - virtual void RestartTournament( void ); - -public: - void State_Transition( gamerules_roundstate_t newState ); - - void RespawnPlayers( bool bForceRespawn, bool bTeam = false, int iTeam = TEAM_UNASSIGNED ); - - void SetForceMapReset( bool reset ); - - void SetRoundToPlayNext( string_t strName ){ m_iszRoundToPlayNext = strName; } - string_t GetRoundToPlayNext( void ){ return m_iszRoundToPlayNext; } - void AddPlayedRound( string_t strName ); - bool IsPreviouslyPlayedRound ( string_t strName ); - string_t GetLastPlayedRound( void ); - - virtual void SetWinningTeam( int team, int iWinReason, bool bForceMapReset = true, bool bSwitchTeams = false, bool bDontAddScore = false ); - virtual void SetStalemate( int iReason, bool bForceMapReset = true, bool bSwitchTeams = false ); - - virtual void SetRoundOverlayDetails( void ){ return; } - - virtual float GetWaitingForPlayersTime( void ) { return mp_waitingforplayers_time.GetFloat(); } - void ShouldResetScores( bool bResetTeam, bool bResetPlayer ){ m_bResetTeamScores = bResetTeam; m_bResetPlayerScores = bResetPlayer; } - void ShouldResetRoundsPlayed( bool bResetRoundsPlayed ){ m_bResetRoundsPlayed = bResetRoundsPlayed; } - - void SetFirstRoundPlayed( string_t strName ){ m_iszFirstRoundPlayed = strName ; } - string_t GetFirstRoundPlayed(){ return m_iszFirstRoundPlayed; } - - void SetTeamRespawnWaveTime( int iTeam, float flValue ); - void AddTeamRespawnWaveTime( int iTeam, float flValue ); - virtual void FillOutTeamplayRoundWinEvent( IGameEvent *event ) {} // derived classes may implement to add fields to this event - - void SetStalemateOnTimelimit( bool bStalemate ) { m_bAllowStalemateAtTimelimit = bStalemate; } - - bool IsGameUnderTimeLimit( void ); - - CTeamRoundTimer *GetActiveRoundTimer( void ); - - void HandleTimeLimitChange( void ); - - void SetTeamReadyState( bool bState, int iTeam ) - { - m_bTeamReady.Set( iTeam, bState ); - } - - virtual void PlayTrainCaptureAlert( CTeamControlPoint *pPoint, bool bFinalPointInMap ){ return; } - -protected: - virtual void Think( void ); - - virtual void CheckChatText( CBasePlayer *pPlayer, char *pText ); - void CheckChatForReadySignal( CBasePlayer *pPlayer, const char *chatmsg ); - - // Game beginning / end handling - virtual void GoToIntermission( void ); - void SetInWaitingForPlayers( bool bWaitingForPlayers ); - void CheckWaitingForPlayers( void ); - void CheckRestartRound( void ); - bool CheckTimeLimit( void ); - int GetTimeLeft( void ); - virtual bool CheckWinLimit( void ); - bool CheckMaxRounds( void ); - - virtual bool CanChangelevelBecauseOfTimeLimit( void ) { return true; } - virtual bool CanGoToStalemate( void ) { return true; } - - // State machine handling - void State_Enter( gamerules_roundstate_t newState ); // Initialize the new state. - void State_Leave(); // Cleanup the previous state. - void State_Think(); // Update the current state. - static CGameRulesRoundStateInfo* State_LookupInfo( gamerules_roundstate_t state ); // Find the state info for the specified state. - - // State Functions - void State_Enter_INIT( void ); - void State_Think_INIT( void ); - - void State_Enter_PREGAME( void ); - void State_Think_PREGAME( void ); - - void State_Enter_STARTGAME( void ); - void State_Think_STARTGAME( void ); - - void State_Enter_PREROUND( void ); - void State_Think_PREROUND( void ); - - void State_Enter_RND_RUNNING( void ); - void State_Think_RND_RUNNING( void ); - - void State_Enter_TEAM_WIN( void ); - void State_Think_TEAM_WIN( void ); - - void State_Enter_RESTART( void ); - void State_Think_RESTART( void ); - - void State_Enter_STALEMATE( void ); - void State_Think_STALEMATE( void ); - void State_Leave_STALEMATE( void ); - -protected: - virtual void InitTeams( void ); - int CountActivePlayers( void ); - - virtual void RoundRespawn( void ); - virtual void CleanUpMap( void ); - void CheckRespawnWaves( void ); - void ResetScores( void ); - void ResetMapTime( void ); - - void PlayStartRoundVoice( void ); - void PlayWinSong( int team ); - void PlayStalemateSong( void ); - void PlaySuddenDeathSong( void ); - void BroadcastSound( int iTeam, const char *sound ); - - inline void RespawnTeam( int iTeam ) { RespawnPlayers( false, true, iTeam ); } - - void HideActiveTimer( void ); - void RestoreActiveTimer( void ); - - virtual void InternalHandleTeamWin( int iWinningTeam ){ return; } - - bool MapHasActiveTimer( void ); - void CreateTimeLimitTimer( void ); - -protected: - CGameRulesRoundStateInfo *m_pCurStateInfo; // Per-state data - float m_flStateTransitionTime; // Timer for round states - - float m_flWaitingForPlayersTimeEnds; - CHandle m_hWaitingForPlayersTimer; - - float m_flNextPeriodicThink; - bool m_bChangeLevelOnRoundEnd; - - bool m_bResetTeamScores; - bool m_bResetPlayerScores; - bool m_bResetRoundsPlayed; - - // Stalemate - EHANDLE m_hPreviousActiveTimer; - CHandle m_hStalemateTimer; - float m_flStalemateStartTime; - - CHandle m_hTimeLimitTimer; - - bool m_bForceMapReset; // should the map be reset when a team wins and the round is restarted? - bool m_bPrevRoundWasWaitingForPlayers; // was the previous map reset after a waiting for players period - bool m_bInitialSpawn; - - string_t m_iszRoundToPlayNext; - CUtlVector m_iszPreviousRounds; // we'll store the two previous rounds so we won't play them again right away if there are other rounds that can be played first - string_t m_iszFirstRoundPlayed; // store the first round played after a full restart so we can pick a different one next time if we have other options - - float m_flOriginalTeamRespawnWaveTime[ MAX_TEAMS ]; - - bool m_bAllowStalemateAtTimelimit; - bool m_bChangelevelAfterStalemate; - - float m_flRoundStartTime; // time the current round started - - int m_nRoundsPlayed; - bool m_bUseAddScoreAnim; - -#endif - // End server specific - //---------------------------------------------------------------------------------- - - //---------------------------------------------------------------------------------- - // Client specific -#ifdef CLIENT_DLL -public: - virtual void OnPreDataChanged( DataUpdateType_t updateType ); - virtual void OnDataChanged( DataUpdateType_t updateType ); - virtual void HandleOvertimeBegin(){} - -private: - bool m_bOldInWaitingForPlayers; - bool m_bOldInOvertime; - bool m_bOldInSetup; -#endif // CLIENT_DLL - -public: - bool WouldChangeUnbalanceTeams( int iNewTeam, int iCurrentTeam ); - bool AreTeamsUnbalanced( int &iHeaviestTeam, int &iLightestTeam ); - -protected: - CNetworkVar( gamerules_roundstate_t, m_iRoundState ); - CNetworkVar( bool, m_bInOvertime ); // Are we currently in overtime? - CNetworkVar( bool, m_bInSetup ); // Are we currently in setup? - CNetworkVar( bool, m_bSwitchedTeamsThisRound ); - -protected: - CNetworkVar( int, m_iWinningTeam ); // Set before entering GR_STATE_TEAM_WIN - CNetworkVar( int, m_iWinReason ); - CNetworkVar( bool, m_bInWaitingForPlayers ); - CNetworkVar( bool, m_bAwaitingReadyRestart ); - CNetworkVar( float, m_flRestartRoundTime ); - CNetworkVar( float, m_flMapResetTime ); // Time that the map was reset - CNetworkArray( float, m_flNextRespawnWave, MAX_TEAMS ); // Minor waste, but cleaner code - CNetworkArray( bool, m_bTeamReady, MAX_TEAMS ); - CNetworkVar( bool, m_bStopWatch ); - -public: - CNetworkArray( float, m_TeamRespawnWaveTimes, MAX_TEAMS ); // Time between each team's respawn wave - -private: - float m_flStartBalancingTeamsAt; - float m_flNextBalanceTeamsTime; - bool m_bPrintedUnbalanceWarning; - float m_flFoundUnbalancedTeamsTime; - -public: - - float m_flStopWatchTotalTime; - int m_iLastCapPointChanged; -}; - -// Utility function -bool FindInList( const char **pStrings, const char *pToFind ); - -inline CTeamplayRoundBasedRules* TeamplayRoundBasedRules() -{ - return static_cast(g_pGameRules); -} - -#endif // TEAMPLAYROUNDBASED_GAMERULES_H diff --git a/game/shared/tempentity.h b/game/shared/tempentity.h deleted file mode 100644 index b754f59ab..000000000 --- a/game/shared/tempentity.h +++ /dev/null @@ -1,35 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef TEMPENTITY_H -#define TEMPENTITY_H -#ifdef _WIN32 -#pragma once -#endif - -#define TE_EXPLFLAG_NONE 0x0 // all flags clear makes default Half-Life explosion -#define TE_EXPLFLAG_NOADDITIVE 0x1 // sprite will be drawn opaque (ensure that the sprite you send is a non-additive sprite) -#define TE_EXPLFLAG_NODLIGHTS 0x2 // do not render dynamic lights -#define TE_EXPLFLAG_NOSOUND 0x4 // do not play client explosion sound -#define TE_EXPLFLAG_NOPARTICLES 0x8 // do not draw particles -#define TE_EXPLFLAG_DRAWALPHA 0x10 // sprite will be drawn alpha -#define TE_EXPLFLAG_ROTATE 0x20 // rotate the sprite randomly -#define TE_EXPLFLAG_NOFIREBALL 0x40 // do not draw a fireball -#define TE_EXPLFLAG_NOFIREBALLSMOKE 0x80 // do not draw smoke with the fireball - -#define TE_BEAMPOINTS 0 // beam effect between two points -#define TE_SPRITE 1 // additive sprite, plays 1 cycle -#define TE_BEAMDISK 2 // disk that expands to max radius over lifetime -#define TE_BEAMCYLINDER 3 // cylinder that expands to max radius over lifetime -#define TE_BEAMFOLLOW 4 // create a line of decaying beam segments until entity stops moving -#define TE_BEAMRING 5 // connect a beam ring to two entities -#define TE_BEAMSPLINE 6 -#define TE_BEAMRINGPOINT 7 -#define TE_BEAMLASER 8 // Fades according to viewpoint -#define TE_BEAMTESLA 9 - - -#endif // TEMPENTITY_H diff --git a/game/shared/test_ehandle.cpp b/game/shared/test_ehandle.cpp deleted file mode 100644 index 74f09b86a..000000000 --- a/game/shared/test_ehandle.cpp +++ /dev/null @@ -1,125 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include "cbase.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// In this test, the server makes an entity (call it A) that has an EHANDLE to another -// entity (call it B). Intitially, A is sent to the client but B is not. Later, -// the server decides to send B to the client too. At that point, without resending A's EHANDLE, -// the client's EHANDLE should access B. - -#if defined( GAME_DLL ) - - // ------------------------------------------------------------------------------------ // - // The main entity class (class A). - // ------------------------------------------------------------------------------------ // - class CHandleTest : public CBaseEntity - { - public: - DECLARE_CLASS( CHandleTest, CBaseEntity ); - DECLARE_SERVERCLASS(); - - CHandleTest() - { - m_bSendHandle = false; - } - - virtual int UpdateTransmitState() - { - // ALWAYS transmit to all clients. - return SetTransmitState( FL_EDICT_ALWAYS ); - } - - virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ) - { - if ( pInfo->m_pTransmitEdict->Get( entindex() ) ) - return; - - BaseClass::SetTransmit( pInfo, bAlways ); - - // Force the thing we're pointing at to be sent too? - if ( m_bSendHandle ) - m_Handle->SetTransmit( pInfo, bAlways ); - } - - CNetworkHandle( CBaseEntity, m_Handle ); - CNetworkVar( bool, m_bSendHandle ); - }; - - IMPLEMENT_SERVERCLASS_ST( CHandleTest, DT_HandleTest ) - SendPropEHandle( SENDINFO( m_Handle ) ), - SendPropInt( SENDINFO( m_bSendHandle ) ) - END_SEND_TABLE() - - LINK_ENTITY_TO_CLASS( handle_test, CHandleTest ); - - - // ------------------------------------------------------------------------------------ // - // The class pointed to by the handle. - // ------------------------------------------------------------------------------------ // - class CHandleDummy : public CBaseEntity - { - DECLARE_CLASS( CHandleDummy, CBaseEntity ); - public: - }; - LINK_ENTITY_TO_CLASS( handle_dummy, CHandleDummy ); - - CHandle g_HandleTest; - - // The test runs this command. - void CC_Test_EHandle() - { - if ( g_HandleTest.Get() ) - { - g_HandleTest->m_bSendHandle = !g_HandleTest->m_bSendHandle; - } - else - { - CHandleTest *pHolder = CREATE_ENTITY( CHandleTest, "handle_test" ); - pHolder->m_Handle = CREATE_ENTITY( CHandleDummy, "handle_dummy" ); - pHolder->Spawn(); - g_HandleTest = pHolder; - Msg( "Created EHANDLE test entity. Run this command again to transmit the second ent.\n" ); - } - } - ConCommand Test_EHandle( "Test_EHandle", CC_Test_EHandle, 0, FCVAR_CHEAT ); - - -#else - - class C_HandleTest : public C_BaseEntity - { - public: - DECLARE_CLASS( C_HandleTest, C_BaseEntity ); - DECLARE_CLIENTCLASS(); - - C_HandleTest() - { - } - - virtual void OnDataChanged( DataUpdateType_t type ) - { - Msg( "m_bSendHandle: %d, m_Handle.Get: 0x%p\n", m_bSendHandle, m_Handle.Get() ); - } - - EHANDLE m_Handle; - bool m_bSendHandle; - }; - - IMPLEMENT_CLIENTCLASS_DT( C_HandleTest, DT_HandleTest, CHandleTest ) - RecvPropEHandle( RECVINFO( m_Handle ) ), - RecvPropInt( RECVINFO( m_bSendHandle ) ) - END_RECV_TABLE() - - -#endif - - diff --git a/game/shared/touchlink.h b/game/shared/touchlink.h deleted file mode 100644 index 165d4b115..000000000 --- a/game/shared/touchlink.h +++ /dev/null @@ -1,39 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Shared data definition file for touch links -// -//=============================================================================// - -#ifndef TOUCHLINK_H -#define TOUCHLINK_H -#ifdef _WIN32 -#pragma once -#endif - - -//----------------------------------------------------------------------------- -// Purpose: for resolving touch/untouch pairs -//----------------------------------------------------------------------------- -enum touchlink_flags_t -{ - FTOUCHLINK_START_TOUCH = 0x00000001, -}; - -struct touchlink_t -{ -#if defined( CLIENT_DLL ) - C_BaseEntity *entityTouched; -#else - EHANDLE entityTouched; -#endif - int touchStamp; - touchlink_t *nextLink; - touchlink_t *prevLink; - int flags; -}; - -// means this touchlink is managed external to the main physics system -#define TOUCHSTAMP_EVENT_DRIVEN -1 - - -#endif // TOUCHLINK_H diff --git a/game/shared/usercmd.cpp b/game/shared/usercmd.cpp deleted file mode 100644 index a6d5b19f9..000000000 --- a/game/shared/usercmd.cpp +++ /dev/null @@ -1,304 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "usercmd.h" -#include "bitbuf.h" -#include "checksum_md5.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// TF2 specific, need enough space for OBJ_LAST items from tf_shareddefs.h -#define WEAPON_SUBTYPE_BITS 6 - -//----------------------------------------------------------------------------- -// Purpose: Write a delta compressed user command. -// Input : *buf - -// *to - -// *from - -// Output : static -//----------------------------------------------------------------------------- -void WriteUsercmd( bf_write *buf, const CUserCmd *to, const CUserCmd *from ) -{ - if ( to->command_number != ( from->command_number + 1 ) ) - { - buf->WriteOneBit( 1 ); - buf->WriteUBitLong( to->command_number, 32 ); - } - else - { - buf->WriteOneBit( 0 ); - } - - if ( to->tick_count != ( from->tick_count + 1 ) ) - { - buf->WriteOneBit( 1 ); - buf->WriteUBitLong( to->tick_count, 32 ); - } - else - { - buf->WriteOneBit( 0 ); - } - - - if ( to->viewangles[ 0 ] != from->viewangles[ 0 ] ) - { - buf->WriteOneBit( 1 ); - buf->WriteFloat( to->viewangles[ 0 ] ); - } - else - { - buf->WriteOneBit( 0 ); - } - - if ( to->viewangles[ 1 ] != from->viewangles[ 1 ] ) - { - buf->WriteOneBit( 1 ); - buf->WriteFloat( to->viewangles[ 1 ] ); - } - else - { - buf->WriteOneBit( 0 ); - } - - if ( to->viewangles[ 2 ] != from->viewangles[ 2 ] ) - { - buf->WriteOneBit( 1 ); - buf->WriteFloat( to->viewangles[ 2 ] ); - } - else - { - buf->WriteOneBit( 0 ); - } - - if ( to->forwardmove != from->forwardmove ) - { - buf->WriteOneBit( 1 ); - buf->WriteFloat( to->forwardmove ); - } - else - { - buf->WriteOneBit( 0 ); - } - - if ( to->sidemove != from->sidemove ) - { - buf->WriteOneBit( 1 ); - buf->WriteFloat( to->sidemove ); - } - else - { - buf->WriteOneBit( 0 ); - } - - if ( to->upmove != from->upmove ) - { - buf->WriteOneBit( 1 ); - buf->WriteFloat( to->upmove ); - } - else - { - buf->WriteOneBit( 0 ); - } - - if ( to->buttons != from->buttons ) - { - buf->WriteOneBit( 1 ); - buf->WriteUBitLong( to->buttons, 32 ); - } - else - { - buf->WriteOneBit( 0 ); - } - - if ( to->impulse != from->impulse ) - { - buf->WriteOneBit( 1 ); - buf->WriteUBitLong( to->impulse, 8 ); - } - else - { - buf->WriteOneBit( 0 ); - } - - - if ( to->weaponselect != from->weaponselect ) - { - buf->WriteOneBit( 1 ); - buf->WriteUBitLong( to->weaponselect, MAX_EDICT_BITS ); - - if ( to->weaponsubtype != from->weaponsubtype ) - { - buf->WriteOneBit( 1 ); - buf->WriteUBitLong( to->weaponsubtype, WEAPON_SUBTYPE_BITS ); - } - else - { - buf->WriteOneBit( 0 ); - } - } - else - { - buf->WriteOneBit( 0 ); - } - - - // TODO: Can probably get away with fewer bits. - if ( to->mousedx != from->mousedx ) - { - buf->WriteOneBit( 1 ); - buf->WriteShort( to->mousedx ); - } - else - { - buf->WriteOneBit( 0 ); - } - - if ( to->mousedy != from->mousedy ) - { - buf->WriteOneBit( 1 ); - buf->WriteShort( to->mousedy ); - } - else - { - buf->WriteOneBit( 0 ); - } - -#if defined( HL2_CLIENT_DLL ) - if ( to->entitygroundcontact.Count() != 0 ) - { - buf->WriteOneBit( 1 ); - buf->WriteShort( to->entitygroundcontact.Count() ); - int i; - for (i = 0; i < to->entitygroundcontact.Count(); i++) - { - buf->WriteUBitLong( to->entitygroundcontact[i].entindex, MAX_EDICT_BITS ); - buf->WriteBitCoord( to->entitygroundcontact[i].minheight ); - buf->WriteBitCoord( to->entitygroundcontact[i].maxheight ); - } - } - else - { - buf->WriteOneBit( 0 ); - } -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Read in a delta compressed usercommand. -// Input : *buf - -// *move - -// *from - -// Output : static void ReadUsercmd -//----------------------------------------------------------------------------- -void ReadUsercmd( bf_read *buf, CUserCmd *move, CUserCmd *from ) -{ - // Assume no change - *move = *from; - - if ( buf->ReadOneBit() ) - { - move->command_number = buf->ReadUBitLong( 32 ); - } - else - { - // Assume steady increment - move->command_number = from->command_number + 1; - } - - if ( buf->ReadOneBit() ) - { - move->tick_count = buf->ReadUBitLong( 32 ); - } - else - { - // Assume steady increment - move->tick_count = from->tick_count + 1; - } - - // Read direction - if ( buf->ReadOneBit() ) - { - move->viewangles[0] = buf->ReadFloat(); - } - - if ( buf->ReadOneBit() ) - { - move->viewangles[1] = buf->ReadFloat(); - } - - if ( buf->ReadOneBit() ) - { - move->viewangles[2] = buf->ReadFloat(); - } - - // Read movement - if ( buf->ReadOneBit() ) - { - move->forwardmove = buf->ReadFloat(); - } - - if ( buf->ReadOneBit() ) - { - move->sidemove = buf->ReadFloat(); - } - - if ( buf->ReadOneBit() ) - { - move->upmove = buf->ReadFloat(); - } - - // read buttons - if ( buf->ReadOneBit() ) - { - move->buttons = buf->ReadUBitLong( 32 ); - } - - if ( buf->ReadOneBit() ) - { - move->impulse = buf->ReadUBitLong( 8 ); - } - - - if ( buf->ReadOneBit() ) - { - move->weaponselect = buf->ReadUBitLong( MAX_EDICT_BITS ); - if ( buf->ReadOneBit() ) - { - move->weaponsubtype = buf->ReadUBitLong( WEAPON_SUBTYPE_BITS ); - } - } - - - move->random_seed = MD5_PseudoRandom( move->command_number ) & 0x7fffffff; - - if ( buf->ReadOneBit() ) - { - move->mousedx = buf->ReadShort(); - } - - if ( buf->ReadOneBit() ) - { - move->mousedy = buf->ReadShort(); - } - -#if defined( HL2_DLL ) - if ( buf->ReadOneBit() ) - { - move->entitygroundcontact.SetCount( buf->ReadShort() ); - - int i; - for (i = 0; i < move->entitygroundcontact.Count(); i++) - { - move->entitygroundcontact[i].entindex = buf->ReadUBitLong( MAX_EDICT_BITS ); - move->entitygroundcontact[i].minheight = buf->ReadBitCoord( ); - move->entitygroundcontact[i].maxheight = buf->ReadBitCoord( ); - } - } -#endif -} diff --git a/game/shared/usercmd.h b/game/shared/usercmd.h deleted file mode 100644 index 10b13cd73..000000000 --- a/game/shared/usercmd.h +++ /dev/null @@ -1,160 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#if !defined( USERCMD_H ) -#define USERCMD_H -#ifdef _WIN32 -#pragma once -#endif - -#include "mathlib/vector.h" -#include "utlvector.h" -#include "imovehelper.h" -#include "checksum_crc.h" - - -class bf_read; -class bf_write; - -class CEntityGroundContact -{ -public: - int entindex; - float minheight; - float maxheight; -}; - -class CUserCmd -{ -public: - CUserCmd() - { - Reset(); - } - - virtual ~CUserCmd() { }; - - void Reset() - { - command_number = 0; - tick_count = 0; - viewangles.Init(); - forwardmove = 0.0f; - sidemove = 0.0f; - upmove = 0.0f; - buttons = 0; - impulse = 0; - weaponselect = 0; - weaponsubtype = 0; - random_seed = 0; - mousedx = 0; - mousedy = 0; - - hasbeenpredicted = false; -#if defined( HL2_DLL ) || defined( HL2_CLIENT_DLL ) - entitygroundcontact.RemoveAll(); -#endif - } - - CUserCmd& operator =( const CUserCmd& src ) - { - if ( this == &src ) - return *this; - - command_number = src.command_number; - tick_count = src.tick_count; - viewangles = src.viewangles; - forwardmove = src.forwardmove; - sidemove = src.sidemove; - upmove = src.upmove; - buttons = src.buttons; - impulse = src.impulse; - weaponselect = src.weaponselect; - weaponsubtype = src.weaponsubtype; - random_seed = src.random_seed; - mousedx = src.mousedx; - mousedy = src.mousedy; - - hasbeenpredicted = src.hasbeenpredicted; - -#if defined( HL2_DLL ) || defined( HL2_CLIENT_DLL ) - entitygroundcontact = src.entitygroundcontact; -#endif - - return *this; - } - - CUserCmd( const CUserCmd& src ) - { - *this = src; - } - - CRC32_t GetChecksum( void ) const - { - CRC32_t crc; - - CRC32_Init( &crc ); - CRC32_ProcessBuffer( &crc, &command_number, sizeof( command_number ) ); - CRC32_ProcessBuffer( &crc, &tick_count, sizeof( tick_count ) ); - CRC32_ProcessBuffer( &crc, &viewangles, sizeof( viewangles ) ); - CRC32_ProcessBuffer( &crc, &forwardmove, sizeof( forwardmove ) ); - CRC32_ProcessBuffer( &crc, &sidemove, sizeof( sidemove ) ); - CRC32_ProcessBuffer( &crc, &upmove, sizeof( upmove ) ); - CRC32_ProcessBuffer( &crc, &buttons, sizeof( buttons ) ); - CRC32_ProcessBuffer( &crc, &impulse, sizeof( impulse ) ); - CRC32_ProcessBuffer( &crc, &weaponselect, sizeof( weaponselect ) ); - CRC32_ProcessBuffer( &crc, &weaponsubtype, sizeof( weaponsubtype ) ); - CRC32_ProcessBuffer( &crc, &random_seed, sizeof( random_seed ) ); - CRC32_ProcessBuffer( &crc, &mousedx, sizeof( mousedx ) ); - CRC32_ProcessBuffer( &crc, &mousedy, sizeof( mousedy ) ); - CRC32_Final( &crc ); - - return crc; - } - - // For matching server and client commands for debugging - int command_number; - - // the tick the client created this command - int tick_count; - - // Player instantaneous view angles. - QAngle viewangles; - // Intended velocities - // forward velocity. - float forwardmove; - // sideways velocity. - float sidemove; - // upward velocity. - float upmove; - // Attack button states - int buttons; - // Impulse command issued. - byte impulse; - // Current weapon id - int weaponselect; - int weaponsubtype; - - int random_seed; // For shared random functions - - short mousedx; // mouse accum in x from create move - short mousedy; // mouse accum in y from create move - - // Client only, tracks whether we've predicted this command at least once - bool hasbeenpredicted; - - // Back channel to communicate IK state -#if defined( HL2_DLL ) || defined( HL2_CLIENT_DLL ) - CUtlVector< CEntityGroundContact > entitygroundcontact; -#endif - -}; - -void ReadUsercmd( bf_read *buf, CUserCmd *move, CUserCmd *from ); -void WriteUsercmd( bf_write *buf, const CUserCmd *to, const CUserCmd *from ); - -#endif // USERCMD_H diff --git a/game/shared/usermessages.cpp b/game/shared/usermessages.cpp deleted file mode 100644 index 31d3cfab5..000000000 --- a/game/shared/usermessages.cpp +++ /dev/null @@ -1,191 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "usermessages.h" -#include - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -void RegisterUserMessages( void ); - -//----------------------------------------------------------------------------- -// Purpose: Force registration on .dll load -// FIXME: Should this be a client/server system? -//----------------------------------------------------------------------------- -CUserMessages::CUserMessages() -{ - // Game specific registration function; - RegisterUserMessages(); -} - -CUserMessages::~CUserMessages() -{ - int c = m_UserMessages.Count(); - for ( int i = 0; i < c; ++i ) - { - delete m_UserMessages[ i ]; - } - m_UserMessages.RemoveAll(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -// Output : int -//----------------------------------------------------------------------------- -int CUserMessages::LookupUserMessage( const char *name ) -{ - int idx = m_UserMessages.Find( name ); - if ( idx == m_UserMessages.InvalidIndex() ) - { - return -1; - } - - return idx; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -// Output : int -//----------------------------------------------------------------------------- -int CUserMessages::GetUserMessageSize( int index ) -{ - if ( index < 0 || index >= (int)m_UserMessages.Count() ) - { - Error( "CUserMessages::GetUserMessageSize( %i ) out of range!!!\n", index ); - } - - CUserMessage *e = m_UserMessages[ index ]; - return e->size; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -// Output : char const -//----------------------------------------------------------------------------- -const char *CUserMessages::GetUserMessageName( int index ) -{ - if ( index < 0 || index >= (int)m_UserMessages.Count() ) - { - Error( "CUserMessages::GetUserMessageSize( %i ) out of range!!!\n", index ); - } - - return m_UserMessages.GetElementName( index ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : index - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CUserMessages::IsValidIndex( int index ) -{ - return m_UserMessages.IsValidIndex( index ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -// size - -1 for variable size -//----------------------------------------------------------------------------- -void CUserMessages::Register( const char *name, int size ) -{ - Assert( name ); - int idx = m_UserMessages.Find( name ); - if ( idx != m_UserMessages.InvalidIndex() ) - { - Error( "CUserMessages::Register '%' already registered\n", name ); - } - - CUserMessage * entry = new CUserMessage; - entry->size = size; - entry->name = name; - - m_UserMessages.Insert( name, entry ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -// hook - -//----------------------------------------------------------------------------- -void CUserMessages::HookMessage( const char *name, pfnUserMsgHook hook ) -{ -#if defined( CLIENT_DLL ) - Assert( name ); - Assert( hook ); - - int idx = m_UserMessages.Find( name ); - if ( idx == m_UserMessages.InvalidIndex() ) - { - DevMsg( "CUserMessages::HookMessage: no such message %s\n", name ); - Assert( 0 ); - return; - } - - int i = m_UserMessages[ idx ]->clienthooks.AddToTail(); - m_UserMessages[ idx ]->clienthooks[i] = hook; - -#else - Error( "CUserMessages::HookMessage called from server code!!!\n" ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pszName - -// iSize - -// *pbuf - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CUserMessages::DispatchUserMessage( int msg_type, bf_read &msg_data ) -{ -#if defined( CLIENT_DLL ) - if ( msg_type < 0 || msg_type >= (int)m_UserMessages.Count() ) - { - DevMsg( "CUserMessages::DispatchUserMessage: Bogus msg type %i (max == %i)\n", msg_type, m_UserMessages.Count() ); - Assert( 0 ); - return false; - } - - CUserMessage *entry = m_UserMessages[ msg_type ]; - - if ( !entry ) - { - DevMsg( "CUserMessages::DispatchUserMessage: Missing client entry for msg type %i\n", msg_type ); - Assert( 0 ); - return false; - } - - if ( entry->clienthooks.Count() == 0 ) - { - DevMsg( "CUserMessages::DispatchUserMessage: missing client hook for %s\n", GetUserMessageName(msg_type) ); - Assert( 0 ); - return false; - } - - for (int i = 0; i < entry->clienthooks.Count(); i++ ) - { - bf_read msg_copy = msg_data; - - pfnUserMsgHook hook = entry->clienthooks[i]; - (*hook)( msg_copy ); - } - return true; -#else - Error( "CUserMessages::DispatchUserMessage called from server code!!!\n" ); - return false; -#endif -} - -// Singleton -static CUserMessages g_UserMessages; -// Expose to rest of .dll -CUserMessages *usermessages = &g_UserMessages; diff --git a/game/shared/usermessages.h b/game/shared/usermessages.h deleted file mode 100644 index 2619b5a83..000000000 --- a/game/shared/usermessages.h +++ /dev/null @@ -1,65 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef USERMESSAGES_H -#define USERMESSAGES_H -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include - - -// Client dispatch function for usermessages -typedef void (*pfnUserMsgHook)(bf_read &msg); - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CUserMessage -{ - public: - // byte size of message, or -1 for variable sized - int size; - const char *name; - // Client only dispatch function for message - CUtlVector clienthooks; -}; - -//----------------------------------------------------------------------------- -// Purpose: Interface for registering and dispatching usermessages -// Shred code creates same ordered list on client/server -//----------------------------------------------------------------------------- -class CUserMessages -{ -public: - - CUserMessages(); - ~CUserMessages(); - - // Returns -1 if not found, otherwise, returns appropriate index - int LookupUserMessage( const char *name ); - int GetUserMessageSize( int index ); - const char *GetUserMessageName( int index ); - bool IsValidIndex( int index ); - - // Server only - void Register( const char *name, int size ); - - // Client only - void HookMessage( const char *name, pfnUserMsgHook hook ); - bool DispatchUserMessage( int msg_type, bf_read &msg_data ); - -private: - - CUtlDict< CUserMessage*, int > m_UserMessages; -}; - -extern CUserMessages *usermessages; - -#endif // USERMESSAGES_H diff --git a/game/shared/util_shared.cpp b/game/shared/util_shared.cpp deleted file mode 100644 index 068e956e2..000000000 --- a/game/shared/util_shared.cpp +++ /dev/null @@ -1,1072 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "mathlib/mathlib.h" -#include "util_shared.h" -#include "model_types.h" -#include "convar.h" -#include "IEffects.h" -#include "vphysics/object_hash.h" -#include "mathlib/IceKey.H" -#include "checksum_crc.h" -#include "particle_parse.h" -#include "KeyValues.h" - -#ifdef CLIENT_DLL - #include "c_te_effect_dispatch.h" -#else - #include "te_effect_dispatch.h" - -bool NPC_CheckBrushExclude( CBaseEntity *pEntity, CBaseEntity *pBrush ); -#endif - - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ConVar r_visualizetraces( "r_visualizetraces", "0", FCVAR_CHEAT ); -ConVar developer("developer", "0", 0, "Set developer message level" ); // developer mode - -float UTIL_VecToYaw( const Vector &vec ) -{ - if (vec.y == 0 && vec.x == 0) - return 0; - - float yaw = atan2( vec.y, vec.x ); - - yaw = RAD2DEG(yaw); - - if (yaw < 0) - yaw += 360; - - return yaw; -} - - -float UTIL_VecToPitch( const Vector &vec ) -{ - if (vec.y == 0 && vec.x == 0) - { - if (vec.z < 0) - return 180.0; - else - return -180.0; - } - - float dist = vec.Length2D(); - float pitch = atan2( -vec.z, dist ); - - pitch = RAD2DEG(pitch); - - return pitch; -} - -float UTIL_VecToYaw( const matrix3x4_t &matrix, const Vector &vec ) -{ - Vector tmp = vec; - VectorNormalize( tmp ); - - float x = matrix[0][0] * tmp.x + matrix[1][0] * tmp.y + matrix[2][0] * tmp.z; - float y = matrix[0][1] * tmp.x + matrix[1][1] * tmp.y + matrix[2][1] * tmp.z; - - if (x == 0.0f && y == 0.0f) - return 0.0f; - - float yaw = atan2( -y, x ); - - yaw = RAD2DEG(yaw); - - if (yaw < 0) - yaw += 360; - - return yaw; -} - - -float UTIL_VecToPitch( const matrix3x4_t &matrix, const Vector &vec ) -{ - Vector tmp = vec; - VectorNormalize( tmp ); - - float x = matrix[0][0] * tmp.x + matrix[1][0] * tmp.y + matrix[2][0] * tmp.z; - float z = matrix[0][2] * tmp.x + matrix[1][2] * tmp.y + matrix[2][2] * tmp.z; - - if (x == 0.0f && z == 0.0f) - return 0.0f; - - float pitch = atan2( z, x ); - - pitch = RAD2DEG(pitch); - - if (pitch < 0) - pitch += 360; - - return pitch; -} - -Vector UTIL_YawToVector( float yaw ) -{ - Vector ret; - - ret.z = 0; - float angle = DEG2RAD( yaw ); - SinCos( angle, &ret.y, &ret.x ); - - return ret; -} - -//----------------------------------------------------------------------------- -// Purpose: Helper function get get determinisitc random values for shared/prediction code -// Input : seedvalue - -// *module - -// line - -// Output : static int -//----------------------------------------------------------------------------- -static int SeedFileLineHash( int seedvalue, const char *sharedname, int additionalSeed ) -{ - CRC32_t retval; - - CRC32_Init( &retval ); - - CRC32_ProcessBuffer( &retval, (void *)&seedvalue, sizeof( int ) ); - CRC32_ProcessBuffer( &retval, (void *)&additionalSeed, sizeof( int ) ); - CRC32_ProcessBuffer( &retval, (void *)sharedname, Q_strlen( sharedname ) ); - - CRC32_Final( &retval ); - - return (int)( retval ); -} - -float SharedRandomFloat( const char *sharedname, float flMinVal, float flMaxVal, int additionalSeed /*=0*/ ) -{ - Assert( CBaseEntity::GetPredictionRandomSeed() != -1 ); - - int seed = SeedFileLineHash( CBaseEntity::GetPredictionRandomSeed(), sharedname, additionalSeed ); - RandomSeed( seed ); - return RandomFloat( flMinVal, flMaxVal ); -} - -int SharedRandomInt( const char *sharedname, int iMinVal, int iMaxVal, int additionalSeed /*=0*/ ) -{ - Assert( CBaseEntity::GetPredictionRandomSeed() != -1 ); - - int seed = SeedFileLineHash( CBaseEntity::GetPredictionRandomSeed(), sharedname, additionalSeed ); - RandomSeed( seed ); - return RandomInt( iMinVal, iMaxVal ); -} - -Vector SharedRandomVector( const char *sharedname, float minVal, float maxVal, int additionalSeed /*=0*/ ) -{ - Assert( CBaseEntity::GetPredictionRandomSeed() != -1 ); - - int seed = SeedFileLineHash( CBaseEntity::GetPredictionRandomSeed(), sharedname, additionalSeed ); - RandomSeed( seed ); - // HACK: Can't call RandomVector/Angle because it uses rand() not vstlib Random*() functions! - // Get a random vector. - Vector random; - random.x = RandomFloat( minVal, maxVal ); - random.y = RandomFloat( minVal, maxVal ); - random.z = RandomFloat( minVal, maxVal ); - return random; -} - -QAngle SharedRandomAngle( const char *sharedname, float minVal, float maxVal, int additionalSeed /*=0*/ ) -{ - Assert( CBaseEntity::GetPredictionRandomSeed() != -1 ); - - int seed = SeedFileLineHash( CBaseEntity::GetPredictionRandomSeed(), sharedname, additionalSeed ); - RandomSeed( seed ); - - // HACK: Can't call RandomVector/Angle because it uses rand() not vstlib Random*() functions! - // Get a random vector. - Vector random; - random.x = RandomFloat( minVal, maxVal ); - random.y = RandomFloat( minVal, maxVal ); - random.z = RandomFloat( minVal, maxVal ); - return QAngle( random.x, random.y, random.z ); -} - - -//----------------------------------------------------------------------------- -// -// Shared client/server trace filter code -// -//----------------------------------------------------------------------------- -bool PassServerEntityFilter( const IHandleEntity *pTouch, const IHandleEntity *pPass ) -{ - if ( !pPass ) - return true; - - if ( pTouch == pPass ) - return false; - - const CBaseEntity *pEntTouch = EntityFromEntityHandle( pTouch ); - const CBaseEntity *pEntPass = EntityFromEntityHandle( pPass ); - if ( !pEntTouch || !pEntPass ) - return true; - - // don't clip against own missiles - if ( pEntTouch->GetOwnerEntity() == pEntPass ) - return false; - - // don't clip against owner - if ( pEntPass->GetOwnerEntity() == pEntTouch ) - return false; - - - return true; -} - - -//----------------------------------------------------------------------------- -// A standard filter to be applied to just about everything. -//----------------------------------------------------------------------------- -bool StandardFilterRules( IHandleEntity *pHandleEntity, int fContentsMask ) -{ - CBaseEntity *pCollide = EntityFromEntityHandle( pHandleEntity ); - - // Static prop case... - if ( !pCollide ) - return true; - - SolidType_t solid = pCollide->GetSolid(); - const model_t *pModel = pCollide->GetModel(); - - if ( ( modelinfo->GetModelType( pModel ) != mod_brush ) || (solid != SOLID_BSP && solid != SOLID_VPHYSICS) ) - { - if ( (fContentsMask & CONTENTS_MONSTER) == 0 ) - return false; - } - - // This code is used to cull out tests against see-thru entities - if ( !(fContentsMask & CONTENTS_WINDOW) && pCollide->IsTransparent() ) - return false; - - // FIXME: this is to skip BSP models that are entities that can be - // potentially moved/deleted, similar to a monster but doors don't seem to - // be flagged as monsters - // FIXME: the FL_WORLDBRUSH looked promising, but it needs to be set on - // everything that's actually a worldbrush and it currently isn't - if ( !(fContentsMask & CONTENTS_MOVEABLE) && (pCollide->GetMoveType() == MOVETYPE_PUSH))// !(touch->flags & FL_WORLDBRUSH) ) - return false; - - return true; -} - - - -//----------------------------------------------------------------------------- -// Simple trace filter -//----------------------------------------------------------------------------- -CTraceFilterSimple::CTraceFilterSimple( const IHandleEntity *passedict, int collisionGroup ) -{ - m_pPassEnt = passedict; - m_collisionGroup = collisionGroup; -} - - -//----------------------------------------------------------------------------- -// The trace filter! -//----------------------------------------------------------------------------- -bool CTraceFilterSimple::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) -{ - if ( !StandardFilterRules( pHandleEntity, contentsMask ) ) - return false; - - if ( m_pPassEnt ) - { - if ( !PassServerEntityFilter( pHandleEntity, m_pPassEnt ) ) - { - return false; - } - } - - // Don't test if the game code tells us we should ignore this collision... - CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); - if ( !pEntity ) - return false; - if ( !pEntity->ShouldCollide( m_collisionGroup, contentsMask ) ) - return false; - if ( pEntity && !g_pGameRules->ShouldCollide( m_collisionGroup, pEntity->GetCollisionGroup() ) ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Trace filter that only hits NPCs and the player -//----------------------------------------------------------------------------- -bool CTraceFilterOnlyNPCsAndPlayer::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) -{ - if ( CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask ) ) - { - CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); - if ( !pEntity ) - return false; - -#ifdef CSTRIKE_DLL -#ifndef CLIENT_DLL - if ( pEntity->Classify() == CLASS_PLAYER_ALLY ) - return true; // CS hostages are CLASS_PLAYER_ALLY but not IsNPC() -#endif // !CLIENT_DLL -#endif // CSTRIKE_DLL - return (pEntity->IsNPC() || pEntity->IsPlayer()); - } - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: Trace filter that only hits anything but NPCs and the player -//----------------------------------------------------------------------------- -bool CTraceFilterNoNPCsOrPlayer::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) -{ - if ( CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask ) ) - { - CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); - if ( !pEntity ) - return false; -#ifndef CLIENT_DLL - if ( pEntity->Classify() == CLASS_PLAYER_ALLY ) - return false; // CS hostages are CLASS_PLAYER_ALLY but not IsNPC() -#endif - return (!pEntity->IsNPC() && !pEntity->IsPlayer()); - } - return false; -} - -//----------------------------------------------------------------------------- -// Trace filter that skips two entities -//----------------------------------------------------------------------------- -CTraceFilterSkipTwoEntities::CTraceFilterSkipTwoEntities( const IHandleEntity *passentity, const IHandleEntity *passentity2, int collisionGroup ) : - BaseClass( passentity, collisionGroup ), m_pPassEnt2(passentity2) -{ -} - -bool CTraceFilterSkipTwoEntities::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) -{ - Assert( pHandleEntity ); - if ( !PassServerEntityFilter( pHandleEntity, m_pPassEnt2 ) ) - return false; - - return BaseClass::ShouldHitEntity( pHandleEntity, contentsMask ); -} - - -//----------------------------------------------------------------------------- -// Trace filter that can take a list of entities to ignore -//----------------------------------------------------------------------------- -CTraceFilterSimpleList::CTraceFilterSimpleList( int collisionGroup ) : - CTraceFilterSimple( NULL, collisionGroup ) -{ -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTraceFilterSimpleList::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) -{ - if ( m_PassEntities.Find(pHandleEntity) != m_PassEntities.InvalidIndex() ) - return false; - - return CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Add an entity to my list of entities to ignore in the trace -//----------------------------------------------------------------------------- -void CTraceFilterSimpleList::AddEntityToIgnore( IHandleEntity *pEntity ) -{ - m_PassEntities.AddToTail( pEntity ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Custom trace filter used for NPC LOS traces -//----------------------------------------------------------------------------- -CTraceFilterLOS::CTraceFilterLOS( IHandleEntity *pHandleEntity, int collisionGroup, IHandleEntity *pHandleEntity2 ) : - CTraceFilterSkipTwoEntities( pHandleEntity, pHandleEntity2, collisionGroup ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTraceFilterLOS::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) -{ - CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); - - if ( !pEntity->BlocksLOS() ) - return false; - - return CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask ); -} - -//----------------------------------------------------------------------------- -// Trace filter that can take a classname to ignore -//----------------------------------------------------------------------------- -CTraceFilterSkipClassname::CTraceFilterSkipClassname( const IHandleEntity *passentity, const char *pchClassname, int collisionGroup ) : -CTraceFilterSimple( passentity, collisionGroup ), m_pchClassname( pchClassname ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTraceFilterSkipClassname::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) -{ - CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); - if ( !pEntity || FClassnameIs( pEntity, m_pchClassname ) ) - return false; - - return CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask ); -} - -//----------------------------------------------------------------------------- -// Trace filter that skips two classnames -//----------------------------------------------------------------------------- -CTraceFilterSkipTwoClassnames::CTraceFilterSkipTwoClassnames( const IHandleEntity *passentity, const char *pchClassname, const char *pchClassname2, int collisionGroup ) : -BaseClass( passentity, pchClassname, collisionGroup ), m_pchClassname2(pchClassname2) -{ -} - -bool CTraceFilterSkipTwoClassnames::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) -{ - CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); - if ( !pEntity || FClassnameIs( pEntity, m_pchClassname2 ) ) - return false; - - return BaseClass::ShouldHitEntity( pHandleEntity, contentsMask ); -} - -//----------------------------------------------------------------------------- -// Trace filter that can take a list of entities to ignore -//----------------------------------------------------------------------------- -CTraceFilterSimpleClassnameList::CTraceFilterSimpleClassnameList( const IHandleEntity *passentity, int collisionGroup ) : -CTraceFilterSimple( passentity, collisionGroup ) -{ -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CTraceFilterSimpleClassnameList::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) -{ - CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); - if ( !pEntity ) - return false; - - for ( int i = 0; i < m_PassClassnames.Count(); ++i ) - { - if ( FClassnameIs( pEntity, m_PassClassnames[ i ] ) ) - return false; - } - - return CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Add an entity to my list of entities to ignore in the trace -//----------------------------------------------------------------------------- -void CTraceFilterSimpleClassnameList::AddClassnameToIgnore( const char *pchClassname ) -{ - m_PassClassnames.AddToTail( pchClassname ); -} - -CTraceFilterChain::CTraceFilterChain( ITraceFilter *pTraceFilter1, ITraceFilter *pTraceFilter2 ) -{ - m_pTraceFilter1 = pTraceFilter1; - m_pTraceFilter2 = pTraceFilter2; -} - -bool CTraceFilterChain::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) -{ - bool bResult1 = true; - bool bResult2 = true; - - if ( m_pTraceFilter1 ) - bResult1 = m_pTraceFilter1->ShouldHitEntity( pHandleEntity, contentsMask ); - - - if ( m_pTraceFilter2 ) - bResult2 = m_pTraceFilter2->ShouldHitEntity( pHandleEntity, contentsMask ); - - return ( bResult1 && bResult2 ); -} - -//----------------------------------------------------------------------------- -// Sweeps against a particular model, using collision rules -//----------------------------------------------------------------------------- -void UTIL_TraceModel( const Vector &vecStart, const Vector &vecEnd, const Vector &hullMin, - const Vector &hullMax, CBaseEntity *pentModel, int collisionGroup, trace_t *ptr ) -{ - // Cull it.... - if ( pentModel && pentModel->ShouldCollide( collisionGroup, MASK_ALL ) ) - { - Ray_t ray; - ray.Init( vecStart, vecEnd, hullMin, hullMax ); - enginetrace->ClipRayToEntity( ray, MASK_ALL, pentModel, ptr ); - } - else - { - memset( ptr, 0, sizeof(trace_t) ); - ptr->fraction = 1.0f; - } -} - -bool UTIL_EntityHasMatchingRootParent( CBaseEntity *pRootParent, CBaseEntity *pEntity ) -{ - if ( pRootParent ) - { - // NOTE: Don't let siblings/parents collide. - if ( pRootParent == pEntity->GetRootMoveParent() ) - return true; - if ( pEntity->GetOwnerEntity() && pRootParent == pEntity->GetOwnerEntity()->GetRootMoveParent() ) - return true; - } - return false; -} - -//----------------------------------------------------------------------------- -// Sweep an entity from the starting to the ending position -//----------------------------------------------------------------------------- -class CTraceFilterEntity : public CTraceFilterSimple -{ - DECLARE_CLASS( CTraceFilterEntity, CTraceFilterSimple ); - -public: - CTraceFilterEntity( CBaseEntity *pEntity, int nCollisionGroup ) - : CTraceFilterSimple( pEntity, nCollisionGroup ) - { - m_pRootParent = pEntity->GetRootMoveParent(); - m_pEntity = pEntity; - m_checkHash = g_EntityCollisionHash->IsObjectInHash(pEntity); - } - - bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) - { - CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity ); - if ( !pEntity ) - return false; - - // Check parents against each other - // NOTE: Don't let siblings/parents collide. - if ( UTIL_EntityHasMatchingRootParent( m_pRootParent, pEntity ) ) - return false; - - if ( m_checkHash ) - { - if ( g_EntityCollisionHash->IsObjectPairInHash( m_pEntity, pEntity ) ) - return false; - } - -#ifndef CLIENT_DLL - if ( m_pEntity->IsNPC() ) - { - if ( NPC_CheckBrushExclude( m_pEntity, pEntity ) ) - return false; - - } -#endif - - return BaseClass::ShouldHitEntity( pHandleEntity, contentsMask ); - } - -private: - - CBaseEntity *m_pRootParent; - CBaseEntity *m_pEntity; - bool m_checkHash; -}; - -class CTraceFilterEntityIgnoreOther : public CTraceFilterEntity -{ - DECLARE_CLASS( CTraceFilterEntityIgnoreOther, CTraceFilterEntity ); -public: - CTraceFilterEntityIgnoreOther( CBaseEntity *pEntity, const IHandleEntity *pIgnore, int nCollisionGroup ) : - CTraceFilterEntity( pEntity, nCollisionGroup ), m_pIgnoreOther( pIgnore ) - { - } - - bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) - { - if ( pHandleEntity == m_pIgnoreOther ) - return false; - - return BaseClass::ShouldHitEntity( pHandleEntity, contentsMask ); - } - -private: - const IHandleEntity *m_pIgnoreOther; -}; - -//----------------------------------------------------------------------------- -// Sweeps a particular entity through the world -//----------------------------------------------------------------------------- -void UTIL_TraceEntity( CBaseEntity *pEntity, const Vector &vecAbsStart, const Vector &vecAbsEnd, unsigned int mask, trace_t *ptr ) -{ - ICollideable *pCollision = pEntity->GetCollideable(); - - // Adding this assertion here so game code catches it, but really the assertion belongs in the engine - // because one day, rotated collideables will work! - Assert( pCollision->GetCollisionAngles() == vec3_angle ); - - CTraceFilterEntity traceFilter( pEntity, pCollision->GetCollisionGroup() ); - -#ifdef PORTAL - UTIL_Portal_TraceEntity( pEntity, vecAbsStart, vecAbsEnd, mask, &traceFilter, ptr ); -#else - enginetrace->SweepCollideable( pCollision, vecAbsStart, vecAbsEnd, pCollision->GetCollisionAngles(), mask, &traceFilter, ptr ); -#endif -} - -void UTIL_TraceEntity( CBaseEntity *pEntity, const Vector &vecAbsStart, const Vector &vecAbsEnd, - unsigned int mask, const IHandleEntity *pIgnore, int nCollisionGroup, trace_t *ptr ) -{ - ICollideable *pCollision; - pCollision = pEntity->GetCollideable(); - - // Adding this assertion here so game code catches it, but really the assertion belongs in the engine - // because one day, rotated collideables will work! - Assert( pCollision->GetCollisionAngles() == vec3_angle ); - - CTraceFilterEntityIgnoreOther traceFilter( pEntity, pIgnore, nCollisionGroup ); - -#ifdef PORTAL - UTIL_Portal_TraceEntity( pEntity, vecAbsStart, vecAbsEnd, mask, &traceFilter, ptr ); -#else - enginetrace->SweepCollideable( pCollision, vecAbsStart, vecAbsEnd, pCollision->GetCollisionAngles(), mask, &traceFilter, ptr ); -#endif -} - -void UTIL_TraceEntity( CBaseEntity *pEntity, const Vector &vecAbsStart, const Vector &vecAbsEnd, - unsigned int mask, ITraceFilter *pFilter, trace_t *ptr ) -{ - ICollideable *pCollision; - pCollision = pEntity->GetCollideable(); - - // Adding this assertion here so game code catches it, but really the assertion belongs in the engine - // because one day, rotated collideables will work! - Assert( pCollision->GetCollisionAngles() == vec3_angle ); - -#ifdef PORTAL - UTIL_Portal_TraceEntity( pEntity, vecAbsStart, vecAbsEnd, mask, pFilter, ptr ); -#else - enginetrace->SweepCollideable( pCollision, vecAbsStart, vecAbsEnd, pCollision->GetCollisionAngles(), mask, pFilter, ptr ); -#endif -} - -// ---- -// This is basically a regular TraceLine that uses the FilterEntity filter. -void UTIL_TraceLineFilterEntity( CBaseEntity *pEntity, const Vector &vecAbsStart, const Vector &vecAbsEnd, - unsigned int mask, int nCollisionGroup, trace_t *ptr ) -{ - CTraceFilterEntity traceFilter( pEntity, nCollisionGroup ); - UTIL_TraceLine( vecAbsStart, vecAbsEnd, mask, &traceFilter, ptr ); -} - -void UTIL_ClipTraceToPlayers( const Vector& vecAbsStart, const Vector& vecAbsEnd, unsigned int mask, ITraceFilter *filter, trace_t *tr ) -{ - trace_t playerTrace; - Ray_t ray; - float smallestFraction = tr->fraction; - const float maxRange = 60.0f; - - ray.Init( vecAbsStart, vecAbsEnd ); - - for ( int k = 1; k <= gpGlobals->maxClients; ++k ) - { - CBasePlayer *player = UTIL_PlayerByIndex( k ); - - if ( !player || !player->IsAlive() ) - continue; - -#ifdef CLIENT_DLL - if ( player->IsDormant() ) - continue; -#endif // CLIENT_DLL - - if ( filter && filter->ShouldHitEntity( player, mask ) == false ) - continue; - - float range = DistanceToRay( player->WorldSpaceCenter(), vecAbsStart, vecAbsEnd ); - if ( range < 0.0f || range > maxRange ) - continue; - - enginetrace->ClipRayToEntity( ray, mask|CONTENTS_HITBOX, player, &playerTrace ); - if ( playerTrace.fraction < smallestFraction ) - { - // we shortened the ray - save off the trace - *tr = playerTrace; - smallestFraction = playerTrace.fraction; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Make a tracer using a particle effect -//----------------------------------------------------------------------------- -void UTIL_ParticleTracer( const char *pszTracerEffectName, const Vector &vecStart, const Vector &vecEnd, - int iEntIndex, int iAttachment, bool bWhiz ) -{ - int iParticleIndex = GetParticleSystemIndex( pszTracerEffectName ); - UTIL_Tracer( vecStart, vecEnd, iEntIndex, iAttachment, 0, bWhiz, "ParticleTracer", iParticleIndex ); -} - -//----------------------------------------------------------------------------- -// Purpose: Make a tracer effect using the old, non-particle system, tracer effects. -//----------------------------------------------------------------------------- -void UTIL_Tracer( const Vector &vecStart, const Vector &vecEnd, int iEntIndex, - int iAttachment, float flVelocity, bool bWhiz, const char *pCustomTracerName, int iParticleID ) -{ - CEffectData data; - data.m_vStart = vecStart; - data.m_vOrigin = vecEnd; -#ifdef CLIENT_DLL - data.m_hEntity = ClientEntityList().EntIndexToHandle( iEntIndex ); -#else - data.m_nEntIndex = iEntIndex; -#endif - data.m_flScale = flVelocity; - data.m_nHitBox = iParticleID; - - // Flags - if ( bWhiz ) - { - data.m_fFlags |= TRACER_FLAG_WHIZ; - } - - if ( iAttachment != TRACER_DONT_USE_ATTACHMENT ) - { - data.m_fFlags |= TRACER_FLAG_USEATTACHMENT; - data.m_nAttachmentIndex = iAttachment; - } - - // Fire it off - if ( pCustomTracerName ) - { - DispatchEffect( pCustomTracerName, data ); - } - else - { - DispatchEffect( "Tracer", data ); - } -} - - -void UTIL_BloodDrips( const Vector &origin, const Vector &direction, int color, int amount ) -{ - if ( !UTIL_ShouldShowBlood( color ) ) - return; - - if ( color == DONT_BLEED || amount == 0 ) - return; - - if ( g_Language.GetInt() == LANGUAGE_GERMAN && color == BLOOD_COLOR_RED ) - color = 0; - - if ( g_pGameRules->IsMultiplayer() ) - { - // scale up blood effect in multiplayer for better visibility - amount *= 5; - } - - if ( amount > 255 ) - amount = 255; - - if (color == BLOOD_COLOR_MECH) - { - g_pEffects->Sparks(origin); - if (random->RandomFloat(0, 2) >= 1) - { - UTIL_Smoke(origin, random->RandomInt(10, 15), 10); - } - } - else - { - // Normal blood impact - UTIL_BloodImpact( origin, direction, color, amount ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Returns low violence settings -//----------------------------------------------------------------------------- -static ConVar violence_hblood( "violence_hblood","1", 0, "Draw human blood" ); -static ConVar violence_hgibs( "violence_hgibs","1", 0, "Show human gib entities" ); -static ConVar violence_ablood( "violence_ablood","1", 0, "Draw alien blood" ); -static ConVar violence_agibs( "violence_agibs","1", 0, "Show alien gib entities" ); - -bool UTIL_IsLowViolence( void ) -{ - // These convars are no longer necessary -- the engine is the final arbiter of - // violence settings -- but they're here for legacy support and for testing low - // violence when the engine is in normal violence mode. - if ( !violence_hblood.GetBool() || !violence_ablood.GetBool() || !violence_hgibs.GetBool() || !violence_agibs.GetBool() ) - return true; - - return engine->IsLowViolence(); -} - -bool UTIL_ShouldShowBlood( int color ) -{ - if ( color != DONT_BLEED ) - { - if ( color == BLOOD_COLOR_RED ) - { - return violence_hblood.GetBool(); - } - else - { - return violence_ablood.GetBool(); - } - } - return false; -} - - -//------------------------------------------------------------------------------ -// Purpose : Use trace to pass a specific decal type to the entity being decaled -// Input : -// Output : -//------------------------------------------------------------------------------ -void UTIL_DecalTrace( trace_t *pTrace, char const *decalName ) -{ - if (pTrace->fraction == 1.0) - return; - - CBaseEntity *pEntity = pTrace->m_pEnt; - pEntity->DecalTrace( pTrace, decalName ); -} - - -void UTIL_BloodDecalTrace( trace_t *pTrace, int bloodColor ) -{ - if ( UTIL_ShouldShowBlood( bloodColor ) ) - { - if ( bloodColor == BLOOD_COLOR_RED ) - { - UTIL_DecalTrace( pTrace, "Blood" ); - } - else - { - UTIL_DecalTrace( pTrace, "YellowBlood" ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &pos - -// &dir - -// color - -// amount - -//----------------------------------------------------------------------------- -void UTIL_BloodImpact( const Vector &pos, const Vector &dir, int color, int amount ) -{ - CEffectData data; - - data.m_vOrigin = pos; - data.m_vNormal = dir; - data.m_flScale = (float)amount; - data.m_nColor = (unsigned char)color; - - DispatchEffect( "bloodimpact", data ); -} - -bool UTIL_IsSpaceEmpty( CBaseEntity *pMainEnt, const Vector &vMin, const Vector &vMax ) -{ - Vector vHalfDims = ( vMax - vMin ) * 0.5f; - Vector vCenter = vMin + vHalfDims; - - trace_t trace; - - UTIL_TraceHull( vCenter, vCenter, -vHalfDims, vHalfDims, MASK_SOLID, pMainEnt, COLLISION_GROUP_NONE, &trace ); - - bool bClear = ( trace.fraction == 1 && trace.allsolid != 1 && (trace.startsolid != 1) ); - return bClear; -} - -void UTIL_StringToFloatArray( float *pVector, int count, const char *pString ) -{ - char *pstr, *pfront, tempString[128]; - int j; - - Q_strncpy( tempString, pString, sizeof(tempString) ); - pstr = pfront = tempString; - - for ( j = 0; j < count; j++ ) // lifted from pr_edict.c - { - pVector[j] = atof( pfront ); - - // skip any leading whitespace - while ( *pstr && *pstr <= ' ' ) - pstr++; - - // skip to next whitespace - while ( *pstr && *pstr > ' ' ) - pstr++; - - if (!*pstr) - break; - - pstr++; - pfront = pstr; - } - for ( j++; j < count; j++ ) - { - pVector[j] = 0; - } -} - -void UTIL_StringToVector( float *pVector, const char *pString ) -{ - UTIL_StringToFloatArray( pVector, 3, pString ); -} - -void UTIL_StringToIntArray( int *pVector, int count, const char *pString ) -{ - char *pstr, *pfront, tempString[128]; - int j; - - Q_strncpy( tempString, pString, sizeof(tempString) ); - pstr = pfront = tempString; - - for ( j = 0; j < count; j++ ) // lifted from pr_edict.c - { - pVector[j] = atoi( pfront ); - - while ( *pstr && *pstr != ' ' ) - pstr++; - if (!*pstr) - break; - pstr++; - pfront = pstr; - } - - for ( j++; j < count; j++ ) - { - pVector[j] = 0; - } -} - -void UTIL_StringToColor32( color32 *color, const char *pString ) -{ - int tmp[4]; - UTIL_StringToIntArray( tmp, 4, pString ); - color->r = tmp[0]; - color->g = tmp[1]; - color->b = tmp[2]; - color->a = tmp[3]; -} - -#ifndef _XBOX -void UTIL_DecodeICE( unsigned char * buffer, int size, const unsigned char *key) -{ - if ( !key ) - return; - - IceKey ice( 0 ); // level 0 = 64bit key - ice.set( key ); // set key - - int blockSize = ice.blockSize(); - - unsigned char *temp = (unsigned char *)_alloca( PAD_NUMBER( size, blockSize ) ); - unsigned char *p1 = buffer; - unsigned char *p2 = temp; - - // encrypt data in 8 byte blocks - int bytesLeft = size; - while ( bytesLeft >= blockSize ) - { - ice.decrypt( p1, p2 ); - bytesLeft -= blockSize; - p1+=blockSize; - p2+=blockSize; - } - - // copy encrypted data back to original buffer - Q_memcpy( buffer, temp, size-bytesLeft ); -} -#endif - -// work-around since client header doesn't like inlined gpGlobals->curtime -float IntervalTimer::Now( void ) const -{ - return gpGlobals->curtime; -} - -// work-around since client header doesn't like inlined gpGlobals->curtime -float CountdownTimer::Now( void ) const -{ - return gpGlobals->curtime; -} - - -#ifdef CLIENT_DLL - CBasePlayer *UTIL_PlayerByIndex( int entindex ) - { - return ToBasePlayer( ClientEntityList().GetEnt( entindex ) ); - } -#endif - - -unsigned short UTIL_GetAchievementEventMask( void ) -{ - CRC32_t mapCRC; - CRC32_Init( &mapCRC ); - - char lowercase[ 256 ]; -#ifdef CLIENT_DLL - Q_FileBase( engine->GetLevelName(), lowercase, sizeof( lowercase ) ); -#else - Q_strncpy( lowercase, STRING( gpGlobals->mapname ), sizeof( lowercase ) ); -#endif - Q_strlower( lowercase ); - - CRC32_ProcessBuffer( &mapCRC, lowercase, Q_strlen( lowercase ) ); - CRC32_Final( &mapCRC ); - - return ( mapCRC & 0xFFFF ); -} - -const char* ReadAndAllocStringValue( KeyValues *pSub, const char *pName, const char *pFilename ) -{ - const char *pValue = pSub->GetString( pName, NULL ); - if ( !pValue ) - { - if ( pFilename ) - { - DevWarning( "Can't get key value '%s' from file '%s'.\n", pName, pFilename ); - } - return ""; - } - - int len = Q_strlen( pValue ) + 1; - char *pAlloced = new char[ len ]; - Assert( pAlloced ); - Q_strncpy( pAlloced, pValue, len ); - return pAlloced; -} - -int UTIL_StringFieldToInt( const char *szValue, const char **pValueStrings, int iNumStrings ) -{ - if ( !szValue || !szValue[0] ) - return -1; - - for ( int i = 0; i < iNumStrings; i++ ) - { - if ( FStrEq(szValue, pValueStrings[i]) ) - return i; - } - - Assert(0); - return -1; -} diff --git a/game/shared/util_shared.h b/game/shared/util_shared.h deleted file mode 100644 index 8a8781fdb..000000000 --- a/game/shared/util_shared.h +++ /dev/null @@ -1,540 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Shared util code between client and server. -// -//=============================================================================// - -#ifndef UTIL_SHARED_H -#define UTIL_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - -#include "mathlib/vector.h" -#include "cmodel.h" -#include "utlvector.h" -#include "networkvar.h" -#include "engine/IEngineTrace.h" -#include "engine/IStaticPropMgr.h" -#include "shared_classnames.h" - -#ifdef CLIENT_DLL -#include "cdll_client_int.h" -#endif - -#ifdef PORTAL -#include "portal_util_shared.h" -#endif - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class CGameTrace; -class CBasePlayer; -typedef CGameTrace trace_t; - -extern ConVar developer; // developer mode - - -//----------------------------------------------------------------------------- -// Language IDs. -//----------------------------------------------------------------------------- -#define LANGUAGE_ENGLISH 0 -#define LANGUAGE_GERMAN 1 -#define LANGUAGE_FRENCH 2 -#define LANGUAGE_BRITISH 3 - - -//----------------------------------------------------------------------------- -// Pitch + yaw -//----------------------------------------------------------------------------- -float UTIL_VecToYaw (const Vector &vec); -float UTIL_VecToPitch (const Vector &vec); -float UTIL_VecToYaw (const matrix3x4_t& matrix, const Vector &vec); -float UTIL_VecToPitch (const matrix3x4_t& matrix, const Vector &vec); -Vector UTIL_YawToVector ( float yaw ); - -//----------------------------------------------------------------------------- -// Shared random number generators for shared/predicted code: -// whenever generating random numbers in shared/predicted code, these functions -// have to be used. Each call should specify a unique "sharedname" string that -// seeds the random number generator. In loops make sure the "additionalSeed" -// is increased with the loop counter, otherwise it will always return the -// same random number -//----------------------------------------------------------------------------- -float SharedRandomFloat( const char *sharedname, float flMinVal, float flMaxVal, int additionalSeed = 0 ); -int SharedRandomInt( const char *sharedname, int iMinVal, int iMaxVal, int additionalSeed = 0 ); -Vector SharedRandomVector( const char *sharedname, float minVal, float maxVal, int additionalSeed = 0 ); -QAngle SharedRandomAngle( const char *sharedname, float minVal, float maxVal, int additionalSeed = 0 ); - -//----------------------------------------------------------------------------- -// Standard collision filters... -//----------------------------------------------------------------------------- -bool PassServerEntityFilter( const IHandleEntity *pTouch, const IHandleEntity *pPass ); -bool StandardFilterRules( IHandleEntity *pHandleEntity, int fContentsMask ); - - -//----------------------------------------------------------------------------- -// Converts an IHandleEntity to an CBaseEntity -//----------------------------------------------------------------------------- -inline const CBaseEntity *EntityFromEntityHandle( const IHandleEntity *pConstHandleEntity ) -{ - IHandleEntity *pHandleEntity = const_cast(pConstHandleEntity); - -#ifdef CLIENT_DLL - IClientUnknown *pUnk = (IClientUnknown*)pHandleEntity; - return pUnk->GetBaseEntity(); -#else - if ( staticpropmgr->IsStaticProp( pHandleEntity ) ) - return NULL; - - IServerUnknown *pUnk = (IServerUnknown*)pHandleEntity; - return pUnk->GetBaseEntity(); -#endif -} - -inline CBaseEntity *EntityFromEntityHandle( IHandleEntity *pHandleEntity ) -{ -#ifdef CLIENT_DLL - IClientUnknown *pUnk = (IClientUnknown*)pHandleEntity; - return pUnk->GetBaseEntity(); -#else - if ( staticpropmgr->IsStaticProp( pHandleEntity ) ) - return NULL; - - IServerUnknown *pUnk = (IServerUnknown*)pHandleEntity; - return pUnk->GetBaseEntity(); -#endif -} - - -//----------------------------------------------------------------------------- -// traceline methods -//----------------------------------------------------------------------------- -class CTraceFilterSimple : public CTraceFilter -{ -public: - // It does have a base, but we'll never network anything below here.. - DECLARE_CLASS_NOBASE( CTraceFilterSimple ); - - CTraceFilterSimple( const IHandleEntity *passentity, int collisionGroup ); - virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ); - virtual void SetPassEntity( const IHandleEntity *pPassEntity ) { m_pPassEnt = pPassEntity; } - virtual void SetCollisionGroup( int iCollisionGroup ) { m_collisionGroup = iCollisionGroup; } - - const IHandleEntity *GetPassEntity( void ){ return m_pPassEnt;} - -private: - const IHandleEntity *m_pPassEnt; - int m_collisionGroup; -}; - -class CTraceFilterSkipTwoEntities : public CTraceFilterSimple -{ -public: - // It does have a base, but we'll never network anything below here.. - DECLARE_CLASS( CTraceFilterSkipTwoEntities, CTraceFilterSimple ); - - CTraceFilterSkipTwoEntities( const IHandleEntity *passentity, const IHandleEntity *passentity2, int collisionGroup ); - virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ); - virtual void SetPassEntity2( const IHandleEntity *pPassEntity2 ) { m_pPassEnt2 = pPassEntity2; } - -private: - const IHandleEntity *m_pPassEnt2; -}; - -class CTraceFilterSimpleList : public CTraceFilterSimple -{ -public: - CTraceFilterSimpleList( int collisionGroup ); - virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ); - - void AddEntityToIgnore( IHandleEntity *pEntity ); -protected: - CUtlVector m_PassEntities; -}; - -class CTraceFilterOnlyNPCsAndPlayer : public CTraceFilterSimple -{ -public: - CTraceFilterOnlyNPCsAndPlayer( const IHandleEntity *passentity, int collisionGroup ) - : CTraceFilterSimple( passentity, collisionGroup ) - { - } - - virtual TraceType_t GetTraceType() const - { - return TRACE_ENTITIES_ONLY; - } - - virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ); -}; - -class CTraceFilterNoNPCsOrPlayer : public CTraceFilterSimple -{ -public: - CTraceFilterNoNPCsOrPlayer( const IHandleEntity *passentity, int collisionGroup ) - : CTraceFilterSimple( passentity, collisionGroup ) - { - } - - virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ); -}; - -//----------------------------------------------------------------------------- -// Purpose: Custom trace filter used for NPC LOS traces -//----------------------------------------------------------------------------- -class CTraceFilterLOS : public CTraceFilterSkipTwoEntities -{ -public: - CTraceFilterLOS( IHandleEntity *pHandleEntity, int collisionGroup, IHandleEntity *pHandleEntity2 = NULL ); - bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ); -}; - -class CTraceFilterSkipClassname : public CTraceFilterSimple -{ -public: - CTraceFilterSkipClassname( const IHandleEntity *passentity, const char *pchClassname, int collisionGroup ); - virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ); - -private: - - const char *m_pchClassname; -}; - -class CTraceFilterSkipTwoClassnames : public CTraceFilterSkipClassname -{ -public: - // It does have a base, but we'll never network anything below here.. - DECLARE_CLASS( CTraceFilterSkipTwoClassnames, CTraceFilterSkipClassname ); - - CTraceFilterSkipTwoClassnames( const IHandleEntity *passentity, const char *pchClassname, const char *pchClassname2, int collisionGroup ); - virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ); - -private: - const char *m_pchClassname2; -}; - -class CTraceFilterSimpleClassnameList : public CTraceFilterSimple -{ -public: - CTraceFilterSimpleClassnameList( const IHandleEntity *passentity, int collisionGroup ); - virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ); - - void AddClassnameToIgnore( const char *pchClassname ); -private: - CUtlVector m_PassClassnames; -}; - -class CTraceFilterChain : public CTraceFilter -{ -public: - CTraceFilterChain( ITraceFilter *pTraceFilter1, ITraceFilter *pTraceFilter2 ); - virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ); - -private: - ITraceFilter *m_pTraceFilter1; - ITraceFilter *m_pTraceFilter2; -}; - -// helper -void DebugDrawLine( const Vector& vecAbsStart, const Vector& vecAbsEnd, int r, int g, int b, bool test, float duration ); - -extern ConVar r_visualizetraces; - -inline void UTIL_TraceLine( const Vector& vecAbsStart, const Vector& vecAbsEnd, unsigned int mask, - const IHandleEntity *ignore, int collisionGroup, trace_t *ptr ) -{ - Ray_t ray; - ray.Init( vecAbsStart, vecAbsEnd ); - CTraceFilterSimple traceFilter( ignore, collisionGroup ); - - enginetrace->TraceRay( ray, mask, &traceFilter, ptr ); - - if( r_visualizetraces.GetBool() ) - { - DebugDrawLine( ptr->startpos, ptr->endpos, 255, 0, 0, true, -1.0f ); - } -} - -inline void UTIL_TraceLine( const Vector& vecAbsStart, const Vector& vecAbsEnd, unsigned int mask, - ITraceFilter *pFilter, trace_t *ptr ) -{ - Ray_t ray; - ray.Init( vecAbsStart, vecAbsEnd ); - - enginetrace->TraceRay( ray, mask, pFilter, ptr ); - - if( r_visualizetraces.GetBool() ) - { - DebugDrawLine( ptr->startpos, ptr->endpos, 255, 0, 0, true, -1.0f ); - } -} - -inline void UTIL_TraceHull( const Vector &vecAbsStart, const Vector &vecAbsEnd, const Vector &hullMin, - const Vector &hullMax, unsigned int mask, const IHandleEntity *ignore, - int collisionGroup, trace_t *ptr ) -{ - Ray_t ray; - ray.Init( vecAbsStart, vecAbsEnd, hullMin, hullMax ); - CTraceFilterSimple traceFilter( ignore, collisionGroup ); - - enginetrace->TraceRay( ray, mask, &traceFilter, ptr ); - - if( r_visualizetraces.GetBool() ) - { - DebugDrawLine( ptr->startpos, ptr->endpos, 255, 255, 0, true, -1.0f ); - } -} - -inline void UTIL_TraceHull( const Vector &vecAbsStart, const Vector &vecAbsEnd, const Vector &hullMin, - const Vector &hullMax, unsigned int mask, ITraceFilter *pFilter, trace_t *ptr ) -{ - Ray_t ray; - ray.Init( vecAbsStart, vecAbsEnd, hullMin, hullMax ); - - enginetrace->TraceRay( ray, mask, pFilter, ptr ); - - if( r_visualizetraces.GetBool() ) - { - DebugDrawLine( ptr->startpos, ptr->endpos, 255, 255, 0, true, -1.0f ); - } -} - -inline void UTIL_TraceRay( const Ray_t &ray, unsigned int mask, - const IHandleEntity *ignore, int collisionGroup, trace_t *ptr ) -{ - CTraceFilterSimple traceFilter( ignore, collisionGroup ); - - enginetrace->TraceRay( ray, mask, &traceFilter, ptr ); - - if( r_visualizetraces.GetBool() ) - { - DebugDrawLine( ptr->startpos, ptr->endpos, 255, 0, 0, true, -1.0f ); - } -} - -// Sweeps a particular entity through the world -void UTIL_TraceEntity( CBaseEntity *pEntity, const Vector &vecAbsStart, const Vector &vecAbsEnd, unsigned int mask, trace_t *ptr ); -void UTIL_TraceEntity( CBaseEntity *pEntity, const Vector &vecAbsStart, const Vector &vecAbsEnd, - unsigned int mask, ITraceFilter *pFilter, trace_t *ptr ); -void UTIL_TraceEntity( CBaseEntity *pEntity, const Vector &vecAbsStart, const Vector &vecAbsEnd, - unsigned int mask, const IHandleEntity *ignore, int collisionGroup, trace_t *ptr ); - -bool UTIL_EntityHasMatchingRootParent( CBaseEntity *pRootParent, CBaseEntity *pEntity ); - -inline int UTIL_PointContents( const Vector &vec ) -{ - return enginetrace->GetPointContents( vec ); -} - -// Sweeps against a particular model, using collision rules -void UTIL_TraceModel( const Vector &vecStart, const Vector &vecEnd, const Vector &hullMin, - const Vector &hullMax, CBaseEntity *pentModel, int collisionGroup, trace_t *ptr ); - -void UTIL_ClipTraceToPlayers( const Vector& vecAbsStart, const Vector& vecAbsEnd, unsigned int mask, ITraceFilter *filter, trace_t *tr ); - -// Particle effect tracer -void UTIL_ParticleTracer( const char *pszTracerEffectName, const Vector &vecStart, const Vector &vecEnd, int iEntIndex = 0, int iAttachment = 0, bool bWhiz = false ); - -// Old style, non-particle system, tracers -void UTIL_Tracer( const Vector &vecStart, const Vector &vecEnd, int iEntIndex = 0, int iAttachment = TRACER_DONT_USE_ATTACHMENT, float flVelocity = 0, bool bWhiz = false, const char *pCustomTracerName = NULL, int iParticleID = 0 ); - -bool UTIL_IsLowViolence( void ); -bool UTIL_ShouldShowBlood( int bloodColor ); -void UTIL_BloodDrips( const Vector &origin, const Vector &direction, int color, int amount ); - -void UTIL_BloodImpact( const Vector &pos, const Vector &dir, int color, int amount ); -void UTIL_BloodDecalTrace( trace_t *pTrace, int bloodColor ); -void UTIL_DecalTrace( trace_t *pTrace, char const *decalName ); -bool UTIL_IsSpaceEmpty( CBaseEntity *pMainEnt, const Vector &vMin, const Vector &vMax ); - -void UTIL_StringToVector( float *pVector, const char *pString ); -void UTIL_StringToIntArray( int *pVector, int count, const char *pString ); -void UTIL_StringToFloatArray( float *pVector, int count, const char *pString ); -void UTIL_StringToColor32( color32 *color, const char *pString ); - -CBasePlayer *UTIL_PlayerByIndex( int entindex ); - -// decodes a buffer using a 64bit ICE key (inplace) -void UTIL_DecodeICE( unsigned char * buffer, int size, const unsigned char *key); - -unsigned short UTIL_GetAchievementEventMask( void ); - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Given a position and a ray, return the shortest distance between the two. - * If 'pos' is beyond either end of the ray, the returned distance is negated. - */ -inline float DistanceToRay( const Vector &pos, const Vector &rayStart, const Vector &rayEnd, float *along = NULL, Vector *pointOnRay = NULL ) -{ - Vector to = pos - rayStart; - Vector dir = rayEnd - rayStart; - float length = dir.NormalizeInPlace(); - - float rangeAlong = DotProduct( dir, to ); - if (along) - { - *along = rangeAlong; - } - - float range; - - if (rangeAlong < 0.0f) - { - // off start point - range = -(pos - rayStart).Length(); - - if (pointOnRay) - { - *pointOnRay = rayStart; - } - } - else if (rangeAlong > length) - { - // off end point - range = -(pos - rayEnd).Length(); - - if (pointOnRay) - { - *pointOnRay = rayEnd; - } - } - else // within ray bounds - { - Vector onRay = rayStart + rangeAlong * dir; - range = (pos - onRay).Length(); - - if (pointOnRay) - { - *pointOnRay = onRay; - } - } - - return range; -} - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Simple class for tracking intervals of game time. - * Upon creation, the timer is invalidated. To measure time intervals, start the timer via Start(). - */ -class IntervalTimer -{ -public: - IntervalTimer( void ) - { - m_timestamp = -1.0f; - } - - void Reset( void ) - { - m_timestamp = Now(); - } - - void Start( void ) - { - m_timestamp = Now(); - } - - void Invalidate( void ) - { - m_timestamp = -1.0f; - } - - bool HasStarted( void ) const - { - return (m_timestamp > 0.0f); - } - - /// if not started, elapsed time is very large - float GetElapsedTime( void ) const - { - return (HasStarted()) ? (Now() - m_timestamp) : 99999.9f; - } - - bool IsLessThen( float duration ) const - { - return (Now() - m_timestamp < duration) ? true : false; - } - - bool IsGreaterThen( float duration ) const - { - return (Now() - m_timestamp > duration) ? true : false; - } - -private: - float m_timestamp; - float Now( void ) const; // work-around since client header doesn't like inlined gpGlobals->curtime -}; - - -//-------------------------------------------------------------------------------------------------------------- -/** - * Simple class for counting down a short interval of time. - * Upon creation, the timer is invalidated. Invalidated countdown timers are considered to have elapsed. - */ -class CountdownTimer -{ -public: - CountdownTimer( void ) - { - m_timestamp = -1.0f; - m_duration = 0.0f; - } - - void Reset( void ) - { - m_timestamp = Now() + m_duration; - } - - void Start( float duration ) - { - m_timestamp = Now() + duration; - m_duration = duration; - } - - void Invalidate( void ) - { - m_timestamp = -1.0f; - } - - bool HasStarted( void ) const - { - return (m_timestamp > 0.0f); - } - - bool IsElapsed( void ) const - { - return (Now() > m_timestamp); - } - - float GetElapsedTime( void ) const - { - return Now() - m_timestamp + m_duration; - } - - float GetRemainingTime( void ) const - { - return (m_timestamp - Now()); - } - - /// return original countdown time - float GetCountdownDuration( void ) const - { - return (m_timestamp > 0.0f) ? m_duration : 0.0f; - } - -private: - float m_duration; - float m_timestamp; - float Now( void ) const; // work-around since client header doesn't like inlined gpGlobals->curtime -}; - -const char* ReadAndAllocStringValue( KeyValues *pSub, const char *pName, const char *pFilename = NULL ); - -int UTIL_StringFieldToInt( const char *szValue, const char **pValueStrings, int iNumStrings ); - -#endif // UTIL_SHARED_H diff --git a/game/shared/vehicle_choreo_generic_shared.h b/game/shared/vehicle_choreo_generic_shared.h deleted file mode 100644 index 18657ea7e..000000000 --- a/game/shared/vehicle_choreo_generic_shared.h +++ /dev/null @@ -1,45 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef VEHICLE_CHOREO_GENERIC_SHARED_H -#define VEHICLE_CHOREO_GENERIC_SHARED_H - -#if defined( _WIN32 ) -#pragma once -#endif - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -struct vehicleview_t -{ - DECLARE_CLASS_NOBASE( vehicleview_t ); - DECLARE_EMBEDDED_NETWORKVAR(); - -#ifndef CLIENT_DLL - DECLARE_DATADESC(); -#endif - - CNetworkVar( bool, bClampEyeAngles ); // Perform eye Z clamping - - CNetworkVar( float, flPitchCurveZero ); // Pitch values below this are clamped to zero. - CNetworkVar( float, flPitchCurveLinear ); // Pitch values above this are mapped directly. - // Spline in between. - CNetworkVar( float, flRollCurveZero ); // Pitch values below this are clamped to zero. - CNetworkVar( float, flRollCurveLinear ); // Roll values above this are mapped directly. - // Spline in between. - CNetworkVar( float, flFOV ); // FOV when in the vehicle. - - CNetworkVar( float, flYawMin ); - CNetworkVar( float, flYawMax ); - - CNetworkVar( float, flPitchMin ); - CNetworkVar( float, flPitchMax ); -}; - - -#endif // VEHICLE_CHOREO_GENERIC_SHARED_H diff --git a/game/shared/vehicle_viewblend_shared.cpp b/game/shared/vehicle_viewblend_shared.cpp deleted file mode 100644 index b8f8d5664..000000000 --- a/game/shared/vehicle_viewblend_shared.cpp +++ /dev/null @@ -1,416 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: Used to calculate the player's view in the vehicle -// -//============================================================================= - -#include "cbase.h" -#include "vehicle_viewblend_shared.h" - -#ifdef CLIENT_DLL - -// Client includes -#include "c_prop_vehicle.h" -#include "view.h" - -#else -// Server include -#include "vehicle_base.h" - -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#ifdef CLIENT_DLL - -extern ConVar default_fov; - -#define CPropVehicleDriveable C_PropVehicleDriveable - -#endif // CLIENT_DLL - -extern ConVar r_VehicleViewDampen; - -BEGIN_SIMPLE_DATADESC( ViewSmoothingData_t ) - DEFINE_FIELD( vecAnglesSaved, FIELD_VECTOR ), - DEFINE_FIELD( vecOriginSaved, FIELD_POSITION_VECTOR ), - DEFINE_FIELD( vecAngleDiffSaved, FIELD_VECTOR ), - DEFINE_FIELD( vecAngleDiffMin, FIELD_VECTOR ), - DEFINE_FIELD( bRunningEnterExit, FIELD_BOOLEAN ), - DEFINE_FIELD( bWasRunningAnim, FIELD_BOOLEAN ), - DEFINE_FIELD( flEnterExitStartTime, FIELD_FLOAT ), - DEFINE_FIELD( flEnterExitDuration, FIELD_FLOAT ), - DEFINE_FIELD( flFOV, FIELD_FLOAT ), - - // These are filled out in the vehicle's constructor: - //CBaseAnimating *pVehicle; - //bool bClampEyeAngles; - //float flPitchCurveZero; - //float flPitchCurveLinear; - //float flRollCurveZero; - //float flRollCurveLinear; - //ViewLockData_t pitchLockData; - //ViewLockData_t rollLockData; - //bool bDampenEyePosition; -END_DATADESC() - -// remaps an angular variable to a 3 band function: -// 0 <= t < start : f(t) = 0 -// start <= t <= end : f(t) = end * spline(( t-start) / (end-start) ) // s curve between clamped and linear -// end < t : f(t) = t -float RemapAngleRange( float startInterval, float endInterval, float value, RemapAngleRange_CurvePart_t *peCurvePart ) -{ - // Fixup the roll - value = AngleNormalize( value ); - float absAngle = fabs(value); - - // beneath cutoff? - if ( absAngle < startInterval ) - { - if ( peCurvePart ) - { - *peCurvePart = RemapAngleRange_CurvePart_Zero; - } - value = 0; - } - // in spline range? - else if ( absAngle <= endInterval ) - { - float newAngle = SimpleSpline( (absAngle - startInterval) / (endInterval-startInterval) ) * endInterval; - - // grab the sign from the initial value - if ( value < 0 ) - { - newAngle *= -1; - } - - if ( peCurvePart ) - { - *peCurvePart = RemapAngleRange_CurvePart_Spline; - } - value = newAngle; - } - // else leave it alone, in linear range - else if ( peCurvePart ) - { - *peCurvePart = RemapAngleRange_CurvePart_Linear; - } - - return value; -} - -//----------------------------------------------------------------------------- -// Purpose: For a given degree of freedom, blends between the raw and clamped -// view depending on this vehicle's preferences. When vehicles wreck -// catastrophically, it's often better to lock the view for a little -// while until things settle down than to keep trying to clamp/flatten -// the view artificially because we can never really catch up with -// the chaotic flipping. -//----------------------------------------------------------------------------- -float ApplyViewLocking( float flAngleRaw, float flAngleClamped, ViewLockData_t &lockData, RemapAngleRange_CurvePart_t eCurvePart ) -{ - // If we're set up to never lock this degree of freedom, return the clamped value. - if ( lockData.flLockInterval == 0 ) - return flAngleClamped; - - float flAngleOut = flAngleClamped; - - // Lock the view if we're in the linear part of the curve, and keep it locked - // until some duration after we return to the flat (zero) part of the curve. - if ( ( eCurvePart == RemapAngleRange_CurvePart_Linear ) || - ( lockData.bLocked && ( eCurvePart == RemapAngleRange_CurvePart_Spline ) ) ) - { - //Msg( "LOCKED\n" ); - lockData.bLocked = true; - lockData.flUnlockTime = gpGlobals->curtime + lockData.flLockInterval; - flAngleOut = flAngleRaw; - } - else - { - if ( ( lockData.bLocked ) && ( gpGlobals->curtime > lockData.flUnlockTime ) ) - { - lockData.bLocked = false; - if ( lockData.flUnlockBlendInterval > 0 ) - { - lockData.flUnlockTime = gpGlobals->curtime; - } - else - { - lockData.flUnlockTime = 0; - } - } - - if ( !lockData.bLocked ) - { - if ( lockData.flUnlockTime != 0 ) - { - // Blend out from the locked raw view (no remapping) to a remapped view. - float flBlend = RemapValClamped( gpGlobals->curtime - lockData.flUnlockTime, 0, lockData.flUnlockBlendInterval, 0, 1 ); - //Msg( "BLEND %f\n", flBlend ); - - flAngleOut = Lerp( flBlend, flAngleRaw, flAngleClamped ); - if ( flBlend >= 1.0f ) - { - lockData.flUnlockTime = 0; - } - } - else - { - // Not blending out from a locked view to a remapped view. - //Msg( "CLAMPED\n" ); - flAngleOut = flAngleClamped; - } - } - else - { - //Msg( "STILL LOCKED\n" ); - flAngleOut = flAngleRaw; - } - } - - return flAngleOut; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pData - -// vehicleEyeAngles - -//----------------------------------------------------------------------------- -void RemapViewAngles( ViewSmoothingData_t *pData, QAngle &vehicleEyeAngles ) -{ - QAngle vecEyeAnglesRemapped; - - // Clamp pitch. - RemapAngleRange_CurvePart_t ePitchCurvePart; - vecEyeAnglesRemapped.x = RemapAngleRange( pData->flPitchCurveZero, pData->flPitchCurveLinear, vehicleEyeAngles.x, &ePitchCurvePart ); - - vehicleEyeAngles.z = vecEyeAnglesRemapped.z = AngleNormalize( vehicleEyeAngles.z ); - - // Blend out the roll dampening as our pitch approaches 90 degrees, to avoid gimbal lock problems. - float flBlendRoll = 1.0; - if ( fabs( vehicleEyeAngles.x ) > 60 ) - { - flBlendRoll = RemapValClamped( fabs( vecEyeAnglesRemapped.x ), 60, 80, 1, 0); - } - - RemapAngleRange_CurvePart_t eRollCurvePart; - float flRollDamped = RemapAngleRange( pData->flRollCurveZero, pData->flRollCurveLinear, vecEyeAnglesRemapped.z, &eRollCurvePart ); - vecEyeAnglesRemapped.z = Lerp( flBlendRoll, vecEyeAnglesRemapped.z, flRollDamped ); - - //Msg("PITCH "); - vehicleEyeAngles.x = ApplyViewLocking( vehicleEyeAngles.x, vecEyeAnglesRemapped.x, pData->pitchLockData, ePitchCurvePart ); - - //Msg("ROLL "); - vehicleEyeAngles.z = ApplyViewLocking( vehicleEyeAngles.z, vecEyeAnglesRemapped.z, pData->rollLockData, eRollCurvePart ); -} - -//----------------------------------------------------------------------------- -// Purpose: Vehicle dampening shared between server and client -//----------------------------------------------------------------------------- -void SharedVehicleViewSmoothing(CBasePlayer *pPlayer, - Vector *pAbsOrigin, QAngle *pAbsAngles, - bool bEnterAnimOn, bool bExitAnimOn, - const Vector &vecEyeExitEndpoint, - ViewSmoothingData_t *pData, - float *pFOV ) -{ - int eyeAttachmentIndex = pData->pVehicle->LookupAttachment( "vehicle_driver_eyes" ); - matrix3x4_t vehicleEyePosToWorld; - Vector vehicleEyeOrigin; - QAngle vehicleEyeAngles; - pData->pVehicle->GetAttachment( eyeAttachmentIndex, vehicleEyeOrigin, vehicleEyeAngles ); - AngleMatrix( vehicleEyeAngles, vehicleEyePosToWorld ); - - // Dampen the eye positional change as we drive around. - *pAbsAngles = pPlayer->EyeAngles(); - if ( r_VehicleViewDampen.GetInt() && pData->bDampenEyePosition ) - { - CPropVehicleDriveable *pDriveable = assert_cast(pData->pVehicle); - pDriveable->DampenEyePosition( vehicleEyeOrigin, vehicleEyeAngles ); - } - - // Started running an entry or exit anim? - bool bRunningAnim = ( bEnterAnimOn || bExitAnimOn ); - if ( bRunningAnim && !pData->bWasRunningAnim ) - { - pData->bRunningEnterExit = true; - pData->flEnterExitStartTime = gpGlobals->curtime; - pData->flEnterExitDuration = pData->pVehicle->SequenceDuration( pData->pVehicle->GetSequence() ); - -#ifdef CLIENT_DLL - pData->vecOriginSaved = PrevMainViewOrigin(); - pData->vecAnglesSaved = PrevMainViewAngles(); -#endif - - // Save our initial angular error, which we will blend out over the length of the animation. - pData->vecAngleDiffSaved.x = AngleDiff( vehicleEyeAngles.x, pData->vecAnglesSaved.x ); - pData->vecAngleDiffSaved.y = AngleDiff( vehicleEyeAngles.y, pData->vecAnglesSaved.y ); - pData->vecAngleDiffSaved.z = AngleDiff( vehicleEyeAngles.z, pData->vecAnglesSaved.z ); - - pData->vecAngleDiffMin = pData->vecAngleDiffSaved; - } - - pData->bWasRunningAnim = bRunningAnim; - - float frac = 0; - float flFracFOV = 0; - - // If we're in an enter/exit animation, blend the player's eye angles to the attachment's - if ( bRunningAnim || pData->bRunningEnterExit ) - { - *pAbsAngles = vehicleEyeAngles; - - // Forward integrate to determine the elapsed time in this entry/exit anim. - frac = ( gpGlobals->curtime - pData->flEnterExitStartTime ) / pData->flEnterExitDuration; - frac = clamp( frac, 0.0f, 1.0f ); - - flFracFOV = ( gpGlobals->curtime - pData->flEnterExitStartTime ) / ( pData->flEnterExitDuration * 0.85f ); - flFracFOV = clamp( flFracFOV, 0.0f, 1.0f ); - - //Msg("Frac: %f\n", frac ); - - if ( frac < 1.0 ) - { - // Blend to the desired vehicle eye origin - //Vector vecToView = (vehicleEyeOrigin - PrevMainViewOrigin()); - //vehicleEyeOrigin = PrevMainViewOrigin() + (vecToView * SimpleSpline(frac)); - //debugoverlay->AddBoxOverlay( vehicleEyeOrigin, -Vector(1,1,1), Vector(1,1,1), vec3_angle, 0,255,255, 64, 10 ); - } - else - { - pData->bRunningEnterExit = false; - - // Enter animation has finished, align view with the eye attachment point - // so they can start mouselooking around. - if ( !bExitAnimOn ) - { - Vector localEyeOrigin; - QAngle localEyeAngles; - - pData->pVehicle->GetAttachmentLocal( eyeAttachmentIndex, localEyeOrigin, localEyeAngles ); -#ifdef CLIENT_DLL - engine->SetViewAngles( localEyeAngles ); -#endif - } - } - } - - // Compute the relative rotation between the unperturbed eye attachment + the eye angles - matrix3x4_t cameraToWorld; - AngleMatrix( *pAbsAngles, cameraToWorld ); - - matrix3x4_t worldToEyePos; - MatrixInvert( vehicleEyePosToWorld, worldToEyePos ); - - matrix3x4_t vehicleCameraToEyePos; - ConcatTransforms( worldToEyePos, cameraToWorld, vehicleCameraToEyePos ); - - // Damp out some of the vehicle motion (neck/head would do this) - if ( pData->bClampEyeAngles ) - { - RemapViewAngles( pData, vehicleEyeAngles ); - } - - AngleMatrix( vehicleEyeAngles, vehicleEyeOrigin, vehicleEyePosToWorld ); - - // Now treat the relative eye angles as being relative to this new, perturbed view position... - matrix3x4_t newCameraToWorld; - ConcatTransforms( vehicleEyePosToWorld, vehicleCameraToEyePos, newCameraToWorld ); - - // output new view abs angles - MatrixAngles( newCameraToWorld, *pAbsAngles ); - - // UNDONE: *pOrigin would already be correct in single player if the HandleView() on the server ran after vphysics - MatrixGetColumn( newCameraToWorld, 3, *pAbsOrigin ); - - float flDefaultFOV; -#ifdef CLIENT_DLL - flDefaultFOV = default_fov.GetFloat(); -#else - flDefaultFOV = pPlayer->GetDefaultFOV(); -#endif - - // If we're playing an entry or exit animation... - if ( bRunningAnim || pData->bRunningEnterExit ) - { - float flSplineFrac = clamp( SimpleSpline( frac ), 0, 1 ); - - // Blend out the error between the player's initial eye angles and the animation's initial - // eye angles over the duration of the animation. - QAngle vecAngleDiffBlend = ( ( 1 - flSplineFrac ) * pData->vecAngleDiffSaved ); - - // If our current error is less than the error amount that we're blending - // out, use that. This lets the angles converge as quickly as possible. - QAngle vecAngleDiffCur; - vecAngleDiffCur.x = AngleDiff( vehicleEyeAngles.x, pData->vecAnglesSaved.x ); - vecAngleDiffCur.y = AngleDiff( vehicleEyeAngles.y, pData->vecAnglesSaved.y ); - vecAngleDiffCur.z = AngleDiff( vehicleEyeAngles.z, pData->vecAnglesSaved.z ); - - // In either case, never increase the error, so track the minimum error and clamp to that. - for (int i = 0; i < 3; i++) - { - if ( fabs(vecAngleDiffCur[i] ) < fabs( pData->vecAngleDiffMin[i] ) ) - { - pData->vecAngleDiffMin[i] = vecAngleDiffCur[i]; - } - - if ( fabs(vecAngleDiffBlend[i] ) < fabs( pData->vecAngleDiffMin[i] ) ) - { - pData->vecAngleDiffMin[i] = vecAngleDiffBlend[i]; - } - } - - // Add the error to the animation's eye angles. - *pAbsAngles -= pData->vecAngleDiffMin; - - // Use this as the basis for the next error calculation. - pData->vecAnglesSaved = *pAbsAngles; - - //if ( gpGlobals->frametime ) - //{ - // Msg("Angle : %.2f %.2f %.2f\n", target.x, target.y, target.z ); - //} - //Msg("Prev: %.2f %.2f %.2f\n", pData->vecAnglesSaved.x, pData->vecAnglesSaved.y, pData->vecAnglesSaved.z ); - - Vector vecAbsOrigin = *pAbsOrigin; - - // If we're exiting, our desired position is the server-sent exit position - if ( bExitAnimOn ) - { - //debugoverlay->AddBoxOverlay( vecEyeExitEndpoint, -Vector(1,1,1), Vector(1,1,1), vec3_angle, 255,255,255, 64, 10 ); - - // Blend to the exit position - *pAbsOrigin = Lerp( flSplineFrac, vecAbsOrigin, vecEyeExitEndpoint ); - - if ( pFOV != NULL ) - { - if ( pData->flFOV > flDefaultFOV ) - { - *pFOV = Lerp( flFracFOV, pData->flFOV, flDefaultFOV ); - } - } - } - else - { - // Blend from our starting position to the desired origin - *pAbsOrigin = Lerp( flSplineFrac, pData->vecOriginSaved, vecAbsOrigin ); - - if ( pFOV != NULL ) - { - if ( pData->flFOV > flDefaultFOV ) - { - *pFOV = Lerp( flFracFOV, flDefaultFOV, pData->flFOV ); - } - } - } - } - else if ( pFOV != NULL ) - { - if ( pData->flFOV > flDefaultFOV ) - { - // Not running an entry/exit anim. Just use the vehicle's FOV. - *pFOV = pData->flFOV; - } - } -} diff --git a/game/shared/vehicle_viewblend_shared.h b/game/shared/vehicle_viewblend_shared.h deleted file mode 100644 index 7f7cc8349..000000000 --- a/game/shared/vehicle_viewblend_shared.h +++ /dev/null @@ -1,79 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef VEHICLE_VIEWBLEND_SHARED_H -#define VEHICLE_VIEWBLEND_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - -// Definition for how to calculate a point on the remap curve -enum RemapAngleRange_CurvePart_t -{ - RemapAngleRange_CurvePart_Zero = 0, - RemapAngleRange_CurvePart_Spline, - RemapAngleRange_CurvePart_Linear, -}; - -// If we enter the linear part of the remap for curve for any degree of freedom, we can lock -// that DOF (stop remapping). This is useful for making flips feel less spastic as we oscillate -// randomly between different parts of the remapping curve. -struct ViewLockData_t -{ - float flLockInterval; // The duration to lock the view when we lock it for this degree of freedom. - // 0 = never lock this degree of freedom. - - bool bLocked; // True if this DOF was locked because of the above condition. - - float flUnlockTime; // If this DOF is locked, the time when we will unlock it. - - float flUnlockBlendInterval; // If this DOF is locked, how long to spend blending out of the locked view when we unlock. -}; - -// This is separate from the base vehicle implementation so that any class -// that derives from IClientVehicle can use it. To use it, contain one of the -// following structs, fill out the first section, and then call VehicleViewSmoothing() -// inside your GetVehicleViewPosition() function. -struct ViewSmoothingData_t -{ - DECLARE_SIMPLE_DATADESC(); - - // Fill these out in your vehicle - CBaseAnimating *pVehicle; - bool bClampEyeAngles; // Perform eye Z clamping - float flPitchCurveZero; // Pitch values below this are clamped to zero. - float flPitchCurveLinear; // Pitch values above this are mapped directly. - // Spline in between. - float flRollCurveZero; // Pitch values below this are clamped to zero. - float flRollCurveLinear; // Roll values above this are mapped directly. - // Spline in between. - float flFOV; // FOV when in the vehicle. - - ViewLockData_t pitchLockData; - ViewLockData_t rollLockData; - - bool bDampenEyePosition; // Only set to true for C_PropVehicleDriveable derived vehicles - - // Don't change these, they're used by VehicleViewSmoothing() - bool bRunningEnterExit; - bool bWasRunningAnim; - float flEnterExitStartTime; // Time we began our animation at - float flEnterExitDuration; // Duration of the animation - QAngle vecAnglesSaved; - Vector vecOriginSaved; - QAngle vecAngleDiffSaved; // The original angular error between the entry/exit anim and player's view when we started playing the anim. - QAngle vecAngleDiffMin; // Tracks the minimum angular error achieved so we can converge on the anim's angles. -}; - -// TEMP: Shared vehicle view smoothing -void SharedVehicleViewSmoothing(CBasePlayer *pPlayer, - Vector *pAbsOrigin, QAngle *pAbsAngles, - bool bEnterAnimOn, bool bExitAnimOn, - const Vector &vecEyeExitEndpoint, - ViewSmoothingData_t *pData, - float *pFOV ); - -#endif // VEHICLE_VIEWBLEND_SHARED_H diff --git a/game/shared/vgui_defaultinputsignal.h b/game/shared/vgui_defaultinputsignal.h deleted file mode 100644 index 8e20f6dfc..000000000 --- a/game/shared/vgui_defaultinputsignal.h +++ /dev/null @@ -1,39 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef VGUI_DEFAULTINPUTSIGNAL_H -#define VGUI_DEFAULTINPUTSIGNAL_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "vgui_inputsignal.h" - - -namespace vgui -{ - // This class derives from vgui::InputSignal and implements empty defaults for all of its functions. - class CDefaultInputSignal : public vgui::InputSignal - { - public: - virtual void cursorMoved(int x,int y,Panel* panel) {} - virtual void cursorEntered(Panel* panel) {} - virtual void cursorExited(Panel* panel) {} - virtual void mousePressed(MouseCode code,Panel* panel) {} - virtual void mouseDoublePressed(MouseCode code,Panel* panel) {} - virtual void mouseReleased(MouseCode code,Panel* panel) {} - virtual void mouseWheeled(int delta,Panel* panel) {} - virtual void keyPressed(KeyCode code,Panel* panel) {} - virtual void keyTyped(KeyCode code,Panel* panel) {} - virtual void keyReleased(KeyCode code,Panel* panel) {} - virtual void keyFocusTicked(Panel* panel) {} - }; -} - - -#endif // VGUI_DEFAULTINPUTSIGNAL_H diff --git a/game/shared/viewport_panel_names.h b/game/shared/viewport_panel_names.h deleted file mode 100644 index b7c758a66..000000000 --- a/game/shared/viewport_panel_names.h +++ /dev/null @@ -1,37 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef VIEWPORT_PANEL_NAMES_H -#define VIEWPORT_PANEL_NAMES_H -#ifdef _WIN32 -#pragma once -#endif - - -// default panel name definitions -#define PANEL_ALL "all" // all current panels -#define PANEL_ACTIVE "active" // current active panel - -#define PANEL_SCOREBOARD "scores" -#define PANEL_OVERVIEW "overview" -#define PANEL_CLASS "class" -#define PANEL_TEAM "team" -#define PANEL_SPECGUI "specgui" // passive spectator elements (top/bottom bars) -#define PANEL_SPECMENU "specmenu" // active spectator elements (options menus etc) -#define PANEL_INFO "info" -#define PANEL_BUY "buy" -#define PANEL_BUY_CT "buy_ct" -#define PANEL_BUY_TER "buy_ter" -#define PANEL_BUY_EQUIP_CT "buyequip_ct" -#define PANEL_BUY_EQUIP_TER "buyequip_ter" -#define PANEL_NAV_PROGRESS "nav_progress" -#define PANEL_BUYPRESET_MAIN "buypreset_main" -#define PANEL_BUYPRESET_EDIT "buypreset_edit" -#define PANEL_INTRO "intro" - -#define PANEL_COMMENTARY_MODELVIEWER "commentary_modelviewer" - -#endif // VIEWPORT_PANEL_NAMES_H diff --git a/game/shared/voice_banmgr.cpp b/game/shared/voice_banmgr.cpp deleted file mode 100644 index 4c3908648..000000000 --- a/game/shared/voice_banmgr.cpp +++ /dev/null @@ -1,185 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include -#include -#include "voice_banmgr.h" -#include "FileSystem.h" -#include "cdll_client_int.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define BANMGR_FILEVERSION 1 -const char *g_pBanMgrFilename = "voice_ban.dt"; - - - -// Hash a player ID to a byte. -unsigned char HashPlayerID(char const playerID[SIGNED_GUID_LEN]) -{ - unsigned char curHash = 0; - - for(int i=0; i < SIGNED_GUID_LEN; i++) - curHash = (unsigned char)(curHash + playerID[i]); - - return curHash; -} - - - -CVoiceBanMgr::CVoiceBanMgr() -{ - Clear(); -} - - -CVoiceBanMgr::~CVoiceBanMgr() -{ - Term(); -} - - -bool CVoiceBanMgr::Init(const char *pGameDir) -{ - Term(); - - // Load in the squelch file. - FileHandle_t fh = filesystem->Open(g_pBanMgrFilename, "rb"); - if (fh) - { - int version; - filesystem->Read(&version, sizeof(version), fh); - if(version == BANMGR_FILEVERSION) - { - filesystem->Seek(fh, 0, FILESYSTEM_SEEK_TAIL); - int nIDs = (filesystem->Tell(fh) - sizeof(version)) / SIGNED_GUID_LEN; - filesystem->Seek(fh, sizeof(version), FILESYSTEM_SEEK_CURRENT); - - for(int i=0; i < nIDs; i++) - { - char playerID[SIGNED_GUID_LEN]; - filesystem->Read(playerID, SIGNED_GUID_LEN, fh); - AddBannedPlayer(playerID); - } - } - - filesystem->Close(fh); - } - - return true; -} - - -void CVoiceBanMgr::Term() -{ - // Free all the player structures. - for(int i=0; i < 256; i++) - { - BannedPlayer *pListHead = &m_PlayerHash[i]; - BannedPlayer *pNext; - for(BannedPlayer *pCur=pListHead->m_pNext; pCur != pListHead; pCur=pNext) - { - pNext = pCur->m_pNext; - delete pCur; - } - } - - Clear(); -} - - -void CVoiceBanMgr::SaveState(const char *pGameDir) -{ - // Save the file out. - FileHandle_t fh = filesystem->Open(g_pBanMgrFilename, "wb"); - if(fh) - { - int version = BANMGR_FILEVERSION; - filesystem->Write(&version, sizeof(version), fh); - - for(int i=0; i < 256; i++) - { - BannedPlayer *pListHead = &m_PlayerHash[i]; - for(BannedPlayer *pCur=pListHead->m_pNext; pCur != pListHead; pCur=pCur->m_pNext) - { - filesystem->Write(pCur->m_PlayerID, SIGNED_GUID_LEN, fh); - } - } - - filesystem->Close(fh); - } -} - - -bool CVoiceBanMgr::GetPlayerBan(char const playerID[SIGNED_GUID_LEN]) -{ - return !!InternalFindPlayerSquelch(playerID); -} - - -void CVoiceBanMgr::SetPlayerBan(char const playerID[SIGNED_GUID_LEN], bool bSquelch) -{ - if(bSquelch) - { - // Is this guy already squelched? - if(GetPlayerBan(playerID)) - return; - - AddBannedPlayer(playerID); - } - else - { - BannedPlayer *pPlayer = InternalFindPlayerSquelch(playerID); - if(pPlayer) - { - pPlayer->m_pPrev->m_pNext = pPlayer->m_pNext; - pPlayer->m_pNext->m_pPrev = pPlayer->m_pPrev; - delete pPlayer; - } - } -} - - -void CVoiceBanMgr::Clear() -{ - // Tie off the hash table entries. - for(int i=0; i < 256; i++) - m_PlayerHash[i].m_pNext = m_PlayerHash[i].m_pPrev = &m_PlayerHash[i]; - - // TODO memory leaks ??? -} - - -CVoiceBanMgr::BannedPlayer* CVoiceBanMgr::InternalFindPlayerSquelch(char const playerID[SIGNED_GUID_LEN]) -{ - int index = HashPlayerID(playerID); - BannedPlayer *pListHead = &m_PlayerHash[index]; - for(BannedPlayer *pCur=pListHead->m_pNext; pCur != pListHead; pCur=pCur->m_pNext) - { - if(memcmp(playerID, pCur->m_PlayerID, SIGNED_GUID_LEN) == 0) - return pCur; - } - - return NULL; -} - - -CVoiceBanMgr::BannedPlayer* CVoiceBanMgr::AddBannedPlayer(char const playerID[SIGNED_GUID_LEN]) -{ - BannedPlayer *pNew = new BannedPlayer; - if(!pNew) - return NULL; - - int index = HashPlayerID(playerID); - memcpy(pNew->m_PlayerID, playerID, SIGNED_GUID_LEN); - pNew->m_pNext = &m_PlayerHash[index]; - pNew->m_pPrev = m_PlayerHash[index].m_pPrev; - pNew->m_pPrev->m_pNext = pNew->m_pNext->m_pPrev = pNew; - return pNew; -} - diff --git a/game/shared/voice_banmgr.h b/game/shared/voice_banmgr.h deleted file mode 100644 index 3da033bcd..000000000 --- a/game/shared/voice_banmgr.h +++ /dev/null @@ -1,54 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef VOICE_BANMGR_H -#define VOICE_BANMGR_H -#ifdef _WIN32 -#pragma once -#endif - - -// This class manages the (persistent) list of squelched players. -class CVoiceBanMgr -{ -public: - - CVoiceBanMgr(); - ~CVoiceBanMgr(); - - // Init loads the list of squelched players from disk. - bool Init(const char *pGameDir); - void Term(); - - // Saves the state into voice_squelch.dt. - void SaveState(const char *pGameDir); - - bool GetPlayerBan(char const playerID[SIGNED_GUID_LEN]); - void SetPlayerBan(char const playerID[SIGNED_GUID_LEN], bool bSquelch); - - -protected: - - class BannedPlayer - { - public: - char m_PlayerID[SIGNED_GUID_LEN]; - BannedPlayer *m_pPrev, *m_pNext; - }; - - void Clear(); - BannedPlayer* InternalFindPlayerSquelch(char const playerID[SIGNED_GUID_LEN]); - BannedPlayer* AddBannedPlayer(char const playerID[SIGNED_GUID_LEN]); - - -protected: - - BannedPlayer m_PlayerHash[256]; -}; - - -#endif // VOICE_BANMGR_H diff --git a/game/shared/voice_common.h b/game/shared/voice_common.h deleted file mode 100644 index fe8a479f4..000000000 --- a/game/shared/voice_common.h +++ /dev/null @@ -1,27 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef VOICE_COMMON_H -#define VOICE_COMMON_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "bitvec.h" -#include "const.h" - - -#define VOICE_MAX_PLAYERS MAX_PLAYERS -#define VOICE_MAX_PLAYERS_DW ((VOICE_MAX_PLAYERS / 32) + !!(VOICE_MAX_PLAYERS & 31)) - -typedef CBitVec CPlayerBitVec; - -#define VOICE_DEFAULT_PROXIMITY_RANGE 1200 //100 feet - - -#endif // VOICE_COMMON_H diff --git a/game/shared/voice_gamemgr.cpp b/game/shared/voice_gamemgr.cpp deleted file mode 100644 index 6e2b72c99..000000000 --- a/game/shared/voice_gamemgr.cpp +++ /dev/null @@ -1,289 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cbase.h" -#include "voice_gamemgr.h" -#include -#include -#include -#include "player.h" -#include "ivoiceserver.h" -#include "usermessages.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define UPDATE_INTERVAL 0.3 - - -// These are stored off as CVoiceGameMgr is created and deleted. -CPlayerBitVec g_PlayerModEnable; // Set to 1 for each player if the player wants to use voice in this mod. - // (If it's zero, then the server reports that the game rules are saying the - // player can't hear anyone). - -CPlayerBitVec g_BanMasks[VOICE_MAX_PLAYERS]; // Tells which players don't want to hear each other. - // These are indexed as clients and each bit represents a client - // (so player entity is bit+1). - -CPlayerBitVec g_SentGameRulesMasks[VOICE_MAX_PLAYERS]; // These store the masks we last sent to each client so we can determine if -CPlayerBitVec g_SentBanMasks[VOICE_MAX_PLAYERS]; // we need to resend them. -CPlayerBitVec g_bWantModEnable; - -ConVar voice_serverdebug( "voice_serverdebug", "0" ); - -// Set game rules to allow all clients to talk to each other. -// Muted players still can't talk to each other. -ConVar sv_alltalk( "sv_alltalk", "0", FCVAR_NOTIFY, "Players can hear all other players, no team restrictions" ); - - -CVoiceGameMgr g_VoiceGameMgr; - - -// ------------------------------------------------------------------------ // -// Static helpers. -// ------------------------------------------------------------------------ // - -// Find a player with a case-insensitive name search. -/*static CBasePlayer* FindPlayerByName(const char *pTestName) -{ - for(int i=1; i <= gpGlobals->maxClients; i++) - { - edict_t *pEdict = engine->PEntityOfEntIndex(i); - if(pEdict) - { - CBaseEntity *pEnt = CBaseEntity::Instance(pEdict); - if(pEnt && pEnt->IsPlayer()) - { - const char *pNetName = STRING(pEnt->GetEntityName()); - if(stricmp(pNetName, pTestName) == 0) - { - return (CBasePlayer*)pEnt; - } - } - } - } - - return NULL; -}*/ - -static void VoiceServerDebug( const char *pFmt, ... ) -{ - char msg[4096]; - va_list marker; - - if( !voice_serverdebug.GetInt() ) - return; - - va_start( marker, pFmt ); - _vsnprintf( msg, sizeof(msg), pFmt, marker ); - va_end( marker ); - - Msg( "%s", msg ); -} - - -CVoiceGameMgr* GetVoiceGameMgr() -{ - return &g_VoiceGameMgr; -} - - - -// ------------------------------------------------------------------------ // -// CVoiceGameMgr. -// ------------------------------------------------------------------------ // - -CVoiceGameMgr::CVoiceGameMgr() -{ - m_UpdateInterval = 0; - m_nMaxPlayers = 0; - m_iProximityDistance = -1; -} - - -CVoiceGameMgr::~CVoiceGameMgr() -{ -} - -bool CVoiceGameMgr::Init( - IVoiceGameMgrHelper *pHelper, - int maxClients) -{ - m_pHelper = pHelper; - m_nMaxPlayers = VOICE_MAX_PLAYERS < maxClients ? VOICE_MAX_PLAYERS : maxClients; - - return true; -} - - -void CVoiceGameMgr::SetHelper(IVoiceGameMgrHelper *pHelper) -{ - m_pHelper = pHelper; -} - - -void CVoiceGameMgr::Update(double frametime) -{ - // Only update periodically. - m_UpdateInterval += frametime; - if(m_UpdateInterval < UPDATE_INTERVAL) - return; - - UpdateMasks(); -} - - -void CVoiceGameMgr::ClientConnected(struct edict_t *pEdict) -{ - int index = ENTINDEX(pEdict) - 1; - - // Clear out everything we use for deltas on this guy. - g_bWantModEnable[index] = true; - g_SentGameRulesMasks[index].Init(0); - g_SentBanMasks[index].Init(0); -} - - -bool CVoiceGameMgr::ClientCommand( CBasePlayer *pPlayer, const CCommand &args ) -{ - int playerClientIndex = pPlayer->entindex() - 1; - if(playerClientIndex < 0 || playerClientIndex >= m_nMaxPlayers) - { - VoiceServerDebug( "CVoiceGameMgr::ClientCommand: cmd %s from invalid client (%d)\n", args[0], playerClientIndex ); - return true; - } - - bool bBan = stricmp( args[0], "vban" ) == 0; - if( bBan && args.ArgC() >= 2 ) - { - for(int i=1; i < args.ArgC(); i++) - { - unsigned long mask = 0; - sscanf( args[i], "%p", (void**)&mask); - - if( i <= VOICE_MAX_PLAYERS_DW ) - { - VoiceServerDebug( "CVoiceGameMgr::ClientCommand: vban (0x%x) from %d\n", mask, playerClientIndex ); - g_BanMasks[playerClientIndex].SetDWord(i-1, mask); - } - else - { - VoiceServerDebug( "CVoiceGameMgr::ClientCommand: invalid index (%d)\n", i ); - } - } - - // Force it to update the masks now. - //UpdateMasks(); - return true; - } - else if(stricmp( args[0], "VModEnable") == 0 && args.ArgC() >= 2) - { - VoiceServerDebug( "CVoiceGameMgr::ClientCommand: VModEnable (%d)\n", !!atoi( args[1] ) ); - g_PlayerModEnable[playerClientIndex] = !!atoi( args[1] ); - g_bWantModEnable[playerClientIndex] = false; - //UpdateMasks(); - return true; - } - else - { - return false; - } -} - -void CVoiceGameMgr::UpdateMasks() -{ - m_UpdateInterval = 0; - - bool bAllTalk = !!sv_alltalk.GetInt(); - - for(int iClient=0; iClient < m_nMaxPlayers; iClient++) - { - CBaseEntity *pEnt = UTIL_PlayerByIndex(iClient+1); - if(!pEnt || !pEnt->IsPlayer()) - continue; - - CBasePlayer *pPlayer = (CBasePlayer*)pEnt; - - CSingleUserRecipientFilter user( pPlayer ); - - // Request the state of their "VModEnable" cvar. - if(g_bWantModEnable[iClient]) - { - - UserMessageBegin( user, "RequestState" ); - MessageEnd(); - // Since this is reliable, only send it once - g_bWantModEnable[iClient] = false; - } - - CPlayerBitVec gameRulesMask; - CPlayerBitVec ProximityMask; - bool bProximity = false; - if( g_PlayerModEnable[iClient] ) - { - // Build a mask of who they can hear based on the game rules. - for(int iOtherClient=0; iOtherClient < m_nMaxPlayers; iOtherClient++) - { - CBaseEntity *pEnt = UTIL_PlayerByIndex(iOtherClient+1); - if(pEnt && pEnt->IsPlayer() && - (bAllTalk || m_pHelper->CanPlayerHearPlayer(pPlayer, (CBasePlayer*)pEnt, bProximity )) ) - { - gameRulesMask[iOtherClient] = true; - ProximityMask[iOtherClient] = bProximity; - } - } - } - - // If this is different from what the client has, send an update. - if(gameRulesMask != g_SentGameRulesMasks[iClient] || - g_BanMasks[iClient] != g_SentBanMasks[iClient]) - { - g_SentGameRulesMasks[iClient] = gameRulesMask; - g_SentBanMasks[iClient] = g_BanMasks[iClient]; - - UserMessageBegin( user, "VoiceMask" ); - int dw; - for(dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++) - { - WRITE_LONG(gameRulesMask.GetDWord(dw)); - WRITE_LONG(g_BanMasks[iClient].GetDWord(dw)); - } - WRITE_BYTE( !!g_PlayerModEnable[iClient] ); - MessageEnd(); - } - - // Tell the engine. - for(int iOtherClient=0; iOtherClient < m_nMaxPlayers; iOtherClient++) - { - bool bCanHear = gameRulesMask[iOtherClient] && !g_BanMasks[iClient][iOtherClient]; - g_pVoiceServer->SetClientListening( iClient+1, iOtherClient+1, bCanHear ); - - if ( bCanHear ) - { - g_pVoiceServer->SetClientProximity( iClient+1, iOtherClient+1, !!ProximityMask[iOtherClient] ); - } - } - } -} - -bool CVoiceGameMgr::IsPlayerIgnoringPlayer( int iTalker, int iListener ) -{ - return !!g_BanMasks[iListener-1][iTalker-1]; -} - -void CVoiceGameMgr::SetProximityDistance( int iDistance ) -{ - m_iProximityDistance = iDistance; -} - -bool CVoiceGameMgr::CheckProximity( int iDistance ) -{ - if ( m_iProximityDistance >= iDistance ) - return true; - - return false; -} diff --git a/game/shared/voice_gamemgr.h b/game/shared/voice_gamemgr.h deleted file mode 100644 index caf171210..000000000 --- a/game/shared/voice_gamemgr.h +++ /dev/null @@ -1,81 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef VOICE_GAMEMGR_H -#define VOICE_GAMEMGR_H -#pragma once - - -#include "voice_common.h" - - -class CGameRules; -class CBasePlayer; - -abstract_class IVoiceGameMgrHelper -{ -public: - virtual ~IVoiceGameMgrHelper() {} - - // Called each frame to determine which players are allowed to hear each other. This overrides - // whatever squelch settings players have. - virtual bool CanPlayerHearPlayer(CBasePlayer *pListener, CBasePlayer *pTalker, bool &bProximity ) = 0; -}; - - -// CVoiceGameMgr manages which clients can hear which other clients. -class CVoiceGameMgr -{ -public: - CVoiceGameMgr(); - virtual ~CVoiceGameMgr(); - - bool Init( - IVoiceGameMgrHelper *m_pHelper, - int maxClients - ); - - void SetHelper(IVoiceGameMgrHelper *pHelper); - - // Updates which players can hear which other players. - // If gameplay mode is DM, then only players within the PVS can hear each other. - // If gameplay mode is teamplay, then only players on the same team can hear each other. - // Player masks are always applied. - void Update(double frametime); - - // Called when a new client connects (unsquelches its entity for everyone). - void ClientConnected(struct edict_t *pEdict); - - // Called on ClientCommand. Checks for the squelch and unsquelch commands. - // Returns true if it handled the command. - bool ClientCommand(CBasePlayer *pPlayer, const CCommand &args ); - - bool CheckProximity( int iDistance ); - void SetProximityDistance( int iDistance ); - - bool IsPlayerIgnoringPlayer( int iTalker, int iListener ); - -private: - - // Force it to update the client masks. - void UpdateMasks(); - - -private: - IVoiceGameMgrHelper *m_pHelper; - int m_nMaxPlayers; - double m_UpdateInterval; // How long since the last update. - int m_iProximityDistance; -}; - - -// Use this to access CVoiceGameMgr. -CVoiceGameMgr* GetVoiceGameMgr(); - - - -#endif // VOICE_GAMEMGR_H diff --git a/game/shared/voice_status.cpp b/game/shared/voice_status.cpp deleted file mode 100644 index 74132c2ef..000000000 --- a/game/shared/voice_status.cpp +++ /dev/null @@ -1,564 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include "basetypes.h" -#include "hud.h" -#include -#include -#include "voice_status.h" -#include "r_efx.h" -#include -#include -#include "cdll_client_int.h" -#include "hud_macros.h" -#include "c_playerresource.h" -#include "cliententitylist.h" -#include "c_baseplayer.h" -#include "materialsystem/imesh.h" -#include "view.h" -#include "convar.h" -#include -#include -#include -#include "vgui_BitmapImage.h" -#include "materialsystem/imaterial.h" -#include "tier0/dbg.h" -#include "cdll_int.h" -#include - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -using namespace vgui; - - -extern int cam_thirdperson; - - -#define VOICE_MODEL_INTERVAL 0.3 -#define SQUELCHOSCILLATE_PER_SECOND 2.0f - -ConVar voice_modenable( "voice_modenable", "1", FCVAR_ARCHIVE | FCVAR_CLIENTCMD_CAN_EXECUTE, "Enable/disable voice in this mod." ); -ConVar voice_clientdebug( "voice_clientdebug", "0" ); - -// ---------------------------------------------------------------------- // -// The voice manager for the client. -// ---------------------------------------------------------------------- // -static CVoiceStatus *g_VoiceStatus = NULL; - -CVoiceStatus* GetClientVoiceMgr() -{ - if ( !g_VoiceStatus ) - { - ClientVoiceMgr_Init(); - } - - return g_VoiceStatus; -} - -void ClientVoiceMgr_Init() -{ - if ( g_VoiceStatus ) - return; - - g_VoiceStatus = new CVoiceStatus(); -} - -void ClientVoiceMgr_Shutdown() -{ - delete g_VoiceStatus; - g_VoiceStatus = NULL; -} - -// ---------------------------------------------------------------------- // -// CVoiceStatus. -// ---------------------------------------------------------------------- // - -static CVoiceStatus *g_pInternalVoiceStatus = NULL; - -void __MsgFunc_VoiceMask(bf_read &msg) -{ - if(g_pInternalVoiceStatus) - g_pInternalVoiceStatus->HandleVoiceMaskMsg(msg); -} - -void __MsgFunc_RequestState(bf_read &msg) -{ - if(g_pInternalVoiceStatus) - g_pInternalVoiceStatus->HandleReqStateMsg(msg); -} - - -// ---------------------------------------------------------------------- // -// CVoiceStatus. -// ---------------------------------------------------------------------- // - -CVoiceStatus::CVoiceStatus() -{ - m_nControlSize = 0; - m_bBanMgrInitialized = false; - m_LastUpdateServerState = 0; - - m_bTalking = m_bServerAcked = false; - - m_bServerModEnable = -1; - - m_pHeadLabelMaterial = NULL; - - m_bHeadLabelsDisabled = false; -} - - -CVoiceStatus::~CVoiceStatus() -{ - if ( m_pHeadLabelMaterial ) - { - m_pHeadLabelMaterial->DecrementReferenceCount(); - } - - g_pInternalVoiceStatus = NULL; - - const char *pGameDir = engine->GetGameDirectory(); - if( pGameDir ) - { - if(m_bBanMgrInitialized) - { - m_BanMgr.SaveState( pGameDir ); - } - } -} - -int CVoiceStatus::Init( - IVoiceStatusHelper *pHelper, - VPANEL pParentPanel) -{ - const char *pGameDir = engine->GetGameDirectory(); - if( pGameDir ) - { - m_BanMgr.Init( pGameDir ); - m_bBanMgrInitialized = true; - } - - Assert(!g_pInternalVoiceStatus); - g_pInternalVoiceStatus = this; - - - m_pHeadLabelMaterial = materials->FindMaterial( "voice/icntlk_pl", TEXTURE_GROUP_VGUI ); - m_pHeadLabelMaterial->IncrementReferenceCount(); - - m_bInSquelchMode = false; - - m_pHelper = pHelper; - m_pParentPanel = pParentPanel; - - HOOK_MESSAGE(VoiceMask); - HOOK_MESSAGE(RequestState); - - return 1; -} - - -BitmapImage* vgui_LoadMaterial( vgui::VPANEL pParent, const char *pFilename ) -{ - return new BitmapImage( pParent, pFilename ); -} - - -void CVoiceStatus::VidInit() -{ -} - - -void CVoiceStatus::Frame(double frametime) -{ - // check server banned players once per second - if (gpGlobals->curtime - m_LastUpdateServerState > 1) - { - UpdateServerState(false); - } -} - - -float g_flHeadOffset = 35; -float g_flHeadIconSize = 8; - - -void CVoiceStatus::SetHeadLabelOffset( float offset ) -{ - g_flHeadOffset = offset; -} - -float CVoiceStatus::GetHeadLabelOffset( void ) const -{ - return g_flHeadOffset; -} - - -void CVoiceStatus::DrawHeadLabels() -{ - if ( m_bHeadLabelsDisabled ) - return; - - if( !m_pHeadLabelMaterial ) - return; - - CMatRenderContextPtr pRenderContext( materials ); - - for(int i=0; i < VOICE_MAX_PLAYERS; i++) - { - if ( !m_VoicePlayers[i] ) - continue; - - IClientNetworkable *pClient = cl_entitylist->GetClientEntity( i+1 ); - - // Don't show an icon if the player is not in our PVS. - if ( !pClient || pClient->IsDormant() ) - continue; - - C_BasePlayer *pPlayer = dynamic_cast(pClient); - if( !pPlayer ) - continue; - - // Don't show an icon for dead or spectating players (ie: invisible entities). - if( pPlayer->IsPlayerDead() ) - continue; - - // Place it 20 units above his head. - Vector vOrigin = pPlayer->WorldSpaceCenter(); - vOrigin.z += g_flHeadOffset; - - - // Align it so it never points up or down. - Vector vUp( 0, 0, 1 ); - Vector vRight = CurrentViewRight(); - if ( fabs( vRight.z ) > 0.95 ) // don't draw it edge-on - continue; - - vRight.z = 0; - VectorNormalize( vRight ); - - - float flSize = g_flHeadIconSize; - - pRenderContext->Bind( pPlayer->GetHeadLabelMaterial() ); - IMesh *pMesh = pRenderContext->GetDynamicMesh(); - CMeshBuilder meshBuilder; - meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 ); - - meshBuilder.Color3f( 1.0, 1.0, 1.0 ); - meshBuilder.TexCoord2f( 0,0,0 ); - meshBuilder.Position3fv( (vOrigin + (vRight * -flSize) + (vUp * flSize)).Base() ); - meshBuilder.AdvanceVertex(); - - meshBuilder.Color3f( 1.0, 1.0, 1.0 ); - meshBuilder.TexCoord2f( 0,1,0 ); - meshBuilder.Position3fv( (vOrigin + (vRight * flSize) + (vUp * flSize)).Base() ); - meshBuilder.AdvanceVertex(); - - meshBuilder.Color3f( 1.0, 1.0, 1.0 ); - meshBuilder.TexCoord2f( 0,1,1 ); - meshBuilder.Position3fv( (vOrigin + (vRight * flSize) + (vUp * -flSize)).Base() ); - meshBuilder.AdvanceVertex(); - - meshBuilder.Color3f( 1.0, 1.0, 1.0 ); - meshBuilder.TexCoord2f( 0,0,1 ); - meshBuilder.Position3fv( (vOrigin + (vRight * -flSize) + (vUp * -flSize)).Base() ); - meshBuilder.AdvanceVertex(); - meshBuilder.End(); - pMesh->Draw(); - } -} - - -void CVoiceStatus::UpdateSpeakerStatus(int entindex, bool bTalking) -{ - if(!m_pParentPanel) - return; - - if( voice_clientdebug.GetInt() ) - { - Msg( "CVoiceStatus::UpdateSpeakerStatus: ent %d talking = %d\n", entindex, bTalking ); - } - - // Is it the local player talking? - if( entindex == -1 ) - { - m_bTalking = !!bTalking; - if( bTalking ) - { - // Enable voice for them automatically if they try to talk. - engine->ClientCmd( "voice_modenable 1" ); - } - } - else if( entindex == -2 ) - { - m_bServerAcked = !!bTalking; - } - else if(entindex > 0 && entindex <= VOICE_MAX_PLAYERS) - { - int iClient = entindex - 1; - if(iClient < 0) - return; - - if(bTalking) - { - m_VoicePlayers[iClient] = true; - m_VoiceEnabledPlayers[iClient] = true; - } - else - { - m_VoicePlayers[iClient] = false; - } - } -} - - -void CVoiceStatus::UpdateServerState(bool bForce) -{ - // Can't do anything when we're not in a level. - if( !g_bLevelInitialized ) - { - if( voice_clientdebug.GetInt() ) - { - Msg( "CVoiceStatus::UpdateServerState: g_bLevelInitialized\n" ); - } - - return; - } - - int bCVarModEnable = !!voice_modenable.GetInt(); - if(bForce || m_bServerModEnable != bCVarModEnable) - { - m_bServerModEnable = bCVarModEnable; - - char str[256]; - Q_snprintf(str, sizeof(str), "VModEnable %d", m_bServerModEnable); - engine->ServerCmd(str); - - if( voice_clientdebug.GetInt() ) - { - Msg( "CVoiceStatus::UpdateServerState: Sending '%s'\n", str ); - } - } - - char str[2048]; - Q_strncpy(str,"vban",sizeof(str)); - bool bChange = false; - - for(unsigned long dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++) - { - unsigned long serverBanMask = 0; - unsigned long banMask = 0; - for(unsigned long i=0; i < 32; i++) - { - int playerIndex = ( dw * 32 + i ); - if ( playerIndex >= MAX_PLAYERS ) - break; - - player_info_t pi; - - if ( !engine->GetPlayerInfo( i+1, &pi ) ) - continue; - - if ( m_BanMgr.GetPlayerBan( pi.guid ) ) - { - banMask |= 1 << i; - } - - if ( m_ServerBannedPlayers[playerIndex] ) - { - serverBanMask |= 1 << i; - } - } - - if ( serverBanMask != banMask ) - { - bChange = true; - } - - // Ok, the server needs to be updated. - char numStr[512]; - Q_snprintf(numStr,sizeof(numStr), " %x", banMask); - Q_strncat(str, numStr, sizeof(str), COPY_ALL_CHARACTERS); - } - - if(bChange || bForce) - { - if( voice_clientdebug.GetInt() ) - { - Msg( "CVoiceStatus::UpdateServerState: Sending '%s'\n", str ); - } - - engine->ServerCmd( str, false ); // Tell the server.. - } - else - { - if( voice_clientdebug.GetInt() ) - { - Msg( "CVoiceStatus::UpdateServerState: no change\n" ); - } - } - - m_LastUpdateServerState = gpGlobals->curtime; -} - -void CVoiceStatus::HandleVoiceMaskMsg(bf_read &msg) -{ - unsigned long dw; - for(dw=0; dw < VOICE_MAX_PLAYERS_DW; dw++) - { - m_AudiblePlayers.SetDWord(dw, (unsigned long)msg.ReadLong()); - m_ServerBannedPlayers.SetDWord(dw, (unsigned long)msg.ReadLong()); - - if( voice_clientdebug.GetInt()) - { - Msg("CVoiceStatus::HandleVoiceMaskMsg\n"); - Msg(" - m_AudiblePlayers[%d] = %lu\n", dw, m_AudiblePlayers.GetDWord(dw)); - Msg(" - m_ServerBannedPlayers[%d] = %lu\n", dw, m_ServerBannedPlayers.GetDWord(dw)); - } - } - - m_bServerModEnable = msg.ReadByte(); -} - -void CVoiceStatus::HandleReqStateMsg(bf_read &msg) -{ - if(voice_clientdebug.GetInt()) - { - Msg("CVoiceStatus::HandleReqStateMsg\n"); - } - - UpdateServerState(true); -} - -void CVoiceStatus::StartSquelchMode() -{ - if(m_bInSquelchMode) - return; - - m_bInSquelchMode = true; - m_pHelper->UpdateCursorState(); -} - -void CVoiceStatus::StopSquelchMode() -{ - m_bInSquelchMode = false; - m_pHelper->UpdateCursorState(); -} - -bool CVoiceStatus::IsInSquelchMode() -{ - return m_bInSquelchMode; -} - -void SetOrUpdateBounds( - vgui::Panel *pPanel, - int left, int top, int wide, int tall, - bool bOnlyUpdateBounds, int &topCoord, int &bottomCoord ) -{ - if ( bOnlyUpdateBounds ) - { - if ( top < topCoord ) - topCoord = top; - - if ( (top+tall) >= bottomCoord ) - bottomCoord = top+tall; - } - else - { - pPanel->SetBounds( left, top, wide, tall ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: returns true if the target client has been banned -// Input : playerID - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CVoiceStatus::IsPlayerBlocked(int iPlayer) -{ - player_info_t pi; - - if ( !engine->GetPlayerInfo( iPlayer, &pi ) ) - return false; - - return m_BanMgr.GetPlayerBan( pi.guid ); -} - -//----------------------------------------------------------------------------- -// Purpose: returns true if the player can't hear the other client due to game rules (eg. the other team) -// Input : playerID - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CVoiceStatus::IsPlayerAudible(int iPlayer) -{ - return !!m_AudiblePlayers[iPlayer-1]; -} - - -//----------------------------------------------------------------------------- -// returns true if the player is currently speaking -//----------------------------------------------------------------------------- -bool CVoiceStatus::IsPlayerSpeaking(int iPlayerIndex) -{ - return m_VoicePlayers[iPlayerIndex-1] != 0; -} - -//----------------------------------------------------------------------------- -// returns true if the local player is attempting to speak -//----------------------------------------------------------------------------- -bool CVoiceStatus::IsLocalPlayerSpeaking( void ) -{ - return m_bTalking; -} - - -//----------------------------------------------------------------------------- -// Purpose: blocks/unblocks the target client from being heard -// Input : playerID - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -void CVoiceStatus::SetPlayerBlockedState(int iPlayer, bool blocked) -{ - if (voice_clientdebug.GetInt()) - { - Msg( "CVoiceStatus::SetPlayerBlockedState part 1\n" ); - } - - player_info_t pi; - if ( !engine->GetPlayerInfo( iPlayer, &pi ) ) - return; - - if (voice_clientdebug.GetInt()) - { - Msg( "CVoiceStatus::SetPlayerBlockedState part 2\n" ); - } - - // Squelch or (try to) unsquelch this player. - if (voice_clientdebug.GetInt()) - { - Msg("CVoiceStatus::SetPlayerBlockedState: setting player %d ban to %d\n", iPlayer, !m_BanMgr.GetPlayerBan(pi.guid)); - } - - m_BanMgr.SetPlayerBan(pi.guid, !m_BanMgr.GetPlayerBan(pi.guid)); - UpdateServerState(false); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CVoiceStatus::SetHeadLabelMaterial( const char *pszMaterial ) -{ - if ( m_pHeadLabelMaterial ) - { - m_pHeadLabelMaterial->DecrementReferenceCount(); - m_pHeadLabelMaterial = NULL; - } - - m_pHeadLabelMaterial = materials->FindMaterial( pszMaterial, TEXTURE_GROUP_VGUI ); - m_pHeadLabelMaterial->IncrementReferenceCount(); -} diff --git a/game/shared/voice_status.h b/game/shared/voice_status.h deleted file mode 100644 index 1743e2d3c..000000000 --- a/game/shared/voice_status.h +++ /dev/null @@ -1,190 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef VOICE_STATUS_H -#define VOICE_STATUS_H -#pragma once - - -#include -//#include "VGUI_Bitmap.h" -#include -#include -#include "voice_common.h" -#include "voice_banmgr.h" -#include "hudelement.h" - - -class CVoiceStatus; -class IMaterial; -class BitmapImage; - -// Voice Panel -class CVoicePanel : public vgui::Panel -{ -public: - CVoicePanel( ); - ~CVoicePanel(); - - virtual void Paint( void ); - virtual void setImage( BitmapImage *pImage ); - -private: - BitmapImage *m_pImage; -}; - -class CVoiceLabel -{ -public: - vgui::Label *m_pLabel; - vgui::Label *m_pBackground; - CVoicePanel *m_pIcon; // Voice icon next to player name. - int m_clientindex; // Client index of the speaker. -1 if this label isn't being used. -}; - -// This is provided by each mod to access data that may not be the same across mods. -abstract_class IVoiceStatusHelper -{ -public: - virtual ~IVoiceStatusHelper() {} - - // Get RGB color for voice status text about this player. - virtual void GetPlayerTextColor(int entindex, int color[3]) = 0; - - // Force it to update the cursor state. - virtual void UpdateCursorState() = 0; - - // Return true if the voice manager is allowed to show speaker labels - // (mods usually return false when the scoreboard is up). - virtual bool CanShowSpeakerLabels() = 0; -}; - -class CVoiceStatus /*: public vgui::CDefaultInputSignal*/ -{ -public: - CVoiceStatus(); - virtual ~CVoiceStatus(); - -// CHudBase overrides. -public: - - // Initialize the cl_dll's voice manager. - virtual int Init( - IVoiceStatusHelper *m_pHelper, - vgui::VPANEL pParentPanel); - - // ackPosition is the bottom position of where CVoiceStatus will draw the voice acknowledgement labels. - virtual void VidInit(); - -public: - - // Call from HUD_Frame each frame. - void Frame(double frametime); - - // Called when a player starts or stops talking. - // entindex is -1 to represent the local client talking (before the data comes back from the server). - // When the server acknowledges that the local client is talking, then entindex will be gEngfuncs.GetLocalPlayer(). - // entindex is -2 to represent the local client's voice being acked by the server. - void UpdateSpeakerStatus(int entindex, bool bTalking); - - // Call from the HUD_CreateEntities function so it can add sprites above player heads. - void DrawHeadLabels(); - void SetHeadLabelOffset( float offset ); - float GetHeadLabelOffset( void ) const; - void SetHeadLabelsDisabled( bool bDisabled ) { m_bHeadLabelsDisabled = bDisabled; } - - // Called when the server registers a change to who this client can hear. - void HandleVoiceMaskMsg(bf_read &msg); - - // The server sends this message initially to tell the client to send their state. - void HandleReqStateMsg(bf_read &msg); - - -// Squelch mode functions. -public: - - // When you enter squelch mode, pass in - void StartSquelchMode(); - void StopSquelchMode(); - bool IsInSquelchMode(); - - // returns true if the target client has been banned - // playerIndex is of range 1..maxplayers - bool IsPlayerBlocked(int iPlayerIndex); - - // returns false if the player can't hear the other client due to game rules (eg. the other team) - bool IsPlayerAudible(int iPlayerIndex); - - // returns true if the player is currently speaking - bool IsPlayerSpeaking(int iPlayerIndex); - - // returns true if the local player is attempting to speak - bool IsLocalPlayerSpeaking( void ); - - // blocks the target client from being heard - void SetPlayerBlockedState(int iPlayerIndex, bool blocked); - - void SetHeadLabelMaterial( const char *pszMaterial ); - - IMaterial *GetHeadLabelMaterial( void ) { return m_pHeadLabelMaterial; } - -private: - - void UpdateServerState(bool bForce); - - // Update the button artwork to reflect the client's current state. - void UpdateBanButton(int iClient); - - -private: - float m_LastUpdateServerState; // Last time we called this function. - int m_bServerModEnable; // What we've sent to the server about our "voice_modenable" cvar. - - vgui::VPANEL m_pParentPanel; - CPlayerBitVec m_VoicePlayers; // Who is currently talking. Indexed by client index. - - // This is the gamerules-defined list of players that you can hear. It is based on what teams people are on - // and is totally separate from the ban list. Indexed by client index. - CPlayerBitVec m_AudiblePlayers; - - // Players who have spoken at least once in the game so far - CPlayerBitVec m_VoiceEnabledPlayers; - - // This is who the server THINKS we have banned (it can become incorrect when a new player arrives on the server). - // It is checked periodically, and the server is told to squelch or unsquelch the appropriate players. - CPlayerBitVec m_ServerBannedPlayers; - - IVoiceStatusHelper *m_pHelper; // Each mod provides an implementation of this. - - // Squelch mode stuff. - bool m_bInSquelchMode; - - bool m_bTalking; // Set to true when the client thinks it's talking. - bool m_bServerAcked; // Set to true when the server knows the client is talking. - -public: - - CVoiceBanMgr m_BanMgr; // Tracks which users we have squelched and don't want to hear. - -private: - - IMaterial *m_pHeadLabelMaterial; // For labels above players' heads. - - bool m_bBanMgrInitialized; - - int m_nControlSize; - - bool m_bHeadLabelsDisabled; -}; - - -// Get the (global) voice manager. -CVoiceStatus* GetClientVoiceMgr(); -void ClientVoiceMgr_Init(); -void ClientVoiceMgr_Shutdown(); - -#endif // VOICE_STATUS_H diff --git a/game/shared/vphysics_sound.h b/game/shared/vphysics_sound.h deleted file mode 100644 index dcf23703c..000000000 --- a/game/shared/vphysics_sound.h +++ /dev/null @@ -1,177 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef VPHYSICS_SOUND_H -#define VPHYSICS_SOUND_H -#ifdef _WIN32 -#pragma once -#endif - -#include "SoundEmitterSystem/isoundemittersystembase.h" - -namespace physicssound -{ - struct impactsound_t - { - void *pGameData; - int entityIndex; - int soundChannel; - float volume; - float impactSpeed; - unsigned short surfaceProps; - unsigned short surfacePropsHit; - Vector origin; - }; - - // UNDONE: Use a sorted container and sort by volume/distance? - struct soundlist_t - { - CUtlVector elements; - impactsound_t &GetElement(int index) { return elements[index]; } - impactsound_t &AddElement() { return elements[elements.AddToTail()]; } - int Count() { return elements.Count(); } - void RemoveAll() { elements.RemoveAll(); } - }; - - void PlayImpactSounds( soundlist_t &list ) - { - for ( int i = list.Count()-1; i >= 0; --i ) - { - impactsound_t &sound = list.GetElement(i); - const surfacedata_t *psurf = physprops->GetSurfaceData( sound.surfaceProps ); - if ( psurf->sounds.impactHard ) - { - const surfacedata_t *pHit = physprops->GetSurfaceData( sound.surfacePropsHit ); - unsigned short soundName = psurf->sounds.impactHard; - if ( pHit && psurf->sounds.impactSoft ) - { - if ( pHit->audio.hardnessFactor < psurf->audio.hardThreshold || - (psurf->audio.hardVelocityThreshold > 0 && psurf->audio.hardVelocityThreshold > sound.impactSpeed) ) - { - soundName = psurf->sounds.impactSoft; - } - } - const char *pSound = physprops->GetString( soundName ); - - CSoundParameters params; - if ( !CBaseEntity::GetParametersForSound( pSound, params, NULL ) ) - break; - - if ( sound.volume > 1 ) - sound.volume = 1; - CPASAttenuationFilter filter( sound.origin, params.soundlevel ); - // JAY: If this entity gets deleted, the sound comes out at the world origin - // this sounds bad! Play on ent 0 for now. - EmitSound_t ep; - ep.m_nChannel = sound.soundChannel; - ep.m_pSoundName = params.soundname; - ep.m_flVolume = params.volume * sound.volume; - ep.m_SoundLevel = params.soundlevel; - ep.m_nPitch = params.pitch; - ep.m_pOrigin = &sound.origin; - - CBaseEntity::EmitSound( filter, 0 /*sound.entityIndex*/, ep ); - } - } - list.RemoveAll(); - } - void AddImpactSound( soundlist_t &list, void *pGameData, int entityIndex, int soundChannel, IPhysicsObject *pObject, int surfaceProps, int surfacePropsHit, float volume, float impactSpeed ) - { - impactSpeed += 1e-4; - for ( int i = list.Count()-1; i >= 0; --i ) - { - impactsound_t &sound = list.GetElement(i); - // UNDONE: Compare entity or channel somehow? - // UNDONE: Doing one slot per entity is too noisy. So now we use one slot per material - - // heuristic - after 4 impacts sounds in one frame, start merging everything - if ( surfaceProps == sound.surfaceProps || list.Count() > 4 ) - { - // UNDONE: Store instance volume separate from aggregate volume and compare that? - if ( volume > sound.volume ) - { - pObject->GetPosition( &sound.origin, NULL ); - sound.pGameData = pGameData; - sound.entityIndex = entityIndex; - sound.soundChannel = soundChannel; - sound.surfacePropsHit = surfacePropsHit; - } - sound.volume += volume; - sound.impactSpeed = MAX(impactSpeed,sound.impactSpeed); - return; - } - } - - impactsound_t &sound = list.AddElement(); - sound.pGameData = pGameData; - sound.entityIndex = entityIndex; - sound.soundChannel = soundChannel; - pObject->GetPosition( &sound.origin, NULL ); - sound.surfaceProps = surfaceProps; - sound.surfacePropsHit = surfacePropsHit; - sound.volume = volume; - sound.impactSpeed = impactSpeed; - } - - struct breaksound_t - { - Vector origin; - int surfacePropsBreak; - }; - - void AddBreakSound( CUtlVector &list, const Vector &origin, unsigned short surfaceProps ) - { - const surfacedata_t *psurf = physprops->GetSurfaceData( surfaceProps ); - if ( !psurf->sounds.breakSound ) - return; - - for ( int i = list.Count()-1; i >= 0; --i ) - { - breaksound_t &sound = list.Element(i); - // Allow 3 break sounds before you start merging anything. - if ( list.Count() > 2 && surfaceProps == sound.surfacePropsBreak ) - { - sound.origin = (sound.origin + origin) * 0.5f; - return; - } - } - breaksound_t sound; - sound.origin = origin; - sound.surfacePropsBreak = surfaceProps; - list.AddToTail(sound); - - } - - void PlayBreakSounds( CUtlVector &list ) - { - for ( int i = list.Count()-1; i >= 0; --i ) - { - breaksound_t &sound = list.Element(i); - - const surfacedata_t *psurf = physprops->GetSurfaceData( sound.surfacePropsBreak ); - const char *pSound = physprops->GetString( psurf->sounds.breakSound ); - CSoundParameters params; - if ( !CBaseEntity::GetParametersForSound( pSound, params, NULL ) ) - return; - - // Play from the world, because the entity is breaking, so it'll be destroyed soon - CPASAttenuationFilter filter( sound.origin, params.soundlevel ); - EmitSound_t ep; - ep.m_nChannel = CHAN_STATIC; - ep.m_pSoundName = params.soundname; - ep.m_flVolume = params.volume; - ep.m_SoundLevel = params.soundlevel; - ep.m_nPitch = params.pitch; - ep.m_pOrigin = &sound.origin; - CBaseEntity::EmitSound( filter, 0 /*sound.entityIndex*/, ep ); - } - list.RemoveAll(); - } -}; - - -#endif // VPHYSICS_SOUND_H diff --git a/game/shared/vphysicsupdateai.h b/game/shared/vphysicsupdateai.h deleted file mode 100644 index df424f6ca..000000000 --- a/game/shared/vphysicsupdateai.h +++ /dev/null @@ -1,24 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef VPHYSICSUPDATEAI_H -#define VPHYSICSUPDATEAI_H -#ifdef _WIN32 -#pragma once -#endif - - -// this is used to temporarily allow the vphysics shadow object to update the entity's position -// for entities that typically ignore those updates. -struct vphysicsupdateai_t -{ - float startUpdateTime; - float stopUpdateTime; - float savedShadowControllerMaxSpeed; -}; - - -#endif // VPHYSICSUPDATEAI_H diff --git a/game/shared/weapon_parse.cpp b/game/shared/weapon_parse.cpp deleted file mode 100644 index 1892207ca..000000000 --- a/game/shared/weapon_parse.cpp +++ /dev/null @@ -1,455 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Weapon data file parsing, shared by game & client dlls. -// -// $NoKeywords: $ -//=============================================================================// -#include "cbase.h" -#include -#include -#include "filesystem.h" -#include "utldict.h" -#include "ammodef.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// The sound categories found in the weapon classname.txt files -// This needs to match the WeaponSound_t enum in weapon_parse.h -#if !defined(_STATIC_LINKED) || defined(CLIENT_DLL) -const char *pWeaponSoundCategories[ NUM_SHOOT_SOUND_TYPES ] = -{ - "empty", - "single_shot", - "single_shot_npc", - "double_shot", - "double_shot_npc", - "burst", - "reload", - "reload_npc", - "melee_miss", - "melee_hit", - "melee_hit_world", - "special1", - "special2", - "special3", - "taunt" -}; -#else -extern const char *pWeaponSoundCategories[ NUM_SHOOT_SOUND_TYPES ]; -#endif - -int GetWeaponSoundFromString( const char *pszString ) -{ - for ( int i = EMPTY; i < NUM_SHOOT_SOUND_TYPES; i++ ) - { - if ( !Q_stricmp(pszString,pWeaponSoundCategories[i]) ) - return (WeaponSound_t)i; - } - return -1; -} - - -// Item flags that we parse out of the file. -typedef struct -{ - const char *m_pFlagName; - int m_iFlagValue; -} itemFlags_t; -#if !defined(_STATIC_LINKED) || defined(CLIENT_DLL) -itemFlags_t g_ItemFlags[8] = -{ - { "ITEM_FLAG_SELECTONEMPTY", ITEM_FLAG_SELECTONEMPTY }, - { "ITEM_FLAG_NOAUTORELOAD", ITEM_FLAG_NOAUTORELOAD }, - { "ITEM_FLAG_NOAUTOSWITCHEMPTY", ITEM_FLAG_NOAUTOSWITCHEMPTY }, - { "ITEM_FLAG_LIMITINWORLD", ITEM_FLAG_LIMITINWORLD }, - { "ITEM_FLAG_EXHAUSTIBLE", ITEM_FLAG_EXHAUSTIBLE }, - { "ITEM_FLAG_DOHITLOCATIONDMG", ITEM_FLAG_DOHITLOCATIONDMG }, - { "ITEM_FLAG_NOAMMOPICKUPS", ITEM_FLAG_NOAMMOPICKUPS }, - { "ITEM_FLAG_NOITEMPICKUP", ITEM_FLAG_NOITEMPICKUP } -}; -#else -extern itemFlags_t g_ItemFlags[7]; -#endif - - -static CUtlDict< FileWeaponInfo_t*, unsigned short > m_WeaponInfoDatabase; - -#ifdef _DEBUG -// used to track whether or not two weapons have been mistakenly assigned the wrong slot -bool g_bUsedWeaponSlots[MAX_WEAPON_SLOTS][MAX_WEAPON_POSITIONS] = { {false} }; - -#endif - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -// Output : FileWeaponInfo_t -//----------------------------------------------------------------------------- -static WEAPON_FILE_INFO_HANDLE FindWeaponInfoSlot( const char *name ) -{ - // Complain about duplicately defined metaclass names... - unsigned short lookup = m_WeaponInfoDatabase.Find( name ); - if ( lookup != m_WeaponInfoDatabase.InvalidIndex() ) - { - return lookup; - } - - FileWeaponInfo_t *insert = CreateWeaponInfo(); - - lookup = m_WeaponInfoDatabase.Insert( name, insert ); - Assert( lookup != m_WeaponInfoDatabase.InvalidIndex() ); - return lookup; -} - -// Find a weapon slot, assuming the weapon's data has already been loaded. -WEAPON_FILE_INFO_HANDLE LookupWeaponInfoSlot( const char *name ) -{ - return m_WeaponInfoDatabase.Find( name ); -} - - - -// FIXME, handle differently? -static FileWeaponInfo_t gNullWeaponInfo; - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : handle - -// Output : FileWeaponInfo_t -//----------------------------------------------------------------------------- -FileWeaponInfo_t *GetFileWeaponInfoFromHandle( WEAPON_FILE_INFO_HANDLE handle ) -{ - if ( handle >= m_WeaponInfoDatabase.Count() ) - { - return &gNullWeaponInfo; - } - - if ( handle == m_WeaponInfoDatabase.InvalidIndex() ) - { - return &gNullWeaponInfo; - } - - return m_WeaponInfoDatabase[ handle ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : WEAPON_FILE_INFO_HANDLE -//----------------------------------------------------------------------------- -WEAPON_FILE_INFO_HANDLE GetInvalidWeaponInfoHandle( void ) -{ - return (WEAPON_FILE_INFO_HANDLE)m_WeaponInfoDatabase.InvalidIndex(); -} - -#if 0 -void ResetFileWeaponInfoDatabase( void ) -{ - int c = m_WeaponInfoDatabase.Count(); - for ( int i = 0; i < c; ++i ) - { - delete m_WeaponInfoDatabase[ i ]; - } - m_WeaponInfoDatabase.RemoveAll(); - -#ifdef _DEBUG - memset(g_bUsedWeaponSlots, 0, sizeof(g_bUsedWeaponSlots)); -#endif -} -#endif - -void PrecacheFileWeaponInfoDatabase( IFileSystem *filesystem, const unsigned char *pICEKey ) -{ - if ( m_WeaponInfoDatabase.Count() ) - return; - - KeyValues *manifest = new KeyValues( "weaponscripts" ); - if ( manifest->LoadFromFile( filesystem, "scripts/weapon_manifest.txt", "GAME" ) ) - { - for ( KeyValues *sub = manifest->GetFirstSubKey(); sub != NULL ; sub = sub->GetNextKey() ) - { - if ( !Q_stricmp( sub->GetName(), "file" ) ) - { - char fileBase[512]; - Q_FileBase( sub->GetString(), fileBase, sizeof(fileBase) ); - WEAPON_FILE_INFO_HANDLE tmp; -#ifdef CLIENT_DLL - if ( ReadWeaponDataFromFileForSlot( filesystem, fileBase, &tmp, pICEKey ) ) - { - gWR.LoadWeaponSprites( tmp ); - } -#else - ReadWeaponDataFromFileForSlot( filesystem, fileBase, &tmp, pICEKey ); -#endif - } - else - { - Error( "Expecting 'file', got %s\n", sub->GetName() ); - } - } - } - manifest->deleteThis(); -} - -KeyValues* ReadEncryptedKVFile( IFileSystem *filesystem, const char *szFilenameWithoutExtension, const unsigned char *pICEKey ) -{ - Assert( strchr( szFilenameWithoutExtension, '.' ) == NULL ); - char szFullName[512]; - - const char *pSearchPath = "MOD"; - - if ( pICEKey == NULL ) - { - pSearchPath = "GAME"; - } - - // Open the weapon data file, and abort if we can't - KeyValues *pKV = new KeyValues( "WeaponDatafile" ); - - Q_snprintf(szFullName,sizeof(szFullName), "%s.txt", szFilenameWithoutExtension); - - if ( !pKV->LoadFromFile( filesystem, szFullName, pSearchPath ) ) // try to load the normal .txt file first - { -#ifndef _XBOX - if ( pICEKey ) - { - Q_snprintf(szFullName,sizeof(szFullName), "%s.ctx", szFilenameWithoutExtension); // fall back to the .ctx file - - FileHandle_t f = filesystem->Open( szFullName, "rb", pSearchPath ); - - if (!f) - { - pKV->deleteThis(); - return NULL; - } - // load file into a null-terminated buffer - int fileSize = filesystem->Size(f); - char *buffer = (char*)MemAllocScratch(fileSize + 1); - - Assert(buffer); - - filesystem->Read(buffer, fileSize, f); // read into local buffer - buffer[fileSize] = 0; // null terminate file as EOF - filesystem->Close( f ); // close file after reading - - UTIL_DecodeICE( (unsigned char*)buffer, fileSize, pICEKey ); - - bool retOK = pKV->LoadFromBuffer( szFullName, buffer, filesystem ); - - MemFreeScratch(); - - if ( !retOK ) - { - pKV->deleteThis(); - return NULL; - } - } - else - { - pKV->deleteThis(); - return NULL; - } -#else - pKV->deleteThis(); - return NULL; -#endif - } - - return pKV; -} - - -//----------------------------------------------------------------------------- -// Purpose: Read data on weapon from script file -// Output: true - if data2 successfully read -// false - if data load fails -//----------------------------------------------------------------------------- - -bool ReadWeaponDataFromFileForSlot( IFileSystem* filesystem, const char *szWeaponName, WEAPON_FILE_INFO_HANDLE *phandle, const unsigned char *pICEKey ) -{ - if ( !phandle ) - { - Assert( 0 ); - return false; - } - - *phandle = FindWeaponInfoSlot( szWeaponName ); - FileWeaponInfo_t *pFileInfo = GetFileWeaponInfoFromHandle( *phandle ); - Assert( pFileInfo ); - - if ( pFileInfo->bParsedScript ) - return true; - - char sz[128]; - Q_snprintf( sz, sizeof( sz ), "scripts/%s", szWeaponName ); - KeyValues *pKV = ReadEncryptedKVFile( filesystem, sz, pICEKey ); - if ( !pKV ) - return false; - - pFileInfo->Parse( pKV, szWeaponName ); - - pKV->deleteThis(); - - return true; -} - - -//----------------------------------------------------------------------------- -// FileWeaponInfo_t implementation. -//----------------------------------------------------------------------------- - -FileWeaponInfo_t::FileWeaponInfo_t() -{ - bParsedScript = false; - bLoadedHudElements = false; - szClassName[0] = 0; - szPrintName[0] = 0; - - szViewModel[0] = 0; - szWorldModel[0] = 0; - szAnimationPrefix[0] = 0; - iSlot = 0; - iPosition = 0; - iMaxClip1 = 0; - iMaxClip2 = 0; - iDefaultClip1 = 0; - iDefaultClip2 = 0; - iWeight = 0; - iRumbleEffect = -1; - bAutoSwitchTo = false; - bAutoSwitchFrom = false; - iFlags = 0; - szAmmo1[0] = 0; - szAmmo2[0] = 0; - memset( aShootSounds, 0, sizeof( aShootSounds ) ); - iAmmoType = 0; - iAmmo2Type = 0; - m_bMeleeWeapon = false; - iSpriteCount = 0; - iconActive = 0; - iconInactive = 0; - iconAmmo = 0; - iconAmmo2 = 0; - iconCrosshair = 0; - iconAutoaim = 0; - iconZoomedCrosshair = 0; - iconZoomedAutoaim = 0; - bShowUsageHint = false; - m_bAllowFlipping = true; - m_bBuiltRightHanded = true; -} - -#ifdef CLIENT_DLL -extern ConVar hud_fastswitch; -#endif - -void FileWeaponInfo_t::Parse( KeyValues *pKeyValuesData, const char *szWeaponName ) -{ - // Okay, we tried at least once to look this up... - bParsedScript = true; - - // Classname - Q_strncpy( szClassName, szWeaponName, MAX_WEAPON_STRING ); - // Printable name - Q_strncpy( szPrintName, pKeyValuesData->GetString( "printname", WEAPON_PRINTNAME_MISSING ), MAX_WEAPON_STRING ); - // View model & world model - Q_strncpy( szViewModel, pKeyValuesData->GetString( "viewmodel" ), MAX_WEAPON_STRING ); - Q_strncpy( szWorldModel, pKeyValuesData->GetString( "playermodel" ), MAX_WEAPON_STRING ); - Q_strncpy( szAnimationPrefix, pKeyValuesData->GetString( "anim_prefix" ), MAX_WEAPON_PREFIX ); - iSlot = pKeyValuesData->GetInt( "bucket", 0 ); - iPosition = pKeyValuesData->GetInt( "bucket_position", 0 ); - - // Use the console (X360) buckets if hud_fastswitch is set to 2. -#ifdef CLIENT_DLL - if ( hud_fastswitch.GetInt() == 2 ) -#else - if ( IsX360() ) -#endif - { - iSlot = pKeyValuesData->GetInt( "bucket_360", iSlot ); - iPosition = pKeyValuesData->GetInt( "bucket_position_360", iPosition ); - } - iMaxClip1 = pKeyValuesData->GetInt( "clip_size", WEAPON_NOCLIP ); // Max primary clips gun can hold (assume they don't use clips by default) - iMaxClip2 = pKeyValuesData->GetInt( "clip2_size", WEAPON_NOCLIP ); // Max secondary clips gun can hold (assume they don't use clips by default) - iDefaultClip1 = pKeyValuesData->GetInt( "default_clip", iMaxClip1 ); // amount of primary ammo placed in the primary clip when it's picked up - iDefaultClip2 = pKeyValuesData->GetInt( "default_clip2", iMaxClip2 ); // amount of secondary ammo placed in the secondary clip when it's picked up - iWeight = pKeyValuesData->GetInt( "weight", 0 ); - - iRumbleEffect = pKeyValuesData->GetInt( "rumble", -1 ); - - // LAME old way to specify item flags. - // Weapon scripts should use the flag names. - iFlags = pKeyValuesData->GetInt( "item_flags", ITEM_FLAG_LIMITINWORLD ); - - for ( size_t i=0; i < ARRAYSIZE( g_ItemFlags ); i++ ) - { - int iVal = pKeyValuesData->GetInt( g_ItemFlags[i].m_pFlagName, -1 ); - if ( iVal == 0 ) - { - iFlags &= ~g_ItemFlags[i].m_iFlagValue; - } - else if ( iVal == 1 ) - { - iFlags |= g_ItemFlags[i].m_iFlagValue; - } - } - - - bShowUsageHint = ( pKeyValuesData->GetInt( "showusagehint", 0 ) != 0 ) ? true : false; - bAutoSwitchTo = ( pKeyValuesData->GetInt( "autoswitchto", 1 ) != 0 ) ? true : false; - bAutoSwitchFrom = ( pKeyValuesData->GetInt( "autoswitchfrom", 1 ) != 0 ) ? true : false; - m_bBuiltRightHanded = ( pKeyValuesData->GetInt( "BuiltRightHanded", 1 ) != 0 ) ? true : false; - m_bAllowFlipping = ( pKeyValuesData->GetInt( "AllowFlipping", 1 ) != 0 ) ? true : false; - m_bMeleeWeapon = ( pKeyValuesData->GetInt( "MeleeWeapon", 0 ) != 0 ) ? true : false; - -#if defined(_DEBUG) && defined(HL2_CLIENT_DLL) - // make sure two weapons aren't in the same slot & position - if ( iSlot >= MAX_WEAPON_SLOTS || - iPosition >= MAX_WEAPON_POSITIONS ) - { - Warning( "Invalid weapon slot or position [slot %d/%d max], pos[%d/%d max]\n", - iSlot, MAX_WEAPON_SLOTS - 1, iPosition, MAX_WEAPON_POSITIONS - 1 ); - } - else - { - if (g_bUsedWeaponSlots[iSlot][iPosition]) - { - Warning( "Duplicately assigned weapon slots in selection hud: %s (%d, %d)\n", szPrintName, iSlot, iPosition ); - } - g_bUsedWeaponSlots[iSlot][iPosition] = true; - } -#endif - - // Primary ammo used - const char *pAmmo = pKeyValuesData->GetString( "primary_ammo", "None" ); - if ( strcmp("None", pAmmo) == 0 ) - Q_strncpy( szAmmo1, "", sizeof( szAmmo1 ) ); - else - Q_strncpy( szAmmo1, pAmmo, sizeof( szAmmo1 ) ); - iAmmoType = GetAmmoDef()->Index( szAmmo1 ); - - // Secondary ammo used - pAmmo = pKeyValuesData->GetString( "secondary_ammo", "None" ); - if ( strcmp("None", pAmmo) == 0) - Q_strncpy( szAmmo2, "", sizeof( szAmmo2 ) ); - else - Q_strncpy( szAmmo2, pAmmo, sizeof( szAmmo2 ) ); - iAmmo2Type = GetAmmoDef()->Index( szAmmo2 ); - - // Now read the weapon sounds - memset( aShootSounds, 0, sizeof( aShootSounds ) ); - KeyValues *pSoundData = pKeyValuesData->FindKey( "SoundData" ); - if ( pSoundData ) - { - for ( int i = EMPTY; i < NUM_SHOOT_SOUND_TYPES; i++ ) - { - const char *soundname = pSoundData->GetString( pWeaponSoundCategories[i] ); - if ( soundname && soundname[0] ) - { - Q_strncpy( aShootSounds[i], soundname, MAX_WEAPON_STRING ); - } - } - } -} - diff --git a/game/shared/weapon_parse.h b/game/shared/weapon_parse.h deleted file mode 100644 index 345781531..000000000 --- a/game/shared/weapon_parse.h +++ /dev/null @@ -1,160 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Weapon data file parsing, shared by game & client dlls. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef WEAPON_PARSE_H -#define WEAPON_PARSE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "shareddefs.h" - -class IFileSystem; - -typedef unsigned short WEAPON_FILE_INFO_HANDLE; - -// ----------------------------------------------------------- -// Weapon sound types -// Used to play sounds defined in the weapon's classname.txt file -// This needs to match pWeaponSoundCategories in weapon_parse.cpp -// ------------------------------------------------------------ -typedef enum { - EMPTY, - SINGLE, - SINGLE_NPC, - WPN_DOUBLE, // Can't be "DOUBLE" because windows.h uses it. - DOUBLE_NPC, - BURST, - RELOAD, - RELOAD_NPC, - MELEE_MISS, - MELEE_HIT, - MELEE_HIT_WORLD, - SPECIAL1, - SPECIAL2, - SPECIAL3, - TAUNT, - - // Add new shoot sound types here - - NUM_SHOOT_SOUND_TYPES, -} WeaponSound_t; - -int GetWeaponSoundFromString( const char *pszString ); - -#define MAX_SHOOT_SOUNDS 16 // Maximum number of shoot sounds per shoot type - -#define MAX_WEAPON_STRING 80 -#define MAX_WEAPON_PREFIX 16 -#define MAX_WEAPON_AMMO_NAME 32 - -#define WEAPON_PRINTNAME_MISSING "!!! Missing printname on weapon" - -class CHudTexture; -class KeyValues; - -//----------------------------------------------------------------------------- -// Purpose: Contains the data read from the weapon's script file. -// It's cached so we only read each weapon's script file once. -// Each game provides a CreateWeaponInfo function so it can have game-specific -// data (like CS move speeds) in the weapon script. -//----------------------------------------------------------------------------- -class FileWeaponInfo_t -{ -public: - - FileWeaponInfo_t(); - - // Each game can override this to get whatever values it wants from the script. - virtual void Parse( KeyValues *pKeyValuesData, const char *szWeaponName ); - - -public: - bool bParsedScript; - bool bLoadedHudElements; - -// SHARED - char szClassName[MAX_WEAPON_STRING]; - char szPrintName[MAX_WEAPON_STRING]; // Name for showing in HUD, etc. - - char szViewModel[MAX_WEAPON_STRING]; // View model of this weapon - char szWorldModel[MAX_WEAPON_STRING]; // Model of this weapon seen carried by the player - char szAnimationPrefix[MAX_WEAPON_PREFIX]; // Prefix of the animations that should be used by the player carrying this weapon - int iSlot; // inventory slot. - int iPosition; // position in the inventory slot. - int iMaxClip1; // max primary clip size (-1 if no clip) - int iMaxClip2; // max secondary clip size (-1 if no clip) - int iDefaultClip1; // amount of primary ammo in the gun when it's created - int iDefaultClip2; // amount of secondary ammo in the gun when it's created - int iWeight; // this value used to determine this weapon's importance in autoselection. - int iRumbleEffect; // Which rumble effect to use when fired? (xbox) - bool bAutoSwitchTo; // whether this weapon should be considered for autoswitching to - bool bAutoSwitchFrom; // whether this weapon can be autoswitched away from when picking up another weapon or ammo - int iFlags; // miscellaneous weapon flags - char szAmmo1[MAX_WEAPON_AMMO_NAME]; // "primary" ammo type - char szAmmo2[MAX_WEAPON_AMMO_NAME]; // "secondary" ammo type - - // Sound blocks - char aShootSounds[NUM_SHOOT_SOUND_TYPES][MAX_WEAPON_STRING]; - - int iAmmoType; - int iAmmo2Type; - bool m_bMeleeWeapon; // Melee weapons can always "fire" regardless of ammo. - - // This tells if the weapon was built right-handed (defaults to true). - // This helps cl_righthand make the decision about whether to flip the model or not. - bool m_bBuiltRightHanded; - bool m_bAllowFlipping; // False to disallow flipping the model, regardless of whether - // it is built left or right handed. - -// CLIENT DLL - // Sprite data, read from the data file - int iSpriteCount; - CHudTexture *iconActive; - CHudTexture *iconInactive; - CHudTexture *iconAmmo; - CHudTexture *iconAmmo2; - CHudTexture *iconCrosshair; - CHudTexture *iconAutoaim; - CHudTexture *iconZoomedCrosshair; - CHudTexture *iconZoomedAutoaim; - CHudTexture *iconSmall; - -// TF2 specific - bool bShowUsageHint; // if true, then when you receive the weapon, show a hint about it - -// SERVER DLL - -}; - -// The weapon parse function -bool ReadWeaponDataFromFileForSlot( IFileSystem* filesystem, const char *szWeaponName, - WEAPON_FILE_INFO_HANDLE *phandle, const unsigned char *pICEKey = NULL ); - -// If weapon info has been loaded for the specified class name, this returns it. -WEAPON_FILE_INFO_HANDLE LookupWeaponInfoSlot( const char *name ); - -FileWeaponInfo_t *GetFileWeaponInfoFromHandle( WEAPON_FILE_INFO_HANDLE handle ); -WEAPON_FILE_INFO_HANDLE GetInvalidWeaponInfoHandle( void ); -void PrecacheFileWeaponInfoDatabase( IFileSystem *filesystem, const unsigned char *pICEKey ); - - -// -// Read a possibly-encrypted KeyValues file in. -// If pICEKey is NULL, then it appends .txt to the filename and loads it as an unencrypted file. -// If pICEKey is non-NULL, then it appends .ctx to the filename and loads it as an encrypted file. -// -// (This should be moved into a more appropriate place). -// -KeyValues* ReadEncryptedKVFile( IFileSystem *filesystem, const char *szFilenameWithoutExtension, const unsigned char *pICEKey ); - - -// Each game implements this. It can return a derived class and override Parse() if it wants. -extern FileWeaponInfo_t* CreateWeaponInfo(); - - -#endif // WEAPON_PARSE_H diff --git a/game/shared/weapon_parse_default.cpp b/game/shared/weapon_parse_default.cpp deleted file mode 100644 index 739deb239..000000000 --- a/game/shared/weapon_parse_default.cpp +++ /dev/null @@ -1,20 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "weapon_parse.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// Default implementation for games that don't add custom data to the weapon scripts. -FileWeaponInfo_t* CreateWeaponInfo() -{ - return new FileWeaponInfo_t; -} - - - diff --git a/game/shared/weapon_proficiency.cpp b/game/shared/weapon_proficiency.cpp deleted file mode 100644 index 47a202c10..000000000 --- a/game/shared/weapon_proficiency.cpp +++ /dev/null @@ -1,29 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "weapon_proficiency.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -static const char *g_ProficiencyNames[] = -{ - "Poor", - "Average", - "Good", - "Very Good", - "Perfect" -}; - -const char *GetWeaponProficiencyName( WeaponProficiency_t proficiency ) -{ - COMPILE_TIME_ASSERT( ARRAYSIZE(g_ProficiencyNames) == WEAPON_PROFICIENCY_PERFECT + 1 ); // Hey, update that there table! - - if ( proficiency < 0 || proficiency > WEAPON_PROFICIENCY_PERFECT ) - return "<>"; - return g_ProficiencyNames[proficiency]; -} diff --git a/game/shared/weapon_proficiency.h b/game/shared/weapon_proficiency.h deleted file mode 100644 index 1081bfd40..000000000 --- a/game/shared/weapon_proficiency.h +++ /dev/null @@ -1,32 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef WEAPON_PROFICIENCY_H -#define WEAPON_PROFICIENCY_H - -#if defined( _WIN32 ) -#pragma once -#endif - -struct WeaponProficiencyInfo_t -{ - float spreadscale; - float bias; -}; - -enum WeaponProficiency_t -{ - WEAPON_PROFICIENCY_POOR = 0, - WEAPON_PROFICIENCY_AVERAGE, - WEAPON_PROFICIENCY_GOOD, - WEAPON_PROFICIENCY_VERY_GOOD, - WEAPON_PROFICIENCY_PERFECT, -}; - -const char *GetWeaponProficiencyName( WeaponProficiency_t proficiency ); - - -#endif // WEAPON_PROFICIENCY_H diff --git a/hl2sdk-manifests b/hl2sdk-manifests new file mode 160000 index 000000000..38b4f3670 --- /dev/null +++ b/hl2sdk-manifests @@ -0,0 +1 @@ +Subproject commit 38b4f3670826bbfe7c536ef33ec53f5971d419e2 diff --git a/lib/public/mathlib.lib b/lib/public/mathlib.lib deleted file mode 100644 index 3ea9c623e..000000000 Binary files a/lib/public/mathlib.lib and /dev/null differ diff --git a/lib/public/tier0.lib b/lib/public/tier0.lib deleted file mode 100644 index c9801912f..000000000 Binary files a/lib/public/tier0.lib and /dev/null differ diff --git a/lib/public/tier1.lib b/lib/public/tier1.lib deleted file mode 100644 index 05f528510..000000000 Binary files a/lib/public/tier1.lib and /dev/null differ diff --git a/lib/public/tier2.lib b/lib/public/tier2.lib deleted file mode 100644 index 38c42e7a4..000000000 Binary files a/lib/public/tier2.lib and /dev/null differ diff --git a/lib/public/tier3.lib b/lib/public/tier3.lib deleted file mode 100644 index f1588270b..000000000 Binary files a/lib/public/tier3.lib and /dev/null differ diff --git a/lib/public/vstdlib.lib b/lib/public/vstdlib.lib deleted file mode 100644 index 24f60f590..000000000 Binary files a/lib/public/vstdlib.lib and /dev/null differ diff --git a/linux_sdk/Makefile b/linux_sdk/Makefile deleted file mode 100644 index 3e887a008..000000000 --- a/linux_sdk/Makefile +++ /dev/null @@ -1,125 +0,0 @@ -# -# SDK Makefile for x86 Linux -# -# - -############################################################################# -# Developer configurable items -############################################################################# - -# the name of the mod binary (_i486.so is appended to the end) -NAME=server - -# the location of the vcproj that builds the mod -MOD_PROJ=../dlls/server_scratch-2005.vcproj -# the name of the mod configuration (typically _) -MOD_CONFIG=server_sdk_ReleaseSDKWin32 - -# the directory the base binaries (tier0_i486.so, etc) are located -#GAME_DIR=/home/desktop/steamcmd/steamapps/common/sdk2007/bin -GAME_DIR=./gamedir - -# compiler options (gcc 3.4.1 or above is required) -CC=/usr/bin/gcc -CPLUS=/usr/bin/g++ -CLINK=/usr/bin/gcc -CPP_LIB="/usr/lib/libstdc++.a /usr/lib/libgcc_eh.a" - -# put any compiler flags you want passed here -USER_CFLAGS= - -# link flags for your mod, make sure to include any special libraries here -LDFLAGS="-lm -ldl mathlib_i486.a choreoobjects_i486.a tier1_i486.a $(GAME_DIR)/bin/tier0_i486.so $(GAME_DIR)/bin/vstdlib_i486.so" - -# XERCES 2.6.0 or above ( http://xml.apache.org/xerces-c/ ) is used by the vcproj to makefile converter -# it must be installed before being able to run this makefile -XERCES_INC_DIR=/usr/include -XERCES_LIB_DIR=/usr/lib - - -############################################################################# -# Things below here shouldn't need to be altered -############################################################################# -MAKE=make -AR="ar rvs" - -# the dir we want to put binaries we build into -BUILD_DIR=. -# the place to put object files -BUILD_OBJ_DIR=$(BUILD_DIR)/obj - -# the location of the source code -SOURCE_DIR=.. - -# Locations of static library projects -TIER1_PROJ=../tier1/tier1-2005.vcproj -MATHLIB_PROJ=../mathlib/mathlib-2005.vcproj -CHOREO_PROJ=../choreoobjects/choreoobjects-2005.vcproj - -# the CPU target for the build, must be i486 for now -ARCH=i486 -ARCH_CFLAGS=-mtune=generic -march=i686 -mfpmath=sse -msse -msse2 -m32 -s -pipe - -BASE_CFLAGS=-D_LINUX -DNDEBUG -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Wno-non-virtual-dtor -Wno-invalid-offsetof -SHLIBEXT=so -SHLIBCFLAGS=-fPIC -SHLIBLDFLAGS=-shared -Wl,-Map,$@_map.txt -Wl - -#flags passed to the c compiler -CFLAGS="$(USER_CFLAGS) $(DEFINES) $(ARCH_CFLAGS) $(BASE_CFLAGS) -Usprintf -Ustrncpy -UPROTECTED_THINGS_ENABLE" - -# define list passed to make for the sub makefile -BASE_DEFINES=CC=$(CC) AR=$(AR) CPLUS=$(CPLUS) CPP_LIB=$(CPP_LIB) \ - BUILD_DIR=$(BUILD_DIR) BUILD_OBJ_DIR=$(BUILD_OBJ_DIR) \ - SOURCE_DIR=$(SOURCE_DIR) SHLIBLDFLAGS=$(SHLIBLDFLAGS) SHLIBEXT=$(SHLIBEXT) \ - CLINK=$(CLINK) CFLAGS=$(CFLAGS) LDFLAGS=$(LDFLAGS) \ - ARCH=$(ARCH) GAME_DIR=$(GAME_DIR) MOD_CONFIG=$(MOD_CONFIG) NAME=$(NAME) \ - XERCES_INC_DIR=$(XERCES_INC_DIR) XERCES_LIB_DIR=$(XERCES_LIB_DIR) - -# Project Makefile -MAKE_MOD=Makefile.game -MAKE_VCPM=Makefile.vcpm -MAKE_PLUGIN=Makefile.plugin -MAKE_TIER1=Makefile.tier1 -MAKE_MATH=Makefile.mathlib -MAKE_CHOREO=Makefile.choreoobjects - -all: check vcpm mod - -check: - if [ -z "$(CC)" ]; then echo "Compiler not defined."; exit; fi - if [ ! -d $(BUILD_DIR) ];then mkdir -p $(BUILD_DIR);fi - cd $(BUILD_DIR) - -vcpm: - if [ ! -f "tier0_i486.so" ]; then ln -s $(GAME_DIR)/bin/tier0_i486.so .; fi - if [ ! -f "vstdlib_i486.so" ]; then ln -s $(GAME_DIR)/bin/vstdlib_i486.so .; fi - $(MAKE) -f $(MAKE_VCPM) $(BASE_DEFINES) - -mod: vcpm - if [ ! -f "tier0_i486.so" ]; then ln -s $(GAME_DIR)/bin/tier0_i486.so .; fi - if [ ! -f "vstdlib_i486.so" ]; then ln -s $(GAME_DIR)/bin/vstdlib_i486.so .; fi - ./vcpm $(MOD_PROJ) - $(MAKE) -f $(MAKE_MOD) $(BASE_DEFINES) - -plugin: - if [ ! -f "tier0_i486.so" ]; then ln -s $(GAME_DIR)/bin/tier0_i486.so .; fi - if [ ! -f "vstdlib_i486.so" ]; then ln -s $(GAME_DIR)/bin/vstdlib_i486.so .; fi - $(MAKE) -f $(MAKE_PLUGIN) $(BASE_DEFINES) - -tier1: - $(MAKE) -f $(MAKE_TIER1) $(BASE_DEFINES) - -mathlib: - $(MAKE) -f $(MAKE_MATH) $(BASE_DEFINES) - -choreoobjects: - $(MAKE) -f $(MAKE_CHOREO) $(BASE_DEFINES) - -clean: - $(MAKE) -f $(MAKE_VCPM) $(BASE_DEFINES) clean - $(MAKE) -f $(MAKE_PLUGIN) $(BASE_DEFINES) clean - $(MAKE) -f $(MAKE_MOD) $(BASE_DEFINES) clean - $(MAKE) -f $(MAKE_TIER1) $(BASE_DEFINES) clean - $(MAKE) -f $(MAKE_MATH) $(BASE_DEFINES) clean - $(MAKE) -f $(MAKE_CHOREO) $(BASE_DEFINES) clean diff --git a/linux_sdk/Makefile.HPB_bot2_DebugWin32 b/linux_sdk/Makefile.HPB_bot2_DebugWin32 deleted file mode 100644 index 062f73c92..000000000 --- a/linux_sdk/Makefile.HPB_bot2_DebugWin32 +++ /dev/null @@ -1,70 +0,0 @@ -UTILS_RCBOT2_META_SRC_DIR=../utils/RCBot2_meta -UTILS_RCBOT2_META_OBJ_DIR=obj/$(NAME)_$(ARCH)/us/RCBot2_metmeta - - -INCLUDES=-I../utils/RCBot2_meta/../../public/mathlib -I../utils/RCBot2_meta/../../public -I../utils/RCBot2_meta/../../public/engine -I../utils/RCBot2_meta/../../public/tier0 -I../utils/RCBot2_meta/../../public/tier1 -I../utils/RCBot2_meta/../../dlls -I../utils/RCBot2_meta/../../game_shared -I../utils/RCBot2_meta/../../game/shared -I../utils/RCBot2_meta/../../game/server -I../utils/RCBot2_meta/../../public/game/server -I../utils/RCBot2_meta/../mmsource/public -I../utils/RCBot2_meta/../mmsource/core -I../utils/RCBot2_meta/../mmsource/core/sourcehook -D_DEBUG -DHOMEFOLDER - -UTILS_RCBOT2_META_OBJS= \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_accessclient.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_buttons.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_client.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_commands.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_configfile.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_coop.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_css_bot.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_dod_bot.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_dod_mod.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_events.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_fortress.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_ga.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_ga_ind.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_getprop.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_globals.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_hl1dmsrc.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_hldm_bot.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_kv.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_menu.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_mods.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_mtrand.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_navmesh.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_perceptron.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_profile.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_profiling.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_schedule.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_tf2_points.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_som.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_squads.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_strings.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_task.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_tf2_mod.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_usercmd.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_utility.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_visibles.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_waypoint.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_waypoint_locations.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_waypoint_visibility.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_weapons.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_wpt_dist.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_zombie.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_sigscan.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_cvars.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_plugin_meta.o \ - - - - -all: dirs $(NAME)_$(ARCH).$(SHLIBEXT) - -dirs: - -mkdir -p $(UTILS_RCBOT2_META_OBJ_DIR) - - - - -$(NAME)_$(ARCH).$(SHLIBEXT): $(UTILS_RCBOT2_META_OBJS) - $(CLINK) $(SHLIBLDFLAGS) $(DEBUG) -o $(BUILD_DIR)/$@ $(UTILS_RCBOT2_META_OBJS) $(LDFLAGS) $(CPP_LIB) - -$(UTILS_RCBOT2_META_OBJ_DIR)/%.o: $(UTILS_RCBOT2_META_SRC_DIR)/%.cpp - $(DO_CC) - diff --git a/linux_sdk/Makefile.HPB_bot2_ReleaseWin32 b/linux_sdk/Makefile.HPB_bot2_ReleaseWin32 deleted file mode 100644 index 4ab3632e4..000000000 --- a/linux_sdk/Makefile.HPB_bot2_ReleaseWin32 +++ /dev/null @@ -1,70 +0,0 @@ -UTILS_RCBOT2_META_SRC_DIR=../utils/RCBot2_meta -UTILS_RCBOT2_META_OBJ_DIR=obj/$(NAME)_$(ARCH)/us/RCBot2_metmeta - - -INCLUDES=-I../utils/RCBot2_meta/../../public/mathlib -I../utils/RCBot2_meta/../../public -I../utils/RCBot2_meta/../../public/engine -I../utils/RCBot2_meta/../../public/tier0 -I../utils/RCBot2_meta/../../public/tier1 -I../utils/RCBot2_meta/../../dlls -I../utils/RCBot2_meta/../../game_shared -I../utils/RCBot2_meta/../../game/shared -I../utils/RCBot2_meta/../../game/server -I../utils/RCBot2_meta/../../public/game/server -I../utils/RCBot2_meta/../mmsource/public -I../utils/RCBot2_meta/../mmsource/core -I../utils/RCBot2_meta/../mmsource/core/sourcehook -DNDEBUG -DHOMEFOLDER - -UTILS_RCBOT2_META_OBJS= \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_accessclient.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_buttons.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_client.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_commands.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_configfile.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_coop.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_css_bot.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_dod_bot.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_dod_mod.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_events.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_fortress.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_ga.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_ga_ind.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_getprop.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_globals.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_hl1dmsrc.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_hldm_bot.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_kv.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_menu.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_mods.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_mtrand.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_navmesh.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_perceptron.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_profile.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_profiling.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_schedule.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_tf2_points.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_som.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_squads.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_strings.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_task.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_tf2_mod.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_usercmd.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_utility.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_visibles.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_waypoint.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_waypoint_locations.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_waypoint_visibility.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_weapons.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_wpt_dist.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_zombie.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_sigscan.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_cvars.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_plugin_meta.o \ - - - - -all: dirs $(NAME)_$(ARCH).$(SHLIBEXT) - -dirs: - -mkdir -p $(UTILS_RCBOT2_META_OBJ_DIR) - - - - -$(NAME)_$(ARCH).$(SHLIBEXT): $(UTILS_RCBOT2_META_OBJS) - $(CLINK) $(SHLIBLDFLAGS) $(DEBUG) -o $(BUILD_DIR)/$@ $(UTILS_RCBOT2_META_OBJS) $(LDFLAGS) $(CPP_LIB) - -$(UTILS_RCBOT2_META_OBJ_DIR)/%.o: $(UTILS_RCBOT2_META_SRC_DIR)/%.cpp - $(DO_CC) - diff --git a/linux_sdk/Makefile.HPB_bot2_Release_NonHomeFolderWin32 b/linux_sdk/Makefile.HPB_bot2_Release_NonHomeFolderWin32 deleted file mode 100644 index e8b59cb34..000000000 --- a/linux_sdk/Makefile.HPB_bot2_Release_NonHomeFolderWin32 +++ /dev/null @@ -1,70 +0,0 @@ -UTILS_RCBOT2_META_SRC_DIR=../utils/RCBot2_meta -UTILS_RCBOT2_META_OBJ_DIR=obj/$(NAME)_$(ARCH)/us/RCBot2_metmeta - - -INCLUDES=-I../utils/RCBot2_meta/../../public/mathlib -I../utils/RCBot2_meta/../../public -I../utils/RCBot2_meta/../../public/engine -I../utils/RCBot2_meta/../../public/tier0 -I../utils/RCBot2_meta/../../public/tier1 -I../utils/RCBot2_meta/../../dlls -I../utils/RCBot2_meta/../../game_shared -I../utils/RCBot2_meta/../../game/shared -I../utils/RCBot2_meta/../../game/server -I../utils/RCBot2_meta/../../public/game/server -I../utils/RCBot2_meta/../mmsource/public -I../utils/RCBot2_meta/../mmsource/core -I../utils/RCBot2_meta/../mmsource/core/sourcehook -DNDEBUG - -UTILS_RCBOT2_META_OBJS= \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_accessclient.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_buttons.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_client.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_commands.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_configfile.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_coop.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_css_bot.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_dod_bot.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_dod_mod.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_events.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_fortress.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_ga.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_ga_ind.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_getprop.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_globals.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_hl1dmsrc.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_hldm_bot.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_kv.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_menu.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_mods.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_mtrand.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_navmesh.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_perceptron.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_profile.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_profiling.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_schedule.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_tf2_points.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_som.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_squads.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_strings.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_task.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_tf2_mod.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_usercmd.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_utility.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_visibles.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_waypoint.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_waypoint_locations.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_waypoint_visibility.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_weapons.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_wpt_dist.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_zombie.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_sigscan.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_cvars.o \ - $(UTILS_RCBOT2_META_OBJ_DIR)/bot_plugin_meta.o \ - - - - -all: dirs $(NAME)_$(ARCH).$(SHLIBEXT) - -dirs: - -mkdir -p $(UTILS_RCBOT2_META_OBJ_DIR) - - - - -$(NAME)_$(ARCH).$(SHLIBEXT): $(UTILS_RCBOT2_META_OBJS) - $(CLINK) $(SHLIBLDFLAGS) $(DEBUG) -o $(BUILD_DIR)/$@ $(UTILS_RCBOT2_META_OBJS) $(LDFLAGS) $(CPP_LIB) - -$(UTILS_RCBOT2_META_OBJ_DIR)/%.o: $(UTILS_RCBOT2_META_SRC_DIR)/%.cpp - $(DO_CC) - diff --git a/linux_sdk/Makefile.choreoobjects b/linux_sdk/Makefile.choreoobjects deleted file mode 100644 index d23ab2326..000000000 --- a/linux_sdk/Makefile.choreoobjects +++ /dev/null @@ -1,45 +0,0 @@ -# -# Choreoobjects Static Library Makefile -# - -CHOREOOBJECTS_SRC_DIR=$(SOURCE_DIR)/choreoobjects -GAMESHARED_SRC_DIR=$(SOURCE_DIR)/game_shared -PUBLIC_SRC_DIR=$(SOURCE_DIR)/public -TIER1_PUBLIC_SRC_DIR=$(SOURCE_DIR)/public/tier1 - -CHOREOOBJECTS_OBJ_DIR=$(BUILD_OBJ_DIR)/choreoobjects_$(ARCH) - -# Extension of linux static library -override SHLIBEXT=a - -CFLAGS=$(BASE_CFLAGS) $(ARCH_CFLAGS) -#DEBUG = -g -ggdb -#CFLAGS+= $(DEBUG) - -INCLUDEDIRS=-I$(GAMESHARED_SRC_DIR) -I$(PUBLIC_SRC_DIR) -I$(TIER1_PUBLIC_SRC_DIR) -D_LIB -DCHOREOOBJECTS_STATIC_LIB - -DO_CC=$(CPLUS) $(INCLUDEDIRS) $(CFLAGS) -DARCH=$(ARCH) -o $@ -c $< - -##################################################################### - -CHOREOOBJECTS_OBJS= \ - $(CHOREOOBJECTS_OBJ_DIR)/choreoactor.o \ - $(CHOREOOBJECTS_OBJ_DIR)/choreochannel.o \ - $(CHOREOOBJECTS_OBJ_DIR)/choreoevent.o \ - $(CHOREOOBJECTS_OBJ_DIR)/choreoscene.o \ - -all: dirs choreoobjects_$(ARCH).$(SHLIBEXT) - -dirs: - -mkdir -p $(BUILD_OBJ_DIR) - -mkdir -p $(CHOREOOBJECTS_OBJ_DIR) - $(CHECK_DSP) $(SOURCE_DSP) - -choreoobjects_$(ARCH).$(SHLIBEXT): $(CHOREOOBJECTS_OBJS) - $(AR) $(BUILD_DIR)/$@ $(CHOREOOBJECTS_OBJS) - -$(CHOREOOBJECTS_OBJ_DIR)/%.o: $(CHOREOOBJECTS_SRC_DIR)/%.cpp - $(DO_CC) - -clean: - -rm -rf $(CHOREOOBJECTS_OBJ_DIR) diff --git a/linux_sdk/Makefile.game b/linux_sdk/Makefile.game deleted file mode 100644 index 1d4548029..000000000 --- a/linux_sdk/Makefile.game +++ /dev/null @@ -1,20 +0,0 @@ -# -# wrapper Makefile for auto-generated make files -# -# - -############################################################################# -# PROJECT MAKEFILES -############################################################################# -MAKE_FILE=Makefile.$(MOD_CONFIG) --include $(MAKE_FILE) - -############################################################################# -# The compiler command line for each src code file to compile -############################################################################# -DO_CC=$(CPLUS) $(INCLUDES) $(CFLAGS) -o $@ -c $< - - -clean: - rm -rf obj/$(NAME)_$(ARCH) - rm -f $(NAME)_$(ARCH).$(SHLIBEXT) diff --git a/linux_sdk/Makefile.mathlib b/linux_sdk/Makefile.mathlib deleted file mode 100644 index 7497459c4..000000000 --- a/linux_sdk/Makefile.mathlib +++ /dev/null @@ -1,45 +0,0 @@ -# -# Mathlin Static Library Makefile -# - -MATHLIB_SRC_DIR=$(SOURCE_DIR)/mathlib -PUBLIC_SRC_DIR=$(SOURCE_DIR)/public -MATHLIB_PUBLIC_SRC_DIR=$(SOURCE_DIR)/public/mathlib - -MATHLIB_OBJ_DIR=$(BUILD_OBJ_DIR)/mathlib_$(ARCH) - -# Extension of linux static library -override SHLIBEXT=a - -CFLAGS=$(BASE_CFLAGS) $(ARCH_CFLAGS) -#DEBUG = -g -ggdb -#CFLAGS+= $(DEBUG) - -INCLUDEDIRS=-I$(PUBLIC_SRC_DIR) -I$(MATHLIB_PUBLIC_SRC_DIR) -D_LIB - -DO_CC=$(CPLUS) $(INCLUDEDIRS) $(CFLAGS) -DARCH=$(ARCH) -o $@ -c $< - -##################################################################### - -MATHLIB_OBJS= \ - $(MATHLIB_OBJ_DIR)/halton.o \ - $(MATHLIB_OBJ_DIR)/lightdesc.o \ - $(MATHLIB_OBJ_DIR)/mathlib_base.o \ - $(MATHLIB_OBJ_DIR)/powsse.o \ - $(MATHLIB_OBJ_DIR)/sseconst.o \ - -all: dirs mathlib_$(ARCH).$(SHLIBEXT) - -dirs: - -mkdir -p $(BUILD_OBJ_DIR) - -mkdir -p $(MATHLIB_OBJ_DIR) - $(CHECK_DSP) $(SOURCE_DSP) - -mathlib_$(ARCH).$(SHLIBEXT): $(MATHLIB_OBJS) - $(AR) $(BUILD_DIR)/$@ $(MATHLIB_OBJS) - -$(MATHLIB_OBJ_DIR)/%.o: $(MATHLIB_SRC_DIR)/%.cpp - $(DO_CC) - -clean: - -rm -rf $(MATHLIB_OBJ_DIR) diff --git a/linux_sdk/Makefile.plugin b/linux_sdk/Makefile.plugin deleted file mode 100644 index 74356e01a..000000000 --- a/linux_sdk/Makefile.plugin +++ /dev/null @@ -1,54 +0,0 @@ -# -# Sample server plugin for SRC engine -# -# October 2004, alfred@valvesoftware.com -# - -PLUGIN_SRC_DIR=$(SOURCE_DIR)/utils/serverplugin_sample -PUBLIC_SRC_DIR=$(SOURCE_DIR)/public -TIER0_PUBLIC_SRC_DIR=$(SOURCE_DIR)/public/tier0 -TIER1_PUBLIC_SRC_DIR=$(SOURCE_DIR)/public/tier1 - -PLUGIN_OBJ_DIR=$(BUILD_OBJ_DIR)/plugin -PUBLIC_OBJ_DIR=$(BUILD_OBJ_DIR)/plugin/public -TIER0_OBJ_DIR=$(BUILD_OBJ_DIR)/plugin/tier0 - -CFLAGS=$(BASE_CFLAGS) $(ARCH_CFLAGS) -#DEBUG = -g -ggdb -#CFLAGS+= $(DEBUG) - -INCLUDEDIRS=-I$(PUBLIC_SRC_DIR) -I$(TIER1_PUBLIC_SRC_DIR) -Dstrcmpi=strcasecmp -D_alloca=alloca - -DO_CC=$(CPLUS) $(INCLUDEDIRS) $(CFLAGS) -DARCH=$(ARCH) -o $@ -c $< - -##################################################################### - -PLUGIN_OBJS = \ - $(PLUGIN_OBJ_DIR)/serverplugin_convar.o \ - $(PLUGIN_OBJ_DIR)/serverplugin_empty.o \ - $(PLUGIN_OBJ_DIR)/serverplugin_bot.o \ - -TIER0_OBJS = \ - $(TIER0_OBJ_DIR)/memoverride.o \ - -all: dirs serverplugin_empty_$(ARCH).$(SHLIBEXT) - -dirs: - -mkdir -p $(BUILD_OBJ_DIR) - -mkdir -p $(PLUGIN_OBJ_DIR) - -mkdir -p $(PUBLIC_OBJ_DIR) - -mkdir -p $(TIER0_OBJ_DIR) - $(CHECK_DSP) $(SOURCE_DSP) - -serverplugin_empty_$(ARCH).$(SHLIBEXT): $(PLUGIN_OBJS) $(TIER0_OBJS) - $(CLINK) $(DEBUG) -o $(BUILD_DIR)/$@ $(SHLIBLDFLAGS) $(PLUGIN_OBJS) $(TIER0_OBJS) $(PUBLIC_OBJS) $(CPP_LIB) $(LDFLAGS) $(CPP_LIB) - -$(PLUGIN_OBJ_DIR)/%.o: $(PLUGIN_SRC_DIR)/%.cpp - $(DO_CC) - -$(TIER0_OBJ_DIR)/%.o: $(TIER0_PUBLIC_SRC_DIR)/%.cpp - $(DO_CC) - -clean: - -rm -rf $(PLUGIN_OBJ_DIR) - -rm -f serverplugin_empty_$(ARCH).$(SHLIBEXT) diff --git a/linux_sdk/Makefile.rcbot2 b/linux_sdk/Makefile.rcbot2 deleted file mode 100644 index 5f8cd6a4c..000000000 --- a/linux_sdk/Makefile.rcbot2 +++ /dev/null @@ -1,170 +0,0 @@ -# -# SDK Makefile for x86 Linux -# -# - -############################################################################# -# Developer configurable items -############################################################################# - -# the name of the mod binary (_i486.so is appended to the end) -#NAME=server -#NAME=HPB_bot2_meta -NAME=RCBot2Meta -#NAME=RCBot2MetaDebug - -# the location of the vcproj that builds the mod -#MOD_PROJ=../game/server/server_hl2mp-2005.vcproj -MOD_PROJ=../utils/RCBot2_meta/HPB_Bot2.vcproj - -# the name of the mod configuration (typically _) -#MOD_CONFIG=ServerHL2MP_ReleaseWin32 -MOD_CONFIG=HPB_bot2_Release_NonHomeFolderWin32 -#MOD_CONFIG=HPB_bot2_DebugWin32 - -# the directory the base binaries (tier0_i486.so, etc) are located -# this should point to your orange box subfolder of where you have srcds installed. -#GAME_DIR=/home/desktop/steamcmd/steamapps/common/sdk2007/bin -GAME_DIR=./gamedir - -# the path to your mods directory -# set this so that 'make install' or 'make installrelease' will copy your binary over automatically. -#MOD_DIR=$(GAME_DIR)/SampleMod -MOD_DIR=$(GAME_DIR)/ - -# compiler options (gcc 3.4.1 will work - 4.8 recommended) -#CC=/usr/local/bin/gcc -#CPLUS=/usr/local/bin/g++ -#CLINK=/usr/local/bin/gcc -#CPP_LIB="/usr/lib/gcc/x86_64-linux-gnu/4.8/32/libstdc++.a /usr/lib/gcc/x86_64-linux-gnu/4.8/32/libgcc.a" -#CC=/usr/bin/gcc -#CPLUS=/usr/bin/g++ -#CLINK=/usr/bin/gcc -CPP_LIB="/usr/lib/gcc/i586-linux-gnu/4.8/libstdc++.a /usr/lib/gcc/i586-linux-gnu/4.8/libgcc_eh.a" -CC=/usr/bin/gcc-4.8 -CPLUS=/usr/bin/g++-4.8 -CLINK=/usr/bin/gcc-4.8 -#CPP_LIB="libstdc++.a libgcc_eh.a" - -# GCC 4.2.2 optimization flags, if you're using anything below, don't use these! -#OPTFLAGS=-O1 -fomit-frame-pointer -ffast-math -fforce-addr -funroll-loops -fthread-jumps -fcrossjumping -foptimize-sibling-calls -fcse-follow-jumps -fcse-skip-blocks -fgcse -fgcse-lm -fexpensive-optimizations -frerun-cse-after-loop -fcaller-saves -fpeephole2 -fschedule-insns2 -fsched-interblock -fsched-spec -fregmove -fstrict-overflow -fdelete-null-pointer-checks -freorder-blocks -freorder-functions -falign-functions -falign-jumps -falign-loops -falign-labels -ftree-vrp -ftree-pre -finline-functions -funswitch-loops -fgcse-after-reload - -OPTFLAGS=-O1 -fomit-frame-pointer -fforce-addr -fthread-jumps -fcrossjumping -foptimize-sibling-calls -fcse-follow-jumps -fcse-skip-blocks -fgcse -fgcse-lm -frerun-cse-after-loop -fcaller-saves -fpeephole2 -fschedule-insns2 -fsched-interblock -fsched-spec -fregmove -fdelete-null-pointer-checks -freorder-blocks -freorder-functions -falign-functions -falign-jumps -falign-loops -falign-labels -ftree-vrp -ftree-pre -finline-functions -funswitch-loops -fgcse-after-reload -funsafe-math-optimizations - -# put any compiler flags you want passed here -USER_CFLAGS= -std=c++11 -w -D__linux# -g -D_DEBUG -DDEBUG -DSH_DEBUG# -DTF2_HOOKS - -# Link Libraries -#LIBFILES= \ -# $(LIB_DIR)/lib/linux/tier1_486.a \ -# $(LIB_DIR)/lib/linux/choreoobjects_486.a \ -# $(LIB_DIR)/lib/linux/particles_486.a \ -# $(LIB_DIR)/lib/linux/dmxloader_486.a \ -# libtier0.so \ -# libvstdlib.so \ -# libsteam_api.so \ -# $(LIB_DIR)/lib/linux/tier3_486.a \ -# $(LIB_DIR)/lib/linux/tier2_486.a \ -# $(LIB_DIR)/lib/linux/tier1_486.a \ -# $(LIB_DIR)/lib/linux/mathlib_486.a \ - - -# link flags for your mod, make sure to include any special libraries here -#NOTE: YES we want to include the lib files 2 times. We've run into problems with the 1-pass linker not bringing in symbols it should. -#LDFLAGS="-lm -ldl $(LIBFILES) $(LIBFILES)" -LIB_DIR = $(SOURCE_DIR)/lib/linux -#LDFLAGS = "-m32 -lm -ldl $(LIB_DIR)/mathlib_i486.a libtier0.so libvstdlib.so $(LIB_DIR)/tier1_i486.a $(LIB_DIR)/tier2_i486.a $(LIB_DIR)/tier3_i486.a " -LDFLAGS = "-m32 -lm -ldl -Wl,-no-undefined -L. -L$(LIB_DIR) -Wl,-soname -Wl,--no-as-needed -l:mathlib_i486.a -l:libtier0_srv.so -l:tier1_i486.a -l:tier2_i486.a -l:tier3_i486.a -l:libvstdlib_srv.so -lpthread" - -# XERCES 2.6.0 or above ( [url=http://xml.apache.org/xerces-c/]http://xml.apache.org/xerces-c/[/url] ) is used by the vcproj to makefile converter -# it must be installed before being able to run this makefile -# if you have xerces installed already you should be able to use the two lines below -#XERCES_INC_DIR=/usr/include -#XERCES_LIB_DIR=/usr/lib -XERCES_INC_DIR=/opt/include -XERCES_LIB_DIR=/opt/lib - -############################################################################# -# Things below here shouldn't need to be altered -############################################################################# -MAKE=make - -# the dir we want to put binaries we build into -BUILD_DIR=. -# the place to put object files -BUILD_OBJ_DIR=$(BUILD_DIR)/obj - -# the location of the source code -SOURCE_DIR=.. -SRC_DIR=~/Documents/rcbot-svn/rcbot2-code-468 - -# the CPU target for the build, must be i486 for now -ARCH=i486 -ARCH_CFLAGS=-mtune=generic -march=i686 -mfpmath=sse -msse -msse2 -m32 -s -pipe - -# -fpermissive is so gcc 3.4.x doesn't complain about some template stuff -BASE_CFLAGS=-DVPROF_LEVEL=1 -DSWDS -D_LINUX -DLINUX -DNDEBUG -fpermissive -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -D__linux__ -DSOURCE_ENGINE=4 -DSE_EPISODEONE=1 -DSE_DARKMESSIAH=2 -DSE_ORANGEBOX=3 -DSE_ORANGEBOXVALVE=4 -DSE_LEFT4DEAD=5 -DSE_LEFT4DEAD2=6 -DSE_ALIENSWARM=7 - -SHLIBEXT=so - -SHLIBCFLAGS=-fPIC -SHLIBLDFLAGS=-shared -Wl,-Map,$@_map.txt -Wl - -#flags passed to the compiler -CFLAGS="$(USER_CFLAGS) $(DEFINES) $(ARCH_CFLAGS) $(OPTFLAGS) $(BASE_CFLAGS) -Usprintf=use_Q_snprintf_instead_of_sprintf -Ustrncpy=use_Q_strncpy_instead -Ufopen=dont_use_fopen -UPROTECTED_THINGS_ENABLE" - -# define list passed to make for the sub makefile -BASE_DEFINES=CC=$(CC) CPLUS=$(CPLUS) CPP_LIB=$(CPP_LIB) \ - BUILD_DIR=$(BUILD_DIR) BUILD_OBJ_DIR=$(BUILD_OBJ_DIR) \ - SRC_DIR=$(SRC_DIR) SHLIBLDFLAGS=$(SHLIBLDFLAGS) SHLIBEXT=$(SHLIBEXT) \ - CLINK=$(CLINK) CFLAGS=$(CFLAGS) LDFLAGS=$(LDFLAGS) DBG_CFLAGS=$(CFLAGS) \ - ARCH=$(ARCH) GAME_DIR=$(GAME_DIR) MOD_CONFIG=$(MOD_CONFIG) NAME=$(NAME) \ - XERCES_INC_DIR=$(XERCES_INC_DIR) XERCES_LIB_DIR=$(XERCES_LIB_DIR) SOURCE_DIR=$(SOURCE_DIR) - -# Project Makefile -MAKE_MOD=Makefile.server -MAKE_VCPM=Makefile.vcpm -MAKE_PLUGIN=Makefile.plugin - -all: check vcpm server - -check: - if [ -z "$(CC)" ]; then echo "Compiler not defined."; exit; fi - if [ ! -d $(BUILD_DIR) ];then mkdir $(BUILD_DIR);fi - cd $(BUILD_DIR) - -vcpm: - $(MAKE) -f $(MAKE_VCPM) $(BASE_DEFINES) - -server: vcpm - # if [ ! -f "libtier0.so" ]; then ln -s $(GAME_DIR)/bin/libtier0.so .; fi - # if [ ! -f "libvstdlib.so" ]; then ln -s $(GAME_DIR)/bin/libvstdlib.so .; fi - - # if [ ! -f "libsteam_api.so" ]; then ln -s $(GAME_DIR)/bin/libsteam_api.so .; fi - # When running over samba we need to copy the files because symlinking isn't possible. - # cp -f $(GAME_DIR)/bin/tier0_i486.so . - # cp -f $(GAME_DIR)/bin/vstdlib_i486.so . - # cp -f $(GAME_DIR)/bin/steam_api_i486.so . - - $(MAKE) -f $(MAKE_MOD) $(BASE_DEFINES) - -genmf: - ./vcpm $(MOD_PROJ) - -plugin: - $(MAKE) -f $(MAKE_PLUGIN) $(BASE_DEFINES) - -clean: - $(MAKE) -f $(MAKE_PLUGIN) $(BASE_DEFINES) clean - $(MAKE) -f $(MAKE_MOD) $(BASE_DEFINES) clean - -cleanvcpm: - $(MAKE) -f $(MAKE_VCPM) $(BASE_DEFINES) clean - -install: - cp -f $(NAME)_$(ARCH).so $(MOD_DIR)/bin/$(NAME)_$(ARCH).so - -installrelease: - cp -f $(NAME)_$(ARCH).so $(MOD_DIR)/bin/$(NAME)_$(ARCH).so - strip $(MOD_DIR)/bin/$(NAME)_$(ARCH).so - diff --git a/linux_sdk/Makefile.server b/linux_sdk/Makefile.server deleted file mode 100644 index fe613f383..000000000 --- a/linux_sdk/Makefile.server +++ /dev/null @@ -1,28 +0,0 @@ -# -# wrapper Makefile for auto-generated make files -# -# - -############################################################################# -# PROJECT MAKEFILES -############################################################################# -MAKE_FILE = Makefile.$(MOD_CONFIG) --include $(MAKE_FILE) - -############################################################################# -# The compiler command line for each src code file to compile -############################################################################# -DO_CC = $(CPLUS) $(INCLUDES) -DARCH=$(ARCH) - -ifeq (_DEBUG,$(findstring _DEBUG,$(CFLAGS))) - DO_CC += $(DEFINES) $(DBG_CFLAGS) -else - DO_CC += $(CFLAGS) -endif - -DO_CC += -o $@ -c $< - -clean: - rm -rf obj/$(NAME)_$(ARCH) - rm -f $(NAME)_$(ARCH).$(SHLIBEXT) - diff --git a/linux_sdk/Makefile.tier1 b/linux_sdk/Makefile.tier1 deleted file mode 100644 index fdfc91f10..000000000 --- a/linux_sdk/Makefile.tier1 +++ /dev/null @@ -1,66 +0,0 @@ -# -# Tier1 Static Library Makefile -# - -TIER1_SRC_DIR=$(SOURCE_DIR)/tier1 -COMMON_SRC_DIR=$(SOURCE_DIR)/common -PUBLIC_SRC_DIR=$(SOURCE_DIR)/public -TIER1_PUBLIC_SRC_DIR=$(SOURCE_DIR)/public/tier1 - -TIER1_OBJ_DIR=$(BUILD_OBJ_DIR)/tier1_$(ARCH) - -# Extension of linux static library -override SHLIBEXT=a - -CFLAGS=$(BASE_CFLAGS) $(ARCH_CFLAGS) -#DEBUG = -g -ggdb -#CFLAGS+= $(DEBUG) - -INCLUDEDIRS=-I$(COMMON_SRC_DIR) -I$(PUBLIC_SRC_DIR) -I$(TIER1_PUBLIC_SRC_DIR) -D_LIB -DTIER1_STATIC_LIB - -DO_CC=$(CPLUS) $(INCLUDEDIRS) $(CFLAGS) -DARCH=$(ARCH) -o $@ -c $< - -##################################################################### - -TIER1_OBJS= \ - $(TIER1_OBJ_DIR)/bitbuf.o \ - $(TIER1_OBJ_DIR)/byteswap.o \ - $(TIER1_OBJ_DIR)/characterset.o \ - $(TIER1_OBJ_DIR)/checksum_crc.o \ - $(TIER1_OBJ_DIR)/checksum_md5.o \ - $(TIER1_OBJ_DIR)/convar.o \ - $(TIER1_OBJ_DIR)/datamanager.o \ - $(TIER1_OBJ_DIR)/diff.o \ - $(TIER1_OBJ_DIR)/generichash.o \ - $(TIER1_OBJ_DIR)/interface.o \ - $(TIER1_OBJ_DIR)/jobthread.o \ - $(TIER1_OBJ_DIR)/KeyValues.o \ - $(TIER1_OBJ_DIR)/mempool.o \ - $(TIER1_OBJ_DIR)/memstack.o \ - $(TIER1_OBJ_DIR)/NetAdr.o \ - $(TIER1_OBJ_DIR)/processor_detect.o \ - $(TIER1_OBJ_DIR)/rangecheckedvar.o \ - $(TIER1_OBJ_DIR)/stringpool.o \ - $(TIER1_OBJ_DIR)/strtools.o \ - $(TIER1_OBJ_DIR)/tier1.o \ - $(TIER1_OBJ_DIR)/tokenreader.o \ - $(TIER1_OBJ_DIR)/utlbuffer.o \ - $(TIER1_OBJ_DIR)/utlstring.o \ - $(TIER1_OBJ_DIR)/utlsymbol.o \ - $(TIER1_OBJ_DIR)/xboxstubs.o \ - -all: dirs tier1_$(ARCH).$(SHLIBEXT) - -dirs: - -mkdir -p $(BUILD_OBJ_DIR) - -mkdir -p $(TIER1_OBJ_DIR) - $(CHECK_DSP) $(SOURCE_DSP) - -tier1_$(ARCH).$(SHLIBEXT): $(TIER1_OBJS) - $(AR) $(BUILD_DIR)/$@ $(TIER1_OBJS) - -$(TIER1_OBJ_DIR)/%.o: $(TIER1_SRC_DIR)/%.cpp - $(DO_CC) - -clean: - -rm -rf $(TIER1_OBJ_DIR) diff --git a/linux_sdk/Makefile.vcpm b/linux_sdk/Makefile.vcpm deleted file mode 100644 index 2612bde6a..000000000 --- a/linux_sdk/Makefile.vcpm +++ /dev/null @@ -1,77 +0,0 @@ -# -# VCProject file to Makefile converter -# -# November 2004, alfred@valvesoftware.com -# -# ADAPTED TO SUPPORT VS2010 BY KILLERMONKEY -# 24 APR 2010 - -VCPM_SRC_DIR=$(SOURCE_DIR)/utils/vprojtomake -UTIL_COMMON_SRC_DIR=$(SOURCE_DIR)/utils/common -TIER0_PUBLIC_SRC_DIR=$(SOURCE_DIR)/public/tier0 -TIER1_PUBLIC_SRC_DIR=$(SOURCE_DIR)/public/tier1 -PUBLIC_SRC_DIR=$(SOURCE_DIR)/public -TIER1_SRC_DIR=$(SOURCE_DIR)/tier1 -TINYXML_SRC_DIR=$(SOURCE_DIR)/utils/vprojtomake/tinyxml - -VCPM_OBJ_DIR=$(BUILD_OBJ_DIR)/vcpm -TIER1_OBJ_DIR=$(BUILD_OBJ_DIR)/vcpm/public -TIER0_OBJ_DIR=$(BUILD_OBJ_DIR)/vcpm/public -TINYXML_OBJ_DIR=$(BUILD_OBJ_DIR)/vcpm/tinyxml - -CFLAGS= -m32 -w -fpermissive -D_LINUX -DNDEBUG -U_DEBUG $(ARCH_CFLAGS) - -INCLUDEDIRS=-I$(PUBLIC_SRC_DIR) -I$(UTIL_COMMON_SRC_DIR) -I$(TIER1_PUBLIC_SRC_DIR) -I$(TIER0_PUBLIC_SRC_DIR) -I$(TINYXML_SRC_DIR) -LDFLAGS_VC= -m32 -lpthread -lm -ldl -Wl,-rpath . libtier0_srv.so libvstdlib_srv.so -Wl,-rpath-link . - -DO_CC=$(CPLUS) $(INCLUDEDIRS) -w $(CFLAGS) -U_DEBUG -DARCH=$(ARCH) -o $@ -c $< -DEBUG= - -##################################################################### - -VCPM_OBJS = \ - $(VCPM_OBJ_DIR)/makefilecreator.o \ - $(VCPM_OBJ_DIR)/vprojtomake.o \ - $(VCPM_OBJ_DIR)/vcprojconvert.o \ - -TIER1_OBJS = \ - $(TIER1_OBJ_DIR)/characterset.o \ - $(TIER1_OBJ_DIR)/interface.o \ - $(TIER1_OBJ_DIR)/generichash.o \ - $(TIER1_OBJ_DIR)/KeyValues.o \ - $(TIER1_OBJ_DIR)/stringpool.o \ - $(TIER1_OBJ_DIR)/utlbuffer.o \ - $(TIER1_OBJ_DIR)/utlsymbol.o \ - $(TIER1_OBJ_DIR)/strtools.o \ - -TINYXML_OBJS = \ - $(TINYXML_OBJ_DIR)/tinyxml.o \ - $(TINYXML_OBJ_DIR)/tinyxmlerror.o \ - $(TINYXML_OBJ_DIR)/tinyxmlparser.o \ - $(TINYXML_OBJ_DIR)/tinystr.o \ - - -all: dirs vcpm - -dirs: - -mkdir $(BUILD_OBJ_DIR) - -mkdir $(VCPM_OBJ_DIR) - -mkdir $(TIER1_OBJ_DIR) - -mkdir $(TIER0_OBJ_DIR) - -mkdir $(TINYXML_OBJ_DIR) - -vcpm: $(VCPM_OBJS) $(TIER1_OBJS) $(TINYXML_OBJS) - $(CLINK) $(DEBUG) -o $(BUILD_DIR)/$@ $(VCPM_OBJS) $(TIER1_OBJS) $(TINYXML_OBJS) $(CPP_LIB) $(LDFLAGS_VC) - -$(VCPM_OBJ_DIR)/%.o: $(VCPM_SRC_DIR)/%.cpp - $(DO_CC) - -$(TIER1_OBJ_DIR)/%.o: $(TIER1_SRC_DIR)/%.cpp - $(DO_CC) - -$(TINYXML_OBJ_DIR)/%.o: $(TINYXML_SRC_DIR)/%.cpp - $(DO_CC) - -clean: - -rm -rf $(VCPM_OBJ_DIR) - -rm -f vcpm diff --git a/linux_sdk/choreoobjects_i486.a b/linux_sdk/choreoobjects_i486.a deleted file mode 100644 index fb4b1e41b..000000000 Binary files a/linux_sdk/choreoobjects_i486.a and /dev/null differ diff --git "a/linux_sdk/compile.log\357\200\215" "b/linux_sdk/compile.log\357\200\215" deleted file mode 100644 index a3549f7a7..000000000 --- "a/linux_sdk/compile.log\357\200\215" +++ /dev/null @@ -1,138 +0,0 @@ -make: 'vcpm' is up to date. -./vcpm ../utils/RCBot2_meta/HPB_Bot2.vcproj -Valve Software - vcprojtomake.exe (Jul 24 2018) -Modified for VS2010 Support by Killer Monkey - -.\bot.cpp -.\bot_accessclient.cpp -.\bot_buttons.cpp -.\bot_client.cpp -.\bot_commands.cpp -.\bot_configfile.cpp -.\bot_coop.cpp -.\bot_css_bot.cpp -.\bot_dod_bot.cpp -.\bot_dod_mod.cpp -.\bot_events.cpp -.\bot_fortress.cpp -.\bot_ga.cpp -.\bot_ga_ind.cpp -.\bot_getprop.cpp -.\bot_globals.cpp -.\bot_hl1dmsrc.cpp -.\bot_hldm_bot.cpp -.\bot_kv.cpp -.\bot_menu.cpp -.\bot_mods.cpp -.\bot_mtrand.cpp -.\bot_navmesh.cpp -.\bot_perceptron.cpp -.\bot_profile.cpp -.\bot_profiling.cpp -.\bot_schedule.cpp -.\bot_tf2_points.cpp -.\bot_som.cpp -.\bot_squads.cpp -.\bot_strings.cpp -.\bot_task.cpp -.\bot_tf2_mod.cpp -.\bot_usercmd.cpp -.\bot_utility.cpp -.\bot_visibles.cpp -.\bot_waypoint.cpp -.\bot_waypoint_locations.cpp -.\bot_waypoint_visibility.cpp -.\bot_weapons.cpp -.\bot_wpt_dist.cpp -.\bot_zombie.cpp -.\bot_sigscan.cpp -.\bot_cvars.cpp -.\bot_plugin_meta.cpp -.\bot.h -.\bot_accessclient.h -.\bot_belief.h -.\bot_buttons.h -.\bot_client.h -.\bot_commands.h -.\bot_config.h -.\bot_configfile.h -.\bot_const.h -.\bot_coop.h -.\bot_css_bot.h -.\bot_dod_bot.h -.\bot_ehandle.h -.\bot_event.h -.\bot_fortress.h -.\bot_ga.h -.\bot_ga_ind.h -.\bot_genclass.h -.\bot_getprop.h -.\bot_globals.h -.\bot_hl1dmsrc_bot.h -.\bot_hldm_bot.h -.\bot_kv.h -.\bot_menu.h -.\bot_mods.h -.\bot_mtrand.h -.\bot_navigator.h -.\bot_perceptron.h -.\bot_profile.h -.\bot_profiling.h -.\bot_rb.h -.\bot_recipients.h -.\bot_schedule.h -.\bot_tf2_points.h -.\bot_som.h -.\bot_squads.h -.\bot_strings.h -.\bot_task.h -.\bot_utility.h -.\bot_visibles.h -.\bot_waypoint.h -.\bot_waypoint_locations.h -.\bot_waypoint_visibility.h -.\bot_weapons.h -.\bot_wpt_color.h -.\bot_wpt_dist.h -.\bot_zombie.h -..\..\public\Color.h -..\..\public\const.h -..\..\public\tier0\dbg.h -..\..\public\dt_send.h -..\..\Public\eiface.h -..\..\Public\FileSystem.h -..\..\public\tier0\icommandline.h -..\..\public\icvar.h -..\..\public\igameevents.h -..\..\public\tier1\interface.h -..\..\public\game\server\iplayerinfo.h -..\..\public\engine\iserverplugin.h -..\..\public\tier1\KeyValues.h -..\..\public\mathlib\mathlib.h -..\..\public\tier0\mem.h -..\..\public\tier0\memalloc.h -..\..\public\tier0\memdbgon.h -..\..\public\server_class.h -..\..\public\tier1\strtools.h -..\..\public\tier1\utlbuffer.h -..\..\public\tier1\utlmemory.h -..\..\public\tier1\utlvector.h -..\..\public\mathlib\vector.h -..\..\public\vstdlib\vstdlib.h -.\update.txt -if [ -z "/usr/bin/gcc-4.8" ]; then echo "Compiler not defined."; exit; fi -# if [ ! -f "libtier0.so" ]; then ln -s ./gamedir/bin/libtier0.so .; fi -if [ ! -d . ];then mkdir .;fi -# if [ ! -f "libvstdlib.so" ]; then ln -s ./gamedir/bin/libvstdlib.so .; fi -cd . -# if [ ! -f "libsteam_api.so" ]; then ln -s ./gamedir/bin/libsteam_api.so .; fi -# When running over samba we need to copy the files because symlinking isn't possible. -# cp -f ./gamedir/bin/tier0_i486.so . -# cp -f ./gamedir/bin/vstdlib_i486.so . -# cp -f ./gamedir/bin/steam_api_i486.so . -make -f Makefile.server CC=/usr/bin/gcc-4.8 CPLUS=/usr/bin/g++-4.8 CPP_LIB="/usr/lib/gcc/i586-linux-gnu/4.8/libstdc++.a /usr/lib/gcc/i586-linux-gnu/4.8/libgcc_eh.a" BUILD_DIR=. BUILD_OBJ_DIR=./obj SRC_DIR=~/Documents/rcbot-svn/rcbot2-code-468 SHLIBLDFLAGS=-shared -Wl,-Map,server_map.txt -Wl SHLIBEXT=so CLINK=/usr/bin/gcc-4.8 CFLAGS="-std=c++11 -w -D__linux -mtune=generic -march=i686 -mfpmath=sse -msse -msse2 -m32 -s -pipe -O1 -fomit-frame-pointer -fforce-addr -fthread-jumps -fcrossjumping -foptimize-sibling-calls -fcse-follow-jumps -fcse-skip-blocks -fgcse -fgcse-lm -frerun-cse-after-loop -fcaller-saves -fpeephole2 -fschedule-insns2 -fsched-interblock -fsched-spec -fregmove -fdelete-null-pointer-checks -freorder-blocks -freorder-functions -falign-functions -falign-jumps -falign-loops -falign-labels -ftree-vrp -ftree-pre -finline-functions -funswitch-loops -fgcse-after-reload -funsafe-math-optimizations -DVPROF_LEVEL=1 -DSWDS -D_LINUX -DLINUX -DNDEBUG -fpermissive -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -D__linux__ -DSOURCE_ENGINE=4 -DSE_EPISODEONE=1 -DSE_DARKMESSIAH=2 -DSE_ORANGEBOX=3 -DSE_ORANGEBOXVALVE=4 -DSE_LEFT4DEAD=5 -DSE_LEFT4DEAD2=6 -DSE_ALIENSWARM=7 -Usprintf=use_Q_snprintf_instead_of_sprintf -Ustrncpy=use_Q_strncpy_instead -Ufopen=dont_use_fopen -UPROTECTED_THINGS_ENABLE" LDFLAGS="-m32 -lm -ldl -Wl,-no-undefined -L. -L../lib/linux -Wl,-soname -Wl,--no-as-needed -l:mathlib_i486.a -l:libtier0_srv.so -l:tier1_i486.a -l:tier2_i486.a -l:tier3_i486.a -l:libvstdlib_srv.so -lpthread" DBG_CFLAGS="-std=c++11 -w -D__linux -mtune=generic -march=i686 -mfpmath=sse -msse -msse2 -m32 -s -pipe -O1 -fomit-frame-pointer -fforce-addr -fthread-jumps -fcrossjumping -foptimize-sibling-calls -fcse-follow-jumps -fcse-skip-blocks -fgcse -fgcse-lm -frerun-cse-after-loop -fcaller-saves -fpeephole2 -fschedule-insns2 -fsched-interblock -fsched-spec -fregmove -fdelete-null-pointer-checks -freorder-blocks -freorder-functions -falign-functions -falign-jumps -falign-loops -falign-labels -ftree-vrp -ftree-pre -finline-functions -funswitch-loops -fgcse-after-reload -funsafe-math-optimizations -DVPROF_LEVEL=1 -DSWDS -D_LINUX -DLINUX -DNDEBUG -fpermissive -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -D__linux__ -DSOURCE_ENGINE=4 -DSE_EPISODEONE=1 -DSE_DARKMESSIAH=2 -DSE_ORANGEBOX=3 -DSE_ORANGEBOXVALVE=4 -DSE_LEFT4DEAD=5 -DSE_LEFT4DEAD2=6 -DSE_ALIENSWARM=7 -Usprintf=use_Q_snprintf_instead_of_sprintf -Ustrncpy=use_Q_strncpy_instead -Ufopen=dont_use_fopen -UPROTECTED_THINGS_ENABLE" ARCH=i486 GAME_DIR=./gamedir MOD_CONFIG=HPB_bot2_Release_NonHomeFolderWin32 NAME=RCBot2Meta XERCES_INC_DIR=/opt/include XERCES_LIB_DIR=/opt/lib SOURCE_DIR=.. -make[1]: Entering directory '/mnt/d/Projects/tf2_server_files/cheeseh_rcbot2_repo/linux_sdk' -mkdir -p obj/RCBot2Meta_i486/us/RCBot2_metmeta -/usr/bin/g++-4.8 -I../utils/RCBot2_meta/../../public/mathlib -I../utils/RCBot2_meta/../../public -I../utils/RCBot2_meta/../../public/engine -I../utils/RCBot2_meta/../../public/tier0 -I../utils/RCBot2_meta/../../public/tier1 -I../utils/RCBot2_meta/../../dlls -I../utils/RCBot2_meta/../../game_shared -I../utils/RCBot2_meta/../../game/shared -I../utils/RCBot2_meta/../../game/server -I../utils/RCBot2_meta/../../public/game/server -I../utils/RCBot2_meta/../mmsource/public -I../utils/RCBot2_meta/../mmsource/core -I../utils/RCBot2_meta/../mmsource/core/sourcehook -DNDEBUG -DARCH=i486 -std=c++11 -w -D__linux -mtune=generic -march=i686 -mfpmath=sse -msse -msse2 -m32 -s -pipe -O1 -fomit-frame-pointer -fforce-addr -fthread-jumps -fcrossjumping -foptimize-sibling-calls -fcse-follow-jumps -fcse-skip-blocks -fgcse -fgcse-lm -frerun-cse-after-loop -fcaller-saves -fpeephole2 -fschedule-insns2 -fsched-interblock -fsched-spec -fregmove -fdelete-null-pointer-checks -freorder-blocks -freorder-functions -falign-functions -falign-jumps -falign-loops -falign-labels -ftree-vrp -ftree-pre -finline-functions -funswitch-loops -fgcse-after-reload -funsafe-math-optimizations -DVPROF_LEVEL=1 -DSWDS -D_LINUX -DLINUX -DNDEBUG -fpermissive -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -D__linux__ -DSOURCE_ENGINE=4 -DSE_EPISODEONE=1 -DSE_DARKMESSIAH=2 -DSE_ORANGEBOX=3 -DSE_ORANGEBOXVALVE=4 -DSE_LEFT4DEAD=5 -DSE_LEFT4DEAD2=6 -DSE_ALIENSWARM=7 -Usprintf=use_Q_snprintf_instead_of_sprintf -Ustrncpy=use_Q_strncpy_instead -Ufopen=dont_use_fopen -UPROTECTED_THINGS_ENABLE -o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_fortress.o -c ../utils/RCBot2_meta/bot_fortress.cpp -/usr/bin/gcc-4.8 -shared -o ./RCBot2Meta_i486.so obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_accessclient.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_buttons.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_client.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_commands.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_configfile.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_coop.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_css_bot.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_dod_bot.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_dod_mod.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_events.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_fortress.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_ga.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_ga_ind.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_getprop.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_globals.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_hl1dmsrc.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_hldm_bot.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_kv.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_menu.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_mods.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_mtrand.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_navmesh.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_perceptron.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_profile.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_profiling.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_schedule.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_tf2_points.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_som.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_squads.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_strings.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_task.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_tf2_mod.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_usercmd.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_utility.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_visibles.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_waypoint.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_waypoint_locations.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_waypoint_visibility.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_weapons.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_wpt_dist.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_zombie.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_sigscan.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_cvars.o obj/RCBot2Meta_i486/us/RCBot2_metmeta/bot_plugin_meta.o -m32 -lm -ldl -Wl,-no-undefined -L. -L../lib/linux -Wl,-soname -Wl,--no-as-needed -l:mathlib_i486.a -l:libtier0_srv.so -l:tier1_i486.a -l:tier2_i486.a -l:tier3_i486.a -l:libvstdlib_srv.so -lpthread /usr/lib/gcc/i586-linux-gnu/4.8/libstdc++.a /usr/lib/gcc/i586-linux-gnu/4.8/libgcc_eh.a -make[1]: Leaving directory '/mnt/d/Projects/tf2_server_files/cheeseh_rcbot2_repo/linux_sdk' diff --git a/linux_sdk/compile.sh b/linux_sdk/compile.sh deleted file mode 100644 index 07879528a..000000000 --- a/linux_sdk/compile.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -echo "make -f Makefile.rcbot2 vcpm" -make -f Makefile.rcbot2 vcpm > compile.log - -echo "" -echo "make -f Makefile.rcbot2 genmf" -make -f Makefile.rcbot2 genmf >> compile.log - -echo "" -echo "make -f Makefile.rcbot2 all -j4" -make -f Makefile.rcbot2 all -j4 >> compile.log - -echo "Done. Check compile.log" diff --git a/linux_sdk/dmxloader_i486.a b/linux_sdk/dmxloader_i486.a deleted file mode 100644 index fc164e017..000000000 Binary files a/linux_sdk/dmxloader_i486.a and /dev/null differ diff --git a/linux_sdk/files.vdf b/linux_sdk/files.vdf deleted file mode 100644 index 724a1bc76..000000000 --- a/linux_sdk/files.vdf +++ /dev/null @@ -1,147 +0,0 @@ -"project" -{ - "Debug|Win32" - { - "0" "bot.cpp" - "1" "bot_accessclient.cpp" - "2" "bot_buttons.cpp" - "3" "bot_client.cpp" - "4" "bot_commands.cpp" - "5" "bot_configfile.cpp" - "6" "bot_coop.cpp" - "7" "bot_css_bot.cpp" - "8" "bot_dod_bot.cpp" - "9" "bot_dod_mod.cpp" - "10" "bot_events.cpp" - "11" "bot_fortress.cpp" - "12" "bot_ga.cpp" - "13" "bot_ga_ind.cpp" - "14" "bot_getprop.cpp" - "15" "bot_globals.cpp" - "16" "bot_hl1dmsrc.cpp" - "17" "bot_hldm_bot.cpp" - "18" "bot_kv.cpp" - "19" "bot_menu.cpp" - "20" "bot_mods.cpp" - "21" "bot_mtrand.cpp" - "22" "bot_navmesh.cpp" - "23" "bot_perceptron.cpp" - "24" "bot_profile.cpp" - "25" "bot_profiling.cpp" - "26" "bot_schedule.cpp" - "27" "bot_tf2_points.cpp" - "28" "bot_som.cpp" - "29" "bot_squads.cpp" - "30" "bot_strings.cpp" - "31" "bot_task.cpp" - "32" "bot_tf2_mod.cpp" - "33" "bot_usercmd.cpp" - "34" "bot_utility.cpp" - "35" "bot_visibles.cpp" - "36" "bot_waypoint.cpp" - "37" "bot_waypoint_locations.cpp" - "38" "bot_waypoint_visibility.cpp" - "39" "bot_weapons.cpp" - "40" "bot_wpt_dist.cpp" - "41" "bot_zombie.cpp" - "42" "bot_sigscan.cpp" - "43" "bot_cvars.cpp" - "44" "bot_plugin_meta.cpp" - } - "Release|Win32" - { - "0" "bot.cpp" - "1" "bot_accessclient.cpp" - "2" "bot_buttons.cpp" - "3" "bot_client.cpp" - "4" "bot_commands.cpp" - "5" "bot_configfile.cpp" - "6" "bot_coop.cpp" - "7" "bot_css_bot.cpp" - "8" "bot_dod_bot.cpp" - "9" "bot_dod_mod.cpp" - "10" "bot_events.cpp" - "11" "bot_fortress.cpp" - "12" "bot_ga.cpp" - "13" "bot_ga_ind.cpp" - "14" "bot_getprop.cpp" - "15" "bot_globals.cpp" - "16" "bot_hl1dmsrc.cpp" - "17" "bot_hldm_bot.cpp" - "18" "bot_kv.cpp" - "19" "bot_menu.cpp" - "20" "bot_mods.cpp" - "21" "bot_mtrand.cpp" - "22" "bot_navmesh.cpp" - "23" "bot_perceptron.cpp" - "24" "bot_profile.cpp" - "25" "bot_profiling.cpp" - "26" "bot_schedule.cpp" - "27" "bot_tf2_points.cpp" - "28" "bot_som.cpp" - "29" "bot_squads.cpp" - "30" "bot_strings.cpp" - "31" "bot_task.cpp" - "32" "bot_tf2_mod.cpp" - "33" "bot_usercmd.cpp" - "34" "bot_utility.cpp" - "35" "bot_visibles.cpp" - "36" "bot_waypoint.cpp" - "37" "bot_waypoint_locations.cpp" - "38" "bot_waypoint_visibility.cpp" - "39" "bot_weapons.cpp" - "40" "bot_wpt_dist.cpp" - "41" "bot_zombie.cpp" - "42" "bot_sigscan.cpp" - "43" "bot_cvars.cpp" - "44" "bot_plugin_meta.cpp" - } - "Release_NonHomeFolder|Win32" - { - "0" "bot.cpp" - "1" "bot_accessclient.cpp" - "2" "bot_buttons.cpp" - "3" "bot_client.cpp" - "4" "bot_commands.cpp" - "5" "bot_configfile.cpp" - "6" "bot_coop.cpp" - "7" "bot_css_bot.cpp" - "8" "bot_dod_bot.cpp" - "9" "bot_dod_mod.cpp" - "10" "bot_events.cpp" - "11" "bot_fortress.cpp" - "12" "bot_ga.cpp" - "13" "bot_ga_ind.cpp" - "14" "bot_getprop.cpp" - "15" "bot_globals.cpp" - "16" "bot_hl1dmsrc.cpp" - "17" "bot_hldm_bot.cpp" - "18" "bot_kv.cpp" - "19" "bot_menu.cpp" - "20" "bot_mods.cpp" - "21" "bot_mtrand.cpp" - "22" "bot_navmesh.cpp" - "23" "bot_perceptron.cpp" - "24" "bot_profile.cpp" - "25" "bot_profiling.cpp" - "26" "bot_schedule.cpp" - "27" "bot_tf2_points.cpp" - "28" "bot_som.cpp" - "29" "bot_squads.cpp" - "30" "bot_strings.cpp" - "31" "bot_task.cpp" - "32" "bot_tf2_mod.cpp" - "33" "bot_usercmd.cpp" - "34" "bot_utility.cpp" - "35" "bot_visibles.cpp" - "36" "bot_waypoint.cpp" - "37" "bot_waypoint_locations.cpp" - "38" "bot_waypoint_visibility.cpp" - "39" "bot_weapons.cpp" - "40" "bot_wpt_dist.cpp" - "41" "bot_zombie.cpp" - "42" "bot_sigscan.cpp" - "43" "bot_cvars.cpp" - "44" "bot_plugin_meta.cpp" - } -} diff --git a/linux_sdk/libtier0_srv.so b/linux_sdk/libtier0_srv.so deleted file mode 100644 index 8bcea0856..000000000 Binary files a/linux_sdk/libtier0_srv.so and /dev/null differ diff --git a/linux_sdk/libvstdlib_srv.so b/linux_sdk/libvstdlib_srv.so deleted file mode 100644 index cb0fddaec..000000000 Binary files a/linux_sdk/libvstdlib_srv.so and /dev/null differ diff --git a/linux_sdk/mathlib_i486.a b/linux_sdk/mathlib_i486.a deleted file mode 100644 index cbe62179c..000000000 Binary files a/linux_sdk/mathlib_i486.a and /dev/null differ diff --git a/linux_sdk/particles_i486.a b/linux_sdk/particles_i486.a deleted file mode 100644 index 4d835a4a8..000000000 Binary files a/linux_sdk/particles_i486.a and /dev/null differ diff --git a/linux_sdk/tier0_i486.so b/linux_sdk/tier0_i486.so deleted file mode 100644 index 5d4ed1936..000000000 Binary files a/linux_sdk/tier0_i486.so and /dev/null differ diff --git a/linux_sdk/tier1_i486.a b/linux_sdk/tier1_i486.a deleted file mode 100644 index 7a686b1aa..000000000 Binary files a/linux_sdk/tier1_i486.a and /dev/null differ diff --git a/linux_sdk/tier2_i486.a b/linux_sdk/tier2_i486.a deleted file mode 100644 index 200b39451..000000000 Binary files a/linux_sdk/tier2_i486.a and /dev/null differ diff --git a/linux_sdk/tier3_i486.a b/linux_sdk/tier3_i486.a deleted file mode 100644 index ba94f302e..000000000 Binary files a/linux_sdk/tier3_i486.a and /dev/null differ diff --git a/linux_sdk/vcpm b/linux_sdk/vcpm deleted file mode 100644 index b973d7613..000000000 Binary files a/linux_sdk/vcpm and /dev/null differ diff --git a/linux_sdk/vstdlib_i486.so b/linux_sdk/vstdlib_i486.so deleted file mode 100644 index 5d4ed1936..000000000 Binary files a/linux_sdk/vstdlib_i486.so and /dev/null differ diff --git a/loader/AMBuilder b/loader/AMBuilder new file mode 100644 index 000000000..e21e0efd2 --- /dev/null +++ b/loader/AMBuilder @@ -0,0 +1,33 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: +import os.path + +loader_name = 'RCBot2Meta' + +for cxx in builder.targets: + if cxx.target.platform in ['windows', 'mac']: + name = loader_name + extra_ldflags = [] + elif cxx.target.platform == 'linux': + name = loader_name + '_i486' + extra_ldflags = ['-ldl'] + + if cxx.target.arch == "x86_64": + name = loader_name + '.x64' + + binary = MMS.Library(cxx, name) + binary.compiler.cxxincludes += [ + os.path.join(MMS.mms_root, 'core'), + os.path.join(MMS.mms_root, 'sourcehook') + ] + binary.compiler.defines += ['META_NO_HL2SDK'] + if binary.compiler.family == 'gcc' or binary.compiler.family == 'clang': + binary.compiler.cxxflags += ['-fno-rtti'] + elif binary.compiler.family == 'msvc': + binary.compiler.cxxflags += ['/GR-'] + binary.compiler.linkflags += extra_ldflags + binary.sources = [ + 'loader.cpp' + ] + + nodes = builder.Add(binary) + MMS.binaries += [nodes] diff --git a/loader/loader.cpp b/loader/loader.cpp new file mode 100644 index 000000000..6dde7f39a --- /dev/null +++ b/loader/loader.cpp @@ -0,0 +1,394 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +/** + * vim: set ts=4 sw=4 tw=99 noet : + * ============================================================================= + * SourceMod + * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + */ + +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#define DLL_EXPORT extern "C" __declspec(dllexport) +#define openlib(lib) LoadLibrary(lib) +#define closelib(lib) FreeLibrary(lib) +#define findsym(lib, sym) GetProcAddress(lib, sym) +#define PLATFORM_EXT ".dll" +#define vsnprintf _vsnprintf +#define PATH_SEP_CHAR "\\" +#include +#else +#define DLL_EXPORT extern "C" __attribute__((visibility("default"))) +#define openlib(lib) dlopen(lib, RTLD_NOW) +#define closelib(lib) dlclose(lib) +#define findsym(lib, sym) dlsym(lib, sym) +#if defined __linux__ +#define PLATFORM_EXT ".so" +#elif defined __APPLE__ +#define PLATFORM_EXT ".dylib" +#endif +typedef void* HINSTANCE; +#define PATH_SEP_CHAR "/" +#include +#endif + +#if defined(_WIN64) || defined(__x86_64__) || defined(__amd64__) +#define PLATFORM_ARCH_FOLDER "x64" PATH_SEP_CHAR +#else +#define PLATFORM_ARCH_FOLDER "" +#endif + +constexpr int METAMOD_API_MAJOR = 2; + +#define FILENAME_1_6_EP2 PLATFORM_ARCH_FOLDER "rcbot.2.ep2" PLATFORM_EXT +#define FILENAME_1_6_EP1 PLATFORM_ARCH_FOLDER "rcbot.2.ep1" PLATFORM_EXT +#define FILENAME_1_6_L4D PLATFORM_ARCH_FOLDER "rcbot.2.l4d" PLATFORM_EXT +#define FILENAME_1_6_DARKM PLATFORM_ARCH_FOLDER "rcbot.2.darkm" PLATFORM_EXT +#define FILENAME_1_6_L4D2 PLATFORM_ARCH_FOLDER "rcbot.2.l4d2" PLATFORM_EXT +#define FILENAME_1_6_SWARM PLATFORM_ARCH_FOLDER "rcbot.2.swarm" PLATFORM_EXT +#define FILENAME_1_6_BGT PLATFORM_ARCH_FOLDER "rcbot.2.bgt" PLATFORM_EXT +#define FILENAME_1_6_EYE PLATFORM_ARCH_FOLDER "rcbot.2.eye" PLATFORM_EXT +#define FILENAME_1_6_PORTAL2 PLATFORM_ARCH_FOLDER "rcbot.2.portal2" PLATFORM_EXT +#define FILENAME_1_6_CSGO PLATFORM_ARCH_FOLDER "rcbot.2.csgo" PLATFORM_EXT +#define FILENAME_1_6_CSS PLATFORM_ARCH_FOLDER "rcbot.2.css" PLATFORM_EXT +#define FILENAME_1_6_HL2DM PLATFORM_ARCH_FOLDER "rcbot.2.hl2dm" PLATFORM_EXT +#define FILENAME_1_6_DODS PLATFORM_ARCH_FOLDER "rcbot.2.dods" PLATFORM_EXT +#define FILENAME_1_6_SDK2013 PLATFORM_ARCH_FOLDER "rcbot.2.sdk2013" PLATFORM_EXT +#define FILENAME_1_6_TF2 PLATFORM_ARCH_FOLDER "rcbot.2.tf2" PLATFORM_EXT +#define FILENAME_1_6_ND PLATFORM_ARCH_FOLDER "rcbot.2.nd" PLATFORM_EXT +#define FILENAME_1_6_BLADE PLATFORM_ARCH_FOLDER "rcbot.2.blade" PLATFORM_EXT +#define FILENAME_1_6_INSURGENCY PLATFORM_ARCH_FOLDER "rcbot.2.insurgency" PLATFORM_EXT +#define FILENAME_1_6_DOI PLATFORM_ARCH_FOLDER "rcbot.2.doi" PLATFORM_EXT +#define FILENAME_1_6_CONTAGION PLATFORM_ARCH_FOLDER "rcbot.2.contagion" PLATFORM_EXT +#define FILENAME_1_6_BMS PLATFORM_ARCH_FOLDER "rcbot.2.bms" PLATFORM_EXT + +HINSTANCE g_hCore = nullptr; +bool load_attempted = false; + +std::size_t UTIL_Format(char *buffer, std::size_t maxlength, const char *fmt, ...); + +class FailPlugin : public SourceMM::ISmmFailPlugin +{ +public: + int GetApiVersion() override + { + return fail_version; + } + + bool Load(SourceMM::PluginId id, SourceMM::ISmmAPI *ismm, char *error, const std::size_t maxlength, bool late) override + { + if (error != nullptr && maxlength != 0) + { + UTIL_Format(error, maxlength, "%s", error_buffer); + } + return false; + } + + int fail_version; + char error_buffer[512]; +} s_FailPlugin; + +std::size_t UTIL_Format(char *buffer, const std::size_t maxlength, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + std::size_t len = vsnprintf(buffer, maxlength, fmt, ap); + va_end(ap); + + if (len >= maxlength) + { + len = maxlength - 1; + buffer[len] = '\0'; + } + + return len; +} + +METAMOD_PLUGIN* _GetPluginPtr(const char* path, const int fail_api) +{ + METAMOD_FN_ORIG_LOAD fn; + METAMOD_PLUGIN* pl = nullptr; // Declare and initialize `pl` at the top [APG]RoboCop[CL] + int ret; + + if (!((g_hCore = openlib(path)))) + { +#if defined __linux__ || defined __APPLE__ + UTIL_Format(s_FailPlugin.error_buffer, sizeof(s_FailPlugin.error_buffer), "%s", dlerror()); +#else + DWORD err = GetLastError(); + + if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), s_FailPlugin.error_buffer, + sizeof(s_FailPlugin.error_buffer), nullptr) + == 0) + { + UTIL_Format(s_FailPlugin.error_buffer, sizeof(s_FailPlugin.error_buffer), "unknown error %x", err); + } +#endif + + s_FailPlugin.fail_version = fail_api; + + return reinterpret_cast(&s_FailPlugin); + } + + if (!((fn = reinterpret_cast(findsym(g_hCore, "CreateInterface"))))) + { + goto error; + } + pl = static_cast(fn(METAMOD_PLAPI_NAME, &ret)); + if (!pl) + { + goto error; + } + + return pl; +error: + closelib(g_hCore); + g_hCore = nullptr; + return nullptr; +} + + +DLL_EXPORT METAMOD_PLUGIN* CreateInterface_MMS(const MetamodVersionInfo* mvi, const MetamodLoaderInfo* mli) +{ + const char* filename = nullptr; + + load_attempted = true; + + if (mvi->api_major > METAMOD_API_MAJOR) + { + return nullptr; + } + + switch (mvi->source_engine) + { + case SOURCE_ENGINE_ORIGINAL: + case SOURCE_ENGINE_EPISODEONE: + { + filename = FILENAME_1_6_EP1; + break; + } + case SOURCE_ENGINE_ORANGEBOX: + { + filename = FILENAME_1_6_EP2; + break; + } + case SOURCE_ENGINE_LEFT4DEAD: + { + filename = FILENAME_1_6_L4D; + break; + } + case SOURCE_ENGINE_DARKMESSIAH: + { + filename = FILENAME_1_6_DARKM; + break; + } + case SOURCE_ENGINE_LEFT4DEAD2: + { + const char* gamedir = mvi->GetGameDir(); + if (strcmp(gamedir, "nucleardawn") == 0) + { + filename = FILENAME_1_6_ND; + } + else + { + filename = FILENAME_1_6_L4D2; + } + break; + } + case SOURCE_ENGINE_NUCLEARDAWN: + { + filename = FILENAME_1_6_ND; + break; + } + case SOURCE_ENGINE_CONTAGION: + { + filename = FILENAME_1_6_CONTAGION; + break; + } + case SOURCE_ENGINE_ALIENSWARM: + { + filename = FILENAME_1_6_SWARM; + break; + } + case SOURCE_ENGINE_BLOODYGOODTIME: + { + filename = FILENAME_1_6_BGT; + break; + } + case SOURCE_ENGINE_EYE: + { + filename = FILENAME_1_6_EYE; + break; + } + case SOURCE_ENGINE_PORTAL2: + { + filename = FILENAME_1_6_PORTAL2; + break; + } + case SOURCE_ENGINE_CSGO: + { + filename = FILENAME_1_6_CSGO; + break; + } + case SOURCE_ENGINE_CSS: + { + filename = FILENAME_1_6_CSS; + break; + } + case SOURCE_ENGINE_HL2DM: + { + filename = FILENAME_1_6_HL2DM; + break; + } + case SOURCE_ENGINE_DODS: + { + filename = FILENAME_1_6_DODS; + break; + } + case SOURCE_ENGINE_SDK2013: + { + filename = FILENAME_1_6_SDK2013; + break; + } + case SOURCE_ENGINE_BMS: + { + const char* gamedir = mvi->GetGameDir(); + if (strcmp(gamedir, "bms") == 0) + { + filename = FILENAME_1_6_BMS; + } + break; + } + case SOURCE_ENGINE_TF2: + { + filename = FILENAME_1_6_TF2; + break; + } + case SOURCE_ENGINE_ORANGEBOXVALVE_DEPRECATED: + { + const char* gamedir = mvi->GetGameDir(); + if (strcmp(gamedir, "tf") == 0) + { + filename = FILENAME_1_6_TF2; + } + else if (strcmp(gamedir, "dod") == 0) + { + filename = FILENAME_1_6_DODS; + } + else if (strcmp(gamedir, "hl2mp") == 0) + { + filename = FILENAME_1_6_HL2DM; + } + else + { + return nullptr; + } + break; + } + case SOURCE_ENGINE_BLADE: + { + filename = FILENAME_1_6_BLADE; + break; + } + case SOURCE_ENGINE_INSURGENCY: + { + filename = FILENAME_1_6_INSURGENCY; + break; + } + case SOURCE_ENGINE_DOI: + { + filename = FILENAME_1_6_DOI; + break; + } + default: + { + return nullptr; + } + } + + char abspath[256]; + UTIL_Format(abspath, sizeof(abspath), "%s" PATH_SEP_CHAR "%s", mli->pl_path, filename); + + return _GetPluginPtr(abspath, METAMOD_FAIL_API_V2); +} + +DLL_EXPORT void UnloadInterface_MMS() +{ + if (g_hCore) + { + closelib(g_hCore); + g_hCore = nullptr; + } +} + +#ifdef _MSC_VER +BOOL WINAPI DllMain(HINSTANCE hinstDLL, const DWORD fdwReason, LPVOID lpReserved) +{ + if (fdwReason == DLL_PROCESS_DETACH) + { + UnloadInterface_MMS(); + } + return TRUE; +} +#else +__attribute__((destructor)) static void gcc_fini() +{ + UnloadInterface_MMS(); +} +#endif + +/* Overload a few things to prevent libstdc++ linking */ +#if defined __linux__ || defined __APPLE__ +extern "C" void __cxa_pure_virtual(void) +{ +} + +void *operator new(std::size_t size) +{ + return malloc(size); +} + +void *operator new[](std::size_t size) +{ + return malloc(size); +} + +void operator delete(void *ptr) +{ + free(ptr); +} + +void operator delete[](void *ptr) +{ + free(ptr); +} +#endif diff --git a/package/config/accessclients.ini b/package/config/accessclients.ini new file mode 100644 index 000000000..22c440f1d --- /dev/null +++ b/package/config/accessclients.ini @@ -0,0 +1,13 @@ +# format is +# "" +# see http://rcbot.bots-united.com/accesslev.htm for access +# levels +# +# example: +# +# +# "STEAM_0:123456789" 63 +# don't put one of '#' these before a line you want to be read +# by the bot! +# +"STEAM_ID_LAN" 63 diff --git a/package/config/attack_util.csv b/package/config/attack_util.csv new file mode 100644 index 000000000..b7b60da8b --- /dev/null +++ b/package/config/attack_util.csv @@ -0,0 +1,93 @@ +//,SCOUT,,SNIPER,,SOLDIER,,DEMOMAN,,MEDIC,,HWGUY,,PYRO,,SPY,,ENGINEER, +//,min,max,min,max,min,max,min,max,min,max,min,max,min,max,min,max,min,max +BOT_UTIL_BUILDSENTRY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_BUILDDISP,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_BUILDTELENT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0.2 +BOT_UTIL_BUILDTELEXT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2 +BOT_UTIL_UPGSENTRY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_UPGDISP,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_UPGTELENT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.1,0.2 +BOT_UTIL_UPGTELEXT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_UPGTMSENTRY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_UPGTMDISP,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_UPGTMTELENT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_UPGTMTELEXT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_GOTODISP,0,0,0,0,0,0,0,0,0,0,0.1,0.2,0,0,0,0,0,0 +BOT_UTIL_GOTORESUPPLY_FOR_HEALTH,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_GETAMMOKIT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_GETAMMOTMDISP,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_GETAMMODISP,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_GETFLAG,0.1,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_GETHEALTHKIT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_GETFLAG_LASTKNOWN,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_SNIPE,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_ROAM,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +//,SCOUT,,SNIPER,,SOLDIER,,DEMOMAN,,MEDIC,,HWGUY,,PYRO,,SPY,,ENGINEER, +//,min,max,min,max,min,max,min,max,min,max,min,max,min,max,min,max,min,max +BOT_UTIL_CAPTURE_FLAG,0.1,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_GOTORESUPPLY_FOR_AMMO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_FIND_NEAREST_HEALTH,0.1,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_FIND_NEAREST_AMMO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_ATTACK_POINT,0.1,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_DEFEND_POINT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_DEFEND_FLAG,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_ENGI_LOOK_AFTER_SENTRY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_DEFEND_FLAG_LASTKNOWN,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_PUSH_PAYLOAD_BOMB,0.3,0.3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_DEFEND_PAYLOAD_BOMB,0,0,0,0,0,0,0,0,0,0,0.1,0.2,0,0,0,0,0,0 +BOT_UTIL_MEDIC_HEAL,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_MEDIC_HEAL_LAST,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_MEDIC_FINDPLAYER,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_SAP_NEAREST_SENTRY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_SAP_ENEMY_SENTRY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +//,SCOUT,,SNIPER,,SOLDIER,,DEMOMAN,,MEDIC,,HWGUY,,PYRO,,SPY,,ENGINEER, +//,min,max,min,max,min,max,min,max,min,max,min,max,min,max,min,max,min,max +BOT_UTIL_SAP_LASTENEMY_SENTRY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_SAP_DISP,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_BACKSTAB,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_REMOVE_SENTRY_SAPPER,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_REMOVE_DISP_SAPPER,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_REMOVE_TMSENTRY_SAPPER,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_REMOVE_TMDISP_SAPPER,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_DEMO_STICKYTRAP_LASTENEMY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_DEMO_STICKYTRAP_POINT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_DEMO_STICKYTRAP_FLAG,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_DEMO_STICKYTRAP_FLAG_LASTKNOWN,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_DEMO_STICKYTRAP_PL,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_REMOVE_TMTELE_SAPPER,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_SAP_NEAREST_TELE,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_SAP_ENEMY_TELE,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_SAP_LASTENEMY_TELE,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_GOTO_NEST,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_MESSAROUND,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_ENGI_MOVE_SENTRY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_ENGI_MOVE_DISP,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_ENGI_MOVE_ENTRANCE,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_ENGI_MOVE_EXIT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_ENGI_DESTROY_SENTRY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_ENGI_DESTROY_DISP,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_ENGI_DESTROY_ENTRANCE,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_ENGI_DESTROY_EXIT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +//,SCOUT,,SNIPER,,SOLDIER,,DEMOMAN,,MEDIC,,HWGUY,,PYRO,,SPY,,ENGINEER, +//,min,max,min,max,min,max,min,max,min,max,min,max,min,max,min,max,min,max + BOT_UTIL_MEDIC_FINDPLAYER_AT_SPAWN,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_HL2DM_GRAVIGUN_PICKUP,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_HL2DM_FIND_ARMOR,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_FIND_LAST_ENEMY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_HL2DM_USE_CHARGER,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_HL2DM_USE_HEALTH_CHARGER,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_THROW_GRENADE,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_PICKUP_WEAPON,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_ATTACK_NEAREST_POINT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_DEFEND_NEAREST_POINT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_DEFEND_BOMB,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_DEFUSE_BOMB,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_PLANT_BOMB,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_PLANT_NEAREST_BOMB,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_DEFUSE_NEAREST_BOMB,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_DEFEND_NEAREST_BOMB,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_PICKUP_BOMB,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_PIPE_NEAREST_SENTRY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_PIPE_LAST_ENEMY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_PIPE_LAST_ENEMY_SENTRY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_MAX,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 diff --git a/package/config/bot_mods.ini b/package/config/bot_mods.ini new file mode 100644 index 000000000..ad3e5f4dc --- /dev/null +++ b/package/config/bot_mods.ini @@ -0,0 +1,51 @@ +# IMPORTANT! This setup is complicated so read carefully. +# Say for example you added RCBot2 in D:\SteamCMD\teamfort2\tf\addons\rcbot2 +# Then you should set the [mod] as [mod = TF2], [gamedir = tf] and [bot] as [TF2]. +# Be sure to change those configs properly and uncomment the lines you need for RCBot2 to load +# +# EXAMPLE MOD FILE# valid mod types +# --------------- +# CSS +# TF2 +# DOD +# HL2DM +# HL1DM +# FF +# SVENCOOP2 +# TIMCOOP +# NS2 +# SYNERGY +# +# valid bot types +# --------------- +# CSS +# TF2 +# DOD +# HL2DM +# HL1DM +# FF +# COOP +# ZOMBIE +# +# weaponlists are changeable in config/weapons.ini +# +#mod = FF +#gamedir = ff +#bot = FF +#weaponlist = FF +# +#mod = HL1DM +#gamedir = hl1dm +#bot = HL1DM +#weaponlist = HL1DMSRC +# +#mod = CUSTOM +#gamedir = dod +#bot = ZOMBIE +#weaponlist = DOD +# +#mod = SYNERGY +#gamedir = synergy +#bot = COOP +#weaponlist = SYNERGY +# \ No newline at end of file diff --git a/package/config/bot_quota.ini b/package/config/bot_quota.ini new file mode 100644 index 000000000..11d74d332 --- /dev/null +++ b/package/config/bot_quota.ini @@ -0,0 +1,38 @@ +# Bot Quota Settings +# To use this settings you have to enable rcbot_bot_quota_interval +# Bear in mind, that the bots also count towards the max_players setting + +Humans "0" => Bots "0" # This is used for the default bot quota (empty server) +Humans "1" => Bots "9" # 1 Human => 9 Bots => 10 Total Players +Humans "2" => Bots "8" # 2 Humans => 8 Bots => 10 Total Players +Humans "3" => Bots "7" # etc. +Humans "4" => Bots "6" +Humans "5" => Bots "5" +Humans "6" => Bots "4" +Humans "7" => Bots "3" +Humans "8" => Bots "2" +Humans "9" => Bots "1" +Humans "10" => Bots "0" +Humans "11" => Bots "0" +Humans "12" => Bots "0" +Humans "13" => Bots "0" +Humans "14" => Bots "0" +Humans "15" => Bots "0" +Humans "16" => Bots "0" +Humans "17" => Bots "0" +Humans "18" => Bots "0" +Humans "19" => Bots "0" +Humans "20" => Bots "0" +Humans "21" => Bots "0" +Humans "22" => Bots "0" +Humans "23" => Bots "0" +Humans "24" => Bots "0" +Humans "25" => Bots "0" +Humans "26" => Bots "0" +Humans "27" => Bots "0" +Humans "28" => Bots "0" +Humans "29" => Bots "0" +Humans "30" => Bots "0" +Humans "31" => Bots "0" +Humans "32" => Bots "0" + diff --git a/package/config/config.ini b/package/config/config.ini new file mode 100644 index 000000000..e8724c702 --- /dev/null +++ b/package/config/config.ini @@ -0,0 +1,250 @@ +######### General Settings ######## +# +# This is a TF2 lag bot prevention fix that prevents causing rcbots to crash +sv_quota_stringcmdspersecond 99999 +# +# General difficulty of the bots. 0.5 = stock, < 0.5 easier, > 0.5 = harder -Broken! +# Not used - DNA.styx +# rcbot_skill 0.8 +# +# If set to 1 will make every bot skill and reaction much higher +rcbot_supermode 0 +# +# The time in seconds for bots to be added after another +rcbot_addbottime 5 +# +# If 1 , bots will all move forward +rcbot_dont_move 0 +# +# Rate for bots to defend +rcbot_defrate 0.2 +# +# Smaller number will make bots turn slower (1 = instant turn but may overshoot) +rcbot_anglespeed 0.25 +# +# Radius in units for bots to avoid things +rcbot_avoid_radius 80 +# +# Strength of avoidance (0 = disable) +rcbot_avoid_strength 100 +# +# (0 = no smoothing) -Broken! +rcbot_aimsmoothing 0 +# +# How many revs the bot searches for visible players and enemies, lower to reduce cpu usage +# Replaced by visionticks_clients setting in profile .ini files - DNA.styx +# rcbot_visrevs_clients 3 +# +# How many revs the bot searches for visible monsters, lower to reduce cpu usage +# Replaced by visionticks setting in profile .ini files - DNA.styx +# rcbot_visrevs 6 +# +# How many revs the bot searches for a path each frame, lower to reduce cpu usage, but causes bots to stand still more +# Replaced by pathticks setting in profile .ini files - DNA.styx +# rcbot_pathrevs 30 +# +# The fov dot product before the bot shoots an enemy 0.7 = 45 degrees +rcbot_enemyshootfov 0.97 +# +# Bots change classes at random intervals - Required to prevent DoDS crashes +rcbot_change_classes 0 +# +# Bots mess around at start up +rcbot_messaround 1 +# +# If 1 bots will only use melee weapons +rcbot_melee_only 0 +# +# Minimum time for bots to consider changing class (seconds) +rcbot_min_cc_time 60 +# +# Maximum time for bots to consider changing class (seconds) +rcbot_max_cc_time 240 +# +# Bots use voice commands e.g. medic/spy etc +rcbot_voice_cmds 1 +# +# Bots don't shoot the host - useful for testing waypoints +rcbot_notarget 0 +# +# Distance for autowaypoints to be placed - useful for adding waypoints +rcbot_autowpt_dist 150.0 +# +# Length for waypoints to automatically add paths at +rcbot_wpt_pathdist 400 +# +# Show welcome message on player connect +rcbot_show_welcome_msg 1 +# +######## DoDS Settings ######## +# +# Free for all mode -- bots shoot everyone +rcbot_ffa 0 +# +# Bots don't capture flags in DOD:S +rcbot_dontcapture 0 +# +# Bots will form their own squads via voice commands +rcbot_bots_form_squads 1 +# +# Time for bots to do other things if squad leader is idle for a short time +rcbot_squad_idle_time 3 +# +# The percentage of time bots make squads with other bots +rcbot_bot_squads_percent 50 +# +# If 1 bots only prone in DOD:S when they have an enemy +rcbot_prone_enemy_only 1 +# +# Tweaks the bots knowledge of projectiles and gravity +rcbot_projtweak 0.05 +# +# If 1, bots will shoot breakable objects +rcbot_shoot_breakables 1 +# +# The distance bots will shoot breakables at +rcbot_shoot_breakable_dist 128.0 +# +# The cosine of the angle bots should worry about breaking objects at (default = 0.9) ~= 25 degrees +rcbot_shoot_breakable_cos 0.9 +# +####### HL2DM Settings ####### +# +# The distance from an obstacle the bot will jump +rcbot_jump_obst_dist 80 +# +# The fov dot product before the bot shoots an enemy 0.98 = 11 degrees +rcbot_enemyshoot_gravgun_fov 0.98 +# +######## TF2 Settings ######## +# +# Enable/disable bots taunting +rcbot_taunt 0 +# +# Debug command : allow spy bots to cloak and disguise +rcbot_tf2_debug_spies_cloakdisguise 1 +# +# Time for medic to let go of medigun to switch players +rcbot_tf2_medic_letgotime 0.5 +# +# Time that the bots will spend more attention to the cap point if attacked +rcbot_tf2_prot_cap_time 12.5 +# +# The percentage (0.25 = 25%) that bots defend the capture point by standing on the point +rcbot_tf2_protect_cap_percent 0.25 +# +# The distance for spy bots to attack players capturing a point +rcbot_tf2_spy_kill_on_cap_dist 200.0 +# +# Time to automatically update points in TF2 for any changes +rcbot_tf2_autoupdate_point_time 60 +# +# Distance for payload bomb to be greater than at cap before defend team retreats +rcbot_tf2_payload_dist_retreat 512.0 +# +# Ammo must be above this to airblast -- if 200 airblast will be disabled +rcbot_tf2_pyro_airblast_ammo 50 +# +# The higher the more often the bots will shoot the boss +rcbot_bossattackfactor 1.0 +# +# Health which spies run away after attacking +rcbot_spy_runaway_health 70 +# +# the FOV from the enemy that spies must backstab from +rcbot_spyknifefov 80 +# +# Fraction of how much the heavy aims at a diagonal offset +rcbot_heavyaimoffset 0.1 +# +# Seconds for bots to start thinking about moving sentries +rcbot_move_sentry_time 120 +# +# kpm = kills per minute, if less than this, bots will think about moving the sentry +rcbot_move_sentry_kpm 1 +# +# Seconds for bots to start thinking about moving dispensers +rcbot_move_disp_time 120 +# +# If dispenser heals less than this per minute, bot will move the dispensers +rcbot_move_disp_healamount 100 +# +# Distance that bots will go back to use a dispenser +rcbot_disp_dist 800.0 +# +# Minimum distance to move objects to +rcbot_move_dist 800 +# +# Seconds for bots to start thinking about moving teleporters +rcbot_move_tele_time 120 +# +# If no of players teleported per minute is less than this, bot will move the teleport +rcbot_move_tele_tpm 1 +# +# Time scout uses to double jump +rcbot_scoutdj 0.5 +# +# Time for soldier to fire rocket after jumping +rcbot_rj 0.01 +# +# Distance the demo bot will take to run up for a pipe/sticky bomb jump +rcbot_demo_runup 99.0 +# +# Enable experimental pipe jumping at rocket jump waypoints +rcbot_enable_pipejump 1 +# +# If 1 rcbot engineers will move objects around +rcbot_move_obj 1 +# +# To enable "Auto Bot Quota" set the interval to a value above 0 (e.g. 5) (unit is seconds) +# This interval is used to check the human/bot player count +# For more information see bot_quota.ini +rcbot_bot_quota_interval -1 +# +# If quota is enabled then min and max are treated as a ceiling and floor for bot numbers. +# If quota is disabled then these become the primary logic for deciding bot numbers. +rcbotd config min_bots -1 +rcbotd config max_bots 10 +# +# If enabled, only concider humans who are actively playing - ie; are on a team +# Caution: if max_bots is too high it's possible to have teams full of bots and humans +# be unable to join since bots will no longer disconnect as soon as players join the server +#rcbot_ignore_spectators 0 +# +# When reducing the number of bots, instead of kicking a randomly chosen bot, kick the most +# recently added bot. If teams are unequal, only concider bots from the larger team. +#rcbot_nonrandom_kicking 0 +# +# When adding a bot, instead of using a randomly chosen profile, treat the profiles as +# an ordered list, loading bot 1 first, bot 2 second and so on. If teams are unequal, +# only concider bots who either have no team preference, or who's team profile is for +# the smaller team. If no suitable bot can be found, fall back to choosing one randomly. +#rcbot_nonrandom_profile 0 +# +# These plugins conflict and may not work well with RCBot2. Please inform us for any plugins that +# conflicts or prevents RCBot2 from working in rcbot.bots-united.com +# The plugins that have been commented are considered greylisted as they aren't guaranteed to work +sm plugins unload bot_ai.smx +sm plugins unload bot_nologic.smx +sm plugins unload bot_playerdestruction_ai.smx +sm plugins unload bot_rocketjump.smx +sm plugins unload bot_rocketjump_alt.smx +sm plugins unload bot_trucefix.smx +sm plugins unload botmanager.smx +#sm plugins unload ClassRestrictionsForBots.smx +sm plugins unload ClassWarfare.smx +#sm plugins unload GiveBotsCosmetics.smx +#sm plugins unload GiveBotsWeapons.smx +#sm plugins unload gscramble.smx +sm plugins unload tf2items_manager.smx +sm plugins unload smac_cvars.smx +sm plugins unload superlogs-tf2.smx +#sm plugins unload bossspawner.smx +sm plugins unload sm_dod_dropweapon.smx +#sm plugins unload addon_dodtms_classrest.smx +# +# Nosoop's new RCBot2 Logging cvar for monitoring warnings and errors +# Display logging messages with increasing verbosity (higher number = more messages) +# Loglevel 2 or below is recommended as having it higher can affect the server's performance +# and can crash when using `rcbot waypoint save` console command and corrupt the waypoint +rcbot_loglevel 2 diff --git a/package/config/default_cfg.txt b/package/config/default_cfg.txt new file mode 100644 index 000000000..48588e4ac --- /dev/null +++ b/package/config/default_cfg.txt @@ -0,0 +1,249 @@ +######### General Settings ######## +# +# General difficulty of the bots. 0.5 = stock, < 0.5 easier, > 0.5 = harder -Broken! +# Not used - DNA.styx +# rcbot_skill 0.8 +# +# If set to 1 will make every bot skill and reaction much higher +rcbot_supermode 0 +# +# The time in seconds for bots to be added after another +rcbot_addbottime 5 +# +# If 1 , bots will all move forward +rcbot_dont_move 0 +# +# Rate for bots to defend +rcbot_defrate 0.2 +# +# Smaller number will make bots turn slower (1 = instant turn but may overshoot) +rcbot_anglespeed 0.25 +# +# Radius in units for bots to avoid things +rcbot_avoid_radius 80 +# +# Strength of avoidance (0 = disable) +rcbot_avoid_strength 100 +# +# (0 = no smoothing) -Broken! +rcbot_aimsmoothing 0 +# +# How many revs the bot searches for visible players and enemies, lower to reduce cpu usage +# Replaced by visionticks_clients setting in profile .ini files - DNA.styx +# rcbot_visrevs_clients 3 +# +# How many revs the bot searches for visible monsters, lower to reduce cpu usage +# Replaced by visionticks setting in profile .ini files - DNA.styx +# rcbot_visrevs 6 +# +# How many revs the bot searches for a path each frame, lower to reduce cpu usage, but causes bots to stand still more +# Replaced by pathticks setting in profile .ini files - DNA.styx +# rcbot_pathrevs 30 +# +# The fov dot product before the bot shoots an enemy 0.7 = 45 degrees +rcbot_enemyshootfov 0.97 +# +# Bots change classes at random intervals - Required to prevent DoDS crashes +rcbot_change_classes 0 +# +# Bots mess around at start up +rcbot_messaround 1 +# +# If 1 bots will only use melee weapons +rcbot_melee_only 0 +# +# Minimum time for bots to consider changing class (seconds) +rcbot_min_cc_time 60 +# +# Maximum time for bots to consider changing class (seconds) +rcbot_max_cc_time 240 +# +# Bots use voice commands e.g. medic/spy etc +rcbot_voice_cmds 1 +# +# Bots don't shoot the host - useful for testing waypoints +rcbot_notarget 0 +# +# Distance for autowaypoints to be placed - useful for adding waypoints +rcbot_autowpt_dist 150.0 +# +# Length for waypoints to automatically add paths at +rcbot_wpt_pathdist 400 +# +# Show welcome message on player connect +rcbot_show_welcome_msg 1 +# +######## DoDS Settings ######## +# +# Free for all mode -- bots shoot everyone +rcbot_ffa 0 +# +# Bots don't capture flags in DOD:S +rcbot_dontcapture 0 +# +# Bots will form their own squads via voice commands +rcbot_bots_form_squads 1 +# +# Time for bots to do other things if squad leader is idle for a short time +rcbot_squad_idle_time 3 +# +# The percentage of time bots make squads with other bots +rcbot_bot_squads_percent 50 +# +# If 1 bots only prone in DOD:S when they have an enemy +rcbot_prone_enemy_only 1 +# +# Tweaks the bots knowledge of projectiles and gravity +rcbot_projtweak 0.05 +# +# If 1, bots will shoot breakable objects +rcbot_shoot_breakables 1 +# +# The distance bots will shoot breakables at +rcbot_shoot_breakable_dist 128.0 +# +# The cosine of the angle bots should worry about breaking objects at (default = 0.9) ~= 25 degrees +rcbot_shoot_breakable_cos 0.9 +# +####### HL2DM Settings ####### +# +# The distance from an obstacle the bot will jump +rcbot_jump_obst_dist 80 +# +# The fov dot product before the bot shoots an enemy 0.98 = 11 degrees +rcbot_enemyshoot_gravgun_fov 0.98 +# +######## TF2 Settings ######## +# +# Enable/disable bots taunting +rcbot_taunt 0 +# +# Debug command : allow spy bots to cloak and disguise +rcbot_tf2_debug_spies_cloakdisguise 1 +# +# Time for medic to let go of medigun to switch players +rcbot_tf2_medic_letgotime 0.5 +# +# Time that the bots will spend more attention to the cap point if attacked +rcbot_tf2_prot_cap_time 12.5 +# +# The percentage (0.25 = 25%) that bots defend the capture point by standing on the point +rcbot_tf2_protect_cap_percent 0.25 +# +# The distance for spy bots to attack players capturing a point +rcbot_tf2_spy_kill_on_cap_dist 200.0 +# +# Time to automatically update points in TF2 for any changes +rcbot_tf2_autoupdate_point_time 60 +# +# Distance for payload bomb to be greater than at cap before defend team retreats +rcbot_tf2_payload_dist_retreat 512.0 +# +# Ammo must be above this to airblast -- if 200 airblast will be disabled +rcbot_tf2_pyro_airblast_ammo 50 +# +# The higher the more often the bots will shoot the boss +rcbot_bossattackfactor 1.0 +# +# Health which spies run away after attacking +rcbot_spy_runaway_health 70 +# +# the FOV from the enemy that spies must backstab from +rcbot_spyknifefov 80 +# +# Fraction of how much the heavy aims at a diagonal offset +rcbot_heavyaimoffset 0.1 +# +# Minimum distance to move objects to +rcbot_move_dist 800 +# +# Seconds for bots to start thinking about moving sentries +rcbot_move_sentry_time 120 +# +# kpm = kills per minute, if less than this, bots will think about moving the sentry +rcbot_move_sentry_kpm 1 +# +# Seconds for bots to start thinking about moving dispensers +rcbot_move_disp_time 120 +# +# If dispenser heals less than this per minute, bot will move the dispensers +rcbot_move_disp_healamount 100 +# +# Distance that bots will go back to use a dispenser +rcbot_disp_dist 800.0 +# +# Seconds for bots to start thinking about moving teleporters +rcbot_move_tele_time 120 +# +# If no of players teleported per minute is less than this, bot will move the teleport +rcbot_move_tele_tpm 1 +# +# Time scout uses to double jump +rcbot_scoutdj 0.5 +# +# Time for soldier to fire rocket after jumping +rcbot_rj 0.01 +# +# Distance the demo bot will take to run up for a pipe/sticky bomb jump +rcbot_demo_runup 99.0 +# +# Enable experimental pipe jumping at rocket jump waypoints +rcbot_enable_pipejump 1 +# +# If 1 rcbot engineers will move objects around +rcbot_move_obj 1 +# +# To enable "Auto Bot Quota" set the interval to a value above 0 (e.g. 5) (unit is seconds) +# This interval is used to check the human/bot player count +# For more information see bot_quota.ini +rcbot_bot_quota_interval -1 +# +# If quota is enabled then min and max are treated as a ceiling and floor for bot numbers. +# If quota is disabled then these become the primary logic for deciding bot numbers. +rcbotd config min_bots -1 +rcbotd config max_bots 10 +# +# If enabled, only concider humans who are actively playing - ie; are on a team +# Caution: if max_bots is too high it's possible to have teams full of bots and humans +# be unable to join since bots will no longer disconnect as soon as players join the server +#rcbot_ignore_spectators 0 +# +# When reducing the number of bots, instead of kicking a randomly chosen bot, kick the most +# recently added bot. If teams are unequal, only concider bots from the larger team. +#rcbot_nonrandom_kicking 0 +# +# When adding a bot, instead of using a randomly chosen profile, treat the profiles as +# an ordered list, loading bot 1 first, bot 2 second and so on. If teams are unequal, +# only concider bots who either have no team preference, or who's team profile is for +# the smaller team. If no suitable bot can be found, fall back to choosing one randomly. +#rcbot_nonrandom_profile 0 +# +# These plugins conflict and may not work well with RCBot2. Please inform us for any plugins that +# conflicts or prevents RCBot2 from working in rcbot.bots-united.com +# The plugins that have been commented are considered greylisted as they aren't guaranteed to work +sm plugins unload bot_ai.smx +sm plugins unload bot_nologic.smx +sm plugins unload bot_playerdestruction_ai.smx +sm plugins unload bot_rocketjump.smx +sm plugins unload bot_rocketjump_alt.smx +sm plugins unload bot_trucefix.smx +sm plugins unload botmanager.smx +#sm plugins unload ClassRestrictionsForBots.smx +sm plugins unload ClassWarfare.smx +#sm plugins unload GiveBotsCosmetics.smx +#sm plugins unload GiveBotsWeapons.smx +#sm plugins unload gscramble.smx +sm plugins unload tf2items_manager.smx +sm plugins unload smac_cvars.smx +sm plugins unload superlogs-tf2.smx +#sm plugins unload bossspawner.smx +sm plugins unload sm_dod_dropweapon.smx +# +# This is a TF2 lag bot prevention fix that prevents causing rcbots to crash +sv_quota_stringcmdspersecond 99999 +# +# Nosoop's new RCBot2 Logging cvar for monitoring warnings and errors +# Display logging messages with increasing verbosity (higher number = more messages) +# Loglevel 2 or below is recommended as having it higher can affect the server's performance +# and can crash when using `rcbot waypoint save` console command and corrupt the waypoint +rcbot_loglevel 2 diff --git a/package/config/hookinfo.ini b/package/config/hookinfo.ini new file mode 100644 index 000000000..faa9e3c2b --- /dev/null +++ b/package/config/hookinfo.ini @@ -0,0 +1,27 @@ +# hookinfo for RCbot2 linux +# https://github.com/nosoop/rcbot2 + +# This config is used to hook against the correct game functions; wrong / outdated data will +# very likely crash your game! + +# CDODPlayer::PlayerRunCommand(CUserCmd*, IMoveHelper*) +# this is used to process bots +# TODO replace it with m_pController->RunPlayerMove() from the SDK in the future +runplayermove_dods_win=425 +runplayermove_dods_linux=426 + +# this is used to process bots +# TODO replace it with m_pController->RunPlayerMove() from the SDK in the future +runplayermove_synergy_win=424 +runplayermove_synergy_linux=425 + +# CreateGameRulesObject from sdktools.games +create_gamerules_object_win=\x55\x8B\xEC\x8B\x0D\x2A\x2A\x2A\x2A\x85\xC9\x74\x07 + +# Offset into CreateGameRulesObject where the address to the gamerules pointer is stored +gamerules_win=5 +gamerules_linux=5 + +# Offset for reading datamaps +getdatadescmap_win=11 +getdatadescmap_linux=12 \ No newline at end of file diff --git a/package/config/normal_util.csv b/package/config/normal_util.csv new file mode 100644 index 000000000..3f33d836f --- /dev/null +++ b/package/config/normal_util.csv @@ -0,0 +1,93 @@ +//,SCOUT,,SNIPER,,SOLDIER,,DEMOMAN,,MEDIC,,HWGUY,,PYRO,,SPY,,ENGINEER, +//,min,max,min,max,min,max,min,max,min,max,min,max,min,max,min,max,min,max +BOT_UTIL_BUILDSENTRY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_BUILDDISP,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_BUILDTELENT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_BUILDTELEXT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_UPGSENTRY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_UPGDISP,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_UPGTELENT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_UPGTELEXT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_UPGTMSENTRY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_UPGTMDISP,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_UPGTMTELENT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_UPGTMTELEXT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_GOTODISP,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_GOTORESUPPLY_FOR_HEALTH,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_GETAMMOKIT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_GETAMMOTMDISP,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_GETAMMODISP,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_GETFLAG,0.1,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_GETHEALTHKIT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_GETFLAG_LASTKNOWN,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_SNIPE,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_ROAM,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +//,SCOUT,,SNIPER,,SOLDIER,,DEMOMAN,,MEDIC,,HWGUY,,PYRO,,SPY,,ENGINEER, +//,min,max,min,max,min,max,min,max,min,max,min,max,min,max,min,max,min,max +BOT_UTIL_CAPTURE_FLAG,0.1,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_GOTORESUPPLY_FOR_AMMO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_FIND_NEAREST_HEALTH,0.1,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_FIND_NEAREST_AMMO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_ATTACK_POINT,0.1,0.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_DEFEND_POINT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_DEFEND_FLAG,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_ENGI_LOOK_AFTER_SENTRY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_DEFEND_FLAG_LASTKNOWN,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_PUSH_PAYLOAD_BOMB,0.3,0.3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_DEFEND_PAYLOAD_BOMB,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_MEDIC_HEAL,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_MEDIC_HEAL_LAST,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_MEDIC_FINDPLAYER,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_SAP_NEAREST_SENTRY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_SAP_ENEMY_SENTRY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +//,SCOUT,,SNIPER,,SOLDIER,,DEMOMAN,,MEDIC,,HWGUY,,PYRO,,SPY,,ENGINEER, +//,min,max,min,max,min,max,min,max,min,max,min,max,min,max,min,max,min,max +BOT_UTIL_SAP_LASTENEMY_SENTRY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_SAP_DISP,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_BACKSTAB,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_REMOVE_SENTRY_SAPPER,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_REMOVE_DISP_SAPPER,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_REMOVE_TMSENTRY_SAPPER,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_REMOVE_TMDISP_SAPPER,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_DEMO_STICKYTRAP_LASTENEMY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_DEMO_STICKYTRAP_POINT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_DEMO_STICKYTRAP_FLAG,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_DEMO_STICKYTRAP_FLAG_LASTKNOWN,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_DEMO_STICKYTRAP_PL,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_REMOVE_TMTELE_SAPPER,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_SAP_NEAREST_TELE,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_SAP_ENEMY_TELE,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_SAP_LASTENEMY_TELE,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_MESSAROUND,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_ENGI_MOVE_SENTRY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_ENGI_MOVE_DISP,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_ENGI_MOVE_ENTRANCE,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_ENGI_MOVE_EXIT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_ENGI_DESTROY_SENTRY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_ENGI_DESTROY_DISP,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_ENGI_DESTROY_ENTRANCE,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_ENGI_DESTROY_EXIT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +BOT_UTIL_HIDE_FROM_ENEMY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +//,SCOUT,,SNIPER,,SOLDIER,,DEMOMAN,,MEDIC,,HWGUY,,PYRO,,SPY,,ENGINEER, +//,min,max,min,max,min,max,min,max,min,max,min,max,min,max,min,max,min,max + BOT_UTIL_MEDIC_FINDPLAYER_AT_SPAWN,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_HL2DM_GRAVIGUN_PICKUP,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_HL2DM_FIND_ARMOR,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_FIND_LAST_ENEMY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_HL2DM_USE_CHARGER,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_HL2DM_USE_HEALTH_CHARGER,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_THROW_GRENADE,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_PICKUP_WEAPON,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_ATTACK_NEAREST_POINT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_DEFEND_NEAREST_POINT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_DEFEND_BOMB,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_DEFUSE_BOMB,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_PLANT_BOMB,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_PLANT_NEAREST_BOMB,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_DEFUSE_NEAREST_BOMB,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_DEFEND_NEAREST_BOMB,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_PICKUP_BOMB,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_PIPE_NEAREST_SENTRY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_PIPE_LAST_ENEMY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_PIPE_LAST_ENEMY_SENTRY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + BOT_UTIL_MAX,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 diff --git a/package/config/weapons.ini b/package/config/weapons.ini new file mode 100644 index 000000000..6756aa7f9 --- /dev/null +++ b/package/config/weapons.ini @@ -0,0 +1,1571 @@ +//slots Primary = 0 Secondary = 1 Melee = 2 +//available flags below +// primary_attack +// secondary_attack +// explosive +// melee +// underwater +// hold_attack +// special +// can_kill_pipes +// can_deflect_rockets +// is_grav_gun +// has_explosive_secondary +// is_zoomable +// is_deployable_dods +// has_melee_secondary +// has_fire_select_mode_dods +// cant_be_fired_unzoomed_undeployed_dods +// is_grenade +// has_high_recoil_dods +// has_scope +// weapon_fires_projectile +// Shiro's Notes, sandvich handled by plugin, soldiers won't rocketjump with some launchers, bots still try and sticky trap with grenade launcher if they have shield +"RCBotWeapons" +{ + "TF2" + { + "tf_weapon_bat" + { + "slot" "2" + "id" "0" + "minPrimDist" "0.0" + "maxPrimDist" "180.0" + "m_iAmmoIndex" "0" + "m_iPreference" "1" + "flags" + { + "primary_attack" "1" + "melee" "1" + "underwater" "1" + } + } + "tf_weapon_bottle" + { + "slot" "2" + "id" "1" + "minPrimDist" "0.0" + "maxPrimDist" "180.0" + "m_iAmmoIndex" "0" + "m_iPreference" "1" + "flags" + { + "primary_attack" "1" + "melee" "1" + "underwater" "1" + } + } + "tf_weapon_fireaxe" + { + "slot" "2" + "id" "2" + "minPrimDist" "0.0" + "maxPrimDist" "180.0" + "m_iAmmoIndex" "0" + "m_iPreference" "1" + "flags" + { + "primary_attack" "1" + "melee" "1" + "underwater" "1" + } + } + "tf_weapon_club" + { + "slot" "2" + "id" "3" + "minPrimDist" "0.0" + "maxPrimDist" "180.0" + "m_iAmmoIndex" "0" + "m_iPreference" "1" + "flags" + { + "primary_attack" "1" + "melee" "1" + "underwater" "1" + } + } + "tf_weapon_knife" + { + "slot" "2" + "id" "4" + "minPrimDist" "0.0" + "maxPrimDist" "220.0" + "m_iAmmoIndex" "0" + "m_iPreference" "2" + "flags" + { + "primary_attack" "1" + "melee" "1" + "underwater" "1" + } + } + "tf_weapon_fists" + { + "slot" "2" + "id" "5" + "minPrimDist" "0.0" + "maxPrimDist" "180.0" + "m_iAmmoIndex" "0" + "m_iPreference" "1" + "flags" + { + "primary_attack" "1" + "melee" "1" + "underwater" "1" + } + } + "tf_weapon_shovel" + { + "slot" "2" + "id" "6" + "minPrimDist" "0.0" + "maxPrimDist" "180.0" + "m_iAmmoIndex" "0" + "m_iPreference" "1" + "flags" + { + "primary_attack" "1" + "melee" "1" + "underwater" "1" + } + } + "tf_weapon_wrench" + { + "slot" "2" + "id" "7" + "minPrimDist" "0.0" + "maxPrimDist" "180.0" + "m_iAmmoIndex" "3" + "m_iPreference" "1" + "flags" + { + "primary_attack" "1" + "melee" "1" + "underwater" "1" + } + } + "tf_weapon_bonesaw" + { + "slot" "2" + "id" "8" + "minPrimDist" "0.0" + "maxPrimDist" "180.0" + "m_iAmmoIndex" "0" + "m_iPreference" "1" + "flags" + { + "primary_attack" "1" + "melee" "1" + "underwater" "1" + } + } + "tf_weapon_shotgun_primary" + { + "slot" "0" + "id" "9" + "minPrimDist" "0.0" + "maxPrimDist" "800.0" + "m_iAmmoIndex" "1" + "m_iPreference" "2" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "can_kill_pipes" "1" + } + } + "tf_weapon_shotgun_soldier" + { + "slot" "1" + "id" "10" + "minPrimDist" "0.0" + "maxPrimDist" "500.0" + "m_iAmmoIndex" "2" + "m_iPreference" "2" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "can_kill_pipes" "1" + } + } + "tf_weapon_shotgun_hwg" + { + "slot" "1" + "id" "11" + "minPrimDist" "0.0" + "maxPrimDist" "800.0" + "m_iAmmoIndex" "2" + "m_iPreference" "2" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "can_kill_pipes" "1" + } + } + "tf_weapon_shotgun_pyro" + { + "slot" "1" + "id" "12" + "minPrimDist" "0.0" + "maxPrimDist" "800.0" + "m_iAmmoIndex" "2" + "m_iPreference" "2" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "can_kill_pipes" "1" + } + } + "tf_weapon_scattergun" + { + "slot" "0" + "id" "13" + "minPrimDist" "0.0" + "maxPrimDist" "800.0" + "m_iAmmoIndex" "1" + "m_iPreference" "3" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "can_kill_pipes" "1" + } + } + "tf_weapon_sniperrifle" + { + "slot" "0" + "id" "14" + "minPrimDist" "180.0" + "maxPrimDist" "4096.0" + "m_iAmmoIndex" "1" + "m_iPreference" "3" + "flags" + { + "primary_attack" "1" + "has_scope" "1" + } + } + "tf_weapon_minigun" + { + "slot" "0" + "id" "15" + "minPrimDist" "0.0" + "maxPrimDist" "1800.0" + "m_iAmmoIndex" "1" + "m_iPreference" "3" + "flags" + { + "primary_attack" "1" + "hold_attack" "1" + } + } + "tf_weapon_smg" + { + "slot" "1" + "id" "16" + "minPrimDist" "0.0" + "maxPrimDist" "1000.0" + "m_iAmmoIndex" "2" + "m_iPreference" "4" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "can_kill_pipes" "1" + } + } + "tf_weapon_syringegun_medic" + { + "slot" "0" + "id" "17" + "minPrimDist" "0.0" + "maxPrimDist" "1000.0" + "m_iAmmoIndex" "1" + "m_iPreference" "2" + "m_fProjSpeed" "1000.0" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "weapon_fires_projectile" "1" + } + } + "tf_weapon_rocketlauncher" + { + "slot" "0" + "id" "18" + "minPrimDist" "200.0" + "maxPrimDist" "4096.0" + "m_iAmmoIndex" "1" + "m_iPreference" "3" + "m_fProjSpeed" "1100.0" + "flags" + { + "primary_attack" "1" + "explosive" "1" + "underwater" "1" + "weapon_fires_projectile" "1" + } + } + "tf_weapon_grenadelauncher" + { + "slot" "0" + "id" "19" + "minPrimDist" "100.0" + "maxPrimDist" "1200.0" + "m_iAmmoIndex" "1" + "m_iPreference" "2" + "m_fProjSpeed" "1216.6" + "flags" + { + "primary_attack" "1" + "explosive" "1" + "underwater" "1" + "weapon_fires_projectile" "1" + } + } + "tf_weapon_pipebomblauncher" + { + "slot" "1" + "id" "20" + "minPrimDist" "0.0" + "maxPrimDist" "1000.0" + "m_iAmmoIndex" "2" + "m_iPreference" "1" + "m_fProjSpeed" "925.38" + "flags" + { + "primary_attack" "1" + "explosive" "1" + "underwater" "1" + "weapon_fires_projectile" "1" + } + } + "tf_weapon_flamethrower" + { + "slot" "0" + "id" "21" + "minPrimDist" "0.0" + "maxPrimDist" "400.0" + "m_iAmmoIndex" "1" + "m_iPreference" "3" + "flags" + { + "primary_attack" "1" + "melee" "1" + "hold_attack" "1" + "special" "1" + "can_deflect_rockets" "1" + } + } + "tf_weapon_pistol" + { + "slot" "1" + "id" "22" + "minPrimDist" "0.0" + "maxPrimDist" "2000.0" + "m_iAmmoIndex" "2" + "m_iPreference" "1" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "can_kill_pipes" "1" + } + } + "tf_weapon_pistol_scout" + { + "slot" "1" + "id" "23" + "minPrimDist" "0.0" + "maxPrimDist" "1800.0" + "m_iAmmoIndex" "2" + "m_iPreference" "2" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "can_kill_pipes" "1" + } + } + "tf_weapon_revolver" + { + "slot" "1" + "id" "24" + "minPrimDist" "0.0" + "maxPrimDist" "1400.0" + "m_iAmmoIndex" "2" + "m_iPreference" "1" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "can_kill_pipes" "1" + } + } + "tf_weapon_drg_pomson" + { + "slot" "0" + "id" "25" + "minPrimDist" "0.0" + "maxPrimDist" "800.0" + "m_iAmmoIndex" "0" + "m_iPreference" "2" + "m_fProjSpeed" "1200.0" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "weapon_fires_projectile" "1" + } + } + "tf_weapon_shotgun" + { + "slot" "1" + "id" "26" + "minPrimDist" "0.0" + "maxPrimDist" "500.0" + "m_iAmmoIndex" "2" + "m_iPreference" "2" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "can_kill_pipes" "1" + } + } + "tf_weapon_sentry_revenge" + { + "slot" "0" + "id" "27" + "minPrimDist" "0.0" + "maxPrimDist" "800.0" + "m_iAmmoIndex" "1" + "m_iPreference" "2" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "can_kill_pipes" "1" + } + } + "tf_weapon_builder" + { + "slot" "3" + "id" "28" + "minPrimDist" "0.0" + "maxPrimDist" "100.0" + "m_iAmmoIndex" "0" + "m_iPreference" "1" + } + "tf_weapon_medigun" + { + "slot" "1" + "id" "29" + "minPrimDist" "0.0" + "maxPrimDist" "100.0" + "m_iAmmoIndex" "0" + "m_iPreference" "1" + } + "tf_weapon_invis" + { + "slot" "3" + "id" "30" + "minPrimDist" "0.0" + "maxPrimDist" "100.0" + "m_iAmmoIndex" "0" + "m_iPreference" "1" + } + "tf_weapon_flaregun" + { + "slot" "1" + "id" "31" + "minPrimDist" "0.0" + "maxPrimDist" "1600.0" + "m_iAmmoIndex" "2" + "m_iPreference" "2" + "m_fProjSpeed" "2000.0" + "flags" + { + "primary_attack" "1" + "weapon_fires_projectile" "1" + } + } + "tf_weapon_buff_item" + { + "slot" "1" + "id" "32" + "minPrimDist" "0.0" + "maxPrimDist" "9000.0" + "m_iAmmoIndex" "0" + "m_iPreference" "1" + } + "obj_sentrygun" + { + "slot" "3" + "id" "33" + "minPrimDist" "0.0" + "maxPrimDist" "0.0" + "m_iAmmoIndex" "0" + "m_iPreference" "0" + } + "saxxy" + { + "slot" "2" + "id" "34" + "minPrimDist" "0.0" + "maxPrimDist" "150.0" + "m_iAmmoIndex" "0" + "m_iPreference" "1" + "flags" + { + "primary_attack" "1" + "melee" "1" + "underwater" "1" + } + } + "tf_weapon_bat_wood" + { + "slot" "2" + "id" "35" + "minPrimDist" "0.0" + "maxPrimDist" "1500.0" + "m_iAmmoIndex" "0" + "m_iPreference" "2" + "m_fProjSpeed" "3000.0" + "flags" + { + "primary_attack" "1" + "melee" "1" + "underwater" "1" + "weapon_fires_projectile" "1" + } + } + "tf_weapon_lunchbox_drink" + { + "slot" "1" + "id" "36" + "minPrimDist" "0.0" + "maxPrimDist" "180.0" + "m_iAmmoIndex" "0" + "m_iPreference" "1" + } + "tf_weapon_compound_bow" + { + "slot" "0" + "id" "37" + "minPrimDist" "0.0" + "maxPrimDist" "2500.0" + "m_iAmmoIndex" "1" + "m_iPreference" "3" + "m_fProjSpeed" "2600.0" + "flags" + { + "primary_attack" "1" + "weapon_fires_projectile" "1" + } + } + "tf_weapon_jar" + { + "slot" "1" + "id" "38" + "minPrimDist" "180.0" + "maxPrimDist" "1000.0" + "m_iAmmoIndex" "2" + "m_iPreference" "4" + "m_fProjSpeed" "1017.9" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "weapon_fires_projectile" "1" + } + } + "tf_weapon_bat_fish" + { + "slot" "2" + "id" "39" + "minPrimDist" "0.0" + "maxPrimDist" "180.0" + "m_iAmmoIndex" "0" + "m_iPreference" "1" + "flags" + { + "primary_attack" "1" + "melee" "1" + "underwater" "1" + } + } + "tf_weapon_rocketlauncher_directhit" + { + "slot" "0" + "id" "40" + "minPrimDist" "200.0" + "maxPrimDist" "4096.0" + "m_iAmmoIndex" "1" + "m_iPreference" "3" + "m_fProjSpeed" "1980.0" + "flags" + { + "primary_attack" "1" + "explosive" "1" + "underwater" "1" + "weapon_fires_projectile" "1" + } + } + "tf_weapon_sword" + { + "slot" "2" + "id" "41" + "minPrimDist" "0.0" + "maxPrimDist" "210.0" + "m_iAmmoIndex" "0" + "m_iPreference" "1" + "flags" + { + "primary_attack" "1" + "melee" "1" + "underwater" "1" + } + } + "tf_weapon_katana" + { + "slot" "2" + "id" "42" + "minPrimDist" "0.0" + "maxPrimDist" "210.0" + "m_iAmmoIndex" "0" + "m_iPreference" "1" + "flags" + { + "primary_attack" "1" + "melee" "1" + "underwater" "1" + } + } + "tf_weapon_particle_cannon" + { + "slot" "0" + "id" "43" + "minPrimDist" "200.0" + "maxPrimDist" "4096.0" + "m_iAmmoIndex" "0" + "m_iPreference" "3" + "m_fProjSpeed" "1100.0" + "flags" + { + "primary_attack" "1" + "explosive" "1" + "underwater" "1" + "weapon_fires_projectile" "1" + } + } + "tf_weapon_crossbow" + { + "slot" "0" + "id" "44" + "minPrimDist" "180.0" + "maxPrimDist" "4000.0" + "m_iAmmoIndex" "1" + "m_iPreference" "3" + "m_fProjSpeed" "2400.0" + "flags" + { + "primary_attack" "1" + "weapon_fires_projectile" "1" + } + } + "tf_weapon_cleaver" + { + "slot" "1" + "id" "45" + "minPrimDist" "800.0" + "maxPrimDist" "1500.0" + "m_iAmmoIndex" "2" + "m_iPreference" "4" + "m_fProjSpeed" "3000.0" + "flags" + { + "primary_attack" "1" + "weapon_fires_projectile" "1" + } + } + "tf_weapon_bat_giftwrap" + { + "slot" "2" + "id" "46" + "minPrimDist" "0.0" + "maxPrimDist" "1500.0" + "m_iAmmoIndex" "0" + "m_iPreference" "2" + "m_fProjSpeed" "3000.0" + "flags" + { + "primary_attack" "1" + "melee" "1" + "underwater" "1" + "weapon_fires_projectile" "1" + } + } + "tf_weapon_raygun" + { + "slot" "1" + "id" "47" + "minPrimDist" "0.0" + "maxPrimDist" "2000.0" + "m_iAmmoIndex" "0" + "m_iPreference" "2" + "m_fProjSpeed" "1200.0" + "flags" + { + "primary_attack" "1" + "weapon_fires_projectile" "1" + } + } + "tf_weapon_pep_brawler_blaster" + { + "slot" "0" + "id" "48" + "minPrimDist" "0.0" + "maxPrimDist" "800.0" + "m_iAmmoIndex" "1" + "m_iPreference" "3" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "can_kill_pipes" "1" + } + } + "tf_weapon_soda_popper" + { + "slot" "0" + "id" "49" + "minPrimDist" "0.0" + "maxPrimDist" "800.0" + "m_iAmmoIndex" "1" + "m_iPreference" "3" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "can_kill_pipes" "1" + } + } + "tf_weapon_handgun_scout_primary" + { + "slot" "0" + "id" "50" + "minPrimDist" "0.0" + "maxPrimDist" "1600.0" + "m_iAmmoIndex" "1" + "m_iPreference" "3" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "can_kill_pipes" "1" + "has_melee_secondary" "1" + } + } + "tf_weapon_handgun_scout_secondary" + { + "slot" "1" + "id" "51" + "minPrimDist" "0.0" + "maxPrimDist" "2000.0" + "m_iAmmoIndex" "2" + "m_iPreference" "2" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "can_kill_pipes" "1" + } + } + "tf_weapon_rocketlauncher_airstrike" + { + "slot" "0" + "id" "52" + "minPrimDist" "200.0" + "maxPrimDist" "4096.0" + "m_iAmmoIndex" "1" + "m_iPreference" "3" + "m_fProjSpeed" "1100.0" + "flags" + { + "primary_attack" "1" + "explosive" "1" + "underwater" "1" + "weapon_fires_projectile" "1" + } + } + "tf_weapon_stickbomb" + { + "slot" "2" + "id" "53" + "minPrimDist" "0.0" + "maxPrimDist" "180.0" + "m_iAmmoIndex" "0" + "m_iPreference" "1" + "flags" + { + "primary_attack" "1" + "melee" "1" + "underwater" "1" + } + } + "tf_weapon_rocketlauncher_fireball" + { + "slot" "0" + "id" "54" + "minPrimDist" "0.0" + "maxPrimDist" "600.0" + "m_iAmmoIndex" "1" + "m_iPreference" "3" + "m_fProjSpeed" "3000.0" + "flags" + { + "primary_attack" "1" + "melee" "1" + "hold_attack" "1" + "special" "1" + "can_deflect_rockets" "1" + "weapon_fires_projectile" "1" + } + } + "tf_weapon_flaregun_revenge" + { + "slot" "1" + "id" "55" + "minPrimDist" "0.0" + "maxPrimDist" "1600.0" + "m_iAmmoIndex" "0" + "m_iPreference" "2" + "m_fProjSpeed" "3000.0" + "flags" + { + "primary_attack" "1" + "weapon_fires_projectile" "1" + } + } + "tf_weapon_breakable_sign" + { + "slot" "2" + "id" "56" + "minPrimDist" "0.0" + "maxPrimDist" "180.0" + "m_iAmmoIndex" "0" + "m_iPreference" "1" + "flags" + { + "primary_attack" "1" + "melee" "1" + "underwater" "1" + } + } + "tf_weapon_slap" + { + "slot" "2" + "id" "57" + "minPrimDist" "0.0" + "maxPrimDist" "180.0" + "m_iAmmoIndex" "0" + "m_iPreference" "1" + "flags" + { + "primary_attack" "1" + "melee" "1" + "underwater" "1" + } + } + "tf_weapon_shotgun_building_rescue" + { + "slot" "0" + "id" "58" + "minPrimDist" "0.0" + "maxPrimDist" "2000.0" + "m_iAmmoIndex" "1" + "m_iPreference" "2" + "m_fProjSpeed" "2400.0" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "weapon_fires_projectile" "1" + } + } + "tf_weapon_jar_milk" + { + "slot" "1" + "id" "59" + "minPrimDist" "800.0" + "maxPrimDist" "1500.0" + "m_iAmmoIndex" "2" + "m_iPreference" "4" + "m_fProjSpeed" "1019.9" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "weapon_fires_projectile" "1" + } + } + "tf_weapon_jar_gas" + { + "slot" "1" + "id" "60" + "minPrimDist" "400.0" + "maxPrimDist" "1000.0" + "m_iAmmoIndex" "2" + "m_iPreference" "4" + "m_fProjSpeed" "2009.2" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "weapon_fires_projectile" "1" + } + } + "tf_weapon_mechanical_arm" + { + "slot" "1" + "id" "61" + "minPrimDist" "0.0" + "maxPrimDist" "400.0" + "m_iAmmoIndex" "3" + "m_iPreference" "3" + "flags" + { + "primary_attack" "1" + "can_kill_pipes" "1" + "can_deflect_rockets" "1" + } + } + "tf_weapon_grapplinghook" + { + "slot" "6" + "id" "62" + "minPrimDist" "0.0" + "maxPrimDist" "9000.0" + "m_iAmmoIndex" "0" + "m_iPreference" "1" + "m_fProjSpeed" "1500.0" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "hold_attack" "1" + "weapon_fires_projectile" "1" + } + } + "tf_weapon_spellbook" + { + "slot" "6" + "id" "63" + "minPrimDist" "0.0" + "maxPrimDist" "9000.0" + "m_iAmmoIndex" "0" + "m_iPreference" "1" + "m_fProjSpeed" "1019.8" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "weapon_fires_projectile" "1" + } + } + "tf_weapon_charged_smg" + { + "slot" "1" + "id" "64" + "minPrimDist" "0.0" + "maxPrimDist" "1000.0" + "m_iAmmoIndex" "2" + "m_iPreference" "4" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "can_kill_pipes" "1" + } + } + "tf_weapon_lunchbox" + { + "slot" "1" + "id" "65" + "minPrimDist" "0.0" + "maxPrimDist" "0.0" + "m_iAmmoIndex" "2" + "m_iPreference" "0" + } + "tf_weapon_laser_pointer" + { + "slot" "1" + "id" "66" + "minPrimDist" "180.0" + "maxPrimDist" "4096.0" + "m_iAmmoIndex" "2" + "m_iPreference" "1" + "flags" + { + "primary_attack" "1" + "hold_attack" "1" + } + } + "tf_weapon_sniperrifle_decap" + { + "slot" "0" + "id" "67" + "minPrimDist" "180.0" + "maxPrimDist" "4096.0" + "m_iAmmoIndex" "1" + "m_iPreference" "3" + "flags" + { + "primary_attack" "1" + "has_scope" "1" + } + } + } + "DOD" + { + "weapon_amerknife" + { + "slot" "1" + "id" "0" + "minPrimDist" "0.0" + "maxPrimDist" "100.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "1" + "flags" + { + "primary_attack" "1" + "melee" "1" + "underwater" "1" + } + } + "weapon_spade" + { + "slot" "1" + "id" "1" + "minPrimDist" "0.0" + "maxPrimDist" "100.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "1" + "flags" + { + "primary_attack" "1" + "melee" "1" + "underwater" "1" + } + } + "weapon_colt" + { + "slot" "2" + "id" "2" + "minPrimDist" "0.0" + "maxPrimDist" "800.0" + "m_iAmmoIndex" "1" + "m_iPreference" "2" + "flags" + { + "primary_attack" "1" + "underwater" "1" + } + } + "weapon_p38" + { + "slot" "2" + "id" "3" + "minPrimDist" "0.0" + "maxPrimDist" "800.0" + "m_iAmmoIndex" "2" + "m_iPreference" "2" + "flags" + { + "primary_attack" "1" + "underwater" "1" + } + } + "weapon_m1carbine" + { + "slot" "3" + "id" "4" + "minPrimDist" "0.0" + "maxPrimDist" "1600.0" + "m_iAmmoIndex" "6" + "m_iPreference" "4" + "flags" + { + "primary_attack" "1" + } + } + "weapon_c96" + { + "slot" "3" + "id" "5" + "minPrimDist" "0.0" + "maxPrimDist" "1600.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "4" + "flags" + { + "primary_attack" "1" + } + } + "weapon_garand" + { + "slot" "3" + "id" "6" + "minPrimDist" "0.0" + "maxPrimDist" "1600.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "3" + "flags" + { + "primary_attack" "1" + "is_zoomable" "1" + } + } + "weapon_k98" + { + "slot" "3" + "id" "7" + "minPrimDist" "0.0" + "maxPrimDist" "1600.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "3" + "flags" + { + "primary_attack" "1" + "is_zoomable" "1" + } + } + "weapon_thompson" + { + "slot" "3" + "id" "8" + "minPrimDist" "0.0" + "maxPrimDist" "900.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "3" + "flags" + { + "primary_attack" "1" + "has_melee_secondary" "1" + } + } + "weapon_mp40" + { + "slot" "3" + "id" "9" + "minPrimDist" "0.0" + "maxPrimDist" "1600.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "4" + "flags" + { + "primary_attack" "1" + "has_melee_secondary" "1" + } + } + "weapon_bar" + { + "slot" "3" + "id" "10" + "minPrimDist" "0.0" + "maxPrimDist" "1600.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "3" + "flags" + { + "primary_attack" "1" + } + } + "weapon_mp44" + { + "slot" "3" + "id" "11" + "minPrimDist" "0.0" + "maxPrimDist" "1600.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "3" + "flags" + { + "primary_attack" "1" + } + } + "weapon_spring" + { + "slot" "3" + "id" "12" + "minPrimDist" "0.0" + "maxPrimDist" "3200.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "3" + "flags" + { + "primary_attack" "1" + "is_zoomable" "1" + "cant_be_fired_unzoomed_undeployed_dods" "1" + "has_scope" "1" + } + } + "weapon_k98_scoped" + { + "slot" "3" + "id" "13" + "minPrimDist" "0.0" + "maxPrimDist" "3200.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "4" + "flags" + { + "primary_attack" "1" + "is_zoomable" "1" + "cant_be_fired_unzoomed_undeployed_dods" "1" + "has_scope" "1" + } + } + "weapon_30cal" + { + "slot" "3" + "id" "14" + "minPrimDist" "0.0" + "maxPrimDist" "2000.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "4" + "flags" + { + "primary_attack" "1" + "is_deployable_dods" "1" + "has_high_recoil_dods" "1" + } + } + "weapon_mg42" + { + "slot" "3" + "id" "15" + "minPrimDist" "0.0" + "maxPrimDist" "2000.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "4" + "flags" + { + "primary_attack" "1" + "is_deployable_dods" "1" + "has_high_recoil_dods" "1" + } + } + "weapon_bazooka" + { + "slot" "3" + "id" "16" + "minPrimDist" "500.0" + "maxPrimDist" "3200.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "5" + "m_fProjSpeed" "1300.0" + "flags" + { + "primary_attack" "1" + "explosive" "1" + "is_deployable_dods" "1" + "cant_be_fired_unzoomed_undeployed_dods" "1" + "weapon_fires_projectile" "1" + } + } + "weapon_pschreck" + { + "slot" "3" + "id" "17" + "minPrimDist" "500.0" + "maxPrimDist" "3200.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "5" + "m_fProjSpeed" "1300.0" + "flags" + { + "primary_attack" "1" + "explosive" "1" + "is_deployable_dods" "1" + "cant_be_fired_unzoomed_undeployed_dods" "1" + "weapon_fires_projectile" "1" + } + } + "weapon_riflegren_us" + { + "slot" "3" + "id" "18" + "minPrimDist" "500.0" + "maxPrimDist" "1800.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "4" + "flags" + { + "primary_attack" "1" + "has_explosive_secondary" "1" + } + } + "weapon_riflegren_ger" + { + "slot" "3" + "id" "19" + "minPrimDist" "500.0" + "maxPrimDist" "1800.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "4" + "flags" + { + "primary_attack" "1" + "has_explosive_secondary" "1" + } + } + "weapon_frag_us" + { + "slot" "3" + "id" "20" + "minPrimDist" "0.0" + "maxPrimDist" "1200.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "1" + "flags" + { + "explosive" "1" + "is_grenade" "1" + "weapon_fires_projectile" "1" + } + } + "weapon_frag_ger" + { + "slot" "3" + "id" "21" + "minPrimDist" "0.0" + "maxPrimDist" "1200.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "1" + "flags" + { + "explosive" "1" + "is_grenade" "1" + "weapon_fires_projectile" "1" + } + } + "weapon_smoke_us" + { + "slot" "3" + "id" "22" + "minPrimDist" "0.0" + "maxPrimDist" "1200.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "1" + "flags" + { + "is_grenade" "1" + "weapon_fires_projectile" "1" + } + } + "weapon_smoke_ger" + { + "slot" "3" + "id" "23" + "minPrimDist" "0.0" + "maxPrimDist" "1200.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "1" + "flags" + { + "is_grenade" "1" + "weapon_fires_projectile" "1" + } + } + "weapon_basebomb" + { + "slot" "3" + "id" "24" + "minPrimDist" "0.0" + "maxPrimDist" "0.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "1" + } + } + "HL2DM" + { + "weapon_pistol" + { + "slot" "2" + "id" "0" + "minPrimDist" "0.0" + "maxPrimDist" "1000.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "1" + "flags" + { + "primary_attack" "1" + "underwater" "1" + } + } + "weapon_crowbar" + { + "slot" "1" + "id" "1" + "minPrimDist" "0.0" + "maxPrimDist" "128.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "1" + "flags" + { + "primary_attack" "1" + "melee" "1" + "underwater" "1" + } + } + "weapon_357" + { + "slot" "2" + "id" "2" + "minPrimDist" "0.0" + "maxPrimDist" "768.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "2" + "flags" + { + "primary_attack" "1" + } + } + "weapon_smg1" + { + "slot" "3" + "id" "3" + "minPrimDist" "0.0" + "maxPrimDist" "1400.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "2" + "flags" + { + "primary_attack" "1" + "secondary_attack" "1" + } + } + "weapon_ar2" + { + "slot" "2" + "id" "4" + "minPrimDist" "0.0" + "maxPrimDist" "1400.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "3" + "flags" + { + "primary_attack" "1" + "secondary_attack" "1" + } + } + "weapon_frag" + { + "slot" "1" + "id" "5" + "minPrimDist" "0.0" + "maxPrimDist" "180.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "1" + "flags" + { + "explosive" "1" + "is_grenade" "1" + } + } + "weapon_stunstick" + { + "slot" "2" + "id" "6" + "minPrimDist" "0.0" + "maxPrimDist" "128.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "1" + "flags" + { + "primary_attack" "1" + "melee" "1" + "underwater" "1" + } + } + "weapon_crossbow" + { + "slot" "3" + "id" "7" + "minPrimDist" "0.0" + "maxPrimDist" "2000.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "2" + "flags" + { + "primary_attack" "1" + "underwater" "1" + "has_scope" "1" + } + } + "weapon_rpg" + { + "slot" "2" + "id" "8" + "minPrimDist" "400.0" + "maxPrimDist" "2000.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "3" + "m_fProjSpeed" "1000.0" + "flags" + { + "primary_attack" "1" + "explosive" "1" + "underwater" "1" + "weapon_fires_projectile" "1" + } + } + "weapon_slam" + { + "slot" "1" + "id" "9" + "minPrimDist" "0.0" + "maxPrimDist" "180.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "1" + "flags" + { + "explosive" "1" + } + } + "weapon_shotgun" + { + "slot" "2" + "id" "10" + "minPrimDist" "0.0" + "maxPrimDist" "768.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "2" + "flags" + { + "primary_attack" "1" + } + } + "weapon_physcannon" + { + "slot" "1" + "id" "11" + "minPrimDist" "0.0" + "maxPrimDist" "768.0" + "m_iAmmoIndex" "-1" + "m_iPreference" "4" + "flags" + { + "primary_attack" "1" + "is_grav_gun" "1" + } + } + } +} diff --git a/package/rcbot2.vdf b/package/rcbot2.vdf new file mode 100644 index 000000000..07d355c7c --- /dev/null +++ b/package/rcbot2.vdf @@ -0,0 +1,6 @@ +"Metamod Plugin" +{ + "alias" "rcbot2" + "file" "addons/rcbot2/bin/RCBot2Meta" + "rcbot2path" "addons/rcbot2/" +} diff --git a/premake/bms.lua b/premake/bms.lua new file mode 100644 index 000000000..108a5c244 --- /dev/null +++ b/premake/bms.lua @@ -0,0 +1,54 @@ +project "RCBot2-BMS" + language "C++" + kind "SharedLib" + cppdialect "C++17" + targetname "rcbot2.2.bms" + defines { "SOURCE_ENGINE=11" } + + local Dir_SDK = "hl2sdk-bms" + + includedirs { + path.join(Path_HL2SDKROOT, Dir_SDK, "public"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "engine"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "mathlib"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "vstdlib"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "tier0"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "tier1"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "toolframework"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "game", "server"), + path.join(Path_HL2SDKROOT, Dir_SDK, "game", "shared"), + path.join(Path_HL2SDKROOT, Dir_SDK, "game", "server"), + path.join(Path_HL2SDKROOT, Dir_SDK, "common"), + path.join(Path_SM, "public"), + path.join(Path_SM, "public", "extensions"), + path.join(Path_SM, "sourcepawn", "include"), + path.join(Path_SM, "public", "amtl", "amtl"), + path.join(Path_SM, "public", "amtl"), + path.join(Path_MMS, "core"), + path.join(Path_MMS, "core", "sourcehook"), + "../", + "../rcbot", + "../utils/RCBot2_meta", + "../versioning/", + "../build/includes/", + "../sm_ext/", + } + files { + "../loader/**.cpp", + "../rcbot/**.h", + "../rcbot/**.cpp", + "../rcbot_subcmds/**.h", + "../rcbot_subcmds/**.cpp", + "../sm_ext/**.h", + "../sm_ext/**.cpp", + "../utils/RCBot2_meta/**.h", + "../utils/RCBot2_meta/**.cpp", + "../versioning/**.h", + "../versioning/**.cpp", + } + + filter { "system:Linux" } + defines { "NO_HOOK_MALLOC", "NO_MALLOC_OVERRIDE" } + + filter {} + defines { "RCBOT_MAXPLAYERS=65", "SM_EXT" } diff --git a/premake/common_sdk.lua b/premake/common_sdk.lua new file mode 100644 index 000000000..e38f2de52 --- /dev/null +++ b/premake/common_sdk.lua @@ -0,0 +1,4 @@ +defines { "RAD_TELEMETRY_DISABLED", "GAME_DLL", "SE_BLADE=19", "SE_BMS=11", "SE_CONTAGION=15", "SE_CS2=25", "SE_CSGO=23", "SE_CSS=6", "SE_DARKMESSIAH=2", "SE_DODS=8" } +defines { "SE_ORANGEBOX=3", "SE_PORTAL2=18", "SE_PVKII=10", "SE_SDK2013=9", "SE_ALIENSWARM=17", "SE_TF2=12" } +defines { "SE_DOI=21", "SE_DOTA=24", "SE_EPISODEONE=1", "SE_EYE=5", "SE_HL2DM=7", "SE_INSURGENCY=20", "SE_LEFT4DEAD=13" } +defines { "SE_LEFT4DEAD2=16", "SE_MCV=22", "SE_MOCK=26", "SE_NUCLEARDAWN=14", "SE_DEADLOCK=27" } \ No newline at end of file diff --git a/premake/css.lua b/premake/css.lua new file mode 100644 index 000000000..097252929 --- /dev/null +++ b/premake/css.lua @@ -0,0 +1,54 @@ +project "RCBot2-CSS" + language "C++" + kind "SharedLib" + cppdialect "C++17" + targetname "rcbot2.2.css" + defines { "SOURCE_ENGINE=6" } + + local Dir_SDK = "hl2sdk-css" + + includedirs { + path.join(Path_HL2SDKROOT, Dir_SDK, "public"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "engine"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "mathlib"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "vstdlib"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "tier0"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "tier1"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "toolframework"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "game", "server"), + path.join(Path_HL2SDKROOT, Dir_SDK, "game", "shared"), + path.join(Path_HL2SDKROOT, Dir_SDK, "game", "server"), + path.join(Path_HL2SDKROOT, Dir_SDK, "common"), + path.join(Path_SM, "public"), + path.join(Path_SM, "public", "extensions"), + path.join(Path_SM, "sourcepawn", "include"), + path.join(Path_SM, "public", "amtl", "amtl"), + path.join(Path_SM, "public", "amtl"), + path.join(Path_MMS, "core"), + path.join(Path_MMS, "core", "sourcehook"), + "../", + "../rcbot", + "../utils/RCBot2_meta", + "../versioning/", + "../build/includes/", + "../sm_ext/", + } + files { + "../loader/**.cpp", + "../rcbot/**.h", + "../rcbot/**.cpp", + "../rcbot_subcmds/**.h", + "../rcbot_subcmds/**.cpp", + "../sm_ext/**.h", + "../sm_ext/**.cpp", + "../utils/RCBot2_meta/**.h", + "../utils/RCBot2_meta/**.cpp", + "../versioning/**.h", + "../versioning/**.cpp", + } + + filter { "system:Linux" } + defines { "NO_HOOK_MALLOC", "NO_MALLOC_OVERRIDE" } + + filter {} + defines { "RCBOT_MAXPLAYERS=65", "SM_EXT" } diff --git a/premake/dods.lua b/premake/dods.lua new file mode 100644 index 000000000..0815531f4 --- /dev/null +++ b/premake/dods.lua @@ -0,0 +1,54 @@ +project "RCBot2-DODS" + language "C++" + kind "SharedLib" + cppdialect "C++17" + targetname "rcbot2.2.dods" + defines { "SOURCE_ENGINE=8" } + + local Dir_SDK = "hl2sdk-dods" + + includedirs { + path.join(Path_HL2SDKROOT, Dir_SDK, "public"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "engine"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "mathlib"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "vstdlib"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "tier0"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "tier1"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "toolframework"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "game", "server"), + path.join(Path_HL2SDKROOT, Dir_SDK, "game", "shared"), + path.join(Path_HL2SDKROOT, Dir_SDK, "game", "server"), + path.join(Path_HL2SDKROOT, Dir_SDK, "common"), + path.join(Path_SM, "public"), + path.join(Path_SM, "public", "extensions"), + path.join(Path_SM, "sourcepawn", "include"), + path.join(Path_SM, "public", "amtl", "amtl"), + path.join(Path_SM, "public", "amtl"), + path.join(Path_MMS, "core"), + path.join(Path_MMS, "core", "sourcehook"), + "../", + "../rcbot", + "../utils/RCBot2_meta", + "../versioning/", + "../build/includes/", + "../sm_ext/", + } + files { + "../loader/**.cpp", + "../rcbot/**.h", + "../rcbot/**.cpp", + "../rcbot_subcmds/**.h", + "../rcbot_subcmds/**.cpp", + "../sm_ext/**.h", + "../sm_ext/**.cpp", + "../utils/RCBot2_meta/**.h", + "../utils/RCBot2_meta/**.cpp", + "../versioning/**.h", + "../versioning/**.cpp", + } + + filter { "system:Linux" } + defines { "NO_HOOK_MALLOC", "NO_MALLOC_OVERRIDE" } + + filter {} + defines { "RCBOT_MAXPLAYERS=65", "OVERRIDE_RUNCMD", "SM_EXT" } diff --git a/premake/episode1.lua b/premake/episode1.lua new file mode 100644 index 000000000..976fc5c00 --- /dev/null +++ b/premake/episode1.lua @@ -0,0 +1,52 @@ +project "RCBot2-EPISODE1" + language "C++" + kind "SharedLib" + cppdialect "C++17" + targetname "rcbot2.2.ep1" + defines { "SOURCE_ENGINE=1" } + + local Dir_SDK = "hl2sdk-episode1" + + includedirs { + path.join(Path_HL2SDKROOT, Dir_SDK, "public"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "engine"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "mathlib"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "vstdlib"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "tier0"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "tier1"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "dlls"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "toolframework"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "game", "server"), + path.join(Path_HL2SDKROOT, Dir_SDK, "game_shared"), + path.join(Path_HL2SDKROOT, Dir_SDK, "game", "server"), + path.join(Path_HL2SDKROOT, Dir_SDK, "common"), + path.join(Path_SM, "public"), + path.join(Path_SM, "public", "extensions"), + path.join(Path_SM, "sourcepawn", "include"), + path.join(Path_SM, "public", "amtl", "amtl"), + path.join(Path_SM, "public", "amtl"), + path.join(Path_MMS, "core"), + path.join(Path_MMS, "core", "sourcehook"), + "../", + "../rcbot", + "../utils/RCBot2_meta", + "../versioning/", + "../build/includes/", + "../sm_ext/", + } + files { + "../loader/**.cpp", + "../rcbot/**.h", + "../rcbot/**.cpp", + "../rcbot_subcmds/**.h", + "../rcbot_subcmds/**.cpp", + "../sm_ext/**.h", + "../sm_ext/**.cpp", + "../utils/RCBot2_meta/**.h", + "../utils/RCBot2_meta/**.cpp", + "../versioning/**.h", + "../versioning/**.cpp", + } + + filter {} + defines { "RCBOT_MAXPLAYERS=65", "SM_EXT" } \ No newline at end of file diff --git a/premake/hl2dm.lua b/premake/hl2dm.lua new file mode 100644 index 000000000..0347ec999 --- /dev/null +++ b/premake/hl2dm.lua @@ -0,0 +1,54 @@ +project "RCBot2-HL2DM" + language "C++" + kind "SharedLib" + cppdialect "C++17" + targetname "rcbot2.2.hl2dm" + defines { "SOURCE_ENGINE=7" } + + local Dir_SDK = "hl2sdk-hl2dm" + + includedirs { + path.join(Path_HL2SDKROOT, Dir_SDK, "public"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "engine"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "mathlib"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "vstdlib"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "tier0"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "tier1"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "toolframework"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "game", "server"), + path.join(Path_HL2SDKROOT, Dir_SDK, "game", "shared"), + path.join(Path_HL2SDKROOT, Dir_SDK, "game", "server"), + path.join(Path_HL2SDKROOT, Dir_SDK, "common"), + path.join(Path_SM, "public"), + path.join(Path_SM, "public", "extensions"), + path.join(Path_SM, "sourcepawn", "include"), + path.join(Path_SM, "public", "amtl", "amtl"), + path.join(Path_SM, "public", "amtl"), + path.join(Path_MMS, "core"), + path.join(Path_MMS, "core", "sourcehook"), + "../", + "../rcbot", + "../utils/RCBot2_meta", + "../versioning/", + "../build/includes/", + "../sm_ext/", + } + files { + "../loader/**.cpp", + "../rcbot/**.h", + "../rcbot/**.cpp", + "../rcbot_subcmds/**.h", + "../rcbot_subcmds/**.cpp", + "../sm_ext/**.h", + "../sm_ext/**.cpp", + "../utils/RCBot2_meta/**.h", + "../utils/RCBot2_meta/**.cpp", + "../versioning/**.h", + "../versioning/**.cpp", + } + + filter { "system:Linux" } + defines { "NO_HOOK_MALLOC", "NO_MALLOC_OVERRIDE" } + + filter {} + defines { "RCBOT_MAXPLAYERS=101", "SM_EXT" } diff --git a/premake/orangebox.lua b/premake/orangebox.lua new file mode 100644 index 000000000..eea1eb1bd --- /dev/null +++ b/premake/orangebox.lua @@ -0,0 +1,51 @@ +project "RCBot2-ORANGEBOX" + language "C++" + kind "SharedLib" + cppdialect "C++17" + targetname "rcbot2.2.ep2" + defines { "SOURCE_ENGINE=3" } + + local Dir_SDK = "hl2sdk-orangebox" + + includedirs { + path.join(Path_HL2SDKROOT, Dir_SDK, "public"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "engine"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "mathlib"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "vstdlib"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "tier0"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "tier1"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "toolframework"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "game", "server"), + path.join(Path_HL2SDKROOT, Dir_SDK, "game", "shared"), + path.join(Path_HL2SDKROOT, Dir_SDK, "game", "server"), + path.join(Path_HL2SDKROOT, Dir_SDK, "common"), + path.join(Path_SM, "public"), + path.join(Path_SM, "public", "extensions"), + path.join(Path_SM, "sourcepawn", "include"), + path.join(Path_SM, "public", "amtl", "amtl"), + path.join(Path_SM, "public", "amtl"), + path.join(Path_MMS, "core"), + path.join(Path_MMS, "core", "sourcehook"), + "../", + "../rcbot", + "../utils/RCBot2_meta", + "../versioning/", + "../build/includes/", + "../sm_ext/", + } + files { + "../loader/**.cpp", + "../rcbot/**.h", + "../rcbot/**.cpp", + "../rcbot_subcmds/**.h", + "../rcbot_subcmds/**.cpp", + "../sm_ext/**.h", + "../sm_ext/**.cpp", + "../utils/RCBot2_meta/**.h", + "../utils/RCBot2_meta/**.cpp", + "../versioning/**.h", + "../versioning/**.cpp", + } + + filter {} + defines { "RCBOT_MAXPLAYERS=65", "SM_EXT" } \ No newline at end of file diff --git a/premake/sdk2013.lua b/premake/sdk2013.lua new file mode 100644 index 000000000..2ea8e54f1 --- /dev/null +++ b/premake/sdk2013.lua @@ -0,0 +1,54 @@ +project "RCBot2-SDK2013" + language "C++" + kind "SharedLib" + cppdialect "C++17" + targetname "rcbot2.2.sdk2013" + defines { "SOURCE_ENGINE=9" } + + local Dir_SDK = "hl2sdk-sdk2013" + + includedirs { + path.join(Path_HL2SDKROOT, Dir_SDK, "public"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "engine"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "mathlib"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "vstdlib"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "tier0"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "tier1"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "toolframework"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "game", "server"), + path.join(Path_HL2SDKROOT, Dir_SDK, "game", "shared"), + path.join(Path_HL2SDKROOT, Dir_SDK, "game", "server"), + path.join(Path_HL2SDKROOT, Dir_SDK, "common"), + path.join(Path_SM, "public"), + path.join(Path_SM, "public", "extensions"), + path.join(Path_SM, "sourcepawn", "include"), + path.join(Path_SM, "public", "amtl", "amtl"), + path.join(Path_SM, "public", "amtl"), + path.join(Path_MMS, "core"), + path.join(Path_MMS, "core", "sourcehook"), + "../", + "../rcbot", + "../utils/RCBot2_meta", + "../versioning/", + "../build/includes/", + "../sm_ext/", + } + files { + "../loader/**.cpp", + "../rcbot/**.h", + "../rcbot/**.cpp", + "../rcbot_subcmds/**.h", + "../rcbot_subcmds/**.cpp", + "../sm_ext/**.h", + "../sm_ext/**.cpp", + "../utils/RCBot2_meta/**.h", + "../utils/RCBot2_meta/**.cpp", + "../versioning/**.h", + "../versioning/**.cpp", + } + + filter { "system:Linux" } + defines { "NO_HOOK_MALLOC", "NO_MALLOC_OVERRIDE" } + + filter {} + defines { "RCBOT_MAXPLAYERS=65", "OVERRIDE_RUNCMD", "SM_EXT" } diff --git a/premake/tf2.lua b/premake/tf2.lua new file mode 100644 index 000000000..1dd4d8963 --- /dev/null +++ b/premake/tf2.lua @@ -0,0 +1,55 @@ +project "RCBot2-TF2" + language "C++" + kind "SharedLib" + cppdialect "C++17" + targetname "rcbot.2.tf2" + defines { "SOURCE_ENGINE=12" } + + local Dir_SDK = "hl2sdk-tf2" + + includedirs { + path.join(Path_HL2SDKROOT, Dir_SDK, "public"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "engine"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "mathlib"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "vstdlib"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "tier0"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "tier1"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "toolframework"), + path.join(Path_HL2SDKROOT, Dir_SDK, "public", "game", "server"), + path.join(Path_HL2SDKROOT, Dir_SDK, "game", "shared"), + path.join(Path_HL2SDKROOT, Dir_SDK, "game", "server"), + path.join(Path_HL2SDKROOT, Dir_SDK, "common"), + path.join(Path_SM, "public"), + path.join(Path_SM, "public", "extensions"), + path.join(Path_SM, "sourcepawn", "include"), + path.join(Path_SM, "public", "amtl", "amtl"), + path.join(Path_SM, "public", "amtl"), + path.join(Path_MMS, "core"), + path.join(Path_MMS, "core", "sourcehook"), + "../", + "../rcbot", + "../utils/RCBot2_meta", + "../versioning/", + "../build/includes/", + "../sm_ext/", + } + files { + "../loader/**.cpp", + "../rcbot/**.h", + "../rcbot/**.cpp", + "../rcbot_subcmds/**.h", + "../rcbot_subcmds/**.cpp", + "../sm_ext/**.h", + "../sm_ext/**.cpp", + "../utils/RCBot2_meta/**.h", + "../utils/RCBot2_meta/**.cpp", + "../versioning/**.h", + "../versioning/**.cpp", + } + + filter { "system:Linux" } + defines { "NO_HOOK_MALLOC", "NO_MALLOC_OVERRIDE" } + + filter {} + defines { "RCBOT_MAXPLAYERS=101", "SM_EXT" } + diff --git a/premake5.lua b/premake5.lua new file mode 100644 index 000000000..b49297df3 --- /dev/null +++ b/premake5.lua @@ -0,0 +1,194 @@ +-- +-- premake5 script for RCBot2 +-- Note: This script is for generating a visual studio solution for editing the source code, compiling should be done via AMBuild. +-- http://premake.github.io/ +-- + +local action = _ACTION or "" +local todir = "premake_build/" .. action + +newoption { + trigger = "hl2sdk-root", + value = "absolute path", + description = "Absolute path to the root folter that contains the HL2-SDKs", + category = "Paths" +} + +newoption { + trigger = "mms-path", + value = "absolute path", + description = "Absolute path to the root metamod-source folder", + category = "Paths" +} + +newoption { + trigger = "sm-path", + value = "absolute path", + description = "Absolute path to the root sourcemod folder", + category = "Paths" +} + +Path_HL2SDKROOT = "" +Path_SM = "" +Path_MMS = "" +g_Compiler = "" + +-- when "premake5 --help" is ran, _ACTION is NULL (nil) +if (_ACTION ~= nil) then + if (_OPTIONS["hl2sdk-root"] == nil) then + error("Failed to get path to HL2SDKs. Set path with --hl2sdk-root=path") + end + + if (_OPTIONS["mms-path"] == nil) then + error("Failed to get path to Metamod Source. Set path with --mms-path=path") + end + + if (_OPTIONS["sm-path"] == nil) then + error("Failed to get path to SourceMod. Set path with --sm-path=path") + end + + if (not os.isdir(_OPTIONS["hl2sdk-root"])) then + error("Failed to get path to HL2SDKs. Set path with --hl2sdk-root=path") + end + + if (not os.isdir(_OPTIONS["mms-path"])) then + error("Failed to get path to Metamod Source. Set path with --mms-path=path") + end + + if (not os.isdir(_OPTIONS["sm-path"])) then + error("Failed to get path to SourceMod. Set path with --sm-path=path") + end + + Path_HL2SDKROOT = path.normalize(_OPTIONS["hl2sdk-root"]) + Path_SM = path.normalize(_OPTIONS["sm-path"]) + Path_MMS = path.normalize(_OPTIONS["mms-path"]) +end + +-- check compiler +if os.host() == "windows" then + g_Compiler = "MSVC" + print("Microsoft C++ compiler selected.") +elseif os.host() == "linux" then + local cxx = os.getenv("CXX") + + if cxx == nil then + g_Compiler = "CLANG" + print("CXX env not set. Using clang.") + else + if string.startswith(cxx, "clang") then + g_Compiler = "CLANG" + print("Clang selected.") + else + g_Compiler = "GCC" + print("GCC selected.") + end + end +end + +workspace "rcbot2" + configurations { + "Debug", + "Release" + } + + platforms { + "Win32", + "Win64", + "Linux32", + "Linux64" + } + + location (todir) + + symbols "On" + exceptionhandling "On" + rtti "On" + stringpooling "On" + omitframepointer "Off" + vectorextensions "SSE2" + pic "On" + include("premake/common_sdk.lua") + + if g_Compiler == "MSVC" then + toolset "msc" + elseif g_Compiler == "CLANG" then + toolset "clang" + else + toolset "gcc" + end + + filter { "system:Windows" } + defines { "_CRT_SECURE_NO_DEPRECATE", "_CRT_SECURE_NO_WARNINGS", "_CRT_NONSTDC_NO_DEPRECATE", "_WINDOWS", "_ITERATOR_DEBUG_LEVEL=0" } + flags { "MultiProcessorCompile" } + characterset "MBCS" + staticruntime "on" + runtime "Release" + editandcontinue "off" + -- Disable macro redefinition warnings + disablewarnings { "4005"} + links { + "kernel32.lib", + "user32.lib", + "legacy_stdio_definitions.lib", + } + + -- Linux options shared for both GCC/Clang + filter { "system:Linux" } + defines { "LINUX", "_LINUX", "POSIX", "_FILE_OFFSET_BITS=64", "COMPILER_GCC" } + defines { "stricmp=strcasecmp", "_stricmp=strcasecmp", "_snprintf=snprintf", "_vsnprintf=vsnprintf", "HAVE_STDINT_H", "GNUC" } + buildoptions { + "-Wno-non-virtual-dtor", "-Wno-overloaded-virtual", "-Wno-register", "-Wno-varargs", "-Wno-array-bounds", "-Wno-unused", + "-Wno-null-dereference", "-Wno-delete-non-virtual-dtor", "-Wno-switch", "-Wno-expansion-to-defined", + } + -- disable prefixes for Linux + targetprefix "" + + -- Linux options for Clang only + filter { "system:linux", "toolset:clang" } + buildoptions { + "-Wno-implicit-exception-spec-mismatch", "-Wno-sometimes-uninitialized", "-Wno-inconsistent-missing-override", "-Wno-tautological-overlap-compare", + "-Wno-implicit-float-conversion", + } + + filter { "configurations:Debug" } + defines { "EXT_DEBUG" } + targetdir "build/bin/%{cfg.architecture}/debug" + optimize "Off" + + filter { "configurations:Release" } + defines { "NDEBUG" } + targetdir "build/bin/%{cfg.architecture}/release" + optimize "Full" + flags { "LinkTimeOptimization" } + visibility "Hidden" + + filter { "platforms:Win32" } + system "Windows" + architecture "x86" + defines { "WIN32", "COMPILER_MSVC", "COMPILER_MSVC32" } + + filter { "platforms:Win64" } + system "Windows" + architecture "x86_64" + defines { "WIN32", "WIN64", "COMPILER_MSVC", "COMPILER_MSVC64", "X64BITS" } + + filter { "platforms:Linux32" } + system "Linux" + architecture "x86" + + filter { "platforms:Linux64" } + system "Linux" + architecture "x86_64" + defines { "X64BITS" } + + -- reset filter + filter {} + +include("premake/tf2.lua") +include("premake/dods.lua") +include("premake/css.lua") +include("premake/bms.lua") +include("premake/sdk2013.lua") +include("premake/hl2dm.lua") +include("premake/orangebox.lua") +include("premake/episode1.lua") \ No newline at end of file diff --git a/game/server/worker_scientist.h b/product.version similarity index 100% rename from game/server/worker_scientist.h rename to product.version diff --git a/public/ATI_Compress.h b/public/ATI_Compress.h deleted file mode 100644 index 36460975d..000000000 --- a/public/ATI_Compress.h +++ /dev/null @@ -1,144 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// ATI Technologies Inc. -// 1 Commerce Valley Drive East -// Markham, Ontario -// CANADA L3T 7X6 -// -// File Name: ATI_Compress.h -// Description: A library to compress/decompress textures -// -// Copyright (c) 2004-2006 ATI Technologies Inc. -// -// Version: 1.4 -// -// Developer: Seth Sowerby -// Email: gputools.support@amd.com -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef ATI_COMPRESS -#define ATI_COMPRESS - -#define ATI_COMPRESS_VERSION_MAJOR 1 -#define ATI_COMPRESS_VERSION_MINOR 4 - -typedef unsigned long ATI_TC_DWORD; -typedef unsigned short ATI_TC_WORD; -typedef unsigned char ATI_TC_BYTE; - -#if defined(WIN32) || defined(_WIN64) -# define ATI_TC_API __cdecl -#else -# define ATI_TC_API -#endif - -#ifdef ATI_COMPRESS_INTERNAL_BUILD -#include "ATI_Compress_Internal.h" -#else // ATI_COMPRESS_INTERNAL_BUILD - -typedef enum -{ - ATI_TC_FORMAT_ARGB_8888, - ATI_TC_FORMAT_ARGB_2101010, - ATI_TC_FORMAT_ARGB_16, - ATI_TC_FORMAT_ARGB_16F, - ATI_TC_FORMAT_ARGB_32F, - ATI_TC_FORMAT_DXT1, - ATI_TC_FORMAT_DXT3, - ATI_TC_FORMAT_DXT5, - ATI_TC_FORMAT_DXT5_xGBR, - ATI_TC_FORMAT_DXT5_RxBG, - ATI_TC_FORMAT_DXT5_RBxG, - ATI_TC_FORMAT_DXT5_xRBG, - ATI_TC_FORMAT_DXT5_RGxB, - ATI_TC_FORMAT_DXT5_xGxR, - ATI_TC_FORMAT_ATI1N, - ATI_TC_FORMAT_ATI2N, - ATI_TC_FORMAT_ATI2N_XY, - ATI_TC_FORMAT_ATI2N_DXT5, - ATI_TC_FORMAT_MAX = ATI_TC_FORMAT_ATI2N_DXT5 -} ATI_TC_FORMAT; - -typedef struct _ATI_TC_CompressOptions -{ - ATI_TC_DWORD dwSize; /* Size of this structure */ - - /* Channel Weightings */ - /* With swizzled formats the weighting applies to the data within the specified channel */ - /* not the channel itself. */ - BOOL bUseChannelWeighting; - double fWeightingRed; /* Weighting of the Red or X Channel */ - double fWeightingGreen; /* Weighting of the Green or Y Channel */ - double fWeightingBlue; /* Weighting of the Blue or Z Channel */ - BOOL bUseAdaptiveWeighting; /* Adapt weighting on a per-block basis */ - BOOL bDXT1UseAlpha; - ATI_TC_BYTE nAlphaThreshold; -} ATI_TC_CompressOptions; -#endif // !ATI_COMPRESS_INTERNAL_BUILD - -typedef struct _ATI_TC_Texture -{ - ATI_TC_DWORD dwSize; /* Size of this structure */ - ATI_TC_DWORD dwWidth; /* Width of the texture */ - ATI_TC_DWORD dwHeight; /* Height of the texture */ - ATI_TC_DWORD dwPitch; /* Distance to start of next line - necessary only for uncompressed textures */ - ATI_TC_FORMAT format; /* Format of the texture */ - ATI_TC_DWORD dwDataSize; /* Size of the allocated texture data */ - ATI_TC_BYTE* pData; /* Pointer to the texture data */ -} ATI_TC_Texture; - -typedef enum -{ - ATI_TC_OK = 0, - ATI_TC_ABORTED, - ATI_TC_ERR_INVALID_SOURCE_TEXTURE, - ATI_TC_ERR_INVALID_DEST_TEXTURE, - ATI_TC_ERR_UNSUPPORTED_SOURCE_FORMAT, - ATI_TC_ERR_UNSUPPORTED_DEST_FORMAT, - ATI_TC_ERR_SIZE_MISMATCH, - ATI_TC_ERR_UNABLE_TO_INIT_CODEC, - ATI_TC_ERR_GENERIC -} ATI_TC_ERROR; - -#define MINIMUM_WEIGHT_VALUE 0.01f - - -#ifdef __cplusplus -extern "C" { -#endif - -/* -** ATI_TC_Feedback_Proc -** Feedback proc for conversion -** Return non-NULL(true) value to abort conversion -*/ - -typedef bool (ATI_TC_API * ATI_TC_Feedback_Proc)(float fProgress, DWORD_PTR pUser1, DWORD_PTR pUser2); - -/* -** ATI_TC_CalculateBufferSize -** Calculates the required buffer size for the specified texture -*/ - -ATI_TC_DWORD ATI_TC_API ATI_TC_CalculateBufferSize(const ATI_TC_Texture* pTexture); - - -/* -** ATI_TC_ConvertTexture -** Converts the source texture to the destination texture -*/ - -ATI_TC_ERROR ATI_TC_API ATI_TC_ConvertTexture(const ATI_TC_Texture* pSourceTexture, /* [in] - Pointer to the source texture */ - ATI_TC_Texture* pDestTexture, /* [out] - Pointer to the destination texture */ - const ATI_TC_CompressOptions* pOptions, /* [in] - Pointer to the compression options - can be NULL */ - ATI_TC_Feedback_Proc pFeedbackProc, /* [in] - Pointer to the feedback proc - can be NULL */ - DWORD_PTR pUser1, /* [in] - User data to pass to the feedback proc */ - DWORD_PTR pUser2); /* [in] - User data to pass to the feedback proc */ - - -#ifdef __cplusplus -}; -#endif - -#endif // !ATI_COMPRESS diff --git a/public/BitmapFontFile.h b/public/BitmapFontFile.h deleted file mode 100644 index b861ff2d4..000000000 --- a/public/BitmapFontFile.h +++ /dev/null @@ -1,54 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ====== -// -// Baked Bitmap fonts -// -//=========================================================================== - -#ifndef _BITMAPFONTFILE_H_ -#define _BITMAPFONTFILE_H_ - -#include "datamap.h" - -#define BITMAPFONT_ID (('T'<<24)|('N'<<16)|('F'<<8)|('V')) -#define BITMAPFONT_VERSION 3 - -// style flags -#define BF_BOLD 0x0001 -#define BF_ITALIC 0x0002 -#define BF_OUTLINED 0x0004 -#define BF_DROPSHADOW 0x0008 -#define BF_BLURRED 0x0010 -#define BF_SCANLINES 0x0020 -#define BF_ANTIALIASED 0x0040 -#define BF_CUSTOM 0x0080 - -#pragma pack(1) //X360TBD -typedef struct BitmapGlyph_s -{ - DECLARE_BYTESWAP_DATADESC(); - short x; - short y; - short w; - short h; - short a; - short b; - short c; -} BitmapGlyph_t; - -typedef struct BitmapFont_s -{ - DECLARE_BYTESWAP_DATADESC(); - int m_id; - int m_Version; - short m_PageWidth; - short m_PageHeight; - short m_MaxCharWidth; - short m_MaxCharHeight; - short m_Flags; - short m_Ascent; - short m_NumGlyphs; - unsigned char m_TranslateTable[256]; -} BitmapFont_t; -#pragma pack() - -#endif diff --git a/public/Color.h b/public/Color.h deleted file mode 100644 index 0fc54b4c3..000000000 --- a/public/Color.h +++ /dev/null @@ -1,103 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef COLOR_H -#define COLOR_H - -#ifdef _WIN32 -#pragma once -#endif - -//----------------------------------------------------------------------------- -// Purpose: Basic handler for an rgb set of colors -// This class is fully inline -//----------------------------------------------------------------------------- -class Color -{ -public: - // constructors - Color() - { - *((int *)this) = 0; - } - Color(int r,int g,int b) - { - SetColor(r, g, b, 0); - } - Color(int r,int g,int b,int a) - { - SetColor(r, g, b, a); - } - - // set the color - // r - red component (0-255) - // g - green component (0-255) - // b - blue component (0-255) - // a - alpha component, controls transparency (0 - transparent, 255 - opaque); - void SetColor(int r, int g, int b, int a = 0) - { - _color[0] = (unsigned char)r; - _color[1] = (unsigned char)g; - _color[2] = (unsigned char)b; - _color[3] = (unsigned char)a; - } - - void GetColor(int &r, int &g, int &b, int &a) const - { - r = _color[0]; - g = _color[1]; - b = _color[2]; - a = _color[3]; - } - - void SetRawColor( int color32 ) - { - *((int *)this) = color32; - } - - int GetRawColor() const - { - return *((int *)this); - } - - inline int r() const { return _color[0]; } - inline int g() const { return _color[1]; } - inline int b() const { return _color[2]; } - inline int a() const { return _color[3]; } - - unsigned char &operator[](int index) - { - return _color[index]; - } - - const unsigned char &operator[](int index) const - { - return _color[index]; - } - - bool operator == (const Color &rhs) const - { - return ( *((int *)this) == *((int *)&rhs) ); - } - - bool operator != (const Color &rhs) const - { - return !(operator==(rhs)); - } - - Color &operator=( const Color &rhs ) - { - SetRawColor( rhs.GetRawColor() ); - return *this; - } - -private: - unsigned char _color[4]; -}; - - -#endif // COLOR_H diff --git a/public/Friends/AddOns/AddOnMessages.h b/public/Friends/AddOns/AddOnMessages.h deleted file mode 100644 index d1eff4052..000000000 --- a/public/Friends/AddOns/AddOnMessages.h +++ /dev/null @@ -1,56 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ADDONMESSAGES_H -#define ADDONMESSAGES_H -#pragma once - -enum GameMessageIDs -{ - GAME_MSG_TEXT = 1, // text chat message - GAME_MSG_DATA, // binary game data - - GAME_MSG_INVITE_REQUEST, - GAME_MSG_INVITE_RESPONSE, - GAME_MSG_REJOIN_REQUEST, - GAME_MSG_REJOIN_RESPONSE, - - GAME_MSG_INVITE_PERMISSION, // ask permission to invite someone - GAME_MSG_INVITE_NOTIFY, // tell everybody that we're inviting - GAME_MSG_INVITE_DENIED, - - GAME_MSG_PLAYER_STATUS_UPDATE, - GAME_MSG_SETUP_INFO, // when user joins a game, host send the setup information of who's in the game - GAME_MSG_INVITE_CANCEL, // host has cancelled an invite - GAME_MSG_GAME_START, // if a game has a setup phase, this tells everybody the game has started - - GAME_MSG_PLAYER_KICK, // player kicked from game - GAME_MSG_UPDATING, - GAME_MSG_UP_TO_DATE, // player is up to date and ready to get data - - GAME_MSG_STARTING_CARD_HAND = 300, - GAME_MSG_STARTING_PLAYER, - GAME_MSG_CARD_PLAY, - - GAME_MSG_CHEAT_POSSIBLE = 400, // when host detects a possible cheat - - GAME_MSG_MOVE = 500, - GAME_MSG_COLOR_CHOICE, - GAME_MSG_RECONNECT_DATA, - GAME_MSG_QUIT, - GAME_MSG_PASS, - - GAME_MSG_ABORT, // phase these out - GAME_MSG_WAITING_ABORT, - -// GAME_MSG_CLOSE_WINDOW, - - // special individual game messages should take IDs 1000 and over -}; - - -#endif // ADDONMESSAGES_H - diff --git a/public/Friends/AddOns/AddOnTypes.h b/public/Friends/AddOns/AddOnTypes.h deleted file mode 100644 index 7295044f6..000000000 --- a/public/Friends/AddOns/AddOnTypes.h +++ /dev/null @@ -1,18 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ADDONTYPES_H -#define ADDONTYPES_H -#pragma once - -#ifndef WIN32 - typedef unsigned long long SessionInt64; -#else - typedef unsigned __int64 SessionInt64; -#endif - -#endif // ADDONTYPES_H - diff --git a/public/Friends/AddOns/ISteamAddOn.h b/public/Friends/AddOns/ISteamAddOn.h deleted file mode 100644 index 5af4114d0..000000000 --- a/public/Friends/AddOns/ISteamAddOn.h +++ /dev/null @@ -1,69 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Interface to a Steam Add On -// -//=============================================================================// - -#ifndef ISTEAMADDON_H -#define ISTEAMADDON_H -#pragma once - -#include "interface.h" -#include "AddOnTypes.h" -#include - -class CUtlMsgBuffer; - -class ISteamAddOn : public IBaseInterface -{ -public: - // allows SteamAddOn to link to the core vgui factories - virtual bool Initialize(CreateInterfaceFn *vguiFactories, int factoryCount) = 0; - - // allows SteamAddOns to link to all other modules - virtual bool PostInitialize(CreateInterfaceFn *modules, int factoryCount) = 0; - - // when Friends closes down - all SteamAddOns are notified - virtual void Deactivate() = 0; - - // notifies the addon who its VGUI parent panel is - virtual void SetParent( vgui::Panel *parent ) = 0; - - // notifies the SteamAddOn of the user's ID and username. - // Note: username can be set mulitple times due to changing of name - virtual void SetUserID(unsigned int userID) = 0; - virtual void SetUserName(const char *userName) = 0; - - // Query if there are any 'open' sessions - open meaning allowing new users to join the sessions - virtual int QueryOpenSessionCount() = 0; - - // will be valid right after a call to QueryOpenInviteCount will set the addOnSessionID and hostname for - // any open sessions for this addOn. Return true if it's a valid index - virtual bool QueryOpenSessionInfo(int nOpenGameIndex, SessionInt64 &addOnSessionID, char *pszHostName) = 0; - - // returns true if this userID is involved in an addOnSession with this ID - virtual bool QueryUserInvolved(SessionInt64 addOnSessionID, unsigned int userID) = 0; - - // if session doesn't exist, then the SteamAddOn body should deal with it - virtual bool OnReceiveMsg(SessionInt64 addOnSessionID, CUtlMsgBuffer *msgBuffer) = 0; - - // Let's the SteamAddOn know when when any friend's status has changed - virtual void OnFriendStatusChanged() = 0; - - // A request to start/join this AddOn with this user ID/name. addOnSessionID will be zero if it's a new session request - virtual void OnInviteUser(unsigned int targetUserID, const char *username, SessionInt64 addOnSessionID) = 0; - - // user accepted this host's invite request - virtual void OnAcceptInviteRequest(unsigned int hostID, const char *hostUserName, SessionInt64 addOnSessionID, const char *pAppData, int dataLen) = 0; - - // user accepted this host's rejoin request - virtual void OnAcceptRejoinRequest(unsigned int hostID, const char *hostUserName, SessionInt64 addOnSessionID, const char *pAppData, int dataLen) = 0; - - // user starts this addOn from a menu - virtual void StartAddOn() = 0; -}; - -#define STEAMADDON_INTERFACE_VERSION "SteamAddOn007" - -#endif // ISTEAMADDON_H - diff --git a/public/Friends/IFriendsNET.h b/public/Friends/IFriendsNET.h deleted file mode 100644 index 41593bacd..000000000 --- a/public/Friends/IFriendsNET.h +++ /dev/null @@ -1,41 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef FRIENDSNET_INTERFACE_H -#define FRIENDSNET_INTERFACE_H -#pragma once - -class CUtlMsgBuffer; -class CServerSession; - -#include "interface.h" -#include "Friends/AddOns/AddOnTypes.h" - -class IFriendsNET : public IBaseInterface -{ -public: - // check if we have network information for this user - virtual bool CheckUserRegistered(unsigned int userID) = 0; - - // update a user's network information - virtual void UpdateUserNetInfo(unsigned int userID, unsigned int netSessionID, int serverID, int IP, int port) = 0; - - // set whether or not we send directly to user or through the server - virtual void SetUserSendViaServer(unsigned int userID, bool bSendViaServer) = 0; - - // Gets a blob of data that represents this user's information - virtual bool GetUserNetInfoBlob(unsigned int userID, unsigned int dataBlob[8]) = 0; - // Sets a user's information using the same blob of data type - virtual bool SetUserNetInfoBlob(unsigned int userID, const unsigned int dataBlob[8]) = 0; - - // send binary data to user, marked with game/sessionID - virtual void SendAddOnPacket(const char *pszGameID, SessionInt64 addOnSessionID, unsigned int userID, const CUtlMsgBuffer& buffer) = 0; -}; - -#define FRIENDSNET_INTERFACE_VERSION "FriendsNET003" - -#endif // FRIENDSNET_INTERFACE_H - diff --git a/public/Friends/IFriendsUser.h b/public/Friends/IFriendsUser.h deleted file mode 100644 index 2c906a930..000000000 --- a/public/Friends/IFriendsUser.h +++ /dev/null @@ -1,62 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IFRIENDSUSER_H -#define IFRIENDSUSER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "interface.h" - -//----------------------------------------------------------------------------- -// Purpose: Interface to accessing information about Friends Users -//----------------------------------------------------------------------------- -class IFriendsUser : public IBaseInterface -{ -public: - // returns true if the interface is ready for use - virtual bool IsValid() = 0; - - // returns the Friends ID of the current user - virtual unsigned int GetFriendsID() = 0; - - // returns information about a user - // information may not be known about some users, "" will be returned - virtual const char *GetUserName(unsigned int friendsID) = 0; - virtual const char *GetFirstName(unsigned int friendsID) = 0; - virtual const char *GetLastName(unsigned int friendsID) = 0; - virtual const char *GetEmail(unsigned int friendsID) = 0; - - // returns true if buddyID is a buddy of the current user - // ie. the current is authorized to see when the buddy is online - virtual bool IsBuddy(unsigned int buddyID) = 0; - - // requests authorization from a user - virtual void RequestAuthorizationFromUser(unsigned int potentialBuddyID) = 0; - - // returns the status of the buddy, > 0 is online, 4 is ingame - virtual int GetBuddyStatus(unsigned int friendsID) = 0; - - // gets the IP address of the server the buddy is on, returns false if couldn't get - virtual bool GetBuddyGameAddress(unsigned int friendsID, int *ip, int *port) = 0; - - // returns the number of buddies - virtual int GetNumberOfBuddies() = 0; - - // returns the FriendsID of a buddy - buddyIndex is valid in the range [0, GetNumberOfBuddies) - virtual unsigned int GetBuddyFriendsID(int buddyIndex) = 0; - - // sets whether or not the user can receive messages at this time - // messages will be queued until this is set to true - virtual void SetCanReceiveMessages(bool state) = 0; -}; - -#define FRIENDSUSER_INTERFACE_VERSION "FriendsUser001" - - -#endif // IFRIENDSUSER_H diff --git a/public/IGameUIFuncs.h b/public/IGameUIFuncs.h deleted file mode 100644 index 18b2adfc1..000000000 --- a/public/IGameUIFuncs.h +++ /dev/null @@ -1,30 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef IGAMEUIFUNCS_H -#define IGAMEUIFUNCS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "vgui/keycode.h" - -abstract_class IGameUIFuncs -{ -public: - virtual bool IsKeyDown( const char *keyname, bool& isdown ) = 0; - virtual const char *GetBindingForButtonCode( ButtonCode_t code ) = 0; - virtual ButtonCode_t GetButtonCodeForBind( const char *pBind ) = 0; - virtual void GetVideoModes( struct vmode_s **liststart, int *count ) = 0; - virtual void SetFriendsID( uint friendsID, const char *friendsName ) = 0; - virtual void GetDesktopResolution( int &width, int &height ) = 0; - virtual bool IsConnectedToVACSecureServer() = 0; -}; - -#define VENGINE_GAMEUIFUNCS_VERSION "VENGINE_GAMEUIFUNCS_VERSION005" - -#endif // IGAMEUIFUNCS_H diff --git a/public/IHammer.h b/public/IHammer.h deleted file mode 100644 index acf63a2ed..000000000 --- a/public/IHammer.h +++ /dev/null @@ -1,56 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: The application object. -// -//=============================================================================// - -#ifndef IHAMMER_H -#define IHAMMER_H - -#include "appframework/IAppSystem.h" - -typedef struct tagMSG MSG; - - -class IStudioDataCache; - - -//----------------------------------------------------------------------------- -// Return values for RequestNewConfig -//----------------------------------------------------------------------------- -enum RequestRetval_t -{ - REQUEST_OK = 0, - REQUEST_QUIT -}; - - -//----------------------------------------------------------------------------- -// Interface used to drive hammer -//----------------------------------------------------------------------------- -#define INTERFACEVERSION_HAMMER "Hammer001" -class IHammer : public IAppSystem -{ -public: - virtual bool HammerPreTranslateMessage( MSG * pMsg ) = 0; - virtual bool HammerIsIdleMessage( MSG * pMsg ) = 0; - virtual bool HammerOnIdle( long count ) = 0; - - virtual void RunFrame() = 0; - - // Returns the mod and the game to initially start up - virtual const char *GetDefaultMod() = 0; - virtual const char *GetDefaultGame() = 0; - - virtual bool InitSessionGameConfig( const char *szGameDir ) = 0; - - // Request a new config from hammer's config system - virtual RequestRetval_t RequestNewConfig() = 0; - - // Returns the full path to the mod and the game to initially start up - virtual const char *GetDefaultModFullPath() = 0; - - virtual int MainLoop() = 0; -}; - -#endif // IHAMMER_H diff --git a/public/OfflineMode.h b/public/OfflineMode.h deleted file mode 100644 index 0a0455c33..000000000 --- a/public/OfflineMode.h +++ /dev/null @@ -1,29 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include -#include - -#define STEAM_OFFLINE_MODE "HKEY_CURRENT_USER\\Software\\Valve\\Steam\\Offline" -#define STEAM_AFS_MODE "HKEY_CURRENT_USER\\Software\\Valve\\Steam\\OfflineAFS" -#define OFFLINE_FILE "Steam\\cached\\offline_" // first part of filename - -inline bool IsSteamInOfflineMode() -{ - int offline = 0; - vgui::system()->GetRegistryInteger( STEAM_OFFLINE_MODE, offline ); - return ( offline == 1 ); -}inline bool IsSteamInAuthenticationFailSafeMode() -{ - int offline = 0; - vgui::system()->GetRegistryInteger( STEAM_AFS_MODE, offline ); - return ( offline == 1 ); -} - -inline bool IsSteamGameServerBrowsingEnabled() -{ - return (IsSteamInAuthenticationFailSafeMode() || !IsSteamInOfflineMode()); -} diff --git a/public/PlayerState.h b/public/PlayerState.h deleted file mode 100644 index 258b20202..000000000 --- a/public/PlayerState.h +++ /dev/null @@ -1,62 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PLAYERSTATE_H -#define PLAYERSTATE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "edict.h" -#include "networkvar.h" -// Only care about this stuff in game/client .dlls -#if defined( CLIENT_DLL ) -#include "predictable_entity.h" -#endif - -class CPlayerState -{ -public: - DECLARE_CLASS_NOBASE( CPlayerState ); - DECLARE_EMBEDDED_NETWORKVAR(); - - // This virtual method is necessary to generate a vtable in all cases - // (DECLARE_PREDICTABLE will generate a vtable also)! - virtual ~CPlayerState() {} - - // true if the player is dead - CNetworkVar( bool, deadflag ); - // Viewing angle (player only) - QAngle v_angle; - -// The client .dll only cares about deadflag -// the game and engine .dlls need to worry about the rest of this data -#if !defined( CLIENT_DLL ) - // Player's network name - string_t netname; - // 0:nothing, 1:force view angles, 2:add avelocity - int fixangle; - // delta angle for fixangle == FIXANGLE_RELATIVE - QAngle anglechange; - // flag to single the HLTV fake client, not transmitted - bool hltv; - int frags; - int deaths; -#endif - -// NOTE: Only care about this stuff in game/client dlls -// Put at end in case it has any effect on size of structure -#if defined( GAME_DLL ) - DECLARE_SIMPLE_DATADESC(); -#endif - -#if defined( CLIENT_DLL ) - DECLARE_PREDICTABLE(); -#endif -}; - -#endif // PLAYERSTATE_H diff --git a/public/ScratchPadUtils.cpp b/public/ScratchPadUtils.cpp deleted file mode 100644 index b9cf0f2dd..000000000 --- a/public/ScratchPadUtils.cpp +++ /dev/null @@ -1,469 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#if !defined(_STATIC_LINKED) || defined(_SHARED_LIB) - -#include "iscratchpad3d.h" -#include "mathlib/mathlib.h" -#include "ScratchPadUtils.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -// --------------------------------------------------------------------------------------------------------------------- // -// CScratchPadGraph implementation. -// --------------------------------------------------------------------------------------------------------------------- // - -CScratchPadGraph::CScratchPadGraph() -{ - m_pPad = NULL; -} - - -void CScratchPadGraph::Init( - IScratchPad3D *pPad, - - Vector vTimeAxis, - float flInchesPerSecond, - Vector vTimeLineColor, - float flTimeOrigin, - - float flTimeLabelEveryNSeconds, - - Vector vValueAxis, - float flInchesPerValue, - Vector vValueLineColor, - float flValueOrigin - - ) -{ - m_pPad = pPad; - m_vTimeAxis = vTimeAxis; - m_flInchesPerSecond = flInchesPerSecond; - m_vValueAxis = vValueAxis; - m_flInchesPerValue = flInchesPerValue; - m_flTimeLabelEveryNSeconds = flTimeLabelEveryNSeconds; - - m_vTimeLineColor = vTimeLineColor; - m_vValueLineColor = vValueLineColor; - - m_flTimeOrigin = flTimeOrigin; - m_flValueOrigin = flValueOrigin; - - m_nTimeLabelsDrawn = 0; - m_flHighestTime = flTimeOrigin; - m_flHighestValue = flValueOrigin; -} - - -bool CScratchPadGraph::IsInitted() const -{ - return m_pPad != NULL; -} - - -CScratchPadGraph::LineID CScratchPadGraph::AddLine( Vector vColor ) -{ - CScratchPadGraph::CLineInfo info; - info.m_bFirst = true; - info.m_flLastTime = 0.0f; - info.m_flLastValue = 0.0f; - info.m_vColor = vColor; - return m_LineInfos.AddToTail( info ); -} - - -void CScratchPadGraph::AddSample( LineID iLine, float flTime, float flValue ) -{ - CScratchPadGraph::CLineInfo *pInfo = &m_LineInfos[iLine]; - - UpdateTicksAndStuff( flTime, flValue ); - - if ( !pInfo->m_bFirst ) - { - // Draw a line from the last value to the current one. - Vector vStart = GetSamplePosition( pInfo->m_flLastTime, pInfo->m_flLastValue ); - Vector vEnd = GetSamplePosition( flTime, flValue ); - - m_pPad->DrawLine( - CSPVert( vStart, pInfo->m_vColor ), - CSPVert( vEnd, pInfo->m_vColor ) - ); - } - - pInfo->m_flLastTime = flTime; - pInfo->m_flLastValue = flValue; - pInfo->m_bFirst = false; -} - - -void CScratchPadGraph::AddVerticalLine( float flTime, float flMinValue, float flMaxValue, const CSPColor &vColor ) -{ - Vector v1 = GetSamplePosition( flTime, flMinValue ); - Vector v2 = GetSamplePosition( flTime, flMaxValue ); - m_pPad->DrawLine( - CSPVert( v1, vColor ), - CSPVert( v2, vColor ) ); -} - - -void CScratchPadGraph::UpdateTicksAndStuff( float flTime, float flValue ) -{ - if ( flTime > m_flHighestTime ) - { - // Update the left part of the time axis. - Vector vStart = GetSamplePosition( m_flHighestTime, m_flValueOrigin ); - Vector vEnd = GetSamplePosition( flTime, m_flValueOrigin ); - - m_pPad->DrawLine( - CSPVert( vStart, m_vTimeLineColor ), - CSPVert( vEnd, m_vTimeLineColor ) - ); - - m_flHighestTime = flTime; - } - - if ( flValue > m_flHighestValue ) - { - // Update the left part of the time axis. - Vector vStart = GetSamplePosition( m_flTimeOrigin, m_flHighestValue ); - Vector vEnd = GetSamplePosition( m_flTimeOrigin, flValue ); - - m_pPad->DrawLine( - CSPVert( vStart, m_vValueLineColor ), - CSPVert( vEnd, m_vValueLineColor ) - ); - - // Extend the lines attached to the time labels. - for ( int i=0; i < m_nTimeLabelsDrawn; i++ ) - { - float flTime = m_flTimeOrigin + m_nTimeLabelsDrawn * m_flTimeLabelEveryNSeconds; - - m_pPad->DrawLine( - CSPVert((const Vector&) GetSamplePosition( flTime, m_flHighestValue )), - CSPVert((const Vector&) GetSamplePosition( flTime, flValue ) ) - ); - } - - m_flHighestValue = flValue; - } - - // More text labels? - int iHighestTextLabel = (int)ceil( (flTime - m_flTimeOrigin) / m_flTimeLabelEveryNSeconds + 0.5f ); - while ( m_nTimeLabelsDrawn < iHighestTextLabel ) - { - CTextParams params; - - float flTime = m_flTimeOrigin + m_nTimeLabelsDrawn * m_flTimeLabelEveryNSeconds; - - params.m_bSolidBackground = true; - params.m_vPos = GetSamplePosition( flTime, m_flValueOrigin-5 ); - params.m_bTwoSided = true; - - char str[512]; - Q_snprintf( str, sizeof( str ), "time: %.2f", flTime ); - m_pPad->DrawText( str, params ); - - - // Now draw the vertical line for the value.. - m_pPad->DrawLine( - CSPVert( (const Vector&)GetSamplePosition( flTime, m_flValueOrigin ) ), - CSPVert( (const Vector&)GetSamplePosition( flTime, m_flHighestValue ) ) - ); - - - m_nTimeLabelsDrawn++; - } -} - - -Vector CScratchPadGraph::GetSamplePosition( float flTime, float flValue ) -{ - Vector vRet = - m_vTimeAxis * ((flTime - m_flTimeOrigin) * m_flInchesPerSecond) + - m_vValueAxis * ((flValue - m_flValueOrigin) * m_flInchesPerValue); - - return vRet; -} - - - -// --------------------------------------------------------------------------------------------------------------------- // -// Global functions. -// --------------------------------------------------------------------------------------------------------------------- // - -void ScratchPad_DrawLitCone( - IScratchPad3D *pPad, - const Vector &vBaseCenter, - const Vector &vTip, - const Vector &vBrightColor, - const Vector &vDarkColor, - const Vector &vLightDir, - float baseWidth, - int nSegments ) -{ - // Make orthogonal vectors. - Vector vDir = vTip - vBaseCenter; - VectorNormalize( vDir ); - - Vector vRight, vUp; - VectorVectors( vDir, vRight, vUp ); - vRight *= baseWidth; - vUp *= baseWidth; - - // Setup the top and bottom caps. - CSPVertList bottomCap, tri; - bottomCap.m_Verts.SetSize( nSegments ); - tri.m_Verts.SetSize( 3 ); - - float flDot = -vLightDir.Dot( vDir ); - Vector topColor, bottomColor; - VectorLerp( vDarkColor, vBrightColor, RemapVal( -flDot, -1, 1, 0, 1 ), bottomColor ); - - - // Draw each quad. - Vector vPrevBottom = vBaseCenter + vRight; - - for ( int i=0; i < nSegments; i++ ) - { - float flAngle = (float)(i+1) * M_PI * 2.0 / nSegments; - Vector vOffset = vRight * cos( flAngle ) + vUp * sin( flAngle ); - Vector vCurBottom = vBaseCenter + vOffset; - - const Vector &v1 = vTip; - const Vector &v2 = vPrevBottom; - const Vector &v3 = vCurBottom; - Vector vFaceNormal = (v2 - v1).Cross( v3 - v1 ); - VectorNormalize( vFaceNormal ); - - // Now light it. - flDot = -vLightDir.Dot( vFaceNormal ); - Vector vColor; - VectorLerp( vDarkColor, vBrightColor, RemapVal( flDot, -1, 1, 0, 1 ), vColor ); - - // Draw the quad. - tri.m_Verts[0] = CSPVert( v1, vColor ); - tri.m_Verts[1] = CSPVert( v2, vColor ); - tri.m_Verts[2] = CSPVert( v3, vColor ); - pPad->DrawPolygon( tri ); - - bottomCap.m_Verts[i] = CSPVert( vCurBottom, bottomColor ); - } - - pPad->DrawPolygon( bottomCap ); -} - - -void ScratchPad_DrawLitCylinder( - IScratchPad3D *pPad, - const Vector &v1, - const Vector &v2, - const Vector &vBrightColor, - const Vector &vDarkColor, - const Vector &vLightDir, - float width, - int nSegments ) -{ - // Make orthogonal vectors. - Vector vDir = v2 - v1; - VectorNormalize( vDir ); - - Vector vRight, vUp; - VectorVectors( vDir, vRight, vUp ); - vRight *= width; - vUp *= width; - - // Setup the top and bottom caps. - CSPVertList topCap, bottomCap, quad; - - topCap.m_Verts.SetSize( nSegments ); - bottomCap.m_Verts.SetSize( nSegments ); - quad.m_Verts.SetSize( 4 ); - - float flDot = -vLightDir.Dot( vDir ); - Vector topColor, bottomColor; - - VectorLerp( vDarkColor, vBrightColor, RemapVal( flDot, -1, 1, 0, 1 ), topColor ); - VectorLerp( vDarkColor, vBrightColor, RemapVal( -flDot, -1, 1, 0, 1 ), bottomColor ); - - - // Draw each quad. - Vector vPrevTop = v1 + vRight; - Vector vPrevBottom = v2 + vRight; - - for ( int i=0; i < nSegments; i++ ) - { - float flAngle = (float)(i+1) * M_PI * 2.0 / nSegments; - Vector vOffset = vRight * cos( flAngle ) + vUp * sin( flAngle ); - Vector vCurTop = v1 + vOffset; - Vector vCurBottom = v2 + vOffset; - - // Now light it. - VectorNormalize( vOffset ); - flDot = -vLightDir.Dot( vOffset ); - Vector vColor; - VectorLerp( vDarkColor, vBrightColor, RemapVal( flDot, -1, 1, 0, 1 ), vColor ); - - // Draw the quad. - quad.m_Verts[0] = CSPVert( vPrevTop, vColor ); - quad.m_Verts[1] = CSPVert( vPrevBottom, vColor ); - quad.m_Verts[2] = CSPVert( vCurBottom, vColor ); - quad.m_Verts[3] = CSPVert( vCurTop, vColor ); - pPad->DrawPolygon( quad ); - - topCap.m_Verts[i] = CSPVert( vCurTop, topColor ); - bottomCap.m_Verts[i] = CSPVert( vCurBottom, bottomColor ); - } - - pPad->DrawPolygon( topCap ); - pPad->DrawPolygon( bottomCap ); -} - - -void ScratchPad_DrawArrow( - IScratchPad3D *pPad, - const Vector &vPos, - const Vector &vDirection, - const Vector &vColor, - float flLength, - float flLineWidth, - float flHeadWidth, - int nCylinderSegments, - int nHeadSegments, - float flArrowHeadPercentage - ) -{ - Vector vNormDir = vDirection; - VectorNormalize( vNormDir ); - - Vector vConeBase = vPos + vNormDir * (flLength * ( 1 - flArrowHeadPercentage ) ); - Vector vConeEnd = vPos + vNormDir * flLength; - - Vector vLightDir( -1, -1, -1 ); - VectorNormalize( vLightDir ); // could precalculate this - - pPad->SetRenderState( IScratchPad3D::RS_FillMode, IScratchPad3D::FillMode_Solid ); - pPad->SetRenderState( IScratchPad3D::RS_ZRead, true ); - - ScratchPad_DrawLitCylinder( pPad, vPos, vConeBase, vColor, vColor*0.25f, vLightDir, flLineWidth, nCylinderSegments ); - ScratchPad_DrawLitCone( pPad, vConeBase, vConeEnd, vColor, vColor*0.25f, vLightDir, flHeadWidth, nHeadSegments ); -} - - -void ScratchPad_DrawArrowSimple( - IScratchPad3D *pPad, - const Vector &vPos, - const Vector &vDirection, - const Vector &vColor, - float flLength ) -{ - ScratchPad_DrawArrow( - pPad, - vPos, - vDirection, - vColor, - flLength, - flLength * 1.0/15, - flLength * 3.0/15, - 4, - 4 ); -} - - -void ScratchPad_DrawSphere( - IScratchPad3D *pPad, - const Vector &vCenter, - float flRadius, - const Vector &vColor, - int nSubDivs ) -{ - CUtlVector prevPoints; - prevPoints.SetSize( nSubDivs ); - - // For each vertical slice.. (the top and bottom ones are just a single point). - for ( int iSlice=0; iSlice < nSubDivs; iSlice++ ) - { - float flHalfSliceAngle = M_PI * (float)iSlice / (nSubDivs - 1); - - if ( iSlice == 0 ) - { - prevPoints[0] = vCenter + Vector( 0, 0, flRadius ); - for ( int z=1; z < prevPoints.Count(); z++ ) - prevPoints[z] = prevPoints[0]; - } - else - { - for ( int iSubPt=0; iSubPt < nSubDivs; iSubPt++ ) - { - float flHalfAngle = M_PI * (float)iSubPt / (nSubDivs - 1); - float flAngle = flHalfAngle * 2; - - Vector pt; - if ( iSlice == (nSubDivs - 1) ) - { - pt = vCenter - Vector( 0, 0, flRadius ); - } - else - { - pt.x = cos( flAngle ) * sin( flHalfSliceAngle ); - pt.y = sin( flAngle ) * sin( flHalfSliceAngle ); - pt.z = cos( flHalfSliceAngle ); - - pt *= flRadius; - pt += vCenter; - } - - pPad->DrawLine( CSPVert( pt, vColor ), CSPVert( prevPoints[iSubPt], vColor ) ); - prevPoints[iSubPt] = pt; - } - - if ( iSlice != (nSubDivs - 1) ) - { - for ( int i=0; i < nSubDivs; i++ ) - pPad->DrawLine( CSPVert( prevPoints[i], vColor ), CSPVert( prevPoints[(i+1)%nSubDivs], vColor ) ); - } - } - } -} - - -void ScratchPad_DrawAABB( - IScratchPad3D *pPad, - const Vector &vMins, - const Vector &vMaxs, - const Vector &vColor ) -{ - int vertOrder[4][2] = {{0,0},{1,0},{1,1},{0,1}}; - const Vector *vecs[2] = {&vMins, &vMaxs}; - - Vector vTop, vBottom, vPrevTop, vPrevBottom; - vTop.z = vPrevTop.z = vMaxs.z; - vBottom.z = vPrevBottom.z = vMins.z; - - vPrevTop.x = vPrevBottom.x = vecs[vertOrder[3][0]]->x; - vPrevTop.y = vPrevBottom.y = vecs[vertOrder[3][1]]->y; - - for ( int i=0; i < 4; i++ ) - { - vTop.x = vBottom.x = vecs[vertOrder[i][0]]->x; - vTop.y = vBottom.y = vecs[vertOrder[i][1]]->y; - - // Draw the top line. - pPad->DrawLine( CSPVert( vPrevTop, vColor ), CSPVert( vTop, vColor ) ); - pPad->DrawLine( CSPVert( vPrevBottom, vColor ), CSPVert( vBottom, vColor ) ); - pPad->DrawLine( CSPVert( vTop, vColor ), CSPVert( vBottom, vColor ) ); - - vPrevTop = vTop; - vPrevBottom = vBottom; - } -} - - -#endif // !_STATIC_LINKED || _SHARED_LIB - diff --git a/public/ScratchPadUtils.h b/public/ScratchPadUtils.h deleted file mode 100644 index aa51d2864..000000000 --- a/public/ScratchPadUtils.h +++ /dev/null @@ -1,163 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: This module contains helper functions for use with scratch pads. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SCRATCHPADUTILS_H -#define SCRATCHPADUTILS_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "iscratchpad3d.h" - - -// Use this to make a graph. -class CScratchPadGraph -{ -public: - - typedef int LineID; - - CScratchPadGraph(); - - // Initialze the orientation and scales of the two axes. - // Axis indices are 0, 1, or 2 for x, y, and z. - void Init( - IScratchPad3D *pPad, - - Vector vTimeAxis = Vector(0,-1,0), - float flInchesPerSecond=1, - Vector vTimeLineColor=Vector(0,0,1), - float flTimeOrigin=0, // Where the origin of the graph is. - - float flTimeLabelEveryNSeconds=1, - - Vector vValueAxis = Vector(0,0,1), - float flInchesPerValue=1, - Vector vValueLineColor=Vector(1,0,0), - float flValueOrigin=0 // Where the origin of the graph is. - - ); - - bool IsInitted() const; - - // Add another line into the graph. - LineID AddLine( Vector vColor ); - void AddSample( LineID iLine, float flTime, float flValue ); - void AddVerticalLine( float flTime, float flMinValue, float flMaxValue, const CSPColor &vColor ); - - // Get the 3D position of a sample on the graph (so you can draw other things there). - Vector GetSamplePosition( float flTime, float flValue ); - - -private: - - void UpdateTicksAndStuff( float flTime, float flValue ); - - - -private: - class CLineInfo - { - public: - bool m_bFirst; - float m_flLastTime; - float m_flLastValue; - Vector m_vColor; - }; - - IScratchPad3D *m_pPad; - - CUtlVector m_LineInfos; - - Vector m_vTimeAxis; - float m_flInchesPerSecond; - - Vector m_vValueAxis; - float m_flInchesPerValue; - - // How often to make a time label. - float m_flTimeLabelEveryNSeconds; - int m_nTimeLabelsDrawn; - - Vector m_vTimeLineColor; - Vector m_vValueLineColor; - - float m_flTimeOrigin; - float m_flValueOrigin; - - // Used to extend the value border. - float m_flHighestValue; - float m_flHighestTime; -}; - - - -// Draw a cone. -void ScratchPad_DrawLitCone( - IScratchPad3D *pPad, - const Vector &vBaseCenter, - const Vector &vTip, - const Vector &vBrightColor, - const Vector &vDarkColor, - const Vector &vLightDir, - float baseWidth, - int nSegments ); - - -// Draw a cylinder. -void ScratchPad_DrawLitCylinder( - IScratchPad3D *pPad, - const Vector &v1, - const Vector &v2, - const Vector &vBrightColor, - const Vector &vDarkColor, - const Vector &vLightDir, - float width, - int nSegments ); - - -// Draw an arrow. -void ScratchPad_DrawArrow( - IScratchPad3D *pPad, - const Vector &vPos, - const Vector &vDirection, - const Vector &vColor, - float flLength=20, - float flLineWidth=3, - float flHeadWidth=8, - int nCylinderSegments=5, - int nHeadSegments=8, - float flArrowHeadPercentage = 0.3f // How much of the line is the arrow head. - ); - - -// Draw an arrow with less parameters.. it generates parameters based on length -// automatically to make the arrow look good. -void ScratchPad_DrawArrowSimple( - IScratchPad3D *pPad, - const Vector &vPos, - const Vector &vDirection, - const Vector &vColor, - float flLength ); - -void ScratchPad_DrawSphere( - IScratchPad3D *pPad, - const Vector &vCenter, - float flRadius, - const Vector &vColor, - int nSubDivs=7 ); - - -void ScratchPad_DrawAABB( - IScratchPad3D *pPad, - const Vector &vMins, - const Vector &vMaxs, - const Vector &vColor = Vector( 1,1,1 ) ); - - -#endif // SCRATCHPADUTILS_H diff --git a/public/SoundEmitterSystem/isoundemittersystembase.h b/public/SoundEmitterSystem/isoundemittersystembase.h deleted file mode 100644 index f7b41febb..000000000 --- a/public/SoundEmitterSystem/isoundemittersystembase.h +++ /dev/null @@ -1,268 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef ISOUNDEMITTERSYSTEMBASE_H -#define ISOUNDEMITTERSYSTEMBASE_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "tier1/utldict.h" -#include "soundflags.h" -#include "mathlib/compressed_vector.h" -#include "appframework/IAppSystem.h" - -#define SOUNDEMITTERSYSTEM_INTERFACE_VERSION "VSoundEmitter002" - -#define SOUNDGENDER_MACRO "$gender" -#define SOUNDGENDER_MACRO_LENGTH 7 // Length of above including $ - -typedef short HSOUNDSCRIPTHANDLE; -#define SOUNDEMITTER_INVALID_HANDLE (HSOUNDSCRIPTHANDLE)-1 - -class IFileList; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -struct CSoundParameters -{ - CSoundParameters() - { - channel = CHAN_AUTO; // 0 - volume = VOL_NORM; // 1.0f - pitch = PITCH_NORM; // 100 - - pitchlow = PITCH_NORM; - pitchhigh = PITCH_NORM; - - soundlevel = SNDLVL_NORM; // 75dB - soundname[ 0 ] = 0; - play_to_owner_only = false; - count = 0; - - delay_msec = 0; - } - - int channel; - float volume; - int pitch; - int pitchlow, pitchhigh; - soundlevel_t soundlevel; - // For weapon sounds... - bool play_to_owner_only; - int count; - char soundname[ 128 ]; - int delay_msec; -}; - -// A bit of a hack, but these are just utility function which are implemented in the SouneParametersInternal.cpp file which all users of this lib also compile -const char *SoundLevelToString( soundlevel_t level ); -const char *ChannelToString( int channel ); -const char *VolumeToString( float volume ); -const char *PitchToString( float pitch ); -soundlevel_t TextToSoundLevel( const char *key ); -int TextToChannel( const char *name ); -float RandomInterval( const interval_t &interval ); - -enum gender_t -{ - GENDER_NONE = 0, - GENDER_MALE, - GENDER_FEMALE, -}; - - -#pragma pack(1) -struct SoundFile -{ - SoundFile() - { - symbol = UTL_INVAL_SYMBOL; - gender = GENDER_NONE; - available = true; - COMPILE_TIME_ASSERT( sizeof(SoundFile) == 4 ); - } - - CUtlSymbol symbol; - byte gender; - byte available; -}; - -#pragma pack() - -#pragma pack(1) -template -struct sound_interval_t -{ - T start; - T range; - - interval_t &ToInterval( interval_t &dest ) const { dest.start = start; dest.range = range; return dest; } - void FromInterval( const interval_t &from ) { start = (T)from.start; range = (T)from.range; } - float Random() const { interval_t temp = { start, range }; return RandomInterval( temp ); } -}; - - -#pragma pack() - -typedef sound_interval_t volume_interval_t; -typedef sound_interval_t soundlevel_interval_t; -typedef sound_interval_t pitch_interval_t; - -#pragma pack(1) -struct CSoundParametersInternal -{ - CSoundParametersInternal(); - ~CSoundParametersInternal(); - - void CopyFrom( const CSoundParametersInternal& src ); - - bool operator == ( const CSoundParametersInternal& other ) const; - - const char *VolumeToString( void ) const; - const char *ChannelToString( void ) const; - const char *SoundLevelToString( void ) const; - const char *PitchToString( void ) const; - - void VolumeFromString( const char *sz ); - void ChannelFromString( const char *sz ); - void PitchFromString( const char *sz ); - void SoundLevelFromString( const char *sz ); - - int GetChannel() const { return channel; } - const volume_interval_t &GetVolume() const { return volume; } - const pitch_interval_t &GetPitch() const { return pitch; } - const soundlevel_interval_t &GetSoundLevel() const { return soundlevel; } - int GetDelayMsec() const { return delay_msec; } - bool OnlyPlayToOwner() const { return play_to_owner_only; } - bool HadMissingWaveFiles() const { return had_missing_wave_files; } - bool UsesGenderToken() const { return uses_gender_token; } - bool ShouldPreload() const { return m_bShouldPreload; } - - void SetChannel( int newChannel ) { channel = newChannel; } - void SetVolume( float start, float range = 0.0 ) { volume.start = start; volume.range = range; } - void SetPitch( float start, float range = 0.0 ) { pitch.start = (uint8)start; pitch.range = (uint8)range; } - void SetSoundLevel( float start, float range = 0.0 ) { soundlevel.start = (uint16)start; soundlevel.range = (uint16)range; } - void SetDelayMsec( int delay ) { delay_msec = delay; } - void SetShouldPreload( bool bShouldPreload ) { m_bShouldPreload = bShouldPreload; } - void SetOnlyPlayToOwner( bool b ) { play_to_owner_only = b; } - void SetHadMissingWaveFiles( bool b ) { had_missing_wave_files = b; } - void SetUsesGenderToken( bool b ) { uses_gender_token = b; } - - void AddSoundName( const SoundFile &soundFile ) { AddToTail( &m_pSoundNames, &m_nSoundNames, soundFile ); } - int NumSoundNames() const { return m_nSoundNames; } - SoundFile * GetSoundNames() { return ( m_nSoundNames == 1 ) ? (SoundFile *)&m_pSoundNames : m_pSoundNames; } - const SoundFile *GetSoundNames() const { return ( m_nSoundNames == 1 ) ? (SoundFile *)&m_pSoundNames : m_pSoundNames; } - - void AddConvertedName( const SoundFile &soundFile ) { AddToTail( &m_pConvertedNames, &m_nConvertedNames, soundFile ); } - int NumConvertedNames() const { return m_nConvertedNames; } - SoundFile * GetConvertedNames() { return ( m_nConvertedNames == 1 ) ? (SoundFile *)&m_pConvertedNames : m_pConvertedNames; } - const SoundFile *GetConvertedNames() const { return ( m_nConvertedNames == 1 ) ? (SoundFile *)&m_pConvertedNames : m_pConvertedNames; } - -private: - void operator=( const CSoundParametersInternal& src ); // disallow implicit copies - CSoundParametersInternal( const CSoundParametersInternal& src ); - - void AddToTail( SoundFile **pDest, uint16 *pDestCount, const SoundFile &source ); - - SoundFile * m_pSoundNames; // 4 - SoundFile * m_pConvertedNames; // 8 - uint16 m_nSoundNames; // 10 - uint16 m_nConvertedNames; // 12 - - volume_interval_t volume; // 16 - soundlevel_interval_t soundlevel; // 20 - pitch_interval_t pitch; // 22 - uint16 channel; // 24 - uint16 delay_msec; // 26 - - bool play_to_owner_only:1; // For weapon sounds... // 27 - // Internal use, for warning about missing .wav files - bool had_missing_wave_files:1; - bool uses_gender_token:1; - bool m_bShouldPreload:1; - - byte reserved; // 28 - - -}; -#pragma pack() - - -//----------------------------------------------------------------------------- -// Purpose: Base class for sound emitter system handling (can be used by tools) -//----------------------------------------------------------------------------- -abstract_class ISoundEmitterSystemBase : public IAppSystem -{ -public: - // Init, shutdown called after we know what mod is running - virtual bool ModInit() = 0; - virtual void ModShutdown() = 0; - - virtual int GetSoundIndex( const char *pName ) const = 0; - virtual bool IsValidIndex( int index ) = 0; - virtual int GetSoundCount( void ) = 0; - - virtual const char *GetSoundName( int index ) = 0; - virtual bool GetParametersForSound( const char *soundname, CSoundParameters& params, gender_t gender, bool isbeingemitted = false ) = 0; - - virtual const char *GetWaveName( CUtlSymbol& sym ) = 0; - virtual CUtlSymbol AddWaveName( const char *name ) = 0; - - virtual soundlevel_t LookupSoundLevel( const char *soundname ) = 0; - virtual const char *GetWavFileForSound( const char *soundname, char const *actormodel ) = 0; - virtual const char *GetWavFileForSound( const char *soundname, gender_t gender ) = 0; - virtual int CheckForMissingWavFiles( bool verbose ) = 0; - virtual const char *GetSourceFileForSound( int index ) const = 0; - - // Iteration methods - virtual int First() const = 0; - virtual int Next( int i ) const = 0; - virtual int InvalidIndex() const = 0; - - virtual CSoundParametersInternal *InternalGetParametersForSound( int index ) = 0; - - // The host application is responsible for dealing with dirty sound scripts, etc. - virtual bool AddSound( const char *soundname, const char *scriptfile, const CSoundParametersInternal& params ) = 0; - virtual void RemoveSound( const char *soundname ) = 0; - virtual void MoveSound( const char *soundname, const char *newscript ) = 0; - virtual void RenameSound( const char *soundname, const char *newname ) = 0; - - virtual void UpdateSoundParameters( const char *soundname, const CSoundParametersInternal& params ) = 0; - - virtual int GetNumSoundScripts() const = 0; - virtual char const *GetSoundScriptName( int index ) const = 0; - virtual bool IsSoundScriptDirty( int index ) const = 0; - virtual int FindSoundScript( const char *name ) const = 0; - virtual void SaveChangesToSoundScript( int scriptindex ) = 0; - - virtual void ExpandSoundNameMacros( CSoundParametersInternal& params, char const *wavename ) = 0; - virtual gender_t GetActorGender( char const *actormodel ) = 0; - virtual void GenderExpandString( char const *actormodel, char const *in, char *out, int maxlen ) = 0; - virtual void GenderExpandString( gender_t gender, char const *in, char *out, int maxlen ) = 0; - virtual bool IsUsingGenderToken( char const *soundname ) = 0; - - // For blowing away caches based on filetimstamps of the manifest, or of any of the - // .txt files that are read into the sound emitter system - virtual unsigned int GetManifestFileTimeChecksum() = 0; - - // Called from both client and server (single player) or just one (server only in dedicated server and client only if connected to a remote server) - // Called by LevelInitPreEntity to override sound scripts for the mod with level specific overrides based on custom mapnames, etc. - virtual void AddSoundOverrides( char const *scriptfile, bool bUnknown ) = 0; - - // Called by either client or server in LevelShutdown to clear out custom overrides - virtual void ClearSoundOverrides() = 0; - - virtual bool GetParametersForSoundEx( const char *soundname, HSOUNDSCRIPTHANDLE& handle, CSoundParameters& params, gender_t gender, bool isbeingemitted = false ) = 0; - virtual soundlevel_t LookupSoundLevelByHandle( char const *soundname, HSOUNDSCRIPTHANDLE& handle ) = 0; - - virtual void ReloadSoundEntriesInList( IFileList *pFileList ) = 0; -}; - -#endif // ISOUNDEMITTERSYSTEMBASE_H diff --git a/public/SoundParametersInternal.cpp b/public/SoundParametersInternal.cpp deleted file mode 100644 index 5568900d3..000000000 --- a/public/SoundParametersInternal.cpp +++ /dev/null @@ -1,575 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include "cbase.h" - -#if !defined(_STATIC_LINKED) || defined(SOUNDEMITTERSYSTEM_DLL) - -#include "SoundEmitterSystem/isoundemittersystembase.h" -#include "interval.h" -#include "soundchars.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -struct SoundChannels -{ - int channel; - const char *name; -}; - -// NOTE: This will need to be updated if channel names are added/removed -static SoundChannels g_pChannelNames[] = -{ - { CHAN_AUTO, "CHAN_AUTO" }, - { CHAN_WEAPON, "CHAN_WEAPON" }, - { CHAN_VOICE, "CHAN_VOICE" }, - { CHAN_ITEM, "CHAN_ITEM" }, - { CHAN_BODY, "CHAN_BODY" }, - { CHAN_STREAM, "CHAN_STREAM" }, - { CHAN_STATIC, "CHAN_STATIC" }, -}; - -struct VolumeLevel -{ - float volume; - const char *name; -}; - -static VolumeLevel g_pVolumeLevels[] = -{ - { VOL_NORM, "VOL_NORM" }, -}; - -struct PitchLookup -{ - float pitch; - const char *name; -}; - -static PitchLookup g_pPitchLookup[] = -{ - { PITCH_NORM, "PITCH_NORM" }, - { PITCH_LOW, "PITCH_LOW" }, - { PITCH_HIGH, "PITCH_HIGH" }, -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -struct SoundLevelLookup -{ - soundlevel_t level; - char const *name; -}; - -// NOTE: Needs to reflect the soundlevel_t enum defined in soundflags.h -static SoundLevelLookup g_pSoundLevels[] = -{ - { SNDLVL_NONE, "SNDLVL_NONE" }, - { SNDLVL_20dB, "SNDLVL_20dB" }, - { SNDLVL_25dB, "SNDLVL_25dB" }, - { SNDLVL_30dB, "SNDLVL_30dB" }, - { SNDLVL_35dB, "SNDLVL_35dB" }, - { SNDLVL_40dB, "SNDLVL_40dB" }, - { SNDLVL_45dB, "SNDLVL_45dB" }, - { SNDLVL_50dB, "SNDLVL_50dB" }, - { SNDLVL_55dB, "SNDLVL_55dB" }, - { SNDLVL_IDLE, "SNDLVL_IDLE" }, - { SNDLVL_TALKING, "SNDLVL_TALKING" }, - { SNDLVL_60dB, "SNDLVL_60dB" }, - { SNDLVL_65dB, "SNDLVL_65dB" }, - { SNDLVL_STATIC, "SNDLVL_STATIC" }, - { SNDLVL_70dB, "SNDLVL_70dB" }, - { SNDLVL_NORM, "SNDLVL_NORM" }, - { SNDLVL_75dB, "SNDLVL_75dB" }, - { SNDLVL_80dB, "SNDLVL_80dB" }, - { SNDLVL_85dB, "SNDLVL_85dB" }, - { SNDLVL_90dB, "SNDLVL_90dB" }, - { SNDLVL_95dB, "SNDLVL_95dB" }, - { SNDLVL_100dB, "SNDLVL_100dB" }, - { SNDLVL_105dB, "SNDLVL_105dB" }, - { SNDLVL_110dB, "SNDLVL_110dB" }, - { SNDLVL_120dB, "SNDLVL_120dB" }, - { SNDLVL_130dB, "SNDLVL_130dB" }, - { SNDLVL_GUNFIRE, "SNDLVL_GUNFIRE" }, - { SNDLVL_140dB, "SNDLVL_140dB" }, - { SNDLVL_150dB, "SNDLVL_150dB" }, - { SNDLVL_180dB, "SNDLVL_180dB" }, -}; - -static const char *_SoundLevelToString( soundlevel_t level ) -{ - int c = ARRAYSIZE( g_pSoundLevels ); - - int i; - - for ( i = 0 ; i < c; i++ ) - { - SoundLevelLookup *entry = &g_pSoundLevels[ i ]; - if ( entry->level == level ) - return entry->name; - } - - static char sz[ 32 ]; - Q_snprintf( sz, sizeof( sz ), "%i", (int)level ); - return sz; -} - -static const char *_ChannelToString( int channel ) -{ - int c = ARRAYSIZE( g_pChannelNames ); - - int i; - - for ( i = 0 ; i < c; i++ ) - { - SoundChannels *entry = &g_pChannelNames[ i ]; - if ( entry->channel == channel ) - return entry->name; - } - - static char sz[ 32 ]; - Q_snprintf( sz, sizeof( sz ), "%i", (int)channel ); - return sz; -} - -static const char *_VolumeToString( float volume ) -{ - int c = ARRAYSIZE( g_pVolumeLevels ); - - int i; - - for ( i = 0 ; i < c; i++ ) - { - VolumeLevel *entry = &g_pVolumeLevels[ i ]; - if ( entry->volume == volume ) - return entry->name; - } - - static char sz[ 32 ]; - Q_snprintf( sz, sizeof( sz ), "%.3f", volume ); - return sz; -} - -static const char *_PitchToString( float pitch ) -{ - int c = ARRAYSIZE( g_pPitchLookup ); - - int i; - - for ( i = 0 ; i < c; i++ ) - { - PitchLookup *entry = &g_pPitchLookup[ i ]; - if ( entry->pitch == pitch ) - return entry->name; - } - - static char sz[ 32 ]; - Q_snprintf( sz, sizeof( sz ), "%.3f", pitch ); - return sz; -} - -#define SNDLVL_PREFIX "SNDLVL_" - -soundlevel_t TextToSoundLevel( const char *key ) -{ - if ( !key ) - { - Assert( 0 ); - return SNDLVL_NORM; - } - - int c = ARRAYSIZE( g_pSoundLevels ); - - int i; - - for ( i = 0 ; i < c; i++ ) - { - SoundLevelLookup *entry = &g_pSoundLevels[ i ]; - if ( !Q_strcasecmp( key, entry->name ) ) - return entry->level; - } - - if ( !Q_strnicmp( key, SNDLVL_PREFIX, Q_strlen( SNDLVL_PREFIX ) ) ) - { - char const *val = key + Q_strlen( SNDLVL_PREFIX ); - int sndlvl = atoi( val ); - if ( sndlvl > 0 && sndlvl <= 180 ) - { - return ( soundlevel_t )sndlvl; - } - } - - DevMsg( "CSoundEmitterSystem: Unknown sound level %s\n", key ); - - return SNDLVL_NORM; -} - -//----------------------------------------------------------------------------- -// Purpose: Convert "chan_xxx" into integer value for channel -// Input : *name - -// Output : static int -//----------------------------------------------------------------------------- -int TextToChannel( const char *name ) -{ - if ( !name ) - { - Assert( 0 ); - // CHAN_AUTO - return CHAN_AUTO; - } - - if ( Q_strncasecmp( name, "chan_", strlen( "chan_" ) ) ) - { - return atoi( name ); - } - - int c = ARRAYSIZE( g_pChannelNames ); - int i; - - for ( i = 0; i < c; i++ ) - { - if ( !Q_strcasecmp( name, g_pChannelNames[ i ].name ) ) - { - return g_pChannelNames[ i ].channel; - } - } - - // At this point, it starts with chan_ but is not recognized - // atoi would return 0, so just do chan auto - DevMsg( "CSoundEmitterSystem: Warning, unknown channel type in sounds.txt (%s)\n", name ); - - return CHAN_AUTO; -} - -const char *SoundLevelToString( soundlevel_t level ) -{ - int c = ARRAYSIZE( g_pSoundLevels ); - - int i; - - for ( i = 0 ; i < c; i++ ) - { - SoundLevelLookup *entry = &g_pSoundLevels[ i ]; - if ( entry->level == level ) - return entry->name; - } - - static char sz[ 32 ]; - Q_snprintf( sz, sizeof( sz ), "%i", (int)level ); - return sz; -} - -const char *ChannelToString( int channel ) -{ - int c = ARRAYSIZE( g_pChannelNames ); - - int i; - - for ( i = 0 ; i < c; i++ ) - { - SoundChannels *entry = &g_pChannelNames[ i ]; - if ( entry->channel == channel ) - return entry->name; - } - - static char sz[ 32 ]; - Q_snprintf( sz, sizeof( sz ), "%i", (int)channel ); - return sz; -} - -const char *VolumeToString( float volume ) -{ - int c = ARRAYSIZE( g_pVolumeLevels ); - - int i; - - for ( i = 0 ; i < c; i++ ) - { - VolumeLevel *entry = &g_pVolumeLevels[ i ]; - if ( entry->volume == volume ) - return entry->name; - } - - static char sz[ 32 ]; - Q_snprintf( sz, sizeof( sz ), "%.3f", volume ); - return sz; -} - -const char *PitchToString( float pitch ) -{ - int c = ARRAYSIZE( g_pPitchLookup ); - - int i; - - for ( i = 0 ; i < c; i++ ) - { - PitchLookup *entry = &g_pPitchLookup[ i ]; - if ( entry->pitch == pitch ) - return entry->name; - } - - static char sz[ 32 ]; - Q_snprintf( sz, sizeof( sz ), "%.3f", pitch ); - return sz; -} - -CSoundParametersInternal::CSoundParametersInternal() -{ - m_pConvertedNames = m_pSoundNames = NULL; - m_nConvertedNames = m_nSoundNames = 0; - channel = CHAN_AUTO; // 0 - - volume.start = VOL_NORM; // 1.0f - volume.range = 0.0f; - - pitch.start = PITCH_NORM; // 100 - pitch.range = 0; - - soundlevel.start = SNDLVL_NORM; // 75dB - soundlevel.range = 0; - delay_msec = 0; - play_to_owner_only = false; - had_missing_wave_files = false; - uses_gender_token = false; - -} - -CSoundParametersInternal::CSoundParametersInternal( const CSoundParametersInternal& src ) -{ - m_pSoundNames = NULL; - m_pConvertedNames = NULL; - CopyFrom( src ); -} - -CSoundParametersInternal::~CSoundParametersInternal() -{ - if ( m_nSoundNames > 1 ) - delete m_pSoundNames; - if ( m_nConvertedNames > 1 ) - delete m_pConvertedNames; -} - -void CSoundParametersInternal::CopyFrom( const CSoundParametersInternal& src ) -{ - if ( m_nSoundNames > 1 ) - delete m_pSoundNames; - if ( m_nConvertedNames > 1 ) - delete m_pConvertedNames; - - channel = src.channel; - volume = src.volume; - pitch = src.pitch; - soundlevel = src.soundlevel; - delay_msec = src.delay_msec; - play_to_owner_only = src.play_to_owner_only; - - m_nSoundNames = src.m_nSoundNames; - if ( m_nSoundNames ) - { - if ( m_nSoundNames > 1 ) - { - m_pSoundNames = new SoundFile[m_nSoundNames]; - memcpy( m_pSoundNames, src.m_pSoundNames, m_nSoundNames * sizeof(SoundFile) ); - } - else - { - m_pSoundNames = src.m_pSoundNames; - } - } - else - { - m_pSoundNames = NULL; - } - - m_nConvertedNames = src.m_nConvertedNames; - if ( m_nConvertedNames ) - { - if ( m_nConvertedNames > 1 ) - { - m_pConvertedNames = new SoundFile[m_nConvertedNames]; - memcpy( m_pConvertedNames, src.m_pConvertedNames, m_nConvertedNames * sizeof(SoundFile) ); - } - else - { - m_pConvertedNames = src.m_pConvertedNames; - } - } - else - { - m_pConvertedNames = NULL; - } - - had_missing_wave_files = src.had_missing_wave_files; - uses_gender_token = src.uses_gender_token; -} - -#define CompareInterval( i1, i2 ) ( memcmp( &(i1), &(i2), sizeof(i1) ) == 0 ) - -bool CSoundParametersInternal::operator == ( const CSoundParametersInternal& other ) const -{ - if ( this == &other ) - return true; - - if ( channel != other.channel ) - return false; - if ( !CompareInterval( volume, other.volume ) ) - return false; - if ( !CompareInterval( pitch, other.pitch ) ) - return false; - if ( !CompareInterval( soundlevel, other.soundlevel ) ) - return false; - if ( delay_msec != other.delay_msec ) - return false; - if ( play_to_owner_only != other.play_to_owner_only ) - return false; - - if ( m_nSoundNames != other.m_nSoundNames ) - return false; - - // Compare items - int c = m_nSoundNames; - for ( int i = 0; i < c; i++ ) - { - if ( GetSoundNames()[ i ].symbol != other.GetSoundNames()[ i ].symbol ) - return false; - } - - return true; -} - -float16 ZERO_FLOAT16; - -const char *CSoundParametersInternal::VolumeToString( void ) const -{ - if ( volume.range == ZERO_FLOAT16 ) - { - return _VolumeToString( volume.start ); - } - - static char sz[ 64 ]; - Q_snprintf( sz, sizeof( sz ), "%.3f, %.3f", (float)volume.start, (float)volume.start + (float)volume.range ); - return sz; -} - -const char *CSoundParametersInternal::ChannelToString( void ) const -{ - return _ChannelToString( channel ); -} - -const char *CSoundParametersInternal::SoundLevelToString( void ) const -{ - if ( soundlevel.range == 0 ) - { - return _SoundLevelToString( (soundlevel_t)(int)soundlevel.start ); - } - - static char sz[ 64 ]; - Q_snprintf( sz, sizeof( sz ), "%i, %i", (soundlevel_t)(int)soundlevel.start, (soundlevel_t)(int)(soundlevel.start + soundlevel.range ) ); - return sz; -} - -const char *CSoundParametersInternal::PitchToString( void ) const -{ - if ( pitch.range == 0 ) - { - return _PitchToString( (int)pitch.start ); - } - - static char sz[ 64 ]; - Q_snprintf( sz, sizeof( sz ), "%i, %i", (int)pitch.start, (int)(pitch.start + pitch.range ) ); - return sz; -} - -void CSoundParametersInternal::VolumeFromString( const char *sz ) -{ - if ( !Q_strcasecmp( sz, "VOL_NORM" ) ) - { - volume.start = VOL_NORM; - volume.range = 0.0f; - } - else - { - volume.FromInterval( ReadInterval( sz ) ); - } -} - -void CSoundParametersInternal::ChannelFromString( const char *sz ) -{ - channel = TextToChannel( sz ); -} - -void CSoundParametersInternal::PitchFromString( const char *sz ) -{ - if ( !Q_strcasecmp( sz, "PITCH_NORM" ) ) - { - pitch.start = PITCH_NORM; - pitch.range = 0; - } - else if ( !Q_strcasecmp( sz, "PITCH_LOW" ) ) - { - pitch.start = PITCH_LOW; - pitch.range = 0; - } - else if ( !Q_strcasecmp( sz, "PITCH_HIGH" ) ) - { - pitch.start = PITCH_HIGH; - pitch.range = 0; - } - else - { - pitch.FromInterval( ReadInterval( sz ) ); - } -} - -void CSoundParametersInternal::SoundLevelFromString( const char *sz ) -{ - if ( !Q_strncasecmp( sz, "SNDLVL_", strlen( "SNDLVL_" ) ) ) - { - soundlevel.start = TextToSoundLevel( sz ); - soundlevel.range = 0; - } - else - { - soundlevel.FromInterval( ReadInterval( sz ) ); - } -} - -void CSoundParametersInternal::AddToTail( SoundFile **pDest, uint16 *pDestCount, const SoundFile &source ) -{ - (*pDestCount)++; - if ( *pDestCount == 1 ) - { - // NOTE: when there's only one soundfile in the list, we store it - // packed into the pointer itself, the four bytes for the pointer is just used to store the sound file! - COMPILE_TIME_ASSERT( sizeof(SoundFile) <= sizeof(SoundFile *) ); - *((SoundFile *)(pDest)) = source; - } - else - { - SoundFile temp; - if ( *pDestCount == 2 ) - { - // Copying from a list of one soundfile. Save off the struct - // packed into the pointer field. - temp = *((SoundFile *)(pDest)); - *pDest = NULL; - } - - *pDest = (SoundFile *)realloc( *pDest, (*pDestCount) * sizeof(SoundFile) ); - (*pDest)[ *pDestCount - 1 ] = source; - - if ( *pDestCount == 2 ) - { - (*pDest)[0] = temp; - } - } -} - -#endif // !_STATIC_LINKED || SOUNDEMITTERSYSTEM_DLL diff --git a/public/UnicodeFileHelpers.cpp b/public/UnicodeFileHelpers.cpp deleted file mode 100644 index 90994cb69..000000000 --- a/public/UnicodeFileHelpers.cpp +++ /dev/null @@ -1,240 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include -#include -#include "UtlBuffer.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Advances until non-whitespace hit -//----------------------------------------------------------------------------- -wchar_t *AdvanceOverWhitespace(wchar_t *Start) -{ - while (*Start != 0 && iswspace(*Start)) - { - Start++; - } - - return Start; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -wchar_t *ReadUnicodeToken(wchar_t *start, wchar_t *token, int tokenBufferSize, bool "ed) -{ - // skip over any whitespace - start = AdvanceOverWhitespace(start); - quoted = false; - *token = 0; - - if (!*start) - { - return start; - } - - // check to see if it's a quoted string - if (*start == '\"') - { - quoted = true; - // copy out the string until we hit an end quote - start++; - int count = 0; - while (*start && *start != '\"' && count < tokenBufferSize-1) - { - // check for special characters - if (*start == '\\' && *(start+1) == 'n') - { - start++; - *token = '\n'; - } - else if (*start == '\\' && *(start+1) == '\"') - { - start++; - *token = '\"'; - } - else - { - *token = *start; - } - - start++; - token++; - count++; - } - - if (*start == '\"') - { - start++; - } - } - else - { - // copy out the string until we hit a whitespace - int count = 0; - while (*start && !iswspace(*start) && count < tokenBufferSize-1) - { - // no checking for special characters if it's not a quoted string - *token = *start; - - start++; - token++; - count++; - } - } - - *token = 0; - return start; -} - -//----------------------------------------------------------------------------- -// Purpose: Same as above but no translation of \n -//----------------------------------------------------------------------------- -wchar_t *ReadUnicodeTokenNoSpecial(wchar_t *start, wchar_t *token, int tokenBufferSize, bool "ed) -{ - // skip over any whitespace - start = AdvanceOverWhitespace(start); - quoted = false; - *token = 0; - - if (!*start) - { - return start; - } - - // check to see if it's a quoted string - if (*start == '\"') - { - quoted = true; - // copy out the string until we hit an end quote - start++; - int count = 0; - while (*start && *start != '\"' && count < tokenBufferSize-1) - { - // check for special characters - /* - if (*start == '\\' && *(start+1) == 'n') - { - start++; - *token = '\n'; - } - else - */ - if (*start == '\\' && *(start+1) == '\"') - { - start++; - *token = '\"'; - } - else - { - *token = *start; - } - - start++; - token++; - count++; - } - - if (*start == '\"') - { - start++; - } - } - else - { - // copy out the string until we hit a whitespace - int count = 0; - while (*start && !iswspace(*start) && count < tokenBufferSize-1) - { - // no checking for special characters if it's not a quoted string - *token = *start; - - start++; - token++; - count++; - } - } - - *token = 0; - return start; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the first character after the next EOL characters -//----------------------------------------------------------------------------- -wchar_t *ReadToEndOfLine(wchar_t *start) -{ - if (!*start) - return start; - - while (*start) - { - if (*start == 0x0D || *start== 0x0A) - break; - start++; - } - - while (*start == 0x0D || *start== 0x0A) - start++; - - return start; -} - -//----------------------------------------------------------------------------- -// Purpose: file writing -//----------------------------------------------------------------------------- -void WriteUnicodeString(CUtlBuffer &buf, const wchar_t *string, bool addQuotes) -{ - if (addQuotes) - { - buf.PutUnsignedShort('\"'); - } - - for (const wchar_t *ws = string; *ws != 0; ws++) - { - // handle special characters - if (addQuotes && *ws == '\"') - { - buf.PutUnsignedShort('\\'); - } - // write the character - buf.PutUnsignedShort(*ws); - } - - if (addQuotes) - { - buf.PutUnsignedShort('\"'); - } -} - -//----------------------------------------------------------------------------- -// Purpose: file writing -//----------------------------------------------------------------------------- -void WriteAsciiStringAsUnicode(CUtlBuffer &buf, const char *string, bool addQuotes) -{ - if (addQuotes) - { - buf.PutUnsignedShort('\"'); - } - - for (const char *sz = string; *sz != 0; sz++) - { - // handle special characters - if (addQuotes && *sz == '\"') - { - buf.PutUnsignedShort('\\'); - } - buf.PutUnsignedShort(*sz); - } - - if (addQuotes) - { - buf.PutUnsignedShort('\"'); - } -} diff --git a/public/UnicodeFileHelpers.h b/public/UnicodeFileHelpers.h deleted file mode 100644 index 9df309c95..000000000 --- a/public/UnicodeFileHelpers.h +++ /dev/null @@ -1,28 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef UNICODEFILEHELPERS_H -#define UNICODEFILEHELPERS_H -#ifdef _WIN32 -#pragma once -#endif - -#include - -// helper functions for parsing unicode file buffers -wchar_t *AdvanceOverWhitespace(wchar_t *start); -wchar_t *ReadUnicodeToken(wchar_t *start, wchar_t *token, int tokenBufferSize, bool "ed); -wchar_t *ReadUnicodeTokenNoSpecial(wchar_t *start, wchar_t *token, int tokenBufferSize, bool "ed); -wchar_t *ReadToEndOfLine(wchar_t *start); - -// writing to unicode files via CUtlBuffer -class CUtlBuffer; -void WriteUnicodeString(CUtlBuffer &buffer, const wchar_t *string, bool addQuotes = false); -void WriteAsciiStringAsUnicode(CUtlBuffer &buffer, const char *string, bool addQuotes = false); - - - -#endif // UNICODEFILEHELPERS_H diff --git a/public/UtlCachedFileData.h b/public/UtlCachedFileData.h deleted file mode 100644 index 0f4beaf77..000000000 --- a/public/UtlCachedFileData.h +++ /dev/null @@ -1,992 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef UTLCACHEDFILEDATA_H -#define UTLCACHEDFILEDATA_H -#if defined( WIN32 ) -#pragma once -#endif - -#include "filesystem.h" // FileNameHandle_t -#include "utlrbtree.h" -#include "utlbuffer.h" -#include "UtlSortVector.h" -#include "tier1/strtools.h" - -#include "tier0/memdbgon.h" - -// If you change to serialization protocols, this must be bumped... -#define UTL_CACHE_SYSTEM_VERSION 2 - -#define UTL_CACHED_FILE_DATA_UNDEFINED_DISKINFO (long)-2 - -// Cacheable types must derive from this and implement the appropriate methods... -abstract_class IBaseCacheInfo -{ -public: - virtual void Save( CUtlBuffer& buf ) = 0; - virtual void Restore( CUtlBuffer& buf ) = 0; - - virtual void Rebuild( char const *filename ) = 0; -}; - -typedef unsigned int (*PFNCOMPUTECACHEMETACHECKSUM)( void ); - -typedef enum -{ - UTL_CACHED_FILE_USE_TIMESTAMP = 0, - UTL_CACHED_FILE_USE_FILESIZE, -} UtlCachedFileDataType_t; - -template -class CUtlCachedFileData -{ -public: - CUtlCachedFileData - ( - char const *repositoryFileName, - int version, - PFNCOMPUTECACHEMETACHECKSUM checksumfunc = NULL, - UtlCachedFileDataType_t fileCheckType = UTL_CACHED_FILE_USE_TIMESTAMP, - bool nevercheckdisk = false, - bool readonly = false, - bool savemanifest = false - ) - : m_Elements( 0, 0, FileNameHandleLessFunc ), - m_pszRepositoryFileName( repositoryFileName ), - m_nVersion( version ), - m_pfnMetaChecksum( checksumfunc ), - m_uCurrentMetaChecksum( 0u ), - m_fileCheckType( fileCheckType ), - m_bNeverCheckDisk( nevercheckdisk ), - m_bReadOnly( readonly ), - m_bSaveManifest( savemanifest ), - m_bDirty( false ), - m_bInitialized( false ) - { - Assert( m_pszRepositoryFileName && m_pszRepositoryFileName[ 0 ] ); - } - - virtual ~CUtlCachedFileData() - { - m_Elements.RemoveAll(); - int c = m_Data.Count(); - for ( int i = 0; i < c ; ++i ) - { - delete m_Data[ i ]; - } - m_Data.RemoveAll(); - } - - T* Get( char const *filename ); - const T* Get( char const *filename ) const; - - T* operator[]( int i ); - const T* operator[]( int i ) const; - - int Count() const; - - void GetElementName( int i, char *buf, int buflen ) - { - buf[ 0 ] = 0; - if ( !m_Elements.IsValidIndex( i ) ) - return; - - g_pFullFileSystem->String( m_Elements[ i ].handle, buf, buflen ); - } - - bool EntryExists( char const *filename ) const - { - ElementType_t element; - element.handle = g_pFullFileSystem->FindOrAddFileName( filename ); - int idx = m_Elements.Find( element ); - return idx != m_Elements.InvalidIndex() ? true : false; - } - - void SetElement( char const *name, long fileinfo, T* src ) - { - SetDirty( true ); - - int idx = GetIndex( name ); - - Assert( idx != m_Elements.InvalidIndex() ); - - ElementType_t& e = m_Elements[ idx ]; - - CUtlBuffer buf( 0, 0, 0 ); - - Assert( e.dataIndex != m_Data.InvalidIndex() ); - - T *dest = m_Data[ e.dataIndex ]; - - Assert( dest ); - - // I suppose we could do an assignment operator, but this should save/restore the data element just fine for - // tool purposes - ((IBaseCacheInfo *)src)->Save( buf ); - ((IBaseCacheInfo *)dest)->Restore( buf ); - - e.fileinfo = fileinfo; - if ( ( e.fileinfo == -1 ) && - ( m_fileCheckType == UTL_CACHED_FILE_USE_FILESIZE ) ) - { - e.fileinfo = 0; - } - // Force recheck - e.diskfileinfo = UTL_CACHED_FILE_DATA_UNDEFINED_DISKINFO; - } - - // If you create a cache and don't call init/shutdown, you can call this to do a quick check to see if the checksum/version - // will cause a rebuild... - bool IsUpToDate(); - - void Shutdown(); - bool Init(); - - void Save(); - - void Reload(); - - void ForceRecheckDiskInfo(); - // Iterates all entries and gets filesystem info and optionally causes rebuild on any existing items which are out of date - void CheckDiskInfo( bool force_rebuild, long cacheFileTime = 0L ); - - void SaveManifest(); - bool ManifestExists(); - - long GetFileInfo( char const *filename ) - { - ElementType_t element; - element.handle = g_pFullFileSystem->FindOrAddFileName( filename ); - int idx = m_Elements.Find( element ); - if ( idx == m_Elements.InvalidIndex() ) - { - return 0L; - } - - return m_Elements[ idx ].fileinfo; - } - - int GetNumElements() - { - return m_Elements.Count(); - } - - bool IsDirty() const - { - return m_bDirty; - } - - T *RebuildItem( const char *filename ); - -private: - - void InitSmallBuffer( FileHandle_t& fh, int fileSize, bool& deleteFile ); - void InitLargeBuffer( FileHandle_t& fh, bool& deleteFile ); - - int GetIndex( const char *filename ) - { - ElementType_t element; - element.handle = g_pFullFileSystem->FindOrAddFileName( filename ); - int idx = m_Elements.Find( element ); - if ( idx == m_Elements.InvalidIndex() ) - { - T *data = new T(); - - int dataIndex = m_Data.AddToTail( data ); - idx = m_Elements.Insert( element ); - m_Elements[ idx ].dataIndex = dataIndex; - } - - return idx; - } - - void CheckInit(); - - void SetDirty( bool dirty ) - { - m_bDirty = dirty; - } - - void RebuildCache( char const *filename, T *data ); - - struct ElementType_t - { - ElementType_t() : - handle( 0 ), - fileinfo( 0 ), - diskfileinfo( UTL_CACHED_FILE_DATA_UNDEFINED_DISKINFO ), - dataIndex( -1 ) - { - } - - FileNameHandle_t handle; - long fileinfo; - long diskfileinfo; - int dataIndex; - }; - - static bool FileNameHandleLessFunc( ElementType_t const &lhs, ElementType_t const &rhs ) - { - return lhs.handle < rhs.handle; - } - - CUtlRBTree< ElementType_t > m_Elements; - CUtlVector< T * > m_Data; - char const *m_pszRepositoryFileName; - int m_nVersion; - PFNCOMPUTECACHEMETACHECKSUM m_pfnMetaChecksum; - unsigned int m_uCurrentMetaChecksum; - UtlCachedFileDataType_t m_fileCheckType; - bool m_bNeverCheckDisk : 1; - bool m_bReadOnly : 1; - bool m_bSaveManifest : 1; - bool m_bDirty : 1; - bool m_bInitialized : 1; - -}; - - -template -T* CUtlCachedFileData::Get( char const *filename ) -{ - int idx = GetIndex( filename ); - - ElementType_t& e = m_Elements[ idx ]; - - if ( e.fileinfo == -1 && - m_fileCheckType == UTL_CACHED_FILE_USE_FILESIZE ) - { - e.fileinfo = 0; - } - long cachefileinfo = e.fileinfo; - // Set the disk fileinfo the first time we encounter the filename - if ( e.diskfileinfo == UTL_CACHED_FILE_DATA_UNDEFINED_DISKINFO ) - { - if ( m_bNeverCheckDisk ) - { - e.diskfileinfo = cachefileinfo; - } - else - { - if ( m_fileCheckType == UTL_CACHED_FILE_USE_FILESIZE ) - { - e.diskfileinfo = g_pFullFileSystem->Size( filename, "GAME" ); - // Missing files get a disk file size of 0 - if ( e.diskfileinfo == -1 ) - { - e.diskfileinfo = 0; - } - } - else - { - e.diskfileinfo = g_pFullFileSystem->GetFileTime( filename, "GAME" ); - } - } - } - - Assert( e.dataIndex != m_Data.InvalidIndex() ); - - T *data = m_Data[ e.dataIndex ]; - - Assert( data ); - - // Compare fileinfo to disk fileinfo and rebuild cache if out of date or not correct... - if ( cachefileinfo != e.diskfileinfo ) - { - if ( !m_bReadOnly ) - { - RebuildCache( filename, data ); - } - e.fileinfo = e.diskfileinfo; - } - - return data; -} - -template -const T* CUtlCachedFileData::Get( char const *filename ) const -{ - return const_cast< CUtlCachedFileData * >(this)->Get( filename ); -} - -template -T* CUtlCachedFileData::operator[]( int i ) -{ - return m_Data[ m_Elements[ i ].dataIndex ]; -} - -template -const T* CUtlCachedFileData::operator[]( int i ) const -{ - return m_Data[ m_Elements[ i ].dataIndex ]; -} - -template -int CUtlCachedFileData::Count() const -{ - return m_Elements.Count(); -} - -template -void CUtlCachedFileData::Reload() -{ - Shutdown(); - Init(); -} - -template -bool CUtlCachedFileData::IsUpToDate() -{ - // Don't call Init/Shutdown if using this method!!! - Assert( !m_bInitialized ); - - if ( !m_pszRepositoryFileName || !m_pszRepositoryFileName[ 0 ] ) - { - Error( "CUtlCachedFileData: Can't IsUpToDate, no repository file specified." ); - return false; - } - - // Always compute meta checksum - m_uCurrentMetaChecksum = m_pfnMetaChecksum ? (*m_pfnMetaChecksum)() : 0; - - FileHandle_t fh; - - fh = g_pFullFileSystem->Open( m_pszRepositoryFileName, "rb", "MOD" ); - if ( fh == FILESYSTEM_INVALID_HANDLE ) - { - return false; - } - - // Version data is in first 12 bytes of file - byte header[ 12 ]; - g_pFullFileSystem->Read( header, sizeof( header ), fh ); - g_pFullFileSystem->Close( fh ); - - int cacheversion = *( int *)&header[ 0 ]; - - if ( UTL_CACHE_SYSTEM_VERSION != cacheversion ) - { - DevMsg( "Discarding repository '%s' due to cache system version change\n", m_pszRepositoryFileName ); - Assert( !m_bReadOnly ); - if ( !m_bReadOnly ) - { - g_pFullFileSystem->RemoveFile( m_pszRepositoryFileName, "MOD" ); - } - return false; - } - - // Now parse data from the buffer - int version = *( int *)&header[ 4 ]; - if ( version != m_nVersion ) - { - DevMsg( "Discarding repository '%s' due to version change\n", m_pszRepositoryFileName ); - Assert( !m_bReadOnly ); - if ( !m_bReadOnly ) - { - g_pFullFileSystem->RemoveFile( m_pszRepositoryFileName, "MOD" ); - } - return false; - } - - // This is a checksum based on any meta data files which the cache depends on (supplied by a passed in - // meta data function - unsigned int cache_meta_checksum = (unsigned int)*( int *)&header[ 8 ]; - - if ( cache_meta_checksum != m_uCurrentMetaChecksum ) - { - DevMsg( "Discarding repository '%s' due to meta checksum change\n", m_pszRepositoryFileName ); - Assert( !m_bReadOnly ); - if ( !m_bReadOnly ) - { - g_pFullFileSystem->RemoveFile( m_pszRepositoryFileName, "MOD" ); - } - return false; - } - - // Looks valid - return true; -} - -template -void CUtlCachedFileData::InitSmallBuffer( FileHandle_t& fh, int fileSize, bool& deleteFile ) -{ - deleteFile = false; - - CUtlBuffer loadBuf; - g_pFullFileSystem->ReadToBuffer( fh, loadBuf ); - g_pFullFileSystem->Close( fh ); - - int cacheversion = 0; - loadBuf.Get( &cacheversion, sizeof( cacheversion ) ); - - if ( UTL_CACHE_SYSTEM_VERSION == cacheversion ) - { - // Now parse data from the buffer - int version = loadBuf.GetInt(); - - if ( version == m_nVersion ) - { - // This is a checksum based on any meta data files which the cache depends on (supplied by a passed in - // meta data function - unsigned int cache_meta_checksum = loadBuf.GetInt(); - - if ( cache_meta_checksum == m_uCurrentMetaChecksum ) - { - int count = loadBuf.GetInt(); - - Assert( count < 2000000 ); - - CUtlBuffer buf( 0, 0, 0 ); - - for ( int i = 0 ; i < count; ++i ) - { - int bufsize = loadBuf.GetInt(); - Assert( bufsize < 1000000 ); - - buf.Clear(); - buf.EnsureCapacity( bufsize ); - - loadBuf.Get( buf.Base(), bufsize ); - - buf.SeekGet( CUtlBuffer::SEEK_HEAD, 0 ); - buf.SeekPut( CUtlBuffer::SEEK_HEAD, bufsize ); - - // Read the element name - char elementFileName[ 512 ]; - buf.GetString( elementFileName, sizeof( elementFileName ) ); - - // Now read the element - int slot = GetIndex( elementFileName ); - - Assert( slot != m_Elements.InvalidIndex() ); - - ElementType_t& element = m_Elements[ slot ]; - - element.fileinfo = buf.GetInt(); - if ( ( element.fileinfo == -1 ) && - ( m_fileCheckType == UTL_CACHED_FILE_USE_FILESIZE ) ) - { - element.fileinfo = 0; - } - - Assert( element.dataIndex != m_Data.InvalidIndex() ); - - T *data = m_Data[ element.dataIndex ]; - - Assert( data ); - - ((IBaseCacheInfo *)data)->Restore( buf ); - } - } - else - { - Msg( "Discarding repository '%s' due to meta checksum change\n", m_pszRepositoryFileName ); - deleteFile = true; - } - } - else - { - Msg( "Discarding repository '%s' due to version change\n", m_pszRepositoryFileName ); - deleteFile = true; - } - } - else - { - DevMsg( "Discarding repository '%s' due to cache system version change\n", m_pszRepositoryFileName ); - deleteFile = true; - } -} - -template -void CUtlCachedFileData::InitLargeBuffer( FileHandle_t& fh, bool& deleteFile ) -{ - deleteFile = false; - - int cacheversion = 0; - g_pFullFileSystem->Read( &cacheversion, sizeof( cacheversion ), fh ); - - if ( UTL_CACHE_SYSTEM_VERSION == cacheversion ) - { - // Now parse data from the buffer - int version = 0; - g_pFullFileSystem->Read( &version, sizeof( version ), fh ); - - if ( version == m_nVersion ) - { - // This is a checksum based on any meta data files which the cache depends on (supplied by a passed in - // meta data function - unsigned int cache_meta_checksum = 0; - - g_pFullFileSystem->Read( &cache_meta_checksum, sizeof( cache_meta_checksum ), fh ); - - if ( cache_meta_checksum == m_uCurrentMetaChecksum ) - { - int count = 0; - - g_pFullFileSystem->Read( &count, sizeof( count ), fh ); - - Assert( count < 2000000 ); - - CUtlBuffer buf( 0, 0, 0 ); - - for ( int i = 0 ; i < count; ++i ) - { - int bufsize = 0; - g_pFullFileSystem->Read( &bufsize, sizeof( bufsize ), fh ); - - Assert( bufsize < 1000000 ); - - buf.Clear(); - buf.EnsureCapacity( bufsize ); - - int nBytesRead = g_pFullFileSystem->Read( buf.Base(), bufsize, fh ); - - buf.SeekGet( CUtlBuffer::SEEK_HEAD, 0 ); - buf.SeekPut( CUtlBuffer::SEEK_HEAD, nBytesRead ); - - // Read the element name - char elementFileName[ 512 ]; - buf.GetString( elementFileName, sizeof( elementFileName ) ); - - // Now read the element - int slot = GetIndex( elementFileName ); - - Assert( slot != m_Elements.InvalidIndex() ); - - ElementType_t& element = m_Elements[ slot ]; - - element.fileinfo = buf.GetInt(); - if ( ( element.fileinfo == -1 ) && - ( m_fileCheckType == UTL_CACHED_FILE_USE_FILESIZE ) ) - { - element.fileinfo = 0; - } - - Assert( element.dataIndex != m_Data.InvalidIndex() ); - - T *data = m_Data[ element.dataIndex ]; - - Assert( data ); - - ((IBaseCacheInfo *)data)->Restore( buf ); - } - } - else - { - Msg( "Discarding repository '%s' due to meta checksum change\n", m_pszRepositoryFileName ); - deleteFile = true; - } - } - else - { - Msg( "Discarding repository '%s' due to version change\n", m_pszRepositoryFileName ); - deleteFile = true; - } - } - else - { - DevMsg( "Discarding repository '%s' due to cache system version change\n", m_pszRepositoryFileName ); - deleteFile = true; - } - - g_pFullFileSystem->Close( fh ); -} - -template -bool CUtlCachedFileData::Init() -{ - if ( m_bInitialized ) - { - return true; - } - - m_bInitialized = true; - - if ( !m_pszRepositoryFileName || !m_pszRepositoryFileName[ 0 ] ) - { - Error( "CUtlCachedFileData: Can't Init, no repository file specified." ); - return false; - } - - // Always compute meta checksum - m_uCurrentMetaChecksum = m_pfnMetaChecksum ? (*m_pfnMetaChecksum)() : 0; - - FileHandle_t fh; - - fh = g_pFullFileSystem->Open( m_pszRepositoryFileName, "rb", "MOD" ); - if ( fh == FILESYSTEM_INVALID_HANDLE ) - { - // Nothing on disk, we'll recreate everything from scratch... - SetDirty( true ); - return true; - } - long fileTime = g_pFullFileSystem->GetFileTime( m_pszRepositoryFileName, "MOD" ); - int size = g_pFullFileSystem->Size( fh ); - - bool deletefile = false; - - if ( size > 1024 * 1024 ) - { - InitLargeBuffer( fh, deletefile ); - } - else - { - InitSmallBuffer( fh, size, deletefile ); - } - - if ( deletefile ) - { - Assert( !m_bReadOnly ); - if ( !m_bReadOnly ) - { - g_pFullFileSystem->RemoveFile( m_pszRepositoryFileName, "MOD" ); - } - SetDirty( true ); - } - CheckDiskInfo( false, fileTime ); - return true; -} - -template -void CUtlCachedFileData::Save() -{ - char path[ 512 ]; - Q_strncpy( path, m_pszRepositoryFileName, sizeof( path ) ); - Q_StripFilename( path ); - - g_pFullFileSystem->CreateDirHierarchy( path, "MOD" ); - - if ( g_pFullFileSystem->FileExists( m_pszRepositoryFileName, "MOD" ) && - !g_pFullFileSystem->IsFileWritable( m_pszRepositoryFileName, "MOD" ) ) - { - g_pFullFileSystem->SetFileWritable( m_pszRepositoryFileName, true, "MOD" ); - } - - // Now write to file - FileHandle_t fh; - fh = g_pFullFileSystem->Open( m_pszRepositoryFileName, "wb" ); - if ( FILESYSTEM_INVALID_HANDLE == fh ) - { - Warning( "Unable to persist cache '%s', check file permissions\n", m_pszRepositoryFileName ); - } - else - { - SetDirty( false ); - - int v = UTL_CACHE_SYSTEM_VERSION; - g_pFullFileSystem->Write( &v, sizeof( v ), fh ); - v = m_nVersion; - g_pFullFileSystem->Write( &v, sizeof( v ), fh ); - v = (int)m_uCurrentMetaChecksum; - g_pFullFileSystem->Write( &v, sizeof( v ), fh ); - - // Element count - int c = Count(); - - g_pFullFileSystem->Write( &c, sizeof( c ), fh ); - - // Save repository back out to disk... - CUtlBuffer buf( 0, 0, 0 ); - - for ( int i = m_Elements.FirstInorder(); i != m_Elements.InvalidIndex(); i = m_Elements.NextInorder( i ) ) - { - buf.SeekPut( CUtlBuffer::SEEK_HEAD, 0 ); - - ElementType_t& element = m_Elements[ i ]; - - char fn[ 512 ]; - g_pFullFileSystem->String( element.handle, fn, sizeof( fn ) ); - - buf.PutString( fn ); - buf.PutInt( element.fileinfo ); - - Assert( element.dataIndex != m_Data.InvalidIndex() ); - - T *data = m_Data[ element.dataIndex ]; - - Assert( data ); - - ((IBaseCacheInfo *)data)->Save( buf ); - - int bufsize = buf.TellPut(); - g_pFullFileSystem->Write( &bufsize, sizeof( bufsize ), fh ); - g_pFullFileSystem->Write( buf.Base(), bufsize, fh ); - } - - g_pFullFileSystem->Close( fh ); - } - - if ( m_bSaveManifest ) - { - SaveManifest(); - } -} - -template -void CUtlCachedFileData::Shutdown() -{ - if ( !m_bInitialized ) - return; - - m_bInitialized = false; - - if ( IsDirty() ) - { - Save(); - } - // No matter what, create the manifest if it doesn't exist on the HD yet - else if ( m_bSaveManifest && !ManifestExists() ) - { - SaveManifest(); - } - - m_Elements.RemoveAll(); -} - -template -bool CUtlCachedFileData::ManifestExists() -{ - char manifest_name[ 512 ]; - Q_strncpy( manifest_name, m_pszRepositoryFileName, sizeof( manifest_name ) ); - - Q_SetExtension( manifest_name, ".manifest", sizeof( manifest_name ) ); - - return g_pFullFileSystem->FileExists( manifest_name, "MOD" ); -} - -template -void CUtlCachedFileData::SaveManifest() -{ - // Save manifest out to disk... - CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); - - for ( int i = m_Elements.FirstInorder(); i != m_Elements.InvalidIndex(); i = m_Elements.NextInorder( i ) ) - { - ElementType_t& element = m_Elements[ i ]; - - char fn[ 512 ]; - g_pFullFileSystem->String( element.handle, fn, sizeof( fn ) ); - - buf.Printf( "\"%s\"\r\n", fn ); - } - - char path[ 512 ]; - Q_strncpy( path, m_pszRepositoryFileName, sizeof( path ) ); - Q_StripFilename( path ); - - g_pFullFileSystem->CreateDirHierarchy( path, "MOD" ); - - char manifest_name[ 512 ]; - Q_strncpy( manifest_name, m_pszRepositoryFileName, sizeof( manifest_name ) ); - - Q_SetExtension( manifest_name, ".manifest", sizeof( manifest_name ) ); - - if ( g_pFullFileSystem->FileExists( manifest_name, "MOD" ) && - !g_pFullFileSystem->IsFileWritable( manifest_name, "MOD" ) ) - { - g_pFullFileSystem->SetFileWritable( manifest_name, true, "MOD" ); - } - - // Now write to file - FileHandle_t fh; - fh = g_pFullFileSystem->Open( manifest_name, "wb" ); - if ( FILESYSTEM_INVALID_HANDLE != fh ) - { - g_pFullFileSystem->Write( buf.Base(), buf.TellPut(), fh ); - g_pFullFileSystem->Close( fh ); - - // DevMsg( "Persisting cache manifest '%s' (%d entries)\n", manifest_name, c ); - } - else - { - Warning( "Unable to persist cache manifest '%s', check file permissions\n", manifest_name ); - } -} - -template -T *CUtlCachedFileData::RebuildItem( const char *filename ) -{ - int idx = GetIndex( filename ); - ElementType_t& e = m_Elements[ idx ]; - - ForceRecheckDiskInfo(); - - long cachefileinfo = e.fileinfo; - // Set the disk fileinfo the first time we encounter the filename - if ( e.diskfileinfo == UTL_CACHED_FILE_DATA_UNDEFINED_DISKINFO ) - { - if ( m_bNeverCheckDisk ) - { - e.diskfileinfo = cachefileinfo; - } - else - { - if ( m_fileCheckType == UTL_CACHED_FILE_USE_FILESIZE ) - { - e.diskfileinfo = g_pFullFileSystem->Size( filename, "GAME" ); - // Missing files get a disk file size of 0 - if ( e.diskfileinfo == -1 ) - { - e.diskfileinfo = 0; - } - } - else - { - e.diskfileinfo = g_pFullFileSystem->GetFileTime( filename, "GAME" ); - } - } - } - - Assert( e.dataIndex != m_Data.InvalidIndex() ); - - T *data = m_Data[ e.dataIndex ]; - - Assert( data ); - - // Compare fileinfo to disk fileinfo and rebuild cache if out of date or not correct... - if ( !m_bReadOnly ) - { - RebuildCache( filename, data ); - } - e.fileinfo = e.diskfileinfo; - - return data; -} - -template -void CUtlCachedFileData::RebuildCache( char const *filename, T *data ) -{ - Assert( !m_bReadOnly ); - - // Recache item, mark self as dirty - SetDirty( true ); - - ((IBaseCacheInfo *)data)->Rebuild( filename ); -} - -template -void CUtlCachedFileData::ForceRecheckDiskInfo() -{ - for ( int i = m_Elements.FirstInorder(); i != m_Elements.InvalidIndex(); i = m_Elements.NextInorder( i ) ) - { - ElementType_t& element = m_Elements[ i ]; - element.diskfileinfo = UTL_CACHED_FILE_DATA_UNDEFINED_DISKINFO; - } -} - -class CSortedCacheFile -{ -public: - FileNameHandle_t handle; - int index; - - bool Less( const CSortedCacheFile &file0, const CSortedCacheFile &file1, void * ) - { - char name0[ 512 ]; - char name1[ 512 ]; - g_pFullFileSystem->String( file0.handle, name0, sizeof( name0 ) ); - g_pFullFileSystem->String( file1.handle, name1, sizeof( name1 ) ); - return Q_stricmp( name0, name1 ) < 0 ? true : false; - } -}; - -// Iterates all entries and causes rebuild on any existing items which are out of date -template -void CUtlCachedFileData::CheckDiskInfo( bool forcerebuild, long cacheFileTime ) -{ - char fn[ 512 ]; - int i; - if ( forcerebuild ) - { - for ( i = m_Elements.FirstInorder(); i != m_Elements.InvalidIndex(); i = m_Elements.NextInorder( i ) ) - { - ElementType_t& element = m_Elements[ i ]; - g_pFullFileSystem->String( element.handle, fn, sizeof( fn ) ); - Get(fn); - } - return; - } - - CUtlSortVector list; - for ( i = m_Elements.FirstInorder(); i != m_Elements.InvalidIndex(); i = m_Elements.NextInorder( i ) ) - { - ElementType_t& element = m_Elements[ i ]; - CSortedCacheFile insert; - insert.handle = element.handle; - insert.index = i; - list.InsertNoSort( insert ); - } - list.RedoSort(); - - if ( !list.Count() ) - return; - - bool bSteam = g_pFullFileSystem->IsSteam(); - - for ( int listStart = 0, listEnd = 0; listStart < list.Count(); listStart = listEnd+1 ) - { - int pathIndex = g_pFullFileSystem->GetPathIndex( m_Elements[list[listStart].index].handle ); - for ( listEnd = listStart; listEnd < list.Count(); listEnd++ ) - { - ElementType_t& element = m_Elements[ list[listEnd].index ]; - - int pathTest = g_pFullFileSystem->GetPathIndex( element.handle ); - if ( pathTest != pathIndex ) - break; - } - g_pFullFileSystem->String( m_Elements[list[listStart].index].handle, fn, sizeof( fn ) ); - Q_StripFilename( fn ); - bool bCheck = true; - - if ( m_bNeverCheckDisk ) - { - bCheck = false; - } - else if ( !bSteam ) - { - long pathTime = g_pFullFileSystem->GetPathTime( fn, "GAME" ); - bCheck = (pathTime > cacheFileTime) ? true : false; - } - - for ( i = listStart; i < listEnd; i++ ) - { - ElementType_t& element = m_Elements[ list[i].index ]; - - if ( element.diskfileinfo == UTL_CACHED_FILE_DATA_UNDEFINED_DISKINFO ) - { - if ( !bCheck ) - { - element.diskfileinfo = element.fileinfo; - } - else - { - g_pFullFileSystem->String( element.handle, fn, sizeof( fn ) ); - if ( m_fileCheckType == UTL_CACHED_FILE_USE_FILESIZE ) - { - element.diskfileinfo = g_pFullFileSystem->Size( fn, "GAME" ); - - // Missing files get a disk file size of 0 - if ( element.diskfileinfo == -1 ) - { - element.diskfileinfo = 0; - } - } - else - { - element.diskfileinfo = g_pFullFileSystem->GetFileTime( fn, "GAME" ); - } - } - } - } - } -} - -#include "tier0/memdbgoff.h" - -#endif // UTLCACHEDFILEDATA_H diff --git a/public/VGuiMatSurface/IMatSystemSurface.h b/public/VGuiMatSurface/IMatSystemSurface.h deleted file mode 100644 index 390bbc2ca..000000000 --- a/public/VGuiMatSurface/IMatSystemSurface.h +++ /dev/null @@ -1,107 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: An extra interface implemented by the material system -// implementation of vgui::ISurface -// -// $Revision: $ -// $NoKeywords: $ -//===========================================================================// - -#ifndef IMATSYSTEMSURFACE_H -#define IMATSYSTEMSURFACE_H -#ifdef _WIN32 -#pragma once -#endif - - -#include -#include "vgui/ISurface.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class VMatrix; -class IMaterial; -struct InputEvent_t; - - -//----------------------------------------------------------------------------- -// Callbacks for mouse getting + setting -//----------------------------------------------------------------------------- -typedef void (*GetMouseCallback_t)(int &x, int &y); -typedef void (*SetMouseCallback_t)(int x, int y); - -//----------------------------------------------------------------------------- -// Callbacks for sound playing -//----------------------------------------------------------------------------- -typedef void (*PlaySoundFunc_t)(const char *pFileName); - - -//----------------------------------------------------------------------------- -// -// An extra interface implemented by the material system implementation of vgui::ISurface -// -//----------------------------------------------------------------------------- -#define MAT_SYSTEM_SURFACE_INTERFACE_VERSION "MatSystemSurface006" -class IMatSystemSurface : public vgui::ISurface -{ -public: - // Hook needed to get input to work. - // If the app drives the input (like the engine needs to do for VCR mode), - // it can set bLetAppDriveInput to true and call HandleInputEvent for the input events. - virtual void AttachToWindow( void *hwnd, bool bLetAppDriveInput=false ) = 0; - - // Tells the surface to ignore windows messages - virtual void EnableWindowsMessages( bool bEnable ) = 0; - - // Starts, ends 3D painting - // NOTE: These methods should only be called from within the paint() - // method of a panel. - virtual void Begin3DPaint( int iLeft, int iTop, int iRight, int iBottom ) = 0; - virtual void End3DPaint() = 0; - - // NOTE: This also should only be called from within the paint() - // method of a panel. Use it to disable clipping for the rendering - // of this panel. - virtual void DisableClipping( bool bDisable ) = 0; - - // Prevents vgui from changing the cursor - virtual bool IsCursorLocked() const = 0; - - // Sets the mouse get + set callbacks - virtual void SetMouseCallbacks( GetMouseCallback_t getFunc, SetMouseCallback_t setFunc ) = 0; - - // Installs a function to play sounds - virtual void InstallPlaySoundFunc( PlaySoundFunc_t soundFunc ) = 0; - - // Some drawing methods that cannot be accomplished under Win32 - virtual void DrawColoredCircle( int centerx, int centery, float radius, int r, int g, int b, int a ) = 0; - virtual int DrawColoredText( vgui::HFont font, int x, int y, int r, int g, int b, int a, char *fmt, ... ) = 0; - - // Draws text with current font at position and wordwrapped to the rect using color values specified - virtual void DrawColoredTextRect( vgui::HFont font, int x, int y, int w, int h, int r, int g, int b, int a, char *fmt, ... ) = 0; - virtual void DrawTextHeight( vgui::HFont font, int w, int& h, char *fmt, ... ) = 0; - - // Returns the length of the text string in pixels - virtual int DrawTextLen( vgui::HFont font, char *fmt, ... ) = 0; - - // Draws a panel in 3D space. Assumes view + projection are already set up - // Also assumes the (x,y) coordinates of the panels are defined in 640xN coords - // (N isn't necessary 480 because the panel may not be 4x3) - // The width + height specified are the size of the panel in world coordinates - virtual void DrawPanelIn3DSpace( vgui::VPANEL pRootPanel, const VMatrix &panelCenterToWorld, int nPixelWidth, int nPixelHeight, float flWorldWidth, float flWorldHeight ) = 0; - - // Binds a material to a surface texture ID - virtual void DrawSetTextureMaterial( int id, IMaterial *pMaterial ) = 0; - - // Handles an input event, returns true if the event should be filtered from the rest of the game - virtual bool HandleInputEvent( const InputEvent_t &event ) = 0; - - virtual void Set3DPaintTempRenderTarget( const char *pRenderTargetName ) = 0; - virtual void Reset3DPaintTempRenderTarget( void ) = 0; -}; - - -#endif // IMATSYSTEMSURFACE_H - diff --git a/public/VGuiMatSurface/IMatSystemSurfaceV5.h b/public/VGuiMatSurface/IMatSystemSurfaceV5.h deleted file mode 100644 index 9b8da47ad..000000000 --- a/public/VGuiMatSurface/IMatSystemSurfaceV5.h +++ /dev/null @@ -1,88 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef IMATSYSTEMSURFACEV5_H -#define IMATSYSTEMSURFACEV5_H -#ifdef _WIN32 -#pragma once -#endif - - -#include -#include "vgui/isurfacev30.h" - - -namespace MatSystemSurfaceV5 -{ - #define MAT_SYSTEM_SURFACE_INTERFACE_VERSION_5 "MatSystemSurface005" - - - class IMatSystemSurface : public SurfaceV30::ISurface - { - public: - // Hook needed to get input to work. - // If the app drives the input (like the engine needs to do for VCR mode), - // it can set bLetAppDriveInput to true and call HandleWindowMessage for the Windows messages. - virtual void AttachToWindow( void *hwnd, bool bLetAppDriveInput=false ) = 0; - - // If you specified true for bLetAppDriveInput, then call this for each window message that comes in. - virtual void HandleWindowMessage( void *hwnd, unsigned int uMsg, unsigned int wParam, long lParam ) = 0; - - // Tells the surface to ignore windows messages - virtual void EnableWindowsMessages( bool bEnable ) = 0; - - // Starts, ends 3D painting - // NOTE: These methods should only be called from within the paint() - // method of a panel. - virtual void Begin3DPaint( int iLeft, int iTop, int iRight, int iBottom ) = 0; - virtual void End3DPaint() = 0; - - // NOTE: This also should only be called from within the paint() - // method of a panel. Use it to disable clipping for the rendering - // of this panel. - virtual void DisableClipping( bool bDisable ) = 0; - - // Prevents vgui from changing the cursor - virtual bool IsCursorLocked() const = 0; - - // Sets the mouse get + set callbacks - virtual void SetMouseCallbacks( GetMouseCallback_t getFunc, SetMouseCallback_t setFunc ) = 0; - - // Installs a function to play sounds - virtual void InstallPlaySoundFunc( PlaySoundFunc_t soundFunc ) = 0; - - // Some drawing methods that cannot be accomplished under Win32 - virtual void DrawColoredCircle( int centerx, int centery, float radius, int r, int g, int b, int a ) = 0; - virtual int DrawColoredText( vgui::HFont font, int x, int y, int r, int g, int b, int a, char *fmt, ... ) = 0; - - // Draws text with current font at position and wordwrapped to the rect using color values specified - virtual void DrawColoredTextRect( vgui::HFont font, int x, int y, int w, int h, int r, int g, int b, int a, char *fmt, ... ) = 0; - virtual void DrawTextHeight( vgui::HFont font, int w, int& h, char *fmt, ... ) = 0; - - // Returns the length of the text string in pixels - virtual int DrawTextLen( vgui::HFont font, char *fmt, ... ) = 0; - - // Draws a panel in 3D space. Assumes view + projection are already set up - // Also assumes the (x,y) coordinates of the panels are defined in 640xN coords - // (N isn't necessary 480 because the panel may not be 4x3) - // The width + height specified are the size of the panel in world coordinates - virtual void DrawPanelIn3DSpace( vgui::VPANEL pRootPanel, const VMatrix &panelCenterToWorld, int nPixelWidth, int nPixelHeight, float flWorldWidth, float flWorldHeight ) = 0; - - // Binds a material to a surface texture ID - virtual void DrawSetTextureMaterial( int id, IMaterial *pMaterial ) = 0; - }; - -} - -//----------------------------------------------------------------------------- -// FIXME: This works around using scoped interfaces w/ EXPOSE_SINGLE_INTERFACE -//----------------------------------------------------------------------------- -class IMatSystemSurfaceV5 : public MatSystemSurfaceV5::IMatSystemSurface -{ -public: -}; - -#endif // IMATSYSTEMSURFACEV5_H diff --git a/public/XUnzip.cpp b/public/XUnzip.cpp deleted file mode 100644 index fc70d4961..000000000 --- a/public/XUnzip.cpp +++ /dev/null @@ -1,4368 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -// XUnzip.cpp Version 1.1 -// -// Authors: Mark Adler et al. (see below) -// -// Modified by: Lucian Wischik -// lu@wischik.com -// -// Version 1.0 - Turned C files into just a single CPP file -// - Made them compile cleanly as C++ files -// - Gave them simpler APIs -// - Added the ability to zip/unzip directly in memory without -// any intermediate files -// -// Modified by: Hans Dietrich -// hdietrich2@hotmail.com -// -// Version 1.1: - Added Unicode support to CreateZip() and ZipAdd() -// - Changed file names to avoid conflicts with Lucian's files -// -/////////////////////////////////////////////////////////////////////////////// -// -// Lucian Wischik's comments: -// -------------------------- -// THIS FILE is almost entirely based upon code by Info-ZIP. -// It has been modified by Lucian Wischik. -// The original code may be found at http://www.info-zip.org -// The original copyright text follows. -// -/////////////////////////////////////////////////////////////////////////////// -// -// Original authors' comments: -// --------------------------- -// This is version 2002-Feb-16 of the Info-ZIP copyright and license. The -// definitive version of this document should be available at -// ftp://ftp.info-zip.org/pub/infozip/license.html indefinitely. -// -// Copyright (c) 1990-2002 Info-ZIP. All rights reserved. -// -// For the purposes of this copyright and license, "Info-ZIP" is defined as -// the following set of individuals: -// -// Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois, -// Jean-loup Gailly, Hunter Goatley, Ian Gorman, Chris Herborth, Dirk Haase, -// Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz, -// David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko, -// Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs, -// Kai Uwe Rommel, Steve Salisbury, Dave Smith, Christian Spieler, -// Antoine Verheijen, Paul von Behren, Rich Wales, Mike White -// -// This software is provided "as is", without warranty of any kind, express -// or implied. In no event shall Info-ZIP or its contributors be held liable -// for any direct, indirect, incidental, special or consequential damages -// arising out of the use of or inability to use this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. Redistributions of source code must retain the above copyright notice, -// definition, disclaimer, and this list of conditions. -// -// 2. Redistributions in binary form (compiled executables) must reproduce -// the above copyright notice, definition, disclaimer, and this list of -// conditions in documentation and/or other materials provided with the -// distribution. The sole exception to this condition is redistribution -// of a standard UnZipSFX binary as part of a self-extracting archive; -// that is permitted without inclusion of this license, as long as the -// normal UnZipSFX banner has not been removed from the binary or disabled. -// -// 3. Altered versions--including, but not limited to, ports to new -// operating systems, existing ports with new graphical interfaces, and -// dynamic, shared, or static library versions--must be plainly marked -// as such and must not be misrepresented as being the original source. -// Such altered versions also must not be misrepresented as being -// Info-ZIP releases--including, but not limited to, labeling of the -// altered versions with the names "Info-ZIP" (or any variation thereof, -// including, but not limited to, different capitalizations), -// "Pocket UnZip", "WiZ" or "MacZip" without the explicit permission of -// Info-ZIP. Such altered versions are further prohibited from -// misrepresentative use of the Zip-Bugs or Info-ZIP e-mail addresses or -// of the Info-ZIP URL(s). -// -// 4. Info-ZIP retains the right to use the names "Info-ZIP", "Zip", "UnZip", -// "UnZipSFX", "WiZ", "Pocket UnZip", "Pocket Zip", and "MacZip" for its -// own source and binary releases. -// -/////////////////////////////////////////////////////////////////////////////// - -#if defined( PROTECTED_THINGS_ENABLE ) -#undef PROTECTED_THINGS_ENABLE // from protected_things.h -#endif - -#include "tier0/platform.h" - -#ifdef IS_WINDOWS_PC -#define STRICT -#define WIN32_LEAN_AND_MEAN -#include -#endif -#include -#include -#include -#include -#include -#include "zip/XUnzip.h" -#if defined( _X360 ) -#include "xbox/xbox_win32stubs.h" -#endif - -// THIS FILE is almost entirely based upon code by Jean-loup Gailly -// and Mark Adler. It has been modified by Lucian Wischik. -// The original code may be found at http://www.gzip.org/zlib/ -// The original copyright text follows. -// -// -// -// zlib.h -- interface of the 'zlib' general purpose compression library -// version 1.1.3, July 9th, 1998 -// -// Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. -// -// Jean-loup Gailly Mark Adler -// jloup@gzip.org madler@alumni.caltech.edu -// -// -// The data format used by the zlib library is described by RFCs (Request for -// Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt -// (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). -// -// -// The 'zlib' compression library provides in-memory compression and -// decompression functions, including integrity checks of the uncompressed -// data. This version of the library supports only one compression method -// (deflation) but other algorithms will be added later and will have the same -// stream interface. -// -// Compression can be done in a single step if the buffers are large -// enough (for example if an input file is mmap'ed), or can be done by -// repeated calls of the compression function. In the latter case, the -// application must provide more input and/or consume the output -// (providing more output space) before each call. -// -// The library also supports reading and writing files in gzip (.gz) format -// with an interface similar to that of stdio. -// -// The library does not install any signal handler. The decoder checks -// the consistency of the compressed data, so the library should never -// crash even in case of corrupted input. -// -// for more info about .ZIP format, see ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip -// PkWare has also a specification at ftp://ftp.pkware.com/probdesc.zip - -#define zmalloc(len) malloc(len) - -#define zfree(p) free(p) - -/* -void *zmalloc(unsigned int len) -{ char *buf = new char[len+32]; - for (int i=0; i<16; i++) - { buf[i]=i; - buf[len+31-i]=i; - } - *((unsigned int*)buf) = len; - char c[1000]; wsprintf(c,"malloc 0x%lx - %lu",buf+16,len); - OutputDebugString(c); - return buf+16; -} - -void zfree(void *buf) -{ char c[1000]; wsprintf(c,"free 0x%lx",buf); - OutputDebugString(c); - char *p = ((char*)buf)-16; - unsigned int len = *((unsigned int*)p); - bool blown=false; - for (int i=0; i<16; i++) - { char lo = p[i]; - char hi = p[len+31-i]; - if (hi!=i || (lo!=i && i>4)) blown=true; - } - if (blown) - { OutputDebugString("BLOWN!!!"); - } - delete[] p; -} -*/ - -#pragma warning(disable : 4702) // unreachable code - -typedef struct tm_unz_s -{ unsigned int tm_sec; // seconds after the minute - [0,59] - unsigned int tm_min; // minutes after the hour - [0,59] - unsigned int tm_hour; // hours since midnight - [0,23] - unsigned int tm_mday; // day of the month - [1,31] - unsigned int tm_mon; // months since January - [0,11] - unsigned int tm_year; // years - [1980..2044] -} tm_unz; - - -// unz_global_info structure contain global data about the ZIPfile -typedef struct unz_global_info_s -{ unsigned long number_entry; // total number of entries in the central dir on this disk - unsigned long size_comment; // size of the global comment of the zipfile -} unz_global_info; - -// unz_file_info contain information about a file in the zipfile -typedef struct unz_file_info_s -{ unsigned long version; // version made by 2 bytes - unsigned long version_needed; // version needed to extract 2 bytes - unsigned long flag; // general purpose bit flag 2 bytes - unsigned long compression_method; // compression method 2 bytes - unsigned long dosDate; // last mod file date in Dos fmt 4 bytes - unsigned long crc; // crc-32 4 bytes - unsigned long compressed_size; // compressed size 4 bytes - unsigned long uncompressed_size; // uncompressed size 4 bytes - unsigned long size_filename; // filename length 2 bytes - unsigned long size_file_extra; // extra field length 2 bytes - unsigned long size_file_comment; // file comment length 2 bytes - unsigned long disk_num_start; // disk number start 2 bytes - unsigned long internal_fa; // internal file attributes 2 bytes - unsigned long external_fa; // external file attributes 4 bytes - tm_unz tmu_date; -} unz_file_info; - - -#define UNZ_OK (0) -#define UNZ_END_OF_LIST_OF_FILE (-100) -#define UNZ_ERRNO (Z_ERRNO) -#define UNZ_EOF (0) -#define UNZ_PARAMERROR (-102) -#define UNZ_BADZIPFILE (-103) -#define UNZ_INTERNALERROR (-104) -#define UNZ_CRCERROR (-105) - - - - - - - -#define ZLIB_VERSION "1.1.3" - - -// Allowed flush values; see deflate() for details -#define Z_NO_FLUSH 0 -#define Z_SYNC_FLUSH 2 -#define Z_FULL_FLUSH 3 -#define Z_FINISH 4 - - -// compression levels -#define Z_NO_COMPRESSION 0 -#define Z_BEST_SPEED 1 -#define Z_BEST_COMPRESSION 9 -#define Z_DEFAULT_COMPRESSION (-1) - -// compression strategy; see deflateInit2() for details -#define Z_FILTERED 1 -#define Z_HUFFMAN_ONLY 2 -#define Z_DEFAULT_STRATEGY 0 - -// Possible values of the data_type field -#define Z_BINARY 0 -#define Z_ASCII 1 -#define Z_UNKNOWN 2 - -// The deflate compression method (the only one supported in this version) -#define Z_DEFLATED 8 - -// for initializing zalloc, zfree, opaque -#define Z_NULL 0 - -// case sensitivity when searching for filenames -#define CASE_SENSITIVE 1 -#define CASE_INSENSITIVE 2 - - -// Return codes for the compression/decompression functions. Negative -// values are errors, positive values are used for special but normal events. -#define Z_OK 0 -#define Z_STREAM_END 1 -#define Z_NEED_DICT 2 -#define Z_ERRNO (-1) -#define Z_STREAM_ERROR (-2) -#define Z_DATA_ERROR (-3) -#define Z_MEM_ERROR (-4) -#define Z_BUF_ERROR (-5) -#define Z_VERSION_ERROR (-6) - - - -// Basic data types -typedef unsigned char Byte; // 8 bits -typedef unsigned int uInt; // 16 bits or more -typedef unsigned long uLong; // 32 bits or more -typedef void *voidpf; -typedef void *voidp; -typedef long z_off_t; - - - - - - - - - - - - -typedef voidpf (*alloc_func) (voidpf opaque, uInt items, uInt size); -typedef void (*free_func) (voidpf opaque, voidpf address); - -struct internal_state; - -typedef struct z_stream_s { - Byte *next_in; // next input byte - uInt avail_in; // number of bytes available at next_in - uLong total_in; // total nb of input bytes read so far - - Byte *next_out; // next output byte should be put there - uInt avail_out; // remaining free space at next_out - uLong total_out; // total nb of bytes output so far - - char *msg; // last error message, NULL if no error - struct internal_state *state; // not visible by applications - - alloc_func zalloc; // used to allocate the internal state - free_func zfree; // used to free the internal state - voidpf opaque; // private data object passed to zalloc and zfree - - int data_type; // best guess about the data type: ascii or binary - uLong adler; // adler32 value of the uncompressed data - uLong reserved; // reserved for future use -} z_stream; - -typedef z_stream *z_streamp; - - -// The application must update next_in and avail_in when avail_in has -// dropped to zero. It must update next_out and avail_out when avail_out -// has dropped to zero. The application must initialize zalloc, zfree and -// opaque before calling the init function. All other fields are set by the -// compression library and must not be updated by the application. -// -// The opaque value provided by the application will be passed as the first -// parameter for calls of zalloc and zfree. This can be useful for custom -// memory management. The compression library attaches no meaning to the -// opaque value. -// -// zalloc must return Z_NULL if there is not enough memory for the object. -// If zlib is used in a multi-threaded application, zalloc and zfree must be -// thread safe. -// -// The fields total_in and total_out can be used for statistics or -// progress reports. After compression, total_in holds the total size of -// the uncompressed data and may be saved for use in the decompressor -// (particularly if the decompressor wants to decompress everything in -// a single step). -// - - -// basic functions - -const char *zlibVersion (); -// The application can compare zlibVersion and ZLIB_VERSION for consistency. -// If the first character differs, the library code actually used is -// not compatible with the zlib.h header file used by the application. -// This check is automatically made by inflateInit. - - - - - - -int inflate (z_streamp strm, int flush); -// -// inflate decompresses as much data as possible, and stops when the input -// buffer becomes empty or the output buffer becomes full. It may some -// introduce some output latency (reading input without producing any output) -// except when forced to flush. -// -// The detailed semantics are as follows. inflate performs one or both of the -// following actions: -// -// - Decompress more input starting at next_in and update next_in and avail_in -// accordingly. If not all input can be processed (because there is not -// enough room in the output buffer), next_in is updated and processing -// will resume at this point for the next call of inflate(). -// -// - Provide more output starting at next_out and update next_out and avail_out -// accordingly. inflate() provides as much output as possible, until there -// is no more input data or no more space in the output buffer (see below -// about the flush parameter). -// -// Before the call of inflate(), the application should ensure that at least -// one of the actions is possible, by providing more input and/or consuming -// more output, and updating the next_* and avail_* values accordingly. -// The application can consume the uncompressed output when it wants, for -// example when the output buffer is full (avail_out == 0), or after each -// call of inflate(). If inflate returns Z_OK and with zero avail_out, it -// must be called again after making room in the output buffer because there -// might be more output pending. -// -// If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much -// output as possible to the output buffer. The flushing behavior of inflate is -// not specified for values of the flush parameter other than Z_SYNC_FLUSH -// and Z_FINISH, but the current implementation actually flushes as much output -// as possible anyway. -// -// inflate() should normally be called until it returns Z_STREAM_END or an -// error. However if all decompression is to be performed in a single step -// (a single call of inflate), the parameter flush should be set to -// Z_FINISH. In this case all pending input is processed and all pending -// output is flushed; avail_out must be large enough to hold all the -// uncompressed data. (The size of the uncompressed data may have been saved -// by the compressor for this purpose.) The next operation on this stream must -// be inflateEnd to deallocate the decompression state. The use of Z_FINISH -// is never required, but can be used to inform inflate that a faster routine -// may be used for the single inflate() call. -// -// If a preset dictionary is needed at this point (see inflateSetDictionary -// below), inflate sets strm-adler to the adler32 checksum of the -// dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise -// it sets strm->adler to the adler32 checksum of all output produced -// so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or -// an error code as described below. At the end of the stream, inflate() -// checks that its computed adler32 checksum is equal to that saved by the -// compressor and returns Z_STREAM_END only if the checksum is correct. -// -// inflate() returns Z_OK if some progress has been made (more input processed -// or more output produced), Z_STREAM_END if the end of the compressed data has -// been reached and all uncompressed output has been produced, Z_NEED_DICT if a -// preset dictionary is needed at this point, Z_DATA_ERROR if the input data was -// corrupted (input stream not conforming to the zlib format or incorrect -// adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent -// (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not -// enough memory, Z_BUF_ERROR if no progress is possible or if there was not -// enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR -// case, the application may then call inflateSync to look for a good -// compression block. -// - - -int inflateEnd (z_streamp strm); -// -// All dynamically allocated data structures for this stream are freed. -// This function discards any unprocessed input and does not flush any -// pending output. -// -// inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state -// was inconsistent. In the error case, msg may be set but then points to a -// static string (which must not be deallocated). - - // Advanced functions - -// The following functions are needed only in some special applications. - - - - - -int inflateSetDictionary (z_streamp strm, - const Byte *dictionary, - uInt dictLength); -// -// Initializes the decompression dictionary from the given uncompressed byte -// sequence. This function must be called immediately after a call of inflate -// if this call returned Z_NEED_DICT. The dictionary chosen by the compressor -// can be determined from the Adler32 value returned by this call of -// inflate. The compressor and decompressor must use exactly the same -// dictionary. -// -// inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a -// parameter is invalid (such as NULL dictionary) or the stream state is -// inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the -// expected one (incorrect Adler32 value). inflateSetDictionary does not -// perform any decompression: this will be done by subsequent calls of -// inflate(). - - -int inflateSync (z_streamp strm); -// -// Skips invalid compressed data until a full flush point can be found, or until all -// available input is skipped. No output is provided. -// -// inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR -// if no more input was provided, Z_DATA_ERROR if no flush point has been found, -// or Z_STREAM_ERROR if the stream structure was inconsistent. In the success -// case, the application may save the current current value of total_in which -// indicates where valid compressed data was found. In the error case, the -// application may repeatedly call inflateSync, providing more input each time, -// until success or end of the input data. - - -int inflateReset (z_streamp strm); -// This function is equivalent to inflateEnd followed by inflateInit, -// but does not free and reallocate all the internal decompression state. -// The stream will keep attributes that may have been set by inflateInit2. -// -// inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source -// stream state was inconsistent (such as zalloc or state being NULL). -// - - - -// checksum functions -// These functions are not related to compression but are exported -// anyway because they might be useful in applications using the -// compression library. - -uLong adler32 (uLong adler, const Byte *buf, uInt len); -// Update a running Adler-32 checksum with the bytes buf[0..len-1] and -// return the updated checksum. If buf is NULL, this function returns -// the required initial value for the checksum. -// An Adler-32 checksum is almost as reliable as a CRC32 but can be computed -// much faster. Usage example: -// -// uLong adler = adler32(0L, Z_NULL, 0); -// -// while (read_buffer(buffer, length) != EOF) { -// adler = adler32(adler, buffer, length); -// } -// if (adler != original_adler) error(); - -uLong ucrc32 (uLong crc, const Byte *buf, uInt len); -// Update a running crc with the bytes buf[0..len-1] and return the updated -// crc. If buf is NULL, this function returns the required initial value -// for the crc. Pre- and post-conditioning (one's complement) is performed -// within this function so it shouldn't be done by the application. -// Usage example: -// -// uLong crc = crc32(0L, Z_NULL, 0); -// -// while (read_buffer(buffer, length) != EOF) { -// crc = crc32(crc, buffer, length); -// } -// if (crc != original_crc) error(); - - - - -const char *zError (int err); -int inflateSyncPoint (z_streamp z); -const uLong *get_crc_table (void); - - - -typedef unsigned char uch; -typedef uch uchf; -typedef unsigned short ush; -typedef ush ushf; -typedef unsigned long ulg; - - - -const char * const z_errmsg[10] = { // indexed by 2-zlib_error -"need dictionary", // Z_NEED_DICT 2 -"stream end", // Z_STREAM_END 1 -"", // Z_OK 0 -"file error", // Z_ERRNO (-1) -"stream error", // Z_STREAM_ERROR (-2) -"data error", // Z_DATA_ERROR (-3) -"insufficient memory", // Z_MEM_ERROR (-4) -"buffer error", // Z_BUF_ERROR (-5) -"incompatible version",// Z_VERSION_ERROR (-6) -""}; - - -#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] - -#define ERR_RETURN(strm,err) \ - return (strm->msg = (char*)ERR_MSG(err), (err)) -// To be used only when the state is known to be valid - - // common constants - - -#define STORED_BLOCK 0 -#define STATIC_TREES 1 -#define DYN_TREES 2 -// The three kinds of block type - -#define MIN_MATCH 3 -#define MAX_MATCH 258 -// The minimum and maximum match lengths - -#define PRESET_DICT 0x20 // preset dictionary flag in zlib header - - // target dependencies - -#define OS_CODE 0x0b // Window 95 & Windows NT - - - - // functions - -#define zmemzero(dest, len) memset(dest, 0, len) - -// Diagnostic functions -#undef Assert -#undef Trace -#undef Tracev -#undef Tracevv -#undef Tracec -#undef Tracecv - -#ifdef DEBUG - int z_verbose = 0; - void z_error (char *m) {fprintf(stderr, "%s\n", m); exit(1);} -# define Assert(cond,msg) {if(!(cond)) z_error(msg);} -# define Trace(x) {if (z_verbose>=0) fprintf x ;} -# define Tracev(x) {if (z_verbose>0) fprintf x ;} -# define Tracevv(x) {if (z_verbose>1) fprintf x ;} -# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} -# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} -#else -# define Assert(cond,msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c,x) -# define Tracecv(c,x) -#endif - - -typedef uLong (*check_func) (uLong check, const Byte *buf, uInt len); -voidpf zcalloc (voidpf opaque, unsigned items, unsigned size); -void zcfree (voidpf opaque, voidpf ptr); - -#define ZALLOC(strm, items, size) \ - (*((strm)->zalloc))((strm)->opaque, (items), (size)) -#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) - -//void ZFREE(z_streamp strm,voidpf addr) -//{ *((strm)->zfree))((strm)->opaque, addr); -//} - -#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} - - - - -// Huffman code lookup table entry--this entry is four bytes for machines -// that have 16-bit pointers (e.g. PC's in the small or medium model). - - -typedef struct inflate_huft_s inflate_huft; - -struct inflate_huft_s { - union { - struct { - Byte Exop; // number of extra bits or operation - Byte Bits; // number of bits in this code or subcode - } what; - uInt pad; // pad structure to a power of 2 (4 bytes for - } word; // 16-bit, 8 bytes for 32-bit int's) - uInt base; // literal, length base, distance base, or table offset -}; - -// Maximum size of dynamic tree. The maximum found in a long but non- -// exhaustive search was 1004 huft structures (850 for length/literals -// and 154 for distances, the latter actually the result of an -// exhaustive search). The actual maximum is not known, but the -// value below is more than safe. -#define MANY 1440 - -int inflate_trees_bits ( - uInt *, // 19 code lengths - uInt *, // bits tree desired/actual depth - inflate_huft * *, // bits tree result - inflate_huft *, // space for trees - z_streamp); // for messages - -int inflate_trees_dynamic ( - uInt, // number of literal/length codes - uInt, // number of distance codes - uInt *, // that many (total) code lengths - uInt *, // literal desired/actual bit depth - uInt *, // distance desired/actual bit depth - inflate_huft * *, // literal/length tree result - inflate_huft * *, // distance tree result - inflate_huft *, // space for trees - z_streamp); // for messages - -int inflate_trees_fixed ( - uInt *, // literal desired/actual bit depth - uInt *, // distance desired/actual bit depth - const inflate_huft * *, // literal/length tree result - const inflate_huft * *, // distance tree result - z_streamp); // for memory allocation - - - - - -struct inflate_blocks_state; -typedef struct inflate_blocks_state inflate_blocks_statef; - -inflate_blocks_statef * inflate_blocks_new ( - z_streamp z, - check_func c, // check function - uInt w); // window size - -int inflate_blocks ( - inflate_blocks_statef *, - z_streamp , - int); // initial return code - -void inflate_blocks_reset ( - inflate_blocks_statef *, - z_streamp , - uLong *); // check value on output - -int inflate_blocks_free ( - inflate_blocks_statef *, - z_streamp); - -void inflate_set_dictionary ( - inflate_blocks_statef *s, - const Byte *d, // dictionary - uInt n); // dictionary length - -int inflate_blocks_sync_point ( - inflate_blocks_statef *s); - - - - -struct inflate_codes_state; -typedef struct inflate_codes_state inflate_codes_statef; - -inflate_codes_statef *inflate_codes_new ( - uInt, uInt, - const inflate_huft *, const inflate_huft *, - z_streamp ); - -int inflate_codes ( - inflate_blocks_statef *, - z_streamp , - int); - -void inflate_codes_free ( - inflate_codes_statef *, - z_streamp ); - - - - -typedef enum { - IBM_TYPE, // get type bits (3, including end bit) - IBM_LENS, // get lengths for stored - IBM_STORED, // processing stored block - IBM_TABLE, // get table lengths - IBM_BTREE, // get bit lengths tree for a dynamic block - IBM_DTREE, // get length, distance trees for a dynamic block - IBM_CODES, // processing fixed or dynamic block - IBM_DRY, // output remaining window bytes - IBM_DONE, // finished last block, done - IBM_BAD} // got a data error--stuck here -inflate_block_mode; - -// inflate blocks semi-private state -struct inflate_blocks_state { - - // mode - inflate_block_mode mode; // current inflate_block mode - - // mode dependent information - union { - uInt left; // if STORED, bytes left to copy - struct { - uInt table; // table lengths (14 bits) - uInt index; // index into blens (or border) - uInt *blens; // bit lengths of codes - uInt bb; // bit length tree depth - inflate_huft *tb; // bit length decoding tree - } trees; // if DTREE, decoding info for trees - struct { - inflate_codes_statef - *codes; - } decode; // if CODES, current state - } sub; // submode - uInt last; // true if this block is the last block - - // mode independent information - uInt bitk; // bits in bit buffer - uLong bitb; // bit buffer - inflate_huft *hufts; // single malloc for tree space - Byte *window; // sliding window - Byte *end; // one byte after sliding window - Byte *read; // window read pointer - Byte *write; // window write pointer - check_func checkfn; // check function - uLong check; // check on output - -}; - - -// defines for inflate input/output -// update pointers and return -#define UPDBITS {s->bitb=b;s->bitk=k;} -#define UPDIN {z->avail_in=n;z->total_in+=(uLong)(p-z->next_in);z->next_in=p;} -#define UPDOUT {s->write=q;} -#define UPDATE {UPDBITS UPDIN UPDOUT} -#define LEAVE {UPDATE return inflate_flush(s,z,r);} -// get bytes and bits -#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} -#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} -#define NEXTBYTE (n--,*p++) -#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);} -// output bytes -#define WAVAIL (uInt)(qread?s->read-q-1:s->end-q) -#define LOADOUT {q=s->write;m=(uInt)WAVAIL;m;} -#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}} -#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} -#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} -#define OUTBYTE(a) {*q++=(Byte)(a);m--;} -// load local pointers -#define LOAD {LOADIN LOADOUT} - -// masks for lower bits (size given to avoid silly warnings with Visual C++) -// And'ing with mask[n] masks the lower n bits -const uInt inflate_mask[17] = { - 0x0000, - 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, - 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff -}; - -// copy as much as possible from the sliding window to the output area -int inflate_flush (inflate_blocks_statef *, z_streamp, int); - -int inflate_fast (uInt, uInt, const inflate_huft *, const inflate_huft *, inflate_blocks_statef *, z_streamp ); - - - -const uInt fixed_bl = 9; -const uInt fixed_bd = 5; -const inflate_huft fixed_tl[] = { - {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, - {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192}, - {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160}, - {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224}, - {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144}, - {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208}, - {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176}, - {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240}, - {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, - {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200}, - {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168}, - {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232}, - {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152}, - {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216}, - {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184}, - {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248}, - {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, - {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196}, - {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164}, - {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228}, - {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148}, - {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212}, - {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180}, - {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244}, - {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204}, - {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172}, - {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236}, - {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156}, - {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220}, - {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188}, - {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252}, - {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, - {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194}, - {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162}, - {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226}, - {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146}, - {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210}, - {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178}, - {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242}, - {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, - {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202}, - {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170}, - {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234}, - {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154}, - {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218}, - {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186}, - {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250}, - {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, - {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198}, - {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166}, - {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230}, - {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150}, - {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214}, - {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182}, - {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246}, - {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206}, - {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174}, - {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238}, - {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158}, - {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222}, - {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190}, - {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254}, - {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, - {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193}, - {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161}, - {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225}, - {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145}, - {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209}, - {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177}, - {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241}, - {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, - {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201}, - {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169}, - {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233}, - {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153}, - {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217}, - {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185}, - {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249}, - {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, - {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197}, - {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165}, - {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229}, - {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149}, - {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213}, - {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181}, - {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245}, - {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205}, - {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173}, - {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237}, - {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157}, - {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221}, - {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189}, - {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253}, - {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, - {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195}, - {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163}, - {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227}, - {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147}, - {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211}, - {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179}, - {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243}, - {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, - {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203}, - {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171}, - {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235}, - {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155}, - {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219}, - {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187}, - {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251}, - {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, - {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199}, - {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167}, - {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231}, - {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151}, - {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215}, - {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183}, - {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247}, - {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, - {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207}, - {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175}, - {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239}, - {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159}, - {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223}, - {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191}, - {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255} - }; -const inflate_huft fixed_td[] = { - {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097}, - {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385}, - {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193}, - {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577}, - {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145}, - {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577}, - {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289}, - {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577} - }; - - - - - - - -// copy as much as possible from the sliding window to the output area -int inflate_flush(inflate_blocks_statef *s,z_streamp z,int r) -{ - uInt n; - Byte *p; - Byte *q; - - // local copies of source and destination pointers - p = z->next_out; - q = s->read; - - // compute number of bytes to copy as far as end of window - n = (uInt)((q <= s->write ? s->write : s->end) - q); - if (n > z->avail_out) n = z->avail_out; - if (n && r == Z_BUF_ERROR) r = Z_OK; - - // update counters - z->avail_out -= n; - z->total_out += n; - - // update check information - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(s->check, q, n); - - // copy as far as end of window - if (n!=0) // check for n!=0 to avoid waking up CodeGuard - { memcpy(p, q, n); - p += n; - q += n; - } - - // see if more to copy at beginning of window - if (q == s->end) - { - // wrap pointers - q = s->window; - if (s->write == s->end) - s->write = s->window; - - // compute bytes to copy - n = (uInt)(s->write - q); - if (n > z->avail_out) n = z->avail_out; - if (n && r == Z_BUF_ERROR) r = Z_OK; - - // update counters - z->avail_out -= n; - z->total_out += n; - - // update check information - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(s->check, q, n); - - // copy - memcpy(p, q, n); - p += n; - q += n; - } - - // update pointers - z->next_out = p; - s->read = q; - - // done - return r; -} - - - - - - -// simplify the use of the inflate_huft type with some defines -#define exop word.what.Exop -#define bits word.what.Bits - -typedef enum { // waiting for "i:"=input, "o:"=output, "x:"=nothing - START, // x: set up for LEN - LEN, // i: get length/literal/eob next - LENEXT, // i: getting length extra (have base) - DIST, // i: get distance next - DISTEXT, // i: getting distance extra - COPY, // o: copying bytes in window, waiting for space - LIT, // o: got literal, waiting for output space - WASH, // o: got eob, possibly still output waiting - END, // x: got eob and all data flushed - BADCODE} // x: got error -inflate_codes_mode; - -// inflate codes private state -struct inflate_codes_state { - - // mode - inflate_codes_mode mode; // current inflate_codes mode - - // mode dependent information - uInt len; - union { - struct { - const inflate_huft *tree; // pointer into tree - uInt need; // bits needed - } code; // if LEN or DIST, where in tree - uInt lit; // if LIT, literal - struct { - uInt get; // bits to get for extra - uInt dist; // distance back to copy from - } copy; // if EXT or COPY, where and how much - } sub; // submode - - // mode independent information - Byte lbits; // ltree bits decoded per branch - Byte dbits; // dtree bits decoder per branch - const inflate_huft *ltree; // literal/length/eob tree - const inflate_huft *dtree; // distance tree - -}; - - -inflate_codes_statef *inflate_codes_new( -uInt bl, uInt bd, -const inflate_huft *tl, -const inflate_huft *td, // need separate declaration for Borland C++ -z_streamp z) -{ - inflate_codes_statef *c; - - if ((c = (inflate_codes_statef *) - ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) - { - c->mode = START; - c->lbits = (Byte)bl; - c->dbits = (Byte)bd; - c->ltree = tl; - c->dtree = td; - Tracev((stderr, "inflate: codes new\n")); - } - return c; -} - - -int inflate_codes(inflate_blocks_statef *s, z_streamp z, int r) -{ - uInt j; // temporary storage - const inflate_huft *t; // temporary pointer - uInt e; // extra bits or operation - uLong b; // bit buffer - uInt k; // bits in bit buffer - Byte *p; // input data pointer - uInt n; // bytes available there - Byte *q; // output window write pointer - uInt m; // bytes to end of window or read pointer - Byte *f; // pointer to copy strings from - inflate_codes_statef *c = s->sub.decode.codes; // codes state - - // copy input/output information to locals (UPDATE macro restores) - LOAD - - // process input and output based on current state - for(;;) switch (c->mode) - { // waiting for "i:"=input, "o:"=output, "x:"=nothing - case START: // x: set up for LEN -#ifndef SLOW - if (m >= 258 && n >= 10) - { - UPDATE - r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); - LOAD - if (r != Z_OK) - { - c->mode = r == Z_STREAM_END ? WASH : BADCODE; - break; - } - } -#endif // !SLOW - c->sub.code.need = c->lbits; - c->sub.code.tree = c->ltree; - c->mode = LEN; - case LEN: // i: get length/literal/eob next - j = c->sub.code.need; - NEEDBITS(j) - t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); - DUMPBITS(t->bits) - e = (uInt)(t->exop); - if (e == 0) // literal - { - c->sub.lit = t->base; - Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", t->base)); - c->mode = LIT; - break; - } - if (e & 16) // length - { - c->sub.copy.get = e & 15; - c->len = t->base; - c->mode = LENEXT; - break; - } - if ((e & 64) == 0) // next table - { - c->sub.code.need = e; - c->sub.code.tree = t + t->base; - break; - } - if (e & 32) // end of block - { - Tracevv((stderr, "inflate: end of block\n")); - c->mode = WASH; - break; - } - c->mode = BADCODE; // invalid code - z->msg = (char*)"invalid literal/length code"; - r = Z_DATA_ERROR; - LEAVE - case LENEXT: // i: getting length extra (have base) - j = c->sub.copy.get; - NEEDBITS(j) - c->len += (uInt)b & inflate_mask[j]; - DUMPBITS(j) - c->sub.code.need = c->dbits; - c->sub.code.tree = c->dtree; - Tracevv((stderr, "inflate: length %u\n", c->len)); - c->mode = DIST; - case DIST: // i: get distance next - j = c->sub.code.need; - NEEDBITS(j) - t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); - DUMPBITS(t->bits) - e = (uInt)(t->exop); - if (e & 16) // distance - { - c->sub.copy.get = e & 15; - c->sub.copy.dist = t->base; - c->mode = DISTEXT; - break; - } - if ((e & 64) == 0) // next table - { - c->sub.code.need = e; - c->sub.code.tree = t + t->base; - break; - } - c->mode = BADCODE; // invalid code - z->msg = (char*)"invalid distance code"; - r = Z_DATA_ERROR; - LEAVE - case DISTEXT: // i: getting distance extra - j = c->sub.copy.get; - NEEDBITS(j) - c->sub.copy.dist += (uInt)b & inflate_mask[j]; - DUMPBITS(j) - Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); - c->mode = COPY; - case COPY: // o: copying bytes in window, waiting for space - f = (uInt)(q - s->window) < c->sub.copy.dist ? - s->end - (c->sub.copy.dist - (q - s->window)) : - q - c->sub.copy.dist; - while (c->len) - { - NEEDOUT - OUTBYTE(*f++) - if (f == s->end) - f = s->window; - c->len--; - } - c->mode = START; - break; - case LIT: // o: got literal, waiting for output space - NEEDOUT - OUTBYTE(c->sub.lit) - c->mode = START; - break; - case WASH: // o: got eob, possibly more output - if (k > 7) // return unused byte, if any - { - Assert(k < 16, "inflate_codes grabbed too many bytes") - k -= 8; - n++; - p--; // can always return one - } - FLUSH - if (s->read != s->write) - LEAVE - c->mode = END; - case END: - r = Z_STREAM_END; - LEAVE - case BADCODE: // x: got error - r = Z_DATA_ERROR; - LEAVE - default: - r = Z_STREAM_ERROR; - LEAVE - } -} - - -void inflate_codes_free(inflate_codes_statef *c,z_streamp z) -{ ZFREE(z, c); - Tracev((stderr, "inflate: codes free\n")); -} - - - -// infblock.c -- interpret and process block types to last block -// Copyright (C) 1995-1998 Mark Adler -// For conditions of distribution and use, see copyright notice in zlib.h - -//struct inflate_codes_state {int dummy;}; // for buggy compilers - - - -// Table for deflate from PKZIP's appnote.txt. -const uInt border[] = { // Order of the bit length code lengths - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - -// -// Notes beyond the 1.93a appnote.txt: -// -// 1. Distance pointers never point before the beginning of the output stream. -// 2. Distance pointers can point back across blocks, up to 32k away. -// 3. There is an implied maximum of 7 bits for the bit length table and -// 15 bits for the actual data. -// 4. If only one code exists, then it is encoded using one bit. (Zero -// would be more efficient, but perhaps a little confusing.) If two -// codes exist, they are coded using one bit each (0 and 1). -// 5. There is no way of sending zero distance codes--a dummy must be -// sent if there are none. (History: a pre 2.0 version of PKZIP would -// store blocks with no distance codes, but this was discovered to be -// too harsh a criterion.) Valid only for 1.93a. 2.04c does allow -// zero distance codes, which is sent as one code of zero bits in -// length. -// 6. There are up to 286 literal/length codes. Code 256 represents the -// end-of-block. Note however that the static length tree defines -// 288 codes just to fill out the Huffman codes. Codes 286 and 287 -// cannot be used though, since there is no length base or extra bits -// defined for them. Similarily, there are up to 30 distance codes. -// However, static trees define 32 codes (all 5 bits) to fill out the -// Huffman codes, but the last two had better not show up in the data. -// 7. Unzip can check dynamic Huffman blocks for complete code sets. -// The exception is that a single code would not be complete (see #4). -// 8. The five bits following the block type is really the number of -// literal codes sent minus 257. -// 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits -// (1+6+6). Therefore, to output three times the length, you output -// three codes (1+1+1), whereas to output four times the same length, -// you only need two codes (1+3). Hmm. -//10. In the tree reconstruction algorithm, Code = Code + Increment -// only if BitLength(i) is not zero. (Pretty obvious.) -//11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) -//12. Note: length code 284 can represent 227-258, but length code 285 -// really is 258. The last length deserves its own, short code -// since it gets used a lot in very redundant files. The length -// 258 is special since 258 - 3 (the min match length) is 255. -//13. The literal/length and distance code bit lengths are read as a -// single stream of lengths. It is possible (and advantageous) for -// a repeat code (16, 17, or 18) to go across the boundary between -// the two sets of lengths. - - -void inflate_blocks_reset(inflate_blocks_statef *s, z_streamp z, uLong *c) -{ - if (c != Z_NULL) - *c = s->check; - if (s->mode == IBM_BTREE || s->mode == IBM_DTREE) - ZFREE(z, s->sub.trees.blens); - if (s->mode == IBM_CODES) - inflate_codes_free(s->sub.decode.codes, z); - s->mode = IBM_TYPE; - s->bitk = 0; - s->bitb = 0; - s->read = s->write = s->window; - if (s->checkfn != Z_NULL) - z->adler = s->check = (*s->checkfn)(0L, (const Byte *)Z_NULL, 0); - Tracev((stderr, "inflate: blocks reset\n")); -} - - -inflate_blocks_statef *inflate_blocks_new(z_streamp z, check_func c, uInt w) -{ - inflate_blocks_statef *s; - - if ((s = (inflate_blocks_statef *)ZALLOC - (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) - return s; - if ((s->hufts = - (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL) - { - ZFREE(z, s); - return Z_NULL; - } - if ((s->window = (Byte *)ZALLOC(z, 1, w)) == Z_NULL) - { - ZFREE(z, s->hufts); - ZFREE(z, s); - return Z_NULL; - } - s->end = s->window + w; - s->checkfn = c; - s->mode = IBM_TYPE; - Tracev((stderr, "inflate: blocks allocated\n")); - inflate_blocks_reset(s, z, Z_NULL); - return s; -} - - -int inflate_blocks(inflate_blocks_statef *s, z_streamp z, int r) -{ - uInt t; // temporary storage - uLong b; // bit buffer - uInt k; // bits in bit buffer - Byte *p; // input data pointer - uInt n; // bytes available there - Byte *q; // output window write pointer - uInt m; // bytes to end of window or read pointer - - // copy input/output information to locals (UPDATE macro restores) - LOAD - - // process input based on current state - for(;;) switch (s->mode) - { - case IBM_TYPE: - NEEDBITS(3) - t = (uInt)b & 7; - s->last = t & 1; - switch (t >> 1) - { - case 0: // stored - Tracev((stderr, "inflate: stored block%s\n", - s->last ? " (last)" : "")); - DUMPBITS(3) - t = k & 7; // go to byte boundary - DUMPBITS(t) - s->mode = IBM_LENS; // get length of stored block - break; - case 1: // fixed - Tracev((stderr, "inflate: fixed codes block%s\n", - s->last ? " (last)" : "")); - { - uInt bl, bd; - const inflate_huft *tl, *td; - - inflate_trees_fixed(&bl, &bd, &tl, &td, z); - s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); - if (s->sub.decode.codes == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - } - DUMPBITS(3) - s->mode = IBM_CODES; - break; - case 2: // dynamic - Tracev((stderr, "inflate: dynamic codes block%s\n", - s->last ? " (last)" : "")); - DUMPBITS(3) - s->mode = IBM_TABLE; - break; - case 3: // illegal - DUMPBITS(3) - s->mode = IBM_BAD; - z->msg = (char*)"invalid block type"; - r = Z_DATA_ERROR; - LEAVE - } - break; - case IBM_LENS: - NEEDBITS(32) - if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) - { - s->mode = IBM_BAD; - z->msg = (char*)"invalid stored block lengths"; - r = Z_DATA_ERROR; - LEAVE - } - s->sub.left = (uInt)b & 0xffff; - b = k = 0; // dump bits - Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); - s->mode = s->sub.left ? IBM_STORED : (s->last ? IBM_DRY : IBM_TYPE); - break; - case IBM_STORED: - if (n == 0) - LEAVE - NEEDOUT - t = s->sub.left; - if (t > n) t = n; - if (t > m) t = m; - memcpy(q, p, t); - p += t; n -= t; - q += t; m -= t; - if ((s->sub.left -= t) != 0) - break; - Tracev((stderr, "inflate: stored end, %lu total out\n", - z->total_out + (q >= s->read ? q - s->read : - (s->end - s->read) + (q - s->window)))); - s->mode = s->last ? IBM_DRY : IBM_TYPE; - break; - case IBM_TABLE: - NEEDBITS(14) - s->sub.trees.table = t = (uInt)b & 0x3fff; - // remove this section to workaround bug in pkzip - if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) - { - s->mode = IBM_BAD; - z->msg = (char*)"too many length or distance symbols"; - r = Z_DATA_ERROR; - LEAVE - } - // end remove - t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); - if ((s->sub.trees.blens = (uInt*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - DUMPBITS(14) - s->sub.trees.index = 0; - Tracev((stderr, "inflate: table sizes ok\n")); - s->mode = IBM_BTREE; - case IBM_BTREE: - while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) - { - NEEDBITS(3) - s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; - DUMPBITS(3) - } - while (s->sub.trees.index < 19) - s->sub.trees.blens[border[s->sub.trees.index++]] = 0; - s->sub.trees.bb = 7; - t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, - &s->sub.trees.tb, s->hufts, z); - if (t != Z_OK) - { - ZFREE(z, s->sub.trees.blens); - r = t; - if (r == Z_DATA_ERROR) - s->mode = IBM_BAD; - LEAVE - } - s->sub.trees.index = 0; - Tracev((stderr, "inflate: bits tree ok\n")); - s->mode = IBM_DTREE; - case IBM_DTREE: - while (t = s->sub.trees.table, - s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) - { - inflate_huft *h; - uInt i, j, c; - - t = s->sub.trees.bb; - NEEDBITS(t) - h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); - t = h->bits; - c = h->base; - if (c < 16) - { - DUMPBITS(t) - s->sub.trees.blens[s->sub.trees.index++] = c; - } - else // c == 16..18 - { - i = c == 18 ? 7 : c - 14; - j = c == 18 ? 11 : 3; - NEEDBITS(t + i) - DUMPBITS(t) - j += (uInt)b & inflate_mask[i]; - DUMPBITS(i) - i = s->sub.trees.index; - t = s->sub.trees.table; - if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || - (c == 16 && i < 1)) - { - ZFREE(z, s->sub.trees.blens); - s->mode = IBM_BAD; - z->msg = (char*)"invalid bit length repeat"; - r = Z_DATA_ERROR; - LEAVE - } - c = c == 16 ? s->sub.trees.blens[i - 1] : 0; - do { - s->sub.trees.blens[i++] = c; - } while (--j); - s->sub.trees.index = i; - } - } - s->sub.trees.tb = Z_NULL; - { - uInt bl, bd; - inflate_huft *tl, *td; - inflate_codes_statef *c; - - bl = 9; // must be <= 9 for lookahead assumptions - bd = 6; // must be <= 9 for lookahead assumptions - t = s->sub.trees.table; - t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), - s->sub.trees.blens, &bl, &bd, &tl, &td, - s->hufts, z); - ZFREE(z, s->sub.trees.blens); - if (t != Z_OK) - { - if (t == (uInt)Z_DATA_ERROR) - s->mode = IBM_BAD; - r = t; - LEAVE - } - Tracev((stderr, "inflate: trees ok\n")); - if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) - { - r = Z_MEM_ERROR; - LEAVE - } - s->sub.decode.codes = c; - } - s->mode = IBM_CODES; - case IBM_CODES: - UPDATE - if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) - return inflate_flush(s, z, r); - r = Z_OK; - inflate_codes_free(s->sub.decode.codes, z); - LOAD - Tracev((stderr, "inflate: codes end, %lu total out\n", - z->total_out + (q >= s->read ? q - s->read : - (s->end - s->read) + (q - s->window)))); - if (!s->last) - { - s->mode = IBM_TYPE; - break; - } - s->mode = IBM_DRY; - case IBM_DRY: - FLUSH - if (s->read != s->write) - LEAVE - s->mode = IBM_DONE; - case IBM_DONE: - r = Z_STREAM_END; - LEAVE - case IBM_BAD: - r = Z_DATA_ERROR; - LEAVE - default: - r = Z_STREAM_ERROR; - LEAVE - } -} - - -int inflate_blocks_free(inflate_blocks_statef *s, z_streamp z) -{ - inflate_blocks_reset(s, z, Z_NULL); - ZFREE(z, s->window); - ZFREE(z, s->hufts); - ZFREE(z, s); - Tracev((stderr, "inflate: blocks freed\n")); - return Z_OK; -} - - - -// inftrees.c -- generate Huffman trees for efficient decoding -// Copyright (C) 1995-1998 Mark Adler -// For conditions of distribution and use, see copyright notice in zlib.h -// - - - -extern const char inflate_copyright[] = - " inflate 1.1.3 Copyright 1995-1998 Mark Adler "; -// If you use the zlib library in a product, an acknowledgment is welcome -// in the documentation of your product. If for some reason you cannot -// include such an acknowledgment, I would appreciate that you keep this -// copyright string in the executable of your product. - - - -int huft_build ( - uInt *, // code lengths in bits - uInt, // number of codes - uInt, // number of "simple" codes - const uInt *, // list of base values for non-simple codes - const uInt *, // list of extra bits for non-simple codes - inflate_huft **,// result: starting table - uInt *, // maximum lookup bits (returns actual) - inflate_huft *, // space for trees - uInt *, // hufts used in space - uInt * ); // space for values - -// Tables for deflate from PKZIP's appnote.txt. -const uInt cplens[31] = { // Copy lengths for literal codes 257..285 - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; - // see note #13 above about 258 -const uInt cplext[31] = { // Extra bits for literal codes 257..285 - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; // 112==invalid -const uInt cpdist[30] = { // Copy offsets for distance codes 0..29 - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577}; -const uInt cpdext[30] = { // Extra bits for distance codes - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, - 12, 12, 13, 13}; - -// -// Huffman code decoding is performed using a multi-level table lookup. -// The fastest way to decode is to simply build a lookup table whose -// size is determined by the longest code. However, the time it takes -// to build this table can also be a factor if the data being decoded -// is not very long. The most common codes are necessarily the -// shortest codes, so those codes dominate the decoding time, and hence -// the speed. The idea is you can have a shorter table that decodes the -// shorter, more probable codes, and then point to subsidiary tables for -// the longer codes. The time it costs to decode the longer codes is -// then traded against the time it takes to make longer tables. -// -// This results of this trade are in the variables lbits and dbits -// below. lbits is the number of bits the first level table for literal/ -// length codes can decode in one step, and dbits is the same thing for -// the distance codes. Subsequent tables are also less than or equal to -// those sizes. These values may be adjusted either when all of the -// codes are shorter than that, in which case the longest code length in -// bits is used, or when the shortest code is *longer* than the requested -// table size, in which case the length of the shortest code in bits is -// used. -// -// There are two different values for the two tables, since they code a -// different number of possibilities each. The literal/length table -// codes 286 possible values, or in a flat code, a little over eight -// bits. The distance table codes 30 possible values, or a little less -// than five bits, flat. The optimum values for speed end up being -// about one bit more than those, so lbits is 8+1 and dbits is 5+1. -// The optimum values may differ though from machine to machine, and -// possibly even between compilers. Your mileage may vary. -// - - -// If BMAX needs to be larger than 16, then h and x[] should be uLong. -#define BMAX 15 // maximum bit length of any code - -int huft_build( -uInt *b, // code lengths in bits (all assumed <= BMAX) -uInt n, // number of codes (assumed <= 288) -uInt s, // number of simple-valued codes (0..s-1) -const uInt *d, // list of base values for non-simple codes -const uInt *e, // list of extra bits for non-simple codes -inflate_huft * *t, // result: starting table -uInt *m, // maximum lookup bits, returns actual -inflate_huft *hp, // space for trees -uInt *hn, // hufts used in space -uInt *v) // working area: values in order of bit length -// Given a list of code lengths and a maximum table size, make a set of -// tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR -// if the given code set is incomplete (the tables are still built in this -// case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of -// lengths), or Z_MEM_ERROR if not enough memory. -{ - - uInt a; // counter for codes of length k - uInt c[BMAX+1]; // bit length count table - uInt f; // i repeats in table every f entries - int g; // maximum code length - int h; // table level - register uInt i; // counter, current code - register uInt j; // counter - register int k; // number of bits in current code - int l; // bits per table (returned in m) - uInt mask; // (1 << w) - 1, to avoid cc -O bug on HP - register uInt *p; // pointer into c[], b[], or v[] - inflate_huft *q; // points to current table - struct inflate_huft_s r; // table entry for structure assignment - inflate_huft *u[BMAX]; // table stack - register int w; // bits before this table == (l * h) - uInt x[BMAX+1]; // bit offsets, then code stack - uInt *xp; // pointer into x - int y; // number of dummy codes added - uInt z; // number of entries in current table - - - // Generate counts for each bit length - p = c; -#define C0 *p++ = 0; -#define C2 C0 C0 C0 C0 -#define C4 C2 C2 C2 C2 - C4; p; // clear c[]--assume BMAX+1 is 16 - p = b; i = n; - do { - c[*p++]++; // assume all entries <= BMAX - } while (--i); - if (c[0] == n) // null input--all zero length codes - { - *t = (inflate_huft *)Z_NULL; - *m = 0; - return Z_OK; - } - - - // Find minimum and maximum length, bound *m by those - l = *m; - for (j = 1; j <= BMAX; j++) - if (c[j]) - break; - k = j; // minimum code length - if ((uInt)l < j) - l = j; - for (i = BMAX; i; i--) - if (c[i]) - break; - g = i; // maximum code length - if ((uInt)l > i) - l = i; - *m = l; - - - // Adjust last length count to fill out codes, if needed - for (y = 1 << j; j < i; j++, y <<= 1) - if ((y -= c[j]) < 0) - return Z_DATA_ERROR; - if ((y -= c[i]) < 0) - return Z_DATA_ERROR; - c[i] += y; - - - // Generate starting offsets into the value table for each length - x[1] = j = 0; - p = c + 1; xp = x + 2; - while (--i) { // note that i == g from above - *xp++ = (j += *p++); - } - - - // Make a table of values in order of bit lengths - p = b; i = 0; - do { - if ((j = *p++) != 0) - v[x[j]++] = i; - } while (++i < n); - n = x[g]; // set n to length of v - - - // Generate the Huffman codes and for each, make the table entries - x[0] = i = 0; // first Huffman code is zero - p = v; // grab values in bit order - h = -1; // no tables yet--level -1 - w = -l; // bits decoded == (l * h) - u[0] = (inflate_huft *)Z_NULL; // just to keep compilers happy - q = (inflate_huft *)Z_NULL; // ditto - z = 0; // ditto - - // go through the bit lengths (k already is bits in shortest code) - for (; k <= g; k++) - { - a = c[k]; - while (a--) - { - // here i is the Huffman code of length k bits for value *p - // make tables up to required level - while (k > w + l) - { - h++; - w += l; // previous table always l bits - - // compute minimum size table less than or equal to l bits - z = g - w; - z = z > (uInt)l ? l : z; // table size upper limit - if ((f = 1 << (j = k - w)) > a + 1) // try a k-w bit table - { // too few codes for k-w bit table - f -= a + 1; // deduct codes from patterns left - xp = c + k; - if (j < z) - while (++j < z) // try smaller tables up to z bits - { - if ((f <<= 1) <= *++xp) - break; // enough codes to use up j bits - f -= *xp; // else deduct codes from patterns - } - } - z = 1 << j; // table entries for j-bit table - - // allocate new table - if (*hn + z > MANY) // (note: doesn't matter for fixed) - return Z_MEM_ERROR; // not enough memory - u[h] = q = hp + *hn; - *hn += z; - - // connect to last table, if there is one - if (h) - { - x[h] = i; // save pattern for backing up - r.bits = (Byte)l; // bits to dump before this table - r.exop = (Byte)j; // bits in this table - j = i >> (w - l); - r.base = (uInt)(q - u[h-1] - j); // offset to this table - u[h-1][j] = r; // connect to last table - } - else - *t = q; // first table is returned result - } - - // set up table entry in r - r.bits = (Byte)(k - w); - if (p >= v + n) - r.exop = 128 + 64; // out of values--invalid code - else if (*p < s) - { - r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); // 256 is end-of-block - r.base = *p++; // simple code is just the value - } - else - { - r.exop = (Byte)(e[*p - s] + 16 + 64);// non-simple--look up in lists - r.base = d[*p++ - s]; - } - - // fill code-like entries with r - f = 1 << (k - w); - for (j = i >> w; j < z; j += f) - q[j] = r; - - // backwards increment the k-bit code i - for (j = 1 << (k - 1); i & j; j >>= 1) - i ^= j; - i ^= j; - - // backup over finished tables - mask = (1 << w) - 1; // needed on HP, cc -O bug - while ((i & mask) != x[h]) - { - h--; // don't need to update q - w -= l; - mask = (1 << w) - 1; - } - } - } - - - // Return Z_BUF_ERROR if we were given an incomplete table - return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; -} - - -int inflate_trees_bits( -uInt *c, // 19 code lengths -uInt *bb, // bits tree desired/actual depth -inflate_huft * *tb, // bits tree result -inflate_huft *hp, // space for trees -z_streamp z) // for messages -{ - int r; - uInt hn = 0; // hufts used in space - uInt *v; // work area for huft_build - - if ((v = (uInt*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL) - return Z_MEM_ERROR; - r = huft_build(c, 19, 19, (uInt*)Z_NULL, (uInt*)Z_NULL, - tb, bb, hp, &hn, v); - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed dynamic bit lengths tree"; - else if (r == Z_BUF_ERROR || *bb == 0) - { - z->msg = (char*)"incomplete dynamic bit lengths tree"; - r = Z_DATA_ERROR; - } - ZFREE(z, v); - return r; -} - - -int inflate_trees_dynamic( -uInt nl, // number of literal/length codes -uInt nd, // number of distance codes -uInt *c, // that many (total) code lengths -uInt *bl, // literal desired/actual bit depth -uInt *bd, // distance desired/actual bit depth -inflate_huft * *tl, // literal/length tree result -inflate_huft * *td, // distance tree result -inflate_huft *hp, // space for trees -z_streamp z) // for messages -{ - int r; - uInt hn = 0; // hufts used in space - uInt *v; // work area for huft_build - - // allocate work area - if ((v = (uInt*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) - return Z_MEM_ERROR; - - // build literal/length tree - r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v); - if (r != Z_OK || *bl == 0) - { - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed literal/length tree"; - else if (r != Z_MEM_ERROR) - { - z->msg = (char*)"incomplete literal/length tree"; - r = Z_DATA_ERROR; - } - ZFREE(z, v); - return r; - } - - // build distance tree - r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v); - if (r != Z_OK || (*bd == 0 && nl > 257)) - { - if (r == Z_DATA_ERROR) - z->msg = (char*)"oversubscribed distance tree"; - else if (r == Z_BUF_ERROR) { - z->msg = (char*)"incomplete distance tree"; - r = Z_DATA_ERROR; - } - else if (r != Z_MEM_ERROR) - { - z->msg = (char*)"empty distance tree with lengths"; - r = Z_DATA_ERROR; - } - ZFREE(z, v); - return r; - } - - // done - ZFREE(z, v); - return Z_OK; -} - - - - - -int inflate_trees_fixed( -uInt *bl, // literal desired/actual bit depth -uInt *bd, // distance desired/actual bit depth -const inflate_huft * * tl, // literal/length tree result -const inflate_huft * *td, // distance tree result -z_streamp ) // for memory allocation -{ - *bl = fixed_bl; - *bd = fixed_bd; - *tl = fixed_tl; - *td = fixed_td; - return Z_OK; -} - - -// inffast.c -- process literals and length/distance pairs fast -// Copyright (C) 1995-1998 Mark Adler -// For conditions of distribution and use, see copyright notice in zlib.h -// - - -//struct inflate_codes_state {int dummy;}; // for buggy compilers - - -// macros for bit input with no checking and for returning unused bytes -#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3;} - -// Called with number of bytes left to write in window at least 258 -// (the maximum string length) and number of input bytes available -// at least ten. The ten bytes are six bytes for the longest length/ -// distance pair plus four bytes for overloading the bit buffer. - -int inflate_fast( -uInt bl, uInt bd, -const inflate_huft *tl, -const inflate_huft *td, // need separate declaration for Borland C++ -inflate_blocks_statef *s, -z_streamp z) -{ - const inflate_huft *t; // temporary pointer - uInt e; // extra bits or operation - uLong b; // bit buffer - uInt k; // bits in bit buffer - Byte *p; // input data pointer - uInt n; // bytes available there - Byte *q; // output window write pointer - uInt m; // bytes to end of window or read pointer - uInt ml; // mask for literal/length tree - uInt md; // mask for distance tree - uInt c; // bytes to copy - uInt d; // distance back to copy from - Byte *r; // copy source pointer - - // load input, output, bit values - LOAD - - // initialize masks - ml = inflate_mask[bl]; - md = inflate_mask[bd]; - - // do until not enough input or output space for fast loop - do { // assume called with m >= 258 && n >= 10 - // get literal/length code - GRABBITS(20) // max bits for literal/length code - if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) - { - DUMPBITS(t->bits) - Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? - "inflate: * literal '%c'\n" : - "inflate: * literal 0x%02x\n", t->base)); - *q++ = (Byte)t->base; - m--; - continue; - } - for (;;) { - DUMPBITS(t->bits) - if (e & 16) - { - // get extra bits for length - e &= 15; - c = t->base + ((uInt)b & inflate_mask[e]); - DUMPBITS(e) - Tracevv((stderr, "inflate: * length %u\n", c)); - - // decode distance base of block to copy - GRABBITS(15); // max bits for distance code - e = (t = td + ((uInt)b & md))->exop; - for (;;) { - DUMPBITS(t->bits) - if (e & 16) - { - // get extra bits to add to distance base - e &= 15; - GRABBITS(e) // get extra bits (up to 13) - d = t->base + ((uInt)b & inflate_mask[e]); - DUMPBITS(e) - Tracevv((stderr, "inflate: * distance %u\n", d)); - - // do the copy - m -= c; - if ((uInt)(q - s->window) >= d) // offset before dest - { // just copy - r = q - d; - *q++ = *r++; c--; // minimum count is three, - *q++ = *r++; c--; // so unroll loop a little - } - else // else offset after destination - { - e = d - (uInt)(q - s->window); // bytes from offset to end - r = s->end - e; // pointer to offset - if (c > e) // if source crosses, - { - c -= e; // copy to end of window - do { - *q++ = *r++; - } while (--e); - r = s->window; // copy rest from start of window - } - } - do { // copy all or what's left - *q++ = *r++; - } while (--c); - break; - } - else if ((e & 64) == 0) - { - t += t->base; - e = (t += ((uInt)b & inflate_mask[e]))->exop; - } - else - { - z->msg = (char*)"invalid distance code"; - UNGRAB - UPDATE - return Z_DATA_ERROR; - } - }; - break; - } - if ((e & 64) == 0) - { - t += t->base; - if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0) - { - DUMPBITS(t->bits) - Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? - "inflate: * literal '%c'\n" : - "inflate: * literal 0x%02x\n", t->base)); - *q++ = (Byte)t->base; - m--; - break; - } - } - else if (e & 32) - { - Tracevv((stderr, "inflate: * end of block\n")); - UNGRAB - UPDATE - return Z_STREAM_END; - } - else - { - z->msg = (char*)"invalid literal/length code"; - UNGRAB - UPDATE - return Z_DATA_ERROR; - } - }; - } while (m >= 258 && n >= 10); - - // not enough input or output--restore pointers and return - UNGRAB - UPDATE - return Z_OK; -} - - - - - - -// crc32.c -- compute the CRC-32 of a data stream -// Copyright (C) 1995-1998 Mark Adler -// For conditions of distribution and use, see copyright notice in zlib.h - -// @(#) $Id$ - - - - - - -// Table of CRC-32's of all single-byte values (made by make_crc_table) -const uLong crc_table[256] = { - 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, - 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, - 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, - 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, - 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, - 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, - 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, - 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, - 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, - 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, - 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, - 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, - 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, - 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, - 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, - 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, - 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, - 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, - 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, - 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, - 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, - 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, - 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, - 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, - 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, - 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, - 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, - 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, - 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, - 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, - 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, - 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, - 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, - 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, - 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, - 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, - 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, - 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, - 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, - 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, - 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, - 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, - 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, - 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, - 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, - 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, - 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, - 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, - 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, - 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, - 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, - 0x2d02ef8dL -}; - -const uLong * get_crc_table() -{ return (const uLong *)crc_table; -} - -#define CRC_DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); -#define CRC_DO2(buf) CRC_DO1(buf); CRC_DO1(buf); -#define CRC_DO4(buf) CRC_DO2(buf); CRC_DO2(buf); -#define CRC_DO8(buf) CRC_DO4(buf); CRC_DO4(buf); - -uLong ucrc32(uLong crc, const Byte *buf, uInt len) -{ if (buf == Z_NULL) return 0L; - crc = crc ^ 0xffffffffL; - while (len >= 8) {CRC_DO8(buf); len -= 8;} - if (len) do {CRC_DO1(buf);} while (--len); - return crc ^ 0xffffffffL; -} - - -// adler32.c -- compute the Adler-32 checksum of a data stream -// Copyright (C) 1995-1998 Mark Adler -// For conditions of distribution and use, see copyright notice in zlib.h - -// @(#) $Id$ - - -#define BASE 65521L // largest prime smaller than 65536 -#define NMAX 5552 -// NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 - -#define AD_DO1(buf,i) {s1 += buf[i]; s2 += s1;} -#define AD_DO2(buf,i) AD_DO1(buf,i); AD_DO1(buf,i+1); -#define AD_DO4(buf,i) AD_DO2(buf,i); AD_DO2(buf,i+2); -#define AD_DO8(buf,i) AD_DO4(buf,i); AD_DO4(buf,i+4); -#define AD_DO16(buf) AD_DO8(buf,0); AD_DO8(buf,8); - -// ========================================================================= -uLong adler32(uLong adler, const Byte *buf, uInt len) -{ - unsigned long s1 = adler & 0xffff; - unsigned long s2 = (adler >> 16) & 0xffff; - int k; - - if (buf == Z_NULL) return 1L; - - while (len > 0) { - k = len < NMAX ? len : NMAX; - len -= k; - while (k >= 16) { - AD_DO16(buf); - buf += 16; - k -= 16; - } - if (k != 0) do { - s1 += *buf++; - s2 += s1; - } while (--k); - s1 %= BASE; - s2 %= BASE; - } - return (s2 << 16) | s1; -} - - - -// zutil.c -- target dependent utility functions for the compression library -// Copyright (C) 1995-1998 Jean-loup Gailly. -// For conditions of distribution and use, see copyright notice in zlib.h -// @(#) $Id$ - - - - - - -const char * zlibVersion() -{ - return ZLIB_VERSION; -} - -// exported to allow conversion of error code to string for compress() and -// uncompress() -const char * zError(int err) -{ return ERR_MSG(err); -} - - - - -voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) -{ - if (opaque) items += size - size; // make compiler happy - return (voidpf)calloc(items, size); -} - -void zcfree (voidpf opaque, voidpf ptr) -{ - zfree(ptr); - if (opaque) return; // make compiler happy -} - - - -// inflate.c -- zlib interface to inflate modules -// Copyright (C) 1995-1998 Mark Adler -// For conditions of distribution and use, see copyright notice in zlib.h - -//struct inflate_blocks_state {int dummy;}; // for buggy compilers - -typedef enum { - IM_METHOD, // waiting for method byte - IM_FLAG, // waiting for flag byte - IM_DICT4, // four dictionary check bytes to go - IM_DICT3, // three dictionary check bytes to go - IM_DICT2, // two dictionary check bytes to go - IM_DICT1, // one dictionary check byte to go - IM_DICT0, // waiting for inflateSetDictionary - IM_BLOCKS, // decompressing blocks - IM_CHECK4, // four check bytes to go - IM_CHECK3, // three check bytes to go - IM_CHECK2, // two check bytes to go - IM_CHECK1, // one check byte to go - IM_DONE, // finished check, done - IM_BAD} // got an error--stay here -inflate_mode; - -// inflate private state -struct internal_state { - - // mode - inflate_mode mode; // current inflate mode - - // mode dependent information - union { - uInt method; // if IM_FLAGS, method byte - struct { - uLong was; // computed check value - uLong need; // stream check value - } check; // if CHECK, check values to compare - uInt marker; // if IM_BAD, inflateSync's marker bytes count - } sub; // submode - - // mode independent information - int nowrap; // flag for no wrapper - uInt wbits; // log2(window size) (8..15, defaults to 15) - inflate_blocks_statef - *blocks; // current inflate_blocks state - -}; - -int inflateReset(z_streamp z) -{ - if (z == Z_NULL || z->state == Z_NULL) - return Z_STREAM_ERROR; - z->total_in = z->total_out = 0; - z->msg = Z_NULL; - z->state->mode = z->state->nowrap ? IM_BLOCKS : IM_METHOD; - inflate_blocks_reset(z->state->blocks, z, Z_NULL); - Tracev((stderr, "inflate: reset\n")); - return Z_OK; -} - -int inflateEnd(z_streamp z) -{ - if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) - return Z_STREAM_ERROR; - if (z->state->blocks != Z_NULL) - inflate_blocks_free(z->state->blocks, z); - ZFREE(z, z->state); - z->state = Z_NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; -} - - -int inflateInit2(z_streamp z) -{ const char *version = ZLIB_VERSION; int stream_size = sizeof(z_stream); - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || stream_size != sizeof(z_stream)) return Z_VERSION_ERROR; - - int w = -15; // MAX_WBITS: 32K LZ77 window. - // Warning: reducing MAX_WBITS makes minigzip unable to extract .gz files created by gzip. - // The memory requirements for deflate are (in bytes): - // (1 << (windowBits+2)) + (1 << (memLevel+9)) - // that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - // plus a few kilobytes for small objects. For example, if you want to reduce - // the default memory requirements from 256K to 128K, compile with - // make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - // Of course this will generally degrade compression (there's no free lunch). - // - // The memory requirements for inflate are (in bytes) 1 << windowBits - // that is, 32K for windowBits=15 (default value) plus a few kilobytes - // for small objects. - - // initialize state - if (z == Z_NULL) return Z_STREAM_ERROR; - z->msg = Z_NULL; - if (z->zalloc == Z_NULL) - { - z->zalloc = zcalloc; - z->opaque = (voidpf)0; - } - if (z->zfree == Z_NULL) z->zfree = zcfree; - if ((z->state = (struct internal_state *) - ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) - return Z_MEM_ERROR; - z->state->blocks = Z_NULL; - - // handle undocumented nowrap option (no zlib header or check) - z->state->nowrap = 0; - if (w < 0) - { - w = - w; - z->state->nowrap = 1; - } - - // set window size - if (w < 8 || w > 15) - { - inflateEnd(z); - return Z_STREAM_ERROR; - } - z->state->wbits = (uInt)w; - - // create inflate_blocks state - if ((z->state->blocks = - inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w)) - == Z_NULL) - { - inflateEnd(z); - return Z_MEM_ERROR; - } - Tracev((stderr, "inflate: allocated\n")); - - // reset state - inflateReset(z); - return Z_OK; -} - - - -#define IM_NEEDBYTE {if(z->avail_in==0)return r;r=f;} -#define IM_NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) - -int inflate(z_streamp z, int f) -{ - int r; - uInt b; - - if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL) - return Z_STREAM_ERROR; - f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; - r = Z_BUF_ERROR; - for (;;) switch (z->state->mode) - { - case IM_METHOD: - IM_NEEDBYTE - if (((z->state->sub.method = IM_NEXTBYTE) & 0xf) != Z_DEFLATED) - { - z->state->mode = IM_BAD; - z->msg = (char*)"unknown compression method"; - z->state->sub.marker = 5; // can't try inflateSync - break; - } - if ((z->state->sub.method >> 4) + 8 > z->state->wbits) - { - z->state->mode = IM_BAD; - z->msg = (char*)"invalid window size"; - z->state->sub.marker = 5; // can't try inflateSync - break; - } - z->state->mode = IM_FLAG; - case IM_FLAG: - IM_NEEDBYTE - b = IM_NEXTBYTE; - if (((z->state->sub.method << 8) + b) % 31) - { - z->state->mode = IM_BAD; - z->msg = (char*)"incorrect header check"; - z->state->sub.marker = 5; // can't try inflateSync - break; - } - Tracev((stderr, "inflate: zlib header ok\n")); - if (!(b & PRESET_DICT)) - { - z->state->mode = IM_BLOCKS; - break; - } - z->state->mode = IM_DICT4; - case IM_DICT4: - IM_NEEDBYTE - z->state->sub.check.need = (uLong)IM_NEXTBYTE << 24; - z->state->mode = IM_DICT3; - case IM_DICT3: - IM_NEEDBYTE - z->state->sub.check.need += (uLong)IM_NEXTBYTE << 16; - z->state->mode = IM_DICT2; - case IM_DICT2: - IM_NEEDBYTE - z->state->sub.check.need += (uLong)IM_NEXTBYTE << 8; - z->state->mode = IM_DICT1; - case IM_DICT1: - IM_NEEDBYTE; r; - z->state->sub.check.need += (uLong)IM_NEXTBYTE; - z->adler = z->state->sub.check.need; - z->state->mode = IM_DICT0; - return Z_NEED_DICT; - case IM_DICT0: - z->state->mode = IM_BAD; - z->msg = (char*)"need dictionary"; - z->state->sub.marker = 0; // can try inflateSync - return Z_STREAM_ERROR; - case IM_BLOCKS: - r = inflate_blocks(z->state->blocks, z, r); - if (r == Z_DATA_ERROR) - { - z->state->mode = IM_BAD; - z->state->sub.marker = 0; // can try inflateSync - break; - } - if (r == Z_OK) - r = f; - if (r != Z_STREAM_END) - return r; - r = f; - inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); - if (z->state->nowrap) - { - z->state->mode = IM_DONE; - break; - } - z->state->mode = IM_CHECK4; - case IM_CHECK4: - IM_NEEDBYTE - z->state->sub.check.need = (uLong)IM_NEXTBYTE << 24; - z->state->mode = IM_CHECK3; - case IM_CHECK3: - IM_NEEDBYTE - z->state->sub.check.need += (uLong)IM_NEXTBYTE << 16; - z->state->mode = IM_CHECK2; - case IM_CHECK2: - IM_NEEDBYTE - z->state->sub.check.need += (uLong)IM_NEXTBYTE << 8; - z->state->mode = IM_CHECK1; - case IM_CHECK1: - IM_NEEDBYTE - z->state->sub.check.need += (uLong)IM_NEXTBYTE; - - if (z->state->sub.check.was != z->state->sub.check.need) - { - z->state->mode = IM_BAD; - z->msg = (char*)"incorrect data check"; - z->state->sub.marker = 5; // can't try inflateSync - break; - } - Tracev((stderr, "inflate: zlib check ok\n")); - z->state->mode = IM_DONE; - case IM_DONE: - return Z_STREAM_END; - case IM_BAD: - return Z_DATA_ERROR; - default: - return Z_STREAM_ERROR; - } -} - - - -#ifdef _UNICODE - -static int GetAnsiFileName(LPCWSTR name, char * buf, int nBufSize) -{ - memset(buf, 0, nBufSize); - - int n = WideCharToMultiByte(CP_ACP, // code page - 0, // performance and mapping flags - name, // wide-character string - -1, // number of chars in string - buf, // buffer for new string - nBufSize, // size of buffer - NULL, // default for unmappable chars - NULL); // set when default char used - return n; -} - -static int GetUnicodeFileName(const char * name, LPWSTR buf, int nBufSize) -{ - memset(buf, 0, nBufSize*sizeof(TCHAR)); - - int n = MultiByteToWideChar(CP_ACP, // code page - 0, // character-type options - name, // string to map - -1, // number of bytes in string - buf, // wide-character buffer - nBufSize); // size of buffer - - return n; -} - -#endif - - -// unzip.c -- IO on .zip files using zlib -// Version 0.15 beta, Mar 19th, 1998, -// Read unzip.h for more info - - - - -#define UNZ_BUFSIZE (16384) -#define UNZ_MAXFILENAMEINZIP (256) -#define SIZECENTRALDIRITEM (0x2e) -#define SIZEZIPLOCALHEADER (0x1e) - - - - -const char unz_copyright[] = " unzip 0.15 Copyright 1998 Gilles Vollant "; - -// unz_file_info_interntal contain internal info about a file in zipfile -typedef struct unz_file_info_internal_s -{ - uLong offset_curfile;// relative offset of local header 4 bytes -} unz_file_info_internal; - - -typedef struct -{ bool is_handle; // either a handle or memory - bool canseek; - // for handles: - HANDLE h; bool herr; unsigned long initial_offset; - // for memory: - void *buf; unsigned int len,pos; // if it's a memory block -} LUFILE; - - -LUFILE *lufopen(void *z,unsigned int len,DWORD flags,ZRESULT *err) -{ - if (flags!=ZIP_HANDLE && flags!=ZIP_FILENAME && flags!=ZIP_MEMORY) - { - *err=ZR_ARGS; - return NULL; - } - // - HANDLE h=0; bool canseek=false; *err=ZR_OK; - if (flags==ZIP_HANDLE||flags==ZIP_FILENAME) - { - if (flags==ZIP_HANDLE) - { - HANDLE hf = z; - - BOOL res = DuplicateHandle(GetCurrentProcess(),hf,GetCurrentProcess(),&h,0,FALSE,DUPLICATE_SAME_ACCESS); - - if (!res) - { - *err=ZR_NODUPH; - return NULL; - } - } - else - { - h = CreateFile((const TCHAR *)z, GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - - if (h == INVALID_HANDLE_VALUE) - { - *err = ZR_NOFILE; - return NULL; - } - } - DWORD type = GetFileType(h); - canseek = (type==FILE_TYPE_DISK); - } - LUFILE *lf = new LUFILE; - if (flags==ZIP_HANDLE||flags==ZIP_FILENAME) - { - lf->is_handle=true; - lf->canseek=canseek; - lf->h=h; lf->herr=false; - lf->initial_offset=0; - if (canseek) - lf->initial_offset = SetFilePointer(h,0,NULL,FILE_CURRENT); - } - else - { - lf->is_handle=false; - lf->canseek=true; - lf->buf=z; - lf->len=len; - lf->pos=0; - lf->initial_offset=0; - } - *err=ZR_OK; - return lf; -} - - -int lufclose(LUFILE *stream) -{ if (stream==NULL) return EOF; - if (stream->is_handle) CloseHandle(stream->h); - delete stream; - return 0; -} - -int luferror(LUFILE *stream) -{ if (stream->is_handle && stream->herr) return 1; - else return 0; -} - -long int luftell(LUFILE *stream) -{ if (stream->is_handle && stream->canseek) return SetFilePointer(stream->h,0,NULL,FILE_CURRENT)-stream->initial_offset; - else if (stream->is_handle) return 0; - else return stream->pos; -} - -int lufseek(LUFILE *stream, long offset, int whence) -{ if (stream->is_handle && stream->canseek) - { if (whence==SEEK_SET) SetFilePointer(stream->h,stream->initial_offset+offset,0,FILE_BEGIN); - else if (whence==SEEK_CUR) SetFilePointer(stream->h,offset,NULL,FILE_CURRENT); - else if (whence==SEEK_END) SetFilePointer(stream->h,offset,NULL,FILE_END); - else return 19; // EINVAL - return 0; - } - else if (stream->is_handle) return 29; // ESPIPE - else - { if (whence==SEEK_SET) stream->pos=offset; - else if (whence==SEEK_CUR) stream->pos+=offset; - else if (whence==SEEK_END) stream->pos=stream->len+offset; - return 0; - } -} - - -size_t lufread(void *ptr,size_t size,size_t n,LUFILE *stream) -{ unsigned int toread = (unsigned int)(size*n); - if (stream->is_handle) - { DWORD red; BOOL res = ReadFile(stream->h,ptr,toread,&red,NULL); - if (!res) stream->herr=true; - return red/size; - } - if (stream->pos+toread > stream->len) toread = stream->len-stream->pos; - memcpy(ptr, (char*)stream->buf + stream->pos, toread); DWORD red = toread; - stream->pos += red; - return red/size; -} - - - - -// file_in_zip_read_info_s contain internal information about a file in zipfile, -// when reading and decompress it -typedef struct -{ - char *read_buffer; // internal buffer for compressed data - z_stream stream; // zLib stream structure for inflate - - uLong pos_in_zipfile; // position in byte on the zipfile, for fseek - uLong stream_initialised; // flag set if stream structure is initialised - - uLong offset_local_extrafield;// offset of the local extra field - uInt size_local_extrafield;// size of the local extra field - uLong pos_local_extrafield; // position in the local extra field in read - - uLong crc32; // crc32 of all data uncompressed - uLong crc32_wait; // crc32 we must obtain after decompress all - uLong rest_read_compressed; // number of byte to be decompressed - uLong rest_read_uncompressed;//number of byte to be obtained after decomp - LUFILE* file; // io structore of the zipfile - uLong compression_method; // compression method (0==store) - uLong byte_before_the_zipfile;// byte before the zipfile, (>0 for sfx) -} file_in_zip_read_info_s; - - -// unz_s contain internal information about the zipfile -typedef struct -{ - LUFILE* file; // io structore of the zipfile - unz_global_info gi; // public global information - uLong byte_before_the_zipfile;// byte before the zipfile, (>0 for sfx) - uLong num_file; // number of the current file in the zipfile - uLong pos_in_central_dir; // pos of the current file in the central dir - uLong current_file_ok; // flag about the usability of the current file - uLong central_pos; // position of the beginning of the central dir - - uLong size_central_dir; // size of the central directory - uLong offset_central_dir; // offset of start of central directory with respect to the starting disk number - - unz_file_info cur_file_info; // public info about the current file in zip - unz_file_info_internal cur_file_info_internal; // private info about it - file_in_zip_read_info_s* pfile_in_zip_read; // structure about the current file if we are decompressing it -} unz_s, *unzFile; - - -int unzStringFileNameCompare (const char* fileName1,const char* fileName2,int iCaseSensitivity); -// Compare two filename (fileName1,fileName2). - -z_off_t unztell (unzFile file); -// Give the current position in uncompressed data - -int unzeof (unzFile file); -// return 1 if the end of file was reached, 0 elsewhere - -int unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len); -// Read extra field from the current file (opened by unzOpenCurrentFile) -// This is the local-header version of the extra field (sometimes, there is -// more info in the local-header version than in the central-header) -// -// if buf==NULL, it return the size of the local extra field -// -// if buf!=NULL, len is the size of the buffer, the extra header is copied in -// buf. -// the return value is the number of bytes copied in buf, or (if <0) -// the error code - - - -// =========================================================================== -// Read a byte from a gz_stream; update next_in and avail_in. Return EOF -// for end of file. -// IN assertion: the stream s has been sucessfully opened for reading. - -int unzlocal_getByte(LUFILE *fin,int *pi) -{ unsigned char c; - int err = (int)lufread(&c, 1, 1, fin); - if (err==1) - { *pi = (int)c; - return UNZ_OK; - } - else - { if (luferror(fin)) return UNZ_ERRNO; - else return UNZ_EOF; - } -} - - -// =========================================================================== -// Reads a long in LSB order from the given gz_stream. Sets -int unzlocal_getShort (LUFILE *fin,uLong *pX) -{ - uLong x ; - int i; - int err; - - err = unzlocal_getByte(fin,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unzlocal_getByte(fin,&i); - x += ((uLong)i)<<8; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - -int unzlocal_getLong (LUFILE *fin,uLong *pX) -{ - uLong x ; - int i; - int err; - - err = unzlocal_getByte(fin,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unzlocal_getByte(fin,&i); - x += ((uLong)i)<<8; - - if (err==UNZ_OK) - err = unzlocal_getByte(fin,&i); - x += ((uLong)i)<<16; - - if (err==UNZ_OK) - err = unzlocal_getByte(fin,&i); - x += ((uLong)i)<<24; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - - -// My own strcmpi / strcasecmp -int strcmpcasenosensitive_internal (const char* fileName1,const char *fileName2) -{ - for (;;) - { - char c1=*(fileName1++); - char c2=*(fileName2++); - if ((c1>='a') && (c1<='z')) - c1 -= (char)0x20; - if ((c2>='a') && (c2<='z')) - c2 -= (char)0x20; - if (c1=='\0') - return ((c2=='\0') ? 0 : -1); - if (c2=='\0') - return 1; - if (c1c2) - return 1; - } -} - - - - -// -// Compare two filename (fileName1,fileName2). -// If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) -// If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi or strcasecmp) -// -int unzStringFileNameCompare (const char*fileName1,const char*fileName2,int iCaseSensitivity) -{ if (iCaseSensitivity==1) return strcmp(fileName1,fileName2); - else return strcmpcasenosensitive_internal(fileName1,fileName2); -} - -#define BUFREADCOMMENT (0x400) - - -// Locate the Central directory of a zipfile (at the end, just before -// the global comment) -uLong unzlocal_SearchCentralDir(LUFILE *fin) -{ if (lufseek(fin,0,SEEK_END) != 0) return 0; - uLong uSizeFile = luftell(fin); - - uLong uMaxBack=0xffff; // maximum size of global comment - if (uMaxBack>uSizeFile) uMaxBack = uSizeFile; - - unsigned char *buf = (unsigned char*)zmalloc(BUFREADCOMMENT+4); - if (buf==NULL) return 0; - uLong uPosFound=0; - - uLong uBackRead = 4; - while (uBackReaduMaxBack) uBackRead = uMaxBack; - else uBackRead+=BUFREADCOMMENT; - uReadPos = uSizeFile-uBackRead ; - uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); - if (lufseek(fin,uReadPos,SEEK_SET)!=0) break; - if (lufread(buf,(uInt)uReadSize,1,fin)!=1) break; - for (i=(int)uReadSize-3; (i--)>0;) - { if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) - { uPosFound = uReadPos+i; break; - } - } - if (uPosFound!=0) break; - } - if (buf) zfree(buf); - return uPosFound; -} - - -int unzGoToFirstFile (unzFile file); -int unzCloseCurrentFile (unzFile file); - -// Open a Zip file. -// If the zipfile cannot be opened (file don't exist or in not valid), return NULL. -// Otherwise, the return value is a unzFile Handle, usable with other unzip functions -unzFile unzOpenInternal(LUFILE *fin) -{ if (fin==NULL) return NULL; - if (unz_copyright[0]!=' ') {lufclose(fin); return NULL;} - - int err=UNZ_OK; - unz_s us; - uLong central_pos,uL; - central_pos = unzlocal_SearchCentralDir(fin); - if (central_pos==0) err=UNZ_ERRNO; - if (lufseek(fin,central_pos,SEEK_SET)!=0) err=UNZ_ERRNO; - // the signature, already checked - if (unzlocal_getLong(fin,&uL)!=UNZ_OK) err=UNZ_ERRNO; - // number of this disk - uLong number_disk; // number of the current dist, used for spanning ZIP, unsupported, always 0 - if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK) err=UNZ_ERRNO; - // number of the disk with the start of the central directory - uLong number_disk_with_CD; // number the the disk with central dir, used for spaning ZIP, unsupported, always 0 - if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK) err=UNZ_ERRNO; - // total number of entries in the central dir on this disk - if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK) err=UNZ_ERRNO; - // total number of entries in the central dir - uLong number_entry_CD; // total number of entries in the central dir (same than number_entry on nospan) - if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK) err=UNZ_ERRNO; - if ((number_entry_CD!=us.gi.number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) err=UNZ_BADZIPFILE; - // size of the central directory - if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK) err=UNZ_ERRNO; - // offset of start of central directory with respect to the starting disk number - if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK) err=UNZ_ERRNO; - // zipfile comment length - if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK) err=UNZ_ERRNO; - if ((central_pos+fin->initial_offsetinitial_offset - (us.offset_central_dir+us.size_central_dir); - us.central_pos = central_pos; - us.pfile_in_zip_read = NULL; - fin->initial_offset = 0; // since the zipfile itself is expected to handle this - - unz_s *s = (unz_s*)zmalloc(sizeof(unz_s)); - *s=us; - unzGoToFirstFile((unzFile)s); - return (unzFile)s; -} - - - -// Close a ZipFile opened with unzipOpen. -// If there is files inside the .Zip opened with unzipOpenCurrentFile (see later), -// these files MUST be closed with unzipCloseCurrentFile before call unzipClose. -// return UNZ_OK if there is no problem. -int unzClose (unzFile file) -{ - unz_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - - if (s->pfile_in_zip_read!=NULL) - unzCloseCurrentFile(file); - - lufclose(s->file); - if (s) zfree(s); // unused s=0; - return UNZ_OK; -} - - -// Write info about the ZipFile in the *pglobal_info structure. -// No preparation of the structure is needed -// return UNZ_OK if there is no problem. -int unzGetGlobalInfo (unzFile file,unz_global_info *pglobal_info) -{ - unz_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - *pglobal_info=s->gi; - return UNZ_OK; -} - - -// Translate date/time from Dos format to tm_unz (readable more easilty) -void unzlocal_DosDateToTmuDate (uLong ulDosDate, tm_unz* ptm) -{ - uLong uDate; - uDate = (uLong)(ulDosDate>>16); - ptm->tm_mday = (uInt)(uDate&0x1f) ; - ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; - ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; - - ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); - ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; - ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; -} - -// Get Info about the current file in the zipfile, with internal only info -int unzlocal_GetCurrentFileInfoInternal (unzFile file, - unz_file_info *pfile_info, - unz_file_info_internal - *pfile_info_internal, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize); - -int unzlocal_GetCurrentFileInfoInternal (unzFile file, unz_file_info *pfile_info, - unz_file_info_internal *pfile_info_internal, char *szFileName, - uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, - char *szComment, uLong commentBufferSize) -{ - unz_s* s; - unz_file_info file_info; - unz_file_info_internal file_info_internal; - int err=UNZ_OK; - uLong uMagic; - long lSeek=0; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (lufseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0) - err=UNZ_ERRNO; - - - // we check the magic - if (err==UNZ_OK) - if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x02014b50) - err=UNZ_BADZIPFILE; - - if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK) - err=UNZ_ERRNO; - - unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); - - if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK) - err=UNZ_ERRNO; - - lSeek+=file_info.size_filename; - if ((err==UNZ_OK) && (szFileName!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_filename0) && (fileNameBufferSize>0)) - if (lufread(szFileName,(uInt)uSizeRead,1,s->file)!=1) - err=UNZ_ERRNO; - lSeek -= uSizeRead; - } - - - if ((err==UNZ_OK) && (extraField!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_file_extrafile,lSeek,SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) - if (lufread(extraField,(uInt)uSizeRead,1,s->file)!=1) - err=UNZ_ERRNO; - lSeek += file_info.size_file_extra - uSizeRead; - } - else - lSeek+=file_info.size_file_extra; - - - if ((err==UNZ_OK) && (szComment!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_file_commentfile,lSeek,SEEK_CUR)==0) - {} // unused lSeek=0; - else - err=UNZ_ERRNO; - if ((file_info.size_file_comment>0) && (commentBufferSize>0)) - if (lufread(szComment,(uInt)uSizeRead,1,s->file)!=1) - err=UNZ_ERRNO; - //unused lSeek+=file_info.size_file_comment - uSizeRead; - } - else {} //unused lSeek+=file_info.size_file_comment; - - if ((err==UNZ_OK) && (pfile_info!=NULL)) - *pfile_info=file_info; - - if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) - *pfile_info_internal=file_info_internal; - - return err; -} - - - -// Write info about the ZipFile in the *pglobal_info structure. -// No preparation of the structure is needed -// return UNZ_OK if there is no problem. -int unzGetCurrentFileInfo (unzFile file, unz_file_info *pfile_info, - char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, - char *szComment, uLong commentBufferSize) -{ return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,szFileName,fileNameBufferSize, - extraField,extraFieldBufferSize, szComment,commentBufferSize); -} - - -// Set the current file of the zipfile to the first file. -// return UNZ_OK if there is no problem -int unzGoToFirstFile (unzFile file) -{ - int err; - unz_s* s; - if (file==NULL) return UNZ_PARAMERROR; - s=(unz_s*)file; - s->pos_in_central_dir=s->offset_central_dir; - s->num_file=0; - err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - - -// Set the current file of the zipfile to the next file. -// return UNZ_OK if there is no problem -// return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. -int unzGoToNextFile (unzFile file) -{ - unz_s* s; - int err; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - if (s->num_file+1==s->gi.number_entry) - return UNZ_END_OF_LIST_OF_FILE; - - s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + - s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; - s->num_file++; - err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - - -// Try locate the file szFileName in the zipfile. -// For the iCaseSensitivity signification, see unzStringFileNameCompare -// return value : -// UNZ_OK if the file is found. It becomes the current file. -// UNZ_END_OF_LIST_OF_FILE if the file is not found -int unzLocateFile (unzFile file, const TCHAR *szFileName, int iCaseSensitivity) -{ - unz_s* s; - int err; - - uLong num_fileSaved; - uLong pos_in_central_dirSaved; - - if (file==NULL) - return UNZ_PARAMERROR; - - if (_tcslen(szFileName)>=UNZ_MAXFILENAMEINZIP) - return UNZ_PARAMERROR; - - char szFileNameA[MAX_PATH]; - -#ifdef _UNICODE - GetAnsiFileName(szFileName, szFileNameA, MAX_PATH-1); -#else - strcpy(szFileNameA, szFileName); -#endif - - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - - num_fileSaved = s->num_file; - pos_in_central_dirSaved = s->pos_in_central_dir; - - err = unzGoToFirstFile(file); - - while (err == UNZ_OK) - { - char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; - unzGetCurrentFileInfo(file,NULL, - szCurrentFileName,sizeof(szCurrentFileName)-1, - NULL,0,NULL,0); - if (unzStringFileNameCompare(szCurrentFileName,szFileNameA,iCaseSensitivity)==0) - return UNZ_OK; - err = unzGoToNextFile(file); - } - - s->num_file = num_fileSaved ; - s->pos_in_central_dir = pos_in_central_dirSaved ; - return err; -} - - -// Read the local header of the current zipfile -// Check the coherency of the local header and info in the end of central -// directory about this file -// store in *piSizeVar the size of extra info in local header -// (filename and size of extra field data) -int unzlocal_CheckCurrentFileCoherencyHeader (unz_s *s,uInt *piSizeVar, - uLong *poffset_local_extrafield, uInt *psize_local_extrafield) -{ - uLong uMagic,uData,uFlags; - uLong size_filename; - uLong size_extra_field; - int err=UNZ_OK; - - *piSizeVar = 0; - *poffset_local_extrafield = 0; - *psize_local_extrafield = 0; - - if (lufseek(s->file,s->cur_file_info_internal.offset_curfile + s->byte_before_the_zipfile,SEEK_SET)!=0) - return UNZ_ERRNO; - - - if (err==UNZ_OK) - if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x04034b50) - err=UNZ_BADZIPFILE; - - if (unzlocal_getShort(s->file,&uData) != UNZ_OK) - err=UNZ_ERRNO; -// else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) -// err=UNZ_BADZIPFILE; - if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&uData) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) - err=UNZ_BADZIPFILE; - - if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && - (s->cur_file_info.compression_method!=Z_DEFLATED)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(s->file,&uData) != UNZ_OK) // date/time - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&uData) != UNZ_OK) // crc - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(s->file,&uData) != UNZ_OK) // size compr - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(s->file,&uData) != UNZ_OK) // size uncompr - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - - if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) - err=UNZ_BADZIPFILE; - - *piSizeVar += (uInt)size_filename; - - if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK) - err=UNZ_ERRNO; - *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + - SIZEZIPLOCALHEADER + size_filename; - *psize_local_extrafield = (uInt)size_extra_field; - - *piSizeVar += (uInt)size_extra_field; - - return err; -} - - - - - -// Open for reading data the current file in the zipfile. -// If there is no error and the file is opened, the return value is UNZ_OK. -int unzOpenCurrentFile (unzFile file) -{ - int err; - int Store; - uInt iSizeVar; - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - uLong offset_local_extrafield; // offset of the local extra field - uInt size_local_extrafield; // size of the local extra field - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_PARAMERROR; - - if (s->pfile_in_zip_read != NULL) - unzCloseCurrentFile(file); - - if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, - &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) - return UNZ_BADZIPFILE; - - pfile_in_zip_read_info = (file_in_zip_read_info_s*)zmalloc(sizeof(file_in_zip_read_info_s)); - if (pfile_in_zip_read_info==NULL) - return UNZ_INTERNALERROR; - - pfile_in_zip_read_info->read_buffer=(char*)zmalloc(UNZ_BUFSIZE); - pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; - pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; - pfile_in_zip_read_info->pos_local_extrafield=0; - - if (pfile_in_zip_read_info->read_buffer==NULL) - { - if (pfile_in_zip_read_info!=0) zfree(pfile_in_zip_read_info); //unused pfile_in_zip_read_info=0; - return UNZ_INTERNALERROR; - } - - pfile_in_zip_read_info->stream_initialised=0; - - if ((s->cur_file_info.compression_method!=0) && (s->cur_file_info.compression_method!=Z_DEFLATED)) - { // unused err=UNZ_BADZIPFILE; - } - Store = s->cur_file_info.compression_method==0; - - pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; - pfile_in_zip_read_info->crc32=0; - pfile_in_zip_read_info->compression_method = - s->cur_file_info.compression_method; - pfile_in_zip_read_info->file=s->file; - pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; - - pfile_in_zip_read_info->stream.total_out = 0; - - if (!Store) - { - pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; - pfile_in_zip_read_info->stream.zfree = (free_func)0; - pfile_in_zip_read_info->stream.opaque = (voidpf)0; - - err=inflateInit2(&pfile_in_zip_read_info->stream); - if (err == Z_OK) - pfile_in_zip_read_info->stream_initialised=1; - // windowBits is passed < 0 to tell that there is no zlib header. - // Note that in this case inflate *requires* an extra "dummy" byte - // after the compressed stream in order to complete decompression and - // return Z_STREAM_END. - // In unzip, i don't wait absolutely Z_STREAM_END because I known the - // size of both compressed and uncompressed data - } - pfile_in_zip_read_info->rest_read_compressed = - s->cur_file_info.compressed_size ; - pfile_in_zip_read_info->rest_read_uncompressed = - s->cur_file_info.uncompressed_size ; - - - pfile_in_zip_read_info->pos_in_zipfile = - s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + - iSizeVar; - - pfile_in_zip_read_info->stream.avail_in = (uInt)0; - - - s->pfile_in_zip_read = pfile_in_zip_read_info; - return UNZ_OK; -} - - -// Read bytes from the current file. -// buf contain buffer where data must be copied -// len the size of buf. -// return the number of byte copied if somes bytes are copied -// return 0 if the end of file was reached -// return <0 with error code if there is an error -// (UNZ_ERRNO for IO error, or zLib error for uncompress error) -int unzReadCurrentFile (unzFile file, voidp buf, unsigned len) -{ int err=UNZ_OK; - uInt iRead = 0; - - unz_s *s = (unz_s*)file; - if (s==NULL) return UNZ_PARAMERROR; - - file_in_zip_read_info_s* pfile_in_zip_read_info = s->pfile_in_zip_read; - if (pfile_in_zip_read_info==NULL) return UNZ_PARAMERROR; - if ((pfile_in_zip_read_info->read_buffer == NULL)) return UNZ_END_OF_LIST_OF_FILE; - if (len==0) return 0; - - pfile_in_zip_read_info->stream.next_out = (Byte*)buf; - pfile_in_zip_read_info->stream.avail_out = (uInt)len; - - if (len>pfile_in_zip_read_info->rest_read_uncompressed) - { pfile_in_zip_read_info->stream.avail_out = (uInt)pfile_in_zip_read_info->rest_read_uncompressed; - } - - while (pfile_in_zip_read_info->stream.avail_out>0) - { if ((pfile_in_zip_read_info->stream.avail_in==0) && (pfile_in_zip_read_info->rest_read_compressed>0)) - { uInt uReadThis = UNZ_BUFSIZE; - if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; - if (uReadThis == 0) return UNZ_EOF; - if (lufseek(pfile_in_zip_read_info->file, pfile_in_zip_read_info->pos_in_zipfile + pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0) return UNZ_ERRNO; - if (lufread(pfile_in_zip_read_info->read_buffer,uReadThis,1,pfile_in_zip_read_info->file)!=1) return UNZ_ERRNO; - pfile_in_zip_read_info->pos_in_zipfile += uReadThis; - pfile_in_zip_read_info->rest_read_compressed-=uReadThis; - pfile_in_zip_read_info->stream.next_in = (Byte*)pfile_in_zip_read_info->read_buffer; - pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; - } - - if (pfile_in_zip_read_info->compression_method==0) - { uInt uDoCopy,i ; - if (pfile_in_zip_read_info->stream.avail_out < pfile_in_zip_read_info->stream.avail_in) - { uDoCopy = pfile_in_zip_read_info->stream.avail_out ; - } - else - { uDoCopy = pfile_in_zip_read_info->stream.avail_in ; - } - for (i=0;istream.next_out+i) = *(pfile_in_zip_read_info->stream.next_in+i); - } - pfile_in_zip_read_info->crc32 = ucrc32(pfile_in_zip_read_info->crc32,pfile_in_zip_read_info->stream.next_out,uDoCopy); - pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; - pfile_in_zip_read_info->stream.avail_in -= uDoCopy; - pfile_in_zip_read_info->stream.avail_out -= uDoCopy; - pfile_in_zip_read_info->stream.next_out += uDoCopy; - pfile_in_zip_read_info->stream.next_in += uDoCopy; - pfile_in_zip_read_info->stream.total_out += uDoCopy; - iRead += uDoCopy; - } - else - { uLong uTotalOutBefore,uTotalOutAfter; - const Byte *bufBefore; - uLong uOutThis; - int flush=Z_SYNC_FLUSH; - uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; - bufBefore = pfile_in_zip_read_info->stream.next_out; - err=inflate(&pfile_in_zip_read_info->stream,flush); - uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; - uOutThis = uTotalOutAfter-uTotalOutBefore; - pfile_in_zip_read_info->crc32 = ucrc32(pfile_in_zip_read_info->crc32,bufBefore,(uInt)(uOutThis)); - pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis; - iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); - if (err==Z_STREAM_END) return (iRead==0) ? UNZ_EOF : iRead; - if (err!=Z_OK) break; - } - } - - if (err==Z_OK) return iRead; - return err; -} - - -// Give the current position in uncompressed data -z_off_t unztell (unzFile file) -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - return (z_off_t)pfile_in_zip_read_info->stream.total_out; -} - - -// return 1 if the end of file was reached, 0 elsewhere -int unzeof (unzFile file) -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - if (pfile_in_zip_read_info->rest_read_uncompressed == 0) - return 1; - else - return 0; -} - - - -// Read extra field from the current file (opened by unzOpenCurrentFile) -// This is the local-header version of the extra field (sometimes, there is -// more info in the local-header version than in the central-header) -// if buf==NULL, it return the size of the local extra field that can be read -// if buf!=NULL, len is the size of the buffer, the extra header is copied in buf. -// the return value is the number of bytes copied in buf, or (if <0) the error code -int unzGetLocalExtrafield (unzFile file,voidp buf,unsigned len) -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - uInt read_now; - uLong size_to_read; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - size_to_read = (pfile_in_zip_read_info->size_local_extrafield - - pfile_in_zip_read_info->pos_local_extrafield); - - if (buf==NULL) - return (int)size_to_read; - - if (len>size_to_read) - read_now = (uInt)size_to_read; - else - read_now = (uInt)len ; - - if (read_now==0) - return 0; - - if (lufseek(pfile_in_zip_read_info->file, pfile_in_zip_read_info->offset_local_extrafield + pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0) - return UNZ_ERRNO; - - if (lufread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1) - return UNZ_ERRNO; - - return (int)read_now; -} - -// Close the file in zip opened with unzipOpenCurrentFile -// Return UNZ_CRCERROR if all the file was read but the CRC is not good -int unzCloseCurrentFile (unzFile file) -{ - int err=UNZ_OK; - - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - - if (pfile_in_zip_read_info->rest_read_uncompressed == 0) - { - if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) - err=UNZ_CRCERROR; - } - - - if (pfile_in_zip_read_info->read_buffer!=0) - { void *buf = pfile_in_zip_read_info->read_buffer; - zfree(buf); - pfile_in_zip_read_info->read_buffer=0; - } - pfile_in_zip_read_info->read_buffer = NULL; - if (pfile_in_zip_read_info->stream_initialised) - inflateEnd(&pfile_in_zip_read_info->stream); - - pfile_in_zip_read_info->stream_initialised = 0; - if (pfile_in_zip_read_info!=0) zfree(pfile_in_zip_read_info); // unused pfile_in_zip_read_info=0; - - s->pfile_in_zip_read=NULL; - - return err; -} - - -// Get the global comment string of the ZipFile, in the szComment buffer. -// uSizeBuf is the size of the szComment buffer. -// return the number of byte copied or an error code <0 -int unzGetGlobalComment (unzFile file, char *szComment, uLong uSizeBuf) -{ //int err=UNZ_OK; - unz_s* s; - uLong uReadThis ; - if (file==NULL) return UNZ_PARAMERROR; - s=(unz_s*)file; - uReadThis = uSizeBuf; - if (uReadThis>s->gi.size_comment) uReadThis = s->gi.size_comment; - if (lufseek(s->file,s->central_pos+22,SEEK_SET)!=0) return UNZ_ERRNO; - if (uReadThis>0) - { *szComment='\0'; - if (lufread(szComment,(uInt)uReadThis,1,s->file)!=1) return UNZ_ERRNO; - } - if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) *(szComment+s->gi.size_comment)='\0'; - return (int)uReadThis; -} - - - - - -int unzOpenCurrentFile (unzFile file); -int unzReadCurrentFile (unzFile file, void *buf, unsigned len); -int unzCloseCurrentFile (unzFile file); - - -FILETIME timet2filetime(const time_t timer) -{ struct tm *tm = gmtime(&timer); - SYSTEMTIME st; - st.wYear = (WORD)(tm->tm_year+1900); - st.wMonth = (WORD)(tm->tm_mon+1); - st.wDay = (WORD)(tm->tm_mday); - st.wHour = (WORD)(tm->tm_hour); - st.wMinute = (WORD)(tm->tm_min); - st.wSecond = (WORD)(tm->tm_sec); - st.wMilliseconds=0; - FILETIME ft; - SystemTimeToFileTime(&st,&ft); - return ft; -} - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -class TUnzip -{ public: - TUnzip() : uf(0), currentfile(-1), czei(-1) {} - - unzFile uf; int currentfile; ZIPENTRY cze; int czei; - TCHAR rootdir[MAX_PATH]; - - ZRESULT Open(void *z,unsigned int len,DWORD flags); - ZRESULT Get(int index,ZIPENTRY *ze); - ZRESULT Find(const TCHAR *name,bool ic,int *index,ZIPENTRY *ze); - ZRESULT Unzip(int index,void *dst,unsigned int len,DWORD flags); - ZRESULT Close(); -}; - - -ZRESULT TUnzip::Open(void *z,unsigned int len,DWORD flags) -{ - if (uf!=0 || currentfile!=-1) - return ZR_NOTINITED; - GetCurrentDirectory(MAX_PATH,rootdir); - _tcscat(rootdir,_T("\\")); - if (flags==ZIP_HANDLE) - { - DWORD type = GetFileType(z); - if (type!=FILE_TYPE_DISK) - return ZR_SEEK; - } - ZRESULT e; - LUFILE *f = lufopen(z,len,flags,&e); - if (f==NULL) - return e; - uf = unzOpenInternal(f); - return ZR_OK; -} - -ZRESULT TUnzip::Get(int index,ZIPENTRY *ze) -{ if (index<-1 || index>=(int)uf->gi.number_entry) - return ZR_ARGS; - if (currentfile!=-1) - unzCloseCurrentFile(uf); - currentfile=-1; - if (index==czei && index!=-1) {memcpy(ze,&cze,sizeof(ZIPENTRY)); return ZR_OK;} - if (index==-1) - { ze->index = uf->gi.number_entry; - ze->name[0]=0; - ze->attr=0; - ze->atime.dwLowDateTime=0; ze->atime.dwHighDateTime=0; - ze->ctime.dwLowDateTime=0; ze->ctime.dwHighDateTime=0; - ze->mtime.dwLowDateTime=0; ze->mtime.dwHighDateTime=0; - ze->comp_size=0; - ze->unc_size=0; - return ZR_OK; - } - if (index<(int)uf->num_file) unzGoToFirstFile(uf); - while ((int)uf->num_filefile,offset,SEEK_SET)!=0) return ZR_READ; - char *extra = new char[extralen]; - if (lufread(extra,1,(uInt)extralen,uf->file)!=extralen) {delete[] extra; return ZR_READ;} - // - ze->index=uf->num_file; - strcpy(ze->name,fn); - // zip has an 'attribute' 32bit value. Its lower half is windows stuff - // its upper half is standard unix attr. - unsigned long a = ufi.external_fa; - bool uisdir = (a&0x40000000)!=0; - //bool uwriteable= (a&0x08000000)!=0; - bool uwriteable= (a&0x00800000)!=0; // ***hd*** - //bool ureadable= (a&0x01000000)!=0; - //bool uexecutable=(a&0x00400000)!=0; - bool wreadonly= (a&0x00000001)!=0; - bool whidden= (a&0x00000002)!=0; - bool wsystem= (a&0x00000004)!=0; - bool wisdir= (a&0x00000010)!=0; - bool warchive= (a&0x00000020)!=0; - ze->attr=FILE_ATTRIBUTE_NORMAL; - if (uisdir || wisdir) ze->attr |= FILE_ATTRIBUTE_DIRECTORY; - if (warchive) ze->attr|=FILE_ATTRIBUTE_ARCHIVE; - if (whidden) ze->attr|=FILE_ATTRIBUTE_HIDDEN; - if (!uwriteable||wreadonly) ze->attr|=FILE_ATTRIBUTE_READONLY; - if (wsystem) ze->attr|=FILE_ATTRIBUTE_SYSTEM; - ze->comp_size = ufi.compressed_size; - ze->unc_size = ufi.uncompressed_size; - // - WORD dostime = (WORD)(ufi.dosDate&0xFFFF); - WORD dosdate = (WORD)((ufi.dosDate>>16)&0xFFFF); - FILETIME ft; - DosDateTimeToFileTime(dosdate,dostime,&ft); - ze->atime=ft; ze->ctime=ft; ze->mtime=ft; - // the zip will always have at least that dostime. But if it also has - // an extra header, then we'll instead get the info from that. - unsigned int epos=0; - while (epos+4mtime = timet2filetime(mtime); - } - if (hasatime) - { - __time32_t atime = *(__time32_t*)(extra+epos); epos+=4; - ze->atime = timet2filetime(atime); - } - if (hasctime) - { - __time32_t ctime = *(__time32_t*)(extra+epos); - ze->ctime = timet2filetime(ctime); - } - break; - } - // - if (extra!=0) delete[] extra; - memcpy(&cze,ze,sizeof(ZIPENTRY)); czei=index; - return ZR_OK; -} - -ZRESULT TUnzip::Find(const TCHAR *name, bool ic, int *index, ZIPENTRY *ze) -{ - int res = unzLocateFile(uf,name,ic?CASE_INSENSITIVE:CASE_SENSITIVE); - if (res!=UNZ_OK) - { - if (index!=0) - *index=-1; - if (ze!=NULL) - { - ZeroMemory(ze,sizeof(ZIPENTRY)); ze->index=-1; - } - return ZR_NOTFOUND; - } - if (currentfile!=-1) - unzCloseCurrentFile(uf); currentfile=-1; - int i = (int)uf->num_file; - if (index!=NULL) - *index=i; - if (ze!=NULL) - { - ZRESULT zres = Get(i,ze); - if (zres!=ZR_OK) - return zres; - } - return ZR_OK; -} - -void EnsureDirectory(const TCHAR *rootdir, const TCHAR *dir) -{ - if (dir==NULL || dir[0] == _T('\0')) - return; - const TCHAR *lastslash = dir, *c = lastslash; - while (*c != _T('\0')) - { - if (*c==_T('/') || *c==_T('\\')) - lastslash=c; - c++; - } - const TCHAR *name=lastslash; - if (lastslash!=dir) - { - TCHAR tmp[MAX_PATH]; - _tcsncpy(tmp, dir, lastslash-dir); - tmp[lastslash-dir] = _T('\0'); - EnsureDirectory(rootdir,tmp); - name++; - } - TCHAR cd[MAX_PATH]; - _tcscpy(cd,rootdir); - _tcscat(cd,name); - CreateDirectory(cd,NULL); -} - -ZRESULT TUnzip::Unzip(int index,void *dst,unsigned int len,DWORD flags) -{ - if (flags!=ZIP_MEMORY && flags!=ZIP_FILENAME && flags!=ZIP_HANDLE) - return ZR_ARGS; - if (flags==ZIP_MEMORY) - { - if (index!=currentfile) - { - if (currentfile!=-1) - unzCloseCurrentFile(uf); - currentfile=-1; - if (index>=(int)uf->gi.number_entry) - return ZR_ARGS; - if (index<(int)uf->num_file) - unzGoToFirstFile(uf); - while ((int)uf->num_file0) - return ZR_MORE; - unzCloseCurrentFile(uf); - currentfile=-1; - if (res==0) - return ZR_OK; - else - return ZR_FLATE; - } - - // otherwise we're writing to a handle or a file - if (currentfile!=-1) - unzCloseCurrentFile(uf); - currentfile=-1; - if (index >= (int)uf->gi.number_entry) - return ZR_ARGS; - if (index < (int)uf->num_file) - unzGoToFirstFile(uf); - while ((int)uf->num_filelen) n=len-1; - strncpy(buf,msg,n); buf[n]=0; - return mlen; -} - - -typedef struct -{ DWORD flag; - TUnzip *unz; -} TUnzipHandleData; - -HZIP OpenZipU(void *z,unsigned int len,DWORD flags) -{ - TUnzip *unz = new TUnzip(); - lasterrorU = unz->Open(z,len,flags); - if (lasterrorU!=ZR_OK) - { - delete unz; - return 0; - } - TUnzipHandleData *han = new TUnzipHandleData; - han->flag=1; - han->unz=unz; - return (HZIP)han; -} - -ZRESULT GetZipItemA(HZIP hz, int index, ZIPENTRY *ze) -{ - if (hz==0) - { - lasterrorU=ZR_ARGS; - return ZR_ARGS; - } - TUnzipHandleData *han = (TUnzipHandleData*)hz; - if (han->flag!=1) - { - lasterrorU=ZR_ZMODE; - return ZR_ZMODE; - } - TUnzip *unz = han->unz; - lasterrorU = unz->Get(index,ze); - return lasterrorU; -} - -ZRESULT GetZipItemW(HZIP hz, int index, ZIPENTRYW *zew) -{ - if (hz==0) - { - lasterrorU=ZR_ARGS; - return ZR_ARGS; - } - TUnzipHandleData *han = (TUnzipHandleData*)hz; - if (han->flag!=1) - { - lasterrorU=ZR_ZMODE; - return ZR_ZMODE; - } - TUnzip *unz = han->unz; - ZIPENTRY ze; - lasterrorU = unz->Get(index,&ze); - if (lasterrorU == ZR_OK) - { - zew->index = ze.index; - zew->attr = ze.attr; - zew->atime = ze.atime; - zew->ctime = ze.ctime; - zew->mtime = ze.mtime; - zew->comp_size = ze.comp_size; - zew->unc_size = ze.unc_size; -#ifdef _UNICODE - GetUnicodeFileName(ze.name, zew->name, MAX_PATH-1); -#else - strcpy(zew->name, ze.name); -#endif - } - return lasterrorU; -} - -ZRESULT FindZipItemA(HZIP hz, const TCHAR *name, bool ic, int *index, ZIPENTRY *ze) -{ - if (hz==0) - { - lasterrorU=ZR_ARGS; - return ZR_ARGS; - } - TUnzipHandleData *han = (TUnzipHandleData*)hz; - if (han->flag!=1) - { - lasterrorU=ZR_ZMODE; - return ZR_ZMODE; - } - TUnzip *unz = han->unz; - lasterrorU = unz->Find(name,ic,index,ze); - return lasterrorU; -} - -ZRESULT FindZipItemW(HZIP hz, const TCHAR *name, bool ic, int *index, ZIPENTRYW *zew) -{ - if (hz==0) - { - lasterrorU=ZR_ARGS; - return ZR_ARGS; - } - TUnzipHandleData *han = (TUnzipHandleData*)hz; - if (han->flag!=1) - { - lasterrorU=ZR_ZMODE; - return ZR_ZMODE; - } - TUnzip *unz = han->unz; - ZIPENTRY ze; - lasterrorU = unz->Find(name,ic,index,&ze); - if (lasterrorU == ZR_OK) - { - zew->index = ze.index; - zew->attr = ze.attr; - zew->atime = ze.atime; - zew->ctime = ze.ctime; - zew->mtime = ze.mtime; - zew->comp_size = ze.comp_size; - zew->unc_size = ze.unc_size; -#ifdef _UNICODE - GetUnicodeFileName(ze.name, zew->name, MAX_PATH-1); -#else - strcpy(zew->name, ze.name); -#endif - } - - return lasterrorU; -} - -ZRESULT UnzipItem(HZIP hz, int index, void *dst, unsigned int len, DWORD flags) -{ - if (hz==0) - { - lasterrorU=ZR_ARGS; - return ZR_ARGS; - } - TUnzipHandleData *han = (TUnzipHandleData*)hz; - if (han->flag!=1) - { - lasterrorU=ZR_ZMODE; - return ZR_ZMODE; - } - TUnzip *unz = han->unz; - lasterrorU = unz->Unzip(index,dst,len,flags); - return lasterrorU; -} - -ZRESULT CloseZipU(HZIP hz) -{ if (hz==0) {lasterrorU=ZR_ARGS;return ZR_ARGS;} - TUnzipHandleData *han = (TUnzipHandleData*)hz; - if (han->flag!=1) {lasterrorU=ZR_ZMODE;return ZR_ZMODE;} - TUnzip *unz = han->unz; - lasterrorU = unz->Close(); - delete unz; - delete han; - return lasterrorU; -} - -bool IsZipHandleU(HZIP hz) -{ if (hz==0) return true; - TUnzipHandleData *han = (TUnzipHandleData*)hz; - return (han->flag==1); -} - - diff --git a/public/XZip.cpp b/public/XZip.cpp deleted file mode 100644 index a0bdefd58..000000000 --- a/public/XZip.cpp +++ /dev/null @@ -1,2945 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -// XZip.cpp Version 1.1 -// -// Authors: Mark Adler et al. (see below) -// -// Modified by: Lucian Wischik -// lu@wischik.com -// -// Version 1.0 - Turned C files into just a single CPP file -// - Made them compile cleanly as C++ files -// - Gave them simpler APIs -// - Added the ability to zip/unzip directly in memory without -// any intermediate files -// -// Modified by: Hans Dietrich -// hdietrich2@hotmail.com -// -// Version 1.1: - Added Unicode support to CreateZip() and ZipAdd() -// - Changed file names to avoid conflicts with Lucian's files -// -/////////////////////////////////////////////////////////////////////////////// -// -// Lucian Wischik's comments: -// -------------------------- -// THIS FILE is almost entirely based upon code by Info-ZIP. -// It has been modified by Lucian Wischik. -// The original code may be found at http://www.info-zip.org -// The original copyright text follows. -// -/////////////////////////////////////////////////////////////////////////////// -// -// Original authors' comments: -// --------------------------- -// This is version 2002-Feb-16 of the Info-ZIP copyright and license. The -// definitive version of this document should be available at -// ftp://ftp.info-zip.org/pub/infozip/license.html indefinitely. -// -// Copyright (c) 1990-2002 Info-ZIP. All rights reserved. -// -// For the purposes of this copyright and license, "Info-ZIP" is defined as -// the following set of individuals: -// -// Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois, -// Jean-loup Gailly, Hunter Goatley, Ian Gorman, Chris Herborth, Dirk Haase, -// Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz, -// David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko, -// Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs, -// Kai Uwe Rommel, Steve Salisbury, Dave Smith, Christian Spieler, -// Antoine Verheijen, Paul von Behren, Rich Wales, Mike White -// -// This software is provided "as is", without warranty of any kind, express -// or implied. In no event shall Info-ZIP or its contributors be held liable -// for any direct, indirect, incidental, special or consequential damages -// arising out of the use of or inability to use this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. Redistributions of source code must retain the above copyright notice, -// definition, disclaimer, and this list of conditions. -// -// 2. Redistributions in binary form (compiled executables) must reproduce -// the above copyright notice, definition, disclaimer, and this list of -// conditions in documentation and/or other materials provided with the -// distribution. The sole exception to this condition is redistribution -// of a standard UnZipSFX binary as part of a self-extracting archive; -// that is permitted without inclusion of this license, as long as the -// normal UnZipSFX banner has not been removed from the binary or disabled. -// -// 3. Altered versions--including, but not limited to, ports to new -// operating systems, existing ports with new graphical interfaces, and -// dynamic, shared, or static library versions--must be plainly marked -// as such and must not be misrepresented as being the original source. -// Such altered versions also must not be misrepresented as being -// Info-ZIP releases--including, but not limited to, labeling of the -// altered versions with the names "Info-ZIP" (or any variation thereof, -// including, but not limited to, different capitalizations), -// "Pocket UnZip", "WiZ" or "MacZip" without the explicit permission of -// Info-ZIP. Such altered versions are further prohibited from -// misrepresentative use of the Zip-Bugs or Info-ZIP e-mail addresses or -// of the Info-ZIP URL(s). -// -// 4. Info-ZIP retains the right to use the names "Info-ZIP", "Zip", "UnZip", -// "UnZipSFX", "WiZ", "Pocket UnZip", "Pocket Zip", and "MacZip" for its -// own source and binary releases. -// -/////////////////////////////////////////////////////////////////////////////// - -#if defined( PROTECTED_THINGS_ENABLE ) -#undef PROTECTED_THINGS_ENABLE // from protected_things.h -#endif - -#include "tier0/platform.h" - -#ifdef IS_WINDOWS_PC -#define STRICT -#define WIN32_LEAN_AND_MEAN -#include -#endif -#include -#include "zip/XZip.h" -#if defined( _X360 ) -#include "xbox/xbox_win32stubs.h" -#endif - -#include "tier1/strtools.h" - -typedef unsigned char uch; // unsigned 8-bit value -typedef unsigned short ush; // unsigned 16-bit value -typedef unsigned long ulg; // unsigned 32-bit value -typedef size_t extent; // file size -typedef unsigned Pos; // must be at least 32 bits -typedef unsigned IPos; // A Pos is an index in the character window. Pos is used only for parameter passing - -#ifndef EOF -#define EOF (-1) -#endif - - -// Error return values. The values 0..4 and 12..18 follow the conventions -// of PKZIP. The values 4..10 are all assigned to "insufficient memory" -// by PKZIP, so the codes 5..10 are used here for other purposes. -#define ZE_MISS -1 // used by procname(), zipbare() -#define ZE_OK 0 // success -#define ZE_EOF 2 // unexpected end of zip file -#define ZE_FORM 3 // zip file structure error -#define ZE_MEM 4 // out of memory -#define ZE_LOGIC 5 // internal logic error -#define ZE_BIG 6 // entry too large to split -#define ZE_NOTE 7 // invalid comment format -#define ZE_TEST 8 // zip test (-T) failed or out of memory -#define ZE_ABORT 9 // user interrupt or termination -#define ZE_TEMP 10 // error using a temp file -#define ZE_READ 11 // read or seek error -#define ZE_NONE 12 // nothing to do -#define ZE_NAME 13 // missing or empty zip file -#define ZE_WRITE 14 // error writing to a file -#define ZE_CREAT 15 // couldn't open to write -#define ZE_PARMS 16 // bad command line -#define ZE_OPEN 18 // could not open a specified file to read -#define ZE_MAXERR 18 // the highest error number - - -// internal file attribute -#define UNKNOWN (-1) -#define BINARY 0 -#define ASCII 1 - -#define BEST -1 // Use best method (deflation or store) -#define STORE 0 // Store method -#define DEFLATE 8 // Deflation method - -#define CRCVAL_INITIAL 0L - -// MSDOS file or directory attributes -#define MSDOS_HIDDEN_ATTR 0x02 -#define MSDOS_DIR_ATTR 0x10 - -// Lengths of headers after signatures in bytes -#define LOCHEAD 26 -#define CENHEAD 42 -#define ENDHEAD 18 - -// Definitions for extra field handling: -#define EB_HEADSIZE 4 /* length of a extra field block header */ -#define EB_LEN 2 /* offset of data length field in header */ -#define EB_UT_MINLEN 1 /* minimal UT field contains Flags byte */ -#define EB_UT_FLAGS 0 /* byte offset of Flags field */ -#define EB_UT_TIME1 1 /* byte offset of 1st time value */ -#define EB_UT_FL_MTIME (1 << 0) /* mtime present */ -#define EB_UT_FL_ATIME (1 << 1) /* atime present */ -#define EB_UT_FL_CTIME (1 << 2) /* ctime present */ -#define EB_UT_LEN(n) (EB_UT_MINLEN + 4 * (n)) -#define EB_L_UT_SIZE (EB_HEADSIZE + EB_UT_LEN(3)) -#define EB_C_UT_SIZE (EB_HEADSIZE + EB_UT_LEN(1)) - - -// Macros for writing machine integers to little-endian format -#define PUTSH(a,f) {char _putsh_c=(char)((a)&0xff); wfunc(param,&_putsh_c,1); _putsh_c=(char)((a)>>8); wfunc(param,&_putsh_c,1);} -#define PUTLG(a,f) {PUTSH((a) & 0xffff,(f)) PUTSH((a) >> 16,(f))} - - -// -- Structure of a ZIP file -- -// Signatures for zip file information headers -#define LOCSIG 0x04034b50L -#define CENSIG 0x02014b50L -#define ENDSIG 0x06054b50L -#define EXTLOCSIG 0x08074b50L - - -#define MIN_MATCH 3 -#define MAX_MATCH 258 -// The minimum and maximum match lengths - - -#define WSIZE (0x8000) -// Maximum window size = 32K. If you are really short of memory, compile -// with a smaller WSIZE but this reduces the compression ratio for files -// of size > WSIZE. WSIZE must be a power of two in the current implementation. -// - -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -// Minimum amount of lookahead, except at the end of the input file. -// See deflate.c for comments about the MIN_MATCH+1. -// - -#define MAX_DIST (WSIZE-MIN_LOOKAHEAD) -// In order to simplify the code, particularly on 16 bit machines, match -// distances are limited to MAX_DIST instead of WSIZE. -// - - - - - -// =========================================================================== -// Constants -// - -#define MAX_BITS 15 -// All codes must not exceed MAX_BITS bits - -#define MAX_BL_BITS 7 -// Bit length codes must not exceed MAX_BL_BITS bits - -#define LENGTH_CODES 29 -// number of length codes, not counting the special END_BLOCK code - -#define LITERALS 256 -// number of literal bytes 0..255 - -#define END_BLOCK 256 -// end of block literal code - -#define L_CODES (LITERALS+1+LENGTH_CODES) -// number of Literal or Length codes, including the END_BLOCK code - -#define D_CODES 30 -// number of distance codes - -#define BL_CODES 19 -// number of codes used to transfer the bit lengths - - -#define STORED_BLOCK 0 -#define STATIC_TREES 1 -#define DYN_TREES 2 -// The three kinds of block type - -#define LIT_BUFSIZE 0x8000 -#define DIST_BUFSIZE LIT_BUFSIZE -// Sizes of match buffers for literals/lengths and distances. There are -// 4 reasons for limiting LIT_BUFSIZE to 64K: -// - frequencies can be kept in 16 bit counters -// - if compression is not successful for the first block, all input data is -// still in the window so we can still emit a stored block even when input -// comes from standard input. (This can also be done for all blocks if -// LIT_BUFSIZE is not greater than 32K.) -// - if compression is not successful for a file smaller than 64K, we can -// even emit a stored file instead of a stored block (saving 5 bytes). -// - creating new Huffman trees less frequently may not provide fast -// adaptation to changes in the input data statistics. (Take for -// example a binary file with poorly compressible code followed by -// a highly compressible string table.) Smaller buffer sizes give -// fast adaptation but have of course the overhead of transmitting trees -// more frequently. -// - I can't count above 4 -// The current code is general and allows DIST_BUFSIZE < LIT_BUFSIZE (to save -// memory at the expense of compression). Some optimizations would be possible -// if we rely on DIST_BUFSIZE == LIT_BUFSIZE. -// - -#define REP_3_6 16 -// repeat previous bit length 3-6 times (2 bits of repeat count) - -#define REPZ_3_10 17 -// repeat a zero length 3-10 times (3 bits of repeat count) - -#define REPZ_11_138 18 -// repeat a zero length 11-138 times (7 bits of repeat count) - -#define HEAP_SIZE (2*L_CODES+1) -// maximum heap size - - -// =========================================================================== -// Local data used by the "bit string" routines. -// - -#define Buf_size (8 * 2*sizeof(char)) -// Number of bits used within bi_buf. (bi_buf may be implemented on -// more than 16 bits on some systems.) - -// Output a 16 bit value to the bit stream, lower (oldest) byte first -#define PUTSHORT(state,w) \ -{ if (state.bs.out_offset >= state.bs.out_size-1) \ - state.flush_outbuf(state.param,state.bs.out_buf, &state.bs.out_offset); \ - state.bs.out_buf[state.bs.out_offset++] = (char) ((w) & 0xff); \ - state.bs.out_buf[state.bs.out_offset++] = (char) ((ush)(w) >> 8); \ -} - -#define PUTBYTE(state,b) \ -{ if (state.bs.out_offset >= state.bs.out_size) \ - state.flush_outbuf(state.param,state.bs.out_buf, &state.bs.out_offset); \ - state.bs.out_buf[state.bs.out_offset++] = (char) (b); \ -} - -// DEFLATE.CPP HEADER - -#define HASH_BITS 15 -// For portability to 16 bit machines, do not use values above 15. - -#define HASH_SIZE (unsigned)(1<= HASH_BITS - -#define max_insert_length max_lazy_match -// Insert new strings in the hash table only if the match length -// is not greater than this length. This saves time but degrades compression. -// max_insert_length is used only for compression levels <= 3. - - - -const int extra_lbits[LENGTH_CODES] // extra bits for each length code - = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; - -const int extra_dbits[D_CODES] // extra bits for each distance code - = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; - -const int extra_blbits[BL_CODES]// extra bits for each bit length code - = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; - -const uch bl_order[BL_CODES] = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; -// The lengths of the bit length codes are sent in order of decreasing -// probability, to avoid transmitting the lengths for unused bit length codes. - - -typedef struct config { - ush good_length; // reduce lazy search above this match length - ush max_lazy; // do not perform lazy search above this match length - ush nice_length; // quit search above this match length - ush max_chain; -} config; - -// Values for max_lazy_match, good_match, nice_match and max_chain_length, -// depending on the desired pack level (0..9). The values given below have -// been tuned to exclude worst case performance for pathological files. -// Better values may be found for specific files. -// - -const config configuration_table[10] = { -// good lazy nice chain - {0, 0, 0, 0}, // 0 store only - {4, 4, 8, 4}, // 1 maximum speed, no lazy matches - {4, 5, 16, 8}, // 2 - {4, 6, 32, 32}, // 3 - {4, 4, 16, 16}, // 4 lazy matches */ - {8, 16, 32, 32}, // 5 - {8, 16, 128, 128}, // 6 - {8, 32, 128, 256}, // 7 - {32, 128, 258, 1024}, // 8 - {32, 258, 258, 4096}};// 9 maximum compression */ - -// Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 -// For deflate_fast() (levels <= 3) good is ignored and lazy has a different meaning. - - - - - -// Data structure describing a single value and its code string. -typedef struct ct_data { - union { - ush freq; // frequency count - ush code; // bit string - } fc; - union { - ush dad; // father node in Huffman tree - ush len; // length of bit string - } dl; -} ct_data; - -typedef struct tree_desc { - ct_data *dyn_tree; // the dynamic tree - ct_data *static_tree; // corresponding static tree or NULL - const int *extra_bits; // extra bits for each code or NULL - int extra_base; // base index for extra_bits - int elems; // max number of elements in the tree - int max_length; // max bit length for the codes - int max_code; // largest code with non zero frequency -} tree_desc; - - - - -class TTreeState -{ public: - TTreeState(); - - ct_data dyn_ltree[HEAP_SIZE]; // literal and length tree - ct_data dyn_dtree[2*D_CODES+1]; // distance tree - ct_data static_ltree[L_CODES+2]; // the static literal tree... - // ... Since the bit lengths are imposed, there is no need for the L_CODES - // extra codes used during heap construction. However the codes 286 and 287 - // are needed to build a canonical tree (see ct_init below). - ct_data static_dtree[D_CODES]; // the static distance tree... - // ... (Actually a trivial tree since all codes use 5 bits.) - ct_data bl_tree[2*BL_CODES+1]; // Huffman tree for the bit lengths - - tree_desc l_desc; - tree_desc d_desc; - tree_desc bl_desc; - - ush bl_count[MAX_BITS+1]; // number of codes at each bit length for an optimal tree - - int heap[2*L_CODES+1]; // heap used to build the Huffman trees - int heap_len; // number of elements in the heap - int heap_max; // element of largest frequency - // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - // The same heap array is used to build all trees. - - uch depth[2*L_CODES+1]; - // Depth of each subtree used as tie breaker for trees of equal frequency - - uch length_code[MAX_MATCH-MIN_MATCH+1]; - // length code for each normalized match length (0 == MIN_MATCH) - - uch dist_code[512]; - // distance codes. The first 256 values correspond to the distances - // 3 .. 258, the last 256 values correspond to the top 8 bits of - // the 15 bit distances. - - int base_length[LENGTH_CODES]; - // First normalized length for each code (0 = MIN_MATCH) - - int base_dist[D_CODES]; - // First normalized distance for each code (0 = distance of 1) - - uch far l_buf[LIT_BUFSIZE]; // buffer for literals/lengths - ush far d_buf[DIST_BUFSIZE]; // buffer for distances - - uch flag_buf[(LIT_BUFSIZE/8)]; - // flag_buf is a bit array distinguishing literals from lengths in - // l_buf, and thus indicating the presence or absence of a distance. - - unsigned last_lit; // running index in l_buf - unsigned last_dist; // running index in d_buf - unsigned last_flags; // running index in flag_buf - uch flags; // current flags not yet saved in flag_buf - uch flag_bit; // current bit used in flags - // bits are filled in flags starting at bit 0 (least significant). - // Note: these flags are overkill in the current code since we don't - // take advantage of DIST_BUFSIZE == LIT_BUFSIZE. - - ulg opt_len; // bit length of current block with optimal trees - ulg static_len; // bit length of current block with static trees - - ulg cmpr_bytelen; // total byte length of compressed file - ulg cmpr_len_bits; // number of bits past 'cmpr_bytelen' - - ulg input_len; // total byte length of input file - // input_len is for debugging only since we can get it by other means. - - ush *file_type; // pointer to UNKNOWN, BINARY or ASCII -// int *file_method; // pointer to DEFLATE or STORE -}; - -TTreeState::TTreeState() -{ tree_desc a = {dyn_ltree, static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS, 0}; l_desc = a; - tree_desc b = {dyn_dtree, static_dtree, extra_dbits, 0, D_CODES, MAX_BITS, 0}; d_desc = b; - tree_desc c = {bl_tree, NULL, extra_blbits, 0, BL_CODES, MAX_BL_BITS, 0}; bl_desc = c; - last_lit=0; - last_dist=0; - last_flags=0; -} - - - -class TBitState -{ public: - - int flush_flg; - // - unsigned bi_buf; - // Output buffer. bits are inserted starting at the bottom (least significant - // bits). The width of bi_buf must be at least 16 bits. - int bi_valid; - // Number of valid bits in bi_buf. All bits above the last valid bit - // are always zero. - char *out_buf; - // Current output buffer. - unsigned out_offset; - // Current offset in output buffer. - // On 16 bit machines, the buffer is limited to 64K. - unsigned out_size; - // Size of current output buffer - ulg bits_sent; // bit length of the compressed data only needed for debugging??? -}; - - - - - - - -class TDeflateState -{ public: - TDeflateState() {window_size=0;} - - uch window[2L*WSIZE]; - // Sliding window. Input bytes are read into the second half of the window, - // and move to the first half later to keep a dictionary of at least WSIZE - // bytes. With this organization, matches are limited to a distance of - // WSIZE-MAX_MATCH bytes, but this ensures that IO is always - // performed with a length multiple of the block size. Also, it limits - // the window size to 64K, which is quite useful on MSDOS. - // To do: limit the window size to WSIZE+CBSZ if SMALL_MEM (the code would - // be less efficient since the data would have to be copied WSIZE/CBSZ times) - Pos prev[WSIZE]; - // Link to older string with same hash index. To limit the size of this - // array to 64K, this link is maintained only for the last 32K strings. - // An index in this array is thus a window index modulo 32K. - Pos head[HASH_SIZE]; - // Heads of the hash chains or NIL. If your compiler thinks that - // HASH_SIZE is a dynamic value, recompile with -DDYN_ALLOC. - - ulg window_size; - // window size, 2*WSIZE except for MMAP or BIG_MEM, where it is the - // input file length plus MIN_LOOKAHEAD. - - long block_start; - // window position at the beginning of the current output block. Gets - // negative when the window is moved backwards. - - int sliding; - // Set to false when the input file is already in memory - - unsigned ins_h; // hash index of string to be inserted - - unsigned int prev_length; - // Length of the best match at previous step. Matches not greater than this - // are discarded. This is used in the lazy match evaluation. - - unsigned strstart; // start of string to insert - unsigned match_start; // start of matching string - int eofile; // flag set at end of input file - unsigned lookahead; // number of valid bytes ahead in window - - unsigned max_chain_length; - // To speed up deflation, hash chains are never searched beyond this length. - // A higher limit improves compression ratio but degrades the speed. - - unsigned int max_lazy_match; - // Attempt to find a better match only when the current match is strictly - // smaller than this value. This mechanism is used only for compression - // levels >= 4. - - unsigned good_match; - // Use a faster search when the previous match is longer than this - - int nice_match; // Stop searching when current match exceeds this -}; - - -typedef struct iztimes { - time_t atime,mtime,ctime; -} iztimes; // access, modify, create times - -typedef struct zlist { - ush vem, ver, flg, how; // See central header in zipfile.c for what vem..off are - ulg tim, crc, siz, len; - extent nam, ext, cext, com; // offset of ext must be >= LOCHEAD - ush dsk, att, lflg; // offset of lflg must be >= LOCHEAD - ulg atx, off; - char name[MAX_PATH]; // File name in zip file - char *extra; // Extra field (set only if ext != 0) - char *cextra; // Extra in central (set only if cext != 0) - char *comment; // Comment (set only if com != 0) - char iname[MAX_PATH]; // Internal file name after cleanup - char zname[MAX_PATH]; // External version of internal name - int mark; // Marker for files to operate on - int trash; // Marker for files to delete - int dosflag; // Set to force MSDOS file attributes - struct zlist far *nxt; // Pointer to next header in list -} TZipFileInfo; - - -class TState; -typedef unsigned (*READFUNC)(TState &state, char *buf,unsigned size); -typedef unsigned (*FLUSHFUNC)(void *param, const char *buf, unsigned *size); -typedef unsigned (*WRITEFUNC)(void *param, const char *buf, unsigned size); -class TState -{ public: TState() {err=0;} - // - void *param; - int level; bool seekable; - READFUNC readfunc; FLUSHFUNC flush_outbuf; - TTreeState ts; TBitState bs; TDeflateState ds; - const char *err; -}; - - - - - - - - - -void Assert(TState &state,bool cond, const char *msg) -{ if (cond) return; - state.err=msg; -} -void __cdecl Trace(const char *x, ...) {va_list paramList; va_start(paramList, x); paramList; va_end(paramList);} -void __cdecl Tracec(bool ,const char *x, ...) {va_list paramList; va_start(paramList, x); paramList; va_end(paramList);} - - - -// =========================================================================== -// Local (static) routines in this file. -// - -void init_block (TState &); -void pqdownheap (TState &,ct_data *tree, int k); -void gen_bitlen (TState &,tree_desc *desc); -void gen_codes (TState &state,ct_data *tree, int max_code); -void build_tree (TState &,tree_desc *desc); -void scan_tree (TState &,ct_data *tree, int max_code); -void send_tree (TState &state,ct_data *tree, int max_code); -int build_bl_tree (TState &); -void send_all_trees (TState &state,int lcodes, int dcodes, int blcodes); -void compress_block (TState &state,ct_data *ltree, ct_data *dtree); -void set_file_type (TState &); -void send_bits (TState &state, int value, int length); -unsigned bi_reverse (unsigned code, int len); -void bi_windup (TState &state); -void copy_block (TState &state,char *buf, unsigned len, int header); - - -#define send_code(state, c, tree) send_bits(state, tree[c].fc.code, tree[c].dl.len) -// Send a code of the given tree. c and tree must not have side effects - -// alternatively... -//#define send_code(state, c, tree) -// { if (state.verbose>1) fprintf(stderr,"\ncd %3d ",(c)); -// send_bits(state, tree[c].fc.code, tree[c].dl.len); } - -#define d_code(dist) ((dist) < 256 ? state.ts.dist_code[dist] : state.ts.dist_code[256+((dist)>>7)]) -// Mapping from a distance to a distance code. dist is the distance - 1 and -// must not have side effects. dist_code[256] and dist_code[257] are never used. - -#define Max(a,b) (a >= b ? a : b) -/* the arguments must not have side effects */ - -/* =========================================================================== - * Allocate the match buffer, initialize the various tables and save the - * location of the internal file attribute (ascii/binary) and method - * (DEFLATE/STORE). - */ -void ct_init(TState &state, ush *attr) -{ - int n; /* iterates over tree elements */ - int bits; /* bit counter */ - int length; /* length value */ - int code; /* code value */ - int dist; /* distance index */ - - state.ts.file_type = attr; - //state.ts.file_method = method; - state.ts.cmpr_bytelen = state.ts.cmpr_len_bits = 0L; - state.ts.input_len = 0L; - - if (state.ts.static_dtree[0].dl.len != 0) return; /* ct_init already called */ - - /* Initialize the mapping length (0..255) -> length code (0..28) */ - length = 0; - for (code = 0; code < LENGTH_CODES-1; code++) { - state.ts.base_length[code] = length; - for (n = 0; n < (1< dist code (0..29) */ - dist = 0; - for (code = 0 ; code < 16; code++) { - state.ts.base_dist[code] = dist; - for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ - for ( ; code < D_CODES; code++) { - state.ts.base_dist[code] = dist << 7; - for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { - state.ts.dist_code[256 + dist++] = (uch)code; - } - } - Assert(state,dist == 256, "ct_init: 256+dist != 512"); - - /* Construct the codes of the static literal tree */ - for (bits = 0; bits <= MAX_BITS; bits++) state.ts.bl_count[bits] = 0; - n = 0; - while (n <= 143) state.ts.static_ltree[n++].dl.len = 8, state.ts.bl_count[8]++; - while (n <= 255) state.ts.static_ltree[n++].dl.len = 9, state.ts.bl_count[9]++; - while (n <= 279) state.ts.static_ltree[n++].dl.len = 7, state.ts.bl_count[7]++; - while (n <= 287) state.ts.static_ltree[n++].dl.len = 8, state.ts.bl_count[8]++; - /* fc.codes 286 and 287 do not exist, but we must include them in the - * tree construction to get a canonical Huffman tree (longest code - * all ones) - */ - gen_codes(state,(ct_data *)state.ts.static_ltree, L_CODES+1); - - /* The static distance tree is trivial: */ - for (n = 0; n < D_CODES; n++) { - state.ts.static_dtree[n].dl.len = 5; - state.ts.static_dtree[n].fc.code = (ush)bi_reverse(n, 5); - } - - /* Initialize the first block of the first file: */ - init_block(state); -} - -/* =========================================================================== - * Initialize a new block. - */ -void init_block(TState &state) -{ - int n; /* iterates over tree elements */ - - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) state.ts.dyn_ltree[n].fc.freq = 0; - for (n = 0; n < D_CODES; n++) state.ts.dyn_dtree[n].fc.freq = 0; - for (n = 0; n < BL_CODES; n++) state.ts.bl_tree[n].fc.freq = 0; - - state.ts.dyn_ltree[END_BLOCK].fc.freq = 1; - state.ts.opt_len = state.ts.static_len = 0L; - state.ts.last_lit = state.ts.last_dist = state.ts.last_flags = 0; - state.ts.flags = 0; state.ts.flag_bit = 1; -} - -#define SMALLEST 1 -/* Index within the heap array of least frequent node in the Huffman tree */ - - -/* =========================================================================== - * Remove the smallest element from the heap and recreate the heap with - * one less element. Updates heap and heap_len. - */ -#define pqremove(tree, top) \ -{\ - top = state.ts.heap[SMALLEST]; \ - state.ts.heap[SMALLEST] = state.ts.heap[state.ts.heap_len--]; \ - pqdownheap(state,tree, SMALLEST); \ -} - -/* =========================================================================== - * Compares to subtrees, using the tree depth as tie breaker when - * the subtrees have equal frequency. This minimizes the worst case length. - */ -#define smaller(tree, n, m) \ - (tree[n].fc.freq < tree[m].fc.freq || \ - (tree[n].fc.freq == tree[m].fc.freq && state.ts.depth[n] <= state.ts.depth[m])) - -/* =========================================================================== - * Restore the heap property by moving down the tree starting at node k, - * exchanging a node with the smallest of its two sons if necessary, stopping - * when the heap property is re-established (each father smaller than its - * two sons). - */ -void pqdownheap(TState &state,ct_data *tree, int k) -{ - int v = state.ts.heap[k]; - int j = k << 1; /* left son of k */ - int htemp; /* required because of bug in SASC compiler */ - - while (j <= state.ts.heap_len) { - /* Set j to the smallest of the two sons: */ - if (j < state.ts.heap_len && smaller(tree, state.ts.heap[j+1], state.ts.heap[j])) j++; - - /* Exit if v is smaller than both sons */ - htemp = state.ts.heap[j]; - if (smaller(tree, v, htemp)) break; - - /* Exchange v with the smallest son */ - state.ts.heap[k] = htemp; - k = j; - - /* And continue down the tree, setting j to the left son of k */ - j <<= 1; - } - state.ts.heap[k] = v; -} - -/* =========================================================================== - * Compute the optimal bit lengths for a tree and update the total bit length - * for the current block. - * IN assertion: the fields freq and dad are set, heap[heap_max] and - * above are the tree nodes sorted by increasing frequency. - * OUT assertions: the field len is set to the optimal bit length, the - * array bl_count contains the frequencies for each bit length. - * The length opt_len is updated; static_len is also updated if stree is - * not null. - */ -void gen_bitlen(TState &state,tree_desc *desc) -{ - ct_data *tree = desc->dyn_tree; - const int *extra = desc->extra_bits; - int base = desc->extra_base; - int max_code = desc->max_code; - int max_length = desc->max_length; - ct_data *stree = desc->static_tree; - int h; /* heap index */ - int n, m; /* iterate over the tree elements */ - int bits; /* bit length */ - int xbits; /* extra bits */ - ush f; /* frequency */ - int overflow = 0; /* number of elements with bit length too large */ - - for (bits = 0; bits <= MAX_BITS; bits++) state.ts.bl_count[bits] = 0; - - /* In a first pass, compute the optimal bit lengths (which may - * overflow in the case of the bit length tree). - */ - tree[state.ts.heap[state.ts.heap_max]].dl.len = 0; /* root of the heap */ - - for (h = state.ts.heap_max+1; h < HEAP_SIZE; h++) { - n = state.ts.heap[h]; - bits = tree[tree[n].dl.dad].dl.len + 1; - if (bits > max_length) bits = max_length, overflow++; - tree[n].dl.len = (ush)bits; - /* We overwrite tree[n].dl.dad which is no longer needed */ - - if (n > max_code) continue; /* not a leaf node */ - - state.ts.bl_count[bits]++; - xbits = 0; - if (n >= base) xbits = extra[n-base]; - f = tree[n].fc.freq; - state.ts.opt_len += (ulg)f * (bits + xbits); - if (stree) state.ts.static_len += (ulg)f * (stree[n].dl.len + xbits); - } - if (overflow == 0) return; - - Trace("\nbit length overflow\n"); - /* This happens for example on obj2 and pic of the Calgary corpus */ - - /* Find the first bit length which could increase: */ - do { - bits = max_length-1; - while (state.ts.bl_count[bits] == 0) bits--; - state.ts.bl_count[bits]--; /* move one leaf down the tree */ - state.ts.bl_count[bits+1] += (ush)2; /* move one overflow item as its brother */ - state.ts.bl_count[max_length]--; - /* The brother of the overflow item also moves one step up, - * but this does not affect bl_count[max_length] - */ - overflow -= 2; - } while (overflow > 0); - - /* Now recompute all bit lengths, scanning in increasing frequency. - * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all - * lengths instead of fixing only the wrong ones. This idea is taken - * from 'ar' written by Haruhiko Okumura.) - */ - for (bits = max_length; bits != 0; bits--) { - n = state.ts.bl_count[bits]; - while (n != 0) { - m = state.ts.heap[--h]; - if (m > max_code) continue; - if (tree[m].dl.len != (ush)bits) { - Trace("code %d bits %d->%d\n", m, tree[m].dl.len, bits); - state.ts.opt_len += ((long)bits-(long)tree[m].dl.len)*(long)tree[m].fc.freq; - tree[m].dl.len = (ush)bits; - } - n--; - } - } -} - -/* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ -void gen_codes (TState &state, ct_data *tree, int max_code) -{ - ush next_code[MAX_BITS+1]; /* next code value for each bit length */ - ush code = 0; /* running code value */ - int bits; /* bit index */ - int n; /* code index */ - - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = (ush)((code + state.ts.bl_count[bits-1]) << 1); - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - Assert(state,code + state.ts.bl_count[MAX_BITS]-1 == (1<< ((ush) MAX_BITS)) - 1, - "inconsistent bit counts"); - Trace("\ngen_codes: max_code %d ", max_code); - - for (n = 0; n <= max_code; n++) { - int len = tree[n].dl.len; - if (len == 0) continue; - /* Now reverse the bits */ - tree[n].fc.code = (ush)bi_reverse(next_code[len]++, len); - - //Tracec(tree != state.ts.static_ltree, "\nn %3d %c l %2d c %4x (%x) ", n, (isgraph(n) ? n : ' '), len, tree[n].fc.code, next_code[len]-1); - } -} - -/* =========================================================================== - * Construct one Huffman tree and assigns the code bit strings and lengths. - * Update the total bit length for the current block. - * IN assertion: the field freq is set for all tree elements. - * OUT assertions: the fields len and code are set to the optimal bit length - * and corresponding code. The length opt_len is updated; static_len is - * also updated if stree is not null. The field max_code is set. - */ -void build_tree(TState &state,tree_desc *desc) -{ - ct_data *tree = desc->dyn_tree; - ct_data *stree = desc->static_tree; - int elems = desc->elems; - int n, m; /* iterate over heap elements */ - int max_code = -1; /* largest code with non zero frequency */ - int node = elems; /* next internal node of the tree */ - - /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - * heap[0] is not used. - */ - state.ts.heap_len = 0, state.ts.heap_max = HEAP_SIZE; - - for (n = 0; n < elems; n++) { - if (tree[n].fc.freq != 0) { - state.ts.heap[++state.ts.heap_len] = max_code = n; - state.ts.depth[n] = 0; - } else { - tree[n].dl.len = 0; - } - } - - /* The pkzip format requires that at least one distance code exists, - * and that at least one bit should be sent even if there is only one - * possible code. So to avoid special checks later on we force at least - * two codes of non zero frequency. - */ - while (state.ts.heap_len < 2) { - int newcp = state.ts.heap[++state.ts.heap_len] = (max_code < 2 ? ++max_code : 0); - tree[newcp].fc.freq = 1; - state.ts.depth[newcp] = 0; - state.ts.opt_len--; if (stree) state.ts.static_len -= stree[newcp].dl.len; - /* new is 0 or 1 so it does not have extra bits */ - } - desc->max_code = max_code; - - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - * establish sub-heaps of increasing lengths: - */ - for (n = state.ts.heap_len/2; n >= 1; n--) pqdownheap(state,tree, n); - - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - do { - pqremove(tree, n); /* n = node of least frequency */ - m = state.ts.heap[SMALLEST]; /* m = node of next least frequency */ - - state.ts.heap[--state.ts.heap_max] = n; /* keep the nodes sorted by frequency */ - state.ts.heap[--state.ts.heap_max] = m; - - /* Create a new node father of n and m */ - tree[node].fc.freq = (ush)(tree[n].fc.freq + tree[m].fc.freq); - state.ts.depth[node] = (uch) (Max(state.ts.depth[n], state.ts.depth[m]) + 1); - tree[n].dl.dad = tree[m].dl.dad = (ush)node; - /* and insert the new node in the heap */ - state.ts.heap[SMALLEST] = node++; - pqdownheap(state,tree, SMALLEST); - - } while (state.ts.heap_len >= 2); - - state.ts.heap[--state.ts.heap_max] = state.ts.heap[SMALLEST]; - - /* At this point, the fields freq and dad are set. We can now - * generate the bit lengths. - */ - gen_bitlen(state,(tree_desc *)desc); - - /* The field len is now set, we can generate the bit codes */ - gen_codes (state,(ct_data *)tree, max_code); -} - -/* =========================================================================== - * Scan a literal or distance tree to determine the frequencies of the codes - * in the bit length tree. Updates opt_len to take into account the repeat - * counts. (The contribution of the bit length codes will be added later - * during the construction of bl_tree.) - */ -void scan_tree (TState &state,ct_data *tree, int max_code) -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].dl.len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - if (nextlen == 0) max_count = 138, min_count = 3; - tree[max_code+1].dl.len = (ush)-1; /* guard */ - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].dl.len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - state.ts.bl_tree[curlen].fc.freq = (ush)(state.ts.bl_tree[curlen].fc.freq + count); - } else if (curlen != 0) { - if (curlen != prevlen) state.ts.bl_tree[curlen].fc.freq++; - state.ts.bl_tree[REP_3_6].fc.freq++; - } else if (count <= 10) { - state.ts.bl_tree[REPZ_3_10].fc.freq++; - } else { - state.ts.bl_tree[REPZ_11_138].fc.freq++; - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Send a literal or distance tree in compressed form, using the codes in - * bl_tree. - */ -void send_tree (TState &state, ct_data *tree, int max_code) -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].dl.len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - /* tree[max_code+1].dl.len = -1; */ /* guard already set */ - if (nextlen == 0) max_count = 138, min_count = 3; - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].dl.len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - do { send_code(state, curlen, state.ts.bl_tree); } while (--count != 0); - - } else if (curlen != 0) { - if (curlen != prevlen) { - send_code(state, curlen, state.ts.bl_tree); count--; - } - Assert(state,count >= 3 && count <= 6, " 3_6?"); - send_code(state,REP_3_6, state.ts.bl_tree); send_bits(state,count-3, 2); - - } else if (count <= 10) { - send_code(state,REPZ_3_10, state.ts.bl_tree); send_bits(state,count-3, 3); - - } else { - send_code(state,REPZ_11_138, state.ts.bl_tree); send_bits(state,count-11, 7); - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Construct the Huffman tree for the bit lengths and return the index in - * bl_order of the last bit length code to send. - */ -int build_bl_tree(TState &state) -{ - int max_blindex; /* index of last bit length code of non zero freq */ - - /* Determine the bit length frequencies for literal and distance trees */ - scan_tree(state,(ct_data *)state.ts.dyn_ltree, state.ts.l_desc.max_code); - scan_tree(state,(ct_data *)state.ts.dyn_dtree, state.ts.d_desc.max_code); - - /* Build the bit length tree: */ - build_tree(state,(tree_desc *)(&state.ts.bl_desc)); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - */ - - /* Determine the number of bit length codes to send. The pkzip format - * requires that at least 4 bit length codes be sent. (appnote.txt says - * 3 but the actual value used is 4.) - */ - for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { - if (state.ts.bl_tree[bl_order[max_blindex]].dl.len != 0) break; - } - /* Update opt_len to include the bit length tree and counts */ - state.ts.opt_len += 3*(max_blindex+1) + 5+5+4; - Trace("\ndyn trees: dyn %ld, stat %ld", state.ts.opt_len, state.ts.static_len); - - return max_blindex; -} - -/* =========================================================================== - * Send the header for a block using dynamic Huffman trees: the counts, the - * lengths of the bit length codes, the literal tree and the distance tree. - * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - */ -void send_all_trees(TState &state,int lcodes, int dcodes, int blcodes) -{ - int rank; /* index in bl_order */ - - Assert(state,lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); - Assert(state,lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, - "too many codes"); - Trace("\nbl counts: "); - send_bits(state,lcodes-257, 5); - /* not +255 as stated in appnote.txt 1.93a or -256 in 2.04c */ - send_bits(state,dcodes-1, 5); - send_bits(state,blcodes-4, 4); /* not -3 as stated in appnote.txt */ - for (rank = 0; rank < blcodes; rank++) { - Trace("\nbl code %2d ", bl_order[rank]); - send_bits(state,state.ts.bl_tree[bl_order[rank]].dl.len, 3); - } - Trace("\nbl tree: sent %ld", state.bs.bits_sent); - - send_tree(state,(ct_data *)state.ts.dyn_ltree, lcodes-1); /* send the literal tree */ - Trace("\nlit tree: sent %ld", state.bs.bits_sent); - - send_tree(state,(ct_data *)state.ts.dyn_dtree, dcodes-1); /* send the distance tree */ - Trace("\ndist tree: sent %ld", state.bs.bits_sent); -} - -/* =========================================================================== - * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and output the encoded block to the zip file. This function - * returns the total compressed length (in bytes) for the file so far. - */ -ulg flush_block(TState &state,char *buf, ulg stored_len, int eof) -{ - ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ - int max_blindex; /* index of last bit length code of non zero freq */ - - state.ts.flag_buf[state.ts.last_flags] = state.ts.flags; /* Save the flags for the last 8 items */ - - /* Check if the file is ascii or binary */ - if (*state.ts.file_type == (ush)UNKNOWN) set_file_type(state); - - /* Construct the literal and distance trees */ - build_tree(state,(tree_desc *)(&state.ts.l_desc)); - Trace("\nlit data: dyn %ld, stat %ld", state.ts.opt_len, state.ts.static_len); - - build_tree(state,(tree_desc *)(&state.ts.d_desc)); - Trace("\ndist data: dyn %ld, stat %ld", state.ts.opt_len, state.ts.static_len); - /* At this point, opt_len and static_len are the total bit lengths of - * the compressed block data, excluding the tree representations. - */ - - /* Build the bit length tree for the above two trees, and get the index - * in bl_order of the last bit length code to send. - */ - max_blindex = build_bl_tree(state); - - /* Determine the best encoding. Compute first the block length in bytes */ - opt_lenb = (state.ts.opt_len+3+7)>>3; - static_lenb = (state.ts.static_len+3+7)>>3; - state.ts.input_len += stored_len; /* for debugging only */ - - Trace("\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u dist %u ", - opt_lenb, state.ts.opt_len, static_lenb, state.ts.static_len, stored_len, - state.ts.last_lit, state.ts.last_dist); - - if (static_lenb <= opt_lenb) opt_lenb = static_lenb; - - // Originally, zip allowed the file to be transformed from a compressed - // into a stored file in the case where compression failed, there - // was only one block, and it was allowed to change. I've removed this - // possibility since the code's cleaner if no changes are allowed. - //if (stored_len <= opt_lenb && eof && state.ts.cmpr_bytelen == 0L - // && state.ts.cmpr_len_bits == 0L && state.seekable) - //{ // && state.ts.file_method != NULL - // // Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: - // Assert(state,buf!=NULL,"block vanished"); - // copy_block(state,buf, (unsigned)stored_len, 0); // without header - // state.ts.cmpr_bytelen = stored_len; - // Assert(state,false,"unimplemented *state.ts.file_method = STORE;"); - // //*state.ts.file_method = STORE; - //} - //else - if (stored_len+4 <= opt_lenb && buf != (char*)NULL) { - /* 4: two words for the lengths */ - /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - * Otherwise we can't have processed more than WSIZE input bytes since - * the last block flush, because compression would have been - * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - * transform a block into a stored block. - */ - send_bits(state,(STORED_BLOCK<<1)+eof, 3); /* send block type */ - state.ts.cmpr_bytelen += ((state.ts.cmpr_len_bits + 3 + 7) >> 3) + stored_len + 4; - state.ts.cmpr_len_bits = 0L; - - copy_block(state,buf, (unsigned)stored_len, 1); /* with header */ - } - else if (static_lenb == opt_lenb) { - send_bits(state,(STATIC_TREES<<1)+eof, 3); - compress_block(state,(ct_data *)state.ts.static_ltree, (ct_data *)state.ts.static_dtree); - state.ts.cmpr_len_bits += 3 + state.ts.static_len; - state.ts.cmpr_bytelen += state.ts.cmpr_len_bits >> 3; - state.ts.cmpr_len_bits &= 7L; - } - else { - send_bits(state,(DYN_TREES<<1)+eof, 3); - send_all_trees(state,state.ts.l_desc.max_code+1, state.ts.d_desc.max_code+1, max_blindex+1); - compress_block(state,(ct_data *)state.ts.dyn_ltree, (ct_data *)state.ts.dyn_dtree); - state.ts.cmpr_len_bits += 3 + state.ts.opt_len; - state.ts.cmpr_bytelen += state.ts.cmpr_len_bits >> 3; - state.ts.cmpr_len_bits &= 7L; - } - Assert(state,((state.ts.cmpr_bytelen << 3) + state.ts.cmpr_len_bits) == state.bs.bits_sent, "bad compressed size"); - init_block(state); - - if (eof) { - // Assert(state,input_len == isize, "bad input size"); - bi_windup(state); - state.ts.cmpr_len_bits += 7; /* align on byte boundary */ - } - Trace("\n"); - - return state.ts.cmpr_bytelen + (state.ts.cmpr_len_bits >> 3); -} - -/* =========================================================================== - * Save the match info and tally the frequency counts. Return true if - * the current block must be flushed. - */ -int ct_tally (TState &state,int dist, int lc) -{ - state.ts.l_buf[state.ts.last_lit++] = (uch)lc; - if (dist == 0) { - /* lc is the unmatched char */ - state.ts.dyn_ltree[lc].fc.freq++; - } else { - /* Here, lc is the match length - MIN_MATCH */ - dist--; /* dist = match distance - 1 */ - Assert(state,(ush)dist < (ush)MAX_DIST && - (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && - (ush)d_code(dist) < (ush)D_CODES, "ct_tally: bad match"); - - state.ts.dyn_ltree[state.ts.length_code[lc]+LITERALS+1].fc.freq++; - state.ts.dyn_dtree[d_code(dist)].fc.freq++; - - state.ts.d_buf[state.ts.last_dist++] = (ush)dist; - state.ts.flags |= state.ts.flag_bit; - } - state.ts.flag_bit <<= 1; - - /* Output the flags if they fill a byte: */ - if ((state.ts.last_lit & 7) == 0) { - state.ts.flag_buf[state.ts.last_flags++] = state.ts.flags; - state.ts.flags = 0, state.ts.flag_bit = 1; - } - /* Try to guess if it is profitable to stop the current block here */ - if (state.level > 2 && (state.ts.last_lit & 0xfff) == 0) { - /* Compute an upper bound for the compressed length */ - ulg out_length = (ulg)state.ts.last_lit*8L; - ulg in_length = (ulg)state.ds.strstart-state.ds.block_start; - int dcode; - for (dcode = 0; dcode < D_CODES; dcode++) { - out_length += (ulg)state.ts.dyn_dtree[dcode].fc.freq*(5L+extra_dbits[dcode]); - } - out_length >>= 3; - Trace("\nlast_lit %u, last_dist %u, in %ld, out ~%ld(%ld%%) ", - state.ts.last_lit, state.ts.last_dist, in_length, out_length, - 100L - out_length*100L/in_length); - if (state.ts.last_dist < state.ts.last_lit/2 && out_length < in_length/2) return 1; - } - return (state.ts.last_lit == LIT_BUFSIZE-1 || state.ts.last_dist == DIST_BUFSIZE); - /* We avoid equality with LIT_BUFSIZE because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ -} - -/* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ -void compress_block(TState &state,ct_data *ltree, ct_data *dtree) -{ - unsigned dist; /* distance of matched string */ - int lc; /* match length or unmatched char (if dist == 0) */ - unsigned lx = 0; /* running index in l_buf */ - unsigned dx = 0; /* running index in d_buf */ - unsigned fx = 0; /* running index in flag_buf */ - uch flag = 0; /* current flags */ - unsigned code; /* the code to send */ - int extra; /* number of extra bits to send */ - - if (state.ts.last_lit != 0) do { - if ((lx & 7) == 0) flag = state.ts.flag_buf[fx++]; - lc = state.ts.l_buf[lx++]; - if ((flag & 1) == 0) { - send_code(state,lc, ltree); /* send a literal byte */ - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = state.ts.length_code[lc]; - send_code(state,code+LITERALS+1, ltree); /* send the length code */ - extra = extra_lbits[code]; - if (extra != 0) { - lc -= state.ts.base_length[code]; - send_bits(state,lc, extra); /* send the extra length bits */ - } - dist = state.ts.d_buf[dx++]; - /* Here, dist is the match distance - 1 */ - code = d_code(dist); - Assert(state,code < D_CODES, "bad d_code"); - - send_code(state,code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra != 0) { - dist -= state.ts.base_dist[code]; - send_bits(state,dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ - flag >>= 1; - } while (lx < state.ts.last_lit); - - send_code(state,END_BLOCK, ltree); -} - -/* =========================================================================== - * Set the file type to ASCII or BINARY, using a crude approximation: - * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. - * IN assertion: the fields freq of dyn_ltree are set and the total of all - * frequencies does not exceed 64K (to fit in an int on 16 bit machines). - */ -void set_file_type(TState &state) -{ - int n = 0; - unsigned ascii_freq = 0; - unsigned bin_freq = 0; - while (n < 7) bin_freq += state.ts.dyn_ltree[n++].fc.freq; - while (n < 128) ascii_freq += state.ts.dyn_ltree[n++].fc.freq; - while (n < LITERALS) bin_freq += state.ts.dyn_ltree[n++].fc.freq; - *state.ts.file_type = (ush)(bin_freq > (ascii_freq >> 2) ? BINARY : ASCII); -} - - -/* =========================================================================== - * Initialize the bit string routines. - */ -void bi_init (TState &state,char *tgt_buf, unsigned tgt_size, int flsh_allowed) -{ - state.bs.out_buf = tgt_buf; - state.bs.out_size = tgt_size; - state.bs.out_offset = 0; - state.bs.flush_flg = flsh_allowed; - - state.bs.bi_buf = 0; - state.bs.bi_valid = 0; - state.bs.bits_sent = 0L; -} - -/* =========================================================================== - * Send a value on a given number of bits. - * IN assertion: length <= 16 and value fits in length bits. - */ -void send_bits(TState &state,int value, int length) -{ - Assert(state,length > 0 && length <= 15, "invalid length"); - state.bs.bits_sent += (ulg)length; - /* If not enough room in bi_buf, use (bi_valid) bits from bi_buf and - * (Buf_size - bi_valid) bits from value to flush the filled bi_buf, - * then fill in the rest of (value), leaving (length - (Buf_size-bi_valid)) - * unused bits in bi_buf. - */ - state.bs.bi_buf |= (value << state.bs.bi_valid); - state.bs.bi_valid += length; - if (state.bs.bi_valid > (int)Buf_size) { - PUTSHORT(state,state.bs.bi_buf); - state.bs.bi_valid -= Buf_size; - state.bs.bi_buf = (unsigned)value >> (length - state.bs.bi_valid); - } -} - -/* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ -unsigned bi_reverse(unsigned code, int len) -{ - register unsigned res = 0; - do { - res |= code & 1; - code >>= 1, res <<= 1; - } while (--len > 0); - return res >> 1; -} - -/* =========================================================================== - * Write out any remaining bits in an incomplete byte. - */ -void bi_windup(TState &state) -{ - if (state.bs.bi_valid > 8) { - PUTSHORT(state,state.bs.bi_buf); - } else if (state.bs.bi_valid > 0) { - PUTBYTE(state,state.bs.bi_buf); - } - if (state.bs.flush_flg) { - state.flush_outbuf(state.param,state.bs.out_buf, &state.bs.out_offset); - } - state.bs.bi_buf = 0; - state.bs.bi_valid = 0; - state.bs.bits_sent = (state.bs.bits_sent+7) & ~7; -} - -/* =========================================================================== - * Copy a stored block to the zip file, storing first the length and its - * one's complement if requested. - */ -void copy_block(TState &state, char *block, unsigned len, int header) -{ - bi_windup(state); /* align on byte boundary */ - - if (header) { - PUTSHORT(state,(ush)len); - PUTSHORT(state,(ush)~len); - state.bs.bits_sent += 2*16; - } - if (state.bs.flush_flg) { - state.flush_outbuf(state.param,state.bs.out_buf, &state.bs.out_offset); - state.bs.out_offset = len; - state.flush_outbuf(state.param,block, &state.bs.out_offset); - } else if (state.bs.out_offset + len > state.bs.out_size) { - Assert(state,false,"output buffer too small for in-memory compression"); - } else { - memcpy(state.bs.out_buf + state.bs.out_offset, block, len); - state.bs.out_offset += len; - } - state.bs.bits_sent += (ulg)len<<3; -} - - - - - - - - -/* =========================================================================== - * Prototypes for functions. - */ - -void fill_window (TState &state); -ulg deflate_fast (TState &state); - -int longest_match (TState &state,IPos cur_match); - - -/* =========================================================================== - * Update a hash value with the given input byte - * IN assertion: all calls to to UPDATE_HASH are made with consecutive - * input characters, so that a running hash key can be computed from the - * previous key instead of complete recalculation each time. - */ -#define UPDATE_HASH(h,c) (h = (((h)< 0 if the input file is already read or - * mmap'ed in the window[] array, 0 otherwise. In the first case, - * window_size is sufficient to contain the whole input file plus - * MIN_LOOKAHEAD bytes (to avoid referencing memory beyond the end - * of window[] when looking for matches towards the end). - */ -void lm_init (TState &state, int pack_level, ush *flags) -{ - register unsigned j; - - Assert(state,pack_level>=1 && pack_level<=8,"bad pack level"); - - /* Do not slide the window if the whole input is already in memory - * (window_size > 0) - */ - state.ds.sliding = 0; - if (state.ds.window_size == 0L) { - state.ds.sliding = 1; - state.ds.window_size = (ulg)2L*WSIZE; - } - - /* Initialize the hash table (avoiding 64K overflow for 16 bit systems). - * prev[] will be initialized on the fly. - */ - state.ds.head[HASH_SIZE-1] = NIL; - memset((char*)state.ds.head, NIL, (unsigned)(HASH_SIZE-1)*sizeof(*state.ds.head)); - - /* Set the default configuration parameters: - */ - state.ds.max_lazy_match = configuration_table[pack_level].max_lazy; - state.ds.good_match = configuration_table[pack_level].good_length; - state.ds.nice_match = configuration_table[pack_level].nice_length; - state.ds.max_chain_length = configuration_table[pack_level].max_chain; - if (pack_level <= 2) { - *flags |= FAST; - } else if (pack_level >= 8) { - *flags |= SLOW; - } - /* ??? reduce max_chain_length for binary files */ - - state.ds.strstart = 0; - state.ds.block_start = 0L; - - j = WSIZE; - j <<= 1; // Can read 64K in one step - state.ds.lookahead = state.readfunc(state, (char*)state.ds.window, j); - - if (state.ds.lookahead == 0 || state.ds.lookahead == (unsigned)EOF) { - state.ds.eofile = 1, state.ds.lookahead = 0; - return; - } - state.ds.eofile = 0; - /* Make sure that we always have enough lookahead. This is important - * if input comes from a device such as a tty. - */ - if (state.ds.lookahead < MIN_LOOKAHEAD) fill_window(state); - - state.ds.ins_h = 0; - for (j=0; j= 1 - */ -// For 80x86 and 680x0 and ARM, an optimized version is in match.asm or -// match.S. The code is functionally equivalent, so you can use the C version -// if desired. Which I do so desire! -int longest_match(TState &state,IPos cur_match) -{ - unsigned chain_length = state.ds.max_chain_length; /* max hash chain length */ - register uch far *scan = state.ds.window + state.ds.strstart; /* current string */ - register uch far *match; /* matched string */ - register int len; /* length of current match */ - int best_len = state.ds.prev_length; /* best match length so far */ - IPos limit = state.ds.strstart > (IPos)MAX_DIST ? state.ds.strstart - (IPos)MAX_DIST : NIL; - /* Stop when cur_match becomes <= limit. To simplify the code, - * we prevent matches with the string of window index 0. - */ - - // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - // It is easy to get rid of this optimization if necessary. - Assert(state,HASH_BITS>=8 && MAX_MATCH==258,"Code too clever"); - - - - register uch far *strend = state.ds.window + state.ds.strstart + MAX_MATCH; - register uch scan_end1 = scan[best_len-1]; - register uch scan_end = scan[best_len]; - - /* Do not waste too much time if we already have a good match: */ - if (state.ds.prev_length >= state.ds.good_match) { - chain_length >>= 2; - } - - Assert(state,state.ds.strstart <= state.ds.window_size-MIN_LOOKAHEAD, "insufficient lookahead"); - - do { - Assert(state,cur_match < state.ds.strstart, "no future"); - match = state.ds.window + cur_match; - - /* Skip to next match if the match length cannot increase - * or if the match length is less than 2: - */ - if (match[best_len] != scan_end || - match[best_len-1] != scan_end1 || - *match != *scan || - *++match != scan[1]) continue; - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2, match++; - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - } while (*++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - scan < strend); - - Assert(state,scan <= state.ds.window+(unsigned)(state.ds.window_size-1), "wild scan"); - - len = MAX_MATCH - (int)(strend - scan); - scan = strend - MAX_MATCH; - - - if (len > best_len) { - state.ds.match_start = cur_match; - best_len = len; - if (len >= state.ds.nice_match) break; - scan_end1 = scan[best_len-1]; - scan_end = scan[best_len]; - } - } while ((cur_match = state.ds.prev[cur_match & WMASK]) > limit - && --chain_length != 0); - - return best_len; -} - - - -#define check_match(state,start, match, length) -// or alternatively... -//void check_match(TState &state,IPos start, IPos match, int length) -//{ // check that the match is indeed a match -// if (memcmp((char*)state.ds.window + match, -// (char*)state.ds.window + start, length) != EQUAL) { -// fprintf(stderr, -// " start %d, match %d, length %d\n", -// start, match, length); -// error("invalid match"); -// } -// if (state.verbose > 1) { -// fprintf(stderr,"\\[%d,%d]", start-match, length); -// do { fprintf(stdout,"%c",state.ds.window[start++]); } while (--length != 0); -// } -//} - -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead, and sets eofile if end of input file. - * - * IN assertion: lookahead < MIN_LOOKAHEAD && strstart + lookahead > 0 - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or eofile is set; file reads are - * performed for at least two bytes (required for the translate_eol option). - */ -void fill_window(TState &state) -{ - register unsigned n, m; - unsigned more; /* Amount of free space at the end of the window. */ - - do { - more = (unsigned)(state.ds.window_size - (ulg)state.ds.lookahead - (ulg)state.ds.strstart); - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (more == (unsigned)EOF) { - /* Very unlikely, but possible on 16 bit machine if strstart == 0 - * and lookahead == 1 (input done one byte at time) - */ - more--; - - /* For MMAP or BIG_MEM, the whole input file is already in memory so - * we must not perform sliding. We must however call (*read_buf)() in - * order to compute the crc, update lookahead and possibly set eofile. - */ - } else if (state.ds.strstart >= WSIZE+MAX_DIST && state.ds.sliding) { - - /* By the IN assertion, the window is not empty so we can't confuse - * more == 0 with more == 64K on a 16 bit machine. - */ - memcpy((char*)state.ds.window, (char*)state.ds.window+WSIZE, (unsigned)WSIZE); - state.ds.match_start -= WSIZE; - state.ds.strstart -= WSIZE; /* we now have strstart >= MAX_DIST: */ - - state.ds.block_start -= (long) WSIZE; - - for (n = 0; n < HASH_SIZE; n++) { - m = state.ds.head[n]; - state.ds.head[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL); - } - for (n = 0; n < WSIZE; n++) { - m = state.ds.prev[n]; - state.ds.prev[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } - more += WSIZE; - } - if (state.ds.eofile) return; - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the MMAP or BIG_MEM case (not yet supported in gzip), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - Assert(state,more >= 2, "more < 2"); - - n = state.readfunc(state, (char*)state.ds.window+state.ds.strstart+state.ds.lookahead, more); - - if (n == 0 || n == (unsigned)EOF) { - state.ds.eofile = 1; - } else { - state.ds.lookahead += n; - } - } while (state.ds.lookahead < MIN_LOOKAHEAD && !state.ds.eofile); -} - -/* =========================================================================== - * Flush the current block, with given end-of-file flag. - * IN assertion: strstart is set to the end of the current match. - */ -#define FLUSH_BLOCK(state,eof) \ - flush_block(state,state.ds.block_start >= 0L ? (char*)&state.ds.window[(unsigned)state.ds.block_start] : \ - (char*)NULL, (long)state.ds.strstart - state.ds.block_start, (eof)) - -/* =========================================================================== - * Processes a new input file and return its compressed length. This - * function does not perform lazy evaluation of matches and inserts - * new strings in the dictionary only for unmatched strings or for short - * matches. It is used only for the fast compression options. - */ -ulg deflate_fast(TState &state) -{ - IPos hash_head = NIL; /* head of the hash chain */ - int flush; /* set if current block must be flushed */ - unsigned match_length = 0; /* length of best match */ - - state.ds.prev_length = MIN_MATCH-1; - while (state.ds.lookahead != 0) { - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - if (state.ds.lookahead >= MIN_MATCH) - INSERT_STRING(state.ds.strstart, hash_head); - - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH - */ - if (hash_head != NIL && state.ds.strstart - hash_head <= MAX_DIST) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - /* Do not look for matches beyond the end of the input. - * This is necessary to make deflate deterministic. - */ - if ((unsigned)state.ds.nice_match > state.ds.lookahead) state.ds.nice_match = (int)state.ds.lookahead; - match_length = longest_match (state,hash_head); - /* longest_match() sets match_start */ - if (match_length > state.ds.lookahead) match_length = state.ds.lookahead; - } - if (match_length >= MIN_MATCH) { - check_match(state,state.ds.strstart, state.ds.match_start, match_length); - - flush = ct_tally(state,state.ds.strstart-state.ds.match_start, match_length - MIN_MATCH); - - state.ds.lookahead -= match_length; - - /* Insert new strings in the hash table only if the match length - * is not too large. This saves time but degrades compression. - */ - if (match_length <= state.ds.max_insert_length - && state.ds.lookahead >= MIN_MATCH) { - match_length--; /* string at strstart already in hash table */ - do { - state.ds.strstart++; - INSERT_STRING(state.ds.strstart, hash_head); - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. - */ - } while (--match_length != 0); - state.ds.strstart++; - } else { - state.ds.strstart += match_length; - match_length = 0; - state.ds.ins_h = state.ds.window[state.ds.strstart]; - UPDATE_HASH(state.ds.ins_h, state.ds.window[state.ds.strstart+1]); - Assert(state,MIN_MATCH==3,"Call UPDATE_HASH() MIN_MATCH-3 more times"); - } - } else { - /* No match, output a literal byte */ - flush = ct_tally (state,0, state.ds.window[state.ds.strstart]); - state.ds.lookahead--; - state.ds.strstart++; - } - if (flush) FLUSH_BLOCK(state,0), state.ds.block_start = state.ds.strstart; - - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (state.ds.lookahead < MIN_LOOKAHEAD) fill_window(state); - } - return FLUSH_BLOCK(state,1); /* eof */ -} - -/* =========================================================================== - * Same as above, but achieves better compression. We use a lazy - * evaluation for matches: a match is finally adopted only if there is - * no better match at the next window position. - */ -ulg deflate(TState &state) -{ - IPos hash_head = NIL; /* head of hash chain */ - IPos prev_match; /* previous match */ - int flush; /* set if current block must be flushed */ - int match_available = 0; /* set if previous match exists */ - register unsigned match_length = MIN_MATCH-1; /* length of best match */ - - if (state.level <= 3) return deflate_fast(state); /* optimized for speed */ - - /* Process the input block. */ - while (state.ds.lookahead != 0) { - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - if (state.ds.lookahead >= MIN_MATCH) - INSERT_STRING(state.ds.strstart, hash_head); - - /* Find the longest match, discarding those <= prev_length. - */ - state.ds.prev_length = match_length, prev_match = state.ds.match_start; - match_length = MIN_MATCH-1; - - if (hash_head != NIL && state.ds.prev_length < state.ds.max_lazy_match && - state.ds.strstart - hash_head <= MAX_DIST) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - /* Do not look for matches beyond the end of the input. - * This is necessary to make deflate deterministic. - */ - if ((unsigned)state.ds.nice_match > state.ds.lookahead) state.ds.nice_match = (int)state.ds.lookahead; - match_length = longest_match (state,hash_head); - /* longest_match() sets match_start */ - if (match_length > state.ds.lookahead) match_length = state.ds.lookahead; - - /* Ignore a length 3 match if it is too distant: */ - if (match_length == MIN_MATCH && state.ds.strstart-state.ds.match_start > TOO_FAR){ - /* If prev_match is also MIN_MATCH, match_start is garbage - * but we will ignore the current match anyway. - */ - match_length = MIN_MATCH-1; - } - } - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ - if (state.ds.prev_length >= MIN_MATCH && match_length <= state.ds.prev_length) { - unsigned max_insert = state.ds.strstart + state.ds.lookahead - MIN_MATCH; - check_match(state,state.ds.strstart-1, prev_match, state.ds.prev_length); - flush = ct_tally(state,state.ds.strstart-1-prev_match, state.ds.prev_length - MIN_MATCH); - - /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. - */ - state.ds.lookahead -= state.ds.prev_length-1; - state.ds.prev_length -= 2; - do { - if (++state.ds.strstart <= max_insert) { - INSERT_STRING(state.ds.strstart, hash_head); - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. - */ - } - } while (--state.ds.prev_length != 0); - state.ds.strstart++; - match_available = 0; - match_length = MIN_MATCH-1; - - if (flush) FLUSH_BLOCK(state,0), state.ds.block_start = state.ds.strstart; - - } else if (match_available) { - /* If there was no match at the previous position, output a - * single literal. If there was a match but the current match - * is longer, truncate the previous match to a single literal. - */ - if (ct_tally (state,0, state.ds.window[state.ds.strstart-1])) { - FLUSH_BLOCK(state,0), state.ds.block_start = state.ds.strstart; - } - state.ds.strstart++; - state.ds.lookahead--; - } else { - /* There is no previous match to compare with, wait for - * the next step to decide. - */ - match_available = 1; - state.ds.strstart++; - state.ds.lookahead--; - } -// Assert(state,strstart <= isize && lookahead <= isize, "a bit too far"); - - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (state.ds.lookahead < MIN_LOOKAHEAD) fill_window(state); - } - if (match_available) ct_tally (state,0, state.ds.window[state.ds.strstart-1]); - - return FLUSH_BLOCK(state,1); /* eof */ -} - - - - - - - - - - - - -int putlocal(struct zlist far *z, WRITEFUNC wfunc,void *param) -{ // Write a local header described by *z to file *f. Return a ZE_ error code. - PUTLG(LOCSIG, f); - PUTSH(z->ver, f); - PUTSH(z->lflg, f); - PUTSH(z->how, f); - PUTLG(z->tim, f); - PUTLG(z->crc, f); - PUTLG(z->siz, f); - PUTLG(z->len, f); - PUTSH(z->nam, f); - PUTSH(z->ext, f); - size_t res = (size_t)wfunc(param, z->iname, (unsigned int)z->nam); - if (res!=z->nam) return ZE_TEMP; - if (z->ext) - { res = (size_t)wfunc(param, z->extra, (unsigned int)z->ext); - if (res!=z->ext) return ZE_TEMP; - } - return ZE_OK; -} - -int putextended(struct zlist far *z, WRITEFUNC wfunc, void *param) -{ // Write an extended local header described by *z to file *f. Returns a ZE_ code - PUTLG(EXTLOCSIG, f); - PUTLG(z->crc, f); - PUTLG(z->siz, f); - PUTLG(z->len, f); - return ZE_OK; -} - -int putcentral(struct zlist far *z, WRITEFUNC wfunc, void *param) -{ // Write a central header entry of *z to file *f. Returns a ZE_ code. - PUTLG(CENSIG, f); - PUTSH(z->vem, f); - PUTSH(z->ver, f); - PUTSH(z->flg, f); - PUTSH(z->how, f); - PUTLG(z->tim, f); - PUTLG(z->crc, f); - PUTLG(z->siz, f); - PUTLG(z->len, f); - PUTSH(z->nam, f); - PUTSH(z->cext, f); - PUTSH(z->com, f); - PUTSH(z->dsk, f); - PUTSH(z->att, f); - PUTLG(z->atx, f); - PUTLG(z->off, f); - if ((size_t)wfunc(param, z->iname, (unsigned int)z->nam) != z->nam || - (z->cext && (size_t)wfunc(param, z->cextra, (unsigned int)z->cext) != z->cext) || - (z->com && (size_t)wfunc(param, z->comment, (unsigned int)z->com) != z->com)) - return ZE_TEMP; - return ZE_OK; -} - - -int putend(int n, ulg s, ulg c, extent m, char *z, WRITEFUNC wfunc, void *param) -{ // write the end of the central-directory-data to file *f. - PUTLG(ENDSIG, f); - PUTSH(0, f); - PUTSH(0, f); - PUTSH(n, f); - PUTSH(n, f); - PUTLG(s, f); - PUTLG(c, f); - PUTSH(m, f); - // Write the comment, if any - if (m && wfunc(param, z, (unsigned int)m) != m) return ZE_TEMP; - return ZE_OK; -} - - - - - - -const ulg crc_table[256] = { - 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, - 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, - 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, - 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, - 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, - 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, - 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, - 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, - 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, - 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, - 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, - 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, - 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, - 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, - 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, - 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, - 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, - 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, - 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, - 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, - 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, - 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, - 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, - 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, - 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, - 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, - 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, - 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, - 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, - 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, - 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, - 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, - 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, - 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, - 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, - 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, - 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, - 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, - 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, - 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, - 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, - 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, - 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, - 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, - 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, - 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, - 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, - 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, - 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, - 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, - 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, - 0x2d02ef8dL -}; - -#define CRC32(c, b) (crc_table[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8)) -#define DO1(buf) crc = CRC32(crc, *buf++) -#define DO2(buf) DO1(buf); DO1(buf) -#define DO4(buf) DO2(buf); DO2(buf) -#define DO8(buf) DO4(buf); DO4(buf) - -ulg crc32(ulg crc, const uch *buf, extent len) -{ if (buf==NULL) return 0L; - crc = crc ^ 0xffffffffL; - while (len >= 8) {DO8(buf); len -= 8;} - if (len) do {DO1(buf);} while (--len); - return crc ^ 0xffffffffL; // (instead of ~c for 64-bit machines) -} - - - - - - - - -bool HasZipSuffix(const char *fn) -{ - const char *ext = fn+strlen(fn); - while (ext>fn && *ext!='.') - { - ext--; - } - if (ext==fn && *ext!='.') return false; - if (Q_stricmp(ext,".Z")==0) return true; - if (Q_stricmp(ext,".zip")==0) return true; - if (Q_stricmp(ext,".zoo")==0) return true; - if (Q_stricmp(ext,".arc")==0) return true; - if (Q_stricmp(ext,".lzh")==0) return true; - if (Q_stricmp(ext,".arj")==0) return true; - if (Q_stricmp(ext,".gz")==0) return true; - if (Q_stricmp(ext,".tgz")==0) return true; - return false; -} - - -time_t filetime2timet(const FILETIME ft) -{ - SYSTEMTIME st; FileTimeToSystemTime(&ft,&st); - if (st.wYear<1970) {st.wYear=1970; st.wMonth=1; st.wDay=1;} - if (st.wYear>=2038) {st.wYear=2037; st.wMonth=12; st.wDay=31;} - struct tm tm; - tm.tm_sec = st.wSecond; - tm.tm_min = st.wMinute; - tm.tm_hour = st.wHour; - tm.tm_mday = st.wDay; - tm.tm_mon = st.wMonth-1; - tm.tm_year = st.wYear-1900; - tm.tm_isdst = 0; - time_t t = mktime(&tm); - return t; -} - - -ZRESULT GetFileInfo(HANDLE hf, ulg *attr, long *size, iztimes *times, ulg *timestamp) -{ - DWORD type=GetFileType(hf); - if (type!=FILE_TYPE_DISK) - return ZR_NOTINITED; - // The handle must be a handle to a file - // The date and time is returned in a long with the date most significant to allow - // unsigned integer comparison of absolute times. The attributes have two - // high bytes unix attr, and two low bytes a mapping of that to DOS attr. - //struct stat s; int res=stat(fn,&s); if (res!=0) return false; - // translate windows file attributes into zip ones. - BY_HANDLE_FILE_INFORMATION bhi; - BOOL res=GetFileInformationByHandle(hf,&bhi); - if (!res) - return ZR_NOFILE; - DWORD fa=bhi.dwFileAttributes; - ulg a=0; - // Zip uses the lower word for its interpretation of windows stuff - if (fa&FILE_ATTRIBUTE_READONLY) a|=0x01; - if (fa&FILE_ATTRIBUTE_HIDDEN) a|=0x02; - if (fa&FILE_ATTRIBUTE_SYSTEM) a|=0x04; - if (fa&FILE_ATTRIBUTE_DIRECTORY)a|=0x10; - if (fa&FILE_ATTRIBUTE_ARCHIVE) a|=0x20; - // It uses the upper word for standard unix attr, which we must manually construct - if (fa&FILE_ATTRIBUTE_DIRECTORY)a|=0x40000000; // directory - else a|=0x80000000; // normal file - a|=0x01000000; // readable - if (fa&FILE_ATTRIBUTE_READONLY) {} - else a|=0x00800000; // writeable - // now just a small heuristic to check if it's an executable: - DWORD red, hsize=GetFileSize(hf,NULL); if (hsize>40) - { SetFilePointer(hf,0,NULL,FILE_BEGIN); unsigned short magic; ReadFile(hf,&magic,sizeof(magic),&red,NULL); - SetFilePointer(hf,36,NULL,FILE_BEGIN); unsigned long hpos; ReadFile(hf,&hpos,sizeof(hpos),&red,NULL); - if (magic==0x54AD && hsize>hpos+4+20+28) - { SetFilePointer(hf,hpos,NULL,FILE_BEGIN); unsigned long signature; ReadFile(hf,&signature,sizeof(signature),&red,NULL); - if (signature==IMAGE_DOS_SIGNATURE || signature==IMAGE_OS2_SIGNATURE - || signature==IMAGE_OS2_SIGNATURE_LE || signature==IMAGE_NT_SIGNATURE) - { a |= 0x00400000; // executable - } - } - } - // - if (attr!=NULL) *attr = a; - if (size!=NULL) *size = hsize; - if (times!=NULL) - { // time_t is 32bit number of seconds elapsed since 0:0:0GMT, Jan1, 1970. - // but FILETIME is 64bit number of 100-nanosecs since Jan1, 1601 - times->atime = filetime2timet(bhi.ftLastAccessTime); - times->mtime = filetime2timet(bhi.ftLastWriteTime); - times->ctime = filetime2timet(bhi.ftCreationTime); - } - if (timestamp!=NULL) - { WORD dosdate,dostime; - FileTimeToDosDateTime(&bhi.ftLastWriteTime,&dosdate,&dostime); - *timestamp = (WORD)dostime | (((DWORD)dosdate)<<16); - } - return ZR_OK; -} - - - - - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -class TZip -{ public: - TZip() : hfout(0),hmapout(0),zfis(0),obuf(0),hfin(0),writ(0),oerr(false),hasputcen(false),ooffset(0) {} - ~TZip() {} - - // These variables say about the file we're writing into - // We can write to pipe, file-by-handle, file-by-name, memory-to-memmapfile - HANDLE hfout; // if valid, we'll write here (for files or pipes) - HANDLE hmapout; // otherwise, we'll write here (for memmap) - unsigned ooffset; // for hfout, this is where the pointer was initially - ZRESULT oerr; // did a write operation give rise to an error? - unsigned writ; // how far have we written. This is maintained by Add, not write(), to avoid confusion over seeks - bool ocanseek; // can we seek? - char *obuf; // this is where we've locked mmap to view. - unsigned int opos; // current pos in the mmap - unsigned int mapsize; // the size of the map we created - bool hasputcen; // have we yet placed the central directory? - // - TZipFileInfo *zfis; // each file gets added onto this list, for writing the table at the end - - ZRESULT Create(void *z,unsigned int len,DWORD flags); - static unsigned sflush(void *param,const char *buf, unsigned *size); - static unsigned swrite(void *param,const char *buf, unsigned size); - unsigned int write(const char *buf,unsigned int size); - bool oseek(unsigned int pos); - ZRESULT GetMemory(void **pbuf, unsigned long *plen); - ZRESULT Close(); - - // some variables to do with the file currently being read: - // I haven't done it object-orientedly here, just put them all - // together, since OO didn't seem to make the design any clearer. - ulg attr; iztimes times; ulg timestamp; // all open_* methods set these - bool iseekable; long isize,ired; // size is not set until close() on pips - ulg crc; // crc is not set until close(). iwrit is cumulative - HANDLE hfin; bool selfclosehf; // for input files and pipes - const char *bufin; unsigned int lenin,posin; // for memory - // and a variable for what we've done with the input: (i.e. compressed it!) - ulg csize; // compressed size, set by the compression routines - // and this is used by some of the compression routines - char buf[16384]; - - - ZRESULT open_file(const TCHAR *fn); - ZRESULT open_handle(HANDLE hf,unsigned int len); - ZRESULT open_mem(void *src,unsigned int len); - ZRESULT open_dir(); - static unsigned sread(TState &s,char *buf,unsigned size); - unsigned read(char *buf, unsigned size); - ZRESULT iclose(); - - ZRESULT ideflate(TZipFileInfo *zfi); - ZRESULT istore(); - - ZRESULT Add(const char *odstzn, void *src,unsigned int len, DWORD flags); - ZRESULT AddCentral(); - -}; - -ZRESULT TZip::Create(void *z,unsigned int len,DWORD flags) -{ - if (hfout!=0 || hmapout!=0 || obuf!=0 || writ!=0 || oerr!=ZR_OK || hasputcen) - return ZR_NOTINITED; - // - if (flags==ZIP_HANDLE) - { - HANDLE hf = (HANDLE)z; - BOOL res = DuplicateHandle(GetCurrentProcess(),hf,GetCurrentProcess(),&hfout,0,FALSE,DUPLICATE_SAME_ACCESS); - if (!res) - return ZR_NODUPH; - // now we have our own hfout, which we must close. And the caller will close hf - DWORD type = GetFileType(hfout); - ocanseek = (type==FILE_TYPE_DISK); - if (type==FILE_TYPE_DISK) - ooffset=SetFilePointer(hfout,0,NULL,FILE_CURRENT); - else - ooffset=0; - return ZR_OK; - } - else if (flags==ZIP_FILENAME) - { -#ifdef _UNICODE - const TCHAR *fn = (const TCHAR*)z; - hfout = CreateFileW(fn,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); -#else - const char *fn = (const char*)z; - hfout = CreateFileA(fn,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); -#endif - - if (hfout==INVALID_HANDLE_VALUE) - { - hfout=0; - return ZR_NOFILE; - } - ocanseek=true; - ooffset=0; - return ZR_OK; - } -#ifndef _XBOX - else if (flags==ZIP_MEMORY) - { - unsigned int size = len; - if (size==0) - return ZR_MEMSIZE; - if (z!=0) - obuf=(char*)z; - else - { - hmapout = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,size,NULL); - if (hmapout==NULL) - return ZR_NOALLOC; - obuf = (char*)MapViewOfFile(hmapout,FILE_MAP_ALL_ACCESS,0,0,size); - if (obuf==0) - { - CloseHandle(hmapout); - hmapout=0; - return ZR_NOALLOC; - } - } - ocanseek=true; - opos=0; - mapsize=size; - return ZR_OK; - } -#endif - else - return ZR_ARGS; -} - - -unsigned TZip::sflush(void *param,const char *buf, unsigned *size) -{ // static - if (*size==0) return 0; - TZip *zip = (TZip*)param; - unsigned int writ = zip->write(buf,*size); - if (writ!=0) *size=0; - return writ; -} -unsigned TZip::swrite(void *param,const char *buf, unsigned size) -{ // static - if (size==0) return 0; - TZip *zip=(TZip*)param; return zip->write(buf,size); -} -unsigned int TZip::write(const char *buf,unsigned int size) -{ if (obuf!=0) - { if (opos+size>=mapsize) {oerr=ZR_MEMSIZE; return 0;} - memcpy(obuf+opos, buf, size); - opos+=size; - return size; - } - else if (hfout!=0) - { DWORD writ; WriteFile(hfout,buf,size,&writ,NULL); - return writ; - } - oerr=ZR_NOTINITED; return 0; -} - -bool TZip::oseek(unsigned int pos) -{ if (!ocanseek) {oerr=ZR_SEEK; return false;} - if (obuf!=0) - { if (pos>=mapsize) {oerr=ZR_MEMSIZE; return false;} - opos=pos; - return true; - } - else if (hfout!=0) - { SetFilePointer(hfout,pos+ooffset,NULL,FILE_BEGIN); - return true; - } - oerr=ZR_NOTINITED; return 0; -} - -ZRESULT TZip::GetMemory(void **pbuf, unsigned long *plen) -{ // When the user calls GetMemory, they're presumably at the end - // of all their adding. In any case, we have to add the central - // directory now, otherwise the memory we tell them won't be complete. - if (!hasputcen) AddCentral(); hasputcen=true; - if (pbuf!=NULL) *pbuf=(void*)obuf; - if (plen!=NULL) *plen=writ; - if (obuf==NULL) return ZR_NOTMMAP; - return ZR_OK; -} - -ZRESULT TZip::Close() -{ // if the directory hadn't already been added through a call to GetMemory, - // then we do it now - ZRESULT res=ZR_OK; if (!hasputcen) res=AddCentral(); hasputcen=true; -#ifndef _XBOX - if (obuf!=0 && hmapout!=0) UnmapViewOfFile(obuf); obuf=0; -#endif - if (hmapout!=0) CloseHandle(hmapout); hmapout=0; - if (hfout!=0) CloseHandle(hfout); hfout=0; - return res; -} - - - - -ZRESULT TZip::open_file(const TCHAR *fn) -{ hfin=0; bufin=0; selfclosehf=false; crc=CRCVAL_INITIAL; isize=0; csize=0; ired=0; - if (fn==0) return ZR_ARGS; - HANDLE hf = CreateFile(fn,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL); - if (hf==INVALID_HANDLE_VALUE) return ZR_NOFILE; - ZRESULT res = open_handle(hf,0); - if (res!=ZR_OK) {CloseHandle(hf); return res;} - selfclosehf=true; - return ZR_OK; -} -ZRESULT TZip::open_handle(HANDLE hf,unsigned int len) -{ hfin=0; bufin=0; selfclosehf=false; crc=CRCVAL_INITIAL; isize=0; csize=0; ired=0; - if (hf==0 || hf==INVALID_HANDLE_VALUE) return ZR_ARGS; - DWORD type = GetFileType(hf); - if (type==FILE_TYPE_DISK) - { ZRESULT res = GetFileInfo(hf,&attr,&isize,×,×tamp); - if (res!=ZR_OK) return res; - SetFilePointer(hf,0,NULL,FILE_BEGIN); // because GetFileInfo will have screwed it up - iseekable=true; hfin=hf; - return ZR_OK; - } - else - { attr= 0x80000000; // just a normal file - isize = -1; // can't know size until at the end - if (len!=0) isize=len; // unless we were told explicitly! - iseekable=false; - SYSTEMTIME st; GetLocalTime(&st); - FILETIME ft; SystemTimeToFileTime(&st,&ft); - WORD dosdate,dostime; FileTimeToDosDateTime(&ft,&dosdate,&dostime); - times.atime = filetime2timet(ft); - times.mtime = times.atime; - times.ctime = times.atime; - timestamp = (WORD)dostime | (((DWORD)dosdate)<<16); - hfin=hf; - return ZR_OK; - } -} -ZRESULT TZip::open_mem(void *src,unsigned int len) -{ hfin=0; bufin=(const char*)src; selfclosehf=false; crc=CRCVAL_INITIAL; ired=0; csize=0; ired=0; - lenin=len; posin=0; - if (src==0 || len==0) return ZR_ARGS; - attr= 0x80000000; // just a normal file - isize = len; - iseekable=true; - SYSTEMTIME st; GetLocalTime(&st); - FILETIME ft; SystemTimeToFileTime(&st,&ft); - WORD dosdate,dostime; FileTimeToDosDateTime(&ft,&dosdate,&dostime); - times.atime = filetime2timet(ft); - times.mtime = times.atime; - times.ctime = times.atime; - timestamp = (WORD)dostime | (((DWORD)dosdate)<<16); - return ZR_OK; -} -ZRESULT TZip::open_dir() -{ hfin=0; bufin=0; selfclosehf=false; crc=CRCVAL_INITIAL; isize=0; csize=0; ired=0; - attr= 0x41C00010; // a readable writable directory, and again directory - isize = 0; - iseekable=false; - SYSTEMTIME st; GetLocalTime(&st); - FILETIME ft; SystemTimeToFileTime(&st,&ft); - WORD dosdate,dostime; FileTimeToDosDateTime(&ft,&dosdate,&dostime); - times.atime = filetime2timet(ft); - times.mtime = times.atime; - times.ctime = times.atime; - timestamp = (WORD)dostime | (((DWORD)dosdate)<<16); - return ZR_OK; -} - -unsigned TZip::sread(TState &s,char *buf,unsigned size) -{ // static - TZip *zip = (TZip*)s.param; - return zip->read(buf,size); -} - -unsigned TZip::read(char *buf, unsigned size) -{ if (bufin!=0) - { if (posin>=lenin) return 0; // end of input - ulg red = lenin-posin; - if (red>size) red=size; - memcpy(buf, bufin+posin, red); - posin += red; - ired += red; - crc = crc32(crc, (uch*)buf, red); - return red; - } - else if (hfin!=0) - { DWORD red; - BOOL ok = ReadFile(hfin,buf,size,&red,NULL); - if (!ok) return 0; - ired += red; - crc = crc32(crc, (uch*)buf, red); - return red; - } - else {oerr=ZR_NOTINITED; return 0;} -} - -ZRESULT TZip::iclose() -{ if (selfclosehf && hfin!=0) CloseHandle(hfin); hfin=0; - bool mismatch = (isize!=-1 && isize!=ired); - isize=ired; // and crc has been being updated anyway - if (mismatch) return ZR_MISSIZE; - else return ZR_OK; -} - - - -ZRESULT TZip::ideflate(TZipFileInfo *zfi) -{ TState state; - state.readfunc=sread; state.flush_outbuf=sflush; - state.param=this; state.level=8; state.seekable=iseekable; state.err=NULL; - // the following line will make ct_init realise it has to perform the init - state.ts.static_dtree[0].dl.len = 0; - // It would be nicer if I could figure out precisely which data had to - // be initted each time, and which didn't, but that's kind of difficult. - // Maybe for the next version... - // - bi_init(state,buf, sizeof(buf), TRUE); // it used to be just 1024-size, not 16384 as here - ct_init(state,&zfi->att); - lm_init(state,state.level, &zfi->flg); - ulg sz = deflate(state); - csize=sz; - if (state.err!=NULL) return ZR_FLATE; - else return ZR_OK; -} - -ZRESULT TZip::istore() -{ ulg size=0; - for (;;) - { unsigned int cin=read(buf,16384); if (cin<=0 || cin==(unsigned int)EOF) break; - unsigned int cout = write(buf,cin); if (cout!=cin) return ZR_MISSIZE; - size += cin; - } - csize=size; - return ZR_OK; -} - - - - -ZRESULT TZip::Add(const char *odstzn, void *src,unsigned int len, DWORD flags) -{ - if (oerr) - return ZR_FAILED; - if (hasputcen) - return ZR_ENDED; - - // zip has its own notion of what its names should look like: i.e. dir/file.stuff - char dstzn[MAX_PATH]; - Q_strncpy(dstzn, odstzn, sizeof(dstzn)); - if (*dstzn == 0) - return ZR_ARGS; - char *d=dstzn; - while (*d != 0) - { - if (*d == '\\') - *d = '/'; d++; - } - bool isdir = (flags==ZIP_FOLDER); - bool needs_trailing_slash = (isdir && dstzn[strlen(dstzn)-1]!='/'); - int method=DEFLATE; - if (isdir || HasZipSuffix(dstzn)) - method=STORE; - - // now open whatever was our input source: - ZRESULT openres; - if (flags==ZIP_FILENAME) - openres=open_file((const TCHAR*)src); - else if (flags==ZIP_HANDLE) - openres=open_handle((HANDLE)src,len); - else if (flags==ZIP_MEMORY) - openres=open_mem(src,len); - else if (flags==ZIP_FOLDER) - openres=open_dir(); - else return ZR_ARGS; - if (openres!=ZR_OK) - return openres; - - // A zip "entry" consists of a local header (which includes the file name), - // then the compressed data, and possibly an extended local header. - - // Initialize the local header - TZipFileInfo zfi; zfi.nxt=NULL; - Q_strncpy(zfi.name, "",sizeof(zfi.name)); - Q_strncpy(zfi.iname, dstzn,sizeof(zfi.iname)); - zfi.nam=strlen(zfi.iname); - if (needs_trailing_slash) - { - Q_strncat(zfi.iname, "/",sizeof(zfi.iname)); - zfi.nam++; - } - Q_strncpy(zfi.zname,"",sizeof(zfi.zname)); - zfi.extra=NULL; zfi.ext=0; // extra header to go after this compressed data, and its length - zfi.cextra=NULL; zfi.cext=0; // extra header to go in the central end-of-zip directory, and its length - zfi.comment=NULL; zfi.com=0; // comment, and its length - zfi.mark = 1; - zfi.dosflag = 0; - zfi.att = (ush)BINARY; - zfi.vem = (ush)0xB17; // 0xB00 is win32 os-code. 0x17 is 23 in decimal: zip 2.3 - zfi.ver = (ush)20; // Needs PKUNZIP 2.0 to unzip it - zfi.tim = timestamp; - // Even though we write the header now, it will have to be rewritten, since we don't know compressed size or crc. - zfi.crc = 0; // to be updated later - zfi.flg = 8; // 8 means 'there is an extra header'. Assume for the moment that we need it. - zfi.lflg = zfi.flg; // to be updated later - zfi.how = (ush)method; // to be updated later - zfi.siz = (ulg)(method==STORE && isize>=0 ? isize : 0); // to be updated later - zfi.len = (ulg)(isize); // to be updated later - zfi.dsk = 0; - zfi.atx = attr; - zfi.off = writ+ooffset; // offset within file of the start of this local record - // stuff the 'times' structure into zfi.extra - char xloc[EB_L_UT_SIZE]; - zfi.extra=xloc; - zfi.ext=EB_L_UT_SIZE; - char xcen[EB_C_UT_SIZE]; - zfi.cextra=xcen; - zfi.cext=EB_C_UT_SIZE; - xloc[0] = 'U'; - xloc[1] = 'T'; - xloc[2] = EB_UT_LEN(3); // length of data part of e.f. - xloc[3] = 0; - xloc[4] = EB_UT_FL_MTIME | EB_UT_FL_ATIME | EB_UT_FL_CTIME; - xloc[5] = (char)(times.mtime); - xloc[6] = (char)(times.mtime >> 8); - xloc[7] = (char)(times.mtime >> 16); - xloc[8] = (char)(times.mtime >> 24); - xloc[9] = (char)(times.atime); - xloc[10] = (char)(times.atime >> 8); - xloc[11] = (char)(times.atime >> 16); - xloc[12] = (char)(times.atime >> 24); - xloc[13] = (char)(times.ctime); - xloc[14] = (char)(times.ctime >> 8); - xloc[15] = (char)(times.ctime >> 16); - xloc[16] = (char)(times.ctime >> 24); - memcpy(zfi.cextra,zfi.extra,EB_C_UT_SIZE); - zfi.cextra[EB_LEN] = EB_UT_LEN(1); - - - // (1) Start by writing the local header: - int r = putlocal(&zfi,swrite,this); - if (r!=ZE_OK) - { - iclose(); - return ZR_WRITE; - } - writ += 4 + LOCHEAD + (unsigned int)zfi.nam + (unsigned int)zfi.ext; - if (oerr!=ZR_OK) - { - iclose(); - return oerr; - } - - //(2) Write deflated/stored file to zip file - ZRESULT writeres=ZR_OK; - if (!isdir && method==DEFLATE) - writeres=ideflate(&zfi); - else if (!isdir && method==STORE) - writeres=istore(); - else if (isdir) - csize=0; - iclose(); - writ += csize; - if (oerr!=ZR_OK) - return oerr; - if (writeres!=ZR_OK) - return ZR_WRITE; - - // (3) Either rewrite the local header with correct information... - bool first_header_has_size_right = (zfi.siz==csize); - zfi.crc = crc; - zfi.siz = csize; - zfi.len = isize; - if (ocanseek) - { - zfi.how = (ush)method; - if ((zfi.flg & 1) == 0) - zfi.flg &= ~8; // clear the extended local header flag - zfi.lflg = zfi.flg; - // rewrite the local header: - if (!oseek(zfi.off-ooffset)) - return ZR_SEEK; - if ((r = putlocal(&zfi, swrite,this)) != ZE_OK) - return ZR_WRITE; - if (!oseek(writ)) - return ZR_SEEK; - } - else - { - // (4) ... or put an updated header at the end - if (zfi.how != (ush) method) - return ZR_NOCHANGE; - if (method==STORE && !first_header_has_size_right) - return ZR_NOCHANGE; - if ((r = putextended(&zfi, swrite,this)) != ZE_OK) - return ZR_WRITE; - writ += 16L; - zfi.flg = zfi.lflg; // if flg modified by inflate, for the central index - } - if (oerr!=ZR_OK) - return oerr; - - // Keep a copy of the zipfileinfo, for our end-of-zip directory - char *cextra = new char[zfi.cext]; - memcpy(cextra,zfi.cextra,zfi.cext); zfi.cextra=cextra; - TZipFileInfo *pzfi = new TZipFileInfo; - memcpy(pzfi,&zfi,sizeof(zfi)); - if (zfis==NULL) - zfis=pzfi; - else - { - TZipFileInfo *z=zfis; - while (z->nxt!=NULL) - z=z->nxt; - z->nxt=pzfi; - } - return ZR_OK; -} - -ZRESULT TZip::AddCentral() -{ // write central directory - int numentries = 0; - ulg pos_at_start_of_central = writ; - //ulg tot_unc_size=0, tot_compressed_size=0; - bool okay=true; - for (TZipFileInfo *zfi=zfis; zfi!=NULL; ) - { if (okay) - { int res = putcentral(zfi, swrite,this); - if (res!=ZE_OK) okay=false; - } - writ += 4 + CENHEAD + (unsigned int)zfi->nam + (unsigned int)zfi->cext + (unsigned int)zfi->com; - //tot_unc_size += zfi->len; - //tot_compressed_size += zfi->siz; - numentries++; - // - TZipFileInfo *zfinext = zfi->nxt; - if (zfi->cextra!=0) delete[] zfi->cextra; - delete zfi; - zfi = zfinext; - } - ulg center_size = writ - pos_at_start_of_central; - if (okay) - { int res = putend(numentries, center_size, pos_at_start_of_central+ooffset, 0, NULL, swrite,this); - if (res!=ZE_OK) okay=false; - writ += 4 + ENDHEAD + 0; - } - if (!okay) return ZR_WRITE; - return ZR_OK; -} - - - - - -ZRESULT lasterrorZ=ZR_OK; - -unsigned int FormatZipMessageZ(ZRESULT code, char *buf,unsigned int len) -{ if (code==ZR_RECENT) code=lasterrorZ; - const char *msg="unknown zip result code"; - switch (code) - { case ZR_OK: msg="Success"; break; - case ZR_NODUPH: msg="Culdn't duplicate handle"; break; - case ZR_NOFILE: msg="Couldn't create/open file"; break; - case ZR_NOALLOC: msg="Failed to allocate memory"; break; - case ZR_WRITE: msg="Error writing to file"; break; - case ZR_NOTFOUND: msg="File not found in the zipfile"; break; - case ZR_MORE: msg="Still more data to unzip"; break; - case ZR_CORRUPT: msg="Zipfile is corrupt or not a zipfile"; break; - case ZR_READ: msg="Error reading file"; break; - case ZR_ARGS: msg="Caller: faulty arguments"; break; - case ZR_PARTIALUNZ: msg="Caller: the file had already been partially unzipped"; break; - case ZR_NOTMMAP: msg="Caller: can only get memory of a memory zipfile"; break; - case ZR_MEMSIZE: msg="Caller: not enough space allocated for memory zipfile"; break; - case ZR_FAILED: msg="Caller: there was a previous error"; break; - case ZR_ENDED: msg="Caller: additions to the zip have already been ended"; break; - case ZR_ZMODE: msg="Caller: mixing creation and opening of zip"; break; - case ZR_NOTINITED: msg="Zip-bug: internal initialisation not completed"; break; - case ZR_SEEK: msg="Zip-bug: trying to seek the unseekable"; break; - case ZR_MISSIZE: msg="Zip-bug: the anticipated size turned out wrong"; break; - case ZR_NOCHANGE: msg="Zip-bug: tried to change mind, but not allowed"; break; - case ZR_FLATE: msg="Zip-bug: an internal error during flation"; break; - } - unsigned int mlen=(unsigned int)strlen(msg); - if (buf==0 || len==0) return mlen; - unsigned int n=mlen; if (n+1>len) n=len-1; - Q_strncpy(buf, msg,n); buf[n]=0; - return mlen; -} - - - -typedef struct -{ DWORD flag; - TZip *zip; -} TZipHandleData; - - -HZIP CreateZipZ(void *z,unsigned int len,DWORD flags) -{ - _tzset(); - TZip *zip = new TZip(); - lasterrorZ = zip->Create(z,len,flags); - if (lasterrorZ != ZR_OK) - { - delete zip; - return 0; - } - TZipHandleData *han = new TZipHandleData; - han->flag = 2; - han->zip = zip; - return (HZIP)han; -} - -ZRESULT ZipAdd(HZIP hz, const TCHAR *dstzn, void *src, unsigned int len, DWORD flags) -{ - if (hz == 0) - { - lasterrorZ = ZR_ARGS; - return ZR_ARGS; - } - TZipHandleData *han = (TZipHandleData*)hz; - if (han->flag != 2) - { - lasterrorZ = ZR_ZMODE; - return ZR_ZMODE; - } - TZip *zip = han->zip; - - - if (flags == ZIP_FILENAME) - { - char szDest[MAX_PATH*2]; - memset(szDest, 0, sizeof(szDest)); - -#ifdef _UNICODE - // need to convert Unicode dest to ANSI - int nActualChars = WideCharToMultiByte(CP_ACP, // code page - 0, // performance and mapping flags - (LPCWSTR) dstzn, // wide-character string - -1, // number of chars in string - szDest, // buffer for new string - MAX_PATH*2-2, // size of buffer - NULL, // default for unmappable chars - NULL); // set when default char used - if (nActualChars == 0) - return ZR_ARGS; -#else - Q_strncpy(szDest, dstzn, sizeof(szDest)); -#endif - - lasterrorZ = zip->Add(szDest, src, len, flags); - } - else - { - lasterrorZ = zip->Add((char *)dstzn, src, len, flags); - } - - return lasterrorZ; -} - -ZRESULT ZipGetMemory(HZIP hz, void **buf, unsigned long *len) -{ if (hz==0) {if (buf!=0) *buf=0; if (len!=0) *len=0; lasterrorZ=ZR_ARGS;return ZR_ARGS;} - TZipHandleData *han = (TZipHandleData*)hz; - if (han->flag!=2) {lasterrorZ=ZR_ZMODE;return ZR_ZMODE;} - TZip *zip = han->zip; - lasterrorZ = zip->GetMemory(buf,len); - return lasterrorZ; -} - -ZRESULT CloseZipZ(HZIP hz) -{ if (hz==0) {lasterrorZ=ZR_ARGS;return ZR_ARGS;} - TZipHandleData *han = (TZipHandleData*)hz; - if (han->flag!=2) {lasterrorZ=ZR_ZMODE;return ZR_ZMODE;} - TZip *zip = han->zip; - lasterrorZ = zip->Close(); - delete zip; - delete han; - return lasterrorZ; -} - -bool IsZipHandleZ(HZIP hz) -{ if (hz==0) return true; - TZipHandleData *han = (TZipHandleData*)hz; - return (han->flag==2); -} - diff --git a/public/appframework/AppFramework.h b/public/appframework/AppFramework.h deleted file mode 100644 index 7884e8f22..000000000 --- a/public/appframework/AppFramework.h +++ /dev/null @@ -1,138 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: An application framework -// -// $Revision: $ -// $NoKeywords: $ -//===========================================================================// - -#ifndef APPFRAMEWORK_H -#define APPFRAMEWORK_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "appframework/IAppSystemGroup.h" - - -//----------------------------------------------------------------------------- -// Gets the application instance.. -//----------------------------------------------------------------------------- -void *GetAppInstance(); - - -//----------------------------------------------------------------------------- -// Sets the application instance, should only be used if you're not calling AppMain. -//----------------------------------------------------------------------------- -void SetAppInstance( void* hInstance ); - - -//----------------------------------------------------------------------------- -// Main entry point for the application -//----------------------------------------------------------------------------- -int AppMain( void* hInstance, void* hPrevInstance, const char* lpCmdLine, int nCmdShow, CAppSystemGroup *pAppSystemGroup ); -int AppMain( int argc, char **argv, CAppSystemGroup *pAppSystemGroup ); - - -//----------------------------------------------------------------------------- -// Used to startup/shutdown the application -//----------------------------------------------------------------------------- -int AppStartup( void* hInstance, void* hPrevInstance, const char* lpCmdLine, int nCmdShow, CAppSystemGroup *pAppSystemGroup ); -int AppStartup( int argc, char **argv, CAppSystemGroup *pAppSystemGroup ); -void AppShutdown( CAppSystemGroup *pAppSystemGroup ); - - -//----------------------------------------------------------------------------- -// Macros to create singleton application objects for windowed + console apps -//----------------------------------------------------------------------------- -#if !defined( _X360 ) -#define DEFINE_WINDOWED_APPLICATION_OBJECT_GLOBALVAR( _globalVarName ) \ - int __stdcall WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) \ - { \ - return AppMain( hInstance, hPrevInstance, lpCmdLine, nCmdShow, &_globalVarName ); \ - } -#else -#define DEFINE_WINDOWED_APPLICATION_OBJECT_GLOBALVAR( _globalVarName ) \ - void __cdecl main() \ - { \ - AppMain( (HINSTANCE)1, (HINSTANCE)0, NULL, 0, &_globalVarName ); \ - } -#endif - -#if !defined( _X360 ) -#define DEFINE_CONSOLE_APPLICATION_OBJECT_GLOBALVAR( _globalVarName ) \ - int main( int argc, char **argv ) \ - { \ - return AppMain( argc, argv, &_globalVarName ); \ - } -#else -#define DEFINE_CONSOLE_APPLICATION_OBJECT_GLOBALVAR( _globalVarName ) \ - void __cdecl main() \ - { \ - AppMain( 0, (char**)NULL, &_globalVarName ); \ - } -#endif - -#define DEFINE_WINDOWED_APPLICATION_OBJECT( _className ) \ - static _className __s_ApplicationObject; \ - DEFINE_WINDOWED_APPLICATION_OBJECT_GLOBALVAR( __s_ApplicationObject ) - -#define DEFINE_CONSOLE_APPLICATION_OBJECT( _className ) \ - static _className __s_ApplicationObject; \ - DEFINE_CONSOLE_APPLICATION_OBJECT_GLOBALVAR( __s_ApplicationObject ) - - -//----------------------------------------------------------------------------- -// This class is a helper class used for steam-based applications. -// It loads up the file system in preparation for using it to load other -// required modules from steam. -//----------------------------------------------------------------------------- -class CSteamApplication : public CAppSystemGroup -{ - typedef CAppSystemGroup BaseClass; - -public: - CSteamApplication( CSteamAppSystemGroup *pAppSystemGroup ); - - // Implementation of IAppSystemGroup - virtual bool Create( ); - virtual bool PreInit( ); - virtual int Main( ); - virtual void PostShutdown(); - virtual void Destroy(); - - // Use this version in cases where you can't control the main loop and - // expect to be ticked - virtual int Startup(); - virtual void Shutdown(); - -protected: - IFileSystem *m_pFileSystem; - CSteamAppSystemGroup *m_pChildAppSystemGroup; - bool m_bSteam; -}; - - -//----------------------------------------------------------------------------- -// Macros to help create singleton application objects for windowed + console steam apps -//----------------------------------------------------------------------------- -#define DEFINE_WINDOWED_STEAM_APPLICATION_OBJECT_GLOBALVAR( _className, _varName ) \ - static CSteamApplication __s_SteamApplicationObject( &_varName ); \ - DEFINE_WINDOWED_APPLICATION_OBJECT_GLOBALVAR( __s_SteamApplicationObject ) - -#define DEFINE_WINDOWED_STEAM_APPLICATION_OBJECT( _className ) \ - static _className __s_ApplicationObject; \ - static CSteamApplication __s_SteamApplicationObject( &__s_ApplicationObject ); \ - DEFINE_WINDOWED_APPLICATION_OBJECT_GLOBALVAR( __s_SteamApplicationObject ) - -#define DEFINE_CONSOLE_STEAM_APPLICATION_OBJECT_GLOBALVAR( _className, _varName ) \ - static CSteamApplication __s_SteamApplicationObject( &_varName ); \ - DEFINE_CONSOLE_APPLICATION_OBJECT_GLOBALVAR( __s_SteamApplicationObject ) - -#define DEFINE_CONSOLE_STEAM_APPLICATION_OBJECT( _className ) \ - static _className __s_ApplicationObject; \ - static CSteamApplication __s_SteamApplicationObject( &__s_ApplicationObject ); \ - DEFINE_CONSOLE_APPLICATION_OBJECT_GLOBALVAR( __s_SteamApplicationObject ) - -#endif // APPFRAMEWORK_H diff --git a/public/appframework/IAppSystem.h b/public/appframework/IAppSystem.h deleted file mode 100644 index a82b510c5..000000000 --- a/public/appframework/IAppSystem.h +++ /dev/null @@ -1,122 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: An application framework -// -// $Revision: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef IAPPSYSTEM_H -#define IAPPSYSTEM_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/interface.h" - - -//----------------------------------------------------------------------------- -// Client systems are singleton objects in the client codebase responsible for -// various tasks -// The order in which the client systems appear in this list are the -// order in which they are initialized and updated. They are shut down in -// reverse order from which they are initialized. -//----------------------------------------------------------------------------- - -enum InitReturnVal_t -{ - INIT_FAILED = 0, - INIT_OK, - - INIT_LAST_VAL, -}; - - -abstract_class IAppSystem -{ -public: - // Here's where the app systems get to learn about each other - virtual bool Connect( CreateInterfaceFn factory ) = 0; - virtual void Disconnect() = 0; - - // Here's where systems can access other interfaces implemented by this object - // Returns NULL if it doesn't implement the requested interface - virtual void *QueryInterface( const char *pInterfaceName ) = 0; - - // Init, shutdown - virtual InitReturnVal_t Init() = 0; - virtual void Shutdown() = 0; -}; - - -//----------------------------------------------------------------------------- -// Helper empty implementation of an IAppSystem -//----------------------------------------------------------------------------- -template< class IInterface > -class CBaseAppSystem : public IInterface -{ -public: - // Here's where the app systems get to learn about each other - virtual bool Connect( CreateInterfaceFn factory ) { return true; } - virtual void Disconnect() {} - - // Here's where systems can access other interfaces implemented by this object - // Returns NULL if it doesn't implement the requested interface - virtual void *QueryInterface( const char *pInterfaceName ) { return NULL; } - - // Init, shutdown - virtual InitReturnVal_t Init() { return INIT_OK; } - virtual void Shutdown() {} -}; - - -//----------------------------------------------------------------------------- -// Helper implementation of an IAppSystem for tier0 -//----------------------------------------------------------------------------- -template< class IInterface > -class CTier0AppSystem : public CBaseAppSystem< IInterface > -{ -public: - CTier0AppSystem( bool bIsPrimaryAppSystem = true ) - { - m_bIsPrimaryAppSystem = bIsPrimaryAppSystem; - } - -protected: - // NOTE: a single DLL may have multiple AppSystems it's trying to - // expose. If this is true, you must return true from only - // one of those AppSystems; not doing so will cause all static - // libraries connected to it to connect/disconnect multiple times - - // NOTE: We don't do this as a virtual function to avoid - // having to up the version on all interfaces - bool IsPrimaryAppSystem() { return m_bIsPrimaryAppSystem; } - -private: - bool m_bIsPrimaryAppSystem; -}; - - -//----------------------------------------------------------------------------- -// This is the version of IAppSystem shipped 10/15/04 -// NOTE: Never change this!!! -//----------------------------------------------------------------------------- -abstract_class IAppSystemV0 -{ -public: - // Here's where the app systems get to learn about each other - virtual bool Connect( CreateInterfaceFn factory ) = 0; - virtual void Disconnect() = 0; - - // Here's where systems can access other interfaces implemented by this object - // Returns NULL if it doesn't implement the requested interface - virtual void *QueryInterface( const char *pInterfaceName ) = 0; - - // Init, shutdown - virtual InitReturnVal_t Init() = 0; - virtual void Shutdown() = 0; -}; - -#endif // IAPPSYSTEM_H - diff --git a/public/appframework/IAppSystemGroup.h b/public/appframework/IAppSystemGroup.h deleted file mode 100644 index bd6fe6d2c..000000000 --- a/public/appframework/IAppSystemGroup.h +++ /dev/null @@ -1,265 +0,0 @@ -//======== (C) Copyright 1999, 2000 Valve, L.L.C. All rights reserved. ======== -// -// The copyright to the contents herein is the property of Valve, L.L.C. -// The contents may be used and/or copied only with the written permission of -// Valve, L.L.C., or in accordance with the terms and conditions stipulated in -// the agreement/contract under which the contents have been supplied. -// -// Purpose: Defines a group of app systems that all have the same lifetime -// that need to be connected/initialized, etc. in a well-defined order -// -// $Revision: $ -// $NoKeywords: $ -//============================================================================= - -#ifndef IAPPSYSTEMGROUP_H -#define IAPPSYSTEMGROUP_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "tier1/interface.h" -#include "tier1/utlvector.h" -#include "tier1/utldict.h" -#include "IAppSystem.h" - -//----------------------------------------------------------------------------- -// forward declarations -//----------------------------------------------------------------------------- -class IAppSystem; -class CSysModule; -class IBaseInterface; -class IFileSystem; - -//----------------------------------------------------------------------------- -// Handle to a DLL -//----------------------------------------------------------------------------- -typedef int AppModule_t; - -enum -{ - APP_MODULE_INVALID = (AppModule_t)~0 -}; - - -//----------------------------------------------------------------------------- -// NOTE: The following methods must be implemented in your application -// although they can be empty implementations if you like... -//----------------------------------------------------------------------------- -abstract_class IAppSystemGroup -{ -public: - // An installed application creation function, you should tell the group - // the DLLs and the singleton interfaces you want to instantiate. - // Return false if there's any problems and the app will abort - virtual bool Create( ) = 0; - - // Allow the application to do some work after AppSystems are connected but - // they are all Initialized. - // Return false if there's any problems and the app will abort - virtual bool PreInit() = 0; - - // Main loop implemented by the application - virtual int Main( ) = 0; - - // Allow the application to do some work after all AppSystems are shut down - virtual void PostShutdown() = 0; - - // Call an installed application destroy function, occurring after all modules - // are unloaded - virtual void Destroy() = 0; -}; - - -//----------------------------------------------------------------------------- -// Specifies a module + interface name for initialization -//----------------------------------------------------------------------------- -struct AppSystemInfo_t -{ - const char *m_pModuleName; - const char *m_pInterfaceName; -}; - - -//----------------------------------------------------------------------------- -// This class represents a group of app systems that all have the same lifetime -// that need to be connected/initialized, etc. in a well-defined order -//----------------------------------------------------------------------------- -class CAppSystemGroup : public IAppSystemGroup -{ -public: - // Used to determine where we exited out from the system - enum AppSystemGroupStage_t - { - CREATION = 0, - CONNECTION, - PREINITIALIZATION, - INITIALIZATION, - SHUTDOWN, - POSTSHUTDOWN, - DISCONNECTION, - DESTRUCTION, - - NONE, // This means no error - }; - -public: - // constructor - CAppSystemGroup( CAppSystemGroup *pParentAppSystem = NULL ); - - // Runs the app system group. - // First, modules are loaded, next they are connected, followed by initialization - // Then Main() is run - // Then modules are shut down, disconnected, and unloaded - int Run( ); - - // Use this version in cases where you can't control the main loop and - // expect to be ticked - virtual int Startup(); - virtual void Shutdown(); - - // Returns the stage at which the app system group ran into an error - AppSystemGroupStage_t GetErrorStage() const; - -protected: - // These methods are meant to be called by derived classes of CAppSystemGroup - - // Methods to load + unload DLLs - AppModule_t LoadModule( const char *pDLLName ); - AppModule_t LoadModule( CreateInterfaceFn factory ); - - // Method to add various global singleton systems - IAppSystem *AddSystem( AppModule_t module, const char *pInterfaceName ); - void AddSystem( IAppSystem *pAppSystem, const char *pInterfaceName ); - - // Simpler method of doing the LoadModule/AddSystem thing. - // Make sure the last AppSystemInfo has a NULL module name - bool AddSystems( AppSystemInfo_t *pSystems ); - - // Method to look up a particular named system... - void *FindSystem( const char *pInterfaceName ); - - // Gets at a class factory for the topmost appsystem group in an appsystem stack - static CreateInterfaceFn GetFactory(); - -private: - int OnStartup(); - void OnShutdown(); - - void UnloadAllModules( ); - void RemoveAllSystems(); - - // Method to connect/disconnect all systems - bool ConnectSystems( ); - void DisconnectSystems(); - - // Method to initialize/shutdown all systems - InitReturnVal_t InitSystems(); - void ShutdownSystems(); - - // Gets at the parent appsystem group - CAppSystemGroup *GetParent(); - - // Loads a module the standard way - virtual CSysModule *LoadModuleDLL( const char *pDLLName ); - - void ReportStartupFailure( int nErrorStage, int nSysIndex ); - - struct Module_t - { - CSysModule *m_pModule; - CreateInterfaceFn m_Factory; - char *m_pModuleName; - }; - - CUtlVector m_Modules; - CUtlVector m_Systems; - CUtlDict m_SystemDict; - CAppSystemGroup *m_pParentAppSystem; - AppSystemGroupStage_t m_nErrorStage; - - friend void *AppSystemCreateInterfaceFn(const char *pName, int *pReturnCode); - friend class CSteamAppSystemGroup; -}; - - -//----------------------------------------------------------------------------- -// This class represents a group of app systems that are loaded through steam -//----------------------------------------------------------------------------- -class CSteamAppSystemGroup : public CAppSystemGroup -{ -public: - CSteamAppSystemGroup( IFileSystem *pFileSystem = NULL, CAppSystemGroup *pParentAppSystem = NULL ); - - // Used by CSteamApplication to set up necessary pointers if we can't do it in the constructor - void Setup( IFileSystem *pFileSystem, CAppSystemGroup *pParentAppSystem ); - -protected: - // Sets up the search paths - bool SetupSearchPaths( const char *pStartingDir, bool bOnlyUseStartingDir, bool bIsTool ); - - // Returns the game info path. Only works if you've called SetupSearchPaths first - const char *GetGameInfoPath() const; - -private: - virtual CSysModule *LoadModuleDLL( const char *pDLLName ); - - IFileSystem *m_pFileSystem; - char m_pGameInfoPath[ MAX_PATH ]; -}; - - -//----------------------------------------------------------------------------- -// Helper empty decorator implementation of an IAppSystemGroup -//----------------------------------------------------------------------------- -template< class CBaseClass > -class CDefaultAppSystemGroup : public CBaseClass -{ -public: - virtual bool Create( ) { return true; } - virtual bool PreInit() { return true; } - virtual void PostShutdown() {} - virtual void Destroy() {} -}; - - -//----------------------------------------------------------------------------- -// Special helper for game info directory suggestion -//----------------------------------------------------------------------------- - -class CFSSteamSetupInfo; // Forward declaration - -// -// SuggestGameInfoDirFn_t -// Game info suggestion function. -// Provided by the application to possibly detect the suggested game info -// directory and initialize all the game-info-related systems appropriately. -// Parameters: -// pFsSteamSetupInfo steam file system setup information if available. -// pchPathBuffer buffer to hold game info directory path on return. -// nBufferLength length of the provided buffer to hold game info directory path. -// pbBubbleDirectories should contain "true" on return to bubble the directories up searching for game info file. -// Return values: -// Returns "true" if the game info directory path suggestion is available and -// was successfully copied into the provided buffer. -// Returns "false" otherwise, interpreted that no suggestion will be used. -// -typedef bool ( * SuggestGameInfoDirFn_t ) ( CFSSteamSetupInfo const *pFsSteamSetupInfo, char *pchPathBuffer, int nBufferLength, bool *pbBubbleDirectories ); - -// -// SetSuggestGameInfoDirFn -// Installs the supplied game info directory suggestion function. -// Parameters: -// pfnNewFn the new game info directory suggestion function. -// Returns: -// The previously installed suggestion function or NULL if none was installed before. -// This function never fails. -// -SuggestGameInfoDirFn_t SetSuggestGameInfoDirFn( SuggestGameInfoDirFn_t pfnNewFn ); - - -#endif // APPSYSTEMGROUP_H - - diff --git a/public/appframework/VguiMatSysApp.h b/public/appframework/VguiMatSysApp.h deleted file mode 100644 index b3f57b01b..000000000 --- a/public/appframework/VguiMatSysApp.h +++ /dev/null @@ -1,71 +0,0 @@ -//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. =========== -// -// The copyright to the contents herein is the property of Valve, L.L.C. -// The contents may be used and/or copied only with the written permission of -// Valve, L.L.C., or in accordance with the terms and conditions stipulated in -// the agreement/contract under which the contents have been supplied. -// -// $Header: $ -// $NoKeywords: $ -// -// Material editor -//============================================================================= - -#ifndef VGUIMATSYSAPP_H -#define VGUIMATSYSAPP_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "appframework/tier3app.h" - - -//----------------------------------------------------------------------------- -// The application object -//----------------------------------------------------------------------------- -class CVguiMatSysApp : public CVguiSteamApp -{ - typedef CVguiSteamApp BaseClass; - -public: - CVguiMatSysApp(); - - // Methods of IApplication - virtual bool Create(); - virtual bool PreInit(); - virtual void PostShutdown(); - virtual void Destroy(); - -protected: - void AppPumpMessages(); - - // Sets the video mode - bool SetVideoMode( ); - - // Returns the window - void* GetAppWindow(); - - // Gets the window size - int GetWindowWidth() const; - int GetWindowHeight() const; - - // Sets up the game path - bool SetupSearchPaths( const char *pStartingDir, bool bOnlyUseStartingDir, bool bIsTool ); - -private: - // Returns the app name - virtual const char *GetAppName() = 0; - virtual bool AppUsesReadPixels() { return false; } - - // Creates the app window - virtual void *CreateAppWindow( char const *pTitle, bool bWindowed, int w, int h ); - - void *m_HWnd; - int m_nWidth; - int m_nHeight; -}; - - -#endif // VGUIMATSYSAPP_H diff --git a/public/appframework/tier2app.h b/public/appframework/tier2app.h deleted file mode 100644 index 2a90f9003..000000000 --- a/public/appframework/tier2app.h +++ /dev/null @@ -1,85 +0,0 @@ -//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. =========== -// -// The copyright to the contents herein is the property of Valve, L.L.C. -// The contents may be used and/or copied only with the written permission of -// Valve, L.L.C., or in accordance with the terms and conditions stipulated in -// the agreement/contract under which the contents have been supplied. -// -// $Header: $ -// $NoKeywords: $ -// -// The application object for apps that use tier2 -//============================================================================= - -#ifndef TIER2APP_H -#define TIER2APP_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "appframework/AppFramework.h" -#include "tier2/tier2dm.h" -#include "tier1/convar.h" - - -//----------------------------------------------------------------------------- -// The application object for apps that use tier2 -//----------------------------------------------------------------------------- -class CTier2SteamApp : public CSteamAppSystemGroup -{ - typedef CSteamAppSystemGroup BaseClass; - -public: - // Methods of IApplication - virtual bool PreInit() - { - CreateInterfaceFn factory = GetFactory(); - ConnectTier1Libraries( &factory, 1 ); - ConVar_Register( 0 ); - ConnectTier2Libraries( &factory, 1 ); - return true; - } - - virtual void PostShutdown() - { - DisconnectTier2Libraries(); - ConVar_Unregister(); - DisconnectTier1Libraries(); - } -}; - - -//----------------------------------------------------------------------------- -// The application object for apps that use tier2 and datamodel -//----------------------------------------------------------------------------- -class CTier2DmSteamApp : public CTier2SteamApp -{ - typedef CTier2SteamApp BaseClass; - -public: - // Methods of IApplication - virtual bool PreInit() - { - if ( !BaseClass::PreInit() ) - return false; - - CreateInterfaceFn factory = GetFactory(); - if ( !ConnectDataModel( factory ) ) - return false; - - InitReturnVal_t nRetVal = InitDataModel(); - return ( nRetVal == INIT_OK ); - } - - virtual void PostShutdown() - { - ShutdownDataModel(); - DisconnectDataModel(); - BaseClass::PostShutdown(); - } -}; - - -#endif // TIER2APP_H diff --git a/public/appframework/tier3app.h b/public/appframework/tier3app.h deleted file mode 100644 index caa6bfcb3..000000000 --- a/public/appframework/tier3app.h +++ /dev/null @@ -1,121 +0,0 @@ -//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. =========== -// -// The copyright to the contents herein is the property of Valve, L.L.C. -// The contents may be used and/or copied only with the written permission of -// Valve, L.L.C., or in accordance with the terms and conditions stipulated in -// the agreement/contract under which the contents have been supplied. -// -// $Header: $ -// $NoKeywords: $ -// -// The application objects for apps that use tier3 -//============================================================================= - -#ifndef TIER3APP_H -#define TIER3APP_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "appframework/tier2app.h" -#include "tier3/tier3.h" -#include "vgui_controls/Controls.h" - - -//----------------------------------------------------------------------------- -// The application object for apps that use tier3 -//----------------------------------------------------------------------------- -class CTier3SteamApp : public CTier2SteamApp -{ - typedef CTier2SteamApp BaseClass; - -public: - // Methods of IApplication - virtual bool PreInit() - { - if ( !BaseClass::PreInit() ) - return false; - - CreateInterfaceFn factory = GetFactory(); - ConnectTier3Libraries( &factory, 1 ); - return true; - } - - virtual void PostShutdown() - { - DisconnectTier3Libraries(); - BaseClass::PostShutdown(); - } -}; - - -//----------------------------------------------------------------------------- -// The application object for apps that use tier3 -//----------------------------------------------------------------------------- -class CTier3DmSteamApp : public CTier2DmSteamApp -{ - typedef CTier2DmSteamApp BaseClass; - -public: - // Methods of IApplication - virtual bool PreInit() - { - if ( !BaseClass::PreInit() ) - return false; - - CreateInterfaceFn factory = GetFactory(); - ConnectTier3Libraries( &factory, 1 ); - return true; - } - - virtual void PostShutdown() - { - DisconnectTier3Libraries(); - BaseClass::PostShutdown(); - } -}; - - -//----------------------------------------------------------------------------- -// The application object for apps that use vgui -//----------------------------------------------------------------------------- -class CVguiSteamApp : public CTier3SteamApp -{ - typedef CTier3SteamApp BaseClass; - -public: - // Methods of IApplication - virtual bool PreInit() - { - if ( !BaseClass::PreInit() ) - return false; - - CreateInterfaceFn factory = GetFactory(); - return vgui::VGui_InitInterfacesList( "CVguiSteamApp", &factory, 1 ); - } -}; - - -//----------------------------------------------------------------------------- -// The application object for apps that use vgui -//----------------------------------------------------------------------------- -class CVguiDmSteamApp : public CTier3DmSteamApp -{ - typedef CTier3DmSteamApp BaseClass; - -public: - // Methods of IApplication - virtual bool PreInit() - { - if ( !BaseClass::PreInit() ) - return false; - - CreateInterfaceFn factory = GetFactory(); - return vgui::VGui_InitInterfacesList( "CVguiSteamApp", &factory, 1 ); - } -}; - - -#endif // TIER3APP_H diff --git a/public/arraystack.h b/public/arraystack.h deleted file mode 100644 index 7bc5671ab..000000000 --- a/public/arraystack.h +++ /dev/null @@ -1,69 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ARRAYSTACK_H -#define ARRAYSTACK_H -#pragma once - -#include -#include "List.h" - -template class ArrayStack -{ -protected: - T *data; - int m_stackDepth; - int m_maxNumElements; - -public: - ArrayStack( int maxNumElements ) - { - data = new T[maxNumElements]; - m_maxNumElements = maxNumElements; - m_stackDepth = 0; - assert( data ); - } - - void Push( T elem ) - { - data[m_stackDepth++] = elem; - if( m_stackDepth > m_maxNumElements ) - { - printf( "ArrayStack overflow\n" ); - assert( 0 ); - } - } - - T Pop( void ) - { - if( m_stackDepth == 0 ) - { - printf( "ArrayStack underflow\n" ); - assert( 0 ); - } - return data[--m_stackDepth]; - } - - bool IsEmpty() - { - return ( m_stackDepth == 0 ); - } - - int GetDepth() - { - return m_stackDepth; - } -}; - - -#endif // ARRAYSTACK_H diff --git a/public/avi/iavi.h b/public/avi/iavi.h deleted file mode 100644 index 7ff3505d2..000000000 --- a/public/avi/iavi.h +++ /dev/null @@ -1,126 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// The copyright to the contents herein is the property of Valve, L.L.C. -// The contents may be used and/or copied only with the written permission of -// Valve, L.L.C., or in accordance with the terms and conditions stipulated in -// the agreement/contract under which the contents have been supplied. -// -//============================================================================= - -#ifndef IAVI_H -#define IAVI_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "appframework/IAppSystem.h" - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -struct BGR888_t; -class IMaterial; - - -//----------------------------------------------------------------------------- -// Parameters for creating a new AVI -//----------------------------------------------------------------------------- -struct AVIParams_t -{ - AVIParams_t() : - m_nFrameRate( 0 ), m_nFrameScale( 1 ), m_nWidth( 0 ), m_nHeight( 0 ), - m_nSampleRate( 0 ), m_nSampleBits( 0 ), m_nNumChannels( 0 ) - { - m_pFileName[ 0 ] = 0; - } - - char m_pFileName[ 256 ]; - char m_pPathID[ 256 ]; - - // fps = m_nFrameRate / m_nFrameScale - // for integer framerates, set framerate to the fps, and framescale to 1 - // for ntsc-style framerates like 29.97 (or 23.976 or 59.94), - // set framerate to 30,000 (or 24,000 or 60,000) and framescale to 1001 - // yes, framescale is an odd naming choice, but it matching MS's AVI api - int m_nFrameRate; - int m_nFrameScale; - - int m_nWidth; - int m_nHeight; - - // Sound/.wav info - int m_nSampleRate; - int m_nSampleBits; - int m_nNumChannels; -}; - - -//----------------------------------------------------------------------------- -// Handle to an AVI -//----------------------------------------------------------------------------- -typedef unsigned short AVIHandle_t; -enum -{ - AVIHANDLE_INVALID = (AVIHandle_t)~0 -}; - - -//----------------------------------------------------------------------------- -// Handle to an AVI material -//----------------------------------------------------------------------------- -typedef unsigned short AVIMaterial_t; -enum -{ - AVIMATERIAL_INVALID = (AVIMaterial_t)~0 -}; - - -//----------------------------------------------------------------------------- -// Main AVI interface -//----------------------------------------------------------------------------- -#define AVI_INTERFACE_VERSION "VAvi001" - -class IAvi : public IAppSystem -{ -public: - // Necessary to call this before any other AVI interface methods - virtual void SetMainWindow( void* hWnd ) = 0; - - // Start/stop recording an AVI - virtual AVIHandle_t StartAVI( const AVIParams_t& params ) = 0; - virtual void FinishAVI( AVIHandle_t handle ) = 0; - - // Add frames to an AVI - virtual void AppendMovieSound( AVIHandle_t h, short *buf, size_t bufsize ) = 0; - virtual void AppendMovieFrame( AVIHandle_t h, const BGR888_t *pRGBData ) = 0; - - // Create/destroy an AVI material (a materialsystem IMaterial) - virtual AVIMaterial_t CreateAVIMaterial( const char *pMaterialName, const char *pFileName, const char *pPathID ) = 0; - virtual void DestroyAVIMaterial( AVIMaterial_t hMaterial ) = 0; - - // Sets the time for an AVI material - virtual void SetTime( AVIMaterial_t hMaterial, float flTime ) = 0; - - // Gets the IMaterial associated with an AVI material - virtual IMaterial* GetMaterial( AVIMaterial_t hMaterial ) = 0; - - // Returns the max texture coordinate of the AVI - virtual void GetTexCoordRange( AVIMaterial_t hMaterial, float *pMaxU, float *pMaxV ) = 0; - - // Returns the frame size of the AVI (stored in a subrect of the material itself) - virtual void GetFrameSize( AVIMaterial_t hMaterial, int *pWidth, int *pHeight ) = 0; - - // Returns the frame rate of the AVI - virtual int GetFrameRate( AVIMaterial_t hMaterial ) = 0; - - // Returns the total frame count of the AVI - virtual int GetFrameCount( AVIMaterial_t hMaterial ) = 0; - - // Sets the frame for an AVI material (use instead of SetTime) - virtual void SetFrame( AVIMaterial_t hMaterial, float flFrame ) = 0; -}; - - - -#endif // IAVI_H diff --git a/public/avi/ibik.h b/public/avi/ibik.h deleted file mode 100644 index 2b8cc9108..000000000 --- a/public/avi/ibik.h +++ /dev/null @@ -1,121 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// The copyright to the contents herein is the property of Valve, L.L.C. -// The contents may be used and/or copied only with the written permission of -// Valve, L.L.C., or in accordance with the terms and conditions stipulated in -// the agreement/contract under which the contents have been supplied. -// -//============================================================================= - -#ifndef IBIK_H -#define IBIK_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "appframework/IAppSystem.h" - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -struct BGR888_t; -class IMaterial; - -//----------------------------------------------------------------------------- -// Parameters for creating a new BINK -//----------------------------------------------------------------------------- -struct BIKParams_t -{ - BIKParams_t() : - m_nFrameRate( 0 ), m_nFrameScale( 1 ), m_nWidth( 0 ), m_nHeight( 0 ), - m_nSampleRate( 0 ), m_nSampleBits( 0 ), m_nNumChannels( 0 ) - { - m_pFileName[ 0 ] = 0; - } - - char m_pFileName[ 256 ]; - char m_pPathID[ 256 ]; - - // fps = m_nFrameRate / m_nFrameScale - // for integer framerates, set framerate to the fps, and framescale to 1 - // for ntsc-style framerates like 29.97 (or 23.976 or 59.94), - // set framerate to 30,000 (or 24,000 or 60,000) and framescale to 1001 - // yes, framescale is an odd naming choice, but it matching MS's AVI api - int m_nFrameRate; - int m_nFrameScale; - - int m_nWidth; - int m_nHeight; - - // Sound/.wav info - int m_nSampleRate; - int m_nSampleBits; - int m_nNumChannels; -}; - -//----------------------------------------------------------------------------- -// Handle to an BINK -//----------------------------------------------------------------------------- -typedef unsigned short BIKHandle_t; -enum -{ - BIKHANDLE_INVALID = (BIKHandle_t)~0 -}; - - -//----------------------------------------------------------------------------- -// Handle to an BINK material -//----------------------------------------------------------------------------- -typedef unsigned short BIKMaterial_t; -enum -{ - BIKMATERIAL_INVALID = (BIKMaterial_t)~0 -}; - - -//----------------------------------------------------------------------------- -// Main AVI interface -//----------------------------------------------------------------------------- -#define BIK_INTERFACE_VERSION "VBik001" - -class IBik : public IAppSystem -{ -public: - // Create/destroy a BINK material (a materialsystem IMaterial) - virtual BIKMaterial_t CreateMaterial( const char *pMaterialName, const char *pFileName, const char *pPathID ) = 0; - virtual void DestroyMaterial( BIKMaterial_t hMaterial ) = 0; - - // Update the frame (if necessary) - virtual bool Update( BIKMaterial_t hMaterial ) = 0; - - // Gets the IMaterial associated with an BINK material - virtual IMaterial* GetMaterial( BIKMaterial_t hMaterial ) = 0; - - // Returns the max texture coordinate of the BINK - virtual void GetTexCoordRange( BIKMaterial_t hMaterial, float *pMaxU, float *pMaxV ) = 0; - - // Returns the frame size of the BINK (stored in a subrect of the material itself) - virtual void GetFrameSize( BIKMaterial_t hMaterial, int *pWidth, int *pHeight ) = 0; - - // Returns the frame rate of the BINK - virtual int GetFrameRate( BIKMaterial_t hMaterial ) = 0; - - // Returns the total frame count of the BINK - virtual int GetFrameCount( BIKMaterial_t hMaterial ) = 0; - - // Sets the frame for an BINK material (use instead of SetTime) - virtual void SetFrame( BIKMaterial_t hMaterial, float flFrame ) = 0; - -#if !defined( _X360 ) - // Sets the direct sound device that Bink will decode to - virtual bool SetDirectSoundDevice( void *pDevice ) = 0; -#else - //needs to be called after xaudio is initialized - virtual bool HookXAudio( void ) = 0; -#endif -}; - - - -#endif // IBIK_H diff --git a/public/basehandle.h b/public/basehandle.h deleted file mode 100644 index d353cb989..000000000 --- a/public/basehandle.h +++ /dev/null @@ -1,177 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef BASEHANDLE_H -#define BASEHANDLE_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "const.h" -#include "tier0/dbg.h" - - -class IHandleEntity; - - -// -------------------------------------------------------------------------------------------------- // -// CBaseHandle. -// -------------------------------------------------------------------------------------------------- // - -class CBaseHandle -{ -friend class CBaseEntityList; - -public: - - CBaseHandle(); - CBaseHandle( const CBaseHandle &other ); - CBaseHandle( unsigned long value ); - CBaseHandle( int iEntry, int iSerialNumber ); - - void Init( int iEntry, int iSerialNumber ); - void Term(); - - // Even if this returns true, Get() still can return return a non-null value. - // This just tells if the handle has been initted with any values. - bool IsValid() const; - - int GetEntryIndex() const; - int GetSerialNumber() const; - - int ToInt() const; - bool operator !=( const CBaseHandle &other ) const; - bool operator ==( const CBaseHandle &other ) const; - bool operator ==( const IHandleEntity* pEnt ) const; - bool operator !=( const IHandleEntity* pEnt ) const; - bool operator <( const CBaseHandle &other ) const; - bool operator <( const IHandleEntity* pEnt ) const; - - // Assign a value to the handle. - const CBaseHandle& operator=( const IHandleEntity *pEntity ); - const CBaseHandle& Set( const IHandleEntity *pEntity ); - - // Use this to dereference the handle. - // Note: this is implemented in game code (ehandle.h) - IHandleEntity* Get() const; - - -protected: - // The low NUM_SERIAL_BITS hold the index. If this value is less than MAX_EDICTS, then the entity is networkable. - // The high NUM_SERIAL_NUM_BITS bits are the serial number. - unsigned long m_Index; -}; - - -#include "ihandleentity.h" - - -inline CBaseHandle::CBaseHandle() -{ - m_Index = INVALID_EHANDLE_INDEX; -} - -inline CBaseHandle::CBaseHandle( const CBaseHandle &other ) -{ - m_Index = other.m_Index; -} - -inline CBaseHandle::CBaseHandle( unsigned long value ) -{ - m_Index = value; -} - -inline CBaseHandle::CBaseHandle( int iEntry, int iSerialNumber ) -{ - Init( iEntry, iSerialNumber ); -} - -inline void CBaseHandle::Init( int iEntry, int iSerialNumber ) -{ - Assert( iEntry >= 0 && iEntry < NUM_ENT_ENTRIES ); - Assert( iSerialNumber >= 0 && iSerialNumber < (1 << NUM_SERIAL_NUM_BITS) ); - - m_Index = iEntry | (iSerialNumber << NUM_ENT_ENTRY_BITS); -} - -inline void CBaseHandle::Term() -{ - m_Index = INVALID_EHANDLE_INDEX; -} - -inline bool CBaseHandle::IsValid() const -{ - return m_Index != INVALID_EHANDLE_INDEX; -} - -inline int CBaseHandle::GetEntryIndex() const -{ - return m_Index & ENT_ENTRY_MASK; -} - -inline int CBaseHandle::GetSerialNumber() const -{ - return m_Index >> NUM_ENT_ENTRY_BITS; -} - -inline int CBaseHandle::ToInt() const -{ - return (int)m_Index; -} - -inline bool CBaseHandle::operator !=( const CBaseHandle &other ) const -{ - return m_Index != other.m_Index; -} - -inline bool CBaseHandle::operator ==( const CBaseHandle &other ) const -{ - return m_Index == other.m_Index; -} - -inline bool CBaseHandle::operator ==( const IHandleEntity* pEnt ) const -{ - return Get() == pEnt; -} - -inline bool CBaseHandle::operator !=( const IHandleEntity* pEnt ) const -{ - return Get() != pEnt; -} - -inline bool CBaseHandle::operator <( const CBaseHandle &other ) const -{ - return m_Index < other.m_Index; -} - -inline bool CBaseHandle::operator <( const IHandleEntity *pEntity ) const -{ - unsigned long otherIndex = (pEntity) ? pEntity->GetRefEHandle().m_Index : INVALID_EHANDLE_INDEX; - return m_Index < otherIndex; -} - -inline const CBaseHandle& CBaseHandle::operator=( const IHandleEntity *pEntity ) -{ - return Set( pEntity ); -} - -inline const CBaseHandle& CBaseHandle::Set( const IHandleEntity *pEntity ) -{ - if ( pEntity ) - { - *this = pEntity->GetRefEHandle(); - } - else - { - m_Index = INVALID_EHANDLE_INDEX; - } - - return *this; -} - - -#endif // BASEHANDLE_H diff --git a/public/bitmap/bitmap.h b/public/bitmap/bitmap.h deleted file mode 100644 index f6eeba4be..000000000 --- a/public/bitmap/bitmap.h +++ /dev/null @@ -1,77 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $Header: $ -// $NoKeywords: $ -//===========================================================================// - -#ifndef BITMAP_H -#define BITMAP_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "bitmap/imageformat.h" - - -//----------------------------------------------------------------------------- -// A Bitmap -//----------------------------------------------------------------------------- -struct Bitmap_t -{ - Bitmap_t(); - ~Bitmap_t(); - void Init( int nWidth, int nHeight, ImageFormat imageFormat ); - unsigned char *GetPixel( int x, int y ); - - int m_nWidth; - int m_nHeight; - ImageFormat m_ImageFormat; - unsigned char *m_pBits; -}; - -inline Bitmap_t::Bitmap_t() -{ - m_nWidth = 0; - m_nHeight = 0; - m_ImageFormat = IMAGE_FORMAT_UNKNOWN; - m_pBits = NULL; -} - -inline Bitmap_t::~Bitmap_t() -{ - if ( m_pBits ) - { - delete[] m_pBits; - m_pBits = NULL; - } -} - -inline void Bitmap_t::Init( int nWidth, int nHeight, ImageFormat imageFormat ) -{ - if ( m_pBits ) - { - delete[] m_pBits; - m_pBits = NULL; - } - - m_nWidth = nWidth; - m_nHeight = nHeight; - m_ImageFormat = imageFormat; - m_pBits = new unsigned char[ nWidth * nHeight * ImageLoader::SizeInBytes( m_ImageFormat ) ]; -} - -inline unsigned char *Bitmap_t::GetPixel( int x, int y ) -{ - if ( !m_pBits ) - return NULL; - - int nPixelSize = ImageLoader::SizeInBytes( m_ImageFormat ); - return &m_pBits[ ( m_nWidth * y + x ) * nPixelSize ]; -} - - -#endif // BITMAP_H diff --git a/public/bitmap/cubemap.h b/public/bitmap/cubemap.h deleted file mode 100644 index 1d6725363..000000000 --- a/public/bitmap/cubemap.h +++ /dev/null @@ -1,68 +0,0 @@ -//===== Copyright 1996-2007, Valve Corporation, All rights reserved. ======// -// -// Purpose: a class for performing cube-mapped spherical sample lookups. -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//===========================================================================// - -#ifndef CUBEMAP_H -#define CUBEMAP_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/platform.h" -#include "tier1/utlmemory.h" -#include "mathlib/mathlib.h" - -template struct CCubeMap -{ - T m_Samples[6][RES][RES]; - -public: - FORCEINLINE void GetCoords( Vector const &vecNormalizedDirection, int &nX, int &nY, int &nFace ) - { - // find largest magnitude component - int nLargest = 0; - int nAxis0 = 1; - int nAxis1 = 2; - if ( fabs( vecNormalizedDirection[1] ) > fabs( vecNormalizedDirection[0] ) ) - { - nLargest = 1; - nAxis0 = 0; - nAxis1 = 2; - } - if ( fabs( vecNormalizedDirection[2] ) > fabs( vecNormalizedDirection[nLargest] ) ) - { - nLargest = 2; - nAxis0 = 0; - nAxis1 = 1; - } - float flZ = vecNormalizedDirection[nLargest]; - if ( flZ < 0 ) - { - flZ = - flZ; - nLargest += 3; - } - nFace = nLargest; - flZ = 1.0 / flZ; - nX = RemapValClamped( vecNormalizedDirection[nAxis0] * flZ, -1, 1, 0, RES - 1 ); - nY = RemapValClamped( vecNormalizedDirection[nAxis1] * flZ, -1, 1, 0, RES - 1 ); - } - - FORCEINLINE T & GetSample( Vector const &vecNormalizedDirection ) - { - int nX, nY, nFace; - GetCoords( vecNormalizedDirection, nX, nY, nFace ); - return m_Samples[nFace][nX][nY]; - } -}; - - - - - -#endif // CUBEMAP_H diff --git a/public/bitmap/float_bm.h b/public/bitmap/float_bm.h deleted file mode 100644 index ae7a8fa26..000000000 --- a/public/bitmap/float_bm.h +++ /dev/null @@ -1,362 +0,0 @@ -//======= Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $Header: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef FLOAT_BM_H -#define FLOAT_BM_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include "tier0/dbg.h" -#include - -struct PixRGBAF -{ - float Red; - float Green; - float Blue; - float Alpha; -}; - -struct PixRGBA8 -{ - unsigned char Red; - unsigned char Green; - unsigned char Blue; - unsigned char Alpha; -}; - -inline PixRGBAF PixRGBA8_to_F( PixRGBA8 const &x ) -{ - PixRGBAF f; - f.Red = x.Red / float( 255.0f ); - f.Green = x.Green / float( 255.0f ); - f.Blue = x.Blue / float( 255.0f ); - f.Alpha = x.Alpha / float( 255.0f ); - return f; -} - -inline PixRGBA8 PixRGBAF_to_8( PixRGBAF const &f ) -{ - PixRGBA8 x; - x.Red = MAX( 0, MIN( 255.0,255.0*f.Red ) ); - x.Green = MAX( 0, MIN( 255.0,255.0*f.Green ) ); - x.Blue = MAX( 0, MIN( 255.0,255.0*f.Blue ) ); - x.Alpha = MAX( 0, MIN( 255.0,255.0*f.Alpha ) ); - return x; -} - -#define SPFLAGS_MAXGRADIENT 1 - -// bit flag options for ComputeSelfShadowedBumpmapFromHeightInAlphaChannel: -#define SSBUMP_OPTION_NONDIRECTIONAL 1 // generate ambient occlusion only -#define SSBUMP_MOD2X_DETAIL_TEXTURE 2 // scale so that a flat unshadowed - // value is 0.5, and bake rgb luminance - // in. - - - -class FloatBitMap_t -{ -public: - int Width, Height; // bitmap dimensions - float *RGBAData; // actual data - - FloatBitMap_t(void) // empty one - { - Width=Height=0; - RGBAData=0; - } - - - - FloatBitMap_t(int width, int height); // make one and allocate space - FloatBitMap_t(char const *filename); // read one from a file (tga or pfm) - FloatBitMap_t(FloatBitMap_t const *orig); - // quantize one to 8 bits - bool WriteTGAFile(char const *filename) const; - - bool LoadFromPFM(char const *filename); // load from floating point pixmap (.pfm) file - bool WritePFM(char const *filename); // save to floating point pixmap (.pfm) file - - - void InitializeWithRandomPixelsFromAnotherFloatBM(FloatBitMap_t const &other); - - inline float & Pixel(int x, int y, int comp) const - { - Assert((x>=0) && (x=0) && (y= Width) - x -= Width; - - if ( y < 0 ) - y+=Height; - else - if ( y >= Height ) - y -= Height; - - return RGBAData[4*(x+Width*y)+comp]; - } - - inline float & PixelClamped(int x, int y, int comp) const - { - // like Pixel except wraps around to other side - x=clamp(x,0,Width-1); - y=clamp(y,0,Height-1); - return RGBAData[4*(x+Width*y)+comp]; - } - - - inline float & Alpha(int x, int y) const - { - Assert((x>=0) && (x=0) && (y=0) && (x=0) && (y=0) && (x=0) && (y=0) && (x=0) && (y - -enum NormalDecodeMode_t -{ - NORMAL_DECODE_NONE = 0, - NORMAL_DECODE_ATI2N = 1, - NORMAL_DECODE_ATI2N_ALPHA = 2 -}; - -// Forward declaration -#ifdef _WIN32 -typedef enum _D3DFORMAT D3DFORMAT; -#endif - -//----------------------------------------------------------------------------- -// The various image format types -//----------------------------------------------------------------------------- - -#ifdef _MSC_VER -// don't bitch that inline functions aren't used!!!! -#pragma warning(disable : 4514) -#endif - -enum ImageFormat -{ - IMAGE_FORMAT_UNKNOWN = -1, - IMAGE_FORMAT_RGBA8888 = 0, - IMAGE_FORMAT_ABGR8888, - IMAGE_FORMAT_RGB888, - IMAGE_FORMAT_BGR888, - IMAGE_FORMAT_RGB565, - IMAGE_FORMAT_I8, - IMAGE_FORMAT_IA88, - IMAGE_FORMAT_P8, - IMAGE_FORMAT_A8, - IMAGE_FORMAT_RGB888_BLUESCREEN, - IMAGE_FORMAT_BGR888_BLUESCREEN, - IMAGE_FORMAT_ARGB8888, - IMAGE_FORMAT_BGRA8888, - IMAGE_FORMAT_DXT1, - IMAGE_FORMAT_DXT3, - IMAGE_FORMAT_DXT5, - IMAGE_FORMAT_BGRX8888, - IMAGE_FORMAT_BGR565, - IMAGE_FORMAT_BGRX5551, - IMAGE_FORMAT_BGRA4444, - IMAGE_FORMAT_DXT1_ONEBITALPHA, - IMAGE_FORMAT_BGRA5551, - IMAGE_FORMAT_UV88, - IMAGE_FORMAT_UVWQ8888, - IMAGE_FORMAT_RGBA16161616F, - IMAGE_FORMAT_RGBA16161616, - IMAGE_FORMAT_UVLX8888, - IMAGE_FORMAT_R32F, // Single-channel 32-bit floating point - IMAGE_FORMAT_RGB323232F, - IMAGE_FORMAT_RGBA32323232F, - - // Depth-stencil texture formats for shadow depth mapping - IMAGE_FORMAT_NV_DST16, // - IMAGE_FORMAT_NV_DST24, // - IMAGE_FORMAT_NV_INTZ, // Vendor-specific depth-stencil texture - IMAGE_FORMAT_NV_RAWZ, // formats for shadow depth mapping - IMAGE_FORMAT_ATI_DST16, // - IMAGE_FORMAT_ATI_DST24, // - IMAGE_FORMAT_NV_NULL, // Dummy format which takes no video memory - - // Compressed normal map formats - IMAGE_FORMAT_ATI2N, // One-surface ATI2N / DXN format - IMAGE_FORMAT_ATI1N, // Two-surface ATI1N format - -#if defined( _X360 ) - // Depth-stencil texture formats - IMAGE_FORMAT_X360_DST16, - IMAGE_FORMAT_X360_DST24, - IMAGE_FORMAT_X360_DST24F, - // supporting these specific formats as non-tiled for procedural cpu access - IMAGE_FORMAT_LINEAR_BGRX8888, - IMAGE_FORMAT_LINEAR_RGBA8888, - IMAGE_FORMAT_LINEAR_ABGR8888, - IMAGE_FORMAT_LINEAR_ARGB8888, - IMAGE_FORMAT_LINEAR_BGRA8888, - IMAGE_FORMAT_LINEAR_RGB888, - IMAGE_FORMAT_LINEAR_BGR888, - IMAGE_FORMAT_LINEAR_BGRX5551, - IMAGE_FORMAT_LINEAR_I8, - IMAGE_FORMAT_LINEAR_RGBA16161616, - - IMAGE_FORMAT_LE_BGRX8888, - IMAGE_FORMAT_LE_BGRA8888, -#endif - - NUM_IMAGE_FORMATS -}; - -//----------------------------------------------------------------------------- -// Color structures -//----------------------------------------------------------------------------- - -struct BGRA8888_t -{ - unsigned char b; // change the order of names to change the - unsigned char g; // order of the output ARGB or BGRA, etc... - unsigned char r; // Last one is MSB, 1st is LSB. - unsigned char a; - inline BGRA8888_t& operator=( const BGRA8888_t& in ) - { - *( unsigned int * )this = *( unsigned int * )∈ - return *this; - } -}; - -struct RGBA8888_t -{ - unsigned char r; // change the order of names to change the - unsigned char g; // order of the output ARGB or BGRA, etc... - unsigned char b; // Last one is MSB, 1st is LSB. - unsigned char a; - inline RGBA8888_t& operator=( const BGRA8888_t& in ) - { - r = in.r; - g = in.g; - b = in.b; - a = in.a; - return *this; - } -}; - -struct RGB888_t -{ - unsigned char r; - unsigned char g; - unsigned char b; - inline RGB888_t& operator=( const BGRA8888_t& in ) - { - r = in.r; - g = in.g; - b = in.b; - return *this; - } - inline bool operator==( const RGB888_t& in ) const - { - return ( r == in.r ) && ( g == in.g ) && ( b == in.b ); - } - inline bool operator!=( const RGB888_t& in ) const - { - return ( r != in.r ) || ( g != in.g ) || ( b != in.b ); - } -}; - -struct BGR888_t -{ - unsigned char b; - unsigned char g; - unsigned char r; - inline BGR888_t& operator=( const BGRA8888_t& in ) - { - r = in.r; - g = in.g; - b = in.b; - return *this; - } -}; - -// 360 uses this structure for x86 dxt decoding -#if defined( _X360 ) -#pragma bitfield_order( push, lsb_to_msb ) -#endif -struct BGR565_t -{ - unsigned short b : 5; // order of names changes - unsigned short g : 6; // byte order of output to 32 bit - unsigned short r : 5; - inline BGR565_t& operator=( const BGRA8888_t& in ) - { - r = in.r >> 3; - g = in.g >> 2; - b = in.b >> 3; - return *this; - } - inline BGR565_t &Set( int red, int green, int blue ) - { - r = red >> 3; - g = green >> 2; - b = blue >> 3; - return *this; - } -}; -#if defined( _X360 ) -#pragma bitfield_order( pop ) -#endif - -struct BGRA5551_t -{ - unsigned short b : 5; // order of names changes - unsigned short g : 5; // byte order of output to 32 bit - unsigned short r : 5; - unsigned short a : 1; - inline BGRA5551_t& operator=( const BGRA8888_t& in ) - { - r = in.r >> 3; - g = in.g >> 3; - b = in.b >> 3; - a = in.a >> 7; - return *this; - } -}; - -struct BGRA4444_t -{ - unsigned short b : 4; // order of names changes - unsigned short g : 4; // byte order of output to 32 bit - unsigned short r : 4; - unsigned short a : 4; - inline BGRA4444_t& operator=( const BGRA8888_t& in ) - { - r = in.r >> 4; - g = in.g >> 4; - b = in.b >> 4; - a = in.a >> 4; - return *this; - } -}; - -struct RGBX5551_t -{ - unsigned short r : 5; - unsigned short g : 5; - unsigned short b : 5; - unsigned short x : 1; - inline RGBX5551_t& operator=( const BGRA8888_t& in ) - { - r = in.r >> 3; - g = in.g >> 3; - b = in.b >> 3; - return *this; - } -}; - -//----------------------------------------------------------------------------- -// some important constants -//----------------------------------------------------------------------------- -#define ARTWORK_GAMMA ( 2.2f ) -#define IMAGE_MAX_DIM ( 2048 ) - - -//----------------------------------------------------------------------------- -// information about each image format -//----------------------------------------------------------------------------- -struct ImageFormatInfo_t -{ - char* m_pName; - int m_NumBytes; - int m_NumRedBits; - int m_NumGreeBits; - int m_NumBlueBits; - int m_NumAlphaBits; - bool m_IsCompressed; -}; - - -//----------------------------------------------------------------------------- -// Various methods related to pixelmaps and color formats -//----------------------------------------------------------------------------- -namespace ImageLoader -{ - - bool GetInfo( const char *fileName, int *width, int *height, enum ImageFormat *imageFormat, float *sourceGamma ); - int GetMemRequired( int width, int height, int depth, ImageFormat imageFormat, bool mipmap ); - int GetMipMapLevelByteOffset( int width, int height, enum ImageFormat imageFormat, int skipMipLevels ); - void GetMipMapLevelDimensions( int *width, int *height, int skipMipLevels ); - int GetNumMipMapLevels( int width, int height, int depth = 1 ); - bool Load( unsigned char *imageData, const char *fileName, int width, int height, enum ImageFormat imageFormat, float targetGamma, bool mipmap ); - bool Load( unsigned char *imageData, FILE *fp, int width, int height, - enum ImageFormat imageFormat, float targetGamma, bool mipmap ); - - // convert from any image format to any other image format. - // return false if the conversion cannot be performed. - // Strides denote the number of bytes per each line, - // by default assumes width * # of bytes per pixel - bool ConvertImageFormat( const unsigned char *src, enum ImageFormat srcImageFormat, - unsigned char *dst, enum ImageFormat dstImageFormat, - int width, int height, int srcStride = 0, int dstStride = 0 ); - - // must be used in conjunction with ConvertImageFormat() to pre-swap and post-swap - void PreConvertSwapImageData( unsigned char *pImageData, int nImageSize, ImageFormat imageFormat, int width = 0, int stride = 0 ); - void PostConvertSwapImageData( unsigned char *pImageData, int nImageSize, ImageFormat imageFormat, int width = 0, int stride = 0 ); - void ByteSwapImageData( unsigned char *pImageData, int nImageSize, ImageFormat imageFormat, int width = 0, int stride = 0 ); - bool IsFormatValidForConversion( ImageFormat fmt ); - - //----------------------------------------------------------------------------- - // convert back and forth from D3D format to ImageFormat, regardless of - // whether it's supported or not - //----------------------------------------------------------------------------- - #ifdef _WIN32 - ImageFormat D3DFormatToImageFormat( D3DFORMAT format ); - D3DFORMAT ImageFormatToD3DFormat( ImageFormat format ); - #endif - - // Flags for ResampleRGBA8888 - enum - { - RESAMPLE_NORMALMAP = 0x1, - RESAMPLE_ALPHATEST = 0x2, - RESAMPLE_NICE_FILTER = 0x4, - RESAMPLE_CLAMPS = 0x8, - RESAMPLE_CLAMPT = 0x10, - RESAMPLE_CLAMPU = 0x20, - }; - - struct ResampleInfo_t - { - - ResampleInfo_t() : m_nSrcDepth(1), m_nDestDepth(1), m_flAlphaThreshhold(0.4f), m_flAlphaHiFreqThreshhold(0.4f), m_nFlags(0) - { - m_flColorScale[0] = 1.0f, m_flColorScale[1] = 1.0f, m_flColorScale[2] = 1.0f, m_flColorScale[3] = 1.0f; - m_flColorGoal[0] = 0.0f, m_flColorGoal[1] = 0.0f, m_flColorGoal[2] = 0.0f, m_flColorGoal[3] = 0.0f; - } - - unsigned char *m_pSrc; - unsigned char *m_pDest; - - int m_nSrcWidth; - int m_nSrcHeight; - int m_nSrcDepth; - - int m_nDestWidth; - int m_nDestHeight; - int m_nDestDepth; - - float m_flSrcGamma; - float m_flDestGamma; - - float m_flColorScale[4]; // Color scale factors RGBA - float m_flColorGoal[4]; // Color goal values RGBA DestColor = ColorGoal + scale * (SrcColor - ColorGoal) - - float m_flAlphaThreshhold; - float m_flAlphaHiFreqThreshhold; - - int m_nFlags; - }; - - bool ResampleRGBA8888( const ResampleInfo_t &info ); - bool ResampleRGBA16161616( const ResampleInfo_t &info ); - bool ResampleRGB323232F( const ResampleInfo_t &info ); - - void ConvertNormalMapRGBA8888ToDUDVMapUVLX8888( const unsigned char *src, int width, int height, - unsigned char *dst_ ); - void ConvertNormalMapRGBA8888ToDUDVMapUVWQ8888( const unsigned char *src, int width, int height, - unsigned char *dst_ ); - void ConvertNormalMapRGBA8888ToDUDVMapUV88( const unsigned char *src, int width, int height, - unsigned char *dst_ ); - - void ConvertIA88ImageToNormalMapRGBA8888( const unsigned char *src, int width, - int height, unsigned char *dst, - float bumpScale ); - - void NormalizeNormalMapRGBA8888( unsigned char *src, int numTexels ); - - - //----------------------------------------------------------------------------- - // Gamma correction - //----------------------------------------------------------------------------- - void GammaCorrectRGBA8888( unsigned char *src, unsigned char* dst, - int width, int height, int depth, float srcGamma, float dstGamma ); - - - //----------------------------------------------------------------------------- - // Makes a gamma table - //----------------------------------------------------------------------------- - void ConstructGammaTable( unsigned char* pTable, float srcGamma, float dstGamma ); - - - //----------------------------------------------------------------------------- - // Gamma corrects using a previously constructed gamma table - //----------------------------------------------------------------------------- - void GammaCorrectRGBA8888( unsigned char* pSrc, unsigned char* pDst, - int width, int height, int depth, unsigned char* pGammaTable ); - - - //----------------------------------------------------------------------------- - // Generates a number of mipmap levels - //----------------------------------------------------------------------------- - void GenerateMipmapLevels( unsigned char* pSrc, unsigned char* pDst, int width, - int height, int depth, ImageFormat imageFormat, float srcGamma, float dstGamma, - int numLevels = 0 ); - - - //----------------------------------------------------------------------------- - // operations on square images (src and dst can be the same) - //----------------------------------------------------------------------------- - bool RotateImageLeft( const unsigned char *src, unsigned char *dst, - int widthHeight, ImageFormat imageFormat ); - bool RotateImage180( const unsigned char *src, unsigned char *dst, - int widthHeight, ImageFormat imageFormat ); - bool FlipImageVertically( void *pSrc, void *pDst, int nWidth, int nHeight, ImageFormat imageFormat, int nDstStride = 0 ); - bool FlipImageHorizontally( void *pSrc, void *pDst, int nWidth, int nHeight, ImageFormat imageFormat, int nDstStride = 0 ); - bool SwapAxes( unsigned char *src, - int widthHeight, ImageFormat imageFormat ); - - - //----------------------------------------------------------------------------- - // Returns info about each image format - //----------------------------------------------------------------------------- - ImageFormatInfo_t const& ImageFormatInfo( ImageFormat fmt ); - - - //----------------------------------------------------------------------------- - // Gets the name of the image format - //----------------------------------------------------------------------------- - inline char const* GetName( ImageFormat fmt ) - { - return ImageFormatInfo(fmt).m_pName; - } - - - //----------------------------------------------------------------------------- - // Gets the size of the image format in bytes - //----------------------------------------------------------------------------- - inline int SizeInBytes( ImageFormat fmt ) - { - return ImageFormatInfo(fmt).m_NumBytes; - } - - //----------------------------------------------------------------------------- - // Does the image format support transparency? - //----------------------------------------------------------------------------- - inline bool IsTransparent( ImageFormat fmt ) - { - return ImageFormatInfo(fmt).m_NumAlphaBits > 0; - } - - - //----------------------------------------------------------------------------- - // Is the image format compressed? - //----------------------------------------------------------------------------- - inline bool IsCompressed( ImageFormat fmt ) - { - return ImageFormatInfo(fmt).m_IsCompressed; - } - - //----------------------------------------------------------------------------- - // Is any channel > 8 bits? - //----------------------------------------------------------------------------- - inline bool HasChannelLargerThan8Bits( ImageFormat fmt ) - { - ImageFormatInfo_t info = ImageFormatInfo(fmt); - return ( info.m_NumRedBits > 8 || info.m_NumGreeBits > 8 || info.m_NumBlueBits > 8 || info.m_NumAlphaBits > 8 ); - } - - -} // end namespace ImageLoader - - -#endif // IMAGEFORMAT_H diff --git a/public/bitmap/psd.h b/public/bitmap/psd.h deleted file mode 100644 index ec56f84a2..000000000 --- a/public/bitmap/psd.h +++ /dev/null @@ -1,105 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: Methods relating to saving + loading PSD files (photoshop) -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef PSD_H -#define PSD_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "bitmap/imageformat.h" //ImageFormat enum definition - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class CUtlBuffer; -struct Bitmap_t; - -class PSDImageResources -{ -public: - enum Resource { - eResFileInfo = 0x0404 - }; - - struct ResElement { - Resource m_eType; - // unsigned char m_pReserved[4]; - unsigned short m_numBytes; - unsigned char const *m_pvData; - }; - -public: - explicit PSDImageResources( unsigned int numBytes, unsigned char const *pvBuffer ) : m_numBytes( numBytes ), m_pvBuffer( pvBuffer ) {} - -public: - ResElement FindElement( Resource eType ) const; - -protected: - unsigned int m_numBytes; - unsigned char const * m_pvBuffer; -}; - -class PSDResFileInfo -{ -public: - enum ResFileInfo { - eTitle = 0x05, - eAuthor = 0x50, - eAuthorTitle = 0x55, - eDescription = 0x78, - eDescriptionWriter = 0x7A, - eKeywords = 0x19, - eCopyrightNotice = 0x74 - }; - - struct ResFileInfoElement { - ResFileInfo m_eType; - unsigned short m_numBytes; - unsigned char const *m_pvData; - }; - -public: - explicit PSDResFileInfo( PSDImageResources::ResElement res ) : m_res( res ) {} - -public: - ResFileInfoElement FindElement( ResFileInfo eType ) const; - -protected: - PSDImageResources::ResElement m_res; -}; - - -//----------------------------------------------------------------------------- -// Is a file a PSD file? -//----------------------------------------------------------------------------- -bool IsPSDFile( const char *pFileName, const char *pPathID ); -bool IsPSDFile( CUtlBuffer &buf ); - - -//----------------------------------------------------------------------------- -// Returns information about the PSD file -//----------------------------------------------------------------------------- -bool PSDGetInfo( const char *pFileName, const char *pPathID, int *pWidth, int *pHeight, ImageFormat *pImageFormat, float *pSourceGamma ); -bool PSDGetInfo( CUtlBuffer &buf, int *pWidth, int *pHeight, ImageFormat *pImageFormat, float *pSourceGamma ); - - -//----------------------------------------------------------------------------- -// Get PSD file image resources, pointers refer into the utlbuffer -//----------------------------------------------------------------------------- -PSDImageResources PSDGetImageResources( CUtlBuffer &buf ); - - -//----------------------------------------------------------------------------- -// Reads the PSD file into the specified buffer -//----------------------------------------------------------------------------- -bool PSDReadFileRGBA8888( CUtlBuffer &buf, Bitmap_t &bitmap ); -bool PSDReadFileRGBA8888( const char *pFileName, const char *pPathID, Bitmap_t &bitmap ); - - -#endif // PSD_H diff --git a/public/bitmap/tgaloader.h b/public/bitmap/tgaloader.h deleted file mode 100644 index 8a9947b85..000000000 --- a/public/bitmap/tgaloader.h +++ /dev/null @@ -1,45 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//===========================================================================// - -#ifndef TGALOADER_H -#define TGALOADER_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "bitmap/imageformat.h" -#include "tier1/utlmemory.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class CUtlBuffer; - - -namespace TGALoader -{ - -int TGAHeaderSize(); - -bool GetInfo( const char *fileName, int *width, int *height, ImageFormat *imageFormat, float *sourceGamma ); -bool GetInfo( CUtlBuffer &buf, int *width, int *height, ImageFormat *imageFormat, float *sourceGamma ); - -bool Load( unsigned char *imageData, const char *fileName, int width, int height, - ImageFormat imageFormat, float targetGamma, bool mipmap ); -bool Load( unsigned char *imageData, CUtlBuffer &buf, int width, int height, - ImageFormat imageFormat, float targetGamma, bool mipmap ); - -bool LoadRGBA8888( const char *pFileName, CUtlMemory &outputData, int &outWidth, int &outHeight ); -bool LoadRGBA8888( CUtlBuffer &buf, CUtlMemory &outputData, int &outWidth, int &outHeight ); - -} // end namespace TGALoader - -#endif // TGALOADER_H diff --git a/public/bitmap/tgawriter.h b/public/bitmap/tgawriter.h deleted file mode 100644 index cf7aeb052..000000000 --- a/public/bitmap/tgawriter.h +++ /dev/null @@ -1,40 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef TGAWRITER_H -#define TGAWRITER_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "tier1/interface.h" -#include "bitmap/imageformat.h" //ImageFormat enum definition - -class CUtlBuffer; - - -namespace TGAWriter -{ - - bool WriteToBuffer( unsigned char *pImageData, CUtlBuffer &buffer, int width, int height, - ImageFormat srcFormat, ImageFormat dstFormat ); - - - // write out a simple tga file from a memory buffer. - bool WriteTGAFile( const char *fileName, int width, int height, enum ImageFormat srcFormat, uint8 const *srcData, int nStride ); - -// A pair of routines for writing to files without allocating any memory in the TGA writer -// Useful for very large files such as posters, which are rendered as sub-rects anyway - bool WriteDummyFileNoAlloc( const char *fileName, int width, int height, ImageFormat dstFormat ); - bool WriteRectNoAlloc( unsigned char *pImageData, const char *fileName, int nXOrigin, int nYOrigin, int width, int height, int nStride, ImageFormat srcFormat ); - - -} // end namespace TGAWriter - -#endif // TGAWRITER_H diff --git a/public/bitvec.h b/public/bitvec.h deleted file mode 100644 index 3dc151b9a..000000000 --- a/public/bitvec.h +++ /dev/null @@ -1,1417 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#ifndef BITVEC_H -#define BITVEC_H -#ifdef _WIN32 -#pragma once -#endif - -#include -#include "tier0/dbg.h" -#include "tier0/basetypes.h" - - -class CBitVecAccessor -{ -public: - CBitVecAccessor(uint32 *pDWords, int iBit); - - void operator=(int val); - operator uint32(); - -private: - uint32 *m_pDWords; - int m_iBit; -}; - - -//----------------------------------------------------------------------------- -// Support functions -//----------------------------------------------------------------------------- - -#define LOG2_BITS_PER_INT 5 -#define BITS_PER_INT 32 - -#if _WIN32 && !defined(_X360) -#include -#pragma intrinsic(_BitScanForward) -#endif - -inline int FirstBitInWord( unsigned int elem, int offset ) -{ -#if _WIN32 - if ( !elem ) - return -1; -#if _X360 - // this implements CountTrailingZeros() / BitScanForward() - unsigned int mask = elem-1; - unsigned int comp = ~elem; - elem = mask & comp; - return (32 - _CountLeadingZeros(elem)) + offset; -#else - unsigned long out; - _BitScanForward(&out, elem); - return out + offset; -#endif - -#else - static unsigned firstBitLUT[256] = - { - 0,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0, - 3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, - 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0, - 3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, - 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0, - 3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0, - 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 - }; - unsigned elemByte; - - elemByte = (elem & 0xFF); - if ( elemByte ) - return offset + firstBitLUT[elemByte]; - - elem >>= 8; - offset += 8; - elemByte = (elem & 0xFF); - if ( elemByte ) - return offset + firstBitLUT[elemByte]; - - elem >>= 8; - offset += 8; - elemByte = (elem & 0xFF); - if ( elemByte ) - return offset + firstBitLUT[elemByte]; - - elem >>= 8; - offset += 8; - elemByte = (elem & 0xFF); - if ( elemByte ) - return offset + firstBitLUT[elemByte]; - - return -1; -#endif -} - -//------------------------------------- - -inline unsigned GetEndMask( int numBits ) -{ - static unsigned bitStringEndMasks[] = - { - 0xffffffff, - 0x00000001, - 0x00000003, - 0x00000007, - 0x0000000f, - 0x0000001f, - 0x0000003f, - 0x0000007f, - 0x000000ff, - 0x000001ff, - 0x000003ff, - 0x000007ff, - 0x00000fff, - 0x00001fff, - 0x00003fff, - 0x00007fff, - 0x0000ffff, - 0x0001ffff, - 0x0003ffff, - 0x0007ffff, - 0x000fffff, - 0x001fffff, - 0x003fffff, - 0x007fffff, - 0x00ffffff, - 0x01ffffff, - 0x03ffffff, - 0x07ffffff, - 0x0fffffff, - 0x1fffffff, - 0x3fffffff, - 0x7fffffff, - }; - - return bitStringEndMasks[numBits % BITS_PER_INT]; -} - - -inline int GetBitForBitnum( int bitNum ) -{ - static int bitsForBitnum[] = - { - ( 1 << 0 ), - ( 1 << 1 ), - ( 1 << 2 ), - ( 1 << 3 ), - ( 1 << 4 ), - ( 1 << 5 ), - ( 1 << 6 ), - ( 1 << 7 ), - ( 1 << 8 ), - ( 1 << 9 ), - ( 1 << 10 ), - ( 1 << 11 ), - ( 1 << 12 ), - ( 1 << 13 ), - ( 1 << 14 ), - ( 1 << 15 ), - ( 1 << 16 ), - ( 1 << 17 ), - ( 1 << 18 ), - ( 1 << 19 ), - ( 1 << 20 ), - ( 1 << 21 ), - ( 1 << 22 ), - ( 1 << 23 ), - ( 1 << 24 ), - ( 1 << 25 ), - ( 1 << 26 ), - ( 1 << 27 ), - ( 1 << 28 ), - ( 1 << 29 ), - ( 1 << 30 ), - ( 1 << 31 ), - }; - - return bitsForBitnum[ (bitNum) & (BITS_PER_INT-1) ]; -} - -inline int GetBitForBitnumByte( int bitNum ) -{ - static int bitsForBitnum[] = - { - ( 1 << 0 ), - ( 1 << 1 ), - ( 1 << 2 ), - ( 1 << 3 ), - ( 1 << 4 ), - ( 1 << 5 ), - ( 1 << 6 ), - ( 1 << 7 ), - }; - - return bitsForBitnum[ bitNum & 7 ]; -} - -inline int CalcNumIntsForBits( int numBits ) { return (numBits + (BITS_PER_INT-1)) / BITS_PER_INT; } - -#ifdef _X360 -#define BitVec_Bit( bitNum ) GetBitForBitnum( bitNum ) -#define BitVec_BitInByte( bitNum ) GetBitForBitnumByte( bitNum ) -#else -#define BitVec_Bit( bitNum ) ( 1 << ( (bitNum) & (BITS_PER_INT-1) ) ) -#define BitVec_BitInByte( bitNum ) ( 1 << ( (bitNum) & 7 ) ) -#endif -#define BitVec_Int( bitNum ) ( (bitNum) >> LOG2_BITS_PER_INT ) - - -//----------------------------------------------------------------------------- -// template CBitVecT -// -// Defines the operations relevant to any bit array. Simply requires a base -// class that implements GetNumBits(), Base(), GetNumDWords() & ValidateOperand() -// -// CVarBitVec and CBitVec are the actual classes generally used -// by clients -// - -template -class CBitVecT : public BASE_OPS -{ -public: - CBitVecT(); - CBitVecT(int numBits); // Must be initialized with the number of bits - - void Init(int val = 0); - - // Access the bits like an array. - CBitVecAccessor operator[](int i); - - // Do NOT override bitwise operators (see note in header) - void And(const CBitVecT &andStr, CBitVecT *out) const; - void Or(const CBitVecT &orStr, CBitVecT *out) const; - void Xor(const CBitVecT &orStr, CBitVecT *out) const; - - void Not(CBitVecT *out) const; - - void CopyTo(CBitVecT *out) const; - void Copy( const CBitVecT &other, int nBits=-1 ); - bool Compare( const CBitVecT &other, int nBits=-1 ) const; - - bool IsAllClear(void) const; // Are all bits zero? - bool IsAllSet(void) const; // Are all bits one? - - uint32 Get( uint32 bitNum ) const; - bool IsBitSet( int bitNum ) const; - void Set( int bitNum ); - void Set( int bitNum, bool bNewVal ); - void Clear(int bitNum); - - bool TestAndSet(int bitNum); - - void Set( uint32 offset, uint32 mask ); - void Clear( uint32 offset, uint32 mask ); - uint32 Get( uint32 offset, uint32 mask ); - - void SetAll(void); // Sets all bits - void ClearAll(void); // Clears all bits - - uint32 GetDWord(int i) const; - void SetDWord(int i, uint32 val); - - CBitVecT& operator=(const CBitVecT &other) { other.CopyTo( this ); return *this; } - bool operator==(const CBitVecT &other) { return Compare( other ); } - bool operator!=(const CBitVecT &other) { return !operator==( other ); } - - static void GetOffsetMaskForBit( uint32 bitNum, uint32 *pOffset, uint32 *pMask ) { *pOffset = BitVec_Int( bitNum ); *pMask = BitVec_Bit( bitNum ); } -}; - -//----------------------------------------------------------------------------- -// class CVarBitVecBase -// -// Defines the operations necessary for a variable sized bit array - -class CVarBitVecBase -{ -public: - bool IsFixedSize() const { return false; } - int GetNumBits(void) const { return m_numBits; } - void Resize( int numBits, bool bClearAll = false ); // resizes bit array - - int GetNumDWords() const { return m_numInts; } - uint32 *Base() { return m_pInt; } - const uint32 *Base() const { return m_pInt; } - - void Attach( uint32 *pBits, int numBits ); - bool Detach( uint32 **ppBits, int *pNumBits ); - - int FindNextSetBit(int iStartBit) const; // returns -1 if no set bit was found - -protected: - CVarBitVecBase(); - CVarBitVecBase(int numBits); - CVarBitVecBase( const CVarBitVecBase &from ); - CVarBitVecBase &operator=( const CVarBitVecBase &from ); - ~CVarBitVecBase(void); - - void ValidateOperand( const CVarBitVecBase &operand ) const { Assert(GetNumBits() == operand.GetNumBits()); } - - unsigned GetEndMask() const { return ::GetEndMask( GetNumBits() ); } - -private: - - unsigned short m_numBits; // Number of bits in the bitstring - unsigned short m_numInts; // Number of ints to needed to store bitstring - uint32 m_iBitStringStorage; // If the bit string fits in one int, it goes here - uint32 * m_pInt; // Array of ints containing the bitstring - - void AllocInts( int numInts ); // Free the allocated bits - void ReallocInts( int numInts ); - void FreeInts( void ); // Free the allocated bits -}; - -//----------------------------------------------------------------------------- -// class CFixedBitVecBase -// -// Defines the operations necessary for a fixed sized bit array. -// - -template struct BitCountToEndMask_t { }; -template <> struct BitCountToEndMask_t< 0> { enum { MASK = 0xffffffff }; }; -template <> struct BitCountToEndMask_t< 1> { enum { MASK = 0x00000001 }; }; -template <> struct BitCountToEndMask_t< 2> { enum { MASK = 0x00000003 }; }; -template <> struct BitCountToEndMask_t< 3> { enum { MASK = 0x00000007 }; }; -template <> struct BitCountToEndMask_t< 4> { enum { MASK = 0x0000000f }; }; -template <> struct BitCountToEndMask_t< 5> { enum { MASK = 0x0000001f }; }; -template <> struct BitCountToEndMask_t< 6> { enum { MASK = 0x0000003f }; }; -template <> struct BitCountToEndMask_t< 7> { enum { MASK = 0x0000007f }; }; -template <> struct BitCountToEndMask_t< 8> { enum { MASK = 0x000000ff }; }; -template <> struct BitCountToEndMask_t< 9> { enum { MASK = 0x000001ff }; }; -template <> struct BitCountToEndMask_t<10> { enum { MASK = 0x000003ff }; }; -template <> struct BitCountToEndMask_t<11> { enum { MASK = 0x000007ff }; }; -template <> struct BitCountToEndMask_t<12> { enum { MASK = 0x00000fff }; }; -template <> struct BitCountToEndMask_t<13> { enum { MASK = 0x00001fff }; }; -template <> struct BitCountToEndMask_t<14> { enum { MASK = 0x00003fff }; }; -template <> struct BitCountToEndMask_t<15> { enum { MASK = 0x00007fff }; }; -template <> struct BitCountToEndMask_t<16> { enum { MASK = 0x0000ffff }; }; -template <> struct BitCountToEndMask_t<17> { enum { MASK = 0x0001ffff }; }; -template <> struct BitCountToEndMask_t<18> { enum { MASK = 0x0003ffff }; }; -template <> struct BitCountToEndMask_t<19> { enum { MASK = 0x0007ffff }; }; -template <> struct BitCountToEndMask_t<20> { enum { MASK = 0x000fffff }; }; -template <> struct BitCountToEndMask_t<21> { enum { MASK = 0x001fffff }; }; -template <> struct BitCountToEndMask_t<22> { enum { MASK = 0x003fffff }; }; -template <> struct BitCountToEndMask_t<23> { enum { MASK = 0x007fffff }; }; -template <> struct BitCountToEndMask_t<24> { enum { MASK = 0x00ffffff }; }; -template <> struct BitCountToEndMask_t<25> { enum { MASK = 0x01ffffff }; }; -template <> struct BitCountToEndMask_t<26> { enum { MASK = 0x03ffffff }; }; -template <> struct BitCountToEndMask_t<27> { enum { MASK = 0x07ffffff }; }; -template <> struct BitCountToEndMask_t<28> { enum { MASK = 0x0fffffff }; }; -template <> struct BitCountToEndMask_t<29> { enum { MASK = 0x1fffffff }; }; -template <> struct BitCountToEndMask_t<30> { enum { MASK = 0x3fffffff }; }; -template <> struct BitCountToEndMask_t<31> { enum { MASK = 0x7fffffff }; }; - -//------------------------------------- - -template -class CFixedBitVecBase -{ -public: - bool IsFixedSize() const { return true; } - int GetNumBits(void) const { return NUM_BITS; } - void Resize( int numBits, bool bClearAll = false ) { Assert(numBits == NUM_BITS); if ( bClearAll ) memset( m_Ints, 0, NUM_INTS * sizeof(uint32) ); }// for syntatic consistency (for when using templates) - - int GetNumDWords() const { return NUM_INTS; } - uint32 * Base() { return m_Ints; } - const uint32 * Base() const { return m_Ints; } - - int FindNextSetBit(int iStartBit) const; // returns -1 if no set bit was found - -protected: - CFixedBitVecBase() {} - CFixedBitVecBase(int numBits) { Assert( numBits == NUM_BITS ); } // doesn't make sense, really. Supported to simplify templates & allow easy replacement of variable - - void ValidateOperand( const CFixedBitVecBase &operand ) const { } // no need, compiler does so statically - -public: // for test code - unsigned GetEndMask() const { return static_cast( BitCountToEndMask_t::MASK ); } - -private: - enum - { - NUM_INTS = (NUM_BITS + (BITS_PER_INT-1)) / BITS_PER_INT - }; - - uint32 m_Ints[(NUM_BITS + (BITS_PER_INT-1)) / BITS_PER_INT]; -}; - -//----------------------------------------------------------------------------- -// -// The actual classes used -// - -// inheritance instead of typedef to allow forward declarations -class CVarBitVec : public CBitVecT -{ -public: - CVarBitVec() - { - } - - CVarBitVec(int numBits) - : CBitVecT(numBits) - { - } -}; - -//----------------------------------------------------------------------------- - -template < int NUM_BITS > -class CBitVec : public CBitVecT< CFixedBitVecBase > -{ -public: - CBitVec() - { - } - - CBitVec(int numBits) - : CBitVecT< CFixedBitVecBase >(numBits) - { - } -}; - - -//----------------------------------------------------------------------------- - -typedef CBitVec<32> CDWordBitVec; - -//----------------------------------------------------------------------------- - -inline CVarBitVecBase::CVarBitVecBase() -{ - memset( this, 0, sizeof( *this ) ); -} - -//----------------------------------------------------------------------------- - -inline CVarBitVecBase::CVarBitVecBase(int numBits) -{ - Assert( numBits ); - m_numBits = numBits; - - // Figure out how many ints are needed - m_numInts = CalcNumIntsForBits( numBits ); - m_pInt = NULL; - AllocInts( m_numInts ); -} - -//----------------------------------------------------------------------------- - -inline CVarBitVecBase::CVarBitVecBase( const CVarBitVecBase &from ) -{ - if ( from.m_numInts ) - { - m_numBits = from.m_numBits; - m_numInts = from.m_numInts; - m_pInt = NULL; - AllocInts( m_numInts ); - memcpy( m_pInt, from.m_pInt, m_numInts * sizeof(int) ); - } - else - memset( this, 0, sizeof( *this ) ); -} - -//----------------------------------------------------------------------------- - -inline CVarBitVecBase &CVarBitVecBase::operator=( const CVarBitVecBase &from ) -{ - Resize( from.GetNumBits() ); - if ( m_pInt ) - memcpy( m_pInt, from.m_pInt, m_numInts * sizeof(int) ); - return (*this); -} - -//----------------------------------------------------------------------------- -// Purpose: Destructor -// Input : -// Output : -//----------------------------------------------------------------------------- - -inline CVarBitVecBase::~CVarBitVecBase(void) -{ - FreeInts(); -} - -//----------------------------------------------------------------------------- - -inline void CVarBitVecBase::Attach( uint32 *pBits, int numBits ) -{ - FreeInts(); - m_numBits = numBits; - m_numInts = CalcNumIntsForBits( numBits ); - if ( m_numInts > 1 ) - { - m_pInt = pBits; - } - else - { - m_iBitStringStorage = *pBits; - m_pInt = &m_iBitStringStorage; - free( pBits ); - } -} - -//----------------------------------------------------------------------------- - -inline bool CVarBitVecBase::Detach( uint32 **ppBits, int *pNumBits ) -{ - if ( !m_numBits ) - { - return false; - } - - *pNumBits = m_numBits; - if ( m_numInts > 1 ) - { - *ppBits = m_pInt; - } - else - { - *ppBits = (uint32 *)malloc( sizeof(uint32) ); - **ppBits = m_iBitStringStorage; - free( m_pInt ); - } - - memset( this, 0, sizeof( *this ) ); - return true; -} - -//----------------------------------------------------------------------------- - -template -inline CBitVecT::CBitVecT() -{ - // undef this is ints are not 4 bytes - // generate a compile error if sizeof(int) is not 4 (HACK: can't use the preprocessor so use the compiler) - - COMPILE_TIME_ASSERT( sizeof(int)==4 ); - - // Initialize bitstring by clearing all bits - ClearAll(); -} - -//----------------------------------------------------------------------------- -template -inline CBitVecT::CBitVecT(int numBits) - : BASE_OPS( numBits ) -{ - // undef this is ints are not 4 bytes - // generate a compile error if sizeof(int) is not 4 (HACK: can't use the preprocessor so use the compiler) - - COMPILE_TIME_ASSERT( sizeof(int)==4 ); - - // Initialize bitstring by clearing all bits - ClearAll(); -} - -//----------------------------------------------------------------------------- - -template -inline CBitVecAccessor CBitVecT::operator[](int i) -{ - Assert(i >= 0 && i < this->GetNumBits()); - return CBitVecAccessor(this->Base(), i); -} - - -//----------------------------------------------------------------------------- - -template -inline void CBitVecT::Init( int val ) -{ - if ( this->Base() ) - memset( this->Base(), ( val ) ? 0xff : 0, this->GetNumDWords() * sizeof(int) ); -} - -//----------------------------------------------------------------------------- - -template -inline uint32 CBitVecT::Get( uint32 bitNum ) const -{ - Assert( bitNum < (uint32)this->GetNumBits() ); - const uint32 *pInt = this->Base() + BitVec_Int( bitNum ); - return ( *pInt & BitVec_Bit( bitNum ) ); -} - -//----------------------------------------------------------------------------- - -template -inline bool CBitVecT::IsBitSet( int bitNum ) const -{ - Assert( bitNum >= 0 && bitNum < this->GetNumBits() ); - const uint32 *pInt = this->Base() + BitVec_Int( bitNum ); - return ( ( *pInt & BitVec_Bit( bitNum ) ) != 0 ); -} - -//----------------------------------------------------------------------------- - -template -inline void CBitVecT::Set( int bitNum ) -{ - Assert( bitNum >= 0 && bitNum < this->GetNumBits() ); - uint32 *pInt = this->Base() + BitVec_Int( bitNum ); - *pInt |= BitVec_Bit( bitNum ); -} - -//----------------------------------------------------------------------------- - -template -inline bool CBitVecT::TestAndSet(int bitNum) -{ - Assert( bitNum >= 0 && bitNum < this->GetNumBits() ); - uint32 bitVecBit = BitVec_Bit( bitNum ); - uint32 *pInt = this->Base() + BitVec_Int( bitNum ); - bool bResult = ( ( *pInt & bitVecBit) != 0 ); - *pInt |= bitVecBit; - return bResult; -} - -//----------------------------------------------------------------------------- - -template -inline void CBitVecT::Clear(int bitNum) -{ - Assert( bitNum >= 0 && bitNum < this->GetNumBits() ); - uint32 *pInt = this->Base() + BitVec_Int( bitNum ); - *pInt &= ~BitVec_Bit( bitNum ); -} - -//----------------------------------------------------------------------------- - -template -inline void CBitVecT::Set( int bitNum, bool bNewVal ) -{ - uint32 *pInt = this->Base() + BitVec_Int( bitNum ); - uint32 bitMask = BitVec_Bit( bitNum ); - if ( bNewVal ) - { - *pInt |= bitMask; - } - else - { - *pInt &= ~bitMask; - } -} - -//----------------------------------------------------------------------------- - -template -inline void CBitVecT::Set( uint32 offset, uint32 mask ) -{ - uint32 *pInt = this->Base() + offset; - *pInt |= mask; -} - -//----------------------------------------------------------------------------- - -template -inline void CBitVecT::Clear( uint32 offset, uint32 mask ) -{ - uint32 *pInt = this->Base() + offset; - *pInt &= ~mask; -} - -//----------------------------------------------------------------------------- - -template -inline uint32 CBitVecT::Get( uint32 offset, uint32 mask ) -{ - uint32 *pInt = this->Base() + offset; - return ( *pInt & mask ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -template -inline void CBitVecT::And(const CBitVecT &addStr, CBitVecT *out) const -{ - this->ValidateOperand( addStr ); - this->ValidateOperand( *out ); - - uint32 * pDest = out->Base(); - const uint32 *pOperand1 = this->Base(); - const uint32 *pOperand2 = addStr.Base(); - - for (int i = this->GetNumDWords() - 1; i >= 0 ; --i) - { - pDest[i] = pOperand1[i] & pOperand2[i]; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -template -inline void CBitVecT::Or(const CBitVecT &orStr, CBitVecT *out) const -{ - this->ValidateOperand( orStr ); - this->ValidateOperand( *out ); - - uint32 * pDest = out->Base(); - const uint32 *pOperand1 = this->Base(); - const uint32 *pOperand2 = orStr.Base(); - - for (int i = this->GetNumDWords() - 1; i >= 0; --i) - { - pDest[i] = pOperand1[i] | pOperand2[i]; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -template -inline void CBitVecT::Xor(const CBitVecT &xorStr, CBitVecT *out) const -{ - uint32 * pDest = out->Base(); - const uint32 *pOperand1 = this->Base(); - const uint32 *pOperand2 = xorStr.Base(); - - for (int i = this->GetNumDWords() - 1; i >= 0; --i) - { - pDest[i] = pOperand1[i] ^ pOperand2[i]; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : -// Output : -//----------------------------------------------------------------------------- -template -inline void CBitVecT::Not(CBitVecT *out) const -{ - this->ValidateOperand( *out ); - - uint32 * pDest = out->Base(); - const uint32 *pOperand = this->Base(); - - for (int i = this->GetNumDWords() - 1; i >= 0; --i) - { - pDest[i] = ~(pOperand[i]); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Copy a bit string -// Input : -// Output : -//----------------------------------------------------------------------------- -template -inline void CBitVecT::CopyTo(CBitVecT *out) const -{ - out->Resize( this->GetNumBits() ); - - this->ValidateOperand( *out ); - Assert( out != this ); - - memcpy( out->Base(), this->Base(), this->GetNumDWords() * sizeof( int ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: Are all bits zero? -// Input : -// Output : -//----------------------------------------------------------------------------- -template -inline bool CBitVecT::IsAllClear(void) const -{ - // Number of available bits may be more than the number - // actually used, so make sure to mask out unused bits - // before testing for zero - (const_cast(this))->Base()[this->GetNumDWords()-1] &= CBitVecT::GetEndMask(); // external semantics of const retained - - for (int i = this->GetNumDWords() - 1; i >= 0; --i) - { - if ( this->Base()[i] !=0 ) - { - return false; - } - } - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Are all bits set? -// Input : -// Output : -//----------------------------------------------------------------------------- -template -inline bool CBitVecT::IsAllSet(void) const -{ - // Number of available bits may be more than the number - // actually used, so make sure to mask out unused bits - // before testing for set bits - (const_cast(this))->Base()[this->GetNumDWords()-1] |= ~CBitVecT::GetEndMask(); // external semantics of const retained - - for (int i = this->GetNumDWords() - 1; i >= 0; --i) - { - if ( this->Base()[i] != ~0 ) - { - return false; - } - } - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Sets all bits -// Input : -// Output : -//----------------------------------------------------------------------------- -template -inline void CBitVecT::SetAll(void) -{ - if ( this->Base() ) - memset( this->Base(), 0xff, this->GetNumDWords() * sizeof(int) ); -} - -//----------------------------------------------------------------------------- -// Purpose: Clears all bits -// Input : -// Output : -//----------------------------------------------------------------------------- -template -inline void CBitVecT::ClearAll(void) -{ - if ( this->Base() ) - memset( this->Base(), 0, this->GetNumDWords() * sizeof(int) ); -} - -//----------------------------------------------------------------------------- -template -inline void CBitVecT::Copy( const CBitVecT &other, int nBits ) -{ - if ( nBits == - 1 ) - { - nBits = other.GetNumBits(); - } - - this->Resize( nBits ); - - this->ValidateOperand( other ); - Assert( &other != this ); - - memcpy( this->Base(), other.Base(), this->GetNumDWords() * sizeof( uint32 ) ); -} - -//----------------------------------------------------------------------------- -template -inline bool CBitVecT::Compare( const CBitVecT &other, int nBits ) const -{ - if ( nBits == - 1 ) - { - if ( other.GetNumBits() != this->GetNumBits() ) - { - return false; - } - - nBits = other.GetNumBits(); - } - - if ( nBits > other.GetNumBits() || nBits > this->GetNumBits() ) - { - return false; - } - - (const_cast(this))->Base()[this->GetNumDWords()-1] &= CBitVecT::GetEndMask(); // external semantics of const retained - (const_cast(&other))->Base()[this->GetNumDWords()-1] &= other.CBitVecT::GetEndMask(); // external semantics of const retained - - int nBytes = PAD_NUMBER( nBits, 8 ) >> 3; - - return ( memcmp( this->Base(), other.Base(), nBytes ) == 0 ); -} - -//----------------------------------------------------------------------------- -template -inline uint32 CBitVecT::GetDWord(int i) const -{ - Assert(i >= 0 && i < this->GetNumDWords()); - return this->Base()[i]; -} - -//----------------------------------------------------------------------------- -template -inline void CBitVecT::SetDWord(int i, uint32 val) -{ - Assert(i >= 0 && i < this->GetNumDWords()); - this->Base()[i] = val; -} - -//----------------------------------------------------------------------------- - -inline unsigned GetStartBitMask( int startBit ) -{ - static unsigned int g_StartMask[32] = - { - 0xffffffff, - 0xfffffffe, - 0xfffffffc, - 0xfffffff8, - 0xfffffff0, - 0xffffffe0, - 0xffffffc0, - 0xffffff80, - 0xffffff00, - 0xfffffe00, - 0xfffffc00, - 0xfffff800, - 0xfffff000, - 0xffffe000, - 0xffffc000, - 0xffff8000, - 0xffff0000, - 0xfffe0000, - 0xfffc0000, - 0xfff80000, - 0xfff00000, - 0xffe00000, - 0xffc00000, - 0xff800000, - 0xff000000, - 0xfe000000, - 0xfc000000, - 0xf8000000, - 0xf0000000, - 0xe0000000, - 0xc0000000, - 0x80000000, - }; - - return g_StartMask[ startBit & 31 ]; -} - -inline int CVarBitVecBase::FindNextSetBit( int startBit ) const -{ - if ( startBit < GetNumBits() ) - { - int wordIndex = BitVec_Int(startBit); - unsigned int startMask = GetStartBitMask( startBit ); - int lastWord = GetNumDWords()-1; - - // handle non dword lengths - if ( (GetNumBits() % BITS_PER_INT) != 0 ) - { - unsigned int elem = Base()[wordIndex]; - elem &= startMask; - if ( wordIndex == lastWord) - { - elem &= (GetEndMask()); - // there's a bit remaining in this word - if ( elem ) - return FirstBitInWord(elem, wordIndex << 5); - } - else - { - // there's a bit remaining in this word - if ( elem ) - return FirstBitInWord(elem, wordIndex << 5); - - // iterate the words - for ( int i = wordIndex+1; i < lastWord; i++ ) - { - elem = Base()[i]; - if ( elem ) - return FirstBitInWord(elem, i << 5); - } - elem = Base()[lastWord] & GetEndMask(); - if ( elem ) - return FirstBitInWord(elem, lastWord << 5); - } - } - else - { - const uint32 * RESTRICT pCurElem = Base() + wordIndex; - unsigned int elem = *pCurElem; - elem &= startMask; - do - { - if ( elem ) - return FirstBitInWord(elem, wordIndex << 5); - ++pCurElem; - elem = *pCurElem; - ++wordIndex; - } while( wordIndex <= lastWord ); - } - - } - - return -1; -} - -template -inline int CFixedBitVecBase::FindNextSetBit( int startBit ) const -{ - if ( startBit < NUM_BITS ) - { - int wordIndex = BitVec_Int(startBit); - unsigned int startMask = GetStartBitMask( startBit ); - - // handle non dword lengths - if ( (NUM_BITS % BITS_PER_INT) != 0 ) - { - unsigned int elem = Base()[wordIndex]; - elem &= startMask; - if ( wordIndex == NUM_INTS-1) - { - elem &= (GetEndMask()); - // there's a bit remaining in this word - if ( elem ) - return FirstBitInWord(elem, wordIndex << 5); - } - else - { - // there's a bit remaining in this word - if ( elem ) - return FirstBitInWord(elem, wordIndex << 5); - - // iterate the words - for ( int i = wordIndex+1; i < NUM_INTS-1; i++ ) - { - elem = Base()[i]; - if ( elem ) - return FirstBitInWord(elem, i << 5); - } - elem = Base()[NUM_INTS-1] & GetEndMask(); - if ( elem ) - return FirstBitInWord(elem, (NUM_INTS-1) << 5); - } - } - else - { - const uint32 * RESTRICT pCurElem = Base() + wordIndex; - unsigned int elem = *pCurElem; - elem &= startMask; - do - { - if ( elem ) - return FirstBitInWord(elem, wordIndex << 5); - ++pCurElem; - elem = *pCurElem; - ++wordIndex; - } while( wordIndex <= NUM_INTS-1); - } - - } - - return -1; -} - -//----------------------------------------------------------------------------- -// Unrolled loops for some common sizes - -template<> -FORCEINLINE_TEMPLATE void CBitVecT< CFixedBitVecBase<256> >::And(const CBitVecT &addStr, CBitVecT *out) const -{ - uint32 * pDest = out->Base(); - const uint32 *pOperand1 = Base(); - const uint32 *pOperand2 = addStr.Base(); - - pDest[0] = pOperand1[0] & pOperand2[0]; - pDest[1] = pOperand1[1] & pOperand2[1]; - pDest[2] = pOperand1[2] & pOperand2[2]; - pDest[3] = pOperand1[3] & pOperand2[3]; - pDest[4] = pOperand1[4] & pOperand2[4]; - pDest[5] = pOperand1[5] & pOperand2[5]; - pDest[6] = pOperand1[6] & pOperand2[6]; - pDest[7] = pOperand1[7] & pOperand2[7]; -} - -template<> -FORCEINLINE_TEMPLATE bool CBitVecT< CFixedBitVecBase<256> >::IsAllClear(void) const -{ - const uint32 *pInts = Base(); - return ( pInts[0] == 0 && pInts[1] == 0 && pInts[2] == 0 && pInts[3] == 0 && pInts[4] == 0 && pInts[5] == 0 && pInts[6] == 0 && pInts[7] == 0 ); -} - -template<> -FORCEINLINE_TEMPLATE void CBitVecT< CFixedBitVecBase<256> >::CopyTo(CBitVecT *out) const -{ - uint32 * pDest = out->Base(); - const uint32 *pInts = Base(); - - pDest[0] = pInts[0]; - pDest[1] = pInts[1]; - pDest[2] = pInts[2]; - pDest[3] = pInts[3]; - pDest[4] = pInts[4]; - pDest[5] = pInts[5]; - pDest[6] = pInts[6]; - pDest[7] = pInts[7]; -} - -template<> -FORCEINLINE_TEMPLATE void CBitVecT< CFixedBitVecBase<128> >::And(const CBitVecT &addStr, CBitVecT *out) const -{ - uint32 * pDest = out->Base(); - const uint32 *pOperand1 = Base(); - const uint32 *pOperand2 = addStr.Base(); - - pDest[0] = pOperand1[0] & pOperand2[0]; - pDest[1] = pOperand1[1] & pOperand2[1]; - pDest[2] = pOperand1[2] & pOperand2[2]; - pDest[3] = pOperand1[3] & pOperand2[3]; -} - -template<> -FORCEINLINE_TEMPLATE bool CBitVecT< CFixedBitVecBase<128> >::IsAllClear(void) const -{ - const uint32 *pInts = Base(); - return ( pInts[0] == 0 && pInts[1] == 0 && pInts[2] == 0 && pInts[3] == 0 ); -} - -template<> -FORCEINLINE_TEMPLATE void CBitVecT< CFixedBitVecBase<128> >::CopyTo(CBitVecT *out) const -{ - uint32 * pDest = out->Base(); - const uint32 *pInts = Base(); - - pDest[0] = pInts[0]; - pDest[1] = pInts[1]; - pDest[2] = pInts[2]; - pDest[3] = pInts[3]; -} - -template<> -inline void CBitVecT< CFixedBitVecBase<96> >::And(const CBitVecT &addStr, CBitVecT *out) const -{ - uint32 * pDest = out->Base(); - const uint32 *pOperand1 = Base(); - const uint32 *pOperand2 = addStr.Base(); - - pDest[0] = pOperand1[0] & pOperand2[0]; - pDest[1] = pOperand1[1] & pOperand2[1]; - pDest[2] = pOperand1[2] & pOperand2[2]; -} - -template<> -inline bool CBitVecT< CFixedBitVecBase<96> >::IsAllClear(void) const -{ - const uint32 *pInts = Base(); - return ( pInts[0] == 0 && pInts[1] == 0 && pInts[2] == 0 ); -} - -template<> -inline void CBitVecT< CFixedBitVecBase<96> >::CopyTo(CBitVecT *out) const -{ - uint32 * pDest = out->Base(); - const uint32 *pInts = Base(); - - pDest[0] = pInts[0]; - pDest[1] = pInts[1]; - pDest[2] = pInts[2]; -} - -template<> -inline void CBitVecT< CFixedBitVecBase<64> >::And(const CBitVecT &addStr, CBitVecT *out) const -{ - uint32 * pDest = out->Base(); - const uint32 *pOperand1 = Base(); - const uint32 *pOperand2 = addStr.Base(); - - pDest[0] = pOperand1[0] & pOperand2[0]; - pDest[1] = pOperand1[1] & pOperand2[1]; -} - -template<> -inline bool CBitVecT< CFixedBitVecBase<64> >::IsAllClear(void) const -{ - const uint32 *pInts = Base(); - return ( pInts[0] == 0 && pInts[1] == 0 ); -} - -template<> -inline void CBitVecT< CFixedBitVecBase<64> >::CopyTo(CBitVecT *out) const -{ - uint32 * pDest = out->Base(); - const uint32 *pInts = Base(); - - pDest[0] = pInts[0]; - pDest[1] = pInts[1]; -} - -template<> -inline void CBitVecT< CFixedBitVecBase<32> >::And(const CBitVecT &addStr, CBitVecT *out) const -{ - uint32 * pDest = out->Base(); - const uint32 *pOperand1 = Base(); - const uint32 *pOperand2 = addStr.Base(); - - pDest[0] = pOperand1[0] & pOperand2[0]; -} - -template<> -inline bool CBitVecT< CFixedBitVecBase<32> >::IsAllClear(void) const -{ - const uint32 *pInts = Base(); - - return ( pInts[0] == 0 ); -} - -template<> -inline void CBitVecT< CFixedBitVecBase<32> >::CopyTo(CBitVecT *out) const -{ - uint32 * pDest = out->Base(); - const uint32 *pInts = Base(); - - pDest[0] = pInts[0]; -} - -//----------------------------------------------------------------------------- - -template <> -inline uint32 CBitVecT< CFixedBitVecBase<32> >::Get( uint32 bitNum ) const -{ - return ( *Base() & BitVec_Bit( bitNum ) ); -} - -//----------------------------------------------------------------------------- - -template <> -inline bool CBitVecT< CFixedBitVecBase<32> >::IsBitSet( int bitNum ) const -{ - return ( ( *Base() & BitVec_Bit( bitNum ) ) != 0 ); -} - -//----------------------------------------------------------------------------- - -template <> -inline void CBitVecT< CFixedBitVecBase<32> >::Set( int bitNum ) -{ - *Base() |= BitVec_Bit( bitNum ); -} - -//----------------------------------------------------------------------------- - -template <> -inline void CBitVecT< CFixedBitVecBase<32> >::Clear(int bitNum) -{ - *Base() &= ~BitVec_Bit( bitNum ); -} - -//----------------------------------------------------------------------------- - -template <> -inline void CBitVecT< CFixedBitVecBase<32> >::Set( int bitNum, bool bNewVal ) -{ - uint32 bitMask = BitVec_Bit( bitNum ); - if ( bNewVal ) - { - *Base() |= bitMask; - } - else - { - *Base() &= ~bitMask; - } -} - - -//----------------------------------------------------------------------------- - -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Resizes the bit string to a new number of bits -// Input : resizeNumBits - -//----------------------------------------------------------------------------- -inline void CVarBitVecBase::Resize( int resizeNumBits, bool bClearAll ) -{ - Assert( resizeNumBits >= 0 && resizeNumBits <= USHRT_MAX ); - - int newIntCount = CalcNumIntsForBits( resizeNumBits ); - if ( newIntCount != GetNumDWords() ) - { - if ( Base() ) - { - ReallocInts( newIntCount ); - if ( !bClearAll && resizeNumBits >= GetNumBits() ) - { - Base()[GetNumDWords() - 1] &= GetEndMask(); - memset( Base() + GetNumDWords(), 0, (newIntCount - GetNumDWords()) * sizeof(int) ); - } - } - else - { - // Figure out how many ints are needed - AllocInts( newIntCount ); - // Initialize bitstring by clearing all bits - bClearAll = true; - } - - m_numInts = newIntCount; - } - else if ( !bClearAll && resizeNumBits >= GetNumBits() && Base() ) - { - Base()[GetNumDWords() - 1] &= GetEndMask(); - } - - if ( bClearAll && Base() ) - { - memset( Base(), 0, newIntCount * sizeof(int) ); - } - - // store the new size and end mask - m_numBits = resizeNumBits; -} - -//----------------------------------------------------------------------------- -// Purpose: Allocate the storage for the ints -// Input : numInts - -//----------------------------------------------------------------------------- -inline void CVarBitVecBase::AllocInts( int numInts ) -{ - Assert( !m_pInt ); - - if ( numInts == 0 ) - return; - - if ( numInts == 1 ) - { - m_pInt = &m_iBitStringStorage; - return; - } - - m_pInt = (uint32 *)malloc( numInts * sizeof(int) ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Reallocate the storage for the ints -// Input : numInts - -//----------------------------------------------------------------------------- -inline void CVarBitVecBase::ReallocInts( int numInts ) -{ - Assert( Base() ); - if ( numInts == 0) - { - FreeInts(); - return; - } - - if ( m_pInt == &m_iBitStringStorage ) - { - if ( numInts != 1 ) - { - m_pInt = ((uint32 *)malloc( numInts * sizeof(int) )); - *m_pInt = m_iBitStringStorage; - } - - return; - } - - if ( numInts == 1 ) - { - m_iBitStringStorage = *m_pInt; - free( m_pInt ); - m_pInt = &m_iBitStringStorage; - return; - } - - m_pInt = (uint32 *)realloc( m_pInt, numInts * sizeof(int) ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Free storage allocated with AllocInts -//----------------------------------------------------------------------------- -inline void CVarBitVecBase::FreeInts( void ) -{ - if ( m_numInts > 1 ) - { - free( m_pInt ); - } - m_pInt = NULL; -} - -#include "tier0/memdbgoff.h" - -// ------------------------------------------------------------------------ // -// CBitVecAccessor inlines. -// ------------------------------------------------------------------------ // - -inline CBitVecAccessor::CBitVecAccessor(uint32 *pDWords, int iBit) -{ - m_pDWords = pDWords; - m_iBit = iBit; -} - - -inline void CBitVecAccessor::operator=(int val) -{ - if(val) - m_pDWords[m_iBit >> 5] |= (1 << (m_iBit & 31)); - else - m_pDWords[m_iBit >> 5] &= ~(unsigned long)(1 << (m_iBit & 31)); -} - -inline CBitVecAccessor::operator uint32() -{ - return m_pDWords[m_iBit >> 5] & (1 << (m_iBit & 31)); -} - - -//============================================================================= - -#endif // BITVEC_H diff --git a/public/blockingudpsocket.cpp b/public/blockingudpsocket.cpp deleted file mode 100644 index 5dab3e231..000000000 --- a/public/blockingudpsocket.cpp +++ /dev/null @@ -1,150 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#if defined(_WIN32) && !defined(_X360) -#include -#elif _LINUX -#define INVALID_SOCKET -1 -#define SOCKET_ERROR -1 -#include -#include -#include -#include -#define closesocket close -#endif - -#include "blockingudpsocket.h" -#include "tier0/vcrmode.h" - -class CBlockingUDPSocket::CImpl -{ -public: - struct sockaddr_in m_SocketIP; - fd_set m_FDSet; -}; - -CBlockingUDPSocket::CBlockingUDPSocket() : - m_cserIP(), - m_Socket( 0 ), - m_pImpl( new CImpl ) -{ - CreateSocket(); -} - -CBlockingUDPSocket::~CBlockingUDPSocket() -{ - delete m_pImpl; - closesocket( static_cast( m_Socket )); -} - -bool CBlockingUDPSocket::CreateSocket (void) -{ - struct sockaddr_in address; - - m_Socket = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP ); - if ( m_Socket == INVALID_SOCKET ) - { - return false; - } - - address = m_pImpl->m_SocketIP; - - if ( SOCKET_ERROR == bind( m_Socket, ( struct sockaddr * )&address, sizeof( address ) ) ) - { - return false; - } - -#ifdef _WIN32 - if ( m_pImpl->m_SocketIP.sin_addr.S_un.S_addr == INADDR_ANY ) - { - m_pImpl->m_SocketIP.sin_addr.S_un.S_addr = 0L; - } -#elif _LINUX - if ( m_pImpl->m_SocketIP.sin_addr.s_addr == INADDR_ANY ) - { - m_pImpl->m_SocketIP.sin_addr.s_addr = 0L; - } -#endif - - return true; -} - -bool CBlockingUDPSocket::WaitForMessage( float timeOutInSeconds ) -{ - struct timeval tv; - - FD_ZERO( &m_pImpl->m_FDSet ); - FD_SET( m_Socket, &m_pImpl->m_FDSet );//lint !e717 - - tv.tv_sec = (int)timeOutInSeconds; - float remainder = timeOutInSeconds - (int)timeOutInSeconds; - tv.tv_usec = (int)( remainder * 1000000 + 0.5f ); /* micro seconds */ - - if ( SOCKET_ERROR == select( ( int )m_Socket + 1, &m_pImpl->m_FDSet, NULL, NULL, &tv ) ) - { - return false; - } - - if ( FD_ISSET( m_Socket, &m_pImpl->m_FDSet) ) - { - return true; - } - - // Timed out - return false; -} - -unsigned int CBlockingUDPSocket::ReceiveSocketMessage( struct sockaddr_in *packet_from, unsigned char *buf, size_t bufsize ) -{ - memset( packet_from, 0, sizeof( *packet_from ) ); - - struct sockaddr fromaddress; - int fromlen = sizeof( fromaddress ); - - int packet_length = VCRHook_recvfrom - ( - m_Socket, - (char *)buf, - (int)bufsize, - 0, - &fromaddress, - &fromlen - ); - - if ( SOCKET_ERROR == packet_length ) - { - return 0; - } - - // In case it's parsed as a string - buf[ packet_length ] = 0; - - // Copy over the receive address - *packet_from = *( struct sockaddr_in * )&fromaddress; - - return ( unsigned int )packet_length; -} - -bool CBlockingUDPSocket::SendSocketMessage( const struct sockaddr_in & rRecipient, const unsigned char *buf, size_t bufsize ) -{ - // Send data - int bytesSent = sendto - ( - m_Socket, - (const char *)buf, - (int)bufsize, - 0, - reinterpret_cast< const sockaddr * >( &rRecipient ), - sizeof( rRecipient ) - ); - - if ( SOCKET_ERROR == bytesSent ) - { - return false; - } - - return true; -} diff --git a/public/blockingudpsocket.h b/public/blockingudpsocket.h deleted file mode 100644 index b30520aaa..000000000 --- a/public/blockingudpsocket.h +++ /dev/null @@ -1,39 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef BLOCKINGUDPSOCKET_H -#define BLOCKINGUDPSOCKET_H -#ifdef _WIN32 -#pragma once -#endif - -#include "netadr.h" - -class CBlockingUDPSocket -{ -public: - explicit CBlockingUDPSocket(); - virtual ~CBlockingUDPSocket(); - - bool WaitForMessage( float timeOutInSeconds ); - unsigned int ReceiveSocketMessage( struct sockaddr_in *packet_from, unsigned char *buf, size_t bufsize ); - bool SendSocketMessage( const struct sockaddr_in& rRecipient, const unsigned char *buf, size_t bufsize ); - - bool IsValid() const { return m_Socket != 0; } - -protected: - bool CreateSocket (void); - - class CImpl; - CImpl *m_pImpl; - - netadr_t m_cserIP; - unsigned int m_Socket; - - -}; - -#endif // BLOCKINGUDPSOCKET_H diff --git a/public/bone_accessor.cpp b/public/bone_accessor.cpp deleted file mode 100644 index d7436db3f..000000000 --- a/public/bone_accessor.cpp +++ /dev/null @@ -1,34 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "cbase.h" -#include "bone_accessor.h" - - -#if defined( CLIENT_DLL ) && defined( _DEBUG ) - - void CBoneAccessor::SanityCheckBone( int iBone, bool bReadable ) const - { - if ( m_pAnimating ) - { - CStudioHdr *pHdr = m_pAnimating->GetModelPtr(); - if ( pHdr ) - { - mstudiobone_t *pBone = pHdr->pBone( iBone ); - if ( bReadable ) - { - AssertOnce( pBone->flags & m_ReadableBones ); - } - else - { - AssertOnce( pBone->flags & m_WritableBones ); - } - } - } - } - -#endif - diff --git a/public/bone_accessor.h b/public/bone_accessor.h deleted file mode 100644 index 442fb4ef5..000000000 --- a/public/bone_accessor.h +++ /dev/null @@ -1,131 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef BONE_ACCESSOR_H -#define BONE_ACCESSOR_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "studio.h" - - -class C_BaseAnimating; - - -class CBoneAccessor -{ -public: - - CBoneAccessor(); - CBoneAccessor( matrix3x4_t *pBones ); // This can be used to allow access to all bones. - - // Initialize. -#if defined( CLIENT_DLL ) - void Init( const C_BaseAnimating *pAnimating, matrix3x4_t *pBones ); -#endif - - int GetReadableBones(); - void SetReadableBones( int flags ); - - int GetWritableBones(); - void SetWritableBones( int flags ); - - // Get bones for read or write access. - const matrix3x4_t& GetBone( int iBone ) const; - const matrix3x4_t& operator[]( int iBone ) const; - matrix3x4_t& GetBoneForWrite( int iBone ); - - matrix3x4_t *GetBoneArrayForWrite( ) const; - -private: - -#if defined( CLIENT_DLL ) && defined( _DEBUG ) - void SanityCheckBone( int iBone, bool bReadable ) const; -#endif - - // Only used in the client DLL for debug verification. - const C_BaseAnimating *m_pAnimating; - - matrix3x4_t *m_pBones; - - int m_ReadableBones; // Which bones can be read. - int m_WritableBones; // Which bones can be written. -}; - - -inline CBoneAccessor::CBoneAccessor() -{ - m_pAnimating = NULL; - m_pBones = NULL; - m_ReadableBones = m_WritableBones = 0; -} - -inline CBoneAccessor::CBoneAccessor( matrix3x4_t *pBones ) -{ - m_pAnimating = NULL; - m_pBones = pBones; -} - -#if defined( CLIENT_DLL ) - inline void CBoneAccessor::Init( const C_BaseAnimating *pAnimating, matrix3x4_t *pBones ) - { - m_pAnimating = pAnimating; - m_pBones = pBones; - } -#endif - -inline int CBoneAccessor::GetReadableBones() -{ - return m_ReadableBones; -} - -inline void CBoneAccessor::SetReadableBones( int flags ) -{ - m_ReadableBones = flags; -} - -inline int CBoneAccessor::GetWritableBones() -{ - return m_WritableBones; -} - -inline void CBoneAccessor::SetWritableBones( int flags ) -{ - m_WritableBones = flags; -} - -inline const matrix3x4_t& CBoneAccessor::GetBone( int iBone ) const -{ -#if defined( CLIENT_DLL ) && defined( _DEBUG ) - SanityCheckBone( iBone, true ); -#endif - return m_pBones[iBone]; -} - -inline const matrix3x4_t& CBoneAccessor::operator[]( int iBone ) const -{ -#if defined( CLIENT_DLL ) && defined( _DEBUG ) - SanityCheckBone( iBone, true ); -#endif - return m_pBones[iBone]; -} - -inline matrix3x4_t& CBoneAccessor::GetBoneForWrite( int iBone ) -{ -#if defined( CLIENT_DLL ) && defined( _DEBUG ) - SanityCheckBone( iBone, false ); -#endif - return m_pBones[iBone]; -} - -inline matrix3x4_t *CBoneAccessor::GetBoneArrayForWrite( void ) const -{ - return m_pBones; -} - -#endif // BONE_ACCESSOR_H diff --git a/public/bone_setup.cpp b/public/bone_setup.cpp deleted file mode 100644 index 7bb443ead..000000000 --- a/public/bone_setup.cpp +++ /dev/null @@ -1,5800 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// - -#include "tier0/dbg.h" -#include "mathlib/mathlib.h" -#include "bone_setup.h" -#include - -#include "collisionutils.h" -#include "vstdlib/random.h" -#include "tier0/vprof.h" -#include "bone_accessor.h" -#include "mathlib/ssequaternion.h" -#include "bitvec.h" -#include "datamanager.h" -#include "convar.h" -#include "tier0/tslist.h" -#include "vphysics_interface.h" -#ifdef CLIENT_DLL - #include "posedebugger.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// ----------------------------------------------------------------- -template -class CBoneSetupMemoryPool -{ -public: - T *Alloc() - { - T *p = (T *)m_FreeBlocks.Pop(); - if ( !p ) - { - p = new T[MAXSTUDIOBONES]; - if ( ((size_t)p) % TSLIST_NODE_ALIGNMENT != 0 ) - DebuggerBreak(); - } - - return p; - } - - void Free( T *p ) - { - m_FreeBlocks.Push( (TSLNodeBase_t *)p ); - } - -private: - CTSListBase m_FreeBlocks; -}; - -CBoneSetupMemoryPool g_QaternionPool; -CBoneSetupMemoryPool g_VectorPool; -CBoneSetupMemoryPool g_MatrixPool; - -// ----------------------------------------------------------------- -CBoneCache *CBoneCache::CreateResource( const bonecacheparams_t ¶ms ) -{ - short studioToCachedIndex[MAXSTUDIOBONES]; - short cachedToStudioIndex[MAXSTUDIOBONES]; - int cachedBoneCount = 0; - for ( int i = 0; i < params.pStudioHdr->numbones(); i++ ) - { - // skip bones that aren't part of the boneMask (and aren't the root bone) - if (i != 0 && !(params.pStudioHdr->boneFlags(i) & params.boneMask)) - { - studioToCachedIndex[i] = -1; - continue; - } - studioToCachedIndex[i] = cachedBoneCount; - cachedToStudioIndex[cachedBoneCount] = i; - cachedBoneCount++; - } - int tableSizeStudio = sizeof(short) * params.pStudioHdr->numbones(); - int tableSizeCached = sizeof(short) * cachedBoneCount; - int matrixSize = sizeof(matrix3x4_t) * cachedBoneCount; - int size = ( sizeof(CBoneCache) + tableSizeStudio + tableSizeCached + matrixSize + 3 ) & ~3; - - CBoneCache *pMem = (CBoneCache *)malloc( size ); - Construct( pMem ); - pMem->Init( params, size, studioToCachedIndex, cachedToStudioIndex, cachedBoneCount ); - return pMem; -} - -unsigned int CBoneCache::EstimatedSize( const bonecacheparams_t ¶ms ) -{ - // conservative estimate - max size - return ( params.pStudioHdr->numbones() * (sizeof(short) + sizeof(short) + sizeof(matrix3x4_t)) + 3 ) & ~3; -} - -void CBoneCache::DestroyResource() -{ - free( this ); -} - - -CBoneCache::CBoneCache() -{ - m_size = 0; - m_cachedBoneCount = 0; -} - -void CBoneCache::Init( const bonecacheparams_t ¶ms, unsigned int size, short *pStudioToCached, short *pCachedToStudio, int cachedBoneCount ) -{ - m_cachedBoneCount = cachedBoneCount; - m_size = size; - m_timeValid = params.curtime; - m_boneMask = params.boneMask; - - int studioTableSize = params.pStudioHdr->numbones() * sizeof(short); - m_cachedToStudioOffset = studioTableSize; - memcpy( StudioToCached(), pStudioToCached, studioTableSize ); - - int cachedTableSize = cachedBoneCount * sizeof(short); - memcpy( CachedToStudio(), pCachedToStudio, cachedTableSize ); - - m_matrixOffset = ( m_cachedToStudioOffset + cachedTableSize + 3 ) & ~3; - - UpdateBones( params.pBoneToWorld, params.pStudioHdr->numbones(), params.curtime ); -} - -void CBoneCache::UpdateBones( const matrix3x4_t *pBoneToWorld, int numbones, float curtime ) -{ - matrix3x4_t *pBones = BoneArray(); - const short *pCachedToStudio = CachedToStudio(); - - for ( int i = 0; i < m_cachedBoneCount; i++ ) - { - int index = pCachedToStudio[i]; - MatrixCopy( pBoneToWorld[index], pBones[i] ); - } - m_timeValid = curtime; -} - -matrix3x4_t *CBoneCache::GetCachedBone( int studioIndex ) -{ - int cachedIndex = StudioToCached()[studioIndex]; - if ( cachedIndex >= 0 ) - { - return BoneArray() + cachedIndex; - } - return NULL; -} - -void CBoneCache::ReadCachedBones( matrix3x4_t *pBoneToWorld ) -{ - matrix3x4_t *pBones = BoneArray(); - const short *pCachedToStudio = CachedToStudio(); - for ( int i = 0; i < m_cachedBoneCount; i++ ) - { - MatrixCopy( pBones[i], pBoneToWorld[pCachedToStudio[i]] ); - } -} - -void CBoneCache::ReadCachedBonePointers( matrix3x4_t **bones, int numbones ) -{ - memset( bones, 0, sizeof(matrix3x4_t *) * numbones ); - matrix3x4_t *pBones = BoneArray(); - const short *pCachedToStudio = CachedToStudio(); - for ( int i = 0; i < m_cachedBoneCount; i++ ) - { - bones[pCachedToStudio[i]] = pBones + i; - } -} - -bool CBoneCache::IsValid( float curtime, float dt ) -{ - if ( curtime - m_timeValid <= dt ) - return true; - return false; -} - - -// private functions -matrix3x4_t *CBoneCache::BoneArray() -{ - return (matrix3x4_t *)( (char *)(this+1) + m_matrixOffset ); -} - -short *CBoneCache::StudioToCached() -{ - return (short *)( (char *)(this+1) ); -} - -short *CBoneCache::CachedToStudio() -{ - return (short *)( (char *)(this+1) + m_cachedToStudioOffset ); -} - -// Construct a singleton -static CDataManager g_StudioBoneCache( 24 * 1024L ); - -CBoneCache *Studio_GetBoneCache( memhandle_t cacheHandle ) -{ - AUTO_LOCK( g_StudioBoneCache.AccessMutex() ); - return g_StudioBoneCache.GetResource_NoLock( cacheHandle ); -} - -memhandle_t Studio_CreateBoneCache( bonecacheparams_t ¶ms ) -{ - AUTO_LOCK( g_StudioBoneCache.AccessMutex() ); - return g_StudioBoneCache.CreateResource( params ); -} - -void Studio_DestroyBoneCache( memhandle_t cacheHandle ) -{ - AUTO_LOCK( g_StudioBoneCache.AccessMutex() ); - g_StudioBoneCache.DestroyResource( cacheHandle ); -} - -void Studio_InvalidateBoneCache( memhandle_t cacheHandle ) -{ - AUTO_LOCK( g_StudioBoneCache.AccessMutex() ); - CBoneCache *pCache = g_StudioBoneCache.GetResource_NoLock( cacheHandle ); - if ( pCache ) - { - pCache->m_timeValid = -1.0f; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -void BuildBoneChain( - const CStudioHdr *pStudioHdr, - const matrix3x4_t &rootxform, - const Vector pos[], - const Quaternion q[], - int iBone, - matrix3x4_t *pBoneToWorld ) -{ - CBoneBitList boneComputed; - BuildBoneChain( pStudioHdr, rootxform, pos, q, iBone, pBoneToWorld, boneComputed ); - return; -} - - -//----------------------------------------------------------------------------- -// Purpose: return a sub frame rotation for a single bone -//----------------------------------------------------------------------------- -void ExtractAnimValue( int frame, mstudioanimvalue_t *panimvalue, float scale, float &v1, float &v2 ) -{ - if ( !panimvalue ) - { - v1 = v2 = 0; - return; - } - - // Avoids a crash reading off the end of the data - // There is probably a better long-term solution; Ken is going to look into it. - if ( ( panimvalue->num.total == 1 ) && ( panimvalue->num.valid == 1 ) ) - { - v1 = v2 = panimvalue[1].value * scale; - return; - } - - int k = frame; - - // find the data list that has the frame - while (panimvalue->num.total <= k) - { - k -= panimvalue->num.total; - panimvalue += panimvalue->num.valid + 1; - if ( panimvalue->num.total == 0 ) - { - Assert( 0 ); // running off the end of the animation stream is bad - v1 = v2 = 0; - return; - } - } - if (panimvalue->num.valid > k) - { - // has valid animation data - v1 = panimvalue[k+1].value * scale; - - if (panimvalue->num.valid > k + 1) - { - // has valid animation blend data - v2 = panimvalue[k+2].value * scale; - } - else - { - if (panimvalue->num.total > k + 1) - { - // data repeats, no blend - v2 = v1; - } - else - { - // pull blend from first data block in next list - v2 = panimvalue[panimvalue->num.valid+2].value * scale; - } - } - } - else - { - // get last valid data block - v1 = panimvalue[panimvalue->num.valid].value * scale; - if (panimvalue->num.total > k + 1) - { - // data repeats, no blend - v2 = v1; - } - else - { - // pull blend from first data block in next list - v2 = panimvalue[panimvalue->num.valid + 2].value * scale; - } - } -} - - -void ExtractAnimValue( int frame, mstudioanimvalue_t *panimvalue, float scale, float &v1 ) -{ - if ( !panimvalue ) - { - v1 = 0; - return; - } - - int k = frame; - - while (panimvalue->num.total <= k) - { - k -= panimvalue->num.total; - panimvalue += panimvalue->num.valid + 1; - if ( panimvalue->num.total == 0 ) - { - Assert( 0 ); // running off the end of the animation stream is bad - v1 = 0; - return; - } - } - if (panimvalue->num.valid > k) - { - v1 = panimvalue[k+1].value * scale; - } - else - { - // get last valid data block - v1 = panimvalue[panimvalue->num.valid].value * scale; - } -} - -//----------------------------------------------------------------------------- -// Purpose: return a sub frame rotation for a single bone -//----------------------------------------------------------------------------- -void CalcBoneQuaternion( int frame, float s, - const Quaternion &baseQuat, const RadianEuler &baseRot, const Vector &baseRotScale, - int iBaseFlags, const Quaternion &baseAlignment, - const mstudioanim_t *panim, Quaternion &q ) -{ - if ( panim->flags & STUDIO_ANIM_RAWROT ) - { - q = *(panim->pQuat48()); - Assert( q.IsValid() ); - return; - } - - if ( panim->flags & STUDIO_ANIM_RAWROT2 ) - { - q = *(panim->pQuat64()); - Assert( q.IsValid() ); - return; - } - - if ( !(panim->flags & STUDIO_ANIM_ANIMROT) ) - { - if (panim->flags & STUDIO_ANIM_DELTA) - { - q.Init( 0.0f, 0.0f, 0.0f, 1.0f ); - } - else - { - q = baseQuat; - } - return; - } - - mstudioanim_valueptr_t *pValuesPtr = panim->pRotV(); - - if (s > 0.001f) - { - QuaternionAligned q1, q2; - RadianEuler angle1, angle2; - - ExtractAnimValue( frame, pValuesPtr->pAnimvalue( 0 ), baseRotScale.x, angle1.x, angle2.x ); - ExtractAnimValue( frame, pValuesPtr->pAnimvalue( 1 ), baseRotScale.y, angle1.y, angle2.y ); - ExtractAnimValue( frame, pValuesPtr->pAnimvalue( 2 ), baseRotScale.z, angle1.z, angle2.z ); - - if (!(panim->flags & STUDIO_ANIM_DELTA)) - { - angle1.x = angle1.x + baseRot.x; - angle1.y = angle1.y + baseRot.y; - angle1.z = angle1.z + baseRot.z; - angle2.x = angle2.x + baseRot.x; - angle2.y = angle2.y + baseRot.y; - angle2.z = angle2.z + baseRot.z; - } - - Assert( angle1.IsValid() && angle2.IsValid() ); - if (angle1.x != angle2.x || angle1.y != angle2.y || angle1.z != angle2.z) - { - AngleQuaternion( angle1, q1 ); - AngleQuaternion( angle2, q2 ); - - #ifdef _X360 - fltx4 q1simd, q2simd, qsimd; - q1simd = LoadAlignedSIMD( q1 ); - q2simd = LoadAlignedSIMD( q2 ); - qsimd = QuaternionBlendSIMD( q1simd, q2simd, s ); - StoreUnalignedSIMD( q.Base(), qsimd ); - #else - QuaternionBlend( q1, q2, s, q ); - #endif - } - else - { - AngleQuaternion( angle1, q ); - } - } - else - { - RadianEuler angle; - - ExtractAnimValue( frame, pValuesPtr->pAnimvalue( 0 ), baseRotScale.x, angle.x ); - ExtractAnimValue( frame, pValuesPtr->pAnimvalue( 1 ), baseRotScale.y, angle.y ); - ExtractAnimValue( frame, pValuesPtr->pAnimvalue( 2 ), baseRotScale.z, angle.z ); - - if (!(panim->flags & STUDIO_ANIM_DELTA)) - { - angle.x = angle.x + baseRot.x; - angle.y = angle.y + baseRot.y; - angle.z = angle.z + baseRot.z; - } - - Assert( angle.IsValid() ); - AngleQuaternion( angle, q ); - } - - Assert( q.IsValid() ); - - // align to unified bone - if (!(panim->flags & STUDIO_ANIM_DELTA) && (iBaseFlags & BONE_FIXED_ALIGNMENT)) - { - QuaternionAlign( baseAlignment, q, q ); - } -} - -inline void CalcBoneQuaternion( int frame, float s, - const mstudiobone_t *pBone, - const mstudiolinearbone_t *pLinearBones, - const mstudioanim_t *panim, Quaternion &q ) -{ - if (pLinearBones) - { - CalcBoneQuaternion( frame, s, pLinearBones->quat(panim->bone), pLinearBones->rot(panim->bone), pLinearBones->rotscale(panim->bone), pLinearBones->flags(panim->bone), pLinearBones->qalignment(panim->bone), panim, q ); - } - else - { - CalcBoneQuaternion( frame, s, pBone->quat, pBone->rot, pBone->rotscale, pBone->flags, pBone->qAlignment, panim, q ); - } -} - - - - - -//----------------------------------------------------------------------------- -// Purpose: return a sub frame position for a single bone -//----------------------------------------------------------------------------- -void CalcBonePosition( int frame, float s, - const Vector &basePos, const Vector &baseBoneScale, - const mstudioanim_t *panim, Vector &pos ) -{ - if (panim->flags & STUDIO_ANIM_RAWPOS) - { - pos = *(panim->pPos()); - Assert( pos.IsValid() ); - - return; - } - else if (!(panim->flags & STUDIO_ANIM_ANIMPOS)) - { - if (panim->flags & STUDIO_ANIM_DELTA) - { - pos.Init( 0.0f, 0.0f, 0.0f ); - } - else - { - pos = basePos; - } - return; - } - - mstudioanim_valueptr_t *pPosV = panim->pPosV(); - int j; - - if (s > 0.001f) - { - float v1, v2; - for (j = 0; j < 3; j++) - { - ExtractAnimValue( frame, pPosV->pAnimvalue( j ), baseBoneScale[j], v1, v2 ); - pos[j] = v1 * (1.0 - s) + v2 * s; - } - } - else - { - for (j = 0; j < 3; j++) - { - ExtractAnimValue( frame, pPosV->pAnimvalue( j ), baseBoneScale[j], pos[j] ); - } - } - - if (!(panim->flags & STUDIO_ANIM_DELTA)) - { - pos.x = pos.x + basePos.x; - pos.y = pos.y + basePos.y; - pos.z = pos.z + basePos.z; - } - - Assert( pos.IsValid() ); -} - - -inline void CalcBonePosition( int frame, float s, - const mstudiobone_t *pBone, - const mstudiolinearbone_t *pLinearBones, - const mstudioanim_t *panim, Vector &pos ) -{ - if (pLinearBones) - { - CalcBonePosition( frame, s, pLinearBones->pos(panim->bone), pLinearBones->posscale(panim->bone), panim, pos ); - } - else - { - CalcBonePosition( frame, s, pBone->pos, pBone->posscale, panim, pos ); - } -} - - - -void SetupSingleBoneMatrix( - CStudioHdr *pOwnerHdr, - int nSequence, - int iFrame, - int iBone, - matrix3x4_t &mBoneLocal ) -{ - mstudioseqdesc_t &seqdesc = pOwnerHdr->pSeqdesc( nSequence ); - mstudioanimdesc_t &animdesc = pOwnerHdr->pAnimdesc( seqdesc.anim( 0, 0 ) ); - int iLocalFrame = iFrame; - mstudioanim_t *panim = animdesc.pAnim( &iLocalFrame ); - float s = 0; - mstudiobone_t *pbone = pOwnerHdr->pBone( iBone ); - - Quaternion boneQuat; - Vector bonePos; - - // search for bone - while (panim && panim->bone != iBone) - { - panim = panim->pNext(); - } - - // look up animation if found, if not, initialize - if (panim && seqdesc.weight(iBone) > 0) - { - CalcBoneQuaternion( iLocalFrame, s, pbone, NULL, panim, boneQuat ); - CalcBonePosition ( iLocalFrame, s, pbone, NULL, panim, bonePos ); - } - else if (animdesc.flags & STUDIO_DELTA) - { - boneQuat.Init( 0.0f, 0.0f, 0.0f, 1.0f ); - bonePos.Init( 0.0f, 0.0f, 0.0f ); - } - else - { - boneQuat = pbone->quat; - bonePos = pbone->pos; - } - - QuaternionMatrix( boneQuat, bonePos, mBoneLocal ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -static void CalcDecompressedAnimation( const mstudiocompressedikerror_t *pCompressed, int iFrame, float fraq, Vector &pos, Quaternion &q ) -{ - if (fraq > 0.0001f) - { - Vector p1, p2; - ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 0 ), pCompressed->scale[0], p1.x, p2.x ); - ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 1 ), pCompressed->scale[1], p1.y, p2.y ); - ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 2 ), pCompressed->scale[2], p1.z, p2.z ); - pos = p1 * (1 - fraq) + p2 * fraq; - - Quaternion q1, q2; - RadianEuler angle1, angle2; - ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 3 ), pCompressed->scale[3], angle1.x, angle2.x ); - ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 4 ), pCompressed->scale[4], angle1.y, angle2.y ); - ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 5 ), pCompressed->scale[5], angle1.z, angle2.z ); - - if (angle1.x != angle2.x || angle1.y != angle2.y || angle1.z != angle2.z) - { - AngleQuaternion( angle1, q1 ); - AngleQuaternion( angle2, q2 ); - QuaternionBlend( q1, q2, fraq, q ); - } - else - { - AngleQuaternion( angle1, q ); - } - } - else - { - ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 0 ), pCompressed->scale[0], pos.x ); - ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 1 ), pCompressed->scale[1], pos.y ); - ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 2 ), pCompressed->scale[2], pos.z ); - - RadianEuler angle; - ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 3 ), pCompressed->scale[3], angle.x ); - ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 4 ), pCompressed->scale[4], angle.y ); - ExtractAnimValue( iFrame, pCompressed->pAnimvalue( 5 ), pCompressed->scale[5], angle.z ); - - AngleQuaternion( angle, q ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: translate animations done in a non-standard parent space -//----------------------------------------------------------------------------- -static void CalcLocalHierarchyAnimation( - const CStudioHdr *pStudioHdr, - matrix3x4_t *boneToWorld, - CBoneBitList &boneComputed, - Vector *pos, - Quaternion *q, - //const mstudioanimdesc_t &animdesc, - const mstudiobone_t *pbone, - mstudiolocalhierarchy_t *pHierarchy, - int iBone, - int iNewParent, - float cycle, - int iFrame, - float flFraq, - int boneMask - ) -{ - Vector localPos; - Quaternion localQ; - - // make fake root transform - static matrix3x4_t rootXform( 1.0f, 0, 0, 0, 0, 1.0f, 0, 0, 0, 0, 1.0f, 0 ); - - // FIXME: missing check to see if seq has a weight for this bone - float weight = 1.0f; - - // check to see if there's a ramp on the influence - if ( pHierarchy->tail - pHierarchy->peak < 1.0f ) - { - float index = cycle; - - if (pHierarchy->end > 1.0f && index < pHierarchy->start) - index += 1.0f; - - if (index < pHierarchy->start) - return; - if (index >= pHierarchy->end) - return; - - if (index < pHierarchy->peak && pHierarchy->start != pHierarchy->peak) - { - weight = (index - pHierarchy->start) / (pHierarchy->peak - pHierarchy->start); - } - else if (index > pHierarchy->tail && pHierarchy->end != pHierarchy->tail) - { - weight = (pHierarchy->end - index) / (pHierarchy->end - pHierarchy->tail); - } - - weight = SimpleSpline( weight ); - } - - CalcDecompressedAnimation( pHierarchy->pLocalAnim(), iFrame - pHierarchy->iStart, flFraq, localPos, localQ ); - - BuildBoneChain( pStudioHdr, rootXform, pos, q, iBone, boneToWorld, boneComputed ); - BuildBoneChain( pStudioHdr, rootXform, pos, q, iNewParent, boneToWorld, boneComputed ); - - matrix3x4_t localXform; - AngleMatrix( localQ, localPos, localXform ); - - ConcatTransforms( boneToWorld[iNewParent], localXform, boneToWorld[iBone] ); - - // back solve - Vector p1; - Quaternion q1; - int n = pbone[iBone].parent; - if (n == -1) - { - if (weight == 1.0f) - { - MatrixAngles( boneToWorld[iBone], q[iBone], pos[iBone] ); - } - else - { - MatrixAngles( boneToWorld[iBone], q1, p1 ); - QuaternionSlerp( q[iBone], q1, weight, q[iBone] ); - pos[iBone] = Lerp( weight, p1, pos[iBone] ); - } - } - else - { - matrix3x4_t worldToBone; - MatrixInvert( boneToWorld[n], worldToBone ); - - matrix3x4_t local; - ConcatTransforms( worldToBone, boneToWorld[iBone], local ); - if (weight == 1.0f) - { - MatrixAngles( local, q[iBone], pos[iBone] ); - } - else - { - MatrixAngles( local, q1, p1 ); - QuaternionSlerp( q[iBone], q1, weight, q[iBone] ); - pos[iBone] = Lerp( weight, p1, pos[iBone] ); - } - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: Calc Zeroframe Data -//----------------------------------------------------------------------------- - -static void CalcZeroframeData( const CStudioHdr *pStudioHdr, const studiohdr_t *pAnimStudioHdr, const virtualgroup_t *pAnimGroup, const mstudiobone_t *pAnimbone, mstudioanimdesc_t &animdesc, float fFrame, Vector *pos, Quaternion *q, int boneMask, float flWeight ) -{ - byte *pData = animdesc.pZeroFrameData(); - - if (!pData) - return; - - int i, j; - - // Msg("zeroframe %s\n", animdesc.pszName() ); - if (animdesc.zeroframecount == 1) - { - for (j = 0; j < pAnimStudioHdr->numbones; j++) - { - if (pAnimGroup) - i = pAnimGroup->masterBone[j]; - else - i = j; - - if (pAnimbone[j].flags & BONE_HAS_SAVEFRAME_POS) - { - if ((i >= 0) && (pStudioHdr->boneFlags(i) & boneMask)) - { - Vector p = *(Vector48 *)pData; - pos[i] = pos[i] * (1.0f - flWeight) + p * flWeight; - Assert( pos[i].IsValid() ); - } - pData += sizeof( Vector48 ); - } - if (pAnimbone[j].flags & BONE_HAS_SAVEFRAME_ROT) - { - if ((i >= 0) && (pStudioHdr->boneFlags(i) & boneMask)) - { - Quaternion q0 = *(Quaternion64 *)pData; - QuaternionBlend( q[i], q0, flWeight, q[i] ); - Assert( q[i].IsValid() ); - } - pData += sizeof( Quaternion64 ); - } - } - } - else - { - float s1; - int index = (int)(fFrame / animdesc.zeroframespan); - if (index >= animdesc.zeroframecount - 1) - { - index = animdesc.zeroframecount - 2; - s1 = 1.0f; - } - else - { - s1 = clamp( (fFrame - index * animdesc.zeroframespan) / animdesc.zeroframespan, 0.0f, 1.0f ); - } - int i0 = MAX( index - 1, 0 ); - int i1 = index; - int i2 = MIN( index + 1, animdesc.zeroframecount - 1 ); - for (j = 0; j < pAnimStudioHdr->numbones; j++) - { - if (pAnimGroup) - i = pAnimGroup->masterBone[j]; - else - i = j; - - if (pAnimbone[j].flags & BONE_HAS_SAVEFRAME_POS) - { - if ((i >= 0) && (pStudioHdr->boneFlags(i) & boneMask)) - { - Vector p0 = *(((Vector48 *)pData) + i0); - Vector p1 = *(((Vector48 *)pData) + i1); - Vector p2 = *(((Vector48 *)pData) + i2); - Vector p3; - Hermite_Spline( p0, p1, p2, s1, p3 ); - pos[i] = pos[i] * (1.0f - flWeight) + p3 * flWeight; - Assert( pos[i].IsValid() ); - } - pData += sizeof( Vector48 ) * animdesc.zeroframecount; - } - if (pAnimbone[j].flags & BONE_HAS_SAVEFRAME_ROT) - { - if ((i >= 0) && (pStudioHdr->boneFlags(i) & boneMask)) - { - Quaternion q0 = *(((Quaternion64 *)pData) + i0); - Quaternion q1 = *(((Quaternion64 *)pData) + i1); - Quaternion q2 = *(((Quaternion64 *)pData) + i2); - if (flWeight == 1.0f) - { - Hermite_Spline( q0, q1, q2, s1, q[i] ); - } - else - { - Quaternion q3; - Hermite_Spline( q0, q1, q2, s1, q3 ); - QuaternionBlend( q[i], q3, flWeight, q[i] ); - } - Assert( q[i].IsValid() ); - } - pData += sizeof( Quaternion64 ) * animdesc.zeroframecount; - } - } - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: Find and decode a sub-frame of animation, remapping the skeleton bone indexes -//----------------------------------------------------------------------------- -static void CalcVirtualAnimation( virtualmodel_t *pVModel, const CStudioHdr *pStudioHdr, Vector *pos, Quaternion *q, - mstudioseqdesc_t &seqdesc, int sequence, int animation, - float cycle, int boneMask ) -{ - int i, j, k; - - const mstudiobone_t *pbone; - const virtualgroup_t *pSeqGroup; - const studiohdr_t *pSeqStudioHdr; - const mstudiolinearbone_t *pSeqLinearBones; - const mstudiobone_t *pSeqbone; - const mstudioanim_t *panim; - const studiohdr_t *pAnimStudioHdr; - const mstudiolinearbone_t *pAnimLinearBones; - const mstudiobone_t *pAnimbone; - const virtualgroup_t *pAnimGroup; - - pSeqGroup = pVModel->pSeqGroup( sequence ); - int baseanimation = pStudioHdr->iRelativeAnim( sequence, animation ); - mstudioanimdesc_t &animdesc = pStudioHdr->pAnimdesc( baseanimation ); - pSeqStudioHdr = pStudioHdr->pSeqStudioHdr( sequence ); - pSeqLinearBones = pSeqStudioHdr->pLinearBones(); - pSeqbone = pSeqStudioHdr->pBone( 0 ); - pAnimGroup = pVModel->pAnimGroup( baseanimation ); - pAnimStudioHdr = pStudioHdr->pAnimStudioHdr( baseanimation ); - pAnimLinearBones = pAnimStudioHdr->pLinearBones(); - pAnimbone = pAnimStudioHdr->pBone( 0 ); - - int iFrame; - float s; - - float fFrame = cycle * (animdesc.numframes - 1); - - iFrame = (int)fFrame; - s = (fFrame - iFrame); - - int iLocalFrame = iFrame; - float flStall; - panim = animdesc.pAnim( &iLocalFrame, flStall ); - - float *pweight = seqdesc.pBoneweight( 0 ); - pbone = pStudioHdr->pBone( 0 ); - - for (i = 0; i < pStudioHdr->numbones(); i++) - { - if (pStudioHdr->boneFlags(i) & boneMask) - { - int j = pSeqGroup->boneMap[i]; - if (j >= 0 && pweight[j] > 0.0f) - { - if (animdesc.flags & STUDIO_DELTA) - { - q[i].Init( 0.0f, 0.0f, 0.0f, 1.0f ); - pos[i].Init( 0.0f, 0.0f, 0.0f ); - } - else if (pSeqLinearBones) - { - q[i] = pSeqLinearBones->quat(j); - pos[i] = pSeqLinearBones->pos(j); - } - else - { - q[i] = pSeqbone[j].quat; - pos[i] = pSeqbone[j].pos; - } -#ifdef STUDIO_ENABLE_PERF_COUNTERS - pStudioHdr->m_nPerfUsedBones++; -#endif - } - } - } - - // if the animation isn't available, look for the zero frame cache - if (!panim) - { - CalcZeroframeData( pStudioHdr, pAnimStudioHdr, pAnimGroup, pAnimbone, animdesc, fFrame, pos, q, boneMask, 1.0 ); - return; - } - - // FIXME: change encoding so that bone -1 is never the case - while (panim && panim->bone < 255) - { - j = pAnimGroup->masterBone[panim->bone]; - if ( j >= 0 && ( pStudioHdr->boneFlags(j) & boneMask ) ) - { - k = pSeqGroup->boneMap[j]; - - if (k >= 0 && pweight[k] > 0.0f) - { - CalcBoneQuaternion( iLocalFrame, s, &pAnimbone[panim->bone], pAnimLinearBones, panim, q[j] ); - CalcBonePosition ( iLocalFrame, s, &pAnimbone[panim->bone], pAnimLinearBones, panim, pos[j] ); -#ifdef STUDIO_ENABLE_PERF_COUNTERS - pStudioHdr->m_nPerfAnimatedBones++; -#endif - } - } - panim = panim->pNext(); - } - - // cross fade in previous zeroframe data - if (flStall > 0.0f) - { - CalcZeroframeData( pStudioHdr, pAnimStudioHdr, pAnimGroup, pAnimbone, animdesc, fFrame, pos, q, boneMask, flStall ); - } - - // calculate a local hierarchy override - if (animdesc.numlocalhierarchy) - { - matrix3x4_t *boneToWorld = g_MatrixPool.Alloc(); - CBoneBitList boneComputed; - - int i; - for (i = 0; i < animdesc.numlocalhierarchy; i++) - { - mstudiolocalhierarchy_t *pHierarchy = animdesc.pHierarchy( i ); - - if ( !pHierarchy ) - break; - - int iBone = pAnimGroup->masterBone[pHierarchy->iBone]; - if (iBone >= 0 && (pStudioHdr->boneFlags(iBone) & boneMask)) - { - int iNewParent = pAnimGroup->masterBone[pHierarchy->iNewParent]; - if (iNewParent >= 0 && (pStudioHdr->boneFlags(iNewParent) & boneMask)) - { - CalcLocalHierarchyAnimation( pStudioHdr, boneToWorld, boneComputed, pos, q, pbone, pHierarchy, iBone, iNewParent, cycle, iFrame, s, boneMask ); - } - } - } - - g_MatrixPool.Free( boneToWorld ); - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: Find and decode a sub-frame of animation -//----------------------------------------------------------------------------- - -static void CalcAnimation( const CStudioHdr *pStudioHdr, Vector *pos, Quaternion *q, - mstudioseqdesc_t &seqdesc, - int sequence, int animation, - float cycle, int boneMask ) -{ -#ifdef STUDIO_ENABLE_PERF_COUNTERS - pStudioHdr->m_nPerfAnimationLayers++; -#endif - - virtualmodel_t *pVModel = pStudioHdr->GetVirtualModel(); - - if (pVModel) - { - CalcVirtualAnimation( pVModel, pStudioHdr, pos, q, seqdesc, sequence, animation, cycle, boneMask ); - return; - } - - mstudioanimdesc_t &animdesc = pStudioHdr->pAnimdesc( animation ); - mstudiobone_t *pbone = pStudioHdr->pBone( 0 ); - const mstudiolinearbone_t *pLinearBones = pStudioHdr->pLinearBones(); - - int i; - int iFrame; - float s; - - float fFrame = cycle * (animdesc.numframes - 1); - - iFrame = (int)fFrame; - s = (fFrame - iFrame); - - int iLocalFrame = iFrame; - float flStall; - mstudioanim_t *panim = animdesc.pAnim( &iLocalFrame, flStall ); - - float *pweight = seqdesc.pBoneweight( 0 ); - - // if the animation isn't available, look for the zero frame cache - if (!panim) - { - // Msg("zeroframe %s\n", animdesc.pszName() ); - // pre initialize - for (i = 0; i < pStudioHdr->numbones(); i++, pbone++, pweight++) - { - if (*pweight > 0 && (pStudioHdr->boneFlags(i) & boneMask)) - { - if (animdesc.flags & STUDIO_DELTA) - { - q[i].Init( 0.0f, 0.0f, 0.0f, 1.0f ); - pos[i].Init( 0.0f, 0.0f, 0.0f ); - } - else - { - q[i] = pbone->quat; - pos[i] = pbone->pos; - } - } - } - - CalcZeroframeData( pStudioHdr, pStudioHdr->GetRenderHdr(), NULL, pStudioHdr->pBone( 0 ), animdesc, fFrame, pos, q, boneMask, 1.0 ); - - return; - } - - // BUGBUG: the sequence, the anim, and the model can have all different bone mappings. - for (i = 0; i < pStudioHdr->numbones(); i++, pbone++, pweight++) - { - if (panim && panim->bone == i) - { - if (*pweight > 0 && (pStudioHdr->boneFlags(i) & boneMask)) - { - CalcBoneQuaternion( iLocalFrame, s, pbone, pLinearBones, panim, q[i] ); - CalcBonePosition ( iLocalFrame, s, pbone, pLinearBones, panim, pos[i] ); -#ifdef STUDIO_ENABLE_PERF_COUNTERS - pStudioHdr->m_nPerfAnimatedBones++; - pStudioHdr->m_nPerfUsedBones++; -#endif - } - panim = panim->pNext(); - } - else if (*pweight > 0 && (pStudioHdr->boneFlags(i) & boneMask)) - { - if (animdesc.flags & STUDIO_DELTA) - { - q[i].Init( 0.0f, 0.0f, 0.0f, 1.0f ); - pos[i].Init( 0.0f, 0.0f, 0.0f ); - } - else - { - q[i] = pbone->quat; - pos[i] = pbone->pos; - } -#ifdef STUDIO_ENABLE_PERF_COUNTERS - pStudioHdr->m_nPerfUsedBones++; -#endif - } - } - - // cross fade in previous zeroframe data - if (flStall > 0.0f) - { - CalcZeroframeData( pStudioHdr, pStudioHdr->GetRenderHdr(), NULL, pStudioHdr->pBone( 0 ), animdesc, fFrame, pos, q, boneMask, flStall ); - } - - if (animdesc.numlocalhierarchy) - { - matrix3x4_t *boneToWorld = g_MatrixPool.Alloc(); - CBoneBitList boneComputed; - - int i; - for (i = 0; i < animdesc.numlocalhierarchy; i++) - { - mstudiolocalhierarchy_t *pHierarchy = animdesc.pHierarchy( i ); - - if ( !pHierarchy ) - break; - - if (pStudioHdr->boneFlags(pHierarchy->iBone) & boneMask) - { - if (pStudioHdr->boneFlags(pHierarchy->iNewParent) & boneMask) - { - CalcLocalHierarchyAnimation( pStudioHdr, boneToWorld, boneComputed, pos, q, pbone, pHierarchy, pHierarchy->iBone, pHierarchy->iNewParent, cycle, iFrame, s, boneMask ); - } - } - } - - g_MatrixPool.Free( boneToWorld ); - } - -} - - -//----------------------------------------------------------------------------- -// Purpose: qt = ( s * p ) * q -//----------------------------------------------------------------------------- -void QuaternionSM( float s, const Quaternion &p, const Quaternion &q, Quaternion &qt ) -{ - Quaternion p1, q1; - - QuaternionScale( p, s, p1 ); - QuaternionMult( p1, q, q1 ); - QuaternionNormalize( q1 ); - qt[0] = q1[0]; - qt[1] = q1[1]; - qt[2] = q1[2]; - qt[3] = q1[3]; -} - -#if ALLOW_SIMD_QUATERNION_MATH -FORCEINLINE fltx4 QuaternionSMSIMD( float s, const fltx4 &p, const fltx4 &q ) -{ - fltx4 p1, q1, result; - p1 = QuaternionScaleSIMD( p, s ); - q1 = QuaternionMultSIMD( p1, q ); - result = QuaternionNormalizeSIMD( q1 ); - return result; -} -#endif - -//----------------------------------------------------------------------------- -// Purpose: qt = p * ( s * q ) -//----------------------------------------------------------------------------- -void QuaternionMA( const Quaternion &p, float s, const Quaternion &q, Quaternion &qt ) -{ - Quaternion p1, q1; - - QuaternionScale( q, s, q1 ); - QuaternionMult( p, q1, p1 ); - QuaternionNormalize( p1 ); - qt[0] = p1[0]; - qt[1] = p1[1]; - qt[2] = p1[2]; - qt[3] = p1[3]; -} - -#if ALLOW_SIMD_QUATERNION_MATH -FORCEINLINE fltx4 QuaternionMASIMD( const fltx4 &p, float s, const fltx4 &q ) -{ - fltx4 p1, q1, result; - q1 = QuaternionScaleSIMD( q, s ); - p1 = QuaternionMultSIMD( p, q1 ); - result = QuaternionNormalizeSIMD( p1 ); - return result; -} -#endif - - -//----------------------------------------------------------------------------- -// Purpose: qt = p + s * q -//----------------------------------------------------------------------------- -void QuaternionAccumulate( const Quaternion &p, float s, const Quaternion &q, Quaternion &qt ) -{ - Quaternion q2; - QuaternionAlign( p, q, q2 ); - - qt[0] = p[0] + s * q2[0]; - qt[1] = p[1] + s * q2[1]; - qt[2] = p[2] + s * q2[2]; - qt[3] = p[3] + s * q2[3]; -} - -#if ALLOW_SIMD_QUATERNION_MATH -FORCEINLINE fltx4 QuaternionAccumulateSIMD( const fltx4 &p, float s, const fltx4 &q ) -{ - fltx4 q2, s4, result; - q2 = QuaternionAlignSIMD( p, q ); - s4 = ReplicateX4( s ); - result = MaddSIMD( s4, q2, p ); - return result; -} -#endif - - - -//----------------------------------------------------------------------------- -// Purpose: blend together in world space q1,pos1 with q2,pos2. Return result in q1,pos1. -// 0 returns q1, pos1. 1 returns q2, pos2 -//----------------------------------------------------------------------------- - -void WorldSpaceSlerp( - const CStudioHdr *pStudioHdr, - Quaternion q1[MAXSTUDIOBONES], - Vector pos1[MAXSTUDIOBONES], - mstudioseqdesc_t &seqdesc, - int sequence, - const Quaternion q2[MAXSTUDIOBONES], - const Vector pos2[MAXSTUDIOBONES], - float s, - int boneMask ) -{ - int i, j; - float s1; // weight of parent for q2, pos2 - float s2; // weight for q2, pos2 - - // make fake root transform - matrix3x4_t rootXform; - SetIdentityMatrix( rootXform ); - - // matrices for q2, pos2 - matrix3x4_t *srcBoneToWorld = g_MatrixPool.Alloc(); - CBoneBitList srcBoneComputed; - - matrix3x4_t *destBoneToWorld = g_MatrixPool.Alloc(); - CBoneBitList destBoneComputed; - - matrix3x4_t *targetBoneToWorld = g_MatrixPool.Alloc(); - CBoneBitList targetBoneComputed; - - virtualmodel_t *pVModel = pStudioHdr->GetVirtualModel(); - const virtualgroup_t *pSeqGroup = NULL; - if (pVModel) - { - pSeqGroup = pVModel->pSeqGroup( sequence ); - } - - mstudiobone_t *pbone = pStudioHdr->pBone( 0 ); - - for (i = 0; i < pStudioHdr->numbones(); i++) - { - // skip unused bones - if (!(pStudioHdr->boneFlags(i) & boneMask)) - { - continue; - } - - int n = pbone[i].parent; - s1 = 0.0; - if (pSeqGroup) - { - j = pSeqGroup->boneMap[i]; - if (j >= 0) - { - s2 = s * seqdesc.weight( j ); // blend in based on this bones weight - if (n != -1) - { - s1 = s * seqdesc.weight( pSeqGroup->boneMap[n] ); - } - } - else - { - s2 = 0.0; - } - } - else - { - s2 = s * seqdesc.weight( i ); // blend in based on this bones weight - if (n != -1) - { - s1 = s * seqdesc.weight( n ); - } - } - - if (s1 == 1.0 && s2 == 1.0) - { - pos1[i] = pos2[i]; - q1[i] = q2[i]; - } - else if (s2 > 0.0) - { - Quaternion srcQ, destQ; - Vector srcPos, destPos; - Quaternion targetQ; - Vector targetPos; - Vector tmp; - - BuildBoneChain( pStudioHdr, rootXform, pos1, q1, i, destBoneToWorld, destBoneComputed ); - BuildBoneChain( pStudioHdr, rootXform, pos2, q2, i, srcBoneToWorld, srcBoneComputed ); - - MatrixAngles( destBoneToWorld[i], destQ, destPos ); - MatrixAngles( srcBoneToWorld[i], srcQ, srcPos ); - - QuaternionSlerp( destQ, srcQ, s2, targetQ ); - AngleMatrix( targetQ, destPos, targetBoneToWorld[i] ); - - // back solve - if (n == -1) - { - MatrixAngles( targetBoneToWorld[i], q1[i], tmp ); - } - else - { - matrix3x4_t worldToBone; - MatrixInvert( targetBoneToWorld[n], worldToBone ); - - matrix3x4_t local; - ConcatTransforms( worldToBone, targetBoneToWorld[i], local ); - MatrixAngles( local, q1[i], tmp ); - - // blend bone lengths (local space) - pos1[i] = Lerp( s2, pos1[i], pos2[i] ); - } - } - } - g_MatrixPool.Free( srcBoneToWorld ); - g_MatrixPool.Free( destBoneToWorld ); - g_MatrixPool.Free( targetBoneToWorld ); -} - - - -//----------------------------------------------------------------------------- -// Purpose: blend together q1,pos1 with q2,pos2. Return result in q1,pos1. -// 0 returns q1, pos1. 1 returns q2, pos2 -//----------------------------------------------------------------------------- -void SlerpBones( - const CStudioHdr *pStudioHdr, - Quaternion q1[MAXSTUDIOBONES], - Vector pos1[MAXSTUDIOBONES], - mstudioseqdesc_t &seqdesc, // source of q2 and pos2 - int sequence, - const QuaternionAligned q2[MAXSTUDIOBONES], - const Vector pos2[MAXSTUDIOBONES], - float s, - int boneMask ) -{ - if (s <= 0.0f) - return; - if (s > 1.0f) - { - s = 1.0f; - } - - if (seqdesc.flags & STUDIO_WORLD) - { - WorldSpaceSlerp( pStudioHdr, q1, pos1, seqdesc, sequence, q2, pos2, s, boneMask ); - return; - } - - int i, j; - virtualmodel_t *pVModel = pStudioHdr->GetVirtualModel(); - const virtualgroup_t *pSeqGroup = NULL; - if (pVModel) - { - pSeqGroup = pVModel->pSeqGroup( sequence ); - } - - // Build weightlist for all bones - int nBoneCount = pStudioHdr->numbones(); - float *pS2 = (float*)stackalloc( nBoneCount * sizeof(float) ); - for (i = 0; i < nBoneCount; i++) - { - // skip unused bones - if (!(pStudioHdr->boneFlags(i) & boneMask)) - { - pS2[i] = 0.0f; - continue; - } - - if ( !pSeqGroup ) - { - pS2[i] = s * seqdesc.weight( i ); // blend in based on this bones weight - continue; - } - - j = pSeqGroup->boneMap[i]; - if ( j >= 0 ) - { - pS2[i] = s * seqdesc.weight( j ); // blend in based on this bones weight - } - else - { - pS2[i] = 0.0; - } - } - - float s1, s2; - if ( seqdesc.flags & STUDIO_DELTA ) - { - for ( i = 0; i < nBoneCount; i++ ) - { - s2 = pS2[i]; - if ( s2 <= 0.0f ) - continue; - - if ( seqdesc.flags & STUDIO_POST ) - { -#ifndef _X360 - QuaternionMA( q1[i], s2, q2[i], q1[i] ); -#else - fltx4 q1simd = LoadUnalignedSIMD( q1[i].Base() ); - fltx4 q2simd = LoadAlignedSIMD( q2[i] ); - fltx4 result = QuaternionMASIMD( q1simd, s2, q2simd ); - StoreUnalignedSIMD( q1[i].Base(), result ); -#endif - // FIXME: are these correct? - pos1[i][0] = pos1[i][0] + pos2[i][0] * s2; - pos1[i][1] = pos1[i][1] + pos2[i][1] * s2; - pos1[i][2] = pos1[i][2] + pos2[i][2] * s2; - } - else - { -#ifndef _X360 - QuaternionSM( s2, q2[i], q1[i], q1[i] ); -#else - fltx4 q1simd = LoadUnalignedSIMD( q1[i].Base() ); - fltx4 q2simd = LoadAlignedSIMD( q2[i] ); - fltx4 result = QuaternionSMSIMD( s2, q2simd, q1simd ); - StoreUnalignedSIMD( q1[i].Base(), result ); -#endif - - // FIXME: are these correct? - pos1[i][0] = pos1[i][0] + pos2[i][0] * s2; - pos1[i][1] = pos1[i][1] + pos2[i][1] * s2; - pos1[i][2] = pos1[i][2] + pos2[i][2] * s2; - } - } - return; - } - - QuaternionAligned q3; - for (i = 0; i < nBoneCount; i++) - { - s2 = pS2[i]; - if ( s2 <= 0.0f ) - continue; - - s1 = 1.0 - s2; - -#ifdef _X360 - fltx4 q1simd, q2simd, result; - q1simd = LoadUnalignedSIMD( q1[i].Base() ); - q2simd = LoadAlignedSIMD( q2[i] ); -#endif - if ( pStudioHdr->boneFlags(i) & BONE_FIXED_ALIGNMENT ) - { -#ifndef _X360 - QuaternionSlerpNoAlign( q2[i], q1[i], s1, q3 ); -#else - result = QuaternionSlerpNoAlignSIMD( q2simd, q1simd, s1 ); -#endif - } - else - { -#ifndef _X360 - QuaternionSlerp( q2[i], q1[i], s1, q3 ); -#else - result = QuaternionSlerpSIMD( q2simd, q1simd, s1 ); -#endif - } - -#ifndef _X360 - q1[i][0] = q3[0]; - q1[i][1] = q3[1]; - q1[i][2] = q3[2]; - q1[i][3] = q3[3]; -#else - StoreUnalignedSIMD( q1[i].Base(), result ); -#endif - - pos1[i][0] = pos1[i][0] * s1 + pos2[i][0] * s2; - pos1[i][1] = pos1[i][1] * s1 + pos2[i][1] * s2; - pos1[i][2] = pos1[i][2] * s1 + pos2[i][2] * s2; - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: Inter-animation blend. Assumes both types are identical. -// blend together q1,pos1 with q2,pos2. Return result in q1,pos1. -// 0 returns q1, pos1. 1 returns q2, pos2 -//----------------------------------------------------------------------------- -void BlendBones( - const CStudioHdr *pStudioHdr, - Quaternion q1[MAXSTUDIOBONES], - Vector pos1[MAXSTUDIOBONES], - mstudioseqdesc_t &seqdesc, - int sequence, - const Quaternion q2[MAXSTUDIOBONES], - const Vector pos2[MAXSTUDIOBONES], - float s, - int boneMask ) -{ - int i, j; - Quaternion q3; - - virtualmodel_t *pVModel = pStudioHdr->GetVirtualModel(); - const virtualgroup_t *pSeqGroup = NULL; - if (pVModel) - { - pSeqGroup = pVModel->pSeqGroup( sequence ); - } - - if (s <= 0) - { - Assert(0); // shouldn't have been called - return; - } - else if (s >= 1.0) - { - Assert(0); // shouldn't have been called - for (i = 0; i < pStudioHdr->numbones(); i++) - { - // skip unused bones - if (!(pStudioHdr->boneFlags(i) & boneMask)) - { - continue; - } - - if (pSeqGroup) - { - j = pSeqGroup->boneMap[i]; - } - else - { - j = i; - } - - if (j >= 0 && seqdesc.weight( j ) > 0.0) - { - q1[i] = q2[i]; - pos1[i] = pos2[i]; - } - } - return; - } - - float s2 = s; - float s1 = 1.0 - s2; - - for (i = 0; i < pStudioHdr->numbones(); i++) - { - // skip unused bones - if (!(pStudioHdr->boneFlags(i) & boneMask)) - { - continue; - } - - if (pSeqGroup) - { - j = pSeqGroup->boneMap[i]; - } - else - { - j = i; - } - - if (j >= 0 && seqdesc.weight( j ) > 0.0) - { - if (pStudioHdr->boneFlags(i) & BONE_FIXED_ALIGNMENT) - { - QuaternionBlendNoAlign( q2[i], q1[i], s1, q3 ); - } - else - { - QuaternionBlend( q2[i], q1[i], s1, q3 ); - } - q1[i][0] = q3[0]; - q1[i][1] = q3[1]; - q1[i][2] = q3[2]; - q1[i][3] = q3[3]; - pos1[i][0] = pos1[i][0] * s1 + pos2[i][0] * s2; - pos1[i][1] = pos1[i][1] * s1 + pos2[i][1] * s2; - pos1[i][2] = pos1[i][2] * s1 + pos2[i][2] * s2; - } - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: Scale a set of bones. Must be of type delta -//----------------------------------------------------------------------------- -void ScaleBones( - const CStudioHdr *pStudioHdr, - Quaternion q1[MAXSTUDIOBONES], - Vector pos1[MAXSTUDIOBONES], - int sequence, - float s, - int boneMask ) -{ - int i, j; - Quaternion q3; - - mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( sequence ); - - virtualmodel_t *pVModel = pStudioHdr->GetVirtualModel(); - const virtualgroup_t *pSeqGroup = NULL; - if (pVModel) - { - pSeqGroup = pVModel->pSeqGroup( sequence ); - } - - float s2 = s; - float s1 = 1.0 - s2; - - for (i = 0; i < pStudioHdr->numbones(); i++) - { - // skip unused bones - if (!(pStudioHdr->boneFlags(i) & boneMask)) - { - continue; - } - - if (pSeqGroup) - { - j = pSeqGroup->boneMap[i]; - } - else - { - j = i; - } - - if (j >= 0 && seqdesc.weight( j ) > 0.0) - { - QuaternionIdentityBlend( q1[i], s1, q1[i] ); - VectorScale( pos1[i], s2, pos1[i] ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: resolve a global pose parameter to the specific setting for this sequence -//----------------------------------------------------------------------------- -void Studio_LocalPoseParameter( const CStudioHdr *pStudioHdr, const float poseParameter[], mstudioseqdesc_t &seqdesc, int iSequence, int iLocalIndex, float &flSetting, int &index ) -{ - int iPose = pStudioHdr->GetSharedPoseParameter( iSequence, seqdesc.paramindex[iLocalIndex] ); - - if (iPose == -1) - { - flSetting = 0; - index = 0; - return; - } - - const mstudioposeparamdesc_t &Pose = pStudioHdr->pPoseParameter( iPose ); - - float flValue = poseParameter[iPose]; - - if (Pose.loop) - { - float wrap = (Pose.start + Pose.end) / 2.0 + Pose.loop / 2.0; - float shift = Pose.loop - wrap; - - flValue = flValue - Pose.loop * floor((flValue + shift) / Pose.loop); - } - - if (seqdesc.posekeyindex == 0) - { - float flLocalStart = ((float)seqdesc.paramstart[iLocalIndex] - Pose.start) / (Pose.end - Pose.start); - float flLocalEnd = ((float)seqdesc.paramend[iLocalIndex] - Pose.start) / (Pose.end - Pose.start); - - // convert into local range - flSetting = (flValue - flLocalStart) / (flLocalEnd - flLocalStart); - - // clamp. This shouldn't ever need to happen if it's looping. - if (flSetting < 0) - flSetting = 0; - if (flSetting > 1) - flSetting = 1; - - index = 0; - if (seqdesc.groupsize[iLocalIndex] > 2 ) - { - // estimate index - index = (int)(flSetting * (seqdesc.groupsize[iLocalIndex] - 1)); - if (index == seqdesc.groupsize[iLocalIndex] - 1) index = seqdesc.groupsize[iLocalIndex] - 2; - flSetting = flSetting * (seqdesc.groupsize[iLocalIndex] - 1) - index; - } - } - else - { - flValue = flValue * (Pose.end - Pose.start) + Pose.start; - index = 0; - - // FIXME: this needs to be 2D - // FIXME: this shouldn't be a linear search - - while (1) - { - flSetting = (flValue - seqdesc.poseKey( iLocalIndex, index )) / (seqdesc.poseKey( iLocalIndex, index + 1 ) - seqdesc.poseKey( iLocalIndex, index )); - /* - if (index > 0 && flSetting < 0.0) - { - index--; - continue; - } - else - */ - if (index < seqdesc.groupsize[iLocalIndex] - 2 && flSetting > 1.0) - { - index++; - continue; - } - break; - } - - // clamp. - if (flSetting < 0.0f) - flSetting = 0.0f; - if (flSetting > 1.0f) - flSetting = 1.0f; - } -} - -void Studio_CalcBoneToBoneTransform( const CStudioHdr *pStudioHdr, int inputBoneIndex, int outputBoneIndex, matrix3x4_t& matrixOut ) -{ - mstudiobone_t *pbone = pStudioHdr->pBone( inputBoneIndex ); - - matrix3x4_t inputToPose; - MatrixInvert( pbone->poseToBone, inputToPose ); - ConcatTransforms( pStudioHdr->pBone( outputBoneIndex )->poseToBone, inputToPose, matrixOut ); -} - -//----------------------------------------------------------------------------- -// Purpose: calculate a pose for a single sequence -//----------------------------------------------------------------------------- -void InitPose( - const CStudioHdr *pStudioHdr, - Vector pos[], - Quaternion q[], - int boneMask - ) -{ - if (!pStudioHdr->pLinearBones()) - { - for (int i = 0; i < pStudioHdr->numbones(); i++) - { - if (pStudioHdr->boneFlags( i ) & boneMask ) - { - mstudiobone_t *pbone = pStudioHdr->pBone( i ); - pos[i] = pbone->pos; - q[i] = pbone->quat; - } - } - } - else - { - mstudiolinearbone_t *pLinearBones = pStudioHdr->pLinearBones(); - for (int i = 0; i < pStudioHdr->numbones(); i++) - { - if (pStudioHdr->boneFlags( i ) & boneMask ) - { - pos[i] = pLinearBones->pos(i); - q[i] = pLinearBones->quat(i); - } - } - } -} - - -inline bool PoseIsAllZeros( - const CStudioHdr *pStudioHdr, - int sequence, - mstudioseqdesc_t &seqdesc, - int i0, - int i1 - ) -{ - int baseanim; - - // remove "zero" positional blends - baseanim = pStudioHdr->iRelativeAnim( sequence, seqdesc.anim(i0 ,i1 ) ); - mstudioanimdesc_t &anim = pStudioHdr->pAnimdesc( baseanim ); - return (anim.flags & STUDIO_ALLZEROS) != 0; -} - -//----------------------------------------------------------------------------- -// Purpose: turn a 2x2 blend into a 3 way triangle blend -// Returns: returns the animination indices and barycentric coordinates of a triangle -// the triangle is a right triangle, and the diagonal is between elements [0] and [2] -//----------------------------------------------------------------------------- - -static ConVar anim_3wayblend( "anim_3wayblend", "1", FCVAR_REPLICATED, "Toggle the 3-way animation blending code." ); - -void Calc3WayBlendIndices( int i0, int i1, float s0, float s1, const mstudioseqdesc_t &seqdesc, int *pAnimIndices, float *pWeight ) -{ - // Figure out which bi-section direction we are using to make triangles. - bool bEven = ( ( ( i0 + i1 ) & 0x1 ) == 0 ); - - int x1, y1; - int x2, y2; - int x3, y3; - - // diagonal is between elements 1 & 3 - // TL to BR - if ( bEven ) - { - if ( s0 > s1 ) - { - // B - x1 = 0; y1 = 0; - x2 = 1; y2 = 0; - x3 = 1; y3 = 1; - pWeight[0] = (1.0f - s0); - pWeight[1] = s0 - s1; - } - else - { - // C - x1 = 1; y1 = 1; - x2 = 0; y2 = 1; - x3 = 0; y3 = 0; - pWeight[0] = s0; - pWeight[1] = s1 - s0; - } - } - // BL to TR - else - { - float flTotal = s0 + s1; - - if( flTotal > 1.0f ) - { - // D - x1 = 1; y1 = 0; - x2 = 1; y2 = 1; - x3 = 0; y3 = 1; - pWeight[0] = (1.0f - s1); - pWeight[1] = s0 - 1.0f + s1; - } - else - { - // A - x1 = 0; y1 = 1; - x2 = 0; y2 = 0; - x3 = 1; y3 = 0; - pWeight[0] = s1; - pWeight[1] = 1.0f - s0 - s1; - } - } - - pAnimIndices[0] = seqdesc.anim( i0 + x1, i1 + y1 ); - pAnimIndices[1] = seqdesc.anim( i0 + x2, i1 + y2 ); - pAnimIndices[2] = seqdesc.anim( i0 + x3, i1 + y3 ); - - /* - float w0 = ((x2-x3)*(y3-s1) - (x3-s0)*(y2-y3)) / ((x1-x3)*(y2-y3) - (x2-x3)*(y1-y3)); - float w1 = ((x1-x3)*(y3-s1) - (x3-s0)*(y1-y3)) / ((x2-x3)*(y1-y3) - (x1-x3)*(y2-y3)); - Assert( pWeight[0] == w0 && pWeight[1] == w1 ); - */ - - // clamp the diagonal - if (pWeight[1] < 0.001f) - pWeight[1] = 0.0f; - pWeight[2] = 1.0f - pWeight[0] - pWeight[1]; - - Assert( pWeight[0] >= 0.0f && pWeight[0] <= 1.0f ); - Assert( pWeight[1] >= 0.0f && pWeight[1] <= 1.0f ); - Assert( pWeight[2] >= 0.0f && pWeight[2] <= 1.0f ); -} - - - -//----------------------------------------------------------------------------- -// Purpose: calculate a pose for a single sequence -//----------------------------------------------------------------------------- -bool CalcPoseSingle( - const CStudioHdr *pStudioHdr, - Vector pos[], - Quaternion q[], - mstudioseqdesc_t &seqdesc, - int sequence, - float cycle, - const float poseParameter[], - int boneMask, - float flTime - ) -{ - bool bResult = true; - - Vector *pos2 = g_VectorPool.Alloc(); - Quaternion *q2 = g_QaternionPool.Alloc(); - Vector *pos3= g_VectorPool.Alloc(); - Quaternion *q3 = g_QaternionPool.Alloc(); - - if (sequence >= pStudioHdr->GetNumSeq()) - { - sequence = 0; - seqdesc = pStudioHdr->pSeqdesc( sequence ); - } - - - int i0 = 0, i1 = 0; - float s0 = 0, s1 = 0; - - Studio_LocalPoseParameter( pStudioHdr, poseParameter, seqdesc, sequence, 0, s0, i0 ); - Studio_LocalPoseParameter( pStudioHdr, poseParameter, seqdesc, sequence, 1, s1, i1 ); - - - if (seqdesc.flags & STUDIO_REALTIME) - { - float cps = Studio_CPS( pStudioHdr, seqdesc, sequence, poseParameter ); - cycle = flTime * cps; - cycle = cycle - (int)cycle; - } - else if (seqdesc.flags & STUDIO_CYCLEPOSE) - { - int iPose = pStudioHdr->GetSharedPoseParameter( sequence, seqdesc.cycleposeindex ); - if (iPose != -1) - { - /* - const mstudioposeparamdesc_t &Pose = pStudioHdr->pPoseParameter( iPose ); - cycle = poseParameter[ iPose ] * (Pose.end - Pose.start) + Pose.start; - */ - cycle = poseParameter[ iPose ]; - } - else - { - cycle = 0.0f; - } - } - else if (cycle < 0 || cycle >= 1) - { - if (seqdesc.flags & STUDIO_LOOPING) - { - cycle = cycle - (int)cycle; - if (cycle < 0) cycle += 1; - } - else - { - cycle = clamp( cycle, 0.0f, 1.0f ); - } - } - - if (s0 < 0.001) - { - if (s1 < 0.001) - { - if (PoseIsAllZeros( pStudioHdr, sequence, seqdesc, i0, i1 )) - { - bResult = false; - } - else - { - CalcAnimation( pStudioHdr, pos, q, seqdesc, sequence, seqdesc.anim( i0 , i1 ), cycle, boneMask ); - } - } - else if (s1 > 0.999) - { - CalcAnimation( pStudioHdr, pos, q, seqdesc, sequence, seqdesc.anim( i0 , i1+1 ), cycle, boneMask ); - } - else - { - CalcAnimation( pStudioHdr, pos, q, seqdesc, sequence, seqdesc.anim( i0 , i1 ), cycle, boneMask ); - CalcAnimation( pStudioHdr, pos2, q2, seqdesc, sequence, seqdesc.anim( i0 , i1+1 ), cycle, boneMask ); - BlendBones( pStudioHdr, q, pos, seqdesc, sequence, q2, pos2, s1, boneMask ); - } - } - else if (s0 > 0.999) - { - if (s1 < 0.001) - { - if (PoseIsAllZeros( pStudioHdr, sequence, seqdesc, i0+1, i1 )) - { - bResult = false; - } - else - { - CalcAnimation( pStudioHdr, pos, q, seqdesc, sequence, seqdesc.anim( i0+1, i1 ), cycle, boneMask ); - } - } - else if (s1 > 0.999) - { - CalcAnimation( pStudioHdr, pos, q, seqdesc, sequence, seqdesc.anim( i0+1, i1+1 ), cycle, boneMask ); - } - else - { - CalcAnimation( pStudioHdr, pos, q, seqdesc, sequence, seqdesc.anim( i0+1, i1 ), cycle, boneMask ); - CalcAnimation( pStudioHdr, pos2, q2, seqdesc, sequence, seqdesc.anim( i0+1, i1+1 ), cycle, boneMask ); - BlendBones( pStudioHdr, q, pos, seqdesc, sequence, q2, pos2, s1, boneMask ); - } - } - else - { - if (s1 < 0.001) - { - if (PoseIsAllZeros( pStudioHdr, sequence, seqdesc, i0+1, i1 )) - { - CalcAnimation( pStudioHdr, pos, q, seqdesc, sequence, seqdesc.anim( i0 ,i1 ), cycle, boneMask ); - ScaleBones( pStudioHdr, q, pos, sequence, 1.0 - s0, boneMask ); - } - else if (PoseIsAllZeros( pStudioHdr, sequence, seqdesc, i0, i1 )) - { - CalcAnimation( pStudioHdr, pos, q, seqdesc, sequence, seqdesc.anim( i0+1 ,i1 ), cycle, boneMask ); - ScaleBones( pStudioHdr, q, pos, sequence, s0, boneMask ); - } - else - { - CalcAnimation( pStudioHdr, pos, q, seqdesc, sequence, seqdesc.anim( i0 ,i1 ), cycle, boneMask ); - CalcAnimation( pStudioHdr, pos2, q2, seqdesc, sequence, seqdesc.anim( i0+1,i1 ), cycle, boneMask ); - - BlendBones( pStudioHdr, q, pos, seqdesc, sequence, q2, pos2, s0, boneMask ); - } - } - else if (s1 > 0.999) - { - CalcAnimation( pStudioHdr, pos, q, seqdesc, sequence, seqdesc.anim( i0 ,i1+1 ), cycle, boneMask ); - CalcAnimation( pStudioHdr, pos2, q2, seqdesc, sequence, seqdesc.anim( i0+1,i1+1 ), cycle, boneMask ); - BlendBones( pStudioHdr, q, pos, seqdesc, sequence, q2, pos2, s0, boneMask ); - } - else if ( !anim_3wayblend.GetBool() ) - { - CalcAnimation( pStudioHdr, pos, q, seqdesc, sequence, seqdesc.anim( i0 ,i1 ), cycle, boneMask ); - CalcAnimation( pStudioHdr, pos2, q2, seqdesc, sequence, seqdesc.anim( i0+1,i1 ), cycle, boneMask ); - BlendBones( pStudioHdr, q, pos, seqdesc, sequence, q2, pos2, s0, boneMask ); - - CalcAnimation( pStudioHdr, pos2, q2, seqdesc, sequence, seqdesc.anim( i0 , i1+1), cycle, boneMask ); - CalcAnimation( pStudioHdr, pos3, q3, seqdesc, sequence, seqdesc.anim( i0+1, i1+1), cycle, boneMask ); - BlendBones( pStudioHdr, q2, pos2, seqdesc, sequence, q3, pos3, s0, boneMask ); - - BlendBones( pStudioHdr, q, pos, seqdesc, sequence, q2, pos2, s1, boneMask ); - } - else - { - int iAnimIndices[3]; - float weight[3]; - - Calc3WayBlendIndices( i0, i1, s0, s1, seqdesc, iAnimIndices, weight ); - - /* - char buf[256]; - sprintf( buf, "%d %6.2f %d %6.2f : %6.2f %6.2f %6.2f\n", i0, s0, i1, s1, weight[0], weight[1], weight[2] ); - OutputDebugString( buf ); - */ - - if (weight[1] < 0.001) - { - // on diagonal - CalcAnimation( pStudioHdr, pos, q, seqdesc, sequence, iAnimIndices[0], cycle, boneMask ); - CalcAnimation( pStudioHdr, pos2, q2, seqdesc, sequence, iAnimIndices[2], cycle, boneMask ); - BlendBones( pStudioHdr, q, pos, seqdesc, sequence, q2, pos2, weight[2] / (weight[0] + weight[2]), boneMask ); - } - else - { - CalcAnimation( pStudioHdr, pos, q, seqdesc, sequence, iAnimIndices[0], cycle, boneMask ); - CalcAnimation( pStudioHdr, pos2, q2, seqdesc, sequence, iAnimIndices[1], cycle, boneMask ); - BlendBones( pStudioHdr, q, pos, seqdesc, sequence, q2, pos2, weight[1] / (weight[0] + weight[1]), boneMask ); - - CalcAnimation( pStudioHdr, pos3, q3, seqdesc, sequence, iAnimIndices[2], cycle, boneMask ); - BlendBones( pStudioHdr, q, pos, seqdesc, sequence, q3, pos3, weight[2], boneMask ); - } - } - } - - g_VectorPool.Free( pos2 ); - g_QaternionPool.Free( q2 ); - g_VectorPool.Free( pos3 ); - g_QaternionPool.Free( q3 ); - - return bResult; -} - - - - -//----------------------------------------------------------------------------- -// Purpose: calculate a pose for a single sequence -// adds autolayers, runs local ik rukes -//----------------------------------------------------------------------------- -void AddSequenceLayers( - const CStudioHdr *pStudioHdr, - CIKContext *pIKContext, - Vector pos[], - Quaternion q[], - mstudioseqdesc_t &seqdesc, - int sequence, - float cycle, - const float poseParameter[], - int boneMask, - float flWeight, - float flTime - ) -{ - for (int i = 0; i < seqdesc.numautolayers; i++) - { - mstudioautolayer_t *pLayer = seqdesc.pAutolayer( i ); - - if (pLayer->flags & STUDIO_AL_LOCAL) - continue; - - float layerCycle = cycle; - float layerWeight = flWeight; - - if (pLayer->start != pLayer->end) - { - float s = 1.0; - float index; - - if (!(pLayer->flags & STUDIO_AL_POSE)) - { - index = cycle; - } - else - { - int iSequence = pStudioHdr->iRelativeSeq( sequence, pLayer->iSequence ); - int iPose = pStudioHdr->GetSharedPoseParameter( iSequence, pLayer->iPose ); - if (iPose != -1) - { - const mstudioposeparamdesc_t &Pose = pStudioHdr->pPoseParameter( iPose ); - index = poseParameter[ iPose ] * (Pose.end - Pose.start) + Pose.start; - } - else - { - index = 0; - } - } - - if (index < pLayer->start) - continue; - if (index >= pLayer->end) - continue; - - if (index < pLayer->peak && pLayer->start != pLayer->peak) - { - s = (index - pLayer->start) / (pLayer->peak - pLayer->start); - } - else if (index > pLayer->tail && pLayer->end != pLayer->tail) - { - s = (pLayer->end - index) / (pLayer->end - pLayer->tail); - } - - if (pLayer->flags & STUDIO_AL_SPLINE) - { - s = SimpleSpline( s ); - } - - if ((pLayer->flags & STUDIO_AL_XFADE) && (index > pLayer->tail)) - { - layerWeight = ( s * flWeight ) / ( 1 - flWeight + s * flWeight ); - } - else if (pLayer->flags & STUDIO_AL_NOBLEND) - { - layerWeight = s; - } - else - { - layerWeight = flWeight * s; - } - - if (!(pLayer->flags & STUDIO_AL_POSE)) - { - layerCycle = (cycle - pLayer->start) / (pLayer->end - pLayer->start); - } - } - - int iSequence = pStudioHdr->iRelativeSeq( sequence, pLayer->iSequence ); - AccumulatePose( pStudioHdr, pIKContext, pos, q, iSequence, layerCycle, poseParameter, boneMask, layerWeight, flTime ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: calculate a pose for a single sequence -// adds autolayers, runs local ik rukes -//----------------------------------------------------------------------------- -void AddLocalLayers( - const CStudioHdr *pStudioHdr, - CIKContext *pIKContext, - Vector pos[], - Quaternion q[], - mstudioseqdesc_t &seqdesc, - int sequence, - float cycle, - const float poseParameter[], - int boneMask, - float flWeight, - float flTime - ) -{ - if (!(seqdesc.flags & STUDIO_LOCAL)) - { - return; - } - - for (int i = 0; i < seqdesc.numautolayers; i++) - { - mstudioautolayer_t *pLayer = seqdesc.pAutolayer( i ); - - if (!(pLayer->flags & STUDIO_AL_LOCAL)) - continue; - - float layerCycle = cycle; - float layerWeight = flWeight; - - if (pLayer->start != pLayer->end) - { - float s = 1.0; - - if (cycle < pLayer->start) - continue; - if (cycle >= pLayer->end) - continue; - - if (cycle < pLayer->peak && pLayer->start != pLayer->peak) - { - s = (cycle - pLayer->start) / (pLayer->peak - pLayer->start); - } - else if (cycle > pLayer->tail && pLayer->end != pLayer->tail) - { - s = (pLayer->end - cycle) / (pLayer->end - pLayer->tail); - } - - if (pLayer->flags & STUDIO_AL_SPLINE) - { - s = SimpleSpline( s ); - } - - if ((pLayer->flags & STUDIO_AL_XFADE) && (cycle > pLayer->tail)) - { - layerWeight = ( s * flWeight ) / ( 1 - flWeight + s * flWeight ); - } - else if (pLayer->flags & STUDIO_AL_NOBLEND) - { - layerWeight = s; - } - else - { - layerWeight = flWeight * s; - } - - layerCycle = (cycle - pLayer->start) / (pLayer->end - pLayer->start); - } - - int iSequence = pStudioHdr->iRelativeSeq( sequence, pLayer->iSequence ); - AccumulatePose( pStudioHdr, pIKContext, pos, q, iSequence, layerCycle, poseParameter, boneMask, layerWeight, flTime ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: calculate a pose for a single sequence -// adds autolayers, runs local ik rukes -//----------------------------------------------------------------------------- -void CalcPose( - const CStudioHdr *pStudioHdr, - CIKContext *pIKContext, - Vector pos[], - Quaternion q[], - int sequence, - float cycle, - const float poseParameter[], - int boneMask, - float flWeight, - float flTime - ) -{ - mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( sequence ); - - Assert( flWeight >= 0.0f && flWeight <= 1.0f ); - // This shouldn't be necessary, but the Assert should help us catch whoever is screwing this up - flWeight = clamp( flWeight, 0.0f, 1.0f ); - - // add any IK locks to prevent numautolayers from moving extremities - CIKContext seq_ik; - if (seqdesc.numiklocks) - { - seq_ik.Init( pStudioHdr, vec3_angle, vec3_origin, 0.0, 0, boneMask ); // local space relative so absolute position doesn't mater - seq_ik.AddSequenceLocks( seqdesc, pos, q ); - } - - CalcPoseSingle( pStudioHdr, pos, q, seqdesc, sequence, cycle, poseParameter, boneMask, flTime ); - - if ( pIKContext ) - { - pIKContext->AddDependencies( seqdesc, sequence, cycle, poseParameter, flWeight ); - } - - AddSequenceLayers( pStudioHdr, pIKContext, pos, q, seqdesc, sequence, cycle, poseParameter, boneMask, flWeight, flTime ); - - if (seqdesc.numiklocks) - { - seq_ik.SolveSequenceLocks( seqdesc, pos, q ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: accumulate a pose for a single sequence on top of existing animation -// adds autolayers, runs local ik rukes -//----------------------------------------------------------------------------- -void AccumulatePose( - const CStudioHdr *pStudioHdr, - CIKContext *pIKContext, - Vector pos[], - Quaternion q[], - int sequence, - float cycle, - const float poseParameter[], - int boneMask, - float flWeight, - float flTime - ) -{ - Vector pos2[MAXSTUDIOBONES]; - QuaternionAligned q2[MAXSTUDIOBONES]; - - Assert( flWeight >= 0.0f && flWeight <= 1.0f ); - // This shouldn't be necessary, but the Assert should help us catch whoever is screwing this up - flWeight = clamp( flWeight, 0.0f, 1.0f ); - - if ( sequence < 0 ) - return; - -#ifdef CLIENT_DLL - // Trigger pose debugger - g_pPoseDebugger->AccumulatePose( pStudioHdr, pIKContext, pos, q, sequence, cycle, poseParameter, boneMask, flWeight, flTime ); -#endif - - mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( sequence ); - - // add any IK locks to prevent extremities from moving - CIKContext seq_ik; - if (seqdesc.numiklocks) - { - seq_ik.Init( pStudioHdr, vec3_angle, vec3_origin, 0.0, 0, boneMask ); // local space relative so absolute position doesn't mater - seq_ik.AddSequenceLocks( seqdesc, pos, q ); - } - - if (seqdesc.flags & STUDIO_LOCAL) - { - InitPose( pStudioHdr, pos2, q2, boneMask ); - } - - if (CalcPoseSingle( pStudioHdr, pos2, q2, seqdesc, sequence, cycle, poseParameter, boneMask, flTime )) - { - // this weight is wrong, the IK rules won't composite at the correct intensity - AddLocalLayers( pStudioHdr, pIKContext, pos2, q2, seqdesc, sequence, cycle, poseParameter, boneMask, 1.0, flTime ); - SlerpBones( pStudioHdr, q, pos, seqdesc, sequence, q2, pos2, flWeight, boneMask ); - } - - if ( pIKContext ) - { - pIKContext->AddDependencies( seqdesc, sequence, cycle, poseParameter, flWeight ); - } - - AddSequenceLayers( pStudioHdr, pIKContext, pos, q, seqdesc, sequence, cycle, poseParameter, boneMask, flWeight, flTime ); - - if (seqdesc.numiklocks) - { - seq_ik.SolveSequenceLocks( seqdesc, pos, q ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: blend together q1,pos1 with q2,pos2. Return result in q1,pos1. -// 0 returns q1, pos1. 1 returns q2, pos2 -//----------------------------------------------------------------------------- -void CalcBoneAdj( - const CStudioHdr *pStudioHdr, - Vector pos[], - Quaternion q[], - const float controllers[], - int boneMask - ) -{ - int i, j, k; - float value; - mstudiobonecontroller_t *pbonecontroller; - Vector p0; - RadianEuler a0; - Quaternion q0; - - for (j = 0; j < pStudioHdr->numbonecontrollers(); j++) - { - pbonecontroller = pStudioHdr->pBonecontroller( j ); - k = pbonecontroller->bone; - - if (pStudioHdr->boneFlags( k ) & boneMask) - { - i = pbonecontroller->inputfield; - value = controllers[i]; - if (value < 0) value = 0; - if (value > 1.0) value = 1.0; - value = (1.0 - value) * pbonecontroller->start + value * pbonecontroller->end; - - switch(pbonecontroller->type & STUDIO_TYPES) - { - case STUDIO_XR: - a0.Init( value * (M_PI / 180.0), 0, 0 ); - AngleQuaternion( a0, q0 ); - QuaternionSM( 1.0, q0, q[k], q[k] ); - break; - case STUDIO_YR: - a0.Init( 0, value * (M_PI / 180.0), 0 ); - AngleQuaternion( a0, q0 ); - QuaternionSM( 1.0, q0, q[k], q[k] ); - break; - case STUDIO_ZR: - a0.Init( 0, 0, value * (M_PI / 180.0) ); - AngleQuaternion( a0, q0 ); - QuaternionSM( 1.0, q0, q[k], q[k] ); - break; - case STUDIO_X: - pos[k].x += value; - break; - case STUDIO_Y: - pos[k].y += value; - break; - case STUDIO_Z: - pos[k].z += value; - break; - } - } - } -} - - -void CalcBoneDerivatives( Vector &velocity, AngularImpulse &angVel, const matrix3x4_t &prev, const matrix3x4_t ¤t, float dt ) -{ - float scale = 1.0; - if ( dt > 0 ) - { - scale = 1.0 / dt; - } - - Vector endPosition, startPosition, deltaAxis; - QAngle endAngles, startAngles; - float deltaAngle; - - MatrixAngles( prev, startAngles, startPosition ); - MatrixAngles( current, endAngles, endPosition ); - - velocity.x = (endPosition.x - startPosition.x) * scale; - velocity.y = (endPosition.y - startPosition.y) * scale; - velocity.z = (endPosition.z - startPosition.z) * scale; - RotationDeltaAxisAngle( startAngles, endAngles, deltaAxis, deltaAngle ); - VectorScale( deltaAxis, (deltaAngle * scale), angVel ); -} - -void CalcBoneVelocityFromDerivative( const QAngle &vecAngles, Vector &velocity, AngularImpulse &angVel, const matrix3x4_t ¤t ) -{ - Vector vecLocalVelocity; - AngularImpulse LocalAngVel; - Quaternion q; - float angle; - MatrixAngles( current, q, vecLocalVelocity ); - QuaternionAxisAngle( q, LocalAngVel, angle ); - LocalAngVel *= angle; - - matrix3x4_t matAngles; - AngleMatrix( vecAngles, matAngles ); - VectorTransform( vecLocalVelocity, matAngles, velocity ); - VectorTransform( LocalAngVel, matAngles, angVel ); -} - - - - -class CIKSolver -{ -public: -//-------- SOLVE TWO LINK INVERSE KINEMATICS ------------- -// Author: Ken Perlin -// -// Given a two link joint from [0,0,0] to end effector position P, -// let link lengths be a and b, and let norm |P| = c. Clearly a+b <= c. -// -// Problem: find a "knee" position Q such that |Q| = a and |P-Q| = b. -// -// In the case of a point on the x axis R = [c,0,0], there is a -// closed form solution S = [d,e,0], where |S| = a and |R-S| = b: -// -// d2+e2 = a2 -- because |S| = a -// (c-d)2+e2 = b2 -- because |R-S| = b -// -// c2-2cd+d2+e2 = b2 -- combine the two equations -// c2-2cd = b2 - a2 -// c-2d = (b2-a2)/c -// d - c/2 = (a2-b2)/c / 2 -// -// d = (c + (a2-b2/c) / 2 -- to solve for d and e. -// e = sqrt(a2-d2) - - static float findD(float a, float b, float c) { - return (c + (a*a-b*b)/c) / 2; - } - static float findE(float a, float d) { return sqrt(a*a-d*d); } - -// This leads to a solution to the more general problem: -// -// (1) R = Mfwd(P) -- rotate P onto the x axis -// (2) Solve for S -// (3) Q = Minv(S) -- rotate back again - - float Mfwd[3][3]; - float Minv[3][3]; - - bool solve(float A, float B, float const P[], float const D[], float Q[]) { - float R[3]; - defineM(P,D); - rot(Minv,P,R); - float r = length(R); - float d = findD(A,B,r); - float e = findE(A,d); - float S[3] = {d,e,0}; - rot(Mfwd,S,Q); - return d > (r - B) && d < A; - } - -// If "knee" position Q needs to be as close as possible to some point D, -// then choose M such that M(D) is in the y>0 half of the z=0 plane. -// -// Given that constraint, define the forward and inverse of M as follows: - - void defineM(float const P[], float const D[]) { - float *X = Minv[0], *Y = Minv[1], *Z = Minv[2]; - -// Minv defines a coordinate system whose x axis contains P, so X = unit(P). - int i; - for (i = 0 ; i < 3 ; i++) - X[i] = P[i]; - normalize(X); - -// Its y axis is perpendicular to P, so Y = unit( E - X(EX) ). - - float dDOTx = dot(D,X); - for (i = 0 ; i < 3 ; i++) - Y[i] = D[i] - dDOTx * X[i]; - normalize(Y); - -// Its z axis is perpendicular to both X and Y, so Z = XY. - - cross(X,Y,Z); - -// Mfwd = (Minv)T, since transposing inverts a rotation matrix. - - for (i = 0 ; i < 3 ; i++) { - Mfwd[i][0] = Minv[0][i]; - Mfwd[i][1] = Minv[1][i]; - Mfwd[i][2] = Minv[2][i]; - } - } - -//------------ GENERAL VECTOR MATH SUPPORT ----------- - - static float dot(float const a[], float const b[]) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; } - - static float length(float const v[]) { return sqrt( dot(v,v) ); } - - static void normalize(float v[]) { - float norm = length(v); - for (int i = 0 ; i < 3 ; i++) - v[i] /= norm; - } - - static void cross(float const a[], float const b[], float c[]) { - c[0] = a[1] * b[2] - a[2] * b[1]; - c[1] = a[2] * b[0] - a[0] * b[2]; - c[2] = a[0] * b[1] - a[1] * b[0]; - } - - static void rot(float const M[3][3], float const src[], float dst[]) { - for (int i = 0 ; i < 3 ; i++) - dst[i] = dot(M[i],src); - } -}; - - - -//----------------------------------------------------------------------------- -// Purpose: visual debugging code -//----------------------------------------------------------------------------- -#if 1 -inline void debugLine(const Vector& origin, const Vector& dest, int r, int g, int b, bool noDepthTest, float duration) { }; -#else -extern void drawLine( const Vector &p1, const Vector &p2, int r = 0, int g = 0, int b = 1, bool noDepthTest = true, float duration = 0.1 ); -void debugLine(const Vector& origin, const Vector& dest, int r, int g, int b, bool noDepthTest, float duration) -{ - drawLine( origin, dest, r, g, b, noDepthTest, duration ); -} -#endif - - -//----------------------------------------------------------------------------- -// Purpose: for a 2 bone chain, find the IK solution and reset the matrices -//----------------------------------------------------------------------------- -bool Studio_SolveIK( mstudioikchain_t *pikchain, Vector &targetFoot, matrix3x4_t *pBoneToWorld ) -{ - if (pikchain->pLink(0)->kneeDir.LengthSqr() > 0.0) - { - Vector targetKneeDir, targetKneePos; - // FIXME: knee length should be as long as the legs - Vector tmp = pikchain->pLink( 0 )->kneeDir; - VectorRotate( tmp, pBoneToWorld[ pikchain->pLink( 0 )->bone ], targetKneeDir ); - MatrixPosition( pBoneToWorld[ pikchain->pLink( 1 )->bone ], targetKneePos ); - return Studio_SolveIK( pikchain->pLink( 0 )->bone, pikchain->pLink( 1 )->bone, pikchain->pLink( 2 )->bone, targetFoot, targetKneePos, targetKneeDir, pBoneToWorld ); - } - else - { - return Studio_SolveIK( pikchain->pLink( 0 )->bone, pikchain->pLink( 1 )->bone, pikchain->pLink( 2 )->bone, targetFoot, pBoneToWorld ); - } -} - - -#define KNEEMAX_EPSILON 0.9998 // (0.9998 is about 1 degree) - -//----------------------------------------------------------------------------- -// Purpose: Solve Knee position for a known hip and foot location, but no specific knee direction preference -//----------------------------------------------------------------------------- - -bool Studio_SolveIK( int iThigh, int iKnee, int iFoot, Vector &targetFoot, matrix3x4_t *pBoneToWorld ) -{ - Vector worldFoot, worldKnee, worldThigh; - - MatrixPosition( pBoneToWorld[ iThigh ], worldThigh ); - MatrixPosition( pBoneToWorld[ iKnee ], worldKnee ); - MatrixPosition( pBoneToWorld[ iFoot ], worldFoot ); - - //debugLine( worldThigh, worldKnee, 0, 0, 255, true, 0 ); - //debugLine( worldKnee, worldFoot, 0, 0, 255, true, 0 ); - - Vector ikFoot, ikKnee; - - ikFoot = targetFoot - worldThigh; - ikKnee = worldKnee - worldThigh; - - float l1 = (worldKnee-worldThigh).Length(); - float l2 = (worldFoot-worldKnee).Length(); - float l3 = (worldFoot-worldThigh).Length(); - - // leg too straight to figure out knee? - if (l3 > (l1 + l2) * KNEEMAX_EPSILON) - { - return false; - } - - Vector ikHalf = (worldFoot-worldThigh) * (l1 / l3); - - // FIXME: what to do when the knee completely straight? - Vector ikKneeDir = ikKnee - ikHalf; - VectorNormalize( ikKneeDir ); - - return Studio_SolveIK( iThigh, iKnee, iFoot, targetFoot, worldKnee, ikKneeDir, pBoneToWorld ); -} - -//----------------------------------------------------------------------------- -// Purpose: Realign the matrix so that its X axis points along the desired axis. -//----------------------------------------------------------------------------- -void Studio_AlignIKMatrix( matrix3x4_t &mMat, const Vector &vAlignTo ) -{ - Vector tmp1, tmp2, tmp3; - - // Column 0 (X) becomes the vector. - tmp1 = vAlignTo; - VectorNormalize( tmp1 ); - MatrixSetColumn( tmp1, 0, mMat ); - - // Column 1 (Y) is the cross of the vector and column 2 (Z). - MatrixGetColumn( mMat, 2, tmp3 ); - tmp2 = tmp3.Cross( tmp1 ); - VectorNormalize( tmp2 ); - // FIXME: check for X being too near to Z - MatrixSetColumn( tmp2, 1, mMat ); - - // Column 2 (Z) is the cross of columns 0 (X) and 1 (Y). - tmp3 = tmp1.Cross( tmp2 ); - MatrixSetColumn( tmp3, 2, mMat ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Solve Knee position for a known hip and foot location, and a known knee direction -//----------------------------------------------------------------------------- - -bool Studio_SolveIK( int iThigh, int iKnee, int iFoot, Vector &targetFoot, Vector &targetKneePos, Vector &targetKneeDir, matrix3x4_t *pBoneToWorld ) -{ - Vector worldFoot, worldKnee, worldThigh; - - MatrixPosition( pBoneToWorld[ iThigh ], worldThigh ); - MatrixPosition( pBoneToWorld[ iKnee ], worldKnee ); - MatrixPosition( pBoneToWorld[ iFoot ], worldFoot ); - - //debugLine( worldThigh, worldKnee, 0, 0, 255, true, 0 ); - //debugLine( worldThigh, worldThigh + targetKneeDir, 0, 0, 255, true, 0 ); - // debugLine( worldKnee, targetKnee, 0, 0, 255, true, 0 ); - - Vector ikFoot, ikTargetKnee, ikKnee; - - ikFoot = targetFoot - worldThigh; - ikKnee = targetKneePos - worldThigh; - - float l1 = (worldKnee-worldThigh).Length(); - float l2 = (worldFoot-worldKnee).Length(); - - // exaggerate knee targets for legs that are nearly straight - // FIXME: should be configurable, and the ikKnee should be from the original animation, not modifed - float d = (targetFoot-worldThigh).Length() - MIN( l1, l2 ); - d = MAX( l1 + l2, d ); - // FIXME: too short knee directions cause trouble - d = d * 100; - - ikTargetKnee = ikKnee + targetKneeDir * d; - - // debugLine( worldKnee, worldThigh + ikTargetKnee, 0, 0, 255, true, 0 ); - - int color[3] = { 0, 255, 0 }; - - // too far away? (0.9998 is about 1 degree) - if (ikFoot.Length() > (l1 + l2) * KNEEMAX_EPSILON) - { - VectorNormalize( ikFoot ); - VectorScale( ikFoot, (l1 + l2) * KNEEMAX_EPSILON, ikFoot ); - color[0] = 255; color[1] = 0; color[2] = 0; - } - - // too close? - // limit distance to about an 80 degree knee bend - float minDist = MAX( fabs(l1 - l2) * 1.15, MIN( l1, l2 ) * 0.15 ); - if (ikFoot.Length() < minDist) - { - // too close to get an accurate vector, just use original vector - ikFoot = (worldFoot - worldThigh); - VectorNormalize( ikFoot ); - VectorScale( ikFoot, minDist, ikFoot ); - } - - CIKSolver ik; - if (ik.solve( l1, l2, ikFoot.Base(), ikTargetKnee.Base(), ikKnee.Base() )) - { - matrix3x4_t& mWorldThigh = pBoneToWorld[ iThigh ]; - matrix3x4_t& mWorldKnee = pBoneToWorld[ iKnee ]; - matrix3x4_t& mWorldFoot = pBoneToWorld[ iFoot ]; - - //debugLine( worldThigh, ikKnee + worldThigh, 255, 0, 0, true, 0 ); - //debugLine( ikKnee + worldThigh, ikFoot + worldThigh, 255, 0, 0, true,0 ); - - // debugLine( worldThigh, ikKnee + worldThigh, color[0], color[1], color[2], true, 0 ); - // debugLine( ikKnee + worldThigh, ikFoot + worldThigh, color[0], color[1], color[2], true,0 ); - - - // build transformation matrix for thigh - Studio_AlignIKMatrix( mWorldThigh, ikKnee ); - Studio_AlignIKMatrix( mWorldKnee, ikFoot - ikKnee ); - - - mWorldKnee[0][3] = ikKnee.x + worldThigh.x; - mWorldKnee[1][3] = ikKnee.y + worldThigh.y; - mWorldKnee[2][3] = ikKnee.z + worldThigh.z; - - mWorldFoot[0][3] = ikFoot.x + worldThigh.x; - mWorldFoot[1][3] = ikFoot.y + worldThigh.y; - mWorldFoot[2][3] = ikFoot.z + worldThigh.z; - - return true; - } - else - { - /* - debugLine( worldThigh, worldThigh + ikKnee, 255, 0, 0, true, 0 ); - debugLine( worldThigh + ikKnee, worldThigh + ikFoot, 255, 0, 0, true, 0 ); - debugLine( worldThigh + ikFoot, worldThigh, 255, 0, 0, true, 0 ); - debugLine( worldThigh + ikKnee, worldThigh + ikTargetKnee, 255, 0, 0, true, 0 ); - */ - return false; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -float Studio_IKRuleWeight( mstudioikrule_t &ikRule, const mstudioanimdesc_t *panim, float flCycle, int &iFrame, float &fraq ) -{ - if (ikRule.end > 1.0f && flCycle < ikRule.start) - { - flCycle = flCycle + 1.0f; - } - - float value = 0.0f; - fraq = (panim->numframes - 1) * (flCycle - ikRule.start) + ikRule.iStart; - iFrame = (int)fraq; - fraq = fraq - iFrame; - - if (flCycle < ikRule.start) - { - iFrame = ikRule.iStart; - fraq = 0.0f; - return 0.0f; - } - else if (flCycle < ikRule.peak ) - { - value = (flCycle - ikRule.start) / (ikRule.peak - ikRule.start); - } - else if (flCycle < ikRule.tail ) - { - return 1.0f; - } - else if (flCycle < ikRule.end ) - { - value = 1.0f - ((flCycle - ikRule.tail) / (ikRule.end - ikRule.tail)); - } - else - { - fraq = (panim->numframes - 1) * (ikRule.end - ikRule.start) + ikRule.iStart; - iFrame = (int)fraq; - fraq = fraq - iFrame; - } - return SimpleSpline( value ); -} - - -float Studio_IKRuleWeight( ikcontextikrule_t &ikRule, float flCycle ) -{ - if (ikRule.end > 1.0f && flCycle < ikRule.start) - { - flCycle = flCycle + 1.0f; - } - - float value = 0.0f; - if (flCycle < ikRule.start) - { - return 0.0f; - } - else if (flCycle < ikRule.peak ) - { - value = (flCycle - ikRule.start) / (ikRule.peak - ikRule.start); - } - else if (flCycle < ikRule.tail ) - { - return 1.0f; - } - else if (flCycle < ikRule.end ) - { - value = 1.0f - ((flCycle - ikRule.tail) / (ikRule.end - ikRule.tail)); - } - return 3.0f * value * value - 2.0f * value * value * value; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -bool Studio_IKShouldLatch( ikcontextikrule_t &ikRule, float flCycle ) -{ - if (ikRule.end > 1.0f && flCycle < ikRule.start) - { - flCycle = flCycle + 1.0f; - } - - if (flCycle < ikRule.peak ) - { - return false; - } - else if (flCycle < ikRule.end ) - { - return true; - } - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -float Studio_IKTail( ikcontextikrule_t &ikRule, float flCycle ) -{ - if (ikRule.end > 1.0f && flCycle < ikRule.start) - { - flCycle = flCycle + 1.0f; - } - - if (flCycle <= ikRule.tail ) - { - return 0.0f; - } - else if (flCycle < ikRule.end ) - { - return ((flCycle - ikRule.tail) / (ikRule.end - ikRule.tail)); - } - return 0.0; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - - -bool Studio_IKAnimationError( const CStudioHdr *pStudioHdr, mstudioikrule_t *pRule, const mstudioanimdesc_t *panim, float flCycle, Vector &pos, Quaternion &q, float &flWeight ) -{ - float fraq; - int iFrame; - - flWeight = Studio_IKRuleWeight( *pRule, panim, flCycle, iFrame, fraq ); - Assert( fraq >= 0.0 && fraq < 1.0 ); - Assert( flWeight >= 0.0f && flWeight <= 1.0f ); - - // This shouldn't be necessary, but the Assert should help us catch whoever is screwing this up - flWeight = clamp( flWeight, 0.0f, 1.0f ); - - if (pRule->type != IK_GROUND && flWeight < 0.0001) - return false; - - mstudioikerror_t *pError = pRule->pError( iFrame ); - if (pError != NULL) - { - if (fraq < 0.001) - { - q = pError[0].q; - pos = pError[0].pos; - } - else - { - QuaternionBlend( pError[0].q, pError[1].q, fraq, q ); - pos = pError[0].pos * (1.0f - fraq) + pError[1].pos * fraq; - } - return true; - } - - mstudiocompressedikerror_t *pCompressed = pRule->pCompressedError(); - if (pCompressed != NULL) - { - CalcDecompressedAnimation( pCompressed, iFrame - pRule->iStart, fraq, pos, q ); - return true; - } - // no data, disable IK rule - Assert( 0 ); - flWeight = 0.0f; - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: For a specific sequence:rule, find where it starts, stops, and what -// the estimated offset from the connection point is. -// return true if the rule is within bounds. -//----------------------------------------------------------------------------- - -bool Studio_IKSequenceError( const CStudioHdr *pStudioHdr, mstudioseqdesc_t &seqdesc, int iSequence, float flCycle, int iRule, const float poseParameter[], mstudioanimdesc_t *panim[4], float weight[4], ikcontextikrule_t &ikRule ) -{ - int i; - - memset( &ikRule, 0, sizeof(ikRule) ); - ikRule.start = ikRule.peak = ikRule.tail = ikRule.end = 0; - - - mstudioikrule_t *prevRule = NULL; - - // find overall influence - for (i = 0; i < 4; i++) - { - if (weight[i]) - { - if (iRule >= panim[i]->numikrules || panim[i]->numikrules != panim[0]->numikrules) - { - Assert( 0 ); - return false; - } - - mstudioikrule_t *pRule = panim[i]->pIKRule( iRule ); - if (pRule == NULL) - return false; - - float dt = 0.0; - if (prevRule != NULL) - { - if (pRule->start - prevRule->start > 0.5) - { - dt = -1.0; - } - else if (pRule->start - prevRule->start < -0.5) - { - dt = 1.0; - } - } - else - { - prevRule = pRule; - } - - ikRule.start += (pRule->start + dt) * weight[i]; - ikRule.peak += (pRule->peak + dt) * weight[i]; - ikRule.tail += (pRule->tail + dt) * weight[i]; - ikRule.end += (pRule->end + dt) * weight[i]; - } - } - if (ikRule.start > 1.0) - { - ikRule.start -= 1.0; - ikRule.peak -= 1.0; - ikRule.tail -= 1.0; - ikRule.end -= 1.0; - } - else if (ikRule.start < 0.0) - { - ikRule.start += 1.0; - ikRule.peak += 1.0; - ikRule.tail += 1.0; - ikRule.end += 1.0; - } - - ikRule.flWeight = Studio_IKRuleWeight( ikRule, flCycle ); - if (ikRule.flWeight <= 0.001f) - { - // go ahead and allow IK_GROUND rules a virtual looping section - if ( panim[0]->pIKRule( iRule ) == NULL ) - return false; - if ((panim[0]->flags & STUDIO_LOOPING) && panim[0]->pIKRule( iRule )->type == IK_GROUND && ikRule.end - ikRule.start > 0.75 ) - { - ikRule.flWeight = 0.001; - flCycle = ikRule.end - 0.001; - } - else - { - return false; - } - } - - Assert( ikRule.flWeight > 0.0f ); - - ikRule.pos.Init(); - ikRule.q.Init(); - - // find target error - float total = 0.0f; - for (i = 0; i < 4; i++) - { - if (weight[i]) - { - Vector pos1; - Quaternion q1; - float w; - - mstudioikrule_t *pRule = panim[i]->pIKRule( iRule ); - if (pRule == NULL) - return false; - - ikRule.chain = pRule->chain; // FIXME: this is anim local - ikRule.bone = pRule->bone; // FIXME: this is anim local - ikRule.type = pRule->type; - ikRule.slot = pRule->slot; - - ikRule.height += pRule->height * weight[i]; - ikRule.floor += pRule->floor * weight[i]; - ikRule.radius += pRule->radius * weight[i]; - ikRule.drop += pRule->drop * weight[i]; - ikRule.top += pRule->top * weight[i]; - - // keep track of tail condition - ikRule.release += Studio_IKTail( ikRule, flCycle ) * weight[i]; - - // only check rules with error values - switch( ikRule.type ) - { - case IK_SELF: - case IK_WORLD: - case IK_GROUND: - case IK_ATTACHMENT: - { - int bResult = Studio_IKAnimationError( pStudioHdr, pRule, panim[i], flCycle, pos1, q1, w ); - - if (bResult) - { - ikRule.pos = ikRule.pos + pos1 * weight[i]; - QuaternionAccumulate( ikRule.q, weight[i], q1, ikRule.q ); - total += weight[i]; - } - } - break; - default: - total += weight[i]; - break; - } - - ikRule.latched = Studio_IKShouldLatch( ikRule, flCycle ) * ikRule.flWeight; - - if (ikRule.type == IK_ATTACHMENT) - { - ikRule.szLabel = pRule->pszAttachment(); - } - } - } - - if (total <= 0.0001f) - { - return false; - } - - if (total < 0.999f) - { - VectorScale( ikRule.pos, 1.0f / total, ikRule.pos ); - QuaternionScale( ikRule.q, 1.0f / total, ikRule.q ); - } - - if (ikRule.type == IK_SELF && ikRule.bone != -1) - { - // FIXME: this is anim local, not seq local! - ikRule.bone = pStudioHdr->RemapSeqBone( iSequence, ikRule.bone ); - if (ikRule.bone == -1) - return false; - } - - QuaternionNormalize( ikRule.q ); - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - - -CIKContext::CIKContext() -{ - m_target.EnsureCapacity( 12 ); // FIXME: this sucks, shouldn't it be grown? - m_iFramecounter = -1; - m_pStudioHdr = NULL; - m_flTime = -1.0f; - m_target.SetSize( 0 ); -} - - -void CIKContext::Init( const CStudioHdr *pStudioHdr, const QAngle &angles, const Vector &pos, float flTime, int iFramecounter, int boneMask ) -{ - m_pStudioHdr = pStudioHdr; - m_ikChainRule.RemoveAll(); // m_numikrules = 0; - if (pStudioHdr->numikchains()) - { - m_ikChainRule.SetSize( pStudioHdr->numikchains() ); - - // FIXME: Brutal hackery to prevent a crash - if (m_target.Count() == 0) - { - m_target.SetSize(12); - memset( m_target.Base(), 0, sizeof(m_target[0])*m_target.Count() ); - ClearTargets(); - } - - } - else - { - m_target.SetSize( 0 ); - } - AngleMatrix( angles, pos, m_rootxform ); - m_iFramecounter = iFramecounter; - m_flTime = flTime; - m_boneMask = boneMask; -} - -void CIKContext::AddDependencies( mstudioseqdesc_t &seqdesc, int iSequence, float flCycle, const float poseParameters[], float flWeight ) -{ - int i; - - if ( m_pStudioHdr->numikchains() == 0) - return; - - if (seqdesc.numikrules == 0) - return; - - ikcontextikrule_t ikrule; - - Assert( flWeight >= 0.0f && flWeight <= 1.0f ); - // This shouldn't be necessary, but the Assert should help us catch whoever is screwing this up - flWeight = clamp( flWeight, 0.0f, 1.0f ); - - // unify this - if (seqdesc.flags & STUDIO_REALTIME) - { - float cps = Studio_CPS( m_pStudioHdr, seqdesc, iSequence, poseParameters ); - flCycle = m_flTime * cps; - flCycle = flCycle - (int)flCycle; - } - else if (flCycle < 0 || flCycle >= 1) - { - if (seqdesc.flags & STUDIO_LOOPING) - { - flCycle = flCycle - (int)flCycle; - if (flCycle < 0) flCycle += 1; - } - else - { - flCycle = MAX( 0.0, MIN( flCycle, 0.9999 ) ); - } - } - - mstudioanimdesc_t *panim[4]; - float weight[4]; - - Studio_SeqAnims( m_pStudioHdr, seqdesc, iSequence, poseParameters, panim, weight ); - - // FIXME: add proper number of rules!!! - for (i = 0; i < seqdesc.numikrules; i++) - { - if ( !Studio_IKSequenceError( m_pStudioHdr, seqdesc, iSequence, flCycle, i, poseParameters, panim, weight, ikrule ) ) - continue; - - // don't add rule if the bone isn't going to be calculated - int bone = m_pStudioHdr->pIKChain( ikrule.chain )->pLink( 2 )->bone; - if ( !(m_pStudioHdr->boneFlags( bone ) & m_boneMask)) - continue; - - // or if its relative bone isn't going to be calculated - if ( ikrule.bone >= 0 && !(m_pStudioHdr->boneFlags( ikrule.bone ) & m_boneMask)) - continue; - - // FIXME: Brutal hackery to prevent a crash - if (m_target.Count() == 0) - { - m_target.SetSize(12); - memset( m_target.Base(), 0, sizeof(m_target[0])*m_target.Count() ); - ClearTargets(); - } - - ikrule.flRuleWeight = flWeight; - - if (ikrule.flRuleWeight * ikrule.flWeight > 0.999) - { - if ( ikrule.type != IK_UNLATCH) - { - // clear out chain if rule is 100% - m_ikChainRule.Element( ikrule.chain ).RemoveAll( ); - if ( ikrule.type == IK_RELEASE) - { - continue; - } - } - } - - int nIndex = m_ikChainRule.Element( ikrule.chain ).AddToTail( ); - m_ikChainRule.Element( ikrule.chain ).Element( nIndex ) = ikrule; - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -void CIKContext::AddAutoplayLocks( Vector pos[], Quaternion q[] ) -{ - // skip all array access if no autoplay locks. - if (m_pStudioHdr->GetNumIKAutoplayLocks() == 0) - { - return; - } - - matrix3x4_t *boneToWorld = g_MatrixPool.Alloc(); - CBoneBitList boneComputed; - - int ikOffset = m_ikLock.AddMultipleToTail( m_pStudioHdr->GetNumIKAutoplayLocks() ); - memset( &m_ikLock[ikOffset], 0, sizeof(ikcontextikrule_t)*m_pStudioHdr->GetNumIKAutoplayLocks() ); - - for (int i = 0; i < m_pStudioHdr->GetNumIKAutoplayLocks(); i++) - { - const mstudioiklock_t &lock = m_pStudioHdr->pIKAutoplayLock( i ); - mstudioikchain_t *pchain = m_pStudioHdr->pIKChain( lock.chain ); - int bone = pchain->pLink( 2 )->bone; - - // don't bother with iklock if the bone isn't going to be calculated - if ( !(m_pStudioHdr->boneFlags( bone ) & m_boneMask)) - continue; - - // eval current ik'd bone - BuildBoneChain( pos, q, bone, boneToWorld, boneComputed ); - - ikcontextikrule_t &ikrule = m_ikLock[ i + ikOffset ]; - - ikrule.chain = lock.chain; - ikrule.slot = i; - ikrule.type = IK_WORLD; - - MatrixAngles( boneToWorld[bone], ikrule.q, ikrule.pos ); - - // save off current knee direction - if (pchain->pLink(0)->kneeDir.LengthSqr() > 0.0) - { - Vector tmp = pchain->pLink( 0 )->kneeDir; - VectorRotate( pchain->pLink( 0 )->kneeDir, boneToWorld[ pchain->pLink( 0 )->bone ], ikrule.kneeDir ); - MatrixPosition( boneToWorld[ pchain->pLink( 1 )->bone ], ikrule.kneePos ); - } - else - { - ikrule.kneeDir.Init( ); - } - } - g_MatrixPool.Free( boneToWorld ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -void CIKContext::AddSequenceLocks( mstudioseqdesc_t &seqdesc, Vector pos[], Quaternion q[] ) -{ - if ( m_pStudioHdr->numikchains() == 0) - { - return; - } - - if ( seqdesc.numiklocks == 0 ) - { - return; - } - - matrix3x4_t *boneToWorld = g_MatrixPool.Alloc(); - CBoneBitList boneComputed; - - int ikOffset = m_ikLock.AddMultipleToTail( seqdesc.numiklocks ); - memset( &m_ikLock[ikOffset], 0, sizeof(ikcontextikrule_t) * seqdesc.numiklocks ); - - for (int i = 0; i < seqdesc.numiklocks; i++) - { - mstudioiklock_t *plock = seqdesc.pIKLock( i ); - mstudioikchain_t *pchain = m_pStudioHdr->pIKChain( plock->chain ); - int bone = pchain->pLink( 2 )->bone; - - // don't bother with iklock if the bone isn't going to be calculated - if ( !(m_pStudioHdr->boneFlags( bone ) & m_boneMask)) - continue; - - // eval current ik'd bone - BuildBoneChain( pos, q, bone, boneToWorld, boneComputed ); - - ikcontextikrule_t &ikrule = m_ikLock[i+ikOffset]; - ikrule.chain = i; - ikrule.slot = i; - ikrule.type = IK_WORLD; - - MatrixAngles( boneToWorld[bone], ikrule.q, ikrule.pos ); - - // save off current knee direction - if (pchain->pLink(0)->kneeDir.LengthSqr() > 0.0) - { - VectorRotate( pchain->pLink( 0 )->kneeDir, boneToWorld[ pchain->pLink( 0 )->bone ], ikrule.kneeDir ); - } - else - { - ikrule.kneeDir.Init( ); - } - } - g_MatrixPool.Free( boneToWorld ); -} - -//----------------------------------------------------------------------------- -// Purpose: build boneToWorld transforms for a specific bone -//----------------------------------------------------------------------------- -void CIKContext::BuildBoneChain( - const Vector pos[], - const Quaternion q[], - int iBone, - matrix3x4_t *pBoneToWorld, - CBoneBitList &boneComputed ) -{ - Assert( m_pStudioHdr->boneFlags( iBone ) & m_boneMask ); - ::BuildBoneChain( m_pStudioHdr, m_rootxform, pos, q, iBone, pBoneToWorld, boneComputed ); -} - - - -//----------------------------------------------------------------------------- -// Purpose: build boneToWorld transforms for a specific bone -//----------------------------------------------------------------------------- -void BuildBoneChain( - const CStudioHdr *pStudioHdr, - const matrix3x4_t &rootxform, - const Vector pos[], - const Quaternion q[], - int iBone, - matrix3x4_t *pBoneToWorld, - CBoneBitList &boneComputed ) -{ - if ( boneComputed.IsBoneMarked(iBone) ) - return; - - matrix3x4_t bonematrix; - QuaternionMatrix( q[iBone], pos[iBone], bonematrix ); - - int parent = pStudioHdr->boneParent( iBone ); - if (parent == -1) - { - ConcatTransforms( rootxform, bonematrix, pBoneToWorld[iBone] ); - } - else - { - // evil recursive!!! - BuildBoneChain( pStudioHdr, rootxform, pos, q, parent, pBoneToWorld, boneComputed ); - ConcatTransforms( pBoneToWorld[parent], bonematrix, pBoneToWorld[iBone]); - } - boneComputed.MarkBone(iBone); -} - - -//----------------------------------------------------------------------------- -// Purpose: turn a specific bones boneToWorld transform into a pos and q in parents bonespace -//----------------------------------------------------------------------------- -void SolveBone( - const CStudioHdr *pStudioHdr, - int iBone, - matrix3x4_t *pBoneToWorld, - Vector pos[], - Quaternion q[] - ) -{ - int iParent = pStudioHdr->boneParent( iBone ); - - matrix3x4_t worldToBone; - MatrixInvert( pBoneToWorld[iParent], worldToBone ); - - matrix3x4_t local; - ConcatTransforms( worldToBone, pBoneToWorld[iBone], local ); - - MatrixAngles( local, q[iBone], pos[iBone] ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -void CIKTarget::SetOwner( int entindex, const Vector &pos, const QAngle &angles ) -{ - latched.owner = entindex; - latched.absOrigin = pos; - latched.absAngles = angles; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -void CIKTarget::ClearOwner( void ) -{ - latched.owner = -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -int CIKTarget::GetOwner( void ) -{ - return latched.owner; -} - -//----------------------------------------------------------------------------- -// Purpose: update the latched IK values that are in a moving frame of reference -//----------------------------------------------------------------------------- - -void CIKTarget::UpdateOwner( int entindex, const Vector &pos, const QAngle &angles ) -{ - if (pos == latched.absOrigin && angles == latched.absAngles) - return; - - matrix3x4_t in, out; - AngleMatrix( angles, pos, in ); - AngleIMatrix( latched.absAngles, latched.absOrigin, out ); - - matrix3x4_t tmp1, tmp2; - QuaternionMatrix( latched.q, latched.pos, tmp1 ); - ConcatTransforms( out, tmp1, tmp2 ); - ConcatTransforms( in, tmp2, tmp1 ); - MatrixAngles( tmp1, latched.q, latched.pos ); -} - - -//----------------------------------------------------------------------------- -// Purpose: sets the ground position of an ik target -//----------------------------------------------------------------------------- - -void CIKTarget::SetPos( const Vector &pos ) -{ - est.pos = pos; -} - -//----------------------------------------------------------------------------- -// Purpose: sets the ground "identity" orientation of an ik target -//----------------------------------------------------------------------------- - -void CIKTarget::SetAngles( const QAngle &angles ) -{ - AngleQuaternion( angles, est.q ); -} - -//----------------------------------------------------------------------------- -// Purpose: sets the ground "identity" orientation of an ik target -//----------------------------------------------------------------------------- - -void CIKTarget::SetQuaternion( const Quaternion &q ) -{ - est.q = q; -} - -//----------------------------------------------------------------------------- -// Purpose: calculates a ground "identity" orientation based on the surface -// normal of the ground and the desired ground identity orientation -//----------------------------------------------------------------------------- - -void CIKTarget::SetNormal( const Vector &normal ) -{ - // recalculate foot angle based on slope of surface - matrix3x4_t m1; - Vector forward, right; - QuaternionMatrix( est.q, m1 ); - - MatrixGetColumn( m1, 1, right ); - forward = CrossProduct( right, normal ); - right = CrossProduct( normal, forward ); - MatrixSetColumn( forward, 0, m1 ); - MatrixSetColumn( right, 1, m1 ); - MatrixSetColumn( normal, 2, m1 ); - QAngle a1; - Vector p1; - MatrixAngles( m1, est.q, p1 ); -} - - -//----------------------------------------------------------------------------- -// Purpose: estimates the ground impact at the center location assuming a the edge of -// an Z axis aligned disc collided with it the surface. -//----------------------------------------------------------------------------- - -void CIKTarget::SetPosWithNormalOffset( const Vector &pos, const Vector &normal ) -{ - // assume it's a disc edge intersecting with the floor, so try to estimate the z location of the center - est.pos = pos; - if (normal.z > 0.9999) - { - return; - } - // clamp at 45 degrees - else if (normal.z > 0.707) - { - // tan == sin / cos - float tan = sqrt( 1 - normal.z * normal.z ) / normal.z; - est.pos.z = est.pos.z - est.radius * tan; - } - else - { - est.pos.z = est.pos.z - est.radius; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -void CIKTarget::SetOnWorld( bool bOnWorld ) -{ - est.onWorld = bOnWorld; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -bool CIKTarget::IsActive() -{ - return (est.flWeight > 0.0f); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -void CIKTarget::IKFailed( void ) -{ - latched.deltaPos.Init(); - latched.deltaQ.Init(); - latched.pos = ideal.pos; - latched.q = ideal.q; - est.latched = 0.0; - est.flWeight = 0.0; - est.onWorld = false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -void CIKTarget::MoveReferenceFrame( Vector &deltaPos, QAngle &deltaAngles ) -{ - est.pos -= deltaPos; - latched.pos -= deltaPos; - offset.pos -= deltaPos; - ideal.pos -= deltaPos; -} - - - -//----------------------------------------------------------------------------- -// Purpose: Invalidate any IK locks. -//----------------------------------------------------------------------------- - -void CIKContext::ClearTargets( void ) -{ - int i; - for (i = 0; i < m_target.Count(); i++) - { - m_target[i].latched.iFramecounter = -9999; - } -} - -//----------------------------------------------------------------------------- -// Purpose: Run through the rules that survived and turn a specific bones boneToWorld -// transform into a pos and q in parents bonespace -//----------------------------------------------------------------------------- - -void CIKContext::UpdateTargets( Vector pos[], Quaternion q[], matrix3x4_t boneToWorld[], CBoneBitList &boneComputed ) -{ - int i, j; - - for (i = 0; i < m_target.Count(); i++) - { - m_target[i].est.flWeight = 0.0f; - m_target[i].est.latched = 1.0f; - m_target[i].est.release = 1.0f; - m_target[i].est.height = 0.0f; - m_target[i].est.floor = 0.0f; - m_target[i].est.radius = 0.0f; - m_target[i].offset.pos.Init(); - m_target[i].offset.q.Init(); - } - - AutoIKRelease( ); - - for (j = 0; j < m_ikChainRule.Count(); j++) - { - for (i = 0; i < m_ikChainRule.Element( j ).Count(); i++) - { - ikcontextikrule_t *pRule = &m_ikChainRule.Element( j ).Element( i ); - - // ikchainresult_t *pChainRule = &chainRule[ m_ikRule[i].chain ]; - - switch( pRule->type ) - { - case IK_ATTACHMENT: - case IK_GROUND: - // case IK_SELF: - { - matrix3x4_t footTarget; - CIKTarget *pTarget = &m_target[pRule->slot]; - pTarget->chain = pRule->chain; - pTarget->type = pRule->type; - - if (pRule->type == IK_ATTACHMENT) - { - pTarget->offset.pAttachmentName = pRule->szLabel; - } - else - { - pTarget->offset.pAttachmentName = NULL; - } - - if (pRule->flRuleWeight == 1.0f || pTarget->est.flWeight == 0.0f) - { - pTarget->offset.q = pRule->q; - pTarget->offset.pos = pRule->pos; - pTarget->est.height = pRule->height; - pTarget->est.floor = pRule->floor; - pTarget->est.radius = pRule->radius; - pTarget->est.latched = pRule->latched * pRule->flRuleWeight; - pTarget->est.release = pRule->release; - pTarget->est.flWeight = pRule->flWeight * pRule->flRuleWeight; - } - else - { - QuaternionSlerp( pTarget->offset.q, pRule->q, pRule->flRuleWeight, pTarget->offset.q ); - pTarget->offset.pos = Lerp( pRule->flRuleWeight, pTarget->offset.pos, pRule->pos ); - pTarget->est.height = Lerp( pRule->flRuleWeight, pTarget->est.height, pRule->height ); - pTarget->est.floor = Lerp( pRule->flRuleWeight, pTarget->est.floor, pRule->floor ); - pTarget->est.radius = Lerp( pRule->flRuleWeight, pTarget->est.radius, pRule->radius ); - //pTarget->est.latched = Lerp( pRule->flRuleWeight, pTarget->est.latched, pRule->latched ); - pTarget->est.latched = MIN( pTarget->est.latched, pRule->latched ); - pTarget->est.release = Lerp( pRule->flRuleWeight, pTarget->est.release, pRule->release ); - pTarget->est.flWeight = Lerp( pRule->flRuleWeight, pTarget->est.flWeight, pRule->flWeight ); - } - - if ( pRule->type == IK_GROUND ) - { - pTarget->latched.deltaPos.z = 0; - pTarget->est.pos.z = pTarget->est.floor + m_rootxform[2][3]; - } - } - break; - case IK_UNLATCH: - { - CIKTarget *pTarget = &m_target[pRule->slot]; - if (pRule->latched > 0.0) - pTarget->est.latched = 0.0; - else - pTarget->est.latched = MIN( pTarget->est.latched, 1.0f - pRule->flWeight ); - } - break; - case IK_RELEASE: - { - CIKTarget *pTarget = &m_target[pRule->slot]; - if (pRule->latched > 0.0) - pTarget->est.latched = 0.0; - else - pTarget->est.latched = MIN( pTarget->est.latched, 1.0f - pRule->flWeight ); - - pTarget->est.flWeight = (pTarget->est.flWeight) * (1 - pRule->flWeight * pRule->flRuleWeight); - } - break; - } - } - } - - for (i = 0; i < m_target.Count(); i++) - { - CIKTarget *pTarget = &m_target[i]; - if (pTarget->est.flWeight > 0.0) - { - mstudioikchain_t *pchain = m_pStudioHdr->pIKChain( pTarget->chain ); - // ikchainresult_t *pChainRule = &chainRule[ i ]; - int bone = pchain->pLink( 2 )->bone; - - // eval current ik'd bone - BuildBoneChain( pos, q, bone, boneToWorld, boneComputed ); - - // xform IK target error into world space - matrix3x4_t local; - matrix3x4_t worldFootpad; - QuaternionMatrix( pTarget->offset.q, pTarget->offset.pos, local ); - MatrixInvert( local, local ); - ConcatTransforms( boneToWorld[bone], local, worldFootpad ); - - if (pTarget->est.latched == 1.0) - { - pTarget->latched.bNeedsLatch = true; - } - else - { - pTarget->latched.bNeedsLatch = false; - } - - // disable latched position if it looks invalid - if (m_iFramecounter < 0 || pTarget->latched.iFramecounter < m_iFramecounter - 1 || pTarget->latched.iFramecounter > m_iFramecounter) - { - pTarget->latched.bHasLatch = false; - pTarget->latched.influence = 0.0; - } - pTarget->latched.iFramecounter = m_iFramecounter; - - // find ideal contact position - MatrixAngles( worldFootpad, pTarget->ideal.q, pTarget->ideal.pos ); - pTarget->est.q = pTarget->ideal.q; - pTarget->est.pos = pTarget->ideal.pos; - - float latched = pTarget->est.latched; - - if (pTarget->latched.bHasLatch) - { - if (pTarget->est.latched == 1.0) - { - // keep track of latch position error from ideal contact position - pTarget->latched.deltaPos = pTarget->latched.pos - pTarget->est.pos; - QuaternionSM( -1, pTarget->est.q, pTarget->latched.q, pTarget->latched.deltaQ ); - pTarget->est.q = pTarget->latched.q; - pTarget->est.pos = pTarget->latched.pos; - } - else if (pTarget->est.latched > 0.0) - { - // ramp out latch differences during decay phase of rule - if (latched > 0 && latched < pTarget->latched.influence) - { - // latching has decreased - float dt = pTarget->latched.influence - latched; - if (pTarget->latched.influence > 0.0) - dt = dt / pTarget->latched.influence; - - VectorScale( pTarget->latched.deltaPos, (1-dt), pTarget->latched.deltaPos ); - QuaternionScale( pTarget->latched.deltaQ, (1-dt), pTarget->latched.deltaQ ); - } - - // move ideal contact position by latched error factor - pTarget->est.pos = pTarget->est.pos + pTarget->latched.deltaPos; - QuaternionMA( pTarget->est.q, 1, pTarget->latched.deltaQ, pTarget->est.q ); - pTarget->latched.q = pTarget->est.q; - pTarget->latched.pos = pTarget->est.pos; - } - else - { - pTarget->latched.bHasLatch = false; - pTarget->latched.q = pTarget->est.q; - pTarget->latched.pos = pTarget->est.pos; - pTarget->latched.deltaPos.Init(); - pTarget->latched.deltaQ.Init(); - } - pTarget->latched.influence = latched; - } - - // check for illegal requests - Vector p1, p2, p3; - MatrixPosition( boneToWorld[pchain->pLink( 0 )->bone], p1 ); // hip - MatrixPosition( boneToWorld[pchain->pLink( 1 )->bone], p2 ); // knee - MatrixPosition( boneToWorld[pchain->pLink( 2 )->bone], p3 ); // foot - - float d1 = (p2 - p1).Length(); - float d2 = (p3 - p2).Length(); - - if (pTarget->latched.bHasLatch) - { - //float d3 = (p3 - p1).Length(); - float d4 = (p3 + pTarget->latched.deltaPos - p1).Length(); - - // unstick feet when distance is too great - if ((d4 < fabs( d1 - d2 ) || d4 * 0.95 > d1 + d2) && pTarget->est.latched > 0.2) - { - pTarget->error.flTime = m_flTime; - } - - // unstick feet when angle is too great - if (pTarget->est.latched > 0.2) - { - float d = fabs( pTarget->latched.deltaQ.w ) * 2.0f - 1.0f; // QuaternionDotProduct( pTarget->latched.q, pTarget->est.q ); - - // FIXME: cos(45), make property of chain - if (d < 0.707) - { - pTarget->error.flTime = m_flTime; - } - } - } - - Vector dt = pTarget->est.pos - p1; - pTarget->trace.hipToFoot = VectorNormalize( dt ); - pTarget->trace.hipToKnee = d1; - pTarget->trace.kneeToFoot = d2; - pTarget->trace.hip = p1; - pTarget->trace.knee = p2; - pTarget->trace.closest = p1 + dt * (fabs( d1 - d2 ) * 1.01); - pTarget->trace.farthest = p1 + dt * (d1 + d2) * 0.99; - pTarget->trace.lowest = p1 + Vector( 0, 0, -1 ) * (d1 + d2) * 0.99; - // pTarget->trace.endpos = pTarget->est.pos; - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: insert release rules if the ik rules were in error -//----------------------------------------------------------------------------- - -void CIKContext::AutoIKRelease( void ) -{ - int i; - - for (i = 0; i < m_target.Count(); i++) - { - CIKTarget *pTarget = &m_target[i]; - - float dt = m_flTime - pTarget->error.flTime; - if (pTarget->error.bInError || dt < 0.5) - { - if (!pTarget->error.bInError) - { - pTarget->error.ramp = 0.0; - pTarget->error.flErrorTime = pTarget->error.flTime; - pTarget->error.bInError = true; - } - - float ft = m_flTime - pTarget->error.flErrorTime; - if (dt < 0.25) - { - pTarget->error.ramp = MIN( pTarget->error.ramp + ft * 4.0, 1.0 ); - } - else - { - pTarget->error.ramp = MAX( pTarget->error.ramp - ft * 4.0, 0.0 ); - } - if (pTarget->error.ramp > 0.0) - { - ikcontextikrule_t ikrule; - - ikrule.index = -1; - ikrule.chain = pTarget->chain; - ikrule.bone = 0; - ikrule.type = IK_RELEASE; - ikrule.slot = i; - ikrule.height = 0.0f; - ikrule.radius = 0.0f; - ikrule.floor = 0.0f; - ikrule.pos = Vector(0.0f, 0.0f, 0.0f); - ikrule.q = Quaternion(0.0f, 0.0f, 0.0f, 0.0f); - ikrule.start = 0.0f; - ikrule.peak = 0.0f; - ikrule.tail = 0.0f; - ikrule.end = 0.0f; - ikrule.top = 0.0f; - ikrule.drop = 0.0f; - ikrule.commit = 0.0f; - ikrule.release = 0.0f; - ikrule.flWeight = SimpleSpline( pTarget->error.ramp ); - ikrule.flRuleWeight = 1.0; - ikrule.latched = dt < 0.25 ? 0.0 : ikrule.flWeight; - ikrule.szLabel = NULL; - ikrule.kneeDir = Vector(0.0f, 0.0f, 0.0f); - ikrule.kneePos = Vector(0.0f, 0.0f, 0.0f); - - // don't bother with AutoIKRelease if the bone isn't going to be calculated - // this code is crashing for some unknown reason. - if ( pTarget->chain >= 0 && pTarget->chain < m_pStudioHdr->numikchains()) - { - mstudioikchain_t *pchain = m_pStudioHdr->pIKChain( pTarget->chain ); - if (pchain != NULL) - { - int bone = pchain->pLink( 2 )->bone; - if (bone >= 0 && bone < m_pStudioHdr->numbones()) - { - mstudiobone_t *pBone = m_pStudioHdr->pBone( bone ); - if (pBone != NULL) - { - if ( !(m_pStudioHdr->boneFlags( bone ) & m_boneMask)) - { - pTarget->error.bInError = false; - continue; - } - /* - char buf[256]; - sprintf( buf, "dt %.4f ft %.4f weight %.4f latched %.4f\n", dt, ft, ikrule.flWeight, ikrule.latched ); - OutputDebugString( buf ); - */ - - int nIndex = m_ikChainRule.Element( ikrule.chain ).AddToTail( ); - m_ikChainRule.Element( ikrule.chain ).Element( nIndex ) = ikrule; - } - else - { - DevWarning( 1, "AutoIKRelease (%s) got a NULL pBone %d\n", m_pStudioHdr->name(), bone ); - } - } - else - { - DevWarning( 1, "AutoIKRelease (%s) got an out of range bone %d (%d)\n", m_pStudioHdr->name(), bone, m_pStudioHdr->numbones() ); - } - } - else - { - DevWarning( 1, "AutoIKRelease (%s) got a NULL pchain %d\n", m_pStudioHdr->name(), pTarget->chain ); - } - } - else - { - DevWarning( 1, "AutoIKRelease (%s) got an out of range chain %d (%d)\n", m_pStudioHdr->name(), pTarget->chain, m_pStudioHdr->numikchains()); - } - } - else - { - pTarget->error.bInError = false; - } - pTarget->error.flErrorTime = m_flTime; - } - } -} - - - -void CIKContext::SolveDependencies( Vector pos[], Quaternion q[], matrix3x4_t boneToWorld[], CBoneBitList &boneComputed ) -{ -// ASSERT_NO_REENTRY(); - - matrix3x4_t worldTarget; - int i, j; - - ikchainresult_t chainResult[32]; // allocate!!! - - // init chain rules - for (i = 0; i < m_pStudioHdr->numikchains(); i++) - { - mstudioikchain_t *pchain = m_pStudioHdr->pIKChain( i ); - ikchainresult_t *pChainResult = &chainResult[ i ]; - int bone = pchain->pLink( 2 )->bone; - - pChainResult->target = -1; - pChainResult->flWeight = 0.0; - - // don't bother with chain if the bone isn't going to be calculated - if ( !(m_pStudioHdr->boneFlags( bone ) & m_boneMask)) - continue; - - // eval current ik'd bone - BuildBoneChain( pos, q, bone, boneToWorld, boneComputed ); - - MatrixAngles( boneToWorld[bone], pChainResult->q, pChainResult->pos ); - } - - for (j = 0; j < m_ikChainRule.Count(); j++) - { - for (i = 0; i < m_ikChainRule.Element( j ).Count(); i++) - { - ikcontextikrule_t *pRule = &m_ikChainRule.Element( j ).Element( i ); - ikchainresult_t *pChainResult = &chainResult[ pRule->chain ]; - pChainResult->target = -1; - - - switch( pRule->type ) - { - case IK_SELF: - { - // xform IK target error into world space - matrix3x4_t local; - QuaternionMatrix( pRule->q, pRule->pos, local ); - // eval target bone space - if (pRule->bone != -1) - { - BuildBoneChain( pos, q, pRule->bone, boneToWorld, boneComputed ); - ConcatTransforms( boneToWorld[pRule->bone], local, worldTarget ); - } - else - { - ConcatTransforms( m_rootxform, local, worldTarget ); - } - - float flWeight = pRule->flWeight * pRule->flRuleWeight; - pChainResult->flWeight = pChainResult->flWeight * (1 - flWeight) + flWeight; - - Vector p2; - Quaternion q2; - - // target p and q - MatrixAngles( worldTarget, q2, p2 ); - - // debugLine( pChainResult->pos, p2, 0, 0, 255, true, 0.1 ); - - // blend in position and angles - pChainResult->pos = pChainResult->pos * (1.0 - flWeight) + p2 * flWeight; - QuaternionSlerp( pChainResult->q, q2, flWeight, pChainResult->q ); - } - break; - case IK_WORLD: - Assert( 0 ); - break; - - case IK_ATTACHMENT: - break; - - case IK_GROUND: - break; - - case IK_RELEASE: - { - // move target back towards original location - float flWeight = pRule->flWeight * pRule->flRuleWeight; - mstudioikchain_t *pchain = m_pStudioHdr->pIKChain( pRule->chain ); - int bone = pchain->pLink( 2 )->bone; - - Vector p2; - Quaternion q2; - - BuildBoneChain( pos, q, bone, boneToWorld, boneComputed ); - MatrixAngles( boneToWorld[bone], q2, p2 ); - - // blend in position and angles - pChainResult->pos = pChainResult->pos * (1.0 - flWeight) + p2 * flWeight; - QuaternionSlerp( pChainResult->q, q2, flWeight, pChainResult->q ); - } - break; - case IK_UNLATCH: - { - /* - pChainResult->flWeight = pChainResult->flWeight * (1 - pRule->flWeight) + pRule->flWeight; - - pChainResult->pos = pChainResult->pos * (1.0 - pRule->flWeight ) + pChainResult->local.pos * pRule->flWeight; - QuaternionSlerp( pChainResult->q, pChainResult->local.q, pRule->flWeight, pChainResult->q ); - */ - } - break; - } - } - } - - for (i = 0; i < m_target.Count(); i++) - { - CIKTarget *pTarget = &m_target[i]; - - if (m_target[i].est.flWeight > 0.0) - { - matrix3x4_t worldFootpad; - matrix3x4_t local; - //mstudioikchain_t *pchain = m_pStudioHdr->pIKChain( m_target[i].chain ); - ikchainresult_t *pChainResult = &chainResult[ pTarget->chain ]; - - AngleMatrix(pTarget->offset.q, pTarget->offset.pos, local ); - - AngleMatrix( pTarget->est.q, pTarget->est.pos, worldFootpad ); - - ConcatTransforms( worldFootpad, local, worldTarget ); - - Vector p2; - Quaternion q2; - // target p and q - MatrixAngles( worldTarget, q2, p2 ); - // MatrixAngles( worldTarget, pChainResult->q, pChainResult->pos ); - - // blend in position and angles - pChainResult->flWeight = pTarget->est.flWeight; - pChainResult->pos = pChainResult->pos * (1.0 - pChainResult->flWeight ) + p2 * pChainResult->flWeight; - QuaternionSlerp( pChainResult->q, q2, pChainResult->flWeight, pChainResult->q ); - } - - if (pTarget->latched.bNeedsLatch) - { - // keep track of latch position - pTarget->latched.bHasLatch = true; - pTarget->latched.q = pTarget->est.q; - pTarget->latched.pos = pTarget->est.pos; - } - } - - for (i = 0; i < m_pStudioHdr->numikchains(); i++) - { - ikchainresult_t *pChainResult = &chainResult[ i ]; - mstudioikchain_t *pchain = m_pStudioHdr->pIKChain( i ); - - if (pChainResult->flWeight > 0.0) - { - Vector tmp; - MatrixPosition( boneToWorld[pchain->pLink( 2 )->bone], tmp ); - // debugLine( pChainResult->pos, tmp, 255, 255, 255, true, 0.1 ); - - // do exact IK solution - // FIXME: once per link! - if (Studio_SolveIK(pchain, pChainResult->pos, boneToWorld )) - { - Vector p3; - MatrixGetColumn( boneToWorld[pchain->pLink( 2 )->bone], 3, p3 ); - QuaternionMatrix( pChainResult->q, p3, boneToWorld[pchain->pLink( 2 )->bone] ); - - // rebuild chain - // FIXME: is this needed if everyone past this uses the boneToWorld array? - SolveBone( m_pStudioHdr, pchain->pLink( 2 )->bone, boneToWorld, pos, q ); - SolveBone( m_pStudioHdr, pchain->pLink( 1 )->bone, boneToWorld, pos, q ); - SolveBone( m_pStudioHdr, pchain->pLink( 0 )->bone, boneToWorld, pos, q ); - } - else - { - // FIXME: need to invalidate the targets that forced this... - if (pChainResult->target != -1) - { - CIKTarget *pTarget = &m_target[pChainResult->target]; - VectorScale( pTarget->latched.deltaPos, 0.8, pTarget->latched.deltaPos ); - QuaternionScale( pTarget->latched.deltaQ, 0.8, pTarget->latched.deltaQ ); - } - } - } - } - -#if 0 - Vector p1, p2, p3; - Quaternion q1, q2, q3; - - // current p and q - MatrixAngles( boneToWorld[bone], q1, p1 ); - - - // target p and q - MatrixAngles( worldTarget, q2, p2 ); - - // blend in position and angles - p3 = p1 * (1.0 - m_ikRule[i].flWeight ) + p2 * m_ikRule[i].flWeight; - - // do exact IK solution - // FIXME: once per link! - Studio_SolveIK(pchain, p3, boneToWorld ); - - // force angle (bad?) - QuaternionSlerp( q1, q2, m_ikRule[i].flWeight, q3 ); - MatrixGetColumn( boneToWorld[bone], 3, p3 ); - QuaternionMatrix( q3, p3, boneToWorld[bone] ); - - // rebuild chain - SolveBone( m_pStudioHdr, pchain->pLink( 2 )->bone, boneToWorld, pos, q ); - SolveBone( m_pStudioHdr, pchain->pLink( 1 )->bone, boneToWorld, pos, q ); - SolveBone( m_pStudioHdr, pchain->pLink( 0 )->bone, boneToWorld, pos, q ); -#endif -} - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -void CIKContext::SolveAutoplayLocks( - Vector pos[], - Quaternion q[] - ) -{ - matrix3x4_t *boneToWorld = g_MatrixPool.Alloc(); - CBoneBitList boneComputed; - int i; - - for (i = 0; i < m_ikLock.Count(); i++) - { - const mstudioiklock_t &lock = m_pStudioHdr->pIKAutoplayLock( i ); - SolveLock( &lock, i, pos, q, boneToWorld, boneComputed ); - } - g_MatrixPool.Free( boneToWorld ); -} - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -void CIKContext::SolveSequenceLocks( - mstudioseqdesc_t &seqdesc, - Vector pos[], - Quaternion q[] - ) -{ - matrix3x4_t *boneToWorld = g_MatrixPool.Alloc(); - CBoneBitList boneComputed; - int i; - - for (i = 0; i < m_ikLock.Count(); i++) - { - mstudioiklock_t *plock = seqdesc.pIKLock( i ); - SolveLock( plock, i, pos, q, boneToWorld, boneComputed ); - } - g_MatrixPool.Free( boneToWorld ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -void CIKContext::AddAllLocks( Vector pos[], Quaternion q[] ) -{ - // skip all array access if no autoplay locks. - if (m_pStudioHdr->GetNumIKChains() == 0) - { - return; - } - - matrix3x4_t *boneToWorld = g_MatrixPool.Alloc(); - CBoneBitList boneComputed; - - int ikOffset = m_ikLock.AddMultipleToTail( m_pStudioHdr->GetNumIKChains() ); - memset( &m_ikLock[ikOffset], 0, sizeof(ikcontextikrule_t)*m_pStudioHdr->GetNumIKChains() ); - - for (int i = 0; i < m_pStudioHdr->GetNumIKChains(); i++) - { - mstudioikchain_t *pchain = m_pStudioHdr->pIKChain( i ); - int bone = pchain->pLink( 2 )->bone; - - // don't bother with iklock if the bone isn't going to be calculated - if ( !(m_pStudioHdr->boneFlags( bone ) & m_boneMask)) - continue; - - // eval current ik'd bone - BuildBoneChain( pos, q, bone, boneToWorld, boneComputed ); - - ikcontextikrule_t &ikrule = m_ikLock[ i + ikOffset ]; - - ikrule.chain = i; - ikrule.slot = i; - ikrule.type = IK_WORLD; - - MatrixAngles( boneToWorld[bone], ikrule.q, ikrule.pos ); - - // save off current knee direction - if (pchain->pLink(0)->kneeDir.LengthSqr() > 0.0) - { - Vector tmp = pchain->pLink( 0 )->kneeDir; - VectorRotate( pchain->pLink( 0 )->kneeDir, boneToWorld[ pchain->pLink( 0 )->bone ], ikrule.kneeDir ); - MatrixPosition( boneToWorld[ pchain->pLink( 1 )->bone ], ikrule.kneePos ); - } - else - { - ikrule.kneeDir.Init( ); - } - } - g_MatrixPool.Free( boneToWorld ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - - -void CIKContext::SolveAllLocks( - Vector pos[], - Quaternion q[] - ) -{ - matrix3x4_t *boneToWorld = g_MatrixPool.Alloc(); - CBoneBitList boneComputed; - int i; - - mstudioiklock_t lock; - - for (i = 0; i < m_ikLock.Count(); i++) - { - lock.chain = i; - lock.flPosWeight = 1.0; - lock.flLocalQWeight = 0.0; - lock.flags = 0; - - SolveLock( &lock, i, pos, q, boneToWorld, boneComputed ); - } - g_MatrixPool.Free( boneToWorld ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - - -void CIKContext::SolveLock( - const mstudioiklock_t *plock, - int i, - Vector pos[], - Quaternion q[], - matrix3x4_t boneToWorld[], - CBoneBitList &boneComputed - ) -{ - mstudioikchain_t *pchain = m_pStudioHdr->pIKChain( plock->chain ); - int bone = pchain->pLink( 2 )->bone; - - // don't bother with iklock if the bone isn't going to be calculated - if ( !(m_pStudioHdr->boneFlags( bone ) & m_boneMask)) - return; - - // eval current ik'd bone - BuildBoneChain( pos, q, bone, boneToWorld, boneComputed ); - - Vector p1, p2, p3; - Quaternion q2, q3; - - // current p and q - MatrixPosition( boneToWorld[bone], p1 ); - - // blend in position - p3 = p1 * (1.0 - plock->flPosWeight ) + m_ikLock[i].pos * plock->flPosWeight; - - // do exact IK solution - if (m_ikLock[i].kneeDir.LengthSqr() > 0) - { - Studio_SolveIK(pchain->pLink( 0 )->bone, pchain->pLink( 1 )->bone, pchain->pLink( 2 )->bone, p3, m_ikLock[i].kneePos, m_ikLock[i].kneeDir, boneToWorld ); - } - else - { - Studio_SolveIK(pchain, p3, boneToWorld ); - } - - // slam orientation - MatrixPosition( boneToWorld[bone], p3 ); - QuaternionMatrix( m_ikLock[i].q, p3, boneToWorld[bone] ); - - // rebuild chain - q2 = q[ bone ]; - SolveBone( m_pStudioHdr, pchain->pLink( 2 )->bone, boneToWorld, pos, q ); - QuaternionSlerp( q[bone], q2, plock->flLocalQWeight, q[bone] ); - - SolveBone( m_pStudioHdr, pchain->pLink( 1 )->bone, boneToWorld, pos, q ); - SolveBone( m_pStudioHdr, pchain->pLink( 0 )->bone, boneToWorld, pos, q ); -} - - -//----------------------------------------------------------------------------- -// Purpose: run all animations that automatically play and are driven off of poseParameters -//----------------------------------------------------------------------------- -void CalcAutoplaySequences( - const CStudioHdr *pStudioHdr, - CIKContext *pIKContext, - Vector pos[], - Quaternion q[], - const float poseParameters[], - int boneMask, - float realTime - ) -{ -// ASSERT_NO_REENTRY(); - - int i; - if ( pIKContext ) - { - pIKContext->AddAutoplayLocks( pos, q ); - } - - unsigned short *pList = NULL; - int count = pStudioHdr->GetAutoplayList( &pList ); - for (i = 0; i < count; i++) - { - int sequenceIndex = pList[i]; - mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( sequenceIndex ); - if (seqdesc.flags & STUDIO_AUTOPLAY) - { - float cycle = 0; - float cps = Studio_CPS( pStudioHdr, seqdesc, sequenceIndex, poseParameters ); - cycle = realTime * cps; - cycle = cycle - (int)cycle; - - AccumulatePose( pStudioHdr, NULL, pos, q, sequenceIndex, cycle, poseParameters, boneMask, 1.0, realTime ); - } - } - - if ( pIKContext ) - { - pIKContext->SolveAutoplayLocks( pos, q ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void Studio_BuildMatrices( - const CStudioHdr *pStudioHdr, - const QAngle& angles, - const Vector& origin, - const Vector pos[], - const Quaternion q[], - int iBone, - matrix3x4_t bonetoworld[MAXSTUDIOBONES], - int boneMask - ) -{ - int i, j; - - int chain[MAXSTUDIOBONES]; - int chainlength = 0; - - if (iBone < -1 || iBone >= pStudioHdr->numbones()) - iBone = 0; - - // build list of what bones to use - if (iBone == -1) - { - // all bones - chainlength = pStudioHdr->numbones(); - for (i = 0; i < pStudioHdr->numbones(); i++) - { - chain[chainlength - i - 1] = i; - } - } - else - { - // only the parent bones - i = iBone; - while (i != -1) - { - chain[chainlength++] = i; - i = pStudioHdr->boneParent( i ); - } - } - - matrix3x4_t bonematrix; - matrix3x4_t rotationmatrix; // model to world transformation - AngleMatrix( angles, origin, rotationmatrix); - - for (j = chainlength - 1; j >= 0; j--) - { - i = chain[j]; - if (pStudioHdr->boneFlags(i) & boneMask) - { - QuaternionMatrix( q[i], pos[i], bonematrix ); - - if (pStudioHdr->boneParent(i) == -1) - { - ConcatTransforms (rotationmatrix, bonematrix, bonetoworld[i]); - } - else - { - ConcatTransforms (bonetoworld[pStudioHdr->boneParent(i)], bonematrix, bonetoworld[i]); - } - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: look at single column vector of another bones local transformation -// and generate a procedural transformation based on how that column -// points down the 6 cardinal axis (all negative weights are clamped to 0). -//----------------------------------------------------------------------------- - -void DoAxisInterpBone( - mstudiobone_t *pbones, - int ibone, - CBoneAccessor &bonetoworld - ) -{ - matrix3x4_t bonematrix; - Vector control; - - mstudioaxisinterpbone_t *pProc = (mstudioaxisinterpbone_t *)pbones[ibone].pProcedure( ); - const matrix3x4_t &controlBone = bonetoworld.GetBone( pProc->control ); - if (pProc && pbones[pProc->control].parent != -1) - { - Vector tmp; - // pull out the control column - tmp.x = controlBone[0][pProc->axis]; - tmp.y = controlBone[1][pProc->axis]; - tmp.z = controlBone[2][pProc->axis]; - - // invert it back into parent's space. - VectorIRotate( tmp, bonetoworld.GetBone( pbones[pProc->control].parent ), control ); -#if 0 - matrix3x4_t tmpmatrix; - matrix3x4_t controlmatrix; - MatrixInvert( bonetoworld.GetBone( pbones[pProc->control].parent ), tmpmatrix ); - ConcatTransforms( tmpmatrix, bonetoworld.GetBone( pProc->control ), controlmatrix ); - - // pull out the control column - control.x = controlmatrix[0][pProc->axis]; - control.y = controlmatrix[1][pProc->axis]; - control.z = controlmatrix[2][pProc->axis]; -#endif - } - else - { - // pull out the control column - control.x = controlBone[0][pProc->axis]; - control.y = controlBone[1][pProc->axis]; - control.z = controlBone[2][pProc->axis]; - } - - Quaternion *q1, *q2, *q3; - Vector *p1, *p2, *p3; - - // find axial control inputs - float a1 = control.x; - float a2 = control.y; - float a3 = control.z; - if (a1 >= 0) - { - q1 = &pProc->quat[0]; - p1 = &pProc->pos[0]; - } - else - { - a1 = -a1; - q1 = &pProc->quat[1]; - p1 = &pProc->pos[1]; - } - - if (a2 >= 0) - { - q2 = &pProc->quat[2]; - p2 = &pProc->pos[2]; - } - else - { - a2 = -a2; - q2 = &pProc->quat[3]; - p2 = &pProc->pos[3]; - } - - if (a3 >= 0) - { - q3 = &pProc->quat[4]; - p3 = &pProc->pos[4]; - } - else - { - a3 = -a3; - q3 = &pProc->quat[5]; - p3 = &pProc->pos[5]; - } - - // do a three-way blend - Vector p; - Quaternion v, tmp; - if (a1 + a2 > 0) - { - float t = 1.0 / (a1 + a2 + a3); - // FIXME: do a proper 3-way Quat blend! - QuaternionSlerp( *q2, *q1, a1 / (a1 + a2), tmp ); - QuaternionSlerp( tmp, *q3, a3 * t, v ); - VectorScale( *p1, a1 * t, p ); - VectorMA( p, a2 * t, *p2, p ); - VectorMA( p, a3 * t, *p3, p ); - } - else - { - QuaternionSlerp( *q3, *q3, 0, v ); // ??? no quat copy? - p = *p3; - } - - QuaternionMatrix( v, p, bonematrix ); - - ConcatTransforms (bonetoworld.GetBone( pbones[ibone].parent ), bonematrix, bonetoworld.GetBoneForWrite( ibone )); -} - - - -//----------------------------------------------------------------------------- -// Purpose: Generate a procedural transformation based on how that another bones -// local transformation matches a set of target orientations. -//----------------------------------------------------------------------------- -void DoQuatInterpBone( - mstudiobone_t *pbones, - int ibone, - CBoneAccessor &bonetoworld - ) -{ - matrix3x4_t bonematrix; - Vector control; - - mstudioquatinterpbone_t *pProc = (mstudioquatinterpbone_t *)pbones[ibone].pProcedure( ); - if (pProc && pbones[pProc->control].parent != -1) - { - Quaternion src; - float weight[32]; - float scale = 0.0; - Quaternion quat; - Vector pos; - - matrix3x4_t tmpmatrix; - matrix3x4_t controlmatrix; - MatrixInvert( bonetoworld.GetBone( pbones[pProc->control].parent), tmpmatrix ); - ConcatTransforms( tmpmatrix, bonetoworld.GetBone( pProc->control ), controlmatrix ); - - MatrixAngles( controlmatrix, src, pos ); // FIXME: make a version without pos - - int i; - for (i = 0; i < pProc->numtriggers; i++) - { - float dot = fabs( QuaternionDotProduct( pProc->pTrigger( i )->trigger, src ) ); - // FIXME: a fast acos should be acceptable - dot = clamp( dot, -1, 1 ); - weight[i] = 1 - (2 * acos( dot ) * pProc->pTrigger( i )->inv_tolerance ); - weight[i] = MAX( 0, weight[i] ); - scale += weight[i]; - } - - if (scale <= 0.001) // EPSILON? - { - AngleMatrix( pProc->pTrigger( 0 )->quat, pProc->pTrigger( 0 )->pos, bonematrix ); - ConcatTransforms ( bonetoworld.GetBone( pbones[ibone].parent ), bonematrix, bonetoworld.GetBoneForWrite( ibone ) ); - return; - } - - scale = 1.0 / scale; - - quat.Init( 0, 0, 0, 0); - pos.Init( ); - - for (i = 0; i < pProc->numtriggers; i++) - { - if (weight[i]) - { - float s = weight[i] * scale; - mstudioquatinterpinfo_t *pTrigger = pProc->pTrigger( i ); - - QuaternionAlign( pTrigger->quat, quat, quat ); - - quat.x = quat.x + s * pTrigger->quat.x; - quat.y = quat.y + s * pTrigger->quat.y; - quat.z = quat.z + s * pTrigger->quat.z; - quat.w = quat.w + s * pTrigger->quat.w; - pos.x = pos.x + s * pTrigger->pos.x; - pos.y = pos.y + s * pTrigger->pos.y; - pos.z = pos.z + s * pTrigger->pos.z; - } - } - Assert( QuaternionNormalize( quat ) != 0); - QuaternionMatrix( quat, pos, bonematrix ); - } - - ConcatTransforms (bonetoworld.GetBone( pbones[ibone].parent ), bonematrix, bonetoworld.GetBoneForWrite( ibone )); -} - -/* - * This is for DoAimAtBone below, was just for testing, not needed in general - * but to turn it back on, uncomment this and the section in DoAimAtBone() below - * - -static ConVar aim_constraint( "aim_constraint", "1", FCVAR_REPLICATED, "Toggle Helper Bones" ); - -*/ - -//----------------------------------------------------------------------------- -// Purpose: Generate a procedural transformation so that one bone points at -// another point on the model -//----------------------------------------------------------------------------- -void DoAimAtBone( - mstudiobone_t *pBones, - int iBone, - CBoneAccessor &bonetoworld, - const CStudioHdr *pStudioHdr - ) -{ - mstudioaimatbone_t *pProc = (mstudioaimatbone_t *)pBones[iBone].pProcedure(); - - if ( !pProc ) - { - return; - } - - /* - * Uncomment this if the ConVar above is uncommented - * - - if ( !aim_constraint.GetBool() ) - { - // If the aim constraint is turned off then just copy the parent transform - // plus the offset value - - matrix3x4_t boneToWorldSpace; - MatrixCopy ( bonetoworld.GetBone( pProc->parent ), boneToWorldSpace ); - Vector boneWorldPosition; - VectorTransform( pProc->basepos, boneToWorldSpace, boneWorldPosition ); - MatrixSetColumn( boneWorldPosition, 3, boneToWorldSpace ); - MatrixCopy( boneToWorldSpace, bonetoworld.GetBoneForWrite( iBone ) ); - - return; - } - - */ - - // The world matrix of the bone to change - matrix3x4_t boneMatrix; - - // Guaranteed to be unit length - const Vector &userAimVector( pProc->aimvector ); - - // Guaranteed to be unit length - const Vector &userUpVector( pProc->upvector ); - - // Get to get position of bone but also for up reference - matrix3x4_t parentSpace; - MatrixCopy ( bonetoworld.GetBone( pProc->parent ), parentSpace ); - - // World space position of the bone to aim - Vector aimWorldPosition; - VectorTransform( pProc->basepos, parentSpace, aimWorldPosition ); - - // The worldspace matrix of the bone to aim at - matrix3x4_t aimAtSpace; - if ( pStudioHdr ) - { - // This means it's AIMATATTACH - const mstudioattachment_t &attachment( pStudioHdr->pAttachment( pProc->aim ) ); - ConcatTransforms( - bonetoworld.GetBone( attachment.localbone ), - attachment.local, - aimAtSpace ); - } - else - { - MatrixCopy( bonetoworld.GetBone( pProc->aim ), aimAtSpace ); - } - - Vector aimAtWorldPosition; - MatrixGetColumn( aimAtSpace, 3, aimAtWorldPosition ); - - // make sure the redundant parent info is correct - Assert( pProc->parent == pBones[iBone].parent ); - // make sure the redundant position info is correct - Assert( pProc->basepos.DistToSqr( pBones[iBone].pos ) < 0.1 ); - - // The aim and up data is relative to this bone, not the parent bone - matrix3x4_t bonematrix, boneLocalToWorld; - AngleMatrix( pBones[iBone].quat, pProc->basepos, bonematrix ); - ConcatTransforms( bonetoworld.GetBone( pProc->parent ), bonematrix, boneLocalToWorld ); - - Vector aimVector; - VectorSubtract( aimAtWorldPosition, aimWorldPosition, aimVector ); - VectorNormalizeFast( aimVector ); - - Vector axis; - CrossProduct( userAimVector, aimVector, axis ); - VectorNormalizeFast( axis ); - Assert( 1.0f - fabs( DotProduct( userAimVector, aimVector ) ) > FLT_EPSILON ); - float angle( acosf( DotProduct( userAimVector, aimVector ) ) ); - Quaternion aimRotation; - AxisAngleQuaternion( axis, RAD2DEG( angle ), aimRotation ); - - if ( ( 1.0f - fabs( DotProduct( userUpVector, userAimVector ) ) ) > FLT_EPSILON ) - { - matrix3x4_t aimRotationMatrix; - QuaternionMatrix( aimRotation, aimRotationMatrix ); - - Vector tmpV; - - Vector tmp_pUp; - VectorRotate( userUpVector, aimRotationMatrix, tmp_pUp ); - VectorScale( aimVector, DotProduct( aimVector, tmp_pUp ), tmpV ); - Vector pUp; - VectorSubtract( tmp_pUp, tmpV, pUp ); - VectorNormalizeFast( pUp ); - - Vector tmp_pParentUp; - VectorRotate( userUpVector, boneLocalToWorld, tmp_pParentUp ); - VectorScale( aimVector, DotProduct( aimVector, tmp_pParentUp ), tmpV ); - Vector pParentUp; - VectorSubtract( tmp_pParentUp, tmpV, pParentUp ); - VectorNormalizeFast( pParentUp ); - - Quaternion upRotation; - //Assert( 1.0f - fabs( DotProduct( pUp, pParentUp ) ) > FLT_EPSILON ); - if( 1.0f - fabs( DotProduct( pUp, pParentUp ) ) > FLT_EPSILON ) - { - angle = acos( DotProduct( pUp, pParentUp ) ); - CrossProduct( pUp, pParentUp, axis ); - } - else - { - angle = 0; - axis = pUp; - } - - VectorNormalizeFast( axis ); - AxisAngleQuaternion( axis, RAD2DEG( angle ), upRotation ); - - Quaternion boneRotation; - QuaternionMult( upRotation, aimRotation, boneRotation ); - QuaternionMatrix( boneRotation, aimWorldPosition, boneMatrix ); - } - else - { - QuaternionMatrix( aimRotation, aimWorldPosition, boneMatrix ); - } - - MatrixCopy( boneMatrix, bonetoworld.GetBoneForWrite( iBone ) ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -bool CalcProceduralBone( - const CStudioHdr *pStudioHdr, - int iBone, - CBoneAccessor &bonetoworld - ) -{ - mstudiobone_t *pbones = pStudioHdr->pBone( 0 ); - - if ( pStudioHdr->boneFlags(iBone) & BONE_ALWAYS_PROCEDURAL ) - { - switch( pbones[iBone].proctype ) - { - case STUDIO_PROC_AXISINTERP: - DoAxisInterpBone( pbones, iBone, bonetoworld ); - return true; - - case STUDIO_PROC_QUATINTERP: - DoQuatInterpBone( pbones, iBone, bonetoworld ); - return true; - - case STUDIO_PROC_AIMATBONE: - DoAimAtBone( pbones, iBone, bonetoworld, NULL ); - return true; - - case STUDIO_PROC_AIMATATTACH: - DoAimAtBone( pbones, iBone, bonetoworld, pStudioHdr ); - return true; - - default: - return false; - } - } - return false; -} - - - -//----------------------------------------------------------------------------- -// Purpose: Lookup a bone controller -//----------------------------------------------------------------------------- - - - -static mstudiobonecontroller_t* FindController( const CStudioHdr *pStudioHdr, int iController) -{ - // find first controller that matches the index - for (int i = 0; i < pStudioHdr->numbonecontrollers(); i++) - { - if (pStudioHdr->pBonecontroller( i )->inputfield == iController) - return pStudioHdr->pBonecontroller( i ); - } - - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: converts a ranged bone controller value into a 0..1 encoded value -// Output: ctlValue contains 0..1 encoding. -// returns clamped ranged value -//----------------------------------------------------------------------------- - -float Studio_SetController( const CStudioHdr *pStudioHdr, int iController, float flValue, float &ctlValue ) -{ - if (! pStudioHdr) - return flValue; - - mstudiobonecontroller_t *pbonecontroller = FindController(pStudioHdr, iController); - if(!pbonecontroller) - { - ctlValue = 0; - return flValue; - } - - // wrap 0..360 if it's a rotational controller - if (pbonecontroller->type & (STUDIO_XR | STUDIO_YR | STUDIO_ZR)) - { - // ugly hack, invert value if end < start - if (pbonecontroller->end < pbonecontroller->start) - flValue = -flValue; - - // does the controller not wrap? - if (pbonecontroller->start + 359.0 >= pbonecontroller->end) - { - if (flValue > ((pbonecontroller->start + pbonecontroller->end) / 2.0) + 180) - flValue = flValue - 360; - if (flValue < ((pbonecontroller->start + pbonecontroller->end) / 2.0) - 180) - flValue = flValue + 360; - } - else - { - if (flValue > 360) - flValue = flValue - (int)(flValue / 360.0) * 360.0; - else if (flValue < 0) - flValue = flValue + (int)((flValue / -360.0) + 1) * 360.0; - } - } - - ctlValue = (flValue - pbonecontroller->start) / (pbonecontroller->end - pbonecontroller->start); - if (ctlValue < 0) ctlValue = 0; - if (ctlValue > 1) ctlValue = 1; - - float flReturnVal = ((1.0 - ctlValue)*pbonecontroller->start + ctlValue *pbonecontroller->end); - - // ugly hack, invert value if a rotational controller and end < start - if (pbonecontroller->type & (STUDIO_XR | STUDIO_YR | STUDIO_ZR) && - pbonecontroller->end < pbonecontroller->start ) - { - flReturnVal *= -1; - } - - return flReturnVal; -} - - -//----------------------------------------------------------------------------- -// Purpose: converts a 0..1 encoded bone controller value into a ranged value -// Output: returns ranged value -//----------------------------------------------------------------------------- - -float Studio_GetController( const CStudioHdr *pStudioHdr, int iController, float ctlValue ) -{ - if (!pStudioHdr) - return 0.0; - - mstudiobonecontroller_t *pbonecontroller = FindController(pStudioHdr, iController); - if(!pbonecontroller) - return 0; - - return ctlValue * (pbonecontroller->end - pbonecontroller->start) + pbonecontroller->start; -} - - -//----------------------------------------------------------------------------- -// Purpose: converts a ranged pose parameter value into a 0..1 encoded value -// Output: ctlValue contains 0..1 encoding. -// returns clamped ranged value -//----------------------------------------------------------------------------- - -float Studio_SetPoseParameter( const CStudioHdr *pStudioHdr, int iParameter, float flValue, float &ctlValue ) -{ - if (iParameter < 0 || iParameter >= pStudioHdr->GetNumPoseParameters()) - { - return 0; - } - - const mstudioposeparamdesc_t &PoseParam = pStudioHdr->pPoseParameter( iParameter ); - - Assert( IsFinite( flValue ) ); - - if (PoseParam.loop) - { - float wrap = (PoseParam.start + PoseParam.end) / 2.0 + PoseParam.loop / 2.0; - float shift = PoseParam.loop - wrap; - - flValue = flValue - PoseParam.loop * floor((flValue + shift) / PoseParam.loop); - } - - ctlValue = (flValue - PoseParam.start) / (PoseParam.end - PoseParam.start); - - if (ctlValue < 0) ctlValue = 0; - if (ctlValue > 1) ctlValue = 1; - - Assert( IsFinite( ctlValue ) ); - - return ctlValue * (PoseParam.end - PoseParam.start) + PoseParam.start; -} - - -//----------------------------------------------------------------------------- -// Purpose: converts a 0..1 encoded pose parameter value into a ranged value -// Output: returns ranged value -//----------------------------------------------------------------------------- - -float Studio_GetPoseParameter( const CStudioHdr *pStudioHdr, int iParameter, float ctlValue ) -{ - if (iParameter < 0 || iParameter >= pStudioHdr->GetNumPoseParameters()) - { - return 0; - } - - const mstudioposeparamdesc_t &PoseParam = pStudioHdr->pPoseParameter( iParameter ); - - return ctlValue * (PoseParam.end - PoseParam.start) + PoseParam.start; -} - -#ifdef _MSC_VER -#pragma warning (disable : 4701) -#endif - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -static int ClipRayToHitbox( const Ray_t &ray, mstudiobbox_t *pbox, matrix3x4_t& matrix, trace_t &tr ) -{ - // scale by current t so hits shorten the ray and increase the likelihood of early outs - Vector delta2; - VectorScale( ray.m_Delta, (0.5f * tr.fraction), delta2 ); - - // OPTIMIZE: Store this in the box instead of computing it here - // compute center in local space - Vector boxextents; - boxextents.x = (pbox->bbmin.x + pbox->bbmax.x) * 0.5; - boxextents.y = (pbox->bbmin.y + pbox->bbmax.y) * 0.5; - boxextents.z = (pbox->bbmin.z + pbox->bbmax.z) * 0.5; - Vector boxCenter; - // transform to world space - VectorTransform( boxextents, matrix, boxCenter ); - // calc extents from local center - boxextents.x = pbox->bbmax.x - boxextents.x; - boxextents.y = pbox->bbmax.y - boxextents.y; - boxextents.z = pbox->bbmax.z - boxextents.z; - // OPTIMIZE: This is optimized for world space. If the transform is fast enough, it may make more - // sense to just xform and call UTIL_ClipToBox() instead. MEASURE THIS. - - // save the extents of the ray along - Vector extent, uextent; - Vector segmentCenter; - segmentCenter.x = ray.m_Start.x + delta2.x - boxCenter.x; - segmentCenter.y = ray.m_Start.y + delta2.y - boxCenter.y; - segmentCenter.z = ray.m_Start.z + delta2.z - boxCenter.z; - - extent.Init(); - - // check box axes for separation - for ( int j = 0; j < 3; j++ ) - { - extent[j] = delta2.x * matrix[0][j] + delta2.y * matrix[1][j] + delta2.z * matrix[2][j]; - uextent[j] = fabsf(extent[j]); - float coord = segmentCenter.x * matrix[0][j] + segmentCenter.y * matrix[1][j] + segmentCenter.z * matrix[2][j]; - coord = fabsf(coord); - - if ( coord > (boxextents[j] + uextent[j]) ) - return -1; - } - - // now check cross axes for separation - float tmp, cextent; - Vector cross; - CrossProduct( delta2, segmentCenter, cross ); - cextent = cross.x * matrix[0][0] + cross.y * matrix[1][0] + cross.z * matrix[2][0]; - cextent = fabsf(cextent); - tmp = boxextents[1]*uextent[2] + boxextents[2]*uextent[1]; - if ( cextent > tmp ) - return -1; - - cextent = cross.x * matrix[0][1] + cross.y * matrix[1][1] + cross.z * matrix[2][1]; - cextent = fabsf(cextent); - tmp = boxextents[0]*uextent[2] + boxextents[2]*uextent[0]; - if ( cextent > tmp ) - return -1; - - cextent = cross.x * matrix[0][2] + cross.y * matrix[1][2] + cross.z * matrix[2][2]; - cextent = fabsf(cextent); - tmp = boxextents[0]*uextent[1] + boxextents[1]*uextent[0]; - if ( cextent > tmp ) - return -1; - - // !!! We hit this box !!! compute intersection point and return - Vector start; - // Compute ray start in bone space - VectorITransform( ray.m_Start, matrix, start ); - // extent is delta2 in bone space, recompute delta in bone space - VectorScale( extent, 2, extent ); - - // delta was prescaled by the current t, so no need to see if this intersection - // is closer - trace_t boxTrace; - if ( !IntersectRayWithBox( start, extent, pbox->bbmin, pbox->bbmax, 0.0f, &boxTrace ) ) - return -1; - Assert( IsFinite(boxTrace.fraction) ); - tr.fraction *= boxTrace.fraction; - tr.startsolid = boxTrace.startsolid; - int hitside = boxTrace.plane.type; - if ( boxTrace.plane.normal[hitside] >= 0 ) - { - hitside += 3; - } - return hitside; -} - -#ifdef _MSC_VER -#pragma warning (default : 4701) -#endif - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool SweepBoxToStudio( IPhysicsSurfaceProps *pProps, const Ray_t& ray, CStudioHdr *pStudioHdr, mstudiohitboxset_t *set, - matrix3x4_t **hitboxbones, int fContentsMask, trace_t &tr ) -{ - tr.fraction = 1.0; - tr.startsolid = false; - - // OPTIMIZE: Partition these? - Ray_t clippedRay = ray; - int hitbox = -1; - for ( int i = 0; i < set->numhitboxes; i++ ) - { - mstudiobbox_t *pbox = set->pHitbox(i); - - // Filter based on contents mask - int fBoneContents = pStudioHdr->pBone( pbox->bone )->contents; - if ( ( fBoneContents & fContentsMask ) == 0 ) - continue; - - trace_t obbTrace; - if ( IntersectRayWithOBB( clippedRay, *hitboxbones[pbox->bone], pbox->bbmin, pbox->bbmax, 0.0f, &obbTrace ) ) - { - tr.startpos = obbTrace.startpos; - tr.endpos = obbTrace.endpos; - tr.plane = obbTrace.plane; - tr.startsolid = obbTrace.startsolid; - tr.allsolid = obbTrace.allsolid; - - // This logic here is to shorten the ray each time to get more early outs - tr.fraction *= obbTrace.fraction; - clippedRay.m_Delta *= obbTrace.fraction; - hitbox = i; - if (tr.startsolid) - break; - } - } - - if ( hitbox >= 0 ) - { - tr.hitgroup = set->pHitbox(hitbox)->group; - tr.hitbox = hitbox; - const mstudiobone_t *pBone = pStudioHdr->pBone( set->pHitbox(hitbox)->bone ); - tr.contents = pBone->contents | CONTENTS_HITBOX; - tr.physicsbone = pBone->physicsbone; - tr.surface.name = "**studio**"; - tr.surface.flags = SURF_HITBOX; - tr.surface.surfaceProps = pProps->GetSurfaceIndex( pBone->pszSurfaceProp() ); - - Assert( tr.physicsbone >= 0 ); - return true; - } - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool TraceToStudio( IPhysicsSurfaceProps *pProps, const Ray_t& ray, CStudioHdr *pStudioHdr, mstudiohitboxset_t *set, - matrix3x4_t **hitboxbones, int fContentsMask, trace_t &tr ) -{ - if ( !ray.m_IsRay ) - { - return SweepBoxToStudio( pProps, ray, pStudioHdr, set, hitboxbones, fContentsMask, tr ); - } - - tr.fraction = 1.0; - tr.startsolid = false; - - // no hit yet - int hitbox = -1; - int hitside = -1; - - // OPTIMIZE: Partition these? - for ( int i = 0; i < set->numhitboxes; i++ ) - { - mstudiobbox_t *pbox = set->pHitbox(i); - - // Filter based on contents mask - int fBoneContents = pStudioHdr->pBone( pbox->bone )->contents; - if ( ( fBoneContents & fContentsMask ) == 0 ) - continue; - - // columns are axes of the bones in world space, translation is in world space - matrix3x4_t& matrix = *hitboxbones[pbox->bone]; - - int side = ClipRayToHitbox( ray, pbox, matrix, tr ); - if ( side >= 0 ) - { - hitbox = i; - hitside = side; - } - } - - if ( hitbox >= 0 ) - { - mstudiobbox_t *pbox = set->pHitbox(hitbox); - VectorMA( ray.m_Start, tr.fraction, ray.m_Delta, tr.endpos ); - tr.hitgroup = set->pHitbox(hitbox)->group; - tr.hitbox = hitbox; - const mstudiobone_t *pBone = pStudioHdr->pBone( pbox->bone ); - tr.contents = pBone->contents | CONTENTS_HITBOX; - tr.physicsbone = pBone->physicsbone; - tr.surface.name = "**studio**"; - tr.surface.flags = SURF_HITBOX; - tr.surface.surfaceProps = pProps->GetSurfaceIndex( pBone->pszSurfaceProp() ); - - Assert( tr.physicsbone >= 0 ); - matrix3x4_t& matrix = *hitboxbones[pbox->bone]; - if ( hitside >= 3 ) - { - hitside -= 3; - tr.plane.normal[0] = matrix[0][hitside]; - tr.plane.normal[1] = matrix[1][hitside]; - tr.plane.normal[2] = matrix[2][hitside]; - //tr.plane.dist = DotProduct( tr.plane.normal, Vector(matrix[0][3], matrix[1][3], matrix[2][3] ) ) + pbox->bbmax[hitside]; - } - else - { - tr.plane.normal[0] = -matrix[0][hitside]; - tr.plane.normal[1] = -matrix[1][hitside]; - tr.plane.normal[2] = -matrix[2][hitside]; - //tr.plane.dist = DotProduct( tr.plane.normal, Vector(matrix[0][3], matrix[1][3], matrix[2][3] ) ) - pbox->bbmin[hitside]; - } - // simpler plane constant equation - tr.plane.dist = DotProduct( tr.endpos, tr.plane.normal ); - tr.plane.type = 3; - return true; - } - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: returns array of animations and weightings for a sequence based on current pose parameters -//----------------------------------------------------------------------------- - -void Studio_SeqAnims( const CStudioHdr *pStudioHdr, mstudioseqdesc_t &seqdesc, int iSequence, const float poseParameter[], mstudioanimdesc_t *panim[4], float *weight ) -{ -#if _DEBUG - VPROF_INCREMENT_COUNTER("SEQ_ANIMS",1); -#endif - if (!pStudioHdr || iSequence >= pStudioHdr->GetNumSeq()) - { - weight[0] = weight[1] = weight[2] = weight[3] = 0.0; - return; - } - - int i0 = 0, i1 = 0; - float s0 = 0, s1 = 0; - - Studio_LocalPoseParameter( pStudioHdr, poseParameter, seqdesc, iSequence, 0, s0, i0 ); - Studio_LocalPoseParameter( pStudioHdr, poseParameter, seqdesc, iSequence, 1, s1, i1 ); - - panim[0] = &pStudioHdr->pAnimdesc( pStudioHdr->iRelativeAnim( iSequence, seqdesc.anim( i0 , i1 ) ) ); - weight[0] = (1 - s0) * (1 - s1); - - panim[1] = &pStudioHdr->pAnimdesc( pStudioHdr->iRelativeAnim( iSequence, seqdesc.anim( i0+1, i1 ) ) ); - weight[1] = (s0) * (1 - s1); - - panim[2] = &pStudioHdr->pAnimdesc( pStudioHdr->iRelativeAnim( iSequence, seqdesc.anim( i0 , i1+1 ) ) ); - weight[2] = (1 - s0) * (s1); - - panim[3] = &pStudioHdr->pAnimdesc( pStudioHdr->iRelativeAnim( iSequence, seqdesc.anim( i0+1, i1+1 ) ) ); - weight[3] = (s0) * (s1); - - Assert( weight[0] >= 0.0f && weight[1] >= 0.0f && weight[2] >= 0.0f && weight[3] >= 0.0f ); -} - -//----------------------------------------------------------------------------- -// Purpose: returns max frame number for a sequence -//----------------------------------------------------------------------------- - -int Studio_MaxFrame( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[] ) -{ - mstudioanimdesc_t *panim[4]; - float weight[4]; - - mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( iSequence ); - Studio_SeqAnims( pStudioHdr, seqdesc, iSequence, poseParameter, panim, weight ); - - float maxFrame = 0; - for (int i = 0; i < 4; i++) - { - if (weight[i] > 0) - { - maxFrame += panim[i]->numframes * weight[i]; - } - } - - if ( maxFrame > 1 ) - maxFrame -= 1; - - - // FIXME: why does the weights sometimes not exactly add it 1.0 and this sometimes rounds down? - return static_cast(maxFrame + 0.01); -} - - -//----------------------------------------------------------------------------- -// Purpose: returns frames per second of a sequence -//----------------------------------------------------------------------------- - -float Studio_FPS( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[] ) -{ - mstudioanimdesc_t *panim[4]; - float weight[4]; - - mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( iSequence ); - Studio_SeqAnims( pStudioHdr, seqdesc, iSequence, poseParameter, panim, weight ); - - float t = 0; - - for (int i = 0; i < 4; i++) - { - if (weight[i] > 0) - { - t += panim[i]->fps * weight[i]; - } - } - return t; -} - - -//----------------------------------------------------------------------------- -// Purpose: returns cycles per second of a sequence (cycles/second) -//----------------------------------------------------------------------------- - -float Studio_CPS( const CStudioHdr *pStudioHdr, mstudioseqdesc_t &seqdesc, int iSequence, const float poseParameter[] ) -{ - mstudioanimdesc_t *panim[4]; - float weight[4]; - - Studio_SeqAnims( pStudioHdr, seqdesc, iSequence, poseParameter, panim, weight ); - - float t = 0; - - for (int i = 0; i < 4; i++) - { - if (weight[i] > 0 && panim[i]->numframes > 1) - { - t += (panim[i]->fps / (panim[i]->numframes - 1)) * weight[i]; - } - } - return t; -} - -//----------------------------------------------------------------------------- -// Purpose: returns length (in seconds) of a sequence (seconds/cycle) -//----------------------------------------------------------------------------- - -float Studio_Duration( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[] ) -{ - mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( iSequence ); - float cps = Studio_CPS( pStudioHdr, seqdesc, iSequence, poseParameter ); - - if( cps == 0 ) - return 0.0f; - - return 1.0f/cps; -} - - -//----------------------------------------------------------------------------- -// Purpose: calculate changes in position and angle relative to the start of an animations cycle -// Output: updated position and angle, relative to the origin -// returns false if animation is not a movement animation -//----------------------------------------------------------------------------- - -bool Studio_AnimPosition( mstudioanimdesc_t *panim, float flCycle, Vector &vecPos, QAngle &vecAngle ) -{ - float prevframe = 0; - vecPos.Init( ); - vecAngle.Init( ); - - if (panim->nummovements == 0) - return false; - - int iLoops = 0; - if (flCycle > 1.0) - { - iLoops = (int)flCycle; - } - else if (flCycle < 0.0) - { - iLoops = (int)flCycle - 1; - } - flCycle = flCycle - iLoops; - - float flFrame = flCycle * (panim->numframes - 1); - - for (int i = 0; i < panim->nummovements; i++) - { - mstudiomovement_t *pmove = panim->pMovement( i ); - - if (pmove->endframe >= flFrame) - { - float f = (flFrame - prevframe) / (pmove->endframe - prevframe); - - float d = pmove->v0 * f + 0.5 * (pmove->v1 - pmove->v0) * f * f; - - vecPos = vecPos + d * pmove->vector; - vecAngle.y = vecAngle.y * (1 - f) + pmove->angle * f; - if (iLoops != 0) - { - mstudiomovement_t *pmove = panim->pMovement( panim->nummovements - 1 ); - vecPos = vecPos + iLoops * pmove->position; - vecAngle.y = vecAngle.y + iLoops * pmove->angle; - } - return true; - } - else - { - prevframe = pmove->endframe; - vecPos = pmove->position; - vecAngle.y = pmove->angle; - } - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: calculate instantaneous velocity in ips at a given point -// in the animations cycle -// Output: velocity vector, relative to identity orientation -// returns false if animation is not a movement animation -//----------------------------------------------------------------------------- - -bool Studio_AnimVelocity( mstudioanimdesc_t *panim, float flCycle, Vector &vecVelocity ) -{ - float prevframe = 0; - - float flFrame = flCycle * (panim->numframes - 1); - flFrame = flFrame - (int)(flFrame / (panim->numframes - 1)); - - for (int i = 0; i < panim->nummovements; i++) - { - mstudiomovement_t *pmove = panim->pMovement( i ); - - if (pmove->endframe >= flFrame) - { - float f = (flFrame - prevframe) / (pmove->endframe - prevframe); - - float vel = pmove->v0 * (1 - f) + pmove->v1 * f; - // scale from per block to per sec velocity - vel = vel * panim->fps / (pmove->endframe - prevframe); - - vecVelocity = pmove->vector * vel; - return true; - } - else - { - prevframe = pmove->endframe; - } - } - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: calculate changes in position and angle between two points in an animation cycle -// Output: updated position and angle, relative to CycleFrom being at the origin -// returns false if animation is not a movement animation -//----------------------------------------------------------------------------- - -bool Studio_AnimMovement( mstudioanimdesc_t *panim, float flCycleFrom, float flCycleTo, Vector &deltaPos, QAngle &deltaAngle ) -{ - if (panim->nummovements == 0) - return false; - - Vector startPos; - QAngle startA; - Studio_AnimPosition( panim, flCycleFrom, startPos, startA ); - - Vector endPos; - QAngle endA; - Studio_AnimPosition( panim, flCycleTo, endPos, endA ); - - Vector tmp = endPos - startPos; - deltaAngle.y = endA.y - startA.y; - VectorYawRotate( tmp, -startA.y, deltaPos ); - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: finds how much of an animation to play to move given linear distance -//----------------------------------------------------------------------------- - -float Studio_FindAnimDistance( mstudioanimdesc_t *panim, float flDist ) -{ - float prevframe = 0; - - if (flDist <= 0) - return 0.0; - - for (int i = 0; i < panim->nummovements; i++) - { - mstudiomovement_t *pmove = panim->pMovement( i ); - - float flMove = (pmove->v0 + pmove->v1) * 0.5; - - if (flMove >= flDist) - { - float root1, root2; - - // d = V0 * t + 1/2 (V1-V0) * t^2 - if (SolveQuadratic( 0.5 * (pmove->v1 - pmove->v0), pmove->v0, -flDist, root1, root2 )) - { - float cpf = 1.0 / (panim->numframes - 1); // cycles per frame - - return (prevframe + root1 * (pmove->endframe - prevframe)) * cpf; - } - return 0.0; - } - else - { - flDist -= flMove; - prevframe = pmove->endframe; - } - } - return 1.0; -} - - -//----------------------------------------------------------------------------- -// Purpose: calculate changes in position and angle between two points in a sequences cycle -// Output: updated position and angle, relative to CycleFrom being at the origin -// returns false if sequence is not a movement sequence -//----------------------------------------------------------------------------- - -bool Studio_SeqMovement( const CStudioHdr *pStudioHdr, int iSequence, float flCycleFrom, float flCycleTo, const float poseParameter[], Vector &deltaPos, QAngle &deltaAngles ) -{ - mstudioanimdesc_t *panim[4]; - float weight[4]; - - mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( iSequence ); - - Studio_SeqAnims( pStudioHdr, seqdesc, iSequence, poseParameter, panim, weight ); - - deltaPos.Init( ); - deltaAngles.Init( ); - - bool found = false; - - for (int i = 0; i < 4; i++) - { - if (weight[i]) - { - Vector localPos; - QAngle localAngles; - - localPos.Init(); - localAngles.Init(); - - if (Studio_AnimMovement( panim[i], flCycleFrom, flCycleTo, localPos, localAngles )) - { - found = true; - deltaPos = deltaPos + localPos * weight[i]; - // FIXME: this makes no sense - deltaAngles = deltaAngles + localAngles * weight[i]; - } - else if (!(panim[i]->flags & STUDIO_DELTA) && panim[i]->nummovements == 0 && seqdesc.weight(0) > 0.0) - { - found = true; - } - } - } - return found; -} - - -//----------------------------------------------------------------------------- -// Purpose: calculate instantaneous velocity in ips at a given point in the sequence's cycle -// Output: velocity vector, relative to identity orientation -// returns false if sequence is not a movement sequence -//----------------------------------------------------------------------------- - -bool Studio_SeqVelocity( const CStudioHdr *pStudioHdr, int iSequence, float flCycle, const float poseParameter[], Vector &vecVelocity ) -{ - mstudioanimdesc_t *panim[4]; - float weight[4]; - - mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( iSequence ); - Studio_SeqAnims( pStudioHdr, seqdesc, iSequence, poseParameter, panim, weight ); - - vecVelocity.Init( ); - - bool found = false; - - for (int i = 0; i < 4; i++) - { - if (weight[i]) - { - Vector vecLocalVelocity; - - if (Studio_AnimVelocity( panim[i], flCycle, vecLocalVelocity )) - { - vecVelocity = vecVelocity + vecLocalVelocity * weight[i]; - found = true; - } - } - } - return found; -} - -//----------------------------------------------------------------------------- -// Purpose: finds how much of an sequence to play to move given linear distance -//----------------------------------------------------------------------------- - -float Studio_FindSeqDistance( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[], float flDist ) -{ - mstudioanimdesc_t *panim[4]; - float weight[4]; - - mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( iSequence ); - Studio_SeqAnims( pStudioHdr, seqdesc, iSequence, poseParameter, panim, weight ); - - float flCycle = 0; - - for (int i = 0; i < 4; i++) - { - if (weight[i]) - { - float flLocalCycle = Studio_FindAnimDistance( panim[i], flDist ); - flCycle = flCycle + flLocalCycle * weight[i]; - } - } - return flCycle; -} - -//----------------------------------------------------------------------------- -// Purpose: lookup attachment by name -//----------------------------------------------------------------------------- - -int Studio_FindAttachment( const CStudioHdr *pStudioHdr, const char *pAttachmentName ) -{ - if ( pStudioHdr && pStudioHdr->SequencesAvailable() ) - { - // Extract the bone index from the name - for (int i = 0; i < pStudioHdr->GetNumAttachments(); i++) - { - if (!stricmp(pAttachmentName,pStudioHdr->pAttachment(i).pszName( ))) - { - return i; - } - } - } - - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: lookup attachments by substring. Randomly return one of the matching attachments. -//----------------------------------------------------------------------------- - -int Studio_FindRandomAttachment( const CStudioHdr *pStudioHdr, const char *pAttachmentName ) -{ - if ( pStudioHdr ) - { - // First move them all matching attachments into a list - CUtlVector matchingAttachments; - - // Extract the bone index from the name - for (int i = 0; i < pStudioHdr->GetNumAttachments(); i++) - { - if ( strstr( pStudioHdr->pAttachment(i).pszName(), pAttachmentName ) ) - { - matchingAttachments.AddToTail(i); - } - } - - // Then randomly return one of the attachments - if ( matchingAttachments.Size() > 0 ) - return matchingAttachments[ RandomInt( 0, matchingAttachments.Size()-1 ) ]; - } - - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: lookup bone by name -//----------------------------------------------------------------------------- - -int Studio_BoneIndexByName( const CStudioHdr *pStudioHdr, const char *pName ) -{ - // binary search for the bone matching pName - int start = 0, end = pStudioHdr->numbones()-1; - const byte *pBoneTable = pStudioHdr->GetBoneTableSortedByName(); - mstudiobone_t *pbones = pStudioHdr->pBone( 0 ); - while (start <= end) - { - int mid = (start + end) >> 1; - int cmp = Q_stricmp( pbones[pBoneTable[mid]].pszName(), pName ); - - if ( cmp < 0 ) - { - start = mid + 1; - } - else if ( cmp > 0 ) - { - end = mid - 1; - } - else - { - return pBoneTable[mid]; - } - } - return -1; -} - -const char *Studio_GetDefaultSurfaceProps( CStudioHdr *pstudiohdr ) -{ - return pstudiohdr->pszSurfaceProp(); -} - -float Studio_GetMass( CStudioHdr *pstudiohdr ) -{ - return pstudiohdr->mass(); -} - -//----------------------------------------------------------------------------- -// Purpose: return pointer to sequence key value buffer -//----------------------------------------------------------------------------- - -const char *Studio_GetKeyValueText( const CStudioHdr *pStudioHdr, int iSequence ) -{ - if (pStudioHdr && pStudioHdr->SequencesAvailable()) - { - if (iSequence >= 0 && iSequence < pStudioHdr->GetNumSeq()) - { - return pStudioHdr->pSeqdesc( iSequence ).KeyValueText(); - } - } - return NULL; -} - -bool Studio_PrefetchSequence( const CStudioHdr *pStudioHdr, int iSequence ) -{ - bool pendingload = false; - mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( iSequence ); - int size0 = seqdesc.groupsize[ 0 ]; - int size1 = seqdesc.groupsize[ 1 ]; - for ( int i = 0; i < size0; ++i ) - { - for ( int j = 0; j < size1; ++j ) - { - mstudioanimdesc_t &animdesc = pStudioHdr->pAnimdesc( seqdesc.anim( i, j ) ); - int iFrame = 0; - mstudioanim_t *panim = animdesc.pAnim( &iFrame ); - if ( !panim ) - { - pendingload = true; - } - } - } - - // Everything for this sequence is resident? - return !pendingload; -} diff --git a/public/bone_setup.h b/public/bone_setup.h deleted file mode 100644 index 65ae31660..000000000 --- a/public/bone_setup.h +++ /dev/null @@ -1,500 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef BONE_SETUP_H -#define BONE_SETUP_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "studio.h" -#include "cmodel.h" -#include "bitvec.h" - - -class CBoneToWorld; -class CIKContext; -class CBoneAccessor; - - -// This provides access to networked arrays, so if this code actually changes a value, -// the entity is marked as changed. -abstract_class IParameterAccess -{ -public: - virtual float GetParameter( int iParam ) = 0; - virtual void SetParameter( int iParam, float flValue ) = 0; -}; - - - -class CBoneBitList : public CBitVec -{ -public: - inline void MarkBone(int iBone) - { - Set(iBone); - } - inline bool IsBoneMarked(int iBone) - { - return Get(iBone) != 0 ? true : false; - } -}; - - - - -//----------------------------------------------------------------------------- -// Purpose: blends together all the bones from two p:q lists -// -// p1 = p1 * (1 - s) + p2 * s -// q1 = q1 * (1 - s) + q2 * s -//----------------------------------------------------------------------------- -void SlerpBones( - const CStudioHdr *pStudioHdr, - Quaternion q1[MAXSTUDIOBONES], - Vector pos1[MAXSTUDIOBONES], - mstudioseqdesc_t &seqdesc, // source of q2 and pos2 - int sequence, - const Quaternion q2[MAXSTUDIOBONES], - const Vector pos2[MAXSTUDIOBONES], - float s, - int boneMask - ); - - -void InitPose( - const CStudioHdr *pStudioHdr, - Vector pos[], - Quaternion q[], - int boneMask - ); - -void CalcPose( - const CStudioHdr *pStudioHdr, - CIKContext *pIKContext, //optional - Vector pos[], - Quaternion q[], - int sequence, - float cycle, - const float poseParameter[], - int boneMask, - float flWeight = 1.0f, - float flTime = 0.0f - ); - -bool CalcPoseSingle( - const CStudioHdr *pStudioHdr, - Vector pos[], - Quaternion q[], - mstudioseqdesc_t &seqdesc, - int sequence, - float cycle, - const float poseParameter[], - int boneMask, - float flTime - ); - -void AccumulatePose( - const CStudioHdr *pStudioHdr, - CIKContext *pIKContext, //optional - Vector pos[], - Quaternion q[], - int sequence, - float cycle, - const float poseParameter[], - int boneMask, - float flWeight, - float flTime - ); - -// takes a "controllers[]" array normalized to 0..1 and adds in the adjustments to pos[], and q[]. -void CalcBoneAdj( - const CStudioHdr *pStudioHdr, - Vector pos[], - Quaternion q[], - const float controllers[], - int boneMask - ); - - -// Given two samples of a bone separated in time by dt, -// compute the velocity and angular velocity of that bone -void CalcBoneDerivatives( Vector &velocity, AngularImpulse &angVel, const matrix3x4_t &prev, const matrix3x4_t ¤t, float dt ); -// Give a derivative of a bone, compute the velocity & angular velocity of that bone -void CalcBoneVelocityFromDerivative( const QAngle &vecAngles, Vector &velocity, AngularImpulse &angVel, const matrix3x4_t ¤t ); - -// This function sets up the local transform for a single frame of animation. It doesn't handle -// pose parameters or interpolation between frames. -void SetupSingleBoneMatrix( - CStudioHdr *pOwnerHdr, - int nSequence, - int iFrame, - int iBone, - matrix3x4_t &mBoneLocal ); - - -// Purpose: build boneToWorld transforms for a specific bone -void BuildBoneChain( - const CStudioHdr *pStudioHdr, - const matrix3x4_t &rootxform, - const Vector pos[], - const Quaternion q[], - int iBone, - matrix3x4_t *pBoneToWorld ); - -void BuildBoneChain( - const CStudioHdr *pStudioHdr, - const matrix3x4_t &rootxform, - const Vector pos[], - const Quaternion q[], - int iBone, - matrix3x4_t *pBoneToWorld, - CBoneBitList &boneComputed ); - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -// ik info -class CIKTarget -{ -public: - void SetOwner( int entindex, const Vector &pos, const QAngle &angles ); - void ClearOwner( void ); - int GetOwner( void ); - void UpdateOwner( int entindex, const Vector &pos, const QAngle &angles ); - void SetPos( const Vector &pos ); - void SetAngles( const QAngle &angles ); - void SetQuaternion( const Quaternion &q ); - void SetNormal( const Vector &normal ); - void SetPosWithNormalOffset( const Vector &pos, const Vector &normal ); - void SetOnWorld( bool bOnWorld = true ); - - bool IsActive( void ); - void IKFailed( void ); - int chain; - int type; - void MoveReferenceFrame( Vector &deltaPos, QAngle &deltaAngles ); - // accumulated offset from ideal footplant location -public: - struct x2 { - char *pAttachmentName; - Vector pos; - Quaternion q; - } offset; -private: - struct x3 { - Vector pos; - Quaternion q; - } ideal; -public: - struct x4 { - float latched; - float release; - float height; - float floor; - float radius; - float flTime; - float flWeight; - Vector pos; - Quaternion q; - bool onWorld; - } est; // estimate contact position - struct x5 { - float hipToFoot; // distance from hip - float hipToKnee; // distance from hip to knee - float kneeToFoot; // distance from knee to foot - Vector hip; // location of hip - Vector closest; // closest valid location from hip to foot that the foot can move to - Vector knee; // pre-ik location of knee - Vector farthest; // farthest valid location from hip to foot that the foot can move to - Vector lowest; // lowest position directly below hip that the foot can drop to - } trace; -private: - // internally latched footset, position - struct x1 { - // matrix3x4_t worldTarget; - bool bNeedsLatch; - bool bHasLatch; - float influence; - int iFramecounter; - int owner; - Vector absOrigin; - QAngle absAngles; - Vector pos; - Quaternion q; - Vector deltaPos; // acculated error - Quaternion deltaQ; - Vector debouncePos; - Quaternion debounceQ; - } latched; - struct x6 { - float flTime; // time last error was detected - float flErrorTime; - float ramp; - bool bInError; - } error; - - friend class CIKContext; -}; - - -struct ikchainresult_t -{ - // accumulated offset from ideal footplant location - int target; - Vector pos; - Quaternion q; - float flWeight; -}; - - - -struct ikcontextikrule_t -{ - int index; - - int type; - int chain; - - int bone; - - int slot; // iktarget slot. Usually same as chain. - float height; - float radius; - float floor; - Vector pos; - Quaternion q; - - float start; // beginning of influence - float peak; // start of full influence - float tail; // end of full influence - float end; // end of all influence - - float top; - float drop; - - float commit; // frame footstep target should be committed - float release; // frame ankle should end rotation from latched orientation - - float flWeight; // processed version of start-end cycle - float flRuleWeight; // blending weight - float latched; // does the IK rule use a latched value? - char *szLabel; - - Vector kneeDir; - Vector kneePos; - - ikcontextikrule_t() {} - -private: - // No copy constructors allowed - ikcontextikrule_t(const ikcontextikrule_t& vOther); -}; - - -void Studio_AlignIKMatrix( matrix3x4_t &mMat, const Vector &vAlignTo ); - -bool Studio_SolveIK( int iThigh, int iKnee, int iFoot, Vector &targetFoot, matrix3x4_t* pBoneToWorld ); - -bool Studio_SolveIK( int iThigh, int iKnee, int iFoot, Vector &targetFoot, Vector &targetKneePos, Vector &targetKneeDir, matrix3x4_t* pBoneToWorld ); - - - -class CIKContext -{ -public: - CIKContext( ); - void Init( const CStudioHdr *pStudioHdr, const QAngle &angles, const Vector &pos, float flTime, int iFramecounter, int boneMask ); - void AddDependencies( mstudioseqdesc_t &seqdesc, int iSequence, float flCycle, const float poseParameters[], float flWeight = 1.0f ); - - void ClearTargets( void ); - void UpdateTargets( Vector pos[], Quaternion q[], matrix3x4_t boneToWorld[], CBoneBitList &boneComputed ); - void AutoIKRelease( void ); - void SolveDependencies( Vector pos[], Quaternion q[], matrix3x4_t boneToWorld[], CBoneBitList &boneComputed ); - - void AddAutoplayLocks( Vector pos[], Quaternion q[] ); - void SolveAutoplayLocks( Vector pos[], Quaternion q[] ); - - void AddSequenceLocks( mstudioseqdesc_t &SeqDesc, Vector pos[], Quaternion q[] ); - void SolveSequenceLocks( mstudioseqdesc_t &SeqDesc, Vector pos[], Quaternion q[] ); - - void AddAllLocks( Vector pos[], Quaternion q[] ); - void SolveAllLocks( Vector pos[], Quaternion q[] ); - - void SolveLock( const mstudioiklock_t *plock, int i, Vector pos[], Quaternion q[], matrix3x4_t boneToWorld[], CBoneBitList &boneComputed ); - - CUtlVectorFixed< CIKTarget, 12 > m_target; - -private: - - CStudioHdr const *m_pStudioHdr; - - bool Estimate( int iSequence, float flCycle, int iTarget, const float poseParameter[], float flWeight = 1.0f ); - void BuildBoneChain( const Vector pos[], const Quaternion q[], int iBone, matrix3x4_t *pBoneToWorld, CBoneBitList &boneComputed ); - - // virtual IK rules, filtered and combined from each sequence - CUtlVector< CUtlVector< ikcontextikrule_t > > m_ikChainRule; - CUtlVector< ikcontextikrule_t > m_ikLock; - matrix3x4_t m_rootxform; - - int m_iFramecounter; - float m_flTime; - int m_boneMask; -}; - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -// takes a "poseparameters[]" array normalized to 0..1 and layers on the sequences driven by them -void CalcAutoplaySequences( - const CStudioHdr *pStudioHdr, - CIKContext *pIKContext, //optional - Vector pos[], - Quaternion q[], - const float poseParameters[], - int boneMask, - float time - ); - -// replaces the bonetoworld transforms for all bones that are procedural -bool CalcProceduralBone( - const CStudioHdr *pStudioHdr, - int iBone, - CBoneAccessor &bonetoworld - ); - -void Studio_BuildMatrices( - const CStudioHdr *pStudioHdr, - const QAngle& angles, - const Vector& origin, - const Vector pos[], - const Quaternion q[], - int iBone, - matrix3x4_t bonetoworld[MAXSTUDIOBONES], - int boneMask - ); - - -// Get a bone->bone relative transform -void Studio_CalcBoneToBoneTransform( const CStudioHdr *pStudioHdr, int inputBoneIndex, int outputBoneIndex, matrix3x4_t &matrixOut ); - -// Given a bone rotation value, figures out the value you need to give to the controller -// to have the bone at that value. -// [in] flValue = the desired bone rotation value -// [out] ctlValue = the (0-1) value to set the controller t. -// return value = flValue, unwrapped to lie between the controller's start and end. -float Studio_SetController( const CStudioHdr *pStudioHdr, int iController, float flValue, float &ctlValue ); - - -// Given a 0-1 controller value, maps it into the controller's start and end and returns the bone rotation angle. -// [in] ctlValue = value in controller space (0-1). -// return value = value in bone space -float Studio_GetController( const CStudioHdr *pStudioHdr, int iController, float ctlValue ); - -float Studio_GetPoseParameter( const CStudioHdr *pStudioHdr, int iParameter, float ctlValue ); -float Studio_SetPoseParameter( const CStudioHdr *pStudioHdr, int iParameter, float flValue, float &ctlValue ); - -// converts a global 0..1 pose parameter into the local sequences blending value -void Studio_LocalPoseParameter( const CStudioHdr *pStudioHdr, const float poseParameter[], mstudioseqdesc_t &seqdesc, int iSequence, int iLocalIndex, float &flSetting, int &index ); - -void Studio_SeqAnims( const CStudioHdr *pStudioHdr, mstudioseqdesc_t &seqdesc, int iSequence, const float poseParameter[], mstudioanimdesc_t *panim[4], float *weight ); -int Studio_MaxFrame( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[] ); -float Studio_FPS( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[] ); -float Studio_CPS( const CStudioHdr *pStudioHdr, mstudioseqdesc_t &seqdesc, int iSequence, const float poseParameter[] ); -float Studio_Duration( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[] ); -void Studio_MovementRate( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[], Vector *pVec ); - -// void Studio_Movement( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[], Vector *pVec ); - -//void Studio_AnimPosition( mstudioanimdesc_t *panim, float flCycle, Vector &vecPos, Vector &vecAngle ); -//void Studio_AnimVelocity( mstudioanimdesc_t *panim, float flCycle, Vector &vecVelocity ); -//float Studio_FindAnimDistance( mstudioanimdesc_t *panim, float flDist ); -bool Studio_AnimMovement( mstudioanimdesc_t *panim, float flCycleFrom, float flCycleTo, Vector &deltaPos, QAngle &deltaAngle ); -bool Studio_SeqMovement( const CStudioHdr *pStudioHdr, int iSequence, float flCycleFrom, float flCycleTo, const float poseParameter[], Vector &deltaMovement, QAngle &deltaAngle ); -bool Studio_SeqVelocity( const CStudioHdr *pStudioHdr, int iSequence, float flCycle, const float poseParameter[], Vector &vecVelocity ); -float Studio_FindSeqDistance( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[], float flDist ); -float Studio_FindSeqVelocity( const CStudioHdr *pStudioHdr, int iSequence, const float poseParameter[], float flVelocity ); -int Studio_FindAttachment( const CStudioHdr *pStudioHdr, const char *pAttachmentName ); -int Studio_FindRandomAttachment( const CStudioHdr *pStudioHdr, const char *pAttachmentName ); -int Studio_BoneIndexByName( const CStudioHdr *pStudioHdr, const char *pName ); -const char *Studio_GetDefaultSurfaceProps( CStudioHdr *pstudiohdr ); -float Studio_GetMass( CStudioHdr *pstudiohdr ); -const char *Studio_GetKeyValueText( const CStudioHdr *pStudioHdr, int iSequence ); - -FORWARD_DECLARE_HANDLE( memhandle_t ); -struct bonecacheparams_t -{ - CStudioHdr *pStudioHdr; - matrix3x4_t *pBoneToWorld; - float curtime; - int boneMask; -}; - -class CBoneCache -{ -public: - - // you must implement these static functions for the ResourceManager - // ----------------------------------------------------------- - static CBoneCache *CreateResource( const bonecacheparams_t ¶ms ); - static unsigned int EstimatedSize( const bonecacheparams_t ¶ms ); - // ----------------------------------------------------------- - // member functions that must be present for the ResourceManager - void DestroyResource(); - CBoneCache *GetData() { return this; } - unsigned int Size() { return m_size; } - // ----------------------------------------------------------- - - CBoneCache(); - - // was constructor, but placement new is messy wrt memdebug - so cast & init instead - void Init( const bonecacheparams_t ¶ms, unsigned int size, short *pStudioToCached, short *pCachedToStudio, int cachedBoneCount ); - - void UpdateBones( const matrix3x4_t *pBoneToWorld, int numbones, float curtime ); - matrix3x4_t *GetCachedBone( int studioIndex ); - void ReadCachedBones( matrix3x4_t *pBoneToWorld ); - void ReadCachedBonePointers( matrix3x4_t **bones, int numbones ); - - bool IsValid( float curtime, float dt = 0.1f ); - -public: - float m_timeValid; - int m_boneMask; - -private: - matrix3x4_t *BoneArray(); - short *StudioToCached(); - short *CachedToStudio(); - - unsigned int m_size; - unsigned short m_cachedBoneCount; - unsigned short m_matrixOffset; - unsigned short m_cachedToStudioOffset; - unsigned short m_boneOutOffset; -}; - -CBoneCache *Studio_GetBoneCache( memhandle_t cacheHandle ); -memhandle_t Studio_CreateBoneCache( bonecacheparams_t ¶ms ); -void Studio_DestroyBoneCache( memhandle_t cacheHandle ); -void Studio_InvalidateBoneCache( memhandle_t cacheHandle ); - -// Given a ray, trace for an intersection with this studiomodel. Get the array of bones from StudioSetupHitboxBones -bool TraceToStudio( class IPhysicsSurfaceProps *pProps, const Ray_t& ray, CStudioHdr *pStudioHdr, mstudiohitboxset_t *set, matrix3x4_t **hitboxbones, int fContentsMask, trace_t &trace ); - - -void QuaternionSM( float s, const Quaternion &p, const Quaternion &q, Quaternion &qt ); -void QuaternionMA( const Quaternion &p, float s, const Quaternion &q, Quaternion &qt ); - -bool Studio_PrefetchSequence( const CStudioHdr *pStudioHdr, int iSequence ); - -#endif // BONE_SETUP_H diff --git a/public/bspfile.h b/public/bspfile.h deleted file mode 100644 index 1aa33a7ad..000000000 --- a/public/bspfile.h +++ /dev/null @@ -1,1161 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Defines and structures for the BSP file format. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef BSPFILE_H -#define BSPFILE_H -#pragma once - -#ifndef MATHLIB_H -#include "mathlib/mathlib.h" -#endif - -#include "datamap.h" -#include "mathlib/bumpvects.h" -#include "mathlib/compressed_light_cube.h" - -// little-endian "VBSP" -#define IDBSPHEADER (('P'<<24)+('S'<<16)+('B'<<8)+'V') - -// MINBSPVERSION is the minimum acceptable version. The engine will load MINBSPVERSION through BSPVERSION -#define MINBSPVERSION 19 -#define BSPVERSION 20 - - -// This needs to match the value in gl_lightmap.h -// Need to dynamically allocate the weights and light values in radial_t to make this variable. -#define MAX_BRUSH_LIGHTMAP_DIM_WITHOUT_BORDER 32 -// This is one more than what vbsp cuts for to allow for rounding errors -#define MAX_BRUSH_LIGHTMAP_DIM_INCLUDING_BORDER 35 - -// We can have larger lightmaps on displacements -#define MAX_DISP_LIGHTMAP_DIM_WITHOUT_BORDER 125 -#define MAX_DISP_LIGHTMAP_DIM_INCLUDING_BORDER 128 - - -// This is the actual max.. (change if you change the brush lightmap dim or disp lightmap dim -#define MAX_LIGHTMAP_DIM_WITHOUT_BORDER MAX_DISP_LIGHTMAP_DIM_WITHOUT_BORDER -#define MAX_LIGHTMAP_DIM_INCLUDING_BORDER MAX_DISP_LIGHTMAP_DIM_INCLUDING_BORDER - -#define MAX_LIGHTSTYLES 64 - - -// upper design bounds -#define MIN_MAP_DISP_POWER 2 // Minimum and maximum power a displacement can be. -#define MAX_MAP_DISP_POWER 4 - -// Max # of neighboring displacement touching a displacement's corner. -#define MAX_DISP_CORNER_NEIGHBORS 4 - -#define NUM_DISP_POWER_VERTS(power) ( ((1 << (power)) + 1) * ((1 << (power)) + 1) ) -#define NUM_DISP_POWER_TRIS(power) ( (1 << (power)) * (1 << (power)) * 2 ) - -#if !defined( BSP_USE_LESS_MEMORY ) -// Common limits -// leaffaces, leafbrushes, planes, and verts are still bounded by -// 16 bit short limits -#define MAX_MAP_MODELS 1024 -#define MAX_MAP_BRUSHES 8192 -#define MAX_MAP_ENTITIES 8192 -#define MAX_MAP_TEXINFO 12288 -#define MAX_MAP_TEXDATA 2048 -#define MAX_MAP_DISPINFO 2048 -#define MAX_MAP_DISP_VERTS ( MAX_MAP_DISPINFO * ((1< x --------------> 2 -// -// ^ ^ -// | | -// | | -// M2C | | M2C -// | | -// | | -// -// x x x -// -// ^ ^ -// | | -// | | -// C2M | | C2M -// | | -// | | -// -// 0 --------------> x --------------> 3 -// -// C2M M2C -// -// -// The CHILDNODE_ defines can be used to refer to a node's child nodes (this is for when you're -// recursing into the node tree inside a displacement): -// -// --------- -// | | | -// | 1 | 0 | -// | | | -// |---x---| -// | | | -// | 2 | 3 | -// | | | -// --------- -// -// ------------------------------------------------------------------------------------------------ // - -// These can be used to index g_ChildNodeIndexMul. -enum -{ - CHILDNODE_UPPER_RIGHT=0, - CHILDNODE_UPPER_LEFT=1, - CHILDNODE_LOWER_LEFT=2, - CHILDNODE_LOWER_RIGHT=3 -}; - - -// Corner indices. Used to index m_CornerNeighbors. -enum -{ - CORNER_LOWER_LEFT=0, - CORNER_UPPER_LEFT=1, - CORNER_UPPER_RIGHT=2, - CORNER_LOWER_RIGHT=3 -}; - - -// These edge indices must match the edge indices of the CCoreDispSurface. -enum -{ - NEIGHBOREDGE_LEFT=0, - NEIGHBOREDGE_TOP=1, - NEIGHBOREDGE_RIGHT=2, - NEIGHBOREDGE_BOTTOM=3 -}; - - -// These denote where one dispinfo fits on another. -// Note: tables are generated based on these indices so make sure to update -// them if these indices are changed. -typedef enum -{ - CORNER_TO_CORNER=0, - CORNER_TO_MIDPOINT=1, - MIDPOINT_TO_CORNER=2 -} NeighborSpan; - - -// These define relative orientations of displacement neighbors. -typedef enum -{ - ORIENTATION_CCW_0=0, - ORIENTATION_CCW_90=1, - ORIENTATION_CCW_180=2, - ORIENTATION_CCW_270=3 -} NeighborOrientation; - - -//============================================================================= - -enum -{ - LUMP_ENTITIES = 0, // * - LUMP_PLANES = 1, // * - LUMP_TEXDATA = 2, // * - LUMP_VERTEXES = 3, // * - LUMP_VISIBILITY = 4, // * - LUMP_NODES = 5, // * - LUMP_TEXINFO = 6, // * - LUMP_FACES = 7, // * - LUMP_LIGHTING = 8, // * - LUMP_OCCLUSION = 9, - LUMP_LEAFS = 10, // * - LUMP_FACEIDS = 11, - LUMP_EDGES = 12, // * - LUMP_SURFEDGES = 13, // * - LUMP_MODELS = 14, // * - LUMP_WORLDLIGHTS = 15, // - LUMP_LEAFFACES = 16, // * - LUMP_LEAFBRUSHES = 17, // * - LUMP_BRUSHES = 18, // * - LUMP_BRUSHSIDES = 19, // * - LUMP_AREAS = 20, // * - LUMP_AREAPORTALS = 21, // * - LUMP_UNUSED0 = 22, - LUMP_UNUSED1 = 23, - LUMP_UNUSED2 = 24, - LUMP_UNUSED3 = 25, - LUMP_DISPINFO = 26, - LUMP_ORIGINALFACES = 27, - LUMP_PHYSDISP = 28, - LUMP_PHYSCOLLIDE = 29, - LUMP_VERTNORMALS = 30, - LUMP_VERTNORMALINDICES = 31, - LUMP_DISP_LIGHTMAP_ALPHAS = 32, - LUMP_DISP_VERTS = 33, // CDispVerts - LUMP_DISP_LIGHTMAP_SAMPLE_POSITIONS = 34, // For each displacement - // For each lightmap sample - // byte for index - // if 255, then index = next byte + 255 - // 3 bytes for barycentric coordinates - // The game lump is a method of adding game-specific lumps - // FIXME: Eventually, all lumps could use the game lump system - LUMP_GAME_LUMP = 35, - LUMP_LEAFWATERDATA = 36, - LUMP_PRIMITIVES = 37, - LUMP_PRIMVERTS = 38, - LUMP_PRIMINDICES = 39, - // A pak file can be embedded in a .bsp now, and the file system will search the pak - // file first for any referenced names, before deferring to the game directory - // file system/pak files and finally the base directory file system/pak files. - LUMP_PAKFILE = 40, - LUMP_CLIPPORTALVERTS = 41, - // A map can have a number of cubemap entities in it which cause cubemap renders - // to be taken after running vrad. - LUMP_CUBEMAPS = 42, - LUMP_TEXDATA_STRING_DATA = 43, - LUMP_TEXDATA_STRING_TABLE = 44, - LUMP_OVERLAYS = 45, - LUMP_LEAFMINDISTTOWATER = 46, - LUMP_FACE_MACRO_TEXTURE_INFO = 47, - LUMP_DISP_TRIS = 48, - LUMP_PHYSCOLLIDESURFACE = 49, // deprecated. We no longer use win32-specific havok compression on terrain - LUMP_WATEROVERLAYS = 50, - LUMP_LEAF_AMBIENT_INDEX_HDR = 51, // index of LUMP_LEAF_AMBIENT_LIGHTING_HDR - LUMP_LEAF_AMBIENT_INDEX = 52, // index of LUMP_LEAF_AMBIENT_LIGHTING - - // optional lumps for HDR - LUMP_LIGHTING_HDR = 53, - LUMP_WORLDLIGHTS_HDR = 54, - LUMP_LEAF_AMBIENT_LIGHTING_HDR = 55, // NOTE: this data overrides part of the data stored in LUMP_LEAFS. - LUMP_LEAF_AMBIENT_LIGHTING = 56, // NOTE: this data overrides part of the data stored in LUMP_LEAFS. - - LUMP_XZIPPAKFILE = 57, // deprecated. xbox 1: xzip version of pak file - LUMP_FACES_HDR = 58, // HDR maps may have different face data. - LUMP_MAP_FLAGS = 59, // extended level-wide flags. not present in all levels - LUMP_OVERLAY_FADES = 60, // Fade distances for overlays -}; - - -// Lumps that have versions are listed here -enum -{ - LUMP_LIGHTING_VERSION = 1, - LUMP_FACES_VERSION = 1, - LUMP_OCCLUSION_VERSION = 2, - LUMP_LEAFS_VERSION = 1, - LUMP_LEAF_AMBIENT_LIGHTING_VERSION = 1, -}; - - -#define HEADER_LUMPS 64 - -#include "zip_uncompressed.h" - -struct lump_t -{ - DECLARE_BYTESWAP_DATADESC(); - int fileofs, filelen; - int version; // default to zero - char fourCC[4]; // default to ( char )0, ( char )0, ( char )0, ( char )0 -}; - - -struct dheader_t -{ - DECLARE_BYTESWAP_DATADESC(); - int ident; - int version; - lump_t lumps[HEADER_LUMPS]; - int mapRevision; // the map's revision (iteration, version) number (added BSPVERSION 6) -}; - -// level feature flags -#define LVLFLAGS_BAKED_STATIC_PROP_LIGHTING_NONHDR 0x00000001 // was processed by vrad with -staticproplighting, no hdr data -#define LVLFLAGS_BAKED_STATIC_PROP_LIGHTING_HDR 0x00000002 // was processed by vrad with -staticproplighting, in hdr - -struct dflagslump_t -{ - DECLARE_BYTESWAP_DATADESC(); - uint32 m_LevelFlags; // LVLFLAGS_xxx -}; - -struct lumpfileheader_t -{ - int lumpOffset; - int lumpID; - int lumpVersion; - int lumpLength; - int mapRevision; // the map's revision (iteration, version) number (added BSPVERSION 6) -}; - -struct dgamelumpheader_t -{ - DECLARE_BYTESWAP_DATADESC(); - int lumpCount; - - // dgamelump_t follow this -}; - -// This is expected to be a four-CC code ('lump') -typedef int GameLumpId_t; - -// 360 only: game lump is compressed, filelen reflects original size -// use next entry fileofs to determine actual disk lump compressed size -// compression stage ensures a terminal null dictionary entry -#define GAMELUMPFLAG_COMPRESSED 0x0001 - -struct dgamelump_t -{ - DECLARE_BYTESWAP_DATADESC(); - GameLumpId_t id; - unsigned short flags; - unsigned short version; - int fileofs; - int filelen; -}; - -extern int g_MapRevision; - -struct dmodel_t -{ - DECLARE_BYTESWAP_DATADESC(); - Vector mins, maxs; - Vector origin; // for sounds or lights - int headnode; - int firstface, numfaces; // submodels just draw faces without walking the bsp tree -}; - -struct dphysmodel_t -{ - DECLARE_BYTESWAP_DATADESC() - int modelIndex; - int dataSize; - int keydataSize; - int solidCount; -}; - -// contains the binary blob for each displacement surface's virtual hull -struct dphysdisp_t -{ - DECLARE_BYTESWAP_DATADESC() - unsigned short numDisplacements; - //unsigned short dataSize[numDisplacements]; -}; - -struct dvertex_t -{ - DECLARE_BYTESWAP_DATADESC(); - Vector point; -}; - -// planes (x&~1) and (x&~1)+1 are always opposites -struct dplane_t -{ - DECLARE_BYTESWAP_DATADESC(); - Vector normal; - float dist; - int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate -}; - -#ifndef BSPFLAGS_H -#include "bspflags.h" -#endif - -struct dnode_t -{ - DECLARE_BYTESWAP_DATADESC(); - int planenum; - int children[2]; // negative numbers are -(leafs+1), not nodes - short mins[3]; // for frustom culling - short maxs[3]; - unsigned short firstface; - unsigned short numfaces; // counting both sides - short area; // If all leaves below this node are in the same area, then - // this is the area index. If not, this is -1. -}; - -typedef struct texinfo_s -{ - DECLARE_BYTESWAP_DATADESC(); - float textureVecsTexelsPerWorldUnits[2][4]; // [s/t][xyz offset] - float lightmapVecsLuxelsPerWorldUnits[2][4]; // [s/t][xyz offset] - length is in units of texels/area - int flags; // miptex flags + overrides - int texdata; // Pointer to texture name, size, etc. -} texinfo_t; - -#define TEXTURE_NAME_LENGTH 128 // changed from 64 BSPVERSION 8 - -struct dtexdata_t -{ - DECLARE_BYTESWAP_DATADESC(); - Vector reflectivity; - int nameStringTableID; // index into g_StringTable for the texture name - int width, height; // source image - int view_width, view_height; // -}; - - -//----------------------------------------------------------------------------- -// Occluders are simply polygons -//----------------------------------------------------------------------------- -// Flags field of doccluderdata_t -enum -{ - OCCLUDER_FLAGS_INACTIVE = 0x1, -}; - -struct doccluderdata_t -{ - DECLARE_BYTESWAP_DATADESC(); - int flags; - int firstpoly; // index into doccluderpolys - int polycount; - Vector mins; - Vector maxs; - int area; -}; - -struct doccluderdataV1_t -{ - int flags; - int firstpoly; // index into doccluderpolys - int polycount; - Vector mins; - Vector maxs; -}; - -struct doccluderpolydata_t -{ - DECLARE_BYTESWAP_DATADESC(); - int firstvertexindex; // index into doccludervertindices - int vertexcount; - int planenum; -}; - - -// NOTE: see the section above titled "displacement neighbor rules". -struct CDispSubNeighbor -{ -public: - DECLARE_BYTESWAP_DATADESC(); - unsigned short GetNeighborIndex() const { return m_iNeighbor; } - NeighborSpan GetSpan() const { return (NeighborSpan)m_Span; } - NeighborSpan GetNeighborSpan() const { return (NeighborSpan)m_NeighborSpan; } - NeighborOrientation GetNeighborOrientation() const { return (NeighborOrientation)m_NeighborOrientation; } - - bool IsValid() const { return m_iNeighbor != 0xFFFF; } - void SetInvalid() { m_iNeighbor = 0xFFFF; } - - -public: - unsigned short m_iNeighbor; // This indexes into ddispinfos. - // 0xFFFF if there is no neighbor here. - - unsigned char m_NeighborOrientation; // (CCW) rotation of the neighbor wrt this displacement. - - // These use the NeighborSpan type. - unsigned char m_Span; // Where the neighbor fits onto this side of our displacement. - unsigned char m_NeighborSpan; // Where we fit onto our neighbor. -}; - - -// NOTE: see the section above titled "displacement neighbor rules". -class CDispNeighbor -{ -public: - DECLARE_BYTESWAP_DATADESC(); - void SetInvalid() { m_SubNeighbors[0].SetInvalid(); m_SubNeighbors[1].SetInvalid(); } - - // Returns false if there isn't anything touching this edge. - bool IsValid() { return m_SubNeighbors[0].IsValid() || m_SubNeighbors[1].IsValid(); } - - -public: - // Note: if there is a neighbor that fills the whole side (CORNER_TO_CORNER), - // then it will always be in CDispNeighbor::m_Neighbors[0] - CDispSubNeighbor m_SubNeighbors[2]; -}; - - -class CDispCornerNeighbors -{ -public: - DECLARE_BYTESWAP_DATADESC(); - void SetInvalid() { m_nNeighbors = 0; } - - -public: - unsigned short m_Neighbors[MAX_DISP_CORNER_NEIGHBORS]; // indices of neighbors. - unsigned char m_nNeighbors; -}; - - -class CDispVert -{ -public: - DECLARE_BYTESWAP_DATADESC(); - Vector m_vVector; // Vector field defining displacement volume. - float m_flDist; // Displacement distances. - float m_flAlpha; // "per vertex" alpha values. -}; - -#define DISPTRI_TAG_SURFACE (1<<0) -#define DISPTRI_TAG_WALKABLE (1<<1) -#define DISPTRI_TAG_BUILDABLE (1<<2) -#define DISPTRI_FLAG_SURFPROP1 (1<<3) -#define DISPTRI_FLAG_SURFPROP2 (1<<4) - -class CDispTri -{ -public: - DECLARE_BYTESWAP_DATADESC(); - unsigned short m_uiTags; // Displacement triangle tags. -}; - -class ddispinfo_t -{ -public: - DECLARE_BYTESWAP_DATADESC(); - int NumVerts() const { return NUM_DISP_POWER_VERTS(power); } - int NumTris() const { return NUM_DISP_POWER_TRIS(power); } - -public: - Vector startPosition; // start position used for orientation -- (added BSPVERSION 6) - int m_iDispVertStart; // Index into LUMP_DISP_VERTS. - int m_iDispTriStart; // Index into LUMP_DISP_TRIS. - - int power; // power - indicates size of map (2^power + 1) - int minTess; // minimum tesselation allowed - float smoothingAngle; // lighting smoothing angle - int contents; // surface contents - - unsigned short m_iMapFace; // Which map face this displacement comes from. - - int m_iLightmapAlphaStart; // Index into ddisplightmapalpha. - // The count is m_pParent->lightmapTextureSizeInLuxels[0]*m_pParent->lightmapTextureSizeInLuxels[1]. - - int m_iLightmapSamplePositionStart; // Index into LUMP_DISP_LIGHTMAP_SAMPLE_POSITIONS. - - CDispNeighbor m_EdgeNeighbors[4]; // Indexed by NEIGHBOREDGE_ defines. - CDispCornerNeighbors m_CornerNeighbors[4]; // Indexed by CORNER_ defines. - - enum unnamed { ALLOWEDVERTS_SIZE = PAD_NUMBER( MAX_DISPVERTS, 32 ) / 32 }; - unsigned long m_AllowedVerts[ALLOWEDVERTS_SIZE]; // This is built based on the layout and sizes of our neighbors - // and tells us which vertices are allowed to be active. -}; - - -// note that edge 0 is never used, because negative edge nums are used for -// counterclockwise use of the edge in a face -struct dedge_t -{ - DECLARE_BYTESWAP_DATADESC(); - unsigned short v[2]; // vertex numbers -}; - -#define MAXLIGHTMAPS 4 - -enum dprimitive_type -{ - PRIM_TRILIST=0, - PRIM_TRISTRIP=1, -}; - -struct dprimitive_t -{ - DECLARE_BYTESWAP_DATADESC(); - unsigned char type; - unsigned short firstIndex; - unsigned short indexCount; - unsigned short firstVert; - unsigned short vertCount; -}; - -struct dprimvert_t -{ - DECLARE_BYTESWAP_DATADESC(); - Vector pos; -}; - -struct dface_t -{ - DECLARE_BYTESWAP_DATADESC(); - unsigned short planenum; - byte side; // faces opposite to the node's plane direction - byte onNode; // 1 of on node, 0 if in leaf - - int firstedge; // we must support > 64k edges - short numedges; - short texinfo; - // This is a union under the assumption that a fog volume boundary (ie. water surface) - // isn't a displacement map. - // FIXME: These should be made a union with a flags or type field for which one it is - // if we can add more to this. -// union -// { - short dispinfo; - // This is only for surfaces that are the boundaries of fog volumes - // (ie. water surfaces) - // All of the rest of the surfaces can look at their leaf to find out - // what fog volume they are in. - short surfaceFogVolumeID; -// }; - - // lighting info - byte styles[MAXLIGHTMAPS]; - int lightofs; // start of [numstyles*surfsize] samples - float area; - - // TODO: make these unsigned chars? - int m_LightmapTextureMinsInLuxels[2]; - int m_LightmapTextureSizeInLuxels[2]; - - int origFace; // reference the original face this face was derived from - - -public: - - unsigned short GetNumPrims() const; - void SetNumPrims( unsigned short nPrims ); - bool AreDynamicShadowsEnabled(); - void SetDynamicShadowsEnabled( bool bEnabled ); - - // non-polygon primitives (strips and lists) -private: - unsigned short m_NumPrims; // Top bit, if set, disables shadows on this surface (this is why there are accessors). - -public: - unsigned short firstPrimID; - - unsigned int smoothingGroups; -}; - - -inline unsigned short dface_t::GetNumPrims() const -{ - return m_NumPrims & 0x7FFF; -} - -inline void dface_t::SetNumPrims( unsigned short nPrims ) -{ - Assert( (nPrims & 0x8000) == 0 ); - m_NumPrims &= ~0x7FFF; - m_NumPrims |= (nPrims & 0x7FFF); -} - -inline bool dface_t::AreDynamicShadowsEnabled() -{ - return (m_NumPrims & 0x8000) == 0; -} - -inline void dface_t::SetDynamicShadowsEnabled( bool bEnabled ) -{ - if ( bEnabled ) - m_NumPrims &= ~0x8000; - else - m_NumPrims |= 0x8000; -} - -struct dfaceid_t -{ - DECLARE_BYTESWAP_DATADESC(); - unsigned short hammerfaceid; -}; - - -// NOTE: Only 7-bits stored!!! -#define LEAF_FLAGS_SKY 0x01 // This leaf has 3D sky in its PVS -#define LEAF_FLAGS_RADIAL 0x02 // This leaf culled away some portals due to radial vis -#define LEAF_FLAGS_SKY2D 0x04 // This leaf has 2D sky in its PVS - -#if defined( _X360 ) -#pragma bitfield_order( push, lsb_to_msb ) -#endif -#ifdef _MSC_VER -#pragma warning( disable:4201 ) // C4201: nonstandard extension used: nameless struct/union -#endif -struct dleaf_version_0_t -{ - DECLARE_BYTESWAP_DATADESC(); - int contents; // OR of all brushes (not needed?) - - short cluster; - - BEGIN_BITFIELD( bf ); - short area:9; - short flags:7; // Per leaf flags. - END_BITFIELD(); - - short mins[3]; // for frustum culling - short maxs[3]; - - unsigned short firstleafface; - unsigned short numleaffaces; - - unsigned short firstleafbrush; - unsigned short numleafbrushes; - short leafWaterDataID; // -1 for not in water - - // Precaculated light info for entities. - CompressedLightCube m_AmbientLighting; -}; - -// version 1 -struct dleaf_t -{ - DECLARE_BYTESWAP_DATADESC(); - int contents; // OR of all brushes (not needed?) - - short cluster; - - BEGIN_BITFIELD( bf ); - short area:9; - short flags:7; // Per leaf flags. - END_BITFIELD(); - - short mins[3]; // for frustum culling - short maxs[3]; - - unsigned short firstleafface; - unsigned short numleaffaces; - - unsigned short firstleafbrush; - unsigned short numleafbrushes; - short leafWaterDataID; // -1 for not in water - - // NOTE: removed this for version 1 and moved into separate lump "LUMP_LEAF_AMBIENT_LIGHTING" or "LUMP_LEAF_AMBIENT_LIGHTING_HDR" - // Precaculated light info for entities. -// CompressedLightCube m_AmbientLighting; -}; -#ifdef _MSC_VER -#pragma warning( default:4201 ) // C4201: nonstandard extension used: nameless struct/union -#endif -#if defined( _X360 ) -#pragma bitfield_order( pop ) -#endif - -// each leaf contains N samples of the ambient lighting -// each sample contains a cube of ambient light projected on to each axis -// and a sampling position encoded as a 0.8 fraction (mins=0,maxs=255) of the leaf's bounding box -struct dleafambientlighting_t -{ - DECLARE_BYTESWAP_DATADESC(); - CompressedLightCube cube; - byte x; // fixed point fraction of leaf bounds - byte y; // fixed point fraction of leaf bounds - byte z; // fixed point fraction of leaf bounds - byte pad; // unused -}; - -struct dleafambientindex_t -{ - DECLARE_BYTESWAP_DATADESC(); - - unsigned short ambientSampleCount; - unsigned short firstAmbientSample; -}; - -struct dbrushside_t -{ - DECLARE_BYTESWAP_DATADESC(); - unsigned short planenum; // facing out of the leaf - short texinfo; - short dispinfo; // displacement info (BSPVERSION 7) - short bevel; // is the side a bevel plane? (BSPVERSION 7) -}; - -struct dbrush_t -{ - DECLARE_BYTESWAP_DATADESC(); - int firstside; - int numsides; - int contents; -}; - -#define ANGLE_UP -1 -#define ANGLE_DOWN -2 - - -// the visibility lump consists of a header with a count, then -// byte offsets for the PVS and PHS of each cluster, then the raw -// compressed bit vectors -#define DVIS_PVS 0 -#define DVIS_PAS 1 -struct dvis_t -{ - int numclusters; - int bitofs[8][2]; // bitofs[numclusters][2] -}; - -// each area has a list of portals that lead into other areas -// when portals are closed, other areas may not be visible or -// hearable even if the vis info says that it should be -struct dareaportal_t -{ - DECLARE_BYTESWAP_DATADESC(); - unsigned short m_PortalKey; // Entities have a key called portalnumber (and in vbsp a variable - // called areaportalnum) which is used - // to bind them to the area portals by comparing with this value. - - unsigned short otherarea; // The area this portal looks into. - - unsigned short m_FirstClipPortalVert; // Portal geometry. - unsigned short m_nClipPortalVerts; - - int planenum; -}; - - -struct darea_t -{ - DECLARE_BYTESWAP_DATADESC(); - int numareaportals; - int firstareaportal; -}; - -struct dleafwaterdata_t -{ - DECLARE_BYTESWAP_DATADESC(); - float surfaceZ; - float minZ; - short surfaceTexInfoID; -}; - -class CFaceMacroTextureInfo -{ -public: - DECLARE_BYTESWAP_DATADESC(); - // This looks up into g_TexDataStringTable, which looks up into g_TexDataStringData. - // 0xFFFF if the face has no macro texture. - unsigned short m_MacroTextureNameID; -}; - -// lights that were used to illuminate the world -enum emittype_t -{ - emit_surface, // 90 degree spotlight - emit_point, // simple point light source - emit_spotlight, // spotlight with penumbra - emit_skylight, // directional light with no falloff (surface must trace to SKY texture) - emit_quakelight, // linear falloff, non-lambertian - emit_skyambient, // spherical light source with no falloff (surface must trace to SKY texture) -}; - - -// Flags for dworldlight_t::flags -#define DWL_FLAGS_INAMBIENTCUBE 0x0001 // This says that the light was put into the per-leaf ambient cubes. - - -struct dworldlight_t -{ - DECLARE_BYTESWAP_DATADESC(); - Vector origin; - Vector intensity; - Vector normal; // for surfaces and spotlights - int cluster; - emittype_t type; - int style; - float stopdot; // start of penumbra for emit_spotlight - float stopdot2; // end of penumbra for emit_spotlight - float exponent; // - float radius; // cutoff distance - // falloff for emit_spotlight + emit_point: - // 1 / (constant_attn + linear_attn * dist + quadratic_attn * dist^2) - float constant_attn; - float linear_attn; - float quadratic_attn; - int flags; // Uses a combination of the DWL_FLAGS_ defines. - int texinfo; // - int owner; // entity that this light it relative to -}; - -struct dcubemapsample_t -{ - DECLARE_BYTESWAP_DATADESC(); - int origin[3]; // position of light snapped to the nearest integer - // the filename for the vtf file is derived from the position - unsigned char size; // 0 - default - // otherwise, 1<<(size-1) -}; - -#define OVERLAY_BSP_FACE_COUNT 64 - -#define OVERLAY_NUM_RENDER_ORDERS (1<> (16 - OVERLAY_RENDER_ORDER_NUM_BITS)); -} - - -struct doverlayfade_t -{ - DECLARE_BYTESWAP_DATADESC(); - - float flFadeDistMinSq; - float flFadeDistMaxSq; -}; - - -#define WATEROVERLAY_BSP_FACE_COUNT 256 -#define WATEROVERLAY_RENDER_ORDER_NUM_BITS 2 -#define WATEROVERLAY_NUM_RENDER_ORDERS (1<> ( 16 - WATEROVERLAY_RENDER_ORDER_NUM_BITS ) ); -} - -#ifndef _DEF_BYTE_ -#define _DEF_BYTE_ -typedef unsigned char byte; -typedef unsigned short word; -#endif - - -#define ANGLE_UP -1 -#define ANGLE_DOWN -2 - - -//=============== - - -struct epair_t -{ - epair_t *next; - char *key; - char *value; -}; - -// finalized page of surface's lightmaps -#define MAX_LIGHTMAPPAGE_WIDTH 256 -#define MAX_LIGHTMAPPAGE_HEIGHT 128 -typedef struct nameForDatadesc_dlightmappage_t // unnamed structs collide in the datadesc macros -{ - DECLARE_BYTESWAP_DATADESC(); - byte data[MAX_LIGHTMAPPAGE_WIDTH*MAX_LIGHTMAPPAGE_HEIGHT]; - byte palette[256*4]; -} dlightmappage_t; - -typedef struct nameForDatadesc_dlightmappageinfo_t // unnamed structs collide in the datadesc macros -{ - DECLARE_BYTESWAP_DATADESC(); - byte page; // lightmap page [0..?] - byte offset[2]; // offset into page (s,t) - byte pad; // unused - ColorRGBExp32 avgColor; // average used for runtime lighting calcs -} dlightmappageinfo_t; - -#endif // BSPFILE_H diff --git a/public/bspflags.h b/public/bspflags.h deleted file mode 100644 index c02961aab..000000000 --- a/public/bspflags.h +++ /dev/null @@ -1,149 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef BSPFLAGS_H -#define BSPFLAGS_H - -#ifdef _WIN32 -#pragma once -#endif - -// contents flags are seperate bits -// a given brush can contribute multiple content bits -// multiple brushes can be in a single leaf - -// these definitions also need to be in q_shared.h! - -// lower bits are stronger, and will eat weaker brushes completely -#define CONTENTS_EMPTY 0 // No contents - -#define CONTENTS_SOLID 0x1 // an eye is never valid in a solid -#define CONTENTS_WINDOW 0x2 // translucent, but not watery (glass) -#define CONTENTS_AUX 0x4 -#define CONTENTS_GRATE 0x8 // alpha-tested "grate" textures. Bullets/sight pass through, but solids don't -#define CONTENTS_SLIME 0x10 -#define CONTENTS_WATER 0x20 -#define CONTENTS_BLOCKLOS 0x40 // block AI line of sight -#define CONTENTS_OPAQUE 0x80 // things that cannot be seen through (may be non-solid though) -#define LAST_VISIBLE_CONTENTS 0x80 - -#define ALL_VISIBLE_CONTENTS (LAST_VISIBLE_CONTENTS | (LAST_VISIBLE_CONTENTS-1)) - -#define CONTENTS_TESTFOGVOLUME 0x100 -#define CONTENTS_UNUSED 0x200 - -// unused -// NOTE: If it's visible, grab from the top + update LAST_VISIBLE_CONTENTS -// if not visible, then grab from the bottom. -#define CONTENTS_UNUSED6 0x400 - -#define CONTENTS_TEAM1 0x800 // per team contents used to differentiate collisions -#define CONTENTS_TEAM2 0x1000 // between players and objects on different teams - -// ignore CONTENTS_OPAQUE on surfaces that have SURF_NODRAW -#define CONTENTS_IGNORE_NODRAW_OPAQUE 0x2000 - -// hits entities which are MOVETYPE_PUSH (doors, plats, etc.) -#define CONTENTS_MOVEABLE 0x4000 - -// remaining contents are non-visible, and don't eat brushes -#define CONTENTS_AREAPORTAL 0x8000 - -#define CONTENTS_PLAYERCLIP 0x10000 -#define CONTENTS_MONSTERCLIP 0x20000 - -// currents can be added to any other contents, and may be mixed -#define CONTENTS_CURRENT_0 0x40000 -#define CONTENTS_CURRENT_90 0x80000 -#define CONTENTS_CURRENT_180 0x100000 -#define CONTENTS_CURRENT_270 0x200000 -#define CONTENTS_CURRENT_UP 0x400000 -#define CONTENTS_CURRENT_DOWN 0x800000 - -#define CONTENTS_ORIGIN 0x1000000 // removed before bsping an entity - -#define CONTENTS_MONSTER 0x2000000 // should never be on a brush, only in game -#define CONTENTS_DEBRIS 0x4000000 -#define CONTENTS_DETAIL 0x8000000 // brushes to be added after vis leafs -#define CONTENTS_TRANSLUCENT 0x10000000 // auto set if any surface has trans -#define CONTENTS_LADDER 0x20000000 -#define CONTENTS_HITBOX 0x40000000 // use accurate hitboxes on trace - - -// NOTE: These are stored in a short in the engine now. Don't use more than 16 bits -#define SURF_LIGHT 0x0001 // value will hold the light strength -#define SURF_SKY2D 0x0002 // don't draw, indicates we should skylight + draw 2d sky but not draw the 3D skybox -#define SURF_SKY 0x0004 // don't draw, but add to skybox -#define SURF_WARP 0x0008 // turbulent water warp -#define SURF_TRANS 0x0010 -#define SURF_NOPORTAL 0x0020 // the surface can not have a portal placed on it -#define SURF_TRIGGER 0x0040 // FIXME: This is an xbox hack to work around elimination of trigger surfaces, which breaks occluders -#define SURF_NODRAW 0x0080 // don't bother referencing the texture - -#define SURF_HINT 0x0100 // make a primary bsp splitter - -#define SURF_SKIP 0x0200 // completely ignore, allowing non-closed brushes -#define SURF_NOLIGHT 0x0400 // Don't calculate light -#define SURF_BUMPLIGHT 0x0800 // calculate three lightmaps for the surface for bumpmapping -#define SURF_NOSHADOWS 0x1000 // Don't receive shadows -#define SURF_NODECALS 0x2000 // Don't receive decals -#define SURF_NOCHOP 0x4000 // Don't subdivide patches on this surface -#define SURF_HITBOX 0x8000 // surface is part of a hitbox - - - -// ----------------------------------------------------- -// spatial content masks - used for spatial queries (traceline,etc.) -// ----------------------------------------------------- -#define MASK_ALL (0xFFFFFFFF) -// everything that is normally solid -#define MASK_SOLID (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE) -// everything that blocks player movement -#define MASK_PLAYERSOLID (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE) -// blocks npc movement -#define MASK_NPCSOLID (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTERCLIP|CONTENTS_WINDOW|CONTENTS_MONSTER|CONTENTS_GRATE) -// water physics in these contents -#define MASK_WATER (CONTENTS_WATER|CONTENTS_MOVEABLE|CONTENTS_SLIME) -// everything that blocks lighting -#define MASK_OPAQUE (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_OPAQUE) -// everything that blocks lighting, but with monsters added. -#define MASK_OPAQUE_AND_NPCS (MASK_OPAQUE|CONTENTS_MONSTER) -// everything that blocks line of sight for AI -#define MASK_BLOCKLOS (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_BLOCKLOS) -// everything that blocks line of sight for AI plus NPCs -#define MASK_BLOCKLOS_AND_NPCS (MASK_BLOCKLOS|CONTENTS_MONSTER) -// everything that blocks line of sight for players -#define MASK_VISIBLE (MASK_OPAQUE|CONTENTS_IGNORE_NODRAW_OPAQUE) -// everything that blocks line of sight for players, but with monsters added. -#define MASK_VISIBLE_AND_NPCS (MASK_OPAQUE_AND_NPCS|CONTENTS_IGNORE_NODRAW_OPAQUE) -// bullets see these as solid -#define MASK_SHOT (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTER|CONTENTS_WINDOW|CONTENTS_DEBRIS|CONTENTS_HITBOX) -// non-raycasted weapons see this as solid (includes grates) -#define MASK_SHOT_HULL (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_MONSTER|CONTENTS_WINDOW|CONTENTS_DEBRIS|CONTENTS_GRATE) -// hits solids (not grates) and passes through everything else -#define MASK_SHOT_PORTAL (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_MONSTER) -// everything normally solid, except monsters (world+brush only) -#define MASK_SOLID_BRUSHONLY (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_GRATE) -// everything normally solid for player movement, except monsters (world+brush only) -#define MASK_PLAYERSOLID_BRUSHONLY (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_PLAYERCLIP|CONTENTS_GRATE) -// everything normally solid for npc movement, except monsters (world+brush only) -#define MASK_NPCSOLID_BRUSHONLY (CONTENTS_SOLID|CONTENTS_MOVEABLE|CONTENTS_WINDOW|CONTENTS_MONSTERCLIP|CONTENTS_GRATE) -// just the world, used for route rebuilding -#define MASK_NPCWORLDSTATIC (CONTENTS_SOLID|CONTENTS_WINDOW|CONTENTS_MONSTERCLIP|CONTENTS_GRATE) -// These are things that can split areaportals -#define MASK_SPLITAREAPORTAL (CONTENTS_WATER|CONTENTS_SLIME) - -// UNDONE: This is untested, any moving water -#define MASK_CURRENT (CONTENTS_CURRENT_0|CONTENTS_CURRENT_90|CONTENTS_CURRENT_180|CONTENTS_CURRENT_270|CONTENTS_CURRENT_UP|CONTENTS_CURRENT_DOWN) - -// everything that blocks corpse movement -// UNDONE: Not used yet / may be deleted -#define MASK_DEADSOLID (CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_WINDOW|CONTENTS_GRATE) - -#endif // BSPFLAGS_H diff --git a/public/bsptreedata.cpp b/public/bsptreedata.cpp deleted file mode 100644 index 1a287e6d0..000000000 --- a/public/bsptreedata.cpp +++ /dev/null @@ -1,352 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Revision: $ -// $NoKeywords: $ -// -// The BSP tree leaf data system -// -//=============================================================================// - -#include "basetypes.h" -#include "bsptreedata.h" -#include "utllinkedlist.h" -#include "utlvector.h" -#include "tier0/dbg.h" -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// The BSP tree leaf data system -//----------------------------------------------------------------------------- -class CBSPTreeData : public IBSPTreeData, public ISpatialLeafEnumerator -{ -public: - // constructor, destructor - CBSPTreeData(); - virtual ~CBSPTreeData(); - - // Methods of IBSPTreeData - void Init( ISpatialQuery* pBSPTree ); - void Shutdown(); - - BSPTreeDataHandle_t Insert( int userId, Vector const& mins, Vector const& maxs ); - void Remove( BSPTreeDataHandle_t handle ); - void ElementMoved( BSPTreeDataHandle_t handle, Vector const& mins, Vector const& maxs ); - - // Enumerate elements in a particular leaf - bool EnumerateElementsInLeaf( int leaf, IBSPTreeDataEnumerator* pEnum, int context ); - - // For convenience, enumerates the leaves along a ray, box, etc. - bool EnumerateLeavesAtPoint( Vector const& pt, ISpatialLeafEnumerator* pEnum, int context ); - bool EnumerateLeavesInBox( Vector const& mins, Vector const& maxs, ISpatialLeafEnumerator* pEnum, int context ); - bool EnumerateLeavesInSphere( Vector const& center, float radius, ISpatialLeafEnumerator* pEnum, int context ); - bool EnumerateLeavesAlongRay( Ray_t const& ray, ISpatialLeafEnumerator* pEnum, int context ); - - // methods of IBSPLeafEnumerator - bool EnumerateLeaf( int leaf, int context ); - - // Is the element in any leaves at all? - bool IsElementInTree( BSPTreeDataHandle_t handle ) const; - -private: - // Creates a new handle - BSPTreeDataHandle_t NewHandle( int userId ); - - // Adds a handle to the list of handles - void AddHandleToLeaf( int leaf, BSPTreeDataHandle_t handle ); - - // insert, remove handles from leaves - void InsertIntoTree( BSPTreeDataHandle_t handle, Vector const& mins, Vector const& maxs ); - void RemoveFromTree( BSPTreeDataHandle_t handle ); - - // Returns the number of elements in a leaf - int CountElementsInLeaf( int leaf ); - -private: - // All the information associated with a particular handle - struct HandleInfo_t - { - int m_UserId; // Client-defined id - unsigned short m_LeafList; // What leafs is it in? - }; - - // The leaf contains an index into a list of elements - struct Leaf_t - { - unsigned short m_FirstElement; - }; - - // The handle knows about the leaves it lies in - struct HandleInLeaf_t - { - int m_Leaf; // what leaf is the handle in? - unsigned short m_LeafElementIndex; // what's the m_LeafElements index of the entry? - }; - - // Stores data associated with each leaf. - CUtlVector< Leaf_t > m_Leaf; - - // Stores all unique handles - CUtlLinkedList< HandleInfo_t, unsigned short > m_Handles; - - // Maintains the list of all handles in a particular leaf - CUtlLinkedList< BSPTreeDataHandle_t, unsigned short, true > m_LeafElements; - - // Maintains the list of all leaves a particular handle spans - CUtlLinkedList< HandleInLeaf_t, unsigned short, true > m_HandleLeafList; - - // Interface to BSP tree - ISpatialQuery* m_pBSPTree; -}; - - -//----------------------------------------------------------------------------- -// Class factory -//----------------------------------------------------------------------------- - -IBSPTreeData* CreateBSPTreeData() -{ - return new CBSPTreeData; -} - -void DestroyBSPTreeData( IBSPTreeData* pTreeData ) -{ - if (pTreeData) - delete pTreeData; -} - - -//----------------------------------------------------------------------------- -// constructor, destructor -//----------------------------------------------------------------------------- - -CBSPTreeData::CBSPTreeData() -{ -} - -CBSPTreeData::~CBSPTreeData() -{ -} - - -//----------------------------------------------------------------------------- -// Level init, shutdown -//----------------------------------------------------------------------------- - -void CBSPTreeData::Init( ISpatialQuery* pBSPTree ) -{ - Assert( pBSPTree ); - m_pBSPTree = pBSPTree; - - m_Handles.EnsureCapacity( 1024 ); - m_LeafElements.EnsureCapacity( 1024 ); - m_HandleLeafList.EnsureCapacity( 1024 ); - - // Add all the leaves we'll need - int leafCount = m_pBSPTree->LeafCount(); - m_Leaf.EnsureCapacity( leafCount ); - - Leaf_t newLeaf; - newLeaf.m_FirstElement = m_LeafElements.InvalidIndex(); - while ( --leafCount >= 0 ) - { - m_Leaf.AddToTail( newLeaf ); - } -} - -void CBSPTreeData::Shutdown() -{ - m_Handles.Purge(); - m_LeafElements.Purge(); - m_HandleLeafList.Purge(); - m_Leaf.Purge(); -} - - -//----------------------------------------------------------------------------- -// Creates a new handle -//----------------------------------------------------------------------------- - -BSPTreeDataHandle_t CBSPTreeData::NewHandle( int userId ) -{ - BSPTreeDataHandle_t handle = m_Handles.AddToTail(); - m_Handles[handle].m_UserId = userId; - m_Handles[handle].m_LeafList = m_HandleLeafList.InvalidIndex(); - - return handle; -} - -//----------------------------------------------------------------------------- -// Add/remove handle -//----------------------------------------------------------------------------- - -BSPTreeDataHandle_t CBSPTreeData::Insert( int userId, Vector const& mins, Vector const& maxs ) -{ - BSPTreeDataHandle_t handle = NewHandle( userId ); - InsertIntoTree( handle, mins, maxs ); - return handle; -} - -void CBSPTreeData::Remove( BSPTreeDataHandle_t handle ) -{ - if (!m_Handles.IsValidIndex(handle)) - return; - - RemoveFromTree( handle ); - m_Handles.Free( handle ); -} - - -//----------------------------------------------------------------------------- -// Adds a handle to a leaf -//----------------------------------------------------------------------------- -void CBSPTreeData::AddHandleToLeaf( int leaf, BSPTreeDataHandle_t handle ) -{ - // Got to a leaf baby! Add the handle to the leaf's list of elements - unsigned short leafElement = m_LeafElements.Alloc( true ); - if (m_Leaf[leaf].m_FirstElement != m_LeafElements.InvalidIndex() ) - m_LeafElements.LinkBefore( m_Leaf[leaf].m_FirstElement, leafElement ); - m_Leaf[leaf].m_FirstElement = leafElement; - m_LeafElements[leafElement] = handle; - - // Insert the leaf into the handles's list of leaves - unsigned short handleElement = m_HandleLeafList.Alloc( true ); - if (m_Handles[handle].m_LeafList != m_HandleLeafList.InvalidIndex() ) - m_HandleLeafList.LinkBefore( m_Handles[handle].m_LeafList, handleElement ); - m_Handles[handle].m_LeafList = handleElement; - m_HandleLeafList[handleElement].m_Leaf = leaf; - m_HandleLeafList[handleElement].m_LeafElementIndex = leafElement; -} - - -//----------------------------------------------------------------------------- -// Inserts an element into the tree -//----------------------------------------------------------------------------- -bool CBSPTreeData::EnumerateLeaf( int leaf, int context ) -{ - BSPTreeDataHandle_t handle = (BSPTreeDataHandle_t)context; - AddHandleToLeaf( leaf, handle ); - return true; -} - -void CBSPTreeData::InsertIntoTree( BSPTreeDataHandle_t handle, Vector const& mins, Vector const& maxs ) -{ - m_pBSPTree->EnumerateLeavesInBox( mins, maxs, this, handle ); -} - -//----------------------------------------------------------------------------- -// Removes an element from the tree -//----------------------------------------------------------------------------- - -void CBSPTreeData::RemoveFromTree( BSPTreeDataHandle_t handle ) -{ - // Iterate over the list of all leaves the handle is in - unsigned short i = m_Handles[handle].m_LeafList; - while (i != m_HandleLeafList.InvalidIndex()) - { - int leaf = m_HandleLeafList[i].m_Leaf; - unsigned short leafElement = m_HandleLeafList[i].m_LeafElementIndex; - - // Unhook the handle from the leaf handle list - if (leafElement == m_Leaf[leaf].m_FirstElement) - m_Leaf[leaf].m_FirstElement = m_LeafElements.Next(leafElement); - m_LeafElements.Free(leafElement); - - unsigned short prevNode = i; - i = m_HandleLeafList.Next(i); - m_HandleLeafList.Free(prevNode); - } - - m_Handles[handle].m_LeafList = m_HandleLeafList.InvalidIndex(); -} - - -//----------------------------------------------------------------------------- -// Call this when the element moves -//----------------------------------------------------------------------------- -void CBSPTreeData::ElementMoved( BSPTreeDataHandle_t handle, Vector const& mins, Vector const& maxs ) -{ - if (handle != TREEDATA_INVALID_HANDLE) - { - RemoveFromTree( handle ); - InsertIntoTree( handle, mins, maxs ); - } -} - - -//----------------------------------------------------------------------------- -// Is the element in any leaves at all? -//----------------------------------------------------------------------------- -bool CBSPTreeData::IsElementInTree( BSPTreeDataHandle_t handle ) const -{ - return m_Handles[handle].m_LeafList != m_HandleLeafList.InvalidIndex(); -} - - -//----------------------------------------------------------------------------- -// Enumerate elements in a particular leaf -//----------------------------------------------------------------------------- -int CBSPTreeData::CountElementsInLeaf( int leaf ) -{ - int i; - int nCount = 0; - for( i = m_Leaf[leaf].m_FirstElement; i != m_LeafElements.InvalidIndex(); i = m_LeafElements.Next(i) ) - { - ++nCount; - } - - return nCount; -} - -//----------------------------------------------------------------------------- -// Enumerate elements in a particular leaf -//----------------------------------------------------------------------------- -bool CBSPTreeData::EnumerateElementsInLeaf( int leaf, IBSPTreeDataEnumerator* pEnum, int context ) -{ -#ifdef _DEBUG - // The enumeration method better damn well not change this list... - int nCount = CountElementsInLeaf(leaf); -#endif - - unsigned short idx = m_Leaf[leaf].m_FirstElement; - while (idx != m_LeafElements.InvalidIndex()) - { - BSPTreeDataHandle_t handle = m_LeafElements[idx]; - if (!pEnum->EnumerateElement( m_Handles[handle].m_UserId, context )) - { - Assert( CountElementsInLeaf(leaf) == nCount ); - return false; - } - idx = m_LeafElements.Next(idx); - } - - Assert( CountElementsInLeaf(leaf) == nCount ); - - return true; -} - - -//----------------------------------------------------------------------------- -// For convenience, enumerates the leaves along a ray, box, etc. -//----------------------------------------------------------------------------- -bool CBSPTreeData::EnumerateLeavesAtPoint( Vector const& pt, ISpatialLeafEnumerator* pEnum, int context ) -{ - return m_pBSPTree->EnumerateLeavesAtPoint( pt, pEnum, context ); -} - -bool CBSPTreeData::EnumerateLeavesInBox( Vector const& mins, Vector const& maxs, ISpatialLeafEnumerator* pEnum, int context ) -{ - return m_pBSPTree->EnumerateLeavesInBox( mins, maxs, pEnum, context ); -} - -bool CBSPTreeData::EnumerateLeavesInSphere( Vector const& center, float radius, ISpatialLeafEnumerator* pEnum, int context ) -{ - return m_pBSPTree->EnumerateLeavesInSphere( center, radius, pEnum, context ); -} - -bool CBSPTreeData::EnumerateLeavesAlongRay( Ray_t const& ray, ISpatialLeafEnumerator* pEnum, int context ) -{ - return m_pBSPTree->EnumerateLeavesAlongRay( ray, pEnum, context ); -} - diff --git a/public/bsptreedata.h b/public/bsptreedata.h deleted file mode 100644 index e6849d737..000000000 --- a/public/bsptreedata.h +++ /dev/null @@ -1,132 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Revision: $ -// $NoKeywords: $ -// -// The BSP tree leaf data system -// -//=============================================================================// - -#include "tier0/platform.h" - -#if !defined( BSPTREEDATA ) -#define BSPTREEDATA -#ifdef _WIN32 -#pragma once -#endif - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- - -class Vector; -struct Ray_t; - - -//----------------------------------------------------------------------------- -// Handle to an renderable in the client leaf system -//----------------------------------------------------------------------------- - -typedef unsigned short BSPTreeDataHandle_t; - -enum -{ - TREEDATA_INVALID_HANDLE = (BSPTreeDataHandle_t)~0 -}; - - -//----------------------------------------------------------------------------- -// Interface needed by tree data to do its job -// -// Note that anything that has convex spatial regions with leaves identified -// by indices can implement the ISpatialQuery. All you have to do is to implement -// a class that can answer the 5 questions in the Query interface about the -// spatial subdivision. For example, a K-D tree or a BSP tree could implement -// this interface -// -//----------------------------------------------------------------------------- - -abstract_class ISpatialLeafEnumerator -{ -public: - // call back with a leaf and a context - // The context is completely user defined; it's passed into the enumeration - // function of ISpatialQuery. - // This gets called by the enumeration methods with each leaf - // that passes the test; return true to continue enumerating, - // false to stop - - virtual bool EnumerateLeaf( int leaf, int context ) = 0; -}; - -abstract_class ISpatialQuery -{ -public: - // Returns the number of leaves - virtual int LeafCount() const = 0; - - // Enumerates the leaves along a ray, box, etc. - virtual bool EnumerateLeavesAtPoint( Vector const& pt, ISpatialLeafEnumerator* pEnum, int context ) = 0; - virtual bool EnumerateLeavesInBox( Vector const& mins, Vector const& maxs, ISpatialLeafEnumerator* pEnum, int context ) = 0; - virtual bool EnumerateLeavesInSphere( Vector const& center, float radius, ISpatialLeafEnumerator* pEnum, int context ) = 0; - virtual bool EnumerateLeavesAlongRay( Ray_t const& ray, ISpatialLeafEnumerator* pEnum, int context ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Data associated with leaves. -// -// This is a parasitic class that attaches data to the leaves specified by the -// ISpatialQuery sent in to the initialization function. It can't exist without -// a spatial partition of some sort to hold onto. -//----------------------------------------------------------------------------- - -abstract_class IBSPTreeDataEnumerator -{ -public: - // call back with a userId and a context - virtual bool FASTCALL EnumerateElement( int userId, int context ) = 0; -}; - -abstract_class IBSPTreeData -{ -public: - // Initializes, shuts down - virtual void Init( ISpatialQuery* pBSPTree ) = 0; - virtual void Shutdown() = 0; - - // Adds and removes data from the leaf lists - virtual BSPTreeDataHandle_t Insert( int userId, Vector const& mins, Vector const& maxs ) = 0; - virtual void Remove( BSPTreeDataHandle_t handle ) = 0; - - // Call this when a element moves - virtual void ElementMoved( BSPTreeDataHandle_t handle, Vector const& mins, Vector const& maxs ) = 0; - - // Enumerate elements in a particular leaf - virtual bool EnumerateElementsInLeaf( int leaf, IBSPTreeDataEnumerator* pEnum, int context ) = 0; - - // Is the element in any leaves at all? - virtual bool IsElementInTree( BSPTreeDataHandle_t handle ) const = 0; - - // NOTE: These methods call through to the functions in the attached - // ISpatialQuery - // For convenience, enumerates the leaves along a ray, box, etc. - virtual bool EnumerateLeavesAtPoint( Vector const& pt, ISpatialLeafEnumerator* pEnum, int context ) = 0; - virtual bool EnumerateLeavesInBox( Vector const& mins, Vector const& maxs, ISpatialLeafEnumerator* pEnum, int context ) = 0; - virtual bool EnumerateLeavesInSphere( Vector const& center, float radius, ISpatialLeafEnumerator* pEnum, int context ) = 0; - virtual bool EnumerateLeavesAlongRay( Ray_t const& ray, ISpatialLeafEnumerator* pEnum, int context ) = 0; -}; - -//----------------------------------------------------------------------------- -// Class factory -//----------------------------------------------------------------------------- - -IBSPTreeData* CreateBSPTreeData(); -void DestroyBSPTreeData( IBSPTreeData* pTreeData ); - - -#endif // BSPTREEDATA - - diff --git a/public/builddisp.cpp b/public/builddisp.cpp deleted file mode 100644 index 22c563856..000000000 --- a/public/builddisp.cpp +++ /dev/null @@ -1,3108 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -//#include -#include -#include -#include "builddisp.h" -#include "collisionutils.h" -#include "tier1/strtools.h" -#include "tier0/dbg.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// -// Node Functions (friend functions) -// - -//----------------------------------------------------------------------------- -// should make this more programatic and extensible! -//----------------------------------------------------------------------------- -int GetNodeLevel( int index ) -{ - // root - if( index == 0 ) - return 1; - - // [1...4] - if( index < 5 ) - return 2; - - // [5....20] - if( index < 21 ) - return 3; - - // [21....84] - if( index < 85 ) - return 4; - - // error!!! - return -1; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int GetNodeCount( int power ) -{ - return ( ( 1 << ( power << 1 ) ) / 3 ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int GetNodeParent( int index ) -{ - // ( index - 1 ) / 4 - return ( ( index - 1 ) >> 2 ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int GetNodeChild( int power, int index, int direction ) -{ - // ( index * 4 ) + direction - return ( ( index << 2 ) + ( direction - 3 ) ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int GetNodeMinNodeAtLevel( int level ) -{ - switch( level ) - { - case 1: return 0; - case 2: return 1; - case 3: return 5; - case 4: return 21; - default: return -99999; - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void GetComponentsFromNodeIndex( int index, int *x, int *y ) -{ - *x = 0; - *y = 0; - - for( int shift = 0; index != 0; shift++ ) - { - *x |= ( index & 1 ) << shift; - index >>= 1; - - *y |= ( index & 1 ) << shift; - index >>= 1; - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int GetNodeIndexFromComponents( int x, int y ) -{ - int index = 0; - - // Interleave bits from the x and y values to create the index: - - int shift; - for( shift = 0; x != 0; shift += 2, x >>= 1 ) - { - index |= ( x & 1 ) << shift; - } - - for( shift = 1; y != 0; shift += 2, y >>= 1 ) - { - index |= ( y & 1 ) << shift; - } - - return index; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CalcBarycentricCooefs( Vector const &v0, Vector const &v1, Vector const &v2, - Vector const &pt, float &c0, float &c1, float &c2 ) -{ - Vector vSeg0, vSeg1, vCross; - vSeg0 = v1 - v0; - vSeg1 = v2 - v0; - - // get the area of the triangle - vCross = vSeg0.Cross( vSeg1 ); - float totalArea = vCross.Length() * 0.5f; - float ooTotalArea = totalArea ? 1.0f / totalArea : 0.0f; - - // get the area for cooeficient 0 (pt, v1, v2) - vSeg0 = v1 - pt; - vSeg1 = v2 - pt; - vCross = vSeg0.Cross( vSeg1 ); - float subArea = vCross.Length() * 0.5f; - c0 = subArea * ooTotalArea; - - // get the area for cooeficient 1 (v0, pt, v2) - vSeg0 = v2 - pt; - vSeg1 = v0 - pt; - vCross = vSeg0.Cross( vSeg1 ); - subArea = vCross.Length() * 0.5f; - c1 = subArea * ooTotalArea; - - // get the area for cooeficient 2 (v0, v1, pt) - vSeg0 = v0 - pt; - vSeg1 = v1 - pt; - vCross = vSeg0.Cross( vSeg1 ); - subArea = vCross.Length() * 0.5f; - c2 = subArea * ooTotalArea; - - float cTotal = c0 + c1 + c2; - if ( FloatMakePositive( 1.0f - cTotal ) < 1e-3 ) - return true; - - return false; -} - -// For some reason, the global optimizer screws up the recursion here. disable the global optimizations to fix this. -// IN VC++ 6.0 -#pragma optimize( "g", off ) - -CCoreDispSurface::CCoreDispSurface() -{ - Init(); -} - - -//============================================================================= -// -// CDispSurface Functions -// - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispSurface::Init( void ) -{ - m_Index = -1; - - m_PointCount = 0; - int i; - for( i = 0; i < QUAD_POINT_COUNT; i++ ) - { - VectorClear( m_Points[i] ); - VectorClear( m_Normals[i] ); - Vector2DClear( m_TexCoords[i] ); - - for( int j = 0; j < NUM_BUMP_VECTS+1; j++ ) - { - Vector2DClear( m_LuxelCoords[i][j] ); - } - - m_Alphas[i] = 1.0f; - } - - m_PointStartIndex = -1; - VectorClear( m_PointStart ); - VectorClear( sAxis ); - VectorClear( tAxis ); - - for( i = 0; i < 4; i++ ) - { - m_EdgeNeighbors[i].SetInvalid(); - m_CornerNeighbors[i].SetInvalid(); - } - - m_Flags = 0; - m_Contents = 0; -} - - -void CCoreDispSurface::SetNeighborData( const CDispNeighbor edgeNeighbors[4], const CDispCornerNeighbors cornerNeighbors[4] ) -{ - for ( int i=0; i < 4; i++ ) - { - m_EdgeNeighbors[i] = edgeNeighbors[i]; - m_CornerNeighbors[i] = cornerNeighbors[i]; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispSurface::GeneratePointStartIndexFromMappingAxes( Vector const &sAxis, Vector const &tAxis ) -{ - if( m_PointStartIndex != -1 ) - return; - - int numIndices = 0; - int indices[4]; - int offsetIndex; - - // - // project all points on to the v-axis first and find the minimum - // - float minValue = DotProduct( tAxis, m_Points[0] ); - indices[numIndices] = 0; - numIndices++; - - int i; - for( i = 1; i < m_PointCount; i++ ) - { - float value = DotProduct( tAxis, m_Points[i] ); - float delta = ( value - minValue ); - delta = FloatMakePositive( delta ); - if( delta < 0.1 ) - { - indices[numIndices] = i; - numIndices++; - } - else if( value < minValue ) - { - minValue = value; - indices[0] = i; - numIndices = 1; - } - } - - // - // break ties with the u-axis projection - // - minValue = DotProduct( sAxis, m_Points[indices[0]] ); - offsetIndex = indices[0]; - - for( i = 1; i < numIndices; i++ ) - { - float value = DotProduct( sAxis, m_Points[indices[i]] ); - if( ( value < minValue ) ) - { - minValue = value; - offsetIndex = indices[i]; - } - } - - m_PointStartIndex = offsetIndex; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CCoreDispSurface::GenerateSurfPointStartIndex( void ) -{ - // - // get the minimum surface component values - // - Vector bMin; - VectorFill( bMin, 99999.0f ); - - int i; - for( i = 0; i < QUAD_POINT_COUNT; i++ ) - { - for( int j = 0; j < 3; j++ ) - { - if( m_Points[i][j] < bMin[j] ) - { - bMin[j] = m_Points[i][j]; - } - } - } - - // - // find the point closest to the minimum, that is the start point - // - int minIndex = -1; - float minDistance = 999999999.0f; - for( i = 0; i < QUAD_POINT_COUNT; i++ ) - { - Vector segment; - segment = m_Points[i] - bMin; - float distanceSq = segment.LengthSqr(); - if( distanceSq < minDistance ) - { - minDistance = distanceSq; - minIndex = i; - } - } - - m_PointStartIndex = minIndex; - - return minIndex; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CCoreDispSurface::FindSurfPointStartIndex( void ) -{ - if( m_PointStartIndex != -1 ) - return m_PointStartIndex; - - int minIndex = -1; - float minDistance = 999999999.0f; - - for( int i = 0; i < QUAD_POINT_COUNT; i++ ) - { - Vector segment; - VectorSubtract( m_PointStart, m_Points[i], segment ); - float distanceSq = segment.LengthSqr(); - if( distanceSq < minDistance ) - { - minDistance = distanceSq; - minIndex = i; - } - } - - m_PointStartIndex = minIndex; - - return minIndex; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispSurface::AdjustSurfPointData( void ) -{ - Vector tmpPoints[4]; - Vector tmpNormals[4]; - Vector2D tmpTexCoords[4]; - float tmpAlphas[4]; - - int i; - for( i = 0; i < QUAD_POINT_COUNT; i++ ) - { - VectorCopy( m_Points[i], tmpPoints[i] ); - VectorCopy( m_Normals[i], tmpNormals[i] ); - Vector2DCopy( m_TexCoords[i], tmpTexCoords[i] ); - - tmpAlphas[i] = m_Alphas[i]; - } - - for( i = 0; i < QUAD_POINT_COUNT; i++ ) - { - VectorCopy( tmpPoints[(i+m_PointStartIndex)%4], m_Points[i] ); - VectorCopy( tmpNormals[(i+m_PointStartIndex)%4], m_Normals[i] ); - Vector2DCopy( tmpTexCoords[(i+m_PointStartIndex)%4], m_TexCoords[i] ); - - m_Alphas[i] = tmpAlphas[i]; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CCoreDispSurface::LongestInU( const Vector &vecU, const Vector &vecV ) -{ - Vector vecNormU = vecU; - Vector vecNormV = vecV; - VectorNormalize( vecNormU ); - VectorNormalize( vecNormV ); - - float flDistU[4]; - float flDistV[4]; - for ( int iPoint = 0; iPoint < 4; ++iPoint ) - { - flDistU[iPoint] = vecNormU.Dot( m_Points[iPoint] ); - flDistV[iPoint] = vecNormV.Dot( m_Points[iPoint] ); - } - - float flULength = 0.0f; - float flVLength = 0.0f; - for ( int iPoint = 0; iPoint < 4; ++iPoint ) - { - float flTestDist = fabs( flDistU[(iPoint+1)%4] - flDistU[iPoint] ); - if ( flTestDist > flULength ) - { - flULength = flTestDist; - } - - flTestDist = fabs( flDistV[(iPoint+1)%4] - flDistV[iPoint] ); - if ( flTestDist > flVLength ) - { - flVLength = flTestDist; - } - } - - if ( flULength < flVLength ) - { - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : - -//----------------------------------------------------------------------------- -bool CCoreDispSurface::CalcLuxelCoords( int nLuxels, bool bAdjust, const Vector &vecU, const Vector &vecV ) -{ - // Valid value? - if ( nLuxels <= 0.0f ) - return false; - - // Get the start point offset. - int iOffset = 0; - if ( bAdjust ) - { - iOffset = GetPointStartIndex(); - } - - // Does projecting along U or V create the longest edge? - bool bLongU = LongestInU( vecU, vecV ); - - float flLengthTemp = 0.0f; - float flULength = ( m_Points[(3+iOffset)%4] - m_Points[(0+iOffset)%4] ).Length(); - flLengthTemp = ( m_Points[(2+iOffset)%4] - m_Points[(1+iOffset)%4] ).Length(); - if ( flLengthTemp > flULength ) - { - flULength = flLengthTemp; - } - - // Find the largest edge in V. - float flVLength = ( m_Points[(1+iOffset)%4] - m_Points[(0+iOffset)%4] ).Length(); - flLengthTemp = ( m_Points[(2+iOffset)%4] - m_Points[(3+iOffset)%4] ).Length(); - if ( flLengthTemp > flVLength ) - { - flVLength = flLengthTemp; - } - - float flOOLuxelScale = 1.0f / static_cast( nLuxels ); - float flUValue = static_cast( static_cast( flULength * flOOLuxelScale ) + 1 ); - if ( flUValue > MAX_DISP_LIGHTMAP_DIM_WITHOUT_BORDER ) - { - flUValue = MAX_DISP_LIGHTMAP_DIM_WITHOUT_BORDER; - } - - float flVValue = static_cast( static_cast( flVLength * flOOLuxelScale ) + 1 ); - if ( flVValue > MAX_DISP_LIGHTMAP_DIM_WITHOUT_BORDER ) - { - flVValue = MAX_DISP_LIGHTMAP_DIM_WITHOUT_BORDER; - } - - // Swap if necessary. - bool bSwapped = false; - if ( bLongU ) - { - if ( flVValue > flUValue ) - { - bSwapped = true; - } - } - else - { - if ( flUValue > flVValue ) - { - bSwapped = true; - } - } - - m_nLuxelU = static_cast( flUValue ); - m_nLuxelV = static_cast( flVValue ); - - // Generate luxel coordinates. - for( int iBump = 0; iBump < NUM_BUMP_VECTS+1; ++iBump ) - { - m_LuxelCoords[iBump][(0+iOffset)%4].Init( 0.5f, 0.5f ); - m_LuxelCoords[iBump][(1+iOffset)%4].Init( 0.5f, flVValue + 0.5 ); - m_LuxelCoords[iBump][(2+iOffset)%4].Init( flUValue + 0.5, flVValue + 0.5 ); - m_LuxelCoords[iBump][(3+iOffset)%4].Init( flUValue + 0.5, 0.5f ); - } - - return bSwapped; -} - -//============================================================================= -// -// CDispNode Functions -// - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispNode::Init( void ) -{ - VectorClear( m_BBox[0] ); - VectorClear( m_BBox[1] ); - - m_ErrorTerm = 0.0f; - - m_VertIndex = -1; - - int j; - for( j = 0; j < MAX_NEIGHBOR_NODE_COUNT; j++ ) - { - m_NeighborVertIndices[j] = -1; - } - - for( j = 0; j < MAX_SURF_AT_NODE_COUNT; j++ ) - { - VectorClear( m_SurfBBoxes[j][0] ); - VectorClear( m_SurfBBoxes[j][1] ); - VectorClear( m_SurfPlanes[j].normal ); - m_SurfPlanes[j].dist = 0.0f; - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void GetDispNodeTriVerts( CCoreDispInfo *pDisp, int nodeIndex, int triIndex, Vector& v1, Vector& v2, Vector& v3 ) -{ - // get the node - CCoreDispNode *pNode = pDisp->GetNode( nodeIndex ); - - switch( triIndex ) - { - case 0: - { - pDisp->GetVert( pNode->GetNeighborVertIndex( 4 ), v1 ); - pDisp->GetVert( pNode->GetNeighborVertIndex( 0 ), v2 ); - pDisp->GetVert( pNode->GetNeighborVertIndex( 3 ), v3 ); - return; - } - case 1: - { - pDisp->GetVert( pNode->GetNeighborVertIndex( 3 ), v1 ); - pDisp->GetVert( pNode->GetNeighborVertIndex( 0 ), v2 ); - pDisp->GetVert( pNode->GetCenterVertIndex(), v3 ); - return; - } - case 2: - { - pDisp->GetVert( pNode->GetNeighborVertIndex( 3 ), v1 ); - pDisp->GetVert( pNode->GetCenterVertIndex(), v2 ); - pDisp->GetVert( pNode->GetNeighborVertIndex( 5 ), v3 ); - return; - } - case 3: - { - pDisp->GetVert( pNode->GetNeighborVertIndex( 5 ), v1 ); - pDisp->GetVert( pNode->GetCenterVertIndex(), v2 ); - pDisp->GetVert( pNode->GetNeighborVertIndex( 2 ), v3 ); - return; - } - case 4: - { - pDisp->GetVert( pNode->GetNeighborVertIndex( 0 ), v1 ); - pDisp->GetVert( pNode->GetNeighborVertIndex( 6 ), v2 ); - pDisp->GetVert( pNode->GetCenterVertIndex(), v3 ); - return; - } - case 5: - { - pDisp->GetVert( pNode->GetCenterVertIndex(), v1 ); - pDisp->GetVert( pNode->GetNeighborVertIndex( 6 ), v2 ); - pDisp->GetVert( pNode->GetNeighborVertIndex( 1 ), v3 ); - return; - } - case 6: - { - pDisp->GetVert( pNode->GetCenterVertIndex(), v1 ); - pDisp->GetVert( pNode->GetNeighborVertIndex( 1 ), v2 ); - pDisp->GetVert( pNode->GetNeighborVertIndex( 2 ), v3 ); - return; - } - case 7: - { - pDisp->GetVert( pNode->GetNeighborVertIndex( 2 ), v1 ); - pDisp->GetVert( pNode->GetNeighborVertIndex( 1 ), v2 ); - pDisp->GetVert( pNode->GetNeighborVertIndex( 7 ), v3 ); - return; - } - default: { return; } - } -} - - -//============================================================================= -// -// CCoreDispInfo Functions -// - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CCoreDispInfo::CCoreDispInfo() -{ - m_pVerts = NULL; - m_RenderIndices = NULL; - m_Nodes = NULL; - m_pTris = NULL; - - // initialize the base surface data - m_Surf.Init(); - - // - // initialize the disp info - // - m_Power = 0; - m_Elevation = 0.0f; - m_RenderIndexCount = 0; - m_RenderCounter = 0; - m_bTouched = false; - - m_pNext = NULL; - - m_ppListBase = NULL; - m_ListSize = 0; - m_nListIndex = -1; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CCoreDispInfo::~CCoreDispInfo() -{ - if (m_pVerts) - delete [] m_pVerts; - if (m_RenderIndices) - delete [] m_RenderIndices; - if (m_Nodes) - delete [] m_Nodes; - if (m_pTris) - delete [] m_pTris; -} - - -#if 0 -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::InitSurf( int parentIndex, Vector points[4], Vector normals[4], - Vector2D texCoords[4], Vector2D lightCoords[4][4], int contents, int flags, - bool bGenerateSurfPointStart, Vector& startPoint, - bool bHasMappingAxes, Vector& uAxis, Vector& vAxis ) -{ - // save the "parent" index - m_Surf.m_Index = parentIndex; - - // - // save the surface points and point normals, texture coordinates, and - // lightmap coordinates - // - m_Surf.m_PointCount = CSurface::QUAD_POINT_COUNT; - for( int i = 0; i < CSurface::QUAD_POINT_COUNT; i++ ) - { - VectorCopy( points[i], m_Surf.m_Points[i] ); - - if( normals ) - { - VectorCopy( normals[i], m_Surf.m_pVerts[i].m_Normal ); - } - - if( texCoords ) - { - Vector2DCopy( texCoords[i], m_Surf.m_TexCoords[i] ); - } - - if( lightCoords ) - { - Assert( NUM_BUMP_VECTS == 3 ); - Vector2DCopy( lightCoords[0][i], m_Surf.m_LightCoords[i][0] ); - Vector2DCopy( lightCoords[1][i], m_Surf.m_LightCoords[i][1] ); - Vector2DCopy( lightCoords[2][i], m_Surf.m_LightCoords[i][2] ); - Vector2DCopy( lightCoords[3][i], m_Surf.m_LightCoords[i][3] ); - } - } - - // save the starting point - if( startPoint ) - { - VectorCopy( startPoint, m_Surf.m_PointStart ); - } - - // - // save the surface contents and flags - // - m_Contents = contents; - m_Flags = flags; - - // - // adjust surface points, texture coordinates, etc.... - // - if( bHasMappingAxes && ( m_Surf.m_PointStartIndex == -1 ) ) - { - GeneratePointStartIndexFromMappingAxes( uAxis, vAxis ); - } - else - { - // - // adjust the surf data - // - if( bGenerateSurfPointStart ) - { - GenerateSurfPointStartIndex(); - } - else - { - FindSurfPointStartIndex(); - } - } - - AdjustSurfPointData(); -} -#endif - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::InitDispInfo( int power, int minTess, float smoothingAngle, - float *alphas, Vector *dispVectorField, float *dispDistances ) -{ - Assert( power >= MIN_MAP_DISP_POWER && power <= MAX_MAP_DISP_POWER ); - - // - // general displacement data - // - m_Power = power; - - if ( ( minTess & 0x80000000 ) != 0 ) - { - // If the high bit is set, this represents FLAGS (SURF_NOPHYSICS_COLL, etc.) flags. - int nFlags = minTess; - nFlags &= ~0x80000000; - GetSurface()->SetFlags( nFlags ); - } - - // Allocate + initialize verts - int size = GetSize(); - m_pVerts = new CoreDispVert_t[size]; - - int nIndexCount = size * 2 * 3; - m_RenderIndices = new unsigned short[nIndexCount]; - - int nNodeCount = GetNodeCount(power); - m_Nodes = new CCoreDispNode[nNodeCount]; - - int i; - for( i = 0; i < size; i++ ) - { - m_pVerts[i].m_FieldVector.Init(); - m_pVerts[i].m_SubdivPos.Init(); - m_pVerts[i].m_SubdivNormal.Init(); - - m_pVerts[i].m_FieldDistance = 0.0f; - - m_pVerts[i].m_Vert.Init(); - m_pVerts[i].m_FlatVert.Init(); - m_pVerts[i].m_Normal.Init(); - m_pVerts[i].m_TangentS.Init(); - m_pVerts[i].m_TangentT.Init(); - m_pVerts[i].m_TexCoord.Init(); - - for( int j = 0; j < ( NUM_BUMP_VECTS + 1 ); j++ ) - { - m_pVerts[i].m_LuxelCoords[j].Init(); - } - - m_pVerts[i].m_Alpha = 0.0f; - } - - for( i = 0; i < nIndexCount; i++ ) - { - m_RenderIndices[i] = 0; - } - - for( i = 0; i < nNodeCount; i++ ) - { - m_Nodes[i].Init(); - } - - // - // save the displacement vector field and distances within the field - // offset have been combined with fieldvectors at this point!!! - // - if (alphas && dispVectorField && dispDistances) - { - for( i = 0; i < size; i++ ) - { - VectorCopy( dispVectorField[i], m_pVerts[i].m_FieldVector ); - m_pVerts[i].m_FieldDistance = dispDistances[i]; - m_pVerts[i].m_Alpha = alphas[i]; - } - } - - // Init triangle information. - int nTriCount = GetTriCount(); - if ( nTriCount != 0 ) - { - m_pTris = new CoreDispTri_t[nTriCount]; - if ( m_pTris ) - { - InitTris(); - } - } -} - - -void CCoreDispInfo::InitDispInfo( int power, int minTess, float smoothingAngle, const CDispVert *pVerts, - const CDispTri *pTris ) -{ - Vector vectors[MAX_DISPVERTS]; - float dists[MAX_DISPVERTS]; - float alphas[MAX_DISPVERTS]; - - int nVerts = NUM_DISP_POWER_VERTS( power ); - for ( int i=0; i < nVerts; i++ ) - { - vectors[i] = pVerts[i].m_vVector; - dists[i] = pVerts[i].m_flDist; - alphas[i] = pVerts[i].m_flAlpha; - } - - InitDispInfo( power, minTess, smoothingAngle, alphas, vectors, dists ); - - int nTris = NUM_DISP_POWER_TRIS( power ); - for ( int iTri = 0; iTri < nTris; ++iTri ) - { - m_pTris[iTri].m_uiTags = pTris[iTri].m_uiTags; - } -} - - -void CCoreDispInfo::SetDispUtilsHelperInfo( CCoreDispInfo **ppListBase, int listSize ) -{ - m_ppListBase = ppListBase; - m_ListSize = listSize; -} - -const CPowerInfo* CCoreDispInfo::GetPowerInfo() const -{ - return ::GetPowerInfo( GetPower() ); -} - -CDispNeighbor* CCoreDispInfo::GetEdgeNeighbor( int index ) -{ - return GetSurface()->GetEdgeNeighbor( index ); -} - -CDispCornerNeighbors* CCoreDispInfo::GetCornerNeighbors( int index ) -{ - return GetSurface()->GetCornerNeighbors( index ); -} - -CDispUtilsHelper* CCoreDispInfo::GetDispUtilsByIndex( int index ) -{ - Assert( m_ppListBase ); - return index == 0xFFFF ? 0 : m_ppListBase[index]; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::BuildTriTLtoBR( int ndx ) -{ - // get width and height of displacement maps - int nWidth = ( ( 1 << m_Power ) + 1 ); - - m_RenderIndices[m_RenderIndexCount] = ndx; - m_RenderIndices[m_RenderIndexCount+1] = ndx + nWidth; - m_RenderIndices[m_RenderIndexCount+2] = ndx + 1; - m_RenderIndexCount += 3; - - m_RenderIndices[m_RenderIndexCount] = ndx + 1; - m_RenderIndices[m_RenderIndexCount+1] = ndx + nWidth; - m_RenderIndices[m_RenderIndexCount+2] = ndx + nWidth + 1; - m_RenderIndexCount += 3; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::BuildTriBLtoTR( int ndx ) -{ - // get width and height of displacement maps - int nWidth = ( ( 1 << m_Power ) + 1 ); - - m_RenderIndices[m_RenderIndexCount] = ndx; - m_RenderIndices[m_RenderIndexCount+1] = ndx + nWidth; - m_RenderIndices[m_RenderIndexCount+2] = ndx + nWidth + 1; - m_RenderIndexCount += 3; - - m_RenderIndices[m_RenderIndexCount] = ndx; - m_RenderIndices[m_RenderIndexCount+1] = ndx + nWidth + 1; - m_RenderIndices[m_RenderIndexCount+2] = ndx + 1; - m_RenderIndexCount += 3; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::GenerateCollisionSurface( void ) -{ - // get width and height of displacement maps - int nWidth = ( ( 1 << m_Power ) + 1 ); - int nHeight = ( ( 1 << m_Power ) + 1 ); - - // - // generate a fan tesselated (at quadtree node) rendering index list - // - m_RenderIndexCount = 0; - for ( int iV = 0; iV < ( nHeight - 1 ); iV++ ) - { - for ( int iU = 0; iU < ( nWidth - 1 ); iU++ ) - { - int ndx = ( iV * nWidth ) + iU; - - // test whether or not the index is odd - bool bOdd = ( ( ndx %2 ) == 1 ); - - // Top Left to Bottom Right - if( bOdd ) - { - BuildTriTLtoBR( ndx ); - } - // Bottom Left to Top Right - else - { - BuildTriBLtoTR( ndx ); - } - } - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::GenerateCollisionData( void ) -{ - GenerateCollisionSurface(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::CalcTriSurfPlanes( int nodeIndex, int indices[8][3] ) -{ - // - // calculate plane info for each face - // - for( int i = 0; i < 8; i++ ) - { - Vector v[3]; - VectorCopy( m_pVerts[indices[i][0]].m_Vert, v[0] ); - VectorCopy( m_pVerts[indices[i][1]].m_Vert, v[1] ); - VectorCopy( m_pVerts[indices[i][2]].m_Vert, v[2] ); - - Vector seg[2]; - VectorSubtract( v[1], v[0], seg[0] ); - VectorSubtract( v[2], v[0], seg[1] ); - - Vector normal; - CrossProduct( seg[1], seg[0], normal ); - VectorNormalize( normal ); - float dist = DotProduct( v[0], normal ); - - m_Nodes[nodeIndex].SetTriPlane( i, normal, dist ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::CalcRayBoundingBoxes( int nodeIndex, int indices[8][3] ) -{ - Vector triMin, triMax; - - for( int i = 0; i < 4; i++ ) - { - triMin[0] = triMax[0] = m_pVerts[indices[(i*2)][0]].m_Vert[0]; - triMin[1] = triMax[1] = m_pVerts[indices[(i*2)][0]].m_Vert[1]; - triMin[2] = triMax[2] = m_pVerts[indices[(i*2)][0]].m_Vert[2]; - - for( int j = 0; j < 3; j++ ) - { - // - // minimum - // - if( triMin[0] > m_pVerts[indices[(i*2)][j]].m_Vert[0] ) - triMin[0] = m_pVerts[indices[(i*2)][j]].m_Vert[0]; - if( triMin[0] > m_pVerts[indices[(i*2+1)][j]].m_Vert[0] ) - triMin[0] = m_pVerts[indices[(i*2+1)][j]].m_Vert[0]; - - if( triMin[1] > m_pVerts[indices[(i*2)][j]].m_Vert[1] ) - triMin[1] = m_pVerts[indices[(i*2)][j]].m_Vert[1]; - if( triMin[1] > m_pVerts[indices[(i*2+1)][j]].m_Vert[1] ) - triMin[1] = m_pVerts[indices[(i*2+1)][j]].m_Vert[1]; - - if( triMin[2] > m_pVerts[indices[(i*2)][j]].m_Vert[2] ) - triMin[2] = m_pVerts[indices[(i*2)][j]].m_Vert[2]; - if( triMin[2] > m_pVerts[indices[(i*2+1)][j]].m_Vert[2] ) - triMin[2] = m_pVerts[indices[(i*2+1)][j]].m_Vert[2]; - - // - // maximum - // - if( triMax[0] < m_pVerts[indices[(i*2)][j]].m_Vert[0] ) - triMax[0] = m_pVerts[indices[(i*2)][j]].m_Vert[0]; - if( triMax[0] < m_pVerts[indices[(i*2+1)][j]].m_Vert[0] ) - triMax[0] = m_pVerts[indices[(i*2+1)][j]].m_Vert[0]; - - if( triMax[1] < m_pVerts[indices[(i*2)][j]].m_Vert[1] ) - triMax[1] = m_pVerts[indices[(i*2)][j]].m_Vert[1]; - if( triMax[1] < m_pVerts[indices[(i*2+1)][j]].m_Vert[1] ) - triMax[1] = m_pVerts[indices[(i*2+1)][j]].m_Vert[1]; - - if( triMax[2] < m_pVerts[indices[(i*2)][j]].m_Vert[2] ) - triMax[2] = m_pVerts[indices[(i*2)][j]].m_Vert[2]; - if( triMax[2] < m_pVerts[indices[(i*2+1)][j]].m_Vert[2] ) - triMax[2] = m_pVerts[indices[(i*2+1)][j]].m_Vert[2]; - } - - m_Nodes[nodeIndex].SetRayBoundingBox( i, triMin, triMax ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::CalcTriSurfBoundingBoxes( int nodeIndex, int indices[8][3] ) -{ - Vector triMin, triMax; - - for( int i = 0; i < 8; i++ ) - { - m_Nodes[nodeIndex].GetTriBoundingBox( i, triMin, triMax ); - - for( int j = 0; j < 3; j++ ) - { - // - // minimum - // - if( triMin[0] > m_pVerts[indices[i][j]].m_Vert[0] ) - triMin[0] = m_pVerts[indices[i][j]].m_Vert[0]; - - if( triMin[1] > m_pVerts[indices[i][j]].m_Vert[1] ) - triMin[1] = m_pVerts[indices[i][j]].m_Vert[1]; - - if( triMin[2] > m_pVerts[indices[i][j]].m_Vert[2] ) - triMin[2] = m_pVerts[indices[i][j]].m_Vert[2]; - - // - // maximum - // - if( triMax[0] < m_pVerts[indices[i][j]].m_Vert[0] ) - triMax[0] = m_pVerts[indices[i][j]].m_Vert[0]; - - if( triMax[1] < m_pVerts[indices[i][j]].m_Vert[1] ) - triMax[1] = m_pVerts[indices[i][j]].m_Vert[1]; - - if( triMax[2] < m_pVerts[indices[i][j]].m_Vert[2] ) - triMax[2] = m_pVerts[indices[i][j]].m_Vert[2]; - } - - m_Nodes[nodeIndex].SetTriBoundingBox( i, triMin, triMax ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::CalcTriSurfIndices( int nodeIndex, int indices[8][3] ) -{ - indices[0][0] = m_Nodes[nodeIndex].GetNeighborVertIndex( 4 ); - indices[0][1] = m_Nodes[nodeIndex].GetNeighborVertIndex( 0 ); - indices[0][2] = m_Nodes[nodeIndex].GetNeighborVertIndex( 3 ); - - indices[1][0] = m_Nodes[nodeIndex].GetNeighborVertIndex( 3 ); - indices[1][1] = m_Nodes[nodeIndex].GetNeighborVertIndex( 0 ); - indices[1][2] = m_Nodes[nodeIndex].GetCenterVertIndex(); - - indices[2][0] = m_Nodes[nodeIndex].GetNeighborVertIndex( 3 ); - indices[2][1] = m_Nodes[nodeIndex].GetCenterVertIndex(); - indices[2][2] = m_Nodes[nodeIndex].GetNeighborVertIndex( 5 ); - - indices[3][0] = m_Nodes[nodeIndex].GetNeighborVertIndex( 5 ); - indices[3][1] = m_Nodes[nodeIndex].GetCenterVertIndex(); - indices[3][2] = m_Nodes[nodeIndex].GetNeighborVertIndex( 2 ); - - indices[4][0] = m_Nodes[nodeIndex].GetNeighborVertIndex( 0 ); - indices[4][1] = m_Nodes[nodeIndex].GetNeighborVertIndex( 6 ); - indices[4][2] = m_Nodes[nodeIndex].GetCenterVertIndex(); - - indices[5][0] = m_Nodes[nodeIndex].GetCenterVertIndex(); - indices[5][1] = m_Nodes[nodeIndex].GetNeighborVertIndex( 6 ); - indices[5][2] = m_Nodes[nodeIndex].GetNeighborVertIndex( 1 ); - - indices[6][0] = m_Nodes[nodeIndex].GetCenterVertIndex(); - indices[6][1] = m_Nodes[nodeIndex].GetNeighborVertIndex( 1 ); - indices[6][2] = m_Nodes[nodeIndex].GetNeighborVertIndex( 2 ); - - indices[7][0] = m_Nodes[nodeIndex].GetNeighborVertIndex( 2 ); - indices[7][1] = m_Nodes[nodeIndex].GetNeighborVertIndex( 1 ); - indices[7][2] = m_Nodes[nodeIndex].GetNeighborVertIndex( 7 ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::CalcTriSurfInfoAtNode( int nodeIndex ) -{ - int indices[8][3]; - - CalcTriSurfIndices( nodeIndex, indices ); - CalcTriSurfBoundingBoxes( nodeIndex, indices ); - CalcRayBoundingBoxes( nodeIndex, indices ); - CalcTriSurfPlanes( nodeIndex, indices ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::CalcMinMaxBoundingBoxAtNode( int nodeIndex, Vector& bMin, Vector& bMax ) -{ - // get the child node index - int childNodeIndex = GetNodeChild( m_Power, nodeIndex, 4 ); - - // get initial bounding box values - m_Nodes[childNodeIndex].GetBoundingBox( bMin, bMax ); - - Vector nodeMin, nodeMax; - for( int i = 1, j = 5; i < 4; i++, j++ ) - { - // - // get the child node bounding box - // - childNodeIndex = GetNodeChild( m_Power, nodeIndex, j ); - m_Nodes[childNodeIndex].GetBoundingBox( nodeMin, nodeMax ); - - // minimum - if( bMin[0] > nodeMin[0] ) - bMin[0] = nodeMin[0]; - - if( bMin[1] > nodeMin[1] ) - bMin[1] = nodeMin[1]; - - if( bMin[2] > nodeMin[2] ) - bMin[2] = nodeMin[2]; - - // maximum - if( bMax[0] < nodeMax[0] ) - bMax[0] = nodeMax[0]; - - if( bMax[1] < nodeMax[1] ) - bMax[1] = nodeMax[1]; - - if( bMax[2] < nodeMax[2] ) - bMax[2] = nodeMax[2]; - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::CalcBoundingBoxAtNode( int nodeIndex ) -{ - Vector bMin, bMax; - - // - // initialize the minimum and maximum values for the bounding box - // - int level = GetNodeLevel( nodeIndex ); - - int vertIndex = m_Nodes[nodeIndex].GetCenterVertIndex(); - if( level == m_Power ) - { - VectorCopy( m_pVerts[vertIndex].m_Vert, bMin ); - VectorCopy( m_pVerts[vertIndex].m_Vert, bMax ); - } - else - { - CalcMinMaxBoundingBoxAtNode( nodeIndex, bMin, bMax ); - - if( bMin[0] > m_pVerts[vertIndex].m_Vert[0] ) - bMin[0] = m_pVerts[vertIndex].m_Vert[0]; - - if( bMin[1] > m_pVerts[vertIndex].m_Vert[1] ) - bMin[1] = m_pVerts[vertIndex].m_Vert[1]; - - if( bMin[2] > m_pVerts[vertIndex].m_Vert[2] ) - bMin[2] = m_pVerts[vertIndex].m_Vert[2]; - - - if( bMax[0] < m_pVerts[vertIndex].m_Vert[0] ) - bMax[0] = m_pVerts[vertIndex].m_Vert[0]; - - if( bMax[1] < m_pVerts[vertIndex].m_Vert[1] ) - bMax[1] = m_pVerts[vertIndex].m_Vert[1]; - - if( bMax[2] < m_pVerts[vertIndex].m_Vert[2] ) - bMax[2] = m_pVerts[vertIndex].m_Vert[2]; - } - - for( int i = 0; i < 8; i++ ) - { - int neighborVertIndex = m_Nodes[nodeIndex].GetNeighborVertIndex( i ); - - // - // minimum - // - if( bMin[0] > m_pVerts[neighborVertIndex].m_Vert[0] ) - bMin[0] = m_pVerts[neighborVertIndex].m_Vert[0]; - - if( bMin[1] > m_pVerts[neighborVertIndex].m_Vert[1] ) - bMin[1] = m_pVerts[neighborVertIndex].m_Vert[1]; - - if( bMin[2] > m_pVerts[neighborVertIndex].m_Vert[2] ) - bMin[2] = m_pVerts[neighborVertIndex].m_Vert[2]; - - // - // maximum - // - if( bMax[0] < m_pVerts[neighborVertIndex].m_Vert[0] ) - bMax[0] = m_pVerts[neighborVertIndex].m_Vert[0]; - - if( bMax[1] < m_pVerts[neighborVertIndex].m_Vert[1] ) - bMax[1] = m_pVerts[neighborVertIndex].m_Vert[1]; - - if( bMax[2] < m_pVerts[neighborVertIndex].m_Vert[2] ) - bMax[2] = m_pVerts[neighborVertIndex].m_Vert[2]; - } - - m_Nodes[nodeIndex].SetBoundingBox( bMin, bMax ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -float CCoreDispInfo::GetMaxErrorFromChildren( int nodeIndex, int level ) -{ - // - // check for children nodes - // - if( level == m_Power ) - return 0.0f; - - // - // get the child's error term and save the greatest error -- SW, SE, NW, NE - // - float errorTerm = 0.0f; - for( int i = 4; i < 8; i++ ) - { - int childIndex = GetNodeChild( m_Power, nodeIndex, i ); - - float nodeErrorTerm = m_Nodes[childIndex].GetErrorTerm(); - if( errorTerm < nodeErrorTerm ) - { - errorTerm = nodeErrorTerm; - } - } - - return errorTerm; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::CalcErrorTermAtNode( int nodeIndex, int level ) -{ - if( level == m_Power ) - return; - - // - // get the vertex indices - // - int neighborVertIndices[9]; - for( int i = 0; i < 8; i++ ) - { - neighborVertIndices[i] = m_Nodes[nodeIndex].GetNeighborVertIndex( i ); - } - neighborVertIndices[8] = m_Nodes[nodeIndex].GetCenterVertIndex(); - - - // - // calculate the error terms - // - Vector segment; - Vector v; - - VectorAdd( m_pVerts[neighborVertIndices[5]].m_Vert, m_pVerts[neighborVertIndices[4]].m_Vert, v ); - VectorScale( v, 0.5f, v ); - VectorSubtract( m_pVerts[neighborVertIndices[0]].m_Vert, v, segment ); - float errorTerm = ( float )VectorLength( segment ); - - VectorAdd( m_pVerts[neighborVertIndices[5]].m_Vert, m_pVerts[neighborVertIndices[6]].m_Vert, v ); - VectorScale( v, 0.5f, v ); - VectorSubtract( m_pVerts[neighborVertIndices[1]].m_Vert, v, segment ); - if( errorTerm < ( float )VectorLength( segment ) ) - errorTerm = ( float )VectorLength( segment ); - - VectorAdd( m_pVerts[neighborVertIndices[6]].m_Vert, m_pVerts[neighborVertIndices[7]].m_Vert, v ); - VectorScale( v, 0.5f, v ); - VectorSubtract( m_pVerts[neighborVertIndices[2]].m_Vert, v, segment ); - if( errorTerm < ( float )VectorLength( segment ) ) - errorTerm = ( float )VectorLength( segment ); - - VectorAdd( m_pVerts[neighborVertIndices[7]].m_Vert, m_pVerts[neighborVertIndices[4]].m_Vert, v ); - VectorScale( v, 0.5f, v ); - VectorSubtract( m_pVerts[neighborVertIndices[3]].m_Vert, v, segment ); - if( errorTerm < ( float )VectorLength( segment ) ) - errorTerm = ( float )VectorLength( segment ); - - VectorAdd( m_pVerts[neighborVertIndices[4]].m_Vert, m_pVerts[neighborVertIndices[6]].m_Vert, v ); - VectorScale( v, 0.5f, v ); - VectorSubtract( m_pVerts[neighborVertIndices[8]].m_Vert, v, segment ); - if( errorTerm < ( float )VectorLength( segment ) ) - errorTerm = ( float )VectorLength( segment ); - - VectorAdd( m_pVerts[neighborVertIndices[5]].m_Vert, m_pVerts[neighborVertIndices[7]].m_Vert, v ); - VectorScale( v, 0.5f, v ); - VectorSubtract( m_pVerts[neighborVertIndices[8]].m_Vert, v, segment ); - if( errorTerm < ( float )VectorLength( segment ) ) - errorTerm = ( float )VectorLength( segment ); - - // - // add the max child's error term - // - errorTerm += GetMaxErrorFromChildren( nodeIndex, level ); - - // set the error term - m_Nodes[nodeIndex].SetErrorTerm( errorTerm ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::CalcNeighborVertIndicesAtNode( int nodeIndex, int level ) -{ - // calculate the shift in direction in the matrix - int shift = ( 1 << ( m_Power - level ) ); - - // calculate the width, height of the displacement surface (are uniform) - int extent = ( ( 1 << m_Power ) + 1 ); - - // - // get the neighbor vertex indices (defining the surface at the node level) - // - for( int direction = 0; direction < 8; direction++ ) - { - // - // get the parent vertex index in component form - // - int posX = m_Nodes[nodeIndex].GetCenterVertIndex() % extent; - int posY = m_Nodes[nodeIndex].GetCenterVertIndex() / extent; - - // - // calculate the neighboring vertex indices for surface rendering - // - bool bError = false; - switch( direction ) - { - case WEST: { posX -= shift; break; } - case NORTH: { posY += shift; break; } - case EAST: { posX += shift; break; } - case SOUTH: { posY -= shift; break; } - case SOUTHWEST: { posX -= shift; posY -= shift; break; } - case SOUTHEAST: { posX += shift; posY -= shift; break; } - case NORTHWEST: { posX -= shift; posY += shift; break; } - case NORTHEAST: { posX += shift; posY += shift; break; } - default: { bError = true; break; } - } - - if( bError ) - { - m_Nodes[nodeIndex].SetNeighborVertIndex( direction, -99999 ); - } - else - { - m_Nodes[nodeIndex].SetNeighborVertIndex( direction, ( ( posY * extent ) + posX ) ); - } - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::CalcNodeInfo( int nodeIndex, int terminationLevel ) -{ - // get the level of the current node - int level = GetNodeLevel( nodeIndex ); - - // - // get the node data at the termination level - // - if( level == terminationLevel ) - { - // get the neighbor vertex indices (used to create surface at node level) - CalcNeighborVertIndicesAtNode( nodeIndex, level ); - - // get the neighbor node indices - //CalcNeighborNodeIndicesAtNode( nodeIndex, level ); - - // calculate the error term at the node - CalcErrorTermAtNode( nodeIndex, level ); - - // calcluate the axial-aligned bounding box at the node - CalcBoundingBoxAtNode( nodeIndex ); - - // calculate the triangular surface info at the node - CalcTriSurfInfoAtNode( nodeIndex ); - - return; - } - - // - // continue recursion (down to nodes "children") - // - for( int i = 4; i < 8; i++ ) - { - int childIndex = GetNodeChild( m_Power, nodeIndex, i ); - CalcNodeInfo( childIndex, terminationLevel ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CCoreDispInfo::GetNodeVertIndexFromParentIndex( int level, int parentVertIndex, int direction ) -{ - // calculate the "shift" - int shift = ( 1 << ( m_Power - ( level + 1 ) ) ); - - // calculate the width and height of displacement (is uniform) - int extent = ( ( 1 << m_Power ) + 1 ); - - // get the parent vertex index in component form - int posX = parentVertIndex % extent; - int posY = parentVertIndex / extent; - - // - // calculate the child index based on the parent index and child - // direction - // - switch( direction ) - { - case SOUTHWEST: { posX -= shift; posY -= shift; break; } - case SOUTHEAST: { posX += shift; posY -= shift; break; } - case NORTHWEST: { posX -= shift; posY += shift; break; } - case NORTHEAST: { posX += shift; posY += shift; break; } - default: return -99999; - } - - // return the child vertex index - return ( ( posY * extent ) + posX ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::CalcVertIndicesAtNodes( int nodeIndex ) -{ - // - // check for recursion termination ( node level = power ) - // - int level = GetNodeLevel( nodeIndex ); - if( level == m_Power ) - return; - - // - // get the children indices - SW, SE, NW, NE - // - int childIndices[4]; - int i, j; - for( i = 0, j = 4; i < 4; i++, j++ ) - { - childIndices[i] = GetNodeChild( m_Power, nodeIndex, j ); - int centerIndex = GetNodeVertIndexFromParentIndex( level, m_Nodes[nodeIndex].GetCenterVertIndex(), j ); - m_Nodes[childIndices[i]].SetCenterVertIndex( centerIndex ); - } - - // - // calculate the children's node vertex indices - // - for( i = 0; i < 4; i++ ) - { - CalcVertIndicesAtNodes( childIndices[i] ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::GenerateLODTree( void ) -{ - // - // calculate the displacement surface's vertex index at each quad-tree node - // centroid - // - int size = GetSize(); - int initialIndex = ( ( size - 1 ) >> 1 ); - m_Nodes[0].SetCenterVertIndex( initialIndex ); - CalcVertIndicesAtNodes( 0 ); - - // - // calculate the error terms, bounding boxes, and neighboring vertex indices - // at each node - // - for( int i = m_Power; i > 0; i-- ) - { - CalcNodeInfo( 0, i ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::CalcDispSurfCoords( bool bLightMap, int lightmapID ) -{ - // - // get base surface texture coords - // - Vector2D texCoords[4]; - Vector2D luxelCoords[4]; - CCoreDispSurface *pSurf = GetSurface(); - - int i; - for( i = 0; i < 4; i++ ) - { - pSurf->GetTexCoord( i, texCoords[i] ); - pSurf->GetLuxelCoord( lightmapID, i, luxelCoords[i] ); - } - - // - // get images width and intervals along the edge - // - int postSpacing = GetPostSpacing(); - float ooInt = ( 1.0f / ( float )( postSpacing - 1 ) ); - - // - // calculate the parallel edge intervals - // - Vector2D edgeInt[2]; - if( !bLightMap ) - { - Vector2DSubtract( texCoords[1], texCoords[0], edgeInt[0] ); - Vector2DSubtract( texCoords[2], texCoords[3], edgeInt[1] ); - } - else - { - Vector2DSubtract( luxelCoords[1], luxelCoords[0], edgeInt[0] ); - Vector2DSubtract( luxelCoords[2], luxelCoords[3], edgeInt[1] ); - } - Vector2DMultiply( edgeInt[0], ooInt, edgeInt[0] ); - Vector2DMultiply( edgeInt[1], ooInt, edgeInt[1] ); - - // - // calculate the displacement points - // - for( i = 0; i < postSpacing; i++ ) - { - // - // position along parallel edges (start and end for a perpendicular segment) - // - Vector2D endPts[2]; - Vector2DMultiply( edgeInt[0], ( float )i, endPts[0] ); - Vector2DMultiply( edgeInt[1], ( float )i, endPts[1] ); - if( !bLightMap ) - { - Vector2DAdd( endPts[0], texCoords[0], endPts[0] ); - Vector2DAdd( endPts[1], texCoords[3], endPts[1] ); - } - else - { - Vector2DAdd( endPts[0], luxelCoords[0], endPts[0] ); - Vector2DAdd( endPts[1], luxelCoords[3], endPts[1] ); - } - - // - // interval length for perpendicular edge - // - Vector2D seg, segInt; - Vector2DSubtract( endPts[1], endPts[0], seg ); - Vector2DMultiply( seg, ooInt, segInt ); - - // - // calculate the material (texture or light) coordinate at each point - // - for( int j = 0; j < postSpacing; j++ ) - { - Vector2DMultiply( segInt, ( float )j, seg ); - - if( !bLightMap ) - { - Vector2DAdd( endPts[0], seg, m_pVerts[i*postSpacing+j].m_TexCoord ); - } - else - { - Vector2DAdd( endPts[0], seg, m_pVerts[i*postSpacing+j].m_LuxelCoords[lightmapID] ); - } - } - } -} - -#if 0 -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::CalcDispSurfAlphas( void ) -{ - // - // get images width and intervals along the edge - // - int postSpacing = GetPostSpacing(); - float ooInt = ( 1.0f / ( float )( postSpacing - 1 ) ); - - // - // calculate the parallel edge intervals - // - float edgeInt[2]; - edgeInt[0] = m_Surf.m_Alpha[1] - m_Surf.m_Alpha[0]; - edgeInt[1] = m_Surf.m_Alpha[2] - m_Surf.m_Alpha[3]; - edgeInt[0] *= ooInt; - edgeInt[1] *= ooInt; - - // - // calculate the displacement points - // - for( int i = 0; i < postSpacing; i++ ) - { - // - // position along parallel edges (start and end for a perpendicular segment) - // - float endValues[2]; - - endValues[0] = edgeInt[0] * ( float )i; - endValues[1] = edgeInt[1] * ( float )i; - endValues[0] += m_Surf.m_Alpha[0]; - endValues[1] += m_Surf.m_Alpha[3]; - - // - // interval length for perpendicular edge - // - float seg, segInt; - seg = endValues[1] - endValues[0]; - segInt = seg * ooInt; - - // - // calculate the alpha value at each point - // - for( int j = 0; j < postSpacing; j++ ) - { - seg = segInt * ( float )j; - m_Alphas[i*postSpacing+j] = endValues[0] + seg; - } - } -} -#endif - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::GenerateDispSurfTangentSpaces( void ) -{ - // - // get texture axes from base surface - // - CCoreDispSurface *pSurf = GetSurface(); - Vector sAxis, tAxis; - pSurf->GetSAxis( sAxis ); - pSurf->GetTAxis( tAxis ); - - // - // calculate the tangent spaces - // - int size = GetSize(); - for( int i = 0; i < size; i++ ) - { - // - // create the axes - normals, tangents, and binormals - // - VectorCopy( tAxis, m_pVerts[i].m_TangentT ); - VectorNormalize( m_pVerts[i].m_TangentT ); - CrossProduct( m_pVerts[i].m_Normal, m_pVerts[i].m_TangentT, m_pVerts[i].m_TangentS ); - VectorNormalize( m_pVerts[i].m_TangentS ); - CrossProduct( m_pVerts[i].m_TangentS, m_pVerts[i].m_Normal, m_pVerts[i].m_TangentT ); - VectorNormalize( m_pVerts[i].m_TangentT ); - - Vector tmpVect; - Vector planeNormal; - pSurf->GetNormal( planeNormal ); - CrossProduct( sAxis, tAxis, tmpVect ); - if( DotProduct( planeNormal, tmpVect ) > 0.0f ) - { - VectorScale( m_pVerts[i].m_TangentS, -1.0f, m_pVerts[i].m_TangentS ); - } - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::CalcNormalFromEdges( int indexRow, int indexCol, bool bIsEdge[4], - Vector& normal ) -{ - // get the post spacing (size/interval of displacement surface) - int postSpacing = ( ( 1 << m_Power ) + 1 ); - - // initialize the normal accumulator - counter - Vector accumNormal; - int normalCount = 0; - - VectorClear( accumNormal ); - - Vector tmpVect[2]; - Vector tmpNormal; - - // - // check quadrant I (posX, posY) - // - if( bIsEdge[1] && bIsEdge[2] ) - { - // tri i - VectorSubtract( m_pVerts[(indexCol+1)*postSpacing+indexRow].m_Vert, m_pVerts[indexCol*postSpacing+indexRow].m_Vert, tmpVect[0] ); - VectorSubtract( m_pVerts[indexCol*postSpacing+(indexRow+1)].m_Vert, m_pVerts[indexCol*postSpacing+indexRow].m_Vert, tmpVect[1] ); - CrossProduct( tmpVect[1], tmpVect[0], tmpNormal ); - VectorNormalize( tmpNormal ); - VectorAdd( accumNormal, tmpNormal, accumNormal ); - normalCount++; - - // tri 2 - VectorSubtract( m_pVerts[(indexCol+1)*postSpacing+indexRow].m_Vert, m_pVerts[indexCol*postSpacing+(indexRow+1)].m_Vert, tmpVect[0] ); - VectorSubtract( m_pVerts[(indexCol+1)*postSpacing+(indexRow+1)].m_Vert, m_pVerts[indexCol*postSpacing+(indexRow+1)].m_Vert, tmpVect[1] ); - CrossProduct( tmpVect[1], tmpVect[0], tmpNormal ); - VectorNormalize( tmpNormal ); - VectorAdd( accumNormal, tmpNormal, accumNormal ); - normalCount++; - } - - // - // check quadrant II (negX, posY) - // - if( bIsEdge[0] && bIsEdge[1] ) - { - // tri i - VectorSubtract( m_pVerts[(indexCol+1)*postSpacing+(indexRow-1)].m_Vert, m_pVerts[indexCol*postSpacing+(indexRow-1)].m_Vert, tmpVect[0] ); - VectorSubtract( m_pVerts[indexCol*postSpacing+indexRow].m_Vert, m_pVerts[indexCol*postSpacing+(indexRow-1)].m_Vert, tmpVect[1] ); - CrossProduct( tmpVect[1], tmpVect[0], tmpNormal ); - VectorNormalize( tmpNormal ); - VectorAdd( accumNormal, tmpNormal, accumNormal ); - normalCount++; - - // tri 2 - VectorSubtract( m_pVerts[(indexCol+1)*postSpacing+(indexRow-1)].m_Vert, m_pVerts[indexCol*postSpacing+indexRow].m_Vert, tmpVect[0] ); - VectorSubtract( m_pVerts[(indexCol+1)*postSpacing+indexRow].m_Vert, m_pVerts[indexCol*postSpacing+indexRow].m_Vert, tmpVect[1] ); - CrossProduct( tmpVect[1], tmpVect[0], tmpNormal ); - VectorNormalize( tmpNormal ); - VectorAdd( accumNormal, tmpNormal, accumNormal ); - normalCount++; - } - - // - // check quadrant III (negX, negY) - // - if( bIsEdge[0] && bIsEdge[3] ) - { - // tri i - VectorSubtract( m_pVerts[indexCol*postSpacing+(indexRow-1)].m_Vert, m_pVerts[(indexCol-1)*postSpacing+(indexRow-1)].m_Vert, tmpVect[0] ); - VectorSubtract( m_pVerts[(indexCol-1)*postSpacing+indexRow].m_Vert, m_pVerts[(indexCol-1)*postSpacing+(indexRow-1)].m_Vert, tmpVect[1] ); - CrossProduct( tmpVect[1], tmpVect[0], tmpNormal ); - VectorNormalize( tmpNormal ); - VectorAdd( accumNormal, tmpNormal, accumNormal ); - normalCount++; - - // tri 2 - VectorSubtract( m_pVerts[indexCol*postSpacing+(indexRow-1)].m_Vert, m_pVerts[(indexCol-1)*postSpacing+indexRow].m_Vert, tmpVect[0] ); - VectorSubtract( m_pVerts[indexCol*postSpacing+indexRow].m_Vert, m_pVerts[(indexCol-1)*postSpacing+indexRow].m_Vert, tmpVect[1] ); - CrossProduct( tmpVect[1], tmpVect[0], tmpNormal ); - VectorNormalize( tmpNormal ); - VectorAdd( accumNormal, tmpNormal, accumNormal ); - normalCount++; - } - - // - // check quadrant IV (posX, negY) - // - if( bIsEdge[2] && bIsEdge[3] ) - { - // tri i - VectorSubtract( m_pVerts[indexCol*postSpacing+indexRow].m_Vert, m_pVerts[(indexCol-1)*postSpacing+indexRow].m_Vert, tmpVect[0] ); - VectorSubtract( m_pVerts[(indexCol-1)*postSpacing+(indexRow+1)].m_Vert, m_pVerts[(indexCol-1)*postSpacing+indexRow].m_Vert, tmpVect[1] ); - CrossProduct( tmpVect[1], tmpVect[0], tmpNormal ); - VectorNormalize( tmpNormal ); - VectorAdd( accumNormal, tmpNormal, accumNormal ); - normalCount++; - - // tri 2 - VectorSubtract( m_pVerts[indexCol*postSpacing+indexRow].m_Vert, m_pVerts[(indexCol-1)*postSpacing+(indexRow+1)].m_Vert, tmpVect[0] ); - VectorSubtract( m_pVerts[indexCol*postSpacing+(indexRow+1)].m_Vert, m_pVerts[(indexCol-1)*postSpacing+(indexRow+1)].m_Vert, tmpVect[1] ); - CrossProduct( tmpVect[1], tmpVect[0], tmpNormal ); - VectorNormalize( tmpNormal ); - VectorAdd( accumNormal, tmpNormal, accumNormal ); - normalCount++; - } - - VectorScale( accumNormal, ( 1.0f / ( float )normalCount ), normal ); -} - - -//----------------------------------------------------------------------------- -// Purpose: This function determines if edges exist in each of the directions -// off of the given point (given in component form). We know ahead of -// time that there are only 4 possibilities. -// -// 1 "directions" -// 0 + 2 -// 3 -// -// Input: indexRow - row position -// indexCol - col position -// direction - the direction (edge) currently being evaluated -// postSpacing - the number of intervals in the row and col directions -// Output: the edge existed? (true/false) -//----------------------------------------------------------------------------- -bool CCoreDispInfo::DoesEdgeExist( int indexRow, int indexCol, int direction, int postSpacing ) -{ - switch( direction ) - { - case 0: - // left edge - if( ( indexRow - 1 ) < 0 ) - return false; - return true; - case 1: - // top edge - if( ( indexCol + 1 ) > ( postSpacing - 1 ) ) - return false; - return true; - case 2: - // right edge - if( ( indexRow + 1 ) > ( postSpacing - 1 ) ) - return false; - return true; - case 3: - // bottom edge - if( ( indexCol - 1 ) < 0 ) - return false; - return true; - default: - return false; - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::GenerateDispSurfNormals( void ) -{ - // get the post spacing (size/interval of displacement surface) - int postSpacing = GetPostSpacing(); - - // - // generate the normals at each displacement surface vertex - // - for( int i = 0; i < postSpacing; i++ ) - { - for( int j = 0; j < postSpacing; j++ ) - { - bool bIsEdge[4]; - - // edges - for( int k = 0; k < 4; k++ ) - { - bIsEdge[k] = DoesEdgeExist( j, i, k, postSpacing ); - } - - Vector normal; - CalcNormalFromEdges( j, i, bIsEdge, normal ); - - // save generated normal - VectorCopy( normal, m_pVerts[i*postSpacing+j].m_Normal ); - } - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::GenerateDispSurf( void ) -{ - int i; - CCoreDispSurface *pSurf = GetSurface(); - Vector points[4]; - for( i = 0; i < 4; i++ ) - { - pSurf->GetPoint( i, points[i] ); - } - - // - // get the spacing (interval = width/height, are equal because it is uniform) along the edge - // - int postSpacing = GetPostSpacing(); - float ooInt = 1.0f / ( float )( postSpacing - 1 ); - - // - // calculate the opposite edge intervals - // - Vector edgeInt[2]; - VectorSubtract( points[1], points[0], edgeInt[0] ); - VectorScale( edgeInt[0], ooInt, edgeInt[0] ); - VectorSubtract( points[2], points[3], edgeInt[1] ); - VectorScale( edgeInt[1], ooInt, edgeInt[1] ); - - Vector elevNormal; - elevNormal.Init(); - if( m_Elevation != 0.0f ) - { - pSurf->GetNormal( elevNormal ); - VectorScale( elevNormal, m_Elevation, elevNormal ); - } - - // - // calculate the displaced vertices - // - for( i = 0; i < postSpacing; i++ ) - { - // - // calculate segment interval between opposite edges - // - Vector endPts[2]; - VectorScale( edgeInt[0], ( float )i, endPts[0] ); - VectorAdd( endPts[0], points[0], endPts[0] ); - VectorScale( edgeInt[1], ( float )i, endPts[1] ); - VectorAdd( endPts[1], points[3], endPts[1] ); - - Vector seg, segInt; - VectorSubtract( endPts[1], endPts[0], seg ); - VectorScale( seg, ooInt, segInt ); - - // - // calculate the surface vertices - // - for( int j = 0; j < postSpacing; j++ ) - { - int ndx = i * postSpacing + j; - - CoreDispVert_t *pVert = &m_pVerts[ndx]; - - // calculate the flat surface position -- saved separately - pVert->m_FlatVert = endPts[0] + ( segInt * ( float )j ); - - // start with the base surface position - pVert->m_Vert = pVert->m_FlatVert; - - // add the elevation vector -- if it exists - if( m_Elevation != 0.0f ) - { - pVert->m_Vert += elevNormal; - } - - // add the subdivision surface position - pVert->m_Vert += pVert->m_SubdivPos; - - // add the displacement field direction(normalized) and distance - pVert->m_Vert += pVert->m_FieldVector * pVert->m_FieldDistance; - } - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//bool CCoreDispInfo::Create( int creationFlags ) -bool CCoreDispInfo::Create( void ) -{ - // sanity check - CCoreDispSurface *pSurf = GetSurface(); - if( pSurf->GetPointCount() != 4 ) - return false; - - // generate the displacement surface - GenerateDispSurf(); - - GenerateDispSurfNormals(); - - GenerateDispSurfTangentSpaces(); - - CalcDispSurfCoords( false, 0 ); - - for( int bumpID = 0; bumpID < ( NUM_BUMP_VECTS + 1 ); bumpID++ ) - { - CalcDispSurfCoords( true, bumpID ); - } - - GenerateLODTree(); - - GenerateCollisionData(); - - CreateTris(); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Create a displacement surface without generating the LOD for it. -//----------------------------------------------------------------------------- -bool CCoreDispInfo::CreateWithoutLOD( void ) -{ - // sanity check - CCoreDispSurface *pSurf = GetSurface(); - if( pSurf->GetPointCount() != 4 ) - return false; - - GenerateDispSurf(); - - GenerateDispSurfNormals(); - - GenerateDispSurfTangentSpaces(); - - CalcDispSurfCoords( false, 0 ); - - for( int bumpID = 0; bumpID < ( NUM_BUMP_VECTS + 1 ); bumpID++ ) - { - CalcDispSurfCoords( true, bumpID ); - } - GenerateCollisionData(); - - CreateTris(); - - return true; -} - - - -//----------------------------------------------------------------------------- -// Purpose: This function calculates the neighbor node index given the base -// node and direction of the neighbor node in the tree. -// Input: power - the size in one dimension of the displacement map (2^power + 1 ) -// index - the "base" node index -// direction - the direction of the neighbor { W = 1, N = 2, E = 3, S = 4 } -// Output: returns the index of the neighbor node -//----------------------------------------------------------------------------- -int GetNodeNeighborNode( int power, int index, int direction, int level ) -{ - // adjust the index to range [0...?] - int minNodeIndex = GetNodeMinNodeAtLevel( level ); - - // get node extent (uniform: height = width) - int nodeExtent = ( 1 << ( level - 1 ) ); - - // - // get node's component positions in quad-tree - // - int posX, posY; - GetComponentsFromNodeIndex( ( index - minNodeIndex ), &posX, &posY ); - - // - // find the neighbor in the "direction" - // - switch( direction ) - { - case CCoreDispInfo::WEST: - { - if( ( posX - 1 ) < 0 ) - { - return -( CCoreDispInfo::WEST + 1 ); - } - else - { - return ( GetNodeIndexFromComponents( ( posX - 1 ), posY ) + minNodeIndex ); - } - } - case CCoreDispInfo::NORTH: - { - if( ( posY + 1 ) == nodeExtent ) - { - return -( CCoreDispInfo::NORTH + 1 ); - } - else - { - return ( GetNodeIndexFromComponents( posX, ( posY + 1 ) ) + minNodeIndex ); - } - } - case CCoreDispInfo::EAST: - { - if( ( posX + 1 ) == nodeExtent ) - { - return -( CCoreDispInfo::EAST + 1 ); - } - else - { - return ( GetNodeIndexFromComponents( ( posX + 1 ), posY ) + minNodeIndex ); - } - } - case CCoreDispInfo::SOUTH: - { - if( ( posY - 1 ) < 0 ) - { - return -( CCoreDispInfo::SOUTH + 1 ); - } - else - { - return ( GetNodeIndexFromComponents( posX, ( posY - 1 ) ) + minNodeIndex ); - } - } - default: - { - return -99999; - } - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int GetNodeNeighborNodeFromNeighborSurf( int power, int index, int direction, int level, int neighborOrient ) -{ - // adjust the index to range [0...?] - int minNodeIndex = GetNodeMinNodeAtLevel( level ); - - // get node extent (uniform: height = width) - int nodeExtent = ( 1 << ( level - 1 ) ); - - // - // get node's component positions in quad-tree - // - int posX, posY; - GetComponentsFromNodeIndex( ( index - minNodeIndex ), &posX, &posY ); - - switch( direction ) - { - case CCoreDispInfo::WEST: - { - switch( neighborOrient ) - { - case CCoreDispInfo::WEST: return -( ( GetNodeIndexFromComponents( posX, ( ( nodeExtent - 1 ) - posY ) ) ) + minNodeIndex ); - case CCoreDispInfo::NORTH: return -( ( GetNodeIndexFromComponents( ( nodeExtent - 1 ) - posY, ( nodeExtent - 1 ) ) ) + minNodeIndex ); - case CCoreDispInfo::EAST: return -( ( GetNodeIndexFromComponents( ( nodeExtent - 1 ), posY ) ) + minNodeIndex ); - case CCoreDispInfo::SOUTH: return -( ( GetNodeIndexFromComponents( posY, posX ) ) + minNodeIndex ); - default: return -99999; - } - } - case CCoreDispInfo::NORTH: - { - switch( neighborOrient ) - { - case CCoreDispInfo::WEST: return -( ( GetNodeIndexFromComponents( ( ( nodeExtent - 1 ) - posY ), ( ( nodeExtent - 1 ) - posX ) ) ) + minNodeIndex ); - case CCoreDispInfo::NORTH: return -( ( GetNodeIndexFromComponents( ( ( nodeExtent - 1 ) - posX ), posY ) ) + minNodeIndex ); - case CCoreDispInfo::EAST: return -( ( GetNodeIndexFromComponents( posY, posX ) ) + minNodeIndex ); - case CCoreDispInfo::SOUTH: return -( ( GetNodeIndexFromComponents( posX, ( ( nodeExtent - 1 ) - posY ) ) ) + minNodeIndex ); - default: return -99999; - } - } - case CCoreDispInfo::EAST: - { - switch( neighborOrient ) - { - case CCoreDispInfo::WEST: return -( ( GetNodeIndexFromComponents( ( ( nodeExtent - 1 ) - posX ), posY ) ) + minNodeIndex ); - case CCoreDispInfo::NORTH: return -( ( GetNodeIndexFromComponents( posY, posX ) ) + minNodeIndex ); - case CCoreDispInfo::EAST: return -( ( GetNodeIndexFromComponents( posX, ( ( nodeExtent - 1 ) - posY ) ) ) + minNodeIndex ); - case CCoreDispInfo::SOUTH: return -( ( GetNodeIndexFromComponents( ( ( nodeExtent - 1 ) - posY ), ( ( nodeExtent - 1 ) - posX ) ) ) + minNodeIndex ); - default: return -99999; - } - } - case CCoreDispInfo::SOUTH: - { - switch( neighborOrient ) - { - case CCoreDispInfo::WEST: return -( ( GetNodeIndexFromComponents( posY, posX ) ) + minNodeIndex ); - case CCoreDispInfo::NORTH: return -( ( GetNodeIndexFromComponents( posX, ( nodeExtent - 1 ) ) ) + minNodeIndex ); - case CCoreDispInfo::EAST: return -( ( GetNodeIndexFromComponents( ( nodeExtent - 1 ), ( ( nodeExtent - 1 ) - posX ) ) ) + minNodeIndex ); - case CCoreDispInfo::SOUTH: return -( ( GetNodeIndexFromComponents( ( ( nodeExtent - 1 ) - posX ), posY ) ) + minNodeIndex ); - default: return -99999; - } - } - default: - { - return -99999; - } - } -} - - - -// Turn the optimizer back on -#pragma optimize( "", on ) - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::GetPositionOnSurface( float u, float v, Vector &vPos, - Vector *pNormal, float *pAlpha ) -{ - Vector2D dispUV( u, v ); - DispUVToSurf( dispUV, vPos, pNormal, pAlpha ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::BaseFacePlaneToDispUV( Vector const &planePt, Vector2D &dispUV ) -{ - // Get the base surface points. - CCoreDispSurface *pSurf = GetSurface(); - Vector vecPoints[4]; - for( int iPoint = 0; iPoint < 4; ++iPoint ) - { - pSurf->GetPoint( iPoint, vecPoints[iPoint] ); - } - - PointInQuadToBarycentric( vecPoints[0], vecPoints[3], vecPoints[2], vecPoints[1], planePt, dispUV ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCoreDispInfo::DispUVToSurf_TriTLToBR_1( const Vector &vecIntersectPoint, - int nSnapU, int nNextU, int nSnapV, int nNextV, - Vector &vecPoint, Vector *pNormal, float *pAlpha, - bool bBackup ) -{ - int nWidth = GetWidth(); - - int nIndices[3]; - nIndices[0] = nNextV * nWidth + nSnapU; - nIndices[1] = nNextV * nWidth + nNextU; - nIndices[2] = nSnapV * nWidth + nNextU; - - Vector vecFlatVerts[3], vecVerts[3]; - float flAlphas[3]; - for ( int iVert = 0; iVert < 3; ++iVert ) - { - vecFlatVerts[iVert] = m_pVerts[nIndices[iVert]].m_FlatVert; - vecVerts[iVert] = m_pVerts[nIndices[iVert]].m_Vert; - flAlphas[iVert] = m_pVerts[nIndices[iVert]].m_Alpha; - } - - if ( nSnapU == nNextU ) - { - if ( nSnapV == nNextV ) - { - vecPoint = vecVerts[0]; - *pAlpha = flAlphas[0]; - } - else - { - float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length(); - vecPoint = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) ); - - if ( pAlpha ) - { - *pAlpha = flAlphas[0] + ( flFrac * ( flAlphas[2] - flAlphas[0] ) ); - } - } - - if( pNormal ) - { - Vector edgeU = vecVerts[0] - vecVerts[1]; - Vector edgeV = vecVerts[2] - vecVerts[1]; - *pNormal = CrossProduct( edgeU, edgeV ); - VectorNormalize( *pNormal ); - } - } - else if ( nSnapV == nNextV ) - { - if ( nSnapU == nNextU ) - { - vecPoint = vecVerts[0]; - *pAlpha = flAlphas[0]; - } - else - { - float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length(); - vecPoint = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) ); - - if ( pAlpha ) - { - *pAlpha = flAlphas[0] + ( flFrac * ( flAlphas[2] - flAlphas[0] ) ); - } - } - - if( pNormal ) - { - Vector edgeU = vecVerts[0] - vecVerts[1]; - Vector edgeV = vecVerts[2] - vecVerts[1]; - *pNormal = CrossProduct( edgeU, edgeV ); - VectorNormalize( *pNormal ); - } - } - else - { - float flCfs[3]; - if ( CalcBarycentricCooefs( vecFlatVerts[0], vecFlatVerts[1], vecFlatVerts[2], vecIntersectPoint, flCfs[0], flCfs[1], flCfs[2] ) ) - { - vecPoint = ( vecVerts[0] * flCfs[0] ) + ( vecVerts[1] * flCfs[1] ) + ( vecVerts[2] * flCfs[2] ); - - if( pAlpha ) - { - *pAlpha = ( flAlphas[0] * flCfs[0] ) + ( flAlphas[1] * flCfs[1] ) + ( flAlphas[2] * flCfs[2] ); - } - - if( pNormal ) - { - Vector edgeU = vecVerts[0] - vecVerts[1]; - Vector edgeV = vecVerts[2] - vecVerts[1]; - *pNormal = CrossProduct( edgeU, edgeV ); - VectorNormalize( *pNormal ); - } - } - else - { - if ( !bBackup ) - { - DispUVToSurf_TriTLToBR_2( vecIntersectPoint, nSnapU, nNextU, nSnapV, nNextV, vecPoint, pNormal, pAlpha, true ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCoreDispInfo::DispUVToSurf_TriTLToBR_2( const Vector &vecIntersectPoint, - int nSnapU, int nNextU, int nSnapV, int nNextV, - Vector &vecPoint, Vector *pNormal, float *pAlpha, - bool bBackup ) -{ - int nWidth = GetWidth(); - - int nIndices[3]; - nIndices[0] = nSnapV * nWidth + nSnapU; - nIndices[1] = nNextV * nWidth + nSnapU; - nIndices[2] = nSnapV * nWidth + nNextU; - - Vector vecFlatVerts[3], vecVerts[3]; - float flAlphas[3]; - for ( int iVert = 0; iVert < 3; ++iVert ) - { - vecFlatVerts[iVert] = m_pVerts[nIndices[iVert]].m_FlatVert; - vecVerts[iVert] = m_pVerts[nIndices[iVert]].m_Vert; - flAlphas[iVert] = m_pVerts[nIndices[iVert]].m_Alpha; - } - - if ( nSnapU == nNextU ) - { - if ( nSnapV == nNextV ) - { - vecPoint = vecVerts[0]; - *pAlpha = flAlphas[0]; - } - else - { - float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[1] - vecFlatVerts[0] ).Length(); - vecPoint = vecVerts[0] + ( flFrac * ( vecVerts[1] - vecVerts[0] ) ); - - if ( pAlpha ) - { - *pAlpha = flAlphas[0] + ( flFrac * ( flAlphas[1] - flAlphas[0] ) ); - } - } - - if( pNormal ) - { - Vector edgeU = vecVerts[2] - vecVerts[0]; - Vector edgeV = vecVerts[1] - vecVerts[0]; - *pNormal = CrossProduct( edgeU, edgeV ); - VectorNormalize( *pNormal ); - } - } - else if ( nSnapV == nNextV ) - { - if ( nSnapU == nNextU ) - { - vecPoint = vecVerts[0]; - *pAlpha = flAlphas[0]; - } - else - { - float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length(); - vecPoint = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) ); - - if ( pAlpha ) - { - *pAlpha = flAlphas[0] + ( flFrac * ( flAlphas[2] - flAlphas[0] ) ); - } - } - - if( pNormal ) - { - Vector edgeU = vecVerts[2] - vecVerts[0]; - Vector edgeV = vecVerts[1] - vecVerts[0]; - *pNormal = CrossProduct( edgeU, edgeV ); - VectorNormalize( *pNormal ); - } - } - else - { - float flCfs[3]; - if ( CalcBarycentricCooefs( vecFlatVerts[0], vecFlatVerts[1], vecFlatVerts[2], vecIntersectPoint, flCfs[0], flCfs[1], flCfs[2] ) ) - { - vecPoint = ( vecVerts[0] * flCfs[0] ) + ( vecVerts[1] * flCfs[1] ) + ( vecVerts[2] * flCfs[2] ); - - if( pAlpha ) - { - *pAlpha = ( flAlphas[0] * flCfs[0] ) + ( flAlphas[1] * flCfs[1] ) + ( flAlphas[2] * flCfs[2] ); - } - - if( pNormal ) - { - Vector edgeU = vecVerts[2] - vecVerts[0]; - Vector edgeV = vecVerts[1] - vecVerts[0]; - *pNormal = CrossProduct( edgeU, edgeV ); - VectorNormalize( *pNormal ); - } - } - else - { - if ( !bBackup ) - { - DispUVToSurf_TriTLToBR_1( vecIntersectPoint, nSnapU, nNextU, nSnapV, nNextV, vecPoint, pNormal, pAlpha, true ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCoreDispInfo::DispUVToSurf_TriTLToBR( Vector &vecPoint, Vector *pNormal, float *pAlpha, - float flU, float flV, const Vector &vecIntersectPoint ) -{ - const float TRIEDGE_EPSILON = 0.00001f; - - int nWidth = GetWidth(); - int nHeight = GetHeight(); - - int nSnapU = static_cast( flU ); - int nSnapV = static_cast( flV ); - int nNextU = nSnapU + 1; - int nNextV = nSnapV + 1; - if ( nNextU == nWidth) { --nNextU; } - if ( nNextV == nHeight ) { --nNextV; } - - float flFracU = flU - static_cast( nSnapU ); - float flFracV = flV - static_cast( nSnapV ); - - if ( ( flFracU + flFracV ) >= ( 1.0f + TRIEDGE_EPSILON ) ) - { - DispUVToSurf_TriTLToBR_1( vecIntersectPoint, nSnapU, nNextU, nSnapV, nNextV, vecPoint, pNormal, pAlpha, false ); - } - else - { - DispUVToSurf_TriTLToBR_2( vecIntersectPoint, nSnapU, nNextU, nSnapV, nNextV, vecPoint, pNormal, pAlpha, false ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCoreDispInfo::DispUVToSurf_TriBLToTR_1( const Vector &vecIntersectPoint, - int nSnapU, int nNextU, int nSnapV, int nNextV, - Vector &vecPoint, Vector *pNormal, float *pAlpha, - bool bBackup ) -{ - int nWidth = GetWidth(); - - int nIndices[3]; - nIndices[0] = nSnapV * nWidth + nSnapU; - nIndices[1] = nNextV * nWidth + nSnapU; - nIndices[2] = nNextV * nWidth + nNextU; - - Vector vecFlatVerts[3], vecVerts[3]; - float flAlphas[3]; - for ( int iVert = 0; iVert < 3; ++iVert ) - { - vecFlatVerts[iVert] = m_pVerts[nIndices[iVert]].m_FlatVert; - vecVerts[iVert] = m_pVerts[nIndices[iVert]].m_Vert; - flAlphas[iVert] = m_pVerts[nIndices[iVert]].m_Alpha; - } - - if ( nSnapU == nNextU ) - { - if ( nSnapV == nNextV ) - { - vecPoint = vecVerts[0]; - *pAlpha = flAlphas[0]; - } - else - { - float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length(); - vecPoint = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) ); - - if ( pAlpha ) - { - *pAlpha = flAlphas[0] + ( flFrac * ( flAlphas[2] - flAlphas[0] ) ); - } - } - - if( pNormal ) - { - Vector edgeU = vecVerts[2] - vecVerts[1]; - Vector edgeV = vecVerts[0] - vecVerts[1]; - *pNormal = CrossProduct( edgeU, edgeV ); - VectorNormalize( *pNormal ); - } - } - else if ( nSnapV == nNextV ) - { - if ( nSnapU == nNextU ) - { - vecPoint = vecVerts[0]; - *pAlpha = flAlphas[0]; - } - else - { - float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length(); - vecPoint = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) ); - - if ( pAlpha ) - { - *pAlpha = flAlphas[0] + ( flFrac * ( flAlphas[2] - flAlphas[0] ) ); - } - } - - if( pNormal ) - { - Vector edgeU = vecVerts[2] - vecVerts[1]; - Vector edgeV = vecVerts[0] - vecVerts[1]; - *pNormal = CrossProduct( edgeV, edgeU ); - VectorNormalize( *pNormal ); - } - } - else - { - float flCfs[3]; - if ( CalcBarycentricCooefs( vecFlatVerts[0], vecFlatVerts[1], vecFlatVerts[2], vecIntersectPoint, flCfs[0], flCfs[1], flCfs[2] ) ) - { - vecPoint = ( vecVerts[0] * flCfs[0] ) + ( vecVerts[1] * flCfs[1] ) + ( vecVerts[2] * flCfs[2] ); - - if( pAlpha ) - { - *pAlpha = ( flAlphas[0] * flCfs[0] ) + ( flAlphas[1] * flCfs[1] ) + ( flAlphas[2] * flCfs[2] ); - } - - if( pNormal ) - { - Vector edgeU = vecVerts[2] - vecVerts[1]; - Vector edgeV = vecVerts[0] - vecVerts[1]; - *pNormal = CrossProduct( edgeV, edgeU ); - VectorNormalize( *pNormal ); - } - } - else - { - if ( !bBackup ) - { - DispUVToSurf_TriBLToTR_2( vecIntersectPoint, nSnapU, nNextU, nSnapV, nNextV, vecPoint, pNormal, pAlpha, true ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCoreDispInfo::DispUVToSurf_TriBLToTR_2( const Vector &vecIntersectPoint, - int nSnapU, int nNextU, int nSnapV, int nNextV, - Vector &vecPoint, Vector *pNormal, float *pAlpha, - bool bBackup ) -{ - int nWidth = GetWidth(); - - int nIndices[3]; - nIndices[0] = nSnapV * nWidth + nSnapU; - nIndices[1] = nNextV * nWidth + nNextU; - nIndices[2] = nSnapV * nWidth + nNextU; - - Vector vecFlatVerts[3], vecVerts[3]; - float flAlphas[3]; - for ( int iVert = 0; iVert < 3; ++iVert ) - { - vecFlatVerts[iVert] = m_pVerts[nIndices[iVert]].m_FlatVert; - vecVerts[iVert] = m_pVerts[nIndices[iVert]].m_Vert; - flAlphas[iVert] = m_pVerts[nIndices[iVert]].m_Alpha; - } - - if ( nSnapU == nNextU ) - { - if ( nSnapV == nNextV ) - { - vecPoint = vecVerts[0]; - *pAlpha = flAlphas[0]; - } - else - { - float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[1] - vecFlatVerts[0] ).Length(); - vecPoint = vecVerts[0] + ( flFrac * ( vecVerts[1] - vecVerts[0] ) ); - - if ( pAlpha ) - { - *pAlpha = flAlphas[0] + ( flFrac * ( flAlphas[1] - flAlphas[0] ) ); - } - } - - if( pNormal ) - { - Vector edgeU = vecVerts[0] - vecVerts[2]; - Vector edgeV = vecVerts[1] - vecVerts[2]; - *pNormal = CrossProduct( edgeV, edgeU ); - VectorNormalize( *pNormal ); - } - } - else if ( nSnapV == nNextV ) - { - if ( nSnapU == nNextU ) - { - vecPoint = vecVerts[0]; - *pAlpha = flAlphas[0]; - } - else - { - float flFrac = ( vecIntersectPoint - vecFlatVerts[0] ).Length() / ( vecFlatVerts[2] - vecFlatVerts[0] ).Length(); - vecPoint = vecVerts[0] + ( flFrac * ( vecVerts[2] - vecVerts[0] ) ); - - if ( pAlpha ) - { - *pAlpha = flAlphas[0] + ( flFrac * ( flAlphas[2] - flAlphas[0] ) ); - } - } - - if( pNormal ) - { - Vector edgeU = vecVerts[0] - vecVerts[2]; - Vector edgeV = vecVerts[1] - vecVerts[2]; - *pNormal = CrossProduct( edgeV, edgeU ); - VectorNormalize( *pNormal ); - } - } - else - { - float flCfs[3]; - if ( CalcBarycentricCooefs( vecFlatVerts[0], vecFlatVerts[1], vecFlatVerts[2], vecIntersectPoint, flCfs[0], flCfs[1], flCfs[2] ) ) - { - vecPoint = ( vecVerts[0] * flCfs[0] ) + ( vecVerts[1] * flCfs[1] ) + ( vecVerts[2] * flCfs[2] ); - - if( pAlpha ) - { - *pAlpha = ( flAlphas[0] * flCfs[0] ) + ( flAlphas[1] * flCfs[1] ) + ( flAlphas[2] * flCfs[2] ); - } - - if( pNormal ) - { - Vector edgeU = vecVerts[0] - vecVerts[2]; - Vector edgeV = vecVerts[1] - vecVerts[2]; - *pNormal = CrossProduct( edgeV, edgeU ); - VectorNormalize( *pNormal ); - } - } - else - { - if ( !bBackup ) - { - DispUVToSurf_TriBLToTR_1( vecIntersectPoint, nSnapU, nNextU, nSnapV, nNextV, vecPoint, pNormal, pAlpha, true ); - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCoreDispInfo::DispUVToSurf_TriBLToTR( Vector &vecPoint, Vector *pNormal, float *pAlpha, - float flU, float flV, const Vector &vecIntersectPoint ) -{ - int nWidth = GetWidth(); - int nHeight = GetHeight(); - - int nSnapU = static_cast( flU ); - int nSnapV = static_cast( flV ); - int nNextU = nSnapU + 1; - int nNextV = nSnapV + 1; - if ( nNextU == nWidth) { --nNextU; } - if ( nNextV == nHeight ) { --nNextV; } - - float flFracU = flU - static_cast( nSnapU ); - float flFracV = flV - static_cast( nSnapV ); - - if( flFracU < flFracV ) - { - DispUVToSurf_TriBLToTR_1( vecIntersectPoint, nSnapU, nNextU, nSnapV, nNextV, vecPoint, pNormal, pAlpha, false ); - } - else - { - DispUVToSurf_TriBLToTR_2( vecIntersectPoint, nSnapU, nNextU, nSnapV, nNextV, vecPoint, pNormal, pAlpha, false ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::DispUVToSurf( Vector2D const &dispUV, Vector &vecPoint, - Vector *pNormal, float *pAlpha ) -{ - // Check to see that the point is on the surface. - if ( dispUV.x < 0.0f || dispUV.x > 1.0f || dispUV.y < 0.0f || dispUV.y > 1.0f ) - return; - - // Get the base surface points. - Vector vecIntersectPoint; - CCoreDispSurface *pSurf = GetSurface(); - PointInQuadFromBarycentric( pSurf->GetPoint( 0 ), pSurf->GetPoint( 3 ), pSurf->GetPoint( 2 ), pSurf->GetPoint( 1 ), dispUV, vecIntersectPoint ); - - // Get the displacement power. - int nWidth = GetWidth(); - int nHeight = GetHeight(); - - // Scale the U, V coordinates to the displacement grid size. - float flU = dispUV.x * ( static_cast( nWidth ) - 1.000001f ); - float flV = dispUV.y * ( static_cast( nHeight ) - 1.000001f ); - - // Find the base U, V. - int nSnapU = static_cast( flU ); - int nSnapV = static_cast( flV ); - - // Use this to get the triangle orientation. - bool bOdd = ( ( ( nSnapV * nWidth ) + nSnapU ) % 2 == 1 ); - - // Top Left to Bottom Right - if( bOdd ) - { - DispUVToSurf_TriTLToBR( vecPoint, pNormal, pAlpha, flU, flV, vecIntersectPoint ); - } - // Bottom Left to Top Right - else - { - DispUVToSurf_TriBLToTR( vecPoint, pNormal, pAlpha, flU, flV, vecIntersectPoint ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Create bounding boxes around pairs of triangles (in a grid-like) -// fashion; used for culling -//----------------------------------------------------------------------------- -void CCoreDispInfo::CreateBoundingBoxes( CoreDispBBox_t *pBBox, int count ) -{ - // - // Initialize the bounding boxes. - // - int iBox; - for( iBox = 0; iBox < count; ++iBox ) - { - pBBox[iBox].vMin.Init( FLT_MAX, FLT_MAX, FLT_MAX ); - pBBox[iBox].vMax.Init( FLT_MIN, FLT_MIN, FLT_MIN ); - } - - // Get the width and height of the displacement surface. - int nHeight = GetHeight(); - int nWidth = GetWidth(); - - // Find bounding box of every two consecutive triangles - iBox = 0; - int nIndex = 0; - for( int iHgt = 0; iHgt < ( nHeight - 1 ); ++iHgt ) - { - for( int iWid = 0; iWid < ( nWidth - 1 ); ++iWid ) - { - for( int iPoint = 0; iPoint < 4; ++iPoint ) - { - switch( iPoint ) - { - case 0: { nIndex = ( nHeight * iHgt ) + iWid; break; } - case 1: { nIndex = ( nHeight * ( iHgt + 1 ) ) + iWid; break; } - case 2: { nIndex = ( nHeight * ( iHgt + 1 ) ) + ( iWid + 1 ); break; } - case 3: { nIndex = ( nHeight * iHgt ) + ( iWid + 1 ); break; } - default: { break; } - } - - Vector vecPoint; - GetVert( nIndex, vecPoint ); - if( vecPoint[0] < pBBox[iBox].vMin[0] ) { pBBox[iBox].vMin[0] = vecPoint[0]; } - if( vecPoint[1] < pBBox[iBox].vMin[1] ) { pBBox[iBox].vMin[1] = vecPoint[1]; } - if( vecPoint[2] < pBBox[iBox].vMin[2] ) { pBBox[iBox].vMin[2] = vecPoint[2]; } - - if( vecPoint[0] > pBBox[iBox].vMax[0] ) { pBBox[iBox].vMax[0] = vecPoint[0]; } - if( vecPoint[1] > pBBox[iBox].vMax[1] ) { pBBox[iBox].vMax[1] = vecPoint[1]; } - if( vecPoint[2] > pBBox[iBox].vMax[2] ) { pBBox[iBox].vMax[2] = vecPoint[2]; } - } - - iBox++; - } - } - - // Verify. - Assert( iBox == count ); - - // Bloat. - for ( iBox = 0; iBox < count; ++iBox ) - { - for( int iAxis = 0; iAxis < 3; ++iAxis ) - { - pBBox[iBox].vMin[iAxis] -= 1.0f; - pBBox[iBox].vMax[iAxis] += 1.0f; - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline bool PointInDispBBox( CoreDispBBox_t *pBox, const Vector &vecPoint ) -{ - // Check to see if point lies in box - if( ( vecPoint.x < pBox->vMin.x ) || ( vecPoint.x > pBox->vMax.x ) ) - return false; - - if( ( vecPoint.y < pBox->vMin.y ) || ( vecPoint.y > pBox->vMax.y ) ) - return false; - - if( ( vecPoint.z < pBox->vMin.z ) || ( vecPoint.z > pBox->vMax.z ) ) - return false; - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void CCoreDispInfo::GetTriangleIndicesForDispBBox( int nIndex, int nTris[2][3] ) -{ - // Test to see whether or not the index is odd. - bool bOdd = ( ( nIndex % 2 ) == 1 ); - - int nWidth = GetWidth(); - - // Tris for TLtoBR - if ( bOdd ) - { - nTris[0][0] = nIndex; - nTris[0][1] = nIndex + nWidth; - nTris[0][2] = nIndex + 1; - - nTris[1][0] = nIndex + 1; - nTris[1][1] = nIndex + nWidth; - nTris[1][2] = nIndex + nWidth + 1; - } - // Tris for BLtoTR - else - { - nTris[0][0] = nIndex; - nTris[0][1] = nIndex + nWidth; - nTris[0][2] = nIndex + nWidth + 1; - - nTris[1][0] = nIndex; - nTris[1][1] = nIndex + nWidth + 1; - nTris[1][2] = nIndex + 1; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CCoreDispInfo::SurfToBaseFacePlane( Vector const &surfPt, Vector &planePt ) -{ - // Create bounding boxes - int nBoxCount = ( GetHeight() - 1 ) * ( GetWidth() - 1 ); - CoreDispBBox_t *pBBox = new CoreDispBBox_t[nBoxCount]; - CreateBoundingBoxes( pBBox, nBoxCount ); - - // Use the boxes as a first-pass culling mechanism. - for( int iBox = 0; iBox < nBoxCount; ++iBox ) - { - // Get the current displacement triangle-pair bounding-box. - CoreDispBBox_t *pBox = &pBBox[iBox]; - if( !pBox ) - continue; - - // Check the point against the current displacement bounding-box. - if ( !PointInDispBBox( pBox, surfPt ) ) - continue; - - // Point lies within the bounding box. - int nIndex = iBox + ( iBox / ( GetWidth() - 1 ) ); - - // Get the triangle coordinates for this box. - int aTris[2][3]; - GetTriangleIndicesForDispBBox( nIndex, aTris ); - - // Barycentrically test the triangles on the displacement surface. - Vector vecPoints[3]; - for ( int iTri = 0; iTri < 2; ++iTri ) - { - for ( int iVert = 0; iVert < 3; ++iVert ) - { - GetVert( aTris[iTri][iVert], vecPoints[iVert] ); - } - - float c[3]; - if ( CalcBarycentricCooefs( vecPoints[0], vecPoints[1], vecPoints[2], surfPt, c[0], c[1], c[2] ) ) - { - Vector vecFlatPoints[3]; - for ( int iVert = 0; iVert < 3; ++iVert ) - { - GetFlatVert( aTris[iTri][iVert], vecFlatPoints[iVert] ); - } - - planePt = ( vecFlatPoints[0] * c[0] ) + ( vecFlatPoints[1] * c[1] ) + ( vecFlatPoints[2] * c[2] ); - - // Delete temporary memory. - delete [] pBBox; - return true; - } - } - } - - // Delete temporary memory - delete [] pBBox; - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CCoreDispInfo::GetTriCount( void ) -{ - return ( ( GetHeight() - 1 ) * ( GetWidth() -1 ) * 2 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCoreDispInfo::GetTriIndices( int iTri, unsigned short &v1, unsigned short &v2, unsigned short &v3 ) -{ - // Verify we have the correct data (only build when collision data is built). - if ( !m_pTris || ( iTri < 0 ) || ( iTri >= GetTriCount() ) ) - { - Assert( iTri >= 0 ); - Assert( iTri < GetTriCount() ); - Assert( m_pTris ); - return; - } - - CoreDispTri_t *pTri = &m_pTris[iTri]; - v1 = pTri->m_iIndex[0]; - v2 = pTri->m_iIndex[1]; - v3 = pTri->m_iIndex[2]; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCoreDispInfo::SetTriIndices( int iTri, unsigned short v1, unsigned short v2, unsigned short v3 ) -{ - // Verify we have the correct data (only build when collision data is built). - if ( !m_pTris || ( iTri < 0 ) || ( iTri >= GetTriCount() ) ) - { - Assert( iTri >= 0 ); - Assert( iTri < GetTriCount() ); - Assert( m_pTris ); - return; - } - - CoreDispTri_t *pTri = &m_pTris[iTri]; - pTri->m_iIndex[0] = v1; - pTri->m_iIndex[1] = v2; - pTri->m_iIndex[2] = v3; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCoreDispInfo::GetTriPos( int iTri, Vector &v1, Vector &v2, Vector &v3 ) -{ - // Verify we have the correct data (only build when collision data is built). - if ( !m_pTris || ( iTri < 0 ) || ( iTri >= GetTriCount() ) ) - { - Assert( iTri >= 0 ); - Assert( iTri < GetTriCount() ); - Assert( m_pTris ); - return; - } - - CoreDispTri_t *pTri = &m_pTris[iTri]; - v1 = m_pVerts[pTri->m_iIndex[0]].m_Vert; - v2 = m_pVerts[pTri->m_iIndex[1]].m_Vert; - v3 = m_pVerts[pTri->m_iIndex[2]].m_Vert; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCoreDispInfo::InitTris( void ) -{ - // Verify we have the correct data (only build when collision data is built). - if ( !m_pTris ) - { - Assert( m_pTris ); - return; - } - - int nTriCount = GetTriCount(); - for ( int iTri = 0; iTri < nTriCount; ++iTri ) - { - m_pTris[iTri].m_uiTags = 0; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCoreDispInfo::CreateTris( void ) -{ - // Verify we have the correct data (only build when collision data is built). - if ( !m_pTris ) - { - Assert( m_pTris ); - return; - } - - // Extra sanity check if wanted! - Assert( GetTriCount() == ( m_RenderIndexCount / 3 ) ); - - int nTriCount = GetTriCount(); - for ( int iTri = 0, iRender = 0; iTri < nTriCount; ++iTri, iRender += 3 ) - { - m_pTris[iTri].m_iIndex[0] = m_RenderIndices[iRender]; - m_pTris[iTri].m_iIndex[1] = m_RenderIndices[iRender+1]; - m_pTris[iTri].m_iIndex[2] = m_RenderIndices[iRender+2]; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CCoreDispInfo::IsTriWalkable( int iTri ) -{ - if ( IsTriTag( iTri, COREDISPTRI_TAG_FORCE_WALKABLE_BIT ) ) - { - return IsTriTag( iTri, COREDISPTRI_TAG_FORCE_WALKABLE_VAL ); - } - - return IsTriTag( iTri, COREDISPTRI_TAG_WALKABLE ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CCoreDispInfo::IsTriBuildable( int iTri ) -{ - if ( IsTriTag( iTri, COREDISPTRI_TAG_FORCE_BUILDABLE_BIT ) ) - { - return IsTriTag( iTri, COREDISPTRI_TAG_FORCE_BUILDABLE_VAL ); - } - - return IsTriTag( iTri, COREDISPTRI_TAG_BUILDABLE ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CCoreDispInfo::Position_Update( int iVert, Vector vecPos ) -{ - Vector vSPos, vFlat; - GetFlatVert( iVert, vFlat ); - GetSubdivPosition( iVert, vSPos ); - - Vector vSeg; - vSeg = vecPos - vFlat; - vSeg -= vSPos; - - // Subtract out the elevation. - float elev = GetElevation(); - if( elev != 0.0 ) - { - Vector vNormal; - GetSurface()->GetNormal( vNormal ); - vNormal *= elev; - - vSeg -= vNormal; - } - - float flDistance = VectorNormalize( vSeg ); - - SetFieldVector( iVert, vSeg ); - SetFieldDistance( iVert, flDistance ); -} diff --git a/public/builddisp.h b/public/builddisp.h deleted file mode 100644 index 6bc911f88..000000000 --- a/public/builddisp.h +++ /dev/null @@ -1,1458 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef BUILDDISP_H -#define BUILDDISP_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "commonmacros.h" -#include "tier0/dbg.h" -#include "bspfile.h" -#include "mathlib/mathlib.h" -#include "mathlib/bumpvects.h" -#include "disp_common.h" -#include "bitvec.h" - -#define DISP_ALPHA_PROP_DELTA 382.5f - -class CCoreDispInfo; - -struct CoreDispBBox_t -{ - Vector vMin, vMax; -}; - -//========================================================================= -// -// Surface Class - interfacing class (fill in with MapFace, dface_t, and -// msurface_t) -// -class CCoreDispSurface -{ -public: - - enum { QUAD_POINT_COUNT = 4 }; - enum { MAX_CORNER_NEIGHBOR_COUNT = 16 }; - - CCoreDispSurface(); - - //========================================================================= - // - // initialization - // - void Init( void ); - - //========================================================================= - // - // parent surface id - index to CMapFace, dface_t, or msurface_t - // - inline void SetHandle( int handle ); - inline int GetHandle( void ); - - //========================================================================= - // - // vertex data - pos, normal, texture, lightmap, alpha, etc... - // - inline void SetPointCount( int count ); - inline int GetPointCount( void ) const; - - inline void SetPoint( int index, Vector const &pt ); - inline void GetPoint( int index, Vector& pt ) const; - inline Vector const& GetPoint( int index ) const; - - inline void SetPointNormal( int index, Vector const &normal ); - inline void GetPointNormal( int index, Vector &normal ); - inline void SetTexCoord( int index, Vector2D const& texCoord ); - inline void GetTexCoord( int index, Vector2D& texCoord ) const; - - inline void SetLuxelCoord( int bumpIndex, int index, Vector2D const& luxelCoord ); - inline void GetLuxelCoord( int bumpIndex, int index, Vector2D& luxelCoord ) const; - inline void SetLuxelCoords( int bumpIndex, Vector2D const coords[4] ); - inline void GetLuxelCoords( int bumpIndex, Vector2D coords[4] ) const; - - inline void SetLuxelU( int nU ) { m_nLuxelU = nU; } - inline int GetLuxelU( void ) { return m_nLuxelU; } - inline void SetLuxelV( int nV ) { m_nLuxelV = nV; } - inline int GetLuxelV( void ) { return m_nLuxelV; } - bool CalcLuxelCoords( int nLuxels, bool bAdjust, const Vector &vecU, const Vector &vecV ); - - inline void SetAlpha( int index, float alpha ); - inline float GetAlpha( int const index ) const; - - //========================================================================= - // - // utils - // - inline void GetNormal( Vector& normal ); - inline void SetFlags( int flag ); - inline int GetFlags( void ); - inline void SetContents( int contents ); - inline int GetContents( void ); - - //========================================================================= - // - // create utils (texture axis not use anymore but here to support older maps) - // - inline void SetSAxis( Vector const &axis ); - inline void GetSAxis( Vector &axis ); - inline void SetTAxis( Vector const &axis ); - inline void GetTAxis( Vector &axis ); - - inline void SetPointStartIndex( int index ); - inline int GetPointStartIndex( void ); - inline void SetPointStart( Vector const &pt ); - inline void GetPointStart( Vector &pt ); - - // Used by the tools to set the neighbor data from the BSP file. - void SetNeighborData( const CDispNeighbor edgeNeighbors[4], const CDispCornerNeighbors cornerNeighbors[4] ); - - void GeneratePointStartIndexFromMappingAxes( Vector const &sAxis, Vector const &tAxis ); - int GenerateSurfPointStartIndex( void ); - int FindSurfPointStartIndex( void ); - void AdjustSurfPointData( void ); - - // Indexed by CORNER_ defines. - CDispCornerNeighbors* GetCornerNeighbors( int iCorner ) { Assert( iCorner >= 0 && iCorner < ARRAYSIZE( m_CornerNeighbors ) ); return &m_CornerNeighbors[iCorner]; } - const CDispCornerNeighbors* GetCornerNeighbors( int iCorner ) const { Assert( iCorner >= 0 && iCorner < ARRAYSIZE( m_CornerNeighbors ) ); return &m_CornerNeighbors[iCorner]; } - - // Indexed by CORNER_ defines. - int GetCornerNeighborCount( int iCorner ) const { return GetCornerNeighbors( iCorner )->m_nNeighbors; } - int GetCornerNeighbor( int iCorner, int iNeighbor ) const { Assert( iNeighbor >= 0 && iNeighbor < GetCornerNeighbors(iCorner)->m_nNeighbors ); return GetCornerNeighbors( iCorner )->m_Neighbors[iNeighbor]; } - - CDispNeighbor* GetEdgeNeighbor( int iEdge ) { Assert( iEdge >= 0 && iEdge < ARRAYSIZE( m_EdgeNeighbors ) ); return &m_EdgeNeighbors[iEdge]; } - const CDispNeighbor* GetEdgeNeighbor( int iEdge ) const { Assert( iEdge >= 0 && iEdge < ARRAYSIZE( m_EdgeNeighbors ) ); return &m_EdgeNeighbors[iEdge]; } - - -protected: - - // Utility - bool LongestInU( const Vector &vecU, const Vector &vecV ); - - - int m_Index; // parent face (CMapFace, dface_t, msurface_t) index "handle" - - int m_PointCount; // number of points in the face (should be 4!) - Vector m_Points[QUAD_POINT_COUNT]; // points - Vector m_Normals[QUAD_POINT_COUNT]; // normals at points - Vector2D m_TexCoords[QUAD_POINT_COUNT]; // texture coordinates at points - Vector2D m_LuxelCoords[NUM_BUMP_VECTS+1][QUAD_POINT_COUNT]; // lightmap coordinates at points - float m_Alphas[QUAD_POINT_COUNT]; // alpha at points - - // Luxels sizes - int m_nLuxelU; - int m_nLuxelV; - - // Straight from the BSP file. - CDispNeighbor m_EdgeNeighbors[4]; - CDispCornerNeighbors m_CornerNeighbors[4]; - - int m_Flags; // surface flags - inherited from the "parent" face - int m_Contents; // contents flags - inherited from the "parent" face - - Vector sAxis; // used to generate start disp orientation (old method) - Vector tAxis; // used to generate start disp orientation (old method) - int m_PointStartIndex; // index to the starting point -- for saving starting point - Vector m_PointStart; // starting point used to determine the orientation of the displacement map on the surface -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispSurface::SetHandle( int handle ) -{ - m_Index = handle; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline int CCoreDispSurface::GetHandle( void ) -{ - return m_Index; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispSurface::SetPointCount( int count ) -{ - // quad only -- currently! - if( count != 4 ) - return; - m_PointCount = count; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline int CCoreDispSurface::GetPointCount( void ) const -{ - return m_PointCount; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispSurface::SetPoint( int index, Vector const &pt ) -{ - Assert( index >= 0 ); - Assert( index < QUAD_POINT_COUNT ); - VectorCopy( pt, m_Points[index] ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispSurface::GetPoint( int index, Vector &pt ) const -{ - Assert( index >= 0 ); - Assert( index < QUAD_POINT_COUNT ); - VectorCopy( m_Points[index], pt ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline Vector const& CCoreDispSurface::GetPoint( int index ) const -{ - Assert( index >= 0 ); - Assert( index < QUAD_POINT_COUNT ); - return m_Points[index]; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispSurface::SetPointNormal( int index, Vector const &normal ) -{ - Assert( index >= 0 ); - Assert( index < QUAD_POINT_COUNT ); - VectorCopy( normal, m_Normals[index] ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispSurface::GetPointNormal( int index, Vector& normal ) -{ - Assert( index >= 0 ); - Assert( index < QUAD_POINT_COUNT ); - VectorCopy( m_Normals[index], normal ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispSurface::SetTexCoord( int index, Vector2D const& texCoord ) -{ - Assert( index >= 0 ); - Assert( index < QUAD_POINT_COUNT ); - Vector2DCopy( texCoord, m_TexCoords[index] ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispSurface::GetTexCoord( int index, Vector2D& texCoord ) const -{ - Assert( index >= 0 ); - Assert( index < QUAD_POINT_COUNT ); - Vector2DCopy( m_TexCoords[index], texCoord ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispSurface::SetLuxelCoord( int bumpIndex, int index, Vector2D const& luxelCoord ) -{ - Assert( index >= 0 ); - Assert( index < QUAD_POINT_COUNT ); - Assert( bumpIndex >= 0 ); - Assert( bumpIndex < NUM_BUMP_VECTS + 1 ); - Vector2DCopy( luxelCoord, m_LuxelCoords[bumpIndex][index] ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispSurface::GetLuxelCoord( int bumpIndex, int index, Vector2D& luxelCoord ) const -{ - Assert( index >= 0 ); - Assert( index < QUAD_POINT_COUNT ); - Assert( bumpIndex >= 0 ); - Assert( bumpIndex < NUM_BUMP_VECTS + 1 ); - Vector2DCopy( m_LuxelCoords[bumpIndex][index], luxelCoord ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispSurface::SetLuxelCoords( int bumpIndex, Vector2D const luxelCoords[4] ) -{ - Assert( bumpIndex >= 0 ); - Assert( bumpIndex < NUM_BUMP_VECTS + 1 ); - for( int i=0; i < 4; i++ ) - Vector2DCopy( luxelCoords[i], m_LuxelCoords[bumpIndex][i] ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispSurface::GetLuxelCoords( int bumpIndex, Vector2D luxelCoords[4] ) const -{ - Assert( bumpIndex >= 0 ); - Assert( bumpIndex < NUM_BUMP_VECTS + 1 ); - for( int i=0; i < 4; i++ ) - Vector2DCopy( m_LuxelCoords[bumpIndex][i], luxelCoords[i] ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispSurface::SetAlpha( int index, float alpha ) -{ - Assert( index >= 0 ); - Assert( index < QUAD_POINT_COUNT ); - m_Alphas[index] = alpha; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline float CCoreDispSurface::GetAlpha( int const index ) const -{ - Assert( index >= 0 ); - Assert( index < QUAD_POINT_COUNT ); - return m_Alphas[index]; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispSurface::SetFlags( int flag ) -{ - m_Flags = flag; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline int CCoreDispSurface::GetFlags( void ) -{ - return m_Flags; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispSurface::SetContents( int contents ) -{ - m_Contents = contents; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline int CCoreDispSurface::GetContents( void ) -{ - return m_Contents; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispSurface::SetSAxis( Vector const &axis ) -{ - VectorCopy( axis, sAxis ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispSurface::GetSAxis( Vector& axis ) -{ - VectorCopy( sAxis, axis ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispSurface::SetTAxis( Vector const &axis ) -{ - VectorCopy( axis, tAxis ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispSurface::GetTAxis( Vector& axis ) -{ - VectorCopy( tAxis, axis ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispSurface::SetPointStartIndex( int index ) -{ - Assert( index >= 0 ); - Assert( index < QUAD_POINT_COUNT ); - m_PointStartIndex = index; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline int CCoreDispSurface::GetPointStartIndex( void ) -{ - return m_PointStartIndex; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispSurface::SetPointStart( Vector const& pt ) -{ - VectorCopy( pt, m_PointStart ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispSurface::GetPointStart( Vector& pt ) -{ - VectorCopy( m_PointStart, pt ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispSurface::GetNormal( Vector& normal ) -{ - // - // calculate the displacement surface normal - // - Vector tmp[2]; - VectorSubtract( m_Points[1], m_Points[0], tmp[0] ); - VectorSubtract( m_Points[3], m_Points[0], tmp[1] ); - CrossProduct( tmp[1], tmp[0], normal ); - VectorNormalize( normal ); -} - - -//========================================================================= -// -// Node Class (for displacement quad-tree) -// -class CCoreDispNode -{ -public: - - enum { MAX_NEIGHBOR_NODE_COUNT = 4 }; - enum { MAX_NEIGHBOR_VERT_COUNT = 8 }; - enum { MAX_SURF_AT_NODE_COUNT = 8 }; - - //========================================================================= - // - // Initialization - // - void Init( void ); - - //========================================================================= - // - // - // - inline void SetBoundingBox( Vector const& bMin, Vector const& bMax ); - inline void GetBoundingBox( Vector& bMin, Vector& bMax ); - - inline void SetErrorTerm( float errorTerm ); - inline float GetErrorTerm( void ); - - inline void SetNeighborNodeIndex( int dir, int index ); - inline int GetNeighborNodeIndex( int dir ); - - inline void SetCenterVertIndex( int index ); - inline int GetCenterVertIndex( void ); - inline void SetNeighborVertIndex( int dir, int index ); - inline int GetNeighborVertIndex( int dir ); - - inline void SetTriBoundingBox( int index, Vector const& bMin, Vector const& bMax ); - inline void GetTriBoundingBox( int index, Vector& bMin, Vector& bMax ); - inline void SetTriPlane( int index, Vector const& normal, float dist ); - inline void GetTriPlane( int index, cplane_t *plane ); - - inline void SetRayBoundingBox( int index, Vector const& bMin, Vector const& bMax ); - inline void GetRayBoundingBox( int index, Vector& bMin, Vector& bMax ); - - //========================================================================= - // - // Node Functions (friend functions) - // - friend int GetNodeLevel( int index ); - friend int GetNodeCount( int power ); - friend int GetNodeParent( int index ); - friend int GetNodeChild( int power, int index, int direction ); - friend int GetNodeNeighborNode( int power, int index, int direction, int level ); - friend int GetNodeNeighborNodeFromNeighborSurf( int power, int index, int direction, int level, int neighborOrient ); - friend int GetNodeMinNodeAtLevel( int level ); - - friend void GetDispNodeTriVerts( CCoreDispInfo *pDisp, int nodeIndex, int triIndex, float *v1, float *v2, float *v3 ); - - friend void GetComponentsFromNodeIndex( int index, int *x, int *y ); - friend int GetNodeIndexFromComponents( int x, int y ); - -protected: - - Vector m_BBox[2]; // displacement node bounding box (take into account size of children) - float m_ErrorTerm; // LOD error term (the "precision" of the representation of the surface at this node's level) - int m_VertIndex; // the node's vertex index (center vertex of node) - int m_NeighborVertIndices[MAX_NEIGHBOR_VERT_COUNT]; // all other vertex indices in node (maximally creates 8 trianglar surfaces) - Vector m_SurfBBoxes[MAX_SURF_AT_NODE_COUNT][2]; // surface bounding boxes - old method - cplane_t m_SurfPlanes[MAX_SURF_AT_NODE_COUNT]; // surface plane info - old method - - Vector m_RayBBoxes[4][2]; // bounding boxes for ray traces -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispNode::SetBoundingBox( Vector const& bMin, Vector const& bMax ) -{ - VectorCopy( bMin, m_BBox[0] ); - VectorCopy( bMax, m_BBox[1] ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispNode::GetBoundingBox( Vector& bMin, Vector& bMax ) -{ - VectorCopy( m_BBox[0], bMin ); - VectorCopy( m_BBox[1], bMax ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispNode::SetErrorTerm( float errorTerm ) -{ - m_ErrorTerm = errorTerm; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline float CCoreDispNode::GetErrorTerm( void ) -{ - return m_ErrorTerm; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispNode::SetCenterVertIndex( int index ) -{ - m_VertIndex = index; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline int CCoreDispNode::GetCenterVertIndex( void ) -{ - return m_VertIndex; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispNode::SetNeighborVertIndex( int dir, int index ) -{ - Assert( dir >= 0 ); - Assert( dir < MAX_NEIGHBOR_VERT_COUNT ); - m_NeighborVertIndices[dir] = index; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline int CCoreDispNode::GetNeighborVertIndex( int dir ) -{ - Assert( dir >= 0 ); - Assert( dir < MAX_NEIGHBOR_VERT_COUNT ); - return m_NeighborVertIndices[dir]; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispNode::SetTriBoundingBox( int index, Vector const& bMin, Vector const& bMax ) -{ - Assert( index >= 0 ); - Assert( index < MAX_SURF_AT_NODE_COUNT ); - VectorCopy( bMin, m_SurfBBoxes[index][0] ); - VectorCopy( bMax, m_SurfBBoxes[index][1] ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispNode::GetTriBoundingBox( int index, Vector& bMin, Vector& bMax ) -{ - Assert( index >= 0 ); - Assert( index < MAX_SURF_AT_NODE_COUNT ); - VectorCopy( m_SurfBBoxes[index][0], bMin ); - VectorCopy( m_SurfBBoxes[index][1], bMax ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispNode::SetTriPlane( int index, Vector const &normal, float dist ) -{ - Assert( index >= 0 ); - Assert( index < MAX_SURF_AT_NODE_COUNT ); - VectorCopy( normal, m_SurfPlanes[index].normal ); - m_SurfPlanes[index].dist = dist; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispNode::GetTriPlane( int index, cplane_t *plane ) -{ - Assert( index >= 0 ); - Assert( index < MAX_SURF_AT_NODE_COUNT ); - VectorCopy( m_SurfPlanes[index].normal, plane->normal ); - plane->dist = m_SurfPlanes[index].dist; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispNode::SetRayBoundingBox( int index, Vector const &bMin, Vector const &bMax ) -{ - Assert( index >= 0 ); - Assert( index < 4 ); - VectorCopy( bMin, m_RayBBoxes[index][0] ); - VectorCopy( bMax, m_RayBBoxes[index][1] ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispNode::GetRayBoundingBox( int index, Vector& bMin, Vector& bMax ) -{ - Assert( index >= 0 ); - Assert( index < 4 ); - VectorCopy( m_RayBBoxes[index][0], bMin ); - VectorCopy( m_RayBBoxes[index][1], bMax ); -} - - -//============================================================================= -// -// CCoreInfoBuilder - the primary data necessay to derive a displacement surface -// used by WorldCraft (CMapFace, CMapDisp), VRAD (dface_t, ddispinto_t), -// and the engine (msurface_t, CDispInfo) -// - -struct CoreDispVert_t -{ - Vector m_FieldVector; // displacement vector field - float m_FieldDistance; // the distances along the displacement vector normal - - Vector m_SubdivNormal; - Vector m_SubdivPos; // used the create curvature of displacements - - // generated displacement surface data - Vector m_Vert; // displacement surface vertices - Vector m_FlatVert; - Vector m_Normal; // displacement surface normals - Vector m_TangentS; // use in calculating the tangent space axes - Vector m_TangentT; // use in calculating the tangent space axes - Vector2D m_TexCoord; // displacement surface texture coordinates - Vector2D m_LuxelCoords[NUM_BUMP_VECTS+1]; // displacement surface lightmap coordinates - - // additional per-vertex data - float m_Alpha; // displacement alpha values (per displacement vertex) -}; - -// New, need to use this at the node level -#define COREDISPTRI_TAG_WALKABLE (1<<0) -#define COREDISPTRI_TAG_FORCE_WALKABLE_BIT (1<<1) -#define COREDISPTRI_TAG_FORCE_WALKABLE_VAL (1<<2) -#define COREDISPTRI_TAG_BUILDABLE (1<<3) -#define COREDISPTRI_TAG_FORCE_BUILDABLE_BIT (1<<4) -#define COREDISPTRI_TAG_FORCE_BUILDABLE_VAL (1<<5) - -struct CoreDispTri_t -{ - unsigned short m_iIndex[3]; // the three indices that make up a triangle - unsigned short m_uiTags; // walkable, buildable, etc. -}; - -class CCoreDispInfo : public CDispUtilsHelper -{ -public: - - // - // tree and displacement surface directions - // - enum { WEST = 0, - NORTH = 1, - EAST = 2, - SOUTH = 3, - SOUTHWEST = 4, - SOUTHEAST = 5, - NORTHWEST = 6, - NORTHEAST = 7 }; - -#if 0 - // - // building parameters - // - enum { BUILD_NORMALS = 0x1, - BUILD_TEXCOORDS = 0x2, - BUILD_LIGHTCOORDS = 0x4, - BUILD_LODTREE = 0x8, - BUILD_COLLISION = 0x10, - BUILD_TANGENTSPACE = 0x20 }; -#endif - - // - // surface info flags - // - enum { SURF_BUMPED = 0x1, - SURF_NOPHYSICS_COLL = 0x2, - SURF_NOHULL_COLL = 0x4, - SURF_NORAY_COLL = 0x8 }; - - enum { MAX_DISP_POWER = MAX_MAP_DISP_POWER }; - enum { MAX_VERT_COUNT = MAX_DISPVERTS }; - enum { MAX_NODE_COUNT = 85 }; - - -// Convert from a CDispUtilsHelper. -public: - - static CCoreDispInfo* FromDispUtils( CDispUtilsHelper *p ) { return (CCoreDispInfo*)p; } - - -// CDispUtilsHelper implementation. -public: - - virtual CDispNeighbor* GetEdgeNeighbor( int index ); - virtual CDispCornerNeighbors* GetCornerNeighbors( int index ); - virtual const CPowerInfo* GetPowerInfo() const; - virtual CDispUtilsHelper* GetDispUtilsByIndex( int index ); - - -public: - - //========================================================================= - // - // Creation/Destruction - // - CCoreDispInfo(); - ~CCoreDispInfo(); - - void InitSurf( int parentIndex, Vector points[4], Vector normals[4], - Vector2D texCoords[4], Vector2D lightCoords[4][4], int contents, int flags, - bool bGenerateSurfPointStart, Vector& startPoint, - bool bHasMappingAxes, Vector& uAxis, Vector& vAxis ); - - void InitDispInfo( int power, int minTess, float smoothingAngle, - float *alphas, Vector *dispVectorField, float *dispDistances ); - - // This just unpacks the contents of the verts into arrays and calls InitDispInfo. - void InitDispInfo( int power, int minTess, float smoothingAngle, const CDispVert *pVerts, const CDispTri *pTris ); - -// bool Create( int creationFlags ); - bool Create( void ); - bool CreateWithoutLOD( void ); - - //========================================================================= - // - // Parameter "Wrappers" - // - CCoreDispSurface* GetSurface() { return &m_Surf; } - const CCoreDispSurface* GetSurface() const { return &m_Surf; } - - inline CCoreDispNode *GetNode( int index ); - - inline void SetPower( int power ); - inline int GetPower( void ) const; - inline int GetPostSpacing( void ); - inline int GetWidth( void ); - inline int GetHeight( void ); - inline int GetSize( void ) const; - - // Use this disp as a CDispUtils. - void SetDispUtilsHelperInfo( CCoreDispInfo **ppListBase, int listSize ); - - void SetNeighborData( const CDispNeighbor edgeNeighbors[4], const CDispCornerNeighbors cornerNeighbors[4] ) { GetSurface()->SetNeighborData( edgeNeighbors, cornerNeighbors ); } - - // Get a corner point. Indexed by the CORNER_ defines. - const CVertIndex& GetCornerPointIndex( int index ) const { return GetPowerInfo()->GetCornerPointIndex( index ); } - const Vector& GetCornerPoint( int index ) const { return GetVert( VertIndexToInt( GetCornerPointIndex( index ) ) ); } - - inline void SetVert( int index, Vector const& vert ); - inline void GetVert( int index, Vector& vert ) const; - - inline const Vector& GetVert( int index ) const; - inline const Vector& GetVert( const CVertIndex &index ) const; - - inline void GetFlatVert( int index, Vector& vert ) const; - inline void SetFlatVert( int index, const Vector &vert ); - - inline void GetNormal( int index, Vector& normal ) const; - inline const Vector& GetNormal( int index ) const; - inline const Vector& GetNormal( const CVertIndex &index ) const; - inline void SetNormal( int index, Vector const& normal ); - inline void SetNormal( const CVertIndex &index, Vector const& normal ); - - inline void GetTangentS( int index, Vector& tangentS ) const; - inline const Vector &GetTangentS( int index ) const; - inline const Vector &GetTangentS( const CVertIndex &index ) const { return GetTangentS(VertIndexToInt(index)); } - inline void GetTangentT( int index, Vector& tangentT ) const; - inline void SetTangentS( int index, Vector const& vTangentS ) { m_pVerts[index].m_TangentS = vTangentS; } - inline void SetTangentT( int index, Vector const& vTangentT ) { m_pVerts[index].m_TangentT = vTangentT; } - - inline void SetTexCoord( int index, Vector2D const& texCoord ); - inline void GetTexCoord( int index, Vector2D& texCoord ) const; - - inline void SetLuxelCoord( int bumpIndex, int index, Vector2D const& luxelCoord ); - inline void GetLuxelCoord( int bumpIndex, int index, Vector2D& luxelCoord ) const; - - inline void SetAlpha( int index, float alpha ); - inline float GetAlpha( int index ); - - int GetTriCount( void ); - void GetTriIndices( int iTri, unsigned short &v1, unsigned short &v2, unsigned short &v3 ); - void SetTriIndices( int iTri, unsigned short v1, unsigned short v2, unsigned short v3 ); - void GetTriPos( int iTri, Vector &v1, Vector &v2, Vector &v3 ); - inline void SetTriTag( int iTri, unsigned short nTag ) { m_pTris[iTri].m_uiTags |= nTag; } - inline void ResetTriTag( int iTri, unsigned short nTag ) { m_pTris[iTri].m_uiTags &= ~nTag; } - inline void ToggleTriTag( int iTri, unsigned short nTag ) { m_pTris[iTri].m_uiTags ^= nTag; } - inline bool IsTriTag( int iTri, unsigned short nTag ) { return ( ( m_pTris[iTri].m_uiTags & nTag ) != 0 ); } - inline unsigned short GetTriTagValue( int iTri ) { return m_pTris[iTri].m_uiTags; } - inline void SetTriTagValue( int iTri, unsigned short nVal ) { m_pTris[iTri].m_uiTags = nVal; } - - bool IsTriWalkable( int iTri ); - bool IsTriBuildable( int iTri ); - - inline void SetElevation( float elevation ); - inline float GetElevation( void ); - - inline void ResetFieldVectors( void ); - inline void SetFieldVector( int index, Vector const &v ); - inline void GetFieldVector( int index, Vector& v ); - inline void ResetFieldDistances( void ); - inline void SetFieldDistance( int index, float dist ); - inline float GetFieldDistance( int index ); - - inline void ResetSubdivPositions( void ); - inline void SetSubdivPosition( int ndx, Vector const &v ); - inline void GetSubdivPosition( int ndx, Vector& v ); - - inline void ResetSubdivNormals( void ); - inline void SetSubdivNormal( int ndx, Vector const &v ); - inline void GetSubdivNormal( int ndx, Vector &v ); - - inline void SetRenderIndexCount( int count ); - inline int GetRenderIndexCount( void ); - inline void SetRenderIndex( int index, int triIndex ); - inline int GetRenderIndex( int index ); - - inline CoreDispVert_t *GetDispVert( int iVert ) { return &m_pVerts[iVert]; } - inline CoreDispVert_t *GetDispVertList(); - inline unsigned short *GetRenderIndexList( void ); - - inline void SetTouched( bool touched ); - inline bool IsTouched( void ); - - void CalcDispSurfCoords( bool bLightMap, int lightmapID ); - void GetPositionOnSurface( float u, float v, Vector &vPos, Vector *pNormal, float *pAlpha ); - - void DispUVToSurf( Vector2D const &dispUV, Vector &vecPoint, Vector *pNormal, float *pAlpha ); - void BaseFacePlaneToDispUV( Vector const &planePt, Vector2D &dispUV ); - bool SurfToBaseFacePlane( Vector const &surfPt, Vector &planePt ); - - const CDispCornerNeighbors* GetCornerNeighbors( int iCorner ) const { return GetSurface()->GetCornerNeighbors( iCorner ); } - const CDispNeighbor* GetEdgeNeighbor( int iEdge ) const { return GetSurface()->GetEdgeNeighbor( iEdge ); } - - void SetListIndex( int nIndex ) { m_nListIndex = nIndex; } - int GetListIndex( void ) { return m_nListIndex; } - - CBitVec& GetAllowedVerts() { return m_AllowedVerts; } - const CBitVec& GetAllowedVerts() const { return m_AllowedVerts; } - void AllowedVerts_Clear( void ) { m_AllowedVerts.SetAll(); } - int AllowedVerts_GetNumDWords() const { return m_AllowedVerts.GetNumDWords(); } - unsigned long AllowedVerts_GetDWord(int i) const { return m_AllowedVerts.GetDWord( i ); } - void AllowedVerts_SetDWord(int i, unsigned long val) { m_AllowedVerts.SetDWord( i, val ); } - - - void Position_Update( int iVert, Vector vecPos ); - - //========================================================================= - // - // friend functions - // - friend void SmoothNeighboringDispSurfNormals( CCoreDispInfo **ppCoreDispInfoList, int listSize ); - -private: - // be changed to match the paint normal next pass) - // LOD/collision node data - CCoreDispNode *m_Nodes; // LOD quad-tree nodes - - float m_Elevation; // distance along the subdivision normal (should - - // defines the size of the displacement surface - int m_Power; // "size" of the displacement map - - // base surface data - CCoreDispSurface m_Surf; // surface containing displacement data - // be changed to match the paint normal next pass) - // Vertex data.. - CoreDispVert_t *m_pVerts; - - // Triangle data.. - CoreDispTri_t *m_pTris; - - // render specific data - int m_RenderIndexCount; // number of indices used in rendering - unsigned short *m_RenderIndices; // rendering index list (list of triangles) - int m_RenderCounter; // counter to verify surfaces are renderered/collided with only once per frame - - // utility data - bool m_bTouched; // touched flag - CCoreDispInfo *m_pNext; // used for chaining - - // The list that this disp is in (used for CDispUtils::IHelper implementation). - CCoreDispInfo **m_ppListBase; - int m_ListSize; - - CBitVec m_AllowedVerts; // Built in VBSP. Defines which verts are allowed to exist based on what the neighbors are. - - int m_nListIndex; - - //========================================================================= - // - // Creation Functions - // - - void GenerateDispSurf( void ); - void GenerateDispSurfNormals( void ); - void GenerateDispSurfTangentSpaces( void ); - bool DoesEdgeExist( int indexRow, int indexCol, int direction, int postSpacing ); - void CalcNormalFromEdges( int indexRow, int indexCol, bool bIsEdge[4], Vector& normal ); - void CalcDispSurfAlphas( void ); - void GenerateLODTree( void ); - void CalcVertIndicesAtNodes( int nodeIndex ); - int GetNodeVertIndexFromParentIndex( int level, int parentVertIndex, int direction ); - void CalcNodeInfo( int nodeIndex, int terminationLevel ); - void CalcNeighborVertIndicesAtNode( int nodeIndex, int level ); - void CalcNeighborNodeIndicesAtNode( int nodeIndex, int level ); - void CalcErrorTermAtNode( int nodeIndex, int level ); - float GetMaxErrorFromChildren( int nodeIndex, int level ); - void CalcBoundingBoxAtNode( int nodeIndex ); - void CalcMinMaxBoundingBoxAtNode( int nodeIndex, Vector& bMin, Vector& bMax ); - void CalcTriSurfInfoAtNode( int nodeIndex ); - void CalcTriSurfIndices( int nodeIndex, int indices[8][3] ); - void CalcTriSurfBoundingBoxes( int nodeIndex, int indices[8][3] ); - void CalcRayBoundingBoxes( int nodeIndex, int indices[8][3] ); - void CalcTriSurfPlanes( int nodeIndex, int indices[8][3] ); - void GenerateCollisionData( void ); - void GenerateCollisionSurface( void ); - - void CreateBoundingBoxes( CoreDispBBox_t *pBBox, int count ); - - void DispUVToSurf_TriTLToBR( Vector &vecPoint, Vector *pNormal, float *pAlpha, float flU, float flV, const Vector &vecIntersectPoint ); - void DispUVToSurf_TriBLToTR( Vector &vecPoint, Vector *pNormal, float *pAlpha, float flU, float flV, const Vector &vecIntersectPoint ); - void DispUVToSurf_TriTLToBR_1( const Vector &vecIntersectPoint, int nSnapU, int nNextU, int nSnapV, int nNextV, Vector &vecPoint, Vector *pNormal, float *pAlpha, bool bBackup ); - void DispUVToSurf_TriTLToBR_2( const Vector &vecIntersectPoint, int nSnapU, int nNextU, int nSnapV, int nNextV, Vector &vecPoint, Vector *pNormal, float *pAlpha, bool bBackup ); - void DispUVToSurf_TriBLToTR_1( const Vector &vecIntersectPoint, int nSnapU, int nNextU, int nSnapV, int nNextV, Vector &vecPoint, Vector *pNormal, float *pAlpha, bool bBackup ); - void DispUVToSurf_TriBLToTR_2( const Vector &vecIntersectPoint, int nSnapU, int nNextU, int nSnapV, int nNextV, Vector &vecPoint, Vector *pNormal, float *pAlpha, bool bBackup ); - - void GetTriangleIndicesForDispBBox( int nIndex, int nTris[2][3] ); - - void BuildTriTLtoBR( int ndx ); - void BuildTriBLtoTR( int ndx ); - - void InitTris( void ); - void CreateTris( void ); -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::SetPower( int power ) -{ - m_Power = power; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline int CCoreDispInfo::GetPower( void ) const -{ - return m_Power; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline int CCoreDispInfo::GetPostSpacing( void ) -{ - return ( ( 1 << m_Power ) + 1 ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline int CCoreDispInfo::GetWidth( void ) -{ - return ( ( 1 << m_Power ) + 1 ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline int CCoreDispInfo::GetHeight( void ) -{ - return ( ( 1 << m_Power ) + 1 ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline int CCoreDispInfo::GetSize( void ) const -{ - return ( ( ( 1 << m_Power ) + 1 ) * ( ( 1 << m_Power ) + 1 ) ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::SetVert( int index, Vector const &vert ) -{ - Assert( index >= 0 ); - Assert( index < MAX_VERT_COUNT ); - VectorCopy( vert, m_pVerts[index].m_Vert ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::GetVert( int index, Vector& vert ) const -{ - Assert( index >= 0 ); - Assert( index < MAX_VERT_COUNT ); - VectorCopy( m_pVerts[index].m_Vert, vert ); -} - - -inline const Vector& CCoreDispInfo::GetVert( int index ) const -{ - Assert( index >= 0 ); - Assert( index < MAX_VERT_COUNT ); - return m_pVerts[index].m_Vert; -} - -inline const Vector& CCoreDispInfo::GetVert( const CVertIndex &index ) const -{ - return GetVert( VertIndexToInt( index ) ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::GetFlatVert( int index, Vector& vert ) const -{ - Assert( index >= 0 ); - Assert( index < MAX_VERT_COUNT ); - VectorCopy( m_pVerts[index].m_FlatVert, vert ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::SetFlatVert( int index, const Vector &vert ) -{ - Assert( index >= 0 ); - Assert( index < MAX_VERT_COUNT ); - VectorCopy( vert, m_pVerts[index].m_FlatVert ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::SetNormal( int index, Vector const &normal ) -{ - Assert( index >= 0 ); - Assert( index < MAX_VERT_COUNT ); - VectorCopy( normal, m_pVerts[index].m_Normal ); -} - - -inline void CCoreDispInfo::SetNormal( const CVertIndex &index, Vector const &normal ) -{ - SetNormal( VertIndexToInt( index ), normal ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::GetNormal( int index, Vector& normal ) const -{ - Assert( index >= 0 ); - Assert( index < MAX_VERT_COUNT ); - VectorCopy( m_pVerts[index].m_Normal, normal ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline const Vector& CCoreDispInfo::GetNormal( int index ) const -{ - Assert( index >= 0 ); - Assert( index < MAX_VERT_COUNT ); - return m_pVerts[index].m_Normal; -} - - -inline const Vector& CCoreDispInfo::GetNormal( const CVertIndex &index ) const -{ - return GetNormal( VertIndexToInt( index ) ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::GetTangentS( int index, Vector& tangentS ) const -{ - Assert( index >= 0 ); - Assert( index < GetSize() ); - VectorCopy( m_pVerts[index].m_TangentS, tangentS ); -} - -inline const Vector &CCoreDispInfo::GetTangentS( int index ) const -{ - Assert( index >= 0 ); - Assert( index < GetSize() ); - return m_pVerts[index].m_TangentS; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::GetTangentT( int index, Vector& tangentT ) const -{ - Assert( index >= 0 ); - Assert( index < GetSize() ); - VectorCopy( m_pVerts[index].m_TangentT, tangentT ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::SetTexCoord( int index, Vector2D const& texCoord ) -{ - Assert( index >= 0 ); - Assert( index < GetSize() ); - Vector2DCopy( texCoord, m_pVerts[index].m_TexCoord ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::GetTexCoord( int index, Vector2D& texCoord ) const -{ - Assert( index >= 0 ); - Assert( index < GetSize() ); - Vector2DCopy( m_pVerts[index].m_TexCoord, texCoord ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::SetLuxelCoord( int bumpIndex, int index, Vector2D const& luxelCoord ) -{ - Assert( index >= 0 ); - Assert( index < GetSize() ); - Assert( bumpIndex >= 0 ); - Assert( bumpIndex < NUM_BUMP_VECTS + 1 ); - Vector2DCopy( luxelCoord, m_pVerts[index].m_LuxelCoords[bumpIndex] ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::GetLuxelCoord( int bumpIndex, int index, Vector2D& luxelCoord ) const -{ - Assert( index >= 0 ); - Assert( index < MAX_VERT_COUNT ); - Assert( bumpIndex >= 0 ); - Assert( bumpIndex < NUM_BUMP_VECTS + 1 ); - Vector2DCopy( m_pVerts[index].m_LuxelCoords[bumpIndex], luxelCoord ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::SetAlpha( int index, float alpha ) -{ - Assert( index >= 0 ); - Assert( index < MAX_VERT_COUNT ); - m_pVerts[index].m_Alpha = alpha; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline float CCoreDispInfo::GetAlpha( int index ) -{ - Assert( index >= 0 ); - Assert( index < MAX_VERT_COUNT ); - return m_pVerts[index].m_Alpha; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::SetElevation( float elevation ) -{ - m_Elevation = elevation; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline float CCoreDispInfo::GetElevation( void ) -{ - return m_Elevation; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::ResetFieldVectors( void ) -{ -// Vector normal; -// m_Surf.GetNormal( normal ); - - int size = GetSize(); - for( int i = 0; i < size; i++ ) - { - m_pVerts[i].m_FieldVector.Init(); -// m_FieldVectors[i] = normal; - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::SetFieldVector( int index, Vector const &v ) -{ - Assert( index >= 0 ); - Assert( index < MAX_VERT_COUNT ); - VectorCopy( v, m_pVerts[index].m_FieldVector ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::GetFieldVector( int index, Vector& v ) -{ - Assert( index >= 0 ); - Assert( index < MAX_VERT_COUNT ); - VectorCopy( m_pVerts[index].m_FieldVector, v ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::ResetSubdivPositions( void ) -{ - int size = GetSize(); - for( int i = 0; i < size; i++ ) - { - m_pVerts[i].m_SubdivPos.Init(); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::SetSubdivPosition( int ndx, Vector const &v ) -{ - Assert( ndx >= 0 ); - Assert( ndx < MAX_VERT_COUNT ); - m_pVerts[ndx].m_SubdivPos = v; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::GetSubdivPosition( int ndx, Vector& v ) -{ - Assert( ndx >= 0 ); - Assert( ndx < MAX_VERT_COUNT ); - v = m_pVerts[ndx].m_SubdivPos; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::ResetSubdivNormals( void ) -{ - Vector normal; - m_Surf.GetNormal( normal ); - - int size = GetSize(); - for( int i = 0; i < size; i++ ) - { - m_pVerts[i].m_SubdivNormal = normal; - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::SetSubdivNormal( int ndx, Vector const &v ) -{ - Assert( ndx >= 0 ); - Assert( ndx < MAX_VERT_COUNT ); - m_pVerts[ndx].m_SubdivNormal = v; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::GetSubdivNormal( int ndx, Vector &v ) -{ - Assert( ndx >= 0 ); - Assert( ndx < MAX_VERT_COUNT ); - v = m_pVerts[ndx].m_SubdivNormal; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::ResetFieldDistances( void ) -{ - int size = GetSize(); - for( int i = 0; i < size; i++ ) - { - m_pVerts[i].m_FieldDistance = 0.0f; - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::SetFieldDistance( int index, float dist ) -{ - Assert( index >= 0 ); - Assert( index < GetSize() ); - m_pVerts[index].m_FieldDistance = dist; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline float CCoreDispInfo::GetFieldDistance( int index ) -{ - Assert( index >= 0 ); - Assert( index < GetSize() ); - return m_pVerts[index].m_FieldDistance; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::SetRenderIndexCount( int count ) -{ - m_RenderIndexCount = count; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline int CCoreDispInfo::GetRenderIndexCount( void ) -{ - return m_RenderIndexCount; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::SetRenderIndex( int index, int triIndex ) -{ - Assert( index >= 0 ); - Assert( index < ( MAX_VERT_COUNT*2*3) ); - m_RenderIndices[index] = triIndex; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline int CCoreDispInfo::GetRenderIndex( int index ) -{ - Assert( index >= 0 ); - Assert( index < ( MAX_VERT_COUNT*2*3) ); - return m_RenderIndices[index]; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline CoreDispVert_t *CCoreDispInfo::GetDispVertList() -{ - return m_pVerts; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline unsigned short *CCoreDispInfo::GetRenderIndexList( void ) -{ - return &m_RenderIndices[0]; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CCoreDispInfo::SetTouched( bool touched ) -{ - m_bTouched = touched; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline bool CCoreDispInfo::IsTouched( void ) -{ - return m_bTouched; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline CCoreDispNode *CCoreDispInfo::GetNode( int index ) -{ - Assert( index >= 0 ); - Assert( index < MAX_NODE_COUNT ); - return &m_Nodes[index]; -} - -bool CalcBarycentricCooefs( Vector const &v0, Vector const &v1, Vector const &v2, - Vector const &pt, float &c0, float &c1, float &c2 ); - -#endif // BUILDDISP_H diff --git a/public/captioncompiler.h b/public/captioncompiler.h deleted file mode 100644 index 73c371c75..000000000 --- a/public/captioncompiler.h +++ /dev/null @@ -1,77 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef CAPTIONCOMPILER_H -#define CAPTIONCOMPILER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "datamap.h" -#include "checksum_crc.h" - -#define MAX_BLOCK_BITS 13 - -#define MAX_BLOCK_SIZE (1< &contexts, CUtlVector< XUSER_PROPERTY > &properties ) = 0; - virtual uint GetPresenceID( const char *pIDName ) = 0; - virtual const char *GetPropertyIdString( const uint id ) = 0; - virtual void GetPropertyDisplayString( uint id, uint value, char *pOutput, int nBytes ) = 0; -#ifdef _WIN32 - virtual void StartStatsReporting( HANDLE handle, bool bArbitrated ) = 0; -#endif - - virtual void InvalidateMdlCache() = 0; - - virtual void IN_SetSampleTime( float frametime ) = 0; - -}; - -#define CLIENT_DLL_INTERFACE_VERSION "VClient015" - -//----------------------------------------------------------------------------- -// Purpose: Interface exposed from the client .dll back to the engine for specifying shared .dll IAppSystems (e.g., ISoundEmitterSystem) -//----------------------------------------------------------------------------- -abstract_class IClientDLLSharedAppSystems -{ -public: - virtual int Count() = 0; - virtual char const *GetDllName( int idx ) = 0; - virtual char const *GetInterfaceName( int idx ) = 0; -}; - -#define CLIENT_DLL_SHARED_APPSYSTEMS "VClientDllSharedAppSystems001" - -#endif // CDLL_INT_H diff --git a/public/chunkfile.cpp b/public/chunkfile.cpp deleted file mode 100644 index 326bf0786..000000000 --- a/public/chunkfile.cpp +++ /dev/null @@ -1,985 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements an interface for reading and writing heirarchical -// text files of key value pairs. The format of the file is as follows: -// -// chunkname0 -// { -// "key0" "value0" -// "key1" "value1" -// ... -// "keyN" "valueN" -// chunkname1 -// { -// "key0" "value0" -// "key1" "value1" -// ... -// "keyN" "valueN" -// } -// } -// ... -// chunknameN -// { -// "key0" "value0" -// "key1" "value1" -// ... -// "keyN" "valueN" -// } -// -// The chunk names are not necessarily unique, nor are the key names, unless the -// parsing application requires them to be. -// -// $NoKeywords: $ -//=============================================================================// - -#include -#ifdef _WIN32 -#include -#endif -#include -#include -#include -#include -#include -#include "chunkfile.h" -#include "mathlib/vector.h" -#include "mathlib/vector4d.h" -#include "tier1/strtools.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -//----------------------------------------------------------------------------- -// Purpose: Constructor. -//----------------------------------------------------------------------------- -CChunkHandlerMap::CChunkHandlerMap(void) -{ - m_pHandlers = NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Destructor. Frees handler list. -//----------------------------------------------------------------------------- -CChunkHandlerMap::~CChunkHandlerMap(void) -{ - ChunkHandlerInfoNode_t *pNode = m_pHandlers; - while (pNode != NULL) - { - ChunkHandlerInfoNode_t *pPrev = pNode; - pNode = pNode->pNext; - - delete pPrev; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Adds a chunk handler to the handler list. -// Input : pszChunkName - Name of chunk to be handled. -// pfnHandler - Address of handler callback function. -// pData - Data to pass to the handler callback. -//----------------------------------------------------------------------------- -void CChunkHandlerMap::AddHandler(const char *pszChunkName, ChunkHandler_t pfnHandler, void *pData) -{ - ChunkHandlerInfoNode_t *pNew = new ChunkHandlerInfoNode_t; - - Q_strncpy(pNew->Handler.szChunkName, pszChunkName, sizeof( pNew->Handler.szChunkName )); - pNew->Handler.pfnHandler = pfnHandler; - pNew->Handler.pData = pData; - pNew->pNext = NULL; - - if (m_pHandlers == NULL) - { - m_pHandlers = pNew; - } - else - { - ChunkHandlerInfoNode_t *pNode = m_pHandlers; - while (pNode->pNext != NULL) - { - pNode = pNode->pNext; - } - pNode->pNext = pNew; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Sets the callback for error handling within this chunk's scope. -// Input : pfnHandler - -// pData - -//----------------------------------------------------------------------------- -void CChunkHandlerMap::SetErrorHandler(ChunkErrorHandler_t pfnHandler, void *pData) -{ - m_pfnErrorHandler = pfnHandler; - m_pErrorData = pData; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : ppData - -// Output : ChunkErrorHandler_t -//----------------------------------------------------------------------------- -ChunkErrorHandler_t CChunkHandlerMap::GetErrorHandler(void **ppData) -{ - *ppData = m_pErrorData; - return(m_pfnErrorHandler); -} - - -//----------------------------------------------------------------------------- -// Purpose: Gets the handler for a given chunk name, if one has been set. -// Input : pszChunkName - Name of chunk. -// ppfnHandler - Receives the address of the callback function. -// ppData - Receives the context data for the given chunk. -// Output : Returns true if a handler was found, false if not. -//----------------------------------------------------------------------------- -ChunkHandler_t CChunkHandlerMap::GetHandler(const char *pszChunkName, void **ppData) -{ - ChunkHandlerInfoNode_t *pNode = m_pHandlers; - while (pNode != NULL) - { - if (!stricmp(pNode->Handler.szChunkName, pszChunkName)) - { - *ppData = pNode->Handler.pData; - return(pNode->Handler.pfnHandler); - } - - pNode = pNode->pNext; - } - - return(false); -} - - -//----------------------------------------------------------------------------- -// Purpose: Constructor. Initializes data members. -//----------------------------------------------------------------------------- -CChunkFile::CChunkFile(void) -{ - m_hFile = NULL; - m_nCurrentDepth = 0; - m_szIndent[0] = '\0'; - m_nHandlerStackDepth = 0; - m_DefaultChunkHandler = 0; -} - - -//----------------------------------------------------------------------------- -// Purpose: Destructor. Closes the file if it is currently open. -//----------------------------------------------------------------------------- -CChunkFile::~CChunkFile(void) -{ - if (m_hFile != NULL) - { - fclose(m_hFile); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pszChunkName - -// Output : ChunkFileResult_t -//----------------------------------------------------------------------------- -ChunkFileResult_t CChunkFile::BeginChunk(const char *pszChunkName) -{ - // - // Write the chunk name and open curly. - // - char szBuf[MAX_KEYVALUE_LEN]; - Q_snprintf(szBuf, sizeof( szBuf ), "%s\r\n%s{", pszChunkName, m_szIndent); - ChunkFileResult_t eResult = WriteLine(szBuf); - - // - // Update the indentation depth. - // - if (eResult == ChunkFile_Ok) - { - m_nCurrentDepth++; - BuildIndentString(m_szIndent, m_nCurrentDepth); - } - - return(eResult); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CChunkFile::BuildIndentString(char *pszDest, int nDepth) -{ - if (nDepth >= 0) - { - for (int i = 0; i < nDepth; i++) - { - pszDest[i] = '\t'; - } - - pszDest[nDepth] = '\0'; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : ChunkFileResult_t -//----------------------------------------------------------------------------- -ChunkFileResult_t CChunkFile::Close(void) -{ - if (m_hFile != NULL) - { - fclose(m_hFile); - m_hFile = NULL; - } - - return(ChunkFile_Ok); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : ChunkFileResult_t -//----------------------------------------------------------------------------- -ChunkFileResult_t CChunkFile::EndChunk(void) -{ - if (m_nCurrentDepth > 0) - { - m_nCurrentDepth--; - BuildIndentString(m_szIndent, m_nCurrentDepth); - } - - WriteLine("}"); - - return(ChunkFile_Ok); -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns a string explaining the last error that occurred. -//----------------------------------------------------------------------------- -const char *CChunkFile::GetErrorText(ChunkFileResult_t eResult) -{ - static char szError[MAX_KEYVALUE_LEN]; - - switch (eResult) - { - case ChunkFile_UnexpectedEOF: - { - Q_strncpy(szError, "unexpected end of file", sizeof( szError ) ); - break; - } - - case ChunkFile_UnexpectedSymbol: - { - Q_snprintf(szError, sizeof( szError ), "unexpected symbol '%s'", m_szErrorToken); - break; - } - - case ChunkFile_OpenFail: - { - Q_snprintf(szError, sizeof( szError ), "%s", strerror(errno)) ; - break; - } - - case ChunkFile_StringTooLong: - { - Q_strncpy(szError, "unterminated string or string too long", sizeof( szError ) ); - break; - } - - default: - { - Q_snprintf(szError, sizeof( szError ), "error %d", eResult); - } - } - - return(m_TokenReader.Error(szError)); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : eError - -//----------------------------------------------------------------------------- -void CChunkFile::HandleError(const char *szChunkName, ChunkFileResult_t eError) -{ - // UNDONE: dispatch errors to the error handler. - // - keep track of current chunkname for reporting errors - // - use the last non-NULL handler that was pushed onto the stack? - // - need a return code to determine whether to abort parsing? -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Output : ChunkFileResult_t -//----------------------------------------------------------------------------- -ChunkFileResult_t CChunkFile::HandleChunk(const char *szChunkName) -{ - // See if the default handler wants it? - if( m_DefaultChunkHandler ) - { - ChunkFileResult_t testResult = m_DefaultChunkHandler( this, m_pDefaultChunkHandlerData, szChunkName ); - if( testResult == ChunkFile_Ok ) - { - return ChunkFile_Ok; - } - } - - // - // If there is an active handler map... - // - if (m_nHandlerStackDepth > 0) - { - CChunkHandlerMap *pHandler = m_HandlerStack[m_nHandlerStackDepth - 1]; - - // - // If a chunk handler was found in the handler map... - // - void *pData; - ChunkHandler_t pfnHandler = pHandler->GetHandler(szChunkName, &pData); - if (pfnHandler != NULL) - { - // Dispatch this chunk to the handler. - ChunkFileResult_t eResult = pfnHandler(this, pData); - if (eResult != ChunkFile_Ok) - { - return(eResult); - } - } - else - { - // - // No handler for this chunk. Skip to the matching close curly brace. - // - int nDepth = 1; - ChunkFileResult_t eResult; - - do - { - ChunkType_t eChunkType; - char szKey[MAX_KEYVALUE_LEN]; - char szValue[MAX_KEYVALUE_LEN]; - - while ((eResult = ReadNext(szKey, szValue, sizeof(szValue), eChunkType)) == ChunkFile_Ok) - { - if (eChunkType == ChunkType_Chunk) - { - nDepth++; - } - } - - if (eResult == ChunkFile_EndOfChunk) - { - eResult = ChunkFile_Ok; - nDepth--; - } - else if (eResult == ChunkFile_EOF) - { - return(ChunkFile_UnexpectedEOF); - } - - } while ((nDepth) && (eResult == ChunkFile_Ok)); - } - } - - return(ChunkFile_Ok); -} - - -//----------------------------------------------------------------------------- -// Purpose: Opens the chunk file for reading or writing. -// Input : pszFileName - Path of file to open. -// eMode - ChunkFile_Read or ChunkFile_Write. -// Output : Returns ChunkFile_Ok on success, ChunkFile_Fail on failure. -// UNDONE: boolean return value? -//----------------------------------------------------------------------------- -ChunkFileResult_t CChunkFile::Open(const char *pszFileName, ChunkFileOpenMode_t eMode) -{ - if (eMode == ChunkFile_Read) - { - // UNDONE: TokenReader encapsulates file - unify reading and writing to use the same file I/O. - // UNDONE: Support in-memory parsing. - if (m_TokenReader.Open(pszFileName)) - { - m_nCurrentDepth = 0; - } - else - { - return(ChunkFile_OpenFail); - } - } - else if (eMode == ChunkFile_Write) - { - m_hFile = fopen(pszFileName, "wb"); - - if (m_hFile == NULL) - { - return(ChunkFile_OpenFail); - } - - m_nCurrentDepth = 0; - } - - return(ChunkFile_Ok); -} - - -//----------------------------------------------------------------------------- -// Purpose: Removes the topmost set of chunk handlers. -//----------------------------------------------------------------------------- -void CChunkFile::PopHandlers(void) -{ - if (m_nHandlerStackDepth > 0) - { - m_nHandlerStackDepth--; - } -} - - -void CChunkFile::SetDefaultChunkHandler( DefaultChunkHandler_t pHandler, void *pData ) -{ - m_DefaultChunkHandler = pHandler; - m_pDefaultChunkHandlerData = pData;} - - -//----------------------------------------------------------------------------- -// Purpose: Adds a set of chunk handlers to the top of the handler stack. -// Input : pHandlerMap - Object containing the list of chunk handlers. -//----------------------------------------------------------------------------- -void CChunkFile::PushHandlers(CChunkHandlerMap *pHandlerMap) -{ - if (m_nHandlerStackDepth < MAX_INDENT_DEPTH) - { - m_HandlerStack[m_nHandlerStackDepth] = pHandlerMap; - m_nHandlerStackDepth++; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Reads the next term from the chunk file. The type of term read is -// returned in the eChunkType parameter. -// Input : szName - Name of key or chunk. -// szValue - If eChunkType is ChunkType_Key, contains the value of the key. -// nValueSize - Size of the buffer pointed to by szValue. -// eChunkType - ChunkType_Key or ChunkType_Chunk. -// Output : Returns ChunkFile_Ok on success, an error code if a parsing error occurs. -//----------------------------------------------------------------------------- -ChunkFileResult_t CChunkFile::ReadNext(char *szName, char *szValue, int nValueSize, ChunkType_t &eChunkType) -{ - // HACK: pass in buffer sizes? - trtoken_t eTokenType = m_TokenReader.NextToken(szName, MAX_KEYVALUE_LEN); - - if (eTokenType != TOKENEOF) - { - switch (eTokenType) - { - case IDENT: - case STRING: - { - char szNext[MAX_KEYVALUE_LEN]; - trtoken_t eNextTokenType; - - // - // Read the next token to determine what we have. - // - eNextTokenType = m_TokenReader.NextToken(szNext, sizeof(szNext)); - - switch (eNextTokenType) - { - case OPERATOR: - { - if (!stricmp(szNext, "{")) - { - // Beginning of new chunk. - m_nCurrentDepth++; - eChunkType = ChunkType_Chunk; - szValue[0] = '\0'; - return(ChunkFile_Ok); - } - else - { - // Unexpected symbol. - Q_strncpy(m_szErrorToken, szNext, sizeof( m_szErrorToken ) ); - return(ChunkFile_UnexpectedSymbol); - } - } - - case STRING: - case IDENT: - { - // Key value pair. - Q_strncpy(szValue, szNext, nValueSize ); - eChunkType = ChunkType_Key; - return(ChunkFile_Ok); - } - - case TOKENEOF: - { - // Unexpected end of file. - return(ChunkFile_UnexpectedEOF); - } - - case TOKENSTRINGTOOLONG: - { - // String too long or unterminated string. - return ChunkFile_StringTooLong; - } - } - } - - case OPERATOR: - { - if (!stricmp(szName, "}")) - { - // End of current chunk. - m_nCurrentDepth--; - return(ChunkFile_EndOfChunk); - } - else - { - // Unexpected symbol. - Q_strncpy(m_szErrorToken, szName, sizeof( m_szErrorToken ) ); - return(ChunkFile_UnexpectedSymbol); - } - } - - case TOKENSTRINGTOOLONG: - { - return ChunkFile_StringTooLong; - } - } - } - - if (m_nCurrentDepth != 0) - { - // End of file while within the scope of a chunk. - return(ChunkFile_UnexpectedEOF); - } - - return(ChunkFile_EOF); -} - - -//----------------------------------------------------------------------------- -// Purpose: Reads the current chunk and dispatches keys and sub-chunks to the -// appropriate handler callbacks. -// Input : pfnKeyHandler - Callback for any key values in this chunk. -// pData - Data to pass to the key value callback function. -// Output : Normally returns ChunkFile_Ok or ChunkFile_EOF. Otherwise, returns -// a ChunkFile_xxx error code. -//----------------------------------------------------------------------------- -ChunkFileResult_t CChunkFile::ReadChunk(KeyHandler_t pfnKeyHandler, void *pData) -{ - // - // Read the keys and sub-chunks. - // - ChunkFileResult_t eResult; - do - { - char szName[MAX_KEYVALUE_LEN]; - char szValue[MAX_KEYVALUE_LEN]; - ChunkType_t eChunkType; - - eResult = ReadNext(szName, szValue, sizeof(szValue), eChunkType); - - if (eResult == ChunkFile_Ok) - { - if (eChunkType == ChunkType_Chunk) - { - // - // Dispatch sub-chunks to the appropriate handler. - // - eResult = HandleChunk(szName); - } - else if ((eChunkType == ChunkType_Key) && (pfnKeyHandler != NULL)) - { - // - // Dispatch keys to the key value handler. - // - eResult = pfnKeyHandler(szName, szValue, pData); - } - } - } while (eResult == ChunkFile_Ok); - - // - // Cover up ChunkFile_EndOfChunk results because the caller doesn't want to see them. - // - if (eResult == ChunkFile_EndOfChunk) - { - eResult = ChunkFile_Ok; - } - - // - // Dispatch errors to the handler. - // - if ((eResult != ChunkFile_Ok) && (eResult != ChunkFile_EOF)) - { - //HandleError("chunkname", eResult); - } - - return(eResult); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pszValue - -// pbBool - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChunkFile::ReadKeyValueBool(const char *pszValue, bool &bBool) -{ - int nValue = atoi(pszValue); - - if (nValue > 0) - { - bBool = true; - } - else - { - bBool = false; - } - - return(true); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pszValue - -// pfFloat - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChunkFile::ReadKeyValueFloat(const char *pszValue, float &flFloat) -{ - flFloat = (float)atof(pszValue); - return(true); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pszValue - -// pnInt - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChunkFile::ReadKeyValueInt(const char *pszValue, int &nInt) -{ - nInt = atoi(pszValue); - return(true); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pszKey - -// r - -// g - -// b - -// Output : -//----------------------------------------------------------------------------- -bool CChunkFile::ReadKeyValueColor(const char *pszValue, unsigned char &chRed, unsigned char &chGreen, unsigned char &chBlue) -{ - if (pszValue != NULL) - { - int r; - int g; - int b; - - if (sscanf(pszValue, "%d %d %d", &r, &g, &b) == 3) - { - chRed = r; - chGreen = g; - chBlue = b; - - return(true); - } - } - - return(false); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pszValue - -// pfPoint - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChunkFile::ReadKeyValuePoint(const char *pszValue, Vector &Point) -{ - if (pszValue != NULL) - { - return(sscanf(pszValue, "(%f %f %f)", &Point.x, &Point.y, &Point.z) == 3); - } - - return(false); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pszValue - -// pfVector - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChunkFile::ReadKeyValueVector2(const char *pszValue, Vector2D &vec) -{ - if (pszValue != NULL) - { - return ( sscanf( pszValue, "[%f %f]", &vec.x, &vec.y) == 2 ); - } - - return(false); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pszValue - -// pfVector - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChunkFile::ReadKeyValueVector3(const char *pszValue, Vector &vec) -{ - if (pszValue != NULL) - { - return(sscanf(pszValue, "[%f %f %f]", &vec.x, &vec.y, &vec.z) == 3); - } - - return(false); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pszValue - -// pfVector - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CChunkFile::ReadKeyValueVector4(const char *pszValue, Vector4D &vec) -{ - if( pszValue != NULL ) - { - return(sscanf(pszValue, "[%f %f %f %f]", &vec[0], &vec[1], &vec[2], &vec[3]) == 4); - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pszLine - -// Output : -//----------------------------------------------------------------------------- -ChunkFileResult_t CChunkFile::WriteKeyValue(const char *pszKey, const char *pszValue) -{ - if ((pszKey != NULL) && (pszValue != NULL)) - { - char szTemp[MAX_KEYVALUE_LEN]; - Q_snprintf(szTemp, sizeof( szTemp ), "\"%s\" \"%s\"", pszKey, pszValue); - return(WriteLine(szTemp)); - } - - return(ChunkFile_Ok); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pszKey - -// bValue - -// Output : -//----------------------------------------------------------------------------- -ChunkFileResult_t CChunkFile::WriteKeyValueBool(const char *pszKey, bool bValue) -{ - if (pszKey != NULL) - { - char szBuf[MAX_KEYVALUE_LEN]; - Q_snprintf(szBuf, sizeof( szBuf ), "\"%s\" \"%d\"", pszKey, (int)bValue); - return(WriteLine(szBuf)); - } - - return(ChunkFile_Ok); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pszKey - -// nValue - -// Output : -//----------------------------------------------------------------------------- -ChunkFileResult_t CChunkFile::WriteKeyValueInt(const char *pszKey, int nValue) -{ - if (pszKey != NULL) - { - char szBuf[MAX_KEYVALUE_LEN]; - Q_snprintf(szBuf, sizeof( szBuf ), "\"%s\" \"%d\"", pszKey, nValue); - return(WriteLine(szBuf)); - } - - return(ChunkFile_Ok); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pszKey - -// fValue - -// Output : -//----------------------------------------------------------------------------- -ChunkFileResult_t CChunkFile::WriteKeyValueFloat(const char *pszKey, float fValue) -{ - if (pszKey != NULL) - { - char szBuf[MAX_KEYVALUE_LEN]; - Q_snprintf(szBuf, sizeof( szBuf ), "\"%s\" \"%g\"", pszKey, (double)fValue); - return(WriteLine(szBuf)); - } - - return(ChunkFile_Ok); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pszKey - -// r - -// g - -// b - -// Output : -//----------------------------------------------------------------------------- -ChunkFileResult_t CChunkFile::WriteKeyValueColor(const char *pszKey, unsigned char r, unsigned char g, unsigned char b) -{ - if (pszKey != NULL) - { - char szBuf[MAX_KEYVALUE_LEN]; - Q_snprintf(szBuf, sizeof( szBuf ), "\"%s\" \"%d %d %d\"", pszKey, (int)r, (int)g, (int)b); - return(WriteLine(szBuf)); - } - - return(ChunkFile_Ok); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pszKey - -// fVector - -// Output : -//----------------------------------------------------------------------------- -ChunkFileResult_t CChunkFile::WriteKeyValuePoint(const char *pszKey, const Vector &Point) -{ - if (pszKey != NULL) - { - char szBuf[MAX_KEYVALUE_LEN]; - Q_snprintf(szBuf, sizeof( szBuf ), "\"%s\" \"(%g %g %g)\"", pszKey, (double)Point[0], (double)Point[1], (double)Point[2]); - return(WriteLine(szBuf)); - } - - return(ChunkFile_Ok); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -ChunkFileResult_t CChunkFile::WriteKeyValueVector2(const char *pszKey, const Vector2D &vec) -{ - if (pszKey != NULL) - { - char szBuf[MAX_KEYVALUE_LEN]; - Q_snprintf( szBuf, sizeof( szBuf ), "\"%s\" \"[%g %g]\"", pszKey, (double)vec.x, (double)vec.y ); - return(WriteLine(szBuf)); - } - - return(ChunkFile_Ok); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -ChunkFileResult_t CChunkFile::WriteKeyValueVector3(const char *pszKey, const Vector &vec) -{ - if (pszKey != NULL) - { - char szBuf[MAX_KEYVALUE_LEN]; - Q_snprintf(szBuf, sizeof( szBuf ), "\"%s\" \"[%g %g %g]\"", pszKey, (double)vec.x, (double)vec.y, (double)vec.z); - return(WriteLine(szBuf)); - } - - return(ChunkFile_Ok); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : pszKey - -// fVector - -// Output : -//----------------------------------------------------------------------------- -ChunkFileResult_t CChunkFile::WriteKeyValueVector4(const char *pszKey, const Vector4D &vec) -{ - if (pszKey != NULL) - { - char szBuf[MAX_KEYVALUE_LEN]; - Q_snprintf(szBuf, sizeof( szBuf ), "\"%s\" \"[%g %g %g %g]\"", pszKey, (double)vec.x, (double)vec.y, (double)vec.z, (double)vec.w); - return( WriteLine( szBuf ) ); - } - - return( ChunkFile_Ok ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pszLine - -// Output : -//----------------------------------------------------------------------------- -ChunkFileResult_t CChunkFile::WriteLine(const char *pszLine) -{ - if (pszLine != NULL) - { - // - // Write the indentation string. - // - if (m_nCurrentDepth > 0) - { - int nWritten = fwrite(m_szIndent, 1, m_nCurrentDepth, m_hFile); - if (nWritten != m_nCurrentDepth) - { - return(ChunkFile_Fail); - } - } - - // - // Write the string. - // - int nLen = strlen(pszLine); - int nWritten = fwrite(pszLine, 1, nLen, m_hFile); - if (nWritten != nLen) - { - return(ChunkFile_Fail); - } - - // - // Write the linefeed. - // - if (fwrite("\r\n", 1, 2, m_hFile) != 2) - { - return(ChunkFile_Fail); - } - } - - return(ChunkFile_Ok); -} - diff --git a/public/chunkfile.h b/public/chunkfile.h deleted file mode 100644 index f18c985f7..000000000 --- a/public/chunkfile.h +++ /dev/null @@ -1,197 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef CHUNKFILE_H -#define CHUNKFILE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include "tokenreader.h" - - -#define MAX_INDENT_DEPTH 80 -#define MAX_KEYVALUE_LEN 1024 - - -class CChunkFile; -class Vector2D; -class Vector; -class Vector4D; - - -// -// Modes for Open. -// -enum ChunkFileOpenMode_t -{ - ChunkFile_Read = 0, - ChunkFile_Write, -}; - - -// -// Return codes. -// -enum ChunkFileResult_t -{ - ChunkFile_Ok = 0, - ChunkFile_Fail, - ChunkFile_OpenFail, - ChunkFile_EndOfChunk, - ChunkFile_EOF, - ChunkFile_UnexpectedEOF, - ChunkFile_UnexpectedSymbol, - ChunkFile_OutOfMemory, - ChunkFile_StringTooLong, - ChunkFile_NotHandled -}; - - -enum ChunkType_t -{ - ChunkType_Key = 0, - ChunkType_Chunk, -}; - - -typedef ChunkFileResult_t (*DefaultChunkHandler_t)(CChunkFile *pFile, void *pData, char const *pChunkName); - -typedef ChunkFileResult_t (*ChunkHandler_t)(CChunkFile *pFile, void *pData); -typedef ChunkFileResult_t (*KeyHandler_t)(const char *szKey, const char *szValue, void *pData); -typedef bool (*ChunkErrorHandler_t)(CChunkFile *pFile, const char *szChunkName, void *pData); - - -struct ChunkHandlerInfo_t -{ - char szChunkName[80]; - ChunkHandler_t pfnHandler; - void *pData; -}; - - -struct ChunkHandlerInfoNode_t -{ - ChunkHandlerInfo_t Handler; - struct ChunkHandlerInfoNode_t *pNext; -}; - - -// -// Consider handling chunks with handler objects instead of callbacks. -// -//class CChunkHandler -//{ -// virtual ChunkFileResult_t HandleChunk(const char *szName); -// virtual ChunkFileResult_t HandleKey(const char *szKey, const char *szValue); -// virtual bool HandleError(const char *szChunkName, ChunkFileResult_t eError); -//}; - - -class CChunkHandlerMap -{ - public: - - CChunkHandlerMap(void); - ~CChunkHandlerMap(void); - - void AddHandler(const char *pszChunkName, ChunkHandler_t pfnHandler, void *pData); - ChunkHandler_t GetHandler(const char *pszChunkName, void **pData); - - void SetErrorHandler(ChunkErrorHandler_t pfnHandler, void *pData); - ChunkErrorHandler_t GetErrorHandler(void **pData); - - protected: - - ChunkHandlerInfoNode_t *m_pHandlers; - ChunkErrorHandler_t m_pfnErrorHandler; - void *m_pErrorData; -}; - - -class CChunkFile -{ - public: - - CChunkFile(void); - ~CChunkFile(void); - - ChunkFileResult_t Open(const char *pszFileName, ChunkFileOpenMode_t eMode); - ChunkFileResult_t Close(void); - const char *GetErrorText(ChunkFileResult_t eResult); - - // - // Functions for writing chunk files. - // - ChunkFileResult_t BeginChunk(const char *pszChunkName); - ChunkFileResult_t EndChunk(void); - - ChunkFileResult_t WriteKeyValue(const char *pszKey, const char *pszValue); - ChunkFileResult_t WriteKeyValueBool(const char *pszKey, bool bValue); - ChunkFileResult_t WriteKeyValueColor(const char *pszKey, unsigned char r, unsigned char g, unsigned char b); - ChunkFileResult_t WriteKeyValueFloat(const char *pszKey, float fValue); - ChunkFileResult_t WriteKeyValueInt(const char *pszKey, int nValue); - ChunkFileResult_t WriteKeyValuePoint(const char *pszKey, const Vector &Point); - ChunkFileResult_t WriteKeyValueVector2(const char *pszKey, const Vector2D &vec); - ChunkFileResult_t WriteKeyValueVector3(const char *pszKey, const Vector &vec); - ChunkFileResult_t WriteKeyValueVector4( const char *pszKey, const Vector4D &vec); - - ChunkFileResult_t WriteLine(const char *pszLine); - - // - // Functions for reading chunk files. - // - ChunkFileResult_t ReadChunk(KeyHandler_t pfnKeyHandler = NULL, void *pData = NULL); - ChunkFileResult_t ReadNext(char *szKey, char *szValue, int nValueSize, ChunkType_t &eChunkType); - ChunkFileResult_t HandleChunk(const char *szChunkName); - void HandleError(const char *szChunkName, ChunkFileResult_t eError); - - // These functions should more really be named Parsexxx and possibly moved elsewhere. - static bool ReadKeyValueBool(const char *pszValue, bool &bBool); - static bool ReadKeyValueColor(const char *pszValue, unsigned char &chRed, unsigned char &chGreen, unsigned char &chBlue); - static bool ReadKeyValueInt(const char *pszValue, int &nInt); - static bool ReadKeyValueFloat(const char *pszValue, float &flFloat); - static bool ReadKeyValuePoint(const char *pszValue, Vector &Point); - static bool ReadKeyValueVector2(const char *pszValue, Vector2D &vec); - static bool ReadKeyValueVector3(const char *pszValue, Vector &vec); - static bool ReadKeyValueVector4( const char *pszValue, Vector4D &vec); - - // The default chunk handler gets called before any other chunk handlers. - // - // If the handler returns ChunkFile_Ok, then it goes into the chunk. - // If the handler returns ChunkFile_NotHandled, then the chunk is - // passed to the regular handlers. - // - // If you pass NULL in here, then it disables the default chunk handler. - void SetDefaultChunkHandler( DefaultChunkHandler_t pHandler, void *pData ); - - void PushHandlers(CChunkHandlerMap *pHandlerMap); - void PopHandlers(void); - - protected: - - void BuildIndentString(char *pszDest, int nDepth); - - TokenReader m_TokenReader; - - FILE *m_hFile; - char m_szErrorToken[80]; - char m_szIndent[MAX_INDENT_DEPTH]; - int m_nCurrentDepth; - - // See SetDefaultChunkHandler.. - DefaultChunkHandler_t m_DefaultChunkHandler; - void *m_pDefaultChunkHandlerData; - - CChunkHandlerMap *m_HandlerStack[MAX_INDENT_DEPTH]; - int m_nHandlerStackDepth; -}; - - -#endif // CHUNKFILE_H diff --git a/public/client_class.cpp b/public/client_class.cpp deleted file mode 100644 index 9eecf4332..000000000 --- a/public/client_class.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include "client_class.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ClientClass *g_pClientClassHead=0; - - diff --git a/public/client_class.h b/public/client_class.h deleted file mode 100644 index 5329cf678..000000000 --- a/public/client_class.h +++ /dev/null @@ -1,180 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#if !defined( CLIENT_CLASS_H ) -#define CLIENT_CLASS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "interface.h" -#include "dt_recv.h" - -//----------------------------------------------------------------------------- -// forward declarations -//----------------------------------------------------------------------------- - -class Vector; -class CMouthInfo; - - -//----------------------------------------------------------------------------- -// represents a handle used only by the client DLL -//----------------------------------------------------------------------------- - -#include "iclientrenderable.h" -#include "iclientnetworkable.h" - - -class ClientClass; -// Linked list of all known client classes -extern ClientClass *g_pClientClassHead; - -// The serial number that gets passed in is used for ehandles. -typedef IClientNetworkable* (*CreateClientClassFn)( int entnum, int serialNum ); -typedef IClientNetworkable* (*CreateEventFn)(); - -//----------------------------------------------------------------------------- -// Purpose: Client side class definition -//----------------------------------------------------------------------------- -class ClientClass -{ -public: - ClientClass( char *pNetworkName, CreateClientClassFn createFn, CreateEventFn createEventFn, RecvTable *pRecvTable ) - { - m_pNetworkName = pNetworkName; - m_pCreateFn = createFn; - m_pCreateEventFn= createEventFn; - m_pRecvTable = pRecvTable; - - // Link it in - m_pNext = g_pClientClassHead; - g_pClientClassHead = this; - } - - const char* GetName() - { - return m_pNetworkName; - } - -public: - CreateClientClassFn m_pCreateFn; - CreateEventFn m_pCreateEventFn; // Only called for event objects. - char *m_pNetworkName; - RecvTable *m_pRecvTable; - ClientClass *m_pNext; - int m_ClassID; // Managed by the engine. -}; - -#define DECLARE_CLIENTCLASS() \ - virtual int YouForgotToImplementOrDeclareClientClass();\ - virtual ClientClass* GetClientClass();\ - static RecvTable *m_pClassRecvTable; \ - DECLARE_CLIENTCLASS_NOBASE() - - -// This can be used to give all datatables access to protected and private members of the class. -#define ALLOW_DATATABLES_PRIVATE_ACCESS() \ - template friend int ClientClassInit(T *); - - -#define DECLARE_CLIENTCLASS_NOBASE ALLOW_DATATABLES_PRIVATE_ACCESS - -// This macro adds a ClientClass to the linked list in g_pClientClassHead (so -// the list can be given to the engine). -// Use this macro to expose your client class to the engine. -// networkName must match the network name of a class registered on the server. -#define IMPLEMENT_CLIENTCLASS(clientClassName, dataTable, serverClassName) \ - INTERNAL_IMPLEMENT_CLIENTCLASS_PROLOGUE(clientClassName, dataTable, serverClassName) \ - static IClientNetworkable* _##clientClassName##_CreateObject( int entnum, int serialNum ) \ - { \ - clientClassName *pRet = new clientClassName; \ - if ( !pRet ) \ - return 0; \ - pRet->Init( entnum, serialNum ); \ - return pRet; \ - } \ - ClientClass __g_##clientClassName##ClientClass(#serverClassName, \ - _##clientClassName##_CreateObject, \ - NULL,\ - &dataTable::g_RecvTable); - -// Implement a client class and provide a factory so you can allocate and delete it yourself -// (or make it a singleton). -#define IMPLEMENT_CLIENTCLASS_FACTORY(clientClassName, dataTable, serverClassName, factory) \ - INTERNAL_IMPLEMENT_CLIENTCLASS_PROLOGUE(clientClassName, dataTable, serverClassName) \ - ClientClass __g_##clientClassName##ClientClass(#serverClassName, \ - factory, \ - NULL,\ - &dataTable::g_RecvTable); - -// The IMPLEMENT_CLIENTCLASS_DT macros do IMPLEMENT_CLIENT_CLASS and also do BEGIN_RECV_TABLE. -#define IMPLEMENT_CLIENTCLASS_DT(clientClassName, dataTable, serverClassName)\ - IMPLEMENT_CLIENTCLASS(clientClassName, dataTable, serverClassName)\ - BEGIN_RECV_TABLE(clientClassName, dataTable) - -#define IMPLEMENT_CLIENTCLASS_DT_NOBASE(clientClassName, dataTable, serverClassName)\ - IMPLEMENT_CLIENTCLASS(clientClassName, dataTable, serverClassName)\ - BEGIN_RECV_TABLE_NOBASE(clientClassName, dataTable) - - -// Using IMPLEMENT_CLIENTCLASS_EVENT means the engine thinks the entity is an event so the entity -// is responsible for freeing itself. -#define IMPLEMENT_CLIENTCLASS_EVENT(clientClassName, dataTable, serverClassName)\ - INTERNAL_IMPLEMENT_CLIENTCLASS_PROLOGUE(clientClassName, dataTable, serverClassName)\ - static clientClassName __g_##clientClassName##; \ - static IClientNetworkable* _##clientClassName##_CreateObject() {return &__g_##clientClassName##;}\ - ClientClass __g_##clientClassName##ClientClass(#serverClassName, \ - NULL,\ - _##clientClassName##_CreateObject, \ - &dataTable::g_RecvTable); - -#define IMPLEMENT_CLIENTCLASS_EVENT_DT(clientClassName, dataTable, serverClassName)\ - namespace dataTable {extern RecvTable g_RecvTable;}\ - IMPLEMENT_CLIENTCLASS_EVENT(clientClassName, dataTable, serverClassName)\ - BEGIN_RECV_TABLE(clientClassName, dataTable) - - -// Register a client event singleton but specify a pointer to give to the engine rather than -// have a global instance. This is useful if you're using Initializers and your object's constructor -// uses some other global object (so you must use Initializers so you're constructed afterwards). -#define IMPLEMENT_CLIENTCLASS_EVENT_POINTER(clientClassName, dataTable, serverClassName, ptr)\ - INTERNAL_IMPLEMENT_CLIENTCLASS_PROLOGUE(clientClassName, dataTable, serverClassName)\ - static IClientNetworkable* _##clientClassName##_CreateObject() {return ptr;}\ - ClientClass __g_##clientClassName##ClientClass(#serverClassName, \ - NULL,\ - _##clientClassName##_CreateObject, \ - &dataTable::g_RecvTable); - -#define IMPLEMENT_CLIENTCLASS_EVENT_NONSINGLETON(clientClassName, dataTable, serverClassName)\ - static IClientNetworkable* _##clientClassName##_CreateObject() \ - { \ - clientClassName *p = new clientClassName; \ - if ( p ) \ - p->Init( -1, 0 ); \ - return p; \ - } \ - ClientClass __g_##clientClassName##ClientClass(#serverClassName, \ - NULL,\ - _##clientClassName##_CreateObject, \ - &dataTable::g_RecvTable); - - -// Used internally.. -#define INTERNAL_IMPLEMENT_CLIENTCLASS_PROLOGUE(clientClassName, dataTable, serverClassName) \ - namespace dataTable {extern RecvTable g_RecvTable;}\ - extern ClientClass __g_##clientClassName##ClientClass;\ - RecvTable* clientClassName::m_pClassRecvTable = &dataTable::g_RecvTable;\ - int clientClassName::YouForgotToImplementOrDeclareClientClass() {return 0;}\ - ClientClass* clientClassName::GetClientClass() {return &__g_##clientClassName##ClientClass;} - -#endif // CLIENT_CLASS_H diff --git a/public/client_render_handle.h b/public/client_render_handle.h deleted file mode 100644 index 9b7ab9219..000000000 --- a/public/client_render_handle.h +++ /dev/null @@ -1,31 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef CLIENT_RENDER_HANDLE_H -#define CLIENT_RENDER_HANDLE_H -#ifdef _WIN32 -#pragma once -#endif - - -//----------------------------------------------------------------------------- -// Foward declarations -//----------------------------------------------------------------------------- -class IClientRenderable; - - -//----------------------------------------------------------------------------- -// Handle to an renderable in the client leaf system -//----------------------------------------------------------------------------- -typedef unsigned short ClientRenderHandle_t; - -enum -{ - INVALID_CLIENT_RENDER_HANDLE = (ClientRenderHandle_t)0xffff, -}; - - -#endif // CLIENT_RENDER_HANDLE_H diff --git a/public/client_textmessage.h b/public/client_textmessage.h deleted file mode 100644 index 5559133e0..000000000 --- a/public/client_textmessage.h +++ /dev/null @@ -1,33 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef CLIENT_TEXTMESSAGE_H -#define CLIENT_TEXTMESSAGE_H -#ifdef _WIN32 -#pragma once -#endif - -struct client_textmessage_t -{ - int effect; - byte r1, g1, b1, a1; // 2 colors for effects - byte r2, g2, b2, a2; - float x; - float y; - float fadein; - float fadeout; - float holdtime; - float fxtime; - const char *pVGuiSchemeFontName; // If null, use default font for messages - const char *pName; - const char *pMessage; - bool bRoundedRectBackdropBox; - float flBoxSize; // as a function of font height - byte boxcolor[4]; - char const *pClearMessage; // message to clear -}; - -#endif // CLIENT_TEXTMESSAGE_H diff --git a/public/clientstats.h b/public/clientstats.h deleted file mode 100644 index c4290b8df..000000000 --- a/public/clientstats.h +++ /dev/null @@ -1,198 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#if !defined( CLIENTSTATS_H ) -#define CLIENTSTATS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "interface.h" -#include -#include "tier0/dbg.h" - -#define INTERFACEVERSION_CLIENTSTATS "ClientStats004" - -//----------------------------------------------------------------------------- -// An interface used to help the client stats implementation tell time -//----------------------------------------------------------------------------- - -struct IClientStatsTime -{ - virtual float GetTime() = 0; -}; - -//----------------------------------------------------------------------------- -// Allows clients to draw their own stats text, will be passed by the -// engine into DisplayStats of the IClientStats interface. -//----------------------------------------------------------------------------- - -struct IClientStatsTextDisplay -{ - // Draws the stats - virtual void DrawStatsText( const char *fmt, ... ) = 0; - - virtual void SetDrawColor( unsigned char r, unsigned char g, unsigned char b ) = 0; - - // Sets a color based on a value and its max acceptable limit - virtual void SetDrawColorFromStatValues( float limit, float value ) = 0; -}; - - -//----------------------------------------------------------------------------- -// This will exist as a singleton within the client DLL and will be hooked into -// the engine to allow clients to render their own stats. -//----------------------------------------------------------------------------- - -abstract_class IClientStats -{ -public: - // This is called at startup to tell the stats about time - virtual void Init( IClientStatsTime* pTime ) = 0; - - // These methods are called at the beginning and the end of each run - virtual void BeginRun() = 0; - virtual void EndRun() = 0; - - // These methods are called at the beginning and the end of each frame - virtual void BeginFrame() = 0; - virtual void EndFrame() = 0; - - // --------------------------------------------------------------- - // All this stuff is used to prop stats for gathering r_speeds data during timedemo. - // --------------------------------------------------------------- - virtual int GetNumTimesStats( void ) const = 0; - - // returns timed stats - virtual double TimedStatInFrame( int statID ) const = 0; - virtual double TotalTimedStat( int statID ) const = 0; -}; - - -//----------------------------------------------------------------------------- -// This is a templatized implementation which can be instantiated anywhere -// Note that you still have to install it and display it though. -//----------------------------------------------------------------------------- - -template -abstract_class CBaseClientStats : public IClientStats -{ -public: - void Init( IClientStatsTime* pTime ); - void BeginRun(); - void EndRun(); - void BeginFrame(); - void EndFrame(); - - // Timed stat gathering - void BeginTimedStat( int stat ); - void EndTimedStat( int stat ); - - // --------------------------------------------------------------- - // All this stuff is used to prop stats for gathering r_speeds data during timedemo. - // --------------------------------------------------------------- - // returns timed stats - double TimedStatInFrame( int statID ) const - { - Assert( statID >= 0 && statID < timedStatCount ); - Assert( m_StatFrameTime[statID] >= 0.0 ); - return m_StatFrameTime[statID]; - } - - double TotalTimedStat( int statID ) const - { - Assert( statID >= 0 && statID < timedStatCount ); - return m_TotalStatTime[statID]; - } - virtual const char *GetCountedStatName( int statID ) const = 0; - virtual const char *GetTimedStatName( int statID ) const = 0; - -protected: - - // Timed statistics - double m_StatFrameTime[timedStatCount]; - double m_StatStartTime[timedStatCount]; - double m_TotalStatTime[timedStatCount]; - -private: - IClientStatsTime* m_pTime; -}; - - -//----------------------------------------------------------------------------- -// Initializes client stats -//----------------------------------------------------------------------------- - -template -void CBaseClientStats::Init( IClientStatsTime* pTime ) -{ - Assert( pTime ); - m_pTime = pTime; -} - -//----------------------------------------------------------------------------- -// These methods are called at the beginning and the end of each run -//----------------------------------------------------------------------------- - -template -void CBaseClientStats::BeginRun() -{ - int i; - - for (i = 0; i < timedStatCount; ++i) - m_TotalStatTime[i] = 0.0; - -} - -template -void CBaseClientStats::EndRun() -{ -} - - -//----------------------------------------------------------------------------- -// These methods are called at the beginning and the end of each frame -//----------------------------------------------------------------------------- - -template -void CBaseClientStats::BeginFrame() -{ - int i; - for (i = 0; i < timedStatCount; ++i) - m_StatFrameTime[i] = 0.0; -} - -template -void CBaseClientStats::EndFrame() -{ - int i; - for (i = 0; i < timedStatCount; ++i) - m_TotalStatTime[i] += m_StatFrameTime[i]; -} - - -//----------------------------------------------------------------------------- -// Inlined stat gathering methods -//----------------------------------------------------------------------------- - -template -void CBaseClientStats::BeginTimedStat( int stat ) -{ - if (m_pTime) - m_StatStartTime[stat] = m_pTime->GetTime(); -} - -template -void CBaseClientStats::EndTimedStat( int stat ) -{ - if (m_pTime) - m_StatFrameTime[stat] += m_pTime->GetTime() - m_StatStartTime[stat]; -} - - -#endif // CLIENTSTATS_H diff --git a/public/cmodel.h b/public/cmodel.h deleted file mode 100644 index b031cffc8..000000000 --- a/public/cmodel.h +++ /dev/null @@ -1,129 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef CMODEL_H -#define CMODEL_H -#ifdef _WIN32 -#pragma once -#endif - -#include "trace.h" -#include "tier0/dbg.h" -#include "basehandle.h" - -struct edict_t; -struct model_t; - -/* -============================================================== - -COLLISION DETECTION - -============================================================== -*/ - -#include "bspflags.h" -//#include "mathlib/vector.h" - -// gi.BoxEdicts() can return a list of either solid or trigger entities -// FIXME: eliminate AREA_ distinction? -#define AREA_SOLID 1 -#define AREA_TRIGGERS 2 - -#include "vcollide.h" - -struct cmodel_t -{ - Vector mins, maxs; - Vector origin; // for sounds or lights - int headnode; - - vcollide_t vcollisionData; -}; - -struct csurface_t -{ - const char *name; - short surfaceProps; - unsigned short flags; // BUGBUG: These are declared per surface, not per material, but this database is per-material now -}; - -//----------------------------------------------------------------------------- -// A ray... -//----------------------------------------------------------------------------- - -struct Ray_t -{ - VectorAligned m_Start; // starting point, centered within the extents - VectorAligned m_Delta; // direction + length of the ray - VectorAligned m_StartOffset; // Add this to m_Start to get the actual ray start - VectorAligned m_Extents; // Describes an axis aligned box extruded along a ray - bool m_IsRay; // are the extents zero? - bool m_IsSwept; // is delta != 0? - - void Init( Vector const& start, Vector const& end ) - { - Assert( &end ); - VectorSubtract( end, start, m_Delta ); - - m_IsSwept = (m_Delta.LengthSqr() != 0); - - VectorClear( m_Extents ); - m_IsRay = true; - - // Offset m_Start to be in the center of the box... - VectorClear( m_StartOffset ); - VectorCopy( start, m_Start ); - } - - void Init( Vector const& start, Vector const& end, Vector const& mins, Vector const& maxs ) - { - Assert( &end ); - VectorSubtract( end, start, m_Delta ); - - m_IsSwept = (m_Delta.LengthSqr() != 0); - - VectorSubtract( maxs, mins, m_Extents ); - m_Extents *= 0.5f; - m_IsRay = (m_Extents.LengthSqr() < 1e-6); - - // Offset m_Start to be in the center of the box... - VectorAdd( mins, maxs, m_StartOffset ); - m_StartOffset *= 0.5f; - VectorAdd( start, m_StartOffset, m_Start ); - m_StartOffset *= -1.0f; - } - - // compute inverse delta - Vector InvDelta() const - { - Vector vecInvDelta; - for ( int iAxis = 0; iAxis < 3; ++iAxis ) - { - if ( m_Delta[iAxis] != 0.0f ) - { - vecInvDelta[iAxis] = 1.0f / m_Delta[iAxis]; - } - else - { - vecInvDelta[iAxis] = FLT_MAX; - } - } - return vecInvDelta; - } - -private: -}; - - -#endif // CMODEL_H - - -#include "gametrace.h" - diff --git a/public/collisionutils.cpp b/public/collisionutils.cpp deleted file mode 100644 index 446663152..000000000 --- a/public/collisionutils.cpp +++ /dev/null @@ -1,3253 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Common collision utility methods -// -// $Header: $ -// $NoKeywords: $ -//=============================================================================// - -#if !defined(_STATIC_LINKED) || defined(_SHARED_LIB) - -#include "collisionutils.h" -#include "cmodel.h" -#include "mathlib/mathlib.h" -#include "mathlib/vector.h" -#include "tier0/dbg.h" -#include -#include "mathlib/vector4d.h" -#include "trace.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#define UNINIT -99999.0 - -//----------------------------------------------------------------------------- -// Clears the trace -//----------------------------------------------------------------------------- -static void Collision_ClearTrace( const Vector &vecRayStart, const Vector &vecRayDelta, CBaseTrace *pTrace ) -{ - pTrace->startpos = vecRayStart; - pTrace->endpos = vecRayStart; - pTrace->endpos += vecRayDelta; - pTrace->startsolid = false; - pTrace->allsolid = false; - pTrace->fraction = 1.0f; - pTrace->contents = 0; -} - - -//----------------------------------------------------------------------------- -// Compute the offset in t along the ray that we'll use for the collision -//----------------------------------------------------------------------------- -static float ComputeBoxOffset( const Ray_t& ray ) -{ - if (ray.m_IsRay) - return 1e-3f; - - // Find the projection of the box diagonal along the ray... - float offset = FloatMakePositive(ray.m_Extents[0] * ray.m_Delta[0]) + - FloatMakePositive(ray.m_Extents[1] * ray.m_Delta[1]) + - FloatMakePositive(ray.m_Extents[2] * ray.m_Delta[2]); - - // We need to divide twice: Once to normalize the computation above - // so we get something in units of extents, and the second to normalize - // that with respect to the entire raycast. - offset *= InvRSquared( ray.m_Delta ); - - // 1e-3 is an epsilon - return offset + 1e-3; -} - - -//----------------------------------------------------------------------------- -// Intersects a swept box against a triangle -//----------------------------------------------------------------------------- -float IntersectRayWithTriangle( const Ray_t& ray, - const Vector& v1, const Vector& v2, const Vector& v3, bool oneSided ) -{ - // This is cute: Use barycentric coordinates to represent the triangle - // Vo(1-u-v) + V1u + V2v and intersect that with a line Po + Dt - // This gives us 3 equations + 3 unknowns, which we can solve with - // Cramer's rule... - // E1x u + E2x v - Dx t = Pox - Vox - // There's a couple of other optimizations, Cramer's rule involves - // computing the determinant of a matrix which has been constructed - // by three vectors. It turns out that - // det | A B C | = -( A x C ) dot B or -(C x B) dot A - // which we'll use below.. - - Vector edge1, edge2, org; - VectorSubtract( v2, v1, edge1 ); - VectorSubtract( v3, v1, edge2 ); - - // Cull out one-sided stuff - if (oneSided) - { - Vector normal; - CrossProduct( edge1, edge2, normal ); - if (DotProduct( normal, ray.m_Delta ) >= 0.0f) - return -1.0f; - } - - // FIXME: This is inaccurate, but fast for boxes - // We want to do a fast separating axis implementation here - // with a swept triangle along the reverse direction of the ray. - - // Compute some intermediary terms - Vector dirCrossEdge2, orgCrossEdge1; - CrossProduct( ray.m_Delta, edge2, dirCrossEdge2 ); - - // Compute the denominator of Cramer's rule: - // | -Dx E1x E2x | - // det | -Dy E1y E2y | = (D x E2) dot E1 - // | -Dz E1z E2z | - float denom = DotProduct( dirCrossEdge2, edge1 ); - if( FloatMakePositive( denom ) < 1e-6 ) - return -1.0f; - denom = 1.0f / denom; - - // Compute u. It's gotta lie in the range of 0 to 1. - // | -Dx orgx E2x | - // u = denom * det | -Dy orgy E2y | = (D x E2) dot org - // | -Dz orgz E2z | - VectorSubtract( ray.m_Start, v1, org ); - float u = DotProduct( dirCrossEdge2, org ) * denom; - if ((u < 0.0f) || (u > 1.0f)) - return -1.0f; - - // Compute t and v the same way... - // In barycentric coords, u + v < 1 - CrossProduct( org, edge1, orgCrossEdge1 ); - float v = DotProduct( orgCrossEdge1, ray.m_Delta ) * denom; - if ((v < 0.0f) || (v + u > 1.0f)) - return -1.0f; - - // Compute the distance along the ray direction that we need to fudge - // when using swept boxes - float boxt = ComputeBoxOffset( ray ); - float t = DotProduct( orgCrossEdge1, edge2 ) * denom; - if ((t < -boxt) || (t > 1.0f + boxt)) - return -1.0f; - - return clamp( t, 0, 1 ); -} - -//----------------------------------------------------------------------------- -// computes the barycentric coordinates of an intersection -//----------------------------------------------------------------------------- - -bool ComputeIntersectionBarycentricCoordinates( const Ray_t& ray, - const Vector& v1, const Vector& v2, const Vector& v3, float& u, float& v, - float *t ) -{ - Vector edge1, edge2, org; - VectorSubtract( v2, v1, edge1 ); - VectorSubtract( v3, v1, edge2 ); - - // Compute some intermediary terms - Vector dirCrossEdge2, orgCrossEdge1; - CrossProduct( ray.m_Delta, edge2, dirCrossEdge2 ); - - // Compute the denominator of Cramer's rule: - // | -Dx E1x E2x | - // det | -Dy E1y E2y | = (D x E2) dot E1 - // | -Dz E1z E2z | - float denom = DotProduct( dirCrossEdge2, edge1 ); - if( FloatMakePositive( denom ) < 1e-6 ) - return false; - denom = 1.0f / denom; - - // Compute u. It's gotta lie in the range of 0 to 1. - // | -Dx orgx E2x | - // u = denom * det | -Dy orgy E2y | = (D x E2) dot org - // | -Dz orgz E2z | - VectorSubtract( ray.m_Start, v1, org ); - u = DotProduct( dirCrossEdge2, org ) * denom; - - // Compute t and v the same way... - // In barycentric coords, u + v < 1 - CrossProduct( org, edge1, orgCrossEdge1 ); - v = DotProduct( orgCrossEdge1, ray.m_Delta ) * denom; - - // Compute the distance along the ray direction that we need to fudge - // when using swept boxes - if( t ) - { - float boxt = ComputeBoxOffset( ray ); - *t = DotProduct( orgCrossEdge1, edge2 ) * denom; - if( ( *t < -boxt ) || ( *t > 1.0f + boxt ) ) - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Intersects a plane with a triangle (requires barycentric definition) -//----------------------------------------------------------------------------- - -int IntersectTriangleWithPlaneBarycentric( const Vector& org, const Vector& edgeU, - const Vector& edgeV, const Vector4D& plane, Vector2D* pIntersection ) -{ - // This uses a barycentric method, since we need that to determine - // interpolated points, alphas, and normals - // Given the plane equation P dot N + d = 0 - // and the barycentric coodinate equation P = Org + EdgeU * u + EdgeV * v - // Plug em in. Intersection occurs at u = 0 or v = 0 or u + v = 1 - - float orgDotNormal = DotProduct( org, plane.AsVector3D() ); - float edgeUDotNormal = DotProduct( edgeU, plane.AsVector3D() ); - float edgeVDotNormal = DotProduct( edgeV, plane.AsVector3D() ); - - int ptIdx = 0; - - // u = 0 - if ( edgeVDotNormal != 0.0f ) - { - pIntersection[ptIdx].x = 0.0f; - pIntersection[ptIdx].y = - ( orgDotNormal - plane.w ) / edgeVDotNormal; - if ((pIntersection[ptIdx].y >= 0.0f) && (pIntersection[ptIdx].y <= 1.0f)) - ++ptIdx; - } - - // v = 0 - if ( edgeUDotNormal != 0.0f ) - { - pIntersection[ptIdx].x = - ( orgDotNormal - plane.w ) / edgeUDotNormal; - pIntersection[ptIdx].y = 0.0f; - if ((pIntersection[ptIdx].x >= 0.0f) && (pIntersection[ptIdx].x <= 1.0f)) - ++ptIdx; - } - - // u + v = 1 - if (ptIdx == 2) - return ptIdx; - - if ( edgeVDotNormal != edgeUDotNormal ) - { - pIntersection[ptIdx].x = - ( orgDotNormal - plane.w + edgeVDotNormal) / - ( edgeUDotNormal - edgeVDotNormal); - pIntersection[ptIdx].y = 1.0f - pIntersection[ptIdx].x;; - if ((pIntersection[ptIdx].x >= 0.0f) && (pIntersection[ptIdx].x <= 1.0f) && - (pIntersection[ptIdx].y >= 0.0f) && (pIntersection[ptIdx].y <= 1.0f)) - ++ptIdx; - } - - Assert( ptIdx < 3 ); - return ptIdx; -} - - -//----------------------------------------------------------------------------- -// Returns true if a box intersects with a sphere -//----------------------------------------------------------------------------- -bool IsSphereIntersectingSphere( const Vector& center1, float radius1, - const Vector& center2, float radius2 ) -{ - Vector delta; - VectorSubtract( center2, center1, delta ); - float distSq = delta.LengthSqr(); - float radiusSum = radius1 + radius2; - return (distSq <= (radiusSum * radiusSum)); -} - - -//----------------------------------------------------------------------------- -// Returns true if a box intersects with a sphere -//----------------------------------------------------------------------------- -bool IsBoxIntersectingSphere( const Vector& boxMin, const Vector& boxMax, - const Vector& center, float radius ) -{ - // See Graphics Gems, box-sphere intersection - float dmin = 0.0f; - float flDelta; - - // Unrolled the loop.. this is a big cycle stealer... - if (center[0] < boxMin[0]) - { - flDelta = center[0] - boxMin[0]; - dmin += flDelta * flDelta; - } - else if (center[0] > boxMax[0]) - { - flDelta = boxMax[0] - center[0]; - dmin += flDelta * flDelta; - } - - if (center[1] < boxMin[1]) - { - flDelta = center[1] - boxMin[1]; - dmin += flDelta * flDelta; - } - else if (center[1] > boxMax[1]) - { - flDelta = boxMax[1] - center[1]; - dmin += flDelta * flDelta; - } - - if (center[2] < boxMin[2]) - { - flDelta = center[2] - boxMin[2]; - dmin += flDelta * flDelta; - } - else if (center[2] > boxMax[2]) - { - flDelta = boxMax[2] - center[2]; - dmin += flDelta * flDelta; - } - - return dmin < radius * radius; -} - -bool IsBoxIntersectingSphereExtents( const Vector& boxCenter, const Vector& boxHalfDiag, - const Vector& center, float radius ) -{ - // See Graphics Gems, box-sphere intersection - float dmin = 0.0f; - float flDelta, flDiff; - - // Unrolled the loop.. this is a big cycle stealer... - flDiff = FloatMakePositive( center.x - boxCenter.x ); - if (flDiff > boxHalfDiag.x) - { - flDelta = flDiff - boxHalfDiag.x; - dmin += flDelta * flDelta; - } - - flDiff = FloatMakePositive( center.y - boxCenter.y ); - if (flDiff > boxHalfDiag.y) - { - flDelta = flDiff - boxHalfDiag.y; - dmin += flDelta * flDelta; - } - - flDiff = FloatMakePositive( center.z - boxCenter.z ); - if (flDiff > boxHalfDiag.z) - { - flDelta = flDiff - boxHalfDiag.z; - dmin += flDelta * flDelta; - } - - return dmin < radius * radius; -} - - -//----------------------------------------------------------------------------- -// Returns true if a rectangle intersects with a circle -//----------------------------------------------------------------------------- -bool IsCircleIntersectingRectangle( const Vector2D& boxMin, const Vector2D& boxMax, - const Vector2D& center, float radius ) -{ - // See Graphics Gems, box-sphere intersection - float dmin = 0.0f; - float flDelta; - - if (center[0] < boxMin[0]) - { - flDelta = center[0] - boxMin[0]; - dmin += flDelta * flDelta; - } - else if (center[0] > boxMax[0]) - { - flDelta = boxMax[0] - center[0]; - dmin += flDelta * flDelta; - } - - if (center[1] < boxMin[1]) - { - flDelta = center[1] - boxMin[1]; - dmin += flDelta * flDelta; - } - else if (center[1] > boxMax[1]) - { - flDelta = boxMax[1] - center[1]; - dmin += flDelta * flDelta; - } - - return dmin < radius * radius; -} - - -//----------------------------------------------------------------------------- -// returns true if there's an intersection between ray and sphere -//----------------------------------------------------------------------------- -bool IsRayIntersectingSphere( const Vector &vecRayOrigin, const Vector &vecRayDelta, - const Vector& vecCenter, float flRadius, float flTolerance ) -{ - // For this algorithm, find a point on the ray which is closest to the sphere origin - // Do this by making a plane passing through the sphere origin - // whose normal is parallel to the ray. Intersect that plane with the ray. - // Plane: N dot P = I, N = D (ray direction), I = C dot N = C dot D - // Ray: P = O + D * t - // D dot ( O + D * t ) = C dot D - // D dot O + D dot D * t = C dot D - // t = (C - O) dot D / D dot D - // Clamp t to (0,1) - // Find distance of the point on the ray to the sphere center. - Assert( flTolerance >= 0.0f ); - flRadius += flTolerance; - - Vector vecRayToSphere; - VectorSubtract( vecCenter, vecRayOrigin, vecRayToSphere ); - float flNumerator = DotProduct( vecRayToSphere, vecRayDelta ); - - float t; - if (flNumerator <= 0.0f) - { - t = 0.0f; - } - else - { - float flDenominator = DotProduct( vecRayDelta, vecRayDelta ); - if ( flNumerator > flDenominator ) - t = 1.0f; - else - t = flNumerator / flDenominator; - } - - Vector vecClosestPoint; - VectorMA( vecRayOrigin, t, vecRayDelta, vecClosestPoint ); - return ( vecClosestPoint.DistToSqr( vecCenter ) <= flRadius * flRadius ); - - // NOTE: This in an alternate algorithm which I didn't use because I'd have to use a sqrt - // So it's probably faster to do this other algorithm. I'll leave the comments here - // for how to go back if we want to - - // Solve using the ray equation + the sphere equation - // P = o + dt - // (x - xc)^2 + (y - yc)^2 + (z - zc)^2 = r^2 - // (ox + dx * t - xc)^2 + (oy + dy * t - yc)^2 + (oz + dz * t - zc)^2 = r^2 - // (ox - xc)^2 + 2 * (ox-xc) * dx * t + dx^2 * t^2 + - // (oy - yc)^2 + 2 * (oy-yc) * dy * t + dy^2 * t^2 + - // (oz - zc)^2 + 2 * (oz-zc) * dz * t + dz^2 * t^2 = r^2 - // (dx^2 + dy^2 + dz^2) * t^2 + 2 * ((ox-xc)dx + (oy-yc)dy + (oz-zc)dz) t + - // (ox-xc)^2 + (oy-yc)^2 + (oz-zc)^2 - r^2 = 0 - // or, t = (-b +/- sqrt( b^2 - 4ac)) / 2a - // a = DotProduct( vecRayDelta, vecRayDelta ); - // b = 2 * DotProduct( vecRayOrigin - vecCenter, vecRayDelta ) - // c = DotProduct(vecRayOrigin - vecCenter, vecRayOrigin - vecCenter) - flRadius * flRadius; - // Valid solutions are possible only if b^2 - 4ac >= 0 - // Therefore, compute that value + see if we got it -} - - -//----------------------------------------------------------------------------- -// -// IntersectInfiniteRayWithSphere -// -// Returns whether or not there was an intersection. -// Returns the two intersection points -// -//----------------------------------------------------------------------------- -bool IntersectInfiniteRayWithSphere( const Vector &vecRayOrigin, const Vector &vecRayDelta, - const Vector &vecSphereCenter, float flRadius, float *pT1, float *pT2 ) -{ - // Solve using the ray equation + the sphere equation - // P = o + dt - // (x - xc)^2 + (y - yc)^2 + (z - zc)^2 = r^2 - // (ox + dx * t - xc)^2 + (oy + dy * t - yc)^2 + (oz + dz * t - zc)^2 = r^2 - // (ox - xc)^2 + 2 * (ox-xc) * dx * t + dx^2 * t^2 + - // (oy - yc)^2 + 2 * (oy-yc) * dy * t + dy^2 * t^2 + - // (oz - zc)^2 + 2 * (oz-zc) * dz * t + dz^2 * t^2 = r^2 - // (dx^2 + dy^2 + dz^2) * t^2 + 2 * ((ox-xc)dx + (oy-yc)dy + (oz-zc)dz) t + - // (ox-xc)^2 + (oy-yc)^2 + (oz-zc)^2 - r^2 = 0 - // or, t = (-b +/- sqrt( b^2 - 4ac)) / 2a - // a = DotProduct( vecRayDelta, vecRayDelta ); - // b = 2 * DotProduct( vecRayOrigin - vecCenter, vecRayDelta ) - // c = DotProduct(vecRayOrigin - vecCenter, vecRayOrigin - vecCenter) - flRadius * flRadius; - - Vector vecSphereToRay; - VectorSubtract( vecRayOrigin, vecSphereCenter, vecSphereToRay ); - - float a = DotProduct( vecRayDelta, vecRayDelta ); - - // This would occur in the case of a zero-length ray - if ( a == 0.0f ) - { - *pT1 = *pT2 = 0.0f; - return vecSphereToRay.LengthSqr() <= flRadius * flRadius; - } - - float b = 2 * DotProduct( vecSphereToRay, vecRayDelta ); - float c = DotProduct( vecSphereToRay, vecSphereToRay ) - flRadius * flRadius; - float flDiscrim = b * b - 4 * a * c; - if ( flDiscrim < 0.0f ) - return false; - - flDiscrim = sqrt( flDiscrim ); - float oo2a = 0.5f / a; - *pT1 = ( - b - flDiscrim ) * oo2a; - *pT2 = ( - b + flDiscrim ) * oo2a; - return true; -} - - - -//----------------------------------------------------------------------------- -// -// IntersectRayWithSphere -// -// Returns whether or not there was an intersection. -// Returns the two intersection points, clamped to (0,1) -// -//----------------------------------------------------------------------------- -bool IntersectRayWithSphere( const Vector &vecRayOrigin, const Vector &vecRayDelta, - const Vector &vecSphereCenter, float flRadius, float *pT1, float *pT2 ) -{ - if ( !IntersectInfiniteRayWithSphere( vecRayOrigin, vecRayDelta, vecSphereCenter, flRadius, pT1, pT2 ) ) - return false; - - if (( *pT1 > 1.0f ) || ( *pT2 < 0.0f )) - return false; - - // Clamp it! - if ( *pT1 < 0.0f ) - *pT1 = 0.0f; - if ( *pT2 > 1.0f ) - *pT2 = 1.0f; - - return true; -} - - -// returns true if the sphere and cone intersect -// NOTE: cone sine/cosine are the half angle of the cone -bool IsSphereIntersectingCone( const Vector &sphereCenter, float sphereRadius, const Vector &coneOrigin, const Vector &coneNormal, float coneSine, float coneCosine ) -{ - Vector backCenter = coneOrigin - (sphereRadius / coneSine) * coneNormal; - Vector delta = sphereCenter - backCenter; - float deltaLen = delta.Length(); - if ( DotProduct(coneNormal, delta) >= deltaLen*coneCosine ) - { - delta = sphereCenter - coneOrigin; - deltaLen = delta.Length(); - if ( -DotProduct(coneNormal, delta) >= deltaLen * coneSine ) - { - return ( deltaLen <= sphereRadius ) ? true : false; - } - return true; - } - return false; -} - - - -//----------------------------------------------------------------------------- -// returns true if the point is in the box -//----------------------------------------------------------------------------- -bool IsPointInBox( const Vector& pt, const Vector& boxMin, const Vector& boxMax ) -{ - Assert( boxMin[0] <= boxMax[0] ); - Assert( boxMin[1] <= boxMax[1] ); - Assert( boxMin[2] <= boxMax[2] ); - - // on x360, force use of SIMD version. - if (IsX360()) - { - return IsPointInBox( LoadUnaligned3SIMD(pt.Base()), LoadUnaligned3SIMD(boxMin.Base()), LoadUnaligned3SIMD(boxMax.Base()) ) ; - } - - if ( (pt[0] > boxMax[0]) || (pt[0] < boxMin[0]) ) - return false; - if ( (pt[1] > boxMax[1]) || (pt[1] < boxMin[1]) ) - return false; - if ( (pt[2] > boxMax[2]) || (pt[2] < boxMin[2]) ) - return false; - return true; -} - - -bool IsPointInCone( const Vector &pt, const Vector &origin, const Vector &axis, float cosAngle, float length ) -{ - Vector delta = pt - origin; - float dist = VectorNormalize( delta ); - float dot = DotProduct( delta, axis ); - if ( dot < cosAngle ) - return false; - if ( dist * dot > length ) - return false; - - return true; -} - - -//----------------------------------------------------------------------------- -// returns true if there's an intersection between two boxes -//----------------------------------------------------------------------------- -bool IsBoxIntersectingBox( const Vector& boxMin1, const Vector& boxMax1, - const Vector& boxMin2, const Vector& boxMax2 ) -{ - Assert( boxMin1[0] <= boxMax1[0] ); - Assert( boxMin1[1] <= boxMax1[1] ); - Assert( boxMin1[2] <= boxMax1[2] ); - Assert( boxMin2[0] <= boxMax2[0] ); - Assert( boxMin2[1] <= boxMax2[1] ); - Assert( boxMin2[2] <= boxMax2[2] ); - - if ( (boxMin1[0] > boxMax2[0]) || (boxMax1[0] < boxMin2[0]) ) - return false; - if ( (boxMin1[1] > boxMax2[1]) || (boxMax1[1] < boxMin2[1]) ) - return false; - if ( (boxMin1[2] > boxMax2[2]) || (boxMax1[2] < boxMin2[2]) ) - return false; - return true; -} - -bool IsBoxIntersectingBoxExtents( const Vector& boxCenter1, const Vector& boxHalfDiagonal1, - const Vector& boxCenter2, const Vector& boxHalfDiagonal2 ) -{ - Vector vecDelta, vecSize; - VectorSubtract( boxCenter1, boxCenter2, vecDelta ); - VectorAdd( boxHalfDiagonal1, boxHalfDiagonal2, vecSize ); - return ( FloatMakePositive( vecDelta.x ) <= vecSize.x ) && - ( FloatMakePositive( vecDelta.y ) <= vecSize.y ) && - ( FloatMakePositive( vecDelta.z ) <= vecSize.z ); -} - - -//----------------------------------------------------------------------------- -// -// IsOBBIntersectingOBB -// -// returns true if there's an intersection between two OBBs -// -//----------------------------------------------------------------------------- -bool IsOBBIntersectingOBB( const Vector &vecOrigin1, const QAngle &vecAngles1, const Vector& boxMin1, const Vector& boxMax1, - const Vector &vecOrigin2, const QAngle &vecAngles2, const Vector& boxMin2, const Vector& boxMax2, float flTolerance ) -{ - // FIXME: Simple case AABB check doesn't work because the min and max extents are not oriented based on the angle - // this fast check would only be good for cubes. - /*if ( vecAngles1 == vecAngles2 ) - { - const Vector &vecDelta = vecOrigin2 - vecOrigin1; - Vector vecOtherMins, vecOtherMaxs; - VectorAdd( boxMin2, vecDelta, vecOtherMins ); - VectorAdd( boxMax2, vecDelta, vecOtherMaxs ); - return IsBoxIntersectingBox( boxMin1, boxMax1, vecOtherMins, vecOtherMaxs ); - }*/ - - // OBB test... - cplane_t plane; - bool bFoundPlane = ComputeSeparatingPlane( vecOrigin1, vecAngles1, boxMin1, boxMax1, - vecOrigin2, vecAngles2, boxMin2, boxMax2, flTolerance, &plane ); - return (bFoundPlane == false); -} - -// NOTE: This is only very slightly faster on high end PCs and x360 -#define USE_SIMD_RAY_CHECKS 1 -//----------------------------------------------------------------------------- -// returns true if there's an intersection between box and ray -//----------------------------------------------------------------------------- -bool FASTCALL IsBoxIntersectingRay( const Vector& boxMin, const Vector& boxMax, - const Vector& origin, const Vector& vecDelta, float flTolerance ) -{ - -#if USE_SIMD_RAY_CHECKS - // Load the unaligned ray/box parameters into SIMD registers - fltx4 start = LoadUnaligned3SIMD(origin.Base()); - fltx4 delta = LoadUnaligned3SIMD(vecDelta.Base()); - fltx4 boxMins = LoadUnaligned3SIMD( boxMin.Base() ); - fltx4 boxMaxs = LoadUnaligned3SIMD( boxMax.Base() ); - fltx4 epsilon = ReplicateX4(flTolerance); - // compute the mins/maxs of the box expanded by the ray extents - // relocate the problem so that the ray start is at the origin. - fltx4 offsetMins = SubSIMD(boxMins, start); - fltx4 offsetMaxs = SubSIMD(boxMaxs, start); - fltx4 offsetMinsExpanded = SubSIMD(offsetMins, epsilon); - fltx4 offsetMaxsExpanded = AddSIMD(offsetMaxs, epsilon); - - // Check to see if both the origin (start point) and the end point (delta) are on the front side - // of any of the box sides - if so there can be no intersection - fltx4 startOutMins = CmpLtSIMD(Four_Zeros, offsetMinsExpanded); - fltx4 endOutMins = CmpLtSIMD(delta,offsetMinsExpanded); - fltx4 minsMask = AndSIMD( startOutMins, endOutMins ); - fltx4 startOutMaxs = CmpGtSIMD(Four_Zeros, offsetMaxsExpanded); - fltx4 endOutMaxs = CmpGtSIMD(delta,offsetMaxsExpanded); - fltx4 maxsMask = AndSIMD( startOutMaxs, endOutMaxs ); - if ( IsAnyNegative(SetWToZeroSIMD(OrSIMD(minsMask,maxsMask)))) - return false; - - // now build the per-axis interval of t for intersections - fltx4 invDelta = ReciprocalSaturateSIMD(delta); - fltx4 tmins = MulSIMD( offsetMinsExpanded, invDelta ); - fltx4 tmaxs = MulSIMD( offsetMaxsExpanded, invDelta ); - fltx4 crossPlane = OrSIMD(XorSIMD(startOutMins,endOutMins), XorSIMD(startOutMaxs,endOutMaxs)); - - // only consider axes where we crossed a plane - tmins = MaskedAssign( crossPlane, tmins, Four_Negative_FLT_MAX ); - tmaxs = MaskedAssign( crossPlane, tmaxs, Four_FLT_MAX ); - - // now sort the interval per axis - fltx4 mint = MinSIMD( tmins, tmaxs ); - fltx4 maxt = MaxSIMD( tmins, tmaxs ); - - // now find the intersection of the intervals on all axes - fltx4 firstOut = FindLowestSIMD3(maxt); - fltx4 lastIn = FindHighestSIMD3(mint); - // NOTE: This is really a scalar quantity now [t0,t1] == [lastIn,firstOut] - firstOut = MinSIMD(firstOut, Four_Ones); - lastIn = MaxSIMD(lastIn, Four_Zeros); - - // If the final interval is valid lastIn boxMax[i] + flTolerance) ) - return false; - - continue; - } - - // non-parallel case - // Find the t's corresponding to the entry and exit of - // the ray along x, y, and z. The find the furthest entry - // point, and the closest exit point. Once that is done, - // we know we don't collide if the closest exit point - // is behind the starting location. We also don't collide if - // the closest exit point is in front of the furthest entry point - - float invDelta = 1.0f / vecDelta[i]; - float t1 = (boxMin[i] - flTolerance - origin[i]) * invDelta; - float t2 = (boxMax[i] + flTolerance - origin[i]) * invDelta; - if (t1 > t2) - { - float temp = t1; - t1 = t2; - t2 = temp; - } - if (t1 > tmin) - tmin = t1; - if (t2 < tmax) - tmax = t2; - if (tmin > tmax) - return false; - if (tmax < 0) - return false; - if (tmin > 1) - return false; - } - - return true; -#endif -} - -//----------------------------------------------------------------------------- -// returns true if there's an intersection between box and ray -//----------------------------------------------------------------------------- -bool FASTCALL IsBoxIntersectingRay( const Vector& boxMin, const Vector& boxMax, - const Vector& origin, const Vector& vecDelta, - const Vector& vecInvDelta, float flTolerance ) -{ -#if USE_SIMD_RAY_CHECKS - // Load the unaligned ray/box parameters into SIMD registers - fltx4 start = LoadUnaligned3SIMD(origin.Base()); - fltx4 delta = LoadUnaligned3SIMD(vecDelta.Base()); - fltx4 boxMins = LoadUnaligned3SIMD( boxMin.Base() ); - fltx4 boxMaxs = LoadUnaligned3SIMD( boxMax.Base() ); - // compute the mins/maxs of the box expanded by the ray extents - // relocate the problem so that the ray start is at the origin. - boxMins = SubSIMD(boxMins, start); - boxMaxs = SubSIMD(boxMaxs, start); - - // Check to see if both the origin (start point) and the end point (delta) are on the front side - // of any of the box sides - if so there can be no intersection - fltx4 startOutMins = CmpLtSIMD(Four_Zeros, boxMins); - fltx4 endOutMins = CmpLtSIMD(delta,boxMins); - fltx4 minsMask = AndSIMD( startOutMins, endOutMins ); - fltx4 startOutMaxs = CmpGtSIMD(Four_Zeros, boxMaxs); - fltx4 endOutMaxs = CmpGtSIMD(delta,boxMaxs); - fltx4 maxsMask = AndSIMD( startOutMaxs, endOutMaxs ); - if ( IsAnyNegative(SetWToZeroSIMD(OrSIMD(minsMask,maxsMask)))) - return false; - - // now build the per-axis interval of t for intersections - fltx4 epsilon = ReplicateX4(flTolerance); - fltx4 invDelta = LoadUnaligned3SIMD(vecInvDelta.Base()); - boxMins = SubSIMD(boxMins, epsilon); - boxMaxs = AddSIMD(boxMaxs, epsilon); - - boxMins = MulSIMD( boxMins, invDelta ); - boxMaxs = MulSIMD( boxMaxs, invDelta ); - - fltx4 crossPlane = OrSIMD(XorSIMD(startOutMins,endOutMins), XorSIMD(startOutMaxs,endOutMaxs)); - // only consider axes where we crossed a plane - boxMins = MaskedAssign( crossPlane, boxMins, Four_Negative_FLT_MAX ); - boxMaxs = MaskedAssign( crossPlane, boxMaxs, Four_FLT_MAX ); - - // now sort the interval per axis - fltx4 mint = MinSIMD( boxMins, boxMaxs ); - fltx4 maxt = MaxSIMD( boxMins, boxMaxs ); - - // now find the intersection of the intervals on all axes - fltx4 firstOut = FindLowestSIMD3(maxt); - fltx4 lastIn = FindHighestSIMD3(mint); - // NOTE: This is really a scalar quantity now [t0,t1] == [lastIn,firstOut] - firstOut = MinSIMD(firstOut, Four_Ones); - lastIn = MaxSIMD(lastIn, Four_Zeros); - - // If the final interval is valid lastIn boxMax[i] + flTolerance ) ) - return false; - - continue; - } - - // Non-parallel case - // Find the t's corresponding to the entry and exit of - // the ray along x, y, and z. The find the furthest entry - // point, and the closest exit point. Once that is done, - // we know we don't collide if the closest exit point - // is behind the starting location. We also don't collide if - // the closest exit point is in front of the furthest entry point - float t1 = ( boxMin[i] - flTolerance - origin[i] ) * vecInvDelta[i]; - float t2 = ( boxMax[i] + flTolerance - origin[i] ) * vecInvDelta[i]; - if ( t1 > t2 ) - { - float temp = t1; - t1 = t2; - t2 = temp; - } - - if (t1 > tmin) - tmin = t1; - - if (t2 < tmax) - tmax = t2; - - if (tmin > tmax) - return false; - - if (tmax < 0) - return false; - - if (tmin > 1) - return false; - } - - return true; -#endif -} - -//----------------------------------------------------------------------------- -// Intersects a ray with a aabb, return true if they intersect -//----------------------------------------------------------------------------- -bool FASTCALL IsBoxIntersectingRay( const Vector& vecBoxMin, const Vector& vecBoxMax, const Ray_t& ray, float flTolerance ) -{ - // On the x360, we force use of the SIMD functions. -#if defined(_X360) - if (IsX360()) - { - return IsBoxIntersectingRay( - LoadUnaligned3SIMD(vecBoxMin.Base()), LoadUnaligned3SIMD(vecBoxMax.Base()), - ray, flTolerance); - } -#endif - - if ( !ray.m_IsSwept ) - { - Vector rayMins, rayMaxs; - VectorSubtract( ray.m_Start, ray.m_Extents, rayMins ); - VectorAdd( ray.m_Start, ray.m_Extents, rayMaxs ); - if ( flTolerance != 0.0f ) - { - rayMins.x -= flTolerance; rayMins.y -= flTolerance; rayMins.z -= flTolerance; - rayMaxs.x += flTolerance; rayMaxs.y += flTolerance; rayMaxs.z += flTolerance; - } - return IsBoxIntersectingBox( vecBoxMin, vecBoxMax, rayMins, rayMaxs ); - } - - Vector vecExpandedBoxMin, vecExpandedBoxMax; - VectorSubtract( vecBoxMin, ray.m_Extents, vecExpandedBoxMin ); - VectorAdd( vecBoxMax, ray.m_Extents, vecExpandedBoxMax ); - return IsBoxIntersectingRay( vecExpandedBoxMin, vecExpandedBoxMax, ray.m_Start, ray.m_Delta, flTolerance ); -} - - -//----------------------------------------------------------------------------- -// returns true if there's an intersection between box and ray (SIMD version) -//----------------------------------------------------------------------------- - - -#ifdef _X360 -bool FASTCALL IsBoxIntersectingRay( fltx4 boxMin, fltx4 boxMax, - fltx4 origin, fltx4 delta, fltx4 invDelta, // ray parameters - fltx4 vTolerance ///< eg from ReplicateX4(flTolerance) - ) -#else -bool FASTCALL IsBoxIntersectingRay( const fltx4 &inBoxMin, const fltx4 & inBoxMax, - const fltx4 & origin, const fltx4 & delta, const fltx4 & invDelta, // ray parameters - const fltx4 & vTolerance ///< eg from ReplicateX4(flTolerance) - ) -#endif -{ - // Load the unaligned ray/box parameters into SIMD registers - // compute the mins/maxs of the box expanded by the ray extents - // relocate the problem so that the ray start is at the origin. - -#ifdef _X360 - boxMin = SubSIMD(boxMin, origin); - boxMax = SubSIMD(boxMax, origin); -#else - fltx4 boxMin = SubSIMD(inBoxMin, origin); - fltx4 boxMax = SubSIMD(inBoxMax, origin); -#endif - - // Check to see if the origin (start point) and the end point (delta) are on the same side - // of any of the box sides - if so there can be no intersection - fltx4 startOutMins = AndSIMD( CmpLtSIMD(Four_Zeros, boxMin), CmpLtSIMD(delta,boxMin) ); - fltx4 startOutMaxs = AndSIMD( CmpGtSIMD(Four_Zeros, boxMax), CmpGtSIMD(delta,boxMax) ); - if ( IsAnyNegative(SetWToZeroSIMD(OrSIMD(startOutMaxs,startOutMins)))) - return false; - - // now build the per-axis interval of t for intersections - boxMin = SubSIMD(boxMin, vTolerance); - boxMax = AddSIMD(boxMax, vTolerance); - - boxMin = MulSIMD( boxMin, invDelta ); - boxMax = MulSIMD( boxMax, invDelta ); - - // now sort the interval per axis - fltx4 mint = MinSIMD( boxMin, boxMax ); - fltx4 maxt = MaxSIMD( boxMin, boxMax ); - - // now find the intersection of the intervals on all axes - fltx4 firstOut = FindLowestSIMD3(maxt); - fltx4 lastIn = FindHighestSIMD3(mint); - // NOTE: This is really a scalar quantity now [t0,t1] == [lastIn,firstOut] - firstOut = MinSIMD(firstOut, Four_Ones); - lastIn = MaxSIMD(lastIn, Four_Zeros); - - // If the final interval is valid lastInt1 = -1.0f; - pTrace->t2 = 1.0f; - pTrace->hitside = -1; - - // UNDONE: This makes this code a little messy - pTrace->startsolid = true; - - for ( i = 0; i < 6; ++i ) - { - if ( i >= 3 ) - { - d1 = vecRayStart[i-3] - boxMaxs[i-3]; - d2 = d1 + vecRayDelta[i-3]; - } - else - { - d1 = -vecRayStart[i] + boxMins[i]; - d2 = d1 - vecRayDelta[i]; - } - - // if completely in front of face, no intersection - if (d1 > 0 && d2 > 0) - { - // UNDONE: Have to revert this in case it's still set - // UNDONE: Refactor to have only 2 return points (true/false) from this function - pTrace->startsolid = false; - return false; - } - - // completely inside, check next face - if (d1 <= 0 && d2 <= 0) - continue; - - if (d1 > 0) - { - pTrace->startsolid = false; - } - - // crosses face - if (d1 > d2) - { - f = d1 - flTolerance; - if ( f < 0 ) - { - f = 0; - } - f = f / (d1-d2); - if (f > pTrace->t1) - { - pTrace->t1 = f; - pTrace->hitside = i; - } - } - else - { - // leave - f = (d1 + flTolerance) / (d1-d2); - if (f < pTrace->t2) - { - pTrace->t2 = f; - } - } - } - - return pTrace->startsolid || (pTrace->t1 < pTrace->t2 && pTrace->t1 >= 0.0f); -} - - -//----------------------------------------------------------------------------- -// Intersects a ray against a box -//----------------------------------------------------------------------------- -bool IntersectRayWithBox( const Vector &vecRayStart, const Vector &vecRayDelta, - const Vector &boxMins, const Vector &boxMaxs, float flTolerance, CBaseTrace *pTrace, float *pFractionLeftSolid ) -{ - Collision_ClearTrace( vecRayStart, vecRayDelta, pTrace ); - - BoxTraceInfo_t trace; - - if ( IntersectRayWithBox( vecRayStart, vecRayDelta, boxMins, boxMaxs, flTolerance, &trace ) ) - { - pTrace->startsolid = trace.startsolid; - if (trace.t1 < trace.t2 && trace.t1 >= 0.0f) - { - pTrace->fraction = trace.t1; - VectorMA( pTrace->startpos, trace.t1, vecRayDelta, pTrace->endpos ); - pTrace->contents = CONTENTS_SOLID; - pTrace->plane.normal = vec3_origin; - if ( trace.hitside >= 3 ) - { - trace.hitside -= 3; - pTrace->plane.dist = boxMaxs[trace.hitside]; - pTrace->plane.normal[trace.hitside] = 1.0f; - pTrace->plane.type = trace.hitside; - } - else - { - pTrace->plane.dist = -boxMins[trace.hitside]; - pTrace->plane.normal[trace.hitside] = -1.0f; - pTrace->plane.type = trace.hitside; - } - return true; - } - - if ( pTrace->startsolid ) - { - pTrace->allsolid = (trace.t2 <= 0.0f) || (trace.t2 >= 1.0f); - pTrace->fraction = 0; - if ( pFractionLeftSolid ) - { - *pFractionLeftSolid = trace.t2; - } - pTrace->endpos = pTrace->startpos; - pTrace->contents = CONTENTS_SOLID; - pTrace->plane.dist = pTrace->startpos[0]; - pTrace->plane.normal.Init( 1.0f, 0.0f, 0.0f ); - pTrace->plane.type = 0; - pTrace->startpos = vecRayStart + (trace.t2 * vecRayDelta); - return true; - } - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Intersects a ray against a box -//----------------------------------------------------------------------------- -bool IntersectRayWithBox( const Ray_t &ray, const Vector &boxMins, const Vector &boxMaxs, - float flTolerance, CBaseTrace *pTrace, float *pFractionLeftSolid ) -{ - if ( !ray.m_IsRay ) - { - Vector vecExpandedMins = boxMins - ray.m_Extents; - Vector vecExpandedMaxs = boxMaxs + ray.m_Extents; - bool bIntersects = IntersectRayWithBox( ray.m_Start, ray.m_Delta, vecExpandedMins, vecExpandedMaxs, flTolerance, pTrace, pFractionLeftSolid ); - pTrace->startpos += ray.m_StartOffset; - pTrace->endpos += ray.m_StartOffset; - return bIntersects; - } - return IntersectRayWithBox( ray.m_Start, ray.m_Delta, boxMins, boxMaxs, flTolerance, pTrace, pFractionLeftSolid ); -} - - -//----------------------------------------------------------------------------- -// Intersects a ray against an OBB, returns t1 and t2 -//----------------------------------------------------------------------------- -bool IntersectRayWithOBB( const Vector &vecRayStart, const Vector &vecRayDelta, - const matrix3x4_t &matOBBToWorld, const Vector &vecOBBMins, const Vector &vecOBBMaxs, - float flTolerance, BoxTraceInfo_t *pTrace ) -{ - // FIXME: Two transforms is pretty expensive. Should we optimize this? - Vector start, delta; - VectorITransform( vecRayStart, matOBBToWorld, start ); - VectorIRotate( vecRayDelta, matOBBToWorld, delta ); - - return IntersectRayWithBox( start, delta, vecOBBMins, vecOBBMaxs, flTolerance, pTrace ); -} - - - -//----------------------------------------------------------------------------- -// Intersects a ray against an OBB -//----------------------------------------------------------------------------- -bool IntersectRayWithOBB( const Vector &vecRayStart, const Vector &vecRayDelta, - const matrix3x4_t &matOBBToWorld, const Vector &vecOBBMins, const Vector &vecOBBMaxs, - float flTolerance, CBaseTrace *pTrace ) -{ - Collision_ClearTrace( vecRayStart, vecRayDelta, pTrace ); - - // FIXME: Make it work with tolerance - Assert( flTolerance == 0.0f ); - - // OPTIMIZE: Store this in the box instead of computing it here - // compute center in local space - Vector vecBoxExtents = (vecOBBMins + vecOBBMaxs) * 0.5; - Vector vecBoxCenter; - - // transform to world space - VectorTransform( vecBoxExtents, matOBBToWorld, vecBoxCenter ); - - // calc extents from local center - vecBoxExtents = vecOBBMaxs - vecBoxExtents; - - // OPTIMIZE: This is optimized for world space. If the transform is fast enough, it may make more - // sense to just xform and call UTIL_ClipToBox() instead. MEASURE THIS. - - // save the extents of the ray along - Vector extent, uextent; - Vector segmentCenter = vecRayStart + vecRayDelta - vecBoxCenter; - - extent.Init(); - - // check box axes for separation - for ( int j = 0; j < 3; j++ ) - { - extent[j] = vecRayDelta.x * matOBBToWorld[0][j] + vecRayDelta.y * matOBBToWorld[1][j] + vecRayDelta.z * matOBBToWorld[2][j]; - uextent[j] = fabsf(extent[j]); - float coord = segmentCenter.x * matOBBToWorld[0][j] + segmentCenter.y * matOBBToWorld[1][j] + segmentCenter.z * matOBBToWorld[2][j]; - coord = fabsf(coord); - - if ( coord > (vecBoxExtents[j] + uextent[j]) ) - return false; - } - - // now check cross axes for separation - float tmp, cextent; - Vector cross = vecRayDelta.Cross( segmentCenter ); - cextent = cross.x * matOBBToWorld[0][0] + cross.y * matOBBToWorld[1][0] + cross.z * matOBBToWorld[2][0]; - cextent = fabsf(cextent); - tmp = vecBoxExtents[1]*uextent[2] + vecBoxExtents[2]*uextent[1]; - if ( cextent > tmp ) - return false; - - cextent = cross.x * matOBBToWorld[0][1] + cross.y * matOBBToWorld[1][1] + cross.z * matOBBToWorld[2][1]; - cextent = fabsf(cextent); - tmp = vecBoxExtents[0]*uextent[2] + vecBoxExtents[2]*uextent[0]; - if ( cextent > tmp ) - return false; - - cextent = cross.x * matOBBToWorld[0][2] + cross.y * matOBBToWorld[1][2] + cross.z * matOBBToWorld[2][2]; - cextent = fabsf(cextent); - tmp = vecBoxExtents[0]*uextent[1] + vecBoxExtents[1]*uextent[0]; - if ( cextent > tmp ) - return false; - - // !!! We hit this box !!! compute intersection point and return - // Compute ray start in bone space - Vector start; - VectorITransform( vecRayStart, matOBBToWorld, start ); - - // extent is ray.m_Delta in bone space, recompute delta in bone space - extent *= 2.0f; - - // delta was prescaled by the current t, so no need to see if this intersection - // is closer - trace_t boxTrace; - if ( !IntersectRayWithBox( start, extent, vecOBBMins, vecOBBMaxs, flTolerance, pTrace ) ) - return false; - - // Fix up the plane information - float flSign = pTrace->plane.normal[ pTrace->plane.type ]; - pTrace->plane.normal[0] = flSign * matOBBToWorld[0][pTrace->plane.type]; - pTrace->plane.normal[1] = flSign * matOBBToWorld[1][pTrace->plane.type]; - pTrace->plane.normal[2] = flSign * matOBBToWorld[2][pTrace->plane.type]; - pTrace->plane.dist = DotProduct( pTrace->endpos, pTrace->plane.normal ); - pTrace->plane.type = 3; - return true; -} - - -//----------------------------------------------------------------------------- -// Intersects a ray against an OBB -//----------------------------------------------------------------------------- -bool IntersectRayWithOBB( const Vector &vecRayOrigin, const Vector &vecRayDelta, - const Vector &vecBoxOrigin, const QAngle &angBoxRotation, - const Vector &vecOBBMins, const Vector &vecOBBMaxs, float flTolerance, CBaseTrace *pTrace ) -{ - if (angBoxRotation == vec3_angle) - { - Vector vecAbsMins, vecAbsMaxs; - VectorAdd( vecBoxOrigin, vecOBBMins, vecAbsMins ); - VectorAdd( vecBoxOrigin, vecOBBMaxs, vecAbsMaxs ); - return IntersectRayWithBox( vecRayOrigin, vecRayDelta, vecAbsMins, vecAbsMaxs, flTolerance, pTrace ); - } - - matrix3x4_t obbToWorld; - AngleMatrix( angBoxRotation, vecBoxOrigin, obbToWorld ); - return IntersectRayWithOBB( vecRayOrigin, vecRayDelta, obbToWorld, vecOBBMins, vecOBBMaxs, flTolerance, pTrace ); -} - - -//----------------------------------------------------------------------------- -// Box support map -//----------------------------------------------------------------------------- -inline void ComputeSupportMap( const Vector &vecDirection, const Vector &vecBoxMins, - const Vector &vecBoxMaxs, float pDist[2] ) -{ - int nIndex = (vecDirection.x > 0.0f); - pDist[nIndex] = vecBoxMaxs.x * vecDirection.x; - pDist[1 - nIndex] = vecBoxMins.x * vecDirection.x; - - nIndex = (vecDirection.y > 0.0f); - pDist[nIndex] += vecBoxMaxs.y * vecDirection.y; - pDist[1 - nIndex] += vecBoxMins.y * vecDirection.y; - - nIndex = (vecDirection.z > 0.0f); - pDist[nIndex] += vecBoxMaxs.z * vecDirection.z; - pDist[1 - nIndex] += vecBoxMins.z * vecDirection.z; -} - -inline void ComputeSupportMap( const Vector &vecDirection, int i1, int i2, - const Vector &vecBoxMins, const Vector &vecBoxMaxs, float pDist[2] ) -{ - int nIndex = (vecDirection[i1] > 0.0f); - pDist[nIndex] = vecBoxMaxs[i1] * vecDirection[i1]; - pDist[1 - nIndex] = vecBoxMins[i1] * vecDirection[i1]; - - nIndex = (vecDirection[i2] > 0.0f); - pDist[nIndex] += vecBoxMaxs[i2] * vecDirection[i2]; - pDist[1 - nIndex] += vecBoxMins[i2] * vecDirection[i2]; -} - -//----------------------------------------------------------------------------- -// Intersects a ray against an OBB -//----------------------------------------------------------------------------- -static int s_ExtIndices[3][2] = -{ - { 2, 1 }, - { 0, 2 }, - { 0, 1 }, -}; - -static int s_MatIndices[3][2] = -{ - { 1, 2 }, - { 2, 0 }, - { 1, 0 }, -}; - -bool IntersectRayWithOBB( const Ray_t &ray, const matrix3x4_t &matOBBToWorld, - const Vector &vecOBBMins, const Vector &vecOBBMaxs, float flTolerance, CBaseTrace *pTrace ) -{ - if ( ray.m_IsRay ) - { - return IntersectRayWithOBB( ray.m_Start, ray.m_Delta, matOBBToWorld, - vecOBBMins, vecOBBMaxs, flTolerance, pTrace ); - } - - Collision_ClearTrace( ray.m_Start + ray.m_StartOffset, ray.m_Delta, pTrace ); - - // Compute a bounding sphere around the bloated OBB - Vector vecOBBCenter; - VectorAdd( vecOBBMins, vecOBBMaxs, vecOBBCenter ); - vecOBBCenter *= 0.5f; - vecOBBCenter.x += matOBBToWorld[0][3]; - vecOBBCenter.y += matOBBToWorld[1][3]; - vecOBBCenter.z += matOBBToWorld[2][3]; - - Vector vecOBBHalfDiagonal; - VectorSubtract( vecOBBMaxs, vecOBBMins, vecOBBHalfDiagonal ); - vecOBBHalfDiagonal *= 0.5f; - - float flRadius = vecOBBHalfDiagonal.Length() + ray.m_Extents.Length(); - if ( !IsRayIntersectingSphere( ray.m_Start, ray.m_Delta, vecOBBCenter, flRadius, flTolerance ) ) - return false; - - // Ok, we passed the trivial reject, so lets do the dirty deed. - // Basically we're going to do the GJK thing explicitly. We'll shrink the ray down - // to a point, and bloat the OBB by the ray's extents. This will generate facet - // planes which are perpendicular to all of the separating axes typically seen in - // a standard seperating axis implementation. - - // We're going to create a number of planes through various vertices in the OBB - // which represent all of the separating planes. Then we're going to bloat the planes - // by the ray extents. - - // We're going to do all work in OBB-space because it's easier to do the - // support-map in this case - - // First, transform the ray into the space of the OBB - Vector vecLocalRayOrigin, vecLocalRayDirection; - VectorITransform( ray.m_Start, matOBBToWorld, vecLocalRayOrigin ); - VectorIRotate( ray.m_Delta, matOBBToWorld, vecLocalRayDirection ); - - // Next compute all separating planes - Vector pPlaneNormal[15]; - float ppPlaneDist[15][2]; - - int i; - for ( i = 0; i < 3; ++i ) - { - // Each plane needs to be bloated an amount = to the abs dot product of - // the ray extents with the plane normal - // For the OBB planes, do it in world space; - // and use the direction of the OBB (the ith column of matOBBToWorld) in world space vs extents - pPlaneNormal[i].Init( ); - pPlaneNormal[i][i] = 1.0f; - - float flExtentDotNormal = - FloatMakePositive( matOBBToWorld[0][i] * ray.m_Extents.x ) + - FloatMakePositive( matOBBToWorld[1][i] * ray.m_Extents.y ) + - FloatMakePositive( matOBBToWorld[2][i] * ray.m_Extents.z ); - - ppPlaneDist[i][0] = vecOBBMins[i] - flExtentDotNormal; - ppPlaneDist[i][1] = vecOBBMaxs[i] + flExtentDotNormal; - - // For the ray-extents planes, they are bloated by the extents - // Use the support map to determine which - VectorCopy( matOBBToWorld[i], pPlaneNormal[i+3].Base() ); - ComputeSupportMap( pPlaneNormal[i+3], vecOBBMins, vecOBBMaxs, ppPlaneDist[i+3] ); - ppPlaneDist[i+3][0] -= ray.m_Extents[i]; - ppPlaneDist[i+3][1] += ray.m_Extents[i]; - - // Now the edge cases... (take the cross product of x,y,z axis w/ ray extent axes - // given by the rows of the obb to world matrix. - // Compute the ray extent bloat in world space because it's easier... - - // These are necessary to compute the world-space versions of - // the edges so we can compute the extent dot products - float flRayExtent0 = ray.m_Extents[s_ExtIndices[i][0]]; - float flRayExtent1 = ray.m_Extents[s_ExtIndices[i][1]]; - const float *pMatRow0 = matOBBToWorld[s_MatIndices[i][0]]; - const float *pMatRow1 = matOBBToWorld[s_MatIndices[i][1]]; - - // x axis of the OBB + world ith axis - pPlaneNormal[i+6].Init( 0.0f, -matOBBToWorld[i][2], matOBBToWorld[i][1] ); - ComputeSupportMap( pPlaneNormal[i+6], 1, 2, vecOBBMins, vecOBBMaxs, ppPlaneDist[i+6] ); - flExtentDotNormal = - FloatMakePositive( pMatRow0[0] ) * flRayExtent0 + - FloatMakePositive( pMatRow1[0] ) * flRayExtent1; - ppPlaneDist[i+6][0] -= flExtentDotNormal; - ppPlaneDist[i+6][1] += flExtentDotNormal; - - // y axis of the OBB + world ith axis - pPlaneNormal[i+9].Init( matOBBToWorld[i][2], 0.0f, -matOBBToWorld[i][0] ); - ComputeSupportMap( pPlaneNormal[i+9], 0, 2, vecOBBMins, vecOBBMaxs, ppPlaneDist[i+9] ); - flExtentDotNormal = - FloatMakePositive( pMatRow0[1] ) * flRayExtent0 + - FloatMakePositive( pMatRow1[1] ) * flRayExtent1; - ppPlaneDist[i+9][0] -= flExtentDotNormal; - ppPlaneDist[i+9][1] += flExtentDotNormal; - - // z axis of the OBB + world ith axis - pPlaneNormal[i+12].Init( -matOBBToWorld[i][1], matOBBToWorld[i][0], 0.0f ); - ComputeSupportMap( pPlaneNormal[i+12], 0, 1, vecOBBMins, vecOBBMaxs, ppPlaneDist[i+12] ); - flExtentDotNormal = - FloatMakePositive( pMatRow0[2] ) * flRayExtent0 + - FloatMakePositive( pMatRow1[2] ) * flRayExtent1; - ppPlaneDist[i+12][0] -= flExtentDotNormal; - ppPlaneDist[i+12][1] += flExtentDotNormal; - } - - float enterfrac, leavefrac; - float d1[2], d2[2]; - float f; - - int hitplane = -1; - int hitside = -1; - enterfrac = -1.0f; - leavefrac = 1.0f; - - pTrace->startsolid = true; - - Vector vecLocalRayEnd; - VectorAdd( vecLocalRayOrigin, vecLocalRayDirection, vecLocalRayEnd ); - - for ( i = 0; i < 15; ++i ) - { - // FIXME: Not particularly optimal since there's a lot of 0's in the plane normals - float flStartDot = DotProduct( pPlaneNormal[i], vecLocalRayOrigin ); - float flEndDot = DotProduct( pPlaneNormal[i], vecLocalRayEnd ); - - // NOTE: Negative here is because the plane normal + dist - // are defined in negative terms for the far plane (plane dist index 0) - d1[0] = -(flStartDot - ppPlaneDist[i][0]); - d2[0] = -(flEndDot - ppPlaneDist[i][0]); - - d1[1] = flStartDot - ppPlaneDist[i][1]; - d2[1] = flEndDot - ppPlaneDist[i][1]; - - int j; - for ( j = 0; j < 2; ++j ) - { - // if completely in front near plane or behind far plane no intersection - if (d1[j] > 0 && d2[j] > 0) - return false; - - // completely inside, check next plane set - if (d1[j] <= 0 && d2[j] <= 0) - continue; - - if (d1[j] > 0) - { - pTrace->startsolid = false; - } - - // crosses face - float flDenom = 1.0f / (d1[j] - d2[j]); - if (d1[j] > d2[j]) - { - f = d1[j] - flTolerance; - if ( f < 0 ) - { - f = 0; - } - f *= flDenom; - if (f > enterfrac) - { - enterfrac = f; - hitplane = i; - hitside = j; - } - } - else - { - // leave - f = (d1[j] + flTolerance) * flDenom; - if (f < leavefrac) - { - leavefrac = f; - } - } - } - } - - if (enterfrac < leavefrac && enterfrac >= 0.0f) - { - pTrace->fraction = enterfrac; - VectorMA( pTrace->startpos, enterfrac, ray.m_Delta, pTrace->endpos ); - pTrace->contents = CONTENTS_SOLID; - - // Need to transform the plane into world space... - cplane_t temp; - temp.normal = pPlaneNormal[hitplane]; - temp.dist = ppPlaneDist[hitplane][hitside]; - if (hitside == 0) - { - temp.normal *= -1.0f; - temp.dist *= -1.0f; - } - temp.type = 3; - - MatrixITransformPlane( matOBBToWorld, temp, pTrace->plane ); - return true; - } - - if ( pTrace->startsolid ) - { - pTrace->allsolid = (leavefrac <= 0.0f) || (leavefrac >= 1.0f); - pTrace->fraction = 0; - pTrace->endpos = pTrace->startpos; - pTrace->contents = CONTENTS_SOLID; - pTrace->plane.dist = pTrace->startpos[0]; - pTrace->plane.normal.Init( 1.0f, 0.0f, 0.0f ); - pTrace->plane.type = 0; - return true; - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Intersects a ray against an OBB -//----------------------------------------------------------------------------- -bool IntersectRayWithOBB( const Ray_t &ray, const Vector &vecBoxOrigin, const QAngle &angBoxRotation, - const Vector &vecOBBMins, const Vector &vecOBBMaxs, float flTolerance, CBaseTrace *pTrace ) -{ - if ( angBoxRotation == vec3_angle ) - { - Vector vecWorldMins, vecWorldMaxs; - VectorAdd( vecBoxOrigin, vecOBBMins, vecWorldMins ); - VectorAdd( vecBoxOrigin, vecOBBMaxs, vecWorldMaxs ); - return IntersectRayWithBox( ray, vecWorldMins, vecWorldMaxs, flTolerance, pTrace ); - } - - if ( ray.m_IsRay ) - { - return IntersectRayWithOBB( ray.m_Start, ray.m_Delta, vecBoxOrigin, angBoxRotation, vecOBBMins, vecOBBMaxs, flTolerance, pTrace ); - } - - matrix3x4_t matOBBToWorld; - AngleMatrix( angBoxRotation, vecBoxOrigin, matOBBToWorld ); - return IntersectRayWithOBB( ray, matOBBToWorld, vecOBBMins, vecOBBMaxs, flTolerance, pTrace ); -} - - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -void GetNonMajorAxes( const Vector &vNormal, Vector2D &axes ) -{ - axes[0] = 0; - axes[1] = 1; - - if( FloatMakePositive( vNormal.x ) > FloatMakePositive( vNormal.y ) ) - { - if( FloatMakePositive( vNormal.x ) > FloatMakePositive( vNormal.z ) ) - { - axes[0] = 1; - axes[1] = 2; - } - } - else - { - if( FloatMakePositive( vNormal.y ) > FloatMakePositive( vNormal.z ) ) - { - axes[0] = 0; - axes[1] = 2; - } - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -QuadBarycentricRetval_t QuadWithParallelEdges( const Vector &vecOrigin, - const Vector &vecU, float lengthU, const Vector &vecV, float lengthV, - const Vector &pt, Vector2D &vecUV ) -{ - Ray_t rayAxis; - Ray_t rayPt; - - // - // handle the u axis - // - rayAxis.m_Start = vecOrigin; - rayAxis.m_Delta = vecU; - rayAxis.m_IsRay = true; - - rayPt.m_Start = pt; - rayPt.m_Delta = vecV * -( lengthV * 10.0f ); - rayPt.m_IsRay = true; - - float s, t; - IntersectRayWithRay( rayAxis, rayPt, t, s ); - vecUV[0] = t / lengthU; - - // - // handle the v axis - // - rayAxis.m_Delta = vecV; - - rayPt.m_Delta = vecU * -( lengthU * 10.0f ); - - IntersectRayWithRay( rayAxis, rayPt, t, s ); - vecUV[1] = t / lengthV; - - // inside of the quad?? - if( ( vecUV[0] < 0.0f ) || ( vecUV[0] > 1.0f ) || - ( vecUV[1] < 0.0f ) || ( vecUV[1] > 1.0f ) ) - return BARY_QUADRATIC_FALSE; - - return BARY_QUADRATIC_TRUE; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void ResolveQuadratic( double tPlus, double tMinus, - const Vector axisU0, const Vector axisU1, - const Vector axisV0, const Vector axisV1, - const Vector axisOrigin, const Vector pt, - int projU, double &s, double &t ) -{ - // calculate the sPlus, sMinus pair(s) - double sDenomPlus = ( axisU0[projU] * ( 1 - tPlus ) ) + ( axisU1[projU] * tPlus ); - double sDenomMinus = ( axisU0[projU] * ( 1 - tMinus ) ) + ( axisU1[projU] * tMinus ); - - double sPlus = UNINIT, sMinus = UNINIT; - if( FloatMakePositive( sDenomPlus ) >= 1e-5 ) - { - sPlus = ( pt[projU] - axisOrigin[projU] - ( axisV0[projU] * tPlus ) ) / sDenomPlus; - } - - if( FloatMakePositive( sDenomMinus ) >= 1e-5 ) - { - sMinus = ( pt[projU] - axisOrigin[projU] - ( axisV0[projU] * tMinus ) ) / sDenomMinus; - } - - if( ( tPlus >= 0.0 ) && ( tPlus <= 1.0 ) && ( sPlus >= 0.0 ) && ( sPlus <= 1.0 ) ) - { - s = sPlus; - t = tPlus; - return; - } - - if( ( tMinus >= 0.0 ) && ( tMinus <= 1.0 ) && ( sMinus >= 0.0 ) && ( sMinus <= 1.0 ) ) - { - s = sMinus; - t = tMinus; - return; - } - - double s0, t0, s1, t1; - - s0 = sPlus; - t0 = tPlus; - if( s0 >= 1.0 ) { s0 -= 1.0; } - if( t0 >= 1.0 ) { t0 -= 1.0; } - - s1 = sMinus; - t1 = tMinus; - if( s1 >= 1.0 ) { s1 -= 1.0; } - if( t1 >= 1.0 ) { t1 -= 1.0; } - - s0 = FloatMakePositive( s0 ); - t0 = FloatMakePositive( t0 ); - s1 = FloatMakePositive( s1 ); - t1 = FloatMakePositive( t1 ); - - double max0, max1; - max0 = s0; - if( t0 > max0 ) { max0 = t0; } - max1 = s1; - if( t1 > max1 ) { max1 = t1; } - - if( max0 > max1 ) - { - s = sMinus; - t = tMinus; - } - else - { - s = sPlus; - t = tPlus; - } -} - - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- - -QuadBarycentricRetval_t PointInQuadToBarycentric( const Vector &v1, const Vector &v2, - const Vector &v3, const Vector &v4, const Vector &point, Vector2D &uv ) -{ -#define PIQ_TEXTURE_EPSILON 0.001 -#define PIQ_PLANE_EPSILON 0.1 -#define PIQ_DOT_EPSILON 0.99f - - // - // Think of a quad with points v1, v2, v3, v4 and u, v line segments - // u0 = v2 - v1 - // u1 = v3 - v4 - // v0 = v4 - v1 - // v1 = v3 - v2 - // - Vector axisU[2], axisV[2]; - Vector axisUNorm[2], axisVNorm[2]; - axisU[0] = axisUNorm[0] = v2 - v1; - axisU[1] = axisUNorm[1] = v3 - v4; - axisV[0] = axisVNorm[0] = v4 - v1; - axisV[1] = axisVNorm[1] = v3 - v2; - - float lengthU[2], lengthV[2]; - lengthU[0] = VectorNormalize( axisUNorm[0] ); - lengthU[1] = VectorNormalize( axisUNorm[1] ); - lengthV[0] = VectorNormalize( axisVNorm[0] ); - lengthV[1] = VectorNormalize( axisVNorm[1] ); - - // - // check for an early out - parallel opposite edges! - // NOTE: quad property if 1 set of opposite edges is parallel and equal - // in length, then the other set of edges is as well - // - if( axisUNorm[0].Dot( axisUNorm[1] ) > PIQ_DOT_EPSILON ) - { - if( FloatMakePositive( lengthU[0] - lengthU[1] ) < PIQ_PLANE_EPSILON ) - { - return QuadWithParallelEdges( v1, axisUNorm[0], lengthU[0], axisVNorm[0], lengthV[0], point, uv ); - } - } - - // - // since we are solving for s in our equations below we need to ensure that - // the v axes are non-parallel - // - bool bFlipped = false; - if( axisVNorm[0].Dot( axisVNorm[1] ) > PIQ_DOT_EPSILON ) - { - Vector tmp[2]; - tmp[0] = axisV[0]; - tmp[1] = axisV[1]; - axisV[0] = axisU[0]; - axisV[1] = axisU[1]; - axisU[0] = tmp[0]; - axisU[1] = tmp[1]; - bFlipped = true; - } - - // - // get the "projection" axes - // - Vector2D projAxes; - Vector vNormal = axisU[0].Cross( axisV[0] ); - GetNonMajorAxes( vNormal, projAxes ); - - // - // NOTE: axisU[0][projAxes[0]] < axisU[0][projAxes[1]], - // this is done to decrease error when dividing later - // - if( FloatMakePositive( axisU[0][(int)projAxes[0]] ) < FloatMakePositive( axisU[0][(int)projAxes[1]] ) ) - { - int tmp = (int)projAxes[0]; - projAxes[0] = projAxes[1]; - projAxes[1] = tmp; - } - - // Here's how we got these equations: - // - // Given the points and u,v line segments above... - // - // Then: - // - // (1.0) PT = P0 + U0 * s + V * t - // - // where - // - // (1.1) V = V0 + s * (V1 - V0) - // (1.2) U = U0 + t * (U1 - U0) - // - // Therefore (from 1.1 + 1.0): - // PT - P0 = U0 * s + (V0 + s * (V1-V0)) * t - // Group s's: - // PT - P0 - t * V0 = s * (U0 + t * (V1-V0)) - // Two equations and two unknowns in x and y get you the following quadratic: - // - // solve the quadratic - // - double s = 0.0, t = 0.0; - double A, negB, C; - - A = ( axisU[0][(int)projAxes[1]] * axisV[0][(int)projAxes[0]] ) - - ( axisU[0][(int)projAxes[0]] * axisV[0][(int)projAxes[1]] ) - - ( axisU[1][(int)projAxes[1]] * axisV[0][(int)projAxes[0]] ) + - ( axisU[1][(int)projAxes[0]] * axisV[0][(int)projAxes[1]] ); - C = ( v1[(int)projAxes[1]] * axisU[0][(int)projAxes[0]] ) - - ( point[(int)projAxes[1]] * axisU[0][(int)projAxes[0]] ) - - ( v1[(int)projAxes[0]] * axisU[0][(int)projAxes[1]] ) + - ( point[(int)projAxes[0]] * axisU[0][(int)projAxes[1]] ); - negB = C - - ( v1[(int)projAxes[1]] * axisU[1][(int)projAxes[0]] ) + - ( point[(int)projAxes[1]] * axisU[1][(int)projAxes[0]] ) + - ( v1[(int)projAxes[0]] * axisU[1][(int)projAxes[1]] ) - - ( point[(int)projAxes[0]] * axisU[1][(int)projAxes[1]] ) + - ( axisU[0][(int)projAxes[1]] * axisV[0][(int)projAxes[0]] ) - - ( axisU[0][(int)projAxes[0]] * axisV[0][(int)projAxes[1]] ); - - if( ( A > -PIQ_PLANE_EPSILON ) && ( A < PIQ_PLANE_EPSILON ) ) - { - // shouldn't be here -- this should have been take care of in the "early out" -// Assert( 0 ); - - Vector vecUAvg, vecVAvg; - vecUAvg = ( axisUNorm[0] + axisUNorm[1] ) * 0.5f; - vecVAvg = ( axisVNorm[0] + axisVNorm[1] ) * 0.5f; - - float fLengthUAvg = ( lengthU[0] + lengthU[1] ) * 0.5f; - float fLengthVAvg = ( lengthV[0] + lengthV[1] ) * 0.5f; - - return QuadWithParallelEdges( v1, vecUAvg, fLengthUAvg, vecVAvg, fLengthVAvg, point, uv ); - -#if 0 - // legacy code -- kept here for completeness! - - // not a quadratic -- solve linearly - t = C / negB; - - // See (1.2) above - float ui = axisU[0][projAxes[0]] + t * ( axisU[1][projAxes[0]] - axisU[0][projAxes[0]] ); - if( FloatMakePositive( ui ) >= 1e-5 ) - { - // See (1.0) above - s = ( point[projAxes[0]] - v1[projAxes[0]] - axisV[0][projAxes[0]] * t ) / ui; - } -#endif - } - else - { - // (-b +/- sqrt( b^2 - 4ac )) / 2a - double discriminant = (negB*negB) - (4.0f * A * C); - if( discriminant < 0.0f ) - { - uv[0] = -99999.0f; - uv[1] = -99999.0f; - return BARY_QUADRATIC_NEGATIVE_DISCRIMINANT; - } - - double quad = sqrt( discriminant ); - double QPlus = ( negB + quad ) / ( 2.0f * A ); - double QMinus = ( negB - quad ) / ( 2.0f * A ); - - ResolveQuadratic( QPlus, QMinus, axisU[0], axisU[1], axisV[0], axisV[1], v1, point, (int)projAxes[0], s, t ); - } - - if( !bFlipped ) - { - uv[0] = ( float )s; - uv[1] = ( float )t; - } - else - { - uv[0] = ( float )t; - uv[1] = ( float )s; - } - - // inside of the quad?? - if( ( uv[0] < 0.0f ) || ( uv[0] > 1.0f ) || ( uv[1] < 0.0f ) || ( uv[1] > 1.0f ) ) - return BARY_QUADRATIC_FALSE; - - return BARY_QUADRATIC_TRUE; - -#undef PIQ_TEXTURE_EPSILON -#undef PIQ_PLANE_EPSILON -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void PointInQuadFromBarycentric( const Vector &v1, const Vector &v2, const Vector &v3, const Vector &v4, - const Vector2D &uv, Vector &point ) -{ - // - // Think of a quad with points v1, v2, v3, v4 and u, v line segments - // find the ray from v0 edge to v1 edge at v - // - Vector vPts[2]; - VectorLerp( v1, v4, uv[1], vPts[0] ); - VectorLerp( v2, v3, uv[1], vPts[1] ); - VectorLerp( vPts[0], vPts[1], uv[0], point ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void TexCoordInQuadFromBarycentric( const Vector2D &v1, const Vector2D &v2, const Vector2D &v3, const Vector2D &v4, - const Vector2D &uv, Vector2D &texCoord ) -{ - // - // Think of a quad with points v1, v2, v3, v4 and u, v line segments - // find the ray from v0 edge to v1 edge at v - // - Vector2D vCoords[2]; - Vector2DLerp( v1, v4, uv[1], vCoords[0] ); - Vector2DLerp( v2, v3, uv[1], vCoords[1] ); - Vector2DLerp( vCoords[0], vCoords[1], uv[0], texCoord ); -} - - -//----------------------------------------------------------------------------- -// Compute point from barycentric specification -// Edge u goes from v0 to v1, edge v goes from v0 to v2 -//----------------------------------------------------------------------------- -void ComputePointFromBarycentric( const Vector& v0, const Vector& v1, const Vector& v2, - float u, float v, Vector& pt ) -{ - Vector edgeU, edgeV; - VectorSubtract( v1, v0, edgeU ); - VectorSubtract( v2, v0, edgeV ); - VectorMA( v0, u, edgeU, pt ); - VectorMA( pt, v, edgeV, pt ); -} - -void ComputePointFromBarycentric( const Vector2D& v0, const Vector2D& v1, const Vector2D& v2, - float u, float v, Vector2D& pt ) -{ - Vector2D edgeU, edgeV; - Vector2DSubtract( v1, v0, edgeU ); - Vector2DSubtract( v2, v0, edgeV ); - Vector2DMA( v0, u, edgeU, pt ); - Vector2DMA( pt, v, edgeV, pt ); -} - - -//----------------------------------------------------------------------------- -// Compute a matrix that has the correct orientation but which has an origin at -// the center of the bounds -//----------------------------------------------------------------------------- -static void ComputeCenterMatrix( const Vector& origin, const QAngle& angles, - const Vector& mins, const Vector& maxs, matrix3x4_t& matrix ) -{ - Vector centroid; - VectorAdd( mins, maxs, centroid ); - centroid *= 0.5f; - AngleMatrix( angles, matrix ); - - Vector worldCentroid; - VectorRotate( centroid, matrix, worldCentroid ); - worldCentroid += origin; - MatrixSetColumn( worldCentroid, 3, matrix ); -} - -static void ComputeCenterIMatrix( const Vector& origin, const QAngle& angles, - const Vector& mins, const Vector& maxs, matrix3x4_t& matrix ) -{ - Vector centroid; - VectorAdd( mins, maxs, centroid ); - centroid *= -0.5f; - AngleIMatrix( angles, matrix ); - - // For the translational component here, note that the origin in world space - // is T = R * C + O, (R = rotation matrix, C = centroid in local space, O = origin in world space) - // The IMatrix translation = - transpose(R) * T = -C - transpose(R) * 0 - Vector localOrigin; - VectorRotate( origin, matrix, localOrigin ); - centroid -= localOrigin; - MatrixSetColumn( centroid, 3, matrix ); -} - - -//----------------------------------------------------------------------------- -// Compute a matrix which is the absolute value of another -//----------------------------------------------------------------------------- -static inline void ComputeAbsMatrix( const matrix3x4_t& in, matrix3x4_t& out ) -{ - FloatBits(out[0][0]) = FloatAbsBits(in[0][0]); - FloatBits(out[0][1]) = FloatAbsBits(in[0][1]); - FloatBits(out[0][2]) = FloatAbsBits(in[0][2]); - FloatBits(out[1][0]) = FloatAbsBits(in[1][0]); - FloatBits(out[1][1]) = FloatAbsBits(in[1][1]); - FloatBits(out[1][2]) = FloatAbsBits(in[1][2]); - FloatBits(out[2][0]) = FloatAbsBits(in[2][0]); - FloatBits(out[2][1]) = FloatAbsBits(in[2][1]); - FloatBits(out[2][2]) = FloatAbsBits(in[2][2]); -} - - -//----------------------------------------------------------------------------- -// Compute a separating plane between two boxes (expensive!) -// Returns false if no separating plane exists -//----------------------------------------------------------------------------- -static bool ComputeSeparatingPlane( const matrix3x4_t &worldToBox1, const matrix3x4_t &box2ToWorld, - const Vector& box1Size, const Vector& box2Size, float tolerance, cplane_t* pPlane ) -{ - // The various separating planes can be either - // 1) A plane parallel to one of the box face planes - // 2) A plane parallel to the cross-product of an edge from each box - - // First, compute the basis of second box in the space of the first box - // NOTE: These basis place the origin at the centroid of each box! - matrix3x4_t box2ToBox1; - ConcatTransforms( worldToBox1, box2ToWorld, box2ToBox1 ); - - // We're going to be using the origin of box2 in the space of box1 alot, - // lets extract it from the matrix.... - Vector box2Origin; - MatrixGetColumn( box2ToBox1, 3, box2Origin ); - - // Next get the absolute values of these entries and store in absbox2ToBox1. - matrix3x4_t absBox2ToBox1; - ComputeAbsMatrix( box2ToBox1, absBox2ToBox1 ); - - // There are 15 tests to make. The first 3 involve trying planes parallel - // to the faces of the first box. - - // NOTE: The algorithm here involves finding the projections of the two boxes - // onto a particular line. If the projections on the line do not overlap, - // that means that there's a plane perpendicular to the line which separates - // the two boxes; and we've therefore found a separating plane. - - // The way we check for overlay is we find the projections of the two boxes - // onto the line, and add them up. We compare the sum with the projection - // of the relative center of box2 onto the same line. - - Vector tmp; - float boxProjectionSum; - float originProjection; - - // NOTE: For these guys, we're taking advantage of the fact that the ith - // row of the box2ToBox1 is the direction of the box1 (x,y,z)-axis - // transformed into the space of box2. - - // First side of box 1 - boxProjectionSum = box1Size.x + MatrixRowDotProduct( absBox2ToBox1, 0, box2Size ); - originProjection = FloatMakePositive( box2Origin.x ) + tolerance; - if ( FloatBits(originProjection) > FloatBits(boxProjectionSum) ) - { - VectorCopy( worldToBox1[0], pPlane->normal.Base() ); - return true; - } - - // Second side of box 1 - boxProjectionSum = box1Size.y + MatrixRowDotProduct( absBox2ToBox1, 1, box2Size ); - originProjection = FloatMakePositive( box2Origin.y ) + tolerance; - if ( FloatBits(originProjection) > FloatBits(boxProjectionSum) ) - { - VectorCopy( worldToBox1[1], pPlane->normal.Base() ); - return true; - } - - // Third side of box 1 - boxProjectionSum = box1Size.z + MatrixRowDotProduct( absBox2ToBox1, 2, box2Size ); - originProjection = FloatMakePositive( box2Origin.z ) + tolerance; - if ( FloatBits(originProjection) > FloatBits(boxProjectionSum) ) - { - VectorCopy( worldToBox1[2], pPlane->normal.Base() ); - return true; - } - - // The next three involve checking splitting planes parallel to the - // faces of the second box. - - // NOTE: For these guys, we're taking advantage of the fact that the 0th - // column of the box2ToBox1 is the direction of the box2 x-axis - // transformed into the space of box1. - // Here, we're determining the distance of box2's center from box1's center - // by projecting it onto a line parallel to box2's axis - - // First side of box 2 - boxProjectionSum = box2Size.x + MatrixColumnDotProduct( absBox2ToBox1, 0, box1Size ); - originProjection = FloatMakePositive( MatrixColumnDotProduct( box2ToBox1, 0, box2Origin ) ) + tolerance; - if ( FloatBits(originProjection) > FloatBits(boxProjectionSum) ) - { - MatrixGetColumn( box2ToWorld, 0, pPlane->normal ); - return true; - } - - // Second side of box 2 - boxProjectionSum = box2Size.y + MatrixColumnDotProduct( absBox2ToBox1, 1, box1Size ); - originProjection = FloatMakePositive( MatrixColumnDotProduct( box2ToBox1, 1, box2Origin ) ) + tolerance; - if ( FloatBits(originProjection) > FloatBits(boxProjectionSum) ) - { - MatrixGetColumn( box2ToWorld, 1, pPlane->normal ); - return true; - } - - // Third side of box 2 - boxProjectionSum = box2Size.z + MatrixColumnDotProduct( absBox2ToBox1, 2, box1Size ); - originProjection = FloatMakePositive( MatrixColumnDotProduct( box2ToBox1, 2, box2Origin ) ) + tolerance; - if ( FloatBits(originProjection) > FloatBits(boxProjectionSum) ) - { - MatrixGetColumn( box2ToWorld, 2, pPlane->normal ); - return true; - } - - // Next check the splitting planes which are orthogonal to the pairs - // of edges, one from box1 and one from box2. As only direction matters, - // there are 9 pairs since each box has 3 distinct edge directions. - - // Here, we take advantage of the fact that the edges from box 1 are all - // axis aligned; therefore the crossproducts are simplified. Let's walk through - // the example of b1e1 x b2e1: - - // In this example, the line to check is perpendicular to b1e1 + b2e2 - // we can compute this line by taking the cross-product: - // - // [ i j k ] - // [ 1 0 0 ] = - ez j + ey k = l1 - // [ ex ey ez ] - - // Where ex, ey, ez is the components of box2's x axis in the space of box 1, - // which is == to the 0th column of of box2toBox1 - - // The projection of box1 onto this line = the absolute dot product of the box size - // against the line, which = - // AbsDot( box1Size, l1 ) = abs( -ez * box1.y ) + abs( ey * box1.z ) - - // To compute the projection of box2 onto this line, we'll do it in the space of box 2 - // - // [ i j k ] - // [ fx fy fz ] = fz j - fy k = l2 - // [ 1 0 0 ] - - // Where fx, fy, fz is the components of box1's x axis in the space of box 2, - // which is == to the 0th row of of box2toBox1 - - // The projection of box2 onto this line = the absolute dot product of the box size - // against the line, which = - // AbsDot( box2Size, l2 ) = abs( fz * box2.y ) + abs ( fy * box2.z ) - - // The projection of the relative origin position on this line is done in the - // space of box 1: - // - // originProjection = DotProduct( <-ez j + ey k>, box2Origin ) = - // -ez * box2Origin.y + ey * box2Origin.z - - // NOTE: These checks can be bogus if both edges are parallel. The if - // checks at the beginning of each block are designed to catch that case - - // b1e1 x b2e1 - if ( absBox2ToBox1[0][0] < 1.0f - 1e-3f ) - { - boxProjectionSum = - box1Size.y * absBox2ToBox1[2][0] + box1Size.z * absBox2ToBox1[1][0] + - box2Size.y * absBox2ToBox1[0][2] + box2Size.z * absBox2ToBox1[0][1]; - originProjection = FloatMakePositive( -box2Origin.y * box2ToBox1[2][0] + box2Origin.z * box2ToBox1[1][0] ) + tolerance; - if ( FloatBits(originProjection) > FloatBits(boxProjectionSum) ) - { - MatrixGetColumn( box2ToWorld, 0, tmp ); - CrossProduct( worldToBox1[0], tmp.Base(), pPlane->normal.Base() ); - return true; - } - } - - // b1e1 x b2e2 - if ( absBox2ToBox1[0][1] < 1.0f - 1e-3f ) - { - boxProjectionSum = - box1Size.y * absBox2ToBox1[2][1] + box1Size.z * absBox2ToBox1[1][1] + - box2Size.x * absBox2ToBox1[0][2] + box2Size.z * absBox2ToBox1[0][0]; - originProjection = FloatMakePositive( -box2Origin.y * box2ToBox1[2][1] + box2Origin.z * box2ToBox1[1][1] ) + tolerance; - if ( FloatBits(originProjection) > FloatBits(boxProjectionSum) ) - { - MatrixGetColumn( box2ToWorld, 1, tmp ); - CrossProduct( worldToBox1[0], tmp.Base(), pPlane->normal.Base() ); - return true; - } - } - - // b1e1 x b2e3 - if ( absBox2ToBox1[0][2] < 1.0f - 1e-3f ) - { - boxProjectionSum = - box1Size.y * absBox2ToBox1[2][2] + box1Size.z * absBox2ToBox1[1][2] + - box2Size.x * absBox2ToBox1[0][1] + box2Size.y * absBox2ToBox1[0][0]; - originProjection = FloatMakePositive( -box2Origin.y * box2ToBox1[2][2] + box2Origin.z * box2ToBox1[1][2] ) + tolerance; - if ( FloatBits(originProjection) > FloatBits(boxProjectionSum) ) - { - MatrixGetColumn( box2ToWorld, 2, tmp ); - CrossProduct( worldToBox1[0], tmp.Base(), pPlane->normal.Base() ); - return true; - } - } - - // b1e2 x b2e1 - if ( absBox2ToBox1[1][0] < 1.0f - 1e-3f ) - { - boxProjectionSum = - box1Size.x * absBox2ToBox1[2][0] + box1Size.z * absBox2ToBox1[0][0] + - box2Size.y * absBox2ToBox1[1][2] + box2Size.z * absBox2ToBox1[1][1]; - originProjection = FloatMakePositive( box2Origin.x * box2ToBox1[2][0] - box2Origin.z * box2ToBox1[0][0] ) + tolerance; - if ( FloatBits(originProjection) > FloatBits(boxProjectionSum) ) - { - MatrixGetColumn( box2ToWorld, 0, tmp ); - CrossProduct( worldToBox1[1], tmp.Base(), pPlane->normal.Base() ); - return true; - } - } - - // b1e2 x b2e2 - if ( absBox2ToBox1[1][1] < 1.0f - 1e-3f ) - { - boxProjectionSum = - box1Size.x * absBox2ToBox1[2][1] + box1Size.z * absBox2ToBox1[0][1] + - box2Size.x * absBox2ToBox1[1][2] + box2Size.z * absBox2ToBox1[1][0]; - originProjection = FloatMakePositive( box2Origin.x * box2ToBox1[2][1] - box2Origin.z * box2ToBox1[0][1] ) + tolerance; - if ( FloatBits(originProjection) > FloatBits(boxProjectionSum) ) - { - MatrixGetColumn( box2ToWorld, 1, tmp ); - CrossProduct( worldToBox1[1], tmp.Base(), pPlane->normal.Base() ); - return true; - } - } - - // b1e2 x b2e3 - if ( absBox2ToBox1[1][2] < 1.0f - 1e-3f ) - { - boxProjectionSum = - box1Size.x * absBox2ToBox1[2][2] + box1Size.z * absBox2ToBox1[0][2] + - box2Size.x * absBox2ToBox1[1][1] + box2Size.y * absBox2ToBox1[1][0]; - originProjection = FloatMakePositive( box2Origin.x * box2ToBox1[2][2] - box2Origin.z * box2ToBox1[0][2] ) + tolerance; - if ( FloatBits(originProjection) > FloatBits(boxProjectionSum) ) - { - MatrixGetColumn( box2ToWorld, 2, tmp ); - CrossProduct( worldToBox1[1], tmp.Base(), pPlane->normal.Base() ); - return true; - } - } - - // b1e3 x b2e1 - if ( absBox2ToBox1[2][0] < 1.0f - 1e-3f ) - { - boxProjectionSum = - box1Size.x * absBox2ToBox1[1][0] + box1Size.y * absBox2ToBox1[0][0] + - box2Size.y * absBox2ToBox1[2][2] + box2Size.z * absBox2ToBox1[2][1]; - originProjection = FloatMakePositive( -box2Origin.x * box2ToBox1[1][0] + box2Origin.y * box2ToBox1[0][0] ) + tolerance; - if ( FloatBits(originProjection) > FloatBits(boxProjectionSum) ) - { - MatrixGetColumn( box2ToWorld, 0, tmp ); - CrossProduct( worldToBox1[2], tmp.Base(), pPlane->normal.Base() ); - return true; - } - } - - // b1e3 x b2e2 - if ( absBox2ToBox1[2][1] < 1.0f - 1e-3f ) - { - boxProjectionSum = - box1Size.x * absBox2ToBox1[1][1] + box1Size.y * absBox2ToBox1[0][1] + - box2Size.x * absBox2ToBox1[2][2] + box2Size.z * absBox2ToBox1[2][0]; - originProjection = FloatMakePositive( -box2Origin.x * box2ToBox1[1][1] + box2Origin.y * box2ToBox1[0][1] ) + tolerance; - if ( FloatBits(originProjection) > FloatBits(boxProjectionSum) ) - { - MatrixGetColumn( box2ToWorld, 1, tmp ); - CrossProduct( worldToBox1[2], tmp.Base(), pPlane->normal.Base() ); - return true; - } - } - - // b1e3 x b2e3 - if ( absBox2ToBox1[2][2] < 1.0f - 1e-3f ) - { - boxProjectionSum = - box1Size.x * absBox2ToBox1[1][2] + box1Size.y * absBox2ToBox1[0][2] + - box2Size.x * absBox2ToBox1[2][1] + box2Size.y * absBox2ToBox1[2][0]; - originProjection = FloatMakePositive( -box2Origin.x * box2ToBox1[1][2] + box2Origin.y * box2ToBox1[0][2] ) + tolerance; - if ( FloatBits(originProjection) > FloatBits(boxProjectionSum) ) - { - MatrixGetColumn( box2ToWorld, 2, tmp ); - CrossProduct( worldToBox1[2], tmp.Base(), pPlane->normal.Base() ); - return true; - } - } - return false; -} - - -//----------------------------------------------------------------------------- -// Compute a separating plane between two boxes (expensive!) -// Returns false if no separating plane exists -//----------------------------------------------------------------------------- -bool ComputeSeparatingPlane( const Vector& org1, const QAngle& angles1, const Vector& min1, const Vector& max1, - const Vector& org2, const QAngle& angles2, const Vector& min2, const Vector& max2, - float tolerance, cplane_t* pPlane ) -{ - matrix3x4_t worldToBox1, box2ToWorld; - ComputeCenterIMatrix( org1, angles1, min1, max1, worldToBox1 ); - ComputeCenterMatrix( org2, angles2, min2, max2, box2ToWorld ); - - // Then compute the size of the two boxes - Vector box1Size, box2Size; - VectorSubtract( max1, min1, box1Size ); - VectorSubtract( max2, min2, box2Size ); - box1Size *= 0.5f; - box2Size *= 0.5f; - - return ComputeSeparatingPlane( worldToBox1, box2ToWorld, box1Size, box2Size, tolerance, pPlane ); -} - - -//----------------------------------------------------------------------------- -// Swept OBB test -//----------------------------------------------------------------------------- -bool IsRayIntersectingOBB( const Ray_t &ray, const Vector& org, const QAngle& angles, - const Vector& mins, const Vector& maxs ) -{ - if ( angles == vec3_angle ) - { - Vector vecWorldMins, vecWorldMaxs; - VectorAdd( org, mins, vecWorldMins ); - VectorAdd( org, maxs, vecWorldMaxs ); - return IsBoxIntersectingRay( vecWorldMins, vecWorldMaxs, ray ); - } - - if ( ray.m_IsRay ) - { - matrix3x4_t worldToBox; - AngleIMatrix( angles, org, worldToBox ); - - Ray_t rotatedRay; - VectorTransform( ray.m_Start, worldToBox, rotatedRay.m_Start ); - VectorRotate( ray.m_Delta, worldToBox, rotatedRay.m_Delta ); - rotatedRay.m_StartOffset = vec3_origin; - rotatedRay.m_Extents = vec3_origin; - rotatedRay.m_IsRay = ray.m_IsRay; - rotatedRay.m_IsSwept = ray.m_IsSwept; - - return IsBoxIntersectingRay( mins, maxs, rotatedRay ); - } - - if ( !ray.m_IsSwept ) - { - cplane_t plane; - return ComputeSeparatingPlane( ray.m_Start, vec3_angle, -ray.m_Extents, ray.m_Extents, - org, angles, mins, maxs, 0.0f, &plane ) == false; - } - - // NOTE: See the comments in ComputeSeparatingPlane to understand this math - - // First, compute the basis of box in the space of the ray - // NOTE: These basis place the origin at the centroid of each box! - matrix3x4_t worldToBox1, box2ToWorld; - ComputeCenterMatrix( org, angles, mins, maxs, box2ToWorld ); - - // Find the center + extents of an AABB surrounding the ray - Vector vecRayCenter; - VectorMA( ray.m_Start, 0.5, ray.m_Delta, vecRayCenter ); - vecRayCenter *= -1.0f; - SetIdentityMatrix( worldToBox1 ); - MatrixSetColumn( vecRayCenter, 3, worldToBox1 ); - - Vector box1Size; - box1Size.x = ray.m_Extents.x + FloatMakePositive( ray.m_Delta.x ) * 0.5f; - box1Size.y = ray.m_Extents.y + FloatMakePositive( ray.m_Delta.y ) * 0.5f; - box1Size.z = ray.m_Extents.z + FloatMakePositive( ray.m_Delta.z ) * 0.5f; - - // Then compute the size of the box - Vector box2Size; - VectorSubtract( maxs, mins, box2Size ); - box2Size *= 0.5f; - - // Do an OBB test of the box with the AABB surrounding the ray - cplane_t plane; - if ( ComputeSeparatingPlane( worldToBox1, box2ToWorld, box1Size, box2Size, 0.0f, &plane ) ) - return false; - - // Now deal with the planes which are the cross products of the ray sweep direction vs box edges - Vector vecRayDirection = ray.m_Delta; - VectorNormalize( vecRayDirection ); - - // Need a vector between ray center vs box center measured in the space of the ray (world) - Vector vecCenterDelta; - vecCenterDelta.x = box2ToWorld[0][3] - ray.m_Start.x; - vecCenterDelta.y = box2ToWorld[1][3] - ray.m_Start.y; - vecCenterDelta.z = box2ToWorld[2][3] - ray.m_Start.z; - - // Rotate the ray direction into the space of the OBB - Vector vecAbsRayDirBox2; - VectorIRotate( vecRayDirection, box2ToWorld, vecAbsRayDirBox2 ); - - // Make abs versions of the ray in world space + ray in box2 space - VectorAbs( vecAbsRayDirBox2, vecAbsRayDirBox2 ); - - // Now do the work for the planes which are perpendicular to the edges of the AABB - // and the sweep direction edges... - - // In this example, the line to check is perpendicular to box edge x + ray delta - // we can compute this line by taking the cross-product: - // - // [ i j k ] - // [ 1 0 0 ] = - dz j + dy k = l1 - // [ dx dy dz ] - - // Where dx, dy, dz is the ray delta (normalized) - - // The projection of the box onto this line = the absolute dot product of the box size - // against the line, which = - // AbsDot( vecBoxHalfDiagonal, l1 ) = abs( -dz * vecBoxHalfDiagonal.y ) + abs( dy * vecBoxHalfDiagonal.z ) - - // Because the plane contains the sweep direction, the sweep will produce - // no extra projection onto the line normal to the plane. - // Therefore all we need to do is project the ray extents onto this line also: - // AbsDot( ray.m_Extents, l1 ) = abs( -dz * ray.m_Extents.y ) + abs( dy * ray.m_Extents.z ) - - Vector vecPlaneNormal; - - // box x x ray delta - CrossProduct( vecRayDirection, Vector( box2ToWorld[0][0], box2ToWorld[1][0], box2ToWorld[2][0] ), vecPlaneNormal ); - float flCenterDeltaProjection = FloatMakePositive( DotProduct( vecPlaneNormal, vecCenterDelta ) ); - float flBoxProjectionSum = - vecAbsRayDirBox2.z * box2Size.y + vecAbsRayDirBox2.y * box2Size.z + - DotProductAbs( vecPlaneNormal, ray.m_Extents ); - if ( FloatBits(flCenterDeltaProjection) > FloatBits(flBoxProjectionSum) ) - return false; - - // box y x ray delta - CrossProduct( vecRayDirection, Vector( box2ToWorld[0][1], box2ToWorld[1][1], box2ToWorld[2][1] ), vecPlaneNormal ); - flCenterDeltaProjection = FloatMakePositive( DotProduct( vecPlaneNormal, vecCenterDelta ) ); - flBoxProjectionSum = - vecAbsRayDirBox2.z * box2Size.x + vecAbsRayDirBox2.x * box2Size.z + - DotProductAbs( vecPlaneNormal, ray.m_Extents ); - if ( FloatBits(flCenterDeltaProjection) > FloatBits(flBoxProjectionSum) ) - return false; - - // box z x ray delta - CrossProduct( vecRayDirection, Vector( box2ToWorld[0][2], box2ToWorld[1][2], box2ToWorld[2][2] ), vecPlaneNormal ); - flCenterDeltaProjection = FloatMakePositive( DotProduct( vecPlaneNormal, vecCenterDelta ) ); - flBoxProjectionSum = - vecAbsRayDirBox2.y * box2Size.x + vecAbsRayDirBox2.x * box2Size.y + - DotProductAbs( vecPlaneNormal, ray.m_Extents ); - if ( FloatBits(flCenterDeltaProjection) > FloatBits(flBoxProjectionSum) ) - return false; - - return true; -} - -//-------------------------------------------------------------------------- -// Purpose: -// -// NOTE: -// triangle points are given in clockwise order (aabb-triangle test) -// -// 1 edge0 = 1 - 0 -// | \ edge1 = 2 - 1 -// | \ edge2 = 0 - 2 -// | \ . -// | \ . -// 0-----2 . -// -//-------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// Purpose: find the minima and maxima of the 3 given values -//----------------------------------------------------------------------------- -inline void FindMinMax( float v1, float v2, float v3, float &min, float &max ) -{ - min = max = v1; - if ( v2 < min ) { min = v2; } - if ( v2 > max ) { max = v2; } - if ( v3 < min ) { min = v3; } - if ( v3 > max ) { max = v3; } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline bool AxisTestEdgeCrossX2( float flEdgeZ, float flEdgeY, float flAbsEdgeZ, float flAbsEdgeY, - const Vector &p1, const Vector &p3, const Vector &vecExtents, - float flTolerance ) -{ - // Cross Product( axialX(1,0,0) x edge ): x = 0.0f, y = edge.z, z = -edge.y - // Triangle Point Distances: dist(x) = normal.y * pt(x).y + normal.z * pt(x).z - float flDist1 = flEdgeZ * p1.y - flEdgeY * p1.z; - float flDist3 = flEdgeZ * p3.y - flEdgeY * p3.z; - - // Extents are symmetric: dist = abs( normal.y ) * extents.y + abs( normal.z ) * extents.z - float flDistBox = flAbsEdgeZ * vecExtents.y + flAbsEdgeY * vecExtents.z; - - // Either dist1, dist3 is the closest point to the box, determine which and test of overlap with box(AABB). - if ( flDist1 < flDist3 ) - { - if ( ( flDist1 > ( flDistBox + flTolerance ) ) || ( flDist3 < -( flDistBox + flTolerance ) ) ) - return false; - } - else - { - if ( ( flDist3 > ( flDistBox + flTolerance ) ) || ( flDist1 < -( flDistBox + flTolerance ) ) ) - return false; - } - - return true; -} - -//-------------------------------------------------------------------------- -// Purpose: -//-------------------------------------------------------------------------- -inline bool AxisTestEdgeCrossX3( float flEdgeZ, float flEdgeY, float flAbsEdgeZ, float flAbsEdgeY, - const Vector &p1, const Vector &p2, const Vector &vecExtents, - float flTolerance ) -{ - // Cross Product( axialX(1,0,0) x edge ): x = 0.0f, y = edge.z, z = -edge.y - // Triangle Point Distances: dist(x) = normal.y * pt(x).y + normal.z * pt(x).z - float flDist1 = flEdgeZ * p1.y - flEdgeY * p1.z; - float flDist2 = flEdgeZ * p2.y - flEdgeY * p2.z; - - // Extents are symmetric: dist = abs( normal.y ) * extents.y + abs( normal.z ) * extents.z - float flDistBox = flAbsEdgeZ * vecExtents.y + flAbsEdgeY * vecExtents.z; - - // Either dist1, dist2 is the closest point to the box, determine which and test of overlap with box(AABB). - if ( flDist1 < flDist2 ) - { - if ( ( flDist1 > ( flDistBox + flTolerance ) ) || ( flDist2 < -( flDistBox + flTolerance ) ) ) - return false; - } - else - { - if ( ( flDist2 > ( flDistBox + flTolerance ) ) || ( flDist1 < -( flDistBox + flTolerance ) ) ) - return false; - } - - return true; -} - -//-------------------------------------------------------------------------- -//-------------------------------------------------------------------------- -inline bool AxisTestEdgeCrossY2( float flEdgeZ, float flEdgeX, float flAbsEdgeZ, float flAbsEdgeX, - const Vector &p1, const Vector &p3, const Vector &vecExtents, - float flTolerance ) -{ - // Cross Product( axialY(0,1,0) x edge ): x = -edge.z, y = 0.0f, z = edge.x - // Triangle Point Distances: dist(x) = normal.x * pt(x).x + normal.z * pt(x).z - float flDist1 = -flEdgeZ * p1.x + flEdgeX * p1.z; - float flDist3 = -flEdgeZ * p3.x + flEdgeX * p3.z; - - // Extents are symmetric: dist = abs( normal.x ) * extents.x + abs( normal.z ) * extents.z - float flDistBox = flAbsEdgeZ * vecExtents.x + flAbsEdgeX * vecExtents.z; - - // Either dist1, dist3 is the closest point to the box, determine which and test of overlap with box(AABB). - if ( flDist1 < flDist3 ) - { - if ( ( flDist1 > ( flDistBox + flTolerance ) ) || ( flDist3 < -( flDistBox + flTolerance ) ) ) - return false; - } - else - { - if ( ( flDist3 > ( flDistBox + flTolerance ) ) || ( flDist1 < -( flDistBox + flTolerance ) ) ) - return false; - } - - return true; -} - -//-------------------------------------------------------------------------- -//-------------------------------------------------------------------------- -inline bool AxisTestEdgeCrossY3( float flEdgeZ, float flEdgeX, float flAbsEdgeZ, float flAbsEdgeX, - const Vector &p1, const Vector &p2, const Vector &vecExtents, - float flTolerance ) -{ - // Cross Product( axialY(0,1,0) x edge ): x = -edge.z, y = 0.0f, z = edge.x - // Triangle Point Distances: dist(x) = normal.x * pt(x).x + normal.z * pt(x).z - float flDist1 = -flEdgeZ * p1.x + flEdgeX * p1.z; - float flDist2 = -flEdgeZ * p2.x + flEdgeX * p2.z; - - // Extents are symmetric: dist = abs( normal.x ) * extents.x + abs( normal.z ) * extents.z - float flDistBox = flAbsEdgeZ * vecExtents.x + flAbsEdgeX * vecExtents.z; - - // Either dist1, dist2 is the closest point to the box, determine which and test of overlap with box(AABB). - if ( flDist1 < flDist2 ) - { - if ( ( flDist1 > ( flDistBox + flTolerance ) ) || ( flDist2 < -( flDistBox + flTolerance ) ) ) - return false; - } - else - { - if ( ( flDist2 > ( flDistBox + flTolerance ) ) || ( flDist1 < -( flDistBox + flTolerance ) ) ) - return false; - } - - return true; -} - -//-------------------------------------------------------------------------- -//-------------------------------------------------------------------------- -inline bool AxisTestEdgeCrossZ1( float flEdgeY, float flEdgeX, float flAbsEdgeY, float flAbsEdgeX, - const Vector &p2, const Vector &p3, const Vector &vecExtents, - float flTolerance ) -{ - // Cross Product( axialZ(0,0,1) x edge ): x = edge.y, y = -edge.x, z = 0.0f - // Triangle Point Distances: dist(x) = normal.x * pt(x).x + normal.y * pt(x).y - float flDist2 = flEdgeY * p2.x - flEdgeX * p2.y; - float flDist3 = flEdgeY * p3.x - flEdgeX * p3.y; - - // Extents are symmetric: dist = abs( normal.x ) * extents.x + abs( normal.y ) * extents.y - float flDistBox = flAbsEdgeY * vecExtents.x + flAbsEdgeX * vecExtents.y; - - // Either dist2, dist3 is the closest point to the box, determine which and test of overlap with box(AABB). - if ( flDist3 < flDist2 ) - { - if ( ( flDist3 > ( flDistBox + flTolerance ) ) || ( flDist2 < -( flDistBox + flTolerance ) ) ) - return false; - } - else - { - if ( ( flDist2 > ( flDistBox + flTolerance ) ) || ( flDist3 < -( flDistBox + flTolerance ) ) ) - return false; - } - - return true; -} - -//-------------------------------------------------------------------------- -//-------------------------------------------------------------------------- -inline bool AxisTestEdgeCrossZ2( float flEdgeY, float flEdgeX, float flAbsEdgeY, float flAbsEdgeX, - const Vector &p1, const Vector &p3, const Vector &vecExtents, - float flTolerance ) -{ - // Cross Product( axialZ(0,0,1) x edge ): x = edge.y, y = -edge.x, z = 0.0f - // Triangle Point Distances: dist(x) = normal.x * pt(x).x + normal.y * pt(x).y - float flDist1 = flEdgeY * p1.x - flEdgeX * p1.y; - float flDist3 = flEdgeY * p3.x - flEdgeX * p3.y; - - // Extents are symmetric: dist = abs( normal.x ) * extents.x + abs( normal.y ) * extents.y - float flDistBox = flAbsEdgeY * vecExtents.x + flAbsEdgeX * vecExtents.y; - - // Either dist1, dist3 is the closest point to the box, determine which and test of overlap with box(AABB). - if ( flDist1 < flDist3 ) - { - if ( ( flDist1 > ( flDistBox + flTolerance ) ) || ( flDist3 < -( flDistBox + flTolerance ) ) ) - return false; - } - else - { - if ( ( flDist3 > ( flDistBox + flTolerance ) ) || ( flDist1 < -( flDistBox + flTolerance ) ) ) - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Test for an intersection (overlap) between an axial-aligned bounding -// box (AABB) and a triangle. -// -// Using the "Separating-Axis Theorem" to test for intersections between -// a triangle and an axial-aligned bounding box (AABB). -// 1. 3 Axis Planes - x, y, z -// 2. 9 Edge Planes Tests - the 3 edges of the triangle crossed with all 3 axial -// planes (x, y, z) -// 3. 1 Face Plane - the triangle plane (cplane_t plane below) -// Output: false = separating axis (no intersection) -// true = intersection -//----------------------------------------------------------------------------- -bool IsBoxIntersectingTriangle( const Vector &vecBoxCenter, const Vector &vecBoxExtents, - const Vector &v1, const Vector &v2, const Vector &v3, - const cplane_t &plane, float flTolerance ) -{ - // Test the axial planes (x,y,z) against the min, max of the triangle. - float flMin, flMax; - Vector p1, p2, p3; - - // x plane - p1.x = v1.x - vecBoxCenter.x; - p2.x = v2.x - vecBoxCenter.x; - p3.x = v3.x - vecBoxCenter.x; - FindMinMax( p1.x, p2.x, p3.x, flMin, flMax ); - if ( ( flMin > ( vecBoxExtents.x + flTolerance ) ) || ( flMax < -( vecBoxExtents.x + flTolerance ) ) ) - return false; - - // y plane - p1.y = v1.y - vecBoxCenter.y; - p2.y = v2.y - vecBoxCenter.y; - p3.y = v3.y - vecBoxCenter.y; - FindMinMax( p1.y, p2.y, p3.y, flMin, flMax ); - if ( ( flMin > ( vecBoxExtents.y + flTolerance ) ) || ( flMax < -( vecBoxExtents.y + flTolerance ) ) ) - return false; - - // z plane - p1.z = v1.z - vecBoxCenter.z; - p2.z = v2.z - vecBoxCenter.z; - p3.z = v3.z - vecBoxCenter.z; - FindMinMax( p1.z, p2.z, p3.z, flMin, flMax ); - if ( ( flMin > ( vecBoxExtents.z + flTolerance ) ) || ( flMax < -( vecBoxExtents.z + flTolerance ) ) ) - return false; - - // Test the 9 edge cases. - Vector vecEdge, vecAbsEdge; - - // edge 0 (cross x,y,z) - vecEdge = p2 - p1; - vecAbsEdge.y = FloatMakePositive( vecEdge.y ); - vecAbsEdge.z = FloatMakePositive( vecEdge.z ); - if ( !AxisTestEdgeCrossX2( vecEdge.z, vecEdge.y, vecAbsEdge.z, vecAbsEdge.y, p1, p3, vecBoxExtents, flTolerance ) ) - return false; - - vecAbsEdge.x = FloatMakePositive( vecEdge.x ); - if ( !AxisTestEdgeCrossY2( vecEdge.z, vecEdge.x, vecAbsEdge.z, vecAbsEdge.x, p1, p3, vecBoxExtents, flTolerance ) ) - return false; - - if ( !AxisTestEdgeCrossZ1( vecEdge.y, vecEdge.x, vecAbsEdge.y, vecAbsEdge.x, p2, p3, vecBoxExtents, flTolerance ) ) - return false; - - // edge 1 (cross x,y,z) - vecEdge = p3 - p2; - vecAbsEdge.y = FloatMakePositive( vecEdge.y ); - vecAbsEdge.z = FloatMakePositive( vecEdge.z ); - if ( !AxisTestEdgeCrossX2( vecEdge.z, vecEdge.y, vecAbsEdge.z, vecAbsEdge.y, p1, p2, vecBoxExtents, flTolerance ) ) - return false; - - vecAbsEdge.x = FloatMakePositive( vecEdge.x ); - if ( !AxisTestEdgeCrossY2( vecEdge.z, vecEdge.x, vecAbsEdge.z, vecAbsEdge.x, p1, p2, vecBoxExtents, flTolerance ) ) - return false; - - if ( !AxisTestEdgeCrossZ2( vecEdge.y, vecEdge.x, vecAbsEdge.y, vecAbsEdge.x, p1, p3, vecBoxExtents, flTolerance ) ) - return false; - - // edge 2 (cross x,y,z) - vecEdge = p1 - p3; - vecAbsEdge.y = FloatMakePositive( vecEdge.y ); - vecAbsEdge.z = FloatMakePositive( vecEdge.z ); - if ( !AxisTestEdgeCrossX3( vecEdge.z, vecEdge.y, vecAbsEdge.z, vecAbsEdge.y, p1, p2, vecBoxExtents, flTolerance ) ) - return false; - - vecAbsEdge.x = FloatMakePositive( vecEdge.x ); - if ( !AxisTestEdgeCrossY3( vecEdge.z, vecEdge.x, vecAbsEdge.z, vecAbsEdge.x, p1, p2, vecBoxExtents, flTolerance ) ) - return false; - - if ( !AxisTestEdgeCrossZ1( vecEdge.y, vecEdge.x, vecAbsEdge.y, vecAbsEdge.x, p2, p3, vecBoxExtents, flTolerance ) ) - return false; - - // Test against the triangle face plane. - Vector vecMin, vecMax; - VectorSubtract( vecBoxCenter, vecBoxExtents, vecMin ); - VectorAdd( vecBoxCenter, vecBoxExtents, vecMax ); - if ( BoxOnPlaneSide( vecMin, vecMax, &plane ) != 3 ) - return false; - - return true; -} - -// NOTE: JAY: This is untested code based on Real-time Collision Detection by Ericson -#if 0 -Vector CalcClosestPointOnTriangle( const Vector &P, const Vector &v0, const Vector &v1, const Vector &v2 ) -{ - Vector e0 = v1 - v0; - Vector e1 = v2 - v0; - Vector p0 = P - v0; - - // voronoi region of v0 - float d1 = DotProduct( e0, p0 ); - float d2 = DotProduct( e1, p0 ); - if (d1 <= 0.0f && d2 <= 0.0f) - return v0; - - // voronoi region of v1 - Vector p1 = P - v1; - float d3 = DotProduct( e0, p1 ); - float d4 = DotProduct( e1, p1 ); - if (d3 >=0.0f && d4 <= d3) - return v1; - - // voronoi region of e0 (v0-v1) - float ve2 = d1*d4 - d3*d2; - if ( ve2 <= 0.0f && d1 >= 0.0f && d3 <= 0.0f ) - { - float v = d1 / (d1-d3); - return v0 + v * e0; - } - // voronoi region of v2 - Vector p2 = P - v2; - float d5 = DotProduct( e0, p2 ); - float d6 = DotProduct( e1, p2 ); - if (d6 >= 0.0f && d5 <= d6) - return v2; - // voronoi region of e1 - float ve1 = d5*d2 - d1*d6; - if (ve1 <= 0.0f && d2 >= 0.0f && d6 >= 0.0f) - { - float w = d2 / (d2-d6); - return v0 + w * e1; - } - // voronoi region on e2 - float ve0 = d3*d6 - d5*d4; - if ( ve0 <= 0.0f && (d4-d3) >= 0.0f && (d5-d6) >= 0.0f ) - { - float w = (d4-d3)/((d4-d3) + (d5-d6)); - return v1 + w * (v2-v1); - } - // voronoi region of v0v1v2 triangle - float denom = 1.0f / (ve0+ve1+ve2); - float v = ve1*denom; - float w = ve2 * denom; - return v0 + e0 * v + e1 * w; -} -#endif - - -bool OBBHasFullyContainedIntersectionWithQuad( const Vector &vOBBExtent1_Scaled, const Vector &vOBBExtent2_Scaled, const Vector &vOBBExtent3_Scaled, const Vector &ptOBBCenter, - const Vector &vQuadNormal, float fQuadPlaneDist, const Vector &ptQuadCenter, - const Vector &vQuadExtent1_Normalized, float fQuadExtent1Length, - const Vector &vQuadExtent2_Normalized, float fQuadExtent2Length ) -{ - Vector ptOBB[8]; //this specific ordering helps us web out from a point to its 3 connecting points with some bit math (most importantly, no if's) - ptOBB[0] = ptOBBCenter - vOBBExtent1_Scaled - vOBBExtent2_Scaled - vOBBExtent3_Scaled; - ptOBB[1] = ptOBBCenter - vOBBExtent1_Scaled - vOBBExtent2_Scaled + vOBBExtent3_Scaled; - ptOBB[2] = ptOBBCenter - vOBBExtent1_Scaled + vOBBExtent2_Scaled + vOBBExtent3_Scaled; - ptOBB[3] = ptOBBCenter - vOBBExtent1_Scaled + vOBBExtent2_Scaled - vOBBExtent3_Scaled; - ptOBB[4] = ptOBBCenter + vOBBExtent1_Scaled - vOBBExtent2_Scaled - vOBBExtent3_Scaled; - ptOBB[5] = ptOBBCenter + vOBBExtent1_Scaled - vOBBExtent2_Scaled + vOBBExtent3_Scaled; - ptOBB[6] = ptOBBCenter + vOBBExtent1_Scaled + vOBBExtent2_Scaled + vOBBExtent3_Scaled; - ptOBB[7] = ptOBBCenter + vOBBExtent1_Scaled + vOBBExtent2_Scaled - vOBBExtent3_Scaled; - - float fDists[8]; - for( int i = 0; i != 8; ++i ) - fDists[i] = vQuadNormal.Dot( ptOBB[i] ) - fQuadPlaneDist; - - int iSides[8]; - int iSideMask = 0; - for( int i = 0; i != 8; ++i ) - { - if( fDists[i] > 0.0f ) - { - iSides[i] = 1; - iSideMask |= 1; - } - else - { - iSides[i] = 2; - iSideMask |= 2; - } - } - - if( iSideMask != 3 ) //points reside entirely on one side of the quad's plane - return false; - - Vector ptPlaneIntersections[12]; //only have 12 lines, can only possibly generate 12 split points - int iPlaneIntersectionsCount = 0; - - for( int i = 0; i != 8; ++i ) - { - if( iSides[i] == 2 ) //point behind the plane - { - int iAxisCrossings[3]; - iAxisCrossings[0] = i ^ 4; //upper 4 vs lower 4 crosses vOBBExtent1 axis - iAxisCrossings[1] = ((i + 1) & 3) + (i & 4); //cycle to the next element while staying within the upper 4 or lower 4, this will cross either vOBBExtent2 or vOBBExtent3 axis, we don't care which - iAxisCrossings[2] = ((i - 1) & 3) + (i & 4); //cylce to the previous element while staying within the upper 4 or lower 4, this will cross the axis iAxisCrossings[1] didn't cross - - for( int j = 0; j != 3; ++j ) - { - if( iSides[iAxisCrossings[j]] == 1 ) //point in front of the plane - { - //line between ptOBB[i] and ptOBB[iAxisCrossings[j]] intersects the plane, generate a point at the intersection for further testing - float fTotalDist = fDists[iAxisCrossings[j]] - fDists[i]; //remember that fDists[i] is a negative value - ptPlaneIntersections[iPlaneIntersectionsCount] = (ptOBB[iAxisCrossings[j]] * (-fDists[i]/fTotalDist)) + (ptOBB[i] * (fDists[iAxisCrossings[j]]/fTotalDist)); - - Assert( fabs( ptPlaneIntersections[iPlaneIntersectionsCount].Dot( vQuadNormal ) - fQuadPlaneDist ) < 0.1f ); //intersection point is on plane - - ++iPlaneIntersectionsCount; - } - } - } - } - - Assert( iPlaneIntersectionsCount != 0 ); - - for( int i = 0; i != iPlaneIntersectionsCount; ++i ) - { - //these points are guaranteed to be on the plane, now just check to see if they're within the quad's extents - Vector vToPointFromQuadCenter = ptPlaneIntersections[i] - ptQuadCenter; - - float fExt1Dist = vQuadExtent1_Normalized.Dot( vToPointFromQuadCenter ); - if( fabs( fExt1Dist ) > fQuadExtent1Length ) - return false; //point is outside boundaries - - //vToPointFromQuadCenter -= vQuadExtent1_Normalized * fExt1Dist; //to handle diamond shaped quads - - float fExt2Dist = vQuadExtent2_Normalized.Dot( vToPointFromQuadCenter ); - if( fabs( fExt2Dist ) > fQuadExtent2Length ) - return false; //point is outside boundaries - } - - return true; //there were lines crossing the quad plane, and every line crossing that plane had its intersection with the plane within the quad's boundaries -} - -//----------------------------------------------------------------------------- -// Compute if the Ray intersects the quad plane, and whether the entire -// Ray/Quad intersection is contained within the quad itself -// -// False if no intersection exists, or if part of the intersection is -// outside the quad's extents -//----------------------------------------------------------------------------- -bool RayHasFullyContainedIntersectionWithQuad( const Ray_t &ray, - const Vector &vQuadNormal, float fQuadPlaneDist, const Vector &ptQuadCenter, - const Vector &vQuadExtent1_Normalized, float fQuadExtent1Length, - const Vector &vQuadExtent2_Normalized, float fQuadExtent2Length ) -{ - Vector ptPlaneIntersections[(12 + 12 + 8)]; //absolute max possible: 12 lines to connect the start box, 12 more to connect the end box, 8 to connect the boxes to eachother - - //8 points to make an AABB, 8 lines to connect each point from it's start to end point along the ray, 8 possible intersections - int iPlaneIntersectionsCount = 0; - - if( ray.m_IsRay ) - { - //just 1 line - if( ray.m_IsSwept ) - { - Vector ptEndPoints[2]; - ptEndPoints[0] = ray.m_Start; - ptEndPoints[1] = ptEndPoints[0] + ray.m_Delta; - - int i; - float fDists[2]; - for( i = 0; i != 2; ++i ) - fDists[i] = vQuadNormal.Dot( ptEndPoints[i] ) - fQuadPlaneDist; - - for( i = 0; i != 2; ++i ) - { - if( fDists[i] <= 0.0f ) - { - int j = 1-i; - if( fDists[j] >= 0.0f ) - { - float fInvTotalDist = 1.0f / (fDists[j] - fDists[i]); //fDists[i] <= 0, ray is swept so no chance that the denom was 0 - ptPlaneIntersections[0] = (ptEndPoints[i] * (fDists[j] * fInvTotalDist)) - (ptEndPoints[j] * (fDists[i] * fInvTotalDist)); //fDists[i] <= 0 - Assert( fabs( ptPlaneIntersections[iPlaneIntersectionsCount].Dot( vQuadNormal ) - fQuadPlaneDist ) < 0.1f ); //intersection point is on plane - iPlaneIntersectionsCount = 1; - } - else - { - return false; - } - break; - } - } - - if( i == 2 ) - return false; - } - else //not swept, so this is actually a point on quad question - { - if( fabs( vQuadNormal.Dot( ray.m_Start ) - fQuadPlaneDist ) < 1e-6 ) - { - ptPlaneIntersections[0] = ray.m_Start; - iPlaneIntersectionsCount = 1; - } - else - { - return false; - } - } - } - else - { - Vector ptEndPoints[2][8]; - //this specific ordering helps us web out from a point to its 3 connecting points with some bit math (most importantly, no if's) - ptEndPoints[0][0] = ray.m_Start; ptEndPoints[0][0].x -= ray.m_Extents.x; ptEndPoints[0][0].y -= ray.m_Extents.y; ptEndPoints[0][0].z -= ray.m_Extents.z; - ptEndPoints[0][1] = ray.m_Start; ptEndPoints[0][1].x -= ray.m_Extents.x; ptEndPoints[0][1].y -= ray.m_Extents.y; ptEndPoints[0][1].z += ray.m_Extents.z; - ptEndPoints[0][2] = ray.m_Start; ptEndPoints[0][2].x -= ray.m_Extents.x; ptEndPoints[0][2].y += ray.m_Extents.y; ptEndPoints[0][2].z += ray.m_Extents.z; - ptEndPoints[0][3] = ray.m_Start; ptEndPoints[0][3].x -= ray.m_Extents.x; ptEndPoints[0][3].y += ray.m_Extents.y; ptEndPoints[0][3].z -= ray.m_Extents.z; - ptEndPoints[0][4] = ray.m_Start; ptEndPoints[0][4].x += ray.m_Extents.x; ptEndPoints[0][4].y -= ray.m_Extents.y; ptEndPoints[0][4].z -= ray.m_Extents.z; - ptEndPoints[0][5] = ray.m_Start; ptEndPoints[0][5].x += ray.m_Extents.x; ptEndPoints[0][5].y -= ray.m_Extents.y; ptEndPoints[0][5].z += ray.m_Extents.z; - ptEndPoints[0][6] = ray.m_Start; ptEndPoints[0][6].x += ray.m_Extents.x; ptEndPoints[0][6].y += ray.m_Extents.y; ptEndPoints[0][6].z += ray.m_Extents.z; - ptEndPoints[0][7] = ray.m_Start; ptEndPoints[0][7].x += ray.m_Extents.x; ptEndPoints[0][7].y += ray.m_Extents.y; ptEndPoints[0][7].z -= ray.m_Extents.z; - - float fDists[2][8]; - int iSides[2][8]; - int iSideMask[2] = { 0, 0 }; - for( int i = 0; i != 8; ++i ) - { - fDists[0][i] = vQuadNormal.Dot( ptEndPoints[0][i] ) - fQuadPlaneDist; - if( fDists[0][i] > 0.0f ) - { - iSides[0][i] = 1; - iSideMask[0] |= 1; - } - else - { - iSides[0][i] = 2; - iSideMask[0] |= 2; - } - } - - if( ray.m_IsSwept ) - { - for( int i = 0; i != 8; ++i ) - ptEndPoints[1][i] = ptEndPoints[0][i] + ray.m_Delta; - - for( int i = 0; i != 8; ++i ) - { - fDists[1][i] = vQuadNormal.Dot( ptEndPoints[1][i] ) - fQuadPlaneDist; - if( fDists[1][i] > 0.0f ) - { - iSides[1][i] = 1; - iSideMask[1] |= 1; - } - else - { - iSides[1][i] = 2; - iSideMask[1] |= 2; - } - } - } - - if( (iSideMask[0] | iSideMask[1]) != 3 ) - { - //Assert( (iSideMask[0] | iSideMask[1]) != 2 ); - return false; //all points resides entirely on one side of the quad - } - - - //generate intersections for boxes split by the plane at either end of the ray - for( int k = 0; k != 2; ++k ) - { - if( iSideMask[k] == 3 ) //box is split by the plane - { - for( int i = 0; i != 8; ++i ) - { - if( iSides[k][i] == 2 ) //point behind the plane - { - int iAxisCrossings[3]; - iAxisCrossings[0] = i ^ 4; //upper 4 vs lower 4 crosses X axis - iAxisCrossings[1] = ((i + 1) & 3) + (i & 4); //cycle to the next element while staying within the upper 4 or lower 4, this will cross either Y or Z axis, we don't care which - iAxisCrossings[2] = ((i - 1) & 3) + (i & 4); //cylce to the previous element while staying within the upper 4 or lower 4, this will cross the axis iAxisCrossings[1] didn't cross - - for( int j = 0; j != 3; ++j ) - { - if( iSides[k][iAxisCrossings[j]] == 1 ) //point in front of the plane - { - //line between ptEndPoints[i] and ptEndPoints[iAxisCrossings[j]] intersects the plane, generate a point at the intersection for further testing - float fInvTotalDist = 1.0f / (fDists[k][iAxisCrossings[j]] - fDists[k][i]); //remember that fDists[k][i] is a negative value - ptPlaneIntersections[iPlaneIntersectionsCount] = (ptEndPoints[k][iAxisCrossings[j]] * (-fDists[k][i] * fInvTotalDist)) + (ptEndPoints[k][i] * (fDists[k][iAxisCrossings[j]] * fInvTotalDist)); - - Assert( fabs( ptPlaneIntersections[iPlaneIntersectionsCount].Dot( vQuadNormal ) - fQuadPlaneDist ) < 0.1f ); //intersection point is on plane - - ++iPlaneIntersectionsCount; - } - } - } - } - } - } - - if( ray.m_IsSwept ) - { - for( int i = 0; i != 8; ++i ) - { - if( iSides[0][i] != iSides[1][i] ) - { - int iPosSide, iNegSide; - if( iSides[0][i] == 1 ) - { - iPosSide = 0; - iNegSide = 1; - } - else - { - iPosSide = 1; - iNegSide = 0; - } - - Assert( (fDists[iPosSide][i] >= 0.0f) && (fDists[iNegSide][i] <= 0.0f) ); - - float fInvTotalDist = 1.0f / (fDists[iPosSide][i] - fDists[iNegSide][i]); //remember that fDists[iNegSide][i] is a negative value - ptPlaneIntersections[iPlaneIntersectionsCount] = (ptEndPoints[iPosSide][i] * (-fDists[iNegSide][i] * fInvTotalDist)) + (ptEndPoints[iNegSide][i] * (fDists[iPosSide][i] * fInvTotalDist)); - - Assert( fabs( ptPlaneIntersections[iPlaneIntersectionsCount].Dot( vQuadNormal ) - fQuadPlaneDist ) < 0.1f ); //intersection point is on plane - - ++iPlaneIntersectionsCount; - } - } - } - } - - //down here, we should simply have a collection of plane intersections, now we see if they reside within the quad - Assert( iPlaneIntersectionsCount != 0 ); - - for( int i = 0; i != iPlaneIntersectionsCount; ++i ) - { - //these points are guaranteed to be on the plane, now just check to see if they're within the quad's extents - Vector vToPointFromQuadCenter = ptPlaneIntersections[i] - ptQuadCenter; - - float fExt1Dist = vQuadExtent1_Normalized.Dot( vToPointFromQuadCenter ); - if( fabs( fExt1Dist ) > fQuadExtent1Length ) - return false; //point is outside boundaries - - //vToPointFromQuadCenter -= vQuadExtent1_Normalized * fExt1Dist; //to handle diamond shaped quads - - float fExt2Dist = vQuadExtent2_Normalized.Dot( vToPointFromQuadCenter ); - if( fabs( fExt2Dist ) > fQuadExtent2Length ) - return false; //point is outside boundaries - } - - return true; //there were lines crossing the quad plane, and every line crossing that plane had its intersection with the plane within the quad's boundaries -} - -#endif // !_STATIC_LINKED || _SHARED_LIB diff --git a/public/collisionutils.h b/public/collisionutils.h deleted file mode 100644 index 1a892abd8..000000000 --- a/public/collisionutils.h +++ /dev/null @@ -1,450 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Common collision utility methods -// -// $Header: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef COLLISIONUTILS_H -#define COLLISIONUTILS_H - -#include "tier0/platform.h" - -#ifdef _WIN32 -#pragma once -#endif - -#include "mathlib/ssemath.h" - -//----------------------------------------------------------------------------- -// forward declarations -//----------------------------------------------------------------------------- -struct Ray_t; -class Vector; -class Vector2D; -class Vector4D; -struct cplane_t; -class QAngle; -class CBaseTrace; -struct matrix3x4_t; - - -//----------------------------------------------------------------------------- -// -// IntersectRayWithTriangle -// -// Intersects a ray with a triangle, returns distance t along ray. -// t will be less than zero if no intersection occurred -// oneSided will cull collisions which approach the triangle from the back -// side, assuming the vertices are specified in counter-clockwise order -// The vertices need not be specified in that order if oneSided is not used -// -//----------------------------------------------------------------------------- -float IntersectRayWithTriangle( const Ray_t& ray, - const Vector& v1, const Vector& v2, const Vector& v3, - bool oneSided ); - -//----------------------------------------------------------------------------- -// -// ComputeIntersectionBarycentricCoordinates -// -// Figures out the barycentric coordinates (u,v) where a ray hits a -// triangle. Note that this will ignore the ray extents, and it also ignores -// the ray length. Note that the edge from v1->v2 represents u (v2: u = 1), -// and the edge from v1->v3 represents v (v3: v = 1). It returns false -// if the ray is parallel to the triangle (or when t is specified if t is less -// than zero). -// -//----------------------------------------------------------------------------- -bool ComputeIntersectionBarycentricCoordinates( const Ray_t& ray, - const Vector& v1, const Vector& v2, const Vector& v3, float& u, float& v, - float *t = 0 ); - -//----------------------------------------------------------------------------- -// -// IntersectRayWithRay -// -// Returns whether or not there was an intersection. The "t" paramter is the -// distance along ray0 and the "s" parameter is the distance along ray1. If -// the two lines to not intersect the "t" and "s" represent the closest approach. -// "t" and "s" will not change if the rays are parallel. -// -//----------------------------------------------------------------------------- -bool IntersectRayWithRay( const Ray_t &ray0, const Ray_t &ray1, float &t, float &s ); - - -//----------------------------------------------------------------------------- -// -// IntersectRayWithSphere -// -// Returns whether or not there was an intersection. Returns the two intersection points. -// NOTE: The point of closest approach can be found at the average t value. -// -//----------------------------------------------------------------------------- -bool IntersectRayWithSphere( const Vector &vecRayOrigin, const Vector &vecRayDelta, const Vector &vecSphereCenter, float flRadius, float *pT1, float *pT2 ); - - -//----------------------------------------------------------------------------- -// -// IntersectInfiniteRayWithSphere -// -// Returns whether or not there was an intersection of a sphere against an infinitely -// extending ray. -// Returns the two intersection points -// -//----------------------------------------------------------------------------- -bool IntersectInfiniteRayWithSphere( const Vector &vecRayOrigin, const Vector &vecRayDelta, - const Vector &vecSphereCenter, float flRadius, float *pT1, float *pT2 ); - - -// returns true if the sphere and cone intersect -// NOTE: cone sine/cosine are the half angle of the cone -bool IsSphereIntersectingCone( const Vector &sphereCenter, float sphereRadius, const Vector &coneOrigin, const Vector &coneNormal, float coneSine, float coneCosine ); - -//----------------------------------------------------------------------------- -// -// IntersectRayWithPlane -// -// Intersects a ray with a plane, returns distance t along ray. -// t will be less than zero the intersection occurs in the opposite direction of the ray. -// -//----------------------------------------------------------------------------- -float IntersectRayWithPlane( const Ray_t& ray, const cplane_t& plane ); -float IntersectRayWithPlane( const Vector& org, const Vector& dir, const cplane_t& plane ); -float IntersectRayWithPlane( const Vector& org, const Vector& dir, const Vector& normal, float dist ); - -// This version intersects a ray with an axis-aligned plane -float IntersectRayWithAAPlane( const Vector& vecStart, const Vector& vecEnd, int nAxis, float flSign, float flDist ); - - -//----------------------------------------------------------------------------- -// IntersectRayWithBox -// -// Purpose: Computes the intersection of a ray with a box (AABB) -// Output : Returns true if there is an intersection + trace information -//----------------------------------------------------------------------------- -bool IntersectRayWithBox( const Vector &rayStart, const Vector &rayDelta, const Vector &boxMins, const Vector &boxMaxs, float epsilon, CBaseTrace *pTrace, float *pFractionLeftSolid = NULL ); -bool IntersectRayWithBox( const Ray_t &ray, const Vector &boxMins, const Vector &boxMaxs, float epsilon, CBaseTrace *pTrace, float *pFractionLeftSolid = NULL ); - -//----------------------------------------------------------------------------- -// Intersects a ray against a box -//----------------------------------------------------------------------------- -struct BoxTraceInfo_t -{ - float t1; - float t2; - int hitside; - bool startsolid; -}; - -bool IntersectRayWithBox( const Vector &vecRayStart, const Vector &vecRayDelta, - const Vector &boxMins, const Vector &boxMaxs, float flTolerance, BoxTraceInfo_t *pTrace ); - - -//----------------------------------------------------------------------------- -// IntersectRayWithOBB -// -// Purpose: Computes the intersection of a ray with a oriented box (OBB) -// Output : Returns true if there is an intersection + trace information -//----------------------------------------------------------------------------- -bool IntersectRayWithOBB( const Vector &vecRayStart, const Vector &vecRayDelta, - const matrix3x4_t &matOBBToWorld, const Vector &vecOBBMins, const Vector &vecOBBMaxs, - float flTolerance, CBaseTrace *pTrace ); - -bool IntersectRayWithOBB( const Vector &vecRayOrigin, const Vector &vecRayDelta, - const Vector &vecBoxOrigin, const QAngle &angBoxRotation, - const Vector &vecOBBMins, const Vector &vecOBBMaxs, float flTolerance, CBaseTrace *pTrace ); - -bool IntersectRayWithOBB( const Ray_t &ray, const Vector &vecBoxOrigin, const QAngle &angBoxRotation, - const Vector &vecOBBMins, const Vector &vecOBBMaxs, float flTolerance, CBaseTrace *pTrace ); - -bool IntersectRayWithOBB( const Ray_t &ray, const matrix3x4_t &matOBBToWorld, - const Vector &vecOBBMins, const Vector &vecOBBMaxs, float flTolerance, CBaseTrace *pTrace ); - -bool IntersectRayWithOBB( const Vector &vecRayStart, const Vector &vecRayDelta, - const matrix3x4_t &matOBBToWorld, const Vector &vecOBBMins, const Vector &vecOBBMaxs, - float flTolerance, BoxTraceInfo_t *pTrace ); - -//----------------------------------------------------------------------------- -// -// IsSphereIntersectingSphere -// -// returns true if there's an intersection between sphere and sphere -// -//----------------------------------------------------------------------------- -bool IsSphereIntersectingSphere( const Vector& center1, float radius1, - const Vector& center2, float radius2 ); - - -//----------------------------------------------------------------------------- -// -// IsBoxIntersectingSphere -// -// returns true if there's an intersection between box and sphere -// -//----------------------------------------------------------------------------- -bool IsBoxIntersectingSphere( const Vector& boxMin, const Vector& boxMax, - const Vector& center, float radius ); - -bool IsBoxIntersectingSphereExtents( const Vector& boxCenter, const Vector& boxHalfDiag, - const Vector& center, float radius ); - -//----------------------------------------------------------------------------- -// returns true if there's an intersection between ray and sphere -//----------------------------------------------------------------------------- -bool IsRayIntersectingSphere( const Vector &vecRayOrigin, const Vector &vecRayDelta, - const Vector &vecSphereCenter, float flRadius, float flTolerance = 0.0f ); - - -//----------------------------------------------------------------------------- -// -// IsCircleIntersectingRectangle -// -// returns true if there's an intersection between rectangle and circle -// -//----------------------------------------------------------------------------- -bool IsCircleIntersectingRectangle( const Vector2D& boxMin, const Vector2D& boxMax, - const Vector2D& center, float radius ); - - -//----------------------------------------------------------------------------- -// -// IsBoxIntersectingBox -// -// returns true if there's an intersection between two boxes -// -//----------------------------------------------------------------------------- -bool IsBoxIntersectingBox( const Vector& boxMin1, const Vector& boxMax1, - const Vector& boxMin2, const Vector& boxMax2 ); - -bool IsBoxIntersectingBoxExtents( const Vector& boxCenter1, const Vector& boxHalfDiagonal1, - const Vector& boxCenter2, const Vector& boxHalfDiagonal2 ); - - -#ifdef _X360 -// inline version: -#include "mathlib/ssemath.h" -inline bool IsBoxIntersectingBoxExtents( const fltx4 boxCenter1, const fltx4 boxHalfDiagonal1, - const fltx4 boxCenter2, const fltx4 boxHalfDiagonal2 ); -#endif - -//----------------------------------------------------------------------------- -// -// IsOBBIntersectingOBB -// -// returns true if there's an intersection between two OBBs -// -//----------------------------------------------------------------------------- -bool IsOBBIntersectingOBB( const Vector &vecOrigin1, const QAngle &vecAngles1, const Vector& boxMin1, const Vector& boxMax1, - const Vector &vecOrigin2, const QAngle &vecAngles2, const Vector& boxMin2, const Vector& boxMax2, float flTolerance = 0.0f ); - - -//----------------------------------------------------------------------------- -// -// IsBoxIntersectingRay -// -// returns true if there's an intersection between box and ray -// -//----------------------------------------------------------------------------- - -bool FASTCALL IsBoxIntersectingRay( const Vector& boxMin, const Vector& boxMax, - const Vector& origin, const Vector& delta, float flTolerance = 0.0f ); - -bool FASTCALL IsBoxIntersectingRay( const Vector& boxMin, const Vector& boxMax, - const Ray_t& ray, float flTolerance = 0.0f ); - -bool FASTCALL IsBoxIntersectingRay( const Vector& boxMin, const Vector& boxMax, - const Vector& origin, const Vector& delta, - const Vector& invDelta, float flTolerance = 0.0f ); - - -// On the PC, we can't pass fltx4's in registers like this. On the x360, it is -// much better if we do. -#ifdef _X360 -bool FASTCALL IsBoxIntersectingRay( fltx4 boxMin, fltx4 boxMax, - fltx4 origin, fltx4 delta, fltx4 invDelta, // ray parameters - fltx4 vTolerance = LoadZeroSIMD() ///< eg from ReplicateX4(flTolerance) - ); -#else -bool FASTCALL IsBoxIntersectingRay( const fltx4 &boxMin, const fltx4 &boxMax, - const fltx4 & origin, const fltx4 & delta, const fltx4 & invDelta, // ray parameters - const fltx4 & vTolerance = Four_Zeros ///< eg from ReplicateX4(flTolerance) - ); -#endif - -bool inline FASTCALL IsBoxIntersectingRay( const fltx4& boxMin, const fltx4& boxMax, - const fltx4& origin, const fltx4& delta, float flTolerance = 0.0f ) -{ - return IsBoxIntersectingRay( boxMin, boxMax, origin, delta, ReciprocalSIMD(delta), ReplicateX4(flTolerance) ); -} - - -bool FASTCALL IsBoxIntersectingRay( const fltx4& boxMin, const fltx4& boxMax, - const Ray_t& ray, float flTolerance = 0.0f ); - - - -//----------------------------------------------------------------------------- -// -// IsPointInBox -// -// returns true if the point is in the box -// -//----------------------------------------------------------------------------- -bool IsPointInBox( const Vector& pt, const Vector& boxMin, const Vector& boxMax ); - - -// SIMD version -FORCEINLINE bool IsPointInBox( const fltx4& pt, const fltx4& boxMin, const fltx4& boxMax ) -{ - fltx4 greater = CmpGtSIMD( pt,boxMax ); - fltx4 less = CmpLtSIMD( pt, boxMin ); - return (IsAllZeros(SetWToZeroSIMD(OrSIMD(greater,less)))); -} - - - -//----------------------------------------------------------------------------- -// Purpose: returns true if pt intersects the truncated cone -// origin - cone tip, axis unit cone axis, cosAngle - cosine of cone axis to surface angle -//----------------------------------------------------------------------------- -bool IsPointInCone( const Vector &pt, const Vector &origin, const Vector &axis, float cosAngle, float length ); - -//----------------------------------------------------------------------------- -// Intersects a plane with a triangle (using barycentric definition) -// The return value, in pIntersection, is an array of barycentric coordinates -// describing at most 2 intersection points. -// The return value is the number of intersection points -//----------------------------------------------------------------------------- -int IntersectTriangleWithPlaneBarycentric( const Vector& org, const Vector& edgeU, const Vector& edgeV, - const Vector4D& plane, Vector2D* pIntersection ); - -//----------------------------------------------------------------------------- -// -// PointInQuadBarycentric -// -// Given a point and a quad in a plane return the u and v (barycentric) positions -// of the point relative to the quad. The points (v1,v2,v3,v4) should be given -// in a counter-clockwise order with v1 acting as the primary corner (u=0, v=0). -// Thus, u0 = v2 - v1, and v0 = v4 - v1. -// -//----------------------------------------------------------------------------- - -enum QuadBarycentricRetval_t -{ - BARY_QUADRATIC_FALSE = 0, - BARY_QUADRATIC_TRUE = 1, - BARY_QUADRATIC_NEGATIVE_DISCRIMINANT = 2 -}; - -QuadBarycentricRetval_t PointInQuadToBarycentric( const Vector &v1, const Vector &v2, - const Vector &v3, const Vector &v4, const Vector &point, Vector2D &uv ); - - -void PointInQuadFromBarycentric( const Vector &v1, const Vector &v2, const Vector &v3, const Vector &v4, - const Vector2D &uv, Vector &point ); -void TexCoordInQuadFromBarycentric( const Vector2D &v1, const Vector2D &v2, const Vector2D &v3, const Vector2D &v4, - const Vector2D &uv, Vector2D &texCoord ); - - -//----------------------------------------------------------------------------- -// Compute point from barycentric specification -// Edge u goes from v0 to v1, edge v goes from v0 to v2 -//----------------------------------------------------------------------------- -void ComputePointFromBarycentric( const Vector& v0, const Vector& v1, const Vector& v2, - float u, float v, Vector& pt ); -void ComputePointFromBarycentric( const Vector2D& v0, const Vector2D& v1, const Vector2D& v2, - float u, float v, Vector2D& pt ); - - -//----------------------------------------------------------------------------- -// Swept OBB test -//----------------------------------------------------------------------------- -bool IsRayIntersectingOBB( const Ray_t &ray, const Vector& org, const QAngle& angles, - const Vector& mins, const Vector& maxs ); - - -//----------------------------------------------------------------------------- -// Compute a separating plane between two boxes (expensive!) -// Returns false if no separating plane exists -//----------------------------------------------------------------------------- -bool ComputeSeparatingPlane( const Vector& org1, const QAngle& angles1, const Vector& min1, const Vector& max1, - const Vector& org2, const QAngle& angles2, const Vector& min2, const Vector& max2, - float tolerance, cplane_t* pPlane ); - -//----------------------------------------------------------------------------- -// IsBoxIntersectingTriangle -// -// Test for an intersection (overlap) between an axial-aligned bounding -// box (AABB) and a triangle. -// -// Triangle points are in counter-clockwise order with the normal facing "out." -// -// Using the "Separating-Axis Theorem" to test for intersections between -// a triangle and an axial-aligned bounding box (AABB). -// 1. 3 Axis Plane Tests - x, y, z -// 2. 9 Edge Planes Tests - the 3 edges of the triangle crossed with all 3 axial -// planes (x, y, z) -// 3. 1 Face Plane Test - the plane the triangle resides in (cplane_t plane) -//----------------------------------------------------------------------------- -bool IsBoxIntersectingTriangle( const Vector &vecBoxCenter, const Vector &vecBoxExtents, - const Vector &v1, const Vector &v2, const Vector &v3, - const cplane_t &plane, float flTolerance ); - - -Vector CalcClosestPointOnTriangle( const Vector &P, const Vector &v0, const Vector &v1, const Vector &v2 ); - - -//----------------------------------------------------------------------------- -// Compute if the OBB intersects the quad plane, and whether the entire -// OBB/Quad intersection is contained within the quad itself -// -// False if no intersection exists, or if part of the intersection is -// outside the quad's extents -//----------------------------------------------------------------------------- -bool OBBHasFullyContainedIntersectionWithQuad( const Vector &vOBBExtent1_Scaled, const Vector &vOBBExtent2_Scaled, const Vector &vOBBExtent3_Scaled, const Vector &ptOBBCenter, - const Vector &vQuadNormal, float fQuadPlaneDist, const Vector &ptQuadCenter, - const Vector &vQuadExtent1_Normalized, float fQuadExtent1Length, - const Vector &vQuadExtent2_Normalized, float fQuadExtent2Length ); - - -//----------------------------------------------------------------------------- -// Compute if the Ray intersects the quad plane, and whether the entire -// Ray/Quad intersection is contained within the quad itself -// -// False if no intersection exists, or if part of the intersection is -// outside the quad's extents -//----------------------------------------------------------------------------- -bool RayHasFullyContainedIntersectionWithQuad( const Ray_t &ray, - const Vector &vQuadNormal, float fQuadPlaneDist, const Vector &ptQuadCenter, - const Vector &vQuadExtent1_Normalized, float fQuadExtent1Length, - const Vector &vQuadExtent2_Normalized, float fQuadExtent2Length ); - - - -//----------------------------------------------------------------------------- -// INLINES -//----------------------------------------------------------------------------- - - -#ifdef _X360 -inline bool IsBoxIntersectingBoxExtents( const fltx4 boxCenter1, const fltx4 boxHalfDiagonal1, - const fltx4 boxCenter2, const fltx4 boxHalfDiagonal2 ) -{ - fltx4 vecDelta, vecSize; - - vecDelta = SubSIMD(boxCenter1, boxCenter2); - vecSize = AddSIMD(boxHalfDiagonal1, boxHalfDiagonal2); - - uint condition; - XMVectorInBoundsR(&condition, vecDelta, vecSize); - // we want the top three words to be all 1's ; that means in bounds - - - return XMComparisonAllInBounds( condition ); -} -#endif - - -#endif // COLLISIONUTILS_H diff --git a/public/con_nprint.h b/public/con_nprint.h deleted file mode 100644 index 02e2c6380..000000000 --- a/public/con_nprint.h +++ /dev/null @@ -1,31 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Debug overlay / notfication printing -// -//=============================================================================// - -#ifndef CON_NPRINT_H -#define CON_NPRINT_H - -#ifdef _WIN32 -#pragma once -#endif - -//----------------------------------------------------------------------------- -// Purpose: Debug overlay / notfication printing -// NOTE: Structure cannot be changed by mods -//----------------------------------------------------------------------------- -typedef struct con_nprint_s -{ - int index; // Row # - float time_to_live; // # of seconds before it disappears. -1 means to display for 1 frame then go away. - float color[ 3 ]; // RGB colors ( 0.0 -> 1.0 scale ) - bool fixed_width_font; -} con_nprint_t; - -// Print string on line idx -void Con_NPrintf( int idx, const char *fmt, ... ); -// Customized printout -void Con_NXPrintf( const con_nprint_t *info, const char *fmt, ... ); - -#endif // CON_NPRINT_H diff --git a/public/const.h b/public/const.h deleted file mode 100644 index 2cfaee42e..000000000 --- a/public/const.h +++ /dev/null @@ -1,388 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef CONST_H -#define CONST_H - -#ifdef _WIN32 -#pragma once -#endif - -// the command line param that tells the engine to use steam -#define STEAM_PARM "-steam" -// the command line param to tell dedicated server to restart -// if they are out of date -#define AUTO_RESTART "-autoupdate" - -// the message a server sends when a clients steam login is expired -#define INVALID_STEAM_TICKET "Invalid STEAM UserID Ticket\n" -#define INVALID_STEAM_LOGON "No Steam logon\n" -#define INVALID_STEAM_VACBANSTATE "VAC banned from secure server\n" -#define INVALID_STEAM_LOGGED_IN_ELSEWHERE "This Steam account is being used in another location\n" - -// This is the default, see shareddefs.h for mod-specific value, which can override this -#define DEFAULT_TICK_INTERVAL (0.015) // 15 msec is the default -#define MINIMUM_TICK_INTERVAL (0.001) -#define MAXIMUM_TICK_INTERVAL (0.1) - -// This is the max # of players the engine can handle -#define ABSOLUTE_PLAYER_LIMIT 255 // not 256, so we can send the limit as a byte -#define ABSOLUTE_PLAYER_LIMIT_DW ( (ABSOLUTE_PLAYER_LIMIT/32) + 1 ) - -// a player name may have 31 chars + 0 on the PC. -// the 360 only allows 15 char + 0, but stick with the larger PC size for cross-platform communication -#define MAX_PLAYER_NAME_LENGTH 32 - -#ifdef _X360 -#define MAX_PLAYERS_PER_CLIENT XUSER_MAX_COUNT // Xbox 360 supports 4 players per console -#else -#define MAX_PLAYERS_PER_CLIENT 1 // One player per PC -#endif - -#define MAX_MAP_NAME 32 -#define MAX_NETWORKID_LENGTH 64 // num chars for a network (i.e steam) ID - -// BUGBUG: Reconcile with or derive this from the engine's internal definition! -// FIXME: I added an extra bit because I needed to make it signed -#define SP_MODEL_INDEX_BITS 11 - -// How many bits to use to encode an edict. -#define MAX_EDICT_BITS 11 // # of bits needed to represent max edicts -// Max # of edicts in a level -#define MAX_EDICTS (1<movetype values -enum MoveType_t -{ - MOVETYPE_NONE = 0, // never moves - MOVETYPE_ISOMETRIC, // For players -- in TF2 commander view, etc. - MOVETYPE_WALK, // Player only - moving on the ground - MOVETYPE_STEP, // gravity, special edge handling -- monsters use this - MOVETYPE_FLY, // No gravity, but still collides with stuff - MOVETYPE_FLYGRAVITY, // flies through the air + is affected by gravity - MOVETYPE_VPHYSICS, // uses VPHYSICS for simulation - MOVETYPE_PUSH, // no clip to world, push and crush - MOVETYPE_NOCLIP, // No gravity, no collisions, still do velocity/avelocity - MOVETYPE_LADDER, // Used by players only when going onto a ladder - MOVETYPE_OBSERVER, // Observer movement, depends on player's observer mode - MOVETYPE_CUSTOM, // Allows the entity to describe its own physics - - // should always be defined as the last item in the list - MOVETYPE_LAST = MOVETYPE_CUSTOM, - - MOVETYPE_MAX_BITS = 4 -}; - -// edict->movecollide values -enum MoveCollide_t -{ - MOVECOLLIDE_DEFAULT = 0, - - // These ones only work for MOVETYPE_FLY + MOVETYPE_FLYGRAVITY - MOVECOLLIDE_FLY_BOUNCE, // bounces, reflects, based on elasticity of surface and object - applies friction (adjust velocity) - MOVECOLLIDE_FLY_CUSTOM, // Touch() will modify the velocity however it likes - MOVECOLLIDE_FLY_SLIDE, // slides along surfaces (no bounce) - applies friciton (adjusts velocity) - - MOVECOLLIDE_COUNT, // Number of different movecollides - - // When adding new movecollide types, make sure this is correct - MOVECOLLIDE_MAX_BITS = 3 -}; - -// edict->solid values -// NOTE: Some movetypes will cause collisions independent of SOLID_NOT/SOLID_TRIGGER when the entity moves -// SOLID only effects OTHER entities colliding with this one when they move - UGH! - -// Solid type basically describes how the bounding volume of the object is represented -// NOTE: SOLID_BBOX MUST BE 2, and SOLID_VPHYSICS MUST BE 6 -// NOTE: These numerical values are used in the FGD by the prop code (see prop_dynamic) -enum SolidType_t -{ - SOLID_NONE = 0, // no solid model - SOLID_BSP = 1, // a BSP tree - SOLID_BBOX = 2, // an AABB - SOLID_OBB = 3, // an OBB (not implemented yet) - SOLID_OBB_YAW = 4, // an OBB, constrained so that it can only yaw - SOLID_CUSTOM = 5, // Always call into the entity for tests - SOLID_VPHYSICS = 6, // solid vphysics object, get vcollide from the model and collide with that - SOLID_LAST, -}; - -enum SolidFlags_t -{ - FSOLID_CUSTOMRAYTEST = 0x0001, // Ignore solid type + always call into the entity for ray tests - FSOLID_CUSTOMBOXTEST = 0x0002, // Ignore solid type + always call into the entity for swept box tests - FSOLID_NOT_SOLID = 0x0004, // Are we currently not solid? - FSOLID_TRIGGER = 0x0008, // This is something may be collideable but fires touch functions - // even when it's not collideable (when the FSOLID_NOT_SOLID flag is set) - FSOLID_NOT_STANDABLE = 0x0010, // You can't stand on this - FSOLID_VOLUME_CONTENTS = 0x0020, // Contains volumetric contents (like water) - FSOLID_FORCE_WORLD_ALIGNED = 0x0040, // Forces the collision rep to be world-aligned even if it's SOLID_BSP or SOLID_VPHYSICS - FSOLID_USE_TRIGGER_BOUNDS = 0x0080, // Uses a special trigger bounds separate from the normal OBB - FSOLID_ROOT_PARENT_ALIGNED = 0x0100, // Collisions are defined in root parent's local coordinate space - FSOLID_TRIGGER_TOUCH_DEBRIS = 0x0200, // This trigger will touch debris objects - - FSOLID_MAX_BITS = 10 -}; - -//----------------------------------------------------------------------------- -// A couple of inline helper methods -//----------------------------------------------------------------------------- -inline bool IsSolid( SolidType_t solidType, int nSolidFlags ) -{ - return (solidType != SOLID_NONE) && ((nSolidFlags & FSOLID_NOT_SOLID) == 0); -} - - -// m_lifeState values -#define LIFE_ALIVE 0 // alive -#define LIFE_DYING 1 // playing death animation or still falling off of a ledge waiting to hit ground -#define LIFE_DEAD 2 // dead. lying still. -#define LIFE_RESPAWNABLE 3 -#define LIFE_DISCARDBODY 4 - -// entity effects -enum -{ - EF_BONEMERGE = 0x001, // Performs bone merge on client side - EF_BRIGHTLIGHT = 0x002, // DLIGHT centered at entity origin - EF_DIMLIGHT = 0x004, // player flashlight - EF_NOINTERP = 0x008, // don't interpolate the next frame - EF_NOSHADOW = 0x010, // Don't cast no shadow - EF_NODRAW = 0x020, // don't draw entity - EF_NORECEIVESHADOW = 0x040, // Don't receive no shadow - EF_BONEMERGE_FASTCULL = 0x080, // For use with EF_BONEMERGE. If this is set, then it places this ent's origin at its - // parent and uses the parent's bbox + the max extents of the aiment. - // Otherwise, it sets up the parent's bones every frame to figure out where to place - // the aiment, which is inefficient because it'll setup the parent's bones even if - // the parent is not in the PVS. - EF_ITEM_BLINK = 0x100, // blink an item so that the user notices it. - EF_PARENT_ANIMATES = 0x200, // always assume that the parent entity is animating - EF_MAX_BITS = 10 -}; - -#define EF_PARITY_BITS 3 -#define EF_PARITY_MASK ((1< -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -void CheckHeap( void ) -{ -#ifdef USECRTMEMDEBUG - _CrtCheckMemory(); -#endif -} - -// undone: this needs to be somehow made to construct before everything else. -// see http://msdn.microsoft.com/library/periodic/period97/dembugs.htm for info -void InitCRTMemDebug( void ) -{ -#ifdef USECRTMEMDEBUG - _CrtSetDbgFlag( -// _CRTDBG_ALLOC_MEM_DF | - _CRTDBG_CHECK_ALWAYS_DF | - _CRTDBG_CHECK_CRT_DF | - _CRTDBG_DELAY_FREE_MEM_DF ); -#endif -} - -#endif // !_STATIC_LINKED || _SHARED_LIB diff --git a/public/crtmemdebug.h b/public/crtmemdebug.h deleted file mode 100644 index 04c5f7a6f..000000000 --- a/public/crtmemdebug.h +++ /dev/null @@ -1,33 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef CRTMEMDEBUG_H -#define CRTMEMDEBUG_H -#pragma once - -#ifdef USECRTMEMDEBUG - -#include -#define MEMCHECK CheckHeap() -void CheckHeap( void ); - -#else - -#define MEMCHECK - -#endif - -void InitCRTMemDebug( void ); - - -#endif // CRTMEMDEBUG_H diff --git a/public/datacache/idatacache.h b/public/datacache/idatacache.h deleted file mode 100644 index a5948963d..000000000 --- a/public/datacache/idatacache.h +++ /dev/null @@ -1,544 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef IDATACACHE_H -#define IDATACACHE_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "tier0/dbg.h" -#include "appframework/IAppSystem.h" - -class IDataCache; - -//----------------------------------------------------------------------------- -// -// Shared Data Cache API -// -//----------------------------------------------------------------------------- - -#define DATACACHE_INTERFACE_VERSION "VDataCache003" - -//----------------------------------------------------------------------------- -// Support types and enums -//----------------------------------------------------------------------------- - -//--------------------------------------------------------- -// Unique (per section) identifier for a cache item defined by client -//--------------------------------------------------------- -typedef uint32 DataCacheClientID_t; - - -//--------------------------------------------------------- -// Cache-defined handle for a cache item -//--------------------------------------------------------- -FORWARD_DECLARE_HANDLE( memhandle_t ); -typedef memhandle_t DataCacheHandle_t; -#define DC_INVALID_HANDLE ((DataCacheHandle_t)0) - -//--------------------------------------------------------- -// Cache Limits -//--------------------------------------------------------- -struct DataCacheLimits_t -{ - DataCacheLimits_t( unsigned nMaxBytes = (unsigned)-1, unsigned nMaxItems = (unsigned)-1, unsigned nMinBytes = 0, unsigned nMinItems = 0 ) - : nMaxBytes(nMaxBytes), - nMaxItems(nMaxItems), - nMinBytes(nMinBytes), - nMinItems(nMinItems) - { - } - - // Maximum levels permitted - unsigned nMaxBytes; - unsigned nMaxItems; - - // Minimum levels permitted - unsigned nMinBytes; - unsigned nMinItems; -}; - -//--------------------------------------------------------- -// Cache status -//--------------------------------------------------------- -struct DataCacheStatus_t -{ - // Current state of the cache - unsigned nBytes; - unsigned nItems; - - unsigned nBytesLocked; - unsigned nItemsLocked; - - // Diagnostics - unsigned nFindRequests; - unsigned nFindHits; -}; - -//--------------------------------------------------------- -// Cache options -//--------------------------------------------------------- -enum DataCacheOptions_t -{ - DC_TRACE_ACTIVITY = (1 << 0), - DC_FORCE_RELOCATE = (1 << 1), - DC_ALWAYS_MISS = (1 << 2), - DC_VALIDATE = (1 << 3), -}; - - -//--------------------------------------------------------- -// Cache report types -//--------------------------------------------------------- -enum DataCacheReportType_t -{ - DC_SUMMARY_REPORT, - DC_DETAIL_REPORT, - DC_DETAIL_REPORT_LRU, -}; - - -//--------------------------------------------------------- -// Notifications to section clients on cache events -//--------------------------------------------------------- -enum DataCacheNotificationType_t -{ - // Used internally to prohibit notifications - DC_NONE, - - // Item is falling off the LRU and should be deleted, return false to block - DC_AGE_DISCARD, - - // Item is being explicitly flushed and should be deleted, return false to block - DC_FLUSH_DISCARD, - - // Item is being explicitly removed and should be deleted. Failure is not an option - DC_REMOVED, - - // Cache is requesting item be relocated for debugging purposes - DC_RELOCATE, - - // Item info should be output to console, return false to accept default handling - DC_PRINT_INF0, -}; - -//------------------------------------- - -struct DataCacheNotification_t -{ - DataCacheNotificationType_t type; - const char * pszSectionName; - DataCacheClientID_t clientId; - const void * pItemData; - unsigned nItemSize; -}; - -//--------------------------------------------------------- - -const int DC_MAX_CLIENT_NAME = 15; -const int DC_MAX_ITEM_NAME = 511; - -//--------------------------------------------------------- -// Result codes -//--------------------------------------------------------- -enum DataCacheRemoveResult_t -{ - DC_OK, - DC_NOT_FOUND, - DC_LOCKED, -}; - -//--------------------------------------------------------- -// Add flags -//--------------------------------------------------------- -enum DataCacheAddFlags_t -{ - DCAF_LOCK = ( 1 << 0 ), - DCAF_DEFAULT = 0, -}; - - - -//----------------------------------------------------------------------------- -// IDataCacheSection -// -// Purpose: Implements a sub-section of the global cache. Subsections are -// areas of the cache with thier own memory constraints and common -// management. -//----------------------------------------------------------------------------- -abstract_class IDataCacheSection -{ -public: - //-------------------------------------------------------- - - virtual IDataCache *GetSharedCache() = 0; - virtual const char *GetName() = 0; - - //-------------------------------------------------------- - // Purpose: Controls cache size & options - //-------------------------------------------------------- - virtual void SetLimits( const DataCacheLimits_t &limits ) = 0; - virtual void SetOptions( unsigned options ) = 0; - - - //-------------------------------------------------------- - // Purpose: Get the current state of the section - //-------------------------------------------------------- - virtual void GetStatus( DataCacheStatus_t *pStatus, DataCacheLimits_t *pLimits = NULL ) = 0; - - - //-------------------------------------------------------- - // Purpose: Add an item to the cache. Purges old items if over budget, returns false if item was already in cache. - //-------------------------------------------------------- - virtual void EnsureCapacity( unsigned nBytes, unsigned nItems = 1 ) = 0; - - - //-------------------------------------------------------- - // Purpose: Add an item to the cache. Purges old items if over budget, returns false if item was already in cache. - //-------------------------------------------------------- - virtual bool Add( DataCacheClientID_t clientId, const void *pItemData, unsigned size, DataCacheHandle_t *pHandle ) = 0; - - //-------------------------------------------------------- - // Purpose: Finds an item in the cache, returns NULL if item is not in cache. Not a cheap operation if section not configured for fast find. - //-------------------------------------------------------- - virtual DataCacheHandle_t Find( DataCacheClientID_t clientId ) = 0; - - - //-------------------------------------------------------- - // Purpose: Get an item out of the cache and remove it. No callbacks are executed unless explicity specified. - //-------------------------------------------------------- - virtual DataCacheRemoveResult_t Remove( DataCacheHandle_t handle, const void **ppItemData, unsigned *pItemSize = NULL, bool bNotify = false ) = 0; - DataCacheRemoveResult_t Remove( DataCacheHandle_t handle, bool bNotify = false ) { return Remove( handle, NULL, NULL, bNotify ); } - - - //-------------------------------------------------------- - // Purpose: Returns if the data is currently in memory, but does *not* change its location in the LRU - //-------------------------------------------------------- - virtual bool IsPresent( DataCacheHandle_t handle ) = 0; - - - //-------------------------------------------------------- - // Purpose: Lock an item in the cache, returns NULL if item is not in the cache. - //-------------------------------------------------------- - virtual void *Lock( DataCacheHandle_t handle ) = 0; - - - //-------------------------------------------------------- - // Purpose: Unlock a previous lock. - //-------------------------------------------------------- - virtual int Unlock( DataCacheHandle_t handle ) = 0; - - - //-------------------------------------------------------- - // Purpose: Get an item without locking it, returns NULL if item is not in the cache. Use with care! - //-------------------------------------------------------- - virtual void *Get( DataCacheHandle_t handle, bool bFrameLock = false ) = 0; - virtual void *GetNoTouch( DataCacheHandle_t handle, bool bFrameLock = false ) = 0; - - //-------------------------------------------------------- - // Purpose: "Frame locking" (not game frame). A crude way to manage locks over relatively - // short periods. Does not affect normal locks/unlocks - //-------------------------------------------------------- - virtual int BeginFrameLocking() = 0; - virtual bool IsFrameLocking() = 0; - virtual void *FrameLock( DataCacheHandle_t handle ) = 0; - virtual int EndFrameLocking() = 0; - virtual int *GetFrameUnlockCounterPtr() = 0; - - - //-------------------------------------------------------- - // Purpose: Lock management, not for the feint of heart - //-------------------------------------------------------- - virtual int GetLockCount( DataCacheHandle_t handle ) = 0; - virtual int BreakLock( DataCacheHandle_t handle ) = 0; - - - //-------------------------------------------------------- - // Purpose: Explicitly mark an item as "recently used" - //-------------------------------------------------------- - virtual bool Touch( DataCacheHandle_t handle ) = 0; - - - //-------------------------------------------------------- - // Purpose: Explicitly mark an item as "least recently used". - //-------------------------------------------------------- - virtual bool Age( DataCacheHandle_t handle ) = 0; - - - //-------------------------------------------------------- - // Purpose: Empty the cache. Returns bytes released, will remove locked items if force specified - //-------------------------------------------------------- - virtual unsigned Flush( bool bUnlockedOnly = true, bool bNotify = true ) = 0; - - - //-------------------------------------------------------- - // Purpose: Dump the oldest items to free the specified amount of memory. Returns amount actually freed - //-------------------------------------------------------- - virtual unsigned Purge( unsigned nBytes ) = 0; - - - //-------------------------------------------------------- - // Purpose: Output the state of the section - //-------------------------------------------------------- - virtual void OutputReport( DataCacheReportType_t reportType = DC_SUMMARY_REPORT ) = 0; - - //-------------------------------------------------------- - // Purpose: Updates the size used by a specific item (locks the item, kicks - // other items out to make room as necessary, unlocks the item). - //-------------------------------------------------------- - virtual void UpdateSize( DataCacheHandle_t handle, unsigned int nNewSize ) = 0; - - - //-------------------------------------------------------- - // Purpose: Access to the mutex. More explicit control during get-then-lock sequences - // to ensure object stays valid during "then" - //-------------------------------------------------------- - virtual void LockMutex() = 0; - virtual void UnlockMutex() = 0; - - //-------------------------------------------------------- - // Purpose: Add an item to the cache. Purges old items if over budget, returns false if item was already in cache. - //-------------------------------------------------------- - virtual bool AddEx( DataCacheClientID_t clientId, const void *pItemData, unsigned size, unsigned flags, DataCacheHandle_t *pHandle ) = 0; -}; - - -//----------------------------------------------------------------------------- -// IDataCacheClient -// -// Purpose: Connection between the cache and the owner of a cache section -// -//----------------------------------------------------------------------------- -abstract_class IDataCacheClient -{ -public: - //-------------------------------------------------------- - // - //-------------------------------------------------------- - virtual bool HandleCacheNotification( const DataCacheNotification_t ¬ification ) = 0; - - - //-------------------------------------------------------- - // - //-------------------------------------------------------- - virtual bool GetItemName( DataCacheClientID_t clientId, const void *pItem, char *pDest, unsigned nMaxLen ) = 0; -}; - -//------------------------------------- - -class CDefaultDataCacheClient : public IDataCacheClient -{ -public: - virtual bool HandleCacheNotification( const DataCacheNotification_t ¬ification ) - { - switch ( notification.type ) - { - case DC_AGE_DISCARD: - case DC_FLUSH_DISCARD: - case DC_REMOVED: - Assert ( 0 ); - return false; - default: - break; - } - return false; - } - - virtual bool GetItemName( DataCacheClientID_t clientId, const void *pItem, char *pDest, unsigned nMaxLen ) - { - return false; - } -}; - - -//----------------------------------------------------------------------------- -// IDataCache -// -// Purpose: The global shared cache. Manages sections and overall budgets. -// -//----------------------------------------------------------------------------- -abstract_class IDataCache : public IAppSystem -{ -public: - //-------------------------------------------------------- - // Purpose: Controls cache size. - //-------------------------------------------------------- - virtual void SetSize( int nMaxBytes ) = 0; - virtual void SetOptions( unsigned options ) = 0; - virtual void SetSectionLimits( const char *pszSectionName, const DataCacheLimits_t &limits ) = 0; - - - //-------------------------------------------------------- - // Purpose: Get the current state of the cache - //-------------------------------------------------------- - virtual void GetStatus( DataCacheStatus_t *pStatus, DataCacheLimits_t *pLimits = NULL ) = 0; - - - //-------------------------------------------------------- - // Purpose: Add a section to the cache - //-------------------------------------------------------- - virtual IDataCacheSection *AddSection( IDataCacheClient *pClient, const char *pszSectionName, const DataCacheLimits_t &limits = DataCacheLimits_t(), bool bSupportFastFind = false ) = 0; - - - //-------------------------------------------------------- - // Purpose: Remove a section from the cache - //-------------------------------------------------------- - virtual void RemoveSection( const char *pszClientName, bool bCallFlush = true ) = 0; - void RemoveSection( IDataCacheSection *pSection, bool bCallFlush = true ) { if ( pSection) RemoveSection( pSection->GetName() ); } - - - //-------------------------------------------------------- - // Purpose: Find a section of the cache - //-------------------------------------------------------- - virtual IDataCacheSection *FindSection( const char *pszClientName ) = 0; - - - //-------------------------------------------------------- - // Purpose: Dump the oldest items to free the specified amount of memory. Returns amount actually freed - //-------------------------------------------------------- - virtual unsigned Purge( unsigned nBytes ) = 0; - - - //-------------------------------------------------------- - // Purpose: Empty the cache. Returns bytes released, will remove locked items if force specified - //-------------------------------------------------------- - virtual unsigned Flush( bool bUnlockedOnly = true, bool bNotify = true ) = 0; - - - //-------------------------------------------------------- - // Purpose: Output the state of the cache - //-------------------------------------------------------- - virtual void OutputReport( DataCacheReportType_t reportType = DC_SUMMARY_REPORT, const char *pszSection = NULL ) = 0; -}; - -//----------------------------------------------------------------------------- -// Helper class to support usage pattern similar to CDataManager -//----------------------------------------------------------------------------- - -template< class STORAGE_TYPE, class CREATE_PARAMS, class LOCK_TYPE = STORAGE_TYPE * > -class CManagedDataCacheClient : public CDefaultDataCacheClient -{ -public: - typedef CManagedDataCacheClient CCacheClientBaseClass; - - CManagedDataCacheClient() - : m_pCache( NULL ) - { - } - - void Init( IDataCache *pSharedCache, const char *pszSectionName, const DataCacheLimits_t &limits = DataCacheLimits_t(), bool bSupportFastFind = false ) - { - if ( !m_pCache ) - { - m_pCache = pSharedCache->AddSection( this, pszSectionName, limits, bSupportFastFind ); - } - } - - void Shutdown() - { - if ( m_pCache ) - { - m_pCache->GetSharedCache()->RemoveSection( m_pCache ); - m_pCache = NULL; - } - } - - LOCK_TYPE CacheGet( DataCacheHandle_t handle, bool bFrameLock = true ) - { - return (LOCK_TYPE)(((STORAGE_TYPE *)m_pCache->Get( handle, bFrameLock ))->GetData()); - } - - LOCK_TYPE CacheGetNoTouch( DataCacheHandle_t handle ) - { - return (LOCK_TYPE)(((STORAGE_TYPE *)m_pCache->GetNoTouch( handle ))->GetData()); - } - - LOCK_TYPE CacheLock( DataCacheHandle_t handle ) - { - return (LOCK_TYPE)(((STORAGE_TYPE *)m_pCache->Lock( handle ))->GetData()); - } - - int CacheUnlock( DataCacheHandle_t handle ) - { - return m_pCache->Unlock( handle ); - } - - void CacheTouch( DataCacheHandle_t handle ) - { - m_pCache->Touch( handle ); - } - - void CacheRemove( DataCacheHandle_t handle, bool bNotify = true ) - { - m_pCache->Remove( handle, bNotify ); - } - - void CacheFlush() - { - m_pCache->Flush(); - } - - DataCacheHandle_t CacheCreate( const CREATE_PARAMS &createParams, unsigned flags = DCAF_DEFAULT ) - { - m_pCache->EnsureCapacity(STORAGE_TYPE::EstimatedSize(createParams)); - STORAGE_TYPE *pStore = STORAGE_TYPE::CreateResource( createParams ); - DataCacheHandle_t handle; - m_pCache->AddEx( (DataCacheClientID_t)pStore, pStore, pStore->Size(), flags, &handle); - return handle; - } - - void CacheLockMutex() - { - m_pCache->LockMutex(); - } - - void CacheUnlockMutex() - { - m_pCache->UnlockMutex(); - } - - bool HandleCacheNotification( const DataCacheNotification_t ¬ification ) - { - switch ( notification.type ) - { - case DC_AGE_DISCARD: - case DC_FLUSH_DISCARD: - case DC_REMOVED: - STORAGE_TYPE *p = (STORAGE_TYPE *)notification.clientId; - p->DestroyResource(); - return true; - } - - return CDefaultDataCacheClient::HandleCacheNotification( notification ); - } - - -protected: - - ~CManagedDataCacheClient() - { - Shutdown(); - } - - IDataCacheSection *GetCacheSection() - { - return m_pCache; - } - -private: - IDataCacheSection *m_pCache; - -}; - -//----------------------------------------------------------------------------- - -#endif // IDataCache diff --git a/public/datacache/imdlcache.h b/public/datacache/imdlcache.h deleted file mode 100644 index cbdd1f10c..000000000 --- a/public/datacache/imdlcache.h +++ /dev/null @@ -1,297 +0,0 @@ -//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. =========== -// -// The copyright to the contents herein is the property of Valve, L.L.C. -// The contents may be used and/or copied only with the written permission of -// Valve, L.L.C., or in accordance with the terms and conditions stipulated in -// the agreement/contract under which the contents have been supplied. -// -// $Header: $ -// $NoKeywords: $ -// -// model loading and caching -// -//============================================================================= - -#ifndef IMDLCACHE_H -#define IMDLCACHE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "appframework/IAppSystem.h" - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -struct studiohdr_t; -struct studiohwdata_t; -struct vcollide_t; -struct virtualmodel_t; -struct vertexFileHeader_t; - -namespace OptimizedModel -{ - struct FileHeader_t; -} - - -//----------------------------------------------------------------------------- -// Reference to a loaded studiomdl -//----------------------------------------------------------------------------- -typedef unsigned short MDLHandle_t; - -enum -{ - MDLHANDLE_INVALID = (MDLHandle_t)~0 -}; - - -//----------------------------------------------------------------------------- -// Cache data types -//----------------------------------------------------------------------------- -enum MDLCacheDataType_t -{ - // Callbacks to get called when data is loaded or unloaded for these: - MDLCACHE_STUDIOHDR = 0, - MDLCACHE_STUDIOHWDATA, - MDLCACHE_VCOLLIDE, - - // Callbacks NOT called when data is loaded or unloaded for these: - MDLCACHE_ANIMBLOCK, - MDLCACHE_VIRTUALMODEL, - MDLCACHE_VERTEXES, - MDLCACHE_DECODEDANIMBLOCK, -}; - -abstract_class IMDLCacheNotify -{ -public: - // Called right after the data is loaded - virtual void OnDataLoaded( MDLCacheDataType_t type, MDLHandle_t handle ) = 0; - - // Called right before the data is unloaded - virtual void OnDataUnloaded( MDLCacheDataType_t type, MDLHandle_t handle ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Flags for flushing -//----------------------------------------------------------------------------- -enum MDLCacheFlush_t -{ - MDLCACHE_FLUSH_STUDIOHDR = 0x01, - MDLCACHE_FLUSH_STUDIOHWDATA = 0x02, - MDLCACHE_FLUSH_VCOLLIDE = 0x04, - MDLCACHE_FLUSH_ANIMBLOCK = 0x08, - MDLCACHE_FLUSH_VIRTUALMODEL = 0x10, - MDLCACHE_FLUSH_AUTOPLAY = 0x20, - MDLCACHE_FLUSH_VERTEXES = 0x40, - - MDLCACHE_FLUSH_IGNORELOCK = 0x80000000, - MDLCACHE_FLUSH_ALL = 0xFFFFFFFF -}; - -/* -#define MDLCACHE_INTERFACE_VERSION_4 "MDLCache004" - -namespace MDLCacheV4 -{ - -abstract_class IMDLCache : public IAppSystem -{ -public: - // Used to install callbacks for when data is loaded + unloaded - virtual void SetCacheNotify( IMDLCacheNotify *pNotify ) = 0; - // NOTE: This assumes the "GAME" path if you don't use - // the UNC method of specifying files. This will also increment - // the reference count of the MDL - virtual MDLHandle_t FindMDL( const char *pMDLRelativePath ) = 0; - - // Reference counting - virtual int AddRef( MDLHandle_t handle ) = 0; - virtual int Release( MDLHandle_t handle ) = 0; - - // Gets at the various data associated with a MDL - virtual studiohdr_t *GetStudioHdr( MDLHandle_t handle ) = 0; - virtual studiohwdata_t *GetHardwareData( MDLHandle_t handle ) = 0; - virtual vcollide_t *GetVCollide( MDLHandle_t handle ) = 0; - virtual unsigned char *GetAnimBlock( MDLHandle_t handle, int nBlock ) = 0; - virtual virtualmodel_t *GetVirtualModel( MDLHandle_t handle ) = 0; - virtual int GetAutoplayList( MDLHandle_t handle, unsigned short **pOut ) = 0; - virtual vertexFileHeader_t *GetVertexData( MDLHandle_t handle ) = 0; - - // Brings all data associated with an MDL into memory - virtual void TouchAllData( MDLHandle_t handle ) = 0; - - // Gets/sets user data associated with the MDL - virtual void SetUserData( MDLHandle_t handle, void* pData ) = 0; - virtual void *GetUserData( MDLHandle_t handle ) = 0; - - // Is this MDL using the error model? - virtual bool IsErrorModel( MDLHandle_t handle ) = 0; - - // Flushes the cache, force a full discard - virtual void Flush( int nFlushFlags = MDLCACHE_FLUSH_ALL ) = 0; - - // Flushes a particular model out of memory - virtual void Flush( MDLHandle_t handle, int nFlushFlags = MDLCACHE_FLUSH_ALL ) = 0; - - // Returns the name of the model (its relative path) - virtual const char *GetModelName( MDLHandle_t handle ) = 0; - - // faster access when you already have the studiohdr - virtual virtualmodel_t *GetVirtualModelFast( const studiohdr_t *pStudioHdr, MDLHandle_t handle ) = 0; - - // all cache entries that subsequently allocated or successfully checked - // are considered "locked" and will not be freed when additional memory is needed - virtual void BeginLock() = 0; - - // reset all protected blocks to normal - virtual void EndLock() = 0; - - // returns a pointer to a counter that is incremented every time the cache has been out of the locked state (EVIL) - virtual int *GetFrameUnlockCounterPtr() = 0; - - // Finish all pending async operations - virtual void FinishPendingLoads() = 0; -}; - - -} -*/ - -//----------------------------------------------------------------------------- -// The main MDL cacher -//----------------------------------------------------------------------------- -#define MDLCACHE_INTERFACE_VERSION "MDLCache004" - -abstract_class IMDLCache : public IAppSystem -{ -public: - // Used to install callbacks for when data is loaded + unloaded - // Returns the prior notify - virtual void SetCacheNotify( IMDLCacheNotify *pNotify ) = 0; - - // NOTE: This assumes the "GAME" path if you don't use - // the UNC method of specifying files. This will also increment - // the reference count of the MDL - virtual MDLHandle_t FindMDL( const char *pMDLRelativePath ) = 0; - - // Reference counting - virtual int AddRef( MDLHandle_t handle ) = 0; - virtual int Release( MDLHandle_t handle ) = 0; - virtual int GetRef( MDLHandle_t handle ) = 0; - - // Gets at the various data associated with a MDL - virtual studiohdr_t *GetStudioHdr( MDLHandle_t handle ) = 0; - virtual studiohwdata_t *GetHardwareData( MDLHandle_t handle ) = 0; - virtual vcollide_t *GetVCollide( MDLHandle_t handle ) = 0; - virtual unsigned char *GetAnimBlock( MDLHandle_t handle, int nBlock ) = 0; - virtual virtualmodel_t *GetVirtualModel( MDLHandle_t handle ) = 0; - virtual int GetAutoplayList( MDLHandle_t handle, unsigned short **pOut ) = 0; - virtual vertexFileHeader_t *GetVertexData( MDLHandle_t handle ) = 0; - - // Brings all data associated with an MDL into memory - virtual void TouchAllData( MDLHandle_t handle ) = 0; - - // Gets/sets user data associated with the MDL - virtual void SetUserData( MDLHandle_t handle, void* pData ) = 0; - virtual void *GetUserData( MDLHandle_t handle ) = 0; - - // Is this MDL using the error model? - virtual bool IsErrorModel( MDLHandle_t handle ) = 0; - - // Flushes the cache, force a full discard - virtual void Flush( MDLCacheFlush_t nFlushFlags = MDLCACHE_FLUSH_ALL ) = 0; - - // Flushes a particular model out of memory - virtual void Flush( MDLHandle_t handle, int nFlushFlags = MDLCACHE_FLUSH_ALL ) = 0; - - // Returns the name of the model (its relative path) - virtual const char *GetModelName( MDLHandle_t handle ) = 0; - - // faster access when you already have the studiohdr - virtual virtualmodel_t *GetVirtualModelFast( const studiohdr_t *pStudioHdr, MDLHandle_t handle ) = 0; - - // all cache entries that subsequently allocated or successfully checked - // are considered "locked" and will not be freed when additional memory is needed - virtual void BeginLock() = 0; - - // reset all protected blocks to normal - virtual void EndLock() = 0; - - // returns a pointer to a counter that is incremented every time the cache has been out of the locked state (EVIL) - virtual int *GetFrameUnlockCounterPtrOLD() = 0; - - // Finish all pending async operations - virtual void FinishPendingLoads() = 0; - - virtual vcollide_t *GetVCollideEx( MDLHandle_t handle, bool synchronousLoad = true ) = 0; - virtual bool GetVCollideSize( MDLHandle_t handle, int *pVCollideSize ) = 0; - - virtual bool GetAsyncLoad( MDLCacheDataType_t type ) = 0; - virtual bool SetAsyncLoad( MDLCacheDataType_t type, bool bAsync ) = 0; - - virtual void BeginMapLoad() = 0; - virtual void EndMapLoad() = 0; - virtual void MarkAsLoaded( MDLHandle_t handle ) = 0; - - virtual void InitPreloadData( bool rebuild ) = 0; - virtual void ShutdownPreloadData() = 0; - - virtual bool IsDataLoaded( MDLHandle_t handle, MDLCacheDataType_t type ) = 0; - - virtual int *GetFrameUnlockCounterPtr( MDLCacheDataType_t type ) = 0; - - virtual studiohdr_t *LockStudioHdr( MDLHandle_t handle ) = 0; - virtual void UnlockStudioHdr( MDLHandle_t handle ) = 0; - - virtual bool PreloadModel( MDLHandle_t handle ) = 0; - - // Hammer uses this. If a model has an error loading in GetStudioHdr, then it is flagged - // as an error model and any further attempts to load it will just get the error model. - // That is, until you call this function. Then it will load the correct model. - virtual void ResetErrorModelStatus( MDLHandle_t handle ) = 0; - - virtual void MarkFrame() = 0; -}; - - -//----------------------------------------------------------------------------- -// Critical section helper code -//----------------------------------------------------------------------------- -class CMDLCacheCriticalSection -{ -public: - CMDLCacheCriticalSection( IMDLCache *pCache ) : m_pCache( pCache ) - { - m_pCache->BeginLock(); - } - - ~CMDLCacheCriticalSection() - { - m_pCache->EndLock(); - } - -private: - IMDLCache *m_pCache; -}; - -#define MDCACHE_FINE_GRAINED 1 - -#if defined(MDCACHE_FINE_GRAINED) -#define MDLCACHE_CRITICAL_SECTION_( pCache ) CMDLCacheCriticalSection cacheCriticalSection(pCache) -#define MDLCACHE_COARSE_LOCK_( pCache ) ((void)(0)) -#elif defined(MDLCACHE_LEVEL_LOCKED) -#define MDLCACHE_CRITICAL_SECTION_( pCache ) ((void)(0)) -#define MDLCACHE_COARSE_LOCK_( pCache ) ((void)(0)) -#else -#define MDLCACHE_CRITICAL_SECTION_( pCache ) ((void)(0)) -#define MDLCACHE_COARSE_LOCK_( pCache ) CMDLCacheCriticalSection cacheCriticalSection(pCache) -#endif -#define MDLCACHE_CRITICAL_SECTION() MDLCACHE_CRITICAL_SECTION_(mdlcache) -#define MDLCACHE_COARSE_LOCK() MDLCACHE_COARSE_LOCK_(mdlcache) - -#endif // IMDLCACHE_H - diff --git a/public/datamap.h b/public/datamap.h deleted file mode 100644 index f3861bbf4..000000000 --- a/public/datamap.h +++ /dev/null @@ -1,456 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef DATAMAP_H -#define DATAMAP_H -#ifdef _WIN32 -#pragma once -#endif - -#ifndef VECTOR_H -#include "mathlib/vector.h" -#endif - -#include "tier1/utlvector.h" - -#include "tier0/memdbgon.h" - -// SINGLE_INHERITANCE restricts the size of CBaseEntity pointers-to-member-functions to 4 bytes -class SINGLE_INHERITANCE CBaseEntity; -struct inputdata_t; - -#define INVALID_TIME (FLT_MAX * -1.0) // Special value not rebased on save/load - -typedef enum _fieldtypes -{ - FIELD_VOID = 0, // No type or value - FIELD_FLOAT, // Any floating point value - FIELD_STRING, // A string ID (return from ALLOC_STRING) - FIELD_VECTOR, // Any vector, QAngle, or AngularImpulse - FIELD_QUATERNION, // A quaternion - FIELD_INTEGER, // Any integer or enum - FIELD_BOOLEAN, // boolean, implemented as an int, I may use this as a hint for compression - FIELD_SHORT, // 2 byte integer - FIELD_CHARACTER, // a byte - FIELD_COLOR32, // 8-bit per channel r,g,b,a (32bit color) - FIELD_EMBEDDED, // an embedded object with a datadesc, recursively traverse and embedded class/structure based on an additional typedescription - FIELD_CUSTOM, // special type that contains function pointers to it's read/write/parse functions - - FIELD_CLASSPTR, // CBaseEntity * - FIELD_EHANDLE, // Entity handle - FIELD_EDICT, // edict_t * - - FIELD_POSITION_VECTOR, // A world coordinate (these are fixed up across level transitions automagically) - FIELD_TIME, // a floating point time (these are fixed up automatically too!) - FIELD_TICK, // an integer tick count( fixed up similarly to time) - FIELD_MODELNAME, // Engine string that is a model name (needs precache) - FIELD_SOUNDNAME, // Engine string that is a sound name (needs precache) - - FIELD_INPUT, // a list of inputed data fields (all derived from CMultiInputVar) - FIELD_FUNCTION, // A class function pointer (Think, Use, etc) - - FIELD_VMATRIX, // a vmatrix (output coords are NOT worldspace) - - // NOTE: Use float arrays for local transformations that don't need to be fixed up. - FIELD_VMATRIX_WORLDSPACE,// A VMatrix that maps some local space to world space (translation is fixed up on level transitions) - FIELD_MATRIX3X4_WORLDSPACE, // matrix3x4_t that maps some local space to world space (translation is fixed up on level transitions) - - FIELD_INTERVAL, // a start and range floating point interval ( e.g., 3.2->3.6 == 3.2 and 0.4 ) - FIELD_MODELINDEX, // a model index - FIELD_MATERIALINDEX, // a material index (using the material precache string table) - - FIELD_VECTOR2D, // 2 floats - - FIELD_TYPECOUNT, // MUST BE LAST -} fieldtype_t; - - -//----------------------------------------------------------------------------- -// Field sizes... -//----------------------------------------------------------------------------- -template -class CDatamapFieldSizeDeducer -{ -public: - enum - { - SIZE = 0 - }; - - static int FieldSize( ) - { - return 0; - } -}; - -#define DECLARE_FIELD_SIZE( _fieldType, _fieldSize ) \ - template< > class CDatamapFieldSizeDeducer<_fieldType> { public: enum { SIZE = _fieldSize }; static int FieldSize() { return _fieldSize; } }; -#define FIELD_SIZE( _fieldType ) CDatamapFieldSizeDeducer<_fieldType>::SIZE -#define FIELD_BITS( _fieldType ) (FIELD_SIZE( _fieldType ) * 8) - -DECLARE_FIELD_SIZE( FIELD_FLOAT, sizeof(float) ) -DECLARE_FIELD_SIZE( FIELD_STRING, sizeof(int) ) -DECLARE_FIELD_SIZE( FIELD_VECTOR, 3 * sizeof(float) ) -DECLARE_FIELD_SIZE( FIELD_VECTOR2D, 2 * sizeof(float) ) -DECLARE_FIELD_SIZE( FIELD_QUATERNION, 4 * sizeof(float)) -DECLARE_FIELD_SIZE( FIELD_INTEGER, sizeof(int)) -DECLARE_FIELD_SIZE( FIELD_BOOLEAN, sizeof(char)) -DECLARE_FIELD_SIZE( FIELD_SHORT, sizeof(short)) -DECLARE_FIELD_SIZE( FIELD_CHARACTER, sizeof(char)) -DECLARE_FIELD_SIZE( FIELD_COLOR32, sizeof(int)) -DECLARE_FIELD_SIZE( FIELD_CLASSPTR, sizeof(int)) -DECLARE_FIELD_SIZE( FIELD_EHANDLE, sizeof(int)) -DECLARE_FIELD_SIZE( FIELD_EDICT, sizeof(int)) -DECLARE_FIELD_SIZE( FIELD_POSITION_VECTOR, 3 * sizeof(float)) -DECLARE_FIELD_SIZE( FIELD_TIME, sizeof(float)) -DECLARE_FIELD_SIZE( FIELD_TICK, sizeof(int)) -DECLARE_FIELD_SIZE( FIELD_MODELNAME, sizeof(int)) -DECLARE_FIELD_SIZE( FIELD_SOUNDNAME, sizeof(int)) -DECLARE_FIELD_SIZE( FIELD_INPUT, sizeof(int)) -DECLARE_FIELD_SIZE( FIELD_FUNCTION, sizeof(int *)) -DECLARE_FIELD_SIZE( FIELD_VMATRIX, 16 * sizeof(float)) -DECLARE_FIELD_SIZE( FIELD_VMATRIX_WORLDSPACE, 16 * sizeof(float)) -DECLARE_FIELD_SIZE( FIELD_MATRIX3X4_WORLDSPACE, 12 * sizeof(float)) -DECLARE_FIELD_SIZE( FIELD_INTERVAL, 2 * sizeof( float) ) // NOTE: Must match interval.h definition -DECLARE_FIELD_SIZE( FIELD_MODELINDEX, sizeof(int) ) -DECLARE_FIELD_SIZE( FIELD_MATERIALINDEX, sizeof(int) ) - - -#ifndef offsetof -#define offsetof(s,m) (size_t)&(((s *)0)->m) -#endif - -#define ARRAYSIZE2D(p) (sizeof(p)/sizeof(p[0][0])) -#define SIZE_OF_ARRAY(p) _ARRAYSIZE(p) - -#define _FIELD(name, fieldtype, count, flags, mapname, tolerance) { fieldtype, #name, { offsetof(classNameTypedef, name), 0 }, count, flags, mapname, NULL, NULL, NULL, sizeof( ((classNameTypedef *)0)->name ), NULL, 0, tolerance } -#define _FIELD_NETARRAY(array, i, fieldtype, count, flags, mapname, tolerance) { fieldtype, #array "[" #i "]", { offsetof(classNameTypedef, array) + offsetof(classNameTypedef::NetworkVar_##array, m_Value[i]), 0 }, count, flags, mapname, NULL, NULL, NULL, sizeof( ((classNameTypedef *)0)->array ), NULL, 0, tolerance } -#define DEFINE_FIELD_NULL { FIELD_VOID,0, {0,0},0,0,0,0,0,0} -#define DEFINE_FIELD(name,fieldtype) _FIELD(name, fieldtype, 1, FTYPEDESC_SAVE, NULL, 0 ) -#define DEFINE_KEYFIELD(name,fieldtype, mapname) _FIELD(name, fieldtype, 1, FTYPEDESC_KEY | FTYPEDESC_SAVE, mapname, 0 ) -#define DEFINE_KEYFIELD_NETARRAY(array, i, fieldtype, mapname) _FIELD_NETARRAY(array, i, fieldtype, 1, FTYPEDESC_KEY | FTYPEDESC_SAVE, mapname, 0 ) -#define DEFINE_KEYFIELD_NOT_SAVED(name,fieldtype, mapname)_FIELD(name, fieldtype, 1, FTYPEDESC_KEY, mapname, 0 ) -#define DEFINE_AUTO_ARRAY(name,fieldtype) _FIELD(name, fieldtype, SIZE_OF_ARRAY(((classNameTypedef *)0)->name), FTYPEDESC_SAVE, NULL, 0 ) -#define DEFINE_AUTO_ARRAY_KEYFIELD(name,fieldtype,mapname) _FIELD(name, fieldtype, SIZE_OF_ARRAY(((classNameTypedef *)0)->name), FTYPEDESC_SAVE, mapname, 0 ) -#define DEFINE_ARRAY(name,fieldtype, count) _FIELD(name, fieldtype, count, FTYPEDESC_SAVE, NULL, 0 ) -#define DEFINE_ENTITY_FIELD(name,fieldtype) _FIELD(edict_t, name, fieldtype, 1, FTYPEDESC_KEY | FTYPEDESC_SAVE, #name, 0 ) -#define DEFINE_ENTITY_GLOBAL_FIELD(name,fieldtype) _FIELD(edict_t, name, fieldtype, 1, FTYPEDESC_KEY | FTYPEDESC_SAVE | FTYPEDESC_GLOBAL, #name, 0 ) -#define DEFINE_GLOBAL_FIELD(name,fieldtype) _FIELD(name, fieldtype, 1, FTYPEDESC_GLOBAL | FTYPEDESC_SAVE, NULL, 0 ) -#define DEFINE_GLOBAL_KEYFIELD(name,fieldtype, mapname) _FIELD(name, fieldtype, 1, FTYPEDESC_GLOBAL | FTYPEDESC_KEY | FTYPEDESC_SAVE, mapname, 0 ) -#define DEFINE_CUSTOM_FIELD(name,datafuncs) { FIELD_CUSTOM, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, datafuncs, NULL } -#define DEFINE_CUSTOM_KEYFIELD(name,datafuncs,mapname) { FIELD_CUSTOM, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE | FTYPEDESC_KEY, mapname, datafuncs, NULL } -#define DEFINE_AUTO_ARRAY2D(name,fieldtype) _FIELD(name, fieldtype, ARRAYSIZE2D(((classNameTypedef *)0)->name), FTYPEDESC_SAVE, NULL, 0 ) -// Used by byteswap datadescs -#define DEFINE_BITFIELD(name,fieldtype,bitcount) DEFINE_ARRAY(name,fieldtype,((bitcount+FIELD_BITS(fieldtype)-1)&~(FIELD_BITS(fieldtype)-1)) / FIELD_BITS(fieldtype) ) -#define DEFINE_INDEX(name,fieldtype) _FIELD(name, fieldtype, 1, FTYPEDESC_INDEX, NULL, 0 ) - -#define DEFINE_EMBEDDED( name ) \ - { FIELD_EMBEDDED, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name.m_DataMap), sizeof( ((classNameTypedef *)0)->name ), NULL, 0, 0.0f } - -#define DEFINE_EMBEDDED_OVERRIDE( name, overridetype ) \ - { FIELD_EMBEDDED, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, NULL, NULL, &((overridetype *)0)->m_DataMap, sizeof( ((classNameTypedef *)0)->name ), NULL, 0, 0.0f } - -#define DEFINE_EMBEDDEDBYREF( name ) \ - { FIELD_EMBEDDED, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE | FTYPEDESC_PTR, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( *(((classNameTypedef *)0)->name) ), NULL, 0, 0.0f } - -#define DEFINE_EMBEDDED_ARRAY( name, count ) \ - { FIELD_EMBEDDED, #name, { offsetof(classNameTypedef, name), 0 }, count, FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( ((classNameTypedef *)0)->name[0] ), NULL, 0, 0.0f } - -#define DEFINE_EMBEDDED_AUTO_ARRAY( name ) \ - { FIELD_EMBEDDED, #name, { offsetof(classNameTypedef, name), 0 }, SIZE_OF_ARRAY( ((classNameTypedef *)0)->name ), FTYPEDESC_SAVE, NULL, NULL, NULL, &(((classNameTypedef *)0)->name->m_DataMap), sizeof( ((classNameTypedef *)0)->name[0] ), NULL, 0, 0.0f } - -#ifndef NO_ENTITY_PREDICTION - -#define DEFINE_PRED_TYPEDESCRIPTION( name, fieldtype ) \ - { FIELD_EMBEDDED, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE, NULL, NULL, NULL, &fieldtype::m_PredMap } - -#define DEFINE_PRED_TYPEDESCRIPTION_PTR( name, fieldtype ) \ - { FIELD_EMBEDDED, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_SAVE | FTYPEDESC_PTR, NULL, NULL, NULL, &fieldtype::m_PredMap } - -#else - -#define DEFINE_PRED_TYPEDESCRIPTION( name, fieldtype ) DEFINE_FIELD_NULL -#define DEFINE_PRED_TYPEDESCRIPTION_PTR( name, fieldtype ) DEFINE_FIELD_NULL - -#endif - -// Extensions to datamap.h macros for predicted entities only -#define DEFINE_PRED_FIELD(name,fieldtype, flags) _FIELD(name, fieldtype, 1, flags, NULL, 0.0f ) -#define DEFINE_PRED_ARRAY(name,fieldtype, count,flags) _FIELD(name, fieldtype, count, flags, NULL, 0.0f ) -#define DEFINE_FIELD_NAME(localname,netname,fieldtype) _FIELD(localname, fieldtype, 1, 0, #netname, 0.0f ) -// Predictable macros, which include a tolerance for floating point values... -#define DEFINE_PRED_FIELD_TOL(name,fieldtype, flags,tolerance) _FIELD(name, fieldtype, 1, flags, NULL, tolerance ) -#define DEFINE_PRED_ARRAY_TOL(name,fieldtype, count,flags,tolerance) _FIELD(name, fieldtype, count, flags, NULL, tolerance) -#define DEFINE_FIELD_NAME_TOL(localname,netname,fieldtolerance) _FIELD(localname, fieldtype, 1, 0, #netname, tolerance ) - -//#define DEFINE_DATA( name, fieldextname, flags ) _FIELD(name, fieldtype, 1, flags, extname ) - -// INPUTS -#define DEFINE_INPUT( name, fieldtype, inputname ) { fieldtype, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_INPUT | FTYPEDESC_SAVE | FTYPEDESC_KEY, inputname, NULL, NULL, NULL, sizeof( ((classNameTypedef *)0)->name ) } -#define DEFINE_INPUTFUNC( fieldtype, inputname, inputfunc ) { fieldtype, #inputfunc, { 0, 0 }, 1, FTYPEDESC_INPUT, inputname, NULL, static_cast (&classNameTypedef::inputfunc) } - -// OUTPUTS -// the variable 'name' MUST BE derived from CBaseOutput -// we know the output type from the variable itself, so it doesn't need to be specified here -class ISaveRestoreOps; -extern ISaveRestoreOps *eventFuncs; -#define DEFINE_OUTPUT( name, outputname ) { FIELD_CUSTOM, #name, { offsetof(classNameTypedef, name), 0 }, 1, FTYPEDESC_OUTPUT | FTYPEDESC_SAVE | FTYPEDESC_KEY, outputname, eventFuncs } - -// replaces EXPORT table for portability and non-DLL based systems (xbox) -#define DEFINE_FUNCTION_RAW( function, func_type ) { FIELD_VOID, nameHolder.GenerateName(#function), { 0, 0 }, 1, FTYPEDESC_FUNCTIONTABLE, NULL, NULL, (inputfunc_t)((func_type)(&classNameTypedef::function)) } -#define DEFINE_FUNCTION( function ) DEFINE_FUNCTION_RAW( function, inputfunc_t ) - - -#define FTYPEDESC_GLOBAL 0x0001 // This field is masked for global entity save/restore -#define FTYPEDESC_SAVE 0x0002 // This field is saved to disk -#define FTYPEDESC_KEY 0x0004 // This field can be requested and written to by string name at load time -#define FTYPEDESC_INPUT 0x0008 // This field can be written to by string name at run time, and a function called -#define FTYPEDESC_OUTPUT 0x0010 // This field propogates it's value to all targets whenever it changes -#define FTYPEDESC_FUNCTIONTABLE 0x0020 // This is a table entry for a member function pointer -#define FTYPEDESC_PTR 0x0040 // This field is a pointer, not an embedded object -#define FTYPEDESC_OVERRIDE 0x0080 // The field is an override for one in a base class (only used by prediction system for now) - -// Flags used by other systems (e.g., prediction system) -#define FTYPEDESC_INSENDTABLE 0x0100 // This field is present in a network SendTable -#define FTYPEDESC_PRIVATE 0x0200 // The field is local to the client or server only (not referenced by prediction code and not replicated by networking) -#define FTYPEDESC_NOERRORCHECK 0x0400 // The field is part of the prediction typedescription, but doesn't get compared when checking for errors - -#define FTYPEDESC_MODELINDEX 0x0800 // The field is a model index (used for debugging output) - -#define FTYPEDESC_INDEX 0x1000 // The field is an index into file data, used for byteswapping. - -// These flags apply to C_BasePlayer derived objects only -#define FTYPEDESC_VIEW_OTHER_PLAYER 0x2000 // By default you can only view fields on the local player (yourself), - // but if this is set, then we allow you to see fields on other players -#define FTYPEDESC_VIEW_OWN_TEAM 0x4000 // Only show this data if the player is on the same team as the local player -#define FTYPEDESC_VIEW_NEVER 0x8000 // Never show this field to anyone, even the local player (unusual) - -#define TD_MSECTOLERANCE 0.001f // This is a FIELD_FLOAT and should only be checked to be within 0.001 of the networked info - -struct typedescription_t; - - -class ISaveRestoreOps; - -// -// Function prototype for all input handlers. -// -typedef void (CBaseEntity::*inputfunc_t)(inputdata_t &data); - -struct datamap_t; -struct typedescription_t; - -enum -{ - TD_OFFSET_NORMAL = 0, - TD_OFFSET_PACKED = 1, - - // Must be last - TD_OFFSET_COUNT, -}; - -struct typedescription_t -{ - fieldtype_t fieldType; - const char *fieldName; - int fieldOffset[ TD_OFFSET_COUNT ]; // 0 == normal, 1 == packed offset - unsigned short fieldSize; - short flags; - // the name of the variable in the map/fgd data, or the name of the action - const char *externalName; - // pointer to the function set for save/restoring of custom data types - ISaveRestoreOps *pSaveRestoreOps; - // for associating function with string names - inputfunc_t inputFunc; - // For embedding additional datatables inside this one - datamap_t *td; - - // Stores the actual member variable size in bytes - int fieldSizeInBytes; - - // FTYPEDESC_OVERRIDE point to first baseclass instance if chains_validated has occurred - struct typedescription_t *override_field; - - // Used to track exclusion of baseclass fields - int override_count; - - // Tolerance for field errors for float fields - float fieldTolerance; -}; - - -//----------------------------------------------------------------------------- -// Purpose: stores the list of objects in the hierarchy -// used to iterate through an object's data descriptions -//----------------------------------------------------------------------------- -struct datamap_t -{ - typedescription_t *dataDesc; - int dataNumFields; - char const *dataClassName; - datamap_t *baseMap; - - bool chains_validated; - // Have the "packed" offsets been computed - bool packed_offsets_computed; - int packed_size; - -#if defined( _DEBUG ) - bool bValidityChecked; -#endif // _DEBUG -}; - - -//----------------------------------------------------------------------------- -// -// Macros used to implement datadescs -// -#define DECLARE_SIMPLE_DATADESC() \ - static datamap_t m_DataMap; \ - static datamap_t *GetBaseMap(); \ - template friend void DataMapAccess(T *, datamap_t **p); \ - template friend datamap_t *DataMapInit(T *); - -#define DECLARE_DATADESC() \ - DECLARE_SIMPLE_DATADESC() \ - virtual datamap_t *GetDataDescMap( void ); - -#define BEGIN_DATADESC( className ) \ - datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \ - datamap_t *className::GetDataDescMap( void ) { return &m_DataMap; } \ - datamap_t *className::GetBaseMap() { datamap_t *pResult; DataMapAccess((BaseClass *)NULL, &pResult); return pResult; } \ - BEGIN_DATADESC_GUTS( className ) - -#define BEGIN_DATADESC_NO_BASE( className ) \ - datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \ - datamap_t *className::GetDataDescMap( void ) { return &m_DataMap; } \ - datamap_t *className::GetBaseMap() { return NULL; } \ - BEGIN_DATADESC_GUTS( className ) - -#define BEGIN_SIMPLE_DATADESC( className ) \ - datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \ - datamap_t *className::GetBaseMap() { return NULL; } \ - BEGIN_DATADESC_GUTS( className ) - -#define BEGIN_SIMPLE_DATADESC_( className, BaseClass ) \ - datamap_t className::m_DataMap = { 0, 0, #className, NULL }; \ - datamap_t *className::GetBaseMap() { datamap_t *pResult; DataMapAccess((BaseClass *)NULL, &pResult); return pResult; } \ - BEGIN_DATADESC_GUTS( className ) - -#define BEGIN_DATADESC_GUTS( className ) \ - template datamap_t *DataMapInit(T *); \ - template <> datamap_t *DataMapInit( className * ); \ - namespace className##_DataDescInit \ - { \ - datamap_t *g_DataMapHolder = DataMapInit( (className *)NULL ); /* This can/will be used for some clean up duties later */ \ - } \ - \ - template <> datamap_t *DataMapInit( className * ) \ - { \ - typedef className classNameTypedef; \ - static CDatadescGeneratedNameHolder nameHolder(#className); \ - className::m_DataMap.baseMap = className::GetBaseMap(); \ - static typedescription_t dataDesc[] = \ - { \ - { FIELD_VOID,0, {0,0},0,0,0,0,0,0}, /* so you can define "empty" tables */ - -#define END_DATADESC() \ - }; \ - \ - if ( sizeof( dataDesc ) > sizeof( dataDesc[0] ) ) \ - { \ - classNameTypedef::m_DataMap.dataNumFields = SIZE_OF_ARRAY( dataDesc ) - 1; \ - classNameTypedef::m_DataMap.dataDesc = &dataDesc[1]; \ - } \ - else \ - { \ - classNameTypedef::m_DataMap.dataNumFields = 1; \ - classNameTypedef::m_DataMap.dataDesc = dataDesc; \ - } \ - return &classNameTypedef::m_DataMap; \ - } - -// used for when there is no data description -#define IMPLEMENT_NULL_SIMPLE_DATADESC( derivedClass ) \ - BEGIN_SIMPLE_DATADESC( derivedClass ) \ - END_DATADESC() - -#define IMPLEMENT_NULL_SIMPLE_DATADESC_( derivedClass, baseClass ) \ - BEGIN_SIMPLE_DATADESC_( derivedClass, baseClass ) \ - END_DATADESC() - -#define IMPLEMENT_NULL_DATADESC( derivedClass ) \ - BEGIN_DATADESC( derivedClass ) \ - END_DATADESC() - -// helps get the offset of a bitfield -#define BEGIN_BITFIELD( name ) \ - union \ - { \ - char name; \ - struct \ - { - -#define END_BITFIELD() \ - }; \ - }; - -//----------------------------------------------------------------------------- -// Forward compatability with potential seperate byteswap datadescs - -#define DECLARE_BYTESWAP_DATADESC() DECLARE_SIMPLE_DATADESC() -#define BEGIN_BYTESWAP_DATADESC(name) BEGIN_SIMPLE_DATADESC(name) -#define BEGIN_BYTESWAP_DATADESC_(name,base) BEGIN_SIMPLE_DATADESC_(name,base) -#define END_BYTESWAP_DATADESC() END_DATADESC() - -//----------------------------------------------------------------------------- - -template -inline void DataMapAccess(T *ignored, datamap_t **p) -{ - *p = &T::m_DataMap; -} - -//----------------------------------------------------------------------------- - -class CDatadescGeneratedNameHolder -{ -public: - CDatadescGeneratedNameHolder( const char *pszBase ) - : m_pszBase(pszBase) - { - m_nLenBase = strlen( m_pszBase ); - } - - ~CDatadescGeneratedNameHolder() - { - for ( int i = 0; i < m_Names.Count(); i++ ) - { - delete m_Names[i]; - } - } - - const char *GenerateName( const char *pszIdentifier ) - { - char *pBuf = new char[m_nLenBase + strlen(pszIdentifier) + 1]; - strcpy( pBuf, m_pszBase ); - strcat( pBuf, pszIdentifier ); - m_Names.AddToTail( pBuf ); - return pBuf; - } - -private: - const char *m_pszBase; - size_t m_nLenBase; - CUtlVector m_Names; -}; - -//----------------------------------------------------------------------------- - -#include "tier0/memdbgoff.h" - -#endif // DATAMAP_H diff --git a/public/datamodel/attributeflags.h b/public/datamodel/attributeflags.h deleted file mode 100644 index 8d2d32dfe..000000000 --- a/public/datamodel/attributeflags.h +++ /dev/null @@ -1,35 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef ATTRIBUTEFLAGS_H -#define ATTRIBUTEFLAGS_H - -#ifdef _WIN32 -#pragma once -#endif - -enum -{ - // NOTE: The first 5 flags bits are reserved for attribute type - FATTRIB_TYPEMASK = 0x1F, - - FATTRIB_READONLY = (1<<5), // Don't allow editing value in editors - FATTRIB_DONTSAVE = (1<<6), // Don't persist to .dmx file - FATTRIB_DIRTY = (1<<7), // Indicates the attribute has been changed since the resolve phase - FATTRIB_HAS_CALLBACK = (1<<8), // Indicates that this will notify its owner and/or other elements when it changes - FATTRIB_EXTERNAL = (1<<9), // Indicates this attribute's data is externally owned (in a CDmElement somewhere) - FATTRIB_TOPOLOGICAL = (1<<10), // Indicates this attribute effects the scene's topology (ie it's an attribute name or element) - FATTRIB_MUSTCOPY = (1<<11), // parent element must make a new copy during CopyInto, even for shallow copy - FATTRIB_NEVERCOPY = (1<<12), // parent element shouldn't make a new copy during CopyInto, even for deep copy - FATTRIB_STANDARD = (1<<13), // This flag is set if it's a "standard" attribute, namely "name" - FATTRIB_USERDEFINED = (1<<14), // This flag is used to sort attributes in the element properties view. User defined flags come last. - FATTRIB_NODUPLICATES = (1<<15),// For element array types, disallows duplicate values from being inserted into the array. - FATTRIB_HAS_ARRAY_CALLBACK = (1<<16), // Indicates that this will notify its owner and/or other elements array elements changes. Note that when elements shift (say, inserting at head, or fast remove), callbacks are not executed for these elements. - FATTRIB_HAS_PRE_CALLBACK = (1<<17), // Indicates that this will notify its owner and/or other elements right before it changes - FATTRIB_OPERATOR_DIRTY = (1<<18),// Used and cleared only by operator phase of datamodel -}; - -#endif // ATTRIBUTEFLAGS_H diff --git a/public/datamodel/dmattribute.h b/public/datamodel/dmattribute.h deleted file mode 100644 index 48773c505..000000000 --- a/public/datamodel/dmattribute.h +++ /dev/null @@ -1,442 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef DMATTRIBUTE_H -#define DMATTRIBUTE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "datamodel/attributeflags.h" -#include "datamodel/idatamodel.h" -#include "datamodel/dmattributetypes.h" -#include "datamodel/dmvar.h" -#include "tier1/utlhash.h" - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class CDmElement; -class CUtlBuffer; - - -//----------------------------------------------------------------------------- -// Used for attribute change callbacks -//----------------------------------------------------------------------------- -typedef unsigned short DmMailingList_t; -enum -{ - DMMAILINGLIST_INVALID = (DmMailingList_t)~0 -}; - - -//----------------------------------------------------------------------------- -// Purpose: A general purpose pAttribute. Eventually will be extensible to arbitrary user types -//----------------------------------------------------------------------------- -class CDmAttribute -{ -public: - // Returns the type - DmAttributeType_t GetType() const; - const char *GetTypeString() const; - template< class T > bool IsA() const; - - // Returns the name. NOTE: The utlsymbol - // can be turned into a string by using g_pDataModel->String(); - const char *GetName() const; - UtlSymId_t GetNameSymbol() const; - void SetName( const char *newName ); - - // Gets the attribute value - // NOTE: GetValueUntyped is used with GetType() for use w/ SetValue( type, void* ) - template< class T > const T& GetValue() const; - template< class T > const T& GetValue( const T& defaultValue ) const; - const char *GetValueString() const; - template< class E > E *GetValueElement() const; - const void *GetValueUntyped() const; - - // Sets the attribute value - template< class T > void SetValue( const T &value ); - template< class E > void SetValue( E* pValue ); - void SetValue( const void *pValue, size_t nSize ); - - // Copies w/ type conversion (if possible) from another attribute - void SetValue( const CDmAttribute *pAttribute ); - void SetValue( CDmAttribute *pAttribute ); - void SetValue( DmAttributeType_t valueType, const void *pValue ); - - // Sets the attribute to its default value based on its type - void SetToDefaultValue(); - - // Convert to and from string - void SetValueFromString( const char *pValue ); - const char *GetValueAsString( char *pBuffer, size_t nBufLen ) const; - - // Used for element and element array attributes; it specifies which type of - // elements are valid to be referred to by this attribute - void SetElementTypeSymbol( UtlSymId_t typeSymbol ); - UtlSymId_t GetElementTypeSymbol() const; - - // Returns the next attribute - CDmAttribute *NextAttribute(); - const CDmAttribute *NextAttribute() const; - - // Returns the owner - CDmElement *GetOwner(); - - // Methods related to flags - void AddFlag( int flags ); - void RemoveFlag( int flags ); - void ClearFlags(); - int GetFlags() const; - bool IsFlagSet( int flags ) const; - - // Serialization - bool Serialize( CUtlBuffer &buf ) const; - bool Unserialize( CUtlBuffer &buf ); - - // Serialization of a single element. - // First version of UnserializeElement adds to tail if it worked - // Second version overwrites, but does not add, the element at the specified index - bool SerializeElement( int nElement, CUtlBuffer &buf ) const; - bool UnserializeElement( CUtlBuffer &buf ); - bool UnserializeElement( int nElement, CUtlBuffer &buf ); - - // Does this attribute serialize on multiple lines? - bool SerializesOnMultipleLines() const; - - // Get the attribute/create an attribute handle - DmAttributeHandle_t GetHandle( bool bCreate = true ); - - // Notify external elements upon change ( Calls OnAttributeChanged ) - // Pass false here to stop notification - void NotifyWhenChanged( DmElementHandle_t h, bool bNotify ); - - // estimate memory overhead - int EstimateMemoryUsage( TraversalDepth_t depth ) const; - -private: - // Class factory - static CDmAttribute *CreateAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName ); - static CDmAttribute *CreateExternalAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName, void *pExternalMemory ); - static void DestroyAttribute( CDmAttribute *pAttribute ); - - // Constructor, destructor - CDmAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName ); - CDmAttribute( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName, void *pMemory ); - ~CDmAttribute(); - - // Used when constructing CDmAttributes - void Init( CDmElement *pOwner, DmAttributeType_t type, const char *pAttributeName ); - - // Used when shutting down, indicates DmAttributeHandle_t referring to this are invalid - void InvalidateHandle(); - - // Used when shutting down, indicates no more change notifications will be sent to listening elements - void CleanupMailingList(); - - // Called when the attribute changes - void PreChanged(); - void OnChanged( bool bArrayCountChanged = false, bool bIsTopological = false ); - - // Is modification allowed in this phase? - bool ModificationAllowed() const; - - // Mark the attribute as being dirty - bool MarkDirty(); - - // Is the data inline in a containing element class? - bool IsDataInline() const; - - // Allocates, frees internal data storage - void CreateAttributeData(); - void DeleteAttributeData(); - - // Gets at the internal data storage - void* GetAttributeData(); - const void* GetAttributeData() const; - template < class T > typename CDmAttributeInfo< T >::StorageType_t* GetData(); - template < class T > const typename CDmAttributeInfo< T >::StorageType_t* GetData() const; - template < class T > typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* GetArrayData(); - template < class T > const typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* GetArrayData() const; - - // Used by CDmElement to manage the list of attributes it owns - CDmAttribute **GetNextAttributeRef(); - - // Implementational function used for memory consumption estimation computation - int EstimateMemoryUsageInternal( CUtlHash< DmElementHandle_t > &visited, TraversalDepth_t depth, int *pCategories ) const; - - // Called by elements after unserialization of their attributes is complete - void OnUnserializationFinished(); - - template< class T > bool IsTypeConvertable() const; - template< class T > bool ShouldModify( const T& src ); - template< class T > void CopyData( const T& src ); - template< class T > void CopyDataOut( T& dest ) const; - -private: - CDmAttribute *m_pNext; - void *m_pData; - CDmElement *m_pOwner; - int m_nFlags; - DmAttributeHandle_t m_Handle; - CUtlSymbol m_Name; - DmMailingList_t m_hMailingList; - - friend class CDmElement; - friend class CDmAttributeAccessor; - template< class T > friend class CDmrElementArray; - template< class E > friend class CDmrElementArrayConst; - template< class T > friend class CDmaArrayAccessor; - template< class T, class B > friend class CDmrDecorator; - template< class T, class B > friend class CDmrDecoratorConst; - template< class T > friend class CDmArrayAttributeOp; -}; - - -//----------------------------------------------------------------------------- -// Inline methods -//----------------------------------------------------------------------------- -inline DmAttributeType_t CDmAttribute::GetType() const -{ - return (DmAttributeType_t)( m_nFlags & FATTRIB_TYPEMASK ); -} - -template< class T > inline bool CDmAttribute::IsA() const -{ - return GetType() == CDmAttributeInfo< T >::AttributeType(); -} - -inline const char *CDmAttribute::GetName() const -{ - return g_pDataModel->GetString( m_Name ); -} - -inline UtlSymId_t CDmAttribute::GetNameSymbol() const -{ - return m_Name; -} - - -//----------------------------------------------------------------------------- -// Iteration -//----------------------------------------------------------------------------- -inline CDmAttribute *CDmAttribute::NextAttribute() -{ - return m_pNext; -} - -inline const CDmAttribute *CDmAttribute::NextAttribute() const -{ - return m_pNext; -} - - -//----------------------------------------------------------------------------- -// Returns the owner -//----------------------------------------------------------------------------- -inline CDmElement *CDmAttribute::GetOwner() -{ - return m_pOwner; -} - - -//----------------------------------------------------------------------------- -// Value getting methods -//----------------------------------------------------------------------------- -template< class T > -inline const T& CDmAttribute::GetValue( const T& defaultValue ) const -{ - if ( GetType() == CDmAttributeInfo< T >::ATTRIBUTE_TYPE ) - return *reinterpret_cast< const T* >( m_pData ); - - if ( IsTypeConvertable< T >() ) - { - static T tempVal; - CopyDataOut( tempVal ); - return tempVal; - } - - Assert( 0 ); - return defaultValue; -} - -template< class T > -inline const T& CDmAttribute::GetValue() const -{ - static CDmaVar< T > defaultVal; - return GetValue( defaultVal.Get() ); -} - -inline const char *CDmAttribute::GetValueString() const -{ - Assert( GetType() == AT_STRING ); - if ( GetType() != AT_STRING ) - return NULL; - - return GetValue< CUtlString >(); -} - -// used with GetType() for use w/ SetValue( type, void* ) -inline const void* CDmAttribute::GetValueUntyped() const -{ - return m_pData; -} - -#ifndef _LINUX -template< class E > -inline E* CDmAttribute::GetValueElement() const -{ - Assert( GetType() == AT_ELEMENT ); - if ( GetType() == AT_ELEMENT ) - return GetElement( this->GetValue( ) ); - return NULL; -} -#endif - - -//----------------------------------------------------------------------------- -// Value setting methods -//----------------------------------------------------------------------------- -template< class E > -inline void CDmAttribute::SetValue( E* pValue ) -{ - Assert( GetType() == AT_ELEMENT ); - if ( GetType() == AT_ELEMENT ) - { - SetValue( pValue ? pValue->GetHandle() : DMELEMENT_HANDLE_INVALID ); - } -} - -template<> -inline void CDmAttribute::SetValue( const char *pValue ) -{ - int nLen = pValue ? Q_strlen( pValue ) + 1 : 0; - CUtlString str( pValue, nLen ); - return SetValue( str ); -} - -template<> -inline void CDmAttribute::SetValue( char *pValue ) -{ - return SetValue( (const char *)pValue ); -} - -inline void CDmAttribute::SetValue( const void *pValue, size_t nSize ) -{ - CUtlBinaryBlock buf( pValue, nSize ); - return SetValue( buf ); -} - - -//----------------------------------------------------------------------------- -// Methods related to flags -//----------------------------------------------------------------------------- -inline void CDmAttribute::AddFlag( int nFlags ) -{ - m_nFlags |= nFlags; -} - -inline void CDmAttribute::RemoveFlag( int nFlags ) -{ - m_nFlags &= ~nFlags; -} - -inline void CDmAttribute::ClearFlags() -{ - m_nFlags = 0; -} - -inline int CDmAttribute::GetFlags() const -{ - return m_nFlags; -} - -inline bool CDmAttribute::IsFlagSet( int nFlags ) const -{ - return ( nFlags & m_nFlags ) ? true : false; -} - -inline bool CDmAttribute::IsDataInline() const -{ - return !IsFlagSet(FATTRIB_EXTERNAL); -} - - -//----------------------------------------------------------------------------- -// Gets at the internal data storage -//----------------------------------------------------------------------------- -inline void* CDmAttribute::GetAttributeData() -{ - return m_pData; -} - -inline const void* CDmAttribute::GetAttributeData() const -{ - return m_pData; -} - -template < class T > -inline typename CDmAttributeInfo< T >::StorageType_t* CDmAttribute::GetData() -{ - return ( typename CDmAttributeInfo< T >::StorageType_t* )m_pData; -} - -template < class T > -inline typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* CDmAttribute::GetArrayData() -{ - return ( typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* )m_pData; -} - -template < class T > -inline const typename CDmAttributeInfo< T >::StorageType_t* CDmAttribute::GetData() const -{ - return ( const typename CDmAttributeInfo< T >::StorageType_t* )m_pData; -} - -template < class T > -inline const typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* CDmAttribute::GetArrayData() const -{ - return ( const typename CDmAttributeInfo< CUtlVector< T > >::StorageType_t* )m_pData; -} - - -//----------------------------------------------------------------------------- -// Used by CDmElement to manage the list of attributes it owns -//----------------------------------------------------------------------------- -inline CDmAttribute **CDmAttribute::GetNextAttributeRef() -{ - return &m_pNext; -} - - -//----------------------------------------------------------------------------- -// helper function for determining which attributes/elements to traverse during copy/find/save/etc. -//----------------------------------------------------------------------------- -inline bool ShouldTraverse( const CDmAttribute *pAttr, TraversalDepth_t depth ) -{ - switch ( depth ) - { - case TD_NONE: - return false; - - case TD_SHALLOW: - if ( !pAttr->IsFlagSet( FATTRIB_MUSTCOPY ) ) - return false; - // fall-through intentional - case TD_DEEP: - if ( pAttr->IsFlagSet( FATTRIB_NEVERCOPY ) ) - return false; - // fall-through intentional - case TD_ALL: - return true; - } - - Assert( 0 ); - return false; -} - -#endif // DMATTRIBUTE_H diff --git a/public/datamodel/dmattributetypes.h b/public/datamodel/dmattributetypes.h deleted file mode 100644 index 48d7707f6..000000000 --- a/public/datamodel/dmattributetypes.h +++ /dev/null @@ -1,315 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef DMATTRIBUTETYPES_H -#define DMATTRIBUTETYPES_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/utlvector.h" -#include "tier1/utlstring.h" -#include "tier1/uniqueid.h" -#include "Color.h" -#include "mathlib/vector2d.h" -#include "mathlib/vector.h" -#include "mathlib/vector4d.h" -#include "mathlib/vmatrix.h" -#include "datamodel/dmelementhandle.h" -#include "tier1/utlsymbol.h" - - -//----------------------------------------------------------------------------- -// Object Id -//----------------------------------------------------------------------------- -typedef UniqueId_t DmObjectId_t; - - -//----------------------------------------------------------------------------- -// Necessary for template specialization for AT_UNKNOWN -//----------------------------------------------------------------------------- -struct DmUnknownAttribute_t -{ - bool operator==( const DmUnknownAttribute_t& src ) const { return true; } -}; - - -//----------------------------------------------------------------------------- -// Element array -//----------------------------------------------------------------------------- -struct DmElementAttribute_t -{ - DmElementAttribute_t() : m_ElementType( UTL_INVAL_SYMBOL ) {} - - operator DmElementHandle_t&() { return m_Handle; } - operator const DmElementHandle_t&() const { return m_Handle; } - - DmElementHandle_t m_Handle; - UtlSymId_t m_ElementType; -}; - -struct DmElementArray_t : public CUtlVector< DmElementHandle_t > -{ - DmElementArray_t() : m_ElementType( UTL_INVAL_SYMBOL ) {} - - UtlSymId_t m_ElementType; -}; - - -//----------------------------------------------------------------------------- -// Attribute chunk type enum -//----------------------------------------------------------------------------- -enum DmAttributeType_t -{ - AT_UNKNOWN = 0, - - AT_FIRST_VALUE_TYPE, - - AT_ELEMENT = AT_FIRST_VALUE_TYPE, - AT_INT, - AT_FLOAT, - AT_BOOL, - AT_STRING, - AT_VOID, - AT_OBJECTID, - AT_COLOR, //rgba - AT_VECTOR2, - AT_VECTOR3, - AT_VECTOR4, - AT_QANGLE, - AT_QUATERNION, - AT_VMATRIX, - - AT_FIRST_ARRAY_TYPE, - - AT_ELEMENT_ARRAY = AT_FIRST_ARRAY_TYPE, - AT_INT_ARRAY, - AT_FLOAT_ARRAY, - AT_BOOL_ARRAY, - AT_STRING_ARRAY, - AT_VOID_ARRAY, - AT_OBJECTID_ARRAY, - AT_COLOR_ARRAY, - AT_VECTOR2_ARRAY, - AT_VECTOR3_ARRAY, - AT_VECTOR4_ARRAY, - AT_QANGLE_ARRAY, - AT_QUATERNION_ARRAY, - AT_VMATRIX_ARRAY, - AT_TYPE_COUNT, -}; - - -inline bool IsValueType( DmAttributeType_t type ) -{ - return type >= AT_FIRST_VALUE_TYPE && type < AT_FIRST_ARRAY_TYPE; -} - -inline bool IsArrayType( DmAttributeType_t type ) -{ - return type >= AT_FIRST_ARRAY_TYPE && type < AT_TYPE_COUNT; -} - -inline bool IsTopological( DmAttributeType_t type ) -{ - return type == AT_ELEMENT || type == AT_ELEMENT_ARRAY; -} - -inline DmAttributeType_t ValueTypeToArrayType( DmAttributeType_t type ) -{ - Assert( IsValueType( type ) ); - return ( DmAttributeType_t )( ( type - AT_FIRST_VALUE_TYPE ) + AT_FIRST_ARRAY_TYPE ); -} - -inline DmAttributeType_t ArrayTypeToValueType( DmAttributeType_t type ) -{ - Assert( IsArrayType( type ) ); - return ( DmAttributeType_t )( ( type - AT_FIRST_ARRAY_TYPE ) + AT_FIRST_VALUE_TYPE ); -} - -inline int NumComponents( DmAttributeType_t type ) -{ - switch ( type ) - { - case AT_BOOL: - case AT_INT: - case AT_FLOAT: - return 1; - - case AT_VECTOR2: - return 2; - - case AT_VECTOR3: - case AT_QANGLE: - return 3; - - case AT_COLOR: //rgba - case AT_VECTOR4: - case AT_QUATERNION: - return 4; - - case AT_VMATRIX: - return 16; - - case AT_ELEMENT: - case AT_STRING: - case AT_VOID: - case AT_OBJECTID: - default: - return 0; - } -} - -template< typename T > -inline float GetComponent( const T &value, int i ) -{ - Assert( 0 ); - return 0.0f; -} - -template <> inline float GetComponent( const bool &value, int i ) -{ - Assert( i == 0 ); - return value ? 1.0f : 0.0f; -} - -template <> inline float GetComponent( const int &value, int i ) -{ - Assert( i == 0 ); - return float( value ); -} - -template <> inline float GetComponent( const float &value, int i ) -{ - Assert( i == 0 ); - return value; -} - -template <> inline float GetComponent( const Vector2D &value, int i ) -{ - return value[ i ]; -} - -template <> inline float GetComponent( const Vector &value, int i ) -{ - return value[ i ]; -} - -template <> inline float GetComponent( const QAngle &value, int i ) -{ - return value[ i ]; -} - -template <> inline float GetComponent( const Color &value, int i ) -{ - return value[ i ]; -} - -template <> inline float GetComponent( const Vector4D &value, int i ) -{ - return value[ i ]; -} - -template <> inline float GetComponent( const Quaternion &value, int i ) -{ - return value[ i ]; -} - -template <> inline float GetComponent( const VMatrix &value, int i ) -{ - return value.Base()[ i ]; -} - - -//----------------------------------------------------------------------------- -// Attribute info... -//----------------------------------------------------------------------------- -template -class CDmAttributeInfo -{ -public: - enum { ATTRIBUTE_TYPE = AT_UNKNOWN }; - - typedef T StorageType_t; - - static DmAttributeType_t AttributeType() - { - return AT_UNKNOWN; - } - - static const char *AttributeTypeName() - { - return "unknown"; - } - - static void SetDefaultValue( T& value ) - { - Assert(0); - } -}; - - -#define DECLARE_ATTRIBUTE_TYPE_INTERNAL( _className, _storageType, _attributeType, _attributeName, _defaultSetStatement ) \ - template< > class CDmAttributeInfo< _className > \ - { \ - public: \ - enum { ATTRIBUTE_TYPE = _attributeType }; \ - typedef _storageType StorageType_t; \ - static DmAttributeType_t AttributeType() { return _attributeType; } \ - static const char *AttributeTypeName() { return _attributeName; } \ - static void SetDefaultValue( _className& value ) { _defaultSetStatement } \ - }; \ - -#define DECLARE_ATTRIBUTE_ARRAY_TYPE_INTERNAL( _className, _storageType, _attributeType, _attributeName ) \ - template< > class CDmAttributeInfo< CUtlVector<_className> > \ - { \ - public: \ - enum { ATTRIBUTE_TYPE = _attributeType }; \ - typedef _storageType StorageType_t; \ - static DmAttributeType_t AttributeType() { return _attributeType; } \ - static const char *AttributeTypeName() { return _attributeName; } \ - static void SetDefaultValue( CUtlVector< _className >& value ) { value.RemoveAll(); } \ - }; \ - -#define DECLARE_ATTRIBUTE_TYPE( _className, _attributeType, _attributeName, _defaultSetStatement ) \ - DECLARE_ATTRIBUTE_TYPE_INTERNAL( _className, _className, _attributeType, _attributeName, _defaultSetStatement ) - -#define DECLARE_ATTRIBUTE_ARRAY_TYPE( _className, _attributeType, _attributeName )\ - DECLARE_ATTRIBUTE_ARRAY_TYPE_INTERNAL( _className, CUtlVector< _className >, _attributeType, _attributeName ) - -// NOTE: If you add an attribute type here, also add it to the list of DEFINE_ATTRIBUTE_TYPES in dmattribute.cpp -DECLARE_ATTRIBUTE_TYPE( int, AT_INT, "int", value = 0; ) -DECLARE_ATTRIBUTE_TYPE( float, AT_FLOAT, "float", value = 0.0f; ) -DECLARE_ATTRIBUTE_TYPE( bool, AT_BOOL, "bool", value = false; ) -DECLARE_ATTRIBUTE_TYPE( Color, AT_COLOR, "color", value.SetColor( 0, 0, 0, 255 ); ) -DECLARE_ATTRIBUTE_TYPE( Vector2D, AT_VECTOR2, "vector2", value.Init( 0.0f, 0.0f ); ) -DECLARE_ATTRIBUTE_TYPE( Vector, AT_VECTOR3, "vector3", value.Init( 0.0f, 0.0f, 0.0f ); ) -DECLARE_ATTRIBUTE_TYPE( Vector4D, AT_VECTOR4, "vector4", value.Init( 0.0f, 0.0f, 0.0f, 0.0f ); ) -DECLARE_ATTRIBUTE_TYPE( QAngle, AT_QANGLE, "qangle", value.Init( 0.0f, 0.0f, 0.0f ); ) -DECLARE_ATTRIBUTE_TYPE( Quaternion, AT_QUATERNION, "quaternion", value.Init( 0.0f, 0.0f, 0.0f, 1.0f ); ) -DECLARE_ATTRIBUTE_TYPE( VMatrix, AT_VMATRIX, "matrix", MatrixSetIdentity( value ); ) -DECLARE_ATTRIBUTE_TYPE( CUtlString, AT_STRING, "string", value.Set( NULL ); ) -DECLARE_ATTRIBUTE_TYPE( CUtlBinaryBlock, AT_VOID, "binary", value.Set( NULL, 0 ); ) -DECLARE_ATTRIBUTE_TYPE( DmObjectId_t, AT_OBJECTID, "elementid", InvalidateUniqueId( &value ); ) -DECLARE_ATTRIBUTE_TYPE_INTERNAL( DmElementHandle_t, DmElementAttribute_t, AT_ELEMENT, "element", value = DMELEMENT_HANDLE_INVALID; ) - -DECLARE_ATTRIBUTE_ARRAY_TYPE( int, AT_INT_ARRAY, "int_array" ) -DECLARE_ATTRIBUTE_ARRAY_TYPE( float, AT_FLOAT_ARRAY, "float_array" ) -DECLARE_ATTRIBUTE_ARRAY_TYPE( bool, AT_BOOL_ARRAY, "bool_array" ) -DECLARE_ATTRIBUTE_ARRAY_TYPE( Color, AT_COLOR_ARRAY, "color_array" ) -DECLARE_ATTRIBUTE_ARRAY_TYPE( Vector2D, AT_VECTOR2_ARRAY, "vector2_array" ) -DECLARE_ATTRIBUTE_ARRAY_TYPE( Vector, AT_VECTOR3_ARRAY, "vector3_array" ) -DECLARE_ATTRIBUTE_ARRAY_TYPE( Vector4D, AT_VECTOR4_ARRAY, "vector4_array" ) -DECLARE_ATTRIBUTE_ARRAY_TYPE( QAngle, AT_QANGLE_ARRAY, "qangle_array" ) -DECLARE_ATTRIBUTE_ARRAY_TYPE( Quaternion, AT_QUATERNION_ARRAY, "quaternion_array" ) -DECLARE_ATTRIBUTE_ARRAY_TYPE( VMatrix, AT_VMATRIX_ARRAY, "matrix_array" ) -DECLARE_ATTRIBUTE_ARRAY_TYPE( CUtlString, AT_STRING_ARRAY, "string_array" ) -DECLARE_ATTRIBUTE_ARRAY_TYPE( CUtlBinaryBlock, AT_VOID_ARRAY, "binary_array" ) -DECLARE_ATTRIBUTE_ARRAY_TYPE( DmObjectId_t, AT_OBJECTID_ARRAY, "elementid_array" ) -DECLARE_ATTRIBUTE_ARRAY_TYPE_INTERNAL( DmElementHandle_t, DmElementArray_t, AT_ELEMENT_ARRAY, "element_array" ) - - -#endif // DMATTRIBUTETYPES_H diff --git a/public/datamodel/dmattributevar.h b/public/datamodel/dmattributevar.h deleted file mode 100644 index 3f39fd281..000000000 --- a/public/datamodel/dmattributevar.h +++ /dev/null @@ -1,1482 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef DMATTRIBUTEVAR_H -#define DMATTRIBUTEVAR_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "datamodel/dmattribute.h" -#include "tier1/utlvector.h" -#include "Color.h" -#include "mathlib/vector2d.h" -#include "mathlib/vector.h" -#include "mathlib/vector4d.h" -#include "mathlib/vmatrix.h" -#include "datamodel/dmelement.h" - -template< class C, bool D > class CDmeHandle; - -//----------------------------------------------------------------------------- -// Specialization for color -//----------------------------------------------------------------------------- -class CDmaColor : public CDmaVar< Color > -{ -public: - // Set methods - void SetColor( int r, int g, int b, int a = 0 ); - void SetRed( int r ); - void SetGreen( int g ); - void SetBlue( int b ); - void SetAlpha( int a ); - - // Sets the color as a 32-bit integer - void SetRawColor( int color ); - - // Get methods - unsigned char r() const; - unsigned char g() const; - unsigned char b() const; - unsigned char a() const; - const unsigned char &operator[]( int index ) const; -}; - - -//----------------------------------------------------------------------------- -// Specialization for object ids -//----------------------------------------------------------------------------- -class CDmaObjectId : public CDmaVar< DmObjectId_t > -{ -public: - void CreateObjectId( ); - void Invalidate( ); - bool IsValid( ) const; - bool IsEqual( const DmObjectId_t &id ) const; - const DmObjectId_t &operator=( const DmObjectId_t& src ); - const CDmaObjectId& operator=( const CDmaObjectId& src ); - const DmObjectId_t& Set( const DmObjectId_t &src ); -}; - - -//----------------------------------------------------------------------------- -// Specialization for binary block -//----------------------------------------------------------------------------- -class CDmaBinaryBlock : public CDmaVar< CUtlBinaryBlock > -{ -public: - void Get( void *pValue, int nMaxLen ) const; - void Set( const void *pValue, int nLen ); - const void *Get() const; - const unsigned char& operator[]( int i ) const; - - // Returns buffer length - int Length() const; -}; - - -//----------------------------------------------------------------------------- -// Specialization for elements -//----------------------------------------------------------------------------- -template -class CDmaElement : public CDmaVar< DmElementHandle_t > -{ - typedef CDmaVar< DmElementHandle_t > BaseClass; - -public: - // Used to initialize the attribute in an element's OnConstruction method - void InitAndCreate( CDmElement *pOwner, const char *pAttributeName, const char *pElementName = NULL, int flags = 0 ); - void Init( CDmElement *pOwner, const char *pAttributeName, int flags = 0 ); - - // Returns the type of elements allowed into this attribute. UTL_INVAL_SYMBOL allows everything. - UtlSymId_t GetElementType() const; - - // Get/set - void Set( T* pElement ); - T* GetElement() const; - - // Cast - T* operator->() const; - operator T*() const; - - // NULL check - bool operator!() const; - - // Assignment.. wish I knew how to un-inline these methods - template CDmaElement &operator=( S* pElement ) - { - Set( static_cast( pElement ) ); - return *this; - } - - template CDmaElement &operator=( const CDmaElement& src ) - { - Set( static_cast( src.Get() ) ); - return *this; - } - - template bool operator==( const CDmaElement& src ) const - { - return Value() == src.Value(); - } - - template bool operator!=( const CDmaElement& src ) const - { - return Value() != src.Value(); - } -}; - - -//----------------------------------------------------------------------------- -// Can access any array attribute, regardless of type -// See below for type-specific array accessors which have more features -//----------------------------------------------------------------------------- -class CDmrGenericArrayConst -{ -public: - CDmrGenericArrayConst( const CDmAttribute* pAttribute ); - CDmrGenericArrayConst( const CDmElement *pElement, const char *pAttributeName ); - - // Array count - int Count() const; - - // Gets - const void* GetUntyped( int i ) const; - - // String conversion - const char* GetAsString( int i, char *pBuffer, size_t nBufLen ) const; - - const CDmAttribute *GetAttribute() const; - bool IsValid() const; - -protected: - CDmrGenericArrayConst(); - void Init( const CDmAttribute *pAttribute ); - void Init( const CDmElement *pElement, const char *pAttributeName ); - - CDmAttribute *m_pAttribute; -}; - -class CDmrGenericArray : public CDmrGenericArrayConst -{ -public: - CDmrGenericArray( CDmAttribute* pAttribute ); - CDmrGenericArray( CDmElement *pElement, const char *pAttributeName ); - - void EnsureCount( int num ); - - // Sets multiple elements at the same time - int AddToTail(); - void Remove( int elem ); // preserves order, shifts elements - void RemoveAll(); // doesn't deallocate memory - void SetMultiple( int i, int nCount, DmAttributeType_t valueType, const void *pValue ); - void Set( int i, DmAttributeType_t valueType, const void *pValue ); - - // String conversion - void SetFromString( int i, const char *pValue ); - - CDmAttribute *GetAttribute(); - const CDmAttribute *GetAttribute() const; -}; - - -//----------------------------------------------------------------------------- -// Helper template for external array attribute vars -// NOTE: To use this class, don't use CDmaArrayBase directly. Instead, use -// CDmaArray var; <- Instantiate an array attribute var as a member of a element class -// CDmrArray var; <- Used to reference an existing array attribute + read/modify it -// CDmrArrayConst var; <- Used to reference an existing array attribute + read it (no modify) -// -// Also, there is a CDmaStringArray/CDmrStringArray/CDmrStringArrayConst for strings -// and a CDmaElementArray/CDmrElementArray/CDmrElementArrayConst for elements -//----------------------------------------------------------------------------- -template< class T, class B > -class CDmaArrayConstBase : public B -{ -public: - // Accessors - const CUtlVector &Get() const; - const T *Base() const; - - // Iteration - int Count() const; - const T& operator[]( int i ) const; - const T& Element( int i ) const; - const T& Get( int i ) const; - const void* GetUntyped( int i ) const; - bool IsValidIndex( int i ) const; - int InvalidIndex( void ) const; - - // Search - int Find( const T &value ) const; - - // Attribute-related methods - const CDmAttribute *GetAttribute() const; - CDmElement *GetOwner(); - bool IsDirty() const; - -protected: - CDmaArrayConstBase( ); - - CDmAttribute *m_pAttribute; -}; - -template< class T, class B > -class CDmaArrayBase : public CDmaArrayConstBase< T, B > -{ -public: - // Insertion - int AddToTail(); - int InsertBefore( int elem ); - int AddToTail( const T& src ); - int InsertBefore( int elem, const T& src ); - int AddMultipleToTail( int num ); - int InsertMultipleBefore( int elem, int num ); - void EnsureCount( int num ); - - // Element Modification - void Set( int i, const T& value ); - void SetMultiple( int i, int nCount, const T* pValue ); - void Swap( int i, int j ); - - // Copy related methods - void CopyArray( const T *pArray, int size ); - - // this is basically just a faster version of CopyArray which uses pointer swap - // NOTE: This doesn't work for element arrays - void SwapArray( CUtlVector< T > &array ); - - // Removal - void FastRemove( int elem ); - void Remove( int elem ); - void RemoveMultiple( int elem, int num ); - void RemoveAll(); - - // Memory management - void EnsureCapacity( int num ); - void Purge(); - - // Attribute-related methods - CDmAttribute *GetAttribute(); - const CDmAttribute *GetAttribute() const; -}; - - -//----------------------------------------------------------------------------- -// Specialization for string arrays -// NOTE: To use this class, don't use CDmaStringArrayBase directly. Instead, use -// CDmaStringArray var; <- Instantiate an array attribute var as a member of a element class -// CDmrStringArray var; <- Used to reference an existing array attribute + read/modify it -// CDmrStringArrayConst var; <- Used to reference an existing array attribute + read it (no modify) -//----------------------------------------------------------------------------- -template< class BaseClass > -class CDmaStringArrayConstBase : public BaseClass -{ -public: - const char *operator[]( int i ) const; - const char *Element( int i ) const; - const char *Get( int i ) const; - const CUtlVector< CUtlString > &Get() const; - - // Returns strlen of element i - int Length( int i ) const; -}; - -template< class B > -class CDmaStringArrayBase : public CDmaStringArrayConstBase< CDmaArrayBase< CUtlString, B > > -{ - typedef CDmaStringArrayConstBase< CDmaArrayBase< CUtlString, B > > BaseClass; - -public: - // Sets an element in the array - void Set( int i, const char * pValue ); - - // Adds an element, uses copy constructor - int AddToTail( const char *pValue ); - int InsertBefore( int elem, const char *pValue ); -}; - - -//----------------------------------------------------------------------------- -// Specialization for elements -// NOTE: To use this class, don't use CDmaElementArrayBase directly. Instead, use -// CDmaElementArray< element_type > var; <- Instantiate an array attribute var as a member of a element class -// CDmrElementArray< element_type > var; <- Used to reference an existing array attribute + read/modify it -// CDmrElementArrayConst< element_type > var; <- Used to reference an existing array attribute + read it (no modify) -//----------------------------------------------------------------------------- -template< class E, class BaseClass > -class CDmaElementArrayConstBase : public BaseClass -{ -public: - // Returns the element type - UtlSymId_t GetElementType() const; - - // Array access - E *operator[]( int i ) const; - E *Element( int i ) const; - E *Get( int i ) const; - const DmElementHandle_t& GetHandle( int i ) const; - const CUtlVector< DmElementHandle_t > &Get() const; - - // Search - int Find( const E *pValue ) const; - int Find( DmElementHandle_t h ) const; -}; - -template < class E, class B > -class CDmaElementArrayBase : public CDmaElementArrayConstBase< E, CDmaArrayBase< DmElementHandle_t, B > > -{ - typedef CDmaElementArrayConstBase< E, CDmaArrayBase< DmElementHandle_t, B > > BaseClass; - -public: - void SetHandle( int i, DmElementHandle_t h ); - void Set( int i, E *pElement ); - - // Insertion - int AddToTail( ); - int AddToTail( DmElementHandle_t src ); - int AddToTail( E *pValue ); - int InsertBefore( int elem ); - int InsertBefore( int elem, DmElementHandle_t src ); - int InsertBefore( int elem, E *pValue ); - - template< class C, bool D > int AddToTail( const CDmeHandle& value ) - { - return BaseClass::AddToTail( value.GetHandle() ); - } - - template< class C, bool D > int InsertBefore( int elem, const CDmeHandle& value ) - { - return BaseClass::InsertBefore( elem, value.GetHandle() ); - } -}; - - -// NOTE: The next couple classes are implementation details used to create CDmrAray/CDmaArray - -//----------------------------------------------------------------------------- -// Base classes that contain data or refer to it; used for array accessor classes -//----------------------------------------------------------------------------- -template< typename T > -class CDmaDataInternal -{ -protected: - typedef typename CDmAttributeInfo< T >::StorageType_t D; - - const T& Value() const { return m_Storage; } - T& Value( ) { return m_Storage; } - const D& Data() const { return m_Storage; } - D& Data( ) { return m_Storage; } - -private: - D m_Storage; -}; - -template< typename T > -class CDmaDataExternal -{ -protected: - typedef typename CDmAttributeInfo< T >::StorageType_t D; - - CDmaDataExternal() : m_pStorage(0) {} - void Attach( void *pData ) { m_pStorage = (D*)pData; } - const T& Value() const { return *m_pStorage; } - T& Value( ) { return *m_pStorage; } - const D& Data() const { return *m_pStorage; } - D& Data( ) { return *m_pStorage; } - -private: - D* m_pStorage; -}; - - -//----------------------------------------------------------------------------- -// Versions for access, or for attribute vars -//----------------------------------------------------------------------------- -template< class T, class B > -class CDmaDecorator : public B -{ -public: - void Init( CDmElement *pOwner, const char *pAttributeName, int flags = 0 ); -}; - - -template< class T, class BaseClass > -class CDmrDecoratorConst : public BaseClass -{ -public: - void Init( const CDmAttribute* pAttribute ); - void Init( const CDmElement *pElement, const char *pAttributeName ); - - bool IsValid() const; -}; - -template< class T, class BaseClass > -class CDmrDecorator : public BaseClass -{ -public: - void Init( CDmAttribute* pAttribute ); - void Init( CDmElement *pElement, const char *pAttributeName, bool bAddAttribute = false ); - - bool IsValid() const; -}; - - -#define DECLARE_ATTRIBUTE_ARRAY_VARIABLE( _className, _elementType ) \ - public: \ - _className() {} - -#define DECLARE_ATTRIBUTE_ARRAY_REFERENCE( _className, _elementType ) \ - public: \ - _className() {} \ - _className( CDmAttribute* pAttribute ) { Init( pAttribute ); } \ - _className( CDmElement *pElement, const char *pAttributeName, bool bAddAttribute = false ) { Init( pElement, pAttributeName, bAddAttribute ); } \ - _className( CDmaArray<_className>& var ) { Init( var.GetAttribute() ); } \ - _className( CDmrArray<_className>& var ) { Init( var.GetAttribute() ); } - -#define DECLARE_ATTRIBUTE_ARRAY_CONST_REFERENCE( _className, _elementType ) \ - public: \ - _className() {} \ - _className( const CDmAttribute* pAttribute ) { Init( pAttribute ); } \ - _className( const CDmElement *pElement, const char *pAttributeName ) { Init( pElement, pAttributeName ); } \ - _className( const CDmaArray<_className>& var ) { Init( var.GetAttribute() ); } \ - _className( const CDmrArrayConst<_className>& var ) { Init( var.GetAttribute() ); } \ - _className( const CDmrArray<_className>& var ) { Init( var.GetAttribute() ); } - -template class CDmrArray; -template class CDmrArrayConst; -template class CDmaArray; - -//----------------------------------------------------------------------------- -// Versions for access, or for attribute vars -//----------------------------------------------------------------------------- -template -class CDmaArray : public CDmaDecorator< T, CDmaArrayBase< T, CDmaDataInternal< CUtlVector< T > > > > -{ - DECLARE_ATTRIBUTE_ARRAY_VARIABLE( CDmaArray, T ); - -public: - const CDmaArray& operator=( const CDmaArray &val ) - { - CopyArray( val.Base(), val.Count() ); - return *this; - } - - template< class C > const CDmaArray& operator=( const C &val ) - { - CopyArray( val.Base(), val.Count() ); - return *this; - } - -private: - CDmaArray( const CDmaArray& array ) {} -}; - - -template -class CDmrArrayConst : public CDmrDecoratorConst< T, CDmaArrayConstBase< T, CDmaDataExternal< CUtlVector< T > > > > -{ - typedef CDmrDecoratorConst< T, CDmaArrayConstBase< T, CDmaDataExternal< CUtlVector< T > > > > BaseClass; - DECLARE_ATTRIBUTE_ARRAY_CONST_REFERENCE( CDmrArrayConst, T ); -}; - - -template -class CDmrArray : public CDmrDecorator< T, CDmaArrayBase< T, CDmaDataExternal< CUtlVector< T > > > > -{ - typedef CDmrDecorator< T, CDmaArrayBase< T, CDmaDataExternal< CUtlVector< T > > > > BaseClass; - DECLARE_ATTRIBUTE_ARRAY_REFERENCE( CDmrArray, T ); - -public: - const CDmrArray& operator=( const CDmrArray &val ) - { - CopyArray( val.Base(), val.Count() ); - return *this; - } - - template< class C > const CDmrArray& operator=( const C &val ) - { - CopyArray( val.Base(), val.Count() ); - return *this; - } -}; - -class CDmrStringArray; - -class CDmaStringArray : public CDmaDecorator< CUtlString, CDmaStringArrayBase< CDmaDataInternal< CUtlVector< CUtlString > > > > -{ - DECLARE_ATTRIBUTE_ARRAY_VARIABLE( CDmaStringArray, CUtlString ); - -public: - const CDmaStringArray& operator=( const CDmaStringArray &val ) - { - CopyArray( val.Base(), val.Count() ); - return *this; - } - - template< class C > const CDmaStringArray& operator=( const C &val ) - { - CopyArray( val.Base(), val.Count() ); - return *this; - } - -private: - CDmaStringArray( const CDmaStringArray& array ) {} -}; - -class CDmrStringArray : public CDmrDecorator< CUtlString, CDmaStringArrayBase< CDmaDataExternal< CUtlVector< CUtlString > > > > -{ - typedef CDmrDecorator< CUtlString, CDmaStringArrayBase< CDmaDataExternal< CUtlVector< CUtlString > > > > BaseClass; - DECLARE_ATTRIBUTE_ARRAY_REFERENCE( CDmrStringArray, CUtlString ); - -public: - CDmrStringArray( CDmaStringArray& var ) { Init( var.GetAttribute() ); } - CDmrStringArray( CDmrStringArray& var ) { Init( var.GetAttribute() ); } - - const CDmrStringArray& operator=( const CDmrStringArray &val ) - { - CopyArray( val.Base(), val.Count() ); - return *this; - } - - template< class C > const CDmrStringArray& operator=( const C &val ) - { - CopyArray( val.Base(), val.Count() ); - return *this; - } -}; - -class CDmrStringArrayConst : public CDmrDecoratorConst< CUtlString, CDmaStringArrayConstBase< CDmaArrayConstBase< CUtlString, CDmaDataExternal< CUtlVector< CUtlString > > > > > -{ - typedef CDmrDecoratorConst< CUtlString, CDmaStringArrayConstBase< CDmaArrayConstBase< CUtlString, CDmaDataExternal< CUtlVector< CUtlString > > > > > BaseClass; - DECLARE_ATTRIBUTE_ARRAY_CONST_REFERENCE( CDmrStringArrayConst, CUtlString ); - -public: - CDmrStringArrayConst( const CDmaStringArray& var ) { Init( var.GetAttribute() ); } - CDmrStringArrayConst( const CDmrStringArray& var ) { Init( var.GetAttribute() ); } - CDmrStringArrayConst( const CDmrStringArrayConst& var ) { Init( var.GetAttribute() ); } -}; - - -//----------------------------------------------------------------------------- -// Prevent CDmaArray for DmElementHandle_t -//----------------------------------------------------------------------------- -template<> class CDmaArray { private: CDmaArray(); }; - - -template< class E > class CDmrElementArray; - -template< class E = CDmElement > -class CDmaElementArray : public CDmaElementArrayBase< E, CDmaDataInternal< CUtlVector< DmElementHandle_t > > > -{ - DECLARE_ATTRIBUTE_ARRAY_VARIABLE( CDmaElementArray, DmElementHandle_t ); - -public: - void Init( CDmElement *pOwner, const char *pAttributeName, int flags = 0 ) - { - Assert( pOwner ); - this->m_pAttribute = pOwner->AddExternalAttribute( pAttributeName, AT_ELEMENT_ARRAY, &Value() ); - this->m_pAttribute->SetElementTypeSymbol( E::GetStaticTypeSymbol() ); - if ( flags ) - { - this->m_pAttribute->AddFlag( flags ); - } - } - - template< typename C > CDmaElementArray& operator=( const C &val ) - { - CopyArray( val.Base(), val.Count() ); - return *this; - } - - // NOTE: The copy operator= must be defined in addition to the generic one - const CDmaElementArray& operator=( const CDmaElementArray &val ) - { - CopyArray( val.Base(), val.Count() ); - return *this; - } - -private: - template< class C > CDmaElementArray( const CDmaElementArray& var ); -}; - -template< class E = CDmElement > -class CDmrElementArrayConst : public CDmaElementArrayConstBase< E, CDmaArrayConstBase< DmElementHandle_t, CDmaDataExternal< CUtlVector< DmElementHandle_t > > > > -{ -public: - CDmrElementArrayConst() - { - this->m_pAttribute = NULL; - } - - CDmrElementArrayConst( const CDmAttribute* pAttribute ) - { - Init( pAttribute ); - } - - CDmrElementArrayConst( const CDmElement *pElement, const char *pAttributeName ) - { - Init( pElement, pAttributeName ); - } - - template< typename C > CDmrElementArrayConst( const CDmaElementArray& var ) - { - Init( var.GetAttribute() ); - } - - template< typename C > CDmrElementArrayConst( const CDmrElementArray& var ) - { - Init( var.GetAttribute() ); - } - - template< typename C > CDmrElementArrayConst( const CDmrElementArrayConst& var ) - { - Init( var.GetAttribute() ); - } - - void Init( const CDmAttribute* pAttribute ) - { - if ( pAttribute && pAttribute->GetType() == AT_ELEMENT_ARRAY ) - { - this->m_pAttribute = const_cast( pAttribute ); - Attach( this->m_pAttribute->GetAttributeData() ); - } - else - { - this->m_pAttribute = NULL; - Attach( NULL ); - } - } - - void Init( const CDmElement *pElement, const char *pAttributeName ) - { - CDmAttribute *pAttribute = NULL; - if ( pElement && pAttributeName && pAttributeName[0] ) - { - pAttribute = pElement->GetAttribute( pAttributeName ); - } - Init( pAttribute ); - } - - bool IsValid() const - { - return this->m_pAttribute != NULL; - } -}; - -template< class T = CDmElement > -class CDmrElementArray : public CDmaElementArrayBase< T, CDmaDataExternal< CUtlVector< DmElementHandle_t > > > -{ -public: - CDmrElementArray() - { - this->m_pAttribute = NULL; - } - - CDmrElementArray( CDmAttribute* pAttribute ) - { - Init( pAttribute ); - } - - CDmrElementArray( CDmElement *pElement, const char *pAttributeName, bool bAddAttribute = false ) - { - Init( pElement, pAttributeName, bAddAttribute ); - } - - template< typename C > CDmrElementArray( CDmaElementArray& var ) - { - Init( var.GetAttribute() ); - } - - template< typename C > CDmrElementArray( CDmrElementArray& var ) - { - Init( var.GetAttribute() ); - } - - void Init( CDmAttribute* pAttribute ) - { - if ( pAttribute && pAttribute->GetType() == AT_ELEMENT_ARRAY ) - { - this->m_pAttribute = pAttribute; - Attach( this->m_pAttribute->GetAttributeData() ); - } - else - { - this->m_pAttribute = NULL; - Attach( NULL ); - } - } - - void Init( CDmElement *pElement, const char *pAttributeName, bool bAddAttribute = false ) - { - CDmAttribute *pAttribute = NULL; - if ( pElement && pAttributeName && pAttributeName[0] ) - { - pAttribute = pElement->GetAttribute( pAttributeName ); - if ( bAddAttribute && !pAttribute ) - { - pAttribute = pElement->CreateAttribute( pAttributeName, AT_ELEMENT_ARRAY ); - - // FIXME: Should we do this? - pAttribute->SetElementTypeSymbol( T::GetStaticTypeSymbol() ); - } - } - Init( pAttribute ); - } - - bool IsValid() const - { - return this->m_pAttribute != NULL; - } - - template< typename C > CDmrElementArray& operator=( const C &val ) - { - CopyArray( val.Base(), val.Count() ); - return *this; - } - - // NOTE: The copy operator= must be defined in addition to the generic one - const CDmrElementArray& operator=( const CDmrElementArray &val ) - { - CopyArray( val.Base(), val.Count() ); - return *this; - } -}; - - -//----------------------------------------------------------------------------- -// -// Inline methods for CDmaVar -// -//----------------------------------------------------------------------------- -template< class T > inline CDmaVar::CDmaVar( ) -{ - m_pAttribute = NULL; - CDmAttributeInfo::SetDefaultValue( m_Storage ); -} - -template< class T > inline void CDmaVar::Init( CDmElement *pOwner, const char *pAttributeName, int flags = 0 ) -{ - Assert( pOwner ); - m_pAttribute = pOwner->AddExternalAttribute( pAttributeName, CDmAttributeInfo::AttributeType(), &m_Storage ); - Assert( m_pAttribute ); - if ( flags ) - { - m_pAttribute->AddFlag( flags ); - } -} - -template< class T > inline void CDmaVar::InitAndSet( CDmElement *pOwner, const char *pAttributeName, const T &value, int flags = 0 ) -{ - Init( pOwner, pAttributeName ); - Set( value ); - - // this has to happen AFTER set so the set happens before FATTRIB_READONLY - if ( flags ) - { - m_pAttribute->AddFlag( flags ); - } -} - -template< class T > inline const T& CDmaVar::Set( const T &val ) -{ - Assert( m_pAttribute ); - m_pAttribute->SetValue( val ); - return m_Storage; -} - -template< class T > inline const T& CDmaVar::operator=( const T &val ) -{ - return Set( val ); -} - -template< class T > inline const CDmaVar& CDmaVar::operator=( const CDmaVar& src ) -{ - Set( src.Get() ); - return *this; -} - -template< class T > inline const T& CDmaVar::operator+=( const T &val ) -{ - return Set( Value() + val ); -} - -template< class T > inline const T& CDmaVar::operator-=( const T &val ) -{ - return Set( Value() - val ); -} - -template< class T > inline const T& CDmaVar::operator/=( const T &val ) -{ - return Set( Value() / val ); -} - -template< class T > inline const T& CDmaVar::operator*=( const T &val ) -{ - return Set( Value() * val ); -} - -template< class T > inline const T& CDmaVar::operator^=( const T &val ) -{ - return Set( Value() ^ val ); -} - -template< class T > inline const T& CDmaVar::operator|=( const T &val ) -{ - return Set( Value() | val ); -} - -template< class T > inline const T& CDmaVar::operator&=( const T &val ) -{ - return Set( Value() & val ); -} - -template< class T > inline T CDmaVar::operator++() -{ - return Set( Value() + 1 ); -} - -template< class T > inline T CDmaVar::operator--() -{ - return Set( Value() - 1 ); -} - -template< class T > inline T CDmaVar::operator++( int ) // postfix version.. -{ - T oldValue = Value(); - Set( Value() + 1 ); - return oldValue; -} - -template< class T > inline T CDmaVar::operator--( int ) // postfix version.. -{ - T oldValue = Value(); - Set( Value() - 1 ); - return oldValue; -} - -template< class T > inline CDmaVar::operator const T&() const -{ - return Value(); -} - -template< class T > inline const T& CDmaVar::Get() const -{ - return Value(); -} - -template< class T > inline const T* CDmaVar::operator->() const -{ - return &Value(); -} - -template< class T > inline CDmAttribute *CDmaVar::GetAttribute() -{ - Assert( m_pAttribute ); - return m_pAttribute; -} - -template< class T > inline const CDmAttribute *CDmaVar::GetAttribute() const -{ - Assert( m_pAttribute ); - return m_pAttribute; -} - -template< class T > inline bool CDmaVar::IsDirty() const -{ - Assert( m_pAttribute ); - return m_pAttribute->IsFlagSet( FATTRIB_DIRTY ); -} - -template< class T > inline const T& CDmaVar::Value() const -{ - return m_Storage; -} - -template< class T > inline T& CDmaVar::Value() -{ - return m_Storage; -} - -template<> inline const DmElementHandle_t& CDmaVar< DmElementHandle_t >::Value() const -{ - return m_Storage.m_Handle; -} - -template<> inline DmElementHandle_t& CDmaVar< DmElementHandle_t >::Value() -{ - return m_Storage.m_Handle; -} - -template< class T > inline const typename CDmaVar::D& CDmaVar::Storage() const -{ - return m_Storage; -} - -template< class T > inline typename CDmaVar::D& CDmaVar::Storage() -{ - return m_Storage; -} - - -//----------------------------------------------------------------------------- -// -// Inline methods for CDmaColor -// -//----------------------------------------------------------------------------- -inline void CDmaColor::SetColor( int r, int g, int b, int a ) -{ - Color clr( r, g, b, a ); - m_pAttribute->SetValue( clr ); -} - -inline void CDmaColor::SetRed( int r ) -{ - Color org = Value(); - org[ 0 ] = r; - m_pAttribute->SetValue( org ); -} - -inline void CDmaColor::SetGreen( int g ) -{ - Color org = Value(); - org[ 1 ] = g; - m_pAttribute->SetValue( org ); -} - -inline void CDmaColor::SetBlue( int b ) -{ - Color org = Value(); - org[ 2 ] = b; - m_pAttribute->SetValue( org ); -} - -inline void CDmaColor::SetAlpha( int a ) -{ - Color org = Value(); - org[ 3 ] = a; - m_pAttribute->SetValue( org ); -} - -inline unsigned char CDmaColor::r() const -{ - return (unsigned char)Value().r(); -} - -inline unsigned char CDmaColor::g() const -{ - return (unsigned char)Value().g(); -} - -inline unsigned char CDmaColor::b() const -{ - return (unsigned char)Value().b(); -} - -inline unsigned char CDmaColor::a() const -{ - return (unsigned char)Value().a(); -} - -inline const unsigned char &CDmaColor::operator[](int index) const -{ - return Value()[index]; -} - -inline void CDmaColor::SetRawColor( int color ) -{ - Color clr; - clr.SetRawColor( color ); - m_pAttribute->SetValue( clr ); -} - - -//----------------------------------------------------------------------------- -// -// Inline methods for CDmaObjectId -// -//----------------------------------------------------------------------------- -inline void CDmaObjectId::CreateObjectId( ) -{ - DmObjectId_t id; - CreateUniqueId( &id ); - m_pAttribute->SetValue( id ); -} - -inline void CDmaObjectId::Invalidate( ) -{ - DmObjectId_t id; - InvalidateUniqueId( &id ); - m_pAttribute->SetValue( id ); -} - -inline bool CDmaObjectId::IsValid( ) const -{ - return IsUniqueIdValid( Value() ); -} - -inline bool CDmaObjectId::IsEqual( const DmObjectId_t &id ) const -{ - return IsUniqueIdEqual( Value(), id ); -} - -inline const DmObjectId_t &CDmaObjectId::operator=( const DmObjectId_t& src ) -{ - m_pAttribute->SetValue( src ); - return Value(); -} - -inline const CDmaObjectId& CDmaObjectId::operator=( const CDmaObjectId& src ) -{ - m_pAttribute->SetValue( src.Get() ); - return *this; -} - -inline const DmObjectId_t& CDmaObjectId::Set( const DmObjectId_t &src ) -{ - m_pAttribute->SetValue( src ); - return Value(); -} - - -//----------------------------------------------------------------------------- -// -// Inline methods for CDmaString -// -//----------------------------------------------------------------------------- -inline const char *CDmaString::Get( ) const -{ - return Value().Get(); -} - -inline CDmaString::operator const char*() const -{ - return Value().Get(); -} - -inline void CDmaString::Set( const char *pValue ) -{ - CUtlString str( pValue, pValue ? Q_strlen( pValue ) + 1 : 0 ); - m_pAttribute->SetValue( str ); -} - -// Returns strlen -inline int CDmaString::Length() const -{ - return Value().Length(); -} - -inline CDmaString &CDmaString::operator=( const char *src ) -{ - Set( src ); - return *this; -} - -inline const CDmaString& CDmaString::operator=( const CDmaString& src ) -{ - Set( src.Get() ); - return *this; -} - - -//----------------------------------------------------------------------------- -// -// Inline methods for CDmaBinaryBlock -// -//----------------------------------------------------------------------------- -inline void CDmaBinaryBlock::Get( void *pValue, int nMaxLen ) const -{ - Value().Get( pValue, nMaxLen ); -} - -inline void CDmaBinaryBlock::Set( const void *pValue, int nLen ) -{ - CUtlBinaryBlock block( pValue, nLen ); - m_pAttribute->SetValue( block ); -} - -inline const void *CDmaBinaryBlock::Get() const -{ - return Value().Get(); -} - -inline const unsigned char& CDmaBinaryBlock::operator[]( int i ) const -{ - return Value()[i]; -} - -inline int CDmaBinaryBlock::Length() const -{ - return Value().Length(); -} - - -//----------------------------------------------------------------------------- -// -// Inline methods for CDmaElement -// -//----------------------------------------------------------------------------- -template -inline void CDmaElement::InitAndCreate( CDmElement *pOwner, const char *pAttributeName, const char *pElementName, int flags ) -{ - Init( pOwner, pAttributeName ); - - DmElementHandle_t hElement = DMELEMENT_HANDLE_INVALID; - if ( !g_pDataModel->IsUnserializing() ) - { - hElement = g_pDataModel->CreateElement( T::GetStaticTypeSymbol(), pElementName, pOwner->GetFileId() ); - } - Assert( m_pAttribute ); - m_pAttribute->SetValue( hElement ); - - // this has to happen AFTER set so the set happens before FATTRIB_READONLY - m_pAttribute->AddFlag( flags | FATTRIB_MUSTCOPY ); -} - -template -inline void CDmaElement::Init( CDmElement *pOwner, const char *pAttributeName, int flags = 0 ) -{ - BaseClass::Init( pOwner, pAttributeName ); - - Assert( m_pAttribute ); - m_pAttribute->SetElementTypeSymbol( T::GetStaticTypeSymbol() ); - if ( flags ) - { - m_pAttribute->AddFlag( flags ); - } -} - -template -inline UtlSymId_t CDmaElement::GetElementType() const -{ - return Data().m_ElementType; -} - -template -inline T* CDmaElement::GetElement() const -{ - CDmElement *pElement = g_pDataModel->GetElement( Value() ); - Assert( !pElement || pElement->IsA( T::GetStaticTypeSymbol() ) ); - return static_cast< T* >( pElement ); -} - -template -inline T* CDmaElement::operator->() const -{ - return GetElement(); -} - -template -inline CDmaElement::operator T*() const -{ - return GetElement(); -} - -template -inline void CDmaElement::Set( T* pElement ) -{ - Assert( m_pAttribute ); - m_pAttribute->SetValue( pElement ? pElement->GetHandle() : DMELEMENT_HANDLE_INVALID ); -} - -template -inline bool CDmaElement::operator!() const -{ - return ( GetElement() == NULL ); -} - - -//----------------------------------------------------------------------------- -// -// Inline methods for CDmaArrayBase -// -//----------------------------------------------------------------------------- -template< class T, class B > -inline const CUtlVector& CDmaArrayConstBase::Get() const -{ - return Value(); -} - -template< class T, class B > -inline const T *CDmaArrayConstBase::Base() const -{ - return Value().Base(); -} - -template< class T, class B > -inline const T& CDmaArrayConstBase::operator[]( int i ) const -{ - return Value()[ i ]; -} - -template< class T, class B > -const T& CDmaArrayConstBase::Element( int i ) const -{ - return Value()[ i ]; -} - -template< class T, class B > -inline const T& CDmaArrayConstBase::Get( int i ) const -{ - return Value()[ i ]; -} - -template< class T, class B > -const void* CDmaArrayConstBase::GetUntyped( int i ) const -{ - return &( Value()[ i ] ); -} - -template< class T, class B > -inline int CDmaArrayConstBase::Count() const -{ - return Value().Count(); -} - -template< class T, class B > -inline bool CDmaArrayConstBase::IsValidIndex( int i ) const -{ - return Value().IsValidIndex( i ); -} - -template< class T, class B > -inline int CDmaArrayConstBase::InvalidIndex( void ) const -{ - return Value().InvalidIndex(); -} - -template< class T, class B > -inline const CDmAttribute *CDmaArrayConstBase::GetAttribute() const -{ - Assert( m_pAttribute ); - return m_pAttribute; -} - -template< class T, class B > -inline CDmElement *CDmaArrayConstBase::GetOwner() -{ - return m_pAttribute->GetOwner(); -} - -template< class T, class B > -inline bool CDmaArrayConstBase::IsDirty() const -{ - return m_pAttribute->IsFlagSet( FATTRIB_DIRTY ); -} - - -template< class T, class B > -inline CDmAttribute *CDmaArrayBase::GetAttribute() -{ - Assert( this->m_pAttribute ); - return this->m_pAttribute; -} - -template< class T, class B > -inline const CDmAttribute *CDmaArrayBase::GetAttribute() const -{ - Assert( this->m_pAttribute ); - return this->m_pAttribute; -} - - -//----------------------------------------------------------------------------- -// -// Inline methods for CDmaStringArrayBase -// -//----------------------------------------------------------------------------- -template< class B > -inline const char *CDmaStringArrayConstBase::operator[]( int i ) const -{ - return Value()[ i ].Get(); -} - -template< class B > -inline const char *CDmaStringArrayConstBase::Element( int i ) const -{ - return Value()[ i ].Get(); -} - -template< class B > -inline const char *CDmaStringArrayConstBase::Get( int i ) const -{ - return Value()[ i ].Get(); -} - -template< class B > -inline const CUtlVector< CUtlString > &CDmaStringArrayConstBase::Get() const -{ - return Value(); -} - -// Returns strlen of element i -template< class B > -inline int CDmaStringArrayConstBase::Length( int i ) const -{ - return Value()[i].Length(); -} - -template< class B > -inline void CDmaStringArrayBase::Set( int i, const char * pValue ) -{ - CUtlString str( pValue, Q_strlen( pValue ) + 1 ); - BaseClass::Set( i, str ); -} - -// Adds an element, uses copy constructor -template< class B > -inline int CDmaStringArrayBase::AddToTail( const char *pValue ) -{ - CUtlString str( pValue, Q_strlen( pValue ) + 1 ); - return BaseClass::AddToTail( str ); -} - -template< class B > -inline int CDmaStringArrayBase::InsertBefore( int elem, const char *pValue ) -{ - CUtlString str( pValue, Q_strlen( pValue ) + 1 ); - return BaseClass::InsertBefore( elem, str ); -} - - -//----------------------------------------------------------------------------- -// -// Inline methods for CDmaElementArrayBase -// -//----------------------------------------------------------------------------- -template< class E, class B > -inline UtlSymId_t CDmaElementArrayConstBase::GetElementType() const -{ - return Data().m_ElementType; -} - -template< class E, class B > -inline E *CDmaElementArrayConstBase::operator[]( int i ) const -{ - return GetElement( Value()[i] ); -} - -template< class E, class B > -inline E *CDmaElementArrayConstBase::Element( int i ) const -{ - return GetElement( Value()[i] ); -} - -template< class E, class B > -inline E *CDmaElementArrayConstBase::Get( int i ) const -{ - return GetElement( Value()[i] ); -} - -template< class E, class B > -inline const DmElementHandle_t& CDmaElementArrayConstBase::GetHandle( int i ) const -{ - return Value()[i]; -} - -template< class E, class B > -inline const CUtlVector< DmElementHandle_t > &CDmaElementArrayConstBase::Get() const -{ - return Value(); -} - -// Search -template< class E, class B > -inline int CDmaElementArrayConstBase::Find( const E *pValue ) const -{ - if ( !pValue ) - return -1; - return B::Find( pValue->GetHandle() ); -} - -template< class E, class B > -inline int CDmaElementArrayConstBase::Find( DmElementHandle_t h ) const -{ - return B::Find( h ); -} - -template< class E, class B > -inline void CDmaElementArrayBase::SetHandle( int i, DmElementHandle_t h ) -{ - BaseClass::Set( i, h ); -} - -template< class E, class B > -inline void CDmaElementArrayBase::Set( int i, E *pElement ) -{ - BaseClass::Set( i, pElement ? pElement->GetHandle() : DMELEMENT_HANDLE_INVALID ); -} - -// Adds an element, uses copy constructor -template< class E, class B > -inline int CDmaElementArrayBase::AddToTail( ) -{ - return BaseClass::AddToTail( ); -} - -template< class E, class B > -inline int CDmaElementArrayBase::AddToTail( E *pValue ) -{ - return BaseClass::AddToTail( pValue ? pValue->GetHandle() : DMELEMENT_HANDLE_INVALID ); -} - -template< class E, class B > -inline int CDmaElementArrayBase::AddToTail( DmElementHandle_t src ) -{ - return BaseClass::AddToTail( src ); -} - -template< class E, class B > -inline int CDmaElementArrayBase::InsertBefore( int elem ) -{ - return BaseClass::InsertBefore( elem ); -} - -template< class E, class B > -inline int CDmaElementArrayBase::InsertBefore( int elem, E *pValue ) -{ - return BaseClass::InsertBefore( elem, pValue ? pValue->GetHandle() : DMELEMENT_HANDLE_INVALID ); -} - -template< class E, class B > -inline int CDmaElementArrayBase::InsertBefore( int elem, DmElementHandle_t src ) -{ - return BaseClass::InsertBefore( elem, src ); -} - - - -//----------------------------------------------------------------------------- -// -// Inline methods for CDmrGenericArray -// -//----------------------------------------------------------------------------- -inline const CDmAttribute *CDmrGenericArrayConst::GetAttribute() const -{ - Assert( m_pAttribute ); - return m_pAttribute; -} - -inline bool CDmrGenericArrayConst::IsValid() const -{ - return m_pAttribute != NULL; -} - -inline CDmAttribute *CDmrGenericArray::GetAttribute() -{ - Assert( m_pAttribute ); - return m_pAttribute; -} - -inline const CDmAttribute *CDmrGenericArray::GetAttribute() const -{ - Assert( m_pAttribute ); - return m_pAttribute; -} - - -#endif // DMATTRIBUTEVAR_H diff --git a/public/datamodel/dmehandle.h b/public/datamodel/dmehandle.h deleted file mode 100644 index a6521268a..000000000 --- a/public/datamodel/dmehandle.h +++ /dev/null @@ -1,241 +0,0 @@ -//========= Copyright 1996-2005, Valve LLC, All rights reserved. ============ -// -// The copyright to the contents herein is the property of Valve, L.L.C. -// The contents may be used and/or copied only with the written permission of -// Valve, L.L.C., or in accordance with the terms and conditions stipulated in -// the agreement/contract under which the contents have been supplied. -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#ifndef DMEHANDLE_H -#define DMEHANDLE_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "datamodel/idatamodel.h" -#include "datamodel/dmelement.h" - - -//----------------------------------------------------------------------------- -// Purpose: CDmeHandle is a templatized wrapper around DmElementHandle_t -//----------------------------------------------------------------------------- -template< class DmeType, bool Counted = false > -class CDmeHandle : public CDmeElementRefHelper -{ -public: - CDmeHandle() : m_handle( DMELEMENT_HANDLE_INVALID ) - { - } - - explicit CDmeHandle( CDmElement *pObject ) : m_handle( DMELEMENT_HANDLE_INVALID ) - { - Set( pObject ); - } - - CDmeHandle( DmElementHandle_t h ) : m_handle( DMELEMENT_HANDLE_INVALID ) - { - Set( h ); - } - - CDmeHandle( const CDmeHandle< DmeType, Counted > &handle ) : m_handle( DMELEMENT_HANDLE_INVALID ) - { - Set( handle.m_handle ); - } - - template < class T, bool B > - CDmeHandle( const CDmeHandle< T, B > &handle ) : m_handle( DMELEMENT_HANDLE_INVALID ) - { - DmeType *p = ( T* )NULL; // triggers compiler error if converting from invalid handle type - NOTE_UNUSED( p ); - - Set( handle.GetHandle() ); - } - - ~CDmeHandle() - { - if ( !g_pDataModel ) - return; // some handles are static, and don't get destroyed until program termination - - Unref( m_handle, Counted ); - } - - template < class T, bool B > - CDmeHandle& operator=( const CDmeHandle< T, B > &handle ) - { - DmeType *p = ( T* )NULL; // triggers compiler error if converting from invalid handle type - NOTE_UNUSED( p ); - - Set( handle.GetHandle() ); - return *this; - } - - DmeType *Get() - { - return static_cast< DmeType* >( g_pDataModel->GetElement( m_handle ) ); - } - - const DmeType *Get() const - { - return static_cast< DmeType* >( g_pDataModel->GetElement( m_handle ) ); - } - - DmElementHandle_t GetHandle() const - { - return m_handle; - } - - void Set( CDmElement *pObject ) - { - Set( pObject ? pObject->GetHandle() : DMELEMENT_HANDLE_INVALID ); - } - - void Set( DmElementHandle_t h ) - { - if ( h == m_handle ) - return; - - Unref( m_handle, Counted ); - - m_handle = h; - if ( h != DMELEMENT_HANDLE_INVALID ) - { - CDmElement *pElement = g_pDataModel->GetElement( m_handle ); - Assert( pElement ); - if ( pElement && !pElement->IsA( DmeType::GetStaticTypeSymbol() ) ) - { - m_handle = DMELEMENT_HANDLE_INVALID; - } - } - - Ref( m_handle, Counted ); - } - - operator DmeType*() - { - return Get(); - } - - operator const DmeType*() const - { - return Get(); - } - - operator DmElementHandle_t() const - { - return m_handle; - } - - DmeType* operator->() - { - return Get(); - } - - const DmeType* operator->() const - { - return Get(); - } - - CDmeHandle& operator=( DmElementHandle_t h ) - { - Set( h ); - return *this; - } - - CDmeHandle& operator=( CDmElement *pObject ) - { - Set( pObject ); - return *this; - } - - bool operator==( const CDmeHandle< DmeType > &h ) const - { - return m_handle == h.m_handle; - } - - bool operator!=( const CDmeHandle< DmeType > &h ) const - { - return !operator==( h ); - } - - bool operator<( const CDmeHandle< DmeType > &h ) const - { - return m_handle < h.m_handle; - } - - bool operator==( DmeType *pObject ) const - { - DmElementHandle_t h = pObject ? pObject->GetHandle() : DMELEMENT_HANDLE_INVALID; - return m_handle == h; - } - - bool operator!=( DmeType *pObject ) const - { - return !operator==( pObject ); - } - - bool operator==( DmElementHandle_t h ) const - { - return ( m_handle == h ); - } - - bool operator!=( DmElementHandle_t h ) const - { - return ( m_handle != h ); - } - - operator bool() const - { - return ( Get() != NULL ); - } - - bool operator!() const - { - return ( Get() == NULL ); - } - -private: - DmElementHandle_t m_handle; -}; - -typedef CDmeHandle< CDmElement, true > CDmeCountedHandle; - - -//----------------------------------------------------------------------------- -// Vector of element handles -//----------------------------------------------------------------------------- -typedef CUtlVector< CDmeHandle > DmeHandleVec_t; - - - -//----------------------------------------------------------------------------- -// helper class for undo classes to allow them to hold onto refcounted element handles -//----------------------------------------------------------------------------- - -template< typename T > -class CDmAttributeUndoStorageType -{ -public: - typedef T UndoStorageType; -}; - -template<> -class CDmAttributeUndoStorageType< DmElementHandle_t > -{ -public: - typedef CDmeCountedHandle UndoStorageType; -}; - -template<> -class CDmAttributeUndoStorageType< CUtlVector< DmElementHandle_t > > -{ -public: - typedef CUtlVector< CDmeCountedHandle > UndoStorageType; -}; - -#endif // DMEHANDLE_H diff --git a/public/datamodel/dmelement.h b/public/datamodel/dmelement.h deleted file mode 100644 index cb1ff5c96..000000000 --- a/public/datamodel/dmelement.h +++ /dev/null @@ -1,960 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef DMELEMENT_H -#define DMELEMENT_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/utlmap.h" -#include "tier1/utlhash.h" -#include "tier1/utlvector.h" -#include "tier1/utlsymbol.h" -#include "datamodel/attributeflags.h" -#include "datamodel/idatamodel.h" -#include "datamodel/dmattribute.h" -#include "datamodel/dmvar.h" -#ifndef _LINUX -#include "datamodel/dmattributevar.h" -#endif - -//----------------------------------------------------------------------------- -// Forward declarations: -//----------------------------------------------------------------------------- -class CDmAttribute; -class Color; -class Vector; -class QAngle; -class Quaternion; -class VMatrix; -class CDmElement; - - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -typedef bool (CDmElement::*pfnCommandMethod)( const char *command, const char *args ); - -// element/element array traversal path item - assumes the full path does NOT contain cycles -struct ElementPathItem_t -{ - ElementPathItem_t( DmElementHandle_t hElem = DMELEMENT_HANDLE_INVALID, - DmAttributeHandle_t hAttr = DMATTRIBUTE_HANDLE_INVALID, - int idx = -1 ) - : hElement( hElem ), hAttribute( hAttr ), nIndex( idx ) - { - } - - // only uses hElement so that it can be used to search for elements - bool operator==( const ElementPathItem_t &that ) const - { - return hElement == that.hElement; - } - - DmElementHandle_t hElement; - DmAttributeHandle_t hAttribute; - int nIndex; -}; - - -//----------------------------------------------------------------------------- -// singly-linked attribute list -//----------------------------------------------------------------------------- -struct DmAttributeList_t -{ - DmAttributeList_t() : m_hAttribute( DMATTRIBUTE_HANDLE_INVALID ), m_pNext( NULL ) {} - DmAttributeHandle_t m_hAttribute; - DmAttributeList_t *m_pNext; -}; - -//----------------------------------------------------------------------------- -// helper class to allow CDmeHandle access to g_pDataModelImp -//----------------------------------------------------------------------------- -class CDmeElementRefHelper -{ -protected: - void Ref ( DmElementHandle_t hElement, bool bStrong ); - void Unref( DmElementHandle_t hElement, bool bStrong ); -}; - -//----------------------------------------------------------------------------- -// element reference struct - containing attribute referrers and handle refcount -//----------------------------------------------------------------------------- -struct DmElementReference_t -{ - explicit DmElementReference_t( DmElementHandle_t hElement = DMELEMENT_HANDLE_INVALID ) : - m_hElement( hElement ), m_nWeakHandleCount( 0 ), m_nStrongHandleCount( 0 ) - { - } - DmElementReference_t( const DmElementReference_t &that ) : - m_hElement( that.m_hElement ), m_nWeakHandleCount( that.m_nWeakHandleCount ), - m_nStrongHandleCount( that.m_nStrongHandleCount ), m_attributes( that.m_attributes ) - { - } - DmElementReference_t &operator=( const DmElementReference_t &that ) - { - m_hElement = that.m_hElement; - m_nWeakHandleCount = that.m_nWeakHandleCount; - m_nStrongHandleCount = that.m_nStrongHandleCount; - m_attributes.m_hAttribute = that.m_attributes.m_hAttribute; - m_attributes.m_pNext = that.m_attributes.m_pNext; - return *this; - } - ~DmElementReference_t() - { - // Assert( !IsStronglyReferenced() ); - } - - void AddAttribute( CDmAttribute *pAttribute ); - void RemoveAttribute( CDmAttribute *pAttribute ); - - bool IsStronglyReferenced() // should this element be kept around (even if it's DmElementHandle_t is invalidated) - { - return m_attributes.m_hAttribute != DMATTRIBUTE_HANDLE_INVALID || m_nStrongHandleCount > 0; - } - - bool IsWeaklyReferenced() // should we keep this element's DmElementHandle_t mapped to it's id (even if the element is deleted) - { - return IsStronglyReferenced() || m_nWeakHandleCount > 0; - } - - int EstimateMemoryOverhead() - { - int nBytes = 0; - for ( DmAttributeList_t *pLink = m_attributes.m_pNext; pLink; pLink = pLink->m_pNext ) - { - nBytes += sizeof( DmAttributeList_t ); - } - return nBytes; - } - - DmElementHandle_t m_hElement; - unsigned short m_nWeakHandleCount; // CDmeHandle - for auto-hookup once the element comes back, mainly used by UI - unsigned short m_nStrongHandleCount; // CDmeCountedElementRef - for preventing elements from being truly deleted, mainly used by undo and file root - DmAttributeList_t m_attributes; -}; - - -//----------------------------------------------------------------------------- -// Base DmElement we inherit from in higher-level classes -//----------------------------------------------------------------------------- -class CDmElement -{ -public: - // Can be overridden by derived classes - virtual void OnAttributeChanged( CDmAttribute *pAttribute ) {} - virtual void PreAttributeChanged( CDmAttribute *pAttribute ) {} - virtual void OnAttributeArrayElementAdded( CDmAttribute *pAttribute, int nFirstElem, int nLastElem ) {} - virtual void OnAttributeArrayElementRemoved( CDmAttribute *pAttribute, int nFirstElem, int nLastElem ) {} - virtual void Resolve() {} - virtual bool IsA( UtlSymId_t typeSymbol ) const; - virtual int GetInheritanceDepth( UtlSymId_t typeSymbol ) const; - virtual void OnElementUnserialized() {} - virtual int AllocatedSize() const { return sizeof( CDmElement ); } - - // Returns the element handle - DmElementHandle_t GetHandle() const; - - // Attribute iteration, finding - // NOTE: Passing a type into GetAttribute will return NULL if the attribute exists but isn't that type - bool HasAttribute( const char *pAttributeName, DmAttributeType_t type = AT_UNKNOWN ) const; - CDmAttribute *GetAttribute( const char *pAttributeName, DmAttributeType_t type = AT_UNKNOWN ); - const CDmAttribute *GetAttribute( const char *pAttributeName, DmAttributeType_t type = AT_UNKNOWN ) const; - int AttributeCount() const; - CDmAttribute* FirstAttribute(); - const CDmAttribute* FirstAttribute() const; - - // Element name, type, ID - // WARNING: SetType() should only be used by format conversion methods (dmxconvert) - UtlSymId_t GetType() const; - const char * GetTypeString() const; - const char * GetName() const; - const DmObjectId_t& GetId() const; - void SetType( const char *pType ); - void SetName( const char* pName ); - - // Attribute management - CDmAttribute * AddAttribute( const char *pAttributeName, DmAttributeType_t type ); - template< class E > CDmAttribute* AddAttributeElement( const char *pAttributeName ); - template< class E > CDmAttribute* AddAttributeElementArray( const char *pAttributeName ); - void RemoveAttribute( const char *pAttributeName ); - void RemoveAttributeByPtr( CDmAttribute *pAttributeName ); - void RenameAttribute( const char *pAttributeName, const char *pNewName ); - - // get attribute value - template< class T > const T& GetValue( const char *pAttributeName ) const; - template< class T > const T& GetValue( const char *pAttributeName, const T& defaultValue ) const; - const char * GetValueString( const char *pAttributeName ) const; - template< class E > E* GetValueElement( const char *pAttributeName ) const; - - // set attribute value - CDmAttribute* SetValue( const char *pAttributeName, const void *value, size_t size ); - template< class T > CDmAttribute* SetValue( const char *pAttributeName, const T& value ); - template< class E > CDmAttribute* SetValue( const char *pAttributeName, E* value ); - - // set attribute value if the attribute doesn't already exist - CDmAttribute* InitValue( const char *pAttributeName, const void *value, size_t size ); - template< class T > CDmAttribute* InitValue( const char *pAttributeName, const T& value ); - template< class E > CDmAttribute* InitValue( const char *pAttributeName, E* value ); - - // Parses an attribute from a string - // Doesn't create an attribute if it doesn't exist and always preserves attribute type - void SetValueFromString( const char *pAttributeName, const char *value ); - const char *GetValueAsString( const char *pAttributeName, char *pBuffer, size_t buflen ) const; - - // Helpers for our RTTI - template< class E > bool IsA() const; - bool IsA( const char *pTypeName ) const; - int GetInheritanceDepth( const char *pTypeName ) const; - static CUtlSymbol GetStaticTypeSymbol(); - - // Indicates whether this element should be copied or not - void SetShared( bool bShared ); - bool IsShared() const; - - // Copies an element and all its attributes - CDmElement* Copy( TraversalDepth_t depth = TD_DEEP ) const; - - // Copies attributes from a specified element - void CopyAttributesTo( CDmElement *pCopy, TraversalDepth_t depth = TD_DEEP ) const; - - // recursively set fileid's, with option to only change elements in the matched file - void SetFileId( DmFileId_t fileid, TraversalDepth_t depth, bool bOnlyIfMatch = false ); - DmFileId_t GetFileId() const; - - bool IsAccessible() const; - void MarkAccessible( bool bAccessible ); - void MarkAccessible( TraversalDepth_t depth = TD_ALL ); - - // returns the first path to the element found traversing all element/element - // array attributes - not necessarily the shortest. - // cycle-safe (skips any references to elements in the current path) - // but may re-traverse elements via different paths - bool FindElement( const CDmElement *pElement, CUtlVector< ElementPathItem_t > &elementPath, TraversalDepth_t depth ) const; - bool FindReferer( DmElementHandle_t hElement, CUtlVector< ElementPathItem_t > &elementPath, TraversalDepth_t depth ) const; - void RemoveAllReferencesToElement( CDmElement *pElement ); - bool IsStronglyReferenced() { return m_ref.IsStronglyReferenced(); } - - // Estimates the memory usage of the element, its attributes, and child elements - int EstimateMemoryUsage( TraversalDepth_t depth = TD_DEEP ); - -protected: - // NOTE: These are protected to ensure that the factory is the only thing that can create these - CDmElement( DmElementHandle_t handle, const char *objectType, const DmObjectId_t &id, const char *objectName, DmFileId_t fileid ); - virtual ~CDmElement(); - - // Used by derived classes to do construction and setting up CDmaVars - void OnConstruction() { } - void OnDestruction() { } - virtual void PerformConstruction(); - virtual void PerformDestruction(); - - // Internal methods related to RTII - static void SetTypeSymbol( CUtlSymbol sym ); - static bool IsA_Implementation( CUtlSymbol typeSymbol ); - static int GetInheritanceDepth_Implementation( CUtlSymbol typeSymbol, int nCurrentDepth ); - - // Internal method for creating a copy of this element - CDmElement* CopyInternal( TraversalDepth_t depth = TD_DEEP ) const; - - // helper for making attributevarelementarray cleanup easier - template< class T > static void DeleteAttributeVarElementArray( T &array ); - -private: - typedef CUtlMap< DmElementHandle_t, DmElementHandle_t, int > CRefMap; - - // Bogus constructor - CDmElement(); - - // internal recursive copy method - builds refmap of old element's handle -> copy's handle, and uses it to fixup references - void CopyAttributesTo( CDmElement *pCopy, CRefMap &refmap, TraversalDepth_t depth ) const; - void CopyElementAttribute( const CDmAttribute *pAttr, CDmAttribute *pCopyAttr, CRefMap &refmap, TraversalDepth_t depth ) const; - void CopyElementArrayAttribute( const CDmAttribute *pAttr, CDmAttribute *pCopyAttr, CRefMap &refmap, TraversalDepth_t depth ) const; - void FixupReferences( CUtlHashFast< DmElementHandle_t > &visited, const CRefMap &refmap, TraversalDepth_t depth ); - - void SetFileId( DmFileId_t fileid ); - void SetFileId_R( CUtlHashFast< DmElementHandle_t > &visited, DmFileId_t fileid, TraversalDepth_t depth, DmFileId_t match, bool bOnlyIfMatch ); - - CDmAttribute* CreateAttribute( const char *pAttributeName, DmAttributeType_t type ); - void RemoveAttribute( CDmAttribute **pAttrRef ); - CDmAttribute* AddExternalAttribute( const char *pAttributeName, DmAttributeType_t type, void *pMemory ); - CDmAttribute *FindAttribute( const char *pAttributeName ) const; - - void Purge(); - void SetId( const DmObjectId_t &id ); - - bool IsDirty() const; - void MarkDirty( bool dirty = true ); - void MarkAttributesClean(); - void MarkBeingUnserialized( bool beingUnserialized = true ); - bool IsBeingUnserialized() const; - - // Used by the undo system only. - void AddAttributeByPtr( CDmAttribute *ptr ); - void RemoveAttributeByPtrNoDelete( CDmAttribute *ptr ); - - // Should only be called from datamodel, who will take care of changing the fileset entry as well - void ChangeHandle( DmElementHandle_t handle ); - - // returns element reference struct w/ list of referrers and handle count - DmElementReference_t* GetReference(); - void SetReference( const DmElementReference_t &ref ); - - // Estimates memory usage - int EstimateMemoryUsage( CUtlHash< DmElementHandle_t > &visited, TraversalDepth_t depth, int *pCategories ); - -protected: - CDmaString m_Name; - -private: - CDmAttribute *m_pAttributes; - DmElementReference_t m_ref; - UtlSymId_t m_Type; - bool m_bDirty : 1; - bool m_bBeingUnserialized : 1; - bool m_bIsAcessible : 1; - unsigned char m_nReserved; // Makes Id be quad aligned - DmObjectId_t m_Id; - DmFileId_t m_fileId; - - // Stores the type symbol - static CUtlSymbol m_classType; - - // Factories can access our constructors - template friend class CDmElementFactory; - template friend class CDmAbstractElementFactory; - template< class T > friend class CDmaVar; - template< class T > friend class CDmaArray; - template< class T > friend class CDmaElementArray; - template< class T, class B > friend class CDmaDecorator; - template< class T > friend class CDmrElementArray; - - friend class CDmElementFactoryDefault; - friend class CDmeElementAccessor; - friend class CDmeOperator; - - friend void CopyElements( const CUtlVector< CDmElement* > &from, CUtlVector< CDmElement* > &to, TraversalDepth_t depth ); -}; - - -//----------------------------------------------------------------------------- -// Fast dynamic cast -//----------------------------------------------------------------------------- -template< class E > -inline E *CastElement( CDmElement *pElement ) -{ - if ( pElement && pElement->IsA( E::GetStaticTypeSymbol() ) ) - return static_cast< E* >( pElement ); - return NULL; -} - - -//----------------------------------------------------------------------------- -// type-safe element creation and accessor helpers - infers type name string from actual type -//----------------------------------------------------------------------------- -template< class E > -inline E *GetElement( DmElementHandle_t hElement ) -{ - CDmElement *pElement = g_pDataModel->GetElement( hElement ); - return CastElement< E >( pElement ); -} - - -//----------------------------------------------------------------------------- -// Typesafe element creation + destruction -//----------------------------------------------------------------------------- -template< class E > -inline E *CreateElement( const char *pObjectName, DmFileId_t fileid = DMFILEID_INVALID, const DmObjectId_t *pObjectID = NULL ) -{ - return GetElement< E >( g_pDataModel->CreateElement( E::GetStaticTypeSymbol(), pObjectName, fileid, pObjectID ) ); -} - -template< class E > -inline E *CreateElement( const char *pElementType, const char *pObjectName, DmFileId_t fileid = DMFILEID_INVALID, const DmObjectId_t *pObjectID = NULL ) -{ - return GetElement< E >( g_pDataModel->CreateElement( pElementType, pObjectName, fileid, pObjectID ) ); -} - -inline void DestroyElement( CDmElement *pElement ) -{ - if ( pElement ) - { - g_pDataModel->DestroyElement( pElement->GetHandle() ); - } -} - -void DestroyElement( CDmElement *pElement, TraversalDepth_t depth ); - - -//----------------------------------------------------------------------------- -// copy groups of elements together so that references between them are maintained -//----------------------------------------------------------------------------- -void CopyElements( const CUtlVector< CDmElement* > &from, CUtlVector< CDmElement* > &to, TraversalDepth_t depth = TD_DEEP ); - - -//----------------------------------------------------------------------------- -// allows elements to chain OnAttributeChanged up to their parents (or at least, referrers) -//----------------------------------------------------------------------------- -void InvokeOnAttributeChangedOnReferrers( DmElementHandle_t hElement, CDmAttribute *pChangedAttr ); - - -//----------------------------------------------------------------------------- -// Gets attributes -//----------------------------------------------------------------------------- -inline CDmAttribute *CDmElement::GetAttribute( const char *pAttributeName, DmAttributeType_t type ) -{ - CDmAttribute *pAttribute = FindAttribute( pAttributeName ); - if ( ( type != AT_UNKNOWN ) && pAttribute && ( pAttribute->GetType() != type ) ) - return NULL; - return pAttribute; -} - -inline const CDmAttribute *CDmElement::GetAttribute( const char *pAttributeName, DmAttributeType_t type ) const -{ - CDmAttribute *pAttribute = FindAttribute( pAttributeName ); - if ( ( type != AT_UNKNOWN ) && pAttribute && ( pAttribute->GetType() != type ) ) - return NULL; - return pAttribute; -} - - -//----------------------------------------------------------------------------- -// AddAttribute calls -//----------------------------------------------------------------------------- -inline CDmAttribute *CDmElement::AddAttribute( const char *pAttributeName, DmAttributeType_t type ) -{ - CDmAttribute *pAttribute = FindAttribute( pAttributeName ); - if ( pAttribute ) - return ( pAttribute->GetType() == type ) ? pAttribute : NULL; - pAttribute = CreateAttribute( pAttributeName, type ); - return pAttribute; -} - -template< class E > inline CDmAttribute *CDmElement::AddAttributeElement( const char *pAttributeName ) -{ - CDmAttribute *pAttribute = AddAttribute( pAttributeName, AT_ELEMENT ); - if ( !pAttribute ) - return NULL; - - // FIXME: If the attribute exists but has a different element type symbol, should we complain? - pAttribute->SetElementTypeSymbol( E::GetStaticTypeSymbol() ); - return pAttribute; -} - -template< class E > inline CDmAttribute *CDmElement::AddAttributeElementArray( const char *pAttributeName ) -{ - CDmAttribute *pAttribute = AddAttribute( pAttributeName, AT_ELEMENT_ARRAY ); - if ( !pAttribute ) - return NULL; - - // FIXME: If the attribute exists but has a different element type symbol, should we complain? - pAttribute->SetElementTypeSymbol( E::GetStaticTypeSymbol() ); - return pAttribute; -} - - -//----------------------------------------------------------------------------- -// GetValue methods -//----------------------------------------------------------------------------- -template< class T > -inline const T& CDmElement::GetValue( const char *pAttributeName, const T& defaultVal ) const -{ - const CDmAttribute *pAttribute = FindAttribute( pAttributeName ); - if ( pAttribute != NULL ) - return pAttribute->GetValue(); - return defaultVal; -} - -template< class T > -inline const T& CDmElement::GetValue( const char *pAttributeName ) const -{ - static CDmaVar defaultVal; - return GetValue( pAttributeName, defaultVal.Get() ); -} - -inline const char *CDmElement::GetValueString( const char *pAttributeName ) const -{ - return GetValue( pAttributeName ).Get(); -} - -template< class E > -inline E* CDmElement::GetValueElement( const char *pAttributeName ) const -{ - DmElementHandle_t h = GetValue< DmElementHandle_t >( pAttributeName ); - return GetElement( h ); -} - - -//----------------------------------------------------------------------------- -// SetValue methods -//----------------------------------------------------------------------------- -template< class T > -inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, const T& value ) -{ - CDmAttribute *pAttribute = FindAttribute( pAttributeName ); - if ( !pAttribute ) - { - pAttribute = CreateAttribute( pAttributeName, CDmAttributeInfo::AttributeType() ); - } - if ( pAttribute ) - { - pAttribute->SetValue( value ); - return pAttribute; - } - return NULL; -} - -template< class E > -inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, E* pElement ) -{ - DmElementHandle_t hElement = pElement ? pElement->GetHandle() : DMELEMENT_HANDLE_INVALID; - return SetValue( pAttributeName, hElement ); -} - -template<> -inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, const char *pValue ) -{ - int nLen = pValue ? Q_strlen( pValue ) + 1 : 0; - CUtlString str( pValue, nLen ); - return SetValue( pAttributeName, str ); -} - -template<> -inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, char *pValue ) -{ - return SetValue( pAttributeName, (const char *)pValue ); -} - -inline CDmAttribute* CDmElement::SetValue( const char *pAttributeName, const void *pValue, size_t nSize ) -{ - CUtlBinaryBlock buf( pValue, nSize ); - return SetValue( pAttributeName, buf ); -} - - -//----------------------------------------------------------------------------- -// AddValue methods( set value if not found ) -//----------------------------------------------------------------------------- -template< class T > -inline CDmAttribute* CDmElement::InitValue( const char *pAttributeName, const T& value ) -{ - CDmAttribute *pAttribute = GetAttribute( pAttributeName ); - if ( !pAttribute ) - return SetValue( pAttributeName, value ); - return pAttribute; -} - -template< class E > -inline CDmAttribute* CDmElement::InitValue( const char *pAttributeName, E* pElement ) -{ - DmElementHandle_t hElement = pElement ? pElement->GetHandle() : DMELEMENT_HANDLE_INVALID; - return InitValue( pAttributeName, hElement ); -} - -inline CDmAttribute* CDmElement::InitValue( const char *pAttributeName, const void *pValue, size_t size ) -{ - CDmAttribute *pAttribute = GetAttribute( pAttributeName ); - if ( !pAttribute ) - return SetValue( pAttributeName, pValue, size ); - return pAttribute; -} - - -//----------------------------------------------------------------------------- -// Returns the type, name, id, fileId -//----------------------------------------------------------------------------- -inline UtlSymId_t CDmElement::GetType() const -{ - return m_Type; -} - -inline const char *CDmElement::GetTypeString() const -{ - return g_pDataModel->GetString( m_Type ); -} - -inline const char *CDmElement::GetName() const -{ - return m_Name.Get(); -} - -inline void CDmElement::SetName( const char* pName ) -{ - m_Name.Set( pName ); -} - -inline const DmObjectId_t& CDmElement::GetId() const -{ - return m_Id; -} - -inline DmFileId_t CDmElement::GetFileId() const -{ - return m_fileId; -} - - -//----------------------------------------------------------------------------- -// Controls whether the element should be copied by default -//----------------------------------------------------------------------------- -inline void CDmElement::SetShared( bool bShared ) -{ - if ( bShared ) - { - SetValue< bool >( "shared", true ); - } - else - { - RemoveAttribute( "shared" ); - } -} - -inline bool CDmElement::IsShared() const -{ - return GetValue< bool >( "shared" ); // if attribute doesn't exist, returns default bool value, which is false -} - - -//----------------------------------------------------------------------------- -// Copies attributes from a specified element -//----------------------------------------------------------------------------- -inline CDmElement* CDmElement::Copy( TraversalDepth_t depth ) const -{ - return CopyInternal( depth ); -} - - -//----------------------------------------------------------------------------- -// RTTI -//----------------------------------------------------------------------------- -inline bool CDmElement::IsA_Implementation( CUtlSymbol typeSymbol ) -{ - return ( m_classType == typeSymbol ) || ( UTL_INVAL_SYMBOL == typeSymbol ); -} - -inline int CDmElement::GetInheritanceDepth_Implementation( CUtlSymbol typeSymbol, int nCurrentDepth ) -{ - return IsA_Implementation( typeSymbol ) ? nCurrentDepth : -1; -} - -inline CUtlSymbol CDmElement::GetStaticTypeSymbol() -{ - return m_classType; -} - -inline bool CDmElement::IsA( const char *pTypeName ) const -{ - CUtlSymbol typeSymbol = g_pDataModel->GetSymbol( pTypeName ); - return IsA( typeSymbol ); -} - -template< class E > inline bool CDmElement::IsA() const -{ - return IsA( E::GetStaticTypeSymbol() ); -} - - -//----------------------------------------------------------------------------- -// Helper for finding elements that refer to this element -//----------------------------------------------------------------------------- -template< class T > -T *FindReferringElement( CDmElement *pElement, const char *pAttrName, bool bMustBeInSameFile = true ) -{ - return FindReferringElement< T >( pElement, g_pDataModel->GetSymbol( pAttrName ), bMustBeInSameFile ); -} - -template< class T > -T *FindReferringElement( CDmElement *pElement, UtlSymId_t symAttrName, bool bMustBeInSameFile = true ) -{ - DmAttributeReferenceIterator_t i = g_pDataModel->FirstAttributeReferencingElement( pElement->GetHandle() ); - while ( i != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID ) - { - CDmAttribute *pAttribute = g_pDataModel->GetAttribute( i ); - CDmElement *pDmeParent = pAttribute->GetOwner(); - if ( pDmeParent && pAttribute->GetNameSymbol() == symAttrName ) - { - T *pParent = CastElement< T >( pDmeParent ); - if ( pParent ) - { - if ( !bMustBeInSameFile || ( pParent->GetFileId() == pElement->GetFileId() ) ) - return pParent; - } - } - i = g_pDataModel->NextAttributeReferencingElement( i ); - } - - return NULL; -} - - -void RemoveElementFromRefereringAttributes( CDmElement *pElement, bool bPreserveOrder = true ); - - -template< class T > -void FindAncestorsReferencingElement( CDmElement *target, CUtlVector< T* >& list ) -{ - if ( !target ) - return; - - list.RemoveAll(); - for ( DmAttributeReferenceIterator_t it = g_pDataModel->FirstAttributeReferencingElement( target->GetHandle() ); - it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID; - it = g_pDataModel->NextAttributeReferencingElement( it ) ) - { - CDmAttribute *attr = g_pDataModel->GetAttribute( it ); - Assert( attr ); - CDmElement *element = attr->GetOwner(); - Assert( element ); - if ( !element ) - continue; - T* t = CastElement< T >( element ); - if ( !t ) - continue; - - if ( list.Find( t ) != list.InvalidIndex() ) - continue; - - list.AddToTail( t ); - } -} - -template< class T > -T *FindAncestorReferencingElement( CDmElement *target ) -{ - if ( !target ) - return NULL; - - for ( DmAttributeReferenceIterator_t it = g_pDataModel->FirstAttributeReferencingElement( target->GetHandle() ); - it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID; - it = g_pDataModel->NextAttributeReferencingElement( it ) ) - { - CDmAttribute *attr = g_pDataModel->GetAttribute( it ); - Assert( attr ); - CDmElement *element = attr->GetOwner(); - Assert( element ); - if ( !element ) - continue; - T *t = CastElement< T >( element ); - if ( !t ) - continue; - - return t; - } - return NULL; -} - -template< class T > -T *FindAncestorReferencingElement_R_Impl( CUtlRBTree< CDmElement * >& visited, CDmElement *check ) -{ - if ( visited.Find( check ) != visited.InvalidIndex() ) - return NULL; - - visited.Insert( check ); - - // Pass one, see if it's in this ancestor list - DmAttributeReferenceIterator_t it; - for ( it = g_pDataModel->FirstAttributeReferencingElement( check->GetHandle() ); - it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID; - it = g_pDataModel->NextAttributeReferencingElement( it ) ) - { - CDmAttribute *attr = g_pDataModel->GetAttribute( it ); - Assert( attr ); - CDmElement *element = attr->GetOwner(); - Assert( element ); - if ( !element ) - continue; - T *t = CastElement< T >( element ); - if ( !t ) - continue; - - return t; - } - - for ( it = g_pDataModel->FirstAttributeReferencingElement( check->GetHandle() ); - it != DMATTRIBUTE_REFERENCE_ITERATOR_INVALID; - it = g_pDataModel->NextAttributeReferencingElement( it ) ) - { - CDmAttribute *attr = g_pDataModel->GetAttribute( it ); - Assert( attr ); - CDmElement *element = attr->GetOwner(); - Assert( element ); - if ( !element ) - continue; - - T *found = FindAncestorReferencingElement_R_Impl< T >( visited, element ); - if ( found ) - return found; - } - return NULL; -} - -template< class T > -T *FindAncestorReferencingElement_R( CDmElement *target ) -{ - if ( !target ) - return NULL; - - CUtlRBTree< CDmElement * > visited( 0, 0, DefLessFunc( CDmElement * ) ); - return FindAncestorReferencingElement_R_Impl< T >( visited, target ); -} - - -//----------------------------------------------------------------------------- -// -// element-specific unique name generation methods -// -//----------------------------------------------------------------------------- - -// returns startindex if none found, 2 if only "prefix" found, and n+1 if "prefixn" found -int GenerateUniqueNameIndex( const char *prefix, const CUtlVector< DmElementHandle_t > &array, int startindex = -1 ); - -bool GenerateUniqueName( char *name, int memsize, const char *prefix, const CUtlVector< DmElementHandle_t > &array ); - -void MakeElementNameUnique( CDmElement *pElement, const char *prefix, const CUtlVector< DmElementHandle_t > &array, bool forceIndex = false ); - - -//----------------------------------------------------------------------------- -// helper for making attributevarelementarray cleanup easier -//----------------------------------------------------------------------------- -template< class T > -inline void CDmElement::DeleteAttributeVarElementArray( T &array ) -{ - int nElements = array.Count(); - for ( int i = 0; i < nElements; ++i ) - { - g_pDataModel->DestroyElement( array.GetHandle( i ) ); - } - array.RemoveAll(); -} - - -//----------------------------------------------------------------------------- -// Default size computation -//----------------------------------------------------------------------------- -template< class T > -int DmeEstimateMemorySize( T* pElement ) -{ - return sizeof( T ); -} - - -//----------------------------------------------------------------------------- -// Helper macro to create an element; this is used for elements that are helper base classes -//----------------------------------------------------------------------------- -#define DEFINE_UNINSTANCEABLE_ELEMENT( className, baseClassName ) \ - protected: \ - className( DmElementHandle_t handle, const char *pElementTypeName, const DmObjectId_t &id, const char *pElementName, DmFileId_t fileid ) : \ - baseClassName( handle, pElementTypeName, id, pElementName, fileid ) \ - { \ - } \ - virtual ~className() \ - { \ - } \ - void OnConstruction(); \ - void OnDestruction(); \ - virtual void PerformConstruction() \ - { \ - BaseClass::PerformConstruction(); \ - OnConstruction(); \ - } \ - virtual void PerformDestruction() \ - { \ - OnDestruction(); \ - BaseClass::PerformDestruction(); \ - } \ - virtual int AllocatedSize() const { return DmeEstimateMemorySize( this ); } \ - \ - private: \ - typedef baseClassName BaseClass; \ - - -//----------------------------------------------------------------------------- -// Helper macro to create the class factory -//----------------------------------------------------------------------------- -#define DEFINE_ELEMENT( className, baseClassName ) \ - public: \ - virtual bool IsA( UtlSymId_t typeSymbol ) const \ - { \ - return IsA_Implementation( typeSymbol );\ - } \ - \ - bool IsA( const char *pTypeName ) const \ - { \ - CUtlSymbol typeSymbol = g_pDataModel->GetSymbol( pTypeName ); \ - return IsA( typeSymbol ); \ - } \ - \ - template< class T > bool IsA() const \ - { \ - return IsA( T::GetStaticTypeSymbol() ); \ - } \ - \ - virtual int GetInheritanceDepth( UtlSymId_t typeSymbol ) const \ - { \ - return GetInheritanceDepth_Implementation( typeSymbol, 0 ); \ - } \ - \ - static CUtlSymbol GetStaticTypeSymbol( ) \ - { \ - return m_classType; \ - } \ - \ - className* Copy( TraversalDepth_t depth = TD_DEEP ) const \ - { \ - return static_cast< className* >( CopyInternal( depth ) ); \ - } \ - protected: \ - className( DmElementHandle_t handle, const char *pElementTypeName, const DmObjectId_t &id, const char *pElementName, DmFileId_t fileid ) : \ - baseClassName( handle, pElementTypeName, id, pElementName, fileid ) \ - { \ - } \ - virtual ~className() \ - { \ - } \ - void OnConstruction(); \ - void OnDestruction(); \ - virtual void PerformConstruction() \ - { \ - BaseClass::PerformConstruction(); \ - OnConstruction(); \ - } \ - virtual void PerformDestruction() \ - { \ - OnDestruction(); \ - BaseClass::PerformDestruction(); \ - } \ - static void SetTypeSymbol( CUtlSymbol typeSymbol ) \ - { \ - m_classType = typeSymbol; \ - } \ - \ - static bool IsA_Implementation( CUtlSymbol typeSymbol ) \ - { \ - if ( typeSymbol == m_classType ) \ - return true; \ - return BaseClass::IsA_Implementation( typeSymbol ); \ - } \ - \ - static int GetInheritanceDepth_Implementation( CUtlSymbol typeSymbol, int nCurrentDepth ) \ - { \ - if ( typeSymbol == m_classType ) \ - return nCurrentDepth; \ - return BaseClass::GetInheritanceDepth_Implementation( typeSymbol, nCurrentDepth+1 );\ - } \ - virtual int AllocatedSize() const { return DmeEstimateMemorySize( this ); } \ - \ - private: \ - typedef baseClassName BaseClass; \ - template friend class CDmElementFactory; \ - template friend class CDmAbstractElementFactory; \ - static CUtlSymbol m_classType - -#define IMPLEMENT_ELEMENT( className ) \ - CUtlSymbol className::m_classType = UTL_INVAL_SYMBOL; - - -#endif // DMELEMENT_H diff --git a/public/datamodel/dmelementfactoryhelper.h b/public/datamodel/dmelementfactoryhelper.h deleted file mode 100644 index 17a236758..000000000 --- a/public/datamodel/dmelementfactoryhelper.h +++ /dev/null @@ -1,188 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef DMELEMENTFACTORYHELPER_H -#define DMELEMENTFACTORYHELPER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "datamodel/idatamodel.h" -#include "datamodel/dmelement.h" -#include "tier1/utlvector.h" -#include "tier1/utlsymbol.h" - - -//----------------------------------------------------------------------------- -// Internal interface for IDmElementFactory -//----------------------------------------------------------------------------- -class IDmElementFactoryInternal : public IDmElementFactory -{ -public: - virtual void SetElementTypeSymbol( CUtlSymbol sym ) = 0; - virtual bool IsAbstract() const = 0; -}; - - -//----------------------------------------------------------------------------- -// Class used to register factories into a global list -//----------------------------------------------------------------------------- -class CDmElementFactoryHelper -{ -public: - // Static list of helpers - static CDmElementFactoryHelper *s_pHelpers[2]; - - // Create all the hud elements - static void InstallFactories( ); - -public: - // Construction - CDmElementFactoryHelper( const char *pClassName, IDmElementFactoryInternal *pFactory, bool bIsStandardFactory ); - - // Accessors - CDmElementFactoryHelper *GetNext( void ); - - const char *GetClassname(); - IDmElementFactoryInternal *GetFactory(); - -private: - // Next factory in list - CDmElementFactoryHelper *m_pNext; - // Creation function to use for this technology - IDmElementFactoryInternal *m_pFactory; - const char *m_pszClassname; -}; - - -//----------------------------------------------------------------------------- -// Inline methods -//----------------------------------------------------------------------------- -inline const char *CDmElementFactoryHelper::GetClassname() -{ - return m_pszClassname; -} - -inline IDmElementFactoryInternal *CDmElementFactoryHelper::GetFactory() -{ - return m_pFactory; -} - - -//----------------------------------------------------------------------------- -// Helper Template factory for simple creation of factories -//----------------------------------------------------------------------------- -template -class CDmElementFactory : public IDmElementFactoryInternal -{ -public: - CDmElementFactory( const char *pLookupName ) : m_pLookupName( pLookupName ) {} - - // Creation, destruction - virtual CDmElement* Create( DmElementHandle_t handle, const char *pElementType, const char *pElementName, DmFileId_t fileid, const DmObjectId_t &id ) - { - return new T( handle, m_pLookupName, id, pElementName, fileid ); - } - - virtual void Destroy( DmElementHandle_t hElement ) - { - CDmElement *pElement = g_pDataModel->GetElement( hElement ); - if ( pElement ) - { - T *pActualElement = static_cast< T* >( pElement ); - delete pActualElement; - } - } - - // Sets the type symbol, used for "isa" implementation - virtual void SetElementTypeSymbol( CUtlSymbol sym ) - { - T::SetTypeSymbol( sym ); - } - - virtual bool IsAbstract() const { return false; } - -private: - const char *m_pLookupName; -}; - - -template < class T > -class CDmAbstractElementFactory : public IDmElementFactoryInternal -{ -public: - CDmAbstractElementFactory() {} - - // Creation, destruction - virtual CDmElement* Create( DmElementHandle_t handle, const char *pElementType, const char *pElementName, DmFileId_t fileid, const DmObjectId_t &id ) - { - return NULL; - } - - virtual void Destroy( DmElementHandle_t hElement ) - { - } - - // Sets the type symbol, used for "isa" implementation - virtual void SetElementTypeSymbol( CUtlSymbol sym ) - { - T::SetTypeSymbol( sym ); - } - - virtual bool IsAbstract() const { return true; } - -private: -}; - - -//----------------------------------------------------------------------------- -// Helper macro to create the class factory -//----------------------------------------------------------------------------- -#if defined( MOVIEOBJECTS_LIB ) || defined ( DATAMODEL_LIB ) || defined ( DMECONTROLS_LIB ) - -#define IMPLEMENT_ELEMENT_FACTORY( lookupName, className ) \ - IMPLEMENT_ELEMENT( className ) \ - CDmElementFactory< className > g_##className##_Factory( #lookupName ); \ - CDmElementFactoryHelper g_##className##_Helper( #lookupName, &g_##className##_Factory, true ); \ - className *g_##className##LinkerHack = NULL; - -#define IMPLEMENT_ABSTRACT_ELEMENT( lookupName, className ) \ - IMPLEMENT_ELEMENT( className ) \ - CDmAbstractElementFactory< className > g_##className##_Factory; \ - CDmElementFactoryHelper g_##className##_Helper( #lookupName, &g_##className##_Factory, true ); \ - className *g_##className##LinkerHack = NULL; - -#else - -#define IMPLEMENT_ELEMENT_FACTORY( lookupName, className ) \ - IMPLEMENT_ELEMENT( className ) \ - CDmElementFactory< className > g_##className##_Factory( #lookupName ); \ - CDmElementFactoryHelper g_##className##_Helper( #lookupName, &g_##className##_Factory, false ); \ - className *g_##className##LinkerHack = NULL; - -#define IMPLEMENT_ABSTRACT_ELEMENT( lookupName, className ) \ - IMPLEMENT_ELEMENT( className ) \ - CDmAbstractElementFactory< className > g_##className##_Factory; \ - CDmElementFactoryHelper g_##className##_Helper( #lookupName, &g_##className##_Factory, false ); \ - className *g_##className##LinkerHack = NULL; - -#endif - - -// Used by classes defined in movieobjects or scenedatabase that must be explicitly installed -#define IMPLEMENT_ELEMENT_FACTORY_INSTALL_EXPLICITLY( lookupName, className ) \ - IMPLEMENT_ELEMENT( className ) \ - CDmElementFactory< className > g_##className##_Factory( #lookupName ); \ - CDmElementFactoryHelper g_##className##_Helper( #lookupName, &g_##className##_Factory, false ); \ - className *g_##className##LinkerHack = NULL; - -//----------------------------------------------------------------------------- -// Installs dm element factories -//----------------------------------------------------------------------------- -void InstallDmElementFactories( ); - - -#endif // DMELEMENTFACTORYHELPER_H diff --git a/public/datamodel/dmelementhandle.h b/public/datamodel/dmelementhandle.h deleted file mode 100644 index 6db43202d..000000000 --- a/public/datamodel/dmelementhandle.h +++ /dev/null @@ -1,47 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef DMELEMENTHANDLE_H -#define DMELEMENTHANDLE_H - -#ifdef _WIN32 -#pragma once -#endif - - -//----------------------------------------------------------------------------- -// handle to an CDmElement -//----------------------------------------------------------------------------- -#define PERFORM_HANDLE_TYPECHECKING 0 -#if PERFORM_HANDLE_TYPECHECKING - -// this is here to make sure we're being type-safe about element handles -// otherwise, the compiler lets us cast to bool incorrectly -// the other solution would be to redefine DmElementHandle_t s.t. DMELEMENT_HANDLE_INVALID==0 -struct DmElementHandle_t -{ - DmElementHandle_t() : handle( 0xffffffff ) {} - explicit DmElementHandle_t( int h ) : handle( h ) {} - inline bool operator==( const DmElementHandle_t &h ) const { return handle == h.handle; } - inline bool operator!=( const DmElementHandle_t &h ) const { return handle != h.handle; } - inline bool operator<( const DmElementHandle_t &h ) const { return handle < h.handle; } -// inline operator int() const { return handle; } // if we're okay with implicit int casts, uncomment this method - int handle; -}; -const DmElementHandle_t DMELEMENT_HANDLE_INVALID; - -#else // PERFORM_HANDLE_TYPECHECKING - -enum DmElementHandle_t -{ - DMELEMENT_HANDLE_INVALID = 0xffffffff -}; - -#endif // PERFORM_HANDLE_TYPECHECKING - - - -#endif // DMELEMENTHANDLE_H diff --git a/public/datamodel/dmvar.h b/public/datamodel/dmvar.h deleted file mode 100644 index 689834ba6..000000000 --- a/public/datamodel/dmvar.h +++ /dev/null @@ -1,93 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef DMVAR_H -#define DMVAR_H -#ifdef _WIN32 -#pragma once -#endif - - -class CDmAttribute; - -//----------------------------------------------------------------------------- -// Helper template for external attributes -//----------------------------------------------------------------------------- -template< typename T > -class CDmaVar -{ - typedef typename CDmAttributeInfo< T >::StorageType_t D; - -public: - CDmaVar( ); - - // Setup to be used in OnConstruction methods of DmElements - void Init( CDmElement *pOwner, const char *pAttributeName, int flags = 0 ); - void InitAndSet( CDmElement *pOwner, const char *pAttributeName, const T &value, int flags = 0 ); - - // Set/get - const T& Set( const T &val ); - const T& Get() const; - - // Cast operators - operator const T&() const; - const T* operator->() const; - - // Assignment operator - const CDmaVar& operator=( const CDmaVar& src ); - - // Math utility operations - const T& operator=( const T &val ); - const T& operator+=( const T &val ); - const T& operator-=( const T &val ); - const T& operator/=( const T &val ); - const T& operator*=( const T &val ); - const T& operator^=( const T &val ); - const T& operator|=( const T &val ); - const T& operator&=( const T &val ); - T operator++(); - T operator--(); - T operator++( int ); // postfix version.. - T operator--( int ); // postfix version.. - - // Returns the attribute associated with the var - CDmAttribute *GetAttribute(); - const CDmAttribute *GetAttribute() const; - - // Is the attribute dirty? - bool IsDirty() const; - -protected: - const T& Value() const; - T& Value(); - const D& Storage() const; - D& Storage(); - -private: - D m_Storage; - -protected: - CDmAttribute *m_pAttribute; -}; - -//----------------------------------------------------------------------------- -// Specialization for string -//----------------------------------------------------------------------------- -class CDmaString : public CDmaVar< CUtlString > -{ -public: - const char *Get( ) const; - operator const char*() const; - - void Set( const char *pValue ); - CDmaString &operator=( const char *src ); - const CDmaString& operator=( const CDmaString& src ); - - // Returns strlen - int Length() const; -}; - -#endif // DMVAR_H diff --git a/public/datamodel/idatamodel.h b/public/datamodel/idatamodel.h deleted file mode 100644 index c4e087d0a..000000000 --- a/public/datamodel/idatamodel.h +++ /dev/null @@ -1,938 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef IDATAMODEL_H -#define IDATAMODEL_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/interface.h" -#include "tier1/utlvector.h" -#include "tier1/utlsymbol.h" -#include "appframework/IAppSystem.h" -#include "datamodel/dmattributetypes.h" - - -//----------------------------------------------------------------------------- -// Forward declarations: -//----------------------------------------------------------------------------- -class CDmAttribute; -class CDmElement; -class IDmeOperator; -class IElementForKeyValueCallback; - -struct DmValueBase_t; -class CUtlBuffer; -class KeyValues; -class CUtlSymbolTable; -class CUtlCharConversion; - - -//----------------------------------------------------------------------------- -// data file format info -//----------------------------------------------------------------------------- -#define DMX_LEGACY_VERSION_STARTING_TOKEN "" - -#define DMX_VERSION_STARTING_TOKEN "" - -#define GENERIC_DMX_FORMAT "dmx" - - -enum -{ - DMX_MAX_FORMAT_NAME_MAX_LENGTH = 64, - DMX_MAX_HEADER_LENGTH = 40 + 2 * DMX_MAX_FORMAT_NAME_MAX_LENGTH, -}; - -struct DmxHeader_t -{ - char encodingName[ DMX_MAX_FORMAT_NAME_MAX_LENGTH ]; - int nEncodingVersion; - char formatName[ DMX_MAX_FORMAT_NAME_MAX_LENGTH ]; - int nFormatVersion; - - DmxHeader_t() : nEncodingVersion( -1 ), nFormatVersion( -1 ) - { - encodingName[ 0 ] = formatName[ 0 ] = '\0'; - } -}; - - -//----------------------------------------------------------------------------- -// element framework phases -//----------------------------------------------------------------------------- -enum DmPhase_t -{ - PH_EDIT, - PH_EDIT_APPLY, - PH_EDIT_RESOLVE, - PH_DEPENDENCY, - PH_OPERATE, - PH_OPERATE_RESOLVE, - PH_OUTPUT, -}; - - -//----------------------------------------------------------------------------- -// file id - also used to refer to elements that don't have file associations -//----------------------------------------------------------------------------- -enum DmFileId_t -{ - DMFILEID_INVALID = 0xffffffff -}; - -//----------------------------------------------------------------------------- -// Handle to an CDmAttribute -//----------------------------------------------------------------------------- -enum DmAttributeHandle_t -{ - DMATTRIBUTE_HANDLE_INVALID = 0xffffffff -}; - -//----------------------------------------------------------------------------- -// Handle to an DmAttributeList_t -//----------------------------------------------------------------------------- -enum DmAttributeReferenceIterator_t -{ - DMATTRIBUTE_REFERENCE_ITERATOR_INVALID = 0 -}; - -//----------------------------------------------------------------------------- -// element framework interface -//----------------------------------------------------------------------------- -abstract_class IDmElementFramework : public IAppSystem -{ -public: - // Methods of IAppSystem - virtual bool Connect( CreateInterfaceFn factory ) = 0; - virtual void Disconnect() = 0; - virtual void *QueryInterface( const char *pInterfaceName ) = 0; - virtual InitReturnVal_t Init() = 0; - virtual void Shutdown() = 0; - - virtual DmPhase_t GetPhase() = 0; - - virtual void SetOperators( const CUtlVector< IDmeOperator* > &operators ) = 0; - - virtual void BeginEdit() = 0; // ends in edit phase, forces apply/resolve if from edit phase - virtual void Operate( bool bResolve ) = 0; // ends in output phase - virtual void Resolve() = 0; -}; - - -//----------------------------------------------------------------------------- -// Used only by aplpications to hook in the element framework -//----------------------------------------------------------------------------- -#define VDMELEMENTFRAMEWORK_VERSION "VDmElementFrameworkVersion001" - - -//----------------------------------------------------------------------------- -// Main interface -//----------------------------------------------------------------------------- -extern IDmElementFramework *g_pDmElementFramework; - - -//----------------------------------------------------------------------------- -// datamodel operator interface - for all elements that need to be sorted in the operator dependency graph -//----------------------------------------------------------------------------- -abstract_class IDmeOperator -{ -public: - virtual bool IsDirty() = 0; // ie needs to operate - virtual void Operate() = 0; - - virtual void GetInputAttributes ( CUtlVector< CDmAttribute * > &attrs ) = 0; - virtual void GetOutputAttributes( CUtlVector< CDmAttribute * > &attrs ) = 0; -}; - -//----------------------------------------------------------------------------- -// Class factory methods: -//----------------------------------------------------------------------------- -class IDmElementFactory -{ -public: - // Creation, destruction - virtual CDmElement* Create( DmElementHandle_t handle, const char *pElementType, const char *pElementName, DmFileId_t fileid, const DmObjectId_t &id ) = 0; - virtual void Destroy( DmElementHandle_t hElement ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Various serialization methods can be installed into the data model factory -//----------------------------------------------------------------------------- -enum DmConflictResolution_t -{ - CR_DELETE_NEW, - CR_DELETE_OLD, - CR_COPY_NEW, - CR_FORCE_COPY, -}; - -// convert files to elements and back -// current file encodings supported: binary, xml, xml_flat, keyvalues2, keyvalues2_flat, keyvalues (vmf/vmt/actbusy), text? (qc/obj) -class IDmSerializer -{ -public: - virtual const char *GetName() const = 0; - virtual const char *GetDescription() const = 0; - virtual bool IsBinaryFormat() const = 0; - virtual bool StoresVersionInFile() const = 0; - virtual int GetCurrentVersion() const = 0; - - // Write into the UtlBuffer, return true if successful - // if we decide to implement non-identity conversions between formats on write, then the source and dest format will need to be passed in here - virtual bool Serialize( CUtlBuffer &buf, CDmElement *pRoot ) = 0; - - // Read from the UtlBuffer, return true if successful, and return the read-in root in ppRoot. - virtual bool Unserialize( CUtlBuffer &buf, const char *pEncodingName, int nEncodingVersion, - const char *pSourceFormatName, int nSourceFormatVersion, - DmFileId_t fileid, DmConflictResolution_t idConflictResolution, CDmElement **ppRoot ) = 0; -}; - -// convert legacy elements to non-legacy elements -// legacy formats include: binary_vN, keyvalues2_v1, keyvalues2_flat_v1, xml, xml_flat -// where N is a version number -class IDmLegacyUpdater -{ -public: - virtual const char *GetName() const = 0; - virtual bool IsLatestVersion() const = 0; - - // Updates ppRoot to first non-legacy generic dmx format, returns false if the conversion fails - virtual bool Update( CDmElement **ppRoot ) = 0; -}; - -// converts old elements to new elements -// current formats include: animset presets, particle definitions, exported maya character, etc. -class IDmFormatUpdater -{ -public: - virtual const char *GetName() const = 0; - virtual const char *GetDescription() const = 0; - virtual const char *GetExtension() const = 0; - virtual int GetCurrentVersion() const = 0; - virtual const char *GetDefaultEncoding() const = 0; - - // Converts pSourceRoot from nSourceVersion to the current version, returns false if the conversion fails - virtual bool Update( CDmElement **pRoot, int nSourceVersion ) = 0; -}; - -//----------------------------------------------------------------------------- -// Interface for callbacks to supply element types for specific keys inside keyvalues files -//----------------------------------------------------------------------------- -class IElementForKeyValueCallback -{ -public: - virtual const char *GetElementForKeyValue( const char *pszKeyName, int iNestingLevel ) = 0; -}; - -//----------------------------------------------------------------------------- -// Purpose: Optional helper passed in with clipboard data which is called when it's time to clean up the clipboard data in case the application -// had some dynamically allocated data attached to a KV SetPtr object... -//----------------------------------------------------------------------------- -abstract_class IClipboardCleanup -{ -public: - virtual void ReleaseClipboardData( CUtlVector< KeyValues * >& list ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Can be installed to be called back when data changes -//----------------------------------------------------------------------------- -enum DmNotifySource_t -{ - // Sources - NOTIFY_SOURCE_APPLICATION = 0, - NOTIFY_SOURCE_UNDO, - NOTIFY_SOURCE_FIRST_DME_CONTROL_SOURCE = 4, // Sources from dme_controls starts here - NOTIFY_SOURCE_FIRST_APPLICATION_SOURCE = 8, // Sources from applications starts here -}; - -enum DmNotifyFlags_t -{ - // Does this dirty the document? - NOTIFY_SOURCE_BITS = 8, - NOTIFY_SETDIRTYFLAG = (1<& list ) = 0; - - virtual void AddUndoElement( IUndoElement *pElement ) = 0; - virtual UtlSymId_t GetUndoDescInternal( const char *context ) = 0; - virtual UtlSymId_t GetRedoDescInternal( const char *context ) = 0; - - virtual void EmptyClipboard() = 0; - virtual void SetClipboardData( CUtlVector< KeyValues * >& data, IClipboardCleanup *pfnOptionalCleanuFunction = 0 ) = 0; - virtual void AddToClipboardData( KeyValues *add ) = 0; - virtual void GetClipboardData( CUtlVector< KeyValues * >& data ) = 0; - virtual bool HasClipboardData() const = 0; - - // Handles to attributes - virtual CDmAttribute * GetAttribute( DmAttributeHandle_t h ) = 0; - virtual bool IsAttributeHandleValid( DmAttributeHandle_t h ) const = 0; - - // file id reference methods - virtual int NumFileIds() = 0; - virtual DmFileId_t GetFileId( int i ) = 0; - virtual DmFileId_t FindOrCreateFileId( const char *pFilename ) = 0; - virtual void RemoveFileId( DmFileId_t fileid ) = 0; - virtual DmFileId_t GetFileId( const char *pFilename ) = 0; - virtual const char * GetFileName( DmFileId_t fileid ) = 0; - virtual void SetFileName( DmFileId_t fileid, const char *pFileName ) = 0; - virtual const char * GetFileFormat( DmFileId_t fileid ) = 0; - virtual void SetFileFormat( DmFileId_t fileid, const char *pFormat ) = 0; - virtual DmElementHandle_t GetFileRoot( DmFileId_t fileid ) = 0; - virtual void SetFileRoot( DmFileId_t fileid, DmElementHandle_t hRoot ) = 0; - virtual bool IsFileLoaded( DmFileId_t fileid ) = 0; - virtual void MarkFileLoaded( DmFileId_t fileid ) = 0; - virtual void UnloadFile( DmFileId_t fileid ) = 0; - virtual int NumElementsInFile( DmFileId_t fileid ) = 0; - - virtual void DontAutoDelete( DmElementHandle_t hElement ) = 0; - - // handle validity methods - these shouldn't really be here, but the undo system needs them... - virtual void MarkHandleInvalid( DmElementHandle_t hElement ) = 0; - virtual void MarkHandleValid( DmElementHandle_t hElement ) = 0; - - virtual DmElementHandle_t FindElement( const DmObjectId_t &id ) = 0; - - virtual DmAttributeReferenceIterator_t FirstAttributeReferencingElement( DmElementHandle_t hElement ) = 0; - virtual DmAttributeReferenceIterator_t NextAttributeReferencingElement( DmAttributeReferenceIterator_t hAttrIter ) = 0; - virtual CDmAttribute * GetAttribute( DmAttributeReferenceIterator_t hAttrIter ) = 0; - - // Install, remove notify callbacks associated w/ undo contexts - virtual bool InstallNotificationCallback( IDmNotify *pNotify ) = 0; - virtual void RemoveNotificationCallback( IDmNotify *pNotify ) = 0; - virtual bool IsSuppressingNotify( ) const = 0; - virtual void SetSuppressingNotify( bool bSuppress ) = 0; - virtual void PushNotificationScope( const char *pReason, int nNotifySource, int nNotifyFlags ) = 0; - virtual void PopNotificationScope( bool bAbort = false ) = 0; - virtual const char *GetUndoString( UtlSymId_t sym ) = 0; - - virtual bool HasElementFactory( const char *pElementType ) const = 0; - - // Call before you make any undo records - virtual void SetUndoDepth( int nSize ) = 0; - - // Displats memory stats to the console - virtual void DisplayMemoryStats() = 0; -}; - - -//----------------------------------------------------------------------------- -// Used only by applications to hook in the data model -//----------------------------------------------------------------------------- -#define VDATAMODEL_INTERFACE_VERSION "VDataModelVersion001" - - -//----------------------------------------------------------------------------- -// Main interface accessor -//----------------------------------------------------------------------------- -extern IDataModel *g_pDataModel; - - -//----------------------------------------------------------------------------- -// Allows clients to implement customized undo elements -//----------------------------------------------------------------------------- -class CUndoElement : public IUndoElement -{ -public: - CUndoElement( const char *pDesc ) - { - m_UndoDesc = g_pDataModel->GetUndoDescInternal( pDesc ); - m_RedoDesc = g_pDataModel->GetRedoDescInternal( pDesc ); - m_pDesc = pDesc; - m_bEndOfStream = false; - } - - virtual void Release() - { - delete this; - } - - virtual const char *UndoDesc() const - { - return g_pDataModel->GetUndoString( m_UndoDesc ); - } - - virtual const char *RedoDesc() const - { - return g_pDataModel->GetUndoString( m_RedoDesc ); - } - - virtual const char *GetDesc() const - { - return m_pDesc; - } - -protected: - virtual bool IsEndOfStream() const - { - return m_bEndOfStream; - } - - virtual void SetEndOfStream( bool end ) - { - m_bEndOfStream = end; - } - - const char *m_pDesc; - CUtlSymbol m_UndoDesc; - CUtlSymbol m_RedoDesc; - bool m_bEndOfStream; - -private: - friend class CUndoManager; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Simple helper class -//----------------------------------------------------------------------------- -class CUndoScopeGuard -{ -public: - explicit CUndoScopeGuard( const char *udesc, const char *rdesc = NULL ) - { - m_bReleased = false; - m_bNotify = false; - m_pNotify = NULL; - g_pDataModel->StartUndo( udesc, rdesc ? rdesc : udesc ); - } - - explicit CUndoScopeGuard( int nChainingID, char const *udesc ) - { - m_bReleased = false; - m_bNotify = false; - m_pNotify = NULL; - g_pDataModel->StartUndo( udesc, udesc, nChainingID ); - } - - explicit CUndoScopeGuard( int nNotifySource, int nNotifyFlags, const char *udesc, const char *rdesc = NULL, int nChainingID = 0 ) - { - m_bReleased = false; - m_bNotify = true; - m_pNotify = NULL; - g_pDataModel->StartUndo( udesc, rdesc ? rdesc : udesc, nChainingID ); - g_pDataModel->PushNotificationScope( udesc, nNotifySource, nNotifyFlags ); - } - - explicit CUndoScopeGuard( int nNotifySource, int nNotifyFlags, IDmNotify *pNotify, const char *udesc, const char *rdesc = NULL, int nChainingID = 0 ) - { - m_bReleased = false; - m_bNotify = true; - m_pNotify = NULL; - g_pDataModel->StartUndo( udesc, rdesc ? rdesc : udesc, nChainingID ); - if ( pNotify ) - { - if ( g_pDataModel->InstallNotificationCallback( pNotify ) ) - { - m_pNotify = pNotify; - } - } - g_pDataModel->PushNotificationScope( udesc, nNotifySource, nNotifyFlags ); - } - - ~CUndoScopeGuard() - { - Release(); - } - - void Release() - { - if ( !m_bReleased ) - { - g_pDataModel->FinishUndo(); - if ( m_bNotify ) - { - g_pDataModel->PopNotificationScope( ); - m_bNotify = false; - } - if ( m_pNotify ) - { - g_pDataModel->RemoveNotificationCallback( m_pNotify ); - m_pNotify = NULL; - } - m_bReleased = true; - } - } - - void Abort() - { - if ( !m_bReleased ) - { - g_pDataModel->AbortUndoableOperation(); - if ( m_bNotify ) - { - g_pDataModel->PopNotificationScope( true ); - m_bNotify = false; - } - if ( m_pNotify ) - { - g_pDataModel->RemoveNotificationCallback( m_pNotify ); - m_pNotify = NULL; - } - m_bReleased = true; - } - } - -private: - IDmNotify *m_pNotify; - bool m_bReleased; - bool m_bNotify; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Simple helper class to disable Undo/Redo operations when in scope -//----------------------------------------------------------------------------- -class CChangeUndoScopeGuard -{ -public: - CChangeUndoScopeGuard( bool bNewState ) - { - m_bReleased = false; - m_bNotify = false; - m_pNotify = NULL; - m_bOldValue = g_pDataModel->IsUndoEnabled(); - g_pDataModel->SetUndoEnabled( bNewState ); - }; - - CChangeUndoScopeGuard( bool bNewState, const char *pDesc, int nNotifySource, int nNotifyFlags, IDmNotify *pNotify = NULL ) - { - m_bReleased = false; - m_bOldValue = g_pDataModel->IsUndoEnabled(); - g_pDataModel->SetUndoEnabled( bNewState ); - - m_bNotify = true; - m_pNotify = NULL; - if ( pNotify ) - { - if ( g_pDataModel->InstallNotificationCallback( pNotify ) ) - { - m_pNotify = pNotify; - } - } - g_pDataModel->PushNotificationScope( pDesc, nNotifySource, nNotifyFlags ); - }; - - ~CChangeUndoScopeGuard() - { - Release(); - } - - void Release() - { - // Releases the guard... - if ( !m_bReleased ) - { - g_pDataModel->SetUndoEnabled( m_bOldValue ); - m_bReleased = true; - if ( m_bNotify ) - { - g_pDataModel->PopNotificationScope( ); - m_bNotify = false; - } - if ( m_pNotify ) - { - g_pDataModel->RemoveNotificationCallback( m_pNotify ); - m_pNotify = NULL; - } - } - } - -private: - IDmNotify *m_pNotify; - bool m_bOldValue; - bool m_bReleased; - bool m_bNotify; -}; - -class CDisableUndoScopeGuard : public CChangeUndoScopeGuard -{ - typedef CChangeUndoScopeGuard BaseClass; - -public: - CDisableUndoScopeGuard() : BaseClass( false ) { } - CDisableUndoScopeGuard( const char *pDesc, int nNotifySource, int nNotifyFlags, IDmNotify *pNotify = NULL ) : - BaseClass( false, pDesc, nNotifySource, nNotifyFlags, pNotify ) {} -}; - -class CEnableUndoScopeGuard : public CChangeUndoScopeGuard -{ - typedef CChangeUndoScopeGuard BaseClass; - -public: - CEnableUndoScopeGuard( ) : BaseClass( true ) { } - CEnableUndoScopeGuard( const char *pDesc, int nNotifySource, int nNotifyFlags, IDmNotify *pNotify = NULL ) : - BaseClass( true, pDesc, nNotifySource, nNotifyFlags, pNotify ) {} -}; - - -#define DEFINE_SOURCE_UNDO_SCOPE_GUARD( _classnameprefix, _source ) \ - class C ## _classnameprefix ## UndoScopeGuard : public CUndoScopeGuard \ - { \ - typedef CUndoScopeGuard BaseClass; \ - \ - public: \ - C ## _classnameprefix ## UndoScopeGuard( int nNotifyFlags, const char *pUndoDesc, const char *pRedoDesc = NULL, int nChainingID = 0 ) : \ - BaseClass( _source, nNotifyFlags, pUndoDesc, pRedoDesc, nChainingID ) \ - { \ - } \ - C ## _classnameprefix ## UndoScopeGuard( int nNotifyFlags, IDmNotify *pNotify, const char *pUndoDesc, const char *pRedoDesc = NULL, int nChainingID = 0 ) : \ - BaseClass( _source, nNotifyFlags, pNotify, pUndoDesc, pRedoDesc, nChainingID ) \ - { \ - } \ - C ## _classnameprefix ## UndoScopeGuard( int nNotifyFlags, const char *pUndoDesc, int nChainingID ) : \ - BaseClass( _source, nNotifyFlags, pUndoDesc, pUndoDesc, nChainingID ) \ - { \ - } \ - }; \ - class C ## _classnameprefix ## DisableUndoScopeGuard : public CDisableUndoScopeGuard \ - { \ - typedef CDisableUndoScopeGuard BaseClass; \ - \ - public: \ - C ## _classnameprefix ## DisableUndoScopeGuard( const char *pDesc, int nNotifyFlags, IDmNotify *pNotify = NULL ) : \ - BaseClass( pDesc, _source, nNotifyFlags, pNotify ) \ - { \ - } \ - }; \ - class C ## _classnameprefix ## EnableUndoScopeGuard : public CEnableUndoScopeGuard \ - { \ - typedef CEnableUndoScopeGuard BaseClass; \ - \ - public: \ - C ## _classnameprefix ## EnableUndoScopeGuard( const char *pDesc, int nNotifyFlags, IDmNotify *pNotify = NULL ) : \ - BaseClass( pDesc, _source, nNotifyFlags, pNotify ) \ - { \ - } \ - } - - -//----------------------------------------------------------------------------- -// Purpose: Simple helper class to disable NotifyDataChanged from current scope -//----------------------------------------------------------------------------- -class CNotifyScopeGuard -{ -public: - CNotifyScopeGuard( const char *pReason, int nNotifySource, int nNotifyFlags, IDmNotify *pNotify = NULL ) - { - m_bReleased = false; - m_pNotify = NULL; - g_pDataModel->PushNotificationScope( pReason, nNotifySource, nNotifyFlags ); - if ( pNotify ) - { - if ( g_pDataModel->InstallNotificationCallback( pNotify ) ) - { - m_pNotify = pNotify; - } - } - }; - - ~CNotifyScopeGuard() - { - Release(); - } - - void Release() - { - // Releases the guard... - if ( !m_bReleased ) - { - g_pDataModel->PopNotificationScope( ); - if ( m_pNotify ) - { - g_pDataModel->RemoveNotificationCallback( m_pNotify ); - m_pNotify = NULL; - } - m_bReleased = true; - } - } - -private: - CNotifyScopeGuard( const CNotifyScopeGuard& g ); - -private: - IDmNotify *m_pNotify; - bool m_bReleased; -}; - - -#define DEFINE_SOURCE_NOTIFY_SCOPE_GUARD( _classnameprefix, _source ) \ - class C ## _classnameprefix ## NotifyScopeGuard : public CNotifyScopeGuard \ - { \ - typedef CNotifyScopeGuard BaseClass; \ - \ - public: \ - C ## _classnameprefix ## NotifyScopeGuard( const char *pReason, int nNotifyFlags, IDmNotify *pNotify = NULL ) : \ - BaseClass( pReason, _source, nNotifyFlags, pNotify )\ - { \ - } \ - } - - -//----------------------------------------------------------------------------- -// Purpose: Simple helper class to disable notifications when in scope -//----------------------------------------------------------------------------- -class CChangeNotifyScopeGuard -{ -public: - CChangeNotifyScopeGuard( bool bNewState ) - { - m_bReleased = false; - m_bOldValue = g_pDataModel->IsSuppressingNotify(); - g_pDataModel->SetSuppressingNotify( bNewState ); - }; - - ~CChangeNotifyScopeGuard() - { - Release(); - } - - void Release() - { - // Releases the guard... - if ( !m_bReleased ) - { - g_pDataModel->SetSuppressingNotify( m_bOldValue ); - m_bReleased = true; - } - } - -private: - bool m_bOldValue; - bool m_bReleased; -}; - -class CDisableNotifyScopeGuard : public CChangeNotifyScopeGuard -{ - typedef CChangeNotifyScopeGuard BaseClass; - -public: - CDisableNotifyScopeGuard() : BaseClass( true ) { } - -private: - CDisableNotifyScopeGuard( const CDisableNotifyScopeGuard& g ); -}; - -class CEnableNotifyScopeGuard : public CChangeNotifyScopeGuard -{ - typedef CChangeNotifyScopeGuard BaseClass; - -public: - CEnableNotifyScopeGuard( ) : BaseClass( false ) { } - -private: - CEnableNotifyScopeGuard( const CEnableNotifyScopeGuard& g ); -}; - - -//----------------------------------------------------------------------------- -// Standard undo/notify guards for the application -//----------------------------------------------------------------------------- -DEFINE_SOURCE_UNDO_SCOPE_GUARD( App, NOTIFY_SOURCE_APPLICATION ); -DEFINE_SOURCE_NOTIFY_SCOPE_GUARD( App, NOTIFY_SOURCE_APPLICATION ); - - - -#endif // IDATAMODEL_H diff --git a/public/demofile/demoformat.h b/public/demofile/demoformat.h deleted file mode 100644 index 5cf5fd4d4..000000000 --- a/public/demofile/demoformat.h +++ /dev/null @@ -1,240 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef DEMOFORMAT_H -#define DEMOFORMAT_H -#ifdef _WIN32 -#pragma once -#endif - -#include "mathlib/vector.h" -#include "utlvector.h" -#include "tier0/platform.h" - -#define DEMO_HEADER_ID "HL2DEMO" -#define DEMO_PROTOCOL 3 - -#if !defined( MAX_OSPATH ) -#define MAX_OSPATH 260 // max length of a filesystem pathname -#endif - -// Demo messages -enum -{ - // it's a startup message, process as fast as possible - dem_signon = 1, - // it's a normal network packet that we stored off - dem_packet, - // sync client clock to demo tick - dem_synctick, - // console command - dem_consolecmd, - // user input command - dem_usercmd, - // network data tables - dem_datatables, - // end of time. - dem_stop, - - dem_stringtables, - - // Last command - dem_lastcmd = dem_stringtables -}; - -struct demoheader_t -{ - char demofilestamp[8]; // Should be HL2DEMO - int demoprotocol; // Should be DEMO_PROTOCOL - int networkprotocol; // Should be PROTOCOL_VERSION - char servername[ MAX_OSPATH ]; // Name of server - char clientname[ MAX_OSPATH ]; // Name of client who recorded the game - char mapname[ MAX_OSPATH ]; // Name of map - char gamedirectory[ MAX_OSPATH ]; // Name of game directory (com_gamedir) - float playback_time; // Time of track - int playback_ticks; // # of ticks in track - int playback_frames; // # of frames in track - int signonlength; // lenght of sigondata in bytes -}; - -#define FDEMO_NORMAL 0 -#define FDEMO_USE_ORIGIN2 (1<<0) -#define FDEMO_USE_ANGLES2 (1<<1) -#define FDEMO_NOINTERP (1<<2) // don't interpolate between this an last view - -struct democmdinfo_t -{ - // Default constructor - democmdinfo_t() - { - flags = FDEMO_NORMAL; - viewOrigin.Init(); - viewAngles.Init(); - localViewAngles.Init(); - - // Resampled origin/angles - viewOrigin2.Init(); - viewAngles2.Init(); - localViewAngles2.Init(); - } - - // Copy constructor - // Assignment - democmdinfo_t& operator=(const democmdinfo_t& src ) - { - if ( this == &src ) - return *this; - - flags = src.flags; - viewOrigin = src.viewOrigin; - viewAngles = src.viewAngles; - localViewAngles = src.localViewAngles; - viewOrigin2 = src.viewOrigin2; - viewAngles2 = src.viewAngles2; - localViewAngles2 = src.localViewAngles2; - - return *this; - } - - const Vector& GetViewOrigin() - { - if ( flags & FDEMO_USE_ORIGIN2 ) - { - return viewOrigin2; - } - return viewOrigin; - } - - const QAngle& GetViewAngles() - { - if ( flags & FDEMO_USE_ANGLES2 ) - { - return viewAngles2; - } - return viewAngles; - } - const QAngle& GetLocalViewAngles() - { - if ( flags & FDEMO_USE_ANGLES2 ) - { - return localViewAngles2; - } - return localViewAngles; - } - - void Reset( void ) - { - flags = 0; - viewOrigin2 = viewOrigin; - viewAngles2 = viewAngles; - localViewAngles2 = localViewAngles; - } - - int flags; - - // original origin/viewangles - Vector viewOrigin; - QAngle viewAngles; - QAngle localViewAngles; - - // Resampled origin/viewangles - Vector viewOrigin2; - QAngle viewAngles2; - QAngle localViewAngles2; -}; - -struct demosmoothing_t -{ - demosmoothing_t() - { - file_offset = 0; - frametick = 0; - selected = false; - samplepoint = false; - - vecmoved.Init(); - angmoved.Init(); - - targetpoint = false; - vectarget.Init(); - } - - demosmoothing_t& operator=(const demosmoothing_t& src ) - { - if ( this == &src ) - return *this; - - file_offset = src.file_offset; - frametick = src.frametick; - selected = src.selected; - samplepoint = src.samplepoint; - vecmoved = src.vecmoved; - angmoved = src.angmoved; - - targetpoint = src.targetpoint; - vectarget = src.vectarget; - - info = src.info; - - return *this; - } - - int file_offset; - - int frametick; - - bool selected; - - // For moved sample points - bool samplepoint; - Vector vecmoved; - QAngle angmoved; - - bool targetpoint; - Vector vectarget; - - democmdinfo_t info; -}; - -struct CSmoothingContext -{ - CSmoothingContext() - { - active = false; - filename[ 0 ] = 0; - m_nFirstSelectableSample = 0; - } - - CSmoothingContext& operator=(const CSmoothingContext& src ) - { - if ( this == &src ) - return *this; - - active = src.active; - Q_strncpy( filename, src.filename, sizeof( filename ) ); - - smooth.RemoveAll(); - int c = src.smooth.Count(); - int i; - for ( i = 0; i < c; i++ ) - { - demosmoothing_t newitem; - newitem = src.smooth[ i ]; - smooth.AddToTail( newitem ); - } - - m_nFirstSelectableSample = src.m_nFirstSelectableSample; - - return *this; - } - - bool active; - char filename[ 512 ]; - CUtlVector< demosmoothing_t > smooth; - int m_nFirstSelectableSample; -}; - -#endif // DEMOFORMAT_H diff --git a/public/disp_common.cpp b/public/disp_common.cpp deleted file mode 100644 index a712755b1..000000000 --- a/public/disp_common.cpp +++ /dev/null @@ -1,1296 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "disp_common.h" -#include "disp_powerinfo.h" -#include "builddisp.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -class CNodeVert -{ -public: - CNodeVert() {} - CNodeVert( int ix, int iy ) {x=ix; y=iy;} - - inline int& operator[]( int i ) {return ((int*)this)[i];} - inline int const& operator[]( int i ) const {return ((int*)this)[i];} - - int x, y; -}; - -static CNodeVert const g_NodeChildLookup[4][2] = -{ - {CNodeVert(0,0), CNodeVert(1,1)}, - {CNodeVert(1,0), CNodeVert(2,1)}, - {CNodeVert(0,1), CNodeVert(1,2)}, - {CNodeVert(1,1), CNodeVert(2,2)} -}; - -static CNodeVert const g_NodeTriWinding[9] = -{ - CNodeVert(0, 1), - CNodeVert(0, 0), - CNodeVert(1, 0), - CNodeVert(2, 0), - CNodeVert(2, 1), - CNodeVert(2, 2), - CNodeVert(1, 2), - CNodeVert(0, 2), - CNodeVert(0, 1) -}; - -// Indexed by CORNER_. These store NEIGHBOREDGE_ defines and tell which edges butt up against the corner. -static int g_CornerEdges[4][2] = -{ - { NEIGHBOREDGE_BOTTOM, NEIGHBOREDGE_LEFT }, // CORNER_LOWER_LEFT - { NEIGHBOREDGE_TOP, NEIGHBOREDGE_LEFT }, // CORNER_UPPER_LEFT - { NEIGHBOREDGE_TOP, NEIGHBOREDGE_RIGHT }, // CORNER_UPPER_RIGHT - { NEIGHBOREDGE_BOTTOM, NEIGHBOREDGE_RIGHT } // CORNER_LOWER_RIGHT -}; - -int g_EdgeDims[4] = -{ - 0, // NEIGHBOREDGE_LEFT = X - 1, // NEIGHBOREDGE_TOP = Y - 0, // NEIGHBOREDGE_RIGHT = X - 1 // NEIGHBOREDGE_BOTTOM = Y -}; - -CShiftInfo g_ShiftInfos[3][3] = -{ - { - {0, 0, true}, // CORNER_TO_CORNER -> CORNER_TO_CORNER - {0, -1, true}, // CORNER_TO_CORNER -> CORNER_TO_MIDPOINT - {2, -1, true} // CORNER_TO_CORNER -> MIDPOINT_TO_CORNER - }, - - { - {0, 1, true}, // CORNER_TO_MIDPOINT -> CORNER_TO_CORNER - {0, 0, false}, // CORNER_TO_MIDPOINT -> CORNER_TO_MIDPOINT (invalid) - {0, 0, false} // CORNER_TO_MIDPOINT -> MIDPOINT_TO_CORNER (invalid) - }, - - { - {-1, 1, true}, // MIDPOINT_TO_CORNER -> CORNER_TO_CORNER - {0, 0, false}, // MIDPOINT_TO_CORNER -> CORNER_TO_MIDPOINT (invalid) - {0, 0, false} // MIDPOINT_TO_CORNER -> MIDPOINT_TO_CORNER (invalid) - } -}; - -int g_EdgeSideLenMul[4] = -{ - 0, - 1, - 1, - 0 -}; - - -// --------------------------------------------------------------------------------- // -// Helper functions. -// --------------------------------------------------------------------------------- // - -inline int SignedBitShift( int val, int shift ) -{ - if( shift > 0 ) - return val << shift; - else - return val >> -shift; -} - -static inline void RotateVertIndex( - NeighborOrientation neighor, - int sideLengthMinus1, - CVertIndex const &in, - CVertIndex &out ) -{ - if( neighor == ORIENTATION_CCW_0 ) - { - out = in; - } - else if( neighor == ORIENTATION_CCW_90 ) - { - out.x = in.y; - out.y = sideLengthMinus1 - in.x; - } - else if( neighor == ORIENTATION_CCW_180 ) - { - out.x = sideLengthMinus1 - in.x; - out.y = sideLengthMinus1 - in.y; - } - else - { - out.x = sideLengthMinus1 - in.y; - out.y = in.x; - } -} - -static inline void RotateVertIncrement( - NeighborOrientation neighor, - CVertIndex const &in, - CVertIndex &out ) -{ - if( neighor == ORIENTATION_CCW_0 ) - { - out = in; - } - else if( neighor == ORIENTATION_CCW_90 ) - { - out.x = in.y; - out.y = -in.x; - } - else if( neighor == ORIENTATION_CCW_180 ) - { - out.x = -in.x; - out.y = -in.y; - } - else - { - out.x = -in.y; - out.y = in.x; - } -} - - -// --------------------------------------------------------------------------------- // -// CDispHelper functions. -// --------------------------------------------------------------------------------- // - -int GetEdgeIndexFromPoint( CVertIndex const &index, int iMaxPower ) -{ - int sideLengthMinus1 = 1 << iMaxPower; - - if( index.x == 0 ) - return NEIGHBOREDGE_LEFT; - else if( index.y == sideLengthMinus1 ) - return NEIGHBOREDGE_TOP; - else if( index.x == sideLengthMinus1 ) - return NEIGHBOREDGE_RIGHT; - else if( index.y == 0 ) - return NEIGHBOREDGE_BOTTOM; - else - return -1; -} - - -int GetCornerIndexFromPoint( CVertIndex const &index, int iPower ) -{ - int sideLengthMinus1 = 1 << iPower; - - if( index.x == 0 && index.y == 0 ) - return CORNER_LOWER_LEFT; - - else if( index.x == 0 && index.y == sideLengthMinus1 ) - return CORNER_UPPER_LEFT; - - else if( index.x == sideLengthMinus1 && index.y == sideLengthMinus1 ) - return CORNER_UPPER_RIGHT; - - else if( index.x == sideLengthMinus1 && index.y == 0 ) - return CORNER_LOWER_RIGHT; - - else - return -1; -} - - -int GetNeighborEdgePower( CDispUtilsHelper *pDisp, int iEdge, int iSub ) -{ - CDispNeighbor *pEdge = pDisp->GetEdgeNeighbor( iEdge ); - CDispSubNeighbor *pSub = &pEdge->m_SubNeighbors[iSub]; - if ( !pSub->IsValid() ) - return -1; - - CDispUtilsHelper *pNeighbor = pDisp->GetDispUtilsByIndex( pSub->GetNeighborIndex() ); - - CShiftInfo *pInfo = &g_ShiftInfos[pSub->m_Span][pSub->m_NeighborSpan]; - Assert( pInfo->m_bValid ); - - return pNeighbor->GetPower() + pInfo->m_PowerShiftAdd; -} - - -CDispUtilsHelper* SetupEdgeIncrements( - CDispUtilsHelper *pDisp, - int iEdge, - int iSub, - CVertIndex &myIndex, - CVertIndex &myInc, - CVertIndex &nbIndex, - CVertIndex &nbInc, - int &myEnd, - int &iFreeDim ) -{ - int iEdgeDim = g_EdgeDims[iEdge]; - iFreeDim = !iEdgeDim; - - CDispNeighbor *pSide = pDisp->GetEdgeNeighbor( iEdge ); - CDispSubNeighbor *pSub = &pSide->m_SubNeighbors[iSub]; - if ( !pSub->IsValid() ) - return NULL; - - CDispUtilsHelper *pNeighbor = pDisp->GetDispUtilsByIndex( pSub->m_iNeighbor ); - - CShiftInfo *pShiftInfo = &g_ShiftInfos[pSub->m_Span][pSub->m_NeighborSpan]; - Assert( pShiftInfo->m_bValid ); - - // Setup a start point and edge increment (NOTE: just precalculate these - // and store them in the CDispSubNeighbors). - CVertIndex tempInc; - - const CPowerInfo *pPowerInfo = pDisp->GetPowerInfo(); - myIndex[iEdgeDim] = g_EdgeSideLenMul[iEdge] * pPowerInfo->m_SideLengthM1; - myIndex[iFreeDim] = pPowerInfo->m_MidPoint * iSub; - TransformIntoSubNeighbor( pDisp, iEdge, iSub, myIndex, nbIndex ); - - int myPower = pDisp->GetPowerInfo()->m_Power; - int nbPower = pNeighbor->GetPowerInfo()->m_Power + pShiftInfo->m_PowerShiftAdd; - - myInc[iEdgeDim] = tempInc[iEdgeDim] = 0; - if( nbPower > myPower ) - { - myInc[iFreeDim] = 1; - tempInc[iFreeDim] = 1 << (nbPower - myPower); - } - else - { - myInc[iFreeDim] = 1 << (myPower - nbPower); - tempInc[iFreeDim] = 1; - } - RotateVertIncrement( pSub->GetNeighborOrientation(), tempInc, nbInc ); - - // Walk along the edge. - if( pSub->m_Span == CORNER_TO_MIDPOINT ) - myEnd = pDisp->GetPowerInfo()->m_SideLength >> 1; - else - myEnd = pDisp->GetPowerInfo()->m_SideLength - 1; - - return pNeighbor; -} - - -int GetSubNeighborIndex( - CDispUtilsHelper *pDisp, - int iEdge, - CVertIndex const &nodeIndex ) -{ - const CPowerInfo *pPowerInfo = pDisp->GetPowerInfo(); - const CDispNeighbor *pSide = pDisp->GetEdgeNeighbor( iEdge ); - - // Figure out if this is a vertical or horizontal edge. - int iEdgeDim = g_EdgeDims[iEdge]; - int iFreeDim = !iEdgeDim; - - int iFreeIndex = nodeIndex[iFreeDim]; - - // Figure out which of the (up to two) neighbors it lies in. - int iSub = 0; - if( iFreeIndex == pPowerInfo->m_MidPoint ) - { - // If it's in the middle, we only are interested if there's one neighbor - // next to us (so we can enable its middle vert). If there are any neighbors - // that touch the midpoint, then we have no need to return them because it would - // touch their corner verts which are always active. - if( pSide->m_SubNeighbors[0].m_Span != CORNER_TO_CORNER ) - return -1; - } - else if ( iFreeIndex > pPowerInfo->m_MidPoint ) - { - iSub = 1; - } - - // Make sure we get a valid neighbor. - if( !pSide->m_SubNeighbors[iSub].IsValid() ) - { - if( iSub == 1 && - pSide->m_SubNeighbors[0].IsValid() && - pSide->m_SubNeighbors[0].m_Span == CORNER_TO_CORNER ) - { - iSub = 0; - } - else - { - return -1; - } - } - - return iSub; -} - - -void SetupSpan( int iPower, int iEdge, NeighborSpan span, CVertIndex &viStart, CVertIndex &viEnd ) -{ - int iFreeDim = !g_EdgeDims[iEdge]; - const CPowerInfo *pPowerInfo = GetPowerInfo( iPower ); - - viStart = pPowerInfo->GetCornerPointIndex( iEdge ); - viEnd = pPowerInfo->GetCornerPointIndex( (iEdge+1) & 3 );; - - if ( iEdge == NEIGHBOREDGE_RIGHT || iEdge == NEIGHBOREDGE_BOTTOM ) - { - // CORNER_TO_MIDPOINT and MIDPOINT_CORNER are defined where the edge moves up or right, - // but pPowerInfo->GetCornerPointIndex walks around the edges clockwise, so on the - // bottom and right edges (where GetCornerPointIndex has us moving down and left) we need to - // reverse the sense here to make sure we return the right span. - if ( span == CORNER_TO_MIDPOINT ) - viStart[iFreeDim] = pPowerInfo->GetMidPoint(); - else if ( span == MIDPOINT_TO_CORNER ) - viEnd[iFreeDim] = pPowerInfo->GetMidPoint(); - } - else - { - if ( span == CORNER_TO_MIDPOINT ) - viEnd[iFreeDim] = pPowerInfo->GetMidPoint(); - else if ( span == MIDPOINT_TO_CORNER ) - viStart[iFreeDim] = pPowerInfo->GetMidPoint(); - } -} - - -CDispUtilsHelper* TransformIntoSubNeighbor( - CDispUtilsHelper *pDisp, - int iEdge, - int iSub, - CVertIndex const &nodeIndex, - CVertIndex &out - ) -{ - const CDispSubNeighbor *pSub = &pDisp->GetEdgeNeighbor( iEdge )->m_SubNeighbors[iSub]; - - // Find the part of pDisp's edge that this neighbor covers. - CVertIndex viSrcStart, viSrcEnd; - SetupSpan( pDisp->GetPower(), iEdge, pSub->GetSpan(), viSrcStart, viSrcEnd ); - - // Find the corresponding parts on the neighbor. - CDispUtilsHelper *pNeighbor = pDisp->GetDispUtilsByIndex( pSub->GetNeighborIndex() ); - int iNBEdge = (iEdge + 2 + pSub->GetNeighborOrientation()) & 3; - - CVertIndex viDestStart, viDestEnd; - SetupSpan( pNeighbor->GetPower(), iNBEdge, pSub->GetNeighborSpan(), viDestEnd, viDestStart ); - - - // Now map the one into the other. - int iFreeDim = !g_EdgeDims[iEdge]; - int fixedPercent = ((nodeIndex[iFreeDim] - viSrcStart[iFreeDim]) * (1<<16)) / (viSrcEnd[iFreeDim] - viSrcStart[iFreeDim]); - Assert( fixedPercent >= 0 && fixedPercent <= (1<<16) ); - - int nbDim = g_EdgeDims[iNBEdge]; - out[nbDim] = viDestStart[nbDim]; - out[!nbDim] = viDestStart[!nbDim] + ((viDestEnd[!nbDim] - viDestStart[!nbDim]) * fixedPercent) / (1<<16); - - Assert( out.x >= 0 && out.x < pNeighbor->GetSideLength() ); - Assert( out.y >= 0 && out.y < pNeighbor->GetSideLength() ); - - return pNeighbor; -} - - -CDispUtilsHelper* TransformIntoNeighbor( - CDispUtilsHelper *pDisp, - int iEdge, - CVertIndex const &nodeIndex, - CVertIndex &out - ) -{ - if ( iEdge == -1 ) - iEdge = GetEdgeIndexFromPoint( nodeIndex, pDisp->GetPower() ); - - int iSub = GetSubNeighborIndex( pDisp, iEdge, nodeIndex ); - if ( iSub == -1 ) - return NULL; - - CDispUtilsHelper *pRet = TransformIntoSubNeighbor( pDisp, iEdge, iSub, nodeIndex, out ); - -#if 0 - // Debug check.. make sure it comes back to the same point from the other side. - #if defined( _DEBUG ) - static bool bTesting = false; - if ( pRet && !bTesting ) - { - bTesting = true; - - // We could let TransformIntoNeighbor figure out the index but if this is a corner vert, then - // it may pick the wrong edge and we'd get a benign assert. - int nbOrientation = pDisp->GetEdgeNeighbor( iEdge )->m_SubNeighbors[iSub].GetNeighborOrientation(); - int iNeighborEdge = (iEdge + 2 + nbOrientation) & 3; - - CVertIndex testIndex; - CDispUtilsHelper *pTest = TransformIntoNeighbor( pRet, iNeighborEdge, out, testIndex ); - Assert( pTest == pDisp ); - Assert( testIndex == nodeIndex ); - - bTesting = false; - } - #endif -#endif - - return pRet; -} - - -bool DoesPointHaveAnyNeighbors( - CDispUtilsHelper *pDisp, - const CVertIndex &index ) -{ - // See if it connects to a neighbor on the edge. - CVertIndex dummy; - if ( TransformIntoNeighbor( pDisp, -1, index, dummy ) ) - return true; - - // See if it connects to a neighbor on a corner. - int iCorner = GetCornerIndexFromPoint( index, pDisp->GetPower() ); - if ( iCorner == -1 ) - return false; - - // If there are any neighbors on the specified corner, then the point has neighbors. - if ( pDisp->GetCornerNeighbors( iCorner )->m_nNeighbors > 0 ) - return true; - - // Since points on corners touch two edges, we actually want to test two edges to see - // if the point has a neighbor on either edge. - for ( int i=0; i < 2; i++ ) - { - if ( TransformIntoNeighbor( pDisp, g_CornerEdges[iCorner][i], index, dummy ) ) - return true; - } - - return false; -} - - -// ------------------------------------------------------------------------------------ // -// CDispSubEdgeIterator. -// ------------------------------------------------------------------------------------ // - -CDispSubEdgeIterator::CDispSubEdgeIterator() -{ - m_pNeighbor = 0; - m_FreeDim = m_Index.x = m_Inc.x = m_End = 0; // Setup so Next returns false. -} - - -void CDispSubEdgeIterator::Start( CDispUtilsHelper *pDisp, int iEdge, int iSub, bool bTouchCorners ) -{ - m_pNeighbor = SetupEdgeIncrements( pDisp, iEdge, iSub, m_Index, m_Inc, m_NBIndex, m_NBInc, m_End, m_FreeDim ); - if ( m_pNeighbor ) - { - if ( bTouchCorners ) - { - // Back up our current position by 1 so we hit the corner first, and extend the endpoint - // so we hit the other corner too. - m_Index -= m_Inc; - m_NBIndex -= m_NBInc; - - m_End += m_Inc[m_FreeDim]; - } - } - else - { - m_FreeDim = m_Index.x = m_Inc.x = m_End = 0; // Setup so Next returns false. - } -} - - -bool CDispSubEdgeIterator::Next() -{ - m_Index += m_Inc; - m_NBIndex += m_NBInc; - - // Were we just at the last point on the edge? - return m_Index[m_FreeDim] < m_End; -} - - -bool CDispSubEdgeIterator::IsLastVert() const -{ - return (m_Index[m_FreeDim] + m_Inc[m_FreeDim]) >= m_End; -} - - -// ------------------------------------------------------------------------------------ // -// CDispEdgeIterator. -// ------------------------------------------------------------------------------------ // - -CDispEdgeIterator::CDispEdgeIterator( CDispUtilsHelper *pDisp, int iEdge ) -{ - m_pDisp = pDisp; - m_iEdge = iEdge; - m_iCurSub = -1; -} - - -bool CDispEdgeIterator::Next() -{ - while ( !m_It.Next() ) - { - // Ok, move up to the next sub. - if ( m_iCurSub == 1 ) - return false; - - ++m_iCurSub; - m_It.Start( m_pDisp, m_iEdge, m_iCurSub ); - } - return true; -} - - -// ------------------------------------------------------------------------------------ // -// CDispCircumferenceIterator. -// ------------------------------------------------------------------------------------ // - -CDispCircumferenceIterator::CDispCircumferenceIterator( int sideLength ) -{ - m_iCurEdge = -1; - m_SideLengthM1 = sideLength - 1; -} - - -bool CDispCircumferenceIterator::Next() -{ - switch ( m_iCurEdge ) - { - case -1: - { - m_iCurEdge = NEIGHBOREDGE_LEFT; - m_VertIndex.Init( 0, 0 ); - } - break; - - case NEIGHBOREDGE_LEFT: - { - ++m_VertIndex.y; - if ( m_VertIndex.y == m_SideLengthM1 ) - m_iCurEdge = NEIGHBOREDGE_TOP; - } - break; - - case NEIGHBOREDGE_TOP: - { - ++m_VertIndex.x; - if ( m_VertIndex.x == m_SideLengthM1 ) - m_iCurEdge = NEIGHBOREDGE_RIGHT; - } - break; - - case NEIGHBOREDGE_RIGHT: - { - --m_VertIndex.y; - if ( m_VertIndex.y == 0 ) - m_iCurEdge = NEIGHBOREDGE_BOTTOM; - } - break; - - case NEIGHBOREDGE_BOTTOM: - { - --m_VertIndex.x; - if ( m_VertIndex.x == 0 ) - return false; // Done! - } - break; - } - - return true; -} - - - -// Helper function to setup an index either on the edges or the center -// of the box defined by [bottomleft,topRight]. -static inline void SetupCoordXY( CNodeVert &out, CNodeVert const &bottomLeft, CNodeVert const &topRight, CNodeVert const &info ) -{ - for( int i=0; i < 2; i++ ) - { - if( info[i] == 0 ) - out[i] = bottomLeft[i]; - else if( info[i] == 1 ) - out[i] = (bottomLeft[i] + topRight[i]) >> 1; - else - out[i] = topRight[i]; - } -} - - -static unsigned short* DispCommon_GenerateTriIndices_R( - CNodeVert const &bottomLeft, - CNodeVert const &topRight, - unsigned short *indices, - int power, - int sideLength ) -{ - if( power == 1 ) - { - // Ok, add triangles. All we do here is follow a list of verts (g_NodeTriWinding) - // around the center vert of this node and make triangles. - int iCurTri = 0; - CNodeVert verts[3]; - - // verts[0] is always the center vert. - SetupCoordXY( verts[0], bottomLeft, topRight, CNodeVert(1,1) ); - int iCurVert = 1; - - for( int i=0; i < 9; i++ ) - { - SetupCoordXY( verts[iCurVert], bottomLeft, topRight, g_NodeTriWinding[i] ); - ++iCurVert; - - if( iCurVert == 3 ) - { - for( int iTriVert=2; iTriVert >= 0; iTriVert-- ) - { - int index = verts[iTriVert].y * sideLength + verts[iTriVert].x; - *indices = index; - ++indices; - } - - // Setup for the next triangle. - verts[1] = verts[2]; - iCurVert = 2; - iCurTri++; - } - } - } - else - { - // Recurse into the children. - for( int i=0; i < 4; i++ ) - { - CNodeVert childBottomLeft, childTopRight; - SetupCoordXY( childBottomLeft, bottomLeft, topRight, g_NodeChildLookup[i][0] ); - SetupCoordXY( childTopRight, bottomLeft, topRight, g_NodeChildLookup[i][1] ); - - indices = DispCommon_GenerateTriIndices_R( childBottomLeft, childTopRight, indices, power-1, sideLength ); - } - } - - return indices; -} - - -// ------------------------------------------------------------------------------------------- // -// CDispUtilsHelper functions. -// ------------------------------------------------------------------------------------------- // - -int CDispUtilsHelper::GetPower() const -{ - return GetPowerInfo()->GetPower(); -} - -int CDispUtilsHelper::GetSideLength() const -{ - return GetPowerInfo()->GetSideLength(); -} - -const CVertIndex& CDispUtilsHelper::GetCornerPointIndex( int iCorner ) const -{ - return GetPowerInfo()->GetCornerPointIndex( iCorner ); -} - -int CDispUtilsHelper::VertIndexToInt( const CVertIndex &i ) const -{ - Assert( i.x >= 0 && i.x < GetSideLength() && i.y >= 0 && i.y < GetSideLength() ); - return i.y * GetSideLength() + i.x; -} - -CVertIndex CDispUtilsHelper::GetEdgeMidPoint( int iEdge ) const -{ - int end = GetSideLength() - 1; - int mid = GetPowerInfo()->GetMidPoint(); - - if ( iEdge == NEIGHBOREDGE_LEFT ) - return CVertIndex( 0, mid ); - - else if ( iEdge == NEIGHBOREDGE_TOP ) - return CVertIndex( mid, end ); - - else if ( iEdge == NEIGHBOREDGE_RIGHT ) - return CVertIndex( end, mid ); - - else if ( iEdge == NEIGHBOREDGE_BOTTOM ) - return CVertIndex( mid, 0 ); - - Assert( false ); - return CVertIndex( 0, 0 ); -} - -int DispCommon_GetNumTriIndices( int power ) -{ - return (1<GetEdgeNeighbor( i )->SetInvalid(); - pDisp->GetCornerNeighbors( i )->SetInvalid(); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void GetDispBox( CCoreDispInfo *pDisp, CDispBox &box ) -{ - // Calculate the bbox for this displacement. - Vector vMin( 1e24, 1e24, 1e24 ); - Vector vMax( -1e24, -1e24, -1e24 ); - - for ( int iVert = 0; iVert < 4; ++iVert ) - { - const Vector &vTest = pDisp->GetSurface()->GetPoint( iVert ); - VectorMin( vTest, vMin, vMin ); - VectorMax( vTest, vMax, vMax ); - } - - // Puff the box out a little. - static float flPuff = 0.1f; - vMin -= Vector( flPuff, flPuff, flPuff ); - vMax += Vector( flPuff, flPuff, flPuff ); - - box.m_Min = vMin; - box.m_Max = vMax; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void SetupDispBoxes( CCoreDispInfo **ppListBase, int nListSize, CUtlVector &out ) -{ - out.SetSize( nListSize ); - for ( int iDisp = 0; iDisp < nListSize; ++iDisp ) - { - CCoreDispInfo *pDisp = ppListBase[iDisp]; - GetDispBox( pDisp, out[iDisp] ); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline bool DoBBoxesTouch( const CDispBox &a, const CDispBox &b ) -{ - for ( int i=0; i < 3; i++ ) - { - if ( a.m_Max[i] < b.m_Min[i] ) - return false; - - if ( a.m_Min[i] > b.m_Max[i] ) - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool FindEdge( CCoreDispInfo *pInfo, Vector const &vPoint1, Vector const &vPoint2, int &iEdge ) -{ - CCoreDispSurface *pSurface = pInfo->GetSurface(); - - for( iEdge=0; iEdge < 4; iEdge++ ) - { - if( VectorsAreEqual( vPoint1, pSurface->GetPoint( iEdge ), 0.01f ) && - VectorsAreEqual( vPoint2, pSurface->GetPoint( (iEdge+1) & 3), 0.01f ) ) - { - return true; - } - } - - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -NeighborSpan NeighborSpanFlip( int iEdge, NeighborSpan span ) -{ - if ( g_bEdgeNeighborFlip[iEdge] ) - return g_SpanFlip[span]; - else - return span; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void AddNeighbor( CCoreDispInfo *pMain, - int iEdge, // Which of pMain's sides this is on. - int iSub, // Which sub neighbor this takes up in pSide. - NeighborSpan span, // What span this fills in pMain. - CCoreDispInfo *pOther, int iNeighborEdge, NeighborSpan nbSpan ) -{ - // The edge iteration before coming in here goes 0-1, 1-2, 2-3, 3-4. - // This flips the sense of CORNER_TO_MIDPOINT/MIDPOINT_TO_CORNER on the right and - // bottom edges and is undone here. - span = NeighborSpanFlip( iEdge, span ); - nbSpan = NeighborSpanFlip( iNeighborEdge, nbSpan ); - - // Get the subspan this fills on our displacement. - CDispSubNeighbor *pSub = &pMain->GetEdgeNeighbor(iEdge)->m_SubNeighbors[iSub]; - - // Which subspan does this use in the neighbor? - CDispSubNeighbor *pNeighborSub; - if ( nbSpan == MIDPOINT_TO_CORNER ) - { - pNeighborSub = &pOther->GetEdgeNeighbor(iNeighborEdge)->m_SubNeighbors[1]; - } - else - { - pNeighborSub = &pOther->GetEdgeNeighbor(iNeighborEdge)->m_SubNeighbors[0]; - } - - // Make sure this slot isn't used on either displacement. - if ( pSub->IsValid() || pNeighborSub->IsValid() ) - { - ExecuteOnce( Warning( "Found a displacement edge abutting multiple other edges.\n" ) ); - return; - } - - // Now just copy the data into each displacement. - pSub->m_iNeighbor = pOther->GetListIndex(); - pSub->m_NeighborOrientation = g_CoreDispNeighborOrientationMap[iEdge][iNeighborEdge]; - pSub->m_Span = span; - pSub->m_NeighborSpan = nbSpan; - - pNeighborSub->m_iNeighbor = pMain->GetListIndex(); - pNeighborSub->m_NeighborOrientation = g_CoreDispNeighborOrientationMap[iNeighborEdge][iEdge]; - pNeighborSub->m_Span = nbSpan; - pNeighborSub->m_NeighborSpan = span; - -#if defined( _DEBUG ) - // Walk an iterator over the new connection to make sure it works. - CDispSubEdgeIterator it; - it.Start( pMain, iEdge, iSub ); - while ( it.Next() ) - { - CVertIndex nbIndex; - TransformIntoNeighbor( pMain, iEdge, it.GetVertIndex(), nbIndex ); - } -#endif -} - -//----------------------------------------------------------------------------- -// This function is symmetric wrt pMain and pOther. It sets up valid neighboring data for -// the relationship between both of them. -//----------------------------------------------------------------------------- -void SetupEdgeNeighbors( CCoreDispInfo *pMain, CCoreDispInfo *pOther ) -{ - // Initialize.. - for( int iEdge=0; iEdge < 4; iEdge++ ) - { - // Setup the edge points and the midpoint. - Vector pt[2], mid; - pMain->GetSurface()->GetPoint( iEdge, pt[0] ); - pMain->GetSurface()->GetPoint( (iEdge + 1) & 3, pt[1] ); - mid = (pt[0] + pt[1]) * 0.5f; - - // Find neighbors. - int iNBEdge; - if( FindEdge( pOther, pt[1], pt[0], iNBEdge ) ) - { - AddNeighbor( pMain, iEdge, 0, CORNER_TO_CORNER, pOther, iNBEdge, CORNER_TO_CORNER ); - } - else - { - // Look for one that takes up our whole side. - if( FindEdge( pOther, pt[1], pt[0]*2 - pt[1], iNBEdge ) ) - { - AddNeighbor( pMain, iEdge, 0, CORNER_TO_CORNER, pOther, iNBEdge, CORNER_TO_MIDPOINT ); - } - else if( FindEdge( pOther, pt[1]*2 - pt[0], pt[0], iNBEdge ) ) - { - AddNeighbor( pMain, iEdge, 0, CORNER_TO_CORNER, pOther, iNBEdge, MIDPOINT_TO_CORNER ); - } - else - { - // Ok, look for 1 or two that abut this side. - if( FindEdge( pOther, mid, pt[0], iNBEdge ) ) - { - AddNeighbor( pMain, iEdge, g_bEdgeNeighborFlip[iEdge], CORNER_TO_MIDPOINT, pOther, iNBEdge, CORNER_TO_CORNER ); - } - - if( FindEdge( pOther, pt[1], mid, iNBEdge ) ) - { - AddNeighbor( pMain, iEdge, !g_bEdgeNeighborFlip[iEdge], MIDPOINT_TO_CORNER, pOther, iNBEdge, CORNER_TO_CORNER ); - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Returns true if the displacement has an edge neighbor with the given index. -//----------------------------------------------------------------------------- -bool HasEdgeNeighbor( const CCoreDispInfo *pMain, int iNeighbor ) -{ - for ( int i=0; i < 4; i++ ) - { - const CDispCornerNeighbors *pCorner = pMain->GetCornerNeighbors( i ); - for ( int iNB=0; iNB < pCorner->m_nNeighbors; iNB++ ) - if ( pCorner->m_Neighbors[iNB] == iNeighbor ) - return true; - - const CDispNeighbor *pEdge = pMain->GetEdgeNeighbor( i ); - if ( pEdge->m_SubNeighbors[0].GetNeighborIndex() == iNeighbor || - pEdge->m_SubNeighbors[1].GetNeighborIndex() == iNeighbor ) - { - return true; - } - } - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void SetupCornerNeighbors( CCoreDispInfo *pMain, CCoreDispInfo *pOther, int *nOverflows ) -{ - if ( HasEdgeNeighbor( pMain, pOther->GetListIndex() ) ) - return; - - // Do these two share a vertex? - int nShared = 0; - int iMainSharedCorner = -1; - int iOtherSharedCorner = -1; - - for ( int iMainCorner=0; iMainCorner < 4; iMainCorner++ ) - { - Vector const &vMainCorner = pMain->GetCornerPoint( iMainCorner ); - - for ( int iOtherCorner=0; iOtherCorner < 4; iOtherCorner++ ) - { - Vector const &vOtherCorner = pOther->GetCornerPoint( iOtherCorner ); - - if ( VectorsAreEqual( vMainCorner, vOtherCorner, 0.001f ) ) - { - iMainSharedCorner = iMainCorner; - iOtherSharedCorner = iOtherCorner; - ++nShared; - } - } - } - - if ( nShared == 1 ) - { - CDispCornerNeighbors *pMainCorner = pMain->GetCornerNeighbors( iMainSharedCorner ); - CDispCornerNeighbors *pOtherCorner = pOther->GetCornerNeighbors( iOtherSharedCorner ); - - if ( pMainCorner->m_nNeighbors < MAX_DISP_CORNER_NEIGHBORS && - pOtherCorner->m_nNeighbors < MAX_DISP_CORNER_NEIGHBORS ) - { - pMainCorner->m_Neighbors[pMainCorner->m_nNeighbors++] = pOther->GetListIndex(); - pOtherCorner->m_Neighbors[pOtherCorner->m_nNeighbors++] = pMain->GetListIndex(); - } - else - { - ++(*nOverflows); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool VerifyNeighborVertConnection( CDispUtilsHelper *pDisp, const CVertIndex &nodeIndex, - const CDispUtilsHelper *pTestNeighbor, const CVertIndex &testNeighborIndex, - int mySide ) -{ - CVertIndex nbIndex( -1, -1 ); - CDispUtilsHelper *pNeighbor = NULL; - if( (pNeighbor = TransformIntoNeighbor( pDisp, mySide, nodeIndex, nbIndex ) ) != NULL ) - { - if ( pTestNeighbor != pNeighbor || nbIndex != testNeighborIndex ) - return false; - - CVertIndex testIndex( -1, -1 ); - int iSide = GetEdgeIndexFromPoint( nbIndex, pNeighbor->GetPowerInfo()->m_Power ); - if ( iSide == -1 ) - { - return false; - } - - CDispUtilsHelper *pTest = TransformIntoNeighbor( pNeighbor, iSide, nbIndex, testIndex ); - - if( pTest != pDisp || nodeIndex != testIndex ) - { - return false; - } - } - - return true; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void VerifyNeighborConnections( CCoreDispInfo **ppListBase, int nDisps ) -{ - while ( 1 ) - { - bool bHappy = true; - - int iDisp; - for ( iDisp = 0; iDisp < nDisps; ++iDisp ) - { - CCoreDispInfo *pDisp = ppListBase[iDisp]; - CDispUtilsHelper *pHelper = pDisp; - - for ( int iEdge=0; iEdge < 4; iEdge++ ) - { - CDispEdgeIterator it( pHelper, iEdge ); - while ( it.Next() ) - { - if ( !VerifyNeighborVertConnection( pHelper, it.GetVertIndex(), it.GetCurrentNeighbor(), it.GetNBVertIndex(), iEdge ) ) - { - pDisp->GetEdgeNeighbor( iEdge )->SetInvalid(); - Warning( "Warning: invalid neighbor connection on displacement near (%.2f %.2f %.2f)\n", VectorExpand( pDisp->GetCornerPoint(0) ) ); - bHappy = false; - } - } - } - } - - if ( bHappy ) - break; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void FindNeighboringDispSurfs( CCoreDispInfo **ppListBase, int nListSize ) -{ - // First, clear all neighboring data. - int iDisp; - for ( iDisp = 0; iDisp < nListSize; ++iDisp ) - { - ClearNeighborData( ppListBase[iDisp] ); - } - - CUtlVector boxes; - SetupDispBoxes( ppListBase, nListSize, boxes ); - - int nCornerOverflows = 0; - - // Now test all pairs of displacements and setup neighboring relations between them. - for( iDisp = 0; iDisp < nListSize; ++iDisp ) - { - CCoreDispInfo *pMain = ppListBase[iDisp]; - - for ( int iDisp2 = iDisp+1; iDisp2 < nListSize; ++iDisp2 ) - { - CCoreDispInfo *pOther = ppListBase[iDisp2]; - - // Trivial reject. - if ( !DoBBoxesTouch( boxes[iDisp], boxes[iDisp2] ) ) - continue; - - SetupEdgeNeighbors( pMain, pOther ); - - // NOTE: this must come after SetupEdgeNeighbors because it makes sure not to add - // corner neighbors for disps that are already edge neighbors. - SetupCornerNeighbors( pMain, pOther, &nCornerOverflows ); - } - } - - if ( nCornerOverflows ) - { - Warning( "Warning: overflowed %d displacement corner-neighbor lists.", nCornerOverflows ); - } - - // Debug check.. make sure the neighbor connections are intact (make sure that any - // edge vert that gets mapped into a neighbor gets mapped back the same way). - VerifyNeighborConnections( ppListBase, nListSize ); -} - -//============================================================================= -// -// Allowable verts. -// - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int IsCorner( CVertIndex const &index, int sideLength ) -{ - if ( index.x == 0 ) - { - if ( index.y == 0 ) - return true; - else if ( index.y == sideLength-1 ) - return true; - } - else if ( index.x == sideLength-1 ) - { - if ( index.y == 0 ) - return true; - else if ( index.y == sideLength-1 ) - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool IsVertAllowed( CDispUtilsHelper *pDisp, CVertIndex const &sideVert, int iLevel ) -{ - if ( IsCorner( sideVert, pDisp->GetPowerInfo()->GetSideLength() ) ) - return true; - - int iSide = GetEdgeIndexFromPoint( sideVert, pDisp->GetPowerInfo()->GetPower() ); - if ( iSide == -1 ) - return true; - - int iSub = GetSubNeighborIndex( pDisp, iSide, sideVert ); - if ( iSub == -1 ) - return true; - - CDispSubNeighbor *pSub = &pDisp->GetEdgeNeighbor( iSide )->m_SubNeighbors[iSub]; - CDispUtilsHelper *pNeighbor = pDisp->GetDispUtilsByIndex( pSub->m_iNeighbor ); - Assert( pNeighbor ); - - // Ok, there is a neighbor.. see if this vertex exists in the neighbor. - CShiftInfo *pShiftInfo = &g_ShiftInfos[pSub->m_Span][pSub->m_NeighborSpan]; - Assert( pShiftInfo->m_bValid ); - - if ( ( pNeighbor->GetPowerInfo()->GetPower() + pShiftInfo->m_PowerShiftAdd ) < ( iLevel+1 ) ) - { - return false; - } - - // Ok, it exists. Make sure the neighbor hasn't disallowed it. - CVertIndex nbIndex; - TransformIntoSubNeighbor( pDisp, iSide, iSub, sideVert, nbIndex ); - - CBitVec &allowedVerts = CCoreDispInfo::FromDispUtils( pNeighbor )->GetAllowedVerts(); - return !!allowedVerts.Get( pNeighbor->VertIndexToInt( nbIndex ) ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void UnallowVerts_R( CDispUtilsHelper *pDisp, CVertIndex const &nodeIndex, int &nUnallowed ) -{ - int iNodeIndex = pDisp->VertIndexToInt( nodeIndex ); - - CCoreDispInfo *pCoreDisp = CCoreDispInfo::FromDispUtils( pDisp ); - if ( !pCoreDisp->GetAllowedVerts().Get( iNodeIndex ) ) - return; - - nUnallowed++; - pCoreDisp->GetAllowedVerts().Clear( iNodeIndex ); - - for ( int iDep=0; iDep < CVertInfo::NUM_REVERSE_DEPENDENCIES; iDep++ ) - { - CVertDependency &dep = pDisp->GetPowerInfo()->m_pVertInfo[iNodeIndex].m_ReverseDependencies[iDep]; - - if( dep.m_iVert.x != -1 && dep.m_iNeighbor == -1 ) - { - UnallowVerts_R( pDisp, dep.m_iVert, nUnallowed ); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void DisableUnallowedVerts_R( CDispUtilsHelper *pDisp, CVertIndex const &nodeIndex, int iLevel, int &nUnallowed ) -{ - int iNodeIndex = pDisp->VertIndexToInt( nodeIndex ); - - // This vertex is not allowed if it is on an edge with a neighbor - // that does not have this vertex. - - // Test side verts. - for( int iSide=0; iSide < 4; iSide++ ) - { - CVertIndex const &sideVert = pDisp->GetPowerInfo()->m_pSideVerts[iNodeIndex].m_Verts[iSide]; - - if( !IsVertAllowed( pDisp, sideVert, iLevel ) ) - { - // This vert (and its dependencies) can't exist. - UnallowVerts_R( pDisp, sideVert, nUnallowed ); - } - } - -#if 0 - // Test dependencies. - for( int iDep=0; iDep < 2; iDep++ ) - { - CVertDependency const &dep = pDisp->GetPowerInfo()->m_pVertInfo[iNodeIndex].m_Dependencies[iDep]; - - if( dep.m_iNeighbor == -1 && !IsVertAllowed( pDisp, dep.m_iVert, iLevel ) ) - { - UnallowVerts_R( pDisp, nodeIndex, nUnallowed ); - } - } -#endif - - // Recurse. - if( iLevel+1 < pDisp->GetPower() ) - { - for( int iChild=0; iChild < 4; iChild++ ) - { - DisableUnallowedVerts_R( pDisp, pDisp->GetPowerInfo()->m_pChildVerts[iNodeIndex].m_Verts[iChild], iLevel+1, nUnallowed ); - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void SetupAllowedVerts( CCoreDispInfo **ppListBase, int nListSize ) -{ - // Set all verts to allowed to start with. - int iDisp; - for ( iDisp = 0; iDisp < nListSize; ++iDisp ) - { - ppListBase[iDisp]->GetAllowedVerts().SetAll(); - } - - // Disable verts that need to be disabled so higher-powered displacements remove - // the necessary triangles when bordering lower-powered displacements. - // It is necessary to loop around here because disabling verts can accumulate into - // neighbors. - bool bContinue; - do - { - bContinue = false; - for( iDisp = 0; iDisp < nListSize; ++iDisp ) - { - CDispUtilsHelper *pDisp = ppListBase[iDisp]; - - int nUnallowed = 0; - DisableUnallowedVerts_R( pDisp, pDisp->GetPowerInfo()->m_RootNode, 0, nUnallowed ); - if ( nUnallowed ) - bContinue = true; - } - } while( bContinue ); -} diff --git a/public/disp_common.h b/public/disp_common.h deleted file mode 100644 index 45bfaa977..000000000 --- a/public/disp_common.h +++ /dev/null @@ -1,262 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef DISP_COMMON_H -#define DISP_COMMON_H -#ifdef _WIN32 -#pragma once -#endif - -#include "disp_vertindex.h" -#include "bspfile.h" -#include "utlvector.h" - -class CPowerInfo; -class CCoreDispInfo; - -// ----------------------------------------------------------------------------- // -// Classes. -// ----------------------------------------------------------------------------- // - -// This class provides a set of utility functions for displacements that work in the tools and the engine. -abstract_class CDispUtilsHelper -{ -// Derived classes must implement these. -public: - virtual const CPowerInfo* GetPowerInfo() const = 0; - virtual CDispNeighbor* GetEdgeNeighbor( int index ) = 0; - virtual CDispCornerNeighbors* GetCornerNeighbors( int index ) = 0; - virtual CDispUtilsHelper* GetDispUtilsByIndex( int index ) = 0; - -// Helper functions. -public: - - int GetPower() const; - int GetSideLength() const; - const CVertIndex& GetCornerPointIndex( int iCorner ) const; - int VertIndexToInt( const CVertIndex &i ) const; - CVertIndex GetEdgeMidPoint( int iEdge ) const; -}; - - -// Use this to walk along two neighboring displacements and touch all the -// common vertices. -class CDispSubEdgeIterator -{ -public: - - CDispSubEdgeIterator(); - - // Normally, this will iterate all shared verts along the edge except the corners. - // If you want the corners to be touched too, then pass in bTouchCorners=true. - void Start( CDispUtilsHelper *pDisp, int iEdge, int iSub, bool bTouchCorners = false ); - bool Next(); - - const CVertIndex& GetVertIndex() const { return m_Index; } // Get the vert index for the displacement in pUtils. - const CVertIndex& GetNBVertIndex() const { return m_NBIndex; } // Get the neighbor's vert index. - CDispUtilsHelper* GetNeighbor() const { return m_pNeighbor; } - - // Returns true if you're on the last vert (ie: the next Next() call will return false).ssssss - bool IsLastVert() const; - - -private: - CDispUtilsHelper *m_pNeighbor; // The neighbor to the edge we were setup on. - - CVertIndex m_Index; - CVertIndex m_Inc; - - CVertIndex m_NBIndex; - CVertIndex m_NBInc; - - int m_End; - int m_FreeDim; -}; - - -// Use this to walk along the edge of a displacement, touching the points in common -// between the two neighbors. Note: this won't hit the corner points of any of the displacements. -// (As a result, it won't hit the midpoint of pDisps's edge if there are 2 neighbors). -class CDispEdgeIterator -{ -public: - CDispEdgeIterator( CDispUtilsHelper *pDisp, int iEdge ); - - // Seek to the next point on the edge. - bool Next(); - - const CVertIndex& GetVertIndex() const { return m_It.GetVertIndex(); } // Get the vert index for the displacement in pUtils. - const CVertIndex& GetNBVertIndex() const { return m_It.GetNBVertIndex(); } // Get the neighbor's vert index. - - // What is the current neighbor? - CDispUtilsHelper* GetCurrentNeighbor() const { return m_It.GetNeighbor(); } - - -private: - CDispUtilsHelper *m_pDisp; - int m_iEdge; - int m_iCurSub; - - CDispSubEdgeIterator m_It; -}; - - -// Use this to walk all the corners and edge verts in the displacement. -// It walks the edges in the order of the NEIGHBOREDGE_ defines. -// Iterate like this: -// CDispCircumferenceIterator iterator( pDisp->GetSideLength() ); -// while ( iterator.Next() ) -// ... -class CDispCircumferenceIterator -{ -public: - CDispCircumferenceIterator( int sideLength ); - - // Seek to the next point. Returns false when there are no more points. - bool Next(); - - const CVertIndex& GetVertIndex() const { return m_VertIndex; } - - -private: - int m_SideLengthM1; - int m_iCurEdge; - CVertIndex m_VertIndex; -}; - - -// These store info about how to scale and shift coordinates between neighbors -// of different relations (in g_ShiftInfos). -class CShiftInfo -{ -public: - int m_MidPointScale; - int m_PowerShiftAdd; - bool m_bValid; -}; - -class CDispBox -{ -public: - Vector m_Min, m_Max; -}; - -// ----------------------------------------------------------------------------- // -// Globals. -// ----------------------------------------------------------------------------- // - - -extern int g_EdgeDims[4]; // This tells which dimension (0 or 1) is locked on an edge for each NEIGHBOREDGE_ enum. -extern CShiftInfo g_ShiftInfos[3][3]; // See CShiftInfo. -extern int g_EdgeSideLenMul[4];// Multiply these by the side length to get the index of the edge. - - -// ----------------------------------------------------------------------------- // -// Helper functions. -// ----------------------------------------------------------------------------- // - -// Reference implementation to generate triangle indices for a displacement. -int DispCommon_GetNumTriIndices( int power ); -void DispCommon_GenerateTriIndices( int power, unsigned short *indices ); - -// Returns a NEIGHBOREDGE_ value for the edge that the index is on. -// Returns -1 if the index is not on a side. -// If the point is on a corner, the edges are tested in the order of the NEIGHBOREDGE_ defines. -int GetEdgeIndexFromPoint( CVertIndex const &index, int iPower ); - -// Returns a CORNER_ value for the corner the point is on, or -1 if it's not on a corner. -int GetEdgeIndexFromPoint( CVertIndex const &index, int iPower ); - -// This returns the neighbor's power, possibly +1 or -1. -// -// It will add one if the neighbor takes up half of your edge (ie: if it took up your -// whole edge, its resolution would be twice what it really is). -// -// It will subtract one if you take up half of its edge (ie: you only touch half of its verts). -// -// Returns -1 if the edge connection is invalid. -int GetNeighborEdgePower( CDispUtilsHelper *pDisp, int iEdge, int iSub ); - -// This function sets you up so you can walk along an edge that joins two neighbors. -// Add myInc to myIndex and nbInc to nbIndex until myIndex[iFreeDim] >= myEnd. -// -// Returns the neighbor displacement, or NULL if the specified sub neighbor isn't valid. -CDispUtilsHelper* SetupEdgeIncrements( - CDispUtilsHelper *pDisp, - int iEdge, - int iSub, - CVertIndex &myIndex, - CVertIndex &myInc, - CVertIndex &nbIndex, - CVertIndex &nbInc, - int &myEnd, - int &iFreeDim ); - -// Figure out which sub neighbor nodeIndex touches. -// Returns -1 if there is no valid sub neighbor at the specified index. -int GetSubNeighborIndex( - CDispUtilsHelper *pDisp, - int iEdge, - CVertIndex const &nodeIndex - ); - -// Given a vert index and the CSubNeighbor the vert lies on, this -// transforms the specified vert into the neighbor's space. -// -// Note: for corner verts, there may be multiple neighbors touching the same vert, so the -// result you get depends on the edge you specify in iEdge (ie: if you specify the same -// node index but a different edge, you may get a different neighbor). -// -// Note: This only returns a point if the point at nodeIndex actually touches a neighbor point. -// An example where this might be unexpected is if pDisp is power 4 and its neighbor on iEdge -// is power 3, and nodeIndex points at a vert in between two of its neighbor's verts. -// In that case, even though there is a neighbor displacement, nodeIndex doesn't touch -// any points on it, so NULL is returned. -CDispUtilsHelper* TransformIntoSubNeighbor( - CDispUtilsHelper *pDisp, - int iEdge, - int iSub, - CVertIndex const &nodeIndex, - CVertIndex &out - ); - -// Transform pDisp's node at nodeIndex into its neighboring connection. -// Returns the neighbor displacement and sets out to the index in the neighbor. -// -// Note: for corner verts, there may be multiple neighbors touching the same vert, so the -// result you get depends on the edge you specify in iEdge (ie: if you specify the same -// node index but a different edge, you may get a different neighbor). -// -// Note: This only returns a point if the point at nodeIndex actually touches a neighbor point. -// An example where this might surprise you is if pDisp is power 4 and its neighbor on iEdge -// is power 3, and nodeIndex points at a vert in between two of its neighbor's verts. -// In that case, even though there is a neighbor displacement, nodeIndex doesn't touch -// any points on it, so NULL is returned. -CDispUtilsHelper* TransformIntoNeighbor( - CDispUtilsHelper *pDisp, - int iEdge, - CVertIndex const &nodeIndex, - CVertIndex &out ); - -// Returns true if the specified point has one or more neighbors. -bool DoesPointHaveAnyNeighbors( - CDispUtilsHelper *pDisp, - const CVertIndex &index ); - - -void FindNeighboringDispSurfs( CCoreDispInfo **ppListBase, int nListSize ); -void SetupAllowedVerts( CCoreDispInfo **ppListBase, int nListSize ); -void GetDispBox( CCoreDispInfo *pDisp, CDispBox &box ); - -// ----------------------------------------------------------------------------- // -// Inlines. -// ----------------------------------------------------------------------------- // - -#include "disp_powerinfo.h" - - -#endif // DISP_COMMON_H diff --git a/public/disp_powerinfo.cpp b/public/disp_powerinfo.cpp deleted file mode 100644 index 0578d947a..000000000 --- a/public/disp_powerinfo.cpp +++ /dev/null @@ -1,580 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "disp_powerinfo.h" -#include "disp_common.h" -#include "commonmacros.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// ------------------------------------------------------------------------ // -// Internal classes. -// ------------------------------------------------------------------------ // - -// These point at the vertices connecting to each of the [north,south,east,west] vertices. -class CVertCorners -{ -public: - short m_Corner1[2]; - short m_Corner2[2]; -}; - - -// ------------------------------------------------------------------------ // -// Globals. -// ------------------------------------------------------------------------ // - -// This points at vertices to the side of a node (north, south, east, west). -static short g_SideVertMul[4][2] = { {1,0}, {0,1}, {-1,0}, {0,-1} }; - -static CVertCorners g_SideVertCorners[4] = -{ - { {1,-1}, {1,1} }, - { {1,1}, {-1,1} }, - { {-1,1}, {-1,-1} }, - { {-1,-1}, {1,-1} } -}; - -// This is used in loops on child nodes. The indices point at the nodes: -// 0 = upper-right -// 1 = upper-left -// 2 = lower-left -// 3 = lower-right -static CVertIndex g_ChildNodeIndexMul[4] = -{ - CVertIndex(1,1), - CVertIndex(-1,1), - CVertIndex(-1,-1), - CVertIndex(1,-1) -}; - -// These are multipliers on vertMul (not nodeMul). -static CVertIndex g_ChildNodeDependencies[4][2] = -{ - { CVertIndex(1,0), CVertIndex(0,1) }, - { CVertIndex(0,1), CVertIndex(-1,0) }, - { CVertIndex(-1,0), CVertIndex(0,-1) }, - { CVertIndex(0,-1), CVertIndex(1,0) } -}; - -// 2x2 rotation matrices for each orientation. -static int g_OrientationRotations[4][2][2] = -{ - {{1, 0}, // CCW_0 - {0, 1}}, - - {{0, 1}, // CCW_90 - {-1,0}}, - - {{-1,0}, // CCW_180 - {0,-1}}, - - {{0, -1}, // CCW_270 - {1, 0}} -}; - - -// ------------------------------------------------------------------------ // -// Helper functions. -// ------------------------------------------------------------------------ // - -// Apply a 2D rotation to the specified CVertIndex around the specified centerpoint. -static CVertIndex Transform2D( - int const mat[2][2], - CVertIndex const &vert, - CVertIndex const ¢erPoint ) -{ - CVertIndex translated = vert - centerPoint; - - CVertIndex transformed( - translated.x*mat[0][0] + translated.y*mat[0][1], - translated.x*mat[1][0] + translated.y*mat[1][1] ); - - return transformed + centerPoint; -} - - -// Rotate a given CVertIndex with a specified orientation. -// Do this with a lookup table eventually! -static void GetEdgeVertIndex( int sideLength, int iEdge, int iVert, CVertIndex &out ) -{ - if( iEdge == NEIGHBOREDGE_RIGHT ) - { - out.x = sideLength - 1; - out.y = iVert; - } - else if( iEdge == NEIGHBOREDGE_TOP ) - { - out.x = iVert; - out.y = sideLength - 1; - } - else if( iEdge == NEIGHBOREDGE_LEFT ) - { - out.x = 0; - out.y = iVert; - } - else - { - out.x = iVert; - out.y = 0; - } -} - - -// Generate an index given a CVertIndex and the size of the displacement it resides in. -static int VertIndex( CVertIndex const &vert, int iMaxPower ) -{ - return vert.y * ((1 << iMaxPower) + 1) + vert.x; -} - - -static CVertIndex WrapVertIndex( CVertIndex const &in, int sideLength ) -{ - int out[2]; - - for( int i=0; i < 2; i++ ) - { - if( in[i] < 0 ) - out[i] = sideLength - 1 - (-in[i] % sideLength); - else if( in[i] >= sideLength ) - out[i] = in[i] % sideLength; - else - out[i] = in[i]; - } - - return CVertIndex( out[0], out[1] ); -} - - -static int GetFreeDependency( CVertDependency *pDep, int nElements ) -{ - for( int i=0; i < nElements; i++ ) - { - if( !pDep[i].IsValid() ) - return i; - } - - Assert( false ); - return 0; -} - - -static void AddDependency( - CVertInfo *dependencies, - int sideLength, - CVertIndex const &nodeIndex, - CVertIndex const &dependency, - int iMaxPower, - bool bCheckNeighborDependency, - bool bAddReverseDependency ) -{ - int iNodeIndex = VertIndex( nodeIndex, iMaxPower ); - CVertInfo *pNode = &dependencies[iNodeIndex]; - - int iDep = GetFreeDependency( pNode->m_Dependencies, sizeof(pNode->m_Dependencies)/sizeof(pNode->m_Dependencies[0]) ); - pNode->m_Dependencies[iDep].m_iVert = dependency; - pNode->m_Dependencies[iDep].m_iNeighbor = -1; - - if( bAddReverseDependency ) - { - CVertInfo *pDep = &dependencies[VertIndex( dependency, iMaxPower )]; - iDep = GetFreeDependency( pDep->m_ReverseDependencies, CVertInfo::NUM_REVERSE_DEPENDENCIES ); - pDep->m_ReverseDependencies[iDep].m_iVert = nodeIndex; - pDep->m_ReverseDependencies[iDep].m_iNeighbor = -1; - } - - // Edge verts automatically add a dependency for the neighbor. - // Internal verts wind up in here twice anyway so it doesn't need to - if( bCheckNeighborDependency ) - { - int iConnection = GetEdgeIndexFromPoint( nodeIndex, iMaxPower ); - if( iConnection != -1 ) - { - Assert( !pNode->m_Dependencies[1].IsValid() ); - - CVertIndex delta( nodeIndex.x - dependency.x, nodeIndex.y - dependency.y ); - CVertIndex newIndex( nodeIndex.x + delta.x, nodeIndex.y + delta.y ); - - int fullSideLength = (1 << iMaxPower) + 1; - pNode->m_Dependencies[1].m_iVert = WrapVertIndex( CVertIndex( newIndex.x, newIndex.y ), fullSideLength ); - pNode->m_Dependencies[1].m_iNeighbor = iConnection; - } - } -} - - -// --------------------------------------------------------------------------------- // -// CTesselateWinding stuff. -// --------------------------------------------------------------------------------- // - -CTesselateVert::CTesselateVert( CVertIndex const &index, int iNode ) - : m_Index( index ) -{ - m_iNode = iNode; -} - - -CVertInfo::CVertInfo() -{ - int i; - for( i=0; i < sizeof(m_Dependencies)/sizeof(m_Dependencies[0]); i++ ) - { - m_Dependencies[i].m_iVert = CVertIndex( -1, -1 ); - m_Dependencies[i].m_iNeighbor = -1; - } - - for( i=0; i < sizeof(m_ReverseDependencies)/sizeof(m_ReverseDependencies[0]); i++ ) - { - m_ReverseDependencies[i].m_iVert = CVertIndex( -1, -1 ); - m_ReverseDependencies[i].m_iNeighbor = -1; - } - - m_iParent.x = m_iParent.y = -1; - m_iNodeLevel = -1; -} - - -CTesselateVert g_TesselateVerts[] = -{ - CTesselateVert( CVertIndex(1,-1), CHILDNODE_LOWER_RIGHT), - CTesselateVert( CVertIndex(0,-1), -1), - CTesselateVert( CVertIndex(-1,-1), CHILDNODE_LOWER_LEFT), - CTesselateVert( CVertIndex(-1, 0), -1), - CTesselateVert( CVertIndex(-1, 1), CHILDNODE_UPPER_LEFT), - CTesselateVert( CVertIndex(0, 1), -1), - CTesselateVert( CVertIndex(1, 1), CHILDNODE_UPPER_RIGHT), - CTesselateVert( CVertIndex(1, 0), -1), - CTesselateVert( CVertIndex(1,-1), CHILDNODE_LOWER_RIGHT) -}; - -CTesselateWinding g_TWinding = -{ - g_TesselateVerts, - sizeof( g_TesselateVerts ) / sizeof( g_TesselateVerts[0] ) -}; - - - -// --------------------------------------------------------------------------------- // -// CPowerInfo stuff. -// --------------------------------------------------------------------------------- // - -// Precalculated info about each particular displacement size. -#define DECLARE_TABLES( size ) \ - static CVertInfo g_VertInfo_##size##x##size[ size*size ]; \ - static CFourVerts g_SideVerts_##size##x##size[ size*size ]; \ - static CFourVerts g_ChildVerts_##size##x##size[ size*size ]; \ - static CFourVerts g_SideVertCorners_##size##x##size[ size*size ]; \ - static CTwoUShorts g_ErrorEdges_##size##x##size[ size*size ]; \ - static CTriInfo g_TriInfos_##size##x##size[ (size-1)*(size-1)*2 ]; \ - static CPowerInfo g_PowerInfo_##size##x##size( \ - g_VertInfo_##size##x##size, \ - g_SideVerts_##size##x##size, \ - g_ChildVerts_##size##x##size, \ - g_SideVertCorners_##size##x##size,\ - g_ErrorEdges_##size##x##size, \ - g_TriInfos_##size##x##size \ - ) - -#define POWERINFO_ENTRY( size ) \ - (&g_PowerInfo_##size##x##size) - -DECLARE_TABLES( 5 ); -DECLARE_TABLES( 9 ); -DECLARE_TABLES( 17 ); - - -// Index by m_Power. -CPowerInfo *g_PowerInfos[NUM_POWERINFOS] = -{ - NULL, - NULL, - POWERINFO_ENTRY(5), - POWERINFO_ENTRY(9), - POWERINFO_ENTRY(17) -}; - - -CPowerInfo::CPowerInfo( - CVertInfo *pVertInfo, - CFourVerts *pSideVerts, - CFourVerts *pChildVerts, - CFourVerts *pSideVertCorners, - CTwoUShorts *pErrorEdges, - CTriInfo *pTriInfos ) -{ - m_pVertInfo = pVertInfo; - m_pSideVerts = pSideVerts; - m_pChildVerts = pChildVerts; - m_pSideVertCorners = pSideVertCorners; - m_pErrorEdges = pErrorEdges; - m_pTriInfos = pTriInfos; -} - -static void InitPowerInfoTriInfos_R( - CPowerInfo *pInfo, - CVertIndex const &nodeIndex, - CTriInfo* &pTriInfo, - int iMaxPower, - int iLevel ) -{ - int iNodeIndex = VertIndex( nodeIndex, iMaxPower ); - - if( iLevel+1 < iMaxPower ) - { - // Recurse into children. - for( int iChild=0; iChild < 4; iChild++ ) - { - InitPowerInfoTriInfos_R( - pInfo, - pInfo->m_pChildVerts[iNodeIndex].m_Verts[iChild], - pTriInfo, - iMaxPower, - iLevel+1 ); - } - } - else - { - unsigned short indices[3]; - - int vertInc = 1 << ((iMaxPower - iLevel) - 1); - - // We're at a leaf, generate the tris. - CTesselateWinding *pWinding = &g_TWinding; - - // Starting at the bottom-left, wind clockwise picking up vertices and - // generating triangles. - int iCurTriVert = 0; - for( int iVert=0; iVert < pWinding->m_nVerts; iVert++ ) - { - CVertIndex sideVert = BuildOffsetVertIndex( nodeIndex, pWinding->m_Verts[iVert].m_Index, vertInc ); - - if( iCurTriVert == 1 ) - { - // Add this vert and finish the tri. - pTriInfo->m_Indices[0] = indices[0]; - pTriInfo->m_Indices[1] = VertIndex( sideVert, iMaxPower ); - pTriInfo->m_Indices[2] = iNodeIndex; - ++pTriInfo; - } - - indices[0] = VertIndex( sideVert, iMaxPower ); - iCurTriVert = 1; - } - } -} - - -static void InitPowerInfo_R( - CPowerInfo *pPowerInfo, - int iMaxPower, - CVertIndex const &nodeIndex, - CVertIndex const &dependency1, - CVertIndex const &dependency2, - CVertIndex const &nodeEdge1, - CVertIndex const &nodeEdge2, - CVertIndex const &iParent, - int iLevel ) -{ - int sideLength = ((1 << iMaxPower) + 1); - int iNodeIndex = VertIndex( nodeIndex, iMaxPower ); - - pPowerInfo->m_pVertInfo[iNodeIndex].m_iParent = iParent; - pPowerInfo->m_pVertInfo[iNodeIndex].m_iNodeLevel = iLevel + 1; - - pPowerInfo->m_pErrorEdges[iNodeIndex].m_Values[0] = (unsigned short)(VertIndex( nodeEdge1, iMaxPower )); - pPowerInfo->m_pErrorEdges[iNodeIndex].m_Values[1] = (unsigned short)(VertIndex( nodeEdge2, iMaxPower )); - - // Add this node's dependencies. - AddDependency( pPowerInfo->m_pVertInfo, sideLength, nodeIndex, dependency1, iMaxPower, false, true ); - AddDependency( pPowerInfo->m_pVertInfo, sideLength, nodeIndex, dependency2, iMaxPower, false, true ); - - // The 4 side vertices depend on this node. - int iPower = iMaxPower - iLevel; - int vertInc = 1 << (iPower - 1); - - for( int iSide=0; iSide < 4; iSide++ ) - { - // Store the side vert index. - CVertIndex sideVert( nodeIndex.x + g_SideVertMul[iSide][0]*vertInc, nodeIndex.y + g_SideVertMul[iSide][1]*vertInc ); - int iSideVert = VertIndex( sideVert, iMaxPower ); - - pPowerInfo->m_pSideVerts[iNodeIndex].m_Verts[iSide] = sideVert; - - // Store the side vert corners. - CVertIndex sideVertCorner0 = CVertIndex( nodeIndex.x + g_SideVertCorners[iSide].m_Corner1[0]*vertInc, nodeIndex.y + g_SideVertCorners[iSide].m_Corner1[1]*vertInc ); - CVertIndex sideVertCorner1 = CVertIndex( nodeIndex.x + g_SideVertCorners[iSide].m_Corner2[0]*vertInc, nodeIndex.y + g_SideVertCorners[iSide].m_Corner2[1]*vertInc ); - - pPowerInfo->m_pSideVertCorners[iNodeIndex].m_Verts[iSide] = sideVertCorner0; - - // Write the side vert corners into the error-edges list. - pPowerInfo->m_pErrorEdges[iSideVert].m_Values[0] = (unsigned short)VertIndex( sideVertCorner0, iMaxPower ); - pPowerInfo->m_pErrorEdges[iSideVert].m_Values[1] = (unsigned short)VertIndex( sideVertCorner1, iMaxPower ); - - AddDependency( - pPowerInfo->m_pVertInfo, - sideLength, - sideVert, - nodeIndex, - iMaxPower, - true, - true ); - } - - // Recurse into the children. - int nodeInc = vertInc >> 1; - if( nodeInc ) - { - for( int iChild=0; iChild < 4; iChild++ ) - { - CVertIndex childVert( nodeIndex.x + g_ChildNodeIndexMul[iChild].x * nodeInc, nodeIndex.y + g_ChildNodeIndexMul[iChild].y * nodeInc ); - - pPowerInfo->m_pChildVerts[iNodeIndex].m_Verts[iChild] = childVert; - - InitPowerInfo_R( pPowerInfo, - iMaxPower, - childVert, - - CVertIndex(nodeIndex.x + g_ChildNodeDependencies[iChild][0].x*vertInc, nodeIndex.y + g_ChildNodeDependencies[iChild][0].y*vertInc), - CVertIndex(nodeIndex.x + g_ChildNodeDependencies[iChild][1].x*vertInc, nodeIndex.y + g_ChildNodeDependencies[iChild][1].y*vertInc), - - nodeIndex, - CVertIndex( nodeIndex.x + g_ChildNodeIndexMul[iChild].x * vertInc, nodeIndex.y + g_ChildNodeIndexMul[iChild].y * vertInc ), - - nodeIndex, - iLevel + 1 ); - } - } -} - - -void InitPowerInfo( CPowerInfo *pInfo, int iMaxPower ) -{ - int sideLength = (1 << iMaxPower) + 1; - - // Precalculate the dependency graph. - CVertIndex nodeDependency1( sideLength-1, sideLength-1 ); - CVertIndex nodeDependency2( 0, 0 ); - - pInfo->m_RootNode = CVertIndex( sideLength/2, sideLength/2 ); - pInfo->m_SideLength = sideLength; - pInfo->m_SideLengthM1 = sideLength - 1; - pInfo->m_MidPoint = sideLength / 2; - pInfo->m_MaxVerts = sideLength * sideLength; - - // Setup the corner indices. - pInfo->m_CornerPointIndices[CORNER_LOWER_LEFT].Init( 0, 0 ); - pInfo->m_CornerPointIndices[CORNER_UPPER_LEFT].Init( 0, sideLength-1 ); - pInfo->m_CornerPointIndices[CORNER_UPPER_RIGHT].Init( sideLength-1, sideLength-1 ); - pInfo->m_CornerPointIndices[CORNER_LOWER_RIGHT].Init( sideLength-1, 0 ); - - InitPowerInfo_R( - pInfo, - iMaxPower, - pInfo->m_RootNode, - - nodeDependency1, // dependencies - nodeDependency2, - - CVertIndex(0,0), // error edge - CVertIndex(sideLength-1, sideLength-1), - - CVertIndex(-1,-1), // parent - 0 ); - - pInfo->m_Power = iMaxPower; - - CTriInfo *pTriInfo = pInfo->m_pTriInfos; - InitPowerInfoTriInfos_R( pInfo, pInfo->m_RootNode, pTriInfo, iMaxPower, 0 ); - - for( int iEdge=0; iEdge < 4; iEdge++ ) - { - // Figure out the start vert and increment. - CVertIndex nextVert; - GetEdgeVertIndex( sideLength, iEdge, 0, pInfo->m_EdgeStartVerts[iEdge] ); - GetEdgeVertIndex( sideLength, iEdge, 1, nextVert ); - pInfo->m_EdgeIncrements[iEdge] = nextVert - pInfo->m_EdgeStartVerts[iEdge]; - - // Now get the neighbor's start vert and increment. - CVertIndex nbStartVert, nbNextVert, nbDelta; - GetEdgeVertIndex( sideLength, (iEdge+2)&3, 0, nbStartVert ); - GetEdgeVertIndex( sideLength, (iEdge+2)&3, 1, nbNextVert ); - nbDelta = nbNextVert - nbStartVert; - - // Rotate it for each orientation. - for( int orient=0; orient < 4; orient++ ) - { - pInfo->m_NeighborStartVerts[iEdge][orient] = Transform2D( - g_OrientationRotations[orient], - nbStartVert, - CVertIndex( sideLength/2, sideLength/2 ) ); - - pInfo->m_NeighborIncrements[iEdge][orient] = Transform2D( - g_OrientationRotations[orient], - nbDelta, - CVertIndex(0,0) ); - } - } - - - // Init the node index increments. - int curPowerOf4 = 1; - int curTotal = 0; - for( int i=0; i < iMaxPower-1; i++ ) - { - curTotal += curPowerOf4; - - pInfo->m_NodeIndexIncrements[iMaxPower-i-2] = curTotal; - - curPowerOf4 *= 4; - } - - // Store off the total node count - pInfo->m_NodeCount = curTotal + curPowerOf4; - - pInfo->m_nTriInfos = Square( 1 << iMaxPower ) * 2; -} - -class CPowerInfoInitializer -{ -public: - CPowerInfoInitializer() - { - Assert( MAX_MAP_DISP_POWER+1 == NUM_POWERINFOS ); - - for( int i=0; i <= MAX_MAP_DISP_POWER; i++ ) - { - if( g_PowerInfos[i] ) - { - InitPowerInfo( g_PowerInfos[i], i ); - } - } - } -}; - -static CPowerInfoInitializer g_PowerInfoInitializer; - - -const CPowerInfo* GetPowerInfo( int iPower ) -{ - Assert( iPower >= 0 && iPower < ARRAYSIZE( g_PowerInfos ) ); - Assert( g_PowerInfos[iPower] ); - return g_PowerInfos[iPower]; -} - - -// ------------------------------------------------------------------------------------------------ // -// CPowerInfo member function initialization. -// ------------------------------------------------------------------------------------------------ // - -const CVertIndex& CPowerInfo::GetCornerPointIndex( int iCorner ) const -{ - Assert( iCorner >= 0 && iCorner < 4 ); - return m_CornerPointIndices[iCorner]; -} - diff --git a/public/disp_powerinfo.h b/public/disp_powerinfo.h deleted file mode 100644 index 7d00a2630..000000000 --- a/public/disp_powerinfo.h +++ /dev/null @@ -1,213 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: This module defines the CPowerInfo class, which contains a -// whole bunch of precalculated data for each displacement power. -// It holds data that indicates how to tesselate, how to access -// neighbor displacements, etc. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef DISP_POWERINFO_H -#define DISP_POWERINFO_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "disp_vertindex.h" -#include "bspfile.h" - - -#define NUM_POWERINFOS (MAX_MAP_DISP_POWER+1) - - -struct DispNodeInfo_t -{ - enum - { - // Indicates if any children at all have triangles - CHILDREN_HAVE_TRIANGLES = 0x1 - }; - - - // Indicates which tesselation indices are associated with a node - unsigned short m_FirstTesselationIndex; - unsigned char m_Count; - unsigned char m_Flags; -}; - - -// ------------------------------------------------------------------------ // -// CTesselateWindings are used to tell what order a node needs to visit -// vertices while tesselating. -// ------------------------------------------------------------------------ // -class CTesselateVert -{ -public: - CTesselateVert( CVertIndex const &index, int iNode ); - - CVertIndex m_Index; - short m_iNode; // Which node this vert is a part of (-1 on left, right, up, and down). -}; - - -class CTesselateWinding -{ -public: - CTesselateVert *m_Verts; - short m_nVerts; // (includes the last vert) -}; - - -class CVertDependency -{ -public: - - // Returns false if there is no dependency stored here. - bool IsValid() { return m_iVert.x != -1; } - - -public: - - // The vert index is in the same power as the source displacement. - // It is also wrapped, so for example, on the middle of the right edge - // of a 3x3, it will have a dependency on the 3x3's root node (1,1), and it - // will have another (1,1) entry that references a neighbor. - CVertIndex m_iVert; - - // This is -1 if the vert exists inside the source displacement. - // It is one of the NEIGHBOREDGE_ codes above if it reaches into a neighbor. - short m_iNeighbor; -}; - - -// Precalculated data about displacement vertices. -class CVertInfo -{ -public: - CVertInfo(); - - // These are the vertices that this vertex depends on (vertices that must be - // active for this vert to exist). - CVertDependency m_Dependencies[2]; - - // These are the vertices that have this vert in their m_Dependencies. - enum { NUM_REVERSE_DEPENDENCIES=4 }; - CVertDependency m_ReverseDependencies[NUM_REVERSE_DEPENDENCIES]; - - short m_iNodeLevel; // -1 if this is not a node. Otherwise, the recursion level - // of this node (root node = 1). - CVertIndex m_iParent; // x=-1 if this is a not a node or if it's the root node. -}; - - -class CTwoUShorts -{ -public: - unsigned short m_Values[2]; -}; - - -class CFourVerts -{ -public: - CVertIndex m_Verts[4]; -}; - - -// Used for referencing triangles in the fully-tesselated displacement by index. -class CTriInfo -{ -public: - unsigned short m_Indices[3]; -}; - - -// Precalculated data for displacements of a certain power. -class CPowerInfo -{ -public: - CPowerInfo( - CVertInfo *pVertInfo, - CFourVerts *pSideVerts, - CFourVerts *pChildVerts, - CFourVerts *pSideVertCorners, - CTwoUShorts *pErrorEdges, - CTriInfo *pTriInfos ); - - int GetPower() const { return m_Power; } - int GetSideLength() const { return m_SideLength; } - const CVertIndex& GetRootNode() const { return m_RootNode; } - int GetMidPoint() const { return m_MidPoint; } // Half the edge length. - - // Get at the tri list. - int GetNumTriInfos() const { return m_nTriInfos; } - const CTriInfo* GetTriInfo( int i ) const { return &m_pTriInfos[i]; } - - // Get the number of vertices in a displacement of this power. - int GetNumVerts() const { return m_MaxVerts; } - - // Return a corner point index. Indexed by the CORNER_ defines. - const CVertIndex& GetCornerPointIndex( int iCorner ) const; - - -public: - - CVertInfo *m_pVertInfo; - CFourVerts *m_pSideVerts; // The 4 side verts for each node. - CFourVerts *m_pChildVerts; // The 4 children for each node. - CFourVerts *m_pSideVertCorners; - CTwoUShorts *m_pErrorEdges; // These are the edges - // that are used to measure the screenspace - // error with respect to each vert. - - CTriInfo *m_pTriInfos; - int m_nTriInfos; - - int m_Power; - - CVertIndex m_RootNode; - int m_SideLength; - int m_SideLengthM1; // Side length minus 1. - int m_MidPoint; // Side length / 2. - int m_MaxVerts; // m_SideLength * m_SideLength - int m_NodeCount; // total # of nodes, including children - - // Precalculated increments if you're using a bit vector to represent nodes. - // Starting at level 0 of the tree, this stores the increment between the nodes at this - // level. Vectors holding node data are stored in preorder traversal, and these - // increments tell the number of elements between nodes at each level. - int m_NodeIndexIncrements[MAX_MAP_DISP_POWER]; - - CVertIndex m_EdgeStartVerts[4]; - CVertIndex m_EdgeIncrements[4]; - - CVertIndex m_NeighborStartVerts[4][4]; // [side][orientation] - CVertIndex m_NeighborIncrements[4][4]; // [side][orientation] - - -private: - friend void InitPowerInfo( CPowerInfo *pInfo, int iMaxPower ); - - CVertIndex m_CornerPointIndices[4]; -}; - - -// ----------------------------------------------------------------------------- // -// Globals. -// ----------------------------------------------------------------------------- // - -// Indexed by the TWINDING_ enums. -extern CTesselateWinding g_TWinding; - - -// ----------------------------------------------------------------------------- // -// Functions. -// ----------------------------------------------------------------------------- // - -// Valid indices are MIN_MAP_DISP_POWER through (and including) MAX_MAP_DISP_POWER. -const CPowerInfo* GetPowerInfo( int iPower ); - - -#endif // DISP_POWERINFO_H diff --git a/public/disp_tesselate.h b/public/disp_tesselate.h deleted file mode 100644 index b36518950..000000000 --- a/public/disp_tesselate.h +++ /dev/null @@ -1,206 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef DISP_TESSELATE_H -#define DISP_TESSELATE_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "disp_powerinfo.h" - - -inline int InternalVertIndex( const CPowerInfo *pInfo, const CVertIndex &vert ) -{ - return vert.y * pInfo->m_SideLength + vert.x; -} - - -template< class TesselateHelper > -inline void InternalEndTriangle( - TesselateHelper *pHelper, - CVertIndex const &nodeIndex, - int &iCurTriVert ) -{ - // End our current triangle here. - Assert( iCurTriVert == 2 ); - - // Finish the triangle. - pHelper->m_TempIndices[2] = (unsigned short)InternalVertIndex( pHelper->m_pPowerInfo, nodeIndex ); - - pHelper->EndTriangle(); - - // Add on the last vertex to join to the next triangle. - pHelper->m_TempIndices[0] = pHelper->m_TempIndices[1]; - iCurTriVert = 1; -} - - -//----------------------------------------------------------------------------- -// Tesselates a single node, doesn't deal with hierarchy -//----------------------------------------------------------------------------- -template< class TesselateHelper > -inline void TesselateDisplacementNode( - TesselateHelper *pHelper, - CVertIndex const &nodeIndex, - int iLevel, - int *pActiveChildren ) -{ - int iPower = pHelper->m_pPowerInfo->m_Power - iLevel; - int vertInc = 1 << (iPower - 1); - - CTesselateWinding *pWinding = &g_TWinding; - - // Starting at the bottom-left, wind clockwise picking up vertices and - // generating triangles. - int iCurTriVert = 0; - for( int iVert=0; iVert < pWinding->m_nVerts; iVert++ ) - { - CVertIndex sideVert = BuildOffsetVertIndex( nodeIndex, pWinding->m_Verts[iVert].m_Index, vertInc ); - - int iVertNode = pWinding->m_Verts[iVert].m_iNode; - bool bNode = (iVertNode != -1) && pActiveChildren[iVertNode]; - if( bNode ) - { - if( iCurTriVert == 2 ) - InternalEndTriangle( pHelper, nodeIndex, iCurTriVert ); - - iCurTriVert = 0; - } - else - { - int iVertBit = InternalVertIndex( pHelper->m_pPowerInfo, sideVert ); - if( pHelper->m_pActiveVerts[iVertBit>>5] & (1 << (iVertBit & 31)) ) - { - // Ok, add a vert here. - pHelper->m_TempIndices[iCurTriVert] = (unsigned short)InternalVertIndex( pHelper->m_pPowerInfo, sideVert ); - iCurTriVert++; - if( iCurTriVert == 2 ) - InternalEndTriangle( pHelper, nodeIndex, iCurTriVert ); - } - } - } -} - - -//----------------------------------------------------------------------------- -// Tesselates in a *breadth first* fashion -//----------------------------------------------------------------------------- -template< class T > -inline void TesselateDisplacement_R( - T *pHelper, - const CVertIndex &nodeIndex, - int iNodeBitIndex, - int iLevel - ) -{ - // Here's the node info for our current node - Assert( iNodeBitIndex < pHelper->m_pPowerInfo->m_NodeCount ); - DispNodeInfo_t& nodeInfo = pHelper->GetNodeInfo( iNodeBitIndex ); - - // Store off the current number of indices - int oldIndexCount = pHelper->m_nIndices; - - // Go through each quadrant. If there is an active child node, recurse down. - int bActiveChildren[4]; - if( iLevel >= pHelper->m_pPowerInfo->m_Power - 1 ) - { - // This node has no children. - bActiveChildren[0] = bActiveChildren[1] = bActiveChildren[2] = bActiveChildren[3] = false; - } - else - { - int iNodeIndex = InternalVertIndex( pHelper->m_pPowerInfo, nodeIndex ); - - int iChildNodeBit = iNodeBitIndex + 1; - for( int iChild=0; iChild < 4; iChild++ ) - { - CVertIndex const &childNode = pHelper->m_pPowerInfo->m_pChildVerts[iNodeIndex].m_Verts[iChild]; - - // Make sure we really can tesselate here (a smaller neighbor displacement could - // have inactivated certain edge verts. - int iVertBit = InternalVertIndex( pHelper->m_pPowerInfo, childNode ); - bActiveChildren[iChild] = ( pHelper->m_pActiveVerts[iVertBit>>5] & (1 << (iVertBit & 31)) ); - - if( bActiveChildren[iChild] ) - { - TesselateDisplacement_R( pHelper, childNode, iChildNodeBit, iLevel+1 ); - } - else - { - // Make sure the triangle counts are cleared on this one because it may visit this - // node in GenerateDecalFragments_R if nodeInfo's CHILDREN_HAVE_TRIANGLES flag is set. - DispNodeInfo_t &childInfo = pHelper->GetNodeInfo( iChildNodeBit ); - childInfo.m_Count = 0; - childInfo.m_Flags = 0; - } - - iChildNodeBit += pHelper->m_pPowerInfo->m_NodeIndexIncrements[iLevel]; - } - } - - // Set the child field - if ( pHelper->m_nIndices != oldIndexCount ) - { - nodeInfo.m_Flags = DispNodeInfo_t::CHILDREN_HAVE_TRIANGLES; - oldIndexCount = pHelper->m_nIndices; - } - else - { - nodeInfo.m_Flags = 0; - } - - // Now tesselate the node itself... - TesselateDisplacementNode( pHelper, nodeIndex, iLevel, bActiveChildren ); - - // Now that we've tesselated, figure out how many indices we've added at this node - nodeInfo.m_Count = pHelper->m_nIndices - oldIndexCount; - nodeInfo.m_FirstTesselationIndex = oldIndexCount; - Assert( nodeInfo.m_Count % 3 == 0 ); -} - - -class CBaseTesselateHelper -{ -public: - - // Functions your derived class must implement: - // void EndTriangle(); // (the 3 indices are in m_TempIndices). - // DispNodeInfo_t& GetNodeInfo( int iNodeBit ); - - - // Set these before calling TesselateDisplacement. - uint32 *m_pActiveVerts; // These bits control the tesselation. - const CPowerInfo *m_pPowerInfo; // Lots of precalculated data about a displacement this size. - - - // Used internally by TesselateDisplacement. - int m_nIndices; // After calling TesselateDisplacement, this is set to the # of indices generated. - unsigned short m_TempIndices[6]; -}; - - - -// This interface is shared betwixt VBSP and the engine. VBSP uses it to build the -// physics mesh and the engine uses it to render. -// -// To use this function, derive a class from CBaseTesselateHelper that supports the TesselateHelper functions. -template< class TesselateHelper > -inline void TesselateDisplacement( TesselateHelper *pHelper ) -{ - pHelper->m_nIndices = 0; - - TesselateDisplacement_R( - pHelper, - pHelper->m_pPowerInfo->m_RootNode, - 0, // node bit indexing CDispDecal::m_NodeIntersects - 0 ); -} - - -#endif // DISP_TESSELATE_H diff --git a/public/disp_vertindex.h b/public/disp_vertindex.h deleted file mode 100644 index 5fb66a931..000000000 --- a/public/disp_vertindex.h +++ /dev/null @@ -1,150 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef DISP_VERTINDEX_H -#define DISP_VERTINDEX_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "tier0/dbg.h" - - -// ------------------------------------------------------------------------ // -// Helper class used for indexing vertices in the 2D grid. -// ------------------------------------------------------------------------ // - -class CVertIndex -{ -public: - CVertIndex(); - CVertIndex( short ix, short iy ); - - void Init( short ix, short iy ); - - short& operator[]( short i ); - short const& operator[]( short i ) const; - void operator+=( CVertIndex const &other ); - void operator-=( CVertIndex const &other ); - CVertIndex operator+( CVertIndex const &other ) const; - CVertIndex operator-( CVertIndex const &other ) const; - void operator<<=( int shift ); - void operator>>=( int shift ); - bool operator==( CVertIndex const &other ) const; - bool operator!=( CVertIndex const &other ) const; - - -public: - - short x, y; -}; - - -// ------------------------------------------------------------------ // -// Helper functions. -// ------------------------------------------------------------------ // - -inline CVertIndex BuildOffsetVertIndex( - CVertIndex const &nodeIndex, - CVertIndex const &offset, - int mul ) -{ - return CVertIndex( nodeIndex.x + offset.x * mul, nodeIndex.y + offset.y * mul ); -} - - -// ------------------------------------------------------------------ // -// CVertIndex inlines. -// ------------------------------------------------------------------ // - -inline CVertIndex::CVertIndex() -{ -} - - -inline CVertIndex::CVertIndex( short ix, short iy ) -{ - x = ix; - y = iy; -} - - -inline void CVertIndex::Init( short ix, short iy ) -{ - x = ix; - y = iy; -} - - -inline short& CVertIndex::operator[]( short i ) -{ - Assert( i >= 0 && i <= 1 ); - return ((short*)this)[i]; -} - - -inline short const& CVertIndex::operator[]( short i ) const -{ - Assert( i >= 0 && i <= 1 ); - return ((short*)this)[i]; -} - - -inline void CVertIndex::operator+=( CVertIndex const &other ) -{ - x += other.x; - y += other.y; -} - - -inline void CVertIndex::operator-=( CVertIndex const &other ) -{ - x -= other.x; - y -= other.y; -} - - -inline CVertIndex CVertIndex::operator+( CVertIndex const &other ) const -{ - return CVertIndex( x + other.x, y + other.y ); -} - - -inline CVertIndex CVertIndex::operator-( CVertIndex const &other ) const -{ - return CVertIndex( x - other.x, y - other.y ); -} - - -inline void CVertIndex::operator<<=( int shift ) -{ - x <<= shift; - y <<= shift; -} - - -inline void CVertIndex::operator>>=( int shift ) -{ - x >>= shift; - y >>= shift; -} - - -inline bool CVertIndex::operator==( CVertIndex const &other ) const -{ - return x==other.x && y==other.y; -} - - -inline bool CVertIndex::operator!=( CVertIndex const &other ) const -{ - return x!=other.x || y!=other.y; -} - - -#endif // DISP_VERTINDEX_H diff --git a/public/dispcoll.cpp b/public/dispcoll.cpp deleted file mode 100644 index 7ef3f7a78..000000000 --- a/public/dispcoll.cpp +++ /dev/null @@ -1,1994 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "BuildDisp.h" -#include "DispColl.h" -#include "tier0/dbg.h" - -//============================================================================= - -const float CDispCollTree::COLLISION_EPSILON = 0.01f; -const float CDispCollTree::ONE_MINUS_COLLISION_EPSILON = 1.0f - COLLISION_EPSILON; - -//============================================================================= -// -// Displacement Collision Triangle Functions -// - - -//----------------------------------------------------------------------------- -// Purpose: initialize the displacement triangles -//----------------------------------------------------------------------------- -void CDispCollTri::Init( void ) -{ - for( int i = 0; i < 3; i++ ) - { - m_Points[i].x = 0.0f; m_Points[i].y = 0.0f; m_Points[i].z = 0.0f; - m_PointNormals[i].x = 0.0f; m_PointNormals[i].y = 0.0f; m_PointNormals[i].z = 0.0f; - } - - m_Normal.x = 0.0f; m_Normal.y = 0.0f; m_Normal.z = 0.0f; - m_Distance = 0.0f; - - m_ProjAxes[0] = -1; - m_ProjAxes[1] = -1; - - m_bIntersect = false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline void CDispCollTri::SetPoint( int index, Vector const &vert ) -{ - Assert( index >= 0 ); - Assert( index < 3 ); - - m_Points[index].x = vert[0]; - m_Points[index].y = vert[1]; - m_Points[index].z = vert[2]; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline void CDispCollTri::SetPointNormal( int index, Vector const &normal ) -{ - Assert( index >= 0 ); - Assert( index < 3 ); - - m_PointNormals[index].x = normal[0]; - m_PointNormals[index].y = normal[1]; - m_PointNormals[index].z = normal[2]; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDispCollTri::CalcPlane( void ) -{ - // - // calculate the plane normal and distance - // - Vector segment1, segment2, cross; - - segment1 = m_Points[1] - m_Points[0]; - segment2 = m_Points[2] - m_Points[0]; - cross = segment1.Cross( segment2 ); - m_Normal = cross; - VectorNormalize(m_Normal); - - m_Distance = m_Normal.Dot( m_Points[0] ); - - // - // calculate the projection axes - // - if( FloatMakePositive( m_Normal[0] ) > FloatMakePositive( m_Normal[1] ) ) - { - if( FloatMakePositive( m_Normal[0] ) > FloatMakePositive( m_Normal[2] ) ) - { - m_ProjAxes[0] = 1; - m_ProjAxes[1] = 2; - } - else - { - m_ProjAxes[0] = 0; - m_ProjAxes[1] = 1; - } - } - else - { - if( FloatMakePositive( m_Normal[1] ) > FloatMakePositive( m_Normal[2] ) ) - { - m_ProjAxes[0] = 0; - m_ProjAxes[1] = 2; - } - else - { - m_ProjAxes[0] = 0; - m_ProjAxes[1] = 1; - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline void CDispCollTri::SetIntersect( bool bIntersect ) -{ - m_bIntersect = bIntersect; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline bool CDispCollTri::IsIntersect( void ) -{ - return m_bIntersect; -} - - -//============================================================================= -// -// Displacement Collision Node Functions -// - - -//----------------------------------------------------------------------------- -// Purpose: constructor -//----------------------------------------------------------------------------- -CDispCollNode::CDispCollNode() -{ - m_Bounds[0].x = m_Bounds[0].y = m_Bounds[0].z = 99999.9f; - m_Bounds[1].x = m_Bounds[1].y = m_Bounds[1].z = -99999.9f; - - m_Tris[0].Init(); - m_Tris[1].Init(); - - m_bIsLeaf = false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline bool CDispCollNode::IsLeaf( void ) -{ - return m_bIsLeaf; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline void CDispCollNode::SetBounds( Vector const &bMin, Vector const &bMax ) -{ - m_Bounds[0] = bMin; - m_Bounds[1] = bMax; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline void CDispCollNode::GetBounds( Vector &bMin, Vector &bMax ) -{ - bMin = m_Bounds[0]; - bMax = m_Bounds[1]; -} - - -//============================================================================= -// -// Displacement Collision Tree Functions -// - -//----------------------------------------------------------------------------- -// Purpose: constructor -//----------------------------------------------------------------------------- -CDispCollTree::CDispCollTree() -{ - m_Power = 0; - - m_NodeCount = 0; - m_pNodes = NULL; - - InitAABBData(); -} - - -//----------------------------------------------------------------------------- -// Purpose: deconstructor -//----------------------------------------------------------------------------- -CDispCollTree::~CDispCollTree() -{ - FreeNodes(); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDispCollTree::InitAABBData( void ) -{ - m_AABBNormals[0].x = -1.0f; m_AABBNormals[0].y = 0.0f; m_AABBNormals[0].z = 0.0f; - m_AABBNormals[1].x = 1.0f; m_AABBNormals[1].y = 0.0f; m_AABBNormals[1].z = 0.0f; - - m_AABBNormals[2].x = 0.0f; m_AABBNormals[2].y = -1.0f; m_AABBNormals[2].z = 0.0f; - m_AABBNormals[3].x = 0.0f; m_AABBNormals[3].y = 1.0f; m_AABBNormals[3].z = 0.0f; - - m_AABBNormals[4].x = 0.0f; m_AABBNormals[4].y = 0.0f; m_AABBNormals[4].z = -1.0f; - m_AABBNormals[5].x = 0.0f; m_AABBNormals[5].y = 0.0f; m_AABBNormals[5].z = 1.0f; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDispCollTree::CalcBounds( CDispCollNode *pNode, int nodeIndex ) -{ - Vector bounds[2]; - bounds[0].Init( 99999.9f, 99999.9f, 99999.9f ); - bounds[1].Init( -99999.9f, -99999.9f, -99999.9f ); - - // - // handle leaves differently -- bounding volume defined by triangles - // - if( pNode->IsLeaf() ) - { - for( int i = 0; i < 2; i++ ) - { - for( int j = 0; j < 3; j++ ) - { - // - // minimum - // - if( bounds[0].x > pNode->m_Tris[i].m_Points[j].x ) { bounds[0].x = pNode->m_Tris[i].m_Points[j].x; } - if( bounds[0].y > pNode->m_Tris[i].m_Points[j].y ) { bounds[0].y = pNode->m_Tris[i].m_Points[j].y; } - if( bounds[0].z > pNode->m_Tris[i].m_Points[j].z ) { bounds[0].z = pNode->m_Tris[i].m_Points[j].z; } - - // - // maximum - // - if( bounds[1].x < pNode->m_Tris[i].m_Points[j].x ) { bounds[1].x = pNode->m_Tris[i].m_Points[j].x; } - if( bounds[1].y < pNode->m_Tris[i].m_Points[j].y ) { bounds[1].y = pNode->m_Tris[i].m_Points[j].y; } - if( bounds[1].z < pNode->m_Tris[i].m_Points[j].z ) { bounds[1].z = pNode->m_Tris[i].m_Points[j].z; } - } - } - } - // - // bounding volume defined by maxima and minima of children volumes - // - else - { - for( int i = 0; i < 4; i++ ) - { - int childIndex = GetChildNode( nodeIndex, i ); - CDispCollNode *pChildNode = &m_pNodes[childIndex]; - - Vector childBounds[2]; - pChildNode->GetBounds( childBounds[0], childBounds[1] ); - - // - // minimum - // - if( bounds[0].x > childBounds[0].x ) { bounds[0].x = childBounds[0].x; } - if( bounds[0].y > childBounds[0].y ) { bounds[0].y = childBounds[0].y; } - if( bounds[0].z > childBounds[0].z ) { bounds[0].z = childBounds[0].z; } - - // - // maximum - // - if( bounds[1].x < childBounds[1].x ) { bounds[1].x = childBounds[1].x; } - if( bounds[1].y < childBounds[1].y ) { bounds[1].y = childBounds[1].y; } - if( bounds[1].z < childBounds[1].z ) { bounds[1].z = childBounds[1].z; } - } - } - - pNode->SetBounds( bounds[0], bounds[1] ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDispCollTree::CreateNodes_r( CCoreDispInfo *pDisp, int nodeIndex, int termLevel ) -{ - int nodeLevel = GetNodeLevel( nodeIndex ); - - // - // terminating condition -- set node info (leaf or otherwise) - // - if( nodeLevel == termLevel ) - { - CDispCollNode *pNode = &m_pNodes[nodeIndex]; - CalcBounds( pNode, nodeIndex ); - - return; - } - - // - // recurse into children - // - for( int i = 0; i < 4; i++ ) - { - CreateNodes_r( pDisp, GetChildNode( nodeIndex, i ), termLevel ); - } -} - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDispCollTree::CreateNodes( CCoreDispInfo *pDisp ) -{ - // - // create all nodes in tree - // - int power = pDisp->GetPower() + 1; - for( int level = power; level > 0; level-- ) - { - CreateNodes_r( pDisp, 0 /* rootIndex */, level ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CDispCollTree::GetNodeIndexFromComponents( int x, int y ) -{ - int index = 0; - - // Interleave bits from the x and y values to create the index: - - for( int shift = 0; x != 0; shift += 2, x >>= 1 ) - { - index |= ( x & 1 ) << shift; - } - - for( shift = 1; y != 0; shift += 2, y >>= 1 ) - { - index |= ( y & 1 ) << shift; - } - - return index; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDispCollTree::InitLeaves( CCoreDispInfo *pDisp ) -{ - // - // get power and width and displacement surface - // - int power = pDisp->GetPower(); - int width = pDisp->GetWidth(); - - // - // get leaf indices - // - int startIndex = CalcNodeCount( power - 1 ); - int endIndex = CalcNodeCount( power ); - - for( int index = startIndex; index < endIndex; index++ ) - { - // - // create triangles at leaves - // - int x = ( index - startIndex ) % ( width - 1 ); - int y = ( index - startIndex ) / ( width - 1 ); - - int nodeIndex = GetNodeIndexFromComponents( x, y ); - nodeIndex += startIndex; - - Vector vert; - Vector normal; - - // - // tri 1 - // - pDisp->GetVert( x + ( y * width ), vert ); - pDisp->GetNormal( x + ( y * width ), normal ); - m_pNodes[nodeIndex].m_Tris[0].SetPoint( 0, vert ); - m_pNodes[nodeIndex].m_Tris[0].SetPointNormal( 0, normal ); - - pDisp->GetVert( x + ( ( y + 1 ) * width ), vert ); - pDisp->GetNormal( x + ( ( y + 1 ) * width ), normal ); - m_pNodes[nodeIndex].m_Tris[0].SetPoint( 1, vert ); - m_pNodes[nodeIndex].m_Tris[0].SetPointNormal( 1, normal ); - - pDisp->GetVert( ( x + 1 ) + ( y * width ), vert ); - pDisp->GetNormal( ( x + 1 ) + ( y * width ), normal ); - m_pNodes[nodeIndex].m_Tris[0].SetPoint( 2, vert ); - m_pNodes[nodeIndex].m_Tris[0].SetPointNormal( 2, normal ); - - m_pNodes[nodeIndex].m_Tris[0].CalcPlane(); - - // - // tri 2 - // - pDisp->GetVert( ( x + 1 ) + ( y * width ), vert ); - pDisp->GetNormal( ( x + 1 ) + ( y * width ), normal ); - m_pNodes[nodeIndex].m_Tris[1].SetPoint( 0, vert ); - m_pNodes[nodeIndex].m_Tris[1].SetPointNormal( 0, normal ); - - pDisp->GetVert( x + ( ( y + 1 ) * width ), vert ); - pDisp->GetNormal( x + ( ( y + 1 ) * width ), normal ); - m_pNodes[nodeIndex].m_Tris[1].SetPoint( 1, vert ); - m_pNodes[nodeIndex].m_Tris[1].SetPointNormal( 1, normal ); - - pDisp->GetVert( ( x + 1 ) + ( ( y + 1 ) * width ), vert ); - pDisp->GetNormal( ( x + 1 ) + ( ( y + 1 ) * width ), normal ); - m_pNodes[nodeIndex].m_Tris[1].SetPoint( 2, vert ); - m_pNodes[nodeIndex].m_Tris[1].SetPointNormal( 2, normal ); - - m_pNodes[nodeIndex].m_Tris[1].CalcPlane(); - - // set node as leaf - m_pNodes[nodeIndex].m_bIsLeaf = true; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: allocate and initialize the displacement collision tree -// Input: power - size of the displacement surface -// Output: bool - success? (true/false) -//----------------------------------------------------------------------------- -bool CDispCollTree::Create( CCoreDispInfo *pDisp ) -{ - // - // calculate the number of nodes needed given the size of the displacement - // - m_Power = pDisp->GetPower(); - m_NodeCount = CalcNodeCount( m_Power ); - - // - // allocate tree space - // - if( !AllocNodes( m_NodeCount ) ) - return false; - - // initialize leaves - InitLeaves( pDisp ); - - // create tree nodes - CreateNodes( pDisp ); - - // tree successfully created! - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: allocate memory for the displacement collision tree -// Input: nodeCount - number of nodes to allocate -// Output: bool - success? (true/false) -//----------------------------------------------------------------------------- -bool CDispCollTree::AllocNodes( int nodeCount ) -{ - // sanity check - Assert( nodeCount != 0 ); - - m_pNodes = new CDispCollNode[nodeCount]; - if( !m_pNodes ) - return false; - - // tree successfully allocated! - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: release allocated memory for displacement collision tree -//----------------------------------------------------------------------------- -void CDispCollTree::FreeNodes( void ) -{ - if( m_pNodes ) - { - delete [] m_pNodes; - m_pNodes = NULL; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: calculate the number of tree nodes given the size of the -// displacement surface -// Input: power - size of the displacement surface -// Output: int - the number of tree nodes -//----------------------------------------------------------------------------- -inline int CDispCollTree::CalcNodeCount( int power ) -{ - // power range [2...4] - Assert( power > 0 ); - Assert( power < 5 ); - - return ( ( 1 << ( ( power + 1 ) << 1 ) ) / 3 ); -} - - -//----------------------------------------------------------------------------- -// Purpose: get the parent node index given the current node -// Input: nodeIndex - current node index -// Output: int - the index of the parent node -//----------------------------------------------------------------------------- -inline int CDispCollTree::GetParentNode( int nodeIndex ) -{ - // node range [0...m_NodeCount) - Assert( nodeIndex >= 0 ); - Assert( nodeIndex < m_NodeCount ); - - // ( nodeIndex - 1 ) / 4 - return ( ( nodeIndex - 1 ) >> 2 ); -} - - -//----------------------------------------------------------------------------- -// Purpose: get the child node index given the current node index and direction -// of the child (1 of 4) -// Input: nodeIndex - current node index -// direction - direction of the child ( [0...3] - SW, SE, NW, NE ) -// Output: int - the index of the child node -//----------------------------------------------------------------------------- -inline int CDispCollTree::GetChildNode( int nodeIndex, int direction ) -{ - // node range [0...m_NodeCount) - Assert( nodeIndex >= 0 ); - Assert( nodeIndex < m_NodeCount ); - - // ( nodeIndex * 4 ) + ( direction + 1 ) - return ( ( nodeIndex << 2 ) + ( direction + 1 ) ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline int CDispCollTree::GetNodeLevel( int nodeIndex ) -{ - // node range [0...m_NodeCount) - Assert( nodeIndex >= 0 ); - Assert( nodeIndex < m_NodeCount ); - - // level = 2^n + 1 - if( nodeIndex == 0 ) { return 1; } - if( nodeIndex < 5 ) { return 2; } - if( nodeIndex < 21 ) { return 3; } - if( nodeIndex < 85 ) { return 4; } - if( nodeIndex < 341 ) { return 5; } - - return -1; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CDispCollTree::RayTriTest( Vector const &rayStart, Vector const &rayDir, float const rayLength, - CDispCollTri const *pTri, float *fraction ) -{ - const float DET_EPSILON = 0.001f; - const float DIST_EPSILON = 0.001f; - - // - // calculate the edges - // - Vector edge1 = pTri->m_Points[1] - pTri->m_Points[0]; - Vector edge2 = pTri->m_Points[2] - pTri->m_Points[0]; - -// Vector faceNormal = edge1.Cross( edge2 ); -// Vector normNormal = faceNormal.Normalize(); - - // - // calculate the triangle's determinant - // - Vector pVec = rayDir.Cross( edge2 ); - float det = pVec.Dot( edge1 ); - - // if determinant is zero -- ray lies in plane - if( ( det > -DET_EPSILON ) && ( det < DET_EPSILON ) ) - return false; - - // - // utility calculations - inverse determinant and distance from v0 to ray start - // - double invDet = 1.0f / det; - Vector tVec = rayStart - pTri->m_Points[0]; - - // - // calculate the U parameter and test bounds - // - double u = pVec.Dot( tVec ) * invDet; - if( ( u < 0.0f ) || ( u > 1.0f ) ) - return false; - - Vector qVec = tVec.Cross( edge1 ); - - // - // calculate the V parameter and test bounds - // - double v = qVec.Dot( rayDir ) * invDet; - if( ( v < 0.0f ) || ( ( u + v ) > 1.0f ) ) - return false; - - // calculate where ray intersects triangle - *fraction = qVec.Dot( edge2 ) * invDet; - *fraction /= rayLength; - - if( ( *fraction < DIST_EPSILON ) || ( *fraction > ( 1.0f - DIST_EPSILON ) ) ) - return false; - - return true; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CDispCollTree::RayTriListTest( CDispCollTreeTempData *pTemp, CDispCollData *pData ) -{ - // save starting fraction -- to test for collision - float startFraction = pData->m_Fraction; - - // - // calculate the ray - // - Vector seg = pData->m_EndPos - pData->m_StartPos; - Vector rayDir = seg; - float rayLength = VectorNormalize( rayDir ); - - // - // test ray against all triangles in list - // - for( int i = 0; i < pTemp->m_TriListCount; i++ ) - { - float fraction = 1.0f; - bool bResult = RayTriTest( pData->m_StartPos, rayDir, rayLength, pTemp->m_ppTriList[i], &fraction ); - if( !bResult ) - continue; - - if( pData->m_bOcclude ) - { - return true; - } - - if( fraction < pData->m_Fraction ) - { - pData->m_Fraction = fraction; - pData->m_Normal = pTemp->m_ppTriList[i]->m_Normal; - pData->m_Distance = pTemp->m_ppTriList[i]->m_Distance; - } - } - - // collision! - if( pData->m_Fraction < startFraction ) - return true; - - // no collision! - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDispCollTree::RayAABBTest( CDispCollTreeTempData *pTemp, Vector &rayStart, Vector &rayEnd ) -{ - const float MY_DIST_EPSILON = 0.01f; - - for( int i = 0; i < 6; i++ ) - { - float dist1 = m_AABBNormals[i].Dot( rayStart ) - pTemp->m_AABBDistances[i]; - float dist2 = m_AABBNormals[i].Dot( rayEnd ) - pTemp->m_AABBDistances[i]; - - // - // entry intersection point - move ray start up to intersection - // - if( ( dist1 > MY_DIST_EPSILON ) && ( dist2 < -MY_DIST_EPSILON ) ) - { - float fraction = ( dist1 / ( dist1 - dist2 ) ); - - Vector segment, increment; - segment = ( rayEnd - rayStart ) * fraction; - increment = segment; - VectorNormalize(increment); - segment += increment; - rayStart += segment; - } - else if( ( dist1 > MY_DIST_EPSILON ) && ( dist2 > MY_DIST_EPSILON ) ) - { - return false; - } - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDispCollTree::CreatePlanesFromBounds( CDispCollTreeTempData *pTemp, Vector const &bbMin, Vector const &bbMax ) -{ - // - // note -- these never change! - // -// m_AABBNormals[0].x = -1; -// m_AABBNormals[1].x = 1; - -// m_AABBNormals[2].y = -1; -// m_AABBNormals[3].y = 1; - -// m_AABBNormals[4].z = -1; -// m_AABBNormals[5].z = 1; - - pTemp->m_AABBDistances[0] = -bbMin.x; - pTemp->m_AABBDistances[1] = bbMax.x; - - pTemp->m_AABBDistances[2] = -bbMin.y; - pTemp->m_AABBDistances[3] = bbMax.y; - - pTemp->m_AABBDistances[4] = -bbMin.z; - pTemp->m_AABBDistances[5] = bbMax.z; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDispCollTree::RayNodeTest_r( CDispCollTreeTempData *pTemp, int nodeIndex, Vector rayStart, Vector rayEnd ) -{ - // get the current node - CDispCollNode *pNode = &m_pNodes[nodeIndex]; - - // - // get node bounding box and create collision planes - // - Vector bounds[2]; - pNode->GetBounds( bounds[0], bounds[1] ); - CreatePlanesFromBounds( pTemp, bounds[0], bounds[1] ); - - bool bIntersect = RayAABBTest( pTemp, rayStart, rayEnd ); - if( bIntersect ) - { - // done -- add triangles to triangle list - if( pNode->IsLeaf() ) - { - // Assert for now -- flush cache later!!!!! - Assert( pTemp->m_TriListCount >= 0 ); - Assert( pTemp->m_TriListCount < TRILIST_CACHE_SIZE ); - - pTemp->m_ppTriList[pTemp->m_TriListCount] = &pNode->m_Tris[0]; - pTemp->m_ppTriList[pTemp->m_TriListCount+1] = &pNode->m_Tris[1]; - pTemp->m_TriListCount += 2; - } - // continue recursion - else - { - for( int i = 0; i < 4; i++ ) - { - RayNodeTest_r( pTemp, GetChildNode( nodeIndex, i ), rayStart, rayEnd ); - } - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDispCollTree::RayTestAllTris( CDispCollData *pData, int power ) -{ - // - // get leaf indices - // - int startIndex = CalcNodeCount( power - 1 ); - int endIndex = CalcNodeCount( power ); - - // save incoming fraction - float startFraction = pData->m_Fraction; - float fraction = pData->m_Fraction; - - Vector ray = pData->m_EndPos - pData->m_StartPos; - Vector rayDir = ray; - float rayLength = VectorNormalize(rayDir); - - // - // test ray against all triangles in list - // - for( int index = startIndex; index < endIndex; index++ ) - { - for( int j = 0; j < 2; j++ ) - { - bool bResult = RayTriTest( pData->m_StartPos, rayDir, rayLength, &m_pNodes[index].m_Tris[j], &fraction ); - if( !bResult ) - continue; - - if( pData->m_bOcclude ) - { - return true; - } - - if( fraction < pData->m_Fraction ) - { - pData->m_Fraction = fraction; - pData->m_Normal = m_pNodes[index].m_Tris[j].m_Normal; - pData->m_Distance = m_pNodes[index].m_Tris[j].m_Distance; - } - } - } - - // collision! - if( pData->m_Fraction < startFraction ) - return true; - - // no collision! - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDispCollTree::RayTest( CDispCollData *pData ) -{ - // reset the triangle list count - CDispCollTreeTempData tmp; - tmp.m_TriListCount = 0; - - // trace against nodes (copy start, end because they change) - RayNodeTest_r( &tmp, 0, pData->m_StartPos, pData->m_EndPos ); - - // - // trace against tris (if need be) - // - if( tmp.m_TriListCount != 0 ) - { - bool result = RayTriListTest( &tmp, pData ); - return result; - } - - return false; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDispCollTree::SweptAABBTriIntersect( Vector &rayStart, Vector &rayEnd, Vector &extents, - CDispCollTri const *pTri, Vector &plNormal, float *plDist, - float *fraction ) -{ - - // - // PUT A COPY HERE OF START AND END -- SINCE I CHANGE THEM!!!!!! - // - - - - - - int dir, ptIndex; - float closeValue; - float distStart, distEnd; - float t; - Vector rayPt; - - // get ray direction - Vector rayDir = rayEnd - rayStart; - - // initialize fraction - *fraction = 1.0f; - - // - // test for collision with axial planes (x, y, z) - // - for( dir = 0; dir < 3; dir++ ) - { - if( rayDir[dir] < 0.0f ) - { - closeValue = -99999.9f; - for( ptIndex = 0; ptIndex < 3; ptIndex++ ) - { - if( pTri->m_Points[ptIndex][dir] > closeValue ) - { - closeValue = pTri->m_Points[ptIndex][dir]; - } - } - - closeValue += extents[dir]; - - distStart = rayStart[dir] - closeValue; - distEnd = rayEnd[dir] - closeValue; - } - else - { - closeValue = 99999.9f; - for( ptIndex = 0; ptIndex < 3; ptIndex++ ) - { - if( pTri->m_Points[ptIndex][dir] < closeValue ) - { - closeValue = pTri->m_Points[ptIndex][dir]; - } - } - - closeValue -= extents[dir]; - - distStart = -( rayStart[dir] - closeValue ); - distEnd = -( rayEnd[dir] - closeValue ); - } - - if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) ) - { - t = ( distStart - COLLISION_EPSILON ) / ( distStart - distEnd ); - if( t > *fraction ) - { - VectorScale( rayDir, t, rayPt ); - VectorAdd( rayStart, rayPt, rayStart ); - *fraction = t; - plNormal.Init(); - plNormal[dir] = 1.0f; - *plDist = closeValue; - } - } - else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - t = ( distStart + COLLISION_EPSILON ) / ( distStart - distEnd ); - VectorScale( rayDir, t, rayPt ); - VectorAdd( rayStart, rayPt, rayEnd ); - } - else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - return false; - } - } - - // - // check for an early out - // - if( ( pTri->m_Normal[0] > ONE_MINUS_COLLISION_EPSILON ) || - ( pTri->m_Normal[1] > ONE_MINUS_COLLISION_EPSILON ) || - ( pTri->m_Normal[2] > ONE_MINUS_COLLISION_EPSILON ) ) - { - if( *fraction == 1.0f ) - return false; - - return true; - } - - // - // handle 9 edge tests - // - Vector normal; - Vector edge; - float dist; - - // find the closest box point - Vector boxPt( 0.0f, 0.0f, 0.0f ); - for( dir = 0; dir < 3; dir++ ) - { - if( rayDir[dir] < 0.0f ) - { - boxPt[dir] = extents[dir]; - } - else - { - boxPt[dir] = -extents[dir]; - } - } - - // - // edge 0 - // - edge = pTri->m_Points[1] - pTri->m_Points[0]; - - // cross x-edge - normal.x = 0.0f; - normal.y = -edge.z; - normal.z = edge.y; - - // extents adjusted dist - dist = ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) ); - - // find distances from plane (start, end) - distStart = ( normal.y * rayStart.y ) + ( normal.z * rayStart.z ) - dist; - distEnd = ( normal.y * rayEnd.y ) + ( normal.z * rayEnd.z ) - dist; - - if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) ) - { - t = ( distStart - COLLISION_EPSILON ) / ( distStart - distEnd ); - if( t > *fraction ) - { - VectorScale( rayDir, t, rayPt ); - VectorAdd( rayStart, rayPt, rayStart ); - *fraction = t; - plNormal = normal; - *plDist = dist; - } - } - else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - t = ( distStart + COLLISION_EPSILON ) / ( distStart - distEnd ); - VectorScale( rayDir, t, rayPt ); - VectorAdd( rayStart, rayPt, rayEnd ); - } - else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - return false; - } - - // cross y-edge - normal.x = edge.z; - normal.y = 0.0f; - normal.z = edge.y; - - // extents adjusted dist - dist = ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) ); - - // find distances from plane (start, end) - distStart = ( normal.x * rayStart.x ) + ( normal.z * rayStart.z ) - dist; - distEnd = ( normal.x * rayEnd.x ) + ( normal.z * rayEnd.z ) - dist; - - if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) ) - { - t = ( distStart - COLLISION_EPSILON ) / ( distStart - distEnd ); - if( t > *fraction ) - { - VectorScale( rayDir, t, rayPt ); - VectorAdd( rayStart, rayPt, rayStart ); - *fraction = t; - plNormal = normal; - *plDist = dist; - } - } - else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - t = ( distStart + COLLISION_EPSILON ) / ( distStart - distEnd ); - VectorScale( rayDir, t, rayPt ); - VectorAdd( rayStart, rayPt, rayEnd ); - } - else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - return false; - } - - // cross z-edge - normal.x = -edge.y; - normal.y = edge.x; - normal.z = 0.0f; - - // extents adjusted dist - dist = ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) ); - - // find distances from plane (start, end) - distStart = ( normal.x * rayStart.x ) + ( normal.y * rayStart.y ) - dist; - distEnd = ( normal.x * rayEnd.x ) + ( normal.y * rayEnd.y ) - dist; - - if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) ) - { - t = ( distStart - COLLISION_EPSILON ) / ( distStart - distEnd ); - if( t > *fraction ) - { - VectorScale( rayDir, t, rayPt ); - VectorAdd( rayStart, rayPt, rayStart ); - *fraction = t; - plNormal = normal; - *plDist = dist; - } - } - else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - t = ( distStart + COLLISION_EPSILON ) / ( distStart - distEnd ); - VectorScale( rayDir, t, rayPt ); - VectorAdd( rayStart, rayPt, rayEnd ); - } - else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - return false; - } - - // - // edge 1 - // - edge = pTri->m_Points[2] - pTri->m_Points[1]; - - // cross x-edge - normal.x = 0.0f; - normal.y = -edge.z; - normal.z = edge.y; - - // extents adjusted dist - dist = ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) ); - - // find distances from plane (start, end) - distStart = ( normal.y * rayStart.y ) + ( normal.z * rayStart.z ) - dist; - distEnd = ( normal.y * rayEnd.y ) + ( normal.z * rayEnd.z ) - dist; - - if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) ) - { - t = ( distStart - COLLISION_EPSILON ) / ( distStart - distEnd ); - if( t > *fraction ) - { - VectorScale( rayDir, t, rayPt ); - VectorAdd( rayStart, rayPt, rayStart ); - *fraction = t; - plNormal = normal; - *plDist = dist; - } - } - else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - t = ( distStart + COLLISION_EPSILON ) / ( distStart - distEnd ); - VectorScale( rayDir, t, rayPt ); - VectorAdd( rayStart, rayPt, rayEnd ); - } - else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - return false; - } - - // cross y-edge - normal.x = edge.z; - normal.y = 0.0f; - normal.z = edge.y; - - // extents adjusted dist - dist = ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) ); - - // find distances from plane (start, end) - distStart = ( normal.x * rayStart.x ) + ( normal.z * rayStart.z ) - dist; - distEnd = ( normal.x * rayEnd.x ) + ( normal.z * rayEnd.z ) - dist; - - if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) ) - { - t = ( distStart - COLLISION_EPSILON ) / ( distStart - distEnd ); - if( t > *fraction ) - { - VectorScale( rayDir, t, rayPt ); - VectorAdd( rayStart, rayPt, rayStart ); - *fraction = t; - plNormal = normal; - *plDist = dist; - } - } - else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - t = ( distStart + COLLISION_EPSILON ) / ( distStart - distEnd ); - VectorScale( rayDir, t, rayPt ); - VectorAdd( rayStart, rayPt, rayEnd ); - } - else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - return false; - } - - // cross z-edge - normal.x = -edge.y; - normal.y = edge.x; - normal.z = 0.0f; - - // extents adjusted dist - dist = ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) ); - - // find distances from plane (start, end) - distStart = ( normal.x * rayStart.x ) + ( normal.y * rayStart.y ) - dist; - distEnd = ( normal.x * rayEnd.x ) + ( normal.y * rayEnd.y ) - dist; - - if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) ) - { - t = ( distStart - COLLISION_EPSILON ) / ( distStart - distEnd ); - if( t > *fraction ) - { - VectorScale( rayDir, t, rayPt ); - VectorAdd( rayStart, rayPt, rayStart ); - *fraction = t; - plNormal = normal; - *plDist = dist; - } - } - else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - t = ( distStart + COLLISION_EPSILON ) / ( distStart - distEnd ); - VectorScale( rayDir, t, rayPt ); - VectorAdd( rayStart, rayPt, rayEnd ); - } - else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - return false; - } - - // - // edge 2 - // - edge = pTri->m_Points[0] - pTri->m_Points[2]; - - // cross x-edge - normal.x = 0.0f; - normal.y = -edge.z; - normal.z = edge.y; - - // extents adjusted dist - dist = ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) ); - - // find distances from plane (start, end) - distStart = ( normal.y * rayStart.y ) + ( normal.z * rayStart.z ) - dist; - distEnd = ( normal.y * rayEnd.y ) + ( normal.z * rayEnd.z ) - dist; - - if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) ) - { - t = ( distStart - COLLISION_EPSILON ) / ( distStart - distEnd ); - if( t > *fraction ) - { - VectorScale( rayDir, t, rayPt ); - VectorAdd( rayStart, rayPt, rayStart ); - *fraction = t; - plNormal = normal; - *plDist = dist; - } - } - else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - t = ( distStart + COLLISION_EPSILON ) / ( distStart - distEnd ); - VectorScale( rayDir, t, rayPt ); - VectorAdd( rayStart, rayPt, rayEnd ); - } - else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - return false; - } - - // cross y-edge - normal.x = edge.z; - normal.y = 0.0f; - normal.z = edge.y; - - // extents adjusted dist - dist = ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) ); - - // find distances from plane (start, end) - distStart = ( normal.x * rayStart.x ) + ( normal.z * rayStart.z ) - dist; - distEnd = ( normal.x * rayEnd.x ) + ( normal.z * rayEnd.z ) - dist; - - if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) ) - { - t = ( distStart - COLLISION_EPSILON ) / ( distStart - distEnd ); - if( t > *fraction ) - { - VectorScale( rayDir, t, rayPt ); - VectorAdd( rayStart, rayPt, rayStart ); - *fraction = t; - plNormal = normal; - *plDist = dist; - } - } - else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - t = ( distStart + COLLISION_EPSILON ) / ( distStart - distEnd ); - VectorScale( rayDir, t, rayPt ); - VectorAdd( rayStart, rayPt, rayEnd ); - } - else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - return false; - } - - // cross z-edge - normal.x = -edge.y; - normal.y = edge.x; - normal.z = 0.0f; - - // extents adjusted dist - dist = ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) ); - - // find distances from plane (start, end) - distStart = ( normal.x * rayStart.x ) + ( normal.y * rayStart.y ) - dist; - distEnd = ( normal.x * rayEnd.x ) + ( normal.y * rayEnd.y ) - dist; - - if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) ) - { - t = ( distStart - COLLISION_EPSILON ) / ( distStart - distEnd ); - if( t > *fraction ) - { - VectorScale( rayDir, t, rayPt ); - VectorAdd( rayStart, rayPt, rayStart ); - *fraction = t; - plNormal = normal; - *plDist = dist; - } - } - else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - t = ( distStart + COLLISION_EPSILON ) / ( distStart - distEnd ); - VectorScale( rayDir, t, rayPt ); - VectorAdd( rayStart, rayPt, rayEnd ); - } - else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - return false; - } - - // - // test face plane - // - dist = ( pTri->m_Normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + - ( pTri->m_Normal.y * ( boxPt.y - pTri->m_Points[0].y ) ) + - ( pTri->m_Normal.z * ( boxPt.z - pTri->m_Points[0].z ) ); - - distStart = pTri->m_Normal.Dot( rayStart ) - dist; - distEnd = pTri->m_Normal.Dot( rayEnd ) - dist; - - if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) ) - { - t = ( distStart - COLLISION_EPSILON ) / ( distStart - distEnd ); - if( t > *fraction ) - { - VectorScale( rayDir, t, rayPt ); - VectorAdd( rayStart, rayPt, rayStart ); - *fraction = t; - plNormal = normal; - *plDist = dist; - } - } - else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - t = ( distStart + COLLISION_EPSILON ) / ( distStart - distEnd ); - VectorScale( rayDir, t, rayPt ); - VectorAdd( rayStart, rayPt, rayEnd ); - } - else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - return false; - } - - if( *fraction == 1.0f ) - return false; - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDispCollTree::AABBTriIntersect( CDispCollTreeTempData *pTemp, CDispCollData *pData ) -{ - bool bResult = false; - - Vector normal; - float fraction, dist; - - // - // sweep ABB against all triangles in list - // - for( int i = 0; i < pTemp->m_TriListCount; i++ ) - { - if( pTemp->m_ppTriList[i]->IsIntersect() ) - { - bResult = SweptAABBTriIntersect( pData->m_StartPos, pData->m_EndPos, pData->m_Extents, - pTemp->m_ppTriList[i], normal, &dist, &fraction ); - if( bResult ) - { - if( fraction < pData->m_Fraction ) - { - pData->m_Fraction = fraction; - pData->m_Normal = normal; - pData->m_Distance = dist; - } - } - } - } - - return bResult; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDispCollTree::IntersectAABBTriTest( Vector &rayStart, Vector &extents, - CDispCollTri const *pTri ) -{ - int dir, ptIndex; - float dist; - - // - // test axail planes (x, y, z) - // - - for( dir = 0; dir < 3; dir++ ) - { - // - // negative axial plane, component = dir - // - dist = rayStart[dir] - extents[dir]; - for( ptIndex = 0; ptIndex < 3; ptIndex++ ) - { - if( pTri->m_Points[ptIndex][dir] > dist ) - break; - } - - if( ptIndex == 3 ) - return false; - - // - // positive axial plane, component = dir - // - dist = rayStart[dir] + extents[dir]; - for( ptIndex = 0; ptIndex < 3; ptIndex++ ) - { - if( pTri->m_Points[ptIndex][dir] < dist ) - break; - } - - if( ptIndex == 3 ) - return false; - } - - // - // add a test here to see if triangle face normal is close to axial -- done if so!!! - // - if( ( pTri->m_Normal[0] > ONE_MINUS_COLLISION_EPSILON ) || - ( pTri->m_Normal[1] > ONE_MINUS_COLLISION_EPSILON ) || - ( pTri->m_Normal[2] > ONE_MINUS_COLLISION_EPSILON ) ) - return true; - - // find the closest point on the box (use negated tri face noraml) - Vector boxPt( 0.0f, 0.0f, 0.0f ); - for( dir = 0; dir < 3; dir++ ) - { - if( pTri->m_Normal[dir] < 0.0f ) - { - boxPt[dir] = extents[dir]; - } - else - { - boxPt[dir] = -extents[dir]; - } - } - - // - // triangle plane test - // - // do the opposite because the ray has been negated - if( ( ( pTri->m_Normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + - ( pTri->m_Normal.y * ( boxPt.y - pTri->m_Points[0].y ) ) + - ( pTri->m_Normal.z * ( boxPt.z - pTri->m_Points[0].z ) ) ) > 0.0f ) - return false; - - // - // test edge planes - 9 of them - // - Vector normal; - Vector edge; - - // - // edge 0 - // - edge = pTri->m_Points[1] - pTri->m_Points[0]; - - // cross x - normal.x = 0.0f; - normal.y = -edge.z; - normal.z = edge.y; - if( ( ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) ) ) > 0.0f ) - return false; - - // cross y - normal.x = edge.z; - normal.y = 0.0f; - normal.z = edge.y; - if( ( ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) ) ) > 0.0f ) - return false; - - // cross z - normal.x = -edge.y; - normal.y = edge.x; - normal.z = 0.0f; - if( ( ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) ) ) > 0.0f ) - return false; - - // - // edge 1 - // - edge = pTri->m_Points[2] - pTri->m_Points[1]; - - // cross x - normal.x = 0.0f; - normal.y = -edge.z; - normal.z = edge.y; - if( ( ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) ) ) > 0.0f ) - return false; - - // cross y - normal.x = edge.z; - normal.y = 0.0f; - normal.z = edge.y; - if( ( ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) ) ) > 0.0f ) - return false; - - // cross z - normal.x = -edge.y; - normal.y = edge.x; - normal.z = 0.0f; - if( ( ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) ) ) > 0.0f ) - return false; - - // - // edge 2 - // - edge = pTri->m_Points[0] - pTri->m_Points[2]; - - // cross x - normal.x = 0.0f; - normal.y = -edge.z; - normal.z = edge.y; - if( ( ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) ) ) > 0.0f ) - return false; - - // cross y - normal.x = edge.z; - normal.y = 0.0f; - normal.z = edge.y; - if( ( ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.z * ( boxPt.z - pTri->m_Points[0].z ) ) ) > 0.0f ) - return false; - - // cross z - normal.x = -edge.y; - normal.y = edge.x; - normal.z = 0.0f; - if( ( ( normal.x * ( boxPt.x - pTri->m_Points[0].x ) ) + ( normal.y * ( boxPt.y - pTri->m_Points[0].y ) ) ) > 0.0f ) - return false; - - return true; -} - - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDispCollTree::SweptAABBTriTest( Vector &rayStart, Vector &rayEnd, Vector &extents, - CDispCollTri const *pTri ) -{ - // get ray direction - Vector rayDir = rayEnd - rayStart; - - // - // quick and dirty test -- test to see if the object is traveling away from triangle surface??? - // - if( pTri->m_Normal.Dot( rayDir ) > 0.0f ) - return false; - - // - // calc the swept triangle face (negate the ray -- opposite direction of box travel) - // - rayDir.Negate(); - - Vector points[3]; - points[0] = pTri->m_Points[0] + rayDir; - points[1] = pTri->m_Points[1] + rayDir; - points[2] = pTri->m_Points[2] + rayDir; - - // - // handle 4 faces tests (3 axial planes and triangle face) - // - int dir; - float dist; - - // - // axial planes tests (x, y, z) - // - for( dir = 0; dir < 3; dir++ ) - { - bool bOutside = true; - - if( rayDir[dir] < 0.0f ) - { - dist = rayStart[dir] - extents[dir]; - for( int ptIndex = 0; ptIndex < 3; ptIndex ) - { - if( points[ptIndex][dir] > dist ) - { - bOutside = false; - break; - } - } - } - else - { - dist = rayStart[dir] + extents[dir]; - for( int ptIndex = 0; ptIndex < 3; ptIndex ) - { - if( pTri->m_Points[ptIndex][dir] < dist ) - { - bOutside = false; - break; - } - } - } - - if( bOutside ) - return false; - } - - // - // add a test here to see if triangle face normal is close to axial -- done if so!!! - // - if( ( pTri->m_Normal[0] > ONE_MINUS_COLLISION_EPSILON ) || - ( pTri->m_Normal[1] > ONE_MINUS_COLLISION_EPSILON ) || - ( pTri->m_Normal[2] > ONE_MINUS_COLLISION_EPSILON ) ) - return true; - - // - // handle 9 edge tests - always use the newly swept face for this - // - Vector normal; - Vector edge; - - // find the closest box point - (is written opposite to normal due to negating ray) - Vector boxPt( 0.0f, 0.0f, 0.0f ); - for( dir = 0; dir < 3; dir++ ) - { - if( rayDir[dir] < 0.0f ) - { - boxPt[dir] = rayStart[dir] - extents[dir]; - } - else - { - boxPt[dir] = rayStart[dir] + extents[dir]; - } - } - - // - // edge 0 - // - edge = points[1] - points[0]; - - // cross x-edge - normal.x = 0.0f; - normal.y = -edge.z; - normal.z = edge.y; - if( ( ( normal.y * ( boxPt.y - points[0].y ) ) + ( normal.z * ( boxPt.z - points[0].z ) ) ) > 0.0f ) - return false; - - // cross, y-edge - normal.x = edge.z; - normal.y = 0.0f; - normal.z = edge.y; - if( ( ( normal.x * ( boxPt.x - points[0].x ) ) + ( normal.z * ( boxPt.z - points[0].z ) ) ) > 0.0f ) - return false; - - // cross z-edge - normal.x = -edge.y; - normal.y = edge.x; - normal.z = 0.0f; - if( ( ( normal.x * ( boxPt.x - points[0].x ) ) + ( normal.y * ( boxPt.y - points[0].y ) ) ) > 0.0f ) - return false; - - // - // edge 1 - // - edge = points[2] - points[1]; - - // cross x-edge - normal.x = 0.0f; - normal.y = -edge.z; - normal.z = edge.y; - if( ( ( normal.y * ( boxPt.y - points[0].y ) ) + ( normal.z * ( boxPt.z - points[0].z ) ) ) > 0.0f ) - return false; - - // cross, y-edge - normal.x = edge.z; - normal.y = 0.0f; - normal.z = edge.y; - if( ( ( normal.x * ( boxPt.x - points[0].x ) ) + ( normal.z * ( boxPt.z - points[0].z ) ) ) > 0.0f ) - return false; - - // cross z-edge - normal.x = -edge.y; - normal.y = edge.x; - normal.z = 0.0f; - if( ( ( normal.x * ( boxPt.x - points[0].x ) ) + ( normal.y * ( boxPt.y - points[0].y ) ) ) > 0.0f ) - return false; - - // - // edge 2 - // - edge = points[0] - points[2]; - - // cross x-edge - normal.x = 0.0f; - normal.y = -edge.z; - normal.z = edge.y; - if( ( ( normal.y * ( boxPt.y - points[0].y ) ) + ( normal.z * ( boxPt.z - points[0].z ) ) ) > 0.0f ) - return false; - - // cross, y-edge - normal.x = edge.z; - normal.y = 0.0f; - normal.z = edge.y; - if( ( ( normal.x * ( boxPt.x - points[0].x ) ) + ( normal.z * ( boxPt.z - points[0].z ) ) ) > 0.0f ) - return false; - - // cross z-edge - normal.x = -edge.y; - normal.y = edge.x; - normal.z = 0.0f; - if( ( ( normal.x * ( boxPt.x - points[0].x ) ) + ( normal.y * ( boxPt.y - points[0].y ) ) ) > 0.0f ) - return false; - - // - // triangle plane test - // - // do the opposite because the ray has been negated - if( ( ( pTri->m_Normal.x * ( boxPt.x - points[0].x ) ) + - ( pTri->m_Normal.y * ( boxPt.y - points[0].y ) ) + - ( pTri->m_Normal.z * ( boxPt.z - points[0].z ) ) ) > 0.0f ) - return false; - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDispCollTree::CullTriList( CDispCollTreeTempData *pTemp, Vector &rayStart, Vector &rayEnd, Vector &extents, bool bIntersect ) -{ - // - // intersect AABB with all triangles in list - // - if( bIntersect ) - { - for( int i = 0; i < pTemp->m_TriListCount; i++ ) - { - if( IntersectAABBTriTest( rayStart, extents, pTemp->m_ppTriList[i] ) ) - return true; - } - - return false; - } - // - // sweep AABB against all triangles in list - // - else - { - bool bResult = false; - - for( int i = 0; i < pTemp->m_TriListCount; i++ ) - { - if( SweptAABBTriTest( rayStart, rayEnd, extents, pTemp->m_ppTriList[i] ) ) - { - pTemp->m_ppTriList[i]->SetIntersect( true ); - bResult = true; - } - } - - return bResult; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDispCollTree::IntersectAABBAABBTest( CDispCollTreeTempData *pTemp, const Vector &pos, const Vector &extents ) -{ - float dist; - - for( int dir = 0; dir < 3; dir++ ) - { - // negative direction - dist = -( pos[dir] - ( pTemp->m_AABBDistances[(dir>>1)] - extents[dir] ) ); - if( dist > COLLISION_EPSILON ) - return false; - - // positive direction - dist = pos[dir] - ( pTemp->m_AABBDistances[(dir>>1)+1] + extents[dir] ); - if( dist > COLLISION_EPSILON ) - return false; - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDispCollTree::SweptAABBAABBTest( CDispCollTreeTempData *pTemp, const Vector &rayStart, const Vector &rayEnd, const Vector &extents ) -{ - int dir; - float distStart, distEnd; - float fraction; - float deltas[3]; - float scalers[3]; - - // - // enter and exit fractions - // - float enterFraction = 0.0f; - float exitFraction = 0.0f; - - // - // de-normalize the paramter space so that we don't have to divide - // to find the fractional amount later (clamped for precision) - // - deltas[0] = rayEnd.x - rayStart.x; - deltas[1] = rayEnd.y - rayStart.y; - deltas[2] = rayEnd.z - rayStart.z; - if( ( deltas[0] < COLLISION_EPSILON ) && ( deltas[0] > -COLLISION_EPSILON ) ) { deltas[0] = 1.0f; } - if( ( deltas[1] < COLLISION_EPSILON ) && ( deltas[1] > -COLLISION_EPSILON ) ) { deltas[0] = 1.0f; } - if( ( deltas[2] < COLLISION_EPSILON ) && ( deltas[2] > -COLLISION_EPSILON ) ) { deltas[0] = 1.0f; } - scalers[0] = deltas[1] * deltas[2]; - scalers[1] = deltas[0] * deltas[2]; - scalers[2] = deltas[0] * deltas[1]; - - for( dir = 0; dir < 3; dir++ ) - { - // - // negative direction - // - distStart = -( rayStart[dir] - ( pTemp->m_AABBDistances[(dir>>1)] - extents[dir] ) ); - distEnd = -( rayEnd[dir] - ( pTemp->m_AABBDistances[(dir>>1)] - extents[dir] ) ); - - if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) ) - { - fraction = distStart * scalers[dir]; - if( fraction > enterFraction ) - { - enterFraction = fraction; - } - } - else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - fraction = distStart * scalers[dir]; - if( fraction < exitFraction ) - { - exitFraction = fraction; - } - } - else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - return false; - } - - // - // positive direction - // - distStart = rayStart[dir] - ( pTemp->m_AABBDistances[(dir>>1)+1] + extents[dir] ); - distEnd = rayEnd[dir] - ( pTemp->m_AABBDistances[(dir>>1)+1] + extents[dir] ); - - if( ( distStart > COLLISION_EPSILON ) && ( distEnd < -COLLISION_EPSILON ) ) - { - fraction = distStart * scalers[dir]; - if( fraction > enterFraction ) - { - enterFraction = fraction; - } - } - else if( ( distStart < -COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - fraction = distStart * scalers[dir]; - if( fraction < exitFraction ) - { - exitFraction = fraction; - } - } - else if( ( distStart > COLLISION_EPSILON ) && ( distEnd > COLLISION_EPSILON ) ) - { - return false; - } - } - - if( exitFraction < enterFraction ) - return false; - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDispCollTree::BuildTriList_r( CDispCollTreeTempData *pTemp, int nodeIndex, Vector &rayStart, Vector &rayEnd, Vector &extents, - bool bIntersect ) -{ - // - // get the current nodes bounds and create collision test planes - // (saved in the in class cache m_AABBNormals, m_AABBDistances) - // - Vector bounds[2]; - CDispCollNode *pNode = &m_pNodes[nodeIndex]; - pNode->GetBounds( bounds[0], bounds[1] ); - CreatePlanesFromBounds( pTemp, bounds[0], bounds[1] ); - - // - // interesect/sweep test - // - bool bResult; - if( bIntersect ) - { - bResult = IntersectAABBAABBTest( pTemp, rayStart, extents ); - } - else - { - bResult = SweptAABBAABBTest( pTemp, rayStart, rayEnd, extents ); - } - - if( bResult ) - { - // if leaf node -- add triangles to interstection test list - if( pNode->IsLeaf() ) - { - // Assert for now -- flush cache later!!!!! - Assert( pTemp->m_TriListCount >= 0 ); - Assert( pTemp->m_TriListCount < TRILIST_CACHE_SIZE ); - - pTemp->m_ppTriList[pTemp->m_TriListCount] = &pNode->m_Tris[0]; - pTemp->m_ppTriList[pTemp->m_TriListCount+1] = &pNode->m_Tris[1]; - pTemp->m_TriListCount += 2; - } - // continue recursion - else - { - BuildTriList_r( pTemp, GetChildNode( nodeIndex, 0 ), rayStart, rayEnd, extents, bIntersect ); - BuildTriList_r( pTemp, GetChildNode( nodeIndex, 1 ), rayStart, rayEnd, extents, bIntersect ); - BuildTriList_r( pTemp, GetChildNode( nodeIndex, 2 ), rayStart, rayEnd, extents, bIntersect ); - BuildTriList_r( pTemp, GetChildNode( nodeIndex, 3 ), rayStart, rayEnd, extents, bIntersect ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDispCollTree::AABBSweep( CDispCollData *pData ) -{ - // reset the triangle lists counts - CDispCollTreeTempData tmp; - tmp.m_TriListCount = 0; - - // sweep the AABB against the tree - BuildTriList_r( &tmp, 0, pData->m_StartPos, pData->m_EndPos, pData->m_Extents, false ); - - // find collision triangles - if( CullTriList( &tmp, pData->m_StartPos, pData->m_EndPos, pData->m_Extents, false ) ) - { - // find closest intersection - return AABBTriIntersect( &tmp, pData ); - } - - return false; -} - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDispCollTree::AABBIntersect( CDispCollData *pData ) -{ - // reset the triangle lists counts - CDispCollTreeTempData tmp; - tmp.m_TriListCount = 0; - - // sweep the AABB against the tree - BuildTriList_r( &tmp, 0, pData->m_StartPos, pData->m_StartPos, pData->m_Extents, true ); - - // find collision triangles - return CullTriList( &tmp, pData->m_StartPos, pData->m_StartPos, pData->m_Extents, true ); -} diff --git a/public/dispcoll.h b/public/dispcoll.h deleted file mode 100644 index 6df17242e..000000000 --- a/public/dispcoll.h +++ /dev/null @@ -1,249 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef DISPCOLL_H -#define DISPCOLL_H -#pragma once - -#include "mathlib/vector.h" - -class CCoreDispInfo; - -//============================================================================= -// -// Displacement Collision Triangle Data -// -class CDispCollTri -{ -public: - - void Init( void ); - inline void SetPoint( int index, Vector const& vert ); - inline void SetPointNormal( int index, Vector const& normal ); - void CalcPlane( void ); - - inline void SetIntersect( bool bIntersect ); - inline bool IsIntersect( void ); - - Vector m_Points[3]; // polygon points - Vector m_PointNormals[3]; // polygon point normals - Vector m_Normal; // plane normal - float m_Distance; // plane distance - short m_ProjAxes[2]; // projection axes (2 minor axes) - bool m_bIntersect; // intersected triangle??? -}; - -//============================================================================= -// -// Displacement Collision Node Data -// -class CDispCollNode -{ -public: - - CDispCollNode(); - inline bool IsLeaf( void ); - inline void SetBounds( Vector const &bMin, Vector const &bMax ); - inline void GetBounds( Vector &bMin, Vector &bMax ); - - Vector m_Bounds[2]; // node minimum and maximum - - bool m_bIsLeaf; // is the node a leaf? ( may have to make this an int for alignment!) - CDispCollTri m_Tris[2]; // two triangles contained in leaf node -}; - - -//============================================================================= -// -// Displacement Collision Data -// -class CDispCollData -{ -public: - - Vector m_StartPos; - Vector m_EndPos; - Vector m_Extents; - float m_Fraction; - int m_Contents; - Vector m_Normal; - float m_Distance; - bool m_bOcclude; -}; - - - -// HACKHACK: JAY: Moved this out of CDispCollTree to be thread safe in vrad -enum { TRILIST_CACHE_SIZE = 128 }; - -class CDispCollTreeTempData -{ -public: - // - // temps - // - int m_TriListCount; - CDispCollTri *m_ppTriList[TRILIST_CACHE_SIZE]; - - // collision tree node cache - float m_AABBDistances[6]; -}; - - -//============================================================================= -// -// Displacement Collision Tree -// -class CDispCollTree -{ -public: - - static const float COLLISION_EPSILON; - static const float ONE_MINUS_COLLISION_EPSILON; - - //========================================================================= - // - // Creation/Destruction - // - CDispCollTree(); - ~CDispCollTree(); - - virtual bool Create( CCoreDispInfo *pDisp ); - - //========================================================================= - // - // Collision Functions - // - bool RayTest( CDispCollData *pData ); - bool RayTestAllTris( CDispCollData *pData, int power ); - - bool AABBIntersect( CDispCollData *pData ); - bool AABBSweep( CDispCollData *pData ); - - //========================================================================= - // - // Attrib Functions - // - inline void SetPower( int power ); - inline int GetPower( void ); - - inline void SetCheckCount( int count ); - inline int GetCheckCount( void ); - - inline void GetBounds( Vector& boundMin, Vector& boundMax ); - -protected: - - int m_Power; - - int m_NodeCount; - CDispCollNode *m_pNodes; - - int m_CheckCount; - - // collision tree node cache - Vector m_AABBNormals[6]; - //========================================================================= - // - // Creation/Destruction - // - void InitAABBData( void ); - void InitLeaves( CCoreDispInfo *pDisp ); - void CreateNodes( CCoreDispInfo *pDisp ); - void CreateNodes_r( CCoreDispInfo *pDisp, int nodeIndex, int termLevel ); - void CalcBounds( CDispCollNode *pNode, int nodeIndex ); - - //========================================================================= - // - // Collision Functions - // - void CreatePlanesFromBounds( CDispCollTreeTempData *pTemp, Vector const &bbMin, Vector const &bbMax ); - -// void RayNodeTest_r( int nodeIndex, Vector &rayStart, Vector &rayEnd ); - void RayNodeTest_r( CDispCollTreeTempData *pTemp, int nodeIndex, Vector rayStart, Vector rayEnd ); - bool RayAABBTest( CDispCollTreeTempData *pTemp, Vector &rayStart, Vector &rayEnd ); - bool RayTriListTest( CDispCollTreeTempData *pTemp, CDispCollData *pData ); - bool RayTriTest( Vector const &rayStart, Vector const &rayDir, float const rayLength, CDispCollTri const *pTri, float *fraction ); - - void BuildTriList_r( CDispCollTreeTempData *pTemp, int nodeIndex, Vector &rayStart, Vector &rayEnd, Vector &extents, bool bIntersect ); - bool IntersectAABBAABBTest( CDispCollTreeTempData *pTemp, const Vector &pos, const Vector &extents ); - bool SweptAABBAABBTest( CDispCollTreeTempData *pTemp, const Vector &rayStart, const Vector &rayEnd, const Vector &extents ); - - bool CullTriList( CDispCollTreeTempData *pTemp, Vector &rayStart, Vector &rayEnd, Vector &extents, bool bIntersect ); - bool SweptAABBTriTest( Vector &rayStart, Vector &rayEnd, Vector &extents, CDispCollTri const *pTri ); - bool AABBTriIntersect( CDispCollTreeTempData *pTemp, CDispCollData *pData ); - bool IntersectAABBTriTest( Vector &rayStart, Vector &extents, CDispCollTri const *pTri ); - bool SweptAABBTriIntersect( Vector &rayStart, Vector &rayEnd, Vector &extents, - CDispCollTri const *pTri, Vector &plNormal, float *plDist, - float *fraction ); - - //========================================================================= - // - // Memory Functions - // - bool AllocNodes( int nodeCount ); - void FreeNodes( void ); - - //========================================================================= - // - // Utility Functions - // - inline int CalcNodeCount( int power ); - inline int GetParentNode( int nodeIndex ); - inline int GetChildNode( int nodeIndex, int direction ); - inline int GetNodeLevel( int nodeIndex ); - int GetNodeIndexFromComponents( int x, int y ); -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CDispCollTree::SetPower( int power ) -{ - m_Power = power; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline int CDispCollTree::GetPower( void ) -{ - return m_Power; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CDispCollTree::SetCheckCount( int count ) -{ - m_CheckCount = count; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline int CDispCollTree::GetCheckCount( void ) -{ - return m_CheckCount; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void CDispCollTree::GetBounds( Vector& boundMin, Vector& boundMax ) -{ - boundMin[0] = m_pNodes[0].m_Bounds[0].x; - boundMin[1] = m_pNodes[0].m_Bounds[0].y; - boundMin[2] = m_pNodes[0].m_Bounds[0].z; - - boundMax[0] = m_pNodes[0].m_Bounds[1].x; - boundMax[1] = m_pNodes[0].m_Bounds[1].y; - boundMax[2] = m_pNodes[0].m_Bounds[1].z; -} - - -#endif // DISPCOLL_H diff --git a/public/dispcoll_common.cpp b/public/dispcoll_common.cpp deleted file mode 100644 index c2f2ae2cb..000000000 --- a/public/dispcoll_common.cpp +++ /dev/null @@ -1,1539 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include "cmodel.h" -#include "dispcoll_common.h" -#include "collisionutils.h" -#include "tier1/strtools.h" -#include "tier0/vprof.h" -#include "tier1/fmtstr.h" -#include "tier1/utlhash.h" -#include "tier1/generichash.h" -#include "tier0/fasttimer.h" -#include "vphysics/virtualmesh.h" -#include "tier1/datamanager.h" -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//============================================================================= -// Cache - -#ifdef ENGINE_DLL -CDataManager g_DispCollTriCache( 2048*1024 ); -#endif - - -struct DispCollPlaneIndex_t -{ - Vector vecPlane; - int index; -}; - -class CPlaneIndexHashFuncs -{ -public: - CPlaneIndexHashFuncs( int ) {} - - // Compare - bool operator()( const DispCollPlaneIndex_t &lhs, const DispCollPlaneIndex_t &rhs ) const - { - return ( lhs.vecPlane == rhs.vecPlane || lhs.vecPlane == -rhs.vecPlane ); - } - - // Hash - unsigned int operator()( const DispCollPlaneIndex_t &item ) const - { - return HashItem( item.vecPlane ) ^ HashItem( -item.vecPlane ); - } -}; - -CUtlHash g_DispCollPlaneIndexHash( 512 ); - - -//============================================================================= -// Displacement Collision Triangle - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CDispCollTri::CDispCollTri() -{ - Init(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDispCollTri::Init( void ) -{ - m_vecNormal.Init(); - m_flDist = 0.0f; - m_TriData[0].m_IndexDummy = m_TriData[1].m_IndexDummy = m_TriData[2].m_IndexDummy = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDispCollTri::CalcPlane( CDispVector &m_aVerts ) -{ - Vector vecEdges[2]; - vecEdges[0] = m_aVerts[GetVert( 1 )] - m_aVerts[GetVert( 0 )]; - vecEdges[1] = m_aVerts[GetVert( 2 )] - m_aVerts[GetVert( 0 )]; - - m_vecNormal = vecEdges[1].Cross( vecEdges[0] ); - VectorNormalize( m_vecNormal ); - m_flDist = m_vecNormal.Dot( m_aVerts[GetVert( 0 )] ); - - // Calculate the signbits for the plane - fast test. - m_ucSignBits = 0; - m_ucPlaneType = PLANE_ANYZ; - for ( int iAxis = 0; iAxis < 3 ; ++iAxis ) - { - if ( m_vecNormal[iAxis] < 0.0f ) - { - m_ucSignBits |= 1 << iAxis; - } - - if ( m_vecNormal[iAxis] == 1.0f ) - { - m_ucPlaneType = iAxis; - } - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void FindMin( float v1, float v2, float v3, int &iMin ) -{ - float flMin = v1; - iMin = 0; - if( v2 < flMin ) { flMin = v2; iMin = 1; } - if( v3 < flMin ) { flMin = v3; iMin = 2; } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -inline void FindMax( float v1, float v2, float v3, int &iMax ) -{ - float flMax = v1; - iMax = 0; - if( v2 > flMax ) { flMax = v2; iMax = 1; } - if( v3 > flMax ) { flMax = v3; iMax = 2; } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDispCollTri::FindMinMax( CDispVector &m_aVerts ) -{ - int iMin, iMax; - FindMin( m_aVerts[GetVert(0)].x, m_aVerts[GetVert(1)].x, m_aVerts[GetVert(2)].x, iMin ); - FindMax( m_aVerts[GetVert(0)].x, m_aVerts[GetVert(1)].x, m_aVerts[GetVert(2)].x, iMax ); - SetMin( 0, iMin ); - SetMax( 0, iMax ); - - FindMin( m_aVerts[GetVert(0)].y, m_aVerts[GetVert(1)].y, m_aVerts[GetVert(2)].y, iMin ); - FindMax( m_aVerts[GetVert(0)].y, m_aVerts[GetVert(1)].y, m_aVerts[GetVert(2)].y, iMax ); - SetMin( 1, iMin ); - SetMax( 1, iMax ); - - FindMin( m_aVerts[GetVert(0)].z, m_aVerts[GetVert(1)].z, m_aVerts[GetVert(2)].z, iMin ); - FindMax( m_aVerts[GetVert(0)].z, m_aVerts[GetVert(1)].z, m_aVerts[GetVert(2)].z, iMax ); - SetMin( 2, iMin ); - SetMax( 2, iMax ); -} - - -// SIMD Routines for intersecting with the quad tree -FORCEINLINE int IntersectRayWithFourBoxes( const FourVectors &rayStart, const FourVectors &invDelta, const FourVectors &rayExtents, const FourVectors &boxMins, const FourVectors &boxMaxs ) -{ - // SIMD Test ray against all four boxes at once - // each node stores the bboxes of its four children - FourVectors hitMins = boxMins; - hitMins -= rayStart; - FourVectors hitMaxs = boxMaxs; - hitMaxs -= rayStart; - - // adjust for swept box by enlarging the child bounds to shrink the sweep down to a point - hitMins -= rayExtents; - hitMaxs += rayExtents; - - // compute the parametric distance along the ray of intersection in each dimension - hitMins *= invDelta; - hitMaxs *= invDelta; - - // Find the exit parametric intersection distance in each dimesion, for each box - FourVectors exitT = maximum(hitMins,hitMaxs); - // Find the entry parametric intersection distance in each dimesion, for each box - FourVectors entryT = minimum(hitMins,hitMaxs); - - // now find the max overall entry distance across all dimensions for each box - fltx4 minTemp = MaxSIMD(entryT.x, entryT.y); - fltx4 boxEntryT = MaxSIMD(minTemp, entryT.z); - - // now find the min overall exit distance across all dimensions for each box - fltx4 maxTemp = MinSIMD(exitT.x, exitT.y); - fltx4 boxExitT = MinSIMD(maxTemp, exitT.z); - - boxEntryT = MaxSIMD(boxEntryT,Four_Zeros); - boxExitT = MinSIMD(boxExitT,Four_Ones); - - // if entry<=exit for the box, we've got a hit - fltx4 active = CmpLeSIMD(boxEntryT,boxExitT); // mask of which boxes are active - - // hit at least one box? - return TestSignSIMD(active); -} - -// This does 4 simultaneous box intersections -// NOTE: This can be used as a 1 vs 4 test by replicating a single box into the one side -FORCEINLINE int IntersectFourBoxPairs( const FourVectors &mins0, const FourVectors &maxs0, const FourVectors &mins1, const FourVectors &maxs1 ) -{ - // find the max mins and min maxs in each dimension - FourVectors intersectMins = maximum(mins0,mins1); - FourVectors intersectMaxs = minimum(maxs0,maxs1); - - // if intersectMins <= intersectMaxs then the boxes overlap in this dimension - fltx4 overlapX = CmpLeSIMD(intersectMins.x,intersectMaxs.x); - fltx4 overlapY = CmpLeSIMD(intersectMins.y,intersectMaxs.y); - fltx4 overlapZ = CmpLeSIMD(intersectMins.z,intersectMaxs.z); - - // if the boxes overlap in all three dimensions, they intersect - fltx4 tmp = AndSIMD( overlapX, overlapY ); - fltx4 active = AndSIMD( tmp, overlapZ ); - - // hit at least one box? - return TestSignSIMD(active); -} - -// This does 4 simultaneous box vs. sphere intersections -// NOTE: This can be used as a 1 vs 4 test by replicating a single sphere/box into one side -FORCEINLINE int IntersectFourBoxSpherePairs( const FourVectors ¢er, const fltx4 &radiusSq, const FourVectors &mins, const FourVectors &maxs ) -{ - // for each dimension of each box, compute the clamped distance from the mins side to the center (must be >= 0) - FourVectors minDist = mins; - minDist -= center; - FourVectors dist; - dist.x = MaxSIMD(Four_Zeros, minDist.x); - dist.y = MaxSIMD(Four_Zeros, minDist.y); - dist.z = MaxSIMD(Four_Zeros, minDist.z); - - // now compute the distance from the maxs side to the center - FourVectors maxDist = center; - maxDist -= maxs; - // NOTE: Don't need to clamp here because we clamp against the minDist which must be >= 0, so the two clamps - // get folded together - FourVectors totalDist; - totalDist.x = MaxSIMD(dist.x, maxDist.x); - totalDist.y = MaxSIMD(dist.y, maxDist.y); - totalDist.z = MaxSIMD(dist.z, maxDist.z); - // get the total squred distance between each box & sphere center by summing the squares of each - // component/dimension - fltx4 distSq = totalDist * totalDist; - - // if squared distance between each sphere center & box is less than the radiusSquared for that sphere - // we have an intersection - fltx4 active = CmpLeSIMD(distSq,radiusSq); - - // at least one intersection? - return TestSignSIMD(active); -} - - -int FORCEINLINE CDispCollTree::BuildRayLeafList( int iNode, rayleaflist_t &list ) -{ - list.nodeList[0] = iNode; - int listIndex = 0; - list.maxIndex = 0; - while ( listIndex <= list.maxIndex ) - { - iNode = list.nodeList[listIndex]; - // the rest are all leaves - if ( IsLeafNode(iNode) ) - return listIndex; - listIndex++; - const CDispCollNode &node = m_nodes[iNode]; - int mask = IntersectRayWithFourBoxes( list.rayStart, list.invDelta, list.rayExtents, node.m_mins, node.m_maxs ); - if ( mask ) - { - int child = Nodes_GetChild( iNode, 0 ); - if ( mask & 1 ) - { - ++list.maxIndex; - list.nodeList[list.maxIndex] = child; - } - if ( mask & 2 ) - { - ++list.maxIndex; - list.nodeList[list.maxIndex] = child+1; - } - if ( mask & 4 ) - { - ++list.maxIndex; - list.nodeList[list.maxIndex] = child+2; - } - if ( mask & 8 ) - { - ++list.maxIndex; - list.nodeList[list.maxIndex] = child+3; - } - Assert(list.maxIndex < MAX_AABB_LIST); - } - } - - return listIndex; -} - - -//----------------------------------------------------------------------------- -// Purpose: Create the AABB tree. -//----------------------------------------------------------------------------- -bool CDispCollTree::AABBTree_Create( CCoreDispInfo *pDisp ) -{ - // Copy the flags. - m_nFlags = pDisp->GetSurface()->GetFlags(); - - // Copy necessary displacement data. - AABBTree_CopyDispData( pDisp ); - - // Setup/create the leaf nodes first so the recusion can use this data to stop. - AABBTree_CreateLeafs(); - - // Create the bounding box of the displacement surface + the base face. - AABBTree_CalcBounds(); - - // Successful. - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDispCollTree::AABBTree_CopyDispData( CCoreDispInfo *pDisp ) -{ - // Displacement size. - m_nPower = pDisp->GetPower(); - - // Displacement base surface data. - CCoreDispSurface *pSurf = pDisp->GetSurface(); - m_nContents = pSurf->GetContents(); - pSurf->GetNormal( m_vecStabDir ); - for ( int iPoint = 0; iPoint < 4; iPoint++ ) - { - pSurf->GetPoint( iPoint, m_vecSurfPoints[iPoint] ); - } - - // Allocate collision tree data. - { - MEM_ALLOC_CREDIT(); - m_aVerts.SetSize( GetSize() ); - } - - { - MEM_ALLOC_CREDIT(); - m_aTris.SetSize( GetTriSize() ); - } - - { - MEM_ALLOC_CREDIT(); - int numLeaves = (GetWidth()-1) * (GetHeight()-1); - m_leaves.SetCount(numLeaves); - int numNodes = Nodes_CalcCount( m_nPower ); - numNodes -= numLeaves; - m_nodes.SetCount(numNodes); - } - - - // Setup size. - m_nSize = sizeof( this ); - m_nSize += sizeof( Vector ) * GetSize(); - m_nSize += sizeof( CDispCollTri ) * GetTriSize(); -#if OLD_DISP_AABB - m_nSize += sizeof( CDispCollAABBNode ) * Nodes_CalcCount( m_nPower ); -#endif - m_nSize += sizeof(m_nodes[0]) * m_nodes.Count(); - m_nSize += sizeof(m_leaves[0]) * m_leaves.Count(); - m_nSize += sizeof( CDispCollTri* ) * DISPCOLL_TREETRI_SIZE; - - // Copy vertex data. - for ( int iVert = 0; iVert < m_aVerts.Count(); iVert++ ) - { - pDisp->GetVert( iVert, m_aVerts[iVert] ); - } - - // Copy and setup triangle data. - unsigned short iVerts[3]; - for ( int iTri = 0; iTri < m_aTris.Count(); ++iTri ) - { - pDisp->GetTriIndices( iTri, iVerts[0], iVerts[1], iVerts[2] ); - m_aTris[iTri].SetVert( 0, iVerts[0] ); - m_aTris[iTri].SetVert( 1, iVerts[1] ); - m_aTris[iTri].SetVert( 2, iVerts[2] ); - m_aTris[iTri].m_uiFlags = pDisp->GetTriTagValue( iTri ); - - // Calculate the surface props and set flags. - float flTotalAlpha = 0.0f; - for ( int iVert = 0; iVert < 3; ++iVert ) - { - flTotalAlpha += pDisp->GetAlpha( m_aTris[iTri].GetVert( iVert ) ); - } - - if ( flTotalAlpha > DISP_ALPHA_PROP_DELTA ) - { - m_aTris[iTri].m_uiFlags |= DISPSURF_FLAG_SURFPROP2; - } - else - { - m_aTris[iTri].m_uiFlags |= DISPSURF_FLAG_SURFPROP1; - } - - // Add the displacement surface flag. - m_aTris[iTri].m_uiFlags |= DISPSURF_FLAG_SURFACE; - - // Calculate the plane normal and the min max. - m_aTris[iTri].CalcPlane( m_aVerts ); - m_aTris[iTri].FindMinMax( m_aVerts ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDispCollTree::AABBTree_CreateLeafs( void ) -{ - int numLeaves = (GetWidth()-1) * (GetHeight()-1); - m_leaves.SetCount(numLeaves); - int numNodes = Nodes_CalcCount( m_nPower ); - numNodes -= numLeaves; - m_nodes.SetCount(numNodes); - - // Get the width and height of the displacement. - int nWidth = GetWidth() - 1; - int nHeight = GetHeight() - 1; - - for ( int iHgt = 0; iHgt < nHeight; ++iHgt ) - { - for ( int iWid = 0; iWid < nWidth; ++iWid ) - { - int iLeaf = Nodes_GetIndexFromComponents( iWid, iHgt ); - int iIndex = iHgt * nWidth + iWid; - int iTri = iIndex * 2; - - m_leaves[iLeaf].m_tris[0] = iTri; - m_leaves[iLeaf].m_tris[1] = iTri + 1; - } - } -} - -void CDispCollTree::AABBTree_GenerateBoxes_r( int nodeIndex, Vector *pMins, Vector *pMaxs ) -{ - // leaf - ClearBounds( *pMins, *pMaxs ); - if ( nodeIndex >= m_nodes.Count() ) - { - int iLeaf = nodeIndex - m_nodes.Count(); - - for ( int iTri = 0; iTri < 2; ++iTri ) - { - int triIndex = m_leaves[iLeaf].m_tris[iTri]; - const CDispCollTri &tri = m_aTris[triIndex]; - AddPointToBounds( m_aVerts[tri.GetVert( 0 )], *pMins, *pMaxs ); - AddPointToBounds( m_aVerts[tri.GetVert( 1 )], *pMins, *pMaxs ); - AddPointToBounds( m_aVerts[tri.GetVert( 2 )], *pMins, *pMaxs ); - } - } - else // node - { - Vector childMins[4], childMaxs[4]; - for ( int i = 0; i < 4; i++ ) - { - int child = Nodes_GetChild( nodeIndex, i ); - AABBTree_GenerateBoxes_r( child, &childMins[i], &childMaxs[i] ); - AddPointToBounds( childMins[i], *pMins, *pMaxs ); - AddPointToBounds( childMaxs[i], *pMins, *pMaxs ); - } - m_nodes[nodeIndex].m_mins.LoadAndSwizzle( childMins[0], childMins[1], childMins[2], childMins[3] ); - m_nodes[nodeIndex].m_maxs.LoadAndSwizzle( childMaxs[0], childMaxs[1], childMaxs[2], childMaxs[3] ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDispCollTree::AABBTree_CalcBounds( void ) -{ - // Check data. - if ( ( m_aVerts.Count() == 0 ) || ( m_nodes.Count() == 0 ) ) - return; - - AABBTree_GenerateBoxes_r( 0, &m_mins, &m_maxs ); - -#if INCLUDE_SURFACE_IN_BOUNDS - // Add surface points to bounds. - for ( int iPoint = 0; iPoint < 4; ++iPoint ) - { - VectorMin( m_vecSurfPoints[iPoint], m_mins, m_mins ); - VectorMax( m_vecSurfPoints[iPoint], m_maxs, m_maxs ); - } -#endif - - // Bloat a little. - for ( int iAxis = 0; iAxis < 3; ++iAxis ) - { - m_mins[iAxis] -= 1.0f; - m_maxs[iAxis] += 1.0f; - } -} - -static CThreadFastMutex s_CacheMutex; -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline void CDispCollTree::LockCache() -{ -#ifdef ENGINE_DLL - if ( !g_DispCollTriCache.LockResource( m_hCache ) ) - { - AUTO_LOCK_FM( s_CacheMutex ); - - // Cache may have just been created, so check once more - if ( !g_DispCollTriCache.LockResource( m_hCache ) ) - { - Cache(); - m_hCache = g_DispCollTriCache.CreateResource( this ); - g_DispCollTriCache.LockResource( m_hCache ); - //Msg( "Adding 0x%x to cache (actual %d) [%d, %d --> %.2f] %d total, %d unique\n", this, GetCacheMemorySize(), GetTriSize(), m_aEdgePlanes.Count(), (float)m_aEdgePlanes.Count()/(float)GetTriSize(), totals, uniques ); - } - } -#else - Cache(); -#endif -} - -inline void CDispCollTree::UnlockCache() -{ -#ifdef ENGINE_DLL - g_DispCollTriCache.UnlockResource( m_hCache ); -#endif -} -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDispCollTree::Cache( void ) -{ - if ( m_aTrisCache.Count() == GetTriSize() ) - { - return; - } - - VPROF( "CDispCollTree::Cache" ); - - // Alloc. -// int nSize = sizeof( CDispCollTriCache ) * GetTriSize(); - int nTriCount = GetTriSize(); - { - MEM_ALLOC_CREDIT(); - m_aTrisCache.SetSize( nTriCount ); - } - - for ( int iTri = 0; iTri < nTriCount; ++iTri ) - { - Cache_Create( &m_aTris[iTri], iTri ); - } - - g_DispCollPlaneIndexHash.Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDispCollTree::AABBTree_Ray( const Ray_t &ray, RayDispOutput_t &output ) -{ - if ( IsBoxIntersectingRay( m_mins, m_maxs, ray.m_Start, ray.m_Delta, DISPCOLL_DIST_EPSILON ) ) - { - return AABBTree_Ray( ray, ray.InvDelta(), output ); - } - return false; -} - -bool CDispCollTree::AABBTree_Ray( const Ray_t &ray, const Vector &vecInvDelta, RayDispOutput_t &output ) -{ - VPROF( "DispRayTest" ); - - // Check for ray test. - if ( CheckFlags( CCoreDispInfo::SURF_NORAY_COLL ) ) - return false; - - // Check for opacity. - if ( !( m_nContents & MASK_OPAQUE ) ) - return false; - - // Pre-calc the inverse delta for perf. - CDispCollTri *pImpactTri = NULL; - - AABBTree_TreeTrisRayBarycentricTest( ray, vecInvDelta, DISPCOLL_ROOTNODE_INDEX, output, &pImpactTri ); - - if ( pImpactTri ) - { - // Collision. - output.ndxVerts[0] = pImpactTri->GetVert( 0 ); - output.ndxVerts[1] = pImpactTri->GetVert( 2 ); - output.ndxVerts[2] = pImpactTri->GetVert( 1 ); - - Assert( (output.u <= 1.0f ) && ( output.v <= 1.0f ) ); - Assert( (output.u >= 0.0f ) && ( output.v >= 0.0f ) ); - - return true; - } - - // No collision. - return false; -} - -void CDispCollTree::AABBTree_TreeTrisRayBarycentricTest( const Ray_t &ray, const Vector &vecInvDelta, int iNode, RayDispOutput_t &output, CDispCollTri **pImpactTri ) -{ - rayleaflist_t list; - // NOTE: This part is loop invariant - should be hoisted up as far as possible - list.invDelta.DuplicateVector(vecInvDelta); - list.rayStart.DuplicateVector(ray.m_Start); - Vector ext = ray.m_Extents + Vector(DISPCOLL_DIST_EPSILON,DISPCOLL_DIST_EPSILON,DISPCOLL_DIST_EPSILON); - list.rayExtents.DuplicateVector(ext); - int listIndex = BuildRayLeafList( iNode, list ); - - float flU, flV, flT; - for ( ; listIndex <= list.maxIndex; listIndex++ ) - { - int leafIndex = list.nodeList[listIndex] - m_nodes.Count(); - CDispCollTri *pTri0 = &m_aTris[m_leaves[leafIndex].m_tris[0]]; - CDispCollTri *pTri1 = &m_aTris[m_leaves[leafIndex].m_tris[1]]; - - if ( ComputeIntersectionBarycentricCoordinates( ray, m_aVerts[pTri0->GetVert( 0 )], m_aVerts[pTri0->GetVert( 2 )], m_aVerts[pTri0->GetVert( 1 )], flU, flV, &flT ) ) - { - // Make sure it's inside the range - if ( ( flU >= 0.0f ) && ( flV >= 0.0f ) && ( ( flU + flV ) <= 1.0f ) ) - { - if( ( flT > 0.0f ) && ( flT < output.dist ) ) - { - (*pImpactTri) = pTri0; - output.u = flU; - output.v = flV; - output.dist = flT; - } - } - } - if ( ComputeIntersectionBarycentricCoordinates( ray, m_aVerts[pTri1->GetVert( 0 )], m_aVerts[pTri1->GetVert( 2 )], m_aVerts[pTri1->GetVert( 1 )], flU, flV, &flT ) ) - { - // Make sure it's inside the range - if ( ( flU >= 0.0f ) && ( flV >= 0.0f ) && ( ( flU + flV ) <= 1.0f ) ) - { - if( ( flT > 0.0f ) && ( flT < output.dist ) ) - { - (*pImpactTri) = pTri1; - output.u = flU; - output.v = flV; - output.dist = flT; - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDispCollTree::AABBTree_Ray( const Ray_t &ray, const Vector &vecInvDelta, CBaseTrace *pTrace, bool bSide ) -{ - VPROF("AABBTree_Ray"); - -// VPROF_BUDGET( "DispRayTraces", VPROF_BUDGETGROUP_DISP_RAYTRACES ); - - // Check for ray test. - if ( CheckFlags( CCoreDispInfo::SURF_NORAY_COLL ) ) - return false; - - // Check for opacity. - if ( !( m_nContents & MASK_OPAQUE ) ) - return false; - - // Pre-calc the inverse delta for perf. - CDispCollTri *pImpactTri = NULL; - - AABBTree_TreeTrisRayTest( ray, vecInvDelta, DISPCOLL_ROOTNODE_INDEX, pTrace, bSide, &pImpactTri ); - - if ( pImpactTri ) - { - // Collision. - VectorCopy( pImpactTri->m_vecNormal, pTrace->plane.normal ); - pTrace->plane.dist = pImpactTri->m_flDist; - pTrace->dispFlags = pImpactTri->m_uiFlags; - return true; - } - - // No collision. - return false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDispCollTree::AABBTree_TreeTrisRayTest( const Ray_t &ray, const Vector &vecInvDelta, int iNode, CBaseTrace *pTrace, bool bSide, CDispCollTri **pImpactTri ) -{ - rayleaflist_t list; - // NOTE: This part is loop invariant - should be hoisted up as far as possible - list.invDelta.DuplicateVector(vecInvDelta); - list.rayStart.DuplicateVector(ray.m_Start); - Vector ext = ray.m_Extents + Vector(DISPCOLL_DIST_EPSILON,DISPCOLL_DIST_EPSILON,DISPCOLL_DIST_EPSILON); - list.rayExtents.DuplicateVector(ext); - int listIndex = BuildRayLeafList( iNode, list ); - - for ( ;listIndex <= list.maxIndex; listIndex++ ) - { - int leafIndex = list.nodeList[listIndex] - m_nodes.Count(); - CDispCollTri *pTri0 = &m_aTris[m_leaves[leafIndex].m_tris[0]]; - CDispCollTri *pTri1 = &m_aTris[m_leaves[leafIndex].m_tris[1]]; - float flFrac = IntersectRayWithTriangle( ray, m_aVerts[pTri0->GetVert( 0 )], m_aVerts[pTri0->GetVert( 2 )], m_aVerts[pTri0->GetVert( 1 )], bSide ); - if( ( flFrac >= 0.0f ) && ( flFrac < pTrace->fraction ) ) - { - pTrace->fraction = flFrac; - (*pImpactTri) = pTri0; - } - - flFrac = IntersectRayWithTriangle( ray, m_aVerts[pTri1->GetVert( 0 )], m_aVerts[pTri1->GetVert( 2 )], m_aVerts[pTri1->GetVert( 1 )], bSide ); - if( ( flFrac >= 0.0f ) && ( flFrac < pTrace->fraction ) ) - { - pTrace->fraction = flFrac; - (*pImpactTri) = pTri1; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -int CDispCollTree::AABBTree_GetTrisInSphere( const Vector ¢er, float radius, unsigned short *pIndexOut, int indexMax ) -{ - return AABBTree_BuildTreeTrisInSphere_r( center, radius, DISPCOLL_ROOTNODE_INDEX, pIndexOut, indexMax ); -} - -int CDispCollTree::AABBTree_BuildTreeTrisInSphere_r( const Vector ¢er, float radius, int iNode, unsigned short *pIndexOut, unsigned short indexMax ) -{ - int nodeList[MAX_AABB_LIST]; - nodeList[0] = iNode; - int nTriCount = 0; - int listIndex = 0; - int maxIndex = 0; - // NOTE: This part is loop invariant - should be hoisted up as far as possible - FourVectors sphereCenters; - sphereCenters.DuplicateVector(center); - float radiusSq = radius * radius; - fltx4 sphereRadSq = ReplicateX4(radiusSq); - while ( listIndex <= maxIndex ) - { - iNode = nodeList[listIndex]; - listIndex++; - // the rest are all leaves - if ( IsLeafNode(iNode) ) - { - VPROF("Tris"); - for ( --listIndex; listIndex <= maxIndex; listIndex++ ) - { - if ( (nTriCount+2) <= indexMax ) - { - int leafIndex = nodeList[listIndex] - m_nodes.Count(); - pIndexOut[nTriCount] = m_leaves[leafIndex].m_tris[0]; - pIndexOut[nTriCount+1] = m_leaves[leafIndex].m_tris[1]; - nTriCount += 2; - } - } - break; - } - else - { - const CDispCollNode &node = m_nodes[iNode]; - int mask = IntersectFourBoxSpherePairs( sphereCenters, sphereRadSq, node.m_mins, node.m_maxs ); - if ( mask ) - { - int child = Nodes_GetChild( iNode, 0 ); - if ( mask & 1 ) - { - ++maxIndex; - nodeList[maxIndex] = child; - } - if ( mask & 2 ) - { - ++maxIndex; - nodeList[maxIndex] = child+1; - } - if ( mask & 4 ) - { - ++maxIndex; - nodeList[maxIndex] = child+2; - } - if ( mask & 8 ) - { - ++maxIndex; - nodeList[maxIndex] = child+3; - } - Assert(maxIndex < MAX_AABB_LIST); - } - } - } - return nTriCount; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDispCollTree::AABBTree_IntersectAABB( const Vector &absMins, const Vector &absMaxs ) -{ - // Check for hull test. - if ( CheckFlags( CCoreDispInfo::SURF_NOHULL_COLL ) ) - return false; - - cplane_t plane; - Vector center = 0.5f *(absMins + absMaxs); - Vector extents = absMaxs - center; - - int nodeList[MAX_AABB_LIST]; - nodeList[0] = 0; - int listIndex = 0; - int maxIndex = 0; - - // NOTE: This part is loop invariant - should be hoisted up as far as possible - FourVectors mins0; - mins0.DuplicateVector(absMins); - FourVectors maxs0; - maxs0.DuplicateVector(absMaxs); - FourVectors rayExtents; - while ( listIndex <= maxIndex ) - { - int iNode = nodeList[listIndex]; - listIndex++; - // the rest are all leaves - if ( IsLeafNode(iNode) ) - { - VPROF("Tris"); - for ( --listIndex; listIndex <= maxIndex; listIndex++ ) - { - int leafIndex = nodeList[listIndex] - m_nodes.Count(); - CDispCollTri *pTri0 = &m_aTris[m_leaves[leafIndex].m_tris[0]]; - CDispCollTri *pTri1 = &m_aTris[m_leaves[leafIndex].m_tris[1]]; - - VectorCopy( pTri0->m_vecNormal, plane.normal ); - plane.dist = pTri0->m_flDist; - plane.signbits = pTri0->m_ucSignBits; - plane.type = pTri0->m_ucPlaneType; - - if ( IsBoxIntersectingTriangle( center, extents, - m_aVerts[pTri0->GetVert( 0 )], - m_aVerts[pTri0->GetVert( 2 )], - m_aVerts[pTri0->GetVert( 1 )], - plane, 0.0f ) ) - return true; - VectorCopy( pTri1->m_vecNormal, plane.normal ); - plane.dist = pTri1->m_flDist; - plane.signbits = pTri1->m_ucSignBits; - plane.type = pTri1->m_ucPlaneType; - - if ( IsBoxIntersectingTriangle( center, extents, - m_aVerts[pTri1->GetVert( 0 )], - m_aVerts[pTri1->GetVert( 2 )], - m_aVerts[pTri1->GetVert( 1 )], - plane, 0.0f ) ) - return true; - } - break; - } - else - { - const CDispCollNode &node = m_nodes[iNode]; - int mask = IntersectFourBoxPairs( mins0, maxs0, node.m_mins, node.m_maxs ); - if ( mask ) - { - int child = Nodes_GetChild( iNode, 0 ); - if ( mask & 1 ) - { - ++maxIndex; - nodeList[maxIndex] = child; - } - if ( mask & 2 ) - { - ++maxIndex; - nodeList[maxIndex] = child+1; - } - if ( mask & 4 ) - { - ++maxIndex; - nodeList[maxIndex] = child+2; - } - if ( mask & 8 ) - { - ++maxIndex; - nodeList[maxIndex] = child+3; - } - Assert(maxIndex < MAX_AABB_LIST); - } - } - } - - // no collision - return false; -} - -static const Vector g_Vec3DispCollEpsilons(DISPCOLL_DIST_EPSILON,DISPCOLL_DIST_EPSILON,DISPCOLL_DIST_EPSILON); -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDispCollTree::AABBTree_SweepAABB( const Ray_t &ray, const Vector &vecInvDelta, CBaseTrace *pTrace ) -{ - VPROF( "DispHullTest" ); - // VPROF_BUDGET( "DispHullTraces", VPROF_BUDGETGROUP_DISP_HULLTRACES ); - // Check for hull test. - if ( CheckFlags( CCoreDispInfo::SURF_NOHULL_COLL ) ) - return false; - - // Test ray against the triangles in the list. - Vector rayDir; - VectorCopy( ray.m_Delta, rayDir ); - VectorNormalize( rayDir ); - // Save fraction. - float flFrac = pTrace->fraction; - - rayleaflist_t list; - // NOTE: This part is loop invariant - should be hoisted up as far as possible - list.invDelta.DuplicateVector(vecInvDelta); - list.rayStart.DuplicateVector(ray.m_Start); - Vector ext = ray.m_Extents + g_Vec3DispCollEpsilons; - list.rayExtents.DuplicateVector(ext); - int listIndex = BuildRayLeafList( 0, list ); - - if ( listIndex <= list.maxIndex ) - { - LockCache(); - for ( ; listIndex <= list.maxIndex; listIndex++ ) - { - int leafIndex = list.nodeList[listIndex] - m_nodes.Count(); - int iTri0 = m_leaves[leafIndex].m_tris[0]; - int iTri1 = m_leaves[leafIndex].m_tris[1]; - CDispCollTri *pTri0 = &m_aTris[iTri0]; - CDispCollTri *pTri1 = &m_aTris[iTri1]; - - SweepAABBTriIntersect( ray, rayDir, iTri0, pTri0, pTrace ); - SweepAABBTriIntersect( ray, rayDir, iTri1, pTri1, pTrace ); - } - UnlockCache(); - } - - // Collision. - if ( pTrace->fraction < flFrac ) - return true; - - // No collision. - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -bool CDispCollTree::ResolveRayPlaneIntersect( float flStart, float flEnd, const Vector &vecNormal, float flDist, CDispCollHelper *pHelper ) -{ - if( ( flStart > 0.0f ) && ( flEnd > 0.0f ) ) - return false; - - if( ( flStart < 0.0f ) && ( flEnd < 0.0f ) ) - return true; - - float flDenom = flStart - flEnd; - bool bDenomIsZero = ( flDenom == 0.0f ); - if( ( flStart >= 0.0f ) && ( flEnd <= 0.0f ) ) - { - // Find t - the parametric distance along the trace line. - float t = ( !bDenomIsZero ) ? ( flStart - DISPCOLL_DIST_EPSILON ) / flDenom : 0.0f; - if( t > pHelper->m_flStartFrac ) - { - pHelper->m_flStartFrac = t; - VectorCopy( vecNormal, pHelper->m_vecImpactNormal ); - pHelper->m_flImpactDist = flDist; - } - } - else - { - // Find t - the parametric distance along the trace line. - float t = ( !bDenomIsZero ) ? ( flStart + DISPCOLL_DIST_EPSILON ) / flDenom : 0.0f; - if( t < pHelper->m_flEndFrac ) - { - pHelper->m_flEndFrac = t; - } - } - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline bool CDispCollTree::FacePlane( const Ray_t &ray, const Vector &rayDir, CDispCollTri *pTri, CDispCollHelper *pHelper ) -{ - // Calculate the closest point on box to plane (get extents in that direction). - Vector vecExtent; - CalcClosestExtents( pTri->m_vecNormal, ray.m_Extents, vecExtent ); - - float flExpandDist = pTri->m_flDist - pTri->m_vecNormal.Dot( vecExtent ); - - float flStart = pTri->m_vecNormal.Dot( ray.m_Start ) - flExpandDist; - float flEnd = pTri->m_vecNormal.Dot( ( ray.m_Start + ray.m_Delta ) ) - flExpandDist; - - return ResolveRayPlaneIntersect( flStart, flEnd, pTri->m_vecNormal, pTri->m_flDist, pHelper ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool FORCEINLINE CDispCollTree::AxisPlanesXYZ( const Ray_t &ray, CDispCollTri *pTri, CDispCollHelper *pHelper ) -{ - static const TableVector g_ImpactNormalVecs[2][3] = - { - { - { -1, 0, 0 }, - { 0, -1, 0 }, - { 0, 0, -1 }, - }, - - { - { 1, 0, 0 }, - { 0, 1, 0 }, - { 0, 0, 1 }, - } - }; - - Vector vecImpactNormal; - float flDist, flExpDist, flStart, flEnd; - - int iAxis; - for ( iAxis = 2; iAxis >= 0; --iAxis ) - { - const float rayStart = ray.m_Start[iAxis]; - const float rayExtent = ray.m_Extents[iAxis]; - const float rayDelta = ray.m_Delta[iAxis]; - - // Min - flDist = m_aVerts[pTri->GetVert(pTri->GetMin(iAxis))][iAxis]; - flExpDist = flDist - rayExtent; - flStart = flExpDist - rayStart; - flEnd = flStart - rayDelta; - - if ( !ResolveRayPlaneIntersect( flStart, flEnd, g_ImpactNormalVecs[0][iAxis], flDist, pHelper ) ) - return false; - - // Max - flDist = m_aVerts[pTri->GetVert(pTri->GetMax(iAxis))][iAxis]; - flExpDist = flDist + rayExtent; - flStart = rayStart - flExpDist; - flEnd = flStart + rayDelta; - - if ( !ResolveRayPlaneIntersect( flStart, flEnd, g_ImpactNormalVecs[1][iAxis], flDist, pHelper ) ) - return false; - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Testing! -//----------------------------------------------------------------------------- -void CDispCollTree::Cache_Create( CDispCollTri *pTri, int iTri ) -{ - MEM_ALLOC_CREDIT(); - Vector *pVerts[3]; - pVerts[0] = &m_aVerts[pTri->GetVert( 0 )]; - pVerts[1] = &m_aVerts[pTri->GetVert( 1 )]; - pVerts[2] = &m_aVerts[pTri->GetVert( 2 )]; - - CDispCollTriCache *pCache = &m_aTrisCache[iTri]; - - Vector vecEdge; - - // Edge 1 - VectorSubtract( *pVerts[1], *pVerts[0], vecEdge ); - Cache_EdgeCrossAxisX( vecEdge, *pVerts[0], *pVerts[2], pTri, pCache->m_iCrossX[0] ); - Cache_EdgeCrossAxisY( vecEdge, *pVerts[0], *pVerts[2], pTri, pCache->m_iCrossY[0] ); - Cache_EdgeCrossAxisZ( vecEdge, *pVerts[0], *pVerts[2], pTri, pCache->m_iCrossZ[0] ); - - // Edge 2 - VectorSubtract( *pVerts[2], *pVerts[1], vecEdge ); - Cache_EdgeCrossAxisX( vecEdge, *pVerts[1], *pVerts[0], pTri, pCache->m_iCrossX[1] ); - Cache_EdgeCrossAxisY( vecEdge, *pVerts[1], *pVerts[0], pTri, pCache->m_iCrossY[1] ); - Cache_EdgeCrossAxisZ( vecEdge, *pVerts[1], *pVerts[0], pTri, pCache->m_iCrossZ[1] ); - - // Edge 3 - VectorSubtract( *pVerts[0], *pVerts[2], vecEdge ); - Cache_EdgeCrossAxisX( vecEdge, *pVerts[2], *pVerts[1], pTri, pCache->m_iCrossX[2] ); - Cache_EdgeCrossAxisY( vecEdge, *pVerts[2], *pVerts[1], pTri, pCache->m_iCrossY[2] ); - Cache_EdgeCrossAxisZ( vecEdge, *pVerts[2], *pVerts[1], pTri, pCache->m_iCrossZ[2] ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -int CDispCollTree::AddPlane( const Vector &vecNormal ) -{ - UtlHashHandle_t handle; - DispCollPlaneIndex_t planeIndex; - bool bDidInsert; - - planeIndex.vecPlane = vecNormal; - planeIndex.index = m_aEdgePlanes.Count(); - - handle = g_DispCollPlaneIndexHash.Insert( planeIndex, &bDidInsert ); - - if ( !bDidInsert ) - { - DispCollPlaneIndex_t &existingEntry = g_DispCollPlaneIndexHash[handle]; - if ( existingEntry.vecPlane == vecNormal ) - { - return existingEntry.index; - } - else - { - return ( existingEntry.index | 0x8000 ); - } - } - - return m_aEdgePlanes.AddToTail( vecNormal ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// NOTE: The plane distance get stored in the normal x position since it isn't -// used. -//----------------------------------------------------------------------------- -bool CDispCollTree::Cache_EdgeCrossAxisX( const Vector &vecEdge, const Vector &vecOnEdge, - const Vector &vecOffEdge, CDispCollTri *pTri, - unsigned short &iPlane ) -{ - // Calculate the normal - edge x axisX = ( 0.0, edgeZ, -edgeY ) - Vector vecNormal( 0.0f, vecEdge.z, -vecEdge.y ); - VectorNormalize( vecNormal ); - - // Check for zero length normals. - if( ( vecNormal.y == 0.0f ) || ( vecNormal.z == 0.0f ) ) - { - iPlane = DISPCOLL_NORMAL_UNDEF; - return false; - } - -// if ( pTri->m_vecNormal.Dot( vecNormal ) ) -// { -// iPlane = DISPCOLL_NORMAL_UNDEF; -// return false; -// } - - // Finish the plane definition - get distance. - float flDist = ( vecNormal.y * vecOnEdge.y ) + ( vecNormal.z * vecOnEdge.z ); - - // Special case the point off edge in plane - float flOffDist = ( vecNormal.y * vecOffEdge.y ) + ( vecNormal.z * vecOffEdge.z ); - if ( !( FloatMakePositive( flOffDist - flDist ) < DISPCOLL_DIST_EPSILON ) && ( flOffDist > flDist ) ) - { - // Adjust plane facing - triangle should be behind the plane. - vecNormal.x = -flDist; - vecNormal.y = -vecNormal.y; - vecNormal.z = -vecNormal.z; - } - else - { - vecNormal.x = flDist; - } - - // Add edge plane to edge plane list. - iPlane = static_cast( AddPlane( vecNormal ) ); - - // Created the cached edge. - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// NOTE: The plane distance get stored in the normal y position since it isn't -// used. -//----------------------------------------------------------------------------- -bool CDispCollTree::Cache_EdgeCrossAxisY( const Vector &vecEdge, const Vector &vecOnEdge, - const Vector &vecOffEdge, CDispCollTri *pTri, - unsigned short &iPlane ) -{ - // Calculate the normal - edge x axisY = ( -edgeZ, 0.0, edgeX ) - Vector vecNormal( -vecEdge.z, 0.0f, vecEdge.x ); - VectorNormalize( vecNormal ); - - // Check for zero length normals - if( ( vecNormal.x == 0.0f ) || ( vecNormal.z == 0.0f ) ) - { - iPlane = DISPCOLL_NORMAL_UNDEF; - return false; - } - -// if ( pTri->m_vecNormal.Dot( vecNormal ) ) -// { -// iPlane = DISPCOLL_NORMAL_UNDEF; -// return false; -// } - - // Finish the plane definition - get distance. - float flDist = ( vecNormal.x * vecOnEdge.x ) + ( vecNormal.z * vecOnEdge.z ); - - // Special case the point off edge in plane - float flOffDist = ( vecNormal.x * vecOffEdge.x ) + ( vecNormal.z * vecOffEdge.z ); - if ( !( FloatMakePositive( flOffDist - flDist ) < DISPCOLL_DIST_EPSILON ) && ( flOffDist > flDist ) ) - { - // Adjust plane facing if necessay - triangle should be behind the plane. - vecNormal.x = -vecNormal.x; - vecNormal.y = -flDist; - vecNormal.z = -vecNormal.z; - } - else - { - vecNormal.y = flDist; - } - - // Add edge plane to edge plane list. - iPlane = static_cast( AddPlane( vecNormal ) ); - - // Created the cached edge. - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDispCollTree::Cache_EdgeCrossAxisZ( const Vector &vecEdge, const Vector &vecOnEdge, - const Vector &vecOffEdge, CDispCollTri *pTri, - unsigned short &iPlane ) -{ - // Calculate the normal - edge x axisY = ( edgeY, -edgeX, 0.0 ) - Vector vecNormal( vecEdge.y, -vecEdge.x, 0.0f ); - VectorNormalize( vecNormal ); - - // Check for zero length normals - if( ( vecNormal.x == 0.0f ) || ( vecNormal.y == 0.0f ) ) - { - iPlane = DISPCOLL_NORMAL_UNDEF; - return false; - } - -// if ( pTri->m_vecNormal.Dot( vecNormal ) ) -// { -// iPlane = DISPCOLL_NORMAL_UNDEF; -// return false; -// } - - // Finish the plane definition - get distance. - float flDist = ( vecNormal.x * vecOnEdge.x ) + ( vecNormal.y * vecOnEdge.y ); - - // Special case the point off edge in plane - float flOffDist = ( vecNormal.x * vecOffEdge.x ) + ( vecNormal.y * vecOffEdge.y ); - if ( !( FloatMakePositive( flOffDist - flDist ) < DISPCOLL_DIST_EPSILON ) && ( flOffDist > flDist ) ) - { - // Adjust plane facing if necessay - triangle should be behind the plane. - vecNormal.x = -vecNormal.x; - vecNormal.y = -vecNormal.y; - vecNormal.z = -flDist; - } - else - { - vecNormal.z = flDist; - } - - // Add edge plane to edge plane list. - iPlane = static_cast( AddPlane( vecNormal ) ); - - // Created the cached edge. - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -template -bool CDispCollTree::EdgeCrossAxis( const Ray_t &ray, unsigned short iPlane, CDispCollHelper *pHelper ) -{ - if ( iPlane == DISPCOLL_NORMAL_UNDEF ) - return true; - - // Get the edge plane. - Vector vecNormal; - if ( ( iPlane & 0x8000 ) != 0 ) - { - VectorCopy( m_aEdgePlanes[(iPlane&0x7fff)], vecNormal ); - vecNormal.Negate(); - } - else - { - VectorCopy( m_aEdgePlanes[iPlane], vecNormal ); - } - - const int OTHER_AXIS1 = ( AXIS + 1 ) % 3; - const int OTHER_AXIS2 = ( AXIS + 2 ) % 3; - - // Get the pland distance are "fix" the normal. - float flDist = vecNormal[AXIS]; - vecNormal[AXIS] = 0.0f; - - // Calculate the closest point on box to plane (get extents in that direction). - Vector vecExtent; - //vecExtent[AXIS] = 0.0f; - vecExtent[OTHER_AXIS1] = ( vecNormal[OTHER_AXIS1] < 0.0f ) ? ray.m_Extents[OTHER_AXIS1] : -ray.m_Extents[OTHER_AXIS1]; - vecExtent[OTHER_AXIS2] = ( vecNormal[OTHER_AXIS2] < 0.0f ) ? ray.m_Extents[OTHER_AXIS2] : -ray.m_Extents[OTHER_AXIS2]; - - // Expand the plane by the extents of the box to reduce the swept box/triangle - // test to a ray/extruded triangle test (one of the triangles extruded planes - // was just calculated above). - Vector vecEnd; - vecEnd[AXIS] = 0; - vecEnd[OTHER_AXIS1] = ray.m_Start[OTHER_AXIS1] + ray.m_Delta[OTHER_AXIS1]; - vecEnd[OTHER_AXIS2] = ray.m_Start[OTHER_AXIS2] + ray.m_Delta[OTHER_AXIS2]; - - float flExpandDist = flDist - ( ( vecNormal[OTHER_AXIS1] * vecExtent[OTHER_AXIS1] ) + ( vecNormal[OTHER_AXIS2] * vecExtent[OTHER_AXIS2] ) ); - float flStart = ( vecNormal[OTHER_AXIS1] * ray.m_Start[OTHER_AXIS1] ) + ( vecNormal[OTHER_AXIS2] * ray.m_Start[OTHER_AXIS2] ) - flExpandDist; - float flEnd = ( vecNormal[OTHER_AXIS1] * vecEnd[OTHER_AXIS1] ) + ( vecNormal[OTHER_AXIS2] * vecEnd[OTHER_AXIS2] ) - flExpandDist; - - return ResolveRayPlaneIntersect( flStart, flEnd, vecNormal, flDist, pHelper ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline bool CDispCollTree::EdgeCrossAxisX( const Ray_t &ray, unsigned short iPlane, CDispCollHelper *pHelper ) -{ - return EdgeCrossAxis<0>( ray, iPlane, pHelper ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline bool CDispCollTree::EdgeCrossAxisY( const Ray_t &ray, unsigned short iPlane, CDispCollHelper *pHelper ) -{ - return EdgeCrossAxis<1>( ray, iPlane, pHelper ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline bool CDispCollTree::EdgeCrossAxisZ( const Ray_t &ray, unsigned short iPlane, CDispCollHelper *pHelper ) -{ - return EdgeCrossAxis<2>( ray, iPlane, pHelper ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CDispCollTree::SweepAABBTriIntersect( const Ray_t &ray, const Vector &rayDir, int iTri, CDispCollTri *pTri, CBaseTrace *pTrace ) -{ - // Init test data. - CDispCollHelper helper; - helper.m_flEndFrac = 1.0f; - helper.m_flStartFrac = DISPCOLL_INVALID_FRAC; - - // Make sure objects are traveling toward one another. - float flDistAlongNormal = pTri->m_vecNormal.Dot( ray.m_Delta ); - if( flDistAlongNormal > DISPCOLL_DIST_EPSILON ) - return; - - // Test against the axis planes. - if ( !AxisPlanesXYZ( ray, pTri, &helper ) ) - { - return; - } - - // - // There are 9 edge tests - edges 1, 2, 3 cross with the box edges (symmetry) 1, 2, 3. However, the box - // is axis-aligned resulting in axially directional edges -- thus each test is edges 1, 2, and 3 vs. - // axial planes x, y, and z - // - // There are potentially 9 more tests with edges, the edge's edges and the direction of motion! - // NOTE: I don't think these tests are necessary for a manifold surface. - // - - CDispCollTriCache *pCache = &m_aTrisCache[iTri]; - - // Edges 1-3, interleaved - axis tests are 2d tests - if ( !EdgeCrossAxisX( ray, pCache->m_iCrossX[0], &helper ) ) { return; } - if ( !EdgeCrossAxisX( ray, pCache->m_iCrossX[1], &helper ) ) { return; } - if ( !EdgeCrossAxisX( ray, pCache->m_iCrossX[2], &helper ) ) { return; } - - if ( !EdgeCrossAxisY( ray, pCache->m_iCrossY[0], &helper ) ) { return; } - if ( !EdgeCrossAxisY( ray, pCache->m_iCrossY[1], &helper ) ) { return; } - if ( !EdgeCrossAxisY( ray, pCache->m_iCrossY[2], &helper ) ) { return; } - - if ( !EdgeCrossAxisZ( ray, pCache->m_iCrossZ[0], &helper ) ) { return; } - if ( !EdgeCrossAxisZ( ray, pCache->m_iCrossZ[1], &helper ) ) { return; } - if ( !EdgeCrossAxisZ( ray, pCache->m_iCrossZ[2], &helper ) ) { return; } - - // Test against the triangle face plane. - if ( !FacePlane( ray, rayDir, pTri, &helper ) ) - return; - - if ( ( helper.m_flStartFrac < helper.m_flEndFrac ) || ( FloatMakePositive( helper.m_flStartFrac - helper.m_flEndFrac ) < 0.001f ) ) - { - if ( ( helper.m_flStartFrac != DISPCOLL_INVALID_FRAC ) && ( helper.m_flStartFrac < pTrace->fraction ) ) - { - // Clamp -- shouldn't really ever be here!??? - if ( helper.m_flStartFrac < 0.0f ) - { - helper.m_flStartFrac = 0.0f; - } - - pTrace->fraction = helper.m_flStartFrac; - VectorCopy( helper.m_vecImpactNormal, pTrace->plane.normal ); - pTrace->plane.dist = helper.m_flImpactDist; - pTrace->dispFlags = pTri->m_uiFlags; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: constructor -//----------------------------------------------------------------------------- -CDispCollTree::CDispCollTree() -{ - m_nPower = 0; - m_nFlags = 0; - - for ( int iPoint = 0; iPoint < 4; ++iPoint ) - { - m_vecSurfPoints[iPoint].Init(); - } - m_nContents = -1; - m_nSurfaceProps[0] = 0; - m_nSurfaceProps[1] = 0; - - m_vecStabDir.Init(); - m_mins.Init( FLT_MAX, FLT_MAX, FLT_MAX ); - m_maxs.Init( -FLT_MAX, -FLT_MAX, -FLT_MAX ); - - m_iCounter = 0; - - m_aVerts.Purge(); - m_aTris.Purge(); - m_aEdgePlanes.Purge(); -#ifdef ENGINE_DLL - m_hCache = INVALID_MEMHANDLE; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: deconstructor -//----------------------------------------------------------------------------- -CDispCollTree::~CDispCollTree() -{ -#ifdef ENGINE_DLL - if ( m_hCache != INVALID_MEMHANDLE ) - g_DispCollTriCache.DestroyResource( m_hCache ); -#endif - m_aVerts.Purge(); - m_aTris.Purge(); - m_aEdgePlanes.Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDispCollTree::Create( CCoreDispInfo *pDisp ) -{ - // Create the AABB Tree. - return AABBTree_Create( pDisp ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CDispCollTree::PointInBounds( const Vector &vecBoxCenter, const Vector &vecBoxMin, - const Vector &vecBoxMax, bool bPoint ) -{ - // Point test inside bounds. - if( bPoint ) - { - return IsPointInBox( vecBoxCenter, m_mins, m_maxs ); - } - - // Box test inside bounds - Vector vecExtents; - VectorSubtract( vecBoxMax, vecBoxMin, vecExtents ); - vecExtents *= 0.5f; - - Vector vecExpandBounds[2]; - vecExpandBounds[0] = m_mins - vecExtents; - vecExpandBounds[1] = m_maxs + vecExtents; - - return IsPointInBox( vecBoxCenter, vecExpandBounds[0], vecExpandBounds[1] ); -} - -void CDispCollTree::GetVirtualMeshList( virtualmeshlist_t *pList ) -{ - int i; - int triangleCount = GetTriSize(); - pList->indexCount = triangleCount * 3; - pList->triangleCount = triangleCount; - pList->vertexCount = m_aVerts.Count(); - pList->pVerts = m_aVerts.Base(); - pList->pHull = NULL; - pList->surfacePropsIndex = GetSurfaceProps(0); - int index = 0; - for ( i = 0 ; i < triangleCount; i++ ) - { - pList->indices[index+0] = m_aTris[i].GetVert(0); - pList->indices[index+1] = m_aTris[i].GetVert(1); - pList->indices[index+2] = m_aTris[i].GetVert(2); - index += 3; - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -#ifdef ENGINE_DLL -static int g_nTrees; -#endif -CDispCollTree *DispCollTrees_Alloc( int count ) -{ - CDispCollTree *pTrees = NULL; -#ifdef ENGINE_DLL - pTrees = (CDispCollTree *)Hunk_Alloc( count * sizeof(CDispCollTree), false ); - g_nTrees = count; - for ( int i = 0; i < g_nTrees; i++ ) - { - Construct( pTrees + i ); - } -#else - pTrees = new CDispCollTree[count]; -#endif - if( !pTrees ) - return NULL; - - for ( int i = 0; i < count; i++ ) - { - pTrees[i].m_iCounter = i; - } - return pTrees; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void DispCollTrees_Free( CDispCollTree *pTrees ) -{ -#ifdef ENGINE_DLL - for ( int i = 0; i < g_nTrees; i++ ) - { - Destruct( pTrees + i ); - } - g_nTrees = 0; -#else - if( pTrees ) - { - delete [] pTrees; - pTrees = NULL; - } -#endif -} diff --git a/public/dispcoll_common.h b/public/dispcoll_common.h deleted file mode 100644 index d30b3de70..000000000 --- a/public/dispcoll_common.h +++ /dev/null @@ -1,456 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef DISPCOLL_COMMON_H -#define DISPCOLL_COMMON_H -#pragma once - -#include "trace.h" -#include "builddisp.h" -#include "bitvec.h" -#ifdef ENGINE_DLL -#include "../engine/zone.h" -#endif - -#ifdef ENGINE_DLL -template -class CDispVector : public CUtlVector > -{ -}; -#else -template -class CDispVector : public CUtlVector> -{ -}; -#endif - -FORWARD_DECLARE_HANDLE( memhandle_t ); - -#define DISPCOLL_TREETRI_SIZE MAX_DISPTRIS -#define DISPCOLL_DIST_EPSILON 0.03125f -#define DISPCOLL_ROOTNODE_INDEX 0 -#define DISPCOLL_INVALID_TRI -1 -#define DISPCOLL_INVALID_FRAC -99999.9f -#define DISPCOLL_NORMAL_UNDEF 0xffff - -extern double g_flDispCollSweepTimer; -extern double g_flDispCollIntersectTimer; -extern double g_flDispCollInCallTimer; - -struct RayDispOutput_t -{ - short ndxVerts[4]; // 3 verts and a pad - float u, v; // the u, v paramters (edgeU = v1 - v0, edgeV = v2 - v0) - float dist; // intersection distance -}; - -// Assumptions: -// Max patch is 17x17, therefore 9 bits needed to represent a triangle index -// - -//============================================================================= -// Displacement Collision Triangle -class CDispCollTri -{ - - struct index_t - { - union - { - struct - { - unsigned short uiVert:9; - unsigned short uiMin:2; - unsigned short uiMax:2; - } m_Index; - - unsigned short m_IndexDummy; - }; - }; - - index_t m_TriData[3]; - -public: - unsigned short m_ucSignBits:3; // Plane test. - unsigned short m_ucPlaneType:3; // Axial test? - unsigned short m_uiFlags:5; // Uses 5-bits - maybe look into merging it with something? - - Vector m_vecNormal; // Triangle normal (plane normal). - float m_flDist; // Triangle plane dist. - - // Creation. - CDispCollTri(); - void Init( void ); - void CalcPlane( CDispVector &m_aVerts ); - void FindMinMax( CDispVector &m_aVerts ); - - // Triangle data. - inline void SetVert( int iPos, int iVert ) { Assert( ( iPos >= 0 ) && ( iPos < 3 ) ); Assert( ( iVert >= 0 ) && ( iVert < ( 1 << 9 ) ) ); m_TriData[iPos].m_Index.uiVert = iVert; } - inline int GetVert( int iPos ) const { Assert( ( iPos >= 0 ) && ( iPos < 3 ) ); return m_TriData[iPos].m_Index.uiVert; } - inline void SetMin( int iAxis, int iMin ) { Assert( ( iAxis >= 0 ) && ( iAxis < 3 ) ); Assert( ( iMin >= 0 ) && ( iMin < 3 ) ); m_TriData[iAxis].m_Index.uiMin = iMin; } - inline int GetMin( int iAxis ) const { Assert( ( iAxis >= 0 ) && ( iAxis < 3 ) ); return m_TriData[iAxis].m_Index.uiMin; } - inline void SetMax( int iAxis, int iMax ) { Assert( ( iAxis >= 0 ) && ( iAxis < 3 ) ); Assert( ( iMax >= 0 ) && ( iMax < 3 ) ); m_TriData[iAxis].m_Index.uiMax = iMax; } - inline int GetMax( int iAxis ) const { Assert( ( iAxis >= 0 ) && ( iAxis < 3 ) ); return m_TriData[iAxis].m_Index.uiMax; } -}; - -//============================================================================= -// Helper -class CDispCollHelper -{ -public: - - float m_flStartFrac; - float m_flEndFrac; - Vector m_vecImpactNormal; - float m_flImpactDist; -}; - -//============================================================================= -// Cache -#pragma pack(1) -class CDispCollTriCache -{ -public: - unsigned short m_iCrossX[3]; - unsigned short m_iCrossY[3]; - unsigned short m_iCrossZ[3]; -}; -#pragma pack() -#include "mathlib/ssemath.h" - -class CDispCollNode -{ -public: - FourVectors m_mins; - FourVectors m_maxs; -}; - -class CDispCollLeaf -{ -public: - short m_tris[2]; -}; - -// a power 4 displacement can have 341 nodes, pad out to 344 for 16-byte alignment -const int MAX_DISP_AABB_NODES = 341; -const int MAX_AABB_LIST = 344; - -struct rayleaflist_t -{ - FourVectors rayStart; - FourVectors rayExtents; - FourVectors invDelta; - int nodeList[MAX_AABB_LIST]; - int maxIndex; -}; - -//============================================================================= -// -// Displacement Collision Tree Data -// -class CDispCollTree -{ -public: - - // Creation/Destruction. - CDispCollTree(); - ~CDispCollTree(); - virtual bool Create( CCoreDispInfo *pDisp ); - - // Raycasts. - // NOTE: These assume you've precalculated invDelta as well as culled to the bounds of this disp - bool AABBTree_Ray( const Ray_t &ray, const Vector &invDelta, CBaseTrace *pTrace, bool bSide = true ); - bool AABBTree_Ray( const Ray_t &ray, const Vector &invDelta, RayDispOutput_t &output ); - // NOTE: Lower perf helper function, should not be used in the game runtime - bool AABBTree_Ray( const Ray_t &ray, RayDispOutput_t &output ); - - // Hull Sweeps. - // NOTE: These assume you've precalculated invDelta as well as culled to the bounds of this disp - bool AABBTree_SweepAABB( const Ray_t &ray, const Vector &invDelta, CBaseTrace *pTrace ); - - // Hull Intersection. - bool AABBTree_IntersectAABB( const Vector &absMins, const Vector &absMaxs ); - - // Point/Box vs. Bounds. - bool PointInBounds( Vector const &vecBoxCenter, Vector const &vecBoxMin, Vector const &vecBoxMax, bool bPoint ); - - // Utility. - inline void SetPower( int power ) { m_nPower = power; } - inline int GetPower( void ) { return m_nPower; } - - inline int GetFlags( void ) { return m_nFlags; } - inline void SetFlags( int nFlags ) { m_nFlags = nFlags; } - inline bool CheckFlags( int nFlags ) { return ( ( nFlags & GetFlags() ) != 0 ) ? true : false; } - - inline int GetWidth( void ) { return ( ( 1 << m_nPower ) + 1 ); } - inline int GetHeight( void ) { return ( ( 1 << m_nPower ) + 1 ); } - inline int GetSize( void ) { return ( ( 1 << m_nPower ) + 1 ) * ( ( 1 << m_nPower ) + 1 ); } - inline int GetTriSize( void ) { return ( ( 1 << m_nPower ) * ( 1 << m_nPower ) * 2 ); } - -// inline void SetTriFlags( short iTri, unsigned short nFlags ) { m_aTris[iTri].m_uiFlags = nFlags; } - - inline void GetStabDirection( Vector &vecDir ) { vecDir = m_vecStabDir; } - - inline void GetBounds( Vector &vecBoxMin, Vector &vecBoxMax ) { vecBoxMin = m_mins; vecBoxMax = m_maxs; } - inline int GetContents( void ) { return m_nContents; } - inline void SetSurfaceProps( int iProp, short nSurfProp ) { Assert( ( iProp >= 0 ) && ( iProp < 2 ) ); m_nSurfaceProps[iProp] = nSurfProp; } - inline short GetSurfaceProps( int iProp ) { return m_nSurfaceProps[iProp]; } - - inline unsigned int GetMemorySize( void ) { return m_nSize; } - inline unsigned int GetCacheMemorySize( void ) { return ( m_aTrisCache.Count() * sizeof(CDispCollTriCache) + m_aEdgePlanes.Count() * sizeof(Vector) ); } - - inline bool IsCached( void ) { return m_aTrisCache.Count() == m_aTris.Count(); } - - void GetVirtualMeshList( struct virtualmeshlist_t *pList ); - int AABBTree_GetTrisInSphere( const Vector ¢er, float radius, unsigned short *pIndexOut, int indexMax ); - -public: - - inline int Nodes_GetChild( int iNode, int nDirection ); - inline int Nodes_CalcCount( int nPower ); - inline int Nodes_GetParent( int iNode ); - inline int Nodes_GetLevel( int iNode ); - inline int Nodes_GetIndexFromComponents( int x, int y ); - - void LockCache(); - void UnlockCache(); - void Cache( void ); - void Uncache() { m_aTrisCache.Purge(); m_aEdgePlanes.Purge(); } - -#ifdef ENGINE_DLL - // Data manager methods - static size_t EstimatedSize( CDispCollTree *pTree ) - { - return pTree->GetCacheMemorySize(); - } - - static CDispCollTree *CreateResource( CDispCollTree *pTree ) - { - // Created ahead of time - return pTree; - } - - bool GetData() - { - return IsCached(); - } - - size_t Size() - { - return GetCacheMemorySize(); - } - - void DestroyResource() - { - Uncache(); - m_hCache = NULL; - } -#endif - -protected: - - bool AABBTree_Create( CCoreDispInfo *pDisp ); - void AABBTree_CopyDispData( CCoreDispInfo *pDisp ); - void AABBTree_CreateLeafs( void ); - void AABBTree_GenerateBoxes_r( int nodeIndex, Vector *pMins, Vector *pMaxs ); - void AABBTree_CalcBounds( void ); - - int AABBTree_BuildTreeTrisInSphere_r( const Vector ¢er, float radius, int iNode, unsigned short *pIndexOut, unsigned short indexMax ); - - void AABBTree_TreeTrisRayTest( const Ray_t &ray, const Vector &vecInvDelta, int iNode, CBaseTrace *pTrace, bool bSide, CDispCollTri **pImpactTri ); - void AABBTree_TreeTrisRayBarycentricTest( const Ray_t &ray, const Vector &vecInvDelta, int iNode, RayDispOutput_t &output, CDispCollTri **pImpactTri ); - - int FORCEINLINE BuildRayLeafList( int iNode, rayleaflist_t &list ); - - struct AABBTree_TreeTrisSweepTest_Args_t - { - AABBTree_TreeTrisSweepTest_Args_t( const Ray_t &ray, const Vector &vecInvDelta, const Vector &rayDir, CBaseTrace *pTrace ) - : ray( ray ), vecInvDelta( vecInvDelta ), rayDir( rayDir ), pTrace( pTrace ) {} - const Ray_t &ray; - const Vector &vecInvDelta; - const Vector &rayDir; - CBaseTrace *pTrace; - }; - -protected: - - void SweepAABBTriIntersect( const Ray_t &ray, const Vector &rayDir, int iTri, CDispCollTri *pTri, CBaseTrace *pTrace ); - - void Cache_Create( CDispCollTri *pTri, int iTri ); // Testing! - bool Cache_EdgeCrossAxisX( const Vector &vecEdge, const Vector &vecOnEdge, const Vector &vecOffEdge, CDispCollTri *pTri, unsigned short &iPlane ); - bool Cache_EdgeCrossAxisY( const Vector &vecEdge, const Vector &vecOnEdge, const Vector &vecOffEdge, CDispCollTri *pTri, unsigned short &iPlane ); - bool Cache_EdgeCrossAxisZ( const Vector &vecEdge, const Vector &vecOnEdge, const Vector &vecOffEdge, CDispCollTri *pTri, unsigned short &iPlane ); - - inline bool FacePlane( const Ray_t &ray, const Vector &rayDir, CDispCollTri *pTri, CDispCollHelper *pHelper ); - bool FORCEINLINE AxisPlanesXYZ( const Ray_t &ray, CDispCollTri *pTri, CDispCollHelper *pHelper ); - inline bool EdgeCrossAxisX( const Ray_t &ray, unsigned short iPlane, CDispCollHelper *pHelper ); - inline bool EdgeCrossAxisY( const Ray_t &ray, unsigned short iPlane, CDispCollHelper *pHelper ); - inline bool EdgeCrossAxisZ( const Ray_t &ray, unsigned short iPlane, CDispCollHelper *pHelper ); - - bool ResolveRayPlaneIntersect( float flStart, float flEnd, const Vector &vecNormal, float flDist, CDispCollHelper *pHelper ); - template bool FORCEINLINE TestOneAxisPlaneMin( const Ray_t &ray, CDispCollTri *pTri ); - template bool FORCEINLINE TestOneAxisPlaneMax( const Ray_t &ray, CDispCollTri *pTri ); - template bool EdgeCrossAxis( const Ray_t &ray, unsigned short iPlane, CDispCollHelper *pHelper ); - - // Utility - inline void CalcClosestBoxPoint( const Vector &vecPlaneNormal, const Vector &vecBoxStart, const Vector &vecBoxExtents, Vector &vecBoxPoint ); - inline void CalcClosestExtents( const Vector &vecPlaneNormal, const Vector &vecBoxExtents, Vector &vecBoxPoint ); - int AddPlane( const Vector &vecNormal ); - bool FORCEINLINE IsLeafNode(int iNode); -public: - Vector m_mins; // Bounding box of the displacement surface and base face - int m_iCounter; - Vector m_maxs; // Bounding box of the displacement surface and base face -protected: - int m_nContents; // The displacement surface "contents" (solid, etc...) - -#ifdef ENGINE_DLL - memhandle_t m_hCache; -#endif - - int m_nPower; // Size of the displacement ( 2^power + 1 ) - int m_nFlags; - - Vector m_vecSurfPoints[4]; // Base surface points. - // Collision data. - Vector m_vecStabDir; // Direction to stab for this displacement surface (is the base face normal) - short m_nSurfaceProps[2]; // Surface properties (save off from texdata for impact responses) - -protected: - CDispVector m_aVerts; // Displacement verts. - CDispVector m_aTris; // Displacement triangles. - CDispVector m_nodes; // Nodes. - CDispVector m_leaves; // Leaves. - // Cache - CUtlVector m_aTrisCache; - CUtlVector m_aEdgePlanes; - - CDispCollHelper m_Helper; - - unsigned int m_nSize; - -}; - -FORCEINLINE bool CDispCollTree::IsLeafNode(int iNode) -{ - return iNode >= m_nodes.Count() ? true : false; -} - -//----------------------------------------------------------------------------- -// Purpose: get the child node index given the current node index and direction -// of the child (1 of 4) -// Input: iNode - current node index -// nDirection - direction of the child ( [0...3] - SW, SE, NW, NE ) -// Output: int - the index of the child node -//----------------------------------------------------------------------------- -inline int CDispCollTree::Nodes_GetChild( int iNode, int nDirection ) -{ - // node range [0...m_NodeCount) - Assert( iNode >= 0 ); - Assert( iNode < m_nodes.Count() ); - - // ( node index * 4 ) + ( direction + 1 ) - return ( ( iNode << 2 ) + ( nDirection + 1 ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline int CDispCollTree::Nodes_CalcCount( int nPower ) -{ - Assert( nPower >= 1 ); - Assert( nPower <= 4 ); - - return ( ( 1 << ( ( nPower + 1 ) << 1 ) ) / 3 ); -} - -//----------------------------------------------------------------------------- -// Purpose: get the parent node index given the current node -// Input: iNode - current node index -// Output: int - the index of the parent node -//----------------------------------------------------------------------------- -inline int CDispCollTree::Nodes_GetParent( int iNode ) -{ - // node range [0...m_NodeCount) - Assert( iNode >= 0 ); - Assert( iNode < m_nodes.Count() ); - - // ( node index - 1 ) / 4 - return ( ( iNode - 1 ) >> 2 ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// TODO: should make this a function - not a hardcoded set of statements!!! -//----------------------------------------------------------------------------- -inline int CDispCollTree::Nodes_GetLevel( int iNode ) -{ - // node range [0...m_NodeCount) - Assert( iNode >= 0 ); - Assert( iNode < m_nodes.Count() ); - - // level = 2^n + 1 - if ( iNode == 0 ) { return 1; } - if ( iNode < 5 ) { return 2; } - if ( iNode < 21 ) { return 3; } - if ( iNode < 85 ) { return 4; } - if ( iNode < 341 ) { return 5; } - - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline int CDispCollTree::Nodes_GetIndexFromComponents( int x, int y ) -{ - int nIndex = 0; - - // Interleave bits from the x and y values to create the index - int iShift; - for( iShift = 0; x != 0; iShift += 2, x >>= 1 ) - { - nIndex |= ( x & 1 ) << iShift; - } - - for( iShift = 1; y != 0; iShift += 2, y >>= 1 ) - { - nIndex |= ( y & 1 ) << iShift; - } - - return nIndex; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline void CDispCollTree::CalcClosestBoxPoint( const Vector &vecPlaneNormal, const Vector &vecBoxStart, - const Vector &vecBoxExtents, Vector &vecBoxPoint ) -{ - vecBoxPoint = vecBoxStart; - ( vecPlaneNormal[0] < 0.0f ) ? vecBoxPoint[0] += vecBoxExtents[0] : vecBoxPoint[0] -= vecBoxExtents[0]; - ( vecPlaneNormal[1] < 0.0f ) ? vecBoxPoint[1] += vecBoxExtents[1] : vecBoxPoint[1] -= vecBoxExtents[1]; - ( vecPlaneNormal[2] < 0.0f ) ? vecBoxPoint[2] += vecBoxExtents[2] : vecBoxPoint[2] -= vecBoxExtents[2]; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -inline void CDispCollTree::CalcClosestExtents( const Vector &vecPlaneNormal, const Vector &vecBoxExtents, - Vector &vecBoxPoint ) -{ - ( vecPlaneNormal[0] < 0.0f ) ? vecBoxPoint[0] = vecBoxExtents[0] : vecBoxPoint[0] = -vecBoxExtents[0]; - ( vecPlaneNormal[1] < 0.0f ) ? vecBoxPoint[1] = vecBoxExtents[1] : vecBoxPoint[1] = -vecBoxExtents[1]; - ( vecPlaneNormal[2] < 0.0f ) ? vecBoxPoint[2] = vecBoxExtents[2] : vecBoxPoint[2] = -vecBoxExtents[2]; -} - -//============================================================================= -// Global Helper Functions -CDispCollTree *DispCollTrees_Alloc( int count ); -void DispCollTrees_Free( CDispCollTree *pTrees ); - -#endif // DISPCOLL_COMMON_H diff --git a/public/dlight.h b/public/dlight.h deleted file mode 100644 index a4285aaaf..000000000 --- a/public/dlight.h +++ /dev/null @@ -1,84 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#if !defined ( DLIGHTH ) -#define DLIGHTH -#ifdef _WIN32 -#pragma once -#endif - -#include "mathlib/vector.h" - -//----------------------------------------------------------------------------- -// Dynamic light structure -//----------------------------------------------------------------------------- - -enum -{ - DLIGHT_NO_WORLD_ILLUMINATION = 0x1, - DLIGHT_NO_MODEL_ILLUMINATION = 0x2, - - // NOTE: These two features are used to dynamically tweak the alpha on displacements - // which is a special effect for selecting which texture to use. If - // we ever change how alpha is stored for displacements, we'll have to kill this feature - DLIGHT_ADD_DISPLACEMENT_ALPHA = 0x4, - DLIGHT_SUBTRACT_DISPLACEMENT_ALPHA = 0x8, - DLIGHT_DISPLACEMENT_MASK = (DLIGHT_ADD_DISPLACEMENT_ALPHA | DLIGHT_SUBTRACT_DISPLACEMENT_ALPHA), -}; - -// This is the lighting value that is used to determine when something can be -// culle from lighting because it is close enough to black to be virtually black. -//#define MIN_LIGHTING_VALUE (1.0f/256.0f) - -// This is the broken value of MIN_LIGHTING_VALUE that we have to take into consideration -// to make sure that the lighting for dlights look the same as they did in HL2. -// We'll use the real MIN_LIGHTING_VALUE above to calculate larger radii for dynamic -// light sources. -//#define HL2_BROKEN_MIN_LIGHTING_VALUE (20.0f/256.0f) - -struct dlight_t -{ - int flags; - Vector origin; - float radius; - ColorRGBExp32 color; // Light color with exponent - float die; // stop lighting after this time - float decay; // drop this each second - float minlight; // don't add when contributing less - int key; - int style; // lightstyle - - // For spotlights. Use m_OuterAngle == 0 for point lights - Vector m_Direction; // center of the light cone - float m_InnerAngle; - float m_OuterAngle; - - // see comments above about HL2_BROKEN_MIN_LIGHTING_VALUE and MIN_LIGHTING_VALUE - // THIS SHOULD ONLY GET CALLED FROM THE ENGINE - float GetRadius() const - { -// return FastSqrt( radius * radius * ( HL2_BROKEN_MIN_LIGHTING_VALUE / MIN_LIGHTING_VALUE ) ); - return radius; - } - - // see comments above about HL2_BROKEN_MIN_LIGHTING_VALUE and MIN_LIGHTING_VALUE - // THIS SHOULD ONLY GET CALLED FROM THE ENGINE - float GetRadiusSquared() const - { -// return radius * radius * ( HL2_BROKEN_MIN_LIGHTING_VALUE / MIN_LIGHTING_VALUE ); - return radius * radius; - } - - // THIS SHOULD ONLY GET CALLED FROM THE ENGINE - float IsRadiusGreaterThanZero() const - { - // don't bother calculating the new radius if you just want to know if it is greater than zero. - return radius > 0.0f; - } -}; - -#endif diff --git a/public/dmserializers/idmserializers.h b/public/dmserializers/idmserializers.h deleted file mode 100644 index 301f486d9..000000000 --- a/public/dmserializers/idmserializers.h +++ /dev/null @@ -1,47 +0,0 @@ -//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. =========== -// -// The copyright to the contents herein is the property of Valve, L.L.C. -// The contents may be used and/or copied only with the written permission of -// Valve, L.L.C., or in accordance with the terms and conditions stipulated in -// the agreement/contract under which the contents have been supplied. -// -// $Header: $ -// $NoKeywords: $ -// -// Main header file for the serializers DLL -// -//============================================================================= - -#ifndef IDMSERIALIZERS_H -#define IDMSERIALIZERS_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "appframework/IAppSystem.h" - - -//----------------------------------------------------------------------------- -// Interface -//----------------------------------------------------------------------------- -class IDmSerializers : public IAppSystem -{ -}; - - -//----------------------------------------------------------------------------- -// Used only by applications to hook in DmSerializers -//----------------------------------------------------------------------------- -#define DMSERIALIZERS_INTERFACE_VERSION "VDmSerializers001" - - -//----------------------------------------------------------------------------- -// Singleton -//----------------------------------------------------------------------------- -extern IDmSerializers *g_pDmSerializers; - - -#endif // DMSERIALIZERS_H - - diff --git a/public/dmxloader/dmxattribute.h b/public/dmxloader/dmxattribute.h deleted file mode 100644 index e8af5584c..000000000 --- a/public/dmxloader/dmxattribute.h +++ /dev/null @@ -1,183 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef DMXATTRIBUTE_H -#define DMXATTRIBUTE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "datamodel/dmattributetypes.h" -#include "tier1/utlvector.h" -#include "tier1/utlrbtree.h" -#include "tier1/utlsymbol.h" -#include "tier1/mempool.h" -#include "dmxloader/dmxloader.h" - - -//----------------------------------------------------------------------------- -// Forward declarations: -//----------------------------------------------------------------------------- -class CDmxElement; - - -//----------------------------------------------------------------------------- -// Attribute info, modified for use in mod code -//----------------------------------------------------------------------------- -DECLARE_ATTRIBUTE_TYPE( CDmxElement*, AT_ELEMENT, "element", value = 0; ) -DECLARE_ATTRIBUTE_ARRAY_TYPE( CDmxElement*, AT_ELEMENT_ARRAY, "element_array" ) - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CDmxAttribute -{ - DECLARE_DMX_ALLOCATOR( ); - -public: - // Returns attribute name and type - DmAttributeType_t GetType() const; - const char *GetTypeString() const; - template< class T > bool IsA() const; - - // Returns the name. NOTE: The utlsymbol - // can be turned into a string by using g_pDataModel->String(); - const char *GetName() const; - CUtlSymbol GetNameSymbol() const; - void SetName( const char *pName ); - - // Gets values - template< class T > const T& GetValue( ) const; - template< class T > const CUtlVector< T >& GetArray( ) const; - const char *GetValueString() const; - - // Sets values (+ type) - template< class T > void SetValue( const T& value ); - void SetValue( const char *pString ); - void SetValue( const void *pBuffer, size_t nLen ); - void SetValue( const CDmxAttribute *pAttribute ); - - // Method to set values in an array (just directly operate on the array) - // NOTE: This will create a new array of the appropriate type if - // the type doesn't match the current type - template< class T > CUtlVector< T >& GetArrayForEdit(); - - // Sets the attribute to its default value based on its type - void SetToDefaultValue(); - - // Convert to and from string - void SetValueFromString( const char *pValue ); - const char *GetValueAsString( char *pBuffer, size_t nBufLen ) const; - - // Gets the size of an array, returns 0 if it's not an array type - int GetArrayCount() const; - - // Read from file - bool Unserialize( DmAttributeType_t type, CUtlBuffer &buf ); - bool UnserializeElement( DmAttributeType_t type, CUtlBuffer &buf ); - bool Serialize( CUtlBuffer &buf ) const; - bool SerializeElement( int nIndex, CUtlBuffer &buf ) const; - bool SerializesOnMultipleLines() const; - - // Returns the size of the variables storing the various attribute types - static int AttributeDataSize( DmAttributeType_t type ); - -private: - CDmxAttribute( const char *pAttributeName ); - CDmxAttribute( CUtlSymbol attributeName ); - ~CDmxAttribute(); - - // Allocate, free memory for data - void AllocateDataMemory( DmAttributeType_t type ); - void FreeDataMemory( ); - - // Untyped method for setting used by unpack - void SetValue( DmAttributeType_t type, const void *pSrc, int nLen ); - - DmAttributeType_t m_Type; - CUtlSymbol m_Name; - void *m_pData; - - static CUtlSymbolTableMT s_AttributeNameSymbols; - - friend class CDmxElement; -}; - - -//----------------------------------------------------------------------------- -// Inline methods -//----------------------------------------------------------------------------- -inline DmAttributeType_t CDmxAttribute::GetType() const -{ - return m_Type; -} - -template< class T > inline bool CDmxAttribute::IsA() const -{ - return GetType() == CDmAttributeInfo< T >::ATTRIBUTE_TYPE; -} - -inline CUtlSymbol CDmxAttribute::GetNameSymbol() const -{ - return m_Name; -} - - -//----------------------------------------------------------------------------- -// Sets a value in the attribute -//----------------------------------------------------------------------------- -template< class T > void CDmxAttribute::SetValue( const T& value ) -{ - AllocateDataMemory( CDmAttributeInfo::AttributeType() ); - CopyConstruct( (T*)m_pData, value ); -} - - -//----------------------------------------------------------------------------- -// Returns data in the attribute -//----------------------------------------------------------------------------- -inline const char *CDmxAttribute::GetValueString() const -{ - if ( m_Type == AT_STRING ) - return *(CUtlString*)m_pData; - return ""; -} - -template< class T > -inline const T& CDmxAttribute::GetValue( ) const -{ - if ( CDmAttributeInfo::AttributeType() == m_Type ) - return *(T*)m_pData; - - static T defaultValue; - CDmAttributeInfo::SetDefaultValue( defaultValue ); - return defaultValue; -} - -template< class T > -inline const CUtlVector< T >& CDmxAttribute::GetArray( ) const -{ - if ( CDmAttributeInfo< CUtlVector< T > >::AttributeType() == m_Type ) - return *( CUtlVector< T > *)m_pData; - - static CUtlVector defaultArray; - return defaultArray; -} - -template< class T > -inline CUtlVector< T >& CDmxAttribute::GetArrayForEdit( ) -{ - if ( CDmAttributeInfo< CUtlVector< T > >::AttributeType() == m_Type ) - return *( CUtlVector< T > *)m_pData; - - AllocateDataMemory( CDmAttributeInfo< CUtlVector< T > >::AttributeType() ); - Construct( (CUtlVector*)m_pData ); - return *(CUtlVector< T > *)m_pData; -} - -#endif // DMXATTRIBUTE_H diff --git a/public/dmxloader/dmxelement.h b/public/dmxloader/dmxelement.h deleted file mode 100644 index db68d0ad8..000000000 --- a/public/dmxloader/dmxelement.h +++ /dev/null @@ -1,305 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef DMXELEMENT_H -#define DMXELEMENT_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "datamodel/dmattributetypes.h" -#include "tier1/utlvector.h" -#include "tier1/utlrbtree.h" -#include "tier1/utlsymbol.h" -#include "tier1/mempool.h" -#include "tier1/UtlSortVector.h" -#include "dmxloader/dmxattribute.h" - - -//----------------------------------------------------------------------------- -// Sort functor class for attributes -//----------------------------------------------------------------------------- -class CDmxAttributeLess -{ -public: - bool Less( const CDmxAttribute * pAttribute1, const CDmxAttribute *pAttribute2, void *pContext ) - { - return pAttribute1->GetNameSymbol() < pAttribute2->GetNameSymbol(); - } -}; - - -//----------------------------------------------------------------------------- -// Used to unpack elements into a structure. Does not recurse -// Also does not work with arrays. -//----------------------------------------------------------------------------- -struct DmxElementUnpackStructure_t -{ - const char *m_pAttributeName; - const char *m_pDefaultString; - DmAttributeType_t m_AttributeType; - int m_nOffset; - int m_nSize; - const void *m_pUserData; // If you want to associate some app-specific data with each field -}; - -#define DECLARE_DMXELEMENT_UNPACK() \ - template friend DmxElementUnpackStructure_t *DmxElementUnpackInit(T *); - -#define BEGIN_DMXELEMENT_UNPACK( _structName ) \ - template DmxElementUnpackStructure_t *DmxElementUnpackInit(T *); \ - template <> DmxElementUnpackStructure_t *DmxElementUnpackInit<_structName>( _structName * ); \ - namespace _structName##_UnpackInit \ - { \ - static DmxElementUnpackStructure_t *s_pUnpack = DmxElementUnpackInit( (_structName *)NULL ); \ - } \ - \ - template <> DmxElementUnpackStructure_t *DmxElementUnpackInit<_structName>( _structName * ) \ - { \ - typedef _structName DestStructType_t; \ - static DmxElementUnpackStructure_t unpack[] = \ - { \ - -#define DMXELEMENT_UNPACK_FLTX4( _attributeName, _defaultString, _varName ) \ - { _attributeName, _defaultString, CDmAttributeInfo::AttributeType(), offsetof( DestStructType_t, _varName ), sizeof( fltx4 ), NULL }, -#define DMXELEMENT_UNPACK_FIELD( _attributeName, _defaultString, _type, _varName ) \ - { _attributeName, _defaultString, CDmAttributeInfo<_type>::AttributeType(), offsetof( DestStructType_t, _varName ), sizeof( ((DestStructType_t *)0)->_varName), NULL }, -#define DMXELEMENT_UNPACK_FIELD_STRING( _attributeName, _defaultString, _varName ) \ - { _attributeName, _defaultString, AT_STRING, offsetof( DestStructType_t, _varName ), sizeof( ((DestStructType_t *)0)->_varName), NULL }, - -#define DMXELEMENT_UNPACK_FIELD_USERDATA( _attributeName, _defaultString, _type, _varName, _userData ) \ - { _attributeName, _defaultString, CDmAttributeInfo<_type>::AttributeType(), offsetof( DestStructType_t, _varName ), sizeof( ((DestStructType_t *)0)->_varName), _userData }, -#define DMXELEMENT_UNPACK_FIELD_STRING_USERDATA( _attributeName, _defaultString, _varName, _userData ) \ - { _attributeName, _defaultString, AT_STRING, offsetof( DestStructType_t, _varName ), sizeof( ((DestStructType_t *)0)->_varName), _userData }, - -#define END_DMXELEMENT_UNPACK( _structName, _varName ) \ - { NULL, NULL, AT_UNKNOWN, 0, 0, NULL } \ - }; \ - return unpack; \ - } \ - DmxElementUnpackStructure_t *_varName = _structName##_UnpackInit::s_pUnpack; - -#define END_DMXELEMENT_UNPACK_TEMPLATE( _structName, _varName ) \ - { NULL, NULL, AT_UNKNOWN, 0, 0, NULL } \ - }; \ - return unpack; \ - } \ - template<> DmxElementUnpackStructure_t *_varName = _structName##_UnpackInit::s_pUnpack; - - -//----------------------------------------------------------------------------- -// Element used to read dmx files from mod code. Similar to keyvalues. -//----------------------------------------------------------------------------- -class CDmxElement -{ - DECLARE_DMX_ALLOCATOR( ); - -public: - bool HasAttribute( const char *pAttributeName ) const; - CDmxAttribute *GetAttribute( const char *pAttributeName ); - const CDmxAttribute *GetAttribute( const char *pAttributeName ) const; - int AttributeCount() const; - CDmxAttribute *GetAttribute( int nIndex ); - const CDmxAttribute *GetAttribute( int nIndex ) const; - CUtlSymbol GetType() const; - const char* GetTypeString() const; - const char* GetName() const; - const DmObjectId_t &GetId() const; - - // Add+remove+rename can only occur during lock - // NOTE: AddAttribute will find or add; returning an existing attribute if - // one with the appropriate name exists - void LockForChanges( bool bLock ); - CDmxAttribute *AddAttribute( const char *pAttributeName ); - void RemoveAttribute( const char *pAttributeName ); - void RemoveAttributeByPtr( CDmxAttribute *pAttribute ); - void RemoveAllAttributes(); - void RenameAttribute( const char *pAttributeName, const char *pNewName ); - - // Simple methods to read attributes - const char *GetValueString( const char *pAttributeName ) const; - template< class T > const T& GetValue( const char *pAttributeName ) const; - template< class T > const T& GetValue( const char *pAttributeName, const T& defaultValue ) const; - - template< class T > const CUtlVector& GetArray( const char *pAttributeName ) const; - template< class T > const CUtlVector& GetArray( const char *pAttributeName, const CUtlVector& defaultValue ) const; - - // Set methods - CDmxAttribute* SetValue( const char *pAttributeName, const char *pString ); - CDmxAttribute* SetValue( const char *pAttributeName, void *pBuffer, int nLen ); - template< class T > CDmxAttribute* SetValue( const char *pAttributeName, const T& value ); - - // Method to unpack data into a structure - void UnpackIntoStructure( void *pData, const DmxElementUnpackStructure_t *pUnpack ) const; - - // Creates attributes based on the unpack structure - void AddAttributesFromStructure( const void *pData, const DmxElementUnpackStructure_t *pUnpack ); - -private: - typedef CUtlSortVector< CDmxAttribute*, CDmxAttributeLess > AttributeList_t; - - CDmxElement( const char *pType ); - ~CDmxElement(); - - // Removes all elements recursively - void RemoveAllElementsRecursive(); - - // Adds elements to delete to the deletion list - void AddElementsToDelete( CUtlVector< CDmxElement * >& elementsToDelete ); - - // Sorts the vector when a change has occurred - void Resort( ) const; - - // Finds an attribute by name - int FindAttribute( const char *pAttributeName ) const; - int FindAttribute( CUtlSymbol attributeName ) const; - - // Sets the object id - void SetId( const DmObjectId_t &id ); - - // Are we locked? - bool IsLocked() const; - - AttributeList_t m_Attributes; - DmObjectId_t m_Id; // We need this strictly because we support serialization - CUtlSymbol m_Type; - char m_nLockCount; - mutable bool m_bResortNeeded : 1; - bool m_bIsMarkedForDeletion : 1; - - static CUtlSymbolTableMT s_TypeSymbols; - - friend class CDmxSerializer; - friend class CDmxSerializerKeyValues2; - friend void CleanupDMX( CDmxElement* pElement ); - friend CDmxElement* CreateDmxElement( const char *pType ); -}; - - -//----------------------------------------------------------------------------- -// inline methods -//----------------------------------------------------------------------------- - -// Are we locked? -inline bool CDmxElement::IsLocked() const -{ - return m_nLockCount > 0; -} - -inline const char *CDmxElement::GetValueString( const char *pAttributeName ) const -{ - const CDmxAttribute* pAttribute = GetAttribute( pAttributeName ); - if ( pAttribute ) - return pAttribute->GetValueString(); - return ""; -} - -template< class T > -inline const T& CDmxElement::GetValue( const char *pAttributeName ) const -{ - const CDmxAttribute* pAttribute = GetAttribute( pAttributeName ); - if ( pAttribute ) - return pAttribute->GetValue(); - - static T defaultValue; - CDmAttributeInfo::SetDefaultValue( defaultValue ); - return defaultValue; -} - -template< class T > -inline const T& CDmxElement::GetValue( const char *pAttributeName, const T& defaultValue ) const -{ - const CDmxAttribute* pAttribute = GetAttribute( pAttributeName ); - if ( pAttribute ) - return pAttribute->GetValue(); - return defaultValue; -} - -template< class T > -inline const CUtlVector& CDmxElement::GetArray( const char *pAttributeName ) const -{ - const CDmxAttribute* pAttribute = GetAttribute( pAttributeName ); - if ( pAttribute ) - return pAttribute->GetArray(); - - static CUtlVector defaultValue; - return defaultValue; -} - -template< class T > -inline const CUtlVector& CDmxElement::GetArray( const char *pAttributeName, const CUtlVector& defaultValue ) const -{ - const CDmxAttribute* pAttribute = GetAttribute( pAttributeName ); - if ( pAttribute ) - return pAttribute->GetArray(); - return defaultValue; -} - - -//----------------------------------------------------------------------------- -// Creates a dmx element -//----------------------------------------------------------------------------- -CDmxElement* CreateDmxElement( const char *pType ); - - -//----------------------------------------------------------------------------- -// Helper class to lock elements for changes -//----------------------------------------------------------------------------- -class CDmxElementModifyScope -{ -public: - CDmxElementModifyScope( CDmxElement *pElement ) : m_pElement( pElement ) - { - m_pElement->LockForChanges( true ); - } - ~CDmxElementModifyScope() - { - Release(); - } - void Release() - { - if ( m_pElement ) - { - m_pElement->LockForChanges( false ); - m_pElement = NULL; - } - } -private: - CDmxElement *m_pElement; -}; - - -//----------------------------------------------------------------------------- -// Set methods -//----------------------------------------------------------------------------- -inline CDmxAttribute* CDmxElement::SetValue( const char *pAttributeName, const char *pString ) -{ - CDmxElementModifyScope modify( this ); - CDmxAttribute *pAttribute = AddAttribute( pAttributeName ); - pAttribute->SetValue( pString ); - return pAttribute; -} - -inline CDmxAttribute* CDmxElement::SetValue( const char *pAttributeName, void *pBuffer, int nLen ) -{ - CDmxElementModifyScope modify( this ); - CDmxAttribute *pAttribute = AddAttribute( pAttributeName ); - pAttribute->SetValue( pBuffer, nLen ); - return pAttribute; -} - -template< class T > -inline CDmxAttribute* CDmxElement::SetValue( const char *pAttributeName, const T& value ) -{ - CDmxElementModifyScope modify( this ); - CDmxAttribute *pAttribute = AddAttribute( pAttributeName ); - pAttribute->SetValue( value ); - return pAttribute; -} - - -#endif // DMXELEMENT_H diff --git a/public/dmxloader/dmxloader.h b/public/dmxloader/dmxloader.h deleted file mode 100644 index 8c1b46d2c..000000000 --- a/public/dmxloader/dmxloader.h +++ /dev/null @@ -1,72 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef DMXLOADER_H -#define DMXLOADER_H - -#ifdef _WIN32 -#pragma once -#endif - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class CUtlBuffer; -class CDmxElement; - - -//----------------------------------------------------------------------------- -// Serialization/Unserialization -//----------------------------------------------------------------------------- -bool SerializeDMX( CUtlBuffer &buf, CDmxElement *pRoot, const char *pFileName = NULL ); -bool SerializeDMX( const char *pFileName, const char *pPathID, bool bTextMode, CDmxElement *pRoot ); - -bool UnserializeDMX( CUtlBuffer &buf, CDmxElement **ppRoot, const char *pFileName = NULL ); -bool UnserializeDMX( const char *pFileName, const char *pPathID, bool bTextMode, CDmxElement **ppRoot ); - -//----------------------------------------------------------------------------- -// DMX elements/attributes can only be accessed inside a dmx context -//----------------------------------------------------------------------------- -void BeginDMXContext( ); -void EndDMXContext( bool bDecommitMemory ); -void DecommitDMXMemory(); - - -//----------------------------------------------------------------------------- -// Helper macro -//----------------------------------------------------------------------------- -class CDMXContextHelper -{ -public: - CDMXContextHelper( bool bDecommitMemory ) { m_bDecommitMemory = bDecommitMemory; BeginDMXContext(); } - ~CDMXContextHelper() { EndDMXContext( m_bDecommitMemory ); } - -private: - bool m_bDecommitMemory; -}; - -#define DECLARE_DMX_CONTEXT( ) CDMXContextHelper __dmxContextHelper( true ); -#define DECLARE_DMX_CONTEXT_NODECOMMIT( ) CDMXContextHelper __dmxContextHelper( false ); -#define DECLARE_DMX_CONTEXT_DECOMMIT( _decommit ) CDMXContextHelper __dmxContextHelper( _decommit ); - - -//----------------------------------------------------------------------------- -// Used for allocation. All will be freed when we leave the DMX context -//----------------------------------------------------------------------------- -void* DMXAlloc( size_t size ); - - -//----------------------------------------------------------------------------- -// Helper macro -//----------------------------------------------------------------------------- -#define DECLARE_DMX_ALLOCATOR( ) \ - public: \ - inline void* operator new( size_t size ) { MEM_ALLOC_CREDIT_( "DMXAlloc" ); return DMXAlloc(size); } \ - inline void* operator new( size_t size, int nBlockUse, const char *pFileName, int nLine ) { MEM_ALLOC_CREDIT_( "DMXAlloc" ); return DMXAlloc(size); } \ - inline void operator delete( void* p ) { } \ - inline void operator delete( void* p, int nBlockUse, const char *pFileName, int nLine ) { } \ - -#endif // DMXLOADER_H diff --git a/public/dt_common.h b/public/dt_common.h deleted file mode 100644 index 982d65e71..000000000 --- a/public/dt_common.h +++ /dev/null @@ -1,196 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef DATATABLE_COMMON_H -#define DATATABLE_COMMON_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "basetypes.h" -#include "tier0/dbg.h" -#include "tier1/strtools.h" -#include - -// Max number of properties in a datatable and its children. -#define MAX_DATATABLES 1024 // must be a power of 2. -#define MAX_DATATABLE_PROPS 4096 - -#define MAX_ARRAY_ELEMENTS 2048 // a network array should have more that 1024 elements - -#define HIGH_DEFAULT -121121.121121f - -#define BITS_FULLRES -1 // Use the full resolution of the type being encoded. -#define BITS_WORLDCOORD -2 // Encode as a world coordinate. - -#define DT_MAX_STRING_BITS 9 -#define DT_MAX_STRING_BUFFERSIZE (1<varName ) - -// Gets the size of a variable in a class. -#define PROPSIZEOF(className, varName) sizeof(((className*)0)->varName) - - -// SendProp::m_Flags. -#define SPROP_UNSIGNED (1<<0) // Unsigned integer data. - -#define SPROP_COORD (1<<1) // If this is set, the float/vector is treated like a world coordinate. - // Note that the bit count is ignored in this case. - -#define SPROP_NOSCALE (1<<2) // For floating point, don't scale into range, just take value as is. - -#define SPROP_ROUNDDOWN (1<<3) // For floating point, limit high value to range minus one bit unit - -#define SPROP_ROUNDUP (1<<4) // For floating point, limit low value to range minus one bit unit - -#define SPROP_NORMAL (1<<5) // If this is set, the vector is treated like a normal (only valid for vectors) - -#define SPROP_EXCLUDE (1<<6) // This is an exclude prop (not excludED, but it points at another prop to be excluded). - -#define SPROP_XYZE (1<<7) // Use XYZ/Exponent encoding for vectors. - -#define SPROP_INSIDEARRAY (1<<8) // This tells us that the property is inside an array, so it shouldn't be put into the - // flattened property list. Its array will point at it when it needs to. - -#define SPROP_PROXY_ALWAYS_YES (1<<9) // Set for datatable props using one of the default datatable proxies like - // SendProxy_DataTableToDataTable that always send the data to all clients. - -#define SPROP_CHANGES_OFTEN (1<<10) // this is an often changed field, moved to head of sendtable so it gets a small index - -#define SPROP_IS_A_VECTOR_ELEM (1<<11) // Set automatically if SPROP_VECTORELEM is used. - -#define SPROP_COLLAPSIBLE (1<<12) // Set automatically if it's a datatable with an offset of 0 that doesn't change the pointer - // (ie: for all automatically-chained base classes). - // In this case, it can get rid of this SendPropDataTable altogether and spare the - // trouble of walking the hierarchy more than necessary. - -#define SPROP_COORD_MP (1<<13) // Like SPROP_COORD, but special handling for multiplayer games -#define SPROP_COORD_MP_LOWPRECISION (1<<14) // Like SPROP_COORD, but special handling for multiplayer games where the fractional component only gets a 3 bits instead of 5 -#define SPROP_COORD_MP_INTEGRAL (1<<15) // SPROP_COORD_MP, but coordinates are rounded to integral boundaries -#define SPROP_VARINT SPROP_NORMAL - -#define SPROP_NUMFLAGBITS_NETWORKED 16 - -// This is server side only, it's used to mark properties whose SendProxy_* functions encode against gpGlobals->tickcount (the only ones that currently do this are -// m_flAnimTime and m_flSimulationTime. MODs shouldn't need to mess with this probably -#define SPROP_ENCODED_AGAINST_TICKCOUNT (1<<16) - -// See SPROP_NUMFLAGBITS_NETWORKED for the ones which are networked -#define SPROP_NUMFLAGBITS 17 - -// Used by the SendProp and RecvProp functions to disable debug checks on type sizes. -#define SIZEOF_IGNORE -1 - - -// Use this to extern send and receive datatables, and reference them. -#define EXTERN_SEND_TABLE(tableName) namespace tableName {extern SendTable g_SendTable;} -#define EXTERN_RECV_TABLE(tableName) namespace tableName {extern RecvTable g_RecvTable;} - -#define REFERENCE_SEND_TABLE(tableName) tableName::g_SendTable -#define REFERENCE_RECV_TABLE(tableName) tableName::g_RecvTable - - -class SendProp; - - -typedef enum -{ - DPT_Int=0, - DPT_Float, - DPT_Vector, - DPT_VectorXY, - DPT_String, - DPT_Array, // An array of the base types (can't be of datatables). - DPT_DataTable, -#if 0 // We can't ship this since it changes the size of DTVariant to be 20 bytes instead of 16 and that breaks MODs!!! - DPT_Quaternion, -#endif - DPT_NUMSendPropTypes -} SendPropType; - - -class DVariant -{ -public: - DVariant() {m_Type = DPT_Float;} - DVariant(float val) {m_Type = DPT_Float; m_Float = val;} - - const char *ToString() - { - static char text[128]; - - switch ( m_Type ) - { - case DPT_Int : - Q_snprintf( text, sizeof(text), "%i", m_Int ); - break; - case DPT_Float : - Q_snprintf( text, sizeof(text), "%.3f", m_Float ); - break; - case DPT_Vector : - Q_snprintf( text, sizeof(text), "(%.3f,%.3f,%.3f)", - m_Vector[0], m_Vector[1], m_Vector[2] ); - break; -#if 0 // We can't ship this since it changes the size of DTVariant to be 20 bytes instead of 16 and that breaks MODs!!! - case DPT_Quaternion : - Q_snprintf( text, sizeof(text), "(%.3f,%.3f,%.3f %.3f)", - m_Vector[0], m_Vector[1], m_Vector[2], m_Vector[3] ); - break; -#endif - case DPT_String : - if ( m_pString ) - return m_pString; - else - return "NULL"; - break; - case DPT_Array : - Q_snprintf( text, sizeof(text), "Array" ); - break; - case DPT_DataTable : - Q_snprintf( text, sizeof(text), "DataTable" ); - break; - default : - Q_snprintf( text, sizeof(text), "DVariant type %i unknown", m_Type ); - break; - } - - return text; - } - - union - { - float m_Float; - long m_Int; - char *m_pString; - void *m_pData; // For DataTables. -#if 0 // We can't ship this since it changes the size of DTVariant to be 20 bytes instead of 16 and that breaks MODs!!! - float m_Vector[4]; -#else - float m_Vector[3]; -#endif - }; - SendPropType m_Type; -}; - - -// This can be used to set the # of bits used to transmit a number between 0 and nMaxElements-1. -inline int NumBitsForCount( int nMaxElements ) -{ - int nBits = 0; - while ( nMaxElements > 0 ) - { - ++nBits; - nMaxElements >>= 1; - } - return nBits; -} - - -#endif // DATATABLE_COMMON_H diff --git a/public/dt_recv.cpp b/public/dt_recv.cpp deleted file mode 100644 index 9fdc289b8..000000000 --- a/public/dt_recv.cpp +++ /dev/null @@ -1,479 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=====================================================================================// - -#include "dt_recv.h" -#include "mathlib/vector.h" -#include "tier1/strtools.h" -#include "dt_utlvector_common.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#if !defined(_STATIC_LINKED) || defined(CLIENT_DLL) - -const char *s_ClientElementNames[MAX_ARRAY_ELEMENTS] = -{ - "000", "001", "002", "003", "004", "005", "006", "007", "008", "009", - "010", "011", "012", "013", "014", "015", "016", "017", "018", "019", - "020", "021", "022", "023", "024", "025", "026", "027", "028", "029", - "030", "031", "032", "033", "034", "035", "036", "037", "038", "039", - "040", "041", "042", "043", "044", "045", "046", "047", "048", "049", - "050", "051", "052", "053", "054", "055", "056", "057", "058", "059", - "060", "061", "062", "063", "064", "065", "066", "067", "068", "069", - "070", "071", "072", "073", "074", "075", "076", "077", "078", "079", - "080", "081", "082", "083", "084", "085", "086", "087", "088", "089", - "090", "091", "092", "093", "094", "095", "096", "097", "098", "099", - "100", "101", "102", "103", "104", "105", "106", "107", "108", "109", - "110", "111", "112", "113", "114", "115", "116", "117", "118", "119", - "120", "121", "122", "123", "124", "125", "126", "127", "128", "129", - "130", "131", "132", "133", "134", "135", "136", "137", "138", "139", - "140", "141", "142", "143", "144", "145", "146", "147", "148", "149", - "150", "151", "152", "153", "154", "155", "156", "157", "158", "159", - "160", "161", "162", "163", "164", "165", "166", "167", "168", "169", - "170", "171", "172", "173", "174", "175", "176", "177", "178", "179", - "180", "181", "182", "183", "184", "185", "186", "187", "188", "189", - "190", "191", "192", "193", "194", "195", "196", "197", "198", "199", - "200", "201", "202", "203", "204", "205", "206", "207", "208", "209", - "210", "211", "212", "213", "214", "215", "216", "217", "218", "219", - "220", "221", "222", "223", "224", "225", "226", "227", "228", "229", - "230", "231", "232", "233", "234", "235", "236", "237", "238", "239", - "240", "241", "242", "243", "244", "245", "246", "247", "248", "249", - "250", "251", "252", "253", "254", "255", "256", "257", "258", "259", - "260", "261", "262", "263", "264", "265", "266", "267", "268", "269", - "270", "271", "272", "273", "274", "275", "276", "277", "278", "279", - "280", "281", "282", "283", "284", "285", "286", "287", "288", "289", - "290", "291", "292", "293", "294", "295", "296", "297", "298", "299", - "300", "301", "302", "303", "304", "305", "306", "307", "308", "309", - "310", "311", "312", "313", "314", "315", "316", "317", "318", "319", - "320", "321", "322", "323", "324", "325", "326", "327", "328", "329", - "330", "331", "332", "333", "334", "335", "336", "337", "338", "339", - "340", "341", "342", "343", "344", "345", "346", "347", "348", "349", - "350", "351", "352", "353", "354", "355", "356", "357", "358", "359", - "360", "361", "362", "363", "364", "365", "366", "367", "368", "369", - "370", "371", "372", "373", "374", "375", "376", "377", "378", "379", - "380", "381", "382", "383", "384", "385", "386", "387", "388", "389", - "390", "391", "392", "393", "394", "395", "396", "397", "398", "399", - "400", "401", "402", "403", "404", "405", "406", "407", "408", "409", - "410", "411", "412", "413", "414", "415", "416", "417", "418", "419", - "420", "421", "422", "423", "424", "425", "426", "427", "428", "429", - "430", "431", "432", "433", "434", "435", "436", "437", "438", "439", - "440", "441", "442", "443", "444", "445", "446", "447", "448", "449", - "450", "451", "452", "453", "454", "455", "456", "457", "458", "459", - "460", "461", "462", "463", "464", "465", "466", "467", "468", "469", - "470", "471", "472", "473", "474", "475", "476", "477", "478", "479", - "480", "481", "482", "483", "484", "485", "486", "487", "488", "489", - "490", "491", "492", "493", "494", "495", "496", "497", "498", "499", - "500", "501", "502", "503", "504", "505", "506", "507", "508", "509", - "510", "511", "512", "513", "514", "515", "516", "517", "518", "519", - "520", "521", "522", "523", "524", "525", "526", "527", "528", "529", - "530", "531", "532", "533", "534", "535", "536", "537", "538", "539", - "540", "541", "542", "543", "544", "545", "546", "547", "548", "549", - "550", "551", "552", "553", "554", "555", "556", "557", "558", "559", - "560", "561", "562", "563", "564", "565", "566", "567", "568", "569", - "570", "571", "572", "573", "574", "575", "576", "577", "578", "579", - "580", "581", "582", "583", "584", "585", "586", "587", "588", "589", - "590", "591", "592", "593", "594", "595", "596", "597", "598", "599", - "600", "601", "602", "603", "604", "605", "606", "607", "608", "609", - "610", "611", "612", "613", "614", "615", "616", "617", "618", "619", - "620", "621", "622", "623", "624", "625", "626", "627", "628", "629", - "630", "631", "632", "633", "634", "635", "636", "637", "638", "639", - "640", "641", "642", "643", "644", "645", "646", "647", "648", "649", - "650", "651", "652", "653", "654", "655", "656", "657", "658", "659", - "660", "661", "662", "663", "664", "665", "666", "667", "668", "669", - "670", "671", "672", "673", "674", "675", "676", "677", "678", "679", - "680", "681", "682", "683", "684", "685", "686", "687", "688", "689", - "690", "691", "692", "693", "694", "695", "696", "697", "698", "699", - "700", "701", "702", "703", "704", "705", "706", "707", "708", "709", - "710", "711", "712", "713", "714", "715", "716", "717", "718", "719", - "720", "721", "722", "723", "724", "725", "726", "727", "728", "729", - "730", "731", "732", "733", "734", "735", "736", "737", "738", "739", - "740", "741", "742", "743", "744", "745", "746", "747", "748", "749", - "750", "751", "752", "753", "754", "755", "756", "757", "758", "759", - "760", "761", "762", "763", "764", "765", "766", "767", "768", "769", - "770", "771", "772", "773", "774", "775", "776", "777", "778", "779", - "780", "781", "782", "783", "784", "785", "786", "787", "788", "789", - "790", "791", "792", "793", "794", "795", "796", "797", "798", "799", - "800", "801", "802", "803", "804", "805", "806", "807", "808", "809", - "810", "811", "812", "813", "814", "815", "816", "817", "818", "819", - "820", "821", "822", "823", "824", "825", "826", "827", "828", "829", - "830", "831", "832", "833", "834", "835", "836", "837", "838", "839", - "840", "841", "842", "843", "844", "845", "846", "847", "848", "849", - "850", "851", "852", "853", "854", "855", "856", "857", "858", "859", - "860", "861", "862", "863", "864", "865", "866", "867", "868", "869", - "870", "871", "872", "873", "874", "875", "876", "877", "878", "879", - "880", "881", "882", "883", "884", "885", "886", "887", "888", "889", - "890", "891", "892", "893", "894", "895", "896", "897", "898", "899", - "900", "901", "902", "903", "904", "905", "906", "907", "908", "909", - "910", "911", "912", "913", "914", "915", "916", "917", "918", "919", - "920", "921", "922", "923", "924", "925", "926", "927", "928", "929", - "930", "931", "932", "933", "934", "935", "936", "937", "938", "939", - "940", "941", "942", "943", "944", "945", "946", "947", "948", "949", - "950", "951", "952", "953", "954", "955", "956", "957", "958", "959", - "960", "961", "962", "963", "964", "965", "966", "967", "968", "969", - "970", "971", "972", "973", "974", "975", "976", "977", "978", "979", - "980", "981", "982", "983", "984", "985", "986", "987", "988", "989", - "990", "991", "992", "993", "994", "995", "996", "997", "998", "999", - "1000", "1001", "1002", "1003", "1004", "1005", "1006", "1007", "1008", "1009", - "1010", "1011", "1012", "1013", "1014", "1015", "1016", "1017", "1018", "1019", - "1020", "1021", "1022", "1023" - -}; - -CStandardRecvProxies::CStandardRecvProxies() -{ - m_Int32ToInt8 = RecvProxy_Int32ToInt8; - m_Int32ToInt16 = RecvProxy_Int32ToInt16; - m_Int32ToInt32 = RecvProxy_Int32ToInt32; - m_FloatToFloat = RecvProxy_FloatToFloat; - m_VectorToVector = RecvProxy_VectorToVector; -} - -CStandardRecvProxies g_StandardRecvProxies; - - -// ---------------------------------------------------------------------- // -// RecvProp. -// ---------------------------------------------------------------------- // -RecvProp::RecvProp() -{ - m_pExtraData = NULL; - m_pVarName = NULL; - m_Offset = 0; - m_RecvType = DPT_Int; - m_Flags = 0; - m_ProxyFn = NULL; - m_DataTableProxyFn = NULL; - m_pDataTable = NULL; - m_nElements = 1; - m_ElementStride = -1; - m_pArrayProp = NULL; - m_ArrayLengthProxy = NULL; - m_bInsideArray = false; -} - -// ---------------------------------------------------------------------- // -// RecvTable. -// ---------------------------------------------------------------------- // -RecvTable::RecvTable() -{ - Construct( NULL, 0, NULL ); -} - -RecvTable::RecvTable(RecvProp *pProps, int nProps, const char *pNetTableName) -{ - Construct( pProps, nProps, pNetTableName ); -} - -RecvTable::~RecvTable() -{ -} - -void RecvTable::Construct( RecvProp *pProps, int nProps, const char *pNetTableName ) -{ - m_pProps = pProps; - m_nProps = nProps; - m_pDecoder = NULL; - m_pNetTableName = pNetTableName; - m_bInitialized = false; - m_bInMainList = false; -} - - -// ---------------------------------------------------------------------- // -// Prop setup functions (for building tables). -// ---------------------------------------------------------------------- // - -RecvProp RecvPropFloat( - const char *pVarName, - int offset, - int sizeofVar, - int flags, - RecvVarProxyFn varProxy - ) -{ - RecvProp ret; - -#ifdef _DEBUG - if ( varProxy == RecvProxy_FloatToFloat ) - { - Assert( sizeofVar == 0 || sizeofVar == 4 ); - } -#endif - - ret.m_pVarName = pVarName; - ret.SetOffset( offset ); - ret.m_RecvType = DPT_Float; - ret.m_Flags = flags; - ret.SetProxyFn( varProxy ); - - return ret; -} - -RecvProp RecvPropVector( - const char *pVarName, - int offset, - int sizeofVar, - int flags, - RecvVarProxyFn varProxy - ) -{ - RecvProp ret; - -#ifdef _DEBUG - if ( varProxy == RecvProxy_VectorToVector ) - { - Assert( sizeofVar == sizeof( Vector ) ); - } -#endif - - ret.m_pVarName = pVarName; - ret.SetOffset( offset ); - ret.m_RecvType = DPT_Vector; - ret.m_Flags = flags; - ret.SetProxyFn( varProxy ); - - return ret; -} - -#if 0 // We can't ship this since it changes the size of DTVariant to be 20 bytes instead of 16 and that breaks MODs!!! - -RecvProp RecvPropQuaternion( - const char *pVarName, - int offset, - int sizeofVar, // Handled by RECVINFO macro, but set to SIZEOF_IGNORE if you don't want to bother. - int flags, - RecvVarProxyFn varProxy - ) -{ - RecvProp ret; - -#ifdef _DEBUG - if ( varProxy == RecvProxy_QuaternionToQuaternion ) - { - Assert( sizeofVar == sizeof( Quaternion ) ); - } -#endif - - ret.m_pVarName = pVarName; - ret.SetOffset( offset ); - ret.m_RecvType = DPT_Quaternion; - ret.m_Flags = flags; - ret.SetProxyFn( varProxy ); - - return ret; -} -#endif - -RecvProp RecvPropInt( - const char *pVarName, - int offset, - int sizeofVar, - int flags, - RecvVarProxyFn varProxy - ) -{ - RecvProp ret; - - // If they didn't specify a proxy, then figure out what type we're writing to. - if (varProxy == NULL) - { - if (sizeofVar == 1) - { - varProxy = RecvProxy_Int32ToInt8; - } - else if (sizeofVar == 2) - { - varProxy = RecvProxy_Int32ToInt16; - } - else if (sizeofVar == 4) - { - varProxy = RecvProxy_Int32ToInt32; - } - else - { - Assert(!"RecvPropInt var has invalid size"); - varProxy = RecvProxy_Int32ToInt8; // safest one... - } - } - - ret.m_pVarName = pVarName; - ret.SetOffset( offset ); - ret.m_RecvType = DPT_Int; - ret.m_Flags = flags; - ret.SetProxyFn( varProxy ); - - return ret; -} - -RecvProp RecvPropString( - const char *pVarName, - int offset, - int bufferSize, - int flags, - RecvVarProxyFn varProxy - ) -{ - RecvProp ret; - - ret.m_pVarName = pVarName; - ret.SetOffset( offset ); - ret.m_RecvType = DPT_String; - ret.m_Flags = flags; - ret.m_StringBufferSize = bufferSize; - ret.SetProxyFn( varProxy ); - - return ret; -} - -RecvProp RecvPropDataTable( - const char *pVarName, - int offset, - int flags, - RecvTable *pTable, - DataTableRecvVarProxyFn varProxy - ) -{ - RecvProp ret; - - ret.m_pVarName = pVarName; - ret.SetOffset( offset ); - ret.m_RecvType = DPT_DataTable; - ret.m_Flags = flags; - ret.SetDataTableProxyFn( varProxy ); - ret.SetDataTable( pTable ); - - return ret; -} - -RecvProp RecvPropArray3( - const char *pVarName, - int offset, - int sizeofVar, - int elements, - RecvProp pArrayProp, - DataTableRecvVarProxyFn varProxy - ) -{ - RecvProp ret; - - Assert( elements <= MAX_ARRAY_ELEMENTS ); - - ret.m_pVarName = pVarName; - ret.SetOffset( offset ); - ret.m_RecvType = DPT_DataTable; - ret.SetDataTableProxyFn( varProxy ); - - RecvProp *pProps = new RecvProp[elements]; // TODO free that again - - const char *pParentArrayPropName = AllocateStringHelper( "%s", pVarName ); - - for ( int i=0; i < elements; i++ ) - { - pProps[i] = pArrayProp; // copy basic property settings - pProps[i].SetOffset( i * sizeofVar ); // adjust offset - pProps[i].m_pVarName = s_ClientElementNames[i]; // give unique name - pProps[i].SetParentArrayPropName( pParentArrayPropName ); // For debugging... - } - - RecvTable *pTable = new RecvTable( pProps, elements, pVarName ); // TODO free that again - - ret.SetDataTable( pTable ); - - return ret; -} - -RecvProp InternalRecvPropArray( - const int elementCount, - const int elementStride, - const char *pName, - ArrayLengthRecvProxyFn proxy - ) -{ - RecvProp ret; - - ret.InitArray( elementCount, elementStride ); - ret.m_pVarName = pName; - ret.SetArrayLengthProxy( proxy ); - - return ret; -} - - -// ---------------------------------------------------------------------- // -// Proxies. -// ---------------------------------------------------------------------- // - -void RecvProxy_FloatToFloat( const CRecvProxyData *pData, void *pStruct, void *pOut ) -{ - Assert( IsFinite( pData->m_Value.m_Float ) ); - *((float*)pOut) = pData->m_Value.m_Float; -} - -void RecvProxy_VectorToVector( const CRecvProxyData *pData, void *pStruct, void *pOut ) -{ - const float *v = pData->m_Value.m_Vector; - - Assert( IsFinite( v[0] ) && IsFinite( v[1] ) && IsFinite( v[2] ) ); - ((float*)pOut)[0] = v[0]; - ((float*)pOut)[1] = v[1]; - ((float*)pOut)[2] = v[2]; -} - -void RecvProxy_QuaternionToQuaternion( const CRecvProxyData *pData, void *pStruct, void *pOut ) -{ - const float *v = pData->m_Value.m_Vector; - - Assert( IsFinite( v[0] ) && IsFinite( v[1] ) && IsFinite( v[2] ) && IsFinite( v[3] ) ); - ((float*)pOut)[0] = v[0]; - ((float*)pOut)[1] = v[1]; - ((float*)pOut)[2] = v[2]; - ((float*)pOut)[3] = v[3]; -} - -void RecvProxy_Int32ToInt8( const CRecvProxyData *pData, void *pStruct, void *pOut ) -{ - *((unsigned char*)pOut) = (unsigned char)pData->m_Value.m_Int; -} - -void RecvProxy_Int32ToInt16( const CRecvProxyData *pData, void *pStruct, void *pOut ) -{ - *((unsigned short*)pOut) = (unsigned short)pData->m_Value.m_Int; -} - -void RecvProxy_Int32ToInt32( const CRecvProxyData *pData, void *pStruct, void *pOut ) -{ - *((unsigned long*)pOut) = (unsigned long)pData->m_Value.m_Int; -} - -void RecvProxy_StringToString( const CRecvProxyData *pData, void *pStruct, void *pOut ) -{ - char *pStrOut = (char*)pOut; - if ( pData->m_pRecvProp->m_StringBufferSize <= 0 ) - { - return; - } - - for ( int i=0; i < pData->m_pRecvProp->m_StringBufferSize; i++ ) - { - pStrOut[i] = pData->m_Value.m_pString[i]; - if ( pStrOut[i] == 0 ) - break; - } - - pStrOut[pData->m_pRecvProp->m_StringBufferSize-1] = 0; -} - -void DataTableRecvProxy_StaticDataTable( const RecvProp *pProp, void **pOut, void *pData, int objectID ) -{ - *pOut = pData; -} - -void DataTableRecvProxy_PointerDataTable( const RecvProp *pProp, void **pOut, void *pData, int objectID ) -{ - *pOut = *((void**)pData); -} - -#endif diff --git a/public/dt_recv.h b/public/dt_recv.h deleted file mode 100644 index 93519dd18..000000000 --- a/public/dt_recv.h +++ /dev/null @@ -1,558 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef DATATABLE_RECV_H -#define DATATABLE_RECV_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "dt_common.h" -#include "tier0/dbg.h" - - -#define ADDRESSPROXY_NONE -1 - - -class RecvTable; -class RecvProp; - - -// This is passed into RecvProxy functions. -class CRecvProxyData -{ -public: - const RecvProp *m_pRecvProp; // The property it's receiving. - - DVariant m_Value; // The value given to you to store. - - int m_iElement; // Which array element you're getting. - - int m_ObjectID; // The object being referred to. -}; - - -//----------------------------------------------------------------------------- -// pStruct = the base structure of the datatable this variable is in (like C_BaseEntity) -// pOut = the variable that this this proxy represents (like C_BaseEntity::m_SomeValue). -// -// Convert the network-standard-type value in m_Value into your own format in pStruct/pOut. -//----------------------------------------------------------------------------- -typedef void (*RecvVarProxyFn)( const CRecvProxyData *pData, void *pStruct, void *pOut ); - -// ------------------------------------------------------------------------ // -// ArrayLengthRecvProxies are optionally used to get the length of the -// incoming array when it changes. -// ------------------------------------------------------------------------ // -typedef void (*ArrayLengthRecvProxyFn)( void *pStruct, int objectID, int currentArrayLength ); - - -// NOTE: DataTable receive proxies work differently than the other proxies. -// pData points at the object + the recv table's offset. -// pOut should be set to the location of the object to unpack the data table into. -// If the parent object just contains the child object, the default proxy just does *pOut = pData. -// If the parent object points at the child object, you need to dereference the pointer here. -// NOTE: don't ever return null from a DataTable receive proxy function. Bad things will happen. -typedef void (*DataTableRecvVarProxyFn)(const RecvProp *pProp, void **pOut, void *pData, int objectID); - - -// This is used to fork over the standard proxy functions to the engine so it can -// make some optimizations. -class CStandardRecvProxies -{ -public: - CStandardRecvProxies(); - - RecvVarProxyFn m_Int32ToInt8; - RecvVarProxyFn m_Int32ToInt16; - RecvVarProxyFn m_Int32ToInt32; - RecvVarProxyFn m_FloatToFloat; - RecvVarProxyFn m_VectorToVector; -}; -extern CStandardRecvProxies g_StandardRecvProxies; - - -class CRecvDecoder; - - -class RecvProp -{ -// This info comes from the receive data table. -public: - RecvProp(); - - void InitArray( int nElements, int elementStride ); - - int GetNumElements() const; - void SetNumElements( int nElements ); - - int GetElementStride() const; - void SetElementStride( int stride ); - - int GetFlags() const; - - const char* GetName() const; - SendPropType GetType() const; - - RecvTable* GetDataTable() const; - void SetDataTable( RecvTable *pTable ); - - RecvVarProxyFn GetProxyFn() const; - void SetProxyFn( RecvVarProxyFn fn ); - - DataTableRecvVarProxyFn GetDataTableProxyFn() const; - void SetDataTableProxyFn( DataTableRecvVarProxyFn fn ); - - int GetOffset() const; - void SetOffset( int o ); - - // Arrays only. - RecvProp* GetArrayProp() const; - void SetArrayProp( RecvProp *pProp ); - - // Arrays only. - void SetArrayLengthProxy( ArrayLengthRecvProxyFn proxy ); - ArrayLengthRecvProxyFn GetArrayLengthProxy() const; - - bool IsInsideArray() const; - void SetInsideArray(); - - // Some property types bind more data to the prop in here. - const void* GetExtraData() const; - void SetExtraData( const void *pData ); - - // If it's one of the numbered "000", "001", etc properties in an array, then - // these can be used to get its array property name for debugging. - const char* GetParentArrayPropName(); - void SetParentArrayPropName( const char *pArrayPropName ); - -public: - - const char *m_pVarName; - SendPropType m_RecvType; - int m_Flags; - int m_StringBufferSize; - - -private: - - bool m_bInsideArray; // Set to true by the engine if this property sits inside an array. - - // Extra data that certain special property types bind to the property here. - const void *m_pExtraData; - - // If this is an array (DPT_Array). - RecvProp *m_pArrayProp; - ArrayLengthRecvProxyFn m_ArrayLengthProxy; - - RecvVarProxyFn m_ProxyFn; - DataTableRecvVarProxyFn m_DataTableProxyFn; // For RDT_DataTable. - - RecvTable *m_pDataTable; // For RDT_DataTable. - int m_Offset; - - int m_ElementStride; - int m_nElements; - - // If it's one of the numbered "000", "001", etc properties in an array, then - // these can be used to get its array property name for debugging. - const char *m_pParentArrayPropName; -}; - - -class RecvTable -{ -public: - - typedef RecvProp PropType; - - RecvTable(); - RecvTable( RecvProp *pProps, int nProps, const char *pNetTableName ); - ~RecvTable(); - - void Construct( RecvProp *pProps, int nProps, const char *pNetTableName ); - - int GetNumProps(); - RecvProp* GetProp( int i ); - - const char* GetName(); - - // Used by the engine while initializing array props. - void SetInitialized( bool bInitialized ); - bool IsInitialized() const; - - // Used by the engine. - void SetInMainList( bool bInList ); - bool IsInMainList() const; - - -public: - - // Properties described in a table. - RecvProp *m_pProps; - int m_nProps; - - // The decoder. NOTE: this covers each RecvTable AND all its children (ie: its children - // will have their own decoders that include props for all their children). - CRecvDecoder *m_pDecoder; - - const char *m_pNetTableName; // The name matched between client and server. - - -private: - - bool m_bInitialized; - bool m_bInMainList; -}; - - -inline int RecvTable::GetNumProps() -{ - return m_nProps; -} - -inline RecvProp* RecvTable::GetProp( int i ) -{ - Assert( i >= 0 && i < m_nProps ); - return &m_pProps[i]; -} - -inline const char* RecvTable::GetName() -{ - return m_pNetTableName; -} - -inline void RecvTable::SetInitialized( bool bInitialized ) -{ - m_bInitialized = bInitialized; -} - -inline bool RecvTable::IsInitialized() const -{ - return m_bInitialized; -} - -inline void RecvTable::SetInMainList( bool bInList ) -{ - m_bInMainList = bInList; -} - -inline bool RecvTable::IsInMainList() const -{ - return m_bInMainList; -} - - -// ------------------------------------------------------------------------------------------------------ // -// See notes on BEGIN_SEND_TABLE for a description. These macros work similarly. -// ------------------------------------------------------------------------------------------------------ // -#define BEGIN_RECV_TABLE(className, tableName) \ - BEGIN_RECV_TABLE_NOBASE(className, tableName) \ - RecvPropDataTable("baseclass", 0, 0, className::BaseClass::m_pClassRecvTable, DataTableRecvProxy_StaticDataTable), - -#define BEGIN_RECV_TABLE_NOBASE(className, tableName) \ - template int ClientClassInit(T *); \ - namespace tableName { \ - struct ignored; \ - } \ - template <> int ClientClassInit(tableName::ignored *); \ - namespace tableName { \ - RecvTable g_RecvTable; \ - int g_RecvTableInit = ClientClassInit((tableName::ignored *)NULL); \ - } \ - template <> int ClientClassInit(tableName::ignored *) \ - { \ - typedef className currentRecvDTClass; \ - const char *pRecvTableName = #tableName; \ - RecvTable &RecvTable = tableName::g_RecvTable; \ - static RecvProp RecvProps[] = { \ - RecvPropInt("should_never_see_this", 0, sizeof(int)), // It adds a dummy property at the start so you can define "empty" SendTables. - -#define END_RECV_TABLE() \ - }; \ - RecvTable.Construct(RecvProps+1, sizeof(RecvProps) / sizeof(RecvProp) - 1, pRecvTableName); \ - return 1; \ - } - - -#define RECVINFO(varName) #varName, offsetof(currentRecvDTClass, varName), sizeof(((currentRecvDTClass*)0)->varName) -#define RECVINFO_NAME(varName, remoteVarName) #remoteVarName, offsetof(currentRecvDTClass, varName), sizeof(((currentRecvDTClass*)0)->varName) -#define RECVINFO_STRING(varName) #varName, offsetof(currentRecvDTClass, varName), STRINGBUFSIZE(currentRecvDTClass, varName) -#define RECVINFO_BASECLASS(tableName) RecvPropDataTable("this", 0, 0, &REFERENCE_RECV_TABLE(tableName)) -#define RECVINFO_ARRAY(varName) #varName, offsetof(currentRecvDTClass, varName), sizeof(((currentRecvDTClass*)0)->varName[0]), sizeof(((currentRecvDTClass*)0)->varName)/sizeof(((currentRecvDTClass*)0)->varName[0]) - -// Just specify the name and offset. Used for strings and data tables. -#define RECVINFO_NOSIZE(varName) #varName, offsetof(currentRecvDTClass, varName) -#define RECVINFO_DT(varName) RECVINFO_NOSIZE(varName) -#define RECVINFO_DTNAME(varName,remoteVarName) #remoteVarName, offsetof(currentRecvDTClass, varName) - - -void RecvProxy_FloatToFloat ( const CRecvProxyData *pData, void *pStruct, void *pOut ); -void RecvProxy_VectorToVector( const CRecvProxyData *pData, void *pStruct, void *pOut ); -void RecvProxy_QuaternionToQuaternion( const CRecvProxyData *pData, void *pStruct, void *pOut ); -void RecvProxy_Int32ToInt8 ( const CRecvProxyData *pData, void *pStruct, void *pOut ); -void RecvProxy_Int32ToInt16 ( const CRecvProxyData *pData, void *pStruct, void *pOut ); -void RecvProxy_StringToString( const CRecvProxyData *pData, void *pStruct, void *pOut ); -void RecvProxy_Int32ToInt32 ( const CRecvProxyData *pData, void *pStruct, void *pOut ); - -// StaticDataTable does *pOut = pData. -void DataTableRecvProxy_StaticDataTable(const RecvProp *pProp, void **pOut, void *pData, int objectID); - -// PointerDataTable does *pOut = *((void**)pData) (ie: pData is a pointer to the object to decode into). -void DataTableRecvProxy_PointerDataTable(const RecvProp *pProp, void **pOut, void *pData, int objectID); - - -RecvProp RecvPropFloat( - const char *pVarName, - int offset, - int sizeofVar=SIZEOF_IGNORE, // Handled by RECVINFO macro, but set to SIZEOF_IGNORE if you don't want to bother. - int flags=0, - RecvVarProxyFn varProxy=RecvProxy_FloatToFloat - ); - -RecvProp RecvPropVector( - const char *pVarName, - int offset, - int sizeofVar=SIZEOF_IGNORE, // Handled by RECVINFO macro, but set to SIZEOF_IGNORE if you don't want to bother. - int flags=0, - RecvVarProxyFn varProxy=RecvProxy_VectorToVector - ); - -// This is here so the RecvTable can look more like the SendTable. -#define RecvPropQAngles RecvPropVector - -#if 0 // We can't ship this since it changes the size of DTVariant to be 20 bytes instead of 16 and that breaks MODs!!! - -RecvProp RecvPropQuaternion( - const char *pVarName, - int offset, - int sizeofVar=SIZEOF_IGNORE, // Handled by RECVINFO macro, but set to SIZEOF_IGNORE if you don't want to bother. - int flags=0, - RecvVarProxyFn varProxy=RecvProxy_QuaternionToQuaternion - ); -#endif - -RecvProp RecvPropInt( - const char *pVarName, - int offset, - int sizeofVar=SIZEOF_IGNORE, // Handled by RECVINFO macro, but set to SIZEOF_IGNORE if you don't want to bother. - int flags=0, - RecvVarProxyFn varProxy=0 - ); - -RecvProp RecvPropString( - const char *pVarName, - int offset, - int bufferSize, - int flags=0, - RecvVarProxyFn varProxy=RecvProxy_StringToString - ); - -RecvProp RecvPropDataTable( - const char *pVarName, - int offset, - int flags, - RecvTable *pTable, - DataTableRecvVarProxyFn varProxy=DataTableRecvProxy_StaticDataTable - ); - -RecvProp RecvPropArray3( - const char *pVarName, - int offset, - int sizeofVar, - int elements, - RecvProp pArrayProp, - DataTableRecvVarProxyFn varProxy=DataTableRecvProxy_StaticDataTable - ); - -// Use the macro to let it automatically generate a table name. You shouldn't -// ever need to reference the table name. If you want to exclude this array, then -// reference the name of the variable in varTemplate. -RecvProp InternalRecvPropArray( - const int elementCount, - const int elementStride, - const char *pName, - ArrayLengthRecvProxyFn proxy - ); - - -// -// Use this if you want to completely manage the way the array data is stored. -// You'll need to provide a proxy inside varTemplate that looks for 'iElement' -// to figure out where to store the specified element. -// -#define RecvPropVirtualArray( arrayLengthProxy, maxArrayLength, varTemplate, propertyName ) \ - varTemplate, \ - InternalRecvPropArray( \ - maxArrayLength, \ - 0, \ - #propertyName, \ - arrayLengthProxy \ - ) - - -// Use this and pass the array name and it will figure out the count and stride automatically. -#define RecvPropVariableLengthArray( arrayLengthProxy, varTemplate, arrayName ) \ - varTemplate, \ - InternalRecvPropArray( \ - sizeof(((currentRecvDTClass*)0)->arrayName) / PROPSIZEOF(currentRecvDTClass, arrayName[0]), \ - PROPSIZEOF(currentRecvDTClass, arrayName[0]), \ - #arrayName, \ - arrayLengthProxy \ - ) - - -// Use this and pass the array name and it will figure out the count and stride automatically. -#define RecvPropArray( varTemplate, arrayName ) \ - RecvPropVariableLengthArray( 0, varTemplate, arrayName ) - - -// Use this one to specify the element count and stride manually. -#define RecvPropArray2( arrayLengthProxy, varTemplate, elementCount, elementStride, arrayName ) \ - varTemplate, \ - InternalRecvPropArray( elementCount, elementStride, #arrayName, arrayLengthProxy ) - - -// ---------------------------------------------------------------------------------------- // -// Inlines. -// ---------------------------------------------------------------------------------------- // - -inline void RecvProp::InitArray( int nElements, int elementStride ) -{ - m_RecvType = DPT_Array; - m_nElements = nElements; - m_ElementStride = elementStride; -} - -inline int RecvProp::GetNumElements() const -{ - return m_nElements; -} - -inline void RecvProp::SetNumElements( int nElements ) -{ - m_nElements = nElements; -} - -inline int RecvProp::GetElementStride() const -{ - return m_ElementStride; -} - -inline void RecvProp::SetElementStride( int stride ) -{ - m_ElementStride = stride; -} - -inline int RecvProp::GetFlags() const -{ - return m_Flags; -} - -inline const char* RecvProp::GetName() const -{ - return m_pVarName; -} - -inline SendPropType RecvProp::GetType() const -{ - return m_RecvType; -} - -inline RecvTable* RecvProp::GetDataTable() const -{ - return m_pDataTable; -} - -inline void RecvProp::SetDataTable( RecvTable *pTable ) -{ - m_pDataTable = pTable; -} - -inline RecvVarProxyFn RecvProp::GetProxyFn() const -{ - return m_ProxyFn; -} - -inline void RecvProp::SetProxyFn( RecvVarProxyFn fn ) -{ - m_ProxyFn = fn; -} - -inline DataTableRecvVarProxyFn RecvProp::GetDataTableProxyFn() const -{ - return m_DataTableProxyFn; -} - -inline void RecvProp::SetDataTableProxyFn( DataTableRecvVarProxyFn fn ) -{ - m_DataTableProxyFn = fn; -} - -inline int RecvProp::GetOffset() const -{ - return m_Offset; -} - -inline void RecvProp::SetOffset( int o ) -{ - m_Offset = o; -} - -inline RecvProp* RecvProp::GetArrayProp() const -{ - return m_pArrayProp; -} - -inline void RecvProp::SetArrayProp( RecvProp *pProp ) -{ - m_pArrayProp = pProp; -} - -inline void RecvProp::SetArrayLengthProxy( ArrayLengthRecvProxyFn proxy ) -{ - m_ArrayLengthProxy = proxy; -} - -inline ArrayLengthRecvProxyFn RecvProp::GetArrayLengthProxy() const -{ - return m_ArrayLengthProxy; -} - -inline bool RecvProp::IsInsideArray() const -{ - return m_bInsideArray; -} - -inline void RecvProp::SetInsideArray() -{ - m_bInsideArray = true; -} - -inline const void* RecvProp::GetExtraData() const -{ - return m_pExtraData; -} - -inline void RecvProp::SetExtraData( const void *pData ) -{ - m_pExtraData = pData; -} - -inline const char* RecvProp::GetParentArrayPropName() -{ - return m_pParentArrayPropName; -} - -inline void RecvProp::SetParentArrayPropName( const char *pArrayPropName ) -{ - m_pParentArrayPropName = pArrayPropName; -} - -#endif // DATATABLE_RECV_H diff --git a/public/dt_send.cpp b/public/dt_send.cpp deleted file mode 100644 index 72510894c..000000000 --- a/public/dt_send.cpp +++ /dev/null @@ -1,798 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - - -#include "dt_send.h" -#include "mathlib/mathlib.h" -#include "mathlib/vector.h" -#include "tier0/dbg.h" -#include "dt_utlvector_common.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#if !defined(_STATIC_LINKED) || defined(GAME_DLL) - - -static CNonModifiedPointerProxy *s_pNonModifiedPointerProxyHead = NULL; - - -void SendProxy_UInt8ToInt32( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID); -void SendProxy_UInt16ToInt32( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID); -void SendProxy_UInt32ToInt32( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID); - -const char *s_ElementNames[MAX_ARRAY_ELEMENTS] = -{ - "000", "001", "002", "003", "004", "005", "006", "007", "008", "009", - "010", "011", "012", "013", "014", "015", "016", "017", "018", "019", - "020", "021", "022", "023", "024", "025", "026", "027", "028", "029", - "030", "031", "032", "033", "034", "035", "036", "037", "038", "039", - "040", "041", "042", "043", "044", "045", "046", "047", "048", "049", - "050", "051", "052", "053", "054", "055", "056", "057", "058", "059", - "060", "061", "062", "063", "064", "065", "066", "067", "068", "069", - "070", "071", "072", "073", "074", "075", "076", "077", "078", "079", - "080", "081", "082", "083", "084", "085", "086", "087", "088", "089", - "090", "091", "092", "093", "094", "095", "096", "097", "098", "099", - "100", "101", "102", "103", "104", "105", "106", "107", "108", "109", - "110", "111", "112", "113", "114", "115", "116", "117", "118", "119", - "120", "121", "122", "123", "124", "125", "126", "127", "128", "129", - "130", "131", "132", "133", "134", "135", "136", "137", "138", "139", - "140", "141", "142", "143", "144", "145", "146", "147", "148", "149", - "150", "151", "152", "153", "154", "155", "156", "157", "158", "159", - "160", "161", "162", "163", "164", "165", "166", "167", "168", "169", - "170", "171", "172", "173", "174", "175", "176", "177", "178", "179", - "180", "181", "182", "183", "184", "185", "186", "187", "188", "189", - "190", "191", "192", "193", "194", "195", "196", "197", "198", "199", - "200", "201", "202", "203", "204", "205", "206", "207", "208", "209", - "210", "211", "212", "213", "214", "215", "216", "217", "218", "219", - "220", "221", "222", "223", "224", "225", "226", "227", "228", "229", - "230", "231", "232", "233", "234", "235", "236", "237", "238", "239", - "240", "241", "242", "243", "244", "245", "246", "247", "248", "249", - "250", "251", "252", "253", "254", "255", "256", "257", "258", "259", - "260", "261", "262", "263", "264", "265", "266", "267", "268", "269", - "270", "271", "272", "273", "274", "275", "276", "277", "278", "279", - "280", "281", "282", "283", "284", "285", "286", "287", "288", "289", - "290", "291", "292", "293", "294", "295", "296", "297", "298", "299", - "300", "301", "302", "303", "304", "305", "306", "307", "308", "309", - "310", "311", "312", "313", "314", "315", "316", "317", "318", "319", - "320", "321", "322", "323", "324", "325", "326", "327", "328", "329", - "330", "331", "332", "333", "334", "335", "336", "337", "338", "339", - "340", "341", "342", "343", "344", "345", "346", "347", "348", "349", - "350", "351", "352", "353", "354", "355", "356", "357", "358", "359", - "360", "361", "362", "363", "364", "365", "366", "367", "368", "369", - "370", "371", "372", "373", "374", "375", "376", "377", "378", "379", - "380", "381", "382", "383", "384", "385", "386", "387", "388", "389", - "390", "391", "392", "393", "394", "395", "396", "397", "398", "399", - "400", "401", "402", "403", "404", "405", "406", "407", "408", "409", - "410", "411", "412", "413", "414", "415", "416", "417", "418", "419", - "420", "421", "422", "423", "424", "425", "426", "427", "428", "429", - "430", "431", "432", "433", "434", "435", "436", "437", "438", "439", - "440", "441", "442", "443", "444", "445", "446", "447", "448", "449", - "450", "451", "452", "453", "454", "455", "456", "457", "458", "459", - "460", "461", "462", "463", "464", "465", "466", "467", "468", "469", - "470", "471", "472", "473", "474", "475", "476", "477", "478", "479", - "480", "481", "482", "483", "484", "485", "486", "487", "488", "489", - "490", "491", "492", "493", "494", "495", "496", "497", "498", "499", - "500", "501", "502", "503", "504", "505", "506", "507", "508", "509", - "510", "511", "512", "513", "514", "515", "516", "517", "518", "519", - "520", "521", "522", "523", "524", "525", "526", "527", "528", "529", - "530", "531", "532", "533", "534", "535", "536", "537", "538", "539", - "540", "541", "542", "543", "544", "545", "546", "547", "548", "549", - "550", "551", "552", "553", "554", "555", "556", "557", "558", "559", - "560", "561", "562", "563", "564", "565", "566", "567", "568", "569", - "570", "571", "572", "573", "574", "575", "576", "577", "578", "579", - "580", "581", "582", "583", "584", "585", "586", "587", "588", "589", - "590", "591", "592", "593", "594", "595", "596", "597", "598", "599", - "600", "601", "602", "603", "604", "605", "606", "607", "608", "609", - "610", "611", "612", "613", "614", "615", "616", "617", "618", "619", - "620", "621", "622", "623", "624", "625", "626", "627", "628", "629", - "630", "631", "632", "633", "634", "635", "636", "637", "638", "639", - "640", "641", "642", "643", "644", "645", "646", "647", "648", "649", - "650", "651", "652", "653", "654", "655", "656", "657", "658", "659", - "660", "661", "662", "663", "664", "665", "666", "667", "668", "669", - "670", "671", "672", "673", "674", "675", "676", "677", "678", "679", - "680", "681", "682", "683", "684", "685", "686", "687", "688", "689", - "690", "691", "692", "693", "694", "695", "696", "697", "698", "699", - "700", "701", "702", "703", "704", "705", "706", "707", "708", "709", - "710", "711", "712", "713", "714", "715", "716", "717", "718", "719", - "720", "721", "722", "723", "724", "725", "726", "727", "728", "729", - "730", "731", "732", "733", "734", "735", "736", "737", "738", "739", - "740", "741", "742", "743", "744", "745", "746", "747", "748", "749", - "750", "751", "752", "753", "754", "755", "756", "757", "758", "759", - "760", "761", "762", "763", "764", "765", "766", "767", "768", "769", - "770", "771", "772", "773", "774", "775", "776", "777", "778", "779", - "780", "781", "782", "783", "784", "785", "786", "787", "788", "789", - "790", "791", "792", "793", "794", "795", "796", "797", "798", "799", - "800", "801", "802", "803", "804", "805", "806", "807", "808", "809", - "810", "811", "812", "813", "814", "815", "816", "817", "818", "819", - "820", "821", "822", "823", "824", "825", "826", "827", "828", "829", - "830", "831", "832", "833", "834", "835", "836", "837", "838", "839", - "840", "841", "842", "843", "844", "845", "846", "847", "848", "849", - "850", "851", "852", "853", "854", "855", "856", "857", "858", "859", - "860", "861", "862", "863", "864", "865", "866", "867", "868", "869", - "870", "871", "872", "873", "874", "875", "876", "877", "878", "879", - "880", "881", "882", "883", "884", "885", "886", "887", "888", "889", - "890", "891", "892", "893", "894", "895", "896", "897", "898", "899", - "900", "901", "902", "903", "904", "905", "906", "907", "908", "909", - "910", "911", "912", "913", "914", "915", "916", "917", "918", "919", - "920", "921", "922", "923", "924", "925", "926", "927", "928", "929", - "930", "931", "932", "933", "934", "935", "936", "937", "938", "939", - "940", "941", "942", "943", "944", "945", "946", "947", "948", "949", - "950", "951", "952", "953", "954", "955", "956", "957", "958", "959", - "960", "961", "962", "963", "964", "965", "966", "967", "968", "969", - "970", "971", "972", "973", "974", "975", "976", "977", "978", "979", - "980", "981", "982", "983", "984", "985", "986", "987", "988", "989", - "990", "991", "992", "993", "994", "995", "996", "997", "998", "999", - "1000", "1001", "1002", "1003", "1004", "1005", "1006", "1007", "1008", "1009", - "1010", "1011", "1012", "1013", "1014", "1015", "1016", "1017", "1018", "1019", - "1020", "1021", "1022", "1023" - -}; - - -CNonModifiedPointerProxy::CNonModifiedPointerProxy( SendTableProxyFn fn ) -{ - m_pNext = s_pNonModifiedPointerProxyHead; - s_pNonModifiedPointerProxyHead = this; - m_Fn = fn; -} - - -CStandardSendProxiesV1::CStandardSendProxiesV1() -{ - m_Int8ToInt32 = SendProxy_Int8ToInt32; - m_Int16ToInt32 = SendProxy_Int16ToInt32; - m_Int32ToInt32 = SendProxy_Int32ToInt32; - - m_UInt8ToInt32 = SendProxy_UInt8ToInt32; - m_UInt16ToInt32 = SendProxy_UInt16ToInt32; - m_UInt32ToInt32 = SendProxy_UInt32ToInt32; - - m_FloatToFloat = SendProxy_FloatToFloat; - m_VectorToVector = SendProxy_VectorToVector; -} - -CStandardSendProxies::CStandardSendProxies() -{ - m_DataTableToDataTable = SendProxy_DataTableToDataTable; - m_SendLocalDataTable = SendProxy_SendLocalDataTable; - m_ppNonModifiedPointerProxies = &s_pNonModifiedPointerProxyHead; - -} -CStandardSendProxies g_StandardSendProxies; - - -// ---------------------------------------------------------------------- // -// Proxies. -// ---------------------------------------------------------------------- // -void SendProxy_AngleToFloat( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) -{ - float angle; - - angle = *((float*)pData); - pOut->m_Float = anglemod( angle ); - - Assert( IsFinite( pOut->m_Float ) ); -} - -void SendProxy_FloatToFloat( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) -{ - pOut->m_Float = *((float*)pData); - Assert( IsFinite( pOut->m_Float ) ); -} - -void SendProxy_QAngles( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ) -{ - QAngle *v = (QAngle*)pData; - pOut->m_Vector[0] = anglemod( v->x ); - pOut->m_Vector[1] = anglemod( v->y ); - pOut->m_Vector[2] = anglemod( v->z ); -} - -void SendProxy_VectorToVector( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) -{ - Vector& v = *(Vector*)pData; - Assert( v.IsValid() ); - pOut->m_Vector[0] = v[0]; - pOut->m_Vector[1] = v[1]; - pOut->m_Vector[2] = v[2]; -} - -#if 0 // We can't ship this since it changes the size of DTVariant to be 20 bytes instead of 16 and that breaks MODs!!! -void SendProxy_QuaternionToQuaternion( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) -{ - Quaternion& q = *(Quaternion*)pData; - Assert( q.IsValid() ); - pOut->m_Vector[0] = q[0]; - pOut->m_Vector[1] = q[1]; - pOut->m_Vector[2] = q[2]; - pOut->m_Vector[3] = q[3]; -} -#endif - -void SendProxy_Int8ToInt32( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) -{ - pOut->m_Int = *((char*)pData); -} - -void SendProxy_Int16ToInt32( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) -{ - pOut->m_Int = *((short*)pData); -} - -void SendProxy_Int32ToInt32( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) -{ - pOut->m_Int = *((int*)pData); -} - -void SendProxy_UInt8ToInt32( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) -{ - pOut->m_Int = *((unsigned char*)pData); -} - -void SendProxy_UInt16ToInt32( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) -{ - pOut->m_Int = *((unsigned short*)pData); -} - -void SendProxy_UInt32ToInt32( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) -{ - *((unsigned long*)&pOut->m_Int) = *((unsigned long*)pData); -} - -void SendProxy_StringToString( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) -{ - pOut->m_pString = (char*)pData; -} - -void* SendProxy_DataTableToDataTable( const SendProp *pProp, const void *pStructBase, const void *pData, CSendProxyRecipients *pRecipients, int objectID ) -{ - return (void*)pData; -} - -void* SendProxy_DataTablePtrToDataTable( const SendProp *pProp, const void *pStructBase, const void *pData, CSendProxyRecipients *pRecipients, int objectID ) -{ - return *((void**)pData); -} - -static void SendProxy_Empty( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: If the recipient is the same as objectID, go ahead and iterate down -// the m_Local stuff, otherwise, act like it wasn't there at all. -// This way, only the local player receives information about him/herself. -// Input : *pVarData - -// *pOut - -// objectID - -//----------------------------------------------------------------------------- - -void* SendProxy_SendLocalDataTable( const SendProp *pProp, const void *pStruct, const void *pVarData, CSendProxyRecipients *pRecipients, int objectID ) -{ - pRecipients->SetOnly( objectID - 1 ); - return ( void * )pVarData; -} - - - - - -// ---------------------------------------------------------------------- // -// Prop setup functions (for building tables). -// ---------------------------------------------------------------------- // -float AssignRangeMultiplier( int nBits, double range ) -{ - unsigned long iHighValue; - if ( nBits == 32 ) - iHighValue = 0xFFFFFFFE; - else - iHighValue = ((1 << (unsigned long)nBits) - 1); - - float fHighLowMul = iHighValue / range; - - // If the precision is messing us up, then adjust it so it won't. - if ( (unsigned long)(fHighLowMul * range) > iHighValue || - (fHighLowMul * range) > (double)iHighValue ) - { - // Squeeze it down smaller and smaller until it's going to produce an integer - // in the valid range when given the highest value. - float multipliers[] = { 0.9999, 0.99, 0.9, 0.8, 0.7 }; - size_t i; - for ( i=0; i < ARRAYSIZE( multipliers ); i++ ) - { - float fHighLowMul = (float)( iHighValue / range ) * multipliers[i]; - if ( (unsigned long)(fHighLowMul * range) > iHighValue || - (fHighLowMul * range) > (double)iHighValue ) - { - } - else - { - break; - } - } - - if ( i == ARRAYSIZE( multipliers ) ) - { - // Doh! We seem to be unable to represent this range. - Assert( false ); - return 0; - } - } - - return fHighLowMul; -} - - - -SendProp SendPropFloat( - const char *pVarName, - // Variable name. - int offset, // Offset into container structure. - int sizeofVar, - int nBits, // Number of bits to use when encoding. - int flags, - float fLowValue, // For floating point, low and high values. - float fHighValue, // High value. If HIGH_DEFAULT, it's (1<m_Int = atoi(pUserStr); - -// pProp : the SendProp that has the proxy -// pStructBase : the base structure (like CBaseEntity*). -// pData : the address of the variable to proxy. -// pOut : where to output the proxied value. -// iElement : the element index if this data is part of an array (or 0 if not). -// objectID : entity index for debugging purposes. - -// Return false if you don't want the engine to register and send a delta to -// the clients for this property (regardless of whether it actually changed or not). -// ------------------------------------------------------------------------ // -typedef void (*SendVarProxyFn)( const SendProp *pProp, const void *pStructBase, const void *pData, DVariant *pOut, int iElement, int objectID ); - -// Return the pointer to the data for the datatable. -// If the proxy returns null, it's the same as if pRecipients->ClearAllRecipients() was called. -class CSendProxyRecipients; - -typedef void* (*SendTableProxyFn)( - const SendProp *pProp, - const void *pStructBase, - const void *pData, - CSendProxyRecipients *pRecipients, - int objectID ); - - -class CNonModifiedPointerProxy -{ -public: - CNonModifiedPointerProxy( SendTableProxyFn fn ); - -public: - - SendTableProxyFn m_Fn; - CNonModifiedPointerProxy *m_pNext; -}; - - -// This tells the engine that the send proxy will not modify the pointer -// - it only plays with the recipients. This must be set on proxies that work -// this way, otherwise the engine can't track which properties changed -// in NetworkStateChanged(). -#define REGISTER_SEND_PROXY_NON_MODIFIED_POINTER( sendProxyFn ) static CNonModifiedPointerProxy __proxy_##sendProxyFn( sendProxyFn ); - - -class CStandardSendProxiesV1 -{ -public: - CStandardSendProxiesV1(); - - SendVarProxyFn m_Int8ToInt32; - SendVarProxyFn m_Int16ToInt32; - SendVarProxyFn m_Int32ToInt32; - - SendVarProxyFn m_UInt8ToInt32; - SendVarProxyFn m_UInt16ToInt32; - SendVarProxyFn m_UInt32ToInt32; - - SendVarProxyFn m_FloatToFloat; - SendVarProxyFn m_VectorToVector; -}; - -class CStandardSendProxies : public CStandardSendProxiesV1 -{ -public: - CStandardSendProxies(); - - SendTableProxyFn m_DataTableToDataTable; - SendTableProxyFn m_SendLocalDataTable; - CNonModifiedPointerProxy **m_ppNonModifiedPointerProxies; -}; - -extern CStandardSendProxies g_StandardSendProxies; - - -// Max # of datatable send proxies you can have in a tree. -#define MAX_DATATABLE_PROXIES 32 - -// ------------------------------------------------------------------------ // -// Datatable send proxies are used to tell the engine where the datatable's -// data is and to specify which clients should get the data. -// -// pRecipients is the object that allows you to specify which clients will -// receive the data. -// ------------------------------------------------------------------------ // -class CSendProxyRecipients -{ -public: - void SetAllRecipients(); // Note: recipients are all set by default when each proxy is called. - void ClearAllRecipients(); - - void SetRecipient( int iClient ); // Note: these are CLIENT indices, not entity indices (so the first player's index is 0). - void ClearRecipient( int iClient ); - - // Clear all recipients and set only the specified one. - void SetOnly( int iClient ); - -public: - // Make sure we have enough room for the max possible player count - CBitVec< ABSOLUTE_PLAYER_LIMIT > m_Bits; -}; - -inline void CSendProxyRecipients::SetAllRecipients() -{ - m_Bits.SetAll(); -} - -inline void CSendProxyRecipients::ClearAllRecipients() -{ - m_Bits.ClearAll(); -} - -inline void CSendProxyRecipients::SetRecipient( int iClient ) -{ - m_Bits.Set( iClient ); -} - -inline void CSendProxyRecipients::ClearRecipient( int iClient ) -{ - m_Bits.Clear( iClient ); -} - -inline void CSendProxyRecipients::SetOnly( int iClient ) -{ - m_Bits.ClearAll(); - m_Bits.Set( iClient ); -} - - - -// ------------------------------------------------------------------------ // -// ArrayLengthSendProxies are used when you want to specify an array's length -// dynamically. -// ------------------------------------------------------------------------ // -typedef int (*ArrayLengthSendProxyFn)( const void *pStruct, int objectID ); - - - -class RecvProp; -class SendTable; -class CSendTablePrecalc; - - -// -------------------------------------------------------------------------------------------------------------- // -// SendProp. -// -------------------------------------------------------------------------------------------------------------- // - -// If SendProp::GetDataTableProxyIndex() returns this, then the proxy is one that always sends -// the data to all clients, so we don't need to store the results. -#define DATATABLE_PROXY_INDEX_NOPROXY 255 -#define DATATABLE_PROXY_INDEX_INVALID 254 - -class SendProp -{ -public: - SendProp(); - virtual ~SendProp(); - - void Clear(); - - int GetOffset() const; - void SetOffset( int i ); - - SendVarProxyFn GetProxyFn() const; - void SetProxyFn( SendVarProxyFn f ); - - SendTableProxyFn GetDataTableProxyFn() const; - void SetDataTableProxyFn( SendTableProxyFn f ); - - SendTable* GetDataTable() const; - void SetDataTable( SendTable *pTable ); - - char const* GetExcludeDTName() const; - - // If it's one of the numbered "000", "001", etc properties in an array, then - // these can be used to get its array property name for debugging. - const char* GetParentArrayPropName(); - void SetParentArrayPropName( const char *pArrayPropName ); - - const char* GetName() const; - - bool IsSigned() const; - - bool IsExcludeProp() const; - - bool IsInsideArray() const; // Returns true if SPROP_INSIDEARRAY is set. - void SetInsideArray(); - - // Arrays only. - void SetArrayProp( SendProp *pProp ); - SendProp* GetArrayProp() const; - - // Arrays only. - void SetArrayLengthProxy( ArrayLengthSendProxyFn fn ); - ArrayLengthSendProxyFn GetArrayLengthProxy() const; - - int GetNumElements() const; - void SetNumElements( int nElements ); - - // Return the # of bits to encode an array length (must hold GetNumElements()). - int GetNumArrayLengthBits() const; - - int GetElementStride() const; - - SendPropType GetType() const; - - int GetFlags() const; - void SetFlags( int flags ); - - // Some property types bind more data to the SendProp in here. - const void* GetExtraData() const; - void SetExtraData( const void *pData ); - -public: - - RecvProp *m_pMatchingRecvProp; // This is temporary and only used while precalculating - // data for the decoders. - - SendPropType m_Type; - int m_nBits; - float m_fLowValue; - float m_fHighValue; - - SendProp *m_pArrayProp; // If this is an array, this is the property that defines each array element. - ArrayLengthSendProxyFn m_ArrayLengthProxy; // This callback returns the array length. - - int m_nElements; // Number of elements in the array (or 1 if it's not an array). - int m_ElementStride; // Pointer distance between array elements. - - union - { - const char *m_pExcludeDTName; // If this is an exclude prop, then this is the name of the datatable to exclude a prop from. - const char *m_pParentArrayPropName; - }; - - void *m_pUnknown; - const char *m_pVarName; - float m_fHighLowMul; - -private: - - int m_Flags; // SPROP_ flags. - - SendVarProxyFn m_ProxyFn; // NULL for DPT_DataTable. - SendTableProxyFn m_DataTableProxyFn; // Valid for DPT_DataTable. - - SendTable *m_pDataTable; - - // SENDPROP_VECTORELEM makes this negative to start with so we can detect that and - // set the SPROP_IS_VECTOR_ELEM flag. - int m_Offset; - - // Extra data bound to this property. - const void *m_pExtraData; -}; - - -inline int SendProp::GetOffset() const -{ - return m_Offset; -} - -inline void SendProp::SetOffset( int i ) -{ - m_Offset = i; -} - -inline SendVarProxyFn SendProp::GetProxyFn() const -{ - Assert( m_Type != DPT_DataTable ); - return m_ProxyFn; -} - -inline void SendProp::SetProxyFn( SendVarProxyFn f ) -{ - m_ProxyFn = f; -} - -inline SendTableProxyFn SendProp::GetDataTableProxyFn() const -{ - Assert( m_Type == DPT_DataTable ); - return m_DataTableProxyFn; -} - -inline void SendProp::SetDataTableProxyFn( SendTableProxyFn f ) -{ - m_DataTableProxyFn = f; -} - -inline SendTable* SendProp::GetDataTable() const -{ - return m_pDataTable; -} - -inline void SendProp::SetDataTable( SendTable *pTable ) -{ - m_pDataTable = pTable; -} - -inline char const* SendProp::GetExcludeDTName() const -{ - return m_pExcludeDTName; -} - -inline const char* SendProp::GetParentArrayPropName() -{ - return m_pParentArrayPropName; -} - -inline void SendProp::SetParentArrayPropName( const char *pArrayPropName ) -{ - Assert( !m_pParentArrayPropName ); - m_pParentArrayPropName = pArrayPropName; -} - -inline const char* SendProp::GetName() const -{ - return m_pVarName; -} - - -inline bool SendProp::IsSigned() const -{ - return !(m_Flags & SPROP_UNSIGNED); -} - -inline bool SendProp::IsExcludeProp() const -{ - return (m_Flags & SPROP_EXCLUDE) != 0; -} - -inline bool SendProp::IsInsideArray() const -{ - return (m_Flags & SPROP_INSIDEARRAY) != 0; -} - -inline void SendProp::SetInsideArray() -{ - m_Flags |= SPROP_INSIDEARRAY; -} - -inline void SendProp::SetArrayProp( SendProp *pProp ) -{ - m_pArrayProp = pProp; -} - -inline SendProp* SendProp::GetArrayProp() const -{ - return m_pArrayProp; -} - -inline void SendProp::SetArrayLengthProxy( ArrayLengthSendProxyFn fn ) -{ - m_ArrayLengthProxy = fn; -} - -inline ArrayLengthSendProxyFn SendProp::GetArrayLengthProxy() const -{ - return m_ArrayLengthProxy; -} - -inline int SendProp::GetNumElements() const -{ - return m_nElements; -} - -inline void SendProp::SetNumElements( int nElements ) -{ - m_nElements = nElements; -} - -inline int SendProp::GetElementStride() const -{ - return m_ElementStride; -} - -inline SendPropType SendProp::GetType() const -{ - return m_Type; -} - -inline int SendProp::GetFlags() const -{ - return m_Flags; -} - -inline void SendProp::SetFlags( int flags ) -{ - // Make sure they're using something from the valid set of flags. - Assert( !( flags & ~((1 << SPROP_NUMFLAGBITS) - 1) ) ); - m_Flags = flags; -} - -inline const void* SendProp::GetExtraData() const -{ - return m_pExtraData; -} - -inline void SendProp::SetExtraData( const void *pData ) -{ - m_pExtraData = pData; -} - - -// -------------------------------------------------------------------------------------------------------------- // -// SendTable. -// -------------------------------------------------------------------------------------------------------------- // - -class SendTable -{ -public: - - typedef SendProp PropType; - - SendTable(); - SendTable( SendProp *pProps, int nProps, const char *pNetTableName ); - ~SendTable(); - - void Construct( SendProp *pProps, int nProps, const char *pNetTableName ); - - const char* GetName() const; - - int GetNumProps() const; - SendProp* GetProp( int i ); - - // Used by the engine. - bool IsInitialized() const; - void SetInitialized( bool bInitialized ); - - // Used by the engine while writing info into the signon. - void SetWriteFlag(bool bHasBeenWritten); - bool GetWriteFlag() const; - - bool HasPropsEncodedAgainstTickCount() const; - void SetHasPropsEncodedAgainstTickcount( bool bState ); - -public: - - SendProp *m_pProps; - int m_nProps; - - const char *m_pNetTableName; // The name matched between client and server. - - // The engine hooks the SendTable here. - CSendTablePrecalc *m_pPrecalc; - - -protected: - bool m_bInitialized : 1; - bool m_bHasBeenWritten : 1; - bool m_bHasPropsEncodedAgainstCurrentTickCount : 1; // m_flSimulationTime and m_flAnimTime, e.g. -}; - - -inline const char* SendTable::GetName() const -{ - return m_pNetTableName; -} - - -inline int SendTable::GetNumProps() const -{ - return m_nProps; -} - - -inline SendProp* SendTable::GetProp( int i ) -{ - Assert( i >= 0 && i < m_nProps ); - return &m_pProps[i]; -} - - -inline bool SendTable::IsInitialized() const -{ - return m_bInitialized; -} - - -inline void SendTable::SetInitialized( bool bInitialized ) -{ - m_bInitialized = bInitialized; -} - - -inline bool SendTable::GetWriteFlag() const -{ - return m_bHasBeenWritten; -} - - -inline void SendTable::SetWriteFlag(bool bHasBeenWritten) -{ - m_bHasBeenWritten = bHasBeenWritten; -} - -inline bool SendTable::HasPropsEncodedAgainstTickCount() const -{ - return m_bHasPropsEncodedAgainstCurrentTickCount; -} - -inline void SendTable::SetHasPropsEncodedAgainstTickcount( bool bState ) -{ - m_bHasPropsEncodedAgainstCurrentTickCount = bState; -} - -// ------------------------------------------------------------------------------------------------------ // -// Use BEGIN_SEND_TABLE if you want to declare a SendTable and have it inherit all the properties from -// its base class. There are two requirements for this to work: - -// 1. Its base class must have a static SendTable pointer member variable called m_pClassSendTable which -// points to its send table. The DECLARE_SERVERCLASS and IMPLEMENT_SERVERCLASS macros do this automatically. - -// 2. Your class must typedef its base class as BaseClass. So it would look like this: -// class Derived : public CBaseEntity -// { -// typedef CBaseEntity BaseClass; -// }; - -// If you don't want to interit a base class's properties, use BEGIN_SEND_TABLE_NOBASE. -// ------------------------------------------------------------------------------------------------------ // -#define BEGIN_SEND_TABLE(className, tableName) \ - BEGIN_SEND_TABLE_NOBASE(className, tableName) \ - SendPropDataTable("baseclass", 0, className::BaseClass::m_pClassSendTable, SendProxy_DataTableToDataTable), - -#define BEGIN_SEND_TABLE_NOBASE(className, tableName) \ - template int ServerClassInit(T *); \ - namespace tableName { \ - struct ignored; \ - } \ - template <> int ServerClassInit(tableName::ignored *); \ - namespace tableName { \ - SendTable g_SendTable;\ - int g_SendTableInit = ServerClassInit((tableName::ignored *)NULL); \ - } \ - template <> int ServerClassInit(tableName::ignored *) \ - { \ - typedef className currentSendDTClass; \ - static const char *g_pSendTableName = #tableName; \ - SendTable &sendTable = tableName::g_SendTable; \ - static SendProp g_SendProps[] = { \ - SendPropInt("should_never_see_this", 0, sizeof(int)), // It adds a dummy property at the start so you can define "empty" SendTables. - -#define END_SEND_TABLE() \ - };\ - sendTable.Construct(g_SendProps+1, sizeof(g_SendProps) / sizeof(SendProp) - 1, g_pSendTableName);\ - return 1; \ - } - - -// These can simplify creating the variables. -// Note: currentSendDTClass::MakeANetworkVar_##varName equates to currentSendDTClass. It's -// there as a check to make sure all networked variables use the CNetworkXXXX macros in network_var.h. -#define SENDINFO(varName) #varName, offsetof(currentSendDTClass::MakeANetworkVar_##varName, varName), sizeof(((currentSendDTClass*)0)->varName) -#define SENDINFO_ARRAY(varName) #varName, offsetof(currentSendDTClass::MakeANetworkVar_##varName, varName), sizeof(((currentSendDTClass*)0)->varName[0]) -#define SENDINFO_ARRAY3(varName) #varName, offsetof(currentSendDTClass::MakeANetworkVar_##varName, varName), sizeof(((currentSendDTClass*)0)->varName[0]), sizeof(((currentSendDTClass*)0)->varName)/sizeof(((currentSendDTClass*)0)->varName[0]) -#define SENDINFO_ARRAYELEM(varName, i) #varName "[" #i "]", offsetof(currentSendDTClass::MakeANetworkVar_##varName, varName[i]), sizeof(((currentSendDTClass*)0)->varName[0]) -#define SENDINFO_ARRAYELEM2(varName, i) #varName "[" #i "]", offsetof(currentSendDTClass::MakeANetworkVar_##varName, varName) + offsetof(currentSendDTClass::MakeANetworkVar_##varName::NetworkVar_##varName, m_Value[i]), sizeof(((currentSendDTClass*)0)->varName[0]) -#define SENDINFO_NETWORKARRAYELEM(varName, i)#varName "[" #i "]", offsetof(currentSendDTClass::MakeANetworkVar_##varName, varName.m_Value[i]), sizeof(((currentSendDTClass*)0)->varName.m_Value[0]) - -// NOTE: Be VERY careful to specify any other vector elems for the same vector IN ORDER and -// right after each other, otherwise it might miss the Y or Z component in SP. -// -// Note: this macro specifies a negative offset so the engine can detect it and setup m_pNext -#define SENDINFO_VECTORELEM(varName, i) #varName "[" #i "]", -(int)offsetof(currentSendDTClass::MakeANetworkVar_##varName, varName.m_Value[i]), sizeof(((currentSendDTClass*)0)->varName.m_Value[0]) -#define SENDINFO_VECTORELEM2(varName, i, which) #varName "[" #i "]", -(int)offsetof(currentSendDTClass::MakeANetworkVar_##varName, varName.m_Value.which), sizeof(((currentSendDTClass*)0)->varName.m_Value[0]) - -#define SENDINFO_STRUCTELEM(varName) #varName, offsetof(currentSendDTClass, varName), sizeof(((currentSendDTClass*)0)->varName.m_Value) -#define SENDINFO_STRUCTARRAYELEM(varName, i)#varName "[" #i "]", offsetof(currentSendDTClass, varName.m_Value[i]), sizeof(((currentSendDTClass*)0)->varName.m_Value[0]) - -// Use this when you're not using a CNetworkVar to represent the data you're sending. -#define SENDINFO_NOCHECK(varName) #varName, offsetof(currentSendDTClass, varName), sizeof(((currentSendDTClass*)0)->varName) -#define SENDINFO_NOCHECK_VECTORELEM(varName, i, which) #varName "[" #i "]", offsetof(currentSendDTClass, varName.which), sizeof(((currentSendDTClass*)0)->varName.which) -#define SENDINFO_STRING_NOCHECK(varName) #varName, offsetof(currentSendDTClass, varName) -#define SENDINFO_DT(varName) #varName, offsetof(currentSendDTClass, varName) -#define SENDINFO_DT_NAME(varName, remoteVarName) #remoteVarName, offsetof(currentSendDTClass, varName) -#define SENDINFO_NAME(varName,remoteVarName) #remoteVarName, offsetof(currentSendDTClass, varName), sizeof(((currentSendDTClass*)0)->varName) - - - - -// ------------------------------------------------------------------------ // -// Built-in proxy types. -// See the definition of SendVarProxyFn for information about these. -// ------------------------------------------------------------------------ // -void SendProxy_QAngles ( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); -void SendProxy_AngleToFloat ( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); -void SendProxy_FloatToFloat ( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); -void SendProxy_VectorToVector ( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); -#if 0 // We can't ship this since it changes the size of DTVariant to be 20 bytes instead of 16 and that breaks MODs!!! -void SendProxy_QuaternionToQuaternion( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); -#endif - -void SendProxy_Int8ToInt32 ( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); -void SendProxy_Int16ToInt32 ( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); -void SendProxy_Int32ToInt32 ( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); -void SendProxy_StringToString ( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); - -// pData is the address of a data table. -void* SendProxy_DataTableToDataTable( const SendProp *pProp, const void *pStructBase, const void *pData, CSendProxyRecipients *pRecipients, int objectID ); - -// pData is the address of a pointer to a data table. -void* SendProxy_DataTablePtrToDataTable( const SendProp *pProp, const void *pStructBase, const void *pData, CSendProxyRecipients *pRecipients, int objectID ); - -// Used on player entities - only sends the data to the local player (objectID-1). -void* SendProxy_SendLocalDataTable( const SendProp *pProp, const void *pStruct, const void *pVarData, CSendProxyRecipients *pRecipients, int objectID ); - - -// ------------------------------------------------------------------------ // -// Use these functions to setup your data tables. -// ------------------------------------------------------------------------ // -SendProp SendPropFloat( - const char *pVarName, // Variable name. - int offset, // Offset into container structure. - int sizeofVar=SIZEOF_IGNORE, - int nBits=32, // Number of bits to use when encoding. - int flags=0, - float fLowValue=0.0f, // For floating point, low and high values. - float fHighValue=HIGH_DEFAULT, // High value. If HIGH_DEFAULT, it's (1<arrayName) / PROPSIZEOF(currentSendDTClass, arrayName[0]), \ - PROPSIZEOF(currentSendDTClass, arrayName[0]), \ - #arrayName, \ - arrayLengthSendProxy \ - ) - -// Use this one to specify the element count and stride manually. -#define SendPropArray2( arrayLengthSendProxy, varTemplate, elementCount, elementStride, arrayName ) \ - varTemplate, \ - InternalSendPropArray( elementCount, elementStride, #arrayName, arrayLengthSendProxy ) - - - - -// Use these to create properties that exclude other properties. This is useful if you want to use most of -// a base class's datatable data, but you want to override some of its variables. -SendProp SendPropExclude( - const char *pDataTableName, // Data table name (given to BEGIN_SEND_TABLE and BEGIN_RECV_TABLE). - const char *pPropName // Name of the property to exclude. - ); - - -#endif // DATATABLE_SEND_H diff --git a/public/dt_shared.cpp b/public/dt_shared.cpp deleted file mode 100644 index d1c4db676..000000000 --- a/public/dt_shared.cpp +++ /dev/null @@ -1,113 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include "dt_shared.h" - -#if !defined (CLIENT_DLL) -#include "sendproxy.h" -#else -#include "recvproxy.h" -#endif - - -// ------------------------------------------------------------------------ // -// Just wrappers to make shared code look easier... -// ------------------------------------------------------------------------ // - -// Use these functions to setup your data tables. -DataTableProp PropFloat( - const char *pVarName, // Variable name. - int offset, // Offset into container structure. - int sizeofVar, - int nBits, // Number of bits to use when encoding. - int flags, - float fLowValue, // For floating point, low and high values. - float fHighValue // High value. If HIGH_DEFAULT, it's (1< *g_STDict = 0; -static CUtlDict *g_RTDict = 0; -#endif - -char* AllocateStringHelper2( const char *pFormat, va_list marker ) -{ - char str[512]; - _vsnprintf( str, sizeof( str ), pFormat, marker ); - - int len = strlen( str ) + 1; - char *pRet = new char[len]; - memcpy( pRet, str, len ); - - return pRet; -} - - -char* AllocateStringHelper( const char *pFormat, ... ) -{ - va_list marker; - va_start( marker, pFormat ); - char *pRet = AllocateStringHelper2( pFormat, marker ); - va_end( marker ); - - return pRet; -} - - -char* AllocateUniqueDataTableName( bool bSendTable, const char *pFormat, ... ) -{ - // Setup the string. - va_list marker; - va_start( marker, pFormat ); - char *pRet = AllocateStringHelper2( pFormat, marker ); - va_end( marker ); - - // Make sure it's unique. -#ifdef _DEBUG - // Have to allocate them here because if they're declared as straight global variables, - // their constructors won't have been called yet by the time we get in here. - if ( !g_STDict ) - { - g_STDict = new CUtlDict; - g_RTDict = new CUtlDict; - } - - CUtlDict *pDict = bSendTable ? g_STDict : g_RTDict; - if ( pDict->Find( pRet ) != pDict->InvalidIndex() ) - { - // If it hits this, then they have 2 utlvectors in different data tables with the same name and the - // same size limit. The names of - Assert( false ); - } - pDict->Insert( pRet, 0 ); -#endif - - return pRet; -} diff --git a/public/dt_utlvector_common.h b/public/dt_utlvector_common.h deleted file mode 100644 index e3306e98d..000000000 --- a/public/dt_utlvector_common.h +++ /dev/null @@ -1,78 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef DT_UTLVECTOR_COMMON_H -#define DT_UTLVECTOR_COMMON_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "utlvector.h" - - -typedef void (*EnsureCapacityFn)( void *pVoid, int offsetToUtlVector, int len ); -typedef void (*ResizeUtlVectorFn)( void *pVoid, int offsetToUtlVector, int len ); - -template< class T > -void UtlVector_InitializeAllocatedElements( T *pBase, int count ) -{ - memset( pBase, 0, count * sizeof( T ) ); -} - -template< class T, class A > -class UtlVectorTemplate -{ -public: - static void ResizeUtlVector( void *pStruct, int offsetToUtlVector, int len ) - { - CUtlVector *pVec = (CUtlVector*)((char*)pStruct + offsetToUtlVector); - if ( pVec->Count() < len ) - pVec->AddMultipleToTail( len - pVec->Count() ); - else if ( pVec->Count() > len ) - pVec->RemoveMultiple( len, pVec->Count()-len ); - } - - static void EnsureCapacity( void *pStruct, int offsetToUtlVector, int len ) - { - CUtlVector *pVec = (CUtlVector*)((char*)pStruct + offsetToUtlVector); - - int oldNumAllocated = pVec->Count(); - - if ( oldNumAllocated < len ) - { - pVec->EnsureCapacity( len ); - - // This is important to do because EnsureCapacity doesn't actually call the constructors - // on the elements, but we need them to be initialized, otherwise it'll have out-of-range - // values which will piss off the datatable encoder. - UtlVector_InitializeAllocatedElements( pVec->Base() + oldNumAllocated, len - oldNumAllocated ); - } - } -}; - -template< class T, class A > -inline ResizeUtlVectorFn GetResizeUtlVectorTemplate( CUtlVector &vec ) -{ - return &UtlVectorTemplate::ResizeUtlVector; -} - -template< class T, class A > -inline EnsureCapacityFn GetEnsureCapacityTemplate( CUtlVector &vec ) -{ - return &UtlVectorTemplate::EnsureCapacity; -} - - -// Format and allocate a string. -char* AllocateStringHelper( const char *pFormat, ... ); - -// Allocates a string for a data table name. Data table names must be unique, so this will -// assert if you try to allocate a duplicate. -char* AllocateUniqueDataTableName( bool bSendTable, const char *pFormat, ... ); - - -#endif // DT_UTLVECTOR_COMMON_H diff --git a/public/dt_utlvector_recv.cpp b/public/dt_utlvector_recv.cpp deleted file mode 100644 index 192201a26..000000000 --- a/public/dt_utlvector_recv.cpp +++ /dev/null @@ -1,157 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include "dt_utlvector_recv.h" - -#include "tier0/memdbgon.h" - - -extern const char *s_ClientElementNames[MAX_ARRAY_ELEMENTS]; - - -class CRecvPropExtra_UtlVector -{ -public: - DataTableRecvVarProxyFn m_DataTableProxyFn; // If it's a datatable, then this is the proxy they specified. - RecvVarProxyFn m_ProxyFn; // If it's a non-datatable, then this is the proxy they specified. - ResizeUtlVectorFn m_ResizeFn; // The function used to resize the CUtlVector. - EnsureCapacityFn m_EnsureCapacityFn; - int m_ElementStride; // Distance between each element in the array. - int m_Offset; // Offset of the CUtlVector from its parent structure. - int m_nMaxElements; // For debugging... -}; - -void RecvProxy_UtlVectorLength( const CRecvProxyData *pData, void *pStruct, void *pOut ) -{ - CRecvPropExtra_UtlVector *pExtra = (CRecvPropExtra_UtlVector*)pData->m_pRecvProp->GetExtraData(); - pExtra->m_ResizeFn( pStruct, pExtra->m_Offset, pData->m_Value.m_Int ); -} - -void RecvProxy_UtlVectorElement( const CRecvProxyData *pData, void *pStruct, void *pOut ) -{ - CRecvPropExtra_UtlVector *pExtra = (CRecvPropExtra_UtlVector*)pData->m_pRecvProp->GetExtraData(); - - // Kind of lame overloading element stride to hold the element index, - // but we can easily move it into its SetExtraData stuff if we need to. - int iElement = pData->m_pRecvProp->GetElementStride(); - - // NOTE: this is cheesy, but it does the trick. - CUtlVector *pUtlVec = (CUtlVector*)((char*)pStruct + pExtra->m_Offset); - - // Call through to the proxy they passed in, making pStruct=the CUtlVector. - // Note: there should be space here as long as the element is < the max # elements - // that we ensured capacity for in DataTableRecvProxy_LengthProxy. - pExtra->m_ProxyFn( pData, pOut, (char*)pUtlVec->Base() + iElement*pExtra->m_ElementStride ); -} - -void RecvProxy_UtlVectorElement_DataTable( const RecvProp *pProp, void **pOut, void *pData, int objectID ) -{ - CRecvPropExtra_UtlVector *pExtra = (CRecvPropExtra_UtlVector*)pProp->GetExtraData(); - - int iElement = pProp->GetElementStride(); - Assert( iElement < pExtra->m_nMaxElements ); - - // NOTE: this is cheesy, but it does the trick. - CUtlVector *pUtlVec = (CUtlVector*)((char*)pData + pExtra->m_Offset); - - // Call through to the proxy they passed in, making pStruct=the CUtlVector and forcing iElement to 0. - pExtra->m_DataTableProxyFn( pProp, pOut, (char*)pUtlVec->Base() + iElement*pExtra->m_ElementStride, objectID ); -} - - -void DataTableRecvProxy_LengthProxy( const RecvProp *pProp, void **pOut, void *pData, int objectID ) -{ - // This is VERY important - since it calls all the datatable proxies in the tree first, - // particularly BEFORE it calls our array length proxy, we need to make sure we return - // valid pointers that aren't going to change when it starts to copy the data into - // the datatable elements. - CRecvPropExtra_UtlVector *pExtra = (CRecvPropExtra_UtlVector*)pProp->GetExtraData(); - pExtra->m_EnsureCapacityFn( pData, pExtra->m_Offset, pExtra->m_nMaxElements ); - - *pOut = pData; -} - - -RecvProp RecvPropUtlVector( - const char *pVarName, // Use RECVINFO_UTLVECTOR to generate these 4. - int offset, // Used to generate pData in the function specified in varProxy. - int sizeofVar, // The size of each element in the utlvector. - ResizeUtlVectorFn fn, - EnsureCapacityFn ensureFn, - int nMaxElements, // Max # of elements in the array. Keep this as low as possible. - RecvProp pArrayProp - ) -{ - RecvProp ret; - - Assert( nMaxElements <= MAX_ARRAY_ELEMENTS ); - - ret.m_RecvType = DPT_DataTable; - ret.m_pVarName = pVarName; - ret.SetOffset( 0 ); - ret.SetDataTableProxyFn( DataTableRecvProxy_StaticDataTable ); - - RecvProp *pProps = new RecvProp[nMaxElements+1]; // TODO free that again - - - // Extra data bound to each of the properties. - CRecvPropExtra_UtlVector *pExtraData = new CRecvPropExtra_UtlVector; - - pExtraData->m_nMaxElements = nMaxElements; - pExtraData->m_ElementStride = sizeofVar; - pExtraData->m_ResizeFn = fn; - pExtraData->m_EnsureCapacityFn = ensureFn; - pExtraData->m_Offset = offset; - - if ( pArrayProp.m_RecvType == DPT_DataTable ) - pExtraData->m_DataTableProxyFn = pArrayProp.GetDataTableProxyFn(); - else - pExtraData->m_ProxyFn = pArrayProp.GetProxyFn(); - - - // The first property is datatable with an int that tells the length of the array. - // It has to go in a datatable, otherwise if this array holds datatable properties, it will be received last. - RecvProp *pLengthProp = new RecvProp; - *pLengthProp = RecvPropInt( AllocateStringHelper( "lengthprop%d", nMaxElements ), 0, 0, 0, RecvProxy_UtlVectorLength ); - pLengthProp->SetExtraData( pExtraData ); - - char *pLengthProxyTableName = AllocateUniqueDataTableName( false, "_LPT_%s_%d", pVarName, nMaxElements ); - RecvTable *pLengthTable = new RecvTable( pLengthProp, 1, pLengthProxyTableName ); - pProps[0] = RecvPropDataTable( "lengthproxy", 0, 0, pLengthTable, DataTableRecvProxy_LengthProxy ); - pProps[0].SetExtraData( pExtraData ); - - // The first element is a sub-datatable. - for ( int i = 1; i < nMaxElements+1; i++ ) - { - pProps[i] = pArrayProp; // copy array element property setting - pProps[i].SetOffset( 0 ); // leave offset at 0 so pStructBase is always a pointer to the CUtlVector - pProps[i].m_pVarName = s_ClientElementNames[i-1]; // give unique name - pProps[i].SetExtraData( pExtraData ); - pProps[i].SetElementStride( i-1 ); // Kind of lame overloading element stride to hold the element index, - // but we can easily move it into its SetExtraData stuff if we need to. - - // We provide our own proxy here. - if ( pArrayProp.m_RecvType == DPT_DataTable ) - { - pProps[i].SetDataTableProxyFn( RecvProxy_UtlVectorElement_DataTable ); - } - else - { - pProps[i].SetProxyFn( RecvProxy_UtlVectorElement ); - } - } - - RecvTable *pTable = new RecvTable( - pProps, - nMaxElements+1, - AllocateUniqueDataTableName( false, "_ST_%s_%d", pVarName, nMaxElements ) - ); // TODO free that again - - ret.SetDataTable( pTable ); - return ret; -} diff --git a/public/dt_utlvector_recv.h b/public/dt_utlvector_recv.h deleted file mode 100644 index f9b226190..000000000 --- a/public/dt_utlvector_recv.h +++ /dev/null @@ -1,60 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Player for HL1. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef DT_UTLVECTOR_RECV_H -#define DT_UTLVECTOR_RECV_H -#pragma once - - -#include "dt_recv.h" -#include "dt_utlvector_common.h" - - - -#define RECVINFO_UTLVECTOR( varName ) #varName, \ - offsetof(currentRecvDTClass, varName), \ - sizeof(((currentRecvDTClass*)0)->varName[0]), \ - GetResizeUtlVectorTemplate( ((currentRecvDTClass*)0)->varName ), \ - GetEnsureCapacityTemplate( ((currentRecvDTClass*)0)->varName ) - -// Use this macro to specify a utlvector where you specify the function -// that gets called to make sure the size of the utlvector is correct. -// The size function looks like this: void ResizeUtlVector( void *pVoid, int len ) -#define RECVINFO_UTLVECTOR_SIZEFN( varName, resizeFn ) #varName, \ - offsetof(currentRecvDTClass, varName), \ - sizeof(((currentRecvDTClass*)0)->varName[0]), \ - resizeFn, \ - GetEnsureCapacityTemplate( ((currentRecvDTClass*)0)->varName ) - - -#define RecvPropUtlVectorDataTable( varName, nMaxElements, dataTableName ) \ - RecvPropUtlVector( RECVINFO_UTLVECTOR( varName ), nMaxElements, RecvPropDataTable(NULL,0,0, &REFERENCE_RECV_TABLE( dataTableName ) ) ) - - -// -// Receive a property sent with SendPropUtlVector. -// -// Example usage: -// -// RecvPropUtlVectorDataTable( m_StructArray, 11, DT_StructArray ) -// -// RecvPropUtlVector( RECVINFO_UTLVECTOR( m_FloatArray ), 16, RecvPropFloat(NULL,0,0) ) -// -RecvProp RecvPropUtlVector( - const char *pVarName, // Use RECVINFO_UTLVECTOR to generate these first 5 parameters. - int offset, - int sizeofVar, - ResizeUtlVectorFn fn, - EnsureCapacityFn ensureFn, - - int nMaxElements, // Max # of elements in the array. Keep this as low as possible. - RecvProp pArrayProp // The definition of the property you're receiving into. - // You can leave all of its parameters at 0 (name, offset, size, etc). - ); - - -#endif // DT_UTLVECTOR_RECV_H diff --git a/public/dt_utlvector_send.cpp b/public/dt_utlvector_send.cpp deleted file mode 100644 index a7a49f70d..000000000 --- a/public/dt_utlvector_send.cpp +++ /dev/null @@ -1,210 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include "dt_utlvector_send.h" - -#include "tier0/memdbgon.h" - - -extern const char *s_ElementNames[MAX_ARRAY_ELEMENTS]; - -// This gets associated with SendProps inside a utlvector and stores extra data needed to make it work. -class CSendPropExtra_UtlVector -{ -public: - SendTableProxyFn m_DataTableProxyFn; // If it's a datatable, then this is the proxy they specified. - SendVarProxyFn m_ProxyFn; // If it's a non-datatable, then this is the proxy they specified. - EnsureCapacityFn m_EnsureCapacityFn; - int m_ElementStride; // Distance between each element in the array. - int m_Offset; // # bytes from the parent structure to its utlvector. - int m_nMaxElements; // For debugging... -}; - - -void SendProxy_UtlVectorElement( - const SendProp *pProp, - const void *pStruct, - const void *pData, - DVariant *pOut, - int iElement, - int objectID ) -{ - CSendPropExtra_UtlVector *pExtra = (CSendPropExtra_UtlVector*)pProp->GetExtraData(); - Assert( pExtra ); - - // Kind of lame overloading element stride to hold the element index, - // but we can easily move it into its SetExtraData stuff if we need to. - iElement = pProp->GetElementStride(); - - // NOTE: this is cheesy, but it does the trick. - CUtlVector *pUtlVec = (CUtlVector*)((char*)pStruct + pExtra->m_Offset); - if ( iElement >= pUtlVec->Count() ) - { - // Pass in zero value. - memset( pOut, 0, sizeof( *pOut ) ); - } - else - { - // Call through to the proxy they passed in, making pStruct=the CUtlVector and forcing iElement to 0. - pExtra->m_ProxyFn( pProp, pData, (char*)pUtlVec->Base() + iElement*pExtra->m_ElementStride, pOut, 0, objectID ); - } -} - -void* SendProxy_UtlVectorElement_DataTable( - const SendProp *pProp, - const void *pStructBase, - const void *pData, - CSendProxyRecipients *pRecipients, - int objectID ) -{ - CSendPropExtra_UtlVector *pExtra = (CSendPropExtra_UtlVector*)pProp->GetExtraData(); - - int iElement = pProp->m_ElementStride; - Assert( iElement < pExtra->m_nMaxElements ); - - // This should have gotten called in SendProxy_LengthTable before we get here, so - // the capacity should be correct. -#ifdef _DEBUG - pExtra->m_EnsureCapacityFn( (void*)pStructBase, pExtra->m_Offset, pExtra->m_nMaxElements ); -#endif - - // NOTE: this is cheesy because we're assuming the type of the template class, but it does the trick. - CUtlVector *pUtlVec = (CUtlVector*)((char*)pStructBase + pExtra->m_Offset); - - // Call through to the proxy they passed in, making pStruct=the CUtlVector and forcing iElement to 0. - return pExtra->m_DataTableProxyFn( pProp, pData, (char*)pUtlVec->Base() + iElement*pExtra->m_ElementStride, pRecipients, objectID ); -} - -void SendProxy_UtlVectorLength( - const SendProp *pProp, - const void *pStruct, - const void *pData, - DVariant *pOut, - int iElement, - int objectID ) -{ - CSendPropExtra_UtlVector *pExtra = (CSendPropExtra_UtlVector*)pProp->GetExtraData(); - - // NOTE: this is cheesy because we're assuming the type of the template class, but it does the trick. - CUtlVector *pUtlVec = (CUtlVector*)((char*)pStruct + pExtra->m_Offset); - - // Don't let them overflow the buffer because they might expect that to get transmitted to the client. - pOut->m_Int = pUtlVec->Count(); - if ( pOut->m_Int > pExtra->m_nMaxElements ) - { - Assert( false ); - pOut->m_Int = pExtra->m_nMaxElements; - } -} - - -void* SendProxy_LengthTable( const SendProp *pProp, const void *pStructBase, const void *pData, CSendProxyRecipients *pRecipients, int objectID ) -{ - // Make sure the array has space to hold all the elements. - CSendPropExtra_UtlVector *pExtra = (CSendPropExtra_UtlVector*)pProp->GetExtraData(); - pExtra->m_EnsureCapacityFn( (void*)pStructBase, pExtra->m_Offset, pExtra->m_nMaxElements ); - return (void*)pData; -} - - -// Note: your pArrayProp will NOT get iElement set to anything other than 0, because this function installs its -// own proxy in front of yours. pStruct will point at the CUtlVector and pData will point at the element in the CUtlVector.It will pass you the direct pointer to the element inside the CUtlVector. -// -// You can skip the first 3 parameters in pArrayProp because they're ignored. So your array specification -// could look like this: -// SendPropUtlVector( -// SENDINFO_UTLVECTOR( m_FloatArray ), -// SendPropFloat( NULL, 0, 0, 0 [# bits], SPROP_NOSCALE [flags] ) ); -// -// Note: you have to be DILIGENT about calling NetworkStateChanged whenever an element in your CUtlVector changes -// since CUtlVector doesn't do this automatically. -SendProp SendPropUtlVector( - const char *pVarName, // Use SENDINFO_UTLVECTOR to generate these 4. - int offset, // Used to generate pData in the function specified in varProxy. - int sizeofVar, // The size of each element in the utlvector. - EnsureCapacityFn ensureFn, // This is the value returned for elements out of the array's current range. - int nMaxElements, // Max # of elements in the array. Keep this as low as possible. - SendProp pArrayProp, // Describe the data inside of each element in the array. - SendTableProxyFn varProxy // This can be overridden to control who the array is sent to. - ) -{ - SendProp ret; - - Assert( nMaxElements <= MAX_ARRAY_ELEMENTS ); - - ret.m_Type = DPT_DataTable; - ret.m_pVarName = pVarName; - ret.SetOffset( 0 ); - ret.SetDataTableProxyFn( varProxy ); - - // Handle special proxy types where they always let all clients get the results. - if ( varProxy == SendProxy_DataTableToDataTable || varProxy == SendProxy_DataTablePtrToDataTable ) - { - ret.SetFlags( SPROP_PROXY_ALWAYS_YES ); - } - - - // Extra data bound to each of the properties. - CSendPropExtra_UtlVector *pExtraData = new CSendPropExtra_UtlVector; - - pExtraData->m_nMaxElements = nMaxElements; - pExtraData->m_ElementStride = sizeofVar; - pExtraData->m_EnsureCapacityFn = ensureFn; - pExtraData->m_Offset = offset; - - if ( pArrayProp.m_Type == DPT_DataTable ) - pExtraData->m_DataTableProxyFn = pArrayProp.GetDataTableProxyFn(); - else - pExtraData->m_ProxyFn = pArrayProp.GetProxyFn(); - - - SendProp *pProps = new SendProp[nMaxElements+1]; // TODO free that again - - // The first property is datatable with an int that tells the length of the array. - // It has to go in a datatable, otherwise if this array holds datatable properties, it will be received last. - SendProp *pLengthProp = new SendProp; - *pLengthProp = SendPropInt( AllocateStringHelper( "lengthprop%d", nMaxElements ), 0, 0, NumBitsForCount( nMaxElements ), SPROP_UNSIGNED, SendProxy_UtlVectorLength ); - pLengthProp->SetExtraData( pExtraData ); - - char *pLengthProxyTableName = AllocateUniqueDataTableName( true, "_LPT_%s_%d", pVarName, nMaxElements ); - SendTable *pLengthTable = new SendTable( pLengthProp, 1, pLengthProxyTableName ); - pProps[0] = SendPropDataTable( "lengthproxy", 0, pLengthTable, SendProxy_LengthTable ); - pProps[0].SetExtraData( pExtraData ); - - - // The first element is a sub-datatable. - for ( int i = 1; i < nMaxElements+1; i++ ) - { - pProps[i] = pArrayProp; // copy array element property setting - pProps[i].SetOffset( 0 ); // leave offset at 0 so pStructBase is always a pointer to the CUtlVector - pProps[i].m_pVarName = s_ElementNames[i-1]; // give unique name - pProps[i].SetExtraData( pExtraData ); - pProps[i].m_ElementStride = i-1; // Kind of lame overloading element stride to hold the element index, - // but we can easily move it into its SetExtraData stuff if we need to. - - // We provide our own proxy here. - if ( pArrayProp.m_Type == DPT_DataTable ) - { - pProps[i].SetDataTableProxyFn( SendProxy_UtlVectorElement_DataTable ); - pProps[i].SetFlags( SPROP_PROXY_ALWAYS_YES ); - } - else - { - pProps[i].SetProxyFn( SendProxy_UtlVectorElement ); - } - } - - SendTable *pTable = new SendTable( - pProps, - nMaxElements+1, - AllocateUniqueDataTableName( true, "_ST_%s_%d", pVarName, nMaxElements ) - ); - - ret.SetDataTable( pTable ); - return ret; -} diff --git a/public/dt_utlvector_send.h b/public/dt_utlvector_send.h deleted file mode 100644 index d561d70bc..000000000 --- a/public/dt_utlvector_send.h +++ /dev/null @@ -1,57 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Player for HL1. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef DT_UTLVECTOR_SEND_H -#define DT_UTLVECTOR_SEND_H -#pragma once - - -#include "dt_send.h" -#include "dt_utlvector_common.h" - - -#define SENDINFO_UTLVECTOR( varName ) #varName, \ - offsetof(currentSendDTClass, varName), \ - sizeof(((currentSendDTClass*)0)->varName[0]), \ - GetEnsureCapacityTemplate( ((currentSendDTClass*)0)->varName ) - - - -#define SendPropUtlVectorDataTable( varName, nMaxElements, dataTableName ) \ - SendPropUtlVector( \ - SENDINFO_UTLVECTOR( varName ), \ - nMaxElements, \ - SendPropDataTable( NULL, 0, &REFERENCE_SEND_TABLE( dataTableName ) ) \ - ) - -// -// Set it up to transmit a CUtlVector of basic types or of structures. -// -// pArrayProp doesn't need a name, offset, or size. You can pass 0 for all those. -// Example usage: -// -// SendPropUtlVectorDataTable( m_StructArray, 11, DT_TestStruct ) -// -// SendPropUtlVector( -// SENDINFO_UTLVECTOR( m_FloatArray ), -// 16, // max elements -// SendPropFloat( NULL, 0, 0, 0, SPROP_NOSCALE ) -// ) -// -SendProp SendPropUtlVector( - const char *pVarName, // Use SENDINFO_UTLVECTOR to generate these first 4 parameters. - int offset, - int sizeofVar, - EnsureCapacityFn ensureFn, - - int nMaxElements, // Max # of elements in the array. Keep this as low as possible. - SendProp pArrayProp, // Describe the data inside of each element in the array. - SendTableProxyFn varProxy=SendProxy_DataTableToDataTable // This can be overridden to control who the array is sent to. - ); - - -#endif // DT_UTLVECTOR_SEND_H diff --git a/public/edict.h b/public/edict.h deleted file mode 100644 index fd8b12400..000000000 --- a/public/edict.h +++ /dev/null @@ -1,430 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef EDICT_H -#define EDICT_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "mathlib/vector.h" -#include "cmodel.h" -#include "const.h" -#include "iserverentity.h" -#include "globalvars_base.h" -#include "engine/ICollideable.h" -#include "iservernetworkable.h" -#include "bitvec.h" - -struct edict_t; - - -//----------------------------------------------------------------------------- -// Purpose: Defines the ways that a map can be loaded. -//----------------------------------------------------------------------------- -enum MapLoadType_t -{ - MapLoad_NewGame = 0, - MapLoad_LoadGame, - MapLoad_Transition, - MapLoad_Background, -}; - - -//----------------------------------------------------------------------------- -// Purpose: Global variables shared between the engine and the game .dll -//----------------------------------------------------------------------------- -class CGlobalVars : public CGlobalVarsBase -{ -public: - - CGlobalVars( bool bIsClient ); - -public: - - // Current map - string_t mapname; - int mapversion; - string_t startspot; - MapLoadType_t eLoadType; // How the current map was loaded - bool bMapLoadFailed; // Map has failed to load, we need to kick back to the main menu - - // game specific flags - bool deathmatch; - bool coop; - bool teamplay; - // current maxentities - int maxEntities; -}; - -inline CGlobalVars::CGlobalVars( bool bIsClient ) : - CGlobalVarsBase( bIsClient ) -{ -} - - -class CPlayerState; -class IServerNetworkable; -class IServerEntity; - - -#define FL_EDICT_CHANGED (1<<0) // Game DLL sets this when the entity state changes - // Mutually exclusive with FL_EDICT_PARTIAL_CHANGE. - -#define FL_EDICT_FREE (1<<1) // this edict if free for reuse -#define FL_EDICT_FULL (1<<2) // this is a full server entity - -#define FL_EDICT_FULLCHECK (0<<0) // call ShouldTransmit() each time, this is a fake flag -#define FL_EDICT_ALWAYS (1<<3) // always transmit this entity -#define FL_EDICT_DONTSEND (1<<4) // don't transmit this entity -#define FL_EDICT_PVSCHECK (1<<5) // always transmit entity, but cull against PVS - -// Used by local network backdoor. -#define FL_EDICT_PENDING_DORMANT_CHECK (1<<6) - -// This is always set at the same time EFL_DIRTY_PVS_INFORMATION is set, but it -// gets cleared in a different place. -#define FL_EDICT_DIRTY_PVS_INFORMATION (1<<7) - -// This is used internally to edict_t to remember that it's carrying a -// "full change list" - all its properties might have changed their value. -#define FL_FULL_EDICT_CHANGED (1<<8) - - -// Max # of variable changes we'll track in an entity before we treat it -// like they all changed. -#define MAX_CHANGE_OFFSETS 19 -#define MAX_EDICT_CHANGE_INFOS 100 - - -class CEdictChangeInfo -{ -public: - // Edicts remember the offsets of properties that change - unsigned short m_ChangeOffsets[MAX_CHANGE_OFFSETS]; - unsigned short m_nChangeOffsets; -}; - -// Shared between engine and game DLL. -class CSharedEdictChangeInfo -{ -public: - CSharedEdictChangeInfo() - { - m_iSerialNumber = 1; - } - - // Matched against edict_t::m_iChangeInfoSerialNumber to determine if its - // change info is valid. - unsigned short m_iSerialNumber; - - CEdictChangeInfo m_ChangeInfos[MAX_EDICT_CHANGE_INFOS]; - unsigned short m_nChangeInfos; // How many are in use this frame. -}; -extern CSharedEdictChangeInfo *g_pSharedChangeInfo; - -class IChangeInfoAccessor -{ -public: - inline void SetChangeInfo( unsigned short info ) - { - m_iChangeInfo = info; - } - - inline void SetChangeInfoSerialNumber( unsigned short sn ) - { - m_iChangeInfoSerialNumber = sn; - } - - inline unsigned short GetChangeInfo() const - { - return m_iChangeInfo; - } - - inline unsigned short GetChangeInfoSerialNumber() const - { - return m_iChangeInfoSerialNumber; - } - -private: - unsigned short m_iChangeInfo; - unsigned short m_iChangeInfoSerialNumber; -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -// NOTE: YOU CAN'T CHANGE THE LAYOUT OR SIZE OF CBASEEDICT AND REMAIN COMPATIBLE WITH HL2_VC6!!!!! -class CBaseEdict -{ -public: - - // Returns an IServerEntity if FL_FULLEDICT is set or NULL if this - // is a lightweight networking entity. - IServerEntity* GetIServerEntity(); - const IServerEntity* GetIServerEntity() const; - - IServerNetworkable* GetNetworkable(); - IServerUnknown* GetUnknown(); - - // Set when initting an entity. If it's only a networkable, this is false. - void SetEdict( IServerUnknown *pUnk, bool bFullEdict ); - - int AreaNum() const; - const char * GetClassName() const; - - bool IsFree() const; - void SetFree(); - void ClearFree(); - - bool HasStateChanged() const; - void ClearStateChanged(); - void StateChanged(); - void StateChanged( unsigned short offset ); - - void ClearTransmitState(); - - void SetChangeInfo( unsigned short info ); - void SetChangeInfoSerialNumber( unsigned short sn ); - unsigned short GetChangeInfo() const; - unsigned short GetChangeInfoSerialNumber() const; - -public: - - // NOTE: this is in the edict instead of being accessed by a virtual because the engine needs fast access to it. - // NOTE: YOU CAN'T CHANGE THE LAYOUT OR SIZE OF CBASEEDICT AND REMAIN COMPATIBLE WITH HL2_VC6!!!!! -#ifdef _XBOX - unsigned short m_fStateFlags; -#else - int m_fStateFlags; -#endif - - // NOTE: this is in the edict instead of being accessed by a virtual because the engine needs fast access to it. - short m_NetworkSerialNumber; // Game DLL sets this when it gets a serial number for its EHANDLE. - short m_iIndex; - - // NOTE: this is in the edict instead of being accessed by a virtual because the engine needs fast access to it. - IServerNetworkable *m_pNetworkable; - -protected: - IServerUnknown *m_pUnk; - - -public: - - IChangeInfoAccessor *GetChangeAccessor(); // The engine implements this and the game .dll implements as - const IChangeInfoAccessor *GetChangeAccessor() const; // The engine implements this and the game .dll implements as - // as callback through to the engine!!! - - // NOTE: YOU CAN'T CHANGE THE LAYOUT OR SIZE OF CBASEEDICT AND REMAIN COMPATIBLE WITH HL2_VC6!!!!! - // This breaks HL2_VC6!!!!! - // References a CEdictChangeInfo with a list of modified network props. - //unsigned short m_iChangeInfo; - //unsigned short m_iChangeInfoSerialNumber; - - friend void InitializeEntityDLLFields( edict_t *pEdict ); -}; - - -//----------------------------------------------------------------------------- -// CBaseEdict inlines. -//----------------------------------------------------------------------------- -inline IServerEntity* CBaseEdict::GetIServerEntity() -{ - if ( m_fStateFlags & FL_EDICT_FULL ) - return (IServerEntity*)m_pUnk; - else - return 0; -} - -inline bool CBaseEdict::IsFree() const -{ - return (m_fStateFlags & FL_EDICT_FREE) != 0; -} - - - -inline bool CBaseEdict::HasStateChanged() const -{ - return (m_fStateFlags & FL_EDICT_CHANGED) != 0; -} - -inline void CBaseEdict::ClearStateChanged() -{ - m_fStateFlags &= ~(FL_EDICT_CHANGED | FL_FULL_EDICT_CHANGED); - SetChangeInfoSerialNumber( 0 ); -} - -inline void CBaseEdict::StateChanged() -{ - // Note: this should only happen for properties in data tables that used some - // kind of pointer dereference. If the data is directly offsetable - m_fStateFlags |= (FL_EDICT_CHANGED | FL_FULL_EDICT_CHANGED); - SetChangeInfoSerialNumber( 0 ); -} - -inline void CBaseEdict::StateChanged( unsigned short offset ) -{ - if ( m_fStateFlags & FL_FULL_EDICT_CHANGED ) - return; - - m_fStateFlags |= FL_EDICT_CHANGED; - - IChangeInfoAccessor *accessor = GetChangeAccessor(); - - if ( accessor->GetChangeInfoSerialNumber() == g_pSharedChangeInfo->m_iSerialNumber ) - { - // Ok, I still own this one. - CEdictChangeInfo *p = &g_pSharedChangeInfo->m_ChangeInfos[accessor->GetChangeInfo()]; - - // Now add this offset to our list of changed variables. - for ( unsigned short i=0; i < p->m_nChangeOffsets; i++ ) - if ( p->m_ChangeOffsets[i] == offset ) - return; - - if ( p->m_nChangeOffsets == MAX_CHANGE_OFFSETS ) - { - // Invalidate our change info. - accessor->SetChangeInfoSerialNumber( 0 ); - m_fStateFlags |= FL_FULL_EDICT_CHANGED; // So we don't get in here again. - } - else - { - p->m_ChangeOffsets[p->m_nChangeOffsets++] = offset; - } - } - else - { - if ( g_pSharedChangeInfo->m_nChangeInfos == MAX_EDICT_CHANGE_INFOS ) - { - // Shucks.. have to mark the edict as fully changed because we don't have room to remember this change. - accessor->SetChangeInfoSerialNumber( 0 ); - m_fStateFlags |= FL_FULL_EDICT_CHANGED; - } - else - { - // Get a new CEdictChangeInfo and fill it out. - accessor->SetChangeInfo( g_pSharedChangeInfo->m_nChangeInfos ); - g_pSharedChangeInfo->m_nChangeInfos++; - - accessor->SetChangeInfoSerialNumber( g_pSharedChangeInfo->m_iSerialNumber ); - - CEdictChangeInfo *p = &g_pSharedChangeInfo->m_ChangeInfos[accessor->GetChangeInfo()]; - p->m_ChangeOffsets[0] = offset; - p->m_nChangeOffsets = 1; - } - } -} - - - -inline void CBaseEdict::SetFree() -{ - m_fStateFlags |= FL_EDICT_FREE; -} - -inline void CBaseEdict::ClearFree() -{ - m_fStateFlags &= ~FL_EDICT_FREE; -} - -inline void CBaseEdict::ClearTransmitState() -{ - m_fStateFlags &= ~(FL_EDICT_ALWAYS|FL_EDICT_PVSCHECK|FL_EDICT_DONTSEND); -} - -inline const IServerEntity* CBaseEdict::GetIServerEntity() const -{ - if ( m_fStateFlags & FL_EDICT_FULL ) - return (IServerEntity*)m_pUnk; - else - return 0; -} - -inline IServerUnknown* CBaseEdict::GetUnknown() -{ - return m_pUnk; -} - -inline IServerNetworkable* CBaseEdict::GetNetworkable() -{ - return m_pNetworkable; -} - -inline void CBaseEdict::SetEdict( IServerUnknown *pUnk, bool bFullEdict ) -{ - m_pUnk = pUnk; - if ( (pUnk != NULL) && bFullEdict ) - { - m_fStateFlags = FL_EDICT_FULL; - } - else - { - m_fStateFlags = 0; - } -} - -inline int CBaseEdict::AreaNum() const -{ - if ( !m_pUnk ) - return 0; - - return m_pNetworkable->AreaNum(); -} - -inline const char * CBaseEdict::GetClassName() const -{ - if ( !m_pUnk ) - return ""; - return m_pNetworkable->GetClassName(); -} - -inline void CBaseEdict::SetChangeInfo( unsigned short info ) -{ - GetChangeAccessor()->SetChangeInfo( info ); -} - -inline void CBaseEdict::SetChangeInfoSerialNumber( unsigned short sn ) -{ - GetChangeAccessor()->SetChangeInfoSerialNumber( sn ); -} - -inline unsigned short CBaseEdict::GetChangeInfo() const -{ - return GetChangeAccessor()->GetChangeInfo(); -} - -inline unsigned short CBaseEdict::GetChangeInfoSerialNumber() const -{ - return GetChangeAccessor()->GetChangeInfoSerialNumber(); -} - -//----------------------------------------------------------------------------- -// Purpose: The engine's internal representation of an entity, including some -// basic collision and position info and a pointer to the class wrapped on top -// of the structure -//----------------------------------------------------------------------------- -struct edict_t : public CBaseEdict -{ -public: - ICollideable *GetCollideable(); - - // The server timestampe at which the edict was freed (so we can try to use other edicts before reallocating this one) - float freetime; -}; - -inline ICollideable *edict_t::GetCollideable() -{ - IServerEntity *pEnt = GetIServerEntity(); - if ( pEnt ) - return pEnt->GetCollideable(); - else - return NULL; -} - - -#endif // EDICT_H diff --git a/public/editor_sendcommand.cpp b/public/editor_sendcommand.cpp deleted file mode 100644 index ef17a5e24..000000000 --- a/public/editor_sendcommand.cpp +++ /dev/null @@ -1,228 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Implements an interface to the map editor for the execution of -// editor shell commands from another application. Commands allow the -// creation and deletion of entities, AI nodes, and AI node connections. -// -// $NoKeywords: $ -//=============================================================================// - -#if !defined(_STATIC_LINKED) || defined(_SHARED_LIB) - -#if !defined(_X360) && defined(_WIN32) -#include -#endif -#include -#include "editor_sendcommand.h" -#include "tier1/strtools.h" -#include "mathlib/vector.h" - -#if defined( _X360 ) -#include "xbox/xbox_win32stubs.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -const int MAX_COMMAND_BUFFER = 2048; -//----------------------------------------------------------------------------- -// Purpose: Sends a command to the editor (if running) to begin an editing session -// of a given map. -// Input : pszMapName - Name of the bsp, without the path or extension: "c1a3a_port" -// nMapVersion - Map version number, from the BSP file. -// Output : Returns Editor_OK on success, an error code if the session was rejected. -//----------------------------------------------------------------------------- -EditorSendResult_t Editor_BeginSession(const char *pszMapName, int nMapVersion, bool bShowUI) -{ - char szCommand[MAX_COMMAND_BUFFER]; - Q_snprintf(szCommand,sizeof(szCommand), "session_begin %s %d", pszMapName, nMapVersion); - return(Editor_SendCommand(szCommand, bShowUI)); -} - - -//----------------------------------------------------------------------------- -// Purpose: Sends a command to the editor (if running) to verify the version and -// map name being edited. -// Input : pszMapName - Name of the bsp, without the path or extension: "c1a3a_port" -// nMapVersion - Map version number, from the BSP file. -// Output : Returns Editor_OK on success, an error code if the session was rejected. -//----------------------------------------------------------------------------- -EditorSendResult_t Editor_CheckVersion(const char *pszMapName, int nMapVersion, bool bShowUI) -{ - char szCommand[MAX_COMMAND_BUFFER]; - Q_snprintf(szCommand,sizeof(szCommand), "map_check_version %s %d", pszMapName, nMapVersion); - return(Editor_SendCommand(szCommand, bShowUI)); -} - - -//----------------------------------------------------------------------------- -// Purpose: Sends a command to the editor (if running) to create an entity at -// a given (x, y, z) coordinate. -// Input : pszEntity - Class name of entity to create, ie "info_player_start". -// x, y, z - World coordinates at which to create entity. -// Output : Returns Editor_OK on success, an error code on failure. -//----------------------------------------------------------------------------- -EditorSendResult_t Editor_CreateEntity(const char *pszEntity, float x, float y, float z, bool bShowUI) -{ - char szCommand[MAX_COMMAND_BUFFER]; - Q_snprintf(szCommand,sizeof(szCommand), "entity_create %s %g %g %g", pszEntity, x, y, z); - return(Editor_SendCommand(szCommand, bShowUI)); -} - - -//----------------------------------------------------------------------------- -// Purpose: Sends a command to the editor (if running) to create an entity at -// a given (x, y, z) coordinate. -// Input : pszNodeClass - Class name of node to create, ie "info_node". -// nID - Unique ID to assign the node. -// x, y, z - World coordinates at which to create node. -// Output : Returns Editor_OK on success, an error code on failure. -//----------------------------------------------------------------------------- -EditorSendResult_t Editor_CreateNode(const char *pszNodeClass, int nID, float x, float y, float z, bool bShowUI) -{ - char szCommand[MAX_COMMAND_BUFFER]; - Q_snprintf(szCommand,sizeof(szCommand), "node_create %s %d %g %g %g", pszNodeClass, nID, x, y, z); - return(Editor_SendCommand(szCommand, bShowUI)); -} - - -//----------------------------------------------------------------------------- -// Purpose: Sends a command to the editor (if running) to create an entity at -// a given (x, y, z) coordinate. -// Input : pszNodeClass - Class name of node to create, ie "info_node". -// nID - Unique ID to assign the node. -// x, y, z - World coordinates at which to create node. -// Output : Returns Editor_OK on success, an error code on failure. -//----------------------------------------------------------------------------- -EditorSendResult_t Editor_CreateNodeLink(int nStartID, int nEndID, bool bShowUI) -{ - char szCommand[MAX_COMMAND_BUFFER]; - Q_snprintf(szCommand,sizeof(szCommand), "nodelink_create %d %d", nStartID, nEndID); - return(Editor_SendCommand(szCommand, bShowUI)); -} - - -//----------------------------------------------------------------------------- -// Purpose: Sends a command to the editor (if running) to delete an entity at -// a given (x, y, z) coordinate. -// Input : pszEntity - Class name of entity to delete, ie "info_player_start". -// x, y, z - World coordinates of entity to delete. -// Output : Returns Editor_OK on success, an error code on failure. -//----------------------------------------------------------------------------- -EditorSendResult_t Editor_DeleteEntity(const char *pszEntity, float x, float y, float z, bool bShowUI) -{ - char szCommand[MAX_COMMAND_BUFFER]; - Q_snprintf(szCommand,sizeof(szCommand), "entity_delete %s %g %g %g", pszEntity, x, y, z); - return(Editor_SendCommand(szCommand, bShowUI)); -} - - -// sets an arbitrary key/value pair in the entity -EditorSendResult_t Editor_SetKeyValue(const char *pszEntity, float x, float y, float z, const char *pKey, const char *pValue, bool bShowUI) -{ - char szCommand[MAX_COMMAND_BUFFER]; - Q_snprintf(szCommand,sizeof(szCommand), "entity_set_keyvalue %s %f %f %f \"%s\" \"%s\"", pszEntity, x, y, z, pKey, pValue); - return(Editor_SendCommand(szCommand, bShowUI)); -} - - -// applies an incremental rotation to an entity -EditorSendResult_t Editor_RotateEntity(const char *pszEntity, float x, float y, float z, const QAngle &incrementalRotation, bool bShowUI) -{ - char szCommand[MAX_COMMAND_BUFFER]; - Q_snprintf(szCommand,sizeof(szCommand), "entity_rotate_incremental %s %f %f %f %f %f %f", pszEntity, x, y, z, incrementalRotation.x, incrementalRotation.y, incrementalRotation.z ); - return(Editor_SendCommand(szCommand, bShowUI)); -} -//----------------------------------------------------------------------------- -// Purpose: Sends a command to the editor (if running) to delete an entity at -// a given (x, y, z) coordinate. -// Input : nID - unique ID of node to delete. -// Output : Returns Editor_OK on success, an error code on failure. -//----------------------------------------------------------------------------- -EditorSendResult_t Editor_DeleteNode(int nID, bool bShowUI) -{ - char szCommand[MAX_COMMAND_BUFFER]; - Q_snprintf(szCommand,sizeof(szCommand), "node_delete %d", nID); - return(Editor_SendCommand(szCommand, bShowUI)); -} - - -//----------------------------------------------------------------------------- -// Purpose: Sends a command to the editor (if running) to delete an entity at -// a given (x, y, z) coordinate. -// Input : nStartID - unique ID of one node that the link is connected to. -// nEndID - unique ID of the other node that the link is connected to. -// Output : Returns Editor_OK on success, an error code on failure. -//----------------------------------------------------------------------------- -EditorSendResult_t Editor_DeleteNodeLink(int nStartID, int nEndID, bool bShowUI) -{ - char szCommand[MAX_COMMAND_BUFFER]; - Q_snprintf(szCommand,sizeof(szCommand), "nodelink_delete %d %d", nStartID, nEndID); - return(Editor_SendCommand(szCommand, bShowUI)); -} - - -//----------------------------------------------------------------------------- -// Purpose: Sends a command to the editor (if running) to end the current remote -// editing session. -// Output : Returns Editor_OK on success, an error code if the session was rejected. -//----------------------------------------------------------------------------- -EditorSendResult_t Editor_EndSession(bool bShowUI) -{ - return(Editor_SendCommand("session_end", bShowUI)); -} - - -//----------------------------------------------------------------------------- -// Purpose: Attempts to sends a shell command to the editor. -// Input : pszCommand - Shell command to send. -// bShowUI - Whether to display mesage boxes on failure. -// Output : Returns one of the following values: -// Editor_OK - The command was executed successfully. -// Editor_NotRunning - Unable to establish a communications channel with the editor. -// Editor_BadCommand - The editor did not accept the command. -//----------------------------------------------------------------------------- -EditorSendResult_t Editor_SendCommand(const char *pszCommand, bool bShowUI) -{ -#ifdef _WIN32 - HWND hwnd = FindWindow("Worldcraft_ShellMessageWnd", "Worldcraft_ShellMessageWnd"); - if (hwnd != NULL) - { - // - // Fill out the data structure to send to the editor. - // - - COPYDATASTRUCT CopyData; - CopyData.cbData = strlen(pszCommand) + 1; - CopyData.dwData = 0; - CopyData.lpData = (void *)pszCommand; - - if (!SendMessage(hwnd, WM_COPYDATA, 0, (LPARAM)&CopyData)) - { - if (bShowUI) - { - char szError[1024]; - Q_snprintf(szError,sizeof(szError), "Worldcraft did not accept the command: \n\n\"%s\"\n\n Make sure the command is valid and that Worldcraft is still running properly.", pszCommand); - MessageBox(NULL, szError, "Editor_SendCommand Error", MB_OK); - } - - return(Editor_BadCommand); - } - } - else - { - if (bShowUI) - { - char szError[1024]; - Q_snprintf(szError,sizeof(szError), "Could not contact Worldcraft to send the command: \n\n\"%s\"\n\n Worldcraft does not appear to be running.", pszCommand); - MessageBox(NULL, szError, "Editor_SendCommand Error", MB_OK); - } - - return(Editor_NotRunning); - } -#endif - - return(Editor_OK); -} - -#endif // !_STATIC_LINKED || _SHARED_LIB diff --git a/public/editor_sendcommand.h b/public/editor_sendcommand.h deleted file mode 100644 index 3f6649b43..000000000 --- a/public/editor_sendcommand.h +++ /dev/null @@ -1,52 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Defines an interface to the map editor for the execution of -// editor shell commands from another application. Commands allow the -// creation and deletion of entities, AI nodes, and AI node connections. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef EDITOR_SENDCOMMAND_H -#define EDITOR_SENDCOMMAND_H -#pragma once - -class QAngle; - -// -// Result codes from Worldcraft_SendCommand. -// -enum EditorSendResult_t -{ - Editor_OK = 0, // Success. - Editor_NotRunning, // Unable to establish a communications channel with the editor. - Editor_BadCommand, // The editor did not accept the command. -}; - - -// -// Wrappers around specific commands for convenience. -// -EditorSendResult_t Editor_BeginSession(const char *pszMapName, int nMapVersion, bool bShowUI = false); -EditorSendResult_t Editor_EndSession(bool bShowUI); -EditorSendResult_t Editor_CheckVersion(const char *pszMapName, int nMapVersion, bool bShowUI = false); - -EditorSendResult_t Editor_CreateEntity(const char *pszEntity, float x, float y, float z, bool bShowUI = false); -EditorSendResult_t Editor_DeleteEntity(const char *pszEntity, float x, float y, float z, bool bShowUI = false); -EditorSendResult_t Editor_SetKeyValue(const char *pszEntity, float x, float y, float z, const char *pKey, const char *pValue, bool bShowUI = false); -EditorSendResult_t Editor_RotateEntity(const char *pszEntity, float x, float y, float z, const QAngle &incrementalRotation, bool bShowUI = false); - -EditorSendResult_t Editor_CreateNode(const char *pszNodeClass, int nID, float x, float y, float z, bool bShowUI = false); -EditorSendResult_t Editor_DeleteNode(int nID, bool bShowUI = false); - -EditorSendResult_t Editor_CreateNodeLink(int nStartID, int nEndID, bool bShowUI = false); -EditorSendResult_t Editor_DeleteNodeLink(int nStartID, int nEndID, bool bShowUI = false); - - -// -// Actually does the work. All the above commands route through this. -// -EditorSendResult_t Editor_SendCommand(const char *pszCommand, bool bShowUI); - - -#endif // EDITOR_SENDCOMMAND_H diff --git a/public/eiface.h b/public/eiface.h deleted file mode 100644 index c363392fc..000000000 --- a/public/eiface.h +++ /dev/null @@ -1,778 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// - -#ifndef EIFACE_H -#define EIFACE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "convar.h" -#include "icvar.h" -#include "edict.h" -#include "mathlib/vplane.h" -#include "iserverentity.h" -#include "engine/ivmodelinfo.h" -#include "soundflags.h" -#include "bitvec.h" -#include "engine/iserverplugin.h" -#include "tier1/bitbuf.h" - -//----------------------------------------------------------------------------- -// forward declarations -//----------------------------------------------------------------------------- -class SendTable; -class ServerClass; -class IMoveHelper; -struct Ray_t; -class CGameTrace; -typedef CGameTrace trace_t; -struct typedescription_t; -class CSaveRestoreData; -struct datamap_t; -class SendTable; -class ServerClass; -class IMoveHelper; -struct Ray_t; -struct studiohdr_t; -class CBaseEntity; -class CRestore; -class CSave; -class variant_t; -struct vcollide_t; -class IRecipientFilter; -class CBaseEntity; -class ITraceFilter; -struct client_textmessage_t; -class INetChannelInfo; -class ISpatialPartition; -class IScratchPad3D; -class CStandardSendProxies; -class IAchievementMgr; -class CGamestatsData; -class CSteamID; -class IReplayFactory; -class IReplaySystem; -class IServer; - -typedef struct player_info_s player_info_t; - -//----------------------------------------------------------------------------- -// defines -//----------------------------------------------------------------------------- - -#ifdef _WIN32 -#define DLLEXPORT __stdcall -#else -#define DLLEXPORT /* */ -#endif - -#define INTERFACEVERSION_VENGINESERVER_VERSION_21 "VEngineServer021" -#define INTERFACEVERSION_VENGINESERVER "VEngineServer022" -#define INTERFACEVERSION_VENGINESERVER_INT 22 - -struct bbox_t -{ - Vector mins; - Vector maxs; -}; - -// Except in the case of an exact match, pMapName is updated to the canonical name of the match. -// NOTE That this is subject to the same limitation as ServerGameDLL::CanProvideLevel -- This is non-blocking, so it -// is possible that blocking ServerGameDLL::PrepareLevelResources call may be able to pull a better match than -// is immediately available to this call (e.g. blocking lookups of cloud maps) -enum eFindMapResult { - // A direct match for this name was found - eFindMap_Found, - // No match for this map name could be found. - eFindMap_NotFound, - // A fuzzy match for this mapname was found and pMapName was updated to the full name. - // Ex: cp_dust -> cp_dustbowl - eFindMap_FuzzyMatch, - // A match for this map name was found, and the map name was updated to the canonical version of the - // name. - // Ex: workshop/1234 -> workshop/cp_qualified_name.ugc1234 - eFindMap_NonCanonical, - // No currently available match for this map name could be found, but it may be possible to load ( see caveat - // about PrepareLevelResources above ) - eFindMap_PossiblyAvailable -}; - -//----------------------------------------------------------------------------- -// Purpose: Interface the engine exposes to the game DLL -//----------------------------------------------------------------------------- -abstract_class IVEngineServer -{ -public: - // Tell engine to change level ( "changelevel s1\n" or "changelevel2 s1 s2\n" ) - virtual void ChangeLevel(const char *s1, const char *s2) = 0; - - // Ask engine whether the specified map is a valid map file (exists and has valid version number). - virtual int IsMapValid(const char *filename) = 0; - - // Is this a dedicated server? - virtual bool IsDedicatedServer(void) = 0; - - // Is in Hammer editing mode? - virtual int IsInEditMode(void) = 0; - - // Add to the server/client lookup/precache table, the specified string is given a unique index - // NOTE: The indices for PrecacheModel are 1 based - // a 0 returned from those methods indicates the model or sound was not correctly precached - // However, generic and decal are 0 based - // If preload is specified, the file is loaded into the server/client's cache memory before level startup, otherwise - // it'll only load when actually used (which can cause a disk i/o hitch if it occurs during play of a level). - virtual int PrecacheModel(const char *s, bool preload = false) = 0; - virtual int PrecacheSentenceFile(const char *s, bool preload = false) = 0; - virtual int PrecacheDecal(const char *name, bool preload = false) = 0; - virtual int PrecacheGeneric(const char *s, bool preload = false) = 0; - - // Check's if the name is precached, but doesn't actually precache the name if not... - virtual bool IsModelPrecached(char const *s) const = 0; - virtual bool IsDecalPrecached(char const *s) const = 0; - virtual bool IsGenericPrecached(char const *s) const = 0; - - // Note that sounds are precached using the IEngineSound interface - - // Special purpose PVS checking - // Get the cluster # for the specified position - virtual int GetClusterForOrigin(const Vector &org) = 0; - // Get the PVS bits for a specified cluster and copy the bits into outputpvs. Returns the number of bytes needed to pack the PVS - virtual int GetPVSForCluster(int cluster, int outputpvslength, unsigned char *outputpvs) = 0; - // Check whether the specified origin is inside the specified PVS - virtual bool CheckOriginInPVS(const Vector &org, const unsigned char *checkpvs, int checkpvssize) = 0; - // Check whether the specified worldspace bounding box is inside the specified PVS - virtual bool CheckBoxInPVS(const Vector &mins, const Vector &maxs, const unsigned char *checkpvs, int checkpvssize) = 0; - - // Returns the server assigned userid for this player. Useful for logging frags, etc. - // returns -1 if the edict couldn't be found in the list of players. - virtual int GetPlayerUserId(const edict_t *e) = 0; - virtual const char *GetPlayerNetworkIDString(const edict_t *e) = 0; - - // Return the current number of used edict slots - virtual int GetEntityCount(void) = 0; - // Given an edict, returns the entity index - virtual int IndexOfEdict(const edict_t *pEdict) = 0; - // Given and entity index, returns the corresponding edict pointer - virtual edict_t *PEntityOfEntIndex(int iEntIndex) = 0; - - // Get stats info interface for a client netchannel - virtual INetChannelInfo* GetPlayerNetInfo(int playerIndex) = 0; - - // Allocate space for string and return index/offset of string in global string list - // If iForceEdictIndex is not -1, then it will return the edict with that index. If that edict index - // is already used, it'll return null. - virtual edict_t *CreateEdict(int iForceEdictIndex = -1) = 0; - // Remove the specified edict and place back into the free edict list - virtual void RemoveEdict(edict_t *e) = 0; - - // Memory allocation for entity class data - virtual void *PvAllocEntPrivateData(long cb) = 0; - virtual void FreeEntPrivateData(void *pEntity) = 0; - - // Save/restore uses a special memory allocator (which zeroes newly allocated memory, etc.) - virtual void *SaveAllocMemory(size_t num, size_t size) = 0; - virtual void SaveFreeMemory(void *pSaveMem) = 0; - - // Emit an ambient sound associated with the specified entity - virtual void EmitAmbientSound(int entindex, const Vector &pos, const char *samp, float vol, soundlevel_t soundlevel, int fFlags, int pitch, float delay = 0.0f) = 0; - - // Fade out the client's volume level toward silence (or fadePercent) - virtual void FadeClientVolume(const edict_t *pEdict, float fadePercent, float fadeOutSeconds, float holdTime, float fadeInSeconds) = 0; - - // Sentences / sentence groups - virtual int SentenceGroupPick(int groupIndex, char *name, int nameBufLen) = 0; - virtual int SentenceGroupPickSequential(int groupIndex, char *name, int nameBufLen, int sentenceIndex, int reset) = 0; - virtual int SentenceIndexFromName(const char *pSentenceName) = 0; - virtual const char *SentenceNameFromIndex(int sentenceIndex) = 0; - virtual int SentenceGroupIndexFromName(const char *pGroupName) = 0; - virtual const char *SentenceGroupNameFromIndex(int groupIndex) = 0; - virtual float SentenceLength(int sentenceIndex) = 0; - - // Issue a command to the command parser as if it was typed at the server console. - virtual void ServerCommand(const char *str) = 0; - // Execute any commands currently in the command parser immediately (instead of once per frame) - virtual void ServerExecute(void) = 0; - // Issue the specified command to the specified client (mimics that client typing the command at the console). - virtual void ClientCommand(edict_t *pEdict, const char *szFmt, ...) = 0; - - // Set the lightstyle to the specified value and network the change to any connected clients. Note that val must not - // change place in memory (use MAKE_STRING) for anything that's not compiled into your mod. - virtual void LightStyle(int style, const char *val) = 0; - - // Project a static decal onto the specified entity / model (for level placed decals in the .bsp) - virtual void StaticDecal(const Vector &originInEntitySpace, int decalIndex, int entityIndex, int modelIndex, bool lowpriority) = 0; - - // Given the current PVS(or PAS) and origin, determine which players should hear/receive the message - virtual void Message_DetermineMulticastRecipients(bool usepas, const Vector& origin, CBitVec< ABSOLUTE_PLAYER_LIMIT >& playerbits) = 0; - - // Begin a message from a server side entity to its client side counterpart (func_breakable glass, e.g.) - virtual bf_write *EntityMessageBegin(int ent_index, ServerClass * ent_class, bool reliable) = 0; - // Begin a usermessage from the server to the client .dll - virtual bf_write *UserMessageBegin(IRecipientFilter *filter, int msg_type) = 0; - // Finish the Entity or UserMessage and dispatch to network layer - virtual void MessageEnd(void) = 0; - - // Print szMsg to the client console. - virtual void ClientPrintf(edict_t *pEdict, const char *szMsg) = 0; - - // SINGLE PLAYER/LISTEN SERVER ONLY (just matching the client .dll api for this) - // Prints the formatted string to the notification area of the screen ( down the right hand edge - // numbered lines starting at position 0 - virtual void Con_NPrintf(int pos, const char *fmt, ...) = 0; - // SINGLE PLAYER/LISTEN SERVER ONLY(just matching the client .dll api for this) - // Similar to Con_NPrintf, but allows specifying custom text color and duration information - virtual void Con_NXPrintf(const struct con_nprint_s *info, const char *fmt, ...) = 0; - - // Change a specified player's "view entity" (i.e., use the view entity position/orientation for rendering the client view) - virtual void SetView(const edict_t *pClient, const edict_t *pViewent) = 0; - - // Get a high precision timer for doing profiling work - virtual float Time(void) = 0; - - // Set the player's crosshair angle - virtual void CrosshairAngle(const edict_t *pClient, float pitch, float yaw) = 0; - - // Get the current game directory (hl2, tf2, hl1, cstrike, etc.) - virtual void GetGameDir(char *szGetGameDir, int maxlength) = 0; - - // Used by AI node graph code to determine if .bsp and .ain files are out of date - virtual int CompareFileTime(const char *filename1, const char *filename2, int *iCompare) = 0; - - // Locks/unlocks the network string tables (.e.g, when adding bots to server, this needs to happen). - // Be sure to reset the lock after executing your code!!! - virtual bool LockNetworkStringTables(bool lock) = 0; - - // Create a bot with the given name. Returns NULL if fake client can't be created - virtual edict_t *CreateFakeClient(const char *netname) = 0; - - // Get a convar keyvalue for s specified client - virtual const char *GetClientConVarValue(int clientIndex, const char *name) = 0; - - // Parse a token from a file - virtual const char *ParseFile(const char *data, char *token, int maxlen) = 0; - // Copies a file - virtual bool CopyFile(const char *source, const char *destination) = 0; - - // Reset the pvs, pvssize is the size in bytes of the buffer pointed to by pvs. - // This should be called right before any calls to AddOriginToPVS - virtual void ResetPVS(byte *pvs, int pvssize) = 0; - // Merge the pvs bits into the current accumulated pvs based on the specified origin ( not that each pvs origin has an 8 world unit fudge factor ) - virtual void AddOriginToPVS(const Vector &origin) = 0; - - // Mark a specified area portal as open/closed. - // Use SetAreaPortalStates if you want to set a bunch of them at a time. - virtual void SetAreaPortalState(int portalNumber, int isOpen) = 0; - - // Queue a temp entity for transmission - virtual void PlaybackTempEntity(IRecipientFilter& filter, float delay, const void *pSender, const SendTable *pST, int classID) = 0; - // Given a node number and the specified PVS, return with the node is in the PVS - virtual int CheckHeadnodeVisible(int nodenum, const byte *pvs, int vissize) = 0; - // Using area bits, cheeck whether area1 flows into area2 and vice versa (depends on area portal state) - virtual int CheckAreasConnected(int area1, int area2) = 0; - // Given an origin, determine which area index the origin is within - virtual int GetArea(const Vector &origin) = 0; - // Get area portal bit set - virtual void GetAreaBits(int area, unsigned char *bits, int buflen) = 0; - // Given a view origin (which tells us the area to start looking in) and a portal key, - // fill in the plane that leads out of this area (it points into whatever area it leads to). - virtual bool GetAreaPortalPlane(Vector const &vViewOrigin, int portalKey, VPlane *pPlane) = 0; - - // Save/restore wrapper - FIXME: At some point we should move this to it's own interface - virtual bool LoadGameState(char const *pMapName, bool createPlayers) = 0; - virtual void LoadAdjacentEnts(const char *pOldLevel, const char *pLandmarkName) = 0; - virtual void ClearSaveDir() = 0; - - // Get the pristine map entity lump string. (e.g., used by CS to reload the map entities when restarting a round.) - virtual const char* GetMapEntitiesString() = 0; - - // Text message system -- lookup the text message of the specified name - virtual client_textmessage_t *TextMessageGet(const char *pName) = 0; - - // Print a message to the server log file - virtual void LogPrint(const char *msg) = 0; - - // Builds PVS information for an entity - virtual void BuildEntityClusterList(edict_t *pEdict, PVSInfo_t *pPVSInfo) = 0; - - // A solid entity moved, update spatial partition - virtual void SolidMoved(edict_t *pSolidEnt, ICollideable *pSolidCollide, const Vector* pPrevAbsOrigin, bool testSurroundingBoundsOnly) = 0; - // A trigger entity moved, update spatial partition - virtual void TriggerMoved(edict_t *pTriggerEnt, bool testSurroundingBoundsOnly) = 0; - - // Create/destroy a custom spatial partition - virtual ISpatialPartition *CreateSpatialPartition(const Vector& worldmin, const Vector& worldmax) = 0; - virtual void DestroySpatialPartition(ISpatialPartition *) = 0; - - // Draw the brush geometry in the map into the scratch pad. - // Flags is currently unused. - virtual void DrawMapToScratchPad(IScratchPad3D *pPad, unsigned long iFlags) = 0; - - // This returns which entities, to the best of the server's knowledge, the client currently knows about. - // This is really which entities were in the snapshot that this client last acked. - // This returns a bit vector with one bit for each entity. - // - // USE WITH CARE. Whatever tick the client is really currently on is subject to timing and - // ordering differences, so you should account for about a quarter-second discrepancy in here. - // Also, this will return NULL if the client doesn't exist or if this client hasn't acked any frames yet. - // - // iClientIndex is the CLIENT index, so if you use pPlayer->entindex(), subtract 1. - virtual const CBitVec* GetEntityTransmitBitsForClient(int iClientIndex) = 0; - - // Is the game paused? - virtual bool IsPaused() = 0; - - // Marks the filename for consistency checking. This should be called after precaching the file. - virtual void ForceExactFile(const char *s) = 0; - virtual void ForceModelBounds(const char *s, const Vector &mins, const Vector &maxs) = 0; - virtual void ClearSaveDirAfterClientLoad() = 0; - - // Sets a USERINFO client ConVar for a fakeclient - virtual void SetFakeClientConVarValue(edict_t *pEntity, const char *cvar, const char *value) = 0; - - // Marks the material (vmt file) for consistency checking. If the client and server have different - // contents for the file, the client's vmt can only use the VertexLitGeneric shader, and can only - // contain $baseTexture and $bumpmap vars. - virtual void ForceSimpleMaterial(const char *s) = 0; - - // Is the engine in Commentary mode? - virtual int IsInCommentaryMode(void) = 0; - - - // Mark some area portals as open/closed. It's more efficient to use this - // than a bunch of individual SetAreaPortalState calls. - virtual void SetAreaPortalStates(const int *portalNumbers, const int *isOpen, int nPortals) = 0; - - // Called when relevant edict state flags change. - virtual void NotifyEdictFlagsChange(int iEdict) = 0; - - // Only valid during CheckTransmit. Also, only the PVS, networked areas, and - // m_pTransmitInfo are valid in the returned strucutre. - virtual const CCheckTransmitInfo* GetPrevCheckTransmitInfo(edict_t *pPlayerEdict) = 0; - - virtual CSharedEdictChangeInfo* GetSharedEdictChangeInfo() = 0; - - // Tells the engine we can immdiately re-use all edict indices - // even though we may not have waited enough time - virtual void AllowImmediateEdictReuse() = 0; - - // Returns true if the engine is an internal build. i.e. is using the internal bugreporter. - virtual bool IsInternalBuild(void) = 0; - - virtual IChangeInfoAccessor *GetChangeAccessor(const edict_t *pEdict) = 0; - - // Name of most recently load .sav file - virtual char const *GetMostRecentlyLoadedFileName() = 0; - virtual char const *GetSaveFileName() = 0; - - // Matchmaking - virtual void MultiplayerEndGame() = 0; - virtual void ChangeTeam(const char *pTeamName) = 0; - - // Cleans up the cluster list - virtual void CleanUpEntityClusterList(PVSInfo_t *pPVSInfo) = 0; - - virtual void SetAchievementMgr(IAchievementMgr *pAchievementMgr) = 0; - virtual IAchievementMgr *GetAchievementMgr() = 0; - - virtual int GetAppID() = 0; - - virtual bool IsLowViolence() = 0; - - // Call this to find out the value of a cvar on the client. - // - // It is an asynchronous query, and it will call IServerGameDLL::OnQueryCvarValueFinished when - // the value comes in from the client. - // - // Store the return value if you want to match this specific query to the OnQueryCvarValueFinished call. - // Returns InvalidQueryCvarCookie if the entity is invalid. - virtual QueryCvarCookie_t StartQueryCvarValue(edict_t *pPlayerEntity, const char *pName) = 0; - - virtual void InsertServerCommand(const char *str) = 0; - - // Fill in the player info structure for the specified player index (name, model, etc.) - virtual bool GetPlayerInfo(int ent_num, player_info_t *pinfo) = 0; - - // Returns true if this client has been fully authenticated by Steam - virtual bool IsClientFullyAuthenticated(edict_t *pEdict) = 0; - - // This makes the host run 1 tick per frame instead of checking the system timer to see how many ticks to run in a certain frame. - // i.e. it does the same thing timedemo does. - virtual void SetDedicatedServerBenchmarkMode(bool bBenchmarkMode) = 0; - - // Methods to set/get a gamestats data container so client & server running in same process can send combined data - virtual void SetGamestatsData(CGamestatsData *pGamestatsData) = 0; - virtual CGamestatsData *GetGamestatsData() = 0; - - // Returns the SteamID of the specified player. It'll be NULL if the player hasn't authenticated yet. - virtual const CSteamID *GetClientSteamID(edict_t *pPlayerEdict) = 0; - - // Returns the SteamID of the game server - virtual const CSteamID *GetGameServerSteamID() = 0; - - // Send a client command keyvalues - // keyvalues are deleted inside the function - virtual void ClientCommandKeyValues(edict_t *pEdict, KeyValues *pCommand) = 0; - - // Returns the SteamID of the specified player. It'll be NULL if the player hasn't authenticated yet. - virtual const CSteamID *GetClientSteamIDByPlayerIndex(int entnum) = 0; - // Gets a list of all clusters' bounds. Returns total number of clusters. - virtual int GetClusterCount() = 0; - virtual int GetAllClusterBounds(bbox_t *pBBoxList, int maxBBox) = 0; - - // Create a bot with the given name. Returns NULL if fake client can't be created - virtual edict_t *CreateFakeClientEx(const char *netname, bool bReportFakeClient = true) = 0; - - // Server version from the steam.inf, this will be compared to the GC version - virtual int GetServerVersion() const = 0; - - // Get sv.GetTime() - virtual float GetServerTime() const = 0; - - // Exposed for server plugin authors - virtual IServer *GetIServer() = 0; - - virtual bool IsPlayerNameLocked(const edict_t *pPlayer) = 0; - virtual bool CanPlayerChangeName(const edict_t *pPlayer) = 0; - - virtual eFindMapResult FindMap( /* in/out */ char *pMapName, int nMapNameMax) = 0; - - virtual IReplaySystem *GetReplay() = 0; -}; - -typedef IVEngineServer IVEngineServer021; - - -#define INTERFACEVERSION_SERVERGAMEDLL_VERSION_8 "ServerGameDLL008" -#define INTERFACEVERSION_SERVERGAMEDLL "ServerGameDLL009" -#define INTERFACEVERSION_SERVERGAMEDLL_INT 9 - -class IServerGCLobby; - -//----------------------------------------------------------------------------- -// Purpose: These are the interfaces that the game .dll exposes to the engine -//----------------------------------------------------------------------------- -abstract_class IServerGameDLL -{ -public: - // Initialize the game (one-time call when the DLL is first loaded ) - // Return false if there is an error during startup. - virtual bool DLLInit(CreateInterfaceFn engineFactory, - CreateInterfaceFn physicsFactory, - CreateInterfaceFn fileSystemFactory, - CGlobalVars *pGlobals) = 0; - - // Setup replay interfaces on the server - virtual bool ReplayInit(CreateInterfaceFn fnReplayFactory) = 0; - - // This is called when a new game is started. (restart, map) - virtual bool GameInit(void) = 0; - - // Called any time a new level is started (after GameInit() also on level transitions within a game) - virtual bool LevelInit(char const *pMapName, - char const *pMapEntities, char const *pOldLevel, - char const *pLandmarkName, bool loadGame, bool background) = 0; - - // The server is about to activate - virtual void ServerActivate(edict_t *pEdictList, int edictCount, int clientMax) = 0; - - // The server should run physics/think on all edicts - virtual void GameFrame(bool simulating) = 0; - - // Called once per simulation frame on the final tick - virtual void PreClientUpdate(bool simulating) = 0; - - // Called when a level is shutdown (including changing levels) - virtual void LevelShutdown(void) = 0; - // This is called when a game ends (server disconnect, death, restart, load) - // NOT on level transitions within a game - virtual void GameShutdown(void) = 0; - - // Called once during DLL shutdown - virtual void DLLShutdown(void) = 0; - - // Get the simulation interval (must be compiled with identical values into both client and game .dll for MOD!!!) - // Right now this is only requested at server startup time so it can't be changed on the fly, etc. - virtual float GetTickInterval(void) const = 0; - - // Give the list of datatable classes to the engine. The engine matches class names from here with - // edict_t::classname to figure out how to encode a class's data for networking - virtual ServerClass* GetAllServerClasses(void) = 0; - - // Returns string describing current .dll. e.g., TeamFortress 2, Half-Life 2. - // Hey, it's more descriptive than just the name of the game directory - virtual const char *GetGameDescription(void) = 0; - - // Let the game .dll allocate it's own network/shared string tables - virtual void CreateNetworkStringTables(void) = 0; - - // Save/restore system hooks - virtual CSaveRestoreData *SaveInit(int size) = 0; - virtual void SaveWriteFields(CSaveRestoreData *, const char *, void *, datamap_t *, typedescription_t *, int) = 0; - virtual void SaveReadFields(CSaveRestoreData *, const char *, void *, datamap_t *, typedescription_t *, int) = 0; - virtual void SaveGlobalState(CSaveRestoreData *) = 0; - virtual void RestoreGlobalState(CSaveRestoreData *) = 0; - virtual void PreSave(CSaveRestoreData *) = 0; - virtual void Save(CSaveRestoreData *) = 0; - virtual void GetSaveComment(char *comment, int maxlength, float flMinutes, float flSeconds, bool bNoTime = false) = 0; - virtual void WriteSaveHeaders(CSaveRestoreData *) = 0; - virtual void ReadRestoreHeaders(CSaveRestoreData *) = 0; - virtual void Restore(CSaveRestoreData *, bool) = 0; - virtual bool IsRestoring() = 0; - - // Returns the number of entities moved across the transition - virtual int CreateEntityTransitionList(CSaveRestoreData *, int) = 0; - // Build the list of maps adjacent to the current map - virtual void BuildAdjacentMapList(void) = 0; - - // Retrieve info needed for parsing the specified user message - virtual bool GetUserMessageInfo(int msg_type, char *name, int maxnamelength, int& size) = 0; - - // Hand over the StandardSendProxies in the game DLL's module. - virtual CStandardSendProxies* GetStandardSendProxies() = 0; - - // Called once during startup, after the game .dll has been loaded and after the client .dll has also been loaded - virtual void PostInit() = 0; - // Called once per frame even when no level is loaded... - virtual void Think(bool finalTick) = 0; - -#ifdef _XBOX - virtual void GetTitleName(const char *pMapName, char* pTitleBuff, int titleBuffSize) = 0; -#endif - - virtual void PreSaveGameLoaded(char const *pSaveName, bool bCurrentlyInGame) = 0; - - // Returns true if the game DLL wants the server not to be made public. - // Used by commentary system to hide multiplayer commentary servers from the master. - virtual bool ShouldHideServer(void) = 0; - - virtual void InvalidateMdlCache() = 0; - - // * This function is new with version 6 of the interface. - // - // This is called when a query from IServerPluginHelpers::StartQueryCvarValue is finished. - // iCookie is the value returned by IServerPluginHelpers::StartQueryCvarValue. - // Added with version 2 of the interface. - virtual void OnQueryCvarValueFinished(QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue) = 0; - - // Called after the steam API has been activated post-level startup - virtual void GameServerSteamAPIActivated(void) = 0; - - // Called after the steam API has been shutdown post-level startup - virtual void GameServerSteamAPIShutdown(void) = 0; - - virtual void SetServerHibernation(bool bHibernating) = 0; - - // interface to the new GC based lobby system - virtual IServerGCLobby *GetServerGCLobby() = 0; - - // Return override string to show in the server browser - // "map" column, or NULL to just use the default value - // (the map name) - virtual const char *GetServerBrowserMapOverride() = 0; - - // Get gamedata string to send to the master serer updater. - virtual const char *GetServerBrowserGameData() = 0; - - // Called to add output to the status command - virtual void Status(void(*print) (const char *fmt, ...)) = 0; -}; - -typedef IServerGameDLL IServerGameDLL008; - -//----------------------------------------------------------------------------- -// Just an interface version name for the random number interface -// See vstdlib/random.h for the interface definition -// NOTE: If you change this, also change VENGINE_CLIENT_RANDOM_INTERFACE_VERSION in cdll_int.h -//----------------------------------------------------------------------------- -#define VENGINE_SERVER_RANDOM_INTERFACE_VERSION "VEngineRandom001" - -#define INTERFACEVERSION_SERVERGAMEENTS "ServerGameEnts001" -//----------------------------------------------------------------------------- -// Purpose: Interface to get at server entities -//----------------------------------------------------------------------------- -abstract_class IServerGameEnts -{ -public: - virtual ~IServerGameEnts() {} - - // Only for debugging. Set the edict base so you can get an edict's index in the debugger while debugging the game .dll - virtual void SetDebugEdictBase(edict_t *base) = 0; - - // The engine wants to mark two entities as touching - virtual void MarkEntitiesAsTouching(edict_t *e1, edict_t *e2) = 0; - - // Frees the entity attached to this edict - virtual void FreeContainingEntity(edict_t *) = 0; - - // This allows the engine to get at edicts in a CGameTrace. - virtual edict_t* BaseEntityToEdict(CBaseEntity *pEnt) = 0; - virtual CBaseEntity* EdictToBaseEntity(edict_t *pEdict) = 0; - - // This sets a bit in pInfo for each edict in the list that wants to be transmitted to the - // client specified in pInfo. - // - // This is also where an entity can force other entities to be transmitted if it refers to them - // with ehandles. - virtual void CheckTransmit(CCheckTransmitInfo *pInfo, const unsigned short *pEdictIndices, int nEdicts) = 0; -}; - -#define INTERFACEVERSION_SERVERGAMECLIENTS_VERSION_3 "ServerGameClients003" -#define INTERFACEVERSION_SERVERGAMECLIENTS "ServerGameClients004" - -//----------------------------------------------------------------------------- -// Purpose: Player / Client related functions -//----------------------------------------------------------------------------- -abstract_class IServerGameClients -{ -public: - // Get server maxplayers and lower bound for same - virtual void GetPlayerLimits(int& minplayers, int& maxplayers, int &defaultMaxPlayers) const = 0; - - // Client is connecting to server ( return false to reject the connection ) - // You can specify a rejection message by writing it into reject - virtual bool ClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen) = 0; - - // Client is going active - // If bLoadGame is true, don't spawn the player because its state is already setup. - virtual void ClientActive(edict_t *pEntity, bool bLoadGame) = 0; - - // Client is disconnecting from server - virtual void ClientDisconnect(edict_t *pEntity) = 0; - - // Client is connected and should be put in the game - virtual void ClientPutInServer(edict_t *pEntity, char const *playername) = 0; - - // The client has typed a command at the console - virtual void ClientCommand(edict_t *pEntity, const CCommand &args) = 0; - - // Sets the client index for the client who typed the command into his/her console - virtual void SetCommandClient(int index) = 0; - - // A player changed one/several replicated cvars (name etc) - virtual void ClientSettingsChanged(edict_t *pEdict) = 0; - - // Determine PVS origin and set PVS for the player/viewentity - virtual void ClientSetupVisibility(edict_t *pViewEntity, edict_t *pClient, unsigned char *pvs, int pvssize) = 0; - - // A block of CUserCmds has arrived from the user, decode them and buffer for execution during player simulation - virtual float ProcessUsercmds(edict_t *player, bf_read *buf, int numcmds, int totalcmds, - int dropped_packets, bool ignore, bool paused) = 0; - - // Let the game .dll do stuff after messages have been sent to all of the clients once the server frame is complete - virtual void PostClientMessagesSent_DEPRECIATED(void) = 0; - - // For players, looks up the CPlayerState structure corresponding to the player - virtual CPlayerState *GetPlayerState(edict_t *player) = 0; - - // Get the ear position for a specified client - virtual void ClientEarPosition(edict_t *pEntity, Vector *pEarOrigin) = 0; - - // returns number of delay ticks if player is in Replay mode (0 = no delay) - virtual int GetReplayDelay(edict_t *player, int& entity) = 0; - - // Anything this game .dll wants to add to the bug reporter text (e.g., the entity/model under the picker crosshair) - // can be added here - virtual void GetBugReportInfo(char *buf, int buflen) = 0; - - // A user has had their network id setup and validated - virtual void NetworkIDValidated(const char *pszUserName, const char *pszNetworkID) = 0; - - // The client has submitted a keyvalues command - virtual void ClientCommandKeyValues(edict_t *pEntity, KeyValues *pKeyValues) = 0; - - // Hook for player spawning - virtual void ClientSpawned(edict_t *pPlayer) = 0; -}; - -typedef IServerGameClients IServerGameClients003; - - -#define INTERFACEVERSION_UPLOADGAMESTATS "ServerUploadGameStats001" - -abstract_class IUploadGameStats -{ -public: - // Note that this call will block the server until the upload is completed, so use only at levelshutdown if at all. - virtual bool UploadGameStats( - char const *mapname, // Game map name - unsigned int blobversion, // Version of the binary blob data - unsigned int blobsize, // Size in bytes of blob data - const void *pvBlobData) = 0; // Pointer to the blob data. - - // Call when created to init the CSER connection - virtual void InitConnection(void) = 0; - - // Call periodically to poll steam for a CSER connection - virtual void UpdateConnection(void) = 0; - - // If user has disabled stats tracking, do nothing - virtual bool IsGameStatsLoggingEnabled() = 0; - - // Gets a non-personally identifiable unique ID for this steam user, used for tracking total gameplay time across - // multiple stats sessions, but isn't trackable back to their Steam account or id. - // Buffer should be 16 bytes, ID will come back as a hexadecimal string version of a GUID - virtual void GetPseudoUniqueId(char *buf, size_t bufsize) = 0; - - // For determining general % of users running using cyber cafe accounts... - virtual bool IsCyberCafeUser(void) = 0; - - // Only works in single player - virtual bool IsHDREnabled(void) = 0; -}; - -#define INTERFACEVERSION_PLUGINHELPERSCHECK "PluginHelpersCheck001" - -//----------------------------------------------------------------------------- -// Purpose: allows the game dll to control which plugin functions can be run -//----------------------------------------------------------------------------- -abstract_class IPluginHelpersCheck -{ -public: - virtual bool CreateMessage(const char *plugin, edict_t *pEntity, DIALOG_TYPE type, KeyValues *data) = 0; -}; - -//----------------------------------------------------------------------------- -// Purpose: Interface exposed from the client .dll back to the engine for specifying shared .dll IAppSystems (e.g., ISoundEmitterSystem) -//----------------------------------------------------------------------------- -abstract_class IServerDLLSharedAppSystems -{ -public: - virtual int Count() = 0; - virtual char const *GetDllName(int idx) = 0; - virtual char const *GetInterfaceName(int idx) = 0; -}; - -#define SERVER_DLL_SHARED_APPSYSTEMS "VServerDllSharedAppSystems001" - -#define INTERFACEVERSION_SERVERGAMETAGS "ServerGameTags001" - -//----------------------------------------------------------------------------- -// Purpose: querying the game dll for Server cvar tags -//----------------------------------------------------------------------------- -abstract_class IServerGameTags -{ -public: - // Get the list of cvars that require tags to show differently in the server browser - virtual void GetTaggedConVarList(KeyValues *pCvarTagList) = 0; -}; - -//----------------------------------------------------------------------------- -// Purpose: Provide hooks for the GC based lobby system -//----------------------------------------------------------------------------- -abstract_class IServerGCLobby -{ -public: - virtual bool HasLobby() const = 0; - virtual bool SteamIDAllowedToConnect(const CSteamID &steamId) const = 0; - virtual void UpdateServerDetails(void) = 0; - virtual bool ShouldHibernate() = 0; -}; - -#endif // EIFACE_H \ No newline at end of file diff --git a/public/eifaceV21.h b/public/eifaceV21.h deleted file mode 100644 index d00e9b9fc..000000000 --- a/public/eifaceV21.h +++ /dev/null @@ -1,614 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Defines entity interface between engine and DLLs. -// This header file included by engine files and DLL files. -// -// Before including this header, DLLs must: -// include edict.h -// This is conveniently done for them in extdll.h -// -// $NoKeywords: $ -// -//============================================================================= - -#ifndef EIFACEV21_H -#define EIFACEV21_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "convar.h" -#include "icvar.h" -#include "edict.h" -#include "iserverentity.h" -#include "engine/ivmodelinfo.h" -#include "soundflags.h" -#include "bitvec.h" - -//----------------------------------------------------------------------------- -// forward declarations -//----------------------------------------------------------------------------- -class SendTable; -class ServerClass; -class IMoveHelper; -struct Ray_t; -class CGameTrace; -typedef CGameTrace trace_t; -struct typedescription_t; -class CSaveRestoreData; -struct datamap_t; -class SendTable; -class ServerClass; -class IMoveHelper; -struct Ray_t; -struct studiohdr_t; -class CBaseEntity; -class CRestore; -class CSave; -class variant_t; -struct vcollide_t; -class bf_read; -class bf_write; -class IRecipientFilter; -class CBaseEntity; -class ITraceFilter; -struct client_textmessage_t; -class INetChannelInfo; -class ISpatialPartition; -class IScratchPad3D; -class CStandardSendProxiesV1; - - -// Terrain Modification Types -enum TerrainModType -{ - TMod_Sphere = 0, // sphere that pushes all vertices out along their normal. - TMod_Suck, - TMod_AABB -}; - -class CTerrainModParams -{ -public: - - // Flags for m_Flags. - enum - { - TMOD_SUCKTONORMAL = ( 1 << 0 ), // For TMod_Suck, suck into m_Normal rather than on +Z. - TMOD_STAYABOVEORIGINAL = ( 1 << 1 ) // For TMod_Suck, don't go below the original vert on Z. - }; - - CTerrainModParams() { m_Flags = 0; } // people always forget to init this - - Vector m_vCenter; - Vector m_vNormal; // If TMod_Suck and TMOD_SUCKTONORMAL is set. - int m_Flags; // Combination of TMOD_ flags. - float m_flRadius; - Vector m_vecMin; // Bounding box. - Vector m_vecMax; - float m_flStrength; // for TMod_Suck - float m_flMorphTime; // time over which the morph takes place -}; - -class CSpeculativeTerrainModVert -{ -public: - Vector m_vOriginal; // vertex position before any mods - Vector m_vCurrent; // current vertex position - Vector m_vNew; // vertex position if the mod were applied -}; - -//----------------------------------------------------------------------------- -// Terrain modification interface -//----------------------------------------------------------------------------- -class ITerrainMod -{ -public: - - //--------------------------------------------------------------------- - // Initialize the terrain modifier. - //--------------------------------------------------------------------- - virtual void Init( const CTerrainModParams ¶ms ) = 0; - - //--------------------------------------------------------------------- - // Apply the terrain modifier to the surface. The vertex should be - // moved from its original position to the target position. - // Return true if the position is modified. - //--------------------------------------------------------------------- - virtual bool ApplyMod( Vector &vecTargetPos, Vector const &vecOriginalPos ) = 0; - - //--------------------------------------------------------------------- - // Apply the terrain modifier to the surface. The vertex should from - // its original position toward the target position bassed on the - // morph time. - // Return true if the posistion is modified. - //--------------------------------------------------------------------- - virtual bool ApplyModAtMorphTime( Vector &vecTargetPos, const Vector&vecOriginalPos, - float flCurrentTime, float flMorphTime ) = 0; - - //--------------------------------------------------------------------- - // Get the bounding box for things that this mod can affect (note that - // it CAN move things outside of this bounding box). - //--------------------------------------------------------------------- - virtual void GetBBox( Vector &vecBBMin, Vector &vecBBMax ) = 0; -}; - - - -//----------------------------------------------------------------------------- -// Purpose: Interface the engine exposes to the game DLL -//----------------------------------------------------------------------------- -#define VENGINESERVER_INTERFACEVERSION_21 "VEngineServer021" - -namespace VEngineServerV21 -{ - -abstract_class IVEngineServer -{ -public: - // Tell engine to change level ( "changelevel s1\n" or "changelevel2 s1 s2\n" ) - virtual void ChangeLevel( const char *s1, const char *s2 ) = 0; - - // Ask engine whether the specified map is a valid map file (exists and has valid version number). - virtual int IsMapValid( const char *filename ) = 0; - - // Is this a dedicated server? - virtual bool IsDedicatedServer( void ) = 0; - - // Is in Hammer editing mode? - virtual int IsInEditMode( void ) = 0; - - // Add to the server/client lookup/precache table, the specified string is given a unique index - // NOTE: The indices for PrecacheModel are 1 based - // a 0 returned from those methods indicates the model or sound was not correctly precached - // However, generic and decal are 0 based - // If preload is specified, the file is loaded into the server/client's cache memory before level startup, otherwise - // it'll only load when actually used (which can cause a disk i/o hitch if it occurs during play of a level). - virtual int PrecacheModel( const char *s, bool preload = false ) = 0; - virtual int PrecacheSentenceFile( const char *s, bool preload = false ) = 0; - virtual int PrecacheDecal( const char *name, bool preload = false ) = 0; - virtual int PrecacheGeneric( const char *s, bool preload = false ) = 0; - - // Check's if the name is precached, but doesn't actually precache the name if not... - virtual bool IsModelPrecached( char const *s ) const = 0; - virtual bool IsDecalPrecached( char const *s ) const = 0; - virtual bool IsGenericPrecached( char const *s ) const = 0; - - // Note that sounds are precached using the IEngineSound interface - - // Special purpose PVS checking - // Get the cluster # for the specified position - virtual int GetClusterForOrigin( const Vector &org ) = 0; - // Get the PVS bits for a specified cluster and copy the bits into outputpvs. Returns the number of bytes needed to pack the PVS - virtual int GetPVSForCluster( int cluster, int outputpvslength, unsigned char *outputpvs ) = 0; - // Check whether the specified origin is inside the specified PVS - virtual bool CheckOriginInPVS( const Vector &org, const unsigned char *checkpvs, int checkpvssize ) = 0; - // Check whether the specified worldspace bounding box is inside the specified PVS - virtual bool CheckBoxInPVS( const Vector &mins, const Vector &maxs, const unsigned char *checkpvs, int checkpvssize ) = 0; - - // Returns the server assigned userid for this player. Useful for logging frags, etc. - // returns -1 if the edict couldn't be found in the list of players. - virtual int GetPlayerUserId( const edict_t *e ) = 0; - virtual const char *GetPlayerNetworkIDString( const edict_t *e ) = 0; - - // Return the current number of used edict slots - virtual int GetEntityCount( void ) = 0; - // Given an edict, returns the entity index - virtual int IndexOfEdict( const edict_t *pEdict ) = 0; - // Given and entity index, returns the corresponding edict pointer - virtual edict_t *PEntityOfEntIndex( int iEntIndex ) = 0; - - // Get stats info interface for a client netchannel - virtual INetChannelInfo* GetPlayerNetInfo( int playerIndex ) = 0; - - // Allocate space for string and return index/offset of string in global string list - // If iForceEdictIndex is not -1, then it will return the edict with that index. If that edict index - // is already used, it'll return null. - virtual edict_t *CreateEdict( int iForceEdictIndex = -1 ) = 0; - // Remove the specified edict and place back into the free edict list - virtual void RemoveEdict( edict_t *e ) = 0; - - // Memory allocation for entity class data - virtual void *PvAllocEntPrivateData( long cb ) = 0; - virtual void FreeEntPrivateData( void *pEntity ) = 0; - - // Save/restore uses a special memory allocator (which zeroes newly allocated memory, etc.) - virtual void *SaveAllocMemory( size_t num, size_t size ) = 0; - virtual void SaveFreeMemory( void *pSaveMem ) = 0; - - // Emit an ambient sound associated with the specified entity - virtual void EmitAmbientSound( int entindex, const Vector &pos, const char *samp, float vol, soundlevel_t soundlevel, int fFlags, int pitch, float delay = 0.0f ) = 0; - - // Fade out the client's volume level toward silence (or fadePercent) - virtual void FadeClientVolume( const edict_t *pEdict, float fadePercent, float fadeOutSeconds, float holdTime, float fadeInSeconds ) = 0; - - // Sentences / sentence groups - virtual int SentenceGroupPick( int groupIndex, char *name, int nameBufLen ) = 0; - virtual int SentenceGroupPickSequential( int groupIndex, char *name, int nameBufLen, int sentenceIndex, int reset ) = 0; - virtual int SentenceIndexFromName( const char *pSentenceName ) = 0; - virtual const char *SentenceNameFromIndex( int sentenceIndex ) = 0; - virtual int SentenceGroupIndexFromName( const char *pGroupName ) = 0; - virtual const char *SentenceGroupNameFromIndex( int groupIndex ) = 0; - virtual float SentenceLength( int sentenceIndex ) = 0; - - // Issue a command to the command parser as if it was typed at the server console. - virtual void ServerCommand( const char *str ) = 0; - // Execute any commands currently in the command parser immediately (instead of once per frame) - virtual void ServerExecute( void ) = 0; - // Issue the specified command to the specified client (mimics that client typing the command at the console). - virtual void ClientCommand( edict_t *pEdict, const char *szFmt, ... ) = 0; - - // Set the lightstyle to the specified value and network the change to any connected clients. Note that val must not - // change place in memory (use MAKE_STRING) for anything that's not compiled into your mod. - virtual void LightStyle( int style, const char *val ) = 0; - - // Project a static decal onto the specified entity / model (for level placed decals in the .bsp) - virtual void StaticDecal( const Vector &originInEntitySpace, int decalIndex, int entityIndex, int modelIndex, bool lowpriority ) = 0; - - // Given the current PVS(or PAS) and origin, determine which players should hear/receive the message - virtual void Message_DetermineMulticastRecipients( bool usepas, const Vector& origin, CBitVec< ABSOLUTE_PLAYER_LIMIT >& playerbits ) = 0; - - // Begin a message from a server side entity to its client side counterpart (func_breakable glass, e.g.) - virtual bf_write *EntityMessageBegin( int ent_index, ServerClass * ent_class, bool reliable ) = 0; - // Begin a usermessage from the server to the client .dll - virtual bf_write *UserMessageBegin( IRecipientFilter *filter, int msg_type ) = 0; - // Finish the Entity or UserMessage and dispatch to network layer - virtual void MessageEnd( void ) = 0; - - // Print szMsg to the client console. - virtual void ClientPrintf( edict_t *pEdict, const char *szMsg ) = 0; - - // SINGLE PLAYER/LISTEN SERVER ONLY (just matching the client .dll api for this) - // Prints the formatted string to the notification area of the screen ( down the right hand edge - // numbered lines starting at position 0 - virtual void Con_NPrintf( int pos, const char *fmt, ... ) = 0; - // SINGLE PLAYER/LISTEN SERVER ONLY(just matching the client .dll api for this) - // Similar to Con_NPrintf, but allows specifying custom text color and duration information - virtual void Con_NXPrintf( const struct con_nprint_s *info, const char *fmt, ... ) = 0; - - // For ConCommand parsing or parsing client commands issued by players typing at their console - // Retrieves the raw command string (untokenized) - virtual const char *Cmd_Args( void ) = 0; - // Returns the number of tokens in the command string - virtual int Cmd_Argc( void ) = 0; - // Retrieves a specified token - virtual char *Cmd_Argv( int argc ) = 0; - - // Change a specified player's "view entity" (i.e., use the view entity position/orientation for rendering the client view) - virtual void SetView( const edict_t *pClient, const edict_t *pViewent ) = 0; - - // Get a high precision timer for doing profiling work - virtual float Time( void ) = 0; - - // Set the player's crosshair angle - virtual void CrosshairAngle( const edict_t *pClient, float pitch, float yaw ) = 0; - - // Get the current game directory (hl2, tf2, hl1, cstrike, etc.) - virtual void GetGameDir( char *szGetGameDir, int maxlength ) = 0; - - // Used by AI node graph code to determine if .bsp and .ain files are out of date - virtual int CompareFileTime( const char *filename1, const char *filename2, int *iCompare ) = 0; - - // Locks/unlocks the network string tables (.e.g, when adding bots to server, this needs to happen). - // Be sure to reset the lock after executing your code!!! - virtual bool LockNetworkStringTables( bool lock ) = 0; - - // Create a bot with the given name. Returns NULL if fake client can't be created - virtual edict_t *CreateFakeClient( const char *netname ) = 0; - - // Get a convar keyvalue for s specified client - virtual const char *GetClientConVarValue( int clientIndex, const char *name ) = 0; - - // Parse a token from a file - virtual const char *ParseFile( const char *data, char *token, int maxlen ) = 0; - // Copies a file - virtual bool CopyFile( const char *source, const char *destination ) = 0; - - // Reset the pvs, pvssize is the size in bytes of the buffer pointed to by pvs. - // This should be called right before any calls to AddOriginToPVS - virtual void ResetPVS( byte *pvs, int pvssize ) = 0; - // Merge the pvs bits into the current accumulated pvs based on the specified origin ( not that each pvs origin has an 8 world unit fudge factor ) - virtual void AddOriginToPVS( const Vector &origin ) = 0; - // Mark a specified area portal as open/closes - virtual void SetAreaPortalState( int portalNumber, int isOpen ) = 0; - // Queue a temp entity for transmission - virtual void PlaybackTempEntity( IRecipientFilter& filter, float delay, const void *pSender, const SendTable *pST, int classID ) = 0; - // Given a node number and the specified PVS, return with the node is in the PVS - virtual int CheckHeadnodeVisible( int nodenum, const byte *pvs, int vissize ) = 0; - // Using area bits, cheeck whether area1 flows into area2 and vice versa (depends on area portal state) - virtual int CheckAreasConnected( int area1, int area2 ) = 0; - // Given an origin, determine which area index the origin is within - virtual int GetArea( const Vector &origin ) = 0; - // Get area portal bit set - virtual void GetAreaBits( int area, unsigned char *bits, int buflen ) = 0; - // Given a view origin (which tells us the area to start looking in) and a portal key, - // fill in the plane that leads out of this area (it points into whatever area it leads to). - virtual bool GetAreaPortalPlane( Vector const &vViewOrigin, int portalKey, VPlane *pPlane ) = 0; - - // Apply a modification to the terrain. - virtual void ApplyTerrainMod( TerrainModType type, CTerrainModParams const ¶ms ) = 0; - - // Save/restore wrapper - FIXME: At some point we should move this to it's own interface - virtual bool LoadGameState( char const *pMapName, bool createPlayers ) = 0; - virtual void LoadAdjacentEnts( const char *pOldLevel, const char *pLandmarkName ) = 0; - virtual void ClearSaveDir() = 0; - - // Get the pristine map entity lump string. (e.g., used by CS to reload the map entities when restarting a round.) - virtual const char* GetMapEntitiesString() = 0; - - // Text message system -- lookup the text message of the specified name - virtual client_textmessage_t *TextMessageGet( const char *pName ) = 0; - - // Print a message to the server log file - virtual void LogPrint( const char *msg ) = 0; - - // Builds PVS information for an entity - virtual void BuildEntityClusterList( edict_t *pEdict, PVSInfo_t *pPVSInfo ) = 0; - - // A solid entity moved, update spatial partition - virtual void SolidMoved( edict_t *pSolidEnt, ICollideable *pSolidCollide, const Vector* pPrevAbsOrigin ) = 0; - // A trigger entity moved, update spatial partition - virtual void TriggerMoved( edict_t *pTriggerEnt ) = 0; - - // Create/destroy a custom spatial partition - virtual ISpatialPartition *CreateSpatialPartition( const Vector& worldmin, const Vector& worldmax ) = 0; - virtual void DestroySpatialPartition( ISpatialPartition * ) = 0; - - // Draw the brush geometry in the map into the scratch pad. - // Flags is currently unused. - virtual void DrawMapToScratchPad( IScratchPad3D *pPad, unsigned long iFlags ) = 0; - - // This returns which entities, to the best of the server's knowledge, the client currently knows about. - // This is really which entities were in the snapshot that this client last acked. - // This returns a bit vector with one bit for each entity. - // - // USE WITH CARE. Whatever tick the client is really currently on is subject to timing and - // ordering differences, so you should account for about a quarter-second discrepancy in here. - // Also, this will return NULL if the client doesn't exist or if this client hasn't acked any frames yet. - // - // iClientIndex is the CLIENT index, so if you use pPlayer->entindex(), subtract 1. - virtual const CBitVec* GetEntityTransmitBitsForClient( int iClientIndex ) = 0; - - // Is the game paused? - virtual bool IsPaused() = 0; - - // Marks the filename for consistency checking. This should be called after precaching the file. - virtual void ForceExactFile( const char *s ) = 0; - virtual void ForceModelBounds( const char *s, const Vector &mins, const Vector &maxs ) = 0; - virtual void ClearSaveDirAfterClientLoad() = 0; - - // Sets a USERINFO client ConVar for a fakeclient - virtual void SetFakeClientConVarValue( edict_t *pEntity, const char *cvar, const char *value ) = 0; - - virtual void InsertServerCommand( const char *str ) = 0; - - // Marks the material (vmt file) for consistency checking. If the client and server have different - // contents for the file, the client's vmt can only use the VertexLitGeneric shader, and can only - // contain $baseTexture and $bumpmap vars. - virtual void ForceSimpleMaterial( const char *s ) = 0; - - - // Is the engine in Commentary mode? - virtual int IsInCommentaryMode( void ) = 0; -}; - -} // end namespace - - -//----------------------------------------------------------------------------- -// Purpose: These are the interfaces that the game .dll exposes to the engine -//----------------------------------------------------------------------------- -#define SERVERGAMEDLL_INTERFACEVERSION_3 "ServerGameDLL003" - -namespace ServerGameDLLV3 -{ - -abstract_class IServerGameDLL -{ -public: - // Initialize the game (one-time call when the DLL is first loaded ) - // Return false if there is an error during startup. - virtual bool DLLInit( CreateInterfaceFn engineFactory, - CreateInterfaceFn physicsFactory, - CreateInterfaceFn fileSystemFactory, - CGlobalVars *pGlobals) = 0; - - // This is called when a new game is started. (restart, map) - virtual bool GameInit( void ) = 0; - - // Called any time a new level is started (after GameInit() also on level transitions within a game) - virtual bool LevelInit( char const *pMapName, - char const *pMapEntities, char const *pOldLevel, - char const *pLandmarkName, bool loadGame, bool background ) = 0; - - // The server is about to activate - virtual void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax ) = 0; - - // The server should run physics/think on all edicts - virtual void GameFrame( bool simulating ) = 0; - - // Called once per simulation frame on the final tick - virtual void PreClientUpdate( bool simulating ) = 0; - - // Called when a level is shutdown (including changing levels) - virtual void LevelShutdown( void ) = 0; - // This is called when a game ends (server disconnect, death, restart, load) - // NOT on level transitions within a game - virtual void GameShutdown( void ) = 0; - - // Called once during DLL shutdown - virtual void DLLShutdown( void ) = 0; - - // Get the simulation interval (must be compiled with identical values into both client and game .dll for MOD!!!) - // Right now this is only requested at server startup time so it can't be changed on the fly, etc. - virtual float GetTickInterval( void ) const = 0; - - // Give the list of datatable classes to the engine. The engine matches class names from here with - // edict_t::classname to figure out how to encode a class's data for networking - virtual ServerClass* GetAllServerClasses( void ) = 0; - - // Returns string describing current .dll. e.g., TeamFortress 2, Half-Life 2. - // Hey, it's more descriptive than just the name of the game directory - virtual const char *GetGameDescription( void ) = 0; - - // Let the game .dll allocate it's own network/shared string tables - virtual void CreateNetworkStringTables( void ) = 0; - - // Save/restore system hooks - virtual CSaveRestoreData *SaveInit( int size ) = 0; - virtual void SaveWriteFields( CSaveRestoreData *, const char *, void *, datamap_t *, typedescription_t *, int ) = 0; - virtual void SaveReadFields( CSaveRestoreData *, const char *, void *, datamap_t *, typedescription_t *, int ) = 0; - virtual void SaveGlobalState( CSaveRestoreData * ) = 0; - virtual void RestoreGlobalState( CSaveRestoreData * ) = 0; - virtual void PreSave( CSaveRestoreData * ) = 0; - virtual void Save( CSaveRestoreData * ) = 0; - virtual void GetSaveComment( char *comment, int maxlength ) = 0; - virtual void WriteSaveHeaders( CSaveRestoreData * ) = 0; - virtual void ReadRestoreHeaders( CSaveRestoreData * ) = 0; - virtual void Restore( CSaveRestoreData *, bool ) = 0; - virtual bool IsRestoring() = 0; - - // Returns the number of entities moved across the transition - virtual int CreateEntityTransitionList( CSaveRestoreData *, int ) = 0; - // Build the list of maps adjacent to the current map - virtual void BuildAdjacentMapList( void ) = 0; - - // Retrieve info needed for parsing the specified user message - virtual bool GetUserMessageInfo( int msg_type, char *name, int maxnamelength, int& size ) = 0; - - // Hand over the StandardSendProxies in the game DLL's module. - virtual CStandardSendProxiesV1* GetStandardSendProxies() = 0; -}; - -} // end namespace - - -//----------------------------------------------------------------------------- -// Just an interface version name for the random number interface -// See vstdlib/random.h for the interface definition -// NOTE: If you change this, also change VENGINE_CLIENT_RANDOM_INTERFACE_VERSION in cdll_int.h -//----------------------------------------------------------------------------- -#define VENGINE_SERVER_RANDOM_INTERFACE_VERSION_1 "VEngineRandom001" - -//----------------------------------------------------------------------------- -// Purpose: Interface to get at server entities -//----------------------------------------------------------------------------- -#define SERVERGAMEENTS_INTERFACEVERSION_1 "ServerGameEnts001" - -namespace ServerGameEntsV1 -{ - -abstract_class IServerGameEnts -{ -public: - virtual ~IServerGameEnts() {} - - // Only for debugging. Set the edict base so you can get an edict's index in the debugger while debugging the game .dll - virtual void SetDebugEdictBase(edict_t *base) = 0; - - // The engine wants to mark two entities as touching - virtual void MarkEntitiesAsTouching( edict_t *e1, edict_t *e2 ) = 0; - - // Frees the entity attached to this edict - virtual void FreeContainingEntity( edict_t * ) = 0; - - // This allows the engine to get at edicts in a CGameTrace. - virtual edict_t* BaseEntityToEdict( CBaseEntity *pEnt ) = 0; - virtual CBaseEntity* EdictToBaseEntity( edict_t *pEdict ) = 0; - - // This sets a bit in pInfo for each edict in the list that wants to be transmitted to the - // client specified in pInfo. - // - // This is also where an entity can force other entities to be transmitted if it refers to them - // with ehandles. - virtual void CheckTransmit( CCheckTransmitInfo *pInfo, const unsigned short *pEdictIndices, int nEdicts ) = 0; -}; - -} // end namespace ServerGameEntsV1 - - -//----------------------------------------------------------------------------- -// Purpose: Player / Client related functions -//----------------------------------------------------------------------------- -#define SERVERGAMECLIENTS_INTERFACEVERSION_3 "ServerGameClients003" - -namespace ServerGameClientsV3 -{ - -abstract_class IServerGameClients -{ -public: - // Get server maxplayers and lower bound for same - virtual void GetPlayerLimits( int& minplayers, int& maxplayers, int &defaultMaxPlayers ) const = 0; - - // Client is connecting to server ( return false to reject the connection ) - // You can specify a rejection message by writing it into reject - virtual bool ClientConnect( edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen ) = 0; - - // Client is going active - // If bLoadGame is true, don't spawn the player because its state is already setup. - virtual void ClientActive( edict_t *pEntity, bool bLoadGame ) = 0; - - // Client is disconnecting from server - virtual void ClientDisconnect( edict_t *pEntity ) = 0; - - // Client is connected and should be put in the game - virtual void ClientPutInServer( edict_t *pEntity, char const *playername ) = 0; - - // The client has typed a command at the console - virtual void ClientCommand( edict_t *pEntity ) = 0; - - // Sets the client index for the client who typed the command into his/her console - virtual void SetCommandClient( int index ) = 0; - - // A player changed one/several replicated cvars (name etc) - virtual void ClientSettingsChanged( edict_t *pEdict ) = 0; - - // Determine PVS origin and set PVS for the player/viewentity - virtual void ClientSetupVisibility( edict_t *pViewEntity, edict_t *pClient, unsigned char *pvs, int pvssize ) = 0; - - // A block of CUserCmds has arrived from the user, decode them and buffer for execution during player simulation - virtual float ProcessUsercmds( edict_t *player, bf_read *buf, int numcmds, int totalcmds, - int dropped_packets, bool ignore, bool paused ) = 0; - - // Let the game .dll do stuff after messages have been sent to all of the clients once the server frame is complete - virtual void PostClientMessagesSent( void ) = 0; - - // For players, looks up the CPlayerState structure corresponding to the player - virtual CPlayerState *GetPlayerState( edict_t *player ) = 0; - - // Get the ear position for a specified client - virtual void ClientEarPosition( edict_t *pEntity, Vector *pEarOrigin ) = 0; - - // returns number of delay ticks if player is in Replay mode (0 = no delay) - virtual int GetReplayDelay( edict_t *player ) = 0; - - // Anything this game .dll wants to add to the bug reporter text (e.g., the entity/model under the picker crosshair) - // can be added here - virtual void GetBugReportInfo( char *buf, int buflen ) = 0; -}; - -} // end namespace ServerGameClientsV3 - - -#define UPLOADGAMESTATS_INTERFACEVERSION_1 "ServerUploadGameStats001" - -namespace UploadGameStatsV1 -{ - -abstract_class IUploadGameStats -{ -public: - // Note that this call will block the server until the upload is completed, so use only at levelshutdown if at all. - virtual bool UploadGameStats( - char const *mapname, // Game map name - unsigned int blobversion, // Version of the binary blob data - unsigned int blobsize, // Size in bytes of blob data - const void *pvBlobData ) = 0; // Pointer to the blob data. -}; - -} // end namespace UploadGameStatsV1 - - -#endif // EIFACEV21_H diff --git a/public/engine/IClientLeafSystem.h b/public/engine/IClientLeafSystem.h deleted file mode 100644 index 4521a89c3..000000000 --- a/public/engine/IClientLeafSystem.h +++ /dev/null @@ -1,73 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Revision: $ -// $NoKeywords: $ -// -// This file contains code to allow us to associate client data with bsp leaves. -// -//=============================================================================// - -#if !defined( ICLIENTLEAFSYSTEM_H ) -#define ICLIENTLEAFSYSTEM_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "client_render_handle.h" - - -//----------------------------------------------------------------------------- -// Render groups -//----------------------------------------------------------------------------- -enum RenderGroup_Config_t -{ - // Number of buckets that are used to hold opaque entities - // and opaque static props by size. The bucketing should be used to reduce overdraw. - RENDER_GROUP_CFG_NUM_OPAQUE_ENT_BUCKETS = 4, -}; - -enum RenderGroup_t -{ - RENDER_GROUP_OPAQUE_STATIC_HUGE = 0, // Huge static prop - RENDER_GROUP_OPAQUE_ENTITY_HUGE = 1, // Huge opaque entity - RENDER_GROUP_OPAQUE_STATIC = RENDER_GROUP_OPAQUE_STATIC_HUGE + ( RENDER_GROUP_CFG_NUM_OPAQUE_ENT_BUCKETS - 1 ) * 2, - RENDER_GROUP_OPAQUE_ENTITY, // Opaque entity (smallest size, or default) - - RENDER_GROUP_TRANSLUCENT_ENTITY, - RENDER_GROUP_TWOPASS, // Implied opaque and translucent in two passes - RENDER_GROUP_VIEW_MODEL_OPAQUE, // Solid weapon view models - RENDER_GROUP_VIEW_MODEL_TRANSLUCENT, // Transparent overlays etc - - RENDER_GROUP_OPAQUE_BRUSH, // Brushes - - RENDER_GROUP_OTHER, // Unclassfied. Won't get drawn. - - // This one's always gotta be last - RENDER_GROUP_COUNT -}; - -#define CLIENTLEAFSYSTEM_INTERFACE_VERSION_1 "ClientLeafSystem001" -#define CLIENTLEAFSYSTEM_INTERFACE_VERSION "ClientLeafSystem002" - - -//----------------------------------------------------------------------------- -// The client leaf system -//----------------------------------------------------------------------------- -abstract_class IClientLeafSystemEngine -{ -public: - // Adds and removes renderables from the leaf lists - // CreateRenderableHandle stores the handle inside pRenderable. - virtual void CreateRenderableHandle( IClientRenderable* pRenderable, bool bIsStaticProp = false ) = 0; - virtual void RemoveRenderable( ClientRenderHandle_t handle ) = 0; - virtual void AddRenderableToLeaves( ClientRenderHandle_t renderable, int nLeafCount, unsigned short *pLeaves ) = 0; - virtual void ChangeRenderableRenderGroup( ClientRenderHandle_t handle, RenderGroup_t group ) = 0; -}; - - -#endif // ICLIENTLEAFSYSTEM_H - - diff --git a/public/engine/ICollideable.h b/public/engine/ICollideable.h deleted file mode 100644 index 7c2fc4b5d..000000000 --- a/public/engine/ICollideable.h +++ /dev/null @@ -1,84 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ENGINE_ICOLLIDEABLE_H -#define ENGINE_ICOLLIDEABLE_H -#ifdef _WIN32 -#pragma once -#endif - - -enum SolidType_t; -class IHandleEntity; -struct Ray_t; -struct model_t; -class Vector; -class QAngle; -class CGameTrace; -typedef CGameTrace trace_t; -class IClientUnknown; - - -abstract_class ICollideable -{ -public: - // Gets at the entity handle associated with the collideable - virtual IHandleEntity *GetEntityHandle() = 0; - - // These methods return the bounds of an OBB measured in "collision" space - // which can be retreived through the CollisionToWorldTransform or - // GetCollisionOrigin/GetCollisionAngles methods - virtual const Vector& OBBMinsPreScaled() const = 0; - virtual const Vector& OBBMaxsPreScaled() const = 0; - virtual const Vector& OBBMins() const = 0; - virtual const Vector& OBBMaxs() const = 0; - - // Returns the bounds of a world-space box used when the collideable is being traced - // against as a trigger. It's only valid to call these methods if the solid flags - // have the FSOLID_USE_TRIGGER_BOUNDS flag set. - virtual void WorldSpaceTriggerBounds( Vector *pVecWorldMins, Vector *pVecWorldMaxs ) const = 0; - - // custom collision test - virtual bool TestCollision( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ) = 0; - - // Perform hitbox test, returns true *if hitboxes were tested at all*!! - virtual bool TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ) = 0; - - // Returns the BRUSH model index if this is a brush model. Otherwise, returns -1. - virtual int GetCollisionModelIndex() = 0; - - // Return the model, if it's a studio model. - virtual const model_t* GetCollisionModel() = 0; - - // Get angles and origin. - virtual const Vector& GetCollisionOrigin() const = 0; - virtual const QAngle& GetCollisionAngles() const = 0; - virtual const matrix3x4_t& CollisionToWorldTransform() const = 0; - - // Return a SOLID_ define. - virtual SolidType_t GetSolid() const = 0; - virtual int GetSolidFlags() const = 0; - - // Gets at the containing class... - virtual IClientUnknown* GetIClientUnknown() = 0; - - // We can filter out collisions based on collision group - virtual int GetCollisionGroup() const = 0; - - // Returns a world-aligned box guaranteed to surround *everything* in the collision representation - // Note that this will surround hitboxes, trigger bounds, physics. - // It may or may not be a tight-fitting box and its volume may suddenly change - virtual void WorldSpaceSurroundingBounds( Vector *pVecMins, Vector *pVecMaxs ) = 0; - - virtual bool ShouldTouchTrigger( int triggerSolidFlags ) const = 0; - - // returns NULL unless this collideable has specified FSOLID_ROOT_PARENT_ALIGNED - virtual const matrix3x4_t *GetRootParentToWorldTransform() const = 0; -}; - - -#endif // ENGINE_ICOLLIDEABLE_H diff --git a/public/engine/IEngineSound.h b/public/engine/IEngineSound.h deleted file mode 100644 index c9dc159d2..000000000 --- a/public/engine/IEngineSound.h +++ /dev/null @@ -1,122 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Client-server neutral sound interface -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IENGINESOUND_H -#define IENGINESOUND_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "basetypes.h" -#include "interface.h" -#include "soundflags.h" -#include "irecipientfilter.h" -#include "utlvector.h" -#include "engine/SndInfo.h" - -//----------------------------------------------------------------------------- -// forward declaration -//----------------------------------------------------------------------------- -class Vector; - -// Handy defines for EmitSound -#define SOUND_FROM_LOCAL_PLAYER -1 -#define SOUND_FROM_WORLD 0 - - - -// These are used to feed a soundlevel to the sound system and have it use -// goldsrc-type attenuation. We should use this as little as possible and -// phase it out as soon as possible. - -// Take a regular sndlevel and convert it to compatibility mode. -#define SNDLEVEL_TO_COMPATIBILITY_MODE( x ) ((soundlevel_t)(int)( (x) + 256 )) - -// Take a compatibility-mode sndlevel and get the REAL sndlevel out of it. -#define SNDLEVEL_FROM_COMPATIBILITY_MODE( x ) ((soundlevel_t)(int)( (x) - 256 )) - -// Tells if the given sndlevel is marked as compatibility mode. -#define SNDLEVEL_IS_COMPATIBILITY_MODE( x ) ( (x) >= 256 ) - - - -//----------------------------------------------------------------------------- -// Client-server neutral effects interface -//----------------------------------------------------------------------------- -#define IENGINESOUND_CLIENT_INTERFACE_VERSION "IEngineSoundClient003" -#define IENGINESOUND_SERVER_INTERFACE_VERSION "IEngineSoundServer003" - -abstract_class IEngineSound -{ -public: - // Precache a particular sample - virtual bool PrecacheSound( const char *pSample, bool bPreload = false, bool bIsUISound = false ) = 0; - virtual bool IsSoundPrecached( const char *pSample ) = 0; - virtual void PrefetchSound( const char *pSample ) = 0; - - // Just loads the file header and checks for duration (not hooked up for .mp3's yet) - // Is accessible to server and client though - virtual float GetSoundDuration( const char *pSample ) = 0; - - // Pitch of 100 is no pitch shift. Pitch > 100 up to 255 is a higher pitch, pitch < 100 - // down to 1 is a lower pitch. 150 to 70 is the realistic range. - // EmitSound with pitch != 100 should be used sparingly, as it's not quite as - // fast (the pitchshift mixer is not native coded). - - // NOTE: setting iEntIndex to -1 will cause the sound to be emitted from the local - // player (client-side only) - virtual void EmitSound( IRecipientFilter& filter, int iEntIndex, int iChannel, const char *pSample, - float flVolume, float flAttenuation, int iFlags = 0, int iPitch = PITCH_NORM, int iSpecialDSP = 0, - const Vector *pOrigin = NULL, const Vector *pDirection = NULL, CUtlVector< Vector >* pUtlVecOrigins = NULL, bool bUpdatePositions = true, float soundtime = 0.0f, int speakerentity = -1 ) = 0; - - virtual void EmitSound( IRecipientFilter& filter, int iEntIndex, int iChannel, const char *pSample, - float flVolume, soundlevel_t iSoundlevel, int iFlags = 0, int iPitch = PITCH_NORM, int iSpecialDSP = 0, - const Vector *pOrigin = NULL, const Vector *pDirection = NULL, CUtlVector< Vector >* pUtlVecOrigins = NULL, bool bUpdatePositions = true, float soundtime = 0.0f, int speakerentity = -1 ) = 0; - - virtual void EmitSentenceByIndex( IRecipientFilter& filter, int iEntIndex, int iChannel, int iSentenceIndex, - float flVolume, soundlevel_t iSoundlevel, int iFlags = 0, int iPitch = PITCH_NORM, int iSpecialDSP = 0, - const Vector *pOrigin = NULL, const Vector *pDirection = NULL, CUtlVector< Vector >* pUtlVecOrigins = NULL, bool bUpdatePositions = true, float soundtime = 0.0f, int speakerentity = -1 ) = 0; - - virtual void StopSound( int iEntIndex, int iChannel, const char *pSample ) = 0; - - // stop all active sounds (client only) - virtual void StopAllSounds(bool bClearBuffers) = 0; - - // Set the room type for a player (client only) - virtual void SetRoomType( IRecipientFilter& filter, int roomType ) = 0; - - // Set the dsp preset for a player (client only) - virtual void SetPlayerDSP( IRecipientFilter& filter, int dspType, bool fastReset ) = 0; - - // emit an "ambient" sound that isn't spatialized - // only available on the client, assert on server - virtual void EmitAmbientSound( const char *pSample, float flVolume, int iPitch = PITCH_NORM, int flags = 0, float soundtime = 0.0f ) = 0; - - -// virtual EntChannel_t CreateEntChannel() = 0; - - virtual float GetDistGainFromSoundLevel( soundlevel_t soundlevel, float dist ) = 0; - - // Client .dll only functions - virtual int GetGuidForLastSoundEmitted() = 0; - virtual bool IsSoundStillPlaying( int guid ) = 0; - virtual void StopSoundByGuid( int guid ) = 0; - // Set's master volume (0.0->1.0) - virtual void SetVolumeByGuid( int guid, float fvol ) = 0; - - // Retrieves list of all active sounds - virtual void GetActiveSounds( CUtlVector< SndInfo_t >& sndlist ) = 0; - - virtual void PrecacheSentenceGroup( const char *pGroupName ) = 0; - virtual void NotifyBeginMoviePlayback() = 0; - virtual void NotifyEndMoviePlayback() = 0; -}; - - -#endif // IENGINESOUND_H diff --git a/public/engine/IEngineTrace.h b/public/engine/IEngineTrace.h deleted file mode 100644 index e66df9432..000000000 --- a/public/engine/IEngineTrace.h +++ /dev/null @@ -1,192 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef ENGINE_IENGINETRACE_H -#define ENGINE_IENGINETRACE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "basehandle.h" -#include "utlvector.h" //need CUtlVector for IEngineTrace::GetBrushesIn*() -#include "mathlib/vector4d.h" - -class Vector; -class IHandleEntity; -struct Ray_t; -class CGameTrace; -typedef CGameTrace trace_t; -class ICollideable; -class QAngle; -class CTraceListData; -class CPhysCollide; -struct cplane_t; - -//----------------------------------------------------------------------------- -// The standard trace filter... NOTE: Most normal traces inherit from CTraceFilter!!! -//----------------------------------------------------------------------------- -enum TraceType_t -{ - TRACE_EVERYTHING = 0, - TRACE_WORLD_ONLY, // NOTE: This does *not* test static props!!! - TRACE_ENTITIES_ONLY, // NOTE: This version will *not* test static props - TRACE_EVERYTHING_FILTER_PROPS, // NOTE: This version will pass the IHandleEntity for props through the filter, unlike all other filters -}; - -abstract_class ITraceFilter -{ -public: - virtual bool ShouldHitEntity( IHandleEntity *pEntity, int contentsMask ) = 0; - virtual TraceType_t GetTraceType() const = 0; -}; - - -//----------------------------------------------------------------------------- -// Classes are expected to inherit these + implement the ShouldHitEntity method -//----------------------------------------------------------------------------- - -// This is the one most normal traces will inherit from -class CTraceFilter : public ITraceFilter -{ -public: - virtual TraceType_t GetTraceType() const - { - return TRACE_EVERYTHING; - } -}; - -class CTraceFilterEntitiesOnly : public ITraceFilter -{ -public: - virtual TraceType_t GetTraceType() const - { - return TRACE_ENTITIES_ONLY; - } -}; - - -//----------------------------------------------------------------------------- -// Classes need not inherit from these -//----------------------------------------------------------------------------- -class CTraceFilterWorldOnly : public ITraceFilter -{ -public: - bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ) - { - return false; - } - virtual TraceType_t GetTraceType() const - { - return TRACE_WORLD_ONLY; - } -}; - -class CTraceFilterWorldAndPropsOnly : public ITraceFilter -{ -public: - bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ) - { - return false; - } - virtual TraceType_t GetTraceType() const - { - return TRACE_EVERYTHING; - } -}; - -class CTraceFilterHitAll : public CTraceFilter -{ -public: - virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ) - { - return true; - } -}; - - -//----------------------------------------------------------------------------- -// Enumeration interface for EnumerateLinkEntities -//----------------------------------------------------------------------------- -abstract_class IEntityEnumerator -{ -public: - // This gets called with each handle - virtual bool EnumEntity( IHandleEntity *pHandleEntity ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Interface the engine exposes to the game DLL -//----------------------------------------------------------------------------- -#define INTERFACEVERSION_ENGINETRACE_SERVER "EngineTraceServer003" -#define INTERFACEVERSION_ENGINETRACE_CLIENT "EngineTraceClient003" -abstract_class IEngineTrace -{ -public: - // Returns the contents mask + entity at a particular world-space position - virtual int GetPointContents( const Vector &vecAbsPosition, IHandleEntity** ppEntity = NULL ) = 0; - - // Get the point contents, but only test the specific entity. This works - // on static props and brush models. - // - // If the entity isn't a static prop or a brush model, it returns CONTENTS_EMPTY and sets - // bFailed to true if bFailed is non-null. - virtual int GetPointContents_Collideable( ICollideable *pCollide, const Vector &vecAbsPosition ) = 0; - - // Traces a ray against a particular entity - virtual void ClipRayToEntity( const Ray_t &ray, unsigned int fMask, IHandleEntity *pEnt, trace_t *pTrace ) = 0; - - // Traces a ray against a particular entity - virtual void ClipRayToCollideable( const Ray_t &ray, unsigned int fMask, ICollideable *pCollide, trace_t *pTrace ) = 0; - - // A version that simply accepts a ray (can work as a traceline or tracehull) - virtual void TraceRay( const Ray_t &ray, unsigned int fMask, ITraceFilter *pTraceFilter, trace_t *pTrace ) = 0; - - // A version that sets up the leaf and entity lists and allows you to pass those in for collision. - virtual void SetupLeafAndEntityListRay( const Ray_t &ray, CTraceListData &traceData ) = 0; - virtual void SetupLeafAndEntityListBox( const Vector &vecBoxMin, const Vector &vecBoxMax, CTraceListData &traceData ) = 0; - virtual void TraceRayAgainstLeafAndEntityList( const Ray_t &ray, CTraceListData &traceData, unsigned int fMask, ITraceFilter *pTraceFilter, trace_t *pTrace ) = 0; - - // A version that sweeps a collideable through the world - // abs start + abs end represents the collision origins you want to sweep the collideable through - // vecAngles represents the collision angles of the collideable during the sweep - virtual void SweepCollideable( ICollideable *pCollide, const Vector &vecAbsStart, const Vector &vecAbsEnd, - const QAngle &vecAngles, unsigned int fMask, ITraceFilter *pTraceFilter, trace_t *pTrace ) = 0; - - // Enumerates over all entities along a ray - // If triggers == true, it enumerates all triggers along a ray - virtual void EnumerateEntities( const Ray_t &ray, bool triggers, IEntityEnumerator *pEnumerator ) = 0; - - // Same thing, but enumerate entitys within a box - virtual void EnumerateEntities( const Vector &vecAbsMins, const Vector &vecAbsMaxs, IEntityEnumerator *pEnumerator ) = 0; - - // Convert a handle entity to a collideable. Useful inside enumer - virtual ICollideable *GetCollideable( IHandleEntity *pEntity ) = 0; - - // HACKHACK: Temp for performance measurments - virtual int GetStatByIndex( int index, bool bClear ) = 0; - - - //finds brushes in an AABB, prone to some false positives - virtual void GetBrushesInAABB( const Vector &vMins, const Vector &vMaxs, CUtlVector *pOutput, int iContentsMask = 0xFFFFFFFF ) = 0; - - //Creates a CPhysCollide out of all displacements wholly or partially contained in the specified AABB - virtual CPhysCollide* GetCollidableFromDisplacementsInAABB( const Vector& vMins, const Vector& vMaxs ) = 0; - - //retrieve brush planes and contents, returns true if data is being returned in the output pointers, false if the brush doesn't exist - virtual bool GetBrushInfo( int iBrush, CUtlVector *pPlanesOut, int *pContentsOut ) = 0; - - virtual bool PointOutsideWorld( const Vector &ptTest ) = 0; //Tests a point to see if it's outside any playable area - - // Walks bsp to find the leaf containing the specified point - virtual int GetLeafContainingPoint( const Vector &ptTest ) = 0; -}; - - - -#endif // ENGINE_IENGINETRACE_H diff --git a/public/engine/IStaticPropMgr.h b/public/engine/IStaticPropMgr.h deleted file mode 100644 index 8d1180d45..000000000 --- a/public/engine/IStaticPropMgr.h +++ /dev/null @@ -1,99 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IPROPS_H -#define IPROPS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "interface.h" -#include "mathlib/vector.h" -#include "utlvector.h" -#include "basehandle.h" - - -struct vcollide_t; -struct Ray_t; -class IClientRenderable; -class CGameTrace; -typedef CGameTrace trace_t; -class IVPhysicsKeyHandler; -class IPhysicsEnvironment; -class ICollideable; - - -//----------------------------------------------------------------------------- -// Interface versions for static props -//----------------------------------------------------------------------------- -#define INTERFACEVERSION_STATICPROPMGR_CLIENT "StaticPropMgrClient004" -#define INTERFACEVERSION_STATICPROPMGR_SERVER "StaticPropMgrServer002" - - -//----------------------------------------------------------------------------- -// Interface for static props -//----------------------------------------------------------------------------- -abstract_class IStaticPropMgr -{ -public: - // Create physics representations of props - virtual void CreateVPhysicsRepresentations( IPhysicsEnvironment *physenv, IVPhysicsKeyHandler *pDefaults, void *pGameData ) = 0; - - // Purpose: Trace a ray against the specified static Prop. Returns point of intersection in trace_t - virtual void TraceRayAgainstStaticProp( const Ray_t& ray, int staticPropIndex, trace_t& tr ) = 0; - - // Is a base handle a static prop? - virtual bool IsStaticProp( IHandleEntity *pHandleEntity ) const = 0; - virtual bool IsStaticProp( CBaseHandle handle ) const = 0; - - // returns a collideable interface to static props - virtual ICollideable *GetStaticPropByIndex( int propIndex ) = 0; -}; - -abstract_class IStaticPropMgrClient : public IStaticPropMgr -{ -public: - // Recomputes the static prop opacity given a view origin - virtual void ComputePropOpacity( const Vector &viewOrigin, float factor ) = 0; - - // Adds decals to static props, returns point of decal in trace_t - virtual void AddDecalToStaticProp( const Vector& rayStart, const Vector& rayEnd, - int staticPropIndex, int decalIndex, bool doTrace, trace_t& tr ) = 0; - - // Adds/removes shadows from static props - virtual void AddShadowToStaticProp( unsigned short shadowHandle, IClientRenderable* pRenderable ) = 0; - virtual void RemoveAllShadowsFromStaticProp( IClientRenderable* pRenderable ) = 0; - - // Gets the lighting + material color of a static prop - virtual void GetStaticPropMaterialColorAndLighting( trace_t* pTrace, - int staticPropIndex, Vector& lighting, Vector& matColor ) = 0; - - //Changes made specifically to support the Portal mod (smack Dave Kircher if something breaks) (Added separately to both client and server to not mess with versioning) - //=================================================================== - virtual void GetAllStaticProps( CUtlVector *pOutput ) = 0; //testing function that will eventually be removed - virtual void GetAllStaticPropsInAABB( const Vector &vMins, const Vector &vMaxs, CUtlVector *pOutput ) = 0; //get all static props that exist wholly or partially in an AABB - virtual void GetAllStaticPropsInOBB( const Vector &ptOrigin, const Vector &vExtent1, const Vector &vExtent2, const Vector &vExtent3, CUtlVector *pOutput ) = 0; //get all static props that exist wholly or partially in an OBB - //=================================================================== - - virtual void DrawStaticProps( IClientRenderable **pProps, int count, bool bShadowDepth, bool drawVCollideWireframe ) = 0; -}; - -class IStaticPropMgrServer : public IStaticPropMgr -{ -public: - - - //Changes made specifically to support the Portal mod (smack Dave Kircher if something breaks) (Added separately to both client and server to not mess with versioning) - //=================================================================== - virtual void GetAllStaticProps( CUtlVector *pOutput ) = 0; //testing function that will eventually be removed - virtual void GetAllStaticPropsInAABB( const Vector &vMins, const Vector &vMaxs, CUtlVector *pOutput ) = 0; //get all static props that exist wholly or partially in an AABB - virtual void GetAllStaticPropsInOBB( const Vector &ptOrigin, const Vector &vExtent1, const Vector &vExtent2, const Vector &vExtent3, CUtlVector *pOutput ) = 0; //get all static props that exist wholly or partially in an OBB - //=================================================================== -}; - - -#endif // IPROPS_H diff --git a/public/engine/SndInfo.h b/public/engine/SndInfo.h deleted file mode 100644 index 75783550f..000000000 --- a/public/engine/SndInfo.h +++ /dev/null @@ -1,49 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef SNDINFO_H -#define SNDINFO_H -#ifdef _WIN32 -#pragma once -#endif - -class Vector; -#include "utlsymbol.h" - -//----------------------------------------------------------------------------- -// Purpose: Client side only -//----------------------------------------------------------------------------- -struct SndInfo_t -{ - // Sound Guid - int m_nGuid; - FileNameHandle_t m_filenameHandle; // filesystem filename handle - call IFilesystem to conver this to a string - int m_nSoundSource; - int m_nChannel; - // If a sound is being played through a speaker entity (e.g., on a monitor,), this is the - // entity upon which to show the lips moving, if the sound has sentence data - int m_nSpeakerEntity; - float m_flVolume; - float m_flLastSpatializedVolume; - // Radius of this sound effect (spatialization is different within the radius) - float m_flRadius; - int m_nPitch; - Vector *m_pOrigin; - Vector *m_pDirection; - - // if true, assume sound source can move and update according to entity - bool m_bUpdatePositions; - // true if playing linked sentence - bool m_bIsSentence; - // if true, bypass all dsp processing for this sound (ie: music) - bool m_bDryMix; - // true if sound is playing through in-game speaker entity. - bool m_bSpeaker; - // for snd_show, networked sounds get colored differently than local sounds - bool m_bFromServer; -}; - -#endif // SNDINFO_H diff --git a/public/engine/imatchmaking.h b/public/engine/imatchmaking.h deleted file mode 100644 index c3ccfa909..000000000 --- a/public/engine/imatchmaking.h +++ /dev/null @@ -1,117 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#ifndef IMATCHMAKING_H -#define IMATCHMAKING_H -#ifdef _WIN32 -#pragma once -#endif - -#include "const.h" -#include "vgui/VGUI.h" - -#if !defined( _X360 ) -#include "xbox/xboxstubs.h" -#endif - -class KeyValues; - -enum SESSION_NOTIFY -{ - SESSION_NOTIFY_FAIL_SEARCH, - SESSION_NOTIFY_SEARCH_COMPLETED, - SESSION_NOFIFY_MODIFYING_SESSION, - SESSION_NOTIFY_MODIFYING_COMPLETED_HOST, - SESSION_NOTIFY_MODIFYING_COMPLETED_CLIENT, - SESSION_NOTIFY_MIGRATION_COMPLETED, - SESSION_NOTIFY_CONNECT_SESSIONFULL, - SESSION_NOTIFY_CONNECT_NOTAVAILABLE, - SESSION_NOTIFY_CONNECTED_TOSESSION, - SESSION_NOTIFY_CONNECTED_TOSERVER, - SESSION_NOTIFY_CONNECT_FAILED, - SESSION_NOTIFY_FAIL_CREATE, - SESSION_NOTIFY_FAIL_MIGRATE, - SESSION_NOTIFY_REGISTER_COMPLETED, - SESSION_NOTIFY_FAIL_REGISTER, - SESSION_NOTIFY_CLIENT_KICKED, - SESSION_NOTIFY_CREATED_HOST, - SESSION_NOTIFY_CREATED_CLIENT, - SESSION_NOTIFY_LOST_HOST, - SESSION_NOTIFY_LOST_SERVER, - SESSION_NOTIFY_COUNTDOWN, - SESSION_NOTIFY_ENDGAME_RANKED, // Ranked - SESSION_NOTIFY_ENDGAME_HOST, // Unranked - SESSION_NOTIFY_ENDGAME_CLIENT, // Unranked - SESSION_NOTIFY_DUMPSTATS, // debugging - SESSION_NOTIFY_WELCOME, // Close all dialogs and show the welcome main menu -}; - -enum SESSION_PROPS -{ - SESSION_CONTEXT, - SESSION_PROPERTY, - SESSION_FLAG, -}; - -struct hostData_s -{ - char hostName[MAX_PLAYER_NAME_LENGTH]; - char scenario[MAX_MAP_NAME]; - int gameState; - int gameTime; - XUID xuid; -}; - -struct MM_QOS_t -{ - int nPingMsMin; // Minimum round-trip time in ms - int nPingMsMed; // Median round-trip time in ms - float flBwUpKbs; // Bandwidth upstream in kilobytes/s - float flBwDnKbs; // Bandwidth downstream in kilobytes/s - float flLoss; // Average packet loss in percents -}; - -#define NO_TIME_LIMIT 65000 - -abstract_class IMatchmaking -{ -public: - virtual void SessionNotification( const SESSION_NOTIFY notification, const int param = 0 ) = 0; - virtual void AddSessionProperty( const uint nType, const char *pID, const char *pValue, const char *pValueType ) = 0; - virtual void SetSessionProperties( KeyValues *pPropertyKeys ) = 0; - virtual void SelectSession( uint idx ) = 0; - virtual void ModifySession() = 0; - virtual void UpdateMuteList() = 0; - virtual void StartHost( bool bSystemLink = false ) = 0; - virtual void StartClient( bool bSystemLink = false ) = 0; - virtual bool StartGame() = 0; - virtual bool CancelStartGame() = 0; - virtual void ChangeTeam( const char *pTeamName ) = 0; - virtual void TellClientsToConnect() = 0; - virtual void CancelCurrentOperation() = 0; - virtual void KickPlayerFromSession( uint64 id ) = 0; - virtual void JoinInviteSession( XSESSION_INFO *pHostInfo ) = 0; - virtual void JoinInviteSessionByID( XNKID nSessionID ) = 0; - virtual void EndStatsReporting() = 0; - - // For Gameui - virtual KeyValues *GetSessionProperties() = 0; - - // For voice chat - virtual uint64 PlayerIdToXuid( int playerId ) = 0; - virtual bool IsPlayerMuted( int iUserId, XUID id ) = 0; - - // To determine host Quality-of-Service - virtual MM_QOS_t GetQosWithLIVE() = 0; - - // Used by non-'host' local machines which are starting a map to "prime" the caches. Will sit at near completion indefinitely -- - // the client is waiting for a TellClientsToConnect message - virtual bool PreventFullServerStartup() = 0; -}; - -#define VENGINE_MATCHMAKING_VERSION "VENGINE_MATCHMAKING_VERSION001" - -#endif // IMATCHMAKING_H diff --git a/public/engine/iserverplugin.h b/public/engine/iserverplugin.h deleted file mode 100644 index 3fb17de86..000000000 --- a/public/engine/iserverplugin.h +++ /dev/null @@ -1,159 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef ISERVERPLUGIN_H -#define ISERVERPLUGIN_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "edict.h" -#include "tier1/interface.h" -#include "tier1/KeyValues.h" - -class CCommand; - -// -// you will also want to listen for game events via IGameEventManager::AddListener() -// - -typedef enum -{ - PLUGIN_CONTINUE = 0, // keep going - PLUGIN_OVERRIDE, // run the game dll function but use our return value instead - PLUGIN_STOP, // don't run the game dll function at all -} PLUGIN_RESULT; - - -typedef enum -{ - eQueryCvarValueStatus_ValueIntact=0, // It got the value fine. - eQueryCvarValueStatus_CvarNotFound=1, - eQueryCvarValueStatus_NotACvar=2, // There's a ConCommand, but it's not a ConVar. - eQueryCvarValueStatus_CvarProtected=3 // The cvar was marked with FCVAR_SERVER_CAN_NOT_QUERY, so the server is not allowed to have its value. -} EQueryCvarValueStatus; - - -typedef int QueryCvarCookie_t; -#define InvalidQueryCvarCookie -1 - - -#define INTERFACEVERSION_ISERVERPLUGINCALLBACKS_VERSION_1 "ISERVERPLUGINCALLBACKS001" -#define INTERFACEVERSION_ISERVERPLUGINCALLBACKS "ISERVERPLUGINCALLBACKS002" - -//----------------------------------------------------------------------------- -// Purpose: callbacks the engine exposes to the 3rd party plugins (ala MetaMod) -//----------------------------------------------------------------------------- -abstract_class IServerPluginCallbacks -{ -public: - // Initialize the plugin to run - // Return false if there is an error during startup. - virtual bool Load( CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory ) = 0; - - // Called when the plugin should be shutdown - virtual void Unload( void ) = 0; - - // called when a plugins execution is stopped but the plugin is not unloaded - virtual void Pause( void ) = 0; - - // called when a plugin should start executing again (sometime after a Pause() call) - virtual void UnPause( void ) = 0; - - // Returns string describing current plugin. e.g., Admin-Mod. - virtual const char *GetPluginDescription( void ) = 0; - - // Called any time a new level is started (after GameInit() also on level transitions within a game) - virtual void LevelInit( char const *pMapName ) = 0; - - // The server is about to activate - virtual void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax ) = 0; - - // The server should run physics/think on all edicts - virtual void GameFrame( bool simulating ) = 0; - - // Called when a level is shutdown (including changing levels) - virtual void LevelShutdown( void ) = 0; - - // Client is going active - virtual void ClientActive( edict_t *pEntity ) = 0; - - // Client is disconnecting from server - virtual void ClientDisconnect( edict_t *pEntity ) = 0; - - // Client is connected and should be put in the game - virtual void ClientPutInServer( edict_t *pEntity, char const *playername ) = 0; - - // Sets the client index for the client who typed the command into their console - virtual void SetCommandClient( int index ) = 0; - - // A player changed one/several replicated cvars (name etc) - virtual void ClientSettingsChanged( edict_t *pEdict ) = 0; - - // Client is connecting to server ( set retVal to false to reject the connection ) - // You can specify a rejection message by writing it into reject - virtual PLUGIN_RESULT ClientConnect( bool *bAllowConnect, edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen ) = 0; - - // The client has typed a command at the console - virtual PLUGIN_RESULT ClientCommand( edict_t *pEntity, const CCommand &args ) = 0; - - // A user has had their network id setup and validated - virtual PLUGIN_RESULT NetworkIDValidated( const char *pszUserName, const char *pszNetworkID ) = 0; - - // This is called when a query from IServerPluginHelpers::StartQueryCvarValue is finished. - // iCookie is the value returned by IServerPluginHelpers::StartQueryCvarValue. - // Added with version 2 of the interface. - virtual void OnQueryCvarValueFinished( QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue ) = 0; - -}; - -#define INTERFACEVERSION_ISERVERPLUGINHELPERS "ISERVERPLUGINHELPERS001" - - -typedef enum -{ - DIALOG_MSG = 0, // just an on screen message - DIALOG_MENU, // an options menu - DIALOG_TEXT, // a richtext dialog - DIALOG_ENTRY, // an entry box - DIALOG_ASKCONNECT // Ask the client to connect to a specified IP address. Only the "time" and "title" keys are used. -} DIALOG_TYPE; - -//----------------------------------------------------------------------------- -// Purpose: functions that only 3rd party plugins need -//----------------------------------------------------------------------------- -abstract_class IServerPluginHelpers -{ -public: - // creates an onscreen menu with various option buttons - // The keyvalues param can contain these fields: - // "title" - (string) the title to show in the hud and in the title bar - // "msg" - (string) a longer message shown in the GameUI - // "color" - (color) the color to display the message in the hud (white by default) - // "level" - (int) the priority of this message (closer to 0 is higher), only 1 message can be outstanding at a time - // "time" - (int) the time in seconds this message should stay active in the GameUI (min 10 sec, max 200 sec) - // - // For DIALOG_MENU add sub keys for each option with these fields: - // "command" - (string) client command to run if selected - // "msg" - (string) button text for this option - // - virtual void CreateMessage( edict_t *pEntity, DIALOG_TYPE type, KeyValues *data, IServerPluginCallbacks *plugin ) = 0; - virtual void ClientCommand( edict_t *pEntity, const char *cmd ) = 0; - - // Call this to find out the value of a cvar on the client. - // - // It is an asynchronous query, and it will call IServerPluginCallbacks::OnQueryCvarValueFinished when - // the value comes in from the client. - // - // Store the return value if you want to match this specific query to the OnQueryCvarValueFinished call. - // Returns InvalidQueryCvarCookie if the entity is invalid. - virtual QueryCvarCookie_t StartQueryCvarValue( edict_t *pEntity, const char *pName ) = 0; -}; - -#endif //ISERVERPLUGIN_H diff --git a/public/engine/ishadowmgr.h b/public/engine/ishadowmgr.h deleted file mode 100644 index 873359555..000000000 --- a/public/engine/ishadowmgr.h +++ /dev/null @@ -1,189 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef ISHADOWMGR_H -#define ISHADOWMGR_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "interface.h" -#include "mathlib/vmatrix.h" - - -//----------------------------------------------------------------------------- -// forward declarations -//----------------------------------------------------------------------------- - -class IMaterial; -class Vector; -class Vector2D; -struct model_t; -typedef unsigned short ModelInstanceHandle_t; -class IClientRenderable; -class ITexture; - -// change this when the new version is incompatable with the old -#define ENGINE_SHADOWMGR_INTERFACE_VERSION "VEngineShadowMgr002" - - -//----------------------------------------------------------------------------- -// Flags for the creation method -//----------------------------------------------------------------------------- -enum ShadowFlags_t -{ - SHADOW_FLAGS_FLASHLIGHT = (1 << 0), - SHADOW_FLAGS_SHADOW = (1 << 1), - // Update this if you add flags - SHADOW_FLAGS_LAST_FLAG = SHADOW_FLAGS_SHADOW -}; - -#define SHADOW_FLAGS_PROJECTED_TEXTURE_TYPE_MASK ( SHADOW_FLAGS_FLASHLIGHT | SHADOW_FLAGS_SHADOW ) - - -//----------------------------------------------------------------------------- -// -// Shadow-related functionality exported by the engine -// -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -// This is a handle to shadows, clients can create as many as they want -//----------------------------------------------------------------------------- -typedef unsigned short ShadowHandle_t; - -enum -{ - SHADOW_HANDLE_INVALID = (ShadowHandle_t)~0 -}; - - -//----------------------------------------------------------------------------- -// Used for the creation Flags field of CreateShadow -//----------------------------------------------------------------------------- -enum ShadowCreateFlags_t -{ - SHADOW_CACHE_VERTS = ( 1 << 0 ), - SHADOW_FLASHLIGHT = ( 1 << 1 ), - - SHADOW_LAST_FLAG = SHADOW_FLASHLIGHT, -}; - - -//----------------------------------------------------------------------------- -// Information about a particular shadow -//----------------------------------------------------------------------------- -struct ShadowInfo_t -{ - // Transforms from world space into texture space of the shadow - VMatrix m_WorldToShadow; - - // The shadow should no longer be drawn once it's further than MaxDist - // along z in shadow texture coordinates. - float m_FalloffOffset; - float m_MaxDist; - float m_FalloffAmount; // how much to lighten the shadow maximally - Vector2D m_TexOrigin; - Vector2D m_TexSize; - unsigned char m_FalloffBias; -}; - -struct FlashlightState_t; - -//----------------------------------------------------------------------------- -// The engine's interface to the shadow manager -//----------------------------------------------------------------------------- -abstract_class IShadowMgr -{ -public: - // Create, destroy shadows (see ShadowCreateFlags_t for creationFlags) - virtual ShadowHandle_t CreateShadow( IMaterial* pMaterial, IMaterial* pModelMaterial, void* pBindProxy, int creationFlags ) = 0; - virtual void DestroyShadow( ShadowHandle_t handle ) = 0; - - // Resets the shadow material (useful for shadow LOD.. doing blobby at distance) - virtual void SetShadowMaterial( ShadowHandle_t handle, IMaterial* pMaterial, IMaterial* pModelMaterial, void* pBindProxy ) = 0; - - // Shadow opacity -// virtual void SetShadowOpacity( ShadowHandle_t handle, float alpha ) = 0; -// virtual float GetShadowOpacity( ShadowHandle_t handle ) const = 0; - - // Project a shadow into the world - // The two points specify the upper left coordinate and the lower-right - // coordinate of the shadow specified in a shadow "viewplane". The - // projection matrix is a shadow viewplane->world transformation, - // and can be orthographic orperspective. - - // I expect that the client DLL will call this method any time the shadow - // changes because the light changes, or because the entity casting the - // shadow moves - - // Note that we can't really control the shadows from the engine because - // the engine only knows about pevs, which don't exist on the client - - // The shadow matrix specifies a world-space transform for the shadow - // the shadow is projected down the z direction, and the origin of the - // shadow matrix is the origin of the projection ray. The size indicates - // the shadow size measured in the space of the shadow matrix; the - // shadow goes from +/- size.x/2 along the x axis of the shadow matrix - // and +/- size.y/2 along the y axis of the shadow matrix. - virtual void ProjectShadow( ShadowHandle_t handle, const Vector &origin, - const Vector& projectionDir, const VMatrix& worldToShadow, const Vector2D& size, - int nLeafCount, const int *pLeafList, - float maxHeight, float falloffOffset, float falloffAmount, const Vector &vecCasterOrigin ) = 0; - - virtual void ProjectFlashlight( ShadowHandle_t handle, const VMatrix &worldToShadow, int nLeafCount, const int *pLeafList ) = 0; - - // Gets at information about a particular shadow - virtual const ShadowInfo_t &GetInfo( ShadowHandle_t handle ) = 0; - - virtual const Frustum_t &GetFlashlightFrustum( ShadowHandle_t handle ) = 0; - - // Methods related to shadows on brush models - virtual void AddShadowToBrushModel( ShadowHandle_t handle, - model_t* pModel, const Vector& origin, const QAngle& angles ) = 0; - - // Removes all shadows from a brush model - virtual void RemoveAllShadowsFromBrushModel( model_t* pModel ) = 0; - - // Sets the texture coordinate range for a shadow... - virtual void SetShadowTexCoord( ShadowHandle_t handle, float x, float y, float w, float h ) = 0; - - // Methods related to shadows on studio models - virtual void AddShadowToModel( ShadowHandle_t shadow, ModelInstanceHandle_t instance ) = 0; - virtual void RemoveAllShadowsFromModel( ModelInstanceHandle_t instance ) = 0; - - // Set extra clip planes related to shadows... - // These are used to prevent pokethru and back-casting - virtual void ClearExtraClipPlanes( ShadowHandle_t shadow ) = 0; - virtual void AddExtraClipPlane( ShadowHandle_t shadow, const Vector& normal, float dist ) = 0; - - // Allows us to disable particular shadows - virtual void EnableShadow( ShadowHandle_t shadow, bool bEnable ) = 0; - - // Set the darkness falloff bias - virtual void SetFalloffBias( ShadowHandle_t shadow, unsigned char ucBias ) = 0; - - // Update the state for a flashlight. - virtual void UpdateFlashlightState( ShadowHandle_t shadowHandle, const FlashlightState_t &lightState ) = 0; - - virtual void DrawFlashlightDepthTexture( ) = 0; - - virtual void AddFlashlightRenderable( ShadowHandle_t shadow, IClientRenderable *pRenderable ) = 0; - virtual ShadowHandle_t CreateShadowEx( IMaterial* pMaterial, IMaterial* pModelMaterial, void* pBindProxy, int creationFlags ) = 0; - - virtual void SetFlashlightDepthTexture( ShadowHandle_t shadowHandle, ITexture *pFlashlightDepthTexture, unsigned char ucShadowStencilBit ) = 0; - - virtual const FlashlightState_t &GetFlashlightState( ShadowHandle_t handle ) = 0; - - virtual void SetFlashlightRenderState( ShadowHandle_t handle ) = 0; -}; - - -#endif diff --git a/public/engine/ivdebugoverlay.h b/public/engine/ivdebugoverlay.h deleted file mode 100644 index 5c0bb8725..000000000 --- a/public/engine/ivdebugoverlay.h +++ /dev/null @@ -1,63 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -// -// cdll_int.h -// -// 4-23-98 -// JOHN: client dll interface declarations -// - -#ifndef IVDEBUGOVERLAY_H -#define IVDEBUGOVERLAY_H - -#ifdef _WIN32 -#pragma once -#endif - -class Vector; - -#define VDEBUG_OVERLAY_INTERFACE_VERSION "VDebugOverlay003" - -// When used as a duration by a server-side NDebugOverlay:: call, -// causes the overlay to persist until the next server update. -#define NDEBUG_PERSIST_TILL_NEXT_SERVER (0.01023f) - -class OverlayText_t; - -abstract_class IVDebugOverlay -{ -public: - virtual void AddEntityTextOverlay(int ent_index, int line_offset, float duration, int r, int g, int b, int a, const char *format, ...) = 0; - virtual void AddBoxOverlay(const Vector& origin, const Vector& mins, const Vector& max, QAngle const& orientation, int r, int g, int b, int a, float duration) = 0; - virtual void AddTriangleOverlay(const Vector& p1, const Vector& p2, const Vector& p3, int r, int g, int b, int a, bool noDepthTest, float duration) = 0; - virtual void AddLineOverlay(const Vector& origin, const Vector& dest, int r, int g, int b,bool noDepthTest, float duration) = 0; - virtual void AddTextOverlay(const Vector& origin, float duration, const char *format, ...) = 0; - virtual void AddTextOverlay(const Vector& origin, int line_offset, float duration, const char *format, ...) = 0; - virtual void AddScreenTextOverlay(float flXPos, float flYPos,float flDuration, int r, int g, int b, int a, const char *text) = 0; - virtual void AddSweptBoxOverlay(const Vector& start, const Vector& end, const Vector& mins, const Vector& max, const QAngle & angles, int r, int g, int b, int a, float flDuration) = 0; - virtual void AddGridOverlay(const Vector& origin) = 0; - virtual int ScreenPosition(const Vector& point, Vector& screen) = 0; - virtual int ScreenPosition(float flXPos, float flYPos, Vector& screen) = 0; - - virtual OverlayText_t *GetFirst( void ) = 0; - virtual OverlayText_t *GetNext( OverlayText_t *current ) = 0; - virtual void ClearDeadOverlays( void ) = 0; - virtual void ClearAllOverlays() = 0; - - virtual void AddTextOverlayRGB(const Vector& origin, int line_offset, float duration, float r, float g, float b, float alpha, const char *format, ...) = 0; - virtual void AddTextOverlayRGB(const Vector& origin, int line_offset, float duration, int r, int g, int b, int a, const char *format, ...) = 0; - - virtual void AddLineOverlayAlpha(const Vector& origin, const Vector& dest, int r, int g, int b, int a, bool noDepthTest, float duration) = 0; - virtual void AddBoxOverlay2( const Vector& origin, const Vector& mins, const Vector& max, QAngle const& orientation, const Color& faceColor, const Color& edgeColor, float duration ) = 0; - -private: - inline void AddTextOverlay(const Vector& origin, int line_offset, float duration, int r, int g, int b, int a, const char *format, ...) {} /* catch improper use of bad interface. Needed because '0' duration can be resolved by compiler to NULL format string (i.e., compiles but calls wrong function) */ -}; - - -#endif // IVDEBUGOVERLAY_H diff --git a/public/engine/ivmodelinfo.h b/public/engine/ivmodelinfo.h deleted file mode 100644 index 0490f00aa..000000000 --- a/public/engine/ivmodelinfo.h +++ /dev/null @@ -1,135 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef IVMODELINFO_H -#define IVMODELINFO_H - -#ifdef _WIN32 -#pragma once -#endif - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class IMaterial; -class KeyValues; -struct vcollide_t; -struct model_t; -class Vector; -class QAngle; -class CGameTrace; -struct cplane_t; -typedef CGameTrace trace_t; -struct studiohdr_t; -struct virtualmodel_t; -typedef unsigned char byte; -struct virtualterrainparams_t; -class CPhysCollide; -typedef unsigned short MDLHandle_t; -class CUtlBuffer; -class IClientRenderable; - - -//----------------------------------------------------------------------------- -// Model info interface -//----------------------------------------------------------------------------- - -// change this when the new version is incompatable with the old -#define VMODELINFO_CLIENT_INTERFACE_VERSION "VModelInfoClient004" -#define VMODELINFO_SERVER_INTERFACE_VERSION "VModelInfoServer002" - -class IVModelInfo -{ -public: - virtual ~IVModelInfo( void ) { } - - virtual const model_t *GetModel( int modelindex ) const = 0; - // Returns index of model by name - virtual int GetModelIndex( const char *name ) const = 0; - - // Returns name of model - virtual const char *GetModelName( const model_t *model ) const = 0; - virtual vcollide_t *GetVCollide( const model_t *model ) const = 0; - virtual vcollide_t *GetVCollide( int modelindex ) const = 0; - virtual void GetModelBounds( const model_t *model, Vector& mins, Vector& maxs ) const = 0; - virtual void GetModelRenderBounds( const model_t *model, Vector& mins, Vector& maxs ) const = 0; - virtual int GetModelFrameCount( const model_t *model ) const = 0; - virtual int GetModelType( const model_t *model ) const = 0; - virtual void *GetModelExtraData( const model_t *model ) = 0; - virtual bool ModelHasMaterialProxy( const model_t *model ) const = 0; - virtual bool IsTranslucent( model_t const* model ) const = 0; - virtual bool IsTranslucentTwoPass( const model_t *model ) const = 0; - virtual void RecomputeTranslucency( const model_t *model, int nSkin, int nBody, void /*IClientRenderable*/ *pClientRenderable ) = 0; - virtual int GetModelMaterialCount( const model_t* model ) const = 0; - virtual void GetModelMaterials( const model_t *model, int count, IMaterial** ppMaterial ) = 0; - virtual bool IsModelVertexLit( const model_t *model ) const = 0; - virtual const char *GetModelKeyValueText( const model_t *model ) = 0; - virtual bool GetModelKeyValue( const model_t *model, CUtlBuffer &buf ) = 0; // supports keyvalue blocks in submodels - virtual float GetModelRadius( const model_t *model ) = 0; - - virtual const studiohdr_t *FindModel( const studiohdr_t *pStudioHdr, void **cache, const char *modelname ) const = 0; - virtual const studiohdr_t *FindModel( void *cache ) const = 0; - virtual virtualmodel_t *GetVirtualModel( const studiohdr_t *pStudioHdr ) const = 0; - virtual byte *GetAnimBlock( const studiohdr_t *pStudioHdr, int iBlock ) const = 0; - - // Available on client only!!! - virtual void GetModelMaterialColorAndLighting( const model_t *model, Vector const& origin, - QAngle const& angles, trace_t* pTrace, - Vector& lighting, Vector& matColor ) = 0; - virtual void GetIlluminationPoint( const model_t *model, IClientRenderable *pRenderable, Vector const& origin, - QAngle const& angles, Vector* pLightingCenter ) = 0; - - virtual int GetModelContents( int modelIndex ) const = 0; - virtual studiohdr_t *GetStudiomodel( const model_t *mod ) = 0; - virtual int GetModelSpriteWidth( const model_t *model ) const = 0; - virtual int GetModelSpriteHeight( const model_t *model ) const = 0; - - // Sets/gets a map-specified fade range (client only) - virtual void SetLevelScreenFadeRange( float flMinSize, float flMaxSize ) = 0; - virtual void GetLevelScreenFadeRange( float *pMinArea, float *pMaxArea ) const = 0; - - // Sets/gets a map-specified per-view fade range (client only) - virtual void SetViewScreenFadeRange( float flMinSize, float flMaxSize ) = 0; - - // Computes fade alpha based on distance fade + screen fade (client only) - virtual unsigned char ComputeLevelScreenFade( const Vector &vecAbsOrigin, float flRadius, float flFadeScale ) const = 0; - virtual unsigned char ComputeViewScreenFade( const Vector &vecAbsOrigin, float flRadius, float flFadeScale ) const = 0; - - // both client and server - virtual int GetAutoplayList( const studiohdr_t *pStudioHdr, unsigned short **pAutoplayList ) const = 0; - - // Gets a virtual terrain collision model (creates if necessary) - // NOTE: This may return NULL if the terrain model cannot be virtualized - virtual CPhysCollide *GetCollideForVirtualTerrain( int index ) = 0; - - virtual bool IsUsingFBTexture( const model_t *model, int nSkin, int nBody, void /*IClientRenderable*/ *pClientRenderable ) const = 0; - - virtual const model_t *FindOrLoadModel( const char *name ) const = 0; - - virtual MDLHandle_t GetCacheHandle( const model_t *model ) const = 0; - - // Returns planes of non-nodraw brush model surfaces - virtual int GetBrushModelPlaneCount( const model_t *model ) const = 0; - virtual void GetBrushModelPlane( const model_t *model, int nIndex, cplane_t &plane, Vector *pOrigin ) const = 0; - virtual int GetSurfacepropsForVirtualTerrain( int index ) = 0; -}; - - -class IVModelInfoClient : public IVModelInfo -{ -public: -}; - - -struct virtualterrainparams_t -{ - // UNDONE: Add grouping here, specified in BSP file? (test grouping to see if this is necessary) - int index; -}; - -#endif // IVMODELINFO_H diff --git a/public/engine/ivmodelrender.h b/public/engine/ivmodelrender.h deleted file mode 100644 index 57361fa2a..000000000 --- a/public/engine/ivmodelrender.h +++ /dev/null @@ -1,180 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// - -#ifndef IVMODELRENDER_H -#define IVMODELRENDER_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "interface.h" -#include "mathlib/mathlib.h" -#include "istudiorender.h" - -//----------------------------------------------------------------------------- -// forward declarations -//----------------------------------------------------------------------------- -struct mstudioanimdesc_t; -struct mstudioseqdesc_t; -struct model_t; -class IClientRenderable; -class Vector; -struct studiohdr_t; -class IMaterial; -class CStudioHdr; - -FORWARD_DECLARE_HANDLE( LightCacheHandle_t ); - - -//----------------------------------------------------------------------------- -// Model rendering state -//----------------------------------------------------------------------------- -struct DrawModelState_t -{ - studiohdr_t* m_pStudioHdr; - studiohwdata_t* m_pStudioHWData; - IClientRenderable* m_pRenderable; - const matrix3x4_t *m_pModelToWorld; - StudioDecalHandle_t m_decals; - int m_drawFlags; - int m_lod; -}; - - -//----------------------------------------------------------------------------- -// Model Rendering + instance data -//----------------------------------------------------------------------------- - -// change this when the new version is incompatable with the old -#define VENGINE_HUDMODEL_INTERFACE_VERSION "VEngineModel016" - -typedef unsigned short ModelInstanceHandle_t; - -enum -{ - MODEL_INSTANCE_INVALID = (ModelInstanceHandle_t)~0 -}; - -struct ModelRenderInfo_t -{ - Vector origin; - QAngle angles; - IClientRenderable *pRenderable; - const model_t *pModel; - const matrix3x4_t *pModelToWorld; - const matrix3x4_t *pLightingOffset; - const Vector *pLightingOrigin; - int flags; - int entity_index; - int skin; - int body; - int hitboxset; - ModelInstanceHandle_t instance; - - ModelRenderInfo_t() - { - pModelToWorld = NULL; - pLightingOffset = NULL; - pLightingOrigin = NULL; - } -}; - -struct StaticPropRenderInfo_t -{ - const matrix3x4_t *pModelToWorld; - const model_t *pModel; - IClientRenderable *pRenderable; - Vector *pLightingOrigin; - short skin; - ModelInstanceHandle_t instance; -}; - -// UNDONE: Move this to hud export code, subsume previous functions -abstract_class IVModelRender -{ -public: - virtual int DrawModel( int flags, - IClientRenderable *pRenderable, - ModelInstanceHandle_t instance, - int entity_index, - const model_t *model, - Vector const& origin, - QAngle const& angles, - int skin, - int body, - int hitboxset, - const matrix3x4_t *modelToWorld = NULL, - const matrix3x4_t *pLightingOffset = NULL ) = 0; - - // This causes a material to be used when rendering the model instead - // of the materials the model was compiled with - virtual void ForcedMaterialOverride( IMaterial *newMaterial, OverrideType_t nOverrideType = OVERRIDE_NORMAL ) = 0; - - virtual void SetViewTarget( const CStudioHdr *pStudioHdr, int nBodyIndex, const Vector& target ) = 0; - - // Creates, destroys instance data to be associated with the model - virtual ModelInstanceHandle_t CreateInstance( IClientRenderable *pRenderable, LightCacheHandle_t *pCache = NULL ) = 0; - virtual void DestroyInstance( ModelInstanceHandle_t handle ) = 0; - - // Associates a particular lighting condition with a model instance handle. - // FIXME: This feature currently only works for static props. To make it work for entities, etc., - // we must clean up the lightcache handles as the model instances are removed. - // At the moment, since only the static prop manager uses this, it cleans up all LightCacheHandles - // at level shutdown. - virtual void SetStaticLighting( ModelInstanceHandle_t handle, LightCacheHandle_t* pHandle ) = 0; - virtual LightCacheHandle_t GetStaticLighting( ModelInstanceHandle_t handle ) = 0; - - // moves an existing InstanceHandle to a nex Renderable to keep decals etc. Models must be the same - virtual bool ChangeInstance( ModelInstanceHandle_t handle, IClientRenderable *pRenderable ) = 0; - - // Creates a decal on a model instance by doing a planar projection - // along the ray. The material is the decal material, the radius is the - // radius of the decal to create. - virtual void AddDecal( ModelInstanceHandle_t handle, Ray_t const& ray, - Vector const& decalUp, int decalIndex, int body, bool noPokeThru = false, int maxLODToDecal = ADDDECAL_TO_ALL_LODS ) = 0; - - // Removes all the decals on a model instance - virtual void RemoveAllDecals( ModelInstanceHandle_t handle ) = 0; - - // Remove all decals from all models - virtual void RemoveAllDecalsFromAllModels() = 0; - - // Shadow rendering, DrawModelShadowSetup returns the address of the bone-to-world array, NULL in case of error - virtual matrix3x4_t* DrawModelShadowSetup( IClientRenderable *pRenderable, int body, int skin, DrawModelInfo_t *pInfo, matrix3x4_t *pCustomBoneToWorld = NULL ) = 0; - virtual void DrawModelShadow( IClientRenderable *pRenderable, const DrawModelInfo_t &info, matrix3x4_t *pCustomBoneToWorld = NULL ) = 0; - - // This gets called when overbright, etc gets changed to recompute static prop lighting. - virtual bool RecomputeStaticLighting( ModelInstanceHandle_t handle ) = 0; - - virtual void ReleaseAllStaticPropColorData( void ) = 0; - virtual void RestoreAllStaticPropColorData( void ) = 0; - - // Extended version of drawmodel - virtual int DrawModelEx( ModelRenderInfo_t &pInfo ) = 0; - - virtual int DrawModelExStaticProp( ModelRenderInfo_t &pInfo ) = 0; - - virtual bool DrawModelSetup( ModelRenderInfo_t &pInfo, DrawModelState_t *pState, matrix3x4_t *pCustomBoneToWorld, matrix3x4_t** ppBoneToWorldOut ) = 0; - virtual void DrawModelExecute( const DrawModelState_t &state, const ModelRenderInfo_t &pInfo, matrix3x4_t *pCustomBoneToWorld = NULL ) = 0; - - // Sets up lighting context for a point in space - virtual void SetupLighting( const Vector &vecCenter ) = 0; - - // doesn't support any debug visualization modes or other model options, but draws static props in the - // fastest way possible - virtual int DrawStaticPropArrayFast( StaticPropRenderInfo_t *pProps, int count, bool bShadowDepth ) = 0; - - // Allow client to override lighting state - virtual void SuppressEngineLighting( bool bSuppress ) = 0; - - virtual void SetupColorMeshes( int nTotalVerts ) = 0; -}; - - -#endif // IVMODELRENDER_H diff --git a/public/engine/view_sharedv1.h b/public/engine/view_sharedv1.h deleted file mode 100644 index af5d8abbf..000000000 --- a/public/engine/view_sharedv1.h +++ /dev/null @@ -1,94 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======// -// -// Purpose: -// -//=============================================================================// - -#ifndef VIEW_SHAREDV1_H -#define VIEW_SHAREDV1_H - -#ifdef _WIN32 -#pragma once -#endif - -//----------------------------------------------------------------------------- -// Purpose: Renderer setup data. -//----------------------------------------------------------------------------- -class CViewSetupV1 -{ -public: - CViewSetupV1() - { - m_bForceAspectRatio1To1 = false; - m_bRenderToSubrectOfLargerScreen = false; - bForceClearWholeRenderTarget = false; - m_bUseRenderTargetAspectRatio = false; - } - -// shared by 2D & 3D views - - // User specified context - int context; - - // left side of view window - int x; - // top side of view window - int y; - // width of view window - int width; - // height of view window - int height; - - // clear the color buffer before rendering this view? - bool clearColor; - // clear the Depth buffer before rendering this view? - bool clearDepth; - // NOTE: This is for a workaround on ATI with building cubemaps. Clearing just the viewport doesn't seem to work properly. - bool bForceClearWholeRenderTarget; - -// the rest are only used by 3D views - - // Orthographic projection? - bool m_bOrtho; - // View-space rectangle for ortho projection. - float m_OrthoLeft; - float m_OrthoTop; - float m_OrthoRight; - float m_OrthoBottom; - - // horizontal FOV in degrees - float fov; - // horizontal FOV in degrees for in-view model - float fovViewmodel; - - // 3D origin of camera - Vector origin; - // Origin gets reflected on the water surface, but things like - // displacement LOD need to be calculated from the viewer's - // real position. - Vector m_vUnreflectedOrigin; - - // heading of camera (pitch, yaw, roll) - QAngle angles; - // local Z coordinate of near plane of camera - float zNear; - // local Z coordinate of far plane of camera - float zFar; - - // local Z coordinate of near plane of camera ( when rendering view model ) - float zNearViewmodel; - // local Z coordinate of far plane of camera ( when rendering view model ) - float zFarViewmodel; - - bool m_bForceAspectRatio1To1; - - // set to true if this is to draw into a subrect of the larger screen - // this really is a hack, but no more than the rest of the way this class is used - bool m_bRenderToSubrectOfLargerScreen; - - // Use this for situations like water where you want to render the aspect ratio of the - // back buffer into a square (or otherwise) render target. - bool m_bUseRenderTargetAspectRatio; -}; - -#endif // VIEW_SHAREDV1_H diff --git a/public/engine_hlds_api.h b/public/engine_hlds_api.h deleted file mode 100644 index 27a3dfa49..000000000 --- a/public/engine_hlds_api.h +++ /dev/null @@ -1,53 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ENGINE_HLDS_API_H -#define ENGINE_HLDS_API_H -#ifdef _WIN32 -#pragma once -#endif - -#include "interface.h" -#include "appframework/IAppSystem.h" - - -#define VENGINE_HLDS_API_VERSION "VENGINE_HLDS_API_VERSION002" - - -struct ModInfo_t -{ - void *m_pInstance; - const char *m_pBaseDirectory; // Executable directory ("c:/program files/half-life 2", for example) - const char *m_pInitialMod; // Mod name ("cstrike", for example) - const char *m_pInitialGame; // Root game name ("hl2", for example, in the case of cstrike) - CAppSystemGroup *m_pParentAppSystemGroup; - bool m_bTextMode; -}; - - -//----------------------------------------------------------------------------- -// Purpose: This is the interface exported by the engine.dll to allow a dedicated server front end -// application to host it. -//----------------------------------------------------------------------------- -class IDedicatedServerAPI : public IAppSystem -{ -// Functions -public: - // Initialize the engine with the specified base directory and interface factories - virtual bool ModInit( ModInfo_t &info ) = 0; - // Shutdown the engine - virtual void ModShutdown( void ) = 0; - // Run a frame - virtual bool RunFrame( void ) = 0; - // Insert text into console - virtual void AddConsoleText( char *text ) = 0; - // Get current status to display in the hlds UI (console window title bar, e.g. ) - virtual void UpdateStatus(float *fps, int *nActive, int *nMaxPlayers, char *pszMap, int maxlen ) = 0; - // Get current Hostname to display in the hlds UI (console window title bar, e.g. ) - virtual void UpdateHostname(char *pszHostname, int maxlen) = 0; -}; - -#endif // ENGINE_HLDS_API_H diff --git a/public/event_flags.h b/public/event_flags.h deleted file mode 100644 index 727fcd34e..000000000 --- a/public/event_flags.h +++ /dev/null @@ -1,28 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef EVENT_FLAGS_H -#define EVENT_FLAGS_H - -#ifdef _WIN32 -#pragma once -#endif - - -// Skip local host for event send. -#define FEV_NOTHOST (1<<0) - -// Send the event reliably. You must specify the origin and angles and use -// PLAYBACK_EVENT_FULL for this to work correctly on the server for anything -// that depends on the event origin/angles. I.e., the origin/angles are not -// taken from the invoking edict for reliable events. -#define FEV_RELIABLE (1<<1) - -// Don't restrict to PAS/PVS, send this event to _everybody_ on the server ( useful for stopping CHAN_STATIC -// sounds started by client event when client is not in PVS anymore ( hwguy in TFC e.g. ). -#define FEV_GLOBAL (1<<2) - -#endif // EVENT_FLAGS_H diff --git a/public/filesystem.h b/public/filesystem.h deleted file mode 100644 index 97c7f5782..000000000 --- a/public/filesystem.h +++ /dev/null @@ -1,860 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#include - -#include "tier0/threadtools.h" -#include "tier0/memalloc.h" -#include "tier1/interface.h" -#include "tier1/utlsymbol.h" -#include "tier1/utlstring.h" -#include "appframework/IAppSystem.h" -#include "tier1/checksum_crc.h" - -#ifndef FILESYSTEM_H -#define FILESYSTEM_H - -#ifdef _WIN32 -#pragma once -#endif - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- - -class CUtlBuffer; -class KeyValues; -class IFileList; - -typedef void * FileHandle_t; -typedef int FileFindHandle_t; -typedef void (*FileSystemLoggingFunc_t)( const char *fileName, const char *accessType ); -typedef int WaitForResourcesHandle_t; - -#ifdef _X360 -typedef void* HANDLE; -#endif - -//----------------------------------------------------------------------------- -// Enums used by the interface -//----------------------------------------------------------------------------- - -#define FILESYSTEM_MAX_SEARCH_PATHS 128 - -enum FileSystemSeek_t -{ - FILESYSTEM_SEEK_HEAD = SEEK_SET, - FILESYSTEM_SEEK_CURRENT = SEEK_CUR, - FILESYSTEM_SEEK_TAIL = SEEK_END, -}; - -enum -{ - FILESYSTEM_INVALID_FIND_HANDLE = -1 -}; - -enum FileWarningLevel_t -{ - // A problem! - FILESYSTEM_WARNING = -1, - - // Don't print anything - FILESYSTEM_WARNING_QUIET = 0, - - // On shutdown, report names of files left unclosed - FILESYSTEM_WARNING_REPORTUNCLOSED, - - // Report number of times a file was opened, closed - FILESYSTEM_WARNING_REPORTUSAGE, - - // Report all open/close events to console ( !slow! ) - FILESYSTEM_WARNING_REPORTALLACCESSES, - - // Report all open/close/read events to the console ( !slower! ) - FILESYSTEM_WARNING_REPORTALLACCESSES_READ, - - // Report all open/close/read/write events to the console ( !slower! ) - FILESYSTEM_WARNING_REPORTALLACCESSES_READWRITE, - - // Report all open/close/read/write events and all async I/O file events to the console ( !slower(est)! ) - FILESYSTEM_WARNING_REPORTALLACCESSES_ASYNC, - -}; - -// search path filtering -enum PathTypeFilter_t -{ - FILTER_NONE = 0, // no filtering, all search path types match - FILTER_CULLPACK = 1, // pack based search paths are culled (maps and zips) - FILTER_CULLNONPACK = 2, // non-pack based search paths are culled -}; - -// search path querying (bit flags) -enum -{ - PATH_IS_NORMAL = 0x00, // normal path, not pack based - PATH_IS_PACKFILE = 0x01, // path is a pack file - PATH_IS_MAPPACKFILE = 0x02, // path is a map pack file - PATH_IS_REMOTE = 0x04, // path is the remote filesystem -}; -typedef uint32 PathTypeQuery_t; - -#define IS_PACKFILE( n ) ( n & ( PATH_IS_PACKFILE | PATH_IS_MAPPACKFILE ) ) -#define IS_REMOTE( n ) ( n & PATH_IS_REMOTE ) - -enum DVDMode_t -{ - DVDMODE_OFF = 0, // not using dvd - DVDMODE_STRICT = 1, // dvd device only - DVDMODE_DEV = 2, // dev mode, mutiple devices ok -}; - -// In non-retail builds, enable the file blocking access tracking stuff... -#if defined( TRACK_BLOCKING_IO ) -enum FileBlockingWarning_t -{ - // Report how long synchronous i/o took to complete - FILESYSTEM_BLOCKING_SYNCHRONOUS = 0, - // Report how long async i/o took to complete if AsyncFileFinished caused it to load via "blocking" i/o - FILESYSTEM_BLOCKING_ASYNCHRONOUS_BLOCK, - // Report how long async i/o took to complete - FILESYSTEM_BLOCKING_ASYNCHRONOUS, - // Report how long the async "callback" took - FILESYSTEM_BLOCKING_CALLBACKTIMING, - - FILESYSTEM_BLOCKING_NUMBINS, -}; - -#pragma pack(1) -class FileBlockingItem -{ -public: - enum - { - FB_ACCESS_OPEN = 1, - FB_ACCESS_CLOSE = 2, - FB_ACCESS_READ = 3, - FB_ACCESS_WRITE = 4, - FB_ACCESS_APPEND = 5, - FB_ACCESS_SIZE = 6 - }; - - FileBlockingItem() : - m_ItemType( (FileBlockingWarning_t)0 ), - m_flElapsed( 0.0f ), - m_nAccessType( 0 ) - { - SetFileName( NULL ); - } - - FileBlockingItem( int type, char const *filename, float elapsed, int accessType ) : - m_ItemType( (FileBlockingWarning_t)type ), - m_flElapsed( elapsed ), - m_nAccessType( accessType ) - { - SetFileName( filename ); - } - - void SetFileName( char const *filename ) - { - if ( !filename ) - { - m_szFilename[ 0 ] = 0; - return; - } - - int len = Q_strlen( filename ); - if ( len >= sizeof( m_szFilename ) ) - { - Q_strncpy( m_szFilename, &filename[ len - sizeof( m_szFilename ) + 1 ], sizeof( m_szFilename ) ); - } - else - { - Q_strncpy( m_szFilename, filename, sizeof( m_szFilename ) ); - } - } - - char const *GetFileName() const - { - return m_szFilename; - } - - FileBlockingWarning_t m_ItemType; - float m_flElapsed; - byte m_nAccessType; -private: - - char m_szFilename[ 32 ]; -}; -#pragma pack() - -class IBlockingFileItemList -{ -public: - - // You can't call any of the below calls without locking first - virtual void LockMutex() = 0; - virtual void UnlockMutex() = 0; - - virtual int First() const = 0; - virtual int Next( int i ) const = 0; - virtual int InvalidIndex() const = 0; - - virtual const FileBlockingItem& Get( int index ) const = 0; - - virtual void Reset() = 0; -}; - -#endif // TRACK_BLOCKING_IO - -enum FilesystemMountRetval_t -{ - FILESYSTEM_MOUNT_OK = 0, - FILESYSTEM_MOUNT_FAILED, -}; - -enum SearchPathAdd_t -{ - PATH_ADD_TO_HEAD, // First path searched - PATH_ADD_TO_TAIL, // Last path searched -}; - -enum FilesystemOpenExFlags_t -{ - FSOPEN_UNBUFFERED = (1 << 0), - FSOPEN_FORCE_TRACK_CRC = (1 << 1), // This makes it calculate a CRC for the file (if the file came from disk) regardless - // of the IFileList passed to RegisterFileWhitelist. - FSOPEN_NEVERINPACK = (1 << 2), // 360 only, hint to FS that file is not allowed to be in pack file -}; - -#define FILESYSTEM_INVALID_HANDLE ( FileHandle_t )0 - -//----------------------------------------------------------------------------- -// Structures used by the interface -//----------------------------------------------------------------------------- - -struct FileSystemStatistics -{ - CInterlockedUInt nReads, - nWrites, - nBytesRead, - nBytesWritten, - nSeeks; -}; - -//----------------------------------------------------------------------------- -// File system allocation functions. Client must free on failure -//----------------------------------------------------------------------------- -typedef void *(*FSAllocFunc_t)( const char *pszFilename, unsigned nBytes ); - - -//----------------------------------------------------------------------------- -// Used to display dirty disk error functions -//----------------------------------------------------------------------------- -typedef void (*FSDirtyDiskReportFunc_t)(); - - -//----------------------------------------------------------------------------- -// Asynchronous support types -//----------------------------------------------------------------------------- -DECLARE_POINTER_HANDLE(FSAsyncControl_t); -DECLARE_POINTER_HANDLE(FSAsyncFile_t); -const FSAsyncFile_t FS_INVALID_ASYNC_FILE = (FSAsyncFile_t)(0x0000ffff); - - -//--------------------------------------------------------- -// Async file status -//--------------------------------------------------------- -enum FSAsyncStatus_t -{ - FSASYNC_ERR_ALIGNMENT = -6, // read parameters invalid for unbuffered IO - FSASYNC_ERR_FAILURE = -5, // hard subsystem failure - FSASYNC_ERR_READING = -4, // read error on file - FSASYNC_ERR_NOMEMORY = -3, // out of memory for file read - FSASYNC_ERR_UNKNOWNID = -2, // caller's provided id is not recognized - FSASYNC_ERR_FILEOPEN = -1, // filename could not be opened (bad path, not exist, etc) - FSASYNC_OK = 0, // operation is successful - FSASYNC_STATUS_PENDING, // file is properly queued, waiting for service - FSASYNC_STATUS_INPROGRESS, // file is being accessed - FSASYNC_STATUS_ABORTED, // file was aborted by caller - FSASYNC_STATUS_UNSERVICED, // file is not yet queued -}; - -//--------------------------------------------------------- -// Async request flags -//--------------------------------------------------------- -enum FSAsyncFlags_t -{ - FSASYNC_FLAGS_ALLOCNOFREE = ( 1 << 0 ), // do the allocation for dataPtr, but don't free - FSASYNC_FLAGS_FREEDATAPTR = ( 1 << 1 ), // free the memory for the dataPtr post callback - FSASYNC_FLAGS_SYNC = ( 1 << 2 ), // Actually perform the operation synchronously. Used to simplify client code paths - FSASYNC_FLAGS_NULLTERMINATE = ( 1 << 3 ), // allocate an extra byte and null terminate the buffer read in -}; - -//--------------------------------------------------------- -// Return value for CheckFileCRC. -//--------------------------------------------------------- -enum EFileCRCStatus -{ - k_eFileCRCStatus_CantOpenFile, // We don't have this file. - k_eFileCRCStatus_GotCRC, - k_eFileCRCStatus_FileInVPK -}; - -// Used in CacheFileCRCs. -enum ECacheCRCType -{ - k_eCacheCRCType_SingleFile, - k_eCacheCRCType_Directory, - k_eCacheCRCType_Directory_Recursive -}; - -//--------------------------------------------------------- -// Optional completion callback for each async file serviced (or failed) -// call is not reentrant, async i/o guaranteed suspended until return -// Note: If you change the signature of the callback, you will have to account for it in FileSystemV12 (toml [4/18/2005] ) -//--------------------------------------------------------- -struct FileAsyncRequest_t; -typedef void (*FSAsyncCallbackFunc_t)(const FileAsyncRequest_t &request, int nBytesRead, FSAsyncStatus_t err); - -//--------------------------------------------------------- -// Description of an async request -//--------------------------------------------------------- -struct FileAsyncRequest_t -{ - FileAsyncRequest_t() { memset( this, 0, sizeof(*this) ); hSpecificAsyncFile = FS_INVALID_ASYNC_FILE; } - const char * pszFilename; // file system name - void * pData; // optional, system will alloc/free if NULL - int nOffset; // optional initial seek_set, 0=beginning - int nBytes; // optional read clamp, -1=exist test, 0=full read - FSAsyncCallbackFunc_t pfnCallback; // optional completion callback - void * pContext; // caller's unique file identifier - int priority; // inter list priority, 0=lowest - unsigned flags; // behavior modifier - const char * pszPathID; // path ID (NOTE: this field is here to remain binary compatible with release HL2 filesystem interface) - FSAsyncFile_t hSpecificAsyncFile; // Optional hint obtained using AsyncBeginRead() - FSAllocFunc_t pfnAlloc; // custom allocator. can be null. not compatible with FSASYNC_FLAGS_FREEDATAPTR -}; - -struct MD5Value_t -{ - unsigned char bits[16]; -}; - -struct FileHash_t -{ - int m_eFileHashType; - CRC32_t m_crcIOSequence; - MD5Value_t m_md5contents; - int m_cbFileLen; - int m_PackFileID; - int m_nPackFileNumber; -}; - -class CUnverifiedFileHash -{ -public: - char m_PathID[MAX_PATH]; - char m_Filename[MAX_PATH]; - int m_nFileFraction; - FileHash_t m_FileHash; -}; - -class CUnverifiedCRCFile -{ -public: - char m_PathID[MAX_PATH]; - char m_Filename[MAX_PATH]; - CRC32_t m_CRC; -}; - -// Spew flags for SetWhitelistSpewFlags (set with the fs_whitelist_spew_flags cvar). -// Update the comment for the fs_whitelist_spew_flags cvar if you change these. -#define WHITELIST_SPEW_WHILE_LOADING 0x0001 // list files as they are added to the CRC tracker -#define WHITELIST_SPEW_RELOAD_FILES 0x0002 // show files the filesystem is telling the engine to reload -#define WHITELIST_SPEW_DONT_RELOAD_FILES 0x0004 // show files the filesystem is NOT telling the engine to reload - -abstract_class IPureServerWhitelist -{ -public: - virtual void AddRef() = 0; - virtual void Release() = 0; - virtual const char *GetFileClass( const char * ) = 0; - virtual int GetTrustedKeyCount() const = 0; - virtual void GetTrustedKey( int keyIndex, int *pBuffer ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Base file system interface -//----------------------------------------------------------------------------- - -// This is the minimal interface that can be implemented to provide access to -// a named set of files. -#define BASEFILESYSTEM_INTERFACE_VERSION "VBaseFileSystem011" - -abstract_class IBaseFileSystem -{ -public: - virtual int Read( void* pOutput, int size, FileHandle_t file ) = 0; - virtual int Write( void const* pInput, int size, FileHandle_t file ) = 0; - - // if pathID is NULL, all paths will be searched for the file - virtual FileHandle_t Open( const char *pFileName, const char *pOptions, const char *pathID = 0 ) = 0; - virtual void Close( FileHandle_t file ) = 0; - - - virtual void Seek( FileHandle_t file, int pos, FileSystemSeek_t seekType ) = 0; - virtual unsigned int Tell( FileHandle_t file ) = 0; - virtual unsigned int Size( FileHandle_t file ) = 0; - virtual unsigned int Size( const char *pFileName, const char *pPathID = 0 ) = 0; - - virtual void Flush( FileHandle_t file ) = 0; - virtual bool Precache( const char *pFileName, const char *pPathID = 0 ) = 0; - - virtual bool FileExists( const char *pFileName, const char *pPathID = 0 ) = 0; - virtual bool IsFileWritable( char const *pFileName, const char *pPathID = 0 ) = 0; - virtual bool SetFileWritable( char const *pFileName, bool writable, const char *pPathID = 0 ) = 0; - - virtual long GetFileTime( const char *pFileName, const char *pPathID = 0 ) = 0; - - //-------------------------------------------------------- - // Reads/writes files to utlbuffers. Use this for optimal read performance when doing open/read/close - //-------------------------------------------------------- - virtual bool ReadFile( const char *pFileName, const char *pPath, CUtlBuffer &buf, int nMaxBytes = 0, int nStartingByte = 0, FSAllocFunc_t pfnAlloc = NULL ) = 0; - virtual bool WriteFile( const char *pFileName, const char *pPath, CUtlBuffer &buf ) = 0; - virtual bool UnzipFile( const char *pFileName, const char *pPath, const char *pDestination ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Main file system interface -//----------------------------------------------------------------------------- - -#define FILESYSTEM_INTERFACE_VERSION "VFileSystem022" - -abstract_class IFileSystem : public IAppSystem, public IBaseFileSystem -{ -public: - //-------------------------------------------------------- - // Steam operations - //-------------------------------------------------------- - - virtual bool IsSteam() const = 0; - - // Supplying an extra app id will mount this app in addition - // to the one specified in the environment variable "steamappid" - // - // If nExtraAppId is < -1, then it will mount that app ID only. - // (Was needed by the dedicated server b/c the "SteamAppId" env var only gets passed to steam.dll - // at load time, so the dedicated couldn't pass it in that way). - virtual FilesystemMountRetval_t MountSteamContent( int nExtraAppId = -1 ) = 0; - - //-------------------------------------------------------- - // Search path manipulation - //-------------------------------------------------------- - - // Add paths in priority order (mod dir, game dir, ....) - // If one or more .pak files are in the specified directory, then they are - // added after the file system path - // If the path is the relative path to a .bsp file, then any previous .bsp file - // override is cleared and the current .bsp is searched for an embedded PAK file - // and this file becomes the highest priority search path ( i.e., it's looked at first - // even before the mod's file system path ). - virtual void AddSearchPath( const char *pPath, const char *pathID, SearchPathAdd_t addType = PATH_ADD_TO_TAIL ) = 0; - virtual bool RemoveSearchPath( const char *pPath, const char *pathID = 0 ) = 0; - - // Remove all search paths (including write path?) - virtual void RemoveAllSearchPaths( void ) = 0; - - // Remove search paths associated with a given pathID - virtual void RemoveSearchPaths( const char *szPathID ) = 0; - - // This is for optimization. If you mark a path ID as "by request only", then files inside it - // will only be accessed if the path ID is specifically requested. Otherwise, it will be ignored. - // If there are currently no search paths with the specified path ID, then it will still - // remember it in case you add search paths with this path ID. - virtual void MarkPathIDByRequestOnly( const char *pPathID, bool bRequestOnly ) = 0; - - // converts a partial path into a full path - virtual const char *RelativePathToFullPath( const char *pFileName, const char *pPathID, char *pLocalPath, int localPathBufferSize, PathTypeFilter_t pathFilter = FILTER_NONE, PathTypeQuery_t *pPathType = NULL ) = 0; - - // Returns the search path, each path is separated by ;s. Returns the length of the string returned - virtual int GetSearchPath( const char *pathID, bool bGetPackFiles, char *pPath, int nMaxLen ) = 0; - - // interface for custom pack files > 4Gb - virtual bool AddPackFile( const char *fullpath, const char *pathID ) = 0; - - //-------------------------------------------------------- - // File manipulation operations - //-------------------------------------------------------- - - // Deletes a file (on the WritePath) - virtual void RemoveFile( char const* pRelativePath, const char *pathID = 0 ) = 0; - - // Renames a file (on the WritePath) - virtual bool RenameFile( char const *pOldPath, char const *pNewPath, const char *pathID = 0 ) = 0; - - // create a local directory structure - virtual void CreateDirHierarchy( const char *path, const char *pathID = 0 ) = 0; - - // File I/O and info - virtual bool IsDirectory( const char *pFileName, const char *pathID = 0 ) = 0; - - virtual void FileTimeToString( char* pStrip, int maxCharsIncludingTerminator, long fileTime ) = 0; - - //-------------------------------------------------------- - // Open file operations - //-------------------------------------------------------- - - virtual void SetBufferSize( FileHandle_t file, unsigned nBytes ) = 0; - - virtual bool IsOk( FileHandle_t file ) = 0; - - virtual bool EndOfFile( FileHandle_t file ) = 0; - - virtual char *ReadLine( char *pOutput, int maxChars, FileHandle_t file ) = 0; - virtual int FPrintf( FileHandle_t file, const char *pFormat, ... ) = 0; - - //-------------------------------------------------------- - // Dynamic library operations - //-------------------------------------------------------- - - // load/unload modules - virtual CSysModule *LoadModule( const char *pFileName, const char *pPathID = 0, bool bValidatedDllOnly = true ) = 0; - virtual void UnloadModule( CSysModule *pModule ) = 0; - - //-------------------------------------------------------- - // File searching operations - //-------------------------------------------------------- - - // FindFirst/FindNext. Also see FindFirstEx. - virtual const char *FindFirst( const char *pWildCard, FileFindHandle_t *pHandle ) = 0; - virtual const char *FindNext( FileFindHandle_t handle ) = 0; - virtual bool FindIsDirectory( FileFindHandle_t handle ) = 0; - virtual void FindClose( FileFindHandle_t handle ) = 0; - - // Same as FindFirst, but you can filter by path ID, which can make it faster. - virtual const char *FindFirstEx( - const char *pWildCard, - const char *pPathID, - FileFindHandle_t *pHandle - ) = 0; - - //-------------------------------------------------------- - // File name and directory operations - //-------------------------------------------------------- - - // FIXME: This method is obsolete! Use RelativePathToFullPath instead! - // converts a partial path into a full path - virtual const char *GetLocalPath( const char *pFileName, char *pLocalPath, int localPathBufferSize ) = 0; - - // Returns true on success ( based on current list of search paths, otherwise false if - // it can't be resolved ) - virtual bool FullPathToRelativePath( const char *pFullpath, char *pRelative, int maxlen ) = 0; - -// Returns true on successfully retrieve case-sensitive full path, otherwise false - - virtual bool GetCaseCorrectFullPath_Ptr( const char *pFullPath, char *pDest, int maxLenInChars ) = 0; - - // Gets the current working directory - virtual bool GetCurrentDirectory( char* pDirectory, int maxlen ) = 0; - - //-------------------------------------------------------- - // Filename dictionary operations - //-------------------------------------------------------- - - virtual FileNameHandle_t FindOrAddFileName( char const *pFileName ) = 0; - virtual bool String( const FileNameHandle_t& handle, char *buf, int buflen ) = 0; - - //-------------------------------------------------------- - // Asynchronous file operations - //-------------------------------------------------------- - - //------------------------------------ - // Global operations - //------------------------------------ - FSAsyncStatus_t AsyncRead( const FileAsyncRequest_t &request, FSAsyncControl_t *phControl = NULL ) { return AsyncReadMultiple( &request, 1, phControl ); } - virtual FSAsyncStatus_t AsyncReadMultiple( const FileAsyncRequest_t *pRequests, int nRequests, FSAsyncControl_t *phControls = NULL ) = 0; - virtual FSAsyncStatus_t AsyncAppend(const char *pFileName, const void *pSrc, int nSrcBytes, bool bFreeMemory, FSAsyncControl_t *pControl = NULL ) = 0; - virtual FSAsyncStatus_t AsyncAppendFile(const char *pAppendToFileName, const char *pAppendFromFileName, FSAsyncControl_t *pControl = NULL ) = 0; - virtual void AsyncFinishAll( int iToPriority = 0 ) = 0; - virtual void AsyncFinishAllWrites() = 0; - virtual FSAsyncStatus_t AsyncFlush() = 0; - virtual bool AsyncSuspend() = 0; - virtual bool AsyncResume() = 0; - - // Next two functions each take an IAsyncFileFetch ptr. - virtual void AsyncAddFetcher( void *pFetch ) = 0; - virtual void AsyncRemoveFetcher( void *pFetch ) = 0; - - //------------------------------------ - // Functions to hold a file open if planning on doing mutiple reads. Use is optional, - // and is taken only as a hint - //------------------------------------ - virtual FSAsyncStatus_t AsyncBeginRead( const char *pszFile, FSAsyncFile_t *phFile ) = 0; - virtual FSAsyncStatus_t AsyncEndRead( FSAsyncFile_t hFile ) = 0; - - //------------------------------------ - // Request management - //------------------------------------ - virtual FSAsyncStatus_t AsyncFinish( FSAsyncControl_t hControl, bool wait = true ) = 0; - virtual FSAsyncStatus_t AsyncGetResult( FSAsyncControl_t hControl, void **ppData, int *pSize ) = 0; - virtual FSAsyncStatus_t AsyncAbort( FSAsyncControl_t hControl ) = 0; - virtual FSAsyncStatus_t AsyncStatus( FSAsyncControl_t hControl ) = 0; - // set a new priority for a file already in the queue - virtual FSAsyncStatus_t AsyncSetPriority(FSAsyncControl_t hControl, int newPriority) = 0; - virtual void AsyncAddRef( FSAsyncControl_t hControl ) = 0; - virtual void AsyncRelease( FSAsyncControl_t hControl ) = 0; - - //-------------------------------------------------------- - // Remote resource management - //-------------------------------------------------------- - - // starts waiting for resources to be available - // returns FILESYSTEM_INVALID_HANDLE if there is nothing to wait on - virtual WaitForResourcesHandle_t WaitForResources( const char *resourcelist ) = 0; - // get progress on waiting for resources; progress is a float [0, 1], complete is true on the waiting being done - // returns false if no progress is available - // any calls after complete is true or on an invalid handle will return false, 0.0f, true - virtual bool GetWaitForResourcesProgress( WaitForResourcesHandle_t handle, float *progress /* out */ , bool *complete /* out */ ) = 0; - // cancels a progress call - virtual void CancelWaitForResources( WaitForResourcesHandle_t handle ) = 0; - - // hints that a set of files will be loaded in near future - // HintResourceNeed() is not to be confused with resource precaching. - virtual int HintResourceNeed( const char *hintlist, int forgetEverything ) = 0; - // returns true if a file is on disk - virtual bool IsFileImmediatelyAvailable(const char *pFileName) = 0; - - // copies file out of pak/bsp/steam cache onto disk (to be accessible by third-party code) - virtual void GetLocalCopy( const char *pFileName ) = 0; - - //-------------------------------------------------------- - // Debugging operations - //-------------------------------------------------------- - - // Dump to printf/OutputDebugString the list of files that have not been closed - virtual void PrintOpenedFiles( void ) = 0; - virtual void PrintSearchPaths( void ) = 0; - - // output - virtual void SetWarningFunc( void (*pfnWarning)( const char *fmt, ... ) ) = 0; - virtual void SetWarningLevel( FileWarningLevel_t level ) = 0; - virtual void AddLoggingFunc( void (*pfnLogFunc)( const char *fileName, const char *accessType ) ) = 0; - virtual void RemoveLoggingFunc( FileSystemLoggingFunc_t logFunc ) = 0; - - // Returns the file system statistics retreived by the implementation. Returns NULL if not supported. - virtual const FileSystemStatistics *GetFilesystemStatistics() = 0; - - //-------------------------------------------------------- - // Start of new functions after Lost Coast release (7/05) - //-------------------------------------------------------- - - virtual FileHandle_t OpenEx( const char *pFileName, const char *pOptions, unsigned flags = 0, const char *pathID = 0, char **ppszResolvedFilename = NULL ) = 0; - - // Extended version of read provides more context to allow for more optimal reading - virtual int ReadEx( void* pOutput, int sizeDest, int size, FileHandle_t file ) = 0; - virtual int ReadFileEx( const char *pFileName, const char *pPath, void **ppBuf, bool bNullTerminate = false, bool bOptimalAlloc = false, int nMaxBytes = 0, int nStartingByte = 0, FSAllocFunc_t pfnAlloc = NULL ) = 0; - - virtual FileNameHandle_t FindFileName( char const *pFileName ) = 0; - -#if defined( TRACK_BLOCKING_IO ) - virtual void EnableBlockingFileAccessTracking( bool state ) = 0; - virtual bool IsBlockingFileAccessEnabled() const = 0; - - virtual IBlockingFileItemList *RetrieveBlockingFileAccessInfo() = 0; -#endif - - virtual void SetupPreloadData() = 0; - virtual void DiscardPreloadData() = 0; - - // Fixme, we could do these via a string embedded into the compiled data, etc... - enum KeyValuesPreloadType_t - { - TYPE_VMT, - TYPE_SOUNDEMITTER, - TYPE_SOUNDSCAPE, - NUM_PRELOAD_TYPES - }; - - virtual void LoadCompiledKeyValues( KeyValuesPreloadType_t type, char const *archiveFile ) = 0; - - // If the "PreloadedData" hasn't been purged, then this'll try and instance the KeyValues using the fast path of compiled keyvalues loaded during startup. - // Otherwise, it'll just fall through to the regular KeyValues loading routines - virtual KeyValues *LoadKeyValues( KeyValuesPreloadType_t type, char const *filename, char const *pPathID = 0 ) = 0; - virtual bool LoadKeyValues( KeyValues& head, KeyValuesPreloadType_t type, char const *filename, char const *pPathID = 0 ) = 0; - virtual bool ExtractRootKeyName( KeyValuesPreloadType_t type, char *outbuf, size_t bufsize, char const *filename, char const *pPathID = 0 ) = 0; - - virtual FSAsyncStatus_t AsyncWrite(const char *pFileName, const void *pSrc, int nSrcBytes, bool bFreeMemory, bool bAppend = false, FSAsyncControl_t *pControl = NULL ) = 0; - virtual FSAsyncStatus_t AsyncWriteFile(const char *pFileName, const CUtlBuffer *pSrc, int nSrcBytes, bool bFreeMemory, bool bAppend = false, FSAsyncControl_t *pControl = NULL ) = 0; - // Async read functions with memory blame - FSAsyncStatus_t AsyncReadCreditAlloc( const FileAsyncRequest_t &request, const char *pszFile, int line, FSAsyncControl_t *phControl = NULL ) { return AsyncReadMultipleCreditAlloc( &request, 1, pszFile, line, phControl ); } - virtual FSAsyncStatus_t AsyncReadMultipleCreditAlloc( const FileAsyncRequest_t *pRequests, int nRequests, const char *pszFile, int line, FSAsyncControl_t *phControls = NULL ) = 0; - - virtual bool GetFileTypeForFullPath( char const *pFullPath, wchar_t *buf, size_t bufSizeInBytes ) = 0; - - //-------------------------------------------------------- - //-------------------------------------------------------- - virtual bool ReadToBuffer( FileHandle_t hFile, CUtlBuffer &buf, int nMaxBytes = 0, FSAllocFunc_t pfnAlloc = NULL ) = 0; - - //-------------------------------------------------------- - // Optimal IO operations - //-------------------------------------------------------- - virtual bool GetOptimalIOConstraints( FileHandle_t hFile, unsigned *pOffsetAlign, unsigned *pSizeAlign, unsigned *pBufferAlign ) = 0; - inline unsigned GetOptimalReadSize( FileHandle_t hFile, unsigned nLogicalSize ); - virtual void *AllocOptimalReadBuffer( FileHandle_t hFile, unsigned nSize = 0, unsigned nOffset = 0 ) = 0; - virtual void FreeOptimalReadBuffer( void * ) = 0; - - //-------------------------------------------------------- - // - //-------------------------------------------------------- - virtual void BeginMapAccess() = 0; - virtual void EndMapAccess() = 0; - - // Returns true on success, otherwise false if it can't be resolved - virtual bool FullPathToRelativePathEx( const char *pFullpath, const char *pPathId, char *pRelative, int maxlen ) = 0; - - virtual int GetPathIndex( const FileNameHandle_t &handle ) = 0; - virtual long GetPathTime( const char *pPath, const char *pPathID ) = 0; - - virtual DVDMode_t GetDVDMode() = 0; - - //-------------------------------------------------------- - // Whitelisting for pure servers. - //-------------------------------------------------------- - - // This should be called ONCE at startup. Multiplayer games (gameinfo.txt does not contain singleplayer_only) - // want to enable this so sv_pure works. - virtual void EnableWhitelistFileTracking( bool bEnable, bool bCacheAllVPKHashes, bool bRecalculateAndCheckHashes ) = 0; - - // This is called when the client connects to a server using a pure_server_whitelist.txt file. - // - // Files listed in pWantCRCList will have CRCs calculated for them IF they come off disk - // (and those CRCs will come out of GetUnverifiedCRCFiles). - // - // Files listed in pAllowFromDiskList will be allowed to load from disk. All other files will - // be forced to come from Steam. - // - // The filesystem hangs onto the whitelists you pass in here, and it will Release() them when it closes down - // or when you call this function again. - // - // NOTE: The whitelists you pass in here will be accessed from multiple threads, so make sure the - // IsFileInList function is thread safe. - // - // If pFilesToReload is non-null, the filesystem will hand back a list of files that should be reloaded because they - // are now "dirty". For example, if you were on a non-pure server and you loaded a certain model, and then you connected - // to a pure server that said that model had to come from Steam, then pFilesToReload would specify that model - // and the engine should reload it so it can come from Steam. - // - // Be sure to call Release() on pFilesToReload. - virtual void RegisterFileWhitelist( IPureServerWhitelist *pPureList, IFileList **pFilesToReload ) = 0; - - // Called when the client logs onto a server. Any files that came off disk should be marked as - // unverified because this server may have a different set of files it wants to guarantee. - virtual void MarkAllCRCsUnverified() = 0; - - // As the server loads whitelists when it transitions maps, it calls this to calculate CRCs for any files marked - // with check_crc. Then it calls CheckCachedFileCRC later when it gets client requests to verify CRCs. - virtual void CacheFileCRCs( const char *pPathname, ECacheCRCType eType, IFileList *pFilter ) = 0; - virtual EFileCRCStatus CheckCachedFileHash( const char *pPathID, const char *pRelativeFilename, int nFileFraction, FileHash_t *pFileHash ) = 0; - - // Fills in the list of files that have been loaded off disk and have not been verified. - // Returns the number of files filled in (between 0 and nMaxFiles). - // - // This also removes any files it's returning from the unverified CRC list, so they won't be - // returned from here again. - // The client sends batches of these to the server to verify. - virtual int GetUnverifiedFileHashes( CUnverifiedFileHash *pFiles, int nMaxFiles ) = 0; - - // Control debug message output. - // Pass a combination of WHITELIST_SPEW_ flags. - virtual int GetWhitelistSpewFlags() = 0; - virtual void SetWhitelistSpewFlags( int flags ) = 0; - - // Installs a callback used to display a dirty disk dialog - virtual void InstallDirtyDiskReportFunc( FSDirtyDiskReportFunc_t func ) = 0; - - // This looks to return a "CFileCacheObject" object. - virtual void *CreateFileCache( void ) = 0; - - // Assuming that the first param in each of these is also a CFileCacheObject ptr. - virtual void AddFilesToFileCache( void *pFileCache, const char **, int size, const char * ) = 0; - virtual bool IsFileCacheFileLoaded( void *pFileCache, const char *szFile ) = 0; - virtual bool IsFileCacheLoaded( void *pFileCache ) = 0; - virtual void DestroyFileCache( void *pFileCache ) = 0; - - virtual bool RegisterMemoryFile( void *pFile, void **ppExistingFileWithRef ) = 0; - virtual void UnregisterMemoryFile( void *pFile ) = 0; - - virtual void CacheAllVPKFileHashes( bool bCacheAllVPKHashes, bool bRecalculateAndCheckHashes ) = 0; - virtual bool CheckVPKFileHash( int PackFileID, int nPackFileNumber, int nFileFraction, MD5Value_t &md5Value ) = 0; - - virtual void NotifyFileUnloaded( const char *pFileName, const char *pPathId ) = 0; -}; - -//----------------------------------------------------------------------------- - -#if defined( _X360 ) && !defined( _RETAIL ) -extern char g_szXboxProfileLastFileOpened[MAX_PATH]; -#define SetLastProfileFileRead( s ) Q_strncpy( g_szXboxProfileLastFileOpened, sizeof( g_szXboxProfileLastFileOpened), pFileName ) -#define GetLastProfileFileRead() (&g_szXboxProfileLastFileOpened[0]) -#else -#define SetLastProfileFileRead( s ) ((void)0) -#define GetLastProfileFileRead() NULL -#endif - -#if defined( _X360 ) && defined( _BASETSD_H_ ) -class CXboxDiskCacheSetter -{ -public: - CXboxDiskCacheSetter( SIZE_T newSize ) - { - m_oldSize = XGetFileCacheSize(); - XSetFileCacheSize( newSize ); - } - - ~CXboxDiskCacheSetter() - { - XSetFileCacheSize( m_oldSize ); - } -private: - SIZE_T m_oldSize; -}; -#define DISK_INTENSIVE() CXboxDiskCacheSetter cacheSetter( 1024*1024 ) -#else -#define DISK_INTENSIVE() ((void)0) -#endif - -//----------------------------------------------------------------------------- - -inline unsigned IFileSystem::GetOptimalReadSize( FileHandle_t hFile, unsigned nLogicalSize ) -{ - unsigned align; - if ( GetOptimalIOConstraints( hFile, &align, NULL, NULL ) ) - return AlignValue( nLogicalSize, align ); - else - return nLogicalSize; -} - -//----------------------------------------------------------------------------- - -// We include this here so it'll catch compile errors in VMPI early. -#include "filesystem_passthru.h" - -//----------------------------------------------------------------------------- -// Async memory tracking -//----------------------------------------------------------------------------- - -#if (defined(_DEBUG) || defined(USE_MEM_DEBUG)) -#define AsyncRead( a, b ) AsyncReadCreditAlloc( a, __FILE__, __LINE__, b ) -#define AsyncReadMutiple( a, b, c ) AsyncReadMultipleCreditAlloc( a, b, __FILE__, __LINE__, c ) -#endif - -extern IFileSystem *g_pFullFileSystem; - -#endif // FILESYSTEM_H diff --git a/public/filesystem/IQueuedLoader.h b/public/filesystem/IQueuedLoader.h deleted file mode 100644 index 762f4406a..000000000 --- a/public/filesystem/IQueuedLoader.h +++ /dev/null @@ -1,145 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#ifndef QUEUEDLOADER_H -#define QUEUEDLOADER_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/platform.h" -#include "appframework/IAppSystem.h" - -enum LoaderError_t -{ - LOADERERROR_NONE = 0, - LOADERERROR_FILEOPEN = -1, - LOADERERROR_READING = -2, -}; - -enum LoaderPriority_t -{ - LOADERPRIORITY_ANYTIME = 0, // low priority, job can finish during gameplay - LOADERPRIORITY_BEFOREPLAY = 1, // job must complete before load ends - LOADERPRIORITY_DURINGPRELOAD = 2, // job must be complete during preload phase -}; - -typedef void ( *QueuedLoaderCallback_t )( void *pContext, void *pContext2, const void *pData, int nSize, LoaderError_t loaderError ); - -struct LoaderJob_t -{ - LoaderJob_t() - { - memset( this, 0, sizeof( *this ) ); - } - - const char *m_pFilename; // path to resource - const char *m_pPathID; // optional, can be NULL - QueuedLoaderCallback_t m_pCallback; // called at i/o delivery - void *m_pContext; // caller provided data - void *m_pContext2; // caller provided data - void *m_pTargetData; // optional, caller provided target buffer - int m_nBytesToRead; // optional read clamp, otherwise 0 - unsigned int m_nStartOffset; // optional start offset, otherwise 0 - LoaderPriority_t m_Priority; // data must arrive by specified interval - bool m_bPersistTargetData; // caller wants ownership of i/o buffer -}; - -enum ResourcePreload_t -{ - RESOURCEPRELOAD_UNKNOWN, - RESOURCEPRELOAD_SOUND, - RESOURCEPRELOAD_MATERIAL, - RESOURCEPRELOAD_MODEL, - RESOURCEPRELOAD_CUBEMAP, - RESOURCEPRELOAD_STATICPROPLIGHTING, - RESOURCEPRELOAD_ANONYMOUS, - RESOURCEPRELOAD_COUNT -}; - -abstract_class IResourcePreload -{ -public: - // Called during preload phase for ALL the resources expected by the level. - // Caller should not do i/o but generate AddJob() requests. Resources that already exist - // and are not referenced by this function would be candidates for purge. - virtual bool CreateResource( const char *pName ) = 0; - - // Sent as an event hint during preload, that creation has completed, AddJob() i/o is about to commence. - // Caller should purge any unreferenced resources before the AddJobs are performed. - // "Must Complete" data will be guaranteed finished, at preload conclusion, before the normal load phase commences. - virtual void PurgeUnreferencedResources() = 0; - - // Sent as an event hint that gameplay rendering is imminent. - // Low priority jobs may still be in async flight. - virtual void OnEndMapLoading( bool bAbort ) = 0; - - virtual void PurgeAll() = 0; -}; - -// Default implementation -class CResourcePreload : public IResourcePreload -{ - void PurgeUnreferencedResources() {} - void OnEndMapLoading( bool bAbort ) {} - void PurgeAll() {} -}; - -// UI can install progress notification -abstract_class ILoaderProgress -{ -public: - // implementation must ignore UpdateProgress() if not scoped by Begin/End - virtual void BeginProgress() = 0; - virtual void EndProgress() = 0; - virtual void UpdateProgress( float progress ) = 0; -}; - -// spew detail -#define LOADER_DETAIL_NONE 0 -#define LOADER_DETAIL_TIMING (1<<0) -#define LOADER_DETAIL_COMPLETIONS (1<<1) -#define LOADER_DETAIL_LATECOMPLETIONS (1<<2) -#define LOADER_DETAIL_PURGES (1<<3) - -#define QUEUEDLOADER_INTERFACE_VERSION "QueuedLoaderVersion001" -abstract_class IQueuedLoader : public IAppSystem -{ -public: - virtual void InstallLoader( ResourcePreload_t type, IResourcePreload *pLoader ) = 0; - virtual void InstallProgress( ILoaderProgress *pProgress ) = 0; - - // Set bOptimizeReload if you want appropriate data (such as static prop lighting) - // to persist - rather than being purged and reloaded - when going from map A to map A. - virtual bool BeginMapLoading( const char *pMapName, bool bLoadForHDR, bool bOptimizeMapReload ) = 0; - virtual void EndMapLoading( bool bAbort ) = 0; - virtual bool AddJob( const LoaderJob_t *pLoaderJob ) = 0; - - // injects a resource into the map's reslist, rejected if not understood - virtual void AddMapResource( const char *pFilename ) = 0; - - // callback is asynchronous - virtual bool ClaimAnonymousJob( const char *pFilename, QueuedLoaderCallback_t pCallback, void *pContext, void *pContext2 = NULL ) = 0; - // provides data if loaded, caller owns data - virtual bool ClaimAnonymousJob( const char *pFilename, void **pData, int *pDataSize, LoaderError_t *pError = NULL ) = 0; - - virtual bool IsMapLoading() const = 0; - virtual bool IsSameMapLoading() const = 0; - virtual bool IsFinished() const = 0; - - // callers can expect that jobs are not immediately started when batching - virtual bool IsBatching() const = 0; - - // callers can conditionalize operational spew - virtual int GetSpewDetail() const = 0; - - virtual void PurgeAll() = 0; -}; - -extern IQueuedLoader *g_pQueuedLoader; - -#endif // QUEUEDLOADER_H diff --git a/public/filesystem_helpers.cpp b/public/filesystem_helpers.cpp deleted file mode 100644 index 67063abb8..000000000 --- a/public/filesystem_helpers.cpp +++ /dev/null @@ -1,137 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=====================================================================================// - -#include "filesystem.h" -#include "filesystem_helpers.h" -#include "characterset.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -// wordbreak parsing set -static characterset_t g_BreakSet, g_BreakSetIncludingColons; - -static void InitializeCharacterSets() -{ - static bool s_CharacterSetInitialized = false; - if (!s_CharacterSetInitialized) - { - CharacterSetBuild( &g_BreakSet, "{}()'" ); - CharacterSetBuild( &g_BreakSetIncludingColons, "{}()':" ); - s_CharacterSetInitialized = true; - } -} - - -const char* ParseFile( const char* pFileBytes, char* pToken, bool* pWasQuoted, characterset_t *pCharSet ) -{ - if (pWasQuoted) - *pWasQuoted = false; - - if (!pFileBytes) - return 0; - - InitializeCharacterSets(); - - // YWB: Ignore colons as token separators in COM_Parse - static bool com_ignorecolons = false; - characterset_t& breaks = pCharSet ? *pCharSet : (com_ignorecolons ? g_BreakSet : g_BreakSetIncludingColons); - - int c; - int len = 0; - pToken[0] = 0; - -// skip whitespace -skipwhite: - - while ( (c = *pFileBytes) <= ' ') - { - if (c == 0) - return 0; // end of file; - pFileBytes++; - } - -// skip // comments - if (c=='/' && pFileBytes[1] == '/') - { - while (*pFileBytes && *pFileBytes != '\n') - pFileBytes++; - goto skipwhite; - } - -// skip c-style comments - if (c=='/' && pFileBytes[1] == '*' ) - { - // Skip "/*" - pFileBytes += 2; - - while ( *pFileBytes ) - { - if ( *pFileBytes == '*' && - pFileBytes[1] == '/' ) - { - pFileBytes += 2; - break; - } - - pFileBytes++; - } - - goto skipwhite; - } - -// handle quoted strings specially - if (c == '\"') - { - if (pWasQuoted) - *pWasQuoted = true; - - pFileBytes++; - while (1) - { - c = *pFileBytes++; - if (c=='\"' || !c) - { - pToken[len] = 0; - return pFileBytes; - } - pToken[len] = c; - len++; - } - } - -// parse single characters - if ( IN_CHARACTERSET( breaks, c ) ) - { - pToken[len] = c; - len++; - pToken[len] = 0; - return pFileBytes+1; - } - -// parse a regular word - do - { - pToken[len] = c; - pFileBytes++; - len++; - c = *pFileBytes; - if ( IN_CHARACTERSET( breaks, c ) ) - break; - } while (c>32); - - pToken[len] = 0; - return pFileBytes; -} - - -char* ParseFile( char* pFileBytes, char* pToken, bool* pWasQuoted ) -{ - return (char*)ParseFile( (const char*)pFileBytes, pToken, pWasQuoted ); -} - - - diff --git a/public/filesystem_helpers.h b/public/filesystem_helpers.h deleted file mode 100644 index f2637cf98..000000000 --- a/public/filesystem_helpers.h +++ /dev/null @@ -1,22 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef FILESYSTEM_HELPERS_H -#define FILESYSTEM_HELPERS_H - -#ifdef _WIN32 -#pragma once -#endif - - -// Call until it returns NULL. Each time you call it, it will parse out a token. -struct characterset_t; -const char* ParseFile( const char* pFileBytes, char* pToken, bool* pWasQuoted, characterset_t *pCharSet = NULL ); -char* ParseFile( char* pFileBytes, char* pToken, bool* pWasQuoted ); // (same exact thing as the const version) - - -#endif // FILESYSTEM_HELPERS_H diff --git a/public/filesystem_init.cpp b/public/filesystem_init.cpp deleted file mode 100644 index e9efc2a44..000000000 --- a/public/filesystem_init.cpp +++ /dev/null @@ -1,1358 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#undef PROTECTED_THINGS_ENABLE -#undef PROTECT_FILEIO_FUNCTIONS - -#if defined( _WIN32 ) && !defined( _X360 ) -#include -#include -#include -#include -#elif defined( _LINUX ) || defined( __APPLE__ ) -#include -#define _putenv putenv -#define _chdir chdir -#define _access access -#endif -#include -#include -#include "tier1/strtools.h" -#include "filesystem_init.h" -#include "tier0/icommandline.h" -#include "KeyValues.h" -#include "appframework/IAppSystemGroup.h" -#include "tier1/smartptr.h" -#if defined( _X360 ) -#include "xbox\xbox_win32stubs.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include - -#if !defined( _X360 ) -#define GAMEINFO_FILENAME "gameinfo.txt" -#else -// The .xtx file is a TCR requirement, as .txt files cannot live on the DVD. -// The .xtx file only exists outside the zips (same as .txt and is made during the image build) and is read to setup the search paths. -// So all other code should be able to safely expect gameinfo.txt after the zip is mounted as the .txt file exists inside the zips. -// The .xtx concept is private and should only have to occurr here. As a safety measure, if the .xtx file is not found -// a retry is made with the original .txt name -#define GAMEINFO_FILENAME "gameinfo.xtx" -#endif -#define GAMEINFO_FILENAME_ALTERNATE "gameinfo.txt" - -static char g_FileSystemError[256]; -static bool s_bUseVProjectBinDir = false; -static FSErrorMode_t g_FileSystemErrorMode = FS_ERRORMODE_VCONFIG; - -// Call this to use a bin directory relative to VPROJECT -void FileSystem_UseVProjectBinDir( bool bEnable ) -{ - s_bUseVProjectBinDir = bEnable; -} - -// This class lets you modify environment variables, and it restores the original value -// when it goes out of scope. -class CTempEnvVar -{ -public: - CTempEnvVar( const char *pVarName ) - { - m_bRestoreOriginalValue = true; - m_pVarName = pVarName; - - const char *pValue = NULL; - -#ifdef _WIN32 - // Use GetEnvironmentVariable instead of getenv because getenv doesn't pick up changes - // to the process environment after the DLL was loaded. - char szBuf[ 4096 ]; - if ( GetEnvironmentVariable( m_pVarName, szBuf, sizeof( szBuf ) ) != 0) - { - pValue = szBuf; - } -#else - // LINUX BUG: see above - pValue = getenv( pVarName ); -#endif - - if ( pValue ) - { - m_bExisted = true; - m_OriginalValue.SetSize( strlen( pValue ) + 1 ); - memcpy( m_OriginalValue.Base(), pValue, m_OriginalValue.Count() ); - } - else - { - m_bExisted = false; - } - } - - ~CTempEnvVar() - { - if ( m_bRestoreOriginalValue ) - { - // Restore the original value. - if ( m_bExisted ) - { - SetValue( "%s", m_OriginalValue.Base() ); - } - else - { - ClearValue(); - } - } - } - - void SetRestoreOriginalValue( bool bRestore ) - { - m_bRestoreOriginalValue = bRestore; - } - - int GetValue(char *pszBuf, int nBufSize ) - { - if ( !pszBuf || ( nBufSize <= 0 ) ) - return 0; - -#ifdef _WIN32 - // Use GetEnvironmentVariable instead of getenv because getenv doesn't pick up changes - // to the process environment after the DLL was loaded. - return GetEnvironmentVariable( m_pVarName, pszBuf, nBufSize ); -#else - // LINUX BUG: see above - const char *pszOut = getenv( m_pVarName ); - if ( !pszOut ) - { - *pszBuf = '\0'; - return 0; - } - - Q_strncpy( pszBuf, pszOut, nBufSize ); - return Q_strlen( pszBuf ); -#endif - } - - void SetValue( const char *pValue, ... ) - { - char valueString[4096]; - va_list marker; - va_start( marker, pValue ); - Q_vsnprintf( valueString, sizeof( valueString ), pValue, marker ); - va_end( marker ); - - char str[4096]; - Q_snprintf( str, sizeof( str ), "%s=%s", m_pVarName, valueString ); - _putenv( str ); - } - - void ClearValue() - { - char str[512]; - Q_snprintf( str, sizeof( str ), "%s=", m_pVarName ); - _putenv( str ); - } - -private: - bool m_bRestoreOriginalValue; - const char *m_pVarName; - bool m_bExisted; - CUtlVector m_OriginalValue; -}; - - -class CSteamEnvVars -{ -public: - CSteamEnvVars() : - m_SteamAppId( "SteamAppId" ), - m_SteamUserPassphrase( "SteamUserPassphrase" ), - m_SteamAppUser( "SteamAppUser" ), - m_Path( "path" ) - { - } - - void SetRestoreOriginalValue_ALL( bool bRestore ) - { - m_SteamAppId.SetRestoreOriginalValue( bRestore ); - m_SteamUserPassphrase.SetRestoreOriginalValue( bRestore ); - m_SteamAppUser.SetRestoreOriginalValue( bRestore ); - m_Path.SetRestoreOriginalValue( bRestore ); - } - - CTempEnvVar m_SteamAppId; - CTempEnvVar m_SteamUserPassphrase; - CTempEnvVar m_SteamAppUser; - CTempEnvVar m_Path; -}; - -// ---------------------------------------------------------------------------------------------------- // -// Helpers. -// ---------------------------------------------------------------------------------------------------- // -void Q_getwd( char *out, int outSize ) -{ -#if defined( _WIN32 ) || defined( WIN32 ) - _getcwd( out, outSize ); - Q_strncat( out, "\\", outSize, COPY_ALL_CHARACTERS ); -#else - getcwd( out, outSize ); - strcat( out, "/" ); -#endif - Q_FixSlashes( out ); -} - -// ---------------------------------------------------------------------------------------------------- // -// Module interface. -// ---------------------------------------------------------------------------------------------------- // - -CFSSearchPathsInit::CFSSearchPathsInit() -{ - m_pDirectoryName = NULL; - m_pLanguage = NULL; - m_ModPath[0] = 0; -} - - -CFSSteamSetupInfo::CFSSteamSetupInfo() -{ - m_pDirectoryName = NULL; - m_bOnlyUseDirectoryName = false; - m_bSteam = false; - m_bToolsMode = true; - m_bNoGameInfo = false; -} - - -CFSLoadModuleInfo::CFSLoadModuleInfo() -{ - m_pFileSystemDLLName = NULL; - m_pFileSystem = NULL; - m_pModule = NULL; -} - - -CFSMountContentInfo::CFSMountContentInfo() -{ - m_bToolsMode = true; - m_pDirectoryName = NULL; - m_pFileSystem = NULL; -} - - -const char *FileSystem_GetLastErrorString() -{ - return g_FileSystemError; -} - - -void AddLanguageGameDir( IFileSystem *pFileSystem, const char *pLocation, const char *pLanguage ) -{ - if ( IsX360() ) - { - // 360 does not use this path for localization - return; - } - -#if !defined( SWDS ) - char temp[MAX_PATH]; - Q_snprintf( temp, sizeof(temp), "%s_%s", pLocation, pLanguage ); - pFileSystem->AddSearchPath( temp, "GAME", PATH_ADD_TO_TAIL ); - - if ( !pFileSystem->IsSteam() ) - { - // also look in "..\localization\" if not running Steam - char baseDir[MAX_PATH]; - char *tempPtr = NULL, *gameDir = NULL; - - Q_strncpy( baseDir, pLocation, sizeof(baseDir) ); - tempPtr = Q_strstr( baseDir, "\\game\\" ); - - if ( tempPtr ) - { - gameDir = tempPtr + Q_strlen( "\\game\\" ); - *tempPtr = 0; - Q_snprintf( temp, sizeof(temp), "%s%clocalization%c%s_%s", baseDir, CORRECT_PATH_SEPARATOR, CORRECT_PATH_SEPARATOR, gameDir, pLanguage ); - pFileSystem->AddSearchPath( temp, "GAME", PATH_ADD_TO_TAIL ); - } - } -#endif -} - - -void AddGameBinDir( IFileSystem *pFileSystem, const char *pLocation ) -{ - char temp[MAX_PATH]; - Q_snprintf( temp, sizeof(temp), "%s%cbin", pLocation, CORRECT_PATH_SEPARATOR ); - pFileSystem->AddSearchPath( temp, "GAMEBIN", PATH_ADD_TO_TAIL ); -} - -KeyValues* ReadKeyValuesFile( const char *pFilename ) -{ - // Read in the gameinfo.txt file and null-terminate it. - FILE *fp = fopen( pFilename, "rb" ); - if ( !fp ) - return NULL; - CUtlVector buf; - fseek( fp, 0, SEEK_END ); - buf.SetSize( ftell( fp ) + 1 ); - fseek( fp, 0, SEEK_SET ); - fread( buf.Base(), 1, buf.Count()-1, fp ); - fclose( fp ); - buf[buf.Count()-1] = 0; - - KeyValues *kv = new KeyValues( "" ); - if ( !kv->LoadFromBuffer( pFilename, buf.Base() ) ) - { - kv->deleteThis(); - return NULL; - } - - return kv; -} - -static bool Sys_GetExecutableName( char *out, int len ) -{ -#if defined( _WIN32 ) - if ( !::GetModuleFileName( ( HINSTANCE )GetModuleHandle( NULL ), out, len ) ) - { - return false; - } -#else - if ( CommandLine()->GetParm(0) ) - { - Q_MakeAbsolutePath( out, len, CommandLine()->GetParm(0) ); - } - else - { - return false; - } -#endif - - return true; -} - -bool FileSystem_GetExecutableDir( char *exedir, int exeDirLen ) -{ - exedir[0] = 0; - - if ( s_bUseVProjectBinDir ) - { - const char *pProject = GetVProjectCmdLineValue(); - if ( !pProject ) - { - // Check their registry. - pProject = getenv( GAMEDIR_TOKEN ); - } - if ( pProject ) - { - Q_snprintf( exedir, exeDirLen, "%s%c..%cbin", pProject, CORRECT_PATH_SEPARATOR, CORRECT_PATH_SEPARATOR ); - return true; - } - return false; - } - - if ( !Sys_GetExecutableName( exedir, exeDirLen ) ) - return false; - Q_StripFilename( exedir ); - - if ( IsX360() ) - { - // The 360 can have its exe and dlls reside on different volumes - // use the optional basedir as the exe dir - if ( CommandLine()->FindParm( "-basedir" ) ) - { - strcpy( exedir, CommandLine()->ParmValue( "-basedir", "" ) ); - } - } - - Q_FixSlashes( exedir ); - - // Return the bin directory as the executable dir if it's not in there - // because that's really where we're running from... - char ext[MAX_PATH]; - Q_StrRight( exedir, 4, ext, sizeof( ext ) ); - if ( ext[0] != CORRECT_PATH_SEPARATOR || Q_stricmp( ext+1, "bin" ) != 0 ) - { - Q_strncat( exedir, "\\bin", exeDirLen, COPY_ALL_CHARACTERS ); - Q_FixSlashes( exedir ); - } - - return true; -} - -static bool FileSystem_GetBaseDir( char *baseDir, int baseDirLen ) -{ - if ( FileSystem_GetExecutableDir( baseDir, baseDirLen ) ) - { - Q_StripFilename( baseDir ); - return true; - } - - return false; -} - -void LaunchVConfig() -{ -#if defined( _WIN32 ) && !defined( _X360 ) - char vconfigExe[MAX_PATH]; - FileSystem_GetExecutableDir( vconfigExe, sizeof( vconfigExe ) ); - Q_AppendSlash( vconfigExe, sizeof( vconfigExe ) ); - Q_strncat( vconfigExe, "vconfig.exe", sizeof( vconfigExe ), COPY_ALL_CHARACTERS ); - - char *argv[] = - { - vconfigExe, - "-allowdebug", - NULL - }; - - _spawnv( _P_NOWAIT, vconfigExe, argv ); -#elif defined( _X360 ) - Msg( "Launching vconfig.exe not supported\n" ); -#endif -} - -const char* GetVProjectCmdLineValue() -{ - return CommandLine()->ParmValue( "-vproject", CommandLine()->ParmValue( "-game" ) ); -} - -FSReturnCode_t SetupFileSystemError( bool bRunVConfig, FSReturnCode_t retVal, const char *pMsg, ... ) -{ - va_list marker; - va_start( marker, pMsg ); - Q_vsnprintf( g_FileSystemError, sizeof( g_FileSystemError ), pMsg, marker ); - va_end( marker ); - - Warning( "%s\n", g_FileSystemError ); - - // Run vconfig? - // Don't do it if they specifically asked for it not to, or if they manually specified a vconfig with -game or -vproject. - if ( bRunVConfig && g_FileSystemErrorMode == FS_ERRORMODE_VCONFIG && !CommandLine()->FindParm( CMDLINEOPTION_NOVCONFIG ) && !GetVProjectCmdLineValue() ) - { - LaunchVConfig(); - } - - if ( g_FileSystemErrorMode == FS_ERRORMODE_AUTO || g_FileSystemErrorMode == FS_ERRORMODE_VCONFIG ) - { - Error( "%s\n", g_FileSystemError ); - } - - return retVal; -} - -FSReturnCode_t LoadGameInfoFile( - const char *pDirectoryName, - KeyValues *&pMainFile, - KeyValues *&pFileSystemInfo, - KeyValues *&pSearchPaths ) -{ - // If GameInfo.txt exists under pBaseDir, then this is their game directory. - // All the filesystem mappings will be in this file. - char gameinfoFilename[MAX_PATH]; - Q_strncpy( gameinfoFilename, pDirectoryName, sizeof( gameinfoFilename ) ); - Q_AppendSlash( gameinfoFilename, sizeof( gameinfoFilename ) ); - Q_strncat( gameinfoFilename, GAMEINFO_FILENAME, sizeof( gameinfoFilename ), COPY_ALL_CHARACTERS ); - Q_FixSlashes( gameinfoFilename ); - pMainFile = ReadKeyValuesFile( gameinfoFilename ); - if ( IsX360() && !pMainFile ) - { - // try again - Q_strncpy( gameinfoFilename, pDirectoryName, sizeof( gameinfoFilename ) ); - Q_AppendSlash( gameinfoFilename, sizeof( gameinfoFilename ) ); - Q_strncat( gameinfoFilename, GAMEINFO_FILENAME_ALTERNATE, sizeof( gameinfoFilename ), COPY_ALL_CHARACTERS ); - Q_FixSlashes( gameinfoFilename ); - pMainFile = ReadKeyValuesFile( gameinfoFilename ); - } - if ( !pMainFile ) - { - return SetupFileSystemError( true, FS_MISSING_GAMEINFO_FILE, "%s is missing.", gameinfoFilename ); - } - - pFileSystemInfo = pMainFile->FindKey( "FileSystem" ); - if ( !pFileSystemInfo ) - { - pMainFile->deleteThis(); - return SetupFileSystemError( true, FS_INVALID_GAMEINFO_FILE, "%s is not a valid format.", gameinfoFilename ); - } - - // Now read in all the search paths. - pSearchPaths = pFileSystemInfo->FindKey( "SearchPaths" ); - if ( !pSearchPaths ) - { - pMainFile->deleteThis(); - return SetupFileSystemError( true, FS_INVALID_GAMEINFO_FILE, "%s is not a valid format.", gameinfoFilename ); - } - return FS_OK; -} - -// checks the registry for the low violence setting -// Check "HKEY_CURRENT_USER\Software\Valve\Source\Settings" and "User Token 2" or "User Token 3" -bool IsLowViolenceBuild( void ) -{ -#if defined(_WIN32) - HKEY hKey; - char szValue[64]; - unsigned long len = sizeof(szValue) - 1; - bool retVal = false; - - if ( IsPC() && RegOpenKeyEx( HKEY_CURRENT_USER, "Software\\Valve\\Source\\Settings", NULL, KEY_READ, &hKey) == ERROR_SUCCESS ) - { - // User Token 2 - if ( RegQueryValueEx( hKey, "User Token 2", NULL, NULL, (unsigned char*)szValue, &len ) == ERROR_SUCCESS ) - { - if ( Q_strlen( szValue ) > 0 ) - { - retVal = true; - } - } - - if ( !retVal ) - { - // reset "len" for the next check - len = sizeof(szValue) - 1; - - // User Token 3 - if ( RegQueryValueEx( hKey, "User Token 3", NULL, NULL, (unsigned char*)szValue, &len ) == ERROR_SUCCESS ) - { - if ( Q_strlen( szValue ) > 0 ) - { - retVal = true; - } - } - } - - RegCloseKey(hKey); - } - - return retVal; -#elif _LINUX - return false; -#else - #error "Fix me" -#endif -} - -static void FileSystem_AddLoadedSearchPath( - CFSSearchPathsInit &initInfo, - const char *pPathID, - bool *bFirstGamePath, - const char *pBaseDir, - const char *pLocation, - bool bLowViolence ) -{ - char fullLocationPath[MAX_PATH]; - Q_MakeAbsolutePath( fullLocationPath, sizeof( fullLocationPath ), pLocation, pBaseDir ); - - // Now resolve any ./'s. - V_FixSlashes( fullLocationPath ); - if ( !V_RemoveDotSlashes( fullLocationPath ) ) - Error( "FileSystem_AddLoadedSearchPath - Can't resolve pathname for '%s'", fullLocationPath ); - - // Add language, mod, and gamebin search paths automatically. - if ( Q_stricmp( pPathID, "game" ) == 0 ) - { - // add the low violence path - if ( bLowViolence ) - { - char szPath[MAX_PATH]; - Q_snprintf( szPath, sizeof(szPath), "%s_lv", fullLocationPath ); - initInfo.m_pFileSystem->AddSearchPath( szPath, pPathID, PATH_ADD_TO_TAIL ); - } - - // add the language path - if ( initInfo.m_pLanguage ) - { - AddLanguageGameDir( initInfo.m_pFileSystem, fullLocationPath, initInfo.m_pLanguage ); - } - - if ( CommandLine()->FindParm( "-tempcontent" ) != 0 ) - { - char szPath[MAX_PATH]; - Q_snprintf( szPath, sizeof(szPath), "%s_tempcontent", fullLocationPath ); - initInfo.m_pFileSystem->AddSearchPath( szPath, pPathID, PATH_ADD_TO_TAIL ); - } - - // mark the first "game" dir as the "MOD" dir - if ( *bFirstGamePath ) - { - *bFirstGamePath = false; - initInfo.m_pFileSystem->AddSearchPath( fullLocationPath, "MOD", PATH_ADD_TO_TAIL ); - Q_strncpy( initInfo.m_ModPath, fullLocationPath, sizeof( initInfo.m_ModPath ) ); - } - - // add the game bin - AddGameBinDir( initInfo.m_pFileSystem, fullLocationPath ); - } - - initInfo.m_pFileSystem->AddSearchPath( fullLocationPath, pPathID, PATH_ADD_TO_TAIL ); -} - - -bool FileSystem_IsHldsUpdateToolDedicatedServer() -{ - // To determine this, we see if the directory our executable was launched from is "orangebox". - // We only are under "orangebox" if we're run from hldsupdatetool. - char baseDir[MAX_PATH]; - if ( !FileSystem_GetBaseDir( baseDir, sizeof( baseDir ) ) ) - return false; - - V_FixSlashes( baseDir ); - V_StripTrailingSlash( baseDir ); - const char *pLastDir = V_UnqualifiedFileName( baseDir ); - return ( pLastDir && V_stricmp( pLastDir, "orangebox" ) == 0 ); -} - - -FSReturnCode_t FileSystem_LoadSearchPaths( CFSSearchPathsInit &initInfo ) -{ - if ( !initInfo.m_pFileSystem || !initInfo.m_pDirectoryName ) - return SetupFileSystemError( false, FS_INVALID_PARAMETERS, "FileSystem_LoadSearchPaths: Invalid parameters specified." ); - - KeyValues *pMainFile, *pFileSystemInfo, *pSearchPaths; - FSReturnCode_t retVal = LoadGameInfoFile( initInfo.m_pDirectoryName, pMainFile, pFileSystemInfo, pSearchPaths ); - if ( retVal != FS_OK ) - return retVal; - - // All paths except those marked with |gameinfo_path| are relative to the base dir. - char baseDir[MAX_PATH]; - if ( !FileSystem_GetBaseDir( baseDir, sizeof( baseDir ) ) ) - return SetupFileSystemError( false, FS_INVALID_PARAMETERS, "FileSystem_GetBaseDir failed." ); - - initInfo.m_ModPath[0] = 0; - - #define GAMEINFOPATH_TOKEN "|gameinfo_path|" - #define BASESOURCEPATHS_TOKEN "|all_source_engine_paths|" - - bool bLowViolence = IsLowViolenceBuild(); - bool bFirstGamePath = true; - - for ( KeyValues *pCur=pSearchPaths->GetFirstValue(); pCur; pCur=pCur->GetNextValue() ) - { - const char *pPathID = pCur->GetName(); - const char *pLocation = pCur->GetString(); - - if ( Q_stristr( pLocation, GAMEINFOPATH_TOKEN ) == pLocation ) - { - pLocation += strlen( GAMEINFOPATH_TOKEN ); - FileSystem_AddLoadedSearchPath( initInfo, pPathID, &bFirstGamePath, initInfo.m_pDirectoryName, pLocation, bLowViolence ); - } - else if ( Q_stristr( pLocation, BASESOURCEPATHS_TOKEN ) == pLocation ) - { - // This is a special identifier that tells it to add the specified path for all source engine versions equal to or prior to this version. - // So in Orange Box, if they specified: - // |all_source_engine_paths|hl2 - // it would add the ep2\hl2 folder and the base (ep1-era) hl2 folder. - // - // We need a special identifier in the gameinfo.txt here because the base hl2 folder exists in different places. - // In the case of a game or a Steam-launched dedicated server, all the necessary prior engine content is mapped in with the Steam depots, - // so we can just use the path as-is. - - // In the case of an hldsupdatetool dedicated server, the base hl2 folder is "..\..\hl2" (since we're up in the 'orangebox' folder). - - pLocation += strlen( BASESOURCEPATHS_TOKEN ); - - // Add the Orange-box path (which also will include whatever the depots mapped in as well if we're - // running a Steam-launched app). - FileSystem_AddLoadedSearchPath( initInfo, pPathID, &bFirstGamePath, baseDir, pLocation, bLowViolence ); - - if ( FileSystem_IsHldsUpdateToolDedicatedServer() ) - { - // If we're using the hldsupdatetool dedicated server, then go up a directory to get the ep1-era files too. - char ep1EraPath[MAX_PATH]; - V_snprintf( ep1EraPath, sizeof( ep1EraPath ), "..%c%s", CORRECT_PATH_SEPARATOR, pLocation ); - FileSystem_AddLoadedSearchPath( initInfo, pPathID, &bFirstGamePath, baseDir, ep1EraPath, bLowViolence ); - } - } - else - { - FileSystem_AddLoadedSearchPath( initInfo, pPathID, &bFirstGamePath, baseDir, pLocation, bLowViolence ); - } - } - - pMainFile->deleteThis(); - - // Also, mark specific path IDs as "by request only". That way, we won't waste time searching in them - // when people forget to specify a search path. - initInfo.m_pFileSystem->MarkPathIDByRequestOnly( "executable_path", true ); - initInfo.m_pFileSystem->MarkPathIDByRequestOnly( "gamebin", true ); - initInfo.m_pFileSystem->MarkPathIDByRequestOnly( "mod", true ); - if ( initInfo.m_ModPath[0] != 0 ) - { - // Add the write path last. - initInfo.m_pFileSystem->AddSearchPath( initInfo.m_ModPath, "DEFAULT_WRITE_PATH", PATH_ADD_TO_TAIL ); - } - -#ifdef _DEBUG - initInfo.m_pFileSystem->PrintSearchPaths(); -#endif - - return FS_OK; -} - -bool DoesFileExistIn( const char *pDirectoryName, const char *pFilename ) -{ - char filename[MAX_PATH]; - - Q_strncpy( filename, pDirectoryName, sizeof( filename ) ); - Q_AppendSlash( filename, sizeof( filename ) ); - Q_strncat( filename, pFilename, sizeof( filename ), COPY_ALL_CHARACTERS ); - Q_FixSlashes( filename ); - bool bExist = ( _access( filename, 0 ) == 0 ); - - return ( bExist ); -} - -namespace -{ - SuggestGameInfoDirFn_t & GetSuggestGameInfoDirFn( void ) - { - static SuggestGameInfoDirFn_t s_pfnSuggestGameInfoDir = NULL; - return s_pfnSuggestGameInfoDir; - } -}; // `anonymous` namespace - -SuggestGameInfoDirFn_t SetSuggestGameInfoDirFn( SuggestGameInfoDirFn_t pfnNewFn ) -{ - SuggestGameInfoDirFn_t &rfn = GetSuggestGameInfoDirFn(); - SuggestGameInfoDirFn_t pfnOldFn = rfn; - rfn = pfnNewFn; - return pfnOldFn; -} - -static FSReturnCode_t TryLocateGameInfoFile( char *pOutDir, int outDirLen, bool bBubbleDir ) -{ - // Retain a copy of suggested path for further attempts - CArrayAutoPtr < char > spchCopyNameBuffer( new char [ outDirLen ] ); - Q_strncpy( spchCopyNameBuffer.Get(), pOutDir, outDirLen ); - spchCopyNameBuffer[ outDirLen - 1 ] = 0; - - // Make appropriate slashes ('/' - Linux style) - for ( char *pchFix = spchCopyNameBuffer.Get(), - *pchEnd = pchFix + outDirLen; - pchFix < pchEnd; ++ pchFix ) - { - if ( '\\' == *pchFix ) - { - *pchFix = '/'; - } - } - - // Have a look in supplied path - do - { - if ( DoesFileExistIn( pOutDir, GAMEINFO_FILENAME ) ) - { - return FS_OK; - } - if ( IsX360() && DoesFileExistIn( pOutDir, GAMEINFO_FILENAME_ALTERNATE ) ) - { - return FS_OK; - } - } - while ( bBubbleDir && Q_StripLastDir( pOutDir, outDirLen ) ); - - // Make an attempt to resolve from "content -> game" directory - Q_strncpy( pOutDir, spchCopyNameBuffer.Get(), outDirLen ); - pOutDir[ outDirLen - 1 ] = 0; - if ( char *pchContentFix = Q_stristr( pOutDir, "/content/" ) ) - { - sprintf( pchContentFix, "/game/" ); - memmove( pchContentFix + 6, pchContentFix + 9, pOutDir + outDirLen - (pchContentFix + 9) ); - - // Try in the mapped "game" directory - do - { - if ( DoesFileExistIn( pOutDir, GAMEINFO_FILENAME ) ) - { - return FS_OK; - } - if ( IsX360() && DoesFileExistIn( pOutDir, GAMEINFO_FILENAME_ALTERNATE ) ) - { - return FS_OK; - } - } - while ( bBubbleDir && Q_StripLastDir( pOutDir, outDirLen ) ); - } - - // Could not find it here - return FS_MISSING_GAMEINFO_FILE; -} - -FSReturnCode_t LocateGameInfoFile( const CFSSteamSetupInfo &fsInfo, char *pOutDir, int outDirLen ) -{ - // Engine and Hammer don't want to search around for it. - if ( fsInfo.m_bOnlyUseDirectoryName ) - { - if ( !fsInfo.m_pDirectoryName ) - return SetupFileSystemError( false, FS_MISSING_GAMEINFO_FILE, "bOnlyUseDirectoryName=1 and pDirectoryName=NULL." ); - - bool bExists = DoesFileExistIn( fsInfo.m_pDirectoryName, GAMEINFO_FILENAME ); - if ( IsX360() && !bExists ) - { - bExists = DoesFileExistIn( fsInfo.m_pDirectoryName, GAMEINFO_FILENAME_ALTERNATE ); - } - if ( !bExists ) - { - if ( IsX360() && CommandLine()->FindParm( "-basedir" ) ) - { - char basePath[MAX_PATH]; - strcpy( basePath, CommandLine()->ParmValue( "-basedir", "" ) ); - Q_AppendSlash( basePath, sizeof( basePath ) ); - Q_strncat( basePath, fsInfo.m_pDirectoryName, sizeof( basePath ), COPY_ALL_CHARACTERS ); - if ( DoesFileExistIn( basePath, GAMEINFO_FILENAME ) ) - { - Q_strncpy( pOutDir, basePath, outDirLen ); - return FS_OK; - } - if ( IsX360() && DoesFileExistIn( basePath, GAMEINFO_FILENAME_ALTERNATE ) ) - { - Q_strncpy( pOutDir, basePath, outDirLen ); - return FS_OK; - } - } - - return SetupFileSystemError( true, FS_MISSING_GAMEINFO_FILE, "Setup file '%s' doesn't exist in subdirectory '%s'.\nCheck your -game parameter or VCONFIG setting.", GAMEINFO_FILENAME, fsInfo.m_pDirectoryName ); - } - - Q_strncpy( pOutDir, fsInfo.m_pDirectoryName, outDirLen ); - return FS_OK; - } - - // First, check for overrides on the command line or environment variables. - const char *pProject = GetVProjectCmdLineValue(); - - if ( pProject ) - { - if ( DoesFileExistIn( pProject, GAMEINFO_FILENAME ) ) - { - Q_MakeAbsolutePath( pOutDir, outDirLen, pProject ); - return FS_OK; - } - if ( IsX360() && DoesFileExistIn( pProject, GAMEINFO_FILENAME_ALTERNATE ) ) - { - Q_MakeAbsolutePath( pOutDir, outDirLen, pProject ); - return FS_OK; - } - - if ( IsX360() && CommandLine()->FindParm( "-basedir" ) ) - { - char basePath[MAX_PATH]; - strcpy( basePath, CommandLine()->ParmValue( "-basedir", "" ) ); - Q_AppendSlash( basePath, sizeof( basePath ) ); - Q_strncat( basePath, pProject, sizeof( basePath ), COPY_ALL_CHARACTERS ); - if ( DoesFileExistIn( basePath, GAMEINFO_FILENAME ) ) - { - Q_strncpy( pOutDir, basePath, outDirLen ); - return FS_OK; - } - if ( DoesFileExistIn( basePath, GAMEINFO_FILENAME_ALTERNATE ) ) - { - Q_strncpy( pOutDir, basePath, outDirLen ); - return FS_OK; - } - } - - if ( fsInfo.m_bNoGameInfo ) - { - // fsInfo.m_bNoGameInfo is set by the Steam dedicated server, before it knows which mod to use. - // Steam dedicated server doesn't need a gameinfo.txt, because we'll ask which mod to use, even if - // -game is supplied on the command line. - Q_strncpy( pOutDir, "", outDirLen ); - return FS_OK; - } - else - { - // They either specified vproject on the command line or it's in their registry. Either way, - // we don't want to continue if they've specified it but it's not valid. - goto ShowError; - } - } - - if ( fsInfo.m_bNoGameInfo ) - { - Q_strncpy( pOutDir, "", outDirLen ); - return FS_OK; - } - - // Ask the application if it can provide us with a game info directory - { - bool bBubbleDir = true; - SuggestGameInfoDirFn_t pfnSuggestGameInfoDirFn = GetSuggestGameInfoDirFn(); - if ( pfnSuggestGameInfoDirFn && - ( * pfnSuggestGameInfoDirFn )( &fsInfo, pOutDir, outDirLen, &bBubbleDir ) && - FS_OK == TryLocateGameInfoFile( pOutDir, outDirLen, bBubbleDir ) ) - return FS_OK; - } - - // Try to use the environment variable / registry - if ( ( pProject = getenv( GAMEDIR_TOKEN ) ) != NULL && - ( Q_MakeAbsolutePath( pOutDir, outDirLen, pProject ), 1 ) && - FS_OK == TryLocateGameInfoFile( pOutDir, outDirLen, false ) ) - return FS_OK; - - if ( IsPC() ) - { - Warning( "Warning: falling back to auto detection of vproject directory.\n" ); - - // Now look for it in the directory they passed in. - if ( fsInfo.m_pDirectoryName ) - Q_MakeAbsolutePath( pOutDir, outDirLen, fsInfo.m_pDirectoryName ); - else - Q_MakeAbsolutePath( pOutDir, outDirLen, "." ); - - if ( FS_OK == TryLocateGameInfoFile( pOutDir, outDirLen, true ) ) - return FS_OK; - - // Use the CWD - Q_getwd( pOutDir, outDirLen ); - if ( FS_OK == TryLocateGameInfoFile( pOutDir, outDirLen, true ) ) - return FS_OK; - } - -ShowError: - return SetupFileSystemError( true, FS_MISSING_GAMEINFO_FILE, - "Unable to find %s. Solutions:\n\n" - "1. Read http://www.valve-erc.com/srcsdk/faq.html#NoGameDir\n" - "2. Run vconfig to specify which game you're working on.\n" - "3. Add -game on the command line where is the directory that %s is in.\n", - GAMEINFO_FILENAME, GAMEINFO_FILENAME ); -} - -bool DoesPathExistAlready( const char *pPathEnvVar, const char *pTestPath ) -{ - // Fix the slashes in the input arguments. - char correctedPathEnvVar[8192], correctedTestPath[MAX_PATH]; - Q_strncpy( correctedPathEnvVar, pPathEnvVar, sizeof( correctedPathEnvVar ) ); - Q_FixSlashes( correctedPathEnvVar ); - pPathEnvVar = correctedPathEnvVar; - - Q_strncpy( correctedTestPath, pTestPath, sizeof( correctedTestPath ) ); - Q_FixSlashes( correctedTestPath ); - if ( strlen( correctedTestPath ) > 0 && PATHSEPARATOR( correctedTestPath[strlen(correctedTestPath)-1] ) ) - correctedTestPath[ strlen(correctedTestPath) - 1 ] = 0; - - pTestPath = correctedTestPath; - - const char *pCurPos = pPathEnvVar; - while ( 1 ) - { - const char *pTestPos = Q_stristr( pCurPos, pTestPath ); - if ( !pTestPos ) - return false; - - // Ok, we found pTestPath in the path, but it's only valid if it's followed by an optional slash and a semicolon. - pTestPos += strlen( pTestPath ); - if ( pTestPos[0] == 0 || pTestPos[0] == ';' || (PATHSEPARATOR( pTestPos[0] ) && pTestPos[1] == ';') ) - return true; - - // Advance our marker.. - pCurPos = pTestPos; - } -} - -FSReturnCode_t SetSteamInstallPath( char *steamInstallPath, int steamInstallPathLen, CSteamEnvVars &steamEnvVars, bool bErrorsAsWarnings ) -{ - if ( IsConsole() ) - { - // consoles don't use steam - return FS_MISSING_STEAM_DLL; - } - - // Start at our bin directory and move up until we find a directory with steam.dll in it. - char executablePath[MAX_PATH]; - if ( !FileSystem_GetExecutableDir( executablePath, sizeof( executablePath ) ) ) - { - if ( bErrorsAsWarnings ) - { - Warning( "SetSteamInstallPath: FileSystem_GetExecutableDir failed.\n" ); - return FS_INVALID_PARAMETERS; - } - else - { - return SetupFileSystemError( false, FS_INVALID_PARAMETERS, "FileSystem_GetExecutableDir failed." ); - } - } - - Q_strncpy( steamInstallPath, executablePath, steamInstallPathLen ); - while ( 1 ) - { - // Ignore steamapp.cfg here in case they're debugging. We still need to know the real steam path so we can find their username. - // find - if ( DoesFileExistIn( steamInstallPath, "steam.dll" ) && !DoesFileExistIn( steamInstallPath, "steamapp.cfg" ) ) - break; - - if ( !Q_StripLastDir( steamInstallPath, steamInstallPathLen ) ) - { - if ( bErrorsAsWarnings ) - { - Warning( "Can't find steam.dll relative to executable path: %s.\n", executablePath ); - return FS_MISSING_STEAM_DLL; - } - else - { - return SetupFileSystemError( false, FS_MISSING_STEAM_DLL, "Can't find steam.dll relative to executable path: %s.", executablePath ); - } - } - } - - // Also, add the install path to their PATH environment variable, so filesystem_steam.dll can get to steam.dll. - char szPath[ 8192 ]; - steamEnvVars.m_Path.GetValue( szPath, sizeof( szPath ) ); - if ( !DoesPathExistAlready( szPath, steamInstallPath ) ) - { - steamEnvVars.m_Path.SetValue( "%s;%s", szPath, steamInstallPath ); - } - return FS_OK; -} - -FSReturnCode_t GetSteamCfgPath( char *steamCfgPath, int steamCfgPathLen ) -{ - steamCfgPath[0] = 0; - char executablePath[MAX_PATH]; - if ( !FileSystem_GetExecutableDir( executablePath, sizeof( executablePath ) ) ) - { - return SetupFileSystemError( false, FS_INVALID_PARAMETERS, "FileSystem_GetExecutableDir failed." ); - } - Q_strncpy( steamCfgPath, executablePath, steamCfgPathLen ); - while ( 1 ) - { - if ( DoesFileExistIn( steamCfgPath, "steam.cfg" ) ) - break; - - if ( !Q_StripLastDir( steamCfgPath, steamCfgPathLen) ) - { - // the file isnt found, thats ok, its not mandatory - return FS_OK; - } - } - Q_AppendSlash( steamCfgPath, steamCfgPathLen ); - Q_strncat( steamCfgPath, "steam.cfg", steamCfgPathLen, COPY_ALL_CHARACTERS ); - - return FS_OK; -} - -void SetSteamAppUser( KeyValues *pSteamInfo, const char *steamInstallPath, CSteamEnvVars &steamEnvVars ) -{ - // Always inherit the Steam user if it's already set, since it probably means we (or the - // the app that launched us) were launched from Steam. - char appUser[MAX_PATH]; - if ( steamEnvVars.m_SteamAppUser.GetValue( appUser, sizeof( appUser ) ) ) - return; - - const char *pTempAppUser = NULL; - if ( pSteamInfo && (pTempAppUser = pSteamInfo->GetString( "SteamAppUser", NULL )) != NULL ) - { - Q_strncpy( appUser, pTempAppUser, sizeof( appUser ) ); - } - else - { - // They don't have SteamInfo.txt, or it's missing SteamAppUser. Try to figure out the user - // by looking in \config\SteamAppData.vdf. - char fullFilename[MAX_PATH]; - Q_strncpy( fullFilename, steamInstallPath, sizeof( fullFilename ) ); - Q_AppendSlash( fullFilename, sizeof( fullFilename ) ); - Q_strncat( fullFilename, "config\\SteamAppData.vdf", sizeof( fullFilename ), COPY_ALL_CHARACTERS ); - - KeyValues *pSteamAppData = ReadKeyValuesFile( fullFilename ); - if ( !pSteamAppData || (pTempAppUser = pSteamAppData->GetString( "AutoLoginUser", NULL )) == NULL ) - { - Error( "Can't find steam app user info." ); - } - Q_strncpy( appUser, pTempAppUser, sizeof( appUser ) ); - - pSteamAppData->deleteThis(); - } - - Q_strlower( appUser ); - steamEnvVars.m_SteamAppUser.SetValue( "%s", appUser ); -} - -void SetSteamUserPassphrase( KeyValues *pSteamInfo, CSteamEnvVars &steamEnvVars ) -{ - // Always inherit the passphrase if it's already set, since it probably means we (or the - // the app that launched us) were launched from Steam. - char szPassPhrase[ MAX_PATH ]; - if ( steamEnvVars.m_SteamUserPassphrase.GetValue( szPassPhrase, sizeof( szPassPhrase ) ) ) - return; - - // SteamUserPassphrase. - const char *pStr; - if ( pSteamInfo && (pStr = pSteamInfo->GetString( "SteamUserPassphrase", NULL )) != NULL ) - { - steamEnvVars.m_SteamUserPassphrase.SetValue( "%s", pStr ); - } -} - -void SetSteamAppId( KeyValues *pFileSystemInfo, const char *pGameInfoDirectory, CSteamEnvVars &steamEnvVars ) -{ - // SteamAppId is in gameinfo.txt->FileSystem->FileSystemInfo_Steam->SteamAppId. - int iAppId = pFileSystemInfo->GetInt( "SteamAppId", -1 ); - if ( iAppId == -1 ) - Error( "Missing SteamAppId in %s\\%s.", pGameInfoDirectory, GAMEINFO_FILENAME ); - - steamEnvVars.m_SteamAppId.SetValue( "%d", iAppId ); -} - -FSReturnCode_t SetupSteamStartupEnvironment( KeyValues *pFileSystemInfo, const char *pGameInfoDirectory, CSteamEnvVars &steamEnvVars ) -{ - // Ok, we're going to run Steam. See if they have SteamInfo.txt. If not, we'll try to deduce what we can. - char steamInfoFile[MAX_PATH]; - Q_strncpy( steamInfoFile, pGameInfoDirectory, sizeof( steamInfoFile ) ); - Q_AppendSlash( steamInfoFile, sizeof( steamInfoFile ) ); - Q_strncat( steamInfoFile, "steaminfo.txt", sizeof( steamInfoFile ), COPY_ALL_CHARACTERS ); - KeyValues *pSteamInfo = ReadKeyValuesFile( steamInfoFile ); - - char steamInstallPath[MAX_PATH]; - FSReturnCode_t ret = SetSteamInstallPath( steamInstallPath, sizeof( steamInstallPath ), steamEnvVars, false ); - if ( ret != FS_OK ) - return ret; - - SetSteamAppUser( pSteamInfo, steamInstallPath, steamEnvVars ); - SetSteamUserPassphrase( pSteamInfo, steamEnvVars ); - SetSteamAppId( pFileSystemInfo, pGameInfoDirectory, steamEnvVars ); - - if ( pSteamInfo ) - pSteamInfo->deleteThis(); - - return FS_OK; -} - -FSReturnCode_t GetSteamExtraAppId( const char *pDirectoryName, int *nExtraAppId ) -{ - // Now, load gameinfo.txt (to make sure it's there) - KeyValues *pMainFile, *pFileSystemInfo, *pSearchPaths; - FSReturnCode_t ret = LoadGameInfoFile( pDirectoryName, pMainFile, pFileSystemInfo, pSearchPaths ); - if ( ret != FS_OK ) - return ret; - - *nExtraAppId = pFileSystemInfo->GetInt( "ToolsAppId", -1 ); - pMainFile->deleteThis(); - return FS_OK; -} - -FSReturnCode_t FileSystem_SetBasePaths( IFileSystem *pFileSystem ) -{ - pFileSystem->RemoveSearchPaths( "EXECUTABLE_PATH" ); - - char executablePath[MAX_PATH]; - if ( !FileSystem_GetExecutableDir( executablePath, sizeof( executablePath ) ) ) - return SetupFileSystemError( false, FS_INVALID_PARAMETERS, "FileSystem_GetExecutableDir failed." ); - - pFileSystem->AddSearchPath( executablePath, "EXECUTABLE_PATH" ); - return FS_OK; -} - -//----------------------------------------------------------------------------- -// Returns the name of the file system DLL to use -//----------------------------------------------------------------------------- -FSReturnCode_t FileSystem_GetFileSystemDLLName( char *pFileSystemDLL, int nMaxLen, bool &bSteam ) -{ - bSteam = false; - - // Inside of here, we don't have a filesystem yet, so we have to assume that the filesystem_stdio or filesystem_steam - // is in this same directory with us. - char executablePath[MAX_PATH]; - if ( !FileSystem_GetExecutableDir( executablePath, sizeof( executablePath ) ) ) - return SetupFileSystemError( false, FS_INVALID_PARAMETERS, "FileSystem_GetExecutableDir failed." ); - -#if defined( _WIN32 ) && !defined( _X360 ) - // If filesystem_stdio.dll is missing or -steam is specified, then load filesystem_steam.dll. - // There are two command line parameters for Steam: - // 1) -steam (runs Steam in remote filesystem mode; requires Steam backend) - // 2) -steamlocal (runs Steam in local filesystem mode (all content off HDD) - Q_snprintf( pFileSystemDLL, nMaxLen, "%s%cfilesystem_stdio.dll", executablePath, CORRECT_PATH_SEPARATOR ); - if ( CommandLine()->FindParm( "-steam" ) || CommandLine()->FindParm( "-steamlocal" ) || _access( pFileSystemDLL, 0 ) != 0 ) - { - Q_snprintf( pFileSystemDLL, nMaxLen, "%s%cfilesystem_steam.dll", executablePath, CORRECT_PATH_SEPARATOR ); - bSteam = true; - } -#elif defined( _X360 ) - Q_snprintf( pFileSystemDLL, nMaxLen, "%s%cfilesystem_stdio.dll", executablePath, CORRECT_PATH_SEPARATOR ); -#elif defined( _LINUX ) - Q_snprintf( pFileSystemDLL, nMaxLen, "%s%cfilesystem_i486.so", executablePath, CORRECT_PATH_SEPARATOR ); -#else - #error "define a filesystem dll name" -#endif - - return FS_OK; -} - -//----------------------------------------------------------------------------- -// Sets up the steam.dll install path in our PATH env var (so you can then just -// LoadLibrary() on filesystem_steam.dll without having to copy steam.dll anywhere special ) -//----------------------------------------------------------------------------- -FSReturnCode_t FileSystem_SetupSteamInstallPath() -{ - CSteamEnvVars steamEnvVars; - char steamInstallPath[MAX_PATH]; - FSReturnCode_t ret = SetSteamInstallPath( steamInstallPath, sizeof( steamInstallPath ), steamEnvVars, true ); - steamEnvVars.m_Path.SetRestoreOriginalValue( false ); // We want to keep the change to the path going forward. - return ret; -} - -//----------------------------------------------------------------------------- -// Sets up the steam environment + gets back the gameinfo.txt path -//----------------------------------------------------------------------------- -FSReturnCode_t FileSystem_SetupSteamEnvironment( CFSSteamSetupInfo &fsInfo ) -{ - // First, locate the directory with gameinfo.txt. - FSReturnCode_t ret = LocateGameInfoFile( fsInfo, fsInfo.m_GameInfoPath, sizeof( fsInfo.m_GameInfoPath ) ); - if ( ret != FS_OK ) - return ret; - - // This is so that processes spawned by this application will have the same VPROJECT - char pEnvBuf[MAX_PATH+32]; - Q_snprintf( pEnvBuf, sizeof(pEnvBuf), "%s=%s", GAMEDIR_TOKEN, fsInfo.m_GameInfoPath ); - _putenv( pEnvBuf ); - - CSteamEnvVars steamEnvVars; - if ( fsInfo.m_bSteam ) - { - if ( fsInfo.m_bToolsMode ) - { - // Now, load gameinfo.txt (to make sure it's there) - KeyValues *pMainFile, *pFileSystemInfo, *pSearchPaths; - ret = LoadGameInfoFile( fsInfo.m_GameInfoPath, pMainFile, pFileSystemInfo, pSearchPaths ); - if ( ret != FS_OK ) - return ret; - - // If filesystem_stdio.dll is missing or -steam is specified, then load filesystem_steam.dll. - // There are two command line parameters for Steam: - // 1) -steam (runs Steam in remote filesystem mode; requires Steam backend) - // 2) -steamlocal (runs Steam in local filesystem mode (all content off HDD) - - // Setup all the environment variables related to Steam so filesystem_steam.dll knows how to initialize Steam. - ret = SetupSteamStartupEnvironment( pFileSystemInfo, fsInfo.m_GameInfoPath, steamEnvVars ); - if ( ret != FS_OK ) - return ret; - - steamEnvVars.m_SteamAppId.SetRestoreOriginalValue( false ); // We want to keep the change to the path going forward. - - // We're done with main file - pMainFile->deleteThis(); - } - else if ( fsInfo.m_bSetSteamDLLPath ) - { - // This is used by the engine to automatically set the path to their steam.dll when running the engine, - // so they can debug it without having to copy steam.dll up into their hl2.exe folder. - char steamInstallPath[MAX_PATH]; - ret = SetSteamInstallPath( steamInstallPath, sizeof( steamInstallPath ), steamEnvVars, true ); - steamEnvVars.m_Path.SetRestoreOriginalValue( false ); // We want to keep the change to the path going forward. - } - } - - return FS_OK; -} - - -//----------------------------------------------------------------------------- -// Loads the file system module -//----------------------------------------------------------------------------- -FSReturnCode_t FileSystem_LoadFileSystemModule( CFSLoadModuleInfo &fsInfo ) -{ - // First, locate the directory with gameinfo.txt. - FSReturnCode_t ret = FileSystem_SetupSteamEnvironment( fsInfo ); - if ( ret != FS_OK ) - return ret; - - // Now that the environment is setup, load the filesystem module. - if ( !Sys_LoadInterface( - fsInfo.m_pFileSystemDLLName, - FILESYSTEM_INTERFACE_VERSION, - &fsInfo.m_pModule, - (void**)&fsInfo.m_pFileSystem ) ) - { - return SetupFileSystemError( false, FS_UNABLE_TO_INIT, "Can't load %s.", fsInfo.m_pFileSystemDLLName ); - } - - if ( !fsInfo.m_pFileSystem->Connect( fsInfo.m_ConnectFactory ) ) - return SetupFileSystemError( false, FS_UNABLE_TO_INIT, "%s IFileSystem::Connect failed.", fsInfo.m_pFileSystemDLLName ); - - if ( fsInfo.m_pFileSystem->Init() != INIT_OK ) - return SetupFileSystemError( false, FS_UNABLE_TO_INIT, "%s IFileSystem::Init failed.", fsInfo.m_pFileSystemDLLName ); - - return FS_OK; -} - - -//----------------------------------------------------------------------------- -// Mounds a particular steam cache -//----------------------------------------------------------------------------- -FSReturnCode_t FileSystem_MountContent( CFSMountContentInfo &mountContentInfo ) -{ - // This part is Steam-only. - if ( mountContentInfo.m_pFileSystem->IsSteam() ) - { - // Find out the "extra app id". This is for tools, which want to mount a base app's filesystem - // like HL2, then mount the SDK content (tools materials and models, etc) in addition. - int nExtraAppId = -1; - if ( mountContentInfo.m_bToolsMode ) - { - FSReturnCode_t ret = GetSteamExtraAppId( mountContentInfo.m_pDirectoryName, &nExtraAppId ); - if ( ret != FS_OK ) - return ret; - } - - // Set our working directory temporarily so Steam can remember it. - // This is what Steam strips off absolute filenames like c:\program files\valve\steam\steamapps\username\sourcesdk - // to get to the relative part of the path. - char baseDir[MAX_PATH], oldWorkingDir[MAX_PATH]; - if ( !FileSystem_GetBaseDir( baseDir, sizeof( baseDir ) ) ) - return SetupFileSystemError( false, FS_INVALID_PARAMETERS, "FileSystem_GetBaseDir failed." ); - - Q_getwd( oldWorkingDir, sizeof( oldWorkingDir ) ); - _chdir( baseDir ); - - // Filesystem_tools needs to add dependencies in here beforehand. - FilesystemMountRetval_t retVal = mountContentInfo.m_pFileSystem->MountSteamContent( nExtraAppId ); - - _chdir( oldWorkingDir ); - - if ( retVal != FILESYSTEM_MOUNT_OK ) - return SetupFileSystemError( true, FS_UNABLE_TO_INIT, "Unable to mount Steam content in the file system" ); - } - - return FileSystem_SetBasePaths( mountContentInfo.m_pFileSystem ); -} - -void FileSystem_SetErrorMode( FSErrorMode_t errorMode ) -{ - g_FileSystemErrorMode = errorMode; -} - -void FileSystem_ClearSteamEnvVars() -{ - CSteamEnvVars envVars; - - // Change the values and don't restore the originals. - envVars.m_SteamAppId.SetValue( "" ); - envVars.m_SteamUserPassphrase.SetValue( "" ); - envVars.m_SteamAppUser.SetValue( "" ); - - envVars.SetRestoreOriginalValue_ALL( false ); -} - -//----------------------------------------------------------------------------- -// Adds the platform folder to the search path. -//----------------------------------------------------------------------------- -void FileSystem_AddSearchPath_Platform( IFileSystem *pFileSystem, const char *szGameInfoPath ) -{ - char platform[MAX_PATH]; - if ( pFileSystem->IsSteam() ) - { - // Steam doesn't support relative paths - Q_strncpy( platform, "platform", MAX_PATH ); - } - else - { - Q_strncpy( platform, szGameInfoPath, MAX_PATH ); - Q_StripTrailingSlash( platform ); - Q_strncat( platform, "/../platform", MAX_PATH, MAX_PATH ); - } - - pFileSystem->AddSearchPath( platform, "PLATFORM" ); -} diff --git a/public/filesystem_init.h b/public/filesystem_init.h deleted file mode 100644 index 3ec0dd7ea..000000000 --- a/public/filesystem_init.h +++ /dev/null @@ -1,219 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef FILESYSTEM_INIT_H -#define FILESYSTEM_INIT_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "filesystem.h" - - -// If this option is on the command line, then filesystem_init won't bring up the vconfig -// dialog even if FS_ERRORMODE_VCONFIG is used. -#define CMDLINEOPTION_NOVCONFIG "-NoVConfig" - -#define GAMEDIR_TOKEN "VProject" - - -#if defined( _WIN32 ) || defined( WIN32 ) -#define PATHSEPARATOR(c) ((c) == '\\' || (c) == '/') -#else //_WIN32 -#define PATHSEPARATOR(c) ((c) == '/') -#endif //_WIN32 - - -enum FSReturnCode_t -{ - FS_OK, - FS_MISSING_GAMEINFO_FILE, - FS_INVALID_GAMEINFO_FILE, - FS_INVALID_PARAMETERS, - FS_UNABLE_TO_INIT, - FS_MISSING_STEAM_DLL -}; - - -enum FSErrorMode_t -{ - FS_ERRORMODE_AUTO, // Call Error() in case of an error. - FS_ERRORMODE_VCONFIG, // Call Error() for errors and run vconfig when appropriate. - FS_ERRORMODE_NONE, // Just return FSReturnCode values and setup the string for FileSystem_GetLastErrorString. -}; - - -class CFSSteamSetupInfo -{ -public: - CFSSteamSetupInfo(); - -// Inputs. -public: - // If this is set, then the init code will look in this directory up to the root for gameinfo.txt. - // It must be set for FileSystem_LoadSearchPaths to work. - // - // (default: null) - const char *m_pDirectoryName; - - // If this is true, then it won't look at -vproject, -game, or the vproject environment variable - // to find gameinfo.txt. If this is true, then m_pDirectoryName must be set. - // - // (default: false) - bool m_bOnlyUseDirectoryName; - - // If this is true, then: - // 1. It will set the environment variables that steam.dll looks at for startup info. - // 2. It will look for ToolsAppId in the gameinfo.txt file and load the - // steam caches associated with that cache if it's there. This is so apps like Hammer and hlmv - // can load the main steam caches (like for Counter-Strike or Half-Life 2), and also load the - // caches that include tools-specific materials (materials\editor, materials\debug, etc). - // - // (default: true - should be FALSE for the engine) - bool m_bToolsMode; - - // If this is true, and m_bToolsMode is false, then it will append the path to steam.dll to the - // PATH environment variable. This makes it so you can run the engine under Steam without - // having to copy steam.dll up into your hl2.exe folder. - // (default: false) - bool m_bSetSteamDLLPath; - - // Are we loading the Steam filesystem? This should be the same value that - // FileSystem_GetFileSystemDLLName gave you. - bool m_bSteam; - - // If this is true, then it won't look for a gameinfo.txt. - // - // (default: false) - bool m_bNoGameInfo; - -// Outputs (if it returns FS_OK). -public: - char m_GameInfoPath[512]; // The directory that gameinfo.txt lives in. -}; - - -class CFSLoadModuleInfo : public CFSSteamSetupInfo -{ -public: - CFSLoadModuleInfo(); - -// Inputs. -public: - // Full path to the file system DLL (gotten from FileSystem_GetFileSystemDLLName). - const char *m_pFileSystemDLLName; - - // Passed to IFileSystem::Connect. - CreateInterfaceFn m_ConnectFactory; - -// Outputs (if it returns FS_OK). -public: - // The filesystem you got from FileSystem_LoadFileSystemModule. - IFileSystem *m_pFileSystem; - CSysModule *m_pModule; -}; - - -class CFSMountContentInfo -{ -public: - CFSMountContentInfo(); - -// Inputs. -public: - - // See CFSLoadModuleInfo::m_bToolsMode (this valid should always be the same as you passed to CFSLoadModuleInfo::m_bToolsMode). - bool m_bToolsMode; - - // This specifies the directory where gameinfo.txt is. This must be set. - // It can come from CFSLoadModuleInfo::m_GameInfoPath. - const char *m_pDirectoryName; - - // Gotten from CFSLoadModuleInfo::m_pFileSystem. - IFileSystem *m_pFileSystem; -}; - - -class CFSSearchPathsInit -{ -public: - CFSSearchPathsInit(); - -// Inputs. -public: - // This specifies the directory where gameinfo.txt is. This must be set. - const char *m_pDirectoryName; - - // If this is set, then it will add a search path with _ appended to the pathname - // for each search path with a path ID of "game". - // (default: null) - const char *m_pLanguage; - - // This is the filesystem FileSystem_LoadSearchPaths is talking to. - IFileSystem *m_pFileSystem; - -// Outputs. -public: - // This is the location of the first search path called "game", which also becomes your "mod" search path. - char m_ModPath[512]; -}; - - -const char *GetVProjectCmdLineValue(); - - -// Call this to use a bin directory relative to VPROJECT -void FileSystem_UseVProjectBinDir( bool bEnable ); - -// This is used by all things that use the application framework: -// Note that the application framework automatically takes care of step 1 if you use CSteamApplication. -// Step 1: Ask filesystem_init for the name of the filesystem DLL to load -FSReturnCode_t FileSystem_GetFileSystemDLLName( char *pFileSystemDLL, int nMaxLen, bool &bSteam ); - -// Step 2: Use filesystem framework to load/connect/init that filesystem DLL -// -or- just set up the steam environment and get back the gameinfo.txt path -// The second method is used by the application framework, which wants to connect/init the filesystem itself -FSReturnCode_t FileSystem_LoadFileSystemModule( CFSLoadModuleInfo &info ); -FSReturnCode_t FileSystem_SetupSteamEnvironment( CFSSteamSetupInfo &info ); - -// Step 3: Ask filesystem_init to set up the executable search path, and mount the steam content based on the mod gameinfo.txt file -FSReturnCode_t FileSystem_MountContent( CFSMountContentInfo &fsInfo ); - -// Step 4: Load the search paths out of pGameDirectory\gameinfo.txt. -FSReturnCode_t FileSystem_LoadSearchPaths( CFSSearchPathsInit &initInfo ); - -// This is automatically done during step 3, but if you want to redo all the search -// paths (like Hammer does), you can call this to reset executable_path. -FSReturnCode_t FileSystem_SetBasePaths( IFileSystem *pFileSystem ); - -// Utility function to add the PLATFORM search path. -void FileSystem_AddSearchPath_Platform( IFileSystem *pFileSystem, const char *szGameInfoPath ); - -// See FSErrorMode_t. If you don't specify one here, then the default is FS_ERRORMODE_VCONFIG. -void FileSystem_SetErrorMode( FSErrorMode_t errorMode = FS_ERRORMODE_VCONFIG ); - -bool FileSystem_GetExecutableDir( char *exedir, int exeDirLen ); - -// Clear SteamAppUser, SteamUserPassphrase, and SteamAppId from this process's environment. -// TODO: always do this after LoadFileSysteModule.. there's no reason it should be -// in the environment. -void FileSystem_ClearSteamEnvVars(); - -// Find the steam.cfg above you for optional stuff -FSReturnCode_t GetSteamCfgPath( char *steamCfgPath, int steamCfgPathLen ); - -// Setup the Steam.dll path without needing all the extra gameinfo stuff first -// used by the CSteamApplication::Create() code to LoadModule() on the filesystem -// before the underlying apps know specific details about the environment to load -FSReturnCode_t FileSystem_SetupSteamInstallPath(); - -// Returns the last error. -const char *FileSystem_GetLastErrorString(); - -void Q_getwd( char *out, int outSize ); - -#endif // FILESYSTEM_INIT_H diff --git a/public/filesystem_passthru.h b/public/filesystem_passthru.h deleted file mode 100644 index 6c05fd8ba..000000000 --- a/public/filesystem_passthru.h +++ /dev/null @@ -1,277 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef FILESYSTEM_PASSTHRU_H -#define FILESYSTEM_PASSTHRU_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "filesystem.h" -#include -#include - -#ifdef AsyncRead -#undef AsyncRead -#undef AsyncReadMutiple -#endif - -// -// These classes pass all filesystem interface calls through to another filesystem -// interface. They can be used anytime you want to override a couple things in -// a filesystem. VMPI uses this to override the base filesystem calls while -// allowing the rest of the filesystem functionality to work on the master. -// - -template -class CInternalFileSystemPassThru : public Base -{ -public: - CInternalFileSystemPassThru() - { - m_pBaseFileSystemPassThru = NULL; - } - virtual void InitPassThru( IBaseFileSystem *pBaseFileSystemPassThru ) - { - m_pBaseFileSystemPassThru = pBaseFileSystemPassThru; - } - virtual int Read( void* pOutput, int size, FileHandle_t file ) { return m_pBaseFileSystemPassThru->Read( pOutput, size, file ); } - virtual int Write( void const* pInput, int size, FileHandle_t file ) { return m_pBaseFileSystemPassThru->Write( pInput, size, file ); } - virtual FileHandle_t Open( const char *pFileName, const char *pOptions, const char *pathID ) { return m_pBaseFileSystemPassThru->Open( pFileName, pOptions, pathID ); } - virtual void Close( FileHandle_t file ) { m_pBaseFileSystemPassThru->Close( file ); } - virtual void Seek( FileHandle_t file, int pos, FileSystemSeek_t seekType ) { m_pBaseFileSystemPassThru->Seek( file, pos, seekType ); } - virtual unsigned int Tell( FileHandle_t file ) { return m_pBaseFileSystemPassThru->Tell( file ); } - virtual unsigned int Size( FileHandle_t file ) { return m_pBaseFileSystemPassThru->Size( file ); } - virtual unsigned int Size( const char *pFileName, const char *pPathID ) { return m_pBaseFileSystemPassThru->Size( pFileName, pPathID ); } - virtual void Flush( FileHandle_t file ) { m_pBaseFileSystemPassThru->Flush( file ); } - virtual bool Precache( const char *pFileName, const char *pPathID ) { return m_pBaseFileSystemPassThru->Precache( pFileName, pPathID ); } - virtual bool FileExists( const char *pFileName, const char *pPathID ) { return m_pBaseFileSystemPassThru->FileExists( pFileName, pPathID ); } - virtual bool IsFileWritable( char const *pFileName, const char *pPathID ) { return m_pBaseFileSystemPassThru->IsFileWritable( pFileName, pPathID ); } - virtual bool SetFileWritable( char const *pFileName, bool writable, const char *pPathID ) { return m_pBaseFileSystemPassThru->SetFileWritable( pFileName, writable, pPathID ); } - virtual long GetFileTime( const char *pFileName, const char *pPathID ) { return m_pBaseFileSystemPassThru->GetFileTime( pFileName, pPathID ); } - virtual bool ReadFile( const char *pFileName, const char *pPath, CUtlBuffer &buf, int nMaxBytes = 0, int nStartingByte = 0, FSAllocFunc_t pfnAlloc = NULL ) { return m_pBaseFileSystemPassThru->ReadFile( pFileName, pPath, buf, nMaxBytes, nStartingByte, pfnAlloc ); } - virtual bool WriteFile( const char *pFileName, const char *pPath, CUtlBuffer &buf ) { return m_pBaseFileSystemPassThru->WriteFile( pFileName, pPath, buf ); } - virtual bool UnzipFile( const char *pFileName, const char *pPath, const char *pDestination ) { return m_pBaseFileSystemPassThru->UnzipFile( pFileName, pPath, pDestination ); } - -protected: - IBaseFileSystem *m_pBaseFileSystemPassThru; -}; - - -class CBaseFileSystemPassThru : public CInternalFileSystemPassThru -{ -public: -}; - - -class CFileSystemPassThru : public CInternalFileSystemPassThru -{ -public: - typedef CInternalFileSystemPassThru BaseClass; - - CFileSystemPassThru() - { - m_pFileSystemPassThru = NULL; - } - virtual void InitPassThru( IFileSystem *pFileSystemPassThru, bool bBaseOnly ) - { - if ( !bBaseOnly ) - m_pFileSystemPassThru = pFileSystemPassThru; - - BaseClass::InitPassThru( pFileSystemPassThru ); - } - - // IAppSystem stuff. - // Here's where the app systems get to learn about each other - virtual bool Connect( CreateInterfaceFn factory ) { return m_pFileSystemPassThru->Connect( factory ); } - virtual void Disconnect() { m_pFileSystemPassThru->Disconnect(); } - virtual void *QueryInterface( const char *pInterfaceName ) { return m_pFileSystemPassThru->QueryInterface( pInterfaceName ); } - virtual InitReturnVal_t Init() { return m_pFileSystemPassThru->Init(); } - virtual void Shutdown() { m_pFileSystemPassThru->Shutdown(); } - - virtual void RemoveAllSearchPaths( void ) { m_pFileSystemPassThru->RemoveAllSearchPaths(); } - virtual void AddSearchPath( const char *pPath, const char *pathID, SearchPathAdd_t addType ) { m_pFileSystemPassThru->AddSearchPath( pPath, pathID, addType ); } - virtual bool RemoveSearchPath( const char *pPath, const char *pathID ) { return m_pFileSystemPassThru->RemoveSearchPath( pPath, pathID ); } - virtual void RemoveFile( char const* pRelativePath, const char *pathID ) { m_pFileSystemPassThru->RemoveFile( pRelativePath, pathID ); } - virtual bool RenameFile( char const *pOldPath, char const *pNewPath, const char *pathID ) { return m_pFileSystemPassThru->RenameFile( pOldPath, pNewPath, pathID ); } - virtual void CreateDirHierarchy( const char *path, const char *pathID ) { m_pFileSystemPassThru->CreateDirHierarchy( path, pathID ); } - virtual bool IsDirectory( const char *pFileName, const char *pathID ) { return m_pFileSystemPassThru->IsDirectory( pFileName, pathID ); } - virtual void FileTimeToString( char* pStrip, int maxCharsIncludingTerminator, long fileTime ) { m_pFileSystemPassThru->FileTimeToString( pStrip, maxCharsIncludingTerminator, fileTime ); } - virtual void SetBufferSize( FileHandle_t file, unsigned nBytes ) { m_pFileSystemPassThru->SetBufferSize( file, nBytes ); } - virtual bool IsOk( FileHandle_t file ) { return m_pFileSystemPassThru->IsOk( file ); } - virtual bool EndOfFile( FileHandle_t file ) { return m_pFileSystemPassThru->EndOfFile( file ); } - virtual char *ReadLine( char *pOutput, int maxChars, FileHandle_t file ) { return m_pFileSystemPassThru->ReadLine( pOutput, maxChars, file ); } - virtual int FPrintf( FileHandle_t file, const char *pFormat, ... ) - { - char str[8192]; - va_list marker; - va_start( marker, pFormat ); - _vsnprintf( str, sizeof( str ), pFormat, marker ); - va_end( marker ); - return m_pFileSystemPassThru->FPrintf( file, "%s", str ); - } - virtual CSysModule *LoadModule( const char *pFileName, const char *pPathID, bool bValidatedDllOnly ) { return m_pFileSystemPassThru->LoadModule( pFileName, pPathID, bValidatedDllOnly ); } - virtual void UnloadModule( CSysModule *pModule ) { m_pFileSystemPassThru->UnloadModule( pModule ); } - virtual const char *FindFirst( const char *pWildCard, FileFindHandle_t *pHandle ) { return m_pFileSystemPassThru->FindFirst( pWildCard, pHandle ); } - virtual const char *FindNext( FileFindHandle_t handle ) { return m_pFileSystemPassThru->FindNext( handle ); } - virtual bool FindIsDirectory( FileFindHandle_t handle ) { return m_pFileSystemPassThru->FindIsDirectory( handle ); } - virtual void FindClose( FileFindHandle_t handle ) { m_pFileSystemPassThru->FindClose( handle ); } - virtual const char *GetLocalPath( const char *pFileName, char *pLocalPath, int localPathBufferSize ) { return m_pFileSystemPassThru->GetLocalPath( pFileName, pLocalPath, localPathBufferSize ); } - virtual bool FullPathToRelativePath( const char *pFullpath, char *pRelative, int maxlen ) { return m_pFileSystemPassThru->FullPathToRelativePath( pFullpath, pRelative, maxlen ); } - virtual bool GetCaseCorrectFullPath_Ptr( const char *pFullPath, char *pDest, int maxLenInChars ) { return m_pFileSystemPassThru->GetCaseCorrectFullPath_Ptr(pFullPath, pDest, maxLenInChars ); } - virtual bool GetCurrentDirectory( char* pDirectory, int maxlen ) { return m_pFileSystemPassThru->GetCurrentDirectory( pDirectory, maxlen ); } - virtual void PrintOpenedFiles( void ) { m_pFileSystemPassThru->PrintOpenedFiles(); } - virtual void PrintSearchPaths( void ) { m_pFileSystemPassThru->PrintSearchPaths(); } - virtual void SetWarningFunc( void (*pfnWarning)( const char *fmt, ... ) ) { m_pFileSystemPassThru->SetWarningFunc( pfnWarning ); } - virtual void SetWarningLevel( FileWarningLevel_t level ) { m_pFileSystemPassThru->SetWarningLevel( level ); } - virtual void AddLoggingFunc( void (*pfnLogFunc)( const char *fileName, const char *accessType ) ){ m_pFileSystemPassThru->AddLoggingFunc( pfnLogFunc ); } - virtual void RemoveLoggingFunc( FileSystemLoggingFunc_t logFunc ) { m_pFileSystemPassThru->RemoveLoggingFunc( logFunc ); } - virtual FSAsyncStatus_t AsyncReadMultiple( const FileAsyncRequest_t *pRequests, int nRequests, FSAsyncControl_t *pControls ) { return m_pFileSystemPassThru->AsyncReadMultiple( pRequests, nRequests, pControls ); } - virtual FSAsyncStatus_t AsyncReadMultipleCreditAlloc( const FileAsyncRequest_t *pRequests, int nRequests, const char *pszFile, int line, FSAsyncControl_t *pControls ) { return m_pFileSystemPassThru->AsyncReadMultipleCreditAlloc( pRequests, nRequests, pszFile, line, pControls ); } - virtual FSAsyncStatus_t AsyncFinish(FSAsyncControl_t hControl, bool wait) { return m_pFileSystemPassThru->AsyncFinish( hControl, wait ); } - virtual FSAsyncStatus_t AsyncGetResult( FSAsyncControl_t hControl, void **ppData, int *pSize ) { return m_pFileSystemPassThru->AsyncGetResult( hControl, ppData, pSize ); } - virtual FSAsyncStatus_t AsyncAbort(FSAsyncControl_t hControl) { return m_pFileSystemPassThru->AsyncAbort( hControl ); } - virtual FSAsyncStatus_t AsyncStatus(FSAsyncControl_t hControl) { return m_pFileSystemPassThru->AsyncStatus( hControl ); } - virtual FSAsyncStatus_t AsyncFlush() { return m_pFileSystemPassThru->AsyncFlush(); } - virtual void AsyncAddRef( FSAsyncControl_t hControl ) { m_pFileSystemPassThru->AsyncAddRef( hControl ); } - virtual void AsyncRelease( FSAsyncControl_t hControl ) { m_pFileSystemPassThru->AsyncRelease( hControl ); } - virtual FSAsyncStatus_t AsyncBeginRead( const char *pszFile, FSAsyncFile_t *phFile ) { return m_pFileSystemPassThru->AsyncBeginRead( pszFile, phFile ); } - virtual FSAsyncStatus_t AsyncEndRead( FSAsyncFile_t hFile ) { return m_pFileSystemPassThru->AsyncEndRead( hFile ); } - virtual const FileSystemStatistics *GetFilesystemStatistics() { return m_pFileSystemPassThru->GetFilesystemStatistics(); } - virtual WaitForResourcesHandle_t WaitForResources( const char *resourcelist ) { return m_pFileSystemPassThru->WaitForResources( resourcelist ); } - virtual bool GetWaitForResourcesProgress( WaitForResourcesHandle_t handle, - float *progress, bool *complete ) { return m_pFileSystemPassThru->GetWaitForResourcesProgress( handle, progress, complete ); } - virtual void CancelWaitForResources( WaitForResourcesHandle_t handle ) { m_pFileSystemPassThru->CancelWaitForResources( handle ); } - virtual int HintResourceNeed( const char *hintlist, int forgetEverything ) { return m_pFileSystemPassThru->HintResourceNeed( hintlist, forgetEverything ); } - virtual bool IsFileImmediatelyAvailable(const char *pFileName) { return m_pFileSystemPassThru->IsFileImmediatelyAvailable( pFileName ); } - virtual void GetLocalCopy( const char *pFileName ) { m_pFileSystemPassThru->GetLocalCopy( pFileName ); } - virtual FileNameHandle_t FindOrAddFileName( char const *pFileName ) { return m_pFileSystemPassThru->FindOrAddFileName( pFileName ); } - virtual FileNameHandle_t FindFileName( char const *pFileName ) { return m_pFileSystemPassThru->FindFileName( pFileName ); } - virtual bool String( const FileNameHandle_t& handle, char *buf, int buflen ) { return m_pFileSystemPassThru->String( handle, buf, buflen ); } - virtual bool IsOk2( FileHandle_t file ) { return IsOk(file); } - virtual void RemoveSearchPaths( const char *szPathID ) { m_pFileSystemPassThru->RemoveSearchPaths( szPathID ); } - virtual bool IsSteam() const { return m_pFileSystemPassThru->IsSteam(); } - virtual FilesystemMountRetval_t MountSteamContent( int nExtraAppId = -1 ) { return m_pFileSystemPassThru->MountSteamContent( nExtraAppId ); } - - virtual const char *FindFirstEx( - const char *pWildCard, - const char *pPathID, - FileFindHandle_t *pHandle - ) { return m_pFileSystemPassThru->FindFirstEx( pWildCard, pPathID, pHandle ); } - virtual void MarkPathIDByRequestOnly( const char *pPathID, bool bRequestOnly ) { m_pFileSystemPassThru->MarkPathIDByRequestOnly( pPathID, bRequestOnly ); } - virtual bool AddPackFile( const char *fullpath, const char *pathID ) { return m_pFileSystemPassThru->AddPackFile( fullpath, pathID ); } - virtual FSAsyncStatus_t AsyncAppend(const char *pFileName, const void *pSrc, int nSrcBytes, bool bFreeMemory, FSAsyncControl_t *pControl ) { return m_pFileSystemPassThru->AsyncAppend( pFileName, pSrc, nSrcBytes, bFreeMemory, pControl); } - virtual FSAsyncStatus_t AsyncWrite(const char *pFileName, const void *pSrc, int nSrcBytes, bool bFreeMemory, bool bAppend, FSAsyncControl_t *pControl ) { return m_pFileSystemPassThru->AsyncWrite( pFileName, pSrc, nSrcBytes, bFreeMemory, bAppend, pControl); } - virtual FSAsyncStatus_t AsyncWriteFile(const char *pFileName, const CUtlBuffer *pSrc, int nSrcBytes, bool bFreeMemory, bool bAppend, FSAsyncControl_t *pControl ) { return m_pFileSystemPassThru->AsyncWriteFile( pFileName, pSrc, nSrcBytes, bFreeMemory, bAppend, pControl); } - virtual FSAsyncStatus_t AsyncAppendFile(const char *pDestFileName, const char *pSrcFileName, FSAsyncControl_t *pControl ) { return m_pFileSystemPassThru->AsyncAppendFile(pDestFileName, pSrcFileName, pControl); } - virtual void AsyncFinishAll( int iToPriority ) { m_pFileSystemPassThru->AsyncFinishAll(iToPriority); } - virtual void AsyncFinishAllWrites() { m_pFileSystemPassThru->AsyncFinishAllWrites(); } - virtual FSAsyncStatus_t AsyncSetPriority(FSAsyncControl_t hControl, int newPriority) { return m_pFileSystemPassThru->AsyncSetPriority(hControl, newPriority); } - virtual bool AsyncSuspend() { return m_pFileSystemPassThru->AsyncSuspend(); } - virtual bool AsyncResume() { return m_pFileSystemPassThru->AsyncResume(); } - // Next two functions each take an IAsyncFileFetch ptr. - virtual void AsyncAddFetcher( void *pFetch ) { return m_pFileSystemPassThru->AsyncAddFetcher(pFetch); } - virtual void AsyncRemoveFetcher( void *pFetch ) { return m_pFileSystemPassThru->AsyncRemoveFetcher(pFetch); } - virtual const char *RelativePathToFullPath( const char *pFileName, const char *pPathID, char *pLocalPath, int localPathBufferSize, PathTypeFilter_t pathFilter = FILTER_NONE, PathTypeQuery_t *pPathType = NULL ) { return m_pFileSystemPassThru->RelativePathToFullPath( pFileName, pPathID, pLocalPath, localPathBufferSize, pathFilter, pPathType ); } - virtual int GetSearchPath( const char *pathID, bool bGetPackFiles, char *pPath, int nMaxLen ) { return m_pFileSystemPassThru->GetSearchPath( pathID, bGetPackFiles, pPath, nMaxLen ); } - - virtual FileHandle_t OpenEx( const char *pFileName, const char *pOptions, unsigned flags = 0, const char *pathID = 0, char **ppszResolvedFilename = NULL ) { return m_pFileSystemPassThru->OpenEx( pFileName, pOptions, flags, pathID, ppszResolvedFilename );} - virtual int ReadEx( void* pOutput, int destSize, int size, FileHandle_t file ) { return m_pFileSystemPassThru->ReadEx( pOutput, destSize, size, file ); } - virtual int ReadFileEx( const char *pFileName, const char *pPath, void **ppBuf, bool bNullTerminate, bool bOptimalAlloc, int nMaxBytes = 0, int nStartingByte = 0, FSAllocFunc_t pfnAlloc = NULL ) { return m_pFileSystemPassThru->ReadFileEx( pFileName, pPath, ppBuf, bNullTerminate, bOptimalAlloc, nMaxBytes, nStartingByte, pfnAlloc ); } - -#if defined( TRACK_BLOCKING_IO ) - virtual void EnableBlockingFileAccessTracking( bool state ) { m_pFileSystemPassThru->EnableBlockingFileAccessTracking( state ); } - virtual bool IsBlockingFileAccessEnabled() const { return m_pFileSystemPassThru->IsBlockingFileAccessEnabled(); } - - virtual IBlockingFileItemList *RetrieveBlockingFileAccessInfo() { return m_pFileSystemPassThru->RetrieveBlockingFileAccessInfo(); } -#endif - virtual void SetupPreloadData() {} - virtual void DiscardPreloadData() {} - - virtual void LoadCompiledKeyValues( KeyValuesPreloadType_t type, char const *archiveFile ) { m_pFileSystemPassThru->LoadCompiledKeyValues( type, archiveFile ); } - - // If the "PreloadedData" hasn't been purged, then this'll try and instance the KeyValues using the fast path of compiled keyvalues loaded during startup. - // Otherwise, it'll just fall through to the regular KeyValues loading routines - virtual KeyValues *LoadKeyValues( KeyValuesPreloadType_t type, char const *filename, char const *pPathID = 0 ) { return m_pFileSystemPassThru->LoadKeyValues( type, filename, pPathID ); } - virtual bool LoadKeyValues( KeyValues& head, KeyValuesPreloadType_t type, char const *filename, char const *pPathID = 0 ) { return m_pFileSystemPassThru->LoadKeyValues( head, type, filename, pPathID ); } - virtual bool ExtractRootKeyName( KeyValuesPreloadType_t type, char *outbuf, size_t bufsize, char const *filename, char const *pPathID = 0 ) { return m_pFileSystemPassThru->ExtractRootKeyName( type, outbuf, bufsize, filename, pPathID ); } - - virtual bool GetFileTypeForFullPath( char const *pFullPath, wchar_t *buf, size_t bufSizeInBytes ) { return m_pFileSystemPassThru->GetFileTypeForFullPath( pFullPath, buf, bufSizeInBytes ); } - - virtual bool GetOptimalIOConstraints( FileHandle_t hFile, unsigned *pOffsetAlign, unsigned *pSizeAlign, unsigned *pBufferAlign ) { return m_pFileSystemPassThru->GetOptimalIOConstraints( hFile, pOffsetAlign, pSizeAlign, pBufferAlign ); } - virtual void *AllocOptimalReadBuffer( FileHandle_t hFile, unsigned nSize, unsigned nOffset ) { return m_pFileSystemPassThru->AllocOptimalReadBuffer( hFile, nOffset, nSize ); } - virtual void FreeOptimalReadBuffer( void *p ) { m_pFileSystemPassThru->FreeOptimalReadBuffer( p ); } - - virtual void BeginMapAccess() { m_pFileSystemPassThru->BeginMapAccess(); } - virtual void EndMapAccess() { m_pFileSystemPassThru->EndMapAccess(); } - - virtual bool ReadToBuffer( FileHandle_t hFile, CUtlBuffer &buf, int nMaxBytes = 0, FSAllocFunc_t pfnAlloc = NULL ) { return m_pFileSystemPassThru->ReadToBuffer( hFile, buf, nMaxBytes, pfnAlloc ); } - virtual bool FullPathToRelativePathEx( const char *pFullPath, const char *pPathId, char *pRelative, int nMaxLen ) { return m_pFileSystemPassThru->FullPathToRelativePathEx( pFullPath, pPathId, pRelative, nMaxLen ); } - virtual int GetPathIndex( const FileNameHandle_t &handle ) { return m_pFileSystemPassThru->GetPathIndex( handle ); } - virtual long GetPathTime( const char *pPath, const char *pPathID ) { return m_pFileSystemPassThru->GetPathTime( pPath, pPathID ); } - - virtual DVDMode_t GetDVDMode() { return m_pFileSystemPassThru->GetDVDMode(); } - - virtual void EnableWhitelistFileTracking( bool bEnable, bool bCacheAllVPKHashes, bool bRecalculateAndCheckHashes ) - { m_pFileSystemPassThru->EnableWhitelistFileTracking( bEnable, bCacheAllVPKHashes, bRecalculateAndCheckHashes ); } - virtual void RegisterFileWhitelist( IPureServerWhitelist *pPureList, IFileList **pFilesToReload ) - { m_pFileSystemPassThru->RegisterFileWhitelist( pPureList, pFilesToReload ); } - virtual void MarkAllCRCsUnverified() - { m_pFileSystemPassThru->MarkAllCRCsUnverified(); } - virtual void CacheFileCRCs( const char *pPathname, ECacheCRCType eType, IFileList *pFilter ) - { return m_pFileSystemPassThru->CacheFileCRCs( pPathname, eType, pFilter ); } - virtual EFileCRCStatus CheckCachedFileHash( const char *pPathID, const char *pRelativeFilename, int nFileFraction, FileHash_t *pFileHash ) - { return m_pFileSystemPassThru->CheckCachedFileHash( pPathID, pRelativeFilename, nFileFraction, pFileHash ); } - virtual int GetUnverifiedFileHashes( CUnverifiedFileHash *pFiles, int nMaxFiles ) - { return m_pFileSystemPassThru->GetUnverifiedFileHashes( pFiles, nMaxFiles ); } - virtual int GetWhitelistSpewFlags() - { return m_pFileSystemPassThru->GetWhitelistSpewFlags(); } - virtual void SetWhitelistSpewFlags( int spewFlags ) - { m_pFileSystemPassThru->SetWhitelistSpewFlags( spewFlags ); } - virtual void InstallDirtyDiskReportFunc( FSDirtyDiskReportFunc_t func ) { m_pFileSystemPassThru->InstallDirtyDiskReportFunc( func ); } - - // This looks to return a "CFileCacheObject" object. - virtual void *CreateFileCache() - { return m_pFileSystemPassThru->CreateFileCache(); } - - // Assuming that the first param in each of these is also a CFileCacheObject ptr. - virtual void AddFilesToFileCache( void *pFileCache, const char **pszUnk1, int size, const char *szUnk2 ) - { m_pFileSystemPassThru->AddFilesToFileCache( pFileCache, pszUnk1, size, szUnk2 ); } - virtual bool IsFileCacheFileLoaded( void *pFileCache, const char *szFile ) - { return m_pFileSystemPassThru->IsFileCacheFileLoaded( pFileCache, szFile ); } - virtual bool IsFileCacheLoaded( void *pFileCache ) - { return m_pFileSystemPassThru->IsFileCacheLoaded( pFileCache ); } - virtual void DestroyFileCache( void *pFileCache ) - { m_pFileSystemPassThru->DestroyFileCache( pFileCache ); } - - virtual bool RegisterMemoryFile( void *pFile, void **ppExistingFileWithRef ) - { return m_pFileSystemPassThru->RegisterMemoryFile( pFile, ppExistingFileWithRef ); } - virtual void UnregisterMemoryFile( void *pFile ) - { m_pFileSystemPassThru->UnregisterMemoryFile( pFile ); } - - virtual void CacheAllVPKFileHashes( bool bCacheAllVPKHashes, bool bRecalculateAndCheckHashes ) - { m_pFileSystemPassThru->CacheAllVPKFileHashes( bCacheAllVPKHashes, bRecalculateAndCheckHashes ); } - virtual bool CheckVPKFileHash( int PackFileID, int nPackFileNumber, int nFileFraction, MD5Value_t &md5Value ) - { return m_pFileSystemPassThru->CheckVPKFileHash( PackFileID, nPackFileNumber, nFileFraction, md5Value ); } - - virtual void NotifyFileUnloaded( const char *pFileName, const char *pPathId ) - { m_pFileSystemPassThru->NotifyFileUnloaded( pFileName, pPathId ); } - -protected: - IFileSystem *m_pFileSystemPassThru; -}; - - -// This is so people who change the filesystem interface are forced to add the passthru wrapper into CFileSystemPassThru, -// so they don't break VMPI. -inline void GiveMeACompileError() -{ - CFileSystemPassThru asdf; -} - - -#endif // FILESYSTEM_PASSTHRU_H diff --git a/public/g15/ig15.h b/public/g15/ig15.h deleted file mode 100644 index 51b77b70e..000000000 --- a/public/g15/ig15.h +++ /dev/null @@ -1,60 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef IG15_H -#define IG15_H -#ifdef _WIN32 -#pragma once -#endif - -typedef void * G15_HANDLE; - -typedef enum -{ - G15_BUTTON_1, G15_BUTTON_2, G15_BUTTON_3, G15_BUTTON_4 -} G15SoftButton; - -typedef enum -{ - G15_SMALL, G15_MEDIUM, G15_BIG -} G15TextSize; - -typedef enum -{ - G15_SCROLLING_TEXT, G15_STATIC_TEXT, G15_ICON, G15_PROGRESS_BAR, G15_UNKNOWN -} G15ObjectType; - -class IG15 -{ -public: - virtual void GetLCDSize( int &w, int &h ) = 0; - - // w, h should match the return value from GetLCDSize!!! - - // Creates the underlying object - virtual bool Init( char const *name ) = 0; - // Destroys the underlying object - virtual void Shutdown() = 0; - - virtual bool IsConnected() = 0; - - // Add/remove - virtual G15_HANDLE AddText(G15ObjectType type, G15TextSize size, int alignment, int maxLengthPixels) = 0; - virtual G15_HANDLE AddIcon( void *icon, int sizeX, int sizeY) = 0; - virtual void RemoveAndDestroyObject( G15_HANDLE hObject ) = 0; - - // Change - virtual int SetText(G15_HANDLE handle, char const * text) = 0; - virtual int SetOrigin(G15_HANDLE handle, int x, int y) = 0; - virtual int SetVisible(G15_HANDLE handle, bool visible) = 0; - - virtual bool ButtonTriggered(int button) = 0; - virtual void UpdateLCD( unsigned int dwTimestamp) = 0; -}; - -#define G15_INTERFACE_VERSION "G15_INTERFACE_VERSION001" - -#endif // IG15_H diff --git a/public/game/client/IGameClientExports.h b/public/game/client/IGameClientExports.h deleted file mode 100644 index 920185997..000000000 --- a/public/game/client/IGameClientExports.h +++ /dev/null @@ -1,37 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IGAMECLIENTEXPORTS_H -#define IGAMECLIENTEXPORTS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "interface.h" - -//----------------------------------------------------------------------------- -// Purpose: Exports a set of functions for the GameUI interface to interact with the game client -//----------------------------------------------------------------------------- -abstract_class IGameClientExports : public IBaseInterface -{ -public: -#ifndef _XBOX - // ingame voice manipulation - virtual bool IsPlayerGameVoiceMuted(int playerIndex) = 0; - virtual void MutePlayerGameVoice(int playerIndex) = 0; - virtual void UnmutePlayerGameVoice(int playerIndex) = 0; - - // notification of gameui state changes - virtual void OnGameUIActivated() = 0; - virtual void OnGameUIHidden() = 0; -#endif -}; - -#define GAMECLIENTEXPORTS_INTERFACE_VERSION "GameClientExports001" - - -#endif // IGAMECLIENTEXPORTS_H diff --git a/public/game/client/iclientrendertargets.h b/public/game/client/iclientrendertargets.h deleted file mode 100644 index 5b71a56f8..000000000 --- a/public/game/client/iclientrendertargets.h +++ /dev/null @@ -1,41 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Exposes interfaces to the engine which allow the client to setup their own render targets -// during the proper period of material system's init. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ICLIENTRENDERTARGETS_H -#define ICLIENTRENDERTARGETS_H -#ifdef _WIN32 - #pragma once -#endif - -#include "interface.h" // For base interface - -class IMaterialSystem; -class IMaterialSystemHardwareConfig; - -//--------------------------------------------------------------------------------------------------- -// Purpose: Exposes interfaces to the engine which allow the client to setup their own render targets -// during the proper period of material system's init. -//--------------------------------------------------------------------------------------------------- -abstract_class IClientRenderTargets -{ -public: - // Pass the material system interface to the client-- Their Material System singleton has not been created - // at the time they receive this call. - virtual void InitClientRenderTargets( IMaterialSystem* pMaterialSystem, IMaterialSystemHardwareConfig* pHardwareConfig ) = 0; - - // Call shutdown on every created refrence-- Clients keep track of this themselves - // and should add shutdown code to this function whenever they add a new render target. - virtual void ShutdownClientRenderTargets( void ) = 0; - -}; - -#define CLIENTRENDERTARGETS_INTERFACE_VERSION "ClientRenderTargets001" - -extern IClientRenderTargets * g_pClientRenderTargets; - -#endif // ICLIENTRENDERTARGETS_H diff --git a/public/game/client/iviewport.h b/public/game/client/iviewport.h deleted file mode 100644 index e381fc633..000000000 --- a/public/game/client/iviewport.h +++ /dev/null @@ -1,61 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#if !defined( IVIEWPORT_H ) -#define IVIEWPORT_H -#ifdef _WIN32 -#pragma once -#endif - -#include - -#include "viewport_panel_names.h" - -class KeyValues; - -abstract_class IViewPortPanel -{ - -public: - virtual ~IViewPortPanel() {}; - - virtual const char *GetName( void ) = 0;// return identifer name - virtual void SetData(KeyValues *data) = 0; // set ViewPortPanel data - virtual void Reset( void ) = 0; // clears internal state, deactivates it - virtual void Update( void ) = 0; // updates all (size, position, content, etc) - virtual bool NeedsUpdate( void ) = 0; // query panel if content needs to be updated - virtual bool HasInputElements( void ) = 0; // true if panel contains elments which accepts input - - virtual void ShowPanel( bool state ) = 0; // activate VGUI Frame - - // VGUI functions: - virtual vgui::VPANEL GetVPanel( void ) = 0; // returns VGUI panel handle - virtual bool IsVisible() = 0; // true if panel is visible - virtual void SetParent( vgui::VPANEL parent ) = 0; -}; - -abstract_class IViewPort -{ -public: - virtual void UpdateAllPanels( void ) = 0; - virtual void ShowPanel( const char *pName, bool state ) = 0; - virtual void ShowPanel( IViewPortPanel* pPanel, bool state ) = 0; - virtual void ShowBackGround(bool bShow) = 0; - virtual IViewPortPanel* FindPanelByName(const char *szPanelName) = 0; - virtual IViewPortPanel* GetActivePanel( void ) = 0; - virtual void PostMessageToPanel( const char *pName, KeyValues *pKeyValues ) = 0; -}; - -extern IViewPort *gViewPortInterface; - - -#endif // IVIEWPORT_H diff --git a/public/game/server/iplayerinfo.h b/public/game/server/iplayerinfo.h deleted file mode 100644 index 78dc8af11..000000000 --- a/public/game/server/iplayerinfo.h +++ /dev/null @@ -1,194 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: provides an interface for dlls to query information about players from the game dll -// -//=============================================================================// -#ifndef IPLAYERINFO_H -#define IPLAYERINFO_H -#ifdef _WIN32 -#pragma once -#endif - -#include "mathlib/vector.h" - -// helper class for user commands -class CBotCmd -{ -public: - CBotCmd() - { - Reset(); - } - - virtual ~CBotCmd() { }; - - void Reset() - { - command_number = 0; - tick_count = 0; - viewangles.Init(); - forwardmove = 0.0f; - sidemove = 0.0f; - upmove = 0.0f; - buttons = 0; - impulse = 0; - weaponselect = 0; - weaponsubtype = 0; - random_seed = 0; - mousedx = 0; - mousedy = 0; - - hasbeenpredicted = false; - } - - CBotCmd& operator =( const CBotCmd& src ) - { - if ( this == &src ) - return *this; - - command_number = src.command_number; - tick_count = src.tick_count; - viewangles = src.viewangles; - forwardmove = src.forwardmove; - sidemove = src.sidemove; - upmove = src.upmove; - buttons = src.buttons; - impulse = src.impulse; - weaponselect = src.weaponselect; - weaponsubtype = src.weaponsubtype; - random_seed = src.random_seed; - mousedx = src.mousedx; - mousedy = src.mousedy; - hasbeenpredicted = src.hasbeenpredicted; - return *this; - } - - // For matching server and client commands for debugging - int command_number; - - // the tick the client created this command - int tick_count; - - // Player instantaneous view angles. - QAngle viewangles; - // Intended velocities - // forward velocity. - float forwardmove; - // sideways velocity. - float sidemove; - // upward velocity. - float upmove; - // Attack button states - int buttons; - // Impulse command issued. - byte impulse; - // Current weapon id - int weaponselect; - int weaponsubtype; - - int random_seed; // For shared random functions - - short mousedx; // mouse accum in x from create move - short mousedy; // mouse accum in y from create move - - // Client only, tracks whether we've predicted this command at least once - bool hasbeenpredicted; -}; - - - - -abstract_class IPlayerInfo -{ -public: - // returns the players name (UTF-8 encoded) - virtual const char *GetName() = 0; - // returns the userid (slot number) - virtual int GetUserID() = 0; - // returns the string of their network (i.e Steam) ID - virtual const char *GetNetworkIDString() = 0; - // returns the team the player is on - virtual int GetTeamIndex() = 0; - // changes the player to a new team (if the game dll logic allows it) - virtual void ChangeTeam( int iTeamNum ) = 0; - // returns the number of kills this player has (exact meaning is mod dependent) - virtual int GetFragCount() = 0; - // returns the number of deaths this player has (exact meaning is mod dependent) - virtual int GetDeathCount() = 0; - // returns if this player slot is actually valid - virtual bool IsConnected() = 0; - // returns the armor/health of the player (exact meaning is mod dependent) - virtual int GetArmorValue() = 0; - - // extensions added to V2 - - // various player flags - virtual bool IsHLTV() = 0; - virtual bool IsPlayer() = 0; - virtual bool IsFakeClient() = 0; - virtual bool IsDead() = 0; - virtual bool IsInAVehicle() = 0; - virtual bool IsObserver() = 0; - - // player position and size - virtual const Vector GetAbsOrigin() = 0; - virtual const QAngle GetAbsAngles() = 0; - virtual const Vector GetPlayerMins() = 0; - virtual const Vector GetPlayerMaxs() = 0; - // the name of the weapon currently being carried - virtual const char *GetWeaponName() = 0; - // the name of the player model in use - virtual const char *GetModelName() = 0; - // current player health - virtual const int GetHealth() = 0; - // max health value - virtual const int GetMaxHealth() = 0; - // the last user input from this player - virtual CBotCmd GetLastUserCommand() = 0; - virtual bool IsReplay() = 0; -}; - - -#define INTERFACEVERSION_PLAYERINFOMANAGER "PlayerInfoManager002" -abstract_class IPlayerInfoManager -{ -public: - virtual IPlayerInfo *GetPlayerInfo( edict_t *pEdict ) = 0; - virtual CGlobalVars *GetGlobalVars() = 0; -}; - - - - -abstract_class IBotController -{ -public: - // change the bots position - virtual void SetAbsOrigin( Vector & vec ) = 0; - virtual void SetAbsAngles( QAngle & ang ) = 0; - virtual void SetLocalOrigin( const Vector& origin ) = 0; - virtual const Vector GetLocalOrigin( void ) = 0; - virtual void SetLocalAngles( const QAngle& angles ) = 0; - virtual const QAngle GetLocalAngles( void ) = 0; - - // strip them of weapons, etc - virtual void RemoveAllItems( bool removeSuit ) = 0; - // give them a weapon - virtual void SetActiveWeapon( const char *WeaponName ) = 0; - // check various effect flags - virtual bool IsEFlagSet( int nEFlagMask ) = 0; - // fire a virtual move command to the bot - virtual void RunPlayerMove( CBotCmd *ucmd ) = 0; -}; - - -#define INTERFACEVERSION_PLAYERBOTMANAGER "BotManager001" -abstract_class IBotManager -{ -public: - virtual IBotController *GetBotController( edict_t *pEdict ) = 0; - // create a new bot and spawn it into the server - virtual edict_t *CreateBot( const char *botname ) = 0; -}; - -#endif // IPLAYERINFO_H diff --git a/public/gamebspfile.h b/public/gamebspfile.h deleted file mode 100644 index 54aff2a25..000000000 --- a/public/gamebspfile.h +++ /dev/null @@ -1,218 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Defines game-specific data -// -// $Revision: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef GAMEBSPFILE_H -#define GAMEBSPFILE_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "mathlib/vector.h" -#include "basetypes.h" - - -//----------------------------------------------------------------------------- -// This enumerations defines all the four-CC codes for the client lump names -//----------------------------------------------------------------------------- -enum -{ - GAMELUMP_DETAIL_PROPS = 'dprp', - GAMELUMP_DETAIL_PROP_LIGHTING = 'dplt', - GAMELUMP_STATIC_PROPS = 'sprp', - GAMELUMP_DETAIL_PROP_LIGHTING_HDR = 'dplh', -}; - -// Versions... -enum -{ - GAMELUMP_DETAIL_PROPS_VERSION = 4, - GAMELUMP_DETAIL_PROP_LIGHTING_VERSION = 0, - GAMELUMP_STATIC_PROPS_VERSION = 6, - GAMELUMP_STATIC_PROP_LIGHTING_VERSION = 0, - GAMELUMP_DETAIL_PROP_LIGHTING_HDR_VERSION = 0, -}; - - -//----------------------------------------------------------------------------- -// This is the data associated with the GAMELUMP_DETAIL_PROPS lump -//----------------------------------------------------------------------------- -#define DETAIL_NAME_LENGTH 128 - -enum DetailPropOrientation_t -{ - DETAIL_PROP_ORIENT_NORMAL = 0, - DETAIL_PROP_ORIENT_SCREEN_ALIGNED, - DETAIL_PROP_ORIENT_SCREEN_ALIGNED_VERTICAL, -}; - -// NOTE: If DetailPropType_t enum changes, change CDetailModel::QuadsToDraw -// in detailobjectsystem.cpp -enum DetailPropType_t -{ - DETAIL_PROP_TYPE_MODEL = 0, - DETAIL_PROP_TYPE_SPRITE, - DETAIL_PROP_TYPE_SHAPE_CROSS, - DETAIL_PROP_TYPE_SHAPE_TRI, -}; - -//----------------------------------------------------------------------------- -// Model index when using studiomdls for detail props -//----------------------------------------------------------------------------- -struct DetailObjectDictLump_t -{ - DECLARE_BYTESWAP_DATADESC(); - char m_Name[DETAIL_NAME_LENGTH]; // model name -}; - -//----------------------------------------------------------------------------- -// Information about the sprite to render -//----------------------------------------------------------------------------- -struct DetailSpriteDictLump_t -{ - DECLARE_BYTESWAP_DATADESC(); - // NOTE: All detail prop sprites must lie in the material detail/detailsprites - Vector2D m_UL; // Coordinate of upper left - Vector2D m_LR; // Coordinate of lower right - Vector2D m_TexUL; // Texcoords of upper left - Vector2D m_TexLR; // Texcoords of lower left -}; - -struct DetailObjectLump_t -{ - DECLARE_BYTESWAP_DATADESC(); - Vector m_Origin; - QAngle m_Angles; - unsigned short m_DetailModel; // either index into DetailObjectDictLump_t or DetailPropSpriteLump_t - unsigned short m_Leaf; - ColorRGBExp32 m_Lighting; - unsigned int m_LightStyles; - unsigned char m_LightStyleCount; - unsigned char m_SwayAmount; // how much do the details sway - unsigned char m_ShapeAngle; // angle param for shaped sprites - unsigned char m_ShapeSize; // size param for shaped sprites - unsigned char m_Orientation; // See DetailPropOrientation_t - unsigned char m_Padding2[3]; // FIXME: Remove when we rev the detail lump again.. - unsigned char m_Type; // See DetailPropType_t - unsigned char m_Padding3[3]; // FIXME: Remove when we rev the detail lump again.. - float m_flScale; // For sprites only currently -}; - -//----------------------------------------------------------------------------- -// This is the data associated with the GAMELUMP_DETAIL_PROP_LIGHTING lump -//----------------------------------------------------------------------------- -struct DetailPropLightstylesLump_t -{ - DECLARE_BYTESWAP_DATADESC(); - ColorRGBExp32 m_Lighting; - unsigned char m_Style; -}; - -//----------------------------------------------------------------------------- -// This is the data associated with the GAMELUMP_STATIC_PROPS lump -//----------------------------------------------------------------------------- -enum -{ - STATIC_PROP_NAME_LENGTH = 128, - - // Flags field - // These are automatically computed - STATIC_PROP_FLAG_FADES = 0x1, - STATIC_PROP_USE_LIGHTING_ORIGIN = 0x2, - STATIC_PROP_NO_DRAW = 0x4, // computed at run time based on dx level - - // These are set in WC - STATIC_PROP_IGNORE_NORMALS = 0x8, - STATIC_PROP_NO_SHADOW = 0x10, - STATIC_PROP_SCREEN_SPACE_FADE = 0x20, - - STATIC_PROP_NO_PER_VERTEX_LIGHTING = 0x40, // in vrad, compute lighting at - // lighting origin, not for each vertex - - STATIC_PROP_NO_SELF_SHADOWING = 0x80, // disable self shadowing in vrad - - STATIC_PROP_WC_MASK = 0xd8, // all flags settable in hammer (?) -}; - -struct StaticPropDictLump_t -{ - DECLARE_BYTESWAP_DATADESC(); - char m_Name[STATIC_PROP_NAME_LENGTH]; // model name -}; - -struct StaticPropLumpV4_t -{ - DECLARE_BYTESWAP_DATADESC(); - Vector m_Origin; - QAngle m_Angles; - unsigned short m_PropType; - unsigned short m_FirstLeaf; - unsigned short m_LeafCount; - unsigned char m_Solid; - unsigned char m_Flags; - int m_Skin; - float m_FadeMinDist; - float m_FadeMaxDist; - Vector m_LightingOrigin; -// int m_Lighting; // index into the GAMELUMP_STATIC_PROP_LIGHTING lump -}; - -struct StaticPropLumpV5_t -{ - DECLARE_BYTESWAP_DATADESC(); - Vector m_Origin; - QAngle m_Angles; - unsigned short m_PropType; - unsigned short m_FirstLeaf; - unsigned short m_LeafCount; - unsigned char m_Solid; - unsigned char m_Flags; - int m_Skin; - float m_FadeMinDist; - float m_FadeMaxDist; - Vector m_LightingOrigin; - float m_flForcedFadeScale; -// int m_Lighting; // index into the GAMELUMP_STATIC_PROP_LIGHTING lump -}; - -struct StaticPropLump_t -{ - DECLARE_BYTESWAP_DATADESC(); - Vector m_Origin; - QAngle m_Angles; - unsigned short m_PropType; - unsigned short m_FirstLeaf; - unsigned short m_LeafCount; - unsigned char m_Solid; - unsigned char m_Flags; - int m_Skin; - float m_FadeMinDist; - float m_FadeMaxDist; - Vector m_LightingOrigin; - float m_flForcedFadeScale; - unsigned short m_nMinDXLevel; - unsigned short m_nMaxDXLevel; - // int m_Lighting; // index into the GAMELUMP_STATIC_PROP_LIGHTING lump -}; - -struct StaticPropLeafLump_t -{ - DECLARE_BYTESWAP_DATADESC(); - unsigned short m_Leaf; -}; - -//----------------------------------------------------------------------------- -// This is the data associated with the GAMELUMP_STATIC_PROP_LIGHTING lump -//----------------------------------------------------------------------------- -struct StaticPropLightstylesLump_t -{ - ColorRGBExp32 m_Lighting; -}; - -#endif // GAMEBSPFILE_H diff --git a/public/gametrace.h b/public/gametrace.h deleted file mode 100644 index 6570fd9a0..000000000 --- a/public/gametrace.h +++ /dev/null @@ -1,176 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef GAMETRACE_H -#define GAMETRACE_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "cmodel.h" -#include "utlvector.h" -#include "ihandleentity.h" -#include "ispatialpartition.h" - -#if defined( CLIENT_DLL ) - class C_BaseEntity; -#else - class CBaseEntity; -#endif - - -//----------------------------------------------------------------------------- -// Purpose: A trace is returned when a box is swept through the world -// NOTE: eventually more of this class should be moved up into the base class!! -//----------------------------------------------------------------------------- -class CGameTrace : public CBaseTrace -{ -public: - - // Returns true if hEnt points at the world entity. - // If this returns true, then you can't use GetHitBoxIndex(). - bool DidHitWorld() const; - - // Returns true if we hit something and it wasn't the world. - bool DidHitNonWorldEntity() const; - - // Gets the entity's network index if the trace has hit an entity. - // If not, returns -1. - int GetEntityIndex() const; - - // Returns true if there was any kind of impact at all - bool DidHit() const; - - // The engine doesn't know what a CBaseEntity is, so it has a backdoor to - // let it get at the edict. -#if defined( ENGINE_DLL ) - void SetEdict( edict_t *pEdict ); - edict_t* GetEdict() const; -#endif - - -public: - - float fractionleftsolid; // time we left a solid, only valid if we started in solid - csurface_t surface; // surface hit (impact surface) - - int hitgroup; // 0 == generic, non-zero is specific body part - short physicsbone; // physics bone hit by trace in studio - -#if defined( CLIENT_DLL ) - C_BaseEntity *m_pEnt; -#else - CBaseEntity *m_pEnt; -#endif - - // NOTE: this member is overloaded. - // If hEnt points at the world entity, then this is the static prop index. - // Otherwise, this is the hitbox index. - int hitbox; // box hit by trace in studio - - CGameTrace() {} - -private: - // No copy constructors allowed - CGameTrace(const CGameTrace& vOther); -}; - - -//----------------------------------------------------------------------------- -// Returns true if there was any kind of impact at all -//----------------------------------------------------------------------------- -inline bool CGameTrace::DidHit() const -{ - return fraction < 1 || allsolid || startsolid; -} - - -typedef CGameTrace trace_t; - -//============================================================================= - -#define TLD_DEF_LEAF_MAX 256 -#define TLD_DEF_ENTITY_MAX 1024 - -class CTraceListData : public IPartitionEnumerator -{ -public: - - CTraceListData( int nLeafMax = TLD_DEF_LEAF_MAX, int nEntityMax = TLD_DEF_ENTITY_MAX ) - { - MEM_ALLOC_CREDIT(); - m_nLeafCount = 0; - m_aLeafList.SetSize( nLeafMax ); - - m_nEntityCount = 0; - m_aEntityList.SetSize( nEntityMax ); - } - - ~CTraceListData() - { - m_nLeafCount = 0; - m_aLeafList.RemoveAll(); - - m_nEntityCount = 0; - m_aEntityList.RemoveAll(); - } - - void Reset( void ) - { - m_nLeafCount = 0; - m_nEntityCount = 0; - } - - bool IsEmpty( void ) const { return ( m_nLeafCount == 0 && m_nEntityCount == 0 ); } - - int LeafCount( void ) const { return m_nLeafCount; } - int LeafCountMax( void ) const { return m_aLeafList.Count(); } - void LeafCountReset( void ) { m_nLeafCount = 0; } - - int EntityCount( void ) const { return m_nEntityCount; } - int EntityCountMax( void ) const { return m_aEntityList.Count(); } - void EntityCountReset( void ) { m_nEntityCount = 0; } - - // For leaves... - void AddLeaf( int iLeaf ) - { - if ( m_nLeafCount >= m_aLeafList.Count() ) - { - DevMsg( "CTraceListData: Max leaf count along ray exceeded!\n" ); - m_aLeafList.AddMultipleToTail( m_aLeafList.Count() ); - } - - m_aLeafList[m_nLeafCount] = iLeaf; - m_nLeafCount++; - } - - // For entities... - IterationRetval_t EnumElement( IHandleEntity *pHandleEntity ) - { - if ( m_nEntityCount >= m_aEntityList.Count() ) - { - DevMsg( "CTraceListData: Max entity count along ray exceeded!\n" ); - m_aEntityList.AddMultipleToTail( m_aEntityList.Count() ); - } - - m_aEntityList[m_nEntityCount] = pHandleEntity; - m_nEntityCount++; - - return ITERATION_CONTINUE; - } - -public: - - int m_nLeafCount; - CUtlVector m_aLeafList; - - int m_nEntityCount; - CUtlVector m_aEntityList; -}; - -#endif // GAMETRACE_H - diff --git a/public/globalvars_base.h b/public/globalvars_base.h deleted file mode 100644 index 82902ccd8..000000000 --- a/public/globalvars_base.h +++ /dev/null @@ -1,109 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef GLOBALVARS_BASE_H -#define GLOBALVARS_BASE_H - -#ifdef _WIN32 -#pragma once -#endif - -class CSaveRestoreData; - -//----------------------------------------------------------------------------- -// Purpose: Global variables used by shared code -//----------------------------------------------------------------------------- -class CGlobalVarsBase -{ -public: - - CGlobalVarsBase( bool bIsClient ); - - // This can be used to filter debug output or to catch the client or server in the act. - bool IsClient() const; - - // for encoding m_flSimulationTime, m_flAnimTime - int GetNetworkBase( int nTick, int nEntity ); - -public: - - // Absolute time (per frame still - Use Plat_FloatTime() for a high precision real time - // perf clock, but not that it doesn't obey host_timescale/host_framerate) - float realtime; - // Absolute frame counter - int framecount; - // Non-paused frametime - float absoluteframetime; - - // Current time - // - // On the client, this (along with tickcount) takes a different meaning based on what - // piece of code you're in: - // - // - While receiving network packets (like in PreDataUpdate/PostDataUpdate and proxies), - // this is set to the SERVER TICKCOUNT for that packet. There is no interval between - // the server ticks. - // [server_current_Tick * tick_interval] - // - // - While rendering, this is the exact client clock - // [client_current_tick * tick_interval + interpolation_amount] - // - // - During prediction, this is based on the client's current tick: - // [client_current_tick * tick_interval] - float curtime; - - // Time spent on last server or client frame (has nothing to do with think intervals) - float frametime; - // current maxplayers setting - int maxClients; - - // Simulation ticks - int tickcount; - - // Simulation tick interval - float interval_per_tick; - - // interpolation amount ( client-only ) based on fraction of next tick which has elapsed - float interpolation_amount; - int simTicksThisFrame; - - int network_protocol; - - // current saverestore data - CSaveRestoreData *pSaveData; - -private: - // Set to true in client code. - bool m_bClient; - - // 100 (i.e., tickcount is rounded down to this base and then the "delta" from this base is networked - int nTimestampNetworkingBase; - // 32 (entindex() % nTimestampRandomizeWindow ) is subtracted from gpGlobals->tickcount to set the networking basis, prevents - // all of the entities from forcing a new PackedEntity on the same tick (i.e., prevents them from getting lockstepped on this) - int nTimestampRandomizeWindow; - -}; - -inline int CGlobalVarsBase::GetNetworkBase( int nTick, int nEntity ) -{ - int nEntityMod = nEntity % nTimestampRandomizeWindow; - int nBaseTick = nTimestampNetworkingBase * (int)( ( nTick - nEntityMod ) / nTimestampNetworkingBase ); - return nBaseTick; -} - -inline CGlobalVarsBase::CGlobalVarsBase( bool bIsClient ) : - m_bClient( bIsClient ), - nTimestampNetworkingBase( 100 ), - nTimestampRandomizeWindow( 32 ) -{ -} - -inline bool CGlobalVarsBase::IsClient() const -{ - return m_bClient; -} - -#endif // GLOBALVARS_BASE_H diff --git a/public/iachievementmgr.h b/public/iachievementmgr.h deleted file mode 100644 index 58e77086c..000000000 --- a/public/iachievementmgr.h +++ /dev/null @@ -1,76 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#ifndef IACHIEVEMENTMGR_H -#define IACHIEVEMENTMGR_H -#ifdef _WIN32 -#pragma once -#endif - -#include "utlmap.h" - -class CBaseAchievement; - -abstract_class IAchievement -{ -public: - virtual int GetAchievementID() = 0; - virtual const char *GetName() = 0; - virtual int GetFlags() = 0; - virtual int GetGoal() = 0; - virtual int GetCount() = 0; - virtual bool IsAchieved() = 0; - virtual int GetPointValue() = 0; - virtual bool ShouldSaveWithGame() = 0; - virtual bool ShouldHideUntilAchieved() = 0; -}; - - -abstract_class IAchievementMgr -{ -public: - virtual IAchievement* GetAchievementByIndex( int index ) = 0; - virtual CBaseAchievement* GetAchievementByID ( int id ) = 0; - virtual int GetAchievementCount() = 0; - virtual void InitializeAchievements() = 0; - virtual void AwardAchievement( int iAchievementID ) = 0; - virtual void OnMapEvent( const char *pchEventName ) = 0; - virtual void DownloadUserData() = 0; - virtual void EnsureGlobalStateLoaded() = 0; - virtual void SaveGlobalStateIfDirty( bool bAsync ) = 0; -}; - -// flags for IAchievement::GetFlags - -#define ACH_LISTEN_KILL_EVENTS 0x0001 -#define ACH_LISTEN_MAP_EVENTS 0x0002 -#define ACH_LISTEN_COMPONENT_EVENTS 0x0004 -#define ACH_HAS_COMPONENTS 0x0020 -#define ACH_SAVE_WITH_GAME 0x0040 -#define ACH_SAVE_GLOBAL 0x0080 -#define ACH_FILTER_ATTACKER_IS_PLAYER 0x0100 -#define ACH_FILTER_VICTIM_IS_PLAYER_ENEMY 0x0200 -#define ACH_FILTER_FULL_ROUND_ONLY 0x0400 - -#define ACH_LISTEN_PLAYER_KILL_ENEMY_EVENTS ACH_LISTEN_KILL_EVENTS | ACH_FILTER_ATTACKER_IS_PLAYER | ACH_FILTER_VICTIM_IS_PLAYER_ENEMY -#define ACH_LISTEN_KILL_ENEMY_EVENTS ACH_LISTEN_KILL_EVENTS | ACH_FILTER_VICTIM_IS_PLAYER_ENEMY - -// Update this for changes in either abstract class in this file -#define ACHIEVEMENTMGR_INTERFACE_VERSION "ACHIEVEMENTMGR_INTERFACE_VERSION001" - -#define ACHIEVEMENT_LOCALIZED_NAME_FROM_STR( name ) \ - ( g_pVGuiLocalize->Find( CFmtStr( "#%s_NAME", name ) ) ) - -#define ACHIEVEMENT_LOCALIZED_NAME( pAchievement ) \ - ( ACHIEVEMENT_LOCALIZED_NAME_FROM_STR( pAchievement->GetName() ) ) - -#define ACHIEVEMENT_LOCALIZED_DESC_FROM_STR( name ) \ - ( g_pVGuiLocalize->Find( CFmtStr( "#%s_DESC", name ) ) ) - -#define ACHIEVEMENT_LOCALIZED_DESC( pAchievement ) \ - ( ACHIEVEMENT_LOCALIZED_DESC_FROM_STR( pAchievement->GetName() ) ) - -#endif // IACHIEVEMENTMGR_H diff --git a/public/ibsppack.h b/public/ibsppack.h deleted file mode 100644 index 9337da4db..000000000 --- a/public/ibsppack.h +++ /dev/null @@ -1,41 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IBSPPACK_H -#define IBSPPACK_H -#ifdef _WIN32 -#pragma once -#endif - -#include "interface.h" -#include "utlvector.h" -#include "utlstring.h" - -class IFileSystem; - -abstract_class IBSPPack -{ -public: - virtual void LoadBSPFile( IFileSystem *pFileSystem, char *filename ) = 0; - virtual void WriteBSPFile( char *filename ) = 0; - virtual void ClearPackFile( void ) = 0; - virtual void AddFileToPack( const char *relativename, const char *fullpath ) = 0; - virtual void AddBufferToPack( const char *relativename, void *data, int length, bool bTextMode ) = 0; - virtual void SetHDRMode( bool bHDR ) = 0; - virtual bool SwapBSPFile( IFileSystem *pFileSystem, const char *filename, const char *swapFilename, bool bSwapOnLoad, VTFConvertFunc_t pVTFConvertFunc, VHVFixupFunc_t pVHVFixupFunc, CompressFunc_t pCompressFunc ) = 0; - - // used to get/set the pak file from a BSP - virtual bool GetPakFileLump( IFileSystem *pFileSystem, const char *pBSPFilename, void **pPakData, int *pPakSize ) = 0; - virtual bool SetPakFileLump( IFileSystem *pFileSystem, const char *pBSPFilename, const char *pNewFilename, void *pPakData, int pakSize ) = 0; - - // populates list of files that bsp owns, i.e. world/cubmap materials, statis props, etc - virtual bool GetBSPDependants( IFileSystem *pFileSystem, const char *pBSPFilename, CUtlVector< CUtlString > *pList ) = 0; -}; - -#define IBSPPACK_VERSION_STRING "IBSPPACK003" - -#endif // IBSPPACK_H diff --git a/public/iclient.h b/public/iclient.h deleted file mode 100644 index 0d0e2e3c1..000000000 --- a/public/iclient.h +++ /dev/null @@ -1,87 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ICLIENT_H -#define ICLIENT_H -#ifdef _WIN32 -#pragma once -#endif - -#include -#include "tier0/platform.h" - -class IServer; -class INetMessage; -struct USERID_t; - -abstract_class IClient : public INetChannelHandler -{ -public: - virtual ~IClient() {} - - // connect client - virtual void Connect(const char * szName, int nUserID, INetChannel *pNetChannel, bool bFakePlayer, int unknown1) = 0; - - // set the client in a pending state waiting for a new game - virtual void Inactivate( void ) = 0; - - // Reconnect without dropiing the netchannel - virtual void Reconnect( void ) = 0; // froce reconnect - - // disconnects a client with a given reason - virtual void Disconnect( const char *reason, ... ) = 0; - - virtual int GetPlayerSlot() const = 0; // returns client slot (usually entity number-1) - virtual int GetUserID() const = 0; // unique ID on this server - virtual const USERID_t GetNetworkID() const = 0; // network wide ID - virtual const char *GetClientName() const = 0; // returns client name - virtual INetChannel *GetNetChannel() = 0; // returns client netchannel - virtual IServer *GetServer() = 0; // returns the object server the client belongs to - virtual const char *GetUserSetting(const char *cvar) const = 0; // returns a clients FCVAR_USERINFO setting - virtual const char *GetNetworkIDString() const = 0; // returns a human readable representation of the network id - - // set/get client data rate in bytes/second - virtual void SetRate( int nRate, bool bForce ) = 0; - virtual int GetRate( void ) const = 0; - - // set/get updates/second rate - virtual void SetUpdateRate( int nUpdateRate, bool bForce ) = 0; - virtual int GetUpdateRate( void ) const = 0; - - // clear complete object & free all memory - virtual void Clear( void ) = 0; - - // returns the highest world tick number acknowledge by client - virtual int GetMaxAckTickCount() const = 0; - - // execute a client command - virtual bool ExecuteStringCommand( const char *s ) = 0; - // send client a network message - virtual bool SendNetMsg(INetMessage &msg, bool bForceReliable = false) = 0; - // send client a text message - virtual void ClientPrintf (const char *fmt, ...) = 0; - - // client has established network channels, nothing else - virtual bool IsConnected( void ) const = 0; - // client is downloading signon data - virtual bool IsSpawned( void ) const = 0; - // client active is ingame, receiving snapshots - virtual bool IsActive( void ) const = 0; - // returns true, if client is not a real player - virtual bool IsFakeClient( void ) const = 0; - // returns true, if client is a HLTV proxy - virtual bool IsHLTV( void ) const = 0; - virtual bool IsReplay( void ) const = 0; - - // returns true, if client hears this player - virtual bool IsHearingClient(int index) const = 0; - // returns true, if client hears this player by proximity - virtual bool IsProximityHearingClient(int index) const = 0; - - virtual void SetMaxRoutablePayloadSize( int nMaxRoutablePayloadSize ) = 0; -}; - -#endif // ICLIENT_H diff --git a/public/icliententity.h b/public/icliententity.h deleted file mode 100644 index 04dbb7ec7..000000000 --- a/public/icliententity.h +++ /dev/null @@ -1,48 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ICLIENTENTITY_H -#define ICLIENTENTITY_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "iclientrenderable.h" -#include "iclientnetworkable.h" -#include "iclientthinkable.h" - -struct Ray_t; -class CGameTrace; -typedef CGameTrace trace_t; -class CMouthInfo; -class IClientEntityInternal; -struct SpatializationInfo_t; - - -//----------------------------------------------------------------------------- -// Purpose: All client entities must implement this interface. -//----------------------------------------------------------------------------- -abstract_class IClientEntity : public IClientUnknown, public IClientRenderable, public IClientNetworkable, public IClientThinkable -{ -public: - // Delete yourself. - virtual void Release( void ) = 0; - - // Network origin + angles - virtual const Vector& GetAbsOrigin( void ) const = 0; - virtual const QAngle& GetAbsAngles( void ) const = 0; - - virtual CMouthInfo *GetMouth( void ) = 0; - - // Retrieve sound spatialization info for the specified sound on this entity - // Return false to indicate sound is not audible - virtual bool GetSoundSpatialization( SpatializationInfo_t& info ) = 0; -}; - - -#endif // ICLIENTENTITY_H diff --git a/public/icliententitylist.h b/public/icliententitylist.h deleted file mode 100644 index 7f7f20b2b..000000000 --- a/public/icliententitylist.h +++ /dev/null @@ -1,56 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// -#if !defined( ICLIENTENTITYLIST_H ) -#define ICLIENTENTITYLIST_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "interface.h" - -class IClientEntity; -class ClientClass; -class IClientNetworkable; -class CBaseHandle; -class IClientUnknown; - - -//----------------------------------------------------------------------------- -// Purpose: Exposes IClientEntity's to engine -//----------------------------------------------------------------------------- -abstract_class IClientEntityList -{ -public: - // Get IClientNetworkable interface for specified entity - virtual IClientNetworkable* GetClientNetworkable( int entnum ) = 0; - virtual IClientNetworkable* GetClientNetworkableFromHandle( CBaseHandle hEnt ) = 0; - virtual IClientUnknown* GetClientUnknownFromHandle( CBaseHandle hEnt ) = 0; - - // NOTE: This function is only a convenience wrapper. - // It returns GetClientNetworkable( entnum )->GetIClientEntity(). - virtual IClientEntity* GetClientEntity( int entnum ) = 0; - virtual IClientEntity* GetClientEntityFromHandle( CBaseHandle hEnt ) = 0; - - // Returns number of entities currently in use - virtual int NumberOfEntities( bool bIncludeNonNetworkable ) = 0; - - // Returns highest index actually used - virtual int GetHighestEntityIndex( void ) = 0; - - // Sizes entity list to specified size - virtual void SetMaxEntities( int maxents ) = 0; - virtual int GetMaxEntities( ) = 0; -}; - -extern IClientEntityList *entitylist; - -#define VCLIENTENTITYLIST_INTERFACE_VERSION "VClientEntityList003" - -#endif // ICLIENTENTITYLIST_H diff --git a/public/iclientnetworkable.h b/public/iclientnetworkable.h deleted file mode 100644 index be8fac940..000000000 --- a/public/iclientnetworkable.h +++ /dev/null @@ -1,105 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ICLIENTNETWORKABLE_H -#define ICLIENTNETWORKABLE_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "iclientunknown.h" -#include "tier1/bitbuf.h" - - -class IClientEntity; -class ClientClass; - - -enum ShouldTransmitState_t -{ - SHOULDTRANSMIT_START=0, // The entity is starting to be transmitted (maybe it entered the PVS). - - SHOULDTRANSMIT_END // Called when the entity isn't being transmitted by the server. - // This signals a good time to hide the entity until next time - // the server wants to transmit its state. -}; - -// NOTE: All of these are commented out; NotifyShouldTransmit actually -// has all these in them. Left it as an enum in case we want to go back though -enum DataUpdateType_t -{ - DATA_UPDATE_CREATED = 0, // indicates it was created +and+ entered the pvs -// DATA_UPDATE_ENTERED_PVS, - DATA_UPDATE_DATATABLE_CHANGED, -// DATA_UPDATE_LEFT_PVS, -// DATA_UPDATE_DESTROYED, // FIXME: Could enable this, but it's a little worrying - // since it changes a bunch of existing code -}; - -abstract_class IClientNetworkable -{ -public: - // Gets at the containing class... - virtual IClientUnknown* GetIClientUnknown() = 0; - - // Called by the engine when the server deletes the entity. - virtual void Release() = 0; - - // Supplied automatically by the IMPLEMENT_CLIENTCLASS macros. - virtual ClientClass* GetClientClass() = 0; - - // This tells the entity what the server says for ShouldTransmit on this entity. - // Note: This used to be EntityEnteredPVS/EntityRemainedInPVS/EntityLeftPVS. - virtual void NotifyShouldTransmit( ShouldTransmitState_t state ) = 0; - - - - // - // NOTE FOR ENTITY WRITERS: - // - // In 90% of the cases, you should hook OnPreDataChanged/OnDataChanged instead of - // PreDataUpdate/PostDataUpdate. - // - // The DataChanged events are only called once per frame whereas Pre/PostDataUpdate - // are called once per packet (and sometimes multiple times per frame). - // - // OnDataChanged is called during simulation where entity origins are correct and - // attachments can be used. whereas PostDataUpdate is called while parsing packets - // so attachments and other entity origins may not be valid yet. - // - - virtual void OnPreDataChanged( DataUpdateType_t updateType ) = 0; - virtual void OnDataChanged( DataUpdateType_t updateType ) = 0; - - // Called when data is being updated across the network. - // Only low-level entities should need to know about these. - virtual void PreDataUpdate( DataUpdateType_t updateType ) = 0; - virtual void PostDataUpdate( DataUpdateType_t updateType ) = 0; - - - // Objects become dormant on the client if they leave the PVS on the server. - virtual bool IsDormant( void ) = 0; - - // Ent Index is the server handle used to reference this entity. - // If the index is < 0, that indicates the entity is not known to the server - virtual int entindex( void ) const = 0; - - // Server to client entity message received - virtual void ReceiveMessage( int classID, bf_read &msg ) = 0; - - // Get the base pointer to the networked data that GetClientClass->m_pRecvTable starts at. - // (This is usually just the "this" pointer). - virtual void* GetDataTableBasePtr() = 0; - - // Tells the entity that it's about to be destroyed due to the client receiving - // an uncompressed update that's caused it to destroy all entities & recreate them. - virtual void SetDestroyedOnRecreateEntities( void ) = 0; -}; - - -#endif // ICLIENTNETWORKABLE_H diff --git a/public/iclientrenderable.h b/public/iclientrenderable.h deleted file mode 100644 index 5926e8a31..000000000 --- a/public/iclientrenderable.h +++ /dev/null @@ -1,279 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef ICLIENTRENDERABLE_H -#define ICLIENTRENDERABLE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "mathlib/mathlib.h" -#include "interface.h" -#include "iclientunknown.h" -#include "client_render_handle.h" -#include "engine/ivmodelrender.h" - -struct model_t; -struct matrix3x4_t; - -extern void DefaultRenderBoundsWorldspace( IClientRenderable *pRenderable, Vector &absMins, Vector &absMaxs ); - -//----------------------------------------------------------------------------- -// Handles to a client shadow -//----------------------------------------------------------------------------- -typedef unsigned short ClientShadowHandle_t; - -enum -{ - CLIENTSHADOW_INVALID_HANDLE = (ClientShadowHandle_t)~0 -}; - -//----------------------------------------------------------------------------- -// What kind of shadows to render? -//----------------------------------------------------------------------------- -enum ShadowType_t -{ - SHADOWS_NONE = 0, - SHADOWS_SIMPLE, - SHADOWS_RENDER_TO_TEXTURE, - SHADOWS_RENDER_TO_TEXTURE_DYNAMIC, // the shadow is always changing state - SHADOWS_RENDER_TO_DEPTH_TEXTURE, -}; - - -// This provides a way for entities to know when they've entered or left the PVS. -// Normally, server entities can use NotifyShouldTransmit to get this info, but client-only -// entities can use this. Store a CPVSNotifyInfo in your -// -// When bInPVS=true, it's being called DURING rendering. It might be after rendering any -// number of views. -// -// If no views had the entity, then it is called with bInPVS=false after rendering. -abstract_class IPVSNotify -{ -public: - virtual void OnPVSStatusChanged( bool bInPVS ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Purpose: All client entities must implement this interface. -//----------------------------------------------------------------------------- -abstract_class IClientRenderable -{ -public: - // Gets at the containing class... - virtual IClientUnknown* GetIClientUnknown() = 0; - - // Data accessors - virtual Vector const& GetRenderOrigin( void ) = 0; - virtual QAngle const& GetRenderAngles( void ) = 0; - virtual bool ShouldDraw( void ) = 0; - virtual bool IsTransparent( void ) = 0; - virtual bool UsesPowerOfTwoFrameBufferTexture() = 0; - virtual bool UsesFullFrameBufferTexture() = 0; - - virtual ClientShadowHandle_t GetShadowHandle() const = 0; - - // Used by the leaf system to store its render handle. - virtual ClientRenderHandle_t& RenderHandle() = 0; - - // Render baby! - virtual const model_t* GetModel( ) const = 0; - virtual int DrawModel( int flags ) = 0; - - // Get the body parameter - virtual int GetBody() = 0; - - // Determine alpha and blend amount for transparent objects based on render state info - virtual void ComputeFxBlend( ) = 0; - virtual int GetFxBlend( void ) = 0; - - // Determine the color modulation amount - virtual void GetColorModulation( float* color ) = 0; - - // Returns false if the entity shouldn't be drawn due to LOD. - // (NOTE: This is no longer used/supported, but kept in the vtable for backwards compat) - virtual bool LODTest() = 0; - - // Call this to get the current bone transforms for the model. - // currentTime parameter will affect interpolation - // nMaxBones specifies how many matrices pBoneToWorldOut can hold. (Should be greater than or - // equal to studiohdr_t::numbones. Use MAXSTUDIOBONES to be safe.) - virtual bool SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, int boneMask, float currentTime ) = 0; - - virtual void SetupWeights( const matrix3x4_t *pBoneToWorld, int nFlexWeightCount, float *pFlexWeights, float *pFlexDelayedWeights ) = 0; - virtual void DoAnimationEvents( void ) = 0; - - // Return this if you want PVS notifications. See IPVSNotify for more info. - // Note: you must always return the same value from this function. If you don't, - // undefined things will occur, and they won't be good. - virtual IPVSNotify* GetPVSNotifyInterface() = 0; - - // Returns the bounds relative to the origin (render bounds) - virtual void GetRenderBounds( Vector& mins, Vector& maxs ) = 0; - - // returns the bounds as an AABB in worldspace - virtual void GetRenderBoundsWorldspace( Vector& mins, Vector& maxs ) = 0; - - // These normally call through to GetRenderAngles/GetRenderBounds, but some entities custom implement them. - virtual void GetShadowRenderBounds( Vector &mins, Vector &maxs, ShadowType_t shadowType ) = 0; - - // Should this object be able to have shadows cast onto it? - virtual bool ShouldReceiveProjectedTextures( int flags ) = 0; - - // These methods return true if we want a per-renderable shadow cast direction + distance - virtual bool GetShadowCastDistance( float *pDist, ShadowType_t shadowType ) const = 0; - virtual bool GetShadowCastDirection( Vector *pDirection, ShadowType_t shadowType ) const = 0; - - // Other methods related to shadow rendering - virtual bool IsShadowDirty( ) = 0; - virtual void MarkShadowDirty( bool bDirty ) = 0; - - // Iteration over shadow hierarchy - virtual IClientRenderable *GetShadowParent() = 0; - virtual IClientRenderable *FirstShadowChild() = 0; - virtual IClientRenderable *NextShadowPeer() = 0; - - // Returns the shadow cast type - virtual ShadowType_t ShadowCastType() = 0; - - // Create/get/destroy model instance - virtual void CreateModelInstance() = 0; - virtual ModelInstanceHandle_t GetModelInstance() = 0; - - // Returns the transform from RenderOrigin/RenderAngles to world - virtual const matrix3x4_t &RenderableToWorldTransform() = 0; - - // Attachments - virtual int LookupAttachment( const char *pAttachmentName ) = 0; - virtual bool GetAttachment( int number, Vector &origin, QAngle &angles ) = 0; - virtual bool GetAttachment( int number, matrix3x4_t &matrix ) = 0; - - // Rendering clip plane, should be 4 floats, return value of NULL indicates a disabled render clip plane - virtual float *GetRenderClipPlane( void ) = 0; - - // Get the skin parameter - virtual int GetSkin() = 0; - - // Is this a two-pass renderable? - virtual bool IsTwoPass( void ) = 0; - - virtual void OnThreadedDrawSetup() = 0; - - virtual bool UsesFlexDelayedWeights() = 0; - - virtual void RecordToolMessage() = 0; -}; - - -// This class can be used to implement default versions of some of the -// functions of IClientRenderable. -abstract_class CDefaultClientRenderable : public IClientUnknown, public IClientRenderable -{ -public: - CDefaultClientRenderable() - { - m_hRenderHandle = INVALID_CLIENT_RENDER_HANDLE; - } - - virtual const Vector & GetRenderOrigin( void ) = 0; - virtual const QAngle & GetRenderAngles( void ) = 0; - virtual const matrix3x4_t & RenderableToWorldTransform() = 0; - virtual bool ShouldDraw( void ) = 0; - virtual bool IsTransparent( void ) = 0; - virtual bool IsTwoPass( void ) { return false; } - virtual void OnThreadedDrawSetup() {} - virtual bool UsesPowerOfTwoFrameBufferTexture( void ) { return false; } - virtual bool UsesFullFrameBufferTexture( void ) { return false; } - - virtual ClientShadowHandle_t GetShadowHandle() const - { - return CLIENTSHADOW_INVALID_HANDLE; - } - - virtual ClientRenderHandle_t& RenderHandle() - { - return m_hRenderHandle; - } - - virtual int GetBody() { return 0; } - virtual int GetSkin() { return 0; } - virtual bool UsesFlexDelayedWeights() { return false; } - - virtual const model_t* GetModel( ) const { return NULL; } - virtual int DrawModel( int flags ) { return 0; } - virtual void ComputeFxBlend( ) { return; } - virtual int GetFxBlend( ) { return 255; } - virtual bool LODTest() { return true; } - virtual bool SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, int boneMask, float currentTime ) { return true; } - virtual void SetupWeights( const matrix3x4_t *pBoneToWorld, int nFlexWeightCount, float *pFlexWeights, float *pFlexDelayedWeights ) {} - virtual void DoAnimationEvents( void ) {} - virtual IPVSNotify* GetPVSNotifyInterface() { return NULL; } - virtual void GetRenderBoundsWorldspace( Vector& absMins, Vector& absMaxs ) { DefaultRenderBoundsWorldspace( this, absMins, absMaxs ); } - - // Determine the color modulation amount - virtual void GetColorModulation( float* color ) - { - Assert(color); - color[0] = color[1] = color[2] = 1.0f; - } - - // Should this object be able to have shadows cast onto it? - virtual bool ShouldReceiveProjectedTextures( int flags ) - { - return false; - } - - // These methods return true if we want a per-renderable shadow cast direction + distance - virtual bool GetShadowCastDistance( float *pDist, ShadowType_t shadowType ) const { return false; } - virtual bool GetShadowCastDirection( Vector *pDirection, ShadowType_t shadowType ) const { return false; } - - virtual void GetShadowRenderBounds( Vector &mins, Vector &maxs, ShadowType_t shadowType ) - { - GetRenderBounds( mins, maxs ); - } - - virtual bool IsShadowDirty( ) { return false; } - virtual void MarkShadowDirty( bool bDirty ) {} - virtual IClientRenderable *GetShadowParent() { return NULL; } - virtual IClientRenderable *FirstShadowChild(){ return NULL; } - virtual IClientRenderable *NextShadowPeer() { return NULL; } - virtual ShadowType_t ShadowCastType() { return SHADOWS_NONE; } - virtual void CreateModelInstance() {} - virtual ModelInstanceHandle_t GetModelInstance() { return MODEL_INSTANCE_INVALID; } - - // Attachments - virtual int LookupAttachment( const char *pAttachmentName ) { return -1; } - virtual bool GetAttachment( int number, Vector &origin, QAngle &angles ) { return false; } - virtual bool GetAttachment( int number, matrix3x4_t &matrix ) { return false; } - - // Rendering clip plane, should be 4 floats, return value of NULL indicates a disabled render clip plane - virtual float *GetRenderClipPlane() { return NULL; } - - virtual void RecordToolMessage() {} - -// IClientUnknown implementation. -public: - virtual void SetRefEHandle( const CBaseHandle &handle ) { Assert( false ); } - virtual const CBaseHandle& GetRefEHandle() const { Assert( false ); return *((CBaseHandle*)0); } - - virtual IClientUnknown* GetIClientUnknown() { return this; } - virtual ICollideable* GetCollideable() { return 0; } - virtual IClientRenderable* GetClientRenderable() { return this; } - virtual IClientNetworkable* GetClientNetworkable() { return 0; } - virtual IClientEntity* GetIClientEntity() { return 0; } - virtual C_BaseEntity* GetBaseEntity() { return 0; } - virtual IClientThinkable* GetClientThinkable() { return 0; } - - -public: - ClientRenderHandle_t m_hRenderHandle; -}; - - -#endif // ICLIENTRENDERABLE_H diff --git a/public/iclientthinkable.h b/public/iclientthinkable.h deleted file mode 100644 index 6a3f59a24..000000000 --- a/public/iclientthinkable.h +++ /dev/null @@ -1,41 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ICLIENTTHINKABLE_H -#define ICLIENTTHINKABLE_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "iclientunknown.h" - - -class CClientThinkHandlePtr; -typedef CClientThinkHandlePtr* ClientThinkHandle_t; - - -// Entities that implement this interface can be put into the client think list. -abstract_class IClientThinkable -{ -public: - // Gets at the containing class... - virtual IClientUnknown* GetIClientUnknown() = 0; - - virtual void ClientThink() = 0; - - // Called when you're added to the think list. - // GetThinkHandle's return value must be initialized to INVALID_THINK_HANDLE. - virtual ClientThinkHandle_t GetThinkHandle() = 0; - virtual void SetThinkHandle( ClientThinkHandle_t hThink ) = 0; - - // Called by the client when it deletes the entity. - virtual void Release() = 0; -}; - - -#endif // ICLIENTTHINKABLE_H diff --git a/public/iclientunknown.h b/public/iclientunknown.h deleted file mode 100644 index 1d7dece14..000000000 --- a/public/iclientunknown.h +++ /dev/null @@ -1,41 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef ICLIENTUNKNOWN_H -#define ICLIENTUNKNOWN_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "tier0/platform.h" -#include "ihandleentity.h" - -class IClientNetworkable; -class C_BaseEntity; -class IClientRenderable; -class ICollideable; -class IClientEntity; -class IClientThinkable; - - - -// This is the client's version of IUnknown. We may want to use a QueryInterface-like -// mechanism if this gets big. -abstract_class IClientUnknown : public IHandleEntity -{ -public: - virtual ICollideable* GetCollideable() = 0; - virtual IClientNetworkable* GetClientNetworkable() = 0; - virtual IClientRenderable* GetClientRenderable() = 0; - virtual IClientEntity* GetIClientEntity() = 0; - virtual C_BaseEntity* GetBaseEntity() = 0; - virtual IClientThinkable* GetClientThinkable() = 0; -}; - - -#endif // ICLIENTUNKNOWN_H diff --git a/public/icvar.h b/public/icvar.h deleted file mode 100644 index b701d2646..000000000 --- a/public/icvar.h +++ /dev/null @@ -1,120 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#ifndef ICVAR_H -#define ICVAR_H -#ifdef _WIN32 -#pragma once -#endif - -#include "appframework/IAppSystem.h" -#include "tier1/iconvar.h" - -class ConCommandBase; -class ConCommand; -class ConVar; -class Color; - - -//----------------------------------------------------------------------------- -// ConVars/ComCommands are marked as having a particular DLL identifier -//----------------------------------------------------------------------------- -typedef int CVarDLLIdentifier_t; - - -//----------------------------------------------------------------------------- -// Used to display console messages -//----------------------------------------------------------------------------- -abstract_class IConsoleDisplayFunc -{ -public: - virtual void ColorPrint( const Color& clr, const char *pMessage ) = 0; - virtual void Print( const char *pMessage ) = 0; - virtual void DPrint( const char *pMessage ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Applications can implement this to modify behavior in ICvar -//----------------------------------------------------------------------------- -#define CVAR_QUERY_INTERFACE_VERSION "VCvarQuery001" -abstract_class ICvarQuery : public IAppSystem -{ -public: - // Can these two convars be aliased? - virtual bool AreConVarsLinkable( const ConVar *child, const ConVar *parent ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Purpose: DLL interface to ConVars/ConCommands -//----------------------------------------------------------------------------- -abstract_class ICvar : public IAppSystem -{ -public: - // Allocate a unique DLL identifier - virtual CVarDLLIdentifier_t AllocateDLLIdentifier() = 0; - - // Register, unregister commands - virtual void RegisterConCommand( ConCommandBase *pCommandBase ) = 0; - virtual void UnregisterConCommand( ConCommandBase *pCommandBase ) = 0; - virtual void UnregisterConCommands( CVarDLLIdentifier_t id ) = 0; - - // If there is a + on the command line, this returns the value. - // Otherwise, it returns NULL. - virtual const char* GetCommandLineValue( const char *pVariableName ) = 0; - - // Try to find the cvar pointer by name - virtual ConCommandBase *FindCommandBase( const char *name ) = 0; - virtual const ConCommandBase *FindCommandBase( const char *name ) const = 0; - virtual ConVar *FindVar ( const char *var_name ) = 0; - virtual const ConVar *FindVar ( const char *var_name ) const = 0; - virtual ConCommand *FindCommand( const char *name ) = 0; - virtual const ConCommand *FindCommand( const char *name ) const = 0; - - // Get first ConCommandBase to allow iteration - virtual ConCommandBase *GetCommands( void ) = 0; - virtual const ConCommandBase *GetCommands( void ) const = 0; - - // Install a global change callback (to be called when any convar changes) - virtual void InstallGlobalChangeCallback( FnChangeCallback_t callback ) = 0; - virtual void RemoveGlobalChangeCallback( FnChangeCallback_t callback ) = 0; - virtual void CallGlobalChangeCallbacks( ConVar *var, const char *pOldString, float flOldValue ) = 0; - - // Install a console printer - virtual void InstallConsoleDisplayFunc( IConsoleDisplayFunc* pDisplayFunc ) = 0; - virtual void RemoveConsoleDisplayFunc( IConsoleDisplayFunc* pDisplayFunc ) = 0; - virtual void ConsoleColorPrintf( const Color& clr, const char *pFormat, ... ) const = 0; - virtual void ConsolePrintf( const char *pFormat, ... ) const = 0; - virtual void ConsoleDPrintf( const char *pFormat, ... ) const = 0; - - // Reverts cvars which contain a specific flag - virtual void RevertFlaggedConVars( int nFlag ) = 0; - - // Method allowing the engine ICvarQuery interface to take over - // A little hacky, owing to the fact the engine is loaded - // well after ICVar, so we can't use the standard connect pattern - virtual void InstallCVarQuery( ICvarQuery *pQuery ) = 0; - -#if defined( _X360 ) - virtual void PublishToVXConsole( ) = 0; -#endif -}; - -#define CVAR_INTERFACE_VERSION "VEngineCvar004" - - -//----------------------------------------------------------------------------- -// These global names are defined by tier1.h, duplicated here so you -// don't have to include tier1.h -//----------------------------------------------------------------------------- - -// These are marked DLL_EXPORT for Linux. -DLL_EXPORT ICvar *cvar; -DLL_EXPORT ICvar *g_pCVar; - - -#endif // ICVAR_H diff --git a/public/idedicatedexports.h b/public/idedicatedexports.h deleted file mode 100644 index 5ad499662..000000000 --- a/public/idedicatedexports.h +++ /dev/null @@ -1,28 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IDEDICATEDEXPORTS_H -#define IDEDICATEDEXPORTS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "interface.h" -#include "appframework/IAppSystem.h" - - -abstract_class IDedicatedExports : public IAppSystem -{ -public: - virtual void Sys_Printf( char *text ) = 0; - virtual void RunServer() = 0; -}; - -#define VENGINE_DEDICATEDEXPORTS_API_VERSION "VENGINE_DEDICATEDEXPORTS_API_VERSION003" - - -#endif // IDEDICATEDEXPORTS_H diff --git a/public/iefx.h b/public/iefx.h deleted file mode 100644 index a1aa3e1c2..000000000 --- a/public/iefx.h +++ /dev/null @@ -1,67 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// - -#if !defined( IEFX_H ) -#define IEFX_H -#ifdef _WIN32 -#pragma once -#endif - -#include "interface.h" -#include "mathlib/vector.h" - -struct model_t; -struct dlight_t; -class IMaterial; - -#define MAX_DLIGHTS 32 - -//----------------------------------------------------------------------------- -// Purpose: Exposes effects api to client .dll -//----------------------------------------------------------------------------- -abstract_class IVEfx -{ -public: - // Retrieve decal texture index from decal by name - virtual int Draw_DecalIndexFromName ( char *name ) = 0; - - // Apply decal - virtual void DecalShoot ( int textureIndex, int entity, - const model_t *model, const Vector& model_origin, const QAngle& model_angles, - const Vector& position, const Vector *saxis, int flags ) = 0; - - // Apply colored decal - virtual void DecalColorShoot ( int textureIndex, int entity, - const model_t *model, const Vector& model_origin, const QAngle& model_angles, - const Vector& position, const Vector *saxis, int flags, const color32 &rgbaColor ) = 0; - - virtual void PlayerDecalShoot( IMaterial *material, void *userdata, int entity, const model_t *model, - const Vector& model_origin, const QAngle& model_angles, - const Vector& position, const Vector *saxis, int flags, const color32 &rgbaColor ) = 0; - - // Allocate a dynamic world light ( key is the entity to whom it is associated ) - virtual dlight_t *CL_AllocDlight ( int key ) = 0; - - // Allocate a dynamic entity light ( key is the entity to whom it is associated ) - virtual dlight_t *CL_AllocElight ( int key ) = 0; - - // Get a list of the currently-active dynamic lights. - virtual int CL_GetActiveDLights( dlight_t *pList[MAX_DLIGHTS] ) = 0; - - // Retrieve decal texture name from decal by index - virtual const char *Draw_DecalNameFromIndex( int nIndex ) = 0; - - // Given an elight key, find it. Does not search ordinary dlights. May return NULL. - virtual dlight_t *GetElightByKey( int key ) = 0; -}; - -#define VENGINE_EFFECTS_INTERFACE_VERSION "VEngineEffects001" - -extern IVEfx *effects; - -#endif // IEFX_H diff --git a/public/ienginevgui.h b/public/ienginevgui.h deleted file mode 100644 index e826ab5f5..000000000 --- a/public/ienginevgui.h +++ /dev/null @@ -1,64 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// -#if !defined( IENGINEVGUI_H ) -#define IENGINEVGUI_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "interface.h" -#include "vgui/VGUI.h" - -// Forward declarations. -namespace vgui -{ - class Panel; -}; - -enum VGuiPanel_t -{ - PANEL_ROOT = 0, - PANEL_GAMEUIDLL, - PANEL_CLIENTDLL, - PANEL_TOOLS, - PANEL_INGAMESCREENS, - PANEL_GAMEDLL, - PANEL_CLIENTDLL_TOOLS -}; - -// In-game panels are cropped to the current engine viewport size -enum PaintMode_t -{ - PAINT_UIPANELS = (1<<0), - PAINT_INGAMEPANELS = (1<<1), -}; - -abstract_class IEngineVGui -{ -public: - virtual ~IEngineVGui( void ) { } - - virtual vgui::VPANEL GetPanel( VGuiPanel_t type ) = 0; - - virtual bool IsGameUIVisible() = 0; -}; - -#define VENGINE_VGUI_VERSION "VEngineVGui001" - -#if defined(_STATIC_LINKED) && defined(CLIENT_DLL) -namespace Client -{ -extern IEngineVGui *enginevgui; -} -#else -extern IEngineVGui *enginevgui; -#endif - -#endif // IENGINEVGUI_H diff --git a/public/ifilelist.h b/public/ifilelist.h deleted file mode 100644 index 0c58d7a03..000000000 --- a/public/ifilelist.h +++ /dev/null @@ -1,28 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IFILELIST_H -#define IFILELIST_H -#ifdef _WIN32 -#pragma once -#endif - - -// This class represents a group of files. Internally, it can represent whole folders of files -// that are in or out of the group. So you can't iterate the list, but you can ask the -// class if a particular filename is in the list. -class IFileList -{ -public: - virtual bool IsFileInList( const char *pFilename ) = 0; - virtual void Release() = 0; -}; - - -#endif // IFILELIST_H - - diff --git a/public/igameevents.h b/public/igameevents.h deleted file mode 100644 index 9f08dc0a7..000000000 --- a/public/igameevents.h +++ /dev/null @@ -1,193 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#if !defined( IGAMEEVENTS_H ) -#define IGAMEEVENTS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/interface.h" - -#define INTERFACEVERSION_GAMEEVENTSMANAGER "GAMEEVENTSMANAGER001" // old game event manager, don't use it! -#define INTERFACEVERSION_GAMEEVENTSMANAGER2 "GAMEEVENTSMANAGER002" // new game event manager, - -#include "tier1/bitbuf.h" -//----------------------------------------------------------------------------- -// Purpose: Engine interface into global game event management -//----------------------------------------------------------------------------- - -/* - -The GameEventManager keeps track and fires of all global game events. Game events -are fired by game.dll for events like player death or team wins. Each event has a -unique name and comes with a KeyValue structure providing informations about this -event. Some events are generated also by the engine. - -Events are networked to connected clients and invoked there to. Therefore you -have to specify all data fields and there data types in an public resource -file which is parsed by server and broadcasted to it's clients. A typical game -event is defined like this: - - "game_start" // a new game starts - { - "roundslimit" "long" // max round - "timelimit" "long" // time limit - "fraglimit" "long" // frag limit - "objective" "string" // round objective - } - -All events must have unique names (case sensitive) and may have a list -of data fields. each data field must specify a data type, so the engine -knows how to serialize/unserialize that event for network transmission. -Valid data types are string, float, long, short, byte & bool. If a -data field should not be broadcasted to clients, use the type "local". -*/ - - -#define MAX_EVENT_NAME_LENGTH 32 // max game event name length -#define MAX_EVENT_BITS 9 // max bits needed for an event index -#define MAX_EVENT_NUMBER (1< (fn) - -class INetMessage -{ -public: - virtual ~INetMessage() {}; - - // Use these to setup who can hear whose voice. - // Pass in client indices (which are their ent indices - 1). - - virtual void SetNetChannel(INetChannel * netchan) = 0; // netchannel this message is from/for - virtual void SetReliable( bool state ) = 0; // set to true if it's a reliable message - - virtual bool Process( void ) = 0; // calles the recently set handler to process this message - - virtual bool ReadFromBuffer( bf_read &buffer ) = 0; // returns true if parsing was OK - virtual bool WriteToBuffer( bf_write &buffer ) = 0; // returns true if writing was OK - - virtual bool IsReliable( void ) const = 0; // true, if message needs reliable handling - - virtual int GetType( void ) const = 0; // returns module specific header tag eg svc_serverinfo - virtual int GetGroup( void ) const = 0; // returns net message group of this message - virtual const char *GetName( void ) const = 0; // returns network message name, eg "svc_serverinfo" - virtual INetChannel *GetNetChannel( void ) const = 0; - virtual const char *ToString( void ) const = 0; // returns a human readable string about message content -}; - - -#endif - diff --git a/public/inetmsghandler.h b/public/inetmsghandler.h deleted file mode 100644 index 55e9f986c..000000000 --- a/public/inetmsghandler.h +++ /dev/null @@ -1,203 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#if !defined( INETMSGHANDLER_H ) -#define INETMSGHANDLER_H -#ifdef _WIN32 -#pragma once -#endif - -class INetChannel; -typedef struct netpacket_s netpacket_t; - -class INetChannelHandler -{ -public: - virtual ~INetChannelHandler( void ) {}; - - virtual void ConnectionStart(INetChannel *chan) = 0; // called first time network channel is established - - virtual void ConnectionClosing(const char *reason) = 0; // network channel is being closed by remote site - - virtual void ConnectionCrashed(const char *reason) = 0; // network error occured - - virtual void PacketStart(int incoming_sequence, int outgoing_acknowledged) = 0; // called each time a new packet arrived - - virtual void PacketEnd( void ) = 0; // all messages has been parsed - - virtual void FileRequested(const char *fileName, unsigned int transferID) = 0; // other side request a file for download - - virtual void FileReceived(const char *fileName, unsigned int transferID) = 0; // we received a file - - virtual void FileDenied(const char *fileName, unsigned int transferID) = 0; // a file request was denied by other side - - virtual void FileSent(const char *fileName, unsigned int transferID) = 0; -}; - -#define PROCESS_NET_MESSAGE( name ) \ - virtual bool Process##name( NET_##name *msg ) - -#define PROCESS_SVC_MESSAGE( name ) \ - virtual bool Process##name( SVC_##name *msg ) - -#define PROCESS_CLC_MESSAGE( name ) \ - virtual bool Process##name( CLC_##name *msg ) - -#define PROCESS_MM_MESSAGE( name ) \ - virtual bool Process##name( MM_##name *msg ) - - -#define REGISTER_NET_MSG( name ) \ - NET_##name * p##name = new NET_##name(); \ - p##name->m_pMessageHandler = this; \ - chan->RegisterMessage( p##name ); \ - -#define REGISTER_SVC_MSG( name ) \ - SVC_##name * p##name = new SVC_##name(); \ - p##name->m_pMessageHandler = this; \ - chan->RegisterMessage( p##name ); \ - -#define REGISTER_CLC_MSG( name ) \ - CLC_##name * p##name = new CLC_##name(); \ - p##name->m_pMessageHandler = this; \ - chan->RegisterMessage( p##name ); \ - -#define REGISTER_MM_MSG( name ) \ - MM_##name * p##name = new MM_##name(); \ - p##name->m_pMessageHandler = this; \ - chan->RegisterMessage( p##name ); \ - -class NET_Tick; -class NET_StringCmd; -class NET_SetConVar; -class NET_SignonState; - - -class INetMessageHandler -{ -public: - virtual ~INetMessageHandler( void ) {}; - - PROCESS_NET_MESSAGE( Tick ) = 0; - PROCESS_NET_MESSAGE( StringCmd ) = 0; - PROCESS_NET_MESSAGE( SetConVar ) = 0; - PROCESS_NET_MESSAGE( SignonState ) = 0; -}; - -class CLC_ClientInfo; -class CLC_Move; -class CLC_VoiceData; -class CLC_BaselineAck; -class CLC_ListenEvents; -class CLC_RespondCvarValue; -class CLC_FileCRCCheck; - -class IClientMessageHandler : public INetMessageHandler -{ -public: - virtual ~IClientMessageHandler( void ) {}; - - PROCESS_CLC_MESSAGE( ClientInfo ) = 0; - PROCESS_CLC_MESSAGE( Move ) = 0; - PROCESS_CLC_MESSAGE( VoiceData ) = 0; - PROCESS_CLC_MESSAGE( BaselineAck ) = 0; - PROCESS_CLC_MESSAGE( ListenEvents ) = 0; - PROCESS_CLC_MESSAGE( RespondCvarValue ) = 0; - PROCESS_CLC_MESSAGE( FileCRCCheck ) = 0; -}; - -class SVC_Print; -class SVC_ServerInfo; -class SVC_SendTable; -class SVC_ClassInfo; -class SVC_SetPause; -class SVC_CreateStringTable; -class SVC_UpdateStringTable; -class SVC_VoiceInit; -class SVC_VoiceData; -class SVC_Sounds; -class SVC_SetView; -class SVC_FixAngle; -class SVC_CrosshairAngle; -class SVC_BSPDecal; -class SVC_GameEvent; -class SVC_UserMessage; -class SVC_EntityMessage; -class SVC_PacketEntities; -class SVC_TempEntities; -class SVC_Prefetch; -class SVC_Menu; -class SVC_GameEventList; -class SVC_GetCvarValue; - -class IServerMessageHandler : public INetMessageHandler -{ -public: - virtual ~IServerMessageHandler( void ) {}; - - PROCESS_SVC_MESSAGE( Print ) = 0; - PROCESS_SVC_MESSAGE( ServerInfo ) = 0; - PROCESS_SVC_MESSAGE( SendTable ) = 0; - PROCESS_SVC_MESSAGE( ClassInfo ) = 0; - PROCESS_SVC_MESSAGE( SetPause ) = 0; - PROCESS_SVC_MESSAGE( CreateStringTable ) = 0; - PROCESS_SVC_MESSAGE( UpdateStringTable ) = 0; - PROCESS_SVC_MESSAGE( VoiceInit ) = 0; - PROCESS_SVC_MESSAGE( VoiceData ) = 0; - PROCESS_SVC_MESSAGE( Sounds ) = 0; - PROCESS_SVC_MESSAGE( SetView ) = 0; - PROCESS_SVC_MESSAGE( FixAngle ) = 0; - PROCESS_SVC_MESSAGE( CrosshairAngle ) = 0; - PROCESS_SVC_MESSAGE( BSPDecal ) = 0; - PROCESS_SVC_MESSAGE( GameEvent ) = 0; - PROCESS_SVC_MESSAGE( UserMessage ) = 0; - PROCESS_SVC_MESSAGE( EntityMessage ) = 0; - PROCESS_SVC_MESSAGE( PacketEntities ) = 0; - PROCESS_SVC_MESSAGE( TempEntities ) = 0; - PROCESS_SVC_MESSAGE( Prefetch ) = 0; - PROCESS_SVC_MESSAGE( Menu ) = 0; - PROCESS_SVC_MESSAGE( GameEventList ) = 0; - PROCESS_SVC_MESSAGE( GetCvarValue ) = 0; -}; - -class MM_Heartbeat; -class MM_ClientInfo; -class MM_JoinResponse; -class MM_RegisterResponse; -class MM_Migrate; -class MM_Mutelist; -class MM_Checkpoint; - -class IMatchmakingMessageHandler : public INetMessageHandler -{ -public: - virtual ~IMatchmakingMessageHandler( void ) {}; - - PROCESS_MM_MESSAGE( Heartbeat ) = 0; - PROCESS_MM_MESSAGE( ClientInfo ) = 0; - PROCESS_MM_MESSAGE( JoinResponse ) = 0; - PROCESS_MM_MESSAGE( RegisterResponse ) = 0; - PROCESS_MM_MESSAGE( Migrate ) = 0; - PROCESS_MM_MESSAGE( Mutelist ) = 0; - PROCESS_MM_MESSAGE( Checkpoint) = 0; -}; - -class IConnectionlessPacketHandler -{ -public: - virtual ~IConnectionlessPacketHandler( void ) {}; - - virtual bool ProcessConnectionlessPacket( netpacket_t *packet ) = 0; // process a connectionless packet -}; - - -#endif // INETMSGHANDLER_H diff --git a/public/inetwork.h b/public/inetwork.h deleted file mode 100644 index 28a4798ee..000000000 --- a/public/inetwork.h +++ /dev/null @@ -1,52 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef INETWORK_H -#define INETWORK_H -#ifdef _WIN32 -#pragma once -#endif - -class IConnectionlessPacketHandler; - -abstract_class INetwork -{ -public: - virtual ~INetwork( void ) {}; - - virtual void Init( void ) = 0; - virtual void Config (bool multiplayer); - virtual void IsMultiplayer( void ) = 0; // true = full MP mode, false = loopback SP mode - virtual void IsEnabled( void ) = 0; - - // shuts down Network, closes all UPD/TCP channels - virtual void Shutdown( void ) = 0; - - // must be called each system frame to do any asynchronouse TCP stuff - virtual void RunFrame( double time ) = 0; - - virtual void ProcessSocket( netsrc_t sock, IConnectionlessPacketHandler * handler ) = 0; - - virtual void OutOfBandPrintf(netsrc_t sock, netadr_t &adr, const char *format, ...) = 0; - virtual void SendConnectionless(netsrc_t sock, netadr_t &adr, unsigned char * data, int length ) = 0; - - virtual void LogBadPacket(netpacket_t * packet) = 0; - - // Address conversion - virtual bool StringToAdr ( const char *s, netadr_t *a) = 0; - - // Convert from host to network byte ordering - virtual unsigned short HostToNetShort( unsigned short us_in ); - - // and vice versa - virtual unsigned short NetToHostShort( unsigned short us_in ); - - - -}; - - -#endif // INETWORK_H diff --git a/public/inputsystem/AnalogCode.h b/public/inputsystem/AnalogCode.h deleted file mode 100644 index 4ddac7fd7..000000000 --- a/public/inputsystem/AnalogCode.h +++ /dev/null @@ -1,44 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef ANALOGCODE_H -#define ANALOGCODE_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "inputsystem/InputEnums.h" - - -//----------------------------------------------------------------------------- -// Macro to get at joystick codes -//----------------------------------------------------------------------------- -#define JOYSTICK_AXIS_INTERNAL( _joystick, _axis ) ( JOYSTICK_FIRST_AXIS + ((_joystick) * MAX_JOYSTICK_AXES) + (_axis) ) -#define JOYSTICK_AXIS( _joystick, _axis ) ( (AnalogCode_t)JOYSTICK_AXIS_INTERNAL( _joystick, _axis ) ) - - -//----------------------------------------------------------------------------- -// Enumeration for analog input devices. Includes joysticks, mousewheel, mouse -//----------------------------------------------------------------------------- -enum AnalogCode_t -{ - ANALOG_CODE_INVALID = -1, - MOUSE_X = 0, - MOUSE_Y, - MOUSE_XY, // Invoked when either x or y changes - MOUSE_WHEEL, - - JOYSTICK_FIRST_AXIS, - JOYSTICK_LAST_AXIS = JOYSTICK_AXIS_INTERNAL( MAX_JOYSTICKS-1, MAX_JOYSTICK_AXES-1 ), - - ANALOG_CODE_LAST, -}; - - -#endif // ANALOGCODE_H diff --git a/public/inputsystem/ButtonCode.h b/public/inputsystem/ButtonCode.h deleted file mode 100644 index 0728853f7..000000000 --- a/public/inputsystem/ButtonCode.h +++ /dev/null @@ -1,266 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef BUTTONCODE_H -#define BUTTONCODE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "inputsystem/InputEnums.h" - -//----------------------------------------------------------------------------- -// Button enum. "Buttons" are binary-state input devices (mouse buttons, keyboard keys) -//----------------------------------------------------------------------------- -enum -{ - JOYSTICK_MAX_BUTTON_COUNT = 32, - JOYSTICK_POV_BUTTON_COUNT = 4, - JOYSTICK_AXIS_BUTTON_COUNT = MAX_JOYSTICK_AXES * 2, -}; - -#define JOYSTICK_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_BUTTON + ((_joystick) * JOYSTICK_MAX_BUTTON_COUNT) + (_button) ) -#define JOYSTICK_POV_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_POV_BUTTON + ((_joystick) * JOYSTICK_POV_BUTTON_COUNT) + (_button) ) -#define JOYSTICK_AXIS_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_AXIS_BUTTON + ((_joystick) * JOYSTICK_AXIS_BUTTON_COUNT) + (_button) ) - -#define JOYSTICK_BUTTON( _joystick, _button ) ( (ButtonCode_t)JOYSTICK_BUTTON_INTERNAL( _joystick, _button ) ) -#define JOYSTICK_POV_BUTTON( _joystick, _button ) ( (ButtonCode_t)JOYSTICK_POV_BUTTON_INTERNAL( _joystick, _button ) ) -#define JOYSTICK_AXIS_BUTTON( _joystick, _button ) ( (ButtonCode_t)JOYSTICK_AXIS_BUTTON_INTERNAL( _joystick, _button ) ) - -enum ButtonCode_t -{ - BUTTON_CODE_INVALID = -1, - BUTTON_CODE_NONE = 0, - - KEY_FIRST = 0, - - KEY_NONE = KEY_FIRST, - KEY_0, - KEY_1, - KEY_2, - KEY_3, - KEY_4, - KEY_5, - KEY_6, - KEY_7, - KEY_8, - KEY_9, - KEY_A, - KEY_B, - KEY_C, - KEY_D, - KEY_E, - KEY_F, - KEY_G, - KEY_H, - KEY_I, - KEY_J, - KEY_K, - KEY_L, - KEY_M, - KEY_N, - KEY_O, - KEY_P, - KEY_Q, - KEY_R, - KEY_S, - KEY_T, - KEY_U, - KEY_V, - KEY_W, - KEY_X, - KEY_Y, - KEY_Z, - KEY_PAD_0, - KEY_PAD_1, - KEY_PAD_2, - KEY_PAD_3, - KEY_PAD_4, - KEY_PAD_5, - KEY_PAD_6, - KEY_PAD_7, - KEY_PAD_8, - KEY_PAD_9, - KEY_PAD_DIVIDE, - KEY_PAD_MULTIPLY, - KEY_PAD_MINUS, - KEY_PAD_PLUS, - KEY_PAD_ENTER, - KEY_PAD_DECIMAL, - KEY_LBRACKET, - KEY_RBRACKET, - KEY_SEMICOLON, - KEY_APOSTROPHE, - KEY_BACKQUOTE, - KEY_COMMA, - KEY_PERIOD, - KEY_SLASH, - KEY_BACKSLASH, - KEY_MINUS, - KEY_EQUAL, - KEY_ENTER, - KEY_SPACE, - KEY_BACKSPACE, - KEY_TAB, - KEY_CAPSLOCK, - KEY_NUMLOCK, - KEY_ESCAPE, - KEY_SCROLLLOCK, - KEY_INSERT, - KEY_DELETE, - KEY_HOME, - KEY_END, - KEY_PAGEUP, - KEY_PAGEDOWN, - KEY_BREAK, - KEY_LSHIFT, - KEY_RSHIFT, - KEY_LALT, - KEY_RALT, - KEY_LCONTROL, - KEY_RCONTROL, - KEY_LWIN, - KEY_RWIN, - KEY_APP, - KEY_UP, - KEY_LEFT, - KEY_DOWN, - KEY_RIGHT, - KEY_F1, - KEY_F2, - KEY_F3, - KEY_F4, - KEY_F5, - KEY_F6, - KEY_F7, - KEY_F8, - KEY_F9, - KEY_F10, - KEY_F11, - KEY_F12, - KEY_CAPSLOCKTOGGLE, - KEY_NUMLOCKTOGGLE, - KEY_SCROLLLOCKTOGGLE, - - KEY_LAST = KEY_SCROLLLOCKTOGGLE, - KEY_COUNT = KEY_LAST - KEY_FIRST + 1, - - // Mouse - MOUSE_FIRST = KEY_LAST + 1, - - MOUSE_LEFT = MOUSE_FIRST, - MOUSE_RIGHT, - MOUSE_MIDDLE, - MOUSE_4, - MOUSE_5, - MOUSE_WHEEL_UP, // A fake button which is 'pressed' and 'released' when the wheel is moved up - MOUSE_WHEEL_DOWN, // A fake button which is 'pressed' and 'released' when the wheel is moved down - - MOUSE_LAST = MOUSE_WHEEL_DOWN, - MOUSE_COUNT = MOUSE_LAST - MOUSE_FIRST + 1, - - // Joystick - JOYSTICK_FIRST = MOUSE_LAST + 1, - - JOYSTICK_FIRST_BUTTON = JOYSTICK_FIRST, - JOYSTICK_LAST_BUTTON = JOYSTICK_BUTTON_INTERNAL( MAX_JOYSTICKS-1, JOYSTICK_MAX_BUTTON_COUNT-1 ), - JOYSTICK_FIRST_POV_BUTTON, - JOYSTICK_LAST_POV_BUTTON = JOYSTICK_POV_BUTTON_INTERNAL( MAX_JOYSTICKS-1, JOYSTICK_POV_BUTTON_COUNT-1 ), - JOYSTICK_FIRST_AXIS_BUTTON, - JOYSTICK_LAST_AXIS_BUTTON = JOYSTICK_AXIS_BUTTON_INTERNAL( MAX_JOYSTICKS-1, JOYSTICK_AXIS_BUTTON_COUNT-1 ), - - JOYSTICK_LAST = JOYSTICK_LAST_AXIS_BUTTON, - - BUTTON_CODE_LAST, - BUTTON_CODE_COUNT = BUTTON_CODE_LAST - KEY_FIRST + 1, - - // Helpers for XBox 360 - KEY_XBUTTON_UP = JOYSTICK_FIRST_POV_BUTTON, // POV buttons - KEY_XBUTTON_RIGHT, - KEY_XBUTTON_DOWN, - KEY_XBUTTON_LEFT, - - KEY_XBUTTON_A = JOYSTICK_FIRST_BUTTON, // Buttons - KEY_XBUTTON_B, - KEY_XBUTTON_X, - KEY_XBUTTON_Y, - KEY_XBUTTON_LEFT_SHOULDER, - KEY_XBUTTON_RIGHT_SHOULDER, - KEY_XBUTTON_BACK, - KEY_XBUTTON_START, - KEY_XBUTTON_STICK1, - KEY_XBUTTON_STICK2, - - KEY_XSTICK1_RIGHT = JOYSTICK_FIRST_AXIS_BUTTON, // XAXIS POSITIVE - KEY_XSTICK1_LEFT, // XAXIS NEGATIVE - KEY_XSTICK1_DOWN, // YAXIS POSITIVE - KEY_XSTICK1_UP, // YAXIS NEGATIVE - KEY_XBUTTON_LTRIGGER, // ZAXIS POSITIVE - KEY_XBUTTON_RTRIGGER, // ZAXIS NEGATIVE - KEY_XSTICK2_RIGHT, // UAXIS POSITIVE - KEY_XSTICK2_LEFT, // UAXIS NEGATIVE - KEY_XSTICK2_DOWN, // VAXIS POSITIVE - KEY_XSTICK2_UP, // VAXIS NEGATIVE -}; - -inline bool IsAlpha( ButtonCode_t code ) -{ - return ( code >= KEY_A ) && ( code <= KEY_Z ); -} - -inline bool IsAlphaNumeric( ButtonCode_t code ) -{ - return ( code >= KEY_0 ) && ( code <= KEY_Z ); -} - -inline bool IsSpace( ButtonCode_t code ) -{ - return ( code == KEY_ENTER ) || ( code == KEY_TAB ) || ( code == KEY_SPACE ); -} - -inline bool IsKeypad( ButtonCode_t code ) -{ - return ( code >= MOUSE_FIRST ) && ( code <= KEY_PAD_DECIMAL ); -} - -inline bool IsPunctuation( ButtonCode_t code ) -{ - return ( code >= KEY_0 ) && ( code <= KEY_SPACE ) && !IsAlphaNumeric( code ) && !IsSpace( code ) && !IsKeypad( code ); -} - -inline bool IsKeyCode( ButtonCode_t code ) -{ - return ( code >= KEY_FIRST ) && ( code <= KEY_LAST ); -} - -inline bool IsMouseCode( ButtonCode_t code ) -{ - return ( code >= MOUSE_FIRST ) && ( code <= MOUSE_LAST ); -} - -inline bool IsJoystickCode( ButtonCode_t code ) -{ - return ( code >= JOYSTICK_FIRST ) && ( code <= JOYSTICK_LAST ); -} - -inline bool IsJoystickButtonCode( ButtonCode_t code ) -{ - return ( code >= JOYSTICK_FIRST_BUTTON ) && ( code <= JOYSTICK_LAST_BUTTON ); -} - -inline bool IsJoystickPOVCode( ButtonCode_t code ) -{ - return ( code >= JOYSTICK_FIRST_POV_BUTTON ) && ( code <= JOYSTICK_LAST_POV_BUTTON ); -} - -inline bool IsJoystickAxisCode( ButtonCode_t code ) -{ - return ( code >= JOYSTICK_FIRST_AXIS_BUTTON ) && ( code <= JOYSTICK_LAST_AXIS_BUTTON ); -} - -#endif // BUTTONCODE_H diff --git a/public/inputsystem/InputEnums.h b/public/inputsystem/InputEnums.h deleted file mode 100644 index 56871b616..000000000 --- a/public/inputsystem/InputEnums.h +++ /dev/null @@ -1,85 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#ifndef INPUTENUMS_H -#define INPUTENUMS_H -#ifdef _WIN32 -#pragma once -#endif - -// Standard maximum +/- value of a joystick axis -#define MAX_BUTTONSAMPLE 32768 - -#if !defined( _X360 ) -#define INVALID_USER_ID -1 -#else -#define INVALID_USER_ID XBX_INVALID_USER_ID -#endif - -//----------------------------------------------------------------------------- -// Forward declarations: -//----------------------------------------------------------------------------- - -enum -{ - MAX_JOYSTICKS = 1, - MOUSE_BUTTON_COUNT = 5, -}; - -enum JoystickAxis_t -{ - JOY_AXIS_X = 0, - JOY_AXIS_Y, - JOY_AXIS_Z, - JOY_AXIS_R, - JOY_AXIS_U, - JOY_AXIS_V, - MAX_JOYSTICK_AXES, -}; - - - -//----------------------------------------------------------------------------- -// Extra mouse codes -//----------------------------------------------------------------------------- -enum -{ - MS_WM_XBUTTONDOWN = 0x020B, - MS_WM_XBUTTONUP = 0x020C, - MS_WM_XBUTTONDBLCLK = 0x020D, - MS_MK_BUTTON4 = 0x0020, - MS_MK_BUTTON5 = 0x0040, -}; - -//----------------------------------------------------------------------------- -// Events -//----------------------------------------------------------------------------- -enum InputEventType_t -{ - IE_ButtonPressed = 0, // m_nData contains a ButtonCode_t - IE_ButtonReleased, // m_nData contains a ButtonCode_t - IE_ButtonDoubleClicked, // m_nData contains a ButtonCode_t - IE_AnalogValueChanged, // m_nData contains an AnalogCode_t, m_nData2 contains the value - - IE_FirstSystemEvent = 100, - IE_Quit = IE_FirstSystemEvent, - IE_ControllerInserted, // m_nData contains the controller ID - IE_ControllerUnplugged, // m_nData contains the controller ID - - IE_FirstVguiEvent = 1000, // Assign ranges for other systems that post user events here - IE_FirstAppEvent = 2000, -}; - -struct InputEvent_t -{ - int m_nType; // Type of the event (see InputEventType_t) - int m_nTick; // Tick on which the event occurred - int m_nData; // Generic 32-bit data, what it contains depends on the event - int m_nData2; // Generic 32-bit data, what it contains depends on the event - int m_nData3; // Generic 32-bit data, what it contains depends on the event -}; - -#endif // INPUTENUMS_H diff --git a/public/inputsystem/iinputsystem.h b/public/inputsystem/iinputsystem.h deleted file mode 100644 index a83971a2b..000000000 --- a/public/inputsystem/iinputsystem.h +++ /dev/null @@ -1,115 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#ifndef IINPUTSYSTEM_H -#define IINPUTSYSTEM_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/platform.h" -#include "appframework/IAppSystem.h" - -#include "inputsystem/InputEnums.h" -#include "inputsystem/ButtonCode.h" -#include "inputsystem/AnalogCode.h" - -//----------------------------------------------------------------------------- -// Main interface for input. This is a low-level interface -//----------------------------------------------------------------------------- -#define INPUTSYSTEM_INTERFACE_VERSION "InputSystemVersion001" -abstract_class IInputSystem : public IAppSystem -{ -public: - // Attach, detach input system from a particular window - // This window should be the root window for the application - // Only 1 window should be attached at any given time. - virtual void AttachToWindow( void* hWnd ) = 0; - virtual void DetachFromWindow( ) = 0; - - // Enables/disables input. PollInputState will not update current - // button/analog states when it is called if the system is disabled. - virtual void EnableInput( bool bEnable ) = 0; - - // Enables/disables the windows message pump. PollInputState will not - // Peek/Dispatch messages if this is disabled - virtual void EnableMessagePump( bool bEnable ) = 0; - - // Polls the current input state - virtual void PollInputState() = 0; - - // Gets the time of the last polling in ms - virtual int GetPollTick() const = 0; - - // Is a button down? "Buttons" are binary-state input devices (mouse buttons, keyboard keys) - virtual bool IsButtonDown( ButtonCode_t code ) const = 0; - - // Returns the tick at which the button was pressed and released - virtual int GetButtonPressedTick( ButtonCode_t code ) const = 0; - virtual int GetButtonReleasedTick( ButtonCode_t code ) const = 0; - - // Gets the value of an analog input device this frame - // Includes joysticks, mousewheel, mouse - virtual int GetAnalogValue( AnalogCode_t code ) const = 0; - - // Gets the change in a particular analog input device this frame - // Includes joysticks, mousewheel, mouse - virtual int GetAnalogDelta( AnalogCode_t code ) const = 0; - - // Returns the input events since the last poll - virtual int GetEventCount() const = 0; - virtual const InputEvent_t* GetEventData( ) const = 0; - - // Posts a user-defined event into the event queue; this is expected - // to be called in overridden wndprocs connected to the root panel. - virtual void PostUserEvent( const InputEvent_t &event ) = 0; - - // Returns the number of joysticks - virtual int GetJoystickCount() const = 0; - - // Enable/disable joystick, it has perf costs - virtual void EnableJoystickInput( int nJoystick, bool bEnable ) = 0; - - // Enable/disable diagonal joystick POV (simultaneous POV buttons down) - virtual void EnableJoystickDiagonalPOV( int nJoystick, bool bEnable ) = 0; - - // Sample the joystick and append events to the input queue - virtual void SampleDevices( void ) = 0; - - // FIXME: Currently force-feedback is only supported on the Xbox 360 - virtual void SetRumble( float fLeftMotor, float fRightMotor, int userId = INVALID_USER_ID ) = 0; - virtual void StopRumble( void ) = 0; - - // Resets the input state - virtual void ResetInputState() = 0; - - // Sets a player as the primary user - all other controllers will be ignored. - virtual void SetPrimaryUserId( int userId ) = 0; - - // Convert back + forth between ButtonCode/AnalogCode + strings - virtual const char *ButtonCodeToString( ButtonCode_t code ) const = 0; - virtual const char *AnalogCodeToString( AnalogCode_t code ) const = 0; - virtual ButtonCode_t StringToButtonCode( const char *pString ) const = 0; - virtual AnalogCode_t StringToAnalogCode( const char *pString ) const = 0; - - // Sleeps until input happens. Pass a negative number to sleep infinitely - virtual void SleepUntilInput( int nMaxSleepTimeMS = -1 ) = 0; - - // Convert back + forth between virtual codes + button codes - // FIXME: This is a temporary piece of code - virtual ButtonCode_t VirtualKeyToButtonCode( int nVirtualKey ) const = 0; - virtual int ButtonCodeToVirtualKey( ButtonCode_t code ) const = 0; - virtual ButtonCode_t ScanCodeToButtonCode( int lParam ) const = 0; - - // How many times have we called PollInputState? - virtual int GetPollCount() const = 0; - - // Sets the cursor position - virtual void SetCursorPosition( int x, int y ) = 0; -}; - - -#endif // IINPUTSYSTEM_H diff --git a/public/interpolatortypes.cpp b/public/interpolatortypes.cpp deleted file mode 100644 index d8ff512f1..000000000 --- a/public/interpolatortypes.cpp +++ /dev/null @@ -1,506 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= -#include "basetypes.h" -#include "tier1/strtools.h" -#include "interpolatortypes.h" -#include "tier0/dbg.h" -#include "mathlib/mathlib.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -struct InterpolatorNameMap_t -{ - int type; - char const *name; - char const *printname; -}; - -static InterpolatorNameMap_t g_InterpolatorNameMap[] = -{ - { INTERPOLATE_DEFAULT, "default", "Default" }, - { INTERPOLATE_CATMULL_ROM_NORMALIZEX, "catmullrom_normalize_x", "Catmull-Rom (Norm X)" }, - { INTERPOLATE_EASE_IN, "easein", "Ease In" }, - { INTERPOLATE_EASE_OUT, "easeout", "Ease Out" }, - { INTERPOLATE_EASE_INOUT, "easeinout", "Ease In/Out" }, - { INTERPOLATE_BSPLINE, "bspline", "B-Spline" }, - { INTERPOLATE_LINEAR_INTERP, "linear_interp", "Linear Interp." }, - { INTERPOLATE_KOCHANEK_BARTELS, "kochanek", "Kochanek-Bartels" }, - { INTERPOLATE_KOCHANEK_BARTELS_EARLY, "kochanek_early", "Kochanek-Bartels Early" }, - { INTERPOLATE_KOCHANEK_BARTELS_LATE, "kochanek_late", "Kochanek-Bartels Late" }, - { INTERPOLATE_SIMPLE_CUBIC, "simple_cubic", "Simple Cubic" }, - { INTERPOLATE_CATMULL_ROM, "catmullrom", "Catmull-Rom" }, - { INTERPOLATE_CATMULL_ROM_NORMALIZE, "catmullrom_normalize", "Catmull-Rom (Norm)" }, - { INTERPOLATE_CATMULL_ROM_TANGENT, "catmullrom_tangent", "Catmull-Rom (Tangent)" }, - { INTERPOLATE_EXPONENTIAL_DECAY, "exponential_decay", "Exponential Decay" }, - { INTERPOLATE_HOLD, "hold", "Hold" }, -}; - -int Interpolator_InterpolatorForName( char const *name ) -{ - for ( int i = 0; i < NUM_INTERPOLATE_TYPES; ++i ) - { - InterpolatorNameMap_t *slot = &g_InterpolatorNameMap[ i ]; - if ( !Q_stricmp( name, slot->name ) ) - return slot->type; - } - - Assert( !"Interpolator_InterpolatorForName failed!!!" ); - return INTERPOLATE_DEFAULT; -} - -char const *Interpolator_NameForInterpolator( int type, bool printname ) -{ - int i = (int)type; - int c = ARRAYSIZE( g_InterpolatorNameMap ); - if ( i < 0 || i >= c ) - { - Assert( "!Interpolator_NameForInterpolator: bogus type!" ); - // returns "unspecified!!!"; - return printname ? g_InterpolatorNameMap[ 0 ].printname : g_InterpolatorNameMap[ 0 ].name; - } - - return printname ? g_InterpolatorNameMap[ i ].printname : g_InterpolatorNameMap[ i ].name; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -struct CurveNameMap_t -{ - int type; - int hotkey; -}; - -static CurveNameMap_t g_CurveNameMap[] = -{ - { CURVE_CATMULL_ROM_TO_CATMULL_ROM, '1' }, - { CURVE_EASE_IN_TO_EASE_OUT, '2' }, - { CURVE_EASE_IN_TO_EASE_IN, '3' }, - { CURVE_EASE_OUT_TO_EASE_OUT, '4' }, - { CURVE_BSPLINE_TO_BSPLINE, '5' }, - { CURVE_LINEAR_INTERP_TO_LINEAR_INTERP, '6' }, - { CURVE_KOCHANEK_BARTELS_TO_KOCHANEK_BARTELS, '7' }, - { CURVE_KOCHANEK_BARTELS_EARLY_TO_KOCHANEK_BARTELS_EARLY, '8' }, - { CURVE_KOCHANEK_BARTELS_LATE_TO_KOCHANEK_BARTELS_LATE, '9' }, - { CURVE_SIMPLE_CUBIC_TO_SIMPLE_CUBIC, '0' }, -}; - -// Turn enum into string and vice versa -int Interpolator_CurveTypeForName( const char *name ) -{ - char sz[ 128 ]; - Q_strncpy( sz, name, sizeof( sz ) ); - - int leftcurve = 0; - int rightcurve = 0; - - int skip = Q_strlen( "curve_" ); - - if ( !Q_strnicmp( sz, "curve_", skip ) ) - { - char *p = sz + skip; - char *second = Q_stristr( p, "_to_curve_" ); - - char save = *second; - *second = 0; - - leftcurve = Interpolator_InterpolatorForName( p ); - - *second = save; - - p = second + Q_strlen( "_to_curve_" ); - - rightcurve = Interpolator_InterpolatorForName( p ); - } - - return MAKE_CURVE_TYPE( leftcurve, rightcurve ); -} - -const char *Interpolator_NameForCurveType( int type, bool printname ) -{ - static char outname[ 256 ]; - - int leftside = GET_LEFT_CURVE( type ); - int rightside = GET_RIGHT_CURVE( type ); - - if ( !printname ) - { - Q_snprintf( outname, sizeof( outname ), "curve_%s_to_curve_%s", - Interpolator_NameForInterpolator( leftside, printname ), - Interpolator_NameForInterpolator( rightside, printname ) ); - } - else - { - Q_snprintf( outname, sizeof( outname ), "%s <-> %s", - Interpolator_NameForInterpolator( leftside, printname ), - Interpolator_NameForInterpolator( rightside, printname ) ); - } - - return outname; -} - -void Interpolator_CurveInterpolatorsForType( int type, int& inbound, int& outbound ) -{ - inbound = GET_LEFT_CURVE( type ); - outbound = GET_RIGHT_CURVE( type ); -} - -int Interpolator_CurveTypeForHotkey( int key ) -{ - int c = ARRAYSIZE( g_CurveNameMap ); - for ( int i = 0; i < c; ++i ) - { - CurveNameMap_t *slot = &g_CurveNameMap[ i ]; - if ( slot->hotkey == key ) - return slot->type; - } - - return -1; -} - -void Interpolator_GetKochanekBartelsParams( int interpolationType, float& tension, float& bias, float& continuity ) -{ - switch ( interpolationType ) - { - default: - tension = 0.0f; - bias = 0.0f; - continuity = 0.0f; - Assert( 0 ); - break; - case INTERPOLATE_KOCHANEK_BARTELS: - tension = 0.77f; - bias = 0.0f; - continuity = 0.77f; - break; - case INTERPOLATE_KOCHANEK_BARTELS_EARLY: - tension = 0.77f; - bias = -1.0f; - continuity = 0.77f; - break; - case INTERPOLATE_KOCHANEK_BARTELS_LATE: - tension = 0.77f; - bias = 1.0f; - continuity = 0.77f; - break; - } -} - -void Interpolator_CurveInterpolate( int interpolationType, - const Vector &vPre, - const Vector &vStart, - const Vector &vEnd, - const Vector &vNext, - float f, - Vector &vOut ) -{ - vOut.Init(); - - switch ( interpolationType ) - { - default: - Warning( "Unknown interpolation type %d\n", - (int)interpolationType ); - // break; // Fall through and use catmull_rom as default - case INTERPOLATE_DEFAULT: - case INTERPOLATE_CATMULL_ROM_NORMALIZEX: - Catmull_Rom_Spline_NormalizeX( - vPre, - vStart, - vEnd, - vNext, - f, - vOut ); - break; - case INTERPOLATE_CATMULL_ROM: - Catmull_Rom_Spline( - vPre, - vStart, - vEnd, - vNext, - f, - vOut ); - break; - case INTERPOLATE_CATMULL_ROM_NORMALIZE: - Catmull_Rom_Spline_Normalize( - vPre, - vStart, - vEnd, - vNext, - f, - vOut ); - break; - case INTERPOLATE_CATMULL_ROM_TANGENT: - Catmull_Rom_Spline_Tangent( - vPre, - vStart, - vEnd, - vNext, - f, - vOut ); - break; - case INTERPOLATE_EASE_IN: - { - f = sin( M_PI * f * 0.5f ); - // Fixme, since this ignores vPre and vNext we could omit computing them aove - VectorLerp( vStart, vEnd, f, vOut ); - } - break; - case INTERPOLATE_EASE_OUT: - { - f = 1.0f - sin( M_PI * f * 0.5f + 0.5f * M_PI ); - // Fixme, since this ignores vPre and vNext we could omit computing them aove - VectorLerp( vStart, vEnd, f, vOut ); - } - break; - case INTERPOLATE_EASE_INOUT: - { - f = SimpleSpline( f ); - // Fixme, since this ignores vPre and vNext we could omit computing them aove - VectorLerp( vStart, vEnd, f, vOut ); - } - break; - case INTERPOLATE_LINEAR_INTERP: - // Fixme, since this ignores vPre and vNext we could omit computing them aove - VectorLerp( vStart, vEnd, f, vOut ); - break; - case INTERPOLATE_KOCHANEK_BARTELS: - case INTERPOLATE_KOCHANEK_BARTELS_EARLY: - case INTERPOLATE_KOCHANEK_BARTELS_LATE: - { - float t, b, c; - Interpolator_GetKochanekBartelsParams( interpolationType, t, b, c ); - Kochanek_Bartels_Spline_NormalizeX - ( - t, b, c, - vPre, - vStart, - vEnd, - vNext, - f, - vOut - ); - } - break; - case INTERPOLATE_SIMPLE_CUBIC: - Cubic_Spline_NormalizeX( - vPre, - vStart, - vEnd, - vNext, - f, - vOut ); - break; - case INTERPOLATE_BSPLINE: - BSpline( - vPre, - vStart, - vEnd, - vNext, - f, - vOut ); - break; - case INTERPOLATE_EXPONENTIAL_DECAY: - { - float dt = vEnd.x - vStart.x; - if ( dt > 0.0f ) - { - float val = 1.0f - ExponentialDecay( 0.001, dt, f * dt ); - vOut.y = vStart.y + val * ( vEnd.y - vStart.y ); - } - else - { - vOut.y = vStart.y; - } - } - break; - case INTERPOLATE_HOLD: - { - vOut.y = vStart.y; - } - break; - } -} - -void Interpolator_CurveInterpolate_NonNormalized( int interpolationType, - const Vector &vPre, - const Vector &vStart, - const Vector &vEnd, - const Vector &vNext, - float f, - Vector &vOut ) -{ - vOut.Init(); - - switch ( interpolationType ) - { - default: - Warning( "Unknown interpolation type %d\n", - (int)interpolationType ); - // break; // Fall through and use catmull_rom as default - case INTERPOLATE_CATMULL_ROM_NORMALIZEX: - case INTERPOLATE_DEFAULT: - case INTERPOLATE_CATMULL_ROM: - case INTERPOLATE_CATMULL_ROM_NORMALIZE: - case INTERPOLATE_CATMULL_ROM_TANGENT: - Catmull_Rom_Spline( - vPre, - vStart, - vEnd, - vNext, - f, - vOut ); - break; - case INTERPOLATE_EASE_IN: - { - f = sin( M_PI * f * 0.5f ); - // Fixme, since this ignores vPre and vNext we could omit computing them aove - VectorLerp( vStart, vEnd, f, vOut ); - } - break; - case INTERPOLATE_EASE_OUT: - { - f = 1.0f - sin( M_PI * f * 0.5f + 0.5f * M_PI ); - // Fixme, since this ignores vPre and vNext we could omit computing them aove - VectorLerp( vStart, vEnd, f, vOut ); - } - break; - case INTERPOLATE_EASE_INOUT: - { - f = SimpleSpline( f ); - // Fixme, since this ignores vPre and vNext we could omit computing them aove - VectorLerp( vStart, vEnd, f, vOut ); - } - break; - case INTERPOLATE_LINEAR_INTERP: - // Fixme, since this ignores vPre and vNext we could omit computing them aove - VectorLerp( vStart, vEnd, f, vOut ); - break; - case INTERPOLATE_KOCHANEK_BARTELS: - case INTERPOLATE_KOCHANEK_BARTELS_EARLY: - case INTERPOLATE_KOCHANEK_BARTELS_LATE: - { - float t, b, c; - Interpolator_GetKochanekBartelsParams( interpolationType, t, b, c ); - Kochanek_Bartels_Spline - ( - t, b, c, - vPre, - vStart, - vEnd, - vNext, - f, - vOut - ); - } - break; - case INTERPOLATE_SIMPLE_CUBIC: - Cubic_Spline( - vPre, - vStart, - vEnd, - vNext, - f, - vOut ); - break; - case INTERPOLATE_BSPLINE: - BSpline( - vPre, - vStart, - vEnd, - vNext, - f, - vOut ); - break; - case INTERPOLATE_EXPONENTIAL_DECAY: - { - float dt = vEnd.x - vStart.x; - if ( dt > 0.0f ) - { - float val = 1.0f - ExponentialDecay( 0.001, dt, f * dt ); - vOut.y = vStart.y + val * ( vEnd.y - vStart.y ); - } - else - { - vOut.y = vStart.y; - } - } - break; - case INTERPOLATE_HOLD: - { - vOut.y = vStart.y; - } - break; - } -} - - -void Interpolator_CurveInterpolate_NonNormalized( int interpolationType, - const Quaternion &vPre, - const Quaternion &vStart, - const Quaternion &vEnd, - const Quaternion &vNext, - float f, - Quaternion &vOut ) -{ - vOut.Init(); - - switch ( interpolationType ) - { - default: - Warning( "Unknown interpolation type %d\n", - (int)interpolationType ); - // break; // Fall through and use catmull_rom as default - case INTERPOLATE_CATMULL_ROM_NORMALIZEX: - case INTERPOLATE_DEFAULT: - case INTERPOLATE_CATMULL_ROM: - case INTERPOLATE_CATMULL_ROM_NORMALIZE: - case INTERPOLATE_CATMULL_ROM_TANGENT: - case INTERPOLATE_KOCHANEK_BARTELS: - case INTERPOLATE_KOCHANEK_BARTELS_EARLY: - case INTERPOLATE_KOCHANEK_BARTELS_LATE: - case INTERPOLATE_SIMPLE_CUBIC: - case INTERPOLATE_BSPLINE: - // FIXME, since this ignores vPre and vNext we could omit computing them aove - QuaternionSlerp( vStart, vEnd, f, vOut ); - break; - case INTERPOLATE_EASE_IN: - { - f = sin( M_PI * f * 0.5f ); - // Fixme, since this ignores vPre and vNext we could omit computing them aove - QuaternionSlerp( vStart, vEnd, f, vOut ); - } - break; - case INTERPOLATE_EASE_OUT: - { - f = 1.0f - sin( M_PI * f * 0.5f + 0.5f * M_PI ); - // Fixme, since this ignores vPre and vNext we could omit computing them aove - QuaternionSlerp( vStart, vEnd, f, vOut ); - } - break; - case INTERPOLATE_EASE_INOUT: - { - f = SimpleSpline( f ); - // Fixme, since this ignores vPre and vNext we could omit computing them aove - QuaternionSlerp( vStart, vEnd, f, vOut ); - } - break; - case INTERPOLATE_LINEAR_INTERP: - // Fixme, since this ignores vPre and vNext we could omit computing them aove - QuaternionSlerp( vStart, vEnd, f, vOut ); - break; - case INTERPOLATE_EXPONENTIAL_DECAY: - vOut.Init(); - break; - case INTERPOLATE_HOLD: - { - vOut = vStart; - } - break; - } -} diff --git a/public/interpolatortypes.h b/public/interpolatortypes.h deleted file mode 100644 index 123f673d3..000000000 --- a/public/interpolatortypes.h +++ /dev/null @@ -1,102 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef INTERPOLATORTYPES_H -#define INTERPOLATORTYPES_H -#ifdef _WIN32 -#pragma once -#endif - -class Quaternion; - -enum -{ - INTERPOLATE_DEFAULT = 0, - INTERPOLATE_CATMULL_ROM_NORMALIZEX, - INTERPOLATE_EASE_IN, - INTERPOLATE_EASE_OUT, - INTERPOLATE_EASE_INOUT, - INTERPOLATE_BSPLINE, - INTERPOLATE_LINEAR_INTERP, - INTERPOLATE_KOCHANEK_BARTELS, - INTERPOLATE_KOCHANEK_BARTELS_EARLY, - INTERPOLATE_KOCHANEK_BARTELS_LATE, - INTERPOLATE_SIMPLE_CUBIC, - - INTERPOLATE_CATMULL_ROM, - INTERPOLATE_CATMULL_ROM_NORMALIZE, - INTERPOLATE_CATMULL_ROM_TANGENT, - - INTERPOLATE_EXPONENTIAL_DECAY, - - INTERPOLATE_HOLD, - - NUM_INTERPOLATE_TYPES, -}; - -#define MAKE_CURVE_TYPE( left, right ) ( ( right ) & 0xff ) | ( ( ( left ) & 0xff ) << 8 ) - -#define GET_RIGHT_CURVE(w) ( ( w ) & 0xff ) -#define GET_LEFT_CURVE(w) ( ( ( w ) >> 8) & 0xff ) - -// Presets used by faceposer -enum -{ - CURVE_DEFAULT = MAKE_CURVE_TYPE( INTERPOLATE_DEFAULT, INTERPOLATE_DEFAULT ), - CURVE_CATMULL_ROM_TO_CATMULL_ROM = MAKE_CURVE_TYPE( INTERPOLATE_CATMULL_ROM_NORMALIZEX , INTERPOLATE_CATMULL_ROM_NORMALIZEX ), // hotkey 1 - CURVE_EASE_IN_TO_EASE_OUT = MAKE_CURVE_TYPE( INTERPOLATE_EASE_IN, INTERPOLATE_EASE_OUT ), // hotkey 2 - CURVE_EASE_IN_TO_EASE_IN = MAKE_CURVE_TYPE( INTERPOLATE_EASE_IN, INTERPOLATE_EASE_IN ), - CURVE_EASE_OUT_TO_EASE_OUT = MAKE_CURVE_TYPE( INTERPOLATE_EASE_OUT, INTERPOLATE_EASE_OUT ), - CURVE_BSPLINE_TO_BSPLINE = MAKE_CURVE_TYPE( INTERPOLATE_BSPLINE, INTERPOLATE_BSPLINE ), - CURVE_LINEAR_INTERP_TO_LINEAR_INTERP = MAKE_CURVE_TYPE( INTERPOLATE_LINEAR_INTERP, INTERPOLATE_LINEAR_INTERP ), - CURVE_KOCHANEK_BARTELS_TO_KOCHANEK_BARTELS = MAKE_CURVE_TYPE( INTERPOLATE_KOCHANEK_BARTELS, INTERPOLATE_KOCHANEK_BARTELS ), - CURVE_KOCHANEK_BARTELS_EARLY_TO_KOCHANEK_BARTELS_EARLY = MAKE_CURVE_TYPE( INTERPOLATE_KOCHANEK_BARTELS_EARLY, INTERPOLATE_KOCHANEK_BARTELS_EARLY ), - CURVE_KOCHANEK_BARTELS_LATE_TO_KOCHANEK_BARTELS_LATE = MAKE_CURVE_TYPE( INTERPOLATE_KOCHANEK_BARTELS_LATE, INTERPOLATE_KOCHANEK_BARTELS_LATE ), - CURVE_SIMPLE_CUBIC_TO_SIMPLE_CUBIC = MAKE_CURVE_TYPE( INTERPOLATE_SIMPLE_CUBIC, INTERPOLATE_SIMPLE_CUBIC ), - CURVE_LINEAR_TO_HOLD = MAKE_CURVE_TYPE( INTERPOLATE_LINEAR_INTERP, INTERPOLATE_HOLD ), - CURVE_HOLD_TO_LINEAR = MAKE_CURVE_TYPE( INTERPOLATE_HOLD, INTERPOLATE_LINEAR_INTERP ), -}; - -// Turn enum into string and vice versa -int Interpolator_CurveTypeForName( const char *name ); -const char *Interpolator_NameForCurveType( int type, bool printname ); -void Interpolator_CurveInterpolatorsForType( int type, int& inbound, int& outbound ); -int Interpolator_CurveTypeForHotkey( int key ); - -int Interpolator_InterpolatorForName( char const *name ); -char const *Interpolator_NameForInterpolator( int type, bool printname ); - -void Interpolator_GetKochanekBartelsParams( int interpolatorType, float& tension, float& bias, float& continuity ); - -class Vector; -// Main spline interpolation function, assumes .x holds time and .y holds one dimensional value -void Interpolator_CurveInterpolate( int interpolationType, - const Vector &vPre, - const Vector &vStart, - const Vector &vEnd, - const Vector &vNext, - float f, - Vector &vOut ); - -// Main spline interpolation function for Vectors, doesn't assume time is in .x and doesn't do normalization -void Interpolator_CurveInterpolate_NonNormalized( int interpolationType, - const Vector &vPre, - const Vector &vStart, - const Vector &vEnd, - const Vector &vNext, - float f, - Vector &vOut ); - -// Main spline interpolation function for Vectors, doesn't assume time is in .x and doesn't do normalization -void Interpolator_CurveInterpolate_NonNormalized( int interpolationType, - const Quaternion &vPre, - const Quaternion &vStart, - const Quaternion &vEnd, - const Quaternion &vNext, - float f, - Quaternion &vOut ); - -#endif // INTERPOLATORTYPES_H diff --git a/public/iprediction.h b/public/iprediction.h deleted file mode 100644 index f81d895ed..000000000 --- a/public/iprediction.h +++ /dev/null @@ -1,67 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#if !defined( IPREDICTION_H ) -#define IPREDICTION_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "interface.h" -#include "mathlib/vector.h" // Solely to get at define for QAngle - - -class IMoveHelper; - -//----------------------------------------------------------------------------- -// Purpose: Engine interface into client side prediction system -//----------------------------------------------------------------------------- -abstract_class IPrediction -{ -public: - virtual ~IPrediction( void ) {}; - - virtual void Init( void ) = 0; - virtual void Shutdown( void ) = 0; - - // Run prediction - virtual void Update - ( - int startframe, // World update ( un-modded ) most recently received - bool validframe, // Is frame data valid - int incoming_acknowledged, // Last command acknowledged to have been run by server (un-modded) - int outgoing_command // Last command (most recent) sent to server (un-modded) - ) = 0; - - // We are about to get a network update from the server. We know the update #, so we can pull any - // data purely predicted on the client side and transfer it to the new from data state. - virtual void PreEntityPacketReceived( int commands_acknowledged, int current_world_update_packet ) = 0; - virtual void PostEntityPacketReceived( void ) = 0; - virtual void PostNetworkDataReceived( int commands_acknowledged ) = 0; - - virtual void OnReceivedUncompressedPacket( void ) = 0; - - // The engine needs to be able to access a few predicted values - virtual void GetViewOrigin( Vector& org ) = 0; - virtual void SetViewOrigin( Vector& org ) = 0; - virtual void GetViewAngles( QAngle& ang ) = 0; - virtual void SetViewAngles( QAngle& ang ) = 0; - virtual void GetLocalViewAngles( QAngle& ang ) = 0; - virtual void SetLocalViewAngles( QAngle& ang ) = 0; -}; - -extern IPrediction *g_pClientSidePrediction; - -#define VCLIENT_PREDICTION_INTERFACE_VERSION "VClientPrediction001" - -#endif // IPREDICTION_H diff --git a/public/irecipientfilter.h b/public/irecipientfilter.h deleted file mode 100644 index ad5041cdc..000000000 --- a/public/irecipientfilter.h +++ /dev/null @@ -1,29 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IRECIPIENTFILTER_H -#define IRECIPIENTFILTER_H -#ifdef _WIN32 -#pragma once -#endif - -//----------------------------------------------------------------------------- -// Purpose: Generic interface for routing messages to users -//----------------------------------------------------------------------------- -class IRecipientFilter -{ -public: - virtual ~IRecipientFilter() {} - - virtual bool IsReliable( void ) const = 0; - virtual bool IsInitMessage( void ) const = 0; - - virtual int GetRecipientCount( void ) const = 0; - virtual int GetRecipientIndex( int slot ) const = 0; -}; - -#endif // IRECIPIENTFILTER_H diff --git a/public/iregistry.h b/public/iregistry.h deleted file mode 100644 index da9ce8dc5..000000000 --- a/public/iregistry.h +++ /dev/null @@ -1,48 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// -#if !defined( UTIL_REGISTRY_H ) -#define UTIL_REGISTRY_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/platform.h" - - -//----------------------------------------------------------------------------- -// Purpose: Interface to registry -//----------------------------------------------------------------------------- -abstract_class IRegistry -{ -public: - // Init/shutdown - virtual bool Init( const char *platformName ) = 0; - virtual void Shutdown( void ) = 0; - - // Read/write integers - virtual int ReadInt( const char *key, int defaultValue = 0 ) = 0; - virtual void WriteInt( const char *key, int value ) = 0; - - // Read/write strings - virtual const char *ReadString( const char *key, const char *defaultValue = 0 ) = 0; - virtual void WriteString( const char *key, const char *value ) = 0; - - // Read/write helper methods - virtual int ReadInt( const char *pKeyBase, const char *pKey, int defaultValue = 0 ) = 0; - virtual void WriteInt( const char *pKeyBase, const char *key, int value ) = 0; - virtual const char *ReadString( const char *pKeyBase, const char *key, const char *defaultValue ) = 0; - virtual void WriteString( const char *pKeyBase, const char *key, const char *value ) = 0; -}; - -extern IRegistry *registry; - -// Creates it and calls Init -IRegistry *InstanceRegistry( char const *subDirectoryUnderValve ); -// Calls Shutdown and deletes it -void ReleaseInstancedRegistry( IRegistry *reg ); - -#endif // UTIL_REGISTRY_H diff --git a/public/isaverestore.h b/public/isaverestore.h deleted file mode 100644 index e9a7da0f9..000000000 --- a/public/isaverestore.h +++ /dev/null @@ -1,387 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ISAVERESTORE_H -#define ISAVERESTORE_H - -#include "string_t.h" -#include "datamap.h" -#include "mathlib/vmatrix.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -#ifndef CLIENT_DLL -class SINGLE_INHERITANCE CBaseEntity; -#endif - -class Vector; -class VMatrix; -struct edict_t; -template< class T > class CHandle; -typedef CHandle EHANDLE; -struct matrix3x4_t; - -class CSaveRestoreData; -class CGameSaveRestoreInfo; - -class ISave; -class IRestore; - -//----------------------------------------------------------------------------- - -#pragma pack(push,1) - -struct SaveRestoreRecordHeader_t -{ - unsigned short size; - unsigned short symbol; -}; - - -#pragma pack(pop) - -//----------------------------------------------------------------------------- -// -// ISaveRestoreBlockHandler -// -//----------------------------------------------------------------------------- - -const int MAX_BLOCK_NAME_LEN = 31; -const int SIZE_BLOCK_NAME_BUF = 31 + 1; - -//------------------------------------- - -abstract_class ISaveRestoreBlockHandler -{ -public: - virtual const char *GetBlockName() = 0; - - virtual void PreSave( CSaveRestoreData * ) = 0; // Called immediately prior to save, generally used to set up any necessary tables - virtual void Save( ISave * ) = 0; - virtual void WriteSaveHeaders( ISave * ) = 0; // Called after save to allow the writing out of any dictionaries/tables/indexes generated during save - virtual void PostSave() = 0; - - virtual void PreRestore() = 0; - virtual void ReadRestoreHeaders( IRestore * ) = 0; // Called prior to Restore() - virtual void Restore( IRestore *, bool fCreatePlayers ) = 0; - virtual void PostRestore() = 0; -}; - -//------------------------------------- - -abstract_class ISaveRestoreBlockSet : public ISaveRestoreBlockHandler -{ -public: - virtual void AddBlockHandler( ISaveRestoreBlockHandler *pHandler ) = 0; - virtual void RemoveBlockHandler( ISaveRestoreBlockHandler *pHandler ) = 0; - virtual void CallBlockHandlerRestore( ISaveRestoreBlockHandler *pHandler, int baseFilePos, IRestore *pRestore, bool fCreatePlayers ) = 0; -}; - -extern ISaveRestoreBlockSet *g_pGameSaveRestoreBlockSet; - -//------------------------------------- - -abstract_class CDefSaveRestoreBlockHandler : public ISaveRestoreBlockHandler -{ - virtual const char *GetBlockName() = 0; - - virtual void PreSave( CSaveRestoreData * ) {} - virtual void Save( ISave * ) {} - virtual void WriteSaveHeaders( ISave * ) {} - virtual void PostSave() {} - - virtual void PreRestore() {} - virtual void ReadRestoreHeaders( IRestore * ) {} - virtual void Restore( IRestore *, bool fCreatePlayers ) {} - virtual void PostRestore() {} -}; - -//----------------------------------------------------------------------------- -// -// ISave -// -//----------------------------------------------------------------------------- - -abstract_class ISave -{ -public: - - //--------------------------------- - // Logging - virtual void StartLogging( const char *pszLogName ) = 0; - virtual void EndLogging( void ) = 0; - - //--------------------------------- - virtual bool IsAsync() = 0; - - //--------------------------------- - - virtual int GetWritePos() const = 0; - virtual void SetWritePos(int pos) = 0; - - //--------------------------------- - // Datamap based writing - // - - virtual int WriteAll( const void *pLeafObject, datamap_t *pLeafMap ) = 0; - virtual int WriteFields( const char *pname, const void *pBaseData, datamap_t *pMap, typedescription_t *pFields, int fieldCount ) = 0; - - template - int WriteAll( const T *pLeafObject ) - { - return WriteAll( pLeafObject, &pLeafObject->m_DataMap ); - } - - //--------------------------------- - // Block support - // - // Using these, one doesn't have to worry about queuing up the read pointer on restore if only - // a subset of the data is read - // - - virtual void StartBlock( const char *pszBlockName ) = 0; - virtual void StartBlock() = 0; - virtual void EndBlock() = 0; - - //--------------------------------- - // Primitive types - // - - virtual void WriteShort( const short *value, int count = 1 ) = 0; - virtual void WriteInt( const int *value, int count = 1 ) = 0; // Save an int - inline void WriteInt( const unsigned *value, int count = 1 ) { WriteInt( (int *)value, count ); } - virtual void WriteBool( const bool *value, int count = 1 ) = 0; // Save a bool - virtual void WriteFloat( const float *value, int count = 1 ) = 0; // Save a float - virtual void WriteData( const char *pdata, int size ) = 0; // Save a binary data block - virtual void WriteString( const char *pstring ) = 0; // Save a null-terminated string - virtual void WriteString( const string_t *stringId, int count = 1 ) = 0; // Save a null-terminated string (engine string) - virtual void WriteVector( const Vector &value ) = 0; // Save a vector - virtual void WriteVector( const Vector *value, int count = 1 ) = 0; // Save a vector array - virtual void WriteQuaternion( const Quaternion &value ) = 0; // Save a Quaternion - virtual void WriteQuaternion( const Quaternion *value, int count = 1 ) = 0; // Save a Quaternion array - - // Note: All of the following will write out both a header and the data. On restore, - // this needs to be cracked - virtual void WriteShort( const char *pname, const short *value, int count = 1 ) = 0; - virtual void WriteInt( const char *pname, const int *value, int count = 1 ) = 0; // Save an int - virtual void WriteBool( const char *pname, const bool *value, int count = 1 ) = 0; // Save a bool - virtual void WriteFloat( const char *pname, const float *value, int count = 1 ) = 0; // Save a float - virtual void WriteData( const char *pname, int size, const char *pdata ) = 0; // Save a binary data block - virtual void WriteString( const char *pname, const char *pstring ) = 0; // Save a null-terminated string - virtual void WriteString( const char *pname, const string_t *stringId, int count = 1 ) = 0; // Save a null-terminated string (engine string) - virtual void WriteVector( const char *pname, const Vector &value ) = 0; // Save a vector - virtual void WriteVector( const char *pname, const Vector *value, int count = 1 ) = 0; // Save a vector array - virtual void WriteQuaternion( const char *pname, const Quaternion &value ) = 0; // Save a Quaternion - virtual void WriteQuaternion( const char *pname, const Quaternion *value, int count = 1 ) = 0; // Save a Quaternion array - - //--------------------------------- - // Game types - // - - virtual void WriteTime( const char *pname, const float *value, int count = 1 ) = 0; // Save a float (timevalue) - virtual void WriteTick( const char *pname, const int *value, int count = 1 ) = 0; // Save a tick (timevalue) - virtual void WritePositionVector( const char *pname, const Vector &value ) = 0; // Offset for landmark if necessary - virtual void WritePositionVector( const char *pname, const Vector *value, int count = 1 ) = 0; // array of pos vectors - virtual void WriteFunction( datamap_t *pMap, const char *pname, const int *value, int count = 1 ) = 0; // Save a function pointer - - virtual void WriteTime( const float *value, int count = 1 ) = 0; // Save a float (timevalue) - virtual void WriteTick( const int *value, int count = 1 ) = 0; // Save a tick (timevalue) - virtual void WritePositionVector( const Vector &value ) = 0; // Offset for landmark if necessary - virtual void WritePositionVector( const Vector *value, int count = 1 ) = 0; // array of pos vectors - - virtual void WriteEntityPtr( const char *pname, CBaseEntity **ppEntity, int count = 1 ) = 0; - virtual void WriteEdictPtr( const char *pname, edict_t **ppEdict, int count = 1 ) = 0; - virtual void WriteEHandle( const char *pname, const EHANDLE *pEHandle, int count = 1 ) = 0; - - virtual void WriteEntityPtr( CBaseEntity **ppEntity, int count = 1 ) = 0; - virtual void WriteEdictPtr( edict_t **ppEdict, int count = 1 ) = 0; - virtual void WriteEHandle( const EHANDLE *pEHandle, int count = 1 ) = 0; - - //--------------------------------- - // Back door to support somewhat awkward ownership of game save/restore data - virtual CGameSaveRestoreInfo *GetGameSaveRestoreInfo() = 0; - -protected: - virtual ~ISave() {}; -}; - -//----------------------------------------------------------------------------- -// -// IRestore -// -//----------------------------------------------------------------------------- - -abstract_class IRestore -{ -public: - - //--------------------------------- - - virtual int GetReadPos() const = 0; - virtual void SetReadPos( int pos ) = 0; - - //--------------------------------- - // Datamap based reading - // - - virtual int ReadAll( void *pLeafObject, datamap_t *pLeafMap ) = 0; - - virtual int ReadFields( const char *pname, void *pBaseData, datamap_t *pMap, typedescription_t *pFields, int fieldcount = 1 ) = 0; - virtual void EmptyFields( void *pBaseData, typedescription_t *pFields, int fieldcount = 1 ) = 0; - - template - int ReadAll( T *pLeafObject ) - { - return ReadAll( pLeafObject, &pLeafObject->m_DataMap ); - } - - //--------------------------------- - // Block support - // - - virtual void StartBlock( SaveRestoreRecordHeader_t *pHeader ) = 0; - virtual void StartBlock( char szBlockName[SIZE_BLOCK_NAME_BUF] ) = 0; - virtual void StartBlock() = 0; - virtual void EndBlock() = 0; - - //--------------------------------- - // Field header cracking - // - - virtual void ReadHeader( SaveRestoreRecordHeader_t *pheader ) = 0; - virtual int SkipHeader() = 0; // skips the header, but returns the size of the field - virtual const char *StringFromHeaderSymbol( int symbol ) = 0; - - //--------------------------------- - // Primitive types - // - - virtual short ReadShort( void ) = 0; - virtual int ReadShort( short *pValue, int count = 1, int nBytesAvailable = 0 ) = 0; - virtual int ReadInt( int *pValue, int count = 1, int nBytesAvailable = 0 ) = 0; - inline int ReadInt( unsigned *pValue, int count = 1, int nBytesAvailable = 0 ) { return ReadInt( (int *)pValue, count, nBytesAvailable ); } - virtual int ReadInt( void ) = 0; - virtual int ReadBool( bool *pValue, int count = 1, int nBytesAvailable = 0 ) = 0; - virtual int ReadFloat( float *pValue, int count = 1, int nBytesAvailable = 0 ) = 0; - virtual int ReadData( char *pData, int size, int nBytesAvailable ) = 0; - virtual void ReadString( char *pDest, int nSizeDest, int nBytesAvailable ) = 0; // A null-terminated string - virtual int ReadString( string_t *pString, int count = 1, int nBytesAvailable = 0 ) = 0; - virtual int ReadVector( Vector *pValue ) = 0; - virtual int ReadVector( Vector *pValue, int count = 1, int nBytesAvailable = 0 ) = 0; - virtual int ReadQuaternion( Quaternion *pValue ) = 0; - virtual int ReadQuaternion( Quaternion *pValue, int count = 1, int nBytesAvailable = 0 ) = 0; - - //--------------------------------- - // Game types - // - - virtual int ReadTime( float *pValue, int count = 1, int nBytesAvailable = 0 ) = 0; - virtual int ReadTick( int *pValue, int count = 1, int nBytesAvailable = 0 ) = 0; - virtual int ReadPositionVector( Vector *pValue ) = 0; - virtual int ReadPositionVector( Vector *pValue, int count = 1, int nBytesAvailable = 0 ) = 0; - virtual int ReadFunction( datamap_t *pMap, void **pValue, int count = 1, int nBytesAvailable = 0) = 0; - - virtual int ReadEntityPtr( CBaseEntity **ppEntity, int count = 1, int nBytesAvailable = 0 ) = 0; - virtual int ReadEdictPtr( edict_t **ppEdict, int count = 1, int nBytesAvailable = 0 ) = 0; - virtual int ReadEHandle( EHANDLE *pEHandle, int count = 1, int nBytesAvailable = 0 ) = 0; - virtual int ReadVMatrix( VMatrix *pValue, int count = 1, int nBytesAvailable = 0) = 0; - virtual int ReadVMatrixWorldspace( VMatrix *pValue, int count = 1, int nBytesAvailable = 0) = 0; - virtual int ReadMatrix3x4Worldspace( matrix3x4_t *pValue, int nElems = 1, int nBytesAvailable = 0 ) = 0; - - //--------------------------------- - - virtual bool GetPrecacheMode( void ) = 0; - - //--------------------------------- - // Back door to support somewhat awkward ownership of game save/restore data - virtual CGameSaveRestoreInfo *GetGameSaveRestoreInfo() = 0; - -protected: - virtual ~IRestore() {}; -}; - -//----------------------------------------------------------------------------- -// Purpose: The operations necessary to save and restore custom types (FIELD_CUSTOM) -// -// - -struct SaveRestoreFieldInfo_t -{ - void * pField; - - // Note that it is legal for the following two fields to be NULL, - // though it may be disallowed by implementors of ISaveRestoreOps - void * pOwner; - typedescription_t *pTypeDesc; -}; - -abstract_class ISaveRestoreOps -{ -public: - // save data type interface - virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave ) = 0; - virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore ) = 0; - - virtual bool IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) = 0; - virtual void MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) = 0; - virtual bool Parse( const SaveRestoreFieldInfo_t &fieldInfo, char const* szValue ) = 0; - - //--------------------------------- - - void Save( void *pField, ISave *pSave ) { SaveRestoreFieldInfo_t fieldInfo = { pField, NULL, NULL }; Save( fieldInfo, pSave ); } - void Restore( void *pField, IRestore *pRestore ) { SaveRestoreFieldInfo_t fieldInfo = { pField, NULL, NULL }; Restore( fieldInfo, pRestore ); } - - bool IsEmpty( void *pField) { SaveRestoreFieldInfo_t fieldInfo = { pField, NULL, NULL }; return IsEmpty( fieldInfo ); } - void MakeEmpty( void *pField) { SaveRestoreFieldInfo_t fieldInfo = { pField, NULL, NULL }; MakeEmpty( fieldInfo ); } - bool Parse( void *pField, char const *pszValue ) { SaveRestoreFieldInfo_t fieldInfo = { pField, NULL, NULL }; return Parse( fieldInfo, pszValue ); } -}; - -//------------------------------------- - -class CDefSaveRestoreOps : public ISaveRestoreOps -{ -public: - // save data type interface - virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave ) {} - virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore ) {} - - virtual bool IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) { return false; } - virtual void MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) {} - virtual bool Parse( const SaveRestoreFieldInfo_t &fieldInfo, char const* szValue ) { return false; } -}; - - -//----------------------------------------------------------------------------- -// Used by ops that deal with pointers -//----------------------------------------------------------------------------- -class CClassPtrSaveRestoreOps : public CDefSaveRestoreOps -{ -public: - virtual bool IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - void **ppClassPtr = (void **)fieldInfo.pField; - int nObjects = fieldInfo.pTypeDesc->fieldSize; - for ( int i = 0; i < nObjects; i++ ) - { - if ( ppClassPtr[i] != NULL ) - return false; - } - return true; - } - - virtual void MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - memset( fieldInfo.pField, 0, fieldInfo.pTypeDesc->fieldSize * sizeof( void * ) ); - } -}; - - -//============================================================================= - -#endif // ISAVERESTORE_H diff --git a/public/iscratchpad3d.h b/public/iscratchpad3d.h deleted file mode 100644 index 69ee7aa7a..000000000 --- a/public/iscratchpad3d.h +++ /dev/null @@ -1,326 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ISCRATCHPAD3D_H -#define ISCRATCHPAD3D_H -#ifdef _WIN32 -#pragma once -#endif - - -// IScratchPad3D will store drawing commands in a file to be viewed by ScratchPad3DViewer. -// It can be used while stepping through geometry code to visualize what is going on as -// drawing commands will be immediately visible in ScratchPad3DViewer even while you're stuck -// in the debugger - -// ScratchPad3DViewer initially orbits 100 inches from the origin, so it can be useful -// to call SetMapping to map what you're drawing input into this cube. - - -#include "mathlib/vector.h" -#include "mathlib/vector2d.h" -#include "utlvector.h" - -class IFileSystem; - - -class CSPColor -{ -public: - CSPColor() - { - m_flAlpha = 1; - } - CSPColor( const Vector &vColor, float flAlpha=1 ) - { - m_vColor = vColor; - m_flAlpha = flAlpha; - } - CSPColor( float r, float g, float b, float a=1 ) - { - m_vColor.Init( r, g, b ); - m_flAlpha = a; - } - - Vector m_vColor; - float m_flAlpha; -}; - - -class CSPVert -{ -public: - CSPVert(); - CSPVert( Vector const &vPos, const CSPColor &vColor=CSPColor( Vector(1, 1, 1), 1 ) ); - - void Init( Vector const &vPos, const CSPColor &vColor=CSPColor( Vector(1, 1, 1), 1 ) ); - -public: - Vector m_vPos; - CSPColor m_vColor; -}; - - -class CSPVertList -{ -public: - CSPVertList( int nVerts = 0 ); - CSPVertList(CSPVert const *pVerts, int nVerts); - CSPVertList(Vector const *pVerts, int nVerts, CSPColor vColor=CSPColor(1,1,1) ); - - CSPVertList(Vector const *pVerts, Vector const *pColors, int nVerts); - CSPVertList(Vector const *pVerts, CSPColor const *pColors, int nVerts); - - CSPVertList(Vector const &vert1, CSPColor const &color1, - Vector const &vert2, CSPColor const &color2, - Vector const &vert3, CSPColor const &color3); - - CUtlVector m_Verts; -}; - -class SPRGBA -{ -public: - unsigned char r,g,b,a; -}; - - -class CTextParams -{ -public: - CTextParams(); - - - Vector m_vColor; // Color of the string (starting color.. at some point, - // we can embed commands in the text itself to change the color). - float m_flAlpha; // Alpha of the whole thing. - - bool m_bSolidBackground; // Should the background be solid or alpha'd? - - // Draw an outline around the text? - bool m_bOutline; - - Vector m_vPos; // Where to render the text. - bool m_bCentered; // Centered on m_vPos, or is m_vPos the upper-left corner? - - QAngle m_vAngles; // Orientation of the text. - bool m_bTwoSided; // Render the text from both sides? - - float m_flLetterWidth; // Letter width in world space. -}; - - -abstract_class IScratchPad3D -{ -protected: - - virtual ~IScratchPad3D() {} - - -// Types. -public: - - enum RenderState - { - RS_FillMode=0, // val = one of the FillMode enums - RS_ZRead, - RS_ZBias // val = 0 - 16 to push Z towards viewer - }; - - enum FillMode - { - FillMode_Wireframe=0, - FillMode_Solid - }; - - -public: - - virtual void Release() = 0; - - // This sets up a mapping between input coordinates and output coordinates. - // This can be used to zoom into an area of interest where you'll be drawing things. - // An alternative is to press Z while in VisLibViewer to have it center and zoom on - // everything that has been drawn. - virtual void SetMapping( - Vector const &vInputMin, - Vector const &vInputMax, - Vector const &vOutputMin, - Vector const &vOutputMax ) = 0; - - // Enable/disable auto flush. When set to true (the default), all drawing commands - // are immediately written to the file and will show up in VisLibViewer right away. - // If you want to draw a lot of things, you can set this to false and call Flush() - // manually when you want the file written out. - // When you set auto flush to true, it calls Flush(). - virtual bool GetAutoFlush() = 0; - virtual void SetAutoFlush( bool bAutoFlush ) = 0; - - // Draw a point. Point size is (roughly) in world coordinates, so points - // get smaller as the viewer moves away. - virtual void DrawPoint( CSPVert const &v, float flPointSize ) = 0; - - // Draw a line. - virtual void DrawLine( CSPVert const &v1, CSPVert const &v2 ) = 0; - - // Draw a polygon. - virtual void DrawPolygon( CSPVertList const &verts ) = 0; - - // Draw 2D rectangles. - virtual void DrawRectYZ( float xPos, Vector2D const &vMin, Vector2D const &vMax, const CSPColor &vColor ) = 0; - virtual void DrawRectXZ( float yPos, Vector2D const &vMin, Vector2D const &vMax, const CSPColor &vColor ) = 0; - virtual void DrawRectXY( float zPos, Vector2D const &vMin, Vector2D const &vMax, const CSPColor &vColor ) = 0; - - // Draw a wireframe box. - virtual void DrawWireframeBox( Vector const &vMin, Vector const &vMax, Vector const &vColor ) = 0; - - // Draw some text. - virtual void DrawText( const char *pStr, const CTextParams ¶ms ) = 0; - - // Wireframe on/off. - virtual void SetRenderState( RenderState state, unsigned long val ) = 0; - - // Clear all the drawing commands. - virtual void Clear() = 0; - - // Calling this writes all the commands to the file. If AutoFlush is true, this is called - // automatically in all the drawing commands. - virtual void Flush() = 0; - - -// Primitives that build on the atomic primitives. -public: - - // Draw a black and white image. - // Corners are in this order: bottom-left, top-left, top-right, bottom-right. - // If the corners are NULL, then the image is drawn in the XY plane from (-100,-100) to (100,100). - virtual void DrawImageBW( - unsigned char const *pData, - int width, - int height, - int pitchInBytes, - bool bOutlinePixels=true, - bool bOutlineImage=false, - Vector *vCorners=NULL ) = 0; - - // Draw an RGBA image. - // Corners are in this order: bottom-left, top-left, top-right, bottom-right. - virtual void DrawImageRGBA( - SPRGBA *pData, - int width, - int height, - int pitchInBytes, - bool bOutlinePixels=true, - bool bOutlineImage=false, - Vector *vCorners=NULL ) = 0; -}; - - -// Just a helper for functions where you want to have a CScratchPad3D around -// and release it automatically when the function exits. -class CScratchPadAutoRelease -{ -public: - CScratchPadAutoRelease( IScratchPad3D *pPad ) { m_pPad = pPad; } - ~CScratchPadAutoRelease() { if( m_pPad ) m_pPad->Release(); } - - IScratchPad3D *m_pPad; -}; - - - -IScratchPad3D* ScratchPad3D_Create( char const *pFilename = "scratch.pad" ); - - - -// ------------------------------------------------------------------------------------ // -// Inlines. -// ------------------------------------------------------------------------------------ // - -inline CTextParams::CTextParams() -{ - m_vColor.Init( 1, 1, 1 ); - m_flAlpha = 1; - m_bSolidBackground = true; - m_bOutline = true; - m_vPos.Init(); - m_bCentered = true; - m_vAngles.Init(); - m_bTwoSided = true; - m_flLetterWidth = 3; -} - -inline CSPVert::CSPVert() -{ -} - -inline CSPVert::CSPVert( Vector const &vPos, const CSPColor &vColor ) -{ - Init( vPos, vColor ); -} - -inline void CSPVert::Init( Vector const &vPos, const CSPColor &vColor ) -{ - m_vPos = vPos; - m_vColor = vColor; -} - - -inline CSPVertList::CSPVertList( int nVerts ) -{ - if( nVerts ) - m_Verts.AddMultipleToTail( nVerts ); -} - -inline CSPVertList::CSPVertList(CSPVert const *pVerts, int nVerts ) -{ - m_Verts.CopyArray( pVerts, nVerts ); -} - -inline CSPVertList::CSPVertList(Vector const *pVerts, int nVerts, CSPColor vColor ) -{ - m_Verts.AddMultipleToTail( nVerts ); - for( int i=0; i < nVerts; i++ ) - { - m_Verts[i].m_vPos = pVerts[i]; - m_Verts[i].m_vColor = vColor; - } -} - -inline CSPVertList::CSPVertList( Vector const *pVerts, Vector const *pColors, int nVerts ) -{ - m_Verts.AddMultipleToTail( nVerts ); - for( int i=0; i < nVerts; i++ ) - { - m_Verts[i].m_vPos = pVerts[i]; - m_Verts[i].m_vColor = pColors[i]; - } -} - -inline CSPVertList::CSPVertList( Vector const *pVerts, CSPColor const *pColors, int nVerts ) -{ - m_Verts.AddMultipleToTail( nVerts ); - for( int i=0; i < nVerts; i++ ) - { - m_Verts[i].m_vPos = pVerts[i]; - m_Verts[i].m_vColor = pColors[i]; - } -} - -inline CSPVertList::CSPVertList( - Vector const &vert1, CSPColor const &color1, - Vector const &vert2, CSPColor const &color2, - Vector const &vert3, CSPColor const &color3 ) -{ - m_Verts.AddMultipleToTail( 3 ); - m_Verts[0].Init( vert1, color1 ); - m_Verts[1].Init( vert2, color2 ); - m_Verts[2].Init( vert3, color3 ); -} - - -#endif // ISCRATCHPAD3D_H diff --git a/public/iserver.h b/public/iserver.h deleted file mode 100644 index 3284fb7cb..000000000 --- a/public/iserver.h +++ /dev/null @@ -1,68 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ISERVER_H -#define ISERVER_H -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include - -class INetMessage; -class IRecipientFilter; -class IClient; - -typedef struct player_info_s player_info_t; - -abstract_class IServer : public IConnectionlessPacketHandler -{ -public: - virtual ~IServer() {} - - virtual int GetNumClients( void ) const = 0; // returns current number of clients - virtual int GetNumProxies( void ) const = 0; // returns number of attached HLTV proxies - virtual int GetNumFakeClients() const = 0; // returns number of fake clients/bots - virtual int GetMaxClients( void ) const = 0; // returns current client limit - virtual IClient *GetClient( int index ) = 0; // returns interface to client - virtual int GetClientCount() const = 0; // returns number of clients slots (used & unused) - virtual int GetUDPPort( void ) const = 0; // returns current used UDP port - virtual float GetTime( void ) const = 0; // returns game world time - virtual int GetTick( void ) const = 0; // returns game world tick - virtual float GetTickInterval( void ) const = 0; // tick interval in seconds - virtual const char *GetName( void ) const = 0; // public server name - virtual const char *GetMapName( void ) const = 0; // current map name (BSP) - virtual int GetSpawnCount( void ) const = 0; - virtual int GetNumClasses( void ) const = 0; - virtual int GetClassBits( void ) const = 0; - virtual void GetNetStats( float &avgIn, float &avgOut ) = 0; // total net in/out in bytes/sec - virtual int GetNumPlayers() = 0; - virtual bool GetPlayerInfo( int nClientIndex, player_info_t *pinfo ) = 0; - - virtual bool IsActive( void ) const = 0; - virtual bool IsLoading( void ) const = 0; - virtual bool IsDedicated( void ) const = 0; - virtual bool IsPaused( void ) const = 0; - virtual bool IsMultiplayer( void ) const = 0; - virtual bool IsPausable() const = 0; - virtual bool IsHLTV() const = 0; - virtual bool IsReplay() const = 0; - - virtual const char * GetPassword() const = 0; // returns the password or NULL if none set - - virtual void SetPaused(bool paused) = 0; - virtual void SetPassword(const char *password) = 0; // set password (NULL to disable) - - virtual void BroadcastMessage( INetMessage &msg, bool onlyActive = false, bool reliable = false) = 0; - virtual void BroadcastMessage( INetMessage &msg, IRecipientFilter &filter ) = 0; - - virtual void DisconnectClient( IClient *client, const char *reason ) = 0; -}; - - -#endif // ISERVER_H diff --git a/public/iserverentity.h b/public/iserverentity.h deleted file mode 100644 index 93b0a495e..000000000 --- a/public/iserverentity.h +++ /dev/null @@ -1,42 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ISERVERENTITY_H -#define ISERVERENTITY_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "iserverunknown.h" -#include "string_t.h" - - - -struct Ray_t; -class ServerClass; -class ICollideable; -class IServerNetworkable; -class Vector; -class QAngle; - -// This class is how the engine talks to entities in the game DLL. -// CBaseEntity implements this interface. -class IServerEntity : public IServerUnknown -{ -public: - virtual ~IServerEntity() {} - -// Previously in pev - virtual int GetModelIndex( void ) const = 0; - virtual string_t GetModelName( void ) const = 0; - - virtual void SetModelIndex( int index ) = 0; -}; - - -#endif // ISERVERENTITY_H diff --git a/public/iservernetworkable.h b/public/iservernetworkable.h deleted file mode 100644 index d1145a2c9..000000000 --- a/public/iservernetworkable.h +++ /dev/null @@ -1,114 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ISERVERNETWORKABLE_H -#define ISERVERNETWORKABLE_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "ihandleentity.h" -#include "basetypes.h" -#include "bitvec.h" -#include "const.h" -#include "bspfile.h" - - - -// Entities can span this many clusters before we revert to a slower area checking algorithm -#define MAX_FAST_ENT_CLUSTERS 4 -#define MAX_ENT_CLUSTERS 64 -#define MAX_WORLD_AREAS 8 - - -class ServerClass; -class SendTable; -struct edict_t; -class CBaseEntity; -class CSerialEntity; -class CBaseNetworkable; - - -class CCheckTransmitInfo -{ -public: - edict_t *m_pClientEnt; // pointer to receiver edict - byte m_PVS[PAD_NUMBER( MAX_MAP_CLUSTERS,8 ) / 8]; - int m_nPVSSize; // PVS size in bytes - - CBitVec *m_pTransmitEdict; // entity n is already marked for transmission - CBitVec *m_pTransmitAlways; // entity n is always send even if not in PVS (HLTV only) - - int m_AreasNetworked; // number of networked areas - int m_Areas[MAX_WORLD_AREAS]; // the areas - - // This is used to determine visibility, so if the previous state - // is the same as the current state (along with pvs and areas networked), - // then the parts of the map that the player can see haven't changed. - byte m_AreaFloodNums[MAX_MAP_AREAS]; - int m_nMapAreas; -}; - -//----------------------------------------------------------------------------- -// Stores information necessary to perform PVS testing. -//----------------------------------------------------------------------------- -struct PVSInfo_t -{ - // headnode for the entity's bounding box - short m_nHeadNode; - - // number of clusters or -1 if too many - short m_nClusterCount; - - // cluster indices - unsigned short *m_pClusters; - - // For dynamic "area portals" - short m_nAreaNum; - short m_nAreaNum2; - - // current position - float m_vCenter[3]; - -private: - unsigned short m_pClustersInline[MAX_FAST_ENT_CLUSTERS]; - - friend class CVEngineServer; -}; - - -// IServerNetworkable is the interface the engine uses for all networkable data. -class IServerNetworkable -{ -// These functions are handled automatically by the server_class macros and CBaseNetworkable. -public: - // Gets at the entity handle associated with the collideable - virtual IHandleEntity *GetEntityHandle() = 0; - - // Tell the engine which class this object is. - virtual ServerClass* GetServerClass() = 0; - - virtual edict_t *GetEdict() const = 0; - - virtual const char* GetClassName() const = 0; - virtual void Release() = 0; - - virtual int AreaNum() const = 0; - - // In place of a generic QueryInterface. - virtual CBaseNetworkable* GetBaseNetworkable() = 0; - virtual CBaseEntity* GetBaseEntity() = 0; // Only used by game code. - virtual PVSInfo_t* GetPVSInfo() = 0; // get current visibilty data - -protected: - // Should never call delete on this! - virtual ~IServerNetworkable() {} -}; - - -#endif // ISERVERNETWORKABLE_H diff --git a/public/iserverunknown.h b/public/iserverunknown.h deleted file mode 100644 index 7fc47eebe..000000000 --- a/public/iserverunknown.h +++ /dev/null @@ -1,35 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ISERVERUNKNOWN_H -#define ISERVERUNKNOWN_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "ihandleentity.h" - -class ICollideable; -class IServerNetworkable; -class CBaseEntity; - - -// This is the server's version of IUnknown. We may want to use a QueryInterface-like -// mechanism if this gets big. -class IServerUnknown : public IHandleEntity -{ -public: - // Gets the interface to the collideable + networkable representation of the entity - virtual ICollideable* GetCollideable() = 0; - virtual IServerNetworkable* GetNetworkable() = 0; - virtual CBaseEntity* GetBaseEntity() = 0; -}; - - -#endif // ISERVERUNKNOWN_H diff --git a/public/ishadercompiledll.h b/public/ishadercompiledll.h deleted file mode 100644 index 57deefd1b..000000000 --- a/public/ishadercompiledll.h +++ /dev/null @@ -1,26 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ISHADERCOMPILEDLL_H -#define ISHADERCOMPILEDLL_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "interface.h" - -#define SHADER_COMPILE_INTERFACE_VERSION "shadercompiledll_0" - -// This is the DLL interface to ShaderCompile -abstract_class IShaderCompileDLL -{ -public: - // All vrad.exe does is load the VRAD DLL and run this. - virtual int main( int argc, char **argv ) = 0; -}; - -#endif // ISHADERCOMPILEDLL_H diff --git a/public/isoundcombiner.h b/public/isoundcombiner.h deleted file mode 100644 index db4c564ab..000000000 --- a/public/isoundcombiner.h +++ /dev/null @@ -1,40 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ISOUNDCOMBINER_H -#define ISOUNDCOMBINER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "utlvector.h" - -class IFileSystem; - -struct CombinerEntry -{ - CombinerEntry() - { - wavefile[ 0 ] = 0; - startoffset = 0.0f; - } - - char wavefile[ MAX_PATH ]; - float startoffset; -}; - -abstract_class ISoundCombiner -{ -public: - virtual ~ISoundCombiner() {} - - virtual bool CombineSoundFiles( IFileSystem *filesystem, char const *outfile, CUtlVector< CombinerEntry >& info ) = 0; - virtual bool IsCombinedFileChecksumValid( IFileSystem *filesystem, char const *outfile, CUtlVector< CombinerEntry >& info ) = 0; -}; - -extern ISoundCombiner *soundcombiner; - -#endif // ISOUNDCOMBINER_H diff --git a/public/ispatialpartition.h b/public/ispatialpartition.h deleted file mode 100644 index 7af45489b..000000000 --- a/public/ispatialpartition.h +++ /dev/null @@ -1,213 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Revision: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef ISPATIALPARTITION_H -#define ISPATIALPARTITION_H - -#include "interface.h" - -//----------------------------------------------------------------------------- -// forward declarations -//----------------------------------------------------------------------------- - -class Vector; -struct Ray_t; -class IHandleEntity; - - -#define INTERFACEVERSION_SPATIALPARTITION "SpatialPartition001" - -//----------------------------------------------------------------------------- -// These are the various partition lists. Note some are server only, some -// are client only -//----------------------------------------------------------------------------- - -enum -{ - PARTITION_ENGINE_SOLID_EDICTS = (1 << 0), // every edict_t that isn't SOLID_TRIGGER or SOLID_NOT (and static props) - PARTITION_ENGINE_TRIGGER_EDICTS = (1 << 1), // every edict_t that IS SOLID_TRIGGER - PARTITION_CLIENT_SOLID_EDICTS = (1 << 2), - PARTITION_CLIENT_RESPONSIVE_EDICTS = (1 << 3), // these are client-side only objects that respond to being forces, etc. - PARTITION_ENGINE_NON_STATIC_EDICTS = (1 << 4), // everything in solid & trigger except the static props, includes SOLID_NOTs - PARTITION_CLIENT_STATIC_PROPS = (1 << 5), - PARTITION_ENGINE_STATIC_PROPS = (1 << 6), - PARTITION_CLIENT_NON_STATIC_EDICTS = (1 << 7), // everything except the static props -}; - -// Use this to look for all client edicts. -#define PARTITION_ALL_CLIENT_EDICTS ( \ - PARTITION_CLIENT_NON_STATIC_EDICTS | \ - PARTITION_CLIENT_STATIC_PROPS | \ - PARTITION_CLIENT_RESPONSIVE_EDICTS | \ - PARTITION_CLIENT_SOLID_EDICTS \ - ) - - -// These are the only handles in the spatial partition that the game is controlling (everything but static props) -// These masks are used to handle updating the dirty spatial partition list in each game DLL -#define PARTITION_CLIENT_GAME_EDICTS (PARTITION_ALL_CLIENT_EDICTS & ~PARTITION_CLIENT_STATIC_PROPS) -#define PARTITION_SERVER_GAME_EDICTS (PARTITION_ENGINE_SOLID_EDICTS|PARTITION_ENGINE_TRIGGER_EDICTS|PARTITION_ENGINE_NON_STATIC_EDICTS) - -//----------------------------------------------------------------------------- -// Clients that want to know about all elements within a particular -// volume must inherit from this -//----------------------------------------------------------------------------- - -enum IterationRetval_t -{ - ITERATION_CONTINUE = 0, - ITERATION_STOP, -}; - - -typedef unsigned short SpatialPartitionHandle_t; - -// A combination of the PARTITION_ flags above. -typedef int SpatialPartitionListMask_t; - -typedef int SpatialTempHandle_t; - - -//----------------------------------------------------------------------------- -// Any search in the CSpatialPartition must use this to filter out entities it doesn't want. -// You're forced to use listMasks because it can filter by listMasks really fast. Any other -// filtering can be done by EnumElement. -//----------------------------------------------------------------------------- - -class IPartitionEnumerator -{ -public: - virtual IterationRetval_t EnumElement( IHandleEntity *pHandleEntity ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Installs a callback to call right before a spatial partition query occurs -//----------------------------------------------------------------------------- -class IPartitionQueryCallback -{ -public: - virtual void OnPreQuery_V1() = 0; - virtual void OnPreQuery( SpatialPartitionListMask_t listMask ) = 0; - virtual void OnPostQuery( SpatialPartitionListMask_t listMask ) = 0; -}; - - -//----------------------------------------------------------------------------- -// This is the spatial partition manager, groups objects into buckets -//----------------------------------------------------------------------------- -enum -{ - PARTITION_INVALID_HANDLE = (SpatialPartitionHandle_t)~0 -}; - - -abstract_class ISpatialPartition -{ -public: - virtual ~ISpatialPartition() {} - - // Create/destroy a handle for this dude in our system. Destroy - // will also remove it from all lists it happens to be in - virtual SpatialPartitionHandle_t CreateHandle( IHandleEntity *pHandleEntity ) = 0; - - // A fast method of creating a handle + inserting into the tree in the right place - virtual SpatialPartitionHandle_t CreateHandle( IHandleEntity *pHandleEntity, - SpatialPartitionListMask_t listMask, const Vector& mins, const Vector& maxs ) = 0; - - virtual void DestroyHandle( SpatialPartitionHandle_t handle ) = 0; - - // Adds, removes an handle from a particular spatial partition list - // There can be multiple partition lists; each has a unique id - virtual void Insert( SpatialPartitionListMask_t listMask, - SpatialPartitionHandle_t handle ) = 0; - virtual void Remove( SpatialPartitionListMask_t listMask, - SpatialPartitionHandle_t handle ) = 0; - - // Same as calling Remove() then Insert(). For performance-sensitive areas where you want to save a call. - virtual void RemoveAndInsert( SpatialPartitionListMask_t removeMask, SpatialPartitionListMask_t insertMask, - SpatialPartitionHandle_t handle ) = 0; - - // This will remove a particular handle from all lists - virtual void Remove( SpatialPartitionHandle_t handle ) = 0; - - // Call this when an entity moves... - virtual void ElementMoved( SpatialPartitionHandle_t handle, - const Vector& mins, const Vector& maxs ) = 0; - - // A fast method to insert + remove a handle from the tree... - // This is used to suppress collision of a single model.. - virtual SpatialTempHandle_t HideElement( SpatialPartitionHandle_t handle ) = 0; - virtual void UnhideElement( SpatialPartitionHandle_t handle, SpatialTempHandle_t tempHandle ) = 0; - - // Installs callbacks to get called right before a query occurs - virtual void InstallQueryCallback_V1( IPartitionQueryCallback *pCallback ) = 0; - virtual void RemoveQueryCallback( IPartitionQueryCallback *pCallback ) = 0; - - // Gets all entities in a particular volume... - // if coarseTest == true, it'll return all elements that are in - // spatial partitions that intersect the box - // if coarseTest == false, it'll return only elements that truly intersect - virtual void EnumerateElementsInBox( - SpatialPartitionListMask_t listMask, - const Vector& mins, - const Vector& maxs, - bool coarseTest, - IPartitionEnumerator* pIterator - ) = 0; - - virtual void EnumerateElementsInSphere( - SpatialPartitionListMask_t listMask, - const Vector& origin, - float radius, - bool coarseTest, - IPartitionEnumerator* pIterator - ) = 0; - - virtual void EnumerateElementsAlongRay( - SpatialPartitionListMask_t listMask, - const Ray_t& ray, - bool coarseTest, - IPartitionEnumerator* pIterator - ) = 0; - - virtual void EnumerateElementsAtPoint( - SpatialPartitionListMask_t listMask, - const Vector& pt, - bool coarseTest, - IPartitionEnumerator* pIterator - ) = 0; - - // For debugging.... suppress queries on particular lists - virtual void SuppressLists( SpatialPartitionListMask_t nListMask, bool bSuppress ) = 0; - virtual SpatialPartitionListMask_t GetSuppressedLists() = 0; - - virtual void RenderAllObjectsInTree( float flTime ) = 0; - virtual void RenderObjectsInPlayerLeafs( const Vector &vecPlayerMin, const Vector &vecPlayerMax, float flTime ) = 0; - virtual void RenderLeafsForRayTraceStart( float flTime ) = 0; - virtual void RenderLeafsForRayTraceEnd( void ) = 0; - virtual void RenderLeafsForHullTraceStart( float flTime ) = 0; - virtual void RenderLeafsForHullTraceEnd( void ) = 0; - virtual void RenderLeafsForBoxStart( float flTime ) = 0; - virtual void RenderLeafsForBoxEnd( void ) = 0; - virtual void RenderLeafsForSphereStart( float flTime ) = 0; - virtual void RenderLeafsForSphereEnd( void ) = 0; - - virtual void RenderObjectsInBox( const Vector &vecMin, const Vector &vecMax, float flTime ) = 0; - virtual void RenderObjectsInSphere( const Vector &vecCenter, float flRadius, float flTime ) = 0; - virtual void RenderObjectsAlongRay( const Ray_t& ray, float flTime ) = 0; - - virtual void ReportStats( const char *pFileName ) = 0; - - virtual void InstallQueryCallback( IPartitionQueryCallback *pCallback ) = 0; -}; - -#endif - - - diff --git a/public/isqlwrapper.h b/public/isqlwrapper.h deleted file mode 100644 index 8b240bfc0..000000000 --- a/public/isqlwrapper.h +++ /dev/null @@ -1,116 +0,0 @@ -//========= Copyright 1996-2004, Valve LLC, All rights reserved. ============ -// -// Purpose: Sql wrapper, encapsulates basic SQL functionality -// -// $NoKeywords: $ -//============================================================================= -#ifndef ISQLWRAPPER_H -#define ISQLWRAPPER_H - -#include "tier0/platform.h" - -#ifdef _WIN32 -#pragma once -#endif - -// SQL column types -enum EColumnType -{ - SQL_NONE = 0, - SQL_INT, - SQL_STRING, - SQL_FLOAT, - SQL_TIME, - SQL_UINT64 -}; - - -//----------------------------------------------------------------------------- -// encapsulates a table's description -//----------------------------------------------------------------------------- -class ISQLTable -{ -public: - virtual int GetCSQLColumn() const = 0; - virtual const char *PchColumnName( int iSQLColumn ) const = 0; - virtual EColumnType GetEColumnType( int iSQLColumn ) const = 0; - virtual const char *PchName() const = 0; -}; - - -//----------------------------------------------------------------------------- -// encapsulates a database worth of tables -//----------------------------------------------------------------------------- -class ISQLTableSet -{ -public: - virtual int GetCSQLTable() const = 0; - virtual const ISQLTable *PSQLTable( int iSQLTable ) const = 0; -}; - - -//----------------------------------------------------------------------------- -// encapsulates a single returned row from a valid SQL query -//----------------------------------------------------------------------------- -class ISQLRow -{ -public: - virtual int GetCSQLRowData() const = 0; - virtual const char *PchData( int iSQLColumn ) const = 0; - virtual int NData( int iSQLColumn ) const = 0; - virtual uint64 UlData( int iSQLColumn ) const = 0; - virtual float FlData( int iSQLColumn ) const = 0; - virtual uint64 UlTime( int iSQLColumn ) const = 0; - virtual bool BData( int iSQLColumn ) const = 0; - virtual EColumnType GetEColumnType( int iSQLColumn ) const = 0; -}; - - -//----------------------------------------------------------------------------- -// encapsulates a result set, which is made up of a series of rows -// You need to call PNextResult() NRow() times to get all the results -// (there is no random access to the result set). -//----------------------------------------------------------------------------- -class IResultSet -{ -public: - virtual int GetCSQLRow() const = 0; - virtual const ISQLRow *PSQLRowNextResult() = 0; // note, not const on the class because it makes a new row object -}; - - -//----------------------------------------------------------------------------- -// This interface encapsulates a database connection and lets you operate on it. -// Use the ISQLWrapperFactory factory to get access to the interface. -// NOTE - you can only have one outstanding query at a time. When you are done with a query call FreeResult() -//----------------------------------------------------------------------------- -class ISQLWrapper -{ -public: - // run a SQL statement against the DB, typically an insert statement as no data is returned - virtual bool BInsert( const char *pchQueryString ) = 0; - // get a description of the tables associated with the db you connected to - virtual const ISQLTableSet *PSQLTableSetDescription() = 0; - // run a query against the db and then iterate the result set (you can only have 1 outstanding query at a time, and call FreeResults() when you are done) - virtual IResultSet *PResultSetQuery( const char *pchQueryString ) = 0; - // you MUST call then after you finish with the IResultSet from the above query - virtual void FreeResult() = 0; -}; - - -//----------------------------------------------------------------------------- -// This is a factory to create objects that let you interact with a MySQL database. -// Make sure you Free() any interfaces you create. -//----------------------------------------------------------------------------- -class ISQLWrapperFactory -{ -public: - // setup details about this db connection - virtual ISQLWrapper *Create( const char *pchDB, const char *pchHost, const char *pchUsername, const char *pchPassword ) = 0; - virtual void Free( ISQLWrapper *pSQLWrapper ) = 0; -}; - -#define INTERFACEVERSION_ISQLWRAPPER "ISQLWRAPPER001" - -#endif // ISQLWRAPPER_H - diff --git a/public/istudiorender.h b/public/istudiorender.h deleted file mode 100644 index f092fe282..000000000 --- a/public/istudiorender.h +++ /dev/null @@ -1,366 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef ISTUDIORENDER_H -#define ISTUDIORENDER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/interface.h" -#include "mathlib/vector.h" -#include "mathlib/vector4d.h" -#include "tier1/utlbuffer.h" -#include "tier1/utlvector.h" -#include "materialsystem/imaterial.h" -#include "materialsystem/imaterialsystem.h" -#include "appframework/IAppSystem.h" -#include "datacache/imdlcache.h" -#include "studio.h" - - -//----------------------------------------------------------------------------- -// forward declarations -//----------------------------------------------------------------------------- -struct studiohdr_t; -struct studiomeshdata_t; -class Vector; -struct LightDesc_t; -class IMaterial; -struct studiohwdata_t; -struct Ray_t; -class Vector4D; -class IMaterialSystem; -struct matrix3x4_t; -class IMesh; -struct vertexFileHeader_t; -struct FlashlightState_t; -class VMatrix; -namespace OptimizedModel { struct FileHeader_t; } -class IPooledVBAllocator; - -// undone: what's the standard for function type naming? -typedef void (*StudioRender_Printf_t)( const char *fmt, ... ); - -struct StudioRenderConfig_t -{ - float fEyeShiftX; // eye X position - float fEyeShiftY; // eye Y position - float fEyeShiftZ; // eye Z position - float fEyeSize; // adjustment to iris textures - float fEyeGlintPixelWidthLODThreshold; - - int maxDecalsPerModel; - int drawEntities; - int skin; - int fullbright; - - bool bEyeMove : 1; // look around - bool bSoftwareSkin : 1; - bool bNoHardware : 1; - bool bNoSoftware : 1; - bool bTeeth : 1; - bool bEyes : 1; - bool bFlex : 1; - bool bWireframe : 1; - bool bDrawNormals : 1; - bool bDrawTangentFrame : 1; - bool bDrawZBufferedWireframe : 1; - bool bSoftwareLighting : 1; - bool bShowEnvCubemapOnly : 1; - bool bWireframeDecals : 1; - - // Reserved for future use - int m_nReserved[4]; -}; - - - -//----------------------------------------------------------------------------- -// Studio render interface -//----------------------------------------------------------------------------- -DECLARE_POINTER_HANDLE( StudioDecalHandle_t ); -#define STUDIORENDER_DECAL_INVALID ( (StudioDecalHandle_t)0 ) - -enum -{ - ADDDECAL_TO_ALL_LODS = -1 -}; - - -//----------------------------------------------------------------------------- -// DrawModel flags -//----------------------------------------------------------------------------- -enum -{ - STUDIORENDER_DRAW_ENTIRE_MODEL = 0, - STUDIORENDER_DRAW_OPAQUE_ONLY = 0x01, - STUDIORENDER_DRAW_TRANSLUCENT_ONLY = 0x02, - STUDIORENDER_DRAW_GROUP_MASK = 0x03, - - STUDIORENDER_DRAW_NO_FLEXES = 0x04, - STUDIORENDER_DRAW_STATIC_LIGHTING = 0x08, - - STUDIORENDER_DRAW_ACCURATETIME = 0x10, // Use accurate timing when drawing the model. - STUDIORENDER_DRAW_NO_SHADOWS = 0x20, - STUDIORENDER_DRAW_GET_PERF_STATS = 0x40, - - STUDIORENDER_DRAW_WIREFRAME = 0x80, - - STUDIORENDER_DRAW_ITEM_BLINK = 0x100, - - STUDIORENDER_SHADOWDEPTHTEXTURE = 0x200 -}; - - -//----------------------------------------------------------------------------- -// Standard model vertex formats -//----------------------------------------------------------------------------- -// FIXME: remove these (materials/shaders should drive vertex format). Need to -// list required forcedmaterialoverrides in models/bsps (rather than -// all models supporting all possible overrides, as they do currently). -#define VERTEX_TEXCOORD0_2D ( ( (uint64) 2 ) << ( TEX_COORD_SIZE_BIT + ( 3*0 ) ) ) -enum MaterialVertexFormat_t -{ - MATERIAL_VERTEX_FORMAT_MODEL_SKINNED = (VertexFormat_t) VERTEX_POSITION | VERTEX_COLOR | VERTEX_NORMAL | VERTEX_TEXCOORD0_2D | VERTEX_BONEWEIGHT(2) | VERTEX_BONE_INDEX | VERTEX_USERDATA_SIZE(4), - MATERIAL_VERTEX_FORMAT_MODEL_SKINNED_DX7 = (VertexFormat_t) VERTEX_POSITION | VERTEX_COLOR | VERTEX_NORMAL | VERTEX_TEXCOORD0_2D | VERTEX_BONEWEIGHT(2) | VERTEX_BONE_INDEX, - MATERIAL_VERTEX_FORMAT_MODEL = (VertexFormat_t) VERTEX_POSITION | VERTEX_COLOR | VERTEX_NORMAL | VERTEX_TEXCOORD0_2D | VERTEX_USERDATA_SIZE(4), - MATERIAL_VERTEX_FORMAT_MODEL_DX7 = (VertexFormat_t) VERTEX_POSITION | VERTEX_COLOR | VERTEX_NORMAL | VERTEX_TEXCOORD0_2D, - MATERIAL_VERTEX_FORMAT_COLOR = (VertexFormat_t) VERTEX_SPECULAR -}; - - -//----------------------------------------------------------------------------- -// What kind of material override is it? -//----------------------------------------------------------------------------- -enum OverrideType_t -{ - OVERRIDE_NORMAL = 0, - OVERRIDE_BUILD_SHADOWS, - OVERRIDE_DEPTH_WRITE, -}; - - -//----------------------------------------------------------------------------- -// DrawModel info -//----------------------------------------------------------------------------- - -// Special flag for studio models that have a compiled in shadow lod version -// It's negative 2 since positive numbers == use a regular slot and -1 means -// have studiorender compute a value instead -enum -{ - USESHADOWLOD = -2, -}; - -// beyond this number of materials, you won't get info back from DrawModel -#define MAX_DRAW_MODEL_INFO_MATERIALS 8 - -struct DrawModelResults_t -{ - int m_ActualTriCount; - int m_TextureMemoryBytes; - int m_NumHardwareBones; - int m_NumBatches; - int m_NumMaterials; - int m_nLODUsed; - int m_flLODMetric; - CFastTimer m_RenderTime; - CUtlVectorFixed m_Materials; -}; - -struct ColorMeshInfo_t -{ - // A given color mesh can own a unique Mesh, or it can use a shared Mesh - // (in which case it uses a sub-range defined by m_nVertOffset and m_nNumVerts) - IMesh * m_pMesh; - IPooledVBAllocator * m_pPooledVBAllocator; - int m_nVertOffsetInBytes; - int m_nNumVerts; -}; - -struct DrawModelInfo_t -{ - studiohdr_t *m_pStudioHdr; - studiohwdata_t *m_pHardwareData; - StudioDecalHandle_t m_Decals; - int m_Skin; - int m_Body; - int m_HitboxSet; - void *m_pClientEntity; - int m_Lod; - ColorMeshInfo_t *m_pColorMeshes; - bool m_bStaticLighting; - Vector m_vecAmbientCube[6]; // ambient, and lights that aren't in locallight[] - int m_nLocalLightCount; - LightDesc_t m_LocalLightDescs[4]; -}; - -struct GetTriangles_Vertex_t -{ - Vector m_Position; - Vector m_Normal; - Vector4D m_TangentS; - Vector2D m_TexCoord; - Vector4D m_BoneWeight; - int m_BoneIndex[4]; - int m_NumBones; -}; - -struct GetTriangles_MaterialBatch_t -{ - IMaterial *m_pMaterial; - CUtlVector m_Verts; - CUtlVector m_TriListIndices; -}; - -struct GetTriangles_Output_t -{ - CUtlVector m_MaterialBatches; - matrix3x4_t m_PoseToWorld[MAXSTUDIOBONES]; -}; - - -struct model_array_instance_t -{ - matrix3x4_t modelToWorld; - - // UNDONE: Per instance lighting values? -}; - -//----------------------------------------------------------------------------- -// Cache Callback Function -// implementation can either statically persist data (tools) or lru cache (engine) it. -// caller returns base pointer to resident data. -// code expectes data to be dynamic and invokes cache callback prior to iterative access. -// virtualModel is member passed in via studiohdr_t and passed back for model identification. -//----------------------------------------------------------------------------- -#define STUDIO_DATA_CACHE_INTERFACE_VERSION "VStudioDataCache005" - -abstract_class IStudioDataCache : public IAppSystem -{ -public: - virtual bool VerifyHeaders( studiohdr_t *pStudioHdr ) = 0; - virtual vertexFileHeader_t *CacheVertexData( studiohdr_t *pStudioHdr ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Studio render interface -//----------------------------------------------------------------------------- -#define STUDIO_RENDER_INTERFACE_VERSION "VStudioRender025" - -abstract_class IStudioRender : public IAppSystem -{ -public: - virtual void BeginFrame( void ) = 0; - virtual void EndFrame( void ) = 0; - - // Used for the mat_stub console command. - virtual void Mat_Stub( IMaterialSystem *pMatSys ) = 0; - - // Updates the rendering configuration - virtual void UpdateConfig( const StudioRenderConfig_t& config ) = 0; - virtual void GetCurrentConfig( StudioRenderConfig_t& config ) = 0; - - // Load, unload model data - virtual bool LoadModel( studiohdr_t *pStudioHdr, void *pVtxData, studiohwdata_t *pHardwareData ) = 0; - virtual void UnloadModel( studiohwdata_t *pHardwareData ) = 0; - - // Refresh the studiohdr since it was lost... - virtual void RefreshStudioHdr( studiohdr_t* pStudioHdr, studiohwdata_t* pHardwareData ) = 0; - - // This is needed to do eyeglint and calculate the correct texcoords for the eyes. - virtual void SetEyeViewTarget( const studiohdr_t *pStudioHdr, int nBodyIndex, const Vector& worldPosition ) = 0; - - // Methods related to lighting state - // NOTE: SetAmbientLightColors assumes that the arraysize is the same as - // returned from GetNumAmbientLightSamples - virtual int GetNumAmbientLightSamples() = 0; - virtual const Vector *GetAmbientLightDirections() = 0; - virtual void SetAmbientLightColors( const Vector4D *pAmbientOnlyColors ) = 0; - virtual void SetAmbientLightColors( const Vector *pAmbientOnlyColors ) = 0; - virtual void SetLocalLights( int numLights, const LightDesc_t *pLights ) = 0; - - // Sets information about the camera location + orientation - virtual void SetViewState( const Vector& viewOrigin, const Vector& viewRight, - const Vector& viewUp, const Vector& viewPlaneNormal ) = 0; - - // Allocates flex weights for use in rendering - // NOTE: Pass in a non-null second parameter to lock delayed flex weights - virtual void LockFlexWeights( int nWeightCount, float **ppFlexWeights, float **ppFlexDelayedWeights = NULL ) = 0; - virtual void UnlockFlexWeights() = 0; - - // Used to allocate bone matrices to be used to pass into DrawModel - virtual matrix3x4_t* LockBoneMatrices( int nBoneCount ) = 0; - virtual void UnlockBoneMatrices() = 0; - - // LOD stuff - virtual int GetNumLODs( const studiohwdata_t &hardwareData ) const = 0; - virtual float GetLODSwitchValue( const studiohwdata_t &hardwareData, int lod ) const = 0; - virtual void SetLODSwitchValue( studiohwdata_t &hardwareData, int lod, float switchValue ) = 0; - - // Sets the color/alpha modulation - virtual void SetColorModulation( float const* pColor ) = 0; - virtual void SetAlphaModulation( float flAlpha ) = 0; - - // Draws the model - virtual void DrawModel( DrawModelResults_t *pResults, const DrawModelInfo_t& info, - matrix3x4_t *pBoneToWorld, float *pFlexWeights, float *pFlexDelayedWeights, const Vector &modelOrigin, int flags = STUDIORENDER_DRAW_ENTIRE_MODEL ) = 0; - - // Methods related to static prop rendering - virtual void DrawModelStaticProp( const DrawModelInfo_t& drawInfo, const matrix3x4_t &modelToWorld, int flags = STUDIORENDER_DRAW_ENTIRE_MODEL ) = 0; - virtual void DrawStaticPropDecals( const DrawModelInfo_t &drawInfo, const matrix3x4_t &modelToWorld ) = 0; - virtual void DrawStaticPropShadows( const DrawModelInfo_t &drawInfo, const matrix3x4_t &modelToWorld, int flags ) = 0; - - // Causes a material to be used instead of the materials the model was compiled with - virtual void ForcedMaterialOverride( IMaterial *newMaterial, OverrideType_t nOverrideType = OVERRIDE_NORMAL ) = 0; - - // Create, destroy list of decals for a particular model - virtual StudioDecalHandle_t CreateDecalList( studiohwdata_t *pHardwareData ) = 0; - virtual void DestroyDecalList( StudioDecalHandle_t handle ) = 0; - - // Add decals to a decal list by doing a planar projection along the ray - // The BoneToWorld matrices must be set before this is called - virtual void AddDecal( StudioDecalHandle_t handle, studiohdr_t *pStudioHdr, matrix3x4_t *pBoneToWorld, - const Ray_t & ray, const Vector& decalUp, IMaterial* pDecalMaterial, float radius, int body, bool noPokethru = false, int maxLODToDecal = ADDDECAL_TO_ALL_LODS ) = 0; - - // Compute the lighting at a point and normal - virtual void ComputeLighting( const Vector* pAmbient, int lightCount, - LightDesc_t* pLights, const Vector& pt, const Vector& normal, Vector& lighting ) = 0; - - // Compute the lighting at a point, constant directional component is passed - // as flDirectionalAmount - virtual void ComputeLightingConstDirectional( const Vector* pAmbient, int lightCount, - LightDesc_t* pLights, const Vector& pt, const Vector& normal, Vector& lighting, float flDirectionalAmount ) = 0; - - // Shadow state (affects the models as they are rendered) - virtual void AddShadow( IMaterial* pMaterial, void* pProxyData, FlashlightState_t *m_pFlashlightState = NULL, VMatrix *pWorldToTexture = NULL, ITexture *pFlashlightDepthTexture = NULL ) = 0; - virtual void ClearAllShadows() = 0; - - // Gets the model LOD; pass in the screen size in pixels of a sphere - // of radius 1 that has the same origin as the model to get the LOD out... - virtual int ComputeModelLod( studiohwdata_t* pHardwareData, float unitSphereSize, float *pMetric = NULL ) = 0; - - // Return a number that is usable for budgets, etc. - // Things that we care about: - // 1) effective triangle count (factors in batch sizes, state changes, etc) - // 2) texture memory usage - // Get Triangles returns the LOD used - virtual void GetPerfStats( DrawModelResults_t *pResults, const DrawModelInfo_t &info, CUtlBuffer *pSpewBuf = NULL ) const = 0; - virtual void GetTriangles( const DrawModelInfo_t& info, matrix3x4_t *pBoneToWorld, GetTriangles_Output_t &out ) = 0; - - // Returns materials used by a particular model - virtual int GetMaterialList( studiohdr_t *pStudioHdr, int count, IMaterial** ppMaterials ) = 0; - virtual int GetMaterialListFromBodyAndSkin( MDLHandle_t studio, int nSkin, int nBody, int nCountOutputMaterials, IMaterial** ppOutputMaterials ) = 0; - // draw an array of models with the same state - virtual void DrawModelArray( const DrawModelInfo_t &drawInfo, int arrayCount, model_array_instance_t *pInstanceData, int instanceStride, int flags = STUDIORENDER_DRAW_ENTIRE_MODEL ) = 0; -}; - -extern IStudioRender *g_pStudioRender; - -#endif // ISTUDIORENDER_H diff --git a/public/ivguicenterprint.h b/public/ivguicenterprint.h deleted file mode 100644 index 897784daf..000000000 --- a/public/ivguicenterprint.h +++ /dev/null @@ -1,39 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#if !defined( IVGUICENTERPRINT_H ) -#define IVGUICENTERPRINT_H -#ifdef _WIN32 -#pragma once -#endif - -#include "interface.h" - -//----------------------------------------------------------------------------- -// Purpose: Engine Center Print Interface -//----------------------------------------------------------------------------- -abstract_class ICenterPrint -{ -public: - virtual void SetTextColor( int r, int g, int b, int a ) = 0; - virtual void Print( char *text ) = 0; - virtual void Print( wchar_t *text ) = 0; - virtual void ColorPrint( int r, int g, int b, int a, char *text ) = 0; - virtual void ColorPrint( int r, int g, int b, int a, wchar_t *text ) = 0; - virtual void Clear( void ) = 0; -}; - -extern ICenterPrint *centerprint; - -#define VCENTERPRINT_INTERFACE_VERSION "VCENTERPRINT002" - -#endif // IVGUICENTERPRINT_H diff --git a/public/ivoiceserver.h b/public/ivoiceserver.h deleted file mode 100644 index 168939dd5..000000000 --- a/public/ivoiceserver.h +++ /dev/null @@ -1,34 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: This module defines the IVoiceServer interface, which is used by -// game code to control which clients are listening to which other -// clients' voice streams. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IVOICESERVER_H -#define IVOICESERVER_H - - -#include "interface.h" - - -#define INTERFACEVERSION_VOICESERVER "VoiceServer002" - - -abstract_class IVoiceServer -{ -public: - virtual ~IVoiceServer() {} - - // Use these to setup who can hear whose voice. - // Pass in client indices (which are their ent indices - 1). - virtual bool GetClientListening(int iReceiver, int iSender) = 0; - virtual bool SetClientListening(int iReceiver, int iSender, bool bListen) = 0; - virtual bool SetClientProximity(int iReceiver, int iSender, bool bUseProximity) = 0; -}; - - -#endif - diff --git a/public/ivoicetweak.h b/public/ivoicetweak.h deleted file mode 100644 index 017ea834c..000000000 --- a/public/ivoicetweak.h +++ /dev/null @@ -1,40 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IVOICETWEAK_H -#define IVOICETWEAK_H -#ifdef _WIN32 -#pragma once -#endif - -// These provide access to the voice controls. -typedef enum -{ - MicrophoneVolume=0, // values 0-1. - OtherSpeakerScale, // values 0-1. Scales how loud other players are. - MicBoost, - SpeakingVolume, // values 0-1. Current voice volume received through Voice Tweak mode - -} VoiceTweakControl; - - -typedef struct IVoiceTweak_s -{ - // These turn voice tweak mode on and off. While in voice tweak mode, the user's voice is echoed back - // without sending to the server. - int (*StartVoiceTweakMode)(); // Returns 0 on error. - void (*EndVoiceTweakMode)(); - - // Get/set control values. - void (*SetControlFloat)(VoiceTweakControl iControl, float value); - float (*GetControlFloat)(VoiceTweakControl iControl); - - bool (*IsStillTweaking)(); // This can return false if the user restarts the sound system during voice tweak mode -} IVoiceTweak; - - -#endif // IVOICETWEAK_H diff --git a/public/ivraddll.h b/public/ivraddll.h deleted file mode 100644 index 2739272ac..000000000 --- a/public/ivraddll.h +++ /dev/null @@ -1,99 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IVRADDLL_H -#define IVRADDLL_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "interface.h" -#include "bspfile.h" - - -#define VRAD_INTERFACE_VERSION "vraddll_1" - - -class CBSPInfo -{ -public: - byte *dlightdata; - int lightdatasize; - - dface_t *dfaces; - unsigned char *m_pFacesTouched; // If non-null, then this has 1 byte for each face and - // tells which faces had their lightmaps updated. - int numfaces; - - dvertex_t *dvertexes; - int numvertexes; - - dedge_t *dedges; - int numedges; - - int *dsurfedges; - int numsurfedges; - - texinfo_t *texinfo; - int numtexinfo; - - dtexdata_t *dtexdata; - int numtexdata; - - ddispinfo_t *g_dispinfo; - int g_numdispinfo; - - char *texDataStringData; - int nTexDataStringData; - - int *texDataStringTable; - int nTexDataStringTable; -}; - - -// This is the DLL interface to VRAD. -class IVRadDLL -{ -public: - // All vrad.exe does is load the VRAD DLL and run this. - virtual int main( int argc, char **argv ) = 0; - - - // Load the BSP file into memory. - virtual bool Init( char const *pFilename ) = 0; - - // You must call this if you call Init(), to free resources. - virtual void Release() = 0; - - // Get some data from the BSP file that's in memory. - virtual void GetBSPInfo( CBSPInfo *pInfo ) = 0; - - // Incrementally relight the BSP file in memory given the new entity - // descriptions in pVMFFile. pVMFFile should only contain light entities. - // - // Returns true only if the lightmaps are updated. If the process is - // interrupted or there is an error, false is returned. - virtual bool DoIncrementalLight( char const *pVMFFile ) = 0; - - // Calling DoIncrementalLight doesn't actually write anything to disk. - // Calling this will write the incremental light file out and will write the - // current in-memory light data into the BSP. - // NOTE: if DoIncrementalLight never finished, this will do nothing and return false. - virtual bool Serialize() = 0; - - // Returns a 0-1 value telling how close it is to completing the task. - // This can be called from a separate thread than DoIncrementLight. - virtual float GetPercentComplete() = 0; - - // This can be called from a separate thread than the DoIncrementalLight thread. - // It asynchronously tells DoIncrementalLight to stop as soon as possible and exit. - virtual void Interrupt() = 0; -}; - - -#endif // IVRADDLL_H diff --git a/public/ivrenderview.h b/public/ivrenderview.h deleted file mode 100644 index 67c9e4d54..000000000 --- a/public/ivrenderview.h +++ /dev/null @@ -1,312 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $Workfile: $ -// $NoKeywords: $ -//===========================================================================// -#if !defined( IVRENDERVIEW_H ) -#define IVRENDERVIEW_H -#ifdef _WIN32 -#pragma once -#endif - -#include "basetypes.h" -#include "mathlib/vplane.h" -#include "interface.h" -#include "materialsystem/imaterialsystem.h" -#include "const.h" -#include "tier1/refcount.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class CViewSetup; -class CEngineSprite; -class IClientEntity; -class IMaterial; -struct model_t; -class IClientRenderable; - - -//----------------------------------------------------------------------------- -// Flags used by DrawWorldLists -//----------------------------------------------------------------------------- -enum -{ - DRAWWORLDLISTS_DRAW_STRICTLYABOVEWATER = 0x001, - DRAWWORLDLISTS_DRAW_STRICTLYUNDERWATER = 0x002, - DRAWWORLDLISTS_DRAW_INTERSECTSWATER = 0x004, - DRAWWORLDLISTS_DRAW_WATERSURFACE = 0x008, - DRAWWORLDLISTS_DRAW_SKYBOX = 0x010, - DRAWWORLDLISTS_DRAW_CLIPSKYBOX = 0x020, - DRAWWORLDLISTS_DRAW_SHADOWDEPTH = 0x040, - DRAWWORLDLISTS_DRAW_REFRACTION = 0x080, - DRAWWORLDLISTS_DRAW_REFLECTION = 0x100, -}; - -enum -{ - MAT_SORT_GROUP_STRICTLY_ABOVEWATER = 0, - MAT_SORT_GROUP_STRICTLY_UNDERWATER, - MAT_SORT_GROUP_INTERSECTS_WATER_SURFACE, - MAT_SORT_GROUP_WATERSURFACE, - - MAX_MAT_SORT_GROUPS -}; - - -typedef VPlane Frustum[FRUSTUM_NUMPLANES]; - - -//----------------------------------------------------------------------------- -// Leaf index -//----------------------------------------------------------------------------- -typedef unsigned short LeafIndex_t; -typedef short LeafFogVolume_t; -enum -{ - INVALID_LEAF_INDEX = (LeafIndex_t)~0 -}; - - -//----------------------------------------------------------------------------- -// Describes the leaves to be rendered this view, set by BuildWorldLists -//----------------------------------------------------------------------------- -struct WorldListInfo_t -{ - int m_ViewFogVolume; - int m_LeafCount; - LeafIndex_t* m_pLeafList; - LeafFogVolume_t* m_pLeafFogVolume; -}; - -class IWorldRenderList : public IRefCounted -{ -}; - -//----------------------------------------------------------------------------- -// Describes the fog volume for a particular point -//----------------------------------------------------------------------------- -struct VisibleFogVolumeInfo_t -{ - int m_nVisibleFogVolume; - int m_nVisibleFogVolumeLeaf; - bool m_bEyeInFogVolume; - float m_flDistanceToWater; - float m_flWaterHeight; - IMaterial *m_pFogVolumeMaterial; -}; - - -//----------------------------------------------------------------------------- -// Vertex format for brush models -//----------------------------------------------------------------------------- -struct BrushVertex_t -{ - Vector m_Pos; - Vector m_Normal; - Vector m_TangentS; - Vector m_TangentT; - Vector2D m_TexCoord; - Vector2D m_LightmapCoord; - -private: - BrushVertex_t( const BrushVertex_t& src ); -}; - -//----------------------------------------------------------------------------- -// Visibility data for area portal culling -//----------------------------------------------------------------------------- -struct VisOverrideData_t -{ - Vector m_vecVisOrigin; // The point to to use as the viewpoint for area portal backface cull checks. - float m_fDistToAreaPortalTolerance; // The distance from an area portal before using the full screen as the viewable portion. -}; - - -//----------------------------------------------------------------------------- -// interface for asking about the Brush surfaces from the client DLL -//----------------------------------------------------------------------------- - -class IBrushSurface -{ -public: - // Computes texture coordinates + lightmap coordinates given a world position - virtual void ComputeTextureCoordinate( Vector const& worldPos, Vector2D& texCoord ) = 0; - virtual void ComputeLightmapCoordinate( Vector const& worldPos, Vector2D& lightmapCoord ) = 0; - - // Gets the vertex data for this surface - virtual int GetVertexCount() const = 0; - virtual void GetVertexData( BrushVertex_t* pVerts ) = 0; - - // Gets at the material properties for this surface - virtual IMaterial* GetMaterial() = 0; -}; - - -//----------------------------------------------------------------------------- -// interface for installing a new renderer for brush surfaces -//----------------------------------------------------------------------------- - -class IBrushRenderer -{ -public: - // Draws the surface; returns true if decals should be rendered on this surface - virtual bool RenderBrushModelSurface( IClientEntity* pBaseEntity, IBrushSurface* pBrushSurface ) = 0; -}; - - -#define MAX_VIS_LEAVES 32 -//----------------------------------------------------------------------------- -// Purpose: Interface to client .dll to set up a rendering pass over world -// The client .dll can call Render multiple times to overlay one or more world -// views on top of one another -//----------------------------------------------------------------------------- -class IVRenderView -{ -public: - - // Draw normal brush model. - // If pMaterialOverride is non-null, then all the faces of the bmodel will - // set this material rather than their regular material. - virtual void DrawBrushModel( - IClientEntity *baseentity, - model_t *model, - const Vector& origin, - const QAngle& angles, - bool sort ) = 0; - - // Draw brush model that has no origin/angles change ( uses identity transform ) - // FIXME, Material proxy IClientEntity *baseentity is unused right now, use DrawBrushModel for brushes with - // proxies for now. - virtual void DrawIdentityBrushModel( IWorldRenderList *pList, model_t *model ) = 0; - - // Mark this dynamic light as having changed this frame ( so light maps affected will be recomputed ) - virtual void TouchLight( struct dlight_t *light ) = 0; - // Draw 3D Overlays - virtual void Draw3DDebugOverlays( void ) = 0; - // Sets global blending fraction - virtual void SetBlend( float blend ) = 0; - virtual float GetBlend( void ) = 0; - - // Sets global color modulation - virtual void SetColorModulation( float const* blend ) = 0; - virtual void GetColorModulation( float* blend ) = 0; - - // Wrap entire scene drawing - virtual void SceneBegin( void ) = 0; - virtual void SceneEnd( void ) = 0; - - // Gets the fog volume for a particular point - virtual void GetVisibleFogVolume( const Vector& eyePoint, VisibleFogVolumeInfo_t *pInfo ) = 0; - - // Wraps world drawing - // If iForceViewLeaf is not -1, then it uses the specified leaf as your starting area for setting up area portal culling. - // This is used by water since your reflected view origin is often in solid space, but we still want to treat it as though - // the first portal we're looking out of is a water portal, so our view effectively originates under the water. - virtual IWorldRenderList * CreateWorldList() = 0; - - virtual void BuildWorldLists( IWorldRenderList *pList, WorldListInfo_t* pInfo, int iForceFViewLeaf, const VisOverrideData_t* pVisData = NULL, bool bShadowDepth = false, float *pReflectionWaterHeight = NULL ) = 0; - virtual void DrawWorldLists( IWorldRenderList *pList, unsigned long flags, float waterZAdjust ) = 0; - - // Optimization for top view - virtual void DrawTopView( bool enable ) = 0; - virtual void TopViewBounds( Vector2D const& mins, Vector2D const& maxs ) = 0; - - // Draw lights - virtual void DrawLights( void ) = 0; - // FIXME: This function is a stub, doesn't do anything in the engine right now - virtual void DrawMaskEntities( void ) = 0; - - // Draw surfaces with alpha - virtual void DrawTranslucentSurfaces( IWorldRenderList *pList, int sortIndex, unsigned long flags, bool bShadowDepth ) = 0; - - // Draw Particles ( just draws the linefine for debugging map leaks ) - virtual void DrawLineFile( void ) = 0; - // Draw lightmaps - virtual void DrawLightmaps( IWorldRenderList *pList, int pageId ) = 0; - // Wraps view render sequence, sets up a view - virtual void ViewSetupVis( bool novis, int numorigins, const Vector origin[] ) = 0; - - // Return true if any of these leaves are visible in the current PVS. - virtual bool AreAnyLeavesVisible( int *leafList, int nLeaves ) = 0; - - virtual void VguiPaint( void ) = 0; - // Sets up view fade parameters - virtual void ViewDrawFade( byte *color, IMaterial *pMaterial ) = 0; - // Sets up the projection matrix for the specified field of view - virtual void OLD_SetProjectionMatrix( float fov, float zNear, float zFar ) = 0; - // Determine lighting at specified position - virtual colorVec GetLightAtPoint( Vector& pos ) = 0; - // Whose eyes are we looking through? - virtual int GetViewEntity( void ) = 0; - // Get engine field of view setting - virtual float GetFieldOfView( void ) = 0; - // 1 == ducking, 0 == not - virtual unsigned char **GetAreaBits( void ) = 0; - - // Set up fog for a particular leaf - virtual void SetFogVolumeState( int nVisibleFogVolume, bool bUseHeightFog ) = 0; - - // Installs a brush surface draw override method, null means use normal renderer - virtual void InstallBrushSurfaceRenderer( IBrushRenderer* pBrushRenderer ) = 0; - - // Draw brush model shadow - virtual void DrawBrushModelShadow( IClientRenderable *pRenderable ) = 0; - - // Does the leaf contain translucent surfaces? - virtual bool LeafContainsTranslucentSurfaces( IWorldRenderList *pList, int sortIndex, unsigned long flags ) = 0; - - virtual bool DoesBoxIntersectWaterVolume( const Vector &mins, const Vector &maxs, int leafWaterDataID ) = 0; - - virtual void SetAreaState( - unsigned char chAreaBits[MAX_AREA_STATE_BYTES], - unsigned char chAreaPortalBits[MAX_AREA_PORTAL_STATE_BYTES] ) = 0; - - // See i - virtual void VGui_Paint( int mode ) = 0; - - // Push, pop views (see PushViewFlags_t above for flags) - virtual void Push3DView( const CViewSetup &view, int nFlags, ITexture* pRenderTarget, Frustum frustumPlanes ) = 0; - virtual void Push2DView( const CViewSetup &view, int nFlags, ITexture* pRenderTarget, Frustum frustumPlanes ) = 0; - virtual void PopView( Frustum frustumPlanes ) = 0; - - // Sets the main view - virtual void SetMainView( const Vector &vecOrigin, const QAngle &angles ) = 0; - - enum - { - VIEW_SETUP_VIS_EX_RETURN_FLAGS_USES_RADIAL_VIS = 0x00000001 - }; - - // Wraps view render sequence, sets up a view - virtual void ViewSetupVisEx( bool novis, int numorigins, const Vector origin[], unsigned int &returnFlags ) = 0; - - //replaces the current view frustum with a rhyming replacement of your choice - virtual void OverrideViewFrustum( Frustum custom ) = 0; - - virtual void DrawBrushModelShadowDepth( IClientEntity *baseentity, model_t *model, const Vector& origin, const QAngle& angles, bool bSort ) = 0; - virtual void UpdateBrushModelLightmap( model_t *model, IClientRenderable *pRenderable ) = 0; - virtual void BeginUpdateLightmaps( void ) = 0; - virtual void EndUpdateLightmaps( void ) = 0; - virtual void OLD_SetOffCenterProjectionMatrix( float fov, float zNear, float zFar, float flAspectRatio, float flBottom, float flTop, float flLeft, float flRight ) = 0; - virtual void OLD_SetProjectionMatrixOrtho( float left, float top, float right, float bottom, float zNear, float zFar ) = 0; - virtual void Push3DView( const CViewSetup &view, int nFlags, ITexture* pRenderTarget, Frustum frustumPlanes, ITexture* pDepthTexture ) = 0; - virtual void GetMatricesForView( const CViewSetup &view, VMatrix *pWorldToView, VMatrix *pViewToProjection, VMatrix *pWorldToProjection, VMatrix *pWorldToPixels ) = 0; -}; - -// change this when the new version is incompatable with the old -#define VENGINE_RENDERVIEW_INTERFACE_VERSION "VEngineRenderView013" - -#if defined(_STATIC_LINKED) && defined(CLIENT_DLL) -namespace Client -{ -extern IVRenderView *render; -} -#else -extern IVRenderView *render; -#endif - -#endif // IVRENDERVIEW_H diff --git a/public/ivtex.h b/public/ivtex.h deleted file mode 100644 index 2bc6cf285..000000000 --- a/public/ivtex.h +++ /dev/null @@ -1,31 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef IVTEX_H -#define IVTEX_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/interface.h" - - -class IVTex -{ -public: - // For use by command-line tools - virtual int VTex( int argc, char **argv ) = 0; - - // For use by engine - virtual int VTex( CreateInterfaceFn filesystemFactory, const char *pGameDir, int argc, char **argv ) = 0; -}; - -#define IVTEX_VERSION_STRING "VTEX_003" - - -#endif // IVTEX_H diff --git a/public/ixboxsystem.h b/public/ixboxsystem.h deleted file mode 100644 index eedbc41a8..000000000 --- a/public/ixboxsystem.h +++ /dev/null @@ -1,83 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: Interface to Xbox 360 system functions. Helps deal with the async system and Live -// functions by either providing a handle for the caller to check results or handling -// automatic cleanup of the async data when the caller doesn't care about the results. -// -//===========================================================================// - -#ifndef IXBOXSYSTEM_H -#define IXBOXSYSTEM_H -#ifdef _WIN32 -#pragma once -#endif - -#if !defined( _X360 ) -#include "xbox/xboxstubs.h" -#endif - -typedef void* AsyncHandle_t; -typedef void* XboxHandle_t; - -#ifdef _LINUX -typedef void *HANDLE; -#define ERROR_SUCCESS 0 -#define ERROR_IO_PENDING 1 -#define ERROR_IO_INCOMPLETE 2 -#define ERROR_INSUFFICIENT_BUFFER 3 -#endif - -//----------------------------------------------------------------------------- -// Xbox system interface -//----------------------------------------------------------------------------- -abstract_class IXboxSystem -{ -public: - virtual AsyncHandle_t CreateAsyncHandle( void ) = 0; - virtual void ReleaseAsyncHandle( AsyncHandle_t handle ) = 0; - virtual int GetOverlappedResult( AsyncHandle_t handle, uint *pResultCode, bool bWait ) = 0; - virtual void CancelOverlappedOperation( AsyncHandle_t handle ) = 0; - - // Save/Load - virtual void GetModSaveContainerNames( const char *pchModName, const wchar_t **ppchDisplayName, const char **ppchName ) = 0; - virtual uint GetContainerRemainingSpace( void ) = 0; - virtual bool DeviceCapacityAdequate( DWORD nStorageID, const char *pModName ) = 0; - virtual DWORD DiscoverUserData( DWORD nUserID, const char *pModName ) = 0; - - // XUI - virtual bool ShowDeviceSelector( bool bForce, uint *pStorageID, AsyncHandle_t *pHandle ) = 0; - virtual void ShowSigninUI( uint nPanes, uint nFlags ) = 0; - - // Rich Presence and Matchmaking - virtual int UserSetContext( uint nUserIdx, uint nContextID, uint nContextValue, bool bAsync = true, AsyncHandle_t *pHandle = NULL ) = 0; - virtual int UserSetProperty( uint nUserIndex, uint nPropertyId, uint nBytes, const void *pvValue, bool bAsync = true, AsyncHandle_t *pHandle = NULL ) = 0; - - // Matchmaking - virtual int CreateSession( uint nFlags, uint nUserIdx, uint nMaxPublicSlots, uint nMaxPrivateSlots, uint64 *pNonce, void *pSessionInfo, XboxHandle_t *pSessionHandle, bool bAsync, AsyncHandle_t *pAsyncHandle = NULL ) = 0; - virtual uint DeleteSession( XboxHandle_t hSession, bool bAsync, AsyncHandle_t *pAsyncHandle = NULL ) = 0; - virtual uint SessionSearch( uint nProcedureIndex, uint nUserIndex, uint nNumResults, uint nNumUsers, uint nNumProperties, uint nNumContexts, XUSER_PROPERTY *pSearchProperties, XUSER_CONTEXT *pSearchContexts, uint *pcbResultsBuffer, XSESSION_SEARCHRESULT_HEADER *pSearchResults, bool bAsync, AsyncHandle_t *pAsyncHandle = NULL ) = 0; - virtual uint SessionStart( XboxHandle_t hSession, uint nFlags, bool bAsync, AsyncHandle_t *pAsyncHandle = NULL ) = 0; - virtual uint SessionEnd( XboxHandle_t hSession, bool bAsync, AsyncHandle_t *pAsyncHandle = NULL ) = 0; - virtual int SessionJoinLocal( XboxHandle_t hSession, uint nUserCount, const uint *pUserIndexes, const bool *pPrivateSlots, bool bAsync, AsyncHandle_t *pAsyncHandle = NULL ) = 0; - virtual int SessionJoinRemote( XboxHandle_t hSession, uint nUserCount, const XUID *pXuids, const bool *pPrivateSlots, bool bAsync, AsyncHandle_t *pAsyncHandle = NULL ) = 0; - virtual int SessionLeaveLocal( XboxHandle_t hSession, uint nUserCount, const uint *pUserIndexes, bool bAsync, AsyncHandle_t *pAsyncHandle = NULL ) = 0; - virtual int SessionLeaveRemote( XboxHandle_t hSession, uint nUserCount, const XUID *pXuids, bool bAsync, AsyncHandle_t *pAsyncHandle = NULL ) = 0; - virtual int SessionMigrate( XboxHandle_t hSession, uint nUserIndex, void *pSessionInfo, bool bAsync, AsyncHandle_t *pAsyncHandle = NULL ) = 0; - virtual int SessionArbitrationRegister( XboxHandle_t hSession, uint nFlags, uint64 nonce, uint *pBytes, void *pBuffer, bool bAsync, AsyncHandle_t *pAsyncHandle = NULL ) = 0; - - // Stats - virtual int WriteStats( XboxHandle_t hSession, XUID xuid, uint nViews, void* pViews, bool bAsync, AsyncHandle_t *pAsyncHandle = NULL ) = 0; - - // Achievements - virtual int EnumerateAchievements( uint nUserIdx, uint64 xuid, uint nStartingIdx, uint nCount, void *pBuffer, uint nBufferBytes, bool bAsync = true, AsyncHandle_t *pAsyncHandle = NULL ) = 0; - virtual void AwardAchievement( uint nUserIdx, uint nAchievementId ) = 0; - - virtual void FinishContainerWrites( void ) = 0; - virtual uint GetContainerOpenResult( void ) = 0; - virtual uint OpenContainers( void ) = 0; - virtual void CloseContainers( void ) = 0; -}; - -#define XBOXSYSTEM_INTERFACE_VERSION "XboxSystemInterface001" - -#endif // IXBOXSYSTEM_H diff --git a/public/jigglebones.cpp b/public/jigglebones.cpp deleted file mode 100644 index 9f0daec1f..000000000 --- a/public/jigglebones.cpp +++ /dev/null @@ -1,548 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#include "tier1/convar.h" -#include "jigglebones.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -ConVar JiggleBoneDebug( "cl_jiggle_bone_debug", "0", FCVAR_CHEAT, "Display physics-based 'jiggle bone' debugging information" ); -ConVar JiggleBoneDebugYawConstraints( "cl_jiggle_bone_debug_yaw_constraints", "0", FCVAR_CHEAT, "Display physics-based 'jiggle bone' debugging information" ); -ConVar JiggleBoneDebugPitchConstraints( "cl_jiggle_bone_debug_pitch_constraints", "0", FCVAR_CHEAT, "Display physics-based 'jiggle bone' debugging information" ); - -class CDummyOverlay -{ -public: - void AddLineOverlay(const Vector& origin, const Vector& dest, int r, int g, int b, bool noDepthTest, float duration) {}; -}; - -CDummyOverlay *debugoverlay = new CDummyOverlay; - -//----------------------------------------------------------------------------- -JiggleData * CJiggleBones::GetJiggleData( int bone, float currenttime, const Vector &initBasePos, const Vector &initTipPos ) -{ - FOR_EACH_LL( m_jiggleBoneState, it ) - { - if ( m_jiggleBoneState[it].bone == bone ) - { - return &m_jiggleBoneState[it]; - } - } - - JiggleData data; - data.Init( bone, currenttime, initBasePos, initTipPos ); - - int idx = m_jiggleBoneState.AddToHead( data ); - if ( idx == m_jiggleBoneState.InvalidIndex() ) - return NULL; - - return &m_jiggleBoneState[idx]; -} - - -//----------------------------------------------------------------------------- -/** - * Do spring physics calculations and update "jiggle bone" matrix - * (Michael Booth, Turtle Rock Studios) - */ -void CJiggleBones::BuildJiggleTransformations( int boneIndex, float currenttime, const mstudiojigglebone_t *jiggleInfo, const matrix3x4_t &goalMX, matrix3x4_t &boneMX ) -{ - Vector goalBasePosition; - MatrixPosition( goalMX, goalBasePosition ); - - Vector goalForward, goalUp, goalLeft; - MatrixGetColumn( goalMX, 0, goalLeft ); - MatrixGetColumn( goalMX, 1, goalUp ); - MatrixGetColumn( goalMX, 2, goalForward ); - - // compute goal tip position - Vector goalTip = goalBasePosition + jiggleInfo->length * goalForward; - - JiggleData *data = GetJiggleData( boneIndex, currenttime, goalBasePosition, goalTip ); - if ( !data ) - { - return; - } - - if ( currenttime - data->lastUpdate > 0.5f ) - { - data->Init( boneIndex, currenttime, goalBasePosition, goalTip ); - } - - //Vector bodyVel; - //EstimateAbsVelocity( bodyVel ); - - // limit maximum deltaT to avoid simulation blowups - // if framerate gets very low, jiggle will run in slow motion - const float thirtyHZ = 0.0333f; - const float thousandHZ = 0.001f; - float deltaT = clamp( currenttime - data->lastUpdate, thousandHZ, thirtyHZ ); - data->lastUpdate = currenttime; - - // - // Bone tip flex - // - if (jiggleInfo->flags & (JIGGLE_IS_FLEXIBLE | JIGGLE_IS_RIGID)) - { - // apply gravity in global space - data->tipAccel.z -= jiggleInfo->tipMass; - - if (jiggleInfo->flags & JIGGLE_IS_FLEXIBLE) - { - // decompose into local coordinates - Vector error = goalTip - data->tipPos; - - Vector localError; - localError.x = DotProduct( goalLeft, error ); - localError.y = DotProduct( goalUp, error ); - localError.z = DotProduct( goalForward, error ); - - Vector localVel; - localVel.x = DotProduct( goalLeft, data->tipVel ); - localVel.y = DotProduct( goalUp, data->tipVel ); - - // yaw spring - float yawAccel = jiggleInfo->yawStiffness * localError.x - jiggleInfo->yawDamping * localVel.x; - - // pitch spring - float pitchAccel = jiggleInfo->pitchStiffness * localError.y - jiggleInfo->pitchDamping * localVel.y; - - if (jiggleInfo->flags & JIGGLE_HAS_LENGTH_CONSTRAINT) - { - // drive tip towards goal tip position - data->tipAccel += yawAccel * goalLeft + pitchAccel * goalUp; - } - else - { - // allow flex along length of spring - localVel.z = DotProduct( goalForward, data->tipVel ); - - // along spring - float alongAccel = jiggleInfo->alongStiffness * localError.z - jiggleInfo->alongDamping * localVel.z; - - // drive tip towards goal tip position - data->tipAccel += yawAccel * goalLeft + pitchAccel * goalUp + alongAccel * goalForward; - } - } - - - // simple euler integration - data->tipVel += data->tipAccel * deltaT; - data->tipPos += data->tipVel * deltaT; - - // clear this timestep's accumulated accelerations - data->tipAccel = vec3_origin; - - // - // Apply optional constraints - // - if (jiggleInfo->flags & (JIGGLE_HAS_YAW_CONSTRAINT | JIGGLE_HAS_PITCH_CONSTRAINT)) - { - // find components of spring vector in local coordinate system - Vector along = data->tipPos - goalBasePosition; - Vector localAlong; - localAlong.x = DotProduct( goalLeft, along ); - localAlong.y = DotProduct( goalUp, along ); - localAlong.z = DotProduct( goalForward, along ); - - Vector localVel; - localVel.x = DotProduct( goalLeft, data->tipVel ); - localVel.y = DotProduct( goalUp, data->tipVel ); - localVel.z = DotProduct( goalForward, data->tipVel ); - - if (jiggleInfo->flags & JIGGLE_HAS_YAW_CONSTRAINT) - { - // enforce yaw constraints in local XZ plane - float yawError = atan2( localAlong.x, localAlong.z ); - - bool isAtLimit = false; - float yaw = 0.0f; - - if (yawError < jiggleInfo->minYaw) - { - // at angular limit - isAtLimit = true; - yaw = jiggleInfo->minYaw; - } - else if (yawError > jiggleInfo->maxYaw) - { - // at angular limit - isAtLimit = true; - yaw = jiggleInfo->maxYaw; - } - - if (isAtLimit) - { - float sy, cy; - SinCos( yaw, &sy, &cy ); - - // yaw matrix - matrix3x4_t yawMatrix; - - yawMatrix[0][0] = cy; - yawMatrix[1][0] = 0; - yawMatrix[2][0] = -sy; - - yawMatrix[0][1] = 0; - yawMatrix[1][1] = 1.0f; - yawMatrix[2][1] = 0; - - yawMatrix[0][2] = sy; - yawMatrix[1][2] = 0; - yawMatrix[2][2] = cy; - - yawMatrix[0][3] = 0; - yawMatrix[1][3] = 0; - yawMatrix[2][3] = 0; - - // global coordinates of limit - matrix3x4_t limitMatrix; - ConcatTransforms( goalMX, yawMatrix, limitMatrix ); - - Vector limitLeft( limitMatrix.m_flMatVal[0][0], - limitMatrix.m_flMatVal[1][0], - limitMatrix.m_flMatVal[2][0] ); - - Vector limitUp( limitMatrix.m_flMatVal[0][1], - limitMatrix.m_flMatVal[1][1], - limitMatrix.m_flMatVal[2][1] ); - - Vector limitForward( limitMatrix.m_flMatVal[0][2], - limitMatrix.m_flMatVal[1][2], - limitMatrix.m_flMatVal[2][2] ); - - if (JiggleBoneDebugYawConstraints.GetBool()) - { - float dT = 0.01f; - const float axisSize = 10.0f; - debugoverlay->AddLineOverlay( goalBasePosition, goalBasePosition + axisSize * limitLeft, 0, 255, 255, true, dT ); - debugoverlay->AddLineOverlay( goalBasePosition, goalBasePosition + axisSize * limitUp, 255, 255, 0, true, dT ); - debugoverlay->AddLineOverlay( goalBasePosition, goalBasePosition + axisSize * limitForward, 255, 0, 255, true, dT ); - } - - Vector limitAlong( DotProduct( limitLeft, along ), - DotProduct( limitUp, along ), - DotProduct( limitForward, along ) ); - - // clip to limit plane - data->tipPos = goalBasePosition + limitAlong.y * limitUp + limitAlong.z * limitForward; - - // yaw friction - rubbing along limit plane - Vector limitVel; - limitVel.y = DotProduct( limitUp, data->tipVel ); - limitVel.z = DotProduct( limitForward, data->tipVel ); - - data->tipAccel -= jiggleInfo->yawFriction * (limitVel.y * limitUp + limitVel.z * limitForward); - - // update velocity reaction to hitting constraint - data->tipVel = -jiggleInfo->yawBounce * limitVel.x * limitLeft + limitVel.y * limitUp + limitVel.z * limitForward; - - // update along vectors for use by pitch constraint - along = data->tipPos - goalBasePosition; - localAlong.x = DotProduct( goalLeft, along ); - localAlong.y = DotProduct( goalUp, along ); - localAlong.z = DotProduct( goalForward, along ); - - localVel.x = DotProduct( goalLeft, data->tipVel ); - localVel.y = DotProduct( goalUp, data->tipVel ); - localVel.z = DotProduct( goalForward, data->tipVel ); - } - } - - - if (jiggleInfo->flags & JIGGLE_HAS_PITCH_CONSTRAINT) - { - // enforce pitch constraints in local YZ plane - float pitchError = atan2( localAlong.y, localAlong.z ); - - bool isAtLimit = false; - float pitch = 0.0f; - - if (pitchError < jiggleInfo->minPitch) - { - // at angular limit - isAtLimit = true; - pitch = jiggleInfo->minPitch; - } - else if (pitchError > jiggleInfo->maxPitch) - { - // at angular limit - isAtLimit = true; - pitch = jiggleInfo->maxPitch; - } - - if (isAtLimit) - { - float sp, cp; - SinCos( pitch, &sp, &cp ); - - // pitch matrix - matrix3x4_t pitchMatrix; - - pitchMatrix[0][0] = 1.0f; - pitchMatrix[1][0] = 0; - pitchMatrix[2][0] = 0; - - pitchMatrix[0][1] = 0; - pitchMatrix[1][1] = cp; - pitchMatrix[2][1] = -sp; - - pitchMatrix[0][2] = 0; - pitchMatrix[1][2] = sp; - pitchMatrix[2][2] = cp; - - pitchMatrix[0][3] = 0; - pitchMatrix[1][3] = 0; - pitchMatrix[2][3] = 0; - - // global coordinates of limit - matrix3x4_t limitMatrix; - ConcatTransforms( goalMX, pitchMatrix, limitMatrix ); - - Vector limitLeft( limitMatrix.m_flMatVal[0][0], - limitMatrix.m_flMatVal[1][0], - limitMatrix.m_flMatVal[2][0] ); - - Vector limitUp( limitMatrix.m_flMatVal[0][1], - limitMatrix.m_flMatVal[1][1], - limitMatrix.m_flMatVal[2][1] ); - - Vector limitForward( limitMatrix.m_flMatVal[0][2], - limitMatrix.m_flMatVal[1][2], - limitMatrix.m_flMatVal[2][2] ); - - if (JiggleBoneDebugPitchConstraints.GetBool()) - { - float dT = 0.01f; - const float axisSize = 10.0f; - debugoverlay->AddLineOverlay( goalBasePosition, goalBasePosition + axisSize * limitLeft, 0, 255, 255, true, dT ); - debugoverlay->AddLineOverlay( goalBasePosition, goalBasePosition + axisSize * limitUp, 255, 255, 0, true, dT ); - debugoverlay->AddLineOverlay( goalBasePosition, goalBasePosition + axisSize * limitForward, 255, 0, 255, true, dT ); - } - - Vector limitAlong( DotProduct( limitLeft, along ), - DotProduct( limitUp, along ), - DotProduct( limitForward, along ) ); - - // clip to limit plane - data->tipPos = goalBasePosition + limitAlong.x * limitLeft + limitAlong.z * limitForward; - - // pitch friction - rubbing along limit plane - Vector limitVel; - limitVel.y = DotProduct( limitUp, data->tipVel ); - limitVel.z = DotProduct( limitForward, data->tipVel ); - - data->tipAccel -= jiggleInfo->pitchFriction * (limitVel.x * limitLeft + limitVel.z * limitForward); - - // update velocity reaction to hitting constraint - data->tipVel = limitVel.x * limitLeft - jiggleInfo->pitchBounce * limitVel.y * limitUp + limitVel.z * limitForward; - } - } - } - - // needed for matrix assembly below - Vector forward = data->tipPos - goalBasePosition; - forward.NormalizeInPlace(); - - if (jiggleInfo->flags & JIGGLE_HAS_ANGLE_CONSTRAINT) - { - // enforce max angular error - Vector error = goalTip - data->tipPos; - float dot = DotProduct( forward, goalForward ); - float angleBetween = acos( dot ); - if (dot < 0.0f) - { - angleBetween = 2.0f * M_PI - angleBetween; - } - - if (angleBetween > jiggleInfo->angleLimit) - { - // at angular limit - float maxBetween = jiggleInfo->length * sin( jiggleInfo->angleLimit ); - - Vector delta = goalTip - data->tipPos; - delta.NormalizeInPlace(); - - data->tipPos = goalTip - maxBetween * delta; - - forward = data->tipPos - goalBasePosition; - forward.NormalizeInPlace(); - } - } - - if (jiggleInfo->flags & JIGGLE_HAS_LENGTH_CONSTRAINT) - { - // enforce spring length - data->tipPos = goalBasePosition + jiggleInfo->length * forward; - - // zero velocity along forward bone axis - data->tipVel -= DotProduct( data->tipVel, forward ) * forward; - } - - // - // Build bone matrix to align along current tip direction - // - Vector left = CrossProduct( goalUp, forward ); - left.NormalizeInPlace(); - - Vector up = CrossProduct( forward, left ); - - boneMX[0][0] = left.x; - boneMX[1][0] = left.y; - boneMX[2][0] = left.z; - boneMX[0][1] = up.x; - boneMX[1][1] = up.y; - boneMX[2][1] = up.z; - boneMX[0][2] = forward.x; - boneMX[1][2] = forward.y; - boneMX[2][2] = forward.z; - - boneMX[0][3] = goalBasePosition.x; - boneMX[1][3] = goalBasePosition.y; - boneMX[2][3] = goalBasePosition.z; - } - - - // - // Bone base flex - // - if (jiggleInfo->flags & JIGGLE_HAS_BASE_SPRING) - { - // gravity - data->baseAccel.z -= jiggleInfo->baseMass; - - // simple spring - Vector error = goalBasePosition - data->basePos; - data->baseAccel += jiggleInfo->baseStiffness * error - jiggleInfo->baseDamping * data->baseVel; - - data->baseVel += data->baseAccel * deltaT; - data->basePos += data->baseVel * deltaT; - - // clear this timestep's accumulated accelerations - data->baseAccel = vec3_origin; - - // constrain to limits - error = data->basePos - goalBasePosition; - Vector localError; - localError.x = DotProduct( goalLeft, error ); - localError.y = DotProduct( goalUp, error ); - localError.z = DotProduct( goalForward, error ); - - Vector localVel; - localVel.x = DotProduct( goalLeft, data->baseVel ); - localVel.y = DotProduct( goalUp, data->baseVel ); - localVel.z = DotProduct( goalForward, data->baseVel ); - - // horizontal constraint - if (localError.x < jiggleInfo->baseMinLeft) - { - localError.x = jiggleInfo->baseMinLeft; - - // friction - data->baseAccel -= jiggleInfo->baseLeftFriction * (localVel.y * goalUp + localVel.z * goalForward); - } - else if (localError.x > jiggleInfo->baseMaxLeft) - { - localError.x = jiggleInfo->baseMaxLeft; - - // friction - data->baseAccel -= jiggleInfo->baseLeftFriction * (localVel.y * goalUp + localVel.z * goalForward); - } - - if (localError.y < jiggleInfo->baseMinUp) - { - localError.y = jiggleInfo->baseMinUp; - - // friction - data->baseAccel -= jiggleInfo->baseUpFriction * (localVel.x * goalLeft + localVel.z * goalForward); - } - else if (localError.y > jiggleInfo->baseMaxUp) - { - localError.y = jiggleInfo->baseMaxUp; - - // friction - data->baseAccel -= jiggleInfo->baseUpFriction * (localVel.x * goalLeft + localVel.z * goalForward); - } - - if (localError.z < jiggleInfo->baseMinForward) - { - localError.z = jiggleInfo->baseMinForward; - - // friction - data->baseAccel -= jiggleInfo->baseForwardFriction * (localVel.x * goalLeft + localVel.y * goalUp); - } - else if (localError.z > jiggleInfo->baseMaxForward) - { - localError.z = jiggleInfo->baseMaxForward; - - // friction - data->baseAccel -= jiggleInfo->baseForwardFriction * (localVel.x * goalLeft + localVel.y * goalUp); - } - - data->basePos = goalBasePosition + localError.x * goalLeft + localError.y * goalUp + localError.z * goalForward; - - - // fix up velocity - data->baseVel = (data->basePos - data->baseLastPos) / deltaT; - data->baseLastPos = data->basePos; - - - if (!(jiggleInfo->flags & (JIGGLE_IS_FLEXIBLE | JIGGLE_IS_RIGID))) - { - // no tip flex - use bone's goal orientation - boneMX = goalMX; - } - - // update bone position - MatrixSetColumn( data->basePos, 3, boneMX ); - } - else if (!(jiggleInfo->flags & (JIGGLE_IS_FLEXIBLE | JIGGLE_IS_RIGID))) - { - // no flex at all - just use goal matrix - boneMX = goalMX; - } - - - // debug display - if ( JiggleBoneDebug.GetBool() ) - { - float dT = 0.01f; - const float axisSize = 5.0f; - debugoverlay->AddLineOverlay( goalBasePosition, goalBasePosition + axisSize * goalLeft, 255, 0, 0, true, dT ); - debugoverlay->AddLineOverlay( goalBasePosition, goalBasePosition + axisSize * goalUp, 0, 255, 0, true, dT ); - debugoverlay->AddLineOverlay( goalBasePosition, goalBasePosition + axisSize * goalForward, 0, 0, 255, true, dT ); - - - const float sz = 1.0f; - - if (jiggleInfo->flags & (JIGGLE_IS_FLEXIBLE | JIGGLE_IS_RIGID)) - { - debugoverlay->AddLineOverlay( goalBasePosition, - data->tipPos, 255, 255, 0, true, dT ); - - debugoverlay->AddLineOverlay( data->tipPos + Vector( -sz, 0, 0 ), - data->tipPos + Vector( sz, 0, 0 ), 0, 255, 255, true, dT ); - debugoverlay->AddLineOverlay( data->tipPos + Vector( 0, -sz, 0 ), - data->tipPos + Vector( 0, sz, 0 ), 0, 255, 255, true, dT ); - debugoverlay->AddLineOverlay( data->tipPos + Vector( 0, 0, -sz ), - data->tipPos + Vector( 0, 0, sz ), 0, 255, 255, true, dT ); - } - - if (jiggleInfo->flags & JIGGLE_HAS_BASE_SPRING) - { - debugoverlay->AddLineOverlay( data->basePos + Vector( -sz, 0, 0 ), - data->basePos + Vector( sz, 0, 0 ), 255, 0, 255, true, dT ); - debugoverlay->AddLineOverlay( data->basePos + Vector( 0, -sz, 0 ), - data->basePos + Vector( 0, sz, 0 ), 255, 0, 255, true, dT ); - debugoverlay->AddLineOverlay( data->basePos + Vector( 0, 0, -sz ), - data->basePos + Vector( 0, 0, sz ), 255, 0, 255, true, dT ); - } - } -} - diff --git a/public/jigglebones.h b/public/jigglebones.h deleted file mode 100644 index e3c8fde3e..000000000 --- a/public/jigglebones.h +++ /dev/null @@ -1,67 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $NoKeywords: $ -//=============================================================================// -#ifndef C_JIGGLEBONES_H -#define C_JIGGLEBONES_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "studio.h" -#include "UtlVector.h" -#include "utllinkedlist.h" - -//----------------------------------------------------------------------------- -/** - * JiggleData is the instance-specific data for a jiggle bone - */ -struct JiggleData -{ - void Init( int initBone, float currenttime, const Vector &initBasePos, const Vector &initTipPos ) - { - bone = initBone; - - lastUpdate = currenttime; - - basePos = initBasePos; - baseLastPos = basePos; - baseVel.Init(); - baseAccel.Init(); - - tipPos = initTipPos; - tipVel.Init(); - tipAccel.Init(); - } - - int bone; - - float lastUpdate; // based on gpGlobals->realtime - - Vector basePos; // position of the base of the jiggle bone - Vector baseLastPos; - Vector baseVel; - Vector baseAccel; - - Vector tipPos; // position of the tip of the jiggle bone - Vector tipVel; - Vector tipAccel; -}; - -class CJiggleBones -{ -public: - JiggleData * GetJiggleData( int bone, float currenttime, const Vector &initBasePos, const Vector &initTipPos ); - void BuildJiggleTransformations( int boneIndex, float currentime, const mstudiojigglebone_t *jiggleParams, const matrix3x4_t &goalMX, matrix3x4_t &boneMX ); - - CUtlLinkedList< JiggleData > m_jiggleBoneState; -}; - - -extern void DevMsgRT( char const* pMsg, ... ); - -#endif // C_BASEANIMATING_H diff --git a/public/jpeglib/jconfig.h b/public/jpeglib/jconfig.h deleted file mode 100644 index 7e291c75b..000000000 --- a/public/jpeglib/jconfig.h +++ /dev/null @@ -1,45 +0,0 @@ -/* jconfig.vc --- jconfig.h for Microsoft Visual C++ on Windows 95 or NT. */ -/* see jconfig.doc for explanations */ - -#define HAVE_PROTOTYPES -#define HAVE_UNSIGNED_CHAR -#define HAVE_UNSIGNED_SHORT -/* #define void char */ -/* #define const */ -#undef CHAR_IS_UNSIGNED -#define HAVE_STDDEF_H -#define HAVE_STDLIB_H -#undef NEED_BSD_STRINGS -#undef NEED_SYS_TYPES_H -#undef NEED_FAR_POINTERS /* we presume a 32-bit flat memory model */ -#undef NEED_SHORT_EXTERNAL_NAMES -#undef INCOMPLETE_TYPES_BROKEN - -/* Define "boolean" as unsigned char, not int, per Windows custom */ -#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ -typedef unsigned char boolean; -#endif -#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ - - -#ifdef JPEG_INTERNALS - -#undef RIGHT_SHIFT_IS_UNSIGNED - -#endif /* JPEG_INTERNALS */ - -#ifdef JPEG_CJPEG_DJPEG - -#define BMP_SUPPORTED /* BMP image file format */ -#define GIF_SUPPORTED /* GIF image file format */ -#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ -#undef RLE_SUPPORTED /* Utah RLE image file format */ -#define TARGA_SUPPORTED /* Targa image file format */ - -#define TWO_FILE_COMMANDLINE /* optional */ -#define USE_SETMODE /* Microsoft has setmode() */ -#undef NEED_SIGNAL_CATCHER -#undef DONT_USE_B_MODE -#undef PROGRESS_REPORT /* optional */ - -#endif /* JPEG_CJPEG_DJPEG */ diff --git a/public/jpeglib/jmorecfg.h b/public/jpeglib/jmorecfg.h deleted file mode 100644 index 67b2ff5f4..000000000 --- a/public/jpeglib/jmorecfg.h +++ /dev/null @@ -1,366 +0,0 @@ -/* - * jmorecfg.h - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file contains additional configuration options that customize the - * JPEG software for special applications or support machine-dependent - * optimizations. Most users will not need to touch this file. - */ - - -/* - * Define BITS_IN_JSAMPLE as either - * 8 for 8-bit sample values (the usual setting) - * 12 for 12-bit sample values - * Only 8 and 12 are legal data precisions for lossy JPEG according to the - * JPEG standard, and the IJG code does not support anything else! - * We do not support run-time selection of data precision, sorry. - */ - -#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ - - -/* - * Maximum number of components (color channels) allowed in JPEG image. - * To meet the letter of the JPEG spec, set this to 255. However, darn - * few applications need more than 4 channels (maybe 5 for CMYK + alpha - * mask). We recommend 10 as a reasonable compromise; use 4 if you are - * really short on memory. (Each allowed component costs a hundred or so - * bytes of storage, whether actually used in an image or not.) - */ - -#define MAX_COMPONENTS 10 /* maximum number of image components */ - - -/* - * Basic data types. - * You may need to change these if you have a machine with unusual data - * type sizes; for example, "char" not 8 bits, "short" not 16 bits, - * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, - * but it had better be at least 16. - */ - -/* Representation of a single sample (pixel element value). - * We frequently allocate large arrays of these, so it's important to keep - * them small. But if you have memory to burn and access to char or short - * arrays is very slow on your hardware, you might want to change these. - */ - -#if BITS_IN_JSAMPLE == 8 -/* JSAMPLE should be the smallest type that will hold the values 0..255. - * You can use a signed char by having GETJSAMPLE mask it with 0xFF. - */ - -#ifdef HAVE_UNSIGNED_CHAR - -typedef unsigned char JSAMPLE; -#define GETJSAMPLE(value) ((int) (value)) - -#else /* not HAVE_UNSIGNED_CHAR */ - -typedef char JSAMPLE; -#ifdef CHAR_IS_UNSIGNED -#define GETJSAMPLE(value) ((int) (value)) -#else -#define GETJSAMPLE(value) ((int) (value) & 0xFF) -#endif /* CHAR_IS_UNSIGNED */ - -#endif /* HAVE_UNSIGNED_CHAR */ - -#define MAXJSAMPLE 255 -#define CENTERJSAMPLE 128 - -#endif /* BITS_IN_JSAMPLE == 8 */ - - -#if BITS_IN_JSAMPLE == 12 -/* JSAMPLE should be the smallest type that will hold the values 0..4095. - * On nearly all machines "short" will do nicely. - */ - -typedef short JSAMPLE; -#define GETJSAMPLE(value) ((int) (value)) - -#define MAXJSAMPLE 4095 -#define CENTERJSAMPLE 2048 - -#endif /* BITS_IN_JSAMPLE == 12 */ - - -/* Representation of a DCT frequency coefficient. - * This should be a signed value of at least 16 bits; "short" is usually OK. - * Again, we allocate large arrays of these, but you can change to int - * if you have memory to burn and "short" is really slow. - */ - -typedef short JCOEF; - - -/* Compressed datastreams are represented as arrays of JOCTET. - * These must be EXACTLY 8 bits wide, at least once they are written to - * external storage. Note that when using the stdio data source/destination - * managers, this is also the data type passed to fread/fwrite. - */ - -#ifdef HAVE_UNSIGNED_CHAR - -typedef unsigned char JOCTET; -#define GETJOCTET(value) (value) - -#else /* not HAVE_UNSIGNED_CHAR */ - -typedef char JOCTET; -#ifdef CHAR_IS_UNSIGNED -#define GETJOCTET(value) (value) -#else -#define GETJOCTET(value) ((value) & 0xFF) -#endif /* CHAR_IS_UNSIGNED */ - -#endif /* HAVE_UNSIGNED_CHAR */ - - -/* These typedefs are used for various table entries and so forth. - * They must be at least as wide as specified; but making them too big - * won't cost a huge amount of memory, so we don't provide special - * extraction code like we did for JSAMPLE. (In other words, these - * typedefs live at a different point on the speed/space tradeoff curve.) - */ - -/* UINT8 must hold at least the values 0..255. */ - -#ifdef HAVE_UNSIGNED_CHAR -typedef unsigned char UINT8; -#else /* not HAVE_UNSIGNED_CHAR */ -#ifdef CHAR_IS_UNSIGNED -typedef char UINT8; -#else /* not CHAR_IS_UNSIGNED */ -typedef short UINT8; -#endif /* CHAR_IS_UNSIGNED */ -#endif /* HAVE_UNSIGNED_CHAR */ - -/* UINT16 must hold at least the values 0..65535. */ - -#ifdef HAVE_UNSIGNED_SHORT -typedef unsigned short UINT16; -#else /* not HAVE_UNSIGNED_SHORT */ -typedef unsigned int UINT16; -#endif /* HAVE_UNSIGNED_SHORT */ - -/* INT16 must hold at least the values -32768..32767. */ - -#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ -typedef short INT16; -#endif - -/* INT32 must hold at least signed 32-bit values. */ - -#ifndef _BASETSD_H_ -#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ -typedef long INT32; -#endif -#endif // #ifndef _BASETSD_H_ - -/* Datatype used for image dimensions. The JPEG standard only supports - * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore - * "unsigned int" is sufficient on all machines. However, if you need to - * handle larger images and you don't mind deviating from the spec, you - * can change this datatype. - */ - -typedef unsigned int JDIMENSION; - -#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ - - -/* These macros are used in all function definitions and extern declarations. - * You could modify them if you need to change function linkage conventions; - * in particular, you'll need to do that to make the library a Windows DLL. - * Another application is to make all functions global for use with debuggers - * or code profilers that require it. - */ - -/* a function called through method pointers: */ -#define METHODDEF(type) static type -/* a function used only in its module: */ -#define LOCAL(type) static type -/* a function referenced thru EXTERNs: */ -#define GLOBAL(type) type -/* a reference to a GLOBAL function: */ -#define EXTERN(type) extern type - - -/* This macro is used to declare a "method", that is, a function pointer. - * We want to supply prototype parameters if the compiler can cope. - * Note that the arglist parameter must be parenthesized! - * Again, you can customize this if you need special linkage keywords. - */ - -#ifdef HAVE_PROTOTYPES -#define JMETHOD(type,methodname,arglist) type (*methodname) arglist -#else -#define JMETHOD(type,methodname,arglist) type (*methodname) () -#endif - - -/* Here is the pseudo-keyword for declaring pointers that must be "far" - * on 80x86 machines. Most of the specialized coding for 80x86 is handled - * by just saying "FAR *" where such a pointer is needed. In a few places - * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. - */ - -#ifndef FAR -#ifdef NEED_FAR_POINTERS -#define FAR far -#else -#define FAR -#endif -#endif - -/* - * On a few systems, type boolean and/or its values FALSE, TRUE may appear - * in standard header files. Or you may have conflicts with application- - * specific header files that you want to include together with these files. - * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. - */ - -#ifndef HAVE_BOOLEAN -typedef int boolean; -#endif -#ifndef FALSE /* in case these macros already exist */ -#define FALSE 0 /* values of boolean */ -#endif -#ifndef TRUE -#define TRUE 1 -#endif - - -/* - * The remaining options affect code selection within the JPEG library, - * but they don't need to be visible to most applications using the library. - * To minimize application namespace pollution, the symbols won't be - * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. - */ - -#ifdef JPEG_INTERNALS -#define JPEG_INTERNAL_OPTIONS -#endif - -#ifdef JPEG_INTERNAL_OPTIONS - - -/* - * These defines indicate whether to include various optional functions. - * Undefining some of these symbols will produce a smaller but less capable - * library. Note that you can leave certain source files out of the - * compilation/linking process if you've #undef'd the corresponding symbols. - * (You may HAVE to do that if your compiler doesn't like null source files.) - */ - -/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ - -/* Capability options common to encoder and decoder: */ - -#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */ -#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */ -#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */ - -/* Encoder capability options: */ - -#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ -#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ -#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ -#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ -/* Note: if you selected 12-bit data precision, it is dangerous to turn off - * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit - * precision, so jchuff.c normally uses entropy optimization to compute - * usable tables for higher precision. If you don't want to do optimization, - * you'll have to supply different default Huffman tables. - * The exact same statements apply for progressive JPEG: the default tables - * don't work for progressive mode. (This may get fixed, however.) - */ -#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ - -/* Decoder capability options: */ - -#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ -#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ -#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/ -#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */ -#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */ -#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ -#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ -#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */ -#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ -#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ - -/* more capability options later, no doubt */ - - -/* - * Ordering of RGB data in scanlines passed to or from the application. - * If your application wants to deal with data in the order B,G,R, just - * change these macros. You can also deal with formats such as R,G,B,X - * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing - * the offsets will also change the order in which colormap data is organized. - * RESTRICTIONS: - * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats. - * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not - * useful if you are using JPEG color spaces other than YCbCr or grayscale. - * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE - * is not 3 (they don't understand about dummy color components!). So you - * can't use color quantization if you change that value. - */ - -#define RGB_RED 0 /* Offset of Red in an RGB scanline element */ -#define RGB_GREEN 1 /* Offset of Green */ -#define RGB_BLUE 2 /* Offset of Blue */ -#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */ - - -/* Definitions for speed-related optimizations. */ - - -/* If your compiler supports inline functions, define INLINE - * as the inline keyword; otherwise define it as empty. - */ - -#ifndef INLINE -#ifdef __GNUC__ /* for instance, GNU C knows about inline */ -#define INLINE __inline__ -#endif -#ifndef INLINE -#define INLINE /* default is to define it as empty */ -#endif -#endif - - -/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying - * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER - * as short on such a machine. MULTIPLIER must be at least 16 bits wide. - */ - -#ifndef MULTIPLIER -#define MULTIPLIER int /* type for fastest integer multiply */ -#endif - - -/* FAST_FLOAT should be either float or double, whichever is done faster - * by your compiler. (Note that this type is only used in the floating point - * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.) - * Typically, float is faster in ANSI C compilers, while double is faster in - * pre-ANSI compilers (because they insist on converting to double anyway). - * The code below therefore chooses float if we have ANSI-style prototypes. - */ - -#ifndef FAST_FLOAT -#ifdef HAVE_PROTOTYPES -#define FAST_FLOAT float -#else -#define FAST_FLOAT double -#endif -#endif - -#endif /* JPEG_INTERNAL_OPTIONS */ diff --git a/public/jpeglib/jpeglib.h b/public/jpeglib/jpeglib.h deleted file mode 100644 index 0bf3c9e2b..000000000 --- a/public/jpeglib/jpeglib.h +++ /dev/null @@ -1,1113 +0,0 @@ -/* - * jpeglib.h - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * For conditions of distribution and use, see the accompanying README file. - * - * This file defines the application interface for the JPEG library. - * Most applications using the library need only include this file, - * and perhaps jerror.h if they want to know the exact error codes. - */ - -#ifndef JPEGLIB_H -#define JPEGLIB_H - -#ifdef __cplusplus -extern "C" { -#endif - -#pragma warning( disable : 4100 ) // unused formal parameter -#pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant -#pragma warning( disable : 4244 ) // warning C4244: '+=' : conversion from 'int' to 'JSAMPLE', possible loss of data -#pragma warning( disable : 4267 ) // warning C4267: '+=' : conversion from 'size_t' to 'long', possible loss of data - -/* - * First we include the configuration files that record how this - * installation of the JPEG library is set up. jconfig.h can be - * generated automatically for many systems. jmorecfg.h contains - * manual configuration options that most people need not worry about. - */ - -#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ -#include "jconfig.h" /* widely used configuration options */ -#endif -#include "jmorecfg.h" /* seldom changed options */ - - -/* Version ID for the JPEG library. - * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60". - */ - -#define JPEG_LIB_VERSION 62 /* Version 6b */ - - -/* Various constants determining the sizes of things. - * All of these are specified by the JPEG standard, so don't change them - * if you want to be compatible. - */ - -#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ -#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ -#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ -#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ -#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ -#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ -#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ -/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; - * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. - * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU - * to handle it. We even let you do this from the jconfig.h file. However, - * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe - * sometimes emits noncompliant files doesn't mean you should too. - */ -#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ -#ifndef D_MAX_BLOCKS_IN_MCU -#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ -#endif - - -/* Data structures for images (arrays of samples and of DCT coefficients). - * On 80x86 machines, the image arrays are too big for near pointers, - * but the pointer arrays can fit in near memory. - */ - -typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ -typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ -typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ - -typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ -typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ -typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ -typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ - -typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ - - -/* Types for JPEG compression parameters and working tables. */ - - -/* DCT coefficient quantization tables. */ - -typedef struct { - /* This array gives the coefficient quantizers in natural array order - * (not the zigzag order in which they are stored in a JPEG DQT marker). - * CAUTION: IJG versions prior to v6a kept this array in zigzag order. - */ - UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ - /* This field is used only during compression. It's initialized FALSE when - * the table is created, and set TRUE when it's been output to the file. - * You could suppress output of a table by setting this to TRUE. - * (See jpeg_suppress_tables for an example.) - */ - boolean sent_table; /* TRUE when table has been output */ -} JQUANT_TBL; - - -/* Huffman coding tables. */ - -typedef struct { - /* These two fields directly represent the contents of a JPEG DHT marker */ - UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ - /* length k bits; bits[0] is unused */ - UINT8 huffval[256]; /* The symbols, in order of incr code length */ - /* This field is used only during compression. It's initialized FALSE when - * the table is created, and set TRUE when it's been output to the file. - * You could suppress output of a table by setting this to TRUE. - * (See jpeg_suppress_tables for an example.) - */ - boolean sent_table; /* TRUE when table has been output */ -} JHUFF_TBL; - - -/* Basic info about one component (color channel). */ - -typedef struct { - /* These values are fixed over the whole image. */ - /* For compression, they must be supplied by parameter setup; */ - /* for decompression, they are read from the SOF marker. */ - int component_id; /* identifier for this component (0..255) */ - int component_index; /* its index in SOF or cinfo->comp_info[] */ - int h_samp_factor; /* horizontal sampling factor (1..4) */ - int v_samp_factor; /* vertical sampling factor (1..4) */ - int quant_tbl_no; /* quantization table selector (0..3) */ - /* These values may vary between scans. */ - /* For compression, they must be supplied by parameter setup; */ - /* for decompression, they are read from the SOS marker. */ - /* The decompressor output side may not use these variables. */ - int dc_tbl_no; /* DC entropy table selector (0..3) */ - int ac_tbl_no; /* AC entropy table selector (0..3) */ - - /* Remaining fields should be treated as private by applications. */ - - /* These values are computed during compression or decompression startup: */ - /* Component's size in DCT blocks. - * Any dummy blocks added to complete an MCU are not counted; therefore - * these values do not depend on whether a scan is interleaved or not. - */ - JDIMENSION width_in_blocks; - JDIMENSION height_in_blocks; - /* Size of a DCT block in samples. Always DCTSIZE for compression. - * For decompression this is the size of the output from one DCT block, - * reflecting any scaling we choose to apply during the IDCT step. - * Values of 1,2,4,8 are likely to be supported. Note that different - * components may receive different IDCT scalings. - */ - int DCT_scaled_size; - /* The downsampled dimensions are the component's actual, unpadded number - * of samples at the main buffer (preprocessing/compression interface), thus - * downsampled_width = ceil(image_width * Hi/Hmax) - * and similarly for height. For decompression, IDCT scaling is included, so - * downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE) - */ - JDIMENSION downsampled_width; /* actual width in samples */ - JDIMENSION downsampled_height; /* actual height in samples */ - /* This flag is used only for decompression. In cases where some of the - * components will be ignored (eg grayscale output from YCbCr image), - * we can skip most computations for the unused components. - */ - boolean component_needed; /* do we need the value of this component? */ - - /* These values are computed before starting a scan of the component. */ - /* The decompressor output side may not use these variables. */ - int MCU_width; /* number of blocks per MCU, horizontally */ - int MCU_height; /* number of blocks per MCU, vertically */ - int MCU_blocks; /* MCU_width * MCU_height */ - int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_scaled_size */ - int last_col_width; /* # of non-dummy blocks across in last MCU */ - int last_row_height; /* # of non-dummy blocks down in last MCU */ - - /* Saved quantization table for component; NULL if none yet saved. - * See jdinput.c comments about the need for this information. - * This field is currently used only for decompression. - */ - JQUANT_TBL * quant_table; - - /* Private per-component storage for DCT or IDCT subsystem. */ - void * dct_table; -} jpeg_component_info; - - -/* The script for encoding a multiple-scan file is an array of these: */ - -typedef struct { - int comps_in_scan; /* number of components encoded in this scan */ - int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */ - int Ss, Se; /* progressive JPEG spectral selection parms */ - int Ah, Al; /* progressive JPEG successive approx. parms */ -} jpeg_scan_info; - -/* The decompressor can save APPn and COM markers in a list of these: */ - -typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr; - -struct jpeg_marker_struct { - jpeg_saved_marker_ptr next; /* next in list, or NULL */ - UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */ - unsigned int original_length; /* # bytes of data in the file */ - unsigned int data_length; /* # bytes of data saved at data[] */ - JOCTET FAR * data; /* the data contained in the marker */ - /* the marker length word is not counted in data_length or original_length */ -}; - -/* Known color spaces. */ - -typedef enum { - JCS_UNKNOWN, /* error/unspecified */ - JCS_GRAYSCALE, /* monochrome */ - JCS_RGB, /* red/green/blue */ - JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ - JCS_CMYK, /* C/M/Y/K */ - JCS_YCCK /* Y/Cb/Cr/K */ -} J_COLOR_SPACE; - -/* DCT/IDCT algorithm options. */ - -typedef enum { - JDCT_ISLOW, /* slow but accurate integer algorithm */ - JDCT_IFAST, /* faster, less accurate integer method */ - JDCT_FLOAT /* floating-point: accurate, fast on fast HW */ -} J_DCT_METHOD; - -#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */ -#define JDCT_DEFAULT JDCT_ISLOW -#endif -#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */ -#define JDCT_FASTEST JDCT_IFAST -#endif - -/* Dithering options for decompression. */ - -typedef enum { - JDITHER_NONE, /* no dithering */ - JDITHER_ORDERED, /* simple ordered dither */ - JDITHER_FS /* Floyd-Steinberg error diffusion dither */ -} J_DITHER_MODE; - - -/* Common fields between JPEG compression and decompression master structs. */ - -#define jpeg_common_fields \ - struct jpeg_error_mgr * err; /* Error handler module */\ - struct jpeg_memory_mgr * mem; /* Memory manager module */\ - struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ - void * client_data; /* Available for use by application */\ - boolean is_decompressor; /* So common code can tell which is which */\ - int global_state /* For checking call sequence validity */ - -/* Routines that are to be used by both halves of the library are declared - * to receive a pointer to this structure. There are no actual instances of - * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. - */ -struct jpeg_common_struct { - jpeg_common_fields; /* Fields common to both master struct types */ - /* Additional fields follow in an actual jpeg_compress_struct or - * jpeg_decompress_struct. All three structs must agree on these - * initial fields! (This would be a lot cleaner in C++.) - */ -}; - -typedef struct jpeg_common_struct * j_common_ptr; -typedef struct jpeg_compress_struct * j_compress_ptr; -typedef struct jpeg_decompress_struct * j_decompress_ptr; - - -/* Master record for a compression instance */ - -struct jpeg_compress_struct { - jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ - - /* Destination for compressed data */ - struct jpeg_destination_mgr * dest; - - /* Description of source image --- these fields must be filled in by - * outer application before starting compression. in_color_space must - * be correct before you can even call jpeg_set_defaults(). - */ - - JDIMENSION image_width; /* input image width */ - JDIMENSION image_height; /* input image height */ - int input_components; /* # of color components in input image */ - J_COLOR_SPACE in_color_space; /* colorspace of input image */ - - double input_gamma; /* image gamma of input image */ - - /* Compression parameters --- these fields must be set before calling - * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to - * initialize everything to reasonable defaults, then changing anything - * the application specifically wants to change. That way you won't get - * burnt when new parameters are added. Also note that there are several - * helper routines to simplify changing parameters. - */ - - int data_precision; /* bits of precision in image data */ - - int num_components; /* # of color components in JPEG image */ - J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ - - jpeg_component_info * comp_info; - /* comp_info[i] describes component that appears i'th in SOF */ - - JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; - /* ptrs to coefficient quantization tables, or NULL if not defined */ - - JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; - JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; - /* ptrs to Huffman coding tables, or NULL if not defined */ - - UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ - UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ - UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ - - int num_scans; /* # of entries in scan_info array */ - const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */ - /* The default value of scan_info is NULL, which causes a single-scan - * sequential JPEG file to be emitted. To create a multi-scan file, - * set num_scans and scan_info to point to an array of scan definitions. - */ - - boolean raw_data_in; /* TRUE=caller supplies downsampled data */ - boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ - boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ - boolean CCIR601_sampling; /* TRUE=first samples are cosited */ - int smoothing_factor; /* 1..100, or 0 for no input smoothing */ - J_DCT_METHOD dct_method; /* DCT algorithm selector */ - - /* The restart interval can be specified in absolute MCUs by setting - * restart_interval, or in MCU rows by setting restart_in_rows - * (in which case the correct restart_interval will be figured - * for each scan). - */ - unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ - int restart_in_rows; /* if > 0, MCU rows per restart interval */ - - /* Parameters controlling emission of special markers. */ - - boolean write_JFIF_header; /* should a JFIF marker be written? */ - UINT8 JFIF_major_version; /* What to write for the JFIF version number */ - UINT8 JFIF_minor_version; - /* These three values are not used by the JPEG code, merely copied */ - /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ - /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ - /* ratio is defined by X_density/Y_density even when density_unit=0. */ - UINT8 density_unit; /* JFIF code for pixel size units */ - UINT16 X_density; /* Horizontal pixel density */ - UINT16 Y_density; /* Vertical pixel density */ - boolean write_Adobe_marker; /* should an Adobe marker be written? */ - - /* State variable: index of next scanline to be written to - * jpeg_write_scanlines(). Application may use this to control its - * processing loop, e.g., "while (next_scanline < image_height)". - */ - - JDIMENSION next_scanline; /* 0 .. image_height-1 */ - - /* Remaining fields are known throughout compressor, but generally - * should not be touched by a surrounding application. - */ - - /* - * These fields are computed during compression startup - */ - boolean progressive_mode; /* TRUE if scan script uses progressive mode */ - int max_h_samp_factor; /* largest h_samp_factor */ - int max_v_samp_factor; /* largest v_samp_factor */ - - JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */ - /* The coefficient controller receives data in units of MCU rows as defined - * for fully interleaved scans (whether the JPEG file is interleaved or not). - * There are v_samp_factor * DCTSIZE sample rows of each component in an - * "iMCU" (interleaved MCU) row. - */ - - /* - * These fields are valid during any one scan. - * They describe the components and MCUs actually appearing in the scan. - */ - int comps_in_scan; /* # of JPEG components in this scan */ - jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; - /* *cur_comp_info[i] describes component that appears i'th in SOS */ - - JDIMENSION MCUs_per_row; /* # of MCUs across the image */ - JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ - - int blocks_in_MCU; /* # of DCT blocks per MCU */ - int MCU_membership[C_MAX_BLOCKS_IN_MCU]; - /* MCU_membership[i] is index in cur_comp_info of component owning */ - /* i'th block in an MCU */ - - int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ - - /* - * Links to compression subobjects (methods and private variables of modules) - */ - struct jpeg_comp_master * master; - struct jpeg_c_main_controller * main; - struct jpeg_c_prep_controller * prep; - struct jpeg_c_coef_controller * coef; - struct jpeg_marker_writer * marker; - struct jpeg_color_converter * cconvert; - struct jpeg_downsampler * downsample; - struct jpeg_forward_dct * fdct; - struct jpeg_entropy_encoder * entropy; - jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */ - int script_space_size; -}; - - -/* Master record for a decompression instance */ - -struct jpeg_decompress_struct { - jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ - - /* Source of compressed data */ - struct jpeg_source_mgr * src; - - /* Basic description of image --- filled in by jpeg_read_header(). */ - /* Application may inspect these values to decide how to process image. */ - - JDIMENSION image_width; /* nominal image width (from SOF marker) */ - JDIMENSION image_height; /* nominal image height */ - int num_components; /* # of color components in JPEG image */ - J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ - - /* Decompression processing parameters --- these fields must be set before - * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes - * them to default values. - */ - - J_COLOR_SPACE out_color_space; /* colorspace for output */ - - unsigned int scale_num, scale_denom; /* fraction by which to scale image */ - - double output_gamma; /* image gamma wanted in output */ - - boolean buffered_image; /* TRUE=multiple output passes */ - boolean raw_data_out; /* TRUE=downsampled data wanted */ - - J_DCT_METHOD dct_method; /* IDCT algorithm selector */ - boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */ - boolean do_block_smoothing; /* TRUE=apply interblock smoothing */ - - boolean quantize_colors; /* TRUE=colormapped output wanted */ - /* the following are ignored if not quantize_colors: */ - J_DITHER_MODE dither_mode; /* type of color dithering to use */ - boolean two_pass_quantize; /* TRUE=use two-pass color quantization */ - int desired_number_of_colors; /* max # colors to use in created colormap */ - /* these are significant only in buffered-image mode: */ - boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */ - boolean enable_external_quant;/* enable future use of external colormap */ - boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */ - - /* Description of actual output image that will be returned to application. - * These fields are computed by jpeg_start_decompress(). - * You can also use jpeg_calc_output_dimensions() to determine these values - * in advance of calling jpeg_start_decompress(). - */ - - JDIMENSION output_width; /* scaled image width */ - JDIMENSION output_height; /* scaled image height */ - int out_color_components; /* # of color components in out_color_space */ - int output_components; /* # of color components returned */ - /* output_components is 1 (a colormap index) when quantizing colors; - * otherwise it equals out_color_components. - */ - int rec_outbuf_height; /* min recommended height of scanline buffer */ - /* If the buffer passed to jpeg_read_scanlines() is less than this many rows - * high, space and time will be wasted due to unnecessary data copying. - * Usually rec_outbuf_height will be 1 or 2, at most 4. - */ - - /* When quantizing colors, the output colormap is described by these fields. - * The application can supply a colormap by setting colormap non-NULL before - * calling jpeg_start_decompress; otherwise a colormap is created during - * jpeg_start_decompress or jpeg_start_output. - * The map has out_color_components rows and actual_number_of_colors columns. - */ - int actual_number_of_colors; /* number of entries in use */ - JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ - - /* State variables: these variables indicate the progress of decompression. - * The application may examine these but must not modify them. - */ - - /* Row index of next scanline to be read from jpeg_read_scanlines(). - * Application may use this to control its processing loop, e.g., - * "while (output_scanline < output_height)". - */ - JDIMENSION output_scanline; /* 0 .. output_height-1 */ - - /* Current input scan number and number of iMCU rows completed in scan. - * These indicate the progress of the decompressor input side. - */ - int input_scan_number; /* Number of SOS markers seen so far */ - JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */ - - /* The "output scan number" is the notional scan being displayed by the - * output side. The decompressor will not allow output scan/row number - * to get ahead of input scan/row, but it can fall arbitrarily far behind. - */ - int output_scan_number; /* Nominal scan number being displayed */ - JDIMENSION output_iMCU_row; /* Number of iMCU rows read */ - - /* Current progression status. coef_bits[c][i] indicates the precision - * with which component c's DCT coefficient i (in zigzag order) is known. - * It is -1 when no data has yet been received, otherwise it is the point - * transform (shift) value for the most recent scan of the coefficient - * (thus, 0 at completion of the progression). - * This pointer is NULL when reading a non-progressive file. - */ - int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */ - - /* Internal JPEG parameters --- the application usually need not look at - * these fields. Note that the decompressor output side may not use - * any parameters that can change between scans. - */ - - /* Quantization and Huffman tables are carried forward across input - * datastreams when processing abbreviated JPEG datastreams. - */ - - JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; - /* ptrs to coefficient quantization tables, or NULL if not defined */ - - JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; - JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; - /* ptrs to Huffman coding tables, or NULL if not defined */ - - /* These parameters are never carried across datastreams, since they - * are given in SOF/SOS markers or defined to be reset by SOI. - */ - - int data_precision; /* bits of precision in image data */ - - jpeg_component_info * comp_info; - /* comp_info[i] describes component that appears i'th in SOF */ - - boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */ - boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ - - UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ - UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ - UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ - - unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ - - /* These fields record data obtained from optional markers recognized by - * the JPEG library. - */ - boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ - /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */ - UINT8 JFIF_major_version; /* JFIF version number */ - UINT8 JFIF_minor_version; - UINT8 density_unit; /* JFIF code for pixel size units */ - UINT16 X_density; /* Horizontal pixel density */ - UINT16 Y_density; /* Vertical pixel density */ - boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ - UINT8 Adobe_transform; /* Color transform code from Adobe marker */ - - boolean CCIR601_sampling; /* TRUE=first samples are cosited */ - - /* Aside from the specific data retained from APPn markers known to the - * library, the uninterpreted contents of any or all APPn and COM markers - * can be saved in a list for examination by the application. - */ - jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */ - - /* Remaining fields are known throughout decompressor, but generally - * should not be touched by a surrounding application. - */ - - /* - * These fields are computed during decompression startup - */ - int max_h_samp_factor; /* largest h_samp_factor */ - int max_v_samp_factor; /* largest v_samp_factor */ - - int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ - - JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */ - /* The coefficient controller's input and output progress is measured in - * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows - * in fully interleaved JPEG scans, but are used whether the scan is - * interleaved or not. We define an iMCU row as v_samp_factor DCT block - * rows of each component. Therefore, the IDCT output contains - * v_samp_factor*DCT_scaled_size sample rows of a component per iMCU row. - */ - - JSAMPLE * sample_range_limit; /* table for fast range-limiting */ - - /* - * These fields are valid during any one scan. - * They describe the components and MCUs actually appearing in the scan. - * Note that the decompressor output side must not use these fields. - */ - int comps_in_scan; /* # of JPEG components in this scan */ - jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; - /* *cur_comp_info[i] describes component that appears i'th in SOS */ - - JDIMENSION MCUs_per_row; /* # of MCUs across the image */ - JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ - - int blocks_in_MCU; /* # of DCT blocks per MCU */ - int MCU_membership[D_MAX_BLOCKS_IN_MCU]; - /* MCU_membership[i] is index in cur_comp_info of component owning */ - /* i'th block in an MCU */ - - int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */ - - /* This field is shared between entropy decoder and marker parser. - * It is either zero or the code of a JPEG marker that has been - * read from the data source, but has not yet been processed. - */ - int unread_marker; - - /* - * Links to decompression subobjects (methods, private variables of modules) - */ - struct jpeg_decomp_master * master; - struct jpeg_d_main_controller * main; - struct jpeg_d_coef_controller * coef; - struct jpeg_d_post_controller * post; - struct jpeg_input_controller * inputctl; - struct jpeg_marker_reader * marker; - struct jpeg_entropy_decoder * entropy; - struct jpeg_inverse_dct * idct; - struct jpeg_upsampler * upsample; - struct jpeg_color_deconverter * cconvert; - struct jpeg_color_quantizer * cquantize; -}; - - -/* "Object" declarations for JPEG modules that may be supplied or called - * directly by the surrounding application. - * As with all objects in the JPEG library, these structs only define the - * publicly visible methods and state variables of a module. Additional - * private fields may exist after the public ones. - */ - - -/* Error handler object */ - -struct jpeg_error_mgr { - /* Error exit handler: does not return to caller */ - JMETHOD(void, error_exit, (j_common_ptr cinfo)); - /* Conditionally emit a trace or warning message */ - JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); - /* Routine that actually outputs a trace or error message */ - JMETHOD(void, output_message, (j_common_ptr cinfo)); - /* Format a message string for the most recent JPEG error or message */ - JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); -#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ - /* Reset error state variables at start of a new image */ - JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); - - /* The message ID code and any parameters are saved here. - * A message can have one string parameter or up to 8 int parameters. - */ - int msg_code; -#define JMSG_STR_PARM_MAX 80 - union { - int i[8]; - char s[JMSG_STR_PARM_MAX]; - } msg_parm; - - /* Standard state variables for error facility */ - - int trace_level; /* max msg_level that will be displayed */ - - /* For recoverable corrupt-data errors, we emit a warning message, - * but keep going unless emit_message chooses to abort. emit_message - * should count warnings in num_warnings. The surrounding application - * can check for bad data by seeing if num_warnings is nonzero at the - * end of processing. - */ - long num_warnings; /* number of corrupt-data warnings */ - - /* These fields point to the table(s) of error message strings. - * An application can change the table pointer to switch to a different - * message list (typically, to change the language in which errors are - * reported). Some applications may wish to add additional error codes - * that will be handled by the JPEG library error mechanism; the second - * table pointer is used for this purpose. - * - * First table includes all errors generated by JPEG library itself. - * Error code 0 is reserved for a "no such error string" message. - */ - const char * const * jpeg_message_table; /* Library errors */ - int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ - /* Second table can be added by application (see cjpeg/djpeg for example). - * It contains strings numbered first_addon_message..last_addon_message. - */ - const char * const * addon_message_table; /* Non-library errors */ - int first_addon_message; /* code for first string in addon table */ - int last_addon_message; /* code for last string in addon table */ -}; - - -/* Progress monitor object */ - -struct jpeg_progress_mgr { - JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); - - long pass_counter; /* work units completed in this pass */ - long pass_limit; /* total number of work units in this pass */ - int completed_passes; /* passes completed so far */ - int total_passes; /* total number of passes expected */ -}; - - -/* Data destination object for compression */ - -struct jpeg_destination_mgr { - JOCTET * next_output_byte; /* => next byte to write in buffer */ - size_t free_in_buffer; /* # of byte spaces remaining in buffer */ - - JMETHOD(void, init_destination, (j_compress_ptr cinfo)); - JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); - JMETHOD(void, term_destination, (j_compress_ptr cinfo)); -}; - - -/* Data source object for decompression */ - -struct jpeg_source_mgr { - const JOCTET * next_input_byte; /* => next byte to read from buffer */ - size_t bytes_in_buffer; /* # of bytes remaining in buffer */ - - JMETHOD(void, init_source, (j_decompress_ptr cinfo)); - JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); - JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); - JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired)); - JMETHOD(void, term_source, (j_decompress_ptr cinfo)); -}; - - -/* Memory manager object. - * Allocates "small" objects (a few K total), "large" objects (tens of K), - * and "really big" objects (virtual arrays with backing store if needed). - * The memory manager does not allow individual objects to be freed; rather, - * each created object is assigned to a pool, and whole pools can be freed - * at once. This is faster and more convenient than remembering exactly what - * to free, especially where malloc()/free() are not too speedy. - * NB: alloc routines never return NULL. They exit to error_exit if not - * successful. - */ - -#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ -#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ -#define JPOOL_NUMPOOLS 2 - -typedef struct jvirt_sarray_control * jvirt_sarray_ptr; -typedef struct jvirt_barray_control * jvirt_barray_ptr; - - -struct jpeg_memory_mgr { - /* Method pointers */ - JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, - size_t sizeofobject)); - JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, - size_t sizeofobject)); - JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, - JDIMENSION samplesperrow, - JDIMENSION numrows)); - JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, - JDIMENSION blocksperrow, - JDIMENSION numrows)); - JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, - int pool_id, - boolean pre_zero, - JDIMENSION samplesperrow, - JDIMENSION numrows, - JDIMENSION maxaccess)); - JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, - int pool_id, - boolean pre_zero, - JDIMENSION blocksperrow, - JDIMENSION numrows, - JDIMENSION maxaccess)); - JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); - JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, - jvirt_sarray_ptr ptr, - JDIMENSION start_row, - JDIMENSION num_rows, - boolean writable)); - JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, - jvirt_barray_ptr ptr, - JDIMENSION start_row, - JDIMENSION num_rows, - boolean writable)); - JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); - JMETHOD(void, self_destruct, (j_common_ptr cinfo)); - - /* Limit on memory allocation for this JPEG object. (Note that this is - * merely advisory, not a guaranteed maximum; it only affects the space - * used for virtual-array buffers.) May be changed by outer application - * after creating the JPEG object. - */ - long max_memory_to_use; - - /* Maximum allocation request accepted by alloc_large. */ - long max_alloc_chunk; -}; - - -/* Routine signature for application-supplied marker processing methods. - * Need not pass marker code since it is stored in cinfo->unread_marker. - */ -typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo)); - - -/* Declarations for routines called by application. - * The JPP macro hides prototype parameters from compilers that can't cope. - * Note JPP requires double parentheses. - */ - -#ifdef HAVE_PROTOTYPES -#define JPP(arglist) arglist -#else -#define JPP(arglist) () -#endif - - -/* Short forms of external names for systems with brain-damaged linkers. - * We shorten external names to be unique in the first six letters, which - * is good enough for all known systems. - * (If your compiler itself needs names to be unique in less than 15 - * characters, you are out of luck. Get a better compiler.) - */ - -#ifdef NEED_SHORT_EXTERNAL_NAMES -#define jpeg_std_error jStdError -#define jpeg_CreateCompress jCreaCompress -#define jpeg_CreateDecompress jCreaDecompress -#define jpeg_destroy_compress jDestCompress -#define jpeg_destroy_decompress jDestDecompress -#define jpeg_stdio_dest jStdDest -#define jpeg_stdio_src jStdSrc -#define jpeg_set_defaults jSetDefaults -#define jpeg_set_colorspace jSetColorspace -#define jpeg_default_colorspace jDefColorspace -#define jpeg_set_quality jSetQuality -#define jpeg_set_linear_quality jSetLQuality -#define jpeg_add_quant_table jAddQuantTable -#define jpeg_quality_scaling jQualityScaling -#define jpeg_simple_progression jSimProgress -#define jpeg_suppress_tables jSuppressTables -#define jpeg_alloc_quant_table jAlcQTable -#define jpeg_alloc_huff_table jAlcHTable -#define jpeg_start_compress jStrtCompress -#define jpeg_write_scanlines jWrtScanlines -#define jpeg_finish_compress jFinCompress -#define jpeg_write_raw_data jWrtRawData -#define jpeg_write_marker jWrtMarker -#define jpeg_write_m_header jWrtMHeader -#define jpeg_write_m_byte jWrtMByte -#define jpeg_write_tables jWrtTables -#define jpeg_read_header jReadHeader -#define jpeg_start_decompress jStrtDecompress -#define jpeg_read_scanlines jReadScanlines -#define jpeg_finish_decompress jFinDecompress -#define jpeg_read_raw_data jReadRawData -#define jpeg_has_multiple_scans jHasMultScn -#define jpeg_start_output jStrtOutput -#define jpeg_finish_output jFinOutput -#define jpeg_input_complete jInComplete -#define jpeg_new_colormap jNewCMap -#define jpeg_consume_input jConsumeInput -#define jpeg_calc_output_dimensions jCalcDimensions -#define jpeg_save_markers jSaveMarkers -#define jpeg_set_marker_processor jSetMarker -#define jpeg_read_coefficients jReadCoefs -#define jpeg_write_coefficients jWrtCoefs -#define jpeg_copy_critical_parameters jCopyCrit -#define jpeg_abort_compress jAbrtCompress -#define jpeg_abort_decompress jAbrtDecompress -#define jpeg_abort jAbort -#define jpeg_destroy jDestroy -#define jpeg_resync_to_restart jResyncRestart -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* Default error-management setup */ -EXTERN(struct jpeg_error_mgr *) jpeg_std_error - JPP((struct jpeg_error_mgr * err)); - -/* Initialization of JPEG compression objects. - * jpeg_create_compress() and jpeg_create_decompress() are the exported - * names that applications should call. These expand to calls on - * jpeg_CreateCompress and jpeg_CreateDecompress with additional information - * passed for version mismatch checking. - * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx. - */ -#define jpeg_create_compress(cinfo) \ - jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \ - (size_t) sizeof(struct jpeg_compress_struct)) -#define jpeg_create_decompress(cinfo) \ - jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \ - (size_t) sizeof(struct jpeg_decompress_struct)) -EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo, - int version, size_t structsize)); -EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo, - int version, size_t structsize)); -/* Destruction of JPEG compression objects */ -EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo)); -EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); - -/* Standard data source and destination managers: stdio streams. */ -/* Caller is responsible for opening the file before and closing after. */ -#ifdef JPEGLIB_USE_STDIO // allow the use of these functions in specific cases where - // reading/writing jpeg files outside the game directory tree is required. -EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); -EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); -#endif - -/* Default parameter setup for compression */ -EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo)); -/* Compression parameter setup aids */ -EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo, - J_COLOR_SPACE colorspace)); -EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo)); -EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, - boolean force_baseline)); -EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo, - int scale_factor, - boolean force_baseline)); -EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, - const unsigned int *basic_table, - int scale_factor, - boolean force_baseline)); -EXTERN(int) jpeg_quality_scaling JPP((int quality)); -EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo)); -EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo, - boolean suppress)); -EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); -EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); - -/* Main entry points for compression */ -EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo, - boolean write_all_tables)); -EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo, - JSAMPARRAY scanlines, - JDIMENSION num_lines)); -EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo)); - -/* Replaces jpeg_write_scanlines when writing raw downsampled data. */ -EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo, - JSAMPIMAGE data, - JDIMENSION num_lines)); - -/* Write a special marker. See libjpeg.doc concerning safe usage. */ -EXTERN(void) jpeg_write_marker - JPP((j_compress_ptr cinfo, int marker, - const JOCTET * dataptr, unsigned int datalen)); -/* Same, but piecemeal. */ -EXTERN(void) jpeg_write_m_header - JPP((j_compress_ptr cinfo, int marker, unsigned int datalen)); -EXTERN(void) jpeg_write_m_byte - JPP((j_compress_ptr cinfo, int val)); - -/* Alternate compression function: just write an abbreviated table file */ -EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo)); - -/* Decompression startup: read start of JPEG datastream to see what's there */ -EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo, - boolean require_image)); -/* Return value is one of: */ -#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */ -#define JPEG_HEADER_OK 1 /* Found valid image datastream */ -#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */ -/* If you pass require_image = TRUE (normal case), you need not check for - * a TABLES_ONLY return code; an abbreviated file will cause an error exit. - * JPEG_SUSPENDED is only possible if you use a data source module that can - * give a suspension return (the stdio source module doesn't). - */ - -/* Main entry points for decompression */ -EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo)); -EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo, - JSAMPARRAY scanlines, - JDIMENSION max_lines)); -EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); - -/* Replaces jpeg_read_scanlines when reading raw downsampled data. */ -EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo, - JSAMPIMAGE data, - JDIMENSION max_lines)); - -/* Additional entry points for buffered-image mode. */ -EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo)); -EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo, - int scan_number)); -EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo)); -EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo)); -EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo)); -EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo)); -/* Return value is one of: */ -/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */ -#define JPEG_REACHED_SOS 1 /* Reached start of new scan */ -#define JPEG_REACHED_EOI 2 /* Reached end of image */ -#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */ -#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */ - -/* Precalculate output dimensions for current decompression parameters. */ -EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); - -/* Control saving of COM and APPn markers into marker_list. */ -EXTERN(void) jpeg_save_markers - JPP((j_decompress_ptr cinfo, int marker_code, - unsigned int length_limit)); - -/* Install a special processing method for COM or APPn markers. */ -EXTERN(void) jpeg_set_marker_processor - JPP((j_decompress_ptr cinfo, int marker_code, - jpeg_marker_parser_method routine)); - -/* Read or write raw DCT coefficients --- useful for lossless transcoding. */ -EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo)); -EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo, - jvirt_barray_ptr * coef_arrays)); -EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo, - j_compress_ptr dstinfo)); - -/* If you choose to abort compression or decompression before completing - * jpeg_finish_(de)compress, then you need to clean up to release memory, - * temporary files, etc. You can just call jpeg_destroy_(de)compress - * if you're done with the JPEG object, but if you want to clean it up and - * reuse it, call this: - */ -EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo)); -EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); - -/* Generic versions of jpeg_abort and jpeg_destroy that work on either - * flavor of JPEG object. These may be more convenient in some places. - */ -EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo)); -EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo)); - -/* Default restart-marker-resync procedure for use by data source modules */ -EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo, - int desired)); - - -/* These marker codes are exported since applications and data source modules - * are likely to want to use them. - */ - -#define JPEG_RST0 0xD0 /* RST0 marker code */ -#define JPEG_EOI 0xD9 /* EOI marker code */ -#define JPEG_APP0 0xE0 /* APP0 marker code */ -#define JPEG_COM 0xFE /* COM marker code */ - - -/* If we have a brain-damaged compiler that emits warnings (or worse, errors) - * for structure definitions that are never filled in, keep it quiet by - * supplying dummy definitions for the various substructures. - */ - -#ifdef INCOMPLETE_TYPES_BROKEN -#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ -struct jvirt_sarray_control { long dummy; }; -struct jvirt_barray_control { long dummy; }; -struct jpeg_comp_master { long dummy; }; -struct jpeg_c_main_controller { long dummy; }; -struct jpeg_c_prep_controller { long dummy; }; -struct jpeg_c_coef_controller { long dummy; }; -struct jpeg_marker_writer { long dummy; }; -struct jpeg_color_converter { long dummy; }; -struct jpeg_downsampler { long dummy; }; -struct jpeg_forward_dct { long dummy; }; -struct jpeg_entropy_encoder { long dummy; }; -struct jpeg_decomp_master { long dummy; }; -struct jpeg_d_main_controller { long dummy; }; -struct jpeg_d_coef_controller { long dummy; }; -struct jpeg_d_post_controller { long dummy; }; -struct jpeg_input_controller { long dummy; }; -struct jpeg_marker_reader { long dummy; }; -struct jpeg_entropy_decoder { long dummy; }; -struct jpeg_inverse_dct { long dummy; }; -struct jpeg_upsampler { long dummy; }; -struct jpeg_color_deconverter { long dummy; }; -struct jpeg_color_quantizer { long dummy; }; -#endif /* JPEG_INTERNALS */ -#endif /* INCOMPLETE_TYPES_BROKEN */ - - -/* - * The JPEG library modules define JPEG_INTERNALS before including this file. - * The internal structure declarations are read only when that is true. - * Applications using the library should not include jpegint.h, but may wish - * to include jerror.h. - */ - -#ifdef JPEG_INTERNALS -#include "jpegint.h" /* fetch private declarations */ -#include "jerror.h" /* fetch error codes too */ -#endif - -#ifdef __cplusplus -} -#endif - - -#endif /* JPEGLIB_H */ diff --git a/public/kevvaluescompiler.cpp b/public/kevvaluescompiler.cpp deleted file mode 100644 index 675bd7552..000000000 --- a/public/kevvaluescompiler.cpp +++ /dev/null @@ -1,436 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= -#include "keyvaluescompiler.h" -#include "filesystem.h" -#include "tier1/KeyValues.h" - -extern IFileSystem *g_pFullFileSystem; - -bool CRunTimeKeyValuesStringTable::ReadStringTable( int numStrings, CUtlBuffer& buf ) -{ - Assert( m_Strings.Count() == 0 ); - - CUtlVector< int > offsets; - offsets.EnsureCapacity( numStrings ); - - offsets.CopyArray( (int *)( buf.PeekGet() ), numStrings ); - - // Skip over data - buf.SeekGet( CUtlBuffer::SEEK_HEAD, buf.TellGet() + numStrings * sizeof( int ) ); - - int stringSize = buf.GetInt(); - - // Read in the string table - m_Strings.EnsureCapacity( numStrings ); - int i; - for ( i = 0 ; i < numStrings; ++i ) - { - m_Strings.AddToTail( (const char *)buf.PeekGet( offsets[ i ] ) ); - } - - buf.SeekGet( CUtlBuffer::SEEK_HEAD, buf.TellGet() + stringSize ); - - return true; -} - -void CCompiledKeyValuesWriter::BuildKVData_R( KeyValues *kv, int parent ) -{ - // Add self - KVInfo_t info; - info.key = m_StringTable.AddString( kv->GetName() ); - info.value = m_StringTable.AddString( kv->GetString() ); - - info.SetSubTree( kv->GetFirstSubKey() != NULL ? true : false ); - info.SetParent( parent ); - - int newParent = m_Data.AddToTail( info ); - - // Then add children - for ( KeyValues *sub = kv->GetFirstSubKey(); sub; sub = sub->GetNextKey() ) - { - BuildKVData_R( sub, newParent ); - } - - // Then add peers - if ( parent == -1 ) - { - if ( kv->GetNextKey() ) - { - BuildKVData_R( kv->GetNextKey(), parent ); - } - } -} - -void CCompiledKeyValuesWriter::Describe( const KVFile_t& file ) -{ - Msg( "file( %s )\n", m_StringTable.String( file.filename ) ); - - int c = file.numElements; - for ( int i = 0; i < c; ++i ) - { - KVInfo_t &info = m_Data[ file.firstElement + i ]; - if ( info.IsSubTree() ) - { - Msg( "%d: %s -> subtree at parent %i\n", - file.firstElement + i, - m_StringTable.String( info.key ), - info.GetParent() ); - } - else - { - Msg( "%d: %s -> %s at parent %i\n", - file.firstElement + i, - m_StringTable.String( info.key ), - m_StringTable.String( info.value ), - info.GetParent() ); - } - } -} - -void CCompiledKeyValuesWriter::AppendKeyValuesFile( char const *filename ) -{ - KVFile_t kvf; - kvf.filename = m_StringTable.AddString( filename ); - kvf.firstElement = m_Data.Count(); - - KeyValues *kv = new KeyValues( filename ); - if ( kv->LoadFromFile( g_pFullFileSystem, filename ) ) - { - // Add to dictionary - // do a depth first traversal of the keyvalues - BuildKVData_R( kv, -1 ); - } - kv->deleteThis(); - - kvf.numElements = m_Data.Count() - kvf.firstElement; - -// Describe( kvf ); - - m_Files.AddToTail( kvf ); -} - -void CCompiledKeyValuesWriter::WriteData( CUtlBuffer& buf ) -{ - int c = m_Data.Count(); - buf.PutInt( c ); - for ( int i = 0; i < c; ++i ) - { - KVInfo_t &info = m_Data[ i ]; - buf.PutShort( info.key ); - buf.PutShort( info.value ); - buf.PutShort( info.GetParent() ); - buf.PutChar( info.IsSubTree() ? 1 : 0 ); - } -} - -void CCompiledKeyValuesWriter::WriteFiles( CUtlBuffer &buf ) -{ - int c = m_Files.Count(); - buf.PutInt( c ); - for ( int i = 0; i < c; ++i ) - { - KVFile_t &file = m_Files[ i ]; - buf.PutShort( file.filename ); - buf.PutShort( file.firstElement ); - buf.PutShort( file.numElements ); - } -} - -void CCompiledKeyValuesWriter::WriteStringTable( CUtlBuffer& buf ) -{ - int i; - CUtlVector< int > offsets; - - CUtlBuffer stringBuffer; - - offsets.AddToTail( stringBuffer.TellPut() ); - - stringBuffer.PutString( "" ); - // save all the rest - int c = m_StringTable.GetNumStrings(); - for ( i = 1; i < c; i++) - { - offsets.AddToTail( stringBuffer.TellPut() ); - stringBuffer.PutString( m_StringTable.String( i ) ); - } - - buf.Put( offsets.Base(), offsets.Count() * sizeof( int ) ); - - buf.PutInt( stringBuffer.TellPut() ); - buf.Put( stringBuffer.Base(), stringBuffer.TellPut() ); -} - -void CCompiledKeyValuesWriter::WriteFile( char const *outfile ) -{ - CUtlBuffer buf; - - // Write the data file out - KVHeader_t header; - header.fileid = COMPILED_KEYVALUES_ID; - header.version = COMPILED_KEYVALUES_VERSION; - header.numStrings = m_StringTable.GetNumStrings(); - - buf.Put( &header, sizeof( header ) ); - - WriteStringTable( buf ); - WriteData( buf ); - WriteFiles( buf ); - - g_pFullFileSystem->WriteFile( outfile, NULL, buf ); -} - -CCompiledKeyValuesReader::CCompiledKeyValuesReader() - : m_Dict( 0, 0, FileInfo_t::Less ) -{ -} - -int CCompiledKeyValuesReader::First() const -{ - return m_Dict.FirstInorder(); -} - -int CCompiledKeyValuesReader::Next( int i ) const -{ - return m_Dict.NextInorder( i ); -} - -int CCompiledKeyValuesReader::InvalidIndex() const -{ - return m_Dict.InvalidIndex(); -} - -void CCompiledKeyValuesReader::GetFileName( int index, char *buf, size_t bufsize ) -{ - Assert( buf ); - buf[ 0 ] = 0; - FileNameHandle_t& handle = m_Dict[ index ].hFile; - g_pFullFileSystem->String( handle, buf, bufsize ); -} - -bool CCompiledKeyValuesReader::LoadFile( char const *filename ) -{ - int i; - m_LoadBuffer.Purge(); - - g_pFullFileSystem->ReadFile( filename, NULL, m_LoadBuffer ); - - KVHeader_t header; - m_LoadBuffer.Get( &header, sizeof( header ) ); - - if ( header.fileid != COMPILED_KEYVALUES_ID ) - { - return false; - } - - if ( header.version != COMPILED_KEYVALUES_VERSION ) - { - return false; - } - - if ( !m_StringTable.ReadStringTable( header.numStrings, m_LoadBuffer ) ) - { - return false; - } - - // Now parse the data - int dataCount = m_LoadBuffer.GetInt(); - m_Data.EnsureCapacity( dataCount ); - for ( i = 0; i < dataCount; ++i ) - { - KVInfo_t info; - info.key = m_LoadBuffer.GetShort(); - info.value = m_LoadBuffer.GetShort(); - info.SetParent( m_LoadBuffer.GetShort() ); - info.SetSubTree( m_LoadBuffer.GetChar() == 1 ? true : false ); - m_Data.AddToTail( info ); - } - - int fileCount = m_LoadBuffer.GetInt(); - for ( i = 0; i < fileCount; ++i ) - { - FileInfo_t kvf; - short fileNameString = m_LoadBuffer.GetShort(); - - kvf.hFile = g_pFullFileSystem->FindOrAddFileName( m_StringTable.Lookup( fileNameString ) ); - kvf.nFirstIndex = m_LoadBuffer.GetShort(); - kvf.nCount = m_LoadBuffer.GetShort(); - - m_Dict.Insert( kvf ); - } - - return true; -} - -struct CreateHelper_t -{ - int index; - KeyValues *kv; - KeyValues *tail; - - static bool Less( const CreateHelper_t& lhs, const CreateHelper_t& rhs ) - { - return lhs.index < rhs.index; - } -}; - -KeyValues *CCompiledKeyValuesReader::CreateFromData( const FileInfo_t& info ) -{ - KeyValues *head = new KeyValues( "" ); - if ( CreateInPlaceFromData( *head, info ) ) - { - return head; - } - else - { - head->deleteThis(); - return NULL; - } -} - -bool CCompiledKeyValuesReader::CreateInPlaceFromData( KeyValues& head, const FileInfo_t& info ) -{ - int first = info.nFirstIndex; - int num = info.nCount; - - KeyValues *root = NULL; - KeyValues *tail = NULL; - - CUtlRBTree< CreateHelper_t, int > helper( 0, 0, CreateHelper_t::Less ); - - for ( int i = 0; i < num; ++i ) - { - int offset = first + i; - KVInfo_t& info = m_Data[ offset ]; - - if ( info.GetParent() != -1 ) - { - CreateHelper_t search; - search.index = info.GetParent(); - int idx = helper.Find( search ); - if ( idx == helper.InvalidIndex() ) - { - return NULL; - } - - KeyValues *parent = helper[ idx ].kv; - Assert( parent ); - - KeyValues *sub = new KeyValues( m_StringTable.Lookup( info.key ) ); - - if ( !info.IsSubTree() ) - { - sub->SetStringValue(m_StringTable.Lookup( info.value ) ); - } - - if ( !parent->GetFirstSubKey() ) - { - parent->AddSubKey( sub ); - } - else - { - KeyValues *last = helper[ idx ].tail; - last->SetNextKey( sub ); - } - - helper[ idx ].tail = sub; - - CreateHelper_t insert; - insert.index = offset; - insert.kv = sub; - insert.tail = NULL; - helper.Insert( insert ); - } - else - { - if ( !root ) - { - root = &head; - root->SetName( m_StringTable.Lookup( info.key ) ); - tail = root; - - CreateHelper_t insert; - insert.index = offset; - insert.kv = root; - insert.tail = NULL; - helper.Insert( insert ); - } - else - { - CreateHelper_t insert; - insert.index = offset; - insert.kv = new KeyValues( m_StringTable.Lookup( info.key ) ); - insert.tail = NULL; - helper.Insert( insert ); - - tail->SetNextKey( insert.kv ); - tail = insert.kv; - } - } - } - return true; -} - - -bool CCompiledKeyValuesReader::InstanceInPlace( KeyValues& head, char const *kvfilename ) -{ - char sz[ 512 ]; - Q_strncpy( sz, kvfilename, sizeof( sz ) ); - Q_FixSlashes( sz ); - - FileInfo_t search; - search.hFile = g_pFullFileSystem->FindOrAddFileName( sz ); - - int idx = m_Dict.Find( search ); - if ( idx == m_Dict.InvalidIndex() ) - { - return false; - } - - const FileInfo_t& info = m_Dict[ idx ]; - - return CreateInPlaceFromData( head, info ); -} - -KeyValues *CCompiledKeyValuesReader::Instance( char const *kvfilename ) -{ - char sz[ 512 ]; - Q_strncpy( sz, kvfilename, sizeof( sz ) ); - Q_FixSlashes( sz ); - - FileInfo_t search; - search.hFile = g_pFullFileSystem->FindOrAddFileName( sz ); - - int idx = m_Dict.Find( search ); - if ( idx == m_Dict.InvalidIndex() ) - { - return NULL; - } - - const FileInfo_t& info = m_Dict[ idx ]; - - return CreateFromData( info ); -} - -bool CCompiledKeyValuesReader::LookupKeyValuesRootKeyName( char const *kvfilename, char *outbuf, size_t bufsize ) -{ - char sz[ 512 ]; - Q_strncpy( sz, kvfilename, sizeof( sz ) ); - Q_FixSlashes( sz ); - - FileInfo_t search; - search.hFile = g_pFullFileSystem->FindOrAddFileName( sz ); - - int idx = m_Dict.Find( search ); - if ( idx == m_Dict.InvalidIndex() ) - { - return false; - } - - const FileInfo_t& info = m_Dict[ idx ]; - - Q_strncpy( outbuf, m_StringTable.Lookup( m_Data[ info.nFirstIndex ].key ), bufsize ); - return true; -} diff --git a/public/keyframe/keyframe.cpp b/public/keyframe/keyframe.cpp deleted file mode 100644 index 1b81f13d8..000000000 --- a/public/keyframe/keyframe.cpp +++ /dev/null @@ -1,504 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#include -#include -#include -#include - -typedef unsigned char byte; - -#ifdef _MSC_VER -#pragma warning(disable:4244) -#endif - -#include "tier0/dbg.h" -#include "mathlib/vector.h" -#include "keyframe.h" -#include "mathlib/mathlib.h" -#include "rope_shared.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// -// Implementation of keyframe.h interface -// -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -// Key Frames -//----------------------------------------------------------------------------- -#define HIGHEST_KEYFRAME 3 -#define LOWEST_KEYFRAME -3 - -#define TOTAL_KEYFRAMES (HIGHEST_KEYFRAME - LOWEST_KEYFRAME + 1) - -// - -struct KeyFrame_t -{ - Vector vPos; - Quaternion qRot; -}; - - -KeyFrame_t g_KeyFrames[ TOTAL_KEYFRAMES ]; -KeyFrame_t *g_KeyFramePtr = &g_KeyFrames[ -LOWEST_KEYFRAME ]; // points to the middle keyframe, keyframe 0 - -bool Motion_SetKeyAngles( int keyNum, Quaternion &quatAngles ) -{ - if ( keyNum > HIGHEST_KEYFRAME || keyNum < LOWEST_KEYFRAME ) - return false; - - g_KeyFramePtr[keyNum].qRot = quatAngles; - return true; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// Time Modifier function enumeration & implementation -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -typedef float (*TimeModifierFunc_t)(float); - -typedef struct -{ - const char *szName; - TimeModifierFunc_t pFunc; - -} TimeModifier_t; - -float TimeModifierFunc_Linear( float time ) -{ - return time; -} - -float TimeModifierFunc_Cosine( float time ) -{ - return ( cos((time+1) * M_PI) * 0.5 ) + 0.5; -} - -float TimeModifierFunc_TimeSquared( float time ) -{ - return (time * time); -} - -TimeModifier_t g_TimeModifiers[] = -{ - { "Linear", TimeModifierFunc_Linear }, - { "Accel/Deaccel (cosine)", TimeModifierFunc_Cosine }, - { "Accel (time*time)", TimeModifierFunc_TimeSquared }, -}; - -int Motion_GetNumberOfTimeModifiers( void ) -{ - return ARRAYSIZE(g_TimeModifiers); -} - -bool Motion_GetTimeModifierDetails( int timeInterpNum, const char **outName ) -{ - if ( timeInterpNum < 0 || timeInterpNum >= Motion_GetNumberOfTimeModifiers() ) - { - return false; - } - - if ( !g_TimeModifiers[0].szName || !g_TimeModifiers[0].pFunc ) - { - return false; - } - - if ( outName ) - *outName = g_TimeModifiers[0].szName; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : time - -// timeModifierFuncNum - -// *outNewTime - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool Motion_CalculateModifiedTime( float time, int timeModifierFuncNum, float *outNewTime ) -{ - *outNewTime = g_TimeModifiers[timeModifierFuncNum].pFunc( time ); - return true; -} - - - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// Position interpolator function enumeration & implementation -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -// ------------------------------------------------------------------------------------ // -// Linear position interpolator. -// ------------------------------------------------------------------------------------ // - -class CPositionInterpolator_Linear : public IPositionInterpolator -{ -public: - virtual void Release(); - virtual void GetDetails( const char **outName, int *outMinKeyReq, int *outMaxKeyReq ); - virtual void SetKeyPosition( int keyNum, Vector const &vPos ); - virtual void InterpolatePosition( float time, Vector &vOut ); - virtual bool ProcessKey( char const *pName, char const *pValue ) { return false; } -}; - -CPositionInterpolator_Linear g_LinearInterpolator; - -IPositionInterpolator* GetLinearInterpolator() -{ - return &g_LinearInterpolator; -} - -void CPositionInterpolator_Linear::Release() -{ -} - -void CPositionInterpolator_Linear::GetDetails( const char **outName, int *outMinKeyReq, int *outMaxKeyReq ) -{ - *outName = "Linear"; - *outMinKeyReq = 0; - *outMaxKeyReq = 1; -} - -void CPositionInterpolator_Linear::SetKeyPosition( int keyNum, Vector const &vPos ) -{ - Assert ( keyNum <= HIGHEST_KEYFRAME && keyNum >= LOWEST_KEYFRAME ); - VectorCopy( vPos, g_KeyFramePtr[keyNum].vPos ); -} - -void CPositionInterpolator_Linear::InterpolatePosition( float time, Vector &vOut ) -{ - VectorLerp( g_KeyFramePtr[0].vPos, g_KeyFramePtr[1].vPos, time, vOut ); -} - - - - - -// ------------------------------------------------------------------------------------ // -// Catmull-Rom position interpolator. -// ------------------------------------------------------------------------------------ // - -class CPositionInterpolator_CatmullRom : public IPositionInterpolator -{ -public: - virtual void Release(); - virtual void GetDetails( const char **outName, int *outMinKeyReq, int *outMaxKeyReq ); - virtual void SetKeyPosition( int keyNum, Vector const &vPos ); - virtual void InterpolatePosition( float time, Vector &vOut ); - virtual bool ProcessKey( char const *pName, char const *pValue ) { return false; } -}; - -CPositionInterpolator_CatmullRom g_CatmullRomInterpolator; - -IPositionInterpolator* GetCatmullRomInterpolator() -{ - return &g_CatmullRomInterpolator; -} - -void CPositionInterpolator_CatmullRom::Release() -{ -} - -void CPositionInterpolator_CatmullRom::GetDetails( const char **outName, int *outMinKeyReq, int *outMaxKeyReq ) -{ - *outName = "Catmull-Rom Spline"; - *outMinKeyReq = -1; - *outMaxKeyReq = 2; -} - -void CPositionInterpolator_CatmullRom::SetKeyPosition( int keyNum, Vector const &vPos ) -{ - Assert ( keyNum <= HIGHEST_KEYFRAME && keyNum >= LOWEST_KEYFRAME ); - VectorCopy( vPos, g_KeyFramePtr[keyNum].vPos ); -} - -void CPositionInterpolator_CatmullRom::InterpolatePosition( float time, Vector &vOut ) -{ - Catmull_Rom_Spline( - g_KeyFramePtr[-1].vPos, - g_KeyFramePtr[0].vPos, - g_KeyFramePtr[1].vPos, - g_KeyFramePtr[2].vPos, - time, - vOut ); -} - - - -// ------------------------------------------------------------------------------------ // -// Rope interpolator. -// ------------------------------------------------------------------------------------ // -#include "rope_physics.h" - -class CRopeDelegate : public CSimplePhysics::IHelper -{ -public: - virtual void GetNodeForces( CSimplePhysics::CNode *pNodes, int iNode, Vector *pAccel ); - virtual void ApplyConstraints( CSimplePhysics::CNode *pNodes, int nNodes ); - - -public: - Vector m_CurEndPoints[2]; -}; - -void CRopeDelegate::GetNodeForces( CSimplePhysics::CNode *pNodes, int iNode, Vector *pAccel ) -{ - // Gravity. - pAccel->Init( 0, 0, -1500 ); -} - -void CRopeDelegate::ApplyConstraints( CSimplePhysics::CNode *pNodes, int nNodes ) -{ - if( nNodes >= 2 ) - { - pNodes[0].m_vPos = m_CurEndPoints[0]; - pNodes[nNodes-1].m_vPos = m_CurEndPoints[1]; - } -} - - -class CPositionInterpolator_Rope : public IPositionInterpolator -{ -public: - CPositionInterpolator_Rope(); - - virtual void Release(); - virtual void GetDetails( const char **outName, int *outMinKeyReq, int *outMaxKeyReq ); - virtual void SetKeyPosition( int keyNum, Vector const &vPos ); - virtual void InterpolatePosition( float time, Vector &vOut ); - virtual bool ProcessKey( char const *pName, char const *pValue ); - - -private: - CRopePhysics<10> m_RopePhysics; - CRopeDelegate m_Delegate; - - float m_flSlack; // Extra length of rope. - - bool m_bChange; - int m_nSegments; -}; - -IPositionInterpolator* GetRopeInterpolator() -{ - return new CPositionInterpolator_Rope; -} - - -CPositionInterpolator_Rope::CPositionInterpolator_Rope() -{ - m_flSlack = 0; - m_bChange = false; - m_nSegments = 5; - - for( int i=0; i < 2; i++ ) - m_Delegate.m_CurEndPoints[i] = Vector( 1e24, 1e24, 1e24 ); -} - -void CPositionInterpolator_Rope::Release() -{ - delete this; -} - -void CPositionInterpolator_Rope::GetDetails( const char **outName, int *outMinKeyReq, int *outMaxKeyReq ) -{ - *outName = "Rope"; - *outMinKeyReq = 0; - *outMinKeyReq = 1; -} - -void CPositionInterpolator_Rope::SetKeyPosition( int keyNum, Vector const &vPos ) -{ - if( keyNum == 0 || keyNum == 1 ) - { - if( vPos != m_Delegate.m_CurEndPoints[keyNum] ) - m_bChange = true; - - m_Delegate.m_CurEndPoints[keyNum] = vPos; - } -} - -void CPositionInterpolator_Rope::InterpolatePosition( float time, Vector &vOut ) -{ - // Check if we need to resimulate.. - if( m_bChange ) - { - m_RopePhysics.SetNumNodes( m_nSegments ); - - // Init all the nodes. - for( int i=0; i < m_RopePhysics.NumNodes(); i++ ) - m_RopePhysics.GetNode(i)->m_vPos = m_RopePhysics.GetNode(i)->m_vPrevPos = m_Delegate.m_CurEndPoints[0]; - - float flDist = (m_Delegate.m_CurEndPoints[0] - m_Delegate.m_CurEndPoints[1]).Length(); - flDist += m_flSlack; - - m_RopePhysics.Restart(); - m_RopePhysics.SetupSimulation( flDist / (m_RopePhysics.NumNodes() - 1), &m_Delegate ); - - // Run the simulation for a while to let the rope settle down.. - m_RopePhysics.Simulate( 5 ); - - m_bChange = false; - } - - // Ok, now we have all the nodes setup.. - float flNode = time * (m_RopePhysics.NumNodes()-1); - int iNode = (int)( flNode ); - VectorLerp( - m_RopePhysics.GetNode(iNode)->m_vPredicted, - m_RopePhysics.GetNode(iNode+1)->m_vPredicted, - flNode - iNode, - vOut ); -} - -bool CPositionInterpolator_Rope::ProcessKey( char const *pName, char const *pValue ) -{ - if( stricmp( pName, "Slack" ) == 0 ) - { - m_flSlack = atof( pValue ) + ROPESLACK_FUDGEFACTOR; - m_bChange = true; - return true; - } - else if( stricmp( pName, "Type" ) == 0 ) - { - int iType = atoi( pValue ); - if( iType == 0 ) - m_nSegments = ROPE_MAX_SEGMENTS; - else if( iType == 1 ) - m_nSegments = ROPE_TYPE1_NUMSEGMENTS; - else - m_nSegments = ROPE_TYPE2_NUMSEGMENTS; - - m_bChange = true; - return true; - } - - return false; -} - - - -// ------------------------------------------------------------------------------------ // -// The global table of all the position interpolators. -// ------------------------------------------------------------------------------------ // - -typedef IPositionInterpolator* (*PositionInterpolatorCreateFn)(); -PositionInterpolatorCreateFn g_PositionInterpolatorCreateFns[] = -{ - GetLinearInterpolator, - GetCatmullRomInterpolator, - GetRopeInterpolator -}; - -int Motion_GetNumberOfPositionInterpolators( void ) -{ - return ARRAYSIZE(g_PositionInterpolatorCreateFns); -} - - -IPositionInterpolator* Motion_GetPositionInterpolator( int interpNum ) -{ - Assert( interpNum >= 0 && interpNum < Motion_GetNumberOfPositionInterpolators() ); - return g_PositionInterpolatorCreateFns[clamp( interpNum, 0, Motion_GetNumberOfPositionInterpolators() - 1 )](); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// Rotation interpolator function enumeration & implementation -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -typedef void (*RotationInterpolatorFunc_t)(float time, Quaternion &outRot); - -typedef struct -{ - const char *szName; - RotationInterpolatorFunc_t pFunc; - - // defines the range of keys this interpolator needs to function - int iMinReqKeyFrame; - int iMaxReqKeyFrame; - -} RotationInterpolator_t; - -void RotationInterpolatorFunc_Linear( float time, Quaternion &outRot ) -{ - // basic 4D spherical linear interpolation - QuaternionSlerp( g_KeyFramePtr[0].qRot, g_KeyFramePtr[1].qRot, time, outRot ); -} - -RotationInterpolator_t g_RotationInterpolators[] = -{ - { "Linear", RotationInterpolatorFunc_Linear, 0, 1 }, -}; - -int Motion_GetNumberOfRotationInterpolators( void ) -{ - return ARRAYSIZE(g_RotationInterpolators); -} - -bool Motion_GetRotationInterpolatorDetails( int rotInterpNum, const char **outName, int *outMinKeyReq, int *outMaxKeyReq ) -{ - if ( rotInterpNum < 0 || rotInterpNum >= Motion_GetNumberOfRotationInterpolators() ) - { - return false; - } - - if ( !g_RotationInterpolators[rotInterpNum].szName || !g_RotationInterpolators[rotInterpNum].pFunc ) - { - return false; - } - - if ( outName ) - *outName = g_RotationInterpolators[rotInterpNum].szName; - - if ( outMinKeyReq ) - *outMinKeyReq = g_RotationInterpolators[rotInterpNum].iMinReqKeyFrame; - - if ( outMaxKeyReq ) - *outMaxKeyReq = g_RotationInterpolators[rotInterpNum].iMaxReqKeyFrame; - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Interpolates a rotation -// Time is assumed to have already been modified by the TimeModifyFunc (above) -// Requires the keyframes be already set -// Input : time - value from 0..1 -// interpFuncNum - -// *outQuatRotation - result in quaternion form -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool Motion_InterpolateRotation( float time, int interpFuncNum, Quaternion &outQuatRotation ) -{ - if ( time < 0.0f || time > 1.0f ) - return false; - - g_RotationInterpolators[interpFuncNum].pFunc( time, outQuatRotation ); - return true; -} diff --git a/public/keyframe/keyframe.h b/public/keyframe/keyframe.h deleted file mode 100644 index 3c42113c7..000000000 --- a/public/keyframe/keyframe.h +++ /dev/null @@ -1,42 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Keyframed animation header -// shared between game and tools -//=============================================================================// - -#ifndef KEYFRAME_H -#define KEYFRAME_H -#pragma once - - -class IPositionInterpolator -{ -public: - virtual void Release() = 0; - - virtual void GetDetails( const char **outName, int *outMinKeyReq, int *outMaxKeyReq ) = 0; - virtual void SetKeyPosition( int keyNum, Vector const &vPos ) = 0; - virtual void InterpolatePosition( float time, Vector &vOut ) = 0; - - // Returns true if the key causes a change that changes the interpolated positions. - virtual bool ProcessKey( char const *pName, char const *pValue ) = 0; -}; - - -// Time modifiers. -int Motion_GetNumberOfTimeModifiers( void ); -bool Motion_GetTimeModifierDetails( int timeInterpNum, const char **outName ); -bool Motion_CalculateModifiedTime( float time, int timeModifierFuncNum, float *outNewTime ); - -// Position interpolators. -int Motion_GetNumberOfPositionInterpolators( void ); -IPositionInterpolator* Motion_GetPositionInterpolator( int interpNum ); - -// Rotation interpolators. -int Motion_GetNumberOfRotationInterpolators( void ); -bool Motion_GetRotationInterpolatorDetails( int rotInterpNum, const char **outName, int *outMinKeyReq, int *outMaxKeyReq ); -bool Motion_InterpolateRotation( float time, int interpFuncNum, Quaternion &outQuatRotation ); -bool Motion_SetKeyAngles( int keyNum, Quaternion &quatAngles ); - - -#endif // KEYFRAME_H diff --git a/public/keyvaluescompiler.h b/public/keyvaluescompiler.h deleted file mode 100644 index ec109a517..000000000 --- a/public/keyvaluescompiler.h +++ /dev/null @@ -1,188 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef KEYVALUESCOMPILER_H -#define KEYVALUESCOMPILER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/platform.h" -#include "tier1/utlbuffer.h" -#include "tier1/utlsymbol.h" -#include "tier1/utldict.h" - -class KeyValues; - -#define COMPILED_KEYVALUES_ID MAKEID( 'V', 'K', 'V', 'F' ) - -#define COMPILED_KEYVALUES_VERSION 1 - -struct KVHeader_t -{ - int fileid; - int version; - int numStrings; -}; - -#pragma pack(1) -struct KVFile_t -{ - KVFile_t() : - filename( 0 ), - firstElement( 0 ), - numElements( 0 ) - { - } - short filename; - short firstElement; - short numElements; -}; - -struct KVInfo_t -{ - KVInfo_t() : - key( 0 ), - value( 0 ), - parentIndex( -1 ), - issubtree( false ) - { - } - - inline void SetParent( int index ) - { - Assert( index <= 32768 ); - parentIndex = index; - } - - inline short GetParent() const - { - return parentIndex; - } - - inline void SetSubTree( bool state ) - { - issubtree = state; - } - - inline bool IsSubTree() const - { - return issubtree; - } - - short key; - short value; - -private: - - short parentIndex; - bool issubtree; -}; -#pragma pack() - -//----------------------------------------------------------------------------- -// Purpose: stringtable is a session global string table. -//----------------------------------------------------------------------------- -class CCompiledKeyValuesWriter -{ -public: - - CCompiledKeyValuesWriter() - { - m_StringTable.AddString( "" ); - } - - void AppendKeyValuesFile( char const *filename ); - void WriteFile( char const *outfile ); - -private: - - void Describe( const KVFile_t& file ); - - void BuildKVData_R( KeyValues *kv, int parent ); - - void WriteStringTable( CUtlBuffer& buf ); - void WriteData( CUtlBuffer& buf ); - void WriteFiles( CUtlBuffer &buf ); - - CUtlVector< KVFile_t > m_Files; - CUtlVector< KVInfo_t > m_Data; - - CUtlSymbolTable m_StringTable; -}; - - -class CRunTimeKeyValuesStringTable -{ -public: - - bool ReadStringTable( int numStrings, CUtlBuffer& buf ); - - inline int CRunTimeKeyValuesStringTable::Count() const - { - return m_Strings.Count(); - } - - inline char const *Lookup( short index ) - { - return m_Strings[ index ]; - } - -private: - CUtlVector< const char * > m_Strings; -}; - -class CCompiledKeyValuesReader -{ -public: - - CCompiledKeyValuesReader(); - - bool LoadFile( char const *filename ); - - KeyValues *Instance( char const *kvfilename ); - bool InstanceInPlace( KeyValues& head, char const *kvfilename ); - bool LookupKeyValuesRootKeyName( char const *kvfilename, char *outbuf, size_t bufsize ); - - int First() const; - int Next( int i ) const; - int InvalidIndex() const; - - void GetFileName( int index, char *buf, size_t bufsize ); - -private: - - struct FileInfo_t - { - FileInfo_t() : - hFile( 0 ), - nFirstIndex( 0 ), - nCount( 0 ) - { - } - FileNameHandle_t hFile; - short nFirstIndex; - short nCount; - - static bool Less( const FileInfo_t& lhs, const FileInfo_t& rhs ) - { - return lhs.hFile < rhs.hFile; - } - }; - - KeyValues *CreateFromData( const FileInfo_t& info ); - bool CreateInPlaceFromData( KeyValues& head, const FileInfo_t& info ); - - // Now get the actual files - CUtlRBTree< FileInfo_t, unsigned short > m_Dict; - CUtlVector< KVInfo_t > m_Data; - - CRunTimeKeyValuesStringTable m_StringTable; - - CUtlBuffer m_LoadBuffer; -}; - -#endif // KEYVALUESCOMPILER_H diff --git a/public/list.h b/public/list.h deleted file mode 100644 index d76d36dc1..000000000 --- a/public/list.h +++ /dev/null @@ -1,352 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef __LIST_H__ -#define __LIST_H__ - -// TODO: -// GetPositionAtIndex needs to keep a cache of the previous call so -// that it doesn't do a linear search every time. - -#include - -// FIXME: change the name of this to something more specific. -typedef struct -{ -} _Position; -typedef _Position *Position; - -template class GList; -template class GListIterator; - -// GListNode: Class decleration and definition -template class GListNode -{ -private: - T data; - GListNode *next; - GListNode *prev; - GListNode(); - GListNode( T item ); - friend class GList; - friend class GListIterator; -}; - -template -GListNode::GListNode() -{ - next = NULL; - prev = NULL; -} - -template -GListNode::GListNode( T item ) -{ - data = item; - next = NULL; - prev = NULL; -} - -// GList: Class decleration and definition -template class GList -{ -public: - // Contructors/destructors - GList(); - - // - Position InsertAtHead( T ); - Position InsertAtTail( T ); - T Remove( Position position ); - void RemoveAll( void (*DeleteItem)( T ) ); - void RemoveSelectedItems( bool (*NeedsRemovalFunc)( T ), void (*DeleteItemFunc)( T ) ); - Position InsertAfter( T item, Position position ); - Position InsertBefore( T item, Position position ); - bool IsEmpty(); - int GetNumItems(); - T GetItemAtPosition( Position position ); - Position GetPositionAtIndex( int index ); - T GetItemAtIndex( int index ); - -protected: - GListNode *head; - GListNode *tail; - int numItems; - friend class GListIterator; -}; - -template -GList::GList() -{ - // Set up a dummy head node and a dummy tail node. - head = new GListNode; - tail = new GListNode; - head->next = tail; - head->prev = head; - tail->next = tail; - tail->prev = head; - numItems = 0; -} - -template -Position GList::InsertAtHead( T item ) -{ - GListNode *newNode = new GListNode( item ); - head->next->prev = newNode; - newNode->next = head->next; - newNode->prev = head; - head->next = newNode; - numItems++; - return ( Position )( void * )newNode; -} - -template -Position GList::InsertAtTail( T item ) -{ - GListNode *newNode = new GListNode( item ); - tail->prev->next = newNode; - newNode->prev = tail->prev; - tail->prev = newNode; - newNode->next = tail; - numItems++; - return ( Position )( void * )newNode; -} - -template -T GList::Remove( Position position ) -{ - GListNode *node = ( GListNode * )( void * )position; - node->prev->next = node->next; - node->next->prev = node->prev; - T data = node->data; - numItems--; - delete node; - return data; -} - -template -void GList::RemoveAll( void (*DeleteItemFunc)( T ) ) -{ - GListNode *tmpNode; - GListNode *node = head->next; - while( node != tail ) - { - if( DeleteItemFunc ) - { - DeleteItemFunc( node->data ); - } - tmpNode = node->next; - delete node; - node = tmpNode; - } - head->next = tail; - head->prev = head; - tail->next = tail; - tail->prev = head; - numItems = 0; -} - -template -void GList::RemoveSelectedItems( bool (*NeedsRemovalFunc)( T ), void (*DeleteItemFunc)( T ) ) -{ - GListNode *tmpNode; - GListNode *node = head->next; - while( node != tail ) - { - if( NeedsRemovalFunc( node->data ) ) - { - DeleteItemFunc( node->data ); - node->prev->next = node->next; - node->next->prev = node->prev; - tmpNode = node; - node = node->next; - delete tmpNode; - numItems--; - } - else - { - node = node->next; - } - } -} - -template -Position GList::InsertAfter( T item, Position position ) -{ - GListNode *node = ( GListNode * )( void * )position; - GListNode *newNode = new GListNode( item ); - newNode->prev = node; - newNode->next = node->next; - node->next->prev = newNode; - node->next = newNode; - numItems++; - return ( Position )( void * )newNode; -} - -template -Position GList::InsertBefore( T item, Position position ) -{ - GListNode *node = ( GListNode * )( void * )position; - GListNode *newNode = new GListNode( item ); - newNode->prev = node->prev; - newNode->next = node; - node->prev->next = newNode; - node->prev = newNode; - numItems++; - return ( Position )( void * )newNode; -} - -template -bool GList::IsEmpty() -{ - return ( numItems == 0 ); -} - -template -int GList::GetNumItems() -{ - return numItems; -} - -template -T GList::GetItemAtPosition( Position position ) -{ - return ( ( GListNode * )( void * )position )->data; -} - -template -Position GList::GetPositionAtIndex( int index ) -{ - int i; - GListNode *node = head->next; - for( i = 0; i < index; i++ ) - { - node = node->next; - } - return ( Position )( void * )node; -} - -template -T GList::GetItemAtIndex( int index ) -{ - return GetItemAtPosition( GetPositionAtIndex( index ) ); -} - -// GListIterator: Class decleration and definition -template class GListIterator -{ -public: - GListIterator( GList *GList ); - void GotoHead( void ); - void GotoTail( void ); - void Goto( int index ); - void Increment(); - void Decrement(); - T GetCurrentAndIncrement(); - T GetCurrentAndDecrement(); - T IncrementAndGetCurrent(); - T DecrementAndGetCurrent(); - // postfix - T operator++( int ) { return GetCurrentAndIncrement(); } - T operator--( int ) { return GetCurrentAndDecrement(); } - // prefix - T operator++() { return IncrementAndGetCurrent(); } - T operator--() { return DecrementAndGetCurrent(); } - T GetCurrent(); - bool AtEnd( void ); - bool AtBeginning( void ); -protected: - GList *list; - GListNode *currentNode; -}; - -template -GListIterator::GListIterator( GList *list ) -{ - this->list = list; - GotoHead(); -} - -template -void GListIterator::GotoHead() -{ - this->currentNode = list->head->next; -} - -template -void GListIterator::GotoTail() -{ - this->currentNode = list->tail->prev; -} - -template -void GListIterator::Goto( int index ) -{ - currentNode = ( GListNode * )( void * )list->GetPositionAtIndex( index ); -} - -template -void GListIterator::Increment() -{ - currentNode = currentNode->next; -} - -template -void GListIterator::Decrement() -{ - currentNode = currentNode->prev; -} - -template -T GListIterator::GetCurrentAndIncrement() -{ - T retval = currentNode->data; - Increment(); - return retval; -} - -template -T GListIterator::GetCurrentAndDecrement() -{ - T retval = currentNode->data; - Decrement(); - return retval; -} - -template -T GListIterator::IncrementAndGetCurrent() -{ - Increment(); - return GetCurrent(); -} - -template -T GListIterator::DecrementAndGetCurrent() -{ - Decrement(); - return GetCurrent(); -} - -template -T GListIterator::GetCurrent() -{ - return currentNode->data; -} - -template -bool GListIterator::AtEnd( void ) -{ - return currentNode->next == currentNode; -} - -template -bool GListIterator::AtBeginning( void ) -{ - return currentNode->prev == currentNode; -} - -#endif /* __LIST_H__ */ diff --git a/public/loadcmdline.cpp b/public/loadcmdline.cpp deleted file mode 100644 index 6899a867b..000000000 --- a/public/loadcmdline.cpp +++ /dev/null @@ -1,123 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: loads additional command line options from a config file -// -// $NoKeywords: $ -//=============================================================================// - -#include "KeyValues.h" -#include "tier1/strtools.h" -#include "FileSystem_Tools.h" -#include "tier1/utlstring.h" - -// So we know whether or not we own argv's memory -static bool sFoundConfigArgs = false; - -//----------------------------------------------------------------------------- -// Purpose: Parses arguments and adds them to argv and argc -//----------------------------------------------------------------------------- -static void AddArguments( int &argc, char **&argv, const char *str ) -{ - char **args = 0; - char *argList = 0; - int argCt = argc; - - argList = new char[ Q_strlen( str ) + 1 ]; - Q_strcpy( argList, str ); - - // Parse the arguments out of the string - char *token = strtok( argList, " " ); - while( token ) - { - ++argCt; - token = strtok( NULL, " " ); - } - - // Make sure someting was actually found in the file - if( argCt > argc ) - { - sFoundConfigArgs = true; - - // Allocate a new array for argv - args = new char*[ argCt ]; - - // Copy original arguments, up to the last one - int i; - for( i = 0; i < argc - 1; ++i ) - { - args[ i ] = new char[ Q_strlen( argv[ i ] ) + 1 ]; - Q_strcpy( args[ i ], argv[ i ] ); - } - - // copy new arguments - Q_strcpy( argList, str ); - token = strtok( argList, " " ); - for( ; i < argCt - 1; ++i ) - { - args[ i ] = new char[ Q_strlen( token ) + 1 ]; - Q_strcpy( args[ i ], token ); - token = strtok( NULL, " " ); - } - - // Copy the last original argument - args[ i ] = new char[ Q_strlen( argv[ argc - 1 ] ) + 1 ]; - Q_strcpy( args[ i ], argv[ argc - 1 ] ); - - argc = argCt; - argv = args; - } - - delete [] argList; -} - -//----------------------------------------------------------------------------- -// Purpose: Loads additional commandline arguments from a config file for an app. -// Filesystem must be initialized before calling this function. -// keyname: Name of the block containing the key/args pairs (ie map or model name) -// appname: Keyname for the commandline arguments to be loaded - typically the exe name. -//----------------------------------------------------------------------------- -void LoadCmdLineFromFile( int &argc, char **&argv, const char *keyname, const char *appname ) -{ - sFoundConfigArgs = false; - - assert( g_pFileSystem ); - if( !g_pFileSystem ) - return; - - // Load the cfg file, and find the keyname - KeyValues *kv = new KeyValues( "CommandLine" ); - - char filename[512]; - Q_snprintf( filename, sizeof( filename ), "%s/cfg/commandline.cfg", gamedir ); - - if ( kv->LoadFromFile( g_pFileSystem, filename ) ) - { - // Load the commandline arguments for this app - KeyValues *appKey = kv->FindKey( keyname ); - if( appKey ) - { - const char *str = appKey->GetString( appname ); - Msg( "Command Line found: %s\n", str ); - - AddArguments( argc, argv, str ); - } - } - - kv->deleteThis(); -} - -//----------------------------------------------------------------------------- -// Purpose: Cleans up any memory allocated for the new argv. Pass in the app's -// argc and argv - this is safe even if no extra arguments were loaded. -//----------------------------------------------------------------------------- -void DeleteCmdLine( int argc, char **argv ) -{ - if( !sFoundConfigArgs ) - return; - - for( int i = 0; i < argc; ++i ) - { - delete [] argv[i]; - } - delete [] argv; -} diff --git a/public/loadcmdline.h b/public/loadcmdline.h deleted file mode 100644 index 0b62e8134..000000000 --- a/public/loadcmdline.h +++ /dev/null @@ -1,27 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: loads additional command line options from a config file -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef LOADCMDLINE_H -#define LOADCMDLINE_H -#ifdef _WIN32 -#pragma once -#endif - -//----------------------------------------------------------------------------- -// Purpose: Loads additional commandline arguments from a config file for an app. -// keyname: Name of the block containing the key/args pairs (ie map or model name) -// appname: Keyname for the commandline arguments to be loaded - typically the exe name. -//----------------------------------------------------------------------------- -void LoadCmdLineFromFile( int &argc, char **&argv, const char *keyname, const char *appname ); - -//----------------------------------------------------------------------------- -// Purpose: Cleans up any memory allocated for the new argv. Pass in the app's -// argc and argv - this is safe even if no extra arguments were loaded. -//----------------------------------------------------------------------------- -void DeleteCmdLine( int argc, char **argv ); - -#endif // LOADCMDLINE_H diff --git a/public/localflexcontroller.h b/public/localflexcontroller.h deleted file mode 100644 index d9f17e2cf..000000000 --- a/public/localflexcontroller.h +++ /dev/null @@ -1,30 +0,0 @@ -//===== Copyright © 1996-2007, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// - -#ifndef LOCALFLEXCONTROLLER_H -#define LOCALFLEXCONTROLLER_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/platform.h" - -enum LocalFlexController_t -{ - // this isn't really an enum - its just a typed int. gcc will not accept it as a fwd decl, so we'll define one value - DUMMY_FLEX_CONTROLLER=0x7fffffff // make take 32 bits -}; - -inline LocalFlexController_t &operator++( LocalFlexController_t &a ) { return a = LocalFlexController_t( int( a ) + 1 ); } -inline LocalFlexController_t &operator--( LocalFlexController_t &a ) { return a = LocalFlexController_t( int( a ) - 1 ); } -inline LocalFlexController_t operator++( LocalFlexController_t &a, int ) { LocalFlexController_t t = a; a = LocalFlexController_t( int( a ) + 1 ); return t; } -inline LocalFlexController_t operator--( LocalFlexController_t &a, int ) { LocalFlexController_t t = a; a = LocalFlexController_t( int( a ) - 1 ); return t; } - - -#endif // LOCALFLEXCONTROLLER_H diff --git a/public/lumpfiles.cpp b/public/lumpfiles.cpp deleted file mode 100644 index 06227cd1d..000000000 --- a/public/lumpfiles.cpp +++ /dev/null @@ -1,27 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "bspfile.h" -#include "strtools.h" -#include "filesystem.h" -#include "lumpfiles.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Generate a lump file name for a given bsp & index -// Input : *bspfilename - -// *lumpfilename - -// iIndex - -//----------------------------------------------------------------------------- -void GenerateLumpFileName( const char *bspfilename, char *lumpfilename, int iBufferSize, int iIndex ) -{ - char lumppre[MAX_PATH]; - V_StripExtension( bspfilename, lumppre, MAX_PATH ); - Q_snprintf( lumpfilename, iBufferSize, "%s_l_%d.lmp", lumppre, iIndex ); -} - diff --git a/public/lumpfiles.h b/public/lumpfiles.h deleted file mode 100644 index 770df78a8..000000000 --- a/public/lumpfiles.h +++ /dev/null @@ -1,20 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef LUMPFILES_H -#define LUMPFILES_H -#ifdef _WIN32 -#pragma once -#endif - -#define MAX_LUMPFILES 128 - -//----------------------------------------------------------------------------- -// Lump files -//----------------------------------------------------------------------------- -void GenerateLumpFileName( const char *bspfilename, char *lumpfilename, int iBufferSize, int iIndex ); - -#endif // LUMPFILES_H diff --git a/public/map_utils.cpp b/public/map_utils.cpp deleted file mode 100644 index 01336dd3e..000000000 --- a/public/map_utils.cpp +++ /dev/null @@ -1,48 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "mathlib/vector.h" -#include "bspfile.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -void SetupLightNormalFromProps( const QAngle &angles, float angle, float pitch, Vector &output ) -{ - if (angle == ANGLE_UP) - { - output[0] = output[1] = 0; - output[2] = 1; - } - else if (angle == ANGLE_DOWN) - { - output[0] = output[1] = 0; - output[2] = -1; - } - else - { - // if we don't have a specific "angle" use the "angles" YAW - if ( !angle ) - { - angle = angles[YAW]; - } - - output[2] = 0; - output[0] = (float)cos (angle/180*M_PI); - output[1] = (float)sin (angle/180*M_PI); - } - - if ( !pitch ) - { - // if we don't have a specific "pitch" use the "angles" PITCH - pitch = angles[PITCH]; - } - - output[2] = (float)sin(pitch/180*M_PI); - output[0] *= (float)cos(pitch/180*M_PI); - output[1] *= (float)cos(pitch/180*M_PI); -} - diff --git a/public/map_utils.h b/public/map_utils.h deleted file mode 100644 index 75976e4eb..000000000 --- a/public/map_utils.h +++ /dev/null @@ -1,25 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef MAP_UTILS_H -#define MAP_UTILS_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "mathlib/vector.h" - - -// angles comes from the "angles" property -// -// yaw and pitch will override the values in angles if they are nonzero -// yaw comes from the (obsolete) "angle" property -// pitch comes from the "pitch" property -void SetupLightNormalFromProps( const QAngle &angles, float yaw, float pitch, Vector &output ); - - -#endif // MAP_UTILS_H diff --git a/public/materialsystem/IColorCorrection.h b/public/materialsystem/IColorCorrection.h deleted file mode 100644 index af8af3c94..000000000 --- a/public/materialsystem/IColorCorrection.h +++ /dev/null @@ -1,73 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =====// -// -// Purpose: -// -//===========================================================================// - -#ifndef ICOLORCORRECTION_H -#define ICOLORCORRECTION_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/interface.h" -#include "bitmap/imageformat.h" - -typedef unsigned int ColorCorrectionHandle_t; -struct ShaderColorCorrectionInfo_t; - -#define COLORCORRECTION_INTERFACE_VERSION "COLORCORRECTION_VERSION_1" - -abstract_class IColorCorrectionSystem -{ -public: - virtual void Init() = 0; - virtual void Shutdown() = 0; - - virtual ColorCorrectionHandle_t AddLookup( const char *pName ) = 0; - virtual bool RemoveLookup( ColorCorrectionHandle_t handle ) = 0; - - virtual void SetLookupWeight( ColorCorrectionHandle_t handle, float flWeight ) = 0; - virtual float GetLookupWeight( ColorCorrectionHandle_t handle ) = 0; - virtual float GetLookupWeight( int i ) = 0; - - virtual void LockLookup() = 0; - virtual void LockLookup( ColorCorrectionHandle_t handle ) = 0; - - virtual void UnlockLookup() = 0; - virtual void UnlockLookup( ColorCorrectionHandle_t handle ) = 0; - - virtual void SetLookup( RGBX5551_t inColor, color24 outColor ) = 0; - virtual void SetLookup( ColorCorrectionHandle_t handle, RGBX5551_t inColor, color24 outColor ) = 0; - - virtual color24 GetLookup( RGBX5551_t inColor ) = 0; - virtual color24 GetLookup( ColorCorrectionHandle_t handle, RGBX5551_t inColor ) = 0; - - virtual void LoadLookup( const char *pLookupName ) = 0; - virtual void LoadLookup( ColorCorrectionHandle_t handle, const char *pLookupName ) = 0; - - virtual void CopyLookup( const color24 *pSrcColorCorrection ) = 0; - virtual void CopyLookup( ColorCorrectionHandle_t handle, const color24 *pSrcColorCorrection ) = 0; - - virtual void ResetLookup( ColorCorrectionHandle_t handle ) = 0; - virtual void ResetLookup( ) = 0; - - virtual void ReleaseTextures( ) = 0; - virtual void RestoreTextures( ) = 0; - - virtual void ResetLookupWeights( ) = 0; - - virtual int GetNumLookups( ) = 0; - - virtual color24 ConvertToColor24( RGBX5551_t inColor ) = 0; - - virtual void SetResetable( ColorCorrectionHandle_t handle, bool bResetable ) = 0; - - virtual void EnableColorCorrection( bool bEnable ) = 0; - - // FIXME: Move this to a private interface only the material system can see? - virtual void GetCurrentColorCorrection( ShaderColorCorrectionInfo_t* pInfo ) = 0; -}; - -#endif diff --git a/public/materialsystem/IShader.h b/public/materialsystem/IShader.h deleted file mode 100644 index 004adcdd4..000000000 --- a/public/materialsystem/IShader.h +++ /dev/null @@ -1,180 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef ISHADER_H -#define ISHADER_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "materialsystem/imaterialsystem.h" -#include "materialsystem/ishaderapi.h" - - -//----------------------------------------------------------------------------- -// forward declarations -//----------------------------------------------------------------------------- -class IMaterialVar; -class IShaderShadow; -class IShaderDynamicAPI; -class IShaderInit; -class CBasePerMaterialContextData; - -//----------------------------------------------------------------------------- -// Shader flags -//----------------------------------------------------------------------------- -enum ShaderFlags_t -{ - SHADER_NOT_EDITABLE = 0x1 -}; - - -//----------------------------------------------------------------------------- -// Shader parameter flags -//----------------------------------------------------------------------------- -enum ShaderParamFlags_t -{ - SHADER_PARAM_NOT_EDITABLE = 0x1 -}; - - -//----------------------------------------------------------------------------- -// Information about each shader parameter -//----------------------------------------------------------------------------- -struct ShaderParamInfo_t -{ - const char *m_pName; - const char *m_pHelp; - ShaderParamType_t m_Type; - const char *m_pDefaultValue; - int m_nFlags; -}; - - -//----------------------------------------------------------------------------- -// Standard vertex shader constants -//----------------------------------------------------------------------------- -enum -{ - // Standard vertex shader constants - VERTEX_SHADER_MATH_CONSTANTS0 = 0, - VERTEX_SHADER_MATH_CONSTANTS1 = 1, - VERTEX_SHADER_CAMERA_POS = 2, - VERTEX_SHADER_LIGHT_INDEX = 3, - VERTEX_SHADER_MODELVIEWPROJ = 4, - VERTEX_SHADER_VIEWPROJ = 8, - VERTEX_SHADER_UNUSED = 12, - VERTEX_SHADER_FLEXSCALE = 13, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_10 = 14, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_11 = 15, - VERTEX_SHADER_FOG_PARAMS = 16, - VERTEX_SHADER_VIEWMODEL = 17, - VERTEX_SHADER_AMBIENT_LIGHT = 21, - VERTEX_SHADER_LIGHTS = 27, - VERTEX_SHADER_LIGHT0_POSITION = 29, - VERTEX_SHADER_MODULATION_COLOR = 47, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_0 = 48, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_1 = 49, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_2 = 50, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_3 = 51, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_4 = 52, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_5 = 53, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_6 = 54, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_7 = 55, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_8 = 56, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_9 = 57, - VERTEX_SHADER_MODEL = 58, - - VERTEX_SHADER_FLEX_WEIGHTS = 1024, - VERTEX_SHADER_MAX_FLEX_WEIGHT_COUNT = 512, -}; - - -//----------------------------------------------------------------------------- -// Standard vertex shader constants -//----------------------------------------------------------------------------- -enum -{ - // Standard vertex shader constants - VERTEX_SHADER_LIGHT_ENABLE_BOOL_CONST = 0, - VERTEX_SHADER_LIGHT_ENABLE_BOOL_CONST_COUNT = 4, - - VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_0 = 4, - VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_1 = 5, - VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_2 = 6, - VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_3 = 7, - VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_4 = 8, - VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_5 = 9, - VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_6 = 10, - VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_7 = 11, -}; -// The public methods exposed by each shader -//----------------------------------------------------------------------------- -abstract_class IShader -{ -public: - // Returns the shader name - virtual char const* GetName( ) const = 0; - - // returns the shader fallbacks - virtual char const* GetFallbackShader( IMaterialVar** params ) const = 0; - - // Shader parameters - virtual int GetNumParams( ) const = 0; - - // These functions must be implemented by the shader - virtual void InitShaderParams( IMaterialVar** ppParams, const char *pMaterialName ) = 0; - virtual void InitShaderInstance( IMaterialVar** ppParams, IShaderInit *pShaderInit, const char *pMaterialName, const char *pTextureGroupName ) = 0; - virtual void DrawElements( IMaterialVar **params, int nModulationFlags, - IShaderShadow* pShaderShadow, IShaderDynamicAPI* pShaderAPI, VertexCompressionType_t vertexCompression, CBasePerMaterialContextData **pContextDataPtr ) = 0; - - virtual char const* GetParamName( int paramIndex ) const = 0; - virtual char const* GetParamHelp( int paramIndex ) const = 0; - virtual ShaderParamType_t GetParamType( int paramIndex ) const = 0; - virtual char const* GetParamDefault( int paramIndex ) const = 0; - - // FIXME: Figure out a better way to do this? - virtual int ComputeModulationFlags( IMaterialVar** params, IShaderDynamicAPI* pShaderAPI ) = 0; - virtual bool NeedsPowerOfTwoFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame = true ) const = 0; - virtual bool NeedsFullFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame ) const = 0; - virtual bool IsTranslucent( IMaterialVar **params ) const = 0; - - virtual int GetParamFlags( int paramIndex ) const = 0; - - virtual int GetFlags() const = 0; - - // FIXME: Remove GetParamName, etc. above -// virtual const ShaderParamInfo_t& GetParamInfo( int paramIndex ) const = 0; -}; - - -//----------------------------------------------------------------------------- -// Shader dictionaries defined in DLLs -//----------------------------------------------------------------------------- -enum PrecompiledShaderType_t -{ - PRECOMPILED_VERTEX_SHADER = 0, - PRECOMPILED_PIXEL_SHADER, - - PRECOMPILED_SHADER_TYPE_COUNT, -}; - - -//----------------------------------------------------------------------------- -// Flags field of PrecompiledShader_t -//----------------------------------------------------------------------------- -enum -{ - // runtime flags - SHADER_DYNAMIC_COMPILE_IS_HLSL = 0x1, - SHADER_FAILED_LOAD = 0x2, -}; - -#endif // ISHADER_H diff --git a/public/materialsystem/MaterialSystemUtil.cpp b/public/materialsystem/MaterialSystemUtil.cpp deleted file mode 100644 index ca9734e51..000000000 --- a/public/materialsystem/MaterialSystemUtil.cpp +++ /dev/null @@ -1,247 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $Workfile: $ -// $NoKeywords: $ -//===========================================================================// - -#include "materialsystem/MaterialSystemUtil.h" -#include "materialsystem/imaterial.h" -#include "materialsystem/itexture.h" -#include "materialsystem/imaterialsystem.h" -#include "tier1/KeyValues.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Little utility class to deal with material references -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// constructor, destructor -//----------------------------------------------------------------------------- -CMaterialReference::CMaterialReference( char const* pMaterialName, const char *pTextureGroupName, bool bComplain ) : m_pMaterial( 0 ) -{ - if ( pMaterialName ) - { - Assert( pTextureGroupName ); - Init( pMaterialName, pTextureGroupName, bComplain ); - } -} - -CMaterialReference::~CMaterialReference() -{ - Shutdown(); -} - -//----------------------------------------------------------------------------- -// Attach to a material -//----------------------------------------------------------------------------- -void CMaterialReference::Init( char const* pMaterialName, const char *pTextureGroupName, bool bComplain ) -{ - IMaterial *pMaterial = materials->FindMaterial( pMaterialName, pTextureGroupName, bComplain); - Assert( pMaterial ); - Init( pMaterial ); -} - -void CMaterialReference::Init( const char *pMaterialName, KeyValues *pVMTKeyValues ) -{ - // CreateMaterial has a refcount of 1 - Shutdown(); - m_pMaterial = materials->CreateMaterial( pMaterialName, pVMTKeyValues ); -} - -void CMaterialReference::Init( const char *pMaterialName, const char *pTextureGroupName, KeyValues *pVMTKeyValues ) -{ - IMaterial *pMaterial = materials->FindProceduralMaterial( pMaterialName, pTextureGroupName, pVMTKeyValues ); - Assert( pMaterial ); - Init( pMaterial ); -} - -void CMaterialReference::Init( IMaterial* pMaterial ) -{ - if ( m_pMaterial != pMaterial ) - { - Shutdown(); - m_pMaterial = pMaterial; - if ( m_pMaterial ) - { - m_pMaterial->IncrementReferenceCount(); - } - } -} - -void CMaterialReference::Init( CMaterialReference& ref ) -{ - if ( m_pMaterial != ref.m_pMaterial ) - { - Shutdown(); - m_pMaterial = ref.m_pMaterial; - if (m_pMaterial) - { - m_pMaterial->IncrementReferenceCount(); - } - } -} - -//----------------------------------------------------------------------------- -// Detach from a material -//----------------------------------------------------------------------------- -void CMaterialReference::Shutdown( ) -{ - if ( m_pMaterial && materials ) - { - m_pMaterial->DecrementReferenceCount(); - m_pMaterial = NULL; - } -} - - -//----------------------------------------------------------------------------- -// Little utility class to deal with texture references -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// constructor, destructor -//----------------------------------------------------------------------------- -CTextureReference::CTextureReference( ) : m_pTexture(NULL) -{ -} - -CTextureReference::CTextureReference( const CTextureReference &ref ) -{ - m_pTexture = ref.m_pTexture; - if ( m_pTexture ) - { - m_pTexture->IncrementReferenceCount(); - } -} - -void CTextureReference::operator=( CTextureReference &ref ) -{ - m_pTexture = ref.m_pTexture; - if ( m_pTexture ) - { - m_pTexture->IncrementReferenceCount(); - } -} - -CTextureReference::~CTextureReference( ) -{ - Shutdown(); -} - -//----------------------------------------------------------------------------- -// Attach to a texture -//----------------------------------------------------------------------------- -void CTextureReference::Init( char const* pTextureName, const char *pTextureGroupName, bool bComplain ) -{ - Shutdown(); - m_pTexture = materials->FindTexture( pTextureName, pTextureGroupName, bComplain ); - if ( m_pTexture ) - { - m_pTexture->IncrementReferenceCount(); - } -} - -void CTextureReference::Init( ITexture* pTexture ) -{ - Shutdown(); - - m_pTexture = pTexture; - if (m_pTexture) - { - m_pTexture->IncrementReferenceCount(); - } -} - -void CTextureReference::InitProceduralTexture( const char *pTextureName, const char *pTextureGroupName, int w, int h, ImageFormat fmt, int nFlags ) -{ - Shutdown(); - - m_pTexture = materials->CreateProceduralTexture( pTextureName, pTextureGroupName, w, h, fmt, nFlags ); - - // NOTE: The texture reference is already incremented internally above! - /* - if ( m_pTexture ) - { - m_pTexture->IncrementReferenceCount(); - } - */ -} - -void CTextureReference::InitRenderTarget( int w, int h, RenderTargetSizeMode_t sizeMode, ImageFormat fmt, MaterialRenderTargetDepth_t depth, bool bHDR, char *pStrOptionalName /* = NULL */ ) -{ - Shutdown(); - - int textureFlags = TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT; - if ( depth == MATERIAL_RT_DEPTH_ONLY ) - textureFlags |= TEXTUREFLAGS_POINTSAMPLE; - - int renderTargetFlags = bHDR ? CREATERENDERTARGETFLAGS_HDR : 0; - - // NOTE: Refcount returned by CreateRenderTargetTexture is 1 - m_pTexture = materials->CreateNamedRenderTargetTextureEx( pStrOptionalName, w, h, sizeMode, fmt, - depth, textureFlags, renderTargetFlags ); - - Assert( m_pTexture ); -} - -//----------------------------------------------------------------------------- -// Detach from a texture -//----------------------------------------------------------------------------- -void CTextureReference::Shutdown( bool bDeleteIfUnReferenced ) -{ - if ( m_pTexture && materials ) - { - m_pTexture->DecrementReferenceCount(); - if ( bDeleteIfUnReferenced ) - { - m_pTexture->DeleteIfUnreferenced(); - } - m_pTexture = NULL; - } -} - -//----------------------------------------------------------------------------- -// Builds ONLY the system ram render target. Used when caller is explicitly managing. -// The paired EDRAM surface can be built in an alternate format. -//----------------------------------------------------------------------------- -#if defined( _X360 ) -void CTextureReference::InitRenderTargetTexture( int w, int h, RenderTargetSizeMode_t sizeMode, ImageFormat fmt, MaterialRenderTargetDepth_t depth, bool bHDR, char *pStrOptionalName ) -{ - // other variants not implemented yet - Assert( depth == MATERIAL_RT_DEPTH_NONE || depth == MATERIAL_RT_DEPTH_SHARED ); - Assert( !bHDR ); - - int renderTargetFlags = CREATERENDERTARGETFLAGS_NOEDRAM; - - m_pTexture = materials->CreateNamedRenderTargetTextureEx( - pStrOptionalName, - w, - h, - sizeMode, - fmt, - depth, - TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT, - renderTargetFlags ); - Assert( m_pTexture ); -} -#endif - -//----------------------------------------------------------------------------- -// Builds ONLY the EDRAM render target surface. Used when caller is explicitly managing. -// The paired system memory texture can be built in an alternate format. -//----------------------------------------------------------------------------- -#if defined( _X360 ) -void CTextureReference::InitRenderTargetSurface( int width, int height, ImageFormat fmt, bool bSameAsTexture ) -{ - // texture has to be created first - Assert( m_pTexture && m_pTexture->IsRenderTarget() ); - - m_pTexture->CreateRenderTargetSurface( width, height, fmt, bSameAsTexture ); -} -#endif - diff --git a/public/materialsystem/MaterialSystemUtil.h b/public/materialsystem/MaterialSystemUtil.h deleted file mode 100644 index ffa076c15..000000000 --- a/public/materialsystem/MaterialSystemUtil.h +++ /dev/null @@ -1,98 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//===========================================================================// -#ifndef MATERIALSYSTEMUTIL_H -#define MATERIALSYSTEMUTIL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "bitmap/imageformat.h" //ImageFormat enum definition -#include "materialsystem/imaterialsystem.h" // RenderTargetSizeMode_t and MaterialRenderTargetDepth_t definition - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class IMaterial; -class ITexture; -class KeyValues; - -class KeyValues; - - -//----------------------------------------------------------------------------- -// Little utility class to deal with material references -//----------------------------------------------------------------------------- -class CMaterialReference -{ -public: - // constructor, destructor - CMaterialReference( char const* pMaterialName = 0, const char *pTextureGroupName = 0, bool bComplain = true ); - ~CMaterialReference(); - - // Attach to a material - void Init( const char* pMaterialName, const char *pTextureGroupName, bool bComplain = true ); - void Init( const char *pMaterialName, KeyValues *pVMTKeyValues ); - void Init( IMaterial* pMaterial ); - void Init( CMaterialReference& ref ); - void Init( const char *pMaterialName, const char *pTextureGroupName, KeyValues *pVMTKeyValues ); - - // Detach from a material - void Shutdown(); - bool IsValid() { return m_pMaterial != 0; } - - // Automatic casts to IMaterial - operator IMaterial*() { return m_pMaterial; } - operator IMaterial const*() const { return m_pMaterial; } - IMaterial* operator->() { return m_pMaterial; } - -private: - IMaterial* m_pMaterial; -}; - -//----------------------------------------------------------------------------- -// Little utility class to deal with texture references -//----------------------------------------------------------------------------- -class CTextureReference -{ -public: - // constructor, destructor - CTextureReference( ); - CTextureReference( const CTextureReference &ref ); - ~CTextureReference(); - - // Attach to a texture - void Init( char const* pTexture, const char *pTextureGroupName, bool bComplain = true ); - void InitProceduralTexture( const char *pTextureName, const char *pTextureGroupName, int w, int h, ImageFormat fmt, int nFlags ); - void InitRenderTarget( int w, int h, RenderTargetSizeMode_t sizeMode, ImageFormat fmt, MaterialRenderTargetDepth_t depth, bool bHDR, char *pStrOptionalName = NULL ); -#if defined( _X360 ) - // used when RT coupling is disparate (texture is DDR based, surface is EDRAM based) - void InitRenderTargetTexture( int width, int height, RenderTargetSizeMode_t sizeMode, ImageFormat fmt, MaterialRenderTargetDepth_t depth, bool bHDR, char *pStrOptionalName = NULL ); - void InitRenderTargetSurface( int width, int height, ImageFormat fmt, bool bSameAsTexture ); -#endif - void Init( ITexture* pTexture ); - - // Detach from a texture - void Shutdown( bool bDeleteIfUnReferenced = false ); - bool IsValid() { return m_pTexture != 0; } - - // Automatic casts to ITexture - operator ITexture*() { return m_pTexture; } - operator ITexture const*() const { return m_pTexture; } - ITexture* operator->() { return m_pTexture; } - - // Assignment operator - void operator=( CTextureReference &ref ); - -private: - ITexture* m_pTexture; -}; - - -#endif // !MATERIALSYSTEMUTIL_H diff --git a/public/materialsystem/deformations.h b/public/materialsystem/deformations.h deleted file mode 100644 index 09c4474f0..000000000 --- a/public/materialsystem/deformations.h +++ /dev/null @@ -1,58 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =====// -// -// Purpose: -// -//===========================================================================// - -#ifndef DEFORMATIONS_H -#define DEFORMATIONS_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/platform.h" - -// nonlinear transformations which may be applied to model vertices when rendering. must be powers of two -enum DeformationType_t -{ - DEFORMATION_CLAMP_TO_BOX_IN_WORLDSPACE = 1, // minxyz.minsoftness / maxxyz.maxsoftness -}; - - -struct DeformationBase_t // base class. don't use this -{ - DeformationType_t m_eType; -}; - - -struct BoxDeformation_t : DeformationBase_t -{ - // don't change the layout without changing code in shaderapidx8!!!! - Vector m_SourceMins; // cube to clamp within - float m_flPad0; - Vector m_SourceMaxes; - float m_flPad1; - - Vector m_ClampMins; - float m_flPad2; - Vector m_ClampMaxes; - float m_flPad3; - - FORCEINLINE BoxDeformation_t( void ) - { - m_eType = DEFORMATION_CLAMP_TO_BOX_IN_WORLDSPACE; - // invalid cube - m_SourceMins.Init( 0,0,0 ); - m_SourceMaxes.Init( -1, -1, -1 ); - - // no clamp - m_ClampMins.Init( -FLT_MAX, -FLT_MAX, -FLT_MAX ); - m_ClampMaxes.Init( FLT_MAX, FLT_MAX, FLT_MAX ); - } - -}; - - - -#endif diff --git a/public/materialsystem/hardwareverts.h b/public/materialsystem/hardwareverts.h deleted file mode 100644 index aeb60d7d1..000000000 --- a/public/materialsystem/hardwareverts.h +++ /dev/null @@ -1,86 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Hardware Verts -// -// Contains data purposely formatted for a dma copy into a D3D Vertex Buffer. -// The file is divided into two partitions, the foremost contains the static -// portion (header), the latter contains the streamable compliant portion. -// The streamable component starts and ends on a sector (512) aligned boundary. -// The header identifies the vertex format of the data and the atomic sizes of each component. -// The hierarchial mesh is flattened for dma but the vertex counts are available -// per mesh to transfer each mesh individually. -//=============================================================================// - -#ifndef HARDWAREVERTS_H -#define HARDWAREVERTS_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "datamap.h" - -// valve hardware vertexes -#define VHV_VERSION 2 - -namespace HardwareVerts -{ - -#pragma pack(1) - -struct MeshHeader_t -{ - DECLARE_BYTESWAP_DATADESC(); - - // this mesh is part of this lod - unsigned int m_nLod; - - // this mesh has this many vertexes - unsigned int m_nVertexes; - - // starting at this offset - unsigned int m_nOffset; - - unsigned int m_nUnused[4]; -}; - -struct FileHeader_t -{ - DECLARE_BYTESWAP_DATADESC(); - - // file version as defined by VHV_VERSION - int m_nVersion; - - // must match checkSum in the .mdl header - unsigned int m_nChecksum; - - // a vertex consists of these components - VertexFormatFlags_t m_nVertexFlags; - - // the byte size of a single vertex - // this won't be adequate, need some concept of byte format i.e. rgbexp32 vs rgba8888 - unsigned int m_nVertexSize; - - // total number of vertexes - unsigned int m_nVertexes; - - int m_nMeshes; - inline MeshHeader_t *pMesh( int nMesh ) const - { - return (MeshHeader_t *)(((byte *)this) + sizeof(FileHeader_t)) + nMesh; - }; - - inline void *pVertexBase( int nMesh ) const - { - return (void *)((byte *)this + pMesh( nMesh )->m_nOffset); - }; - - unsigned int m_nUnused[4]; -}; - -#pragma pack() - -}; // end namespace - -#endif // HARDWAREVERTS_H - diff --git a/public/materialsystem/idebugtextureinfo.h b/public/materialsystem/idebugtextureinfo.h deleted file mode 100644 index cf3e3333a..000000000 --- a/public/materialsystem/idebugtextureinfo.h +++ /dev/null @@ -1,69 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef IDEBUGTEXTUREINFO_H -#define IDEBUGTEXTUREINFO_H -#ifdef _WIN32 -#pragma once -#endif - - -class KeyValues; - - -// This interface is actually exported by the shader API DLL. -#define DEBUG_TEXTURE_INFO_VERSION "DebugTextureInfo001" - - -abstract_class IDebugTextureInfo -{ -public: - - // Use this to turn on the mode where it builds the debug texture list. - // At the end of the next frame, GetDebugTextureList() will return a valid list of the textures. - virtual void EnableDebugTextureList( bool bEnable ) = 0; - - // If this is on, then it will return all textures that exist, not just the ones that were bound in the last frame. - // It is required to enable debug texture list to get this. - virtual void EnableGetAllTextures( bool bEnable ) = 0; - - // Use this to get the results of the texture list. - // Do NOT release the KeyValues after using them. - // There will be a bunch of subkeys, each with these values: - // Name - the texture's filename - // Binds - how many times the texture was bound - // Format - ImageFormat of the texture - // Width - Width of the texture - // Height - Height of the texture - // It is required to enable debug texture list to get this. - virtual KeyValues* GetDebugTextureList() = 0; - - // Texture memory usage - enum TextureMemoryType - { - MEMORY_RESERVED_MIN = 0, - MEMORY_BOUND_LAST_FRAME, // sums up textures bound last frame - MEMORY_TOTAL_LOADED, // total texture memory used - MEMORY_ESTIMATE_PICMIP_1, // estimate of running with "picmip 1" - MEMORY_ESTIMATE_PICMIP_2, // estimate of running with "picmip 2" - MEMORY_RESERVED_MAX - }; - - // This returns how much memory was used. - virtual int GetTextureMemoryUsed( TextureMemoryType eTextureMemory ) = 0; - - // Use this to determine if texture debug info was computed within last numFramesAllowed frames. - virtual bool IsDebugTextureListFresh( int numFramesAllowed = 1 ) = 0; - - // Enable debug texture rendering when texture binds should not count towards textures - // used during a frame. Returns the old state of debug texture rendering flag to use - // it for restoring the mode. - virtual bool SetDebugTextureRendering( bool bEnable ) = 0; - -}; - - -#endif // IDEBUGTEXTUREINFO_H diff --git a/public/materialsystem/imaterial.h b/public/materialsystem/imaterial.h deleted file mode 100644 index 497ec0ff9..000000000 --- a/public/materialsystem/imaterial.h +++ /dev/null @@ -1,612 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// - -#ifndef IMATERIAL_H -#define IMATERIAL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "bitmap/imageformat.h" -#include "materialsystem/imaterialsystem.h" - -//----------------------------------------------------------------------------- -// forward declaraions -//----------------------------------------------------------------------------- - -class IMaterialVar; -class ITexture; -class IMaterialProxy; -class Vector; - -//----------------------------------------------------------------------------- -// Flags for GetVertexFormat -//----------------------------------------------------------------------------- -enum VertexFormatFlags_t -{ - // Indicates an uninitialized VertexFormat_t value - VERTEX_FORMAT_INVALID = 0xFFFFFFFFFFFFFFFFLL, - - VERTEX_POSITION = 0x0001, - VERTEX_NORMAL = 0x0002, - VERTEX_COLOR = 0x0004, - VERTEX_SPECULAR = 0x0008, - - VERTEX_TANGENT_S = 0x0010, - VERTEX_TANGENT_T = 0x0020, - VERTEX_TANGENT_SPACE= VERTEX_TANGENT_S | VERTEX_TANGENT_T, - - // Indicates we're using wrinkle - VERTEX_WRINKLE = 0x0040, - - // Indicates we're using bone indices - VERTEX_BONE_INDEX = 0x0080, - - // Indicates this is a vertex shader - VERTEX_FORMAT_VERTEX_SHADER = 0x0100, - - // Indicates this format shouldn't be bloated to cache align it - // (only used for VertexUsage) - VERTEX_FORMAT_USE_EXACT_FORMAT = 0x0200, - - // Indicates that compressed vertex elements are to be used (see also VertexCompressionType_t) - VERTEX_FORMAT_COMPRESSED = 0x400, - - // Update this if you add or remove bits... - VERTEX_LAST_BIT = 10, - - VERTEX_BONE_WEIGHT_BIT = VERTEX_LAST_BIT + 1, - USER_DATA_SIZE_BIT = VERTEX_LAST_BIT + 4, - TEX_COORD_SIZE_BIT = VERTEX_LAST_BIT + 7, - - VERTEX_BONE_WEIGHT_MASK = ( 0x7 << VERTEX_BONE_WEIGHT_BIT ), - USER_DATA_SIZE_MASK = ( 0x7 << USER_DATA_SIZE_BIT ), - - VERTEX_FORMAT_FIELD_MASK = 0x0FF, - - // If everything is off, it's an unknown vertex format - VERTEX_FORMAT_UNKNOWN = 0, -}; - -//----------------------------------------------------------------------------- -// Macros for construction.. -//----------------------------------------------------------------------------- -#define VERTEX_BONEWEIGHT( _n ) ((_n) << VERTEX_BONE_WEIGHT_BIT) -#define VERTEX_USERDATA_SIZE( _n ) ((_n) << USER_DATA_SIZE_BIT) -#define VERTEX_TEXCOORD_MASK( _coord ) (( 0x7ULL ) << ( TEX_COORD_SIZE_BIT + 3 * (_coord) )) - -inline VertexFormat_t VERTEX_TEXCOORD_SIZE( int nIndex, int nNumCoords ) -{ - uint64 n64=nNumCoords; - uint64 nShift=TEX_COORD_SIZE_BIT + (3*nIndex); - return n64 << nShift; -} - - - -//----------------------------------------------------------------------------- -// Gets at various vertex format info... -//----------------------------------------------------------------------------- -inline int VertexFlags( VertexFormat_t vertexFormat ) -{ - return static_cast ( vertexFormat & ( (1 << (VERTEX_LAST_BIT+1)) - 1 ) ); -} - -inline int NumBoneWeights( VertexFormat_t vertexFormat ) -{ - return static_cast ( (vertexFormat >> VERTEX_BONE_WEIGHT_BIT) & 0x7 ); -} - -inline int UserDataSize( VertexFormat_t vertexFormat ) -{ - return static_cast ( (vertexFormat >> USER_DATA_SIZE_BIT) & 0x7 ); -} - -inline int TexCoordSize( int nTexCoordIndex, VertexFormat_t vertexFormat ) -{ - return static_cast ( (vertexFormat >> (TEX_COORD_SIZE_BIT + 3*nTexCoordIndex) ) & 0x7 ); -} - -inline bool UsesVertexShader( VertexFormat_t vertexFormat ) -{ - return (vertexFormat & VERTEX_FORMAT_VERTEX_SHADER) != 0; -} - -inline VertexCompressionType_t CompressionType( VertexFormat_t vertexFormat ) -{ - // This is trivial now, but we may add multiple flavours of compressed vertex later on - if ( vertexFormat & VERTEX_FORMAT_COMPRESSED ) - return VERTEX_COMPRESSION_ON; - else - return VERTEX_COMPRESSION_NONE; -} - - -//----------------------------------------------------------------------------- -// VertexElement_t (enumerates all usable vertex elements) -//----------------------------------------------------------------------------- -// FIXME: unify this with VertexFormat_t (i.e. construct the lower bits of VertexFormat_t with "1 << (VertexElement_t)element") -enum VertexElement_t -{ - VERTEX_ELEMENT_NONE = -1, - - // Deliberately explicitly numbered so it's a pain in the ass to change, so you read this: - // #!#!#NOTE#!#!# update GetVertexElementSize, VertexElementToDeclType and - // CVBAllocTracker (elementTable) when you update this! - VERTEX_ELEMENT_POSITION = 0, - VERTEX_ELEMENT_NORMAL = 1, - VERTEX_ELEMENT_COLOR = 2, - VERTEX_ELEMENT_SPECULAR = 3, - VERTEX_ELEMENT_TANGENT_S = 4, - VERTEX_ELEMENT_TANGENT_T = 5, - VERTEX_ELEMENT_WRINKLE = 6, - VERTEX_ELEMENT_BONEINDEX = 7, - VERTEX_ELEMENT_BONEWEIGHTS1 = 8, - VERTEX_ELEMENT_BONEWEIGHTS2 = 9, - VERTEX_ELEMENT_BONEWEIGHTS3 = 10, - VERTEX_ELEMENT_BONEWEIGHTS4 = 11, - VERTEX_ELEMENT_USERDATA1 = 12, - VERTEX_ELEMENT_USERDATA2 = 13, - VERTEX_ELEMENT_USERDATA3 = 14, - VERTEX_ELEMENT_USERDATA4 = 15, - VERTEX_ELEMENT_TEXCOORD1D_0 = 16, - VERTEX_ELEMENT_TEXCOORD1D_1 = 17, - VERTEX_ELEMENT_TEXCOORD1D_2 = 18, - VERTEX_ELEMENT_TEXCOORD1D_3 = 19, - VERTEX_ELEMENT_TEXCOORD1D_4 = 20, - VERTEX_ELEMENT_TEXCOORD1D_5 = 21, - VERTEX_ELEMENT_TEXCOORD1D_6 = 22, - VERTEX_ELEMENT_TEXCOORD1D_7 = 23, - VERTEX_ELEMENT_TEXCOORD2D_0 = 24, - VERTEX_ELEMENT_TEXCOORD2D_1 = 25, - VERTEX_ELEMENT_TEXCOORD2D_2 = 26, - VERTEX_ELEMENT_TEXCOORD2D_3 = 27, - VERTEX_ELEMENT_TEXCOORD2D_4 = 28, - VERTEX_ELEMENT_TEXCOORD2D_5 = 29, - VERTEX_ELEMENT_TEXCOORD2D_6 = 30, - VERTEX_ELEMENT_TEXCOORD2D_7 = 31, - VERTEX_ELEMENT_TEXCOORD3D_0 = 32, - VERTEX_ELEMENT_TEXCOORD3D_1 = 33, - VERTEX_ELEMENT_TEXCOORD3D_2 = 34, - VERTEX_ELEMENT_TEXCOORD3D_3 = 35, - VERTEX_ELEMENT_TEXCOORD3D_4 = 36, - VERTEX_ELEMENT_TEXCOORD3D_5 = 37, - VERTEX_ELEMENT_TEXCOORD3D_6 = 38, - VERTEX_ELEMENT_TEXCOORD3D_7 = 39, - VERTEX_ELEMENT_TEXCOORD4D_0 = 40, - VERTEX_ELEMENT_TEXCOORD4D_1 = 41, - VERTEX_ELEMENT_TEXCOORD4D_2 = 42, - VERTEX_ELEMENT_TEXCOORD4D_3 = 43, - VERTEX_ELEMENT_TEXCOORD4D_4 = 44, - VERTEX_ELEMENT_TEXCOORD4D_5 = 45, - VERTEX_ELEMENT_TEXCOORD4D_6 = 46, - VERTEX_ELEMENT_TEXCOORD4D_7 = 47, - - VERTEX_ELEMENT_NUMELEMENTS = 48 -}; - -inline void Detect_VertexElement_t_Changes( VertexElement_t element ) // GREPs for VertexElement_t will hit this -{ - // Make it harder for someone to change VertexElement_t without noticing that dependent code - // (GetVertexElementSize, VertexElementToDeclType, CVBAllocTracker) needs updating - Assert( VERTEX_ELEMENT_NUMELEMENTS == 48 ); - switch ( element ) - { - case VERTEX_ELEMENT_POSITION: Assert( VERTEX_ELEMENT_POSITION == 0 ); break; - case VERTEX_ELEMENT_NORMAL: Assert( VERTEX_ELEMENT_NORMAL == 1 ); break; - case VERTEX_ELEMENT_COLOR: Assert( VERTEX_ELEMENT_COLOR == 2 ); break; - case VERTEX_ELEMENT_SPECULAR: Assert( VERTEX_ELEMENT_SPECULAR == 3 ); break; - case VERTEX_ELEMENT_TANGENT_S: Assert( VERTEX_ELEMENT_TANGENT_S == 4 ); break; - case VERTEX_ELEMENT_TANGENT_T: Assert( VERTEX_ELEMENT_TANGENT_T == 5 ); break; - case VERTEX_ELEMENT_WRINKLE: Assert( VERTEX_ELEMENT_WRINKLE == 6 ); break; - case VERTEX_ELEMENT_BONEINDEX: Assert( VERTEX_ELEMENT_BONEINDEX == 7 ); break; - case VERTEX_ELEMENT_BONEWEIGHTS1: Assert( VERTEX_ELEMENT_BONEWEIGHTS1 == 8 ); break; - case VERTEX_ELEMENT_BONEWEIGHTS2: Assert( VERTEX_ELEMENT_BONEWEIGHTS2 == 9 ); break; - case VERTEX_ELEMENT_BONEWEIGHTS3: Assert( VERTEX_ELEMENT_BONEWEIGHTS3 == 10 ); break; - case VERTEX_ELEMENT_BONEWEIGHTS4: Assert( VERTEX_ELEMENT_BONEWEIGHTS4 == 11 ); break; - case VERTEX_ELEMENT_USERDATA1: Assert( VERTEX_ELEMENT_USERDATA1 == 12 ); break; - case VERTEX_ELEMENT_USERDATA2: Assert( VERTEX_ELEMENT_USERDATA2 == 13 ); break; - case VERTEX_ELEMENT_USERDATA3: Assert( VERTEX_ELEMENT_USERDATA3 == 14 ); break; - case VERTEX_ELEMENT_USERDATA4: Assert( VERTEX_ELEMENT_USERDATA4 == 15 ); break; - case VERTEX_ELEMENT_TEXCOORD1D_0: Assert( VERTEX_ELEMENT_TEXCOORD1D_0 == 16 ); break; - case VERTEX_ELEMENT_TEXCOORD1D_1: Assert( VERTEX_ELEMENT_TEXCOORD1D_1 == 17 ); break; - case VERTEX_ELEMENT_TEXCOORD1D_2: Assert( VERTEX_ELEMENT_TEXCOORD1D_2 == 18 ); break; - case VERTEX_ELEMENT_TEXCOORD1D_3: Assert( VERTEX_ELEMENT_TEXCOORD1D_3 == 19 ); break; - case VERTEX_ELEMENT_TEXCOORD1D_4: Assert( VERTEX_ELEMENT_TEXCOORD1D_4 == 20 ); break; - case VERTEX_ELEMENT_TEXCOORD1D_5: Assert( VERTEX_ELEMENT_TEXCOORD1D_5 == 21 ); break; - case VERTEX_ELEMENT_TEXCOORD1D_6: Assert( VERTEX_ELEMENT_TEXCOORD1D_6 == 22 ); break; - case VERTEX_ELEMENT_TEXCOORD1D_7: Assert( VERTEX_ELEMENT_TEXCOORD1D_7 == 23 ); break; - case VERTEX_ELEMENT_TEXCOORD2D_0: Assert( VERTEX_ELEMENT_TEXCOORD2D_0 == 24 ); break; - case VERTEX_ELEMENT_TEXCOORD2D_1: Assert( VERTEX_ELEMENT_TEXCOORD2D_1 == 25 ); break; - case VERTEX_ELEMENT_TEXCOORD2D_2: Assert( VERTEX_ELEMENT_TEXCOORD2D_2 == 26 ); break; - case VERTEX_ELEMENT_TEXCOORD2D_3: Assert( VERTEX_ELEMENT_TEXCOORD2D_3 == 27 ); break; - case VERTEX_ELEMENT_TEXCOORD2D_4: Assert( VERTEX_ELEMENT_TEXCOORD2D_4 == 28 ); break; - case VERTEX_ELEMENT_TEXCOORD2D_5: Assert( VERTEX_ELEMENT_TEXCOORD2D_5 == 29 ); break; - case VERTEX_ELEMENT_TEXCOORD2D_6: Assert( VERTEX_ELEMENT_TEXCOORD2D_6 == 30 ); break; - case VERTEX_ELEMENT_TEXCOORD2D_7: Assert( VERTEX_ELEMENT_TEXCOORD2D_7 == 31 ); break; - case VERTEX_ELEMENT_TEXCOORD3D_0: Assert( VERTEX_ELEMENT_TEXCOORD3D_0 == 32 ); break; - case VERTEX_ELEMENT_TEXCOORD3D_1: Assert( VERTEX_ELEMENT_TEXCOORD3D_1 == 33 ); break; - case VERTEX_ELEMENT_TEXCOORD3D_2: Assert( VERTEX_ELEMENT_TEXCOORD3D_2 == 34 ); break; - case VERTEX_ELEMENT_TEXCOORD3D_3: Assert( VERTEX_ELEMENT_TEXCOORD3D_3 == 35 ); break; - case VERTEX_ELEMENT_TEXCOORD3D_4: Assert( VERTEX_ELEMENT_TEXCOORD3D_4 == 36 ); break; - case VERTEX_ELEMENT_TEXCOORD3D_5: Assert( VERTEX_ELEMENT_TEXCOORD3D_5 == 37 ); break; - case VERTEX_ELEMENT_TEXCOORD3D_6: Assert( VERTEX_ELEMENT_TEXCOORD3D_6 == 38 ); break; - case VERTEX_ELEMENT_TEXCOORD3D_7: Assert( VERTEX_ELEMENT_TEXCOORD3D_7 == 39 ); break; - case VERTEX_ELEMENT_TEXCOORD4D_0: Assert( VERTEX_ELEMENT_TEXCOORD4D_0 == 40 ); break; - case VERTEX_ELEMENT_TEXCOORD4D_1: Assert( VERTEX_ELEMENT_TEXCOORD4D_1 == 41 ); break; - case VERTEX_ELEMENT_TEXCOORD4D_2: Assert( VERTEX_ELEMENT_TEXCOORD4D_2 == 42 ); break; - case VERTEX_ELEMENT_TEXCOORD4D_3: Assert( VERTEX_ELEMENT_TEXCOORD4D_3 == 43 ); break; - case VERTEX_ELEMENT_TEXCOORD4D_4: Assert( VERTEX_ELEMENT_TEXCOORD4D_4 == 44 ); break; - case VERTEX_ELEMENT_TEXCOORD4D_5: Assert( VERTEX_ELEMENT_TEXCOORD4D_5 == 45 ); break; - case VERTEX_ELEMENT_TEXCOORD4D_6: Assert( VERTEX_ELEMENT_TEXCOORD4D_6 == 46 ); break; - case VERTEX_ELEMENT_TEXCOORD4D_7: Assert( VERTEX_ELEMENT_TEXCOORD4D_7 == 47 ); break; - default: - Assert( 0 ); // Invalid input or VertexElement_t has definitely changed - break; - } -} - -// We're testing 2 normal compression methods -// One compressed normals+tangents into a SHORT2 each (8 bytes total) -// The other compresses them together, into a single UBYTE4 (4 bytes total) -// FIXME: pick one or the other, compare lighting quality in important cases -#define COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 0 -#define COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 1 -//#define COMPRESSED_NORMALS_TYPE COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 -#define COMPRESSED_NORMALS_TYPE COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 - -inline int GetVertexElementSize( VertexElement_t element, VertexCompressionType_t compressionType ) -{ - Detect_VertexElement_t_Changes( element ); - - if ( compressionType == VERTEX_COMPRESSION_ON ) - { - // Compressed-vertex element sizes - switch ( element ) - { -#if ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 ) - case VERTEX_ELEMENT_NORMAL: - return ( 2 * sizeof( short ) ); - case VERTEX_ELEMENT_USERDATA4: - return ( 2 * sizeof( short ) ); -#else //( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 ) - // Normals and tangents (userdata4) are combined into a single UBYTE4 vertex element - case VERTEX_ELEMENT_NORMAL: - return ( 4 * sizeof( unsigned char ) ); - case VERTEX_ELEMENT_USERDATA4: - return ( 0 ); -#endif - // Compressed bone weights use a SHORT2 vertex element: - case VERTEX_ELEMENT_BONEWEIGHTS1: - case VERTEX_ELEMENT_BONEWEIGHTS2: - return ( 2 * sizeof( short ) ); - default: - break; - } - } - - // Uncompressed-vertex element sizes - switch ( element ) - { - case VERTEX_ELEMENT_POSITION: return ( 3 * sizeof( float ) ); - case VERTEX_ELEMENT_NORMAL: return ( 3 * sizeof( float ) ); - case VERTEX_ELEMENT_COLOR: return ( 4 * sizeof( unsigned char ) ); - case VERTEX_ELEMENT_SPECULAR: return ( 4 * sizeof( unsigned char ) ); - case VERTEX_ELEMENT_TANGENT_S: return ( 3 * sizeof( float ) ); - case VERTEX_ELEMENT_TANGENT_T: return ( 3 * sizeof( float ) ); - case VERTEX_ELEMENT_WRINKLE: return ( 1 * sizeof( float ) ); // Packed into Position.W - case VERTEX_ELEMENT_BONEINDEX: return ( 4 * sizeof( unsigned char ) ); - case VERTEX_ELEMENT_BONEWEIGHTS1: return ( 1 * sizeof( float ) ); - case VERTEX_ELEMENT_BONEWEIGHTS2: return ( 2 * sizeof( float ) ); - case VERTEX_ELEMENT_BONEWEIGHTS3: return ( 3 * sizeof( float ) ); - case VERTEX_ELEMENT_BONEWEIGHTS4: return ( 4 * sizeof( float ) ); - case VERTEX_ELEMENT_USERDATA1: return ( 1 * sizeof( float ) ); - case VERTEX_ELEMENT_USERDATA2: return ( 2 * sizeof( float ) ); - case VERTEX_ELEMENT_USERDATA3: return ( 3 * sizeof( float ) ); - case VERTEX_ELEMENT_USERDATA4: return ( 4 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD1D_0: return ( 1 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD1D_1: return ( 1 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD1D_2: return ( 1 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD1D_3: return ( 1 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD1D_4: return ( 1 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD1D_5: return ( 1 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD1D_6: return ( 1 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD1D_7: return ( 1 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD2D_0: return ( 2 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD2D_1: return ( 2 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD2D_2: return ( 2 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD2D_3: return ( 2 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD2D_4: return ( 2 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD2D_5: return ( 2 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD2D_6: return ( 2 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD2D_7: return ( 2 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD3D_0: return ( 3 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD3D_1: return ( 3 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD3D_2: return ( 3 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD3D_3: return ( 3 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD3D_4: return ( 3 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD3D_5: return ( 3 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD3D_6: return ( 3 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD3D_7: return ( 3 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD4D_0: return ( 4 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD4D_1: return ( 4 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD4D_2: return ( 4 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD4D_3: return ( 4 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD4D_4: return ( 4 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD4D_5: return ( 4 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD4D_6: return ( 4 * sizeof( float ) ); - case VERTEX_ELEMENT_TEXCOORD4D_7: return ( 4 * sizeof( float ) ); - default: - Assert(0); - return 0; - }; -} - - -//----------------------------------------------------------------------------- -// Shader state flags can be read from the FLAGS materialvar -// Also can be read or written to with the Set/GetMaterialVarFlags() call -// Also make sure you add/remove a string associated with each flag below to CShaderSystem::ShaderStateString in ShaderSystem.cpp -//----------------------------------------------------------------------------- -enum MaterialVarFlags_t -{ - MATERIAL_VAR_DEBUG = (1 << 0), - MATERIAL_VAR_NO_DEBUG_OVERRIDE = (1 << 1), - MATERIAL_VAR_NO_DRAW = (1 << 2), - MATERIAL_VAR_USE_IN_FILLRATE_MODE = (1 << 3), - - MATERIAL_VAR_VERTEXCOLOR = (1 << 4), - MATERIAL_VAR_VERTEXALPHA = (1 << 5), - MATERIAL_VAR_SELFILLUM = (1 << 6), - MATERIAL_VAR_ADDITIVE = (1 << 7), - MATERIAL_VAR_ALPHATEST = (1 << 8), - MATERIAL_VAR_MULTIPASS = (1 << 9), - MATERIAL_VAR_ZNEARER = (1 << 10), - MATERIAL_VAR_MODEL = (1 << 11), - MATERIAL_VAR_FLAT = (1 << 12), - MATERIAL_VAR_NOCULL = (1 << 13), - MATERIAL_VAR_NOFOG = (1 << 14), - MATERIAL_VAR_IGNOREZ = (1 << 15), - MATERIAL_VAR_DECAL = (1 << 16), - MATERIAL_VAR_ENVMAPSPHERE = (1 << 17), - MATERIAL_VAR_NOALPHAMOD = (1 << 18), - MATERIAL_VAR_ENVMAPCAMERASPACE = (1 << 19), - MATERIAL_VAR_BASEALPHAENVMAPMASK = (1 << 20), - MATERIAL_VAR_TRANSLUCENT = (1 << 21), - MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK = (1 << 22), - MATERIAL_VAR_NEEDS_SOFTWARE_SKINNING = (1 << 23), - MATERIAL_VAR_OPAQUETEXTURE = (1 << 24), - MATERIAL_VAR_ENVMAPMODE = (1 << 25), - MATERIAL_VAR_SUPPRESS_DECALS = (1 << 26), - MATERIAL_VAR_HALFLAMBERT = (1 << 27), - MATERIAL_VAR_WIREFRAME = (1 << 28), - MATERIAL_VAR_ALLOWALPHATOCOVERAGE = (1 << 29), - - // NOTE: Only add flags here that either should be read from - // .vmts or can be set directly from client code. Other, internal - // flags should to into the flag enum in IMaterialInternal.h -}; - - -//----------------------------------------------------------------------------- -// Internal flags not accessible from outside the material system. Stored in Flags2 -//----------------------------------------------------------------------------- -enum MaterialVarFlags2_t -{ - // NOTE: These are for $flags2!!!!! -// UNUSED = (1 << 0), - - MATERIAL_VAR2_LIGHTING_UNLIT = 0, - MATERIAL_VAR2_LIGHTING_VERTEX_LIT = (1 << 1), - MATERIAL_VAR2_LIGHTING_LIGHTMAP = (1 << 2), - MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP = (1 << 3), - MATERIAL_VAR2_LIGHTING_MASK = - ( MATERIAL_VAR2_LIGHTING_VERTEX_LIT | - MATERIAL_VAR2_LIGHTING_LIGHTMAP | - MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP ), - - // FIXME: Should this be a part of the above lighting enums? - MATERIAL_VAR2_DIFFUSE_BUMPMAPPED_MODEL = (1 << 4), - MATERIAL_VAR2_USES_ENV_CUBEMAP = (1 << 5), - MATERIAL_VAR2_NEEDS_TANGENT_SPACES = (1 << 6), - MATERIAL_VAR2_NEEDS_SOFTWARE_LIGHTING = (1 << 7), - // GR - HDR path puts lightmap alpha in separate texture... - MATERIAL_VAR2_BLEND_WITH_LIGHTMAP_ALPHA = (1 << 8), - MATERIAL_VAR2_NEEDS_BAKED_LIGHTING_SNAPSHOTS = (1 << 9), - MATERIAL_VAR2_USE_FLASHLIGHT = (1 << 10), - MATERIAL_VAR2_USE_FIXED_FUNCTION_BAKED_LIGHTING = (1 << 11), - MATERIAL_VAR2_NEEDS_FIXED_FUNCTION_FLASHLIGHT = (1 << 12), - MATERIAL_VAR2_USE_EDITOR = (1 << 13), - MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE = (1 << 14), - MATERIAL_VAR2_NEEDS_FULL_FRAME_BUFFER_TEXTURE = (1 << 15), - MATERIAL_VAR2_IS_SPRITECARD = (1 << 16), - MATERIAL_VAR2_USES_VERTEXID = (1 << 17), - MATERIAL_VAR2_SUPPORTS_HW_SKINNING = (1 << 18), - MATERIAL_VAR2_SUPPORTS_FLASHLIGHT = (1 << 19), -}; - - -//----------------------------------------------------------------------------- -// Preview image return values -//----------------------------------------------------------------------------- -enum PreviewImageRetVal_t -{ - MATERIAL_PREVIEW_IMAGE_BAD = 0, - MATERIAL_PREVIEW_IMAGE_OK, - MATERIAL_NO_PREVIEW_IMAGE, -}; - - -//----------------------------------------------------------------------------- -// material interface -//----------------------------------------------------------------------------- -abstract_class IMaterial -{ -public: - // Get the name of the material. This is a full path to - // the vmt file starting from "hl2/materials" (or equivalent) without - // a file extension. - virtual const char * GetName() const = 0; - virtual const char * GetTextureGroupName() const = 0; - - // Get the preferred size/bitDepth of a preview image of a material. - // This is the sort of image that you would use for a thumbnail view - // of a material, or in WorldCraft until it uses materials to render. - // separate this for the tools maybe - virtual PreviewImageRetVal_t GetPreviewImageProperties( int *width, int *height, - ImageFormat *imageFormat, bool* isTranslucent ) const = 0; - - // Get a preview image at the specified width/height and bitDepth. - // Will do resampling if necessary.(not yet!!! :) ) - // Will do color format conversion. (works now.) - virtual PreviewImageRetVal_t GetPreviewImage( unsigned char *data, - int width, int height, - ImageFormat imageFormat ) const = 0; - // - virtual int GetMappingWidth( ) = 0; - virtual int GetMappingHeight( ) = 0; - - virtual int GetNumAnimationFrames( ) = 0; - - // For material subrects (material pages). Offset(u,v) and scale(u,v) are normalized to texture. - virtual bool InMaterialPage( void ) = 0; - virtual void GetMaterialOffset( float *pOffset ) = 0; - virtual void GetMaterialScale( float *pScale ) = 0; - virtual IMaterial *GetMaterialPage( void ) = 0; - - // find a vmt variable. - // This is how game code affects how a material is rendered. - // The game code must know about the params that are used by - // the shader for the material that it is trying to affect. - virtual IMaterialVar * FindVar( const char *varName, bool *found, bool complain = true ) = 0; - - // The user never allocates or deallocates materials. Reference counting is - // used instead. Garbage collection is done upon a call to - // IMaterialSystem::UncacheUnusedMaterials. - virtual void IncrementReferenceCount( void ) = 0; - virtual void DecrementReferenceCount( void ) = 0; - - inline void AddRef() { IncrementReferenceCount(); } - inline void Release() { DecrementReferenceCount(); } - - // Each material is assigned a number that groups it with like materials - // for sorting in the application. - virtual int GetEnumerationID( void ) const = 0; - - virtual void GetLowResColorSample( float s, float t, float *color ) const = 0; - - // This computes the state snapshots for this material - virtual void RecomputeStateSnapshots() = 0; - - // Are we translucent? - virtual bool IsTranslucent() = 0; - - // Are we alphatested? - virtual bool IsAlphaTested() = 0; - - // Are we vertex lit? - virtual bool IsVertexLit() = 0; - - // Gets the vertex format - virtual VertexFormat_t GetVertexFormat() const = 0; - - // returns true if this material uses a material proxy - virtual bool HasProxy( void ) const = 0; - - virtual bool UsesEnvCubemap( void ) = 0; - - virtual bool NeedsTangentSpace( void ) = 0; - - virtual bool NeedsPowerOfTwoFrameBufferTexture( bool bCheckSpecificToThisFrame = true ) = 0; - virtual bool NeedsFullFrameBufferTexture( bool bCheckSpecificToThisFrame = true ) = 0; - - // returns true if the shader doesn't do skinning itself and requires - // the data that is sent to it to be preskinned. - virtual bool NeedsSoftwareSkinning( void ) = 0; - - // Apply constant color or alpha modulation - virtual void AlphaModulate( float alpha ) = 0; - virtual void ColorModulate( float r, float g, float b ) = 0; - - // Material Var flags... - virtual void SetMaterialVarFlag( MaterialVarFlags_t flag, bool on ) = 0; - virtual bool GetMaterialVarFlag( MaterialVarFlags_t flag ) const = 0; - - // Gets material reflectivity - virtual void GetReflectivity( Vector& reflect ) = 0; - - // Gets material property flags - virtual bool GetPropertyFlag( MaterialPropertyTypes_t type ) = 0; - - // Is the material visible from both sides? - virtual bool IsTwoSided() = 0; - - // Sets the shader associated with the material - virtual void SetShader( const char *pShaderName ) = 0; - - // Can't be const because the material might have to precache itself. - virtual int GetNumPasses( void ) = 0; - - // Can't be const because the material might have to precache itself. - virtual int GetTextureMemoryBytes( void ) = 0; - - // Meant to be used with materials created using CreateMaterial - // It updates the materials to reflect the current values stored in the material vars - virtual void Refresh() = 0; - - // GR - returns true is material uses lightmap alpha for blending - virtual bool NeedsLightmapBlendAlpha( void ) = 0; - - // returns true if the shader doesn't do lighting itself and requires - // the data that is sent to it to be prelighted - virtual bool NeedsSoftwareLighting( void ) = 0; - - // Gets at the shader parameters - virtual int ShaderParamCount() const = 0; - virtual IMaterialVar **GetShaderParams( void ) = 0; - - // Returns true if this is the error material you get back from IMaterialSystem::FindMaterial if - // the material can't be found. - virtual bool IsErrorMaterial() const = 0; - - virtual void SetUseFixedFunctionBakedLighting( bool bEnable ) = 0; - - // Gets the current alpha modulation - virtual float GetAlphaModulation() = 0; - virtual void GetColorModulation( float *r, float *g, float *b ) = 0; - - // Gets the morph format - virtual MorphFormat_t GetMorphFormat() const = 0; - - // fast find that stores the index of the found var in the string table in local cache - virtual IMaterialVar * FindVarFast( char const *pVarName, unsigned int *pToken ) = 0; - - // Sets new VMT shader parameters for the material - virtual void SetShaderAndParams( KeyValues *pKeyValues ) = 0; - virtual const char * GetShaderName() const = 0; - - virtual void DeleteIfUnreferenced() = 0; - - virtual bool IsSpriteCard() = 0; - - virtual void CallBindProxy( void *proxyData ) = 0; - - virtual void RefreshPreservingMaterialVars() = 0; - - virtual bool WasReloadedFromWhitelist() = 0; -}; - - -inline bool IsErrorMaterial( IMaterial *pMat ) -{ - return !pMat || pMat->IsErrorMaterial(); -} - - -#endif // IMATERIAL_H diff --git a/public/materialsystem/imaterialproxy.h b/public/materialsystem/imaterialproxy.h deleted file mode 100644 index 5b9e954c8..000000000 --- a/public/materialsystem/imaterialproxy.h +++ /dev/null @@ -1,32 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IMATERIALPROXY_H -#define IMATERIALPROXY_H -#pragma once - -#include "interface.h" - -#define IMATERIAL_PROXY_INTERFACE_VERSION "_IMaterialProxy003" - -class IMaterial; -class KeyValues; - -abstract_class IMaterialProxy -{ -public: - virtual bool Init( IMaterial* pMaterial, KeyValues *pKeyValues ) = 0; - virtual void OnBind( void * ) = 0; - virtual void Release() = 0; - virtual IMaterial * GetMaterial() = 0; - -protected: - // no one should call this directly - virtual ~IMaterialProxy() {} -}; - -#endif // IMATERIALPROXY_H diff --git a/public/materialsystem/imaterialproxyfactory.h b/public/materialsystem/imaterialproxyfactory.h deleted file mode 100644 index fa9911275..000000000 --- a/public/materialsystem/imaterialproxyfactory.h +++ /dev/null @@ -1,25 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IMATERIALPROXYFACTORY_H -#define IMATERIALPROXYFACTORY_H -#pragma once - -#include "interface.h" - -#define IMATERIAL_PROXY_FACTOR_INTERFACE_VERSION "IMaterialProxyFactory001" - -class IMaterialProxy; - -abstract_class IMaterialProxyFactory -{ -public: - virtual IMaterialProxy *CreateProxy( const char *proxyName ) = 0; - virtual void DeleteProxy( IMaterialProxy *pProxy ) = 0; -}; - -#endif // IMATERIALPROXYFACTORY_H diff --git a/public/materialsystem/imaterialsystem.h b/public/materialsystem/imaterialsystem.h deleted file mode 100644 index de42cc22c..000000000 --- a/public/materialsystem/imaterialsystem.h +++ /dev/null @@ -1,1517 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// - -#ifndef IMATERIALSYSTEM_H -#define IMATERIALSYSTEM_H - -#ifdef _WIN32 -#pragma once -#endif - -#define OVERBRIGHT 2.0f -#define OO_OVERBRIGHT ( 1.0f / 2.0f ) -#define GAMMA 2.2f -#define TEXGAMMA 2.2f - -#include "tier1/interface.h" -#include "tier1/refcount.h" -#include "mathlib/vector.h" -#include "mathlib/vector4d.h" -#include "mathlib/vmatrix.h" -#include "appframework/IAppSystem.h" -#include "bitmap/imageformat.h" -#include "texture_group_names.h" -#include "vtf/vtf.h" -#include "materialsystem/deformations.h" -#include "materialsystem/imaterialsystemhardwareconfig.h" -#include "materialsystem/IColorCorrection.h" - - -//----------------------------------------------------------------------------- -// forward declarations -//----------------------------------------------------------------------------- -class IMaterial; -class IMesh; -class IVertexBuffer; -class IIndexBuffer; -struct MaterialSystem_Config_t; -class VMatrix; -struct matrix3x4_t; -class ITexture; -struct MaterialSystemHardwareIdentifier_t; -class KeyValues; -class IShader; -class IVertexTexture; -class IMorph; -class IMatRenderContext; -class ICallQueue; -struct MorphWeight_t; -class IFileList; - - -//----------------------------------------------------------------------------- -// The vertex format type -//----------------------------------------------------------------------------- -typedef uint64 VertexFormat_t; - -//----------------------------------------------------------------------------- -// important enumeration -//----------------------------------------------------------------------------- - -// NOTE NOTE NOTE!!!! If you up this, grep for "NEW_INTERFACE" to see if there is anything -// waiting to be enabled during an interface revision. -#define MATERIAL_SYSTEM_INTERFACE_VERSION "VMaterialSystem079" - -enum ShaderParamType_t -{ - SHADER_PARAM_TYPE_TEXTURE, - SHADER_PARAM_TYPE_INTEGER, - SHADER_PARAM_TYPE_COLOR, - SHADER_PARAM_TYPE_VEC2, - SHADER_PARAM_TYPE_VEC3, - SHADER_PARAM_TYPE_VEC4, - SHADER_PARAM_TYPE_ENVMAP, // obsolete - SHADER_PARAM_TYPE_FLOAT, - SHADER_PARAM_TYPE_BOOL, - SHADER_PARAM_TYPE_FOURCC, - SHADER_PARAM_TYPE_MATRIX, - SHADER_PARAM_TYPE_MATERIAL, - SHADER_PARAM_TYPE_STRING, -}; - -enum MaterialMatrixMode_t -{ - MATERIAL_VIEW = 0, - MATERIAL_PROJECTION, - - // Texture matrices - MATERIAL_TEXTURE0, - MATERIAL_TEXTURE1, - MATERIAL_TEXTURE2, - MATERIAL_TEXTURE3, - MATERIAL_TEXTURE4, - MATERIAL_TEXTURE5, - MATERIAL_TEXTURE6, - MATERIAL_TEXTURE7, - - MATERIAL_MODEL, - - // Total number of matrices - NUM_MATRIX_MODES = MATERIAL_MODEL+1, - - // Number of texture transforms - NUM_TEXTURE_TRANSFORMS = MATERIAL_TEXTURE7 - MATERIAL_TEXTURE0 + 1 -}; - -// FIXME: How do I specify the actual number of matrix modes? -const int NUM_MODEL_TRANSFORMS = 53; -const int MATERIAL_MODEL_MAX = MATERIAL_MODEL + NUM_MODEL_TRANSFORMS; - -enum MaterialPrimitiveType_t -{ - MATERIAL_POINTS = 0x0, - MATERIAL_LINES, - MATERIAL_TRIANGLES, - MATERIAL_TRIANGLE_STRIP, - MATERIAL_LINE_STRIP, - MATERIAL_LINE_LOOP, // a single line loop - MATERIAL_POLYGON, // this is a *single* polygon - MATERIAL_QUADS, - MATERIAL_INSTANCED_QUADS, // (X360) like MATERIAL_QUADS, but uses vertex instancing - - // This is used for static meshes that contain multiple types of - // primitive types. When calling draw, you'll need to specify - // a primitive type. - MATERIAL_HETEROGENOUS -}; - -enum MaterialPropertyTypes_t -{ - MATERIAL_PROPERTY_NEEDS_LIGHTMAP = 0, // bool - MATERIAL_PROPERTY_OPACITY, // int (enum MaterialPropertyOpacityTypes_t) - MATERIAL_PROPERTY_REFLECTIVITY, // vec3_t - MATERIAL_PROPERTY_NEEDS_BUMPED_LIGHTMAPS // bool -}; - -// acceptable property values for MATERIAL_PROPERTY_OPACITY -enum MaterialPropertyOpacityTypes_t -{ - MATERIAL_ALPHATEST = 0, - MATERIAL_OPAQUE, - MATERIAL_TRANSLUCENT -}; - -enum MaterialBufferTypes_t -{ - MATERIAL_FRONT = 0, - MATERIAL_BACK -}; - -enum MaterialCullMode_t -{ - MATERIAL_CULLMODE_CCW, // this culls polygons with counterclockwise winding - MATERIAL_CULLMODE_CW // this culls polygons with clockwise winding -}; - -enum MaterialIndexFormat_t -{ - MATERIAL_INDEX_FORMAT_UNKNOWN = -1, - MATERIAL_INDEX_FORMAT_16BIT = 0, - MATERIAL_INDEX_FORMAT_32BIT, -}; - -enum MaterialFogMode_t -{ - MATERIAL_FOG_NONE, - MATERIAL_FOG_LINEAR, - MATERIAL_FOG_LINEAR_BELOW_FOG_Z, -}; - -enum MaterialHeightClipMode_t -{ - MATERIAL_HEIGHTCLIPMODE_DISABLE, - MATERIAL_HEIGHTCLIPMODE_RENDER_ABOVE_HEIGHT, - MATERIAL_HEIGHTCLIPMODE_RENDER_BELOW_HEIGHT -}; - -enum MaterialNonInteractiveMode_t -{ - MATERIAL_NON_INTERACTIVE_MODE_NONE = -1, - MATERIAL_NON_INTERACTIVE_MODE_STARTUP = 0, - MATERIAL_NON_INTERACTIVE_MODE_LEVEL_LOAD, - - MATERIAL_NON_INTERACTIVE_MODE_COUNT, -}; - - -//----------------------------------------------------------------------------- -// Special morph used in decalling pass -//----------------------------------------------------------------------------- -#define MATERIAL_MORPH_DECAL ( (IMorph*)1 ) - - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- - -enum MaterialThreadMode_t -{ - MATERIAL_SINGLE_THREADED, - MATERIAL_QUEUED_SINGLE_THREADED, - MATERIAL_QUEUED_THREADED -}; - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- - -enum MaterialContextType_t -{ - MATERIAL_HARDWARE_CONTEXT, - MATERIAL_QUEUED_CONTEXT, - MATERIAL_NULL_CONTEXT -}; - - -//----------------------------------------------------------------------------- -// Light structure -//----------------------------------------------------------------------------- -#include "mathlib/lightdesc.h" - -#if 0 -enum LightType_t -{ - MATERIAL_LIGHT_DISABLE = 0, - MATERIAL_LIGHT_POINT, - MATERIAL_LIGHT_DIRECTIONAL, - MATERIAL_LIGHT_SPOT, -}; - -enum LightType_OptimizationFlags_t -{ - LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0 = 1, - LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION1 = 2, - LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION2 = 4, -}; - - -struct LightDesc_t -{ - LightType_t m_Type; - Vector m_Color; - Vector m_Position; - Vector m_Direction; - float m_Range; - float m_Falloff; - float m_Attenuation0; - float m_Attenuation1; - float m_Attenuation2; - float m_Theta; - float m_Phi; - // These aren't used by DX8. . used for software lighting. - float m_ThetaDot; - float m_PhiDot; - unsigned int m_Flags; - - - LightDesc_t() {} - -private: - // No copy constructors allowed - LightDesc_t(const LightDesc_t& vOther); -}; -#endif - -#define CREATERENDERTARGETFLAGS_HDR 0x00000001 -#define CREATERENDERTARGETFLAGS_AUTOMIPMAP 0x00000002 -#define CREATERENDERTARGETFLAGS_UNFILTERABLE_OK 0x00000004 -// XBOX ONLY: -#define CREATERENDERTARGETFLAGS_NOEDRAM 0x00000008 // inhibit allocation in 360 EDRAM -#define CREATERENDERTARGETFLAGS_TEMP 0x00000010 // only allocates memory upon first resolve, destroyed at level end - - -//----------------------------------------------------------------------------- -// allowed stencil operations. These match the d3d operations -//----------------------------------------------------------------------------- -enum StencilOperation_t -{ -#if !defined( _X360 ) - STENCILOPERATION_KEEP = 1, - STENCILOPERATION_ZERO = 2, - STENCILOPERATION_REPLACE = 3, - STENCILOPERATION_INCRSAT = 4, - STENCILOPERATION_DECRSAT = 5, - STENCILOPERATION_INVERT = 6, - STENCILOPERATION_INCR = 7, - STENCILOPERATION_DECR = 8, -#else - STENCILOPERATION_KEEP = D3DSTENCILOP_KEEP, - STENCILOPERATION_ZERO = D3DSTENCILOP_ZERO, - STENCILOPERATION_REPLACE = D3DSTENCILOP_REPLACE, - STENCILOPERATION_INCRSAT = D3DSTENCILOP_INCRSAT, - STENCILOPERATION_DECRSAT = D3DSTENCILOP_DECRSAT, - STENCILOPERATION_INVERT = D3DSTENCILOP_INVERT, - STENCILOPERATION_INCR = D3DSTENCILOP_INCR, - STENCILOPERATION_DECR = D3DSTENCILOP_DECR, -#endif - STENCILOPERATION_FORCE_DWORD = 0x7fffffff -}; - -enum StencilComparisonFunction_t -{ -#if !defined( _X360 ) - STENCILCOMPARISONFUNCTION_NEVER = 1, - STENCILCOMPARISONFUNCTION_LESS = 2, - STENCILCOMPARISONFUNCTION_EQUAL = 3, - STENCILCOMPARISONFUNCTION_LESSEQUAL = 4, - STENCILCOMPARISONFUNCTION_GREATER = 5, - STENCILCOMPARISONFUNCTION_NOTEQUAL = 6, - STENCILCOMPARISONFUNCTION_GREATEREQUAL = 7, - STENCILCOMPARISONFUNCTION_ALWAYS = 8, -#else - STENCILCOMPARISONFUNCTION_NEVER = D3DCMP_NEVER, - STENCILCOMPARISONFUNCTION_LESS = D3DCMP_LESS, - STENCILCOMPARISONFUNCTION_EQUAL = D3DCMP_EQUAL, - STENCILCOMPARISONFUNCTION_LESSEQUAL = D3DCMP_LESSEQUAL, - STENCILCOMPARISONFUNCTION_GREATER = D3DCMP_GREATER, - STENCILCOMPARISONFUNCTION_NOTEQUAL = D3DCMP_NOTEQUAL, - STENCILCOMPARISONFUNCTION_GREATEREQUAL = D3DCMP_GREATEREQUAL, - STENCILCOMPARISONFUNCTION_ALWAYS = D3DCMP_ALWAYS, -#endif - - STENCILCOMPARISONFUNCTION_FORCE_DWORD = 0x7fffffff -}; - - -//----------------------------------------------------------------------------- -// Enumeration for the various fields capable of being morphed -//----------------------------------------------------------------------------- -enum MorphFormatFlags_t -{ - MORPH_POSITION = 0x0001, // 3D - MORPH_NORMAL = 0x0002, // 3D - MORPH_WRINKLE = 0x0004, // 1D - MORPH_SPEED = 0x0008, // 1D - MORPH_SIDE = 0x0010, // 1D -}; - - -//----------------------------------------------------------------------------- -// The morph format type -//----------------------------------------------------------------------------- -typedef unsigned int MorphFormat_t; - - -//----------------------------------------------------------------------------- -// Standard lightmaps -//----------------------------------------------------------------------------- -enum StandardLightmap_t -{ - MATERIAL_SYSTEM_LIGHTMAP_PAGE_WHITE = -1, - MATERIAL_SYSTEM_LIGHTMAP_PAGE_WHITE_BUMP = -2, - MATERIAL_SYSTEM_LIGHTMAP_PAGE_USER_DEFINED = -3 -}; - - -struct MaterialSystem_SortInfo_t -{ - IMaterial *material; - int lightmapPageID; -}; - - -#define MAX_FB_TEXTURES 4 - -//----------------------------------------------------------------------------- -// Information about each adapter -//----------------------------------------------------------------------------- -enum -{ - MATERIAL_ADAPTER_NAME_LENGTH = 512 -}; - -struct MaterialAdapterInfo_t -{ - char m_pDriverName[MATERIAL_ADAPTER_NAME_LENGTH]; - unsigned int m_VendorID; - unsigned int m_DeviceID; - unsigned int m_SubSysID; - unsigned int m_Revision; - int m_nDXSupportLevel; // This is the *preferred* dx support level - int m_nMaxDXSupportLevel; - unsigned int m_nDriverVersionHigh; - unsigned int m_nDriverVersionLow; -}; - - -//----------------------------------------------------------------------------- -// Video mode info.. -//----------------------------------------------------------------------------- -struct MaterialVideoMode_t -{ - int m_Width; // if width and height are 0 and you select - int m_Height; // windowed mode, it'll use the window size - ImageFormat m_Format; // use ImageFormats (ignored for windowed mode) - int m_RefreshRate; // 0 == default (ignored for windowed mode) -}; - -// fixme: should move this into something else. -struct FlashlightState_t -{ - FlashlightState_t() - { - m_bEnableShadows = false; // Provide reasonable defaults for shadow depth mapping parameters - m_bDrawShadowFrustum = false; - m_flShadowMapResolution = 1024.0f; - m_flShadowFilterSize = 3.0f; - m_flShadowSlopeScaleDepthBias = 16.0f; - m_flShadowDepthBias = 0.0005f; - m_flShadowJitterSeed = 0.0f; - m_flShadowAtten = 0.0f; - m_bScissor = false; - m_nLeft = -1; - m_nTop = -1; - m_nRight = -1; - m_nBottom = -1; - m_nShadowQuality = 0; - } - - Vector m_vecLightOrigin; - Quaternion m_quatOrientation; - float m_NearZ; - float m_FarZ; - float m_fHorizontalFOVDegrees; - float m_fVerticalFOVDegrees; - float m_fQuadraticAtten; - float m_fLinearAtten; - float m_fConstantAtten; - float m_Color[4]; - ITexture *m_pSpotlightTexture; - int m_nSpotlightTextureFrame; - - // Shadow depth mapping parameters - bool m_bEnableShadows; - bool m_bDrawShadowFrustum; - float m_flShadowMapResolution; - float m_flShadowFilterSize; - float m_flShadowSlopeScaleDepthBias; - float m_flShadowDepthBias; - float m_flShadowJitterSeed; - float m_flShadowAtten; - int m_nShadowQuality; - - // Getters for scissor members - bool DoScissor() { return m_bScissor; } - int GetLeft() { return m_nLeft; } - int GetTop() { return m_nTop; } - int GetRight() { return m_nRight; } - int GetBottom() { return m_nBottom; } - -private: - - friend class CShadowMgr; - - bool m_bScissor; - int m_nLeft; - int m_nTop; - int m_nRight; - int m_nBottom; -}; - -//----------------------------------------------------------------------------- -// Flags to be used with the Init call -//----------------------------------------------------------------------------- -enum MaterialInitFlags_t -{ - MATERIAL_INIT_ALLOCATE_FULLSCREEN_TEXTURE = 0x2, - MATERIAL_INIT_REFERENCE_RASTERIZER = 0x4, -}; - -//----------------------------------------------------------------------------- -// Flags to specify type of depth buffer used with RT -//----------------------------------------------------------------------------- - -// GR - this is to add RT with no depth buffer bound - -enum MaterialRenderTargetDepth_t -{ - MATERIAL_RT_DEPTH_SHARED = 0x0, - MATERIAL_RT_DEPTH_SEPARATE = 0x1, - MATERIAL_RT_DEPTH_NONE = 0x2, - MATERIAL_RT_DEPTH_ONLY = 0x3, -}; - -//----------------------------------------------------------------------------- -// A function to be called when we need to release all vertex buffers -// NOTE: The restore function will tell the caller if all the vertex formats -// changed so that it can flush caches, etc. if it needs to (for dxlevel support) -//----------------------------------------------------------------------------- -enum RestoreChangeFlags_t -{ - MATERIAL_RESTORE_VERTEX_FORMAT_CHANGED = 0x1, -}; - - -// NOTE: All size modes will force the render target to be smaller than or equal to -// the size of the framebuffer. -enum RenderTargetSizeMode_t -{ - RT_SIZE_NO_CHANGE=0, // Only allowed for render targets that don't want a depth buffer - // (because if they have a depth buffer, the render target must be less than or equal to the size of the framebuffer). - RT_SIZE_DEFAULT=1, // Don't play with the specified width and height other than making sure it fits in the framebuffer. - RT_SIZE_PICMIP=2, // Apply picmip to the render target's width and height. - RT_SIZE_HDR=3, // frame_buffer_width / 4 - RT_SIZE_FULL_FRAME_BUFFER=4, // Same size as frame buffer, or next lower power of 2 if we can't do that. - RT_SIZE_OFFSCREEN=5, // Target of specified size, don't mess with dimensions - RT_SIZE_FULL_FRAME_BUFFER_ROUNDED_UP=6 // Same size as the frame buffer, rounded up if necessary for systems that can't do non-power of two textures. -}; - -typedef void (*MaterialBufferReleaseFunc_t)( ); -typedef void (*MaterialBufferRestoreFunc_t)( int nChangeFlags ); // see RestoreChangeFlags_t -typedef void (*ModeChangeCallbackFunc_t)( void ); - -typedef int VertexBufferHandle_t; -typedef unsigned short MaterialHandle_t; - -DECLARE_POINTER_HANDLE( OcclusionQueryObjectHandle_t ); -#define INVALID_OCCLUSION_QUERY_OBJECT_HANDLE ( (OcclusionQueryObjectHandle_t)0 ) - -class IMaterialProxyFactory; -class ITexture; -class IMaterialSystemHardwareConfig; -class CShadowMgr; - -DECLARE_POINTER_HANDLE( MaterialLock_t ); - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- - -abstract_class IMaterialSystem : public IAppSystem -{ -public: - - // Placeholder for API revision - virtual bool Connect( CreateInterfaceFn factory ) = 0; - virtual void Disconnect() = 0; - virtual void *QueryInterface( const char *pInterfaceName ) = 0; - virtual InitReturnVal_t Init() = 0; - virtual void Shutdown() = 0; - - //--------------------------------------------------------- - // Initialization and shutdown - //--------------------------------------------------------- - - // Call this to initialize the material system - // returns a method to create interfaces in the shader dll - virtual CreateInterfaceFn Init( char const* pShaderAPIDLL, - IMaterialProxyFactory *pMaterialProxyFactory, - CreateInterfaceFn fileSystemFactory, - CreateInterfaceFn cvarFactory=NULL ) = 0; - - // Call this to set an explicit shader version to use - // Must be called before Init(). - virtual void SetShaderAPI( char const *pShaderAPIDLL ) = 0; - - // Must be called before Init(), if you're going to call it at all... - virtual void SetAdapter( int nAdapter, int nFlags ) = 0; - - // Call this when the mod has been set up, which may occur after init - // At this point, the game + gamebin paths have been set up - virtual void ModInit() = 0; - virtual void ModShutdown() = 0; - - //--------------------------------------------------------- - // - //--------------------------------------------------------- - virtual void SetThreadMode( MaterialThreadMode_t mode, int nServiceThread = -1 ) = 0; - virtual MaterialThreadMode_t GetThreadMode() = 0; - virtual void ExecuteQueued() = 0; - - //--------------------------------------------------------- - // Config management - //--------------------------------------------------------- - - virtual IMaterialSystemHardwareConfig *GetHardwareConfig( const char *pVersion, int *returnCode ) = 0; - - - // Call this before rendering each frame with the current config - // for the material system. - // Will do whatever is necessary to get the material system into the correct state - // upon configuration change. .doesn't much else otherwise. - virtual bool UpdateConfig( bool bForceUpdate ) = 0; - - // Force this to be the config; update all material system convars to match the state - // return true if lightmaps need to be redownloaded - virtual bool OverrideConfig( const MaterialSystem_Config_t &config, bool bForceUpdate ) = 0; - - // Get the current config for this video card (as last set by UpdateConfig) - virtual const MaterialSystem_Config_t &GetCurrentConfigForVideoCard() const = 0; - - // Gets *recommended* configuration information associated with the display card, - // given a particular dx level to run under. - // Use dxlevel 0 to use the recommended dx level. - // The function returns false if an invalid dxlevel was specified - - // UNDONE: To find out all convars affected by configuration, we'll need to change - // the dxsupport.pl program to output all column headers into a single keyvalue block - // and then we would read that in, and send it back to the client - virtual bool GetRecommendedConfigurationInfo( int nDXLevel, KeyValues * pKeyValues ) = 0; - - - // ----------------------------------------------------------- - // Device methods - // ----------------------------------------------------------- - - // Gets the number of adapters... - virtual int GetDisplayAdapterCount() const = 0; - - // Returns the current adapter in use - virtual int GetCurrentAdapter() const = 0; - - // Returns info about each adapter - virtual void GetDisplayAdapterInfo( int adapter, MaterialAdapterInfo_t& info ) const = 0; - - // Returns the number of modes - virtual int GetModeCount( int adapter ) const = 0; - - // Returns mode information.. - virtual void GetModeInfo( int adapter, int mode, MaterialVideoMode_t& info ) const = 0; - - virtual void AddModeChangeCallBack( ModeChangeCallbackFunc_t func ) = 0; - - // Returns the mode info for the current display device - virtual void GetDisplayMode( MaterialVideoMode_t& mode ) const = 0; - - // Sets the mode... - virtual bool SetMode( void* hwnd, const MaterialSystem_Config_t &config ) = 0; - - virtual bool SupportsMSAAMode( int nMSAAMode ) = 0; - - // FIXME: REMOVE! Get video card identitier - virtual const MaterialSystemHardwareIdentifier_t &GetVideoCardIdentifier( void ) const = 0; - - // Use this to spew information about the 3D layer - virtual void SpewDriverInfo() const = 0; - - virtual void GetDXLevelDefaults(uint &max_dxlevel,uint &recommended_dxlevel) = 0; - - // Get the image format of the back buffer. . useful when creating render targets, etc. - virtual void GetBackBufferDimensions( int &width, int &height) const = 0; - virtual ImageFormat GetBackBufferFormat() const = 0; - - virtual bool SupportsHDRMode( HDRType_t nHDRModede ) = 0; - - - // ----------------------------------------------------------- - // Window methods - // ----------------------------------------------------------- - - // Creates/ destroys a child window - virtual bool AddView( void* hwnd ) = 0; - virtual void RemoveView( void* hwnd ) = 0; - - // Sets the view - virtual void SetView( void* hwnd ) = 0; - - - // ----------------------------------------------------------- - // Control flow - // ----------------------------------------------------------- - - virtual void BeginFrame( float frameTime ) = 0; - virtual void EndFrame( ) = 0; - virtual void Flush( bool flushHardware = false ) = 0; - - /// FIXME: This stuff needs to be cleaned up and abstracted. - // Stuff that gets exported to the launcher through the engine - virtual void SwapBuffers( ) = 0; - - // Flushes managed textures from the texture cacher - virtual void EvictManagedResources() = 0; - - virtual void ReleaseResources(void) = 0; - virtual void ReacquireResources(void ) = 0; - - - // ----------------------------------------------------------- - // Device loss/restore - // ----------------------------------------------------------- - - // Installs a function to be called when we need to release vertex buffers + textures - virtual void AddReleaseFunc( MaterialBufferReleaseFunc_t func ) = 0; - virtual void RemoveReleaseFunc( MaterialBufferReleaseFunc_t func ) = 0; - - // Installs a function to be called when we need to restore vertex buffers - virtual void AddRestoreFunc( MaterialBufferRestoreFunc_t func ) = 0; - virtual void RemoveRestoreFunc( MaterialBufferRestoreFunc_t func ) = 0; - - // Release temporary HW memory... - virtual void ResetTempHWMemory( bool bExitingLevel = false ) = 0; - - // For dealing with device lost in cases where SwapBuffers isn't called all the time (Hammer) - virtual void HandleDeviceLost() = 0; - - - // ----------------------------------------------------------- - // Shaders - // ----------------------------------------------------------- - - // Used to iterate over all shaders for editing purposes - // GetShaders returns the number of shaders it actually found - virtual int ShaderCount() const = 0; - virtual int GetShaders( int nFirstShader, int nMaxCount, IShader **ppShaderList ) const = 0; - - // FIXME: Is there a better way of doing this? - // Returns shader flag names for editors to be able to edit them - virtual int ShaderFlagCount() const = 0; - virtual const char * ShaderFlagName( int nIndex ) const = 0; - - // Gets the actual shader fallback for a particular shader - virtual void GetShaderFallback( const char *pShaderName, char *pFallbackShader, int nFallbackLength ) = 0; - - - // ----------------------------------------------------------- - // Material proxies - // ----------------------------------------------------------- - - virtual IMaterialProxyFactory *GetMaterialProxyFactory() = 0; - - // Sets the material proxy factory. Calling this causes all materials to be uncached. - virtual void SetMaterialProxyFactory( IMaterialProxyFactory* pFactory ) = 0; - - - // ----------------------------------------------------------- - // Editor mode - // ----------------------------------------------------------- - - // Used to enable editor materials. Must be called before Init. - virtual void EnableEditorMaterials() = 0; - - - // ----------------------------------------------------------- - // Stub mode mode - // ----------------------------------------------------------- - - // Force it to ignore Draw calls. - virtual void SetInStubMode( bool bInStubMode ) = 0; - - - //--------------------------------------------------------- - // Debug support - //--------------------------------------------------------- - - virtual void DebugPrintUsedMaterials( const char *pSearchSubString, bool bVerbose ) = 0; - virtual void DebugPrintUsedTextures( void ) = 0; - - virtual void ToggleSuppressMaterial( char const* pMaterialName ) = 0; - virtual void ToggleDebugMaterial( char const* pMaterialName ) = 0; - - - //--------------------------------------------------------- - // Misc features - //--------------------------------------------------------- - //returns whether fast clipping is being used or not - needed to be exposed for better per-object clip behavior - virtual bool UsingFastClipping( void ) = 0; - - virtual int StencilBufferBits( void ) = 0; //number of bits per pixel in the stencil buffer - - - //--------------------------------------------------------- - // Material and texture management - //--------------------------------------------------------- - - // uncache all materials. . good for forcing reload of materials. - virtual void UncacheAllMaterials( ) = 0; - - // Remove any materials from memory that aren't in use as determined - // by the IMaterial's reference count. - virtual void UncacheUnusedMaterials( bool bRecomputeStateSnapshots = false ) = 0; - - // Load any materials into memory that are to be used as determined - // by the IMaterial's reference count. - virtual void CacheUsedMaterials( ) = 0; - - // Force all textures to be reloaded from disk. - virtual void ReloadTextures( ) = 0; - - // Reloads materials - virtual void ReloadMaterials( const char *pSubString = NULL ) = 0; - - // Create a procedural material. The keyvalues looks like a VMT file - virtual IMaterial * CreateMaterial( const char *pMaterialName, KeyValues *pVMTKeyValues ) = 0; - - // Find a material by name. - // The name of a material is a full path to - // the vmt file starting from "hl2/materials" (or equivalent) without - // a file extension. - // eg. "dev/dev_bumptest" refers to somethign similar to: - // "d:/hl2/hl2/materials/dev/dev_bumptest.vmt" - // - // Most of the texture groups for pTextureGroupName are listed in texture_group_names.h. - // - // Note: if the material can't be found, this returns a checkerboard material. You can - // find out if you have that material by calling IMaterial::IsErrorMaterial(). - // (Or use the global IsErrorMaterial function, which checks if it's null too). - virtual IMaterial * FindMaterial( char const* pMaterialName, const char *pTextureGroupName, bool complain = true, const char *pComplainPrefix = NULL ) = 0; - - //--------------------------------- - // This is the interface for knowing what materials are available - // is to use the following functions to get a list of materials. The - // material names will have the full path to the material, and that is the - // only way that the directory structure of the materials will be seen through this - // interface. - // NOTE: This is mostly for worldcraft to get a list of materials to put - // in the "texture" browser.in Worldcraft - virtual MaterialHandle_t FirstMaterial() const = 0; - - // returns InvalidMaterial if there isn't another material. - // WARNING: you must call GetNextMaterial until it returns NULL, - // otherwise there will be a memory leak. - virtual MaterialHandle_t NextMaterial( MaterialHandle_t h ) const = 0; - - // This is the invalid material - virtual MaterialHandle_t InvalidMaterial() const = 0; - - // Returns a particular material - virtual IMaterial* GetMaterial( MaterialHandle_t h ) const = 0; - - // Get the total number of materials in the system. These aren't just the used - // materials, but the complete collection. - virtual int GetNumMaterials( ) const = 0; - - //--------------------------------- - - virtual ITexture * FindTexture( char const* pTextureName, const char *pTextureGroupName, bool complain = true ) = 0; - - // Checks to see if a particular texture is loaded - virtual bool IsTextureLoaded( char const* pTextureName ) const = 0; - - // Creates a procedural texture - virtual ITexture * CreateProceduralTexture( const char *pTextureName, - const char *pTextureGroupName, - int w, - int h, - ImageFormat fmt, - int nFlags ) = 0; - - // - // Render targets - // - virtual void BeginRenderTargetAllocation() = 0; - virtual void EndRenderTargetAllocation() = 0; // Simulate an Alt-Tab in here, which causes a release/restore of all resources - - // Creates a render target - // If depth == true, a depth buffer is also allocated. If not, then - // the screen's depth buffer is used. - // Creates a texture for use as a render target - virtual ITexture * CreateRenderTargetTexture( int w, - int h, - RenderTargetSizeMode_t sizeMode, // Controls how size is generated (and regenerated on video mode change). - ImageFormat format, - MaterialRenderTargetDepth_t depth = MATERIAL_RT_DEPTH_SHARED ) = 0; - - virtual ITexture * CreateNamedRenderTargetTextureEx( const char *pRTName, // Pass in NULL here for an unnamed render target. - int w, - int h, - RenderTargetSizeMode_t sizeMode, // Controls how size is generated (and regenerated on video mode change). - ImageFormat format, - MaterialRenderTargetDepth_t depth = MATERIAL_RT_DEPTH_SHARED, - unsigned int textureFlags = TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT, - unsigned int renderTargetFlags = 0 ) = 0; - - virtual ITexture * CreateNamedRenderTargetTexture( const char *pRTName, - int w, - int h, - RenderTargetSizeMode_t sizeMode, // Controls how size is generated (and regenerated on video mode change). - ImageFormat format, - MaterialRenderTargetDepth_t depth = MATERIAL_RT_DEPTH_SHARED, - bool bClampTexCoords = true, - bool bAutoMipMap = false ) = 0; - - // Must be called between the above Begin-End calls! - virtual ITexture * CreateNamedRenderTargetTextureEx2( const char *pRTName, // Pass in NULL here for an unnamed render target. - int w, - int h, - RenderTargetSizeMode_t sizeMode, // Controls how size is generated (and regenerated on video mode change). - ImageFormat format, - MaterialRenderTargetDepth_t depth = MATERIAL_RT_DEPTH_SHARED, - unsigned int textureFlags = TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT, - unsigned int renderTargetFlags = 0 ) = 0; - - // ----------------------------------------------------------- - // Lightmaps - // ----------------------------------------------------------- - - // To allocate lightmaps, sort the whole world by material twice. - // The first time through, call AllocateLightmap for every surface. - // that has a lightmap. - // The second time through, call AllocateWhiteLightmap for every - // surface that expects to use shaders that expect lightmaps. - virtual void BeginLightmapAllocation( ) = 0; - virtual void EndLightmapAllocation( ) = 0; - - // returns the sorting id for this surface - virtual int AllocateLightmap( int width, int height, - int offsetIntoLightmapPage[2], - IMaterial *pMaterial ) = 0; - // returns the sorting id for this surface - virtual int AllocateWhiteLightmap( IMaterial *pMaterial ) = 0; - - // lightmaps are in linear color space - // lightmapPageID is returned by GetLightmapPageIDForSortID - // lightmapSize and offsetIntoLightmapPage are returned by AllocateLightmap. - // You should never call UpdateLightmap for a lightmap allocated through - // AllocateWhiteLightmap. - virtual void UpdateLightmap( int lightmapPageID, int lightmapSize[2], - int offsetIntoLightmapPage[2], - float *pFloatImage, float *pFloatImageBump1, - float *pFloatImageBump2, float *pFloatImageBump3 ) = 0; - - // fixme: could just be an array of ints for lightmapPageIDs since the material - // for a surface is already known. - virtual int GetNumSortIDs( ) = 0; - virtual void GetSortInfo( MaterialSystem_SortInfo_t *sortInfoArray ) = 0; - - // Read the page size of an existing lightmap by sort id (returned from AllocateLightmap()) - virtual void GetLightmapPageSize( int lightmap, int *width, int *height ) const = 0; - - virtual void ResetMaterialLightmapPageInfo() = 0; - - - - virtual void ClearBuffers( bool bClearColor, bool bClearDepth, bool bClearStencil = false ) = 0; - - // ----------------------------------------------------------- - // X360 specifics - // ----------------------------------------------------------- - -#if defined( _X360 ) - virtual void ListUsedMaterials( void ) = 0; - virtual HXUIFONT OpenTrueTypeFont( const char *pFontname, int tall, int style ) = 0; - virtual void CloseTrueTypeFont( HXUIFONT hFont ) = 0; - virtual bool GetTrueTypeFontMetrics( HXUIFONT hFont, XUIFontMetrics *pFontMetrics, XUICharMetrics charMetrics[256] ) = 0; - // Render a sequence of characters and extract the data into a buffer - // For each character, provide the width+height of the font texture subrect, - // an offset to apply when rendering the glyph, and an offset into a buffer to receive the RGBA data - virtual bool GetTrueTypeGlyphs( HXUIFONT hFont, int numChars, wchar_t *pWch, int *pOffsetX, int *pOffsetY, int *pWidth, int *pHeight, unsigned char *pRGBA, int *pRGBAOffset ) = 0; - virtual void PersistDisplay() = 0; - virtual void *GetD3DDevice() = 0; - virtual bool OwnGPUResources( bool bEnable ) = 0; -#endif - - // ----------------------------------------------------------- - // Access the render contexts - // ----------------------------------------------------------- - virtual IMatRenderContext * GetRenderContext() = 0; - - virtual bool SupportsShadowDepthTextures( void ) = 0; - virtual void BeginUpdateLightmaps( void ) = 0; - virtual void EndUpdateLightmaps( void ) = 0; - - // ----------------------------------------------------------- - // Methods to force the material system into non-threaded, non-queued mode - // ----------------------------------------------------------- - virtual MaterialLock_t Lock() = 0; - virtual void Unlock( MaterialLock_t ) = 0; - - // Vendor-dependent shadow depth texture format - virtual ImageFormat GetShadowDepthTextureFormat() = 0; - - virtual bool SupportsFetch4( void ) = 0; - - // Create a custom render context. Cannot be used to create MATERIAL_HARDWARE_CONTEXT - virtual IMatRenderContext *CreateRenderContext( MaterialContextType_t type ) = 0; - - // Set a specified render context to be the global context for the thread. Returns the prior context. - virtual IMatRenderContext *SetRenderContext( IMatRenderContext * ) = 0; - - virtual bool SupportsCSAAMode( int nNumSamples, int nQualityLevel ) = 0; - - virtual void RemoveModeChangeCallBack( ModeChangeCallbackFunc_t func ) = 0; - - // Finds or create a procedural material. - virtual IMaterial * FindProceduralMaterial( const char *pMaterialName, const char *pTextureGroupName, KeyValues *pVMTKeyValues ) = 0; - - virtual ImageFormat GetNullTextureFormat() = 0; - - virtual void AddTextureAlias( const char *pAlias, const char *pRealName ) = 0; - virtual void RemoveTextureAlias( const char *pAlias ) = 0; - - // returns a lightmap page ID for this allocation, -1 if none available - // frameID is a number that should be changed every frame to prevent locking any textures that are - // being used to draw in the previous frame - virtual int AllocateDynamicLightmap( int lightmapSize[2], int *pOutOffsetIntoPage, int frameID ) = 0; - - virtual void SetExcludedTextures( const char *pScriptName ) = 0; - virtual void UpdateExcludedTextures( void ) = 0; - - virtual bool IsInFrame( ) const = 0; - - virtual void CompactMemory() = 0; - - // For sv_pure mode. The filesystem figures out which files the client needs to reload to be "pure" ala the server's preferences. - virtual void ReloadFilesInList( IFileList *pFilesToReload ) = 0; -}; - - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -abstract_class IMatRenderContext : public IRefCounted -{ -public: - virtual void BeginRender() = 0; - virtual void EndRender() = 0; - - virtual void Flush( bool flushHardware = false ) = 0; - - virtual void BindLocalCubemap( ITexture *pTexture ) = 0; - - // pass in an ITexture (that is build with "rendertarget" "1") or - // pass in NULL for the regular backbuffer. - virtual void SetRenderTarget( ITexture *pTexture ) = 0; - virtual ITexture * GetRenderTarget( void ) = 0; - - virtual void GetRenderTargetDimensions( int &width, int &height) const = 0; - - // Bind a material is current for rendering. - virtual void Bind( IMaterial *material, void *proxyData = 0 ) = 0; - // Bind a lightmap page current for rendering. You only have to - // do this for materials that require lightmaps. - virtual void BindLightmapPage( int lightmapPageID ) = 0; - - // inputs are between 0 and 1 - virtual void DepthRange( float zNear, float zFar ) = 0; - - virtual void ClearBuffers( bool bClearColor, bool bClearDepth, bool bClearStencil = false ) = 0; - - // read to a unsigned char rgb image. - virtual void ReadPixels( int x, int y, int width, int height, unsigned char *data, ImageFormat dstFormat ) = 0; - - // Sets lighting - virtual void SetAmbientLight( float r, float g, float b ) = 0; - virtual void SetLight( int lightNum, const LightDesc_t& desc ) = 0; - - // The faces of the cube are specified in the same order as cubemap textures - virtual void SetAmbientLightCube( Vector4D cube[6] ) = 0; - - // Blit the backbuffer to the framebuffer texture - virtual void CopyRenderTargetToTexture( ITexture *pTexture ) = 0; - - // Set the current texture that is a copy of the framebuffer. - virtual void SetFrameBufferCopyTexture( ITexture *pTexture, int textureIndex = 0 ) = 0; - virtual ITexture *GetFrameBufferCopyTexture( int textureIndex ) = 0; - - // - // end vertex array api - // - - // matrix api - virtual void MatrixMode( MaterialMatrixMode_t matrixMode ) = 0; - virtual void PushMatrix( void ) = 0; - virtual void PopMatrix( void ) = 0; - virtual void LoadMatrix( VMatrix const& matrix ) = 0; - virtual void LoadMatrix( matrix3x4_t const& matrix ) = 0; - virtual void MultMatrix( VMatrix const& matrix ) = 0; - virtual void MultMatrix( matrix3x4_t const& matrix ) = 0; - virtual void MultMatrixLocal( VMatrix const& matrix ) = 0; - virtual void MultMatrixLocal( matrix3x4_t const& matrix ) = 0; - virtual void GetMatrix( MaterialMatrixMode_t matrixMode, VMatrix *matrix ) = 0; - virtual void GetMatrix( MaterialMatrixMode_t matrixMode, matrix3x4_t *matrix ) = 0; - virtual void LoadIdentity( void ) = 0; - virtual void Ortho( double left, double top, double right, double bottom, double zNear, double zFar ) = 0; - virtual void PerspectiveX( double fovx, double aspect, double zNear, double zFar ) = 0; - virtual void PickMatrix( int x, int y, int width, int height ) = 0; - virtual void Rotate( float angle, float x, float y, float z ) = 0; - virtual void Translate( float x, float y, float z ) = 0; - virtual void Scale( float x, float y, float z ) = 0; - // end matrix api - - // Sets/gets the viewport - virtual void Viewport( int x, int y, int width, int height ) = 0; - virtual void GetViewport( int& x, int& y, int& width, int& height ) const = 0; - - // The cull mode - virtual void CullMode( MaterialCullMode_t cullMode ) = 0; - - // end matrix api - - // This could easily be extended to a general user clip plane - virtual void SetHeightClipMode( MaterialHeightClipMode_t nHeightClipMode ) = 0; - // garymcthack : fog z is always used for heightclipz for now. - virtual void SetHeightClipZ( float z ) = 0; - - // Fog methods... - virtual void FogMode( MaterialFogMode_t fogMode ) = 0; - virtual void FogStart( float fStart ) = 0; - virtual void FogEnd( float fEnd ) = 0; - virtual void SetFogZ( float fogZ ) = 0; - virtual MaterialFogMode_t GetFogMode( void ) = 0; - - virtual void FogColor3f( float r, float g, float b ) = 0; - virtual void FogColor3fv( float const* rgb ) = 0; - virtual void FogColor3ub( unsigned char r, unsigned char g, unsigned char b ) = 0; - virtual void FogColor3ubv( unsigned char const* rgb ) = 0; - - virtual void GetFogColor( unsigned char *rgb ) = 0; - - // Sets the number of bones for skinning - virtual void SetNumBoneWeights( int numBones ) = 0; - - // Creates/destroys Mesh - virtual IMesh* CreateStaticMesh( VertexFormat_t fmt, const char *pTextureBudgetGroup, IMaterial * pMaterial = NULL ) = 0; - virtual void DestroyStaticMesh( IMesh* mesh ) = 0; - - // Gets the dynamic mesh associated with the currently bound material - // note that you've got to render the mesh before calling this function - // a second time. Clients should *not* call DestroyStaticMesh on the mesh - // returned by this call. - // Use buffered = false if you want to not have the mesh be buffered, - // but use it instead in the following pattern: - // meshBuilder.Begin - // meshBuilder.End - // Draw partial - // Draw partial - // Draw partial - // meshBuilder.Begin - // meshBuilder.End - // etc - // Use Vertex or Index Override to supply a static vertex or index buffer - // to use in place of the dynamic buffers. - // - // If you pass in a material in pAutoBind, it will automatically bind the - // material. This can be helpful since you must bind the material you're - // going to use BEFORE calling GetDynamicMesh. - virtual IMesh* GetDynamicMesh( - bool buffered = true, - IMesh* pVertexOverride = 0, - IMesh* pIndexOverride = 0, - IMaterial *pAutoBind = 0 ) = 0; - - // ------------ New Vertex/Index Buffer interface ---------------------------- - // Do we need support for bForceTempMesh and bSoftwareVertexShader? - // I don't think we use bSoftwareVertexShader anymore. .need to look into bForceTempMesh. - virtual IVertexBuffer *CreateStaticVertexBuffer( VertexFormat_t fmt, int nVertexCount, const char *pTextureBudgetGroup ) = 0; - virtual IIndexBuffer *CreateStaticIndexBuffer( MaterialIndexFormat_t fmt, int nIndexCount, const char *pTextureBudgetGroup ) = 0; - virtual void DestroyVertexBuffer( IVertexBuffer * ) = 0; - virtual void DestroyIndexBuffer( IIndexBuffer * ) = 0; - // Do we need to specify the stream here in the case of locking multiple dynamic VBs on different streams? - virtual IVertexBuffer *GetDynamicVertexBuffer( int streamID, VertexFormat_t vertexFormat, bool bBuffered = true ) = 0; - virtual IIndexBuffer *GetDynamicIndexBuffer( MaterialIndexFormat_t fmt, bool bBuffered = true ) = 0; - virtual void BindVertexBuffer( int streamID, IVertexBuffer *pVertexBuffer, int nOffsetInBytes, int nFirstVertex, int nVertexCount, VertexFormat_t fmt, int nRepetitions = 1 ) = 0; - virtual void BindIndexBuffer( IIndexBuffer *pIndexBuffer, int nOffsetInBytes ) = 0; - virtual void Draw( MaterialPrimitiveType_t primitiveType, int firstIndex, int numIndices ) = 0; - // ------------ End ---------------------------- - - // Selection mode methods - virtual int SelectionMode( bool selectionMode ) = 0; - virtual void SelectionBuffer( unsigned int* pBuffer, int size ) = 0; - virtual void ClearSelectionNames( ) = 0; - virtual void LoadSelectionName( int name ) = 0; - virtual void PushSelectionName( int name ) = 0; - virtual void PopSelectionName() = 0; - - // Sets the Clear Color for ClearBuffer.... - virtual void ClearColor3ub( unsigned char r, unsigned char g, unsigned char b ) = 0; - virtual void ClearColor4ub( unsigned char r, unsigned char g, unsigned char b, unsigned char a ) = 0; - - // Allows us to override the depth buffer setting of a material - virtual void OverrideDepthEnable( bool bEnable, bool bDepthEnable ) = 0; - - // FIXME: This is a hack required for NVidia/XBox, can they fix in drivers? - virtual void DrawScreenSpaceQuad( IMaterial* pMaterial ) = 0; - - // For debugging and building recording files. This will stuff a token into the recording file, - // then someone doing a playback can watch for the token. - virtual void SyncToken( const char *pToken ) = 0; - - // FIXME: REMOVE THIS FUNCTION! - // The only reason why it's not gone is because we're a week from ship when I found the bug in it - // and everything's tuned to use it. - // It's returning values which are 2x too big (it's returning sphere diameter x2) - // Use ComputePixelDiameterOfSphere below in all new code instead. - virtual float ComputePixelWidthOfSphere( const Vector& origin, float flRadius ) = 0; - - // - // Occlusion query support - // - - // Allocate and delete query objects. - virtual OcclusionQueryObjectHandle_t CreateOcclusionQueryObject( void ) = 0; - virtual void DestroyOcclusionQueryObject( OcclusionQueryObjectHandle_t ) = 0; - - // Bracket drawing with begin and end so that we can get counts next frame. - virtual void BeginOcclusionQueryDrawing( OcclusionQueryObjectHandle_t ) = 0; - virtual void EndOcclusionQueryDrawing( OcclusionQueryObjectHandle_t ) = 0; - - // Get the number of pixels rendered between begin and end on an earlier frame. - // Calling this in the same frame is a huge perf hit! - virtual int OcclusionQuery_GetNumPixelsRendered( OcclusionQueryObjectHandle_t ) = 0; - - virtual void SetFlashlightMode( bool bEnable ) = 0; - - virtual void SetFlashlightState( const FlashlightState_t &state, const VMatrix &worldToTexture ) = 0; - - // Gets the current height clip mode - virtual MaterialHeightClipMode_t GetHeightClipMode( ) = 0; - - // This returns the diameter of the sphere in pixels based on - // the current model, view, + projection matrices and viewport. - virtual float ComputePixelDiameterOfSphere( const Vector& vecAbsOrigin, float flRadius ) = 0; - - // By default, the material system applies the VIEW and PROJECTION matrices to the user clip - // planes (which are specified in world space) to generate projection-space user clip planes - // Occasionally (for the particle system in hl2, for example), we want to override that - // behavior and explictly specify a ViewProj transform for user clip planes - virtual void EnableUserClipTransformOverride( bool bEnable ) = 0; - virtual void UserClipTransform( const VMatrix &worldToView ) = 0; - - virtual bool GetFlashlightMode() const = 0; - - // Used to make the handle think it's never had a successful query before - virtual void ResetOcclusionQueryObject( OcclusionQueryObjectHandle_t ) = 0; - - // FIXME: Remove - virtual void Unused3() {} - - // Creates/destroys morph data associated w/ a particular material - virtual IMorph *CreateMorph( MorphFormat_t format, const char *pDebugName ) = 0; - virtual void DestroyMorph( IMorph *pMorph ) = 0; - - // Binds the morph data for use in rendering - virtual void BindMorph( IMorph *pMorph ) = 0; - - // Sets flexweights for rendering - virtual void SetFlexWeights( int nFirstWeight, int nCount, const MorphWeight_t* pWeights ) = 0; - - // FIXME: Remove - virtual void Unused4() {}; - virtual void Unused5() {}; - virtual void Unused6() {}; - virtual void Unused7() {}; - virtual void Unused8() {}; - - // Read w/ stretch to a host-memory buffer - virtual void ReadPixelsAndStretch( Rect_t *pSrcRect, Rect_t *pDstRect, unsigned char *pBuffer, ImageFormat dstFormat, int nDstStride ) = 0; - - // Gets the window size - virtual void GetWindowSize( int &width, int &height ) const = 0; - - // This function performs a texture map from one texture map to the render destination, doing - // all the necessary pixel/texel coordinate fix ups. fractional values can be used for the - // src_texture coordinates to get linear sampling - integer values should produce 1:1 mappings - // for non-scaled operations. - virtual void DrawScreenSpaceRectangle( - IMaterial *pMaterial, - int destx, int desty, - int width, int height, - float src_texture_x0, float src_texture_y0, // which texel you want to appear at - // destx/y - float src_texture_x1, float src_texture_y1, // which texel you want to appear at - // destx+width-1, desty+height-1 - int src_texture_width, int src_texture_height, // needed for fixup - void *pClientRenderable = NULL, - int nXDice = 1, - int nYDice = 1 )=0; - - virtual void LoadBoneMatrix( int boneIndex, const matrix3x4_t& matrix ) = 0; - - // This version will push the current rendertarget + current viewport onto the stack - virtual void PushRenderTargetAndViewport( ) = 0; - - // This version will push a new rendertarget + a maximal viewport for that rendertarget onto the stack - virtual void PushRenderTargetAndViewport( ITexture *pTexture ) = 0; - - // This version will push a new rendertarget + a specified viewport onto the stack - virtual void PushRenderTargetAndViewport( ITexture *pTexture, int nViewX, int nViewY, int nViewW, int nViewH ) = 0; - - // This version will push a new rendertarget + a specified viewport onto the stack - virtual void PushRenderTargetAndViewport( ITexture *pTexture, ITexture *pDepthTexture, int nViewX, int nViewY, int nViewW, int nViewH ) = 0; - - // This will pop a rendertarget + viewport - virtual void PopRenderTargetAndViewport( void ) = 0; - - // Binds a particular texture as the current lightmap - virtual void BindLightmapTexture( ITexture *pLightmapTexture ) = 0; - - // Blit a subrect of the current render target to another texture - virtual void CopyRenderTargetToTextureEx( ITexture *pTexture, int nRenderTargetID, Rect_t *pSrcRect, Rect_t *pDstRect = NULL ) = 0; - - // Special off-center perspective matrix for DoF, MSAA jitter and poster rendering - virtual void PerspectiveOffCenterX( double fovx, double aspect, double zNear, double zFar, double bottom, double top, double left, double right ) = 0; - - // Rendering parameters control special drawing modes withing the material system, shader - // system, shaders, and engine. renderparm.h has their definitions. - virtual void SetFloatRenderingParameter(int parm_number, float value) = 0; - virtual void SetIntRenderingParameter(int parm_number, int value) = 0; - virtual void SetVectorRenderingParameter(int parm_number, Vector const &value) = 0; - - // stencil buffer operations. - virtual void SetStencilEnable(bool onoff) = 0; - virtual void SetStencilFailOperation(StencilOperation_t op) = 0; - virtual void SetStencilZFailOperation(StencilOperation_t op) = 0; - virtual void SetStencilPassOperation(StencilOperation_t op) = 0; - virtual void SetStencilCompareFunction(StencilComparisonFunction_t cmpfn) = 0; - virtual void SetStencilReferenceValue(int ref) = 0; - virtual void SetStencilTestMask(uint32 msk) = 0; - virtual void SetStencilWriteMask(uint32 msk) = 0; - virtual void ClearStencilBufferRectangle(int xmin, int ymin, int xmax, int ymax,int value) =0; - - virtual void SetRenderTargetEx( int nRenderTargetID, ITexture *pTexture ) = 0; - - // rendering clip planes, beware that only the most recently pushed plane will actually be used in a sizeable chunk of hardware configurations - // and that changes to the clip planes mid-frame while UsingFastClipping() is true will result unresolvable depth inconsistencies - virtual void PushCustomClipPlane( const float *pPlane ) = 0; - virtual void PopCustomClipPlane( void ) = 0; - - // Returns the number of vertices + indices we can render using the dynamic mesh - // Passing true in the second parameter will return the max # of vertices + indices - // we can use before a flush is provoked and may return different values - // if called multiple times in succession. - // Passing false into the second parameter will return - // the maximum possible vertices + indices that can be rendered in a single batch - virtual void GetMaxToRender( IMesh *pMesh, bool bMaxUntilFlush, int *pMaxVerts, int *pMaxIndices ) = 0; - - // Returns the max possible vertices + indices to render in a single draw call - virtual int GetMaxVerticesToRender( IMaterial *pMaterial ) = 0; - virtual int GetMaxIndicesToRender( ) = 0; - virtual void DisableAllLocalLights() = 0; - virtual int CompareMaterialCombos( IMaterial *pMaterial1, IMaterial *pMaterial2, int lightMapID1, int lightMapID2 ) = 0; - - virtual IMesh *GetFlexMesh() = 0; - - virtual void SetFlashlightStateEx( const FlashlightState_t &state, const VMatrix &worldToTexture, ITexture *pFlashlightDepthTexture ) = 0; - - // Returns the currently bound local cubemap - virtual ITexture *GetLocalCubemap( ) = 0; - - // This is a version of clear buffers which will only clear the buffer at pixels which pass the stencil test - virtual void ClearBuffersObeyStencil( bool bClearColor, bool bClearDepth ) = 0; - - //enables/disables all entered clipping planes, returns the input from the last time it was called. - virtual bool EnableClipping( bool bEnable ) = 0; - - //get fog distances entered with FogStart(), FogEnd(), and SetFogZ() - virtual void GetFogDistances( float *fStart, float *fEnd, float *fFogZ ) = 0; - - // Hooks for firing PIX events from outside the Material System... - virtual void BeginPIXEvent( unsigned long color, const char *szName ) = 0; - virtual void EndPIXEvent() = 0; - virtual void SetPIXMarker( unsigned long color, const char *szName ) = 0; - - // Batch API - // from changelist 166623: - // - replaced obtuse material system batch usage with an explicit and easier to thread API - virtual void BeginBatch( IMesh* pIndices ) = 0; - virtual void BindBatch( IMesh* pVertices, IMaterial *pAutoBind = NULL ) = 0; - virtual void DrawBatch(int firstIndex, int numIndices ) = 0; - virtual void EndBatch() = 0; - - // Raw access to the call queue, which can be NULL if not in a queued mode - virtual ICallQueue *GetCallQueue() = 0; - - // Returns the world-space camera position - virtual void GetWorldSpaceCameraPosition( Vector *pCameraPos ) = 0; - virtual void GetWorldSpaceCameraVectors( Vector *pVecForward, Vector *pVecRight, Vector *pVecUp ) = 0; - - // Tone mapping - virtual void ResetToneMappingScale( float monoscale) = 0; // set scale to monoscale instantly with no chasing - virtual void SetGoalToneMappingScale( float monoscale) = 0; // set scale to monoscale instantly with no chasing - - // call TurnOnToneMapping before drawing the 3d scene to get the proper interpolated brightness - // value set. - virtual void TurnOnToneMapping() = 0; - - // Set a linear vector color scale for all 3D rendering. - // A value of [1.0f, 1.0f, 1.0f] should match non-tone-mapped rendering. - virtual void SetToneMappingScaleLinear( const Vector &scale ) = 0; - - virtual Vector GetToneMappingScaleLinear( void ) = 0; - virtual void SetShadowDepthBiasFactors( float fSlopeScaleDepthBias, float fDepthBias ) = 0; - - // Apply stencil operations to every pixel on the screen without disturbing depth or color buffers - virtual void PerformFullScreenStencilOperation( void ) = 0; - - // Sets lighting origin for the current model (needed to convert directional lights to points) - virtual void SetLightingOrigin( Vector vLightingOrigin ) = 0; - - // Set scissor rect for rendering - virtual void SetScissorRect( const int nLeft, const int nTop, const int nRight, const int nBottom, const bool bEnableScissor ) = 0; - - // Methods used to build the morph accumulator that is read from when HW morph -{ - typedef CRefPtr BaseClass; -public: - CMatRenderContextPtr() {} - CMatRenderContextPtr( IMatRenderContext *pInit ) : BaseClass( pInit ) { if ( BaseClass::m_pObject ) BaseClass::m_pObject->BeginRender(); } - CMatRenderContextPtr( IMaterialSystem *pFrom ) : BaseClass( pFrom->GetRenderContext() ) { if ( BaseClass::m_pObject ) BaseClass::m_pObject->BeginRender(); } - ~CMatRenderContextPtr() { if ( BaseClass::m_pObject ) BaseClass::m_pObject->EndRender(); } - - IMatRenderContext *operator=( IMatRenderContext *p ) { if ( p ) p->BeginRender(); return BaseClass::operator=( p ); } - - void SafeRelease() { if ( BaseClass::m_pObject ) BaseClass::m_pObject->EndRender(); BaseClass::SafeRelease(); } - void AssignAddRef( IMatRenderContext *pFrom ) { if ( BaseClass::m_pObject ) BaseClass::m_pObject->EndRender(); BaseClass::AssignAddRef( pFrom ); BaseClass::m_pObject->BeginRender(); } - - void GetFrom( IMaterialSystem *pFrom ) { AssignAddRef( pFrom->GetRenderContext() ); } - - -private: - CMatRenderContextPtr( const CMatRenderContextPtr &from ); - void operator=( const CMatRenderContextPtr &from ); - -}; - -//----------------------------------------------------------------------------- -// Helper class for begin/end of pix event via constructor/destructor -//----------------------------------------------------------------------------- -#define PIX_VALVE_ORANGE 0xFFF5940F - -class PIXEvent -{ -public: - PIXEvent( IMatRenderContext *pRenderContext, const char *szName, unsigned long color = PIX_VALVE_ORANGE ) - { - m_pRenderContext = pRenderContext; - Assert( m_pRenderContext ); - Assert( szName ); - m_pRenderContext->BeginPIXEvent( color, szName ); - } - ~PIXEvent() - { - m_pRenderContext->EndPIXEvent(); - } -private: - IMatRenderContext *m_pRenderContext; -}; - - -#define PIX_ENABLE 0 // set this to 1 and build engine/studiorender to enable pix events in the engine - -#if PIX_ENABLE -# define PIXEVENT PIXEvent _pixEvent -#else -# define PIXEVENT -#endif - -//----------------------------------------------------------------------------- - -#ifdef MATERIAL_SYSTEM_DEBUG_CALL_QUEUE -#include "tier1/callqueue.h" -#include "tier1/fmtstr.h" -static void DoMatSysQueueMark( IMaterialSystem *pMaterialSystem, const char *psz ) -{ - CMatRenderContextPtr pRenderContext( pMaterialSystem ); - if ( pRenderContext->GetCallQueue() ) - pRenderContext->GetCallQueue()->QueueCall( Plat_DebugString, CUtlEnvelope( psz ) ); -} - -#define MatSysQueueMark( pMaterialSystem, ...) DoMatSysQueueMark( pMaterialSystem, CFmtStr( __VA_ARGS__ ) ) -#else -#define MatSysQueueMark( msg, ...) ((void)0) -#endif - -//----------------------------------------------------------------------------- - -extern IMaterialSystem *materials; -extern IMaterialSystem *g_pMaterialSystem; - -#endif // IMATERIALSYSTEM_H diff --git a/public/materialsystem/imaterialsystemhardwareconfig.h b/public/materialsystem/imaterialsystemhardwareconfig.h deleted file mode 100644 index 56e84eec1..000000000 --- a/public/materialsystem/imaterialsystemhardwareconfig.h +++ /dev/null @@ -1,191 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $Header: $ -// $NoKeywords: $ -//===========================================================================// - -#ifndef IMATERIALSYSTEMHARDWARECONFIG_H -#define IMATERIALSYSTEMHARDWARECONFIG_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "tier1/interface.h" - - -//----------------------------------------------------------------------------- -// Material system interface version -//----------------------------------------------------------------------------- -#define MATERIALSYSTEM_HARDWARECONFIG_INTERFACE_VERSION "MaterialSystemHardwareConfig012" - -// HDRFIXME NOTE: must match common_ps_fxc.h -enum HDRType_t -{ - HDR_TYPE_NONE, - HDR_TYPE_INTEGER, - HDR_TYPE_FLOAT, -}; - -// For now, vertex compression is simply "on or off" (for the sake of simplicity -// and MeshBuilder perf.), but later we may support multiple flavours. -enum VertexCompressionType_t -{ - // This indicates an uninitialized VertexCompressionType_t value - VERTEX_COMPRESSION_INVALID = 0xFFFFFFFF, - - // 'VERTEX_COMPRESSION_NONE' means that no elements of a vertex are compressed - VERTEX_COMPRESSION_NONE = 0, - - // Currently (more stuff may be added as needed), 'VERTEX_COMPRESSION_ON' means: - // - if a vertex contains VERTEX_ELEMENT_NORMAL, this is compressed - // (see CVertexBuilder::CompressedNormal3f) - // - if a vertex contains VERTEX_ELEMENT_USERDATA4 (and a normal - together defining a tangent - // frame, with the binormal reconstructed in the vertex shader), this is compressed - // (see CVertexBuilder::CompressedUserData) - // - if a vertex contains VERTEX_ELEMENT_BONEWEIGHTSx, this is compressed - // (see CVertexBuilder::CompressedBoneWeight3fv) - VERTEX_COMPRESSION_ON = 1 -}; - - -// use DEFCONFIGMETHOD to define time-critical methods that we want to make just return constants -// on the 360, so that the checks will happen at compile time. Not all methods are defined this way -// - just the ones that I perceive as being called often in the frame interval. -#ifdef _X360 -#define DEFCONFIGMETHOD( ret_type, method, xbox_return_value ) \ -FORCEINLINE ret_type method const \ -{ \ - return xbox_return_value; \ -} - - -#else -#define DEFCONFIGMETHOD( ret_type, method, xbox_return_value ) \ -virtual ret_type method const = 0; -#endif - - - -//----------------------------------------------------------------------------- -// Material system configuration -//----------------------------------------------------------------------------- -class IMaterialSystemHardwareConfig -{ -public: - // on xbox, some methods are inlined to return constants - - DEFCONFIGMETHOD( bool, HasDestAlphaBuffer(), true ); - DEFCONFIGMETHOD( bool, HasStencilBuffer(), true ); - virtual int GetFrameBufferColorDepth() const = 0; - virtual int GetSamplerCount() const = 0; - virtual bool HasSetDeviceGammaRamp() const = 0; - DEFCONFIGMETHOD( bool, SupportsCompressedTextures(), true ); - virtual VertexCompressionType_t SupportsCompressedVertices() const = 0; - DEFCONFIGMETHOD( bool, SupportsNormalMapCompression(), true ); - DEFCONFIGMETHOD( bool, SupportsVertexAndPixelShaders(), true ); - DEFCONFIGMETHOD( bool, SupportsPixelShaders_1_4(), true ); - DEFCONFIGMETHOD( bool, SupportsPixelShaders_2_0(), true ); - DEFCONFIGMETHOD( bool, SupportsVertexShaders_2_0(), true ); - virtual int MaximumAnisotropicLevel() const = 0; // 0 means no anisotropic filtering - virtual int MaxTextureWidth() const = 0; - virtual int MaxTextureHeight() const = 0; - virtual int TextureMemorySize() const = 0; - virtual bool SupportsOverbright() const = 0; - virtual bool SupportsCubeMaps() const = 0; - virtual bool SupportsMipmappedCubemaps() const = 0; - virtual bool SupportsNonPow2Textures() const = 0; - - // The number of texture stages represents the number of computations - // we can do in the fixed-function pipeline, it is *not* related to the - // simultaneous number of textures we can use - virtual int GetTextureStageCount() const = 0; - virtual int NumVertexShaderConstants() const = 0; - virtual int NumPixelShaderConstants() const = 0; - virtual int MaxNumLights() const = 0; - virtual bool SupportsHardwareLighting() const = 0; - virtual int MaxBlendMatrices() const = 0; - virtual int MaxBlendMatrixIndices() const = 0; - virtual int MaxTextureAspectRatio() const = 0; - virtual int MaxVertexShaderBlendMatrices() const = 0; - virtual int MaxUserClipPlanes() const = 0; - virtual bool UseFastClipping() const = 0; - - // This here should be the major item looked at when checking for compat - // from anywhere other than the material system shaders - DEFCONFIGMETHOD( int, GetDXSupportLevel(), 98 ); - virtual const char *GetShaderDLLName() const = 0; - - virtual bool ReadPixelsFromFrontBuffer() const = 0; - - // Are dx dynamic textures preferred? - virtual bool PreferDynamicTextures() const = 0; - - DEFCONFIGMETHOD( bool, SupportsHDR(), true ); - - virtual bool HasProjectedBumpEnv() const = 0; - virtual bool SupportsSpheremapping() const = 0; - virtual bool NeedsAAClamp() const = 0; - virtual bool NeedsATICentroidHack() const = 0; - - virtual bool SupportsColorOnSecondStream() const = 0; - virtual bool SupportsStaticPlusDynamicLighting() const = 0; - - // Does our card have a hard time with fillrate - // relative to other cards w/ the same dx level? - virtual bool PreferReducedFillrate() const = 0; - - // This is the max dx support level supported by the card - virtual int GetMaxDXSupportLevel() const = 0; - - // Does the card specify fog color in linear space when sRGBWrites are enabled? - virtual bool SpecifiesFogColorInLinearSpace() const = 0; - - // Does the card support sRGB reads/writes? - DEFCONFIGMETHOD( bool, SupportsSRGB(), true ); - - virtual bool IsAAEnabled() const = 0; // Is antialiasing being used? - - // NOTE: Anything after this was added after shipping HL2. - virtual int GetVertexTextureCount() const = 0; - virtual int GetMaxVertexTextureDimension() const = 0; - - virtual int MaxTextureDepth() const = 0; - - virtual HDRType_t GetHDRType() const = 0; - virtual HDRType_t GetHardwareHDRType() const = 0; - - DEFCONFIGMETHOD( bool, SupportsPixelShaders_2_b(), true ); - virtual bool SupportsStreamOffset() const = 0; - - virtual int StencilBufferBits() const = 0; - virtual int MaxViewports() const = 0; - - virtual void OverrideStreamOffsetSupport( bool bOverrideEnabled, bool bEnableSupport ) = 0; - - virtual int GetShadowFilterMode() const = 0; - - virtual int NeedsShaderSRGBConversion() const = 0; - - DEFCONFIGMETHOD( bool, UsesSRGBCorrectBlending(), true ); - - virtual bool SupportsShaderModel_3_0() const = 0; - virtual bool HasFastVertexTextures() const = 0; - virtual int MaxHWMorphBatchCount() const = 0; - - // Does the board actually support this? - DEFCONFIGMETHOD( bool, ActuallySupportsPixelShaders_2_b(), true ); - - virtual bool SupportsHDRMode( HDRType_t nHDRMode ) const = 0; - - virtual bool GetHDREnabled( void ) const = 0; - virtual void SetHDREnabled( bool bEnable ) = 0; - - virtual bool SupportsBorderColor( void ) const = 0; - virtual bool SupportsFetch4( void ) const = 0; -}; - -#endif // IMATERIALSYSTEMHARDWARECONFIG_H diff --git a/public/materialsystem/imaterialsystemstub.h b/public/materialsystem/imaterialsystemstub.h deleted file mode 100644 index 76cbc6b4c..000000000 --- a/public/materialsystem/imaterialsystemstub.h +++ /dev/null @@ -1,31 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef IMATERIALSYSTEMSTUB_H -#define IMATERIALSYSTEMSTUB_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "materialsystem/imaterialsystem.h" - - -// If you get this interface out of the material system, it'll return an IMaterialSystem -// with everything stubbed. This is used for running the client in text mode. -#define MATERIAL_SYSTEM_STUB_INTERFACE_VERSION "VMaterialSystemStub001" - - -class IMaterialSystemStub : public IMaterialSystem -{ -public: - // If this is called, then the stub will call through to the real material - // system in some functions. - virtual void SetRealMaterialSystem( IMaterialSystem *pSys ) = 0; -}; - - -#endif // IMATERIALSYSTEMSTUB_H diff --git a/public/materialsystem/imaterialvar.h b/public/materialsystem/imaterialvar.h deleted file mode 100644 index c8e3f605f..000000000 --- a/public/materialsystem/imaterialvar.h +++ /dev/null @@ -1,245 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// - -#ifndef IMATERIALVAR_H -#define IMATERIALVAR_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/platform.h" -#include "tier1/utlsymbol.h" -#include "mathlib/vector4d.h" -class IMaterial; -class VMatrix; -class ITexture; - -#define MAKE_MATERIALVAR_FOURCC(ch0, ch1, ch2, ch3) \ - ((unsigned long)(ch0) | ((unsigned long)(ch1) << 8) | \ - ((unsigned long)(ch2) << 16) | ((unsigned long)(ch3) << 24 )) - -// This fourcc is reserved. -#define FOURCC_UNKNOWN MAKE_MATERIALVAR_FOURCC('U','N','K','N') - - -//----------------------------------------------------------------------------- -// Various material var types -//----------------------------------------------------------------------------- -enum MaterialVarType_t -{ - MATERIAL_VAR_TYPE_FLOAT = 0, - MATERIAL_VAR_TYPE_STRING, - MATERIAL_VAR_TYPE_VECTOR, - MATERIAL_VAR_TYPE_TEXTURE, - MATERIAL_VAR_TYPE_INT, - MATERIAL_VAR_TYPE_FOURCC, - MATERIAL_VAR_TYPE_UNDEFINED, - MATERIAL_VAR_TYPE_MATRIX, - MATERIAL_VAR_TYPE_MATERIAL, -}; - -typedef unsigned short MaterialVarSym_t; - -class IMaterialVar -{ -public: - typedef unsigned long FourCC; - -protected: - // base data and accessors - char* m_pStringVal; - int m_intVal; - Vector4D m_VecVal; - - // member data. total = 4 bytes - uint8 m_Type : 4; - uint8 m_nNumVectorComps : 3; - uint8 m_bFakeMaterialVar : 1; - uint8 m_nTempIndex; - CUtlSymbol m_Name; - -public: - // class factory methods - static IMaterialVar* Create( IMaterial* pMaterial, char const* pKey, VMatrix const& matrix ); - static IMaterialVar* Create( IMaterial* pMaterial, char const* pKey, char const* pVal ); - static IMaterialVar* Create( IMaterial* pMaterial, char const* pKey, float* pVal, int numcomps ); - static IMaterialVar* Create( IMaterial* pMaterial, char const* pKey, float val ); - static IMaterialVar* Create( IMaterial* pMaterial, char const* pKey, int val ); - static IMaterialVar* Create( IMaterial* pMaterial, char const* pKey ); - static void Destroy( IMaterialVar* pVar ); - static MaterialVarSym_t GetSymbol( char const* pName ); - static MaterialVarSym_t FindSymbol( char const* pName ); - static bool SymbolMatches( char const* pName, MaterialVarSym_t symbol ); - static void DeleteUnreferencedTextures( bool enable ); - - virtual ITexture *GetTextureValue( void ) = 0; - - virtual char const * GetName( void ) const = 0; - virtual MaterialVarSym_t GetNameAsSymbol() const = 0; - - virtual void SetFloatValue( float val ) = 0; - - virtual void SetIntValue( int val ) = 0; - - virtual void SetStringValue( char const *val ) = 0; - virtual char const * GetStringValue( void ) const = 0; - - // Use FourCC values to pass app-defined data structures between - // the proxy and the shader. The shader should ignore the data if - // its FourCC type not correct. - virtual void SetFourCCValue( FourCC type, void *pData ) = 0; - virtual void GetFourCCValue( FourCC *type, void **ppData ) = 0; - - // Vec (dim 2-4) - virtual void SetVecValue( float const* val, int numcomps ) = 0; - virtual void SetVecValue( float x, float y ) = 0; - virtual void SetVecValue( float x, float y, float z ) = 0; - virtual void SetVecValue( float x, float y, float z, float w ) = 0; - virtual void GetLinearVecValue( float *val, int numcomps ) const = 0; - - // revisit: is this a good interface for textures? - virtual void SetTextureValue( ITexture * ) = 0; - - virtual IMaterial * GetMaterialValue( void ) = 0; - virtual void SetMaterialValue( IMaterial * ) = 0; - - virtual bool IsDefined() const = 0; - virtual void SetUndefined() = 0; - - // Matrix - virtual void SetMatrixValue( VMatrix const& matrix ) = 0; - virtual const VMatrix &GetMatrixValue( ) = 0; - virtual bool MatrixIsIdentity() const = 0; - - // Copy.... - virtual void CopyFrom( IMaterialVar *pMaterialVar ) = 0; - - virtual void SetValueAutodetectType( char const *val ) = 0; - - virtual IMaterial * GetOwningMaterial() = 0; - - //set just 1 component - virtual void SetVecComponentValue( float fVal, int nComponent ) = 0; - -protected: - virtual int GetIntValueInternal( void ) const = 0; - virtual float GetFloatValueInternal( void ) const = 0; - virtual float const* GetVecValueInternal( ) const = 0; - virtual void GetVecValueInternal( float *val, int numcomps ) const = 0; - virtual int VectorSizeInternal() const = 0; - -public: - FORCEINLINE MaterialVarType_t GetType( void ) const - { - return ( MaterialVarType_t )m_Type; - } - - FORCEINLINE bool IsTexture() const - { - return m_Type == MATERIAL_VAR_TYPE_TEXTURE; - } - - FORCEINLINE operator ITexture*() - { - return GetTextureValue(); - } - - // NOTE: Fast methods should only be called in thread-safe situations - FORCEINLINE int GetIntValueFast( void ) const - { - // Set methods for float and vector update this - return m_intVal; - } - - FORCEINLINE float GetFloatValueFast( void ) const - { - return m_VecVal[0]; - } - - FORCEINLINE float const* GetVecValueFast( ) const - { - return m_VecVal.Base(); - } - - FORCEINLINE void GetVecValueFast( float *val, int numcomps ) const - { - Assert( ( numcomps >0 ) && ( numcomps <= 4 ) ); - for( int i=0 ; i < numcomps; i++ ) - { - val[i] = m_VecVal[ i ]; - } - } - - FORCEINLINE int VectorSizeFast() const - { - return m_nNumVectorComps; - } - -#ifdef FAST_MATERIALVAR_ACCESS - FORCEINLINE int GetIntValue( void ) const - { - return GetIntValueFast(); - } - - FORCEINLINE float GetFloatValue( void ) const - { - return GetFloatValueFast(); - } - - FORCEINLINE float const* GetVecValue( ) const - { - return GetVecValueFast(); - } - - FORCEINLINE void GetVecValue( float *val, int numcomps ) const - { - GetVecValueFast( val, numcomps ); - } - - FORCEINLINE int VectorSize() const - { - return VectorSizeFast(); - } -#else // !FAST_MATERIALVAR_ACCESS - FORCEINLINE int GetIntValue( void ) const - { - return GetIntValueInternal(); - } - - FORCEINLINE float GetFloatValue( void ) const - { - return GetFloatValueInternal(); - } - - FORCEINLINE float const* GetVecValue( ) const - { - return GetVecValueInternal(); - } - - FORCEINLINE void GetVecValue( float *val, int numcomps ) const - { - return GetVecValueInternal( val, numcomps ); - } - - FORCEINLINE int VectorSize() const - { - return VectorSizeInternal(); - } -#endif - -private: - FORCEINLINE void SetTempIndex( int nIndex ) - { - m_nTempIndex = nIndex; - } - - friend void EnableThreadedMaterialVarAccess( bool bEnable, IMaterialVar **ppParams, int nVarCount ); -}; - -#endif // IMATERIALVAR_H diff --git a/public/materialsystem/imesh.h b/public/materialsystem/imesh.h deleted file mode 100644 index 8ed84e856..000000000 --- a/public/materialsystem/imesh.h +++ /dev/null @@ -1,3750 +0,0 @@ -//==== Copyright 1996-2005, Valve Corporation, All rights reserved. =======// -// -// Purpose: -// -//===========================================================================// - -#ifndef IMESH_H -#define IMESH_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/interface.h" -#include "materialsystem/imaterial.h" -#include -#include -#include "tier0/dbg.h" -#include "tier2/meshutils.h" - - -//----------------------------------------------------------------------------- -// forward declarations -//----------------------------------------------------------------------------- -class IMaterial; -class CMeshBuilder; -class IMaterialVar; -typedef uint64 VertexFormat_t; - - -//----------------------------------------------------------------------------- -// Define this to find write-combine problems -//----------------------------------------------------------------------------- -#ifdef _DEBUG -//#ifndef DEBUG_WRITE_COMBINE -//#define DEBUG_WRITE_COMBINE 1 -//#endif -#endif - - -//----------------------------------------------------------------------------- -// The Vertex Buffer interface -//----------------------------------------------------------------------------- -enum -{ - VERTEX_MAX_TEXTURE_COORDINATES = 8, - BONE_MATRIX_INDEX_INVALID = 255 -}; - -// Internal maximums for sizes. Don't use directly, use IMaterialSystem::GetMaxToRender() -enum -{ - INDEX_BUFFER_SIZE = 32768, - DYNAMIC_VERTEX_BUFFER_MEMORY = ( 1024 + 512 ) * 1024, - DYNAMIC_VERTEX_BUFFER_MEMORY_SMALL = 384 * 1024, // Only allocate this much during map transitions -}; - -// Vertex fields must be written in well-defined order to achieve write combining, -// which is a perf booster -enum WriteCombineOrdering_t -{ - MB_FIELD_NONE = -1, - MB_FIELD_POSITION = 0, - MB_FIELD_BONE_WEIGHTS, - MB_FIELD_BONE_INDEX, - MB_FIELD_NORMAL, - MB_FIELD_COLOR, - MB_FIELD_SPECULAR, - MB_FIELD_TEXCOORD_FIRST, - MB_FIELD_TEXCOORD_LAST = MB_FIELD_TEXCOORD_FIRST + VERTEX_MAX_TEXTURE_COORDINATES - 1, - MB_FIELD_TANGENT_S, - MB_FIELD_TANGENT_T, - MB_FIELD_USERDATA, -}; - -#define MB_FIELD_TEXCOORD( nStage ) ( MB_FIELD_TEXCOORD_FIRST + ( nStage ) ) - -struct VertexDesc_t -{ - // These can be set to zero if there are pointers to dummy buffers, when the - // actual buffer format doesn't contain the data but it needs to be safe to - // use all the CMeshBuilder functions. - int m_VertexSize_Position; - int m_VertexSize_BoneWeight; - int m_VertexSize_BoneMatrixIndex; - int m_VertexSize_Normal; - int m_VertexSize_Color; - int m_VertexSize_Specular; - int m_VertexSize_TexCoord[VERTEX_MAX_TEXTURE_COORDINATES]; - int m_VertexSize_TangentS; - int m_VertexSize_TangentT; - int m_VertexSize_Wrinkle; - - int m_VertexSize_UserData; - - int m_ActualVertexSize; // Size of the vertices.. Some of the m_VertexSize_ elements above - // are set to this value and some are set to zero depending on which - // fields exist in a buffer's vertex format. - - // The type of compression applied to this vertex data - VertexCompressionType_t m_CompressionType; - - // Number of bone weights per vertex... - int m_NumBoneWeights; - - // Pointers to our current vertex data - float *m_pPosition; - - float *m_pBoneWeight; - -#ifndef NEW_SKINNING - unsigned char *m_pBoneMatrixIndex; -#else - float *m_pBoneMatrixIndex; -#endif - - float *m_pNormal; - - unsigned char *m_pColor; - unsigned char *m_pSpecular; - float *m_pTexCoord[VERTEX_MAX_TEXTURE_COORDINATES]; - - // Tangent space *associated with one particular set of texcoords* - float *m_pTangentS; - float *m_pTangentT; - - float *m_pWrinkle; - - // user data - float *m_pUserData; - - // The first vertex index (used for buffered vertex buffers, or cards that don't support stream offset) - int m_nFirstVertex; - - // The offset in bytes of the memory we're writing into - // from the start of the D3D buffer (will be 0 for static meshes) - unsigned int m_nOffset; - -#ifdef DEBUG_WRITE_COMBINE - int m_nLastWrittenField; - unsigned char* m_pLastWrittenAddress; -#endif -}; - -struct IndexDesc_t -{ - // Pointers to the index data - unsigned short *m_pIndices; - - // The offset in bytes of the memory we're writing into - // from the start of the D3D buffer (will be 0 for static meshes) - unsigned int m_nOffset; - - // The first index (used for buffered index buffers, or cards that don't support stream offset) - unsigned int m_nFirstIndex; - - // 1 if the device is active, 0 if the device isn't active. - // Faster than doing if checks for null m_pIndices if someone is - // trying to write the m_pIndices while the device is inactive. - unsigned char m_nIndexSize; -}; - - -//----------------------------------------------------------------------------- -// The Mesh memory descriptor -//----------------------------------------------------------------------------- -struct MeshDesc_t : public VertexDesc_t, public IndexDesc_t -{ -}; - - -//----------------------------------------------------------------------------- -// Standard vertex formats for models -//----------------------------------------------------------------------------- -struct ModelVertexDX7_t -{ - Vector m_vecPosition; - Vector2D m_flBoneWeights; - unsigned int m_nBoneIndices; - Vector m_vecNormal; - unsigned int m_nColor; // ARGB - Vector2D m_vecTexCoord; -}; - -struct ModelVertexDX8_t : public ModelVertexDX7_t -{ - Vector4D m_vecUserData; -}; - - -//----------------------------------------------------------------------------- -// Utility methods for buffer builders -//----------------------------------------------------------------------------- -inline float *OffsetFloatPointer( float *pBufferPointer, int nVertexCount, int vertexSize ) -{ - return reinterpret_cast( - reinterpret_cast(pBufferPointer) + - nVertexCount * vertexSize); -} - -inline const float *OffsetFloatPointer( const float *pBufferPointer, int nVertexCount, int vertexSize ) -{ - return reinterpret_cast( - reinterpret_cast(pBufferPointer) + - nVertexCount * vertexSize); -} - -inline void IncrementFloatPointer( float* &pBufferPointer, int vertexSize ) -{ - pBufferPointer = reinterpret_cast( reinterpret_cast( pBufferPointer ) + vertexSize ); -} - - -//----------------------------------------------------------------------------- -// Used in lists of indexed primitives. -//----------------------------------------------------------------------------- -class CPrimList -{ -public: - CPrimList(); - CPrimList( int nFirstIndex, int nIndexCount ); - - int m_FirstIndex; - int m_NumIndices; -}; - -inline CPrimList::CPrimList() -{ -} - -inline CPrimList::CPrimList( int nFirstIndex, int nIndexCount ) -{ - m_FirstIndex = nFirstIndex; - m_NumIndices = nIndexCount; -} - -abstract_class IVertexBuffer -{ -public: - // NOTE: The following two methods are only valid for static vertex buffers - // Returns the number of vertices and the format of the vertex buffer - virtual int VertexCount() const = 0; - virtual VertexFormat_t GetVertexFormat() const = 0; - - // Is this vertex buffer dynamic? - virtual bool IsDynamic() const = 0; - - // NOTE: For dynamic vertex buffers only! - // Casts the memory of the dynamic vertex buffer to the appropriate type - virtual void BeginCastBuffer( VertexFormat_t format ) = 0; - virtual void EndCastBuffer() = 0; - - // Returns the number of vertices that can still be written into the buffer - virtual int GetRoomRemaining() const = 0; - - virtual bool Lock( int nVertexCount, bool bAppend, VertexDesc_t &desc ) = 0; - virtual void Unlock( int nVertexCount, VertexDesc_t &desc ) = 0; - - // Spews the mesh data - virtual void Spew( int nVertexCount, const VertexDesc_t &desc ) = 0; - - // Call this in debug mode to make sure our data is good. - virtual void ValidateData( int nVertexCount, const VertexDesc_t & desc ) = 0; -}; - -abstract_class IIndexBuffer -{ -public: - // NOTE: The following two methods are only valid for static index buffers - // Returns the number of indices and the format of the index buffer - virtual int IndexCount() const = 0; - virtual MaterialIndexFormat_t IndexFormat() const = 0; - - // Is this index buffer dynamic? - virtual bool IsDynamic() const = 0; - - // NOTE: For dynamic index buffers only! - // Casts the memory of the dynamic index buffer to the appropriate type - virtual void BeginCastBuffer( MaterialIndexFormat_t format ) = 0; - virtual void EndCastBuffer() = 0; - - // Returns the number of indices that can still be written into the buffer - virtual int GetRoomRemaining() const = 0; - - // Locks, unlocks the index buffer - virtual bool Lock( int nMaxIndexCount, bool bAppend, IndexDesc_t &desc ) = 0; - virtual void Unlock( int nWrittenIndexCount, IndexDesc_t &desc ) = 0; - - // FIXME: Remove this!! - // Locks, unlocks the index buffer for modify - virtual void ModifyBegin( bool bReadOnly, int nFirstIndex, int nIndexCount, IndexDesc_t& desc ) = 0; - virtual void ModifyEnd( IndexDesc_t& desc ) = 0; - - // Spews the mesh data - virtual void Spew( int nIndexCount, const IndexDesc_t &desc ) = 0; - - // Ensures the data in the index buffer is valid - virtual void ValidateData( int nIndexCount, const IndexDesc_t &desc ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Interface to the mesh - needs to contain an IVertexBuffer and an IIndexBuffer to emulate old mesh behavior -//----------------------------------------------------------------------------- -abstract_class IMesh : public IVertexBuffer, public IIndexBuffer -{ -public: - // ----------------------------------- - - // Sets/gets the primitive type - virtual void SetPrimitiveType( MaterialPrimitiveType_t type ) = 0; - - // Draws the mesh - virtual void Draw( int nFirstIndex = -1, int nIndexCount = 0 ) = 0; - - virtual void SetColorMesh( IMesh *pColorMesh, int nVertexOffset ) = 0; - - // Draw a list of (lists of) primitives. Batching your lists together that use - // the same lightmap, material, vertex and index buffers with multipass shaders - // can drastically reduce state-switching overhead. - // NOTE: this only works with STATIC meshes. - virtual void Draw( CPrimList *pLists, int nLists ) = 0; - - // Copy verts and/or indices to a mesh builder. This only works for temp meshes! - virtual void CopyToMeshBuilder( - int iStartVert, // Which vertices to copy. - int nVerts, - int iStartIndex, // Which indices to copy. - int nIndices, - int indexOffset, // This is added to each index. - CMeshBuilder &builder ) = 0; - - // Spews the mesh data - virtual void Spew( int nVertexCount, int nIndexCount, const MeshDesc_t &desc ) = 0; - - // Call this in debug mode to make sure our data is good. - virtual void ValidateData( int nVertexCount, int nIndexCount, const MeshDesc_t &desc ) = 0; - - // New version - // Locks/unlocks the mesh, providing space for nVertexCount and nIndexCount. - // nIndexCount of -1 means don't lock the index buffer... - virtual void LockMesh( int nVertexCount, int nIndexCount, MeshDesc_t &desc ) = 0; - virtual void ModifyBegin( int nFirstVertex, int nVertexCount, int nFirstIndex, int nIndexCount, MeshDesc_t& desc ) = 0; - virtual void ModifyEnd( MeshDesc_t& desc ) = 0; - virtual void UnlockMesh( int nVertexCount, int nIndexCount, MeshDesc_t &desc ) = 0; - - virtual void ModifyBeginEx( bool bReadOnly, int nFirstVertex, int nVertexCount, int nFirstIndex, int nIndexCount, MeshDesc_t &desc ) = 0; - - virtual void SetFlexMesh( IMesh *pMesh, int nVertexOffset ) = 0; - - virtual void DisableFlexMesh() = 0; - - virtual void MarkAsDrawn() = 0; - -#if defined( _X360 ) - virtual unsigned ComputeMemoryUsed() = 0; -#endif -}; - - -#include "meshreader.h" - -#define INVALID_BUFFER_OFFSET 0xFFFFFFFFUL - -//----------------------------------------------------------------------------- -// -// Helper class used to define vertex buffers -// -//----------------------------------------------------------------------------- -class CVertexBuilder : private VertexDesc_t -{ -public: - CVertexBuilder(); - CVertexBuilder( IVertexBuffer *pVertexBuffer, VertexFormat_t fmt = 0 ); - ~CVertexBuilder(); - - // Begins, ends modification of the index buffer (returns true if the lock succeeded) - // A lock may not succeed if append is set to true and there isn't enough room - // NOTE: Append is only used with dynamic index buffers; it's ignored for static buffers - bool Lock( int nMaxIndexCount, bool bAppend = false ); - void Unlock(); - - // Spews the current data - // NOTE: Can only be called during a lock/unlock block - void SpewData(); - - // Returns the number of indices we can fit into the buffer without needing to discard - int GetRoomRemaining() const; - - // Binds this vertex buffer - void Bind( IMatRenderContext *pContext, int nStreamID, VertexFormat_t usage = 0 ); - - // Returns the byte offset - int Offset() const; - - // This must be called before Begin, if a vertex buffer with a compressed format is to be used - void SetCompressionType( VertexCompressionType_t compressionType ); - void ValidateCompressionType(); - - void Begin( IVertexBuffer *pVertexBuffer, int nVertexCount, int *nFirstVertex ); - void Begin( IVertexBuffer *pVertexBuffer, int nVertexCount ); - - // Use this when you're done writing - // Set bDraw to true to call m_pMesh->Draw automatically. - void End( bool bSpewData = false ); - - // Locks the vertex buffer to modify existing data - // Passing nVertexCount == -1 says to lock all the vertices for modification. - void BeginModify( IVertexBuffer *pVertexBuffer, int nFirstVertex = 0, int nVertexCount = -1 ); - void EndModify( bool bSpewData = false ); - - // returns the number of vertices - int VertexCount() const; - - // Returns the total number of vertices across all Locks() - int TotalVertexCount() const; - - // Resets the mesh builder so it points to the start of everything again - void Reset(); - - // Returns the size of the vertex - int VertexSize() { return m_ActualVertexSize; } - - // returns the data size of a given texture coordinate - int TextureCoordinateSize( int nTexCoordNumber ) { return m_VertexSize_TexCoord[ nTexCoordNumber ]; } - - // Returns the base vertex memory pointer - void* BaseVertexData(); - - // Selects the nth Vertex and Index - void SelectVertex( int idx ); - - // Advances the current vertex and index by one - void AdvanceVertex(); - void AdvanceVertices( int nVerts ); - - int GetCurrentVertex() const; - int GetFirstVertex() const; - - // Data retrieval... - const float *Position() const; - - const float *Normal() const; - - unsigned int Color() const; - - unsigned char *Specular() const; - - const float *TexCoord( int stage ) const; - - const float *TangentS() const; - const float *TangentT() const; - - const float *BoneWeight() const; - float Wrinkle() const; - - int NumBoneWeights() const; -#ifndef NEW_SKINNING - unsigned char *BoneMatrix() const; -#else - float *BoneMatrix() const; -#endif - - // position setting - void Position3f( float x, float y, float z ); - void Position3fv( const float *v ); - - // normal setting - void Normal3f( float nx, float ny, float nz ); - void Normal3fv( const float *n ); - void NormalDelta3fv( const float *n ); - void NormalDelta3f( float nx, float ny, float nz ); - // normal setting (templatized for code which needs to support compressed vertices) - template void CompressedNormal3f( float nx, float ny, float nz ); - template void CompressedNormal3fv( const float *n ); - - // color setting - void Color3f( float r, float g, float b ); - void Color3fv( const float *rgb ); - void Color4f( float r, float g, float b, float a ); - void Color4fv( const float *rgba ); - - // Faster versions of color - void Color3ub( unsigned char r, unsigned char g, unsigned char b ); - void Color3ubv( unsigned char const* rgb ); - void Color4ub( unsigned char r, unsigned char g, unsigned char b, unsigned char a ); - void Color4ubv( unsigned char const* rgba ); - - // specular color setting - void Specular3f( float r, float g, float b ); - void Specular3fv( const float *rgb ); - void Specular4f( float r, float g, float b, float a ); - void Specular4fv( const float *rgba ); - - // Faster version of specular - void Specular3ub( unsigned char r, unsigned char g, unsigned char b ); - void Specular3ubv( unsigned char const *c ); - void Specular4ub( unsigned char r, unsigned char g, unsigned char b, unsigned char a ); - void Specular4ubv( unsigned char const *c ); - - // texture coordinate setting - void TexCoord1f( int stage, float s ); - void TexCoord2f( int stage, float s, float t ); - void TexCoord2fv( int stage, const float *st ); - void TexCoord3f( int stage, float s, float t, float u ); - void TexCoord3fv( int stage, const float *stu ); - void TexCoord4f( int stage, float s, float t, float u, float w ); - void TexCoord4fv( int stage, const float *stuv ); - - void TexCoordSubRect2f( int stage, float s, float t, float offsetS, float offsetT, float scaleS, float scaleT ); - void TexCoordSubRect2fv( int stage, const float *st, const float *offset, const float *scale ); - - // tangent space - void TangentS3f( float sx, float sy, float sz ); - void TangentS3fv( const float* s ); - - void TangentT3f( float tx, float ty, float tz ); - void TangentT3fv( const float* t ); - - // Wrinkle - void Wrinkle1f( float flWrinkle ); - - // bone weights - void BoneWeight( int idx, float weight ); - // bone weights (templatized for code which needs to support compressed vertices) - template void CompressedBoneWeight3fv( const float * pWeights ); - - // bone matrix index - void BoneMatrix( int idx, int matrixIndex ); - - // Generic per-vertex data - void UserData( const float* pData ); - // Generic per-vertex data (templatized for code which needs to support compressed vertices) - template void CompressedUserData( const float* pData ); - - // Fast Vertex! No need to call advance vertex, and no random access allowed. - // WARNING - these are low level functions that are intended only for use - // in the software vertex skinner. - void FastVertex( const ModelVertexDX7_t &vertex ); - void FastVertexSSE( const ModelVertexDX7_t &vertex ); - - // store 4 dx7 vertices fast. for special sse dx7 pipeline - void Fast4VerticesSSE( - ModelVertexDX7_t const *vtx_a, - ModelVertexDX7_t const *vtx_b, - ModelVertexDX7_t const *vtx_c, - ModelVertexDX7_t const *vtx_d); - - void FastVertex( const ModelVertexDX8_t &vertex ); - void FastVertexSSE( const ModelVertexDX8_t &vertex ); - - // Add number of verts and current vert since FastVertex routines do not update. - void FastAdvanceNVertices( int n ); - -#if defined( _X360 ) - void VertexDX8ToX360( const ModelVertexDX8_t &vertex ); -#endif - - // FIXME: Remove! Backward compat so we can use this from a CMeshBuilder. - void AttachBegin( IMesh* pMesh, int nMaxVertexCount, const MeshDesc_t &desc ); - void AttachEnd(); - void AttachBeginModify( IMesh* pMesh, int nFirstVertex, int nVertexCount, const MeshDesc_t &desc ); - void AttachEndModify(); - -private: - // The vertex buffer we're modifying - IVertexBuffer *m_pVertexBuffer; - - // Used to make sure Begin/End calls and BeginModify/EndModify calls match. - bool m_bModify; - - // Max number of indices and vertices - int m_nMaxVertexCount; - - // Number of indices and vertices - int m_nVertexCount; - - // The current vertex and index - mutable int m_nCurrentVertex; - - // Optimization: Pointer to the current pos, norm, texcoord, and color - mutable float *m_pCurrPosition; - mutable float *m_pCurrNormal; - mutable float *m_pCurrTexCoord[VERTEX_MAX_TEXTURE_COORDINATES]; - mutable unsigned char *m_pCurrColor; - - // Total number of vertices appended - int m_nTotalVertexCount; - - // First vertex buffer offset + index - unsigned int m_nBufferOffset; - unsigned int m_nBufferFirstVertex; - -#if ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 ) - // Debug checks to make sure we write userdata4/tangents AFTER normals - bool m_bWrittenNormal : 1; - bool m_bWrittenUserData : 1; -#endif - - friend class CMeshBuilder; -}; - - -//----------------------------------------------------------------------------- -// -// Inline methods of CVertexBuilder -// -//----------------------------------------------------------------------------- -inline CVertexBuilder::CVertexBuilder() -{ - m_pVertexBuffer = NULL; - m_nBufferOffset = INVALID_BUFFER_OFFSET; - m_nBufferFirstVertex = 0; - m_nVertexCount = 0; - m_nCurrentVertex = 0; - m_nMaxVertexCount = 0; - m_nTotalVertexCount = 0; - m_CompressionType = VERTEX_COMPRESSION_INVALID; - -#ifdef _DEBUG - m_pCurrPosition = NULL; - m_pCurrNormal = NULL; - m_pCurrColor = NULL; - memset( m_pCurrTexCoord, 0, sizeof( m_pCurrTexCoord ) ); - m_bModify = false; -#endif -} - -inline CVertexBuilder::CVertexBuilder( IVertexBuffer *pVertexBuffer, VertexFormat_t fmt ) -{ - m_pVertexBuffer = pVertexBuffer; - m_nBufferOffset = INVALID_BUFFER_OFFSET; - m_nBufferFirstVertex = 0; - m_nVertexCount = 0; - m_nCurrentVertex = 0; - m_nMaxVertexCount = 0; - m_nTotalVertexCount = 0; - m_CompressionType = VERTEX_COMPRESSION_INVALID; - - if ( m_pVertexBuffer->IsDynamic() ) - { - m_pVertexBuffer->BeginCastBuffer( fmt ); - } - else - { - Assert( m_pVertexBuffer->GetVertexFormat() == fmt ); - } - -#ifdef _DEBUG - m_pCurrPosition = NULL; - m_pCurrNormal = NULL; - m_pCurrColor = NULL; - memset( m_pCurrTexCoord, 0, sizeof( m_pCurrTexCoord ) ); - m_bModify = false; -#endif -} - -inline CVertexBuilder::~CVertexBuilder() -{ - if ( m_pVertexBuffer && m_pVertexBuffer->IsDynamic() ) - { - m_pVertexBuffer->EndCastBuffer(); - } -} - -//----------------------------------------------------------------------------- -// Begins, ends modification of the index buffer -//----------------------------------------------------------------------------- -inline bool CVertexBuilder::Lock( int nMaxVertexCount, bool bAppend ) -{ - Assert( m_pVertexBuffer ); - m_bModify = false; - m_nMaxVertexCount = nMaxVertexCount; - bool bFirstLock = ( m_nBufferOffset == INVALID_BUFFER_OFFSET ); - if ( bFirstLock ) - { - bAppend = false; - } - if ( !bAppend ) - { - m_nTotalVertexCount = 0; - } - - // Lock the vertex buffer - if ( !m_pVertexBuffer->Lock( m_nMaxVertexCount, bAppend, *this ) ) - { - m_nMaxVertexCount = 0; - return false; - } - - Reset(); - - if ( bFirstLock ) - { - m_nBufferOffset = m_nOffset; - m_nBufferFirstVertex = m_nFirstVertex; - } - - return true; -} - -inline void CVertexBuilder::Unlock() -{ - Assert( !m_bModify && m_pVertexBuffer ); - -#ifdef _DEBUG - m_pVertexBuffer->ValidateData( m_nVertexCount, *this ); -#endif - - m_pVertexBuffer->Unlock( m_nVertexCount, *this ); - m_nTotalVertexCount += m_nVertexCount; - - m_nMaxVertexCount = 0; - -#ifdef _DEBUG - // Null out our data... - m_pCurrPosition = NULL; - m_pCurrNormal = NULL; - m_pCurrColor = NULL; - memset( m_pCurrTexCoord, 0, sizeof( m_pCurrTexCoord ) ); - memset( static_cast( this ), 0, sizeof(VertexDesc_t) ); -#endif -} - -inline void CVertexBuilder::SpewData() -{ - m_pVertexBuffer->Spew( m_nVertexCount, *this ); -} - - -//----------------------------------------------------------------------------- -// Binds this vertex buffer -//----------------------------------------------------------------------------- -inline void CVertexBuilder::Bind( IMatRenderContext *pContext, int nStreamID, VertexFormat_t usage ) -{ - if ( m_pVertexBuffer && ( m_nBufferOffset != INVALID_BUFFER_OFFSET ) ) - { - pContext->BindVertexBuffer( nStreamID, m_pVertexBuffer, m_nBufferOffset, - m_nFirstVertex, m_nTotalVertexCount, usage ? usage : m_pVertexBuffer->GetVertexFormat() ); - } - else - { - pContext->BindVertexBuffer( nStreamID, NULL, 0, 0, 0, 0 ); - } -} - - -//----------------------------------------------------------------------------- -// Returns the byte offset -//----------------------------------------------------------------------------- -inline int CVertexBuilder::Offset() const -{ - return m_nBufferOffset; -} - -inline int CVertexBuilder::GetFirstVertex() const -{ - return m_nBufferFirstVertex; -} - -//----------------------------------------------------------------------------- -// Specify the type of vertex compression that this CMeshBuilder will perform -//----------------------------------------------------------------------------- -inline void CVertexBuilder::SetCompressionType( VertexCompressionType_t compressionType ) -{ - // The real purpose of this method is to allow us to emit a Warning in Begin() - m_CompressionType = compressionType; -} - -inline void CVertexBuilder::ValidateCompressionType() -{ -#ifdef _DEBUG - VertexCompressionType_t vbCompressionType = CompressionType( m_pVertexBuffer->GetVertexFormat() ); - if ( vbCompressionType != VERTEX_COMPRESSION_NONE ) - { - Assert( m_CompressionType == vbCompressionType ); - if ( m_CompressionType != vbCompressionType ) - { - Warning( "ERROR: CVertexBuilder::SetCompressionType() must be called to specify the same vertex compression type (%s) as the vertex buffer being modified." - "Junk vertices will be rendered, or there will be a crash in CVertexBuilder!\n", - vbCompressionType == VERTEX_COMPRESSION_ON ? "VERTEX_COMPRESSION_ON" : "VERTEX_COMPRESSION_NONE" ); - } - // Never use vertex compression for dynamic VBs (the conversions can really hurt perf) - Assert( !m_pVertexBuffer->IsDynamic() ); - } -#endif -} - -inline void CVertexBuilder::Begin( IVertexBuffer *pVertexBuffer, int nVertexCount ) -{ - Assert( pVertexBuffer && (!m_pVertexBuffer) ); - - m_pVertexBuffer = pVertexBuffer; - m_bModify = false; - - m_nMaxVertexCount = nVertexCount; - m_nVertexCount = 0; - - // Make sure SetCompressionType was called correctly, if this VB is compressed - ValidateCompressionType(); - - // Lock the vertex and index buffer - m_pVertexBuffer->Lock( m_nMaxVertexCount, false, *this ); - - // Point to the start of the buffers.. - Reset(); -} - - -//----------------------------------------------------------------------------- -// Use this when you're done modifying the mesh -//----------------------------------------------------------------------------- -inline void CVertexBuilder::End( bool bSpewData ) -{ - // Make sure they called Begin() - Assert( !m_bModify ); - - if ( bSpewData ) - { - m_pVertexBuffer->Spew( m_nVertexCount, *this ); - } - -#ifdef _DEBUG - m_pVertexBuffer->ValidateData( m_nVertexCount, *this ); -#endif - - // Unlock our buffers - m_pVertexBuffer->Unlock( m_nVertexCount, *this ); - - m_pVertexBuffer = 0; - m_nMaxVertexCount = 0; - - m_CompressionType = VERTEX_COMPRESSION_INVALID; - -#ifdef _DEBUG - // Null out our pointers... - m_pCurrPosition = NULL; - m_pCurrNormal = NULL; - m_pCurrColor = NULL; - memset( m_pCurrTexCoord, 0, sizeof( m_pCurrTexCoord ) ); - memset( static_cast< VertexDesc_t* >( this ), 0, sizeof(VertexDesc_t) ); -#endif -} - - -//----------------------------------------------------------------------------- -// FIXME: Remove! Backward compat so we can use this from a CMeshBuilder. -//----------------------------------------------------------------------------- -inline void CVertexBuilder::AttachBegin( IMesh* pMesh, int nMaxVertexCount, const MeshDesc_t &desc ) -{ - m_pVertexBuffer = pMesh; - memcpy( static_cast( this ), static_cast( &desc ), sizeof(VertexDesc_t) ); - m_nMaxVertexCount = nMaxVertexCount; - m_NumBoneWeights = m_NumBoneWeights == 0 ? 0 : 2; // Two weights if any - m_nVertexCount = 0; - m_bModify = false; - - // Make sure SetCompressionType was called correctly, if this VB is compressed - ValidateCompressionType(); - - if ( m_nBufferOffset == INVALID_BUFFER_OFFSET ) - { - m_nTotalVertexCount = 0; - m_nBufferOffset = static_cast< const VertexDesc_t* >( &desc )->m_nOffset; - m_nBufferFirstVertex = desc.m_nFirstVertex; - } -} - -inline void CVertexBuilder::AttachEnd() -{ - // Make sure they called Begin() - Assert( !m_bModify ); - - m_nMaxVertexCount = 0; - m_pVertexBuffer = NULL; - - m_CompressionType = VERTEX_COMPRESSION_INVALID; - -#ifdef _DEBUG - // Null out our pointers... - m_pCurrPosition = NULL; - m_pCurrNormal = NULL; - m_pCurrColor = NULL; - memset( m_pCurrTexCoord, 0, sizeof( m_pCurrTexCoord ) ); - memset( static_cast( this ), 0, sizeof(VertexDesc_t) ); -#endif -} - -inline void CVertexBuilder::AttachBeginModify( IMesh* pMesh, int nFirstVertex, int nVertexCount, const MeshDesc_t &desc ) -{ - Assert( pMesh && (!m_pVertexBuffer) ); - - m_pVertexBuffer = pMesh; - memcpy( static_cast( this ), static_cast( &desc ), sizeof(VertexDesc_t) ); - m_nMaxVertexCount = m_nVertexCount = nVertexCount; - m_NumBoneWeights = m_NumBoneWeights == 0 ? 0 : 2; // Two weights if any - m_bModify = true; - - // Make sure SetCompressionType was called correctly, if this VB is compressed - ValidateCompressionType(); -} - -inline void CVertexBuilder::AttachEndModify() -{ - Assert( m_pVertexBuffer ); - Assert( m_bModify ); // Make sure they called BeginModify. - - m_pVertexBuffer = 0; - m_nMaxVertexCount = 0; - - m_CompressionType = VERTEX_COMPRESSION_INVALID; - -#ifdef _DEBUG - // Null out our pointers... - m_pCurrPosition = NULL; - m_pCurrNormal = NULL; - m_pCurrColor = NULL; - memset( m_pCurrTexCoord, 0, sizeof( m_pCurrTexCoord ) ); - memset( static_cast( this ), 0, sizeof(VertexDesc_t) ); -#endif -} - - -//----------------------------------------------------------------------------- -// Computes the first min non-null address -//----------------------------------------------------------------------------- -inline unsigned char* FindMinAddress( void *pAddress1, void *pAddress2, int nAddress2Size ) -{ - if ( nAddress2Size == 0 ) - return (unsigned char*)pAddress1; - if ( !pAddress1 ) - return (unsigned char*)pAddress2; - return ( pAddress1 < pAddress2 ) ? (unsigned char*)pAddress1 : (unsigned char*)pAddress2; -} - -//----------------------------------------------------------------------------- -// Resets the vertex buffer builder so it points to the start of everything again -//----------------------------------------------------------------------------- -inline void CVertexBuilder::Reset() -{ - m_nCurrentVertex = 0; - - m_pCurrPosition = m_pPosition; - m_pCurrNormal = m_pNormal; - for ( int i = 0; i < NELEMS( m_pCurrTexCoord ); i++ ) - { - m_pCurrTexCoord[i] = m_pTexCoord[i]; - } - m_pCurrColor = m_pColor; - -#if ( defined( _DEBUG ) && ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 ) ) - m_bWrittenNormal = false; - m_bWrittenUserData = false; -#endif - -#ifdef DEBUG_WRITE_COMBINE - // Logic for m_pLastWrittenAddress is tricky. It really wants the min of the - // non-null address pointers. - m_nLastWrittenField = MB_FIELD_NONE; - m_pLastWrittenAddress = NULL; - m_pLastWrittenAddress = FindMinAddress( m_pLastWrittenAddress, m_pPosition, m_VertexSize_Position ); - m_pLastWrittenAddress = FindMinAddress( m_pLastWrittenAddress, m_pBoneWeight, m_VertexSize_BoneWeight ); - m_pLastWrittenAddress = FindMinAddress( m_pLastWrittenAddress, m_pBoneMatrixIndex, m_VertexSize_BoneMatrixIndex ); - m_pLastWrittenAddress = FindMinAddress( m_pLastWrittenAddress, m_pNormal, m_VertexSize_Normal ); - m_pLastWrittenAddress = FindMinAddress( m_pLastWrittenAddress, m_pColor, m_VertexSize_Color ); - m_pLastWrittenAddress = FindMinAddress( m_pLastWrittenAddress, m_pSpecular, m_VertexSize_Specular ); - for ( int i = 0; i < VERTEX_MAX_TEXTURE_COORDINATES; ++i ) - { - m_pLastWrittenAddress = FindMinAddress( m_pLastWrittenAddress, m_pTexCoord[i], m_VertexSize_TexCoord[i] ); - } - m_pLastWrittenAddress = FindMinAddress( m_pLastWrittenAddress, m_pTangentS, m_VertexSize_TangentS ); - m_pLastWrittenAddress = FindMinAddress( m_pLastWrittenAddress, m_pTangentT, m_VertexSize_TangentT ); - m_pLastWrittenAddress = FindMinAddress( m_pLastWrittenAddress, m_pUserData, m_VertexSize_UserData ); -#endif -} - - -//----------------------------------------------------------------------------- -// returns the number of vertices -//----------------------------------------------------------------------------- -inline int CVertexBuilder::VertexCount() const -{ - return m_nVertexCount; -} - - -//----------------------------------------------------------------------------- -// Returns the total number of vertices across all Locks() -//----------------------------------------------------------------------------- -inline int CVertexBuilder::TotalVertexCount() const -{ - return m_nTotalVertexCount; -} - - -//----------------------------------------------------------------------------- -// Returns the base vertex memory pointer -//----------------------------------------------------------------------------- -inline void* CVertexBuilder::BaseVertexData() -{ - // FIXME: If there's no position specified, we need to find - // the base address - Assert( m_pPosition ); - return m_pPosition; -} - - -//----------------------------------------------------------------------------- -// Selects the current vertex -//----------------------------------------------------------------------------- -inline void CVertexBuilder::SelectVertex( int nIndex ) -{ - // NOTE: This index is expected to be relative - Assert( (nIndex >= 0) && (nIndex < m_nMaxVertexCount) ); - m_nCurrentVertex = nIndex; - - m_pCurrPosition = OffsetFloatPointer( m_pPosition, m_nCurrentVertex, m_VertexSize_Position ); - m_pCurrNormal = OffsetFloatPointer( m_pNormal, m_nCurrentVertex, m_VertexSize_Normal ); - - COMPILE_TIME_ASSERT( VERTEX_MAX_TEXTURE_COORDINATES == 8 ); - m_pCurrTexCoord[0] = OffsetFloatPointer( m_pTexCoord[0], m_nCurrentVertex, m_VertexSize_TexCoord[0] ); - m_pCurrTexCoord[1] = OffsetFloatPointer( m_pTexCoord[1], m_nCurrentVertex, m_VertexSize_TexCoord[1] ); - m_pCurrTexCoord[2] = OffsetFloatPointer( m_pTexCoord[2], m_nCurrentVertex, m_VertexSize_TexCoord[2] ); - m_pCurrTexCoord[3] = OffsetFloatPointer( m_pTexCoord[3], m_nCurrentVertex, m_VertexSize_TexCoord[3] ); - m_pCurrTexCoord[4] = OffsetFloatPointer( m_pTexCoord[4], m_nCurrentVertex, m_VertexSize_TexCoord[4] ); - m_pCurrTexCoord[5] = OffsetFloatPointer( m_pTexCoord[5], m_nCurrentVertex, m_VertexSize_TexCoord[5] ); - m_pCurrTexCoord[6] = OffsetFloatPointer( m_pTexCoord[6], m_nCurrentVertex, m_VertexSize_TexCoord[6] ); - m_pCurrTexCoord[7] = OffsetFloatPointer( m_pTexCoord[7], m_nCurrentVertex, m_VertexSize_TexCoord[7] ); - m_pCurrColor = m_pColor + m_nCurrentVertex * m_VertexSize_Color; - -#if ( defined( _DEBUG ) && ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 ) ) - m_bWrittenNormal = false; - m_bWrittenUserData = false; -#endif -} - - -//----------------------------------------------------------------------------- -// Advances vertex after you're done writing to it. -//----------------------------------------------------------------------------- -inline void CVertexBuilder::AdvanceVertex() -{ - if ( ++m_nCurrentVertex > m_nVertexCount ) - { - m_nVertexCount = m_nCurrentVertex; - } - - IncrementFloatPointer( m_pCurrPosition, m_VertexSize_Position ); - IncrementFloatPointer( m_pCurrNormal, m_VertexSize_Normal ); - - COMPILE_TIME_ASSERT( VERTEX_MAX_TEXTURE_COORDINATES == 8 ); - IncrementFloatPointer( m_pCurrTexCoord[0], m_VertexSize_TexCoord[0] ); - IncrementFloatPointer( m_pCurrTexCoord[1], m_VertexSize_TexCoord[1] ); - IncrementFloatPointer( m_pCurrTexCoord[2], m_VertexSize_TexCoord[2] ); - IncrementFloatPointer( m_pCurrTexCoord[3], m_VertexSize_TexCoord[3] ); - IncrementFloatPointer( m_pCurrTexCoord[4], m_VertexSize_TexCoord[4] ); - IncrementFloatPointer( m_pCurrTexCoord[5], m_VertexSize_TexCoord[5] ); - IncrementFloatPointer( m_pCurrTexCoord[6], m_VertexSize_TexCoord[6] ); - IncrementFloatPointer( m_pCurrTexCoord[7], m_VertexSize_TexCoord[7] ); - m_pCurrColor += m_VertexSize_Color; - -#if ( defined( _DEBUG ) && ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 ) ) - m_bWrittenNormal = false; - m_bWrittenUserData = false; -#endif -} - -inline void CVertexBuilder::AdvanceVertices( int nVerts ) -{ - m_nCurrentVertex += nVerts; - if ( m_nCurrentVertex > m_nVertexCount ) - { - m_nVertexCount = m_nCurrentVertex; - } - - IncrementFloatPointer( m_pCurrPosition, m_VertexSize_Position*nVerts ); - IncrementFloatPointer( m_pCurrNormal, m_VertexSize_Normal*nVerts ); - - COMPILE_TIME_ASSERT( VERTEX_MAX_TEXTURE_COORDINATES == 8 ); - IncrementFloatPointer( m_pCurrTexCoord[0], m_VertexSize_TexCoord[0]*nVerts ); - IncrementFloatPointer( m_pCurrTexCoord[1], m_VertexSize_TexCoord[1]*nVerts ); - IncrementFloatPointer( m_pCurrTexCoord[2], m_VertexSize_TexCoord[2]*nVerts ); - IncrementFloatPointer( m_pCurrTexCoord[3], m_VertexSize_TexCoord[3]*nVerts ); - IncrementFloatPointer( m_pCurrTexCoord[4], m_VertexSize_TexCoord[4]*nVerts ); - IncrementFloatPointer( m_pCurrTexCoord[5], m_VertexSize_TexCoord[5]*nVerts ); - IncrementFloatPointer( m_pCurrTexCoord[6], m_VertexSize_TexCoord[6]*nVerts ); - IncrementFloatPointer( m_pCurrTexCoord[7], m_VertexSize_TexCoord[7]*nVerts ); - m_pCurrColor += m_VertexSize_Color*nVerts; - -#if ( defined( _DEBUG ) && ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 ) ) - m_bWrittenNormal = false; - m_bWrittenUserData = false; -#endif -} - - -//----------------------------------------------------------------------------- -// For use with the FastVertex methods, advances the current vertex by N -//----------------------------------------------------------------------------- -inline void CVertexBuilder::FastAdvanceNVertices( int n ) -{ - m_nCurrentVertex += n; - m_nVertexCount = m_nCurrentVertex; -} - - -//----------------------------------------------------------------------------- -// Fast Vertex! No need to call advance vertex, and no random access allowed -//----------------------------------------------------------------------------- -inline void CVertexBuilder::FastVertex( const ModelVertexDX7_t &vertex ) -{ - Assert( m_CompressionType == VERTEX_COMPRESSION_NONE ); // FIXME: support compressed verts if needed - Assert( m_nCurrentVertex < m_nMaxVertexCount ); - -#if defined( _WIN32 ) && !defined( _X360 ) - const void *pRead = &vertex; - void *pCurrPos = m_pCurrPosition; - - __asm - { - mov esi, pRead - mov edi, pCurrPos - - movq mm0, [esi + 0] - movq mm1, [esi + 8] - movq mm2, [esi + 16] - movq mm3, [esi + 24] - movq mm4, [esi + 32] - movq mm5, [esi + 40] - - movntq [edi + 0], mm0 - movntq [edi + 8], mm1 - movntq [edi + 16], mm2 - movntq [edi + 24], mm3 - movntq [edi + 32], mm4 - movntq [edi + 40], mm5 - - emms - } -#else - Error( "Implement CMeshBuilder::FastVertex(dx7) "); -#endif - - IncrementFloatPointer( m_pCurrPosition, m_VertexSize_Position ); - //m_nVertexCount = ++m_nCurrentVertex; - -#if ( defined( _DEBUG ) && ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 ) ) - m_bWrittenNormal = false; - m_bWrittenUserData = false; -#endif -} - -inline void CVertexBuilder::FastVertexSSE( const ModelVertexDX7_t &vertex ) -{ - Assert( m_CompressionType == VERTEX_COMPRESSION_NONE ); // FIXME: support compressed verts if needed - Assert( m_nCurrentVertex < m_nMaxVertexCount ); - -#if defined( _WIN32 ) && !defined( _X360 ) - const void *pRead = &vertex; - void *pCurrPos = m_pCurrPosition; - __asm - { - mov esi, pRead - mov edi, pCurrPos - - movaps xmm0, [esi + 0] - movaps xmm1, [esi + 16] - movaps xmm2, [esi + 32] - - movntps [edi + 0], xmm0 - movntps [edi + 16], xmm1 - movntps [edi + 32], xmm2 - } -#else - Error( "Implement CMeshBuilder::FastVertexSSE(dx7)" ); -#endif - - IncrementFloatPointer( m_pCurrPosition, m_VertexSize_Position ); - //m_nVertexCount = ++m_nCurrentVertex; - -#if ( defined( _DEBUG ) && ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 ) ) - m_bWrittenNormal = false; - m_bWrittenUserData = false; -#endif -} - -inline void CVertexBuilder::Fast4VerticesSSE( - ModelVertexDX7_t const *vtx_a, - ModelVertexDX7_t const *vtx_b, - ModelVertexDX7_t const *vtx_c, - ModelVertexDX7_t const *vtx_d) -{ - Assert( m_CompressionType == VERTEX_COMPRESSION_NONE ); // FIXME: support compressed verts if needed - Assert( m_nCurrentVertex < m_nMaxVertexCount-3 ); - -#if defined( _WIN32 ) && !defined( _X360 ) - void *pCurrPos = m_pCurrPosition; - __asm - { - mov esi, vtx_a - mov ebx, vtx_b - - mov edi, pCurrPos - nop - - movaps xmm0, [esi + 0] - movaps xmm1, [esi + 16] - movaps xmm2, [esi + 32] - movaps xmm3, [ebx + 0] - movaps xmm4, [ebx + 16] - movaps xmm5, [ebx + 32] - - mov esi, vtx_c - mov ebx, vtx_d - - movntps [edi + 0], xmm0 - movntps [edi + 16], xmm1 - movntps [edi + 32], xmm2 - movntps [edi + 48], xmm3 - movntps [edi + 64], xmm4 - movntps [edi + 80], xmm5 - - movaps xmm0, [esi + 0] - movaps xmm1, [esi + 16] - movaps xmm2, [esi + 32] - movaps xmm3, [ebx + 0] - movaps xmm4, [ebx + 16] - movaps xmm5, [ebx + 32] - - movntps [edi + 0+96], xmm0 - movntps [edi + 16+96], xmm1 - movntps [edi + 32+96], xmm2 - movntps [edi + 48+96], xmm3 - movntps [edi + 64+96], xmm4 - movntps [edi + 80+96], xmm5 - - } -#else - Error( "Implement CMeshBuilder::Fast4VerticesSSE\n"); -#endif - IncrementFloatPointer( m_pCurrPosition, 4*m_VertexSize_Position ); - -#if ( defined( _DEBUG ) && ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 ) ) - m_bWrittenNormal = false; - m_bWrittenUserData = false; -#endif -} - -inline void CVertexBuilder::FastVertex( const ModelVertexDX8_t &vertex ) -{ - Assert( m_CompressionType == VERTEX_COMPRESSION_NONE ); // FIXME: support compressed verts if needed - Assert( m_nCurrentVertex < m_nMaxVertexCount ); - -#if defined( _WIN32 ) && !defined( _X360 ) - const void *pRead = &vertex; - void *pCurrPos = m_pCurrPosition; - __asm - { - mov esi, pRead - mov edi, pCurrPos - - movq mm0, [esi + 0] - movq mm1, [esi + 8] - movq mm2, [esi + 16] - movq mm3, [esi + 24] - movq mm4, [esi + 32] - movq mm5, [esi + 40] - movq mm6, [esi + 48] - movq mm7, [esi + 56] - - movntq [edi + 0], mm0 - movntq [edi + 8], mm1 - movntq [edi + 16], mm2 - movntq [edi + 24], mm3 - movntq [edi + 32], mm4 - movntq [edi + 40], mm5 - movntq [edi + 48], mm6 - movntq [edi + 56], mm7 - - emms - } -#else - Error( "Implement CMeshBuilder::FastVertex(dx8)" ); -#endif - - IncrementFloatPointer( m_pCurrPosition, m_VertexSize_Position ); - // m_nVertexCount = ++m_nCurrentVertex; - -#if ( defined( _DEBUG ) && ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 ) ) - m_bWrittenNormal = false; - m_bWrittenUserData = false; -#endif -} - -inline void CVertexBuilder::FastVertexSSE( const ModelVertexDX8_t &vertex ) -{ - Assert( m_CompressionType == VERTEX_COMPRESSION_NONE ); // FIXME: support compressed verts if needed - Assert( m_nCurrentVertex < m_nMaxVertexCount ); - -#if defined( _WIN32 ) && !defined( _X360 ) - const void *pRead = &vertex; - void *pCurrPos = m_pCurrPosition; - __asm - { - mov esi, pRead - mov edi, pCurrPos - - movaps xmm0, [esi + 0] - movaps xmm1, [esi + 16] - movaps xmm2, [esi + 32] - movaps xmm3, [esi + 48] - - movntps [edi + 0], xmm0 - movntps [edi + 16], xmm1 - movntps [edi + 32], xmm2 - movntps [edi + 48], xmm3 - } -#else - Error( "Implement CMeshBuilder::FastVertexSSE((dx8)" ); -#endif - - IncrementFloatPointer( m_pCurrPosition, m_VertexSize_Position ); - // m_nVertexCount = ++m_nCurrentVertex; - -#if ( defined( _DEBUG ) && ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 ) ) - m_bWrittenNormal = false; - m_bWrittenUserData = false; -#endif -} - - -//----------------------------------------------------------------------------- -// Returns the current vertex -//----------------------------------------------------------------------------- -inline int CVertexBuilder::GetCurrentVertex() const -{ - return m_nCurrentVertex; -} - - -//----------------------------------------------------------------------------- -// Copies a vertex into the x360 format -//----------------------------------------------------------------------------- -#if defined( _X360 ) -inline void CVertexBuilder::VertexDX8ToX360( const ModelVertexDX8_t &vertex ) -{ - Assert( m_CompressionType == VERTEX_COMPRESSION_NONE ); // FIXME: support compressed verts if needed - Assert( m_nCurrentVertex < m_nMaxVertexCount ); - - // get the start of the data - unsigned char *pDst = (unsigned char*)m_pCurrPosition; - - Assert( m_VertexSize_Position > 0 ); // Assume position is always present - Assert( GetVertexElementSize( VERTEX_ELEMENT_POSITION, VERTEX_COMPRESSION_NONE ) == sizeof( vertex.m_vecPosition ) ); - memcpy( pDst, vertex.m_vecPosition.Base(), sizeof( vertex.m_vecPosition ) ); - pDst += sizeof( vertex.m_vecPosition ); - - if ( m_VertexSize_BoneWeight ) - { - Assert( vertex.m_flBoneWeights[0] >= 0 && vertex.m_flBoneWeights[0] <= 1.0f ); - Assert( vertex.m_flBoneWeights[1] >= 0 && vertex.m_flBoneWeights[1] <= 1.0f ); - Assert( GetVertexElementSize( VERTEX_ELEMENT_BONEWEIGHTS2, VERTEX_COMPRESSION_NONE ) == sizeof( vertex.m_flBoneWeights ) ); - memcpy( pDst, vertex.m_flBoneWeights.Base(), sizeof( vertex.m_flBoneWeights ) ); - pDst += sizeof( vertex.m_flBoneWeights ); - - if ( m_VertexSize_BoneMatrixIndex ) - { - Assert( GetVertexElementSize( VERTEX_ELEMENT_BONEINDEX, VERTEX_COMPRESSION_NONE ) == sizeof( vertex.m_nBoneIndices ) ); - *(unsigned int*)pDst = vertex.m_nBoneIndices; - pDst += sizeof( vertex.m_nBoneIndices ); - } - } - - if ( m_VertexSize_Normal ) - { - Assert( GetVertexElementSize( VERTEX_ELEMENT_NORMAL, VERTEX_COMPRESSION_NONE ) == sizeof( vertex.m_vecNormal ) ); - memcpy( pDst, vertex.m_vecNormal.Base(), sizeof( vertex.m_vecNormal ) ); - pDst += sizeof( vertex.m_vecNormal ); - } - - if ( m_VertexSize_Color ) - { - Assert( GetVertexElementSize( VERTEX_ELEMENT_COLOR, VERTEX_COMPRESSION_NONE ) == sizeof( vertex.m_nColor ) ); - *(unsigned int*)pDst = vertex.m_nColor; - pDst += sizeof( vertex.m_nColor ); - } - - if ( m_VertexSize_TexCoord[0] ) - { - Assert( GetVertexElementSize( VERTEX_ELEMENT_TEXCOORD2D_0, VERTEX_COMPRESSION_NONE ) == sizeof( vertex.m_vecTexCoord ) ); - memcpy( pDst, vertex.m_vecTexCoord.Base(), sizeof( vertex.m_vecTexCoord ) ); - pDst += sizeof( vertex.m_vecTexCoord ); - } - - if ( m_VertexSize_UserData ) - { - Assert( GetVertexElementSize( VERTEX_ELEMENT_USERDATA4, VERTEX_COMPRESSION_NONE ) == sizeof( vertex.m_vecUserData ) ); - memcpy( pDst, vertex.m_vecUserData.Base(), sizeof( vertex.m_vecUserData ) ); - pDst += sizeof( vertex.m_vecUserData ); - } - - // ensure code is synced with the mesh builder that established the offsets - Assert( pDst - (unsigned char*)m_pCurrPosition == m_VertexSize_Position ); - - IncrementFloatPointer( m_pCurrPosition, m_VertexSize_Position ); - -#if ( defined( _DEBUG ) && ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 ) ) - m_bWrittenNormal = false; - m_bWrittenUserData = false; -#endif -} -#endif - - -//----------------------------------------------------------------------------- -// Data retrieval... -//----------------------------------------------------------------------------- -inline const float* CVertexBuilder::Position() const -{ - // FIXME: add a templatized accessor (return type varies to ensure calling code is updated appropriately) - // for code that needs to access compressed data (and/or a return-by-value templatized accessor) - Assert( m_CompressionType == VERTEX_COMPRESSION_NONE ); - Assert( m_nCurrentVertex < m_nMaxVertexCount ); - return m_pCurrPosition; -} - -inline const float* CVertexBuilder::Normal() const -{ - // FIXME: add a templatized accessor (return type varies to ensure calling code is updated appropriately) - // for code that needs to access compressed data (and/or a return-by-value templatized accessor) - Assert( m_CompressionType == VERTEX_COMPRESSION_NONE ); - Assert( m_nCurrentVertex < m_nMaxVertexCount ); - return m_pCurrNormal; -} - -inline unsigned int CVertexBuilder::Color() const -{ - // FIXME: add a templatized accessor (return type varies to ensure calling code is updated appropriately) - // for code that needs to access compressed data (and/or a return-by-value templatized accessor) - Assert( m_CompressionType == VERTEX_COMPRESSION_NONE ); - // Swizzle it so it returns the same format as accepted by Color4ubv - rgba - Assert( m_nCurrentVertex < m_nMaxVertexCount ); - unsigned int color; - if ( IsPC() || !IsX360() ) - { - color = (m_pCurrColor[3] << 24) | (m_pCurrColor[0] << 16) | (m_pCurrColor[1] << 8) | (m_pCurrColor[2]); - } - else - { - // in memory as argb, back to rgba - color = (m_pCurrColor[1] << 24) | (m_pCurrColor[2] << 16) | (m_pCurrColor[3] << 8) | (m_pCurrColor[0]); - } - return color; -} - -inline unsigned char *CVertexBuilder::Specular() const -{ - // FIXME: add a templatized accessor (return type varies to ensure calling code is updated appropriately) - // for code that needs to access compressed data (and/or a return-by-value templatized accessor) - Assert( m_CompressionType == VERTEX_COMPRESSION_NONE ); - Assert( m_nCurrentVertex < m_nMaxVertexCount ); - return m_pSpecular + m_nCurrentVertex * m_VertexSize_Specular; -} - -inline const float* CVertexBuilder::TexCoord( int stage ) const -{ - // FIXME: add a templatized accessor (return type varies to ensure calling code is updated appropriately) - // for code that needs to access compressed data (and/or a return-by-value templatized accessor) - Assert( m_CompressionType == VERTEX_COMPRESSION_NONE ); - Assert( m_nCurrentVertex < m_nMaxVertexCount ); - return m_pCurrTexCoord[stage]; -} - -inline const float* CVertexBuilder::TangentS() const -{ - // FIXME: add a templatized accessor (return type varies to ensure calling code is updated appropriately) - // for code that needs to access compressed data (and/or a return-by-value templatized accessor) - Assert( m_CompressionType == VERTEX_COMPRESSION_NONE ); - Assert( m_nCurrentVertex < m_nMaxVertexCount ); - return OffsetFloatPointer( m_pTangentS, m_nCurrentVertex, m_VertexSize_TangentS ); -} - -inline const float* CVertexBuilder::TangentT() const -{ - // FIXME: add a templatized accessor (return type varies to ensure calling code is updated appropriately) - // for code that needs to access compressed data (and/or a return-by-value templatized accessor) - Assert( m_CompressionType == VERTEX_COMPRESSION_NONE ); - Assert( m_nCurrentVertex < m_nMaxVertexCount ); - return OffsetFloatPointer( m_pTangentT, m_nCurrentVertex, m_VertexSize_TangentT ); -} - -inline float CVertexBuilder::Wrinkle() const -{ - // FIXME: add a templatized accessor (return type varies to ensure calling code is updated appropriately) - // for code that needs to access compressed data (and/or a return-by-value templatized accessor) - Assert( m_CompressionType == VERTEX_COMPRESSION_NONE ); - Assert( m_nCurrentVertex < m_nMaxVertexCount ); - return *OffsetFloatPointer( m_pWrinkle, m_nCurrentVertex, m_VertexSize_Wrinkle ); -} - -inline const float* CVertexBuilder::BoneWeight() const -{ - // FIXME: add a templatized accessor (return type varies to ensure calling code is updated appropriately) - // for code that needs to access compressed data (and/or a return-by-value templatized accessor) - Assert( m_CompressionType == VERTEX_COMPRESSION_NONE ); - Assert( m_nCurrentVertex < m_nMaxVertexCount ); - return OffsetFloatPointer( m_pBoneWeight, m_nCurrentVertex, m_VertexSize_BoneWeight ); -} - -inline int CVertexBuilder::NumBoneWeights() const -{ - return m_NumBoneWeights; -} - -#ifndef NEW_SKINNING -inline unsigned char* CVertexBuilder::BoneMatrix() const -{ - // FIXME: add a templatized accessor (return type varies to ensure calling code is updated appropriately) - // for code that needs to access compressed data (and/or a return-by-value templatized accessor) - Assert( m_CompressionType == VERTEX_COMPRESSION_NONE ); - Assert( m_nCurrentVertex < m_nMaxVertexCount ); - return m_pBoneMatrixIndex + m_nCurrentVertex * m_VertexSize_BoneMatrixIndex; -} -#else -inline float* CVertexBuilder::BoneMatrix() const -{ - // FIXME: add a templatized accessor (return type varies to ensure calling code is updated appropriately) - // for code that needs to access compressed data (and/or a return-by-value templatized accessor) - Assert( m_CompressionType == VERTEX_COMPRESSION_NONE ); - Assert( m_nCurrentVertex < m_nMaxVertexCount ); - return m_pBoneMatrixIndex + m_nCurrentVertex * m_VertexSize_BoneMatrixIndex; -} -#endif - - -//----------------------------------------------------------------------------- -// Position setting methods -//----------------------------------------------------------------------------- -inline void CVertexBuilder::Position3f( float x, float y, float z ) -{ - Assert( m_pPosition && m_pCurrPosition ); - Assert( IsFinite(x) && IsFinite(y) && IsFinite(z) ); - float *pDst = m_pCurrPosition; - *pDst++ = x; - *pDst++ = y; - *pDst = z; -} - -inline void CVertexBuilder::Position3fv( const float *v ) -{ - Assert(v); - Assert( m_pPosition && m_pCurrPosition ); - - float *pDst = m_pCurrPosition; - *pDst++ = *v++; - *pDst++ = *v++; - *pDst = *v; -} - - -//----------------------------------------------------------------------------- -// Normal setting methods -//----------------------------------------------------------------------------- -inline void CVertexBuilder::Normal3f( float nx, float ny, float nz ) -{ - Assert( m_CompressionType == VERTEX_COMPRESSION_NONE ); // Use the templatized version if you want to support compression - Assert( m_pNormal ); - Assert( IsFinite(nx) && IsFinite(ny) && IsFinite(nz) ); - Assert( nx >= -1.05f && nx <= 1.05f ); - Assert( ny >= -1.05f && ny <= 1.05f ); - Assert( nz >= -1.05f && nz <= 1.05f ); - - float *pDst = m_pCurrNormal; - *pDst++ = nx; - *pDst++ = ny; - *pDst = nz; -} - -inline void CVertexBuilder::Normal3fv( const float *n ) -{ - Assert( m_CompressionType == VERTEX_COMPRESSION_NONE ); // Use the templatized version if you want to support compression - Assert( n ); - Assert( m_pNormal && m_pCurrNormal ); - Assert( IsFinite(n[0]) && IsFinite(n[1]) && IsFinite(n[2]) ); - Assert( n[0] >= -1.05f && n[0] <= 1.05f ); - Assert( n[1] >= -1.05f && n[1] <= 1.05f ); - Assert( n[2] >= -1.05f && n[2] <= 1.05f ); - - float *pDst = m_pCurrNormal; - *pDst++ = *n++; - *pDst++ = *n++; - *pDst = *n; -} - -inline void CVertexBuilder::NormalDelta3f( float nx, float ny, float nz ) -{ - Assert( m_CompressionType == VERTEX_COMPRESSION_NONE ); // Use the templatized version if you want to support compression - Assert( m_pNormal ); - Assert( IsFinite(nx) && IsFinite(ny) && IsFinite(nz) ); - - float *pDst = m_pCurrNormal; - *pDst++ = nx; - *pDst++ = ny; - *pDst = nz; -} - -inline void CVertexBuilder::NormalDelta3fv( const float *n ) -{ - Assert( m_CompressionType == VERTEX_COMPRESSION_NONE ); // Use the templatized version if you want to support compression - Assert( n ); - Assert( m_pNormal && m_pCurrNormal ); - Assert( IsFinite(n[0]) && IsFinite(n[1]) && IsFinite(n[2]) ); - - float *pDst = m_pCurrNormal; - *pDst++ = *n++; - *pDst++ = *n++; - *pDst = *n; -} - -//----------------------------------------------------------------------------- -// Templatized normal setting methods which support compressed vertices -//----------------------------------------------------------------------------- -template inline void CVertexBuilder::CompressedNormal3f( float nx, float ny, float nz ) -{ - Assert( T == m_CompressionType ); - Assert( m_pNormal && m_pCurrNormal ); - Assert( IsFinite(nx) && IsFinite(ny) && IsFinite(nz) ); - Assert( nx >= -1.05f && nx <= 1.05f ); - Assert( ny >= -1.05f && ny <= 1.05f ); - Assert( nz >= -1.05f && nz <= 1.05f ); - // FIXME: studiorender is passing in non-unit normals - //float lengthSqd = nx*nx + ny*ny + nz*nz; - //Assert( lengthSqd >= 0.95f && lengthSqd <= 1.05f ); - - if ( T == VERTEX_COMPRESSION_ON ) - { -#if ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 ) - PackNormal_SHORT2( nx, ny, nz, (unsigned int *)m_pCurrNormal ); - -#else //( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 ) - // NOTE: write the normal into the lower 16 bits of a word, clearing the top 16 bits - a userdata4 - // tangent must be written into the upper 16 bits by CompressedUserData() *AFTER* this. -#ifdef _DEBUG - Assert( m_bWrittenUserData == false ); - m_bWrittenNormal = true; -#endif - PackNormal_UBYTE4( nx, ny, nz, (unsigned int *)m_pCurrNormal ); -#endif - } - else - { - float *pDst = m_pCurrNormal; - *pDst++ = nx; - *pDst++ = ny; - *pDst = nz; - } -} - -template inline void CVertexBuilder::CompressedNormal3fv( const float *n ) -{ - Assert( n ); - CompressedNormal3f( n[0], n[1], n[2] ); -} - - -//----------------------------------------------------------------------------- -// Color setting methods -//----------------------------------------------------------------------------- -inline void CVertexBuilder::Color3f( float r, float g, float b ) -{ - Assert( m_pColor && m_pCurrColor ); - Assert( IsFinite(r) && IsFinite(g) && IsFinite(b) ); - Assert( (r >= 0.0) && (g >= 0.0) && (b >= 0.0) ); - Assert( (r <= 1.0) && (g <= 1.0) && (b <= 1.0) ); - - int col = (FastFToC(b)) | (FastFToC(g) << 8) | (FastFToC(r) << 16) | 0xFF000000; - *(int*)m_pCurrColor = col; -} - -inline void CVertexBuilder::Color3fv( const float *rgb ) -{ - Assert(rgb); - Assert( m_pColor && m_pCurrColor ); - Assert( IsFinite(rgb[0]) && IsFinite(rgb[1]) && IsFinite(rgb[2]) ); - Assert( (rgb[0] >= 0.0) && (rgb[1] >= 0.0) && (rgb[2] >= 0.0) ); - Assert( (rgb[0] <= 1.0) && (rgb[1] <= 1.0) && (rgb[2] <= 1.0) ); - - int col = (FastFToC(rgb[2])) | (FastFToC(rgb[1]) << 8) | (FastFToC(rgb[0]) << 16) | 0xFF000000; - *(int*)m_pCurrColor = col; -} - -inline void CVertexBuilder::Color4f( float r, float g, float b, float a ) -{ - Assert( m_pColor && m_pCurrColor ); - Assert( IsFinite(r) && IsFinite(g) && IsFinite(b) && IsFinite(a) ); - Assert( (r >= 0.0) && (g >= 0.0) && (b >= 0.0) && (a >= 0.0) ); - Assert( (r <= 1.0) && (g <= 1.0) && (b <= 1.0) && (a <= 1.0) ); - - int col = (FastFToC(b)) | (FastFToC(g) << 8) | (FastFToC(r) << 16) | (FastFToC(a) << 24); - *(int*)m_pCurrColor = col; -} - -inline void CVertexBuilder::Color4fv( const float *rgba ) -{ - Assert(rgba); - Assert( m_pColor && m_pCurrColor ); - Assert( IsFinite(rgba[0]) && IsFinite(rgba[1]) && IsFinite(rgba[2]) && IsFinite(rgba[3]) ); - Assert( (rgba[0] >= 0.0) && (rgba[1] >= 0.0) && (rgba[2] >= 0.0) && (rgba[3] >= 0.0) ); - Assert( (rgba[0] <= 1.0) && (rgba[1] <= 1.0) && (rgba[2] <= 1.0) && (rgba[3] <= 1.0) ); - - int col = (FastFToC(rgba[2])) | (FastFToC(rgba[1]) << 8) | (FastFToC(rgba[0]) << 16) | (FastFToC(rgba[3]) << 24); - *(int*)m_pCurrColor = col; -} - - -//----------------------------------------------------------------------------- -// Faster versions of color -//----------------------------------------------------------------------------- -inline void CVertexBuilder::Color3ub( unsigned char r, unsigned char g, unsigned char b ) -{ - Assert( m_pColor && m_pCurrColor ); - int col = b | (g << 8) | (r << 16) | 0xFF000000; - *(int*)m_pCurrColor = col; -} - -inline void CVertexBuilder::Color3ubv( unsigned char const* rgb ) -{ - Assert(rgb); - Assert( m_pColor && m_pCurrColor ); - - int col = rgb[2] | (rgb[1] << 8) | (rgb[0] << 16) | 0xFF000000; - *(int*)m_pCurrColor = col; -} - -inline void CVertexBuilder::Color4ub( unsigned char r, unsigned char g, unsigned char b, unsigned char a ) -{ - Assert( m_pColor && m_pCurrColor ); - int col = b | (g << 8) | (r << 16) | (a << 24); - *(int*)m_pCurrColor = col; -} - -inline void CVertexBuilder::Color4ubv( unsigned char const* rgba ) -{ - Assert( rgba ); - Assert( m_pColor && m_pCurrColor ); - int col = rgba[2] | (rgba[1] << 8) | (rgba[0] << 16) | (rgba[3] << 24); - *(int*)m_pCurrColor = col; -} - -inline void CVertexBuilder::Specular3f( float r, float g, float b ) -{ - Assert( m_pSpecular ); - Assert( IsFinite(r) && IsFinite(g) && IsFinite(b) ); - Assert( (r >= 0.0) && (g >= 0.0) && (b >= 0.0) ); - Assert( (r <= 1.0) && (g <= 1.0) && (b <= 1.0) ); - - unsigned char* pSpecular = &m_pSpecular[m_nCurrentVertex * m_VertexSize_Specular]; - int col = (FastFToC(b)) | (FastFToC(g) << 8) | (FastFToC(r) << 16) | 0xFF000000; - *(int*)pSpecular = col; -} - -inline void CVertexBuilder::Specular3fv( const float *rgb ) -{ - Assert(rgb); - Assert( m_pSpecular ); - Assert( IsFinite(rgb[0]) && IsFinite(rgb[1]) && IsFinite(rgb[2]) ); - Assert( (rgb[0] >= 0.0) && (rgb[1] >= 0.0) && (rgb[2] >= 0.0) ); - Assert( (rgb[0] <= 1.0) && (rgb[1] <= 1.0) && (rgb[2] <= 1.0) ); - - unsigned char* pSpecular = &m_pSpecular[m_nCurrentVertex * m_VertexSize_Specular]; - int col = (FastFToC(rgb[2])) | (FastFToC(rgb[1]) << 8) | (FastFToC(rgb[0]) << 16) | 0xFF000000; - *(int*)pSpecular = col; -} - -inline void CVertexBuilder::Specular4f( float r, float g, float b, float a ) -{ - Assert( m_pSpecular ); - Assert( IsFinite(r) && IsFinite(g) && IsFinite(b) && IsFinite(a) ); - Assert( (r >= 0.0) && (g >= 0.0) && (b >= 0.0) && (a >= 0.0) ); - Assert( (r <= 1.0) && (g <= 1.0) && (b <= 1.0) && (a <= 1.0f) ); - - unsigned char* pSpecular = &m_pSpecular[m_nCurrentVertex * m_VertexSize_Specular]; - int col = (FastFToC(b)) | (FastFToC(g) << 8) | (FastFToC(r) << 16) | (FastFToC(a) << 24); - *(int*)pSpecular = col; -} - -inline void CVertexBuilder::Specular4fv( const float *rgb ) -{ - Assert(rgb); - Assert( m_pSpecular ); - Assert( IsFinite(rgb[0]) && IsFinite(rgb[1]) && IsFinite(rgb[2]) && IsFinite(rgb[3]) ); - Assert( (rgb[0] >= 0.0) && (rgb[1] >= 0.0) && (rgb[2] >= 0.0) && (rgb[3] >= 0.0) ); - Assert( (rgb[0] <= 1.0) && (rgb[1] <= 1.0) && (rgb[2] <= 1.0) && (rgb[3] <= 1.0) ); - - unsigned char* pSpecular = &m_pSpecular[m_nCurrentVertex * m_VertexSize_Specular]; - int col = (FastFToC(rgb[2])) | (FastFToC(rgb[1]) << 8) | (FastFToC(rgb[0]) << 16) | (FastFToC(rgb[3]) << 24); - *(int*)pSpecular = col; -} - -inline void CVertexBuilder::Specular3ub( unsigned char r, unsigned char g, unsigned char b ) -{ - Assert( m_pSpecular ); - unsigned char *pSpecular = &m_pSpecular[m_nCurrentVertex * m_VertexSize_Specular]; - int col = b | (g << 8) | (r << 16) | 0xFF000000; - *(int*)pSpecular = col; -} - -inline void CVertexBuilder::Specular3ubv( unsigned char const *c ) -{ - Assert( m_pSpecular ); - unsigned char *pSpecular = &m_pSpecular[m_nCurrentVertex * m_VertexSize_Specular]; - int col = c[2] | (c[1] << 8) | (c[0] << 16) | 0xFF000000; - *(int*)pSpecular = col; -} - -inline void CVertexBuilder::Specular4ub( unsigned char r, unsigned char g, unsigned char b, unsigned char a ) -{ - Assert( m_pSpecular ); - unsigned char *pSpecular = &m_pSpecular[m_nCurrentVertex * m_VertexSize_Specular]; - int col = b | (g << 8) | (r << 16) | (a << 24); - *(int*)pSpecular = col; -} - -inline void CVertexBuilder::Specular4ubv( unsigned char const *c ) -{ - Assert( m_pSpecular ); - unsigned char *pSpecular = &m_pSpecular[m_nCurrentVertex * m_VertexSize_Specular]; - int col = c[2] | (c[1] << 8) | (c[0] << 16) | (c[3] << 24); - *(int*)pSpecular = col; -} - - -//----------------------------------------------------------------------------- -// Texture coordinate setting methods -//----------------------------------------------------------------------------- -inline void CVertexBuilder::TexCoord1f( int nStage, float s ) -{ - Assert( m_pTexCoord[nStage] && m_pCurrTexCoord[nStage] ); - Assert( IsFinite(s) ); - - float *pDst = m_pCurrTexCoord[nStage]; - *pDst = s; -} - -inline void CVertexBuilder::TexCoord2f( int nStage, float s, float t ) -{ - Assert( m_pTexCoord[nStage] && m_pCurrTexCoord[nStage] ); - Assert( IsFinite(s) && IsFinite(t) ); - - float *pDst = m_pCurrTexCoord[nStage]; - *pDst++ = s; - *pDst = t; -} - -inline void CVertexBuilder::TexCoord2fv( int nStage, const float *st ) -{ - Assert(st); - Assert( m_pTexCoord[nStage] && m_pCurrTexCoord[nStage] ); - Assert( IsFinite(st[0]) && IsFinite(st[1]) ); - - float *pDst = m_pCurrTexCoord[nStage]; - *pDst++ = *st++; - *pDst = *st; -} - -inline void CVertexBuilder::TexCoord3f( int stage, float s, float t, float u ) -{ - // Tried to add too much! - Assert( m_pTexCoord[stage] && m_pCurrTexCoord[stage] ); - Assert( IsFinite(s) && IsFinite(t) && IsFinite(u) ); - float *pDst = m_pCurrTexCoord[stage]; - *pDst++ = s; - *pDst++ = t; - *pDst = u; -} - -inline void CVertexBuilder::TexCoord3fv( int stage, const float *stu ) -{ - Assert(stu); - Assert( m_pTexCoord[stage] && m_pCurrTexCoord[stage] ); - Assert( IsFinite(stu[0]) && IsFinite(stu[1]) && IsFinite(stu[2]) ); - - float *pDst = m_pCurrTexCoord[stage]; - *pDst++ = *stu++; - *pDst++ = *stu++; - *pDst = *stu; -} - -inline void CVertexBuilder::TexCoord4f( int stage, float s, float t, float u, float v ) -{ - // Tried to add too much! - Assert( m_pTexCoord[stage] && m_pCurrTexCoord[stage] ); - Assert( IsFinite(s) && IsFinite(t) && IsFinite(u) ); - float *pDst = m_pCurrTexCoord[stage]; - *pDst++ = s; - *pDst++ = t; - *pDst++ = u; - *pDst = v; -} - -inline void CVertexBuilder::TexCoord4fv( int stage, const float *stuv ) -{ - Assert(stuv); - Assert( m_pTexCoord[stage] && m_pCurrTexCoord[stage] ); - Assert( IsFinite(stuv[0]) && IsFinite(stuv[1]) && IsFinite(stuv[2]) ); - - float *pDst = m_pCurrTexCoord[stage]; - *pDst++ = *stuv++; - *pDst++ = *stuv++; - *pDst++ = *stuv++; - *pDst = *stuv; -} - - -inline void CVertexBuilder::TexCoordSubRect2f( int stage, float s, float t, float offsetS, float offsetT, float scaleS, float scaleT ) -{ - Assert( m_pTexCoord[stage] && m_pCurrTexCoord[stage] ); - Assert( IsFinite(s) && IsFinite(t) ); - - float *pDst = m_pCurrTexCoord[stage]; - *pDst++ = ( s * scaleS ) + offsetS; - *pDst = ( t * scaleT ) + offsetT; -} - -inline void CVertexBuilder::TexCoordSubRect2fv( int stage, const float *st, const float *offset, const float *scale ) -{ - Assert(st); - Assert( m_pTexCoord[stage] && m_pCurrTexCoord[stage] ); - Assert( IsFinite(st[0]) && IsFinite(st[1]) ); - - float *pDst = m_pCurrTexCoord[stage]; - *pDst++ = ( *st++ * *scale++ ) + *offset++; - *pDst = ( *st * *scale ) + *offset; -} - - -//----------------------------------------------------------------------------- -// Tangent space setting methods -//----------------------------------------------------------------------------- -inline void CVertexBuilder::TangentS3f( float sx, float sy, float sz ) -{ - Assert( m_pTangentS ); - Assert( IsFinite(sx) && IsFinite(sy) && IsFinite(sz) ); - - float* pTangentS = OffsetFloatPointer( m_pTangentS, m_nCurrentVertex, m_VertexSize_TangentS ); - *pTangentS++ = sx; - *pTangentS++ = sy; - *pTangentS = sz; -} - -inline void CVertexBuilder::TangentS3fv( const float* s ) -{ - Assert( s ); - Assert( m_pTangentS ); - Assert( IsFinite(s[0]) && IsFinite(s[1]) && IsFinite(s[2]) ); - - float* pTangentS = OffsetFloatPointer( m_pTangentS, m_nCurrentVertex, m_VertexSize_TangentS ); - *pTangentS++ = *s++; - *pTangentS++ = *s++; - *pTangentS = *s; -} - -inline void CVertexBuilder::TangentT3f( float tx, float ty, float tz ) -{ - Assert( m_pTangentT ); - Assert( IsFinite(tx) && IsFinite(ty) && IsFinite(tz) ); - - float* pTangentT = OffsetFloatPointer( m_pTangentT, m_nCurrentVertex, m_VertexSize_TangentT ); - *pTangentT++ = tx; - *pTangentT++ = ty; - *pTangentT = tz; -} - -inline void CVertexBuilder::TangentT3fv( const float* t ) -{ - Assert( t ); - Assert( m_pTangentT ); - Assert( IsFinite(t[0]) && IsFinite(t[1]) && IsFinite(t[2]) ); - - float* pTangentT = OffsetFloatPointer( m_pTangentT, m_nCurrentVertex, m_VertexSize_TangentT ); - *pTangentT++ = *t++; - *pTangentT++ = *t++; - *pTangentT = *t; -} - - -//----------------------------------------------------------------------------- -// Wrinkle setting methods -//----------------------------------------------------------------------------- -inline void CVertexBuilder::Wrinkle1f( float flWrinkle ) -{ - Assert( m_pWrinkle ); - Assert( IsFinite(flWrinkle) ); - - float *pWrinkle = OffsetFloatPointer( m_pWrinkle, m_nCurrentVertex, m_VertexSize_Wrinkle ); - *pWrinkle = flWrinkle; -} - - -//----------------------------------------------------------------------------- -// Bone weight setting methods -//----------------------------------------------------------------------------- -inline void CVertexBuilder::BoneWeight( int idx, float weight ) -{ - Assert( m_pBoneWeight ); - Assert( IsFinite( weight ) ); - Assert( idx >= 0 ); - Assert( m_NumBoneWeights == 2 ); - - // This test is here because we store N-1 bone weights (the Nth is computed in - // the vertex shader as "1 - C", where C is the sum of the (N-1) other weights) - if ( idx < m_NumBoneWeights ) - { - float* pBoneWeight = OffsetFloatPointer( m_pBoneWeight, m_nCurrentVertex, m_VertexSize_BoneWeight ); - pBoneWeight[idx] = weight; - } -} - -inline void CVertexBuilder::BoneMatrix( int idx, int matrixIdx ) -{ - Assert( m_pBoneMatrixIndex ); - Assert( idx >= 0 ); - Assert( idx < 4 ); - - // garymcthack - if ( matrixIdx == BONE_MATRIX_INDEX_INVALID ) - { - matrixIdx = 0; - } - Assert( (matrixIdx >= 0) && (matrixIdx < 53) ); - -#ifndef NEW_SKINNING - unsigned char* pBoneMatrix = &m_pBoneMatrixIndex[m_nCurrentVertex * m_VertexSize_BoneMatrixIndex]; - if ( IsX360() ) - { - // store sequentially as wzyx order, gpu delivers as xyzw - idx = 3-idx; - } - pBoneMatrix[idx] = (unsigned char)matrixIdx; -#else - float* pBoneMatrix = &m_pBoneMatrixIndex[m_nCurrentVertex * m_VertexSize_BoneMatrixIndex]; - pBoneMatrix[idx] = matrixIdx; -#endif -} - -//----------------------------------------------------------------------------- -// Templatized bone weight setting methods which support compressed vertices -//----------------------------------------------------------------------------- -template inline void CVertexBuilder::CompressedBoneWeight3fv( const float * pWeights ) -{ - Assert( T == m_CompressionType ); - Assert( m_pBoneWeight ); - Assert( pWeights ); - - float *pDestWeights = OffsetFloatPointer( m_pBoneWeight, m_nCurrentVertex, m_VertexSize_BoneWeight ); - - if ( T == VERTEX_COMPRESSION_ON ) - { - // Quantize to 15 bits per weight (we use D3DDECLTYPE_SHORT2) - // NOTE: we perform careful normalization (weights sum to 1.0f in the vertex shader), so - // as to avoid cracking at boundaries between meshes with different numbers of weights - // per vertex. For example, (1) needs to yield the same normalized weights as (1,0), - // and (0.5,0.49) needs to normalize the same normalized weights as (0.5,0.49,0). - // The key is that values which are *computed* in the shader (e.g. the second weight - // in a 2-weight mesh) must exactly equal values which are *read* from the vertex - // stream (e.g. the second weight in a 3-weight mesh). - - // Only 1 or 2 weights (SHORT2N) supported for compressed verts so far - Assert( m_NumBoneWeights <= 2 ); - - const int WEIGHT0_SHIFT = IsX360() ? 16 : 0; - const int WEIGHT1_SHIFT = IsX360() ? 0 : 16; - unsigned int *weights = (unsigned int *)pDestWeights; - - // We scale our weights so that they sum to 32768, then subtract 1 (which gets added - // back in the shader), because dividing by 32767 introduces nasty rounding issues. - Assert( IsFinite( pWeights[0] ) && ( pWeights[0] >= 0.0f ) && ( pWeights[0] <= 1.0f ) ); - unsigned int weight0 = Float2Int( pWeights[0] * 32768.0f ); - *weights = ( 0x0000FFFF & (weight0 - 1) ) << WEIGHT0_SHIFT; - -#ifdef DEBUG - if ( m_NumBoneWeights == 1 ) - { - // Double-check the validity of the values that were passed in - Assert( IsFinite( pWeights[1] ) && ( pWeights[1] >= 0.0f ) && ( pWeights[1] <= 1.0f ) ); - unsigned int weight1 = Float2Int( pWeights[1] * 32768.0f ); - Assert( ( weight0 + weight1 ) <= 32768 ); - } -#endif - - if ( m_NumBoneWeights > 1 ) - { - // This path for 3 weights per vert (2 are stored and the 3rd is computed - // in the shader - we do post-quantization normalization here in such a - // way as to avoid mesh-boundary cracking) - Assert( m_NumBoneWeights == 2 ); - Assert( IsFinite( pWeights[1] ) && ( pWeights[1] >= 0.0f ) && ( pWeights[1] <= 1.0f ) ); - Assert( IsFinite( pWeights[2] ) && ( pWeights[2] >= 0.0f ) && ( pWeights[2] <= 1.0f ) ); - unsigned int weight1 = Float2Int( pWeights[1] * 32768.0f ); - unsigned int weight2 = Float2Int( pWeights[2] * 32768.0f ); - Assert( ( weight0 + weight1 + weight2 ) <= 32768 ); - unsigned int residual = 32768 - ( weight0 + weight1 + weight2 ); - weight1 += residual; // Normalize - *weights |= ( 0x0000FFFF & ( weight1 - 1 ) ) << WEIGHT1_SHIFT; - } - } - else // Uncompressed path - { - pDestWeights[0] = pWeights[0]; - pDestWeights[1] = pWeights[1]; - } -} - -//----------------------------------------------------------------------------- -// Generic per-vertex data setting method -//----------------------------------------------------------------------------- -inline void CVertexBuilder::UserData( const float* pData ) -{ - Assert( m_CompressionType == VERTEX_COMPRESSION_NONE ); // Use the templatized version if you want to support compression - Assert( pData ); - - int userDataSize = 4; // garymcthack - float *pUserData = OffsetFloatPointer( m_pUserData, m_nCurrentVertex, m_VertexSize_UserData ); - memcpy( pUserData, pData, sizeof( float ) * userDataSize ); -} - -//----------------------------------------------------------------------------- -// Templatized generic per-vertex data setting method which supports compressed vertices -//----------------------------------------------------------------------------- -template inline void CVertexBuilder::CompressedUserData( const float* pData ) -{ - Assert( T == m_CompressionType ); - Assert( pData ); - // This is always in fact a tangent vector, not generic 'userdata' - Assert( IsFinite(pData[0]) && IsFinite(pData[1]) && IsFinite(pData[2]) ); - Assert( pData[0] >= -1.05f && pData[0] <= 1.05f ); - Assert( pData[1] >= -1.05f && pData[1] <= 1.05f ); - Assert( pData[2] >= -1.05f && pData[2] <= 1.05f ); - Assert( pData[3] == +1.0f || pData[3] == -1.0f ); - // FIXME: studiorender is passing in non-unit normals - //float lengthSqd = pData[0]*pData[0] + pData[1]*pData[1] + pData[2]*pData[2]; - //Assert( lengthSqd >= 0.95f && lengthSqd <= 1.05f ); - - if ( T == VERTEX_COMPRESSION_ON ) - { - float binormalSign = pData[3]; - -#if ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 ) - float *pUserData = OffsetFloatPointer( m_pUserData, m_nCurrentVertex, m_VertexSize_UserData ); - PackNormal_SHORT2( pData, (unsigned int *)pUserData, binormalSign ); -#else //( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 ) - // FIXME: add a combined CompressedNormalAndTangent() accessor, to avoid reading back from write-combined memory here - // The normal should have already been written into the lower 16 - // bits - here, we OR in the tangent into the upper 16 bits - unsigned int existingNormalData = *(unsigned int *)m_pCurrNormal; - Assert( ( existingNormalData & 0xFFFF0000 ) == 0 ); -#ifdef _DEBUG - Assert( m_bWrittenNormal == true ); - m_bWrittenUserData = true; -#endif - bool bIsTangent = true; - unsigned int tangentData = 0; - PackNormal_UBYTE4( pData, &tangentData, bIsTangent, binormalSign ); - *(unsigned int *)m_pCurrNormal = existingNormalData | tangentData; -#endif - } - else - { - int userDataSize = 4; // garymcthack - float *pUserData = OffsetFloatPointer( m_pUserData, m_nCurrentVertex, m_VertexSize_UserData ); - memcpy( pUserData, pData, sizeof( float ) * userDataSize ); - } -} - - -//----------------------------------------------------------------------------- -// -// Helper class used to define index buffers -// -//----------------------------------------------------------------------------- -class CIndexBuilder : private IndexDesc_t -{ -public: - CIndexBuilder(); - CIndexBuilder( IIndexBuffer *pIndexBuffer, MaterialIndexFormat_t fmt = MATERIAL_INDEX_FORMAT_UNKNOWN ); - ~CIndexBuilder(); - - // Begins, ends modification of the index buffer (returns true if the lock succeeded) - // A lock may not succeed if append is set to true and there isn't enough room - // NOTE: Append is only used with dynamic index buffers; it's ignored for static buffers - bool Lock( int nMaxIndexCount, int nIndexOffset, bool bAppend = false ); - void Unlock(); - - // Spews the current data - // NOTE: Can only be called during a lock/unlock block - void SpewData(); - - // Returns the number of indices we can fit into the buffer without needing to discard - int GetRoomRemaining() const; - - // Binds this index buffer - void Bind( IMatRenderContext *pContext ); - - // Returns the byte offset - int Offset() const; - - // Begins, ends modification of the index buffer - // NOTE: IndexOffset is the number to add to all indices written into the buffer; - // useful when using dynamic vertex buffers. - void Begin( IIndexBuffer *pIndexBuffer, int nMaxIndexCount, int nIndexOffset = 0 ); - void End( bool bSpewData = false ); - - // Locks the index buffer to modify existing data - // Passing nVertexCount == -1 says to lock all the vertices for modification. - // Pass 0 for nIndexCount to not lock the index buffer. - void BeginModify( IIndexBuffer *pIndexBuffer, int nFirstIndex = 0, int nIndexCount = 0, int nIndexOffset = 0 ); - void EndModify( bool bSpewData = false ); - - // returns the number of indices - int IndexCount() const; - - // Returns the total number of indices across all Locks() - int TotalIndexCount() const; - - // Resets the mesh builder so it points to the start of everything again - void Reset(); - - // Selects the nth Index - void SelectIndex( int nBufferIndex ); - - // Advances the current index by one - void AdvanceIndex(); - void AdvanceIndices( int nIndexCount ); - - int GetCurrentIndex(); - int GetFirstIndex() const; - - unsigned short const* Index() const; - - // Used to define the indices (only used if you aren't using primitives) - void Index( unsigned short nIndex ); - - // Fast Index! No need to call advance index, and no random access allowed - void FastIndex( unsigned short nIndex ); - - // NOTE: This version is the one you really want to achieve write-combining; - // Write combining only works if you write in 4 bytes chunks. - void FastIndex2( unsigned short nIndex1, unsigned short nIndex2 ); - - // Generates indices for a particular primitive type - void GenerateIndices( MaterialPrimitiveType_t primitiveType, int nIndexCount ); - - // FIXME: Remove! Backward compat so we can use this from a CMeshBuilder. - void AttachBegin( IMesh* pMesh, int nMaxIndexCount, const MeshDesc_t &desc ); - void AttachEnd(); - void AttachBeginModify( IMesh* pMesh, int nFirstIndex, int nIndexCount, const MeshDesc_t &desc ); - void AttachEndModify(); - -private: - // The mesh we're modifying - IIndexBuffer *m_pIndexBuffer; - - // Max number of indices - int m_nMaxIndexCount; - - // Number of indices - int m_nIndexCount; - - // Offset to add to each index as it's written into the buffer - int m_nIndexOffset; - - // The current index - mutable int m_nCurrentIndex; - - // Total number of indices appended - int m_nTotalIndexCount; - - // First index buffer offset + first index - unsigned int m_nBufferOffset; - unsigned int m_nBufferFirstIndex; - - // Used to make sure Begin/End calls and BeginModify/EndModify calls match. - bool m_bModify; -}; - - -//----------------------------------------------------------------------------- -// -// Inline methods related to CIndexBuilder -// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -inline CIndexBuilder::CIndexBuilder() : m_pIndexBuffer(0), m_nIndexCount(0), - m_nCurrentIndex(0), m_nMaxIndexCount(0) -{ - m_nTotalIndexCount = 0; - m_nBufferOffset = INVALID_BUFFER_OFFSET; - m_nBufferFirstIndex = 0; -#ifdef _DEBUG - m_bModify = false; -#endif -} - -inline CIndexBuilder::CIndexBuilder( IIndexBuffer *pIndexBuffer, MaterialIndexFormat_t fmt ) -{ - m_pIndexBuffer = pIndexBuffer; - m_nBufferOffset = INVALID_BUFFER_OFFSET; - m_nBufferFirstIndex = 0; - m_nIndexCount = 0; - m_nCurrentIndex = 0; - m_nMaxIndexCount = 0; - m_nTotalIndexCount = 0; - if ( m_pIndexBuffer->IsDynamic() ) - { - m_pIndexBuffer->BeginCastBuffer( fmt ); - } - else - { - Assert( m_pIndexBuffer->IndexFormat() == fmt ); - } -#ifdef _DEBUG - m_bModify = false; -#endif -} - -inline CIndexBuilder::~CIndexBuilder() -{ - if ( m_pIndexBuffer && m_pIndexBuffer->IsDynamic() ) - { - m_pIndexBuffer->EndCastBuffer(); - } -} - - -//----------------------------------------------------------------------------- -// Begins, ends modification of the index buffer -//----------------------------------------------------------------------------- -inline bool CIndexBuilder::Lock( int nMaxIndexCount, int nIndexOffset, bool bAppend ) -{ - Assert( m_pIndexBuffer ); - m_bModify = false; - m_nIndexOffset = nIndexOffset; - m_nMaxIndexCount = nMaxIndexCount; - bool bFirstLock = ( m_nBufferOffset == INVALID_BUFFER_OFFSET ); - if ( bFirstLock ) - { - bAppend = false; - } - if ( !bAppend ) - { - m_nTotalIndexCount = 0; - } - Reset(); - - // Lock the index buffer - if ( !m_pIndexBuffer->Lock( m_nMaxIndexCount, bAppend, *this ) ) - { - m_nMaxIndexCount = 0; - return false; - } - - if ( bFirstLock ) - { - m_nBufferOffset = m_nOffset; - m_nBufferFirstIndex = m_nFirstIndex; - } - - return true; -} - -inline void CIndexBuilder::Unlock() -{ - Assert( !m_bModify && m_pIndexBuffer ); - - m_pIndexBuffer->Unlock( m_nIndexCount, *this ); - m_nTotalIndexCount += m_nIndexCount; - - m_nMaxIndexCount = 0; - -#ifdef _DEBUG - // Null out our data... - memset( (IndexDesc_t*)this, 0, sizeof(IndexDesc_t) ); -#endif -} - -inline void CIndexBuilder::SpewData() -{ - m_pIndexBuffer->Spew( m_nIndexCount, *this ); -} - - -//----------------------------------------------------------------------------- -// Binds this index buffer -//----------------------------------------------------------------------------- -inline void CIndexBuilder::Bind( IMatRenderContext *pContext ) -{ - if ( m_pIndexBuffer && ( m_nBufferOffset != INVALID_BUFFER_OFFSET ) ) - { - pContext->BindIndexBuffer( m_pIndexBuffer, m_nBufferOffset ); - } - else - { - pContext->BindIndexBuffer( NULL, 0 ); - } -} - - -//----------------------------------------------------------------------------- -// Returns the byte offset -//----------------------------------------------------------------------------- -inline int CIndexBuilder::Offset() const -{ - return m_nBufferOffset; -} - -inline int CIndexBuilder::GetFirstIndex() const -{ - return m_nBufferFirstIndex; -} - - -//----------------------------------------------------------------------------- -// Begins, ends modification of the index buffer -//----------------------------------------------------------------------------- -inline void CIndexBuilder::Begin( IIndexBuffer *pIndexBuffer, int nMaxIndexCount, int nIndexOffset ) -{ - Assert( pIndexBuffer && (!m_pIndexBuffer) ); - - m_pIndexBuffer = pIndexBuffer; - m_nIndexCount = 0; - m_nMaxIndexCount = nMaxIndexCount; - m_nIndexOffset = nIndexOffset; - - m_bModify = false; - - // Lock the index buffer - m_pIndexBuffer->Lock( m_nMaxIndexCount, false, *this ); - - // Point to the start of the buffers.. - Reset(); -} - -inline void CIndexBuilder::End( bool bSpewData ) -{ - // Make sure they called Begin() - Assert( !m_bModify ); - - if ( bSpewData ) - { - m_pIndexBuffer->Spew( m_nIndexCount, *this ); - } - - // Unlock our buffers - m_pIndexBuffer->Unlock( m_nIndexCount, *this ); - - m_pIndexBuffer = 0; - m_nMaxIndexCount = 0; - -#ifdef _DEBUG - // Null out our data... - memset( (IndexDesc_t*)this, 0, sizeof(IndexDesc_t) ); -#endif -} - - -//----------------------------------------------------------------------------- -// Begins, ends modification of an existing index buffer which has already been filled out -//----------------------------------------------------------------------------- -inline void CIndexBuilder::BeginModify( IIndexBuffer* pIndexBuffer, int nFirstIndex, int nIndexCount, int nIndexOffset ) -{ - m_pIndexBuffer = pIndexBuffer; - m_nIndexCount = nIndexCount; - m_nMaxIndexCount = nIndexCount; - m_nIndexOffset = nIndexOffset; - m_bModify = true; - - // Lock the vertex and index buffer - m_pIndexBuffer->ModifyBegin( false, nFirstIndex, nIndexCount, *this ); - - // Point to the start of the buffers.. - Reset(); -} - -inline void CIndexBuilder::EndModify( bool bSpewData ) -{ - Assert( m_pIndexBuffer ); - Assert( m_bModify ); // Make sure they called BeginModify. - - if ( bSpewData ) - { - m_pIndexBuffer->Spew( m_nIndexCount, *this ); - } - - // Unlock our buffers - m_pIndexBuffer->ModifyEnd( *this ); - - m_pIndexBuffer = 0; - m_nMaxIndexCount = 0; - -#ifdef _DEBUG - // Null out our data... - memset( (IndexDesc_t*)this, 0, sizeof(IndexDesc_t) ); -#endif -} - - -//----------------------------------------------------------------------------- -// FIXME: Remove! Backward compat so we can use this from a CMeshBuilder. -//----------------------------------------------------------------------------- -inline void CIndexBuilder::AttachBegin( IMesh* pMesh, int nMaxIndexCount, const MeshDesc_t &desc ) -{ - m_pIndexBuffer = pMesh; - m_nIndexCount = 0; - m_nMaxIndexCount = nMaxIndexCount; - - m_bModify = false; - - // Copy relevant data from the mesh desc - m_nIndexOffset = desc.m_nFirstVertex; - m_pIndices = desc.m_pIndices; - m_nIndexSize = desc.m_nIndexSize; - - // Point to the start of the buffers.. - Reset(); -} - -inline void CIndexBuilder::AttachEnd() -{ - Assert( m_pIndexBuffer ); - Assert( !m_bModify ); // Make sure they called AttachBegin. - - m_pIndexBuffer = 0; - m_nMaxIndexCount = 0; - -#ifdef _DEBUG - // Null out our data... - memset( (IndexDesc_t*)this, 0, sizeof(IndexDesc_t) ); -#endif -} - -inline void CIndexBuilder::AttachBeginModify( IMesh* pMesh, int nFirstIndex, int nIndexCount, const MeshDesc_t &desc ) -{ - m_pIndexBuffer = pMesh; - m_nIndexCount = nIndexCount; - m_nMaxIndexCount = nIndexCount; - m_bModify = true; - - // Copy relevant data from the mesh desc - m_nIndexOffset = desc.m_nFirstVertex; - m_pIndices = desc.m_pIndices; - m_nIndexSize = desc.m_nIndexSize; - - // Point to the start of the buffers.. - Reset(); -} - -inline void CIndexBuilder::AttachEndModify() -{ - Assert( m_pIndexBuffer ); - Assert( m_bModify ); // Make sure they called AttachBeginModify. - - m_pIndexBuffer = 0; - m_nMaxIndexCount = 0; - -#ifdef _DEBUG - // Null out our data... - memset( (IndexDesc_t*)this, 0, sizeof(IndexDesc_t) ); -#endif -} - - -//----------------------------------------------------------------------------- -// Resets the index buffer builder so it points to the start of everything again -//----------------------------------------------------------------------------- -inline void CIndexBuilder::Reset() -{ - m_nCurrentIndex = 0; -} - - -//----------------------------------------------------------------------------- -// returns the number of indices -//----------------------------------------------------------------------------- -inline int CIndexBuilder::IndexCount() const -{ - return m_nIndexCount; -} - - -//----------------------------------------------------------------------------- -// Returns the total number of indices across all Locks() -//----------------------------------------------------------------------------- -inline int CIndexBuilder::TotalIndexCount() const -{ - return m_nTotalIndexCount; -} - - -//----------------------------------------------------------------------------- -// Advances the current index -//----------------------------------------------------------------------------- -inline void CIndexBuilder::AdvanceIndex() -{ - m_nCurrentIndex += m_nIndexSize; - if ( m_nCurrentIndex > m_nIndexCount ) - { - m_nIndexCount = m_nCurrentIndex; - } -} - -inline void CIndexBuilder::AdvanceIndices( int nIndices ) -{ - m_nCurrentIndex += nIndices * m_nIndexSize; - if ( m_nCurrentIndex > m_nIndexCount ) - { - m_nIndexCount = m_nCurrentIndex; - } -} - - -//----------------------------------------------------------------------------- -// Returns the current index -//----------------------------------------------------------------------------- -inline int CIndexBuilder::GetCurrentIndex() -{ - return m_nCurrentIndex; -} - -inline unsigned short const* CIndexBuilder::Index() const -{ - Assert( m_nCurrentIndex < m_nMaxIndexCount ); - return &m_pIndices[m_nCurrentIndex]; -} - -inline void CIndexBuilder::SelectIndex( int nIndex ) -{ - Assert( ( nIndex >= 0 ) && ( nIndex < m_nIndexCount ) ); - m_nCurrentIndex = nIndex * m_nIndexSize; -} - - -//----------------------------------------------------------------------------- -// Used to write data into the index buffer -//----------------------------------------------------------------------------- -inline void CIndexBuilder::Index( unsigned short nIndex ) -{ - Assert( m_pIndices ); - Assert( m_nCurrentIndex < m_nMaxIndexCount ); - m_pIndices[ m_nCurrentIndex ] = (unsigned short)( m_nIndexOffset + nIndex ); -} - -// Fast Index! No need to call advance index -inline void CIndexBuilder::FastIndex( unsigned short nIndex ) -{ - Assert( m_pIndices ); - Assert( m_nCurrentIndex < m_nMaxIndexCount ); - m_pIndices[m_nCurrentIndex] = (unsigned short)( m_nIndexOffset + nIndex ); - m_nCurrentIndex += m_nIndexSize; - m_nIndexCount = m_nCurrentIndex; -} - -//----------------------------------------------------------------------------- -// NOTE: This version is the one you really want to achieve write-combining; -// Write combining only works if you write in 4 bytes chunks. -//----------------------------------------------------------------------------- -inline void CIndexBuilder::FastIndex2( unsigned short nIndex1, unsigned short nIndex2 ) -{ - Assert( m_pIndices ); - Assert( m_nCurrentIndex < m_nMaxIndexCount - 1 ); -// Assert( ( (int)( &m_pIndices[m_nCurrentIndex] ) & 0x3 ) == 0 ); - -#ifndef _X360 - unsigned int nIndices = ( (unsigned int)nIndex1 + m_nIndexOffset ) | ( ( (unsigned int)nIndex2 + m_nIndexOffset ) << 16 ); -#else - unsigned int nIndices = ( (unsigned int)nIndex2 + m_nIndexOffset ) | ( ( (unsigned int)nIndex1 + m_nIndexOffset ) << 16 ); -#endif - - *(int*)( &m_pIndices[m_nCurrentIndex] ) = nIndices; - m_nCurrentIndex += m_nIndexSize + m_nIndexSize; - m_nIndexCount = m_nCurrentIndex; -} - - -//----------------------------------------------------------------------------- -// Generates indices for a particular primitive type -//----------------------------------------------------------------------------- -inline void CIndexBuilder::GenerateIndices( MaterialPrimitiveType_t primitiveType, int nIndexCount ) -{ - // FIXME: How to make this work with short vs int sized indices? - // Don't generate indices if we've got an empty buffer - if ( m_nIndexSize == 0 ) - return; - - int nMaxIndices = m_nMaxIndexCount - m_nCurrentIndex; - nIndexCount = MIN( nMaxIndices, nIndexCount ); - if ( nIndexCount == 0 ) - return; - - unsigned short *pIndices = &m_pIndices[m_nCurrentIndex]; - - switch( primitiveType ) - { - case MATERIAL_INSTANCED_QUADS: - Assert(0); // Shouldn't get here (this primtype is unindexed) - break; - case MATERIAL_QUADS: - GenerateQuadIndexBuffer( pIndices, nIndexCount, m_nIndexOffset ); - break; - case MATERIAL_POLYGON: - GeneratePolygonIndexBuffer( pIndices, nIndexCount, m_nIndexOffset ); - break; - case MATERIAL_LINE_STRIP: - GenerateLineStripIndexBuffer( pIndices, nIndexCount, m_nIndexOffset ); - break; - case MATERIAL_LINE_LOOP: - GenerateLineLoopIndexBuffer( pIndices, nIndexCount, m_nIndexOffset ); - break; - case MATERIAL_POINTS: - Assert(0); // Shouldn't get here (this primtype is unindexed) - break; - default: - GenerateSequentialIndexBuffer( pIndices, nIndexCount, m_nIndexOffset ); - break; - } - - AdvanceIndices( nIndexCount ); -} - - -//----------------------------------------------------------------------------- -// -// Helper class used to define meshes -// -//----------------------------------------------------------------------------- -//class CMeshBuilder : private MeshDesc_t -// hack fixme -class CMeshBuilder : public MeshDesc_t -{ -public: - CMeshBuilder(); - ~CMeshBuilder() { Assert(!m_pMesh); } // if this fires you did a Begin() without an End() - - // This must be called before Begin, if a vertex buffer with a compressed format is to be used - void SetCompressionType( VertexCompressionType_t compressionType ); - - // Locks the vertex buffer - // (*cannot* use the Index() call below) - void Begin( IMesh *pMesh, MaterialPrimitiveType_t type, int numPrimitives ); - - // Locks the vertex buffer, can specify arbitrary index lists - // (must use the Index() call below) - void Begin( IMesh *pMesh, MaterialPrimitiveType_t type, int nVertexCount, int nIndexCount, int *nFirstVertex ); - void Begin( IMesh *pMesh, MaterialPrimitiveType_t type, int nVertexCount, int nIndexCount ); - - // forward compat - void Begin( IVertexBuffer *pVertexBuffer, MaterialPrimitiveType_t type, int numPrimitives ); - void Begin( IVertexBuffer *pVertexBuffer, IIndexBuffer *pIndexBuffer, MaterialPrimitiveType_t type, int nVertexCount, int nIndexCount, int *nFirstVertex ); - void Begin( IVertexBuffer *pVertexBuffer, IIndexBuffer *pIndexBuffer, MaterialPrimitiveType_t type, int nVertexCount, int nIndexCount ); - - // Use this when you're done writing - // Set bDraw to true to call m_pMesh->Draw automatically. - void End( bool bSpewData = false, bool bDraw = false ); - - // Locks the vertex buffer to modify existing data - // Passing nVertexCount == -1 says to lock all the vertices for modification. - // Pass 0 for nIndexCount to not lock the index buffer. - void BeginModify( IMesh *pMesh, int nFirstVertex = 0, int nVertexCount = -1, int nFirstIndex = 0, int nIndexCount = 0 ); - void EndModify( bool bSpewData = false ); - - // A helper method since this seems to be done a whole bunch. - void DrawQuad( IMesh* pMesh, const float *v1, const float *v2, - const float *v3, const float *v4, unsigned char const *pColor, bool wireframe = false ); - - // returns the number of indices and vertices - int VertexCount() const; - int IndexCount() const; - - // Resets the mesh builder so it points to the start of everything again - void Reset(); - - // Returns the size of the vertex - int VertexSize() { return m_ActualVertexSize; } - - // returns the data size of a given texture coordinate - int TextureCoordinateSize( int nTexCoordNumber ) { return m_VertexSize_TexCoord[ nTexCoordNumber ]; } - - // Returns the base vertex memory pointer - void* BaseVertexData(); - - // Selects the nth Vertex and Index - void SelectVertex( int idx ); - void SelectIndex( int idx ); - - // Given an index, point to the associated vertex - void SelectVertexFromIndex( int idx ); - - // Advances the current vertex and index by one - void AdvanceVertex(); - void AdvanceVertices( int nVerts ); - void AdvanceIndex(); - void AdvanceIndices( int nIndices ); - - int GetCurrentVertex(); - int GetCurrentIndex(); - - // Data retrieval... - const float *Position() const; - - const float *Normal() const; - - unsigned int Color() const; - - unsigned char *Specular() const; - - const float *TexCoord( int stage ) const; - - const float *TangentS() const; - const float *TangentT() const; - - const float *BoneWeight() const; - float Wrinkle() const; - - int NumBoneWeights() const; -#ifndef NEW_SKINNING - unsigned char *BoneMatrix() const; -#else - float *BoneMatrix() const; -#endif - unsigned short const *Index() const; - - // position setting - void Position3f( float x, float y, float z ); - void Position3fv( const float *v ); - - // normal setting - void Normal3f( float nx, float ny, float nz ); - void Normal3fv( const float *n ); - void NormalDelta3fv( const float *n ); - void NormalDelta3f( float nx, float ny, float nz ); - - // normal setting (templatized for code which needs to support compressed vertices) - template void CompressedNormal3f( float nx, float ny, float nz ); - template void CompressedNormal3fv( const float *n ); - - // color setting - void Color3f( float r, float g, float b ); - void Color3fv( const float *rgb ); - void Color4f( float r, float g, float b, float a ); - void Color4fv( const float *rgba ); - - // Faster versions of color - void Color3ub( unsigned char r, unsigned char g, unsigned char b ); - void Color3ubv( unsigned char const* rgb ); - void Color4ub( unsigned char r, unsigned char g, unsigned char b, unsigned char a ); - void Color4ubv( unsigned char const* rgba ); - - // specular color setting - void Specular3f( float r, float g, float b ); - void Specular3fv( const float *rgb ); - void Specular4f( float r, float g, float b, float a ); - void Specular4fv( const float *rgba ); - - // Faster version of specular - void Specular3ub( unsigned char r, unsigned char g, unsigned char b ); - void Specular3ubv( unsigned char const *c ); - void Specular4ub( unsigned char r, unsigned char g, unsigned char b, unsigned char a ); - void Specular4ubv( unsigned char const *c ); - - // texture coordinate setting - void TexCoord1f( int stage, float s ); - void TexCoord2f( int stage, float s, float t ); - void TexCoord2fv( int stage, const float *st ); - void TexCoord3f( int stage, float s, float t, float u ); - void TexCoord3fv( int stage, const float *stu ); - void TexCoord4f( int stage, float s, float t, float u, float w ); - void TexCoord4fv( int stage, const float *stuv ); - - void TexCoordSubRect2f( int stage, float s, float t, float offsetS, float offsetT, float scaleS, float scaleT ); - void TexCoordSubRect2fv( int stage, const float *st, const float *offset, const float *scale ); - - // tangent space - void TangentS3f( float sx, float sy, float sz ); - void TangentS3fv( const float *s ); - - void TangentT3f( float tx, float ty, float tz ); - void TangentT3fv( const float *t ); - - // Wrinkle - void Wrinkle1f( float flWrinkle ); - - // bone weights - void BoneWeight( int idx, float weight ); - // bone weights (templatized for code which needs to support compressed vertices) - template void CompressedBoneWeight3fv( const float * pWeights ); - - // bone matrix index - void BoneMatrix( int idx, int matrixIndex ); - - // Generic per-vertex data - void UserData( const float *pData ); - // Generic per-vertex data (templatized for code which needs to support compressed vertices) - template void CompressedUserData( const float* pData ); - - // Used to define the indices (only used if you aren't using primitives) - void Index( unsigned short index ); - - // NOTE: Use this one to get write combining! Much faster than the other version of FastIndex - // Fast Index! No need to call advance index, and no random access allowed - void FastIndex2( unsigned short nIndex1, unsigned short nIndex2 ); - - // Fast Index! No need to call advance index, and no random access allowed - void FastIndex( unsigned short index ); - - // Fast Vertex! No need to call advance vertex, and no random access allowed. - // WARNING - these are low level functions that are intended only for use - // in the software vertex skinner. - void FastVertex( const ModelVertexDX7_t &vertex ); - void FastVertexSSE( const ModelVertexDX7_t &vertex ); - - // store 4 dx7 vertices fast. for special sse dx7 pipeline - void Fast4VerticesSSE( - ModelVertexDX7_t const *vtx_a, - ModelVertexDX7_t const *vtx_b, - ModelVertexDX7_t const *vtx_c, - ModelVertexDX7_t const *vtx_d); - - void FastVertex( const ModelVertexDX8_t &vertex ); - void FastVertexSSE( const ModelVertexDX8_t &vertex ); - - // Add number of verts and current vert since FastVertexxx routines do not update. - void FastAdvanceNVertices(int n); - -#if defined( _X360 ) - void VertexDX8ToX360( const ModelVertexDX8_t &vertex ); -#endif - -private: - // Computes number of verts and indices - void ComputeNumVertsAndIndices( int *pMaxVertices, int *pMaxIndices, - MaterialPrimitiveType_t type, int nPrimitiveCount ); - int IndicesFromVertices( MaterialPrimitiveType_t type, int nVertexCount ); - - // The mesh we're modifying - IMesh *m_pMesh; - - MaterialPrimitiveType_t m_Type; - - // Generate indices? - bool m_bGenerateIndices; - - CIndexBuilder m_IndexBuilder; - CVertexBuilder m_VertexBuilder; -}; - - -//----------------------------------------------------------------------------- -// Forward compat -//----------------------------------------------------------------------------- -inline void CMeshBuilder::Begin( IVertexBuffer* pVertexBuffer, MaterialPrimitiveType_t type, int numPrimitives ) -{ - Assert( 0 ); - // Begin( pVertexBuffer->GetMesh(), type, numPrimitives ); -} - -inline void CMeshBuilder::Begin( IVertexBuffer* pVertexBuffer, IIndexBuffer *pIndexBuffer, MaterialPrimitiveType_t type, int nVertexCount, int nIndexCount, int *nFirstVertex ) -{ - Assert( 0 ); - // Begin( pVertexBuffer->GetMesh(), type, nVertexCount, nIndexCount, nFirstVertex ); -} - -inline void CMeshBuilder::Begin( IVertexBuffer* pVertexBuffer, IIndexBuffer *pIndexBuffer, MaterialPrimitiveType_t type, int nVertexCount, int nIndexCount ) -{ - Assert( 0 ); - // Begin( pVertexBuffer->GetMesh(), type, nVertexCount, nIndexCount ); -} - - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -inline CMeshBuilder::CMeshBuilder() : m_pMesh(0), m_bGenerateIndices(false) -{ -} - - -//----------------------------------------------------------------------------- -// Computes the number of verts and indices based on primitive type and count -//----------------------------------------------------------------------------- -inline void CMeshBuilder::ComputeNumVertsAndIndices( int *pMaxVertices, int *pMaxIndices, - MaterialPrimitiveType_t type, int nPrimitiveCount ) -{ - switch(type) - { - case MATERIAL_POINTS: - *pMaxVertices = *pMaxIndices = nPrimitiveCount; - break; - - case MATERIAL_LINES: - *pMaxVertices = *pMaxIndices = nPrimitiveCount * 2; - break; - - case MATERIAL_LINE_STRIP: - *pMaxVertices = nPrimitiveCount + 1; - *pMaxIndices = nPrimitiveCount * 2; - break; - - case MATERIAL_LINE_LOOP: - *pMaxVertices = nPrimitiveCount; - *pMaxIndices = nPrimitiveCount * 2; - break; - - case MATERIAL_TRIANGLES: - *pMaxVertices = *pMaxIndices = nPrimitiveCount * 3; - break; - - case MATERIAL_TRIANGLE_STRIP: - *pMaxVertices = *pMaxIndices = nPrimitiveCount + 2; - break; - - case MATERIAL_QUADS: - *pMaxVertices = nPrimitiveCount * 4; - *pMaxIndices = nPrimitiveCount * 6; - break; - - case MATERIAL_INSTANCED_QUADS: - *pMaxVertices = nPrimitiveCount; - *pMaxIndices = 0; // This primtype is unindexed - break; - - case MATERIAL_POLYGON: - *pMaxVertices = nPrimitiveCount; - *pMaxIndices = (nPrimitiveCount - 2) * 3; - break; - - default: - Assert(0); - } - - // FIXME: need to get this from meshdx8.cpp, or move it to somewhere common - Assert( *pMaxVertices <= 32768 ); - Assert( *pMaxIndices <= 32768 ); -} - - -inline int CMeshBuilder::IndicesFromVertices( MaterialPrimitiveType_t type, int nVertexCount ) -{ - switch( type ) - { - case MATERIAL_QUADS: - Assert( (nVertexCount & 0x3) == 0 ); - return (nVertexCount * 6) / 4; - - case MATERIAL_INSTANCED_QUADS: - // This primtype is unindexed - return 0; - - case MATERIAL_POLYGON: - Assert( nVertexCount >= 3 ); - return (nVertexCount - 2) * 3; - - case MATERIAL_LINE_STRIP: - Assert( nVertexCount >= 2 ); - return (nVertexCount - 1) * 2; - - case MATERIAL_LINE_LOOP: - Assert( nVertexCount >= 3 ); - return nVertexCount * 2; - - default: - return nVertexCount; - } -} - -//----------------------------------------------------------------------------- -// Specify the type of vertex compression that this CMeshBuilder will perform -//----------------------------------------------------------------------------- -inline void CMeshBuilder::SetCompressionType( VertexCompressionType_t vertexCompressionType ) -{ - m_VertexBuilder.SetCompressionType( vertexCompressionType ); -} - -//----------------------------------------------------------------------------- -// Begins modifying the mesh -//----------------------------------------------------------------------------- -inline void CMeshBuilder::Begin( IMesh *pMesh, MaterialPrimitiveType_t type, int numPrimitives ) -{ - Assert( pMesh && (!m_pMesh) ); - Assert( type != MATERIAL_HETEROGENOUS ); - - m_pMesh = pMesh; - m_bGenerateIndices = true; - m_Type = type; - - int nMaxVertexCount, nMaxIndexCount; - ComputeNumVertsAndIndices( &nMaxVertexCount, &nMaxIndexCount, type, numPrimitives ); - - switch( type ) - { - case MATERIAL_INSTANCED_QUADS: - m_pMesh->SetPrimitiveType( MATERIAL_INSTANCED_QUADS ); - break; - - case MATERIAL_QUADS: - case MATERIAL_POLYGON: - m_pMesh->SetPrimitiveType( MATERIAL_TRIANGLES ); - break; - - case MATERIAL_LINE_STRIP: - case MATERIAL_LINE_LOOP: - m_pMesh->SetPrimitiveType( MATERIAL_LINES ); - break; - - default: - m_pMesh->SetPrimitiveType( type ); - } - - // Lock the mesh - m_pMesh->LockMesh( nMaxVertexCount, nMaxIndexCount, *this ); - - m_IndexBuilder.AttachBegin( pMesh, nMaxIndexCount, *this ); - m_VertexBuilder.AttachBegin( pMesh, nMaxVertexCount, *this ); - - // Point to the start of the index and vertex buffers - Reset(); -} - -inline void CMeshBuilder::Begin( IMesh *pMesh, MaterialPrimitiveType_t type, int nVertexCount, int nIndexCount, int *nFirstVertex ) -{ - Begin( pMesh, type, nVertexCount, nIndexCount ); - - *nFirstVertex = m_VertexBuilder.m_nFirstVertex * m_VertexBuilder.VertexSize(); -} - -inline void CMeshBuilder::Begin( IMesh* pMesh, MaterialPrimitiveType_t type, int nVertexCount, int nIndexCount ) -{ - Assert( pMesh && (!m_pMesh) ); - - // NOTE: We can't specify the indices when we use quads, polygons, or - // linestrips; they aren't actually directly supported by - // the material system - Assert( (type != MATERIAL_QUADS) && (type != MATERIAL_INSTANCED_QUADS) && (type != MATERIAL_POLYGON) && - (type != MATERIAL_LINE_STRIP) && (type != MATERIAL_LINE_LOOP)); - - // Dx8 doesn't support indexed points... - Assert( type != MATERIAL_POINTS ); - - m_pMesh = pMesh; - m_bGenerateIndices = false; - m_Type = type; - - // Set the primitive type - m_pMesh->SetPrimitiveType( type ); - - // Lock the vertex and index buffer - m_pMesh->LockMesh( nVertexCount, nIndexCount, *this ); - - m_IndexBuilder.AttachBegin( pMesh, nIndexCount, *this ); - m_VertexBuilder.AttachBegin( pMesh, nVertexCount, *this ); - - // Point to the start of the buffers.. - Reset(); -} - - -//----------------------------------------------------------------------------- -// Use this when you're done modifying the mesh -//----------------------------------------------------------------------------- -inline void CMeshBuilder::End( bool bSpewData, bool bDraw ) -{ - if ( m_bGenerateIndices ) - { - int nIndexCount = IndicesFromVertices( m_Type, m_VertexBuilder.VertexCount() ); - m_IndexBuilder.GenerateIndices( m_Type, nIndexCount ); - } - - if ( bSpewData ) - { - m_pMesh->Spew( m_VertexBuilder.VertexCount(), m_IndexBuilder.IndexCount(), *this ); - } - -#ifdef _DEBUG - m_pMesh->ValidateData( m_VertexBuilder.VertexCount(), m_IndexBuilder.IndexCount(), *this ); -#endif - - // Unlock our buffers - m_pMesh->UnlockMesh( m_VertexBuilder.VertexCount(), m_IndexBuilder.IndexCount(), *this ); - - m_IndexBuilder.AttachEnd(); - m_VertexBuilder.AttachEnd(); - - if ( bDraw ) - { - m_pMesh->Draw(); - } - - m_pMesh = 0; - -#ifdef _DEBUG - memset( (MeshDesc_t*)this, 0, sizeof(MeshDesc_t) ); -#endif -} - - -//----------------------------------------------------------------------------- -// Locks the vertex buffer to modify existing data -//----------------------------------------------------------------------------- -inline void CMeshBuilder::BeginModify( IMesh* pMesh, int nFirstVertex, int nVertexCount, int nFirstIndex, int nIndexCount ) -{ - Assert( pMesh && (!m_pMesh) ); - - if (nVertexCount < 0) - { - nVertexCount = pMesh->VertexCount(); - } - - m_pMesh = pMesh; - m_bGenerateIndices = false; - - // Locks mesh for modifying - pMesh->ModifyBeginEx( false, nFirstVertex, nVertexCount, nFirstIndex, nIndexCount, *this ); - - m_IndexBuilder.AttachBeginModify( pMesh, nFirstIndex, nIndexCount, *this ); - m_VertexBuilder.AttachBeginModify( pMesh, nFirstVertex, nVertexCount, *this ); - - // Point to the start of the buffers.. - Reset(); -} - -inline void CMeshBuilder::EndModify( bool bSpewData ) -{ - Assert( m_pMesh ); - - if (bSpewData) - { - m_pMesh->Spew( m_VertexBuilder.VertexCount(), m_IndexBuilder.IndexCount(), *this ); - } -#ifdef _DEBUG - m_pMesh->ValidateData( m_VertexBuilder.VertexCount(), m_IndexBuilder.IndexCount(), *this ); -#endif - - // Unlocks mesh - m_pMesh->ModifyEnd( *this ); - m_pMesh = 0; - - m_IndexBuilder.AttachEndModify(); - m_VertexBuilder.AttachEndModify(); - -#ifdef _DEBUG - // Null out our pointers... - memset( (MeshDesc_t*)this, 0, sizeof(MeshDesc_t) ); -#endif -} - - -//----------------------------------------------------------------------------- -// Resets the mesh builder so it points to the start of everything again -//----------------------------------------------------------------------------- -inline void CMeshBuilder::Reset() -{ - m_IndexBuilder.Reset(); - m_VertexBuilder.Reset(); -} - - -//----------------------------------------------------------------------------- -// Selects the current Vertex and Index -//----------------------------------------------------------------------------- -FORCEINLINE void CMeshBuilder::SelectVertex( int nIndex ) -{ - m_VertexBuilder.SelectVertex( nIndex ); -} - -inline void CMeshBuilder::SelectVertexFromIndex( int idx ) -{ - // NOTE: This index is expected to be relative - int vertIdx = idx - m_nFirstVertex; - SelectVertex( vertIdx ); -} - -FORCEINLINE void CMeshBuilder::SelectIndex( int idx ) -{ - m_IndexBuilder.SelectIndex( idx ); -} - - -//----------------------------------------------------------------------------- -// Advances the current vertex and index by one -//----------------------------------------------------------------------------- -FORCEINLINE void CMeshBuilder::AdvanceVertex() -{ - m_VertexBuilder.AdvanceVertex(); -} - -FORCEINLINE void CMeshBuilder::AdvanceVertices( int nVertexCount ) -{ - m_VertexBuilder.AdvanceVertices( nVertexCount ); -} - -FORCEINLINE void CMeshBuilder::AdvanceIndex() -{ - m_IndexBuilder.AdvanceIndex(); -} - -FORCEINLINE void CMeshBuilder::AdvanceIndices( int nIndices ) -{ - m_IndexBuilder.AdvanceIndices( nIndices ); -} - -FORCEINLINE int CMeshBuilder::GetCurrentVertex() -{ - return m_VertexBuilder.GetCurrentVertex(); -} - -FORCEINLINE int CMeshBuilder::GetCurrentIndex() -{ - return m_IndexBuilder.GetCurrentIndex(); -} - - -//----------------------------------------------------------------------------- -// A helper method since this seems to be done a whole bunch. -//----------------------------------------------------------------------------- -inline void CMeshBuilder::DrawQuad( IMesh* pMesh, const float* v1, const float* v2, - const float* v3, const float* v4, unsigned char const* pColor, bool wireframe ) -{ - if (!wireframe) - { - Begin( pMesh, MATERIAL_TRIANGLE_STRIP, 2 ); - - Position3fv (v1); - Color4ubv( pColor ); - AdvanceVertex(); - - Position3fv (v2); - Color4ubv( pColor ); - AdvanceVertex(); - - Position3fv (v4); - Color4ubv( pColor ); - AdvanceVertex(); - - Position3fv (v3); - Color4ubv( pColor ); - AdvanceVertex(); - } - else - { - Begin( pMesh, MATERIAL_LINE_LOOP, 4 ); - Position3fv (v1); - Color4ubv( pColor ); - AdvanceVertex(); - - Position3fv (v2); - Color4ubv( pColor ); - AdvanceVertex(); - - Position3fv (v3); - Color4ubv( pColor ); - AdvanceVertex(); - - Position3fv (v4); - Color4ubv( pColor ); - AdvanceVertex(); - } - - End(); - pMesh->Draw(); -} - - -//----------------------------------------------------------------------------- -// returns the number of indices and vertices -//----------------------------------------------------------------------------- -FORCEINLINE int CMeshBuilder::VertexCount() const -{ - return m_VertexBuilder.VertexCount(); -} - -FORCEINLINE int CMeshBuilder::IndexCount() const -{ - return m_IndexBuilder.IndexCount(); -} - - -//----------------------------------------------------------------------------- -// Returns the base vertex memory pointer -//----------------------------------------------------------------------------- -FORCEINLINE void* CMeshBuilder::BaseVertexData() -{ - return m_VertexBuilder.BaseVertexData(); -} - -//----------------------------------------------------------------------------- -// Data retrieval... -//----------------------------------------------------------------------------- -FORCEINLINE const float* CMeshBuilder::Position() const -{ - return m_VertexBuilder.Position(); -} - -FORCEINLINE const float* CMeshBuilder::Normal() const -{ - return m_VertexBuilder.Normal(); -} - -FORCEINLINE unsigned int CMeshBuilder::Color() const -{ - return m_VertexBuilder.Color(); -} - -FORCEINLINE unsigned char *CMeshBuilder::Specular() const -{ - return m_VertexBuilder.Specular(); -} - -FORCEINLINE const float* CMeshBuilder::TexCoord( int nStage ) const -{ - return m_VertexBuilder.TexCoord( nStage ); -} - -FORCEINLINE const float* CMeshBuilder::TangentS() const -{ - return m_VertexBuilder.TangentS(); -} - -FORCEINLINE const float* CMeshBuilder::TangentT() const -{ - return m_VertexBuilder.TangentT(); -} - -FORCEINLINE float CMeshBuilder::Wrinkle() const -{ - return m_VertexBuilder.Wrinkle(); -} - -FORCEINLINE const float* CMeshBuilder::BoneWeight() const -{ - return m_VertexBuilder.BoneWeight(); -} - -FORCEINLINE int CMeshBuilder::NumBoneWeights() const -{ - return m_VertexBuilder.NumBoneWeights(); -} - -FORCEINLINE unsigned short const* CMeshBuilder::Index() const -{ - return m_IndexBuilder.Index(); -} - - -//----------------------------------------------------------------------------- -// Index -//----------------------------------------------------------------------------- -FORCEINLINE void CMeshBuilder::Index( unsigned short idx ) -{ - m_IndexBuilder.Index( idx ); -} - - -//----------------------------------------------------------------------------- -// Fast Index! No need to call advance index -//----------------------------------------------------------------------------- -FORCEINLINE void CMeshBuilder::FastIndex( unsigned short idx ) -{ - m_IndexBuilder.FastIndex( idx ); -} - -// NOTE: Use this one to get write combining! Much faster than the other version of FastIndex -// Fast Index! No need to call advance index, and no random access allowed -FORCEINLINE void CMeshBuilder::FastIndex2( unsigned short nIndex1, unsigned short nIndex2 ) -{ - m_IndexBuilder.FastIndex2( nIndex1, nIndex2 ); -} - -//----------------------------------------------------------------------------- -// For use with the FastVertex methods, advances the current vertex by N -//----------------------------------------------------------------------------- -FORCEINLINE void CMeshBuilder::FastAdvanceNVertices( int nVertexCount ) -{ - m_VertexBuilder.FastAdvanceNVertices( nVertexCount ); -} - - -//----------------------------------------------------------------------------- -// Fast Vertex! No need to call advance vertex, and no random access allowed -//----------------------------------------------------------------------------- -FORCEINLINE void CMeshBuilder::FastVertex( const ModelVertexDX7_t &vertex ) -{ - m_VertexBuilder.FastVertex( vertex ); -} - -FORCEINLINE void CMeshBuilder::FastVertexSSE( const ModelVertexDX7_t &vertex ) -{ - m_VertexBuilder.FastVertexSSE( vertex ); -} - -FORCEINLINE void CMeshBuilder::Fast4VerticesSSE( - const ModelVertexDX7_t *vtx_a, const ModelVertexDX7_t *vtx_b, - const ModelVertexDX7_t *vtx_c, const ModelVertexDX7_t *vtx_d ) -{ - m_VertexBuilder.Fast4VerticesSSE( vtx_a, vtx_b, vtx_c, vtx_d ); -} - -FORCEINLINE void CMeshBuilder::FastVertex( const ModelVertexDX8_t &vertex ) -{ - m_VertexBuilder.FastVertex( vertex ); -} - -FORCEINLINE void CMeshBuilder::FastVertexSSE( const ModelVertexDX8_t &vertex ) -{ - m_VertexBuilder.FastVertexSSE( vertex ); -} - -//----------------------------------------------------------------------------- -// Copies a vertex into the x360 format -//----------------------------------------------------------------------------- -#if defined( _X360 ) -inline void CMeshBuilder::VertexDX8ToX360( const ModelVertexDX8_t &vertex ) -{ - m_VertexBuilder.VertexDX8ToX360( vertex ); -} -#endif - -//----------------------------------------------------------------------------- -// Vertex field setting methods -//----------------------------------------------------------------------------- -FORCEINLINE void CMeshBuilder::Position3f( float x, float y, float z ) -{ - m_VertexBuilder.Position3f( x, y, z ); -} - -FORCEINLINE void CMeshBuilder::Position3fv( const float *v ) -{ - m_VertexBuilder.Position3fv( v ); -} - -FORCEINLINE void CMeshBuilder::Normal3f( float nx, float ny, float nz ) -{ - m_VertexBuilder.Normal3f( nx, ny, nz ); -} - -FORCEINLINE void CMeshBuilder::Normal3fv( const float *n ) -{ - m_VertexBuilder.Normal3fv( n ); -} - -FORCEINLINE void CMeshBuilder::NormalDelta3f( float nx, float ny, float nz ) -{ - m_VertexBuilder.NormalDelta3f( nx, ny, nz ); -} - -FORCEINLINE void CMeshBuilder::NormalDelta3fv( const float *n ) -{ - m_VertexBuilder.NormalDelta3fv( n ); -} - -FORCEINLINE void CMeshBuilder::Color3f( float r, float g, float b ) -{ - m_VertexBuilder.Color3f( r, g, b ); -} - -FORCEINLINE void CMeshBuilder::Color3fv( const float *rgb ) -{ - m_VertexBuilder.Color3fv( rgb ); -} - -FORCEINLINE void CMeshBuilder::Color4f( float r, float g, float b, float a ) -{ - m_VertexBuilder.Color4f( r, g ,b, a ); -} - -FORCEINLINE void CMeshBuilder::Color4fv( const float *rgba ) -{ - m_VertexBuilder.Color4fv( rgba ); -} - -FORCEINLINE void CMeshBuilder::Color3ub( unsigned char r, unsigned char g, unsigned char b ) -{ - m_VertexBuilder.Color3ub( r, g, b ); -} - -FORCEINLINE void CMeshBuilder::Color3ubv( unsigned char const* rgb ) -{ - m_VertexBuilder.Color3ubv( rgb ); -} - -FORCEINLINE void CMeshBuilder::Color4ub( unsigned char r, unsigned char g, unsigned char b, unsigned char a ) -{ - m_VertexBuilder.Color4ub( r, g, b, a ); -} - -FORCEINLINE void CMeshBuilder::Color4ubv( unsigned char const* rgba ) -{ - m_VertexBuilder.Color4ubv( rgba ); -} - -FORCEINLINE void CMeshBuilder::Specular3f( float r, float g, float b ) -{ - m_VertexBuilder.Specular3f( r, g, b ); -} - -FORCEINLINE void CMeshBuilder::Specular3fv( const float *rgb ) -{ - m_VertexBuilder.Specular3fv( rgb ); -} - -FORCEINLINE void CMeshBuilder::Specular4f( float r, float g, float b, float a ) -{ - m_VertexBuilder.Specular4f( r, g, b, a ); -} - -FORCEINLINE void CMeshBuilder::Specular4fv( const float *rgba ) -{ - m_VertexBuilder.Specular4fv( rgba ); -} - -FORCEINLINE void CMeshBuilder::Specular3ub( unsigned char r, unsigned char g, unsigned char b ) -{ - m_VertexBuilder.Specular3ub( r, g, b ); -} - -FORCEINLINE void CMeshBuilder::Specular3ubv( unsigned char const *c ) -{ - m_VertexBuilder.Specular3ubv( c ); -} - -FORCEINLINE void CMeshBuilder::Specular4ub( unsigned char r, unsigned char g, unsigned char b, unsigned char a ) -{ - m_VertexBuilder.Specular4ub( r, g, b, a ); -} - -FORCEINLINE void CMeshBuilder::Specular4ubv( unsigned char const *c ) -{ - m_VertexBuilder.Specular4ubv( c ); -} - -FORCEINLINE void CMeshBuilder::TexCoord1f( int nStage, float s ) -{ - m_VertexBuilder.TexCoord1f( nStage, s ); -} - -FORCEINLINE void CMeshBuilder::TexCoord2f( int nStage, float s, float t ) -{ - m_VertexBuilder.TexCoord2f( nStage, s, t ); -} - -FORCEINLINE void CMeshBuilder::TexCoord2fv( int nStage, const float *st ) -{ - m_VertexBuilder.TexCoord2fv( nStage, st ); -} - -FORCEINLINE void CMeshBuilder::TexCoord3f( int nStage, float s, float t, float u ) -{ - m_VertexBuilder.TexCoord3f( nStage, s, t, u ); -} - -FORCEINLINE void CMeshBuilder::TexCoord3fv( int nStage, const float *stu ) -{ - m_VertexBuilder.TexCoord3fv( nStage, stu ); -} - -FORCEINLINE void CMeshBuilder::TexCoord4f( int nStage, float s, float t, float u, float v ) -{ - m_VertexBuilder.TexCoord4f( nStage, s, t, u, v ); -} - -FORCEINLINE void CMeshBuilder::TexCoord4fv( int nStage, const float *stuv ) -{ - m_VertexBuilder.TexCoord4fv( nStage, stuv ); -} - -FORCEINLINE void CMeshBuilder::TexCoordSubRect2f( int nStage, float s, float t, float offsetS, float offsetT, float scaleS, float scaleT ) -{ - m_VertexBuilder.TexCoordSubRect2f( nStage, s, t, offsetS, offsetT, scaleS, scaleT ); -} - -FORCEINLINE void CMeshBuilder::TexCoordSubRect2fv( int nStage, const float *st, const float *offset, const float *scale ) -{ - m_VertexBuilder.TexCoordSubRect2fv( nStage, st, offset, scale ); -} - -FORCEINLINE void CMeshBuilder::TangentS3f( float sx, float sy, float sz ) -{ - m_VertexBuilder.TangentS3f( sx, sy, sz ); -} - -FORCEINLINE void CMeshBuilder::TangentS3fv( const float* s ) -{ - m_VertexBuilder.TangentS3fv( s ); -} - -FORCEINLINE void CMeshBuilder::TangentT3f( float tx, float ty, float tz ) -{ - m_VertexBuilder.TangentT3f( tx, ty, tz ); -} - -FORCEINLINE void CMeshBuilder::TangentT3fv( const float* t ) -{ - m_VertexBuilder.TangentT3fv( t ); -} - -FORCEINLINE void CMeshBuilder::Wrinkle1f( float flWrinkle ) -{ - m_VertexBuilder.Wrinkle1f( flWrinkle ); -} - -FORCEINLINE void CMeshBuilder::BoneWeight( int nIndex, float flWeight ) -{ - m_VertexBuilder.BoneWeight( nIndex, flWeight ); -} - -template FORCEINLINE void CMeshBuilder::CompressedBoneWeight3fv( const float * pWeights ) -{ - m_VertexBuilder.CompressedBoneWeight3fv( pWeights ); -} - -FORCEINLINE void CMeshBuilder::BoneMatrix( int nIndex, int nMatrixIdx ) -{ - m_VertexBuilder.BoneMatrix( nIndex, nMatrixIdx ); -} - -FORCEINLINE void CMeshBuilder::UserData( const float* pData ) -{ - m_VertexBuilder.UserData( pData ); -} - -template FORCEINLINE void CMeshBuilder::CompressedUserData( const float* pData ) -{ - m_VertexBuilder.CompressedUserData( pData ); -} - -//----------------------------------------------------------------------------- -// Templatized vertex field setting methods which support compression -//----------------------------------------------------------------------------- - -template FORCEINLINE void CMeshBuilder::CompressedNormal3f( float nx, float ny, float nz ) -{ - m_VertexBuilder.CompressedNormal3f( nx, ny, nz ); -} - -template FORCEINLINE void CMeshBuilder::CompressedNormal3fv( const float *n ) -{ - m_VertexBuilder.CompressedNormal3fv( n ); -} - -#endif // IMESH_H diff --git a/public/materialsystem/imorph.h b/public/materialsystem/imorph.h deleted file mode 100644 index 73d9814ce..000000000 --- a/public/materialsystem/imorph.h +++ /dev/null @@ -1,251 +0,0 @@ -//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. =========== -// -// The copyright to the contents herein is the property of Valve, L.L.C. -// The contents may be used and/or copied only with the written permission of -// Valve, L.L.C., or in accordance with the terms and conditions stipulated in -// the agreement/contract under which the contents have been supplied. -// -// $Header: $ -// $NoKeywords: $ -// -// Interface used to construct morph buffers -//============================================================================= - -#ifndef IMORPH_H -#define IMORPH_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "mathlib/vector.h" -#include -#include "tier0/dbg.h" -#include "materialsystem/imaterial.h" - - -//----------------------------------------------------------------------------- -// Single morph data -//----------------------------------------------------------------------------- -struct MorphVertexInfo_t -{ - int m_nVertexId; // What vertex is this going to affect? - int m_nMorphTargetId; // What morph did it come from? - Vector m_PositionDelta; // Positional morph delta - Vector m_NormalDelta; // Normal morph delta - float m_flWrinkleDelta; // Wrinkle morph delta - float m_flSpeed; - float m_flSide; -}; - - -//----------------------------------------------------------------------------- -// Morph weight data -//----------------------------------------------------------------------------- -enum MorphWeightType_t -{ - MORPH_WEIGHT = 0, - MORPH_WEIGHT_LAGGED, - MORPH_WEIGHT_STEREO, - MORPH_WEIGHT_STEREO_LAGGED, - - MORPH_WEIGHT_COUNT, -}; - -struct MorphWeight_t -{ - float m_pWeight[MORPH_WEIGHT_COUNT]; -}; - - -//----------------------------------------------------------------------------- -// Interface to the morph -//----------------------------------------------------------------------------- -abstract_class IMorph -{ -public: - // Locks the morph, destroys any existing contents - virtual void Lock( float flFloatToFixedScale = 1.0f ) = 0; - - // Adds a morph - virtual void AddMorph( const MorphVertexInfo_t &info ) = 0; - - // Unlocks the morph - virtual void Unlock( ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Morph builders -//----------------------------------------------------------------------------- -class CMorphBuilder -{ -public: - CMorphBuilder(); - ~CMorphBuilder(); - - // Start building the morph - void Begin( IMorph *pMorph, float flFloatToFixedScale = 1.0f ); - - // End building the morph - void End(); - - void PositionDelta3fv( const float *pDelta ); - void PositionDelta3f( float dx, float dy, float dz ); - void PositionDelta3( const Vector &vec ); - - void NormalDelta3fv( const float *pDelta ); - void NormalDelta3f( float dx, float dy, float dz ); - void NormalDelta3( const Vector &vec ); - - void WrinkleDelta1f( float flWrinkle ); - - // Both are 0-1 values indicating which morph target to use (for stereo morph targets) - // and how much to blend between using lagged weights vs actual weights - // Speed: 0 - use lagged, 1 - use actual - void Speed1f( float flSpeed ); - void Side1f( float flSide ); - - void AdvanceMorph( int nSourceVertex, int nMorphTargetId ); - -private: - MorphVertexInfo_t m_Info; - IMorph *m_pMorph; -}; - - -//----------------------------------------------------------------------------- -// Constructor, destructor -//----------------------------------------------------------------------------- -inline CMorphBuilder::CMorphBuilder() -{ - m_pMorph = NULL; -} - -inline CMorphBuilder::~CMorphBuilder() -{ - // You forgot to call End()! - Assert( !m_pMorph ); -} - - -//----------------------------------------------------------------------------- -// Start building the morph -//----------------------------------------------------------------------------- -inline void CMorphBuilder::Begin( IMorph *pMorph, float flFloatToFixedScale ) -{ - Assert( pMorph && !m_pMorph ); - m_pMorph = pMorph; - m_pMorph->Lock( flFloatToFixedScale ); - -#ifdef _DEBUG - m_Info.m_PositionDelta.Init( VEC_T_NAN, VEC_T_NAN, VEC_T_NAN ); - m_Info.m_NormalDelta.Init( VEC_T_NAN, VEC_T_NAN, VEC_T_NAN ); - m_Info.m_flWrinkleDelta = VEC_T_NAN; - m_Info.m_flSpeed = VEC_T_NAN; - m_Info.m_flSide = VEC_T_NAN; -#endif -} - -// End building the morph -inline void CMorphBuilder::End() -{ - Assert( m_pMorph ); - m_pMorph->Unlock(); - m_pMorph = NULL; -} - - -//----------------------------------------------------------------------------- -// Set position delta -//----------------------------------------------------------------------------- -inline void CMorphBuilder::PositionDelta3fv( const float *pDelta ) -{ - Assert( m_pMorph ); - m_Info.m_PositionDelta.Init( pDelta[0], pDelta[1], pDelta[2] ); -} - -inline void CMorphBuilder::PositionDelta3f( float dx, float dy, float dz ) -{ - Assert( m_pMorph ); - m_Info.m_PositionDelta.Init( dx, dy, dz ); -} - -inline void CMorphBuilder::PositionDelta3( const Vector &vec ) -{ - Assert( m_pMorph ); - m_Info.m_PositionDelta = vec; -} - - -//----------------------------------------------------------------------------- -// Set normal delta -//----------------------------------------------------------------------------- -inline void CMorphBuilder::NormalDelta3fv( const float *pDelta ) -{ - Assert( m_pMorph ); - m_Info.m_NormalDelta.Init( pDelta[0], pDelta[1], pDelta[2] ); -} - -inline void CMorphBuilder::NormalDelta3f( float dx, float dy, float dz ) -{ - Assert( m_pMorph ); - m_Info.m_NormalDelta.Init( dx, dy, dz ); -} - -inline void CMorphBuilder::NormalDelta3( const Vector &vec ) -{ - Assert( m_pMorph ); - m_Info.m_NormalDelta = vec; -} - - -//----------------------------------------------------------------------------- -// Set wrinkle delta -//----------------------------------------------------------------------------- -inline void CMorphBuilder::WrinkleDelta1f( float flWrinkle ) -{ - Assert( m_pMorph ); - m_Info.m_flWrinkleDelta = flWrinkle; -} - - -//----------------------------------------------------------------------------- -// Set speed,side data -//----------------------------------------------------------------------------- -inline void CMorphBuilder::Speed1f( float flSpeed ) -{ - Assert( m_pMorph ); - m_Info.m_flSpeed = flSpeed; -} - -inline void CMorphBuilder::Side1f( float flSide ) -{ - Assert( m_pMorph ); - m_Info.m_flSide = flSide; -} - - -//----------------------------------------------------------------------------- -// Advance morph -//----------------------------------------------------------------------------- -inline void CMorphBuilder::AdvanceMorph( int nSourceVertex, int nMorphTargetId ) -{ - Assert( m_pMorph ); - - m_Info.m_nVertexId = nSourceVertex; - m_Info.m_nMorphTargetId = nMorphTargetId; - - m_pMorph->AddMorph( m_Info ); - -#ifdef _DEBUG - m_Info.m_PositionDelta.Init( VEC_T_NAN, VEC_T_NAN, VEC_T_NAN ); - m_Info.m_NormalDelta.Init( VEC_T_NAN, VEC_T_NAN, VEC_T_NAN ); - m_Info.m_flWrinkleDelta = VEC_T_NAN; - m_Info.m_flSpeed = VEC_T_NAN; - m_Info.m_flSide = VEC_T_NAN; -#endif -} - - -#endif // IMORPH_H diff --git a/public/materialsystem/ishaderapi.h b/public/materialsystem/ishaderapi.h deleted file mode 100644 index 30777cc20..000000000 --- a/public/materialsystem/ishaderapi.h +++ /dev/null @@ -1,43 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: NOTE: This file is for backward compat! -// We'll get rid of it soon. Most of the contents of this file were moved -// into shaderpi/ishadershadow.h, shaderapi/ishaderdynamic.h, or -// shaderapi/shareddefs.h -// -// $NoKeywords: $ -// -//===========================================================================// - -#ifndef ISHADERAPI_MS_H -#define ISHADERAPI_MS_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include - - -//----------------------------------------------------------------------------- -// forward declarations -//----------------------------------------------------------------------------- -class IMaterialVar; - - -//----------------------------------------------------------------------------- -// Methods that can be called from the SHADER_INIT blocks of shaders -//----------------------------------------------------------------------------- -abstract_class IShaderInit -{ -public: - // Loads up a texture - virtual void LoadTexture( IMaterialVar *pTextureVar, const char *pTextureGroupName ) = 0; - virtual void LoadBumpMap( IMaterialVar *pTextureVar, const char *pTextureGroupName ) = 0; - virtual void LoadCubeMap( IMaterialVar **ppParams, IMaterialVar *pTextureVar ) = 0; -}; - - -#endif // ISHADERAPI_MS_H diff --git a/public/materialsystem/itexture.h b/public/materialsystem/itexture.h deleted file mode 100644 index 4297c03c8..000000000 --- a/public/materialsystem/itexture.h +++ /dev/null @@ -1,129 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// - -#ifndef ITEXTURE_H -#define ITEXTURE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/platform.h" -#include "bitmap/imageformat.h" // ImageFormat defn. - -class IVTFTexture; -class ITexture; -struct Rect_t; - -//----------------------------------------------------------------------------- -// This will get called on procedural textures to re-fill the textures -// with the appropriate bit pattern. Calling Download() will also -// cause this interface to be called. It will also be called upon -// mode switch, or on other occasions where the bits are discarded. -//----------------------------------------------------------------------------- -abstract_class ITextureRegenerator -{ -public: - // This will be called when the texture bits need to be regenerated. - // Use the VTFTexture interface, which has been set up with the - // appropriate texture size + format - // The rect specifies which part of the texture needs to be updated - // You can choose to update all of the bits if you prefer - virtual void RegenerateTextureBits( ITexture *pTexture, IVTFTexture *pVTFTexture, Rect_t *pRect ) = 0; - - // This will be called when the regenerator needs to be deleted - // which will happen when the texture is destroyed - virtual void Release() = 0; -}; - -abstract_class ITexture -{ -public: - // Various texture polling methods - virtual const char *GetName( void ) const = 0; - virtual int GetMappingWidth() const = 0; - virtual int GetMappingHeight() const = 0; - virtual int GetActualWidth() const = 0; - virtual int GetActualHeight() const = 0; - virtual int GetNumAnimationFrames() const = 0; - virtual bool IsTranslucent() const = 0; - virtual bool IsMipmapped() const = 0; - - virtual void GetLowResColorSample( float s, float t, float *color ) const = 0; - - // Gets texture resource data of the specified type. - // Params: - // eDataType type of resource to retrieve. - // pnumBytes on return is the number of bytes available in the read-only data buffer or is undefined - // Returns: - // pointer to the resource data, or NULL - virtual void *GetResourceData( uint32 eDataType, size_t *pNumBytes ) const = 0; - - // Methods associated with reference count - virtual void IncrementReferenceCount( void ) = 0; - virtual void DecrementReferenceCount( void ) = 0; - - inline void AddRef() { IncrementReferenceCount(); } - inline void Release() { DecrementReferenceCount(); } - - // Used to modify the texture bits (procedural textures only) - virtual void SetTextureRegenerator( ITextureRegenerator *pTextureRegen ) = 0; - - // Reconstruct the texture bits in HW memory - - // If rect is not specified, reconstruct all bits, otherwise just - // reconstruct a subrect. - virtual void Download( Rect_t *pRect = 0 ) = 0; - - // Uses for stats. . .get the approximate size of the texture in it's current format. - virtual int GetApproximateVidMemBytes( void ) const = 0; - - // Returns true if the texture data couldn't be loaded. - virtual bool IsError() const = 0; - - // NOTE: Stuff after this is added after shipping HL2. - - // For volume textures - virtual bool IsVolumeTexture() const = 0; - virtual int GetMappingDepth() const = 0; - virtual int GetActualDepth() const = 0; - - virtual ImageFormat GetImageFormat() const = 0; - virtual NormalDecodeMode_t GetNormalDecodeMode() const = 0; - - // Various information about the texture - virtual bool IsRenderTarget() const = 0; - virtual bool IsCubeMap() const = 0; - virtual bool IsNormalMap() const = 0; - virtual bool IsProcedural() const = 0; - - virtual void DeleteIfUnreferenced() = 0; - -#if defined( _X360 ) - virtual bool ClearTexture( int r, int g, int b, int a ) = 0; - virtual bool CreateRenderTargetSurface( int width, int height, ImageFormat format, bool bSameAsTexture ) = 0; -#endif - - // swap everything except the name with another texture - virtual void SwapContents( ITexture *pOther ) = 0; - - // Retrieve the vtf flags mask - virtual unsigned int GetFlags( void ) const = 0; - - // Force LOD override (automatically downloads the texture) - virtual void ForceLODOverride( int iNumLodsOverrideUpOrDown ) = 0; -}; - - -inline bool IsErrorTexture( ITexture *pTex ) -{ - return !pTex || pTex->IsError(); -} - - -#endif // ITEXTURE_H diff --git a/public/materialsystem/ivballoctracker.h b/public/materialsystem/ivballoctracker.h deleted file mode 100644 index bc9570b62..000000000 --- a/public/materialsystem/ivballoctracker.h +++ /dev/null @@ -1,35 +0,0 @@ -//===== Copyright 1996-2007, Valve Corporation, All rights reserved. ======// -// -// Purpose: tracks VB allocations (and compressed/uncompressed vertex memory usage) -// -//===========================================================================// - -#ifndef IVBALLOCTRACKER_H -#define IVBALLOCTRACKER_H - -#include "materialsystem/imaterialsystem.h" - -// By default, only enable this alloc tracking for a debug shaderapidx*.dll -// (it uses about 0.25MB to track ~7000 allocations) -#if defined(_DEBUG) -#define ENABLE_VB_ALLOC_TRACKER 1 -#else -#define ENABLE_VB_ALLOC_TRACKER 0 -#endif - -// This interface is actually exported by the shader API DLL. -#define VB_ALLOC_TRACKER_INTERFACE_VERSION "VBAllocTracker001" - -// Interface to the VB mem alloc tracker -abstract_class IVBAllocTracker -{ -public: - // This should be called wherever VertexBuffers are allocated - virtual void CountVB( void * buffer, bool isDynamic, int bufferSize, int vertexSize, VertexFormat_t fmt ) = 0; - // This should be called wherever VertexBuffers are freed - virtual void UnCountVB( void * buffer ) = 0; - // Track mesh allocations (set this before an allocation, clear it after) - virtual void TrackMeshAllocations( const char * allocatorName ) = 0; -}; - -#endif IVBALLOCTRACKER_H diff --git a/public/materialsystem/materialsystem_config.h b/public/materialsystem/materialsystem_config.h deleted file mode 100644 index bae9d1aa1..000000000 --- a/public/materialsystem/materialsystem_config.h +++ /dev/null @@ -1,215 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef MATERIALSYSTEM_CONFIG_H -#define MATERIALSYSTEM_CONFIG_H -#ifdef _WIN32 -#pragma once -#endif - -#include "materialsystem/imaterialsystem.h" - -#define MATERIALSYSTEM_CONFIG_VERSION "VMaterialSystemConfig002" - -enum MaterialSystem_Config_Flags_t -{ - MATSYS_VIDCFG_FLAGS_WINDOWED = ( 1 << 0 ), - MATSYS_VIDCFG_FLAGS_RESIZING = ( 1 << 1 ), - MATSYS_VIDCFG_FLAGS_NO_WAIT_FOR_VSYNC = ( 1 << 3 ), - MATSYS_VIDCFG_FLAGS_STENCIL = ( 1 << 4 ), - MATSYS_VIDCFG_FLAGS_FORCE_TRILINEAR = ( 1 << 5 ), - MATSYS_VIDCFG_FLAGS_FORCE_HWSYNC = ( 1 << 6 ), - MATSYS_VIDCFG_FLAGS_DISABLE_SPECULAR = ( 1 << 7 ), - MATSYS_VIDCFG_FLAGS_DISABLE_BUMPMAP = ( 1 << 8 ), - MATSYS_VIDCFG_FLAGS_ENABLE_PARALLAX_MAPPING = ( 1 << 9 ), - MATSYS_VIDCFG_FLAGS_USE_Z_PREFILL = ( 1 << 10 ), - MATSYS_VIDCFG_FLAGS_REDUCE_FILLRATE = ( 1 << 11 ), - MATSYS_VIDCFG_FLAGS_ENABLE_HDR = ( 1 << 12 ), - MATSYS_VIDCFG_FLAGS_LIMIT_WINDOWED_SIZE = ( 1 << 13 ), - MATSYS_VIDCFG_FLAGS_SCALE_TO_OUTPUT_RESOLUTION = ( 1 << 14 ), - MATSYS_VIDCFG_FLAGS_USING_MULTIPLE_WINDOWS = ( 1 << 15 ), -}; - -struct MaterialSystemHardwareIdentifier_t -{ - char *m_pCardName; - unsigned int m_nVendorID; - unsigned int m_nDeviceID; -}; - -struct MaterialSystem_Config_t -{ - bool Windowed() const { return ( m_Flags & MATSYS_VIDCFG_FLAGS_WINDOWED ) != 0; } - bool Resizing() const { return ( m_Flags & MATSYS_VIDCFG_FLAGS_RESIZING ) != 0; } - bool WaitForVSync() const { return ( m_Flags & MATSYS_VIDCFG_FLAGS_NO_WAIT_FOR_VSYNC ) == 0; } - bool Stencil() const { return (m_Flags & MATSYS_VIDCFG_FLAGS_STENCIL ) != 0; } - bool ForceTrilinear() const { return ( m_Flags & MATSYS_VIDCFG_FLAGS_FORCE_TRILINEAR ) != 0; } - bool ForceHWSync() const { return ( m_Flags & MATSYS_VIDCFG_FLAGS_FORCE_HWSYNC ) != 0; } - bool UseSpecular() const { return ( m_Flags & MATSYS_VIDCFG_FLAGS_DISABLE_SPECULAR ) == 0; } - bool UseBumpmapping() const { return ( m_Flags & MATSYS_VIDCFG_FLAGS_DISABLE_BUMPMAP ) == 0; } - bool UseParallaxMapping() const { return ( m_Flags & MATSYS_VIDCFG_FLAGS_ENABLE_PARALLAX_MAPPING ) != 0; } - bool UseZPrefill() const { return ( m_Flags & MATSYS_VIDCFG_FLAGS_USE_Z_PREFILL ) != 0; } - bool ReduceFillrate() const { return ( m_Flags & MATSYS_VIDCFG_FLAGS_REDUCE_FILLRATE ) != 0; } - bool HDREnabled() const { return ( m_Flags & MATSYS_VIDCFG_FLAGS_ENABLE_HDR ) != 0; } - bool LimitWindowedSize() const { return ( m_Flags & MATSYS_VIDCFG_FLAGS_LIMIT_WINDOWED_SIZE ) != 0; } - bool ScaleToOutputResolution() const { return ( m_Flags & MATSYS_VIDCFG_FLAGS_SCALE_TO_OUTPUT_RESOLUTION ) != 0; } - bool UsingMultipleWindows() const { return ( m_Flags & MATSYS_VIDCFG_FLAGS_USING_MULTIPLE_WINDOWS ) != 0; } - bool ShadowDepthTexture() const { return m_bShadowDepthTexture; } - bool MotionBlur() const { return m_bMotionBlur; } - bool SupportFlashlight() const { return m_bSupportFlashlight; } - - void SetFlag( unsigned int flag, bool val ) - { - if( val ) - { - m_Flags |= flag; - } - else - { - m_Flags &= ~flag; - } - } - - // control panel stuff - MaterialVideoMode_t m_VideoMode; - float m_fMonitorGamma; - float m_fGammaTVRangeMin; - float m_fGammaTVRangeMax; - float m_fGammaTVExponent; - bool m_bGammaTVEnabled; - - int m_nAASamples; - int m_nForceAnisotropicLevel; - int skipMipLevels; - int dxSupportLevel; - unsigned int m_Flags; - bool bEditMode; // true if in Hammer. - unsigned char proxiesTestMode; // 0 = normal, 1 = no proxies, 2 = alpha test all, 3 = color mod all - bool bCompressedTextures; - bool bFilterLightmaps; - bool bFilterTextures; - bool bReverseDepth; - bool bBufferPrimitives; - bool bDrawFlat; - bool bMeasureFillRate; - bool bVisualizeFillRate; - bool bNoTransparency; - bool bSoftwareLighting; - bool bAllowCheats; - char nShowMipLevels; - bool bShowLowResImage; - bool bShowNormalMap; - bool bMipMapTextures; - unsigned char nFullbright; - bool m_bFastNoBump; - bool m_bSuppressRendering; - - // debug modes - bool bShowSpecular; // This is the fast version that doesn't require reloading materials - bool bShowDiffuse; // This is the fast version that doesn't require reloading materials - - // misc - int m_nReserved; // Currently unused - - // No depth bias - float m_SlopeScaleDepthBias_Normal; - float m_DepthBias_Normal; - - // Depth bias for rendering decals closer to the camera - float m_SlopeScaleDepthBias_Decal; - float m_DepthBias_Decal; - - // Depth bias for biasing shadow depth map rendering away from the camera - float m_SlopeScaleDepthBias_ShadowMap; - float m_DepthBias_ShadowMap; - - uint m_WindowedSizeLimitWidth; - uint m_WindowedSizeLimitHeight; - int m_nAAQuality; - bool m_bShadowDepthTexture; - bool m_bMotionBlur; - bool m_bSupportFlashlight; - - MaterialSystem_Config_t() - { - memset( this, 0, sizeof( *this ) ); - - // video config defaults - SetFlag( MATSYS_VIDCFG_FLAGS_WINDOWED, false ); - SetFlag( MATSYS_VIDCFG_FLAGS_RESIZING, false ); - SetFlag( MATSYS_VIDCFG_FLAGS_NO_WAIT_FOR_VSYNC, true ); - SetFlag( MATSYS_VIDCFG_FLAGS_STENCIL, false ); - SetFlag( MATSYS_VIDCFG_FLAGS_FORCE_TRILINEAR, true ); - SetFlag( MATSYS_VIDCFG_FLAGS_FORCE_HWSYNC, true ); - SetFlag( MATSYS_VIDCFG_FLAGS_DISABLE_SPECULAR, false ); - SetFlag( MATSYS_VIDCFG_FLAGS_DISABLE_BUMPMAP, false ); - SetFlag( MATSYS_VIDCFG_FLAGS_ENABLE_PARALLAX_MAPPING, true ); - SetFlag( MATSYS_VIDCFG_FLAGS_USE_Z_PREFILL, false ); - SetFlag( MATSYS_VIDCFG_FLAGS_REDUCE_FILLRATE, false ); - SetFlag( MATSYS_VIDCFG_FLAGS_LIMIT_WINDOWED_SIZE, false ); - SetFlag( MATSYS_VIDCFG_FLAGS_SCALE_TO_OUTPUT_RESOLUTION, false ); - SetFlag( MATSYS_VIDCFG_FLAGS_USING_MULTIPLE_WINDOWS, false ); - - m_VideoMode.m_Width = 640; - m_VideoMode.m_Height = 480; - m_VideoMode.m_RefreshRate = 60; - dxSupportLevel = 0; - bCompressedTextures = true; - bFilterTextures = true; - bFilterLightmaps = true; - bMipMapTextures = true; - bBufferPrimitives = true; - - m_fMonitorGamma = 2.2f; - m_fGammaTVRangeMin = 16.0f; - m_fGammaTVRangeMax = 255.0f; - m_fGammaTVExponent = 2.5; - m_bGammaTVEnabled = IsX360(); - - m_nAASamples = 1; - m_bShadowDepthTexture = false; - m_bMotionBlur = false; - m_bSupportFlashlight = true; - - // misc defaults - bAllowCheats = false; - bCompressedTextures = true; - bEditMode = false; - - // debug modes - bShowSpecular = true; - bShowDiffuse = true; - nFullbright = 0; - bShowNormalMap = false; - bFilterLightmaps = true; - bFilterTextures = true; - bMipMapTextures = true; - nShowMipLevels = 0; - bShowLowResImage = false; - bReverseDepth = false; - bBufferPrimitives = true; - bDrawFlat = false; - bMeasureFillRate = false; - bVisualizeFillRate = false; - bSoftwareLighting = false; - bNoTransparency = false; - proxiesTestMode = 0; - m_bFastNoBump = false; - m_bSuppressRendering = false; - m_SlopeScaleDepthBias_Decal = -0.5f; - m_SlopeScaleDepthBias_Normal = 0.0f; - m_SlopeScaleDepthBias_ShadowMap = 0.5f; - m_DepthBias_Decal = -262144; - m_DepthBias_Normal = 0.0f; - m_DepthBias_ShadowMap = 262144; - m_WindowedSizeLimitWidth = 1280; - m_WindowedSizeLimitHeight = 1024; - } -}; - - -#endif // MATERIALSYSTEM_CONFIG_H diff --git a/public/materialsystem/meshreader.h b/public/materialsystem/meshreader.h deleted file mode 100644 index f5688ee72..000000000 --- a/public/materialsystem/meshreader.h +++ /dev/null @@ -1,268 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=====================================================================================// - -#ifndef MESHREADER_H -#define MESHREADER_H - -#ifdef _WIN32 -#pragma once -#endif - - -//----------------------------------------------------------------------------- -// This is used to read vertex and index data out of already-created meshes. -// xbox uses this a lot so it doesn't have to store sysmem backups of the -// vertex data. -//----------------------------------------------------------------------------- -class CBaseMeshReader : protected MeshDesc_t -{ -// Initialization. -public: - - CBaseMeshReader(); - ~CBaseMeshReader(); - - // Use BeginRead/EndRead to initialize the mesh reader. - void BeginRead( - IMesh* pMesh, - int firstVertex = 0, - int numVertices = 0, - int firstIndex = 0, - int numIndices = 0 ); - - void EndRead(); - - // PC can use this if it stores its own copy of meshes around, in case - // locking static buffers is too costly. - void BeginRead_Direct( const MeshDesc_t &desc, int numVertices, int nIndices ); - - // Resets the mesh builder so it points to the start of everything again - void Reset(); - - -protected: - IMesh *m_pMesh; - int m_MaxVertices; - int m_MaxIndices; -}; - - -// A bunch of accessors for the data that CBaseMeshReader sets up. -class CMeshReader : public CBaseMeshReader -{ -public: -// Access to vertex data. -public: - int NumIndices() const; - unsigned short Index( int index ) const; - - const Vector& Position( int iVertex ) const; - - unsigned int Color( int iVertex ) const; - - const float *TexCoord( int iVertex, int stage ) const; - void TexCoord2f( int iVertex, int stage, float &s, float &t ) const; - const Vector2D& TexCoordVector2D( int iVertex, int stage ) const; - - int NumBoneWeights() const; - float Wrinkle( int iVertex ) const; - - const Vector &Normal( int iVertex ) const; - void Normal( int iVertex, Vector &vNormal ) const; - - const Vector &TangentS( int iVertex ) const; - const Vector &TangentT( int iVertex ) const; - float BoneWeight( int iVertex ) const; - -#ifdef NEW_SKINNING - float* BoneMatrix( int iVertex ) const; -#else - unsigned char* BoneMatrix( int iVertex ) const; -#endif -}; - - -//----------------------------------------------------------------------------- -// CBaseMeshReader implementation. -//----------------------------------------------------------------------------- - -inline CBaseMeshReader::CBaseMeshReader() -{ - m_pMesh = NULL; -} - -inline CBaseMeshReader::~CBaseMeshReader() -{ - Assert( !m_pMesh ); -} - -inline void CBaseMeshReader::BeginRead( - IMesh* pMesh, - int firstVertex, - int numVertices, - int firstIndex, - int numIndices ) -{ - Assert( pMesh && (!m_pMesh) ); - - if ( numVertices < 0 ) - { - numVertices = pMesh->VertexCount(); - } - - if ( numIndices < 0 ) - { - numIndices = pMesh->IndexCount(); - } - - m_pMesh = pMesh; - m_MaxVertices = numVertices; - m_MaxIndices = numIndices; - - // UNDONE: support reading from compressed VBs if needed - VertexCompressionType_t compressionType = CompressionType( pMesh->GetVertexFormat() ); - Assert( compressionType == VERTEX_COMPRESSION_NONE ); - if ( compressionType != VERTEX_COMPRESSION_NONE ) - { - Warning( "Cannot use CBaseMeshReader with compressed vertices! Will get junk data or a crash.\n" ); - } - - // Locks mesh for modifying - pMesh->ModifyBeginEx( true, firstVertex, numVertices, firstIndex, numIndices, *this ); - - // Point to the start of the buffers.. - Reset(); -} - -inline void CBaseMeshReader::EndRead() -{ - Assert( m_pMesh ); - m_pMesh->ModifyEnd( *this ); - m_pMesh = NULL; -} - -inline void CBaseMeshReader::BeginRead_Direct( const MeshDesc_t &desc, int nVertices, int nIndices ) -{ - MeshDesc_t *pThis = this; - *pThis = desc; - m_MaxVertices = nVertices; - m_MaxIndices = nIndices; - - // UNDONE: support reading from compressed verts if necessary - Assert( desc.m_CompressionType == VERTEX_COMPRESSION_NONE ); - if ( desc.m_CompressionType != VERTEX_COMPRESSION_NONE ) - { - Warning( "Cannot use CBaseMeshReader with compressed vertices!\n" ); - } -} - -inline void CBaseMeshReader::Reset() -{ -} - - - - -// -------------------------------------------------------------------------------------- // -// CMeshReader implementation. -// -------------------------------------------------------------------------------------- // - -inline int CMeshReader::NumIndices() const -{ - return m_MaxIndices; -} - -inline unsigned short CMeshReader::Index( int index ) const -{ - Assert( (index >= 0) && (index < m_MaxIndices) ); - return m_pIndices[index * m_nIndexSize]; -} - -inline const Vector& CMeshReader::Position( int iVertex ) const -{ - Assert( iVertex >= 0 && iVertex < m_MaxVertices ); - return *(Vector*)((char*)m_pPosition + iVertex * m_VertexSize_Position); -} - -inline unsigned int CMeshReader::Color( int iVertex ) const -{ - Assert( iVertex >= 0 && iVertex < m_MaxVertices ); - unsigned char *pColor = m_pColor + iVertex * m_VertexSize_Color; - return (pColor[0] << 16) | (pColor[1] << 8) | (pColor[2]) | (pColor[3] << 24); -} - -inline const float *CMeshReader::TexCoord( int iVertex, int iStage ) const -{ - Assert( iVertex >= 0 && iVertex < m_MaxVertices ); - return (float*)( (char*)m_pTexCoord[iStage] + iVertex * m_VertexSize_TexCoord[iStage] ); -} - -inline void CMeshReader::TexCoord2f( int iVertex, int iStage, float &s, float &t ) const -{ - Assert( iVertex >= 0 && iVertex < m_MaxVertices ); - float *p = (float*)( (char*)m_pTexCoord[iStage] + iVertex * m_VertexSize_TexCoord[iStage] ); - s = p[0]; - t = p[1]; -} - -inline const Vector2D& CMeshReader::TexCoordVector2D( int iVertex, int iStage ) const -{ - Assert( iVertex >= 0 && iVertex < m_MaxVertices ); - Vector2D *p = (Vector2D*)( (char*)m_pTexCoord[iStage] + iVertex * m_VertexSize_TexCoord[iStage] ); - return *p; -} - -inline float CMeshReader::Wrinkle( int iVertex ) const -{ - Assert( iVertex >= 0 && iVertex < m_MaxVertices ); - return *(float*)( (char*)m_pWrinkle + iVertex * m_VertexSize_Wrinkle ); -} - -inline int CMeshReader::NumBoneWeights() const -{ - return m_NumBoneWeights; -} - -inline const Vector &CMeshReader::Normal( int iVertex ) const -{ - Assert( iVertex >= 0 && iVertex < m_MaxVertices ); - return *(const Vector *)(const float*)( (char*)m_pNormal + iVertex * m_VertexSize_Normal ); -} - -inline void CMeshReader::Normal( int iVertex, Vector &vNormal ) const -{ - Assert( iVertex >= 0 && iVertex < m_MaxVertices ); - const float *p = (const float*)( (char*)m_pNormal + iVertex * m_VertexSize_Normal ); - vNormal.Init( p[0], p[1], p[2] ); -} - -inline const Vector &CMeshReader::TangentS( int iVertex ) const -{ - Assert( iVertex >= 0 && iVertex < m_MaxVertices ); - return *(const Vector*)( (char*)m_pTangentS + iVertex * m_VertexSize_TangentS ); -} - -inline const Vector &CMeshReader::TangentT( int iVertex ) const -{ - Assert( iVertex >= 0 && iVertex < m_MaxVertices ); - return *(const Vector*)( (char*)m_pTangentT + iVertex * m_VertexSize_TangentT ); -} - -inline float CMeshReader::BoneWeight( int iVertex ) const -{ - Assert( iVertex >= 0 && iVertex < m_MaxVertices ); - float *p = (float*)( (char*)m_pBoneWeight + iVertex * m_VertexSize_BoneWeight ); - return *p; -} - -#endif // MESHREADER_H - - - - - - - diff --git a/public/materialsystem/shader_vcs_version.h b/public/materialsystem/shader_vcs_version.h deleted file mode 100644 index 903e34fb2..000000000 --- a/public/materialsystem/shader_vcs_version.h +++ /dev/null @@ -1,75 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef SHADER_VCS_VERSION_H -#define SHADER_VCS_VERSION_H -#ifdef _WIN32 -#pragma once -#endif - -// 1 = hl2 shipped -// 2 = compressed with diffs version (lostcoast) -// 3 = compressed with bzip -// 4 = v2 + crc32 -// 5 = v3 + crc32 -// 6 = v5 + duplicate static combo records -#define SHADER_VCS_VERSION_NUMBER 6 - -#define MAX_SHADER_UNPACKED_BLOCK_SIZE (1<<17) -#define MAX_SHADER_PACKED_SIZE (1+MAX_SHADER_UNPACKED_BLOCK_SIZE) - -#pragma pack(1) -struct ShaderHeader_t -{ - int32 m_nVersion; - int32 m_nTotalCombos; - int32 m_nDynamicCombos; - uint32 m_nFlags; - uint32 m_nCentroidMask; - uint32 m_nNumStaticCombos; // includes sentinal key - uint32 m_nSourceCRC32; // NOTE: If you move this, update copyshaders.pl, *_prep.pl, updateshaders.pl -}; -#pragma pack() - -#pragma pack(1) -struct ShaderHeader_t_v4 // still used for assembly shaders -{ - int32 m_nVersion; - int32 m_nTotalCombos; - int32 m_nDynamicCombos; - uint32 m_nFlags; - uint32 m_nCentroidMask; - uint32 m_nDiffReferenceSize; - uint32 m_nSourceCRC32; // NOTE: If you move this, update copyshaders.pl, *_prep.pl, updateshaders.pl -}; -#pragma pack() - -// for old format files -struct ShaderDictionaryEntry_t -{ - int m_Offset; - int m_Size; -}; - -// record for one static combo -struct StaticComboRecord_t -{ - uint32 m_nStaticComboID; - uint32 m_nFileOffset; -}; - - -struct StaticComboAliasRecord_t // for duplicate static combos -{ - uint32 m_nStaticComboID; // this combo - uint32 m_nSourceStaticCombo; // the combo it is the same as -}; - - - - -#endif // SHADER_VCS_VERSION_H - diff --git a/public/mathlib/IceKey.H b/public/mathlib/IceKey.H deleted file mode 100644 index f8641d067..000000000 --- a/public/mathlib/IceKey.H +++ /dev/null @@ -1,62 +0,0 @@ -// Purpose: Header file for the C++ ICE encryption class. -// Taken from public domain code, as written by Matthew Kwan - July 1996 -// http://www.darkside.com.au/ice/ - -#ifndef _IceKey_H -#define _IceKey_H - -/* -The IceKey class is used for encrypting and decrypting 64-bit blocks of data -with the ICE (Information Concealment Engine) encryption algorithm. - -The constructor creates a new IceKey object that can be used to encrypt and decrypt data. -The level of encryption determines the size of the key, and hence its speed. -Level 0 uses the Thin-ICE variant, which is an 8-round cipher taking an 8-byte key. -This is the fastest option, and is generally considered to be at least as secure as DES, -although it is not yet certain whether it is as secure as its key size. - -For levels n greater than zero, a 16n-round cipher is used, taking 8n-byte keys. -Although not as fast as level 0, these are very very secure. - -Before an IceKey can be used to encrypt data, its key schedule must be set with the set() member function. -The length of the key required is determined by the level, as described above. - -The member functions encrypt() and decrypt() encrypt and decrypt respectively data -in blocks of eight chracters, using the specified key. - -Two functions keySize() and blockSize() are provided -which return the key and block size respectively, measured in bytes. -The key size is determined by the level, while the block size is always 8. - -The destructor zeroes out and frees up all memory associated with the key. -*/ - -class IceSubkey; - -class IceKey { - public: - IceKey (int n); - ~IceKey (); - - void set (const unsigned char *key); - - void encrypt (const unsigned char *plaintext, - unsigned char *ciphertext) const; - - void decrypt (const unsigned char *ciphertext, - unsigned char *plaintext) const; - - int keySize () const; - - int blockSize () const; - - private: - void scheduleBuild (unsigned short *k, int n, - const int *keyrot); - - int _size; - int _rounds; - IceSubkey *_keysched; -}; - -#endif diff --git a/public/mathlib/amd3dx.h b/public/mathlib/amd3dx.h deleted file mode 100644 index a44a28894..000000000 --- a/public/mathlib/amd3dx.h +++ /dev/null @@ -1,1187 +0,0 @@ -/****************************************************************************** - - Copyright (c) 1999 Advanced Micro Devices, Inc. - - LIMITATION OF LIABILITY: THE MATERIALS ARE PROVIDED *AS IS* WITHOUT ANY - EXPRESS OR IMPLIED WARRANTY OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, - NONINFRINGEMENT OF THIRD-PARTY INTELLECTUAL PROPERTY, OR FITNESS FOR ANY - PARTICULAR PURPOSE. IN NO EVENT SHALL AMD OR ITS SUPPLIERS BE LIABLE FOR ANY - DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, - BUSINESS INTERRUPTION, LOSS OF INFORMATION) ARISING OUT OF THE USE OF OR - INABILITY TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE POSSIBILITY - OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE EXCLUSION OR LIMITATION - OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY - NOT APPLY TO YOU. - - AMD does not assume any responsibility for any errors which may appear in the - Materials nor any responsibility to support or update the Materials. AMD retains - the right to make changes to its test specifications at any time, without notice. - - NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any - further information, software, technical information, know-how, or show-how - available to you. - - So that all may benefit from your experience, please report any problems - or suggestions about this software to 3dsdk.support@amd.com - - AMD Developer Technologies, M/S 585 - Advanced Micro Devices, Inc. - 5900 E. Ben White Blvd. - Austin, TX 78741 - 3dsdk.support@amd.com - -******************************************************************************* - - AMD3DX.H - - MACRO FORMAT - ============ - This file contains inline assembly macros that - generate AMD-3D instructions in binary format. - Therefore, C or C++ programmer can use AMD-3D instructions - without any penalty in their C or C++ source code. - - The macro's name and format conventions are as follow: - - - 1. First argument of macro is a destination and - second argument is a source operand. - ex) _asm PFCMPEQ (mm3, mm4) - | | - dst src - - 2. The destination operand can be m0 to m7 only. - The source operand can be any one of the register - m0 to m7 or _eax, _ecx, _edx, _ebx, _esi, or _edi - that contains effective address. - ex) _asm PFRCP (MM7, MM6) - ex) _asm PFRCPIT2 (mm0, mm4) - ex) _asm PFMUL (mm3, _edi) - - 3. The prefetch(w) takes one src operand _eax, ecx, _edx, - _ebx, _esi, or _edi that contains effective address. - ex) _asm PREFETCH (_edi) - - For WATCOM C/C++ users, when using #pragma aux instead if - _asm, all macro names should be prefixed by a p_ or P_. - Macros should not be enclosed in quotes. - ex) p_pfrcp (MM7,MM6) - - NOTE: Not all instruction macros, nor all possible - combinations of operands have been explicitely - tested. If any errors are found, please report - them. - - EXAMPLE - ======= - Following program doesn't do anything but it shows you - how to use inline assembly AMD-3D instructions in C. - Note that this will only work in flat memory model which - segment registers cs, ds, ss and es point to the same - linear address space total less than 4GB. - - Used Microsoft VC++ 5.0 - - #include - #include "amd3d.h" - - void main () - { - float x = (float)1.25; - float y = (float)1.25; - float z, zz; - - _asm { - movd mm1, x - movd mm2, y - pfmul (mm1, mm2) - movd z, mm1 - femms - } - - printf ("value of z = %f\n", z); - - // - // Demonstration of using the memory instead of - // multimedia register - // - _asm { - movd mm3, x - lea esi, y // load effective address of y - pfmul (mm3, _esi) - movd zz, mm3 - femms - } - - printf ("value of zz = %f\n", zz); - } - - #pragma aux EXAMPLE with WATCOM C/C++ v11.x - =========================================== - - extern void Add(float *__Dest, float *__A, float *__B); - #pragma aux Add = \ - p_femms \ - "movd mm6,[esi]" \ - p_pfadd(mm6,_edi) \ - "movd [ebx],mm6" \ - p_femms \ - parm [ebx] [esi] [edi]; - -*******************************************************************************/ - -#ifndef _K3DMACROSINCLUDED_ -#define _K3DMACROSINCLUDED_ - -#if defined (__WATCOMC__) - -// The WATCOM C/C++ version of the 3DNow! macros. -// -// The older, compbined register style for WATCOM C/C++ macros is not -// supported. - -/* Operand defines for instructions two operands */ -#define _k3d_mm0_mm0 0xc0 -#define _k3d_mm0_mm1 0xc1 -#define _k3d_mm0_mm2 0xc2 -#define _k3d_mm0_mm3 0xc3 -#define _k3d_mm0_mm4 0xc4 -#define _k3d_mm0_mm5 0xc5 -#define _k3d_mm0_mm6 0xc6 -#define _k3d_mm0_mm7 0xc7 -#define _k3d_mm0_eax 0x00 -#define _k3d_mm0_ecx 0x01 -#define _k3d_mm0_edx 0x02 -#define _k3d_mm0_ebx 0x03 -#define _k3d_mm0_esi 0x06 -#define _k3d_mm0_edi 0x07 -#define _k3d_mm1_mm0 0xc8 -#define _k3d_mm1_mm1 0xc9 -#define _k3d_mm1_mm2 0xca -#define _k3d_mm1_mm3 0xcb -#define _k3d_mm1_mm4 0xcc -#define _k3d_mm1_mm5 0xcd -#define _k3d_mm1_mm6 0xce -#define _k3d_mm1_mm7 0xcf -#define _k3d_mm1_eax 0x08 -#define _k3d_mm1_ecx 0x09 -#define _k3d_mm1_edx 0x0a -#define _k3d_mm1_ebx 0x0b -#define _k3d_mm1_esi 0x0e -#define _k3d_mm1_edi 0x0f -#define _k3d_mm2_mm0 0xd0 -#define _k3d_mm2_mm1 0xd1 -#define _k3d_mm2_mm2 0xd2 -#define _k3d_mm2_mm3 0xd3 -#define _k3d_mm2_mm4 0xd4 -#define _k3d_mm2_mm5 0xd5 -#define _k3d_mm2_mm6 0xd6 -#define _k3d_mm2_mm7 0xd7 -#define _k3d_mm2_eax 0x10 -#define _k3d_mm2_ecx 0x11 -#define _k3d_mm2_edx 0x12 -#define _k3d_mm2_ebx 0x13 -#define _k3d_mm2_esi 0x16 -#define _k3d_mm2_edi 0x17 -#define _k3d_mm3_mm0 0xd8 -#define _k3d_mm3_mm1 0xd9 -#define _k3d_mm3_mm2 0xda -#define _k3d_mm3_mm3 0xdb -#define _k3d_mm3_mm4 0xdc -#define _k3d_mm3_mm5 0xdd -#define _k3d_mm3_mm6 0xde -#define _k3d_mm3_mm7 0xdf -#define _k3d_mm3_eax 0x18 -#define _k3d_mm3_ecx 0x19 -#define _k3d_mm3_edx 0x1a -#define _k3d_mm3_ebx 0x1b -#define _k3d_mm3_esi 0x1e -#define _k3d_mm3_edi 0x1f -#define _k3d_mm4_mm0 0xe0 -#define _k3d_mm4_mm1 0xe1 -#define _k3d_mm4_mm2 0xe2 -#define _k3d_mm4_mm3 0xe3 -#define _k3d_mm4_mm4 0xe4 -#define _k3d_mm4_mm5 0xe5 -#define _k3d_mm4_mm6 0xe6 -#define _k3d_mm4_mm7 0xe7 -#define _k3d_mm4_eax 0x20 -#define _k3d_mm4_ecx 0x21 -#define _k3d_mm4_edx 0x22 -#define _k3d_mm4_ebx 0x23 -#define _k3d_mm4_esi 0x26 -#define _k3d_mm4_edi 0x27 -#define _k3d_mm5_mm0 0xe8 -#define _k3d_mm5_mm1 0xe9 -#define _k3d_mm5_mm2 0xea -#define _k3d_mm5_mm3 0xeb -#define _k3d_mm5_mm4 0xec -#define _k3d_mm5_mm5 0xed -#define _k3d_mm5_mm6 0xee -#define _k3d_mm5_mm7 0xef -#define _k3d_mm5_eax 0x28 -#define _k3d_mm5_ecx 0x29 -#define _k3d_mm5_edx 0x2a -#define _k3d_mm5_ebx 0x2b -#define _k3d_mm5_esi 0x2e -#define _k3d_mm5_edi 0x2f -#define _k3d_mm6_mm0 0xf0 -#define _k3d_mm6_mm1 0xf1 -#define _k3d_mm6_mm2 0xf2 -#define _k3d_mm6_mm3 0xf3 -#define _k3d_mm6_mm4 0xf4 -#define _k3d_mm6_mm5 0xf5 -#define _k3d_mm6_mm6 0xf6 -#define _k3d_mm6_mm7 0xf7 -#define _k3d_mm6_eax 0x30 -#define _k3d_mm6_ecx 0x31 -#define _k3d_mm6_edx 0x32 -#define _k3d_mm6_ebx 0x33 -#define _k3d_mm6_esi 0x36 -#define _k3d_mm6_edi 0x37 -#define _k3d_mm7_mm0 0xf8 -#define _k3d_mm7_mm1 0xf9 -#define _k3d_mm7_mm2 0xfa -#define _k3d_mm7_mm3 0xfb -#define _k3d_mm7_mm4 0xfc -#define _k3d_mm7_mm5 0xfd -#define _k3d_mm7_mm6 0xfe -#define _k3d_mm7_mm7 0xff -#define _k3d_mm7_eax 0x38 -#define _k3d_mm7_ecx 0x39 -#define _k3d_mm7_edx 0x3a -#define _k3d_mm7_ebx 0x3b -#define _k3d_mm7_esi 0x3e -#define _k3d_mm7_edi 0x3f - -#define _k3d_name_xlat_m0 _mm0 -#define _k3d_name_xlat_m1 _mm1 -#define _k3d_name_xlat_m2 _mm2 -#define _k3d_name_xlat_m3 _mm3 -#define _k3d_name_xlat_m4 _mm4 -#define _k3d_name_xlat_m5 _mm5 -#define _k3d_name_xlat_m6 _mm6 -#define _k3d_name_xlat_m7 _mm7 -#define _k3d_name_xlat_M0 _mm0 -#define _k3d_name_xlat_M1 _mm1 -#define _k3d_name_xlat_M2 _mm2 -#define _k3d_name_xlat_M3 _mm3 -#define _k3d_name_xlat_M4 _mm4 -#define _k3d_name_xlat_M5 _mm5 -#define _k3d_name_xlat_M6 _mm6 -#define _k3d_name_xlat_M7 _mm7 -#define _k3d_name_xlat_mm0 _mm0 -#define _k3d_name_xlat_mm1 _mm1 -#define _k3d_name_xlat_mm2 _mm2 -#define _k3d_name_xlat_mm3 _mm3 -#define _k3d_name_xlat_mm4 _mm4 -#define _k3d_name_xlat_mm5 _mm5 -#define _k3d_name_xlat_mm6 _mm6 -#define _k3d_name_xlat_mm7 _mm7 -#define _k3d_name_xlat_MM0 _mm0 -#define _k3d_name_xlat_MM1 _mm1 -#define _k3d_name_xlat_MM2 _mm2 -#define _k3d_name_xlat_MM3 _mm3 -#define _k3d_name_xlat_MM4 _mm4 -#define _k3d_name_xlat_MM5 _mm5 -#define _k3d_name_xlat_MM6 _mm6 -#define _k3d_name_xlat_MM7 _mm7 -#define _k3d_name_xlat_eax _eax -#define _k3d_name_xlat_ebx _ebx -#define _k3d_name_xlat_ecx _ecx -#define _k3d_name_xlat_edx _edx -#define _k3d_name_xlat_esi _esi -#define _k3d_name_xlat_edi _edi -#define _k3d_name_xlat_ebp _ebp -#define _k3d_name_xlat_EAX _eax -#define _k3d_name_xlat_EBX _ebx -#define _k3d_name_xlat_ECX _ecx -#define _k3d_name_xlat_EDX _edx -#define _k3d_name_xlat_ESI _esi -#define _k3d_name_xlat_EDI _edi -#define _k3d_name_xlat_EBP _ebp -#define _k3d_name_xlat__eax _eax -#define _k3d_name_xlat__ebx _ebx -#define _k3d_name_xlat__ecx _ecx -#define _k3d_name_xlat__edx _edx -#define _k3d_name_xlat__esi _esi -#define _k3d_name_xlat__edi _edi -#define _k3d_name_xlat__ebp _ebp -#define _k3d_name_xlat__EAX _eax -#define _k3d_name_xlat__EBX _ebx -#define _k3d_name_xlat__ECX _ecx -#define _k3d_name_xlat__EDX _edx -#define _k3d_name_xlat__ESI _esi -#define _k3d_name_xlat__EDI _edi -#define _k3d_name_xlat__EBP _ebp - -#define _k3d_xglue3(a,b,c) a##b##c -#define _k3d_glue3(a,b,c) _k3d_xglue3(a,b,c) -#define _k3d_MODRM(dst, src) _k3d_glue3(_k3d,_k3d_name_xlat_##dst,_k3d_name_xlat_##src) - -/* Operand defines for prefetch and prefetchw */ - -#define _k3d_pref_eax 0x00 -#define _k3d_pref_ecx 0x01 -#define _k3d_pref_edx 0x02 -#define _k3d_pref_ebx 0x03 -#define _k3d_pref_esi 0x06 -#define _k3d_pref_edi 0x07 -#define _k3d_pref_EAX 0x00 -#define _k3d_pref_ECX 0x01 -#define _k3d_pref_EDX 0x02 -#define _k3d_pref_EBX 0x03 -#define _k3d_pref_ESI 0x06 -#define _k3d_pref_EDI 0x07 -#define _k3d_prefw_eax 0x08 -#define _k3d_prefw_ecx 0x09 -#define _k3d_prefw_edx 0x0A -#define _k3d_prefw_ebx 0x0B -#define _k3d_prefw_esi 0x0E -#define _k3d_prefw_edi 0x0F -#define _k3d_prefw_EAX 0x08 -#define _k3d_prefw_ECX 0x09 -#define _k3d_prefw_EDX 0x0A -#define _k3d_prefw_EBX 0x0B -#define _k3d_prefw_ESI 0x0E -#define _k3d_prefw_EDI 0x0F - -/* Defines for 3DNow! instructions */ -#define PF2ID(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x1d -#define PFACC(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xae -#define PFADD(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x9e -#define PFCMPEQ(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xb0 -#define PFCMPGE(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x90 -#define PFCMPGT(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xa0 -#define PFMAX(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xa4 -#define PFMIN(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x94 -#define PFMUL(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xb4 -#define PFRCP(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x96 -#define PFRCPIT1(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xa6 -#define PFRCPIT2(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xb6 -#define PFRSQRT(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x97 -#define PFRSQIT1(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xa7 -#define PFSUB(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x9a -#define PFSUBR(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xaa -#define PI2FD(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0x0d -#define FEMMS db 0x0f, 0x0e -#define PAVGUSB(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xbf -#define PMULHRW(dst, src) db 0x0f, 0x0f, _k3d_MODRM(dst, src), 0xb7 -#define PREFETCH(src) db 0x0f, 0x0d, _k3d_pref_##src -#define PREFETCHW(src) db 0x0f, 0x0d, _k3d_prefw_##src -#define CPUID db 0x0f, 0xa2 - -/* Defines for new, K7 opcodes */ -#define PFNACC(dst,src) db 0x0f, 0x0f, _k3d_MODRM(dst,src), 0x8a -#define FPPNACC(dst,src) db 0x0f, 0x0f, _k3d_MODRM(dst,src), 0x8e -#define PSWAPD(dst,src) db 0x0f, 0x0f, _k3d_MODRM(dst,src), 0xbb -#define PMINUB(dst,src) db 0x0f, 0xda, _k3d_MODRM(dst,src) -#define PMAXUB(dst,src) db 0x0f, 0xde, _k3d_MODRM(dst,src) -#define PMINSW(dst,src) db 0x0f, 0xea, _k3d_MODRM(dst,src) -#define PMAXSW(dst,src) db 0x0f, 0xee, _k3d_MODRM(dst,src) -#define PMULHUW(dst,src) db 0x0f, 0xe4, _k3d_MODRM(dst,src) -#define PAVGB(dst,src) db 0x0f, 0xe0, _k3d_MODRM(dst,src) -#define PAVGW(dst,src) db 0x0f, 0xe3, _k3d_MODRM(dst,src) -#define PSADBW(dst,src) db 0x0f, 0xf6, _k3d_MODRM(dst,src) -#define PMOVMSKB(dst,src) db 0x0f, 0xd7, _k3d_MODRM(dst,src) -#define PMASKMOVQ(dst,src) db 0x0f, 0xf7, _k3d_MODRM(dst,src) -#define PINSRW(dst,src,msk) db 0x0f, 0xc4, _k3d_MODRM(dst,src), msk -#define PEXTRW(dst,src,msk) db 0x0f, 0xc5, _k3d_MODRM(dst,src), msk -#define PSHUFW(dst,src,msk) db 0x0f, 0x70, _k3d_MODRM(dst,src), msk -#define MOVNTQ(dst,src) db 0x0f, 0xe7, _k3d_MODRM(src,dst) -#define SFENCE db 0x0f, 0xae, 0xf8 - -/* Memory/offset versions of the opcodes */ -#define PF2IDM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x1d -#define PFACCM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xae -#define PFADDM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x9e -#define PFCMPEQM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xb0 -#define PFCMPGEM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x90 -#define PFCMPGTM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xa0 -#define PFMAXM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xa4 -#define PFMINM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x94 -#define PFMULM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xb4 -#define PFRCPM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x96 -#define PFRCPIT1M(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xa6 -#define PFRCPIT2M(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xb6 -#define PFRSQRTM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x97 -#define PFRSQIT1M(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xa7 -#define PFSUBM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x9a -#define PFSUBRM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xaa -#define PI2FDM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x0d -#define PAVGUSBM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xbf -#define PMULHRWM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xb7 - - -/* Memory/offset versions of the new, K7 opcodes */ -#define PFNACCM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x8a -#define FPPNACCM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0x8e -#define PSWAPDM(dst,src,off) db 0x0f, 0x0f, _k3d_MODRM(dst,src) | 0x40, off, 0xbb -#define PMINUBM(dst,src,off) db 0x0f, 0xda, _k3d_MODRM(dst,src) | 0x40, off -#define PMAXUBM(dst,src,off) db 0x0f, 0xde, _k3d_MODRM(dst,src) | 0x40, off -#define PMINSWM(dst,src,off) db 0x0f, 0xea, _k3d_MODRM(dst,src) | 0x40, off -#define PMAXSWM(dst,src,off) db 0x0f, 0xee, _k3d_MODRM(dst,src) | 0x40, off -#define PMULHUWM(dst,src,off) db 0x0f, 0xe4, _k3d_MODRM(dst,src) | 0x40, off -#define PAVGBM(dst,src,off) db 0x0f, 0xe0, _k3d_MODRM(dst,src) | 0x40, off -#define PAVGWM(dst,src,off) db 0x0f, 0xe3, _k3d_MODRM(dst,src) | 0x40, off -#define PSADBWM(dst,src,off) db 0x0f, 0xf6, _k3d_MODRM(dst,src) | 0x40, off -#define PMOVMSKBM(dst,src,off) db 0x0f, 0xd7, _k3d_MODRM(dst,src) | 0x40, off -#define PMASKMOVQM(dst,src,off) db 0x0f, 0xf7, _k3d_MODRM(dst,src) | 0x40, off -#define MOVNTQM(dst,src,off) db 0x0f, 0xe7, _k3d_MODRM(src,dst) | 0x40, off -#define PINSRWM(dst,src,off,msk) db 0x0f, 0xc4, _k3d_MODRM(dst,src) | 0x40, off, msk -#define PSHUFWM(dst,src,off,msk) db 0x0f, 0x70, _k3d_MODRM(dst,src) | 0x40, off, msk - - -/* Defines for 3DNow! instructions for use in pragmas */ -#define p_pf2id(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x1d -#define p_pfacc(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xae -#define p_pfadd(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x9e -#define p_pfcmpeq(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xb0 -#define p_pfcmpge(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x90 -#define p_pfcmpgt(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xa0 -#define p_pfmax(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xa4 -#define p_pfmin(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x94 -#define p_pfmul(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xb4 -#define p_pfrcp(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x96 -#define p_pfrcpit1(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xa6 -#define p_pfrcpit2(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xb6 -#define p_pfrsqrt(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x97 -#define p_pfrsqit1(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xa7 -#define p_pfsub(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x9a -#define p_pfsubr(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xaa -#define p_pi2fd(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0x0d -#define p_femms 0x0f 0x0e -#define p_pavgusb(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xbf -#define p_pmulhrw(dst,src) 0x0f 0x0f _k3d_MODRM(dst,src) 0xb7 -#define p_prefetch(src) 0x0f 0x0d _k3d_pref_##src -#define p_prefetchw(src) 0x0f 0x0d _k3d_prefw_##src -#define P_PFNACC(dst,src) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x8a -#define P_FPPNACC(dst,src) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x8e -#define P_PSWAPD(dst,src) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xbb -#define P_PMINUB(dst,src) 0x0f 0xda (_k3d_MODRM(dst,src) | 0x40) off -#define P_PMAXUB(dst,src) 0x0f 0xde (_k3d_MODRM(dst,src) | 0x40) off -#define P_PMINSW(dst,src) 0x0f 0xea (_k3d_MODRM(dst,src) | 0x40) off -#define P_PMAXSW(dst,src) 0x0f 0xee (_k3d_MODRM(dst,src) | 0x40) off -#define P_PMULHUW(dst,src) 0x0f 0xe4 (_k3d_MODRM(dst,src) | 0x40) off -#define P_PAVGB(dst,src) 0x0f 0xe0 (_k3d_MODRM(dst,src) | 0x40) off -#define P_PAVGW(dst,src) 0x0f 0xe3 (_k3d_MODRM(dst,src) | 0x40) off -#define P_PSADBW(dst,src) 0x0f 0xf6 (_k3d_MODRM(dst,src) | 0x40) off -#define P_PMOVMSKB(dst,src) 0x0f 0xd7 (_k3d_MODRM(dst,src) | 0x40) off -#define P_PMASKMOVQ(dst,src) 0x0f 0xf7 (_k3d_MODRM(dst,src) | 0x40) off -#define P_PINSRW(dst,src,msk) 0x0f 0xc4 (_k3d_MODRM(dst,src) | 0x40) off msk -#define P_PEXTRW(dst,src,msk) 0x0f 0xc5 (_k3d_MODRM(dst,src) | 0x40) off msk -#define P_PSHUFW(dst,src,msk) 0x0f 0x70 (_k3d_MODRM(dst,src) | 0x40) off msk -#define P_MOVNTQ(dst,src) 0x0f 0xe7 (_k3d_MODRM(src,dst) | 0x40) off - -#define P_PF2IDM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x1d -#define P_PFACCM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xae -#define P_PFADDM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x9e -#define P_PFCMPEQM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xb0 -#define P_PFCMPGEM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x90 -#define P_PFCMPGTM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xa0 -#define P_PFMAXM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xa4 -#define P_PFMINM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x94 -#define P_PFMULM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xb4 -#define P_PFRCPM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x96 -#define P_PFRCPIT1M(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xa6 -#define P_PFRCPIT2M(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xb6 -#define P_PFRSQRTM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x97 -#define P_PFRSQIT1M(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xa7 -#define P_PFSUBM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x9a -#define P_PFSUBRM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xaa -#define P_PI2FDM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x0d -#define P_PAVGUSBM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xbf -#define P_PMULHRWM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xb7 -#define P_PFNACCM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x8a -#define P_FPPNACCM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0x8e -#define P_PSWAPDM(dst,src,off) 0x0f 0x0f (_k3d_MODRM(dst,src) | 0x40) off 0xbb -#define P_PMINUBM(dst,src,off) 0x0f 0xda (_k3d_MODRM(dst,src) | 0x40) off -#define P_PMAXUBM(dst,src,off) 0x0f 0xde (_k3d_MODRM(dst,src) | 0x40) off -#define P_PMINSWM(dst,src,off) 0x0f 0xea (_k3d_MODRM(dst,src) | 0x40) off -#define P_PMAXSWM(dst,src,off) 0x0f 0xee (_k3d_MODRM(dst,src) | 0x40) off -#define P_PMULHUWM(dst,src,off) 0x0f 0xe4 (_k3d_MODRM(dst,src) | 0x40) off -#define P_PAVGBM(dst,src,off) 0x0f 0xe0 (_k3d_MODRM(dst,src) | 0x40) off -#define P_PAVGWM(dst,src,off) 0x0f 0xe3 (_k3d_MODRM(dst,src) | 0x40) off -#define P_PSADBWM(dst,src,off) 0x0f 0xf6 (_k3d_MODRM(dst,src) | 0x40) off -#define P_PMOVMSKBM(dst,src,off) 0x0f 0xd7 (_k3d_MODRM(dst,src) | 0x40) off -#define P_MOVNTQM(dst,src,off) 0x0f 0xe7 (_k3d_MODRM(src,dst) | 0x40) off -#define P_PMASKMOVQM(dst,src,off) 0x0f 0xf7 (_k3d_MODRM(dst,src) | 0x40) off -#define P_PINSRWM(dst,src,off,msk) 0x0f 0xc4 (_k3d_MODRM(dst,src) | 0x40) off msk -#define P_PSHUFWM(dst,src,off,msk) 0x0f 0x70 (_k3d_MODRM(dst,src) | 0x40) off msk - - -#define P_PF2ID(dst,src) p_pf2id(dst,src) -#define P_PFACC(dst,src) p_pfacc(dst,src) -#define P_PFADD(dst,src) p_pfadd(dst,src) -#define P_PFCMPEQ(dst,src) p_pfcmpeq(dst,src) -#define P_PFCMPGE(dst,src) p_pfcmpge(dst,src) -#define P_PFCMPGT(dst,src) p_pfcmpgt(dst,src) -#define P_PFMAX(dst,src) p_pfmax(dst,src) -#define P_PFMIN(dst,src) p_pfmin(dst,src) -#define P_PFMUL(dst,src) p_pfmul(dst,src) -#define P_PFRCP(dst,src) p_pfrcp(dst,src) -#define P_PFRCPIT1(dst,src) p_pfrcpit1(dst,src) -#define P_PFRCPIT2(dst,src) p_pfrcpit2(dst,src) -#define P_PFRSQRT(dst,src) p_pfrsqrt(dst,src) -#define P_PFRSQIT1(dst,src) p_pfrsqit1(dst,src) -#define P_PFSUB(dst,src) p_pfsub(dst,src) -#define P_PFSUBR(dst,src) p_pfsubr(dst,src) -#define P_PI2FD(dst,src) p_pi2fd(dst,src) -#define P_FEMMS p_femms -#define P_PAVGUSB(dst,src) p_pavgusb(dst,src) -#define P_PMULHRW(dst,src) p_pmulhrw(dst,src) -#define P_PREFETCH(src) p_prefetch(src) -#define P_PREFETCHW(src) p_prefetchw(src) -#define p_CPUID 0x0f 0xa2 -#define p_pf2idm(dst,src,off) P_PF2IDM(dst,src,off) -#define p_pfaccm(dst,src,off) P_PFACCM(dst,src,off) -#define p_pfaddm(dst,src,off) P_PFADDM(dst,src,off) -#define p_pfcmpeqm(dst,src,off) P_PFCMPEQM(dst,src,off) -#define p_pfcmpgem(dst,src,off) P_PFCMPGEM(dst,src,off) -#define p_pfcmpgtm(dst,src,off) P_PFCMPGTM(dst,src,off) -#define p_pfmaxm(dst,src,off) P_PFMAXM(dst,src,off) -#define p_pfminm(dst,src,off) P_PFMINM(dst,src,off) -#define p_pfmulm(dst,src,off) P_PFMULM(dst,src,off) -#define p_pfrcpm(dst,src,off) P_PFRCPM(dst,src,off) -#define p_pfrcpit1m(dst,src,off) P_PFRCPIT1M(dst,src,off) -#define p_pfrcpit2m(dst,src,off) P_PFRCPIT2M(dst,src,off) -#define p_pfrsqrtm(dst,src,off) P_PFRSQRTM(dst,src,off) -#define p_pfrsqit1m(dst,src,off) P_PFRSQIT1M(dst,src,off) -#define p_pfsubm(dst,src,off) P_PFSUBM(dst,src,off) -#define p_pfsubrm(dst,src,off) P_PFSUBRM(dst,src,off) -#define p_pi2fdm(dst,src,off) P_PI2FDM(dst,src,off) -#define p_pavgusbm(dst,src,off) P_PAVGUSBM(dst,src,off) -#define p_pmulhrwm(dst,src,off) P_PMULHRWM(dst,src,off) - -#define P_PFNACC(dst,src) p_pfnacc(dst,src) -#define P_FPPNACC(dst,src) p_pfpnacc(dst,src) -#define P_PSWAPD(dst,src) p_pswapd(dst,src) -#define P_PMINUB(dst,src) p_pminub(dst,src) -#define P_PMAXUB(dst,src) p_pmaxub(dst,src) -#define P_PMINSW(dst,src) p_pminsw(dst,src) -#define P_PMAXSW(dst,src) p_pmaxsw(dst,src) -#define P_PMULHUW(dst,src) p_pmulhuw(dst,src) -#define P_PAVGB(dst,src) p_pavgb(dst,src) -#define P_PAVGW(dst,src) p_avgw(dst,src) -#define P_PSADBW(dst,src) p_psadbw(dst,src) -#define P_PMOVMSKB(dst,src) p_pmovmskb(dst,src) -#define P_PMASKMOVQ(dst,src) p_pmaskmovq(dst,src) -#define P_PINSRW(dst,src,msk) p_pinsrw(dst,src) -#define P_PEXTRW(dst,src,msk) p_pextrw(dst,src) -#define P_PSHUFW(dst,src,msk) p_pshufw(dst,src) -#define P_MOVNTQ(dst,src) p_movntq(dst,src) - -#define P_PFNACCM(dst,src,off) p_pfnaccm(dst,src,off) -#define P_FPPNACCM(dst,src,off) p_pfpnaccm(dst,src,off) -#define P_PSWAPDM(dst,src,off) p_pswapdm(dst,src,off) -#define P_PMINUBM(dst,src,off) p_pminubm(dst,src,off) -#define P_PMAXUBM(dst,src,off) p_pmaxubm(dst,src,off) -#define P_PMINSWM(dst,src,off) p_pminswm(dst,src,off) -#define P_PMAXSWM(dst,src,off) p_pmaxswm(dst,src,off) -#define P_PMULHUWM(dst,src,off) p_pmulhuwm(dst,src,off) -#define P_PAVGBM(dst,src,off) p_pavgbm(dst,src,off) -#define P_PAVGWM(dst,src,off) p_avgwm(dst,src,off) -#define P_PSADBWM(dst,src,off) p_psadbwm(dst,src,off) -#define P_PMOVMSKBM(dst,src,off) p_pmovmskbm(dst,src,off) -#define P_PMASKMOVQM(dst,src,off) p_pmaskmovqm(dst,src,off) -#define P_PINSRWM(dst,src,off,msk) p_pinsrwm(dst,src,off,msk) -#define P_PSHUFWM(dst,src,off,msk) p_pshufwm(dst,src,off,msk) -#define P_MOVNTQM(dst,src,off) p_movntqm(dst,src,off) - -#elif defined (_MSC_VER) && !defined (__MWERKS__) -// The Microsoft Visual C++ version of the 3DNow! macros. - -// Stop the "no EMMS" warning, since it doesn't detect FEMMS properly -#pragma warning(disable:4799) - -// Defines for operands. -#define _K3D_MM0 0xc0 -#define _K3D_MM1 0xc1 -#define _K3D_MM2 0xc2 -#define _K3D_MM3 0xc3 -#define _K3D_MM4 0xc4 -#define _K3D_MM5 0xc5 -#define _K3D_MM6 0xc6 -#define _K3D_MM7 0xc7 -#define _K3D_mm0 0xc0 -#define _K3D_mm1 0xc1 -#define _K3D_mm2 0xc2 -#define _K3D_mm3 0xc3 -#define _K3D_mm4 0xc4 -#define _K3D_mm5 0xc5 -#define _K3D_mm6 0xc6 -#define _K3D_mm7 0xc7 -#define _K3D_EAX 0x00 -#define _K3D_ECX 0x01 -#define _K3D_EDX 0x02 -#define _K3D_EBX 0x03 -#define _K3D_ESI 0x06 -#define _K3D_EDI 0x07 -#define _K3D_eax 0x00 -#define _K3D_ecx 0x01 -#define _K3D_edx 0x02 -#define _K3D_ebx 0x03 -#define _K3D_esi 0x06 -#define _K3D_edi 0x07 - -// These defines are for compatibility with the previous version of the header file. -#define _K3D_M0 0xc0 -#define _K3D_M1 0xc1 -#define _K3D_M2 0xc2 -#define _K3D_M3 0xc3 -#define _K3D_M4 0xc4 -#define _K3D_M5 0xc5 -#define _K3D_M6 0xc6 -#define _K3D_M7 0xc7 -#define _K3D_m0 0xc0 -#define _K3D_m1 0xc1 -#define _K3D_m2 0xc2 -#define _K3D_m3 0xc3 -#define _K3D_m4 0xc4 -#define _K3D_m5 0xc5 -#define _K3D_m6 0xc6 -#define _K3D_m7 0xc7 -#define _K3D__EAX 0x00 -#define _K3D__ECX 0x01 -#define _K3D__EDX 0x02 -#define _K3D__EBX 0x03 -#define _K3D__ESI 0x06 -#define _K3D__EDI 0x07 -#define _K3D__eax 0x00 -#define _K3D__ecx 0x01 -#define _K3D__edx 0x02 -#define _K3D__ebx 0x03 -#define _K3D__esi 0x06 -#define _K3D__edi 0x07 - -// General 3DNow! instruction format that is supported by -// these macros. Note that only the most basic form of memory -// operands are supported by these macros. - -#define InjK3DOps(dst,src,inst) \ -{ \ - _asm _emit 0x0f \ - _asm _emit 0x0f \ - _asm _emit ((_K3D_##dst & 0x3f) << 3) | _K3D_##src \ - _asm _emit _3DNowOpcode##inst \ -} - -#define InjK3DMOps(dst,src,off,inst) \ -{ \ - _asm _emit 0x0f \ - _asm _emit 0x0f \ - _asm _emit (((_K3D_##dst & 0x3f) << 3) | _K3D_##src | 0x40) \ - _asm _emit off \ - _asm _emit _3DNowOpcode##inst \ -} - -#define InjMMXOps(dst,src,inst) \ -{ \ - _asm _emit 0x0f \ - _asm _emit _3DNowOpcode##inst \ - _asm _emit ((_K3D_##dst & 0x3f) << 3) | _K3D_##src \ -} - -#define InjMMXMOps(dst,src,off,inst) \ -{ \ - _asm _emit 0x0f \ - _asm _emit _3DNowOpcode##inst \ - _asm _emit (((_K3D_##dst & 0x3f) << 3) | _K3D_##src | 0x40) \ - _asm _emit off \ -} - -#define _3DNowOpcodePF2ID 0x1d -#define _3DNowOpcodePFACC 0xae -#define _3DNowOpcodePFADD 0x9e -#define _3DNowOpcodePFCMPEQ 0xb0 -#define _3DNowOpcodePFCMPGE 0x90 -#define _3DNowOpcodePFCMPGT 0xa0 -#define _3DNowOpcodePFMAX 0xa4 -#define _3DNowOpcodePFMIN 0x94 -#define _3DNowOpcodePFMUL 0xb4 -#define _3DNowOpcodePFRCP 0x96 -#define _3DNowOpcodePFRCPIT1 0xa6 -#define _3DNowOpcodePFRCPIT2 0xb6 -#define _3DNowOpcodePFRSQRT 0x97 -#define _3DNowOpcodePFRSQIT1 0xa7 -#define _3DNowOpcodePFSUB 0x9a -#define _3DNowOpcodePFSUBR 0xaa -#define _3DNowOpcodePI2FD 0x0d -#define _3DNowOpcodePAVGUSB 0xbf -#define _3DNowOpcodePMULHRW 0xb7 -#define _3DNowOpcodePFNACC 0x8a -#define _3DNowOpcodeFPPNACC 0x8e -#define _3DNowOpcodePSWAPD 0xbb -#define _3DNowOpcodePMINUB 0xda -#define _3DNowOpcodePMAXUB 0xde -#define _3DNowOpcodePMINSW 0xea -#define _3DNowOpcodePMAXSW 0xee -#define _3DNowOpcodePMULHUW 0xe4 -#define _3DNowOpcodePAVGB 0xe0 -#define _3DNowOpcodePAVGW 0xe3 -#define _3DNowOpcodePSADBW 0xf6 -#define _3DNowOpcodePMOVMSKB 0xd7 -#define _3DNowOpcodePMASKMOVQ 0xf7 -#define _3DNowOpcodePINSRW 0xc4 -#define _3DNowOpcodePEXTRW 0xc5 -#define _3DNowOpcodePSHUFW 0x70 -#define _3DNowOpcodeMOVNTQ 0xe7 -#define _3DNowOpcodePREFETCHT 0x18 - - -#define PF2ID(dst,src) InjK3DOps(dst, src, PF2ID) -#define PFACC(dst,src) InjK3DOps(dst, src, PFACC) -#define PFADD(dst,src) InjK3DOps(dst, src, PFADD) -#define PFCMPEQ(dst,src) InjK3DOps(dst, src, PFCMPEQ) -#define PFCMPGE(dst,src) InjK3DOps(dst, src, PFCMPGE) -#define PFCMPGT(dst,src) InjK3DOps(dst, src, PFCMPGT) -#define PFMAX(dst,src) InjK3DOps(dst, src, PFMAX) -#define PFMIN(dst,src) InjK3DOps(dst, src, PFMIN) -#define PFMUL(dst,src) InjK3DOps(dst, src, PFMUL) -#define PFRCP(dst,src) InjK3DOps(dst, src, PFRCP) -#define PFRCPIT1(dst,src) InjK3DOps(dst, src, PFRCPIT1) -#define PFRCPIT2(dst,src) InjK3DOps(dst, src, PFRCPIT2) -#define PFRSQRT(dst,src) InjK3DOps(dst, src, PFRSQRT) -#define PFRSQIT1(dst,src) InjK3DOps(dst, src, PFRSQIT1) -#define PFSUB(dst,src) InjK3DOps(dst, src, PFSUB) -#define PFSUBR(dst,src) InjK3DOps(dst, src, PFSUBR) -#define PI2FD(dst,src) InjK3DOps(dst, src, PI2FD) -#define PAVGUSB(dst,src) InjK3DOps(dst, src, PAVGUSB) -#define PMULHRW(dst,src) InjK3DOps(dst, src, PMULHRW) - -#define FEMMS \ -{ \ - _asm _emit 0x0f \ - _asm _emit 0x0e \ -} - -#define PREFETCH(src) \ -{ \ - _asm _emit 0x0f \ - _asm _emit 0x0d \ - _asm _emit (_K3D_##src & 0x07) \ -} - -/* Prefetch with a short offset, < 127 or > -127 - Carefull! Doesn't check for your offset being - in range. */ - -#define PREFETCHM(src,off) \ -{ \ - _asm _emit 0x0f \ - _asm _emit 0x0d \ - _asm _emit (0x40 | (_K3D_##src & 0x07)) \ - _asm _emit off \ -} - -/* Prefetch with a long offset */ - -#define PREFETCHMLONG(src,off) \ -{ \ - _asm _emit 0x0f \ - _asm _emit 0x0d \ - _asm _emit (0x80 | (_K3D_##src & 0x07)) \ - _asm _emit (off & 0x000000ff) \ - _asm _emit (off & 0x0000ff00) >> 8 \ - _asm _emit (off & 0x00ff0000) >> 16 \ - _asm _emit (off & 0xff000000) >> 24 \ -} - -#define PREFETCHW(src) \ -{ \ - _asm _emit 0x0f \ - _asm _emit 0x0d \ - _asm _emit (0x08 | (_K3D_##src & 0x07)) \ -} - -#define PREFETCHWM(src,off) \ -{ \ - _asm _emit 0x0f \ - _asm _emit 0x0d \ - _asm _emit 0x48 | (_K3D_##src & 0x07) \ - _asm _emit off \ -} - -#define PREFETCHWMLONG(src,off) \ -{ \ - _asm _emit 0x0f \ - _asm _emit 0x0d \ - _asm _emit 0x88 | (_K3D_##src & 0x07) \ - _asm _emit (off & 0x000000ff) \ - _asm _emit (off & 0x0000ff00) >> 8 \ - _asm _emit (off & 0x00ff0000) >> 16 \ - _asm _emit (off & 0xff000000) >> 24 \ -} - -#define CPUID \ -{ \ - _asm _emit 0x0f \ - _asm _emit 0xa2 \ -} - - -/* Defines for new, K7 opcodes */ -#define SFENCE \ -{ \ - _asm _emit 0x0f \ - _asm _emit 0xae \ - _asm _emit 0xf8 \ -} - -#define PFNACC(dst,src) InjK3DOps(dst,src,PFNACC) -#define PFPNACC(dst,src) InjK3DOps(dst,src,PFPNACC) -#define PSWAPD(dst,src) InjK3DOps(dst,src,PSWAPD) -#define PMINUB(dst,src) InjMMXOps(dst,src,PMINUB) -#define PMAXUB(dst,src) InjMMXOps(dst,src,PMAXUB) -#define PMINSW(dst,src) InjMMXOps(dst,src,PMINSW) -#define PMAXSW(dst,src) InjMMXOps(dst,src,PMAXSW) -#define PMULHUW(dst,src) InjMMXOps(dst,src,PMULHUW) -#define PAVGB(dst,src) InjMMXOps(dst,src,PAVGB) -#define PAVGW(dst,src) InjMMXOps(dst,src,PAVGW) -#define PSADBW(dst,src) InjMMXOps(dst,src,PSADBW) -#define PMOVMSKB(dst,src) InjMMXOps(dst,src,PMOVMSKB) -#define PMASKMOVQ(dst,src) InjMMXOps(dst,src,PMASKMOVQ) -#define PINSRW(dst,src,msk) InjMMXOps(dst,src,PINSRW) _asm _emit msk -#define PEXTRW(dst,src,msk) InjMMXOps(dst,src,PEXTRW) _asm _emit msk -#define PSHUFW(dst,src,msk) InjMMXOps(dst,src,PSHUFW) _asm _emit msk -#define MOVNTQ(dst,src) InjMMXOps(src,dst,MOVNTQ) -#define PREFETCHNTA(mem) InjMMXOps(mm0,mem,PREFETCHT) -#define PREFETCHT0(mem) InjMMXOps(mm1,mem,PREFETCHT) -#define PREFETCHT1(mem) InjMMXOps(mm2,mem,PREFETCHT) -#define PREFETCHT2(mem) InjMMXOps(mm3,mem,PREFETCHT) - - -/* Memory/offset versions of the opcodes */ -#define PAVGUSBM(dst,src,off) InjK3DMOps(dst,src,off,PAVGUSB) -#define PF2IDM(dst,src,off) InjK3DMOps(dst,src,off,PF2ID) -#define PFACCM(dst,src,off) InjK3DMOps(dst,src,off,PFACC) -#define PFADDM(dst,src,off) InjK3DMOps(dst,src,off,PFADD) -#define PFCMPEQM(dst,src,off) InjK3DMOps(dst,src,off,PFCMPEQ) -#define PFCMPGEM(dst,src,off) InjK3DMOps(dst,src,off,PFCMPGE) -#define PFCMPGTM(dst,src,off) InjK3DMOps(dst,src,off,PFCMPGT) -#define PFMAXM(dst,src,off) InjK3DMOps(dst,src,off,PFMAX) -#define PFMINM(dst,src,off) InjK3DMOps(dst,src,off,PFMIN) -#define PFMULM(dst,src,off) InjK3DMOps(dst,src,off,PFMUL) -#define PFRCPM(dst,src,off) InjK3DMOps(dst,src,off,PFRCP) -#define PFRCPIT1M(dst,src,off) InjK3DMOps(dst,src,off,PFRCPIT1) -#define PFRCPIT2M(dst,src,off) InjK3DMOps(dst,src,off,PFRCPIT2) -#define PFRSQRTM(dst,src,off) InjK3DMOps(dst,src,off,PFRSQRT) -#define PFRSQIT1M(dst,src,off) InjK3DMOps(dst,src,off,PFRSQIT1) -#define PFSUBM(dst,src,off) InjK3DMOps(dst,src,off,PFSUB) -#define PFSUBRM(dst,src,off) InjK3DMOps(dst,src,off,PFSUBR) -#define PI2FDM(dst,src,off) InjK3DMOps(dst,src,off,PI2FD) -#define PMULHRWM(dst,src,off) InjK3DMOps(dst,src,off,PMULHRW) - - -/* Memory/offset versions of the K7 opcodes */ -#define PFNACCM(dst,src,off) InjK3DMOps(dst,src,off,PFNACC) -#define PFPNACCM(dst,src,off) InjK3DMOps(dst,src,off,PFPNACC) -#define PSWAPDM(dst,src,off) InjK3DMOps(dst,src,off,PSWAPD) -#define PMINUBM(dst,src,off) InjMMXMOps(dst,src,off,PMINUB) -#define PMAXUBM(dst,src,off) InjMMXMOps(dst,src,off,PMAXUB) -#define PMINSWM(dst,src,off) InjMMXMOps(dst,src,off,PMINSW) -#define PMAXSWM(dst,src,off) InjMMXMOps(dst,src,off,PMAXSW) -#define PMULHUWM(dst,src,off) InjMMXMOps(dst,src,off,PMULHUW) -#define PAVGBM(dst,src,off) InjMMXMOps(dst,src,off,PAVGB) -#define PAVGWM(dst,src,off) InjMMXMOps(dst,src,off,PAVGW) -#define PSADBWM(dst,src,off) InjMMXMOps(dst,src,off,PSADBW) -#define PMOVMSKBM(dst,src,off) InjMMXMOps(dst,src,off,PMOVMSKB) -#define PMASKMOVQM(dst,src,off) InjMMXMOps(dst,src,off,PMASKMOVQ) -#define PINSRWM(dst,src,off,msk) InjMMXMOps(dst,src,off,PINSRW) _asm _emit msk -#define PSHUFWM(dst,src,off,msk) InjMMXMOps(dst,src,off,PSHUFW) _asm _emit msk -#define MOVNTQM(dst,src,off) InjMMXMOps(src,dst,off,MOVNTQ) -#define PREFETCHNTAM(mem,off) InjMMXMOps(mm0,mem,off,PREFETCHT) -#define PREFETCHT0M(mem,off) InjMMXMOps(mm1,mem,off,PREFETCHT) -#define PREFETCHT1M(mem,off) InjMMXMOps(mm2,mem,off,PREFETCHT) -#define PREFETCHT2M(mem,off) InjMMXMOps(mm3,mem,off,PREFETCHT) - - -#else - -/* Assume built-in support for 3DNow! opcodes, replace macros with opcodes */ -#define PAVGUSB(dst,src) pavgusb dst,src -#define PF2ID(dst,src) pf2id dst,src -#define PFACC(dst,src) pfacc dst,src -#define PFADD(dst,src) pfadd dst,src -#define PFCMPEQ(dst,src) pfcmpeq dst,src -#define PFCMPGE(dst,src) pfcmpge dst,src -#define PFCMPGT(dst,src) pfcmpgt dst,src -#define PFMAX(dst,src) pfmax dst,src -#define PFMIN(dst,src) pfmin dst,src -#define PFMUL(dst,src) pfmul dst,src -#define PFRCP(dst,src) pfrcp dst,src -#define PFRCPIT1(dst,src) pfrcpit1 dst,src -#define PFRCPIT2(dst,src) pfrcpit2 dst,src -#define PFRSQRT(dst,src) pfrsqrt dst,src -#define PFRSQIT1(dst,src) pfrsqit1 dst,src -#define PFSUB(dst,src) pfsub dst,src -#define PFSUBR(dst,src) pfsubr dst,src -#define PI2FD(dst,src) pi2fd dst,src -#define PMULHRW(dst,src) pmulhrw dst,src -#define PREFETCH(src) prefetch src -#define PREFETCHW(src) prefetchw src - -#define PAVGUSBM(dst,src,off) pavgusb dst,[src+off] -#define PF2IDM(dst,src,off) PF2ID dst,[src+off] -#define PFACCM(dst,src,off) PFACC dst,[src+off] -#define PFADDM(dst,src,off) PFADD dst,[src+off] -#define PFCMPEQM(dst,src,off) PFCMPEQ dst,[src+off] -#define PFCMPGEM(dst,src,off) PFCMPGE dst,[src+off] -#define PFCMPGTM(dst,src,off) PFCMPGT dst,[src+off] -#define PFMAXM(dst,src,off) PFMAX dst,[src+off] -#define PFMINM(dst,src,off) PFMIN dst,[src+off] -#define PFMULM(dst,src,off) PFMUL dst,[src+off] -#define PFRCPM(dst,src,off) PFRCP dst,[src+off] -#define PFRCPIT1M(dst,src,off) PFRCPIT1 dst,[src+off] -#define PFRCPIT2M(dst,src,off) PFRCPIT2 dst,[src+off] -#define PFRSQRTM(dst,src,off) PFRSQRT dst,[src+off] -#define PFRSQIT1M(dst,src,off) PFRSQIT1 dst,[src+off] -#define PFSUBM(dst,src,off) PFSUB dst,[src+off] -#define PFSUBRM(dst,src,off) PFSUBR dst,[src+off] -#define PI2FDM(dst,src,off) PI2FD dst,[src+off] -#define PMULHRWM(dst,src,off) PMULHRW dst,[src+off] - - -#if defined (__MWERKS__) -// At the moment, CodeWarrior does not support these opcodes, so hand-assemble them - -// Defines for operands. -#define _K3D_MM0 0xc0 -#define _K3D_MM1 0xc1 -#define _K3D_MM2 0xc2 -#define _K3D_MM3 0xc3 -#define _K3D_MM4 0xc4 -#define _K3D_MM5 0xc5 -#define _K3D_MM6 0xc6 -#define _K3D_MM7 0xc7 -#define _K3D_mm0 0xc0 -#define _K3D_mm1 0xc1 -#define _K3D_mm2 0xc2 -#define _K3D_mm3 0xc3 -#define _K3D_mm4 0xc4 -#define _K3D_mm5 0xc5 -#define _K3D_mm6 0xc6 -#define _K3D_mm7 0xc7 -#define _K3D_EAX 0x00 -#define _K3D_ECX 0x01 -#define _K3D_EDX 0x02 -#define _K3D_EBX 0x03 -#define _K3D_ESI 0x06 -#define _K3D_EDI 0x07 -#define _K3D_eax 0x00 -#define _K3D_ecx 0x01 -#define _K3D_edx 0x02 -#define _K3D_ebx 0x03 -#define _K3D_esi 0x06 -#define _K3D_edi 0x07 -#define _K3D_EAX 0x00 -#define _K3D_ECX 0x01 -#define _K3D_EDX 0x02 -#define _K3D_EBX 0x03 -#define _K3D_ESI 0x06 -#define _K3D_EDI 0x07 -#define _K3D_eax 0x00 -#define _K3D_ecx 0x01 -#define _K3D_edx 0x02 -#define _K3D_ebx 0x03 -#define _K3D_esi 0x06 -#define _K3D_edi 0x07 - -#define InjK3DOps(dst,src,inst) \ - db 0x0f, 0x0f, (((_K3D_##dst & 0x3f) << 3) | _K3D_##src), _3DNowOpcode##inst - -#define InjK3DMOps(dst,src,off,inst) \ - db 0x0f, 0x0f, (((_K3D_##dst & 0x3f) << 3) | _K3D_##src | 0x40), off, _3DNowOpcode##inst - -#define InjMMXOps(dst,src,inst) \ - db 0x0f, _3DNowOpcode##inst, (((_K3D_##dst & 0x3f) << 3) | _K3D_##src) - -#define InjMMXMOps(dst,src,off,inst) \ - db 0x0f, _3DNowOpcode##inst, (((_K3D_##dst & 0x3f) << 3) | _K3D_##src | 0x40), off - -#define PFNACC(dst,src) InjK3DOps(dst,src,PFNACC) -#define PFPNACC(dst,src) InjK3DOps(dst,src,PFPNACC) -#define PSWAPD(dst,src) InjK3DOps(dst,src,PSWAPD) -#define PMINUB(dst,src) InjMMXOps(dst,src,PMINUB) -#define PMAXUB(dst,src) InjMMXOps(dst,src,PMAXUB) -#define PMINSW(dst,src) InjMMXOps(dst,src,PMINSW) -#define PMAXSW(dst,src) InjMMXOps(dst,src,PMAXSW) -#define PMULHUW(dst,src) InjMMXOps(dst,src,PMULHUW) -#define PAVGB(dst,src) InjMMXOps(dst,src,PAVGB) -#define PAVGW(dst,src) InjMMXOps(dst,src,PAVGW) -#define PSADBW(dst,src) InjMMXOps(dst,src,PSADBW) -#define PMOVMSKB(dst,src) InjMMXOps(dst,src,PMOVMSKB) -#define PMASKMOVQ(dst,src) InjMMXOps(dst,src,PMASKMOVQ) -#define PINSRW(dst,src,msk) InjMMXOps(dst,src,PINSRW) db msk -#define PEXTRW(dst,src,msk) InjMMXOps(dst,src,PEXTRW) db msk -#define PSHUFW(dst,src,msk) InjMMXOps(dst,src,PSHUFW) db msk -#define MOVNTQ(dst,src) InjMMXOps(src,dst,MOVNTQ) -#define PREFETCHNTA(mem) InjMMXOps(mm0,mem,PREFETCHT) -#define PREFETCHT0(mem) InjMMXOps(mm1,mem,PREFETCHT) -#define PREFETCHT1(mem) InjMMXOps(mm2,mem,PREFETCHT) -#define PREFETCHT2(mem) InjMMXOps(mm3,mem,PREFETCHT) - - -/* Memory/offset versions of the K7 opcodes */ -#define PFNACCM(dst,src,off) InjK3DMOps(dst,src,off,PFNACC) -#define PFPNACCM(dst,src,off) InjK3DMOps(dst,src,off,PFPNACC) -#define PSWAPDM(dst,src,off) InjK3DMOps(dst,src,off,PSWAPD) -#define PMINUBM(dst,src,off) InjMMXMOps(dst,src,off,PMINUB) -#define PMAXUBM(dst,src,off) InjMMXMOps(dst,src,off,PMAXUB) -#define PMINSWM(dst,src,off) InjMMXMOps(dst,src,off,PMINSW) -#define PMAXSWM(dst,src,off) InjMMXMOps(dst,src,off,PMAXSW) -#define PMULHUWM(dst,src,off) InjMMXMOps(dst,src,off,PMULHUW) -#define PAVGBM(dst,src,off) InjMMXMOps(dst,src,off,PAVGB) -#define PAVGWM(dst,src,off) InjMMXMOps(dst,src,off,PAVGW) -#define PSADBWM(dst,src,off) InjMMXMOps(dst,src,off,PSADBW) -#define PMOVMSKBM(dst,src,off) InjMMXMOps(dst,src,off,PMOVMSKB) -#define PMASKMOVQM(dst,src,off) InjMMXMOps(dst,src,off,PMASKMOVQ) -#define PINSRWM(dst,src,off,msk) InjMMXMOps(dst,src,off,PINSRW), msk -#define PEXTRWM(dst,src,off,msk) InjMMXMOps(dst,src,off,PEXTRW), msk -#define PSHUFWM(dst,src,off,msk) InjMMXMOps(dst,src,off,PSHUFW), msk -#define MOVNTQM(dst,src,off) InjMMXMOps(src,dst,off,MOVNTQ) -#define PREFETCHNTAM(mem,off) InjMMXMOps(mm0,mem,off,PREFETCHT) -#define PREFETCHT0M(mem,off) InjMMXMOps(mm1,mem,off,PREFETCHT) -#define PREFETCHT1M(mem,off) InjMMXMOps(mm2,mem,off,PREFETCHT) -#define PREFETCHT2M(mem,off) InjMMXMOps(mm3,mem,off,PREFETCHT) - - -#else - -#define PFNACC(dst,src) PFNACC dst,src -#define PFPNACC(dst,src) PFPNACC dst,src -#define PSWAPD(dst,src) PSWAPD dst,src -#define PMINUB(dst,src) PMINUB dst,src -#define PMAXUB(dst,src) PMAXUB dst,src -#define PMINSW(dst,src) PMINSW dst,src -#define PMAXSW(dst,src) PMAXSW dst,src -#define PMULHUW(dst,src) PMULHUW dst,src -#define PAVGB(dst,src) PAVGB dst,src -#define PAVGW(dst,src) PAVGW dst,src -#define PSADBW(dst,src) PSADBW dst,src -#define PMOVMSKB(dst,src) PMOVMSKB dst,src -#define PMASKMOVQ(dst,src) PMASKMOVQ dst,src -#define PINSRW(dst,src,msk) PINSRW dst,src,msk -#define PEXTRW(dst,src,msk) PEXTRW dst,src,msk -#define PSHUFW(dst,src,msk) PSHUFW dst,src,msk -#define MOVNTQ(dst,src) MOVNTQ dst,src - -#define PFNACCM(dst,src,off) PFNACC dst,[src+off] -#define PFPNACCM(dst,src,off) PFPNACC dst,[src+off] -#define PSWAPDM(dst,src,off) PSWAPD dst,[src+off] -#define PMINUBM(dst,src,off) PMINUB dst,[src+off] -#define PMAXUBM(dst,src,off) PMAXUB dst,[src+off] -#define PMINSWM(dst,src,off) PMINSW dst,[src+off] -#define PMAXSWM(dst,src,off) PMAXSW dst,[src+off] -#define PMULHUWM(dst,src,off) PMULHUW dst,[src+off] -#define PAVGBM(dst,src,off) PAVGB dst,[src+off] -#define PAVGWM(dst,src,off) PAVGW dst,[src+off] -#define PSADBWM(dst,src,off) PSADBW dst,[src+off] -#define PMOVMSKBM(dst,src,off) PMOVMSKB dst,[src+off] -#define PMASKMOVQM(dst,src,off) PMASKMOVQ dst,[src+off] -#define PINSRWM(dst,src,off,msk) PINSRW dst,[src+off],msk -#define PEXTRWM(dst,src,off,msk) PEXTRW dst,[src+off],msk -#define PSHUFWM(dst,src,off,msk) PSHUFW dst,[src+off],msk -#define MOVNTQM(dst,src,off) MOVNTQ dst,[src+off] - -#endif - -#endif - -/* Just to deal with lower case. */ -#define pf2id(dst,src) PF2ID(dst,src) -#define pfacc(dst,src) PFACC(dst,src) -#define pfadd(dst,src) PFADD(dst,src) -#define pfcmpeq(dst,src) PFCMPEQ(dst,src) -#define pfcmpge(dst,src) PFCMPGE(dst,src) -#define pfcmpgt(dst,src) PFCMPGT(dst,src) -#define pfmax(dst,src) PFMAX(dst,src) -#define pfmin(dst,src) PFMIN(dst,src) -#define pfmul(dst,src) PFMUL(dst,src) -#define pfrcp(dst,src) PFRCP(dst,src) -#define pfrcpit1(dst,src) PFRCPIT1(dst,src) -#define pfrcpit2(dst,src) PFRCPIT2(dst,src) -#define pfrsqrt(dst,src) PFRSQRT(dst,src) -#define pfrsqit1(dst,src) PFRSQIT1(dst,src) -#define pfsub(dst,src) PFSUB(dst,src) -#define pfsubr(dst,src) PFSUBR(dst,src) -#define pi2fd(dst,src) PI2FD(dst,src) -#define femms FEMMS -#define pavgusb(dst,src) PAVGUSB(dst,src) -#define pmulhrw(dst,src) PMULHRW(dst,src) -#define prefetch(src) PREFETCH(src) -#define prefetchw(src) PREFETCHW(src) - -#define prefetchm(src,off) PREFETCHM(src,off) -#define prefetchmlong(src,off) PREFETCHMLONG(src,off) -#define prefetchwm(src,off) PREFETCHWM(src,off) -#define prefetchwmlong(src,off) PREFETCHWMLONG(src,off) - -#define pfnacc(dst,src) PFNACC(dst,src) -#define pfpnacc(dst,src) PFPNACC(dst,src) -#define pswapd(dst,src) PSWAPD(dst,src) -#define pminub(dst,src) PMINUB(dst,src) -#define pmaxub(dst,src) PMAXUB(dst,src) -#define pminsw(dst,src) PMINSW(dst,src) -#define pmaxsw(dst,src) PMAXSW(dst,src) -#define pmulhuw(dst,src) PMULHUW(dst,src) -#define pavgb(dst,src) PAVGB(dst,src) -#define pavgw(dst,src) PAVGW(dst,src) -#define psadbw(dst,src) PSADBW(dst,src) -#define pmovmskb(dst,src) PMOVMSKB(dst,src) -#define pmaskmovq(dst,src) PMASKMOVQ(dst,src) -#define pinsrw(dst,src,msk) PINSRW(dst,src,msk) -#define pextrw(dst,src,msk) PEXTRW(dst,src,msk) -#define pshufw(dst,src,msk) PSHUFW(dst,src,msk) -#define movntq(dst,src) MOVNTQ(dst,src) -#define prefetchnta(mem) PREFETCHNTA(mem) -#define prefetcht0(mem) PREFETCHT0(mem) -#define prefetcht1(mem) PREFETCHT1(mem) -#define prefetcht2(mem) PREFETCHT2(mem) - - -#define pavgusbm(dst,src,off) PAVGUSBM(dst,src,off) -#define pf2idm(dst,src,off) PF2IDM(dst,src,off) -#define pfaccm(dst,src,off) PFACCM(dst,src,off) -#define pfaddm(dst,src,off) PFADDM(dst,src,off) -#define pfcmpeqm(dst,src,off) PFCMPEQM(dst,src,off) -#define pfcmpgem(dst,src,off) PFCMPGEM(dst,src,off) -#define pfcmpgtm(dst,src,off) PFCMPGTM(dst,src,off) -#define pfmaxm(dst,src,off) PFMAXM(dst,src,off) -#define pfminm(dst,src,off) PFMINM(dst,src,off) -#define pfmulm(dst,src,off) PFMULM(dst,src,off) -#define pfrcpm(dst,src,off) PFRCPM(dst,src,off) -#define pfrcpit1m(dst,src,off) PFRCPIT1M(dst,src,off) -#define pfrcpit2m(dst,src,off) PFRCPIT2M(dst,src,off) -#define pfrsqrtm(dst,src,off) PFRSQRTM(dst,src,off) -#define pfrsqit1m(dst,src,off) PFRSQIT1M(dst,src,off) -#define pfsubm(dst,src,off) PFSUBM(dst,src,off) -#define pfsubrm(dst,src,off) PFSUBRM(dst,src,off) -#define pi2fdm(dst,src,off) PI2FDM(dst,src,off) -#define pmulhrwm(dst,src,off) PMULHRWM(dst,src,off) -#define cpuid CPUID -#define sfence SFENCE - -#define pfnaccm(dst,src,off) PFNACCM(dst,src,off) -#define pfpnaccm(dst,src,off) PFPNACCM(dst,src,off) -#define pswapdm(dst,src,off) PSWAPDM(dst,src,off) -#define pminubm(dst,src,off) PMINUBM(dst,src,off) -#define pmaxubm(dst,src,off) PMAXUBM(dst,src,off) -#define pminswm(dst,src,off) PMINSWM(dst,src,off) -#define pmaxswm(dst,src,off) PMAXSWM(dst,src,off) -#define pmulhuwm(dst,src,off) PMULHUWM(dst,src,off) -#define pavgbm(dst,src,off) PAVGBM(dst,src,off) -#define pavgwm(dst,src,off) PAVGWM(dst,src,off) -#define psadbwm(dst,src,off) PSADBWM(dst,src,off) -#define pmovmskbm(dst,src,off) PMOVMSKBM(dst,src,off) -#define pmaskmovqm(dst,src,off) PMASKMOVQM(dst,src,off) -#define pinsrwm(dst,src,off,msk) PINSRWM(dst,src,off,msk) -#define pextrwm(dst,src,off,msk) PEXTRWM(dst,src,off,msk) -#define pshufwm(dst,src,off,msk) PSHUFWM(dst,src,off,msk) -#define movntqm(dst,src,off) MOVNTQM(dst,src,off) -#define prefetchntam(mem,off) PREFETCHNTA(mem,off) -#define prefetcht0m(mem,off) PREFETCHT0(mem,off) -#define prefetcht1m(mem,off) PREFETCHT1(mem,off) -#define prefetcht2m(mem,off) PREFETCHT2(mem,off) - -#endif diff --git a/public/mathlib/anorms.h b/public/mathlib/anorms.h deleted file mode 100644 index b27e5ceb1..000000000 --- a/public/mathlib/anorms.h +++ /dev/null @@ -1,25 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ANORMS_H -#define ANORMS_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "mathlib/vector.h" - - -#define NUMVERTEXNORMALS 162 - -// the angle between consecutive g_anorms[] vectors is ~14.55 degrees -#define VERTEXNORMAL_CONE_INNER_ANGLE DEG2RAD(7.275) - -extern Vector g_anorms[NUMVERTEXNORMALS]; - - -#endif // ANORMS_H diff --git a/public/mathlib/bumpvects.h b/public/mathlib/bumpvects.h deleted file mode 100644 index 6b859ad0d..000000000 --- a/public/mathlib/bumpvects.h +++ /dev/null @@ -1,37 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef BUMPVECTS_H -#define BUMPVECTS_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "mathlib/mathlib.h" - -#define OO_SQRT_2 0.70710676908493042f -#define OO_SQRT_3 0.57735025882720947f -#define OO_SQRT_6 0.40824821591377258f -// sqrt( 2 / 3 ) -#define OO_SQRT_2_OVER_3 0.81649661064147949f - -#define NUM_BUMP_VECTS 3 - -const TableVector g_localBumpBasis[NUM_BUMP_VECTS] = -{ - { OO_SQRT_2_OVER_3, 0.0f, OO_SQRT_3 }, - { -OO_SQRT_6, OO_SQRT_2, OO_SQRT_3 }, - { -OO_SQRT_6, -OO_SQRT_2, OO_SQRT_3 } -}; - -void GetBumpNormals( const Vector& sVect, const Vector& tVect, const Vector& flatNormal, - const Vector& phongNormal, Vector bumpNormals[NUM_BUMP_VECTS] ); - -#endif // BUMPVECTS_H diff --git a/public/mathlib/compressed_3d_unitvec.h b/public/mathlib/compressed_3d_unitvec.h deleted file mode 100644 index 4adcc1fdc..000000000 --- a/public/mathlib/compressed_3d_unitvec.h +++ /dev/null @@ -1,284 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef _3D_UNITVEC_H -#define _3D_UNITVEC_H - - -#define UNITVEC_DECLARE_STATICS \ - float cUnitVector::mUVAdjustment[0x2000]; \ - Vector cUnitVector::mTmpVec; - -// upper 3 bits -#define SIGN_MASK 0xe000 -#define XSIGN_MASK 0x8000 -#define YSIGN_MASK 0x4000 -#define ZSIGN_MASK 0x2000 - -// middle 6 bits - xbits -#define TOP_MASK 0x1f80 - -// lower 7 bits - ybits -#define BOTTOM_MASK 0x007f - -// unitcomp.cpp : A Unit Vector to 16-bit word conversion -// algorithm based on work of Rafael Baptista (rafael@oroboro.com) -// Accuracy improved by O.D. (punkfloyd@rocketmail.com) -// Used with Permission. - -// a compressed unit vector. reasonable fidelty for unit -// vectors in a 16 bit package. Good enough for surface normals -// we hope. -class cUnitVector // : public c3dMathObject -{ -public: - cUnitVector() { mVec = 0; } - cUnitVector( const Vector& vec ) - { - packVector( vec ); - } - cUnitVector( unsigned short val ) { mVec = val; } - - cUnitVector& operator=( const Vector& vec ) - { packVector( vec ); return *this; } - - operator Vector() - { - unpackVector( mTmpVec ); - return mTmpVec; - } - - void packVector( const Vector& vec ) - { - // convert from Vector to cUnitVector - - Assert( vec.IsValid()); - Vector tmp = vec; - - // input vector does not have to be unit length - // Assert( tmp.length() <= 1.001f ); - - mVec = 0; - if ( tmp.x < 0 ) { mVec |= XSIGN_MASK; tmp.x = -tmp.x; } - if ( tmp.y < 0 ) { mVec |= YSIGN_MASK; tmp.y = -tmp.y; } - if ( tmp.z < 0 ) { mVec |= ZSIGN_MASK; tmp.z = -tmp.z; } - - // project the normal onto the plane that goes through - // X0=(1,0,0),Y0=(0,1,0),Z0=(0,0,1). - // on that plane we choose an (projective!) coordinate system - // such that X0->(0,0), Y0->(126,0), Z0->(0,126),(0,0,0)->Infinity - - // a little slower... old pack was 4 multiplies and 2 adds. - // This is 2 multiplies, 2 adds, and a divide.... - float w = 126.0f / ( tmp.x + tmp.y + tmp.z ); - long xbits = (long)( tmp.x * w ); - long ybits = (long)( tmp.y * w ); - - Assert( xbits < 127 ); - Assert( xbits >= 0 ); - Assert( ybits < 127 ); - Assert( ybits >= 0 ); - - // Now we can be sure that 0<=xp<=126, 0<=yp<=126, 0<=xp+yp<=126 - // however for the sampling we want to transform this triangle - // into a rectangle. - if ( xbits >= 64 ) - { - xbits = 127 - xbits; - ybits = 127 - ybits; - } - - // now we that have xp in the range (0,127) and yp in - // the range (0,63), we can pack all the bits together - mVec |= ( xbits << 7 ); - mVec |= ybits; - } - - void unpackVector( Vector& vec ) - { - // if we do a straightforward backward transform - // we will get points on the plane X0,Y0,Z0 - // however we need points on a sphere that goes through - // these points. Therefore we need to adjust x,y,z so - // that x^2+y^2+z^2=1 by normalizing the vector. We have - // already precalculated the amount by which we need to - // scale, so all we do is a table lookup and a - // multiplication - - // get the x and y bits - long xbits = (( mVec & TOP_MASK ) >> 7 ); - long ybits = ( mVec & BOTTOM_MASK ); - - // map the numbers back to the triangle (0,0)-(0,126)-(126,0) - if (( xbits + ybits ) >= 127 ) - { - xbits = 127 - xbits; - ybits = 127 - ybits; - } - - // do the inverse transform and normalization - // costs 3 extra multiplies and 2 subtracts. No big deal. - float uvadj = mUVAdjustment[mVec & ~SIGN_MASK]; - vec.x = uvadj * (float) xbits; - vec.y = uvadj * (float) ybits; - vec.z = uvadj * (float)( 126 - xbits - ybits ); - - // set all the sign bits - if ( mVec & XSIGN_MASK ) vec.x = -vec.x; - if ( mVec & YSIGN_MASK ) vec.y = -vec.y; - if ( mVec & ZSIGN_MASK ) vec.z = -vec.z; - - Assert( vec.IsValid()); - } - - static void initializeStatics() - { - for ( int idx = 0; idx < 0x2000; idx++ ) - { - long xbits = idx >> 7; - long ybits = idx & BOTTOM_MASK; - - // map the numbers back to the triangle (0,0)-(0,127)-(127,0) - if (( xbits + ybits ) >= 127 ) - { - xbits = 127 - xbits; - ybits = 127 - ybits; - } - - // convert to 3D vectors - float x = (float)xbits; - float y = (float)ybits; - float z = (float)( 126 - xbits - ybits ); - - // calculate the amount of normalization required - mUVAdjustment[idx] = 1.0f / sqrtf( y*y + z*z + x*x ); - Assert( _finite( mUVAdjustment[idx])); - - //cerr << mUVAdjustment[idx] << "\t"; - //if ( xbits == 0 ) cerr << "\n"; - } - } - -#if 0 - void test() - { - #define TEST_RANGE 4 - #define TEST_RANDOM 100 - #define TEST_ANGERROR 1.0 - - float maxError = 0; - float avgError = 0; - int numVecs = 0; - - {for ( int x = -TEST_RANGE; x < TEST_RANGE; x++ ) - { - for ( int y = -TEST_RANGE; y < TEST_RANGE; y++ ) - { - for ( int z = -TEST_RANGE; z < TEST_RANGE; z++ ) - { - if (( x + y + z ) == 0 ) continue; - - Vector vec( (float)x, (float)y, (float)z ); - Vector vec2; - - vec.normalize(); - packVector( vec ); - unpackVector( vec2 ); - - float ang = vec.dot( vec2 ); - ang = (( fabs( ang ) > 0.99999f ) ? 0 : (float)acos(ang)); - - if (( ang > TEST_ANGERROR ) | ( !_finite( ang ))) - { - cerr << "error: " << ang << endl; - cerr << "orig vec: " << vec.x << ",\t" - << vec.y << ",\t" << vec.z << "\tmVec: " - << mVec << endl; - cerr << "quantized vec2: " << vec2.x - << ",\t" << vec2.y << ",\t" - << vec2.z << endl << endl; - } - avgError += ang; - numVecs++; - if ( maxError < ang ) maxError = ang; - } - } - }} - - for ( int w = 0; w < TEST_RANDOM; w++ ) - { - Vector vec( genRandom(), genRandom(), genRandom()); - Vector vec2; - vec.normalize(); - - packVector( vec ); - unpackVector( vec2 ); - - float ang =vec.dot( vec2 ); - ang = (( ang > 0.999f ) ? 0 : (float)acos(ang)); - - if (( ang > TEST_ANGERROR ) | ( !_finite( ang ))) - { - cerr << "error: " << ang << endl; - cerr << "orig vec: " << vec.x << ",\t" - << vec.y << ",\t" << vec.z << "\tmVec: " - << mVec << endl; - cerr << "quantized vec2: " << vec2.x << ",\t" - << vec2.y << ",\t" - << vec2.z << endl << endl; - } - avgError += ang; - numVecs++; - if ( maxError < ang ) maxError = ang; - } - - { for ( int x = 0; x < 50; x++ ) - { - Vector vec( (float)x, 25.0f, 0.0f ); - Vector vec2; - - vec.normalize(); - packVector( vec ); - unpackVector( vec2 ); - - float ang = vec.dot( vec2 ); - ang = (( fabs( ang ) > 0.999f ) ? 0 : (float)acos(ang)); - - if (( ang > TEST_ANGERROR ) | ( !_finite( ang ))) - { - cerr << "error: " << ang << endl; - cerr << "orig vec: " << vec.x << ",\t" - << vec.y << ",\t" << vec.z << "\tmVec: " - << mVec << endl; - cerr << " quantized vec2: " << vec2.x << ",\t" - << vec2.y << ",\t" << vec2.z << endl << endl; - } - - avgError += ang; - numVecs++; - if ( maxError < ang ) maxError = ang; - }} - - cerr << "max angle error: " << maxError - << ", average error: " << avgError / numVecs - << ", num tested vecs: " << numVecs << endl; - } - - friend ostream& operator<< ( ostream& os, const cUnitVector& vec ) - { os << vec.mVec; return os; } -#endif - -//protected: // !!!! - - unsigned short mVec; - static float mUVAdjustment[0x2000]; - static Vector mTmpVec; -}; - -#endif // _3D_VECTOR_H - - diff --git a/public/mathlib/compressed_light_cube.h b/public/mathlib/compressed_light_cube.h deleted file mode 100644 index 0b26bdfb8..000000000 --- a/public/mathlib/compressed_light_cube.h +++ /dev/null @@ -1,24 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef COMPRESSED_LIGHT_CUBE_H -#define COMPRESSED_LIGHT_CUBE_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "mathlib/mathlib.h" - - -struct CompressedLightCube -{ - DECLARE_BYTESWAP_DATADESC(); - ColorRGBExp32 m_Color[6]; -}; - - -#endif // COMPRESSED_LIGHT_CUBE_H diff --git a/public/mathlib/compressed_vector.h b/public/mathlib/compressed_vector.h deleted file mode 100644 index 6b2f6f853..000000000 --- a/public/mathlib/compressed_vector.h +++ /dev/null @@ -1,608 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef COMPRESSED_VECTOR_H -#define COMPRESSED_VECTOR_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -// For vec_t, put this somewhere else? -#include "basetypes.h" - -// For rand(). We really need a library! -#include - -#include "tier0/dbg.h" -#include "mathlib/vector.h" - -#include "mathlib/mathlib.h" - -#if defined( _X360 ) -#pragma bitfield_order( push, lsb_to_msb ) -#endif -//========================================================= -// fit a 3D vector into 32 bits -//========================================================= - -class Vector32 -{ -public: - // Construction/destruction: - Vector32(void); - Vector32(vec_t X, vec_t Y, vec_t Z); - - // assignment - Vector32& operator=(const Vector &vOther); - operator Vector (); - -private: - unsigned short x:10; - unsigned short y:10; - unsigned short z:10; - unsigned short exp:2; -}; - -inline Vector32& Vector32::operator=(const Vector &vOther) -{ - CHECK_VALID(vOther); - - static float expScale[4] = { 4.0f, 16.0f, 32.f, 64.f }; - - float fmax = MAX( fabs( vOther.x ), fabs( vOther.y ) ); - fmax = fpmax( fmax, fabs( vOther.z ) ); - - for (exp = 0; exp < 3; exp++) - { - if (fmax < expScale[exp]) - break; - } - Assert( fmax < expScale[exp] ); - - float fexp = 512.0f / expScale[exp]; - - x = clamp( (int)(vOther.x * fexp) + 512, 0, 1023 ); - y = clamp( (int)(vOther.y * fexp) + 512, 0, 1023 ); - z = clamp( (int)(vOther.z * fexp) + 512, 0, 1023 ); - return *this; -} - - -inline Vector32::operator Vector () -{ - Vector tmp; - - static float expScale[4] = { 4.0f, 16.0f, 32.f, 64.f }; - - float fexp = expScale[exp] / 512.0f; - - tmp.x = (((int)x) - 512) * fexp; - tmp.y = (((int)y) - 512) * fexp; - tmp.z = (((int)z) - 512) * fexp; - return tmp; -} - - -//========================================================= -// Fit a unit vector into 32 bits -//========================================================= - -class Normal32 -{ -public: - // Construction/destruction: - Normal32(void); - Normal32(vec_t X, vec_t Y, vec_t Z); - - // assignment - Normal32& operator=(const Vector &vOther); - operator Vector (); - -private: - unsigned short x:15; - unsigned short y:15; - unsigned short zneg:1; -}; - - -inline Normal32& Normal32::operator=(const Vector &vOther) -{ - CHECK_VALID(vOther); - - x = clamp( (int)(vOther.x * 16384) + 16384, 0, 32767 ); - y = clamp( (int)(vOther.y * 16384) + 16384, 0, 32767 ); - zneg = (vOther.z < 0); - //x = vOther.x; - //y = vOther.y; - //z = vOther.z; - return *this; -} - - -inline Normal32::operator Vector () -{ - Vector tmp; - - tmp.x = ((int)x - 16384) * (1 / 16384.0); - tmp.y = ((int)y - 16384) * (1 / 16384.0); - tmp.z = sqrt( 1 - tmp.x * tmp.x - tmp.y * tmp.y ); - if (zneg) - tmp.z = -tmp.z; - return tmp; -} - - -//========================================================= -// 64 bit Quaternion -//========================================================= - -class Quaternion64 -{ -public: - // Construction/destruction: - Quaternion64(void); - Quaternion64(vec_t X, vec_t Y, vec_t Z); - - // assignment - // Quaternion& operator=(const Quaternion64 &vOther); - Quaternion64& operator=(const Quaternion &vOther); - operator Quaternion (); -private: - uint64 x:21; - uint64 y:21; - uint64 z:21; - uint64 wneg:1; -}; - - -inline Quaternion64::operator Quaternion () -{ - Quaternion tmp; - - // shift to -1048576, + 1048575, then round down slightly to -1.0 < x < 1.0 - tmp.x = ((int)x - 1048576) * (1 / 1048576.5f); - tmp.y = ((int)y - 1048576) * (1 / 1048576.5f); - tmp.z = ((int)z - 1048576) * (1 / 1048576.5f); - tmp.w = sqrt( 1 - tmp.x * tmp.x - tmp.y * tmp.y - tmp.z * tmp.z ); - if (wneg) - tmp.w = -tmp.w; - return tmp; -} - -inline Quaternion64& Quaternion64::operator=(const Quaternion &vOther) -{ - CHECK_VALID(vOther); - - x = clamp( (int)(vOther.x * 1048576) + 1048576, 0, 2097151 ); - y = clamp( (int)(vOther.y * 1048576) + 1048576, 0, 2097151 ); - z = clamp( (int)(vOther.z * 1048576) + 1048576, 0, 2097151 ); - wneg = (vOther.w < 0); - return *this; -} - -//========================================================= -// 48 bit Quaternion -//========================================================= - -class Quaternion48 -{ -public: - // Construction/destruction: - Quaternion48(void); - Quaternion48(vec_t X, vec_t Y, vec_t Z); - - // assignment - // Quaternion& operator=(const Quaternion48 &vOther); - Quaternion48& operator=(const Quaternion &vOther); - operator Quaternion (); -private: - unsigned short x:16; - unsigned short y:16; - unsigned short z:15; - unsigned short wneg:1; -}; - - -inline Quaternion48::operator Quaternion () -{ - Quaternion tmp; - - tmp.x = ((int)x - 32768) * (1 / 32768.0); - tmp.y = ((int)y - 32768) * (1 / 32768.0); - tmp.z = ((int)z - 16384) * (1 / 16384.0); - tmp.w = sqrt( 1 - tmp.x * tmp.x - tmp.y * tmp.y - tmp.z * tmp.z ); - if (wneg) - tmp.w = -tmp.w; - return tmp; -} - -inline Quaternion48& Quaternion48::operator=(const Quaternion &vOther) -{ - CHECK_VALID(vOther); - - x = clamp( (int)(vOther.x * 32768) + 32768, 0, 65535 ); - y = clamp( (int)(vOther.y * 32768) + 32768, 0, 65535 ); - z = clamp( (int)(vOther.z * 16384) + 16384, 0, 32767 ); - wneg = (vOther.w < 0); - return *this; -} - -//========================================================= -// 32 bit Quaternion -//========================================================= - -class Quaternion32 -{ -public: - // Construction/destruction: - Quaternion32(void); - Quaternion32(vec_t X, vec_t Y, vec_t Z); - - // assignment - // Quaternion& operator=(const Quaternion48 &vOther); - Quaternion32& operator=(const Quaternion &vOther); - operator Quaternion (); -private: - unsigned int x:11; - unsigned int y:10; - unsigned int z:10; - unsigned int wneg:1; -}; - - -inline Quaternion32::operator Quaternion () -{ - Quaternion tmp; - - tmp.x = ((int)x - 1024) * (1 / 1024.0); - tmp.y = ((int)y - 512) * (1 / 512.0); - tmp.z = ((int)z - 512) * (1 / 512.0); - tmp.w = sqrt( 1 - tmp.x * tmp.x - tmp.y * tmp.y - tmp.z * tmp.z ); - if (wneg) - tmp.w = -tmp.w; - return tmp; -} - -inline Quaternion32& Quaternion32::operator=(const Quaternion &vOther) -{ - CHECK_VALID(vOther); - - x = clamp( (int)(vOther.x * 1024) + 1024, 0, 2047 ); - y = clamp( (int)(vOther.y * 512) + 512, 0, 1023 ); - z = clamp( (int)(vOther.z * 512) + 512, 0, 1023 ); - wneg = (vOther.w < 0); - return *this; -} - -//========================================================= -// 16 bit float -//========================================================= - - -const int float32bias = 127; -const int float16bias = 15; - -const float maxfloat16bits = 65504.0f; - -class float16 -{ -public: - //float16() {} - //float16( float f ) { m_storage.rawWord = ConvertFloatTo16bits(f); } - - void Init() { m_storage.rawWord = 0; } -// float16& operator=(const float16 &other) { m_storage.rawWord = other.m_storage.rawWord; return *this; } -// float16& operator=(const float &other) { m_storage.rawWord = ConvertFloatTo16bits(other); return *this; } -// operator unsigned short () { return m_storage.rawWord; } -// operator float () { return Convert16bitFloatTo32bits( m_storage.rawWord ); } - unsigned short GetBits() const - { - return m_storage.rawWord; - } - float GetFloat() const - { - return Convert16bitFloatTo32bits( m_storage.rawWord ); - } - void SetFloat( float in ) - { - m_storage.rawWord = ConvertFloatTo16bits( in ); - } - - bool IsInfinity() const - { - return m_storage.bits.biased_exponent == 31 && m_storage.bits.mantissa == 0; - } - bool IsNaN() const - { - return m_storage.bits.biased_exponent == 31 && m_storage.bits.mantissa != 0; - } - - bool operator==(const float16 other) const { return m_storage.rawWord == other.m_storage.rawWord; } - bool operator!=(const float16 other) const { return m_storage.rawWord != other.m_storage.rawWord; } - -// bool operator< (const float other) const { return GetFloat() < other; } -// bool operator> (const float other) const { return GetFloat() > other; } - -protected: - union float32bits - { - float rawFloat; - struct - { - unsigned int mantissa : 23; - unsigned int biased_exponent : 8; - unsigned int sign : 1; - } bits; - }; - - union float16bits - { - unsigned short rawWord; - struct - { - unsigned short mantissa : 10; - unsigned short biased_exponent : 5; - unsigned short sign : 1; - } bits; - }; - - static bool IsNaN( float16bits in ) - { - return in.bits.biased_exponent == 31 && in.bits.mantissa != 0; - } - static bool IsInfinity( float16bits in ) - { - return in.bits.biased_exponent == 31 && in.bits.mantissa == 0; - } - - // 0x0001 - 0x03ff - static unsigned short ConvertFloatTo16bits( float input ) - { - if ( input > maxfloat16bits ) - input = maxfloat16bits; - else if ( input < -maxfloat16bits ) - input = -maxfloat16bits; - - float16bits output; - float32bits inFloat; - - inFloat.rawFloat = input; - - output.bits.sign = inFloat.bits.sign; - - if ( (inFloat.bits.biased_exponent==0) && (inFloat.bits.mantissa==0) ) - { - // zero - output.bits.mantissa = 0; - output.bits.biased_exponent = 0; - } - else if ( (inFloat.bits.biased_exponent==0) && (inFloat.bits.mantissa!=0) ) - { - // denorm -- denorm float maps to 0 half - output.bits.mantissa = 0; - output.bits.biased_exponent = 0; - } - else if ( (inFloat.bits.biased_exponent==0xff) && (inFloat.bits.mantissa==0) ) - { -#if 0 - // infinity - output.bits.mantissa = 0; - output.bits.biased_exponent = 31; -#else - // infinity maps to maxfloat - output.bits.mantissa = 0x3ff; - output.bits.biased_exponent = 0x1e; -#endif - } - else if ( (inFloat.bits.biased_exponent==0xff) && (inFloat.bits.mantissa!=0) ) - { -#if 0 - // NaN - output.bits.mantissa = 1; - output.bits.biased_exponent = 31; -#else - // NaN maps to zero - output.bits.mantissa = 0; - output.bits.biased_exponent = 0; -#endif - } - else - { - // regular number - int new_exp = inFloat.bits.biased_exponent-127; - - if (new_exp<-24) - { - // this maps to 0 - output.bits.mantissa = 0; - output.bits.biased_exponent = 0; - } - - if (new_exp<-14) - { - // this maps to a denorm - output.bits.biased_exponent = 0; - unsigned int exp_val = ( unsigned int )( -14 - ( inFloat.bits.biased_exponent - float32bias ) ); - if( exp_val > 0 && exp_val < 11 ) - { - output.bits.mantissa = ( 1 << ( 10 - exp_val ) ) + ( inFloat.bits.mantissa >> ( 13 + exp_val ) ); - } - } - else if (new_exp>15) - { -#if 0 - // map this value to infinity - output.bits.mantissa = 0; - output.bits.biased_exponent = 31; -#else - // to big. . . maps to maxfloat - output.bits.mantissa = 0x3ff; - output.bits.biased_exponent = 0x1e; -#endif - } - else - { - output.bits.biased_exponent = new_exp+15; - output.bits.mantissa = (inFloat.bits.mantissa >> 13); - } - } - return output.rawWord; - } - - static float Convert16bitFloatTo32bits( unsigned short input ) - { - float32bits output; - const float16bits &inFloat = *((float16bits *)&input); - - if( IsInfinity( inFloat ) ) - { - return maxfloat16bits * ( ( inFloat.bits.sign == 1 ) ? -1.0f : 1.0f ); - } - if( IsNaN( inFloat ) ) - { - return 0.0; - } - if( inFloat.bits.biased_exponent == 0 && inFloat.bits.mantissa != 0 ) - { - // denorm - const float half_denorm = (1.0f/16384.0f); // 2^-14 - float mantissa = ((float)(inFloat.bits.mantissa)) / 1024.0f; - float sgn = (inFloat.bits.sign)? -1.0f :1.0f; - output.rawFloat = sgn*mantissa*half_denorm; - } - else - { - // regular number - unsigned mantissa = inFloat.bits.mantissa; - unsigned biased_exponent = inFloat.bits.biased_exponent; - unsigned sign = ((unsigned)inFloat.bits.sign) << 31; - biased_exponent = ( (biased_exponent - float16bias + float32bias) * (biased_exponent != 0) ) << 23; - mantissa <<= (23-10); - - *((unsigned *)&output) = ( mantissa | biased_exponent | sign ); - } - - return output.rawFloat; - } - - - float16bits m_storage; -}; - -class float16_with_assign : public float16 -{ -public: - float16_with_assign() {} - float16_with_assign( float f ) { m_storage.rawWord = ConvertFloatTo16bits(f); } - - float16& operator=(const float16 &other) { m_storage.rawWord = ((float16_with_assign &)other).m_storage.rawWord; return *this; } - float16& operator=(const float &other) { m_storage.rawWord = ConvertFloatTo16bits(other); return *this; } -// operator unsigned short () const { return m_storage.rawWord; } - operator float () const { return Convert16bitFloatTo32bits( m_storage.rawWord ); } -}; - -//========================================================= -// Fit a 3D vector in 48 bits -//========================================================= - -class Vector48 -{ -public: - // Construction/destruction: - Vector48(void) {} - Vector48(vec_t X, vec_t Y, vec_t Z) { x.SetFloat( X ); y.SetFloat( Y ); z.SetFloat( Z ); } - - // assignment - Vector48& operator=(const Vector &vOther); - operator Vector (); - - const float operator[]( int i ) const { return (((float16 *)this)[i]).GetFloat(); } - - float16 x; - float16 y; - float16 z; -}; - -inline Vector48& Vector48::operator=(const Vector &vOther) -{ - CHECK_VALID(vOther); - - x.SetFloat( vOther.x ); - y.SetFloat( vOther.y ); - z.SetFloat( vOther.z ); - return *this; -} - - -inline Vector48::operator Vector () -{ - Vector tmp; - - tmp.x = x.GetFloat(); - tmp.y = y.GetFloat(); - tmp.z = z.GetFloat(); - - return tmp; -} - -//========================================================= -// Fit a 2D vector in 32 bits -//========================================================= - -class Vector2d32 -{ -public: - // Construction/destruction: - Vector2d32(void) {} - Vector2d32(vec_t X, vec_t Y) { x.SetFloat( X ); y.SetFloat( Y ); } - - // assignment - Vector2d32& operator=(const Vector &vOther); - Vector2d32& operator=(const Vector2D &vOther); - - operator Vector2D (); - - void Init( vec_t ix = 0.f, vec_t iy = 0.f); - - float16_with_assign x; - float16_with_assign y; -}; - -inline Vector2d32& Vector2d32::operator=(const Vector2D &vOther) -{ - x.SetFloat( vOther.x ); - y.SetFloat( vOther.y ); - return *this; -} - -inline Vector2d32::operator Vector2D () -{ - Vector2D tmp; - - tmp.x = x.GetFloat(); - tmp.y = y.GetFloat(); - - return tmp; -} - -inline void Vector2d32::Init( vec_t ix, vec_t iy ) -{ - x.SetFloat(ix); - y.SetFloat(iy); -} - -#if defined( _X360 ) -#pragma bitfield_order( pop ) -#endif - -#endif - diff --git a/public/mathlib/halton.h b/public/mathlib/halton.h deleted file mode 100644 index 2b75da1e3..000000000 --- a/public/mathlib/halton.h +++ /dev/null @@ -1,70 +0,0 @@ -// $Id$ - -// halton.h - classes, etc for generating numbers using the Halton pseudo-random sequence. See -// http://halton-sequences.wikiverse.org/. -// -// what this function is useful for is any sort of sampling/integration problem where -// you want to solve it by random sampling. Each call the NextValue() generates -// a random number between 0 and 1, in an unclumped manner, so that the space can be more -// or less evenly sampled with a minimum number of samples. -// -// It is NOT useful for generating random numbers dynamically, since the outputs aren't -// particularly random. -// -// To generate multidimensional sample values (points in a plane, etc), use two -// HaltonSequenceGenerator_t's, with different (primes) bases. - -#ifndef HALTON_H -#define HALTON_H - -#include -#include - -class HaltonSequenceGenerator_t -{ - int seed; - int base; - float fbase; //< base as a float - -public: - HaltonSequenceGenerator_t(int base); //< base MUST be prime, >=2 - - float GetElement(int element); - - inline float NextValue(void) - { - return GetElement(seed++); - } - -}; - - -class DirectionalSampler_t //< pseudo-random sphere sampling -{ - HaltonSequenceGenerator_t zdot; - HaltonSequenceGenerator_t vrot; -public: - DirectionalSampler_t(void) - : zdot(2),vrot(3) - { - } - - Vector NextValue(void) - { - float zvalue=zdot.NextValue(); - zvalue=2*zvalue-1.0; // map from 0..1 to -1..1 - float phi=acos(zvalue); - // now, generate a random rotation angle for x/y - float theta=2.0*M_PI*vrot.NextValue(); - float sin_p=sin(phi); - return Vector(cos(theta)*sin_p, - sin(theta)*sin_p, - zvalue); - - } -}; - - - - -#endif // halton_h diff --git a/public/mathlib/lightdesc.h b/public/mathlib/lightdesc.h deleted file mode 100644 index 91feec3f7..000000000 --- a/public/mathlib/lightdesc.h +++ /dev/null @@ -1,167 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -// light structure definitions. -#ifndef LIGHTDESC_H -#define LIGHTDESC_H - -#include -#include - -//----------------------------------------------------------------------------- -// Light structure -//----------------------------------------------------------------------------- - -enum LightType_t -{ - MATERIAL_LIGHT_DISABLE = 0, - MATERIAL_LIGHT_POINT, - MATERIAL_LIGHT_DIRECTIONAL, - MATERIAL_LIGHT_SPOT, -}; - -enum LightType_OptimizationFlags_t -{ - LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0 = 1, - LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION1 = 2, - LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION2 = 4, -}; - -struct LightDesc_t -{ - LightType_t m_Type; //< MATERIAL_LIGHT_xxx - Vector m_Color; //< color+intensity - Vector m_Position; //< light source center position - Vector m_Direction; //< for SPOT, direction it is pointing - float m_Range; //< distance range for light.0=infinite - float m_Falloff; //< angular falloff exponent for spot lights - float m_Attenuation0; //< constant distance falloff term - float m_Attenuation1; //< linear term of falloff - float m_Attenuation2; //< quadatic term of falloff - float m_Theta; //< inner cone angle. no angular falloff - //< within this cone - float m_Phi; //< outer cone angle - - // the values below are derived from the above settings for optimizations - // These aren't used by DX8. . used for software lighting. - float m_ThetaDot; - float m_PhiDot; - unsigned int m_Flags; -protected: - float OneOver_ThetaDot_Minus_PhiDot; - float m_RangeSquared; -public: - - void RecalculateDerivedValues(void); // calculate m_xxDot, m_Type for changed parms - - LightDesc_t(void) - { - } - - // constructors for various useful subtypes - - // a point light with infinite range - LightDesc_t( const Vector &pos, const Vector &color ) - { - InitPoint( pos, color ); - } - - /// a simple light. cone boundaries in radians. you pass a look_at point and the - /// direciton is derived from that. - LightDesc_t( const Vector &pos, const Vector &color, const Vector &point_at, - float inner_cone_boundary, float outer_cone_boundary ) - { - InitSpot( pos, color, point_at, inner_cone_boundary, outer_cone_boundary ); - } - - void InitPoint( const Vector &pos, const Vector &color ); - void InitDirectional( const Vector &dir, const Vector &color ); - void InitSpot(const Vector &pos, const Vector &color, const Vector &point_at, - float inner_cone_boundary, float outer_cone_boundary ); - - /// Given 4 points and 4 normals, ADD lighting from this light into "color". - void ComputeLightAtPoints( const FourVectors &pos, const FourVectors &normal, - FourVectors &color, bool DoHalfLambert=false ) const; - void ComputeNonincidenceLightAtPoints( const FourVectors &pos, FourVectors &color ) const; - void ComputeLightAtPointsForDirectional( const FourVectors &pos, - const FourVectors &normal, - FourVectors &color, bool DoHalfLambert=false ) const; - - // warning - modifies color!!! set color first!! - void SetupOldStyleAttenuation( float fQuadatricAttn, float fLinearAttn, float fConstantAttn ); - - void SetupNewStyleAttenuation( float fFiftyPercentDistance, float fZeroPercentDistance ); - - -/// given a direction relative to the light source position, is this ray within the - /// light cone (for spotlights..non spots consider all rays to be within their cone) - bool IsDirectionWithinLightCone(const Vector &rdir) const - { - return ((m_Type!=MATERIAL_LIGHT_SPOT) || (rdir.Dot(m_Direction)>=m_PhiDot)); - } -}; - - -//----------------------------------------------------------------------------- -// a point light with infinite range -//----------------------------------------------------------------------------- -inline void LightDesc_t::InitPoint( const Vector &pos, const Vector &color ) -{ - m_Type=MATERIAL_LIGHT_POINT; - m_Color=color; - m_Position=pos; - m_Range=0.0; // infinite - m_Attenuation0=1.0; - m_Attenuation1=0; - m_Attenuation2=0; - RecalculateDerivedValues(); -} - - -//----------------------------------------------------------------------------- -// a directional light with infinite range -//----------------------------------------------------------------------------- -inline void LightDesc_t::InitDirectional( const Vector &dir, const Vector &color ) -{ - m_Type=MATERIAL_LIGHT_DIRECTIONAL; - m_Color=color; - m_Direction=dir; - m_Range=0.0; // infinite - m_Attenuation0=1.0; - m_Attenuation1=0; - m_Attenuation2=0; - RecalculateDerivedValues(); -} - - -//----------------------------------------------------------------------------- -// a simple light. cone boundaries in radians. you pass a look_at point and the -// direciton is derived from that. -//----------------------------------------------------------------------------- -inline void LightDesc_t::InitSpot(const Vector &pos, const Vector &color, const Vector &point_at, - float inner_cone_boundary, float outer_cone_boundary) -{ - m_Type=MATERIAL_LIGHT_SPOT; - m_Color=color; - m_Position=pos; - m_Direction=point_at; - m_Direction-=pos; - VectorNormalizeFast(m_Direction); - m_Falloff=5.0; // linear angle falloff - m_Theta=inner_cone_boundary; - m_Phi=outer_cone_boundary; - - m_Range=0.0; // infinite - - m_Attenuation0=1.0; - m_Attenuation1=0; - m_Attenuation2=0; - RecalculateDerivedValues(); -} - - -#endif - diff --git a/public/mathlib/math_pfns.h b/public/mathlib/math_pfns.h deleted file mode 100644 index 817ddd8d1..000000000 --- a/public/mathlib/math_pfns.h +++ /dev/null @@ -1,72 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=====================================================================================// - -#ifndef _MATH_PFNS_H_ -#define _MATH_PFNS_H_ - -#if defined( _X360 ) -#include -#endif - -#if !defined( _X360 ) - -// These globals are initialized by mathlib and redirected based on available fpu features -extern float (*pfSqrt)(float x); -extern float (*pfRSqrt)(float x); -extern float (*pfRSqrtFast)(float x); -extern void (*pfFastSinCos)(float x, float *s, float *c); -extern float (*pfFastCos)(float x); - -// The following are not declared as macros because they are often used in limiting situations, -// and sometimes the compiler simply refuses to inline them for some reason -#define FastSqrt(x) (*pfSqrt)(x) -#define FastRSqrt(x) (*pfRSqrt)(x) -#define FastRSqrtFast(x) (*pfRSqrtFast)(x) -#define FastSinCos(x,s,c) (*pfFastSinCos)(x,s,c) -#define FastCos(x) (*pfFastCos)(x) - -#endif // !_X360 - -#if defined( _X360 ) - -FORCEINLINE float _VMX_Sqrt( float x ) -{ - return __fsqrts( x ); -} - -FORCEINLINE float _VMX_RSqrt( float x ) -{ - float rroot = __frsqrte( x ); - - // Single iteration NewtonRaphson on reciprocal square root estimate - return (0.5f * rroot) * (3.0f - (x * rroot) * rroot); -} - -FORCEINLINE float _VMX_RSqrtFast( float x ) -{ - return __frsqrte( x ); -} - -FORCEINLINE void _VMX_SinCos( float a, float *pS, float *pC ) -{ - XMScalarSinCos( pS, pC, a ); -} - -FORCEINLINE float _VMX_Cos( float a ) -{ - return XMScalarCos( a ); -} - -// the 360 has fixed hw and calls directly -#define FastSqrt(x) _VMX_Sqrt(x) -#define FastRSqrt(x) _VMX_RSqrt(x) -#define FastRSqrtFast(x) _VMX_RSqrtFast(x) -#define FastSinCos(x,s,c) _VMX_SinCos(x,s,c) -#define FastCos(x) _VMX_Cos(x) - -#endif // _X360 - -#endif // _MATH_PFNS_H_ diff --git a/public/mathlib/mathlib.h b/public/mathlib/mathlib.h deleted file mode 100644 index 27154229c..000000000 --- a/public/mathlib/mathlib.h +++ /dev/null @@ -1,2073 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#ifndef MATH_LIB_H -#define MATH_LIB_H - -#include -#include "tier0/basetypes.h" -#include "mathlib/vector.h" -#include "mathlib/vector2d.h" -#include "tier0/dbg.h" - -#include "mathlib/math_pfns.h" - -// plane_t structure -// !!! if this is changed, it must be changed in asm code too !!! -// FIXME: does the asm code even exist anymore? -// FIXME: this should move to a different file -struct cplane_t -{ - Vector normal; - float dist; - byte type; // for fast side tests - byte signbits; // signx + (signy<<1) + (signz<<1) - byte pad[2]; - -#ifdef VECTOR_NO_SLOW_OPERATIONS - cplane_t() {} - -private: - // No copy constructors allowed if we're in optimal mode - cplane_t(const cplane_t& vOther); -#endif -}; - -// structure offset for asm code -#define CPLANE_NORMAL_X 0 -#define CPLANE_NORMAL_Y 4 -#define CPLANE_NORMAL_Z 8 -#define CPLANE_DIST 12 -#define CPLANE_TYPE 16 -#define CPLANE_SIGNBITS 17 -#define CPLANE_PAD0 18 -#define CPLANE_PAD1 19 - -// 0-2 are axial planes -#define PLANE_X 0 -#define PLANE_Y 1 -#define PLANE_Z 2 - -// 3-5 are non-axial planes snapped to the nearest -#define PLANE_ANYX 3 -#define PLANE_ANYY 4 -#define PLANE_ANYZ 5 - - -//----------------------------------------------------------------------------- -// Frustum plane indices. -// WARNING: there is code that depends on these values -//----------------------------------------------------------------------------- - -enum -{ - FRUSTUM_RIGHT = 0, - FRUSTUM_LEFT = 1, - FRUSTUM_TOP = 2, - FRUSTUM_BOTTOM = 3, - FRUSTUM_NEARZ = 4, - FRUSTUM_FARZ = 5, - FRUSTUM_NUMPLANES = 6 -}; - -extern int SignbitsForPlane( cplane_t *out ); - -class Frustum_t -{ -public: - void SetPlane( int i, int nType, const Vector &vecNormal, float dist ) - { - m_Plane[i].normal = vecNormal; - m_Plane[i].dist = dist; - m_Plane[i].type = nType; - m_Plane[i].signbits = SignbitsForPlane( &m_Plane[i] ); - m_AbsNormal[i].Init( fabs(vecNormal.x), fabs(vecNormal.y), fabs(vecNormal.z) ); - } - - inline const cplane_t *GetPlane( int i ) const { return &m_Plane[i]; } - inline const Vector &GetAbsNormal( int i ) const { return m_AbsNormal[i]; } - -private: - cplane_t m_Plane[FRUSTUM_NUMPLANES]; - Vector m_AbsNormal[FRUSTUM_NUMPLANES]; -}; - -// Computes Y fov from an X fov and a screen aspect ratio + X from Y -float CalcFovY( float flFovX, float flScreenAspect ); -float CalcFovX( float flFovY, float flScreenAspect ); - -// Generate a frustum based on perspective view parameters -// NOTE: FOV is specified in degrees, as the *full* view angle (not half-angle) -void GeneratePerspectiveFrustum( const Vector& origin, const QAngle &angles, float flZNear, float flZFar, float flFovX, float flAspectRatio, Frustum_t &frustum ); -void GeneratePerspectiveFrustum( const Vector& origin, const Vector &forward, const Vector &right, const Vector &up, float flZNear, float flZFar, float flFovX, float flFovY, Frustum_t &frustum ); - -// Cull the world-space bounding box to the specified frustum. -bool R_CullBox( const Vector& mins, const Vector& maxs, const Frustum_t &frustum ); -bool R_CullBoxSkipNear( const Vector& mins, const Vector& maxs, const Frustum_t &frustum ); - -struct matrix3x4_t -{ - matrix3x4_t() {} - matrix3x4_t( - float m00, float m01, float m02, float m03, - float m10, float m11, float m12, float m13, - float m20, float m21, float m22, float m23 ) - { - m_flMatVal[0][0] = m00; m_flMatVal[0][1] = m01; m_flMatVal[0][2] = m02; m_flMatVal[0][3] = m03; - m_flMatVal[1][0] = m10; m_flMatVal[1][1] = m11; m_flMatVal[1][2] = m12; m_flMatVal[1][3] = m13; - m_flMatVal[2][0] = m20; m_flMatVal[2][1] = m21; m_flMatVal[2][2] = m22; m_flMatVal[2][3] = m23; - } - - //----------------------------------------------------------------------------- - // Creates a matrix where the X axis = forward - // the Y axis = left, and the Z axis = up - //----------------------------------------------------------------------------- - void Init( const Vector& xAxis, const Vector& yAxis, const Vector& zAxis, const Vector &vecOrigin ) - { - m_flMatVal[0][0] = xAxis.x; m_flMatVal[0][1] = yAxis.x; m_flMatVal[0][2] = zAxis.x; m_flMatVal[0][3] = vecOrigin.x; - m_flMatVal[1][0] = xAxis.y; m_flMatVal[1][1] = yAxis.y; m_flMatVal[1][2] = zAxis.y; m_flMatVal[1][3] = vecOrigin.y; - m_flMatVal[2][0] = xAxis.z; m_flMatVal[2][1] = yAxis.z; m_flMatVal[2][2] = zAxis.z; m_flMatVal[2][3] = vecOrigin.z; - } - - //----------------------------------------------------------------------------- - // Creates a matrix where the X axis = forward - // the Y axis = left, and the Z axis = up - //----------------------------------------------------------------------------- - matrix3x4_t( const Vector& xAxis, const Vector& yAxis, const Vector& zAxis, const Vector &vecOrigin ) - { - Init( xAxis, yAxis, zAxis, vecOrigin ); - } - - inline void Invalidate( void ) - { - for (int i = 0; i < 3; i++) - { - for (int j = 0; j < 4; j++) - { - m_flMatVal[i][j] = VEC_T_NAN; - } - } - } - - float *operator[]( int i ) { Assert(( i >= 0 ) && ( i < 3 )); return m_flMatVal[i]; } - const float *operator[]( int i ) const { Assert(( i >= 0 ) && ( i < 3 )); return m_flMatVal[i]; } - float *Base() { return &m_flMatVal[0][0]; } - const float *Base() const { return &m_flMatVal[0][0]; } - - float m_flMatVal[3][4]; -}; - - -#ifndef M_PI - #define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h -#endif - -#define M_PI_F ((float)(M_PI)) // Shouldn't collide with anything. - -// NJS: Inlined to prevent floats from being autopromoted to doubles, as with the old system. -#ifndef RAD2DEG - #define RAD2DEG( x ) ( (float)(x) * (float)(180.f / M_PI_F) ) -#endif - -#ifndef DEG2RAD - #define DEG2RAD( x ) ( (float)(x) * (float)(M_PI_F / 180.f) ) -#endif - -// Used to represent sides of things like planes. -#define SIDE_FRONT 0 -#define SIDE_BACK 1 -#define SIDE_ON 2 -#define SIDE_CROSS -2 // necessary for polylib.c - -#define ON_VIS_EPSILON 0.01 // necessary for vvis (flow.c) -- again look into moving later! -#define EQUAL_EPSILON 0.001 // necessary for vbsp (faces.c) -- should look into moving it there? - -extern bool s_bMathlibInitialized; - -extern const Vector vec3_origin; -extern const QAngle vec3_angle; -extern const Quaternion quat_identity; -extern const Vector vec3_invalid; -extern const int nanmask; - -#define IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask) - -FORCEINLINE vec_t DotProduct(const vec_t *v1, const vec_t *v2) -{ - return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; -} -FORCEINLINE void VectorSubtract(const vec_t *a, const vec_t *b, vec_t *c) -{ - c[0]=a[0]-b[0]; - c[1]=a[1]-b[1]; - c[2]=a[2]-b[2]; -} -FORCEINLINE void VectorAdd(const vec_t *a, const vec_t *b, vec_t *c) -{ - c[0]=a[0]+b[0]; - c[1]=a[1]+b[1]; - c[2]=a[2]+b[2]; -} -FORCEINLINE void VectorCopy(const vec_t *a, vec_t *b) -{ - b[0]=a[0]; - b[1]=a[1]; - b[2]=a[2]; -} -FORCEINLINE void VectorClear(vec_t *a) -{ - a[0]=a[1]=a[2]=0; -} - -FORCEINLINE float VectorMaximum(const vec_t *v) -{ - return MAX( v[0], MAX( v[1], v[2] ) ); -} - -FORCEINLINE float VectorMaximum(const Vector& v) -{ - return MAX( v.x, MAX( v.y, v.z ) ); -} - -FORCEINLINE void VectorScale (const float* in, vec_t scale, float* out) -{ - out[0] = in[0]*scale; - out[1] = in[1]*scale; - out[2] = in[2]*scale; -} - - -// Cannot be forceinline as they have overloads: -inline void VectorFill(vec_t *a, float b) -{ - a[0]=a[1]=a[2]=b; -} - -inline void VectorNegate(vec_t *a) -{ - a[0]=-a[0]; - a[1]=-a[1]; - a[2]=-a[2]; -} - - -//#define VectorMaximum(a) ( MAX( (a)[0], MAX( (a)[1], (a)[2] ) ) ) -#define Vector2Clear(x) {(x)[0]=(x)[1]=0;} -#define Vector2Negate(x) {(x)[0]=-((x)[0]);(x)[1]=-((x)[1]);} -#define Vector2Copy(a,b) {(b)[0]=(a)[0];(b)[1]=(a)[1];} -#define Vector2Subtract(a,b,c) {(c)[0]=(a)[0]-(b)[0];(c)[1]=(a)[1]-(b)[1];} -#define Vector2Add(a,b,c) {(c)[0]=(a)[0]+(b)[0];(c)[1]=(a)[1]+(b)[1];} -#define Vector2Scale(a,b,c) {(c)[0]=(b)*(a)[0];(c)[1]=(b)*(a)[1];} - -// NJS: Some functions in VBSP still need to use these for dealing with mixing vec4's and shorts with vec_t's. -// remove when no longer needed. -#define VECTOR_COPY( A, B ) do { (B)[0] = (A)[0]; (B)[1] = (A)[1]; (B)[2]=(A)[2]; } while(0) -#define DOT_PRODUCT( A, B ) ( (A)[0]*(B)[0] + (A)[1]*(B)[1] + (A)[2]*(B)[2] ) - -FORCEINLINE void VectorMAInline( const float* start, float scale, const float* direction, float* dest ) -{ - dest[0]=start[0]+direction[0]*scale; - dest[1]=start[1]+direction[1]*scale; - dest[2]=start[2]+direction[2]*scale; -} - -FORCEINLINE void VectorMAInline( const Vector& start, float scale, const Vector& direction, Vector& dest ) -{ - dest.x=start.x+direction.x*scale; - dest.y=start.y+direction.y*scale; - dest.z=start.z+direction.z*scale; -} - -//FORCEINLINE void VectorMA( const Vector& start, float scale, const Vector& direction, Vector& dest ) -//{ -// VectorMAInline(start, scale, direction, dest); -//} - -FORCEINLINE void VectorMA( const float * start, float scale, const float *direction, float *dest ) -{ - VectorMAInline(start, scale, direction, dest); -} - - -int VectorCompare (const float *v1, const float *v2); - -inline float VectorLength(const float *v) -{ - return FastSqrt( v[0]*v[0] + v[1]*v[1] + v[2]*v[2] + FLT_EPSILON ); -} - -void CrossProduct (const float *v1, const float *v2, float *cross); - -qboolean VectorsEqual( const float *v1, const float *v2 ); - -inline vec_t RoundInt (vec_t in) -{ - return floor(in + 0.5f); -} - -int Q_log2(int val); - -// Math routines done in optimized assembly math package routines -void inline SinCos( float radians, float *sine, float *cosine ) -{ -#if defined( _X360 ) - XMScalarSinCos( sine, cosine, radians ); -#elif defined( _WIN32 ) - _asm - { - fld DWORD PTR [radians] - fsincos - - mov edx, DWORD PTR [cosine] - mov eax, DWORD PTR [sine] - - fstp DWORD PTR [edx] - fstp DWORD PTR [eax] - } -#elif defined( _LINUX ) || defined ( __APPLE__ ) - register double __cosr, __sinr; - __asm __volatile__ - ("fsincos" - : "=t" (__cosr), "=u" (__sinr) : "0" (radians)); - - *sine = __sinr; - *cosine = __cosr; -#endif -} - -#define SIN_TABLE_SIZE 256 -#define FTOIBIAS 12582912.f -extern float SinCosTable[SIN_TABLE_SIZE]; - -inline float TableCos( float theta ) -{ - union - { - int i; - float f; - } ftmp; - - // ideally, the following should compile down to: theta * constant + constant, changing any of these constants from defines sometimes fubars this. - ftmp.f = theta * ( float )( SIN_TABLE_SIZE / ( 2.0f * M_PI ) ) + ( FTOIBIAS + ( SIN_TABLE_SIZE / 4 ) ); - return SinCosTable[ ftmp.i & ( SIN_TABLE_SIZE - 1 ) ]; -} - -inline float TableSin( float theta ) -{ - union - { - int i; - float f; - } ftmp; - - // ideally, the following should compile down to: theta * constant + constant - ftmp.f = theta * ( float )( SIN_TABLE_SIZE / ( 2.0f * M_PI ) ) + FTOIBIAS; - return SinCosTable[ ftmp.i & ( SIN_TABLE_SIZE - 1 ) ]; -} - -template -FORCEINLINE T Square( T const &a ) -{ - return a * a; -} - - -FORCEINLINE bool IsPowerOfTwo( uint x ) -{ - return ( x & ( x - 1 ) ) == 0; -} - -// return the smallest power of two >= x. -// returns 0 if x == 0 or x > 0x80000000 (ie numbers that would be negative if x was signed) -// NOTE: the old code took an int, and if you pass in an int of 0x80000000 casted to a uint, -// you'll get 0x80000000, which is correct for uints, instead of 0, which was correct for ints -FORCEINLINE uint SmallestPowerOfTwoGreaterOrEqual( uint x ) -{ - x -= 1; - x |= x >> 1; - x |= x >> 2; - x |= x >> 4; - x |= x >> 8; - x |= x >> 16; - return x + 1; -} - -// return the largest power of two <= x. Will return 0 if passed 0 -FORCEINLINE uint LargestPowerOfTwoLessThanOrEqual( uint x ) -{ - if ( x >= 0x80000000 ) - return 0x80000000; - - return SmallestPowerOfTwoGreaterOrEqual( x + 1 ) >> 1; -} - - -// Math routines for optimizing division -void FloorDivMod (double numer, double denom, int *quotient, int *rem); -int GreatestCommonDivisor (int i1, int i2); - -// Test for FPU denormal mode -bool IsDenormal( const float &val ); - -// MOVEMENT INFO -enum -{ - PITCH = 0, // up / down - YAW, // left / right - ROLL // fall over -}; - -void MatrixAngles( const matrix3x4_t & matrix, float *angles ); // !!!! -void MatrixVectors( const matrix3x4_t &matrix, Vector* pForward, Vector *pRight, Vector *pUp ); -void VectorTransform (const float *in1, const matrix3x4_t & in2, float *out); -void VectorITransform (const float *in1, const matrix3x4_t & in2, float *out); -void VectorRotate( const float *in1, const matrix3x4_t & in2, float *out); -void VectorRotate( const Vector &in1, const QAngle &in2, Vector &out ); -void VectorRotate( const Vector &in1, const Quaternion &in2, Vector &out ); -void VectorIRotate( const float *in1, const matrix3x4_t & in2, float *out); - -#ifndef VECTOR_NO_SLOW_OPERATIONS - -QAngle TransformAnglesToLocalSpace( const QAngle &angles, const matrix3x4_t &parentMatrix ); -QAngle TransformAnglesToWorldSpace( const QAngle &angles, const matrix3x4_t &parentMatrix ); - -#endif - -void MatrixInitialize( matrix3x4_t &mat, const Vector &vecOrigin, const Vector &vecXAxis, const Vector &vecYAxis, const Vector &vecZAxis ); -void MatrixCopy( const matrix3x4_t &in, matrix3x4_t &out ); -void MatrixInvert( const matrix3x4_t &in, matrix3x4_t &out ); - -// Matrix equality test -bool MatricesAreEqual( const matrix3x4_t &src1, const matrix3x4_t &src2, float flTolerance = 1e-5 ); - -void MatrixGetColumn( const matrix3x4_t &in, int column, Vector &out ); -void MatrixSetColumn( const Vector &in, int column, matrix3x4_t &out ); - -//void DecomposeRotation( const matrix3x4_t &mat, float *out ); -void ConcatRotations (const matrix3x4_t &in1, const matrix3x4_t &in2, matrix3x4_t &out); -void ConcatTransforms (const matrix3x4_t &in1, const matrix3x4_t &in2, matrix3x4_t &out); - -// For identical interface w/ VMatrix -inline void MatrixMultiply ( const matrix3x4_t &in1, const matrix3x4_t &in2, matrix3x4_t &out ) -{ - ConcatTransforms( in1, in2, out ); -} - -void QuaternionSlerp( const Quaternion &p, const Quaternion &q, float t, Quaternion &qt ); -void QuaternionSlerpNoAlign( const Quaternion &p, const Quaternion &q, float t, Quaternion &qt ); -void QuaternionBlend( const Quaternion &p, const Quaternion &q, float t, Quaternion &qt ); -void QuaternionBlendNoAlign( const Quaternion &p, const Quaternion &q, float t, Quaternion &qt ); -void QuaternionIdentityBlend( const Quaternion &p, float t, Quaternion &qt ); -float QuaternionAngleDiff( const Quaternion &p, const Quaternion &q ); -void QuaternionScale( const Quaternion &p, float t, Quaternion &q ); -void QuaternionAlign( const Quaternion &p, const Quaternion &q, Quaternion &qt ); -float QuaternionDotProduct( const Quaternion &p, const Quaternion &q ); -void QuaternionConjugate( const Quaternion &p, Quaternion &q ); -void QuaternionInvert( const Quaternion &p, Quaternion &q ); -float QuaternionNormalize( Quaternion &q ); -void QuaternionAdd( const Quaternion &p, const Quaternion &q, Quaternion &qt ); -void QuaternionMult( const Quaternion &p, const Quaternion &q, Quaternion &qt ); -void QuaternionMatrix( const Quaternion &q, matrix3x4_t &matrix ); -void QuaternionMatrix( const Quaternion &q, const Vector &pos, matrix3x4_t &matrix ); -void QuaternionAngles( const Quaternion &q, QAngle &angles ); -void AngleQuaternion( const QAngle& angles, Quaternion &qt ); -void QuaternionAngles( const Quaternion &q, RadianEuler &angles ); -void AngleQuaternion( RadianEuler const &angles, Quaternion &qt ); -void QuaternionAxisAngle( const Quaternion &q, Vector &axis, float &angle ); -void AxisAngleQuaternion( const Vector &axis, float angle, Quaternion &q ); -void BasisToQuaternion( const Vector &vecForward, const Vector &vecRight, const Vector &vecUp, Quaternion &q ); -void MatrixQuaternion( const matrix3x4_t &mat, Quaternion &q ); - -// A couple methods to find the dot product of a vector with a matrix row or column... -inline float MatrixRowDotProduct( const matrix3x4_t &in1, int row, const Vector& in2 ) -{ - Assert( (row >= 0) && (row < 3) ); - return DotProduct( in1[row], in2.Base() ); -} - -inline float MatrixColumnDotProduct( const matrix3x4_t &in1, int col, const Vector& in2 ) -{ - Assert( (col >= 0) && (col < 4) ); - return in1[0][col] * in2[0] + in1[1][col] * in2[1] + in1[2][col] * in2[2]; -} - -int __cdecl BoxOnPlaneSide (const float *emins, const float *emaxs, const cplane_t *plane); - -inline float anglemod(float a) -{ - a = (360.f/65536) * ((int)(a*(65536.f/360.0f)) & 65535); - return a; -} - -// Remap a value in the range [A,B] to [C,D]. -inline float RemapVal( float val, float A, float B, float C, float D) -{ - if ( A == B ) - return val >= B ? D : C; - return C + (D - C) * (val - A) / (B - A); -} - -inline float RemapValClamped( float val, float A, float B, float C, float D) -{ - if ( A == B ) - return val >= B ? D : C; - float cVal = (val - A) / (B - A); - cVal = clamp( cVal, 0.0f, 1.0f ); - - return C + (D - C) * cVal; -} - -// Returns A + (B-A)*flPercent. -// float Lerp( float flPercent, float A, float B ); -template -FORCEINLINE T Lerp( float flPercent, T const &A, T const &B ) -{ - return (T)(A + (B - A) * flPercent); -} - -FORCEINLINE float Sqr( float f ) -{ - return f*f; -} - -// 5-argument floating point linear interpolation. -// FLerp(f1,f2,i1,i2,x)= -// f1 at x=i1 -// f2 at x=i2 -// smooth lerp between f1 and f2 at x>i1 and xi2 -// -// If you know a function f(x)'s value (f1) at position i1, and its value (f2) at position i2, -// the function can be linearly interpolated with FLerp(f1,f2,i1,i2,x) -// i2=i1 will cause a divide by zero. -static inline float FLerp(float f1, float f2, float i1, float i2, float x) -{ - return f1+(f2-f1)*(x-i1)/(i2-i1); -} - - -#ifndef VECTOR_NO_SLOW_OPERATIONS - -// YWB: Specialization for interpolating euler angles via quaternions... -template<> FORCEINLINE QAngle Lerp( float flPercent, const QAngle& q1, const QAngle& q2 ) -{ - // Avoid precision errors - if ( q1 == q2 ) - return q1; - - Quaternion src, dest; - - // Convert to quaternions - AngleQuaternion( q1, src ); - AngleQuaternion( q2, dest ); - - Quaternion result; - - // Slerp - QuaternionSlerp( src, dest, flPercent, result ); - - // Convert to euler - QAngle output; - QuaternionAngles( result, output ); - return output; -} - -#else - -#pragma error - -// NOTE NOTE: I haven't tested this!! It may not work! Check out interpolatedvar.cpp in the client dll to try it -template<> FORCEINLINE QAngleByValue Lerp( float flPercent, const QAngleByValue& q1, const QAngleByValue& q2 ) -{ - // Avoid precision errors - if ( q1 == q2 ) - return q1; - - Quaternion src, dest; - - // Convert to quaternions - AngleQuaternion( q1, src ); - AngleQuaternion( q2, dest ); - - Quaternion result; - - // Slerp - QuaternionSlerp( src, dest, flPercent, result ); - - // Convert to euler - QAngleByValue output; - QuaternionAngles( result, output ); - return output; -} - -#endif // VECTOR_NO_SLOW_OPERATIONS - - -// Swap two of anything. -template -FORCEINLINE void swap( T& x, T& y ) -{ - T temp = x; - x = y; - y = temp; -} - -template FORCEINLINE T AVG(T a, T b) -{ - return (a+b)/2; -} - -// number of elements in an array of static size -#define NELEMS(x) ((sizeof(x))/sizeof(x[0])) - -// XYZ macro, for printf type functions - ex printf("%f %f %f",XYZ(myvector)); -#define XYZ(v) (v).x,(v).y,(v).z - -// -// Returns a clamped value in the range [min, max]. -// -#define clamp(val, min, max) (((val) > (max)) ? (max) : (((val) < (min)) ? (min) : (val))) - -inline float Sign( float x ) -{ - return (x <0.0f) ? -1.0f : 1.0f; -} - -// -// Clamps the input integer to the given array bounds. -// Equivalent to the following, but without using any branches: -// -// if( n < 0 ) return 0; -// else if ( n > maxindex ) return maxindex; -// else return n; -// -// This is not always a clear performance win, but when you have situations where a clamped -// value is thrashing against a boundary this is a big win. (ie, valid, invalid, valid, invalid, ...) -// -// Note: This code has been run against all possible integers. -// -inline int ClampArrayBounds( int n, unsigned maxindex ) -{ - // mask is 0 if less than 4096, 0xFFFFFFFF if greater than - unsigned int inrangemask = 0xFFFFFFFF + (((unsigned) n) > maxindex ); - unsigned int lessthan0mask = 0xFFFFFFFF + ( n >= 0 ); - - // If the result was valid, set the result, (otherwise sets zero) - int result = (inrangemask & n); - - // if the result was out of range or zero. - result |= ((~inrangemask) & (~lessthan0mask)) & maxindex; - - return result; -} - - -#define BOX_ON_PLANE_SIDE(emins, emaxs, p) \ - (((p)->type < 3)? \ - ( \ - ((p)->dist <= (emins)[(p)->type])? \ - 1 \ - : \ - ( \ - ((p)->dist >= (emaxs)[(p)->type])?\ - 2 \ - : \ - 3 \ - ) \ - ) \ - : \ - BoxOnPlaneSide( (emins), (emaxs), (p))) - -//----------------------------------------------------------------------------- -// FIXME: Vector versions.... the float versions will go away hopefully soon! -//----------------------------------------------------------------------------- - -void AngleVectors (const QAngle& angles, Vector *forward); -void AngleVectors (const QAngle& angles, Vector *forward, Vector *right, Vector *up); -void AngleVectorsTranspose (const QAngle& angles, Vector *forward, Vector *right, Vector *up); -void AngleMatrix (const QAngle &angles, matrix3x4_t &mat ); -void AngleMatrix( const QAngle &angles, const Vector &position, matrix3x4_t &mat ); -void AngleMatrix (const RadianEuler &angles, matrix3x4_t &mat ); -void AngleMatrix( RadianEuler const &angles, const Vector &position, matrix3x4_t &mat ); -void AngleIMatrix (const QAngle &angles, matrix3x4_t &mat ); -void AngleIMatrix (const QAngle &angles, const Vector &position, matrix3x4_t &mat ); -void AngleIMatrix (const RadianEuler &angles, matrix3x4_t &mat ); -void VectorAngles( const Vector &forward, QAngle &angles ); -void VectorAngles( const Vector &forward, const Vector &pseudoup, QAngle &angles ); -void VectorMatrix( const Vector &forward, matrix3x4_t &mat ); -void VectorVectors( const Vector &forward, Vector &right, Vector &up ); -void SetIdentityMatrix( matrix3x4_t &mat ); -void SetScaleMatrix( float x, float y, float z, matrix3x4_t &dst ); -void MatrixBuildRotationAboutAxis( const Vector &vAxisOfRot, float angleDegrees, matrix3x4_t &dst ); - -inline void SetScaleMatrix( float flScale, matrix3x4_t &dst ) -{ - SetScaleMatrix( flScale, flScale, flScale, dst ); -} - -inline void SetScaleMatrix( const Vector& scale, matrix3x4_t &dst ) -{ - SetScaleMatrix( scale.x, scale.y, scale.z, dst ); -} - -// Computes the inverse transpose -void MatrixTranspose( matrix3x4_t& mat ); -void MatrixTranspose( const matrix3x4_t& src, matrix3x4_t& dst ); -void MatrixInverseTranspose( const matrix3x4_t& src, matrix3x4_t& dst ); - -inline void PositionMatrix( const Vector &position, matrix3x4_t &mat ) -{ - MatrixSetColumn( position, 3, mat ); -} - -inline void MatrixPosition( const matrix3x4_t &matrix, Vector &position ) -{ - MatrixGetColumn( matrix, 3, position ); -} - -inline void VectorRotate( const Vector& in1, const matrix3x4_t &in2, Vector &out) -{ - VectorRotate( &in1.x, in2, &out.x ); -} - -inline void VectorIRotate( const Vector& in1, const matrix3x4_t &in2, Vector &out) -{ - VectorIRotate( &in1.x, in2, &out.x ); -} - -inline void MatrixAngles( const matrix3x4_t &matrix, QAngle &angles ) -{ - MatrixAngles( matrix, &angles.x ); -} - -inline void MatrixAngles( const matrix3x4_t &matrix, QAngle &angles, Vector &position ) -{ - MatrixAngles( matrix, angles ); - MatrixPosition( matrix, position ); -} - -inline void MatrixAngles( const matrix3x4_t &matrix, RadianEuler &angles ) -{ - MatrixAngles( matrix, &angles.x ); - - angles.Init( DEG2RAD( angles.z ), DEG2RAD( angles.x ), DEG2RAD( angles.y ) ); -} - -void MatrixAngles( const matrix3x4_t &mat, RadianEuler &angles, Vector &position ); - -void MatrixAngles( const matrix3x4_t &mat, Quaternion &q, Vector &position ); - -inline int VectorCompare (const Vector& v1, const Vector& v2) -{ - return v1 == v2; -} - -inline void VectorTransform (const Vector& in1, const matrix3x4_t &in2, Vector &out) -{ - VectorTransform( &in1.x, in2, &out.x ); -} - -inline void VectorITransform (const Vector& in1, const matrix3x4_t &in2, Vector &out) -{ - VectorITransform( &in1.x, in2, &out.x ); -} - -/* -inline void DecomposeRotation( const matrix3x4_t &mat, Vector &out ) -{ - DecomposeRotation( mat, &out.x ); -} -*/ - -inline int BoxOnPlaneSide (const Vector& emins, const Vector& emaxs, const cplane_t *plane ) -{ - return BoxOnPlaneSide( &emins.x, &emaxs.x, plane ); -} - -inline void VectorFill(Vector& a, float b) -{ - a[0]=a[1]=a[2]=b; -} - -inline void VectorNegate(Vector& a) -{ - a[0] = -a[0]; - a[1] = -a[1]; - a[2] = -a[2]; -} - -inline vec_t VectorAvg(Vector& a) -{ - return ( a[0] + a[1] + a[2] ) / 3; -} - -//----------------------------------------------------------------------------- -// Box/plane test (slow version) -//----------------------------------------------------------------------------- -inline int FASTCALL BoxOnPlaneSide2 (const Vector& emins, const Vector& emaxs, const cplane_t *p, float tolerance = 0.f ) -{ - Vector corners[2]; - - if (p->normal[0] < 0) - { - corners[0][0] = emins[0]; - corners[1][0] = emaxs[0]; - } - else - { - corners[1][0] = emins[0]; - corners[0][0] = emaxs[0]; - } - - if (p->normal[1] < 0) - { - corners[0][1] = emins[1]; - corners[1][1] = emaxs[1]; - } - else - { - corners[1][1] = emins[1]; - corners[0][1] = emaxs[1]; - } - - if (p->normal[2] < 0) - { - corners[0][2] = emins[2]; - corners[1][2] = emaxs[2]; - } - else - { - corners[1][2] = emins[2]; - corners[0][2] = emaxs[2]; - } - - int sides = 0; - - float dist1 = DotProduct (p->normal, corners[0]) - p->dist; - if (dist1 >= tolerance) - sides = 1; - - float dist2 = DotProduct (p->normal, corners[1]) - p->dist; - if (dist2 < -tolerance) - sides |= 2; - - return sides; -} - -//----------------------------------------------------------------------------- -// Helpers for bounding box construction -//----------------------------------------------------------------------------- - -void ClearBounds (Vector& mins, Vector& maxs); -void AddPointToBounds (const Vector& v, Vector& mins, Vector& maxs); - -// -// COLORSPACE/GAMMA CONVERSION STUFF -// -void BuildGammaTable( float gamma, float texGamma, float brightness, int overbright ); - -// convert texture to linear 0..1 value -inline float TexLightToLinear( int c, int exponent ) -{ - extern float power2_n[256]; - Assert( exponent >= -128 && exponent <= 127 ); - return ( float )c * power2_n[exponent+128]; -} - - -// convert texture to linear 0..1 value -int LinearToTexture( float f ); -// converts 0..1 linear value to screen gamma (0..255) -int LinearToScreenGamma( float f ); -float TextureToLinear( int c ); - -// compressed color format -struct ColorRGBExp32 -{ - byte r, g, b; - signed char exponent; -}; - -void ColorRGBExp32ToVector( const ColorRGBExp32& in, Vector& out ); -void VectorToColorRGBExp32( const Vector& v, ColorRGBExp32 &c ); - -// solve for "x" where "a x^2 + b x + c = 0", return true if solution exists -bool SolveQuadratic( float a, float b, float c, float &root1, float &root2 ); - -// solves for "a, b, c" where "a x^2 + b x + c = y", return true if solution exists -bool SolveInverseQuadratic( float x1, float y1, float x2, float y2, float x3, float y3, float &a, float &b, float &c ); - -// solves for a,b,c specified as above, except that it always creates a monotonically increasing or -// decreasing curve if the data is monotonically increasing or decreasing. In order to enforce the -// monoticity condition, it is possible that the resulting quadratic will only approximate the data -// instead of interpolating it. This code is not especially fast. -bool SolveInverseQuadraticMonotonic( float x1, float y1, float x2, float y2, - float x3, float y3, float &a, float &b, float &c ); - - - - -// solves for "a, b, c" where "1/(a x^2 + b x + c ) = y", return true if solution exists -bool SolveInverseReciprocalQuadratic( float x1, float y1, float x2, float y2, float x3, float y3, float &a, float &b, float &c ); - -// rotate a vector around the Z axis (YAW) -void VectorYawRotate( const Vector& in, float flYaw, Vector &out); - - -// Bias takes an X value between 0 and 1 and returns another value between 0 and 1 -// The curve is biased towards 0 or 1 based on biasAmt, which is between 0 and 1. -// Lower values of biasAmt bias the curve towards 0 and higher values bias it towards 1. -// -// For example, with biasAmt = 0.2, the curve looks like this: -// -// 1 -// | * -// | * -// | * -// | ** -// | ** -// | **** -// |********* -// |___________________ -// 0 1 -// -// -// With biasAmt = 0.8, the curve looks like this: -// -// 1 -// | ************** -// | ** -// | * -// | * -// |* -// |* -// |* -// |___________________ -// 0 1 -// -// With a biasAmt of 0.5, Bias returns X. -float Bias( float x, float biasAmt ); - - -// Gain is similar to Bias, but biasAmt biases towards or away from 0.5. -// Lower bias values bias towards 0.5 and higher bias values bias away from it. -// -// For example, with biasAmt = 0.2, the curve looks like this: -// -// 1 -// | * -// | * -// | ** -// | *************** -// | ** -// | * -// |* -// |___________________ -// 0 1 -// -// -// With biasAmt = 0.8, the curve looks like this: -// -// 1 -// | ***** -// | *** -// | * -// | * -// | * -// | *** -// |***** -// |___________________ -// 0 1 -float Gain( float x, float biasAmt ); - - -// SmoothCurve maps a 0-1 value into another 0-1 value based on a cosine wave -// where the derivatives of the function at 0 and 1 (and 0.5) are 0. This is useful for -// any fadein/fadeout effect where it should start and end smoothly. -// -// The curve looks like this: -// -// 1 -// | ** -// | * * -// | * * -// | * * -// | * * -// | ** ** -// |*** *** -// |___________________ -// 0 1 -// -float SmoothCurve( float x ); - - -// This works like SmoothCurve, with two changes: -// -// 1. Instead of the curve peaking at 0.5, it will peak at flPeakPos. -// (So if you specify flPeakPos=0.2, then the peak will slide to the left). -// -// 2. flPeakSharpness is a 0-1 value controlling the sharpness of the peak. -// Low values blunt the peak and high values sharpen the peak. -float SmoothCurve_Tweak( float x, float flPeakPos=0.5, float flPeakSharpness=0.5 ); - - -//float ExponentialDecay( float halflife, float dt ); -//float ExponentialDecay( float decayTo, float decayTime, float dt ); - -// halflife is time for value to reach 50% -inline float ExponentialDecay( float halflife, float dt ) -{ - // log(0.5) == -0.69314718055994530941723212145818 - return expf( -0.69314718f / halflife * dt); -} - -// decayTo is factor the value should decay to in decayTime -inline float ExponentialDecay( float decayTo, float decayTime, float dt ) -{ - return expf( logf( decayTo ) / decayTime * dt); -} - -// Get the integrated distanced traveled -// decayTo is factor the value should decay to in decayTime -// dt is the time relative to the last velocity update -inline float ExponentialDecayIntegral( float decayTo, float decayTime, float dt ) -{ - return (powf( decayTo, dt / decayTime) * decayTime - decayTime) / logf( decayTo ); -} - -// hermite basis function for smooth interpolation -// Similar to Gain() above, but very cheap to call -// value should be between 0 & 1 inclusive -inline float SimpleSpline( float value ) -{ - float valueSquared = value * value; - - // Nice little ease-in, ease-out spline-like curve - return (3 * valueSquared - 2 * valueSquared * value); -} - -// remaps a value in [startInterval, startInterval+rangeInterval] from linear to -// spline using SimpleSpline -inline float SimpleSplineRemapVal( float val, float A, float B, float C, float D) -{ - if ( A == B ) - return val >= B ? D : C; - float cVal = (val - A) / (B - A); - return C + (D - C) * SimpleSpline( cVal ); -} - -// remaps a value in [startInterval, startInterval+rangeInterval] from linear to -// spline using SimpleSpline -inline float SimpleSplineRemapValClamped( float val, float A, float B, float C, float D ) -{ - if ( A == B ) - return val >= B ? D : C; - float cVal = (val - A) / (B - A); - cVal = clamp( cVal, 0.0f, 1.0f ); - return C + (D - C) * SimpleSpline( cVal ); -} - -FORCEINLINE int RoundFloatToInt(float f) -{ -#if defined( _X360 ) -#ifdef Assert - Assert( IsFPUControlWordSet() ); -#endif - union - { - double flResult; - int pResult[2]; - }; - flResult = __fctiw( f ); - return pResult[1]; -#else // !X360 - int nResult; -#if defined( _WIN32 ) - __asm - { - fld f - fistp nResult - } -#elif defined( _LINUX ) || defined( __APPLE__ ) - __asm __volatile__ ( - "fistpl %0;": "=m" (nResult): "t" (f) : "st" - ); -#endif - return nResult; -#endif -} - -FORCEINLINE unsigned char RoundFloatToByte(float f) -{ -#if defined( _X360 ) -#ifdef Assert - Assert( IsFPUControlWordSet() ); -#endif - union - { - double flResult; - int pIntResult[2]; - unsigned char pResult[8]; - }; - flResult = __fctiw( f ); -#ifdef Assert - Assert( pIntResult[1] >= 0 && pIntResult[1] <= 255 ); -#endif - return pResult[8]; - -#else // !X360 - - int nResult; - -#if defined( _WIN32 ) - __asm - { - fld f - fistp nResult - } -#elif defined( _LINUX ) || defined( __APPLE__ ) - __asm __volatile__ ( - "fistpl %0;": "=m" (nResult): "t" (f) : "st" - ); -#endif - -#ifdef Assert - Assert( nResult >= 0 && nResult <= 255 ); -#endif - return nResult; - -#endif -} - -FORCEINLINE unsigned long RoundFloatToUnsignedLong(float f) -{ -#if defined( _X360 ) -#ifdef Assert - Assert( IsFPUControlWordSet() ); -#endif - union - { - double flResult; - int pIntResult[2]; - unsigned long pResult[2]; - }; - flResult = __fctiw( f ); - Assert( pIntResult[1] >= 0 ); - return pResult[1]; -#else // !X360 - - unsigned char nResult[8]; - -#if defined( _WIN32 ) - __asm - { - fld f - fistp qword ptr nResult - } -#elif defined( _LINUX ) || defined( __APPLE__ ) - __asm __volatile__ ( - "fistpl %0;": "=m" (nResult): "t" (f) : "st" - ); -#endif - - return *((unsigned long*)nResult); -#endif -} - -FORCEINLINE bool IsIntegralValue( float flValue, float flTolerance = 0.001f ) -{ - return fabs( RoundFloatToInt( flValue ) - flValue ) < flTolerance; -} - -// Fast, accurate ftol: -FORCEINLINE int Float2Int( float a ) -{ -#if defined( _X360 ) - union - { - double flResult; - int pResult[2]; - }; - flResult = __fctiwz( a ); - return pResult[1]; -#else // !X360 - - int RetVal; - -#if defined( _WIN32 ) - int CtrlwdHolder; - int CtrlwdSetter; - __asm - { - fld a // push 'a' onto the FP stack - fnstcw CtrlwdHolder // store FPU control word - movzx eax, CtrlwdHolder // move and zero extend word into eax - and eax, 0xFFFFF3FF // set all bits except rounding bits to 1 - or eax, 0x00000C00 // set rounding mode bits to round towards zero - mov CtrlwdSetter, eax // Prepare to set the rounding mode -- prepare to enter plaid! - fldcw CtrlwdSetter // Entering plaid! - fistp RetVal // Store and converted (to int) result - fldcw CtrlwdHolder // Restore control word - } -#elif defined( _LINUX ) || defined ( __APPLE__ ) - RetVal = static_cast( a ); -#endif - - return RetVal; -#endif -} - -// Over 15x faster than: (int)floor(value) -inline int Floor2Int( float a ) -{ - int RetVal; - -#if defined( _X360 ) - RetVal = (int)floor( a ); -#elif defined( _WIN32 ) - int CtrlwdHolder; - int CtrlwdSetter; - __asm - { - fld a // push 'a' onto the FP stack - fnstcw CtrlwdHolder // store FPU control word - movzx eax, CtrlwdHolder // move and zero extend word into eax - and eax, 0xFFFFF3FF // set all bits except rounding bits to 1 - or eax, 0x00000400 // set rounding mode bits to round down - mov CtrlwdSetter, eax // Prepare to set the rounding mode -- prepare to enter plaid! - fldcw CtrlwdSetter // Entering plaid! - fistp RetVal // Store floored and converted (to int) result - fldcw CtrlwdHolder // Restore control word - } -#elif defined( _LINUX ) || defined( __APPLE__ ) - RetVal = static_cast( floor(a) ); -#endif - - return RetVal; -} - -//----------------------------------------------------------------------------- -// Fast color conversion from float to unsigned char -//----------------------------------------------------------------------------- -FORCEINLINE unsigned char FastFToC( float c ) -{ - volatile float dc; - - // ieee trick - dc = c * 255.0f + (float)(1 << 23); - - // return the lsb -#if defined( _X360 ) - return ((unsigned char*)&dc)[3]; -#else - return *(unsigned char*)&dc; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: Bound input float to .001 (millisecond) boundary -// Input : in - -// Output : inline float -//----------------------------------------------------------------------------- -inline float ClampToMsec( float in ) -{ - int msec = Floor2Int( in * 1000.0f + 0.5f ); - return msec / 1000.0f; -} - -// Over 15x faster than: (int)ceil(value) -inline int Ceil2Int( float a ) -{ - int RetVal; - -#if defined( _X360 ) - RetVal = (int)ceil( a ); -#elif defined( _WIN32 ) - int CtrlwdHolder; - int CtrlwdSetter; - __asm - { - fld a // push 'a' onto the FP stack - fnstcw CtrlwdHolder // store FPU control word - movzx eax, CtrlwdHolder // move and zero extend word into eax - and eax, 0xFFFFF3FF // set all bits except rounding bits to 1 - or eax, 0x00000800 // set rounding mode bits to round down - mov CtrlwdSetter, eax // Prepare to set the rounding mode -- prepare to enter plaid! - fldcw CtrlwdSetter // Entering plaid! - fistp RetVal // Store floored and converted (to int) result - fldcw CtrlwdHolder // Restore control word - } -#elif defined( _LINUX ) || defined( __APPLE__ ) - RetVal = static_cast( ceil(a) ); -#endif - - return RetVal; -} - - -// Regular signed area of triangle -#define TriArea2D( A, B, C ) \ - ( 0.5f * ( ( B.x - A.x ) * ( C.y - A.y ) - ( B.y - A.y ) * ( C.x - A.x ) ) ) - -// This version doesn't premultiply by 0.5f, so it's the area of the rectangle instead -#define TriArea2DTimesTwo( A, B, C ) \ - ( ( ( B.x - A.x ) * ( C.y - A.y ) - ( B.y - A.y ) * ( C.x - A.x ) ) ) - - -// Get the barycentric coordinates of "pt" in triangle [A,B,C]. -inline void GetBarycentricCoords2D( - Vector2D const &A, - Vector2D const &B, - Vector2D const &C, - Vector2D const &pt, - float bcCoords[3] ) -{ - // Note, because to top and bottom are both x2, the issue washes out in the composite - float invTriArea = 1.0f / TriArea2DTimesTwo( A, B, C ); - - // NOTE: We assume here that the lightmap coordinate vertices go counterclockwise. - // If not, TriArea2D() is negated so this works out right. - bcCoords[0] = TriArea2DTimesTwo( B, C, pt ) * invTriArea; - bcCoords[1] = TriArea2DTimesTwo( C, A, pt ) * invTriArea; - bcCoords[2] = TriArea2DTimesTwo( A, B, pt ) * invTriArea; -} - - -// Return true of the sphere might touch the box (the sphere is actually treated -// like a box itself, so this may return true if the sphere's bounding box touches -// a corner of the box but the sphere itself doesn't). -inline bool QuickBoxSphereTest( - const Vector& vOrigin, - float flRadius, - const Vector& bbMin, - const Vector& bbMax ) -{ - return vOrigin.x - flRadius < bbMax.x && vOrigin.x + flRadius > bbMin.x && - vOrigin.y - flRadius < bbMax.y && vOrigin.y + flRadius > bbMin.y && - vOrigin.z - flRadius < bbMax.z && vOrigin.z + flRadius > bbMin.z; -} - - -// Return true of the boxes intersect (but not if they just touch). -inline bool QuickBoxIntersectTest( - const Vector& vBox1Min, - const Vector& vBox1Max, - const Vector& vBox2Min, - const Vector& vBox2Max ) -{ - return - vBox1Min.x < vBox2Max.x && vBox1Max.x > vBox2Min.x && - vBox1Min.y < vBox2Max.y && vBox1Max.y > vBox2Min.y && - vBox1Min.z < vBox2Max.z && vBox1Max.z > vBox2Min.z; -} - - -extern float GammaToLinearFullRange( float gamma ); -extern float LinearToGammaFullRange( float linear ); -extern float GammaToLinear( float gamma ); -extern float LinearToGamma( float linear ); - -extern float SrgbGammaToLinear( float flSrgbGammaValue ); -extern float SrgbLinearToGamma( float flLinearValue ); -extern float X360GammaToLinear( float fl360GammaValue ); -extern float X360LinearToGamma( float flLinearValue ); -extern float SrgbGammaTo360Gamma( float flSrgbGammaValue ); - -// linear (0..4) to screen corrected vertex space (0..1?) -FORCEINLINE float LinearToVertexLight( float f ) -{ - extern float lineartovertex[4096]; - - // Gotta clamp before the multiply; could overflow... - // assume 0..4 range - int i = RoundFloatToInt( f * 1024.f ); - - // Presumably the comman case will be not to clamp, so check that first: - if( (unsigned)i > 4095 ) - { - if ( i < 0 ) - i = 0; // Compare to zero instead of 4095 to save 4 bytes in the instruction stream - else - i = 4095; - } - - return lineartovertex[i]; -} - - -FORCEINLINE unsigned char LinearToLightmap( float f ) -{ - extern unsigned char lineartolightmap[4096]; - - // Gotta clamp before the multiply; could overflow... - int i = RoundFloatToInt( f * 1024.f ); // assume 0..4 range - - // Presumably the comman case will be not to clamp, so check that first: - if ( (unsigned)i > 4095 ) - { - if ( i < 0 ) - i = 0; // Compare to zero instead of 4095 to save 4 bytes in the instruction stream - else - i = 4095; - } - - return lineartolightmap[i]; -} - -FORCEINLINE void ColorClamp( Vector& color ) -{ - float maxc = MAX( color.x, MAX( color.y, color.z ) ); - if ( maxc > 1.0f ) - { - float ooMax = 1.0f / maxc; - color.x *= ooMax; - color.y *= ooMax; - color.z *= ooMax; - } - - if ( color[0] < 0.f ) color[0] = 0.f; - if ( color[1] < 0.f ) color[1] = 0.f; - if ( color[2] < 0.f ) color[2] = 0.f; -} - -inline void ColorClampTruncate( Vector& color ) -{ - if (color[0] > 1.0f) color[0] = 1.0f; else if (color[0] < 0.0f) color[0] = 0.0f; - if (color[1] > 1.0f) color[1] = 1.0f; else if (color[1] < 0.0f) color[1] = 0.0f; - if (color[2] > 1.0f) color[2] = 1.0f; else if (color[2] < 0.0f) color[2] = 0.0f; -} - -// Interpolate a Catmull-Rom spline. -// t is a [0,1] value and interpolates a curve between p2 and p3. -void Catmull_Rom_Spline( - const Vector &p1, - const Vector &p2, - const Vector &p3, - const Vector &p4, - float t, - Vector &output ); - -// Interpolate a Catmull-Rom spline. -// Returns the tangent of the point at t of the spline -void Catmull_Rom_Spline_Tangent( - const Vector &p1, - const Vector &p2, - const Vector &p3, - const Vector &p4, - float t, - Vector &output ); - -// area under the curve [0..t] -void Catmull_Rom_Spline_Integral( - const Vector &p1, - const Vector &p2, - const Vector &p3, - const Vector &p4, - float t, - Vector& output ); - -// area under the curve [0..1] -void Catmull_Rom_Spline_Integral( - const Vector &p1, - const Vector &p2, - const Vector &p3, - const Vector &p4, - Vector& output ); - -// Interpolate a Catmull-Rom spline. -// Normalize p2->p1 and p3->p4 to be the same length as p2->p3 -void Catmull_Rom_Spline_Normalize( - const Vector &p1, - const Vector &p2, - const Vector &p3, - const Vector &p4, - float t, - Vector &output ); - -// area under the curve [0..t] -// Normalize p2->p1 and p3->p4 to be the same length as p2->p3 -void Catmull_Rom_Spline_Integral_Normalize( - const Vector &p1, - const Vector &p2, - const Vector &p3, - const Vector &p4, - float t, - Vector& output ); - -// Interpolate a Catmull-Rom spline. -// Normalize p2.x->p1.x and p3.x->p4.x to be the same length as p2.x->p3.x -void Catmull_Rom_Spline_NormalizeX( - const Vector &p1, - const Vector &p2, - const Vector &p3, - const Vector &p4, - float t, - Vector &output ); - -// area under the curve [0..t] -void Catmull_Rom_Spline_NormalizeX( - const Vector &p1, - const Vector &p2, - const Vector &p3, - const Vector &p4, - float t, - Vector& output ); - -// Interpolate a Hermite spline. -// t is a [0,1] value and interpolates a curve between p1 and p2 with the deltas d1 and d2. -void Hermite_Spline( - const Vector &p1, - const Vector &p2, - const Vector &d1, - const Vector &d2, - float t, - Vector& output ); - -float Hermite_Spline( - float p1, - float p2, - float d1, - float d2, - float t ); - -// t is a [0,1] value and interpolates a curve between p1 and p2 with the slopes p0->p1 and p1->p2 -void Hermite_Spline( - const Vector &p0, - const Vector &p1, - const Vector &p2, - float t, - Vector& output ); - -float Hermite_Spline( - float p0, - float p1, - float p2, - float t ); - - -void Hermite_SplineBasis( float t, float basis[] ); - -void Hermite_Spline( - const Quaternion &q0, - const Quaternion &q1, - const Quaternion &q2, - float t, - Quaternion &output ); - - -// See http://en.wikipedia.org/wiki/Kochanek-Bartels_curves -// -// Tension: -1 = Round -> 1 = Tight -// Bias: -1 = Pre-shoot (bias left) -> 1 = Post-shoot (bias right) -// Continuity: -1 = Box corners -> 1 = Inverted corners -// -// If T=B=C=0 it's the same matrix as Catmull-Rom. -// If T=1 & B=C=0 it's the same as Cubic. -// If T=B=0 & C=-1 it's just linear interpolation -// -// See http://news.povray.org/povray.binaries.tutorials/attachment/%3CXns91B880592482seed7@povray.org%3E/Splines.bas.txt -// for example code and descriptions of various spline types... -// -void Kochanek_Bartels_Spline( - float tension, - float bias, - float continuity, - const Vector &p1, - const Vector &p2, - const Vector &p3, - const Vector &p4, - float t, - Vector& output ); - -void Kochanek_Bartels_Spline_NormalizeX( - float tension, - float bias, - float continuity, - const Vector &p1, - const Vector &p2, - const Vector &p3, - const Vector &p4, - float t, - Vector& output ); - -// See link at Kochanek_Bartels_Spline for info on the basis matrix used -void Cubic_Spline( - const Vector &p1, - const Vector &p2, - const Vector &p3, - const Vector &p4, - float t, - Vector& output ); - -void Cubic_Spline_NormalizeX( - const Vector &p1, - const Vector &p2, - const Vector &p3, - const Vector &p4, - float t, - Vector& output ); - -// See link at Kochanek_Bartels_Spline for info on the basis matrix used -void BSpline( - const Vector &p1, - const Vector &p2, - const Vector &p3, - const Vector &p4, - float t, - Vector& output ); - -void BSpline_NormalizeX( - const Vector &p1, - const Vector &p2, - const Vector &p3, - const Vector &p4, - float t, - Vector& output ); - -// See link at Kochanek_Bartels_Spline for info on the basis matrix used -void Parabolic_Spline( - const Vector &p1, - const Vector &p2, - const Vector &p3, - const Vector &p4, - float t, - Vector& output ); - -void Parabolic_Spline_NormalizeX( - const Vector &p1, - const Vector &p2, - const Vector &p3, - const Vector &p4, - float t, - Vector& output ); - -// quintic interpolating polynomial from Perlin. -// 0->0, 1->1, smooth-in between with smooth tangents -FORCEINLINE float QuinticInterpolatingPolynomial(float t) -{ - // 6t^5-15t^4+10t^3 - return t * t * t *( t * ( t* 6.0 - 15.0 ) + 10.0 ); -} - -// given a table of sorted tabulated positions, return the two indices and blendfactor to linear -// interpolate. Does a search. Can be used to find the blend value to interpolate between -// keyframes. -void GetInterpolationData( float const *pKnotPositions, - float const *pKnotValues, - int nNumValuesinList, - int nInterpolationRange, - float flPositionToInterpolateAt, - bool bWrap, - float *pValueA, - float *pValueB, - float *pInterpolationValue); - -float RangeCompressor( float flValue, float flMin, float flMax, float flBase ); - -// Get the minimum distance from vOrigin to the bounding box defined by [mins,maxs] -// using voronoi regions. -// 0 is returned if the origin is inside the box. -float CalcSqrDistanceToAABB( const Vector &mins, const Vector &maxs, const Vector &point ); -void CalcClosestPointOnAABB( const Vector &mins, const Vector &maxs, const Vector &point, Vector &closestOut ); -void CalcSqrDistAndClosestPointOnAABB( const Vector &mins, const Vector &maxs, const Vector &point, Vector &closestOut, float &distSqrOut ); - -inline float CalcDistanceToAABB( const Vector &mins, const Vector &maxs, const Vector &point ) -{ - float flDistSqr = CalcSqrDistanceToAABB( mins, maxs, point ); - return sqrt(flDistSqr); -} - -// Get the closest point from P to the (infinite) line through vLineA and vLineB and -// calculate the shortest distance from P to the line. -// If you pass in a value for t, it will tell you the t for (A + (B-A)t) to get the closest point. -// If the closest point lies on the segment between A and B, then 0 <= t <= 1. -void CalcClosestPointOnLine( const Vector &P, const Vector &vLineA, const Vector &vLineB, Vector &vClosest, float *t=0 ); -float CalcDistanceToLine( const Vector &P, const Vector &vLineA, const Vector &vLineB, float *t=0 ); -float CalcDistanceSqrToLine( const Vector &P, const Vector &vLineA, const Vector &vLineB, float *t=0 ); - -// The same three functions as above, except now the line is closed between A and B. -void CalcClosestPointOnLineSegment( const Vector &P, const Vector &vLineA, const Vector &vLineB, Vector &vClosest, float *t=0 ); -float CalcDistanceToLineSegment( const Vector &P, const Vector &vLineA, const Vector &vLineB, float *t=0 ); -float CalcDistanceSqrToLineSegment( const Vector &P, const Vector &vLineA, const Vector &vLineB, float *t=0 ); - -// A function to compute the closes line segment connnection two lines (or false if the lines are parallel, etc.) -bool CalcLineToLineIntersectionSegment( - const Vector& p1,const Vector& p2,const Vector& p3,const Vector& p4,Vector *s1,Vector *s2, - float *t1, float *t2 ); - -// The above functions in 2D -void CalcClosestPointOnLine2D( Vector2D const &P, Vector2D const &vLineA, Vector2D const &vLineB, Vector2D &vClosest, float *t=0 ); -float CalcDistanceToLine2D( Vector2D const &P, Vector2D const &vLineA, Vector2D const &vLineB, float *t=0 ); -float CalcDistanceSqrToLine2D( Vector2D const &P, Vector2D const &vLineA, Vector2D const &vLineB, float *t=0 ); -void CalcClosestPointOnLineSegment2D( Vector2D const &P, Vector2D const &vLineA, Vector2D const &vLineB, Vector2D &vClosest, float *t=0 ); -float CalcDistanceToLineSegment2D( Vector2D const &P, Vector2D const &vLineA, Vector2D const &vLineB, float *t=0 ); -float CalcDistanceSqrToLineSegment2D( Vector2D const &P, Vector2D const &vLineA, Vector2D const &vLineB, float *t=0 ); - -// Init the mathlib -void MathLib_Init( float gamma = 2.2f, float texGamma = 2.2f, float brightness = 0.0f, int overbright = 2.0f, bool bAllow3DNow = true, bool bAllowSSE = true, bool bAllowSSE2 = true, bool bAllowMMX = true ); -bool MathLib_3DNowEnabled( void ); -bool MathLib_MMXEnabled( void ); -bool MathLib_SSEEnabled( void ); -bool MathLib_SSE2Enabled( void ); - -float Approach( float target, float value, float speed ); -float ApproachAngle( float target, float value, float speed ); -float AngleDiff( float destAngle, float srcAngle ); -float AngleDistance( float next, float cur ); -float AngleNormalize( float angle ); - -// ensure that 0 <= angle <= 360 -float AngleNormalizePositive( float angle ); - -bool AnglesAreEqual( float a, float b, float tolerance = 0.0f ); - - -void RotationDeltaAxisAngle( const QAngle &srcAngles, const QAngle &destAngles, Vector &deltaAxis, float &deltaAngle ); -void RotationDelta( const QAngle &srcAngles, const QAngle &destAngles, QAngle *out ); - -void ComputeTrianglePlane( const Vector& v1, const Vector& v2, const Vector& v3, Vector& normal, float& intercept ); -int PolyFromPlane( Vector *outVerts, const Vector& normal, float dist, float fHalfScale = 9000.0f ); -int ClipPolyToPlane( Vector *inVerts, int vertCount, Vector *outVerts, const Vector& normal, float dist, float fOnPlaneEpsilon = 0.1f ); -int ClipPolyToPlane_Precise( double *inVerts, int vertCount, double *outVerts, const double *normal, double dist, double fOnPlaneEpsilon = 0.1 ); - -//----------------------------------------------------------------------------- -// Computes a reasonable tangent space for a triangle -//----------------------------------------------------------------------------- -void CalcTriangleTangentSpace( const Vector &p0, const Vector &p1, const Vector &p2, - const Vector2D &t0, const Vector2D &t1, const Vector2D& t2, - Vector &sVect, Vector &tVect ); - -//----------------------------------------------------------------------------- -// Transforms a AABB into another space; which will inherently grow the box. -//----------------------------------------------------------------------------- -void TransformAABB( const matrix3x4_t &in1, const Vector &vecMinsIn, const Vector &vecMaxsIn, Vector &vecMinsOut, Vector &vecMaxsOut ); - -//----------------------------------------------------------------------------- -// Uses the inverse transform of in1 -//----------------------------------------------------------------------------- -void ITransformAABB( const matrix3x4_t &in1, const Vector &vecMinsIn, const Vector &vecMaxsIn, Vector &vecMinsOut, Vector &vecMaxsOut ); - -//----------------------------------------------------------------------------- -// Rotates a AABB into another space; which will inherently grow the box. -// (same as TransformAABB, but doesn't take the translation into account) -//----------------------------------------------------------------------------- -void RotateAABB( const matrix3x4_t &in1, const Vector &vecMinsIn, const Vector &vecMaxsIn, Vector &vecMinsOut, Vector &vecMaxsOut ); - -//----------------------------------------------------------------------------- -// Uses the inverse transform of in1 -//----------------------------------------------------------------------------- -void IRotateAABB( const matrix3x4_t &in1, const Vector &vecMinsIn, const Vector &vecMaxsIn, Vector &vecMinsOut, Vector &vecMaxsOut ); - -//----------------------------------------------------------------------------- -// Transform a plane -//----------------------------------------------------------------------------- -inline void MatrixTransformPlane( const matrix3x4_t &src, const cplane_t &inPlane, cplane_t &outPlane ) -{ - // What we want to do is the following: - // 1) transform the normal into the new space. - // 2) Determine a point on the old plane given by plane dist * plane normal - // 3) Transform that point into the new space - // 4) Plane dist = DotProduct( new normal, new point ) - - // An optimized version, which works if the plane is orthogonal. - // 1) Transform the normal into the new space - // 2) Realize that transforming the old plane point into the new space - // is given by [ d * n'x + Tx, d * n'y + Ty, d * n'z + Tz ] - // where d = old plane dist, n' = transformed normal, Tn = translational component of transform - // 3) Compute the new plane dist using the dot product of the normal result of #2 - - // For a correct result, this should be an inverse-transpose matrix - // but that only matters if there are nonuniform scale or skew factors in this matrix. - VectorRotate( inPlane.normal, src, outPlane.normal ); - outPlane.dist = inPlane.dist * DotProduct( outPlane.normal, outPlane.normal ); - outPlane.dist += outPlane.normal.x * src[0][3] + outPlane.normal.y * src[1][3] + outPlane.normal.z * src[2][3]; -} - -inline void MatrixITransformPlane( const matrix3x4_t &src, const cplane_t &inPlane, cplane_t &outPlane ) -{ - // The trick here is that Tn = translational component of transform, - // but for an inverse transform, Tn = - R^-1 * T - Vector vecTranslation; - MatrixGetColumn( src, 3, vecTranslation ); - - Vector vecInvTranslation; - VectorIRotate( vecTranslation, src, vecInvTranslation ); - - VectorIRotate( inPlane.normal, src, outPlane.normal ); - outPlane.dist = inPlane.dist * DotProduct( outPlane.normal, outPlane.normal ); - outPlane.dist -= outPlane.normal.x * vecInvTranslation[0] + outPlane.normal.y * vecInvTranslation[1] + outPlane.normal.z * vecInvTranslation[2]; -} - -int CeilPow2( int in ); -int FloorPow2( int in ); - -FORCEINLINE float * UnpackNormal_HEND3N( const unsigned int *pPackedNormal, float *pNormal ) -{ - int temp[3]; - temp[0] = ((*pPackedNormal >> 0L) & 0x7ff); - if ( temp[0] & 0x400 ) - { - temp[0] = 2048 - temp[0]; - } - temp[1] = ((*pPackedNormal >> 11L) & 0x7ff); - if ( temp[1] & 0x400 ) - { - temp[1] = 2048 - temp[1]; - } - temp[2] = ((*pPackedNormal >> 22L) & 0x3ff); - if ( temp[2] & 0x200 ) - { - temp[2] = 1024 - temp[2]; - } - pNormal[0] = (float)temp[0] * 1.0f/1023.0f; - pNormal[1] = (float)temp[1] * 1.0f/1023.0f; - pNormal[2] = (float)temp[2] * 1.0f/511.0f; - return pNormal; -} - -FORCEINLINE unsigned int * PackNormal_HEND3N( const float *pNormal, unsigned int *pPackedNormal ) -{ - int temp[3]; - - temp[0] = Float2Int( pNormal[0] * 1023.0f ); - temp[1] = Float2Int( pNormal[1] * 1023.0f ); - temp[2] = Float2Int( pNormal[2] * 511.0f ); - - // the normal is out of bounds, determine the source and fix - // clamping would be even more of a slowdown here - Assert( temp[0] >= -1023 && temp[0] <= 1023 ); - Assert( temp[1] >= -1023 && temp[1] <= 1023 ); - Assert( temp[2] >= -511 && temp[2] <= 511 ); - - *pPackedNormal = ( ( temp[2] & 0x3ff ) << 22L ) | - ( ( temp[1] & 0x7ff ) << 11L ) | - ( ( temp[0] & 0x7ff ) << 0L ); - return pPackedNormal; -} - -FORCEINLINE unsigned int * PackNormal_HEND3N( float nx, float ny, float nz, unsigned int *pPackedNormal ) -{ - int temp[3]; - - temp[0] = Float2Int( nx * 1023.0f ); - temp[1] = Float2Int( ny * 1023.0f ); - temp[2] = Float2Int( nz * 511.0f ); - - // the normal is out of bounds, determine the source and fix - // clamping would be even more of a slowdown here - Assert( temp[0] >= -1023 && temp[0] <= 1023 ); - Assert( temp[1] >= -1023 && temp[1] <= 1023 ); - Assert( temp[2] >= -511 && temp[2] <= 511 ); - - *pPackedNormal = ( ( temp[2] & 0x3ff ) << 22L ) | - ( ( temp[1] & 0x7ff ) << 11L ) | - ( ( temp[0] & 0x7ff ) << 0L ); - return pPackedNormal; -} - -FORCEINLINE float * UnpackNormal_SHORT2( const unsigned int *pPackedNormal, float *pNormal, bool bIsTangent = FALSE ) -{ - // Unpacks from Jason's 2-short format (fills in a 4th binormal-sign (+1/-1) value, if this is a tangent vector) - - // FIXME: short math is slow on 360 - use ints here instead (bit-twiddle to deal w/ the sign bits) - short iX = (*pPackedNormal & 0x0000FFFF); - short iY = (*pPackedNormal & 0xFFFF0000) >> 16; - - float zSign = +1; - if ( iX < 0 ) - { - zSign = -1; - iX = -iX; - } - float tSign = +1; - if ( iY < 0 ) - { - tSign = -1; - iY = -iY; - } - - pNormal[0] = ( iX - 16384.0f ) / 16384.0f; - pNormal[1] = ( iY - 16384.0f ) / 16384.0f; - pNormal[2] = zSign*sqrtf( 1.0f - ( pNormal[0]*pNormal[0] + pNormal[1]*pNormal[1] ) ); - if ( bIsTangent ) - { - pNormal[3] = tSign; - } - - return pNormal; -} - -FORCEINLINE unsigned int * PackNormal_SHORT2( float nx, float ny, float nz, unsigned int *pPackedNormal, float binormalSign = +1.0f ) -{ - // Pack a vector (ASSUMED TO BE NORMALIZED) into Jason's 4-byte (SHORT2) format. - // This simply reconstructs Z from X & Y. It uses the sign bits of the X & Y coords - // to reconstruct the sign of Z and, if this is a tangent vector, the sign of the - // binormal (this is needed because tangent/binormal vectors are supposed to follow - // UV gradients, but shaders reconstruct the binormal from the tangent and normal - // assuming that they form a right-handed basis). - - nx += 1; // [-1,+1] -> [0,2] - ny += 1; - nx *= 16384.0f; // [ 0, 2] -> [0,32768] - ny *= 16384.0f; - - // '0' and '32768' values are invalid encodings - nx = MAX( nx, 1.0f ); // Make sure there are no zero values - ny = MAX( ny, 1.0f ); - nx = MIN( nx, 32767.0f ); // Make sure there are no 32768 values - ny = MIN( ny, 32767.0f ); - - if ( nz < 0.0f ) - nx = -nx; // Set the sign bit for z - - ny *= binormalSign; // Set the sign bit for the binormal (use when encoding a tangent vector) - - // FIXME: short math is slow on 360 - use ints here instead (bit-twiddle to deal w/ the sign bits), also use Float2Int() - short sX = (short)nx; // signed short [1,32767] - short sY = (short)ny; - - *pPackedNormal = ( sX & 0x0000FFFF ) | ( sY << 16 ); // NOTE: The mask is necessary (if sX is negative and cast to an int...) - - return pPackedNormal; -} - -FORCEINLINE unsigned int * PackNormal_SHORT2( const float *pNormal, unsigned int *pPackedNormal, float binormalSign = +1.0f ) -{ - return PackNormal_SHORT2( pNormal[0], pNormal[1], pNormal[2], pPackedNormal, binormalSign ); -} - -// Unpacks a UBYTE4 normal (for a tangent, the result's fourth component receives the binormal 'sign') -FORCEINLINE float * UnpackNormal_UBYTE4( const unsigned int *pPackedNormal, float *pNormal, bool bIsTangent = FALSE ) -{ - unsigned char cX, cY; - if ( bIsTangent ) - { - cX = *pPackedNormal >> 16; // Unpack Z - cY = *pPackedNormal >> 24; // Unpack W - } - else - { - cX = *pPackedNormal >> 0; // Unpack X - cY = *pPackedNormal >> 8; // Unpack Y - } - - float x = cX - 128.0f; - float y = cY - 128.0f; - float z; - - float zSignBit = x < 0 ? 1.0f : 0.0f; // z and t negative bits (like slt asm instruction) - float tSignBit = y < 0 ? 1.0f : 0.0f; - float zSign = -( 2*zSignBit - 1 ); // z and t signs - float tSign = -( 2*tSignBit - 1 ); - - x = x*zSign - zSignBit; // 0..127 - y = y*tSign - tSignBit; - x = x - 64; // -64..63 - y = y - 64; - - float xSignBit = x < 0 ? 1.0f : 0.0f; // x and y negative bits (like slt asm instruction) - float ySignBit = y < 0 ? 1.0f : 0.0f; - float xSign = -( 2*xSignBit - 1 ); // x and y signs - float ySign = -( 2*ySignBit - 1 ); - - x = ( x*xSign - xSignBit ) / 63.0f; // 0..1 range - y = ( y*ySign - ySignBit ) / 63.0f; - z = 1.0f - x - y; - - float oolen = 1.0f / sqrt( x*x + y*y + z*z ); // Normalize and - x *= oolen * xSign; // Recover signs - y *= oolen * ySign; - z *= oolen * zSign; - - pNormal[0] = x; - pNormal[1] = y; - pNormal[2] = z; - if ( bIsTangent ) - { - pNormal[3] = tSign; - } - - return pNormal; -} - -////////////////////////////////////////////////////////////////////////////// -// See: http://www.oroboro.com/rafael/docserv.php/index/programming/article/unitv2 -// -// UBYTE4 encoding, using per-octant projection onto x+y+z=1 -// Assume input vector is already unit length -// -// binormalSign specifies 'sign' of binormal, stored in t sign bit of tangent -// (lets the shader know whether norm/tan/bin form a right-handed basis) -// -// bIsTangent is used to specify which WORD of the output to store the data -// The expected usage is to call once with the normal and once with -// the tangent and binormal sign flag, bitwise OR'ing the returned DWORDs -FORCEINLINE unsigned int * PackNormal_UBYTE4( float nx, float ny, float nz, unsigned int *pPackedNormal, bool bIsTangent = false, float binormalSign = +1.0f ) -{ - float xSign = nx < 0.0f ? -1.0f : 1.0f; // -1 or 1 sign - float ySign = ny < 0.0f ? -1.0f : 1.0f; - float zSign = nz < 0.0f ? -1.0f : 1.0f; - float tSign = binormalSign; - Assert( ( binormalSign == +1.0f ) || ( binormalSign == -1.0f ) ); - - float xSignBit = 0.5f*( 1 - xSign ); // [-1,+1] -> [1,0] - float ySignBit = 0.5f*( 1 - ySign ); // 1 is negative bit (like slt instruction) - float zSignBit = 0.5f*( 1 - zSign ); - float tSignBit = 0.5f*( 1 - binormalSign ); - - float absX = xSign*nx; // 0..1 range (abs) - float absY = ySign*ny; - float absZ = zSign*nz; - - float xbits = absX / ( absX + absY + absZ ); // Project onto x+y+z=1 plane - float ybits = absY / ( absX + absY + absZ ); - - xbits *= 63; // 0..63 - ybits *= 63; - - xbits = xbits * xSign - xSignBit; // -64..63 range - ybits = ybits * ySign - ySignBit; - xbits += 64.0f; // 0..127 range - ybits += 64.0f; - - xbits = xbits * zSign - zSignBit; // Negate based on z and t - ybits = ybits * tSign - tSignBit; // -128..127 range - - xbits += 128.0f; // 0..255 range - ybits += 128.0f; - - unsigned char cX = (unsigned char) xbits; - unsigned char cY = (unsigned char) ybits; - - if ( !bIsTangent ) - *pPackedNormal = (cX << 0) | (cY << 8); // xy for normal - else - *pPackedNormal = (cX << 16) | (cY << 24); // zw for tangent - - return pPackedNormal; -} - -FORCEINLINE unsigned int * PackNormal_UBYTE4( const float *pNormal, unsigned int *pPackedNormal, bool bIsTangent = false, float binormalSign = +1.0f ) -{ - return PackNormal_UBYTE4( pNormal[0], pNormal[1], pNormal[2], pPackedNormal, bIsTangent, binormalSign ); -} - - -//----------------------------------------------------------------------------- -// Convert RGB to HSV -//----------------------------------------------------------------------------- -void RGBtoHSV( const Vector &rgb, Vector &hsv ); - - -//----------------------------------------------------------------------------- -// Convert HSV to RGB -//----------------------------------------------------------------------------- -void HSVtoRGB( const Vector &hsv, Vector &rgb ); - - - -#endif // MATH_BASE_H - diff --git a/public/mathlib/noise.h b/public/mathlib/noise.h deleted file mode 100644 index 0300363a6..000000000 --- a/public/mathlib/noise.h +++ /dev/null @@ -1,35 +0,0 @@ -//========= Copyright 1996-2006, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=====================================================================================// - -#ifndef NOISE_H -#define NOISE_H - -#include -#include "basetypes.h" -#include "mathlib/vector.h" -#include "tier0/dbg.h" - - -// The following code is the c-ification of Ken Perlin's new noise algorithm -// "JAVA REFERENCE IMPLEMENTATION OF IMPROVED NOISE - COPYRIGHT 2002 KEN PERLIN" -// as available here: http://mrl.nyu.edu/~perlin/noise/ -// it generates a single octave of noise in the -1..1 range -// this should at some point probably replace SparseConvolutionNoise - jd -float ImprovedPerlinNoise( Vector const &pnt ); - -// get the noise value at a point. Output range is 0..1. -float SparseConvolutionNoise( Vector const &pnt ); - -// get the noise value at a point, passing a custom noise shaping function. The noise shaping -// function should map the domain 0..1 to 0..1. -float SparseConvolutionNoise(Vector const &pnt, float (*pNoiseShapeFunction)(float) ); - -// returns a 1/f noise. more octaves take longer -float FractalNoise( Vector const &pnt, int n_octaves ); - -// returns a abs(f)*1/f noise i.e. turbulence -float Turbulence( Vector const &pnt, int n_octaves ); -#endif // NOISE_H diff --git a/public/mathlib/polyhedron.h b/public/mathlib/polyhedron.h deleted file mode 100644 index cf0199761..000000000 --- a/public/mathlib/polyhedron.h +++ /dev/null @@ -1,73 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef POLYHEDRON_H_ -#define POLYHEDRON_H_ - -#ifdef _WIN32 -#pragma once -#endif - -#include "mathlib/mathlib.h" - - - -struct Polyhedron_IndexedLine_t -{ - unsigned short iPointIndices[2]; -}; - -struct Polyhedron_IndexedLineReference_t -{ - unsigned short iLineIndex; - unsigned char iEndPointIndex; //since two polygons reference any one line, one needs to traverse the line backwards, this flags that behavior -}; - -struct Polyhedron_IndexedPolygon_t -{ - unsigned short iFirstIndex; - unsigned short iIndexCount; - Vector polyNormal; -}; - -class CPolyhedron //made into a class because it's going virtual to support distinctions between temp and permanent versions -{ -public: - Vector *pVertices; - Polyhedron_IndexedLine_t *pLines; - Polyhedron_IndexedLineReference_t *pIndices; - Polyhedron_IndexedPolygon_t *pPolygons; - - unsigned short iVertexCount; - unsigned short iLineCount; - unsigned short iIndexCount; - unsigned short iPolygonCount; - - virtual ~CPolyhedron( void ) {}; - virtual void Release( void ) = 0; - Vector Center( void ); -}; - -class CPolyhedron_AllocByNew : public CPolyhedron -{ -public: - virtual void Release( void ); - static CPolyhedron_AllocByNew *Allocate( unsigned short iVertices, unsigned short iLines, unsigned short iIndices, unsigned short iPolygons ); //creates the polyhedron along with enough memory to hold all it's data in a single allocation - -private: - CPolyhedron_AllocByNew( void ) { }; //CPolyhedron_AllocByNew::Allocate() is the only way to create one of these. -}; - -CPolyhedron *GeneratePolyhedronFromPlanes( const float *pOutwardFacingPlanes, int iPlaneCount, float fOnPlaneEpsilon, bool bUseTemporaryMemory = false ); //be sure to polyhedron->Release() -CPolyhedron *ClipPolyhedron( const CPolyhedron *pExistingPolyhedron, const float *pOutwardFacingPlanes, int iPlaneCount, float fOnPlaneEpsilon, bool bUseTemporaryMemory = false ); //this does NOT modify/delete the existing polyhedron - -CPolyhedron *GetTempPolyhedron( unsigned short iVertices, unsigned short iLines, unsigned short iIndices, unsigned short iPolygons ); //grab the temporary polyhedron. Avoids new/delete for quick work. Can only be in use by one chunk of code at a time - - -#endif //#ifndef POLYHEDRON_H_ - diff --git a/public/mathlib/quantize.h b/public/mathlib/quantize.h deleted file mode 100644 index af9618f94..000000000 --- a/public/mathlib/quantize.h +++ /dev/null @@ -1,141 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef QUANTIZE_H -#define QUANTIZE_H - -#ifndef STRING_H -#include -#endif - -#define MAXDIMS 768 -#define MAXQUANT 16000 - - -#include - -struct Sample; - -struct QuantizedValue { - double MinError; // minimum possible error. used - // for neighbor searches. - struct QuantizedValue *Children[2]; // splits - int32 value; // only exists for leaf nodes - struct Sample *Samples; // every sample quantized into this - // entry - int32 NSamples; // how many were quantized to this. - int32 TotSamples; - double *ErrorMeasure; // variance measure for each dimension - double TotalError; // sum of errors - uint8 *Mean; // average value of each dimension - uint8 *Mins; // min box for children and this - uint8 *Maxs; // max box for children and this - int NQuant; // the number of samples which were - // quantzied to this node since the - // last time OptimizeQuantizer() - // was called. - int *Sums; // sum used by OptimizeQuantizer - int sortdim; // dimension currently sorted along. -}; - -struct Sample { - int32 ID; // identifier of this sample. can - // be used for any purpose. - int32 Count; // number of samples this sample - // represents - int32 QNum; // what value this sample ended up quantized - // to. - struct QuantizedValue *qptr; // ptr to what this was quantized to. - uint8 Value[1]; // array of values for multi-dimensional - // variables. -}; - -void FreeQuantization(struct QuantizedValue *t); - -struct QuantizedValue *Quantize(struct Sample *s, int nsamples, int ndims, - int nvalues, uint8 *weights, int value0=0); - -int CompressSamples(struct Sample *s, int nsamples, int ndims); - -struct QuantizedValue *FindMatch(uint8 const *sample, - int ndims,uint8 *weights, - struct QuantizedValue *QTable); -void PrintSamples(struct Sample const *s, int nsamples, int ndims); - -struct QuantizedValue *FindQNode(struct QuantizedValue const *q, int32 code); - -inline struct Sample *NthSample(struct Sample *s, int i, int nd) -{ - uint8 *r=(uint8 *) s; - r+=i*(sizeof(*s)+(nd-1)); - return (struct Sample *) r; -} - -inline struct Sample *AllocSamples(int ns, int nd) -{ - size_t size5=(sizeof(struct Sample)+(nd-1))*ns; - void *ret=new uint8[size5]; - memset(ret,0,size5); - for(int i=0;iCount=1; - return (struct Sample *) ret; -} - - -// MinimumError: what is the min error which will occur if quantizing -// a sample to the given qnode? This is just the error if the qnode -// is a leaf. -double MinimumError(struct QuantizedValue const *q, uint8 const *sample, - int ndims, uint8 const *weights); -double MaximumError(struct QuantizedValue const *q, uint8 const *sample, - int ndims, uint8 const *weights); - -void PrintQTree(struct QuantizedValue const *p,int idlevel=0); -void OptimizeQuantizer(struct QuantizedValue *q, int ndims); - -// RecalculateVelues: update the means in a sample tree, based upon -// the samples. can be used to reoptimize when samples are deleted, -// for instance. - -void RecalculateValues(struct QuantizedValue *q, int ndims); - -extern double SquaredError; // may be reset and examined. updated by - // FindMatch() - - - - -// the routines below can be used for uniform quantization via dart-throwing. -typedef void (*GENERATOR)(void *); // generate a random sample -typedef double (*COMPARER)(void const *a, void const *b); - -void *DartThrow(int NResults, int NTries, size_t itemsize, GENERATOR gen, - COMPARER cmp); -void *FindClosestDart(void *items,int NResults, size_t itemsize, - COMPARER cmp, void *lookfor, int *idx); - - - - -// color quantization of 24 bit images -#define QUANTFLAGS_NODITHER 1 // don't do Floyd-steinberg dither - -extern void ColorQuantize( -uint8 const *pImage, // 4 byte pixels ARGB -int nWidth, -int nHeight, -int nFlags, // QUANTFLAGS_xxx -int nColors, // # of colors to fill in in palette -uint8 *pOutPixels, // where to store resulting 8 bit pixels -uint8 *pOutPalette, // where to store resulting 768-byte palette -int nFirstColor); // first color to use in mapping - - - - - -#endif diff --git a/public/mathlib/simdvectormatrix.h b/public/mathlib/simdvectormatrix.h deleted file mode 100644 index 9f5267e6b..000000000 --- a/public/mathlib/simdvectormatrix.h +++ /dev/null @@ -1,142 +0,0 @@ -//====== Copyright 1996-2006, Valve Corporation, All rights reserved. =======// -// -// Purpose: Provide a class (SSE/SIMD only) holding a 2d matrix of class FourVectors, -// for high speed processing in tools. -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef SIMDVECTORMATRIX_H -#define SIMDVECTORMATRIX_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include -#include "tier0/platform.h" -#include "tier0/dbg.h" -#include "tier1/utlsoacontainer.h" -#include "mathlib/ssemath.h" - -class CSIMDVectorMatrix -{ -public: - int m_nWidth; // in actual vectors - int m_nHeight; - - int m_nPaddedWidth; // # of 4x wide elements - - FourVectors *m_pData; - -protected: - void Init( void ) - { - m_pData = NULL; - m_nWidth = 0; - m_nHeight = 0; - m_nPaddedWidth = 0; - } - - int NVectors( void ) const - { - return m_nHeight * m_nPaddedWidth; - } - -public: - // constructors and destructors - CSIMDVectorMatrix( void ) - { - Init(); - } - - ~CSIMDVectorMatrix( void ) - { - if ( m_pData ) - delete[] m_pData; - } - - // set up storage and fields for m x n matrix. destroys old data - void SetSize( int width, int height ) - { - if ( ( ! m_pData ) || ( width != m_nWidth ) || ( height != m_nHeight ) ) - { - if ( m_pData ) - delete[] m_pData; - - m_nWidth = width; - m_nHeight = height; - - m_nPaddedWidth = ( m_nWidth + 3) >> 2; - m_pData = NULL; - if ( width && height ) - m_pData = new FourVectors[ m_nPaddedWidth * m_nHeight ]; - } - } - - CSIMDVectorMatrix( int width, int height ) - { - Init(); - SetSize( width, height ); - } - - CSIMDVectorMatrix &operator=( CSIMDVectorMatrix const &src ) - { - SetSize( src.m_nWidth, src.m_nHeight ); - if ( m_pData ) - memcpy( m_pData, src.m_pData, m_nHeight*m_nPaddedWidth*sizeof(m_pData[0]) ); - return *this; - } - - CSIMDVectorMatrix &operator+=( CSIMDVectorMatrix const &src ); - - CSIMDVectorMatrix &operator*=( Vector const &src ); - - // create from an RGBA float bitmap. alpha ignored. - void CreateFromRGBA_FloatImageData(int srcwidth, int srcheight, float const *srcdata ); - - // create from 3 fields in a csoa - void CreateFromCSOAAttributes( CSOAContainer const *pSrc, - int nAttrIdx0, int nAttrIdx1, int nAttrIdx2 ); - - // Element access. If you are calling this a lot, you don't want to use this class, because - // you're not getting the sse advantage - Vector Element(int x, int y) const - { - Assert( m_pData ); - Assert( x < m_nWidth ); - Assert( y < m_nHeight ); - Vector ret; - FourVectors const *pData=m_pData+y*m_nPaddedWidth+(x >> 2); - - int xo=(x & 3); - ret.x=pData->X( xo ); - ret.y=pData->Y( xo ); - ret.z=pData->Z( xo ); - return ret; - } - - //addressing the individual fourvectors elements - FourVectors &CompoundElement(int x, int y) - { - Assert( m_pData ); - Assert( y < m_nHeight ); - Assert( x < m_nPaddedWidth ); - return m_pData[x + m_nPaddedWidth*y ]; - } - - // math operations on the whole image - void Clear( void ) - { - Assert( m_pData ); - memset( m_pData, 0, m_nHeight*m_nPaddedWidth*sizeof(m_pData[0]) ); - } - - void RaiseToPower( float power ); -}; - - - -#endif diff --git a/public/mathlib/spherical_geometry.h b/public/mathlib/spherical_geometry.h deleted file mode 100644 index c05302180..000000000 --- a/public/mathlib/spherical_geometry.h +++ /dev/null @@ -1,73 +0,0 @@ -//====== Copyright 2007-2007, Valve Corporation, All rights reserved. =======// -// -// Purpose: Functions for spherical geometry. -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef SPHERICAL_GEOMETRY_H -#define SPHERICAL_GEOMETRY_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -// see http://mathworld.wolfram.com/SphericalTrigonometry.html - -// return the spherical distance, in radians, between 2 points on the unit sphere. -FORCEINLINE float UnitSphereLineSegmentLength( Vector const &a, Vector const &b ) -{ - // check unit length - Assert( fabs( VectorLength( a ) - 1.0 ) < 1.0e-3 ); - Assert( fabs( VectorLength( b ) - 1.0 ) < 1.0e-3 ); - return acos( DotProduct( a, b ) ); -} - - -// given 3 points on the unit sphere, return the spherical area (in radians) of the triangle they form. -// valid for "small" triangles. -FORCEINLINE float UnitSphereTriangleArea( Vector const &a, Vector const &b , Vector const &c ) -{ - float flLengthA = UnitSphereLineSegmentLength( b, c ); - float flLengthB = UnitSphereLineSegmentLength( c, a ); - float flLengthC = UnitSphereLineSegmentLength( a, b ); - - if ( ( flLengthA == 0. ) || ( flLengthB == 0. ) || ( flLengthC == 0. ) ) - return 0.; // zero area triangle - - // now, find the 3 incribed angles for the triangle - float flHalfSumLens = 0.5 * ( flLengthA + flLengthB + flLengthC ); - float flSinSums = sin( flHalfSumLens ); - float flSinSMinusA= sin( flHalfSumLens - flLengthA ); - float flSinSMinusB= sin( flHalfSumLens - flLengthB ); - float flSinSMinusC= sin( flHalfSumLens - flLengthC ); - - float flTanAOver2 = sqrt ( ( flSinSMinusB * flSinSMinusC ) / ( flSinSums * flSinSMinusA ) ); - float flTanBOver2 = sqrt ( ( flSinSMinusA * flSinSMinusC ) / ( flSinSums * flSinSMinusB ) ); - float flTanCOver2 = sqrt ( ( flSinSMinusA * flSinSMinusB ) / ( flSinSums * flSinSMinusC ) ); - - // Girards formula : area = sum of angles - pi. - return 2.0 * ( atan( flTanAOver2 ) + atan( flTanBOver2 ) + atan( flTanCOver2 ) ) - M_PI; -} - -// spherical harmonics-related functions. Best explanation at http://www.research.scea.com/gdc2003/spherical-harmonic-lighting.pdf - -// Evaluate associated legendre polynomial P( l, m ) at flX, using recurrence relation -float AssociatedLegendrePolynomial( int nL, int nM, float flX ); - -// Evaluate order N spherical harmonic with spherical coordinates -// nL = band, 0..N -// nM = -nL .. nL -// theta = 0..M_PI -// phi = 0.. 2 * M_PHI -float SphericalHarmonic( int nL, int nM, float flTheta, float flPhi ); - -// evaluate spherical harmonic with normalized vector direction -float SphericalHarmonic( int nL, int nM, Vector const &vecDirection ); - - -#endif // SPHERICAL_GEOMETRY_H diff --git a/public/mathlib/ssemath.h b/public/mathlib/ssemath.h deleted file mode 100644 index 0243a9eef..000000000 --- a/public/mathlib/ssemath.h +++ /dev/null @@ -1,3098 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: - defines SIMD "structure of arrays" classes and functions. -// -//===========================================================================// -#ifndef SSEMATH_H -#define SSEMATH_H - -#if defined( _X360 ) -#include -#else -#include -#endif - -#include -#include - -#if defined(_LINUX) || defined(__APPLE__) -#define USE_STDC_FOR_SIMD 0 -#else -#define USE_STDC_FOR_SIMD 0 -#endif - -#if (!defined(_X360) && (USE_STDC_FOR_SIMD == 0)) -#define _SSE1 1 -#endif - -// I thought about defining a class/union for the SIMD packed floats instead of using fltx4, -// but decided against it because (a) the nature of SIMD code which includes comparisons is to blur -// the relationship between packed floats and packed integer types and (b) not sure that the -// compiler would handle generating good code for the intrinsics. - -#if USE_STDC_FOR_SIMD - -typedef union -{ - float m128_f32[4]; - uint32 m128_u32[4]; -} fltx4; - -typedef fltx4 i32x4; -typedef fltx4 u32x4; - -#elif ( defined( _X360 ) ) - -typedef union -{ - // This union allows float/int access (which generally shouldn't be done in inner loops) - __vector4 vmx; - float m128_f32[4]; - uint32 m128_u32[4]; -} fltx4_union; - -typedef __vector4 fltx4; -typedef __vector4 i32x4; // a VMX register; just a way of making it explicit that we're doing integer ops. -typedef __vector4 u32x4; // a VMX register; just a way of making it explicit that we're doing unsigned integer ops. - -#else - -typedef __m128 fltx4; -typedef __m128 i32x4; -typedef __m128 u32x4; - -#endif - -// The FLTX4 type is a fltx4 used as a parameter to a function. -// On the 360, the best way to do this is pass-by-copy on the registers. -// On the PC, the best way is to pass by const reference. -// The compiler will sometimes, but not always, replace a pass-by-const-ref -// with a pass-in-reg on the 360; to avoid this confusion, you can -// explicitly use a FLTX4 as the parameter type. -#ifdef _X360 -typedef __vector4 FLTX4; -#else -typedef const fltx4 & FLTX4; -#endif - -// A 16-byte aligned int32 datastructure -// (for use when writing out fltx4's as SIGNED -// ints). -struct ALIGN16 intx4 -{ - int32 m_i32[4]; - - inline int & operator[](int which) - { - return m_i32[which]; - } - - inline const int & operator[](int which) const - { - return m_i32[which]; - } - - inline int32 *Base() { - return m_i32; - } - - inline const int32 *Base() const - { - return m_i32; - } - - inline const bool operator==(const intx4 &other) const - { - return m_i32[0] == other.m_i32[0] && - m_i32[1] == other.m_i32[1] && - m_i32[2] == other.m_i32[2] && - m_i32[3] == other.m_i32[3] ; - } -}; - - -#if defined( _DEBUG ) && defined( _X360 ) -FORCEINLINE void TestVPUFlags() -{ - // Check that the VPU is in the appropriate (Java-compliant) mode (see 3.2.1 in altivec_pem.pdf on xds.xbox.com) - __vector4 a; - __asm - { - mfvscr a; - } - unsigned int * flags = (unsigned int *)&a; - unsigned int controlWord = flags[3]; - Assert(controlWord == 0); -} -#else // _DEBUG -FORCEINLINE void TestVPUFlags() {} -#endif // _DEBUG - - -// useful constants in SIMD packed float format: -// (note: some of these aren't stored on the 360, -// but are manufactured directly in one or two -// instructions, saving a load and possible L2 -// miss.) -#ifndef _X360 -extern const fltx4 Four_Zeros; // 0 0 0 0 -extern const fltx4 Four_Ones; // 1 1 1 1 -extern const fltx4 Four_Twos; // 2 2 2 2 -extern const fltx4 Four_Threes; // 3 3 3 3 -extern const fltx4 Four_Fours; // guess. -extern const fltx4 Four_Point225s; // .225 .225 .225 .225 -extern const fltx4 Four_PointFives; // .5 .5 .5 .5 -extern const fltx4 Four_Epsilons; // FLT_EPSILON FLT_EPSILON FLT_EPSILON FLT_EPSILON -extern const fltx4 Four_2ToThe21s; // (1<<21).. -extern const fltx4 Four_2ToThe22s; // (1<<22).. -extern const fltx4 Four_2ToThe23s; // (1<<23).. -extern const fltx4 Four_2ToThe24s; // (1<<24).. -extern const fltx4 Four_Origin; // 0 0 0 1 (origin point, like vr0 on the PS2) -extern const fltx4 Four_NegativeOnes; // -1 -1 -1 -1 -#else -#define Four_Zeros XMVectorZero() // 0 0 0 0 -#define Four_Ones XMVectorSplatOne() // 1 1 1 1 -extern const fltx4 Four_Twos; // 2 2 2 2 -extern const fltx4 Four_Threes; // 3 3 3 3 -extern const fltx4 Four_Fours; // guess. -extern const fltx4 Four_Point225s; // .225 .225 .225 .225 -extern const fltx4 Four_PointFives; // .5 .5 .5 .5 -extern const fltx4 Four_Epsilons; // FLT_EPSILON FLT_EPSILON FLT_EPSILON FLT_EPSILON -extern const fltx4 Four_2ToThe21s; // (1<<21).. -extern const fltx4 Four_2ToThe22s; // (1<<22).. -extern const fltx4 Four_2ToThe23s; // (1<<23).. -extern const fltx4 Four_2ToThe24s; // (1<<24).. -extern const fltx4 Four_Origin; // 0 0 0 1 (origin point, like vr0 on the PS2) -extern const fltx4 Four_NegativeOnes; // -1 -1 -1 -1 -#endif -extern const fltx4 Four_FLT_MAX; // FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX -extern const fltx4 Four_Negative_FLT_MAX; // -FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX -extern const fltx4 g_SIMD_0123; // 0 1 2 3 as float - -// external aligned integer constants -extern const ALIGN16 int32 g_SIMD_clear_signmask[]; // 0x7fffffff x 4 -extern const ALIGN16 int32 g_SIMD_signmask[]; // 0x80000000 x 4 -extern const ALIGN16 int32 g_SIMD_lsbmask[]; // 0xfffffffe x 4 -extern const ALIGN16 int32 g_SIMD_clear_wmask[]; // -1 -1 -1 0 -extern const ALIGN16 int32 g_SIMD_ComponentMask[4][4]; // [0xFFFFFFFF 0 0 0], [0 0xFFFFFFFF 0 0], [0 0 0xFFFFFFFF 0], [0 0 0 0xFFFFFFFF] -extern const ALIGN16 int32 g_SIMD_AllOnesMask[]; // ~0,~0,~0,~0 -extern const ALIGN16 int32 g_SIMD_Low16BitsMask[]; // 0xffff x 4 - -// this mask is used for skipping the tail of things. If you have N elements in an array, and wish -// to mask out the tail, g_SIMD_SkipTailMask[N & 3] what you want to use for the last iteration. -extern const int32 ALIGN16 g_SIMD_SkipTailMask[4][4]; - -// Define prefetch macros. -// The characteristics of cache and prefetch are completely -// different between the different platforms, so you DO NOT -// want to just define one macro that maps to every platform -// intrinsic under the hood -- you need to prefetch at different -// intervals between x86 and PPC, for example, and that is -// a higher level code change. -// On the other hand, I'm tired of typing #ifdef _X360 -// all over the place, so this is just a nop on Intel, PS3. -#ifdef _X360 -#define PREFETCH360(address, offset) __dcbt(offset,address) -#else -#define PREFETCH360(x,y) // nothing -#endif - -#if USE_STDC_FOR_SIMD - -//--------------------------------------------------------------------- -// Standard C (fallback/Linux) implementation (only there for compat - slow) -//--------------------------------------------------------------------- - -FORCEINLINE float SubFloat( const fltx4 & a, int idx ) -{ - return a.m128_f32[ idx ]; -} - -FORCEINLINE float & SubFloat( fltx4 & a, int idx ) -{ - return a.m128_f32[idx]; -} - -FORCEINLINE uint32 SubInt( const fltx4 & a, int idx ) -{ - return a.m128_u32[idx]; -} - -FORCEINLINE uint32 & SubInt( fltx4 & a, int idx ) -{ - return a.m128_u32[idx]; -} - -// Return one in the fastest way -- on the x360, faster even than loading. -FORCEINLINE fltx4 LoadZeroSIMD( void ) -{ - return Four_Zeros; -} - -// Return one in the fastest way -- on the x360, faster even than loading. -FORCEINLINE fltx4 LoadOneSIMD( void ) -{ - return Four_Ones; -} - -FORCEINLINE fltx4 SplatXSIMD( const fltx4 & a ) -{ - fltx4 retVal; - SubFloat( retVal, 0 ) = SubFloat( a, 0 ); - SubFloat( retVal, 1 ) = SubFloat( a, 0 ); - SubFloat( retVal, 2 ) = SubFloat( a, 0 ); - SubFloat( retVal, 3 ) = SubFloat( a, 0 ); - return retVal; -} - -FORCEINLINE fltx4 SplatYSIMD( fltx4 a ) -{ - fltx4 retVal; - SubFloat( retVal, 0 ) = SubFloat( a, 1 ); - SubFloat( retVal, 1 ) = SubFloat( a, 1 ); - SubFloat( retVal, 2 ) = SubFloat( a, 1 ); - SubFloat( retVal, 3 ) = SubFloat( a, 1 ); - return retVal; -} - -FORCEINLINE fltx4 SplatZSIMD( fltx4 a ) -{ - fltx4 retVal; - SubFloat( retVal, 0 ) = SubFloat( a, 2 ); - SubFloat( retVal, 1 ) = SubFloat( a, 2 ); - SubFloat( retVal, 2 ) = SubFloat( a, 2 ); - SubFloat( retVal, 3 ) = SubFloat( a, 2 ); - return retVal; -} - -FORCEINLINE fltx4 SplatWSIMD( fltx4 a ) -{ - fltx4 retVal; - SubFloat( retVal, 0 ) = SubFloat( a, 3 ); - SubFloat( retVal, 1 ) = SubFloat( a, 3 ); - SubFloat( retVal, 2 ) = SubFloat( a, 3 ); - SubFloat( retVal, 3 ) = SubFloat( a, 3 ); - return retVal; -} - -FORCEINLINE fltx4 SetXSIMD( const fltx4& a, const fltx4& x ) -{ - fltx4 result = a; - SubFloat( result, 0 ) = SubFloat( x, 0 ); - return result; -} - -FORCEINLINE fltx4 SetYSIMD( const fltx4& a, const fltx4& y ) -{ - fltx4 result = a; - SubFloat( result, 1 ) = SubFloat( y, 1 ); - return result; -} - -FORCEINLINE fltx4 SetZSIMD( const fltx4& a, const fltx4& z ) -{ - fltx4 result = a; - SubFloat( result, 2 ) = SubFloat( z, 2 ); - return result; -} - -FORCEINLINE fltx4 SetWSIMD( const fltx4& a, const fltx4& w ) -{ - fltx4 result = a; - SubFloat( result, 3 ) = SubFloat( w, 3 ); - return result; -} - -FORCEINLINE fltx4 SetComponentSIMD( const fltx4& a, int nComponent, float flValue ) -{ - fltx4 result = a; - SubFloat( result, nComponent ) = flValue; - return result; -} - -// a b c d -> b c d a -FORCEINLINE fltx4 RotateLeft( const fltx4 & a ) -{ - fltx4 retVal; - SubFloat( retVal, 0 ) = SubFloat( a, 1 ); - SubFloat( retVal, 1 ) = SubFloat( a, 2 ); - SubFloat( retVal, 2 ) = SubFloat( a, 3 ); - SubFloat( retVal, 3 ) = SubFloat( a, 0 ); - return retVal; -} - -// a b c d -> c d a b -FORCEINLINE fltx4 RotateLeft2( const fltx4 & a ) -{ - fltx4 retVal; - SubFloat( retVal, 0 ) = SubFloat( a, 2 ); - SubFloat( retVal, 1 ) = SubFloat( a, 3 ); - SubFloat( retVal, 2 ) = SubFloat( a, 0 ); - SubFloat( retVal, 3 ) = SubFloat( a, 1 ); - return retVal; -} - -#define BINOP(op) \ - fltx4 retVal; \ - SubFloat( retVal, 0 ) = ( SubFloat( a, 0 ) op SubFloat( b, 0 ) ); \ - SubFloat( retVal, 1 ) = ( SubFloat( a, 1 ) op SubFloat( b, 1 ) ); \ - SubFloat( retVal, 2 ) = ( SubFloat( a, 2 ) op SubFloat( b, 2 ) ); \ - SubFloat( retVal, 3 ) = ( SubFloat( a, 3 ) op SubFloat( b, 3 ) ); \ - return retVal; - -#define IBINOP(op) \ - fltx4 retVal; \ - SubInt( retVal, 0 ) = ( SubInt( a, 0 ) op SubInt ( b, 0 ) ); \ - SubInt( retVal, 1 ) = ( SubInt( a, 1 ) op SubInt ( b, 1 ) ); \ - SubInt( retVal, 2 ) = ( SubInt( a, 2 ) op SubInt ( b, 2 ) ); \ - SubInt( retVal, 3 ) = ( SubInt( a, 3 ) op SubInt ( b, 3 ) ); \ - return retVal; - -FORCEINLINE fltx4 AddSIMD( const fltx4 & a, const fltx4 & b ) -{ - BINOP(+); -} - -FORCEINLINE fltx4 SubSIMD( const fltx4 & a, const fltx4 & b ) // a-b -{ - BINOP(-); -}; - -FORCEINLINE fltx4 MulSIMD( const fltx4 & a, const fltx4 & b ) // a*b -{ - BINOP(*); -} - -FORCEINLINE fltx4 DivSIMD( const fltx4 & a, const fltx4 & b ) // a/b -{ - BINOP(/); -} - - -FORCEINLINE fltx4 MaddSIMD( const fltx4 & a, const fltx4 & b, const fltx4 & c ) // a*b + c -{ - return AddSIMD( MulSIMD(a,b), c ); -} - -FORCEINLINE fltx4 MsubSIMD( const fltx4 & a, const fltx4 & b, const fltx4 & c ) // c - a*b -{ - return SubSIMD( c, MulSIMD(a,b) ); -}; - - -FORCEINLINE fltx4 SinSIMD( const fltx4 &radians ) -{ - fltx4 result; - SubFloat( result, 0 ) = sin( SubFloat( radians, 0 ) ); - SubFloat( result, 1 ) = sin( SubFloat( radians, 1 ) ); - SubFloat( result, 2 ) = sin( SubFloat( radians, 2 ) ); - SubFloat( result, 3 ) = sin( SubFloat( radians, 3 ) ); - return result; -} - -FORCEINLINE void SinCos3SIMD( fltx4 &sine, fltx4 &cosine, const fltx4 &radians ) -{ - SinCos( SubFloat( radians, 0 ), &SubFloat( sine, 0 ), &SubFloat( cosine, 0 ) ); - SinCos( SubFloat( radians, 1 ), &SubFloat( sine, 1 ), &SubFloat( cosine, 1 ) ); - SinCos( SubFloat( radians, 2 ), &SubFloat( sine, 2 ), &SubFloat( cosine, 2 ) ); -} - -FORCEINLINE void SinCosSIMD( fltx4 &sine, fltx4 &cosine, const fltx4 &radians ) -{ - SinCos( SubFloat( radians, 0 ), &SubFloat( sine, 0 ), &SubFloat( cosine, 0 ) ); - SinCos( SubFloat( radians, 1 ), &SubFloat( sine, 1 ), &SubFloat( cosine, 1 ) ); - SinCos( SubFloat( radians, 2 ), &SubFloat( sine, 2 ), &SubFloat( cosine, 2 ) ); - SinCos( SubFloat( radians, 3 ), &SubFloat( sine, 3 ), &SubFloat( cosine, 3 ) ); -} - -FORCEINLINE fltx4 ArcSinSIMD( const fltx4 &sine ) -{ - fltx4 result; - SubFloat( result, 0 ) = asin( SubFloat( sine, 0 ) ); - SubFloat( result, 1 ) = asin( SubFloat( sine, 1 ) ); - SubFloat( result, 2 ) = asin( SubFloat( sine, 2 ) ); - SubFloat( result, 3 ) = asin( SubFloat( sine, 3 ) ); - return result; -} - -FORCEINLINE fltx4 ArcCosSIMD( const fltx4 &cs ) -{ - fltx4 result; - SubFloat( result, 0 ) = acos( SubFloat( cs, 0 ) ); - SubFloat( result, 1 ) = acos( SubFloat( cs, 1 ) ); - SubFloat( result, 2 ) = acos( SubFloat( cs, 2 ) ); - SubFloat( result, 3 ) = acos( SubFloat( cs, 3 ) ); - return result; -} - -// tan^1(a/b) .. ie, pass sin in as a and cos in as b -FORCEINLINE fltx4 ArcTan2SIMD( const fltx4 &a, const fltx4 &b ) -{ - fltx4 result; - SubFloat( result, 0 ) = atan2( SubFloat( a, 0 ), SubFloat( b, 0 ) ); - SubFloat( result, 1 ) = atan2( SubFloat( a, 1 ), SubFloat( b, 1 ) ); - SubFloat( result, 2 ) = atan2( SubFloat( a, 2 ), SubFloat( b, 2 ) ); - SubFloat( result, 3 ) = atan2( SubFloat( a, 3 ), SubFloat( b, 3 ) ); - return result; -} - -FORCEINLINE fltx4 MaxSIMD( const fltx4 & a, const fltx4 & b ) // MAX(a,b) -{ - fltx4 retVal; - SubFloat( retVal, 0 ) = MAX( SubFloat( a, 0 ), SubFloat( b, 0 ) ); - SubFloat( retVal, 1 ) = MAX( SubFloat( a, 1 ), SubFloat( b, 1 ) ); - SubFloat( retVal, 2 ) = MAX( SubFloat( a, 2 ), SubFloat( b, 2 ) ); - SubFloat( retVal, 3 ) = MAX( SubFloat( a, 3 ), SubFloat( b, 3 ) ); - return retVal; -} - -FORCEINLINE fltx4 MinSIMD( const fltx4 & a, const fltx4 & b ) // MIN(a,b) -{ - fltx4 retVal; - SubFloat( retVal, 0 ) = MIN( SubFloat( a, 0 ), SubFloat( b, 0 ) ); - SubFloat( retVal, 1 ) = MIN( SubFloat( a, 1 ), SubFloat( b, 1 ) ); - SubFloat( retVal, 2 ) = MIN( SubFloat( a, 2 ), SubFloat( b, 2 ) ); - SubFloat( retVal, 3 ) = MIN( SubFloat( a, 3 ), SubFloat( b, 3 ) ); - return retVal; -} - -FORCEINLINE fltx4 AndSIMD( const fltx4 & a, const fltx4 & b ) // a & b -{ - IBINOP(&); -} - -FORCEINLINE fltx4 AndNotSIMD( const fltx4 & a, const fltx4 & b ) // ~a & b -{ - fltx4 retVal; - SubInt( retVal, 0 ) = ~SubInt( a, 0 ) & SubInt( b, 0 ); - SubInt( retVal, 1 ) = ~SubInt( a, 1 ) & SubInt( b, 1 ); - SubInt( retVal, 2 ) = ~SubInt( a, 2 ) & SubInt( b, 2 ); - SubInt( retVal, 3 ) = ~SubInt( a, 3 ) & SubInt( b, 3 ); - return retVal; -} - -FORCEINLINE fltx4 XorSIMD( const fltx4 & a, const fltx4 & b ) // a ^ b -{ - IBINOP(^); -} - -FORCEINLINE fltx4 OrSIMD( const fltx4 & a, const fltx4 & b ) // a | b -{ - IBINOP(|); -} - -FORCEINLINE fltx4 NegSIMD(const fltx4 &a) // negate: -a -{ - fltx4 retval; - SubFloat( retval, 0 ) = -SubFloat( a, 0 ); - SubFloat( retval, 1 ) = -SubFloat( a, 1 ); - SubFloat( retval, 2 ) = -SubFloat( a, 2 ); - SubFloat( retval, 3 ) = -SubFloat( a, 3 ); - - return retval; -} - -FORCEINLINE bool IsAllZeros( const fltx4 & a ) // all floats of a zero? -{ - return ( SubFloat( a, 0 ) == 0.0 ) && - ( SubFloat( a, 1 ) == 0.0 ) && - ( SubFloat( a, 2 ) == 0.0 ) && - ( SubFloat( a, 3 ) == 0.0 ) ; -} - - -// for branching when a.xyzw > b.xyzw -FORCEINLINE bool IsAllGreaterThan( const fltx4 &a, const fltx4 &b ) -{ - return SubFloat(a,0) > SubFloat(b,0) && - SubFloat(a,1) > SubFloat(b,1) && - SubFloat(a,2) > SubFloat(b,2) && - SubFloat(a,3) > SubFloat(b,3); -} - -// for branching when a.xyzw >= b.xyzw -FORCEINLINE bool IsAllGreaterThanOrEq( const fltx4 &a, const fltx4 &b ) -{ - return SubFloat(a,0) >= SubFloat(b,0) && - SubFloat(a,1) >= SubFloat(b,1) && - SubFloat(a,2) >= SubFloat(b,2) && - SubFloat(a,3) >= SubFloat(b,3); -} - -// For branching if all a.xyzw == b.xyzw -FORCEINLINE bool IsAllEqual( const fltx4 & a, const fltx4 & b ) -{ - return SubFloat(a,0) == SubFloat(b,0) && - SubFloat(a,1) == SubFloat(b,1) && - SubFloat(a,2) == SubFloat(b,2) && - SubFloat(a,3) == SubFloat(b,3); -} - -FORCEINLINE int TestSignSIMD( const fltx4 & a ) // mask of which floats have the high bit set -{ - int nRet = 0; - - nRet |= ( SubInt( a, 0 ) & 0x80000000 ) >> 31; // sign(x) -> bit 0 - nRet |= ( SubInt( a, 1 ) & 0x80000000 ) >> 30; // sign(y) -> bit 1 - nRet |= ( SubInt( a, 2 ) & 0x80000000 ) >> 29; // sign(z) -> bit 2 - nRet |= ( SubInt( a, 3 ) & 0x80000000 ) >> 28; // sign(w) -> bit 3 - - return nRet; -} - -FORCEINLINE bool IsAnyNegative( const fltx4 & a ) // (a.x < 0) || (a.y < 0) || (a.z < 0) || (a.w < 0) -{ - return (0 != TestSignSIMD( a )); -} - -FORCEINLINE fltx4 CmpEqSIMD( const fltx4 & a, const fltx4 & b ) // (a==b) ? ~0:0 -{ - fltx4 retVal; - SubInt( retVal, 0 ) = ( SubFloat( a, 0 ) == SubFloat( b, 0 )) ? ~0 : 0; - SubInt( retVal, 1 ) = ( SubFloat( a, 1 ) == SubFloat( b, 1 )) ? ~0 : 0; - SubInt( retVal, 2 ) = ( SubFloat( a, 2 ) == SubFloat( b, 2 )) ? ~0 : 0; - SubInt( retVal, 3 ) = ( SubFloat( a, 3 ) == SubFloat( b, 3 )) ? ~0 : 0; - return retVal; -} - -FORCEINLINE fltx4 CmpGtSIMD( const fltx4 & a, const fltx4 & b ) // (a>b) ? ~0:0 -{ - fltx4 retVal; - SubInt( retVal, 0 ) = ( SubFloat( a, 0 ) > SubFloat( b, 0 )) ? ~0 : 0; - SubInt( retVal, 1 ) = ( SubFloat( a, 1 ) > SubFloat( b, 1 )) ? ~0 : 0; - SubInt( retVal, 2 ) = ( SubFloat( a, 2 ) > SubFloat( b, 2 )) ? ~0 : 0; - SubInt( retVal, 3 ) = ( SubFloat( a, 3 ) > SubFloat( b, 3 )) ? ~0 : 0; - return retVal; -} - -FORCEINLINE fltx4 CmpGeSIMD( const fltx4 & a, const fltx4 & b ) // (a>=b) ? ~0:0 -{ - fltx4 retVal; - SubInt( retVal, 0 ) = ( SubFloat( a, 0 ) >= SubFloat( b, 0 )) ? ~0 : 0; - SubInt( retVal, 1 ) = ( SubFloat( a, 1 ) >= SubFloat( b, 1 )) ? ~0 : 0; - SubInt( retVal, 2 ) = ( SubFloat( a, 2 ) >= SubFloat( b, 2 )) ? ~0 : 0; - SubInt( retVal, 3 ) = ( SubFloat( a, 3 ) >= SubFloat( b, 3 )) ? ~0 : 0; - return retVal; -} - -FORCEINLINE fltx4 CmpLtSIMD( const fltx4 & a, const fltx4 & b ) // (a= -b) ? ~0 : 0 -{ - fltx4 retVal; - SubInt( retVal, 0 ) = ( SubFloat( a, 0 ) <= SubFloat( b, 0 ) && SubFloat( a, 0 ) >= -SubFloat( b, 0 ) ) ? ~0 : 0; - SubInt( retVal, 1 ) = ( SubFloat( a, 1 ) <= SubFloat( b, 1 ) && SubFloat( a, 1 ) >= -SubFloat( b, 1 ) ) ? ~0 : 0; - SubInt( retVal, 2 ) = ( SubFloat( a, 2 ) <= SubFloat( b, 2 ) && SubFloat( a, 2 ) >= -SubFloat( b, 2 ) ) ? ~0 : 0; - SubInt( retVal, 3 ) = ( SubFloat( a, 3 ) <= SubFloat( b, 3 ) && SubFloat( a, 3 ) >= -SubFloat( b, 3 ) ) ? ~0 : 0; - return retVal; -} - - -FORCEINLINE fltx4 MaskedAssign( const fltx4 & ReplacementMask, const fltx4 & NewValue, const fltx4 & OldValue ) -{ - return OrSIMD( - AndSIMD( ReplacementMask, NewValue ), - AndNotSIMD( ReplacementMask, OldValue ) ); -} - -FORCEINLINE fltx4 ReplicateX4( float flValue ) // a,a,a,a -{ - fltx4 retVal; - SubFloat( retVal, 0 ) = flValue; - SubFloat( retVal, 1 ) = flValue; - SubFloat( retVal, 2 ) = flValue; - SubFloat( retVal, 3 ) = flValue; - return retVal; -} - -/// replicate a single 32 bit integer value to all 4 components of an m128 -FORCEINLINE fltx4 ReplicateIX4( int nValue ) -{ - fltx4 retVal; - SubInt( retVal, 0 ) = nValue; - SubInt( retVal, 1 ) = nValue; - SubInt( retVal, 2 ) = nValue; - SubInt( retVal, 3 ) = nValue; - return retVal; - -} - -// Round towards positive infinity -FORCEINLINE fltx4 CeilSIMD( const fltx4 &a ) -{ - fltx4 retVal; - SubFloat( retVal, 0 ) = ceil( SubFloat( a, 0 ) ); - SubFloat( retVal, 1 ) = ceil( SubFloat( a, 1 ) ); - SubFloat( retVal, 2 ) = ceil( SubFloat( a, 2 ) ); - SubFloat( retVal, 3 ) = ceil( SubFloat( a, 3 ) ); - return retVal; - -} - -// Round towards negative infinity -FORCEINLINE fltx4 FloorSIMD( const fltx4 &a ) -{ - fltx4 retVal; - SubFloat( retVal, 0 ) = floor( SubFloat( a, 0 ) ); - SubFloat( retVal, 1 ) = floor( SubFloat( a, 1 ) ); - SubFloat( retVal, 2 ) = floor( SubFloat( a, 2 ) ); - SubFloat( retVal, 3 ) = floor( SubFloat( a, 3 ) ); - return retVal; - -} - -FORCEINLINE fltx4 SqrtEstSIMD( const fltx4 & a ) // sqrt(a), more or less -{ - fltx4 retVal; - SubFloat( retVal, 0 ) = sqrt( SubFloat( a, 0 ) ); - SubFloat( retVal, 1 ) = sqrt( SubFloat( a, 1 ) ); - SubFloat( retVal, 2 ) = sqrt( SubFloat( a, 2 ) ); - SubFloat( retVal, 3 ) = sqrt( SubFloat( a, 3 ) ); - return retVal; -} - -FORCEINLINE fltx4 SqrtSIMD( const fltx4 & a ) // sqrt(a) -{ - fltx4 retVal; - SubFloat( retVal, 0 ) = sqrt( SubFloat( a, 0 ) ); - SubFloat( retVal, 1 ) = sqrt( SubFloat( a, 1 ) ); - SubFloat( retVal, 2 ) = sqrt( SubFloat( a, 2 ) ); - SubFloat( retVal, 3 ) = sqrt( SubFloat( a, 3 ) ); - return retVal; -} - -FORCEINLINE fltx4 ReciprocalSqrtEstSIMD( const fltx4 & a ) // 1/sqrt(a), more or less -{ - fltx4 retVal; - SubFloat( retVal, 0 ) = 1.0 / sqrt( SubFloat( a, 0 ) ); - SubFloat( retVal, 1 ) = 1.0 / sqrt( SubFloat( a, 1 ) ); - SubFloat( retVal, 2 ) = 1.0 / sqrt( SubFloat( a, 2 ) ); - SubFloat( retVal, 3 ) = 1.0 / sqrt( SubFloat( a, 3 ) ); - return retVal; -} - -FORCEINLINE fltx4 ReciprocalSqrtEstSaturateSIMD( const fltx4 & a ) -{ - fltx4 retVal; - SubFloat( retVal, 0 ) = 1.0 / sqrt( SubFloat( a, 0 ) != 0.0f ? SubFloat( a, 0 ) : FLT_EPSILON ); - SubFloat( retVal, 1 ) = 1.0 / sqrt( SubFloat( a, 1 ) != 0.0f ? SubFloat( a, 1 ) : FLT_EPSILON ); - SubFloat( retVal, 2 ) = 1.0 / sqrt( SubFloat( a, 2 ) != 0.0f ? SubFloat( a, 2 ) : FLT_EPSILON ); - SubFloat( retVal, 3 ) = 1.0 / sqrt( SubFloat( a, 3 ) != 0.0f ? SubFloat( a, 3 ) : FLT_EPSILON ); - return retVal; -} - -FORCEINLINE fltx4 ReciprocalSqrtSIMD( const fltx4 & a ) // 1/sqrt(a) -{ - fltx4 retVal; - SubFloat( retVal, 0 ) = 1.0 / sqrt( SubFloat( a, 0 ) ); - SubFloat( retVal, 1 ) = 1.0 / sqrt( SubFloat( a, 1 ) ); - SubFloat( retVal, 2 ) = 1.0 / sqrt( SubFloat( a, 2 ) ); - SubFloat( retVal, 3 ) = 1.0 / sqrt( SubFloat( a, 3 ) ); - return retVal; -} - -FORCEINLINE fltx4 ReciprocalEstSIMD( const fltx4 & a ) // 1/a, more or less -{ - fltx4 retVal; - SubFloat( retVal, 0 ) = 1.0 / SubFloat( a, 0 ); - SubFloat( retVal, 1 ) = 1.0 / SubFloat( a, 1 ); - SubFloat( retVal, 2 ) = 1.0 / SubFloat( a, 2 ); - SubFloat( retVal, 3 ) = 1.0 / SubFloat( a, 3 ); - return retVal; -} - -FORCEINLINE fltx4 ReciprocalSIMD( const fltx4 & a ) // 1/a -{ - fltx4 retVal; - SubFloat( retVal, 0 ) = 1.0 / SubFloat( a, 0 ); - SubFloat( retVal, 1 ) = 1.0 / SubFloat( a, 1 ); - SubFloat( retVal, 2 ) = 1.0 / SubFloat( a, 2 ); - SubFloat( retVal, 3 ) = 1.0 / SubFloat( a, 3 ); - return retVal; -} - -/// 1/x for all 4 values. -/// 1/0 will result in a big but NOT infinite result -FORCEINLINE fltx4 ReciprocalEstSaturateSIMD( const fltx4 & a ) -{ - fltx4 retVal; - SubFloat( retVal, 0 ) = 1.0 / (SubFloat( a, 0 ) == 0.0f ? FLT_EPSILON : SubFloat( a, 0 )); - SubFloat( retVal, 1 ) = 1.0 / (SubFloat( a, 1 ) == 0.0f ? FLT_EPSILON : SubFloat( a, 1 )); - SubFloat( retVal, 2 ) = 1.0 / (SubFloat( a, 2 ) == 0.0f ? FLT_EPSILON : SubFloat( a, 2 )); - SubFloat( retVal, 3 ) = 1.0 / (SubFloat( a, 3 ) == 0.0f ? FLT_EPSILON : SubFloat( a, 3 )); - return retVal; -} - -FORCEINLINE fltx4 ReciprocalSaturateSIMD( const fltx4 & a ) -{ - fltx4 retVal; - SubFloat( retVal, 0 ) = 1.0 / (SubFloat( a, 0 ) == 0.0f ? FLT_EPSILON : SubFloat( a, 0 )); - SubFloat( retVal, 1 ) = 1.0 / (SubFloat( a, 1 ) == 0.0f ? FLT_EPSILON : SubFloat( a, 1 )); - SubFloat( retVal, 2 ) = 1.0 / (SubFloat( a, 2 ) == 0.0f ? FLT_EPSILON : SubFloat( a, 2 )); - SubFloat( retVal, 3 ) = 1.0 / (SubFloat( a, 3 ) == 0.0f ? FLT_EPSILON : SubFloat( a, 3 )); - return retVal; -} - -// 2^x for all values (the antilog) -FORCEINLINE fltx4 ExpSIMD( const fltx4 &toPower ) -{ - fltx4 retVal; - SubFloat( retVal, 0 ) = powf( 2, SubFloat(toPower, 0) ); - SubFloat( retVal, 1 ) = powf( 2, SubFloat(toPower, 1) ); - SubFloat( retVal, 2 ) = powf( 2, SubFloat(toPower, 2) ); - SubFloat( retVal, 3 ) = powf( 2, SubFloat(toPower, 3) ); - - return retVal; -} - -FORCEINLINE fltx4 Dot3SIMD( const fltx4 &a, const fltx4 &b ) -{ - float flDot = SubFloat( a, 0 ) * SubFloat( b, 0 ) + - SubFloat( a, 1 ) * SubFloat( b, 1 ) + - SubFloat( a, 2 ) * SubFloat( b, 2 ); - return ReplicateX4( flDot ); -} - -FORCEINLINE fltx4 Dot4SIMD( const fltx4 &a, const fltx4 &b ) -{ - float flDot = SubFloat( a, 0 ) * SubFloat( b, 0 ) + - SubFloat( a, 1 ) * SubFloat( b, 1 ) + - SubFloat( a, 2 ) * SubFloat( b, 2 ) + - SubFloat( a, 3 ) * SubFloat( b, 3 ); - return ReplicateX4( flDot ); -} - -// Clamps the components of a vector to a specified minimum and maximum range. -FORCEINLINE fltx4 ClampVectorSIMD( FLTX4 in, FLTX4 min, FLTX4 max) -{ - return MaxSIMD( min, MinSIMD( max, in ) ); -} - -// Squelch the w component of a vector to +0.0. -// Most efficient when you say a = SetWToZeroSIMD(a) (avoids a copy) -FORCEINLINE fltx4 SetWToZeroSIMD( const fltx4 & a ) -{ - fltx4 retval; - retval = a; - SubFloat( retval, 0 ) = 0; - return retval; -} - -FORCEINLINE fltx4 LoadUnalignedSIMD( const void *pSIMD ) -{ - return *( reinterpret_cast< const fltx4 *> ( pSIMD ) ); -} - -FORCEINLINE fltx4 LoadUnaligned3SIMD( const void *pSIMD ) -{ - return *( reinterpret_cast< const fltx4 *> ( pSIMD ) ); -} - -FORCEINLINE fltx4 LoadAlignedSIMD( const void *pSIMD ) -{ - return *( reinterpret_cast< const fltx4 *> ( pSIMD ) ); -} - -// for the transitional class -- load a 3-by VectorAligned and squash its w component -FORCEINLINE fltx4 LoadAlignedSIMD( const VectorAligned & pSIMD ) -{ - fltx4 retval = LoadAlignedSIMD(pSIMD.Base()); - // squelch w - SubInt( retval, 3 ) = 0; - return retval; -} - -FORCEINLINE void StoreAlignedSIMD( float *pSIMD, const fltx4 & a ) -{ - *( reinterpret_cast< fltx4 *> ( pSIMD ) ) = a; -} - -FORCEINLINE void StoreUnalignedSIMD( float *pSIMD, const fltx4 & a ) -{ - *( reinterpret_cast< fltx4 *> ( pSIMD ) ) = a; -} - -FORCEINLINE void StoreUnaligned3SIMD( float *pSIMD, const fltx4 & a ) -{ - *pSIMD = SubFloat(a, 0); - *(pSIMD+1) = SubFloat(a, 1); - *(pSIMD+2) = SubFloat(a, 2); -} - -// strongly typed -- syntactic castor oil used for typechecking as we transition to SIMD -FORCEINLINE void StoreAligned3SIMD( VectorAligned * RESTRICT pSIMD, const fltx4 & a ) -{ - StoreAlignedSIMD(pSIMD->Base(),a); -} - -FORCEINLINE void TransposeSIMD( fltx4 & x, fltx4 & y, fltx4 & z, fltx4 & w ) -{ -#define SWAP_FLOATS( _a_, _ia_, _b_, _ib_ ) { float tmp = SubFloat( _a_, _ia_ ); SubFloat( _a_, _ia_ ) = SubFloat( _b_, _ib_ ); SubFloat( _b_, _ib_ ) = tmp; } - SWAP_FLOATS( x, 1, y, 0 ); - SWAP_FLOATS( x, 2, z, 0 ); - SWAP_FLOATS( x, 3, w, 0 ); - SWAP_FLOATS( y, 2, z, 1 ); - SWAP_FLOATS( y, 3, w, 1 ); - SWAP_FLOATS( z, 3, w, 2 ); -} - -// find the lowest component of a.x, a.y, a.z, -// and replicate it to the whole return value. -FORCEINLINE fltx4 FindLowestSIMD3( const fltx4 & a ) -{ - float lowest = MIN( MIN( SubFloat(a, 0), SubFloat(a, 1) ), SubFloat(a, 2)); - return ReplicateX4(lowest); -} - -// find the highest component of a.x, a.y, a.z, -// and replicate it to the whole return value. -FORCEINLINE fltx4 FindHighestSIMD3( const fltx4 & a ) -{ - float highest = MAX( MAX( SubFloat(a, 0), SubFloat(a, 1) ), SubFloat(a, 2)); - return ReplicateX4(highest); -} - -// Fixed-point conversion and save as SIGNED INTS. -// pDest->x = Int (vSrc.x) -// note: some architectures have means of doing -// fixed point conversion when the fix depth is -// specified as an immediate.. but there is no way -// to guarantee an immediate as a parameter to function -// like this. -FORCEINLINE void ConvertStoreAsIntsSIMD(intx4 * RESTRICT pDest, const fltx4 &vSrc) -{ - (*pDest)[0] = SubFloat(vSrc, 0); - (*pDest)[1] = SubFloat(vSrc, 1); - (*pDest)[2] = SubFloat(vSrc, 2); - (*pDest)[3] = SubFloat(vSrc, 3); -} - -// ------------------------------------ -// INTEGER SIMD OPERATIONS. -// ------------------------------------ -// splat all components of a vector to a signed immediate int number. -FORCEINLINE fltx4 IntSetImmediateSIMD( int nValue ) -{ - fltx4 retval; - SubInt( retval, 0 ) = SubInt( retval, 1 ) = SubInt( retval, 2 ) = SubInt( retval, 3) = nValue; - return retval; -} - -// Load 4 aligned words into a SIMD register -FORCEINLINE i32x4 LoadAlignedIntSIMD(const void * RESTRICT pSIMD) -{ - return *( reinterpret_cast< const i32x4 *> ( pSIMD ) ); -} - -// Load 4 unaligned words into a SIMD register -FORCEINLINE i32x4 LoadUnalignedIntSIMD( const void * RESTRICT pSIMD) -{ - return *( reinterpret_cast< const i32x4 *> ( pSIMD ) ); -} - -// save into four words, 16-byte aligned -FORCEINLINE void StoreAlignedIntSIMD( int32 *pSIMD, const fltx4 & a ) -{ - *( reinterpret_cast< i32x4 *> ( pSIMD ) ) = a; -} - -FORCEINLINE void StoreAlignedIntSIMD( intx4 &pSIMD, const fltx4 & a ) -{ - *( reinterpret_cast< i32x4 *> ( pSIMD.Base() ) ) = a; -} - -FORCEINLINE void StoreUnalignedIntSIMD( int32 *pSIMD, const fltx4 & a ) -{ - *( reinterpret_cast< i32x4 *> ( pSIMD ) ) = a; -} - -// Take a fltx4 containing fixed-point uints and -// return them as single precision floats. No -// fixed point conversion is done. -FORCEINLINE fltx4 UnsignedIntConvertToFltSIMD( const u32x4 &vSrcA ) -{ - Assert(0); /* pc has no such operation */ - fltx4 retval; - SubFloat( retval, 0 ) = ( (float) SubInt( retval, 0 ) ); - SubFloat( retval, 1 ) = ( (float) SubInt( retval, 1 ) ); - SubFloat( retval, 2 ) = ( (float) SubInt( retval, 2 ) ); - SubFloat( retval, 3 ) = ( (float) SubInt( retval, 3 ) ); - return retval; -} - - -#if 0 /* pc has no such op */ -// Take a fltx4 containing fixed-point sints and -// return them as single precision floats. No -// fixed point conversion is done. -FORCEINLINE fltx4 SignedIntConvertToFltSIMD( const i32x4 &vSrcA ) -{ - fltx4 retval; - SubFloat( retval, 0 ) = ( (float) (reinterpret_cast(&vSrcA.m128_s32[0])) ); - SubFloat( retval, 1 ) = ( (float) (reinterpret_cast(&vSrcA.m128_s32[1])) ); - SubFloat( retval, 2 ) = ( (float) (reinterpret_cast(&vSrcA.m128_s32[2])) ); - SubFloat( retval, 3 ) = ( (float) (reinterpret_cast(&vSrcA.m128_s32[3])) ); - return retval; -} - - -/* - works on fltx4's as if they are four uints. - the first parameter contains the words to be shifted, - the second contains the amount to shift by AS INTS - - for i = 0 to 3 - shift = vSrcB_i*32:(i*32)+4 - vReturned_i*32:(i*32)+31 = vSrcA_i*32:(i*32)+31 << shift -*/ -FORCEINLINE i32x4 IntShiftLeftWordSIMD(const i32x4 &vSrcA, const i32x4 &vSrcB) -{ - i32x4 retval; - SubInt(retval, 0) = SubInt(vSrcA, 0) << SubInt(vSrcB, 0); - SubInt(retval, 1) = SubInt(vSrcA, 1) << SubInt(vSrcB, 1); - SubInt(retval, 2) = SubInt(vSrcA, 2) << SubInt(vSrcB, 2); - SubInt(retval, 3) = SubInt(vSrcA, 3) << SubInt(vSrcB, 3); - - - return retval; -} -#endif - -#elif ( defined( _X360 ) ) - -//--------------------------------------------------------------------- -// X360 implementation -//--------------------------------------------------------------------- - -FORCEINLINE float & FloatSIMD( fltx4 & a, int idx ) -{ - fltx4_union & a_union = (fltx4_union &)a; - return a_union.m128_f32[idx]; -} - -FORCEINLINE unsigned int & UIntSIMD( fltx4 & a, int idx ) -{ - fltx4_union & a_union = (fltx4_union &)a; - return a_union.m128_u32[idx]; -} - -FORCEINLINE fltx4 AddSIMD( const fltx4 & a, const fltx4 & b ) -{ - return __vaddfp( a, b ); -} - -FORCEINLINE fltx4 SubSIMD( const fltx4 & a, const fltx4 & b ) // a-b -{ - return __vsubfp( a, b ); -} - -FORCEINLINE fltx4 MulSIMD( const fltx4 & a, const fltx4 & b ) // a*b -{ - return __vmulfp( a, b ); -} - -FORCEINLINE fltx4 MaddSIMD( const fltx4 & a, const fltx4 & b, const fltx4 & c ) // a*b + c -{ - return __vmaddfp( a, b, c ); -} - -FORCEINLINE fltx4 MsubSIMD( const fltx4 & a, const fltx4 & b, const fltx4 & c ) // c - a*b -{ - return __vnmsubfp( a, b, c ); -}; - -FORCEINLINE fltx4 Dot3SIMD( const fltx4 &a, const fltx4 &b ) -{ - return __vmsum3fp( a, b ); -} - -FORCEINLINE fltx4 Dot4SIMD( const fltx4 &a, const fltx4 &b ) -{ - return __vmsum4fp( a, b ); -} - -FORCEINLINE fltx4 SinSIMD( const fltx4 &radians ) -{ - return XMVectorSin( radians ); -} - -FORCEINLINE void SinCos3SIMD( fltx4 &sine, fltx4 &cosine, const fltx4 &radians ) -{ - XMVectorSinCos( &sine, &cosine, radians ); -} - -FORCEINLINE void SinCosSIMD( fltx4 &sine, fltx4 &cosine, const fltx4 &radians ) -{ - XMVectorSinCos( &sine, &cosine, radians ); -} - -FORCEINLINE void CosSIMD( fltx4 &cosine, const fltx4 &radians ) -{ - cosine = XMVectorCos( radians ); -} - -FORCEINLINE fltx4 ArcSinSIMD( const fltx4 &sine ) -{ - return XMVectorASin( sine ); -} - -FORCEINLINE fltx4 ArcCosSIMD( const fltx4 &cs ) -{ - return XMVectorACos( cs ); -} - -// tan^1(a/b) .. ie, pass sin in as a and cos in as b -FORCEINLINE fltx4 ArcTan2SIMD( const fltx4 &a, const fltx4 &b ) -{ - return XMVectorATan2( a, b ); -} - -// DivSIMD defined further down, since it uses ReciprocalSIMD - -FORCEINLINE fltx4 MaxSIMD( const fltx4 & a, const fltx4 & b ) // MAX(a,b) -{ - return __vmaxfp( a, b ); -} - -FORCEINLINE fltx4 MinSIMD( const fltx4 & a, const fltx4 & b ) // MIN(a,b) -{ - return __vminfp( a, b ); -} - -FORCEINLINE fltx4 AndSIMD( const fltx4 & a, const fltx4 & b ) // a & b -{ - return __vand( a, b ); -} - -FORCEINLINE fltx4 AndNotSIMD( const fltx4 & a, const fltx4 & b ) // ~a & b -{ - // NOTE: a and b are swapped in the call: SSE complements the first argument, VMX the second - return __vandc( b, a ); -} - -FORCEINLINE fltx4 XorSIMD( const fltx4 & a, const fltx4 & b ) // a ^ b -{ - return __vxor( a, b ); -} - -FORCEINLINE fltx4 OrSIMD( const fltx4 & a, const fltx4 & b ) // a | b -{ - return __vor( a, b ); -} - -FORCEINLINE fltx4 NegSIMD(const fltx4 &a) // negate: -a -{ - return XMVectorNegate(a); -} - -FORCEINLINE bool IsAllZeros( const fltx4 & a ) // all floats of a zero? -{ - unsigned int equalFlags = 0; - __vcmpeqfpR( a, Four_Zeros, &equalFlags ); - return XMComparisonAllTrue( equalFlags ); -} - -FORCEINLINE bool IsAnyZeros( const fltx4 & a ) // any floats are zero? -{ - unsigned int conditionregister; - XMVectorEqualR(&conditionregister, a, XMVectorZero()); - return XMComparisonAnyTrue(conditionregister); -} - -FORCEINLINE bool IsAnyXYZZero( const fltx4 &a ) // are any of x,y,z zero? -{ - // copy a's x component into w, in case w was zero. - fltx4 temp = __vrlimi(a, a, 1, 1); - unsigned int conditionregister; - XMVectorEqualR(&conditionregister, temp, XMVectorZero()); - return XMComparisonAnyTrue(conditionregister); -} - -// for branching when a.xyzw > b.xyzw -FORCEINLINE bool IsAllGreaterThan( const fltx4 &a, const fltx4 &b ) -{ - unsigned int cr; - XMVectorGreaterR(&cr,a,b); - return XMComparisonAllTrue(cr); -} - -// for branching when a.xyzw >= b.xyzw -FORCEINLINE bool IsAllGreaterThanOrEq( const fltx4 &a, const fltx4 &b ) -{ - unsigned int cr; - XMVectorGreaterOrEqualR(&cr,a,b); - return XMComparisonAllTrue(cr); -} - -// For branching if all a.xyzw == b.xyzw -FORCEINLINE bool IsAllEqual( const fltx4 & a, const fltx4 & b ) -{ - unsigned int cr; - XMVectorEqualR(&cr,a,b); - return XMComparisonAllTrue(cr); -} - - -FORCEINLINE int TestSignSIMD( const fltx4 & a ) // mask of which floats have the high bit set -{ - // NOTE: this maps to SSE way better than it does to VMX (most code uses IsAnyNegative(), though) - int nRet = 0; - - const fltx4_union & a_union = (const fltx4_union &)a; - nRet |= ( a_union.m128_u32[0] & 0x80000000 ) >> 31; // sign(x) -> bit 0 - nRet |= ( a_union.m128_u32[1] & 0x80000000 ) >> 30; // sign(y) -> bit 1 - nRet |= ( a_union.m128_u32[2] & 0x80000000 ) >> 29; // sign(z) -> bit 2 - nRet |= ( a_union.m128_u32[3] & 0x80000000 ) >> 28; // sign(w) -> bit 3 - - return nRet; -} - -// Squelch the w component of a vector to +0.0. -// Most efficient when you say a = SetWToZeroSIMD(a) (avoids a copy) -FORCEINLINE fltx4 SetWToZeroSIMD( const fltx4 & a ) -{ - return __vrlimi( a, __vzero(), 1, 0 ); -} - -FORCEINLINE bool IsAnyNegative( const fltx4 & a ) // (a.x < 0) || (a.y < 0) || (a.z < 0) || (a.w < 0) -{ - // NOTE: this tests the top bits of each vector element using integer math - // (so it ignores NaNs - it will return true for "-NaN") - unsigned int equalFlags = 0; - fltx4 signMask = __vspltisw( -1 ); // 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF 0xFFFFFFFF (low order 5 bits of each element = 31) - signMask = __vslw( signMask, signMask ); // 0x80000000 0x80000000 0x80000000 0x80000000 - __vcmpequwR( Four_Zeros, __vand( signMask, a ), &equalFlags ); - return !XMComparisonAllTrue( equalFlags ); -} - -FORCEINLINE fltx4 CmpEqSIMD( const fltx4 & a, const fltx4 & b ) // (a==b) ? ~0:0 -{ - return __vcmpeqfp( a, b ); -} - - -FORCEINLINE fltx4 CmpGtSIMD( const fltx4 & a, const fltx4 & b ) // (a>b) ? ~0:0 -{ - return __vcmpgtfp( a, b ); -} - -FORCEINLINE fltx4 CmpGeSIMD( const fltx4 & a, const fltx4 & b ) // (a>=b) ? ~0:0 -{ - return __vcmpgefp( a, b ); -} - -FORCEINLINE fltx4 CmpLtSIMD( const fltx4 & a, const fltx4 & b ) // (a= -b) ? ~0 : 0 -{ - return XMVectorInBounds( a, b ); -} - -// returned[i] = ReplacementMask[i] == 0 ? OldValue : NewValue -FORCEINLINE fltx4 MaskedAssign( const fltx4 & ReplacementMask, const fltx4 & NewValue, const fltx4 & OldValue ) -{ - return __vsel( OldValue, NewValue, ReplacementMask ); -} - -// AKA "Broadcast", "Splat" -FORCEINLINE fltx4 ReplicateX4( float flValue ) // a,a,a,a -{ - // NOTE: if flValue comes from a register, this causes a Load-Hit-Store stall (don't mix fpu/vpu math!) - float * pValue = &flValue; - Assert( pValue ); - Assert( ((unsigned int)pValue & 3) == 0); - return __vspltw( __lvlx( pValue, 0 ), 0 ); -} - -FORCEINLINE fltx4 ReplicateX4( const float *pValue ) // a,a,a,a -{ - Assert( pValue ); - return __vspltw( __lvlx( pValue, 0 ), 0 ); -} - -/// replicate a single 32 bit integer value to all 4 components of an m128 -FORCEINLINE fltx4 ReplicateIX4( int nValue ) -{ - // NOTE: if nValue comes from a register, this causes a Load-Hit-Store stall (should not mix ints with fltx4s!) - int * pValue = &nValue; - Assert( pValue ); - Assert( ((unsigned int)pValue & 3) == 0); - return __vspltw( __lvlx( pValue, 0 ), 0 ); -} - -// Round towards positive infinity -FORCEINLINE fltx4 CeilSIMD( const fltx4 &a ) -{ - return __vrfip(a); -} - -// Round towards nearest integer -FORCEINLINE fltx4 RoundSIMD( const fltx4 &a ) -{ - return __vrfin(a); -} - -// Round towards negative infinity -FORCEINLINE fltx4 FloorSIMD( const fltx4 &a ) -{ - return __vrfim(a); -} - -FORCEINLINE fltx4 SqrtEstSIMD( const fltx4 & a ) // sqrt(a), more or less -{ - // This is emulated from rsqrt - return XMVectorSqrtEst( a ); -} - -FORCEINLINE fltx4 SqrtSIMD( const fltx4 & a ) // sqrt(a) -{ - // This is emulated from rsqrt - return XMVectorSqrt( a ); -} - -FORCEINLINE fltx4 ReciprocalSqrtEstSIMD( const fltx4 & a ) // 1/sqrt(a), more or less -{ - return __vrsqrtefp( a ); -} - -FORCEINLINE fltx4 ReciprocalSqrtEstSaturateSIMD( const fltx4 & a ) -{ - // Convert zeros to epsilons - fltx4 zero_mask = CmpEqSIMD( a, Four_Zeros ); - fltx4 a_safe = OrSIMD( a, AndSIMD( Four_Epsilons, zero_mask ) ); - return ReciprocalSqrtEstSIMD( a_safe ); -} - -FORCEINLINE fltx4 ReciprocalSqrtSIMD( const fltx4 & a ) // 1/sqrt(a) -{ - // This uses Newton-Raphson to improve the HW result - return XMVectorReciprocalSqrt( a ); -} - -FORCEINLINE fltx4 ReciprocalEstSIMD( const fltx4 & a ) // 1/a, more or less -{ - return __vrefp( a ); -} - -/// 1/x for all 4 values. uses reciprocal approximation instruction plus newton iteration. -/// No error checking! -FORCEINLINE fltx4 ReciprocalSIMD( const fltx4 & a ) // 1/a -{ - // This uses Newton-Raphson to improve the HW result - return XMVectorReciprocal( a ); -} - -// FIXME: on 360, this is very slow, since it uses ReciprocalSIMD (do we need DivEstSIMD?) -FORCEINLINE fltx4 DivSIMD( const fltx4 & a, const fltx4 & b ) // a/b -{ - return MulSIMD( ReciprocalSIMD( b ), a ); -} - -/// 1/x for all 4 values. -/// 1/0 will result in a big but NOT infinite result -FORCEINLINE fltx4 ReciprocalEstSaturateSIMD( const fltx4 & a ) -{ - // Convert zeros to epsilons - fltx4 zero_mask = CmpEqSIMD( a, Four_Zeros ); - fltx4 a_safe = OrSIMD( a, AndSIMD( Four_Epsilons, zero_mask ) ); - return ReciprocalEstSIMD( a_safe ); -} - -FORCEINLINE fltx4 ReciprocalSaturateSIMD( const fltx4 & a ) -{ - // Convert zeros to epsilons - fltx4 zero_mask = CmpEqSIMD( a, Four_Zeros ); - fltx4 a_safe = OrSIMD( a, AndSIMD( Four_Epsilons, zero_mask ) ); - return ReciprocalSIMD( a_safe ); - - // FIXME: This could be faster (BUT: it doesn't preserve the sign of -0.0, whereas the above does) - // fltx4 zeroMask = CmpEqSIMD( Four_Zeros, a ); - // fltx4 a_safe = XMVectorSelect( a, Four_Epsilons, zeroMask ); - // return ReciprocalSIMD( a_safe ); -} - -// CHRISG: is it worth doing integer bitfiddling for this? -// 2^x for all values (the antilog) -FORCEINLINE fltx4 ExpSIMD( const fltx4 &toPower ) -{ - return XMVectorExp(toPower); -} - -// Clamps the components of a vector to a specified minimum and maximum range. -FORCEINLINE fltx4 ClampVectorSIMD( FLTX4 in, FLTX4 min, FLTX4 max) -{ - return XMVectorClamp(in, min, max); -} - -FORCEINLINE fltx4 LoadUnalignedSIMD( const void *pSIMD ) -{ - return XMLoadVector4( pSIMD ); -} - -// load a 3-vector (as opposed to LoadUnalignedSIMD, which loads a 4-vec). -FORCEINLINE fltx4 LoadUnaligned3SIMD( const void *pSIMD ) -{ - return XMLoadVector3( pSIMD ); -} - -FORCEINLINE fltx4 LoadAlignedSIMD( const void *pSIMD ) -{ - return *( reinterpret_cast< const fltx4 *> ( pSIMD ) ); -} - -// for the transitional class -- load a 3-by VectorAligned and squash its w component -FORCEINLINE fltx4 LoadAlignedSIMD( const VectorAligned & pSIMD ) -{ - fltx4 out = XMLoadVector3A(pSIMD.Base()); - // squelch w - return __vrlimi( out, __vzero(), 1, 0 ); -} - -// for the transitional class -- load a 3-by VectorAligned and squash its w component -FORCEINLINE fltx4 LoadAlignedSIMD( const VectorAligned * RESTRICT pSIMD ) -{ - fltx4 out = XMLoadVector3A(pSIMD); - // squelch w - return __vrlimi( out, __vzero(), 1, 0 ); -} - -FORCEINLINE void StoreAlignedSIMD( float *pSIMD, const fltx4 & a ) -{ - *( reinterpret_cast< fltx4 *> ( pSIMD ) ) = a; -} - -FORCEINLINE void StoreUnalignedSIMD( float *pSIMD, const fltx4 & a ) -{ - XMStoreVector4( pSIMD, a ); -} - -FORCEINLINE void StoreUnaligned3SIMD( float *pSIMD, const fltx4 & a ) -{ - XMStoreVector3( pSIMD, a ); -} - - -// strongly typed -- for typechecking as we transition to SIMD -FORCEINLINE void StoreAligned3SIMD( VectorAligned * RESTRICT pSIMD, const fltx4 & a ) -{ - XMStoreVector3A(pSIMD->Base(),a); -} - - -// Fixed-point conversion and save as SIGNED INTS. -// pDest->x = Int (vSrc.x) -// note: some architectures have means of doing -// fixed point conversion when the fix depth is -// specified as an immediate.. but there is no way -// to guarantee an immediate as a parameter to function -// like this. -FORCEINLINE void ConvertStoreAsIntsSIMD(intx4 * RESTRICT pDest, const fltx4 &vSrc) -{ - fltx4 asInt = __vctsxs( vSrc, 0 ); - XMStoreVector4A(pDest->Base(), asInt); -} - -FORCEINLINE void TransposeSIMD( fltx4 & x, fltx4 & y, fltx4 & z, fltx4 & w ) -{ - XMMATRIX xyzwMatrix = _XMMATRIX( x, y, z, w ); - xyzwMatrix = XMMatrixTranspose( xyzwMatrix ); - x = xyzwMatrix.r[0]; - y = xyzwMatrix.r[1]; - z = xyzwMatrix.r[2]; - w = xyzwMatrix.r[3]; -} - -// Return one in the fastest way -- faster even than loading. -FORCEINLINE fltx4 LoadZeroSIMD( void ) -{ - return XMVectorZero(); -} - -// Return one in the fastest way -- faster even than loading. -FORCEINLINE fltx4 LoadOneSIMD( void ) -{ - return XMVectorSplatOne(); -} - -FORCEINLINE fltx4 SplatXSIMD( fltx4 a ) -{ - return XMVectorSplatX( a ); -} - -FORCEINLINE fltx4 SplatYSIMD( fltx4 a ) -{ - return XMVectorSplatY( a ); -} - -FORCEINLINE fltx4 SplatZSIMD( fltx4 a ) -{ - return XMVectorSplatZ( a ); -} - -FORCEINLINE fltx4 SplatWSIMD( fltx4 a ) -{ - return XMVectorSplatW( a ); -} - -FORCEINLINE fltx4 SetXSIMD( const fltx4& a, const fltx4& x ) -{ - fltx4 result = __vrlimi(a, x, 8, 0); - return result; -} - -FORCEINLINE fltx4 SetYSIMD( const fltx4& a, const fltx4& y ) -{ - fltx4 result = __vrlimi(a, y, 4, 0); - return result; -} - -FORCEINLINE fltx4 SetZSIMD( const fltx4& a, const fltx4& z ) -{ - fltx4 result = __vrlimi(a, z, 2, 0); - return result; -} - -FORCEINLINE fltx4 SetWSIMD( const fltx4& a, const fltx4& w ) -{ - fltx4 result = __vrlimi(a, w, 1, 0); - return result; -} - -FORCEINLINE fltx4 SetComponentSIMD( const fltx4& a, int nComponent, float flValue ) -{ - static int s_nVrlimiMask[4] = { 8, 4, 2, 1 }; - fltx4 val = ReplicateX4( flValue ); - fltx4 result = __vrlimi(a, val, s_nVrlimiMask[nComponent], 0); - return result; -} - -FORCEINLINE fltx4 RotateLeft( const fltx4 & a ) -{ - fltx4 compareOne = a; - return __vrlimi( compareOne, a, 8 | 4 | 2 | 1, 1 ); -} - -FORCEINLINE fltx4 RotateLeft2( const fltx4 & a ) -{ - fltx4 compareOne = a; - return __vrlimi( compareOne, a, 8 | 4 | 2 | 1, 2 ); -} - - - -// find the lowest component of a.x, a.y, a.z, -// and replicate it to the whole return value. -// ignores a.w. -// Though this is only five instructions long, -// they are all dependent, making this stall city. -// Forcing this inline should hopefully help with scheduling. -FORCEINLINE fltx4 FindLowestSIMD3( const fltx4 & a ) -{ - // a is [x,y,z,G] (where G is garbage) - // rotate left by one - fltx4 compareOne = a ; - compareOne = __vrlimi( compareOne, a, 8 | 4 , 1 ); - // compareOne is [y,z,G,G] - fltx4 retval = MinSIMD( a, compareOne ); - // retVal is [MIN(x,y), MIN(y,z), G, G] - compareOne = __vrlimi( compareOne, a, 8 , 2); - // compareOne is [z, G, G, G] - retval = MinSIMD( retval, compareOne ); - // retVal = [ MIN(MIN(x,y),z), G, G, G ] - - // splat the x component out to the whole vector and return - return SplatXSIMD( retval ); -} - -// find the highest component of a.x, a.y, a.z, -// and replicate it to the whole return value. -// ignores a.w. -// Though this is only five instructions long, -// they are all dependent, making this stall city. -// Forcing this inline should hopefully help with scheduling. -FORCEINLINE fltx4 FindHighestSIMD3( const fltx4 & a ) -{ - // a is [x,y,z,G] (where G is garbage) - // rotate left by one - fltx4 compareOne = a ; - compareOne = __vrlimi( compareOne, a, 8 | 4 , 1 ); - // compareOne is [y,z,G,G] - fltx4 retval = MaxSIMD( a, compareOne ); - // retVal is [MAX(x,y), MAX(y,z), G, G] - compareOne = __vrlimi( compareOne, a, 8 , 2); - // compareOne is [z, G, G, G] - retval = MaxSIMD( retval, compareOne ); - // retVal = [ MAX(MAX(x,y),z), G, G, G ] - - // splat the x component out to the whole vector and return - return SplatXSIMD( retval ); -} - - -// Transform many (horizontal) points in-place by a 3x4 matrix, -// here already loaded onto three fltx4 registers. -// The points must be stored as 16-byte aligned. They are points -// and not vectors because we assume the w-component to be 1. -// To spare yourself the annoyance of loading the matrix yourself, -// use one of the overloads below. -void TransformManyPointsBy(VectorAligned * RESTRICT pVectors, unsigned int numVectors, FLTX4 mRow1, FLTX4 mRow2, FLTX4 mRow3); - -// Transform many (horizontal) points in-place by a 3x4 matrix. -// The points must be stored as 16-byte aligned. They are points -// and not vectors because we assume the w-component to be 1. -// In this function, the matrix need not be aligned. -FORCEINLINE void TransformManyPointsBy(VectorAligned * RESTRICT pVectors, unsigned int numVectors, const matrix3x4_t &pMatrix) -{ - return TransformManyPointsBy(pVectors, numVectors, - LoadUnalignedSIMD( pMatrix[0] ), LoadUnalignedSIMD( pMatrix[1] ), LoadUnalignedSIMD( pMatrix[2] ) ); -} - -// Transform many (horizontal) points in-place by a 3x4 matrix. -// The points must be stored as 16-byte aligned. They are points -// and not vectors because we assume the w-component to be 1. -// In this function, the matrix must itself be aligned on a 16-byte -// boundary. -FORCEINLINE void TransformManyPointsByA(VectorAligned * RESTRICT pVectors, unsigned int numVectors, const matrix3x4_t &pMatrix) -{ - return TransformManyPointsBy(pVectors, numVectors, - LoadAlignedSIMD( pMatrix[0] ), LoadAlignedSIMD( pMatrix[1] ), LoadAlignedSIMD( pMatrix[2] ) ); -} - -// ------------------------------------ -// INTEGER SIMD OPERATIONS. -// ------------------------------------ - -// Load 4 aligned words into a SIMD register -FORCEINLINE i32x4 LoadAlignedIntSIMD( const void * RESTRICT pSIMD) -{ - return XMLoadVector4A(pSIMD); -} - -// Load 4 unaligned words into a SIMD register -FORCEINLINE i32x4 LoadUnalignedIntSIMD(const void * RESTRICT pSIMD) -{ - return XMLoadVector4( pSIMD ); -} - -// save into four words, 16-byte aligned -FORCEINLINE void StoreAlignedIntSIMD( int32 *pSIMD, const fltx4 & a ) -{ - *( reinterpret_cast< i32x4 *> ( pSIMD ) ) = a; -} - -FORCEINLINE void StoreAlignedIntSIMD( intx4 &pSIMD, const fltx4 & a ) -{ - *( reinterpret_cast< i32x4 *> ( pSIMD.Base() ) ) = a; -} - -FORCEINLINE void StoreUnalignedIntSIMD( int32 *pSIMD, const fltx4 & a ) -{ - XMStoreVector4(pSIMD, a); -} - - -// Take a fltx4 containing fixed-point uints and -// return them as single precision floats. No -// fixed point conversion is done. -FORCEINLINE fltx4 UnsignedIntConvertToFltSIMD( const i32x4 &vSrcA ) -{ - return __vcfux( vSrcA, 0 ); -} - - -// Take a fltx4 containing fixed-point sints and -// return them as single precision floats. No -// fixed point conversion is done. -FORCEINLINE fltx4 SignedIntConvertToFltSIMD( const i32x4 &vSrcA ) -{ - return __vcfsx( vSrcA, 0 ); -} - -// Take a fltx4 containing fixed-point uints and -// return them as single precision floats. Each uint -// will be divided by 2^immed after conversion -// (eg, this is fixed point math). -/* as if: - FORCEINLINE fltx4 UnsignedIntConvertToFltSIMD( const i32x4 &vSrcA, unsigned int uImmed ) - { - return __vcfux( vSrcA, uImmed ); - } -*/ -#define UnsignedFixedIntConvertToFltSIMD(vSrcA, uImmed) (__vcfux( (vSrcA), (uImmed) )) - -// Take a fltx4 containing fixed-point sints and -// return them as single precision floats. Each int -// will be divided by 2^immed (eg, this is fixed point -// math). -/* as if: - FORCEINLINE fltx4 SignedIntConvertToFltSIMD( const i32x4 &vSrcA, unsigned int uImmed ) - { - return __vcfsx( vSrcA, uImmed ); - } -*/ -#define SignedFixedIntConvertToFltSIMD(vSrcA, uImmed) (__vcfsx( (vSrcA), (uImmed) )) - -// set all components of a vector to a signed immediate int number. -/* as if: - FORCEINLINE fltx4 IntSetImmediateSIMD(int toImmediate) - { - return __vspltisw( toImmediate ); - } -*/ -#define IntSetImmediateSIMD(x) (__vspltisw(x)) - -/* - works on fltx4's as if they are four uints. - the first parameter contains the words to be shifted, - the second contains the amount to shift by AS INTS - - for i = 0 to 3 - shift = vSrcB_i*32:(i*32)+4 - vReturned_i*32:(i*32)+31 = vSrcA_i*32:(i*32)+31 << shift -*/ -FORCEINLINE fltx4 IntShiftLeftWordSIMD(fltx4 vSrcA, fltx4 vSrcB) -{ - return __vslw(vSrcA, vSrcB); -} - -FORCEINLINE float SubFloat( const fltx4 & a, int idx ) -{ - // NOTE: if the output goes into a register, this causes a Load-Hit-Store stall (don't mix fpu/vpu math!) - const fltx4_union & a_union = (const fltx4_union &)a; - return a_union.m128_f32[ idx ]; -} - -FORCEINLINE float & SubFloat( fltx4 & a, int idx ) -{ - fltx4_union & a_union = (fltx4_union &)a; - return a_union.m128_f32[idx]; -} - -FORCEINLINE uint32 SubFloatConvertToInt( const fltx4 & a, int idx ) -{ - fltx4 t = __vctuxs( a, 0 ); - const fltx4_union & a_union = (const fltx4_union &)t; - return a_union.m128_u32[idx]; -} - - -FORCEINLINE uint32 SubInt( const fltx4 & a, int idx ) -{ - const fltx4_union & a_union = (const fltx4_union &)a; - return a_union.m128_u32[idx]; -} - -FORCEINLINE uint32 & SubInt( fltx4 & a, int idx ) -{ - fltx4_union & a_union = (fltx4_union &)a; - return a_union.m128_u32[idx]; -} - -#else - -//--------------------------------------------------------------------- -// Intel/SSE implementation -//--------------------------------------------------------------------- - -FORCEINLINE void StoreAlignedSIMD( float * RESTRICT pSIMD, const fltx4 & a ) -{ - _mm_store_ps( pSIMD, a ); -} - -FORCEINLINE void StoreUnalignedSIMD( float * RESTRICT pSIMD, const fltx4 & a ) -{ - _mm_storeu_ps( pSIMD, a ); -} - - -FORCEINLINE fltx4 RotateLeft( const fltx4 & a ); -FORCEINLINE fltx4 RotateLeft2( const fltx4 & a ); - -FORCEINLINE void StoreUnaligned3SIMD( float *pSIMD, const fltx4 & a ) -{ - _mm_store_ss(pSIMD, a); - _mm_store_ss(pSIMD+1, RotateLeft(a)); - _mm_store_ss(pSIMD+2, RotateLeft2(a)); -} - -// strongly typed -- syntactic castor oil used for typechecking as we transition to SIMD -FORCEINLINE void StoreAligned3SIMD( VectorAligned * RESTRICT pSIMD, const fltx4 & a ) -{ - StoreAlignedSIMD( pSIMD->Base(),a ); -} - -FORCEINLINE fltx4 LoadAlignedSIMD( const void *pSIMD ) -{ - return _mm_load_ps( reinterpret_cast< const float *> ( pSIMD ) ); -} - -FORCEINLINE fltx4 AndSIMD( const fltx4 & a, const fltx4 & b ) // a & b -{ - return _mm_and_ps( a, b ); -} - -FORCEINLINE fltx4 AndNotSIMD( const fltx4 & a, const fltx4 & b ) // a & ~b -{ - return _mm_andnot_ps( a, b ); -} - -FORCEINLINE fltx4 XorSIMD( const fltx4 & a, const fltx4 & b ) // a ^ b -{ - return _mm_xor_ps( a, b ); -} - -FORCEINLINE fltx4 OrSIMD( const fltx4 & a, const fltx4 & b ) // a | b -{ - return _mm_or_ps( a, b ); -} - -// Squelch the w component of a vector to +0.0. -// Most efficient when you say a = SetWToZeroSIMD(a) (avoids a copy) -FORCEINLINE fltx4 SetWToZeroSIMD( const fltx4 & a ) -{ - return AndSIMD( a, LoadAlignedSIMD( g_SIMD_clear_wmask ) ); -} - -// for the transitional class -- load a 3-by VectorAligned and squash its w component -FORCEINLINE fltx4 LoadAlignedSIMD( const VectorAligned & pSIMD ) -{ - return SetWToZeroSIMD( LoadAlignedSIMD(pSIMD.Base()) ); -} - -FORCEINLINE fltx4 LoadUnalignedSIMD( const void *pSIMD ) -{ - return _mm_loadu_ps( reinterpret_cast( pSIMD ) ); -} - -FORCEINLINE fltx4 LoadUnaligned3SIMD( const void *pSIMD ) -{ - return _mm_loadu_ps( reinterpret_cast( pSIMD ) ); -} - -/// replicate a single 32 bit integer value to all 4 components of an m128 -FORCEINLINE fltx4 ReplicateIX4( int i ) -{ - fltx4 value = _mm_set_ss( * ( ( float *) &i ) );; - return _mm_shuffle_ps( value, value, 0); -} - - -FORCEINLINE fltx4 ReplicateX4( float flValue ) -{ - __m128 value = _mm_set_ss( flValue ); - return _mm_shuffle_ps( value, value, 0 ); -} - - -FORCEINLINE float SubFloat( const fltx4 & a, int idx ) -{ - // NOTE: if the output goes into a register, this causes a Load-Hit-Store stall (don't mix fpu/vpu math!) -#if !defined _LINUX && !defined __APPLE__ - return a.m128_f32[ idx ]; -#else - return (reinterpret_cast(&a))[idx]; -#endif -} - -FORCEINLINE float & SubFloat( fltx4 & a, int idx ) -{ -#if !defined _LINUX && !defined __APPLE__ - return a.m128_f32[ idx ]; -#else - return (reinterpret_cast(&a))[idx]; -#endif -} - -FORCEINLINE uint32 SubFloatConvertToInt( const fltx4 & a, int idx ) -{ - return (uint32)SubFloat(a,idx); -} - -FORCEINLINE uint32 SubInt( const fltx4 & a, int idx ) -{ -#if !defined _LINUX && !defined __APPLE__ - return a.m128_u32[idx]; -#else - return (reinterpret_cast(&a))[idx]; -#endif -} - -FORCEINLINE uint32 & SubInt( fltx4 & a, int idx ) -{ -#if !defined _LINUX && !defined __APPLE__ - return a.m128_u32[idx]; -#else - return (reinterpret_cast(&a))[idx]; -#endif -} - -// Return one in the fastest way -- on the x360, faster even than loading. -FORCEINLINE fltx4 LoadZeroSIMD( void ) -{ - return Four_Zeros; -} - -// Return one in the fastest way -- on the x360, faster even than loading. -FORCEINLINE fltx4 LoadOneSIMD( void ) -{ - return Four_Ones; -} - -FORCEINLINE fltx4 MaskedAssign( const fltx4 & ReplacementMask, const fltx4 & NewValue, const fltx4 & OldValue ) -{ - return OrSIMD( - AndSIMD( ReplacementMask, NewValue ), - AndNotSIMD( ReplacementMask, OldValue ) ); -} - -// remember, the SSE numbers its words 3 2 1 0 -// The way we want to specify shuffles is backwards from the default -// MM_SHUFFLE_REV is in array index order (default is reversed) -#define MM_SHUFFLE_REV(a,b,c,d) _MM_SHUFFLE(d,c,b,a) - -FORCEINLINE fltx4 SplatXSIMD( fltx4 const & a ) -{ - return _mm_shuffle_ps( a, a, MM_SHUFFLE_REV( 0, 0, 0, 0 ) ); -} - -FORCEINLINE fltx4 SplatYSIMD( fltx4 const &a ) -{ - return _mm_shuffle_ps( a, a, MM_SHUFFLE_REV( 1, 1, 1, 1 ) ); -} - -FORCEINLINE fltx4 SplatZSIMD( fltx4 const &a ) -{ - return _mm_shuffle_ps( a, a, MM_SHUFFLE_REV( 2, 2, 2, 2 ) ); -} - -FORCEINLINE fltx4 SplatWSIMD( fltx4 const &a ) -{ - return _mm_shuffle_ps( a, a, _MM_SHUFFLE( 3, 3, 3, 3 ) ); -} - -FORCEINLINE fltx4 SetXSIMD( const fltx4& a, const fltx4& x ) -{ - fltx4 result = MaskedAssign( LoadAlignedSIMD( g_SIMD_ComponentMask[0] ), x, a ); - return result; -} - -FORCEINLINE fltx4 SetYSIMD( const fltx4& a, const fltx4& y ) -{ - fltx4 result = MaskedAssign( LoadAlignedSIMD( g_SIMD_ComponentMask[1] ), y, a ); - return result; -} - -FORCEINLINE fltx4 SetZSIMD( const fltx4& a, const fltx4& z ) -{ - fltx4 result = MaskedAssign( LoadAlignedSIMD( g_SIMD_ComponentMask[2] ), z, a ); - return result; -} - -FORCEINLINE fltx4 SetWSIMD( const fltx4& a, const fltx4& w ) -{ - fltx4 result = MaskedAssign( LoadAlignedSIMD( g_SIMD_ComponentMask[3] ), w, a ); - return result; -} - -FORCEINLINE fltx4 SetComponentSIMD( const fltx4& a, int nComponent, float flValue ) -{ - fltx4 val = ReplicateX4( flValue ); - fltx4 result = MaskedAssign( LoadAlignedSIMD( g_SIMD_ComponentMask[nComponent] ), val, a ); - return result; -} - -// a b c d -> b c d a -FORCEINLINE fltx4 RotateLeft( const fltx4 & a ) -{ - return _mm_shuffle_ps( a, a, MM_SHUFFLE_REV( 1, 2, 3, 0 ) ); -} - -// a b c d -> c d a b -FORCEINLINE fltx4 RotateLeft2( const fltx4 & a ) -{ - return _mm_shuffle_ps( a, a, MM_SHUFFLE_REV( 2, 3, 0, 1 ) ); -} - -// a b c d -> d a b c -FORCEINLINE fltx4 RotateRight( const fltx4 & a ) -{ - return _mm_shuffle_ps( a, a, _MM_SHUFFLE( 0, 3, 2, 1) ); -} - -// a b c d -> c d a b -FORCEINLINE fltx4 RotateRight2( const fltx4 & a ) -{ - return _mm_shuffle_ps( a, a, _MM_SHUFFLE( 1, 0, 3, 2 ) ); -} - - -FORCEINLINE fltx4 AddSIMD( const fltx4 & a, const fltx4 & b ) // a+b -{ - return _mm_add_ps( a, b ); -}; - -FORCEINLINE fltx4 SubSIMD( const fltx4 & a, const fltx4 & b ) // a-b -{ - return _mm_sub_ps( a, b ); -}; - -FORCEINLINE fltx4 MulSIMD( const fltx4 & a, const fltx4 & b ) // a*b -{ - return _mm_mul_ps( a, b ); -}; - -FORCEINLINE fltx4 DivSIMD( const fltx4 & a, const fltx4 & b ) // a/b -{ - return _mm_div_ps( a, b ); -}; - -FORCEINLINE fltx4 MaddSIMD( const fltx4 & a, const fltx4 & b, const fltx4 & c ) // a*b + c -{ - return AddSIMD( MulSIMD(a,b), c ); -} - -FORCEINLINE fltx4 MsubSIMD( const fltx4 & a, const fltx4 & b, const fltx4 & c ) // c - a*b -{ - return SubSIMD( c, MulSIMD(a,b) ); -}; - -FORCEINLINE fltx4 Dot3SIMD( const fltx4 &a, const fltx4 &b ) -{ - fltx4 m = MulSIMD( a, b ); - float flDot = SubFloat( m, 0 ) + SubFloat( m, 1 ) + SubFloat( m, 2 ); - return ReplicateX4( flDot ); -} - -FORCEINLINE fltx4 Dot4SIMD( const fltx4 &a, const fltx4 &b ) -{ - fltx4 m = MulSIMD( a, b ); - float flDot = SubFloat( m, 0 ) + SubFloat( m, 1 ) + SubFloat( m, 2 ) + SubFloat( m, 3 ); - return ReplicateX4( flDot ); -} - -//TODO: implement as four-way Taylor series (see xbox implementation) -FORCEINLINE fltx4 SinSIMD( const fltx4 &radians ) -{ - fltx4 result; - SubFloat( result, 0 ) = sin( SubFloat( radians, 0 ) ); - SubFloat( result, 1 ) = sin( SubFloat( radians, 1 ) ); - SubFloat( result, 2 ) = sin( SubFloat( radians, 2 ) ); - SubFloat( result, 3 ) = sin( SubFloat( radians, 3 ) ); - return result; -} - -FORCEINLINE void SinCos3SIMD( fltx4 &sine, fltx4 &cosine, const fltx4 &radians ) -{ - // FIXME: Make a fast SSE version - SinCos( SubFloat( radians, 0 ), &SubFloat( sine, 0 ), &SubFloat( cosine, 0 ) ); - SinCos( SubFloat( radians, 1 ), &SubFloat( sine, 1 ), &SubFloat( cosine, 1 ) ); - SinCos( SubFloat( radians, 2 ), &SubFloat( sine, 2 ), &SubFloat( cosine, 2 ) ); -} - -FORCEINLINE void SinCosSIMD( fltx4 &sine, fltx4 &cosine, const fltx4 &radians ) // a*b + c -{ - // FIXME: Make a fast SSE version - SinCos( SubFloat( radians, 0 ), &SubFloat( sine, 0 ), &SubFloat( cosine, 0 ) ); - SinCos( SubFloat( radians, 1 ), &SubFloat( sine, 1 ), &SubFloat( cosine, 1 ) ); - SinCos( SubFloat( radians, 2 ), &SubFloat( sine, 2 ), &SubFloat( cosine, 2 ) ); - SinCos( SubFloat( radians, 3 ), &SubFloat( sine, 3 ), &SubFloat( cosine, 3 ) ); -} - -//TODO: implement as four-way Taylor series (see xbox implementation) -FORCEINLINE fltx4 ArcSinSIMD( const fltx4 &sine ) -{ - // FIXME: Make a fast SSE version - fltx4 result; - SubFloat( result, 0 ) = asin( SubFloat( sine, 0 ) ); - SubFloat( result, 1 ) = asin( SubFloat( sine, 1 ) ); - SubFloat( result, 2 ) = asin( SubFloat( sine, 2 ) ); - SubFloat( result, 3 ) = asin( SubFloat( sine, 3 ) ); - return result; -} - -FORCEINLINE fltx4 ArcCosSIMD( const fltx4 &cs ) -{ - fltx4 result; - SubFloat( result, 0 ) = acos( SubFloat( cs, 0 ) ); - SubFloat( result, 1 ) = acos( SubFloat( cs, 1 ) ); - SubFloat( result, 2 ) = acos( SubFloat( cs, 2 ) ); - SubFloat( result, 3 ) = acos( SubFloat( cs, 3 ) ); - return result; -} - -// tan^1(a/b) .. ie, pass sin in as a and cos in as b -FORCEINLINE fltx4 ArcTan2SIMD( const fltx4 &a, const fltx4 &b ) -{ - fltx4 result; - SubFloat( result, 0 ) = atan2( SubFloat( a, 0 ), SubFloat( b, 0 ) ); - SubFloat( result, 1 ) = atan2( SubFloat( a, 1 ), SubFloat( b, 1 ) ); - SubFloat( result, 2 ) = atan2( SubFloat( a, 2 ), SubFloat( b, 2 ) ); - SubFloat( result, 3 ) = atan2( SubFloat( a, 3 ), SubFloat( b, 3 ) ); - return result; -} - -FORCEINLINE fltx4 NegSIMD(const fltx4 &a) // negate: -a -{ - return SubSIMD(LoadZeroSIMD(),a); -} - -FORCEINLINE int TestSignSIMD( const fltx4 & a ) // mask of which floats have the high bit set -{ - return _mm_movemask_ps( a ); -} - -FORCEINLINE bool IsAnyNegative( const fltx4 & a ) // (a.x < 0) || (a.y < 0) || (a.z < 0) || (a.w < 0) -{ - return (0 != TestSignSIMD( a )); -} - -FORCEINLINE fltx4 CmpEqSIMD( const fltx4 & a, const fltx4 & b ) // (a==b) ? ~0:0 -{ - return _mm_cmpeq_ps( a, b ); -} - -FORCEINLINE fltx4 CmpGtSIMD( const fltx4 & a, const fltx4 & b ) // (a>b) ? ~0:0 -{ - return _mm_cmpgt_ps( a, b ); -} - -FORCEINLINE fltx4 CmpGeSIMD( const fltx4 & a, const fltx4 & b ) // (a>=b) ? ~0:0 -{ - return _mm_cmpge_ps( a, b ); -} - -FORCEINLINE fltx4 CmpLtSIMD( const fltx4 & a, const fltx4 & b ) // (a b.xyzw -FORCEINLINE bool IsAllGreaterThan( const fltx4 &a, const fltx4 &b ) -{ - return TestSignSIMD( CmpLeSIMD( a, b ) ) == 0; -} - -// for branching when a.xyzw >= b.xyzw -FORCEINLINE bool IsAllGreaterThanOrEq( const fltx4 &a, const fltx4 &b ) -{ - return TestSignSIMD( CmpLtSIMD( a, b ) ) == 0; -} - -// For branching if all a.xyzw == b.xyzw -FORCEINLINE bool IsAllEqual( const fltx4 & a, const fltx4 & b ) -{ - return TestSignSIMD( CmpEqSIMD( a, b ) ) == 0xf; -} - -FORCEINLINE fltx4 CmpInBoundsSIMD( const fltx4 & a, const fltx4 & b ) // (a <= b && a >= -b) ? ~0 : 0 -{ - return AndSIMD( CmpLeSIMD(a,b), CmpGeSIMD(a, NegSIMD(b)) ); -} - -FORCEINLINE fltx4 MinSIMD( const fltx4 & a, const fltx4 & b ) // MIN(a,b) -{ - return _mm_min_ps( a, b ); -} - -FORCEINLINE fltx4 MaxSIMD( const fltx4 & a, const fltx4 & b ) // MAX(a,b) -{ - return _mm_max_ps( a, b ); -} - - - -// SSE lacks rounding operations. -// Really. -// You can emulate them by setting the rounding mode for the -// whole processor and then converting to int, and then back again. -// But every time you set the rounding mode, you clear out the -// entire pipeline. So, I can't do them per operation. You -// have to do it once, before the loop that would call these. -// Round towards positive infinity -FORCEINLINE fltx4 CeilSIMD( const fltx4 &a ) -{ - fltx4 retVal; - SubFloat( retVal, 0 ) = ceil( SubFloat( a, 0 ) ); - SubFloat( retVal, 1 ) = ceil( SubFloat( a, 1 ) ); - SubFloat( retVal, 2 ) = ceil( SubFloat( a, 2 ) ); - SubFloat( retVal, 3 ) = ceil( SubFloat( a, 3 ) ); - return retVal; - -} - -fltx4 fabs( const fltx4 & x ); -// Round towards negative infinity -// This is the implementation that was here before; it assumes -// you are in round-to-floor mode, which I guess is usually the -// case for us vis-a-vis SSE. It's totally unnecessary on -// VMX, which has a native floor op. -FORCEINLINE fltx4 FloorSIMD( const fltx4 &val ) -{ - fltx4 fl4Abs = fabs( val ); - fltx4 ival = SubSIMD( AddSIMD( fl4Abs, Four_2ToThe23s ), Four_2ToThe23s ); - ival = MaskedAssign( CmpGtSIMD( ival, fl4Abs ), SubSIMD( ival, Four_Ones ), ival ); - return XorSIMD( ival, XorSIMD( val, fl4Abs ) ); // restore sign bits -} - - - -inline bool IsAllZeros( const fltx4 & var ) -{ - return TestSignSIMD( CmpEqSIMD( var, Four_Zeros ) ) == 0xF; -} - -FORCEINLINE fltx4 SqrtEstSIMD( const fltx4 & a ) // sqrt(a), more or less -{ - return _mm_sqrt_ps( a ); -} - -FORCEINLINE fltx4 SqrtSIMD( const fltx4 & a ) // sqrt(a) -{ - return _mm_sqrt_ps( a ); -} - -FORCEINLINE fltx4 ReciprocalSqrtEstSIMD( const fltx4 & a ) // 1/sqrt(a), more or less -{ - return _mm_rsqrt_ps( a ); -} - -FORCEINLINE fltx4 ReciprocalSqrtEstSaturateSIMD( const fltx4 & a ) -{ - fltx4 zero_mask = CmpEqSIMD( a, Four_Zeros ); - fltx4 ret = OrSIMD( a, AndSIMD( Four_Epsilons, zero_mask ) ); - ret = ReciprocalSqrtEstSIMD( ret ); - return ret; -} - -/// uses newton iteration for higher precision results than ReciprocalSqrtEstSIMD -FORCEINLINE fltx4 ReciprocalSqrtSIMD( const fltx4 & a ) // 1/sqrt(a) -{ - fltx4 guess = ReciprocalSqrtEstSIMD( a ); - // newton iteration for 1/sqrt(a) : y(n+1) = 1/2 (y(n)*(3-a*y(n)^2)); - guess = MulSIMD( guess, SubSIMD( Four_Threes, MulSIMD( a, MulSIMD( guess, guess )))); - guess = MulSIMD( Four_PointFives, guess); - return guess; -} - -FORCEINLINE fltx4 ReciprocalEstSIMD( const fltx4 & a ) // 1/a, more or less -{ - return _mm_rcp_ps( a ); -} - -/// 1/x for all 4 values, more or less -/// 1/0 will result in a big but NOT infinite result -FORCEINLINE fltx4 ReciprocalEstSaturateSIMD( const fltx4 & a ) -{ - fltx4 zero_mask = CmpEqSIMD( a, Four_Zeros ); - fltx4 ret = OrSIMD( a, AndSIMD( Four_Epsilons, zero_mask ) ); - ret = ReciprocalEstSIMD( ret ); - return ret; -} - -/// 1/x for all 4 values. uses reciprocal approximation instruction plus newton iteration. -/// No error checking! -FORCEINLINE fltx4 ReciprocalSIMD( const fltx4 & a ) // 1/a -{ - fltx4 ret = ReciprocalEstSIMD( a ); - // newton iteration is: Y(n+1) = 2*Y(n)-a*Y(n)^2 - ret = SubSIMD( AddSIMD( ret, ret ), MulSIMD( a, MulSIMD( ret, ret ) ) ); - return ret; -} - -/// 1/x for all 4 values. -/// 1/0 will result in a big but NOT infinite result -FORCEINLINE fltx4 ReciprocalSaturateSIMD( const fltx4 & a ) -{ - fltx4 zero_mask = CmpEqSIMD( a, Four_Zeros ); - fltx4 ret = OrSIMD( a, AndSIMD( Four_Epsilons, zero_mask ) ); - ret = ReciprocalSIMD( ret ); - return ret; -} - -// CHRISG: is it worth doing integer bitfiddling for this? -// 2^x for all values (the antilog) -FORCEINLINE fltx4 ExpSIMD( const fltx4 &toPower ) -{ - fltx4 retval; - SubFloat( retval, 0 ) = powf( 2, SubFloat(toPower, 0) ); - SubFloat( retval, 1 ) = powf( 2, SubFloat(toPower, 1) ); - SubFloat( retval, 2 ) = powf( 2, SubFloat(toPower, 2) ); - SubFloat( retval, 3 ) = powf( 2, SubFloat(toPower, 3) ); - - return retval; -} - -// Clamps the components of a vector to a specified minimum and maximum range. -FORCEINLINE fltx4 ClampVectorSIMD( FLTX4 in, FLTX4 min, FLTX4 max) -{ - return MaxSIMD( min, MinSIMD( max, in ) ); -} - -FORCEINLINE void TransposeSIMD( fltx4 & x, fltx4 & y, fltx4 & z, fltx4 & w) -{ - _MM_TRANSPOSE4_PS( x, y, z, w ); -} - -FORCEINLINE fltx4 FindLowestSIMD3( const fltx4 &a ) -{ - // a is [x,y,z,G] (where G is garbage) - // rotate left by one - fltx4 compareOne = RotateLeft( a ); - // compareOne is [y,z,G,x] - fltx4 retval = MinSIMD( a, compareOne ); - // retVal is [MIN(x,y), ... ] - compareOne = RotateLeft2( a ); - // compareOne is [z, G, x, y] - retval = MinSIMD( retval, compareOne ); - // retVal = [ MIN(MIN(x,y),z)..] - // splat the x component out to the whole vector and return - return SplatXSIMD( retval ); - -} - -FORCEINLINE fltx4 FindHighestSIMD3( const fltx4 &a ) -{ - // a is [x,y,z,G] (where G is garbage) - // rotate left by one - fltx4 compareOne = RotateLeft( a ); - // compareOne is [y,z,G,x] - fltx4 retval = MaxSIMD( a, compareOne ); - // retVal is [MAX(x,y), ... ] - compareOne = RotateLeft2( a ); - // compareOne is [z, G, x, y] - retval = MaxSIMD( retval, compareOne ); - // retVal = [ MAX(MAX(x,y),z)..] - // splat the x component out to the whole vector and return - return SplatXSIMD( retval ); - -} - -// ------------------------------------ -// INTEGER SIMD OPERATIONS. -// ------------------------------------ - - -#if 0 /* pc does not have these ops */ -// splat all components of a vector to a signed immediate int number. -FORCEINLINE fltx4 IntSetImmediateSIMD(int to) -{ - //CHRISG: SSE2 has this, but not SSE1. What to do? - fltx4 retval; - SubInt( retval, 0 ) = to; - SubInt( retval, 1 ) = to; - SubInt( retval, 2 ) = to; - SubInt( retval, 3 ) = to; - return retval; -} -#endif - -// Load 4 aligned words into a SIMD register -FORCEINLINE i32x4 LoadAlignedIntSIMD( const void * RESTRICT pSIMD) -{ - return _mm_load_ps( reinterpret_cast(pSIMD) ); -} - -// Load 4 unaligned words into a SIMD register -FORCEINLINE i32x4 LoadUnalignedIntSIMD( const void * RESTRICT pSIMD) -{ - return _mm_loadu_ps( reinterpret_cast(pSIMD) ); -} - -// save into four words, 16-byte aligned -FORCEINLINE void StoreAlignedIntSIMD( int32 * RESTRICT pSIMD, const fltx4 & a ) -{ - _mm_store_ps( reinterpret_cast(pSIMD), a ); -} - -FORCEINLINE void StoreAlignedIntSIMD( intx4 &pSIMD, const fltx4 & a ) -{ - _mm_store_ps( reinterpret_cast(pSIMD.Base()), a ); -} - -FORCEINLINE void StoreUnalignedIntSIMD( int32 * RESTRICT pSIMD, const fltx4 & a ) -{ - _mm_storeu_ps( reinterpret_cast(pSIMD), a ); -} - - -// CHRISG: the conversion functions all seem to operate on m64's only... -// how do we make them work here? - -// Take a fltx4 containing fixed-point uints and -// return them as single precision floats. No -// fixed point conversion is done. -FORCEINLINE fltx4 UnsignedIntConvertToFltSIMD( const u32x4 &vSrcA ) -{ - fltx4 retval; - SubFloat( retval, 0 ) = ( (float) SubInt( retval, 0 ) ); - SubFloat( retval, 1 ) = ( (float) SubInt( retval, 1 ) ); - SubFloat( retval, 2 ) = ( (float) SubInt( retval, 2 ) ); - SubFloat( retval, 3 ) = ( (float) SubInt( retval, 3 ) ); - return retval; -} - - -// Take a fltx4 containing fixed-point sints and -// return them as single precision floats. No -// fixed point conversion is done. -FORCEINLINE fltx4 SignedIntConvertToFltSIMD( const i32x4 &vSrcA ) -{ - fltx4 retval; - SubFloat( retval, 0 ) = ( (float) (reinterpret_cast(&vSrcA)[0])); - SubFloat( retval, 1 ) = ( (float) (reinterpret_cast(&vSrcA)[1])); - SubFloat( retval, 2 ) = ( (float) (reinterpret_cast(&vSrcA)[2])); - SubFloat( retval, 3 ) = ( (float) (reinterpret_cast(&vSrcA)[3])); - return retval; -} - -/* - works on fltx4's as if they are four uints. - the first parameter contains the words to be shifted, - the second contains the amount to shift by AS INTS - - for i = 0 to 3 - shift = vSrcB_i*32:(i*32)+4 - vReturned_i*32:(i*32)+31 = vSrcA_i*32:(i*32)+31 << shift -*/ -FORCEINLINE i32x4 IntShiftLeftWordSIMD(const i32x4 &vSrcA, const i32x4 &vSrcB) -{ - i32x4 retval; - SubInt(retval, 0) = SubInt(vSrcA, 0) << SubInt(vSrcB, 0); - SubInt(retval, 1) = SubInt(vSrcA, 1) << SubInt(vSrcB, 1); - SubInt(retval, 2) = SubInt(vSrcA, 2) << SubInt(vSrcB, 2); - SubInt(retval, 3) = SubInt(vSrcA, 3) << SubInt(vSrcB, 3); - - - return retval; -} - - -// Fixed-point conversion and save as SIGNED INTS. -// pDest->x = Int (vSrc.x) -// note: some architectures have means of doing -// fixed point conversion when the fix depth is -// specified as an immediate.. but there is no way -// to guarantee an immediate as a parameter to function -// like this. -FORCEINLINE void ConvertStoreAsIntsSIMD(intx4 * RESTRICT pDest, const fltx4 &vSrc) -{ - __m64 bottom = _mm_cvttps_pi32( vSrc ); - __m64 top = _mm_cvttps_pi32( _mm_movehl_ps(vSrc,vSrc) ); - - *reinterpret_cast<__m64 *>(&(*pDest)[0]) = bottom; - *reinterpret_cast<__m64 *>(&(*pDest)[2]) = top; - - _mm_empty(); -} - - - -#endif - - - -/// class FourVectors stores 4 independent vectors for use in SIMD processing. These vectors are -/// stored in the format x x x x y y y y z z z z so that they can be efficiently SIMD-accelerated. -class ALIGN16 FourVectors -{ -public: - fltx4 x, y, z; - - FORCEINLINE void DuplicateVector(Vector const &v) //< set all 4 vectors to the same vector value - { - x=ReplicateX4(v.x); - y=ReplicateX4(v.y); - z=ReplicateX4(v.z); - } - - FORCEINLINE fltx4 const & operator[](int idx) const - { - return *((&x)+idx); - } - - FORCEINLINE fltx4 & operator[](int idx) - { - return *((&x)+idx); - } - - FORCEINLINE void operator+=(FourVectors const &b) //< add 4 vectors to another 4 vectors - { - x=AddSIMD(x,b.x); - y=AddSIMD(y,b.y); - z=AddSIMD(z,b.z); - } - - FORCEINLINE void operator-=(FourVectors const &b) //< subtract 4 vectors from another 4 - { - x=SubSIMD(x,b.x); - y=SubSIMD(y,b.y); - z=SubSIMD(z,b.z); - } - - FORCEINLINE void operator*=(FourVectors const &b) //< scale all four vectors per component scale - { - x=MulSIMD(x,b.x); - y=MulSIMD(y,b.y); - z=MulSIMD(z,b.z); - } - - FORCEINLINE void operator*=(const fltx4 & scale) //< scale - { - x=MulSIMD(x,scale); - y=MulSIMD(y,scale); - z=MulSIMD(z,scale); - } - - FORCEINLINE void operator*=(float scale) //< uniformly scale all 4 vectors - { - fltx4 scalepacked = ReplicateX4(scale); - *this *= scalepacked; - } - - FORCEINLINE fltx4 operator*(FourVectors const &b) const //< 4 dot products - { - fltx4 dot=MulSIMD(x,b.x); - dot=MaddSIMD(y,b.y,dot); - dot=MaddSIMD(z,b.z,dot); - return dot; - } - - FORCEINLINE fltx4 operator*(Vector const &b) const //< dot product all 4 vectors with 1 vector - { - fltx4 dot=MulSIMD(x,ReplicateX4(b.x)); - dot=MaddSIMD(y,ReplicateX4(b.y), dot); - dot=MaddSIMD(z,ReplicateX4(b.z), dot); - return dot; - } - - FORCEINLINE void VProduct(FourVectors const &b) //< component by component mul - { - x=MulSIMD(x,b.x); - y=MulSIMD(y,b.y); - z=MulSIMD(z,b.z); - } - FORCEINLINE void MakeReciprocal(void) //< (x,y,z)=(1/x,1/y,1/z) - { - x=ReciprocalSIMD(x); - y=ReciprocalSIMD(y); - z=ReciprocalSIMD(z); - } - - FORCEINLINE void MakeReciprocalSaturate(void) //< (x,y,z)=(1/x,1/y,1/z), 1/0=1.0e23 - { - x=ReciprocalSaturateSIMD(x); - y=ReciprocalSaturateSIMD(y); - z=ReciprocalSaturateSIMD(z); - } - - // Assume the given matrix is a rotation, and rotate these vectors by it. - // If you have a long list of FourVectors structures that you all want - // to rotate by the same matrix, use FourVectors::RotateManyBy() instead. - inline void RotateBy(const matrix3x4_t& matrix); - - /// You can use this to rotate a long array of FourVectors all by the same - /// matrix. The first parameter is the head of the array. The second is the - /// number of vectors to rotate. The third is the matrix. - static void RotateManyBy(FourVectors * RESTRICT pVectors, unsigned int numVectors, const matrix3x4_t& rotationMatrix ); - - /// Assume the vectors are points, and transform them in place by the matrix. - inline void TransformBy(const matrix3x4_t& matrix); - - /// You can use this to Transform a long array of FourVectors all by the same - /// matrix. The first parameter is the head of the array. The second is the - /// number of vectors to rotate. The third is the matrix. The fourth is the - /// output buffer, which must not overlap the pVectors buffer. This is not - /// an in-place transformation. - static void TransformManyBy(FourVectors * RESTRICT pVectors, unsigned int numVectors, const matrix3x4_t& rotationMatrix, FourVectors * RESTRICT pOut ); - - /// You can use this to Transform a long array of FourVectors all by the same - /// matrix. The first parameter is the head of the array. The second is the - /// number of vectors to rotate. The third is the matrix. The fourth is the - /// output buffer, which must not overlap the pVectors buffer. - /// This is an in-place transformation. - static void TransformManyBy(FourVectors * RESTRICT pVectors, unsigned int numVectors, const matrix3x4_t& rotationMatrix ); - - // X(),Y(),Z() - get at the desired component of the i'th (0..3) vector. - FORCEINLINE const float & X(int idx) const - { - // NOTE: if the output goes into a register, this causes a Load-Hit-Store stall (don't mix fpu/vpu math!) - return SubFloat( (fltx4 &)x, idx ); - } - - FORCEINLINE const float & Y(int idx) const - { - return SubFloat( (fltx4 &)y, idx ); - } - - FORCEINLINE const float & Z(int idx) const - { - return SubFloat( (fltx4 &)z, idx ); - } - - FORCEINLINE float & X(int idx) - { - return SubFloat( x, idx ); - } - - FORCEINLINE float & Y(int idx) - { - return SubFloat( y, idx ); - } - - FORCEINLINE float & Z(int idx) - { - return SubFloat( z, idx ); - } - - FORCEINLINE Vector Vec(int idx) const //< unpack one of the vectors - { - return Vector( X(idx), Y(idx), Z(idx) ); - } - - FourVectors(void) - { - } - - FourVectors( FourVectors const &src ) - { - x=src.x; - y=src.y; - z=src.z; - } - - FORCEINLINE void operator=( FourVectors const &src ) - { - x=src.x; - y=src.y; - z=src.z; - } - - /// LoadAndSwizzle - load 4 Vectors into a FourVectors, performing transpose op - FORCEINLINE void LoadAndSwizzle(Vector const &a, Vector const &b, Vector const &c, Vector const &d) - { - // TransposeSIMD has large sub-expressions that the compiler can't eliminate on x360 - // use an unfolded implementation here -#if _X360 - fltx4 tx = LoadUnalignedSIMD( &a.x ); - fltx4 ty = LoadUnalignedSIMD( &b.x ); - fltx4 tz = LoadUnalignedSIMD( &c.x ); - fltx4 tw = LoadUnalignedSIMD( &d.x ); - fltx4 r0 = __vmrghw(tx, tz); - fltx4 r1 = __vmrghw(ty, tw); - fltx4 r2 = __vmrglw(tx, tz); - fltx4 r3 = __vmrglw(ty, tw); - - x = __vmrghw(r0, r1); - y = __vmrglw(r0, r1); - z = __vmrghw(r2, r3); -#else - x = LoadUnalignedSIMD( &( a.x )); - y = LoadUnalignedSIMD( &( b.x )); - z = LoadUnalignedSIMD( &( c.x )); - fltx4 w = LoadUnalignedSIMD( &( d.x )); - // now, matrix is: - // x y z ? - // x y z ? - // x y z ? - // x y z ? - TransposeSIMD(x, y, z, w); -#endif - } - - /// LoadAndSwizzleAligned - load 4 Vectors into a FourVectors, performing transpose op. - /// all 4 vectors must be 128 bit boundary - FORCEINLINE void LoadAndSwizzleAligned(const float *RESTRICT a, const float *RESTRICT b, const float *RESTRICT c, const float *RESTRICT d) - { -#if _X360 - fltx4 tx = LoadAlignedSIMD(a); - fltx4 ty = LoadAlignedSIMD(b); - fltx4 tz = LoadAlignedSIMD(c); - fltx4 tw = LoadAlignedSIMD(d); - fltx4 r0 = __vmrghw(tx, tz); - fltx4 r1 = __vmrghw(ty, tw); - fltx4 r2 = __vmrglw(tx, tz); - fltx4 r3 = __vmrglw(ty, tw); - - x = __vmrghw(r0, r1); - y = __vmrglw(r0, r1); - z = __vmrghw(r2, r3); -#else - x = LoadAlignedSIMD( a ); - y = LoadAlignedSIMD( b ); - z = LoadAlignedSIMD( c ); - fltx4 w = LoadAlignedSIMD( d ); - // now, matrix is: - // x y z ? - // x y z ? - // x y z ? - // x y z ? - TransposeSIMD( x, y, z, w ); -#endif - } - - FORCEINLINE void LoadAndSwizzleAligned(Vector const &a, Vector const &b, Vector const &c, Vector const &d) - { - LoadAndSwizzleAligned( &a.x, &b.x, &c.x, &d.x ); - } - - /// return the squared length of all 4 vectors - FORCEINLINE fltx4 length2(void) const - { - return (*this)*(*this); - } - - /// return the approximate length of all 4 vectors. uses the sqrt approximation instruction - FORCEINLINE fltx4 length(void) const - { - return SqrtEstSIMD(length2()); - } - - /// normalize all 4 vectors in place. not mega-accurate (uses reciprocal approximation instruction) - FORCEINLINE void VectorNormalizeFast(void) - { - fltx4 mag_sq=(*this)*(*this); // length^2 - (*this) *= ReciprocalSqrtEstSIMD(mag_sq); // *(1.0/sqrt(length^2)) - } - - /// normalize all 4 vectors in place. - FORCEINLINE void VectorNormalize(void) - { - fltx4 mag_sq=(*this)*(*this); // length^2 - (*this) *= ReciprocalSqrtSIMD(mag_sq); // *(1.0/sqrt(length^2)) - } - - /// construct a FourVectors from 4 separate Vectors - FORCEINLINE FourVectors(Vector const &a, Vector const &b, Vector const &c, Vector const &d) - { - LoadAndSwizzle(a,b,c,d); - } - - /// construct a FourVectors from 4 separate Vectors - FORCEINLINE FourVectors(VectorAligned const &a, VectorAligned const &b, VectorAligned const &c, VectorAligned const &d) - { - LoadAndSwizzleAligned(a,b,c,d); - } - - FORCEINLINE fltx4 DistToSqr( FourVectors const &pnt ) - { - fltx4 fl4dX = SubSIMD( pnt.x, x ); - fltx4 fl4dY = SubSIMD( pnt.y, y ); - fltx4 fl4dZ = SubSIMD( pnt.z, z ); - return AddSIMD( MulSIMD( fl4dX, fl4dX), AddSIMD( MulSIMD( fl4dY, fl4dY ), MulSIMD( fl4dZ, fl4dZ ) ) ); - - } - - FORCEINLINE fltx4 TValueOfClosestPointOnLine( FourVectors const &p0, FourVectors const &p1 ) const - { - FourVectors lineDelta = p1; - lineDelta -= p0; - fltx4 OOlineDirDotlineDir = ReciprocalSIMD( p1 * p1 ); - FourVectors v4OurPnt = *this; - v4OurPnt -= p0; - return MulSIMD( OOlineDirDotlineDir, v4OurPnt * lineDelta ); - } - - FORCEINLINE fltx4 DistSqrToLineSegment( FourVectors const &p0, FourVectors const &p1 ) const - { - FourVectors lineDelta = p1; - FourVectors v4OurPnt = *this; - v4OurPnt -= p0; - lineDelta -= p0; - - fltx4 OOlineDirDotlineDir = ReciprocalSIMD( lineDelta * lineDelta ); - - fltx4 fl4T = MulSIMD( OOlineDirDotlineDir, v4OurPnt * lineDelta ); - - fl4T = MinSIMD( fl4T, Four_Ones ); - fl4T = MaxSIMD( fl4T, Four_Zeros ); - lineDelta *= fl4T; - return v4OurPnt.DistToSqr( lineDelta ); - } - -}; - -/// form 4 cross products -inline FourVectors operator ^(const FourVectors &a, const FourVectors &b) -{ - FourVectors ret; - ret.x=SubSIMD(MulSIMD(a.y,b.z),MulSIMD(a.z,b.y)); - ret.y=SubSIMD(MulSIMD(a.z,b.x),MulSIMD(a.x,b.z)); - ret.z=SubSIMD(MulSIMD(a.x,b.y),MulSIMD(a.y,b.x)); - return ret; -} - -/// component-by-componentwise MAX operator -inline FourVectors maximum(const FourVectors &a, const FourVectors &b) -{ - FourVectors ret; - ret.x=MaxSIMD(a.x,b.x); - ret.y=MaxSIMD(a.y,b.y); - ret.z=MaxSIMD(a.z,b.z); - return ret; -} - -/// component-by-componentwise MIN operator -inline FourVectors minimum(const FourVectors &a, const FourVectors &b) -{ - FourVectors ret; - ret.x=MinSIMD(a.x,b.x); - ret.y=MinSIMD(a.y,b.y); - ret.z=MinSIMD(a.z,b.z); - return ret; -} - -/// calculate reflection vector. incident and normal dir assumed normalized -FORCEINLINE FourVectors VectorReflect( const FourVectors &incident, const FourVectors &normal ) -{ - FourVectors ret = incident; - fltx4 iDotNx2 = incident * normal; - iDotNx2 = AddSIMD( iDotNx2, iDotNx2 ); - FourVectors nPart = normal; - nPart *= iDotNx2; - ret -= nPart; // i-2(n*i)n - return ret; -} - -/// calculate slide vector. removes all components of a vector which are perpendicular to a normal vector. -FORCEINLINE FourVectors VectorSlide( const FourVectors &incident, const FourVectors &normal ) -{ - FourVectors ret = incident; - fltx4 iDotN = incident * normal; - FourVectors nPart = normal; - nPart *= iDotN; - ret -= nPart; // i-(n*i)n - return ret; -} - - -// Assume the given matrix is a rotation, and rotate these vectors by it. -// If you have a long list of FourVectors structures that you all want -// to rotate by the same matrix, use FourVectors::RotateManyBy() instead. -void FourVectors::RotateBy(const matrix3x4_t& matrix) -{ - // Splat out each of the entries in the matrix to a fltx4. Do this - // in the order that we will need them, to hide latency. I'm - // avoiding making an array of them, so that they'll remain in - // registers. - fltx4 matSplat00, matSplat01, matSplat02, - matSplat10, matSplat11, matSplat12, - matSplat20, matSplat21, matSplat22; - - { - // Load the matrix into local vectors. Sadly, matrix3x4_ts are - // often unaligned. The w components will be the tranpose row of - // the matrix, but we don't really care about that. - fltx4 matCol0 = LoadUnalignedSIMD( matrix[0] ); - fltx4 matCol1 = LoadUnalignedSIMD( matrix[1] ); - fltx4 matCol2 = LoadUnalignedSIMD( matrix[2] ); - - matSplat00 = SplatXSIMD( matCol0 ); - matSplat01 = SplatYSIMD( matCol0 ); - matSplat02 = SplatZSIMD( matCol0 ); - - matSplat10 = SplatXSIMD( matCol1 ); - matSplat11 = SplatYSIMD( matCol1 ); - matSplat12 = SplatZSIMD( matCol1 ); - - matSplat20 = SplatXSIMD( matCol2 ); - matSplat21 = SplatYSIMD( matCol2 ); - matSplat22 = SplatZSIMD( matCol2 ); - } - - // Trust in the compiler to schedule these operations correctly: - fltx4 outX, outY, outZ; - outX = AddSIMD( AddSIMD( MulSIMD( x, matSplat00 ), MulSIMD( y, matSplat01 ) ), MulSIMD( z, matSplat02 ) ); - outY = AddSIMD( AddSIMD( MulSIMD( x, matSplat10 ), MulSIMD( y, matSplat11 ) ), MulSIMD( z, matSplat12 ) ); - outZ = AddSIMD( AddSIMD( MulSIMD( x, matSplat20 ), MulSIMD( y, matSplat21 ) ), MulSIMD( z, matSplat22 ) ); - - x = outX; - y = outY; - z = outZ; -} - -// Assume the given matrix is a rotation, and rotate these vectors by it. -// If you have a long list of FourVectors structures that you all want -// to rotate by the same matrix, use FourVectors::RotateManyBy() instead. -void FourVectors::TransformBy(const matrix3x4_t& matrix) -{ - // Splat out each of the entries in the matrix to a fltx4. Do this - // in the order that we will need them, to hide latency. I'm - // avoiding making an array of them, so that they'll remain in - // registers. - fltx4 matSplat00, matSplat01, matSplat02, - matSplat10, matSplat11, matSplat12, - matSplat20, matSplat21, matSplat22; - - { - // Load the matrix into local vectors. Sadly, matrix3x4_ts are - // often unaligned. The w components will be the tranpose row of - // the matrix, but we don't really care about that. - fltx4 matCol0 = LoadUnalignedSIMD( matrix[0] ); - fltx4 matCol1 = LoadUnalignedSIMD( matrix[1] ); - fltx4 matCol2 = LoadUnalignedSIMD( matrix[2] ); - - matSplat00 = SplatXSIMD( matCol0 ); - matSplat01 = SplatYSIMD( matCol0 ); - matSplat02 = SplatZSIMD( matCol0 ); - - matSplat10 = SplatXSIMD( matCol1 ); - matSplat11 = SplatYSIMD( matCol1 ); - matSplat12 = SplatZSIMD( matCol1 ); - - matSplat20 = SplatXSIMD( matCol2 ); - matSplat21 = SplatYSIMD( matCol2 ); - matSplat22 = SplatZSIMD( matCol2 ); - } - - // Trust in the compiler to schedule these operations correctly: - fltx4 outX, outY, outZ; - - outX = MaddSIMD( z, matSplat02, AddSIMD( MulSIMD( x, matSplat00 ), MulSIMD( y, matSplat01 ) ) ); - outY = MaddSIMD( z, matSplat12, AddSIMD( MulSIMD( x, matSplat10 ), MulSIMD( y, matSplat11 ) ) ); - outZ = MaddSIMD( z, matSplat22, AddSIMD( MulSIMD( x, matSplat20 ), MulSIMD( y, matSplat21 ) ) ); - - x = AddSIMD( outX, ReplicateX4( matrix[0][3] )); - y = AddSIMD( outY, ReplicateX4( matrix[1][3] )); - z = AddSIMD( outZ, ReplicateX4( matrix[2][3] )); -} - - - -/// quick, low quality perlin-style noise() function suitable for real time use. -/// return value is -1..1. Only reliable around +/- 1 million or so. -fltx4 NoiseSIMD( const fltx4 & x, const fltx4 & y, const fltx4 & z ); -fltx4 NoiseSIMD( FourVectors const &v ); - -// vector valued noise direction -FourVectors DNoiseSIMD( FourVectors const &v ); - -// vector value "curl" noise function. see http://hyperphysics.phy-astr.gsu.edu/hbase/curl.html -FourVectors CurlNoiseSIMD( FourVectors const &v ); - - -/// calculate the absolute value of a packed single -inline fltx4 fabs( const fltx4 & x ) -{ - return AndSIMD( x, LoadAlignedSIMD( g_SIMD_clear_signmask ) ); -} - -/// negate all four components of a SIMD packed single -inline fltx4 fnegate( const fltx4 & x ) -{ - return XorSIMD( x, LoadAlignedSIMD( g_SIMD_signmask ) ); -} - - -fltx4 Pow_FixedPoint_Exponent_SIMD( const fltx4 & x, int exponent); - -// PowSIMD - raise a SIMD register to a power. This is analogous to the C pow() function, with some -// restictions: fractional exponents are only handled with 2 bits of precision. Basically, -// fractions of 0,.25,.5, and .75 are handled. PowSIMD(x,.30) will be the same as PowSIMD(x,.25). -// negative and fractional powers are handled by the SIMD reciprocal and square root approximation -// instructions and so are not especially accurate ----Note that this routine does not raise -// numeric exceptions because it uses SIMD--- This routine is O(log2(exponent)). -inline fltx4 PowSIMD( const fltx4 & x, float exponent ) -{ - return Pow_FixedPoint_Exponent_SIMD(x,(int) (4.0*exponent)); -} - - - -// random number generation - generate 4 random numbers quickly. - -void SeedRandSIMD(uint32 seed); // seed the random # generator -fltx4 RandSIMD( int nContext = 0 ); // return 4 numbers in the 0..1 range - -// for multithreaded, you need to use these and use the argument form of RandSIMD: -int GetSIMDRandContext( void ); -void ReleaseSIMDRandContext( int nContext ); - -FORCEINLINE fltx4 RandSignedSIMD( void ) // -1..1 -{ - return SubSIMD( MulSIMD( Four_Twos, RandSIMD() ), Four_Ones ); -} - - -// SIMD versions of mathlib simplespline functions -// hermite basis function for smooth interpolation -// Similar to Gain() above, but very cheap to call -// value should be between 0 & 1 inclusive -inline fltx4 SimpleSpline( const fltx4 & value ) -{ - // Arranged to avoid a data dependency between these two MULs: - fltx4 valueDoubled = MulSIMD( value, Four_Twos ); - fltx4 valueSquared = MulSIMD( value, value ); - - // Nice little ease-in, ease-out spline-like curve - return SubSIMD( - MulSIMD( Four_Threes, valueSquared ), - MulSIMD( valueDoubled, valueSquared ) ); -} - -// remaps a value in [startInterval, startInterval+rangeInterval] from linear to -// spline using SimpleSpline -inline fltx4 SimpleSplineRemapValWithDeltas( const fltx4 & val, - const fltx4 & A, const fltx4 & BMinusA, - const fltx4 & OneOverBMinusA, const fltx4 & C, - const fltx4 & DMinusC ) -{ -// if ( A == B ) -// return val >= B ? D : C; - fltx4 cVal = MulSIMD( SubSIMD( val, A), OneOverBMinusA ); - return AddSIMD( C, MulSIMD( DMinusC, SimpleSpline( cVal ) ) ); -} - -inline fltx4 SimpleSplineRemapValWithDeltasClamped( const fltx4 & val, - const fltx4 & A, const fltx4 & BMinusA, - const fltx4 & OneOverBMinusA, const fltx4 & C, - const fltx4 & DMinusC ) -{ -// if ( A == B ) -// return val >= B ? D : C; - fltx4 cVal = MulSIMD( SubSIMD( val, A), OneOverBMinusA ); - cVal = MinSIMD( Four_Ones, MaxSIMD( Four_Zeros, cVal ) ); - return AddSIMD( C, MulSIMD( DMinusC, SimpleSpline( cVal ) ) ); -} - -FORCEINLINE fltx4 FracSIMD( const fltx4 &val ) -{ - fltx4 fl4Abs = fabs( val ); - fltx4 ival = SubSIMD( AddSIMD( fl4Abs, Four_2ToThe23s ), Four_2ToThe23s ); - ival = MaskedAssign( CmpGtSIMD( ival, fl4Abs ), SubSIMD( ival, Four_Ones ), ival ); - return XorSIMD( SubSIMD( fl4Abs, ival ), XorSIMD( val, fl4Abs ) ); // restore sign bits -} - -FORCEINLINE fltx4 Mod2SIMD( const fltx4 &val ) -{ - fltx4 fl4Abs = fabs( val ); - fltx4 ival = SubSIMD( AndSIMD( LoadAlignedSIMD( (float *) g_SIMD_lsbmask ), AddSIMD( fl4Abs, Four_2ToThe23s ) ), Four_2ToThe23s ); - ival = MaskedAssign( CmpGtSIMD( ival, fl4Abs ), SubSIMD( ival, Four_Twos ), ival ); - return XorSIMD( SubSIMD( fl4Abs, ival ), XorSIMD( val, fl4Abs ) ); // restore sign bits -} - -FORCEINLINE fltx4 Mod2SIMDPositiveInput( const fltx4 &val ) -{ - fltx4 ival = SubSIMD( AndSIMD( LoadAlignedSIMD( g_SIMD_lsbmask ), AddSIMD( val, Four_2ToThe23s ) ), Four_2ToThe23s ); - ival = MaskedAssign( CmpGtSIMD( ival, val ), SubSIMD( ival, Four_Twos ), ival ); - return SubSIMD( val, ival ); -} - - -// approximate sin of an angle, with -1..1 representing the whole sin wave period instead of -pi..pi. -// no range reduction is done - for values outside of 0..1 you won't like the results -FORCEINLINE fltx4 _SinEst01SIMD( const fltx4 &val ) -{ - // really rough approximation - x*(4-x*4) - a parabola. s(0) = 0, s(.5) = 1, s(1)=0, smooth in-between. - // sufficient for simple oscillation. - return MulSIMD( val, SubSIMD( Four_Fours, MulSIMD( val, Four_Fours ) ) ); -} - -FORCEINLINE fltx4 _Sin01SIMD( const fltx4 &val ) -{ - // not a bad approximation : parabola always over-estimates. Squared parabola always - // underestimates. So lets blend between them: goodsin = badsin + .225*( badsin^2-badsin) - fltx4 fl4BadEst = MulSIMD( val, SubSIMD( Four_Fours, MulSIMD( val, Four_Fours ) ) ); - return AddSIMD( MulSIMD( Four_Point225s, SubSIMD( MulSIMD( fl4BadEst, fl4BadEst ), fl4BadEst ) ), fl4BadEst ); -} - -// full range useable implementations -FORCEINLINE fltx4 SinEst01SIMD( const fltx4 &val ) -{ - fltx4 fl4Abs = fabs( val ); - fltx4 fl4Reduced2 = Mod2SIMDPositiveInput( fl4Abs ); - fltx4 fl4OddMask = CmpGeSIMD( fl4Reduced2, Four_Ones ); - fltx4 fl4val = SubSIMD( fl4Reduced2, AndSIMD( Four_Ones, fl4OddMask ) ); - fltx4 fl4Sin = _SinEst01SIMD( fl4val ); - fl4Sin = XorSIMD( fl4Sin, AndSIMD( LoadAlignedSIMD( g_SIMD_signmask ), XorSIMD( val, fl4OddMask ) ) ); - return fl4Sin; - -} - -FORCEINLINE fltx4 Sin01SIMD( const fltx4 &val ) -{ - fltx4 fl4Abs = fabs( val ); - fltx4 fl4Reduced2 = Mod2SIMDPositiveInput( fl4Abs ); - fltx4 fl4OddMask = CmpGeSIMD( fl4Reduced2, Four_Ones ); - fltx4 fl4val = SubSIMD( fl4Reduced2, AndSIMD( Four_Ones, fl4OddMask ) ); - fltx4 fl4Sin = _Sin01SIMD( fl4val ); - fl4Sin = XorSIMD( fl4Sin, AndSIMD( LoadAlignedSIMD( g_SIMD_signmask ), XorSIMD( val, fl4OddMask ) ) ); - return fl4Sin; - -} - -// Schlick style Bias approximation see graphics gems 4 : bias(t,a)= t/( (1/a-2)*(1-t)+1) - -FORCEINLINE fltx4 PreCalcBiasParameter( const fltx4 &bias_parameter ) -{ - // convert perlin-style-bias parameter to the value right for the approximation - return SubSIMD( ReciprocalSIMD( bias_parameter ), Four_Twos ); -} - -FORCEINLINE fltx4 BiasSIMD( const fltx4 &val, const fltx4 &precalc_param ) -{ - // similar to bias function except pass precalced bias value from calling PreCalcBiasParameter. - - //!!speed!! use reciprocal est? - //!!speed!! could save one op by precalcing _2_ values - return DivSIMD( val, AddSIMD( MulSIMD( precalc_param, SubSIMD( Four_Ones, val ) ), Four_Ones ) ); -} - -//----------------------------------------------------------------------------- -// Box/plane test -// NOTE: The w component of emins + emaxs must be 1 for this to work -//----------------------------------------------------------------------------- -FORCEINLINE int BoxOnPlaneSideSIMD( const fltx4& emins, const fltx4& emaxs, const cplane_t *p, float tolerance = 0.f ) -{ - fltx4 corners[2]; - fltx4 normal = LoadUnalignedSIMD( p->normal.Base() ); - fltx4 dist = ReplicateX4( -p->dist ); - normal = SetWSIMD( normal, dist ); - fltx4 t4 = ReplicateX4( tolerance ); - fltx4 negt4 = ReplicateX4( -tolerance ); - fltx4 cmp = CmpGeSIMD( normal, Four_Zeros ); - corners[0] = MaskedAssign( cmp, emaxs, emins ); - corners[1] = MaskedAssign( cmp, emins, emaxs ); - fltx4 dot1 = Dot4SIMD( normal, corners[0] ); - fltx4 dot2 = Dot4SIMD( normal, corners[1] ); - cmp = CmpGeSIMD( dot1, t4 ); - fltx4 cmp2 = CmpGtSIMD( negt4, dot2 ); - fltx4 result = MaskedAssign( cmp, Four_Ones, Four_Zeros ); - fltx4 result2 = MaskedAssign( cmp2, Four_Twos, Four_Zeros ); - result = AddSIMD( result, result2 ); - intx4 sides; - ConvertStoreAsIntsSIMD( &sides, result ); - return sides[0]; -} - -#endif // _ssemath_h diff --git a/public/mathlib/ssequaternion.h b/public/mathlib/ssequaternion.h deleted file mode 100644 index bdc858a4c..000000000 --- a/public/mathlib/ssequaternion.h +++ /dev/null @@ -1,367 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: - defines SIMD "structure of arrays" classes and functions. -// -//===========================================================================// -#ifndef SSEQUATMATH_H -#define SSEQUATMATH_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "mathlib/ssemath.h" - -// Use this #define to allow SSE versions of Quaternion math -// to exist on PC. -// On PC, certain horizontal vector operations are not supported. -// This causes the SSE implementation of quaternion math to mix the -// vector and scalar floating point units, which is extremely -// performance negative if you don't compile to native SSE2 (which -// we don't as of Sept 1, 2007). So, it's best not to allow these -// functions to exist at all. It's not good enough to simply replace -// the contents of the functions with scalar math, because each call -// to LoadAligned and StoreAligned will result in an unnecssary copy -// of the quaternion, and several moves to and from the XMM registers. -// -// Basically, the problem you run into is that for efficient SIMD code, -// you need to load the quaternions and vectors into SIMD registers and -// keep them there as long as possible while doing only SIMD math, -// whereas for efficient scalar code, each time you copy onto or ever -// use a fltx4, it hoses your pipeline. So the difference has to be -// in the management of temporary variables in the calling function, -// not inside the math functions. -// -// If you compile assuming the presence of SSE2, the MSVC will abandon -// the traditional x87 FPU operations altogether and make everything use -// the SSE2 registers, which lessens this problem a little. - -// permitted only on 360, as we've done careful tuning on its Altivec math: -#ifdef _X360 -#define ALLOW_SIMD_QUATERNION_MATH 1 // not on PC! -#endif - - - -//--------------------------------------------------------------------- -// Load/store quaternions -//--------------------------------------------------------------------- -#ifndef _X360 -#if ALLOW_SIMD_QUATERNION_MATH -// Using STDC or SSE -FORCEINLINE fltx4 LoadAlignedSIMD( const QuaternionAligned & pSIMD ) -{ - fltx4 retval = LoadAlignedSIMD( pSIMD.Base() ); - return retval; -} - -FORCEINLINE fltx4 LoadAlignedSIMD( const QuaternionAligned * RESTRICT pSIMD ) -{ - fltx4 retval = LoadAlignedSIMD( pSIMD ); - return retval; -} - -FORCEINLINE void StoreAlignedSIMD( QuaternionAligned * RESTRICT pSIMD, const fltx4 & a ) -{ - StoreAlignedSIMD( pSIMD->Base(), a ); -} -#endif -#else - -// for the transitional class -- load a QuaternionAligned -FORCEINLINE fltx4 LoadAlignedSIMD( const QuaternionAligned & pSIMD ) -{ - fltx4 retval = XMLoadVector4A( pSIMD.Base() ); - return retval; -} - -FORCEINLINE fltx4 LoadAlignedSIMD( const QuaternionAligned * RESTRICT pSIMD ) -{ - fltx4 retval = XMLoadVector4A( pSIMD ); - return retval; -} - -FORCEINLINE void StoreAlignedSIMD( QuaternionAligned * RESTRICT pSIMD, const fltx4 & a ) -{ - XMStoreVector4A( pSIMD->Base(), a ); -} - -#endif - - -#if ALLOW_SIMD_QUATERNION_MATH -//--------------------------------------------------------------------- -// Make sure quaternions are within 180 degrees of one another, if not, reverse q -//--------------------------------------------------------------------- -FORCEINLINE fltx4 QuaternionAlignSIMD( const fltx4 &p, const fltx4 &q ) -{ - // decide if one of the quaternions is backwards - fltx4 a = SubSIMD( p, q ); - fltx4 b = AddSIMD( p, q ); - a = Dot4SIMD( a, a ); - b = Dot4SIMD( b, b ); - fltx4 cmp = CmpGtSIMD( a, b ); - fltx4 result = MaskedAssign( cmp, NegSIMD(q), q ); - return result; -} - -//--------------------------------------------------------------------- -// Normalize Quaternion -//--------------------------------------------------------------------- -#if USE_STDC_FOR_SIMD - -FORCEINLINE fltx4 QuaternionNormalizeSIMD( const fltx4 &q ) -{ - fltx4 radius, result; - radius = Dot4SIMD( q, q ); - - if ( SubFloat( radius, 0 ) ) // > FLT_EPSILON && ((radius < 1.0f - 4*FLT_EPSILON) || (radius > 1.0f + 4*FLT_EPSILON)) - { - float iradius = 1.0f / sqrt( SubFloat( radius, 0 ) ); - result = ReplicateX4( iradius ); - result = MulSIMD( result, q ); - return result; - } - return q; -} - -#else - -// SSE + X360 implementation -FORCEINLINE fltx4 QuaternionNormalizeSIMD( const fltx4 &q ) -{ - fltx4 radius, result, mask; - radius = Dot4SIMD( q, q ); - mask = CmpEqSIMD( radius, Four_Zeros ); // all ones iff radius = 0 - result = ReciprocalSqrtSIMD( radius ); - result = MulSIMD( result, q ); - return MaskedAssign( mask, q, result ); // if radius was 0, just return q -} - -#endif - - -//--------------------------------------------------------------------- -// 0.0 returns p, 1.0 return q. -//--------------------------------------------------------------------- -FORCEINLINE fltx4 QuaternionBlendNoAlignSIMD( const fltx4 &p, const fltx4 &q, float t ) -{ - fltx4 sclp, sclq, result; - sclq = ReplicateX4( t ); - sclp = SubSIMD( Four_Ones, sclq ); - result = MulSIMD( sclp, p ); - result = MaddSIMD( sclq, q, result ); - return QuaternionNormalizeSIMD( result ); -} - - -//--------------------------------------------------------------------- -// Blend Quaternions -//--------------------------------------------------------------------- -FORCEINLINE fltx4 QuaternionBlendSIMD( const fltx4 &p, const fltx4 &q, float t ) -{ - // decide if one of the quaternions is backwards - fltx4 q2, result; - q2 = QuaternionAlignSIMD( p, q ); - result = QuaternionBlendNoAlignSIMD( p, q2, t ); - return result; -} - - -//--------------------------------------------------------------------- -// Multiply Quaternions -//--------------------------------------------------------------------- -#ifndef _X360 - -// SSE and STDC -FORCEINLINE fltx4 QuaternionMultSIMD( const fltx4 &p, const fltx4 &q ) -{ - // decide if one of the quaternions is backwards - fltx4 q2, result; - q2 = QuaternionAlignSIMD( p, q ); - SubFloat( result, 0 ) = SubFloat( p, 0 ) * SubFloat( q2, 3 ) + SubFloat( p, 1 ) * SubFloat( q2, 2 ) - SubFloat( p, 2 ) * SubFloat( q2, 1 ) + SubFloat( p, 3 ) * SubFloat( q2, 0 ); - SubFloat( result, 1 ) = -SubFloat( p, 0 ) * SubFloat( q2, 2 ) + SubFloat( p, 1 ) * SubFloat( q2, 3 ) + SubFloat( p, 2 ) * SubFloat( q2, 0 ) + SubFloat( p, 3 ) * SubFloat( q2, 1 ); - SubFloat( result, 2 ) = SubFloat( p, 0 ) * SubFloat( q2, 1 ) - SubFloat( p, 1 ) * SubFloat( q2, 0 ) + SubFloat( p, 2 ) * SubFloat( q2, 3 ) + SubFloat( p, 3 ) * SubFloat( q2, 2 ); - SubFloat( result, 3 ) = -SubFloat( p, 0 ) * SubFloat( q2, 0 ) - SubFloat( p, 1 ) * SubFloat( q2, 1 ) - SubFloat( p, 2 ) * SubFloat( q2, 2 ) + SubFloat( p, 3 ) * SubFloat( q2, 3 ); - return result; -} - -#else - -// X360 -extern const fltx4 g_QuatMultRowSign[4]; -FORCEINLINE fltx4 QuaternionMultSIMD( const fltx4 &p, const fltx4 &q ) -{ - fltx4 q2, row, result; - q2 = QuaternionAlignSIMD( p, q ); - - row = XMVectorSwizzle( q2, 3, 2, 1, 0 ); - row = MulSIMD( row, g_QuatMultRowSign[0] ); - result = Dot4SIMD( row, p ); - - row = XMVectorSwizzle( q2, 2, 3, 0, 1 ); - row = MulSIMD( row, g_QuatMultRowSign[1] ); - row = Dot4SIMD( row, p ); - result = __vrlimi( result, row, 4, 0 ); - - row = XMVectorSwizzle( q2, 1, 0, 3, 2 ); - row = MulSIMD( row, g_QuatMultRowSign[2] ); - row = Dot4SIMD( row, p ); - result = __vrlimi( result, row, 2, 0 ); - - row = MulSIMD( q2, g_QuatMultRowSign[3] ); - row = Dot4SIMD( row, p ); - result = __vrlimi( result, row, 1, 0 ); - return result; -} - -#endif - - -//--------------------------------------------------------------------- -// Quaternion scale -//--------------------------------------------------------------------- -#ifndef _X360 - -// SSE and STDC -FORCEINLINE fltx4 QuaternionScaleSIMD( const fltx4 &p, float t ) -{ - float r; - fltx4 q; - - // FIXME: nick, this isn't overly sensitive to accuracy, and it may be faster to - // use the cos part (w) of the quaternion (sin(omega)*N,cos(omega)) to figure the new scale. - float sinom = sqrt( SubFloat( p, 0 ) * SubFloat( p, 0 ) + SubFloat( p, 1 ) * SubFloat( p, 1 ) + SubFloat( p, 2 ) * SubFloat( p, 2 ) ); - sinom = MIN( sinom, 1.f ); - - float sinsom = sin( asin( sinom ) * t ); - - t = sinsom / (sinom + FLT_EPSILON); - SubFloat( q, 0 ) = t * SubFloat( p, 0 ); - SubFloat( q, 1 ) = t * SubFloat( p, 1 ); - SubFloat( q, 2 ) = t * SubFloat( p, 2 ); - - // rescale rotation - r = 1.0f - sinsom * sinsom; - - // Assert( r >= 0 ); - if (r < 0.0f) - r = 0.0f; - r = sqrt( r ); - - // keep sign of rotation - SubFloat( q, 3 ) = fsel( SubFloat( p, 3 ), r, -r ); - return q; -} - -#else - -// X360 -FORCEINLINE fltx4 QuaternionScaleSIMD( const fltx4 &p, float t ) -{ - fltx4 sinom = Dot3SIMD( p, p ); - sinom = SqrtSIMD( sinom ); - sinom = MinSIMD( sinom, Four_Ones ); - fltx4 sinsom = ArcSinSIMD( sinom ); - fltx4 t4 = ReplicateX4( t ); - sinsom = MulSIMD( sinsom, t4 ); - sinsom = SinSIMD( sinsom ); - sinom = AddSIMD( sinom, Four_Epsilons ); - sinom = ReciprocalSIMD( sinom ); - t4 = MulSIMD( sinsom, sinom ); - fltx4 result = MulSIMD( p, t4 ); - - // rescale rotation - sinsom = MulSIMD( sinsom, sinsom ); - fltx4 r = SubSIMD( Four_Ones, sinsom ); - r = MaxSIMD( r, Four_Zeros ); - r = SqrtSIMD( r ); - - // keep sign of rotation - fltx4 cmp = CmpGeSIMD( p, Four_Zeros ); - r = MaskedAssign( cmp, r, NegSIMD( r ) ); - - result = __vrlimi(result, r, 1, 0); - return result; -} - -#endif - - -//----------------------------------------------------------------------------- -// Quaternion sphereical linear interpolation -//----------------------------------------------------------------------------- -#ifndef _X360 - -// SSE and STDC -FORCEINLINE fltx4 QuaternionSlerpNoAlignSIMD( const fltx4 &p, const fltx4 &q, float t ) -{ - float omega, cosom, sinom, sclp, sclq; - - fltx4 result; - - // 0.0 returns p, 1.0 return q. - cosom = SubFloat( p, 0 ) * SubFloat( q, 0 ) + SubFloat( p, 1 ) * SubFloat( q, 1 ) + - SubFloat( p, 2 ) * SubFloat( q, 2 ) + SubFloat( p, 3 ) * SubFloat( q, 3 ); - - if ( (1.0f + cosom ) > 0.000001f ) - { - if ( (1.0f - cosom ) > 0.000001f ) - { - omega = acos( cosom ); - sinom = sin( omega ); - sclp = sin( (1.0f - t)*omega) / sinom; - sclq = sin( t*omega ) / sinom; - } - else - { - // TODO: add short circuit for cosom == 1.0f? - sclp = 1.0f - t; - sclq = t; - } - SubFloat( result, 0 ) = sclp * SubFloat( p, 0 ) + sclq * SubFloat( q, 0 ); - SubFloat( result, 1 ) = sclp * SubFloat( p, 1 ) + sclq * SubFloat( q, 1 ); - SubFloat( result, 2 ) = sclp * SubFloat( p, 2 ) + sclq * SubFloat( q, 2 ); - SubFloat( result, 3 ) = sclp * SubFloat( p, 3 ) + sclq * SubFloat( q, 3 ); - } - else - { - SubFloat( result, 0 ) = -SubFloat( q, 1 ); - SubFloat( result, 1 ) = SubFloat( q, 0 ); - SubFloat( result, 2 ) = -SubFloat( q, 3 ); - SubFloat( result, 3 ) = SubFloat( q, 2 ); - sclp = sin( (1.0f - t) * (0.5f * M_PI)); - sclq = sin( t * (0.5f * M_PI)); - SubFloat( result, 0 ) = sclp * SubFloat( p, 0 ) + sclq * SubFloat( result, 0 ); - SubFloat( result, 1 ) = sclp * SubFloat( p, 1 ) + sclq * SubFloat( result, 1 ); - SubFloat( result, 2 ) = sclp * SubFloat( p, 2 ) + sclq * SubFloat( result, 2 ); - } - - return result; -} - -#else - -// X360 -FORCEINLINE fltx4 QuaternionSlerpNoAlignSIMD( const fltx4 &p, const fltx4 &q, float t ) -{ - return XMQuaternionSlerp( p, q, t ); -} - -#endif - - -FORCEINLINE fltx4 QuaternionSlerpSIMD( const fltx4 &p, const fltx4 &q, float t ) -{ - fltx4 q2, result; - q2 = QuaternionAlignSIMD( p, q ); - result = QuaternionSlerpNoAlignSIMD( p, q2, t ); - return result; -} - - -#endif // ALLOW_SIMD_QUATERNION_MATH - -#endif // SSEQUATMATH_H - diff --git a/public/mathlib/vector.h b/public/mathlib/vector.h deleted file mode 100644 index f315b208c..000000000 --- a/public/mathlib/vector.h +++ /dev/null @@ -1,2233 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef VECTOR_H -#define VECTOR_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -// For vec_t, put this somewhere else? -#include "tier0/basetypes.h" - -// For rand(). We really need a library! -#include - -#ifndef _X360 -// For MMX intrinsics -#include -#endif - -#include "tier0/dbg.h" -#include "tier0/threadtools.h" -#include "mathlib/vector2d.h" -#include "mathlib/math_pfns.h" - -// Uncomment this to add extra Asserts to check for NANs, uninitialized vecs, etc. -//#define VECTOR_PARANOIA 1 - -// Uncomment this to make sure we don't do anything slow with our vectors -//#define VECTOR_NO_SLOW_OPERATIONS 1 - - -// Used to make certain code easier to read. -#define X_INDEX 0 -#define Y_INDEX 1 -#define Z_INDEX 2 - - -#ifdef VECTOR_PARANOIA -#define CHECK_VALID( _v) Assert( (_v).IsValid() ) -#else -#define CHECK_VALID( _v) -#endif - -#define VecToString(v) (static_cast(CFmtStr("(%f, %f, %f)", (v).x, (v).y, (v).z))) // ** Note: this generates a temporary, don't hold reference! - -class VectorByValue; - -//========================================================= -// 3D Vector -//========================================================= -class Vector -{ -public: - // Members - vec_t x, y, z; - - // Construction/destruction: - Vector(void); - Vector(vec_t X, vec_t Y, vec_t Z); - Vector(vec_t XYZ); // TODO (Ilya): is this potentially a bad idea? - - // Initialization - void Init(vec_t ix=0.0f, vec_t iy=0.0f, vec_t iz=0.0f); - // TODO (Ilya): Should there be an init that takes a single float for consistency? - - // Got any nasty NAN's? - bool IsValid() const; - void Invalidate(); - - // array access... - vec_t operator[](int i) const; - vec_t& operator[](int i); - - // Base address... - vec_t* Base(); - vec_t const* Base() const; - - // Cast to Vector2D... - Vector2D& AsVector2D(); - const Vector2D& AsVector2D() const; - - // Initialization methods - void Random( vec_t minVal, vec_t maxVal ); - inline void Zero(); ///< zero out a vector - - // equality - bool operator==(const Vector& v) const; - bool operator!=(const Vector& v) const; - - // arithmetic operations - FORCEINLINE Vector& operator+=(const Vector &v); - FORCEINLINE Vector& operator-=(const Vector &v); - FORCEINLINE Vector& operator*=(const Vector &v); - FORCEINLINE Vector& operator*=(float s); - FORCEINLINE Vector& operator/=(const Vector &v); - FORCEINLINE Vector& operator/=(float s); - FORCEINLINE Vector& operator+=(float fl) ; ///< broadcast add - FORCEINLINE Vector& operator-=(float fl) ; ///< broadcast sub - -// negate the vector components - void Negate(); - - // Get the vector's magnitude. - inline vec_t Length() const; - - // Get the vector's magnitude squared. - FORCEINLINE vec_t LengthSqr(void) const - { - CHECK_VALID(*this); - return (x*x + y*y + z*z); - } - - // return true if this vector is (0,0,0) within tolerance - bool IsZero( float tolerance = 0.01f ) const - { - return (x > -tolerance && x < tolerance && - y > -tolerance && y < tolerance && - z > -tolerance && z < tolerance); - } - - vec_t NormalizeInPlace(); - bool IsLengthGreaterThan( float val ) const; - bool IsLengthLessThan( float val ) const; - - // check if a vector is within the box defined by two other vectors - FORCEINLINE bool WithinAABox( Vector const &boxmin, Vector const &boxmax); - - // Get the distance from this vector to the other one. - vec_t DistTo(const Vector &vOther) const; - - // Get the distance from this vector to the other one squared. - // NJS: note, VC wasn't inlining it correctly in several deeply nested inlines due to being an 'out of line' inline. - // may be able to tidy this up after switching to VC7 - FORCEINLINE vec_t DistToSqr(const Vector &vOther) const - { - Vector delta; - - delta.x = x - vOther.x; - delta.y = y - vOther.y; - delta.z = z - vOther.z; - - return delta.LengthSqr(); - } - - // Copy - void CopyToArray(float* rgfl) const; - - // Multiply, add, and assign to this (ie: *this = a + b * scalar). This - // is about 12% faster than the actual vector equation (because it's done per-component - // rather than per-vector). - void MulAdd(const Vector& a, const Vector& b, float scalar); - - // Dot product. - vec_t Dot(const Vector& vOther) const; - - // assignment - Vector& operator=(const Vector &vOther); - - // 2d - vec_t Length2D(void) const; - vec_t Length2DSqr(void) const; - - operator VectorByValue &() { return *((VectorByValue *)(this)); } - operator const VectorByValue &() const { return *((const VectorByValue *)(this)); } - -#ifndef VECTOR_NO_SLOW_OPERATIONS - // copy constructors -// Vector(const Vector &vOther); - - // arithmetic operations - Vector operator-(void) const; - - Vector operator+(const Vector& v) const; - Vector operator-(const Vector& v) const; - Vector operator*(const Vector& v) const; - Vector operator/(const Vector& v) const; - Vector operator*(float fl) const; - Vector operator/(float fl) const; - - // Cross product between two vectors. - Vector Cross(const Vector &vOther) const; - - // Returns a vector with the min or max in X, Y, and Z. - Vector Min(const Vector &vOther) const; - Vector Max(const Vector &vOther) const; - -#else - -private: - // No copy constructors allowed if we're in optimal mode - Vector(const Vector& vOther); -#endif -}; - - - -#define USE_M64S ( ( !defined( _X360 ) ) && ( ! defined( _LINUX) ) ) - - - -//========================================================= -// 4D Short Vector (aligned on 8-byte boundary) -//========================================================= -class ALIGN8 ShortVector -{ -public: - - short x, y, z, w; - - // Initialization - void Init(short ix = 0, short iy = 0, short iz = 0, short iw = 0 ); - - -#if USE_M64S - __m64 &AsM64() { return *(__m64*)&x; } - const __m64 &AsM64() const { return *(const __m64*)&x; } -#endif - - // Setter - void Set( const ShortVector& vOther ); - void Set( const short ix, const short iy, const short iz, const short iw ); - - // array access... - short operator[](int i) const; - short& operator[](int i); - - // Base address... - short* Base(); - short const* Base() const; - - // equality - bool operator==(const ShortVector& v) const; - bool operator!=(const ShortVector& v) const; - - // Arithmetic operations - FORCEINLINE ShortVector& operator+=(const ShortVector &v); - FORCEINLINE ShortVector& operator-=(const ShortVector &v); - FORCEINLINE ShortVector& operator*=(const ShortVector &v); - FORCEINLINE ShortVector& operator*=(float s); - FORCEINLINE ShortVector& operator/=(const ShortVector &v); - FORCEINLINE ShortVector& operator/=(float s); - FORCEINLINE ShortVector operator*(float fl) const; - -private: - - // No copy constructors allowed if we're in optimal mode -// ShortVector(ShortVector const& vOther); - - // No assignment operators either... -// ShortVector& operator=( ShortVector const& src ); - -}; - - - - - - -//========================================================= -// 4D Integer Vector -//========================================================= -class IntVector4D -{ -public: - - int x, y, z, w; - - // Initialization - void Init(int ix = 0, int iy = 0, int iz = 0, int iw = 0 ); - -#if USE_M64S - __m64 &AsM64() { return *(__m64*)&x; } - const __m64 &AsM64() const { return *(const __m64*)&x; } -#endif - - // Setter - void Set( const IntVector4D& vOther ); - void Set( const int ix, const int iy, const int iz, const int iw ); - - // array access... - int operator[](int i) const; - int& operator[](int i); - - // Base address... - int* Base(); - int const* Base() const; - - // equality - bool operator==(const IntVector4D& v) const; - bool operator!=(const IntVector4D& v) const; - - // Arithmetic operations - FORCEINLINE IntVector4D& operator+=(const IntVector4D &v); - FORCEINLINE IntVector4D& operator-=(const IntVector4D &v); - FORCEINLINE IntVector4D& operator*=(const IntVector4D &v); - FORCEINLINE IntVector4D& operator*=(float s); - FORCEINLINE IntVector4D& operator/=(const IntVector4D &v); - FORCEINLINE IntVector4D& operator/=(float s); - FORCEINLINE IntVector4D operator*(float fl) const; - -private: - - // No copy constructors allowed if we're in optimal mode - // IntVector4D(IntVector4D const& vOther); - - // No assignment operators either... - // IntVector4D& operator=( IntVector4D const& src ); - -}; - - - -//----------------------------------------------------------------------------- -// Allows us to specifically pass the vector by value when we need to -//----------------------------------------------------------------------------- -class VectorByValue : public Vector -{ -public: - // Construction/destruction: - VectorByValue(void) : Vector() {} - VectorByValue(vec_t X, vec_t Y, vec_t Z) : Vector( X, Y, Z ) {} - VectorByValue(const VectorByValue& vOther) { *this = vOther; } -}; - - -//----------------------------------------------------------------------------- -// Utility to simplify table construction. No constructor means can use -// traditional C-style initialization -//----------------------------------------------------------------------------- -class TableVector -{ -public: - vec_t x, y, z; - - operator Vector &() { return *((Vector *)(this)); } - operator const Vector &() const { return *((const Vector *)(this)); } - - // array access... - inline vec_t& operator[](int i) - { - Assert( (i >= 0) && (i < 3) ); - return ((vec_t*)this)[i]; - } - - inline vec_t operator[](int i) const - { - Assert( (i >= 0) && (i < 3) ); - return ((vec_t*)this)[i]; - } -}; - - -//----------------------------------------------------------------------------- -// Here's where we add all those lovely SSE optimized routines -//----------------------------------------------------------------------------- - -class ALIGN16 VectorAligned : public Vector -{ -public: - inline VectorAligned(void) {}; - inline VectorAligned(vec_t X, vec_t Y, vec_t Z) - { - Init(X,Y,Z); - } - -#ifdef VECTOR_NO_SLOW_OPERATIONS - -private: - // No copy constructors allowed if we're in optimal mode - VectorAligned(const VectorAligned& vOther); - VectorAligned(const Vector &vOther); - -#else -public: - explicit VectorAligned(const Vector &vOther) - { - Init(vOther.x, vOther.y, vOther.z); - } - - VectorAligned& operator=(const Vector &vOther) - { - Init(vOther.x, vOther.y, vOther.z); - return *this; - } - -#endif - float w; // this space is used anyway -}; - -//----------------------------------------------------------------------------- -// Vector related operations -//----------------------------------------------------------------------------- - -// Vector clear -FORCEINLINE void VectorClear( Vector& a ); - -// Copy -FORCEINLINE void VectorCopy( const Vector& src, Vector& dst ); - -// Vector arithmetic -FORCEINLINE void VectorAdd( const Vector& a, const Vector& b, Vector& result ); -FORCEINLINE void VectorSubtract( const Vector& a, const Vector& b, Vector& result ); -FORCEINLINE void VectorMultiply( const Vector& a, vec_t b, Vector& result ); -FORCEINLINE void VectorMultiply( const Vector& a, const Vector& b, Vector& result ); -FORCEINLINE void VectorDivide( const Vector& a, vec_t b, Vector& result ); -FORCEINLINE void VectorDivide( const Vector& a, const Vector& b, Vector& result ); -inline void VectorScale ( const Vector& in, vec_t scale, Vector& result ); -inline void VectorMA( const Vector& start, float scale, const Vector& direction, Vector& dest ); - -// Vector equality with tolerance -bool VectorsAreEqual( const Vector& src1, const Vector& src2, float tolerance = 0.0f ); - -#define VectorExpand(v) (v).x, (v).y, (v).z - - -// Normalization -// FIXME: Can't use quite yet -//vec_t VectorNormalize( Vector& v ); - -// Length -inline vec_t VectorLength( const Vector& v ); - -// Dot Product -FORCEINLINE vec_t DotProduct(const Vector& a, const Vector& b); - -// Cross product -void CrossProduct(const Vector& a, const Vector& b, Vector& result ); - -// Store the min or max of each of x, y, and z into the result. -void VectorMin( const Vector &a, const Vector &b, Vector &result ); -void VectorMax( const Vector &a, const Vector &b, Vector &result ); - -// Linearly interpolate between two vectors -void VectorLerp(const Vector& src1, const Vector& src2, vec_t t, Vector& dest ); - -#ifndef VECTOR_NO_SLOW_OPERATIONS - -// Cross product -Vector CrossProduct( const Vector& a, const Vector& b ); - -// Random vector creation -Vector RandomVector( vec_t minVal, vec_t maxVal ); - -#endif - -//----------------------------------------------------------------------------- -// -// Inlined Vector methods -// -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -// constructors -//----------------------------------------------------------------------------- -inline Vector::Vector(void) -{ -#ifdef _DEBUG -#ifdef VECTOR_PARANOIA - // Initialize to NAN to catch errors - x = y = z = VEC_T_NAN; -#endif -#endif -} - -inline Vector::Vector(vec_t X, vec_t Y, vec_t Z) -{ - x = X; y = Y; z = Z; - CHECK_VALID(*this); -} - -inline Vector::Vector(vec_t XYZ) -{ - x = y = z = XYZ; - CHECK_VALID(*this); -} - -//inline Vector::Vector(const float *pFloat) -//{ -// Assert( pFloat ); -// x = pFloat[0]; y = pFloat[1]; z = pFloat[2]; -// CHECK_VALID(*this); -//} - -#if 0 -//----------------------------------------------------------------------------- -// copy constructor -//----------------------------------------------------------------------------- - -inline Vector::Vector(const Vector &vOther) -{ - CHECK_VALID(vOther); - x = vOther.x; y = vOther.y; z = vOther.z; -} -#endif - -//----------------------------------------------------------------------------- -// initialization -//----------------------------------------------------------------------------- - -inline void Vector::Init( vec_t ix, vec_t iy, vec_t iz ) -{ - x = ix; y = iy; z = iz; - CHECK_VALID(*this); -} - -inline void Vector::Random( vec_t minVal, vec_t maxVal ) -{ - x = minVal + ((float)rand() / RAND_MAX) * (maxVal - minVal); - y = minVal + ((float)rand() / RAND_MAX) * (maxVal - minVal); - z = minVal + ((float)rand() / RAND_MAX) * (maxVal - minVal); - CHECK_VALID(*this); -} - -// This should really be a single opcode on the PowerPC (move r0 onto the vec reg) -inline void Vector::Zero() -{ - x = y = z = 0.0f; -} - -inline void VectorClear( Vector& a ) -{ - a.x = a.y = a.z = 0.0f; -} - -//----------------------------------------------------------------------------- -// assignment -//----------------------------------------------------------------------------- - -inline Vector& Vector::operator=(const Vector &vOther) -{ - CHECK_VALID(vOther); - x=vOther.x; y=vOther.y; z=vOther.z; - return *this; -} - - -//----------------------------------------------------------------------------- -// Array access -//----------------------------------------------------------------------------- -inline vec_t& Vector::operator[](int i) -{ - Assert( (i >= 0) && (i < 3) ); - return ((vec_t*)this)[i]; -} - -inline vec_t Vector::operator[](int i) const -{ - Assert( (i >= 0) && (i < 3) ); - return ((vec_t*)this)[i]; -} - - -//----------------------------------------------------------------------------- -// Base address... -//----------------------------------------------------------------------------- -inline vec_t* Vector::Base() -{ - return (vec_t*)this; -} - -inline vec_t const* Vector::Base() const -{ - return (vec_t const*)this; -} - -//----------------------------------------------------------------------------- -// Cast to Vector2D... -//----------------------------------------------------------------------------- - -inline Vector2D& Vector::AsVector2D() -{ - return *(Vector2D*)this; -} - -inline const Vector2D& Vector::AsVector2D() const -{ - return *(const Vector2D*)this; -} - -//----------------------------------------------------------------------------- -// IsValid? -//----------------------------------------------------------------------------- - -inline bool Vector::IsValid() const -{ - return IsFinite(x) && IsFinite(y) && IsFinite(z); -} - -//----------------------------------------------------------------------------- -// Invalidate -//----------------------------------------------------------------------------- - -inline void Vector::Invalidate() -{ -//#ifdef _DEBUG -//#ifdef VECTOR_PARANOIA - x = y = z = VEC_T_NAN; -//#endif -//#endif -} - -//----------------------------------------------------------------------------- -// comparison -//----------------------------------------------------------------------------- - -inline bool Vector::operator==( const Vector& src ) const -{ - CHECK_VALID(src); - CHECK_VALID(*this); - return (src.x == x) && (src.y == y) && (src.z == z); -} - -inline bool Vector::operator!=( const Vector& src ) const -{ - CHECK_VALID(src); - CHECK_VALID(*this); - return (src.x != x) || (src.y != y) || (src.z != z); -} - - -//----------------------------------------------------------------------------- -// Copy -//----------------------------------------------------------------------------- - -FORCEINLINE void VectorCopy( const Vector& src, Vector& dst ) -{ - CHECK_VALID(src); - dst.x = src.x; - dst.y = src.y; - dst.z = src.z; -} - -inline void Vector::CopyToArray(float* rgfl) const -{ - Assert( rgfl ); - CHECK_VALID(*this); - rgfl[0] = x, rgfl[1] = y, rgfl[2] = z; -} - -//----------------------------------------------------------------------------- -// standard math operations -//----------------------------------------------------------------------------- -// #pragma message("TODO: these should be SSE") - -inline void Vector::Negate() -{ - CHECK_VALID(*this); - x = -x; y = -y; z = -z; -} - -FORCEINLINE Vector& Vector::operator+=(const Vector& v) -{ - CHECK_VALID(*this); - CHECK_VALID(v); - x+=v.x; y+=v.y; z += v.z; - return *this; -} - -FORCEINLINE Vector& Vector::operator-=(const Vector& v) -{ - CHECK_VALID(*this); - CHECK_VALID(v); - x-=v.x; y-=v.y; z -= v.z; - return *this; -} - -FORCEINLINE Vector& Vector::operator*=(float fl) -{ - x *= fl; - y *= fl; - z *= fl; - CHECK_VALID(*this); - return *this; -} - -FORCEINLINE Vector& Vector::operator*=(const Vector& v) -{ - CHECK_VALID(v); - x *= v.x; - y *= v.y; - z *= v.z; - CHECK_VALID(*this); - return *this; -} - -// this ought to be an opcode. -FORCEINLINE Vector& Vector::operator+=(float fl) -{ - x += fl; - y += fl; - z += fl; - CHECK_VALID(*this); - return *this; -} - -FORCEINLINE Vector& Vector::operator-=(float fl) -{ - x -= fl; - y -= fl; - z -= fl; - CHECK_VALID(*this); - return *this; -} - - - -FORCEINLINE Vector& Vector::operator/=(float fl) -{ - Assert( fl != 0.0f ); - float oofl = 1.0f / fl; - x *= oofl; - y *= oofl; - z *= oofl; - CHECK_VALID(*this); - return *this; -} - -FORCEINLINE Vector& Vector::operator/=(const Vector& v) -{ - CHECK_VALID(v); - Assert( v.x != 0.0f && v.y != 0.0f && v.z != 0.0f ); - x /= v.x; - y /= v.y; - z /= v.z; - CHECK_VALID(*this); - return *this; -} - - - -//----------------------------------------------------------------------------- -// -// Inlined Short Vector methods -// -//----------------------------------------------------------------------------- - - -inline void ShortVector::Init( short ix, short iy, short iz, short iw ) -{ - x = ix; y = iy; z = iz; w = iw; -} - -FORCEINLINE void ShortVector::Set( const ShortVector& vOther ) -{ - x = vOther.x; - y = vOther.y; - z = vOther.z; - w = vOther.w; -} - -FORCEINLINE void ShortVector::Set( const short ix, const short iy, const short iz, const short iw ) -{ - x = ix; - y = iy; - z = iz; - w = iw; -} - - -//----------------------------------------------------------------------------- -// Array access -//----------------------------------------------------------------------------- -inline short ShortVector::operator[](int i) const -{ - Assert( (i >= 0) && (i < 4) ); - return ((short*)this)[i]; -} - -inline short& ShortVector::operator[](int i) -{ - Assert( (i >= 0) && (i < 4) ); - return ((short*)this)[i]; -} - -//----------------------------------------------------------------------------- -// Base address... -//----------------------------------------------------------------------------- -inline short* ShortVector::Base() -{ - return (short*)this; -} - -inline short const* ShortVector::Base() const -{ - return (short const*)this; -} - - -//----------------------------------------------------------------------------- -// comparison -//----------------------------------------------------------------------------- - -inline bool ShortVector::operator==( const ShortVector& src ) const -{ - return (src.x == x) && (src.y == y) && (src.z == z) && (src.w == w); -} - -inline bool ShortVector::operator!=( const ShortVector& src ) const -{ - return (src.x != x) || (src.y != y) || (src.z != z) || (src.w != w); -} - - - -//----------------------------------------------------------------------------- -// standard math operations -//----------------------------------------------------------------------------- - -FORCEINLINE ShortVector& ShortVector::operator+=(const ShortVector& v) -{ - x+=v.x; y+=v.y; z += v.z; w += v.w; - return *this; -} - -FORCEINLINE ShortVector& ShortVector::operator-=(const ShortVector& v) -{ - x-=v.x; y-=v.y; z -= v.z; w -= v.w; - return *this; -} - -FORCEINLINE ShortVector& ShortVector::operator*=(float fl) -{ - x = static_cast(x* fl); - y = static_cast(y * fl); - z = static_cast(z * fl); - w = static_cast(w * fl); - return *this; -} - -FORCEINLINE ShortVector& ShortVector::operator*=(const ShortVector& v) -{ - x *= v.x; - y *= v.y; - z *= v.z; - w *= v.w; - return *this; -} - -FORCEINLINE ShortVector& ShortVector::operator/=(float fl) -{ - Assert( fl != 0.0f ); - float oofl = 1.0f / fl; - x = static_cast(x * oofl); - y = static_cast(y * oofl); - z = static_cast(z * oofl); - w = static_cast(w * oofl); - return *this; -} - -FORCEINLINE ShortVector& ShortVector::operator/=(const ShortVector& v) -{ - Assert( v.x != 0 && v.y != 0 && v.z != 0 && v.w != 0 ); - x /= v.x; - y /= v.y; - z /= v.z; - w /= v.w; - return *this; -} - -FORCEINLINE void ShortVectorMultiply( const ShortVector& src, float fl, ShortVector& res ) -{ - Assert( IsFinite(fl) ); - res.x = static_cast(src.x * fl); - res.y = static_cast(src.y * fl); - res.z = static_cast(src.z * fl); - res.w = static_cast(src.w * fl); -} - -FORCEINLINE ShortVector ShortVector::operator*(float fl) const -{ - ShortVector res; - ShortVectorMultiply( *this, fl, res ); - return res; -} - - - - - - -//----------------------------------------------------------------------------- -// -// Inlined Integer Vector methods -// -//----------------------------------------------------------------------------- - - -inline void IntVector4D::Init( int ix, int iy, int iz, int iw ) -{ - x = ix; y = iy; z = iz; w = iw; -} - -FORCEINLINE void IntVector4D::Set( const IntVector4D& vOther ) -{ - x = vOther.x; - y = vOther.y; - z = vOther.z; - w = vOther.w; -} - -FORCEINLINE void IntVector4D::Set( const int ix, const int iy, const int iz, const int iw ) -{ - x = ix; - y = iy; - z = iz; - w = iw; -} - - -//----------------------------------------------------------------------------- -// Array access -//----------------------------------------------------------------------------- -inline int IntVector4D::operator[](int i) const -{ - Assert( (i >= 0) && (i < 4) ); - return ((int*)this)[i]; -} - -inline int& IntVector4D::operator[](int i) -{ - Assert( (i >= 0) && (i < 4) ); - return ((int*)this)[i]; -} - -//----------------------------------------------------------------------------- -// Base address... -//----------------------------------------------------------------------------- -inline int* IntVector4D::Base() -{ - return (int*)this; -} - -inline int const* IntVector4D::Base() const -{ - return (int const*)this; -} - - -//----------------------------------------------------------------------------- -// comparison -//----------------------------------------------------------------------------- - -inline bool IntVector4D::operator==( const IntVector4D& src ) const -{ - return (src.x == x) && (src.y == y) && (src.z == z) && (src.w == w); -} - -inline bool IntVector4D::operator!=( const IntVector4D& src ) const -{ - return (src.x != x) || (src.y != y) || (src.z != z) || (src.w != w); -} - - - -//----------------------------------------------------------------------------- -// standard math operations -//----------------------------------------------------------------------------- - -FORCEINLINE IntVector4D& IntVector4D::operator+=(const IntVector4D& v) -{ - x+=v.x; y+=v.y; z += v.z; w += v.w; - return *this; -} - -FORCEINLINE IntVector4D& IntVector4D::operator-=(const IntVector4D& v) -{ - x-=v.x; y-=v.y; z -= v.z; w -= v.w; - return *this; -} - -FORCEINLINE IntVector4D& IntVector4D::operator*=(float fl) -{ - x = static_cast(x * fl); - y = static_cast(y * fl); - z = static_cast(z * fl); - w = static_cast(w * fl); - return *this; -} - -FORCEINLINE IntVector4D& IntVector4D::operator*=(const IntVector4D& v) -{ - x *= v.x; - y *= v.y; - z *= v.z; - w *= v.w; - return *this; -} - -FORCEINLINE IntVector4D& IntVector4D::operator/=(float fl) -{ - Assert( fl != 0.0f ); - float oofl = 1.0f / fl; - x = static_cast(x * oofl); - y = static_cast(y * oofl); - z = static_cast(z * oofl); - w = static_cast(w * oofl); - return *this; -} - -FORCEINLINE IntVector4D& IntVector4D::operator/=(const IntVector4D& v) -{ - Assert( v.x != 0 && v.y != 0 && v.z != 0 && v.w != 0 ); - x /= v.x; - y /= v.y; - z /= v.z; - w /= v.w; - return *this; -} - -FORCEINLINE void IntVector4DMultiply( const IntVector4D& src, float fl, IntVector4D& res ) -{ - Assert( IsFinite(fl) ); - res.x = static_cast(src.x * fl); - res.y = static_cast(src.y * fl); - res.z = static_cast(src.z * fl); - res.w = static_cast(src.w * fl); -} - -FORCEINLINE IntVector4D IntVector4D::operator*(float fl) const -{ - IntVector4D res; - IntVector4DMultiply( *this, fl, res ); - return res; -} - - - -// ======================= - - -FORCEINLINE void VectorAdd( const Vector& a, const Vector& b, Vector& c ) -{ - CHECK_VALID(a); - CHECK_VALID(b); - c.x = a.x + b.x; - c.y = a.y + b.y; - c.z = a.z + b.z; -} - -FORCEINLINE void VectorSubtract( const Vector& a, const Vector& b, Vector& c ) -{ - CHECK_VALID(a); - CHECK_VALID(b); - c.x = a.x - b.x; - c.y = a.y - b.y; - c.z = a.z - b.z; -} - -FORCEINLINE void VectorMultiply( const Vector& a, vec_t b, Vector& c ) -{ - CHECK_VALID(a); - Assert( IsFinite(b) ); - c.x = a.x * b; - c.y = a.y * b; - c.z = a.z * b; -} - -FORCEINLINE void VectorMultiply( const Vector& a, const Vector& b, Vector& c ) -{ - CHECK_VALID(a); - CHECK_VALID(b); - c.x = a.x * b.x; - c.y = a.y * b.y; - c.z = a.z * b.z; -} - -// for backwards compatability -inline void VectorScale ( const Vector& in, vec_t scale, Vector& result ) -{ - VectorMultiply( in, scale, result ); -} - -inline void VectorMA( const Vector& start, float scale, const Vector& direction, Vector& dest ) -{ - CHECK_VALID(start); - CHECK_VALID(direction); - dest.x = start.x + scale * direction.x; - dest.y = start.y + scale * direction.y; - dest.z = start.z + scale * direction.z; -} - -FORCEINLINE void VectorDivide( const Vector& a, vec_t b, Vector& c ) -{ - CHECK_VALID(a); - Assert( b != 0.0f ); - vec_t oob = 1.0f / b; - c.x = a.x * oob; - c.y = a.y * oob; - c.z = a.z * oob; -} - -FORCEINLINE void VectorDivide( const Vector& a, const Vector& b, Vector& c ) -{ - CHECK_VALID(a); - CHECK_VALID(b); - Assert( (b.x != 0.0f) && (b.y != 0.0f) && (b.z != 0.0f) ); - c.x = a.x / b.x; - c.y = a.y / b.y; - c.z = a.z / b.z; -} - -// FIXME: Remove -// For backwards compatability -inline void Vector::MulAdd(const Vector& a, const Vector& b, float scalar) -{ - CHECK_VALID(a); - CHECK_VALID(b); - x = a.x + b.x * scalar; - y = a.y + b.y * scalar; - z = a.z + b.z * scalar; -} - -inline void VectorLerp(const Vector& src1, const Vector& src2, vec_t t, Vector& dest ) -{ - CHECK_VALID(src1); - CHECK_VALID(src2); - dest.x = src1.x + (src2.x - src1.x) * t; - dest.y = src1.y + (src2.y - src1.y) * t; - dest.z = src1.z + (src2.z - src1.z) * t; -} - - -//----------------------------------------------------------------------------- -// Temporary storage for vector results so const Vector& results can be returned -//----------------------------------------------------------------------------- -inline Vector &AllocTempVector() -{ - static Vector s_vecTemp[128]; - static CInterlockedInt s_nIndex; - - int nIndex; - for (;;) - { - int nOldIndex = s_nIndex; - nIndex = ( (nOldIndex + 0x10001) & 0x7F ); - - if ( s_nIndex.AssignIf( nOldIndex, nIndex ) ) - { - break; - } - ThreadPause(); - } - return s_vecTemp[nIndex & 0xffff]; -} - - - -//----------------------------------------------------------------------------- -// dot, cross -//----------------------------------------------------------------------------- -FORCEINLINE vec_t DotProduct(const Vector& a, const Vector& b) -{ - CHECK_VALID(a); - CHECK_VALID(b); - return( a.x*b.x + a.y*b.y + a.z*b.z ); -} - -// for backwards compatability -inline vec_t Vector::Dot( const Vector& vOther ) const -{ - CHECK_VALID(vOther); - return DotProduct( *this, vOther ); -} - -inline void CrossProduct(const Vector& a, const Vector& b, Vector& result ) -{ - CHECK_VALID(a); - CHECK_VALID(b); - Assert( &a != &result ); - Assert( &b != &result ); - result.x = a.y*b.z - a.z*b.y; - result.y = a.z*b.x - a.x*b.z; - result.z = a.x*b.y - a.y*b.x; -} - -inline vec_t DotProductAbs( const Vector &v0, const Vector &v1 ) -{ - CHECK_VALID(v0); - CHECK_VALID(v1); - return FloatMakePositive(v0.x*v1.x) + FloatMakePositive(v0.y*v1.y) + FloatMakePositive(v0.z*v1.z); -} - -inline vec_t DotProductAbs( const Vector &v0, const float *v1 ) -{ - return FloatMakePositive(v0.x * v1[0]) + FloatMakePositive(v0.y * v1[1]) + FloatMakePositive(v0.z * v1[2]); -} - -//----------------------------------------------------------------------------- -// length -//----------------------------------------------------------------------------- - -inline vec_t VectorLength( const Vector& v ) -{ - CHECK_VALID(v); - return (vec_t)FastSqrt(v.x*v.x + v.y*v.y + v.z*v.z); -} - - -inline vec_t Vector::Length(void) const -{ - CHECK_VALID(*this); - return VectorLength( *this ); -} - - -//----------------------------------------------------------------------------- -// Normalization -//----------------------------------------------------------------------------- - -/* -// FIXME: Can't use until we're un-macroed in mathlib.h -inline vec_t VectorNormalize( Vector& v ) -{ - Assert( v.IsValid() ); - vec_t l = v.Length(); - if (l != 0.0f) - { - v /= l; - } - else - { - // FIXME: - // Just copying the existing implemenation; shouldn't res.z == 0? - v.x = v.y = 0.0f; v.z = 1.0f; - } - return l; -} -*/ - - -// check a point against a box -bool Vector::WithinAABox( Vector const &boxmin, Vector const &boxmax) -{ - return ( - ( x >= boxmin.x ) && ( x <= boxmax.x) && - ( y >= boxmin.y ) && ( y <= boxmax.y) && - ( z >= boxmin.z ) && ( z <= boxmax.z) - ); -} - -//----------------------------------------------------------------------------- -// Get the distance from this vector to the other one -//----------------------------------------------------------------------------- -inline vec_t Vector::DistTo(const Vector &vOther) const -{ - Vector delta; - VectorSubtract( *this, vOther, delta ); - return delta.Length(); -} - - -//----------------------------------------------------------------------------- -// Vector equality with tolerance -//----------------------------------------------------------------------------- -inline bool VectorsAreEqual( const Vector& src1, const Vector& src2, float tolerance ) -{ - if (FloatMakePositive(src1.x - src2.x) > tolerance) - return false; - if (FloatMakePositive(src1.y - src2.y) > tolerance) - return false; - return (FloatMakePositive(src1.z - src2.z) <= tolerance); -} - - -//----------------------------------------------------------------------------- -// Computes the closest point to vecTarget no farther than flMaxDist from vecStart -//----------------------------------------------------------------------------- -inline void ComputeClosestPoint( const Vector& vecStart, float flMaxDist, const Vector& vecTarget, Vector *pResult ) -{ - Vector vecDelta; - VectorSubtract( vecTarget, vecStart, vecDelta ); - float flDistSqr = vecDelta.LengthSqr(); - if ( flDistSqr <= flMaxDist * flMaxDist ) - { - *pResult = vecTarget; - } - else - { - vecDelta /= FastSqrt( flDistSqr ); - VectorMA( vecStart, flMaxDist, vecDelta, *pResult ); - } -} - - -//----------------------------------------------------------------------------- -// Takes the absolute value of a vector -//----------------------------------------------------------------------------- -inline void VectorAbs( const Vector& src, Vector& dst ) -{ - dst.x = FloatMakePositive(src.x); - dst.y = FloatMakePositive(src.y); - dst.z = FloatMakePositive(src.z); -} - - -//----------------------------------------------------------------------------- -// -// Slow methods -// -//----------------------------------------------------------------------------- - -#ifndef VECTOR_NO_SLOW_OPERATIONS - -//----------------------------------------------------------------------------- -// Returns a vector with the min or max in X, Y, and Z. -//----------------------------------------------------------------------------- -inline Vector Vector::Min(const Vector &vOther) const -{ - return Vector(x < vOther.x ? x : vOther.x, - y < vOther.y ? y : vOther.y, - z < vOther.z ? z : vOther.z); -} - -inline Vector Vector::Max(const Vector &vOther) const -{ - return Vector(x > vOther.x ? x : vOther.x, - y > vOther.y ? y : vOther.y, - z > vOther.z ? z : vOther.z); -} - - -//----------------------------------------------------------------------------- -// arithmetic operations -//----------------------------------------------------------------------------- - -inline Vector Vector::operator-(void) const -{ - return Vector(-x,-y,-z); -} - -inline Vector Vector::operator+(const Vector& v) const -{ - Vector res; - VectorAdd( *this, v, res ); - return res; -} - -inline Vector Vector::operator-(const Vector& v) const -{ - Vector res; - VectorSubtract( *this, v, res ); - return res; -} - -inline Vector Vector::operator*(float fl) const -{ - Vector res; - VectorMultiply( *this, fl, res ); - return res; -} - -inline Vector Vector::operator*(const Vector& v) const -{ - Vector res; - VectorMultiply( *this, v, res ); - return res; -} - -inline Vector Vector::operator/(float fl) const -{ - Vector res; - VectorDivide( *this, fl, res ); - return res; -} - -inline Vector Vector::operator/(const Vector& v) const -{ - Vector res; - VectorDivide( *this, v, res ); - return res; -} - -inline Vector operator*(float fl, const Vector& v) -{ - return v * fl; -} - -//----------------------------------------------------------------------------- -// cross product -//----------------------------------------------------------------------------- - -inline Vector Vector::Cross(const Vector& vOther) const -{ - Vector res; - CrossProduct( *this, vOther, res ); - return res; -} - -//----------------------------------------------------------------------------- -// 2D -//----------------------------------------------------------------------------- - -inline vec_t Vector::Length2D(void) const -{ - return (vec_t)FastSqrt(x*x + y*y); -} - -inline vec_t Vector::Length2DSqr(void) const -{ - return (x*x + y*y); -} - -inline Vector CrossProduct(const Vector& a, const Vector& b) -{ - return Vector( a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x ); -} - -inline void VectorMin( const Vector &a, const Vector &b, Vector &result ) -{ - result.x = fpmin(a.x, b.x); - result.y = fpmin(a.y, b.y); - result.z = fpmin(a.z, b.z); -} - -inline void VectorMax( const Vector &a, const Vector &b, Vector &result ) -{ - result.x = fpmax(a.x, b.x); - result.y = fpmax(a.y, b.y); - result.z = fpmax(a.z, b.z); -} - -// Get a random vector. -inline Vector RandomVector( float minVal, float maxVal ) -{ - Vector random; - random.Random( minVal, maxVal ); - return random; -} - -#endif //slow - -//----------------------------------------------------------------------------- -// Helper debugging stuff.... -//----------------------------------------------------------------------------- - -inline bool operator==( float const* f, const Vector& v ) -{ - // AIIIEEEE!!!! - Assert(0); - return false; -} - -inline bool operator==( const Vector& v, float const* f ) -{ - // AIIIEEEE!!!! - Assert(0); - return false; -} - -inline bool operator!=( float const* f, const Vector& v ) -{ - // AIIIEEEE!!!! - Assert(0); - return false; -} - -inline bool operator!=( const Vector& v, float const* f ) -{ - // AIIIEEEE!!!! - Assert(0); - return false; -} - - -//----------------------------------------------------------------------------- -// AngularImpulse -//----------------------------------------------------------------------------- -// AngularImpulse are exponetial maps (an axis scaled by a "twist" angle in degrees) -typedef Vector AngularImpulse; - -#ifndef VECTOR_NO_SLOW_OPERATIONS - -inline AngularImpulse RandomAngularImpulse( float minVal, float maxVal ) -{ - AngularImpulse angImp; - angImp.Random( minVal, maxVal ); - return angImp; -} - -#endif - - -//----------------------------------------------------------------------------- -// Quaternion -//----------------------------------------------------------------------------- - -class RadianEuler; - -class Quaternion // same data-layout as engine's vec4_t, -{ // which is a vec_t[4] -public: - inline Quaternion(void) { - - // Initialize to NAN to catch errors -#ifdef _DEBUG -#ifdef VECTOR_PARANOIA - x = y = z = w = VEC_T_NAN; -#endif -#endif - } - inline Quaternion(vec_t ix, vec_t iy, vec_t iz, vec_t iw) : x(ix), y(iy), z(iz), w(iw) { } - inline Quaternion(RadianEuler const &angle); // evil auto type promotion!!! - - inline void Init(vec_t ix=0.0f, vec_t iy=0.0f, vec_t iz=0.0f, vec_t iw=0.0f) { x = ix; y = iy; z = iz; w = iw; } - - bool IsValid() const; - void Invalidate(); - - bool operator==( const Quaternion &src ) const; - bool operator!=( const Quaternion &src ) const; - - vec_t* Base() { return (vec_t*)this; } - const vec_t* Base() const { return (vec_t*)this; } - - // array access... - vec_t operator[](int i) const; - vec_t& operator[](int i); - - vec_t x, y, z, w; -}; - - -//----------------------------------------------------------------------------- -// Array access -//----------------------------------------------------------------------------- -inline vec_t& Quaternion::operator[](int i) -{ - Assert( (i >= 0) && (i < 4) ); - return ((vec_t*)this)[i]; -} - -inline vec_t Quaternion::operator[](int i) const -{ - Assert( (i >= 0) && (i < 4) ); - return ((vec_t*)this)[i]; -} - - -//----------------------------------------------------------------------------- -// Equality test -//----------------------------------------------------------------------------- -inline bool Quaternion::operator==( const Quaternion &src ) const -{ - return ( x == src.x ) && ( y == src.y ) && ( z == src.z ) && ( w == src.w ); -} - -inline bool Quaternion::operator!=( const Quaternion &src ) const -{ - return !operator==( src ); -} - - -//----------------------------------------------------------------------------- -// Quaternion equality with tolerance -//----------------------------------------------------------------------------- -inline bool QuaternionsAreEqual( const Quaternion& src1, const Quaternion& src2, float tolerance ) -{ - if (FloatMakePositive(src1.x - src2.x) > tolerance) - return false; - if (FloatMakePositive(src1.y - src2.y) > tolerance) - return false; - if (FloatMakePositive(src1.z - src2.z) > tolerance) - return false; - return (FloatMakePositive(src1.w - src2.w) <= tolerance); -} - - -//----------------------------------------------------------------------------- -// Here's where we add all those lovely SSE optimized routines -//----------------------------------------------------------------------------- -class ALIGN16 QuaternionAligned : public Quaternion -{ -public: - inline QuaternionAligned(void) {}; - inline QuaternionAligned(vec_t X, vec_t Y, vec_t Z, vec_t W) - { - Init(X,Y,Z,W); - } - -#ifdef VECTOR_NO_SLOW_OPERATIONS - -private: - // No copy constructors allowed if we're in optimal mode - QuaternionAligned(const QuaternionAligned& vOther); - QuaternionAligned(const Quaternion &vOther); - -#else -public: - explicit QuaternionAligned(const Quaternion &vOther) - { - Init(vOther.x, vOther.y, vOther.z, vOther.w); - } - - QuaternionAligned& operator=(const Quaternion &vOther) - { - Init(vOther.x, vOther.y, vOther.z, vOther.w); - return *this; - } - -#endif -}; - - -//----------------------------------------------------------------------------- -// Radian Euler angle aligned to axis (NOT ROLL/PITCH/YAW) -//----------------------------------------------------------------------------- -class QAngle; -class RadianEuler -{ -public: - inline RadianEuler(void) { } - inline RadianEuler(vec_t X, vec_t Y, vec_t Z) { x = X; y = Y; z = Z; } - inline RadianEuler(Quaternion const &q); // evil auto type promotion!!! - inline RadianEuler(QAngle const &angles); // evil auto type promotion!!! - - // Initialization - inline void Init(vec_t ix=0.0f, vec_t iy=0.0f, vec_t iz=0.0f) { x = ix; y = iy; z = iz; } - - // conversion to qangle - QAngle ToQAngle( void ) const; - bool IsValid() const; - void Invalidate(); - - // array access... - vec_t operator[](int i) const; - vec_t& operator[](int i); - - vec_t x, y, z; -}; - - -extern void AngleQuaternion( RadianEuler const &angles, Quaternion &qt ); -extern void QuaternionAngles( Quaternion const &q, RadianEuler &angles ); -inline Quaternion::Quaternion(RadianEuler const &angle) -{ - AngleQuaternion( angle, *this ); -} - -inline bool Quaternion::IsValid() const -{ - return IsFinite(x) && IsFinite(y) && IsFinite(z) && IsFinite(w); -} - -inline void Quaternion::Invalidate() -{ -//#ifdef _DEBUG -//#ifdef VECTOR_PARANOIA - x = y = z = w = VEC_T_NAN; -//#endif -//#endif -} - -inline RadianEuler::RadianEuler(Quaternion const &q) -{ - QuaternionAngles( q, *this ); -} - -inline void VectorCopy( RadianEuler const& src, RadianEuler &dst ) -{ - CHECK_VALID(src); - dst.x = src.x; - dst.y = src.y; - dst.z = src.z; -} - -inline void VectorScale( RadianEuler const& src, float b, RadianEuler &dst ) -{ - CHECK_VALID(src); - Assert( IsFinite(b) ); - dst.x = src.x * b; - dst.y = src.y * b; - dst.z = src.z * b; -} - -inline bool RadianEuler::IsValid() const -{ - return IsFinite(x) && IsFinite(y) && IsFinite(z); -} - -inline void RadianEuler::Invalidate() -{ -//#ifdef _DEBUG -//#ifdef VECTOR_PARANOIA - x = y = z = VEC_T_NAN; -//#endif -//#endif -} - - -//----------------------------------------------------------------------------- -// Array access -//----------------------------------------------------------------------------- -inline vec_t& RadianEuler::operator[](int i) -{ - Assert( (i >= 0) && (i < 3) ); - return ((vec_t*)this)[i]; -} - -inline vec_t RadianEuler::operator[](int i) const -{ - Assert( (i >= 0) && (i < 3) ); - return ((vec_t*)this)[i]; -} - - -//----------------------------------------------------------------------------- -// Degree Euler QAngle pitch, yaw, roll -//----------------------------------------------------------------------------- -class QAngleByValue; - -class QAngle -{ -public: - // Members - vec_t x, y, z; - - // Construction/destruction - QAngle(void); - QAngle(vec_t X, vec_t Y, vec_t Z); -// QAngle(RadianEuler const &angles); // evil auto type promotion!!! - - // Allow pass-by-value - operator QAngleByValue &() { return *((QAngleByValue *)(this)); } - operator const QAngleByValue &() const { return *((const QAngleByValue *)(this)); } - - // Initialization - void Init(vec_t ix=0.0f, vec_t iy=0.0f, vec_t iz=0.0f); - void Random( vec_t minVal, vec_t maxVal ); - - // Got any nasty NAN's? - bool IsValid() const; - void Invalidate(); - - // array access... - vec_t operator[](int i) const; - vec_t& operator[](int i); - - // Base address... - vec_t* Base(); - vec_t const* Base() const; - - // equality - bool operator==(const QAngle& v) const; - bool operator!=(const QAngle& v) const; - - // arithmetic operations - QAngle& operator+=(const QAngle &v); - QAngle& operator-=(const QAngle &v); - QAngle& operator*=(float s); - QAngle& operator/=(float s); - - // Get the vector's magnitude. - vec_t Length() const; - vec_t LengthSqr() const; - - // negate the QAngle components - //void Negate(); - - // No assignment operators either... - QAngle& operator=( const QAngle& src ); - -#ifndef VECTOR_NO_SLOW_OPERATIONS - // copy constructors - - // arithmetic operations - QAngle operator-(void) const; - - QAngle operator+(const QAngle& v) const; - QAngle operator-(const QAngle& v) const; - QAngle operator*(float fl) const; - QAngle operator/(float fl) const; -#else - -private: - // No copy constructors allowed if we're in optimal mode - QAngle(const QAngle& vOther); - -#endif -}; - -//----------------------------------------------------------------------------- -// Allows us to specifically pass the vector by value when we need to -//----------------------------------------------------------------------------- -class QAngleByValue : public QAngle -{ -public: - // Construction/destruction: - QAngleByValue(void) : QAngle() {} - QAngleByValue(vec_t X, vec_t Y, vec_t Z) : QAngle( X, Y, Z ) {} - QAngleByValue(const QAngleByValue& vOther) { *this = vOther; } -}; - - -inline void VectorAdd( const QAngle& a, const QAngle& b, QAngle& result ) -{ - CHECK_VALID(a); - CHECK_VALID(b); - result.x = a.x + b.x; - result.y = a.y + b.y; - result.z = a.z + b.z; -} - -inline void VectorMA( const QAngle &start, float scale, const QAngle &direction, QAngle &dest ) -{ - CHECK_VALID(start); - CHECK_VALID(direction); - dest.x = start.x + scale * direction.x; - dest.y = start.y + scale * direction.y; - dest.z = start.z + scale * direction.z; -} - - -//----------------------------------------------------------------------------- -// constructors -//----------------------------------------------------------------------------- -inline QAngle::QAngle(void) -{ -#ifdef _DEBUG -#ifdef VECTOR_PARANOIA - // Initialize to NAN to catch errors - x = y = z = VEC_T_NAN; -#endif -#endif -} - -inline QAngle::QAngle(vec_t X, vec_t Y, vec_t Z) -{ - x = X; y = Y; z = Z; - CHECK_VALID(*this); -} - - -//----------------------------------------------------------------------------- -// initialization -//----------------------------------------------------------------------------- -inline void QAngle::Init( vec_t ix, vec_t iy, vec_t iz ) -{ - x = ix; y = iy; z = iz; - CHECK_VALID(*this); -} - -inline void QAngle::Random( vec_t minVal, vec_t maxVal ) -{ - x = minVal + ((float)rand() / RAND_MAX) * (maxVal - minVal); - y = minVal + ((float)rand() / RAND_MAX) * (maxVal - minVal); - z = minVal + ((float)rand() / RAND_MAX) * (maxVal - minVal); - CHECK_VALID(*this); -} - -#ifndef VECTOR_NO_SLOW_OPERATIONS - -inline QAngle RandomAngle( float minVal, float maxVal ) -{ - Vector random; - random.Random( minVal, maxVal ); - QAngle ret( random.x, random.y, random.z ); - return ret; -} - -#endif - - -inline RadianEuler::RadianEuler(QAngle const &angles) -{ - Init( - angles.z * 3.14159265358979323846f / 180.f, - angles.x * 3.14159265358979323846f / 180.f, - angles.y * 3.14159265358979323846f / 180.f ); -} - - - - -inline QAngle RadianEuler::ToQAngle( void) const -{ - return QAngle( - y * 180.f / 3.14159265358979323846f, - z * 180.f / 3.14159265358979323846f, - x * 180.f / 3.14159265358979323846f ); -} - - -//----------------------------------------------------------------------------- -// assignment -//----------------------------------------------------------------------------- -inline QAngle& QAngle::operator=(const QAngle &vOther) -{ - CHECK_VALID(vOther); - x=vOther.x; y=vOther.y; z=vOther.z; - return *this; -} - - -//----------------------------------------------------------------------------- -// Array access -//----------------------------------------------------------------------------- -inline vec_t& QAngle::operator[](int i) -{ - Assert( (i >= 0) && (i < 3) ); - return ((vec_t*)this)[i]; -} - -inline vec_t QAngle::operator[](int i) const -{ - Assert( (i >= 0) && (i < 3) ); - return ((vec_t*)this)[i]; -} - - -//----------------------------------------------------------------------------- -// Base address... -//----------------------------------------------------------------------------- -inline vec_t* QAngle::Base() -{ - return (vec_t*)this; -} - -inline vec_t const* QAngle::Base() const -{ - return (vec_t const*)this; -} - - -//----------------------------------------------------------------------------- -// IsValid? -//----------------------------------------------------------------------------- -inline bool QAngle::IsValid() const -{ - return IsFinite(x) && IsFinite(y) && IsFinite(z); -} - -//----------------------------------------------------------------------------- -// Invalidate -//----------------------------------------------------------------------------- - -inline void QAngle::Invalidate() -{ -//#ifdef _DEBUG -//#ifdef VECTOR_PARANOIA - x = y = z = VEC_T_NAN; -//#endif -//#endif -} - -//----------------------------------------------------------------------------- -// comparison -//----------------------------------------------------------------------------- -inline bool QAngle::operator==( const QAngle& src ) const -{ - CHECK_VALID(src); - CHECK_VALID(*this); - return (src.x == x) && (src.y == y) && (src.z == z); -} - -inline bool QAngle::operator!=( const QAngle& src ) const -{ - CHECK_VALID(src); - CHECK_VALID(*this); - return (src.x != x) || (src.y != y) || (src.z != z); -} - - -//----------------------------------------------------------------------------- -// Copy -//----------------------------------------------------------------------------- -inline void VectorCopy( const QAngle& src, QAngle& dst ) -{ - CHECK_VALID(src); - dst.x = src.x; - dst.y = src.y; - dst.z = src.z; -} - - -//----------------------------------------------------------------------------- -// standard math operations -//----------------------------------------------------------------------------- -inline QAngle& QAngle::operator+=(const QAngle& v) -{ - CHECK_VALID(*this); - CHECK_VALID(v); - x+=v.x; y+=v.y; z += v.z; - return *this; -} - -inline QAngle& QAngle::operator-=(const QAngle& v) -{ - CHECK_VALID(*this); - CHECK_VALID(v); - x-=v.x; y-=v.y; z -= v.z; - return *this; -} - -inline QAngle& QAngle::operator*=(float fl) -{ - x *= fl; - y *= fl; - z *= fl; - CHECK_VALID(*this); - return *this; -} - -inline QAngle& QAngle::operator/=(float fl) -{ - Assert( fl != 0.0f ); - float oofl = 1.0f / fl; - x *= oofl; - y *= oofl; - z *= oofl; - CHECK_VALID(*this); - return *this; -} - - -//----------------------------------------------------------------------------- -// length -//----------------------------------------------------------------------------- -inline vec_t QAngle::Length( ) const -{ - CHECK_VALID(*this); - return (vec_t)FastSqrt( LengthSqr( ) ); -} - - -inline vec_t QAngle::LengthSqr( ) const -{ - CHECK_VALID(*this); - return x * x + y * y + z * z; -} - - -//----------------------------------------------------------------------------- -// Vector equality with tolerance -//----------------------------------------------------------------------------- -inline bool QAnglesAreEqual( const QAngle& src1, const QAngle& src2, float tolerance = 0.0f ) -{ - if (FloatMakePositive(src1.x - src2.x) > tolerance) - return false; - if (FloatMakePositive(src1.y - src2.y) > tolerance) - return false; - return (FloatMakePositive(src1.z - src2.z) <= tolerance); -} - - -//----------------------------------------------------------------------------- -// arithmetic operations (SLOW!!) -//----------------------------------------------------------------------------- -#ifndef VECTOR_NO_SLOW_OPERATIONS - -inline QAngle QAngle::operator-(void) const -{ - QAngle ret(-x,-y,-z); - return ret; -} - -inline QAngle QAngle::operator+(const QAngle& v) const -{ - QAngle res; - res.x = x + v.x; - res.y = y + v.y; - res.z = z + v.z; - return res; -} - -inline QAngle QAngle::operator-(const QAngle& v) const -{ - QAngle res; - res.x = x - v.x; - res.y = y - v.y; - res.z = z - v.z; - return res; -} - -inline QAngle QAngle::operator*(float fl) const -{ - QAngle res; - res.x = x * fl; - res.y = y * fl; - res.z = z * fl; - return res; -} - -inline QAngle QAngle::operator/(float fl) const -{ - QAngle res; - res.x = x / fl; - res.y = y / fl; - res.z = z / fl; - return res; -} - -inline QAngle operator*(float fl, const QAngle& v) -{ - QAngle ret( v * fl ); - return ret; -} - -#endif // VECTOR_NO_SLOW_OPERATIONS - - -//----------------------------------------------------------------------------- -// NOTE: These are not completely correct. The representations are not equivalent -// unless the QAngle represents a rotational impulse along a coordinate axis (x,y,z) -inline void QAngleToAngularImpulse( const QAngle &angles, AngularImpulse &impulse ) -{ - impulse.x = angles.z; - impulse.y = angles.x; - impulse.z = angles.y; -} - -inline void AngularImpulseToQAngle( const AngularImpulse &impulse, QAngle &angles ) -{ - angles.x = impulse.y; - angles.y = impulse.z; - angles.z = impulse.x; -} - -#if !defined( _X360 ) -extern float (*pfInvRSquared)( const float *v ); - -FORCEINLINE vec_t InvRSquared( float const *v ) -{ - return (*pfInvRSquared)(v); -} - -FORCEINLINE vec_t InvRSquared( const Vector &v ) -{ - return InvRSquared(&v.x); -} - -#else - -// call directly -FORCEINLINE float _VMX_InvRSquared( const Vector &v ) -{ - XMVECTOR xmV = XMVector3ReciprocalLength( XMLoadVector3( v.Base() ) ); - xmV = XMVector3Dot( xmV, xmV ); - return xmV.x; -} - -#define InvRSquared(x) _VMX_InvRSquared(x) - -#endif // _X360 - -#if !defined( _X360 ) -extern float (FASTCALL *pfVectorNormalize)(Vector& v); - -// FIXME: Change this back to a #define once we get rid of the vec_t version -FORCEINLINE float VectorNormalize( Vector& v ) -{ - return (*pfVectorNormalize)(v); -} -// FIXME: Obsolete version of VectorNormalize, once we remove all the friggin float*s -FORCEINLINE float VectorNormalize( float * v ) -{ - return VectorNormalize(*(reinterpret_cast(v))); -} - -#else - -// call directly -FORCEINLINE float _VMX_VectorNormalize( Vector &vec ) -{ - float mag = XMVector3Length( XMLoadVector3( vec.Base() ) ).x; - float den = 1.f / (mag + FLT_EPSILON ); - vec.x *= den; - vec.y *= den; - vec.z *= den; - return mag; -} -// FIXME: Change this back to a #define once we get rid of the vec_t version -FORCEINLINE float VectorNormalize( Vector& v ) -{ - return _VMX_VectorNormalize( v ); -} -// FIXME: Obsolete version of VectorNormalize, once we remove all the friggin float*s -FORCEINLINE float VectorNormalize( float *pV ) -{ - return _VMX_VectorNormalize(*(reinterpret_cast(pV))); -} - -#endif // _X360 - -#if !defined( _X360 ) -extern void (FASTCALL *pfVectorNormalizeFast)(Vector& v); - -FORCEINLINE void VectorNormalizeFast( Vector& v ) -{ - (*pfVectorNormalizeFast)(v); -} - -#else - -// call directly -FORCEINLINE void VectorNormalizeFast( Vector &vec ) -{ - XMVECTOR xmV = XMVector3LengthEst( XMLoadVector3( vec.Base() ) ); - float den = 1.f / (xmV.x + FLT_EPSILON); - vec.x *= den; - vec.y *= den; - vec.z *= den; -} - -#endif // _X360 - -inline vec_t Vector::NormalizeInPlace() -{ - return VectorNormalize( *this ); -} - -inline bool Vector::IsLengthGreaterThan( float val ) const -{ - return LengthSqr() > val*val; -} - -inline bool Vector::IsLengthLessThan( float val ) const -{ - return LengthSqr() < val*val; -} - -#endif - diff --git a/public/mathlib/vector2d.h b/public/mathlib/vector2d.h deleted file mode 100644 index 4eef4b204..000000000 --- a/public/mathlib/vector2d.h +++ /dev/null @@ -1,670 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef VECTOR2D_H -#define VECTOR2D_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -// For vec_t, put this somewhere else? -#include "tier0/basetypes.h" - -// For rand(). We really need a library! -#include - -#include "tier0/dbg.h" -#include "mathlib/math_pfns.h" - -//========================================================= -// 2D Vector2D -//========================================================= - -class Vector2D -{ -public: - // Members - vec_t x, y; - - // Construction/destruction - Vector2D(void); - Vector2D(vec_t X, vec_t Y); - Vector2D(const float *pFloat); - - // Initialization - void Init(vec_t ix=0.0f, vec_t iy=0.0f); - - // Got any nasty NAN's? - bool IsValid() const; - - // array access... - vec_t operator[](int i) const; - vec_t& operator[](int i); - - // Base address... - vec_t* Base(); - vec_t const* Base() const; - - // Initialization methods - void Random( float minVal, float maxVal ); - - // equality - bool operator==(const Vector2D& v) const; - bool operator!=(const Vector2D& v) const; - - // arithmetic operations - Vector2D& operator+=(const Vector2D &v); - Vector2D& operator-=(const Vector2D &v); - Vector2D& operator*=(const Vector2D &v); - Vector2D& operator*=(float s); - Vector2D& operator/=(const Vector2D &v); - Vector2D& operator/=(float s); - - // negate the Vector2D components - void Negate(); - - // Get the Vector2D's magnitude. - vec_t Length() const; - - // Get the Vector2D's magnitude squared. - vec_t LengthSqr(void) const; - - // return true if this vector is (0,0) within tolerance - bool IsZero( float tolerance = 0.01f ) const - { - return (x > -tolerance && x < tolerance && - y > -tolerance && y < tolerance); - } - - // Normalize in place and return the old length. - vec_t NormalizeInPlace(); - - // Compare length. - bool IsLengthGreaterThan( float val ) const; - bool IsLengthLessThan( float val ) const; - - // Get the distance from this Vector2D to the other one. - vec_t DistTo(const Vector2D &vOther) const; - - // Get the distance from this Vector2D to the other one squared. - vec_t DistToSqr(const Vector2D &vOther) const; - - // Copy - void CopyToArray(float* rgfl) const; - - // Multiply, add, and assign to this (ie: *this = a + b * scalar). This - // is about 12% faster than the actual Vector2D equation (because it's done per-component - // rather than per-Vector2D). - void MulAdd(const Vector2D& a, const Vector2D& b, float scalar); - - // Dot product. - vec_t Dot(const Vector2D& vOther) const; - - // assignment - Vector2D& operator=(const Vector2D &vOther); - -#ifndef VECTOR_NO_SLOW_OPERATIONS - // copy constructors - Vector2D(const Vector2D &vOther); - - // arithmetic operations - Vector2D operator-(void) const; - - Vector2D operator+(const Vector2D& v) const; - Vector2D operator-(const Vector2D& v) const; - Vector2D operator*(const Vector2D& v) const; - Vector2D operator/(const Vector2D& v) const; - Vector2D operator*(float fl) const; - Vector2D operator/(float fl) const; - - // Cross product between two vectors. - Vector2D Cross(const Vector2D &vOther) const; - - // Returns a Vector2D with the min or max in X, Y, and Z. - Vector2D Min(const Vector2D &vOther) const; - Vector2D Max(const Vector2D &vOther) const; - -#else - -private: - // No copy constructors allowed if we're in optimal mode - Vector2D(const Vector2D& vOther); -#endif -}; - -//----------------------------------------------------------------------------- - -const Vector2D vec2_origin(0,0); -const Vector2D vec2_invalid( FLT_MAX, FLT_MAX ); - -//----------------------------------------------------------------------------- -// Vector2D related operations -//----------------------------------------------------------------------------- - -// Vector2D clear -void Vector2DClear( Vector2D& a ); - -// Copy -void Vector2DCopy( const Vector2D& src, Vector2D& dst ); - -// Vector2D arithmetic -void Vector2DAdd( const Vector2D& a, const Vector2D& b, Vector2D& result ); -void Vector2DSubtract( const Vector2D& a, const Vector2D& b, Vector2D& result ); -void Vector2DMultiply( const Vector2D& a, vec_t b, Vector2D& result ); -void Vector2DMultiply( const Vector2D& a, const Vector2D& b, Vector2D& result ); -void Vector2DDivide( const Vector2D& a, vec_t b, Vector2D& result ); -void Vector2DDivide( const Vector2D& a, const Vector2D& b, Vector2D& result ); -void Vector2DMA( const Vector2D& start, float s, const Vector2D& dir, Vector2D& result ); - -// Store the min or max of each of x, y, and z into the result. -void Vector2DMin( const Vector2D &a, const Vector2D &b, Vector2D &result ); -void Vector2DMax( const Vector2D &a, const Vector2D &b, Vector2D &result ); - -#define Vector2DExpand( v ) (v).x, (v).y - -// Normalization -vec_t Vector2DNormalize( Vector2D& v ); - -// Length -vec_t Vector2DLength( const Vector2D& v ); - -// Dot Product -vec_t DotProduct2D(const Vector2D& a, const Vector2D& b); - -// Linearly interpolate between two vectors -void Vector2DLerp(const Vector2D& src1, const Vector2D& src2, vec_t t, Vector2D& dest ); - - -//----------------------------------------------------------------------------- -// -// Inlined Vector2D methods -// -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -// constructors -//----------------------------------------------------------------------------- - -inline Vector2D::Vector2D(void) -{ -#ifdef _DEBUG - // Initialize to NAN to catch errors - x = y = VEC_T_NAN; -#endif -} - -inline Vector2D::Vector2D(vec_t X, vec_t Y) -{ - x = X; y = Y; - Assert( IsValid() ); -} - -inline Vector2D::Vector2D(const float *pFloat) -{ - Assert( pFloat ); - x = pFloat[0]; y = pFloat[1]; - Assert( IsValid() ); -} - - -//----------------------------------------------------------------------------- -// copy constructor -//----------------------------------------------------------------------------- - -inline Vector2D::Vector2D(const Vector2D &vOther) -{ - Assert( vOther.IsValid() ); - x = vOther.x; y = vOther.y; -} - -//----------------------------------------------------------------------------- -// initialization -//----------------------------------------------------------------------------- - -inline void Vector2D::Init( vec_t ix, vec_t iy ) -{ - x = ix; y = iy; - Assert( IsValid() ); -} - -inline void Vector2D::Random( float minVal, float maxVal ) -{ - x = minVal + ((float)rand() / RAND_MAX) * (maxVal - minVal); - y = minVal + ((float)rand() / RAND_MAX) * (maxVal - minVal); -} - -inline void Vector2DClear( Vector2D& a ) -{ - a.x = a.y = 0.0f; -} - -//----------------------------------------------------------------------------- -// assignment -//----------------------------------------------------------------------------- - -inline Vector2D& Vector2D::operator=(const Vector2D &vOther) -{ - Assert( vOther.IsValid() ); - x=vOther.x; y=vOther.y; - return *this; -} - -//----------------------------------------------------------------------------- -// Array access -//----------------------------------------------------------------------------- - -inline vec_t& Vector2D::operator[](int i) -{ - Assert( (i >= 0) && (i < 2) ); - return ((vec_t*)this)[i]; -} - -inline vec_t Vector2D::operator[](int i) const -{ - Assert( (i >= 0) && (i < 2) ); - return ((vec_t*)this)[i]; -} - -//----------------------------------------------------------------------------- -// Base address... -//----------------------------------------------------------------------------- - -inline vec_t* Vector2D::Base() -{ - return (vec_t*)this; -} - -inline vec_t const* Vector2D::Base() const -{ - return (vec_t const*)this; -} - -//----------------------------------------------------------------------------- -// IsValid? -//----------------------------------------------------------------------------- - -inline bool Vector2D::IsValid() const -{ - return IsFinite(x) && IsFinite(y); -} - -//----------------------------------------------------------------------------- -// comparison -//----------------------------------------------------------------------------- - -inline bool Vector2D::operator==( const Vector2D& src ) const -{ - Assert( src.IsValid() && IsValid() ); - return (src.x == x) && (src.y == y); -} - -inline bool Vector2D::operator!=( const Vector2D& src ) const -{ - Assert( src.IsValid() && IsValid() ); - return (src.x != x) || (src.y != y); -} - - -//----------------------------------------------------------------------------- -// Copy -//----------------------------------------------------------------------------- - -inline void Vector2DCopy( const Vector2D& src, Vector2D& dst ) -{ - Assert( src.IsValid() ); - dst.x = src.x; - dst.y = src.y; -} - -inline void Vector2D::CopyToArray(float* rgfl) const -{ - Assert( IsValid() ); - Assert( rgfl ); - rgfl[0] = x; rgfl[1] = y; -} - -//----------------------------------------------------------------------------- -// standard math operations -//----------------------------------------------------------------------------- - -inline void Vector2D::Negate() -{ - Assert( IsValid() ); - x = -x; y = -y; -} - -inline Vector2D& Vector2D::operator+=(const Vector2D& v) -{ - Assert( IsValid() && v.IsValid() ); - x+=v.x; y+=v.y; - return *this; -} - -inline Vector2D& Vector2D::operator-=(const Vector2D& v) -{ - Assert( IsValid() && v.IsValid() ); - x-=v.x; y-=v.y; - return *this; -} - -inline Vector2D& Vector2D::operator*=(float fl) -{ - x *= fl; - y *= fl; - Assert( IsValid() ); - return *this; -} - -inline Vector2D& Vector2D::operator*=(const Vector2D& v) -{ - x *= v.x; - y *= v.y; - Assert( IsValid() ); - return *this; -} - -inline Vector2D& Vector2D::operator/=(float fl) -{ - Assert( fl != 0.0f ); - float oofl = 1.0f / fl; - x *= oofl; - y *= oofl; - Assert( IsValid() ); - return *this; -} - -inline Vector2D& Vector2D::operator/=(const Vector2D& v) -{ - Assert( v.x != 0.0f && v.y != 0.0f ); - x /= v.x; - y /= v.y; - Assert( IsValid() ); - return *this; -} - -inline void Vector2DAdd( const Vector2D& a, const Vector2D& b, Vector2D& c ) -{ - Assert( a.IsValid() && b.IsValid() ); - c.x = a.x + b.x; - c.y = a.y + b.y; -} - -inline void Vector2DSubtract( const Vector2D& a, const Vector2D& b, Vector2D& c ) -{ - Assert( a.IsValid() && b.IsValid() ); - c.x = a.x - b.x; - c.y = a.y - b.y; -} - -inline void Vector2DMultiply( const Vector2D& a, vec_t b, Vector2D& c ) -{ - Assert( a.IsValid() && IsFinite(b) ); - c.x = a.x * b; - c.y = a.y * b; -} - -inline void Vector2DMultiply( const Vector2D& a, const Vector2D& b, Vector2D& c ) -{ - Assert( a.IsValid() && b.IsValid() ); - c.x = a.x * b.x; - c.y = a.y * b.y; -} - - -inline void Vector2DDivide( const Vector2D& a, vec_t b, Vector2D& c ) -{ - Assert( a.IsValid() ); - Assert( b != 0.0f ); - vec_t oob = 1.0f / b; - c.x = a.x * oob; - c.y = a.y * oob; -} - -inline void Vector2DDivide( const Vector2D& a, const Vector2D& b, Vector2D& c ) -{ - Assert( a.IsValid() ); - Assert( (b.x != 0.0f) && (b.y != 0.0f) ); - c.x = a.x / b.x; - c.y = a.y / b.y; -} - -inline void Vector2DMA( const Vector2D& start, float s, const Vector2D& dir, Vector2D& result ) -{ - Assert( start.IsValid() && IsFinite(s) && dir.IsValid() ); - result.x = start.x + s*dir.x; - result.y = start.y + s*dir.y; -} - -// FIXME: Remove -// For backwards compatability -inline void Vector2D::MulAdd(const Vector2D& a, const Vector2D& b, float scalar) -{ - x = a.x + b.x * scalar; - y = a.y + b.y * scalar; -} - -inline void Vector2DLerp(const Vector2D& src1, const Vector2D& src2, vec_t t, Vector2D& dest ) -{ - dest[0] = src1[0] + (src2[0] - src1[0]) * t; - dest[1] = src1[1] + (src2[1] - src1[1]) * t; -} - -//----------------------------------------------------------------------------- -// dot, cross -//----------------------------------------------------------------------------- -inline vec_t DotProduct2D(const Vector2D& a, const Vector2D& b) -{ - Assert( a.IsValid() && b.IsValid() ); - return( a.x*b.x + a.y*b.y ); -} - -// for backwards compatability -inline vec_t Vector2D::Dot( const Vector2D& vOther ) const -{ - return DotProduct2D( *this, vOther ); -} - - -//----------------------------------------------------------------------------- -// length -//----------------------------------------------------------------------------- -inline vec_t Vector2DLength( const Vector2D& v ) -{ - Assert( v.IsValid() ); - return (vec_t)FastSqrt(v.x*v.x + v.y*v.y); -} - -inline vec_t Vector2D::LengthSqr(void) const -{ - Assert( IsValid() ); - return (x*x + y*y); -} - -inline vec_t Vector2D::NormalizeInPlace() -{ - return Vector2DNormalize( *this ); -} - -inline bool Vector2D::IsLengthGreaterThan( float val ) const -{ - return LengthSqr() > val*val; -} - -inline bool Vector2D::IsLengthLessThan( float val ) const -{ - return LengthSqr() < val*val; -} - -inline vec_t Vector2D::Length(void) const -{ - return Vector2DLength( *this ); -} - - -inline void Vector2DMin( const Vector2D &a, const Vector2D &b, Vector2D &result ) -{ - result.x = (a.x < b.x) ? a.x : b.x; - result.y = (a.y < b.y) ? a.y : b.y; -} - - -inline void Vector2DMax( const Vector2D &a, const Vector2D &b, Vector2D &result ) -{ - result.x = (a.x > b.x) ? a.x : b.x; - result.y = (a.y > b.y) ? a.y : b.y; -} - - -//----------------------------------------------------------------------------- -// Normalization -//----------------------------------------------------------------------------- -inline vec_t Vector2DNormalize( Vector2D& v ) -{ - Assert( v.IsValid() ); - vec_t l = v.Length(); - if (l != 0.0f) - { - v /= l; - } - else - { - v.x = v.y = 0.0f; - } - return l; -} - - -//----------------------------------------------------------------------------- -// Get the distance from this Vector2D to the other one -//----------------------------------------------------------------------------- -inline vec_t Vector2D::DistTo(const Vector2D &vOther) const -{ - Vector2D delta; - Vector2DSubtract( *this, vOther, delta ); - return delta.Length(); -} - -inline vec_t Vector2D::DistToSqr(const Vector2D &vOther) const -{ - Vector2D delta; - Vector2DSubtract( *this, vOther, delta ); - return delta.LengthSqr(); -} - - -//----------------------------------------------------------------------------- -// Computes the closest point to vecTarget no farther than flMaxDist from vecStart -//----------------------------------------------------------------------------- -inline void ComputeClosestPoint2D( const Vector2D& vecStart, float flMaxDist, const Vector2D& vecTarget, Vector2D *pResult ) -{ - Vector2D vecDelta; - Vector2DSubtract( vecTarget, vecStart, vecDelta ); - float flDistSqr = vecDelta.LengthSqr(); - if ( flDistSqr <= flMaxDist * flMaxDist ) - { - *pResult = vecTarget; - } - else - { - vecDelta /= FastSqrt( flDistSqr ); - Vector2DMA( vecStart, flMaxDist, vecDelta, *pResult ); - } -} - - - -//----------------------------------------------------------------------------- -// -// Slow methods -// -//----------------------------------------------------------------------------- - -#ifndef VECTOR_NO_SLOW_OPERATIONS - -//----------------------------------------------------------------------------- -// Returns a Vector2D with the min or max in X, Y, and Z. -//----------------------------------------------------------------------------- - -inline Vector2D Vector2D::Min(const Vector2D &vOther) const -{ - return Vector2D(x < vOther.x ? x : vOther.x, - y < vOther.y ? y : vOther.y); -} - -inline Vector2D Vector2D::Max(const Vector2D &vOther) const -{ - return Vector2D(x > vOther.x ? x : vOther.x, - y > vOther.y ? y : vOther.y); -} - - -//----------------------------------------------------------------------------- -// arithmetic operations -//----------------------------------------------------------------------------- - -inline Vector2D Vector2D::operator-(void) const -{ - return Vector2D(-x,-y); -} - -inline Vector2D Vector2D::operator+(const Vector2D& v) const -{ - Vector2D res; - Vector2DAdd( *this, v, res ); - return res; -} - -inline Vector2D Vector2D::operator-(const Vector2D& v) const -{ - Vector2D res; - Vector2DSubtract( *this, v, res ); - return res; -} - -inline Vector2D Vector2D::operator*(float fl) const -{ - Vector2D res; - Vector2DMultiply( *this, fl, res ); - return res; -} - -inline Vector2D Vector2D::operator*(const Vector2D& v) const -{ - Vector2D res; - Vector2DMultiply( *this, v, res ); - return res; -} - -inline Vector2D Vector2D::operator/(float fl) const -{ - Vector2D res; - Vector2DDivide( *this, fl, res ); - return res; -} - -inline Vector2D Vector2D::operator/(const Vector2D& v) const -{ - Vector2D res; - Vector2DDivide( *this, v, res ); - return res; -} - -inline Vector2D operator*(float fl, const Vector2D& v) -{ - return v * fl; -} - -#endif //slow - -#endif // VECTOR2D_H - diff --git a/public/mathlib/vector4d.h b/public/mathlib/vector4d.h deleted file mode 100644 index 552caea0a..000000000 --- a/public/mathlib/vector4d.h +++ /dev/null @@ -1,690 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef VECTOR4D_H -#define VECTOR4D_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include // For rand(). We really need a library! -#include -#if !defined( _X360 ) -#include // For SSE -#endif -#include "basetypes.h" // For vec_t, put this somewhere else? -#include "tier0/dbg.h" -#include "mathlib/math_pfns.h" - -// forward declarations -class Vector; -class Vector2D; - -//========================================================= -// 4D Vector4D -//========================================================= - -class Vector4D -{ -public: - // Members - vec_t x, y, z, w; - - // Construction/destruction - Vector4D(void); - Vector4D(vec_t X, vec_t Y, vec_t Z, vec_t W); - Vector4D(const float *pFloat); - - // Initialization - void Init(vec_t ix=0.0f, vec_t iy=0.0f, vec_t iz=0.0f, vec_t iw=0.0f); - - // Got any nasty NAN's? - bool IsValid() const; - - // array access... - vec_t operator[](int i) const; - vec_t& operator[](int i); - - // Base address... - inline vec_t* Base(); - inline vec_t const* Base() const; - - // Cast to Vector and Vector2D... - Vector& AsVector3D(); - Vector const& AsVector3D() const; - - Vector2D& AsVector2D(); - Vector2D const& AsVector2D() const; - - // Initialization methods - void Random( vec_t minVal, vec_t maxVal ); - - // equality - bool operator==(const Vector4D& v) const; - bool operator!=(const Vector4D& v) const; - - // arithmetic operations - Vector4D& operator+=(const Vector4D &v); - Vector4D& operator-=(const Vector4D &v); - Vector4D& operator*=(const Vector4D &v); - Vector4D& operator*=(float s); - Vector4D& operator/=(const Vector4D &v); - Vector4D& operator/=(float s); - - // negate the Vector4D components - void Negate(); - - // Get the Vector4D's magnitude. - vec_t Length() const; - - // Get the Vector4D's magnitude squared. - vec_t LengthSqr(void) const; - - // return true if this vector is (0,0,0,0) within tolerance - bool IsZero( float tolerance = 0.01f ) const - { - return (x > -tolerance && x < tolerance && - y > -tolerance && y < tolerance && - z > -tolerance && z < tolerance && - w > -tolerance && w < tolerance); - } - - // Get the distance from this Vector4D to the other one. - vec_t DistTo(const Vector4D &vOther) const; - - // Get the distance from this Vector4D to the other one squared. - vec_t DistToSqr(const Vector4D &vOther) const; - - // Copy - void CopyToArray(float* rgfl) const; - - // Multiply, add, and assign to this (ie: *this = a + b * scalar). This - // is about 12% faster than the actual Vector4D equation (because it's done per-component - // rather than per-Vector4D). - void MulAdd(Vector4D const& a, Vector4D const& b, float scalar); - - // Dot product. - vec_t Dot(Vector4D const& vOther) const; - - // No copy constructors allowed if we're in optimal mode -#ifdef VECTOR_NO_SLOW_OPERATIONS -private: -#else -public: -#endif - Vector4D(Vector4D const& vOther); - - // No assignment operators either... - Vector4D& operator=( Vector4D const& src ); -}; - -const Vector4D vec4_origin( 0.0f, 0.0f, 0.0f, 0.0f ); -const Vector4D vec4_invalid( FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX ); - -//----------------------------------------------------------------------------- -// SSE optimized routines -//----------------------------------------------------------------------------- - -#ifdef _WIN32 -class __declspec(align(16)) Vector4DAligned : public Vector4D -#elif defined _LINUX || defined __APPLE__ -class __attribute__((aligned(16))) Vector4DAligned : public Vector4D -#endif -{ -public: - Vector4DAligned(void) {} - Vector4DAligned( vec_t X, vec_t Y, vec_t Z, vec_t W ); - - inline void Set( vec_t X, vec_t Y, vec_t Z, vec_t W ); - inline void InitZero( void ); - - inline __m128 &AsM128() { return *(__m128*)&x; } - inline const __m128 &AsM128() const { return *(const __m128*)&x; } - -private: - // No copy constructors allowed if we're in optimal mode - Vector4DAligned( Vector4DAligned const& vOther ); - - // No assignment operators either... - Vector4DAligned& operator=( Vector4DAligned const& src ); -}; - -//----------------------------------------------------------------------------- -// Vector4D related operations -//----------------------------------------------------------------------------- - -// Vector4D clear -void Vector4DClear( Vector4D& a ); - -// Copy -void Vector4DCopy( Vector4D const& src, Vector4D& dst ); - -// Vector4D arithmetic -void Vector4DAdd( Vector4D const& a, Vector4D const& b, Vector4D& result ); -void Vector4DSubtract( Vector4D const& a, Vector4D const& b, Vector4D& result ); -void Vector4DMultiply( Vector4D const& a, vec_t b, Vector4D& result ); -void Vector4DMultiply( Vector4D const& a, Vector4D const& b, Vector4D& result ); -void Vector4DDivide( Vector4D const& a, vec_t b, Vector4D& result ); -void Vector4DDivide( Vector4D const& a, Vector4D const& b, Vector4D& result ); -void Vector4DMA( Vector4D const& start, float s, Vector4D const& dir, Vector4D& result ); - -// Vector4DAligned arithmetic -void Vector4DMultiplyAligned( Vector4DAligned const& a, vec_t b, Vector4DAligned& result ); - - -#define Vector4DExpand( v ) (v).x, (v).y, (v).z, (v).w - -// Normalization -vec_t Vector4DNormalize( Vector4D& v ); - -// Length -vec_t Vector4DLength( Vector4D const& v ); - -// Dot Product -vec_t DotProduct4D(Vector4D const& a, Vector4D const& b); - -// Linearly interpolate between two vectors -void Vector4DLerp(Vector4D const& src1, Vector4D const& src2, vec_t t, Vector4D& dest ); - - -//----------------------------------------------------------------------------- -// -// Inlined Vector4D methods -// -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -// constructors -//----------------------------------------------------------------------------- - -inline Vector4D::Vector4D(void) -{ -#ifdef _DEBUG - // Initialize to NAN to catch errors - x = y = z = w = VEC_T_NAN; -#endif -} - -inline Vector4D::Vector4D(vec_t X, vec_t Y, vec_t Z, vec_t W ) -{ - x = X; y = Y; z = Z; w = W; - Assert( IsValid() ); -} - -inline Vector4D::Vector4D(const float *pFloat) -{ - Assert( pFloat ); - x = pFloat[0]; y = pFloat[1]; z = pFloat[2]; w = pFloat[3]; - Assert( IsValid() ); -} - - -//----------------------------------------------------------------------------- -// copy constructor -//----------------------------------------------------------------------------- - -inline Vector4D::Vector4D(const Vector4D &vOther) -{ - Assert( vOther.IsValid() ); - x = vOther.x; y = vOther.y; z = vOther.z; w = vOther.w; -} - -//----------------------------------------------------------------------------- -// initialization -//----------------------------------------------------------------------------- - -inline void Vector4D::Init( vec_t ix, vec_t iy, vec_t iz, vec_t iw ) -{ - x = ix; y = iy; z = iz; w = iw; - Assert( IsValid() ); -} - -inline void Vector4D::Random( vec_t minVal, vec_t maxVal ) -{ - x = minVal + ((vec_t)rand() / RAND_MAX) * (maxVal - minVal); - y = minVal + ((vec_t)rand() / RAND_MAX) * (maxVal - minVal); - z = minVal + ((vec_t)rand() / RAND_MAX) * (maxVal - minVal); - w = minVal + ((vec_t)rand() / RAND_MAX) * (maxVal - minVal); -} - -inline void Vector4DClear( Vector4D& a ) -{ - a.x = a.y = a.z = a.w = 0.0f; -} - -//----------------------------------------------------------------------------- -// assignment -//----------------------------------------------------------------------------- - -inline Vector4D& Vector4D::operator=(const Vector4D &vOther) -{ - Assert( vOther.IsValid() ); - x=vOther.x; y=vOther.y; z=vOther.z; w=vOther.w; - return *this; -} - -//----------------------------------------------------------------------------- -// Array access -//----------------------------------------------------------------------------- - -inline vec_t& Vector4D::operator[](int i) -{ - Assert( (i >= 0) && (i < 4) ); - return ((vec_t*)this)[i]; -} - -inline vec_t Vector4D::operator[](int i) const -{ - Assert( (i >= 0) && (i < 4) ); - return ((vec_t*)this)[i]; -} - -//----------------------------------------------------------------------------- -// Cast to Vector and Vector2D... -//----------------------------------------------------------------------------- - -inline Vector& Vector4D::AsVector3D() -{ - return *(Vector*)this; -} - -inline Vector const& Vector4D::AsVector3D() const -{ - return *(Vector const*)this; -} - -inline Vector2D& Vector4D::AsVector2D() -{ - return *(Vector2D*)this; -} - -inline Vector2D const& Vector4D::AsVector2D() const -{ - return *(Vector2D const*)this; -} - -//----------------------------------------------------------------------------- -// Base address... -//----------------------------------------------------------------------------- - -inline vec_t* Vector4D::Base() -{ - return (vec_t*)this; -} - -inline vec_t const* Vector4D::Base() const -{ - return (vec_t const*)this; -} - -//----------------------------------------------------------------------------- -// IsValid? -//----------------------------------------------------------------------------- - -inline bool Vector4D::IsValid() const -{ - return IsFinite(x) && IsFinite(y) && IsFinite(z) && IsFinite(w); -} - -//----------------------------------------------------------------------------- -// comparison -//----------------------------------------------------------------------------- - -inline bool Vector4D::operator==( Vector4D const& src ) const -{ - Assert( src.IsValid() && IsValid() ); - return (src.x == x) && (src.y == y) && (src.z == z) && (src.w == w); -} - -inline bool Vector4D::operator!=( Vector4D const& src ) const -{ - Assert( src.IsValid() && IsValid() ); - return (src.x != x) || (src.y != y) || (src.z != z) || (src.w != w); -} - - -//----------------------------------------------------------------------------- -// Copy -//----------------------------------------------------------------------------- - -inline void Vector4DCopy( Vector4D const& src, Vector4D& dst ) -{ - Assert( src.IsValid() ); - dst.x = src.x; - dst.y = src.y; - dst.z = src.z; - dst.w = src.w; -} - -inline void Vector4D::CopyToArray(float* rgfl) const -{ - Assert( IsValid() ); - Assert( rgfl ); - rgfl[0] = x; rgfl[1] = y; rgfl[2] = z; rgfl[3] = w; -} - -//----------------------------------------------------------------------------- -// standard math operations -//----------------------------------------------------------------------------- - -inline void Vector4D::Negate() -{ - Assert( IsValid() ); - x = -x; y = -y; z = -z; w = -w; -} - -inline Vector4D& Vector4D::operator+=(const Vector4D& v) -{ - Assert( IsValid() && v.IsValid() ); - x+=v.x; y+=v.y; z += v.z; w += v.w; - return *this; -} - -inline Vector4D& Vector4D::operator-=(const Vector4D& v) -{ - Assert( IsValid() && v.IsValid() ); - x-=v.x; y-=v.y; z -= v.z; w -= v.w; - return *this; -} - -inline Vector4D& Vector4D::operator*=(float fl) -{ - x *= fl; - y *= fl; - z *= fl; - w *= fl; - Assert( IsValid() ); - return *this; -} - -inline Vector4D& Vector4D::operator*=(Vector4D const& v) -{ - x *= v.x; - y *= v.y; - z *= v.z; - w *= v.w; - Assert( IsValid() ); - return *this; -} - -inline Vector4D& Vector4D::operator/=(float fl) -{ - Assert( fl != 0.0f ); - float oofl = 1.0f / fl; - x *= oofl; - y *= oofl; - z *= oofl; - w *= oofl; - Assert( IsValid() ); - return *this; -} - -inline Vector4D& Vector4D::operator/=(Vector4D const& v) -{ - Assert( v.x != 0.0f && v.y != 0.0f && v.z != 0.0f && v.w != 0.0f ); - x /= v.x; - y /= v.y; - z /= v.z; - w /= v.w; - Assert( IsValid() ); - return *this; -} - -inline void Vector4DAdd( Vector4D const& a, Vector4D const& b, Vector4D& c ) -{ - Assert( a.IsValid() && b.IsValid() ); - c.x = a.x + b.x; - c.y = a.y + b.y; - c.z = a.z + b.z; - c.w = a.w + b.w; -} - -inline void Vector4DSubtract( Vector4D const& a, Vector4D const& b, Vector4D& c ) -{ - Assert( a.IsValid() && b.IsValid() ); - c.x = a.x - b.x; - c.y = a.y - b.y; - c.z = a.z - b.z; - c.w = a.w - b.w; -} - -inline void Vector4DMultiply( Vector4D const& a, vec_t b, Vector4D& c ) -{ - Assert( a.IsValid() && IsFinite(b) ); - c.x = a.x * b; - c.y = a.y * b; - c.z = a.z * b; - c.w = a.w * b; -} - -inline void Vector4DMultiply( Vector4D const& a, Vector4D const& b, Vector4D& c ) -{ - Assert( a.IsValid() && b.IsValid() ); - c.x = a.x * b.x; - c.y = a.y * b.y; - c.z = a.z * b.z; - c.w = a.w * b.w; -} - -inline void Vector4DDivide( Vector4D const& a, vec_t b, Vector4D& c ) -{ - Assert( a.IsValid() ); - Assert( b != 0.0f ); - vec_t oob = 1.0f / b; - c.x = a.x * oob; - c.y = a.y * oob; - c.z = a.z * oob; - c.w = a.w * oob; -} - -inline void Vector4DDivide( Vector4D const& a, Vector4D const& b, Vector4D& c ) -{ - Assert( a.IsValid() ); - Assert( (b.x != 0.0f) && (b.y != 0.0f) && (b.z != 0.0f) && (b.w != 0.0f) ); - c.x = a.x / b.x; - c.y = a.y / b.y; - c.z = a.z / b.z; - c.w = a.w / b.w; -} - -inline void Vector4DMA( Vector4D const& start, float s, Vector4D const& dir, Vector4D& result ) -{ - Assert( start.IsValid() && IsFinite(s) && dir.IsValid() ); - result.x = start.x + s*dir.x; - result.y = start.y + s*dir.y; - result.z = start.z + s*dir.z; - result.w = start.w + s*dir.w; -} - -// FIXME: Remove -// For backwards compatability -inline void Vector4D::MulAdd(Vector4D const& a, Vector4D const& b, float scalar) -{ - x = a.x + b.x * scalar; - y = a.y + b.y * scalar; - z = a.z + b.z * scalar; - w = a.w + b.w * scalar; -} - -inline void Vector4DLerp(const Vector4D& src1, const Vector4D& src2, vec_t t, Vector4D& dest ) -{ - dest[0] = src1[0] + (src2[0] - src1[0]) * t; - dest[1] = src1[1] + (src2[1] - src1[1]) * t; - dest[2] = src1[2] + (src2[2] - src1[2]) * t; - dest[3] = src1[3] + (src2[3] - src1[3]) * t; -} - -//----------------------------------------------------------------------------- -// dot, cross -//----------------------------------------------------------------------------- - -inline vec_t DotProduct4D(const Vector4D& a, const Vector4D& b) -{ - Assert( a.IsValid() && b.IsValid() ); - return( a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w ); -} - -// for backwards compatability -inline vec_t Vector4D::Dot( Vector4D const& vOther ) const -{ - return DotProduct4D( *this, vOther ); -} - - -//----------------------------------------------------------------------------- -// length -//----------------------------------------------------------------------------- - -inline vec_t Vector4DLength( Vector4D const& v ) -{ - Assert( v.IsValid() ); - return (vec_t)FastSqrt(v.x*v.x + v.y*v.y + v.z*v.z + v.w*v.w); -} - -inline vec_t Vector4D::LengthSqr(void) const -{ - Assert( IsValid() ); - return (x*x + y*y + z*z + w*w); -} - -inline vec_t Vector4D::Length(void) const -{ - return Vector4DLength( *this ); -} - - -//----------------------------------------------------------------------------- -// Normalization -//----------------------------------------------------------------------------- - -// FIXME: Can't use until we're un-macroed in mathlib.h -inline vec_t Vector4DNormalize( Vector4D& v ) -{ - Assert( v.IsValid() ); - vec_t l = v.Length(); - if (l != 0.0f) - { - v /= l; - } - else - { - v.x = v.y = v.z = v.w = 0.0f; - } - return l; -} - -//----------------------------------------------------------------------------- -// Get the distance from this Vector4D to the other one -//----------------------------------------------------------------------------- - -inline vec_t Vector4D::DistTo(const Vector4D &vOther) const -{ - Vector4D delta; - Vector4DSubtract( *this, vOther, delta ); - return delta.Length(); -} - -inline vec_t Vector4D::DistToSqr(const Vector4D &vOther) const -{ - Vector4D delta; - Vector4DSubtract( *this, vOther, delta ); - return delta.LengthSqr(); -} - - -//----------------------------------------------------------------------------- -// Vector4DAligned routines -//----------------------------------------------------------------------------- - -inline Vector4DAligned::Vector4DAligned( vec_t X, vec_t Y, vec_t Z, vec_t W ) -{ - x = X; y = Y; z = Z; w = W; - Assert( IsValid() ); -} - -inline void Vector4DAligned::Set( vec_t X, vec_t Y, vec_t Z, vec_t W ) -{ - x = X; y = Y; z = Z; w = W; - Assert( IsValid() ); -} - -inline void Vector4DAligned::InitZero( void ) -{ -#if !defined( _X360 ) - this->AsM128() = _mm_set1_ps( 0.0f ); -#else - this->AsM128() = __vspltisw( 0 ); -#endif - Assert( IsValid() ); -} - -inline void Vector4DMultiplyAligned( Vector4DAligned const& a, Vector4DAligned const& b, Vector4DAligned& c ) -{ - Assert( a.IsValid() && b.IsValid() ); -#if !defined( _X360 ) - c.x = a.x * b.x; - c.y = a.y * b.y; - c.z = a.z * b.z; - c.w = a.w * b.w; -#else - c.AsM128() = __vmulfp( a.AsM128(), b.AsM128() ); -#endif -} - -inline void Vector4DWeightMAD( vec_t w, Vector4DAligned const& vInA, Vector4DAligned& vOutA, Vector4DAligned const& vInB, Vector4DAligned& vOutB ) -{ - Assert( vInA.IsValid() && vInB.IsValid() && IsFinite(w) ); - -#if !defined( _X360 ) - vOutA.x += vInA.x * w; - vOutA.y += vInA.y * w; - vOutA.z += vInA.z * w; - vOutA.w += vInA.w * w; - - vOutB.x += vInB.x * w; - vOutB.y += vInB.y * w; - vOutB.z += vInB.z * w; - vOutB.w += vInB.w * w; -#else - __vector4 temp; - - temp = __lvlx( &w, 0 ); - temp = __vspltw( temp, 0 ); - - vOutA.AsM128() = __vmaddfp( vInA.AsM128(), temp, vOutA.AsM128() ); - vOutB.AsM128() = __vmaddfp( vInB.AsM128(), temp, vOutB.AsM128() ); -#endif -} - -inline void Vector4DWeightMADSSE( vec_t w, Vector4DAligned const& vInA, Vector4DAligned& vOutA, Vector4DAligned const& vInB, Vector4DAligned& vOutB ) -{ - Assert( vInA.IsValid() && vInB.IsValid() && IsFinite(w) ); - -#if !defined( _X360 ) - // Replicate scalar float out to 4 components - __m128 packed = _mm_set1_ps( w ); - - // 4D SSE Vector MAD - vOutA.AsM128() = _mm_add_ps( vOutA.AsM128(), _mm_mul_ps( vInA.AsM128(), packed ) ); - vOutB.AsM128() = _mm_add_ps( vOutB.AsM128(), _mm_mul_ps( vInB.AsM128(), packed ) ); -#else - __vector4 temp; - - temp = __lvlx( &w, 0 ); - temp = __vspltw( temp, 0 ); - - vOutA.AsM128() = __vmaddfp( vInA.AsM128(), temp, vOutA.AsM128() ); - vOutB.AsM128() = __vmaddfp( vInB.AsM128(), temp, vOutB.AsM128() ); -#endif -} - -#endif // VECTOR4D_H - diff --git a/public/mathlib/vmatrix.h b/public/mathlib/vmatrix.h deleted file mode 100644 index 90b1fcf9c..000000000 --- a/public/mathlib/vmatrix.h +++ /dev/null @@ -1,938 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -// -// VMatrix always postmultiply vectors as in Ax = b. -// Given a set of basis vectors ((F)orward, (L)eft, (U)p), and a (T)ranslation, -// a matrix to transform a vector into that space looks like this: -// Fx Lx Ux Tx -// Fy Ly Uy Ty -// Fz Lz Uz Tz -// 0 0 0 1 - -// Note that concatenating matrices needs to multiply them in reverse order. -// ie: if I want to apply matrix A, B, then C, the equation needs to look like this: -// C * B * A * v -// ie: -// v = A * v; -// v = B * v; -// v = C * v; -//============================================================================= - -#ifndef VMATRIX_H -#define VMATRIX_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include "mathlib/vector.h" -#include "mathlib/vplane.h" -#include "mathlib/vector4d.h" -#include "mathlib/mathlib.h" - -struct cplane_t; - - -class VMatrix -{ -public: - - VMatrix(); - VMatrix( - vec_t m00, vec_t m01, vec_t m02, vec_t m03, - vec_t m10, vec_t m11, vec_t m12, vec_t m13, - vec_t m20, vec_t m21, vec_t m22, vec_t m23, - vec_t m30, vec_t m31, vec_t m32, vec_t m33 - ); - - // Creates a matrix where the X axis = forward - // the Y axis = left, and the Z axis = up - VMatrix( const Vector& forward, const Vector& left, const Vector& up ); - - // Construct from a 3x4 matrix - VMatrix( const matrix3x4_t& matrix3x4 ); - - // Set the values in the matrix. - void Init( - vec_t m00, vec_t m01, vec_t m02, vec_t m03, - vec_t m10, vec_t m11, vec_t m12, vec_t m13, - vec_t m20, vec_t m21, vec_t m22, vec_t m23, - vec_t m30, vec_t m31, vec_t m32, vec_t m33 - ); - - - // Initialize from a 3x4 - void Init( const matrix3x4_t& matrix3x4 ); - - // array access - inline float* operator[](int i) - { - return m[i]; - } - - inline const float* operator[](int i) const - { - return m[i]; - } - - // Get a pointer to m[0][0] - inline float *Base() - { - return &m[0][0]; - } - - inline const float *Base() const - { - return &m[0][0]; - } - - void SetLeft(const Vector &vLeft); - void SetUp(const Vector &vUp); - void SetForward(const Vector &vForward); - - void GetBasisVectors(Vector &vForward, Vector &vLeft, Vector &vUp) const; - void SetBasisVectors(const Vector &vForward, const Vector &vLeft, const Vector &vUp); - - // Get/set the translation. - Vector & GetTranslation( Vector &vTrans ) const; - void SetTranslation(const Vector &vTrans); - - void PreTranslate(const Vector &vTrans); - void PostTranslate(const Vector &vTrans); - - matrix3x4_t& As3x4(); - const matrix3x4_t& As3x4() const; - void CopyFrom3x4( const matrix3x4_t &m3x4 ); - void Set3x4( matrix3x4_t& matrix3x4 ) const; - - bool operator==( const VMatrix& src ) const; - bool operator!=( const VMatrix& src ) const { return !( *this == src ); } - -#ifndef VECTOR_NO_SLOW_OPERATIONS - // Access the basis vectors. - Vector GetLeft() const; - Vector GetUp() const; - Vector GetForward() const; - Vector GetTranslation() const; -#endif - - -// Matrix->vector operations. -public: - // Multiply by a 3D vector (same as operator*). - void V3Mul(const Vector &vIn, Vector &vOut) const; - - // Multiply by a 4D vector. - void V4Mul(const Vector4D &vIn, Vector4D &vOut) const; - -#ifndef VECTOR_NO_SLOW_OPERATIONS - // Applies the rotation (ignores translation in the matrix). (This just calls VMul3x3). - Vector ApplyRotation(const Vector &vVec) const; - - // Multiply by a vector (divides by w, assumes input w is 1). - Vector operator*(const Vector &vVec) const; - - // Multiply by the upper 3x3 part of the matrix (ie: only apply rotation). - Vector VMul3x3(const Vector &vVec) const; - - // Apply the inverse (transposed) rotation (only works on pure rotation matrix) - Vector VMul3x3Transpose(const Vector &vVec) const; - - // Multiply by the upper 3 rows. - Vector VMul4x3(const Vector &vVec) const; - - // Apply the inverse (transposed) transformation (only works on pure rotation/translation) - Vector VMul4x3Transpose(const Vector &vVec) const; -#endif - - -// Matrix->plane operations. -public: - // Transform the plane. The matrix can only contain translation and rotation. - void TransformPlane( const VPlane &inPlane, VPlane &outPlane ) const; - -#ifndef VECTOR_NO_SLOW_OPERATIONS - // Just calls TransformPlane and returns the result. - VPlane operator*(const VPlane &thePlane) const; -#endif - -// Matrix->matrix operations. -public: - - VMatrix& operator=(const VMatrix &mOther); - - // Multiply two matrices (out = this * vm). - void MatrixMul( const VMatrix &vm, VMatrix &out ) const; - - // Add two matrices. - const VMatrix& operator+=(const VMatrix &other); - -#ifndef VECTOR_NO_SLOW_OPERATIONS - // Just calls MatrixMul and returns the result. - VMatrix operator*(const VMatrix &mOther) const; - - // Add/Subtract two matrices. - VMatrix operator+(const VMatrix &other) const; - VMatrix operator-(const VMatrix &other) const; - - // Negation. - VMatrix operator-() const; - - // Return inverse matrix. Be careful because the results are undefined - // if the matrix doesn't have an inverse (ie: InverseGeneral returns false). - VMatrix operator~() const; -#endif - -// Matrix operations. -public: - // Set to identity. - void Identity(); - - bool IsIdentity() const; - - // Setup a matrix for origin and angles. - void SetupMatrixOrgAngles( const Vector &origin, const QAngle &vAngles ); - - // General inverse. This may fail so check the return! - bool InverseGeneral(VMatrix &vInverse) const; - - // Does a fast inverse, assuming the matrix only contains translation and rotation. - void InverseTR( VMatrix &mRet ) const; - - // Usually used for debug checks. Returns true if the upper 3x3 contains - // unit vectors and they are all orthogonal. - bool IsRotationMatrix() const; - -#ifndef VECTOR_NO_SLOW_OPERATIONS - // This calls the other InverseTR and returns the result. - VMatrix InverseTR() const; - - // Get the scale of the matrix's basis vectors. - Vector GetScale() const; - - // (Fast) multiply by a scaling matrix setup from vScale. - VMatrix Scale(const Vector &vScale); - - // Normalize the basis vectors. - VMatrix NormalizeBasisVectors() const; - - // Transpose. - VMatrix Transpose() const; - - // Transpose upper-left 3x3. - VMatrix Transpose3x3() const; -#endif - -public: - // The matrix. - vec_t m[4][4]; -}; - - - -//----------------------------------------------------------------------------- -// Helper functions. -//----------------------------------------------------------------------------- - -#ifndef VECTOR_NO_SLOW_OPERATIONS - -// Setup an identity matrix. -VMatrix SetupMatrixIdentity(); - -// Setup as a scaling matrix. -VMatrix SetupMatrixScale(const Vector &vScale); - -// Setup a translation matrix. -VMatrix SetupMatrixTranslation(const Vector &vTranslation); - -// Setup a matrix to reflect around the plane. -VMatrix SetupMatrixReflection(const VPlane &thePlane); - -// Setup a matrix to project from vOrigin onto thePlane. -VMatrix SetupMatrixProjection(const Vector &vOrigin, const VPlane &thePlane); - -// Setup a matrix to rotate the specified amount around the specified axis. -VMatrix SetupMatrixAxisRot(const Vector &vAxis, vec_t fDegrees); - -// Setup a matrix from euler angles. Just sets identity and calls MatrixAngles. -VMatrix SetupMatrixAngles(const QAngle &vAngles); - -// Setup a matrix for origin and angles. -VMatrix SetupMatrixOrgAngles(const Vector &origin, const QAngle &vAngles); - -#endif - -#define VMatToString(mat) (static_cast(CFmtStr("[ (%f, %f, %f), (%f, %f, %f), (%f, %f, %f), (%f, %f, %f) ]", mat.m[0][0], mat.m[0][1], mat.m[0][2], mat.m[0][3], mat.m[1][0], mat.m[1][1], mat.m[1][2], mat.m[1][3], mat.m[2][0], mat.m[2][1], mat.m[2][2], mat.m[2][3], mat.m[3][0], mat.m[3][1], mat.m[3][2], mat.m[3][3] ))) // ** Note: this generates a temporary, don't hold reference! - -//----------------------------------------------------------------------------- -// Returns the point at the intersection on the 3 planes. -// Returns false if it can't be solved (2 or more planes are parallel). -//----------------------------------------------------------------------------- -bool PlaneIntersection( const VPlane &vp1, const VPlane &vp2, const VPlane &vp3, Vector &vOut ); - - -//----------------------------------------------------------------------------- -// These methods are faster. Use them if you want faster code -//----------------------------------------------------------------------------- -void MatrixSetIdentity( VMatrix &dst ); -void MatrixTranspose( const VMatrix& src, VMatrix& dst ); -void MatrixCopy( const VMatrix& src, VMatrix& dst ); -void MatrixMultiply( const VMatrix& src1, const VMatrix& src2, VMatrix& dst ); - -// Accessors -void MatrixGetColumn( const VMatrix &src, int nCol, Vector *pColumn ); -void MatrixSetColumn( VMatrix &src, int nCol, const Vector &column ); -void MatrixGetRow( const VMatrix &src, int nCol, Vector *pColumn ); -void MatrixSetRow( VMatrix &src, int nCol, const Vector &column ); - -// Vector3DMultiply treats src2 as if it's a direction vector -void Vector3DMultiply( const VMatrix& src1, const Vector& src2, Vector& dst ); - -// Vector3DMultiplyPosition treats src2 as if it's a point (adds the translation) -inline void Vector3DMultiplyPosition( const VMatrix& src1, const VectorByValue src2, Vector& dst ); - -// Vector3DMultiplyPositionProjective treats src2 as if it's a point -// and does the perspective divide at the end -void Vector3DMultiplyPositionProjective( const VMatrix& src1, const Vector &src2, Vector& dst ); - -// Vector3DMultiplyPosition treats src2 as if it's a direction -// and does the perspective divide at the end -// NOTE: src1 had better be an inverse transpose to use this correctly -void Vector3DMultiplyProjective( const VMatrix& src1, const Vector &src2, Vector& dst ); - -void Vector4DMultiply( const VMatrix& src1, const Vector4D& src2, Vector4D& dst ); - -// Same as Vector4DMultiply except that src2 has an implicit W of 1 -void Vector4DMultiplyPosition( const VMatrix& src1, const Vector &src2, Vector4D& dst ); - -// Multiplies the vector by the transpose of the matrix -void Vector3DMultiplyTranspose( const VMatrix& src1, const Vector& src2, Vector& dst ); -void Vector4DMultiplyTranspose( const VMatrix& src1, const Vector4D& src2, Vector4D& dst ); - -// Transform a plane -void MatrixTransformPlane( const VMatrix &src, const cplane_t &inPlane, cplane_t &outPlane ); - -// Transform a plane that has an axis-aligned normal -void MatrixTransformAxisAlignedPlane( const VMatrix &src, int nDim, float flSign, float flDist, cplane_t &outPlane ); - -void MatrixBuildTranslation( VMatrix& dst, float x, float y, float z ); -void MatrixBuildTranslation( VMatrix& dst, const Vector &translation ); - -inline void MatrixTranslate( VMatrix& dst, const Vector &translation ) -{ - VMatrix matTranslation, temp; - MatrixBuildTranslation( matTranslation, translation ); - MatrixMultiply( dst, matTranslation, temp ); - dst = temp; -} - - -void MatrixBuildRotationAboutAxis( VMatrix& dst, const Vector& vAxisOfRot, float angleDegrees ); -void MatrixBuildRotateZ( VMatrix& dst, float angleDegrees ); - -inline void MatrixRotate( VMatrix& dst, const Vector& vAxisOfRot, float angleDegrees ) -{ - VMatrix rotation, temp; - MatrixBuildRotationAboutAxis( rotation, vAxisOfRot, angleDegrees ); - MatrixMultiply( dst, rotation, temp ); - dst = temp; -} - -// Builds a rotation matrix that rotates one direction vector into another -void MatrixBuildRotation( VMatrix &dst, const Vector& initialDirection, const Vector& finalDirection ); - -// Builds a scale matrix -void MatrixBuildScale( VMatrix &dst, float x, float y, float z ); -void MatrixBuildScale( VMatrix &dst, const Vector& scale ); - -// Build a perspective matrix. -// zNear and zFar are assumed to be positive. -// You end up looking down positive Z, X is to the right, Y is up. -// X range: [0..1] -// Y range: [0..1] -// Z range: [0..1] -void MatrixBuildPerspective( VMatrix &dst, float fovX, float fovY, float zNear, float zFar ); - -//----------------------------------------------------------------------------- -// Given a projection matrix, take the extremes of the space in transformed into world space and -// get a bounding box. -//----------------------------------------------------------------------------- -void CalculateAABBFromProjectionMatrix( const VMatrix &worldToVolume, Vector *pMins, Vector *pMaxs ); - -//----------------------------------------------------------------------------- -// Given a projection matrix, take the extremes of the space in transformed into world space and -// get a bounding sphere. -//----------------------------------------------------------------------------- -void CalculateSphereFromProjectionMatrix( const VMatrix &worldToVolume, Vector *pCenter, float *pflRadius ); - -//----------------------------------------------------------------------------- -// Given an inverse projection matrix, take the extremes of the space in transformed into world space and -// get a bounding box. -//----------------------------------------------------------------------------- -void CalculateAABBFromProjectionMatrixInverse( const VMatrix &volumeToWorld, Vector *pMins, Vector *pMaxs ); - -//----------------------------------------------------------------------------- -// Given an inverse projection matrix, take the extremes of the space in transformed into world space and -// get a bounding sphere. -//----------------------------------------------------------------------------- -void CalculateSphereFromProjectionMatrixInverse( const VMatrix &volumeToWorld, Vector *pCenter, float *pflRadius ); - -//----------------------------------------------------------------------------- -// Calculate frustum planes given a clip->world space transform. -//----------------------------------------------------------------------------- -void FrustumPlanesFromMatrix( const VMatrix &clipToWorld, Frustum_t &frustum ); - -//----------------------------------------------------------------------------- -// Setup a matrix from euler angles. -//----------------------------------------------------------------------------- -void MatrixFromAngles( const QAngle& vAngles, VMatrix& dst ); - -//----------------------------------------------------------------------------- -// Creates euler angles from a matrix -//----------------------------------------------------------------------------- -void MatrixToAngles( const VMatrix& src, QAngle& vAngles ); - -//----------------------------------------------------------------------------- -// Does a fast inverse, assuming the matrix only contains translation and rotation. -//----------------------------------------------------------------------------- -void MatrixInverseTR( const VMatrix& src, VMatrix &dst ); - -//----------------------------------------------------------------------------- -// Inverts any matrix at all -//----------------------------------------------------------------------------- -bool MatrixInverseGeneral(const VMatrix& src, VMatrix& dst); - -//----------------------------------------------------------------------------- -// Computes the inverse transpose -//----------------------------------------------------------------------------- -void MatrixInverseTranspose( const VMatrix& src, VMatrix& dst ); - - - -//----------------------------------------------------------------------------- -// VMatrix inlines. -//----------------------------------------------------------------------------- -inline VMatrix::VMatrix() -{ -} - -inline VMatrix::VMatrix( - vec_t m00, vec_t m01, vec_t m02, vec_t m03, - vec_t m10, vec_t m11, vec_t m12, vec_t m13, - vec_t m20, vec_t m21, vec_t m22, vec_t m23, - vec_t m30, vec_t m31, vec_t m32, vec_t m33) -{ - Init( - m00, m01, m02, m03, - m10, m11, m12, m13, - m20, m21, m22, m23, - m30, m31, m32, m33 - ); -} - - -inline VMatrix::VMatrix( const matrix3x4_t& matrix3x4 ) -{ - Init( matrix3x4 ); -} - - -//----------------------------------------------------------------------------- -// Creates a matrix where the X axis = forward -// the Y axis = left, and the Z axis = up -//----------------------------------------------------------------------------- -inline VMatrix::VMatrix( const Vector& xAxis, const Vector& yAxis, const Vector& zAxis ) -{ - Init( - xAxis.x, yAxis.x, zAxis.x, 0.0f, - xAxis.y, yAxis.y, zAxis.y, 0.0f, - xAxis.z, yAxis.z, zAxis.z, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f - ); -} - - -inline void VMatrix::Init( - vec_t m00, vec_t m01, vec_t m02, vec_t m03, - vec_t m10, vec_t m11, vec_t m12, vec_t m13, - vec_t m20, vec_t m21, vec_t m22, vec_t m23, - vec_t m30, vec_t m31, vec_t m32, vec_t m33 - ) -{ - m[0][0] = m00; - m[0][1] = m01; - m[0][2] = m02; - m[0][3] = m03; - - m[1][0] = m10; - m[1][1] = m11; - m[1][2] = m12; - m[1][3] = m13; - - m[2][0] = m20; - m[2][1] = m21; - m[2][2] = m22; - m[2][3] = m23; - - m[3][0] = m30; - m[3][1] = m31; - m[3][2] = m32; - m[3][3] = m33; -} - - -//----------------------------------------------------------------------------- -// Initialize from a 3x4 -//----------------------------------------------------------------------------- -inline void VMatrix::Init( const matrix3x4_t& matrix3x4 ) -{ - memcpy(m, matrix3x4.Base(), sizeof( matrix3x4_t ) ); - - m[3][0] = 0.0f; - m[3][1] = 0.0f; - m[3][2] = 0.0f; - m[3][3] = 1.0f; -} - - -//----------------------------------------------------------------------------- -// Methods related to the basis vectors of the matrix -//----------------------------------------------------------------------------- - -#ifndef VECTOR_NO_SLOW_OPERATIONS - -inline Vector VMatrix::GetForward() const -{ - return Vector(m[0][0], m[1][0], m[2][0]); -} - -inline Vector VMatrix::GetLeft() const -{ - return Vector(m[0][1], m[1][1], m[2][1]); -} - -inline Vector VMatrix::GetUp() const -{ - return Vector(m[0][2], m[1][2], m[2][2]); -} - -#endif - -inline void VMatrix::SetForward(const Vector &vForward) -{ - m[0][0] = vForward.x; - m[1][0] = vForward.y; - m[2][0] = vForward.z; -} - -inline void VMatrix::SetLeft(const Vector &vLeft) -{ - m[0][1] = vLeft.x; - m[1][1] = vLeft.y; - m[2][1] = vLeft.z; -} - -inline void VMatrix::SetUp(const Vector &vUp) -{ - m[0][2] = vUp.x; - m[1][2] = vUp.y; - m[2][2] = vUp.z; -} - -inline void VMatrix::GetBasisVectors(Vector &vForward, Vector &vLeft, Vector &vUp) const -{ - vForward.Init( m[0][0], m[1][0], m[2][0] ); - vLeft.Init( m[0][1], m[1][1], m[2][1] ); - vUp.Init( m[0][2], m[1][2], m[2][2] ); -} - -inline void VMatrix::SetBasisVectors(const Vector &vForward, const Vector &vLeft, const Vector &vUp) -{ - SetForward(vForward); - SetLeft(vLeft); - SetUp(vUp); -} - - -//----------------------------------------------------------------------------- -// Methods related to the translation component of the matrix -//----------------------------------------------------------------------------- -#ifndef VECTOR_NO_SLOW_OPERATIONS - -inline Vector VMatrix::GetTranslation() const -{ - return Vector(m[0][3], m[1][3], m[2][3]); -} - -#endif - -inline Vector& VMatrix::GetTranslation( Vector &vTrans ) const -{ - vTrans.x = m[0][3]; - vTrans.y = m[1][3]; - vTrans.z = m[2][3]; - return vTrans; -} - -inline void VMatrix::SetTranslation(const Vector &vTrans) -{ - m[0][3] = vTrans.x; - m[1][3] = vTrans.y; - m[2][3] = vTrans.z; -} - - -//----------------------------------------------------------------------------- -// appply translation to this matrix in the input space -//----------------------------------------------------------------------------- -inline void VMatrix::PreTranslate(const Vector &vTrans) -{ - Vector tmp; - Vector3DMultiplyPosition( *this, vTrans, tmp ); - m[0][3] = tmp.x; - m[1][3] = tmp.y; - m[2][3] = tmp.z; -} - - -//----------------------------------------------------------------------------- -// appply translation to this matrix in the output space -//----------------------------------------------------------------------------- -inline void VMatrix::PostTranslate(const Vector &vTrans) -{ - m[0][3] += vTrans.x; - m[1][3] += vTrans.y; - m[2][3] += vTrans.z; -} - -inline const matrix3x4_t& VMatrix::As3x4() const -{ - return *((const matrix3x4_t*)this); -} - -inline matrix3x4_t& VMatrix::As3x4() -{ - return *((matrix3x4_t*)this); -} - -inline void VMatrix::CopyFrom3x4( const matrix3x4_t &m3x4 ) -{ - memcpy( m, m3x4.Base(), sizeof( matrix3x4_t ) ); - m[3][0] = m[3][1] = m[3][2] = 0; - m[3][3] = 1; -} - -inline void VMatrix::Set3x4( matrix3x4_t& matrix3x4 ) const -{ - memcpy(matrix3x4.Base(), m, sizeof( matrix3x4_t ) ); -} - - -//----------------------------------------------------------------------------- -// Matrix math operations -//----------------------------------------------------------------------------- -inline const VMatrix& VMatrix::operator+=(const VMatrix &other) -{ - for(int i=0; i < 4; i++) - { - for(int j=0; j < 4; j++) - { - m[i][j] += other.m[i][j]; - } - } - - return *this; -} - - -#ifndef VECTOR_NO_SLOW_OPERATIONS - -inline VMatrix VMatrix::operator+(const VMatrix &other) const -{ - VMatrix ret; - for(int i=0; i < 16; i++) - { - ((float*)ret.m)[i] = ((float*)m)[i] + ((float*)other.m)[i]; - } - return ret; -} - -inline VMatrix VMatrix::operator-(const VMatrix &other) const -{ - VMatrix ret; - - for(int i=0; i < 4; i++) - { - for(int j=0; j < 4; j++) - { - ret.m[i][j] = m[i][j] - other.m[i][j]; - } - } - - return ret; -} - -inline VMatrix VMatrix::operator-() const -{ - VMatrix ret; - for( int i=0; i < 16; i++ ) - { - ((float*)ret.m)[i] = ((float*)m)[i]; - } - return ret; -} - -#endif // VECTOR_NO_SLOW_OPERATIONS - - -//----------------------------------------------------------------------------- -// Vector transformation -//----------------------------------------------------------------------------- - -#ifndef VECTOR_NO_SLOW_OPERATIONS - -inline Vector VMatrix::operator*(const Vector &vVec) const -{ - Vector vRet; - vRet.x = m[0][0]*vVec.x + m[0][1]*vVec.y + m[0][2]*vVec.z + m[0][3]; - vRet.y = m[1][0]*vVec.x + m[1][1]*vVec.y + m[1][2]*vVec.z + m[1][3]; - vRet.z = m[2][0]*vVec.x + m[2][1]*vVec.y + m[2][2]*vVec.z + m[2][3]; - - return vRet; -} - -inline Vector VMatrix::VMul4x3(const Vector &vVec) const -{ - Vector vResult; - Vector3DMultiplyPosition( *this, vVec, vResult ); - return vResult; -} - - -inline Vector VMatrix::VMul4x3Transpose(const Vector &vVec) const -{ - Vector tmp = vVec; - tmp.x -= m[0][3]; - tmp.y -= m[1][3]; - tmp.z -= m[2][3]; - - return Vector( - m[0][0]*tmp.x + m[1][0]*tmp.y + m[2][0]*tmp.z, - m[0][1]*tmp.x + m[1][1]*tmp.y + m[2][1]*tmp.z, - m[0][2]*tmp.x + m[1][2]*tmp.y + m[2][2]*tmp.z - ); -} - -inline Vector VMatrix::VMul3x3(const Vector &vVec) const -{ - return Vector( - m[0][0]*vVec.x + m[0][1]*vVec.y + m[0][2]*vVec.z, - m[1][0]*vVec.x + m[1][1]*vVec.y + m[1][2]*vVec.z, - m[2][0]*vVec.x + m[2][1]*vVec.y + m[2][2]*vVec.z - ); -} - -inline Vector VMatrix::VMul3x3Transpose(const Vector &vVec) const -{ - return Vector( - m[0][0]*vVec.x + m[1][0]*vVec.y + m[2][0]*vVec.z, - m[0][1]*vVec.x + m[1][1]*vVec.y + m[2][1]*vVec.z, - m[0][2]*vVec.x + m[1][2]*vVec.y + m[2][2]*vVec.z - ); -} - -#endif // VECTOR_NO_SLOW_OPERATIONS - - -inline void VMatrix::V3Mul(const Vector &vIn, Vector &vOut) const -{ - vec_t rw; - - rw = 1.0f / (m[3][0]*vIn.x + m[3][1]*vIn.y + m[3][2]*vIn.z + m[3][3]); - vOut.x = (m[0][0]*vIn.x + m[0][1]*vIn.y + m[0][2]*vIn.z + m[0][3]) * rw; - vOut.y = (m[1][0]*vIn.x + m[1][1]*vIn.y + m[1][2]*vIn.z + m[1][3]) * rw; - vOut.z = (m[2][0]*vIn.x + m[2][1]*vIn.y + m[2][2]*vIn.z + m[2][3]) * rw; -} - -inline void VMatrix::V4Mul(const Vector4D &vIn, Vector4D &vOut) const -{ - vOut[0] = m[0][0]*vIn[0] + m[0][1]*vIn[1] + m[0][2]*vIn[2] + m[0][3]*vIn[3]; - vOut[1] = m[1][0]*vIn[0] + m[1][1]*vIn[1] + m[1][2]*vIn[2] + m[1][3]*vIn[3]; - vOut[2] = m[2][0]*vIn[0] + m[2][1]*vIn[1] + m[2][2]*vIn[2] + m[2][3]*vIn[3]; - vOut[3] = m[3][0]*vIn[0] + m[3][1]*vIn[1] + m[3][2]*vIn[2] + m[3][3]*vIn[3]; -} - - -//----------------------------------------------------------------------------- -// Plane transformation -//----------------------------------------------------------------------------- -inline void VMatrix::TransformPlane( const VPlane &inPlane, VPlane &outPlane ) const -{ - Vector vTrans; - Vector3DMultiply( *this, inPlane.m_Normal, outPlane.m_Normal ); - outPlane.m_Dist = inPlane.m_Dist * DotProduct( outPlane.m_Normal, outPlane.m_Normal ); - outPlane.m_Dist += DotProduct( outPlane.m_Normal, GetTranslation( vTrans ) ); -} - - -//----------------------------------------------------------------------------- -// Other random stuff -//----------------------------------------------------------------------------- -inline void VMatrix::Identity() -{ - MatrixSetIdentity( *this ); -} - - -inline bool VMatrix::IsIdentity() const -{ - return - m[0][0] == 1.0f && m[0][1] == 0.0f && m[0][2] == 0.0f && m[0][3] == 0.0f && - m[1][0] == 0.0f && m[1][1] == 1.0f && m[1][2] == 0.0f && m[1][3] == 0.0f && - m[2][0] == 0.0f && m[2][1] == 0.0f && m[2][2] == 1.0f && m[2][3] == 0.0f && - m[3][0] == 0.0f && m[3][1] == 0.0f && m[3][2] == 0.0f && m[3][3] == 1.0f; -} - -#ifndef VECTOR_NO_SLOW_OPERATIONS - -inline Vector VMatrix::ApplyRotation(const Vector &vVec) const -{ - return VMul3x3(vVec); -} - -inline VMatrix VMatrix::operator~() const -{ - VMatrix mRet; - InverseGeneral(mRet); - return mRet; -} - -#endif - - -//----------------------------------------------------------------------------- -// Accessors -//----------------------------------------------------------------------------- -inline void MatrixGetColumn( const VMatrix &src, int nCol, Vector *pColumn ) -{ - Assert( (nCol >= 0) && (nCol <= 3) ); - - pColumn->x = src[0][nCol]; - pColumn->y = src[1][nCol]; - pColumn->z = src[2][nCol]; -} - -inline void MatrixSetColumn( VMatrix &src, int nCol, const Vector &column ) -{ - Assert( (nCol >= 0) && (nCol <= 3) ); - - src.m[0][nCol] = column.x; - src.m[1][nCol] = column.y; - src.m[2][nCol] = column.z; -} - -inline void MatrixGetRow( const VMatrix &src, int nRow, Vector *pRow ) -{ - Assert( (nRow >= 0) && (nRow <= 3) ); - *pRow = *(Vector*)src[nRow]; -} - -inline void MatrixSetRow( VMatrix &dst, int nRow, const Vector &row ) -{ - Assert( (nRow >= 0) && (nRow <= 3) ); - *(Vector*)dst[nRow] = row; -} - - -//----------------------------------------------------------------------------- -// Vector3DMultiplyPosition treats src2 as if it's a point (adds the translation) -//----------------------------------------------------------------------------- -// NJS: src2 is passed in as a full vector rather than a reference to prevent the need -// for 2 branches and a potential copy in the body. (ie, handling the case when the src2 -// reference is the same as the dst reference ). -inline void Vector3DMultiplyPosition( const VMatrix& src1, const VectorByValue src2, Vector& dst ) -{ - dst[0] = src1[0][0] * src2.x + src1[0][1] * src2.y + src1[0][2] * src2.z + src1[0][3]; - dst[1] = src1[1][0] * src2.x + src1[1][1] * src2.y + src1[1][2] * src2.z + src1[1][3]; - dst[2] = src1[2][0] * src2.x + src1[2][1] * src2.y + src1[2][2] * src2.z + src1[2][3]; -} - - -//----------------------------------------------------------------------------- -// Transform a plane that has an axis-aligned normal -//----------------------------------------------------------------------------- -inline void MatrixTransformAxisAlignedPlane( const VMatrix &src, int nDim, float flSign, float flDist, cplane_t &outPlane ) -{ - // See MatrixTransformPlane in the .cpp file for an explanation of the algorithm. - MatrixGetColumn( src, nDim, &outPlane.normal ); - outPlane.normal *= flSign; - outPlane.dist = flDist * DotProduct( outPlane.normal, outPlane.normal ); - - // NOTE: Writing this out by hand because it doesn't inline (inline depth isn't large enough) - // This should read outPlane.dist += DotProduct( outPlane.normal, src.GetTranslation ); - outPlane.dist += outPlane.normal.x * src.m[0][3] + outPlane.normal.y * src.m[1][3] + outPlane.normal.z * src.m[2][3]; -} - - -//----------------------------------------------------------------------------- -// Matrix equality test -//----------------------------------------------------------------------------- -inline bool MatricesAreEqual( const VMatrix &src1, const VMatrix &src2, float flTolerance ) -{ - for ( int i = 0; i < 3; ++i ) - { - for ( int j = 0; j < 3; ++j ) - { - if ( fabs( src1[i][j] - src2[i][j] ) > flTolerance ) - return false; - } - } - return true; -} - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -void MatrixBuildOrtho( VMatrix& dst, double left, double top, double right, double bottom, double zNear, double zFar ); -void MatrixBuildPerspectiveX( VMatrix& dst, double flFovX, double flAspect, double flZNear, double flZFar ); -void MatrixBuildPerspectiveOffCenterX( VMatrix& dst, double flFovX, double flAspect, double flZNear, double flZFar, double bottom, double top, double left, double right ); - -inline void MatrixOrtho( VMatrix& dst, double left, double top, double right, double bottom, double zNear, double zFar ) -{ - VMatrix mat; - MatrixBuildOrtho( mat, left, top, right, bottom, zNear, zFar ); - - VMatrix temp; - MatrixMultiply( dst, mat, temp ); - dst = temp; -} - -inline void MatrixPerspectiveX( VMatrix& dst, double flFovX, double flAspect, double flZNear, double flZFar ) -{ - VMatrix mat; - MatrixBuildPerspectiveX( mat, flFovX, flAspect, flZNear, flZFar ); - - VMatrix temp; - MatrixMultiply( dst, mat, temp ); - dst = temp; -} - -inline void MatrixPerspectiveOffCenterX( VMatrix& dst, double flFovX, double flAspect, double flZNear, double flZFar, double bottom, double top, double left, double right ) -{ - VMatrix mat; - MatrixBuildPerspectiveOffCenterX( mat, flFovX, flAspect, flZNear, flZFar, bottom, top, left, right ); - - VMatrix temp; - MatrixMultiply( dst, mat, temp ); - dst = temp; -} - -#endif - - diff --git a/public/mathlib/vplane.h b/public/mathlib/vplane.h deleted file mode 100644 index 16cf8c2aa..000000000 --- a/public/mathlib/vplane.h +++ /dev/null @@ -1,182 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef VPLANE_H -#define VPLANE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "mathlib/vector.h" - -typedef int SideType; - -// Used to represent sides of things like planes. -#define SIDE_FRONT 0 -#define SIDE_BACK 1 -#define SIDE_ON 2 - -#define VP_EPSILON 0.01f - - -class VPlane -{ -public: - VPlane(); - VPlane(const Vector &vNormal, vec_t dist); - - void Init(const Vector &vNormal, vec_t dist); - - // Return the distance from the point to the plane. - vec_t DistTo(const Vector &vVec) const; - - // Copy. - VPlane& operator=(const VPlane &thePlane); - - // Returns SIDE_ON, SIDE_FRONT, or SIDE_BACK. - // The epsilon for SIDE_ON can be passed in. - SideType GetPointSide(const Vector &vPoint, vec_t sideEpsilon=VP_EPSILON) const; - - // Returns SIDE_FRONT or SIDE_BACK. - SideType GetPointSideExact(const Vector &vPoint) const; - - // Classify the box with respect to the plane. - // Returns SIDE_ON, SIDE_FRONT, or SIDE_BACK - SideType BoxOnPlaneSide(const Vector &vMin, const Vector &vMax) const; - -#ifndef VECTOR_NO_SLOW_OPERATIONS - // Flip the plane. - VPlane Flip(); - - // Get a point on the plane (normal*dist). - Vector GetPointOnPlane() const; - - // Snap the specified point to the plane (along the plane's normal). - Vector SnapPointToPlane(const Vector &vPoint) const; -#endif - -public: - Vector m_Normal; - vec_t m_Dist; - -#ifdef VECTOR_NO_SLOW_OPERATIONS -private: - // No copy constructors allowed if we're in optimal mode - VPlane(const VPlane& vOther); -#endif -}; - - -//----------------------------------------------------------------------------- -// Inlines. -//----------------------------------------------------------------------------- -inline VPlane::VPlane() -{ -} - -inline VPlane::VPlane(const Vector &vNormal, vec_t dist) -{ - m_Normal = vNormal; - m_Dist = dist; -} - -inline void VPlane::Init(const Vector &vNormal, vec_t dist) -{ - m_Normal = vNormal; - m_Dist = dist; -} - -inline vec_t VPlane::DistTo(const Vector &vVec) const -{ - return vVec.Dot(m_Normal) - m_Dist; -} - -inline VPlane& VPlane::operator=(const VPlane &thePlane) -{ - m_Normal = thePlane.m_Normal; - m_Dist = thePlane.m_Dist; - return *this; -} - -#ifndef VECTOR_NO_SLOW_OPERATIONS - -inline VPlane VPlane::Flip() -{ - return VPlane(-m_Normal, -m_Dist); -} - -inline Vector VPlane::GetPointOnPlane() const -{ - return m_Normal * m_Dist; -} - -inline Vector VPlane::SnapPointToPlane(const Vector &vPoint) const -{ - return vPoint - m_Normal * DistTo(vPoint); -} - -#endif - -inline SideType VPlane::GetPointSide(const Vector &vPoint, vec_t sideEpsilon) const -{ - vec_t fDist; - - fDist = DistTo(vPoint); - if(fDist >= sideEpsilon) - return SIDE_FRONT; - else if(fDist <= -sideEpsilon) - return SIDE_BACK; - else - return SIDE_ON; -} - -inline SideType VPlane::GetPointSideExact(const Vector &vPoint) const -{ - return DistTo(vPoint) > 0.0f ? SIDE_FRONT : SIDE_BACK; -} - - -// BUGBUG: This should either simply use the implementation in mathlib or cease to exist. -// mathlib implementation is much more efficient. Check to see that VPlane isn't used in -// performance critical code. -inline SideType VPlane::BoxOnPlaneSide(const Vector &vMin, const Vector &vMax) const -{ - int i, firstSide, side; - TableVector vPoints[8] = - { - { vMin.x, vMin.y, vMin.z }, - { vMin.x, vMin.y, vMax.z }, - { vMin.x, vMax.y, vMax.z }, - { vMin.x, vMax.y, vMin.z }, - - { vMax.x, vMin.y, vMin.z }, - { vMax.x, vMin.y, vMax.z }, - { vMax.x, vMax.y, vMax.z }, - { vMax.x, vMax.y, vMin.z }, - }; - - firstSide = GetPointSideExact(vPoints[0]); - for(i=1; i < 8; i++) - { - side = GetPointSideExact(vPoints[i]); - - // Does the box cross the plane? - if(side != firstSide) - return SIDE_ON; - } - - // Ok, they're all on the same side, return that. - return firstSide; -} - - - - -#endif // VPLANE_H diff --git a/public/matsys_controls/QCGenerator.h b/public/matsys_controls/QCGenerator.h deleted file mode 100644 index 723793edf..000000000 --- a/public/matsys_controls/QCGenerator.h +++ /dev/null @@ -1,155 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef QCGENERATOR_H -#define QCGENERATOR_H -#ifdef _WIN32 -#pragma once -#endif - -#include "vgui_controls/EditablePanel.h" -#include "vgui_controls/Frame.h" -#include "vgui_controls/Button.h" -#include "tier1/utlstring.h" -#include "vgui_controls/TextEntry.h" - -class CQCGenerator; - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -namespace vgui -{ - class Panel; -} - -class CBrowseButton : public vgui::Button -{ - DECLARE_CLASS_SIMPLE( CBrowseButton, vgui::Button ); - -public: - CBrowseButton( vgui::Panel *pParent ); - ~CBrowseButton(); - void InitBrowseInfo( int x, int y, char *pszName, const char *pszDir, char *pszFilter, char *pszField ); - -private: - char *pszStartingDirectory; - char *pszFileFilter; - char *pszTargetField; - - char **GetStartingDirectory(){ return &pszStartingDirectory; } - char **GetFileFilter(){ return &pszFileFilter; } - char **GetTargetField(){ return &pszTargetField; } - void SetCharVar( char **pVar, const char *pszNewText ); - void SetActionMessage(); -}; - -struct LODInfo -{ - char pszFilename[MAX_PATH]; - int iLOD; -}; - -struct QCInfo -{ - CQCGenerator *pQCGenerator; - - char pszSMDPath[MAX_PATH]; - char pszCollisionPath[MAX_PATH]; - char pszSurfaceProperty[MAX_PATH]; - char pszMaterialPath[MAX_PATH]; - char pszSceneName[MAX_PATH]; - - bool bStaticProp; - bool bMostlyOpaque; - bool bDisableCollision; - bool bReferenceAsPhys; - bool bConcave; - bool bAutomass; - bool bNoAnimation; - - CUtlVector LODs; - - float fScale; - float fMass; - void Init( CQCGenerator *pPanel ) - { - pQCGenerator = pPanel; - - Q_strcpy( pszSMDPath, "" ); - Q_strcpy( pszCollisionPath, "" ); - Q_strcpy( pszSurfaceProperty, "default" ); - bStaticProp = false; - bMostlyOpaque = false; - bDisableCollision = false; - bReferenceAsPhys = false; - bConcave = false; - bAutomass = false; - bNoAnimation = true; - - fScale = 1.0; - fMass = 10.0; - } - void SyncToControls(); - void SyncFromControls(); -}; - -//----------------------------------------------------------------------------- -// Purpose: Base class for generating QC files -//----------------------------------------------------------------------------- -class CQCGenerator : public vgui::EditablePanel -{ - DECLARE_CLASS_SIMPLE( CQCGenerator, vgui::EditablePanel ); - -public: - CQCGenerator( vgui::Panel *pParent, const char *pszPath, const char *pszScene ); - ~CQCGenerator(); - - // overridden frame functions -// virtual void Activate(); - - virtual void OnCommand( const char *command ); - - // Purpose: -// virtual void OnKeyCodeTyped( vgui::KeyCode code ); - - MESSAGE_FUNC( OnNewLODText, "TextNewLine" ); - MESSAGE_FUNC_PARAMS( OnBrowse, "browse", data ); - MESSAGE_FUNC_PARAMS( OnFileSelected, "FileSelected", data ); - MESSAGE_FUNC_PARAMS( OnDirectorySelected, "DirectorySelected", data ); - - bool GenerateQCFile(); -// void BrowseDirectory( KeyValues *data ); - void BrowseFile( KeyValues *data ); - - void DeleteLOD( ); - void EditLOD(); - virtual void OnKeyCodeTyped( vgui::KeyCode code); - void InitializeSMDPaths( const char *pszPath, const char *pszScene ); - -protected: - // Creates standard controls. Allows the derived class to - // add these controls to various splitter windows - void CreateStandardControls( vgui::Panel *pParent ); - -private: - - CBrowseButton *m_pCollisionBrowseButton; - char m_szTargetField[MAX_PATH]; - vgui::ListPanel *m_pLODPanel; - - vgui::TextEntry *m_pLODEdit; - - int m_nSelectedSequence; - int m_nSelectedColumn; - - QCInfo m_QCInfo_t; -}; - - - - -#endif // QCGENERATOR_H diff --git a/public/matsys_controls/assetpicker.h b/public/matsys_controls/assetpicker.h deleted file mode 100644 index 9baae50a0..000000000 --- a/public/matsys_controls/assetpicker.h +++ /dev/null @@ -1,51 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef ASSETPICKER_H -#define ASSETPICKER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "matsys_controls/BaseAssetPicker.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -namespace vgui -{ - class Panel; -} - - -//----------------------------------------------------------------------------- -// Purpose: Base class for choosing raw assets -//----------------------------------------------------------------------------- -class CAssetPicker : public CBaseAssetPicker -{ - DECLARE_CLASS_SIMPLE( CAssetPicker, CBaseAssetPicker ); - -public: - CAssetPicker( vgui::Panel *pParent, const char *pAssetType, - const char *pExt, const char *pSubDir, const char *pTextType ); -}; - - -//----------------------------------------------------------------------------- -// Purpose: Modal dialog for asset picker -//----------------------------------------------------------------------------- -class CAssetPickerFrame : public CBaseAssetPickerFrame -{ - DECLARE_CLASS_SIMPLE( CAssetPickerFrame, CBaseAssetPickerFrame ); - -public: - CAssetPickerFrame( vgui::Panel *pParent, const char *pTitle, - const char *pAssetType, const char *pExt, const char *pSubDir, const char *pTextType ); -}; - - -#endif // ASSETPICKER_H diff --git a/public/matsys_controls/baseassetpicker.h b/public/matsys_controls/baseassetpicker.h deleted file mode 100644 index 37b90bf8a..000000000 --- a/public/matsys_controls/baseassetpicker.h +++ /dev/null @@ -1,193 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef BASEASSETPICKER_H -#define BASEASSETPICKER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "vgui_controls/EditablePanel.h" -#include "vgui_controls/Frame.h" -#include "tier1/utlstring.h" -#include "tier1/utllinkedlist.h" -#include "filesystem.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class CAssetTreeView; -namespace vgui -{ - class Panel; -} -FORWARD_DECLARE_HANDLE( AssetList_t ); - -typedef unsigned short DirHandle_t; - - -//----------------------------------------------------------------------------- -// Purpose: Base class for choosing raw assets -//----------------------------------------------------------------------------- -class CBaseAssetPicker : public vgui::EditablePanel -{ - DECLARE_CLASS_SIMPLE( CBaseAssetPicker, vgui::EditablePanel ); - -public: - CBaseAssetPicker( vgui::Panel *pParent, const char *pAssetType, - const char *pExt, const char *pSubDir, const char *pTextType ); - ~CBaseAssetPicker(); - - // overridden frame functions - virtual void OnTick(); - virtual bool HasUserConfigSettings(); - virtual void ApplyUserConfigSettings( KeyValues *pUserConfig ); - virtual void GetUserConfigSettings( KeyValues *pUserConfig ); - virtual void OnCommand( const char *pCommand ); - - // Purpose: - virtual void OnKeyCodeTyped( vgui::KeyCode code ); - - // Returns the selected asset name - int GetSelectedAssetCount(); - const char *GetSelectedAsset( int nAssetIndex = -1 ); - - // Is multiselect enabled? - bool IsMultiselectEnabled() const; - - // Sets the initial selected asset - void SetInitialSelection( const char *pAssetName ); - - // Set/get the filter - void SetFilter( const char *pFilter ); - const char *GetFilter(); - - // Purpose: refreshes the file tree - void RefreshFileTree(); - - virtual void Activate(); - -protected: - // Creates standard controls. Allows the derived class to - // add these controls to various splitter windows - void CreateStandardControls( vgui::Panel *pParent, bool bAllowMultiselect = false ); - - // Allows the picker to browse multiple asset types - void AddExtension( const char *pExtension ); - - // Derived classes have this called when the previewed asset changes - virtual void OnSelectedAssetPicked( const char *pAssetName ) {} - - // Derived classes have this called when the next selected asset is selected by default - virtual void OnNextSelectionIsDefault() {} - - // Request focus of the filter box - void RequestFilterFocus(); - - // Rescan assets - void RescanAssets(); - - MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", kv ); - MESSAGE_FUNC_PARAMS( OnItemSelected, "ItemSelected", kv ); - MESSAGE_FUNC_PARAMS( OnCheckButtonChecked, "CheckButtonChecked", kv ); - MESSAGE_FUNC( OnFileSelected, "TreeViewItemSelected" ); - -private: - struct AssetInfo_t - { - int m_nAssetIndex; - int m_nItemId; - }; - - void BuildAssetNameList(); - void RefreshAssetList( ); - int GetSelectedAssetModIndex( ); - - // Is a particular asset visible? - bool IsAssetVisible( int nAssetIndex ); - - // Recursively add all files matching the wildcard under this directory - void AddAssetToList( int nAssetIndex ); - - // Update column headers - void UpdateAssetColumnHeader( ); - - vgui::Splitter *m_pAssetSplitter; - CAssetTreeView* m_pFileTree; - vgui::CheckButton* m_pSubDirCheck; - vgui::TextEntry *m_pFilter; - vgui::ListPanel *m_pAssetBrowser; - vgui::TextEntry *m_pFullPath; - vgui::ComboBox *m_pModSelector; - vgui::Button *m_pRescanButton; - - AssetList_t m_hAssetList; - CUtlString m_FolderFilter; - CUtlString m_Filter; - CUtlString m_SelectedAsset; - CUtlVector< AssetInfo_t > m_AssetList; - const char *m_pAssetType; - const char *m_pAssetTextType; - const char *m_pAssetExt; - const char *m_pAssetSubDir; - CUtlVector< const char * > m_ExtraAssetExt; - bool m_bBuiltAssetList : 1; - bool m_bFirstAssetScan : 1; - bool m_bFinishedAssetListScan : 1; - int m_nCurrentModFilter; - int m_nMatchingAssets; - bool m_bSubDirCheck; - - friend class CBaseAssetPickerFrame; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Modal dialog for asset picker -//----------------------------------------------------------------------------- -class CBaseAssetPickerFrame : public vgui::Frame -{ - DECLARE_CLASS_SIMPLE( CBaseAssetPickerFrame, vgui::Frame ); - -public: - CBaseAssetPickerFrame( vgui::Panel *pParent ); - ~CBaseAssetPickerFrame(); - - // Inherited from Frame - virtual void OnCommand( const char *pCommand ); - - // Purpose: Activate the dialog - // The message "AssetSelected" will be sent if an asset is picked - // Pass in optional keyvalues to add to the message - void DoModal( KeyValues *pContextKeyValues = NULL ); - - // Sets the initial selected asset - void SetInitialSelection( const char *pAssetName ); - - // Set/get the filter - void SetFilter( const char *pFilter ); - const char *GetFilter(); - -protected: - // Allows the derived class to create the picker - void SetAssetPicker( CBaseAssetPicker* pPicker ); - CBaseAssetPicker* GetAssetPicker() { return m_pPicker; } - - // Posts a message (passing the key values) - void PostMessageAndClose( KeyValues *pKeyValues ); - -private: - void CleanUpMessage(); - - CBaseAssetPicker *m_pPicker; - vgui::Button *m_pOpenButton; - vgui::Button *m_pCancelButton; - KeyValues *m_pContextKeyValues; -}; - - -#endif // BASEASSETPICKER_H diff --git a/public/matsys_controls/colorpickerpanel.h b/public/matsys_controls/colorpickerpanel.h deleted file mode 100644 index 1414112ec..000000000 --- a/public/matsys_controls/colorpickerpanel.h +++ /dev/null @@ -1,162 +0,0 @@ -//====== Copyright 1996-2003, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef COLORPICKERPANEL_H -#define COLORPICKERPANEL_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "vgui_controls/editablepanel.h" -#include "vgui_controls/frame.h" -#include "vgui_controls/button.h" -#include "bitmap/imageformat.h" -#include "mathlib/vector.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class CColorXYPreview; -class CColorZPreview; - -namespace vgui -{ - class RadioButton; - class TextEntry; - class IScheme; -} - - -//----------------------------------------------------------------------------- -// -// Color picker panel -// -//----------------------------------------------------------------------------- -class CColorPickerPanel : public vgui::EditablePanel -{ - DECLARE_CLASS_SIMPLE( CColorPickerPanel, vgui::EditablePanel ); - -public: - // constructor - CColorPickerPanel( vgui::Panel *pParent, const char *pName ); - void SetInitialColor( Color initialColor ); - void GetCurrentColor( Color *pColor ); - void GetInitialColor( Color *pColor ); - - // Inherited from Panel - virtual void ApplySchemeSettings( vgui::IScheme *pScheme ); - virtual void OnMousePressed( vgui::MouseCode code ); - -private: - MESSAGE_FUNC_PARAMS( OnRadioButtonChecked, "RadioButtonChecked", kv ); - MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", data ); - MESSAGE_FUNC_PARAMS( OnHSVSelected, "HSVSelected", data ); - MESSAGE_FUNC_PARAMS( OnColorSelected, "ColorSelected", data ); - - // Called when the color changes - void OnColorChanged( vgui::TextEntry *pChanged = NULL ); - - // Updates the preview colors - void UpdatePreviewColors(); - - CColorXYPreview *m_pColorXYPreview; - CColorZPreview *m_pColorZPreview; - vgui::RadioButton* m_pHueRadio; - vgui::RadioButton* m_pSaturationRadio; - vgui::RadioButton* m_pValueRadio; - vgui::RadioButton* m_pRedRadio; - vgui::RadioButton* m_pGreenRadio; - vgui::RadioButton* m_pBlueRadio; - vgui::TextEntry* m_pHueText; - vgui::TextEntry* m_pSaturationText; - vgui::TextEntry* m_pValueText; - vgui::TextEntry* m_pRedText; - vgui::TextEntry* m_pGreenText; - vgui::TextEntry* m_pBlueText; - vgui::Panel* m_pInitialColor; - vgui::Panel* m_pCurrentColor; - vgui::TextEntry* m_pAlphaText; - - RGB888_t m_InitialColor; - RGB888_t m_CurrentColor; - unsigned char m_InitialAlpha; - unsigned char m_CurrentAlpha; - Vector m_CurrentHSVColor; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Modal dialog for picker -//----------------------------------------------------------------------------- -class CColorPickerFrame : public vgui::Frame -{ - DECLARE_CLASS_SIMPLE( CColorPickerFrame, vgui::Frame ); - -public: - CColorPickerFrame( vgui::Panel *pParent, const char *pTitle ); - ~CColorPickerFrame(); - - // Inherited from Frame - virtual void OnCommand( const char *pCommand ); - - // Purpose: Activate the dialog - // If a color is picked, the message 'ColorPickerPicked' is sent with the "color" field set to the color - // If cancel is hit, the message 'ColorPickerCancel' is sent - // If the color is changed in the preview, the message 'ColorPickerPreview' is sent with the "color" field set to the color - void DoModal( Color initialColor, KeyValues *pContextKeys = NULL ); - - // Gets the initial color - void GetInitialColor( Color *pColor ); - -private: - void CleanUpMessage(); - - CColorPickerPanel *m_pPicker; - vgui::Button *m_pOpenButton; - vgui::Button *m_pCancelButton; - KeyValues *m_pContextKeys; -}; - - -//----------------------------------------------------------------------------- -// Purpose: A button which brings up the color picker -//----------------------------------------------------------------------------- -class CColorPickerButton : public vgui::Button -{ - DECLARE_CLASS_SIMPLE( CColorPickerButton, vgui::Button ); - - /* - NOTE: Sends ColorPickerPicked message when a color is picked - color - picked color - Sends ColorPickerPreview message when a color is previewed - color - current preview color - Sends ColorPickerCancelled message when the cancel button was hit - startingColor - color before the picking occurred - */ - -public: - CColorPickerButton( vgui::Panel *pParent, const char *pName, vgui::Panel *pActionSignalTarget = NULL ); - ~CColorPickerButton(); - - virtual void ApplySchemeSettings( vgui::IScheme *pScheme ); - virtual void DoClick(); - - void SetColor( const Color& clr ); - void SetColor( int r, int g, int b, int a ); - -private: - MESSAGE_FUNC_PARAMS( OnPicked, "ColorPickerPicked", data ); - MESSAGE_FUNC_PARAMS( OnPreview, "ColorPickerPreview", data ); - MESSAGE_FUNC( OnCancelled, "ColorPickerCancel" ); - - void UpdateButtonColor(); - Color m_CurrentColor; -}; - -#endif // COLORPICKERPANEL_H \ No newline at end of file diff --git a/public/matsys_controls/curveeditorpanel.h b/public/matsys_controls/curveeditorpanel.h deleted file mode 100644 index dbf962aa4..000000000 --- a/public/matsys_controls/curveeditorpanel.h +++ /dev/null @@ -1,67 +0,0 @@ -//====== Copyright 1996-2003, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef CURVEEDITORPANEL_H -#define CURVEEDITORPANEL_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "vgui_controls/Panel.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -struct BGRA8888_t; - - -//----------------------------------------------------------------------------- -// -// Curve editor image panel -// -//----------------------------------------------------------------------------- -class CCurveEditorPanel : public vgui::Panel -{ - DECLARE_CLASS_SIMPLE( CCurveEditorPanel, vgui::Panel ); - -public: - // constructor - CCurveEditorPanel( vgui::Panel *pParent, const char *pName ); - ~CCurveEditorPanel(); - - virtual void Paint( void ); - virtual void PaintBackground( void ); - - virtual void OnCursorMoved( int x,int y ); - virtual void OnMousePressed( vgui::MouseCode code ); - virtual void OnMouseReleased( vgui::MouseCode code ); - virtual void OnKeyCodePressed( vgui::KeyCode code ); - -protected: - // Control points + values... - virtual int FindOrAddControlPoint( float flIn, float flTolerance, float flOut ) = 0; - virtual int FindControlPoint( float flIn, float flTolerance ) = 0; - virtual int ModifyControlPoint( int nPoint, float flIn, float flOut ) = 0; - virtual void RemoveControlPoint( int nPoint ) = 0; - virtual float GetValue( float flIn ) = 0; - virtual int ControlPointCount() = 0; - virtual void GetControlPoint( int nPoint, float *pIn, float *pOut ) = 0; - -private: - // Converts screen location to normalized values and back - void ScreenToValue( int x, int y, float *pIn, float *pOut ); - void ValueToScreen( float flIn, float flOut, int *x, int *y ); - - int m_nSelectedPoint; - int m_nHighlightedPoint; // Used when not selecting -}; - - - -#endif // CURVEEDITORPANEL_H diff --git a/public/matsys_controls/gamefiletreeview.h b/public/matsys_controls/gamefiletreeview.h deleted file mode 100644 index 5e57e72b6..000000000 --- a/public/matsys_controls/gamefiletreeview.h +++ /dev/null @@ -1,81 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef GAMEFILETREEVIEW_H -#define GAMEFILETREEVIEW_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "tier1/utlstring.h" -#include "vgui_controls/treeview.h" -#include "vgui_controls/ImageList.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -namespace vgui -{ - class IScheme; -} - - -//----------------------------------------------------------------------------- -// Purpose: Handles file view for game files -//----------------------------------------------------------------------------- -class CGameFileTreeView : public vgui::TreeView -{ - DECLARE_CLASS_SIMPLE( CGameFileTreeView, vgui::TreeView ); - -public: - CGameFileTreeView( vgui::Panel *parent, const char *name, const char *pRootFolderName, const char *pRootDir, const char *pExtension = NULL ); - - // Inherited from base classes - virtual void GenerateChildrenOfNode( int itemIndex ); - virtual void GenerateContextMenu( int itemIndex, int x, int y ); - virtual void ApplySchemeSettings( vgui::IScheme *pScheme ); - - // Purpose: Refreshes the active file list - void RefreshFileList(); - - // Sets an item to be colored as if its a menu - void SetItemColorForDirectories( int itemID ); - - // Gets the number of root directories - int GetRootDirectoryCount(); - - // Gets the ith root directory - const char *GetRootDirectory( int nIndex ); - - // Selects the root folder - void SelectRoot(); - -private: - // Populate the root node (necessary since tree view can't have multiple roots) - void PopulateRootNode( int itemIndex ); - - // Populate the root node with directories - void AddDirectoriesOfNode( int itemIndex, const char *pFilePath ); - - // Populate the root node with directories - bool DoesDirectoryHaveSubdirectories( const char *pFilePath ); - - // Populate the root node with files - void AddFilesOfNode( int itemIndex, const char *pFilePath, const char *pExt ); - - CUtlString m_RootDir; - CUtlString m_Ext; - CUtlString m_RootFolderName; - vgui::ImageList m_Images; - bool m_bUseExt; // To differentiate "" from NULL in m_Ext -}; - - -#endif // GAMEFILETREEVIEW_H - diff --git a/public/matsys_controls/manipulator.h b/public/matsys_controls/manipulator.h deleted file mode 100644 index e2bfab974..000000000 --- a/public/matsys_controls/manipulator.h +++ /dev/null @@ -1,128 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef MANIPULATOR_H -#define MANIPULATOR_H -#ifdef _WIN32 -#pragma once -#endif - -#include "vgui_controls/Panel.h" -#include "mathlib/Vector.h" - -//----------------------------------------------------------------------------- -// Manipulator interface -//----------------------------------------------------------------------------- -class IManipulator -{ -public: - virtual void OnBeginManipulation( void ) = 0; - virtual void OnAcceptManipulation( void ) = 0; - virtual void OnCancelManipulation( void ) = 0; - - virtual void OnTick( void ) = 0; - - virtual void OnCursorMoved( int x, int y ) = 0; - virtual void OnMousePressed( vgui::MouseCode code, int x, int y ) = 0; - virtual void OnMouseReleased( vgui::MouseCode code, int x, int y ) = 0; - virtual void OnMouseWheeled( int delta ) = 0; - - virtual void SetViewportSize( int w, int h ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Base class helper for implementing manipulators -//----------------------------------------------------------------------------- -class CBaseManipulator : public IManipulator -{ -public: - CBaseManipulator() - { - m_nViewport[ 0 ] = m_nViewport[ 1 ] = 0; - } - - virtual void OnTick( void ) {}; - - virtual void OnBeginManipulation( void ) {} - virtual void OnAcceptManipulation( void ) {}; - virtual void OnCancelManipulation( void ) {}; - - virtual void OnCursorMoved( int x, int y ) {}; - virtual void OnMousePressed( vgui::MouseCode code, int x, int y ) {}; - virtual void OnMouseReleased( vgui::MouseCode code, int x, int y ) {}; - virtual void OnMouseWheeled( int delta ) {}; - - virtual void SetViewportSize( int w, int h ) - { - m_nViewport[ 0 ] = w; - m_nViewport[ 1 ] = h; - } - -protected: - int m_nViewport[ 2 ]; -}; - - -//----------------------------------------------------------------------------- -// Base class for manipulators which operate on transforms -//----------------------------------------------------------------------------- -class CTransformManipulator : public CBaseManipulator -{ -public: - CTransformManipulator( matrix3x4_t *pTransform ); - - void SetTransform( matrix3x4_t *transform ); - matrix3x4_t *GetTransform(); - -protected: - matrix3x4_t *m_pTransform; -}; - - -//----------------------------------------------------------------------------- -// Standard maya-like transform manipulator -//----------------------------------------------------------------------------- -class CPotteryWheelManip : public CTransformManipulator -{ -public: - CPotteryWheelManip( matrix3x4_t *pTransform ); - - virtual void OnBeginManipulation( void ); - virtual void OnAcceptManipulation( void ); - virtual void OnCancelManipulation( void ); - - virtual void OnTick( void ); - - virtual void OnCursorMoved( int x, int y ); - virtual void OnMousePressed( vgui::MouseCode code, int x, int y ); - virtual void OnMouseReleased( vgui::MouseCode code, int x, int y ); - virtual void OnMouseWheeled( int delta ); - - // Sets the zoom level - void SetZoom( float flZoom ); - -protected: - int m_lastx, m_lasty; - - float m_zoom; - float m_altitude, m_azimuth; - //vec3 m_lookat - - float m_prevZoom; - float m_prevAltitude, m_prevAzimuth; - - float m_flLastMouseTime; - float m_flLastTickTime; - float m_flSpin; - bool m_bSpin; - - void UpdateTransform( void ); - void UpdateZoom( float delta ); -}; - - -#endif // MANIPULATOR_H diff --git a/public/matsys_controls/matsyscontrols.h b/public/matsys_controls/matsyscontrols.h deleted file mode 100644 index 1f16187ab..000000000 --- a/public/matsys_controls/matsyscontrols.h +++ /dev/null @@ -1,72 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef MATSYSCONTROLS_H -#define MATSYSCONTROLS_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/interface.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class IMaterialSystem; -class IMaterialSystemHardwareConfig; -class IMDLCache; -class IMatSystemSurface; -class IStudioRender; - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// handles the initialization of the vgui interfaces. -// NOTE: Calls into VGui_InitInterfacesList -// interfaces (listed below) are first attempted to be loaded from primaryProvider, then secondaryProvider -// moduleName should be the name of the module that this instance of the vgui_controls has been compiled into -//----------------------------------------------------------------------------- -bool VGui_InitMatSysInterfacesList( const char *moduleName, CreateInterfaceFn *factoryList, int numFactories ); - - -//----------------------------------------------------------------------------- -// set of accessor functions to matsys interfaces -// the appropriate header file for each is listed above the item -//----------------------------------------------------------------------------- - -// #include -IMaterialSystem *MaterialSystem(); - -// #include -IMDLCache *MDLCache(); - -// #include -IMatSystemSurface *MatSystemSurface(); - -// #include -IMaterialSystemHardwareConfig *MaterialSystemHardwareConfig(); - -} // end namespace vgui - - -//----------------------------------------------------------------------------- -// predeclare all the matsys control class names -//----------------------------------------------------------------------------- -class CMDLPanel; -class CMDLSequencePicker; -class CMDLPicker; -class CSequencePicker; -class CGameFileTreeView; - - -#endif // MATSYSCONTROLS_H diff --git a/public/matsys_controls/mdlpanel.h b/public/matsys_controls/mdlpanel.h deleted file mode 100644 index d82c55cae..000000000 --- a/public/matsys_controls/mdlpanel.h +++ /dev/null @@ -1,107 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef MDLPANEL_H -#define MDLPANEL_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "vgui_controls/Panel.h" -#include "datacache/imdlcache.h" -#include "materialsystem/materialsystemutil.h" -#include "matsys_controls/potterywheelpanel.h" -#include "tier3/mdlutils.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -namespace vgui -{ - class IScheme; -} - - -//----------------------------------------------------------------------------- -// MDL Viewer Panel -//----------------------------------------------------------------------------- -class CMDLPanel : public CPotteryWheelPanel -{ - DECLARE_CLASS_SIMPLE( CMDLPanel, CPotteryWheelPanel ); - -public: - // constructor, destructor - CMDLPanel( vgui::Panel *pParent, const char *pName ); - virtual ~CMDLPanel(); - - // Overriden methods of vgui::Panel - virtual void ApplySchemeSettings( vgui::IScheme *pScheme ); - - virtual void OnTick(); - - // Sets the current mdl - virtual void SetMDL( MDLHandle_t handle ); - virtual void SetMDL( const char *pMDLName ); - - // Sets the camera to look at the model - void LookAtMDL( ); - - // Sets the current sequence - void SetSequence( int nSequence ); - - void SetCollsionModel( bool bVisible ); - void SetGroundGrid( bool bVisible ); - void SetWireFrame( bool bVisible ); - void SetLockView( bool bLocked ); - void SetSkin( int nSkin ); - void SetLookAtCamera( bool bLookAtCamera ); - - // Bounds. - bool GetBoundingBox( Vector &vecBoundsMin, Vector &vecBoundsMax ); - bool GetBoundingSphere( Vector &vecCenter, float &flRadius ); - - void SetModelAnglesAndPosition( const QAngle &angRot, const Vector &vecPos ); - - // Attached models. - void SetMergeMDL( MDLHandle_t handle ); - void SetMergeMDL( const char *pMDLName ); - int GetMergeMDLIndex( MDLHandle_t handle ); - void ClearMergeMDLs( void ); - -protected: - - struct MDLData_t - { - CMDL m_MDL; - matrix3x4_t m_MDLToWorld; - }; - - MDLData_t m_RootMDL; - CUtlVector m_aMergeMDLs; - -private: - // paint it! - void OnPaint3D(); - void OnMouseDoublePressed( vgui::MouseCode code ); - - void DrawCollisionModel(); - void UpdateStudioRenderConfig( void ); - - CTextureReference m_DefaultEnvCubemap; - CTextureReference m_DefaultHDREnvCubemap; - - bool m_bDrawCollisionModel : 1; - bool m_bGroundGrid : 1; - bool m_bLockView : 1; - bool m_bWireFrame : 1; - bool m_bLookAtCamera : 1; -}; - - -#endif // MDLPANEL_H diff --git a/public/matsys_controls/mdlpicker.h b/public/matsys_controls/mdlpicker.h deleted file mode 100644 index bdcc1b29c..000000000 --- a/public/matsys_controls/mdlpicker.h +++ /dev/null @@ -1,139 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef MDLPICKER_H -#define MDLPICKER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/utlstring.h" -#include "vgui_controls/Frame.h" -#include "matsys_controls/baseassetpicker.h" -#include "datacache/imdlcache.h" - - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -namespace vgui -{ - class Splitter; -} - -class CMDLPanel; - - -//----------------------------------------------------------------------------- -// Purpose: Main app window -//----------------------------------------------------------------------------- -class CMDLPicker : public CBaseAssetPicker -{ - DECLARE_CLASS_SIMPLE( CMDLPicker, CBaseAssetPicker ); - -public: - - enum PageType_t - { - PAGE_NONE = 0, - PAGE_RENDER = 0x1, - PAGE_SEQUENCES = 0x2, - PAGE_ACTIVITIES = 0x4, - PAGE_SKINS = 0x8, - PAGE_INFO = 0x10, - PAGE_ALL = 0xFFFFFFFF, - }; - - CMDLPicker( vgui::Panel *pParent, int nFlags = PAGE_ALL ); - ~CMDLPicker(); - - // overridden frame functions - virtual void PerformLayout(); - virtual void OnCommand( const char *pCommand ); - - // Get current model - void GetSelectedMDLName( char *pBuffer, int nMaxLen ); - - // get current selected options page - int GetSelectedPage(); - - // Allows external apps to select a MDL - void SelectMDL( const char *pRelativePath ); - - // Set/Get Sequence - void SelectSequence( const char *pSequenceName ); - const char *GetSelectedSequenceName(); - - // Set/Get Activity - void SelectActivity( const char *pActivityName ); - const char *GetSelectedActivityName(); - - void SelectSkin( int nSkin ); - int GetSelectedSkin(); - -private: - MESSAGE_FUNC_PARAMS( OnAssetSelected, "AssetSelected", params ); - - virtual void OnSelectedAssetPicked( const char *pMDLName ); - - void RefreshActivitiesAndSequencesList(); - void RefreshRenderSettings(); - int UpdateSkinsList(); - void UpdateInfoTab(); - int UpdatePropDataList( const char* pszPropData, bool &bIsStatic ); - - // Plays the selected activity - void PlaySelectedActivity( ); - - // Plays the selected sequence - void PlaySelectedSequence( ); - - MESSAGE_FUNC_PARAMS( OnCheckButtonChecked, "CheckButtonChecked", kv ); - MESSAGE_FUNC_PARAMS( OnItemSelected, "ItemSelected", kv ); - MESSAGE_FUNC( OnPageChanged, "PageChanged" ); - - CMDLPanel *m_pMDLPreview; - vgui::Splitter* m_pFileBrowserSplitter; - vgui::Splitter* m_pPreviewSplitter; - - vgui::PropertySheet *m_pViewsSheet; - vgui::PropertyPage *m_pRenderPage; - vgui::PropertyPage *m_pSequencesPage; - vgui::PropertyPage *m_pActivitiesPage; - vgui::PropertyPage *m_pSkinsPage; - vgui::PropertyPage *m_pInfoPage; - - vgui::ListPanel *m_pSequencesList; - vgui::ListPanel *m_pActivitiesList; - vgui::ListPanel *m_pSkinsList; - vgui::ListPanel *m_pPropDataList; - - MDLHandle_t m_hSelectedMDL; - - int m_nFlags; - - friend class CMDLPickerFrame; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Main app window -//----------------------------------------------------------------------------- -class CMDLPickerFrame : public CBaseAssetPickerFrame -{ - DECLARE_CLASS_SIMPLE( CMDLPickerFrame, CBaseAssetPickerFrame ); - -public: - CMDLPickerFrame( vgui::Panel *pParent, const char *pTitle, int nFlags = CMDLPicker::PAGE_ALL ); - virtual ~CMDLPickerFrame(); - - // Allows external apps to select a MDL - void SelectMDL( const char *pRelativePath ); -}; - - -#endif // MDLPICKER_H diff --git a/public/matsys_controls/mdlsequencepicker.h b/public/matsys_controls/mdlsequencepicker.h deleted file mode 100644 index aa62906ef..000000000 --- a/public/matsys_controls/mdlsequencepicker.h +++ /dev/null @@ -1,116 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef MDLSEQUENCEPICKER_H -#define MDLSEQUENCEPICKER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "vgui_controls/ImageList.h" -#include "vgui_controls/Frame.h" -#include "datacache/imdlcache.h" -#include "matsys_controls/mdlpanel.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -namespace vgui -{ - class Splitter; - class Button; -} - -class CGameFileTreeView; - - -//----------------------------------------------------------------------------- -// Purpose: Main app window -//----------------------------------------------------------------------------- -class CMDLSequencePicker : public vgui::EditablePanel -{ - DECLARE_CLASS_SIMPLE( CMDLSequencePicker, vgui::EditablePanel ); -public: - CMDLSequencePicker( vgui::Panel *pParent ); - virtual ~CMDLSequencePicker(); - - // overridden frame functions - virtual void Activate(); - virtual void OnClose(); - virtual void PerformLayout(); - virtual void OnTick(); - - char const *GetModelName(); - char const *GetSequenceName(); - int GetSequenceNumber(); - -private: - void SelectMDL( const char *pMDLName ); - void RefreshFileList(); - void RefreshActivitiesAndSequencesList(); - - // Plays the selected activity - void PlaySelectedActivity( ); - - // Plays the selected sequence - void PlaySelectedSequence( ); - - MESSAGE_FUNC( OnFileSelected, "TreeViewItemSelected" ); - MESSAGE_FUNC_PTR_CHARPTR( OnTextChanged, "TextChanged", Panel, text ); - MESSAGE_FUNC_PARAMS( OnItemSelected, "ItemSelected", kv ); - MESSAGE_FUNC( OnPageChanged, "PageChanged" ); - - // changes -// MESSAGE_FUNC_INT( CloakFolder, "CloakFolder", item ); -// MESSAGE_FUNC_INT( OpenFileForEdit, "EditFile", item ); -// MESSAGE_FUNC_INT( OpenFileForDelete, "DeleteFile", item ); - - CMDLPanel *m_pMDLPreview; - vgui::ComboBox *m_pFilterList; - CGameFileTreeView *m_pFileTree; - vgui::ImageList m_Images; - vgui::Splitter* m_pMDLSplitter; - vgui::Splitter* m_pSequenceSplitter; - vgui::PropertySheet *m_pViewsSheet; - vgui::PropertyPage *m_pSequencesPage; - vgui::PropertyPage *m_pActivitiesPage; - - vgui::ListPanel *m_pSequencesList; - vgui::ListPanel *m_pActivitiesList; - - MDLHandle_t m_hSelectedMDL; - - friend class CMDLSequencePickerFrame; -}; - -//----------------------------------------------------------------------------- -// Model sequence picker frame -//----------------------------------------------------------------------------- -class CMDLSequencePickerFrame : public vgui::Frame -{ - DECLARE_CLASS_SIMPLE( CMDLSequencePickerFrame, vgui::Frame ); -public: - CMDLSequencePickerFrame( vgui::Panel *parent, char const *title ); - virtual ~CMDLSequencePickerFrame(); - - virtual void PerformLayout(); - -protected: - - virtual void OnTick(); - - MESSAGE_FUNC( OnOK, "OnOK" ); - MESSAGE_FUNC( OnCancel, "OnCancel" ); - -private: - CMDLSequencePicker *m_pMDLSequencePicker; - - vgui::Button *m_pOK; - vgui::Button *m_pCancel; -}; - -#endif // MDLSEQUENCEPICKER_H diff --git a/public/matsys_controls/picker.h b/public/matsys_controls/picker.h deleted file mode 100644 index 9361b05a8..000000000 --- a/public/matsys_controls/picker.h +++ /dev/null @@ -1,133 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: An arbitrary picker -// -//============================================================================= - -#ifndef PICKER_H -#define PICKER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "vgui_controls/EditablePanel.h" -#include "vgui_controls/Frame.h" -#include "tier1/utlstring.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -namespace vgui -{ - class Panel; -} - - -//----------------------------------------------------------------------------- -// List of strings to appear in the picker -//----------------------------------------------------------------------------- -enum PickerChoiceType_t -{ - PICKER_CHOICE_STRING = 0, - PICKER_CHOICE_PTR, -}; - -struct PickerInfo_t -{ - const char *m_pChoiceString; // This is what displays in the dialog - union - { - const char *m_pChoiceValue; - void *m_pChoiceValuePtr; - }; -}; - -struct PickerList_t -{ - PickerList_t() : m_Type( PICKER_CHOICE_STRING ) {} - PickerList_t( int nGrowSize, int nInitSize ) : m_Choices( nGrowSize, nInitSize ), m_Type( PICKER_CHOICE_STRING ) {} - - int Count() const { return m_Choices.Count(); } - PickerInfo_t& operator[]( int i ) { return m_Choices[i]; } - const PickerInfo_t& operator[]( int i ) const { return m_Choices[i]; } - int AddToTail() { return m_Choices.AddToTail(); } - void RemoveAll() { return m_Choices.RemoveAll(); } - - PickerChoiceType_t m_Type; - CUtlVector< PickerInfo_t > m_Choices; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Base class for choosing raw assets -//----------------------------------------------------------------------------- -class CPicker : public vgui::EditablePanel -{ - DECLARE_CLASS_SIMPLE( CPicker, vgui::EditablePanel ); - -public: - CPicker( vgui::Panel *pParent, const char *pColumnHeader, const char *pTextType ); - ~CPicker(); - - // Sets the list of strings to display - void SetStringList( const PickerList_t &list ); - - // Purpose: - virtual void OnKeyCodeTyped( vgui::KeyCode code ); - - // Returns the selected string - PickerChoiceType_t GetSelectionType() const; - const char *GetSelectedString( ) const; - void *GetSelectedPtr( ) const; - - // Returns the index of the selected string - int GetSelectedIndex(); - -private: - void RefreshChoiceList( ); - MESSAGE_FUNC( OnTextChanged, "TextChanged" ); - - vgui::TextEntry *m_pFilterList; - vgui::ListPanel *m_pPickerBrowser; - CUtlString m_Filter; - const char *m_pPickerType; - const char *m_pPickerTextType; - const char *m_pPickerExt; - const char *m_pPickerSubDir; - PickerChoiceType_t m_Type; - - friend class CPickerFrame; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Modal dialog for picker -//----------------------------------------------------------------------------- -class CPickerFrame : public vgui::Frame -{ - DECLARE_CLASS_SIMPLE( CPickerFrame, vgui::Frame ); - -public: - CPickerFrame( vgui::Panel *pParent, const char *pTitle, const char *pColumnHeader, const char *pTextType ); - ~CPickerFrame(); - - // Inherited from Frame - virtual void OnCommand( const char *pCommand ); - - // Purpose: Activate the dialog - // The message "Picked" will be sent if something is picked. - // You can pass in keyvalues to get added to the message also. - void DoModal( const PickerList_t &list, KeyValues *pContextKeyValues = NULL ); - -private: - void CleanUpMessage(); - - CPicker *m_pPicker; - vgui::Button *m_pOpenButton; - vgui::Button *m_pCancelButton; - KeyValues *m_pContextKeyValues; -}; - - -#endif // PICKER_H diff --git a/public/matsys_controls/potterywheelpanel.h b/public/matsys_controls/potterywheelpanel.h deleted file mode 100644 index 636d15834..000000000 --- a/public/matsys_controls/potterywheelpanel.h +++ /dev/null @@ -1,155 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef POTTERYWHEELPANEL_H -#define POTTERYWHEELPANEL_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "vgui_controls/EditablePanel.h" -#include "materialsystem/materialsystemutil.h" -#include "tier2/camerautils.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class IManipulator; -class CPotteryWheelManip; -class CBaseManipulator; -class CTransformManipulator; -class CDmxElement; - -namespace vgui -{ - class IScheme; -} - - -//----------------------------------------------------------------------------- -// Pottery wheel Panel -//----------------------------------------------------------------------------- -class CPotteryWheelPanel : public vgui::EditablePanel -{ - DECLARE_CLASS_SIMPLE( CPotteryWheelPanel, vgui::EditablePanel ); - -public: - // constructor, destructor - CPotteryWheelPanel( vgui::Panel *pParent, const char *pName ); - virtual ~CPotteryWheelPanel(); - - // Overriden methods of vgui::Panel - virtual void Paint(); - - virtual void OnKeyCodePressed ( vgui::KeyCode code ); - virtual void OnKeyCodeReleased( vgui::KeyCode code ); - virtual void OnMousePressed ( vgui::MouseCode code ); - virtual void OnMouseReleased( vgui::MouseCode code ); - virtual void OnCursorMoved( int x, int y ); - virtual void OnMouseWheeled( int delta ); - virtual void OnTick(); - - virtual void OnMouseCaptureLost(); - - // Sets the camera to look at the the thing we're spinning around - void LookAt( const Vector &vecCenter, float flRadius ); - void LookAt( float flRadius ); - - void ComputePanelPosition( const Vector &vecPosition, Vector2D *pPanelPos ); - - void SetBackgroundColor( int r, int g, int b ); - void SetBackgroundColor( const Color& c ); - const Color& GetBackgroundColor() const; - - // Light probe - void SetLightProbe( CDmxElement *pLightProbe ); - - // Camera. - int GetCameraFOV( void ); - void SetCameraFOV( float flFOV ); - void SetCameraPositionAndAngles( const Vector &vecPos, const QAngle &angDir ); - void SetCameraOffset( const Vector &vecOffset ); - void ResetCameraPivot( void ); - void ComputeCameraTransform( matrix3x4_t *pWorldToCamera ); - void UpdateCameraTransform(); - -private: - // Inherited classes must implement this - virtual void OnPaint3D() = 0; - -protected: - - enum - { - MAX_LIGHT_COUNT = 4 - }; - - struct LightInfo_t - { - LightDesc_t m_Desc; - matrix3x4_t m_LightToWorld; - }; - - - - enum ManipulationMode_t - { - CAMERA_ROTATE, - CAMERA_TRANSLATE, - CAMERA_ZOOM, - LIGHT_MODE, - }; - - virtual void EnterManipulationMode( ManipulationMode_t manipMode, bool bMouseCapture = true, vgui::MouseCode mouseCode = vgui::MouseCode( -1 ) ); - void Select(); - void AcceptManipulation( bool bReleaseMouseCapture = true ); - void CancelManipulation(); - void EnableMouseCapture( bool enable, vgui::MouseCode code = vgui::MouseCode( -1 ) ); - bool WarpMouse( int &x, int &y ); - IManipulator *m_pCurrentManip; - int m_nManipStartX, m_nManipStartY; - - bool HasLightProbe() const; - ITexture *GetLightProbeCubemap( bool bHDR ); - void DrawGrid(); - CMaterialReference m_Wireframe; - -private: - void SetupRenderState( int nDisplayWidth, int nDisplayHeight ); - void CreateDefaultLights(); - void DestroyLights(); - - CMaterialReference m_LightProbeBackground; - CMaterialReference m_LightProbeHDRBackground; - CTextureReference m_LightProbeCubemap; - CTextureReference m_LightProbeHDRCubemap; - - Camera_t m_Camera; - matrix3x4_t m_CameraPivot; - int m_nLightCount; - LightInfo_t m_Lights[MAX_LIGHT_COUNT]; - Vector4D m_vecAmbientCube[6]; - - Color m_ClearColor; - Vector m_vecCameraOffset; - CTransformManipulator *m_pCameraRotate; - CTransformManipulator *m_pCameraTranslate; - CBaseManipulator *m_pCameraZoom; - CPotteryWheelManip *m_pLightManip; - vgui::MouseCode m_nCaptureMouseCode; - - int m_xoffset, m_yoffset; - - bool m_bHasLightProbe : 1; - - CPanelAnimationVar( bool, m_bUseParentBG, "useparentbg", "0" ); -}; - - -#endif // SIMPLEPOTTERYWHEELPANEL_H diff --git a/public/matsys_controls/proceduraltexturepanel.h b/public/matsys_controls/proceduraltexturepanel.h deleted file mode 100644 index d5a7bde4c..000000000 --- a/public/matsys_controls/proceduraltexturepanel.h +++ /dev/null @@ -1,92 +0,0 @@ -//====== Copyright 1996-2003, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef PROCEDURALTEXTUREPANEL_H -#define PROCEDURALTEXTUREPANEL_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "materialsystem/itexture.h" -#include "materialsystem/MaterialSystemUtil.h" -#include "vgui_controls/EditablePanel.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -struct BGRA8888_t; - - -//----------------------------------------------------------------------------- -// -// Procedural texture image panel -// -//----------------------------------------------------------------------------- -class CProceduralTexturePanel : public vgui::EditablePanel, public ITextureRegenerator -{ - DECLARE_CLASS_SIMPLE( CProceduralTexturePanel, vgui::EditablePanel ); - -public: - // constructor - CProceduralTexturePanel( vgui::Panel *pParent, const char *pName ); - ~CProceduralTexturePanel(); - - // Methods of ITextureRegenerator - virtual void Release() {} - virtual void RegenerateTextureBits( ITexture *pTexture, IVTFTexture *pVTFTexture, Rect_t *pRect ); - - // initialization, shutdown - virtual bool Init( int nWidth, int nHeight, bool bAllocateImageBuffer ); - virtual void Shutdown(); - - // Returns the image buffer + dimensions - BGRA8888_t *GetImageBuffer(); - int GetImageWidth() const; - int GetImageHeight() const; - - // Redownloads the procedural texture - void DownloadTexture(); - - // Sets the rectangle to paint. Use null to fill the entire panel - void SetPaintRect( const Rect_t *pPaintRect = NULL ); - - // Sets the texcoords to use with the procedural texture - void SetTextureSubRect( const Rect_t &subRect ); - - // Maintain proportions when drawing - void MaintainProportions( bool bEnable ); - - virtual void Paint( void ); - virtual void PaintBackground( void ) {} - -private: - void CleanUp(); - -protected: - // Image buffer - BGRA8888_t *m_pImageBuffer; - int m_nWidth; - int m_nHeight; - - // Paint rectangle - Rect_t m_PaintRect; - - // Texture coordinate rectangle - Rect_t m_TextureSubRect; - - CTextureReference m_ProceduralTexture; - CMaterialReference m_ProceduralMaterial; - - int m_nTextureID; - bool m_bMaintainProportions; - bool m_bUsePaintRect; -}; - - -#endif // PROCEDURALTEXTUREPANEL_H diff --git a/public/matsys_controls/sequencepicker.h b/public/matsys_controls/sequencepicker.h deleted file mode 100644 index a79ba98c4..000000000 --- a/public/matsys_controls/sequencepicker.h +++ /dev/null @@ -1,111 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef SEQUENCEPICKER_H -#define SEQUENCEPICKER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/utlstring.h" -#include "vgui_controls/Frame.h" -#include "vgui_controls/EditablePanel.h" -#include "vgui_controls/ImageList.h" -#include "datacache/imdlcache.h" -#include "matsys_controls/mdlpanel.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -namespace vgui -{ - class Splitter; -} - - -//----------------------------------------------------------------------------- -// Purpose: Sequence picker panel -//----------------------------------------------------------------------------- -class CSequencePicker : public vgui::EditablePanel -{ - DECLARE_CLASS_SIMPLE( CSequencePicker, vgui::EditablePanel ); - -public: - enum PickType_t - { - PICK_NONE = 0, - PICK_SEQUENCES = 0x1, - PICK_ACTIVITIES = 0x2, - PICK_ALL = 0xFFFFFFFF, - }; - - // Flags come from PickType_t - CSequencePicker( vgui::Panel *pParent, int nFlags = PICK_ALL ); - ~CSequencePicker(); - - // overridden frame functions - virtual void PerformLayout(); - - // Sets the MDL to preview sequences for - void SetMDL( const char *pMDLName ); - - // Gets the selected activity/sequence - PickType_t GetSelectedSequenceType(); - const char *GetSelectedSequenceName( ); - -private: - void RefreshActivitiesAndSequencesList(); - - // Plays the selected activity - void PlayActivity( const char *pActivityName ); - - // Plays the selected sequence - void PlaySequence( const char *pSequenceName ); - - MESSAGE_FUNC_PARAMS( OnItemSelected, "ItemSelected", kv ); - MESSAGE_FUNC( OnPageChanged, "PageChanged" ); - - CMDLPanel *m_pMDLPreview; - vgui::Splitter* m_pPreviewSplitter; - vgui::PropertySheet *m_pViewsSheet; - vgui::PropertyPage *m_pSequencesPage; - vgui::PropertyPage *m_pActivitiesPage; - vgui::ListPanel *m_pSequencesList; - vgui::ListPanel *m_pActivitiesList; - MDLHandle_t m_hSelectedMDL; - CUtlString m_Filter; - - friend class CSequencePickerFrame; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Main app window -//----------------------------------------------------------------------------- -class CSequencePickerFrame : public vgui::Frame -{ - DECLARE_CLASS_SIMPLE( CSequencePickerFrame, vgui::Frame ); - -public: - CSequencePickerFrame( vgui::Panel *pParent, int nFlags ); - - // Inherited from Frame - virtual void OnCommand( const char *pCommand ); - - // Purpose: Activate the dialog - void DoModal( const char *pMDLName ); - -private: - MESSAGE_FUNC_PARAMS( OnSequencePreviewChanged, "SequencePreviewChanged", kv ); - - CSequencePicker *m_pPicker; - vgui::Button *m_pOpenButton; - vgui::Button *m_pCancelButton; -}; - - -#endif // SEQUENCEPICKER_H diff --git a/public/matsys_controls/tgapreviewpanel.h b/public/matsys_controls/tgapreviewpanel.h deleted file mode 100644 index fbb5d6a9a..000000000 --- a/public/matsys_controls/tgapreviewpanel.h +++ /dev/null @@ -1,39 +0,0 @@ -//====== Copyright 1996-2003, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef TGAPREVIEWPANEL_H -#define TGAPREVIEWPANEL_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "matsys_controls/proceduraltexturepanel.h" -#include "tier1/utlstring.h" - - -//----------------------------------------------------------------------------- -// -// TGA Preview panel -// -//----------------------------------------------------------------------------- -class CTGAPreviewPanel : public CProceduralTexturePanel -{ - DECLARE_CLASS_SIMPLE( CTGAPreviewPanel, CProceduralTexturePanel ); - -public: - // constructor - CTGAPreviewPanel( vgui::Panel *pParent, const char *pName ); - void SetTGA( const char *pFullPath ); - const char *GetTGA() const; - -private: - CUtlString m_TGAName; -}; - - -#endif // TGAPREVIEWPANEL_H \ No newline at end of file diff --git a/public/matsys_controls/vmtpanel.h b/public/matsys_controls/vmtpanel.h deleted file mode 100644 index 1e69b92ef..000000000 --- a/public/matsys_controls/vmtpanel.h +++ /dev/null @@ -1,91 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef VMTPANEL_H -#define VMTPANEL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "matsys_controls/PotteryWheelPanel.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class IMaterial; -class CMeshBuilder; -class Vector; - -namespace vgui -{ - class ScrollBar; - class IScheme; -} - - -//----------------------------------------------------------------------------- -// Material Viewer Panel -//----------------------------------------------------------------------------- -class CVMTPanel : public CPotteryWheelPanel -{ - DECLARE_CLASS_SIMPLE( CVMTPanel, CPotteryWheelPanel ); - -public: - // constructor, destructor - CVMTPanel( vgui::Panel *pParent, const char *pName ); - virtual ~CVMTPanel(); - - // Set the material to draw - void SetMaterial( IMaterial *pMaterial ); - - // Set rendering mode (stretch to full screen, or use actual size) - void RenderUsingActualSize( bool bEnable ); - - // performs the layout - virtual void PerformLayout(); - - virtual void ApplySchemeSettings( vgui::IScheme *pScheme ); - -private: - // paint it stretched to the window size - void DrawStretchedToPanel( CMeshBuilder &meshBuilder ); - - // paint it actual size - void DrawActualSize( CMeshBuilder &meshBuilder ); - - // Draw it on a sphere - void RenderSphere( const Vector &vCenter, float flRadius, int nTheta, int nPhi ); - - // paint it! - virtual void OnPaint3D(); - -private: - // The material to draw - IMaterial *m_pMaterial; - - // A texture to use for a lightmap - CTextureReference m_pLightmapTexture; - - // The default env_cubemap - CTextureReference m_DefaultEnvCubemap; - - // Are we using actual size or not? - bool m_bUseActualSize; - - // Scroll bars - vgui::ScrollBar *m_pHorizontalBar; - vgui::ScrollBar *m_pVerticalBar; - - // The viewable size - int m_iViewableWidth; - int m_iViewableHeight; -}; - -#endif // VMTPANEL_H - \ No newline at end of file diff --git a/public/matsys_controls/vmtpicker.h b/public/matsys_controls/vmtpicker.h deleted file mode 100644 index 227b31b88..000000000 --- a/public/matsys_controls/vmtpicker.h +++ /dev/null @@ -1,61 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef VMTPICKER_H -#define VMTPICKER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "matsys_controls/BaseAssetPicker.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class CVMTPreviewPanel; - -namespace vgui -{ - class Splitter; -} - - -//----------------------------------------------------------------------------- -// Purpose: Base class for choosing raw assets -//----------------------------------------------------------------------------- -class CVMTPicker : public CBaseAssetPicker -{ - DECLARE_CLASS_SIMPLE( CVMTPicker, CBaseAssetPicker ); - -public: - CVMTPicker( vgui::Panel *pParent, bool bAllowMultiselect = false ); - virtual ~CVMTPicker(); - -private: - // Derived classes have this called when the previewed asset changes - virtual void OnSelectedAssetPicked( const char *pAssetName ); - - CVMTPreviewPanel *m_pVMTPreview2D; - CVMTPreviewPanel *m_pVMTPreview3D; - vgui::Splitter *m_p2D3DSplitter; - vgui::Splitter *m_pPreviewSplitter; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Modal dialog for asset picker -//----------------------------------------------------------------------------- -class CVMTPickerFrame : public CBaseAssetPickerFrame -{ - DECLARE_CLASS_SIMPLE( CVMTPickerFrame, CBaseAssetPickerFrame ); - -public: - CVMTPickerFrame( vgui::Panel *pParent, const char *pTitle, bool bAllowMultiselect = false ); -}; - - -#endif // VMTPICKER_H diff --git a/public/matsys_controls/vmtpreviewpanel.h b/public/matsys_controls/vmtpreviewpanel.h deleted file mode 100644 index 4ad7d9260..000000000 --- a/public/matsys_controls/vmtpreviewpanel.h +++ /dev/null @@ -1,81 +0,0 @@ -//====== Copyright 1996-2003, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef VMTPREVIEWPANEL_H -#define VMTPREVIEWPANEL_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "vgui_controls/panel.h" -#include "tier1/utlstring.h" -#include "materialsystem/materialsystemutil.h" -#include "mathlib/vector.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -// -// VMT Preview panel -// -//----------------------------------------------------------------------------- -class CVMTPreviewPanel : public vgui::Panel -{ - DECLARE_CLASS_SIMPLE( CVMTPreviewPanel, vgui::Panel ); - -public: - // constructor - CVMTPreviewPanel( vgui::Panel *pParent, const char *pName ); - void SetVMT( const char *pMaterialName ); - const char *GetVMT() const; - - // Paints the texture - virtual void Paint( void ); - - // View it in 3D or 2D mode - void DrawIn3DMode( bool b3DMode ); - -private: - // Two different preview methods - void DrawSphere( void ); - void DrawRectangle( void ); - - // Set up a projection matrix for a 90 degree fov - void SetupProjectionMatrix( int nWidth, int nHeight ); - void SetupOrthoMatrix( int nWidth, int nHeight ); - - // Sets the camera to look at the the thing we're spinning around - void LookAt( const Vector &vecLookAt, float flRadius ); - - // Sets up lighting state - void SetupLightingState(); - - // Draw a sphere - void RenderSphere( const Vector &vCenter, float flRadius, int nTheta, int nPhi ); - - // Draw sprite-card based materials - void RenderSpriteCard( const Vector &vCenter, float flRadius ); - - CUtlString m_VMTName; - CMaterialReference m_Material; - CTextureReference m_pLightmapTexture; - CTextureReference m_DefaultEnvCubemap; - Vector m_LightDirection; - Color m_LightColor; - float m_flLightIntensity; - Vector m_vecCameraDirection; - float m_flLastRotationTime; - bool m_bDrawIn3DMode; -}; - - -#endif // VMTPREVIEWPANEL_H \ No newline at end of file diff --git a/public/matsys_controls/vtfpicker.h b/public/matsys_controls/vtfpicker.h deleted file mode 100644 index c1a77cc47..000000000 --- a/public/matsys_controls/vtfpicker.h +++ /dev/null @@ -1,59 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef VTFPICKER_H -#define VTFPICKER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "matsys_controls/BaseAssetPicker.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class CVTFPreviewPanel; - -namespace vgui -{ - class Splitter; -} - - -//----------------------------------------------------------------------------- -// Purpose: Base class for choosing raw assets -//----------------------------------------------------------------------------- -class CVTFPicker : public CBaseAssetPicker -{ - DECLARE_CLASS_SIMPLE( CVTFPicker, CBaseAssetPicker ); - -public: - CVTFPicker( vgui::Panel *pParent ); - virtual ~CVTFPicker(); - -private: - // Derived classes have this called when the previewed asset changes - virtual void OnSelectedAssetPicked( const char *pAssetName ); - - CVTFPreviewPanel *m_pVTFPreview; - vgui::Splitter *m_pPreviewSplitter; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Modal dialog for asset picker -//----------------------------------------------------------------------------- -class CVTFPickerFrame : public CBaseAssetPickerFrame -{ - DECLARE_CLASS_SIMPLE( CVTFPickerFrame, CBaseAssetPickerFrame ); - -public: - CVTFPickerFrame( vgui::Panel *pParent, const char *pTitle ); -}; - - -#endif // VTFPICKER_H diff --git a/public/matsys_controls/vtfpreviewpanel.h b/public/matsys_controls/vtfpreviewpanel.h deleted file mode 100644 index b48972a57..000000000 --- a/public/matsys_controls/vtfpreviewpanel.h +++ /dev/null @@ -1,68 +0,0 @@ -//====== Copyright 1996-2003, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef VTFPREVIEWPANEL_H -#define VTFPREVIEWPANEL_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "vgui_controls/panel.h" -#include "tier1/utlstring.h" -#include "materialsystem/materialsystemutil.h" -#include "mathlib/vector.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- -// -// VTF Preview panel -// -//----------------------------------------------------------------------------- -class CVTFPreviewPanel : public vgui::Panel -{ - DECLARE_CLASS_SIMPLE( CVTFPreviewPanel, vgui::Panel ); - -public: - // constructor - CVTFPreviewPanel( vgui::Panel *pParent, const char *pName ); - void SetVTF( const char *pFullPath, bool bLoadImmediately = true ); - const char *GetVTF() const; - - // Paints the texture - virtual void Paint( void ); - -private: - void PaintNormalMapTexture( void ); - void PaintCubeTexture( void ); - void PaintStandardTexture( void ); - void PaintVolumeTexture( void ); - - // Set up a projection matrix for a 90 degree fov - void SetupProjectionMatrix( int nWidth, int nHeight ); - - // Sets the camera to look at the the thing we're spinning around - void LookAt( const Vector &vecLookAt, float flRadius ); - - // Draw a sphere - void RenderSphere( const Vector &vCenter, float flRadius, int nTheta, int nPhi ); - - CUtlString m_VTFName; - CTextureReference m_PreviewTexture; - CMaterialReference m_PreviewMaterial; - int m_nTextureID; - Vector m_vecCameraDirection; - float m_flLastRotationTime; -}; - - -#endif // VTFPREVIEWPANEL_H \ No newline at end of file diff --git a/public/maya/IMayaVGui.h b/public/maya/IMayaVGui.h deleted file mode 100644 index 4267dc2f1..000000000 --- a/public/maya/IMayaVGui.h +++ /dev/null @@ -1,62 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: Interface for dealing with vgui focus issues across all plugins -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef IMAYAVGUI_H -#define IMAYAVGUI_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "tier0/platform.h" -#include "appframework/iappsystem.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -namespace vgui -{ - class EditablePanel; -} - - -//----------------------------------------------------------------------------- -// Factory for creating vgui windows -//----------------------------------------------------------------------------- -abstract_class IMayaVguiWindowFactory -{ -public: - virtual void CreateVguiWindow( const char *pPanelName ) = 0; - virtual void DestroyVguiWindow( const char *pPanelName ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Interface for dealing with vgui focus issues across all plugins -//----------------------------------------------------------------------------- -#define MAYA_VGUI_INTERFACE_VERSION "VMayaVGui001" -abstract_class IMayaVGui : public IAppSystem -{ -public: - virtual void InstallVguiWindowFactory( const char *pWindowTypeName, IMayaVguiWindowFactory *pFactory ) = 0; - virtual void RemoveVguiWindowFactory( const char *pWindowTypeName, IMayaVguiWindowFactory *pFactory ) = 0; - virtual void SetFocus( void *hWnd, int hVGuiContext ) = 0; - virtual bool HasFocus( void *hWnd ) = 0; - - // In this mode, maya's in a strange re-entrant mode waiting for a modal dialog - // We still get WM_PAINT messages, but we're in the middle of a callstack - // deep in the bowels of VGUI - virtual void SetModalMode( bool bEnable ) = 0; - virtual bool IsInModalMode( ) const = 0; -}; - -extern IMayaVGui* g_pMayaVGui; - - -#endif // IMAYAVGUI_H diff --git a/public/maya/ValveMaya/HyperShadeUtil.h b/public/maya/ValveMaya/HyperShadeUtil.h deleted file mode 100644 index cc6fa2002..000000000 --- a/public/maya/ValveMaya/HyperShadeUtil.h +++ /dev/null @@ -1,46 +0,0 @@ -//======= Copyright 1996-2007, Valve Corporation, All rights reserved. ====== -// -// Purpose: Utils for working with HyperShade in Maya -// -//============================================================================= - - -// Maya includes -#include - - -// Valve includes -#include "valveMaya/Undo.h" - - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -namespace ValveMaya -{ - - class CHyperShadeUtil - { - public: - CHyperShadeUtil(); - - CHyperShadeUtil( CUndo &undo ); - - MStatus AddUtility( const MObject &utilityNode ); - - MStatus AddShader( const MObject &shaderNode ); - - MStatus AddTexture( const MObject &textureNode ); - - protected: - CUndo m_tmpUndo; - CUndo &m_undo; - - MObject m_renderUtilityListObj; - MObject m_shaderListObj; - MObject m_textureListObj; - - void Init(); - }; - -} \ No newline at end of file diff --git a/public/maya/ValveMaya/Undo.h b/public/maya/ValveMaya/Undo.h deleted file mode 100644 index 5e5e51cfc..000000000 --- a/public/maya/ValveMaya/Undo.h +++ /dev/null @@ -1,327 +0,0 @@ -//======= Copyright 1996-2006, Valve Corporation, All rights reserved. ====== -// -// Maya Undo helper, use it like this -// -// class CMyCmd : MPxCommand -// { -// // ... regular stuff ... // -// -// ValveMaya::CUndo m_undo; -// }; -// -// MStatus CMyCmd::doIt( const MArgList &mArgList ) -// { -// m_undo.SetArgList( Syntax(), mArgList ); -// } -// -// MStatus CMyCmd::redoIt( const MArgList &mArgList ) -// { -// // Get at command line args -// m_undo.ArgDatabase().isFlagSet( ... ); -// -// // Do operations -// m_undo.SaveCurrentSelection(); -// m_undo.DagModifier().createNode( ... ); -// m_undo.DagModifierDoIt(); -// m_undo.SetAttr( mPlug, value ); -// -// /// etc ... -// } -// -// MStatus CMyCmd::undoIt( const MArgList &mArgList ) -// { -// m_undo.Undo(); -// } -// -// bool CMyCmd::isUndoable() -// { -// return m_undo.IsUndoable(); -// } -// -// If there's a need to get fancy, any of the CUndoOp* classes can be -// constructed via 'new' and a boost::shared_ptr< CUndoOp > constructed -// with that pointed can be passed to CUndo::Push(). Note that means -// that the pointer will be managed by boost::shared_ptr so if the -// lifetime of the data needs to be controlled by the caller (it shouldn't) -// then a shared_ptr should be kept -// -// Setting the ArgList and using ArgDatabase doesn't affect the undo/redo -// ability but it's a convnient place to keep that data -// -//============================================================================= - -#ifndef VALVEMAYA_UNDO_H -#define VALVEMAYA_UNDO_H -#if defined( _WIN32 ) -#pragma once -#endif - - -// Standard includes - - -// Maya includes -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -// Valve includes -#include "tier1/utlstack.h" - - -namespace ValveMaya -{ - -// Forward declarations -class CUndoOp; - - -//============================================================================= -// -// -// CUndo: Undo stack manager class -// -// -//============================================================================= - -class CUndo -{ -public: - CUndo(); - - ~CUndo(); - - void Clear(); - - MStatus SetArgList( - const MSyntax &mSyntax, - const MArgList &mArgList ); - - const MArgDatabase &ArgDatabase(); - - void SaveCurrentSelection(); - - MDagModifier &DagModifier(); - - MStatus DagModifierDoIt(); - - MStatus Connect( - const MPlug &srcP, - const MPlug &dstP, - bool force = false ); - - bool SetAttr( - MPlug &mPlug, - MObject &val ); - - bool SetAttr( - MPlug &mPlug, - double val ); - - bool Lock( - MPlug &mPlug, - bool lock ); - - void NodeCreated( MObject &nodeObject ); - - void Push( - CUndoOp *pUndoOp ); - - bool IsUndoable() const; - - MStatus Undo(); - -protected: - MArgDatabase *m_pArgDatabase; - CUtlStack< CUndoOp * > m_undoStack; -}; - - -//============================================================================= -// -// -// CUndoOp: Undo stack member abstract base class -// -// -//============================================================================= -class CUndoOp -{ -public: - virtual ~CUndoOp() - { - } - - virtual void Undo() = 0; -}; - - -//============================================================================= -// -// -// CUndoOpDagModifier: Undo stack member Dag Modifier class -// -// -//============================================================================= -class CUndoOpDagModifier : public CUndoOp -{ -public: - virtual ~CUndoOpDagModifier() - { - } - - virtual void Undo() - { - m_mDagModifier.undoIt(); - } - -protected: - friend class CUndo; - - MDagModifier m_mDagModifier; -}; - - -//============================================================================= -// -// -// CUndoOpSetAttr: Undo stack member for setting attributes -// -// -//============================================================================= -class CUndoOpSetAttr : public CUndoOp -{ -public: - CUndoOpSetAttr( - MPlug &mPlug, - MObject &mObjectVal ); - - CUndoOpSetAttr( - MPlug &mPlug, - double numericVal ); - - virtual ~CUndoOpSetAttr() - { - } - - virtual void Undo(); - -protected: - MPlug m_mPlug; - MObject m_mObjectVal; - double m_numericVal; - const bool m_numeric; - -private: - // Visual C++ is retarded - tell it there's no assignment operator - CUndoOpSetAttr &operator=( const CUndoOpSetAttr &rhs ); - -}; - - -//============================================================================= -// -// -// CUndoOpSelection: Undo stack member for changing selection -// -// -//============================================================================= -class CUndoOpSelection : public CUndoOp -{ -public: - CUndoOpSelection(); - - virtual ~CUndoOpSelection() - { - } - - virtual void Undo(); - -protected: - MSelectionList m_mSelectionList; - -}; - - -//============================================================================= -// -// -// CUndoOpSelection: Undo stack member for locking and unlocking attributes -// -// -//============================================================================= -class CUndoOpLock : public CUndoOp -{ -public: - - CUndoOpLock( - MPlug &mPlug, - bool lock ); - - virtual ~CUndoOpLock() - { - } - - virtual void Undo(); - -protected: - MPlug m_mPlug; - const bool m_locked; - -private: - // Visual C++ is retarded - tell it there's no assignment operator - CUndoOpLock &operator=( const CUndoOpLock &rhs ); -}; - - -//============================================================================= -// -//============================================================================= -class CUndoOpResetRestPosition : public CUndoOp -{ -public: - CUndoOpResetRestPosition( - const MDagPath &mDagPath ); - - virtual ~CUndoOpResetRestPosition() - { - } - - virtual void Undo(); - -protected: - const MDagPath m_mDagPath; - MTransformationMatrix m_matrix; -}; - - -//============================================================================= -// For node creation via something like MFnMesh::create, etc.. -//============================================================================= -class CUndoOpNodeCreated : public CUndoOp -{ -public: - CUndoOpNodeCreated( - MObject &mObject ); - - virtual ~CUndoOpNodeCreated() - { - } - - virtual void Undo(); - -protected: - MObject m_nodeObject; -}; - - -} -#endif // VALVEMAYA_UNDO_H diff --git a/public/maya/VsMayaDmx.h b/public/maya/VsMayaDmx.h deleted file mode 100644 index 139c79b1c..000000000 --- a/public/maya/VsMayaDmx.h +++ /dev/null @@ -1,30 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef VSMAYADMX_H -#define VSMAYADMX_H - -#ifdef _WIN32 -#pragma once -#endif - -// Maya includes - -#include - -// Valve includes - -#include "movieobjects/dmemesh.h" - -class VsMayaDmx -{ - static CDmeMesh *MayaMeshToDmeMesh( - const MDagPath &i_mDagPath, - DmFileId_t fileId ); - -}; - -#endif // VSMAYADMX_H diff --git a/public/maya/VsMayaMPxFactory.h b/public/maya/VsMayaMPxFactory.h deleted file mode 100644 index 8c1d214b0..000000000 --- a/public/maya/VsMayaMPxFactory.h +++ /dev/null @@ -1,954 +0,0 @@ -//======= Copyright 1996-2006, Valve Corporation, All rights reserved. ====== -// -// Purpose: Utility classes for creating, registering & deregistering -// Maya MPx* derived classes -// -//============================================================================= - -#ifndef VSMAYAMPXFACTORY_H -#define VSMAYAMPXFACTORY_H -#if defined( _WIN32 ) -#pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if MAYA_API_VERSION >= 200800 -#include -#endif //MAYA_API_VERSION >= 200800 - -//----------------------------------------------------------------------------- -// -// Forward declarations -// -//----------------------------------------------------------------------------- -class MFnPlugin; -namespace ValveMaya -{ - class CMSyntaxHelp; -} - - -//============================================================================= -// -// Base class for Maya MPx factories -// -//============================================================================= -class CVsMayaMPxFactoryBase -{ -public: - // Registers all MPx derived things that have been allocated - static MStatus RegisterEverything( MFnPlugin &pluginFn ); - - // Deregisters all MPx derived things that have been allocated - static MStatus DeregisterEverything( MFnPlugin &pluginFn ); - - // Displays a list of stuff in the plugin - static void DisplaySummary( const MString &pluginName ); - - // Types of things the MPxFactory can create - enum Type - { - // NOTE: Ensure this list of enums stays in sync with GetTypeName() array - kCommand, - kFileTranslator, - kDependencyNode, - kShaderNode, - kTransform, - kLocatorNode, - kImageFile, - // Insert new ones above here - kUnknown - }; - -protected: - // Constructor - CVsMayaMPxFactoryBase(); - -private: - // The next factory - CVsMayaMPxFactoryBase* m_pNextFactory; - - // The starting factory - static CVsMayaMPxFactoryBase *s_pFirstFactory; - - // Register the thing associated with this factory - virtual MStatus Register( MFnPlugin &pluginFn ) const = 0; - - // Deregister the thing associated with this factory - virtual MStatus Deregister( MFnPlugin &pluginFn ) const = 0; - - // Everything has a name - virtual const MString &GetName() const = 0; - - // Everything has a description - virtual const MString &GetDesc() const = 0; - - // Everything has a type - virtual Type GetType() const = 0; - - // Everything has a type (map types to names) - MString GetTypeName() const; -}; - - -//----------------------------------------------------------------------------- -// -// Templatized helpers for creating MPx derived classes -// -//----------------------------------------------------------------------------- -template< class T > -class CVsMayaMPxFactory : public CVsMayaMPxFactoryBase -{ -private: - // Register the thing associated with this factory - virtual MStatus Register( MFnPlugin &pluginFn ) const - { - return T::Register( pluginFn ); - } - - // Deregister the thing associated with this factory - virtual MStatus Deregister( MFnPlugin &pluginFn ) const - { - return T::Deregister( pluginFn ); - } - - virtual const MString &GetName() const - { - return T::s_name; - } - - virtual const MString &GetDesc() const - { - return T::s_desc; - } - - virtual Type GetType() const - { - return T::GetType(); - } -}; - - -//============================================================================ -// -// Base class for Valve Maya commands ( CVsMayaMPxCommand ) -// -//============================================================================ -class CVsMayaMPxCommand : public MPxCommand -{ -public: - virtual const MString &GetName() const { return m_nullStr; } - virtual const MString &GetDesc() const { return m_nullStr; } - -protected: - // Derived classes must specify this to override syntax - virtual void SpecifySyntax( MSyntax &mSyntax, ValveMaya::CMSyntaxHelp &help ); - ValveMaya::CMSyntaxHelp *GetSyntaxHelp() { return m_pSyntaxHelp; } - -private: - ValveMaya::CMSyntaxHelp *m_pSyntaxHelp; - - static MStatus Register( - MFnPlugin &pluginFn, - const MString &name, - MCreatorFunction creatorFunction, - MCreateSyntaxFunction createSyntaxFunction = NULL ); - - static MStatus Deregister( MFnPlugin &pluginFn, const MString &name ); - - template < class T > friend class CVsMayaMPxCommandDecorator; - - MString m_nullStr; -}; - - -//----------------------------------------------------------------------------- -// -// Decorator class for Valve Maya commands ( CVsMayaMPxCommandDecorator ) -// -//----------------------------------------------------------------------------- -template < class T > -class CVsMayaMPxCommandDecorator : public T -{ -public: - static const MString &Name() { return s_name; }; - static const MString &Desc() { return s_desc; }; - - virtual const MString &GetName() const { return Name(); }; - virtual const MString &GetDesc() const { return Desc(); }; - - static CVsMayaMPxFactoryBase::Type GetType() { return CVsMayaMPxFactoryBase::kCommand; } - -private: - friend class CVsMayaMPxFactoryBase; - template < class U > friend class CVsMayaMPxFactory; - - // These should be const but it's not because the CVsMayaMPxFactoryCommand class - // only knows its name and therefore it's description at runtime - - static MString s_name; - static MString s_desc; - static ValveMaya::CMSyntaxHelp s_mSyntaxHelp; // Keeps track of command line flags - - static void *Create() - { - CVsMayaMPxCommandDecorator *pDecorator = new CVsMayaMPxCommandDecorator< T >; - pDecorator->m_pSyntaxHelp = &s_mSyntaxHelp; - return pDecorator; - } - - static MSyntax CreateSyntax() - { - // Maya will simply never call this unless the 'hasSyntax()' virtual returns true - // doesn't matter if a syntaxCreator is registered or not, and an empty - // MSyntax is fine too. Also note the return is by value and not reference. - // Also... even when Maya does call this, it is only ever called once, the - // first time Maya needs to know what the syntax is (when the command is - // invoked or when help cmd is done - - MSyntax mSyntax; - T().SpecifySyntax( mSyntax, s_mSyntaxHelp ); - return mSyntax; - } - - static MStatus Register( MFnPlugin &pluginFn ) - { - return T::Register( pluginFn, s_name, Create, T().hasSyntax() ? CreateSyntax : NULL ); - } - - static MStatus Deregister( MFnPlugin &pluginFn ) - { - return T::Deregister( pluginFn, s_name ); - } -}; - - -//============================================================================= -// -// Base class for Valve Maya file translators ( CVsMayaMPxFileTranslator ) -// -//============================================================================= -class CVsMayaMPxFileTranslator : public MPxFileTranslator -{ -public: - virtual const MString &GetName() const = 0; - virtual const MString &GetGUIName() const = 0; - -protected: - static MStatus Register( - MFnPlugin &pluginFn, - const MString &name, - const MString &guiName, - MCreatorFunction creatorFunction ); - - static MStatus Deregister( - MFnPlugin &pluginFn, - const MString &name ); -}; - - -//----------------------------------------------------------------------------- -// -// Decorator class for Valve Maya file translators ( CVsMayaMPxFileTranslatorDecorator ) -// -//----------------------------------------------------------------------------- -template < class T > -class CVsMayaMPxFileTranslatorDecorator : public T -{ -public: - virtual const MString &GetName() const { return s_name; }; - - virtual const MString &GetGUIName() const { return s_guiName; }; - - virtual const MString &GetDesc() const { return s_desc; }; - - static CVsMayaMPxFactoryBase::Type GetType() { return CVsMayaMPxFactoryBase::kFileTranslator; } - -private: - template < class U > friend class CVsMayaMPxFactory; - - static const MString s_name; - - static const MString s_desc; - - static const MString s_guiName; - - static void *Create() - { - return new CVsMayaMPxFileTranslatorDecorator< T >; - } - - static MStatus Register( MFnPlugin &pluginFn ) - { - return T::Register( pluginFn, s_name, s_guiName, Create ); - } - - static MStatus Deregister( MFnPlugin &pluginFn ) - { - return T::Deregister( pluginFn, s_guiName ); - } -}; - - -//============================================================================= -// -// Base class for Valve Maya Dependency Nodes ( CVsMayaMPxNode ) -// -//============================================================================ -class CVsMayaMPxNode : public MPxNode -{ -public: - virtual const MString &GetName() const = 0; - -protected: - static MStatus Register( - MFnPlugin &pluginFn, - const MString &name, - const MTypeId &mTypeId, - MCreatorFunction creatorFunction, - MInitializeFunction initFunction, - const MString &classification ); - - static MStatus Deregister( - MFnPlugin &pluginFn, - const MTypeId &mTypeId ); -}; - - -//----------------------------------------------------------------------------- -// -// Decorator class for Valve Maya nodes ( CVsMayaMPxNodeDecorator ) -// -//----------------------------------------------------------------------------- -template < class T > -class CVsMayaMPxNodeDecorator : public T -{ -public: - static const MString &Name() { return s_name; }; - - virtual const MString &GetName() const { return Name(); }; - - virtual const MString &GetDesc() const { return s_desc; }; - - static CVsMayaMPxFactoryBase::Type GetType() - { - return s_classification.length() ? CVsMayaMPxFactoryBase::kShaderNode : CVsMayaMPxFactoryBase::kDependencyNode; - } - -private: - template < class U > friend class CVsMayaMPxFactory; - - static const MString s_name; - - static const MString s_desc; - - static const MTypeId s_mTypeId; - - static const MInitializeFunction s_mInitializeFunction; - - static const MString s_classification; - - static void *Create() - { - return new CVsMayaMPxNodeDecorator< T >; - } - - static MStatus Register( MFnPlugin &pluginFn ) - { - return T::Register( pluginFn, s_name, s_mTypeId, Create, s_mInitializeFunction, s_classification ); - } - - static MStatus Deregister( MFnPlugin &pluginFn ) - { - return T::Deregister( pluginFn, s_mTypeId ); - } -}; - - -//============================================================================= -// -// Base class for Valve Maya Transform Nodes ( CVsMayaMPxTransform ) -// -//============================================================================ -class CVsMayaMPxTransform : public MPxTransform -{ -public: - virtual const MString &GetName() const = 0; - -protected: - static MStatus Register( - MFnPlugin &pluginFn, - const MString &name, - const MTypeId &mTypeId, - MCreatorFunction creatorFunction, - MInitializeFunction initFunction, - MCreatorFunction xformCreatorFunction = MPxTransformationMatrix::creator, - const MTypeId &xformMTypeId = MPxTransformationMatrix::baseTransformationMatrixId, - const MString *classification = NULL ); - - static MStatus Deregister( - MFnPlugin &pluginFn, - const MTypeId &mTypeId ); -}; - - -//----------------------------------------------------------------------------- -// -// Decorator class for Valve Maya commands ( CVsMayaMPxCommandDecorator ) -// -//----------------------------------------------------------------------------- -template < class T > -class CVsMayaMPxTransformDecorator : public T -{ -public: - static const MString &Name() { return s_name; }; - - virtual const MString &GetName() const { return Name(); }; - - virtual const MString &GetDesc() const { return s_desc; }; - - static CVsMayaMPxFactoryBase::Type GetType() { return CVsMayaMPxFactoryBase::kTransform; } - -private: - template < class U > friend class CVsMayaMPxFactory; - - static const MString s_name; - - static const MString s_desc; - - static const MTypeId s_mTypeId; - - static const MInitializeFunction s_mInitializeFunction; - - static const MCreatorFunction s_xformMCreatorFunction; - - static const MTypeId s_xformMTypeId; - - static void *Create() - { - return new CVsMayaMPxTransformDecorator< T >; - } - - static MStatus Register( MFnPlugin &pluginFn ) - { - return T::Register( pluginFn, s_name, s_mTypeId, Create, s_mInitializeFunction, s_xformMCreatorFunction, s_xformMTypeId ); - } - - static MStatus Deregister( MFnPlugin &pluginFn ) - { - return T::Deregister( pluginFn, s_mTypeId ); - } -}; - - -//============================================================================= -// -// Base class for Valve Maya Locator Nodes ( CVsMayaMPxLocatorNode ) -// -//============================================================================ -class CVsMayaMPxLocatorNode : public MPxLocatorNode -{ -public: - virtual const MString &GetName() const = 0; - -protected: - static MStatus Register( - MFnPlugin &pluginFn, - const MString &name, - const MTypeId &mTypeId, - MCreatorFunction creatorFunction, - MInitializeFunction initFunction ); - - static MStatus Deregister( - MFnPlugin &pluginFn, - const MTypeId &mTypeId ); -}; - - -//----------------------------------------------------------------------------- -// -// Decorator class for Valve Maya nodes ( CVsMayaMPxLocatorNodeDecorator ) -// -//----------------------------------------------------------------------------- -template < class T > -class CVsMayaMPxLocatorNodeDecorator : public T -{ -public: - static const MString &Name() { return s_name; }; - - virtual const MString &GetName() const { return Name(); }; - - virtual const MString &GetDesc() const { return s_desc; }; - - static CVsMayaMPxFactoryBase::Type GetType() - { - return CVsMayaMPxFactoryBase::kLocatorNode; - } - -private: - template < class U > friend class CVsMayaMPxFactory; - - static const MString s_name; - - static const MString s_desc; - - static const MTypeId s_mTypeId; - - static const MInitializeFunction s_mInitializeFunction; - - static void *Create() - { - return new CVsMayaMPxLocatorNodeDecorator< T >; - } - - static MStatus Register( MFnPlugin &pluginFn ) - { - return T::Register( pluginFn, s_name, s_mTypeId, Create, s_mInitializeFunction ); - } - - static MStatus Deregister( MFnPlugin &pluginFn ) - { - return T::Deregister( pluginFn, s_mTypeId ); - } -}; - - -//============================================================================= -// -// Base class for Valve Maya Drag And Drop Behaviors ( CVsMayaMPxDragAndDropBehavior ) -// -//============================================================================ -class CVsMayaMPxDragAndDropBehavior : public MPxDragAndDropBehavior -{ -public: - virtual const MString &GetName() const = 0; - -protected: - static MStatus Register( - MFnPlugin &pluginFn, - const MString &name, - MCreatorFunction creatorFunction ); - - static MStatus Deregister( - MFnPlugin &pluginFn, - const MString &name ); -}; - - -//----------------------------------------------------------------------------- -// -// Decorator class for Valve Maya drag and drop behaviors ( CVsMayaMPxDragAndDropBehavior ) -// -//----------------------------------------------------------------------------- -template < class T > -class CVsMayaMPxDragAndDropBehaviorDecorator : public T -{ -public: - static const MString &Name() { return s_name; }; - - virtual const MString &GetName() const { return Name(); }; - - virtual const MString &GetDesc() const { return s_desc; }; - - static CVsMayaMPxFactoryBase::Type GetType() - { - return CVsMayaMPxFactoryBase::kLocatorNode; - } - -private: - template < class U > friend class CVsMayaMPxFactory; - - static const MString s_name; - - static const MString s_desc; - - static const MInitializeFunction s_mInitializeFunction; - - static void *Create() - { - return new CVsMayaMPxDragAndDropBehaviorDecorator< T >; - } - - static MStatus Register( MFnPlugin &pluginFn ) - { - return T::Register( pluginFn, s_name, Create ); - } - - static MStatus Deregister( MFnPlugin &pluginFn ) - { - return T::Deregister( pluginFn, s_name ); - } -}; - - -//============================================================================= -// -// Base class for Valve Maya Shape Nodes ( CVsMayaMPxShapeNode ) -// -//============================================================================ -class CVsMayaMPxShapeNode : public MPxSurfaceShape -{ -public: - virtual const MString &GetName() const = 0; - -protected: - static MStatus Register( - MFnPlugin &pluginFn, - const MString &name, - const MTypeId &mTypeId, - MCreatorFunction creatorFunction, - MInitializeFunction initFunction, - MCreatorFunction uiCreatorFunction ); - - static MStatus Deregister( - MFnPlugin &pluginFn, - const MTypeId &mTypeId ); -}; - - -//----------------------------------------------------------------------------- -// -// Decorator class for Valve Maya shape nodes ( CVsMayaMPxShapeNodeDecorator ) -// -//----------------------------------------------------------------------------- -template < class T, class U > -class CVsMayaMPxShapeNodeDecorator : public T -{ -public: - static const MString &Name() { return s_name; }; - - virtual const MString &GetName() const { return Name(); }; - - virtual const MString &GetDesc() const { return s_desc; }; - - static CVsMayaMPxFactoryBase::Type GetType() - { - return CVsMayaMPxFactoryBase::kLocatorNode; - } - -private: - template < class U > friend class CVsMayaMPxFactory; - - static const MString s_name; - - static const MString s_desc; - - static const MTypeId s_mTypeId; - - static const MInitializeFunction s_mInitializeFunction; - - static const MCreatorFunction s_uiCreatorFunction; - - static void *Create() - { - return new CVsMayaMPxShapeNodeDecorator< T, U >; - } - - static void *CreateUI() - { - return new U; - } - - static MStatus Register( MFnPlugin &pluginFn ) - { - return T::Register( pluginFn, s_name, s_mTypeId, Create, s_mInitializeFunction, CreateUI ); - } - - static MStatus Deregister( MFnPlugin &pluginFn ) - { - return T::Deregister( pluginFn, s_mTypeId ); - } -}; - -#if MAYA_API_VERSION >= 200800 -//============================================================================= -// -// Base class for Valve Maya Image File Types ( CVsMayaMPxImageFile ) -// -//============================================================================ -class CVsMayaMPxImageFile : public MPxImageFile -{ -public: - virtual const MString &GetName() const = 0; - -protected: - static MStatus Register( - MFnPlugin &pluginFn, - const MString &name, - MCreatorFunction creatorFunction, - const MStringArray &extensions ); - - static MStatus Deregister( - MFnPlugin &pluginFn, - const MString &name ); -}; - - -//----------------------------------------------------------------------------- -// -// Decorator class for Valve Maya Image Files ( CVsMayaMPxImageFileDecorator ) -// -//----------------------------------------------------------------------------- -template < class T > -class CVsMayaMPxImageFileDecorator : public T -{ -public: - static const MString &Name() { return s_name; }; - - virtual const MString &GetName() const { return Name(); }; - - virtual const MString &GetDesc() const { return s_desc; }; - - static CVsMayaMPxFactoryBase::Type GetType() - { - return CVsMayaMPxFactoryBase::kImageFile; - } - -private: - template < class T > friend class CVsMayaMPxFactory; - - static const MString s_name; - - static const MString s_desc; - - static const MStringArray s_extensions; - - static const MCreatorFunction s_creatorFunction; - - static void *Create() - { - return new CVsMayaMPxImageFileDecorator< T >; - } - - static MStatus Register( MFnPlugin &pluginFn ) - { - return T::Register( pluginFn, s_name, Create, s_extensions ); - } - - static MStatus Deregister( MFnPlugin &pluginFn ) - { - return T::Deregister( pluginFn, s_name ); - } -}; - - -//----------------------------------------------------------------------------- -// Helper macro to instantiate an image file -//----------------------------------------------------------------------------- -#define INSTALL_MAYA_MPXIMAGEFILE( _class, _name, _extensions, _desc ) \ - const MString CVsMayaMPxImageFileDecorator< _class >::s_name( #_name ); \ - const MString CVsMayaMPxImageFileDecorator< _class >::s_desc( _desc ); \ - const MStringArray CVsMayaMPxImageFileDecorator< _class >::s_extensions( _extensions ); \ - static CVsMayaMPxFactory< CVsMayaMPxImageFileDecorator< _class > > s_##_name##_Factory - - -#endif // MAYA_API_VERSION >= 200800 - - -//============================================================================= -// -// Base class for Valve Maya Dependency Nodes ( CVsMayaMPxNode ) -// -//============================================================================ -class CVsMayaMPxDeformerNode : public MPxDeformerNode -{ -public: - virtual const MString &GetName() const = 0; - -protected: - static MStatus Register( - MFnPlugin &pluginFn, - const MString &name, - const MTypeId &mTypeId, - MCreatorFunction creatorFunction, - MInitializeFunction initFunction, - const MString &classification ); - - static MStatus Deregister( - MFnPlugin &pluginFn, - const MTypeId &mTypeId ); -}; - - -//----------------------------------------------------------------------------- -// -// Decorator class for Valve Maya nodes ( CVsMayaMPxDeformerNodeDecorator ) -// -//----------------------------------------------------------------------------- -template < class T > -class CVsMayaMPxDeformerNodeDecorator : public T -{ -public: - static const MString &Name() { return s_name; }; - - virtual const MString &GetName() const { return Name(); }; - - virtual const MString &GetDesc() const { return s_desc; }; - - static CVsMayaMPxFactoryBase::Type GetType() - { - return s_classification.length() ? CVsMayaMPxFactoryBase::kShaderNode : CVsMayaMPxFactoryBase::kDependencyNode; - } - -private: - template < class U > friend class CVsMayaMPxFactory; - - static const MString s_name; - - static const MString s_desc; - - static const MTypeId s_mTypeId; - - static const MInitializeFunction s_mInitializeFunction; - - static const MString s_classification; - - static void *Create() - { - return new CVsMayaMPxDeformerNodeDecorator< T >; - } - - static MStatus Register( MFnPlugin &pluginFn ) - { - return T::Register( pluginFn, s_name, s_mTypeId, Create, s_mInitializeFunction, s_classification ); - } - - static MStatus Deregister( MFnPlugin &pluginFn ) - { - return T::Deregister( pluginFn, s_mTypeId ); - } -}; - - -//============================================================================= -// -// Helper Macros -// -//============================================================================= - -//----------------------------------------------------------------------------- -// Helper macro to instantiate a command -//----------------------------------------------------------------------------- -#define INSTALL_MAYA_MPXCOMMAND( _class, _name, _desc ) \ - MString CVsMayaMPxCommandDecorator< _class >::s_name( #_name ); \ - MString CVsMayaMPxCommandDecorator< _class >::s_desc( _desc ); \ - ValveMaya::CMSyntaxHelp CVsMayaMPxCommandDecorator< _class >::s_mSyntaxHelp; \ - static CVsMayaMPxFactory< CVsMayaMPxCommandDecorator< _class > > s_##_name##_Factory - - -//----------------------------------------------------------------------------- -// Helper macro to instantiate a translator -//----------------------------------------------------------------------------- -#define INSTALL_MAYA_MPXFILETRANSLATOR( _class, _name, _guiName, _desc ) \ - const MString CVsMayaMPxFileTranslatorDecorator< _class >::s_name( #_name ); \ - const MString CVsMayaMPxFileTranslatorDecorator< _class >::s_desc( _desc ); \ - const MString CVsMayaMPxFileTranslatorDecorator< _class >::s_guiName( _guiName ); \ - static CVsMayaMPxFactory< CVsMayaMPxFileTranslatorDecorator< _class > > s_##_name##_Factory - - -//----------------------------------------------------------------------------- -// Helper macro to instantiate a regular dependency node -//----------------------------------------------------------------------------- -#define INSTALL_MAYA_MPXNODE( _class, _name, _typeId, _initializeFunction, _desc ) \ - const MString CVsMayaMPxNodeDecorator< _class >::s_name( #_name ); \ - const MString CVsMayaMPxNodeDecorator< _class >::s_desc( _desc ); \ - const MTypeId CVsMayaMPxNodeDecorator< _class >::s_mTypeId( _typeId ); \ - const MInitializeFunction CVsMayaMPxNodeDecorator< _class >::s_mInitializeFunction( _initializeFunction ); \ - const MString CVsMayaMPxNodeDecorator< _class >::s_classification( "" ); \ - static CVsMayaMPxFactory< CVsMayaMPxNodeDecorator< _class > > s_##_name##_Factory - - -//----------------------------------------------------------------------------- -// Helper macro to instantiate a shader dependency node -//----------------------------------------------------------------------------- -#define INSTALL_MAYA_MPXSHADERNODE( _class, _name, _typeId, _initializeFunction, _classification, _desc ) \ - const MString CVsMayaMPxNodeDecorator< _class >::s_name( #_name ); \ - const MString CVsMayaMPxNodeDecorator< _class >::s_desc( _desc ); \ - const MTypeId CVsMayaMPxNodeDecorator< _class >::s_mTypeId( _typeId ); \ - const MInitializeFunction CVsMayaMPxNodeDecorator< _class >::s_mInitializeFunction( _initializeFunction ); \ - const MString CVsMayaMPxNodeDecorator< _class >::s_classification( _classification ); \ - static CVsMayaMPxFactory< CVsMayaMPxNodeDecorator< _class > > s_##_name##_Factory - - -//----------------------------------------------------------------------------- -// Helper macro to instantiate a transform node -//----------------------------------------------------------------------------- -#define INSTALL_MAYA_MPXTRANSFORM( _class, _name, _typeId, _initializeFunction, _desc ) \ - const MString CVsMayaMPxTransformDecorator< _class >::s_name( #_name ); \ - const MString CVsMayaMPxTransformDecorator< _class >::s_desc( _desc ); \ - const MTypeId CVsMayaMPxTransformDecorator< _class >::s_mTypeId( _typeId ); \ - const MInitializeFunction CVsMayaMPxTransformDecorator< _class >::s_mInitializeFunction( _initializeFunction ); \ - const MCreatorFunction CVsMayaMPxTransformDecorator< _class >::s_xformMCreatorFunction( MPxTransformationMatrix::creator ); \ - const MTypeId CVsMayaMPxTransformDecorator< _class >::s_xformMTypeId( MPxTransformationMatrix::baseTransformationMatrixId ); \ - static CVsMayaMPxFactory< CVsMayaMPxTransformDecorator< _class > > s_##_name##_Factory - - -//----------------------------------------------------------------------------- -// Helper macro to instantiate a transform node with a custom transformation matrix -// TODO: Make CVsMayaMPxTransformationMatrix and create the MCreatorFunction for the user -//----------------------------------------------------------------------------- -#define INSTALL_MAYA_MPXTRANSFORM_WITHMATRIX( _class, _name, _typeId, _initializeFunction, _xformCreatorFunction, _xformTypeId, _desc ) \ - const MString CVsMayaMPxTransformDecorator< _class >::s_name( #_name ); \ - const MString CVsMayaMPxTransformDecorator< _class >::s_desc( _desc ); \ - const MTypeId CVsMayaMPxTransformDecorator< _class >::s_mTypeId( _typeId ); \ - const MInitializeFunction CVsMayaMPxTransformDecorator< _class >::s_mInitializeFunction( _initializeFunction ); \ - const MCreatorFunction CVsMayaMPxTransformDecorator< _class >::s_xformMCreatorFunction( _xformCreatorFunction ); \ - const MTypeId CVsMayaMPxTransformDecorator< _class >::s_xformMTypeId( _xformTypeId ); \ - static CVsMayaMPxFactory< CVsMayaMPxTransformDecorator< _class > > s_##_name##_Factory - - -//----------------------------------------------------------------------------- -// Helper macro to instantiate a locator node -//----------------------------------------------------------------------------- -#define INSTALL_MAYA_MPXLOCATORNODE( _class, _name, _typeId, _initializeFunction, _desc ) \ - const MString CVsMayaMPxLocatorNodeDecorator< _class >::s_name( #_name ); \ - const MString CVsMayaMPxLocatorNodeDecorator< _class >::s_desc( _desc ); \ - const MTypeId CVsMayaMPxLocatorNodeDecorator< _class >::s_mTypeId( _typeId ); \ - const MInitializeFunction CVsMayaMPxLocatorNodeDecorator< _class >::s_mInitializeFunction( _initializeFunction ); \ - static CVsMayaMPxFactory< CVsMayaMPxLocatorNodeDecorator< _class > > s_##_name##_Factory - - -//----------------------------------------------------------------------------- -// Helper macro to instantiate a drag and drop behavior -//----------------------------------------------------------------------------- -#define INSTALL_MAYA_MPXDRAGANDDROPBEHAVIOR( _class, _name, _desc ) \ - const MString CVsMayaMPxDragAndDropBehaviorDecorator< _class >::s_name( #_name ); \ - const MString CVsMayaMPxDragAndDropBehaviorDecorator< _class >::s_desc( _desc ); \ - static CVsMayaMPxFactory< CVsMayaMPxDragAndDropBehaviorDecorator< _class > > s_##_name##_Factory - - -//----------------------------------------------------------------------------- -// Helper macro to instantiate a shape node -//----------------------------------------------------------------------------- -#define INSTALL_MAYA_MPXSHAPENODE( _class, _name, _typeId, _initializeFunction, _uiClass, _desc ) \ - const MString CVsMayaMPxShapeNodeDecorator< _class, _uiClass >::s_name( #_name ); \ - const MString CVsMayaMPxShapeNodeDecorator< _class, _uiClass >::s_desc( _desc ); \ - const MTypeId CVsMayaMPxShapeNodeDecorator< _class, _uiClass >::s_mTypeId( _typeId ); \ - const MInitializeFunction CVsMayaMPxShapeNodeDecorator< _class, _uiClass >::s_mInitializeFunction( _initializeFunction ); \ - static CVsMayaMPxFactory< CVsMayaMPxShapeNodeDecorator< _class, _uiClass > > s_##_name##_Factory - - -//----------------------------------------------------------------------------- -// Helper macro to instantiate a deformer dependency node -//----------------------------------------------------------------------------- -#define INSTALL_MAYA_MPXDEFORMERNODE( _class, _name, _typeId, _initializeFunction, _desc ) \ - const MString CVsMayaMPxDeformerNodeDecorator< _class >::s_name( #_name ); \ - const MString CVsMayaMPxDeformerNodeDecorator< _class >::s_desc( _desc ); \ - const MTypeId CVsMayaMPxDeformerNodeDecorator< _class >::s_mTypeId( _typeId ); \ - const MInitializeFunction CVsMayaMPxDeformerNodeDecorator< _class >::s_mInitializeFunction( _initializeFunction ); \ - const MString CVsMayaMPxDeformerNodeDecorator< _class >::s_classification( "" ); \ - static CVsMayaMPxFactory< CVsMayaMPxDeformerNodeDecorator< _class > > s_##_name##_Factory - - -#endif // VSMAYAMPXFACTORY_H diff --git a/public/maya/VsVGuiWindow.h b/public/maya/VsVGuiWindow.h deleted file mode 100644 index 71c209cba..000000000 --- a/public/maya/VsVGuiWindow.h +++ /dev/null @@ -1,107 +0,0 @@ -//===== Copyright 1996-2006, Valve Corporation, All rights reserved. ======// -// -// Base class for windows that draw vgui in Maya -// -//===========================================================================// - -#ifndef VSVGUIWINDOW_H -#define VSVGUIWINDOW_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "imayavgui.h" -#include "vgui_controls/Frame.h" - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class IMayaVGui; - - -//----------------------------------------------------------------------------- -// The singleton is defined here twice just so we don't have to include valvemaya.h also -//----------------------------------------------------------------------------- -extern IMayaVGui *g_pMayaVGui; - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -namespace vgui -{ - class EditablePanel; -} - - -//----------------------------------------------------------------------------- -// Creates, destroys a maya vgui window -//----------------------------------------------------------------------------- -void CreateMayaVGuiWindow( vgui::EditablePanel *pRootPanel, const char *pPanelName ); -void DestroyMayaVGuiWindow( const char *pPanelName ); - - -//----------------------------------------------------------------------------- -// Factory used to install vgui windows easily -//----------------------------------------------------------------------------- -class CVsVguiWindowFactoryBase : public IMayaVguiWindowFactory -{ -public: - CVsVguiWindowFactoryBase( const char *pWindowTypeName, const char *pDccStartupCommand ); - - // Returns the DCC command - const char *GetDccStartupCommand() const; - - // Registers/deregisters all vgui windows - static void RegisterAllVguiWindows( ); - static void UnregisterAllVguiWindows( ); - -protected: - const char *m_pWindowTypeName; - const char *m_pDccStartupCommand; - -private: - CVsVguiWindowFactoryBase *m_pNext; - static CVsVguiWindowFactoryBase *s_pFirstCommandFactory; -}; - - -template< class T > -class CVsVguiWindowFactory : public CVsVguiWindowFactoryBase -{ - typedef CVsVguiWindowFactoryBase BaseClass; - -public: - CVsVguiWindowFactory( const char *pWindowTypeName, const char *pDccCommand ) : BaseClass( pWindowTypeName, pDccCommand ) - { - } - - virtual void CreateVguiWindow( const char *pPanelName ) - { - T *pVguiPanel = new T( NULL, pPanelName ); - vgui::Frame* pFrame = dynamic_cast( pVguiPanel ); - if ( pFrame ) - { - pFrame->SetSizeable( false ); - pFrame->SetCloseButtonVisible( false ); - pFrame->SetMoveable( false ); - } - CreateMayaVGuiWindow( pVguiPanel, pPanelName ); - } - - virtual void DestroyVguiWindow( const char *pPanelName ) - { - DestroyMayaVGuiWindow( pPanelName ); - } - -private: -}; - - -#define INSTALL_MAYA_VGUI_WINDOW( _className, _windowTypeName, _dccCommand ) \ - static CVsVguiWindowFactory< _className > s_VsVguiWindowFactory##_className##( _windowTypeName, _dccCommand ) - - -#endif // VSVGUIWINDOW_H diff --git a/public/maya/valveMaya.h b/public/maya/valveMaya.h deleted file mode 100644 index 06eb91b23..000000000 --- a/public/maya/valveMaya.h +++ /dev/null @@ -1,472 +0,0 @@ -//======= Copyright 1996-2006, Valve Corporation, All rights reserved. ====== -// -// Purpose: -// -//============================================================================= - -#ifndef VALVEMAYA_H -#define VALVEMAYA_H - -#if defined( _WIN32 ) -#pragma once -#endif - -// Maya Includes - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Valve Includes - -#include "tier1/stringpool.h" -#include "tier1/utlstring.h" -#include "tier1/utlstringmap.h" -#include "tier1/utlvector.h" -#include "tier1/interface.h" - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class IMayaVGui; - - -//----------------------------------------------------------------------------- -// Maya-specific library singletons -//----------------------------------------------------------------------------- -extern IMayaVGui *g_pMayaVGui; - - -//----------------------------------------------------------------------------- -// -// Purpose: Group a bunch of functions into the Valve Maya Namespace -// -//----------------------------------------------------------------------------- - - -namespace ValveMaya -{ - //----------------------------------------------------------------------------- - // Forward declarations - //----------------------------------------------------------------------------- - class CUndo; - - //----------------------------------------------------------------------------- - // Statics - //----------------------------------------------------------------------------- - extern const MQuaternion v2mQuat; // Valve Engine -> Maya Quaternion - extern const MQuaternion m2vQuat; // Maya -> Valve Engine Quaternion - extern const MMatrix v2mMat; // Valve Engine -> Maya Matrix - extern const MMatrix m2vMat; // Maya -> Valve Engine Matrix - - extern const MQuaternion vc2mcQuat; // Valve Engine Camera -> Maya Camera Quaternion - extern const MQuaternion mc2vcQuat; // Maya Camera -> Valve Camera Engine Quaternion - extern const MMatrix vc2mcMat; // Valve Engine Camera -> Maya Camera Quaternion - extern const MMatrix mc2vcMat; // Maya Camera -> Valve Camera Engine Quaternion - - inline MQuaternion ValveToMaya( const MQuaternion &q ) { return q * v2mQuat; } - inline MQuaternion ValveCameraToMayaCamera( const MQuaternion &q ) { return vc2mcQuat * q * v2mQuat; } - inline MQuaternion MayaToValve( const MQuaternion &q ) { return q * m2vQuat; } - inline MQuaternion MayaCameraToValveCamera( const MQuaternion &q ) { return mc2vcQuat * q * m2vQuat; } - - inline MVector ValveToMaya( const MVector &p ) { return p.rotateBy( v2mQuat ); } - inline MVector ValveCameraToMayaCamera( const MVector &p ) { return p.rotateBy( v2mQuat ); } - inline MVector MayaToValve( const MVector &p ) { return p.rotateBy( m2vQuat ); } - inline MVector MayaCameraToValveCamera( const MVector &p ) { return p.rotateBy( m2vQuat ); } - -//----------------------------------------------------------------------------- -// Connect, disconnect -//----------------------------------------------------------------------------- -bool ConnectLibraries( CreateInterfaceFn factory ); -void DisconnectLibraries(); - -MStatus CreateDagNode( - const char *const i_nodeType, - const char *const i_transformName = NULL, - const MObject &i_parentObj = MObject::kNullObj, - MObject *o_pTransformObj = NULL, - MObject *o_pShapeObj = NULL, - MDagModifier *i_mDagModifier = NULL); - -inline MStatus CreateDagNode( - CUndo &undo, - const char *const i_nodeType, - const char *const i_transformName = NULL, - const MObject &i_parentObj = MObject::kNullObj, - MObject *o_pTransformObj = NULL, - MObject *o_pShapeObj = NULL ) -{ - return CreateDagNode( i_nodeType, i_transformName, i_parentObj, o_pTransformObj, o_pShapeObj ); -} - -bool IsNodeVisible( const MDagPath &mDagPath, bool bTemplateAsInvisible = true ); -bool IsPathVisible( MDagPath mDagPath, bool bTemplateAsInvisible = true ); - -class CMSyntaxHelp -{ -public: - CMSyntaxHelp() - : m_groupedHelp( false ) // Make case sensitive - , m_helpCount( 0 ) - , m_shortNameLength( 0 ) - {} - - void Clear(); - - MStatus AddFlag( - MSyntax &i_mSyntax, - const char *i_shortName, - const char *i_longName, - const char *i_group, - const char *i_help, - const MSyntax::MArgType i_argType1 = MSyntax::kNoArg, - const MSyntax::MArgType i_argType2 = MSyntax::kNoArg, - const MSyntax::MArgType i_argType3 = MSyntax::kNoArg, - const MSyntax::MArgType i_argType4 = MSyntax::kNoArg, - const MSyntax::MArgType i_argType5 = MSyntax::kNoArg, - const MSyntax::MArgType i_argType6 = MSyntax::kNoArg); - - void PrintHelp( - const char *const i_cmdName, - const char *const i_cmdDesc, - int i_lineLength = 0U); - - void PrintHelp( - const MString &i_cmdName, - const MString &i_cmdDesc, - int i_lineLength = 0U) - { - PrintHelp( i_cmdName.asChar(), i_cmdDesc.asChar(), i_lineLength ); - } - -protected: -public: -protected: - CCountedStringPool m_stringPool; - - struct HelpData_t - { - const char *m_shortName; - const char *m_longName; - const char *m_help; - CUtlVector m_argTypes; - }; - - CUtlVector m_groupOrder; - CUtlStringMap > m_groupedHelp; - int m_helpCount; - int m_shortNameLength; -}; - -MString RemoveNameSpace( const MString &mString ); - -MString &BackslashToSlash( MString &mString ); - -template < class T_t > bool IsDefault( T_t &, const MPlug & ); - -bool IsDefault( const MPlug &aPlug ); - -uint NextAvailable( MPlug &mPlug ); - -MObject AddColorSetToMesh( - const MString &colorSetName, - const MDagPath &mDagPath, - MDagModifier &mDagModifier ); - -MString GetMaterialPath( - const MObject &shadingGroupObj, - MObject *pSurfaceShaderObj, - MObject *pFileObj, - MObject *pPlace2dTextureObj, - MObject *pVmtObj, - bool *pbTransparent, - MString *pDebugWhy ); - -// Returns the first node that is connected to the specified plug as input or output -MObject FindConnectedNode( const MPlug &mPlug ); - -// Returns the plug connected to the specified plug as an input, a NULL plug if no plug is connected -MPlug FindInputPlug( const MPlug &dstPlug ); - -MPlug FindInputPlug( const MObject &dstNodeObj, const MString &dstPlugName ); - -MObject FindInputNode( const MPlug &dstPlug ); - -MObject FindInputNode( const MObject &dstNodeObj, const MString &dstPlugName ); - -MObject FindInputAttr( const MPlug &dstPlug ); - -MObject FindInputAttr( const MObject &dstNodeObj, const MString &dstPlugName ); - -// Returns the first found node MObject of the specified type in the history of the specified node -MObject FindInputNodeOfType( const MObject &dstNodeObj, const MString &typeName, const MString &dstPlugName ); - -MObject FindInputNodeOfType( const MObject &dstNodeObj, const MString &typeName ); - -// Creates a deformer of the specified type and deforms the specified shape with an optional component -MObject DeformShape( ValveMaya::CUndo &undo, const MString &deformerType, const MDagPath &inOrigDagPath, MObject &origCompObj = MObject::kNullObj ); - -} // end namespace ValveMaya - - -// Make an alias for the ValveMaya namespace - -namespace vm = ValveMaya; - - -//----------------------------------------------------------------------------- -// A simple stream class for printing information to the Maya script editor -//----------------------------------------------------------------------------- -class CMayaStream -{ -public: - enum StreamType { kInfo, kWarning, kError }; - - CMayaStream( const StreamType i_streamType = kInfo ) - : m_streamType( i_streamType ) - {} - - template < class T_t > - CMayaStream &operator<<( const T_t &v ); - - // This is a hack so CMayaStream << std::endl works as expected - CMayaStream &operator<<( std::ostream &(*StdEndl_t)( std::ostream & ) ) - { - return flush(); - } - - CMayaStream &flush() { return outputString(); } - -protected: - CMayaStream &outputString() - { - // Always ensure it's terminated with a newline - if ( *( m_string.asChar() + m_string.length() - 1 ) != '\n' ) - { - m_string += "\n"; - } - - const char *pBegin = m_string.asChar(); - const char *const pEnd = pBegin + m_string.length(); - const char *pCurr = pBegin; - - while ( *pCurr && pCurr < pEnd ) - { - if ( *pCurr == '\n' ) - { - switch ( m_streamType ) - { - case kWarning: - MGlobal::displayWarning( MString( pBegin, pCurr - pBegin ) ); - break; - case kError: - MGlobal::displayError( MString( pBegin, pCurr - pBegin ) ); - break; - default: - MGlobal::displayInfo( MString( pBegin, pCurr - pBegin ) ); - break; - } - - ++pCurr; - pBegin = pCurr; - } - else - { - ++pCurr; - } - } - - m_string.clear(); - - return *this; - } - - CMayaStream &checkForFlush() - { - const char *pCurr = m_string.asChar(); - const char *pEnd = pCurr + m_string.length(); - while ( *pCurr && pCurr != pEnd ) - { - if ( *pCurr == '\n' ) - { - return outputString(); - } - - ++pCurr; - } - - return *this; - } - - StreamType m_streamType; - MString m_string; -}; - - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -class CMayaWarnStream : public CMayaStream -{ -public: - CMayaWarnStream() - : CMayaStream( CMayaStream::kWarning ) - {} - -}; - - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -class CMayaErrStream : public CMayaStream -{ -public: - CMayaErrStream() - : CMayaStream( CMayaStream::kError ) - {} -}; - - -//----------------------------------------------------------------------------- -// Specialization for std::string -//----------------------------------------------------------------------------- -template <> -inline CMayaStream &CMayaStream::operator<<( const std::string &v ) -{ - *this << v.c_str(); - return *this; -} - - -//----------------------------------------------------------------------------- -// Specialization for char -//----------------------------------------------------------------------------- -template <> -inline CMayaStream &CMayaStream::operator<<( const char &v ) -{ - m_string += MString( &v, 1 ); - return *this; -} - - -//----------------------------------------------------------------------------- -// Specialization for MVector -//----------------------------------------------------------------------------- -template <> -inline CMayaStream &CMayaStream::operator<<( const MVector &v ) -{ - m_string += v.x; - m_string += " "; - m_string += v.y; - m_string += " "; - m_string += v.z; - return *this; -} - - -//----------------------------------------------------------------------------- -// Specialization for MFloatVector -//----------------------------------------------------------------------------- -template <> -inline CMayaStream &CMayaStream::operator<<( const MFloatVector &v ) -{ - m_string += v.x; - m_string += " "; - m_string += v.y; - m_string += " "; - m_string += v.z; - return *this; -} - - -//----------------------------------------------------------------------------- -// Specialization for MQuaternion -//----------------------------------------------------------------------------- -template <> -inline CMayaStream &CMayaStream::operator<<( const MQuaternion &q ) -{ - m_string += q.x; - m_string += " "; - m_string += q.y; - m_string += " "; - m_string += q.z; - m_string += " "; - m_string += q.w; - return *this; -} - - -//----------------------------------------------------------------------------- -// Specialization for MEulerRotation -//----------------------------------------------------------------------------- -template <> -inline CMayaStream &CMayaStream::operator<<( const MEulerRotation &e ) -{ - m_string += MAngle( e.x, MAngle::kRadians ).asDegrees(); - m_string += " "; - m_string += MAngle( e.y, MAngle::kRadians ).asDegrees(); - m_string += " "; - m_string += MAngle( e.z, MAngle::kRadians ).asDegrees(); - switch ( e.order ) - { - case MEulerRotation::kXYZ: - m_string += " (XYZ)"; - break; - case MEulerRotation::kXZY: - m_string += " (XZY)"; - break; - case MEulerRotation::kYXZ: - m_string += " (YXZ)"; - break; - case MEulerRotation::kYZX: - m_string += " (YZX)"; - break; - case MEulerRotation::kZXY: - m_string += " (ZXY)"; - break; - case MEulerRotation::kZYX: - m_string += " (ZYX)"; - break; - default: - m_string += " (Unknown)"; - break; - } - return *this; -} - - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -template < class T_t > -inline CMayaStream &CMayaStream::operator<<( const T_t &v ) -{ - m_string += v; - return checkForFlush(); -} - - -//----------------------------------------------------------------------------- -// -// minfo, mwarn & merr are ostreams which can be used to send stuff to -// the Maya history window -// -//----------------------------------------------------------------------------- - -extern CMayaStream minfo; -extern CMayaWarnStream mwarn; -extern CMayaErrStream merr; - - -#endif // VALVEMAYA_H diff --git a/public/mdllib/mdllib.h b/public/mdllib/mdllib.h deleted file mode 100644 index d787dd341..000000000 --- a/public/mdllib/mdllib.h +++ /dev/null @@ -1,119 +0,0 @@ -//====== Copyright 1996-2007, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef MDLLIB_H -#define MDLLIB_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/utlbuffer.h" -#include "appframework/IAppSystem.h" - -// -// Forward interface declarations -// -abstract_class IMdlLib; - -abstract_class IMdlStripInfo; - - -//----------------------------------------------------------------------------- -// Purpose: Interface to accessing model data operations -//----------------------------------------------------------------------------- -#define MDLLIB_INTERFACE_VERSION "VMDLLIB001" - -abstract_class IMdlLib : public IAppSystem -{ - // - // Stripping routines - // -public: - - // - // StripModelBuffers - // The main function that strips the model buffers - // mdlBuffer - mdl buffer, updated, no size change - // vvdBuffer - vvd buffer, updated, size reduced - // vtxBuffer - vtx buffer, updated, size reduced - // ppStripInfo - if nonzero on return will be filled with the stripping info - // - virtual bool StripModelBuffers( CUtlBuffer &mdlBuffer, CUtlBuffer &vvdBuffer, CUtlBuffer &vtxBuffer, IMdlStripInfo **ppStripInfo ) = 0; - - // - // CreateNewStripInfo - // Creates an empty strip info or resets an existing strip info so that it can be reused. - // - virtual bool CreateNewStripInfo( IMdlStripInfo **ppStripInfo ) = 0; - -}; - - -abstract_class IMdlStripInfo -{ - // - // Serialization - // -public: - // Save the strip info to the buffer (appends to the end) - virtual bool Serialize( CUtlBuffer &bufStorage ) const = 0; - - // Load the strip info from the buffer (reads from the current position as much as needed) - virtual bool UnSerialize( CUtlBuffer &bufData ) = 0; - - // - // Stripping info state - // -public: - // Returns the checksums that the stripping info was generated for: - // plChecksumOriginal if non-NULL will hold the checksum of the original model submitted for stripping - // plChecksumStripped if non-NULL will hold the resulting checksum of the stripped model - virtual bool GetCheckSum( long *plChecksumOriginal, long *plChecksumStripped ) const = 0; - - // - // Stripping - // -public: - - // - // StripHardwareVertsBuffer - // The main function that strips the vhv buffer - // vhvBuffer - vhv buffer, updated, size reduced - // - virtual bool StripHardwareVertsBuffer( CUtlBuffer &vhvBuffer ) = 0; - - // - // StripModelBuffer - // The main function that strips the mdl buffer - // mdlBuffer - mdl buffer, updated - // - virtual bool StripModelBuffer( CUtlBuffer &mdlBuffer ) = 0; - - // - // StripVertexDataBuffer - // The main function that strips the vvd buffer - // vvdBuffer - vvd buffer, updated, size reduced - // - virtual bool StripVertexDataBuffer( CUtlBuffer &vvdBuffer ) = 0; - - // - // StripOptimizedModelBuffer - // The main function that strips the vtx buffer - // vtxBuffer - vtx buffer, updated, size reduced - // - virtual bool StripOptimizedModelBuffer( CUtlBuffer &vtxBuffer ) = 0; - - // - // Release the object with "delete this" - // -public: - virtual void DeleteThis() = 0; -}; - - - -#endif // MDLLIB_H diff --git a/public/measure_section.cpp b/public/measure_section.cpp deleted file mode 100644 index 441192d6b..000000000 --- a/public/measure_section.cpp +++ /dev/null @@ -1,271 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#include -#include -#include "basetypes.h" -#include "measure_section.h" -#include "convar.h" - - -// Static members -CMeasureSection *CMeasureSection::s_pSections = 0; -int CMeasureSection::s_nCount = 0; -double CMeasureSection::m_dNextResort = 0.0; - -ConVar measure_resort( "measure_resort", "1.0", 0, "How often to re-sort profiling sections\n" ); -ConVar game_speeds( "game_speeds","0" ); -extern ConVar host_speeds; - -//----------------------------------------------------------------------------- -// Purpose: Creates a profiling section -// Input : *name - name of the section ( allocated on stack hopefully ) -//----------------------------------------------------------------------------- -CMeasureSection::CMeasureSection( const char *name ) -{ - // Just point at name since it's static - m_pszName = name; - - // Clear accumulators - Reset(); - SortReset(); - m_dMaxTime.Init(); - - // Link into master list - m_pNext = s_pSections; - s_pSections = this; - // Update count - s_nCount++; -} - -//----------------------------------------------------------------------------- -// Purpose: Destroys the object -//----------------------------------------------------------------------------- -CMeasureSection::~CMeasureSection( void ) -{ - m_pNext = NULL; - s_nCount--; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMeasureSection::UpdateMax( void ) -{ - if (m_dMaxTime.IsLessThan(m_dAccumulatedTime)) - { - m_dMaxTime.Init(); - CCycleCount::Add(m_dMaxTime,m_dAccumulatedTime,m_dMaxTime); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMeasureSection::Reset( void ) -{ - m_dAccumulatedTime.Init(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CMeasureSection::SortReset( void ) -{ - m_dTotalTime.Init(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CMeasureSection::GetName( void ) -{ - return m_pszName; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : -//----------------------------------------------------------------------------- -CCycleCount const& CMeasureSection::GetTotalTime( void ) -{ - return m_dTotalTime; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : -//----------------------------------------------------------------------------- -CCycleCount const& CMeasureSection::GetTime( void ) -{ - return m_dAccumulatedTime; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : -//----------------------------------------------------------------------------- -CCycleCount const& CMeasureSection::GetMaxTime( void ) -{ - return m_dMaxTime; -} - -//----------------------------------------------------------------------------- -// Purpose: Accumulates a timeslice -// Input : time - -//----------------------------------------------------------------------------- -void CMeasureSection::AddTime( CCycleCount const &rCount ) -{ - CCycleCount::Add(m_dAccumulatedTime, rCount, m_dAccumulatedTime); - CCycleCount::Add(m_dTotalTime, rCount, m_dTotalTime); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CMeasureSection -//----------------------------------------------------------------------------- -CMeasureSection *CMeasureSection::GetNext( void ) -{ - return m_pNext; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : CMeasureSection -//----------------------------------------------------------------------------- -CMeasureSection *CMeasureSection::GetList( void ) -{ - return s_pSections; -} - -//----------------------------------------------------------------------------- -// Purpose: Compares accumulated time for two sections -// Input : ppms1 - -// ppms2 - -// Output : static int -//----------------------------------------------------------------------------- -static int SectionCompare( const void* ppms1,const void* ppms2 ) -{ - CMeasureSection* pms1 = *(CMeasureSection**)ppms1; - CMeasureSection* pms2 = *(CMeasureSection**)ppms2; - - if ( pms1->GetTotalTime().IsLessThan(pms2->GetTotalTime()) ) - return 1; - else - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: Sorts sections by time usage -//----------------------------------------------------------------------------- -void CMeasureSection::SortSections( void ) -{ - // Not enough to be sortable - if ( s_nCount <= 1 ) - return; - - CMeasureSection *sortarray[ 128 ]; - CMeasureSection *ms; - - memset(sortarray,sizeof(CMeasureSection*)*128,0); - - ms = GetList(); - int i; - int c = 0; - while ( ms ) - { - sortarray[ c++ ] = ms; - ms = ms->GetNext(); - } - - // Sort the array alphabetically - qsort( sortarray, c , sizeof( CMeasureSection * ), SectionCompare ); - - // Fix next pointers - for ( i = 0; i < c-1; i++ ) - { - sortarray[ i ]->m_pNext = sortarray[ i + 1 ]; - } - sortarray[i]->m_pNext = NULL; - - // Point head of list at it - s_pSections = sortarray[ 0 ]; -} - -//----------------------------------------------------------------------------- -// Purpose: Creates an instance for timing a section -// Input : *ms - -//----------------------------------------------------------------------------- -CMeasureSectionInstance::CMeasureSectionInstance( CMeasureSection *ms ) -{ - // Remember where to put accumulated time - m_pMS = ms; - - if ( host_speeds.GetInt() < 3 && !game_speeds.GetInt()) - return; - - // Get initial timestamp - m_Timer.Start(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CMeasureSectionInstance::~CMeasureSectionInstance( void ) -{ - if ( host_speeds.GetInt() < 3 && !game_speeds.GetInt()) - return; - - // Get final timestamp - m_Timer.End(); - - // Add time to section - m_pMS->AddTime( m_Timer.GetDuration() ); -} - -//----------------------------------------------------------------------------- -// Purpose: Re-sort all data and determine whether sort keys should be reset too ( after -// re-doing sort if needed ). -//----------------------------------------------------------------------------- -void ResetTimeMeasurements( void ) -{ -#if defined( _DEBUG ) || defined( FORCE_MEASURE ) - bool sort_reset = false; - - // Time to redo sort? - if ( measure_resort.GetFloat() > 0.0 && - GetRealTime() >= CMeasureSection::m_dNextResort ) - { - // Redo it - CMeasureSection::SortSections(); - // Set next time - CMeasureSection::m_dNextResort = GetRealTime() + measure_resort.GetFloat(); - // Flag to reset sort accumulator, too - sort_reset = true; - } - - // Iterate through the sections now - CMeasureSection *p = CMeasureSection::GetList(); - while ( p ) - { - // Reset regular accum. - p->Reset(); - // Reset sort accum less often - if ( sort_reset ) - { - p->SortReset(); - } - p = p->GetNext(); - } -#endif -} diff --git a/public/measure_section.h b/public/measure_section.h deleted file mode 100644 index 6922b6a7c..000000000 --- a/public/measure_section.h +++ /dev/null @@ -1,127 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// -#if !defined( MEASURE_SECTION_H ) -#define MEASURE_SECTION_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "tier0/fasttimer.h" -#include "convar.h" - - -// This is the macro to use in your code to measure until the code goes -// out of scope -#if defined( _DEBUG ) || defined( FORCE_MEASURE ) -#define MEASURECODE( description ) \ - static CMeasureSection _xxx_ms( description ); \ - CMeasureSectionInstance _xxx_ms_inst( &_xxx_ms ); -#else -#define MEASURECODE( description ) -#endif - - -// ------------------------------------------------------------------------------------ // -// These things must exist in the executable for the CMeasureSection code to work. -// ------------------------------------------------------------------------------------ // -float GetRealTime(); // Get the clock's time. - -extern ConVar game_speeds; -extern ConVar measure_resort; -// ------------------------------------------------------------------------------------ // - - - -// Called once per frame to allow any necessary measurements to latch -void ResetTimeMeasurements( void ); - -//----------------------------------------------------------------------------- -// Purpose: Accumulates time for the named section -//----------------------------------------------------------------------------- -class CMeasureSection -{ -public: - // Allows for measuring named section - CMeasureSection( const char *name ); - virtual ~CMeasureSection( void ); - - - // Update max value hit - void UpdateMax( void ); - // Reset totals - void Reset( void ); - // Reset sortable totals - void SortReset( void ); - // Get static name of section - const char *GetName( void ); - - // Get accumulated time - CCycleCount const& GetTotalTime( void ); - - CCycleCount const& GetTime(); - - CCycleCount const& GetMaxTime(); - - // Add in some time - void AddTime( CCycleCount const &rCount ); - - // Get next section in chain - CMeasureSection *GetNext( void ); - - // Get head of list of all sections - static CMeasureSection *GetList( void ); - // Sort all sections by most time consuming - static void SortSections( void ); - -public: - // Time when list should be sorted again - static double m_dNextResort; - -private: - // Accumulated time for section - CCycleCount m_dAccumulatedTime; - - // Max time for section - CCycleCount m_dMaxTime; - - // Elapsed time for section - CCycleCount m_dTotalTime; - - // Name of section - const char *m_pszName; - // Next section in chain - CMeasureSection *m_pNext; - // Head of section list - static CMeasureSection *s_pSections; - // Quick total for doing sorts faster - static int s_nCount; -}; - -//----------------------------------------------------------------------------- -// Purpose: On construction marks time and on destruction adds time to -// parent CMeasureSection object -//----------------------------------------------------------------------------- -class CMeasureSectionInstance -{ -public: - // Constructor: Points to object to accumulate time into - CMeasureSectionInstance( CMeasureSection *ms ); - // Destructor: Latches accumulated time - virtual ~CMeasureSectionInstance( void ); - -private: - // Time of construction - CFastTimer m_Timer; - - // Where to place elapsed time - CMeasureSection *m_pMS; -}; - -#endif // MEASURE_SECTION_H diff --git a/public/minmax.h b/public/minmax.h deleted file mode 100644 index 477b413df..000000000 --- a/public/minmax.h +++ /dev/null @@ -1,22 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef MINMAX_H -#define MINMAX_H - -#if defined( _WIN32 ) -#pragma once -#endif - -#ifndef min -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif -#ifndef max -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#endif - -#endif // MINMAX_H diff --git a/public/model_types.h b/public/model_types.h deleted file mode 100644 index 74b6a5d41..000000000 --- a/public/model_types.h +++ /dev/null @@ -1,41 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//=============================================================================// -#if !defined( MODEL_TYPES_H ) -#define MODEL_TYPES_H -#ifdef _WIN32 -#pragma once -#endif - -#define STUDIO_NONE 0x00000000 -#define STUDIO_RENDER 0x00000001 -#define STUDIO_VIEWXFORMATTACHMENTS 0x00000002 -#define STUDIO_DRAWTRANSLUCENTSUBMODELS 0x00000004 -#define STUDIO_TWOPASS 0x00000008 -#define STUDIO_STATIC_LIGHTING 0x00000010 -#define STUDIO_WIREFRAME 0x00000020 -#define STUDIO_ITEM_BLINK 0x00000040 -#define STUDIO_NOSHADOWS 0x00000080 -#define STUDIO_WIREFRAME_VCOLLIDE 0x00000100 - -// Not a studio flag, but used to flag model as a non-sorting brush model -#define STUDIO_TRANSPARENCY 0x80000000 - -// Not a studio flag, but used to flag model as using shadow depth material override -#define STUDIO_SHADOWDEPTHTEXTURE 0x40000000 - - -enum modtype_t -{ - mod_bad = 0, - mod_brush, - mod_sprite, - mod_studio -}; - -#endif // MODEL_TYPES_H diff --git a/public/modes.h b/public/modes.h deleted file mode 100644 index bcbf1f76c..000000000 --- a/public/modes.h +++ /dev/null @@ -1,21 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#if !defined( MODES_H ) -#define MODES_H -#ifdef _WIN32 -#pragma once -#endif - -typedef struct vmode_s -{ - int width; - int height; - int bpp; - int refreshRate; -} vmode_t; - -#endif // MODES_H diff --git a/public/mouthinfo.h b/public/mouthinfo.h deleted file mode 100644 index a6357f4ce..000000000 --- a/public/mouthinfo.h +++ /dev/null @@ -1,194 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#if !defined( MOUTHINFO_H ) -#define MOUTHINFO_H -#ifdef _WIN32 -#pragma once -#endif - -class CAudioSource; - -class CVoiceData -{ -public: - CVoiceData( void ) - { - m_flElapsed = 0.0f; - m_pAudioSource = NULL; - m_bIgnorePhonemes = false; - } - - void SetElapsedTime( float t ) - { - m_flElapsed = t; - } - - float GetElapsedTime() const - { - return m_flElapsed; - } - - void SetSource( CAudioSource *source, bool bIgnorePhonemes ) - { - m_pAudioSource = source; - m_bIgnorePhonemes = bIgnorePhonemes; - } - - bool ShouldIgnorePhonemes() const - { - return m_bIgnorePhonemes; - } - - CAudioSource *GetSource() - { - return m_pAudioSource; - } - -private: - float m_flElapsed; - CAudioSource *m_pAudioSource; - bool m_bIgnorePhonemes; -}; - -#define UNKNOWN_VOICE_SOURCE -1 - -//----------------------------------------------------------------------------- -// Purpose: Describes position of mouth for lip syncing -//----------------------------------------------------------------------------- -class CMouthInfo -{ -public: - // 0 = mouth closed, 255 = mouth agape - byte mouthopen; - // counter for running average - byte sndcount; - // running average - int sndavg; - -public: - CMouthInfo( void ) { m_nVoiceSources = 0; m_needsEnvelope = false; } - virtual ~CMouthInfo( void ) { ClearVoiceSources(); } - - int GetNumVoiceSources( void ); - CVoiceData *GetVoiceSource( int number ); - - void ClearVoiceSources( void ); - int GetIndexForSource( CAudioSource *source ); - bool IsSourceReferenced( CAudioSource *source ); - - CVoiceData *AddSource( CAudioSource *source, bool bIgnorePhonemes ); - - void RemoveSource( CAudioSource *source ); - void RemoveSourceByIndex( int index ); - - bool IsActive( void ); - bool NeedsEnvelope() { return m_needsEnvelope != 0; } - void ActivateEnvelope() { m_needsEnvelope = true; } - -private: - enum - { - MAX_VOICE_DATA = 4 - }; - - CVoiceData m_VoiceSources[ MAX_VOICE_DATA ]; - short m_nVoiceSources; - short m_needsEnvelope; -}; - -inline bool CMouthInfo::IsActive( void ) -{ - return ( GetNumVoiceSources() > 0 ) ? true : false; -} - -inline int CMouthInfo::GetNumVoiceSources( void ) -{ - return m_nVoiceSources; -} - -inline CVoiceData *CMouthInfo::GetVoiceSource( int number ) -{ - if ( number < 0 || number >= m_nVoiceSources ) - return NULL; - - return &m_VoiceSources[ number ]; -} - -inline void CMouthInfo::ClearVoiceSources( void ) -{ - m_nVoiceSources = 0; -} - -inline int CMouthInfo::GetIndexForSource( CAudioSource *source ) -{ - for ( int i = 0; i < m_nVoiceSources; i++ ) - { - CVoiceData *v = &m_VoiceSources[ i ]; - if ( !v ) - continue; - - if ( v->GetSource() == source ) - return i; - } - - return UNKNOWN_VOICE_SOURCE; -} - -inline bool CMouthInfo::IsSourceReferenced( CAudioSource *source ) -{ - if ( GetIndexForSource( source ) != UNKNOWN_VOICE_SOURCE ) - return true; - - return false; -} - -inline void CMouthInfo::RemoveSource( CAudioSource *source ) -{ - int idx = GetIndexForSource( source ); - if ( idx == UNKNOWN_VOICE_SOURCE ) - return; - - RemoveSourceByIndex( idx ); -} - -inline void CMouthInfo::RemoveSourceByIndex( int index ) -{ - if ( index < 0 || index >= m_nVoiceSources ) - return; - - m_VoiceSources[ index ] = m_VoiceSources[ --m_nVoiceSources ]; -} - -inline CVoiceData *CMouthInfo::AddSource( CAudioSource *source, bool bIgnorePhonemes ) -{ - int idx = GetIndexForSource( source ); - if ( idx == UNKNOWN_VOICE_SOURCE ) - { - if ( m_nVoiceSources < MAX_VOICE_DATA ) - { - idx = m_nVoiceSources++; - } - else - { - // No room! - return NULL; - } - } - - CVoiceData *data = &m_VoiceSources[ idx ]; - data->SetSource( source, bIgnorePhonemes ); - data->SetElapsedTime( 0.0f ); - return data; -} - -#endif // MOUTHINFO_H diff --git a/public/networkstringtabledefs.h b/public/networkstringtabledefs.h deleted file mode 100644 index 37fefe0f5..000000000 --- a/public/networkstringtabledefs.h +++ /dev/null @@ -1,80 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef NETWORKSTRINGTABLEDEFS_H -#define NETWORKSTRINGTABLEDEFS_H -#ifdef _WIN32 -#pragma once -#endif - -typedef int TABLEID; - -#define INVALID_STRING_TABLE -1 -const unsigned short INVALID_STRING_INDEX = (unsigned short )-1; - -// table index is sent in log2(MAX_TABLES) bits -#define MAX_TABLES 32 // Table id is 4 bits - -#define INTERFACENAME_NETWORKSTRINGTABLESERVER "VEngineServerStringTable001" -#define INTERFACENAME_NETWORKSTRINGTABLECLIENT "VEngineClientStringTable001" - -class INetworkStringTable; - -typedef void (*pfnStringChanged)( void *object, INetworkStringTable *stringTable, int stringNumber, char const *newString, void const *newData ); - -//----------------------------------------------------------------------------- -// Purpose: Game .dll shared string table interfaces -//----------------------------------------------------------------------------- -class INetworkStringTable -{ -public: - - virtual ~INetworkStringTable( void ) {}; - - // Table Info - virtual const char *GetTableName( void ) const = 0; - virtual TABLEID GetTableId( void ) const = 0; - virtual int GetNumStrings( void ) const = 0; - virtual int GetMaxStrings( void ) const = 0; - virtual int GetEntryBits( void ) const = 0; - - // Networking - virtual void SetTick( int tick ) = 0; - virtual bool ChangedSinceTick( int tick ) const = 0; - - // Accessors (length -1 means don't change user data if string already exits) - virtual int AddString( bool bIsServer, const char *value, int length = -1, const void *userdata = 0 ) = 0; - - virtual const char *GetString( int stringNumber ) = 0; - virtual void SetStringUserData( int stringNumber, int length, const void *userdata ) = 0; - virtual const void *GetStringUserData( int stringNumber, int *length ) = 0; - virtual int FindStringIndex( char const *string ) = 0; // returns INVALID_STRING_INDEX if not found - - // Callbacks - virtual void SetStringChangedCallback( void *object, pfnStringChanged changeFunc ) = 0; -}; - -class INetworkStringTableContainer -{ -public: - - virtual ~INetworkStringTableContainer( void ) {}; - - // table creation/destruction - virtual INetworkStringTable *CreateStringTable( const char *tableName, int maxentries, int userdatafixedsize = 0, int userdatanetworkbits = 0 ) = 0; - virtual void RemoveAllTables( void ) = 0; - - // table infos - virtual INetworkStringTable *FindTable( const char *tableName ) const = 0; - virtual INetworkStringTable *GetTable( TABLEID stringTable ) const = 0; - virtual int GetNumTables( void ) const = 0; - - virtual INetworkStringTable *CreateStringTableEx( const char *tableName, int maxentries, int userdatafixedsize = 0, int userdatanetworkbits = 0, bool bIsFilenames = false ) = 0; - virtual void SetAllowClientSideAddString( INetworkStringTable *table, bool bAllowClientSideAddString ) = 0; -}; - -#endif // NETWORKSTRINGTABLEDEFS_H diff --git a/public/networkvar.cpp b/public/networkvar.cpp deleted file mode 100644 index e96947c37..000000000 --- a/public/networkvar.cpp +++ /dev/null @@ -1,15 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#if !defined(_STATIC_LINKED) || defined(_SHARED_LIB) - - -bool g_bUseNetworkVars = true; - -#endif - - - diff --git a/public/networkvar.h b/public/networkvar.h deleted file mode 100644 index df212498e..000000000 --- a/public/networkvar.h +++ /dev/null @@ -1,768 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef NETWORKVAR_H -#define NETWORKVAR_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "tier0/dbg.h" -#include "convar.h" - -#if defined( CLIENT_DLL ) || defined( GAME_DLL ) - #include "basehandle.h" -#endif - -#ifdef _MSC_VER -#pragma warning( disable : 4284 ) // warning C4284: return type for 'CNetworkVarT::operator ->' is 'int *' (ie; not a UDT or reference to a UDT. Will produce errors if applied using infix notation) -#endif - -#define MyOffsetOf( type, var ) ( (int)&((type*)0)->var ) - -#ifdef _DEBUG - extern bool g_bUseNetworkVars; - #define CHECK_USENETWORKVARS if(g_bUseNetworkVars) -#else - #define CHECK_USENETWORKVARS // don't check for g_bUseNetworkVars -#endif - - - -inline int InternalCheckDeclareClass( const char *pClassName, const char *pClassNameMatch, void *pTestPtr, void *pBasePtr ) -{ - // This makes sure that casting from ThisClass to BaseClass works right. You'll get a compiler error if it doesn't - // work at all, and you'll get a runtime error if you use multiple inheritance. - Assert( pTestPtr == pBasePtr ); - - // This is triggered by IMPLEMENT_SERVER_CLASS. It does DLLClassName::CheckDeclareClass( #DLLClassName ). - // If they didn't do a DECLARE_CLASS in DLLClassName, then it'll be calling its base class's version - // and the class names won't match. - Assert( (void*)pClassName == (void*)pClassNameMatch ); - return 0; -} - - -template -inline int CheckDeclareClass_Access( T *, const char *pShouldBe ) -{ - return T::CheckDeclareClass( pShouldBe ); -} - -#ifndef _STATIC_LINKED -#ifdef _MSC_VER -#if defined(_DEBUG) && (_MSC_VER > 1200 ) - #define VALIDATE_DECLARE_CLASS 1 -#endif -#endif -#endif - -#ifdef VALIDATE_DECLARE_CLASS - - #define DECLARE_CLASS( className, baseClassName ) \ - typedef baseClassName BaseClass; \ - typedef className ThisClass; \ - template friend int CheckDeclareClass_Access(T *, const char *pShouldBe); \ - static int CheckDeclareClass( const char *pShouldBe ) \ - { \ - InternalCheckDeclareClass( pShouldBe, #className, (ThisClass*)0xFFFFF, (BaseClass*)(ThisClass*)0xFFFFF ); \ - return CheckDeclareClass_Access( (BaseClass *)NULL, #baseClassName ); \ - } - - // Use this macro when you have a base class, but it's part of a library that doesn't use network vars - // or any of the things that use ThisClass or BaseClass. - #define DECLARE_CLASS_GAMEROOT( className, baseClassName ) \ - typedef baseClassName BaseClass; \ - typedef className ThisClass; \ - template friend int CheckDeclareClass_Access(T *, const char *pShouldBe); \ - static int CheckDeclareClass( const char *pShouldBe ) \ - { \ - return InternalCheckDeclareClass( pShouldBe, #className, (ThisClass*)0xFFFFF, (BaseClass*)(ThisClass*)0xFFFFF ); \ - } - - // Deprecated macro formerly used to work around VC++98 bug - #define DECLARE_CLASS_NOFRIEND( className, baseClassName ) \ - DECLARE_CLASS( className, baseClassName ) - - #define DECLARE_CLASS_NOBASE( className ) \ - typedef className ThisClass; \ - template friend int CheckDeclareClass_Access(T *, const char *pShouldBe); \ - static int CheckDeclareClass( const char *pShouldBe ) \ - { \ - return InternalCheckDeclareClass( pShouldBe, #className, 0, 0 ); \ - } - -#else - #define DECLARE_CLASS( className, baseClassName ) \ - typedef baseClassName BaseClass; \ - typedef className ThisClass; - - #define DECLARE_CLASS_GAMEROOT( className, baseClassName ) DECLARE_CLASS( className, baseClassName ) - #define DECLARE_CLASS_NOFRIEND( className, baseClassName ) DECLARE_CLASS( className, baseClassName ) - - #define DECLARE_CLASS_NOBASE( className ) typedef className ThisClass; -#endif - - - - -// All classes that contain CNetworkVars need a NetworkStateChanged() function. If the class is not an entity, -// it needs to forward the call to the entity it's in. These macros can help. - - // These macros setup an entity pointer in your class. Use IMPLEMENT_NETWORKVAR_CHAIN before you do - // anything inside the class itself. - class CBaseEntity; - class CAutoInitEntPtr - { - public: - CAutoInitEntPtr() - { - m_pEnt = NULL; - } - CBaseEntity *m_pEnt; - }; - - //TODO: Currently, these don't get the benefit of tracking changes to individual vars. - // Would be nice if they did. - #define DECLARE_NETWORKVAR_CHAIN() \ - CAutoInitEntPtr __m_pChainEntity; \ - void NetworkStateChanged() { CHECK_USENETWORKVARS __m_pChainEntity.m_pEnt->NetworkStateChanged(); } \ - void NetworkStateChanged( void *pVar ) { CHECK_USENETWORKVARS __m_pChainEntity.m_pEnt->NetworkStateChanged(); } - - #define IMPLEMENT_NETWORKVAR_CHAIN( varName ) \ - (varName)->__m_pChainEntity.m_pEnt = this; - - - -// Use this macro when you want to embed a structure inside your entity and have CNetworkVars in it. -template< class T > -static inline void DispatchNetworkStateChanged( T *pObj ) -{ - CHECK_USENETWORKVARS pObj->NetworkStateChanged(); -} -template< class T > -static inline void DispatchNetworkStateChanged( T *pObj, void *pVar ) -{ - CHECK_USENETWORKVARS pObj->NetworkStateChanged( pVar ); -} - - -#define DECLARE_EMBEDDED_NETWORKVAR() \ - template friend int ServerClassInit(T *); \ - template friend int ClientClassInit(T *); \ - virtual void NetworkStateChanged() {} virtual void NetworkStateChanged( void *pProp ) {} - -// NOTE: Assignment operator is disabled because it doesn't call copy constructors of scalar types within the aggregate, so they are not marked changed -#define CNetworkVarEmbedded( type, name ) \ - class NetworkVar_##name; \ - friend class NetworkVar_##name; \ - static inline int GetOffset_##name() { return MyOffsetOf(ThisClass,name); } \ - typedef ThisClass ThisClass_##name; \ - class NetworkVar_##name : public type \ - { \ - template< class T > NetworkVar_##name& operator=( const T &val ) { *((type*)this) = val; return *this; } \ - public: \ - void CopyFrom( const type &src ) { *((type *)this) = src; NetworkStateChanged(); } \ - virtual void NetworkStateChanged() \ - { \ - DispatchNetworkStateChanged( (ThisClass_##name*)( ((char*)this) - GetOffset_##name() ) ); \ - } \ - virtual void NetworkStateChanged( void *pVar ) \ - { \ - DispatchNetworkStateChanged( (ThisClass_##name*)( ((char*)this) - GetOffset_##name() ), pVar ); \ - } \ - }; \ - NetworkVar_##name name; - - - -template< class Type, class Changer > -class CNetworkVarBase -{ -public: - template< class C > - const Type& operator=( const C &val ) - { - return Set( ( const Type )val ); - } - - template< class C > - const Type& operator=( const CNetworkVarBase< C, Changer > &val ) - { - return Set( ( const Type )val.m_Value ); - } - - const Type& Set( const Type &val ) - { - if ( memcmp( &m_Value, &val, sizeof(Type) ) ) - { - NetworkStateChanged(); - m_Value = val; - } - return m_Value; - } - - Type& GetForModify() - { - NetworkStateChanged(); - return m_Value; - } - - template< class C > - const Type& operator+=( const C &val ) - { - return Set( m_Value + ( const Type )val ); - } - - template< class C > - const Type& operator-=( const C &val ) - { - return Set( m_Value - ( const Type )val ); - } - - template< class C > - const Type& operator/=( const C &val ) - { - return Set( m_Value / ( const Type )val ); - } - - template< class C > - const Type& operator*=( const C &val ) - { - return Set( m_Value * ( const Type )val ); - } - - template< class C > - const Type& operator^=( const C &val ) - { - return Set( m_Value ^ ( const Type )val ); - } - - template< class C > - const Type& operator|=( const C &val ) - { - return Set( m_Value | ( const Type )val ); - } - - const Type& operator++() - { - return (*this += 1); - } - - Type operator--() - { - return (*this -= 1); - } - - Type operator++( int ) // postfix version.. - { - Type val = m_Value; - (*this += 1); - return val; - } - - Type operator--( int ) // postfix version.. - { - Type val = m_Value; - (*this -= 1); - return val; - } - - // For some reason the compiler only generates type conversion warnings for this operator when used like - // CNetworkVarBase = 0x1 - // (it warns about converting from an int to an unsigned char). - template< class C > - const Type& operator&=( const C &val ) - { - return Set( m_Value & ( const Type )val ); - } - - operator const Type&() const - { - return m_Value; - } - - const Type& Get() const - { - return m_Value; - } - - const Type* operator->() const - { - return &m_Value; - } - - Type m_Value; - -protected: - inline void NetworkStateChanged() - { - Changer::NetworkStateChanged( this ); - } -}; - - -template< class Type, class Changer > -class CNetworkColor32Base : public CNetworkVarBase< Type, Changer > -{ -public: - inline void Init( byte rVal, byte gVal, byte bVal ) - { - SetR( rVal ); - SetG( gVal ); - SetB( bVal ); - } - inline void Init( byte rVal, byte gVal, byte bVal, byte aVal ) - { - SetR( rVal ); - SetG( gVal ); - SetB( bVal ); - SetA( aVal ); - } - - const Type& operator=( const Type &val ) - { - return Set( val ); - } - - const Type& operator=( const CNetworkColor32Base &val ) - { - return CNetworkVarBase::Set( val.m_Value ); - } - - inline byte GetR() const { return CNetworkColor32Base::m_Value.r; } - inline byte GetG() const { return CNetworkColor32Base::m_Value.g; } - inline byte GetB() const { return CNetworkColor32Base::m_Value.b; } - inline byte GetA() const { return CNetworkColor32Base::m_Value.a; } - inline void SetR( byte val ) { SetVal( CNetworkColor32Base::m_Value.r, val ); } - inline void SetG( byte val ) { SetVal( CNetworkColor32Base::m_Value.g, val ); } - inline void SetB( byte val ) { SetVal( CNetworkColor32Base::m_Value.b, val ); } - inline void SetA( byte val ) { SetVal( CNetworkColor32Base::m_Value.a, val ); } - -protected: - inline void SetVal( byte &out, const byte &in ) - { - if ( out != in ) - { - this->NetworkStateChanged(); - out = in; - } - } -}; - - -// Network vector wrapper. -template< class Type, class Changer > -class CNetworkVectorBase : public CNetworkVarBase< Type, Changer > -{ -public: - inline void Init( float ix=0, float iy=0, float iz=0 ) - { - SetX( ix ); - SetY( iy ); - SetZ( iz ); - } - - const Type& operator=( const Type &val ) - { - return CNetworkVarBase< Type, Changer >::Set( val ); - } - - const Type& operator=( const CNetworkVectorBase &val ) - { - return CNetworkVarBase::Set( val.m_Value ); - } - - inline float GetX() const { return CNetworkVectorBase::m_Value.x; } - inline float GetY() const { return CNetworkVectorBase::m_Value.y; } - inline float GetZ() const { return CNetworkVectorBase::m_Value.z; } - inline float operator[]( int i ) const { return CNetworkVectorBase::m_Value[i]; } - - inline void SetX( float val ) { DetectChange( CNetworkVectorBase::m_Value.x, val ); } - inline void SetY( float val ) { DetectChange( CNetworkVectorBase::m_Value.y, val ); } - inline void SetZ( float val ) { DetectChange( CNetworkVectorBase::m_Value.z, val ); } - inline void Set( int i, float val ) { DetectChange( CNetworkVectorBase::m_Value[i], val ); } - - bool operator==( const Type &val ) const - { - return CNetworkVectorBase::m_Value == (Type)val; - } - - bool operator!=( const Type &val ) const - { - return CNetworkVectorBase::m_Value != (Type)val; - } - - const Type operator+( const Type &val ) const - { - return CNetworkVectorBase::m_Value + val; - } - - const Type operator-( const Type &val ) const - { - return CNetworkVectorBase::m_Value - val; - } - - const Type operator*( const Type &val ) const - { - return CNetworkVectorBase::m_Value * val; - } - - const Type& operator*=( float val ) - { - return CNetworkVarBase< Type, Changer >::Set( CNetworkVectorBase::m_Value * val ); - } - - const Type operator*( float val ) const - { - return CNetworkVectorBase::m_Value * val; - } - - const Type operator/( const Type &val ) const - { - return CNetworkVectorBase::m_Value / val; - } - -private: - inline void DetectChange( float &out, float in ) - { - if ( out != in ) - { - this->NetworkStateChanged(); - out = in; - } - } -}; - - -// Network vector wrapper. -template< class Type, class Changer > -class CNetworkQuaternionBase : public CNetworkVarBase< Type, Changer > -{ -public: - inline void Init( float ix=0, float iy=0, float iz=0, float iw = 0 ) - { - SetX( ix ); - SetY( iy ); - SetZ( iz ); - SetZ( iw ); - } - - const Type& operator=( const Type &val ) - { - return CNetworkVarBase< Type, Changer >::Set( val ); - } - - const Type& operator=( const CNetworkQuaternionBase &val ) - { - return CNetworkVarBase::Set( val.m_Value ); - } - - inline float GetX() const { return CNetworkQuaternionBase::m_Value.x; } - inline float GetY() const { return CNetworkQuaternionBase::m_Value.y; } - inline float GetZ() const { return CNetworkQuaternionBase::m_Value.z; } - inline float GetW() const { return CNetworkQuaternionBase::m_Value.w; } - inline float operator[]( int i ) const { return CNetworkQuaternionBase::m_Value[i]; } - - inline void SetX( float val ) { DetectChange( CNetworkQuaternionBase::m_Value.x, val ); } - inline void SetY( float val ) { DetectChange( CNetworkQuaternionBase::m_Value.y, val ); } - inline void SetZ( float val ) { DetectChange( CNetworkQuaternionBase::m_Value.z, val ); } - inline void SetW( float val ) { DetectChange( CNetworkQuaternionBase::m_Value.w, val ); } - inline void Set( int i, float val ) { DetectChange( CNetworkQuaternionBase::m_Value[i], val ); } - - bool operator==( const Type &val ) const - { - return CNetworkQuaternionBase::m_Value == (Type)val; - } - - bool operator!=( const Type &val ) const - { - return CNetworkQuaternionBase::m_Value != (Type)val; - } - - const Type operator+( const Type &val ) const - { - return CNetworkQuaternionBase::m_Value + val; - } - - const Type operator-( const Type &val ) const - { - return CNetworkQuaternionBase::m_Value - val; - } - - const Type operator*( const Type &val ) const - { - return CNetworkQuaternionBase::m_Value * val; - } - - const Type& operator*=( float val ) - { - return CNetworkQuaternionBase< Type, Changer >::Set( CNetworkQuaternionBase::m_Value * val ); - } - - const Type operator*( float val ) const - { - return CNetworkQuaternionBase::m_Value * val; - } - - const Type operator/( const Type &val ) const - { - return CNetworkQuaternionBase::m_Value / val; - } - -private: - inline void DetectChange( float &out, float in ) - { - if ( out != in ) - { - this->NetworkStateChanged(); - out = in; - } - } -}; - - -// Network ehandle wrapper. -#if defined( CLIENT_DLL ) || defined( GAME_DLL ) - template< class Type, class Changer > - class CNetworkHandleBase : public CNetworkVarBase< CBaseHandle, Changer > - { - public: - const Type* operator=( const Type *val ) - { - return Set( val ); - } - - const Type& operator=( const CNetworkHandleBase &val ) - { - const CBaseHandle &handle = CNetworkVarBase::Set( val.m_Value ); - return *(const Type*)handle.Get(); - } - - bool operator !() const - { - return !CNetworkHandleBase::m_Value.Get(); - } - - operator Type*() const - { - return static_cast< Type* >( CNetworkHandleBase::m_Value.Get() ); - } - - const Type* Set( const Type *val ) - { - if ( CNetworkHandleBase::m_Value != val ) - { - this->NetworkStateChanged(); - CNetworkHandleBase::m_Value = val; - } - return val; - } - - Type* Get() const - { - return static_cast< Type* >( CNetworkHandleBase::m_Value.Get() ); - } - - Type* operator->() const - { - return static_cast< Type* >( CNetworkHandleBase::m_Value.Get() ); - } - - bool operator==( const Type *val ) const - { - return CNetworkHandleBase::m_Value == val; - } - - bool operator!=( const Type *val ) const - { - return CNetworkHandleBase::m_Value != val; - } - }; - - - - #define CNetworkHandle( type, name ) CNetworkHandleInternal( type, name, NetworkStateChanged ) - - #define CNetworkHandleInternal( type, name, stateChangedFn ) \ - NETWORK_VAR_START( type, name ) \ - NETWORK_VAR_END( type, name, CNetworkHandleBase, stateChangedFn ) -#endif - - -// Use this macro to define a network variable. -#define CNetworkVar( type, name ) \ - NETWORK_VAR_START( type, name ) \ - NETWORK_VAR_END( type, name, CNetworkVarBase, NetworkStateChanged ) - - -// Use this macro when you have a base class with a variable, and it doesn't have that variable in a SendTable, -// but a derived class does. Then, the entity is only flagged as changed when the variable is changed in -// an entity that wants to transmit the variable. - #define CNetworkVarForDerived( type, name ) \ - virtual void NetworkStateChanged_##name() {} \ - virtual void NetworkStateChanged_##name( void *pVar ) {} \ - NETWORK_VAR_START( type, name ) \ - NETWORK_VAR_END( type, name, CNetworkVarBase, NetworkStateChanged_##name ) - - #define CNetworkVectorForDerived( name ) \ - virtual void NetworkStateChanged_##name() {} \ - virtual void NetworkStateChanged_##name( void *pVar ) {} \ - CNetworkVectorInternal( Vector, name, NetworkStateChanged_##name ) - - #define CNetworkHandleForDerived( type, name ) \ - virtual void NetworkStateChanged_##name() {} \ - virtual void NetworkStateChanged_##name( void *pVar ) {} \ - CNetworkHandleInternal( type, name, NetworkStateChanged_##name ) - - #define CNetworkArrayForDerived( type, name, count ) \ - virtual void NetworkStateChanged_##name() {} \ - virtual void NetworkStateChanged_##name( void *pVar ) {} \ - CNetworkArrayInternal( type, name, count, NetworkStateChanged_##name ) - - #define IMPLEMENT_NETWORK_VAR_FOR_DERIVED( name ) \ - virtual void NetworkStateChanged_##name() { CHECK_USENETWORKVARS NetworkStateChanged(); } \ - virtual void NetworkStateChanged_##name( void *pVar ) { CHECK_USENETWORKVARS NetworkStateChanged( pVar ); } - - -// This virtualizes the change detection on the variable, but it is ON by default. -// Use this when you have a base class in which MOST of its derived classes use this variable -// in their SendTables, but there are a couple that don't (and they -// can use DISABLE_NETWORK_VAR_FOR_DERIVED). - #define CNetworkVarForDerived_OnByDefault( type, name ) \ - virtual void NetworkStateChanged_##name() { CHECK_USENETWORKVARS NetworkStateChanged(); } \ - virtual void NetworkStateChanged_##name( void *pVar ) { CHECK_USENETWORKVARS NetworkStateChanged( pVar ); } \ - NETWORK_VAR_START( type, name ) \ - NETWORK_VAR_END( type, name, CNetworkVarBase, NetworkStateChanged_##name ) - - #define DISABLE_NETWORK_VAR_FOR_DERIVED( name ) \ - virtual void NetworkStateChanged_##name() {} \ - virtual void NetworkStateChanged_##name( void *pVar ) {} - - - -// Vectors + some convenient helper functions. -#define CNetworkVector( name ) CNetworkVectorInternal( Vector, name, NetworkStateChanged ) -#define CNetworkQAngle( name ) CNetworkVectorInternal( QAngle, name, NetworkStateChanged ) - -#define CNetworkVectorInternal( type, name, stateChangedFn ) \ - NETWORK_VAR_START( type, name ) \ - NETWORK_VAR_END( type, name, CNetworkVectorBase, stateChangedFn ) - -#define CNetworkQuaternion( name ) \ - NETWORK_VAR_START( Quaternion, name ) \ - NETWORK_VAR_END( Quaternion, name, CNetworkQuaternionBase, NetworkStateChanged ) - -// Helper for color32's. Contains GetR(), SetR(), etc.. functions. -#define CNetworkColor32( name ) \ - NETWORK_VAR_START( color32, name ) \ - NETWORK_VAR_END( color32, name, CNetworkColor32Base, NetworkStateChanged ) - - -#define CNetworkString( name, length ) \ - class NetworkVar_##name; \ - friend class NetworkVar_##name; \ - typedef ThisClass MakeANetworkVar_##name; \ - class NetworkVar_##name \ - { \ - public: \ - operator const char*() const { return m_Value; } \ - const char* Get() const { return m_Value; } \ - char* GetForModify() \ - { \ - NetworkStateChanged(); \ - return m_Value; \ - } \ - protected: \ - inline void NetworkStateChanged() \ - { \ - CHECK_USENETWORKVARS ((ThisClass*)(((char*)this) - MyOffsetOf(ThisClass,name)))->NetworkStateChanged(); \ - } \ - private: \ - char m_Value[length]; \ - }; \ - NetworkVar_##name name; - - - - -// Use this to define networked arrays. -// You can access elements for reading with operator[], and you can set elements with the Set() function. -#define CNetworkArrayInternal( type, name, count, stateChangedFn ) \ - class NetworkVar_##name; \ - friend class NetworkVar_##name; \ - typedef ThisClass MakeANetworkVar_##name; \ - class NetworkVar_##name \ - { \ - public: \ - template friend int ServerClassInit(T *); \ - template friend datamap_t *DataMapInit(T *); \ - const type& operator[]( int i ) const \ - { \ - return Get( i ); \ - } \ - \ - const type& Get( int i ) const \ - { \ - Assert( i >= 0 && i < count ); \ - return m_Value[i]; \ - } \ - \ - type& GetForModify( int i ) \ - { \ - Assert( i >= 0 && i < count ); \ - NetworkStateChanged( i ); \ - return m_Value[i]; \ - } \ - \ - void Set( int i, const type &val ) \ - { \ - Assert( i >= 0 && i < count ); \ - if( memcmp( &m_Value[i], &val, sizeof(type) ) ) \ - { \ - NetworkStateChanged( i ); \ - m_Value[i] = val; \ - } \ - } \ - const type* Base() const { return m_Value; } \ - int Count() const { return count; } \ - protected: \ - inline void NetworkStateChanged( int index ) \ - { \ - CHECK_USENETWORKVARS ((ThisClass*)(((char*)this) - MyOffsetOf(ThisClass,name)))->stateChangedFn( &m_Value[index] ); \ - } \ - type m_Value[count]; \ - }; \ - NetworkVar_##name name; - - -#define CNetworkArray( type, name, count ) CNetworkArrayInternal( type, name, count, NetworkStateChanged ) - - -// Internal macros used in definitions of network vars. -#define NETWORK_VAR_START( type, name ) \ - class NetworkVar_##name; \ - friend class NetworkVar_##name; \ - typedef ThisClass MakeANetworkVar_##name; \ - class NetworkVar_##name \ - { \ - public: \ - template friend int ServerClassInit(T *); - - -#define NETWORK_VAR_END( type, name, base, stateChangedFn ) \ - public: \ - static inline void NetworkStateChanged( void *ptr ) \ - { \ - CHECK_USENETWORKVARS ((ThisClass*)(((char*)ptr) - MyOffsetOf(ThisClass,name)))->stateChangedFn( ptr ); \ - } \ - }; \ - base< type, NetworkVar_##name > name; - - - -#endif // NETWORKVAR_H diff --git a/public/nmatrix.h b/public/nmatrix.h deleted file mode 100644 index 5d588da5f..000000000 --- a/public/nmatrix.h +++ /dev/null @@ -1,332 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef NMATRIX_H -#define NMATRIX_H -#ifdef _WIN32 -#pragma once -#endif - - -#include -#include "nvector.h" - - -#define NMatrixMN NMatrix - - -template -class NMatrix -{ -public: - - NMatrixMN() {} - - static NMatrixMN SetupNMatrixNull(); // Return a matrix of all zeros. - static NMatrixMN SetupNMatrixIdentity(); // Return an identity matrix. - - NMatrixMN const& operator=( NMatrixMN const &other ); - - NMatrixMN operator+( NMatrixMN const &v ) const; - NMatrixMN const& operator+=( NMatrixMN const &v ); - - NMatrixMN operator-() const; - NMatrixMN operator-( NMatrixMN const &v ) const; - - // Multiplies the column vector on the right-hand side. - NVector operator*( NVector const &v ) const; - - // Can't get the compiler to work with a real MxN * NxR matrix multiply... - NMatrix operator*( NMatrix const &b ) const; - - NMatrixMN operator*( float val ) const; - - bool InverseGeneral( NMatrixMN &mInverse ) const; - NMatrix Transpose() const; - - -public: - - float m[M][N]; -}; - - - -// Return the matrix generated by multiplying a column vector 'a' by row vector 'b'. -template -inline NMatrix OuterProduct( NVectorN const &a, NVectorN const &b ) -{ - NMatrix ret; - - for( int i=0; i < N; i++ ) - for( int j=0; j < N; j++ ) - ret.m[i][j] = a.v[i] * b.v[j]; - - return ret; -} - - -// -------------------------------------------------------------------------------- // -// NMatrix inlines. -// -------------------------------------------------------------------------------- // - -template -inline NMatrixMN NMatrixMN::SetupNMatrixNull() -{ - NMatrix ret; - memset( ret.m, 0, sizeof(float)*M*N ); - return ret; -} - - -template -inline NMatrixMN NMatrixMN::SetupNMatrixIdentity() -{ - assert( M == N ); // Identity matrices must be square. - - NMatrix ret; - memset( ret.m, 0, sizeof(float)*M*N ); - for( int i=0; i < N; i++ ) - ret.m[i][i] = 1; - return ret; -} - - -template -inline NMatrixMN const &NMatrixMN::operator=( NMatrixMN const &v ) -{ - memcpy( m, v.m, sizeof(float)*M*N ); - return *this; -} - - -template -inline NMatrixMN NMatrixMN::operator+( NMatrixMN const &v ) const -{ - NMatrixMN ret; - for( int i=0; i < M; i++ ) - for( int j=0; j < N; j++ ) - ret.m[i][j] = m[i][j] + v.m[i][j]; - - return ret; -} - - -template -inline NMatrixMN const &NMatrixMN::operator+=( NMatrixMN const &v ) -{ - for( int i=0; i < M; i++ ) - for( int j=0; j < N; j++ ) - m[i][j] += v.m[i][j]; - - return *this; -} - - -template -inline NMatrixMN NMatrixMN::operator-() const -{ - NMatrixMN ret; - - for( int i=0; i < M*N; i++ ) - ((float*)ret.m)[i] = -((float*)m)[i]; - - return ret; -} - - -template -inline NMatrixMN NMatrixMN::operator-( NMatrixMN const &v ) const -{ - NMatrixMN ret; - for( int i=0; i < M; i++ ) - for( int j=0; j < N; j++ ) - ret.m[i][j] = m[i][j] - v.m[i][j]; - return ret; -} - - -template -inline NVector NMatrixMN::operator*( NVectorN const &v ) const -{ - NVectorN ret; - - for( int i=0; i < M; i++ ) - { - ret.v[i] = 0; - - for( int j=0; j < N; j++ ) - ret.v[i] += m[i][j] * v.v[j]; - } - - return ret; -} - - -template -inline NMatrix NMatrixMN::operator*( NMatrix const &b ) const -{ - NMatrix ret; - - for( int myRow=0; myRow < M; myRow++ ) - { - for( int otherCol=0; otherCol < M; otherCol++ ) - { - ret[myRow][otherCol] = 0; - for( int i=0; i < N; i++ ) - ret[myRow][otherCol] += a.m[myRow][i] * b.m[i][otherCol]; - } - } - - return ret; -} - - -template -inline NMatrixMN NMatrixMN::operator*( float val ) const -{ - NMatrixMN ret; - - for( int i=0; i < N*M; i++ ) - ((float*)ret.m)[i] = ((float*)m)[i] * val; - - return ret; -} - - -template -bool NMatrixMN::InverseGeneral( NMatrixMN &mInverse ) const -{ - int iRow, i, j, iTemp, iTest; - float mul, fTest, fLargest; - float mat[N][2*N]; - int rowMap[N], iLargest; - float *pOut, *pRow, *pScaleRow; - - - // Can only invert square matrices. - if( M != N ) - { - assert( !"Tried to invert a non-square matrix" ); - return false; - } - - - // How it's done. - // AX = I - // A = this - // X = the matrix we're looking for - // I = identity - - // Setup AI - for(i=0; i < N; i++) - { - const float *pIn = m[i]; - pOut = mat[i]; - - for(j=0; j < N; j++) - { - pOut[j] = pIn[j]; - } - - for(j=N; j < 2*N; j++) - pOut[j] = 0; - - pOut[i+N] = 1.0f; - - rowMap[i] = i; - } - - // Use row operations to get to reduced row-echelon form using these rules: - // 1. Multiply or divide a row by a nonzero number. - // 2. Add a multiple of one row to another. - // 3. Interchange two rows. - - for(iRow=0; iRow < N; iRow++) - { - // Find the row with the largest element in this column. - fLargest = 0.001f; - iLargest = -1; - for(iTest=iRow; iTest < N; iTest++) - { - fTest = (float)fabs(mat[rowMap[iTest]][iRow]); - if(fTest > fLargest) - { - iLargest = iTest; - fLargest = fTest; - } - } - - // They're all too small.. sorry. - if(iLargest == -1) - { - return false; - } - - // Swap the rows. - iTemp = rowMap[iLargest]; - rowMap[iLargest] = rowMap[iRow]; - rowMap[iRow] = iTemp; - - pRow = mat[rowMap[iRow]]; - - // Divide this row by the element. - mul = 1.0f / pRow[iRow]; - for(j=0; j < 2*N; j++) - pRow[j] *= mul; - - pRow[iRow] = 1.0f; // Preserve accuracy... - - // Eliminate this element from the other rows using operation 2. - for(i=0; i < N; i++) - { - if(i == iRow) - continue; - - pScaleRow = mat[rowMap[i]]; - - // Multiply this row by -(iRow*the element). - mul = -pScaleRow[iRow]; - for(j=0; j < 2*N; j++) - { - pScaleRow[j] += pRow[j] * mul; - } - - pScaleRow[iRow] = 0.0f; // Preserve accuracy... - } - } - - // The inverse is on the right side of AX now (the identity is on the left). - for(i=0; i < N; i++) - { - const float *pIn = mat[rowMap[i]] + N; - pOut = mInverse.m[i]; - - for(j=0; j < N; j++) - { - pOut[j] = pIn[j]; - } - } - - return true; -} - - -template -inline NMatrix NMatrixMN::Transpose() const -{ - NMatrix ret; - - for( int i=0; i < M; i++ ) - for( int j=0; j < N; j++ ) - ret.m[j][i] = m[i][j]; - - return ret; -} - -#endif // NMATRIX_H - diff --git a/public/ntree.h b/public/ntree.h deleted file mode 100644 index ef5b7257a..000000000 --- a/public/ntree.h +++ /dev/null @@ -1,316 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef __TREE_H__ -#define __TREE_H__ - -#include "List.h" -#include "ArrayStack.h" - -// NTreeNode: Class decleration and definition -template class NTreeNode -{ -public: - // constructor - NTreeNode( T data ); - - NTreeNode *PrependChild( NTreeNode *node ); - NTreeNode *AppendChild( NTreeNode *node ); - NTreeNode *InsertChildAfterIndex( NTreeNode *node, int index ); - NTreeNode *InsertChildBeforeIndex( NTreeNode *node, int index ); - NTreeNode *RemoveChild( Position position ); - NTreeNode *RemoveChild( int index ); - Position InsertAfter( NTreeNode *node, Position position ); - Position InsertBefore( NTreeNode *node, Position position ); - int GetNumChildren(); - Position GetChildPosition( int childNum ); - NTreeNode *GetChild( int childNum ); - NTreeNode *GetChild( Position position ); - int GetIndexRelativeToParent(); - T GetItem(); - NTreeNode *GetParent(); - NTreeNode *GetRoot(); - NTreeNode *GetNextSibling(); - void Traverse( void (*VisitFunc)( T, int depth ), int maxTreeDepth ); - NTreeNode *ReentrantTraversalGetFirst( int maxTreeDepth ); - NTreeNode *ReentrantTraversalGetNext( void ); - -protected: - GList * > *list; - T data; - NTreeNode *parent; - ArrayStack *> *reentrantStack; -}; - -template -NTreeNode::NTreeNode( T data ) -{ - list = new GList * >; - this->data = data; - this->parent = NULL; - this->reentrantStack = NULL; -} - -template -NTreeNode *NTreeNode::PrependChild( NTreeNode *node ) -{ - node->parent = this; - return list->GetItemAtPosition( list->InsertAtHead( node ) ); -} - -template -NTreeNode *NTreeNode::AppendChild( NTreeNode *node ) -{ - node->parent = this; - return list->GetItemAtPosition( list->InsertAtTail( node ) ); -} - -template -NTreeNode *NTreeNode::InsertChildAfterIndex( NTreeNode *node, int index ) -{ - node->parent = this; - if( index < 0 ) - { - // if out of range in the negative direction, prepend - this->PrependChild( node ); - } - else if( index > list->GetNumItems() - 1 ) - { - // if out of range, just append. - this->AppendChild( node ); - } - else - { - Position pos; - pos = list->GetPositionAtIndex( index ); - list->InsertAfter( node, pos ); - } - return node; -} - -template -NTreeNode *NTreeNode::InsertChildBeforeIndex( NTreeNode *node, int index ) -{ - node->parent = this; - if( index < 0 ) - { - // if out of range in the negative direction, prepend - this->PrependChild( node ); - } - else if( index > list->GetNumItems() - 1 ) - { - // if out of range, just append. - this->AppendChild( node ); - } - else - { - Position pos; - pos = list->GetPositionAtIndex( index ); - list->InsertBefore( node, pos ); - } - return node; -} - -template -NTreeNode *NTreeNode::RemoveChild( Position position ) -{ - NTreeNode **node = ( NTreeNode ** )( void * )position; - ( *node )->parent = NULL; - return list->Remove( position ); -} - -template -NTreeNode *NTreeNode::RemoveChild( int index ) -{ - Position position = list->GetPositionAtIndex( index ); - NTreeNode **node = ( NTreeNode ** )( void * )position; - ( *node )->parent = NULL; - return list->Remove( position ); -} - -template -Position NTreeNode::InsertAfter( NTreeNode *node, Position position ) -{ - node->parent = this; - return list->InsertAfter( node, position ); -} - -template -Position NTreeNode::InsertBefore( NTreeNode *node, Position position ) -{ - node->parent = this; - return list->InsertBefore( node, position ); -} - -template -int NTreeNode::GetNumChildren() -{ - return list->GetNumItems(); -} - -template -Position NTreeNode::GetChildPosition( int childNum ) -{ - return list->GetPositionAtIndex( childNum ); -} - -template -NTreeNode *NTreeNode::GetChild( int childNum ) -{ - return list->GetItemAtIndex( childNum ); -} - -template -NTreeNode *NTreeNode::GetChild( Position position ) -{ - return list->GetItemAtIndex( position ); -} - -template -int NTreeNode::GetIndexRelativeToParent() -{ - if( !parent ) - { - assert( 0 ); // hack - return -1; - } - GListIterator *> iterator( parent->list ); - int i; - for( i = 0, iterator.GotoHead(); !iterator.AtEnd(); iterator++, i++ ) - { - if( iterator.GetCurrent() == this ) - { - return i; - } - } - assert( 0 ); // hack - return -1; -} - -template -T NTreeNode::GetItem() -{ - return data; -} - -template -NTreeNode *NTreeNode::GetParent() -{ - return parent; -} - -template -NTreeNode *NTreeNode::GetRoot() -{ - NTreeNode *node; - node = this; - while( node->GetParent() ) - { - node = node->GetParent(); - } - return node; -} - -template -NTreeNode *NTreeNode::GetNextSibling() -{ - int currentID, siblingID; - NTreeNode *parent; - parent = this->GetParent(); - if( !parent ) - { - return NULL; - } - currentID = this->GetIndexRelativeToParent(); - siblingID = currentID + 1; - if( siblingID < parent->GetNumChildren() ) - { - return parent->GetChild( siblingID ); - } - else - { - return NULL; - } -} - -template -void NTreeNode::Traverse( void (*VisitFunc)( T, int depth ), int maxTreeDepth ) -{ - ArrayStack *> stack( maxTreeDepth ); - NTreeNode *current, *nextSibling; - - stack.Push( this ); - Visit( this->GetItem(), 0 ); - while( !stack.IsEmpty() ) - { - current = stack.Pop(); - if( current->GetNumChildren() > 0 ) - { - stack.Push( current ); - stack.Push( current->GetChild( 0 ) ); - Visit( current->GetChild( 0 )->GetItem(), stack.GetDepth() - 1 ); - } - else - { - while( !stack.IsEmpty() && !( nextSibling = current->GetNextSibling() ) ) - { - current = stack.Pop(); - } - if( !stack.IsEmpty() ) - { - stack.Push( nextSibling ); - Visit( nextSibling->GetItem(), stack.GetDepth() - 1 ); - } - } - } -} - -template -NTreeNode *NTreeNode::ReentrantTraversalGetFirst( int maxTreeDepth ) -{ - if( reentrantStack ) - { - delete reentrantStack; - } - reentrantStack = new ArrayStack *>( maxTreeDepth ); - reentrantStack->Push( this ); - return this; -} - -template -NTreeNode *NTreeNode::ReentrantTraversalGetNext( void ) -{ - NTreeNode *current, *nextSibling; - - while( !reentrantStack->IsEmpty() ) - { - current = reentrantStack->Pop(); - if( current->GetNumChildren() > 0 ) - { - reentrantStack->Push( current ); - reentrantStack->Push( current->GetChild( 0 ) ); - return current->GetChild( 0 ); - } - else - { - while( !reentrantStack->IsEmpty() && !( nextSibling = current->GetNextSibling() ) ) - { - current = reentrantStack->Pop(); - } - if( !reentrantStack->IsEmpty() ) - { - reentrantStack->Push( nextSibling ); - return nextSibling; - } - } - } - delete reentrantStack; - reentrantStack = NULL; - return NULL; -} - -#endif /* __TREE_H__ */ diff --git a/public/nvector.h b/public/nvector.h deleted file mode 100644 index 95813b9e4..000000000 --- a/public/nvector.h +++ /dev/null @@ -1,203 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef NVECTOR_H -#define NVECTOR_H -#ifdef _WIN32 -#pragma once -#endif - - -#include - - -#define NVectorN NVector -#define NVector3 NVector<3> - - -// N-dimensional vector. -template -class NVector -{ -public: - - NVectorN() {} - - float& operator[]( int i ); - float const& operator[]( int i ) const; - - float Dot( NVectorN const &b ) const; - NVectorN Cross( NVectorN const &b ) const; - NVectorN Normalize() const; - float Length() const; - - NVectorN operator-() const; - NVectorN operator+( NVectorN const &b ) const; - NVectorN const &operator+=( NVectorN const &b ); - NVectorN operator-( NVectorN const &b ) const; - NVectorN operator*( float val ) const; - - -// Static helpers. -public: - - static NVectorN SetupNVectorNull(); // Returns a vector of all zeros. - - -public: - - float v[N]; -}; - - -template -inline float NDot( NVector const &a, NVector const &b ) -{ - float ret = 0; - for( int i=0; i < N; i++ ) - ret += a.v[i] * b.v[i]; - return ret; -} - -template -Vector& ToVec( NVector &vec ) {assert( N >= 3 ); return *((Vector*)&vec);} - -template -Vector const& ToVec( NVector const &vec ){assert( N >= 3 ); return *((Vector const*)&vec);} - -NVector<3>& ToNVec( Vector &vec ) {return *((NVector<3>*)&vec);} -NVector<3> const& ToNVec( Vector const &vec ) {return *((NVector<3> const*)&vec);} - - -// ------------------------------------------------------------------------------------ // -// NVector inlines. -// ------------------------------------------------------------------------------------ // - -template -NVectorN NVectorN::SetupNVectorNull() -{ - NVector ret; - memset( ret.v, 0, sizeof(float)*N ); - return ret; -} - - -template -float& NVectorN::operator[]( int i ) -{ - assert( i >= 0 && i < N ); - return v[i]; -} - - -template -float const& NVectorN::operator[]( int i ) const -{ - assert( i >= 0 && i < N ); - return v[i]; -} - - -template -float NVectorN::Dot( NVectorN const &b ) const -{ - float ret = 0; - - for( int i=0; i < N; i++ ) - ret += v[i]*b.v[i]; - - return ret; -} - - -template -NVectorN NVectorN::Cross( NVectorN const &b ) const -{ - NVector ret; - NMatrix mat; - - for( int i=0; i < N; i++ ) - { - for( y=0; y < N; y++ ) - for( x=0; x < N; x++ ) - mat.m[y][x] = - - ret.v[i] = v[i]*b.v[i]; - } - - return ret; -} - - -template -NVectorN NVectorN::Normalize() const -{ - return *this * (1.0f / Length()); -} - - -template -float NVectorN::Length() const -{ - return (float)sqrt( Dot(*this) ); -} - - -template -NVectorN NVectorN::operator-() const -{ - NVectorN ret; - for( int i=0; i < N; i++ ) - ret.v[i] = -v[i]; - return ret; -} - - -template -NVectorN NVectorN::operator+( NVectorN const &b ) const -{ - NVectorN ret; - - for( int i=0; i < N; i++ ) - ret.v[i] = v[i]+b.v[i]; - - return ret; -} - - -template -NVectorN const &NVectorN::operator+=( NVectorN const &b ) -{ - for( int i=0; i < N; i++ ) - v[i] += b.v[i]; - return *this; -} - - -template -NVectorN NVectorN::operator-( NVectorN const &b ) const -{ - NVectorN ret; - - for( int i=0; i < N; i++ ) - ret.v[i] = v[i]-b.v[i]; - - return ret; -} - -template -NVectorN NVectorN::operator*( float val ) const -{ - NVectorN ret; - for( int i=0; i < N; i++ ) - ret.v[i] = v[i] * val; - return ret; -} - - -#endif // NVECTOR_H - diff --git a/public/nvtc.h b/public/nvtc.h deleted file mode 100644 index df3900acd..000000000 --- a/public/nvtc.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 1997-8 S3 Inc. All Rights Reserved. - * - * Module Name: s3_intrf.h - * - * Purpose: Constant, structure, and prototype definitions for S3TC - * interface to DX surface - * - * Author: Dan Hung, Martin Hoffesommer - * - * Revision History: - * version Beta 1.00.00-98-03-26 - */ - -// Highlevel interface - -#ifndef NVTC_H -#define NVTC_H - -#if defined( _WIN32 ) && !defined( _X360 ) -#include -#endif - -// RGB encoding types -#define S3TC_ENCODE_RGB_FULL 0x0 -#define S3TC_ENCODE_RGB_COLOR_KEY 0x1 -#define S3TC_ENCODE_RGB_ALPHA_COMPARE 0x2 -#define _S3TC_ENCODE_RGB_MASK 0xff - -// alpha encoding types -#define S3TC_ENCODE_ALPHA_NONE 0x000 -#define S3TC_ENCODE_ALPHA_EXPLICIT 0x100 -#define S3TC_ENCODE_ALPHA_INTERPOLATED 0x200 -#define _S3TC_ENCODE_ALPHA_MASK 0xff00 - - -#if defined( _WIN32 ) && !defined( _X360 ) -// common encoding types -//@@@TBD - -// error codes -#define ERROR_ABORTED -1 - -// Progress Callback for S3TCencode -typedef BOOL (* LP_S3TC_PROGRESS_CALLBACK)(float fProgress, LPVOID lpUser1, LPVOID lpUser2); - -// set alpha reference value for alpha compare encoding -void S3TCsetAlphaReference(int nRef); - -// determine number of bytes needed to compress given source image -unsigned int S3TCgetEncodeSize(DDSURFACEDESC *lpDesc, // [in] - unsigned int dwEncodeType // [in] - ); - -// encode (compress) given source image to given destination surface -void S3TCencode(DDSURFACEDESC *lpSrc, // [in] - PALETTEENTRY *lpPal, // [in], may be NULL - DDSURFACEDESC *lpDest, // [out] - void *lpDestBuf, // [in] - unsigned int dwEncodeType, // [in] - float *weight // [in] - ); - -int S3TCencodeEx(DDSURFACEDESC *lpSrc, // [in] - PALETTEENTRY *lpPal, // [in], may be NULL - DDSURFACEDESC *lpDest, // [out] - void *lpDestBuf, // [in] - unsigned int dwEncodeType, // [in] - float *weight, // [in] - LP_S3TC_PROGRESS_CALLBACK lpS3TCProgressProc, // [in], may be NULL - LPVOID lpArg1, // in - LPVOID lpArg2 // in - ); - -// determine number of bytes needed do decompress given compressed image -unsigned int S3TCgetDecodeSize(DDSURFACEDESC *lpDesc); - -// decode (decompress) to ARGB8888 -void S3TCdecode(DDSURFACEDESC *lpSrc, // [in] - DDSURFACEDESC *lpDest, // [out] - void *lpDestBuf // [in] - ); - -#endif // _WIN32 - -#endif // NVTC_H diff --git a/public/optimize.h b/public/optimize.h deleted file mode 100644 index cee6fce51..000000000 --- a/public/optimize.h +++ /dev/null @@ -1,257 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef OPTIMIZE_H -#define OPTIMIZE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "studio.h" - - -// NOTE: You can change this without affecting the vtx file format. -#define MAX_NUM_BONES_PER_TRI ( MAX_NUM_BONES_PER_VERT * 3 ) -#define MAX_NUM_BONES_PER_STRIP 512 - -#define OPTIMIZED_MODEL_FILE_VERSION 7 - -extern bool g_bDumpGLViewFiles; - -struct s_bodypart_t; - -namespace OptimizedModel -{ - -#pragma pack(1) - -struct BoneStateChangeHeader_t -{ - DECLARE_BYTESWAP_DATADESC(); - int hardwareID; - int newBoneID; -}; - -struct Vertex_t -{ - DECLARE_BYTESWAP_DATADESC(); - // these index into the mesh's vert[origMeshVertID]'s bones - unsigned char boneWeightIndex[MAX_NUM_BONES_PER_VERT]; - unsigned char numBones; - - unsigned short origMeshVertID; - - // for sw skinned verts, these are indices into the global list of bones - // for hw skinned verts, these are hardware bone indices - char boneID[MAX_NUM_BONES_PER_VERT]; -}; - -enum StripHeaderFlags_t { - STRIP_IS_TRILIST = 0x01, - STRIP_IS_TRISTRIP = 0x02 -}; - -// a strip is a piece of a stripgroup that is divided by bones -// (and potentially tristrips if we remove some degenerates.) -struct StripHeader_t -{ - DECLARE_BYTESWAP_DATADESC(); - // indexOffset offsets into the mesh's index array. - int numIndices; - int indexOffset; - - // vertexOffset offsets into the mesh's vert array. - int numVerts; - int vertOffset; - - // use this to enable/disable skinning. - // May decide (in optimize.cpp) to put all with 1 bone in a different strip - // than those that need skinning. - short numBones; - - unsigned char flags; - - int numBoneStateChanges; - int boneStateChangeOffset; - inline BoneStateChangeHeader_t *pBoneStateChange( int i ) const - { - return (BoneStateChangeHeader_t *)(((byte *)this) + boneStateChangeOffset) + i; - }; -}; - -enum StripGroupFlags_t -{ - STRIPGROUP_IS_FLEXED = 0x01, - STRIPGROUP_IS_HWSKINNED = 0x02, - STRIPGROUP_IS_DELTA_FLEXED = 0x04, - STRIPGROUP_SUPPRESS_HW_MORPH = 0x08, // NOTE: This is a temporary flag used at run time. -}; - -// a locking group -// a single vertex buffer -// a single index buffer -struct StripGroupHeader_t -{ - DECLARE_BYTESWAP_DATADESC(); - // These are the arrays of all verts and indices for this mesh. strips index into this. - int numVerts; - int vertOffset; - inline Vertex_t *pVertex( int i ) const - { - return (Vertex_t *)(((byte *)this) + vertOffset) + i; - }; - - int numIndices; - int indexOffset; - inline unsigned short *pIndex( int i ) const - { - return (unsigned short *)(((byte *)this) + indexOffset) + i; - }; - - int numStrips; - int stripOffset; - inline StripHeader_t *pStrip( int i ) const - { - return (StripHeader_t *)(((byte *)this) + stripOffset) + i; - }; - - unsigned char flags; -}; - -enum MeshFlags_t { - // these are both material properties, and a mesh has a single material. - MESH_IS_TEETH = 0x01, - MESH_IS_EYES = 0x02 -}; - -// a collection of locking groups: -// up to 4: -// non-flexed, hardware skinned -// flexed, hardware skinned -// non-flexed, software skinned -// flexed, software skinned -// -// A mesh has a material associated with it. -struct MeshHeader_t -{ - DECLARE_BYTESWAP_DATADESC(); - int numStripGroups; - int stripGroupHeaderOffset; - inline StripGroupHeader_t *pStripGroup( int i ) const - { - StripGroupHeader_t *pDebug = (StripGroupHeader_t *)(((byte *)this) + stripGroupHeaderOffset) + i; - return pDebug; - }; - unsigned char flags; -}; - -struct ModelLODHeader_t -{ - DECLARE_BYTESWAP_DATADESC(); - int numMeshes; - int meshOffset; - float switchPoint; - inline MeshHeader_t *pMesh( int i ) const - { - MeshHeader_t *pDebug = (MeshHeader_t *)(((byte *)this) + meshOffset) + i; - return pDebug; - }; -}; - -// This maps one to one with models in the mdl file. -// There are a bunch of model LODs stored inside potentially due to the qc $lod command -struct ModelHeader_t -{ - DECLARE_BYTESWAP_DATADESC(); - int numLODs; // garymcthack - this is also specified in FileHeader_t - int lodOffset; - inline ModelLODHeader_t *pLOD( int i ) const - { - ModelLODHeader_t *pDebug = ( ModelLODHeader_t *)(((byte *)this) + lodOffset) + i; - return pDebug; - }; -}; - -struct BodyPartHeader_t -{ - DECLARE_BYTESWAP_DATADESC(); - int numModels; - int modelOffset; - inline ModelHeader_t *pModel( int i ) const - { - ModelHeader_t *pDebug = (ModelHeader_t *)(((byte *)this) + modelOffset) + i; - return pDebug; - }; -}; - -struct MaterialReplacementHeader_t -{ - DECLARE_BYTESWAP_DATADESC(); - short materialID; - int replacementMaterialNameOffset; - inline const char *pMaterialReplacementName( void ) - { - const char *pDebug = (const char *)(((byte *)this) + replacementMaterialNameOffset); - return pDebug; - } -}; - -struct MaterialReplacementListHeader_t -{ - DECLARE_BYTESWAP_DATADESC(); - int numReplacements; - int replacementOffset; - inline MaterialReplacementHeader_t *pMaterialReplacement( int i ) const - { - MaterialReplacementHeader_t *pDebug = ( MaterialReplacementHeader_t *)(((byte *)this) + replacementOffset) + i; - return pDebug; - } -}; - -struct FileHeader_t -{ - DECLARE_BYTESWAP_DATADESC(); - // file version as defined by OPTIMIZED_MODEL_FILE_VERSION - int version; - - // hardware params that affect how the model is to be optimized. - int vertCacheSize; - unsigned short maxBonesPerStrip; - unsigned short maxBonesPerTri; - int maxBonesPerVert; - - // must match checkSum in the .mdl - long checkSum; - - int numLODs; // garymcthack - this is also specified in ModelHeader_t and should match - - // one of these for each LOD - int materialReplacementListOffset; - MaterialReplacementListHeader_t *pMaterialReplacementList( int lodID ) const - { - MaterialReplacementListHeader_t *pDebug = - (MaterialReplacementListHeader_t *)(((byte *)this) + materialReplacementListOffset) + lodID; - return pDebug; - } - - int numBodyParts; - int bodyPartOffset; - inline BodyPartHeader_t *pBodyPart( int i ) const - { - BodyPartHeader_t *pDebug = (BodyPartHeader_t *)(((byte *)this) + bodyPartOffset) + i; - return pDebug; - }; -}; - -#pragma pack() - -void WriteOptimizedFiles( studiohdr_t *phdr, s_bodypart_t *pSrcBodyParts ); - -}; // namespace OptimizedModel - -#endif // OPTIMIZE_H diff --git a/public/overlaytext.h b/public/overlaytext.h deleted file mode 100644 index 09be0143f..000000000 --- a/public/overlaytext.h +++ /dev/null @@ -1,58 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// -#if !defined( OVERLAYTEXT_H ) -#define OVERLAYTEXT_H -#ifdef _WIN32 -#pragma once -#endif - -#include "mathlib/vector.h" - -class OverlayText_t -{ -public: - OverlayText_t() - { - nextOverlayText = 0; - origin.Init(); - bUseOrigin = false; - lineOffset = 0; - flXPos = 0; - flYPos = 0; - text[ 0 ] = 0; - m_flEndTime = 0.0f; - m_nServerCount = -1; - m_nCreationTick = -1; - r = g = b = a = 255; - } - - bool IsDead(); - void SetEndTime( float duration ); - - Vector origin; - bool bUseOrigin; - int lineOffset; - float flXPos; - float flYPos; - char text[512]; - float m_flEndTime; // When does this text go away - int m_nCreationTick; // If > 0, show only one server frame - int m_nServerCount; // compare server spawn count to remove stale overlays - int r; - int g; - int b; - int a; - OverlayText_t *nextOverlayText; -}; - -#endif // OVERLAYTEXT_H diff --git a/public/p4lib/ip4.h b/public/p4lib/ip4.h deleted file mode 100644 index fdb33627e..000000000 --- a/public/p4lib/ip4.h +++ /dev/null @@ -1,189 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef IP4_H -#define IP4_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/utlsymbol.h" -#include "tier1/utlvector.h" -#include "tier1/utlstring.h" -#include "appframework/IAppSystem.h" - - -//----------------------------------------------------------------------------- -// Current perforce file state -//----------------------------------------------------------------------------- -enum P4FileState_t -{ - P4FILE_UNOPENED = 0, - P4FILE_OPENED_FOR_ADD, - P4FILE_OPENED_FOR_EDIT, - P4FILE_OPENED_FOR_DELETE, - P4FILE_OPENED_FOR_INTEGRATE, -}; - - -//----------------------------------------------------------------------------- -// Purpose: definition of a file -//----------------------------------------------------------------------------- -struct P4File_t -{ - CUtlSymbol m_sName; // file name - CUtlSymbol m_sPath; // residing folder - CUtlSymbol m_sDepotFile; // the name in the depot - CUtlSymbol m_sClientFile; // the name on the client in Perforce syntax - CUtlSymbol m_sLocalFile; // the name on the client in local syntax - int m_iHeadRevision; // head revision number - int m_iHaveRevision; // the revision the clientspec has synced locally - bool m_bDir; // directory - bool m_bDeleted; // deleted - P4FileState_t m_eOpenState; // current change state - int m_iChangelist; // changelist current opened in -}; - - -//----------------------------------------------------------------------------- -// Purpose: a single revision of a file -//----------------------------------------------------------------------------- -struct P4Revision_t -{ - int m_iChange; // changelist number - int m_nYear, m_nMonth, m_nDay; - int m_nHour, m_nMinute, m_nSecond; - - CUtlSymbol m_sUser; // submitting user - CUtlSymbol m_sClient; // submitting client - CUtlString m_Description; -}; - - -//----------------------------------------------------------------------------- -// Purpose: a single clientspec -//----------------------------------------------------------------------------- -struct P4Client_t -{ - CUtlSymbol m_sName; - CUtlSymbol m_sUser; - CUtlSymbol m_sHost; // machine name this client is on - CUtlSymbol m_sLocalRoot; // local path -}; - - -//----------------------------------------------------------------------------- -// Purpose: Interface to accessing P4 commands -//----------------------------------------------------------------------------- -#define P4_INTERFACE_VERSION "VP4001" -// Vitaliy - 09-Feb-'07: if anybody ups the version of this interface, please -// move the method "SetOpenFileChangeList" into the appropriate section. - -abstract_class IP4 : public IAppSystem -{ -public: - // name of the current clientspec - virtual P4Client_t &GetActiveClient() = 0; - - // changes the current client - virtual void SetActiveClient(const char *clientname) = 0; - - // Refreshes the current client from p4 settings - virtual void RefreshActiveClient() = 0; - - // translate filespecs into the desired syntax - virtual void GetDepotFilePath(char *depotFilePath, const char *filespec, int size) = 0; - virtual void GetClientFilePath(char *clientFilePath, const char *filespec, int size) = 0; - virtual void GetLocalFilePath(char *localFilePath, const char *filespec, int size) = 0; - - // retreives the list of files in a path - virtual CUtlVector &GetFileList( const char *path ) = 0; - - // returns the list of files opened for edit/integrate/delete - virtual void GetOpenedFileList( CUtlVector &fileList ) = 0; - virtual void GetOpenedFileList( const char *pRootDirectory, CUtlVector &fileList ) = 0; - virtual void GetOpenedFileListInPath( const char *pPathID, CUtlVector &fileList ) = 0; - - // retrieves revision history for a file or directory - virtual CUtlVector &GetRevisionList( const char *path, bool bIsDir ) = 0; - - // returns a list of clientspecs - virtual CUtlVector &GetClientList() = 0; - - // changes the clientspec to remove the specified path (cloaking) - virtual void RemovePathFromActiveClientspec( const char *path ) = 0; - - // file manipulation - virtual bool OpenFileForAdd( const char *pFullPath ) = 0; - virtual bool OpenFileForEdit( const char *pFullPath ) = 0; - virtual bool OpenFileForDelete( const char *pFullPath ) = 0; - - // submit/revert - virtual bool SubmitFile( const char *pFullPath, const char *pDescription ) = 0; - virtual bool RevertFile( const char *pFullPath ) = 0; - - // file checkin/checkout for multiple files - virtual bool OpenFilesForAdd( int nCount, const char **ppFullPathList ) = 0; - virtual bool OpenFilesForEdit( int nCount, const char **ppFullPathList ) = 0; - virtual bool OpenFilesForDelete( int nCount, const char **ppFullPathList ) = 0; - - // submit/revert for multiple files - virtual bool SubmitFiles( int nCount, const char **ppFullPathList, const char *pDescription ) = 0; - virtual bool RevertFiles( int nCount, const char **ppFullPathList ) = 0; - - // Is this file in perforce? - virtual bool IsFileInPerforce( const char *pFullPath ) = 0; - - // Get the perforce file state - virtual P4FileState_t GetFileState( const char *pFullPath ) = 0; - - // depot root - virtual const char *GetDepotRoot() = 0; - virtual int GetDepotRootLength() = 0; - - // local root - virtual const char *GetLocalRoot() = 0; - virtual int GetLocalRootLength() = 0; - - // Gets a string for a symbol - virtual const char *String( CUtlSymbol s ) const = 0; - - // Returns which clientspec a file lies under. This will - // search for p4config files in root directories of the file - // It returns false if it didn't find a p4config file. - virtual bool GetClientSpecForFile( const char *pFullPath, char *pClientSpec, int nMaxLen ) = 0; - virtual bool GetClientSpecForDirectory( const char *pFullPathDir, char *pClientSpec, int nMaxLen ) = 0; - - // Returns which clientspec a filesystem path ID lies under. This will - // search for p4config files in all root directories of the all paths in - // the search path. NOTE: All directories in a path need to use the same clientspec - // or this function will return false. - // It returns false if it didn't find a p4config file. - virtual bool GetClientSpecForPath( const char *pPathId, char *pClientSpec, int nMaxLen ) = 0; - - // Opens a file in p4 win - virtual void OpenFileInP4Win( const char *pFullPath ) = 0; - - // have we connected? if not, nothing works - virtual bool IsConnectedToServer( bool bRetry = true ) = 0; - - // Returns file information for a single file - virtual bool GetFileInfo( const char *pFullPath, P4File_t *pFileInfo ) = 0; - - // retreives the list of files in a path, using a known client spec - virtual CUtlVector &GetFileListUsingClientSpec( const char *pPath, const char *pClientSpec ) = 0; - - // retrieves the last error from the last op (which is likely to span multiple lines) - // this is only valid after OpenFile[s]For{Add,Edit,Delete} or {Submit,Revert}File[s] - virtual const char *GetLastError() = 0; - - // sets the name of the changelist to open files under, NULL for "Default" changelist - virtual void SetOpenFileChangeList( const char *pChangeListName ) = 0; -}; - - - -#endif // IP4_H diff --git a/public/particles/particles.h b/public/particles/particles.h deleted file mode 100644 index 45cb145f4..000000000 --- a/public/particles/particles.h +++ /dev/null @@ -1,2215 +0,0 @@ -//===== Copyright © 1996-2006, Valve Corporation, All rights reserved. ======// -// -// Purpose: particle system definitions -// -//===========================================================================// - -#ifndef PARTICLES_H -#define PARTICLES_H -#ifdef _WIN32 -#pragma once -#endif - -#include "mathlib/mathlib.h" -#include "mathlib/vector.h" -#include "mathlib/ssemath.h" -#include "materialsystem/imaterialsystem.h" -#include "dmxloader/dmxelement.h" -#include "tier1/utlintrusivelist.h" -#include "vstdlib/random.h" -#include "tier1/utlobjectreference.h" -#include "tier1/UtlStringMap.h" -#include "tier1/utlmap.h" -#include "materialsystem/MaterialSystemUtil.h" -#include "trace.h" -#include "tier1/utlsoacontainer.h" - -#ifndef SWDS -#include -#endif - -#if defined( CLIENT_DLL ) -#include "c_pixel_visibility.h" -#endif - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -struct DmxElementUnpackStructure_t; -class CParticleSystemDefinition; -class CParticleCollection; -class CParticleOperatorInstance; -class CParticleSystemDictionary; -class CUtlBuffer; -class IParticleOperatorDefinition; -class CSheet; -class CMeshBuilder; -extern float s_pRandomFloats[]; - - -//----------------------------------------------------------------------------- -// Random numbers -//----------------------------------------------------------------------------- -#define MAX_RANDOM_FLOATS 4096 -#define RANDOM_FLOAT_MASK ( MAX_RANDOM_FLOATS - 1 ) - - -//----------------------------------------------------------------------------- -// Particle attributes -//----------------------------------------------------------------------------- -#define MAX_PARTICLE_ATTRIBUTES 32 - -#define DEFPARTICLE_ATTRIBUTE( name, bit ) \ - const int PARTICLE_ATTRIBUTE_##name##_MASK = (1 << bit); \ - const int PARTICLE_ATTRIBUTE_##name = bit; - -// required -DEFPARTICLE_ATTRIBUTE( XYZ, 0 ); - -// particle lifetime (duration) of particle as a float. -DEFPARTICLE_ATTRIBUTE( LIFE_DURATION, 1 ); - -// prev coordinates for verlet integration -DEFPARTICLE_ATTRIBUTE( PREV_XYZ, 2 ); - -// radius of particle -DEFPARTICLE_ATTRIBUTE( RADIUS, 3 ); - -// rotation angle of particle -DEFPARTICLE_ATTRIBUTE( ROTATION, 4 ); - -// rotation speed of particle -DEFPARTICLE_ATTRIBUTE( ROTATION_SPEED, 5 ); - -// tint of particle -DEFPARTICLE_ATTRIBUTE( TINT_RGB, 6 ); - -// alpha tint of particle -DEFPARTICLE_ATTRIBUTE( ALPHA, 7 ); - -// creation time stamp (relative to particle system creation) -DEFPARTICLE_ATTRIBUTE( CREATION_TIME, 8 ); - -// sequnece # (which animation sequence number this particle uses ) -DEFPARTICLE_ATTRIBUTE( SEQUENCE_NUMBER, 9 ); - -// length of the trail -DEFPARTICLE_ATTRIBUTE( TRAIL_LENGTH, 10 ); - -// unique particle identifier -DEFPARTICLE_ATTRIBUTE( PARTICLE_ID, 11 ); - -// unique rotation around up vector -DEFPARTICLE_ATTRIBUTE( YAW, 12 ); - -// second sequnece # (which animation sequence number this particle uses ) -DEFPARTICLE_ATTRIBUTE( SEQUENCE_NUMBER1, 13 ); - -// hit box index -DEFPARTICLE_ATTRIBUTE( HITBOX_INDEX, 14 ); - -DEFPARTICLE_ATTRIBUTE( HITBOX_RELATIVE_XYZ, 15 ); - -DEFPARTICLE_ATTRIBUTE( ALPHA2, 16 ); - -// particle trace caching fields -DEFPARTICLE_ATTRIBUTE( TRACE_P0, 17 ); // start pnt of trace -DEFPARTICLE_ATTRIBUTE( TRACE_P1, 18 ); // end pnt of trace -DEFPARTICLE_ATTRIBUTE( TRACE_HIT_T, 19 ); // 0..1 if hit -DEFPARTICLE_ATTRIBUTE( TRACE_HIT_NORMAL, 20 ); // 0 0 0 if no hit - - -#define MAX_PARTICLE_CONTROL_POINTS 64 - -#define ATTRIBUTES_WHICH_ARE_VEC3S_MASK ( PARTICLE_ATTRIBUTE_TRACE_P0_MASK | PARTICLE_ATTRIBUTE_TRACE_P1_MASK | \ - PARTICLE_ATTRIBUTE_TRACE_HIT_NORMAL | PARTICLE_ATTRIBUTE_XYZ_MASK | \ - PARTICLE_ATTRIBUTE_PREV_XYZ_MASK | PARTICLE_ATTRIBUTE_TINT_RGB_MASK | \ - PARTICLE_ATTRIBUTE_HITBOX_RELATIVE_XYZ_MASK ) -#define ATTRIBUTES_WHICH_ARE_0_TO_1 (PARTICLE_ATTRIBUTE_ALPHA_MASK | PARTICLE_ATTRIBUTE_ALPHA2_MASK) -#define ATTRIBUTES_WHICH_ARE_ANGLES (PARTICLE_ATTRIBUTE_ROTATION_MASK | PARTICLE_ATTRIBUTE_YAW_MASK ) -#define ATTRIBUTES_WHICH_ARE_INTS (PARTICLE_ATTRIBUTE_PARTICLE_ID_MASK | PARTICLE_ATTRIBUTE_HITBOX_INDEX_MASK ) - -#if defined( _X360 ) -#define MAX_PARTICLES_IN_A_SYSTEM 2000 -#else -#define MAX_PARTICLES_IN_A_SYSTEM 5000 -#endif - -#define MEASURE_PARTICLE_PERF 1 - - -//----------------------------------------------------------------------------- -// Particle function types -//----------------------------------------------------------------------------- -enum ParticleFunctionType_t -{ - FUNCTION_RENDERER = 0, - FUNCTION_OPERATOR, - FUNCTION_INITIALIZER, - FUNCTION_EMITTER, - FUNCTION_CHILDREN, // NOTE: This one is a fake function type, only here to help eliminate a ton of duplicated code in the editor - FUNCTION_FORCEGENERATOR, - FUNCTION_CONSTRAINT, - PARTICLE_FUNCTION_COUNT -}; - -struct CParticleVisibilityInputs -{ - float m_flInputMin; - float m_flInputMax; - float m_flAlphaScaleMin; - float m_flAlphaScaleMax; - float m_flRadiusScaleMin; - float m_flRadiusScaleMax; - float m_flProxyRadius; - float m_flBBoxScale; - bool m_bUseBBox; - int m_nCPin; -}; - -struct ModelHitBoxInfo_t -{ - Vector m_vecBoxMins; - Vector m_vecBoxMaxes; - matrix3x4_t m_Transform; -}; - -class CModelHitBoxesInfo -{ -public: - float m_flLastUpdateTime; - float m_flPrevLastUpdateTime; - int m_nNumHitBoxes; - int m_nNumPrevHitBoxes; - ModelHitBoxInfo_t *m_pHitBoxes; - ModelHitBoxInfo_t *m_pPrevBoxes; - - bool CurAndPrevValid( void ) const - { - return ( m_nNumHitBoxes && ( m_nNumPrevHitBoxes == m_nNumHitBoxes ) ); - } - - CModelHitBoxesInfo( void ) - { - m_flLastUpdateTime = -1; - m_nNumHitBoxes = 0; - m_nNumPrevHitBoxes = 0; - m_pHitBoxes = NULL; - m_pPrevBoxes = NULL; - } - - ~CModelHitBoxesInfo( void ) - { - if ( m_pHitBoxes ) - delete[] m_pHitBoxes; - if ( m_pPrevBoxes ) - delete[] m_pPrevBoxes; - } - -}; - - - - -//----------------------------------------------------------------------------- -// Interface to allow the particle system to call back into the client -//----------------------------------------------------------------------------- - -#define PARTICLE_SYSTEM_QUERY_INTERFACE_VERSION "VParticleSystemQuery001" - -class IParticleSystemQuery : public IAppSystem -{ -public: - virtual void GetLightingAtPoint( const Vector& vecOrigin, Color &tint ) = 0; - virtual void TraceLine( const Vector& vecAbsStart, - const Vector& vecAbsEnd, unsigned int mask, - const class IHandleEntity *ignore, - int collisionGroup, - CBaseTrace *ptr ) = 0; - - // given a possible spawn point, tries to movie it to be on or in the source object. returns - // true if it succeeded - virtual bool MovePointInsideControllingObject( CParticleCollection *pParticles, - void *pObject, - Vector *pPnt ) - { - return true; - } - - virtual bool IsPointInControllingObjectHitBox( - CParticleCollection *pParticles, - int nControlPointNumber, Vector vecPos, bool bBBoxOnly = false ) - { - return true; - } - - virtual int GetCollisionGroupFromName( const char *pszCollisionGroupName ) - { - return 0; // == COLLISION_GROUP_NONE - } - - virtual void GetRandomPointsOnControllingObjectHitBox( - CParticleCollection *pParticles, - int nControlPointNumber, - int nNumPtsOut, - float flBBoxScale, - int nNumTrysToGetAPointInsideTheModel, - Vector *pPntsOut, - Vector vecDirectionBias, - Vector *pHitBoxRelativeCoordOut = NULL, - int *pHitBoxIndexOut = NULL ) = 0; - - - virtual int GetControllingObjectHitBoxInfo( - CParticleCollection *pParticles, - int nControlPointNumber, - int nBufSize, // # of output slots available - ModelHitBoxInfo_t *pHitBoxOutputBuffer ) - { - // returns number of hit boxes output - return 0; - } - - virtual Vector GetLocalPlayerPos( void ) - { - return vec3_origin; - } - - virtual void GetLocalPlayerEyeVectors( Vector *pForward, Vector *pRight = NULL, Vector *pUp = NULL ) - { - *pForward = vec3_origin; - *pRight = vec3_origin; - *pUp = vec3_origin; - } - - virtual float GetPixelVisibility( int *pQueryHandle, const Vector &vecOrigin, float flScale ) = 0; - - virtual void SetUpLightingEnvironment( const Vector& pos ) - { - } -}; - - -//----------------------------------------------------------------------------- -// -// Particle system manager. Using a class because tools need it that way -// so the SFM and PET tools can share managers despite being linked to -// separate particle system .libs -// -//----------------------------------------------------------------------------- -typedef int ParticleSystemHandle_t; - -class CParticleSystemMgr -{ -public: - // Constructor, destructor - CParticleSystemMgr(); - ~CParticleSystemMgr(); - - // Initialize the particle system - bool Init( IParticleSystemQuery *pQuery ); - - // methods to add builtin operators. If you don't call these at startup, you won't be able to sim or draw. These are done separately from Init, so that - // the server can omit the code needed for rendering/simulation, if desired. - void AddBuiltinSimulationOperators( void ); - void AddBuiltinRenderingOperators( void ); - - - - // Registration of known operators - void AddParticleOperator( ParticleFunctionType_t nOpType, IParticleOperatorDefinition *pOpFactory ); - - // Read a particle config file, add it to the list of particle configs - bool ReadParticleConfigFile( const char *pFileName, bool bPrecache, bool bDecommitTempMemory = true ); - bool ReadParticleConfigFile( CUtlBuffer &buf, bool bPrecache, bool bDecommitTempMemory = true, const char *pFileName = NULL ); - void DecommitTempMemory(); - - // For recording, write a specific particle system to a CUtlBuffer in DMX format - bool WriteParticleConfigFile( const char *pParticleSystemName, CUtlBuffer &buf, bool bPreventNameBasedLookup = false ); - bool WriteParticleConfigFile( const DmObjectId_t& id, CUtlBuffer &buf, bool bPreventNameBasedLookup = false ); - - // create a particle system by name. returns null if one of that name does not exist - CParticleCollection *CreateParticleCollection( const char *pParticleSystemName, float flDelay = 0.0f, int nRandomSeed = 0 ); - - // create a particle system given a particle system id - CParticleCollection *CreateParticleCollection( const DmObjectId_t &id, float flDelay = 0.0f, int nRandomSeed = 0 ); - - // Is a particular particle system defined? - bool IsParticleSystemDefined( const char *pParticleSystemName ); - bool IsParticleSystemDefined( const DmObjectId_t &id ); - - // Returns the index of the specified particle system. - ParticleSystemHandle_t GetParticleSystemIndex( const char *pParticleSystemName ); - - // Returns the name of the specified particle system. - const char *GetParticleSystemNameFromIndex( ParticleSystemHandle_t iIndex ); - - // Return the number of particle systems in our dictionary - int GetParticleSystemCount( void ); - - // call to get available particle operator definitions - // NOTE: FUNCTION_CHILDREN will return a faked one, for ease of writing the editor - CUtlVector< IParticleOperatorDefinition *> &GetAvailableParticleOperatorList( ParticleFunctionType_t nWhichList ); - - // Returns the unpack structure for a particle system definition - const DmxElementUnpackStructure_t *GetParticleSystemDefinitionUnpackStructure(); - - // Particle sheet management - void ShouldLoadSheets( bool bLoadSheets ); - CSheet *FindOrLoadSheet( char const *pszFname, ITexture *pTexture ); - CSheet *FindOrLoadSheet( IMaterial *pMaterial ); - void FlushAllSheets( void ); - - - // Render cache used to render opaque particle collections - void ResetRenderCache( void ); - void AddToRenderCache( CParticleCollection *pParticles ); - void DrawRenderCache( bool bShadowDepth ); - - IParticleSystemQuery *Query( void ) { return m_pQuery; } - - // return the particle field name - const char* GetParticleFieldName( int nParticleField ) const; - - // WARNING: the pointer returned by this function may be invalidated - // *at any time* by the editor, so do not ever cache it. - CParticleSystemDefinition* FindParticleSystem( const char *pName ); - CParticleSystemDefinition* FindParticleSystem( const DmObjectId_t& id ); - - void CommitProfileInformation( bool bCommit ); // call after simulation, if you want - // sim time recorded. if oyu pass - // flase, info will be thrown away and - // uncomitted time reset. Having this - // function lets you only record - // profile data for slow frames if - // desired. - - - void DumpProfileInformation( void ); // write particle_profile.csv - - // Cache/uncache materials used by particle systems - void PrecacheParticleSystem( const char *pName ); - void UncacheAllParticleSystems(); - - // Sets the last simulation time, used for particle system sleeping logic - void SetLastSimulationTime( float flTime ); - float GetLastSimulationTime() const; - -private: - struct RenderCache_t - { - IMaterial *m_pMaterial; - CUtlVector< CParticleCollection * > m_ParticleCollections; - }; - - struct BatchStep_t - { - CParticleCollection *m_pParticles; - CParticleOperatorInstance *m_pRenderer; - void *m_pContext; - int m_nFirstParticle; - int m_nParticleCount; - int m_nVertCount; - }; - - struct Batch_t - { - int m_nVertCount; - int m_nIndexCount; - CUtlVector< BatchStep_t > m_BatchStep; - }; - - // Unserialization-related methods - bool ReadParticleDefinitions( CUtlBuffer &buf, const char *pFileName, bool bPrecache, bool bDecommitTempMemory ); - void AddParticleSystem( CDmxElement *pParticleSystem ); - - // Serialization-related methods - CDmxElement *CreateParticleDmxElement( const DmObjectId_t &id ); - CDmxElement *CreateParticleDmxElement( const char *pParticleSystemName ); - - bool WriteParticleConfigFile( CDmxElement *pParticleSystem, CUtlBuffer &buf, bool bPreventNameBasedLookup ); - - // Builds a list of batches to render - void BuildBatchList( int iRenderCache, IMatRenderContext *pRenderContext, CUtlVector< Batch_t >& batches ); - - // Known operators - CUtlVector m_ParticleOperators[PARTICLE_FUNCTION_COUNT]; - - // Particle system dictionary - CParticleSystemDictionary *m_pParticleSystemDictionary; - - // typedef CUtlMap< ITexture *, CSheet* > SheetsCache; - typedef CUtlStringMap< CSheet* > SheetsCache_t; - SheetsCache_t m_SheetList; - - // attaching and dtaching killlists. when simulating, a particle system gets a kill list. after - // simulating, the memory for that will be used for the next particle system. This matters for - // threaded particles, because we don't want to share the same kill list between simultaneously - // simulating particle systems. - void AttachKillList( CParticleCollection *pParticles); - void DetachKillList( CParticleCollection *pParticles); - - // For visualization (currently can only visualize one operator at a time) - CParticleCollection *m_pVisualizedParticles; - DmObjectId_t m_VisualizedOperatorId; - IParticleSystemQuery *m_pQuery; - CUtlVector< RenderCache_t > m_RenderCache; - IMaterial *m_pShadowDepthMaterial; - float m_flLastSimulationTime; - - bool m_bDidInit; - bool m_bUsingDefaultQuery; - bool m_bShouldLoadSheets; - - int m_nNumFramesMeasured; - - friend class CParticleSystemDefinition; - friend class CParticleCollection; -}; - -extern CParticleSystemMgr *g_pParticleSystemMgr; - - -//----------------------------------------------------------------------------- -// A particle system can only have 1 operator using a particular ID -//----------------------------------------------------------------------------- -enum ParticleOperatorId_t -{ - // Generic IDs - OPERATOR_GENERIC = -2, // Can have as many of these as you want - OPERATOR_SINGLETON = -1, // Can only have 1 operator with the same name as this one - - // Renderer operator IDs - - // Operator IDs - - // Initializer operator IDs - OPERATOR_PI_POSITION, // Particle initializer: position (can only have 1 position setter) - OPERATOR_PI_RADIUS, - OPERATOR_PI_ALPHA, - OPERATOR_PI_TINT_RGB, - OPERATOR_PI_ROTATION, - OPERATOR_PI_YAW, - - // Emitter IDs - - OPERATOR_ID_COUNT, -}; - - -//----------------------------------------------------------------------------- -// Class factory for particle operators -//----------------------------------------------------------------------------- -class IParticleOperatorDefinition -{ -public: - virtual const char *GetName() const = 0; - virtual CParticleOperatorInstance *CreateInstance( const DmObjectId_t &id ) const = 0; -// virtual void DestroyInstance( CParticleOperatorInstance *pInstance ) const = 0; - virtual const DmxElementUnpackStructure_t* GetUnpackStructure() const = 0; - virtual ParticleOperatorId_t GetId() const = 0; - virtual bool IsObsolete() const = 0; - -#if MEASURE_PARTICLE_PERF - // performance monitoring - float m_flMaxExecutionTime; - float m_flTotalExecutionTime; - float m_flUncomittedTime; - - FORCEINLINE void RecordExecutionTime( float flETime ) - { - m_flUncomittedTime += flETime; - m_flMaxExecutionTime = MAX( m_flMaxExecutionTime, flETime ); - } - - FORCEINLINE float TotalRecordedExecutionTime( void ) const - { - return m_flTotalExecutionTime; - } - - FORCEINLINE float MaximumRecordedExecutionTime( void ) const - { - return m_flMaxExecutionTime; - } -#endif -}; - - -//----------------------------------------------------------------------------- -// Particle operators -//----------------------------------------------------------------------------- -class CParticleOperatorInstance -{ -public: - // custom allocators so we can be simd aligned - void *operator new( size_t nSize ); - void* operator new( size_t size, int nBlockUse, const char *pFileName, int nLine ); - void operator delete( void *pData ); - void operator delete( void* p, int nBlockUse, const char *pFileName, int nLine ); - - // unpack structure will be applied by creator. add extra initialization needed here - virtual void InitParams( CParticleSystemDefinition *pDef, CDmxElement *pElement ) - { - } - - virtual size_t GetRequiredContextBytes( ) const - { - return 0; - } - - virtual void InitializeContextData( CParticleCollection *pParticles, void *pContext ) const - { - } - - virtual uint32 GetWrittenAttributes( void ) const = 0; - virtual uint32 GetReadAttributes( void ) const = 0; - virtual uint64 GetReadControlPointMask() const - { - return 0; - } - - // Used when an operator needs to read the attributes of a particle at spawn time - virtual uint32 GetReadInitialAttributes( void ) const - { - return 0; - } - - // a particle simulator does this - virtual void Operate( CParticleCollection *pParticles, float flOpStrength, void *pContext ) const - { - } - - // a renderer overrides this - virtual void Render( IMatRenderContext *pRenderContext, - CParticleCollection *pParticles, void *pContext ) const - { - } - - virtual bool IsBatchable() const - { - return true; - } - - virtual void RenderUnsorted( CParticleCollection *pParticles, void *pContext, IMatRenderContext *pRenderContext, CMeshBuilder &meshBuilder, int nVertexOffset, int nFirstParticle, int nParticleCount ) const - { - } - - // Returns the number of verts + indices to render - virtual int GetParticlesToRender( CParticleCollection *pParticles, void *pContext, int nFirstParticle, int nRemainingVertices, int nRemainingIndices, int *pVertsUsed, int *pIndicesUsed ) const - { - *pVertsUsed = 0; - *pIndicesUsed = 0; - return 0; - } - - - // emitters over-ride this. Return a mask of what fields you initted - virtual uint32 Emit( CParticleCollection *pParticles, float flOpCurStrength, - void *pContext ) const - { - return 0; - } - - // emitters over-ride this. - virtual void StopEmission( CParticleCollection *pParticles, void *pContext, bool bInfiniteOnly = false ) const - { - } - virtual void StartEmission( CParticleCollection *pParticles, void *pContext, bool bInfiniteOnly = false ) const - { - } - virtual void Restart( CParticleCollection *pParticles, void *pContext ) {} - - // initters over-ride this - virtual void InitParticleSystem( CParticleCollection *pParticles, void *pContext ) const - { - } - - - // a force generator does this. It accumulates in the force array - virtual void AddForces( FourVectors *AccumulatedForces, - CParticleCollection *pParticles, - int nBlocks, - float flCurStrength, - void *pContext ) const - { - } - - - // this is called for each constarint every frame. It can set up data like nearby world traces, - // etc - virtual void SetupConstraintPerFrameData( CParticleCollection *pParticles, - void *pContext ) const - { - } - - - // a constraint overrides this. It shold return a true if it did anything - virtual bool EnforceConstraint( int nStartBlock, - int nNumBlocks, - CParticleCollection *pParticles, - void *pContext, - int nNumValidParticlesInLastChunk ) const - { - return false; - } - - // should the constraint be run only once after all other constraints? - virtual bool IsFinalConstaint( void ) const - { - return false; - } - - // determines if a mask needs to be initialized multiple times. - virtual bool InitMultipleOverride() - { - return false; - } - - - // Indicates if this initializer is scrub-safe (initializers don't use random numbers, for example) - virtual bool IsScrubSafe() - { - return false; - } - - // particle-initters over-ride this - virtual void InitNewParticlesScalar( CParticleCollection *pParticles, int nFirstParticle, int n_particles, int attribute_write_mask, void *pContext ) const - { - } - - // init new particles in blocks of 4. initters that have sse smarts should over ride this. the scalar particle initter will still be cllaed for head/tail. - virtual void InitNewParticlesBlock( CParticleCollection *pParticles, int start_block, int n_blocks, int attribute_write_mask, void *pContext ) const - { - // default behaviour is to call the scalar one 4x times - InitNewParticlesScalar( pParticles, 4*start_block, 4*n_blocks, attribute_write_mask, pContext ); - } - - // splits particle initialization up into scalar and block sections, callingt he right code - void InitNewParticles( CParticleCollection *pParticles, int nFirstParticle, int n_particles, int attribute_write_mask , void *pContext) const; - - - // this function is queried to determine if a particle system is over and doen with. A particle - // system is done with when it has noparticles and no operators intend to create any more - virtual bool MayCreateMoreParticles( CParticleCollection *pParticles, void *pContext ) const - { - return false; - } - - // Returns the operator definition that spawned this operator - const IParticleOperatorDefinition *GetDefinition() - { - return m_pDef; - } - - virtual bool ShouldRunBeforeEmitters( void ) const - { - return false; - } - - // Called when the SFM wants to skip forward in time - virtual void SkipToTime( float flTime, CParticleCollection *pParticles, void *pContext ) const {} - - // Returns a unique ID for this definition - const DmObjectId_t& GetId() { return m_Id; } - - // Used for editing + debugging to visualize the operator in 3D - virtual void Render( CParticleCollection *pParticles ) const {} - - // Used as a debugging mechanism to prevent bogus calls to RandomInt or RandomFloat inside operators - // Use CParticleCollection::RandomInt/RandomFloat instead - int RandomInt( int nMin, int nMax ) - { - // NOTE: Use CParticleCollection::RandomInt! - Assert(0); - return 0; - } - - float RandomFloat( float flMinVal = 0.0f, float flMaxVal = 1.0f ) - { - // NOTE: Use CParticleCollection::RandomFloat! - Assert(0); - return 0.0f; - } - - float RandomFloatExp( float flMinVal = 0.0f, float flMaxVal = 1.0f, float flExponent = 1.0f ) - { - // NOTE: Use CParticleCollection::RandomFloatExp! - Assert(0); - return 0.0f; - } - - float m_flOpStartFadeInTime; - float m_flOpEndFadeInTime; - float m_flOpStartFadeOutTime; - float m_flOpEndFadeOutTime; - float m_flOpFadeOscillatePeriod; - - virtual ~CParticleOperatorInstance( void ) - { - // so that sheet references, etc can be cleaned up - } - -protected: - // utility function for initting a scalar attribute to a random range in an sse fashion - void InitScalarAttributeRandomRangeBlock( int nAttributeId, float fMinValue, float fMaxValue, - CParticleCollection *pParticles, int nStartBlock, int nBlockCount ) const; - void InitScalarAttributeRandomRangeExpBlock( int nAttributeId, float fMinValue, float fMaxValue, float fExp, - CParticleCollection *pParticles, int nStartBlock, int nBlockCount ) const; - void AddScalarAttributeRandomRangeBlock( int nAttributeId, float fMinValue, float fMaxValue, float fExp, - CParticleCollection *pParticles, int nStartBlock, int nBlockCount, bool bRandomlyInvert ) const; - -private: - friend class CParticleCollection; - - const IParticleOperatorDefinition *m_pDef; - void SetDefinition( const IParticleOperatorDefinition * pDef, const DmObjectId_t &id ) - { - m_pDef = pDef; - CopyUniqueId( id, &m_Id ); - } - - DmObjectId_t m_Id; - - template friend class CParticleOperatorDefinition; -}; - -class CParticleRenderOperatorInstance : public CParticleOperatorInstance -{ -public: - - CParticleVisibilityInputs VisibilityInputs; -}; - -//----------------------------------------------------------------------------- -// Helper macro for creating particle operator factories -//----------------------------------------------------------------------------- -template < class T > -class CParticleOperatorDefinition : public IParticleOperatorDefinition -{ -public: - CParticleOperatorDefinition( const char *pFactoryName, ParticleOperatorId_t id, bool bIsObsolete ) : m_pFactoryName( pFactoryName ), m_Id( id ) - { - m_flTotalExecutionTime = 0.0f; - m_flMaxExecutionTime = 0.0f; - m_flUncomittedTime = 0.0f; - m_bIsObsolete = bIsObsolete; - } - - virtual const char *GetName() const - { - return m_pFactoryName; - } - - virtual ParticleOperatorId_t GetId() const - { - return m_Id; - } - - virtual CParticleOperatorInstance *CreateInstance( const DmObjectId_t &id ) const - { - CParticleOperatorInstance *pOp = new T; - pOp->SetDefinition( this, id ); - return pOp; - } - - virtual const DmxElementUnpackStructure_t* GetUnpackStructure() const - { - return m_pUnpackParams; - } - - // Editor won't display obsolete operators - virtual bool IsObsolete() const - { - return m_bIsObsolete; - } - -private: - const char *m_pFactoryName; - ParticleOperatorId_t m_Id; - bool m_bIsObsolete; - static DmxElementUnpackStructure_t *m_pUnpackParams; -}; - -#define DECLARE_PARTICLE_OPERATOR( _className ) \ - DECLARE_DMXELEMENT_UNPACK() \ - friend class CParticleOperatorDefinition<_className > - -#define DEFINE_PARTICLE_OPERATOR( _className, _operatorName, _id ) \ - static CParticleOperatorDefinition<_className> s_##_className##Factory( _operatorName, _id, false ) - -#define DEFINE_PARTICLE_OPERATOR_OBSOLETE( _className, _operatorName, _id ) \ - static CParticleOperatorDefinition<_className> s_##_className##Factory( _operatorName, _id, true ) - -#define BEGIN_PARTICLE_OPERATOR_UNPACK( _className ) \ - BEGIN_DMXELEMENT_UNPACK( _className ) \ - DMXELEMENT_UNPACK_FIELD( "operator start fadein","0", float, m_flOpStartFadeInTime ) \ - DMXELEMENT_UNPACK_FIELD( "operator end fadein","0", float, m_flOpEndFadeInTime ) \ - DMXELEMENT_UNPACK_FIELD( "operator start fadeout","0", float, m_flOpStartFadeOutTime ) \ - DMXELEMENT_UNPACK_FIELD( "operator end fadeout","0", float, m_flOpEndFadeOutTime ) \ - DMXELEMENT_UNPACK_FIELD( "operator fade oscillate","0", float, m_flOpFadeOscillatePeriod ) - -#define END_PARTICLE_OPERATOR_UNPACK( _className ) \ - END_DMXELEMENT_UNPACK_TEMPLATE( _className, CParticleOperatorDefinition<_className>::m_pUnpackParams ) - -#define BEGIN_PARTICLE_RENDER_OPERATOR_UNPACK( _className ) \ - BEGIN_PARTICLE_OPERATOR_UNPACK( _className ) \ - DMXELEMENT_UNPACK_FIELD( "Visibility Proxy Input Control Point Number", "-1", int, VisibilityInputs.m_nCPin ) \ - DMXELEMENT_UNPACK_FIELD( "Visibility Proxy Radius", "1.0", float, VisibilityInputs.m_flProxyRadius ) \ - DMXELEMENT_UNPACK_FIELD( "Visibility input minimum","0", float, VisibilityInputs.m_flInputMin ) \ - DMXELEMENT_UNPACK_FIELD( "Visibility input maximum","1", float, VisibilityInputs.m_flInputMax ) \ - DMXELEMENT_UNPACK_FIELD( "Visibility Alpha Scale minimum","0", float, VisibilityInputs.m_flAlphaScaleMin ) \ - DMXELEMENT_UNPACK_FIELD( "Visibility Alpha Scale maximum","1", float, VisibilityInputs.m_flAlphaScaleMax ) \ - DMXELEMENT_UNPACK_FIELD( "Visibility Radius Scale minimum","1", float, VisibilityInputs.m_flRadiusScaleMin ) \ - DMXELEMENT_UNPACK_FIELD( "Visibility Radius Scale maximum","1", float, VisibilityInputs.m_flRadiusScaleMax ) -// DMXELEMENT_UNPACK_FIELD( "Visibility Use Bounding Box for Proxy", "0", bool, VisibilityInputs.m_bUseBBox ) -// DMXELEMENT_UNPACK_FIELD( "Visibility Bounding Box Scale", "1.0", float, VisibilityInputs.m_flBBoxScale ) - -#define REGISTER_PARTICLE_OPERATOR( _type, _className ) \ - g_pParticleSystemMgr->AddParticleOperator( _type, &s_##_className##Factory ) - - -// need to think about particle constraints in terms of segregating affected particles so as to -// run multi-pass constraints on only a subset - - -//----------------------------------------------------------------------------- -// flags for particle systems -//----------------------------------------------------------------------------- -enum -{ - PCFLAGS_FIRST_FRAME = 0x1, - PCFLAGS_PREV_CONTROL_POINTS_INITIALIZED = 0x2, -}; - - - -#define DEBUG_PARTICLE_SORT 0 - -// sorting functionality for rendering. Call GetRenderList( bool bSorted ) to get the list of -// particles to render (sorted or not, including children). -// **do not casually change this structure**. The sorting code treats it interchangably as an SOA -// and accesses it using sse. Any changes to this struct need the sort code updated.** -struct ParticleRenderData_t -{ - float m_flSortKey; // what we sort by - int m_nIndex; // index or fudged index (for child particles) - float m_flRadius; // effective radius, using visibility -#if LITTLE_ENDIAN - uint8 m_nAlpha; // effective alpha, combining alpha and alpha2 and vis. 0 - 255 - uint8 m_nAlphaPad[3]; // this will be written to -#else - uint8 m_nAlphaPad[3]; // this will be written to - uint8 m_nAlpha; // effective alpha, combining alpha and alpha2 and vis. 0 - 255 -#endif -}; - -struct ExtendedParticleRenderData_t : ParticleRenderData_t -{ - float m_flX; - float m_flY; - float m_flZ; - float m_flPad; -}; - - -typedef struct ALIGN16 _FourInts -{ - int32 m_nValue[4]; -} FourInts; - - - -// structure describing the parameter block used by operators which use the path between two points to -// control particles. -struct CPathParameters -{ - int m_nStartControlPointNumber; - int m_nEndControlPointNumber; - int m_nBulgeControl; - float m_flBulge; - float m_flMidPoint; - - void ClampControlPointIndices( void ) - { - m_nStartControlPointNumber = MAX(0, MIN( MAX_PARTICLE_CONTROL_POINTS-1, m_nStartControlPointNumber ) ); - m_nEndControlPointNumber = MAX(0, MIN( MAX_PARTICLE_CONTROL_POINTS-1, m_nEndControlPointNumber ) ); - } -}; - -struct CParticleVisibilityData -{ - float m_flAlphaVisibility; - float m_flRadiusVisibility; - bool m_bUseVisibility; -}; - -struct CParticleControlPoint -{ - Vector m_Position; - Vector m_PrevPosition; - - // orientation - Vector m_ForwardVector; - Vector m_UpVector; - Vector m_RightVector; - - // reference to entity or whatever this control point comes from - void *m_pObject; - - // parent for hierarchies - int m_nParent; -}; - - -// struct for simd xform to transform a point from an identitiy coordinate system to that of the control point -struct CParticleSIMDTransformation -{ - FourVectors m_v4Origin; - FourVectors m_v4Fwd; - FourVectors m_v4Up; - FourVectors m_v4Right; - - - FORCEINLINE void VectorRotate( FourVectors &InPnt ) - { - fltx4 fl4OutX = SubSIMD( AddSIMD( MulSIMD( InPnt.x, m_v4Fwd.x ), MulSIMD( InPnt.z, m_v4Up.x ) ), MulSIMD( InPnt.y, m_v4Right.x ) ); - fltx4 fl4OutY = SubSIMD( AddSIMD( MulSIMD( InPnt.x, m_v4Fwd.y ), MulSIMD( InPnt.z, m_v4Up.y ) ), MulSIMD( InPnt.y, m_v4Right.y ) ); - InPnt.z = SubSIMD( AddSIMD( MulSIMD( InPnt.x, m_v4Fwd.z ), MulSIMD( InPnt.z, m_v4Up.z ) ), MulSIMD( InPnt.y, m_v4Right.z ) ); - InPnt.x = fl4OutX; - InPnt.y = fl4OutY; - } - - FORCEINLINE void VectorTransform( FourVectors &InPnt ) - { - VectorRotate( InPnt ); - InPnt.x = AddSIMD( InPnt.x, m_v4Origin.x ); - InPnt.y = AddSIMD( InPnt.y, m_v4Origin.y ); - InPnt.z = AddSIMD( InPnt.z, m_v4Origin.z ); - } -}; - -#define NUM_COLLISION_CACHE_MODES 4 - -//----------------------------------------------------------------------------- -// -// CParticleCollection -// -//----------------------------------------------------------------------------- -class CParticleCollection -{ -public: - ~CParticleCollection( void ); - - // Restarts the particle collection, stopping all non-continuous emitters - void Restart(); - - // compute bounds from particle list - void RecomputeBounds( void ); - - void SetControlPoint( int nWhichPoint, const Vector &v ); - void SetControlPointObject( int nWhichPoint, void *pObject ); - - void SetControlPointOrientation( int nWhichPoint, const Vector &forward, - const Vector &right, const Vector &up ); - void SetControlPointOrientation( int nWhichPoint, const Quaternion &q ); - void SetControlPointForwardVector( int nWhichPoint, const Vector &v ); - void SetControlPointUpVector( int nWhichPoint, const Vector &v ); - void SetControlPointRightVector( int nWhichPoint, const Vector &v ); - void SetControlPointParent( int nWhichPoint, int n ); - - // get the pointer to an attribute for a given particle. - // !!speed!! if you find yourself calling this anywhere that matters, - // you're not handling the simd-ness of the particle system well - // and will have bad perf. - const float *GetFloatAttributePtr( int nAttribute, int nParticleNumber ) const; - const int *GetIntAttributePtr( int nAttribute, int nParticleNumber ) const; - const fltx4 *GetM128AttributePtr( int nAttribute, size_t *pStrideOut ) const; - const FourVectors *Get4VAttributePtr( int nAttribute, size_t *pStrideOut ) const; - const FourInts *Get4IAttributePtr( int nAttribute, size_t *pStrideOut ) const; - const int *GetIntAttributePtr( int nAttribute, size_t *pStrideOut ) const; - - - int *GetIntAttributePtrForWrite( int nAttribute, int nParticleNumber ); - - float *GetFloatAttributePtrForWrite( int nAttribute, int nParticleNumber ); - fltx4 *GetM128AttributePtrForWrite( int nAttribute, size_t *pStrideOut ); - FourVectors *Get4VAttributePtrForWrite( int nAttribute, size_t *pStrideOut ); - - const float *GetInitialFloatAttributePtr( int nAttribute, int nParticleNumber ) const; - const fltx4 *GetInitialM128AttributePtr( int nAttribute, size_t *pStrideOut ) const; - const FourVectors *GetInitial4VAttributePtr( int nAttribute, size_t *pStrideOut ) const; - float *GetInitialFloatAttributePtrForWrite( int nAttribute, int nParticleNumber ); - fltx4 *GetInitialM128AttributePtrForWrite( int nAttribute, size_t *pStrideOut ); - - void Simulate( float dt ); - void SkipToTime( float t ); - - // the camera objetc may be compared for equality against control point objects - void Render( IMatRenderContext *pRenderContext, bool bTranslucentOnly = false, void *pCameraObject = NULL ); - - bool IsValid( void ) const { return m_pDef != NULL; } - const char *GetName() const; - - // IsFinished returns true when a system has no particles and won't be creating any more - bool IsFinished( void ); - - // Used to make sure we're accessing valid memory - bool IsValidAttributePtr( int nAttribute, const void *pPtr ) const; - - void SwapPosAndPrevPos( void ); - - void SetNActiveParticles( int nCount ); - void KillParticle(int nPidx); - - void StopEmission( bool bInfiniteOnly = false, bool bRemoveAllParticles = false, bool bWakeOnStop = false ); - void StartEmission( bool bInfiniteOnly = false ); - void SetDormant( bool bDormant ); - - const Vector& GetControlPointAtCurrentTime( int nControlPoint ) const; - void GetControlPointOrientationAtCurrentTime( int nControlPoint, Vector *pForward, Vector *pRight, Vector *pUp ) const; - void GetControlPointTransformAtCurrentTime( int nControlPoint, matrix3x4_t *pMat ); - void GetControlPointTransformAtCurrentTime( int nControlPoint, VMatrix *pMat ); - int GetControlPointParent( int nControlPoint ) const; - - - // Used to retrieve the position of a control point - // somewhere between m_fCurTime and m_fCurTime - m_fPreviousDT - void GetControlPointAtTime( int nControlPoint, float flTime, Vector *pControlPoint ); - void GetControlPointAtPrevTime( int nControlPoint, Vector *pControlPoint ); - void GetControlPointOrientationAtTime( int nControlPoint, float flTime, Vector *pForward, Vector *pRight, Vector *pUp ); - void GetControlPointTransformAtTime( int nControlPoint, float flTime, matrix3x4_t *pMat ); - void GetControlPointTransformAtTime( int nControlPoint, float flTime, VMatrix *pMat ); - void GetControlPointTransformAtTime( int nControlPoint, float flTime, CParticleSIMDTransformation *pXForm ); - int GetHighestControlPoint( void ) const; - - // Control point accessed: - // NOTE: Unlike the definition's version of these methods, - // these OR-in the masks of their children. - bool ReadsControlPoint( int nPoint ) const; - - // Used by particle systems to generate random numbers. Do not call these methods - use sse - // code - int RandomInt( int nMin, int nMax ); - float RandomFloat( float flMin, float flMax ); - float RandomFloatExp( float flMin, float flMax, float flExponent ); - void RandomVector( float flMin, float flMax, Vector *pVector ); - void RandomVector( const Vector &vecMin, const Vector &vecMax, Vector *pVector ); - float RandomVectorInUnitSphere( Vector *pVector ); // Returns the length sqr of the vector - - // NOTE: These versions will produce the *same random numbers* if you give it the same random - // sample id. do not use these methods. - int RandomInt( int nRandomSampleId, int nMin, int nMax ); - float RandomFloat( int nRandomSampleId, float flMin, float flMax ); - float RandomFloatExp( int nRandomSampleId, float flMin, float flMax, float flExponent ); - void RandomVector( int nRandomSampleId, float flMin, float flMax, Vector *pVector ); - void RandomVector( int nRandomSampleId, const Vector &vecMin, const Vector &vecMax, Vector *pVector ); - float RandomVectorInUnitSphere( int nRandomSampleId, Vector *pVector ); // Returns the length sqr of the vector - - fltx4 RandomFloat( const FourInts &ParticleID, int nRandomSampleOffset ); - - - // Random number offset (for use in getting Random #s in operators) - int OperatorRandomSampleOffset() const; - - // Returns the render bounds - void GetBounds( Vector *pMin, Vector *pMax ); - - // Visualize operators (for editing/debugging) - void VisualizeOperator( const DmObjectId_t *pOpId = NULL ); - - // Does the particle system use the power of two frame buffer texture (refraction?) - bool UsesPowerOfTwoFrameBufferTexture( bool bThisFrame ) const; - - // Does the particle system use the full frame buffer texture (soft particles) - bool UsesFullFrameBufferTexture( bool bThisFrame ) const; - - // Is the particle system translucent? - bool IsTranslucent() const; - - // Is the particle system two-pass? - bool IsTwoPass() const; - - // Is the particle system batchable? - bool IsBatchable() const; - - // Renderer iteration - int GetRendererCount() const; - CParticleOperatorInstance *GetRenderer( int i ); - void *GetRendererContext( int i ); - - - bool CheckIfOperatorShouldRun( CParticleOperatorInstance const * op, float *pflCurStrength = NULL ); - - Vector TransformAxis( const Vector &SrcAxis, bool bLocalSpace, int nControlPointNumber = 0); - - // return backwards-sorted particle list. use --addressing - const ParticleRenderData_t *GetRenderList( IMatRenderContext *pRenderContext, bool bSorted, int *pNparticles, CParticleVisibilityData *pVisibilityData ); - - // calculate the points of a curve for a path - void CalculatePathValues( CPathParameters const &PathIn, - float flTimeStamp, - Vector *pStartPnt, - Vector *pMidPnt, - Vector *pEndPnt - ); - - int GetGroupID() const; - - void InitializeNewParticles( int nFirstParticle, int nParticleCount, uint32 nInittedMask ); - - // update hit boxes for control point if not updated yet for this sim step - void UpdateHitBoxInfo( int nControlPointNumber ); - - // Used by particle system definitions to manage particle collection lists - void UnlinkFromDefList( ); - - CParticleCollection *GetNextCollectionUsingSameDef() { return m_pNextDef; } - - CUtlReference< CSheet > m_Sheet; - - - -protected: - CParticleCollection( ); - - // Used by client code - bool Init( const char *pParticleSystemName ); - bool Init( CParticleSystemDefinition *pDef ); - - // Bloat the bounding box by bounds around the control point - void BloatBoundsUsingControlPoint(); - -private: - void GenerateSortedIndexList( Vector vecCameraPos, CParticleVisibilityData *pVisibilityData, bool bSorted ); - - void Init( CParticleSystemDefinition *pDef, float flDelay, int nRandomSeed ); - void InitStorage( CParticleSystemDefinition *pDef ); - void InitParticleCreationTime( int nFirstParticle, int nNumToInit ); - void CopyInitialAttributeValues( int nStartParticle, int nNumParticles ); - void ApplyKillList( void ); - void SetAttributeToConstant( int nAttribute, float fValue ); - void SetAttributeToConstant( int nAttribute, float fValueX, float fValueY, float fValueZ ); - void InitParticleAttributes( int nStartParticle, int nNumParticles, int nAttrsLeftToInit ); - - // initialize this attribute for all active particles - void FillAttributeWithConstant( int nAttribute, float fValue ); - - // Updates the previous control points - void UpdatePrevControlPoints( float dt ); - - // Returns the memory for a particular constant attribute - float *GetConstantAttributeMemory( int nAttribute ); - - // Swaps two particles in the particle list - void SwapAdjacentParticles( int hParticle ); - - // Unlinks a particle from the list - void UnlinkParticle( int hParticle ); - - // Inserts a particle before another particle in the list - void InsertParticleBefore( int hParticle, int hBefore ); - - // Move a particle from one index to another - void MoveParticle( int nInitialIndex, int nNewIndex ); - - // Computes the sq distance to a particle position - float ComputeSqrDistanceToParticle( int hParticle, const Vector &vecPosition ) const; - - // Grows the dist sq range for all particles - void GrowDistSqrBounds( float flDistSqr ); - - // Simulates the first frame - void SimulateFirstFrame( ); - - bool SystemContainsParticlesWithBoolSet( bool CParticleCollection::*pField ) const; - // Does the particle collection contain opaque particle systems - bool ContainsOpaqueCollections(); - bool ComputeUsesPowerOfTwoFrameBufferTexture(); - bool ComputeUsesFullFrameBufferTexture(); - bool ComputeIsTranslucent(); - bool ComputeIsTwoPass(); - bool ComputeIsBatchable(); - - void LabelTextureUsage( void ); - - void LinkIntoDefList( ); - -public: - fltx4 m_fl4CurTime; // accumulated time - - int m_nPaddedActiveParticles; // # of groups of 4 particles - float m_flCurTime; // accumulated time - - int m_nActiveParticles; // # of active particles - float m_flDt; - float m_flPreviousDt; - float m_flNextSleepTime; // time to go to sleep if not drawn - - CUtlReference< CParticleSystemDefinition > m_pDef; - int m_nAllocatedParticles; - int m_nMaxAllowedParticles; - bool m_bDormant; - bool m_bEmissionStopped; - - int m_LocalLightingCP; - Color m_LocalLighting; - - // control point data. Don't set these directly, or they won't propagate down to children - // particle control points can act as emitter centers, repulsions points, etc. what they are - // used for depends on what operators and parameters your system has. - CParticleControlPoint m_ControlPoints[MAX_PARTICLE_CONTROL_POINTS]; - - CModelHitBoxesInfo m_ControlPointHitBoxes[MAX_PARTICLE_CONTROL_POINTS]; - - // public so people can call methods - uint8 *m_pOperatorContextData; - CParticleCollection *m_pNext; // for linking children together - CParticleCollection *m_pPrev; // for linking children together - - struct CWorldCollideContextData *m_pCollisionCacheData[NUM_COLLISION_CACHE_MODES]; // children can share collision caches w/ parent - CParticleCollection *m_pParent; - - CUtlIntrusiveDList m_Children; // list for all child particle systems - - void *operator new(size_t nSize); - void *operator new( size_t size, int nBlockUse, const char *pFileName, int nLine ); - void operator delete(void *pData); - void operator delete( void* p, int nBlockUse, const char *pFileName, int nLine ); - - -protected: - // current bounds for the particle system - bool m_bBoundsValid; - Vector m_MinBounds; - Vector m_MaxBounds; - int m_nHighestCP; //Highest CP set externally. Needs to assert if a system calls to an unassigned CP. - -private: - - - unsigned char *m_pParticleMemory; // fixed size at initialization. Must be aligned for SSE - unsigned char *m_pParticleInitialMemory; // fixed size at initialization. Must be aligned for SSE - unsigned char *m_pConstantMemory; - - int m_nPerParticleInitializedAttributeMask; - int m_nPerParticleUpdatedAttributeMask; - int m_nPerParticleReadInitialAttributeMask; // What fields do operators want to see initial attribute values for? - float *m_pParticleAttributes[MAX_PARTICLE_ATTRIBUTES]; - float *m_pParticleInitialAttributes[MAX_PARTICLE_ATTRIBUTES]; - size_t m_nParticleFloatStrides[MAX_PARTICLE_ATTRIBUTES]; - size_t m_nParticleInitialFloatStrides[MAX_PARTICLE_ATTRIBUTES]; - - float *m_pConstantAttributes; - - uint64 m_nControlPointReadMask; // Mask indicating which control points have been accessed - int m_nParticleFlags; // PCFLAGS_xxx - bool m_bIsScrubbable : 1; - bool m_bIsRunningInitializers : 1; - bool m_bIsRunningOperators : 1; - bool m_bIsTranslucent : 1; - bool m_bIsTwoPass : 1; - bool m_bAnyUsesPowerOfTwoFrameBufferTexture : 1; // whether or not we or any children use this - bool m_bAnyUsesFullFrameBufferTexture : 1; - bool m_bIsBatchable : 1; - - bool m_bUsesPowerOfTwoFrameBufferTexture; // whether or not we use this, _not_ our children - bool m_bUsesFullFrameBufferTexture; - - // How many frames have we drawn? - int m_nDrawnFrames; - - Vector m_Center; // average of particle centers - - // Used to assign unique ids to each particle - int m_nUniqueParticleId; - - // Used to generate random numbers - int m_nRandomQueryCount; - int m_nRandomSeed; - int m_nOperatorRandomSampleOffset; - - float m_flMinDistSqr; - float m_flMaxDistSqr; - float m_flOOMaxDistSqr; - Vector m_vecLastCameraPos; - float m_flLastMinDistSqr; - float m_flLastMaxDistSqr; - - // Particle collection kill list. set up by particle system mgr - int m_nNumParticlesToKill; - int *m_pParticleKillList; - - // Used to build a list of all particle collections that have the same particle def - CParticleCollection *m_pNextDef; - CParticleCollection *m_pPrevDef; - - void LoanKillListTo( CParticleCollection *pBorrower ) const; - bool HasAttachedKillList( void ) const; - - - // For debugging - CParticleOperatorInstance *m_pRenderOp; - friend class CParticleSystemMgr; - friend class CParticleOperatorInstance; -}; - - - -class CM128InitialAttributeIterator : public CStridedConstPtr -{ -public: - FORCEINLINE CM128InitialAttributeIterator( int nAttribute, CParticleCollection *pParticles ) - { - m_pData = pParticles->GetInitialM128AttributePtr( nAttribute, &m_nStride ); - } -}; - - -class CM128AttributeIterator : public CStridedConstPtr -{ -public: - FORCEINLINE CM128AttributeIterator( int nAttribute, CParticleCollection *pParticles ) - { - m_pData = pParticles->GetM128AttributePtr( nAttribute, &m_nStride ); - } -}; - -class C4IAttributeIterator : public CStridedConstPtr -{ -public: - FORCEINLINE C4IAttributeIterator( int nAttribute, CParticleCollection *pParticles ) - { - m_pData = pParticles->Get4IAttributePtr( nAttribute, &m_nStride ); - } -}; - -class CM128AttributeWriteIterator : public CStridedPtr -{ -public: - FORCEINLINE CM128AttributeWriteIterator( void ) - { - } - FORCEINLINE void Init ( int nAttribute, CParticleCollection *pParticles ) - { - m_pData = pParticles->GetM128AttributePtrForWrite( nAttribute, &m_nStride ); - } - FORCEINLINE CM128AttributeWriteIterator( int nAttribute, CParticleCollection *pParticles ) - { - Init( nAttribute, pParticles ); - } -}; - -class C4VAttributeIterator : public CStridedConstPtr -{ -public: - FORCEINLINE C4VAttributeIterator( int nAttribute, CParticleCollection *pParticles ) - { - m_pData = pParticles->Get4VAttributePtr( nAttribute, &m_nStride ); - } -}; - -class C4VInitialAttributeIterator : public CStridedConstPtr -{ -public: - FORCEINLINE C4VInitialAttributeIterator( int nAttribute, CParticleCollection *pParticles ) - { - m_pData = pParticles->GetInitial4VAttributePtr( nAttribute, &m_nStride ); - } -}; - -class C4VAttributeWriteIterator : public CStridedPtr -{ -public: - FORCEINLINE C4VAttributeWriteIterator( int nAttribute, CParticleCollection *pParticles ) - { - m_pData = pParticles->Get4VAttributePtrForWrite( nAttribute, &m_nStride ); - } -}; - - -//----------------------------------------------------------------------------- -// Inline methods of CParticleCollection -//----------------------------------------------------------------------------- - -inline bool CParticleCollection::HasAttachedKillList( void ) const -{ - return m_pParticleKillList != NULL; -} - -inline bool CParticleCollection::ReadsControlPoint( int nPoint ) const -{ - return ( m_nControlPointReadMask & ( 1ULL << nPoint ) ) != 0; -} - -inline void CParticleCollection::SetNActiveParticles( int nCount ) -{ - Assert( nCount <= m_nMaxAllowedParticles ); - m_nActiveParticles = nCount; - m_nPaddedActiveParticles = ( nCount+3 )/4; -} - -inline void CParticleCollection::SwapPosAndPrevPos( void ) -{ - // strides better be the same! - Assert( m_nParticleFloatStrides[PARTICLE_ATTRIBUTE_XYZ] == m_nParticleFloatStrides[ PARTICLE_ATTRIBUTE_PREV_XYZ ] ); - swap( m_pParticleAttributes[ PARTICLE_ATTRIBUTE_XYZ ], m_pParticleAttributes[ PARTICLE_ATTRIBUTE_PREV_XYZ ] ); -} - -inline void CParticleCollection::LoanKillListTo( CParticleCollection *pBorrower ) const -{ - Assert(! pBorrower->m_pParticleKillList ); - pBorrower->m_nNumParticlesToKill = 0; - pBorrower->m_pParticleKillList = m_pParticleKillList; -} - -inline void CParticleCollection::SetAttributeToConstant( int nAttribute, float fValue ) -{ - float *fconst = m_pConstantAttributes + 4*3*nAttribute; - fconst[0] = fconst[1] = fconst[2] = fconst[3] = fValue; -} - -inline void CParticleCollection::SetAttributeToConstant( int nAttribute, float fValueX, float fValueY, float fValueZ ) -{ - float *fconst = m_pConstantAttributes + 4*3*nAttribute; - fconst[0] = fconst[1] = fconst[2] = fconst[3] = fValueX; - fconst[4] = fconst[5] = fconst[6] = fconst[7] = fValueY; - fconst[8] = fconst[9] = fconst[10] = fconst[11] = fValueZ; -} - -inline void CParticleCollection::SetControlPoint( int nWhichPoint, const Vector &v ) -{ - Assert( ( nWhichPoint >= 0) && ( nWhichPoint < MAX_PARTICLE_CONTROL_POINTS ) ); - m_nHighestCP = MAX( m_nHighestCP, nWhichPoint ); - m_ControlPoints[ nWhichPoint ].m_Position = v; - for( CParticleCollection *i = m_Children.m_pHead; i; i=i->m_pNext ) - { - i->SetControlPoint( nWhichPoint, v ); - } -} - -inline void CParticleCollection::SetControlPointObject( int nWhichPoint, void *pObject ) -{ - Assert( ( nWhichPoint >= 0) && ( nWhichPoint < MAX_PARTICLE_CONTROL_POINTS ) ); - m_ControlPoints[ nWhichPoint ].m_pObject = pObject; - for( CParticleCollection *i = m_Children.m_pHead; i; i=i->m_pNext ) - { - i->SetControlPointObject( nWhichPoint, pObject ); - } -} - -inline void CParticleCollection::SetControlPointOrientation( int nWhichPoint, const Vector &forward, - const Vector &right, const Vector &up ) -{ - Assert( ( nWhichPoint >= 0) && ( nWhichPoint < MAX_PARTICLE_CONTROL_POINTS ) ); - - // check perpendicular - Assert( fabs( DotProduct( forward, up ) ) <= 0.1f ); - Assert( fabs( DotProduct( forward, right ) ) <= 0.1f ); - Assert( fabs( DotProduct( right, up ) ) <= 0.1f ); - - m_ControlPoints[ nWhichPoint ].m_ForwardVector = forward; - m_ControlPoints[ nWhichPoint ].m_UpVector = up; - m_ControlPoints[ nWhichPoint ].m_RightVector = right; - - // make sure all children are finished - for( CParticleCollection *i = m_Children.m_pHead; i; i=i->m_pNext ) - { - i->SetControlPointOrientation( nWhichPoint, forward, right, up ); - } -} - -inline Vector CParticleCollection::TransformAxis( const Vector &SrcAxis, bool bLocalSpace, - int nControlPointNumber) -{ - if ( bLocalSpace ) - { - return // mxmul - ( SrcAxis.x*m_ControlPoints[nControlPointNumber].m_RightVector )+ - ( SrcAxis.y*m_ControlPoints[nControlPointNumber].m_ForwardVector )+ - ( SrcAxis.z*m_ControlPoints[nControlPointNumber].m_UpVector ); - } - else - return SrcAxis; -} - - -inline void CParticleCollection::SetControlPointOrientation( int nWhichPoint, const Quaternion &q ) -{ - matrix3x4_t mat; - Vector vecForward, vecUp, vecRight; - QuaternionMatrix( q, mat ); - MatrixVectors( mat, &vecForward, &vecRight, &vecUp ); - SetControlPointOrientation( nWhichPoint, vecForward, vecRight, vecUp ); -} - -inline void CParticleCollection::SetControlPointForwardVector( int nWhichPoint, const Vector &v) -{ - Assert( ( nWhichPoint >= 0) && ( nWhichPoint < MAX_PARTICLE_CONTROL_POINTS ) ); - m_ControlPoints[ nWhichPoint ].m_ForwardVector = v; - for( CParticleCollection *i = m_Children.m_pHead; i; i=i->m_pNext ) - { - i->SetControlPointForwardVector( nWhichPoint, v ); - } -} - -inline void CParticleCollection::SetControlPointUpVector( int nWhichPoint, const Vector &v) -{ - Assert( ( nWhichPoint >= 0) && ( nWhichPoint < MAX_PARTICLE_CONTROL_POINTS ) ); - m_ControlPoints[ nWhichPoint ].m_UpVector = v; - for( CParticleCollection *i = m_Children.m_pHead; i; i=i->m_pNext ) - { - i->SetControlPointUpVector( nWhichPoint, v ); - } -} - -inline void CParticleCollection::SetControlPointRightVector( int nWhichPoint, const Vector &v) -{ - Assert( ( nWhichPoint >= 0) && ( nWhichPoint < MAX_PARTICLE_CONTROL_POINTS ) ); - m_ControlPoints[ nWhichPoint ].m_RightVector = v; - for( CParticleCollection *i = m_Children.m_pHead; i; i=i->m_pNext ) - { - i->SetControlPointRightVector( nWhichPoint, v ); - } -} - -inline void CParticleCollection::SetControlPointParent( int nWhichPoint, int n ) -{ - Assert( ( nWhichPoint >= 0) && ( nWhichPoint < MAX_PARTICLE_CONTROL_POINTS ) ); - m_ControlPoints[ nWhichPoint ].m_nParent = n; - for( CParticleCollection *i = m_Children.m_pHead; i; i=i->m_pNext ) - { - i->SetControlPointParent( nWhichPoint, n ); - } -} - - -// Returns the memory for a particular constant attribute -inline float *CParticleCollection::GetConstantAttributeMemory( int nAttribute ) -{ - return m_pConstantAttributes + 3 * 4 * nAttribute; -} - -// Random number offset (for use in getting Random #s in operators) -inline int CParticleCollection::OperatorRandomSampleOffset() const -{ - return m_nOperatorRandomSampleOffset; -} - -// Used by particle systems to generate random numbers -inline int CParticleCollection::RandomInt( int nRandomSampleId, int nMin, int nMax ) -{ - // do not call - float flRand = s_pRandomFloats[ ( m_nRandomSeed + nRandomSampleId ) & RANDOM_FLOAT_MASK ]; - flRand *= ( nMax + 1 - nMin ); - int nRand = (int)flRand + nMin; - return nRand; -} - -inline float CParticleCollection::RandomFloat( int nRandomSampleId, float flMin, float flMax ) -{ - // do not call - float flRand = s_pRandomFloats[ ( m_nRandomSeed + nRandomSampleId ) & RANDOM_FLOAT_MASK ]; - flRand *= ( flMax - flMin ); - flRand += flMin; - return flRand; -} - -inline fltx4 CParticleCollection::RandomFloat( const FourInts &ParticleID, int nRandomSampleOffset ) -{ - fltx4 Retval; - int nOfs=m_nRandomSeed+nRandomSampleOffset; - SubFloat( Retval, 0 ) = s_pRandomFloats[ ( nOfs + ParticleID.m_nValue[0] ) & RANDOM_FLOAT_MASK ]; - SubFloat( Retval, 1 ) = s_pRandomFloats[ ( nOfs + ParticleID.m_nValue[1] ) & RANDOM_FLOAT_MASK ]; - SubFloat( Retval, 2 ) = s_pRandomFloats[ ( nOfs + ParticleID.m_nValue[2] ) & RANDOM_FLOAT_MASK ]; - SubFloat( Retval, 3 ) = s_pRandomFloats[ ( nOfs + ParticleID.m_nValue[3] ) & RANDOM_FLOAT_MASK ]; - return Retval; -} - - -inline float CParticleCollection::RandomFloatExp( int nRandomSampleId, float flMin, float flMax, float flExponent ) -{ - // do not call - float flRand = s_pRandomFloats[ ( m_nRandomSeed + nRandomSampleId ) & RANDOM_FLOAT_MASK ]; - flRand = powf( flRand, flExponent ); - flRand *= ( flMax - flMin ); - flRand += flMin; - return flRand; -} - -inline void CParticleCollection::RandomVector( int nRandomSampleId, float flMin, float flMax, Vector *pVector ) -{ - // do not call - float flDelta = flMax - flMin; - int nBaseId = m_nRandomSeed + nRandomSampleId; - - pVector->x = s_pRandomFloats[ nBaseId & RANDOM_FLOAT_MASK ]; - pVector->x *= flDelta; - pVector->x += flMin; - - pVector->y = s_pRandomFloats[ ( nBaseId + 1 ) & RANDOM_FLOAT_MASK ]; - pVector->y *= flDelta; - pVector->y += flMin; - - pVector->z = s_pRandomFloats[ ( nBaseId + 2 ) & RANDOM_FLOAT_MASK ]; - pVector->z *= flDelta; - pVector->z += flMin; -} - -inline void CParticleCollection::RandomVector( int nRandomSampleId, const Vector &vecMin, const Vector &vecMax, Vector *pVector ) -{ - // do not call - int nBaseId = m_nRandomSeed + nRandomSampleId; - pVector->x = RandomFloat( nBaseId, vecMin.x, vecMax.x ); - pVector->y = RandomFloat( nBaseId + 1, vecMin.y, vecMax.y ); - pVector->z = RandomFloat( nBaseId + 2, vecMin.z, vecMax.z ); -} - -// Used by particle systems to generate random numbers -inline int CParticleCollection::RandomInt( int nMin, int nMax ) -{ - // do not call - return RandomInt( m_nRandomQueryCount++, nMin, nMax ); -} - -inline float CParticleCollection::RandomFloat( float flMin, float flMax ) -{ - // do not call - return RandomFloat( m_nRandomQueryCount++, flMin, flMax ); -} - -inline float CParticleCollection::RandomFloatExp( float flMin, float flMax, float flExponent ) -{ - // do not call - return RandomFloatExp( m_nRandomQueryCount++, flMin, flMax, flExponent ); -} - -inline void CParticleCollection::RandomVector( float flMin, float flMax, Vector *pVector ) -{ - // do not call - RandomVector( m_nRandomQueryCount++, flMin, flMax, pVector ); -} - -inline void CParticleCollection::RandomVector( const Vector &vecMin, const Vector &vecMax, Vector *pVector ) -{ - // do not call - RandomVector( m_nRandomQueryCount++, vecMin, vecMax, pVector ); -} - -inline float CParticleCollection::RandomVectorInUnitSphere( Vector *pVector ) -{ - // do not call - return RandomVectorInUnitSphere( m_nRandomQueryCount++, pVector ); -} - - -// get the pointer to an attribute for a given particle. !!speed!! if you find yourself -// calling this anywhere that matters, you're not handling the simd-ness of the particle system -// well and will have bad perf. -inline const float *CParticleCollection::GetFloatAttributePtr( int nAttribute, int nParticleNumber ) const -{ - Assert( nParticleNumber < m_nAllocatedParticles ); - int block_ofs = nParticleNumber/4; - return m_pParticleAttributes[ nAttribute ] + - m_nParticleFloatStrides[ nAttribute ] * block_ofs + - ( nParticleNumber & 3 ); -} - -inline int *CParticleCollection::GetIntAttributePtrForWrite( int nAttribute, int nParticleNumber ) -{ - return reinterpret_cast< int* >( GetFloatAttributePtrForWrite( nAttribute, nParticleNumber ) ); -} - -inline const int *CParticleCollection::GetIntAttributePtr( int nAttribute, int nParticleNumber ) const -{ - return (int*)GetFloatAttributePtr( nAttribute, nParticleNumber ); -} - -inline const fltx4 *CParticleCollection::GetM128AttributePtr( int nAttribute, size_t *pStrideOut ) const -{ - *(pStrideOut) = m_nParticleFloatStrides[ nAttribute ]/4; - return reinterpret_cast( m_pParticleAttributes[ nAttribute ] ); -} - -inline const FourInts *CParticleCollection::Get4IAttributePtr( int nAttribute, size_t *pStrideOut ) const -{ - *(pStrideOut) = m_nParticleFloatStrides[ nAttribute ]/4; - return reinterpret_cast( m_pParticleAttributes[ nAttribute ] ); -} - -inline const int32 *CParticleCollection::GetIntAttributePtr( int nAttribute, size_t *pStrideOut ) const -{ - *(pStrideOut) = m_nParticleFloatStrides[ nAttribute ]; - return reinterpret_cast( m_pParticleAttributes[ nAttribute ] ); -} - -inline const FourVectors *CParticleCollection::Get4VAttributePtr( int nAttribute, size_t *pStrideOut ) const -{ - *(pStrideOut) = m_nParticleFloatStrides[ nAttribute ]/12; - return reinterpret_cast( m_pParticleAttributes[ nAttribute ] ); -} - -inline FourVectors *CParticleCollection::Get4VAttributePtrForWrite( int nAttribute, size_t *pStrideOut ) -{ - *(pStrideOut) = m_nParticleFloatStrides[ nAttribute ]/12; - return reinterpret_cast( m_pParticleAttributes[ nAttribute ] ); -} - -inline const FourVectors *CParticleCollection::GetInitial4VAttributePtr( int nAttribute, size_t *pStrideOut ) const -{ - *(pStrideOut) = m_nParticleInitialFloatStrides[ nAttribute ]/12; - return reinterpret_cast( m_pParticleInitialAttributes[ nAttribute ] ); -} - -inline float *CParticleCollection::GetFloatAttributePtrForWrite( int nAttribute, int nParticleNumber ) -{ - // NOTE: If you hit this assertion, it means your particle operator isn't returning - // the appropriate fields in the RequiredAttributesMask call - Assert( !m_bIsRunningInitializers || ( m_nPerParticleInitializedAttributeMask & (1 << nAttribute) ) ); - Assert( !m_bIsRunningOperators || ( m_nPerParticleUpdatedAttributeMask & (1 << nAttribute) ) ); - - Assert( m_nParticleFloatStrides[nAttribute] != 0 ); - - Assert( nParticleNumber < m_nAllocatedParticles ); - int block_ofs = nParticleNumber/4; - return m_pParticleAttributes[ nAttribute ] + - m_nParticleFloatStrides[ nAttribute ] * block_ofs + - ( nParticleNumber & 3 ); -} - -inline fltx4 *CParticleCollection::GetM128AttributePtrForWrite( int nAttribute, size_t *pStrideOut ) -{ - // NOTE: If you hit this assertion, it means your particle operator isn't returning - // the appropriate fields in the RequiredAttributesMask call - Assert( !m_bIsRunningInitializers || ( m_nPerParticleInitializedAttributeMask & (1 << nAttribute) ) ); - Assert( !m_bIsRunningOperators || ( m_nPerParticleUpdatedAttributeMask & (1 << nAttribute) ) ); - Assert( m_nParticleFloatStrides[nAttribute] != 0 ); - - *(pStrideOut) = m_nParticleFloatStrides[ nAttribute ]/4; - return reinterpret_cast( m_pParticleAttributes[ nAttribute ] ); -} - -inline const float *CParticleCollection::GetInitialFloatAttributePtr( int nAttribute, int nParticleNumber ) const -{ - Assert( nParticleNumber < m_nAllocatedParticles ); - int block_ofs = nParticleNumber / 4; - return m_pParticleInitialAttributes[ nAttribute ] + m_nParticleInitialFloatStrides[ nAttribute ] * block_ofs + ( nParticleNumber & 3 ); -} - -inline const fltx4 *CParticleCollection::GetInitialM128AttributePtr( int nAttribute, size_t *pStrideOut ) const -{ - *(pStrideOut) = m_nParticleInitialFloatStrides[ nAttribute ]/4; - return reinterpret_cast( m_pParticleInitialAttributes[ nAttribute ] ); -} - -inline float *CParticleCollection::GetInitialFloatAttributePtrForWrite( int nAttribute, int nParticleNumber ) -{ - Assert( nParticleNumber < m_nAllocatedParticles ); - Assert( m_nPerParticleReadInitialAttributeMask & ( 1 << nAttribute ) ); - int block_ofs = nParticleNumber / 4; - return m_pParticleInitialAttributes[ nAttribute ] + m_nParticleInitialFloatStrides[ nAttribute ] * block_ofs + ( nParticleNumber & 3 ); -} - -inline fltx4 *CParticleCollection::GetInitialM128AttributePtrForWrite( int nAttribute, size_t *pStrideOut ) -{ - Assert( m_nPerParticleReadInitialAttributeMask & ( 1 << nAttribute ) ); - *(pStrideOut) = m_nParticleInitialFloatStrides[ nAttribute ] / 4; - return reinterpret_cast( m_pParticleInitialAttributes[ nAttribute ] ); -} - -// Used to make sure we're accessing valid memory -inline bool CParticleCollection::IsValidAttributePtr( int nAttribute, const void *pPtr ) const -{ - if ( pPtr < m_pParticleAttributes[nAttribute] ) - return false; - - size_t nArraySize = m_nParticleFloatStrides[nAttribute] * m_nAllocatedParticles / 4; - void *pMaxPtr = m_pParticleAttributes[nAttribute] + nArraySize; - return ( pPtr <= pMaxPtr ); -} - - -FORCEINLINE void CParticleCollection::KillParticle( int nPidx ) -{ - // add a particle to the sorted kill list. entries must be added in sorted order. - // within a particle operator, this is safe to call. Outside of one, you have to call - // the ApplyKillList() method yourself. The storage for the kill list is global between - // all particle systems, so you can't kill a particle in 2 different CParticleCollections - // w/o calling ApplyKillList - - // That said, we only expect the particle index to be at most more than 3 larger than the - // particle count - Assert( nPidx < m_nActiveParticles + 4 ); - - // note that it is permissible to kill particles with indices>the number of active - // particles, in order to faciliate easy sse coding - Assert( m_nNumParticlesToKill < MAX_PARTICLES_IN_A_SYSTEM ); - m_pParticleKillList[ m_nNumParticlesToKill++ ] = nPidx; -} - -// initialize this attribute for all active particles -inline void CParticleCollection::FillAttributeWithConstant( int nAttribute, float fValue ) -{ - size_t stride; - fltx4 *pAttr = GetM128AttributePtrForWrite( nAttribute, &stride ); - fltx4 fill=ReplicateX4( fValue ); - for( int i = 0; i < m_nPaddedActiveParticles; i++ ) - { - *(pAttr) = fill; - pAttr += stride; - } -} - - -//----------------------------------------------------------------------------- -// Helper to set vector attribute values -//----------------------------------------------------------------------------- -FORCEINLINE void SetVectorAttribute( float *pAttribute, float x, float y, float z ) -{ - pAttribute[0] = x; - pAttribute[4] = y; - pAttribute[8] = z; -} - -FORCEINLINE void SetVectorAttribute( float *pAttribute, const Vector &v ) -{ - pAttribute[0] = v.x; - pAttribute[4] = v.y; - pAttribute[8] = v.z; -} - -FORCEINLINE void SetVectorFromAttribute( Vector &v, const float *pAttribute ) -{ - v.x = pAttribute[0]; - v.y = pAttribute[4]; - v.z = pAttribute[8]; -} - - -//----------------------------------------------------------------------------- -// Computes the sq distance to a particle position -//----------------------------------------------------------------------------- -FORCEINLINE float CParticleCollection::ComputeSqrDistanceToParticle( int hParticle, const Vector &vecPosition ) const -{ - const float *xyz = GetFloatAttributePtr( PARTICLE_ATTRIBUTE_XYZ, hParticle ); - Vector vecParticlePosition( xyz[0], xyz[4], xyz[8] ); - return vecParticlePosition.DistToSqr( vecPosition ); -} - - -//----------------------------------------------------------------------------- -// Grows the dist sq range for all particles -//----------------------------------------------------------------------------- -FORCEINLINE void CParticleCollection::GrowDistSqrBounds( float flDistSqr ) -{ - if ( m_flLastMinDistSqr > flDistSqr ) - { - m_flLastMinDistSqr = flDistSqr; - } - else if ( m_flLastMaxDistSqr < flDistSqr ) - { - m_flLastMaxDistSqr = flDistSqr; - } -} - - - - -//----------------------------------------------------------------------------- -// Data associated with children particle systems -//----------------------------------------------------------------------------- -struct ParticleChildrenInfo_t -{ - DmObjectId_t m_Id; - CUtlString m_Name; - bool m_bUseNameBasedLookup; - float m_flDelay; // How much to delay this system after the parent starts -}; - - -//----------------------------------------------------------------------------- -// A template describing how a particle system will function -//----------------------------------------------------------------------------- -class CParticleSystemDefinition -{ - DECLARE_DMXELEMENT_UNPACK(); - DECLARE_REFERENCED_CLASS( CParticleSystemDefinition ); - - -public: - CParticleSystemDefinition( void ); - ~CParticleSystemDefinition( void ); - - // Serialization, unserialization - void Read( CDmxElement *pElement ); - CDmxElement *Write(); - - const char *MaterialName() const; - IMaterial *GetMaterial(); - const char *GetName() const; - const DmObjectId_t& GetId() const; - - // Does the particle system use the power of two frame buffer texture (refraction?) - bool UsesPowerOfTwoFrameBufferTexture(); - - // Does the particle system use the full frame buffer texture (soft particles) - bool UsesFullFrameBufferTexture(); - - // Should we always precache this? - bool ShouldAlwaysPrecache() const; - - // Should we batch particle collections using this definition up? - bool ShouldBatch() const; - - // Is the particle system rendered on the viewmodel? - bool IsViewModelEffect() const; - - // Used to iterate over all particle collections using the same def - CParticleCollection *FirstCollection(); - - // What's the effective cull size + fill cost? - // Used for early retirement - float GetCullRadius() const; - float GetCullFillCost() const; - int GetCullControlPoint() const; - const char *GetCullReplacementDefinition() const; - - // Retirement - bool HasRetirementBeenChecked( int nFrame ) const; - void MarkRetirementCheck( int nFrame ); - - // Control point read - void MarkReadsControlPoint( int nPoint ); - bool ReadsControlPoint( int nPoint ) const; - -private: - void Precache(); - void Uncache(); - bool IsPrecached(); - - void UnlinkAllCollections(); - - void SetupContextData( ); - void ParseChildren( CDmxElement *pElement ); - void ParseOperators( const char *pszName, ParticleFunctionType_t nFunctionType, - CDmxElement *pElement, CUtlVector &out_list ); - void WriteChildren( CDmxElement *pElement ); - void WriteOperators( CDmxElement *pElement, const char *pOpKeyName, - const CUtlVector &inList ); - CUtlVector *GetOperatorList( ParticleFunctionType_t type ); - CParticleOperatorInstance *FindOperatorById( ParticleFunctionType_t type, const DmObjectId_t &id ); - -private: - int m_nInitialParticles; - int m_nPerParticleUpdatedAttributeMask; - int m_nPerParticleInitializedAttributeMask; - int m_nInitialAttributeReadMask; - int m_nAttributeReadMask; - uint64 m_nControlPointReadMask; - Vector m_BoundingBoxMin; - Vector m_BoundingBoxMax; - char m_pszMaterialName[MAX_PATH]; - CMaterialReference m_Material; - CParticleCollection *m_pFirstCollection; - char m_pszCullReplacementName[128]; - float m_flCullRadius; - float m_flCullFillCost; - int m_nCullControlPoint; - int m_nRetireCheckFrame; - - // Default attribute values - Color m_ConstantColor; - float m_flConstantRadius; - float m_flConstantRotation; - float m_flConstantRotationSpeed; - int m_nConstantSequenceNumber; - int m_nConstantSequenceNumber1; - int m_nGroupID; - float m_flMaximumTimeStep; - float m_flMaximumSimTime; // maximum time to sim before drawing first frame. - float m_flMinimumSimTime; // minimum time to sim before drawing first frame - prevents all - // capped particles from drawing at 0 time. - - int m_nMinimumFrames; // number of frames to apply max/min simulation times - - - // Is the particle system rendered on the viewmodel? - bool m_bViewModelEffect; - - - size_t m_nContextDataSize; - DmObjectId_t m_Id; - -public: - float m_flMaxDrawDistance; // distance at which to not draw. - float m_flNoDrawTimeToGoToSleep; // after not beeing seen for this long, the system will sleep - - int m_nMaxParticles; - int m_nSkipRenderControlPoint; // if the camera is attached to the - // object associated with this control - // point, don't render the system - - CUtlString m_Name; - - CUtlVector m_Operators; - CUtlVector m_Renderers; - CUtlVector m_Initializers; - CUtlVector m_Emitters; - CUtlVector m_ForceGenerators; - CUtlVector m_Constraints; - CUtlVector m_Children; - - CUtlVector m_nOperatorsCtxOffsets; - CUtlVector m_nRenderersCtxOffsets; - CUtlVector m_nInitializersCtxOffsets; - CUtlVector m_nEmittersCtxOffsets; - CUtlVector m_nForceGeneratorsCtxOffsets; - CUtlVector m_nConstraintsCtxOffsets; - - // profiling information - float m_flTotalSimTime; - float m_flUncomittedTotalSimTime; - float m_flMaxMeasuredSimTime; - int m_nMaximumActiveParticles; - bool m_bShouldSort; - bool m_bShouldBatch; - bool m_bIsPrecached : 1; - bool m_bAlwaysPrecache : 1; - - friend class CParticleCollection; - friend class CParticleSystemMgr; -}; - - -//----------------------------------------------------------------------------- -// Inline methods -//----------------------------------------------------------------------------- -inline CParticleSystemDefinition::CParticleSystemDefinition( void ) -{ - m_nControlPointReadMask = 0; - m_nInitialAttributeReadMask = 0; - m_nPerParticleInitializedAttributeMask = 0; - m_nPerParticleUpdatedAttributeMask = 0; - m_nAttributeReadMask = 0; - m_flTotalSimTime = 0.0; - m_flMaxMeasuredSimTime = 0.0; - m_nMaximumActiveParticles = 0; - m_bIsPrecached = false; - m_bAlwaysPrecache = false; - m_bShouldBatch = false; - m_bShouldSort = true; - m_pFirstCollection = NULL; - m_flCullRadius = 0.0f; - m_flCullFillCost = 1.0f; - m_nRetireCheckFrame = 0; -} - -inline CParticleSystemDefinition::~CParticleSystemDefinition( void ) -{ - UnlinkAllCollections(); - m_Operators.PurgeAndDeleteElements(); - m_Renderers.PurgeAndDeleteElements(); - m_Initializers.PurgeAndDeleteElements(); - m_Emitters.PurgeAndDeleteElements(); - m_ForceGenerators.PurgeAndDeleteElements(); - m_Constraints.PurgeAndDeleteElements(); -} - -// Used to iterate over all particle collections using the same def -inline CParticleCollection *CParticleSystemDefinition::FirstCollection() -{ - return m_pFirstCollection; -} - -inline float CParticleSystemDefinition::GetCullRadius() const -{ - return m_flCullRadius; -} - -inline float CParticleSystemDefinition::GetCullFillCost() const -{ - return m_flCullFillCost; -} - -inline const char *CParticleSystemDefinition::GetCullReplacementDefinition() const -{ - return m_pszCullReplacementName; -} - -inline int CParticleSystemDefinition::GetCullControlPoint() const -{ - return m_nCullControlPoint; -} - -inline void CParticleSystemDefinition::MarkReadsControlPoint( int nPoint ) -{ - m_nControlPointReadMask |= ( 1ULL << nPoint ); -} - -inline bool CParticleSystemDefinition::ReadsControlPoint( int nPoint ) const -{ - return ( m_nControlPointReadMask & ( 1ULL << nPoint ) ) != 0; -} - -// Retirement -inline bool CParticleSystemDefinition::HasRetirementBeenChecked( int nFrame ) const -{ - return m_nRetireCheckFrame == nFrame; -} - -inline void CParticleSystemDefinition::MarkRetirementCheck( int nFrame ) -{ - m_nRetireCheckFrame = nFrame; -} - -inline bool CParticleSystemDefinition::ShouldBatch() const -{ - return m_bShouldBatch; -} - -inline bool CParticleSystemDefinition::IsViewModelEffect() const -{ - return m_bViewModelEffect; -} - -inline const char *CParticleSystemDefinition::MaterialName() const -{ - return m_pszMaterialName; -} - -inline const DmObjectId_t& CParticleSystemDefinition::GetId() const -{ - return m_Id; -} - -inline int CParticleCollection::GetGroupID( void ) const -{ - return m_pDef->m_nGroupID; -} - -FORCEINLINE const Vector& CParticleCollection::GetControlPointAtCurrentTime( int nControlPoint ) const -{ - Assert( nControlPoint <= GetHighestControlPoint() ); - Assert( m_pDef->ReadsControlPoint( nControlPoint ) ); - return m_ControlPoints[nControlPoint].m_Position; -} - -FORCEINLINE void CParticleCollection::GetControlPointOrientationAtCurrentTime( int nControlPoint, Vector *pForward, Vector *pRight, Vector *pUp ) const -{ - Assert( nControlPoint <= GetHighestControlPoint() ); - Assert( m_pDef->ReadsControlPoint( nControlPoint ) ); - - // FIXME: Use quaternion lerp to get control point transform at time - *pForward = m_ControlPoints[nControlPoint].m_ForwardVector; - *pRight = m_ControlPoints[nControlPoint].m_RightVector; - *pUp = m_ControlPoints[nControlPoint].m_UpVector; -} - -FORCEINLINE int CParticleCollection::GetControlPointParent( int nControlPoint ) const -{ - Assert( nControlPoint <= GetHighestControlPoint() ); - Assert( m_pDef->ReadsControlPoint( nControlPoint ) ); - return m_ControlPoints[nControlPoint].m_nParent; -} - - -#endif // PARTICLES_H diff --git a/public/phonemeconverter.cpp b/public/phonemeconverter.cpp deleted file mode 100644 index 28845347c..000000000 --- a/public/phonemeconverter.cpp +++ /dev/null @@ -1,202 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// -#include -#include -#include "tier0/dbg.h" - -struct PhonemeMap_t -{ - const char *string; - int code; - float weight; - bool isStandard; - const char *desc; -}; - -static PhonemeMap_t g_Phonemes[] = -{ - { "b", 'b', 0.8f, true, "Big : voiced alveolar stop" }, - { "m", 'm', 1.0f, true, "Mat : voiced bilabial nasal" }, - { "p", 'p', 0.8f, true, "Put; voiceless alveolar stop" }, - { "w", 'w', 1.0f, true, "With : voiced labial-velar approximant" }, - { "f", 'f', 0.8f, true, "Fork : voiceless labiodental fricative" }, - { "v", 'v', 0.8f, true, "Val : voiced labialdental fricative" }, - { "r", 0x0279, 1.0f, true, "Red : voiced alveolar approximant" }, - { "r2", 'r', 1.0f, true, "Red : voiced alveolar trill" }, - { "r3", 0x027b, 1.0f, true, "Red : voiced retroflex approximant" }, - { "er", 0x025a, 1.2f, true, "URn : rhotacized schwa" }, - { "er2", 0x025d, 1.2f, true, "URn : rhotacized lower-mid central vowel" }, - { "dh", 0x00f0, 1.0f, true, "THen : voiced dental fricative" }, - { "th", 0x03b8, 1.0f, true, "THin : voiceless dental fricative" }, - { "sh", 0x0283, 1.0f, true, "SHe : voiceless postalveolar fricative" }, - { "jh", 0x02a4, 1.0f, true, "Joy : voiced postalveolar afficate" }, - { "ch", 0x02a7, 1.0f, true, "CHin : voiceless postalveolar affricate" }, - { "s", 's', 0.8f, true, "Sit : voiceless alveolar fricative" }, - { "z", 'z', 0.8f, true, "Zap : voiced alveolar fricative" }, - { "d", 'd', 0.8f, true, "Dig : voiced bilabial stop" }, - { "d2", 0x027e, 0.8f, true, "Dig : voiced alveolar flap or tap" }, - { "l", 'l', 0.8f, true, "Lid : voiced alveolar lateral approximant" }, - { "l2", 0x026b, 0.8f, true, "Lid : velarized voiced alveolar lateral approximant" }, - { "n", 'n', 0.8f, true, "No : voiced alveolar nasal" }, - { "t", 't', 0.8f, true, "Talk : voiceless bilabial stop" }, - { "ow", 'o', 1.2f, true, "gO : upper-mid back rounded vowel" }, - { "uw", 'u', 1.2f, true, "tOO : high back rounded vowel" }, - { "ey", 'e', 1.0f, true, "Ate : upper-mid front unrounded vowel" }, - { "ae", 0x00e6, 1.0f, true, "cAt : semi-low front unrounded vowel" }, - { "aa", 0x0251, 1.0f, true, "fAther : low back unrounded vowel" }, - { "aa2", 'a', 1.0f, true, "fAther : low front unrounded vowel" }, - { "iy", 'i', 1.0f, true, "fEEl : high front unrounded vowel" }, - { "y", 'j', 0.7f, true, "Yacht : voiced palatal approximant" }, - { "ah", 0x028c, 1.0f, true, "cUt : lower-mid back unrounded vowel" }, - { "ao", 0x0254, 1.2f, true, "dOg : lower-mid back rounded vowel" }, - { "ax", 0x0259, 1.0f, true, "Ago : mid-central unrounded vowel" }, - { "ax2", 0x025c, 1.0f, true, "Ago : lower-mid central unrounded vowel" }, - { "eh", 0x025b, 1.0f, true, "pEt : lower-mid front unrounded vowel"}, - { "ih", 0x026a, 1.0f, true, "fIll : semi-high front unrounded vowel" }, - { "ih2", 0x0268, 1.0f, true, "fIll : high central unrounded vowel" }, - { "uh", 0x028a, 1.0f, true, "bOOk : semi-high back rounded vowel" }, - { "g", 'g', 0.8f, true, "taG : voiced velar stop" }, - { "g2", 0x0261, 1.0f, true, "taG : voiced velar stop" }, - { "hh", 'h', 0.8f, true, "Help : voiceless glottal fricative" }, - { "hh2", 0x0266, 0.8f, true, "Help : breathy-voiced glottal fricative" }, - { "c", 'k', 0.6f, true, "Cut : voiceless velar stop" }, - { "nx", 0x014b, 1.0f, true, "siNG : voiced velar nasal" }, - { "zh", 0x0292, 1.0f, true, "aZure : voiced postalveolar fricative" }, - - // Added - { "h", 'h', 0.8f, false, "Help : voiceless glottal fricative" }, - { "k", 'k', 0.6f, false, "Cut : voiceless velar stop" }, - { "ay", 0x0251, 1.0f, false, "fAther : low back unrounded vowel" }, // or possibly +0x026a (ih) - { "ng", 0x014b, 1.0f, false, "siNG : voiced velar nasal" }, // nx - { "aw", 0x0251, 1.2f, false, "fAther : low back unrounded vowel" }, // // vOWel, // aa + uh??? - { "oy", 'u', 1.2f, false, "tOO : high back rounded vowel" }, - - // Silence - { "", '_', 1.0f, true, "silence" }, -}; - -//----------------------------------------------------------------------------- -// Purpose: -// Input : code - -// Output : const char -//----------------------------------------------------------------------------- -const char *ConvertPhoneme( int code ) -{ - for ( int i = 0; i < ARRAYSIZE( g_Phonemes ); ++i ) - { - PhonemeMap_t *test = &g_Phonemes[ i ]; - if ( test->code == code ) - return test->string; - } - - Warning( "Unrecognized phoneme code %i\n", code ); - return ""; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *text - -// Output : int -//----------------------------------------------------------------------------- -int TextToPhoneme( const char *text ) -{ - for ( int i = 0; i < ARRAYSIZE( g_Phonemes ); ++i ) - { - PhonemeMap_t *test = &g_Phonemes[ i ]; - if ( !stricmp( test->string, text ) ) - return test->code; - } - - Warning( "Unrecognized phoneme %s\n", text ); - return '_'; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : code - -// Output : float -//----------------------------------------------------------------------------- -float WeightForPhonemeCode( int code ) -{ - for ( int i = 0; i < ARRAYSIZE( g_Phonemes ); ++i ) - { - PhonemeMap_t *test = &g_Phonemes[ i ]; - if ( test->code == code ) - return test->weight; - } - - Warning( "Unrecognized phoneme code %i\n", code ); - return 1.0f; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *text - -// Output : float -//----------------------------------------------------------------------------- -float WeightForPhoneme( char *text ) -{ - for ( int i = 0; i < ARRAYSIZE( g_Phonemes ); ++i ) - { - PhonemeMap_t *test = &g_Phonemes[ i ]; - if ( !stricmp( test->string, text ) ) - return test->weight; - } - - Warning( "WeightForPhoneme:: Unrecognized phoneme %s\n", text ); - return 1.0f; -} - -int NumPhonemes() -{ - return ARRAYSIZE( g_Phonemes ); -} - -const char *NameForPhonemeByIndex( int index ) -{ - Assert( index >= 0 && index < NumPhonemes() ); - return g_Phonemes[ index ].string; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *text - -// Output : int -//----------------------------------------------------------------------------- -int TextToPhonemeIndex( const char *text ) -{ - for ( int i = 0; i < ARRAYSIZE( g_Phonemes ); ++i ) - { - PhonemeMap_t *test = &g_Phonemes[ i ]; - if ( !stricmp( test->string, text ) ) - return i; - } - - return -1; -} - -int CodeForPhonemeByIndex( int index ) -{ - if ( index < 0 || index >= NumPhonemes() ) - return '_'; - return g_Phonemes[ index ].code; -} - -bool IsStandardPhoneme( int index ) -{ - if ( index < 0 || index >= NumPhonemes() ) - return false; - return g_Phonemes[ index ].isStandard; -} - -const char *DescForPhonemeByIndex( int index ) -{ - if ( index < 0 || index >= NumPhonemes() ) - return NULL; - return g_Phonemes[ index ].desc; -} diff --git a/public/phonemeconverter.h b/public/phonemeconverter.h deleted file mode 100644 index 07768948c..000000000 --- a/public/phonemeconverter.h +++ /dev/null @@ -1,26 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef PHONEMECONVERTER_H -#define PHONEMECONVERTER_H -#ifdef _WIN32 -#pragma once -#endif - -const char *ConvertPhoneme( int code ); -int TextToPhoneme( const char *text ); -float WeightForPhonemeCode( int code ); -float WeightForPhoneme( char *text ); - -int NumPhonemes(); -int TextToPhonemeIndex( const char *text ); -const char *NameForPhonemeByIndex( int index ); -int CodeForPhonemeByIndex( int index ); -const char *DescForPhonemeByIndex( int index ); -bool IsStandardPhoneme( int index ); - -#endif // PHONEMECONVERTER_H diff --git a/public/phonemeextractor/phonemeextractor.h b/public/phonemeextractor/phonemeextractor.h deleted file mode 100644 index 01ea4bec3..000000000 --- a/public/phonemeextractor/phonemeextractor.h +++ /dev/null @@ -1,50 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PHONEMEEXTRACTOR_H -#define PHONEMEEXTRACTOR_H -#ifdef _WIN32 -#pragma once -#endif - -#include "interface.h" - -class CSentence; - -typedef enum -{ - SPEECH_API_SAPI = 0, - SPEECH_API_LIPSINC, -} PE_APITYPE; - -typedef enum -{ - SR_RESULT_NORESULT = 0, - SR_RESULT_ERROR, - SR_RESULT_SUCCESS, - SR_RESULT_FAILED -} SR_RESULT; - -abstract_class IPhonemeExtractor -{ -public: - virtual PE_APITYPE GetAPIType() const = 0; - - // Used for menus, etc - virtual char const *GetName() const = 0; - - virtual SR_RESULT Extract( - const char *wavfile, - int numsamples, - void (*pfnPrint)( const char *fmt, ... ), - CSentence& inwords, - CSentence& outwords ) = 0; -}; - -#define VPHONEME_EXTRACTOR_INTERFACE "PHONEME_EXTRACTOR_001" - -#endif // PHONEMEEXTRACTOR_H diff --git a/public/phyfile.h b/public/phyfile.h deleted file mode 100644 index c3e893055..000000000 --- a/public/phyfile.h +++ /dev/null @@ -1,23 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PHYFILE_H -#define PHYFILE_H -#pragma once - -#include "datamap.h" - -typedef struct phyheader_s -{ - DECLARE_BYTESWAP_DATADESC(); - int size; - int id; - int solidCount; - long checkSum; // checksum of source .mdl file -} phyheader_t; - -#endif // PHYFILE_H diff --git a/public/pixelwriter.h b/public/pixelwriter.h deleted file mode 100644 index 0cac21e03..000000000 --- a/public/pixelwriter.h +++ /dev/null @@ -1,875 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// - -#ifndef PIXELWRITER_H -#define PIXELWRITER_H - -#ifdef _WIN32 -#pragma once -#endif - -#ifdef _WIN32 -#define FORCEINLINE_PIXEL FORCEINLINE -#elif _LINUX -#define FORCEINLINE_PIXEL inline -#else -#error "implement me" -#endif - -#include "bitmap/imageformat.h" -#include "tier0/dbg.h" -#include "mathlib/compressed_vector.h" -#include "mathlib/ssemath.h" - -//----------------------------------------------------------------------------- -// Color writing class -//----------------------------------------------------------------------------- - -class CPixelWriter -{ -public: - FORCEINLINE void SetPixelMemory( ImageFormat format, void* pMemory, int stride ); - FORCEINLINE void *GetPixelMemory() { return m_pBase; } - - // this is no longer used: -#if 0 // defined( _X360 ) - // set after SetPixelMemory() - FORCEINLINE void ActivateByteSwapping( bool bSwap ); -#endif - - FORCEINLINE void Seek( int x, int y ); - FORCEINLINE void* SkipBytes( int n ); - FORCEINLINE void SkipPixels( int n ); - FORCEINLINE void WritePixel( int r, int g, int b, int a = 255 ); - FORCEINLINE void WritePixelNoAdvance( int r, int g, int b, int a = 255 ); - FORCEINLINE void WritePixelSigned( int r, int g, int b, int a = 255 ); - FORCEINLINE void WritePixelNoAdvanceSigned( int r, int g, int b, int a = 255 ); - FORCEINLINE void ReadPixelNoAdvance( int &r, int &g, int &b, int &a ); - - // Floating point formats - FORCEINLINE void WritePixelNoAdvanceF( float r, float g, float b, float a = 1.0f ); - FORCEINLINE void WritePixelF( float r, float g, float b, float a = 1.0f ); - - // SIMD formats - FORCEINLINE void WritePixel( FLTX4 rgba ); - FORCEINLINE void WritePixelNoAdvance( FLTX4 rgba ); -#ifdef _X360 - // here are some explicit formats so we can avoid the switch: - FORCEINLINE void WritePixelNoAdvance_RGBA8888( FLTX4 rgba ); - FORCEINLINE void WritePixelNoAdvance_BGRA8888( FLTX4 rgba ); - // as above, but with m_pBits passed in to avoid a LHS - FORCEINLINE void WritePixelNoAdvance_BGRA8888( FLTX4 rgba, void *pBits ); - // for writing entire SIMD registers at once when they have - // already been packed, and when m_pBits is vector-aligned - // (which is a requirement for write-combined memory) - // offset is added to m_pBits (saving you from the obligatory - // LHS of a SkipBytes) - FORCEINLINE void WriteFourPixelsExplicitLocation_BGRA8888( FLTX4 rgba, int offset ); -#endif - - - FORCEINLINE unsigned char GetPixelSize() { return m_Size; } - - FORCEINLINE bool IsUsingFloatFormat() const; - FORCEINLINE unsigned char *GetCurrentPixel() { return m_pBits; } - -private: - enum - { - PIXELWRITER_USING_FLOAT_FORMAT = 0x01, - PIXELWRITER_USING_16BIT_FLOAT_FORMAT = 0x02, - PIXELWRITER_SWAPBYTES = 0x04, - }; - - unsigned char* m_pBase; - unsigned char* m_pBits; - unsigned short m_BytesPerRow; - unsigned char m_Size; - unsigned char m_nFlags; - signed short m_RShift; - signed short m_GShift; - signed short m_BShift; - signed short m_AShift; - unsigned int m_RMask; - unsigned int m_GMask; - unsigned int m_BMask; - unsigned int m_AMask; - -#ifdef _X360 - ImageFormat m_Format; -public: - inline const ImageFormat &GetFormat() { return m_Format; } -private: -#endif -}; - -FORCEINLINE_PIXEL bool CPixelWriter::IsUsingFloatFormat() const -{ - return (m_nFlags & PIXELWRITER_USING_FLOAT_FORMAT) != 0; -} - -FORCEINLINE_PIXEL void CPixelWriter::SetPixelMemory( ImageFormat format, void* pMemory, int stride ) -{ - m_pBits = (unsigned char*)pMemory; - m_pBase = m_pBits; - m_BytesPerRow = (unsigned short)stride; - m_nFlags = 0; -#ifdef _X360 - m_Format = format; -#endif - - switch ( format ) - { - case IMAGE_FORMAT_R32F: // NOTE! : the low order bits are first in this naming convention. - m_Size = 4; - m_RShift = 0; - m_GShift = 0; - m_BShift = 0; - m_AShift = 0; - m_RMask = 0xFFFFFFFF; - m_GMask = 0x0; - m_BMask = 0x0; - m_AMask = 0x0; - m_nFlags |= PIXELWRITER_USING_FLOAT_FORMAT; - break; - - case IMAGE_FORMAT_RGBA32323232F: - m_Size = 16; - m_RShift = 0; - m_GShift = 32; - m_BShift = 64; - m_AShift = 96; - m_RMask = 0xFFFFFFFF; - m_GMask = 0xFFFFFFFF; - m_BMask = 0xFFFFFFFF; - m_AMask = 0xFFFFFFFF; - m_nFlags |= PIXELWRITER_USING_FLOAT_FORMAT; - break; - - case IMAGE_FORMAT_RGBA16161616F: - m_Size = 8; - m_RShift = 0; - m_GShift = 16; - m_BShift = 32; - m_AShift = 48; - m_RMask = 0xFFFF; - m_GMask = 0xFFFF; - m_BMask = 0xFFFF; - m_AMask = 0xFFFF; - m_nFlags |= PIXELWRITER_USING_FLOAT_FORMAT | PIXELWRITER_USING_16BIT_FLOAT_FORMAT; - break; - - case IMAGE_FORMAT_RGBA8888: -#if defined( _X360 ) - case IMAGE_FORMAT_LINEAR_RGBA8888: -#endif - m_Size = 4; - m_RShift = 0; - m_GShift = 8; - m_BShift = 16; - m_AShift = 24; - m_RMask = 0xFF; - m_GMask = 0xFF; - m_BMask = 0xFF; - m_AMask = 0xFF; - break; - - case IMAGE_FORMAT_BGRA8888: // NOTE! : the low order bits are first in this naming convention. -#if defined( _X360 ) - case IMAGE_FORMAT_LINEAR_BGRA8888: -#endif - m_Size = 4; - m_RShift = 16; - m_GShift = 8; - m_BShift = 0; - m_AShift = 24; - m_RMask = 0xFF; - m_GMask = 0xFF; - m_BMask = 0xFF; - m_AMask = 0xFF; - break; - - case IMAGE_FORMAT_BGRX8888: -#if defined( _X360 ) - case IMAGE_FORMAT_LINEAR_BGRX8888: -#endif - m_Size = 4; - m_RShift = 16; - m_GShift = 8; - m_BShift = 0; - m_AShift = 24; - m_RMask = 0xFF; - m_GMask = 0xFF; - m_BMask = 0xFF; - m_AMask = 0x00; - break; - - case IMAGE_FORMAT_BGRA4444: - m_Size = 2; - m_RShift = 4; - m_GShift = 0; - m_BShift = -4; - m_AShift = 8; - m_RMask = 0xF0; - m_GMask = 0xF0; - m_BMask = 0xF0; - m_AMask = 0xF0; - break; - - case IMAGE_FORMAT_BGR888: - m_Size = 3; - m_RShift = 16; - m_GShift = 8; - m_BShift = 0; - m_AShift = 0; - m_RMask = 0xFF; - m_GMask = 0xFF; - m_BMask = 0xFF; - m_AMask = 0x00; - break; - - case IMAGE_FORMAT_BGR565: - m_Size = 2; - m_RShift = 8; - m_GShift = 3; - m_BShift = -3; - m_AShift = 0; - m_RMask = 0xF8; - m_GMask = 0xFC; - m_BMask = 0xF8; - m_AMask = 0x00; - break; - - case IMAGE_FORMAT_BGRA5551: - case IMAGE_FORMAT_BGRX5551: - m_Size = 2; - m_RShift = 7; - m_GShift = 2; - m_BShift = -3; - m_AShift = 8; - m_RMask = 0xF8; - m_GMask = 0xF8; - m_BMask = 0xF8; - m_AMask = 0x80; - break; - - // GR - alpha format for HDR support - case IMAGE_FORMAT_A8: - m_Size = 1; - m_RShift = 0; - m_GShift = 0; - m_BShift = 0; - m_AShift = 0; - m_RMask = 0x00; - m_GMask = 0x00; - m_BMask = 0x00; - m_AMask = 0xFF; - break; - - case IMAGE_FORMAT_UVWQ8888: - m_Size = 4; - m_RShift = 0; - m_GShift = 8; - m_BShift = 16; - m_AShift = 24; - m_RMask = 0xFF; - m_GMask = 0xFF; - m_BMask = 0xFF; - m_AMask = 0xFF; - break; - - case IMAGE_FORMAT_RGBA16161616: -#if defined( _X360 ) - case IMAGE_FORMAT_LINEAR_RGBA16161616: -#endif - m_Size = 8; - if ( !IsX360() ) - { - m_RShift = 0; - m_GShift = 16; - m_BShift = 32; - m_AShift = 48; - } - else - { - m_RShift = 48; - m_GShift = 32; - m_BShift = 16; - m_AShift = 0; - } - m_RMask = 0xFFFF; - m_GMask = 0xFFFF; - m_BMask = 0xFFFF; - m_AMask = 0xFFFF; - break; - - case IMAGE_FORMAT_I8: - // whatever goes into R is considered the intensity. - m_Size = 1; - m_RShift = 0; - m_GShift = 0; - m_BShift = 0; - m_AShift = 0; - m_RMask = 0xFF; - m_GMask = 0x00; - m_BMask = 0x00; - m_AMask = 0x00; - break; - // FIXME: Add more color formats as need arises - default: - { - static bool format_error_printed[NUM_IMAGE_FORMATS]; - if ( !format_error_printed[format] ) - { - Assert( 0 ); - Msg( "CPixelWriter::SetPixelMemory: Unsupported image format %i\n", format ); - format_error_printed[format] = true; - } - m_Size = 0; // set to zero so that we don't stomp memory for formats that we don't understand. - } - break; - } -} - -#if 0 // defined( _X360 ) -FORCEINLINE void CPixelWriter::ActivateByteSwapping( bool bSwap ) -{ - // X360TBD: Who is trying to use this? - // Purposely not hooked up because PixelWriter has been ported to read/write native pixels only - Assert( 0 ); - - if ( bSwap && !(m_nFlags & PIXELWRITER_SWAPBYTES ) ) - { - m_nFlags |= PIXELWRITER_SWAPBYTES; - - // only tested with 4 byte formats - Assert( m_Size == 4 ); - } - else if ( !bSwap && (m_nFlags & PIXELWRITER_SWAPBYTES ) ) - { - m_nFlags &= ~PIXELWRITER_SWAPBYTES; - } - else - { - // same state - return; - } - - // swap the shifts - m_RShift = 24-m_RShift; - m_GShift = 24-m_GShift; - m_BShift = 24-m_BShift; - m_AShift = 24-m_AShift; -} -#endif - -//----------------------------------------------------------------------------- -// Sets where we're writing to -//----------------------------------------------------------------------------- -FORCEINLINE_PIXEL void CPixelWriter::Seek( int x, int y ) -{ - m_pBits = m_pBase + y * m_BytesPerRow + x * m_Size; -} - - -//----------------------------------------------------------------------------- -// Skips n bytes: -//----------------------------------------------------------------------------- -FORCEINLINE_PIXEL void* CPixelWriter::SkipBytes( int n ) RESTRICT -{ - m_pBits += n; - return m_pBits; -} - - -//----------------------------------------------------------------------------- -// Skips n pixels: -//----------------------------------------------------------------------------- -FORCEINLINE_PIXEL void CPixelWriter::SkipPixels( int n ) -{ - SkipBytes( n * m_Size ); -} - - -//----------------------------------------------------------------------------- -// Writes a pixel without advancing the index PC ONLY -//----------------------------------------------------------------------------- -FORCEINLINE_PIXEL void CPixelWriter::WritePixelNoAdvanceF( float r, float g, float b, float a ) -{ - Assert( IsUsingFloatFormat() ); - - // X360TBD: Not ported - Assert( IsPC() ); - - if (PIXELWRITER_USING_16BIT_FLOAT_FORMAT & m_nFlags) - { - float16 fp16[4]; - fp16[0].SetFloat( r ); - fp16[1].SetFloat( g ); - fp16[2].SetFloat( b ); - fp16[3].SetFloat( a ); - // fp16 - unsigned short pBuf[4] = { 0, 0, 0, 0 }; - pBuf[ m_RShift >> 4 ] |= (fp16[0].GetBits() & m_RMask) << ( m_RShift & 0xF ); - pBuf[ m_GShift >> 4 ] |= (fp16[1].GetBits() & m_GMask) << ( m_GShift & 0xF ); - pBuf[ m_BShift >> 4 ] |= (fp16[2].GetBits() & m_BMask) << ( m_BShift & 0xF ); - pBuf[ m_AShift >> 4 ] |= (fp16[3].GetBits() & m_AMask) << ( m_AShift & 0xF ); - memcpy( m_pBits, pBuf, m_Size ); - } - else - { - // fp32 - int pBuf[4] = { 0, 0, 0, 0 }; - pBuf[ m_RShift >> 5 ] |= (FloatBits(r) & m_RMask) << ( m_RShift & 0x1F ); - pBuf[ m_GShift >> 5 ] |= (FloatBits(g) & m_GMask) << ( m_GShift & 0x1F ); - pBuf[ m_BShift >> 5 ] |= (FloatBits(b) & m_BMask) << ( m_BShift & 0x1F ); - pBuf[ m_AShift >> 5 ] |= (FloatBits(a) & m_AMask) << ( m_AShift & 0x1F ); - memcpy( m_pBits, pBuf, m_Size ); - } -} - -//----------------------------------------------------------------------------- -// Writes a pixel, advances the write index -//----------------------------------------------------------------------------- -FORCEINLINE_PIXEL void CPixelWriter::WritePixelF( float r, float g, float b, float a ) -{ - WritePixelNoAdvanceF(r, g, b, a); - m_pBits += m_Size; -} - - -//----------------------------------------------------------------------------- -// Writes a pixel, advances the write index -//----------------------------------------------------------------------------- -FORCEINLINE_PIXEL void CPixelWriter::WritePixel( int r, int g, int b, int a ) -{ - WritePixelNoAdvance(r,g,b,a); - m_pBits += m_Size; -} - -//----------------------------------------------------------------------------- -// Writes a pixel, advances the write index -//----------------------------------------------------------------------------- -FORCEINLINE_PIXEL void CPixelWriter::WritePixelSigned( int r, int g, int b, int a ) -{ - WritePixelNoAdvanceSigned(r,g,b,a); - m_pBits += m_Size; -} - - -//----------------------------------------------------------------------------- -// Writes a pixel without advancing the index -//----------------------------------------------------------------------------- -FORCEINLINE_PIXEL void CPixelWriter::WritePixelNoAdvance( int r, int g, int b, int a ) -{ - Assert( !IsUsingFloatFormat() ); - - if ( m_Size <= 0 ) - { - return; - } - if ( m_Size < 5 ) - { - unsigned int val = (r & m_RMask) << m_RShift; - val |= (g & m_GMask) << m_GShift; - val |= (m_BShift > 0) ? ((b & m_BMask) << m_BShift) : ((b & m_BMask) >> -m_BShift); - val |= (a & m_AMask) << m_AShift; - - switch( m_Size ) - { - default: - Assert( 0 ); - return; - case 1: - { - m_pBits[0] = (unsigned char)((val & 0xff)); - return; - } - case 2: - { - ((unsigned short *)m_pBits)[0] = (unsigned short)((val & 0xffff)); - return; - } - case 3: - { - if ( IsPC() || !IsX360() ) - { - ((unsigned short *)m_pBits)[0] = (unsigned short)((val & 0xffff)); - m_pBits[2] = (unsigned char)((val >> 16) & 0xff); - } - else - { - m_pBits[0] = (unsigned char)(((val >> 16) & 0xff)); - m_pBits[1] = (unsigned char)(((val >> 8 ) & 0xff)); - m_pBits[2] = (unsigned char)(val & 0xff); - } - return; - } - case 4: - { - ((unsigned int *)m_pBits)[0] = val; - return; - } - } - } - else // RGBA32323232 or RGBA16161616 -- PC only. - { - AssertMsg(!IsX360(), "Unsupported lightmap format used in WritePixelNoAdvance(). This is a severe performance fault.\n"); - - int64 val = ( ( int64 )(r & m_RMask) ) << m_RShift; - val |= ( ( int64 )(g & m_GMask) ) << m_GShift; - val |= (m_BShift > 0) ? ((( int64 )( b & m_BMask)) << m_BShift) : (((int64)( b & m_BMask)) >> -m_BShift); - val |= ( ( int64 )(a & m_AMask) ) << m_AShift; - - switch( m_Size ) - { - case 6: - { - if ( IsPC() || !IsX360() ) - { - ((unsigned int *)m_pBits)[0] = val & 0xffffffff; - ((unsigned short *)m_pBits)[2] = (unsigned short)( ( val >> 32 ) & 0xffff ); - } - else - { - ((unsigned int *)m_pBits)[0] = (val >> 16) & 0xffffffff; - ((unsigned short *)m_pBits)[2] = (unsigned short)( val & 0xffff ); - } - return; - } - case 8: - { - if ( IsPC() || !IsX360() ) - { - ((unsigned int *)m_pBits)[0] = val & 0xffffffff; - ((unsigned int *)m_pBits)[1] = ( val >> 32 ) & 0xffffffff; - } - else - { - ((unsigned int *)m_pBits)[0] = ( val >> 32 ) & 0xffffffff; - ((unsigned int *)m_pBits)[1] = val & 0xffffffff; - } - return; - } - default: - Assert( 0 ); - return; - } - } -} - -#ifdef _X360 -// There isn't a PC port of these because of the many varied -// pixel formats the PC deals with. If you write SSE versions -// of all the various necessary packers, then this can be made -// to work on PC. - -//----------------------------------------------------------------------------- -// Writes a pixel, advances the write index -//----------------------------------------------------------------------------- -FORCEINLINE_PIXEL void CPixelWriter::WritePixel( FLTX4 rgba ) RESTRICT -{ - WritePixelNoAdvance(rgba); - m_pBits += m_Size; -} - -//----------------------------------------------------------------------------- -// Writes a pixel without advancing the index -// rgba are four float values, each on the range 0..255 (though they may leak -// fractionally over 255 due to numerical errors earlier) -//----------------------------------------------------------------------------- -FORCEINLINE_PIXEL void CPixelWriter::WritePixelNoAdvance( FLTX4 rgba ) RESTRICT -{ - Assert( !IsUsingFloatFormat() ); - - switch (m_Size) - { - case 0: - return; - case 4: - { - AssertMsg((reinterpret_cast(m_pBits) & 0x03) == 0,"Unaligned m_pBits in WritePixelNoAdvance!"); - switch ( m_Format ) - { - // note: format names are low-order-byte first. - case IMAGE_FORMAT_RGBA8888: - case IMAGE_FORMAT_LINEAR_RGBA8888: - WritePixelNoAdvance_RGBA8888(rgba); - break; - - case IMAGE_FORMAT_BGRA8888: // NOTE! : the low order bits are first in this naming convention. - case IMAGE_FORMAT_LINEAR_BGRA8888: - WritePixelNoAdvance_BGRA8888(rgba); - break; - - - default: - AssertMsg1(false, "Unknown four-byte pixel format %d in lightmap write.\n", m_Format); - } - break; - } - - default: - AssertMsg1(false, "WritePixelNoAdvance on unsupported 360 %d-byte format\n", m_Size); - break; - } - -} - - -// here are some explicit formats so we can avoid the switch: -FORCEINLINE void CPixelWriter::WritePixelNoAdvance_RGBA8888( FLTX4 rgba ) -{ - // it's easier to do tiered convert-saturates here - // than the d3d color convertor op - - // first permute - const static fltx4 permReverse = XMVectorPermuteControl(3,2,1,0); - fltx4 N = XMVectorPermute(rgba, rgba, permReverse); - - N = __vctuxs(N, 0); // convert to unsigned fixed point 0 w/ saturate - N = __vpkuwus(N, N); // convert to halfword saturate - N = __vpkuhus(N, N); // convert to byte saturate - N = __vspltw(N, 0); // splat w-word to all four - - __stvewx(N, m_pBits, 0); // store whatever word happens to be aligned with m_pBits to that word -} - -FORCEINLINE void CPixelWriter::WritePixelNoAdvance_BGRA8888( FLTX4 rgba ) -{ - WritePixelNoAdvance_BGRA8888( rgba, m_pBits ); -} - -FORCEINLINE void CPixelWriter::WritePixelNoAdvance_BGRA8888( FLTX4 rgba, void * RESTRICT pBits ) RESTRICT -{ - // this happens to be in an order such that we can use the handy builtin packing op - // clamp to 0..255 (coz it might have leaked over) - static const fltx4 vTwoFiftyFive = {255.0f, 255.0f, 255.0f, 255.0f}; - fltx4 N = MinSIMD(vTwoFiftyFive, rgba); - - // the magic number such that when mul-accummulated against rbga, - // gets us a representation 3.0 + (r)*2^-22 -- puts the bits at - // the bottom of the float - static CONST XMVECTOR PackScale = { (1.0f / (FLOAT)(1 << 22)), (1.0f / (FLOAT)(1 << 22)), (1.0f / (FLOAT)(1 << 22)), (1.0f / (FLOAT)(1 << 22))}; // 255.0f / (FLOAT)(1 << 22) - static const XMVECTOR Three = {3.0f, 3.0f, 3.0f, 3.0f}; - - N = __vmaddfp(N, PackScale, Three); - N = __vpkd3d(N, N, VPACK_D3DCOLOR, VPACK_32, 3); // pack to X word - N = __vspltw(N, 0); // splat X - - // this is a nasty thing to work around the April XDK bug in __stvewx - { - void * RESTRICT copyOfPBits = pBits; - __stvewx(N, copyOfPBits, 0); - } - -} - -// for writing entire SIMD registers at once -FORCEINLINE void CPixelWriter::WriteFourPixelsExplicitLocation_BGRA8888 ( FLTX4 rgba, int offset ) -{ - Assert( (reinterpret_cast(m_pBits) & 15) == 0 ); // assert alignment - XMStoreVector4A( m_pBits + offset , rgba ); -} - - -#endif - -//----------------------------------------------------------------------------- -// Writes a signed pixel without advancing the index -//----------------------------------------------------------------------------- - -FORCEINLINE_PIXEL void CPixelWriter::WritePixelNoAdvanceSigned( int r, int g, int b, int a ) -{ - Assert( !IsUsingFloatFormat() ); - - if ( m_Size <= 0 ) - { - return; - } - - if ( m_Size < 5 ) - { - int val = (r & m_RMask) << m_RShift; - val |= (g & m_GMask) << m_GShift; - val |= (m_BShift > 0) ? ((b & m_BMask) << m_BShift) : ((b & m_BMask) >> -m_BShift); - val |= (a & m_AMask) << m_AShift; - signed char *pSignedBits = (signed char *)m_pBits; - - if ( IsPC() || !IsX360() ) - { - switch ( m_Size ) - { - case 4: - pSignedBits[3] = (signed char)((val >> 24) & 0xff); - // fall through intentionally. - case 3: - pSignedBits[2] = (signed char)((val >> 16) & 0xff); - // fall through intentionally. - case 2: - pSignedBits[1] = (signed char)((val >> 8) & 0xff); - // fall through intentionally. - case 1: - pSignedBits[0] = (signed char)((val & 0xff)); - // fall through intentionally. - return; - } - } - else - { - switch ( m_Size ) - { - case 4: - pSignedBits[0] = (signed char)((val >> 24) & 0xff); - pSignedBits[1] = (signed char)((val >> 16) & 0xff); - pSignedBits[2] = (signed char)((val >> 8) & 0xff); - pSignedBits[3] = (signed char)(val & 0xff); - break; - case 3: - pSignedBits[0] = (signed char)((val >> 16) & 0xff); - pSignedBits[1] = (signed char)((val >> 8) & 0xff); - pSignedBits[2] = (signed char)(val & 0xff); - break; - case 2: - pSignedBits[0] = (signed char)((val >> 8) & 0xff); - pSignedBits[1] = (signed char)(val & 0xff); - break; - case 1: - pSignedBits[0] = (signed char)(val & 0xff); - break; - } - } - } - else - { - int64 val = ( ( int64 )(r & m_RMask) ) << m_RShift; - val |= ( ( int64 )(g & m_GMask) ) << m_GShift; - val |= (m_BShift > 0) ? ((( int64 )( b & m_BMask)) << m_BShift) : (((int64)( b & m_BMask)) >> -m_BShift); - val |= ( ( int64 )(a & m_AMask) ) << m_AShift; - signed char *pSignedBits = ( signed char * )m_pBits; - - if ( IsPC() || !IsX360() ) - { - switch( m_Size ) - { - case 8: - pSignedBits[7] = (signed char)((val >> 56) & 0xff); - pSignedBits[6] = (signed char)((val >> 48) & 0xff); - // fall through intentionally. - case 6: - pSignedBits[5] = (signed char)((val >> 40) & 0xff); - pSignedBits[4] = (signed char)((val >> 32) & 0xff); - // fall through intentionally. - case 4: - pSignedBits[3] = (signed char)((val >> 24) & 0xff); - // fall through intentionally. - case 3: - pSignedBits[2] = (signed char)((val >> 16) & 0xff); - // fall through intentionally. - case 2: - pSignedBits[1] = (signed char)((val >> 8) & 0xff); - // fall through intentionally. - case 1: - pSignedBits[0] = (signed char)((val & 0xff)); - break; - default: - Assert( 0 ); - return; - } - } - else - { - switch( m_Size ) - { - case 8: - pSignedBits[0] = (signed char)((val >> 56) & 0xff); - pSignedBits[1] = (signed char)((val >> 48) & 0xff); - pSignedBits[2] = (signed char)((val >> 40) & 0xff); - pSignedBits[3] = (signed char)((val >> 32) & 0xff); - pSignedBits[4] = (signed char)((val >> 24) & 0xff); - pSignedBits[5] = (signed char)((val >> 16) & 0xff); - pSignedBits[6] = (signed char)((val >> 8) & 0xff); - pSignedBits[7] = (signed char)(val & 0xff); - break; - case 6: - pSignedBits[0] = (signed char)((val >> 40) & 0xff); - pSignedBits[1] = (signed char)((val >> 32) & 0xff); - pSignedBits[2] = (signed char)((val >> 24) & 0xff); - pSignedBits[3] = (signed char)((val >> 16) & 0xff); - pSignedBits[4] = (signed char)((val >> 8) & 0xff); - pSignedBits[5] = (signed char)(val & 0xff); - break; - case 4: - pSignedBits[0] = (signed char)((val >> 24) & 0xff); - pSignedBits[1] = (signed char)((val >> 16) & 0xff); - pSignedBits[2] = (signed char)((val >> 8) & 0xff); - pSignedBits[3] = (signed char)(val & 0xff); - break; - case 3: - pSignedBits[0] = (signed char)((val >> 16) & 0xff); - pSignedBits[1] = (signed char)((val >> 8) & 0xff); - pSignedBits[2] = (signed char)(val & 0xff); - break; - case 2: - pSignedBits[0] = (signed char)((val >> 8) & 0xff); - pSignedBits[1] = (signed char)(val & 0xff); - break; - case 1: - pSignedBits[0] = (signed char)(val & 0xff); - break; - default: - Assert( 0 ); - return; - } - } - } -} - -FORCEINLINE_PIXEL void CPixelWriter::ReadPixelNoAdvance( int &r, int &g, int &b, int &a ) -{ - Assert( !IsUsingFloatFormat() ); - - int val = m_pBits[0]; - if ( m_Size > 1 ) - { - if ( IsPC() || !IsX360() ) - { - val |= (int)m_pBits[1] << 8; - if ( m_Size > 2 ) - { - val |= (int)m_pBits[2] << 16; - if ( m_Size > 3 ) - { - val |= (int)m_pBits[3] << 24; - } - } - } - else - { - val <<= 8; - val |= (int)m_pBits[1]; - if ( m_Size > 2 ) - { - val <<= 8; - val |= (int)m_pBits[2]; - if ( m_Size > 3 ) - { - val <<= 8; - val |= (int)m_pBits[3]; - } - } - } - } - - r = (val>>m_RShift) & m_RMask; - g = (val>>m_GShift) & m_GMask; - b = (val>>m_BShift) & m_BMask; - a = (val>>m_AShift) & m_AMask; -} - -#endif // PIXELWRITER_H; diff --git a/public/posedebugger.cpp b/public/posedebugger.cpp deleted file mode 100644 index 76eaa0bfe..000000000 --- a/public/posedebugger.cpp +++ /dev/null @@ -1,655 +0,0 @@ -//====== Copyright c 1996-2007, Valve Corporation, All rights reserved. =======// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include "tier0/dbg.h" -#include "tier0/platform.h" -#include "mathlib/mathlib.h" -#include "tier0/tslist.h" -#include "tier1/utlmap.h" -#include "tier1/convar.h" - -#include "bone_setup.h" - -#include "con_nprint.h" -#include "cdll_int.h" -#include "globalvars_base.h" - -#include "posedebugger.h" - -#include "iclientnetworkable.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -extern IVEngineClient *engine; -extern CGlobalVarsBase *gpGlobals; - -static ConVar ui_posedebug_fade_in_time( "ui_posedebug_fade_in_time", "0.2", - FCVAR_CHEAT | FCVAR_DONTRECORD, - "Time during which a new pose activity layer is shown in green in +posedebug UI" ); -static ConVar ui_posedebug_fade_out_time( "ui_posedebug_fade_out_time", "0.8", - FCVAR_CHEAT | FCVAR_DONTRECORD, - "Time to keep a no longer active pose activity layer in red until removing it from +posedebug UI" ); - - -////////////////////////////////////////////////////////////////////////// -// -// CPoseDebuggerStub : IPoseDebugger -// empty interface implementation -// -////////////////////////////////////////////////////////////////////////// - -class CPoseDebuggerStub : public IPoseDebugger -{ -public: - virtual void StartBlending( IClientNetworkable *pEntity, const CStudioHdr *pStudioHdr ) { } - virtual void AccumulatePose( - const CStudioHdr *pStudioHdr, - CIKContext *pIKContext, - Vector pos[], - Quaternion q[], - int sequence, - float cycle, - const float poseParameter[], - int boneMask, - float flWeight, - float flTime - ) { } -}; - -static CPoseDebuggerStub s_PoseDebuggerStub; -IPoseDebugger *g_pPoseDebugger = &s_PoseDebuggerStub; - -////////////////////////////////////////////////////////////////////////// -// -// CPoseDebuggerImpl : IPoseDebugger -// Purpose: Main implementation of the pose debugger -// Declaration -// -////////////////////////////////////////////////////////////////////////// - -class ModelPoseDebugInfo -{ -public: - ModelPoseDebugInfo() : m_iEntNum( 0 ), m_iCurrentText( 0 ) { } - - -public: - // Entity number - int m_iEntNum; - - // Currently processed text - int m_iCurrentText; - - // Info Text Flags - enum InfoTextFlags - { - F_SEEN_THIS_FRAME = 1 << 0, - F_SEEN_LAST_FRAME = 1 << 1, - }; - - struct InfoText - { - InfoText() { memset( this, 0, sizeof( *this ) ); } - - // Flags - uint32 m_uiFlags; - - // Time seen - float m_flTimeToLive, m_flTimeAlive; - - // Activity/label - int m_iActivity; - char m_chActivity[100]; - char m_chLabel[100]; - - // Text - char m_chTextLines[4][256]; - enum - { - MAX_TEXT_LINES = 4 - }; - }; - - CCopyableUtlVector< InfoText > m_arrTxt; - - -public: - // Add an info text - void AddInfoText( InfoText *x, ModelPoseDebugInfo *pOld ); - - // Lookup an info text - InfoText *LookupInfoText( InfoText *x ); - - // Print pending info text - void PrintPendingInfoText( int &rnPosPrint ); -}; - -void ModelPoseDebugInfo::AddInfoText( InfoText *x, ModelPoseDebugInfo *pOld ) -{ - if ( x ) - { - // Try to set the proper flags on the info text - x->m_uiFlags &= ~F_SEEN_LAST_FRAME; - x->m_uiFlags |= F_SEEN_THIS_FRAME; - } - - // If we have smth to compare against - if ( pOld ) - { - // Search for the same activity/label in the other model pose debug info - ModelPoseDebugInfo &o = *pOld; - int k = o.m_iCurrentText; - if ( x ) - { - for ( ; k < o.m_arrTxt.Count(); ++ k ) - { - InfoText &txt = o.m_arrTxt[k]; - if ( ( txt.m_uiFlags & F_SEEN_THIS_FRAME ) && - !stricmp( x->m_chActivity, txt.m_chActivity ) && - !stricmp( x->m_chLabel, txt.m_chLabel ) && - ( x->m_iActivity == txt.m_iActivity ) ) - { - x->m_flTimeAlive = txt.m_flTimeAlive; - break; - } - } - } - else - { - k = o.m_arrTxt.Count(); - } - - // Range of finished activities - int iFinishedRange[2] = { o.m_iCurrentText, k }; - - // Check whether this is a new message - if ( k == o.m_arrTxt.Count() ) - { - if ( !x ) - { - o.m_iCurrentText = k; - } - else - { - // Don't update the current when insertion happens and don't have finished commands - iFinishedRange[1] = iFinishedRange[0]; - } - } - else - { - o.m_iCurrentText = k + 1; - if ( x ) - { - x->m_uiFlags |= F_SEEN_LAST_FRAME; - x->m_flTimeAlive += gpGlobals->frametime; - } - } - - // Everything before finished - for ( int iFinished = iFinishedRange[0]; iFinished < iFinishedRange[1]; ++ iFinished ) - { - InfoText &txtFinished = o.m_arrTxt[ iFinished ]; - - if ( txtFinished.m_uiFlags & F_SEEN_THIS_FRAME ) - txtFinished.m_uiFlags |= F_SEEN_LAST_FRAME; - - txtFinished.m_uiFlags &= ~F_SEEN_THIS_FRAME; - - txtFinished.m_flTimeToLive -= gpGlobals->frametime; - txtFinished.m_flTimeAlive += gpGlobals->frametime; - - if ( txtFinished.m_flTimeToLive >= 0.0f ) - m_arrTxt.AddToTail( txtFinished ); - } - } - - if ( x ) - { - // Now add it to the array - x->m_flTimeToLive = ui_posedebug_fade_out_time.GetFloat(); - m_arrTxt.AddToTail( *x ); - } -} - -ModelPoseDebugInfo::InfoText * ModelPoseDebugInfo::LookupInfoText( InfoText *x ) -{ - int k = m_iCurrentText; - if ( x ) - { - for ( ; k < m_arrTxt.Count(); ++ k ) - { - InfoText &txt = m_arrTxt[k]; - if ( ( txt.m_uiFlags & F_SEEN_THIS_FRAME ) && - !stricmp( x->m_chActivity, txt.m_chActivity ) && - !stricmp( x->m_chLabel, txt.m_chLabel ) && - ( x->m_iActivity == txt.m_iActivity ) ) - { - return &txt; - } - } - } - return NULL; -} - -void ModelPoseDebugInfo::PrintPendingInfoText( int &rnPosPrint ) -{ - con_nprint_s nxPrn = { 0 }; - nxPrn.time_to_live = -1; - nxPrn.color[0] = 1.0f, nxPrn.color[1] = 1.0f, nxPrn.color[2] = 1.0f; - nxPrn.fixed_width_font = true; - - float const flFadeInTime = ui_posedebug_fade_in_time.GetFloat(); - float const flFadeOutTime = ui_posedebug_fade_out_time.GetFloat(); - - // Now print all the accumulated spew - for ( int k = m_iCurrentText; k < m_arrTxt.Count(); ++ k ) - { - InfoText &prntxt = m_arrTxt[k]; - - switch( prntxt.m_uiFlags & ( F_SEEN_LAST_FRAME | F_SEEN_THIS_FRAME ) ) - { - case ( F_SEEN_LAST_FRAME | F_SEEN_THIS_FRAME ) : - nxPrn.color[0] = 1.f; - nxPrn.color[1] = 1.f; - nxPrn.color[2] = 1.f; - if ( prntxt.m_flTimeAlive > flFadeInTime ) - break; - else - NULL; // Fall-through to keep showing in green - case F_SEEN_THIS_FRAME : - if ( flFadeInTime > 0.f ) - { - nxPrn.color[0] = 1.f * prntxt.m_flTimeAlive / flFadeInTime; - nxPrn.color[1] = 1.f; - nxPrn.color[2] = 1.f * prntxt.m_flTimeAlive / flFadeInTime; - } - else - { - nxPrn.color[0] = ( prntxt.m_flTimeAlive > 0.0f ) ? 1.f : 0.f; - nxPrn.color[1] = 1.f; - nxPrn.color[2] = ( prntxt.m_flTimeAlive > 0.0f ) ? 1.f : 0.f; - } - break; - case F_SEEN_LAST_FRAME : - case 0: - if ( flFadeOutTime > 0.f ) - nxPrn.color[0] = 1.f * prntxt.m_flTimeToLive / flFadeOutTime; - else - nxPrn.color[0] = ( prntxt.m_flTimeToLive > 0.0f ) ? 1.f : 0.f; - nxPrn.color[1] = 0.f; - nxPrn.color[2] = 0.f; - break; - } - - nxPrn.index = ( rnPosPrint += 1 ); - engine->Con_NXPrintf( &nxPrn, "%s", prntxt.m_chTextLines[0] ); - - for ( int iLine = 1; iLine < ModelPoseDebugInfo::InfoText::MAX_TEXT_LINES; ++ iLine) - { - if ( !prntxt.m_chTextLines[iLine][0] ) - break; - - nxPrn.index = ( rnPosPrint += 1 ); - engine->Con_NXPrintf( &nxPrn, "%s", prntxt.m_chTextLines[iLine] ); - } - } - - m_iCurrentText = m_arrTxt.Count(); -} - - - -class CPoseDebuggerImpl : public IPoseDebugger -{ -public: - CPoseDebuggerImpl(); - ~CPoseDebuggerImpl(); - -public: - void ShowAllModels( bool bShow ); - void ShowModel( int iEntNum, bool bShow ); - bool IsModelShown( int iEntNum ) const; - -public: - virtual void StartBlending( IClientNetworkable *pEntity, const CStudioHdr *pStudioHdr ); - virtual void AccumulatePose( - const CStudioHdr *pStudioHdr, - CIKContext *pIKContext, - Vector pos[], - Quaternion q[], - int sequence, - float cycle, - const float poseParameter[], - int boneMask, - float flWeight, - float flTime - ); - -protected: - typedef CUtlMap< CStudioHdr const *, ModelPoseDebugInfo > MapModel; - MapModel m_mapModel, m_mapModelOld; - int m_nPosPrint; - - CBitVec< MAX_EDICTS > m_uiMaskShowModels; - - CStudioHdr const *m_pLastModel; -}; - -static CPoseDebuggerImpl s_PoseDebuggerImpl; - -////////////////////////////////////////////////////////////////////////// -// -// CPoseDebuggerImpl -// Implementation -// -////////////////////////////////////////////////////////////////////////// - -CPoseDebuggerImpl::CPoseDebuggerImpl() : - m_mapModel( DefLessFunc( CStudioHdr const * ) ), - m_mapModelOld( DefLessFunc( CStudioHdr const * ) ), - m_nPosPrint( 0 ), - m_pLastModel( NULL ) -{ - m_uiMaskShowModels.SetAll(); -} - -CPoseDebuggerImpl::~CPoseDebuggerImpl() -{ - // g_pPoseDebugger = &s_PoseDebuggerStub; -} - -void CPoseDebuggerImpl::ShowAllModels( bool bShow ) -{ - bShow ? m_uiMaskShowModels.SetAll() : m_uiMaskShowModels.ClearAll(); -} - -void CPoseDebuggerImpl::ShowModel( int iEntNum, bool bShow ) -{ - Assert( iEntNum < MAX_EDICTS ); - if ( iEntNum < MAX_EDICTS ) - m_uiMaskShowModels.Set( iEntNum, bShow ); -} - -bool CPoseDebuggerImpl::IsModelShown( int iEntNum ) const -{ - Assert( iEntNum < MAX_EDICTS ); - if ( iEntNum >= 0 && iEntNum < MAX_EDICTS ) - return m_uiMaskShowModels.IsBitSet( iEntNum ); - else - return false; -} - -void CPoseDebuggerImpl::StartBlending( IClientNetworkable *pEntity, const CStudioHdr *pStudioHdr ) -{ -// virtualmodel_t const *pVMdl = pStudioHdr->GetVirtualModel(); -// if ( !pVMdl ) -// return; - - // If we are starting a new model then finalize the previous one - if ( pStudioHdr != m_pLastModel && m_pLastModel ) - { - MapModel::IndexType_t idx = m_mapModel.Find( m_pLastModel ); - if ( idx != m_mapModel.InvalidIndex() ) - { - ModelPoseDebugInfo &mpi = m_mapModel.Element( idx ); - ModelPoseDebugInfo *pMpiOld = NULL; - MapModel::IndexType_t idxMapModelOld = m_mapModelOld.Find( m_pLastModel ); - if ( idxMapModelOld != m_mapModelOld.InvalidIndex() ) - { - pMpiOld = &m_mapModelOld.Element( idxMapModelOld ); - } - mpi.AddInfoText( NULL, pMpiOld ); - mpi.PrintPendingInfoText( m_nPosPrint ); - } - } - m_pLastModel = pStudioHdr; - - // Go ahead with the new model - studiohdr_t const *pRMdl = pStudioHdr->GetRenderHdr(); - if ( !pRMdl || - !pRMdl->numincludemodels ) - return; - - // Entity number - int iEntNum = pEntity->entindex(); - if ( !IsModelShown( iEntNum ) ) - return; - - // Check if we saw the model - if ( m_mapModel.Find( pStudioHdr ) != m_mapModel.InvalidIndex() ) - { - // Initialize the printing position - m_nPosPrint = 9; - - // Swap the maps - m_mapModelOld.RemoveAll(); - m_mapModelOld.Swap( m_mapModel ); - - // Zero out the text on the old map - for ( int k = m_mapModelOld.FirstInorder(); - k != m_mapModelOld.InvalidIndex(); - k = m_mapModelOld.NextInorder( k ) ) - { - ModelPoseDebugInfo &mpi = m_mapModelOld[k]; - mpi.m_iCurrentText = 0; - } - } - else - { - // Next model - m_nPosPrint += 3; - } - - ModelPoseDebugInfo mpi; - mpi.m_iEntNum = iEntNum; - m_mapModel.Insert( pStudioHdr, mpi ); - - con_nprint_s nxPrn = { 0 }; - nxPrn.index = m_nPosPrint; - nxPrn.time_to_live = -1; - nxPrn.color[0] = 0.9f, nxPrn.color[1] = 1.0f, nxPrn.color[2] = 0.9f; - nxPrn.fixed_width_font = false; - - engine->Con_NXPrintf( &nxPrn, "[ %2d ] Model: %s", iEntNum, pRMdl->pszName() ); - m_nPosPrint += 3; -} - -void CPoseDebuggerImpl::AccumulatePose( const CStudioHdr *pStudioHdr, CIKContext *pIKContext, - Vector pos[], Quaternion q[], int sequence, float cycle, - const float poseParameter[], int boneMask, - float flWeight, float flTime ) -{ -// virtualmodel_t const *pVMdl = pStudioHdr->GetVirtualModel(); -// if ( !pVMdl ) -// return; - - studiohdr_t const *pRMdl = pStudioHdr->GetRenderHdr(); - if ( !pRMdl || - !pRMdl->numincludemodels ) - return; - - MapModel::IndexType_t idxMapModel = m_mapModel.Find( pStudioHdr ); - if ( idxMapModel == m_mapModel.InvalidIndex() ) - return; - - ModelPoseDebugInfo &mpi = m_mapModel.Element( idxMapModel ); - if ( !IsModelShown( mpi.m_iEntNum ) ) - return; - - ModelPoseDebugInfo *pMpiOld = NULL; - MapModel::IndexType_t idxMapModelOld = m_mapModelOld.Find( pStudioHdr ); - if ( idxMapModelOld != m_mapModelOld.InvalidIndex() ) - { - pMpiOld = &m_mapModelOld.Element( idxMapModelOld ); - } - - - // - // Actual processing - // - - mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( sequence ); - - if ( sequence >= pStudioHdr->GetNumSeq() ) - { - sequence = 0; - seqdesc = pStudioHdr->pSeqdesc( sequence ); - } - - enum - { - widthActivity = 35, - widthLayer = 35, - widthIks = 60, - widthPercent = 6, - }; - - // Prepare the text - char chBuffer[256]; - ModelPoseDebugInfo::InfoText txt; - int numLines = 0; - - txt.m_iActivity = seqdesc.activity; - sprintf( txt.m_chActivity, "%s", seqdesc.pszActivityName() ); - sprintf( txt.m_chLabel, "%s", seqdesc.pszLabel() ); - - if ( !txt.m_chActivity[0] ) - { - // Try to find the last seen activity and re-use it - for ( int iLast = mpi.m_arrTxt.Count(); iLast --> 0; ) - { - ModelPoseDebugInfo::InfoText &lastSeenTxt = mpi.m_arrTxt[iLast]; - if ( lastSeenTxt.m_uiFlags & ModelPoseDebugInfo::F_SEEN_THIS_FRAME && - lastSeenTxt.m_chActivity[0] ) - { - sprintf( txt.m_chActivity, "%s", lastSeenTxt.m_chActivity ); - break; - } - } - } - - // The layer information - ModelPoseDebugInfo::InfoText *pOldTxt = pMpiOld ? pMpiOld->LookupInfoText( &txt ) : NULL; - sprintf( txt.m_chTextLines[numLines], - "%-*s %-*s %*.2f %*.1f/%-*d %*.0f%% ", - widthActivity, - seqdesc.pszActivityName(), - widthLayer, - seqdesc.pszLabel(), - 7, - pOldTxt ? pOldTxt->m_flTimeAlive : 0.f, - 5, - cycle * ( pStudioHdr->pAnimdesc( seqdesc.anim( 0, 0 ) ).numframes - 1 ), - 3, - pStudioHdr->pAnimdesc( seqdesc.anim( 0, 0 ) ).numframes, - widthPercent, - flWeight * 100.0f - ); - ++ numLines; - - if ( seqdesc.numiklocks ) - { - sprintf( chBuffer, - "iklocks : %-2d : ", - seqdesc.numiklocks ); - - for ( int k = 0; k < seqdesc.numiklocks; ++ k ) - { - mstudioiklock_t *plock = seqdesc.pIKLock( k ); - mstudioikchain_t *pchain = pStudioHdr->pIKChain( plock->chain ); - - sprintf( chBuffer + strlen( chBuffer ), "%s ", pchain->pszName() ); - // plock->flPosWeight; - // plock->flLocalQWeight; - } - - sprintf( txt.m_chTextLines[numLines], - "%-*s", - widthIks, - chBuffer - ); - ++ numLines; - } - - if ( seqdesc.numikrules ) - { - sprintf( chBuffer, "ikrules : %-2d", - seqdesc.numikrules ); - - sprintf( txt.m_chTextLines[numLines], - "%-*s", - widthIks, - chBuffer - ); - ++ numLines; - } - - - // Now add the accumulated text into the container - mpi.AddInfoText( &txt, pMpiOld ); - mpi.PrintPendingInfoText( m_nPosPrint ); -} - - -////////////////////////////////////////////////////////////////////////// -// -// Con-commands -// -////////////////////////////////////////////////////////////////////////// - -static void IN_PoseDebuggerStart( const CCommand &args ) -{ - if ( args.ArgC() <= 1 ) - { - // No args, enable all - s_PoseDebuggerImpl.ShowAllModels( true ); - } - else - { - // If explicitly showing the pose debugger when it was disabled - if ( g_pPoseDebugger != &s_PoseDebuggerImpl ) - { - s_PoseDebuggerImpl.ShowAllModels( false ); - } - - // Show only specific models - for ( int k = 1; k < args.ArgC(); ++ k ) - { - int iEntNum = atoi( args.Arg( k ) ); - s_PoseDebuggerImpl.ShowModel( iEntNum, true ); - } - } - - g_pPoseDebugger = &s_PoseDebuggerImpl; -} - -static void IN_PoseDebuggerEnd( const CCommand &args ) -{ - if ( args.ArgC() <= 1 ) - { - // No args, disable all - s_PoseDebuggerImpl.ShowAllModels( false ); - - // Set the stub pointer - g_pPoseDebugger = &s_PoseDebuggerStub; - } - else - { - // Hide only specific models - for ( int k = 1; k < args.ArgC(); ++ k ) - { - int iEntNum = atoi( args.Arg( k ) ); - s_PoseDebuggerImpl.ShowModel( iEntNum, false ); - } - } -} - -static ConCommand posedebuggerstart( "+posedebug", IN_PoseDebuggerStart, "Turn on pose debugger or add ents to pose debugger UI", FCVAR_CHEAT ); -static ConCommand posedebuggerend ( "-posedebug", IN_PoseDebuggerEnd, "Turn off pose debugger or hide ents from pose debugger UI", FCVAR_CHEAT ); diff --git a/public/posedebugger.h b/public/posedebugger.h deleted file mode 100644 index fb5e95cc6..000000000 --- a/public/posedebugger.h +++ /dev/null @@ -1,38 +0,0 @@ -//====== Copyright c 1996-2007, Valve Corporation, All rights reserved. =======// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef POSEDEBUGGER_H -#define POSEDEBUGGER_H -#ifdef _WIN32 -#pragma once -#endif - -class IClientNetworkable; - -abstract_class IPoseDebugger -{ -public: - virtual void StartBlending( IClientNetworkable *pEntity, const CStudioHdr *pStudioHdr ) = 0; - - virtual void AccumulatePose( - const CStudioHdr *pStudioHdr, - CIKContext *pIKContext, - Vector pos[], - Quaternion q[], - int sequence, - float cycle, - const float poseParameter[], - int boneMask, - float flWeight, - float flTime - ) = 0; -}; - -extern IPoseDebugger *g_pPoseDebugger; - -#endif // #ifndef POSEDEBUGGER_H diff --git a/public/r_efx.h b/public/r_efx.h deleted file mode 100644 index d958cc74c..000000000 --- a/public/r_efx.h +++ /dev/null @@ -1,38 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// -#if !defined ( EFXH ) -#define EFXH -#ifdef _WIN32 -#pragma once -#endif - -#include "iefx.h" - -class IMaterial; -struct dlight_t; - -class CVEfx : public IVEfx -{ -public: - virtual ~CVEfx() {} - - virtual int Draw_DecalIndexFromName ( char *name ); - virtual void DecalShoot ( int textureIndex, int entity, const model_t *model, const Vector& model_origin, const QAngle& model_angles, const Vector& position, const Vector *saxis, int flags); - virtual void DecalColorShoot ( int textureIndex, int entity, const model_t *model, const Vector& model_origin, const QAngle& model_angles, const Vector& position, const Vector *saxis, int flags, const color32 &rgbaColor); - virtual void PlayerDecalShoot ( IMaterial *material, void *userdata, int entity, const model_t *model, const Vector& model_origin, const QAngle& model_angles, - const Vector& position, const Vector *saxis, int flags, const color32 &rgbaColor ); - virtual dlight_t *CL_AllocDlight ( int key ); - virtual dlight_t *CL_AllocElight ( int key ); - virtual int CL_GetActiveDLights ( dlight_t *pList[MAX_DLIGHTS] ); - virtual const char *Draw_DecalNameFromIndex ( int nIndex ); - virtual dlight_t *GetElightByKey ( int key ); -}; - -extern CVEfx *g_pEfx; - -#endif diff --git a/public/raytrace.h b/public/raytrace.h deleted file mode 100644 index 62657529e..000000000 --- a/public/raytrace.h +++ /dev/null @@ -1,389 +0,0 @@ -// $Id:$ - -#ifndef RAYTRACE_H -#define RAYTRACE_H - -#include -#include -#include -#include -#include -#include -#include -#include - -// fast SSE-ONLY ray tracing module. Based upon various "real time ray tracing" research. -//#define DEBUG_RAYTRACE 1 - -class FourRays -{ -public: - FourVectors origin; - FourVectors direction; - - inline void Check(void) const - { - // in order to be valid to trace as a group, all four rays must have the same signs in all - // of their direction components -#ifndef NDEBUG - for(int c=1;c<4;c++) - { - Assert(direction.X(0)*direction.X(c)>=0); - Assert(direction.Y(0)*direction.Y(c)>=0); - Assert(direction.Z(0)*direction.Z(c)>=0); - } -#endif - } - // returns direction sign mask for 4 rays. returns -1 if the rays can not be traced as a - // bundle. - int CalculateDirectionSignMask(void) const; - -}; - -/// The format a triangle is stored in for intersections. size of this structure is important. -/// This structure can be in one of two forms. Before the ray tracing environment is set up, the -/// ProjectedEdgeEquations hold the coordinates of the 3 vertices, for facilitating bounding box -/// checks needed while building the tree. afterwards, they are changed into the projected ege -/// equations for intersection purposes. -enum triangleflags -{ - FCACHETRI_TRANSPARENT = 0x01, - FCACHETRI_NEGATIVE_NORMAL = 0x02, -}; - - -struct TriIntersectData_t -{ - // this structure is 16longs=64 bytes for cache line packing. - float m_flNx, m_flNy, m_flNz; // plane equation - float m_flD; - - int32 m_nTriangleID; // id of the triangle. - - float m_ProjectedEdgeEquations[6]; // A,B,C for each edge equation. a - // point is inside the triangle if - // a*c1+b*c2+c is negative for all 3 - // edges. - - uint8 m_nCoordSelect0,m_nCoordSelect1; // the triangle is projected onto a 2d - // plane for edge testing. These are - // the indices (0..2) of the - // coordinates preserved in the - // projection - - uint8 m_nFlags; // triangle flags - uint8 m_unused0; // no longer used -}; - - -struct TriGeometryData_t -{ - int32 m_nTriangleID; // id of the triangle. - - float m_VertexCoordData[9]; // can't use a vector in a union - - uint8 m_nFlags; // triangle flags - signed char m_nTmpData0; // used by kd-tree builder - signed char m_nTmpData1; // used by kd-tree builder - - - // accessors to get around union annoyance - FORCEINLINE Vector &Vertex(int idx) - { - return * ( reinterpret_cast ( m_VertexCoordData+3*idx ) ); - } - -}; - - -struct CacheOptimizedTriangle -{ - - union - { - TriIntersectData_t m_IntersectData; - TriGeometryData_t m_GeometryData; - } m_Data; - - // accessors to get around union annoyance - FORCEINLINE Vector &Vertex(int idx) - { - return * ( reinterpret_cast (m_Data.m_GeometryData.m_VertexCoordData+3*idx ) ); - } - - FORCEINLINE const Vector &Vertex(int idx) const - { - return * ( reinterpret_cast (m_Data.m_GeometryData.m_VertexCoordData+3*idx ) ); - } - - void ChangeIntoIntersectionFormat(void); // change information storage format for - // computing intersections. - - int ClassifyAgainstAxisSplit(int split_plane, float split_value); // PLANECHECK_xxx below - -}; - -#define PLANECHECK_POSITIVE 1 -#define PLANECHECK_NEGATIVE -1 -#define PLANECHECK_STRADDLING 0 - -#define KDNODE_STATE_XSPLIT 0 // this node is an x split -#define KDNODE_STATE_YSPLIT 1 // this node is a ysplit -#define KDNODE_STATE_ZSPLIT 2 // this node is a zsplit -#define KDNODE_STATE_LEAF 3 // this node is a leaf - -struct CacheOptimizedKDNode -{ - // this is the cache intensive data structure. "Tricks" are used to fit it into 8 bytes: - // - // A) the right child is always stored after the left child, which means we only need one - // pointer - // B) The type of node (KDNODE_xx) is stored in the lower 2 bits of the pointer. - // C) for leaf nodes, we store the number of triangles in the leaf in the same place as the floating - // point splitting parameter is stored in a non-leaf node - - int32 Children; // child idx, or'ed with flags above - float SplittingPlaneValue; // for non-leaf nodes, the nodes on the - // "high" side of the splitting plane - // are on the right - -#ifdef DEBUG_RAYTRACE - Vector vecMins; - Vector vecMaxs; -#endif - - inline int NodeType(void) const - - { - return Children & 3; - } - - inline int32 TriangleIndexStart(void) const - { - assert(NodeType()==KDNODE_STATE_LEAF); - return Children>>2; - } - - inline int LeftChild(void) const - { - assert(NodeType()!=KDNODE_STATE_LEAF); - return Children>>2; - } - - inline int RightChild(void) const - { - return LeftChild()+1; - } - - inline int NumberOfTrianglesInLeaf(void) const - { - assert(NodeType()==KDNODE_STATE_LEAF); - return *((int32 *) &SplittingPlaneValue); - } - - inline void SetNumberOfTrianglesInLeafNode(int n) - { - *((int32 *) &SplittingPlaneValue)=n; - } - -protected: - - -}; - - -struct RayTracingSingleResult -{ - Vector surface_normal; // surface normal at intersection - int32 HitID; // -1=no hit. otherwise, triangle index - float HitDistance; // distance to intersection - float ray_length; // leng of initial ray -}; - -struct RayTracingResult -{ - FourVectors surface_normal; // surface normal at intersection - ALIGN16 int32 HitIds[4]; // -1=no hit. otherwise, triangle index - fltx4 HitDistance; // distance to intersection -}; - - -class RayTraceLight -{ -public: - FourVectors Position; - FourVectors Intensity; -}; - - -#define RTE_FLAGS_FAST_TREE_GENERATION 1 -#define RTE_FLAGS_DONT_STORE_TRIANGLE_COLORS 2 // saves memory if not needed -#define RTE_FLAGS_DONT_STORE_TRIANGLE_MATERIALS 4 - -enum RayTraceLightingMode_t { - DIRECT_LIGHTING, // just dot product lighting - DIRECT_LIGHTING_WITH_SHADOWS, // with shadows - GLOBAL_LIGHTING // global light w/ shadows -}; - - -class RayStream -{ - friend class RayTracingEnvironment; - - RayTracingSingleResult *PendingStreamOutputs[8][4]; - int n_in_stream[8]; - FourRays PendingRays[8]; - -public: - RayStream(void) - { - memset(n_in_stream,0,sizeof(n_in_stream)); - } -}; - -// When transparent triangles are in the list, the caller can provide a callback that will get called at each triangle -// allowing the callback to stop processing if desired. -// UNDONE: This is not currently SIMD - it really only supports single rays -// Also for efficiency FourRays really needs some kind of active mask for the cases where rays get unbundled -class ITransparentTriangleCallback -{ -public: - virtual bool VisitTriangle_ShouldContinue( const TriIntersectData_t &triangle, const FourRays &rays, fltx4 *hitMask, fltx4 *b0, fltx4 *b1, fltx4 *b2, int32 hitID ) = 0; -}; - -class RayTracingEnvironment -{ -public: - uint32 Flags; // RTE_FLAGS_xxx above - Vector m_MinBound; - Vector m_MaxBound; - - FourVectors BackgroundColor; //< color where no intersection - CUtlVector OptimizedKDTree; //< the packed kdtree. root is 0 - CUtlBlockVector OptimizedTriangleList; //< the packed triangles - CUtlVector TriangleIndexList; //< the list of triangle indices. - CUtlVector LightList; //< the list of lights - CUtlVector TriangleColors; //< color of tries - CUtlVector TriangleMaterials; //< material index of tries - -public: - RayTracingEnvironment() : OptimizedTriangleList( 1024 ) - { - BackgroundColor.DuplicateVector(Vector(1,0,0)); // red - Flags=0; - } - - - // call AddTriangle to set up the world - void AddTriangle(int32 id, const Vector &v1, const Vector &v2, const Vector &v3, - const Vector &color); - - // Adds a triangle with flags & material - void AddTriangle(int32 id, const Vector &v1, const Vector &v2, const Vector &v3, - const Vector &color, uint16 flags, int32 materialIndex); - - - void AddQuad(int32 id, const Vector &v1, const Vector &v2, const Vector &v3, - const Vector &v4, // specify vertices in cw or ccw order - const Vector &color); - - // for ease of testing. - void AddAxisAlignedRectangularSolid(int id,Vector mincoord, Vector Maxcoord, - const Vector &color); - - - // SetupAccelerationStructure to prepare for tracing - void SetupAccelerationStructure(void); - - - // lowest level intersection routine - fire 4 rays through the scene. all 4 rays must pass the - // Check() function, and t extents must be initialized. skipid can be set to exclude a - // particular id (such as the origin surface). This function finds the closest intersection. - void Trace4Rays(const FourRays &rays, fltx4 TMin, fltx4 TMax,int DirectionSignMask, - RayTracingResult *rslt_out, - int32 skip_id=-1, ITransparentTriangleCallback *pCallback = NULL); - - // higher level intersection routine that handles computing the mask and handling rays which do not match in direciton sign - void Trace4Rays(const FourRays &rays, fltx4 TMin, fltx4 TMax, - RayTracingResult *rslt_out, - int32 skip_id=-1, ITransparentTriangleCallback *pCallback = NULL); - - // compute virtual light sources to model inter-reflection - void ComputeVirtualLightSources(void); - - - // high level interface - pass viewing parameters, rendering flags, and a destination frame - // buffer, and get a ray traced scene in 32-bit rgba format - void RenderScene(int width, int height, // width and height of desired rendering - int stride, // actual width in pixels of target buffer - uint32 *output_buffer, // pointer to destination - Vector CameraOrigin, // eye position - Vector ULCorner, // word space coordinates of upper left - // monitor corner - Vector URCorner, // top right corner - Vector LLCorner, // lower left - Vector LRCorner, // lower right - RayTraceLightingMode_t lightmode=DIRECT_LIGHTING); - - - /// raytracing stream - lets you trace an array of rays by feeding them to this function. - /// results will not be returned until FinishStream is called. This function handles sorting - /// the rays by direction, tracing them 4 at a time, and de-interleaving the results. - - void AddToRayStream(RayStream &s, - Vector const &start,Vector const &end,RayTracingSingleResult *rslt_out); - - inline void RayTracingEnvironment::FlushStreamEntry(RayStream &s,int msk); - - /// call this when you are done. handles all cleanup. After this is called, all rslt ptrs - /// previously passed to AddToRaySteam will have been filled in. - void FinishRayStream(RayStream &s); - - - int MakeLeafNode(int first_tri, int last_tri); - - - float CalculateCostsOfSplit( - int split_plane,int32 const *tri_list,int ntris, - Vector MinBound,Vector MaxBound, float &split_value, - int &nleft, int &nright, int &nboth); - - void RefineNode(int node_number,int32 const *tri_list,int ntris, - Vector MinBound,Vector MaxBound, int depth); - - void CalculateTriangleListBounds(int32 const *tris,int ntris, - Vector &minout, Vector &maxout); - - void AddInfinitePointLight(Vector position, // light center - Vector intensity); // rgb amount - - // use the global variables set by LoadBSPFile to populated the RayTracingEnvironment with - // faces. - void InitializeFromLoadedBSP(void); - - void AddBSPFace(int id,dface_t const &face); - - // MakeRoomForTriangles - a hint telling it how many triangles we are going to add so that - // the utl vectors used can be pre-allocated - void MakeRoomForTriangles( int ntriangles ); - - const CacheOptimizedTriangle &GetTriangle( int32 triID ) - { - return OptimizedTriangleList[triID]; - } - - int32 GetTriangleMaterial( int32 triID ) - { - return TriangleMaterials[triID]; - } - const Vector &GetTriangleColor( int triID ) - { - return TriangleColors[triID]; - } - -}; - - - -#endif diff --git a/public/registry.cpp b/public/registry.cpp deleted file mode 100644 index 22553846a..000000000 --- a/public/registry.cpp +++ /dev/null @@ -1,323 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef _LINUX -#if !defined( _X360 ) -#include -#endif -#include "tier0/platform.h" -#include "tier0/vcrmode.h" -#include "iregistry.h" -#include "tier0/dbg.h" -#include "tier1/strtools.h" -#include -#if defined( _X360 ) -#include "xbox/xbox_win32stubs.h" -#endif - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: Exposes registry interface to rest of launcher -//----------------------------------------------------------------------------- -class CRegistry : public IRegistry -{ -public: - CRegistry( void ); - virtual ~CRegistry( void ); - - virtual bool Init( const char *platformName ); - virtual bool DirectInit( const char *subDirectoryUnderValve ); - virtual void Shutdown( void ); - - virtual int ReadInt( const char *key, int defaultValue = 0); - virtual void WriteInt( const char *key, int value ); - - virtual const char *ReadString( const char *key, const char *defaultValue = NULL ); - virtual void WriteString( const char *key, const char *value ); - - // Read/write helper methods - virtual int ReadInt( const char *pKeyBase, const char *pKey, int defaultValue = 0 ); - virtual void WriteInt( const char *pKeyBase, const char *key, int value ); - virtual const char *ReadString( const char *pKeyBase, const char *key, const char *defaultValue ); - virtual void WriteString( const char *pKeyBase, const char *key, const char *value ); - -private: - bool m_bValid; - HKEY m_hKey; -}; - -// Creates it and calls Init -IRegistry *InstanceRegistry( char const *subDirectoryUnderValve ) -{ - CRegistry *instance = new CRegistry(); - instance->DirectInit( subDirectoryUnderValve ); - return instance; -} - -// Calls Shutdown and deletes it -void ReleaseInstancedRegistry( IRegistry *reg ) -{ - if ( !reg ) - { - Assert( !"ReleaseInstancedRegistry( reg == NULL )!" ); - return; - } - - reg->Shutdown(); - delete reg; -} - -// Expose to launcher -static CRegistry g_Registry; -IRegistry *registry = ( IRegistry * )&g_Registry; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CRegistry::CRegistry( void ) -{ - // Assume failure - m_bValid = false; - m_hKey = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CRegistry::~CRegistry( void ) -{ -} - -//----------------------------------------------------------------------------- -// Purpose: Read integer from registry -// Input : *key - -// defaultValue - -// Output : int -//----------------------------------------------------------------------------- -int CRegistry::ReadInt( const char *key, int defaultValue /*= 0*/ ) -{ - LONG lResult; // Registry function result code - DWORD dwType; // Type of key - DWORD dwSize; // Size of element data - - int value; - - if ( !m_bValid ) - { - return defaultValue; - } - - dwSize = sizeof( DWORD ); - - lResult = VCRHook_RegQueryValueEx( - m_hKey, // handle to key - key, // value name - 0, // reserved - &dwType, // type buffer - (LPBYTE)&value, // data buffer - &dwSize ); // size of data buffer - - if (lResult != ERROR_SUCCESS) // Failure - return defaultValue; - - if (dwType != REG_DWORD) - return defaultValue; - - return value; -} - -//----------------------------------------------------------------------------- -// Purpose: Save integer to registry -// Input : *key - -// value - -//----------------------------------------------------------------------------- -void CRegistry::WriteInt( const char *key, int value ) -{ - // Size of element data - DWORD dwSize; - - if ( !m_bValid ) - { - return; - } - - dwSize = sizeof( DWORD ); - - VCRHook_RegSetValueEx( - m_hKey, // handle to key - key, // value name - 0, // reserved - REG_DWORD, // type buffer - (LPBYTE)&value, // data buffer - dwSize ); // size of data buffer -} - -//----------------------------------------------------------------------------- -// Purpose: Read string value from registry -// Input : *key - -// *defaultValue - -// Output : const char -//----------------------------------------------------------------------------- -const char *CRegistry::ReadString( const char *key, const char *defaultValue /* = NULL */ ) -{ - LONG lResult; - // Type of key - DWORD dwType; - // Size of element data - DWORD dwSize = 512; - - static char value[ 512 ]; - - value[0] = 0; - - if ( !m_bValid ) - { - return defaultValue; - } - - lResult = VCRHook_RegQueryValueEx( - m_hKey, // handle to key - key, // value name - 0, // reserved - &dwType, // type buffer - (unsigned char *)value, // data buffer - &dwSize ); // size of data buffer - - if ( lResult != ERROR_SUCCESS ) - { - return defaultValue; - } - - if ( dwType != REG_SZ ) - { - return defaultValue; - } - - return value; -} - -//----------------------------------------------------------------------------- -// Purpose: Save string to registry -// Input : *key - -// *value - -//----------------------------------------------------------------------------- -void CRegistry::WriteString( const char *key, const char *value ) -{ - DWORD dwSize; // Size of element data - - if ( !m_bValid ) - { - return; - } - - dwSize = (DWORD)( strlen( value ) + 1 ); - - VCRHook_RegSetValueEx( - m_hKey, // handle to key - key, // value name - 0, // reserved - REG_SZ, // type buffer - (LPBYTE)value, // data buffer - dwSize ); // size of data buffer -} - - -//----------------------------------------------------------------------------- -// Read/write helper methods -//----------------------------------------------------------------------------- -int CRegistry::ReadInt( const char *pKeyBase, const char *pKey, int defaultValue ) -{ - int nLen = strlen( pKeyBase ); - int nKeyLen = strlen( pKey ); - char *pFullKey = (char*)_alloca( nLen + nKeyLen + 2 ); - Q_snprintf( pFullKey, nLen + nKeyLen + 2, "%s\\%s", pKeyBase, pKey ); - return ReadInt( pFullKey, defaultValue ); -} - -void CRegistry::WriteInt( const char *pKeyBase, const char *pKey, int value ) -{ - int nLen = strlen( pKeyBase ); - int nKeyLen = strlen( pKey ); - char *pFullKey = (char*)_alloca( nLen + nKeyLen + 2 ); - Q_snprintf( pFullKey, nLen + nKeyLen + 2, "%s\\%s", pKeyBase, pKey ); - WriteInt( pFullKey, value ); -} - -const char *CRegistry::ReadString( const char *pKeyBase, const char *pKey, const char *defaultValue ) -{ - int nLen = strlen( pKeyBase ); - int nKeyLen = strlen( pKey ); - char *pFullKey = (char*)_alloca( nLen + nKeyLen + 2 ); - Q_snprintf( pFullKey, nLen + nKeyLen + 2, "%s\\%s", pKeyBase, pKey ); - return ReadString( pFullKey, defaultValue ); -} - -void CRegistry::WriteString( const char *pKeyBase, const char *pKey, const char *value ) -{ - int nLen = strlen( pKeyBase ); - int nKeyLen = strlen( pKey ); - char *pFullKey = (char*)_alloca( nLen + nKeyLen + 2 ); - Q_snprintf( pFullKey, nLen + nKeyLen + 2, "%s\\%s", pKeyBase, pKey ); - WriteString( pFullKey, value ); -} - -bool CRegistry::DirectInit( const char *subDirectoryUnderValve ) -{ - LONG lResult; // Registry function result code - ULONG dwDisposition; // Type of key opening event - - char szModelKey[ 1024 ]; - wsprintf( szModelKey, "Software\\Valve\\%s", subDirectoryUnderValve ); - - lResult = VCRHook_RegCreateKeyEx( - HKEY_CURRENT_USER, // handle of open key - szModelKey, // address of name of subkey to open - 0ul, // DWORD ulOptions, // reserved - NULL, // Type of value - REG_OPTION_NON_VOLATILE, // Store permanently in reg. - KEY_ALL_ACCESS, // REGSAM samDesired, // security access mask - NULL, - &m_hKey, // Key we are creating - &dwDisposition ); // Type of creation - - if ( lResult != ERROR_SUCCESS ) - { - m_bValid = false; - return false; - } - - // Success - m_bValid = true; - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Open default launcher key based on game directory -//----------------------------------------------------------------------------- -bool CRegistry::Init( const char *platformName ) -{ - char subDir[ 512 ]; - wsprintf( subDir, "%s\\Settings", platformName ); - return DirectInit( subDir ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CRegistry::Shutdown( void ) -{ - if ( !m_bValid ) - return; - - // Make invalid - m_bValid = false; - VCRHook_RegCloseKey( m_hKey ); -} -#endif // _LINUX - diff --git a/public/renderparm.h b/public/renderparm.h deleted file mode 100644 index a10bcae1e..000000000 --- a/public/renderparm.h +++ /dev/null @@ -1,39 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: defines constants to use for the materialsystem and shaderapi -// SetxxxRenderingParameter functions -// -// $NoKeywords: $ -// -//===========================================================================// - -#ifndef RENDERPARM_H -#define RENDERPARM_H - -#ifndef _WIN32 -#pragma once -#endif - -#define MAX_FLOAT_RENDER_PARMS 20 -#define MAX_VECTOR_RENDER_PARMS 20 - -enum RenderParamInt_t -{ - INT_RENDERPARM_ENABLE_FIXED_LIGHTING = 0, - INT_RENDERPARM_MORPH_ACCUMULATOR_X_OFFSET, - INT_RENDERPARM_MORPH_ACCUMULATOR_Y_OFFSET, - INT_RENDERPARM_MORPH_ACCUMULATOR_SUBRECT_WIDTH, - INT_RENDERPARM_MORPH_ACCUMULATOR_SUBRECT_HEIGHT, - INT_RENDERPARM_MORPH_ACCUMULATOR_4TUPLE_COUNT, - - INT_RENDERPARM_MORPH_WEIGHT_X_OFFSET, - INT_RENDERPARM_MORPH_WEIGHT_Y_OFFSET, - INT_RENDERPARM_MORPH_WEIGHT_SUBRECT_WIDTH, - INT_RENDERPARM_MORPH_WEIGHT_SUBRECT_HEIGHT, - - INT_RENDERPARM_WRITE_DEPTH_TO_DESTALPHA, - - MAX_INT_RENDER_PARMS = 20 -}; - -#endif // RENDERPARM_H diff --git a/public/rope_physics.cpp b/public/rope_physics.cpp deleted file mode 100644 index 225e205f6..000000000 --- a/public/rope_physics.cpp +++ /dev/null @@ -1,152 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - - -#include "rope_physics.h" -#include "tier0/dbg.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -CBaseRopePhysics::CBaseRopePhysics( CSimplePhysics::CNode *pNodes, int nNodes, CRopeSpring *pSprings, float *flSpringDistsSqr ) -{ - m_pNodes = pNodes; - m_pSprings = pSprings; - m_flNodeSpringDistsSqr = flSpringDistsSqr; - m_flSpringDist = m_flSpringDistSqr = 1; - Restart(); - - // Initialize the nodes. - for ( int i=0; i < nNodes; i++ ) - { - pNodes[i].m_vPos.Init(); - pNodes[i].m_vPrevPos.Init(); - pNodes[i].m_vPredicted.Init(); - } - - SetNumNodes( nNodes ); - - m_pDelegate = NULL; -} - - -void CBaseRopePhysics::SetNumNodes( int nNodes ) -{ - m_nNodes = nNodes; - - // Setup the springs. - for( int i=0; i < NumSprings(); i++ ) - { - m_pSprings[i].m_pNode1 = &m_pNodes[i].m_vPos; - m_pSprings[i].m_pNode2 = &m_pNodes[i+1].m_vPos; - Assert( m_pSprings[i].m_pNode1->IsValid() ); - Assert( m_pSprings[i].m_pNode2->IsValid() ); - - m_flNodeSpringDistsSqr[i] = m_flSpringDistSqr / NumSprings(); - } -} - - -void CBaseRopePhysics::Restart() -{ - m_Physics.Init( 1.0 / 50 ); -} - - -void CBaseRopePhysics::ResetSpringLength( float flSpringDist ) -{ - m_flSpringDist = MAX( flSpringDist, 0 ); - m_flSpringDistSqr = m_flSpringDist * m_flSpringDist; - - for( int i=0; i < NumSprings(); i++ ) - { - m_flNodeSpringDistsSqr[i] = m_flSpringDistSqr / NumSprings(); - } -} - -float CBaseRopePhysics::GetSpringLength() const -{ - return m_flSpringDist; -} - -void CBaseRopePhysics::ResetNodeSpringLength( int iStartNode, float flSpringDist ) -{ - m_flNodeSpringDistsSqr[iStartNode] = flSpringDist * flSpringDist; -} - -void CBaseRopePhysics::SetupSimulation( float flSpringDist, CSimplePhysics::IHelper *pDelegate ) -{ - ResetSpringLength( flSpringDist ); - SetDelegate( pDelegate ); -} - - -void CBaseRopePhysics::SetDelegate( CSimplePhysics::IHelper *pDelegate ) -{ - m_pDelegate = pDelegate; -} - - -void CBaseRopePhysics::Simulate( float dt ) -{ - static float flEnergy = 0.98; - m_Physics.Simulate( m_pNodes, m_nNodes, this, dt, flEnergy ); -} - - -void CBaseRopePhysics::GetNodeForces( CSimplePhysics::CNode *pNodes, int iNode, Vector *pAccel ) -{ - if( m_pDelegate ) - m_pDelegate->GetNodeForces( pNodes, iNode, pAccel ); - else - pAccel->Init( 0, 0, 0 ); -} - - -void CBaseRopePhysics::ApplyConstraints( CSimplePhysics::CNode *pNodes, int nNodes ) -{ - // Handle springs.. - // - // Iterate multiple times here. If we don't, then gravity tends to - // win over the constraint solver and it's impossible to get straight ropes. - static int nIterations = 3; - for( int iIteration=0; iIteration < nIterations; iIteration++ ) - { - for( int i=0; i < NumSprings(); i++ ) - { - CRopeSpring *s = &m_pSprings[i]; - - Vector vTo = *s->m_pNode1 - *s->m_pNode2; - - float flDistSqr = vTo.LengthSqr(); - - // If we don't have an overall spring distance, see if we have a per-node one - float flSpringDist = m_flSpringDistSqr; - if ( !flSpringDist ) - { - // TODO: This still isn't enough. Ropes with different spring lengths - // per-node will oscillate forever. - flSpringDist = m_flNodeSpringDistsSqr[i]; - } - - if( flDistSqr > flSpringDist ) - { - float flDist = (float)sqrt( flDistSqr ); - vTo *= 1 - (m_flSpringDist / flDist); - - *s->m_pNode1 -= vTo * 0.5f; - *s->m_pNode2 += vTo * 0.5f; - } - } - - if( m_pDelegate ) - m_pDelegate->ApplyConstraints( pNodes, nNodes ); - } -} - - diff --git a/public/rope_physics.h b/public/rope_physics.h deleted file mode 100644 index 94e1e9b79..000000000 --- a/public/rope_physics.h +++ /dev/null @@ -1,117 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ROPE_PHYSICS_H -#define ROPE_PHYSICS_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "simple_physics.h" -#include "networkvar.h" - - -class CRopeSpring -{ -public: - Vector *m_pNode1; - Vector *m_pNode2; -}; - - -class CBaseRopePhysics : public CSimplePhysics::IHelper -{ -public: - DECLARE_CLASS_NOBASE( CBaseRopePhysics ); - - CBaseRopePhysics( - CSimplePhysics::CNode *pNodes, - int nNodes, - CRopeSpring *pSprings, - float *flSpringDistsSqr ); - - // nNodes should be less than or equal to what you passed into the constructor. - void SetNumNodes( int nNodes ); - - // Restart timers and such. - void Restart(); - - void ResetSpringLength(float flSpringDist ); - float GetSpringLength() const; - void ResetNodeSpringLength( int iStartNode, float flSpringDist ); - - // Set simulation parameters. - // If you pass in a delegate, you can be called to apply constraints. - void SetupSimulation( float flSpringDist, CSimplePhysics::IHelper *pDelegate=0 ); - - // Set the physics delegate. - void SetDelegate( CSimplePhysics::IHelper *pDelegate ); - - void Simulate( float dt ); - - int NumNodes() { return m_nNodes; } - CSimplePhysics::CNode* GetNode( int iNode ) { return &m_pNodes[iNode]; } - CSimplePhysics::CNode* GetFirstNode() { return &m_pNodes[0]; } - CSimplePhysics::CNode* GetLastNode() { return &m_pNodes[ m_nNodes-1 ]; } - - - -public: - - virtual void GetNodeForces( CSimplePhysics::CNode *pNodes, int iNode, Vector *pAccel ); - virtual void ApplyConstraints( CSimplePhysics::CNode *pNodes, int nNodes ); - - -private: - - int NumSprings() {return m_nNodes - 1;} - - -protected: - - CSimplePhysics::IHelper *m_pDelegate; - - CSimplePhysics::CNode *m_pNodes; - int m_nNodes; - - CRopeSpring *m_pSprings; - - float m_flSpringDist; - float m_flSpringDistSqr; - - // Spring lengths per node - float *m_flNodeSpringDistsSqr; - - CSimplePhysics m_Physics; -}; - - - - - -template< int NUM_NODES > -class CRopePhysics : public CBaseRopePhysics -{ -public: - - CRopePhysics(); - - CSimplePhysics::CNode m_Nodes[NUM_NODES]; - CRopeSpring m_Springs[NUM_NODES - 1]; - float m_SpringDistsSqr[NUM_NODES - 1]; -}; - - -template< int NUM_NODES > -CRopePhysics::CRopePhysics() : - CBaseRopePhysics( m_Nodes, NUM_NODES, m_Springs, m_SpringDistsSqr ) -{ -} - - -#endif // ROPE_PHYSICS_H diff --git a/public/rope_shared.h b/public/rope_shared.h deleted file mode 100644 index a71ebd2f6..000000000 --- a/public/rope_shared.h +++ /dev/null @@ -1,69 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ROPE_SHARED_H -#define ROPE_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - - -// Shared definitions for rope. -#define ROPE_MAX_SEGMENTS 10 -#define ROPE_TYPE1_NUMSEGMENTS 4 -#define ROPE_TYPE2_NUMSEGMENTS 2 - -// Default rope gravity vector. -#define ROPE_GRAVITY 0, 0, -1500 - - -// Rope flags. -#define ROPE_RESIZE (1<<0) // Try to keep the rope dangling the same amount - // even as the rope length changes. -#define ROPE_BARBED (1<<1) // Hack option to draw like a barbed wire. -#define ROPE_COLLIDE (1<<2) // Collide with the world? -#define ROPE_SIMULATE (1<<3) // Is the rope valid? -#define ROPE_BREAKABLE (1<<4) // Can the endpoints detach? -#define ROPE_NO_WIND (1<<5) // No wind simulation on this rope. -#define ROPE_INITIAL_HANG (1<<6) // By default, ropes will simulate for a bit internally when they - // are created so they sag, but dynamically created ropes for things - // like harpoons don't want this. -#define ROPE_PLAYER_WPN_ATTACH (1<<7) // If this flag is set, then the second attachment must be a player. - // The rope will attach to "buff_attach" on the player's active weapon. - // (This is a flag because it requires special code on the client to - // find the weapon). -#define ROPE_NO_GRAVITY (1<<8) // Disable gravity on this rope. -#define ROPE_NUMFLAGS 9 - - -// This is added to all rope slacks so when a level designer enters a -// slack of zero in the entity, it doesn't dangle so low. -#define ROPESLACK_FUDGEFACTOR -100 - - -// Rope shader IDs. -#define ROPESHADER_BLACKCABLE 0 -#define ROPESHADER_ROPE 1 -#define ROPESHADER_CHAIN 2 - - -// Rope locked points -enum -{ - ROPE_LOCK_START_POINT = 0x1, - ROPE_LOCK_END_POINT = 0x2, - ROPE_LOCK_START_DIRECTION = 0x4, - ROPE_LOCK_END_DIRECTION = 0x8, -}; - - -// Rope attachment points. -#define ROPE_ATTACHMENT_START_POINT 1 -#define ROPE_ATTACHMENT_END_POINT 2 - - -#endif // ROPE_SHARED_H diff --git a/public/savegame_version.h b/public/savegame_version.h deleted file mode 100644 index 0e5f0a273..000000000 --- a/public/savegame_version.h +++ /dev/null @@ -1,15 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#if !defined( SAVEGAME_VERSION_H ) -#define SAVEGAME_VERSION_H -#ifdef _WIN32 -#pragma once -#endif - -#define SAVEGAME_VERSION 0x0073 // Version 0.73 - -#endif // SAVEGAME_VERSION_H diff --git a/public/saverestoretypes.h b/public/saverestoretypes.h deleted file mode 100644 index 1ce0259ca..000000000 --- a/public/saverestoretypes.h +++ /dev/null @@ -1,547 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -// @Note (toml 12-02-02): For now, all of the methods in the types defined here -// are inline to permit simple cross-DLL usage -//=============================================================================// - -#ifndef SAVERESTORETYPES_H -#define SAVERESTORETYPES_H - -#if defined( _WIN32 ) -#pragma once -#endif - -#include "tier1/utlhash.h" - -#include // NULL_STRING define -struct edict_t; - - -#ifdef EHANDLE_H // not available to engine -#define SR_ENTS_VISIBLE 1 -#endif - - -//----------------------------------------------------------------------------- -// -// class CSaveRestoreSegment -// - -class CSaveRestoreSegment -{ -public: - CSaveRestoreSegment(); - - //--------------------------------- - // Buffer operations - // - void Init( void *pNewBase, int nBytes ); - void Rebase(); - void Rewind( int nBytes ); - char *GetBuffer(); - int BytesAvailable() const; - int SizeBuffer() const; - bool Write( const void *pData, int nBytes ); - bool Read( void *pOutput, int nBytes ); - int GetCurPos(); - char *AccessCurPos(); - bool Seek( int absPosition ); - void MoveCurPos( int nBytes ); - - //--------------------------------- - // Symbol table operations - // - void InitSymbolTable( char **pNewTokens, int sizeTable); - char **DetachSymbolTable(); - int SizeSymbolTable(); - bool DefineSymbol( const char *pszToken, int token ); - unsigned short FindCreateSymbol( const char *pszToken ); - const char *StringFromSymbol( int token ); - -private: -#ifndef _WIN32 - unsigned _rotr ( unsigned val, int shift); -#endif - unsigned int HashString( const char *pszToken ); - - //--------------------------------- - // Buffer data - // - char *pBaseData; // Start of all entity save data - char *pCurrentData; // Current buffer pointer for sequential access - int size; // Current data size, aka, pCurrentData - pBaseData - int bufferSize; // Total space for data - - //--------------------------------- - // Symbol table - // - int tokenCount; // Number of elements in the pTokens table - char **pTokens; // Hash table of entity strings (sparse) -}; - - -//----------------------------------------------------------------------------- -// -// class CGameSaveRestoreInfo -// - -struct levellist_t -{ - DECLARE_SIMPLE_DATADESC(); - - char mapName[ MAX_MAP_NAME ]; - char landmarkName[ 32 ]; - edict_t *pentLandmark; - Vector vecLandmarkOrigin; -}; - -#define MAX_LEVEL_CONNECTIONS 16 // These are encoded in the lower 16bits of entitytable_t->flags - -//------------------------------------- - -struct EHandlePlaceholder_t // Engine does some of the game writing (alas, probably shouldn't), but can't see ehandle.h -{ - unsigned long i; -}; - -//------------------------------------- - -struct entitytable_t -{ - void Clear() - { - id = -1; - edictindex = -1; - saveentityindex = -1; - restoreentityindex = -1; - location = 0; - size = 0; - flags = 0; - classname = NULL_STRING; - globalname = NULL_STRING; - landmarkModelSpace.Init(); - modelname = NULL_STRING; - } - - int id; // Ordinal ID of this entity (used for entity <--> pointer conversions) - int edictindex; // saved for if the entity requires a certain edict number when restored (players, world) - - int saveentityindex; // the entity index the entity had at save time ( for fixing up client side entities ) - int restoreentityindex; // the entity index given to this entity at restore time - -#ifdef SR_ENTS_VISIBLE - EHANDLE hEnt; // Pointer to the in-game entity -#else - EHandlePlaceholder_t hEnt; -#endif - - int location; // Offset from the base data of this entity - int size; // Byte size of this entity's data - int flags; // This could be a short -- bit mask of transitions that this entity is in the PVS of - string_t classname; // entity class name - string_t globalname; // entity global name - Vector landmarkModelSpace; // a fixed position in model space for comparison - // NOTE: Brush models can be built in different coordiante systems - // in different levels, so this fixes up local quantities to match - // those differences. - string_t modelname; - - DECLARE_SIMPLE_DATADESC(); -}; - -#define FENTTABLE_PLAYER 0x80000000 -#define FENTTABLE_REMOVED 0x40000000 -#define FENTTABLE_MOVEABLE 0x20000000 -#define FENTTABLE_GLOBAL 0x10000000 -#define FENTTABLE_PLAYERCHILD 0x08000000 // this entity is connected to a player, so it must be spawned with it -#define FENTTABLE_LEVELMASK 0x0000FFFF // reserve bits for 16 level connections -//------------------------------------- - -struct saverestorelevelinfo_t -{ - int connectionCount;// Number of elements in the levelList[] - levellist_t levelList[ MAX_LEVEL_CONNECTIONS ]; // List of connections from this level - - // smooth transition - int fUseLandmark; - char szLandmarkName[20]; // landmark we'll spawn near in next level - Vector vecLandmarkOffset; // for landmark transitions - float time; - char szCurrentMapName[MAX_MAP_NAME]; // To check global entities - int mapVersion; -}; - -//------------------------------------- - -class CGameSaveRestoreInfo -{ -public: - CGameSaveRestoreInfo() - : tableCount( 0 ), pTable( 0 ), m_pCurrentEntity( 0 ), m_EntityToIndex( 1024 ) - { - memset( &levelInfo, 0, sizeof( levelInfo ) ); - modelSpaceOffset.Init( 0, 0, 0 ); - } - - void InitEntityTable( entitytable_t *pNewTable = NULL, int size = 0 ) - { - pTable = pNewTable; - tableCount = size; - - for ( int i = 0; i < NumEntities(); i++ ) - { - GetEntityInfo( i )->Clear(); - } - } - - entitytable_t *DetachEntityTable() - { - entitytable_t *pReturn = pTable; - pTable = NULL; - tableCount = 0; - return pReturn; - } - - CBaseEntity *GetCurrentEntityContext() { return m_pCurrentEntity; } - void SetCurrentEntityContext(CBaseEntity *pEntity) { m_pCurrentEntity = pEntity; } - - int NumEntities() { return tableCount; } - entitytable_t *GetEntityInfo( int i ) { return (pTable + i); } - float GetBaseTime() const { return levelInfo.time; } - Vector GetLandmark() const { return ( levelInfo.fUseLandmark ) ? levelInfo.vecLandmarkOffset : vec3_origin; } - - void BuildEntityHash() - { -#ifdef GAME_DLL - int i; - entitytable_t *pTable; - int nEntities = NumEntities(); - - for ( i = 0; i < nEntities; i++ ) - { - pTable = GetEntityInfo( i ); - m_EntityToIndex.Insert( CHashElement( pTable->hEnt.Get(), i ) ); - } -#endif - } - - void PurgeEntityHash() - { - m_EntityToIndex.Purge(); - } - - int GetEntityIndex( const CBaseEntity *pEntity ) - { -#ifdef SR_ENTS_VISIBLE - if ( pEntity ) - { - if ( m_EntityToIndex.Count() ) - { - UtlHashHandle_t hElement = m_EntityToIndex.Find( CHashElement( pEntity ) ); - if ( hElement != m_EntityToIndex.InvalidHandle() ) - { - return m_EntityToIndex.Element( hElement ).index; - } - } - else - { - int i; - entitytable_t *pTable; - - int nEntities = NumEntities(); - for ( i = 0; i < nEntities; i++ ) - { - pTable = GetEntityInfo( i ); - if ( pTable->hEnt == pEntity ) - return pTable->id; - } - } - } -#endif - return -1; - } - - saverestorelevelinfo_t levelInfo; - Vector modelSpaceOffset; // used only for globaly entity brushes modelled in different coordinate systems. - -private: - int tableCount; // Number of elements in the entity table - entitytable_t *pTable; // Array of entitytable_t elements (1 for each entity) - CBaseEntity *m_pCurrentEntity; // only valid during the save functions of this entity, NULL otherwise - - - struct CHashElement - { - const CBaseEntity *pEntity; - int index; - - CHashElement( const CBaseEntity *pEntity, int index) : pEntity(pEntity), index(index) {} - CHashElement( const CBaseEntity *pEntity ) : pEntity(pEntity) {} - CHashElement() {} - }; - - class CHashFuncs - { - public: - CHashFuncs( int ) {} - - // COMPARE - bool operator()( const CHashElement &lhs, const CHashElement &rhs ) const - { - return lhs.pEntity == rhs.pEntity; - } - - // HASH - unsigned int operator()( const CHashElement &item ) const - { - return HashItem( item.pEntity ); - } - }; - - typedef CUtlHash CEntityToIndexHash; - - CEntityToIndexHash m_EntityToIndex; -}; - -//----------------------------------------------------------------------------- - - -class CSaveRestoreData : public CSaveRestoreSegment, - public CGameSaveRestoreInfo -{ -public: - CSaveRestoreData() : bAsync( false ) {} - - - bool bAsync; -}; - -inline CSaveRestoreData *MakeSaveRestoreData( void *pMemory ) -{ - return new (pMemory) CSaveRestoreData; -} - -//----------------------------------------------------------------------------- -// -// class CSaveRestoreSegment, inline functions -// - -inline CSaveRestoreSegment::CSaveRestoreSegment() -{ - memset( this, 0, sizeof(*this) ); -} - -inline void CSaveRestoreSegment::Init( void *pNewBase, int nBytes ) -{ - pCurrentData = pBaseData = (char *)pNewBase; - size = 0; - bufferSize = nBytes; -} - -inline void CSaveRestoreSegment::MoveCurPos( int nBytes ) -{ - pCurrentData += nBytes; - size += nBytes; -} - -inline void CSaveRestoreSegment::Rebase() -{ - pBaseData = pCurrentData; - bufferSize -= size; - size = 0; -} - -inline void CSaveRestoreSegment::Rewind( int nBytes ) -{ - if ( size < nBytes ) - nBytes = size; - - MoveCurPos( -nBytes ); -} - -inline char *CSaveRestoreSegment::GetBuffer() -{ - return pBaseData; -} - -inline int CSaveRestoreSegment::BytesAvailable() const -{ - return (bufferSize - size); -} - -inline int CSaveRestoreSegment::SizeBuffer() const -{ - return bufferSize; -} - -inline bool CSaveRestoreSegment::Write( const void *pData, int nBytes ) -{ - if ( nBytes > BytesAvailable() ) - { - size = bufferSize; - return false; - } - - memcpy( pCurrentData, pData, nBytes ); - MoveCurPos( nBytes ); - - return true; -} - -inline bool CSaveRestoreSegment::Read( void *pOutput, int nBytes ) -{ - if ( !BytesAvailable() ) - return false; - - if ( nBytes > BytesAvailable() ) - { - size = bufferSize; - return false; - } - - if ( pOutput ) - memcpy( pOutput, pCurrentData, nBytes ); - MoveCurPos( nBytes ); - return true; -} - -inline int CSaveRestoreSegment::GetCurPos() -{ - return size; -} - -inline char *CSaveRestoreSegment::AccessCurPos() -{ - return pCurrentData; -} - -inline bool CSaveRestoreSegment::Seek( int absPosition ) -{ - if ( absPosition < 0 || absPosition >= bufferSize ) - return false; - - size = absPosition; - pCurrentData = pBaseData + size; - return true; -} - -inline void CSaveRestoreSegment::InitSymbolTable( char **pNewTokens, int sizeTable) -{ - Assert( !pTokens ); - tokenCount = sizeTable; - pTokens = pNewTokens; - memset( pTokens, 0, sizeTable * sizeof( pTokens[0]) ); -} - -inline char **CSaveRestoreSegment::DetachSymbolTable() -{ - char **pResult = pTokens; - tokenCount = 0; - pTokens = NULL; - return pResult; -} - -inline int CSaveRestoreSegment::SizeSymbolTable() -{ - return tokenCount; -} - -inline bool CSaveRestoreSegment::DefineSymbol( const char *pszToken, int token ) -{ - if ( pTokens[token] == NULL ) - { - pTokens[token] = (char *)pszToken; - return true; - } - Assert( 0 ); - return false; -} - -inline unsigned short CSaveRestoreSegment::FindCreateSymbol( const char *pszToken ) -{ - unsigned short hash = (unsigned short)(HashString( pszToken ) % (unsigned)tokenCount ); - -#if _DEBUG - static int tokensparsed = 0; - tokensparsed++; - if ( !tokenCount || !pTokens ) - { - AssertMsg( 0, ("No token table array in TokenHash()!") ); - } -#endif - - for ( int i=0; i 50 && !beentheredonethat ) - { - beentheredonethat = true; - AssertMsg( 0, ("CSaveRestoreBuffer::TokenHash() is getting too full!" ) ); - } -#endif - - int index = hash + i; - if ( index >= tokenCount ) - index -= tokenCount; - - if ( !pTokens[index] || strcmp( pszToken, pTokens[index] ) == 0 ) - { - pTokens[index] = (char *)pszToken; - return index; - } - } - - // Token hash table full!!! - // [Consider doing overflow table(s) after the main table & limiting linear hash table search] - Warning( "CSaveRestoreBuffer::TokenHash() is COMPLETELY FULL!" ); - Assert( 0 ); - return 0; -} - -inline const char *CSaveRestoreSegment::StringFromSymbol( int token ) -{ - if ( token >= 0 && token < tokenCount ) - return pTokens[token]; - Assert( 0 ); - return "<>"; -} - -#ifndef _WIN32 -inline unsigned CSaveRestoreSegment::_rotr ( unsigned val, int shift) -{ - register unsigned lobit; /* non-zero means lo bit set */ - register unsigned num = val; /* number to rotate */ - - shift &= 0x1f; /* modulo 32 -- this will also make - negative shifts work */ - - while (shift--) - { - lobit = num & 1; /* get high bit */ - num >>= 1; /* shift right one bit */ - if (lobit) - num |= 0x80000000; /* set hi bit if lo bit was set */ - } - - return num; -} -#endif - -inline unsigned int CSaveRestoreSegment::HashString( const char *pszToken ) -{ - unsigned int hash = 0; - - while ( *pszToken ) - hash = _rotr( hash, 4 ) ^ *pszToken++; - - return hash; -} - -//============================================================================= - -#endif // SAVERESTORETYPES_H diff --git a/public/scenefilecache/ISceneFileCache.h b/public/scenefilecache/ISceneFileCache.h deleted file mode 100644 index 1ea4bd496..000000000 --- a/public/scenefilecache/ISceneFileCache.h +++ /dev/null @@ -1,43 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef ISCENEFILECACHE_H -#define ISCENEFILECACHE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "interface.h" -#include "appframework/IAppSystem.h" - -// the file cache can support persisting some calcs -struct SceneCachedData_t -{ - unsigned int msecs; - int numSounds; - int sceneId; -}; - -class ISceneFileCache : public IAppSystem -{ -public: - - // async implemenation - virtual size_t GetSceneBufferSize( char const *filename ) = 0; - virtual bool GetSceneData( char const *filename, byte *buf, size_t bufsize ) = 0; - - // persisted scene data, returns true if valid, false otherwise - virtual bool GetSceneCachedData( char const *pFilename, SceneCachedData_t *pData ) = 0; - virtual short GetSceneCachedSound( int iScene, int iSound ) = 0; - virtual const char *GetSceneString( short stringId ) = 0; - - // Physically reloads image from disk - virtual void Reload() = 0; -}; - -#define SCENE_FILE_CACHE_INTERFACE_VERSION "SceneFileCache002" - -#endif // ISCENEFILECACHE_H diff --git a/public/scenefilecache/SceneImageFile.h b/public/scenefilecache/SceneImageFile.h deleted file mode 100644 index fa4740f81..000000000 --- a/public/scenefilecache/SceneImageFile.h +++ /dev/null @@ -1,58 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: A Scene Image file aggregates all the compiled binary VCD files into -// a single file. -// -//=====================================================================================// -#ifndef SCENE_IMAGE_FILE_H -#define SCENE_IMAGE_FILE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "commonmacros.h" -#include "tier1/checksum_crc.h" - -#define SCENE_IMAGE_ID MAKEID( 'V','S','I','F' ) -#define SCENE_IMAGE_VERSION 2 - -// scene summary: cached calcs for commmon startup queries, variable sized -struct SceneImageSummary_t -{ - unsigned int msecs; - int numSounds; - int soundStrings[1]; // has numSounds -}; - -// stored sorted by crc filename for binary search -struct SceneImageEntry_t -{ - CRC32_t crcFilename; // expected to be normalized as scenes\???.vcd - int nDataOffset; // offset to dword aligned data from start - int nDataLength; - int nSceneSummaryOffset; // offset to summary -}; - -struct SceneImageHeader_t -{ - int nId; - int nVersion; - int nNumScenes; // number of scene files - int nNumStrings; // number of unique strings in table - int nSceneEntryOffset; - - inline const char *String( short iString ) - { - if ( iString < 0 || iString >= nNumStrings ) - { - Assert( 0 ); - return NULL; - } - - // access string table (after header) to access pool - unsigned int *pTable = (unsigned int *)((byte *)this + sizeof( SceneImageHeader_t )); - return (char *)this + pTable[iString]; - } -}; - -#endif // SCENE_IMAGE_FILE_H diff --git a/public/scratchpad3d.cpp b/public/scratchpad3d.cpp deleted file mode 100644 index e12ace5d7..000000000 --- a/public/scratchpad3d.cpp +++ /dev/null @@ -1,639 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include -#include "scratchpad3d.h" -#include "tier0/dbg.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#if defined _LINUX && !defined __stdcall -#define __stdcall -#endif - -#ifndef _LINUX -// NOTE - linux doesn't need any of this code! - -extern "C" -{ - extern void __stdcall Sleep( unsigned long ms ); -}; - - -class CFileRead -{ -public: - CFileRead( IFileSystem* pFileSystem, FileHandle_t fp ) - { - m_pFileSystem = pFileSystem; - m_fp = fp; - m_Pos = 0; - } - - bool Read( void *pDest, int len ) - { - int count = m_pFileSystem->Read( pDest, len, m_fp ); - m_Pos += count; - return count == len; - } - - IFileSystem* m_pFileSystem; - FileHandle_t m_fp; - int m_Pos; -}; - - -// ------------------------------------------------------------------------ // -// CCommand_Point. -// ------------------------------------------------------------------------ // - -void CScratchPad3D::CCommand_Point::Read( CFileRead *pFile ) -{ - pFile->Read( &m_flPointSize, sizeof(m_flPointSize) ); - pFile->Read( &m_Vert, sizeof(m_Vert) ); -} - -void CScratchPad3D::CCommand_Point::Write( IFileSystem* pFileSystem, FileHandle_t fp ) -{ - pFileSystem->Write( &m_flPointSize, sizeof(m_flPointSize), fp ); - pFileSystem->Write( &m_Vert, sizeof(m_Vert), fp ); -} - - -// ------------------------------------------------------------------------ // -// CCommand_Line. -// ------------------------------------------------------------------------ // - -void CScratchPad3D::CCommand_Line::Read( CFileRead *pFile ) -{ - pFile->Read( m_Verts, sizeof(m_Verts) ); -} - -void CScratchPad3D::CCommand_Line::Write( IFileSystem* pFileSystem, FileHandle_t fp ) -{ - pFileSystem->Write( m_Verts, sizeof(m_Verts), fp ); -} - - -// ------------------------------------------------------------------------ // -// CCommand_Polygon. -// ------------------------------------------------------------------------ // - -void CScratchPad3D::CCommand_Polygon::Read( CFileRead *pFile ) -{ - int count; - pFile->Read( &count, sizeof(count) ); - m_Verts.RemoveAll(); - m_Verts.AddMultipleToTail( count ); - - if( count ) - pFile->Read( &m_Verts[0], sizeof(CSPVert)*count ); -} - -void CScratchPad3D::CCommand_Polygon::Write( IFileSystem* pFileSystem, FileHandle_t fp ) -{ - int count = m_Verts.Size(); - pFileSystem->Write( &count, sizeof(count), fp ); - - if( count ) - pFileSystem->Write( &m_Verts[0], sizeof(CSPVert)*count, fp ); -} - - -// ------------------------------------------------------------------------ // -// CCommand_Matrix. -// ------------------------------------------------------------------------ // - -void CScratchPad3D::CCommand_Matrix::Read( CFileRead *pFile ) -{ - pFile->Read( &m_mMatrix, sizeof(m_mMatrix) ); -} - -void CScratchPad3D::CCommand_Matrix::Write( IFileSystem* pFileSystem, FileHandle_t fp ) -{ - pFileSystem->Write( &m_mMatrix, sizeof(m_mMatrix), fp ); -} - - -// ------------------------------------------------------------------------ // -// CCommand_RenderState. -// ------------------------------------------------------------------------ // - -void CScratchPad3D::CCommand_RenderState::Read( CFileRead *pFile ) -{ - pFile->Read( &m_State, sizeof(m_State) ); - pFile->Read( &m_Val, sizeof(m_Val) ); -} - -void CScratchPad3D::CCommand_RenderState::Write( IFileSystem* pFileSystem, FileHandle_t fp ) -{ - pFileSystem->Write( &m_State, sizeof(m_State), fp ); - pFileSystem->Write( &m_Val, sizeof(m_Val), fp ); -} - - -// ------------------------------------------------------------------------ // -// CCommand_Text. -// ------------------------------------------------------------------------ // - -void CScratchPad3D::CCommand_Text::Read( CFileRead *pFile ) -{ - int strLen; - pFile->Read( &strLen, sizeof( strLen ) ); - m_String.SetSize( strLen ); - pFile->Read( m_String.Base(), strLen ); - - pFile->Read( &m_TextParams, sizeof( m_TextParams ) ); -} - - -void CScratchPad3D::CCommand_Text::Write( IFileSystem* pFileSystem, FileHandle_t fp ) -{ - int strLen = m_String.Count(); - pFileSystem->Write( &strLen, sizeof( strLen ), fp ); - pFileSystem->Write( m_String.Base(), strLen, fp ); - - pFileSystem->Write( &m_TextParams, sizeof( m_TextParams ), fp ); -} - - -// ------------------------------------------------------------------------ // -// CScratchPad3D internals. -// ------------------------------------------------------------------------ // - -CScratchPad3D::CScratchPad3D( char const *pFilename, IFileSystem* pFileSystem, bool bAutoClear ) -{ - m_pFileSystem = pFileSystem; - m_pFilename = pFilename; - m_bAutoFlush = true; - - if( bAutoClear ) - Clear(); // Clear whatever is in the file.. -} - -void CScratchPad3D::AutoFlush() -{ - if( m_bAutoFlush ) - Flush(); -} - -void CScratchPad3D::DrawRectGeneric( int iPlane, int otherDim1, int otherDim2, float planeDist, const Vector2D &vMin, const Vector2D &vMax, const CSPColor &vColor ) -{ - Vector verts[4]; - - verts[0][iPlane] = verts[1][iPlane] = verts[2][iPlane] = verts[3][iPlane] = planeDist; - - verts[0][otherDim1] = vMin.x; - verts[0][otherDim2] = vMin.y; - - verts[1][otherDim1] = vMin.x; - verts[1][otherDim2] = vMax.y; - - verts[2][otherDim1] = vMax.x; - verts[2][otherDim2] = vMax.y; - - verts[3][otherDim1] = vMax.x; - verts[3][otherDim2] = vMin.y; - - DrawPolygon( CSPVertList(verts, 4, vColor) ); -} - -void CScratchPad3D::DeleteCommands() -{ - for( int i=0; i < m_Commands.Size(); i++ ) - delete m_Commands[i]; - - m_Commands.RemoveAll(); -} - -bool CScratchPad3D::LoadCommandsFromFile( ) -{ - DeleteCommands(); - - FileHandle_t fp = m_pFileSystem->Open( m_pFilename, "rb" ); - if( !fp ) - return false; - - long fileEndPos = m_pFileSystem->Size( fp ); - - CFileRead fileRead( m_pFileSystem, fp ); - while( fileRead.m_Pos != fileEndPos ) - { - unsigned char iCommand; - fileRead.Read( &iCommand, sizeof(iCommand) ); - - CBaseCommand *pCmd = NULL; - if( iCommand == COMMAND_POINT ) - pCmd = new CCommand_Point; - else if( iCommand == COMMAND_LINE ) - pCmd = new CCommand_Line; - else if( iCommand == COMMAND_POLYGON ) - pCmd = new CCommand_Polygon; - else if( iCommand == COMMAND_MATRIX ) - pCmd = new CCommand_Matrix; - else if( iCommand == COMMAND_RENDERSTATE ) - pCmd = new CCommand_RenderState; - else if ( iCommand == COMMAND_TEXT ) - pCmd = new CCommand_Text; - - if( !pCmd ) - { - Assert( !"LoadCommandsFromFile: invalid file" ); - m_pFileSystem->Close( fp ); - return false; - } - - pCmd->Read( &fileRead ); - m_Commands.AddToTail( pCmd ); - } - - m_pFileSystem->Close( fp ); - return true; -} - - -// ------------------------------------------------------------------------ // -// CScratchPad3D's IScratchPad3D implementation. -// ------------------------------------------------------------------------ // - -void CScratchPad3D::Release() -{ - Flush(); - delete this; -} - -void CScratchPad3D::SetMapping( - const Vector &vInputMin, - const Vector &vInputMax, - const Vector &vOutputMin, - const Vector &vOutputMax ) -{ - CCommand_Matrix *cmd = new CCommand_Matrix; - m_Commands.AddToTail( cmd ); - - Vector vDivisor(1,1,1); - for( int i=0; i < 3; i++ ) - vDivisor[i] = fabs(vInputMax[i] - vInputMin[i]) < 0.0001f ? 0.001f : (vInputMax[i] - vInputMin[i]); - - Vector vScale = (vOutputMax - vOutputMin) / vDivisor; - Vector vShift = -vInputMin * vScale + vOutputMin; - - cmd->m_mMatrix.Init( - vScale.x, 0, 0, vShift.x, - 0, vScale.y, 0, vShift.y, - 0, 0, vScale.z, vShift.z, - 0, 0, 0, 1 ); - - - AutoFlush(); -} - -bool CScratchPad3D::GetAutoFlush() -{ - return m_bAutoFlush; -} - -void CScratchPad3D::SetAutoFlush( bool bAutoFlush ) -{ - m_bAutoFlush = bAutoFlush; - if( m_bAutoFlush ) - Flush(); -} - -void CScratchPad3D::DrawPoint( CSPVert const &v, float flPointSize ) -{ - CCommand_Point *cmd = new CCommand_Point; - m_Commands.AddToTail( cmd ); - - cmd->m_Vert = v; - cmd->m_flPointSize = flPointSize; - - AutoFlush(); -} - -void CScratchPad3D::DrawLine( CSPVert const &v1, CSPVert const &v2 ) -{ - CCommand_Line *cmd = new CCommand_Line; - m_Commands.AddToTail( cmd ); - - cmd->m_Verts[0] = v1; - cmd->m_Verts[1] = v2; - - AutoFlush(); -} - -void CScratchPad3D::DrawPolygon( CSPVertList const &verts ) -{ - CCommand_Polygon *cmd = new CCommand_Polygon; - m_Commands.AddToTail( cmd ); - - cmd->m_Verts.AddVectorToTail( verts.m_Verts ); - - AutoFlush(); -} - -void CScratchPad3D::DrawRectYZ( float xPos, const Vector2D &vMin, const Vector2D &vMax, const CSPColor &vColor ) -{ - DrawRectGeneric( 0, 1, 2, xPos, vMin, vMax, vColor ); -} - -void CScratchPad3D::DrawRectXZ( float yPos, const Vector2D &vMin, const Vector2D &vMax, const CSPColor &vColor ) -{ - DrawRectGeneric( 1, 0, 2, yPos, vMin, vMax, vColor ); -} - -void CScratchPad3D::DrawRectXY( float zPos, const Vector2D &vMin, const Vector2D &vMax, const CSPColor &vColor ) -{ - DrawRectGeneric( 2, 0, 1, zPos, vMin, vMax, vColor ); -} - -void CScratchPad3D::SetRenderState( RenderState state, unsigned long val ) -{ - CCommand_RenderState *cmd = new CCommand_RenderState; - m_Commands.AddToTail( cmd ); - - cmd->m_State = (unsigned long)state; - cmd->m_Val = val; -} - -void CScratchPad3D::DrawWireframeBox( const Vector &vMin, const Vector &vMax, const Vector &vColor ) -{ - // Bottom 4. - DrawLine( - CSPVert(Vector(vMin.x, vMin.y, vMin.z), vColor), - CSPVert(Vector(vMax.x, vMin.y, vMin.z), vColor) ); - - DrawLine( - CSPVert(Vector(vMin.x, vMin.y, vMin.z), vColor), - CSPVert(Vector(vMin.x, vMax.y, vMin.z), vColor) ); - - DrawLine( - CSPVert(Vector(vMax.x, vMin.y, vMin.z), vColor), - CSPVert(Vector(vMax.x, vMax.y, vMin.z), vColor) ); - - DrawLine( - CSPVert(Vector(vMax.x, vMax.y, vMin.z), vColor), - CSPVert(Vector(vMin.x, vMax.y, vMin.z), vColor) ); - - // Top 4. - DrawLine( - CSPVert(Vector(vMin.x, vMin.y, vMax.z), vColor), - CSPVert(Vector(vMax.x, vMin.y, vMax.z), vColor) ); - - DrawLine( - CSPVert(Vector(vMin.x, vMin.y, vMax.z), vColor), - CSPVert(Vector(vMin.x, vMax.y, vMax.z), vColor) ); - - DrawLine( - CSPVert(Vector(vMax.x, vMin.y, vMax.z), vColor), - CSPVert(Vector(vMax.x, vMax.y, vMax.z), vColor) ); - - DrawLine( - CSPVert(Vector(vMax.x, vMax.y, vMax.z), vColor), - CSPVert(Vector(vMin.x, vMax.y, vMax.z), vColor) ); - - // Connecting 4. - DrawLine( - CSPVert(Vector(vMin.x, vMin.y, vMin.z), vColor), - CSPVert(Vector(vMin.x, vMin.y, vMax.z), vColor) ); - - DrawLine( - CSPVert(Vector(vMin.x, vMax.y, vMin.z), vColor), - CSPVert(Vector(vMin.x, vMax.y, vMax.z), vColor) ); - - DrawLine( - CSPVert(Vector(vMax.x, vMax.y, vMin.z), vColor), - CSPVert(Vector(vMax.x, vMax.y, vMax.z), vColor) ); - - DrawLine( - CSPVert(Vector(vMax.x, vMin.y, vMin.z), vColor), - CSPVert(Vector(vMax.x, vMin.y, vMax.z), vColor) ); -} - - -void CScratchPad3D::DrawText( const char *pStr, const CTextParams ¶ms ) -{ - CCommand_Text *cmd = new CCommand_Text; - m_Commands.AddToTail( cmd ); - - cmd->m_String.CopyArray( pStr, strlen( pStr ) + 1 ); - cmd->m_TextParams = params; - - AutoFlush(); -} - - -void CScratchPad3D::Clear() -{ - FileHandle_t fp; - - while( ( fp = m_pFileSystem->Open(m_pFilename, "wb") ) == NULL ) - { -#ifdef _WIN32 - Sleep( 5 ); -#elif _LINUX - usleep( 5 ); -#endif - } - - m_pFileSystem->Close( fp ); - - DeleteCommands(); -} - - -void CScratchPad3D::Flush() -{ - FileHandle_t fp; - - while( ( fp = m_pFileSystem->Open(m_pFilename, "ab+") ) == NULL ) - { -#ifdef _WIN32 - Sleep( 5 ); -#elif _LINUX - usleep( 5 ); -#endif - } - - // Append the new commands to the file. - for( int i=0; i < m_Commands.Size(); i++ ) - { - m_pFileSystem->Write( &m_Commands[i]->m_iCommand, sizeof(m_Commands[i]->m_iCommand), fp ); - m_Commands[i]->Write( m_pFileSystem, fp ); - } - - m_pFileSystem->Close( fp ); - - DeleteCommands(); -} - -void CScratchPad3D::DrawImageBW( - unsigned char const *pData, - int width, - int height, - int pitchInBytes, - bool bOutlinePixels, - bool bOutlineImage, - Vector *vCorners ) -{ - SPRGBA *pRGBA = new SPRGBA[width*height]; - for( int y=0; y < height; y++ ) - { - SPRGBA *pDest = &pRGBA[ y * width ]; - unsigned char const *pSrc = &pData[ y * pitchInBytes ]; - for( int x=0; x < width; x++ ) - { - pDest->r = pDest->g = pDest->b = *pSrc; - ++pSrc; - ++pDest; - } - } - - DrawImageRGBA( pRGBA, width, height, width*sizeof(SPRGBA), bOutlinePixels, bOutlineImage, vCorners ); - delete [] pRGBA; -} - - -void CScratchPad3D::DrawPolygonsForPixels( - SPRGBA *pData, - int width, - int height, - int pitchInBytes, - Vector *vCorners ) -{ - // Scan top-down. - Vector vCurLeft = vCorners[1]; - Vector vCurRight = vCorners[2]; - - Vector vLeftInc = (vCorners[0] - vCorners[1]) / height; - Vector vRightInc = (vCorners[3] - vCorners[2]) / height; - - Vector vNextLeft = vCurLeft + vLeftInc; - Vector vNextRight = vCurRight + vRightInc; - - Vector vPolyBox[4]; - Vector &vTopLeft = vPolyBox[0]; - Vector &vTopRight = vPolyBox[1]; - Vector &vBottomRight = vPolyBox[2]; - Vector &vBottomLeft = vPolyBox[3]; - - for( int y=0; y < height; y++ ) - { - vTopLeft = vCurLeft; - vBottomLeft = vNextLeft; - - Vector vTopXInc = (vCurRight - vCurLeft) / width; - Vector vBottomXInc = (vNextRight - vNextLeft) / width; - - vTopRight = vTopLeft + vTopXInc; - vBottomRight = vBottomLeft + vBottomXInc; - - SPRGBA *pSrc = &pData[ y * (pitchInBytes/sizeof(SPRGBA)) ]; - for( int x=0; x < width; x++ ) - { - if ( pData ) - DrawPolygon( CSPVertList( vPolyBox, 4, Vector(pSrc->r/255.1f, pSrc->g/255.1f, pSrc->b/255.1f) ) ); - else - DrawPolygon( CSPVertList( vPolyBox, 4, Vector(1,1,1) ) ); - - ++pSrc; - vTopLeft += vTopXInc; - vTopRight += vTopXInc; - vBottomLeft += vBottomXInc; - vBottomRight += vBottomXInc; - } - - vCurLeft += vLeftInc; - vNextLeft += vLeftInc; - vCurRight += vRightInc; - vNextRight += vRightInc; - } -} - - -void CScratchPad3D::DrawImageRGBA( - SPRGBA *pData, - int width, - int height, - int pitchInBytes, - bool bOutlinePixels, - bool bOutlineImage, - Vector *vCorners ) -{ - Assert( pitchInBytes % sizeof(SPRGBA) == 0 ); - - Vector vDefaultCorners[4]; - if ( !vCorners ) - { - vCorners = vDefaultCorners; - vDefaultCorners[0].Init( -100, -100 ); - vDefaultCorners[1].Init( -100, 100 ); - vDefaultCorners[2].Init( 100, 100 ); - vDefaultCorners[3].Init( 100, -100 ); - } - - // Don't auto-flush while drawing all these primitives. - bool bOldAutoFlush = m_bAutoFlush; - m_bAutoFlush = false; - - // Draw solids. - SetRenderState( IScratchPad3D::RS_FillMode, IScratchPad3D::FillMode_Solid ); - DrawPolygonsForPixels( pData, width, height, pitchInBytes, vCorners ); - - // Draw wireframe. - if ( bOutlinePixels ) - { - SetRenderState( IScratchPad3D::RS_FillMode, IScratchPad3D::FillMode_Wireframe ); - DrawPolygonsForPixels( NULL, width, height, pitchInBytes, vCorners ); - } - - // Draw an outline around the whole image. - if ( bOutlineImage ) - { - SetRenderState( IScratchPad3D::RS_FillMode, IScratchPad3D::FillMode_Wireframe ); - DrawPolygon( CSPVertList( vCorners, 4 ) ); - } - - // Restore the old auto-flush state. - m_bAutoFlush = bOldAutoFlush; - AutoFlush(); -} - - -// ------------------------------------------------------------------------ // -// Global functions. -// ------------------------------------------------------------------------ // -IFileSystem* ScratchPad3D_SetupFileSystem() -{ - // Get a filesystem interface. - CSysModule *pModule = Sys_LoadModule( "filesystem_stdio" ); - if( !pModule ) - return NULL; - - CreateInterfaceFn fn = Sys_GetFactory( pModule ); - IFileSystem *pFileSystem; - if( !fn || (pFileSystem = (IFileSystem *)fn( FILESYSTEM_INTERFACE_VERSION, NULL )) == NULL ) - { - Sys_UnloadModule( pModule ); - return NULL; - } - - return pFileSystem; -} - -IScratchPad3D* ScratchPad3D_Create( char const *pFilename ) -{ - IFileSystem *pFileSystem = ScratchPad3D_SetupFileSystem(); - if( !pFileSystem ) - return NULL; - - CScratchPad3D *pRet = new CScratchPad3D( pFilename, pFileSystem, true ); - return pRet; -} -#endif // _LINUX - diff --git a/public/scratchpad3d.h b/public/scratchpad3d.h deleted file mode 100644 index b49140585..000000000 --- a/public/scratchpad3d.h +++ /dev/null @@ -1,224 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SCRATCHPAD3D_H -#define SCRATCHPAD3D_H -#ifdef _WIN32 -#pragma once -#endif - - -#include -#include "iscratchpad3d.h" -#include "mathlib/vmatrix.h" -#include "filesystem.h" - -class CFileRead; - - -class CScratchPad3D : public IScratchPad3D -{ -// Commands that can go in the file. -public: - - enum - { - COMMAND_POINT=0, - COMMAND_LINE, - COMMAND_POLYGON, - COMMAND_MATRIX, - COMMAND_RENDERSTATE, - COMMAND_TEXT, - COMMAND_NUMCOMMANDS - }; - - class ICachedRenderData - { - public: - virtual void Release() = 0; - }; - - class CBaseCommand - { - public: - CBaseCommand( unsigned char iCommand ) - { - m_iCommand = (unsigned char)iCommand; - m_pCachedRenderData = NULL; - } - - ~CBaseCommand() - { - ReleaseCachedRenderData(); - } - - virtual void Read( CFileRead *pFile ) = 0; - virtual void Write( IFileSystem* pFileSystem, FileHandle_t fp ) = 0; - - // Release cached render data. Usually used for releasing things like textures when - // the app is resizing.. - void ReleaseCachedRenderData() - { - if ( m_pCachedRenderData ) - { - m_pCachedRenderData->Release(); - m_pCachedRenderData = NULL; - } - } - - public: - - unsigned char m_iCommand; // One of the COMMAND_ defines. - - // The renderer can cache data with the commands to speedup the rendering after - // the first time (text uses this big time). - ICachedRenderData *m_pCachedRenderData; - }; - - class CCommand_Point : public CBaseCommand - { - public: - CCommand_Point() : CBaseCommand( COMMAND_POINT ) {} - - virtual void Read( CFileRead *pFile ); - virtual void Write( IFileSystem* pFileSystem, FileHandle_t fp ); - - float m_flPointSize; - CSPVert m_Vert; - }; - - class CCommand_Line : public CBaseCommand - { - public: - CCommand_Line() : CBaseCommand( COMMAND_LINE ) {} - - virtual void Read( CFileRead *pFile ); - virtual void Write( IFileSystem* pFileSystem, FileHandle_t fp ); - - CSPVert m_Verts[2]; - }; - - class CCommand_Polygon : public CBaseCommand - { - public: - CCommand_Polygon() : CBaseCommand( COMMAND_POLYGON ) {} - - virtual void Read( CFileRead *pFile ); - virtual void Write( IFileSystem* pFileSystem, FileHandle_t fp ); - - CUtlVector m_Verts; - }; - - class CCommand_Matrix : public CBaseCommand - { - public: - CCommand_Matrix() : CBaseCommand( COMMAND_MATRIX ) {} - - virtual void Read( CFileRead *pFile ); - virtual void Write( IFileSystem* pFileSystem, FileHandle_t fp ); - - VMatrix m_mMatrix; - }; - - class CCommand_RenderState : public CBaseCommand - { - public: - CCommand_RenderState() : CBaseCommand( COMMAND_RENDERSTATE ) {} - - virtual void Read( CFileRead *pFile ); - virtual void Write( IFileSystem* pFileSystem, FileHandle_t fp ); - - unsigned long m_State; // One of the RS_ enums. - unsigned long m_Val; - }; - - class CCommand_Text : public CBaseCommand - { - public: - CCommand_Text() : CBaseCommand( COMMAND_TEXT ) {} - - virtual void Read( CFileRead *pFile ); - virtual void Write( IFileSystem* pFileSystem, FileHandle_t fp ); - - CUtlVector m_String; // The string to render. - CTextParams m_TextParams; - }; - - -public: - - CScratchPad3D( char const *pFilename, IFileSystem *pFileSystem, bool bAutoClear ); - - void AutoFlush(); - void DrawRectGeneric( int iPlane, int otherDim1, int otherDim2, float planeDist, Vector2D const &vMin, Vector2D const &vMax, CSPColor const &vColor ); - void DeleteCommands(); - - // Load a file... - bool LoadCommandsFromFile( ); - - -public: - - virtual void Release(); - - virtual void SetMapping( - Vector const &vInputMin, - Vector const &vInputMax, - Vector const &vOutputMin, - Vector const &vOutputMax ); - virtual bool GetAutoFlush(); - virtual void SetAutoFlush( bool bAutoFlush ); - virtual void DrawPoint( CSPVert const &v, float flPointSize ); - virtual void DrawLine( CSPVert const &v1, CSPVert const &v2 ); - virtual void DrawPolygon( CSPVertList const &verts ); - virtual void DrawRectYZ( float xPos, Vector2D const &vMin, Vector2D const &vMax, CSPColor const &vColor ); - virtual void DrawRectXZ( float yPos, Vector2D const &vMin, Vector2D const &vMax, CSPColor const &vColor ); - virtual void DrawRectXY( float zPos, Vector2D const &vMin, Vector2D const &vMax, CSPColor const &vColor ); - virtual void DrawWireframeBox( Vector const &vMin, Vector const &vMax, Vector const &vColor ); - virtual void DrawText( const char *pStr, const CTextParams ¶ms ); - virtual void SetRenderState( RenderState state, unsigned long val ); - virtual void Clear(); - virtual void Flush(); - virtual void DrawImageBW( - unsigned char const *pData, - int width, - int height, - int pitchInBytes, - bool bOutlinePixels=true, - bool bOutlineImage=false, - Vector *vCorners=NULL ); - - // Draw an RGBA image. - // Corners are in this order: bottom-left, top-left, top-right, bottom-right. - virtual void DrawImageRGBA( - SPRGBA *pData, - int width, - int height, - int pitchInBytes, - bool bOutlinePixels=true, - bool bOutlineImage=false, - Vector *vCorners=NULL ); - - void DrawPolygonsForPixels( - SPRGBA *pData, - int width, - int height, - int pitchInBytes, - Vector *vCorners ); - -public: - IFileSystem* m_pFileSystem; - char const *m_pFilename; - CUtlVector m_Commands; - bool m_bAutoFlush; -}; - - -IFileSystem* ScratchPad3D_SetupFileSystem(); - - -#endif // SCRATCHPAD3D_H diff --git a/public/sentence.cpp b/public/sentence.cpp deleted file mode 100644 index 2b07167cb..000000000 --- a/public/sentence.cpp +++ /dev/null @@ -1,1764 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#if !defined(_STATIC_LINKED) || defined(_SHARED_LIB) - -#include -#include "commonmacros.h" -#include "basetypes.h" -#include "sentence.h" -#include "utlbuffer.h" -#include -#include "mathlib/vector.h" -#include "mathlib/mathlib.h" -#include -#include "checksum_crc.h" -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Purpose: converts an english string to unicode -//----------------------------------------------------------------------------- -int ConvertANSIToUnicode(const char *ansi, wchar_t *unicode, int unicodeBufferSize); - -#if PHONEME_EDITOR -void CEmphasisSample::SetSelected( bool isSelected ) -{ - selected = isSelected; -} -void CPhonemeTag::SetSelected( bool isSelected ) -{ - m_bSelected = isSelected; -} -bool CPhonemeTag::GetSelected() const -{ - return m_bSelected; -} -void CPhonemeTag::SetStartAndEndBytes( unsigned int start, unsigned int end ) -{ - m_uiStartByte = start; - m_uiEndByte = end; -} -unsigned int CPhonemeTag::GetStartByte() const -{ - return m_uiStartByte; -} -unsigned int CPhonemeTag::GetEndByte() const -{ - return m_uiEndByte; -} -void CWordTag::SetSelected( bool isSelected ) -{ - m_bSelected = isSelected; -} -bool CWordTag::GetSelected() const -{ - return m_bSelected; -} -void CWordTag::SetStartAndEndBytes( unsigned int start, unsigned int end ) -{ - m_uiStartByte = start; - m_uiEndByte = end; -} -unsigned int CWordTag::GetStartByte() const -{ - return m_uiStartByte; -} -unsigned int CWordTag::GetEndByte() const -{ - return m_uiEndByte; -} -#else -// xbox doesn't store this data -void CEmphasisSample::SetSelected( bool isSelected ) {} -void CPhonemeTag::SetSelected( bool isSelected ) {} -bool CPhonemeTag::GetSelected() const { return false; } -void CPhonemeTag::SetStartAndEndBytes( unsigned int start, unsigned int end ) {} -unsigned int CPhonemeTag::GetStartByte() const { return 0; } -unsigned int CPhonemeTag::GetEndByte() const { return 0; } -void CWordTag::SetSelected( bool isSelected ) {} -bool CWordTag::GetSelected() const { return false; } -void CWordTag::SetStartAndEndBytes( unsigned int start, unsigned int end ) {} -unsigned int CWordTag::GetStartByte() const { return 0; } -unsigned int CWordTag::GetEndByte() const { return 0; } -#endif - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CWordTag::CWordTag( void ) -{ - m_pszWord = NULL; - - SetStartAndEndBytes( 0, 0 ); - - m_flStartTime = 0.0f; - m_flEndTime = 0.0f; - - SetSelected( false ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : from - -//----------------------------------------------------------------------------- -CWordTag::CWordTag( const CWordTag& from ) -{ - m_pszWord = NULL; - SetWord( from.m_pszWord ); - - SetStartAndEndBytes( from.GetStartByte(), from.GetEndByte() ); - - m_flStartTime = from.m_flStartTime; - m_flEndTime = from.m_flEndTime; - - SetSelected( from.GetSelected() ); - - for ( int p = 0; p < from.m_Phonemes.Size(); p++ ) - { - CPhonemeTag *newPhoneme = new CPhonemeTag( *from.m_Phonemes[ p ] ); - m_Phonemes.AddToTail( newPhoneme ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *word - -//----------------------------------------------------------------------------- -CWordTag::CWordTag( const char *word ) -{ - SetStartAndEndBytes( 0, 0 ); - - m_flStartTime = 0.0f; - m_flEndTime = 0.0f; - - m_pszWord = NULL; - - SetSelected( false ); - - SetWord( word ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CWordTag::~CWordTag( void ) -{ - delete[] m_pszWord; - - while ( m_Phonemes.Size() > 0 ) - { - delete m_Phonemes[ 0 ]; - m_Phonemes.Remove( 0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *tag - -// Output : int -//----------------------------------------------------------------------------- -int CWordTag::IndexOfPhoneme( CPhonemeTag *tag ) -{ - for ( int i = 0 ; i < m_Phonemes.Size(); i++ ) - { - CPhonemeTag *p = m_Phonemes[ i ]; - if ( p == tag ) - return i; - } - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *word - -//----------------------------------------------------------------------------- -void CWordTag::SetWord( const char *word ) -{ - delete[] m_pszWord; - m_pszWord = NULL; - if ( !word || !word[ 0 ] ) - return; - - int len = strlen( word ) + 1; - m_pszWord = new char[ len ]; - Assert( m_pszWord ); - Q_strncpy( m_pszWord, word, len ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CWordTag::GetWord() const -{ - return m_pszWord ? m_pszWord : ""; -} - - -unsigned int CWordTag::ComputeDataCheckSum() -{ - int i; - int c; - CRC32_t crc; - CRC32_Init( &crc ); - - // Checksum the text - if ( m_pszWord != NULL ) - { - CRC32_ProcessBuffer( &crc, m_pszWord, Q_strlen( m_pszWord ) ); - } - // Checksum phonemes - c = m_Phonemes.Count(); - for ( i = 0; i < c; ++i ) - { - CPhonemeTag *phoneme = m_Phonemes[ i ]; - unsigned int phonemeCheckSum = phoneme->ComputeDataCheckSum(); - CRC32_ProcessBuffer( &crc, &phonemeCheckSum, sizeof( unsigned int ) ); - } - // Checksum timestamps - CRC32_ProcessBuffer( &crc, &m_flStartTime, sizeof( float ) ); - CRC32_ProcessBuffer( &crc, &m_flEndTime, sizeof( float ) ); - - CRC32_Final( &crc ); - - return ( unsigned int )crc; -} - -CBasePhonemeTag::CBasePhonemeTag() -{ - m_flStartTime = 0; - m_flEndTime = 0; - - m_nPhonemeCode = 0; -} - -CBasePhonemeTag::CBasePhonemeTag( const CBasePhonemeTag& from ) -{ - memcpy( this, &from, sizeof(*this) ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CPhonemeTag::CPhonemeTag( void ) -{ - m_szPhoneme = NULL; - - SetStartAndEndBytes( 0, 0 ); - - SetSelected( false ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : from - -//----------------------------------------------------------------------------- -CPhonemeTag::CPhonemeTag( const CPhonemeTag& from ) : - BaseClass( from ) -{ - SetStartAndEndBytes( from.GetStartByte(), from.GetEndByte() ); - - SetSelected( from.GetSelected() ); - - m_szPhoneme = NULL; - SetTag( from.GetTag() ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *phoneme - -//----------------------------------------------------------------------------- -CPhonemeTag::CPhonemeTag( const char *phoneme ) -{ - SetStartAndEndBytes( 0, 0 ); - - SetStartTime( 0.0f ); - SetEndTime( 0.0f ); - - SetSelected( false ); - - SetPhonemeCode( 0 ); - - m_szPhoneme = NULL; - SetTag( phoneme ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CPhonemeTag::~CPhonemeTag( void ) -{ - delete[] m_szPhoneme; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *phoneme - -//----------------------------------------------------------------------------- -void CPhonemeTag::SetTag( const char *phoneme ) -{ - delete m_szPhoneme; - m_szPhoneme = NULL; - if ( !phoneme || !phoneme [ 0 ] ) - return; - - int len = Q_strlen( phoneme ) + 1; - m_szPhoneme = new char[ len ]; - Assert( m_szPhoneme ); - Q_strncpy( m_szPhoneme, phoneme, len ); -} - -char const *CPhonemeTag::GetTag() const -{ - return m_szPhoneme ? m_szPhoneme : ""; -} - - -unsigned int CPhonemeTag::ComputeDataCheckSum() -{ - CRC32_t crc; - CRC32_Init( &crc ); - - // Checksum the text - CRC32_ProcessBuffer( &crc, m_szPhoneme, Q_strlen( m_szPhoneme ) ); - int phonemeCode = GetPhonemeCode(); - CRC32_ProcessBuffer( &crc, &phonemeCode, sizeof( int ) ); - - // Checksum timestamps - float startTime = GetStartTime(); - float endTime = GetEndTime(); - CRC32_ProcessBuffer( &crc, &startTime, sizeof( float ) ); - CRC32_ProcessBuffer( &crc, &endTime, sizeof( float ) ); - - CRC32_Final( &crc ); - - return ( unsigned int )crc; -} - -//----------------------------------------------------------------------------- -// Purpose: Simple language to string and string to language lookup dictionary -//----------------------------------------------------------------------------- -#pragma pack(1) - -struct CCLanguage -{ - int type; - char const *name; - unsigned char r, g, b; // For faceposer, indicator color for this language -}; - -static CCLanguage g_CCLanguageLookup[] = -{ - { CC_ENGLISH, "english", 0, 0, 0 }, - { CC_FRENCH, "french", 150, 0, 0 }, - { CC_GERMAN, "german", 0, 150, 0 }, - { CC_ITALIAN, "italian", 0, 150, 150 }, - { CC_KOREAN, "korean", 150, 0, 150 }, - { CC_SCHINESE, "schinese", 150, 0, 150 }, - { CC_SPANISH, "spanish", 0, 0, 150 }, - { CC_TCHINESE, "tchinese", 150, 0, 150 }, - { CC_JAPANESE, "japanese", 250, 150, 0 }, - { CC_RUSSIAN, "russian", 0, 250, 150 }, - { CC_THAI, "thai", 0 , 150, 250 }, - { CC_PORTUGUESE,"portuguese", 0 , 0, 150 }, -}; - -#pragma pack() - -void CSentence::ColorForLanguage( int language, unsigned char& r, unsigned char& g, unsigned char& b ) -{ - r = g = b = 0; - - if ( language < 0 || language >= CC_NUM_LANGUAGES ) - { - return; - } - - r = g_CCLanguageLookup[ language ].r; - g = g_CCLanguageLookup[ language ].g; - b = g_CCLanguageLookup[ language ].b; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : language - -// Output : char const -//----------------------------------------------------------------------------- -char const *CSentence::NameForLanguage( int language ) -{ - if ( language < 0 || language >= CC_NUM_LANGUAGES ) - return "unknown_language"; - - CCLanguage *entry = &g_CCLanguageLookup[ language ]; - Assert( entry->type == language ); - return entry->name; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *name - -// Output : int -//----------------------------------------------------------------------------- -int CSentence::LanguageForName( char const *name ) -{ - int l; - for ( l = 0; l < CC_NUM_LANGUAGES; l++ ) - { - CCLanguage *entry = &g_CCLanguageLookup[ l ]; - Assert( entry->type == l ); - if ( !stricmp( entry->name, name ) ) - return l; - } - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CSentence::CSentence( void ) -{ -#if PHONEME_EDITOR - m_nResetWordBase = 0; - m_szText = 0; - m_uCheckSum = 0; -#endif - m_bShouldVoiceDuck = false; - m_bStoreCheckSum = false; - m_bIsValid = false; - m_bIsCached = false; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CSentence::~CSentence( void ) -{ - Reset(); -#if PHONEME_EDITOR - delete[] m_szText; -#endif -} - - -void CSentence::ParsePlaintext( CUtlBuffer& buf ) -{ - char token[ 4096 ]; - char text[ 4096 ]; - text[ 0 ] = 0; - while ( 1 ) - { - buf.GetString( token ); - if ( !stricmp( token, "}" ) ) - break; - - Q_strncat( text, token, sizeof( text ), COPY_ALL_CHARACTERS ); - Q_strncat( text, " ", sizeof( text ), COPY_ALL_CHARACTERS ); - } - - SetText( text ); -} - -void CSentence::ParseWords( CUtlBuffer& buf ) -{ - char token[ 4096 ]; - char word[ 256 ]; - float start, end; - - while ( 1 ) - { - buf.GetString( token ); - if ( !stricmp( token, "}" ) ) - break; - - if ( stricmp( token, "WORD" ) ) - break; - - buf.GetString( token ); - Q_strncpy( word, token, sizeof( word ) ); - - buf.GetString( token ); - start = atof( token ); - buf.GetString( token ); - end = atof( token ); - - CWordTag *wt = new CWordTag( word ); - assert( wt ); - wt->m_flStartTime = start; - wt->m_flEndTime = end; - - AddWordTag( wt ); - - buf.GetString( token ); - if ( stricmp( token, "{" ) ) - break; - - while ( 1 ) - { - buf.GetString( token ); - if ( !stricmp( token, "}" ) ) - break; - - // Parse phoneme - int code; - char phonemename[ 256 ]; - float start, end; - float volume; - - code = atoi( token ); - - buf.GetString( token ); - Q_strncpy( phonemename, token, sizeof( phonemename ) ); - buf.GetString( token ); - start = atof( token ); - buf.GetString( token ); - end = atof( token ); - buf.GetString( token ); - volume = atof( token ); - - CPhonemeTag *pt = new CPhonemeTag(); - assert( pt ); - pt->SetPhonemeCode( code ); - pt->SetTag( phonemename ); - pt->SetStartTime( start ); - pt->SetEndTime( end ); - - AddPhonemeTag( wt, pt ); - } - } -} - -void CSentence::ParseEmphasis( CUtlBuffer& buf ) -{ - char token[ 4096 ]; - while ( 1 ) - { - buf.GetString( token ); - if ( !stricmp( token, "}" ) ) - break; - - char t[ 256 ]; - Q_strncpy( t, token, sizeof( t ) ); - buf.GetString( token ); - - char value[ 256 ]; - Q_strncpy( value, token, sizeof( value ) ); - - CEmphasisSample sample; - sample.SetSelected( false ); - sample.time = atof( t ); - sample.value = atof( value ); - - - m_EmphasisSamples.AddToTail( sample ); - - } -} - -// This is obsolete, so it doesn't do anything with the data which is parsed. -void CSentence::ParseCloseCaption( CUtlBuffer& buf ) -{ - char token[ 4096 ]; - while ( 1 ) - { - // Format is - // language_name - // { - // PHRASE char streamlength "streambytes" starttime endtime - // PHRASE unicode streamlength "streambytes" starttime endtime - // } - buf.GetString( token ); - if ( !stricmp( token, "}" ) ) - break; - - buf.GetString( token ); - if ( stricmp( token, "{" ) ) - break; - - buf.GetString( token ); - while ( 1 ) - { - if ( !stricmp( token, "}" ) ) - break; - - if ( stricmp( token, "PHRASE" ) ) - break; - - char cc_type[32]; - char cc_stream[ 4096 ]; - int cc_length; - - memset( cc_stream, 0, sizeof( cc_stream ) ); - - buf.GetString( token ); - Q_strncpy( cc_type, token, sizeof( cc_type ) ); - - bool unicode = false; - if ( !stricmp( cc_type, "unicode" ) ) - { - unicode = true; - } - else if ( stricmp( cc_type, "char" ) ) - { - Assert( 0 ); - } - - buf.GetString( token ); - cc_length = atoi( token ); - Assert( cc_length >= 0 && cc_length < sizeof( cc_stream ) ); - // Skip space - buf.GetChar(); - buf.Get( cc_stream, cc_length ); - cc_stream[ cc_length ] = 0; - - // Skip space - buf.GetChar(); - buf.GetString( token ); - buf.GetString( token ); - - buf.GetString( token ); - } - } -} - -void CSentence::ParseOptions( CUtlBuffer& buf ) -{ - char token[ 4096 ]; - while ( 1 ) - { - buf.GetString( token ); - if ( !stricmp( token, "}" ) ) - break; - - if ( Q_strlen( token ) == 0 ) - break; - - char key[ 256 ]; - Q_strncpy( key, token, sizeof( key ) ); - char value[ 256 ]; - buf.GetString( token ); - Q_strncpy( value, token, sizeof( value ) ); - - if ( !strcmpi( key, "voice_duck" ) ) - { - SetVoiceDuck( atoi(value) ? true : false ); - } - else if ( !strcmpi( key, "checksum" ) ) - { - SetDataCheckSum( (unsigned int)atoi( value ) ); - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: VERSION 1.0 parser, need to implement new ones if -// file format changes!!! -// Input : buf - -//----------------------------------------------------------------------------- -void CSentence::ParseDataVersionOnePointZero( CUtlBuffer& buf ) -{ - char token[ 4096 ]; - - while ( 1 ) - { - buf.GetString( token ); - if ( strlen( token ) <= 0 ) - break; - - char section[ 256 ]; - Q_strncpy( section, token, sizeof( section ) ); - - buf.GetString( token ); - if ( stricmp( token, "{" ) ) - break; - - if ( !stricmp( section, "PLAINTEXT" ) ) - { - ParsePlaintext( buf ); - } - else if ( !stricmp( section, "WORDS" ) ) - { - ParseWords( buf ); - } - else if ( !stricmp( section, "EMPHASIS" ) ) - { - ParseEmphasis( buf ); - } - else if ( !stricmp( section, "CLOSECAPTION" ) ) - { - // NOTE: CLOSECAPTION IS NO LONGER VALID - // This just skips the section of data. - ParseCloseCaption( buf ); - } - else if ( !stricmp( section, "OPTIONS" ) ) - { - ParseOptions( buf ); - } - } -} - -// This is a compressed save of just the data needed to drive phonemes in the engine (no word / sentence text, etc ) -//----------------------------------------------------------------------------- -// Purpose: -// Input : buf - -//----------------------------------------------------------------------------- -void CSentence::CacheSaveToBuffer( CUtlBuffer& buf, int version ) -{ - Assert( !buf.IsText() ); - Assert( m_bIsCached ); - - int i; - unsigned short pcount = GetRuntimePhonemeCount(); - - // header - if ( version == CACHED_SENTENCE_VERSION_ALIGNED ) - { - buf.PutChar( version ); - buf.PutChar( 0 ); - buf.PutChar( 0 ); - buf.PutChar( 0 ); - buf.PutInt( pcount ); - } - else - { - buf.PutChar( version ); - buf.PutShort( pcount ); - } - - // phoneme - if ( version == CACHED_SENTENCE_VERSION_ALIGNED ) - { - for ( i = 0; i < pcount; ++i ) - { - const CBasePhonemeTag *phoneme = GetRuntimePhoneme( i ); - Assert( phoneme ); - buf.PutInt( phoneme->GetPhonemeCode() ); - buf.PutFloat( phoneme->GetStartTime() ); - buf.PutFloat( phoneme->GetEndTime() ); - } - } - else - { - for ( i = 0; i < pcount; ++i ) - { - const CBasePhonemeTag *phoneme = GetRuntimePhoneme( i ); - Assert( phoneme ); - buf.PutShort( phoneme->GetPhonemeCode() ); - buf.PutFloat( phoneme->GetStartTime() ); - buf.PutFloat( phoneme->GetEndTime() ); - } - } - - // emphasis samples and voice duck - int c = m_EmphasisSamples.Count(); - Assert( c <= 32767 ); - - if ( version == CACHED_SENTENCE_VERSION_ALIGNED ) - { - buf.PutInt( c ); - for ( i = 0; i < c; i++ ) - { - CEmphasisSample *sample = &m_EmphasisSamples[i]; - Assert( sample ); - buf.PutFloat( sample->time ); - buf.PutFloat( sample->value ); - } - buf.PutInt( GetVoiceDuck() ? 1 : 0 ); - } - else - { - buf.PutShort( c ); - for ( i = 0; i < c; i++ ) - { - CEmphasisSample *sample = &m_EmphasisSamples[i]; - Assert( sample ); - buf.PutFloat( sample->time ); - short scaledValue = clamp( (short)( sample->value * 32767 ), 0, 32767 ); - buf.PutShort( scaledValue ); - } - buf.PutChar( GetVoiceDuck() ? 1 : 0 ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : buf - -//----------------------------------------------------------------------------- -void CSentence::CacheRestoreFromBuffer( CUtlBuffer& buf ) -{ - Assert( !buf.IsText() ); - - Reset(); - - m_bIsCached = true; - - // determine format - int version = buf.GetChar(); - if ( version != CACHED_SENTENCE_VERSION && version != CACHED_SENTENCE_VERSION_ALIGNED ) - { - // Uh oh, version changed... - m_bIsValid = false; - return; - } - - unsigned short pcount; - if ( version == CACHED_SENTENCE_VERSION_ALIGNED ) - { - buf.GetChar(); - buf.GetChar(); - buf.GetChar(); - pcount = buf.GetInt(); - } - else - { - pcount = (unsigned short)buf.GetShort(); - } - - // phonemes - CPhonemeTag pt; - int i; - if ( version == CACHED_SENTENCE_VERSION_ALIGNED ) - { - for ( i = 0; i < pcount; ++i ) - { - int code = buf.GetInt(); - float st = buf.GetFloat(); - float et = buf.GetFloat(); - - pt.SetPhonemeCode( code ); - pt.SetStartTime( st ); - pt.SetEndTime( et ); - AddRuntimePhoneme( &pt ); - } - } - else - { - for ( i = 0; i < pcount; ++i ) - { - unsigned short code = buf.GetShort(); - float st = buf.GetFloat(); - float et = buf.GetFloat(); - - pt.SetPhonemeCode( code ); - pt.SetStartTime( st ); - pt.SetEndTime( et ); - AddRuntimePhoneme( &pt ); - } - } - - // emphasis samples and voice duck - int c; - if ( version == CACHED_SENTENCE_VERSION_ALIGNED ) - { - c = buf.GetInt(); - for ( i = 0; i < c; i++ ) - { - CEmphasisSample sample; - sample.SetSelected( false ); - sample.time = buf.GetFloat(); - sample.value = buf.GetFloat(); - m_EmphasisSamples.AddToTail( sample ); - } - SetVoiceDuck( buf.GetInt() == 0 ? false : true ); - } - else - { - c = buf.GetShort(); - for ( i = 0; i < c; i++ ) - { - CEmphasisSample sample; - sample.SetSelected( false ); - sample.time = buf.GetFloat(); - sample.value = (float)buf.GetShort() / 32767.0f; - m_EmphasisSamples.AddToTail( sample ); - } - SetVoiceDuck( buf.GetChar() == 0 ? false : true ); - } - - m_bIsValid = true; -} - -int CSentence::GetRuntimePhonemeCount() const -{ - return m_RunTimePhonemes.Count(); -} - -const CBasePhonemeTag *CSentence::GetRuntimePhoneme( int i ) const -{ - Assert( m_bIsCached ); - return m_RunTimePhonemes[ i ]; -} - -void CSentence::ClearRuntimePhonemes() -{ - while ( m_RunTimePhonemes.Count() > 0 ) - { - CBasePhonemeTag *tag = m_RunTimePhonemes[ 0 ]; - delete tag; - m_RunTimePhonemes.Remove( 0 ); - } -} - -void CSentence::AddRuntimePhoneme( const CPhonemeTag *src ) -{ - Assert( m_bIsCached ); - - CBasePhonemeTag *tag = new CBasePhonemeTag(); - *tag = *src; - - m_RunTimePhonemes.AddToTail( tag ); -} - -void CSentence::MakeRuntimeOnly() -{ - m_bIsCached = true; -#if PHONEME_EDITOR - delete m_szText; - m_szText = NULL; - - int c = m_Words.Count(); - for ( int i = 0; i < c; ++i ) - { - CWordTag *word = m_Words[ i ]; - Assert( word ); - int pcount = word->m_Phonemes.Count(); - for ( int j = 0; j < pcount; ++j ) - { - CPhonemeTag *phoneme = word->m_Phonemes[ j ]; - assert( phoneme ); - - AddRuntimePhoneme( phoneme ); - } - } - - // Remove all existing words - while ( m_Words.Count() > 0 ) - { - CWordTag *word = m_Words[ 0 ]; - delete word; - m_Words.Remove( 0 ); - } -#endif - m_bIsValid = true; -} - - -void CSentence::SaveToBuffer( CUtlBuffer& buf ) -{ -#if PHONEME_EDITOR - Assert( !m_bIsCached ); - - int i, j; - - buf.Printf( "VERSION 1.0\n" ); - - buf.Printf( "PLAINTEXT\n" ); - buf.Printf( "{\n" ); - buf.Printf( "%s\n", GetText() ); - buf.Printf( "}\n" ); - buf.Printf( "WORDS\n" ); - buf.Printf( "{\n" ); - for ( i = 0; i < m_Words.Size(); i++ ) - { - CWordTag *word = m_Words[ i ]; - Assert( word ); - - buf.Printf( "WORD %s %.3f %.3f\n", - word->GetWord(), - word->m_flStartTime, - word->m_flEndTime ); - - buf.Printf( "{\n" ); - for ( j = 0; j < word->m_Phonemes.Size(); j++ ) - { - CPhonemeTag *phoneme = word->m_Phonemes[ j ]; - Assert( phoneme ); - - buf.Printf( "%i %s %.3f %.3f 1\n", - phoneme->GetPhonemeCode(), - phoneme->GetTag(), - phoneme->GetStartTime(), - phoneme->GetEndTime() ); - } - - buf.Printf( "}\n" ); - } - buf.Printf( "}\n" ); - buf.Printf( "EMPHASIS\n" ); - buf.Printf( "{\n" ); - int c = m_EmphasisSamples.Count(); - for ( i = 0; i < c; i++ ) - { - CEmphasisSample *sample = &m_EmphasisSamples[ i ]; - Assert( sample ); - - buf.Printf( "%f %f\n", sample->time, sample->value ); - } - - buf.Printf( "}\n" ); - buf.Printf( "OPTIONS\n" ); - buf.Printf( "{\n" ); - buf.Printf( "voice_duck %d\n", GetVoiceDuck() ? 1 : 0 ); - if ( m_bStoreCheckSum ) - { - buf.Printf( "checksum %d\n", m_uCheckSum ); - } - buf.Printf( "}\n" ); -#else - Assert( 0 ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *data - -// size - -//----------------------------------------------------------------------------- -void CSentence::InitFromDataChunk( void *data, int size ) -{ - CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); - buf.EnsureCapacity( size ); - buf.Put( data, size ); - buf.SeekPut( CUtlBuffer::SEEK_HEAD, size ); - - InitFromBuffer( buf ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : buf - -//----------------------------------------------------------------------------- -void CSentence::InitFromBuffer( CUtlBuffer& buf ) -{ - Assert( buf.IsText() ); - - Reset(); - - char token[ 4096 ]; - buf.GetString( token ); - - if ( stricmp( token, "VERSION" ) ) - return; - - buf.GetString( token ); - if ( atof( token ) == 1.0f ) - { - ParseDataVersionOnePointZero( buf ); - m_bIsValid = true; - } - else - { - assert( 0 ); - return; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CSentence::GetWordBase( void ) -{ -#if PHONEME_EDITOR - return m_nResetWordBase; -#else - Assert( 0 ); - return 0; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSentence::ResetToBase( void ) -{ -#if PHONEME_EDITOR - // Delete everything after m_nResetWordBase - while ( m_Words.Size() > m_nResetWordBase ) - { - delete m_Words[ m_Words.Size() - 1 ]; - m_Words.Remove( m_Words.Size() - 1 ); - } -#endif - ClearRuntimePhonemes(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSentence::MarkNewPhraseBase( void ) -{ -#if PHONEME_EDITOR - m_nResetWordBase = MAX( m_Words.Size(), 0 ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSentence::Reset( void ) -{ -#if PHONEME_EDITOR - m_nResetWordBase = 0; - - while ( m_Words.Size() > 0 ) - { - delete m_Words[ 0 ]; - m_Words.Remove( 0 ); - } -#endif - m_EmphasisSamples.RemoveAll(); - - ClearRuntimePhonemes(); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *tag - -//----------------------------------------------------------------------------- -void CSentence::AddPhonemeTag( CWordTag *word, CPhonemeTag *tag ) -{ - word->m_Phonemes.AddToTail( tag ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *tag - -//----------------------------------------------------------------------------- -void CSentence::AddWordTag( CWordTag *tag ) -{ -#if PHONEME_EDITOR - m_Words.AddToTail( tag ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : int -//----------------------------------------------------------------------------- -int CSentence::CountPhonemes( void ) -{ - int c = 0; -#if PHONEME_EDITOR - for( int i = 0; i < m_Words.Size(); i++ ) - { - CWordTag *word = m_Words[ i ]; - c += word->m_Phonemes.Size(); - } -#endif - return c; -} - -//----------------------------------------------------------------------------- -// Purpose: // For legacy loading, try to find a word that contains the time -// Input : time - -// Output : CWordTag -//----------------------------------------------------------------------------- -CWordTag *CSentence::EstimateBestWord( float time ) -{ -#if PHONEME_EDITOR - CWordTag *bestWord = NULL; - - for( int i = 0; i < m_Words.Size(); i++ ) - { - CWordTag *word = m_Words[ i ]; - if ( !word ) - continue; - - if ( word->m_flStartTime <= time && word->m_flEndTime >= time ) - return word; - - if ( time < word->m_flStartTime ) - { - bestWord = word; - } - - if ( time > word->m_flEndTime && bestWord ) - return bestWord; - } - - // return best word if we found one - if ( bestWord ) - { - return bestWord; - } - - // Return last word - if ( m_Words.Size() >= 1 ) - { - return m_Words[ m_Words.Size() - 1 ]; - } -#endif - // Oh well - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *phoneme - -// Output : CWordTag -//----------------------------------------------------------------------------- -CWordTag *CSentence::GetWordForPhoneme( CPhonemeTag *phoneme ) -{ -#if PHONEME_EDITOR - for( int i = 0; i < m_Words.Size(); i++ ) - { - CWordTag *word = m_Words[ i ]; - if ( !word ) - continue; - - for ( int j = 0 ; j < word->m_Phonemes.Size() ; j++ ) - { - CPhonemeTag *p = word->m_Phonemes[ j ]; - if ( p == phoneme ) - { - return word; - } - } - - } -#endif - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: Assignment operator -// Input : src - -// Output : CSentence& -//----------------------------------------------------------------------------- -CSentence& CSentence::operator=( const CSentence& src ) -{ - int i; - - // Clear current stuff - Reset(); - - int c; - -#if PHONEME_EDITOR - // Copy everything - for ( i = 0 ; i < src.m_Words.Size(); i++ ) - { - CWordTag *word = src.m_Words[ i ]; - - CWordTag *newWord = new CWordTag( *word ); - - AddWordTag( newWord ); - } - - SetText( src.GetText() ); - m_nResetWordBase = src.m_nResetWordBase; - - c = src.m_EmphasisSamples.Size(); - for ( i = 0; i < c; i++ ) - { - CEmphasisSample s = src.m_EmphasisSamples[ i ]; - m_EmphasisSamples.AddToTail( s ); - } -#endif - - m_bIsCached = src.m_bIsCached; - - c = src.GetRuntimePhonemeCount(); - for ( i = 0; i < c; i++ ) - { - Assert( m_bIsCached ); - - const CBasePhonemeTag *tag = src.GetRuntimePhoneme( i ); - CPhonemeTag full; - ((CBasePhonemeTag &)(full)) = *tag; - - AddRuntimePhoneme( &full ); - } - - m_bShouldVoiceDuck = src.m_bShouldVoiceDuck; -#if PHONEME_EDITOR - m_bStoreCheckSum = src.m_bStoreCheckSum; - m_uCheckSum = src.m_uCheckSum; -#endif - m_bIsValid = src.m_bIsValid; - - return (*this); -} - -void CSentence::Append( float starttime, const CSentence& src ) -{ -#if PHONEME_EDITOR - int i; - // Combine - for ( i = 0 ; i < src.m_Words.Size(); i++ ) - { - CWordTag *word = src.m_Words[ i ]; - - CWordTag *newWord = new CWordTag( *word ); - - newWord->m_flStartTime += starttime; - newWord->m_flEndTime += starttime; - - // Offset times - int c = newWord->m_Phonemes.Count(); - for ( int i = 0; i < c; ++i ) - { - CPhonemeTag *tag = newWord->m_Phonemes[ i ]; - tag->AddStartTime( starttime ); - tag->AddEndTime( starttime ); - } - - AddWordTag( newWord ); - } - - if ( src.GetText()[ 0 ] ) - { - char fulltext[ 4096 ]; - if ( GetText()[ 0 ] ) - { - Q_snprintf( fulltext, sizeof( fulltext ), "%s %s", GetText(), src.GetText() ); - } - else - { - Q_strncpy( fulltext, src.GetText(), sizeof( fulltext ) ); - } - SetText( fulltext ); - } - - int c = src.m_EmphasisSamples.Size(); - for ( i = 0; i < c; i++ ) - { - CEmphasisSample s = src.m_EmphasisSamples[ i ]; - - s.time += starttime; - - m_EmphasisSamples.AddToTail( s ); - } - - // Or in voice duck settings - m_bShouldVoiceDuck |= src.m_bShouldVoiceDuck; -#else - Assert( 0 ); -#endif -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *text - -//----------------------------------------------------------------------------- -void CSentence::SetText( const char *text ) -{ -#if PHONEME_EDITOR - delete[] m_szText; - m_szText = NULL; - - if ( !text || !text[ 0 ] ) - { - return; - } - - int len = Q_strlen( text ) + 1; - - m_szText = new char[ len ]; - Assert( m_szText ); - Q_strncpy( m_szText, text, len ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -// Output : const char -//----------------------------------------------------------------------------- -const char *CSentence::GetText( void ) const -{ -#if PHONEME_EDITOR - return m_szText ? m_szText : ""; -#else - return ""; -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSentence::SetTextFromWords( void ) -{ -#if PHONEME_EDITOR - char fulltext[ 1024 ]; - fulltext[ 0 ] = 0; - for ( int i = 0 ; i < m_Words.Size(); i++ ) - { - CWordTag *word = m_Words[ i ]; - - Q_strncat( fulltext, word->GetWord(), sizeof( fulltext ), COPY_ALL_CHARACTERS ); - - if ( i != m_Words.Size() ) - { - Q_strncat( fulltext, " ", sizeof( fulltext ), COPY_ALL_CHARACTERS ); - } - } - - SetText( fulltext ); -#endif -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CSentence::Resort( void ) -{ - int c = m_EmphasisSamples.Size(); - for ( int i = 0; i < c; i++ ) - { - for ( int j = i + 1; j < c; j++ ) - { - CEmphasisSample src = m_EmphasisSamples[ i ]; - CEmphasisSample dest = m_EmphasisSamples[ j ]; - - if ( src.time > dest.time ) - { - m_EmphasisSamples[ i ] = dest; - m_EmphasisSamples[ j ] = src; - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : number - -// Output : CEmphasisSample -//----------------------------------------------------------------------------- -CEmphasisSample *CSentence::GetBoundedSample( int number, float endtime ) -{ - // Search for two samples which span time f - static CEmphasisSample nullstart; - nullstart.time = 0.0f; - nullstart.value = 0.5f; - static CEmphasisSample nullend; - nullend.time = endtime; - nullend.value = 0.5f; - - if ( number < 0 ) - { - return &nullstart; - } - else if ( number >= GetNumSamples() ) - { - return &nullend; - } - - return GetSample( number ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : time - -// type - -// Output : float -//----------------------------------------------------------------------------- -float CSentence::GetIntensity( float time, float endtime ) -{ - float zeroValue = 0.5f; - - int c = GetNumSamples(); - - if ( c <= 0 ) - { - return zeroValue; - } - - int i; - for ( i = -1 ; i < c; i++ ) - { - CEmphasisSample *s = GetBoundedSample( i, endtime ); - CEmphasisSample *n = GetBoundedSample( i + 1, endtime ); - if ( !s || !n ) - continue; - - if ( time >= s->time && time <= n->time ) - { - break; - } - } - - int prev = i - 1; - int start = i; - int end = i + 1; - int next = i + 2; - - prev = MAX( -1, prev ); - start = MAX( -1, start ); - end = MIN( end, GetNumSamples() ); - next = MIN( next, GetNumSamples() ); - - CEmphasisSample *esPre = GetBoundedSample( prev, endtime ); - CEmphasisSample *esStart = GetBoundedSample( start, endtime ); - CEmphasisSample *esEnd = GetBoundedSample( end, endtime ); - CEmphasisSample *esNext = GetBoundedSample( next, endtime ); - - float dt = esEnd->time - esStart->time; - dt = clamp( dt, 0.01f, 1.0f ); - - Vector vPre( esPre->time, esPre->value, 0 ); - Vector vStart( esStart->time, esStart->value, 0 ); - Vector vEnd( esEnd->time, esEnd->value, 0 ); - Vector vNext( esNext->time, esNext->value, 0 ); - - float f2 = ( time - esStart->time ) / ( dt ); - f2 = clamp( f2, 0.0f, 1.0f ); - - Vector vOut; - Catmull_Rom_Spline( - vPre, - vStart, - vEnd, - vNext, - f2, - vOut ); - - float retval = clamp( vOut.y, 0.0f, 1.0f ); - return retval; -} - -int CSentence::GetNumSamples( void ) -{ - return m_EmphasisSamples.Count(); -} - -CEmphasisSample *CSentence::GetSample( int index ) -{ - if ( index < 0 || index >= GetNumSamples() ) - return NULL; - - return &m_EmphasisSamples[ index ]; -} - -void CSentence::GetEstimatedTimes( float& start, float &end ) -{ -#if PHONEME_EDITOR - float beststart = 100000.0f; - float bestend = -100000.0f; - - int c = m_Words.Count(); - if ( !c ) - { - start = end = 0.0f; - return; - } - - for ( int i = 0; i< c; i++ ) - { - CWordTag *w = m_Words[ i ]; - Assert( w ); - if ( w->m_flStartTime < beststart ) - { - beststart = w->m_flStartTime; - } - if ( w->m_flEndTime > bestend ) - { - bestend = w->m_flEndTime; - } - } - - if ( beststart == 100000.0f ) - { - Assert( 0 ); - beststart = 0.0f; - } - if ( bestend == -100000.0f ) - { - Assert( 0 ); - bestend = 1.0f; - } - start = beststart; - end = bestend; -#endif -} - -void CSentence::SetDataCheckSum( unsigned int chk ) -{ -#if PHONEME_EDITOR - m_bStoreCheckSum = true; - m_uCheckSum = chk; -#endif -} - -unsigned int CSentence::ComputeDataCheckSum() -{ -#if PHONEME_EDITOR - int i; - int c; - CRC32_t crc; - CRC32_Init( &crc ); - - // Checksum the text - CRC32_ProcessBuffer( &crc, GetText(), Q_strlen( GetText() ) ); - // Checsum words and phonemes - c = m_Words.Count(); - for ( i = 0; i < c; ++i ) - { - CWordTag *word = m_Words[ i ]; - unsigned int wordCheckSum = word->ComputeDataCheckSum(); - CRC32_ProcessBuffer( &crc, &wordCheckSum, sizeof( unsigned int ) ); - } - - // Checksum emphasis data - c = m_EmphasisSamples.Count(); - for ( i = 0; i < c; ++i ) - { - CRC32_ProcessBuffer( &crc, &m_EmphasisSamples[ i ].time, sizeof( float ) ); - CRC32_ProcessBuffer( &crc, &m_EmphasisSamples[ i ].value, sizeof( float ) ); - } - - CRC32_Final( &crc ); - - return ( unsigned int )crc; -#else - Assert( 0 ); - return 0; -#endif -} - -unsigned int CSentence::GetDataCheckSum() const -{ -#if PHONEME_EDITOR - Assert( m_bStoreCheckSum ); - Assert( m_uCheckSum != 0 ); - return m_uCheckSum; -#else - Assert( 0 ); - return 0; -#endif -} - -#define STARTEND_TIMEGAP 0.1 - -int CSentence::CountWords( char const *str ) -{ - if ( !str || !str[ 0 ] ) - return 0; - - int c = 1; - - unsigned char *p = (unsigned char *)str; - while ( *p ) - { - if ( *p <= 32 ) - { - c++; - - while ( *p && *p <= 32 ) - { - p++; - } - } - - if ( !(*p) ) - break; - - p++; - } - - return c; -} - - -//----------------------------------------------------------------------------- -// Purpose: Static method -// Input : in - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CSentence::ShouldSplitWord( char in ) -{ - if ( in <= 32 ) - return true; - - if ( in >= 128 ) - return true; - - if ( ispunct( in ) ) - { - // don't split on apostrophe - if ( in == '\'' ) - return false; - return true; - } - - return false; -} - -void CSentence::CreateEventWordDistribution( char const *pszText, float flSentenceDuration ) -{ - Assert( pszText ); - if ( !pszText ) - return; - - int wordCount = CountWords( pszText ); - if ( wordCount <= 0 ) - return; - - float wordLength = ( flSentenceDuration - 2 * STARTEND_TIMEGAP) / (float)wordCount; - float wordStart = STARTEND_TIMEGAP; - - Reset(); - - char word[ 256 ]; - unsigned char const *in = (unsigned char *)pszText; - char *out = word; - - while ( *in ) - { - if ( !ShouldSplitWord( *in ) ) - { - *out++ = *in++; - } - else - { - *out = 0; - - // Skip over splitters - while ( *in && ( ShouldSplitWord( *in ) ) ) - { - in++; - } - - if ( strlen( word ) > 0 ) - { - CWordTag *w = new CWordTag(); - Assert( w ); - w->SetWord( word ); - w->m_flStartTime = wordStart; - w->m_flEndTime = wordStart + wordLength; - - AddWordTag( w ); - - wordStart += wordLength; - } - - out = word; - } - } - - *out = 0; - - if ( strlen( word ) > 0 ) - { - CWordTag *w = new CWordTag(); - Assert( w ); - w->SetWord( word ); - w->m_flStartTime = wordStart; - w->m_flEndTime = wordStart + wordLength; - - AddWordTag( w ); - - wordStart += wordLength; - } -} - - -#endif // !_STATIC_LINKED || _SHARED_LIB diff --git a/public/sentence.h b/public/sentence.h deleted file mode 100644 index cea5f2e0f..000000000 --- a/public/sentence.h +++ /dev/null @@ -1,302 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef SENTENCE_H -#define SENTENCE_H -#ifdef _WIN32 -#pragma once -#endif - -// X360 optimizes out the extra memory needed by the editors in these types -#ifndef _X360 -#define PHONEME_EDITOR 1 -#endif - -#include "utlvector.h" - -class CUtlBuffer; - -#define CACHED_SENTENCE_VERSION 1 -#define CACHED_SENTENCE_VERSION_ALIGNED 4 - -//----------------------------------------------------------------------------- -// Purpose: A sample point -//----------------------------------------------------------------------------- -// Can't do this due to backward compat issues -//#ifdef _WIN32 -//#pragma pack (1) -//#endif - -struct CEmphasisSample -{ - float time; - float value; - - void SetSelected( bool isSelected ); -#if PHONEME_EDITOR - // Used by editors only - bool selected; -#endif -}; - -class CBasePhonemeTag -{ -public: - CBasePhonemeTag(); - CBasePhonemeTag( const CBasePhonemeTag& from ); - - CBasePhonemeTag &operator=( const CBasePhonemeTag &from ) { memcpy( this, &from, sizeof(*this) ); return *this; } - - float GetStartTime() const { return m_flStartTime; } - void SetStartTime( float startTime ) { m_flStartTime = startTime; } - void AddStartTime( float startTime ) { m_flStartTime += startTime; } - - float GetEndTime() const { return m_flEndTime; } - void SetEndTime( float endTime ) { m_flEndTime = endTime; } - void AddEndTime( float startTime ) { m_flEndTime += startTime; } - - int GetPhonemeCode() const { return m_nPhonemeCode; } - void SetPhonemeCode( int phonemeCode ) { m_nPhonemeCode = phonemeCode; } - -private: - float m_flStartTime; - float m_flEndTime; - unsigned short m_nPhonemeCode; -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CPhonemeTag : public CBasePhonemeTag -{ - typedef CBasePhonemeTag BaseClass; -public: - - CPhonemeTag( void ); - CPhonemeTag( const char *phoneme ); - CPhonemeTag( const CPhonemeTag& from ); - ~CPhonemeTag( void ); - - void SetTag( const char *phoneme ); - char const *GetTag() const; - - unsigned int ComputeDataCheckSum(); -#if PHONEME_EDITOR - bool m_bSelected; - unsigned int m_uiStartByte; - unsigned int m_uiEndByte; -#endif - void SetSelected( bool isSelected ); - bool GetSelected() const; - void SetStartAndEndBytes( unsigned int start, unsigned int end ); - unsigned int GetStartByte() const; - unsigned int GetEndByte() const; - -private: - char *m_szPhoneme; - -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class CWordTag -{ -public: - CWordTag( void ); - CWordTag( const char *word ); - CWordTag( const CWordTag& from ); - ~CWordTag( void ); - - void SetWord( const char *word ); - const char *GetWord() const; - - int IndexOfPhoneme( CPhonemeTag *tag ); - - unsigned int ComputeDataCheckSum(); - - float m_flStartTime; - float m_flEndTime; - - CUtlVector < CPhonemeTag *> m_Phonemes; -#if PHONEME_EDITOR - bool m_bSelected; - unsigned int m_uiStartByte; - unsigned int m_uiEndByte; -#endif - void SetSelected( bool isSelected ); - bool GetSelected() const; - void SetStartAndEndBytes( unsigned int start, unsigned int end ); - unsigned int GetStartByte() const; - unsigned int GetEndByte() const; - -private: - char *m_pszWord; -}; - -// A sentence can be closed captioned -// The default case is the entire sentence shown at start time -// -// "The default case" -// "is the entire sentence shown at start time" - -// Commands that aren't closed at end of phrase are automatically terminated -// -// Commands -// The line should persist for 2.0 seconds beyond m_flEndTime -// Don't go to new line for next phrase on stack -// Push current color onto stack and start drawing with new -// color until we reach the next marker or a with no commands which -// means restore the previous color -// Underline text (start/end) -// Italics text (start/end) -// Bold text (start/end) -// Draw caption at special location ??? needed -// Go to new line - -// Close Captioning Support -// The phonemes drive the mouth in english, but the CC text can -// be one of several languages -enum -{ - CC_ENGLISH = 0, - CC_FRENCH, - CC_GERMAN, - CC_ITALIAN, - CC_KOREAN, - CC_SCHINESE, // Simplified Chinese - CC_SPANISH, - CC_TCHINESE, // Traditional Chinese - CC_JAPANESE, - CC_RUSSIAN, - CC_THAI, - CC_PORTUGUESE, - // etc etc - - CC_NUM_LANGUAGES -}; - -//----------------------------------------------------------------------------- -// Purpose: A sentence is a box of words, and words contain phonemes -//----------------------------------------------------------------------------- -class CSentence -{ -public: - static char const *NameForLanguage( int language ); - static int LanguageForName( char const *name ); - static void ColorForLanguage( int language, unsigned char& r, unsigned char& g, unsigned char& b ); - - // Construction - CSentence( void ); - ~CSentence( void ); - - // Assignment operator - CSentence& operator =(const CSentence& src ); - - void Append( float starttime, const CSentence& src ); - - void SetText( const char *text ); - const char *GetText( void ) const; - - void InitFromDataChunk( void *data, int size ); - void InitFromBuffer( CUtlBuffer& buf ); - void SaveToBuffer( CUtlBuffer& buf ); - - // This strips out all of the stuff used by the editor, leaving just one blank work, no sentence text, and just - // the phonemes without the phoneme text...(same as the cacherestore version below) - void MakeRuntimeOnly(); - - // This is a compressed save of just the data needed to drive phonemes in the engine (no word / sentence text, etc ) - void CacheSaveToBuffer( CUtlBuffer& buf, int version ); - void CacheRestoreFromBuffer( CUtlBuffer& buf ); - - // Add word/phoneme to sentence - void AddPhonemeTag( CWordTag *word, CPhonemeTag *tag ); - void AddWordTag( CWordTag *tag ); - - void Reset( void ); - - void ResetToBase( void ); - - void MarkNewPhraseBase( void ); - - int GetWordBase( void ); - - int CountPhonemes( void ); - - // For legacy loading, try to find a word that contains the time - CWordTag *EstimateBestWord( float time ); - - CWordTag *GetWordForPhoneme( CPhonemeTag *phoneme ); - - void SetTextFromWords( void ); - - float GetIntensity( float time, float endtime ); - void Resort( void ); - CEmphasisSample *GetBoundedSample( int number, float endtime ); - int GetNumSamples( void ); - CEmphasisSample *GetSample( int index ); - - // Compute start and endtime based on all words - void GetEstimatedTimes( float& start, float &end ); - - void SetVoiceDuck( bool shouldDuck ) { m_bShouldVoiceDuck = shouldDuck; } - bool GetVoiceDuck() const { return m_bShouldVoiceDuck; } - - unsigned int ComputeDataCheckSum(); - - void SetDataCheckSum( unsigned int chk ); - unsigned int GetDataCheckSum() const; - - int GetRuntimePhonemeCount() const; - const CBasePhonemeTag *GetRuntimePhoneme( int i ) const; - void ClearRuntimePhonemes(); - void AddRuntimePhoneme( const CPhonemeTag *src ); - - void CreateEventWordDistribution( char const *pszText, float flSentenceDuration ); - static int CountWords( char const *pszText ); - static bool ShouldSplitWord( char in ); - -public: -#if PHONEME_EDITOR - char *m_szText; - - CUtlVector< CWordTag * > m_Words; -#endif - CUtlVector < CBasePhonemeTag *> m_RunTimePhonemes; - -#if PHONEME_EDITOR - int m_nResetWordBase; -#endif - // Phoneme emphasis data - CUtlVector< CEmphasisSample > m_EmphasisSamples; - -#if PHONEME_EDITOR - unsigned int m_uCheckSum; -#endif - bool m_bIsValid : 8; - bool m_bStoreCheckSum : 8; - bool m_bShouldVoiceDuck : 8; - bool m_bIsCached : 8; - -private: - void ParseDataVersionOnePointZero( CUtlBuffer& buf ); - void ParsePlaintext( CUtlBuffer& buf ); - void ParseWords( CUtlBuffer& buf ); - void ParseEmphasis( CUtlBuffer& buf ); - void ParseOptions( CUtlBuffer& buf ); - void ParseCloseCaption( CUtlBuffer& buf ); - - void ResetCloseCaptionAll( void ); - - friend class PhonemeEditor; -}; - -//#ifdef _WIN32 -//#pragma pack () -//#endif - -#endif // SENTENCE_H diff --git a/public/server_class.cpp b/public/server_class.cpp deleted file mode 100644 index 0d53686fb..000000000 --- a/public/server_class.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include "server_class.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -ServerClass *g_pServerClassHead=0; - - diff --git a/public/server_class.h b/public/server_class.h deleted file mode 100644 index 3869c85d1..000000000 --- a/public/server_class.h +++ /dev/null @@ -1,146 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef SERVER_CLASS_H -#define SERVER_CLASS_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/dbg.h" -#include "dt_send.h" -#include "networkstringtabledefs.h" - - -class ServerClass; -class SendTable; - -extern ServerClass *g_pServerClassHead; - - -class ServerClass -{ -public: - ServerClass( const char *pNetworkName, SendTable *pTable ) - { - m_pNetworkName = pNetworkName; - m_pTable = pTable; - m_InstanceBaselineIndex = INVALID_STRING_INDEX; - // g_pServerClassHead is sorted alphabetically, so find the correct place to insert - if ( !g_pServerClassHead ) - { - g_pServerClassHead = this; - m_pNext = NULL; - } - else - { - ServerClass *p1 = g_pServerClassHead; - ServerClass *p2 = p1->m_pNext; - - // use _stricmp because Q_stricmp isn't hooked up properly yet - if ( _stricmp( p1->GetName(), pNetworkName ) > 0) - { - m_pNext = g_pServerClassHead; - g_pServerClassHead = this; - p1 = NULL; - } - - while( p1 ) - { - if ( p2 == NULL || _stricmp( p2->GetName(), pNetworkName ) > 0) - { - m_pNext = p2; - p1->m_pNext = this; - break; - } - p1 = p2; - p2 = p2->m_pNext; - } - } - } - - const char* GetName() { return m_pNetworkName; } - - -public: - const char *m_pNetworkName; - SendTable *m_pTable; - ServerClass *m_pNext; - int m_ClassID; // Managed by the engine. - - // This is an index into the network string table (sv.GetInstanceBaselineTable()). - int m_InstanceBaselineIndex; // INVALID_STRING_INDEX if not initialized yet. -}; - - -class CBaseNetworkable; - -// If you do a DECLARE_SERVERCLASS, you need to do this inside the class definition. -#define DECLARE_SERVERCLASS() \ - public: \ - virtual ServerClass* GetServerClass(); \ - static SendTable *m_pClassSendTable; \ - template friend int ServerClassInit(T *); \ - virtual int YouForgotToImplementOrDeclareServerClass(); \ - -#define DECLARE_SERVERCLASS_NOBASE() \ - public: \ - template friend int ServerClassInit(T *); \ - -// Use this macro to expose your class's data across the network. -#define IMPLEMENT_SERVERCLASS( DLLClassName, sendTable ) \ - IMPLEMENT_SERVERCLASS_INTERNAL( DLLClassName, sendTable ) - -// You can use this instead of BEGIN_SEND_TABLE and it will do a DECLARE_SERVERCLASS automatically. -#define IMPLEMENT_SERVERCLASS_ST(DLLClassName, sendTable) \ - IMPLEMENT_SERVERCLASS_INTERNAL( DLLClassName, sendTable )\ - BEGIN_SEND_TABLE(DLLClassName, sendTable) - -#define IMPLEMENT_SERVERCLASS_ST_NOBASE(DLLClassName, sendTable) \ - IMPLEMENT_SERVERCLASS_INTERNAL( DLLClassName, sendTable )\ - BEGIN_SEND_TABLE_NOBASE( DLLClassName, sendTable ) - - -#ifdef VALIDATE_DECLARE_CLASS - #define CHECK_DECLARE_CLASS( DLLClassName, sendTable ) \ - template int CheckDeclareClass_Access(T *); \ - template <> int CheckDeclareClass_Access(sendTable::ignored *, const char *pIgnored) \ - { \ - return DLLClassName::CheckDeclareClass( #DLLClassName ); \ - } \ - namespace sendTable \ - { \ - int verifyDeclareClass = CheckDeclareClass_Access( (sendTable::ignored*)0 ); \ - } -#else - #define CHECK_DECLARE_CLASS( DLLClassName, sendTable ) -#endif - - -#define IMPLEMENT_SERVERCLASS_INTERNAL( DLLClassName, sendTable ) \ - namespace sendTable \ - { \ - struct ignored; \ - extern SendTable g_SendTable; \ - } \ - CHECK_DECLARE_CLASS( DLLClassName, sendTable ) \ - static ServerClass g_##DLLClassName##_ClassReg(\ - #DLLClassName, \ - &sendTable::g_SendTable\ - ); \ - \ - ServerClass* DLLClassName::GetServerClass() {return &g_##DLLClassName##_ClassReg;} \ - SendTable *DLLClassName::m_pClassSendTable = &sendTable::g_SendTable;\ - int DLLClassName::YouForgotToImplementOrDeclareServerClass() {return 0;} - - -#endif - - - diff --git a/public/shaderlib/BaseShader.h b/public/shaderlib/BaseShader.h deleted file mode 100644 index 7845ace45..000000000 --- a/public/shaderlib/BaseShader.h +++ /dev/null @@ -1,339 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// This is what all shaders inherit from. -//===========================================================================// - -#ifndef BASESHADER_H -#define BASESHADER_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "materialsystem/IShader.h" -#include "materialsystem/imaterialvar.h" -#include "materialsystem/ishaderapi.h" -#include "materialsystem/imaterialsystemhardwareconfig.h" -#include "shaderlib/BaseShader.h" - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class IMaterialVar; - -//----------------------------------------------------------------------------- -// Standard material vars -//----------------------------------------------------------------------------- -// Note: if you add to these, add to s_StandardParams in CBaseShader.cpp -enum ShaderMaterialVars_t -{ - FLAGS = 0, - FLAGS_DEFINED, // mask indicating if the flag was specified - FLAGS2, - FLAGS_DEFINED2, - COLOR, - ALPHA, - BASETEXTURE, - FRAME, - BASETEXTURETRANSFORM, - FLASHLIGHTTEXTURE, - FLASHLIGHTTEXTUREFRAME, - COLOR2, - SRGBTINT, - - NUM_SHADER_MATERIAL_VARS -}; - - -// Alpha belnd mode enums. Moved from basevsshader -enum BlendType_t -{ - // no alpha blending - BT_NONE = 0, - - - - // src * srcAlpha + dst * (1-srcAlpha) - // two passes for HDR: - // pass 1: - // color: src * srcAlpha + dst * (1-srcAlpha) - // alpha: srcAlpha * zero + dstAlpha * (1-srcAlpha) - // pass 2: - // color: none - // alpha: srcAlpha * one + dstAlpha * one - // - BT_BLEND, - - - - // src * one + dst * one - // one pass for HDR - BT_ADD, - - - - // Why do we ever use this instead of using premultiplied alpha? - // src * srcAlpha + dst * one - // two passes for HDR - // pass 1: - // color: src * srcAlpha + dst * one - // alpha: srcAlpha * one + dstAlpha * one - // pass 2: - // color: none - // alpha: srcAlpha * one + dstAlpha * one - BT_BLENDADD -}; - - -//----------------------------------------------------------------------------- -// Base class for shaders, contains helper methods. -//----------------------------------------------------------------------------- -class CBaseShader : public IShader -{ -public: - // constructor - CBaseShader(); - - // Methods inherited from IShader - virtual char const* GetFallbackShader( IMaterialVar** params ) const { return 0; } - virtual int GetNumParams( ) const; - virtual char const* GetParamName( int paramIndex ) const; - virtual char const* GetParamHelp( int paramIndex ) const; - virtual ShaderParamType_t GetParamType( int paramIndex ) const; - virtual char const* GetParamDefault( int paramIndex ) const; - virtual int GetParamFlags( int nParamIndex ) const; - - virtual void InitShaderParams( IMaterialVar** ppParams, const char *pMaterialName ); - virtual void InitShaderInstance( IMaterialVar** ppParams, IShaderInit *pShaderInit, const char *pMaterialName, const char *pTextureGroupName ); - virtual void DrawElements( IMaterialVar **params, int nModulationFlags, IShaderShadow* pShaderShadow, IShaderDynamicAPI* pShaderAPI, - VertexCompressionType_t vertexCompression, CBasePerMaterialContextData **pContext ); - - virtual const SoftwareVertexShader_t GetSoftwareVertexShader() const { return m_SoftwareVertexShader; } - - virtual int ComputeModulationFlags( IMaterialVar** params, IShaderDynamicAPI* pShaderAPI ); - virtual bool NeedsPowerOfTwoFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame = true ) const; - virtual bool NeedsFullFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame = true ) const; - virtual bool IsTranslucent( IMaterialVar **params ) const; - -public: - // These functions must be implemented by the shader - virtual void OnInitShaderParams( IMaterialVar** ppParams, const char *pMaterialName ) {} - virtual void OnInitShaderInstance( IMaterialVar** ppParams, IShaderInit *pShaderInit, const char *pMaterialName ) = 0; - virtual void OnDrawElements( IMaterialVar **params, IShaderShadow* pShaderShadow, IShaderDynamicAPI* pShaderAPI, VertexCompressionType_t vertexCompression, CBasePerMaterialContextData **pContextDataPtr ) = 0; - - // Sets the default shadow state - void SetInitialShadowState( ); - - // Draws a snapshot - void Draw( bool bMakeActualDrawCall = true ); - - // Are we currently taking a snapshot? - bool IsSnapshotting() const; - - // Gets at the current materialvar flags - int CurrentMaterialVarFlags() const; - - // Finds a particular parameter (works because the lowest parameters match the shader) - int FindParamIndex( const char *pName ) const; - - // Are we using graphics? - bool IsUsingGraphics(); - - // Are we using editor materials? - bool CanUseEditorMaterials(); - - // Gets the builder... - CMeshBuilder* MeshBuilder(); - - // Loads a texture - void LoadTexture( int nTextureVar ); - - // Loads a bumpmap - void LoadBumpMap( int nTextureVar ); - - // Loads a cubemap - void LoadCubeMap( int nTextureVar ); - - // get the shaderapi handle for a texture. BE CAREFUL WITH THIS. - ShaderAPITextureHandle_t GetShaderAPITextureBindHandle( int nTextureVar, int nFrameVar, int nTextureChannel = 0 ); - - - // Binds a texture - void BindTexture( Sampler_t sampler1, Sampler_t sampler2, int nTextureVar, int nFrameVar = -1 ); - void BindTexture( Sampler_t sampler1, int nTextureVar, int nFrameVar = -1 ); - void BindTexture( Sampler_t sampler1, ITexture *pTexture, int nFrame = 0 ); - void BindTexture( Sampler_t sampler1, Sampler_t sampler2, ITexture *pTexture, int nFrame = 0 ); - - // Is the texture translucent? - bool TextureIsTranslucent( int textureVar, bool isBaseTexture ); - - // Returns the translucency... - float GetAlpha( IMaterialVar** params = NULL ); - - // Is the color var white? - bool IsWhite( int colorVar ); - - // Helper methods for fog - void FogToOOOverbright( void ); - void FogToWhite( void ); - void FogToBlack( void ); - void FogToGrey( void ); - void FogToFogColor( void ); - void DisableFog( void ); - void DefaultFog( void ); - - // Helpers for alpha blending - void EnableAlphaBlending( ShaderBlendFactor_t src, ShaderBlendFactor_t dst ); - void DisableAlphaBlending(); - - void SetBlendingShadowState( BlendType_t nMode ); - - void SetNormalBlendingShadowState( int textureVar = -1, bool isBaseTexture = true ); - void SetAdditiveBlendingShadowState( int textureVar = -1, bool isBaseTexture = true ); - void SetDefaultBlendingShadowState( int textureVar = -1, bool isBaseTexture = true ); - void SingleTextureLightmapBlendMode( ); - - // Helpers for color modulation - void SetColorState( int colorVar, bool setAlpha = false ); - bool IsAlphaModulating(); - bool IsColorModulating(); - void ComputeModulationColor( float* color ); - void SetModulationShadowState( int tintVar = -1 ); - void SetModulationDynamicState( int tintVar = -1 ); - - // Helpers for HDR - bool IsHDREnabled( void ); - - // Loads the identity matrix into the texture - void LoadIdentity( MaterialMatrixMode_t matrixMode ); - - // Loads the camera to world transform - void LoadCameraToWorldTransform( MaterialMatrixMode_t matrixMode ); - void LoadCameraSpaceSphereMapTransform( MaterialMatrixMode_t matrixMode ); - - // Sets a texture translation transform in fixed function - void SetFixedFunctionTextureTranslation( MaterialMatrixMode_t mode, int translationVar ); - void SetFixedFunctionTextureScale( MaterialMatrixMode_t mode, int scaleVar ); - void SetFixedFunctionTextureScaledTransform( MaterialMatrixMode_t textureTransform, int transformVar, int scaleVar ); - void SetFixedFunctionTextureTransform( MaterialMatrixMode_t textureTransform, int transformVar ); - - void CleanupDynamicStateFixedFunction( ); - - // Fixed function Base * detail pass - void FixedFunctionBaseTimesDetailPass( int baseTextureVar, int frameVar, - int baseTextureTransformVar, int detailVar, int detailScaleVar ); - - // Fixed function Self illumination pass - void FixedFunctionSelfIlluminationPass( Sampler_t sampler, - int baseTextureVar, int frameVar, int baseTextureTransformVar, int selfIllumTintVar ); - - // Masked environment map - void FixedFunctionMaskedEnvmapPass( int envMapVar, int envMapMaskVar, - int baseTextureVar, int envMapFrameVar, int envMapMaskFrameVar, - int frameVar, int maskOffsetVar, int maskScaleVar, int tintVar = -1 ); - - // Additive masked environment map - void FixedFunctionAdditiveMaskedEnvmapPass( int envMapVar, int envMapMaskVar, - int baseTextureVar, int envMapFrameVar, int envMapMaskFrameVar, - int frameVar, int maskOffsetVar, int maskScaleVar, int tintVar = -1 ); - - // Modulate by detail texture pass - void FixedFunctionMultiplyByDetailPass( int baseTextureVar, int frameVar, - int textureOffsetVar, int detailVar, int detailScaleVar ); - - // Multiply by lightmap pass - void FixedFunctionMultiplyByLightmapPass( int baseTextureVar, int frameVar, - int baseTextureTransformVar, float alphaOverride = -1 ); - - // Helper methods for environment mapping - int SetShadowEnvMappingState( int envMapMaskVar, int tintVar = -1 ); - void SetDynamicEnvMappingState( int envMapVar, int envMapMaskVar, - int baseTextureVar, int envMapFrameVar, int envMapMaskFrameVar, - int frameVar, int maskOffsetVar, int maskScaleVar, int tintVar = -1 ); - - bool UsingFlashlight( IMaterialVar **params ) const; - bool UsingEditor( IMaterialVar **params ) const; - - void DrawFlashlight_dx70( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, - IShaderShadow* pShaderShadow, - int flashlightTextureVar, int flashlightTextureFrameVar, - bool suppress_lighting = false ); - - void SetFlashlightFixedFunctionTextureTransform( MaterialMatrixMode_t matrix ); - - void GetColorParameter( IMaterialVar** params, float *pColorOut ) const; // return tint color (color*color2) - void ApplyColor2Factor( float *pColorOut ) const; // (*pColorOut) *= COLOR2 - - static IMaterialVar **s_ppParams; - -protected: - SoftwareVertexShader_t m_SoftwareVertexShader; - - static const char *s_pTextureGroupName; // Current material's texture group name. - static IShaderShadow *s_pShaderShadow; - static IShaderDynamicAPI *s_pShaderAPI; - static IShaderInit *s_pShaderInit; - -private: - static int s_nModulationFlags; - static CMeshBuilder *s_pMeshBuilder; -}; - - -//----------------------------------------------------------------------------- -// Gets at the current materialvar flags -//----------------------------------------------------------------------------- -inline int CBaseShader::CurrentMaterialVarFlags() const -{ - return s_ppParams[FLAGS]->GetIntValue(); -} - -//----------------------------------------------------------------------------- -// Are we currently taking a snapshot? -//----------------------------------------------------------------------------- -inline bool CBaseShader::IsSnapshotting() const -{ - return (s_pShaderShadow != NULL); -} - -//----------------------------------------------------------------------------- -// Is the color var white? -//----------------------------------------------------------------------------- -inline bool CBaseShader::IsWhite( int colorVar ) -{ - if (colorVar < 0) - return true; - - if (!s_ppParams[colorVar]->IsDefined()) - return true; - - float color[3]; - s_ppParams[colorVar]->GetVecValue( color, 3 ); - return (color[0] >= 1.0f) && (color[1] >= 1.0f) && (color[2] >= 1.0f); -} - - -class CBasePerMaterialContextData // shaders can keep per material data in classes descended from this -{ - public: - uint32 m_nVarChangeID; - bool m_bMaterialVarsChanged; // set by mat system when material vars change. shader should rehtink and then clear the var - - FORCEINLINE CBasePerMaterialContextData( void ) - { - m_bMaterialVarsChanged = true; - m_nVarChangeID = 0xffffffff; - } - - // virtual destructor so that derived classes can have their own data to be cleaned up on - // delete of material - virtual ~CBasePerMaterialContextData( void ) - { - } -}; - - -#endif // BASESHADER_H diff --git a/public/shaderlib/ShaderDLL.h b/public/shaderlib/ShaderDLL.h deleted file mode 100644 index bb090bfc6..000000000 --- a/public/shaderlib/ShaderDLL.h +++ /dev/null @@ -1,49 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Header: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef SHADERDLL_H -#define SHADERDLL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include - -//----------------------------------------------------------------------------- -// forward declarations -//----------------------------------------------------------------------------- -class IShader; -class ICvar; - -//----------------------------------------------------------------------------- -// The standard implementation of CShaderDLL -//----------------------------------------------------------------------------- -class IShaderDLL -{ -public: - // Adds a shader to the list of shaders - virtual void InsertShader( IShader *pShader ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Singleton interface -//----------------------------------------------------------------------------- -IShaderDLL *GetShaderDLL(); - -//----------------------------------------------------------------------------- -// Singleton interface for CVars -//----------------------------------------------------------------------------- -ICvar *GetCVar(); - - - - - -#endif // SHADERDLL_H diff --git a/public/shaderlib/cshader.h b/public/shaderlib/cshader.h deleted file mode 100644 index 37c53c4fb..000000000 --- a/public/shaderlib/cshader.h +++ /dev/null @@ -1,474 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef CSHADER_H -#define CSHADER_H - -#ifdef _WIN32 -#pragma once -#endif - -// uncomment this if you want to build for nv3x -//#define NV3X 1 - -// This is what all shaders include. -// CBaseShader will become CShader in this file. -#include "materialsystem/ishaderapi.h" -#include "utlvector.h" -#include "materialsystem/imaterialvar.h" -#include "materialsystem/imaterial.h" -#include "BaseShader.h" - -#include "materialsystem/itexture.h" - -// Included for convenience because they are used in a bunch of shaders -#include "materialsystem/imesh.h" -#include "materialsystem/imaterialsystemhardwareconfig.h" -#include "materialsystem/materialsystem_config.h" -#include "shaderlib/ShaderDLL.h" - -// make "local variable is initialized but not referenced" warnings errors for combo checking macros -#pragma warning ( error : 4189 ) - -//----------------------------------------------------------------------------- -// Global interfaces -//----------------------------------------------------------------------------- -extern IMaterialSystemHardwareConfig *g_pHardwareConfig; -extern const MaterialSystem_Config_t *g_pConfig; - - -// Helper method -bool IsUsingGraphics(); - -#define SOFTWARE_VERTEX_SHADER(name) \ - static void SoftwareVertexShader_ ## name( CMeshBuilder &meshBuilder, IMaterialVar **params, IShaderDynamicAPI* pShaderAPI ) - -#define FORWARD_DECLARE_SOFTWARE_VERTEX_SHADER(name)\ - static void SoftwareVertexShader_ ## name( CMeshBuilder &meshBuilder, IMaterialVar **params, IShaderDynamicAPI* pShaderAPI ); - -#define USE_SOFTWARE_VERTEX_SHADER(name) \ - m_SoftwareVertexShader = SoftwareVertexShader_ ## name - -#define SHADER_INIT_PARAMS() \ - virtual void OnInitShaderParams( IMaterialVar **params, const char *pMaterialName ) - -#define SHADER_FALLBACK \ - virtual char const* GetFallbackShader( IMaterialVar** params ) const - -// Typesafe flag setting -inline void CShader_SetFlags( IMaterialVar **params, MaterialVarFlags_t _flag ) -{ - params[FLAGS]->SetIntValue( params[FLAGS]->GetIntValue() | (_flag) ); -} - -inline bool CShader_IsFlagSet( IMaterialVar **params, MaterialVarFlags_t _flag ) -{ - return ((params[FLAGS]->GetIntValue() & (_flag) ) != 0); -} - -#define SET_FLAGS( _flag ) CShader_SetFlags( params, _flag ) -#define CLEAR_FLAGS( _flag ) params[FLAGS]->SetIntValue( params[FLAGS]->GetIntValue() & ~(_flag) ) -#define IS_FLAG_SET( _flag ) CShader_IsFlagSet( params, _flag ) -#define IS_FLAG_DEFINED( _flag ) ((params[FLAGS_DEFINED]->GetIntValue() & (_flag) ) != 0) - -#define IS_PARAM_DEFINED( _param ) ( ( ( _param >= 0 ) && ( params[_param]->IsDefined() ) ) ) - -#define SET_PARAM_STRING_IF_NOT_DEFINED( nParamIndex, kDefaultValue ) \ - if ( ( nParamIndex != -1 ) && ( !params[nParamIndex]->IsDefined() ) ) \ - { \ - params[nParamIndex]->SetStringValue( kDefaultValue ); \ - } - -#define SET_PARAM_FLOAT_IF_NOT_DEFINED( nParamIndex, kDefaultValue ) \ - if ( ( nParamIndex != -1 ) && ( !params[nParamIndex]->IsDefined() ) ) \ - { \ - params[nParamIndex]->SetFloatValue( kDefaultValue ); \ - } - -#define SET_PARAM_VEC_IF_NOT_DEFINED( nParamIndex, kDefaultValue, nSize ) \ - if ( ( nParamIndex != -1 ) && ( !params[nParamIndex]->IsDefined() ) ) \ - { \ - params[nParamIndex]->SetVecValue( kDefaultValue, nSize ); \ - } - -// Typesafe flag setting -inline void CShader_SetFlags2( IMaterialVar **params, MaterialVarFlags2_t _flag ) -{ - params[FLAGS2]->SetIntValue( params[FLAGS2]->GetIntValue() | (_flag) ); -} - -inline bool CShader_IsFlag2Set( IMaterialVar **params, MaterialVarFlags2_t _flag ) -{ - return ((params[FLAGS2]->GetIntValue() & (_flag) ) != 0); -} - -#define SET_FLAGS2( _flag ) CShader_SetFlags2( params, _flag ) -#define CLEAR_FLAGS2( _flag ) params[FLAGS2]->SetIntValue( params[FLAGS2]->GetIntValue() & ~(_flag) ) -#define IS_FLAG2_SET( _flag ) CShader_IsFlag2Set( params, _flag ) -#define IS_FLAG2_DEFINED( _flag ) ((params[FLAGS_DEFINED2]->GetIntValue() & (_flag) ) != 0) - -#define __BEGIN_SHADER_INTERNAL(_baseclass, name, help, flags) \ - namespace name \ - {\ - typedef _baseclass CBaseClass;\ - static const char *s_HelpString = help; \ - static const char *s_Name = #name; \ - static int s_nFlags = flags; \ - class CShaderParam;\ - static CUtlVector s_ShaderParams;\ - static CShaderParam *s_pShaderParamOverrides[NUM_SHADER_MATERIAL_VARS];\ - class CShaderParam\ - {\ - public:\ - CShaderParam( ShaderMaterialVars_t var, ShaderParamType_t type, const char *pDefaultParam, const char *pHelp, int nFlags )\ - {\ - m_Info.m_pName = "override";\ - m_Info.m_Type = type;\ - m_Info.m_pDefaultValue = pDefaultParam;\ - m_Info.m_pHelp = pHelp;\ - m_Info.m_nFlags = nFlags;\ - AssertMsg( !s_pShaderParamOverrides[var], ( "Shader parameter override duplicately defined!" ) );\ - s_pShaderParamOverrides[var] = this;\ - m_Index = var;\ - }\ - CShaderParam( const char *pName, ShaderParamType_t type, const char *pDefaultParam, const char *pHelp, int nFlags )\ - {\ - m_Info.m_pName = pName;\ - m_Info.m_Type = type;\ - m_Info.m_pDefaultValue = pDefaultParam;\ - m_Info.m_pHelp = pHelp;\ - m_Info.m_nFlags = nFlags;\ - m_Index = NUM_SHADER_MATERIAL_VARS + s_ShaderParams.Count();\ - s_ShaderParams.AddToTail( this );\ - }\ - operator int() \ - {\ - return m_Index;\ - }\ - const char *GetName()\ - {\ - return m_Info.m_pName;\ - }\ - ShaderParamType_t GetType()\ - {\ - return m_Info.m_Type;\ - }\ - const char *GetDefault()\ - {\ - return m_Info.m_pDefaultValue;\ - }\ - int GetFlags() const\ - {\ - return m_Info.m_nFlags;\ - }\ - const char *GetHelp()\ - {\ - return m_Info.m_pHelp;\ - }\ - private:\ - ShaderParamInfo_t m_Info; \ - int m_Index;\ - };\ - -#define BEGIN_SHADER(name,help) __BEGIN_SHADER_INTERNAL( CBaseShader, name, help, 0 ) -#define BEGIN_SHADER_FLAGS(name,help,flags) __BEGIN_SHADER_INTERNAL( CBaseShader, name, help, flags ) - -#define BEGIN_SHADER_PARAMS - -#define SHADER_PARAM( param, paramtype, paramdefault, paramhelp ) \ - static CShaderParam param( "$" #param, paramtype, paramdefault, paramhelp, 0 ); - -#define SHADER_PARAM_FLAGS( param, paramtype, paramdefault, paramhelp, flags ) \ - static CShaderParam param( "$" #param, paramtype, paramdefault, paramhelp, flags ); - -#define SHADER_PARAM_OVERRIDE( param, paramtype, paramdefault, paramhelp, flags ) \ - static CShaderParam param( (ShaderMaterialVars_t)param, paramtype, paramdefault, paramhelp, flags ); - -#define END_SHADER_PARAMS \ - class CShader : public CBaseClass\ - {\ - public: - -#define END_SHADER }; \ - static CShader s_ShaderInstance;\ -} // namespace - - -#define SHADER_INIT \ - char const* GetName() const \ - { \ - return s_Name; \ - } \ - int GetFlags() const \ - { \ - return s_nFlags; \ - } \ - int GetNumParams() const \ - {\ - return CBaseClass::GetNumParams() + s_ShaderParams.Count();\ - }\ - char const* GetParamName( int param ) const \ - {\ - int nBaseClassParamCount = CBaseClass::GetNumParams(); \ - if (param < nBaseClassParamCount) \ - return CBaseClass::GetParamName(param); \ - else \ - return s_ShaderParams[param - nBaseClassParamCount]->GetName(); \ - }\ - char const* GetParamHelp( int param ) const \ - {\ - int nBaseClassParamCount = CBaseClass::GetNumParams(); \ - if (param < nBaseClassParamCount) \ - { \ - if ( !s_pShaderParamOverrides[param] ) \ - return CBaseClass::GetParamHelp( param ); \ - else \ - return s_pShaderParamOverrides[param]->GetHelp(); \ - } \ - else \ - return s_ShaderParams[param - nBaseClassParamCount]->GetHelp(); \ - }\ - ShaderParamType_t GetParamType( int param ) const \ - {\ - int nBaseClassParamCount = CBaseClass::GetNumParams(); \ - if (param < nBaseClassParamCount) \ - return CBaseClass::GetParamType( param ); \ - else \ - return s_ShaderParams[param - nBaseClassParamCount]->GetType(); \ - }\ - char const* GetParamDefault( int param ) const \ - {\ - int nBaseClassParamCount = CBaseClass::GetNumParams(); \ - if (param < nBaseClassParamCount) \ - { \ - if ( !s_pShaderParamOverrides[param] ) \ - return CBaseClass::GetParamDefault( param ); \ - else \ - return s_pShaderParamOverrides[param]->GetDefault(); \ - } \ - else \ - return s_ShaderParams[param - nBaseClassParamCount]->GetDefault(); \ - }\ - int GetParamFlags( int param ) const \ - {\ - int nBaseClassParamCount = CBaseClass::GetNumParams(); \ - if (param < nBaseClassParamCount) \ - { \ - if ( !s_pShaderParamOverrides[param] ) \ - return CBaseClass::GetParamFlags( param ); \ - else \ - return s_pShaderParamOverrides[param]->GetFlags(); \ - } \ - else \ - return s_ShaderParams[param - nBaseClassParamCount]->GetFlags(); \ - }\ - void OnInitShaderInstance( IMaterialVar **params, IShaderInit *pShaderInit, const char *pMaterialName ) - -#define SHADER_DRAW \ - void OnDrawElements( IMaterialVar **params, IShaderShadow* pShaderShadow, IShaderDynamicAPI* pShaderAPI, VertexCompressionType_t vertexCompression, CBasePerMaterialContextData **pContextDataPtr ) - -#define SHADOW_STATE if (pShaderShadow) -#define DYNAMIC_STATE if (pShaderAPI) - -#define ShaderWarning if (pShaderShadow) Warning - -//----------------------------------------------------------------------------- -// Used to easily define a shader which *always* falls back -//----------------------------------------------------------------------------- -#define DEFINE_FALLBACK_SHADER( _shadername, _fallbackshadername ) \ - BEGIN_SHADER( _shadername, "" ) \ - BEGIN_SHADER_PARAMS \ - END_SHADER_PARAMS \ - SHADER_FALLBACK { return #_fallbackshadername; } \ - SHADER_INIT {} \ - SHADER_DRAW {} \ - END_SHADER - - -//----------------------------------------------------------------------------- -// Used to easily define a shader which inherits from another shader -//----------------------------------------------------------------------------- - -// FIXME: There's a compiler bug preventing this from working. -// Maybe it'll work under VC7! - -//#define BEGIN_INHERITED_SHADER( name, _baseclass, help ) \ -// namespace _baseclass \ -// {\ -// __BEGIN_SHADER_INTERNAL( _baseclass::CShader, name, help ) - -//#define END_INHERITED_SHADER END_SHADER } - -//#define CHAIN_SHADER_INIT_PARAMS() CBaseClass::OnInitShaderParams( params, pMaterialName ) -//#define CHAIN_SHADER_FALLBACK() CBaseClass::GetFallbackShader( params ) -//#define CHAIN_SHADER_INIT() CBaseClass::OnInitShaderInstance( params, pShaderInit, pMaterialName ) -//#define CHAIN_SHADER_DRAW() CBaseClass::OnDrawElements( params, pShaderShadow, pShaderAPI ) - -// A dumbed-down version which does what I need now which works -// This version doesn't allow you to do chain *anything* down to the base class -#define BEGIN_INHERITED_SHADER_FLAGS( _name, _base, _help, _flags ) \ - namespace _base\ - {\ - namespace _name\ - {\ - static const char *s_Name = #_name; \ - static const char *s_HelpString = _help;\ - static int s_nFlags = _flags;\ - class CShader : public _base::CShader\ - {\ - public:\ - char const* GetName() const \ - { \ - return s_Name; \ - } \ - int GetFlags() const \ - { \ - return s_nFlags; \ - } - -#define BEGIN_INHERITED_SHADER( _name, _base, _help ) BEGIN_INHERITED_SHADER_FLAGS( _name, _base, _help, 0 ) -#define END_INHERITED_SHADER END_SHADER } - -// psh ## shader is used here to generate a warning if you don't ever call SET_DYNAMIC_PIXEL_SHADER -#define DECLARE_DYNAMIC_PIXEL_SHADER( shader ) \ - int declaredynpixshader_ ## shader ## _missingcurlybraces = 0; \ - declaredynpixshader_ ## shader ## _missingcurlybraces = declaredynpixshader_ ## shader ## _missingcurlybraces; \ - shader ## _Dynamic_Index _pshIndex; \ - int psh ## shader = 0 - -// vsh ## shader is used here to generate a warning if you don't ever call SET_DYNAMIC_VERTEX_SHADER -#define DECLARE_DYNAMIC_VERTEX_SHADER( shader ) \ - int declaredynvertshader_ ## shader ## _missingcurlybraces = 0; \ - declaredynvertshader_ ## shader ## _missingcurlybraces = declaredynvertshader_ ## shader ## _missingcurlybraces; \ - shader ## _Dynamic_Index _vshIndex; \ - int vsh ## shader = 0 - - -// psh ## shader is used here to generate a warning if you don't ever call SET_STATIC_PIXEL_SHADER -#define DECLARE_STATIC_PIXEL_SHADER( shader ) \ - int declarestaticpixshader_ ## shader ## _missingcurlybraces = 0; \ - declarestaticpixshader_ ## shader ## _missingcurlybraces = declarestaticpixshader_ ## shader ## _missingcurlybraces; \ - shader ## _Static_Index _pshIndex; \ - int psh ## shader = 0 - -// vsh ## shader is used here to generate a warning if you don't ever call SET_STATIC_VERTEX_SHADER -#define DECLARE_STATIC_VERTEX_SHADER( shader ) \ - int declarestaticvertshader_ ## shader ## _missingcurlybraces = 0; \ - declarestaticvertshader_ ## shader ## _missingcurlybraces = declarestaticvertshader_ ## shader ## _missingcurlybraces; \ - shader ## _Static_Index _vshIndex; \ - int vsh ## shader = 0 - - -// psh_forgot_to_set_dynamic_ ## var is used to make sure that you set all -// all combos. If you don't, you will get an undefined variable used error -// in the SET_DYNAMIC_PIXEL_SHADER block. -#define SET_DYNAMIC_PIXEL_SHADER_COMBO( var, val ) \ - int dynpixshadercombo_ ## var ## _missingcurlybraces = 0; \ - dynpixshadercombo_ ## var ## _missingcurlybraces = dynpixshadercombo_ ## var ## _missingcurlybraces; \ - _pshIndex.Set ## var( ( val ) ); \ - int psh_forgot_to_set_dynamic_ ## var = 0 - -// vsh_forgot_to_set_dynamic_ ## var is used to make sure that you set all -// all combos. If you don't, you will get an undefined variable used error -// in the SET_DYNAMIC_VERTEX_SHADER block. -#define SET_DYNAMIC_VERTEX_SHADER_COMBO( var, val ) \ - int dynvertshadercombo_ ## var ## _missingcurlybraces = 0; \ - dynvertshadercombo_ ## var ## _missingcurlybraces = dynvertshadercombo_ ## var ## _missingcurlybraces; \ - _vshIndex.Set ## var( ( val ) ); \ - int vsh_forgot_to_set_dynamic_ ## var = 0 - - -// psh_forgot_to_set_static_ ## var is used to make sure that you set all -// all combos. If you don't, you will get an undefined variable used error -// in the SET_STATIC_PIXEL_SHADER block. -#define SET_STATIC_PIXEL_SHADER_COMBO( var, val ) \ - int staticpixshadercombo_ ## var ## _missingcurlybraces = 0; \ - staticpixshadercombo_ ## var ## _missingcurlybraces = staticpixshadercombo_ ## var ## _missingcurlybraces; \ - _pshIndex.Set ## var( ( val ) ); \ - int psh_forgot_to_set_static_ ## var = 0 - -// vsh_forgot_to_set_static_ ## var is used to make sure that you set all -// all combos. If you don't, you will get an undefined variable used error -// in the SET_STATIC_VERTEX_SHADER block. -#define SET_STATIC_VERTEX_SHADER_COMBO( var, val ) \ - int staticvertshadercombo_ ## var ## _missingcurlybraces = 0; \ - staticvertshadercombo_ ## var ## _missingcurlybraces = staticvertshadercombo_ ## var ## _missingcurlybraces; \ - _vshIndex.Set ## var( ( val ) ); \ - int vsh_forgot_to_set_static_ ## var = 0 - - -// psh_testAllCombos adds up all of the psh_forgot_to_set_dynamic_ ## var's from -// SET_DYNAMIC_PIXEL_SHADER_COMBO so that an error is generated if they aren't set. -// psh_testAllCombos is set to itself to avoid an unused variable warning. -// psh ## shader being set to itself ensures that DECLARE_DYNAMIC_PIXEL_SHADER -// was called for this particular shader. -#define SET_DYNAMIC_PIXEL_SHADER( shader ) \ - int dynamicpixshader_ ## shader ## _missingcurlybraces = 0; \ - dynamicpixshader_ ## shader ## _missingcurlybraces = dynamicpixshader_ ## shader ## _missingcurlybraces; \ - int psh_testAllCombos = shaderDynamicTest_ ## shader; \ - psh_testAllCombos = psh_testAllCombos; \ - psh ## shader = psh ## shader; \ - pShaderAPI->SetPixelShaderIndex( _pshIndex.GetIndex() ) - -#define SET_DYNAMIC_PIXEL_SHADER_CMD( cmdstream, shader ) \ - int dynamicpixshader_ ## shader ## _missingcurlybraces = 0; \ - dynamicpixshader_ ## shader ## _missingcurlybraces = dynamicpixshader_ ## shader ## _missingcurlybraces; \ - int psh_testAllCombos = shaderDynamicTest_ ## shader; \ - psh_testAllCombos = psh_testAllCombos; \ - psh ## shader = psh ## shader; \ - cmdstream.SetPixelShaderIndex( _pshIndex.GetIndex() ) - - -// vsh_testAllCombos adds up all of the vsh_forgot_to_set_dynamic_ ## var's from -// SET_DYNAMIC_VERTEX_SHADER_COMBO so that an error is generated if they aren't set. -// vsh_testAllCombos is set to itself to avoid an unused variable warning. -// vsh ## shader being set to itself ensures that DECLARE_DYNAMIC_VERTEX_SHADER -// was called for this particular shader. -#define SET_DYNAMIC_VERTEX_SHADER( shader ) \ - int dynamicvertshader_ ## shader ## _missingcurlybraces = 0; \ - dynamicvertshader_ ## shader ## _missingcurlybraces = dynamicvertshader_ ## shader ## _missingcurlybraces; \ - int vsh_testAllCombos = shaderDynamicTest_ ## shader; \ - vsh_testAllCombos = vsh_testAllCombos; \ - vsh ## shader = vsh ## shader; \ - pShaderAPI->SetVertexShaderIndex( _vshIndex.GetIndex() ) - -#define SET_DYNAMIC_VERTEX_SHADER_CMD( cmdstream, shader ) \ - int dynamicvertshader_ ## shader ## _missingcurlybraces = 0; \ - dynamicvertshader_ ## shader ## _missingcurlybraces = dynamicvertshader_ ## shader ## _missingcurlybraces; \ - int vsh_testAllCombos = shaderDynamicTest_ ## shader; \ - vsh_testAllCombos = vsh_testAllCombos; \ - vsh ## shader = vsh ## shader; \ - cmdstream.SetVertexShaderIndex( _vshIndex.GetIndex() ) - - -// psh_testAllCombos adds up all of the psh_forgot_to_set_static_ ## var's from -// SET_STATIC_PIXEL_SHADER_COMBO so that an error is generated if they aren't set. -// psh_testAllCombos is set to itself to avoid an unused variable warning. -// psh ## shader being set to itself ensures that DECLARE_STATIC_PIXEL_SHADER -// was called for this particular shader. -#define SET_STATIC_PIXEL_SHADER( shader ) \ - int staticpixshader_ ## shader ## _missingcurlybraces = 0; \ - staticpixshader_ ## shader ## _missingcurlybraces = staticpixshader_ ## shader ## _missingcurlybraces; \ - int psh_testAllCombos = shaderStaticTest_ ## shader; \ - psh_testAllCombos = psh_testAllCombos; \ - psh ## shader = psh ## shader; \ - pShaderShadow->SetPixelShader( #shader, _pshIndex.GetIndex() ) - -// vsh_testAllCombos adds up all of the vsh_forgot_to_set_static_ ## var's from -// SET_STATIC_VERTEX_SHADER_COMBO so that an error is generated if they aren't set. -// vsh_testAllCombos is set to itself to avoid an unused variable warning. -// vsh ## shader being set to itself ensures that DECLARE_STATIC_VERTEX_SHADER -// was called for this particular shader. -#define SET_STATIC_VERTEX_SHADER( shader ) \ - int staticvertshader_ ## shader ## _missingcurlybraces = 0; \ - staticvertshader_ ## shader ## _missingcurlybraces = staticvertshader_ ## shader ## _missingcurlybraces; \ - int vsh_testAllCombos = shaderStaticTest_ ## shader; \ - vsh_testAllCombos = vsh_testAllCombos; \ - vsh ## shader = vsh ## shader; \ - pShaderShadow->SetVertexShader( #shader, _vshIndex.GetIndex() ) - -#endif // CSHADER_H diff --git a/public/shake.h b/public/shake.h deleted file mode 100644 index 815f5c875..000000000 --- a/public/shake.h +++ /dev/null @@ -1,63 +0,0 @@ -//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Network data for screen shake and screen fade. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SHAKE_H -#define SHAKE_H -#ifdef _WIN32 -#pragma once -#endif - - -// -// Commands for the screen shake effect. -// - -struct ScreenShake_t -{ - int command; - float amplitude; - float frequency; - float duration; -}; - -enum ShakeCommand_t -{ - SHAKE_START = 0, // Starts the screen shake for all players within the radius. - SHAKE_STOP, // Stops the screen shake for all players within the radius. - SHAKE_AMPLITUDE, // Modifies the amplitude of an active screen shake for all players within the radius. - SHAKE_FREQUENCY, // Modifies the frequency of an active screen shake for all players within the radius. - SHAKE_START_RUMBLEONLY, // Starts a shake effect that only rumbles the controller, no screen effect. - SHAKE_START_NORUMBLE, // Starts a shake that does NOT rumble the controller. -}; - - -// -// Screen shake message. -// -extern int gmsgShake; - -// Fade in/out -extern int gmsgFade; - -#define FFADE_IN 0x0001 // Just here so we don't pass 0 into the function -#define FFADE_OUT 0x0002 // Fade out (not in) -#define FFADE_MODULATE 0x0004 // Modulate (don't blend) -#define FFADE_STAYOUT 0x0008 // ignores the duration, stays faded out until new ScreenFade message received -#define FFADE_PURGE 0x0010 // Purges all other fades, replacing them with this one - -#define SCREENFADE_FRACBITS 9 // which leaves 16-this for the integer part -// This structure is sent over the net to describe a screen fade event -struct ScreenFade_t -{ - unsigned short duration; // FIXED 16 bit, with SCREENFADE_FRACBITS fractional, seconds duration - unsigned short holdTime; // FIXED 16 bit, with SCREENFADE_FRACBITS fractional, seconds duration until reset (fade & hold) - short fadeFlags; // flags - unsigned char r, g, b, a; // fade to color ( max alpha ) -}; - - -#endif // SHAKE_H diff --git a/public/shattersurfacetypes.h b/public/shattersurfacetypes.h deleted file mode 100644 index ffdee42eb..000000000 --- a/public/shattersurfacetypes.h +++ /dev/null @@ -1,21 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#if !defined ( SHATTERSURFACETYPES_H ) -#define SHATTERSURFACETYPES_H -#ifdef _WIN32 -#pragma once -#endif - -enum ShatterSurface_t -{ - // Note: This much match with the client entity - SHATTERSURFACE_GLASS = 0, - SHATTERSURFACE_TILE = 1, -}; - -#endif diff --git a/public/simple_physics.cpp b/public/simple_physics.cpp deleted file mode 100644 index 10f58b24c..000000000 --- a/public/simple_physics.cpp +++ /dev/null @@ -1,72 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include "simple_physics.h" -#include "tier0/dbg.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -CSimplePhysics::CSimplePhysics() -{ - Init( 1.0f / 30.0f ); // default is 30 steps per second -} - - -void CSimplePhysics::Init( float flTimeStep ) -{ - m_flPredictedTime = 0; - m_iCurTimeStep = 0; - m_flTimeStep = flTimeStep; - m_flTimeStepMul = m_flTimeStep*m_flTimeStep*0.5f; -} - - -void CSimplePhysics::Simulate( - CSimplePhysics::CNode *pNodes, - int nNodes, - CSimplePhysics::IHelper *pHelper, - float dt, - float flDamp ) -{ - // Figure out how many time steps to run. - m_flPredictedTime += dt; - int newTimeStep = (int)ceil( m_flPredictedTime / m_flTimeStep ); - int nTimeSteps = newTimeStep - m_iCurTimeStep; - for( int iTimeStep=0; iTimeStep < nTimeSteps; iTimeStep++ ) - { - // Simulate everything.. - for( int iNode=0; iNode < nNodes; iNode++ ) - { - CSimplePhysics::CNode *pNode = &pNodes[iNode]; - - // Apply forces. - Vector vAccel; - pHelper->GetNodeForces( pNodes, iNode, &vAccel ); - Assert( vAccel.IsValid() ); - - Vector vPrevPos = pNode->m_vPos; - pNode->m_vPos = pNode->m_vPos + (pNode->m_vPos - pNode->m_vPrevPos) * flDamp + vAccel * m_flTimeStepMul; - pNode->m_vPrevPos = vPrevPos; - } - - // Apply constraints. - pHelper->ApplyConstraints( pNodes, nNodes ); - } - m_iCurTimeStep = newTimeStep; - - // Setup predicted positions. - float flInterpolant = (m_flPredictedTime - (GetCurTime() - m_flTimeStep)) / m_flTimeStep; - for( int iNode=0; iNode < nNodes; iNode++ ) - { - CSimplePhysics::CNode *pNode = &pNodes[iNode]; - VectorLerp( pNode->m_vPrevPos, pNode->m_vPos, flInterpolant, pNode->m_vPredicted ); - } -} - - diff --git a/public/simple_physics.h b/public/simple_physics.h deleted file mode 100644 index 6cec7af41..000000000 --- a/public/simple_physics.h +++ /dev/null @@ -1,81 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SIMPLE_PHYSICS_H -#define SIMPLE_PHYSICS_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "mathlib/vector.h" - - -// CSimplePhysics is a framework for simplified physics simulation. -// It simulates at a fixed timestep and uses the Verlet integrator. -// -// To use it, create your nodes and implement your constraints and -// forces in an IHelper, then call Simulate each frame. -// CSimplePhysics will figure out how many timesteps to run and will -// provide predicted positions of things for you. -class CSimplePhysics -{ -public: - - class CNode - { - public: - - // Call this when initializing the nodes with their starting positions. - void Init( const Vector &vPos ) - { - m_vPos = m_vPrevPos = m_vPredicted = vPos; - } - - Vector m_vPos; // At time t - Vector m_vPrevPos; // At time t - m_flTimeStep - Vector m_vPredicted; // Predicted position - }; - - class IHelper - { - public: - virtual void GetNodeForces( CNode *pNodes, int iNode, Vector *pAccel ) = 0; - virtual void ApplyConstraints( CNode *pNodes, int nNodes ) = 0; - }; - - -public: - - CSimplePhysics(); - - void Init( float flTimeStep ); - - void Simulate( - CNode *pNodes, - int nNodes, - IHelper *pHelper, - float dt, - float flDamp ); - - -private: - - double GetCurTime() { return m_flTimeStep * m_iCurTimeStep; } - - -private: - - double m_flPredictedTime; // (GetCurTime()-m_flTimeStep) <= m_flPredictedTime <= GetCurTime() - int m_iCurTimeStep; - - float m_flTimeStep; - float m_flTimeStepMul; // dt*dt*0.5 -}; - - -#endif // SIMPLE_PHYSICS_H diff --git a/public/smooth_average.h b/public/smooth_average.h deleted file mode 100644 index 9f80e31f9..000000000 --- a/public/smooth_average.h +++ /dev/null @@ -1,222 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef SMOOTH_AVERAGE_H -#define SMOOTH_AVERAGE_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "utldict.h" - - - -// Use this macro around any value, and it'll queue up the results given to it nTimes and -// provide a running average. -#define SMOOTH_AVERAGE( value, nCount ) CalcSmoothAverage( value, nCount, __FILE__, __LINE__ ) - - -// Same as their counterpart functions but they return more info in a CTimingInfo structure. -#define SMOOTH_AVERAGE_STRUCT( value, nCount ) CalcSmoothAverage_Struct( value, nCount, __FILE__, __LINE__ ) -#define SUM_OVER_TIME_INTERVAL_STRUCT( value, nSeconds ) SumOverTimeInterval_Struct( value, nSeconds, __FILE__, __LINE__ ) - - -template< class T > -class CTimingInfo -{ -public: - T m_AverageValue; // Note: this will be the SUM of the values if using SUM_OVER_TIME_INTERVAL. - - // The high and low points for m_AverageValue over the time interval. - T m_HighAverage; - T m_LowAverage; - - // The high and low points for the value itself over the time interval. - T m_HighValue; - T m_LowValue; -}; - - -template< class T > -class CAveragesInfo -{ -public: - class CEntry - { - public: - T m_Average; - T m_Value; - }; - -public: - CUtlVector< CEntry > m_Values; - int m_iCurValue; -}; - - -template< class T > -class CAveragesInfo_TimeBased -{ -public: - class CEntry - { - public: - CCycleCount m_Time; // When this sample was taken. - T m_Value; - T m_Average; - }; - - CUtlVector m_Values; -}; - - -#if 0 -template< class T > -inline CTimingInfo< T > CalcSmoothAverage_Struct( const T &value, int nTimes, const char *pFilename, int iLine ) -{ - // Find an entry at this file and line. - char fullStr[1024]; - Q_snprintf( fullStr, sizeof( fullStr ), "%s_%i", pFilename, iLine ); - - int index = s_SmoothAverages.Find( fullStr ); - CAveragesInfo *pInfo; - if ( index == s_SmoothAverages.InvalidIndex() ) - { - pInfo = new CAveragesInfo; - index = s_SmoothAverages.Insert( fullStr, pInfo ); - } - else - { - pInfo = (CAveragesInfo*)s_SmoothAverages[index]; - } - - // Add the new value. - int newValueIndex; - CAveragesInfo< T >::CEntry entry; - entry.m_Value = value; - if ( pInfo->m_Values.Count() < nTimes ) - { - newValueIndex = pInfo->m_Values.AddToTail( entry ); - pInfo->m_iCurValue = 0; - } - else - { - newValueIndex = pInfo->m_iCurValue; - pInfo->m_Values[pInfo->m_iCurValue] = entry; - pInfo->m_iCurValue = (pInfo->m_iCurValue+1) % pInfo->m_Values.Count(); - } - - CTimingInfo< T > info; - info.m_AverageValue = pInfo->m_Values[0].m_Value; - - info.m_HighAverage = pInfo->m_Values[0].m_Average; - info.m_LowAverage = pInfo->m_Values[0].m_Average; - - info.m_HighValue = pInfo->m_Values[0].m_Value; - info.m_LowValue = pInfo->m_Values[0].m_Value; - - for ( int i=1; i < pInfo->m_Values.Count(); i++ ) - { - if ( i != newValueIndex ) - { - info.m_HighAverage = MAX( pInfo->m_Values[i].m_Average, info.m_HighAverage ); - info.m_LowAverage = MIN( pInfo->m_Values[i].m_Average, info.m_LowAverage ); - } - - info.m_HighValue = MAX( pInfo->m_Values[i].m_Value, info.m_HighValue ); - info.m_LowValue = MIN( pInfo->m_Values[i].m_Value, info.m_LowValue ); - - info.m_AverageValue += pInfo->m_Values[i].m_Value; - } - - info.m_AverageValue /= pInfo->m_Values.Count(); - pInfo->m_Values[newValueIndex].m_Average = info.m_AverageValue; - return info; -} -#endif - -template< class T > -inline T CalcSmoothAverage( const T &value, int nTimes, const char *pFilename, int iLine ) -{ - CTimingInfo< T > info = CalcSmoothAverage_Struct( value, nTimes, pFilename, iLine ); - return info.m_AverageValue; -}; - - -template< class T > -inline CTimingInfo< T > SumOverTimeInterval_Struct( const T &value, float nSeconds, const char *pFilename, int iLine ) -{ - static CUtlDict< CAveragesInfo_TimeBased< T >*, int > s_SmoothAverages; - - char fullStr[1024]; - Q_snprintf( fullStr, sizeof( fullStr ), "%s_%i", pFilename, iLine ); - - int index = s_SmoothAverages.Find( fullStr ); - CAveragesInfo_TimeBased *pInfo; - if ( index == s_SmoothAverages.InvalidIndex() ) - { - pInfo = new CAveragesInfo_TimeBased; - index = s_SmoothAverages.Insert( fullStr, pInfo ); - } - else - { - pInfo = s_SmoothAverages[index]; - } - - // Get the current time now. - CCycleCount curTime; - curTime.Sample(); - - // Get rid of old samples. - while ( pInfo->m_Values.Count() > 0 && (curTime.GetSeconds() - pInfo->m_Values[0].m_Time.GetSeconds()) > nSeconds ) - pInfo->m_Values.Remove( 0 ); - - // Add on the new sample. - typename CAveragesInfo_TimeBased< T >::CEntry newEntry; - newEntry.m_Time = curTime; - newEntry.m_Value = value; - int newValueIndex = pInfo->m_Values.AddToTail( newEntry ); - - CTimingInfo< T > info; - info.m_AverageValue = pInfo->m_Values[0].m_Value; - - info.m_HighAverage = pInfo->m_Values[0].m_Average; - info.m_LowAverage = pInfo->m_Values[0].m_Average; - - info.m_HighValue = pInfo->m_Values[0].m_Value; - info.m_LowValue = pInfo->m_Values[0].m_Value; - - for ( int i=1; i < pInfo->m_Values.Count(); i++ ) - { - if ( i != newValueIndex ) - { - info.m_HighAverage = MAX( pInfo->m_Values[i].m_Average, info.m_HighAverage ); - info.m_LowAverage = MIN( pInfo->m_Values[i].m_Average, info.m_LowAverage ); - } - - info.m_HighValue = MAX( pInfo->m_Values[i].m_Value, info.m_HighValue ); - info.m_LowValue = MIN( pInfo->m_Values[i].m_Value, info.m_LowValue ); - - info.m_AverageValue += pInfo->m_Values[i].m_Value; - } - - info.m_AverageValue /= pInfo->m_Values.Count(); - pInfo->m_Values[newValueIndex].m_Average = info.m_AverageValue; - return info; -} - - -template< class T > -inline CTimingInfo< T > SumOverTimeInterval( const T &value, float nSeconds, const char *pFilename, int iLine ) -{ - CTimingInfo< T > info = SumOverTimeInterval_Struct( value, nSeconds, pFilename, iLine ); - return info.m_AverageValue; -} - - -#endif // SMOOTH_AVERAGE_H - diff --git a/public/soundchars.h b/public/soundchars.h deleted file mode 100644 index eb2f80f91..000000000 --- a/public/soundchars.h +++ /dev/null @@ -1,68 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef SOUNDCHARS_H -#define SOUNDCHARS_H -#ifdef _WIN32 -#pragma once -#endif - -#define CHAR_STREAM '*' // as one of 1st 2 chars in name, indicates streaming wav data -#define CHAR_USERVOX '?' // as one of 1st 2 chars in name, indicates user realtime voice data -#define CHAR_SENTENCE '!' // as one of 1st 2 chars in name, indicates sentence wav -#define CHAR_DRYMIX '#' // as one of 1st 2 chars in name, indicates wav bypasses dsp fx -#define CHAR_DOPPLER '>' // as one of 1st 2 chars in name, indicates doppler encoded stereo wav: left wav (incomming) and right wav (outgoing). -#define CHAR_DIRECTIONAL '<' // as one of 1st 2 chars in name, indicates stereo wav has direction cone: mix left wav (front facing) with right wav (rear facing) based on soundfacing direction -#define CHAR_DISTVARIANT '^' // as one of 1st 2 chars in name, indicates distance variant encoded stereo wav (left is close, right is far) -#define CHAR_OMNI '@' // as one of 1st 2 chars in name, indicates non-directional wav (default mono or stereo) -#define CHAR_SPATIALSTEREO ')' // as one of 1st 2 chars in name, indicates spatialized stereo wav -#define CHAR_FAST_PITCH '}' // as one of 1st 2 chars in name, forces low quality, non-interpolated pitch shift - -inline bool IsSoundChar(char c) -{ - bool b; - - b = (c == CHAR_STREAM || c == CHAR_USERVOX || c == CHAR_SENTENCE || c == CHAR_DRYMIX || c == CHAR_OMNI ); - b = b || (c == CHAR_DOPPLER || c == CHAR_DIRECTIONAL || c == CHAR_DISTVARIANT || c == CHAR_SPATIALSTEREO || c == CHAR_FAST_PITCH ); - - return b; -} - -// return pointer to first valid character in file name -// by skipping over CHAR_STREAM...CHAR_DRYMIX - -inline char *PSkipSoundChars(const char *pch) -{ - char *pcht = (char *)pch; - - while ( 1 ) - { - if (!IsSoundChar(*pcht)) - break; - pcht++; - } - - return pcht; -} - - -inline bool TestSoundChar(const char *pch, char c) -{ - char *pcht = (char *)pch; - - while ( 1 ) - { - if (!IsSoundChar(*pcht)) - break; - if (*pcht == c) - return true; - pcht++; - } - - return false; -} - -#endif // SOUNDCHARS_H diff --git a/public/soundcombiner.cpp b/public/soundcombiner.cpp deleted file mode 100644 index c6b09f9da..000000000 --- a/public/soundcombiner.cpp +++ /dev/null @@ -1,823 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#include "cbase.h" -#include "isoundcombiner.h" -#include "sentence.h" -#include "filesystem.h" -#include "tier2/riff.h" -#include "tier1/utlbuffer.h" -#include "snd_audio_source.h" -#include "snd_wave_source.h" -#include "AudioWaveOutput.h" -#include "ifaceposersound.h" -#include "vstdlib/random.h" -#include "checksum_crc.h" - -#define WAVEOUTPUT_BITSPERCHANNEL 16 -#define WAVEOUTPUT_FREQUENCY 44100 - -class CSoundCombiner : public ISoundCombiner -{ -public: - CSoundCombiner() : - m_pWaveOutput( NULL ), - m_pOutRIFF( NULL ), - m_pOutIterator( NULL ) - { - m_szOutFile[ 0 ] = 0; - } - - virtual bool CombineSoundFiles( IFileSystem *filesystem, char const *outfile, CUtlVector< CombinerEntry >& info ); - virtual bool IsCombinedFileChecksumValid( IFileSystem *filesystem, char const *outfile, CUtlVector< CombinerEntry >& info ); - -private: - - struct CombinerWork - { - CombinerWork() : - sentence(), - duration( 0.0 ), - wave( 0 ), - mixer( 0 ), - entry( 0 ) - { - } - CSentence sentence; - float duration; - CAudioSource *wave; - CAudioMixer *mixer; - CombinerEntry *entry; - }; - - bool InternalCombineSoundFiles( IFileSystem *filesystem, char const *outfile, CUtlVector< CombinerEntry >& info ); - bool VerifyFilesExist( IFileSystem *filesystem, CUtlVector< CombinerEntry >& info ); - bool CreateWorkList( IFileSystem *filesystem, CUtlVector< CombinerEntry >& info ); - - bool PerformSplicingOnWorkItems( IFileSystem *filesystem ); - void CleanupWork(); - - // .wav file utils - int ComputeBestNumChannels(); - void ParseSentence( CSentence& sentence, IterateRIFF &walk ); - bool LoadSentenceFromWavFileUsingIO( char const *wavfile, CSentence& sentence, IFileReadBinary& io ); - bool LoadSentenceFromWavFile( char const *wavfile, CSentence& sentence ); - void StoreValveDataChunk( CSentence& sentence ); -// bool SaveSentenceToWavFile( char const *wavfile, CSentence& sentence ); - - bool InitSplicer( IFileSystem *filesystem, int samplerate, int numchannels, int bitspersample ); - bool LoadSpliceAudioSources(); - bool AppendSilence( int ¤tsample, float duration ); - bool AppendStereo16Data( short samples[ 2 ] ); - bool AppendWaveData( int& currentsample, CAudioSource *wave, CAudioMixer *mixer ); - void AddSentenceToCombined( float offset, CSentence& sentence ); - - unsigned int CheckSumWork( IFileSystem *filesystem, CUtlVector< CombinerEntry >& info ); - unsigned int ComputeChecksum(); - - CUtlVector< CombinerWork * > m_Work; - CSentence m_Combined; - - CAudioWaveOutput *m_pWaveOutput; - - OutFileRIFF *m_pOutRIFF; - IterateOutputRIFF *m_pOutIterator; - - int m_nSampleRate; - int m_nNumChannels; - int m_nBitsPerSample; - int m_nBytesPerSample; - char m_szOutFile[ MAX_PATH ]; -}; - -static CSoundCombiner g_SoundCombiner; -ISoundCombiner *soundcombiner = &g_SoundCombiner; - -bool CSoundCombiner::CreateWorkList( IFileSystem *filesystem, CUtlVector< CombinerEntry >& info ) -{ - m_Work.RemoveAll(); - - int c = info.Count(); - for ( int i = 0; i < c; ++i ) - { - CombinerWork *workitem = new CombinerWork(); - - char fullpath[ MAX_PATH ]; - Q_strncpy( fullpath, info[ i ].wavefile, sizeof( fullpath ) ); - filesystem->GetLocalPath( info[ i ].wavefile, fullpath, sizeof( fullpath ) ); - - if ( !LoadSentenceFromWavFile( fullpath, workitem->sentence ) ) - { - Warning( "CSoundCombiner::CreateWorkList couldn't load %s for work item (%d)\n", - fullpath, i ); - return false; - } - - workitem->entry = &info[ i ]; - - m_Work.AddToTail( workitem ); - } - - return true; -} - -void CSoundCombiner::CleanupWork() -{ - int c = m_Work.Count(); - for ( int i = 0; i < c; ++i ) - { - CombinerWork *workitem = m_Work[ i ]; - delete workitem->mixer; - delete workitem->wave; - - delete m_Work[ i ]; - } - m_Work.RemoveAll(); - - delete m_pOutIterator; - m_pOutIterator = NULL; - - delete m_pOutRIFF; - m_pOutRIFF = NULL; -} - -bool CSoundCombiner::InternalCombineSoundFiles( IFileSystem *filesystem, char const *outfile, CUtlVector< CombinerEntry >& info ) -{ - Q_strncpy( m_szOutFile, outfile, sizeof( m_szOutFile ) ); - if ( info.Count() <= 0 ) - { - Warning( "CSoundCombiner::InternalCombineSoundFiles: work item count is zero\n" ); - return false; - } - - if ( !VerifyFilesExist( filesystem, info ) ) - { - return false; - } - - if ( !CreateWorkList( filesystem, info ) ) - { - return false; - } - - PerformSplicingOnWorkItems( filesystem ); - - return true; -} - -bool CSoundCombiner::CombineSoundFiles( IFileSystem *filesystem, char const *outfile, CUtlVector< CombinerEntry >& info ) -{ - bool bret = InternalCombineSoundFiles( filesystem, outfile, info ); - CleanupWork(); - return bret; -} - -unsigned int CSoundCombiner::ComputeChecksum() -{ - CRC32_t crc; - CRC32_Init( &crc ); - - int c = m_Work.Count(); - for ( int i = 0; i < c; ++i ) - { - CombinerWork *curitem = m_Work[ i ]; - unsigned int chk = curitem->sentence.ComputeDataCheckSum(); - - // Msg( " %i -> sentence %u, startoffset %f fn %s\n", - // i, chk, curitem->entry->startoffset, curitem->entry->wavefile ); - - CRC32_ProcessBuffer( &crc, &chk, sizeof( unsigned long ) ); - CRC32_ProcessBuffer( &crc, &curitem->entry->startoffset, sizeof( float ) ); - CRC32_ProcessBuffer( &crc, curitem->entry->wavefile, Q_strlen( curitem->entry->wavefile ) ); - } - - CRC32_Final( &crc ); - return ( unsigned int )crc; -} - -unsigned int CSoundCombiner::CheckSumWork( IFileSystem *filesystem, CUtlVector< CombinerEntry >& info ) -{ - if ( info.Count() <= 0 ) - { - Warning( "CSoundCombiner::CheckSumWork: work item count is zero\n" ); - return 0; - } - - if ( !VerifyFilesExist( filesystem, info ) ) - { - return 0; - } - - if ( !CreateWorkList( filesystem, info ) ) - { - return 0; - } - - // Checkum work items - unsigned int checksum = ComputeChecksum(); - - return checksum; -} - -bool CSoundCombiner::IsCombinedFileChecksumValid( IFileSystem *filesystem, char const *outfile, CUtlVector< CombinerEntry >& info ) -{ - unsigned int computedChecksum = CheckSumWork( filesystem, info ); - - char fullpath[ MAX_PATH ]; - Q_strncpy( fullpath, outfile, sizeof( fullpath ) ); - filesystem->GetLocalPath( outfile, fullpath, sizeof( fullpath ) ); - - CSentence sentence; - - bool valid = false; - - if ( LoadSentenceFromWavFile( fullpath, sentence ) ) - { - unsigned int diskFileEmbeddedChecksum = sentence.GetDataCheckSum(); - - valid = computedChecksum == diskFileEmbeddedChecksum; - - if ( !valid ) - { - Warning( " checksum computed %u, disk %u\n", - computedChecksum, diskFileEmbeddedChecksum ); - } - } - else - { - Warning( "CSoundCombiner::IsCombinedFileChecksumValid: Unabled to load %s\n", fullpath ); - } - - CleanupWork(); - return valid; -} - -bool CSoundCombiner::VerifyFilesExist( IFileSystem *filesystem, CUtlVector< CombinerEntry >& info ) -{ - int c = info.Count(); - for ( int i = 0 ; i < c; ++i ) - { - CombinerEntry& entry = info[ i ]; - if ( !filesystem->FileExists( entry.wavefile ) ) - { - Warning( "CSoundCombiner::VerifyFilesExist: missing file %s\n", entry.wavefile ); - return false; - } - } - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Implements the RIFF i/o interface on stdio -//----------------------------------------------------------------------------- -class StdIOReadBinary : public IFileReadBinary -{ -public: - int open( const char *pFileName ) - { - return (int)filesystem->Open( pFileName, "rb" ); - } - - int read( void *pOutput, int size, int file ) - { - if ( !file ) - return 0; - - return filesystem->Read( pOutput, size, (FileHandle_t)file ); - } - - void seek( int file, int pos ) - { - if ( !file ) - return; - - filesystem->Seek( (FileHandle_t)file, pos, FILESYSTEM_SEEK_HEAD ); - } - - unsigned int tell( int file ) - { - if ( !file ) - return 0; - - return filesystem->Tell( (FileHandle_t)file ); - } - - unsigned int size( int file ) - { - if ( !file ) - return 0; - - return filesystem->Size( (FileHandle_t)file ); - } - - void close( int file ) - { - if ( !file ) - return; - - filesystem->Close( (FileHandle_t)file ); - } -}; - -class StdIOWriteBinary : public IFileWriteBinary -{ -public: - int create( const char *pFileName ) - { - return (int)filesystem->Open( pFileName, "wb" ); - } - - int write( void *pData, int size, int file ) - { - return filesystem->Write( pData, size, (FileHandle_t)file ); - } - - void close( int file ) - { - filesystem->Close( (FileHandle_t)file ); - } - - void seek( int file, int pos ) - { - filesystem->Seek( (FileHandle_t)file, pos, FILESYSTEM_SEEK_HEAD ); - } - - unsigned int tell( int file ) - { - return filesystem->Tell( (FileHandle_t)file ); - } -}; - -static StdIOReadBinary io_in; -static StdIOWriteBinary io_out; - -#define RIFF_WAVE MAKEID('W','A','V','E') -#define WAVE_FMT MAKEID('f','m','t',' ') -#define WAVE_DATA MAKEID('d','a','t','a') -#define WAVE_FACT MAKEID('f','a','c','t') -#define WAVE_CUE MAKEID('c','u','e',' ') - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &walk - -//----------------------------------------------------------------------------- -void CSoundCombiner::ParseSentence( CSentence& sentence, IterateRIFF &walk ) -{ - CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); - - buf.EnsureCapacity( walk.ChunkSize() ); - walk.ChunkRead( buf.Base() ); - buf.SeekPut( CUtlBuffer::SEEK_HEAD, walk.ChunkSize() ); - - sentence.InitFromDataChunk( buf.Base(), buf.TellPut() ); -} - -bool CSoundCombiner::LoadSentenceFromWavFileUsingIO( char const *wavfile, CSentence& sentence, IFileReadBinary& io ) -{ - sentence.Reset(); - - InFileRIFF riff( wavfile, io ); - - // UNDONE: Don't use printf to handle errors - if ( riff.RIFFName() != RIFF_WAVE ) - { - return false; - } - - // set up the iterator for the whole file (root RIFF is a chunk) - IterateRIFF walk( riff, riff.RIFFSize() ); - - // This chunk must be first as it contains the wave's format - // break out when we've parsed it - bool found = false; - while ( walk.ChunkAvailable() && !found ) - { - switch( walk.ChunkName() ) - { - case WAVE_VALVEDATA: - { - found = true; - CSoundCombiner::ParseSentence( sentence, walk ); - } - break; - } - walk.ChunkNext(); - } - - return true; -} - -bool CSoundCombiner::LoadSentenceFromWavFile( char const *wavfile, CSentence& sentence ) -{ - return CSoundCombiner::LoadSentenceFromWavFileUsingIO( wavfile, sentence, io_in ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : store - -//----------------------------------------------------------------------------- -void CSoundCombiner::StoreValveDataChunk( CSentence& sentence ) -{ - // Buffer and dump data - CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); - - sentence.SaveToBuffer( buf ); - - // Copy into store - m_pOutIterator->ChunkWriteData( buf.Base(), buf.TellPut() ); -} - -/* -bool CSoundCombiner::SaveSentenceToWavFile( char const *wavfile, CSentence& sentence ) -{ - char tempfile[ 512 ]; - - Q_StripExtension( wavfile, tempfile, sizeof( tempfile ) ); - Q_DefaultExtension( tempfile, ".tmp", sizeof( tempfile ) ); - - if ( filesystem->FileExists( tempfile, NULL ) ) - { - filesystem->RemoveFile( tempfile, NULL ); - } - - if ( !filesystem->IsFileWritable( wavfile ) ) - { - Msg( "%s is not writable, can't save sentence data to file\n", wavfile ); - return false; - } - - // Rename original wavfile to temp - filesystem->RenameFile( wavfile, tempfile, NULL ); - - // NOTE: Put this in it's own scope so that the destructor for outfileRFF actually closes the file!!!! - { - // Read from Temp - InFileRIFF riff( tempfile, io_in ); - Assert( riff.RIFFName() == RIFF_WAVE ); - - // set up the iterator for the whole file (root RIFF is a chunk) - IterateRIFF walk( riff, riff.RIFFSize() ); - - // And put data back into original wavfile by name - OutFileRIFF riffout( wavfile, io_out ); - - IterateOutputRIFF store( riffout ); - - bool wordtrackwritten = false; - - // Walk input chunks and copy to output - while ( walk.ChunkAvailable() ) - { - m_pOutIterator->ChunkStart( walk.ChunkName() ); - - switch ( walk.ChunkName() ) - { - case WAVE_VALVEDATA: - { - // Overwrite data - CSoundCombiner::StoreValveDataChunk( sentence ); - wordtrackwritten = true; - } - break; - default: - m_pOutIterator->CopyChunkData( walk ); - break; - } - - m_pOutIterator->ChunkFinish(); - - walk.ChunkNext(); - } - - // If we didn't write it above, write it now - if ( !wordtrackwritten ) - { - m_pOutIterator->ChunkStart( WAVE_VALVEDATA ); - CSoundCombiner::StoreValveDataChunk( sentence ); - m_pOutIterator->ChunkFinish(); - } - } - - // Remove temp file - filesystem->RemoveFile( tempfile, NULL ); - - return true; -} -*/ - -typedef struct channel_s -{ - int leftvol; - int rightvol; - int rleftvol; - int rrightvol; - float pitch; -} channel_t; - -bool CSoundCombiner::InitSplicer( IFileSystem *filesystem, int samplerate, int numchannels, int bitspersample ) -{ - m_nSampleRate = samplerate; - m_nNumChannels = numchannels; - m_nBitsPerSample = bitspersample; - m_nBytesPerSample = bitspersample >> 3; - - m_pWaveOutput = ( CAudioWaveOutput * )sound->GetAudioOutput(); - if ( !m_pWaveOutput ) - { - Warning( "CSoundCombiner::InitSplicer m_pWaveOutput == NULL\n" ); - return false; - } - - // Make sure the directory exists - char basepath[ 512 ]; - Q_ExtractFilePath( m_szOutFile, basepath, sizeof( basepath ) ); - filesystem->CreateDirHierarchy( basepath, "GAME" ); - - // Create out put file - m_pOutRIFF = new OutFileRIFF( m_szOutFile, io_out ); - if ( !m_pOutRIFF ) - { - Warning( "CSoundCombiner::InitSplicer m_pOutRIFF == NULL\n" ); - return false; - } - - // Create output iterator - m_pOutIterator = new IterateOutputRIFF( *m_pOutRIFF ); - if ( !m_pOutIterator ) - { - Warning( "CSoundCombiner::InitSplicer m_pOutIterator == NULL\n" ); - return false; - } - - WAVEFORMATEX format; - format.cbSize = sizeof( format ); - - format.wFormatTag = WAVE_FORMAT_PCM; - format.nAvgBytesPerSec = m_nSampleRate * m_nNumChannels * m_nBytesPerSample; - format.nChannels = m_nNumChannels; - format.wBitsPerSample = m_nBitsPerSample; - format.nSamplesPerSec = m_nSampleRate; - format.nBlockAlign = 1; - - // Always store the format chunk first - m_pOutIterator->ChunkWrite( WAVE_FMT, &format, sizeof( format ) ); - - return true; -} - -bool CSoundCombiner::LoadSpliceAudioSources() -{ - int c = m_Work.Count(); - for ( int i = 0; i < c; ++i ) - { - CombinerWork *item = m_Work[ i ]; - - CAudioSource *wave = sound->LoadSound( item->entry->wavefile ); - if ( !wave ) - { - Warning( "CSoundCombiner::LoadSpliceAudioSources LoadSound failed '%s'\n", item->entry->wavefile ); - return false; - } - - CAudioMixer *pMixer = wave->CreateMixer(); - if ( !pMixer ) - { - Warning( "CSoundCombiner::LoadSpliceAudioSources CreateMixer failed '%s'\n", item->entry->wavefile ); - return false; - } - - item->wave = wave; - item->mixer = pMixer; - item->duration = wave->GetRunningLength(); - } - - return true; -} - -bool CSoundCombiner::AppendSilence( int ¤tsample, float duration ) -{ - int numSamples = duration * m_nSampleRate; - -#define MOTION_RANGE 150 -#define MOTION_MAXSTEP 20 - int currentValue = 32767; - int maxValue = currentValue + ( MOTION_RANGE / 2 ); - int minValue = currentValue - ( MOTION_RANGE / 2 ); - - short samples[ 2 ]; - - while ( --numSamples >= 0 ) - { - currentValue += random->RandomInt( -MOTION_MAXSTEP, MOTION_MAXSTEP ); - currentValue = MIN( maxValue, currentValue ); - currentValue = MAX( minValue, currentValue ); - - // Downsample to 0 65556 range - short s = (float)currentValue / 32768.0f; - - samples[ 0 ] = s; - samples[ 1 ] = s; - - AppendStereo16Data( samples ); - } - - return true; -} - -bool CSoundCombiner::AppendStereo16Data( short samples[ 2 ] ) -{ -// Convert from 16 bit, 2 channels to output size - if ( m_nNumChannels == 1 ) - { - if ( m_nBytesPerSample == 1 ) - { - // Convert to 8 bit mono - // left + right (2 channels ) * 16 bits - float s1 = (float)( samples[ 0 ] >> 8 ); - float s2 = (float)( samples[ 1 ] >> 8 ); - - float avg = ( s1 + s2 ) * 0.5f; - avg = clamp( avg, -127.0f, 127.0f ); - byte chopped = (byte)( avg+ 127 ); - - m_pOutIterator->ChunkWriteData( &chopped, sizeof( byte ) ); - } - else if ( m_nBytesPerSample == 2 ) - { - // Conver to 16 bit mono - float s1 = (float)( samples[ 0 ] ); - float s2 = (float)( samples[ 1 ] ); - - float avg = ( s1 + s2 ) * 0.5f; - unsigned short chopped = (unsigned short)( avg ); - - m_pOutIterator->ChunkWriteData( &chopped, sizeof( unsigned short ) ); - } - else - { - Assert( 0 ); - return false; - } - } - else if ( m_nNumChannels == 2 ) - { - if ( m_nBytesPerSample == 1 ) - { - // Convert to 8 bit stereo - // left + right (2 channels ) * 16 bits - float s1 = (float)( samples[ 0 ] >> 8 ); - float s2 = (float)( samples[ 1 ] >> 8 ); - - s1 = clamp( s1, -127.0f, 127.0f ); - s2 = clamp( s2, -127.0f, 127.0f ); - - byte chopped1 = (byte)( s1 + 127.0f ); - byte chopped2 = (byte)( s2 + 127.0f ); - - m_pOutIterator->ChunkWriteData( &chopped1, sizeof( byte ) ); - m_pOutIterator->ChunkWriteData( &chopped2, sizeof( byte ) ); - } - else if ( m_nBytesPerSample == 2 ) - { - // Leave as 16 bit stereo - // Directly store values - m_pOutIterator->ChunkWriteData( &samples[ 0 ], sizeof( unsigned short ) ); - m_pOutIterator->ChunkWriteData( &samples[ 1 ], sizeof( unsigned short ) ); - } - else - { - Assert( 0 ); - return false; - } - } - else - { - Assert( 0 ); - return false; - } - - return true; -} - -bool CSoundCombiner::AppendWaveData( int& currentsample, CAudioSource *wave, CAudioMixer *mixer ) -{ - // need a bit of space - short samples[ 2 ]; - channel_t channel; - memset( &channel, 0, sizeof( channel ) ); - channel.leftvol = 255; - channel.rightvol = 255; - channel.pitch = 1.0; - - while ( 1 ) - { - m_pWaveOutput->m_audioDevice.MixBegin(); - - if ( !mixer->MixDataToDevice( &m_pWaveOutput->m_audioDevice, &channel, currentsample, 1, wave->SampleRate(), true ) ) - break; - - m_pWaveOutput->m_audioDevice.TransferBufferStereo16( samples, 1 ); - - currentsample = mixer->GetSamplePosition(); - - AppendStereo16Data( samples ); - } - - return true; -} - -int CSoundCombiner::ComputeBestNumChannels() -{ - // We prefer mono output unless one of the source wav files is stereo, then we'll do stereo output - int c = m_Work.Count(); - for ( int i = 0; i < c; ++i ) - { - CombinerWork *curitem = m_Work[ i ]; - - if ( curitem->wave->GetNumChannels() == 2 ) - { - return 2; - } - } - return 1; -} - -bool CSoundCombiner::PerformSplicingOnWorkItems( IFileSystem *filesystem ) -{ - if ( !LoadSpliceAudioSources() ) - { - return false; - } - - int bestNumChannels = ComputeBestNumChannels(); - int bitsPerChannel = WAVEOUTPUT_BITSPERCHANNEL; - - // Pull in data and write it out - if ( !InitSplicer( filesystem, WAVEOUTPUT_FREQUENCY, bestNumChannels, bitsPerChannel ) ) - { - return false; - } - - m_pOutIterator->ChunkStart( WAVE_DATA ); - - float timeoffset = 0.0f; - - m_Combined.Reset(); - m_Combined.SetText( "" ); - - int c = m_Work.Count(); - for ( int i = 0; i < c; ++i ) - { - int currentsample = 0; - - CombinerWork *curitem = m_Work[ i ]; - CombinerWork *nextitem = NULL; - if ( i != c - 1 ) - { - nextitem = m_Work[ i + 1 ]; - } - - float duration = curitem->duration; - - AppendWaveData( currentsample, curitem->wave, curitem->mixer ); - - AddSentenceToCombined( timeoffset, curitem->sentence ); - - timeoffset += duration; - - if ( nextitem != NULL ) - { - float nextstart = nextitem->entry->startoffset; - float silence_time = nextstart - timeoffset; - - AppendSilence( currentsample, silence_time ); - - timeoffset += silence_time; - } - } - - m_pOutIterator->ChunkFinish(); - - // Checksum the work items - unsigned int checksum = ComputeChecksum(); - - // Make sure the checksum is embedded in the data file - m_Combined.SetDataCheckSum( checksum ); - - // Msg( " checksum computed %u\n", checksum ); - - m_pOutIterator->ChunkStart( WAVE_VALVEDATA ); - StoreValveDataChunk( m_Combined ); - m_pOutIterator->ChunkFinish(); - - - return true; -} - -void CSoundCombiner::AddSentenceToCombined( float offset, CSentence& sentence ) -{ - m_Combined.Append( offset, sentence ); -} diff --git a/public/soundflags.h b/public/soundflags.h deleted file mode 100644 index a1ceeb634..000000000 --- a/public/soundflags.h +++ /dev/null @@ -1,158 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SOUNDFLAGS_H -#define SOUNDFLAGS_H - -#if defined( _WIN32 ) -#pragma once -#endif - - -//----------------------------------------------------------------------------- -// channels -//----------------------------------------------------------------------------- -enum -{ - CHAN_REPLACE = -1, - CHAN_AUTO = 0, - CHAN_WEAPON = 1, - CHAN_VOICE = 2, - CHAN_ITEM = 3, - CHAN_BODY = 4, - CHAN_STREAM = 5, // allocate stream channel from the static or dynamic area - CHAN_STATIC = 6, // allocate channel from the static area - CHAN_VOICE_BASE = 7, // allocate channel for network voice data - CHAN_USER_BASE = (CHAN_VOICE_BASE+128) // Anything >= this number is allocated to game code. -}; - -//----------------------------------------------------------------------------- -// common volume values -//----------------------------------------------------------------------------- -#define VOL_NORM 1.0f - - -//----------------------------------------------------------------------------- -// common attenuation values -//----------------------------------------------------------------------------- -#define ATTN_NONE 0.0f -#define ATTN_NORM 0.8f -#define ATTN_IDLE 2.0f -#define ATTN_STATIC 1.25f -#define ATTN_RICOCHET 1.5f - -// HL2 world is 8x bigger now! We want to hear gunfire from farther. -// Don't change this without consulting Kelly or Wedge (sjb). -#define ATTN_GUNFIRE 0.27f - -enum soundlevel_t -{ - SNDLVL_NONE = 0, - - SNDLVL_20dB = 20, // rustling leaves - SNDLVL_25dB = 25, // whispering - SNDLVL_30dB = 30, // library - SNDLVL_35dB = 35, - SNDLVL_40dB = 40, - SNDLVL_45dB = 45, // refrigerator - - SNDLVL_50dB = 50, // 3.9 // average home - SNDLVL_55dB = 55, // 3.0 - - SNDLVL_IDLE = 60, // 2.0 - SNDLVL_60dB = 60, // 2.0 // normal conversation, clothes dryer - - SNDLVL_65dB = 65, // 1.5 // washing machine, dishwasher - SNDLVL_STATIC = 66, // 1.25 - - SNDLVL_70dB = 70, // 1.0 // car, vacuum cleaner, mixer, electric sewing machine - - SNDLVL_NORM = 75, - SNDLVL_75dB = 75, // 0.8 // busy traffic - - SNDLVL_80dB = 80, // 0.7 // mini-bike, alarm clock, noisy restaurant, office tabulator, outboard motor, passing snowmobile - SNDLVL_TALKING = 80, // 0.7 - SNDLVL_85dB = 85, // 0.6 // average factory, electric shaver - SNDLVL_90dB = 90, // 0.5 // screaming child, passing motorcycle, convertible ride on frw - SNDLVL_95dB = 95, - SNDLVL_100dB = 100, // 0.4 // subway train, diesel truck, woodworking shop, pneumatic drill, boiler shop, jackhammer - SNDLVL_105dB = 105, // helicopter, power mower - SNDLVL_110dB = 110, // snowmobile drvrs seat, inboard motorboat, sandblasting - SNDLVL_120dB = 120, // auto horn, propeller aircraft - SNDLVL_130dB = 130, // air raid siren - - SNDLVL_GUNFIRE = 140, // 0.27 // THRESHOLD OF PAIN, gunshot, jet engine - SNDLVL_140dB = 140, // 0.2 - - SNDLVL_150dB = 150, // 0.2 - - SNDLVL_180dB = 180, // rocket launching - - // NOTE: Valid soundlevel_t values are 0-255. - // 256-511 are reserved for sounds using goldsrc compatibility attenuation. -}; - -#define MAX_SNDLVL_BITS 9 // Used to encode 0-255 for regular soundlevel_t's and 256-511 for goldsrc-compatible ones. -#define MIN_SNDLVL_VALUE 0 -#define MAX_SNDLVL_VALUE ((1< 50) ? (20.0f / (float)(a - 50)) : 4.0 ) - -// This is a limit due to network encoding. -// It encodes attenuation * 64 in 8 bits, so the maximum is (255 / 64) -#define MAX_ATTENUATION 3.98f - -//----------------------------------------------------------------------------- -// Flags to be or-ed together for the iFlags field -//----------------------------------------------------------------------------- -enum SoundFlags_t -{ - SND_NOFLAGS = 0, // to keep the compiler happy - SND_CHANGE_VOL = (1<<0), // change sound vol - SND_CHANGE_PITCH = (1<<1), // change sound pitch - SND_STOP = (1<<2), // stop the sound - SND_SPAWNING = (1<<3), // we're spawning, used in some cases for ambients - // not sent over net, only a param between dll and server. - SND_DELAY = (1<<4), // sound has an initial delay - SND_STOP_LOOPING = (1<<5), // stop all looping sounds on the entity. - SND_SPEAKER = (1<<6), // being played again by a microphone through a speaker - - SND_SHOULDPAUSE = (1<<7), // this sound should be paused if the game is paused - SND_IGNORE_PHONEMES = (1<<8), - SND_IGNORE_NAME = (1<<9), // used to change all sounds emitted by an entity, regardless of scriptname -}; - -#define SND_FLAG_BITS_ENCODE 9 - -#define MAX_SOUND_INDEX_BITS 13 -#define MAX_SOUNDS (1<name ) \ - buffer.WriteOneBit(0); \ - else \ - { \ - buffer.WriteOneBit(1); \ - buffer.WriteUBitLong( name, length ); \ - } - -#define READ_DELTA_UINT( name, length ) \ - if ( buffer.ReadOneBit() != 0 ) \ - { name = buffer.ReadUBitLong( length ); }\ - else { name = delta->name; } - -#define WRITE_DELTA_SINT( name, length ) \ - if ( name == delta->name ) \ - buffer.WriteOneBit(0); \ - else \ - { \ - buffer.WriteOneBit(1); \ - buffer.WriteSBitLong( name, length ); \ - } - -#define WRITE_DELTA_SINT_SCALE( name, scale, length ) \ - if ( name == delta->name ) \ - buffer.WriteOneBit(0); \ - else \ - { \ - buffer.WriteOneBit(1); \ - buffer.WriteSBitLong( name / scale, length ); \ - } - -#define READ_DELTA_SINT( name, length ) \ - if ( buffer.ReadOneBit() != 0 ) \ - { name = buffer.ReadSBitLong( length ); } \ - else { name = delta->name; } - -#define READ_DELTA_SINT_SCALE( name, scale, length ) \ - if ( buffer.ReadOneBit() != 0 ) \ - { name = scale * buffer.ReadSBitLong( length ); } \ - else { name = delta->name; } - -#define SOUND_SEQNUMBER_BITS 10 -#define SOUND_SEQNUMBER_MASK ( (1<nEntityIndex ) - { - buffer.WriteOneBit( 0 ); - } - else - { - buffer.WriteOneBit( 1 ); - - if ( nEntityIndex <= 31) - { - buffer.WriteOneBit( 1 ); - buffer.WriteUBitLong( nEntityIndex, 5 ); - } - else - { - buffer.WriteOneBit( 0 ); - buffer.WriteUBitLong( nEntityIndex, MAX_EDICT_BITS ); - } - } - - WRITE_DELTA_UINT( nSoundNum, MAX_SOUND_INDEX_BITS ); - - WRITE_DELTA_UINT( nFlags, SND_FLAG_BITS_ENCODE ); - - WRITE_DELTA_UINT( nChannel, 3 ); - - buffer.WriteOneBit( bIsAmbient?1:0 ); - buffer.WriteOneBit( bIsSentence?1:0 ); // NOTE: SND_STOP behavior is different depending on this flag - - if ( nFlags != SND_STOP ) - { - if ( nSequenceNumber == delta->nSequenceNumber ) - { - // didn't change, most often case - buffer.WriteOneBit( 1 ); - } - else if ( nSequenceNumber == (delta->nSequenceNumber+1) ) - { - // increased by one - buffer.WriteOneBit( 0 ); - buffer.WriteOneBit( 1 ); - } - else - { - // send full seqnr - buffer.WriteUBitLong( 0, 2 ); // 2 zero bits - buffer.WriteUBitLong( nSequenceNumber, SOUND_SEQNUMBER_BITS ); - } - - if ( fVolume == delta->fVolume ) - { - buffer.WriteOneBit( 0 ); - } - else - { - buffer.WriteOneBit( 1 ); - buffer.WriteUBitLong( (unsigned int)(fVolume*127.0f), 7 ); - } - - WRITE_DELTA_UINT( Soundlevel, MAX_SNDLVL_BITS ); - - WRITE_DELTA_UINT( nPitch, 8 ); - - if ( fDelay == delta->fDelay ) - { - buffer.WriteOneBit( 0 ); - } - else - { - buffer.WriteOneBit( 1 ); - - // skipahead works in 10 ms increments - // bias results so that we only incur the precision loss on relatively large skipaheads - fDelay += SOUND_DELAY_OFFSET; - - // Convert to msecs - int iDelay = fDelay * 1000.0f; - - iDelay = clamp( iDelay, (int)(-10 * MAX_SOUND_DELAY_MSEC), (int)(MAX_SOUND_DELAY_MSEC) ); - - if ( iDelay < 0 ) - { - iDelay /=10; - } - - buffer.WriteSBitLong( iDelay , MAX_SOUND_DELAY_MSEC_ENCODE_BITS ); - } - - // don't transmit sounds with high precision - WRITE_DELTA_SINT_SCALE( vOrigin.x, 8.0f, COORD_INTEGER_BITS - 2 ); - WRITE_DELTA_SINT_SCALE( vOrigin.y, 8.0f, COORD_INTEGER_BITS - 2 ); - WRITE_DELTA_SINT_SCALE( vOrigin.z, 8.0f, COORD_INTEGER_BITS - 2 ); - - WRITE_DELTA_SINT( nSpeakerEntity, MAX_EDICT_BITS + 1 ); - } - else - { - ClearStopFields(); - } - }; - - void ReadDelta( SoundInfo_t *delta, bf_read &buffer) - { - if ( !buffer.ReadOneBit() ) - { - nEntityIndex = delta->nEntityIndex; - } - else - { - if ( buffer.ReadOneBit() ) - { - nEntityIndex = buffer.ReadUBitLong( 5 ); - } - else - { - nEntityIndex = buffer.ReadUBitLong( MAX_EDICT_BITS ); - } - } - - READ_DELTA_UINT( nSoundNum, MAX_SOUND_INDEX_BITS ); - - READ_DELTA_UINT( nFlags, SND_FLAG_BITS_ENCODE ); - - READ_DELTA_UINT( nChannel, 3 ); - - bIsAmbient = buffer.ReadOneBit() != 0; - bIsSentence = buffer.ReadOneBit() != 0; // NOTE: SND_STOP behavior is different depending on this flag - - if ( nFlags != SND_STOP ) - { - if ( buffer.ReadOneBit() != 0 ) - { - nSequenceNumber = delta->nSequenceNumber; - } - else if ( buffer.ReadOneBit() != 0 ) - { - nSequenceNumber = delta->nSequenceNumber + 1; - } - else - { - nSequenceNumber = buffer.ReadUBitLong( SOUND_SEQNUMBER_BITS ); - } - - if ( buffer.ReadOneBit() != 0 ) - { - fVolume = (float)buffer.ReadUBitLong( 7 )/127.0f; - } - else - { - fVolume = delta->fVolume; - } - - if ( buffer.ReadOneBit() != 0 ) - { - Soundlevel = (soundlevel_t)buffer.ReadUBitLong( MAX_SNDLVL_BITS ); - } - else - { - Soundlevel = delta->Soundlevel; - } - - READ_DELTA_UINT( nPitch, 8 ); - - - if ( buffer.ReadOneBit() != 0 ) - { - // Up to 4096 msec delay - fDelay = (float)buffer.ReadSBitLong( MAX_SOUND_DELAY_MSEC_ENCODE_BITS ) / 1000.0f; ; - - if ( fDelay < 0 ) - { - fDelay *= 10.0f; - } - // bias results so that we only incur the precision loss on relatively large skipaheads - fDelay -= SOUND_DELAY_OFFSET; - } - else - { - fDelay = delta->fDelay; - } - - READ_DELTA_SINT_SCALE( vOrigin.x, 8.0f, COORD_INTEGER_BITS - 2 ); - READ_DELTA_SINT_SCALE( vOrigin.y, 8.0f, COORD_INTEGER_BITS - 2 ); - READ_DELTA_SINT_SCALE( vOrigin.z, 8.0f, COORD_INTEGER_BITS - 2 ); - - READ_DELTA_SINT( nSpeakerEntity, MAX_EDICT_BITS + 1 ); - } - else - { - ClearStopFields(); - } - } -}; - -struct SpatializationInfo_t -{ - typedef enum - { - SI_INCREATION = 0, - SI_INSPATIALIZATION - } SPATIALIZATIONTYPE; - - // Inputs - SPATIALIZATIONTYPE type; - // Info about the sound, channel, origin, direction, etc. - SoundInfo_t info; - - // Requested Outputs ( NULL == not requested ) - Vector *pOrigin; - QAngle *pAngles; - float *pflRadius; -}; - -#endif // SOUNDINFO_H diff --git a/public/soundsystem/isoundsystem.h b/public/soundsystem/isoundsystem.h deleted file mode 100644 index 240561dcf..000000000 --- a/public/soundsystem/isoundsystem.h +++ /dev/null @@ -1,70 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#ifndef ISOUNDSYSTEM_H -#define ISOUNDSYSTEM_H -#ifdef _WIN32 -#pragma once -#endif - -#include "appframework/iappsystem.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class IAudioDevice; -class CAudioSource; -class CAudioMixer; - - -//----------------------------------------------------------------------------- -// Sound handle -//----------------------------------------------------------------------------- -typedef unsigned short AudioSourceHandle_t; -enum -{ - AUDIOSOURCEHANDLE_INVALID = (AudioSourceHandle_t)~0 -}; - - -//----------------------------------------------------------------------------- -// Flags for FindAudioSource -//----------------------------------------------------------------------------- -enum FindAudioSourceFlags_t -{ - FINDAUDIOSOURCE_NODELAY = 0x1, - FINDAUDIOSOURCE_PREFETCH = 0x2, - FINDAUDIOSOURCE_PLAYONCE = 0x4, -}; - - -//----------------------------------------------------------------------------- -// Purpose: DLL interface for low-level sound utilities -//----------------------------------------------------------------------------- -#define SOUNDSYSTEM_INTERFACE_VERSION "SoundSystem001" - -abstract_class ISoundSystem : public IAppSystem -{ -public: - virtual void Update( float time ) = 0; - virtual void Flush( void ) = 0; - - virtual CAudioSource *FindOrAddSound( const char *filename ) = 0; - virtual CAudioSource *LoadSound( const char *wavfile ) = 0; - - virtual void PlaySound( CAudioSource *source, float volume, CAudioMixer **ppMixer ) = 0; - - virtual bool IsSoundPlaying( CAudioMixer *pMixer ) = 0; - virtual CAudioMixer *FindMixer( CAudioSource *source ) = 0; - - virtual void StopAll( void ) = 0; - virtual void StopSound( CAudioMixer *mixer ) = 0; -}; - - - -#endif // ISOUNDSYSTEM_H diff --git a/public/soundsystem/snd_audio_source.h b/public/soundsystem/snd_audio_source.h deleted file mode 100644 index a455581f0..000000000 --- a/public/soundsystem/snd_audio_source.h +++ /dev/null @@ -1,101 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//===========================================================================// - -#ifndef SND_AUDIO_SOURCE_H -#define SND_AUDIO_SOURCE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/platform.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class CAudioSource; -class IAudioDevice; -struct channel_t; - - -//----------------------------------------------------------------------------- -// Purpose: This is an instance of an audio source. -// Mixers are attached to channels and reference an audio source. -// Mixers are specific to the sample format and source format. -// Mixers are never re-used, so they can track instance data like -// sample position, fractional sample, stream cache, faders, etc. -//----------------------------------------------------------------------------- -abstract_class CAudioMixer -{ -public: - virtual ~CAudioMixer( void ) {} - - // UNDONE: time compress - virtual bool MixDataToDevice( IAudioDevice *pDevice, channel_t *pChannel, int startSample, int sampleCount, int outputRate, bool forward = true ) = 0; - virtual void IncrementSamples( channel_t *pChannel, int startSample, int sampleCount,int outputRate, bool forward = true ) = 0; - virtual bool SkipSamples( IAudioDevice *pDevice, channel_t *pChannel, int startSample, int sampleCount, int outputRate, bool forward = true ) = 0; - - virtual CAudioSource *GetSource( void ) = 0; - - virtual int GetSamplePosition( void ) = 0; - virtual int GetScubPosition( void ) = 0; - - virtual bool SetSamplePosition( int position, bool scrubbing = false ) = 0; - virtual void SetLoopPosition( int position ) = 0; - virtual int GetStartPosition( void ) = 0; - - virtual bool GetActive( void ) = 0; - virtual void SetActive( bool active ) = 0; - - virtual void SetModelIndex( int index ) = 0; - virtual int GetModelIndex( void ) const = 0; - - virtual void SetDirection( bool forward ) = 0; - virtual bool GetDirection( void ) const = 0; - - virtual void SetAutoDelete( bool autodelete ) = 0; - virtual bool GetAutoDelete( void ) const = 0; - - virtual void SetVolume( float volume ) = 0; - virtual channel_t *GetChannel() = 0; -}; - -//----------------------------------------------------------------------------- -// Purpose: A source is an abstraction for a stream, cached file, or procedural -// source of audio. -//----------------------------------------------------------------------------- -class CSentence; - -abstract_class CAudioSource -{ -public: - CAudioSource( void ); - virtual ~CAudioSource( void ); - - // Create an instance (mixer) of this audio source - virtual CAudioMixer *CreateMixer( void ) = 0; - virtual int GetOutputData( void **pData, int samplePosition, int sampleCount, bool forward = true ) = 0; - virtual int SampleRate( void ) = 0; - virtual int SampleSize( void ) = 0; - virtual int SampleCount( void ) = 0; - virtual float TrueSampleSize( void ) = 0; - virtual bool IsLooped( void ) = 0; - virtual bool IsStreaming( void ) = 0; - virtual float GetRunningLength( void ) = 0; - virtual int GetNumChannels() = 0; - - virtual CSentence *GetSentence( void ) { return NULL; }; - -}; - - -extern CAudioSource *AudioSource_Create( const char *pName ); - -#endif // SND_AUDIO_SOURCE_H diff --git a/public/soundsystem/snd_device.h b/public/soundsystem/snd_device.h deleted file mode 100644 index 76981d06e..000000000 --- a/public/soundsystem/snd_device.h +++ /dev/null @@ -1,105 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//===========================================================================// - -#ifndef SND_DEVICE_H -#define SND_DEVICE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/platform.h" - -//----------------------------------------------------------------------------- -// 4.28 fixed point stuff for real-time resampling -//----------------------------------------------------------------------------- -#define FIX_BITS 28 -#define FIX_SCALE (1 << FIX_BITS) -#define FIX_MASK ((1 << FIX_BITS)-1) -#define FIX_FLOAT(a) ((int)((a) * FIX_SCALE)) -#define FIX(a) (((int)(a)) << FIX_BITS) -#define FIX_INTPART(a) (((int)(a)) >> FIX_BITS) -#define FIX_FRACTION(a,b) (FIX(a)/(b)) -#define FIX_FRACPART(a) ((a) & FIX_MASK) - -typedef unsigned int fixedint; - - -//----------------------------------------------------------------------------- -// sound rate defines -//----------------------------------------------------------------------------- -#define SOUND_DMA_SPEED 44100 // hardware playback rate -#define SOUND_11k 11025 // 11khz sample rate -#define SOUND_22k 22050 // 22khz sample rate -#define SOUND_44k 44100 // 44khz sample rate -#define SOUND_ALL_RATES 1 // mix all sample rates - - -//----------------------------------------------------------------------------- -// Information about the channel -//----------------------------------------------------------------------------- -struct channel_t -{ - int leftvol; - int rightvol; - float pitch; -}; - - -//----------------------------------------------------------------------------- -// The audio device is responsible for mixing -//----------------------------------------------------------------------------- -abstract_class IAudioDevice -{ -public: - // This initializes the sound hardware. true on success, false on failure - virtual bool Init( void ) = 0; - - // This releases all sound hardware - virtual void Shutdown( void ) = 0; - - // device parameters - virtual const char *DeviceName( void ) const = 0; - virtual int DeviceChannels( void ) const = 0; // 1 = mono, 2 = stereo - virtual int DeviceSampleBits( void ) const = 0; // bits per sample (8 or 16) - virtual int DeviceSampleBytes( void ) const = 0; // above / 8 - virtual int DeviceSampleRate( void ) const = 0; // Actual DMA speed - virtual int DeviceSampleCount( void ) const = 0; // Total samples in buffer - - // Called each time a new paint buffer is mixed (may be multiple times per frame) - virtual void MixBegin( void ) = 0; - - // Main mixing routines - virtual void Mix8Mono( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress, bool forward = true ) = 0; - virtual void Mix8Stereo( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress, bool forward = true ) = 0; - virtual void Mix16Mono( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress, bool forward = true ) = 0; - virtual void Mix16Stereo( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress, bool forward = true ) = 0; - - // Size of the paint buffer in samples - virtual int PaintBufferSampleCount( void ) const = 0; - - // Adds a mixer to be mixed - virtual void AddSource( CAudioMixer *pSource ) = 0; - - // Stops all sounds - virtual void StopSounds( void ) = 0; - - // Updates sound mixing - virtual void Update( float time ) = 0; - - // Resets the device - virtual void Flush( void ) = 0; - - virtual int FindSourceIndex( CAudioMixer *pSource ) = 0; - virtual CAudioMixer *GetMixerForSource( CAudioSource *source ) = 0; - virtual void FreeChannel( int channelIndex ) = 0; -}; - - -#endif // SND_DEVICE_H diff --git a/public/stdstring.h b/public/stdstring.h deleted file mode 100644 index 91f47dd5c..000000000 --- a/public/stdstring.h +++ /dev/null @@ -1,86 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#include "isaverestore.h" - -#ifndef STDSTRING_H -#define STDSTRING_H - -#if defined( _WIN32 ) -#pragma once -#endif - -#ifdef _WIN32 -#pragma warning(push) -#include // warnings get enabled in yvals.h -#pragma warning(disable:4663) -#pragma warning(disable:4530) -#pragma warning(disable:4245) -#pragma warning(disable:4018) -#pragma warning(disable:4511) -#endif - -#include - -#ifdef _WIN32 -#pragma warning(pop) -#endif - -class CStdStringSaveRestoreOps : public CDefSaveRestoreOps -{ -public: - enum - { - MAX_SAVE_LEN = 4096, - }; - - // save data type interface - virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave ) - { - std::string *pString = (std::string *)fieldInfo.pField; - Assert( pString->length() < MAX_SAVE_LEN - 1 ); - if ( pString->length() < MAX_SAVE_LEN - 1 ) - pSave->WriteString( pString->c_str() ); - else - pSave->WriteString( "<>" ); - } - - virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore ) - { - std::string *pString = (std::string *)fieldInfo.pField; - char szString[MAX_SAVE_LEN]; - pRestore->ReadString( szString, sizeof(szString), 0 ); - szString[MAX_SAVE_LEN - 1] = 0; - pString->assign( szString ); - } - - virtual void MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - std::string *pString = (std::string *)fieldInfo.pField; - pString->erase(); - } - - virtual bool IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) - { - std::string *pString = (std::string *)fieldInfo.pField; - return pString->empty(); - } -}; - -//------------------------------------- - -inline ISaveRestoreOps *GetStdStringDataOps() -{ - static CStdStringSaveRestoreOps ops; - return &ops; -} - -//------------------------------------- - -#define DEFINE_STDSTRING(name) \ - { FIELD_CUSTOM, #name, { offsetof(classNameTypedef,name), 0 }, 1, FTYPEDESC_SAVE, NULL, GetStdStringDataOps(), NULL } - -#endif // STDSTRING_H diff --git a/public/steam/isteamapps.h b/public/steam/isteamapps.h deleted file mode 100644 index 104d97bdc..000000000 --- a/public/steam/isteamapps.h +++ /dev/null @@ -1,39 +0,0 @@ -//====== Copyright 1996-2007, Valve Corporation, All rights reserved. ======= -// -// Purpose: interface to app data in Steam -// -//============================================================================= - -#ifndef ISTEAMAPPS_H -#define ISTEAMAPPS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "steam/isteamapps.h" - -//----------------------------------------------------------------------------- -// Purpose: interface to app data -//----------------------------------------------------------------------------- -class ISteamApps -{ -public: - // returns 0 if the key does not exist - // this may be true on first call, since the app data may not be cached locally yet - // If you expect it to exists wait for the AppDataChanged_t after the first failure and ask again - virtual int GetAppData( uint32 nAppID, const char *pchKey, char *pchValue, int cchValueMax ) = 0; -}; - -#define STEAMAPPS_INTERFACE_VERSION "STEAMAPPS_INTERFACE_VERSION001" - -//----------------------------------------------------------------------------- -// Purpose: called when new information about an app has arrived -//----------------------------------------------------------------------------- -struct AppDataChanged_t -{ - enum { k_iCallback = k_iSteamAppsCallbacks + 1 }; - uint32 m_nAppID; - bool m_bWebDataChanged; -}; - -#endif // ISTEAMAPPS_H diff --git a/public/steam/isteamclient.h b/public/steam/isteamclient.h deleted file mode 100644 index 200007fb5..000000000 --- a/public/steam/isteamclient.h +++ /dev/null @@ -1,137 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef ISTEAMCLIENT_H -#define ISTEAMCLIENT_H -#ifdef _WIN32 -#pragma once -#endif - -#include "steamtypes.h" -#include "steamclientpublic.h" - -// handle to a communication pipe to the Steam client -typedef int32 HSteamPipe; -// handle to single instance of a steam user -typedef int32 HSteamUser; - -#ifndef DLL_EXPORT -#define DLL_EXPORT -#endif - -// interface predec -class ISteamUser; -class ISteamGameServer; -class ISteamFriends; -class ISteamUtils; -class ISteamMatchmaking; -class ISteamContentServer; -class ISteamMasterServerUpdater; -class ISteamMatchmakingServers; -class ISteam2Bridge; -class ISteamUserStats; -class ISteamApps; - -//----------------------------------------------------------------------------- -// Purpose: Interface to creating a new steam instance, or to -// connect to an existing steam instance, whether it's in a -// different process or is local -//----------------------------------------------------------------------------- -class ISteamClient -{ -public: - // Creates a communication pipe to the Steam client - virtual HSteamPipe CreateSteamPipe() = 0; - - // Releases a previously created communications pipe - virtual bool BReleaseSteamPipe( HSteamPipe hSteamPipe ) = 0; - - // connects to an existing global user, failing if none exists - // used by the game to coordinate with the steamUI - virtual HSteamUser ConnectToGlobalUser( HSteamPipe hSteamPipe ) = 0; - - // used by game servers, create a steam user that won't be shared with anyone else - virtual HSteamUser CreateLocalUser( HSteamPipe *phSteamPipe ) = 0; - - // removes an allocated user - virtual void ReleaseUser( HSteamPipe hSteamPipe, HSteamUser hUser ) = 0; - - // retrieves the ISteamUser interface associated with the handle - virtual ISteamUser *GetISteamUser( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0; - - // retrieves the ISteamGameServer interface associated with the handle - virtual ISteamGameServer *GetISteamGameServer( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0; - - // set the local IP and Port to bind to - // this must be set before CreateLocalUser() - virtual void SetLocalIPBinding( uint32 unIP, uint16 usPort ) = 0; - - // returns the ISteamFriends interface - virtual ISteamFriends *GetISteamFriends( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0; - - // returns the ISteamUtils interface - virtual ISteamUtils *GetISteamUtils( HSteamPipe hSteamPipe, const char *pchVersion ) = 0; - - // returns the ISteamMatchmaking interface - virtual ISteamMatchmaking *GetISteamMatchmaking( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0; - - // returns the ISteamContentServer interface - virtual ISteamContentServer *GetISteamContentServer( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0; - - // returns the ISteamMasterServerUpdater interface - virtual ISteamMasterServerUpdater *GetISteamMasterServerUpdater( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0; - - // returns the ISteamMatchmakingServers interface - virtual ISteamMatchmakingServers *GetISteamMatchmakingServers( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0; - - // returns the ISteam2Bridge interface - virtual ISteam2Bridge *GetISteam2Bridge( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0; - - virtual void RunFrame() = 0; - - // returns the number of IPC calls made since the last time this function was called - // Used for perf debugging so you can understand how many IPC calls your game makes per frame - // Every IPC call is at minimum a thread context switch if not a process one so you want to rate - // control how often you do them. - virtual uint32 GetIPCCallCount() = 0; - - // returns the ISteamUserStats interface - virtual ISteamUserStats *GetISteamUserStats( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0; - - // returns apps interface - virtual ISteamApps *GetISteamApps( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0; -}; - -#define STEAMCLIENT_INTERFACE_VERSION "SteamClient007" - -//----------------------------------------------------------------------------- -// Purpose: Base values for callback identifiers, each callback must -// have a unique ID. -//----------------------------------------------------------------------------- -enum { k_iSteamUserCallbacks = 100 }; -enum { k_iSteamGameServerCallbacks = 200 }; -enum { k_iSteamFriendsCallbacks = 300 }; -enum { k_iSteamBillingCallbacks = 400 }; -enum { k_iSteamMatchmakingCallbacks = 500 }; -enum { k_iSteamContentServerCallbacks = 600 }; -enum { k_iSteamUtilsCallbacks = 700 }; -enum { k_iClientFriendsCallbacks = 800 }; -enum { k_iClientUserCallbacks = 900 }; -enum { k_iSteamAppsCallbacks = 1000 }; -enum { k_iSteamUserStatsCallbacks = 1100 }; - -// For GoldSRC we need a C API as the C++ ABI changed from the GoldSRC compiler -// (GCC 2.95.3) to the Source/Steam3 one (GCC 3.4.1) -// C functions we export for the C API, maps to ISteamClient functions -DLL_EXPORT HSteamPipe Steam_CreateSteamPipe(); -DLL_EXPORT bool Steam_BReleaseSteamPipe( HSteamPipe hSteamPipe ); -DLL_EXPORT HSteamUser Steam_CreateLocalUser( HSteamPipe *phSteamPipe ); -DLL_EXPORT HSteamUser Steam_ConnectToGlobalUser( HSteamPipe hSteamPipe ); -DLL_EXPORT void Steam_ReleaseUser( HSteamPipe hSteamPipe, HSteamUser hUser ); -DLL_EXPORT void Steam_SetLocalIPBinding( uint32 unIP, uint16 usLocalPort ); - - -#endif // ISTEAMCLIENT_H diff --git a/public/steam/isteamfriends.h b/public/steam/isteamfriends.h deleted file mode 100644 index b6db70dea..000000000 --- a/public/steam/isteamfriends.h +++ /dev/null @@ -1,168 +0,0 @@ - -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: interface to friends data in Steam -// -//============================================================================= - -#ifndef ISTEAMFRIENDS_H -#define ISTEAMFRIENDS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "isteamclient.h" - -//----------------------------------------------------------------------------- -// Purpose: set of relationships to other users -//----------------------------------------------------------------------------- -// WARNING: DO NOT RENUMBER EXISTING VALUES - STORED IN DATABASE -enum EFriendRelationship -{ - k_EFriendRelationshipNone = 0, - k_EFriendRelationshipBlocked = 1, - k_EFriendRelationshipRequestRecipient = 2, - k_EFriendRelationshipFriend = 3, - k_EFriendRelationshipRequestInitiator = 4, -}; - - -//----------------------------------------------------------------------------- -// Purpose: list of states a friend can be in -//----------------------------------------------------------------------------- -enum EPersonaState -{ - k_EPersonaStateOffline = 0, // friend is not currently logged on - k_EPersonaStateOnline = 1, // friend is logged on - k_EPersonaStateBusy = 2, // user is on, but busy - k_EPersonaStateAway = 3, // auto-away feature - k_EPersonaStateSnooze = 4, // auto-away for a long time - k_EPersonaStateMax, -}; - - -// for enumerating friends list -enum k_EFriendFlags -{ - k_EFriendFlagNone = 0x00, - k_EFriendFlagBlocked = 0x01, - k_EFriendFlagFriendshipRequested = 0x02, - k_EFriendFlagImmediate = 0x04, // "regular" friend - k_EFriendFlagClanMember = 0x08, - k_EFriendFlagOnGameServer = 0x10, - // k_EFriendFlagHasPlayedWith = 0x20, - // k_EFriendFlagFriendOfFriend = 0x40, - k_EFriendFlagRequestingFriendship = 0x80, - k_EFriendFlagRequestingInfo = 0x100, - k_EFriendFlagAll = 0xFFFF, -}; - - -enum { k_cchPersonaNameMax = 128 }; - -// size limit on chat room or member metadata -const uint32 k_cubChatMetadataMax = 4096; - -//----------------------------------------------------------------------------- -// Purpose: interface to friends -//----------------------------------------------------------------------------- -class ISteamFriends -{ -public: - // returns the local players name - guaranteed to not be NULL. - virtual const char *GetPersonaName() = 0; - // sets the player name, stores it on the server and publishes the changes to all friends who are online - virtual void SetPersonaName( const char *pchPersonaName ) = 0; - // gets the friend status of the current user - virtual EPersonaState GetPersonaState() = 0; - - // friend iteration - virtual int GetFriendCount( int iFriendFlags ) = 0; - virtual CSteamID GetFriendByIndex( int iFriend, int iFriendFlags ) = 0; - - // gets the relationship to a user - virtual EFriendRelationship GetFriendRelationship( CSteamID steamIDFriend ) = 0; - // returns true if the specified user is considered a friend (can see our online status) - virtual EPersonaState GetFriendPersonaState( CSteamID steamIDFriend ) = 0; - // returns the name of a friend - guaranteed to not be NULL. - virtual const char *GetFriendPersonaName( CSteamID steamIDFriend ) = 0; - // gets the avatar of the current user, which is a handle to be used in IClientUtils::GetImageRGBA(), or 0 if none set - virtual int GetFriendAvatar( CSteamID steamIDFriend ) = 0; - // returns true if the friend is actually in a game - virtual bool GetFriendGamePlayed( CSteamID steamIDFriend, uint64 *pulGameID, uint32 *punGameIP, uint16 *pusGamePort, uint16 *pusQueryPort ) = 0; - // accesses old friends names - returns an empty string when their are no more items in the history - virtual const char *GetFriendPersonaNameHistory( CSteamID steamIDFriend, int iPersonaName ) = 0; - - // returns true if the specified user is considered a friend - virtual bool HasFriend( CSteamID steamIDFriend, int iFriendFlags ) = 0; - - // clan functions - virtual int GetClanCount() = 0; - virtual CSteamID GetClanByIndex( int iClan ) = 0; - virtual const char *GetClanName( CSteamID steamIDClan ) = 0; - - // iterators for any source - virtual int GetFriendCountFromSource( CSteamID steamIDSource ) = 0; - virtual CSteamID GetFriendFromSourceByIndex( CSteamID steamIDSource, int iFriend ) = 0; - virtual bool IsUserInSource( CSteamID steamIDUser, CSteamID steamIDSource ) = 0; - - // User is in a game pressing the talk button (will suppress the microphone for all voice comms from the Steam friends UI) - virtual void SetInGameVoiceSpeaking( CSteamID steamIDUser, bool bSpeaking ) = 0; - - // activates the game overlay, with an optional dialog to open ("Friends", "Community", "Players", "Settings") - virtual void ActivateGameOverlay( const char *pchDialog ) = 0; -}; - -#define STEAMFRIENDS_INTERFACE_VERSION "SteamFriends003" - -//----------------------------------------------------------------------------- -// Purpose: called when a friends' status changes -//----------------------------------------------------------------------------- -struct PersonaStateChange_t -{ - enum { k_iCallback = k_iSteamFriendsCallbacks + 4 }; - - uint64 m_ulSteamID; // steamID of the friend who changed - int m_nChangeFlags; // what's changed -}; - - -// used in PersonaStateChange_t::m_nChangeFlags to describe what's changed about a user -// these flags describe what the client has learned has changed recently, so on startup you'll see a name, avatar & relationship change for every friend -enum EPersonaChange -{ - k_EPersonaChangeName = 0x001, - k_EPersonaChangeStatus = 0x002, - k_EPersonaChangeComeOnline = 0x004, - k_EPersonaChangeGoneOffline = 0x008, - k_EPersonaChangeGamePlayed = 0x010, - k_EPersonaChangeGameServer = 0x020, - k_EPersonaChangeAvatar = 0x040, - k_EPersonaChangeJoinedSource= 0x080, - k_EPersonaChangeLeftSource = 0x100, - k_EPersonaChangeRelationshipChanged = 0x200, - k_EPersonaChangeNameFirstSet = 0x400, -}; - - -//----------------------------------------------------------------------------- -// Purpose: posted when game overlay activates or deactivates -//----------------------------------------------------------------------------- -struct GameOverlayActivated_t -{ - enum { k_iCallback = k_iSteamFriendsCallbacks + 31 }; - uint8 m_bActive; // true if it's just been activated, false otherwise -}; - - -//----------------------------------------------------------------------------- -// Purpose: called when the user tries to join a different game server from their friends list -//----------------------------------------------------------------------------- -struct GameServerChangeRequested_t -{ - enum { k_iCallback = k_iSteamFriendsCallbacks + 32 }; - char m_rgchServer[64]; // server address ("127.0.0.1:27015", "tf2.valvesoftware.com") - char m_rgchPassword[64]; // server password, if any -}; - -#endif // ISTEAMFRIENDS_H diff --git a/public/steam/isteammatchmaking.h b/public/steam/isteammatchmaking.h deleted file mode 100644 index 1c80ea430..000000000 --- a/public/steam/isteammatchmaking.h +++ /dev/null @@ -1,300 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: interface to steam managing game server/client match making -// -//============================================================================= -#ifndef ISTEAMMATCHMAKING -#define ISTEAMMATCHMAKING -#ifdef _WIN32 -#pragma once -#endif - -#include "steamtypes.h" -#include "steamclientpublic.h" -#include "matchmakingtypes.h" -#include "isteamclient.h" -#include "isteamfriends.h" - -// 32KB max size on chat messages -enum { k_cchFriendChatMsgMax = 32 * 1024 }; - -//----------------------------------------------------------------------------- -// Purpose: Functions for match making services for clients to get to favorites -//----------------------------------------------------------------------------- -class ISteamMatchmaking -{ -public: - virtual int GetFavoriteGameCount() = 0; - - // Obsolete. Use the ...2 versions of these functions, which take separate connection and query ports. - virtual bool GetFavoriteGame( int iGame, uint32 *pnAppID, uint32 *pnIP, uint16 *pnConnPort, uint32 *punFlags, uint32 *pRTime32LastPlayedOnServer ) = 0; - virtual int AddFavoriteGame( uint32 nAppID, uint32 nIP, uint16 nConnPort, uint32 unFlags, uint32 rTime32LastPlayedOnServer ) =0; - virtual bool RemoveFavoriteGame( uint32 nAppID, uint32 nIP, uint16 nConnPort, uint32 unFlags ) = 0; - - - // returns the details of the game server - // iGame is of range [0,iGame) - virtual bool GetFavoriteGame2( int iGame, uint32 *pnAppID, uint32 *pnIP, uint16 *pnConnPort, uint16 *pnQueryPort, uint32 *punFlags, uint32 *pRTime32LastPlayedOnServer ) = 0; - - // returns the new index of the game - virtual int AddFavoriteGame2( uint32 nAppID, uint32 nIP, uint16 nConnPort, uint16 nQueryPort, uint32 unFlags, uint32 rTime32LastPlayedOnServer ) =0; - - // removes the game; returns true if one was removed - virtual bool RemoveFavoriteGame2( uint32 nAppID, uint32 nIP, uint16 nConnPort, uint16 nQueryPort, uint32 unFlags ) = 0; - - /////// - // Game lobby functions - - // Get a list of relevant lobbies - virtual void RequestLobbyList( uint64 ulGameID, MatchMakingKeyValuePair_t *pFilters, uint32 nFilters ) = 0; - virtual CSteamID GetLobbyByIndex( int iLobby ) = 0; - // Create a lobby - you'll get the SteamID of it on success - virtual void CreateLobby( uint64 ulGameID, bool bPrivate ) = 0; - // Join a lobby - virtual void JoinLobby( CSteamID steamIDLobby ) = 0; - // Leave a lobby - virtual void LeaveLobby( CSteamID steamIDLobby ) = 0; - // Invite someone to the lobby - virtual bool InviteUserToLobby( CSteamID steamIDLobby, CSteamID steamIDInvitee ) = 0; - // List users in this lobby - virtual int GetNumLobbyMembers( CSteamID steamIDLobby ) = 0; - virtual CSteamID GetLobbyMemberByIndex( CSteamID steamIDLobby, int iMember ) = 0; - // Get data associated with this lobby - virtual const char *GetLobbyData( CSteamID SteamIDLobby, const char *pchKey ) = 0; - // Update lobby data (Admin only) - virtual void SetLobbyData( CSteamID steamIDLobby, const char *pchKey, const char *pchValue ) = 0; - // Get per-user data for someone in this lobby - virtual const char *GetLobbyMemberData( CSteamID steamIDLobby, CSteamID steamIDUser, const char *pchKey ) = 0; - // Update user data (for you only) - virtual void SetLobbyMemberData( CSteamID steamIDLobby, const char *pchKey, const char *pchValue ) = 0; - // change the lobby Admin (Admin only) - virtual void ChangeLobbyAdmin( CSteamID steamIDLobby, CSteamID steamIDNewAdmin ) = 0; - // Send a chat message to the lobby - virtual bool SendLobbyChatMsg( CSteamID steamIDLobby, const void *pvMsgBody, int cubMsgBody ) = 0; - // Get a chat message entry - virtual int GetLobbyChatEntry( CSteamID steamIDLobby, int iChatID, CSteamID *pSteamIDUser, void *pvData, int cubData, EChatEntryType *peChatEntryType ) = 0; - -}; -#define STEAMMATCHMAKING_INTERFACE_VERSION "SteamMatchMaking001" - - -//----------------------------------------------------------------------------- -// Purpose: Callback interfaces for server list functions -//----------------------------------------------------------------------------- -class ISteamMatchmakingServerListResponse -{ -public: - virtual void ServerResponded( int iServer ) = 0; - virtual void ServerFailedToRespond( int iServer ) = 0; - virtual void RefreshComplete( EMatchMakingServerResponse response ) = 0; -}; - -class ISteamMatchmakingPingResponse -{ -public: - virtual void ServerResponded( gameserveritem_t &server ) = 0; - virtual void ServerFailedToRespond() = 0; -}; - -class ISteamMatchmakingPlayersResponse -{ -public: - virtual void AddPlayerToList( const char *pchName, int nScore, float flTimePlayed ) = 0; - virtual void PlayersFailedToRespond() = 0; - virtual void PlayersRefreshComplete() = 0; -}; - - -class ISteamMatchmakingRulesResponse -{ -public: - virtual void RulesResponded( const char *pchRule, const char *pchValue ) = 0; - virtual void RulesFailedToRespond() = 0; - virtual void RulesRefreshComplete() = 0; -}; - -typedef int HServerQuery; -const int HSERVERQUERY_INVALID = 0xffffffff; - -//----------------------------------------------------------------------------- -// Purpose: Functions for match making services for clients to get to game servers -//----------------------------------------------------------------------------- -class ISteamMatchmakingServers -{ -public: - // request a new list of servers of a particular type - virtual void RequestInternetServerList( uint32 iApp, MatchMakingKeyValuePair_t **ppchFilters, uint32 nFilters, ISteamMatchmakingServerListResponse *pRequestServersResponse ) = 0; - virtual void RequestLANServerList( uint32 iApp, ISteamMatchmakingServerListResponse *pRequestServersResponse ) = 0; - virtual void RequestFriendsServerList( uint32 iApp, MatchMakingKeyValuePair_t **ppchFilters, uint32 nFilters, ISteamMatchmakingServerListResponse *pRequestServersResponse ) = 0; - virtual void RequestFavoritesServerList( uint32 iApp, MatchMakingKeyValuePair_t **ppchFilters, uint32 nFilters, ISteamMatchmakingServerListResponse *pRequestServersResponse ) = 0; - virtual void RequestHistoryServerList( uint32 iApp, MatchMakingKeyValuePair_t **ppchFilters, uint32 nFilters, ISteamMatchmakingServerListResponse *pRequestServersResponse ) = 0; - virtual void RequestSpectatorServerList( uint32 iApp, MatchMakingKeyValuePair_t **ppchFilters, uint32 nFilters, ISteamMatchmakingServerListResponse *pRequestServersResponse ) = 0; - - virtual gameserveritem_t *GetServerDetails( EMatchMakingType eType, int iServer ) = 0; - - virtual void CancelQuery( EMatchMakingType eType ) = 0; // stop getting new servers from an earlier query - virtual void RefreshQuery( EMatchMakingType eType ) = 0; // ping every server in your list again but don't update the list of servers - virtual bool IsRefreshing( EMatchMakingType eType ) = 0; // returns true if the list is currently refreshing its server list - virtual int GetServerCount( EMatchMakingType eType ) = 0; // how many servers in this list, GetServerDetails takes 0... GetServerCount() - 1 - virtual void RefreshServer( EMatchMakingType eType, int iServer ) = 0; // refresh a single server inside of a query (rather than all the servers ) - - // queries to individual servers - virtual HServerQuery PingServer( uint32 unIP, uint16 usPort, ISteamMatchmakingPingResponse *pRequestServersResponse ) = 0; // request details from a single server - virtual HServerQuery PlayerDetails( uint32 unIP, uint16 usPort, ISteamMatchmakingPlayersResponse *pRequestServersResponse ) = 0; // get a list of players from a server - virtual HServerQuery ServerRules( uint32 unIP, uint16 usPort, ISteamMatchmakingRulesResponse *pRequestServersResponse ) = 0; // get the rules that server is running - virtual void CancelServerQuery( HServerQuery hServerQuery ) = 0; // cancel an outstanding query from above -}; -#define STEAMMATCHMAKINGSERVERS_INTERFACE_VERSION "SteamMatchMakingServers001" - -//----------------------------------------------------------------------------- -// Callbacks -//----------------------------------------------------------------------------- - -// game server flags -const uint32 k_unFavoriteFlagNone = 0x00; -const uint32 k_unFavoriteFlagFavorite = 0x01; // this game favorite entry is for the favorites list -const uint32 k_unFavoriteFlagHistory = 0x02; // this game favorite entry is for the history list - -// callbacks - - -// a server was added/removed from the favorites list, you should refresh now -struct FavoritesListChanged_t -{ - enum { k_iCallback = k_iSteamMatchmakingCallbacks + 2 }; // +2 as +1 was a previous version of this call with a different layout - uint32 m_nIP; // an IP of 0 means reload the whole list, any other value means just one server - uint32 m_nQueryPort; - uint32 m_nConnPort; - uint32 m_nAppID; - uint32 m_nFlags; - bool m_bAdd; // true if this is adding the entry, otherwise it is a remove -}; - -//----------------------------------------------------------------------------- -// Purpose: Someone has invited you to join a Lobby -//----------------------------------------------------------------------------- -struct LobbyInvite_t -{ - enum { k_iCallback = k_iSteamMatchmakingCallbacks + 3 }; - - uint64 m_ulSteamIDUser; // Steam ID of the person making the invite - uint64 m_ulSteamIDLobby; // Steam ID of the Lobby -}; - -//----------------------------------------------------------------------------- -// Purpose: You have entered a Lobby -//----------------------------------------------------------------------------- -struct LobbyEnter_t -{ - enum { k_iCallback = k_iSteamMatchmakingCallbacks + 4 }; - - uint64 m_ulSteamIDLobby; // SteamID of the Lobby you have entered - uint32 m_rgfChatPermissions; // Permissions of the current user - bool m_bLocked; // If true, then only invited users may join - uint32 m_EChatRoomEnterResponse; // EChatRoomEnterResponse -}; - -//----------------------------------------------------------------------------- -// Purpose: The lobby data has changed -//----------------------------------------------------------------------------- -struct LobbyDataUpdate_t -{ - enum { k_iCallback = k_iSteamMatchmakingCallbacks + 5 }; - - uint64 m_ulSteamIDLobby; // steamID of the Lobby - uint64 m_ulSteamIDMember; // steamID of the member whose data changed, or the room itself -}; - - -//----------------------------------------------------------------------------- -// Purpose: The lobby chat room state has changed -//----------------------------------------------------------------------------- -struct LobbyChatUpdate_t -{ - enum { k_iCallback = k_iSteamMatchmakingCallbacks + 6 }; - - uint64 m_ulSteamIDLobby; // Lobby ID - uint64 m_ulSteamIDUserChanged; // user who's status in the lobby just changed - can be recipient - uint64 m_ulSteamIDMakingChange; // Chat member who made the change (different from SteamIDUserChange if kicking, muting, etc.) - uint32 m_rgfChatMemberStateChange; // bitfield of EChatMemberStateChange values -}; - -//----------------------------------------------------------------------------- -// Purpose: A chat message for this lobby -//----------------------------------------------------------------------------- -struct LobbyChatMsg_t -{ - enum { k_iCallback = k_iSteamMatchmakingCallbacks + 7 }; - - uint64 m_ulSteamIDLobby; // the lobby id this is in - uint64 m_ulSteamIDUser; // steamID of the user who has sent this message - uint8 m_eChatEntryType; // type of message - uint32 m_iChatID; // index of the chat entry to lookup -}; - -//----------------------------------------------------------------------------- -// Purpose: There's a change of Admin in this Lobby -//----------------------------------------------------------------------------- -struct LobbyAdminChange_t -{ - enum { k_iCallback = k_iSteamMatchmakingCallbacks + 8 }; - - uint64 m_ulSteamIDLobby; - uint64 m_ulSteamIDNewAdmin; -}; - - -//----------------------------------------------------------------------------- -// Purpose: The Admin of a Lobby has created a game to join -//----------------------------------------------------------------------------- -struct LobbyGameCreated_t -{ - enum { k_iCallback = k_iSteamMatchmakingCallbacks + 9 }; - - uint64 m_ulSteamIDLobby; - uint32 m_unIP; - uint16 m_usPort; -}; - -//----------------------------------------------------------------------------- -// Purpose: Number of matching lobbies found, iterate with GetLobbyByIndex -//----------------------------------------------------------------------------- -struct LobbyMatchList_t -{ - enum { k_iCallback = k_iSteamMatchmakingCallbacks + 10 }; - uint32 m_nLobbiesMatching; // Number of lobbies that matched search criteria and we have SteamIDs for -}; - - -//----------------------------------------------------------------------------- -// Purpose: The Lobby is closing -//----------------------------------------------------------------------------- -struct LobbyClosing_t -{ - enum { k_iCallback = k_iSteamMatchmakingCallbacks + 11 }; - uint64 m_ulSteamIDLobby; // Lobby -}; - - -//----------------------------------------------------------------------------- -// Purpose: You have been kicked from the lobby -//----------------------------------------------------------------------------- -struct LobbyKicked_t -{ - enum { k_iCallback = k_iSteamMatchmakingCallbacks + 12 }; - uint64 m_ulSteamIDLobby; // Lobby - uint64 m_ulSteamIDAdmin; // User who kicked you -}; - - -//----------------------------------------------------------------------------- -// Purpose: Result of our request to create a Lobby -//----------------------------------------------------------------------------- -struct LobbyCreate_t -{ - enum { k_iCallback = k_iSteamMatchmakingCallbacks + 13 }; - EResult m_eResult; // Result - uint64 m_ulSteamIDLobby; // chat room, zero if failed -}; - -#endif // ISTEAMMATCHMAKING diff --git a/public/steam/isteamuser.h b/public/steam/isteamuser.h deleted file mode 100644 index 3c588e1ed..000000000 --- a/public/steam/isteamuser.h +++ /dev/null @@ -1,174 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: interface to user account information in Steam -// -//============================================================================= - -#ifndef ISTEAMUSER_H -#define ISTEAMUSER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "isteamclient.h" - -// structure that contains client callback data -struct CallbackMsg_t -{ - HSteamUser m_hSteamUser; - int m_iCallback; - uint8 *m_pubParam; - int m_cubParam; -}; - -// reference to a steam call, to filter results by -typedef int32 HSteamCall; - -enum ERegistrySubTree -{ - k_ERegistrySubTreeNews = 0, - k_ERegistrySubTreeApps = 1, - k_ERegistrySubTreeSubscriptions = 2, - k_ERegistrySubTreeGameServers = 3, - k_ERegistrySubTreeFriends = 4, - k_ERegistrySubTreeSystem = 5, -}; - -enum EAppUsageEvent -{ - k_EAppUsageEventGameLaunch = 1, - k_EAppUsageEventGameLaunchTrial = 2, - k_EAppUsageEventMedia = 3, - k_EAppUsageEventPreloadStart = 4, - k_EAppUsageEventPreloadFinish = 5, - k_EAppUsageEventMarketingMessageView = 6, // deprecated, do not use - k_EAppUsageEventInGameAdViewed = 7, - k_EAppUsageEventGameLaunchFreeWeekend = 8, -}; - - -//----------------------------------------------------------------------------- -// Purpose: Functions for accessing and manipulating a steam account -// associated with one client instance -//----------------------------------------------------------------------------- -class ISteamUser -{ -public: - // returns the HSteamUser this interface represents - virtual HSteamUser GetHSteamUser() = 0; - - // steam account management functions - virtual bool BLoggedOn() = 0; - virtual CSteamID GetSteamID() = 0; - - // notify of connection to game server - virtual int InitiateGameConnection( void *pBlob, int cbMaxBlob, CSteamID steamID, CGameID gameID, uint32 unIPServer, uint16 usPortServer, bool bSecure, void *pvSteam2GetEncryptionKey, int cbSteam2GetEncryptionKey ) = 0; - // notify of disconnect - virtual void TerminateGameConnection( uint32 unIPServer, uint16 usPortServer ) = 0; - - // game info - virtual void TrackAppUsageEvent( CGameID gameID, int eAppUsageEvent, const char *pchExtraInfo = "" ) = 0; - - // legacy authentication support - need to be called if the game server rejects the user with a 'bad ticket' error - virtual void RefreshSteam2Login() = 0; -}; - -#define STEAMUSER_INTERFACE_VERSION "SteamUser008" - - -// callbacks - - -//----------------------------------------------------------------------------- -// Purpose: called when a logon attempt has succeeded -//----------------------------------------------------------------------------- -struct LogonSuccess_t -{ - enum { k_iCallback = k_iSteamUserCallbacks + 1 }; -}; - - -//----------------------------------------------------------------------------- -// Purpose: called when a logon attempt has failed -//----------------------------------------------------------------------------- -struct LogonFailure_t -{ - enum { k_iCallback = k_iSteamUserCallbacks + 2 }; - EResult m_eResult; -}; - - -//----------------------------------------------------------------------------- -// Purpose: called when the user logs off -//----------------------------------------------------------------------------- -struct LoggedOff_t -{ - enum { k_iCallback = k_iSteamUserCallbacks + 3 }; - EResult m_eResult; -}; - - -//----------------------------------------------------------------------------- -// Purpose: called when the client is trying to retry logon after being unintentionally logged off -//----------------------------------------------------------------------------- -struct BeginLogonRetry_t -{ - enum { k_iCallback = k_iSteamUserCallbacks + 4 }; -}; - - -//----------------------------------------------------------------------------- -// Purpose: connect to game server denied -//----------------------------------------------------------------------------- -struct ClientGameServerDeny_t -{ - enum { k_iCallback = k_iSteamUserCallbacks + 13 }; - - uint32 m_uAppID; - uint32 m_unGameServerIP; - uint16 m_usGameServerPort; - uint16 m_bSecure; - uint32 m_uReason; -}; - - -//----------------------------------------------------------------------------- -// Purpose: called when the callback system for this client is in an error state (and has flushed pending callbacks) -// When getting this message the client should disconnect from Steam, reset any stored Steam state and reconnect -//----------------------------------------------------------------------------- -struct CallbackPipeFailure_t -{ - enum { k_iCallback = k_iSteamUserCallbacks + 17 }; -}; - - -//----------------------------------------------------------------------------- -// Purpose: connect to game server denied -//----------------------------------------------------------------------------- -struct GSPolicyResponse_t -{ - enum { k_iCallback = k_iSteamUserCallbacks + 15 }; - uint8 m_bSecure; -}; - - -// C API bindings for GoldSRC, see isteamclient.h for details -extern "C" -{ - // C functions we export for the C API, maps to ISteamUser functions - DLL_EXPORT void Steam_LogOn( HSteamUser hUser, HSteamPipe hSteamPipe, uint64 ulSteamID ); - DLL_EXPORT void Steam_LogOff( HSteamUser hUser, HSteamPipe hSteamPipe ); - DLL_EXPORT bool Steam_BLoggedOn( HSteamUser hUser, HSteamPipe hSteamPipe ); - DLL_EXPORT bool Steam_BConnected( HSteamUser hUser, HSteamPipe hSteamPipe ); - DLL_EXPORT bool Steam_BGetCallback( HSteamPipe hSteamPipe, CallbackMsg_t *pCallbackMsg, HSteamCall *phSteamCall ); - DLL_EXPORT void Steam_FreeLastCallback( HSteamPipe hSteamPipe ); - DLL_EXPORT int Steam_GSGetSteamGameConnectToken( HSteamUser hUser, HSteamPipe hSteamPipe, void *pBlob, int cbBlobMax ); - DLL_EXPORT int Steam_InitiateGameConnection( HSteamUser hUser, HSteamPipe hSteamPipe, void *pBlob, int cbMaxBlob, uint64 steamID, int nGameAppID, uint32 unIPServer, uint16 usPortServer, bool bSecure ); - DLL_EXPORT void Steam_TerminateGameConnection( HSteamUser hUser, HSteamPipe hSteamPipe, uint32 unIPServer, uint16 usPortServer ); - - - typedef bool (*PFNSteam_BGetCallback)( HSteamPipe hSteamPipe, CallbackMsg_t *pCallbackMsg, HSteamCall *phSteamCall ); - typedef void (*PFNSteam_FreeLastCallback)( HSteamPipe hSteamPipe ); -} - -#endif // ISTEAMUSER_H diff --git a/public/steam/isteamuserstats.h b/public/steam/isteamuserstats.h deleted file mode 100644 index 136e34777..000000000 --- a/public/steam/isteamuserstats.h +++ /dev/null @@ -1,112 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: interface to user account information in Steam -// -//============================================================================= - -#ifndef ISTEAMUSERSTATS_H -#define ISTEAMUSERSTATS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "isteamclient.h" - -// size limit on stat or achievement name -const uint32 k_cchStatNameMax = 128; - -class ISteamUserStats -{ -public: - - // The "schema" of a Game's UserData is really defined elsewhere, and - // the game should know it before accessing this interface. These top - // three functions are mostly provided for iteration / testing purposes. - // Get the number of stats fields for nGameID - virtual uint32 GetNumStats( CGameID nGameID ) = 0; - // Get stat name iStat in [0,GetNumStats) - virtual const char *GetStatName( CGameID nGameID, uint32 iStat ) = 0; - // Get type of this field - virtual ESteamUserStatType GetStatType( CGameID nGameID, const char *pchName ) = 0; - // Get the number of achievements for nGameID - virtual uint32 GetNumAchievements( CGameID nGameID ) = 0; - // Get achievement name iAchievement in [0,GetNumAchievements) - virtual const char *GetAchievementName( CGameID nGameID, uint32 iAchievement ) = 0; - - // Ask the server to send down this user's data and achievements for nGameID - virtual bool RequestCurrentStats( CGameID nGameID ) = 0; - - // Data accessors - virtual bool GetStat( CGameID nGameID, const char *pchName, int32 *pData ) = 0; - virtual bool GetStat( CGameID nGameID, const char *pchName, float *pData ) = 0; - - // Set / update data - virtual bool SetStat( CGameID nGameID, const char *pchName, int32 nData ) = 0; - virtual bool SetStat( CGameID nGameID, const char *pchName, float fData ) = 0; - virtual bool UpdateAvgRateStat( CGameID nGameID, const char *pchName, uint32 nCountThisSession, double dSessionLength ) = 0; - - // Achievement flag accessors - virtual bool GetAchievement( CGameID nGameID, const char *pchName, bool *pbAchieved ) = 0; - virtual bool SetAchievement( CGameID nGameID, const char *pchName ) = 0; - virtual bool ClearAchievement( CGameID nGameID, const char *pchName ) = 0; - - // Store the current data on the server, will get a callback when set - // And one callback for every new achievement - virtual bool StoreStats( CGameID nGameID ) = 0; - - // Achievement / GroupAchievement metadata - - // Gets the icon of the achievement, which is a handle to be used in IClientUtils::GetImageRGBA(), or 0 if none set - virtual int GetAchievementIcon( CGameID nGameID, const char *pchName ) = 0; - // Get general attributes (display name / text, etc) for an Achievement - virtual const char *GetAchievementDisplayAttribute( CGameID nGameID, const char *pchName, const char *pchKey ) = 0; - - // Achievement progress - triggers an AchievementProgress callback, that is all. - // Calling this w/ N out of N progress will NOT set the achievement, the game must still do that. - virtual bool IndicateAchievementProgress( CGameID nGameID, const char *pchName, uint32 nCurProgress, uint32 nMaxProgress ) = 0; - -}; - - -#define STEAMUSERSTATS_INTERFACE_VERSION "STEAMUSERSTATS_INTERFACE_VERSION002" - -//----------------------------------------------------------------------------- -// Purpose: called when the latests stats and achievements have been received -// from the server -//----------------------------------------------------------------------------- -struct UserStatsReceived_t -{ - enum { k_iCallback = k_iSteamUserStatsCallbacks + 1 }; - uint64 m_nGameID; // Game these stats are for - EResult m_eResult; // Success / error fetching the stats -}; - - -//----------------------------------------------------------------------------- -// Purpose: result of a request to store the user stats for a game -//----------------------------------------------------------------------------- -struct UserStatsStored_t -{ - enum { k_iCallback = k_iSteamUserStatsCallbacks + 2 }; - uint64 m_nGameID; // Game these stats are for - EResult m_eResult; // success / error -}; - -//----------------------------------------------------------------------------- -// Purpose: result of a request to store the achievements for a game, or an -// "indicate progress" call. If both m_nCurProgress and m_nMaxProgress -// are zero, that means the achievement has been fully unlocked. -//----------------------------------------------------------------------------- -struct UserAchievementStored_t -{ - enum { k_iCallback = k_iSteamUserStatsCallbacks + 3 }; - - uint64 m_nGameID; // Game this is for - bool m_bGroupAchievement; // if this is a "group" achievement - char m_rgchAchievementName[k_cchStatNameMax]; // name of the achievement - uint32 m_nCurProgress; // current progress towards the achievement - uint32 m_nMaxProgress; // "out of" this many -}; - - -#endif // ISTEAMUSER_H diff --git a/public/steam/isteamutils.h b/public/steam/isteamutils.h deleted file mode 100644 index 93e1524dd..000000000 --- a/public/steam/isteamutils.h +++ /dev/null @@ -1,74 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: interface to utility functions in Steam -// -//============================================================================= - -#ifndef ISTEAMUTILS_H -#define ISTEAMUTILS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "isteamclient.h" - -//----------------------------------------------------------------------------- -// Purpose: interface to user independent utility functions -//----------------------------------------------------------------------------- -class ISteamUtils -{ -public: - // return the number of seconds since the user - virtual uint32 GetSecondsSinceAppActive() = 0; - virtual uint32 GetSecondsSinceComputerActive() = 0; - - // the universe this client is connecting to - virtual EUniverse GetConnectedUniverse() = 0; - - // Steam server time - in PST, number of seconds since January 1, 1970 (i.e unix time) - virtual uint32 GetServerRealTime() = 0; - - // returns the 2 digit ISO 3166-1-alpha-2 format country code this client is running in (as looked up via an IP-to-location database) - // e.g "US" or "UK". - virtual const char *GetIPCountry() = 0; - - // returns true if the image exists, and valid sizes were filled out - virtual bool GetImageSize( int iImage, uint32 *pnWidth, uint32 *pnHeight ) = 0; - - // returns true if the image exists, and the buffer was successfully filled out - // results are returned in RGBA format - // the destination buffer size should be 4 * height * width * sizeof(char) - virtual bool GetImageRGBA( int iImage, uint8 *pubDest, int nDestBufferSize ) = 0; - - // returns the IP of the reporting server for valve - currently only used in Source engine games - virtual bool GetCSERIPPort( uint32 *unIP, uint16 *usPort ) = 0; - - // return the amount of battery power left in the current system in % [0..100], 255 for being on AC power - virtual uint8 GetCurrentBatteryPower() = 0; -}; - -#define STEAMUTILS_INTERFACE_VERSION "SteamUtils002" - - -// callbacks - - -//----------------------------------------------------------------------------- -// Purpose: The country of the user changed -//----------------------------------------------------------------------------- -struct IPCountry_t -{ - enum { k_iCallback = k_iSteamUtilsCallbacks + 1 }; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Fired when running on a laptop and less than 10 minutes of battery is left, fires then every minute -//----------------------------------------------------------------------------- -struct LowBatteryPower_t -{ - enum { k_iCallback = k_iSteamUtilsCallbacks + 2 }; - uint8 m_nMinutesBatteryLeft; -}; - -#endif // ISTEAMUTILS_H diff --git a/public/steam/matchmakingtypes.h b/public/steam/matchmakingtypes.h deleted file mode 100644 index 705433956..000000000 --- a/public/steam/matchmakingtypes.h +++ /dev/null @@ -1,235 +0,0 @@ -//========= Copyright 1996-2001, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#ifndef MATCHMAKINGTYPES_H -#define MATCHMAKINGTYPES_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -struct MatchMakingKeyValuePair_t -{ - MatchMakingKeyValuePair_t() { m_szKey[0] = m_szValue[0] = 0; } - MatchMakingKeyValuePair_t( const char *pchKey, const char *pchValue ) - { - strncpy( m_szKey, pchKey, sizeof(m_szKey) ); // this is a public header, use basic c library string funcs only! - strncpy( m_szValue, pchValue, sizeof(m_szValue) ); - } - char m_szKey[ 256 ]; - char m_szValue[ 256 ]; -}; - - -enum EMatchMakingServerResponse -{ - eServerResponded = 0, - eServerFailedToRespond, - eNoServersListedOnMasterServer // for the Internet query type, returned in response callback if no servers of this type match -}; - -enum EMatchMakingType -{ - eInternetServer = 0, - eLANServer, - eFriendsServer, - eFavoritesServer, - eHistoryServer, - eSpectatorServer, - eInvalidServer -}; - - -// servernetadr_t is all the addressing info the serverbrowser needs to know about a game server, -// namely: its IP, its connection port, and its query port. -class servernetadr_t -{ -public: - - void Init( unsigned int ip, uint16 usQueryPort, uint16 usConnectionPort ); -#ifdef NETADR_H - void Init( const netadr_t &ipAndQueryPort, uint16 usConnectionPort ); - netadr_t& GetIPAndQueryPort(); -#endif - - // Access the query port. - uint16 GetQueryPort() const; - void SetQueryPort( uint16 usPort ); - - // Access the connection port. - uint16 GetConnectionPort() const; - void SetConnectionPort( uint16 usPort ); - - // Access the IP - uint32 GetIP() const; - void SetIP( uint32 ); - - // This gets the 'a.b.c.d:port' string with the connection port (instead of the query port). - const char *GetConnectionAddressString() const; - const char *GetQueryAddressString() const; - - // Comparison operators and functions. - bool operator<(const servernetadr_t &netadr) const; - void operator=( const servernetadr_t &that ) - { - m_usConnectionPort = that.m_usConnectionPort; - m_usQueryPort = that.m_usQueryPort; - m_unIP = that.m_unIP; - } - - -private: - const char *ToString( uint32 unIP, uint16 usPort ) const; - uint16 m_usConnectionPort; // (in HOST byte order) - uint16 m_usQueryPort; - uint32 m_unIP; -}; - - -inline void servernetadr_t::Init( unsigned int ip, uint16 usQueryPort, uint16 usConnectionPort ) -{ - m_unIP = ip; - m_usQueryPort = usQueryPort; - m_usConnectionPort = usConnectionPort; -} - -#ifdef NETADR_H -inline void servernetadr_t::Init( const netadr_t &ipAndQueryPort, uint16 usConnectionPort ) -{ - Init( ipAndQueryPort.GetIP(), ipAndQueryPort.GetPort(), usConnectionPort ); -} - -inline netadr_t& servernetadr_t::GetIPAndQueryPort() -{ - static netadr_t netAdr; - netAdr.SetIP( m_unIP ); - netAdr.SetPort( m_usQueryPort ); - return netAdr; -} -#endif - -inline uint16 servernetadr_t::GetQueryPort() const -{ - return m_usQueryPort; -} - -inline void servernetadr_t::SetQueryPort( uint16 usPort ) -{ - m_usQueryPort = usPort; -} - -inline uint16 servernetadr_t::GetConnectionPort() const -{ - return m_usConnectionPort; -} - -inline void servernetadr_t::SetConnectionPort( uint16 usPort ) -{ - m_usConnectionPort = usPort; -} - -inline uint32 servernetadr_t::GetIP() const -{ - return m_unIP; -} - -inline void servernetadr_t::SetIP( uint32 unIP ) -{ - m_unIP = unIP; -} - -inline const char *servernetadr_t::ToString( uint32 unIP, uint16 usPort ) const -{ - static char s[4][64]; - static int nBuf = 0; - unsigned char *ipByte = (unsigned char *)&unIP; - Q_snprintf (s[nBuf], sizeof( s[nBuf] ), "%u.%u.%u.%u:%i", (int)(ipByte[3]), (int)(ipByte[2]), (int)(ipByte[1]), (int)(ipByte[0]), usPort ); - const char *pchRet = s[nBuf]; - ++nBuf; - nBuf %= ( (sizeof(s)/sizeof(s[0])) ); - return pchRet; -} - -inline const char* servernetadr_t::GetConnectionAddressString() const -{ - return ToString( m_unIP, m_usConnectionPort ); -} - -inline const char* servernetadr_t::GetQueryAddressString() const -{ - return ToString( m_unIP, m_usQueryPort ); -} - -inline bool servernetadr_t::operator<(const servernetadr_t &netadr) const -{ - return ( m_unIP < netadr.m_unIP ) || ( m_unIP == netadr.m_unIP && m_usQueryPort < netadr.m_usQueryPort ); -} - -//----------------------------------------------------------------------------- -// Purpose: Data describing a single server -//----------------------------------------------------------------------------- -class gameserveritem_t -{ -public: - gameserveritem_t(); - - const char* GetName() const; - void SetName( const char *pName ); - -public: - servernetadr_t m_NetAdr; // IP/Query Port/Connection Port for this server - int m_nPing; // current ping time in milliseconds - bool m_bHadSuccessfulResponse; // server has responded successfully in the past - bool m_bDoNotRefresh; // server is marked as not responding and should no longer be refreshed - char m_szGameDir[32]; // current game directory - char m_szMap[32]; // current map - char m_szGameDescription[64]; // game description - int m_nAppID; // Steam App ID of this server - int m_nPlayers; // current number of players on the server - int m_nMaxPlayers; // Maximum players that can join this server - int m_nBotPlayers; // Number of bots (i.e simulated players) on this server - bool m_bPassword; // true if this server needs a password to join - bool m_bSecure; // Is this server protected by VAC - uint32 m_ulTimeLastPlayed; // time (in unix time) when this server was last played on (for favorite/history servers) - int m_nServerVersion; // server version as reported to Steam - -private: - char m_szServerName[64]; // Game server name - - // For data added after SteamMatchMaking001 add it here -public: - char m_szGameTags[128]; // the tags this server exposes -}; - - -inline gameserveritem_t::gameserveritem_t() -{ - m_szGameDir[0] = m_szMap[0] = m_szGameDescription[0] = m_szServerName[0] = 0; - m_bHadSuccessfulResponse = m_bDoNotRefresh = m_bPassword = m_bSecure = false; - m_nPing = m_nAppID = m_nPlayers = m_nMaxPlayers = m_nBotPlayers = m_ulTimeLastPlayed = m_nServerVersion = 0; - m_szGameTags[0] = 0; -} - -inline const char* gameserveritem_t::GetName() const -{ - // Use the IP address as the name if nothing is set yet. - if ( m_szServerName[0] == 0 ) - return m_NetAdr.GetConnectionAddressString(); - else - return m_szServerName; -} - -inline void gameserveritem_t::SetName( const char *pName ) -{ - strncpy( m_szServerName, pName, sizeof( m_szServerName ) ); -} - - -#endif // MATCHMAKINGTYPES_H diff --git a/public/steam/steam_api.h b/public/steam/steam_api.h deleted file mode 100644 index 30f2f757f..000000000 --- a/public/steam/steam_api.h +++ /dev/null @@ -1,295 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef STEAM_API_H -#define STEAM_API_H -#ifdef _WIN32 -#pragma once -#endif - -#include "isteamclient.h" -#include "isteamuser.h" -#include "isteamfriends.h" -#include "isteamutils.h" -#include "isteammatchmaking.h" -#include "isteamuserstats.h" -#include "isteamapps.h" - -// Steam API export macro -#if defined( _WIN32 ) && !defined( _X360 ) - #if defined( STEAM_API_EXPORTS ) - #define S_API extern "C" __declspec( dllexport ) - #elif defined( STEAM_API_NODLL ) - #define S_API extern "C" - #else - #define S_API extern "C" __declspec( dllimport ) - #endif // STEAM_API_EXPORTS -#else // !WIN32 - #if defined( STEAM_API_EXPORTS ) - #define S_API extern "C" - #else - #define S_API extern "C" - #endif // STEAM_API_EXPORTS -#endif - -//----------------------------------------------------------------------------------------------------------------------------------------------------------// -// Steam API setup & teardown -// -// These functions manage loading, initializing and shutdown of the steamclient.dll -// -// bugbug johnc: seperate defining these to defining game server interface more cleanly -// -//----------------------------------------------------------------------------------------------------------------------------------------------------------// - -S_API void SteamAPI_Shutdown(); - -S_API void SteamAPI_WriteMiniDump( uint32 uStructuredExceptionCode, void* pvExceptionInfo, uint32 uBuildID ); -S_API void SteamAPI_SetMiniDumpComment( const char *pchMsg ); - -// interface pointers, configured by SteamAPI_Init() -S_API ISteamClient *SteamClient(); - - -// -// VERSION_SAFE_STEAM_API_INTERFACES is usually not necessary, but it provides safety against releasing -// new steam_api.dll's without recompiling/rereleasing modules that use it. -// -// If you use VERSION_SAFE_STEAM_API_INTERFACES, then you should call SteamAPI_InitSafe(). Also, to get the -// Steam interfaces, you must create and Init() a CSteamAPIContext (below) and use the interfaces in there. -// -// If you don't use VERSION_SAFE_STEAM_API_INTERFACES, then you can use SteamAPI_Init() and the SteamXXXX() -// functions below to get at the Steam interfaces. -// -#ifdef VERSION_SAFE_STEAM_API_INTERFACES -S_API bool SteamAPI_InitSafe(); -#else -S_API bool SteamAPI_Init(); - -S_API ISteamUser *SteamUser(); -S_API ISteamFriends *SteamFriends(); -S_API ISteamUtils *SteamUtils(); -S_API ISteamMatchmaking *SteamMatchmaking(); -S_API ISteamUserStats *SteamUserStats(); -S_API ISteamApps *SteamApps(); -S_API ISteamMatchmakingServers *SteamMatchmakingServers(); -#endif // VERSION_SAFE_STEAM_API_INTERFACES - -//----------------------------------------------------------------------------------------------------------------------------------------------------------// -// steam callback helper functions -// -// These following classes/macros are used to be able to easily multiplex callbacks -// from the Steam API into various objects in the app in a thread-safe manner -// -// This functors are triggered via the SteamAPI_RunCallbacks() function, mapping the callback -// to as many functions/objects as are registered to it -//----------------------------------------------------------------------------------------------------------------------------------------------------------// - -S_API void SteamAPI_RunCallbacks(); - - - -// functions used by the utility CCallback objects to receive callbacks -S_API void SteamAPI_RegisterCallback( class CCallbackBase *pCallback, int iCallback ); -S_API void SteamAPI_UnregisterCallback( class CCallbackBase *pCallback ); - -//----------------------------------------------------------------------------- -// Purpose: base for callbacks, -// used only by CCallback, shouldn't be used directly -//----------------------------------------------------------------------------- -class CCallbackBase -{ -public: - CCallbackBase() { m_nCallbackFlags = 0; } - // don't add a virtual destructor because we export this binary interface across dll's - virtual void Run( void *pvParam ) = 0; - -protected: - enum { k_ECallbackFlagsRegistered = 0x01, k_ECallbackFlagsGameServer = 0x02 }; - uint8 m_nCallbackFlags; -private: - int m_iCallback; - friend class CCallbackMgr; -}; - - -//----------------------------------------------------------------------------- -// Purpose: maps a steam callback to a class member function -// template params: T = local class, P = parameter struct -//----------------------------------------------------------------------------- -template< class T, class P, bool bGameServer > -class CCallback : private CCallbackBase -{ -public: - typedef void (T::*func_t)( P* ); - - // If you can't support constructing a callback with the correct parameters - // then uncomment the empty constructor below and manually call - // ::Register() for your object - //CCallback() {} - - // constructor for initializing this object in owner's constructor - CCallback( T *pObj, func_t func ) : m_pObj( pObj ), m_Func( func ) - { - if ( bGameServer ) - { - m_nCallbackFlags |= k_ECallbackFlagsGameServer; - } - - Register( pObj, func ); - } - - ~CCallback() - { - SteamAPI_UnregisterCallback( this ); - } - - // manual registration of the callback - void Register( T *pObj, func_t func ) - { - m_pObj = pObj; - m_Func = func; - SteamAPI_RegisterCallback( this, P::k_iCallback ); - } - -private: - virtual void Run( void *pvParam ) - { - (m_pObj->*m_Func)( (P *)pvParam ); - } - - T *m_pObj; - func_t m_Func; -}; - - -// utility macro for declaring the function and callback object together -#define STEAM_CALLBACK( thisclass, func, param, var ) CCallback< thisclass, param, false > var; void func( param *pParam ) - - - - -//----------------------------------------------------------------------------------------------------------------------------------------------------------// -// steamclient.dll private wrapper functions -// -// The following functions are part of abstracting API access to the steamclient.dll, but should only be used in very specific cases -//----------------------------------------------------------------------------------------------------------------------------------------------------------// - -// pumps out all the steam messages, calling the register callback -S_API void Steam_RunCallbacks( HSteamPipe hSteamPipe, bool bGameServerCallbacks ); - -// register the callback funcs to use to interact with the steam dll -S_API void Steam_RegisterInterfaceFuncs( void *hModule ); - -// returns the HSteamUser of the last user to dispatch a callback -S_API HSteamUser Steam_GetHSteamUserCurrent(); - -// returns the filename path of the current running Steam process, used if you need to load an explicit steam dll by name -S_API const char *SteamAPI_GetSteamInstallPath(); - - -#ifdef VERSION_SAFE_STEAM_API_INTERFACES -//----------------------------------------------------------------------------------------------------------------------------------------------------------// -// VERSION_SAFE_STEAM_API_INTERFACES uses CSteamAPIContext to provide interfaces to each module in a way that -// lets them each specify the interface versions they are compiled with. -// -// It's important that these stay inlined in the header so the calling module specifies the interface versions -// for whatever Steam API version it has. -//----------------------------------------------------------------------------------------------------------------------------------------------------------// -#if defined( _WIN32 ) && !defined( _X360 ) - S_API HSteamPipe GetHSteamPipe(); - S_API HSteamUser GetHSteamUser(); -#endif - -class CSteamAPIContext -{ -public: - CSteamAPIContext(); - void Clear(); - - bool Init(); - - ISteamUser* SteamUser() { return m_pSteamUser; } - ISteamFriends* SteamFriends() { return m_pSteamFriends; } - ISteamUtils* SteamUtils() { return m_pSteamUtils; } - ISteamMatchmaking* SteamMatchmaking() { return m_pSteamMatchmaking; } - ISteamUserStats* SteamUserStats() { return m_pSteamUserStats; } - ISteamApps* SteamApps() { return m_pSteamApps; } - ISteamMatchmakingServers* SteamMatchmakingServers() { return m_pSteamMatchmakingServers; } - -private: - ISteamUser *m_pSteamUser; - ISteamFriends *m_pSteamFriends; - ISteamUtils *m_pSteamUtils; - ISteamMatchmaking *m_pSteamMatchmaking; - ISteamUserStats *m_pSteamUserStats; - ISteamApps *m_pSteamApps; - ISteamMatchmakingServers *m_pSteamMatchmakingServers; -}; - -inline CSteamAPIContext::CSteamAPIContext() -{ - Clear(); -} - -inline void CSteamAPIContext::Clear() -{ - m_pSteamUser = NULL; - m_pSteamFriends = NULL; - m_pSteamUtils = NULL; - m_pSteamMatchmaking = NULL; - m_pSteamUserStats = NULL; - m_pSteamApps = NULL; - m_pSteamMatchmakingServers = NULL; -} - -// This function must be inlined so the module using steam_api.dll gets the version names they want. -inline bool CSteamAPIContext::Init() -{ -#if defined( _WIN32 ) && !defined( _X360 ) - - if ( !SteamClient() ) - return false; - - HSteamUser hSteamUser = GetHSteamUser(); - HSteamPipe hSteamPipe = GetHSteamPipe(); - - m_pSteamUser = SteamClient()->GetISteamUser( hSteamUser, hSteamPipe, STEAMUSER_INTERFACE_VERSION ); - if ( !m_pSteamUser ) - return false; - - m_pSteamFriends = SteamClient()->GetISteamFriends( hSteamUser, hSteamPipe, STEAMFRIENDS_INTERFACE_VERSION ); - if ( !m_pSteamFriends ) - return false; - - m_pSteamUtils = SteamClient()->GetISteamUtils( hSteamUser, STEAMUTILS_INTERFACE_VERSION ); - if ( !m_pSteamUtils ) - return false; - - m_pSteamMatchmaking = SteamClient()->GetISteamMatchmaking( hSteamUser, hSteamPipe, STEAMMATCHMAKING_INTERFACE_VERSION ); - if ( !m_pSteamMatchmaking ) - return false; - - m_pSteamMatchmakingServers = SteamClient()->GetISteamMatchmakingServers( hSteamUser, hSteamPipe, STEAMMATCHMAKINGSERVERS_INTERFACE_VERSION ); - if ( !m_pSteamMatchmakingServers ) - return false; - - m_pSteamUserStats = SteamClient()->GetISteamUserStats( hSteamUser, hSteamPipe, STEAMUSERSTATS_INTERFACE_VERSION ); - if ( !m_pSteamUserStats ) - return false; - - m_pSteamApps = SteamClient()->GetISteamApps( hSteamUser, hSteamPipe, STEAMAPPS_INTERFACE_VERSION ); - if ( !m_pSteamApps ) - return false; - - return true; -#else - return false; -#endif -} - -#endif // VERSION_SAFE_STEAM_API_INTERFACES - -#endif // STEAM_API_H diff --git a/public/steam/steamclientpublic.h b/public/steam/steamclientpublic.h deleted file mode 100644 index 1a74fc2bb..000000000 --- a/public/steam/steamclientpublic.h +++ /dev/null @@ -1,709 +0,0 @@ -//========= Copyright 1996-2004, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#ifndef STEAMCLIENTPUBLIC_H -#define STEAMCLIENTPUBLIC_H -#ifdef _WIN32 -#pragma once -#endif -//lint -save -e1931 -e1927 -e1924 -e613 -e726 - -// This header file defines the interface between the calling application and the code that -// knows how to communicate with the connection manager (CM) from the Steam service - -// This header file is intended to be portable; ideally this 1 header file plus a lib or dll -// is all you need to integrate the client library into some other tree. So please avoid -// including or requiring other header files if possible. This header should only describe the -// interface layer, no need to include anything about the implementation. - -#include "steamtypes.h" - - -// General result codes -enum EResult -{ - k_EResultOK = 1, // success - k_EResultFail = 2, // generic failure - k_EResultNoConnection = 3, // no/failed network connection -// k_EResultNoConnectionRetry = 4, // OBSOLETE - removed - k_EResultInvalidPassword = 5, // password/ticket is invalid - k_EResultLoggedInElsewhere = 6, // same user logged in elsewhere - k_EResultInvalidProtocolVer = 7, // protocol version is incorrect - k_EResultInvalidParam = 8, // a parameter is incorrect - k_EResultFileNotFound = 9, // file was not found - k_EResultBusy = 10, // called method busy - action not taken - k_EResultInvalidState = 11, // called object was in an invalid state - k_EResultInvalidName = 12, // name is invalid - k_EResultInvalidEmail = 13, // email is invalid - k_EResultDuplicateName = 14, // name is not unique - k_EResultAccessDenied = 15, // access is denied - k_EResultTimeout = 16, // operation timed out - k_EResultBanned = 17, // VAC2 banned - k_EResultAccountNotFound = 18, // account not found - k_EResultInvalidSteamID = 19, // steamID is invalid - k_EResultServiceUnavailable = 20, // The requested service is currently unavailable - k_EResultNotLoggedOn = 21, // The user is not logged on - k_EResultPending = 22, // Request is pending (may be in process, or waiting on third party) - k_EResultEncryptionFailure = 23, // Encryption or Decryption failed - k_EResultInsufficientPrivilege = 24, // Insufficient privilege - k_EResultLimitExceeded = 25, // Too much of a good thing - k_EResultRevoked = 26, // Access has been revoked (used for revoked guest passes) - k_EResultExpired = 27, // License/Guest pass the user is trying to access is expired - k_EResultAlreadyRedeemed = 28, // Guest pass has already been redeemed by account, cannot be acked again - k_EResultDuplicateRequest = 29, // The request is a duplicate and the action has already occurred in the past, ignored this time - k_EResultAlreadyOwned = 30, // All the games in this guest pass redemption request are already owned by the user - k_EResultIPNotFound = 31, // IP address not found - k_EResultPersistFailed = 32, // failed to write change to the data store - k_EResultLockingFailed = 33, // failed to acquire access lock for this operation - k_EResultLogonSessionReplaced = 34, - k_EResultConnectFailed = 35, - k_EResultHandshakeFailed = 36, - k_EResultIOFailure = 37, - k_EResultRemoteDisconnect = 38, - k_EResultShoppingCartNotFound = 39, // failed to find the shopping cart requested -}; - -// Result codes to GSHandleClientDeny/Kick -typedef enum -{ - k_EDenyInvalidVersion = 1, - k_EDenyGeneric = 2, - k_EDenyNotLoggedOn = 3, - k_EDenyNoLicense = 4, - k_EDenyCheater = 5, - k_EDenyLoggedInElseWhere = 6, - k_EDenyUnknownText = 7, - k_EDenyIncompatibleAnticheat = 8, - k_EDenyMemoryCorruption = 9, - k_EDenyIncompatibleSoftware = 10, - k_EDenySteamConnectionLost = 11, - k_EDenySteamConnectionError = 12, - k_EDenySteamResponseTimedOut = 13, - k_EDenySteamValidationStalled = 14, -} EDenyReason; - -// Steam universes. Each universe is a self-contained Steam instance. -enum EUniverse -{ - k_EUniverseInvalid = 0, - k_EUniversePublic = 1, - k_EUniverseBeta = 2, - k_EUniverseInternal = 3, - k_EUniverseDev = 4, - k_EUniverseRC = 5, - - k_EUniverseMax -}; - -// Steam account types -enum EAccountType -{ - k_EAccountTypeInvalid = 0, - k_EAccountTypeIndividual = 1, // single user account - k_EAccountTypeMultiseat = 2, // multiseat (e.g. cybercafe) account - k_EAccountTypeGameServer = 3, // game server account - k_EAccountTypeAnonGameServer = 4, // anonymous game server account - k_EAccountTypePending = 5, // pending - k_EAccountTypeContentServer = 6, // content server - k_EAccountTypeClan = 7, - k_EAccountTypeChat = 8, - k_EAccountTypeP2PSuperSeeder = 9, // a fake steamid used by superpeers to seed content to users of Steam P2P stuff - - // Max of 16 items in this field - k_EAccountTypeMax -}; - - -//----------------------------------------------------------------------------- -// types of user game stats fields -// WARNING: DO NOT RENUMBER EXISTING VALUES - STORED IN DATABASE -//----------------------------------------------------------------------------- -enum ESteamUserStatType -{ - k_ESteamUserStatTypeINVALID = 0, - k_ESteamUserStatTypeINT = 1, - k_ESteamUserStatTypeFLOAT = 2, - // Read as FLOAT, set with count / session length - k_ESteamUserStatTypeAVGRATE = 3, - k_ESteamUserStatTypeACHIEVEMENTS = 4, - k_ESteamUserStatTypeGROUPACHIEVEMENTS = 5, -}; - - -//----------------------------------------------------------------------------- -// Purpose: Chat Entry Types (previously was only friend-to-friend message types) -//----------------------------------------------------------------------------- -enum EChatEntryType -{ - k_EChatEntryTypeChatMsg = 1, // Normal text message from another user - k_EChatEntryTypeTyping = 2, // Another user is typing (not used in multi-user chat) - k_EChatEntryTypeInviteGame = 3, // DEPRECATED Invite from other user into that users current game - k_EChatEntryTypeEmote = 4, // text emote message - // Above are previous FriendMsgType entries, now merged into more generic chat entry types -}; - - -//----------------------------------------------------------------------------- -// Purpose: Chat Room Enter Responses -//----------------------------------------------------------------------------- -enum EChatRoomEnterResponse -{ - k_EChatRoomEnterResponseSuccess = 1, // Success - k_EChatRoomEnterResponseDoesntExist = 2, // Chat doesn't exist (probably closed) - k_EChatRoomEnterResponseNotAllowed = 3, // General Denied - You don't have the permissions needed to join the chat - k_EChatRoomEnterResponseFull = 4, // Chat room has reached its maximum size - k_EChatRoomEnterResponseError = 5, // Unexpected Error - k_EChatRoomEnterResponseBanned = 6, // You are banned from this chat room and may not join -}; - - -typedef void (*PFNLegacyKeyRegistration)( const char *pchCDKey, const char *pchInstallPath ); -typedef bool (*PFNLegacyKeyInstalled)(); - - -#pragma pack( push, 1 ) - -// Steam ID structure (64 bits total) -class CSteamID -{ -public: - - //----------------------------------------------------------------------------- - // Purpose: Constructor - //----------------------------------------------------------------------------- - CSteamID() - { - m_unAccountID = 0; - m_EAccountType = k_EAccountTypeInvalid; - m_EUniverse = k_EUniverseInvalid; - m_unAccountInstance = 0; - } - - - //----------------------------------------------------------------------------- - // Purpose: Constructor - // Input : unAccountID - 32-bit account ID - // eUniverse - Universe this account belongs to - // eAccountType - Type of account - //----------------------------------------------------------------------------- - CSteamID( uint32 unAccountID, EUniverse eUniverse, EAccountType eAccountType ) - { - Set( unAccountID, eUniverse, eAccountType ); - } - - - //----------------------------------------------------------------------------- - // Purpose: Constructor - // Input : unAccountID - 32-bit account ID - // unAccountInstance - instance - // eUniverse - Universe this account belongs to - // eAccountType - Type of account - //----------------------------------------------------------------------------- - CSteamID( uint32 unAccountID, unsigned int unAccountInstance, EUniverse eUniverse, EAccountType eAccountType ) - { -#if defined(_SERVER) && defined(Assert) - Assert( ! ( ( k_EAccountTypeIndividual == eAccountType ) && ( 1 != unAccountInstance ) ) ); // enforce that for individual accounts, instance is always 1 -#endif // _SERVER - InstancedSet( unAccountID, unAccountInstance, eUniverse, eAccountType ); - } - - - //----------------------------------------------------------------------------- - // Purpose: Constructor - // Input : ulSteamID - 64-bit representation of a Steam ID - // Note: Will not accept a uint32 or int32 as input, as that is a probable mistake. - // See the stubbed out overloads in the private: section for more info. - //----------------------------------------------------------------------------- - CSteamID( uint64 ulSteamID ) - { - SetFromUint64( ulSteamID ); - } - - - //----------------------------------------------------------------------------- - // Purpose: Sets parameters for steam ID - // Input : unAccountID - 32-bit account ID - // eUniverse - Universe this account belongs to - // eAccountType - Type of account - //----------------------------------------------------------------------------- - void Set( uint32 unAccountID, EUniverse eUniverse, EAccountType eAccountType ) - { - m_unAccountID = unAccountID; - m_EUniverse = eUniverse; - m_EAccountType = eAccountType; - m_unAccountInstance = 1; - } - - - //----------------------------------------------------------------------------- - // Purpose: Sets parameters for steam ID - // Input : unAccountID - 32-bit account ID - // eUniverse - Universe this account belongs to - // eAccountType - Type of account - //----------------------------------------------------------------------------- - void InstancedSet( uint32 unAccountID, uint32 unInstance, EUniverse eUniverse, EAccountType eAccountType ) - { - m_unAccountID = unAccountID; - m_EUniverse = eUniverse; - m_EAccountType = eAccountType; - m_unAccountInstance = unInstance; - } - - - //----------------------------------------------------------------------------- - // Purpose: Initializes a steam ID from its 52 bit parts and universe/type - // Input : ulIdentifier - 52 bits of goodness - //----------------------------------------------------------------------------- - void FullSet( uint64 ulIdentifier, EUniverse eUniverse, EAccountType eAccountType ) - { - m_unAccountID = ( ulIdentifier & 0xFFFFFFFF ); // account ID is low 32 bits - m_unAccountInstance = ( ( ulIdentifier >> 32 ) & 0xFFFFF ); // account instance is next 20 bits - m_EUniverse = eUniverse; - m_EAccountType = eAccountType; - } - - - //----------------------------------------------------------------------------- - // Purpose: Initializes a steam ID from its 64-bit representation - // Input : ulSteamID - 64-bit representation of a Steam ID - //----------------------------------------------------------------------------- - void SetFromUint64( uint64 ulSteamID ) - { - m_unAccountID = ( ulSteamID & 0xFFFFFFFF ); // account ID is low 32 bits - m_unAccountInstance = ( ( ulSteamID >> 32 ) & 0xFFFFF ); // account instance is next 20 bits - - m_EAccountType = ( EAccountType ) ( ( ulSteamID >> 52 ) & 0xF ); // type is next 4 bits - m_EUniverse = ( EUniverse ) ( ( ulSteamID >> 56 ) & 0xFF ); // universe is next 8 bits - } - - -#if defined( INCLUDED_STEAM_COMMON_STEAMCOMMON_H ) - //----------------------------------------------------------------------------- - // Purpose: Initializes a steam ID from a Steam2 ID structure - // Input: pTSteamGlobalUserID - Steam2 ID to convert - // eUniverse - universe this ID belongs to - //----------------------------------------------------------------------------- - void SetFromSteam2( TSteamGlobalUserID *pTSteamGlobalUserID, EUniverse eUniverse ) - { - m_unAccountID = pTSteamGlobalUserID->m_SteamLocalUserID.Split.Low32bits * 2 + - pTSteamGlobalUserID->m_SteamLocalUserID.Split.High32bits; - m_EUniverse = eUniverse; // set the universe - m_EAccountType = k_EAccountTypeIndividual; // Steam 2 accounts always map to account type of individual - m_unAccountInstance = 1; // individual accounts always have an account instance ID of 1 - } - - //----------------------------------------------------------------------------- - // Purpose: Fills out a Steam2 ID structure - // Input: pTSteamGlobalUserID - Steam2 ID to write to - //----------------------------------------------------------------------------- - void ConvertToSteam2( TSteamGlobalUserID *pTSteamGlobalUserID ) const - { - // only individual accounts have any meaning in Steam 2, only they can be mapped - // Assert( m_EAccountType == k_EAccountTypeIndividual ); - - pTSteamGlobalUserID->m_SteamInstanceID = 0; - pTSteamGlobalUserID->m_SteamLocalUserID.Split.High32bits = m_unAccountID % 2; - pTSteamGlobalUserID->m_SteamLocalUserID.Split.Low32bits = m_unAccountID / 2; - } -#endif // defined( INCLUDED_STEAM_COMMON_STEAMCOMMON_H ) - - //----------------------------------------------------------------------------- - // Purpose: Converts steam ID to its 64-bit representation - // Output : 64-bit representation of a Steam ID - //----------------------------------------------------------------------------- - uint64 ConvertToUint64() const - { - return (uint64) ( ( ( (uint64) m_EUniverse ) << 56 ) + ( ( (uint64) m_EAccountType ) << 52 ) + - ( ( (uint64) m_unAccountInstance ) << 32 ) + m_unAccountID ); - } - - - //----------------------------------------------------------------------------- - // Purpose: Converts the static parts of a steam ID to a 64-bit representation. - // For multiseat accounts, all instances of that account will have the - // same static account key, so they can be grouped together by the static - // account key. - // Output : 64-bit static account key - //----------------------------------------------------------------------------- - uint64 GetStaticAccountKey() const - { - // note we do NOT include the account instance (which is a dynamic property) in the static account key - return (uint64) ( ( ( (uint64) m_EUniverse ) << 56 ) + ((uint64) m_EAccountType << 52 ) + m_unAccountID ); - } - - - //----------------------------------------------------------------------------- - // Purpose: create an anonymous game server login to be filled in by the AM - //----------------------------------------------------------------------------- - void CreateBlankAnonLogon( EUniverse eUniverse ) - { - m_unAccountID = 0; - m_EAccountType = k_EAccountTypeAnonGameServer; - m_EUniverse = eUniverse; - m_unAccountInstance = 0; - } - - //----------------------------------------------------------------------------- - // Purpose: Is this an anonymous game server login that will be filled in? - //----------------------------------------------------------------------------- - bool BBlankAnonAccount() const - { - return m_unAccountID == 0 && - m_EAccountType == k_EAccountTypeAnonGameServer && - m_unAccountInstance == 0; - } - - //----------------------------------------------------------------------------- - // Purpose: Is this a game server account id? - //----------------------------------------------------------------------------- - bool BGameServerAccount() const - { - return m_EAccountType == k_EAccountTypeGameServer || m_EAccountType == k_EAccountTypeAnonGameServer; - } - - //----------------------------------------------------------------------------- - // Purpose: Is this a content server account id? - //----------------------------------------------------------------------------- - bool BContentServerAccount() const - { - return m_EAccountType == k_EAccountTypeContentServer; - } - - - //----------------------------------------------------------------------------- - // Purpose: Is this a clan account id? - //----------------------------------------------------------------------------- - bool BClanAccount() const - { - return m_EAccountType == k_EAccountTypeClan; - } - - - //----------------------------------------------------------------------------- - // Purpose: Is this a chat account id? - //----------------------------------------------------------------------------- - bool BChatAccount() const - { - return m_EAccountType == k_EAccountTypeChat; - } - - - //----------------------------------------------------------------------------- - // Purpose: Is this an individual user account id? - //----------------------------------------------------------------------------- - bool BIndividualAccount() const - { - return m_EAccountType == k_EAccountTypeIndividual; - } - - - // simple accessors - void SetAccountID( uint32 unAccountID ) { m_unAccountID = unAccountID; } - uint32 GetAccountID() const { return m_unAccountID; } - uint32 GetUnAccountInstance() const { return m_unAccountInstance; } - EAccountType GetEAccountType() const { return ( EAccountType ) m_EAccountType; } - EUniverse GetEUniverse() const { return m_EUniverse; } - void SetEUniverse( EUniverse eUniverse ) { m_EUniverse = eUniverse; } - bool IsValid() const { return ( m_EAccountType != k_EAccountTypeInvalid && m_EUniverse != k_EUniverseInvalid ); } - - // this set of functions is hidden, will be moved out of class - explicit CSteamID( const char *pchSteamID, EUniverse eDefaultUniverse = k_EUniverseInvalid ); - char * Render() const; // renders this steam ID to string - static char * Render( uint64 ulSteamID ); // static method to render a uint64 representation of a steam ID to a string - - void SetFromString( const char *pchSteamID, EUniverse eDefaultUniverse ); - bool SetFromSteam2String( const char *pchSteam2ID, EUniverse eUniverse ); - - bool operator==( const CSteamID &val ) const - { - return ( ( val.m_unAccountID == m_unAccountID ) && ( val.m_unAccountInstance == m_unAccountInstance ) - && ( val.m_EAccountType == m_EAccountType ) && ( val.m_EUniverse == m_EUniverse ) ); - } - - bool operator!=( const CSteamID &val ) const { return !operator==( val ); } - bool operator<( const CSteamID &val ) const { return ConvertToUint64() < val.ConvertToUint64(); } - - // DEBUG function - bool BValidExternalSteamID() const; - -private: - // These are defined here to prevent accidental implicit conversion of a u32AccountID to a CSteamID. - // If you get a compiler error about an ambiguous constructor/function then it may be because you're - // passing a 32-bit int to a function that takes a CSteamID. You should explicitly create the SteamID - // using the correct Universe and account Type/Instance values. - CSteamID( uint32 ); - CSteamID( int32 ); - -#ifdef _WIN32 -#pragma warning(push) -#pragma warning(disable:4201) // nameless union is nonstandard - // 64 bits total - union - { - struct - { -#endif - uint32 m_unAccountID : 32; // unique account identifier - unsigned int m_unAccountInstance : 20; // dynamic instance ID (used for multiseat type accounts only) - unsigned int m_EAccountType : 4; // type of account - can't show as EAccountType, due to signed / unsigned difference - EUniverse m_EUniverse : 8; // universe this account belongs to -#ifdef _WIN32 - }; - - uint64 m_unAll64Bits; - }; -#pragma warning(pop) // no more anonymous unions until next time -#endif -}; - -const int k_unSteamAccountIDMask = 0xFFFFFFFF; -const int k_unSteamAccountInstanceMask = 0x000FFFFF; - - -// Special flags for Chat accounts - they go in the top 8 bits -// of the steam ID's "instance", leaving 12 for the actual instances -enum EChatSteamIDInstanceFlags -{ - k_EChatAccountInstanceMask = 0x00000FFF, // top 8 bits are flags - - k_EChatInstanceFlagClan = ( k_unSteamAccountInstanceMask + 1 ) >> 1, // top bit - k_EChatInstanceFlagLobby = ( k_unSteamAccountInstanceMask + 1 ) >> 2, // next one down, etc - - // Max of 8 flags -}; - - -// generic invalid CSteamID -const CSteamID k_steamIDNil; - -// This steamID comes from a user game connection to an out of date GS that hasnt implemented the protocol -// to provide its steamID -const CSteamID k_steamIDOutofDateGS( 0, 0, k_EUniverseInvalid, k_EAccountTypeInvalid ); -// This steamID comes from a user game connection to an sv_lan GS -const CSteamID k_steamIDLanModeGS( 0, 0, k_EUniversePublic, k_EAccountTypeInvalid ); -// This steamID can come from a user game connection to a GS that has just booted but hasnt yet even initialized -// its steam3 component and started logging on. -const CSteamID k_steamIDNotInitYetGS( 1, 0, k_EUniverseInvalid, k_EAccountTypeInvalid ); - - -#ifdef STEAM -// Returns the matching chat steamID, with the default instance of 0 -// If the steamID passed in is already of type k_EAccountTypeChat it will be returned with the same instance -CSteamID ChatIDFromSteamID( CSteamID &steamID ); -// Returns the matching clan steamID, with the default instance of 0 -// If the steamID passed in is already of type k_EAccountTypeClan it will be returned with the same instance -CSteamID ClanIDFromSteamID( CSteamID &steamID ); -// Asserts steamID type before conversion -CSteamID ChatIDFromClanID( CSteamID &steamIDClan ); -// Asserts steamID type before conversion -CSteamID ClanIDFromChatID( CSteamID &steamIDChat ); - -#endif // _STEAM - - -//----------------------------------------------------------------------------- -// Purpose: encapsulates an appID/modID pair -//----------------------------------------------------------------------------- -class CGameID -{ -public: - CGameID() - { - m_ulGameID = 0; - } - - explicit CGameID( uint64 ulGameID ) - { - m_ulGameID = ulGameID; - } - - explicit CGameID( int32 nAppID ) - { - m_ulGameID = 0; - m_gameID.m_nAppID = nAppID; - } - - explicit CGameID( uint32 nAppID ) - { - m_ulGameID = 0; - m_gameID.m_nAppID = nAppID; - } - - CGameID( uint32 nAppID, uint32 nModID ) - { - m_ulGameID = 0; - m_gameID.m_nAppID = nAppID; - m_gameID.m_nModID = nModID; - m_gameID.m_nType = k_EGameIDTypeGameMod; - } - - // Hidden functions used only by Steam - explicit CGameID( const char *pchGameID ); - char * Render() const; // renders this Game ID to string - static char * Render( uint64 ulGameID ); // static method to render a uint64 representation of a Game ID to a string - - // must include checksum_crc.h first to get this functionality -#if defined( CHECKSUM_CRC_H ) - CGameID( uint32 nAppID, const char *pchModPath ) - { - m_ulGameID = 0; - m_gameID.m_nAppID = nAppID; - m_gameID.m_nType = k_EGameIDTypeGameMod; - - char rgchModDir[MAX_PATH]; - Q_FileBase( pchModPath, rgchModDir, sizeof( rgchModDir ) ); - CRC32_t crc32; - CRC32_Init( &crc32 ); - CRC32_ProcessBuffer( &crc32, rgchModDir, Q_strlen( rgchModDir ) ); - CRC32_Final( &crc32 ); - - // set the high-bit on the mod-id - // reduces crc32 to 31bits, but lets us use the modID as a guaranteed unique - // replacement for appID's - m_gameID.m_nModID = crc32 | (0x80000000); - } - - CGameID( const char *pchExePath, const char *pchAppName ) - { - m_ulGameID = 0; - m_gameID.m_nAppID = 0; - m_gameID.m_nType = k_EGameIDTypeShortcut; - - CRC32_t crc32; - CRC32_Init( &crc32 ); - CRC32_ProcessBuffer( &crc32, pchExePath, Q_strlen( pchExePath ) ); - CRC32_ProcessBuffer( &crc32, pchAppName, Q_strlen( pchAppName ) ); - CRC32_Final( &crc32 ); - - // set the high-bit on the mod-id - // reduces crc32 to 31bits, but lets us use the modID as a guaranteed unique - // replacement for appID's - m_gameID.m_nModID = crc32 | (0x80000000); - } -#endif - - void SetAsShortcut() - { - m_gameID.m_nAppID = 0; - m_gameID.m_nType = k_EGameIDTypeShortcut; - } - - void SetAsP2PFile() - { - m_gameID.m_nAppID = 0; - m_gameID.m_nType = k_EGameIDTypeP2P; - } - - uint64 ToUint64() const - { - return m_ulGameID; - } - - uint64 *GetUint64Ptr() - { - return &m_ulGameID; - } - - bool IsMod() const - { - return ( m_gameID.m_nType == k_EGameIDTypeGameMod ); - } - - bool IsShortcut() const - { - return ( m_gameID.m_nType == k_EGameIDTypeShortcut ); - } - - bool IsP2PFile() const - { - return ( m_gameID.m_nType == k_EGameIDTypeP2P ); - } - - bool IsSteamApp() const - { - return ( m_gameID.m_nType == k_EGameIDTypeApp ); - } - - - - uint32 ModID() const - { - return m_gameID.m_nModID; - } - - uint32 AppID() const - { - return m_gameID.m_nAppID; - } - - bool operator == ( const CGameID &rhs ) const - { - return m_ulGameID == rhs.m_ulGameID; - } - - bool operator != ( const CGameID &rhs ) const - { - return !(*this == rhs); - } - - bool operator < ( const CGameID &rhs ) const - { - return ( m_ulGameID < rhs.m_ulGameID ); - } - - bool IsValid() const - { - return ( m_ulGameID != 0 ); - } - - void Reset() - { - m_ulGameID = 0; - } - - - -private: - enum EGameIDType - { - k_EGameIDTypeApp = 0, - k_EGameIDTypeGameMod = 1, - k_EGameIDTypeShortcut = 2, - k_EGameIDTypeP2P = 3, - }; - - struct GameID_t - { - unsigned int m_nAppID : 24; - unsigned int m_nType : 8; - unsigned int m_nModID : 32; - }; - - union - { - uint64 m_ulGameID; - GameID_t m_gameID; - }; -}; - -#pragma pack( pop ) - -const int k_cchGameExtraInfoMax = 64; - - -// Max number of credit cards stored for one account -const int k_nMaxNumCardsPerAccount = 1; - - -//----------------------------------------------------------------------------- -// Constants used for query ports. -//----------------------------------------------------------------------------- - -#define QUERY_PORT_NOT_INITIALIZED 0xFFFF // We haven't asked the GS for this query port's actual value yet. -#define QUERY_PORT_ERROR 0xFFFE // We were unable to get the query port for this server. - -#endif // STEAMCLIENTPUBLIC_H diff --git a/public/steam/steamtypes.h b/public/steam/steamtypes.h deleted file mode 100644 index 71f1fb0c9..000000000 --- a/public/steam/steamtypes.h +++ /dev/null @@ -1,75 +0,0 @@ -//========= Copyright 1996-2004, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#ifndef STEAMTYPES_H -#define STEAMTYPES_H -#ifdef _WIN32 -#pragma once -#endif - -// Steam-specific types. Defined here so this header file can be included in other code bases. -#ifndef WCHARTYPES_H -typedef unsigned char uint8; -#endif - - -#if defined(__x86_64__) || defined(_WIN64) -#define X64BITS -#endif - -typedef unsigned char uint8; -typedef signed char int8; - -#if defined( _WIN32 ) - -typedef __int16 int16; -typedef unsigned __int16 uint16; -typedef __int32 int32; -typedef unsigned __int32 uint32; -typedef __int64 int64; -typedef unsigned __int64 uint64; - -#ifdef X64BITS -typedef __int64 intp; // intp is an integer that can accomodate a pointer -typedef unsigned __int64 uintp; // (ie, sizeof(intp) >= sizeof(int) && sizeof(intp) >= sizeof(void *) -#else -typedef __int32 intp; -typedef unsigned __int32 uintp; -#endif - -#else // _WIN32 - -typedef short int16; -typedef unsigned short uint16; -typedef int int32; -typedef unsigned int uint32; -typedef long long int64; -typedef unsigned long long uint64; -#ifdef X64BITS -typedef long long intp; -typedef unsigned long long uintp; -#else -typedef int intp; -typedef unsigned int uintp; -#endif - -#endif // else _WIN32 - -const int k_cubDigestSize = 20; // CryptoPP::SHA::DIGESTSIZE -const int k_cubSaltSize = 8; - -typedef uint8 SHADigest_t[ k_cubDigestSize ]; -typedef uint8 Salt_t[ k_cubSaltSize ]; - -typedef uint64 GID_t; // globally unique identifier - -// RTime32 -// We use this 32 bit time representing real world time. -// It offers 1 second resolution beginning on January 1, 1970 (Unix time) -typedef uint32 RTime32; - -#endif // STEAMTYPES_H diff --git a/public/string_t.h b/public/string_t.h deleted file mode 100644 index 0914199c5..000000000 --- a/public/string_t.h +++ /dev/null @@ -1,113 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Defines the more complete set of operations on the string_t defined -// These should be used instead of direct manipulation to allow more -// flexibility in future ports or optimization. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef STRING_T_H -#define STRING_T_H - -#if defined( _WIN32 ) -#pragma once -#endif - -#ifndef NO_STRING_T - -#ifdef WEAK_STRING_T - -typedef int string_t; - -//----------------------------------------------------------------------------- -// Purpose: The correct way to specify the NULL string as a constant. -//----------------------------------------------------------------------------- - -#define NULL_STRING 0 - -//----------------------------------------------------------------------------- -// Purpose: Given a string_t, make a C string. By convention the result string -// pointer should be considered transient and should not be stored. -//----------------------------------------------------------------------------- - -#define STRING( offset ) ( ( offset ) ? reinterpret_cast( offset ) : "" ) - -//----------------------------------------------------------------------------- -// Purpose: Given a C string, obtain a string_t -//----------------------------------------------------------------------------- - -#define MAKE_STRING( str ) ( ( *str != 0 ) ? reinterpret_cast( str ) : 0 ) - -//----------------------------------------------------------------------------- - -#define IDENT_STRINGS( s1, s2 ) ( *((void **)&(s1)) == *((void **)&(s2)) ) - -//----------------------------------------------------------------------------- - -#else // Strong string_t - -//----------------------------------------------------------------------------- - -struct string_t -{ -public: - bool operator!() const { return ( pszValue == NULL ); } - bool operator==( const string_t &rhs ) const { return ( pszValue == rhs.pszValue ); } - bool operator!=( const string_t &rhs ) const { return ( pszValue != rhs.pszValue ); } - bool operator<( const string_t &rhs ) const { return ((void *)pszValue < (void *)rhs.pszValue ); } - - const char *ToCStr() const { return ( pszValue ) ? pszValue : ""; } - -protected: - const char *pszValue; -}; - -//----------------------------------------------------------------------------- - -struct castable_string_t : public string_t // string_t is used in unions, hence, no constructor allowed -{ - castable_string_t() { pszValue = NULL; } - castable_string_t( const char *pszFrom ) { pszValue = (pszFrom && *pszFrom) ? pszFrom : 0; } -}; - -//----------------------------------------------------------------------------- -// Purpose: The correct way to specify the NULL string as a constant. -//----------------------------------------------------------------------------- - -#define NULL_STRING castable_string_t() - -//----------------------------------------------------------------------------- -// Purpose: Given a string_t, make a C string. By convention the result string -// pointer should be considered transient and should not be stored. -//----------------------------------------------------------------------------- - -#define STRING( string_t_obj ) (string_t_obj).ToCStr() - -//----------------------------------------------------------------------------- -// Purpose: Given a C string, obtain a string_t -//----------------------------------------------------------------------------- - -#define MAKE_STRING( c_str ) castable_string_t( c_str ) - -//----------------------------------------------------------------------------- - -#define IDENT_STRINGS( s1, s2 ) ( *((void **)&(s1)) == *((void **)&(s2)) ) - -//----------------------------------------------------------------------------- - -#endif - -#else // NO_STRING_T - -typedef const char *string_t; -#define NULL_STRING 0 -#define STRING( c_str ) ( c_str ) -#define MAKE_STRING( c_str ) ( c_str ) -#define IDENT_STRINGS( s1, s2 ) ( *((void **)&(s1)) == *((void **)&(s2)) ) - -#endif // NO_STRING_T - -//============================================================================= - -#endif // STRING_T_H diff --git a/public/stringregistry.cpp b/public/stringregistry.cpp deleted file mode 100644 index b1f65649f..000000000 --- a/public/stringregistry.cpp +++ /dev/null @@ -1,145 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: A registry of strings and associated ints -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - - -#include -#include -#include "stringregistry.h" -#include "utldict.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -#if !defined(_STATIC_LINKED) || defined(CLIENT_DLL) - -//----------------------------------------------------------------------------- -// Purpose: This class wraps the containers that do the actual work -//----------------------------------------------------------------------------- -struct StringTable_t : public CUtlDict -{ -}; - - - -//----------------------------------------------------------------------------- -// Purpose: Add null terminated string to the string registry -// Input : -// Output : -//----------------------------------------------------------------------------- -unsigned short CStringRegistry::AddString(const char *stringText, int stringID) -{ - return m_pStringList->Insert( stringText, stringID ); -} - -//----------------------------------------------------------------------------- -// Purpose: Given string text get the string ID -// Input : Text of string to find -// Output : Return string id or -1 if no such string exists -//----------------------------------------------------------------------------- -int CStringRegistry::GetStringID( const char *stringText ) -{ - unsigned short index = m_pStringList->Find( stringText ); - if ( m_pStringList->IsValidIndex( index ) ) - { - return (*m_pStringList)[index]; - } - - return -1; -} - -//----------------------------------------------------------------------------- -// Purpose: Given a string ID return the string text -// Input : ID of string to find -// Output : Return string text of NULL of no such ID exists -//----------------------------------------------------------------------------- -char const *CStringRegistry::GetStringText( int stringID ) -{ - for( unsigned short index = m_pStringList->First() ; index != m_pStringList->InvalidIndex(); index = m_pStringList->Next( index ) ) - { - if ( (*m_pStringList)[index] == stringID ) - { - return m_pStringList->GetElementName( index ); - } - } - - return NULL; -} - - -//----------------------------------------------------------------------------- -// Purpose: Given a key return the string text -//----------------------------------------------------------------------------- -char const *CStringRegistry::GetStringForKey( unsigned short key ) -{ - if ( !m_pStringList->IsValidIndex( key ) ) - return NULL; - - return m_pStringList->GetElementName( key ); -} - -//----------------------------------------------------------------------------- -// Purpose: Given a key return the string text -//----------------------------------------------------------------------------- -int CStringRegistry::GetIDForKey( unsigned short key ) -{ - if ( !m_pStringList->IsValidIndex( key ) ) - return 0; - - return (*m_pStringList)[key]; -} - -//----------------------------------------------------------------------------- -// Purpose: Clear all strings from the string registry -//----------------------------------------------------------------------------- -void CStringRegistry::ClearStrings(void) -{ - m_pStringList->RemoveAll(); -} - -//----------------------------------------------------------------------------- -// Purpose: Destructor - delete the list of strings and maps -// Input : -// Output : -//----------------------------------------------------------------------------- -CStringRegistry::~CStringRegistry(void) -{ - delete m_pStringList; -} - -//----------------------------------------------------------------------------- -// Purpose: Constructor -// Input : -// Output : -//----------------------------------------------------------------------------- -CStringRegistry::CStringRegistry(void) -{ - m_pStringList = new StringTable_t; -} - - -unsigned short CStringRegistry::First() const -{ - return m_pStringList->First(); -} - -unsigned short CStringRegistry::Next( unsigned short key ) const -{ - return m_pStringList->Next( key ); -} - -unsigned short CStringRegistry::InvalidIndex() const -{ - return m_pStringList->InvalidIndex(); -} - -#endif // _STATIC_LINKED && CLIENT_DLL diff --git a/public/stringregistry.h b/public/stringregistry.h deleted file mode 100644 index 2609aaafa..000000000 --- a/public/stringregistry.h +++ /dev/null @@ -1,57 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: A registry of strings and associated ints -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef STRINGREGISTRY_H -#define STRINGREGISTRY_H -#pragma once - -struct StringTable_t; - -//----------------------------------------------------------------------------- -// Purpose: Just a convenience/legacy wrapper for CUtlDict<> . -//----------------------------------------------------------------------------- -class CStringRegistry -{ -private: - StringTable_t *m_pStringList; - -public: - // returns a key for a given string - unsigned short AddString(const char *stringText, int stringID); - - // This is optimized. It will do 2 O(logN) searches - // Only one of the searches needs to compare strings, the other compares symbols (ints) - // returns -1 if the string is not present in the registry. - int GetStringID(const char *stringText); - - // This is unoptimized. It will linearly search (but only compares ints, not strings) - const char *GetStringText(int stringID); - - // This is O(1). It will not search. key MUST be a value that was returned by AddString - const char *GetStringForKey(unsigned short key); - // This is O(1). It will not search. key MUST be a value that was returned by AddString - int GetIDForKey(unsigned short key); - - void ClearStrings(void); - - - // Iterate all the keys. - unsigned short First() const; - unsigned short Next( unsigned short key ) const; - unsigned short InvalidIndex() const; - - ~CStringRegistry(void); // Need to free allocated memory - CStringRegistry(void); -}; - -#endif // STRINGREGISTRY_H diff --git a/public/studio.cpp b/public/studio.cpp deleted file mode 100644 index 107ac0c17..000000000 --- a/public/studio.cpp +++ /dev/null @@ -1,1823 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include "studio.h" -#include "datacache/idatacache.h" -#include "datacache/imdlcache.h" -#include "convar.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -mstudioanimdesc_t &studiohdr_t::pAnimdesc( int i ) const -{ - if (numincludemodels == 0) - { - return *pLocalAnimdesc( i ); - } - - virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel(); - Assert( pVModel ); - - virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_anim[i].group ]; - const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr(); - Assert( pStudioHdr ); - - return *pStudioHdr->pLocalAnimdesc( pVModel->m_anim[i].index ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -mstudioanim_t *mstudioanimdesc_t::pAnimBlock( int block, int index ) const -{ - if (block == -1) - { - return (mstudioanim_t *)NULL; - } - if (block == 0) - { - return (mstudioanim_t *)(((byte *)this) + index); - } - - byte *pAnimBlock = pStudiohdr()->GetAnimBlock( block ); - if ( pAnimBlock ) - { - return (mstudioanim_t *)(pAnimBlock + index); - } - - return (mstudioanim_t *)NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -static ConVar mod_load_showstall( "mod_load_showstall", "0", 0, "1 - show hitches , 2 - show stalls" ); -mstudioanim_t *mstudioanimdesc_t::pAnim( int *piFrame ) const -{ - float flStall; - return pAnim( piFrame, flStall ); -} - -mstudioanim_t *mstudioanimdesc_t::pAnim( int *piFrame, float &flStall ) const -{ - mstudioanim_t *panim = NULL; - - int block = animblock; - int index = animindex; - int section = 0; - - if (sectionframes != 0) - { - if (numframes > sectionframes && *piFrame == numframes - 1) - { - // last frame on long anims is stored separately - *piFrame = 0; - section = (numframes / sectionframes) + 1; - } - else - { - section = *piFrame / sectionframes; - *piFrame -= section * sectionframes; - } - - block = pSection( section )->animblock; - index = pSection( section )->animindex; - } - - if (block == -1) - { - // model needs to be recompiled - return NULL; - } - - panim = pAnimBlock( block, index ); - - // force a preload on the next block - if ( sectionframes != 0 ) - { - int count = ( numframes / sectionframes) + 2; - for ( int i = section + 1; i < count; i++ ) - { - if ( pSection( i )->animblock != block ) - { - pAnimBlock( pSection( i )->animblock, pSection( i )->animindex ); - break; - } - } - } - - if (panim == NULL) - { - if (section > 0 && mod_load_showstall.GetInt() > 0) - { - Msg("[%8.3f] hitch on %s:%s:%d:%d\n", Plat_FloatTime(), pStudiohdr()->pszName(), pszName(), section, block ); - } - // back up until a previously loaded block is found - while (--section >= 0) - { - block = pSection( section )->animblock; - index = pSection( section )->animindex; - panim = pAnimBlock( block, index ); - if (panim) - { - // set it to the last frame in the last valid section - *piFrame = sectionframes - 1; - break; - } - } - } - - // try to guess a valid stall time interval (tuned for the X360) - flStall = 0.0f; - if (panim == NULL && section <= 0) - { - zeroframestalltime = Plat_FloatTime(); - flStall = 1.0f; - } - else if (panim != NULL && zeroframestalltime != 0.0f) - { - float dt = Plat_FloatTime() - zeroframestalltime; - if (dt >= 0.0) - { - flStall = SimpleSpline( clamp( (0.200f - dt) * 5.0, 0.0f, 1.0f ) ); - } - - if (flStall == 0.0f) - { - // disable stalltime - zeroframestalltime = 0.0f; - } - else if (mod_load_showstall.GetInt() > 1) - { - Msg("[%8.3f] stall blend %.2f on %s:%s:%d:%d\n", Plat_FloatTime(), flStall, pStudiohdr()->pszName(), pszName(), section, block ); - } - } - - if (panim == NULL && mod_load_showstall.GetInt() > 1) - { - Msg("[%8.3f] stall on %s:%s:%d:%d\n", Plat_FloatTime(), pStudiohdr()->pszName(), pszName(), section, block ); - } - - return panim; -} - -mstudioikrule_t *mstudioanimdesc_t::pIKRule( int i ) const -{ - if (ikruleindex) - { - return (mstudioikrule_t *)(((byte *)this) + ikruleindex) + i; - } - else if (animblockikruleindex) - { - if (animblock == 0) - { - return (mstudioikrule_t *)(((byte *)this) + animblockikruleindex) + i; - } - else - { - byte *pAnimBlocks = pStudiohdr()->GetAnimBlock( animblock ); - - if ( pAnimBlocks ) - { - return (mstudioikrule_t *)(pAnimBlocks + animblockikruleindex) + i; - } - } - } - - return NULL; -} - - -mstudiolocalhierarchy_t *mstudioanimdesc_t::pHierarchy( int i ) const -{ - if (localhierarchyindex) - { - if (animblock == 0) - { - return (mstudiolocalhierarchy_t *)(((byte *)this) + localhierarchyindex) + i; - } - else - { - byte *pAnimBlocks = pStudiohdr()->GetAnimBlock( animblock ); - - if ( pAnimBlocks ) - { - return (mstudiolocalhierarchy_t *)(pAnimBlocks + localhierarchyindex) + i; - } - } - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -bool studiohdr_t::SequencesAvailable() const -{ - if (numincludemodels == 0) - { - return true; - } - - return ( GetVirtualModel() != NULL ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -int studiohdr_t::GetNumSeq( void ) const -{ - if (numincludemodels == 0) - { - return numlocalseq; - } - - virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel(); - Assert( pVModel ); - return pVModel->m_seq.Count(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -mstudioseqdesc_t &studiohdr_t::pSeqdesc( int i ) const -{ - if (numincludemodels == 0) - { - return *pLocalSeqdesc( i ); - } - - virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel(); - Assert( pVModel ); - - if ( !pVModel ) - { - return *pLocalSeqdesc( i ); - } - - virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_seq[i].group ]; - const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr(); - Assert( pStudioHdr ); - - return *pStudioHdr->pLocalSeqdesc( pVModel->m_seq[i].index ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -int studiohdr_t::iRelativeAnim( int baseseq, int relanim ) const -{ - if (numincludemodels == 0) - { - return relanim; - } - - virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel(); - Assert( pVModel ); - - virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_seq[baseseq].group ]; - - return pGroup->masterAnim[ relanim ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -int studiohdr_t::iRelativeSeq( int baseseq, int relseq ) const -{ - if (numincludemodels == 0) - { - return relseq; - } - - virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel(); - Assert( pVModel ); - - virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_seq[baseseq].group ]; - - return pGroup->masterSeq[ relseq ]; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -int studiohdr_t::GetNumPoseParameters( void ) const -{ - if (numincludemodels == 0) - { - return numlocalposeparameters; - } - - virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel(); - Assert( pVModel ); - - return pVModel->m_pose.Count(); -} - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -const mstudioposeparamdesc_t &studiohdr_t::pPoseParameter( int i ) const -{ - if (numincludemodels == 0) - { - return *pLocalPoseParameter( i ); - } - - virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel(); - Assert( pVModel ); - - if ( pVModel->m_pose[i].group == 0) - return *pLocalPoseParameter( pVModel->m_pose[i].index ); - - virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_pose[i].group ]; - - const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr(); - Assert( pStudioHdr ); - - return *pStudioHdr->pLocalPoseParameter( pVModel->m_pose[i].index ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -int studiohdr_t::GetSharedPoseParameter( int iSequence, int iLocalPose ) const -{ - if (numincludemodels == 0) - { - return iLocalPose; - } - - if (iLocalPose == -1) - return iLocalPose; - - virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel(); - Assert( pVModel ); - - virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_seq[iSequence].group ]; - - return pGroup->masterPose[iLocalPose]; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -int studiohdr_t::EntryNode( int iSequence ) const -{ - mstudioseqdesc_t &seqdesc = pSeqdesc( iSequence ); - - if (numincludemodels == 0 || seqdesc.localentrynode == 0) - { - return seqdesc.localentrynode; - } - - virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel(); - Assert( pVModel ); - - virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_seq[iSequence].group ]; - - return pGroup->masterNode[seqdesc.localentrynode-1]+1; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - - -int studiohdr_t::ExitNode( int iSequence ) const -{ - mstudioseqdesc_t &seqdesc = pSeqdesc( iSequence ); - - if (numincludemodels == 0 || seqdesc.localexitnode == 0) - { - return seqdesc.localexitnode; - } - - virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel(); - Assert( pVModel ); - - virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_seq[iSequence].group ]; - - return pGroup->masterNode[seqdesc.localexitnode-1]+1; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -int studiohdr_t::GetNumAttachments( void ) const -{ - if (numincludemodels == 0) - { - return numlocalattachments; - } - - virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel(); - Assert( pVModel ); - - return pVModel->m_attachment.Count(); -} - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -const mstudioattachment_t &studiohdr_t::pAttachment( int i ) const -{ - if (numincludemodels == 0) - { - return *pLocalAttachment( i ); - } - - virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel(); - Assert( pVModel ); - - virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_attachment[i].group ]; - const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr(); - Assert( pStudioHdr ); - - return *pStudioHdr->pLocalAttachment( pVModel->m_attachment[i].index ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -int studiohdr_t::GetAttachmentBone( int i ) const -{ - const mstudioattachment_t &attachment = pAttachment( i ); - - // remap bone - virtualmodel_t *pVModel = GetVirtualModel(); - if (pVModel) - { - virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_attachment[i].group ]; - int iBone = pGroup->masterBone[attachment.localbone]; - if (iBone == -1) - return 0; - return iBone; - } - return attachment.localbone; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -void studiohdr_t::SetAttachmentBone( int iAttachment, int iBone ) -{ - mstudioattachment_t &attachment = (mstudioattachment_t &)pAttachment( iAttachment ); - - // remap bone - virtualmodel_t *pVModel = GetVirtualModel(); - if (pVModel) - { - virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_attachment[iAttachment].group ]; - iBone = pGroup->boneMap[iBone]; - } - attachment.localbone = iBone; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -const char *studiohdr_t::pszNodeName( int iNode ) const -{ - if (numincludemodels == 0) - { - return pszLocalNodeName( iNode ); - } - - virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel(); - Assert( pVModel ); - - if ( pVModel->m_node.Count() <= iNode-1 ) - return "Invalid node"; - - return pVModel->m_group[ pVModel->m_node[iNode-1].group ].GetStudioHdr()->pszLocalNodeName( pVModel->m_node[iNode-1].index ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -int studiohdr_t::GetTransition( int iFrom, int iTo ) const -{ - if (numincludemodels == 0) - { - return *pLocalTransition( (iFrom-1)*numlocalnodes + (iTo - 1) ); - } - - return iTo; - /* - FIXME: not connected - virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel(); - Assert( pVModel ); - - return pVModel->m_transition.Element( iFrom ).Element( iTo ); - */ -} - - -int studiohdr_t::GetActivityListVersion( void ) const -{ - if (numincludemodels == 0) - { - return activitylistversion; - } - - virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel(); - Assert( pVModel ); - - int version = activitylistversion; - - int i; - for (i = 1; i < pVModel->m_group.Count(); i++) - { - virtualgroup_t *pGroup = &pVModel->m_group[ i ]; - const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr(); - - Assert( pStudioHdr ); - - version = MIN( version, pStudioHdr->activitylistversion ); - } - - return version; -} - -void studiohdr_t::SetActivityListVersion( int version ) const -{ - activitylistversion = version; - - if (numincludemodels == 0) - { - return; - } - - virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel(); - Assert( pVModel ); - - int i; - for (i = 1; i < pVModel->m_group.Count(); i++) - { - virtualgroup_t *pGroup = &pVModel->m_group[ i ]; - const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr(); - - Assert( pStudioHdr ); - - pStudioHdr->SetActivityListVersion( version ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - - -int studiohdr_t::GetNumIKAutoplayLocks( void ) const -{ - if (numincludemodels == 0) - { - return numlocalikautoplaylocks; - } - - virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel(); - Assert( pVModel ); - - return pVModel->m_iklock.Count(); -} - -const mstudioiklock_t &studiohdr_t::pIKAutoplayLock( int i ) const -{ - if (numincludemodels == 0) - { - return *pLocalIKAutoplayLock( i ); - } - - virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel(); - Assert( pVModel ); - - virtualgroup_t *pGroup = &pVModel->m_group[ pVModel->m_iklock[i].group ]; - const studiohdr_t *pStudioHdr = pGroup->GetStudioHdr(); - Assert( pStudioHdr ); - - return *pStudioHdr->pLocalIKAutoplayLock( pVModel->m_iklock[i].index ); -} - -int studiohdr_t::CountAutoplaySequences() const -{ - int count = 0; - for (int i = 0; i < GetNumSeq(); i++) - { - mstudioseqdesc_t &seqdesc = pSeqdesc( i ); - if (seqdesc.flags & STUDIO_AUTOPLAY) - { - count++; - } - } - return count; -} - -int studiohdr_t::CopyAutoplaySequences( unsigned short *pOut, int outCount ) const -{ - int outIndex = 0; - for (int i = 0; i < GetNumSeq() && outIndex < outCount; i++) - { - mstudioseqdesc_t &seqdesc = pSeqdesc( i ); - if (seqdesc.flags & STUDIO_AUTOPLAY) - { - pOut[outIndex] = i; - outIndex++; - } - } - return outIndex; -} - -//----------------------------------------------------------------------------- -// Purpose: maps local sequence bone to global bone -//----------------------------------------------------------------------------- - -int studiohdr_t::RemapSeqBone( int iSequence, int iLocalBone ) const -{ - // remap bone - virtualmodel_t *pVModel = GetVirtualModel(); - if (pVModel) - { - const virtualgroup_t *pSeqGroup = pVModel->pSeqGroup( iSequence ); - return pSeqGroup->masterBone[iLocalBone]; - } - return iLocalBone; -} - -int studiohdr_t::RemapAnimBone( int iAnim, int iLocalBone ) const -{ - // remap bone - virtualmodel_t *pVModel = GetVirtualModel(); - if (pVModel) - { - const virtualgroup_t *pAnimGroup = pVModel->pAnimGroup( iAnim ); - return pAnimGroup->masterBone[iLocalBone]; - } - return iLocalBone; -} - - - - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -CStudioHdr::CStudioHdr( void ) -{ - // set pointer to bogus value - m_nFrameUnlockCounter = 0; - m_pFrameUnlockCounter = &m_nFrameUnlockCounter; - Init( NULL ); -} - -CStudioHdr::CStudioHdr( const studiohdr_t *pStudioHdr, IMDLCache *mdlcache ) -{ - // preset pointer to bogus value (it may be overwritten with legitimate data later) - m_nFrameUnlockCounter = 0; - m_pFrameUnlockCounter = &m_nFrameUnlockCounter; - Init( pStudioHdr, mdlcache ); -} - - -// extern IDataCache *g_pDataCache; - -void CStudioHdr::Init( const studiohdr_t *pStudioHdr, IMDLCache *mdlcache ) -{ - m_pStudioHdr = pStudioHdr; - - m_pVModel = NULL; - m_pStudioHdrCache.RemoveAll(); - - if (m_pStudioHdr == NULL) - { - return; - } - - if ( mdlcache ) - { - m_pFrameUnlockCounter = mdlcache->GetFrameUnlockCounterPtr( MDLCACHE_STUDIOHDR ); - m_nFrameUnlockCounter = *m_pFrameUnlockCounter - 1; - } - - if (m_pStudioHdr->numincludemodels == 0) - { -#if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE -#else - m_ActivityToSequence.Initialize(this); -#endif - } - else - { - ResetVModel( m_pStudioHdr->GetVirtualModel() ); -#if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE -#else - m_ActivityToSequence.Initialize(this); -#endif - } - - m_boneFlags.EnsureCount( numbones() ); - m_boneParent.EnsureCount( numbones() ); - for (int i = 0; i < numbones(); i++) - { - m_boneFlags[i] = pBone( i )->flags; - m_boneParent[i] = pBone( i )->parent; - } -} - -void CStudioHdr::Term() -{ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -bool CStudioHdr::SequencesAvailable() const -{ - if (m_pStudioHdr->numincludemodels == 0) - { - return true; - } - - if (m_pVModel == NULL) - { - // repoll m_pVModel - return (ResetVModel( m_pStudioHdr->GetVirtualModel() ) != NULL); - } - else - return true; -} - - -const virtualmodel_t * CStudioHdr::ResetVModel( const virtualmodel_t *pVModel ) const -{ - if (pVModel != NULL) - { - m_pVModel = (virtualmodel_t *)pVModel; - #if defined(_WIN32) && !defined(THREAD_PROFILER) - Assert( !pVModel->m_Lock.GetOwnerId() ); - #endif - m_pStudioHdrCache.SetCount( m_pVModel->m_group.Count() ); - - int i; - for (i = 0; i < m_pStudioHdrCache.Count(); i++) - { - m_pStudioHdrCache[ i ] = NULL; - } - - return const_cast(pVModel); - } - else - { - m_pVModel = NULL; - return NULL; - } -} - -const studiohdr_t *CStudioHdr::GroupStudioHdr( int i ) const -{ - if ( !this ) - { - ExecuteNTimes( 5, Warning( "Call to NULL CStudioHdr::GroupStudioHdr()\n" ) ); - } - - if ( m_nFrameUnlockCounter != *m_pFrameUnlockCounter ) - { - m_FrameUnlockCounterMutex.Lock(); - if ( *m_pFrameUnlockCounter != m_nFrameUnlockCounter ) // i.e., this thread got the mutex - { - memset( m_pStudioHdrCache.Base(), 0, m_pStudioHdrCache.Count() * sizeof(studiohdr_t *) ); - m_nFrameUnlockCounter = *m_pFrameUnlockCounter; - } - m_FrameUnlockCounterMutex.Unlock(); - } - - if ( !m_pStudioHdrCache.IsValidIndex( i ) ) - { - const char *pszName = ( m_pStudioHdr ) ? m_pStudioHdr->pszName() : "<>"; - ExecuteNTimes( 5, Warning( "Invalid index passed to CStudioHdr(%s)::GroupStudioHdr(): %d, but max is %d [%d]\n", pszName, i, m_pStudioHdrCache.Count() ) ); - DebuggerBreakIfDebugging(); - return m_pStudioHdr; // return something known to probably exist, certainly things will be messed up, but hopefully not crash before the warning is noticed - } - - const studiohdr_t *pStudioHdr = m_pStudioHdrCache[ i ]; - - if (pStudioHdr == NULL) - { - #if defined(_WIN32) && !defined(THREAD_PROFILER) - Assert( !m_pVModel->m_Lock.GetOwnerId() ); - #endif - virtualgroup_t *pGroup = &m_pVModel->m_group[ i ]; - pStudioHdr = pGroup->GetStudioHdr(); - m_pStudioHdrCache[ i ] = pStudioHdr; - } - - Assert( pStudioHdr ); - return pStudioHdr; -} - - -const studiohdr_t *CStudioHdr::pSeqStudioHdr( int sequence ) const -{ - if (m_pVModel == NULL) - { - return m_pStudioHdr; - } - - const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_seq[sequence].group ); - - return pStudioHdr; -} - - -const studiohdr_t *CStudioHdr::pAnimStudioHdr( int animation ) const -{ - if (m_pVModel == NULL) - { - return m_pStudioHdr; - } - - const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_anim[animation].group ); - - return pStudioHdr; -} - - - -mstudioanimdesc_t &CStudioHdr::pAnimdesc( int i ) const -{ - if (m_pVModel == NULL) - { - return *m_pStudioHdr->pLocalAnimdesc( i ); - } - - const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_anim[i].group ); - - return *pStudioHdr->pLocalAnimdesc( m_pVModel->m_anim[i].index ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -int CStudioHdr::GetNumSeq( void ) const -{ - if (m_pVModel == NULL) - { - return m_pStudioHdr->numlocalseq; - } - - return m_pVModel->m_seq.Count(); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -mstudioseqdesc_t &CStudioHdr::pSeqdesc( int i ) const -{ - Assert( i >= 0 && i < GetNumSeq() ); - if ( i < 0 || i >= GetNumSeq() ) - { - // Avoid reading random memory. - i = 0; - } - - if (m_pVModel == NULL) - { - return *m_pStudioHdr->pLocalSeqdesc( i ); - } - - const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_seq[i].group ); - - return *pStudioHdr->pLocalSeqdesc( m_pVModel->m_seq[i].index ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -int CStudioHdr::iRelativeAnim( int baseseq, int relanim ) const -{ - if (m_pVModel == NULL) - { - return relanim; - } - - virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_seq[baseseq].group ]; - - return pGroup->masterAnim[ relanim ]; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -int CStudioHdr::iRelativeSeq( int baseseq, int relseq ) const -{ - if (m_pVModel == NULL) - { - return relseq; - } - - Assert( m_pVModel ); - - virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_seq[baseseq].group ]; - - return pGroup->masterSeq[ relseq ]; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -int CStudioHdr::GetNumPoseParameters( void ) const -{ - if (m_pVModel == NULL) - { - return m_pStudioHdr->numlocalposeparameters; - } - - Assert( m_pVModel ); - - return m_pVModel->m_pose.Count(); -} - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -const mstudioposeparamdesc_t &CStudioHdr::pPoseParameter( int i ) const -{ - if (m_pVModel == NULL) - { - return *m_pStudioHdr->pLocalPoseParameter( i ); - } - - if ( m_pVModel->m_pose[i].group == 0) - return *m_pStudioHdr->pLocalPoseParameter( m_pVModel->m_pose[i].index ); - - const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_pose[i].group ); - - return *pStudioHdr->pLocalPoseParameter( m_pVModel->m_pose[i].index ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -int CStudioHdr::GetSharedPoseParameter( int iSequence, int iLocalPose ) const -{ - if (m_pVModel == NULL) - { - return iLocalPose; - } - - if (iLocalPose == -1) - return iLocalPose; - - Assert( m_pVModel ); - - virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_seq[iSequence].group ]; - - return pGroup->masterPose[iLocalPose]; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -int CStudioHdr::EntryNode( int iSequence ) const -{ - mstudioseqdesc_t &seqdesc = pSeqdesc( iSequence ); - - if (m_pVModel == NULL || seqdesc.localentrynode == 0) - { - return seqdesc.localentrynode; - } - - Assert( m_pVModel ); - - virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_seq[iSequence].group ]; - - return pGroup->masterNode[seqdesc.localentrynode-1]+1; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - - -int CStudioHdr::ExitNode( int iSequence ) const -{ - mstudioseqdesc_t &seqdesc = pSeqdesc( iSequence ); - - if (m_pVModel == NULL || seqdesc.localexitnode == 0) - { - return seqdesc.localexitnode; - } - - Assert( m_pVModel ); - - virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_seq[iSequence].group ]; - - return pGroup->masterNode[seqdesc.localexitnode-1]+1; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -int CStudioHdr::GetNumAttachments( void ) const -{ - if (m_pVModel == NULL) - { - return m_pStudioHdr->numlocalattachments; - } - - Assert( m_pVModel ); - - return m_pVModel->m_attachment.Count(); -} - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -const mstudioattachment_t &CStudioHdr::pAttachment( int i ) const -{ - if (m_pVModel == NULL) - { - return *m_pStudioHdr->pLocalAttachment( i ); - } - - Assert( m_pVModel ); - - const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_attachment[i].group ); - - return *pStudioHdr->pLocalAttachment( m_pVModel->m_attachment[i].index ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -int CStudioHdr::GetAttachmentBone( int i ) const -{ - if (m_pVModel == 0) - { - return m_pStudioHdr->pLocalAttachment( i )->localbone; - } - - virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_attachment[i].group ]; - const mstudioattachment_t &attachment = pAttachment( i ); - int iBone = pGroup->masterBone[attachment.localbone]; - if (iBone == -1) - return 0; - return iBone; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -void CStudioHdr::SetAttachmentBone( int iAttachment, int iBone ) -{ - mstudioattachment_t &attachment = (mstudioattachment_t &)m_pStudioHdr->pAttachment( iAttachment ); - - // remap bone - if (m_pVModel) - { - virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_attachment[iAttachment].group ]; - iBone = pGroup->boneMap[iBone]; - } - attachment.localbone = iBone; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -const char *CStudioHdr::pszNodeName( int iNode ) const -{ - if (m_pVModel == NULL) - { - return m_pStudioHdr->pszLocalNodeName( iNode ); - } - - if ( m_pVModel->m_node.Count() <= iNode-1 ) - return "Invalid node"; - - const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_node[iNode-1].group ); - - return pStudioHdr->pszLocalNodeName( m_pVModel->m_node[iNode-1].index ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -int CStudioHdr::GetTransition( int iFrom, int iTo ) const -{ - if (m_pVModel == NULL) - { - return *m_pStudioHdr->pLocalTransition( (iFrom-1)*m_pStudioHdr->numlocalnodes + (iTo - 1) ); - } - - return iTo; - /* - FIXME: not connected - virtualmodel_t *pVModel = (virtualmodel_t *)GetVirtualModel(); - Assert( pVModel ); - - return pVModel->m_transition.Element( iFrom ).Element( iTo ); - */ -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -int CStudioHdr::GetActivityListVersion( void ) const -{ - if (m_pVModel == NULL) - { - return m_pStudioHdr->activitylistversion; - } - - int version = m_pStudioHdr->activitylistversion; - - int i; - for (i = 1; i < m_pVModel->m_group.Count(); i++) - { - const studiohdr_t *pStudioHdr = GroupStudioHdr( i ); - Assert( pStudioHdr ); - version = MIN( version, pStudioHdr->activitylistversion ); - } - - return version; -} - -void CStudioHdr::SetActivityListVersion( int version ) -{ - m_pStudioHdr->activitylistversion = version; - - if (m_pVModel == NULL) - { - return; - } - - int i; - for (i = 1; i < m_pVModel->m_group.Count(); i++) - { - const studiohdr_t *pStudioHdr = GroupStudioHdr( i ); - Assert( pStudioHdr ); - pStudioHdr->SetActivityListVersion( version ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -int CStudioHdr::GetEventListVersion( void ) const -{ - if (m_pVModel == NULL) - { - return m_pStudioHdr->eventsindexed; - } - - int version = m_pStudioHdr->eventsindexed; - - int i; - for (i = 1; i < m_pVModel->m_group.Count(); i++) - { - const studiohdr_t *pStudioHdr = GroupStudioHdr( i ); - Assert( pStudioHdr ); - version = MIN( version, pStudioHdr->eventsindexed ); - } - - return version; -} - -void CStudioHdr::SetEventListVersion( int version ) -{ - m_pStudioHdr->eventsindexed = version; - - if (m_pVModel == NULL) - { - return; - } - - int i; - for (i = 1; i < m_pVModel->m_group.Count(); i++) - { - const studiohdr_t *pStudioHdr = GroupStudioHdr( i ); - Assert( pStudioHdr ); - pStudioHdr->eventsindexed = version; - } -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - - -int CStudioHdr::GetNumIKAutoplayLocks( void ) const -{ - if (m_pVModel == NULL) - { - return m_pStudioHdr->numlocalikautoplaylocks; - } - - return m_pVModel->m_iklock.Count(); -} - -const mstudioiklock_t &CStudioHdr::pIKAutoplayLock( int i ) const -{ - if (m_pVModel == NULL) - { - return *m_pStudioHdr->pLocalIKAutoplayLock( i ); - } - - const studiohdr_t *pStudioHdr = GroupStudioHdr( m_pVModel->m_iklock[i].group ); - Assert( pStudioHdr ); - return *pStudioHdr->pLocalIKAutoplayLock( m_pVModel->m_iklock[i].index ); -} - -#if 0 -int CStudioHdr::CountAutoplaySequences() const -{ - int count = 0; - for (int i = 0; i < GetNumSeq(); i++) - { - mstudioseqdesc_t &seqdesc = pSeqdesc( i ); - if (seqdesc.flags & STUDIO_AUTOPLAY) - { - count++; - } - } - return count; -} - -int CStudioHdr::CopyAutoplaySequences( unsigned short *pOut, int outCount ) const -{ - int outIndex = 0; - for (int i = 0; i < GetNumSeq() && outIndex < outCount; i++) - { - mstudioseqdesc_t &seqdesc = pSeqdesc( i ); - if (seqdesc.flags & STUDIO_AUTOPLAY) - { - pOut[outIndex] = i; - outIndex++; - } - } - return outIndex; -} - -#endif - -//----------------------------------------------------------------------------- -// Purpose: maps local sequence bone to global bone -//----------------------------------------------------------------------------- - -int CStudioHdr::RemapSeqBone( int iSequence, int iLocalBone ) const -{ - // remap bone - if (m_pVModel) - { - const virtualgroup_t *pSeqGroup = m_pVModel->pSeqGroup( iSequence ); - return pSeqGroup->masterBone[iLocalBone]; - } - return iLocalBone; -} - -int CStudioHdr::RemapAnimBone( int iAnim, int iLocalBone ) const -{ - // remap bone - if (m_pVModel) - { - const virtualgroup_t *pAnimGroup = m_pVModel->pAnimGroup( iAnim ); - return pAnimGroup->masterBone[iLocalBone]; - } - return iLocalBone; -} - -// JasonM hack -//ConVar flex_maxrule( "flex_maxrule", "0" ); - - -//----------------------------------------------------------------------------- -// Purpose: run the interpreted FAC's expressions, converting flex_controller -// values into FAC weights -//----------------------------------------------------------------------------- -void CStudioHdr::RunFlexRules( const float *src, float *dest ) -{ - int i, j; - - // FIXME: this shouldn't be needed, flex without rules should be stripped in studiomdl - for (i = 0; i < numflexdesc(); i++) - { - dest[i] = 0; - } - - for (i = 0; i < numflexrules(); i++) - { - float stack[32]; - int k = 0; - mstudioflexrule_t *prule = pFlexRule( i ); - - mstudioflexop_t *pops = prule->iFlexOp( 0 ); -/* - // JasonM hack for flex perf testing... - int nFlexRulesToRun = 0; // 0 means run them all - const char *pszExpression = flex_maxrule.GetString(); - if ( pszExpression ) - { - nFlexRulesToRun = atoi(pszExpression); // 0 will be returned if not a numeric string - } - // end JasonM hack -//*/ - // debugoverlay->AddTextOverlay( GetAbsOrigin() + Vector( 0, 0, 64 ), i + 1, 0, "%2d:%d\n", i, prule->flex ); - - for (j = 0; j < prule->numops; j++) - { - switch (pops->op) - { - case STUDIO_ADD: stack[k-2] = stack[k-2] + stack[k-1]; k--; break; - case STUDIO_SUB: stack[k-2] = stack[k-2] - stack[k-1]; k--; break; - case STUDIO_MUL: stack[k-2] = stack[k-2] * stack[k-1]; k--; break; - case STUDIO_DIV: - if (stack[k-1] > 0.0001) - { - stack[k-2] = stack[k-2] / stack[k-1]; - } - else - { - stack[k-2] = 0; - } - k--; - break; - case STUDIO_NEG: stack[k-1] = -stack[k-1]; break; - case STUDIO_MAX: stack[k-2] = MAX( stack[k-2], stack[k-1] ); k--; break; - case STUDIO_MIN: stack[k-2] = MIN( stack[k-2], stack[k-1] ); k--; break; - case STUDIO_CONST: stack[k] = pops->d.value; k++; break; - case STUDIO_FETCH1: - { - int m = pFlexcontroller( (LocalFlexController_t)pops->d.index)->localToGlobal; - stack[k] = src[m]; - k++; - break; - } - case STUDIO_FETCH2: - { - stack[k] = dest[pops->d.index]; k++; break; - } - case STUDIO_COMBO: - { - int m = pops->d.index; - int km = k - m; - for ( int i = km + 1; i < k; ++i ) - { - stack[ km ] *= stack[ i ]; - } - k = k - m + 1; - } - break; - case STUDIO_DOMINATE: - { - int m = pops->d.index; - int km = k - m; - float dv = stack[ km ]; - for ( int i = km + 1; i < k; ++i ) - { - dv *= stack[ i ]; - } - stack[ km - 1 ] *= 1.0f - dv; - k -= m; - } - break; - case STUDIO_2WAY_0: - { - int m = pFlexcontroller( (LocalFlexController_t)pops->d.index )->localToGlobal; - stack[ k ] = RemapValClamped( src[m], -1.0f, 0.0f, 1.0f, 0.0f ); - k++; - } - break; - case STUDIO_2WAY_1: - { - int m = pFlexcontroller( (LocalFlexController_t)pops->d.index )->localToGlobal; - stack[ k ] = RemapValClamped( src[m], 0.0f, 1.0f, 0.0f, 1.0f ); - k++; - } - break; - case STUDIO_NWAY: - { - LocalFlexController_t valueControllerIndex = static_cast< LocalFlexController_t >( (int)stack[ k - 1 ] ); - int m = pFlexcontroller( valueControllerIndex )->localToGlobal; - float flValue = src[ m ]; - int v = pFlexcontroller( (LocalFlexController_t)pops->d.index )->localToGlobal; - - const Vector4D filterRamp( stack[ k - 5 ], stack[ k - 4 ], stack[ k - 3 ], stack[ k - 2 ] ); - - // Apply multicontrol remapping - if ( flValue <= filterRamp.x || flValue >= filterRamp.w ) - { - flValue = 0.0f; - } - else if ( flValue < filterRamp.y ) - { - flValue = RemapValClamped( flValue, filterRamp.x, filterRamp.y, 0.0f, 1.0f ); - } - else if ( flValue > filterRamp.z ) - { - flValue = RemapValClamped( flValue, filterRamp.z, filterRamp.w, 1.0f, 0.0f ); - } - else - { - flValue = 1.0f; - } - - stack[ k - 5 ] = flValue * src[ v ]; - - k -= 4; - } - break; - case STUDIO_DME_LOWER_EYELID: - { - const mstudioflexcontroller_t *const pCloseLidV = pFlexcontroller( (LocalFlexController_t)pops->d.index ); - const float flCloseLidV = RemapValClamped( src[ pCloseLidV->localToGlobal ], pCloseLidV->min, pCloseLidV->max, 0.0f, 1.0f ); - - const mstudioflexcontroller_t *const pCloseLid = pFlexcontroller( static_cast< LocalFlexController_t >( (int)stack[ k - 1 ] ) ); - const float flCloseLid = RemapValClamped( src[ pCloseLid->localToGlobal ], pCloseLid->min, pCloseLid->max, 0.0f, 1.0f ); - - int nBlinkIndex = static_cast< int >( stack[ k - 2 ] ); - float flBlink = 0.0f; - if ( nBlinkIndex >= 0 ) - { - const mstudioflexcontroller_t *const pBlink = pFlexcontroller( static_cast< LocalFlexController_t >( (int)stack[ k - 2 ] ) ); - flBlink = RemapValClamped( src[ pBlink->localToGlobal ], pBlink->min, pBlink->max, 0.0f, 1.0f ); - } - - int nEyeUpDownIndex = static_cast< int >( stack[ k - 3 ] ); - float flEyeUpDown = 0.0f; - if ( nEyeUpDownIndex >= 0 ) - { - const mstudioflexcontroller_t *const pEyeUpDown = pFlexcontroller( static_cast< LocalFlexController_t >( (int)stack[ k - 3 ] ) ); - flEyeUpDown = RemapValClamped( src[ pEyeUpDown->localToGlobal ], pEyeUpDown->min, pEyeUpDown->max, -1.0f, 1.0f ); - } - - if ( flEyeUpDown > 0.0 ) - { - stack [ k - 3 ] = ( 1.0f - flEyeUpDown ) * ( 1.0f - flCloseLidV ) * flCloseLid; - } - else - { - stack [ k - 3 ] = ( 1.0f - flCloseLidV ) * flCloseLid; - } - k -= 2; - } - break; - case STUDIO_DME_UPPER_EYELID: - { - const mstudioflexcontroller_t *const pCloseLidV = pFlexcontroller( (LocalFlexController_t)pops->d.index ); - const float flCloseLidV = RemapValClamped( src[ pCloseLidV->localToGlobal ], pCloseLidV->min, pCloseLidV->max, 0.0f, 1.0f ); - - const mstudioflexcontroller_t *const pCloseLid = pFlexcontroller( static_cast< LocalFlexController_t >( (int)stack[ k - 1 ] ) ); - const float flCloseLid = RemapValClamped( src[ pCloseLid->localToGlobal ], pCloseLid->min, pCloseLid->max, 0.0f, 1.0f ); - - int nBlinkIndex = static_cast< int >( stack[ k - 2 ] ); - float flBlink = 0.0f; - if ( nBlinkIndex >= 0 ) - { - const mstudioflexcontroller_t *const pBlink = pFlexcontroller( static_cast< LocalFlexController_t >( (int)stack[ k - 2 ] ) ); - flBlink = RemapValClamped( src[ pBlink->localToGlobal ], pBlink->min, pBlink->max, 0.0f, 1.0f ); - } - - int nEyeUpDownIndex = static_cast< int >( stack[ k - 3 ] ); - float flEyeUpDown = 0.0f; - if ( nEyeUpDownIndex >= 0 ) - { - const mstudioflexcontroller_t *const pEyeUpDown = pFlexcontroller( static_cast< LocalFlexController_t >( (int)stack[ k - 3 ] ) ); - flEyeUpDown = RemapValClamped( src[ pEyeUpDown->localToGlobal ], pEyeUpDown->min, pEyeUpDown->max, -1.0f, 1.0f ); - } - - if ( flEyeUpDown < 0.0f ) - { - stack [ k - 3 ] = ( 1.0f + flEyeUpDown ) * flCloseLidV * flCloseLid; - } - else - { - stack [ k - 3 ] = flCloseLidV * flCloseLid; - } - k -= 2; - } - break; - } - - pops++; - } - - dest[prule->flex] = stack[0]; -/* - // JasonM hack - if ( nFlexRulesToRun == 0) // 0 means run all rules correctly - { - dest[prule->flex] = stack[0]; - } - else // run only up to nFlexRulesToRun correctly...zero out the rest - { - if ( j < nFlexRulesToRun ) - dest[prule->flex] = stack[0]; - else - dest[prule->flex] = 0.0f; - } - - dest[prule->flex] = 1.0f; -//*/ - // end JasonM hack - - } -} - - - -//----------------------------------------------------------------------------- -// CODE PERTAINING TO ACTIVITY->SEQUENCE MAPPING SUBCLASS -//----------------------------------------------------------------------------- -#define iabs(i) (( (i) >= 0 ) ? (i) : -(i) ) - - -extern void SetActivityForSequence( CStudioHdr *pstudiohdr, int i ); -void CStudioHdr::CActivityToSequenceMapping::Initialize( CStudioHdr * __restrict pstudiohdr ) -{ - // Algorithm: walk through every sequence in the model, determine to which activity - // it corresponds, and keep a count of sequences per activity. Once the total count - // is available, allocate an array large enough to contain them all, update the - // starting indices for every activity's section in the array, and go back through, - // populating the array with its data. - - AssertMsg1( m_pSequenceTuples == NULL, "Tried to double-initialize sequence mapping for %s", pstudiohdr->pszName() ); - if ( m_pSequenceTuples != NULL ) - return; // don't double initialize. - - SetValidationPair(pstudiohdr); - - if ( ! pstudiohdr->SequencesAvailable() ) - return; // nothing to do. - -#if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE - m_bIsInitialized = true; -#endif - - // Some studio headers have no activities at all. In those - // cases we can avoid a lot of this effort. - bool bFoundOne = false; - - // for each sequence in the header... - const int NumSeq = pstudiohdr->GetNumSeq(); - for ( int i = 0 ; i < NumSeq ; ++i ) - { - const mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( i ); -#if defined(SERVER_DLL) || defined(CLIENT_DLL) || defined(GAME_DLL) - if (!(seqdesc.flags & STUDIO_ACTIVITY)) - { - // AssertMsg2( false, "Sequence %d on studiohdr %s didn't have its activity initialized!", i, pstudiohdr->pszName() ); - SetActivityForSequence( pstudiohdr, i ); - } -#endif - - // is there an activity associated with this sequence? - if (seqdesc.activity >= 0) - { - bFoundOne = true; - - // look up if we already have an entry. First we need to make a speculative one -- - HashValueType entry(seqdesc.activity, 0, 1, iabs(seqdesc.actweight)); - UtlHashHandle_t handle = m_ActToSeqHash.Find(entry); - if ( m_ActToSeqHash.IsValidHandle(handle) ) - { - // we already have an entry and must update it by incrementing count - HashValueType * __restrict toUpdate = &m_ActToSeqHash.Element(handle); - toUpdate->count += 1; - toUpdate->totalWeight += iabs(seqdesc.actweight); - } - else - { - // we do not have an entry yet; create one. - m_ActToSeqHash.Insert(entry); - } - } - } - - // if we found nothing, don't bother with any other initialization! - if (!bFoundOne) - return; - - // Now, create starting indices for each activity. For an activity n, - // the starting index is of course the sum of counts [0..n-1]. - register int sequenceCount = 0; - int topActivity = 0; // this will store the highest seen activity number (used later to make an ad hoc map on the stack) - for ( UtlHashHandle_t handle = m_ActToSeqHash.GetFirstHandle() ; - m_ActToSeqHash.IsValidHandle(handle) ; - handle = m_ActToSeqHash.GetNextHandle(handle) ) - { - HashValueType &element = m_ActToSeqHash[handle]; - element.startingIdx = sequenceCount; - sequenceCount += element.count; - topActivity = MAX(topActivity, element.activityIdx); - } - - - // Allocate the actual array of sequence information. Note the use of restrict; - // this is an important optimization, but means that you must never refer to this - // array through m_pSequenceTuples in the scope of this function. - SequenceTuple * __restrict tupleList = new SequenceTuple[sequenceCount]; - m_pSequenceTuples = tupleList; // save it off -- NEVER USE m_pSequenceTuples in this function! - m_iSequenceTuplesCount = sequenceCount; - - - - // Now we're going to actually populate that list with the relevant data. - // First, create an array on the stack to store how many sequences we've written - // so far for each activity. (This is basically a very simple way of doing a map.) - // This stack may potentially grow very large; so if you have problems with it, - // go to a utlmap or similar structure. - unsigned int allocsize = (topActivity + 1) * sizeof(int); -#define ALIGN_VALUE( val, alignment ) ( ( val + alignment - 1 ) & ~( alignment - 1 ) ) // need macro for constant expression - allocsize = ALIGN_VALUE(allocsize,16); - int * __restrict seqsPerAct = static_cast(stackalloc(allocsize)); - memset(seqsPerAct, 0, allocsize); - - // okay, walk through all the sequences again, and write the relevant data into - // our little table. - for ( int i = 0 ; i < NumSeq ; ++i ) - { - const mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( i ); - if (seqdesc.activity >= 0) - { - const HashValueType &element = m_ActToSeqHash[m_ActToSeqHash.Find(HashValueType(seqdesc.activity, 0, 0, 0))]; - - // If this assert trips, we've written more sequences per activity than we allocated - // (therefore there must have been a miscount in the first for loop above). - int tupleOffset = seqsPerAct[seqdesc.activity]; - Assert( tupleOffset < element.count ); - - // You might be tempted to collapse this pointer math into a single pointer -- - // don't! the tuple list is marked __restrict above. - (tupleList + element.startingIdx + tupleOffset)->seqnum = i; // store sequence number - (tupleList + element.startingIdx + tupleOffset)->weight = iabs(seqdesc.actweight); - - seqsPerAct[seqdesc.activity] += 1; - } - } - -#ifdef DBGFLAG_ASSERT - // double check that we wrote exactly the right number of sequences. - unsigned int chkSequenceCount = 0; - for (int j = 0 ; j <= topActivity ; ++j) - { - chkSequenceCount += seqsPerAct[j]; - } - Assert(chkSequenceCount == m_iSequenceTuplesCount); -#endif - -} - -/// Force Initialize() to occur again, even if it has already occured. -void CStudioHdr::CActivityToSequenceMapping::Reinitialize( CStudioHdr *pstudiohdr ) -{ - m_bIsInitialized = false; - if (m_pSequenceTuples) - { - delete m_pSequenceTuples; - m_pSequenceTuples = NULL; - } - m_ActToSeqHash.RemoveAll(); - - Initialize(pstudiohdr); -} - -// Look up relevant data for an activity's sequences. This isn't terribly efficient, due to the -// load-hit-store on the output parameters, so the most common case -- SelectWeightedSequence -- -// is specially implemented. -const CStudioHdr::CActivityToSequenceMapping::SequenceTuple *CStudioHdr::CActivityToSequenceMapping::GetSequences( int forActivity, int * __restrict outSequenceCount, int * __restrict outTotalWeight ) -{ - // Construct a dummy entry so we can do a hash lookup (the UtlHash does not divorce keys from values) - - HashValueType entry(forActivity, 0, 0, 0); - UtlHashHandle_t handle = m_ActToSeqHash.Find(entry); - - if (m_ActToSeqHash.IsValidHandle(handle)) - { - const HashValueType &element = m_ActToSeqHash[handle]; - const SequenceTuple *retval = m_pSequenceTuples + element.startingIdx; - *outSequenceCount = element.count; - *outTotalWeight = element.totalWeight; - - return retval; - } - else - { - // invalid handle; return NULL. - // this is actually a legit use case, so no need to assert. - return NULL; - } -} - -int CStudioHdr::CActivityToSequenceMapping::NumSequencesForActivity( int forActivity ) -{ - // If this trips, you've called this function on something that doesn't - // have activities. - //Assert(m_pSequenceTuples != NULL); - if ( m_pSequenceTuples == NULL ) - return 0; - - HashValueType entry(forActivity, 0, 0, 0); - UtlHashHandle_t handle = m_ActToSeqHash.Find(entry); - if (m_ActToSeqHash.IsValidHandle(handle)) - { - return m_ActToSeqHash[handle].count; - } - else - { - return 0; - } -} - -// double-check that the data I point to hasn't changed -bool CStudioHdr::CActivityToSequenceMapping::ValidateAgainst( const CStudioHdr * RESTRICT pstudiohdr ) RESTRICT -{ - if (m_bIsInitialized) - { - return m_expectedPStudioHdr == pstudiohdr->GetRenderHdr() && - m_expectedVModel == pstudiohdr->GetVirtualModel(); - } - else - { - return true; // Allow an ordinary initialization to take place without printing a panicky assert. - } -} - -void CStudioHdr::CActivityToSequenceMapping::SetValidationPair( const CStudioHdr *RESTRICT pstudiohdr ) RESTRICT -{ - m_expectedPStudioHdr = pstudiohdr->GetRenderHdr(); - m_expectedVModel = pstudiohdr->GetVirtualModel(); -} diff --git a/public/studio.h b/public/studio.h deleted file mode 100644 index fefc5e821..000000000 --- a/public/studio.h +++ /dev/null @@ -1,3094 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// - -#ifndef STUDIO_H -#define STUDIO_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "basetypes.h" -#include "mathlib/vector2d.h" -#include "mathlib/vector.h" -#include "mathlib/vector4d.h" -#include "mathlib/compressed_vector.h" -#include "tier0/dbg.h" -#include "tier0/threadtools.h" -#include "mathlib/mathlib.h" -#include "utlvector.h" -#include "utlhash.h" -#include "datamap.h" -#include "generichash.h" -#include "localflexcontroller.h" - - -#ifndef offsetof -#define offsetof(s,m) (size_t)&(((s *)0)->m) -#endif - -#define STUDIO_ENABLE_PERF_COUNTERS - -#define STUDIO_SEQUENCE_ACTIVITY_LOOKUPS_ARE_SLOW 0 -// If this is set to 1, then the activity->sequence mapping inside -// the CStudioHdr will not be initialized until the first call to -// SelectWeightedSequence() or HaveSequenceForActivity(). If set -// to zero, the mapping will be initialized from CStudioHdr::Init() -// (itself called from the constructor). -// As of June 4 2007, this was set to 1 because physics, among other -// systems, extemporaneously declares CStudioHdrs inside local function -// scopes without querying their activity/sequence mapping at all. -#define STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE 1 - -//----------------------------------------------------------------------------- -// forward declarations -//----------------------------------------------------------------------------- - -class IMaterial; -class IMesh; -class IMorph; -struct virtualmodel_t; -struct vertexFileHeader_t; -struct thinModelVertices_t; - -namespace OptimizedModel -{ - struct StripHeader_t; -} - - -/* -============================================================================== - -STUDIO MODELS - -Studio models are position independent, so the cache manager can move them. -============================================================================== -*/ - -#define STUDIO_VERSION 48 - -#ifndef _XBOX -#define MAXSTUDIOTRIANGLES 65536 // TODO: tune this -#define MAXSTUDIOVERTS 65536 // TODO: tune this -#define MAXSTUDIOFLEXVERTS 10000 // max number of verts that can be flexed per mesh. TODO: tune this -#else -#define MAXSTUDIOTRIANGLES 25000 -#define MAXSTUDIOVERTS 10000 -#define MAXSTUDIOFLEXVERTS 1000 -#endif -#define MAXSTUDIOSKINS 32 // total textures -#define MAXSTUDIOBONES 128 // total bones actually used -#define MAXSTUDIOFLEXDESC 1024 // maximum number of low level flexes (actual morph targets) -#define MAXSTUDIOFLEXCTRL 96 // maximum number of flexcontrollers (input sliders) -#define MAXSTUDIOPOSEPARAM 24 -#define MAXSTUDIOBONECTRLS 4 -#define MAXSTUDIOANIMBLOCKS 256 - -#define MAXSTUDIOBONEBITS 7 // NOTE: MUST MATCH MAXSTUDIOBONES - -// NOTE!!! : Changing this number also changes the vtx file format!!!!! -#define MAX_NUM_BONES_PER_VERT 3 - -//Adrian - Remove this when we completely phase out the old event system. -#define NEW_EVENT_STYLE ( 1 << 10 ) - -struct mstudiodata_t -{ - int count; - int offset; -}; - -#define STUDIO_PROC_AXISINTERP 1 -#define STUDIO_PROC_QUATINTERP 2 -#define STUDIO_PROC_AIMATBONE 3 -#define STUDIO_PROC_AIMATATTACH 4 -#define STUDIO_PROC_JIGGLE 5 - -struct mstudioaxisinterpbone_t -{ - DECLARE_BYTESWAP_DATADESC(); - int control;// local transformation of this bone used to calc 3 point blend - int axis; // axis to check - Vector pos[6]; // X+, X-, Y+, Y-, Z+, Z- - Quaternion quat[6];// X+, X-, Y+, Y-, Z+, Z- - - mstudioaxisinterpbone_t(){} -private: - // No copy constructors allowed - mstudioaxisinterpbone_t(const mstudioaxisinterpbone_t& vOther); -}; - - -struct mstudioquatinterpinfo_t -{ - DECLARE_BYTESWAP_DATADESC(); - float inv_tolerance; // 1 / radian angle of trigger influence - Quaternion trigger; // angle to match - Vector pos; // new position - Quaternion quat; // new angle - - mstudioquatinterpinfo_t(){} -private: - // No copy constructors allowed - mstudioquatinterpinfo_t(const mstudioquatinterpinfo_t& vOther); -}; - -struct mstudioquatinterpbone_t -{ - DECLARE_BYTESWAP_DATADESC(); - int control;// local transformation to check - int numtriggers; - int triggerindex; - inline mstudioquatinterpinfo_t *pTrigger( int i ) const { return (mstudioquatinterpinfo_t *)(((byte *)this) + triggerindex) + i; }; - - mstudioquatinterpbone_t(){} -private: - // No copy constructors allowed - mstudioquatinterpbone_t(const mstudioquatinterpbone_t& vOther); -}; - - -#define JIGGLE_IS_FLEXIBLE 0x01 -#define JIGGLE_IS_RIGID 0x02 -#define JIGGLE_HAS_YAW_CONSTRAINT 0x04 -#define JIGGLE_HAS_PITCH_CONSTRAINT 0x08 -#define JIGGLE_HAS_ANGLE_CONSTRAINT 0x10 -#define JIGGLE_HAS_LENGTH_CONSTRAINT 0x20 -#define JIGGLE_HAS_BASE_SPRING 0x40 - -struct mstudiojigglebone_t -{ - DECLARE_BYTESWAP_DATADESC(); - - int flags; - - // general params - float length; // how from from bone base, along bone, is tip - float tipMass; - - // flexible params - float yawStiffness; - float yawDamping; - float pitchStiffness; - float pitchDamping; - float alongStiffness; - float alongDamping; - - // angle constraint - float angleLimit; // maximum deflection of tip in radians - - // yaw constraint - float minYaw; // in radians - float maxYaw; // in radians - float yawFriction; - float yawBounce; - - // pitch constraint - float minPitch; // in radians - float maxPitch; // in radians - float pitchFriction; - float pitchBounce; - - // base spring - float baseMass; - float baseStiffness; - float baseDamping; - float baseMinLeft; - float baseMaxLeft; - float baseLeftFriction; - float baseMinUp; - float baseMaxUp; - float baseUpFriction; - float baseMinForward; - float baseMaxForward; - float baseForwardFriction; - -private: - // No copy constructors allowed - //mstudiojigglebone_t(const mstudiojigglebone_t& vOther); -}; - -struct mstudioaimatbone_t -{ - DECLARE_BYTESWAP_DATADESC(); - - int parent; - int aim; // Might be bone or attach - Vector aimvector; - Vector upvector; - Vector basepos; - - mstudioaimatbone_t() {} -private: - // No copy constructors allowed - mstudioaimatbone_t(const mstudioaimatbone_t& vOther); -}; - -// bones -struct mstudiobone_t -{ - DECLARE_BYTESWAP_DATADESC(); - int sznameindex; - inline char * const pszName( void ) const { return ((char *)this) + sznameindex; } - int parent; // parent bone - int bonecontroller[6]; // bone controller index, -1 == none - - // default values - Vector pos; - Quaternion quat; - RadianEuler rot; - // compression scale - Vector posscale; - Vector rotscale; - - matrix3x4_t poseToBone; - Quaternion qAlignment; - int flags; - int proctype; - int procindex; // procedural rule - mutable int physicsbone; // index into physically simulated bone - inline void *pProcedure( ) const { if (procindex == 0) return NULL; else return (void *)(((byte *)this) + procindex); }; - int surfacepropidx; // index into string tablefor property name - inline char * const pszSurfaceProp( void ) const { return ((char *)this) + surfacepropidx; } - int contents; // See BSPFlags.h for the contents flags - - int unused[8]; // remove as appropriate - - mstudiobone_t(){} -private: - // No copy constructors allowed - mstudiobone_t(const mstudiobone_t& vOther); -}; - -struct mstudiolinearbone_t -{ - DECLARE_BYTESWAP_DATADESC(); - - int numbones; - - int flagsindex; - inline int flags( int i ) const { Assert( i >= 0 && i < numbones); return *((int *)(((byte *)this) + flagsindex) + i); }; - inline int *pflags( int i ) { Assert( i >= 0 && i < numbones); return ((int *)(((byte *)this) + flagsindex) + i); }; - - int parentindex; - inline int parent( int i ) const { Assert( i >= 0 && i < numbones); return *((int *)(((byte *)this) + parentindex) + i); }; - - int posindex; - inline Vector pos( int i ) const { Assert( i >= 0 && i < numbones); return *((Vector *)(((byte *)this) + posindex) + i); }; - - int quatindex; - inline Quaternion quat( int i ) const { Assert( i >= 0 && i < numbones); return *((Quaternion *)(((byte *)this) + quatindex) + i); }; - - int rotindex; - inline RadianEuler rot( int i ) const { Assert( i >= 0 && i < numbones); return *((RadianEuler *)(((byte *)this) + rotindex) + i); }; - - int posetoboneindex; - inline matrix3x4_t poseToBone( int i ) const { Assert( i >= 0 && i < numbones); return *((matrix3x4_t *)(((byte *)this) + posetoboneindex) + i); }; - - int posscaleindex; - inline Vector posscale( int i ) const { Assert( i >= 0 && i < numbones); return *((Vector *)(((byte *)this) + posscaleindex) + i); }; - - int rotscaleindex; - inline Vector rotscale( int i ) const { Assert( i >= 0 && i < numbones); return *((Vector *)(((byte *)this) + rotscaleindex) + i); }; - - int qalignmentindex; - inline Quaternion qalignment( int i ) const { Assert( i >= 0 && i < numbones); return *((Quaternion *)(((byte *)this) + qalignmentindex) + i); }; - - int unused[6]; - - mstudiolinearbone_t(){} -private: - // No copy constructors allowed - mstudiolinearbone_t(const mstudiolinearbone_t& vOther); -}; - - -#define BONE_CALCULATE_MASK 0x1F -#define BONE_PHYSICALLY_SIMULATED 0x01 // bone is physically simulated when physics are active -#define BONE_PHYSICS_PROCEDURAL 0x02 // procedural when physics is active -#define BONE_ALWAYS_PROCEDURAL 0x04 // bone is always procedurally animated -#define BONE_SCREEN_ALIGN_SPHERE 0x08 // bone aligns to the screen, not constrained in motion. -#define BONE_SCREEN_ALIGN_CYLINDER 0x10 // bone aligns to the screen, constrained by it's own axis. - -#define BONE_USED_MASK 0x0007FF00 -#define BONE_USED_BY_ANYTHING 0x0007FF00 -#define BONE_USED_BY_HITBOX 0x00000100 // bone (or child) is used by a hit box -#define BONE_USED_BY_ATTACHMENT 0x00000200 // bone (or child) is used by an attachment point -#define BONE_USED_BY_VERTEX_MASK 0x0003FC00 -#define BONE_USED_BY_VERTEX_LOD0 0x00000400 // bone (or child) is used by the toplevel model via skinned vertex -#define BONE_USED_BY_VERTEX_LOD1 0x00000800 -#define BONE_USED_BY_VERTEX_LOD2 0x00001000 -#define BONE_USED_BY_VERTEX_LOD3 0x00002000 -#define BONE_USED_BY_VERTEX_LOD4 0x00004000 -#define BONE_USED_BY_VERTEX_LOD5 0x00008000 -#define BONE_USED_BY_VERTEX_LOD6 0x00010000 -#define BONE_USED_BY_VERTEX_LOD7 0x00020000 -#define BONE_USED_BY_BONE_MERGE 0x00040000 // bone is available for bone merge to occur against it - -#define BONE_USED_BY_VERTEX_AT_LOD(lod) ( BONE_USED_BY_VERTEX_LOD0 << (lod) ) -#define BONE_USED_BY_ANYTHING_AT_LOD(lod) ( ( BONE_USED_BY_ANYTHING & ~BONE_USED_BY_VERTEX_MASK ) | BONE_USED_BY_VERTEX_AT_LOD(lod) ) - -#define MAX_NUM_LODS 8 - -#define BONE_TYPE_MASK 0x00F00000 -#define BONE_FIXED_ALIGNMENT 0x00100000 // bone can't spin 360 degrees, all interpolation is normalized around a fixed orientation - -#define BONE_HAS_SAVEFRAME_POS 0x00200000 // Vector48 -#define BONE_HAS_SAVEFRAME_ROT 0x00400000 // Quaternion64 - -// bone controllers -struct mstudiobonecontroller_t -{ - DECLARE_BYTESWAP_DATADESC(); - int bone; // -1 == 0 - int type; // X, Y, Z, XR, YR, ZR, M - float start; - float end; - int rest; // byte index value at rest - int inputfield; // 0-3 user set controller, 4 mouth - int unused[8]; -}; - -// intersection boxes -struct mstudiobbox_t -{ - DECLARE_BYTESWAP_DATADESC(); - int bone; - int group; // intersection group - Vector bbmin; // bounding box - Vector bbmax; - int szhitboxnameindex; // offset to the name of the hitbox. - int unused[8]; - - const char* pszHitboxName() - { - if( szhitboxnameindex == 0 ) - return ""; - - return ((char*)this) + szhitboxnameindex; - } - - mstudiobbox_t() {} - -private: - // No copy constructors allowed - mstudiobbox_t(const mstudiobbox_t& vOther); -}; - -// demand loaded sequence groups -struct mstudiomodelgroup_t -{ - DECLARE_BYTESWAP_DATADESC(); - int szlabelindex; // textual name - inline char * const pszLabel( void ) const { return ((char *)this) + szlabelindex; } - int sznameindex; // file name - inline char * const pszName( void ) const { return ((char *)this) + sznameindex; } -}; - -struct mstudiomodelgrouplookup_t -{ - int modelgroup; - int indexwithingroup; -}; - -// events -struct mstudioevent_t -{ - DECLARE_BYTESWAP_DATADESC(); - float cycle; - int event; - int type; - inline const char * pszOptions( void ) const { return options; } - char options[64]; - - int szeventindex; - inline char * const pszEventName( void ) const { return ((char *)this) + szeventindex; } -}; - -#define ATTACHMENT_FLAG_WORLD_ALIGN 0x10000 - -// attachment -struct mstudioattachment_t -{ - DECLARE_BYTESWAP_DATADESC(); - int sznameindex; - inline char * const pszName( void ) const { return ((char *)this) + sznameindex; } - unsigned int flags; - int localbone; - matrix3x4_t local; // attachment point - int unused[8]; -}; - -#define IK_SELF 1 -#define IK_WORLD 2 -#define IK_GROUND 3 -#define IK_RELEASE 4 -#define IK_ATTACHMENT 5 -#define IK_UNLATCH 6 - -struct mstudioikerror_t -{ - DECLARE_BYTESWAP_DATADESC(); - Vector pos; - Quaternion q; - - mstudioikerror_t() {} - -private: - // No copy constructors allowed - mstudioikerror_t(const mstudioikerror_t& vOther); -}; - -union mstudioanimvalue_t; - -struct mstudiocompressedikerror_t -{ - DECLARE_BYTESWAP_DATADESC(); - float scale[6]; - short offset[6]; - inline mstudioanimvalue_t *pAnimvalue( int i ) const { if (offset[i] > 0) return (mstudioanimvalue_t *)(((byte *)this) + offset[i]); else return NULL; }; - mstudiocompressedikerror_t(){} - -private: - // No copy constructors allowed - mstudiocompressedikerror_t(const mstudiocompressedikerror_t& vOther); -}; - -struct mstudioikrule_t -{ - DECLARE_BYTESWAP_DATADESC(); - int index; - - int type; - int chain; - - int bone; - - int slot; // iktarget slot. Usually same as chain. - float height; - float radius; - float floor; - Vector pos; - Quaternion q; - - int compressedikerrorindex; - inline mstudiocompressedikerror_t *pCompressedError() const { return (mstudiocompressedikerror_t *)(((byte *)this) + compressedikerrorindex); }; - int unused2; - - int iStart; - int ikerrorindex; - inline mstudioikerror_t *pError( int i ) const { return (ikerrorindex) ? (mstudioikerror_t *)(((byte *)this) + ikerrorindex) + (i - iStart) : NULL; }; - - float start; // beginning of influence - float peak; // start of full influence - float tail; // end of full influence - float end; // end of all influence - - float unused3; // - float contact; // frame footstep makes ground concact - float drop; // how far down the foot should drop when reaching for IK - float top; // top of the foot box - - int unused6; - int unused7; - int unused8; - - int szattachmentindex; // name of world attachment - inline char * const pszAttachment( void ) const { return ((char *)this) + szattachmentindex; } - - int unused[7]; - - mstudioikrule_t() {} - -private: - // No copy constructors allowed - mstudioikrule_t(const mstudioikrule_t& vOther); -}; - - -struct mstudioiklock_t -{ - DECLARE_BYTESWAP_DATADESC(); - int chain; - float flPosWeight; - float flLocalQWeight; - int flags; - - int unused[4]; -}; - - -struct mstudiolocalhierarchy_t -{ - DECLARE_BYTESWAP_DATADESC(); - int iBone; // bone being adjusted - int iNewParent; // the bones new parent - - float start; // beginning of influence - float peak; // start of full influence - float tail; // end of full influence - float end; // end of all influence - - int iStart; // first frame - - int localanimindex; - inline mstudiocompressedikerror_t *pLocalAnim() const { return (mstudiocompressedikerror_t *)(((byte *)this) + localanimindex); }; - - int unused[4]; -}; - - - -// animation frames -union mstudioanimvalue_t -{ - struct - { - byte valid; - byte total; - } num; - short value; -}; - -struct mstudioanim_valueptr_t -{ - DECLARE_BYTESWAP_DATADESC(); - short offset[3]; - inline mstudioanimvalue_t *pAnimvalue( int i ) const { if (offset[i] > 0) return (mstudioanimvalue_t *)(((byte *)this) + offset[i]); else return NULL; }; -}; - -#define STUDIO_ANIM_RAWPOS 0x01 // Vector48 -#define STUDIO_ANIM_RAWROT 0x02 // Quaternion48 -#define STUDIO_ANIM_ANIMPOS 0x04 // mstudioanim_valueptr_t -#define STUDIO_ANIM_ANIMROT 0x08 // mstudioanim_valueptr_t -#define STUDIO_ANIM_DELTA 0x10 -#define STUDIO_ANIM_RAWROT2 0x20 // Quaternion64 - - -// per bone per animation DOF and weight pointers -struct mstudioanim_t -{ - DECLARE_BYTESWAP_DATADESC(); - byte bone; - byte flags; // weighing options - - // valid for animating data only - inline byte *pData( void ) const { return (((byte *)this) + sizeof( struct mstudioanim_t )); }; - inline mstudioanim_valueptr_t *pRotV( void ) const { return (mstudioanim_valueptr_t *)(pData()); }; - inline mstudioanim_valueptr_t *pPosV( void ) const { return (mstudioanim_valueptr_t *)(pData()) + ((flags & STUDIO_ANIM_ANIMROT) != 0); }; - - // valid if animation unvaring over timeline - inline Quaternion48 *pQuat48( void ) const { return (Quaternion48 *)(pData()); }; - inline Quaternion64 *pQuat64( void ) const { return (Quaternion64 *)(pData()); }; - inline Vector48 *pPos( void ) const { return (Vector48 *)(pData() + ((flags & STUDIO_ANIM_RAWROT) != 0) * sizeof( *pQuat48() ) + ((flags & STUDIO_ANIM_RAWROT2) != 0) * sizeof( *pQuat64() ) ); }; - - short nextoffset; - inline mstudioanim_t *pNext( void ) const { if (nextoffset != 0) return (mstudioanim_t *)(((byte *)this) + nextoffset); else return NULL; }; -}; - -struct mstudiomovement_t -{ - DECLARE_BYTESWAP_DATADESC(); - int endframe; - int motionflags; - float v0; // velocity at start of block - float v1; // velocity at end of block - float angle; // YAW rotation at end of this blocks movement - Vector vector; // movement vector relative to this blocks initial angle - Vector position; // relative to start of animation??? - - mstudiomovement_t(){} -private: - // No copy constructors allowed - mstudiomovement_t(const mstudiomovement_t& vOther); -}; - -struct studiohdr_t; - -// used for piecewise loading of animation data -struct mstudioanimblock_t -{ - DECLARE_BYTESWAP_DATADESC(); - int datastart; - int dataend; -}; - -struct mstudioanimsections_t -{ - DECLARE_BYTESWAP_DATADESC(); - int animblock; - int animindex; -}; - -struct mstudioanimdesc_t -{ - DECLARE_BYTESWAP_DATADESC(); - int baseptr; - inline studiohdr_t *pStudiohdr( void ) const { return (studiohdr_t *)(((byte *)this) + baseptr); } - - int sznameindex; - inline char * const pszName( void ) const { return ((char *)this) + sznameindex; } - - float fps; // frames per second - int flags; // looping/non-looping flags - - int numframes; - - // piecewise movement - int nummovements; - int movementindex; - inline mstudiomovement_t * const pMovement( int i ) const { return (mstudiomovement_t *)(((byte *)this) + movementindex) + i; }; - - int unused1[6]; // remove as appropriate (and zero if loading older versions) - - int animblock; - int animindex; // non-zero when anim data isn't in sections - mstudioanim_t *pAnimBlock( int block, int index ) const; // returns pointer to a specific anim block (local or external) - mstudioanim_t *pAnim( int *piFrame, float &flStall ) const; // returns pointer to data and new frame index - mstudioanim_t *pAnim( int *piFrame ) const; // returns pointer to data and new frame index - - int numikrules; - int ikruleindex; // non-zero when IK data is stored in the mdl - int animblockikruleindex; // non-zero when IK data is stored in animblock file - mstudioikrule_t *pIKRule( int i ) const; - - int numlocalhierarchy; - int localhierarchyindex; - mstudiolocalhierarchy_t *pHierarchy( int i ) const; - - int sectionindex; - int sectionframes; // number of frames used in each fast lookup section, zero if not used - inline mstudioanimsections_t * const pSection( int i ) const { return (mstudioanimsections_t *)(((byte *)this) + sectionindex) + i; } - - short zeroframespan; // frames per span - short zeroframecount; // number of spans - int zeroframeindex; - byte *pZeroFrameData( ) const { if (zeroframeindex) return (((byte *)this) + zeroframeindex); else return NULL; }; - mutable float zeroframestalltime; // saved during read stalls - - mstudioanimdesc_t(){} -private: - // No copy constructors allowed - mstudioanimdesc_t(const mstudioanimdesc_t& vOther); -}; - -struct mstudioikrule_t; - -struct mstudioautolayer_t -{ - DECLARE_BYTESWAP_DATADESC(); -//private: - short iSequence; - short iPose; -//public: - int flags; - float start; // beginning of influence - float peak; // start of full influence - float tail; // end of full influence - float end; // end of all influence -}; - -// sequence descriptions -struct mstudioseqdesc_t -{ - DECLARE_BYTESWAP_DATADESC(); - int baseptr; - inline studiohdr_t *pStudiohdr( void ) const { return (studiohdr_t *)(((byte *)this) + baseptr); } - - int szlabelindex; - inline char * const pszLabel( void ) const { return ((char *)this) + szlabelindex; } - - int szactivitynameindex; - inline char * const pszActivityName( void ) const { return ((char *)this) + szactivitynameindex; } - - int flags; // looping/non-looping flags - - int activity; // initialized at loadtime to game DLL values - int actweight; - - int numevents; - int eventindex; - inline mstudioevent_t *pEvent( int i ) const { Assert( i >= 0 && i < numevents); return (mstudioevent_t *)(((byte *)this) + eventindex) + i; }; - - Vector bbmin; // per sequence bounding box - Vector bbmax; - - int numblends; - - // Index into array of shorts which is groupsize[0] x groupsize[1] in length - int animindexindex; - - inline int anim( int x, int y ) const - { - if ( x >= groupsize[0] ) - { - x = groupsize[0] - 1; - } - - if ( y >= groupsize[1] ) - { - y = groupsize[ 1 ] - 1; - } - - int offset = y * groupsize[0] + x; - short *blends = (short *)(((byte *)this) + animindexindex); - int value = (int)blends[ offset ]; - return value; - } - - int movementindex; // [blend] float array for blended movement - int groupsize[2]; - int paramindex[2]; // X, Y, Z, XR, YR, ZR - float paramstart[2]; // local (0..1) starting value - float paramend[2]; // local (0..1) ending value - int paramparent; - - float fadeintime; // ideal cross fate in time (0.2 default) - float fadeouttime; // ideal cross fade out time (0.2 default) - - int localentrynode; // transition node at entry - int localexitnode; // transition node at exit - int nodeflags; // transition rules - - float entryphase; // used to match entry gait - float exitphase; // used to match exit gait - - float lastframe; // frame that should generation EndOfSequence - - int nextseq; // auto advancing sequences - int pose; // index of delta animation between end and nextseq - - int numikrules; - - int numautolayers; // - int autolayerindex; - inline mstudioautolayer_t *pAutolayer( int i ) const { Assert( i >= 0 && i < numautolayers); return (mstudioautolayer_t *)(((byte *)this) + autolayerindex) + i; }; - - int weightlistindex; - inline float *pBoneweight( int i ) const { return ((float *)(((byte *)this) + weightlistindex) + i); }; - inline float weight( int i ) const { return *(pBoneweight( i)); }; - - // FIXME: make this 2D instead of 2x1D arrays - int posekeyindex; - float *pPoseKey( int iParam, int iAnim ) const { return (float *)(((byte *)this) + posekeyindex) + iParam * groupsize[0] + iAnim; } - float poseKey( int iParam, int iAnim ) const { return *(pPoseKey( iParam, iAnim )); } - - int numiklocks; - int iklockindex; - inline mstudioiklock_t *pIKLock( int i ) const { Assert( i >= 0 && i < numiklocks); return (mstudioiklock_t *)(((byte *)this) + iklockindex) + i; }; - - // Key values - int keyvalueindex; - int keyvaluesize; - inline const char * KeyValueText( void ) const { return keyvaluesize != 0 ? ((char *)this) + keyvalueindex : NULL; } - - int cycleposeindex; // index of pose parameter to use as cycle index - - int unused[7]; // remove/add as appropriate (grow back to 8 ints on version change!) - - mstudioseqdesc_t(){} -private: - // No copy constructors allowed - mstudioseqdesc_t(const mstudioseqdesc_t& vOther); -}; - - -struct mstudioposeparamdesc_t -{ - DECLARE_BYTESWAP_DATADESC(); - int sznameindex; - inline char * const pszName( void ) const { return ((char *)this) + sznameindex; } - int flags; // ???? - float start; // starting value - float end; // ending value - float loop; // looping range, 0 for no looping, 360 for rotations, etc. -}; - -struct mstudioflexdesc_t -{ - DECLARE_BYTESWAP_DATADESC(); - int szFACSindex; - inline char * const pszFACS( void ) const { return ((char *)this) + szFACSindex; } -}; - - - -struct mstudioflexcontroller_t -{ - DECLARE_BYTESWAP_DATADESC(); - int sztypeindex; - inline char * const pszType( void ) const { return ((char *)this) + sztypeindex; } - int sznameindex; - inline char * const pszName( void ) const { return ((char *)this) + sznameindex; } - mutable int localToGlobal; // remapped at load time to master list - float min; - float max; -}; - - -enum FlexControllerRemapType_t -{ - FLEXCONTROLLER_REMAP_PASSTHRU = 0, - FLEXCONTROLLER_REMAP_2WAY, // Control 0 -> ramps from 1-0 from 0->0.5. Control 1 -> ramps from 0-1 from 0.5->1 - FLEXCONTROLLER_REMAP_NWAY, // StepSize = 1 / (control count-1) Control n -> ramps from 0-1-0 from (n-1)*StepSize to n*StepSize to (n+1)*StepSize. A second control is needed to specify amount to use - FLEXCONTROLLER_REMAP_EYELID -}; - - -class CStudioHdr; -struct mstudioflexcontrollerui_t -{ - DECLARE_BYTESWAP_DATADESC(); - int sznameindex; - inline char * const pszName( void ) const { return ((char *)this) + sznameindex; } - - // These are used like a union to save space - // Here are the possible configurations for a UI controller - // - // SIMPLE NON-STEREO: 0: control 1: unused 2: unused - // STEREO: 0: left 1: right 2: unused - // NWAY NON-STEREO: 0: control 1: unused 2: value - // NWAY STEREO: 0: left 1: right 2: value - - int szindex0; - int szindex1; - int szindex2; - - inline const mstudioflexcontroller_t *pController( void ) const - { - return !stereo ? (mstudioflexcontroller_t *)( (char *)this + szindex0 ) : NULL; - } - inline char * const pszControllerName( void ) const { return !stereo ? pController()->pszName() : NULL; } - inline int controllerIndex( const CStudioHdr &cStudioHdr ) const; - - inline const mstudioflexcontroller_t *pLeftController( void ) const - { - return stereo ? (mstudioflexcontroller_t *)( (char *)this + szindex0 ) : NULL; - } - inline char * const pszLeftName( void ) const { return stereo ? pLeftController()->pszName() : NULL; } - inline int leftIndex( const CStudioHdr &cStudioHdr ) const; - - inline const mstudioflexcontroller_t *pRightController( void ) const - { - return stereo ? (mstudioflexcontroller_t *)( (char *)this + szindex1 ): NULL; - } - inline char * const pszRightName( void ) const { return stereo ? pRightController()->pszName() : NULL; } - inline int rightIndex( const CStudioHdr &cStudioHdr ) const; - - inline const mstudioflexcontroller_t *pNWayValueController( void ) const - { - return remaptype == FLEXCONTROLLER_REMAP_NWAY ? (mstudioflexcontroller_t *)( (char *)this + szindex2 ) : NULL; - } - inline char * const pszNWayValueName( void ) const { return remaptype == FLEXCONTROLLER_REMAP_NWAY ? pNWayValueController()->pszName() : NULL; } - inline int nWayValueIndex( const CStudioHdr &cStudioHdr ) const; - - // Number of controllers this ui description contains, 1, 2 or 3 - inline int Count() const { return ( stereo ? 2 : 1 ) + ( remaptype == FLEXCONTROLLER_REMAP_NWAY ? 1 : 0 ); } - inline const mstudioflexcontroller_t *pController( int index ) const; - - unsigned char remaptype; // See the FlexControllerRemapType_t enum - bool stereo; // Is this a stereo control? - byte unused[2]; -}; - - -// these are the on-disk format vertex anims -struct dstudiovertanim_t -{ - unsigned short index; - byte speed; // 255/max_length_in_flex - byte side; // 255/left_right - Vector48 delta; - Vector48 ndelta; - -private: - // No copy constructors allowed - dstudiovertanim_t(const dstudiovertanim_t& vOther); -}; - - -struct dstudiovertanim_wrinkle_t : public dstudiovertanim_t -{ - short wrinkledelta; // Encodes a range from -1 to 1. NOTE: -32768 == -32767 == -1.0f, 32767 = 1.0f - -private: - // No copy constructors allowed - dstudiovertanim_wrinkle_t( const dstudiovertanim_t& vOther ); -}; - -const float g_VertAnimFixedPointScale = 1.0f / 4096.0f; -const float g_VertAnimFixedPointScaleInv = 1.0f / g_VertAnimFixedPointScale; - -// this is the memory image of vertex anims (16-bit fixed point) -struct mstudiovertanim_t -{ - DECLARE_BYTESWAP_DATADESC(); - unsigned short index; - byte speed; // 255/max_length_in_flex - byte side; // 255/left_right - -protected: - // JasonM changing this type a lot, to prefer fixed point 16 bit... - union - { - short delta[3]; - float16 flDelta[3]; - }; - - union - { - short ndelta[3]; - float16 flNDelta[3]; - }; - -public: - inline Vector GetDeltaFixed() - { - return Vector( delta[0]*g_VertAnimFixedPointScale, delta[1]*g_VertAnimFixedPointScale, delta[2]*g_VertAnimFixedPointScale ); - } - inline Vector GetNDeltaFixed() - { - return Vector( ndelta[0]*g_VertAnimFixedPointScale, ndelta[1]*g_VertAnimFixedPointScale, ndelta[2]*g_VertAnimFixedPointScale ); - } - inline void GetDeltaFixed4DAligned( Vector4DAligned *vFillIn ) - { - vFillIn->Set( delta[0]*g_VertAnimFixedPointScale, delta[1]*g_VertAnimFixedPointScale, delta[2]*g_VertAnimFixedPointScale, 0.0f ); - } - inline void GetNDeltaFixed4DAligned( Vector4DAligned *vFillIn ) - { - vFillIn->Set( ndelta[0]*g_VertAnimFixedPointScale, ndelta[1]*g_VertAnimFixedPointScale, ndelta[2]*g_VertAnimFixedPointScale, 0.0f ); - } - inline Vector GetDeltaFloat() - { - return Vector (flDelta[0].GetFloat(), flDelta[1].GetFloat(), flDelta[2].GetFloat()); - } - inline Vector GetNDeltaFloat() - { - return Vector (flNDelta[0].GetFloat(), flNDelta[1].GetFloat(), flNDelta[2].GetFloat()); - } - inline void SetDeltaFixed( const Vector& vInput ) - { - delta[0] = static_cast(vInput.x * g_VertAnimFixedPointScaleInv); - delta[1] = static_cast(vInput.y * g_VertAnimFixedPointScaleInv); - delta[2] = static_cast(vInput.z * g_VertAnimFixedPointScaleInv); - } - inline void SetNDeltaFixed( const Vector& vInputNormal ) - { - ndelta[0] = static_cast(vInputNormal.x * g_VertAnimFixedPointScaleInv); - ndelta[1] = static_cast(vInputNormal.y * g_VertAnimFixedPointScaleInv); - ndelta[2] = static_cast(vInputNormal.z * g_VertAnimFixedPointScaleInv); - } - - // Ick...can also force fp16 data into this structure for writing to file in legacy format... - inline void SetDeltaFloat( const Vector& vInput ) - { - flDelta[0].SetFloat( vInput.x ); - flDelta[1].SetFloat( vInput.y ); - flDelta[2].SetFloat( vInput.z ); - } - inline void SetNDeltaFloat( const Vector& vInputNormal ) - { - flNDelta[0].SetFloat( vInputNormal.x ); - flNDelta[1].SetFloat( vInputNormal.y ); - flNDelta[2].SetFloat( vInputNormal.z ); - } - - mstudiovertanim_t(){} -private: - // No copy constructors allowed - mstudiovertanim_t(const mstudiovertanim_t& vOther); -}; - - -// this is the memory image of vertex anims (16-bit fixed point) -struct mstudiovertanim_wrinkle_t : public mstudiovertanim_t -{ - DECLARE_BYTESWAP_DATADESC(); - - short wrinkledelta; - - inline void SetWrinkleFixed( float flWrinkle ) - { - int nWrinkleDeltaInt = static_cast(flWrinkle * g_VertAnimFixedPointScaleInv); - wrinkledelta = clamp( nWrinkleDeltaInt, -32767, 32767 ); - } - - inline Vector4D GetDeltaFixed() - { - return Vector4D( delta[0]*g_VertAnimFixedPointScale, delta[1]*g_VertAnimFixedPointScale, delta[2]*g_VertAnimFixedPointScale, wrinkledelta*g_VertAnimFixedPointScale ); - } - - inline void GetDeltaFixed4DAligned( Vector4DAligned *vFillIn ) - { - vFillIn->Set( delta[0]*g_VertAnimFixedPointScale, delta[1]*g_VertAnimFixedPointScale, delta[2]*g_VertAnimFixedPointScale, wrinkledelta*g_VertAnimFixedPointScale ); - } -}; - - -enum StudioVertAnimType_t -{ - STUDIO_VERT_ANIM_NORMAL = 0, - STUDIO_VERT_ANIM_WRINKLE, -}; - -struct mstudioflex_t -{ - DECLARE_BYTESWAP_DATADESC(); - int flexdesc; // input value - - float target0; // zero - float target1; // one - float target2; // one - float target3; // zero - - int numverts; - int vertindex; - - inline mstudiovertanim_t *pVertanim( int i ) const { Assert( vertanimtype == STUDIO_VERT_ANIM_NORMAL ); return (mstudiovertanim_t *)(((byte *)this) + vertindex) + i; }; - inline mstudiovertanim_wrinkle_t *pVertanimWrinkle( int i ) const { Assert( vertanimtype == STUDIO_VERT_ANIM_WRINKLE ); return (mstudiovertanim_wrinkle_t *)(((byte *)this) + vertindex) + i; }; - - inline byte *pBaseVertanim( ) const { return ((byte *)this) + vertindex; }; - inline int VertAnimSizeBytes() const { return ( vertanimtype == STUDIO_VERT_ANIM_NORMAL ) ? sizeof(mstudiovertanim_t) : sizeof(mstudiovertanim_wrinkle_t); } - - int flexpair; // second flex desc - unsigned char vertanimtype; // See StudioVertAnimType_t - unsigned char unusedchar[3]; - int unused[6]; -}; - - -struct mstudioflexop_t -{ - DECLARE_BYTESWAP_DATADESC(); - int op; - union - { - int index; - float value; - } d; -}; - -struct mstudioflexrule_t -{ - DECLARE_BYTESWAP_DATADESC(); - int flex; - int numops; - int opindex; - inline mstudioflexop_t *iFlexOp( int i ) const { return (mstudioflexop_t *)(((byte *)this) + opindex) + i; }; -}; - -// 16 bytes -struct mstudioboneweight_t -{ - DECLARE_BYTESWAP_DATADESC(); - float weight[MAX_NUM_BONES_PER_VERT]; - char bone[MAX_NUM_BONES_PER_VERT]; - byte numbones; - -// byte material; -// short firstref; -// short lastref; -}; - -// NOTE: This is exactly 48 bytes -struct mstudiovertex_t -{ - DECLARE_BYTESWAP_DATADESC(); - mstudioboneweight_t m_BoneWeights; - Vector m_vecPosition; - Vector m_vecNormal; - Vector2D m_vecTexCoord; - - mstudiovertex_t() {} - -private: - // No copy constructors allowed - mstudiovertex_t(const mstudiovertex_t& vOther); -}; - -// skin info -struct mstudiotexture_t -{ - DECLARE_BYTESWAP_DATADESC(); - int sznameindex; - inline char * const pszName( void ) const { return ((char *)this) + sznameindex; } - int flags; - int used; - int unused1; - mutable IMaterial *material; // fixme: this needs to go away . .isn't used by the engine, but is used by studiomdl - mutable void *clientmaterial; // gary, replace with client material pointer if used - - int unused[10]; -}; - -// eyeball -struct mstudioeyeball_t -{ - DECLARE_BYTESWAP_DATADESC(); - int sznameindex; - inline char * const pszName( void ) const { return ((char *)this) + sznameindex; } - int bone; - Vector org; - float zoffset; - float radius; - Vector up; - Vector forward; - int texture; - - int unused1; - float iris_scale; - int unused2; - - int upperflexdesc[3]; // index of raiser, neutral, and lowerer flexdesc that is set by flex controllers - int lowerflexdesc[3]; - float uppertarget[3]; // angle (radians) of raised, neutral, and lowered lid positions - float lowertarget[3]; - - int upperlidflexdesc; // index of flex desc that actual lid flexes look to - int lowerlidflexdesc; - int unused[4]; // These were used before, so not guaranteed to be 0 - bool m_bNonFACS; // Never used before version 44 - char unused3[3]; - int unused4[7]; - - mstudioeyeball_t(){} -private: - // No copy constructors allowed - mstudioeyeball_t(const mstudioeyeball_t& vOther); -}; - - -// ikinfo -struct mstudioiklink_t -{ - DECLARE_BYTESWAP_DATADESC(); - int bone; - Vector kneeDir; // ideal bending direction (per link, if applicable) - Vector unused0; // unused - - mstudioiklink_t(){} -private: - // No copy constructors allowed - mstudioiklink_t(const mstudioiklink_t& vOther); -}; - -struct mstudioikchain_t -{ - DECLARE_BYTESWAP_DATADESC(); - int sznameindex; - inline char * const pszName( void ) const { return ((char *)this) + sznameindex; } - int linktype; - int numlinks; - int linkindex; - inline mstudioiklink_t *pLink( int i ) const { return (mstudioiklink_t *)(((byte *)this) + linkindex) + i; }; - // FIXME: add unused entries -}; - - -struct mstudioiface_t -{ - unsigned short a, b, c; // Indices to vertices -}; - - -struct mstudiomodel_t; - -struct mstudio_modelvertexdata_t -{ - DECLARE_BYTESWAP_DATADESC(); - Vector *Position( int i ) const; - Vector *Normal( int i ) const; - Vector4D *TangentS( int i ) const; - Vector2D *Texcoord( int i ) const; - mstudioboneweight_t *BoneWeights( int i ) const; - mstudiovertex_t *Vertex( int i ) const; - bool HasTangentData( void ) const; - int GetGlobalVertexIndex( int i ) const; - int GetGlobalTangentIndex( int i ) const; - - // base of external vertex data stores - const void *pVertexData; - const void *pTangentData; -}; - -struct mstudio_meshvertexdata_t -{ - DECLARE_BYTESWAP_DATADESC(); - Vector *Position( int i ) const; - Vector *Normal( int i ) const; - Vector4D *TangentS( int i ) const; - Vector2D *Texcoord( int i ) const; - mstudioboneweight_t *BoneWeights( int i ) const; - mstudiovertex_t *Vertex( int i ) const; - bool HasTangentData( void ) const; - int GetModelVertexIndex( int i ) const; - int GetGlobalVertexIndex( int i ) const; - - // indirection to this mesh's model's vertex data - const mstudio_modelvertexdata_t *modelvertexdata; - - // used for fixup calcs when culling top level lods - // expected number of mesh verts at desired lod - int numLODVertexes[MAX_NUM_LODS]; -}; - -struct mstudiomesh_t -{ - DECLARE_BYTESWAP_DATADESC(); - int material; - - int modelindex; - mstudiomodel_t *pModel() const; - - int numvertices; // number of unique vertices/normals/texcoords - int vertexoffset; // vertex mstudiovertex_t - - // Access thin/fat mesh vertex data (only one will return a non-NULL result) - const mstudio_meshvertexdata_t *GetVertexData( void *pModelData = NULL ); - const thinModelVertices_t *GetThinVertexData( void *pModelData = NULL ); - - int numflexes; // vertex animation - int flexindex; - inline mstudioflex_t *pFlex( int i ) const { return (mstudioflex_t *)(((byte *)this) + flexindex) + i; }; - - // special codes for material operations - int materialtype; - int materialparam; - - // a unique ordinal for this mesh - int meshid; - - Vector center; - - mstudio_meshvertexdata_t vertexdata; - - int unused[8]; // remove as appropriate - - mstudiomesh_t(){} -private: - // No copy constructors allowed - mstudiomesh_t(const mstudiomesh_t& vOther); -}; - -// studio models -struct mstudiomodel_t -{ - DECLARE_BYTESWAP_DATADESC(); - inline const char * pszName( void ) const { return name; } - char name[64]; - - int type; - - float boundingradius; - - int nummeshes; - int meshindex; - inline mstudiomesh_t *pMesh( int i ) const { return (mstudiomesh_t *)(((byte *)this) + meshindex) + i; }; - - // cache purposes - int numvertices; // number of unique vertices/normals/texcoords - int vertexindex; // vertex Vector - int tangentsindex; // tangents Vector - - // These functions are defined in application-specific code: - const vertexFileHeader_t *CacheVertexData( void *pModelData ); - - // Access thin/fat mesh vertex data (only one will return a non-NULL result) - const mstudio_modelvertexdata_t *GetVertexData( void *pModelData = NULL ); - const thinModelVertices_t *GetThinVertexData( void *pModelData = NULL ); - - int numattachments; - int attachmentindex; - - int numeyeballs; - int eyeballindex; - inline mstudioeyeball_t *pEyeball( int i ) { return (mstudioeyeball_t *)(((byte *)this) + eyeballindex) + i; }; - - mstudio_modelvertexdata_t vertexdata; - - int unused[8]; // remove as appropriate -}; - -inline bool mstudio_modelvertexdata_t::HasTangentData( void ) const -{ - return (pTangentData != NULL); -} - -inline int mstudio_modelvertexdata_t::GetGlobalVertexIndex( int i ) const -{ - mstudiomodel_t *modelptr = (mstudiomodel_t *)((byte *)this - offsetof(mstudiomodel_t, vertexdata)); - Assert( ( modelptr->vertexindex % sizeof( mstudiovertex_t ) ) == 0 ); - return ( i + ( modelptr->vertexindex / sizeof( mstudiovertex_t ) ) ); -} - -inline int mstudio_modelvertexdata_t::GetGlobalTangentIndex( int i ) const -{ - mstudiomodel_t *modelptr = (mstudiomodel_t *)((byte *)this - offsetof(mstudiomodel_t, vertexdata)); - Assert( ( modelptr->tangentsindex % sizeof( Vector4D ) ) == 0 ); - return ( i + ( modelptr->tangentsindex / sizeof( Vector4D ) ) ); -} - -inline mstudiovertex_t *mstudio_modelvertexdata_t::Vertex( int i ) const -{ - return (mstudiovertex_t *)pVertexData + GetGlobalVertexIndex( i ); -} - -inline Vector *mstudio_modelvertexdata_t::Position( int i ) const -{ - return &Vertex(i)->m_vecPosition; -} - -inline Vector *mstudio_modelvertexdata_t::Normal( int i ) const -{ - return &Vertex(i)->m_vecNormal; -} - -inline Vector4D *mstudio_modelvertexdata_t::TangentS( int i ) const -{ - // NOTE: The tangents vector is 16-bytes in a separate array - // because it only exists on the high end, and if I leave it out - // of the mstudiovertex_t, the vertex is 64-bytes (good for low end) - return (Vector4D *)pTangentData + GetGlobalTangentIndex( i ); -} - -inline Vector2D *mstudio_modelvertexdata_t::Texcoord( int i ) const -{ - return &Vertex(i)->m_vecTexCoord; -} - -inline mstudioboneweight_t *mstudio_modelvertexdata_t::BoneWeights( int i ) const -{ - return &Vertex(i)->m_BoneWeights; -} - -inline mstudiomodel_t *mstudiomesh_t::pModel() const -{ - return (mstudiomodel_t *)(((byte *)this) + modelindex); -} - -inline bool mstudio_meshvertexdata_t::HasTangentData( void ) const -{ - return modelvertexdata->HasTangentData(); -} - -inline const mstudio_meshvertexdata_t *mstudiomesh_t::GetVertexData( void *pModelData ) -{ - // get this mesh's model's vertex data (allow for mstudiomodel_t::GetVertexData - // returning NULL if the data has been converted to 'thin' vertices) - this->pModel()->GetVertexData( pModelData ); - vertexdata.modelvertexdata = &( this->pModel()->vertexdata ); - - if ( !vertexdata.modelvertexdata->pVertexData ) - return NULL; - - return &vertexdata; -} - -inline const thinModelVertices_t * mstudiomesh_t::GetThinVertexData( void *pModelData ) -{ - // get this mesh's model's thin vertex data - return this->pModel()->GetThinVertexData( pModelData ); -} - -inline int mstudio_meshvertexdata_t::GetModelVertexIndex( int i ) const -{ - mstudiomesh_t *meshptr = (mstudiomesh_t *)((byte *)this - offsetof(mstudiomesh_t,vertexdata)); - return meshptr->vertexoffset + i; -} - -inline int mstudio_meshvertexdata_t::GetGlobalVertexIndex( int i ) const -{ - return modelvertexdata->GetGlobalVertexIndex( GetModelVertexIndex( i ) ); -} - -inline Vector *mstudio_meshvertexdata_t::Position( int i ) const -{ - return modelvertexdata->Position( GetModelVertexIndex( i ) ); -}; - -inline Vector *mstudio_meshvertexdata_t::Normal( int i ) const -{ - return modelvertexdata->Normal( GetModelVertexIndex( i ) ); -}; - -inline Vector4D *mstudio_meshvertexdata_t::TangentS( int i ) const -{ - return modelvertexdata->TangentS( GetModelVertexIndex( i ) ); -} - -inline Vector2D *mstudio_meshvertexdata_t::Texcoord( int i ) const -{ - return modelvertexdata->Texcoord( GetModelVertexIndex( i ) ); -}; - -inline mstudioboneweight_t *mstudio_meshvertexdata_t::BoneWeights( int i ) const -{ - return modelvertexdata->BoneWeights( GetModelVertexIndex( i ) ); -}; - -inline mstudiovertex_t *mstudio_meshvertexdata_t::Vertex( int i ) const -{ - return modelvertexdata->Vertex( GetModelVertexIndex( i ) ); -} - -// a group of studio model data -enum studiomeshgroupflags_t -{ - MESHGROUP_IS_FLEXED = 0x1, - MESHGROUP_IS_HWSKINNED = 0x2, - MESHGROUP_IS_DELTA_FLEXED = 0x4 -}; - - -// ---------------------------------------------------------- -// runtime stuff -// ---------------------------------------------------------- - -struct studiomeshgroup_t -{ - IMesh *m_pMesh; - int m_NumStrips; - int m_Flags; // see studiomeshgroupflags_t - OptimizedModel::StripHeader_t *m_pStripData; - unsigned short *m_pGroupIndexToMeshIndex; - int m_NumVertices; - int *m_pUniqueTris; // for performance measurements - unsigned short *m_pIndices; - bool m_MeshNeedsRestore; - short m_ColorMeshID; - IMorph *m_pMorph; - - inline unsigned short MeshIndex( int i ) const { return m_pGroupIndexToMeshIndex[m_pIndices[i]]; } -}; - - -// studio model data -struct studiomeshdata_t -{ - int m_NumGroup; - studiomeshgroup_t* m_pMeshGroup; -}; - -struct studioloddata_t -{ - // not needed - this is really the same as studiohwdata_t.m_NumStudioMeshes - //int m_NumMeshes; - studiomeshdata_t *m_pMeshData; // there are studiohwdata_t.m_NumStudioMeshes of these. - float m_SwitchPoint; - // one of these for each lod since we can switch to simpler materials on lower lods. - int numMaterials; - IMaterial **ppMaterials; /* will have studiohdr_t.numtextures elements allocated */ - // hack - this needs to go away. - int *pMaterialFlags; /* will have studiohdr_t.numtextures elements allocated */ - - // For decals on hardware morphing, we must actually do hardware skinning - // For this to work, we have to hope that the total # of bones used by - // hw flexed verts is < than the max possible for the dx level we're running under - int *m_pHWMorphDecalBoneRemap; - int m_nDecalBoneCount; -}; - -struct studiohwdata_t -{ - int m_RootLOD; // calced and clamped, nonzero for lod culling - int m_NumLODs; - studioloddata_t *m_pLODs; - int m_NumStudioMeshes; - - inline float LODMetric( float unitSphereSize ) const { return ( unitSphereSize != 0.0f ) ? (100.0f / unitSphereSize) : 0.0f; } - inline int GetLODForMetric( float lodMetric ) const - { - if ( !m_NumLODs ) - return 0; - - // shadow lod is specified on the last lod with a negative switch - // never consider shadow lod as viable candidate - int numLODs = (m_pLODs[m_NumLODs-1].m_SwitchPoint < 0.0f) ? m_NumLODs-1 : m_NumLODs; - - for ( int i = m_RootLOD; i < numLODs-1; i++ ) - { - if ( m_pLODs[i+1].m_SwitchPoint > lodMetric ) - return i; - } - - return numLODs-1; - } -}; - -// ---------------------------------------------------------- -// ---------------------------------------------------------- - -// body part index -struct mstudiobodyparts_t -{ - DECLARE_BYTESWAP_DATADESC(); - int sznameindex; - inline char * const pszName( void ) const { return ((char *)this) + sznameindex; } - int nummodels; - int base; - int modelindex; // index into models array - inline mstudiomodel_t *pModel( int i ) const { return (mstudiomodel_t *)(((byte *)this) + modelindex) + i; }; -}; - - -struct mstudiomouth_t -{ - DECLARE_BYTESWAP_DATADESC(); - int bone; - Vector forward; - int flexdesc; - - mstudiomouth_t(){} -private: - // No copy constructors allowed - mstudiomouth_t(const mstudiomouth_t& vOther); -}; - -struct mstudiohitboxset_t -{ - DECLARE_BYTESWAP_DATADESC(); - int sznameindex; - inline char * const pszName( void ) const { return ((char *)this) + sznameindex; } - int numhitboxes; - int hitboxindex; - inline mstudiobbox_t *pHitbox( int i ) const { return (mstudiobbox_t *)(((byte *)this) + hitboxindex) + i; }; -}; - - -//----------------------------------------------------------------------------- -// Src bone transforms are transformations that will convert .dmx or .smd-based animations into .mdl-based animations -// NOTE: The operation you should apply is: pretransform * bone transform * posttransform -//----------------------------------------------------------------------------- -struct mstudiosrcbonetransform_t -{ - DECLARE_BYTESWAP_DATADESC(); - - int sznameindex; - inline const char *pszName( void ) const { return ((char *)this) + sznameindex; } - matrix3x4_t pretransform; - matrix3x4_t posttransform; -}; - - -// ---------------------------------------------------------- -// Purpose: Load time results on model compositing -// ---------------------------------------------------------- - -class virtualgroup_t -{ -public: - virtualgroup_t( void ) { cache = NULL; }; - // tool dependant. In engine this is a model_t, in tool it's a direct pointer - void *cache; - // converts cache entry into a usable studiohdr_t * - const studiohdr_t *GetStudioHdr( void ) const; - - CUtlVector< int > boneMap; // maps global bone to local bone - CUtlVector< int > masterBone; // maps local bone to global bone - CUtlVector< int > masterSeq; // maps local sequence to master sequence - CUtlVector< int > masterAnim; // maps local animation to master animation - CUtlVector< int > masterAttachment; // maps local attachment to global - CUtlVector< int > masterPose; // maps local pose parameter to global - CUtlVector< int > masterNode; // maps local transition nodes to global -}; - -struct virtualsequence_t -{ -#ifdef _XBOX - short flags; - short activity; - short group; - short index; -#else - int flags; - int activity; - int group; - int index; -#endif -}; - -struct virtualgeneric_t -{ -#ifdef _XBOX - short group; - short index; -#else - int group; - int index; -#endif -}; - - -struct virtualmodel_t -{ - void AppendSequences( int group, const studiohdr_t *pStudioHdr ); - void AppendAnimations( int group, const studiohdr_t *pStudioHdr ); - void AppendAttachments( int ground, const studiohdr_t *pStudioHdr ); - void AppendPoseParameters( int group, const studiohdr_t *pStudioHdr ); - void AppendBonemap( int group, const studiohdr_t *pStudioHdr ); - void AppendNodes( int group, const studiohdr_t *pStudioHdr ); - void AppendTransitions( int group, const studiohdr_t *pStudioHdr ); - void AppendIKLocks( int group, const studiohdr_t *pStudioHdr ); - void AppendModels( int group, const studiohdr_t *pStudioHdr ); - void UpdateAutoplaySequences( const studiohdr_t *pStudioHdr ); - - virtualgroup_t *pAnimGroup( int animation ) { return &m_group[ m_anim[ animation ].group ]; }; // Note: user must manage mutex for this - virtualgroup_t *pSeqGroup( int sequence ) { return &m_group[ m_seq[ sequence ].group ]; }; // Note: user must manage mutex for this - - CThreadFastMutex m_Lock; - - CUtlVector< virtualsequence_t > m_seq; - CUtlVector< virtualgeneric_t > m_anim; - CUtlVector< virtualgeneric_t > m_attachment; - CUtlVector< virtualgeneric_t > m_pose; - CUtlVector< virtualgroup_t > m_group; - CUtlVector< virtualgeneric_t > m_node; - CUtlVector< virtualgeneric_t > m_iklock; - CUtlVector< unsigned short > m_autoplaySequences; -}; - -// 'thin' vertex data, used to do model decals (see Studio_CreateThinVertexes()) -struct thinModelVertices_t -{ - void Init( int numBoneInfluences, Vector *positions, unsigned short *normals, float *boneWeights, char *boneIndices ) - { - Assert( positions != NULL ); - Assert( normals != NULL ); - Assert( ( numBoneInfluences >= 0 ) && ( numBoneInfluences <= 3 ) ); - Assert( numBoneInfluences > 0 ? !!boneIndices : !boneIndices ); - Assert( numBoneInfluences > 1 ? !!boneWeights : !boneWeights ); - m_numBoneInfluences = numBoneInfluences; - m_vecPositions = positions; - m_vecNormals = normals; - m_boneWeights = boneWeights; - m_boneIndices = boneIndices; - } - - void SetPosition( int vertIndex, const Vector & position ) - { - Assert( m_vecPositions ); - m_vecPositions[ vertIndex ] = position; - } - - void SetNormal( int vertIndex, const Vector & normal ) - { - Assert( m_vecNormals ); - unsigned int packedNormal; - PackNormal_UBYTE4( normal.x, normal.y, normal.z, &packedNormal ); - m_vecNormals[ vertIndex ] = (unsigned short)( 0x0000FFFF & packedNormal ); - } - - void SetBoneWeights( int vertIndex, const mstudioboneweight_t & boneWeights ) - { - Assert( ( m_numBoneInfluences >= 1 ) && ( m_numBoneInfluences <= 3 ) ); - Assert( ( boneWeights.numbones >= 1 ) && ( boneWeights.numbones <= m_numBoneInfluences ) ); - int numStoredWeights = MAX( 0, ( m_numBoneInfluences - 1 ) ); - float *pBaseWeight = m_boneWeights + vertIndex*numStoredWeights; - char *pBaseIndex = m_boneIndices + vertIndex*m_numBoneInfluences; - for ( int i = 0; i < m_numBoneInfluences; i++ ) - { - pBaseIndex[i] = boneWeights.bone[i]; - } - for ( int i = 0; i < numStoredWeights; i++ ) - { - pBaseWeight[i] = boneWeights.weight[i]; - } - } - - void GetMeshPosition( mstudiomesh_t *pMesh, int meshIndex, Vector *pPosition ) const - { - Assert( pMesh ); - GetPosition( pMesh->vertexdata.GetGlobalVertexIndex( meshIndex ), pPosition ); - } - - void GetMeshNormal( mstudiomesh_t *pMesh, int meshIndex, Vector *pNormal ) const - { - Assert( pMesh ); - GetNormal( pMesh->vertexdata.GetGlobalVertexIndex( meshIndex ), pNormal ); - } - - void GetMeshBoneWeights( mstudiomesh_t *pMesh, int meshIndex, mstudioboneweight_t *pBoneWeights ) const - { - Assert( pMesh ); - GetBoneWeights( pMesh->vertexdata.GetGlobalVertexIndex( meshIndex ), pBoneWeights ); - } - - void GetModelPosition( mstudiomodel_t *pModel, int modelIndex, Vector *pPosition ) const - { - Assert( pModel ); - GetPosition( pModel->vertexdata.GetGlobalVertexIndex( modelIndex ), pPosition ); - } - - void GetModelNormal( mstudiomodel_t *pModel, int modelIndex, Vector *pNormal ) const - { - Assert( pModel ); - GetNormal( pModel->vertexdata.GetGlobalVertexIndex( modelIndex ), pNormal ); - } - - void GetModelBoneWeights( mstudiomodel_t *pModel, int modelIndex, mstudioboneweight_t *pBoneWeights ) const - { - Assert( pModel ); - GetBoneWeights( pModel->vertexdata.GetGlobalVertexIndex( modelIndex ), pBoneWeights ); - } - -private: - void GetPosition( int vertIndex, Vector *pPosition ) const - { - Assert( pPosition ); - Assert( m_vecPositions ); - *pPosition = m_vecPositions[ vertIndex ]; - } - - void GetNormal( int vertIndex, Vector *pNormal ) const - { - Assert( pNormal ); - Assert( m_vecNormals ); - unsigned int packedNormal = 0x0000FFFF & m_vecNormals[ vertIndex ]; - UnpackNormal_UBYTE4( &packedNormal, pNormal->Base() ); - } - - void GetBoneWeights( int vertIndex, mstudioboneweight_t *pBoneWeights ) const - { - Assert( pBoneWeights ); - Assert( ( m_numBoneInfluences <= 1 ) || ( m_boneWeights != NULL ) ); - Assert( ( m_numBoneInfluences <= 0 ) || ( m_boneIndices != NULL ) ); - int numStoredWeights = MAX( 0, ( m_numBoneInfluences - 1 ) ); - float *pBaseWeight = m_boneWeights + vertIndex*numStoredWeights; - char *pBaseIndex = m_boneIndices + vertIndex*m_numBoneInfluences; - float sum = 0.0f; - for (int i = 0;i < MAX_NUM_BONES_PER_VERT;i++) - { - if ( i < ( m_numBoneInfluences - 1 ) ) - pBoneWeights->weight[i] = pBaseWeight[i]; - else - pBoneWeights->weight[i] = 1.0f - sum; - sum += pBoneWeights->weight[i]; - - pBoneWeights->bone[i] = ( i < m_numBoneInfluences ) ? pBaseIndex[i] : 0; - } - - // Treat 'zero weights' as '100% binding to bone zero': - pBoneWeights->numbones = m_numBoneInfluences ? m_numBoneInfluences : 1; - } - - int m_numBoneInfluences;// Number of bone influences per vertex, N - float *m_boneWeights; // This array stores (N-1) weights per vertex (unless N is zero) - char *m_boneIndices; // This array stores N indices per vertex - Vector *m_vecPositions; - unsigned short *m_vecNormals; // Normals are compressed into 16 bits apiece (see PackNormal_UBYTE4() ) -}; - -// ---------------------------------------------------------- -// Studio Model Vertex Data File -// Position independent flat data for cache manager -// ---------------------------------------------------------- - -// little-endian "IDSV" -#define MODEL_VERTEX_FILE_ID (('V'<<24)+('S'<<16)+('D'<<8)+'I') -#define MODEL_VERTEX_FILE_VERSION 4 -// this id (IDCV) is used once the vertex data has been compressed (see CMDLCache::CreateThinVertexes) -#define MODEL_VERTEX_FILE_THIN_ID (('V'<<24)+('C'<<16)+('D'<<8)+'I') - -struct vertexFileHeader_t -{ - DECLARE_BYTESWAP_DATADESC(); - int id; // MODEL_VERTEX_FILE_ID - int version; // MODEL_VERTEX_FILE_VERSION - long checksum; // same as studiohdr_t, ensures sync - int numLODs; // num of valid lods - int numLODVertexes[MAX_NUM_LODS]; // num verts for desired root lod - int numFixups; // num of vertexFileFixup_t - int fixupTableStart; // offset from base to fixup table - int vertexDataStart; // offset from base to vertex block - int tangentDataStart; // offset from base to tangent block - -public: - - // Accessor to fat vertex data - const mstudiovertex_t *GetVertexData() const - { - if ( ( id == MODEL_VERTEX_FILE_ID ) && ( vertexDataStart != 0 ) ) - return ( mstudiovertex_t * ) ( vertexDataStart + (byte *)this ); - else - return NULL; - } - // Accessor to (fat) tangent vertex data (tangents aren't stored in compressed data) - const Vector4D *GetTangentData() const - { - if ( ( id == MODEL_VERTEX_FILE_ID ) && ( tangentDataStart != 0 ) ) - return ( Vector4D * ) ( tangentDataStart + (byte *)this ); - else - return NULL; - } - // Accessor to thin vertex data - const thinModelVertices_t *GetThinVertexData() const - { - if ( ( id == MODEL_VERTEX_FILE_THIN_ID ) && ( vertexDataStart != 0 ) ) - return ( thinModelVertices_t * ) ( vertexDataStart + (byte *)this ); - else - return NULL; - } -}; - -// model vertex data accessor (defined here so vertexFileHeader_t can be used) -inline const mstudio_modelvertexdata_t * mstudiomodel_t::GetVertexData( void *pModelData ) -{ - const vertexFileHeader_t * pVertexHdr = CacheVertexData( pModelData ); - if ( !pVertexHdr ) - return NULL; - - vertexdata.pVertexData = pVertexHdr->GetVertexData(); - vertexdata.pTangentData = pVertexHdr->GetTangentData(); - - if ( !vertexdata.pVertexData ) - return NULL; - - return &vertexdata; -} - -// model thin vertex data accessor (defined here so vertexFileHeader_t can be used) -inline const thinModelVertices_t * mstudiomodel_t::GetThinVertexData( void *pModelData ) -{ - const vertexFileHeader_t * pVertexHdr = CacheVertexData( pModelData ); - if ( !pVertexHdr ) - return NULL; - - return pVertexHdr->GetThinVertexData(); -} - -// apply sequentially to lod sorted vertex and tangent pools to re-establish mesh order -struct vertexFileFixup_t -{ - DECLARE_BYTESWAP_DATADESC(); - int lod; // used to skip culled root lod - int sourceVertexID; // absolute index from start of vertex/tangent blocks - int numVertexes; -}; - -// This flag is set if no hitbox information was specified -#define STUDIOHDR_FLAGS_AUTOGENERATED_HITBOX ( 1 << 0 ) - -// NOTE: This flag is set at loadtime, not mdl build time so that we don't have to rebuild -// models when we change materials. -#define STUDIOHDR_FLAGS_USES_ENV_CUBEMAP ( 1 << 1 ) - -// Use this when there are translucent parts to the model but we're not going to sort it -#define STUDIOHDR_FLAGS_FORCE_OPAQUE ( 1 << 2 ) - -// Use this when we want to render the opaque parts during the opaque pass -// and the translucent parts during the translucent pass -#define STUDIOHDR_FLAGS_TRANSLUCENT_TWOPASS ( 1 << 3 ) - -// This is set any time the .qc files has $staticprop in it -// Means there's no bones and no transforms -#define STUDIOHDR_FLAGS_STATIC_PROP ( 1 << 4 ) - -// NOTE: This flag is set at loadtime, not mdl build time so that we don't have to rebuild -// models when we change materials. -#define STUDIOHDR_FLAGS_USES_FB_TEXTURE ( 1 << 5 ) - -// This flag is set by studiomdl.exe if a separate "$shadowlod" entry was present -// for the .mdl (the shadow lod is the last entry in the lod list if present) -#define STUDIOHDR_FLAGS_HASSHADOWLOD ( 1 << 6 ) - -// NOTE: This flag is set at loadtime, not mdl build time so that we don't have to rebuild -// models when we change materials. -#define STUDIOHDR_FLAGS_USES_BUMPMAPPING ( 1 << 7 ) - -// NOTE: This flag is set when we should use the actual materials on the shadow LOD -// instead of overriding them with the default one (necessary for translucent shadows) -#define STUDIOHDR_FLAGS_USE_SHADOWLOD_MATERIALS ( 1 << 8 ) - -// NOTE: This flag is set when we should use the actual materials on the shadow LOD -// instead of overriding them with the default one (necessary for translucent shadows) -#define STUDIOHDR_FLAGS_OBSOLETE ( 1 << 9 ) - -#define STUDIOHDR_FLAGS_UNUSED ( 1 << 10 ) - -// NOTE: This flag is set at mdl build time -#define STUDIOHDR_FLAGS_NO_FORCED_FADE ( 1 << 11 ) - -// NOTE: The npc will lengthen the viseme check to always include two phonemes -#define STUDIOHDR_FLAGS_FORCE_PHONEME_CROSSFADE ( 1 << 12 ) - -// This flag is set when the .qc has $constantdirectionallight in it -// If set, we use constantdirectionallightdot to calculate light intensity -// rather than the normal directional dot product -// only valid if STUDIOHDR_FLAGS_STATIC_PROP is also set -#define STUDIOHDR_FLAGS_CONSTANT_DIRECTIONAL_LIGHT_DOT ( 1 << 13 ) - -// Flag to mark delta flexes as already converted from disk format to memory format -#define STUDIOHDR_FLAGS_FLEXES_CONVERTED ( 1 << 14 ) - -// Indicates the studiomdl was built in preview mode -#define STUDIOHDR_FLAGS_BUILT_IN_PREVIEW_MODE ( 1 << 15 ) - -// Ambient boost (runtime flag) -#define STUDIOHDR_FLAGS_AMBIENT_BOOST ( 1 << 16 ) - -// Don't cast shadows from this model (useful on first-person models) -#define STUDIOHDR_FLAGS_DO_NOT_CAST_SHADOWS ( 1 << 17 ) - -// alpha textures should cast shadows in vrad on this model (ONLY prop_static!) -#define STUDIOHDR_FLAGS_CAST_TEXTURE_SHADOWS ( 1 << 18 ) - - -// NOTE! Next time we up the .mdl file format, remove studiohdr2_t -// and insert all fields in this structure into studiohdr_t. -struct studiohdr2_t -{ - // NOTE: For forward compat, make sure any methods in this struct - // are also available in studiohdr_t so no leaf code ever directly references - // a studiohdr2_t structure - DECLARE_BYTESWAP_DATADESC(); - int numsrcbonetransform; - int srcbonetransformindex; - - int illumpositionattachmentindex; - inline int IllumPositionAttachmentIndex() const { return illumpositionattachmentindex; } - - float flMaxEyeDeflection; - inline float MaxEyeDeflection() const { return flMaxEyeDeflection != 0.0f ? flMaxEyeDeflection : 0.866f; } // default to cos(30) if not set - - int linearboneindex; - inline mstudiolinearbone_t *pLinearBones() const { return (linearboneindex) ? (mstudiolinearbone_t *)(((byte *)this) + linearboneindex) : NULL; } - - int reserved[59]; -}; - -struct studiohdr_t -{ - DECLARE_BYTESWAP_DATADESC(); - int id; - int version; - - long checksum; // this has to be the same in the phy and vtx files to load! - - inline const char * pszName( void ) const { return name; } - char name[64]; - int length; - - - Vector eyeposition; // ideal eye position - - Vector illumposition; // illumination center - - Vector hull_min; // ideal movement hull size - Vector hull_max; - - Vector view_bbmin; // clipping bounding box - Vector view_bbmax; - - int flags; - - int numbones; // bones - int boneindex; - inline mstudiobone_t *pBone( int i ) const { Assert( i >= 0 && i < numbones); return (mstudiobone_t *)(((byte *)this) + boneindex) + i; }; - int RemapSeqBone( int iSequence, int iLocalBone ) const; // maps local sequence bone to global bone - int RemapAnimBone( int iAnim, int iLocalBone ) const; // maps local animations bone to global bone - - int numbonecontrollers; // bone controllers - int bonecontrollerindex; - inline mstudiobonecontroller_t *pBonecontroller( int i ) const { Assert( i >= 0 && i < numbonecontrollers); return (mstudiobonecontroller_t *)(((byte *)this) + bonecontrollerindex) + i; }; - - int numhitboxsets; - int hitboxsetindex; - - // Look up hitbox set by index - mstudiohitboxset_t *pHitboxSet( int i ) const - { - Assert( i >= 0 && i < numhitboxsets); - return (mstudiohitboxset_t *)(((byte *)this) + hitboxsetindex ) + i; - }; - - // Calls through to hitbox to determine size of specified set - inline mstudiobbox_t *pHitbox( int i, int set ) const - { - mstudiohitboxset_t const *s = pHitboxSet( set ); - if ( !s ) - return NULL; - - return s->pHitbox( i ); - }; - - // Calls through to set to get hitbox count for set - inline int iHitboxCount( int set ) const - { - mstudiohitboxset_t const *s = pHitboxSet( set ); - if ( !s ) - return 0; - - return s->numhitboxes; - }; - - // file local animations? and sequences -//private: - int numlocalanim; // animations/poses - int localanimindex; // animation descriptions - inline mstudioanimdesc_t *pLocalAnimdesc( int i ) const { if (i < 0 || i >= numlocalanim) i = 0; return (mstudioanimdesc_t *)(((byte *)this) + localanimindex) + i; }; - - int numlocalseq; // sequences - int localseqindex; - inline mstudioseqdesc_t *pLocalSeqdesc( int i ) const { if (i < 0 || i >= numlocalseq) i = 0; return (mstudioseqdesc_t *)(((byte *)this) + localseqindex) + i; }; - -//public: - bool SequencesAvailable() const; - int GetNumSeq() const; - mstudioanimdesc_t &pAnimdesc( int i ) const; - mstudioseqdesc_t &pSeqdesc( int i ) const; - int iRelativeAnim( int baseseq, int relanim ) const; // maps seq local anim reference to global anim index - int iRelativeSeq( int baseseq, int relseq ) const; // maps seq local seq reference to global seq index - -//private: - mutable int activitylistversion; // initialization flag - have the sequences been indexed? - mutable int eventsindexed; -//public: - int GetSequenceActivity( int iSequence ); - void SetSequenceActivity( int iSequence, int iActivity ); - int GetActivityListVersion( void ) const; - void SetActivityListVersion( int version ) const; - int GetEventListVersion( void ) const; - void SetEventListVersion( int version ) const; - - // raw textures - int numtextures; - int textureindex; - inline mstudiotexture_t *pTexture( int i ) const { Assert( i >= 0 && i < numtextures ); return (mstudiotexture_t *)(((byte *)this) + textureindex) + i; }; - - - // raw textures search paths - int numcdtextures; - int cdtextureindex; - inline char *pCdtexture( int i ) const { return (((char *)this) + *((int *)(((byte *)this) + cdtextureindex) + i)); }; - - // replaceable textures tables - int numskinref; - int numskinfamilies; - int skinindex; - inline short *pSkinref( int i ) const { return (short *)(((byte *)this) + skinindex) + i; }; - - int numbodyparts; - int bodypartindex; - inline mstudiobodyparts_t *pBodypart( int i ) const { return (mstudiobodyparts_t *)(((byte *)this) + bodypartindex) + i; }; - - // queryable attachable points -//private: - int numlocalattachments; - int localattachmentindex; - inline mstudioattachment_t *pLocalAttachment( int i ) const { Assert( i >= 0 && i < numlocalattachments); return (mstudioattachment_t *)(((byte *)this) + localattachmentindex) + i; }; -//public: - int GetNumAttachments( void ) const; - const mstudioattachment_t &pAttachment( int i ) const; - int GetAttachmentBone( int i ) const; - // used on my tools in hlmv, not persistant - void SetAttachmentBone( int iAttachment, int iBone ); - - // animation node to animation node transition graph -//private: - int numlocalnodes; - int localnodeindex; - int localnodenameindex; - inline char *pszLocalNodeName( int iNode ) const { Assert( iNode >= 0 && iNode < numlocalnodes); return (((char *)this) + *((int *)(((byte *)this) + localnodenameindex) + iNode)); } - inline byte *pLocalTransition( int i ) const { Assert( i >= 0 && i < (numlocalnodes * numlocalnodes)); return (byte *)(((byte *)this) + localnodeindex) + i; }; - -//public: - int EntryNode( int iSequence ) const; - int ExitNode( int iSequence ) const; - const char *pszNodeName( int iNode ) const; - int GetTransition( int iFrom, int iTo ) const; - - int numflexdesc; - int flexdescindex; - inline mstudioflexdesc_t *pFlexdesc( int i ) const { Assert( i >= 0 && i < numflexdesc); return (mstudioflexdesc_t *)(((byte *)this) + flexdescindex) + i; }; - - int numflexcontrollers; - int flexcontrollerindex; - inline mstudioflexcontroller_t *pFlexcontroller( LocalFlexController_t i ) const { Assert( i >= 0 && i < numflexcontrollers); return (mstudioflexcontroller_t *)(((byte *)this) + flexcontrollerindex) + i; }; - - int numflexrules; - int flexruleindex; - inline mstudioflexrule_t *pFlexRule( int i ) const { Assert( i >= 0 && i < numflexrules); return (mstudioflexrule_t *)(((byte *)this) + flexruleindex) + i; }; - - int numikchains; - int ikchainindex; - inline mstudioikchain_t *pIKChain( int i ) const { Assert( i >= 0 && i < numikchains); return (mstudioikchain_t *)(((byte *)this) + ikchainindex) + i; }; - - int nummouths; - int mouthindex; - inline mstudiomouth_t *pMouth( int i ) const { Assert( i >= 0 && i < nummouths); return (mstudiomouth_t *)(((byte *)this) + mouthindex) + i; }; - -//private: - int numlocalposeparameters; - int localposeparamindex; - inline mstudioposeparamdesc_t *pLocalPoseParameter( int i ) const { Assert( i >= 0 && i < numlocalposeparameters); return (mstudioposeparamdesc_t *)(((byte *)this) + localposeparamindex) + i; }; -//public: - int GetNumPoseParameters( void ) const; - const mstudioposeparamdesc_t &pPoseParameter( int i ) const; - int GetSharedPoseParameter( int iSequence, int iLocalPose ) const; - - int surfacepropindex; - inline char * const pszSurfaceProp( void ) const { return ((char *)this) + surfacepropindex; } - - // Key values - int keyvalueindex; - int keyvaluesize; - inline const char * KeyValueText( void ) const { return keyvaluesize != 0 ? ((char *)this) + keyvalueindex : NULL; } - - int numlocalikautoplaylocks; - int localikautoplaylockindex; - inline mstudioiklock_t *pLocalIKAutoplayLock( int i ) const { Assert( i >= 0 && i < numlocalikautoplaylocks); return (mstudioiklock_t *)(((byte *)this) + localikautoplaylockindex) + i; }; - - int GetNumIKAutoplayLocks( void ) const; - const mstudioiklock_t &pIKAutoplayLock( int i ) const; - int CountAutoplaySequences() const; - int CopyAutoplaySequences( unsigned short *pOut, int outCount ) const; - int GetAutoplayList( unsigned short **pOut ) const; - - // The collision model mass that jay wanted - float mass; - int contents; - - // external animations, models, etc. - int numincludemodels; - int includemodelindex; - inline mstudiomodelgroup_t *pModelGroup( int i ) const { Assert( i >= 0 && i < numincludemodels); return (mstudiomodelgroup_t *)(((byte *)this) + includemodelindex) + i; }; - // implementation specific call to get a named model - const studiohdr_t *FindModel( void **cache, char const *modelname ) const; - - // implementation specific back pointer to virtual data - mutable void *virtualModel; - virtualmodel_t *GetVirtualModel( void ) const; - - // for demand loaded animation blocks - int szanimblocknameindex; - inline char * const pszAnimBlockName( void ) const { return ((char *)this) + szanimblocknameindex; } - int numanimblocks; - int animblockindex; - inline mstudioanimblock_t *pAnimBlock( int i ) const { Assert( i > 0 && i < numanimblocks); return (mstudioanimblock_t *)(((byte *)this) + animblockindex) + i; }; - mutable void *animblockModel; - byte * GetAnimBlock( int i ) const; - - int bonetablebynameindex; - inline const byte *GetBoneTableSortedByName() const { return (byte *)this + bonetablebynameindex; } - - // used by tools only that don't cache, but persist mdl's peer data - // engine uses virtualModel to back link to cache pointers - void *pVertexBase; - void *pIndexBase; - - // if STUDIOHDR_FLAGS_CONSTANT_DIRECTIONAL_LIGHT_DOT is set, - // this value is used to calculate directional components of lighting - // on static props - byte constdirectionallightdot; - - // set during load of mdl data to track *desired* lod configuration (not actual) - // the *actual* clamped root lod is found in studiohwdata - // this is stored here as a global store to ensure the staged loading matches the rendering - byte rootLOD; - - // set in the mdl data to specify that lod configuration should only allow first numAllowRootLODs - // to be set as root LOD: - // numAllowedRootLODs = 0 means no restriction, any lod can be set as root lod. - // numAllowedRootLODs = N means that lod0 - lod(N-1) can be set as root lod, but not lodN or lower. - byte numAllowedRootLODs; - - byte unused[1]; - - int unused4; // zero out if version < 47 - - int numflexcontrollerui; - int flexcontrolleruiindex; - mstudioflexcontrollerui_t *pFlexControllerUI( int i ) const { Assert( i >= 0 && i < numflexcontrollerui); return (mstudioflexcontrollerui_t *)(((byte *)this) + flexcontrolleruiindex) + i; } - - int unused3[2]; - - // FIXME: Remove when we up the model version. Move all fields of studiohdr2_t into studiohdr_t. - int studiohdr2index; - studiohdr2_t* pStudioHdr2() const { return (studiohdr2_t *)( ( (byte *)this ) + studiohdr2index ); } - - // Src bone transforms are transformations that will convert .dmx or .smd-based animations into .mdl-based animations - int NumSrcBoneTransforms() const { return studiohdr2index ? pStudioHdr2()->numsrcbonetransform : 0; } - const mstudiosrcbonetransform_t* SrcBoneTransform( int i ) const { Assert( i >= 0 && i < NumSrcBoneTransforms()); return (mstudiosrcbonetransform_t *)(((byte *)this) + pStudioHdr2()->srcbonetransformindex) + i; } - - inline int IllumPositionAttachmentIndex() const { return studiohdr2index ? pStudioHdr2()->IllumPositionAttachmentIndex() : 0; } - - inline float MaxEyeDeflection() const { return studiohdr2index ? pStudioHdr2()->MaxEyeDeflection() : 0.866f; } // default to cos(30) if not set - - inline mstudiolinearbone_t *pLinearBones() const { return studiohdr2index ? pStudioHdr2()->pLinearBones() : NULL; } - - // NOTE: No room to add stuff? Up the .mdl file format version - // [and move all fields in studiohdr2_t into studiohdr_t and kill studiohdr2_t], - // or add your stuff to studiohdr2_t. See NumSrcBoneTransforms/SrcBoneTransform for the pattern to use. - int unused2[1]; - - studiohdr_t() {} - -private: - // No copy constructors allowed - studiohdr_t(const studiohdr_t& vOther); - - friend struct virtualmodel_t; -}; - - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -class IDataCache; -class IMDLCache; - -class CStudioHdr -{ -public: - CStudioHdr( void ); - CStudioHdr( const studiohdr_t *pStudioHdr, IMDLCache *mdlcache = NULL ); - ~CStudioHdr() { Term(); } - - void Init( const studiohdr_t *pStudioHdr, IMDLCache *mdlcache = NULL ); - void Term(); - -public: - inline bool IsVirtual( void ) { return (m_pVModel != NULL); }; - inline bool IsValid( void ) { return (m_pStudioHdr != NULL); }; - inline bool IsReadyForAccess( void ) const { return (m_pStudioHdr != NULL); }; - inline virtualmodel_t *GetVirtualModel( void ) const { return m_pVModel; }; - inline const studiohdr_t *GetRenderHdr( void ) const { return m_pStudioHdr; }; - const studiohdr_t *pSeqStudioHdr( int sequence ) const; - const studiohdr_t *pAnimStudioHdr( int animation )const; - -private: - mutable const studiohdr_t *m_pStudioHdr; - mutable virtualmodel_t *m_pVModel; - - const virtualmodel_t * ResetVModel( const virtualmodel_t *pVModel ) const; - const studiohdr_t *GroupStudioHdr( int group ) const; - mutable CUtlVector< const studiohdr_t * > m_pStudioHdrCache; - - mutable int m_nFrameUnlockCounter; - int * m_pFrameUnlockCounter; - CThreadFastMutex m_FrameUnlockCounterMutex; - -public: - inline int numbones( void ) const { return m_pStudioHdr->numbones; }; - inline mstudiobone_t *pBone( int i ) const { return m_pStudioHdr->pBone( i ); }; - int RemapAnimBone( int iAnim, int iLocalBone ) const; // maps local animations bone to global bone - int RemapSeqBone( int iSequence, int iLocalBone ) const; // maps local sequence bone to global bone - - bool SequencesAvailable() const; - int GetNumSeq( void ) const; - mstudioanimdesc_t &pAnimdesc( int i ) const; - mstudioseqdesc_t &pSeqdesc( int iSequence ) const; - int iRelativeAnim( int baseseq, int relanim ) const; // maps seq local anim reference to global anim index - int iRelativeSeq( int baseseq, int relseq ) const; // maps seq local seq reference to global seq index - - int GetSequenceActivity( int iSequence ); - void SetSequenceActivity( int iSequence, int iActivity ); - int GetActivityListVersion( void ) const; - void SetActivityListVersion( int version ); - int GetEventListVersion( void ) const; - void SetEventListVersion( int version ); - - int GetNumAttachments( void ) const; - const mstudioattachment_t &pAttachment( int i ) const; - int GetAttachmentBone( int i ) const; - // used on my tools in hlmv, not persistant - void SetAttachmentBone( int iAttachment, int iBone ); - - int EntryNode( int iSequence ) const; - int ExitNode( int iSequence ) const; - const char *pszNodeName( int iNode ) const; - // FIXME: where should this one be? - int GetTransition( int iFrom, int iTo ) const; - - int GetNumPoseParameters( void ) const; - const mstudioposeparamdesc_t &pPoseParameter( int i ) const; - int GetSharedPoseParameter( int iSequence, int iLocalPose ) const; - - int GetNumIKAutoplayLocks( void ) const; - const mstudioiklock_t &pIKAutoplayLock( int i ) const; - - inline int CountAutoplaySequences() const { return m_pStudioHdr->CountAutoplaySequences(); }; - inline int CopyAutoplaySequences( unsigned short *pOut, int outCount ) const { return m_pStudioHdr->CopyAutoplaySequences( pOut, outCount ); }; - inline int GetAutoplayList( unsigned short **pOut ) const { return m_pStudioHdr->GetAutoplayList( pOut ); }; - - inline int GetNumBoneControllers( void ) const { return m_pStudioHdr->numbonecontrollers; }; - inline mstudiobonecontroller_t *pBonecontroller( int i ) const { return m_pStudioHdr->pBonecontroller( i ); }; - - inline int numikchains() const { return m_pStudioHdr->numikchains; }; - inline int GetNumIKChains( void ) const { return m_pStudioHdr->numikchains; }; - inline mstudioikchain_t *pIKChain( int i ) const { return m_pStudioHdr->pIKChain( i ); }; - - inline int numflexrules() const { return m_pStudioHdr->numflexrules; }; - inline mstudioflexrule_t *pFlexRule( int i ) const { return m_pStudioHdr->pFlexRule( i ); }; - - inline int numflexdesc() const{ return m_pStudioHdr->numflexdesc; }; - inline mstudioflexdesc_t *pFlexdesc( int i ) const { return m_pStudioHdr->pFlexdesc( i ); }; - - inline LocalFlexController_t numflexcontrollers() const{ return (LocalFlexController_t)m_pStudioHdr->numflexcontrollers; }; - inline mstudioflexcontroller_t *pFlexcontroller( LocalFlexController_t i ) const { return m_pStudioHdr->pFlexcontroller( i ); }; - - inline int numflexcontrollerui() const{ return m_pStudioHdr->numflexcontrollerui; }; - inline mstudioflexcontrollerui_t *pFlexcontrollerUI( int i ) const { return m_pStudioHdr->pFlexControllerUI( i ); }; - - inline const char *name() const { return m_pStudioHdr->name; }; // deprecated -- remove after full xbox merge - inline const char *pszName() const { return m_pStudioHdr->pszName(); }; - - inline int numbonecontrollers() const { return m_pStudioHdr->numbonecontrollers; }; - - inline int numhitboxsets() const { return m_pStudioHdr->numhitboxsets; }; - inline mstudiohitboxset_t *pHitboxSet( int i ) const { return m_pStudioHdr->pHitboxSet( i ); }; - - inline mstudiobbox_t *pHitbox( int i, int set ) const { return m_pStudioHdr->pHitbox( i, set ); }; - inline int iHitboxCount( int set ) const { return m_pStudioHdr->iHitboxCount( set ); }; - - inline int numbodyparts() const { return m_pStudioHdr->numbodyparts; }; - inline mstudiobodyparts_t *pBodypart( int i ) const { return m_pStudioHdr->pBodypart( i ); }; - - inline int numskinfamilies() const { return m_pStudioHdr->numskinfamilies; } - - inline Vector eyeposition() const { return m_pStudioHdr->eyeposition; }; - - inline int flags() const { return m_pStudioHdr->flags; }; - - inline char *const pszSurfaceProp( void ) const { return m_pStudioHdr->pszSurfaceProp(); }; - - inline float mass() const { return m_pStudioHdr->mass; }; - inline int contents() const { return m_pStudioHdr->contents; } - - inline const byte *GetBoneTableSortedByName() const { return m_pStudioHdr->GetBoneTableSortedByName(); }; - - inline Vector illumposition() const { return m_pStudioHdr->illumposition; }; - - inline Vector hull_min() const { return m_pStudioHdr->hull_min; }; // ideal movement hull size - inline Vector hull_max() const { return m_pStudioHdr->hull_max; }; - - inline Vector view_bbmin() const { return m_pStudioHdr->view_bbmin; }; // clipping bounding box - inline Vector view_bbmax() const { return m_pStudioHdr->view_bbmax; }; - - inline int numtextures() const { return m_pStudioHdr->numtextures; }; - - inline int IllumPositionAttachmentIndex() const { return m_pStudioHdr->IllumPositionAttachmentIndex(); } - - inline float MaxEyeDeflection() const { return m_pStudioHdr->MaxEyeDeflection(); } - - inline mstudiolinearbone_t *pLinearBones() const { return m_pStudioHdr->pLinearBones(); } - -public: - int IsSequenceLooping( int iSequence ); - float GetSequenceCycleRate( int iSequence ); - - void RunFlexRules( const float *src, float *dest ); - - -public: - inline int boneFlags( int iBone ) const { return m_boneFlags[ iBone ]; } - inline int boneParent( int iBone ) const { return m_boneParent[ iBone ]; } - -private: - CUtlVector< int > m_boneFlags; - CUtlVector< int > m_boneParent; - -public: - // This class maps an activity to sequences allowed for that activity, accelerating the resolution - // of SelectWeightedSequence(), especially on PowerPC. Iterating through every sequence - // attached to a model turned out to be a very destructive cache access pattern on 360. - // - // I've encapsulated this behavior inside a nested class for organizational reasons; there is - // no particular programmatic or efficiency benefit to it. It just makes clearer what particular - // code in the otherwise very complicated StudioHdr class has to do with this particular - // optimization, and it lets you collapse the whole definition down to a single line in Visual - // Studio. - class CActivityToSequenceMapping /* final */ - { - public: - // A tuple of a sequence and its corresponding weight. Lists of these correspond to activities. - struct SequenceTuple - { - short seqnum; - short weight; // the absolute value of the weight from the sequence header - }; - - // The type of the hash's stored data, a composite of both key and value - // (because that's how CUtlHash works): - // key: an int, the activity # - // values: an index into the m_pSequenceTuples array, a count of the - // total sequences present for an activity, and the sum of their - // weights. - // Note this struct is 128-bits wide, exactly coincident to a PowerPC - // cache line and VMX register. Please consider very carefully the - // performance implications before adding any additional fields to this. - // You could probably do away with totalWeight if you really had to. - struct HashValueType - { - // KEY (hashed) - int activityIdx; - - // VALUE (not hashed) - int startingIdx; - int count; - int totalWeight; - - HashValueType(int _actIdx, int _stIdx, int _ct, int _tW) : - activityIdx(_actIdx), startingIdx(_stIdx), count(_ct), totalWeight(_tW) {} - - // default constructor (ought not to be actually used) - HashValueType() : activityIdx(-1), startingIdx(-1), count(-1), totalWeight(-1) - { AssertMsg(false, "Don't use default HashValueType()!"); } - - - class HashFuncs - { - public: - // dummy constructor (gndn) - HashFuncs( int ) {} - - // COMPARE - // compare two entries for uniqueness. We should never have two different - // entries for the same activity, so we only compare the activity index; - // this allows us to use the utlhash as a dict by constructing dummy entries - // as hash lookup keys. - bool operator()( const HashValueType &lhs, const HashValueType &rhs ) const - { - return lhs.activityIdx == rhs.activityIdx; - } - - // HASH - // We only hash on the activity index; everything else is data. - unsigned int operator()( const HashValueType &item ) const - { - return HashInt( item.activityIdx ); - } - }; - }; - - typedef CUtlHash ActivityToValueIdxHash; - - // ctor - CActivityToSequenceMapping( void ) - : m_pSequenceTuples(NULL), m_iSequenceTuplesCount(0), -#if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE - m_bIsInitialized(false), -#endif - m_ActToSeqHash(8,0,0), m_expectedPStudioHdr(NULL), m_expectedVModel(NULL) - {}; - - // dtor -- not virtual because this class has no inheritors - ~CActivityToSequenceMapping() - { - if ( m_pSequenceTuples != NULL ) - { - delete[] m_pSequenceTuples; - } - } - - /// Get the list of sequences for an activity. Returns the pointer to the - /// first sequence tuple. Output parameters are a count of sequences present, - /// and the total weight of all the sequences. (it would be more LHS-friendly - /// to return these on registers, if only C++ offered more than one return - /// value....) - const SequenceTuple *GetSequences( int forActivity, int *outSequenceCount, int *outTotalWeight ); - - /// The number of sequences available for an activity. - int NumSequencesForActivity( int forActivity ); - -#if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE - inline bool IsInitialized( void ) { return m_bIsInitialized; } -#endif - - private: - - /// Allocate my internal array. (It is freed in the destructor.) Also, - /// build the hash of activities to sequences and populate m_pSequenceTuples. - void Initialize( CStudioHdr *pstudiohdr ); - - /// Force Initialize() to occur again, even if it has already occured. - void Reinitialize( CStudioHdr *pstudiohdr ); - - /// A more efficient version of the old SelectWeightedSequence() function in animation.cpp. - int SelectWeightedSequence( CStudioHdr *pstudiohdr, int activity, int curSequence ); - - // Actually a big array, into which the hash values index. - SequenceTuple *m_pSequenceTuples; - unsigned int m_iSequenceTuplesCount; // (size of the whole array) -#if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE - bool m_bIsInitialized; -#endif - - // we don't store an outer pointer because we can't initialize it at construction time - // (warning c4355) -- there are ways around this but it's easier to just pass in a - // pointer to the CStudioHdr when we need it, since this class isn't supposed to - // export its interface outside the studio header anyway. - // CStudioHdr * const m_pOuter; - - ActivityToValueIdxHash m_ActToSeqHash; - - // we store these so we can know if the contents of the studiohdr have changed - // from underneath our feet (this is an emergency data integrity check) - const void *m_expectedPStudioHdr; - const void *m_expectedVModel; - - // double-check that the data I point to hasn't changed - bool ValidateAgainst( const CStudioHdr * RESTRICT pstudiohdr ); - void SetValidationPair( const CStudioHdr *RESTRICT pstudiohdr ); - - friend class CStudioHdr; - }; - - CActivityToSequenceMapping m_ActivityToSequence; - - /// A more efficient version of the old SelectWeightedSequence() function in animation.cpp. - /// Returns -1 on failure to find a sequence - inline int SelectWeightedSequence( int activity, int curSequence ) - { -#if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE - // We lazy-initialize the header on demand here, because CStudioHdr::Init() is - // called from the constructor, at which time the this pointer is illegitimate. - if ( !m_ActivityToSequence.IsInitialized() ) - { - m_ActivityToSequence.Initialize(this); - } -#endif - return m_ActivityToSequence.SelectWeightedSequence( this, activity, curSequence ); - } - - /// True iff there is at least one sequence for the given activity. - inline bool HaveSequenceForActivity( int activity ) - { -#if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE - if ( !m_ActivityToSequence.IsInitialized() ) - { - m_ActivityToSequence.Initialize(this); - } -#endif - return (m_ActivityToSequence.NumSequencesForActivity( activity ) > 0); - } - - // Force this CStudioHdr's activity-to-sequence mapping to be reinitialized - inline void ReinitializeSequenceMapping(void) - { - m_ActivityToSequence.Reinitialize(this); - } - -#ifdef STUDIO_ENABLE_PERF_COUNTERS -public: - inline void ClearPerfCounters( void ) - { - m_nPerfAnimatedBones = 0; - m_nPerfUsedBones = 0; - m_nPerfAnimationLayers = 0; - }; - - // timing info - mutable int m_nPerfAnimatedBones; - mutable int m_nPerfUsedBones; - mutable int m_nPerfAnimationLayers; -#endif - - -}; - -/* -class CModelAccess -{ -public: - CModelAccess(CStudioHdr *pSemaphore) - : m_pStudioHdr(pSemaphore) - { - m_pStudioHdr->IncrementAccess(); - } - - ~CModelAccess() - { - m_pStudioHdr->DecrementAccess(); - } - -private: - CStudioHdr *m_pStudioHdr; -}; - -#define ENABLE_MODEL_ACCESS( a ) \ - CModelAccess ModelAccess##__LINE__( a->m_pStudioHdr ) -*/ - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -struct flexweight_t -{ - DECLARE_BYTESWAP_DATADESC(); - int key; - float weight; - float influence; -}; - -struct flexsetting_t -{ - DECLARE_BYTESWAP_DATADESC(); - int nameindex; - - inline char *pszName( void ) const - { - return (char *)(((byte *)this) + nameindex); - } - - // Leaving this for legacy support - int obsolete1; - - // Number of flex settings - int numsettings; - int index; - - // OBSOLETE: - int obsolete2; - - // Index of start of contiguous array of flexweight_t structures - int settingindex; - - //----------------------------------------------------------------------------- - // Purpose: Retrieves a pointer to the flexweight_t, including resolving - // any markov chain hierarchy. Because of this possibility, we return - // the number of settings in the weights array returned. We'll generally - // call this function with i == 0 - // Input : *base - - // i - - // **weights - - // Output : int - //----------------------------------------------------------------------------- - inline int psetting( byte *base, int i, flexweight_t **weights ) const; -}; - - -struct flexsettinghdr_t -{ - DECLARE_BYTESWAP_DATADESC(); - int id; - int version; - - inline const char * pszName( void ) const { return name; } - char name[64]; - int length; - - int numflexsettings; - int flexsettingindex; - inline flexsetting_t *pSetting( int i ) const { return (flexsetting_t *)(((byte *)this) + flexsettingindex) + i; }; - int nameindex; - - // look up flex settings by "index" - int numindexes; - int indexindex; - - inline flexsetting_t *pIndexedSetting( int index ) const - { - if ( index < 0 || index >= numindexes ) - { - return NULL; - } - - int i = *((int *)(((byte *)this) + indexindex) + index); - - if (i == -1) - { - return NULL; - } - - return pSetting( i ); - } - - // index names of "flexcontrollers" - int numkeys; - int keynameindex; - inline char *pLocalName( int i ) const { return (char *)(((byte *)this) + *((int *)(((byte *)this) + keynameindex) + i)); }; - - int keymappingindex; - inline int *pLocalToGlobal( int i ) const { return (int *)(((byte *)this) + keymappingindex) + i; }; - inline int LocalToGlobal( int i ) const { return *pLocalToGlobal( i ); }; -}; - -//----------------------------------------------------------------------------- -// Purpose: Retrieves a pointer to the flexweight_t. -// Input : *base - flexsettinghdr_t * pointer -// i - index of flex setting to retrieve -// **weights - destination for weights array starting at index i. -// Output : int -//----------------------------------------------------------------------------- -inline int flexsetting_t::psetting( byte *base, int i, flexweight_t **weights ) const -{ - // Grab array pointer - *weights = (flexweight_t *)(((byte *)this) + settingindex) + i; - // Return true number of settings - return numsettings; -}; - - -//----------------------------------------------------------------------------- -// For a given flex controller ui struct, these return the index of the -// studiohdr_t flex controller that correspond to the the left and right -// flex controllers if the ui controller is a stereo control. -// nWayValueIndex returns the index of the flex controller that is the value -// flex controller for an NWAY combination -// If these functions are called and the ui controller isn't of the type -// specified then -1 is returned -//----------------------------------------------------------------------------- -inline int mstudioflexcontrollerui_t::controllerIndex( const CStudioHdr &cStudioHdr ) const -{ - return !stereo ? pController() - cStudioHdr.pFlexcontroller( (LocalFlexController_t)0 ) : -1; -} - - -inline int mstudioflexcontrollerui_t::rightIndex( const CStudioHdr &cStudioHdr ) const -{ - return stereo ? pRightController() - cStudioHdr.pFlexcontroller( (LocalFlexController_t)0 ) : -1; -} - - -inline int mstudioflexcontrollerui_t::leftIndex( const CStudioHdr &cStudioHdr ) const -{ - return stereo ? pLeftController() - cStudioHdr.pFlexcontroller((LocalFlexController_t) 0 ) : -1; -} - - -inline int mstudioflexcontrollerui_t::nWayValueIndex( const CStudioHdr &cStudioHdr ) const -{ - return remaptype == FLEXCONTROLLER_REMAP_NWAY ? pNWayValueController() - cStudioHdr.pFlexcontroller( (LocalFlexController_t)0 ) : -1; -} - - -inline const mstudioflexcontroller_t *mstudioflexcontrollerui_t::pController( int index ) const -{ - if ( index < 0 || index > Count() ) - return NULL; - - if ( remaptype == FLEXCONTROLLER_REMAP_NWAY ) - { - if ( stereo ) - return (mstudioflexcontroller_t *)( ( char * ) this ) + *( &szindex0 + index ); - - if ( index == 0 ) - return pController(); - - if ( index == 1 ) - return pNWayValueController(); - - return NULL; - } - - if ( index > 1 ) - return NULL; - - if ( stereo ) - return (mstudioflexcontroller_t *)( ( char * ) this ) + *( &szindex0 + index ); - - if ( index > 0 ) - return NULL; - - return pController(); -} - - -#define STUDIO_CONST 1 // get float -#define STUDIO_FETCH1 2 // get Flexcontroller value -#define STUDIO_FETCH2 3 // get flex weight -#define STUDIO_ADD 4 -#define STUDIO_SUB 5 -#define STUDIO_MUL 6 -#define STUDIO_DIV 7 -#define STUDIO_NEG 8 // not implemented -#define STUDIO_EXP 9 // not implemented -#define STUDIO_OPEN 10 // only used in token parsing -#define STUDIO_CLOSE 11 -#define STUDIO_COMMA 12 // only used in token parsing -#define STUDIO_MAX 13 -#define STUDIO_MIN 14 -#define STUDIO_2WAY_0 15 // Fetch a value from a 2 Way slider for the 1st value RemapVal( 0.0, 0.5, 0.0, 1.0 ) -#define STUDIO_2WAY_1 16 // Fetch a value from a 2 Way slider for the 2nd value RemapVal( 0.5, 1.0, 0.0, 1.0 ) -#define STUDIO_NWAY 17 // Fetch a value from a 2 Way slider for the 2nd value RemapVal( 0.5, 1.0, 0.0, 1.0 ) -#define STUDIO_COMBO 18 // Perform a combo operation (essentially multiply the last N values on the stack) -#define STUDIO_DOMINATE 19 // Performs a combination domination operation -#define STUDIO_DME_LOWER_EYELID 20 // -#define STUDIO_DME_UPPER_EYELID 21 // - -// motion flags -#define STUDIO_X 0x00000001 -#define STUDIO_Y 0x00000002 -#define STUDIO_Z 0x00000004 -#define STUDIO_XR 0x00000008 -#define STUDIO_YR 0x00000010 -#define STUDIO_ZR 0x00000020 - -#define STUDIO_LX 0x00000040 -#define STUDIO_LY 0x00000080 -#define STUDIO_LZ 0x00000100 -#define STUDIO_LXR 0x00000200 -#define STUDIO_LYR 0x00000400 -#define STUDIO_LZR 0x00000800 - -#define STUDIO_LINEAR 0x00001000 - -#define STUDIO_TYPES 0x0003FFFF -#define STUDIO_RLOOP 0x00040000 // controller that wraps shortest distance - -// sequence and autolayer flags -#define STUDIO_LOOPING 0x0001 // ending frame should be the same as the starting frame -#define STUDIO_SNAP 0x0002 // do not interpolate between previous animation and this one -#define STUDIO_DELTA 0x0004 // this sequence "adds" to the base sequences, not slerp blends -#define STUDIO_AUTOPLAY 0x0008 // temporary flag that forces the sequence to always play -#define STUDIO_POST 0x0010 // -#define STUDIO_ALLZEROS 0x0020 // this animation/sequence has no real animation data -// 0x0040 -#define STUDIO_CYCLEPOSE 0x0080 // cycle index is taken from a pose parameter index -#define STUDIO_REALTIME 0x0100 // cycle index is taken from a real-time clock, not the animations cycle index -#define STUDIO_LOCAL 0x0200 // sequence has a local context sequence -#define STUDIO_HIDDEN 0x0400 // don't show in default selection views -#define STUDIO_OVERRIDE 0x0800 // a forward declared sequence (empty) -#define STUDIO_ACTIVITY 0x1000 // Has been updated at runtime to activity index -#define STUDIO_EVENT 0x2000 // Has been updated at runtime to event index -#define STUDIO_WORLD 0x4000 // sequence blends in worldspace -// autolayer flags -// 0x0001 -// 0x0002 -// 0x0004 -// 0x0008 -#define STUDIO_AL_POST 0x0010 // -// 0x0020 -#define STUDIO_AL_SPLINE 0x0040 // convert layer ramp in/out curve is a spline instead of linear -#define STUDIO_AL_XFADE 0x0080 // pre-bias the ramp curve to compense for a non-1 weight, assuming a second layer is also going to accumulate -// 0x0100 -#define STUDIO_AL_NOBLEND 0x0200 // animation always blends at 1.0 (ignores weight) -// 0x0400 -// 0x0800 -#define STUDIO_AL_LOCAL 0x1000 // layer is a local context sequence -// 0x2000 -#define STUDIO_AL_POSE 0x4000 // layer blends using a pose parameter instead of parent cycle - - -// Insert this code anywhere that you need to allow for conversion from an old STUDIO_VERSION -// to a new one. -// If we only support the current version, this function should be empty. -inline bool Studio_ConvertStudioHdrToNewVersion( studiohdr_t *pStudioHdr ) -{ - COMPILE_TIME_ASSERT( STUDIO_VERSION == 48 ); // put this to make sure this code is updated upon changing version. - - int version = pStudioHdr->version; - if ( version == STUDIO_VERSION ) - return true; - - bool bResult = true; - if (version < 46) - { - // some of the anim index data is incompatible - for (int i = 0; i < pStudioHdr->numlocalanim; i++) - { - mstudioanimdesc_t *pAnim = (mstudioanimdesc_t *)pStudioHdr->pLocalAnimdesc( i ); - - // old ANI files that used sections (v45 only) are not compatible - if ( pAnim->sectionframes != 0 ) - { - // zero most everything out - memset( &(pAnim->numframes), 0, (byte *)(pAnim + 1) - (byte *)&(pAnim->numframes) ); - - pAnim->numframes = 1; - pAnim->animblock = -1; // disable animation fetching - bResult = false; - } - } - } - - if (version < 47) - { - // used to contain zeroframe cache data - if (pStudioHdr->unused4 != 0) - { - pStudioHdr->unused4 = 0; - bResult = false; - } - for (int i = 0; i < pStudioHdr->numlocalanim; i++) - { - mstudioanimdesc_t *pAnim = (mstudioanimdesc_t *)pStudioHdr->pLocalAnimdesc( i ); - pAnim->zeroframeindex = 0; - pAnim->zeroframespan = 0; - } - } - else if (version == 47) - { - for (int i = 0; i < pStudioHdr->numlocalanim; i++) - { - mstudioanimdesc_t *pAnim = (mstudioanimdesc_t *)pStudioHdr->pLocalAnimdesc( i ); - if (pAnim->zeroframeindex != 0) - { - pAnim->zeroframeindex = 0; - pAnim->zeroframespan = 0; - bResult = false; - } - } - } - - // for now, just slam the version number since they're compatible - pStudioHdr->version = STUDIO_VERSION; - - return bResult; -} - -// must be run to fixup with specified rootLOD -inline void Studio_SetRootLOD( studiohdr_t *pStudioHdr, int rootLOD ) -{ - // honor studiohdr restriction of root lod in case requested root lod exceeds restriction. - if ( pStudioHdr->numAllowedRootLODs > 0 && - rootLOD >= pStudioHdr->numAllowedRootLODs ) - { - rootLOD = pStudioHdr->numAllowedRootLODs - 1; - } - - // run the lod fixups that culls higher detail lods - // vertexes are external, fixups ensure relative offsets and counts are cognizant of shrinking data - // indexes are built in lodN..lod0 order so higher detail lod data can be truncated at load - // the fixup lookup arrays are filled (or replicated) to ensure all slots valid - int vertexindex = 0; - int tangentsindex = 0; - int bodyPartID; - for ( bodyPartID = 0; bodyPartID < pStudioHdr->numbodyparts; bodyPartID++ ) - { - mstudiobodyparts_t *pBodyPart = pStudioHdr->pBodypart( bodyPartID ); - int modelID; - for ( modelID = 0; modelID < pBodyPart->nummodels; modelID++ ) - { - mstudiomodel_t *pModel = pBodyPart->pModel( modelID ); - int totalMeshVertexes = 0; - int meshID; - for ( meshID = 0; meshID < pModel->nummeshes; meshID++ ) - { - mstudiomesh_t *pMesh = pModel->pMesh( meshID ); - - // get the fixup, vertexes are reduced - pMesh->numvertices = pMesh->vertexdata.numLODVertexes[rootLOD]; - pMesh->vertexoffset = totalMeshVertexes; - totalMeshVertexes += pMesh->numvertices; - } - - // stay in sync - pModel->numvertices = totalMeshVertexes; - pModel->vertexindex = vertexindex; - pModel->tangentsindex = tangentsindex; - - vertexindex += totalMeshVertexes*sizeof(mstudiovertex_t); - tangentsindex += totalMeshVertexes*sizeof(Vector4D); - } - } - - // track the set desired configuration - pStudioHdr->rootLOD = rootLOD; -} - -// Determines allocation requirements for vertexes -inline int Studio_VertexDataSize( const vertexFileHeader_t *pVvdHdr, int rootLOD, bool bNeedsTangentS ) -{ - // the quantity of vertexes necessary for root lod and all lower detail lods - // add one extra vertex to each section - // the extra vertex allows prefetch hints to read ahead 1 vertex without faulting - int numVertexes = pVvdHdr->numLODVertexes[rootLOD] + 1; - int dataLength = pVvdHdr->vertexDataStart + numVertexes*sizeof(mstudiovertex_t); - if (bNeedsTangentS) - { - dataLength += numVertexes*sizeof(Vector4D); - } - - // allocate this much - return dataLength; -} - -// Load the minimum quantity of verts and run fixups -inline int Studio_LoadVertexes( const vertexFileHeader_t *pTempVvdHdr, vertexFileHeader_t *pNewVvdHdr, int rootLOD, bool bNeedsTangentS ) -{ - int i; - int target; - int numVertexes; - vertexFileFixup_t *pFixupTable; - - numVertexes = pTempVvdHdr->numLODVertexes[rootLOD]; - - // copy all data up to start of vertexes - memcpy((void*)pNewVvdHdr, (void*)pTempVvdHdr, pTempVvdHdr->vertexDataStart); - - for ( i = 0; i < rootLOD; i++) - { - pNewVvdHdr->numLODVertexes[i] = pNewVvdHdr->numLODVertexes[rootLOD]; - } - - // fixup data starts - if (bNeedsTangentS) - { - // tangent data follows possibly reduced vertex data - pNewVvdHdr->tangentDataStart = pNewVvdHdr->vertexDataStart + numVertexes*sizeof(mstudiovertex_t); - } - else - { - // no tangent data will be available, mark for identification - pNewVvdHdr->tangentDataStart = 0; - } - - if (!pNewVvdHdr->numFixups) - { - // fixups not required - // transfer vertex data - memcpy( - (byte *)pNewVvdHdr+pNewVvdHdr->vertexDataStart, - (byte *)pTempVvdHdr+pTempVvdHdr->vertexDataStart, - numVertexes*sizeof(mstudiovertex_t) ); - - if (bNeedsTangentS) - { - // transfer tangent data to cache memory - memcpy( - (byte *)pNewVvdHdr+pNewVvdHdr->tangentDataStart, - (byte *)pTempVvdHdr+pTempVvdHdr->tangentDataStart, - numVertexes*sizeof(Vector4D) ); - } - - return numVertexes; - } - - // fixups required - // re-establish mesh ordered vertexes into cache memory, according to table - target = 0; - pFixupTable = (vertexFileFixup_t *)((byte *)pTempVvdHdr + pTempVvdHdr->fixupTableStart); - for (i=0; inumFixups; i++) - { - if (pFixupTable[i].lod < rootLOD) - { - // working bottom up, skip over copying higher detail lods - continue; - } - - // copy vertexes - memcpy( - (mstudiovertex_t *)((byte *)pNewVvdHdr+pNewVvdHdr->vertexDataStart) + target, - (mstudiovertex_t *)((byte *)pTempVvdHdr+pTempVvdHdr->vertexDataStart) + pFixupTable[i].sourceVertexID, - pFixupTable[i].numVertexes*sizeof(mstudiovertex_t) ); - - if (bNeedsTangentS) - { - // copy tangents - memcpy( - (Vector4D *)((byte *)pNewVvdHdr+pNewVvdHdr->tangentDataStart) + target, - (Vector4D *)((byte *)pTempVvdHdr+pTempVvdHdr->tangentDataStart) + pFixupTable[i].sourceVertexID, - pFixupTable[i].numVertexes*sizeof(Vector4D) ); - } - - // data is placed consecutively - target += pFixupTable[i].numVertexes; - } - - pNewVvdHdr->numFixups = 0; - - return target; -} - -#endif // STUDIO_H diff --git a/public/studio_generic_io.cpp b/public/studio_generic_io.cpp deleted file mode 100644 index 054c911b7..000000000 --- a/public/studio_generic_io.cpp +++ /dev/null @@ -1,156 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#include - -#include "studio.h" -#include "UtlRBTree.h" - -extern studiohdr_t *FindOrLoadGroupFile( char const *modelname ); - -virtualmodel_t *studiohdr_t::GetVirtualModel( void ) const -{ - if (numincludemodels == 0) - { - return NULL; - } - - virtualmodel_t *pVModel = (virtualmodel_t *)virtualModel; - - if (pVModel == NULL) - { - pVModel = new virtualmodel_t; - - // !!! Set cache handle? Set pointer to local virtual model?? - virtualModel = (void *)pVModel; - - int group = pVModel->m_group.AddToTail( ); - pVModel->m_group[ group ].cache = (void *)this; - pVModel->AppendModels( 0, this ); - } - - return pVModel; -} - - -const studiohdr_t *studiohdr_t::FindModel( void **cache, char const *modelname ) const -{ - studiohdr_t *hdr = (studiohdr_t *)(*cache); - - if (hdr) - { - return hdr; - } - - hdr = FindOrLoadGroupFile( modelname ); - - *cache = (void *)hdr; - - return hdr; -} - -const studiohdr_t *virtualgroup_t::GetStudioHdr( void ) const -{ - return (studiohdr_t *)cache; -} - - -byte *studiohdr_t::GetAnimBlock( int i ) const -{ - byte *hdr = (byte *)animblockModel; - - if (!hdr) - { - hdr = (byte *)FindOrLoadGroupFile( pszAnimBlockName() ); - animblockModel = hdr; - } - - return hdr + pAnimBlock( i )->datastart; -} - -//----------------------------------------------------------------------------- -// Purpose: Builds up a dictionary of autoplay indices by studiohdr_t * -// NOTE: This list never gets freed even if the model gets unloaded, but we're in a tool so we can probably live with that -//----------------------------------------------------------------------------- -struct AutoPlayGeneric_t -{ -public: - - AutoPlayGeneric_t() : - hdr( 0 ) - { - } - - // Implement copy constructor - AutoPlayGeneric_t( const AutoPlayGeneric_t& src ) - { - hdr = src.hdr; - autoplaylist.EnsureCount( src.autoplaylist.Count() ); - autoplaylist.CopyArray( src.autoplaylist.Base(), src.autoplaylist.Count() ); - } - - static bool AutoPlayGenericLessFunc( const AutoPlayGeneric_t& lhs, const AutoPlayGeneric_t& rhs ) - { - return lhs.hdr < rhs.hdr; - } - -public: - // Data - const studiohdr_t *hdr; - CUtlVector< unsigned short > autoplaylist; -}; - -// A global array to track this data -static CUtlRBTree< AutoPlayGeneric_t, int > g_AutoPlayGeneric( 0, 0, AutoPlayGeneric_t::AutoPlayGenericLessFunc ); - -int studiohdr_t::GetAutoplayList( unsigned short **pAutoplayList ) const -{ - virtualmodel_t *pVirtualModel = GetVirtualModel(); - if ( pVirtualModel ) - { - if ( pAutoplayList && pVirtualModel->m_autoplaySequences.Count() ) - { - *pAutoplayList = pVirtualModel->m_autoplaySequences.Base(); - } - return pVirtualModel->m_autoplaySequences.Count(); - } - - AutoPlayGeneric_t *pData = NULL; - - // Search for this studiohdr_t ptr in the global list - AutoPlayGeneric_t search; - search.hdr = this; - int index = g_AutoPlayGeneric.Find( search ); - if ( index == g_AutoPlayGeneric.InvalidIndex() ) - { - // Not there, so add it - index = g_AutoPlayGeneric.Insert( search ); - pData = &g_AutoPlayGeneric[ index ]; - // And compute the autoplay info this one time - int autoPlayCount = CountAutoplaySequences(); - pData->autoplaylist.EnsureCount( autoPlayCount ); - CopyAutoplaySequences( pData->autoplaylist.Base(), autoPlayCount ); - } - else - { - // Refer to existing data - pData = &g_AutoPlayGeneric[ index ]; - } - - // Oops!!! - if ( !pData ) - { - return 0; - } - - // Give back data if it's being requested - if ( pAutoplayList ) - { - *pAutoplayList = pData->autoplaylist.Base(); - } - return pData->autoplaylist.Count(); -} diff --git a/public/studio_virtualmodel.cpp b/public/studio_virtualmodel.cpp deleted file mode 100644 index 56082a459..000000000 --- a/public/studio_virtualmodel.cpp +++ /dev/null @@ -1,575 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#include -#include "studio.h" -#include "tier1/utlmap.h" -#include "tier1/utldict.h" -#include "tier1/utlbuffer.h" -#include "filesystem.h" -#include "tier0/icommandline.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -extern IFileSystem * g_pFileSystem; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -// a string table to speed up searching for sequences in the current virtual model -struct modellookup_t -{ - CUtlDict seqTable; - CUtlDict animTable; -}; - -static CUtlVector g_ModelLookup; -static int g_ModelLookupIndex = -1; - -inline bool HasLookupTable() -{ - return g_ModelLookupIndex >= 0 ? true : false; -} - -inline CUtlDict *GetSeqTable() -{ - return &g_ModelLookup[g_ModelLookupIndex].seqTable; -} - -inline CUtlDict *GetAnimTable() -{ - return &g_ModelLookup[g_ModelLookupIndex].animTable; -} - -class CModelLookupContext -{ -public: - CModelLookupContext(int group, const studiohdr_t *pStudioHdr); - ~CModelLookupContext(); - -private: - int m_lookupIndex; -}; - -CModelLookupContext::CModelLookupContext(int group, const studiohdr_t *pStudioHdr) -{ - m_lookupIndex = -1; - if ( group == 0 && pStudioHdr->numincludemodels ) - { - m_lookupIndex = g_ModelLookup.AddToTail(); - g_ModelLookupIndex = g_ModelLookup.Count()-1; - } -} - -CModelLookupContext::~CModelLookupContext() -{ - if ( m_lookupIndex >= 0 ) - { - Assert(m_lookupIndex == (g_ModelLookup.Count()-1)); - g_ModelLookup.FastRemove(m_lookupIndex); - g_ModelLookupIndex = g_ModelLookup.Count()-1; - } -} - -void virtualmodel_t::AppendModels( int group, const studiohdr_t *pStudioHdr ) -{ - AUTO_LOCK_( CThreadTerminalMutex, m_Lock ); - - // build a search table if necesary - CModelLookupContext ctx(group, pStudioHdr); - - AppendSequences( group, pStudioHdr ); - AppendAnimations( group, pStudioHdr ); - AppendBonemap( group, pStudioHdr ); - AppendAttachments( group, pStudioHdr ); - AppendPoseParameters( group, pStudioHdr ); - AppendNodes( group, pStudioHdr ); - AppendIKLocks( group, pStudioHdr ); - - struct HandleAndHeader_t - { - void *handle; - const studiohdr_t *pHdr; - }; - HandleAndHeader_t list[64]; - - // determine quantity of valid include models in one pass only - // temporarily cache results off, otherwise FindModel() causes ref counting problems - int j; - int nValidIncludes = 0; - for (j = 0; j < pStudioHdr->numincludemodels; j++) - { - // find model (increases ref count) - void *tmp = NULL; - const studiohdr_t *pTmpHdr = pStudioHdr->FindModel( &tmp, pStudioHdr->pModelGroup( j )->pszName() ); - if ( pTmpHdr ) - { - if ( nValidIncludes >= ARRAYSIZE( list ) ) - { - // would cause stack overflow - Assert( 0 ); - break; - } - - list[nValidIncludes].handle = tmp; - list[nValidIncludes].pHdr = pTmpHdr; - nValidIncludes++; - } - } - - if ( nValidIncludes ) - { - m_group.EnsureCapacity( m_group.Count() + nValidIncludes ); - for (j = 0; j < nValidIncludes; j++) - { - MEM_ALLOC_CREDIT(); - int group = m_group.AddToTail(); - m_group[group].cache = list[j].handle; - AppendModels( group, list[j].pHdr ); - } - } - - UpdateAutoplaySequences( pStudioHdr ); -} - -void virtualmodel_t::AppendSequences( int group, const studiohdr_t *pStudioHdr ) -{ - AUTO_LOCK_( CThreadTerminalMutex, m_Lock ); - int numCheck = m_seq.Count(); - - int j, k; - - MEM_ALLOC_CREDIT(); - - CUtlVector< virtualsequence_t > seq; - - seq = m_seq; - - m_group[ group ].masterSeq.SetCount( pStudioHdr->numlocalseq ); - - for (j = 0; j < pStudioHdr->numlocalseq; j++) - { - const mstudioseqdesc_t *seqdesc = pStudioHdr->pLocalSeqdesc( j ); - char *s1 = seqdesc->pszLabel(); - - if ( HasLookupTable() ) - { - k = numCheck; - short index = GetSeqTable()->Find( s1 ); - if ( index != GetSeqTable()->InvalidIndex() ) - { - k = GetSeqTable()->Element(index); - } - } - else - { - for (k = 0; k < numCheck; k++) - { - const studiohdr_t *hdr = m_group[ seq[k].group ].GetStudioHdr(); - char *s2 = hdr->pLocalSeqdesc( seq[k].index )->pszLabel(); - if ( !stricmp( s1, s2 ) ) - { - break; - } - } - } - // no duplication - if (k == numCheck) - { - virtualsequence_t tmp; - tmp.group = group; - tmp.index = j; - tmp.flags = seqdesc->flags; - tmp.activity = seqdesc->activity; - k = seq.AddToTail( tmp ); - } - else if (m_group[ seq[k].group ].GetStudioHdr()->pLocalSeqdesc( seq[k].index )->flags & STUDIO_OVERRIDE) - { - // the one in memory is a forward declared sequence, override it - virtualsequence_t tmp; - tmp.group = group; - tmp.index = j; - tmp.flags = seqdesc->flags; - tmp.activity = seqdesc->activity; - seq[k] = tmp; - } - m_group[ group ].masterSeq[ j ] = k; - } - - if ( HasLookupTable() ) - { - for ( j = numCheck; j < seq.Count(); j++ ) - { - const studiohdr_t *hdr = m_group[ seq[j].group ].GetStudioHdr(); - const char *s1 = hdr->pLocalSeqdesc( seq[j].index )->pszLabel(); - GetSeqTable()->Insert( s1, j ); - } - } - - m_seq = seq; -} - - -void virtualmodel_t::UpdateAutoplaySequences( const studiohdr_t *pStudioHdr ) -{ - AUTO_LOCK_( CThreadTerminalMutex, m_Lock ); - int autoplayCount = pStudioHdr->CountAutoplaySequences(); - m_autoplaySequences.SetCount( autoplayCount ); - pStudioHdr->CopyAutoplaySequences( m_autoplaySequences.Base(), autoplayCount ); -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -void virtualmodel_t::AppendAnimations( int group, const studiohdr_t *pStudioHdr ) -{ - AUTO_LOCK_( CThreadTerminalMutex, m_Lock ); - int numCheck = m_anim.Count(); - - CUtlVector< virtualgeneric_t > anim; - anim = m_anim; - - MEM_ALLOC_CREDIT(); - - int j, k; - - m_group[ group ].masterAnim.SetCount( pStudioHdr->numlocalanim ); - - for (j = 0; j < pStudioHdr->numlocalanim; j++) - { - char *s1 = pStudioHdr->pLocalAnimdesc( j )->pszName(); - if ( HasLookupTable() ) - { - k = numCheck; - short index = GetAnimTable()->Find( s1 ); - if ( index != GetAnimTable()->InvalidIndex() ) - { - k = GetAnimTable()->Element(index); - } - } - else - { - for (k = 0; k < numCheck; k++) - { - char *s2 = m_group[ anim[k].group ].GetStudioHdr()->pLocalAnimdesc( anim[k].index )->pszName(); - if (stricmp( s1, s2 ) == 0) - { - break; - } - } - } - // no duplication - if (k == numCheck) - { - virtualgeneric_t tmp; - tmp.group = group; - tmp.index = j; - k = anim.AddToTail( tmp ); - } - - m_group[ group ].masterAnim[ j ] = k; - } - - if ( HasLookupTable() ) - { - for ( j = numCheck; j < anim.Count(); j++ ) - { - const char *s1 = m_group[ anim[j].group ].GetStudioHdr()->pLocalAnimdesc( anim[j].index )->pszName(); - GetAnimTable()->Insert( s1, j ); - } - } - - m_anim = anim; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -void virtualmodel_t::AppendBonemap( int group, const studiohdr_t *pStudioHdr ) -{ - AUTO_LOCK_( CThreadTerminalMutex, m_Lock ); - MEM_ALLOC_CREDIT(); - - const studiohdr_t *pBaseStudioHdr = m_group[ 0 ].GetStudioHdr( ); - - m_group[ group ].boneMap.SetCount( pBaseStudioHdr->numbones ); - m_group[ group ].masterBone.SetCount( pStudioHdr->numbones ); - - int j, k; - - if (group == 0) - { - for (j = 0; j < pStudioHdr->numbones; j++) - { - m_group[ group ].boneMap[ j ] = j; - m_group[ group ].masterBone[ j ] = j; - } - } - else - { - for (j = 0; j < pBaseStudioHdr->numbones; j++) - { - m_group[ group ].boneMap[ j ] = -1; - } - for (j = 0; j < pStudioHdr->numbones; j++) - { - // NOTE: studiohdr has a bone table - using the table is ~5% faster than this for alyx.mdl on a P4/3.2GHz - for (k = 0; k < pBaseStudioHdr->numbones; k++) - { - if (stricmp( pStudioHdr->pBone( j )->pszName(), pBaseStudioHdr->pBone( k )->pszName() ) == 0) - { - break; - } - } - if (k < pBaseStudioHdr->numbones) - { - m_group[ group ].masterBone[ j ] = k; - m_group[ group ].boneMap[ k ] = j; - - // FIXME: these runtime messages don't display in hlmv - if ((pStudioHdr->pBone( j )->parent == -1) || (pBaseStudioHdr->pBone( k )->parent == -1)) - { - if ((pStudioHdr->pBone( j )->parent != -1) || (pBaseStudioHdr->pBone( k )->parent != -1)) - { - Warning( "%s/%s : missmatched parent bones on \"%s\"\n", pBaseStudioHdr->pszName(), pStudioHdr->pszName(), pStudioHdr->pBone( j )->pszName() ); - } - } - else if (m_group[ group ].masterBone[ pStudioHdr->pBone( j )->parent ] != m_group[ 0 ].masterBone[ pBaseStudioHdr->pBone( k )->parent ]) - { - Warning( "%s/%s : missmatched parent bones on \"%s\"\n", pBaseStudioHdr->pszName(), pStudioHdr->pszName(), pStudioHdr->pBone( j )->pszName() ); - } - } - else - { - m_group[ group ].masterBone[ j ] = -1; - } - } - } -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -void virtualmodel_t::AppendAttachments( int group, const studiohdr_t *pStudioHdr ) -{ - AUTO_LOCK_( CThreadTerminalMutex, m_Lock ); - int numCheck = m_attachment.Count(); - - CUtlVector< virtualgeneric_t > attachment; - attachment = m_attachment; - - MEM_ALLOC_CREDIT(); - - int j, k, n; - - m_group[ group ].masterAttachment.SetCount( pStudioHdr->numlocalattachments ); - - for (j = 0; j < pStudioHdr->numlocalattachments; j++) - { - - n = m_group[ group ].masterBone[ pStudioHdr->pLocalAttachment( j )->localbone ]; - - // skip if the attachments bone doesn't exist in the root model - if (n == -1) - { - continue; - } - - - char *s1 = pStudioHdr->pLocalAttachment( j )->pszName(); - for (k = 0; k < numCheck; k++) - { - char *s2 = m_group[ attachment[k].group ].GetStudioHdr()->pLocalAttachment( attachment[k].index )->pszName(); - - if (stricmp( s1, s2 ) == 0) - { - break; - } - } - // no duplication - if (k == numCheck) - { - virtualgeneric_t tmp; - tmp.group = group; - tmp.index = j; - k = attachment.AddToTail( tmp ); - - // make sure bone flags are set so attachment calculates - if ((m_group[ 0 ].GetStudioHdr()->pBone( n )->flags & BONE_USED_BY_ATTACHMENT) == 0) - { - while (n != -1) - { - m_group[ 0 ].GetStudioHdr()->pBone( n )->flags |= BONE_USED_BY_ATTACHMENT; - - if (m_group[ 0 ].GetStudioHdr()->pLinearBones()) - { - *m_group[ 0 ].GetStudioHdr()->pLinearBones()->pflags(n) |= BONE_USED_BY_ATTACHMENT; - } - - n = m_group[ 0 ].GetStudioHdr()->pBone( n )->parent; - } - continue; - } - } - - m_group[ group ].masterAttachment[ j ] = k; - } - - m_attachment = attachment; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -void virtualmodel_t::AppendPoseParameters( int group, const studiohdr_t *pStudioHdr ) -{ - AUTO_LOCK_( CThreadTerminalMutex, m_Lock ); - int numCheck = m_pose.Count(); - - CUtlVector< virtualgeneric_t > pose; - pose = m_pose; - - MEM_ALLOC_CREDIT(); - - int j, k; - - m_group[ group ].masterPose.SetCount( pStudioHdr->numlocalposeparameters ); - - for (j = 0; j < pStudioHdr->numlocalposeparameters; j++) - { - char *s1 = pStudioHdr->pLocalPoseParameter( j )->pszName(); - for (k = 0; k < numCheck; k++) - { - char *s2 = m_group[ pose[k].group ].GetStudioHdr()->pLocalPoseParameter( pose[k].index )->pszName(); - - if (stricmp( s1, s2 ) == 0) - { - break; - } - } - if (k == numCheck) - { - // no duplication - virtualgeneric_t tmp; - tmp.group = group; - tmp.index = j; - k = pose.AddToTail( tmp ); - } - else - { - // duplicate, reset start and end to fit full dynamic range - mstudioposeparamdesc_t *pPose1 = pStudioHdr->pLocalPoseParameter( j ); - mstudioposeparamdesc_t *pPose2 = m_group[ pose[k].group ].GetStudioHdr()->pLocalPoseParameter( pose[k].index ); - float start = MIN( pPose2->end, MIN( pPose1->end, MIN( pPose2->start, pPose1->start ) ) ); - float end = MAX( pPose2->end, MAX( pPose1->end, MAX( pPose2->start, pPose1->start ) ) ); - pPose2->start = start; - pPose2->end = end; - } - - m_group[ group ].masterPose[ j ] = k; - } - - m_pose = pose; -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - -void virtualmodel_t::AppendNodes( int group, const studiohdr_t *pStudioHdr ) -{ - AUTO_LOCK_( CThreadTerminalMutex, m_Lock ); - int numCheck = m_node.Count(); - - CUtlVector< virtualgeneric_t > node; - node = m_node; - - MEM_ALLOC_CREDIT(); - - int j, k; - - m_group[ group ].masterNode.SetCount( pStudioHdr->numlocalnodes ); - - for (j = 0; j < pStudioHdr->numlocalnodes; j++) - { - char *s1 = pStudioHdr->pszLocalNodeName( j ); - for (k = 0; k < numCheck; k++) - { - char *s2 = m_group[ node[k].group ].GetStudioHdr()->pszLocalNodeName( node[k].index ); - - if (stricmp( s1, s2 ) == 0) - { - break; - } - } - // no duplication - if (k == numCheck) - { - virtualgeneric_t tmp; - tmp.group = group; - tmp.index = j; - k = node.AddToTail( tmp ); - } - - m_group[ group ].masterNode[ j ] = k; - } - - m_node = node; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- - - -void virtualmodel_t::AppendIKLocks( int group, const studiohdr_t *pStudioHdr ) -{ - AUTO_LOCK_( CThreadTerminalMutex, m_Lock ); - int numCheck = m_iklock.Count(); - - CUtlVector< virtualgeneric_t > iklock; - iklock = m_iklock; - - int j, k; - - for (j = 0; j < pStudioHdr->numlocalikautoplaylocks; j++) - { - int chain1 = pStudioHdr->pLocalIKAutoplayLock( j )->chain; - for (k = 0; k < numCheck; k++) - { - int chain2 = m_group[ iklock[k].group ].GetStudioHdr()->pLocalIKAutoplayLock( iklock[k].index )->chain; - - if (chain1 == chain2) - { - break; - } - } - // no duplication - if (k == numCheck) - { - MEM_ALLOC_CREDIT(); - - virtualgeneric_t tmp; - tmp.group = group; - tmp.index = j; - k = iklock.AddToTail( tmp ); - } - } - - m_iklock = iklock; -} diff --git a/public/surfinfo.h b/public/surfinfo.h deleted file mode 100644 index 3fb3bc60a..000000000 --- a/public/surfinfo.h +++ /dev/null @@ -1,31 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#ifndef SURFINFO_H -#define SURFINFO_H -#ifdef _WIN32 -#pragma once -#endif - -#include "mathlib/vplane.h" - -//#include "mathlib/vector.h" -#define MAX_SURFINFO_VERTS 16 -class SurfInfo -{ -public: - // Shape of the surface. - Vector m_Verts[ MAX_SURFINFO_VERTS ]; - unsigned long m_nVerts; - - // Plane of the surface. - VPlane m_Plane; - - // For engine use only.. - void *m_pEngineData; -}; - -#endif // SURFINFO_H diff --git a/public/texture_group_names.h b/public/texture_group_names.h deleted file mode 100644 index 7b169ffc2..000000000 --- a/public/texture_group_names.h +++ /dev/null @@ -1,43 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#ifndef TEXTURE_GROUP_NAMES_H -#define TEXTURE_GROUP_NAMES_H -#ifdef _WIN32 -#pragma once -#endif - -// These are given to FindMaterial to reference the texture groups that show up on the -#define TEXTURE_GROUP_LIGHTMAP "Lightmaps" -#define TEXTURE_GROUP_WORLD "World textures" -#define TEXTURE_GROUP_MODEL "Model textures" -#define TEXTURE_GROUP_VGUI "VGUI textures" -#define TEXTURE_GROUP_PARTICLE "Particle textures" -#define TEXTURE_GROUP_DECAL "Decal textures" -#define TEXTURE_GROUP_SKYBOX "SkyBox textures" -#define TEXTURE_GROUP_CLIENT_EFFECTS "ClientEffect textures" -#define TEXTURE_GROUP_OTHER "Other textures" -#define TEXTURE_GROUP_PRECACHED "Precached" // TODO: assign texture groups to the precached materials -#define TEXTURE_GROUP_CUBE_MAP "CubeMap textures" -#define TEXTURE_GROUP_RENDER_TARGET "RenderTargets" -#define TEXTURE_GROUP_UNACCOUNTED "Unaccounted textures" // Textures that weren't assigned a texture group. -//#define TEXTURE_GROUP_STATIC_VERTEX_BUFFER "Static Vertex" -#define TEXTURE_GROUP_STATIC_INDEX_BUFFER "Static Indices" -#define TEXTURE_GROUP_STATIC_VERTEX_BUFFER_DISP "Displacement Verts" -#define TEXTURE_GROUP_STATIC_VERTEX_BUFFER_COLOR "Lighting Verts" -#define TEXTURE_GROUP_STATIC_VERTEX_BUFFER_WORLD "World Verts" -#define TEXTURE_GROUP_STATIC_VERTEX_BUFFER_MODELS "Model Verts" -#define TEXTURE_GROUP_STATIC_VERTEX_BUFFER_OTHER "Other Verts" -#define TEXTURE_GROUP_DYNAMIC_INDEX_BUFFER "Dynamic Indices" -#define TEXTURE_GROUP_DYNAMIC_VERTEX_BUFFER "Dynamic Verts" -#define TEXTURE_GROUP_DEPTH_BUFFER "DepthBuffer" -#define TEXTURE_GROUP_VIEW_MODEL "ViewModel" -#define TEXTURE_GROUP_PIXEL_SHADERS "Pixel Shaders" -#define TEXTURE_GROUP_VERTEX_SHADERS "Vertex Shaders" -#define TEXTURE_GROUP_RENDER_TARGET_SURFACE "RenderTarget Surfaces" -#define TEXTURE_GROUP_MORPH_TARGETS "Morph Targets" - -#endif // TEXTURE_GROUP_NAMES_H diff --git a/public/tier0/EventMasks.h b/public/tier0/EventMasks.h deleted file mode 100644 index 4774809f4..000000000 --- a/public/tier0/EventMasks.h +++ /dev/null @@ -1,480 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#pragma once - -typedef union EVENT_MASK(TC_deliver_mode) -{ - struct - { - uint16 DD:1; // both logical processors in deliver mode }, - uint16 DB:1; // logical processor 0 in deliver mode, 1 in build mode }, - uint16 DI:1; // logical processor 0 in deliver mode, 1 is inactive }, - uint16 BD:1; // logical processor 0 in build mode, 1 in deliver mode }, - uint16 BB:1; // both logical processors in build mode }, - uint16 BI:1; // logical processor 0 in build mode, 1 is inactive }, - uint16 ID:1; // logical processor 0 is inactive, 1 in deliver mode }, - uint16 IB:1; // logical processor 0 is inactive, 1 in build mode } - }; - uint16 flat; -} EVENT_MASK(TC_deliver_mode); - -typedef union EVENT_MASK(BPU_fetch_request) -{ - - struct - { - uint16 TCMISS:1; // Trace cache lookup miss }, - }; - uint16 flat; -} EVENT_MASK(BPU_fetch_request); - - -typedef union EVENT_MASK(ITLB_reference) -{ - struct - { - uint16 HIT : 1; //ITLB hit }, - uint16 MISS : 1;//ITLB miss }, - uint16 HIT_UC :1; // Uncacheable ITLB hit } - }; - uint16 flat; -} EVENT_MASK(ITLB_reference); - -typedef union EVENT_MASK(memory_cancel) -{ - struct - { - uint16 dummy : 2; - - uint16 ST_RB_FULL:1; //Replayed because no store request buffer is available }, - uint16 _64K_CONF:1; //Conflicts due to 64K aliasing } - }; - uint16 flat; -}EVENT_MASK(memory_cancel); - -typedef union EVENT_MASK(memory_complete) -{ - struct - { - uint16 LSC:1; // Load split completed, excluding UC/WC loads }, - uint16 SSC:1; //Any split stores completed } } - }; - uint16 flat; -} EVENT_MASK(memory_complete); - -typedef union EVENT_MASK(load_port_replay) -{ - struct - { - uint16 dummy:1; - uint16 SPLIT_LD:1; //Split load } } - }; - uint16 flat; -} EVENT_MASK(load_port_replay); - -typedef union EVENT_MASK(store_port_replay) -{ - struct - { - uint16 dummy0:1; - uint16 SPLIT_ST:1; //Split store } } - - }; - uint16 flat; -} EVENT_MASK(store_port_replay); - -typedef union EVENT_MASK(MOB_load_replay) -{ - struct - { - uint16 dummy0:1; - - uint16 NO_STA:1; //Replayed because of unknown store address }, - - uint16 dummy2:1; - - uint16 NO_STD:1; //Replayed because of unknown store data }, - uint16 PARTIAL_DATA:1; //Replayed because of partially overlapped data access between the load and store operations }, - uint16 UNALGN_ADDR:1; //Replayed because the lower 4 bits of the linear address do not match between the load and store operations } } - }; - uint16 flat; -}EVENT_MASK(MOB_load_replay); - -typedef union EVENT_MASK(page_walk_type) -{ - struct - { - uint16 DTMISS:1; // Page walk for a data TLB miss }, - uint16 ITMISS:1; // Page walk for an instruction TLB miss } } - }; - uint16 flat; -}EVENT_MASK(page_walk_type); - - -typedef union EVENT_MASK(BSQ_cache_reference) -{ - struct - { - uint16 RD_2ndL_HITS:1; // Read 2nd level cache hit Shared }, - uint16 RD_2ndL_HITE:1; // Read 2nd level cache hit Exclusive }, - uint16 RD_2ndL_HITM:1; // Read 2nd level cache hit Modified }, - uint16 RD_3rdL_HITS:1; // Read 3rd level cache hit Shared }, - uint16 RD_3rdL_HITE:1; // Read 3rd level cache hit Exclusive }, - uint16 RD_3rdL_HITM:1; // Read 3rd level cache hit Modified }, - uint16 dummy6:1; - uint16 dummy7:1; - uint16 RD_2ndL_MISS:1; // Read 2nd level cache miss }, - uint16 RD_3rdL_MISS:1; // Read 3rd level cache miss }, - uint16 WR_2ndL_MISS:1; // Writeback lookup from DAC misses the 2nd level cache } } - }; - uint16 flat; -} EVENT_MASK(BSQ_cache_reference) ; - -typedef union EVENT_MASK(IOQ) -{ - struct - { - uint16 bit0:1; // bus request type (use 00001 for invalid or default) - uint16 bit1:1; // - uint16 bit2:1; // - uint16 bit3:1; // - uint16 bit4:1; // - uint16 ALL_READ:1; // Count read entries }, - uint16 ALL_WRITE:1; // Count write entries }, - uint16 MEM_UC:1; // Count UC memory access entries }, - uint16 MEM_WC:1; // Count WC memory access entries }, - uint16 MEM_WT:1; // Count WT memory access entries }, - uint16 MEM_WP:1; // Count WP memory access entries }, - uint16 MEM_WB:1; // Count WB memory access entries }, - uint16 dummy12:1; - - uint16 OWN:1; // Count own store requests }, - uint16 OTHER:1; // Count other and DMA store requests }, - uint16 PREFETCH:1; // Include HW and SW prefetch requests } } - }; - uint16 flat; -} EVENT_MASK(IOQ) ; - -typedef union EVENT_MASK(FSB_data_activity) -{ - struct - { - /* DRDY_OWN is mutually exclusive with DRDY_OTHER */ - /* DBSY_OWN is mutually exclusive with DBSY_OTHER */ - uint16 DRDY_DRV:1; // Count when this processor drives data onto the bus }, - uint16 DRDY_OWN:1; // Count when this processor reads data from the bus }, - uint16 DRDY_OTHER:1; // Count when data is on the bus but not being sampled by the processor }, - uint16 DBSY_DRV:1; // Count when this processor reserves the bus for driving data }, - uint16 DBSY_OWN:1; // Count when this processor reserves the bus for sampling data }, - uint16 DBSY_OTHER:1; // Count when the bus is reserved for driving data this processor will not sample } } - }; - uint16 flat; -}EVENT_MASK(FSB_data_activity); - -typedef union EVENT_MASK(BSQ) -{ - struct - { - uint16 REQ_TYPE0:1; // Request type encoding bit 0 }, - uint16 REQ_TYPE1:1; // Request type encoding bit 1 }, - uint16 REQ_LEN0:1; // Request length encoding bit 0 }, - uint16 REQ_LEN1:1; // Request length encoding bit 1 }, - uint16 dummy4: 1; - uint16 REQ_IO_TYPE:1; // Request type is input or output }, - uint16 REQ_LOCK_TYPE:1; // Request type is bus lock }, - uint16 REQ_CACHE_TYPE:1; // Request type is cacheable }, - uint16 REQ_SPLIT_TYPE:1; // Request type is a bus 8-byte chunk split across 8-byte boundary }, - uint16 REQ_DEM_TYPE:1; // Request type is a demand (1) or prefetch (0) }, - uint16 REQ_ORD_TYPE:1; // Request is an ordered type }, - uint16 MEM_TYPE0:1; // Memory type encoding bit 0 }, - uint16 MEM_TYPE1:1; // Memory type encoding bit 1 }, - uint16 MEM_TYPE2:1; // Memory type encoding bit 2 } } - }; - uint16 flat; -} EVENT_MASK(BSQ); - -typedef union EVENT_MASK(firm_uop) -{ - struct - { - uint16 dummy15 : 15; - uint16 ALL:1; // count all uops of this type } } - }; - uint16 flat; -} EVENT_MASK(firm_uop); - - - -typedef union EVENT_MASK(TC_misc) -{ - struct - { - uint16 dymmy4 : 4; - uint16 FLUSH:1; // Number of flushes } } - }; - uint16 flat; -} EVENT_MASK(TC_misc); - -typedef union EVENT_MASK(global_power_events) -{ - struct - { - uint16 Running:1; // The processor is active } } - }; - uint16 flat; -} EVENT_MASK(global_power_events); - -typedef union EVENT_MASK(tc_ms_xfer) -{ - struct - { - uint16 CISC:1; // A TC to MS transfer ocurred } } - }; - uint16 flat; -}EVENT_MASK(tc_ms_xfer); - - - -typedef union EVENT_MASK(uop_queue_writes) -{ - struct - { - uint16 FROM_TC_BUILD:1; // uops written from TC build mode - uint16 FROM_TC_DELIVER:1; // uops written from TC deliver mode - uint16 FROM_ROM:1; // uops written from microcode ROM } } - }; - uint16 flat; -} EVENT_MASK(uop_queue_writes); - -typedef union EVENT_MASK(branch_type) -{ - struct - { - uint16 dummy : 1; - uint16 CONDITIONAL:1; // Conditional jumps - uint16 CALL:1; // Direct or indirect call - uint16 RETURN:1; // Return branches - uint16 INDIRECT:1; // Returns, indirect calls, or indirect jumps - }; - uint16 flat; -} EVENT_MASK(branch_type); - - - -typedef union EVENT_MASK(resource_stall) -{ - struct - { - uint16 dummy1 : 5; - uint16 SBFULL:1; // A Stall due to lack of store buffers } } - }; - uint16 flat; -} EVENT_MASK(resource_stall); - - - - -typedef union EVENT_MASK(WC_Buffer) -{ - struct - { - uint16 WCB_EVICTS : 1; // all causes }, - uint16 WCB_FULL_EVICT : 1; // no WC buffer is available }, - /* XXX: 245472-011 no longer lists bit 2, but that looks like - a table formatting error. Keeping it for now. */ - uint16 WCB_HITM_EVICT : 1; // store encountered a Hit Modified condition } } - }; - uint16 flat; -} EVENT_MASK(WC_Buffer); - - -typedef union EVENT_MASK(b2b_cycles) -{ - struct - { - uint16 dummy0 : 1; - uint16 bit1 : 1; // - uint16 bit2 : 1; // - uint16 bit3 : 1; // - uint16 bit4 : 1; // - uint16 bit5 : 1; // - uint16 bit6 : 1; // - - }; - uint16 flat; -} EVENT_MASK(b2b_cycles); - -typedef union EVENT_MASK(bnr) -{ - struct - { - uint16 bit0:1; // - uint16 bit1:1; // - uint16 bit2:1; // - }; - uint16 flat; -} EVENT_MASK(bnr); - - -typedef union EVENT_MASK(snoop) -{ - struct - { - uint16 dummy0 : 1; - uint16 dummy1 : 1; - - uint16 bit2:1; // - uint16 dummy3:1; // - uint16 dummy4:1; // - uint16 dummy5:1; // - uint16 bit6:1; // - uint16 bit7:1; // - }; - uint16 flat; -} EVENT_MASK(snoop); - - -typedef union EVENT_MASK(response) -{ - struct - { - uint16 dummy0:1; // - uint16 bit1:1; // - uint16 bit2:1; // - uint16 dummy3:1; // - uint16 dummy4:1; // - uint16 dummy5:1; // - uint16 dummy6:1; // - uint16 dummy7:1; // - uint16 bit8:1; // - uint16 bit9:1; // - }; - uint16 flat; -} EVENT_MASK(response); - - -typedef union EVENT_MASK(nbogus_bogus) -{ - struct - { - uint16 NBOGUS:1; // The marked uops are not bogus - uint16 BOGUS:1; // The marked uops are bogus - }; - uint16 flat; -} EVENT_MASK(nbogus_bogus); - - -typedef union EVENT_MASK(execution_event) -{ - struct - { - uint16 NBOGUS0:1; // non-bogus uops with tag bit 0 set }, - uint16 NBOGUS1:1; // non-bogus uops with tag bit 1 set }, - uint16 NBOGUS2:1; // non-bogus uops with tag bit 2 set }, - uint16 NBOGUS3:1; // non-bogus uops with tag bit 3 set }, - uint16 BOGUS0:1; // bogus uops with tag bit 0 set }, - uint16 BOGUS1:1; // bogus uops with tag bit 1 set }, - uint16 BOGUS2:1; // bogus uops with tag bit 2 set }, - uint16 BOGUS3:1; // bogus uops with tag bit 3 set } } - }; - uint16 flat; -}EVENT_MASK(execution_event); - -typedef union EVENT_MASK(instr_retired) -{ - struct - { - uint16 NBOGUSNTAG:1; // Non-bogus instructions that are not tagged }, - uint16 NBOGUSTAG:1; // Non-bogus instructions that are tagged }, - uint16 BOGUSNTAG:1; // Bogus instructions that are not tagged }, - uint16 BOGUSTAG:1; // Bogus instructions that are tagged } } - }; - uint16 flat; -} EVENT_MASK(instr_retired); - - -typedef union EVENT_MASK(uop_type) -{ - struct - { - uint16 dummy0 : 1; - uint16 TAGLOADS:1; // The uop is a load operation }, - uint16 TAGSTORES:1; // The uop is a store operation } } - }; - uint16 flat; -} EVENT_MASK(uop_type); - -typedef union EVENT_MASK(branch_retired) -{ - struct - { - uint16 MMNP:1; // Branch Not-taken Predicted - uint16 MMNM:1; // Branch Not-taken Mispredicted - uint16 MMTP:1; // Branch Taken Predicted - uint16 MMTM:1; // Branch Taken Mispredicted - }; - uint16 flat; -} EVENT_MASK(branch_retired); - -typedef union EVENT_MASK(mispred_branch_retired) -{ - struct - { - uint16 NBOGUS:1; // The retired branch is not bogus } } - }; - uint16 flat; -} EVENT_MASK(mispred_branch_retired); - - -typedef union EVENT_MASK(x87_assist) -{ - struct - { - uint16 FPSU:1; // FP stack underflow }, - uint16 FPSO:1; // FP stack overflow }, - uint16 POAO:1; // x87 output overflow }, - uint16 POAU:1; // x87 output underflow }, - uint16 PREA:1; // x87 input assist } } - }; - uint16 flat; -}EVENT_MASK(x87_assist); - -typedef union EVENT_MASK(machine_clear) -{ - struct - { - uint16 CLEAR:1; // Count a portion of the cycles when the machine is cleared }, - uint16 dummy1: 1; - uint16 MOCLEAR:1; // Count clears due to memory ordering issues }, - uint16 dummy3: 1; - uint16 dummy4: 1; - uint16 dummy5: 1; - - uint16 SMCLEAR:1;// Count clears due to self-modifying code issues } } - }; - uint16 flat; -} EVENT_MASK(machine_clear); - - -typedef union EVENT_MASK(x87_SIMD_moves_uop) -{ - struct - { - uint16 dummy3:3; - uint16 ALLP0:1; // Count all x87/SIMD store/move uops }, - uint16 ALLP2:1; // count all x87/SIMD load uops } } - }; - uint16 flat; -} EVENT_MASK(x87_SIMD_moves_uop); - - - - - - - diff --git a/public/tier0/EventModes.h b/public/tier0/EventModes.h deleted file mode 100644 index 05e5b21e0..000000000 --- a/public/tier0/EventModes.h +++ /dev/null @@ -1,1787 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef EVENTMODES_H -#define EVENTMODES_H - - -#pragma once - -/* - - - - Event Modes to choose from: - - P4Event_TC_deliver_mode - - P4Event_BPU_fetch_request - - P4Event_ITLB_reference - - P4Event_memory_cancel - - P4Event_memory_complete - - P4Event_load_port_replay - - P4Event_store_port_replay - - P4Event_MOB_load_replay - - P4Event_page_walk_type - - P4Event_BSQ_cache_reference - - P4Event_IOQ_allocation - - P4Event_IOQ_active_entries - - P4Event_FSB_data_activity - - P4Event_BSQ_allocation - - P4Event_BSQ_active_entries - - P4Event_SSE_input_assist - - P4Event_packed_SP_uop - - P4Event_packed_DP_uop - - P4Event_scalar_SP_uop - - P4Event_scalar_DP_uop - - P4Event_64bit_MMX_uop - - P4Event_128bit_MMX_uop - - P4Event_x87_FP_uop - - P4Event_x87_SIMD_moves_uop - - P4Event_TC_misc - - P4Event_global_power_events - - P4Event_tc_ms_xfer - - P4Event_uop_queue_writes - - P4Event_retired_mispred_branch_type - - P4Event_retired_branch_type - - P4Event_resource_stall - - P4Event_WC_Buffer - - P4Event_b2b_cycles - - P4Event_bnr - - P4Event_snoop - - P4Event_response - - P4Event_front_end_event - - P4Event_execution_event - - P4Event_replay_event - - P4Event_instr_retired - - P4Event_uops_retired - - P4Event_uop_type - - P4Event_branch_retired - - P4Event_mispred_branch_retired - - P4Event_x87_assist - - P4Event_machine_clear - - -*/ - - - -class P4P4Event_TC_deliver_mode: public P4BaseEvent -{ -public: - EVENT_MASK(TC_deliver_mode) * eventMask; - - P4P4Event_TC_deliver_mode() - { - eventMask = (EVENT_MASK(TC_deliver_mode) *)&m_eventMask; - - escr.ESCREventSelect = 0x01; - cccr.CCCRSelect = 0x01; - //// eventType = EVENT_TYPE(TC_deliver_mode); - description = _T("TC_deliver_mode"); - UseCounter4(); - } - - - void UseCounter4() - { - SetCounter(4);; - } - void UseCounter5() - { - SetCounter(5); - } - void UseCounter6() - { - SetCounter(6); - } - void UseCounter7() - { - SetCounter(7); - } -}; - -class P4P4Event_BPU_fetch_request: public P4BaseEvent - -{ -public: - EVENT_MASK(BPU_fetch_request)* eventMask; - - P4P4Event_BPU_fetch_request() - { - eventMask = (EVENT_MASK(BPU_fetch_request) *)&m_eventMask; - - escr.ESCREventSelect= 0x03; - cccr.CCCRSelect= 0x00; - // eventType = EVENT_TYPE(BPU_fetch_request); - description=_T("BPU_fetch_request"); - UseCounter0(); - } - void UseCounter0() - { - SetCounter(0); - } - void UseCounter1() - { - SetCounter(1); - } - void UseCounter2() - { - SetCounter(2); - } - void UseCounter3() - { - SetCounter(3); - } - -}; -class P4P4Event_ITLB_reference: public P4BaseEvent - -{ -public: - EVENT_MASK(ITLB_reference) * eventMask; - - P4P4Event_ITLB_reference() - { - eventMask = (EVENT_MASK(ITLB_reference) *)&m_eventMask; - - escr.ESCREventSelect= 0x18; - cccr.CCCRSelect= 0x03; - // eventType=EVENT_TYPE(ITLB_reference); - description=_T("ITLB_reference"); - UseCounter0(); - } - void UseCounter0() - { - SetCounter(0); - } - void UseCounter1() - { - SetCounter(1); - } - void UseCounter2() - { - SetCounter(2); - } - void UseCounter3() - { - SetCounter(3); - } -}; -class P4Event_memory_cancel: public P4BaseEvent - -{ -public: - EVENT_MASK(memory_cancel) * eventMask; - - P4Event_memory_cancel() - { - eventMask = (EVENT_MASK(memory_cancel) *)&m_eventMask; - - escr.ESCREventSelect= 0x02; - cccr.CCCRSelect= 0x05; - // eventType=EVENT_TYPE(memory_cancel); - description=_T("memory_cancel"); - UseCounter8(); - } - - void UseCounter8() - { - SetCounter(8); - } - void UseCounter9() - { - SetCounter(9); - } - void UseCounter10() - { - SetCounter(10); - } - void UseCounter11() - { - SetCounter(11); - } - -}; -class P4Event_memory_complete: public P4BaseEvent - -{ -public: - EVENT_MASK(memory_complete) * eventMask; - - P4Event_memory_complete() - { - eventMask = (EVENT_MASK(memory_complete) *)&m_eventMask; - - escr.ESCREventSelect= 0x08; - cccr.CCCRSelect= 0x02; - // eventType=EVENT_TYPE(memory_complete); - description=_T("memory_complete"); - UseCounter8(); - } - void UseCounter8() - { - SetCounter(8); - } - void UseCounter9() - { - SetCounter(9); - } - void UseCounter10() - { - SetCounter(10); - } - void UseCounter11() - { - SetCounter(11); - } - -}; -class P4Event_load_port_replay: public P4BaseEvent - -{ -public: - EVENT_MASK(load_port_replay) * eventMask; - - P4Event_load_port_replay() - { - eventMask = (EVENT_MASK(load_port_replay) *)&m_eventMask; - - escr.ESCREventSelect= 0x04; - cccr.CCCRSelect= 0x02; - // eventType=EVENT_TYPE(load_port_replay); - description=_T("load_port_replay"); - UseCounter8(); - } - void UseCounter8() - { - SetCounter(8); - } - void UseCounter9() - { - SetCounter(9); - } - void UseCounter10() - { - SetCounter(10); - } - void UseCounter11() - { - SetCounter(11); - } - -}; -class P4Event_store_port_replay: public P4BaseEvent - -{ -public: - EVENT_MASK(store_port_replay) * eventMask; - - P4Event_store_port_replay() - { - eventMask = (EVENT_MASK(store_port_replay) *)&m_eventMask; - - escr.ESCREventSelect= 0x05; - cccr.CCCRSelect= 0x02; - // eventType=EVENT_TYPE(store_port_replay); - description=_T("store_port_replay"); - UseCounter8(); - } - void UseCounter8() - { - SetCounter(8); - } - void UseCounter9() - { - SetCounter(9); - } - void UseCounter10() - { - SetCounter(10); - } - void UseCounter11() - { - SetCounter(11); - } - -}; -class P4Event_MOB_load_replay: public P4BaseEvent - -{ -public: - EVENT_MASK(MOB_load_replay) * eventMask; - - P4Event_MOB_load_replay() - { - eventMask = (EVENT_MASK(MOB_load_replay) *)&m_eventMask; - - escr.ESCREventSelect= 0x03; - cccr.CCCRSelect= 0x02; - // eventType=EVENT_TYPE(MOB_load_replay); - description=_T("MOB_load_replay"); - UseCounter0(); - } - void UseCounter0() - { - SetCounter(0); - } - void UseCounter1() - { - SetCounter(1); - } - void UseCounter2() - { - SetCounter(2); - } - void UseCounter3() - { - SetCounter(3); - } -}; -class P4Event_page_walk_type: public P4BaseEvent - -{ -public: - EVENT_MASK(page_walk_type) * eventMask; - - P4Event_page_walk_type() - { - eventMask = (EVENT_MASK(page_walk_type) *)&m_eventMask; - - escr.ESCREventSelect= 0x01; - cccr.CCCRSelect= 0x04; - // eventType=EVENT_TYPE(page_walk_type); - description=_T("page_walk_type"); - UseCounter0(); - } - void UseCounter0() - { - SetCounter(0); - } - void UseCounter1() - { - SetCounter(1); - } - void UseCounter2() - { - SetCounter(2); - } - void UseCounter3() - { - SetCounter(3); - } -}; -class P4Event_BSQ_cache_reference: public P4BaseEvent - -{ -public: - EVENT_MASK(BSQ_cache_reference) * eventMask; - - P4Event_BSQ_cache_reference() - { - eventMask = (EVENT_MASK(BSQ_cache_reference) *)&m_eventMask; - - escr.ESCREventSelect= 0x0C; - cccr.CCCRSelect= 0x07; - // eventType=EVENT_TYPE(BSQ_cache_reference); - description=_T("BSQ_cache_reference"); - UseCounter0(); - } - void UseCounter0() - { - SetCounter(0); - } - void UseCounter1() - { - SetCounter(1); - } - void UseCounter2() - { - SetCounter(2); - } - void UseCounter3() - { - SetCounter(3); - } -}; -class P4Event_IOQ_allocation: public P4BaseEvent - -{ -public: - EVENT_MASK(IOQ) * eventMask; - - P4Event_IOQ_allocation() - { - eventMask = (EVENT_MASK(IOQ) *)&m_eventMask; - - escr.ESCREventSelect= 0x03; - cccr.CCCRSelect= 0x06; - // eventType=EVENT_TYPE(IOQ); - description=_T("IOQ_allocation"); - UseCounter0(); - } - void UseCounter0() - { - SetCounter(0); - } - void UseCounter1() - { - SetCounter(1); - } - void UseCounter2() - { - SetCounter(2); - } - void UseCounter3() - { - SetCounter(3); - } -}; -class P4Event_IOQ_active_entries: public P4BaseEvent - -{ -public: - EVENT_MASK(IOQ) * eventMask; - - P4Event_IOQ_active_entries() - { - eventMask = (EVENT_MASK(IOQ) *)&m_eventMask; - - escr.ESCREventSelect= 0x1A; - cccr.CCCRSelect= 0x06; - // eventType=EVENT_TYPE(IOQ); - description=_T("IOQ_active_entries"); - UseCounter2(); - } - void UseCounter2() - { - SetCounter(2); - } - void UseCounter3() - { - SetCounter(3); - } -}; -class P4Event_FSB_data_activity: public P4BaseEvent - -{ -public: - EVENT_MASK(FSB_data_activity) * eventMask; - - P4Event_FSB_data_activity() - { - eventMask = (EVENT_MASK(FSB_data_activity) *)&m_eventMask; - - escr.ESCREventSelect= 0x17; - cccr.CCCRSelect= 0x06; - // eventType=EVENT_TYPE(FSB_data_activity); - description=_T("FSB_data_activity"); - UseCounter0(); - } - void UseCounter0() - { - SetCounter(0); - } - void UseCounter1() - { - SetCounter(1); - } - void UseCounter2() - { - SetCounter(2); - } - void UseCounter3() - { - SetCounter(3); - } -}; -class P4Event_BSQ_allocation: public P4BaseEvent - -{ -public: - EVENT_MASK(BSQ) * eventMask; - - P4Event_BSQ_allocation() - { - eventMask = (EVENT_MASK(BSQ) *)&m_eventMask; - - escr.ESCREventSelect= 0x05; - cccr.CCCRSelect= 0x07; - // eventType=EVENT_TYPE(BSQ); - description=_T("BSQ_allocation"); - UseCounter0(); - } - - void UseCounter0() - { - SetCounter(0); - } - void UseCounter1() - { - SetCounter(1); - - } -}; -class P4Event_BSQ_active_entries: public P4BaseEvent - -{ -public: - EVENT_MASK(BSQ) * eventMask; - - P4Event_BSQ_active_entries() - { - eventMask = (EVENT_MASK(BSQ) *)&m_eventMask; - - escr.ESCREventSelect= 0x06; - cccr.CCCRSelect= 0x07; - // eventType=EVENT_TYPE(BSQ); - description=_T("bsq_active_entries"); - UseCounter2(); - } - void UseCounter2() - { - SetCounter(2); - } - void UseCounter3() - { - SetCounter(3); - } -}; -class P4Event_SSE_input_assist: public P4BaseEvent - -{ -public: - EVENT_MASK(firm_uop) * eventMask; - - P4Event_SSE_input_assist() - { - eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask; - - escr.ESCREventSelect= 0x34; - cccr.CCCRSelect= 0x01; - // eventType=EVENT_TYPE(firm_uop); - description=_T("SSE_input_assist"); - UseCounter8(); - } - void UseCounter8() - { - SetCounter(8); - } - void UseCounter9() - { - SetCounter(9); - } - void UseCounter10() - { - SetCounter(10); - } - void UseCounter11() - { - SetCounter(11); - } - -}; -class P4Event_packed_SP_uop: public P4BaseEvent - -{ -public: - EVENT_MASK(firm_uop) * eventMask; - - P4Event_packed_SP_uop() - { - eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask; - - escr.ESCREventSelect= 0x08; - cccr.CCCRSelect= 0x01; - // eventType=EVENT_TYPE(firm_uop); - description=_T("packed_SP_uop"); - UseCounter8(); - } - void UseCounter8() - { - SetCounter(8); - } - void UseCounter9() - { - SetCounter(9); - } - void UseCounter10() - { - SetCounter(10); - } - void UseCounter11() - { - SetCounter(11); - } - -}; -class P4Event_packed_DP_uop: public P4BaseEvent - -{ -public: - EVENT_MASK(firm_uop) * eventMask; - - P4Event_packed_DP_uop() - { - eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask; - - escr.ESCREventSelect= 0x0C; - cccr.CCCRSelect= 0x01; - // eventType=EVENT_TYPE(firm_uop); - description=_T("packed_DP_uop"); - UseCounter8(); - } - void UseCounter8() - { - SetCounter(8); - } - void UseCounter9() - { - SetCounter(9); - } - void UseCounter10() - { - SetCounter(10); - } - void UseCounter11() - { - SetCounter(11); - } - -}; -class P4Event_scalar_SP_uop: public P4BaseEvent - -{ -public: - EVENT_MASK(firm_uop) * eventMask; - - P4Event_scalar_SP_uop() - { - eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask; - - escr.ESCREventSelect= 0x0A; - cccr.CCCRSelect= 0x01; - // eventType=EVENT_TYPE(firm_uop); - description=_T("scalar_SP_uop"); - UseCounter8(); - } - void UseCounter8() - { - SetCounter(8); - } - void UseCounter9() - { - SetCounter(9); - } - void UseCounter10() - { - SetCounter(10); - } - void UseCounter11() - { - SetCounter(11); - } - -}; -class P4Event_scalar_DP_uop: public P4BaseEvent - -{ -public: - EVENT_MASK(firm_uop) * eventMask; - - P4Event_scalar_DP_uop() - { - eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask; - - escr.ESCREventSelect= 0x0E; - cccr.CCCRSelect= 0x01; - // eventType=EVENT_TYPE(firm_uop); - description=_T("scalar_DP_uop"); - UseCounter8(); - } - void UseCounter8() - { - SetCounter(8); - } - void UseCounter9() - { - SetCounter(9); - } - void UseCounter10() - { - SetCounter(10); - } - void UseCounter11() - { - SetCounter(11); - } - -}; -class P4Event_64bit_MMX_uop: public P4BaseEvent - -{ -public: - EVENT_MASK(firm_uop) * eventMask; - - P4Event_64bit_MMX_uop() - { - eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask; - - escr.ESCREventSelect= 0x02; - cccr.CCCRSelect= 0x01; - // eventType=EVENT_TYPE(firm_uop); - description=_T("64bit_MMX_uop"); - UseCounter8(); - } - void UseCounter8() - { - SetCounter(8); - } - void UseCounter9() - { - SetCounter(9); - } - void UseCounter10() - { - SetCounter(10); - } - void UseCounter11() - { - SetCounter(11); - } - -}; -class P4Event_128bit_MMX_uop: public P4BaseEvent - -{ -public: - EVENT_MASK(firm_uop) * eventMask; - - P4Event_128bit_MMX_uop() - { - eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask; - - escr.ESCREventSelect= 0x1A; - cccr.CCCRSelect= 0x01; - // eventType=EVENT_TYPE(firm_uop); - description=_T("128bit_MMX_uop"); - UseCounter8(); - } - void UseCounter8() - { - SetCounter(8); - } - void UseCounter9() - { - SetCounter(9); - } - void UseCounter10() - { - SetCounter(10); - } - void UseCounter11() - { - SetCounter(11); - } - -}; -class P4Event_x87_FP_uop: public P4BaseEvent - -{ -public: - EVENT_MASK(firm_uop) * eventMask; - - P4Event_x87_FP_uop() - { - eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask; - - escr.ESCREventSelect= 0x04; - cccr.CCCRSelect= 0x01; - // eventType=EVENT_TYPE(firm_uop); - description=_T("x87_FP_uop"); - UseCounter8(); - } - void UseCounter8() - { - SetCounter(8); - } - void UseCounter9() - { - SetCounter(9); - } - void UseCounter10() - { - SetCounter(10); - } - void UseCounter11() - { - SetCounter(11); - } - -}; -class P4Event_x87_SIMD_moves_uop: public P4BaseEvent - -{ -public: - EVENT_MASK(x87_SIMD_moves_uop) * eventMask; - - P4Event_x87_SIMD_moves_uop() - { - eventMask = (EVENT_MASK(x87_SIMD_moves_uop) *)&m_eventMask; - - escr.ESCREventSelect= 0x2E; - cccr.CCCRSelect= 0; - // eventType=EVENT_TYPE(x87_SIMD_moves_uop); - description=_T("x87_SIMD_moves_uop"); - UseCounter8(); - } - void UseCounter8() - { - SetCounter(8); - } - void UseCounter9() - { - SetCounter(9); - } - void UseCounter10() - { - SetCounter(10); - } - void UseCounter11() - { - SetCounter(11); - } - -}; -class P4Event_TC_misc: public P4BaseEvent - -{ -public: - EVENT_MASK(TC_misc) * eventMask; - - P4Event_TC_misc() - { - eventMask = (EVENT_MASK(TC_misc) *)&m_eventMask; - - escr.ESCREventSelect= 0x06; - cccr.CCCRSelect= 0x01; - // eventType=EVENT_TYPE(TC_misc); - description=_T("TC_misc"); - UseCounter4(); - } - - void UseCounter4() - { - SetCounter(4);; - } - void UseCounter5() - { - SetCounter(5); - } - void UseCounter6() - { - SetCounter(6); - } - void UseCounter7() - { - SetCounter(7); - } -}; -class P4Event_global_power_events: public P4BaseEvent - -{ -public: - EVENT_MASK(global_power_events) * eventMask; - - P4Event_global_power_events() - { - eventMask = (EVENT_MASK(global_power_events) *)&m_eventMask; - - escr.ESCREventSelect= 0x13; - cccr.CCCRSelect= 0x06; - // eventType=EVENT_TYPE(global_power_events); - description=_T("global_power_events"); - UseCounter0(); - } - - void UseCounter0() - { - SetCounter(0); - } - void UseCounter1() - { - SetCounter(1); - } - void UseCounter2() - { - SetCounter(2); - } - void UseCounter3() - { - SetCounter(3); - } -}; -class P4Event_tc_ms_xfer: public P4BaseEvent - -{ -public: - EVENT_MASK(tc_ms_xfer) * eventMask; - - P4Event_tc_ms_xfer() - { - eventMask = (EVENT_MASK(tc_ms_xfer) *)&m_eventMask; - - escr.ESCREventSelect= 0x05; - cccr.CCCRSelect= 0x00; - // eventType=EVENT_TYPE(tc_ms_xfer); - description=_T("tc_ms_xfer"); - UseCounter4(); - } - - void UseCounter4() - { - SetCounter(4);; - } - void UseCounter5() - { - SetCounter(5); - } - void UseCounter6() - { - SetCounter(6); - } - void UseCounter7() - { - SetCounter(7); - } -}; -class P4Event_uop_queue_writes: public P4BaseEvent - -{ -public: - EVENT_MASK(uop_queue_writes) * eventMask; - - P4Event_uop_queue_writes() - { - eventMask = (EVENT_MASK(uop_queue_writes) *)&m_eventMask; - - escr.ESCREventSelect= 0x09; - cccr.CCCRSelect= 0x00; - // eventType=EVENT_TYPE(uop_queue_writes); - description=_T("uop_queue_writes"); - UseCounter4(); - } - - void UseCounter4() - { - SetCounter(4);; - } - void UseCounter5() - { - SetCounter(5); - } - void UseCounter6() - { - SetCounter(6); - } - void UseCounter7() - { - SetCounter(7); - } -}; -class P4Event_retired_mispred_branch_type: public P4BaseEvent - -{ -public: - EVENT_MASK(branch_type) * eventMask; - - P4Event_retired_mispred_branch_type() - { - eventMask = (EVENT_MASK(branch_type) *)&m_eventMask; - - escr.ESCREventSelect= 0x05; - cccr.CCCRSelect= 0x02; - // eventType=EVENT_TYPE(branch_type); - description=_T("retired_mispred_branch_type"); - UseCounter4(); - } - - void UseCounter4() - { - SetCounter(4);; - } - void UseCounter5() - { - SetCounter(5); - } - void UseCounter6() - { - SetCounter(6); - } - void UseCounter7() - { - SetCounter(7); - } -}; -class P4Event_retired_branch_type: public P4BaseEvent - -{ -public: - EVENT_MASK(branch_type) * eventMask; - - P4Event_retired_branch_type() - { - eventMask = (EVENT_MASK(branch_type) *)&m_eventMask; - - escr.ESCREventSelect= 0x04; - cccr.CCCRSelect= 0x04; - // eventType=EVENT_TYPE(branch_type); - description=_T("retired_branch_type"); - UseCounter4(); - } - - void UseCounter4() - { - SetCounter(4);; - } - void UseCounter5() - { - SetCounter(5); - } - void UseCounter6() - { - SetCounter(6); - } - void UseCounter7() - { - SetCounter(7); - } -}; -class P4Event_resource_stall: public P4BaseEvent - -{ -public: - EVENT_MASK(resource_stall) * eventMask; - - P4Event_resource_stall() - { - eventMask = (EVENT_MASK(resource_stall) *)&m_eventMask; - - escr.ESCREventSelect= 0x01; - cccr.CCCRSelect= 0x02; - // eventType=EVENT_TYPE(resource_stall); - description=_T("resource_stall"); - UseCounter12(); - } - void UseCounter12() - { - SetCounter(12); - } - void UseCounter13() - { - SetCounter(13); - - } - - void UseCounter14() - { - SetCounter(14); - } - void UseCounter15() - { - SetCounter(15); - - } - - void UseCounter16() - { - SetCounter(16); - } - void UseCounter17() - { - SetCounter(17); - - } - -}; -class P4Event_WC_Buffer: public P4BaseEvent - -{ -public: - EVENT_MASK(WC_Buffer) * eventMask; - - P4Event_WC_Buffer() - { - eventMask = (EVENT_MASK(WC_Buffer) *)&m_eventMask; - - escr.ESCREventSelect= 0x05; - cccr.CCCRSelect= 0x05; - // eventType=EVENT_TYPE(WC_Buffer); - description=_T("WC_Buffer"); - UseCounter8(); - } - void UseCounter8() - { - SetCounter(8); - } - void UseCounter9() - { - SetCounter(9); - } - void UseCounter10() - { - SetCounter(10); - } - void UseCounter11() - { - SetCounter(11); - } - -}; -class P4Event_b2b_cycles: public P4BaseEvent - -{ -public: - EVENT_MASK(b2b_cycles) * eventMask; - - P4Event_b2b_cycles() - { - eventMask = (EVENT_MASK(b2b_cycles) *)&m_eventMask; - - escr.ESCREventSelect= 0x16; - cccr.CCCRSelect= 0x03; - // eventType=EVENT_TYPE(b2b_cycles); - description=_T("b2b_cycles"); - UseCounter0(); - } - void UseCounter0() - { - SetCounter(0); - } - void UseCounter1() - { - SetCounter(1); - } - void UseCounter2() - { - SetCounter(2); - } - void UseCounter3() - { - SetCounter(3); - } -}; -class P4Event_bnr: public P4BaseEvent - -{ -public: - EVENT_MASK(bnr) * eventMask; - - P4Event_bnr() - { - eventMask = (EVENT_MASK(bnr) *)&m_eventMask; - - escr.ESCREventSelect= 0x08; - cccr.CCCRSelect= 0x03; - // eventType=EVENT_TYPE(bnr); - description=_T("bnr"); - UseCounter0(); - } - void UseCounter0() - { - SetCounter(0); - } - void UseCounter1() - { - SetCounter(1); - } - void UseCounter2() - { - SetCounter(2); - } - void UseCounter3() - { - SetCounter(3); - } -}; -class P4Event_snoop: public P4BaseEvent - -{ -public: - EVENT_MASK(snoop) * eventMask; - - P4Event_snoop() - { - eventMask = (EVENT_MASK(snoop) *)&m_eventMask; - - escr.ESCREventSelect= 0x06; - cccr.CCCRSelect= 0x03; - // eventType=EVENT_TYPE(snoop); - description=_T("snoop"); - UseCounter0(); - } - void UseCounter0() - { - SetCounter(0); - } - void UseCounter1() - { - SetCounter(1); - } - void UseCounter2() - { - SetCounter(2); - } - void UseCounter3() - { - SetCounter(3); - } -}; -class P4Event_response: public P4BaseEvent - -{ -public: - EVENT_MASK(response) * eventMask; - - P4Event_response() - { - eventMask = (EVENT_MASK(response) *)&m_eventMask; - - escr.ESCREventSelect= 0x04; - cccr.CCCRSelect= 0x03; - // eventType=EVENT_TYPE(response); - description=_T("response"); - UseCounter0(); - } - void UseCounter0() - { - SetCounter(0); - } - void UseCounter1() - { - SetCounter(1); - } - void UseCounter2() - { - SetCounter(2); - } - void UseCounter3() - { - SetCounter(3); - } -}; -class P4Event_front_end_event: public P4BaseEvent - -{ -public: - EVENT_MASK(nbogus_bogus) * eventMask; - - P4Event_front_end_event() - { - eventMask = (EVENT_MASK(nbogus_bogus) *)&m_eventMask; - - escr.ESCREventSelect= 0x08; - cccr.CCCRSelect= 0x05; - // eventType=EVENT_TYPE(nbogus_bogus); - description=_T("front_end_event"); - UseCounter12(); - } - - void UseCounter12() - { - SetCounter(12); - } - void UseCounter13() - { - SetCounter(13); - - } - - void UseCounter14() - { - SetCounter(14); - } - void UseCounter15() - { - SetCounter(15); - - } - - void UseCounter16() - { - SetCounter(16); - } - void UseCounter17() - { - SetCounter(17); - - } -}; -class P4Event_execution_event: public P4BaseEvent - -{ -public: - EVENT_MASK(execution_event) * eventMask; - - P4Event_execution_event() - { - eventMask = (EVENT_MASK(execution_event) *)&m_eventMask; - - escr.ESCREventSelect= 0x0C; - cccr.CCCRSelect= 0x05; - // eventType=EVENT_TYPE(execution_event); - description=_T("execution_event"); - UseCounter12(); - } - void UseCounter12() - { - SetCounter(12); - } - void UseCounter13() - { - SetCounter(13); - - } - - void UseCounter14() - { - SetCounter(14); - } - void UseCounter15() - { - SetCounter(15); - - } - - void UseCounter16() - { - SetCounter(16); - } - void UseCounter17() - { - SetCounter(17); - - } -}; -class P4Event_replay_event: public P4BaseEvent - -{ -public: - EVENT_MASK(nbogus_bogus) * eventMask; - - P4Event_replay_event() - { - eventMask = (EVENT_MASK(nbogus_bogus) *)&m_eventMask; - - escr.ESCREventSelect= 0x09; - cccr.CCCRSelect= 0x05; - // eventType=EVENT_TYPE(nbogus_bogus); - description=_T("replay_event"); - UseCounter12(); - } - void UseCounter12() - { - SetCounter(12); - } - void UseCounter13() - { - SetCounter(13); - - } - - void UseCounter14() - { - SetCounter(14); - } - void UseCounter15() - { - SetCounter(15); - - } - - void UseCounter16() - { - SetCounter(16); - } - void UseCounter17() - { - SetCounter(17); - - } -}; -class P4Event_instr_retired: public P4BaseEvent - -{ -public: - EVENT_MASK(instr_retired) * eventMask; - - P4Event_instr_retired() - { - eventMask = (EVENT_MASK(instr_retired) *)&m_eventMask; - - escr.ESCREventSelect= 0x02; - cccr.CCCRSelect= 0x04; - // eventType=EVENT_TYPE(instr_retired); - description=_T("instr_retired"); - UseCounter12(); - } - - void UseCounter12() - { - SetCounter(12); - } - void UseCounter13() - { - SetCounter(13); - - } - - void UseCounter14() - { - SetCounter(14); - } - void UseCounter15() - { - SetCounter(15); - - } - - void UseCounter16() - { - SetCounter(16); - } - void UseCounter17() - { - SetCounter(17); - - } -}; -class P4Event_uops_retired: public P4BaseEvent - -{ -public: - EVENT_MASK(nbogus_bogus) * eventMask; - - P4Event_uops_retired() - { - eventMask = (EVENT_MASK(nbogus_bogus) *)&m_eventMask; - - escr.ESCREventSelect= 0x01; - cccr.CCCRSelect= 0x04; - // eventType=EVENT_TYPE(nbogus_bogus); - description=_T("uops_retired"); - UseCounter12(); - } - void UseCounter12() - { - SetCounter(12); - } - void UseCounter13() - { - SetCounter(13); - - } - - void UseCounter14() - { - SetCounter(14); - } - void UseCounter15() - { - SetCounter(15); - - } - - void UseCounter16() - { - SetCounter(16); - } - void UseCounter17() - { - SetCounter(17); - - } -}; -class P4Event_uop_type: public P4BaseEvent - -{ -public: - EVENT_MASK(uop_type) * eventMask; - - P4Event_uop_type() - { - eventMask = (EVENT_MASK(uop_type) *)&m_eventMask; - - escr.ESCREventSelect= 0x02; - cccr.CCCRSelect= 0x02; - // eventType=EVENT_TYPE(uop_type); - description=_T("uop_type"); - UseCounter12(); - } - void UseCounter12() - { - SetCounter(12); - } - void UseCounter13() - { - SetCounter(13); - - } - - void UseCounter14() - { - SetCounter(14); - } - void UseCounter15() - { - SetCounter(15); - - } - - void UseCounter16() - { - SetCounter(16); - } - void UseCounter17() - { - SetCounter(17); - - } -}; -class P4Event_branch_retired: public P4BaseEvent - -{ -public: - EVENT_MASK(branch_retired) * eventMask; - - P4Event_branch_retired() - { - eventMask = (EVENT_MASK(branch_retired) *)&m_eventMask; - - escr.ESCREventSelect= 0x06; - cccr.CCCRSelect= 0x05; - // eventType=EVENT_TYPE(branch_retired); - description=_T("branch_retired"); - UseCounter12(); - } - void UseCounter12() - { - SetCounter(12); - } - void UseCounter13() - { - SetCounter(13); - - } - - void UseCounter14() - { - SetCounter(14); - } - void UseCounter15() - { - SetCounter(15); - - } - - void UseCounter16() - { - SetCounter(16); - } - void UseCounter17() - { - SetCounter(17); - - } -}; -class P4Event_mispred_branch_retired: public P4BaseEvent - -{ -public: - EVENT_MASK(mispred_branch_retired) * eventMask; - - P4Event_mispred_branch_retired() - { - eventMask = (EVENT_MASK(mispred_branch_retired) *)&m_eventMask; - - escr.ESCREventSelect= 0x03; - cccr.CCCRSelect= 0x04; - // eventType=EVENT_TYPE(mispred_branch_retired); - description=_T("mispred_branch_retired"); - UseCounter12(); - } - void UseCounter12() - { - SetCounter(12); - } - void UseCounter13() - { - SetCounter(13); - - } - - void UseCounter14() - { - SetCounter(14); - } - void UseCounter15() - { - SetCounter(15); - - } - - void UseCounter16() - { - SetCounter(16); - } - void UseCounter17() - { - SetCounter(17); - - } -}; -class P4Event_x87_assist: public P4BaseEvent - -{ -public: - EVENT_MASK(x87_assist) * eventMask; - - P4Event_x87_assist() - { - eventMask = (EVENT_MASK(x87_assist) *)&m_eventMask; - - escr.ESCREventSelect= 0x03; - cccr.CCCRSelect= 0x05; - // eventType=EVENT_TYPE(x87_assist); - description=_T("x87_assist"); - UseCounter12(); - } - void UseCounter12() - { - SetCounter(12); - } - void UseCounter13() - { - SetCounter(13); - - } - - void UseCounter14() - { - SetCounter(14); - } - void UseCounter15() - { - SetCounter(15); - - } - - void UseCounter16() - { - SetCounter(16); - } - void UseCounter17() - { - SetCounter(17); - - } -}; -class P4Event_machine_clear: public P4BaseEvent - -{ -public: - EVENT_MASK(machine_clear) * eventMask; - - P4Event_machine_clear() - { - eventMask = (EVENT_MASK(machine_clear) *)&m_eventMask; - escr.ESCREventSelect= 0x02; - cccr.CCCRSelect= 0x05; - // eventType=EVENT_TYPE(machine_clear); - description=_T("machine_clear"); - UseCounter12(); - } - - - - void UseCounter12() - { - SetCounter(12); - } - void UseCounter13() - { - SetCounter(13); - - } - - void UseCounter14() - { - SetCounter(14); - } - void UseCounter15() - { - SetCounter(15); - - } - - void UseCounter16() - { - SetCounter(16); - } - void UseCounter17() - { - SetCounter(17); - - } - -}; - -#endif // EVENTMODES_H diff --git a/public/tier0/IOCTLCodes.h b/public/tier0/IOCTLCodes.h deleted file mode 100644 index 7fc8efb0f..000000000 --- a/public/tier0/IOCTLCodes.h +++ /dev/null @@ -1,29 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef IOCTLCODES_H -#define IOCTLCODES_H -#pragma once - -// Define the IOCTL codes we will use. The IOCTL code contains a command -// identifier, plus other information about the device, the type of access -// with which the file must have been opened, and the type of buffering. - -// Device type -- in the "User Defined" range." -#define DEVICE_FILE_TYPE 40000 - - -// The IOCTL function codes from 0x800 to 0xFFF are for customer use. - -#define IOCTL_WRITE_MSR \ - CTL_CODE( DEVICE_FILE_TYPE, 0x900, METHOD_BUFFERED, FILE_READ_ACCESS ) - -#define IOCTL_READ_MSR \ - CTL_CODE( DEVICE_FILE_TYPE, 0x901, METHOD_BUFFERED, FILE_READ_ACCESS ) - - -#endif IOCTLCODES_H diff --git a/public/tier0/K8PerformanceCounters.h b/public/tier0/K8PerformanceCounters.h deleted file mode 100644 index d0f83a5d4..000000000 --- a/public/tier0/K8PerformanceCounters.h +++ /dev/null @@ -1,2028 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef K8PERFORMANCECOUNTERS_H -#define K8PERFORMANCECOUNTERS_H - -/* - * AMD K8 events. - * - */ - - - -typedef union EVENT_MASK(NULL_MASK) -{ - // no tests defined - uint16 flat; -} EVENT_MASK(NULL_MASK); - - -#define MSR_K8_EVNTSEL0 0xC0010000 /* .. 0xC0010003 */ -#define MSR_K8_PERFCTR0 0xC0010004 /* .. 0xC0010007 */ - -# pragma pack(push, 1) - - - -// access to these bits is through the methods -typedef union PerfEvtSel -{ - struct - { - uint64 EventMask : 8; - - uint64 UnitMask : 8; - uint64 USR : 1; - uint64 OS : 1; - uint64 Edge : 1; - uint64 PC : 1; - uint64 INTAPIC : 1; - uint64 Reserved21 : 1; - uint64 Enable : 1; - uint64 Complement : 1; // aka INV - uint64 Threshold : 8; // aka CounterMask - uint64 Reserver32 : 32; - }; - uint64 flat; - -} PerfEvtSel; - - -enum UnitEncode -{ - FP, - LS, - DC, - BU, - IC, - UE_Unknown, - FR, - NB -}; - -# pragma pack(pop) - -// Turn off the no return value warning in ReadCounter. -#pragma warning( disable : 4035 ) -#define k8NUM_COUNTERS 4 -class k8BaseEvent -{ -public: - - PME * pme; - - PerfEvtSel eventSelect[k8NUM_COUNTERS]; - - unsigned short m_eventMask; - int event_id; - tchar * name; - tchar revRequired; - int eventSelectNum; - UnitEncode unitEncode; - - - void SetCounter(int n) - { - if (n < 0) - n = 0; - else if (n > 3) - n = 3; - eventSelectNum = n; - - } - k8BaseEvent() - { - pme = PME::Instance(); - - for(int i = 0; i< k8NUM_COUNTERS; i++) - { - eventSelect[i].flat = 0; - - } - eventSelectNum = 0; - - m_eventMask = 0; - event_id = 0; - name = 0; - revRequired = 'A'; - - - } - - void SetCaptureMode(PrivilegeCapture priv) - { - PerfEvtSel & select = eventSelect[eventSelectNum]; - StopCounter(); - - switch (priv) - { - case OS_Only: - select.USR = 0; - select.OS = 1; - break; - - case USR_Only: - select.USR = 1; - select.OS = 0; - break; - - case OS_and_USR: - select.USR = 1; - select.OS = 1; - break; - } - - - select.UnitMask = m_eventMask; - select.EventMask = event_id; - - - int selectPort = MSR_K8_EVNTSEL0 + eventSelectNum; - pme->WriteMSR(selectPort, select.flat); - } - - - void SetFiltering(CompareState compareEnable, - CompareMethod compareMethod, - uint8 threshold, - EdgeState edgeEnable) - { - - PerfEvtSel & select = eventSelect[eventSelectNum]; - - StopCounter(); - - if (compareEnable == CompareDisable) - select.Threshold = 0; - else - select.Threshold = threshold; - - select.Complement = compareMethod; - - select.Edge = edgeEnable; - - int selectPort = MSR_K8_EVNTSEL0 + eventSelectNum; - pme->WriteMSR(selectPort, select.flat); - - - } - - - void StartCounter() - { - PerfEvtSel & select = eventSelect[eventSelectNum]; - - select.Enable = 1; - int selectPort = MSR_K8_EVNTSEL0 + eventSelectNum; - - pme->WriteMSR(selectPort, select.flat); - - } - void StopCounter() - { - PerfEvtSel & select = eventSelect[eventSelectNum]; - select.Enable = 0; - int selectPort = MSR_K8_EVNTSEL0 + eventSelectNum; - - pme->WriteMSR(selectPort, select.flat); - } - - - - void ClearCounter() - { - PerfEvtSel & select = eventSelect[eventSelectNum]; - - int counterPort = MSR_K8_PERFCTR0 + eventSelectNum; - - pme->WriteMSR(counterPort, 0ui64 ); // clear - } - - void WriteCounter(int64 value) - { - - PerfEvtSel & select = eventSelect[eventSelectNum]; - - int counterPort = MSR_K8_PERFCTR0 + eventSelectNum; - pme->WriteMSR(counterPort, value); // clear - } - - int64 ReadCounter() - { - -#if PME_DEBUG - PerfEvtSel & select = eventSelect[eventSelectNum]; - - if (select.USR == 0 && select.OS == 0) - return -1; // no area to collect, use SetCaptureMode - - if (select.EventMask == 0) - return -2; // no event mask set - - if (eventSelectNum < 0 || eventSelectNum > 3) - return -3; // counter not legal - - // check revision - -#endif - - // ReadMSR should work here too, but RDPMC should be faster - //ReadMSR(counterPort, int64); - - // we need to copy this into a temp for some reason - int temp = eventSelectNum; - _asm - { - mov ecx, temp - RDPMC - } - - } - - -}; -#pragma warning( default : 4035 ) - - - - -typedef union EVENT_MASK(k8_dispatched_fpu_ops) -{ - // event 0 - struct - { - uint16 AddPipeOps:1; // Add pipe ops excluding junk ops" }, - uint16 MulPipeOps:1; // Multiply pipe ops excluding junk ops" },, - uint16 StoreOps:1; // Store pipe ops excluding junk ops" }, - uint16 AndPipeOpsJunk:1; // Add pipe junk ops" },, - uint16 MulPipeOpsJunk:1; // Multiply pipe junk ops" }, - uint16 StoreOpsJunk:1; // Store pipe junk ops" } } - }; - uint16 flat; -} EVENT_MASK(k8_dispatched_fpu_ops); - -class k8Event_DISPATCHED_FPU_OPS : public k8BaseEvent -{ -public: - - k8Event_DISPATCHED_FPU_OPS() - { - eventMask = (EVENT_MASK(k8_dispatched_fpu_ops) *)&m_eventMask; - - event_id = 0x00; - unitEncode = FP; - name = _T("Dispatched FPU ops"); - revRequired = 'B'; - } - EVENT_MASK(k8_dispatched_fpu_ops) * eventMask; - -}; - -////////////////////////////////////////////////////////// - - - -class k8Event_NO_FPU_OPS : public k8BaseEvent -{ -public: - - k8Event_NO_FPU_OPS() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - event_id = 0x01; - unitEncode = FP; - - name = _T("Cycles with no FPU ops retired"); - revRequired = 'B'; - } - EVENT_MASK(NULL_MASK) * eventMask; - -}; - -////////////////////////////////////////////////////////// - -class k8Event_FAST_FPU_OPS : public k8BaseEvent -{ -public: - - k8Event_FAST_FPU_OPS() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - event_id = 0x02; - unitEncode = FP; - - name = _T("Dispatched FPU ops that use the fast flag interface"); - revRequired = 'B'; - - } - EVENT_MASK(NULL_MASK) * eventMask; - -}; - - -////////////////////////////////////////////////////////// - - -typedef union EVENT_MASK(k8_segment_register_load) -{ - - struct - { - uint16 ES:1; - uint16 CS:1; - uint16 SS:1; - uint16 DS:1; - uint16 FS:1; - uint16 GS:1; - uint16 HS:1; - }; - uint16 flat; -} EVENT_MASK(k8_segment_register_load); - - -class k8Event_SEG_REG_LOAD : public k8BaseEvent -{ -public: - - k8Event_SEG_REG_LOAD() - { - eventMask = (EVENT_MASK(k8_segment_register_load) *)&m_eventMask; - name = _T("Segment register load"); - event_id = 0x20; - unitEncode = LS; - - } - EVENT_MASK(k8_segment_register_load) * eventMask; - -}; - - -class k8Event_SELF_MODIFY_RESYNC : public k8BaseEvent -{ -public: - - k8Event_SELF_MODIFY_RESYNC() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Microarchitectural resync caused by self modifying code"); - event_id = 0x21; - unitEncode = LS; - - } - EVENT_MASK(NULL_MASK) * eventMask; - - -}; -class k8Event_LS_RESYNC_BY_SNOOP : public k8BaseEvent -{ -public: - - k8Event_LS_RESYNC_BY_SNOOP() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - event_id = 0x22; - unitEncode = LS; - - name = _T("Microarchitectural resync caused by snoop"); - } - EVENT_MASK(NULL_MASK) * eventMask; - - -}; -class k8Event_LS_BUFFER_FULL : public k8BaseEvent -{ -public: - - k8Event_LS_BUFFER_FULL() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("LS Buffer 2 Full"); - event_id = 0x23; - unitEncode = LS; - - } - EVENT_MASK(NULL_MASK) * eventMask; - -}; - - -typedef union EVENT_MASK(k8_locked_op) -{ - - - struct - { - uint16 NumLockInstr : 1; //Number of lock instructions executed - uint16 NumCyclesInRequestGrant : 1; //Number of cycles spent in the lock request/grant stage - - uint16 NumCyclesForLock:1; - /*Number of cycles a lock takes to complete once it is - non-speculative and is the oldest load/store operation - (non-speculative cycles in Ls2 entry 0)*/ - - - }; - uint16 flat; - - -} EVENT_MASK(k8_locked_op); - - - -class k8Event_LOCKED_OP : public k8BaseEvent -{ -public: - - EVENT_MASK(k8_locked_op) * eventMask; - - k8Event_LOCKED_OP() - { - eventMask = (EVENT_MASK(k8_locked_op) *)&m_eventMask; - name = _T("Locked operation"); - event_id = 0x24; - unitEncode = LS; - - revRequired = 'C'; - } - - -}; - -class k8Event_OP_LATE_CANCEL : public k8BaseEvent -{ -public: - - k8Event_OP_LATE_CANCEL() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Microarchitectural late cancel of an operation"); - event_id = 0x25; - unitEncode = LS; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("OP_LATE_CANCEL"); - - -}; -class k8Event_CFLUSH_RETIRED : public k8BaseEvent -{ -public: - - k8Event_CFLUSH_RETIRED() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Retired CFLUSH instructions"); - event_id = 0x26; - unitEncode = LS; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("CFLUSH_RETIRED"); - - -}; -class k8Event_CPUID_RETIRED : public k8BaseEvent -{ -public: - - k8Event_CPUID_RETIRED() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Retired CPUID instructions"); - event_id = 0x27; - unitEncode = LS; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("CPUID_RETIRED"); - - -}; - -typedef union EVENT_MASK( k8_cache) -{ - - struct - { - uint16 Invalid:1; - uint16 Exclusive:1; - uint16 Shared:1; - uint16 Owner:1; - uint16 Modified:1; - }; - uint16 flat; - -}EVENT_MASK( k8_cache); - /* 0x40-0x47: from K7 official event set */ - - -class k8Event_DATA_CACHE_ACCESSES : public k8BaseEvent -{ - k8Event_DATA_CACHE_ACCESSES() - { - - event_id = 0x40; - unitEncode = DC; - - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - - //_T("DATA_CACHE_ACCESSES"), - name = _T("Data cache accesses"); - } - EVENT_MASK(NULL_MASK) * eventMask; - -}; - -class k8Event_DATA_CACHE_MISSES : public k8BaseEvent -{ - k8Event_DATA_CACHE_MISSES() - { - - event_id = 0x41; - unitEncode = DC; - - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - - //_T("DATA_CACHE_MISSES"), - name = _T("Data cache misses"); - } - EVENT_MASK(NULL_MASK) * eventMask; -}; - -class k8Event_DATA_CACHE_REFILLS_FROM_L2 : public k8BaseEvent -{ - k8Event_DATA_CACHE_REFILLS_FROM_L2() - { - - event_id = 0x42; - unitEncode = DC; - - eventMask = (EVENT_MASK(k8_cache) *)&m_eventMask; - - - name = _T("Data cache refills from L2"); - } - EVENT_MASK(k8_cache) * eventMask; - -}; - -class k8Event_DATA_CACHE_REFILLS_FROM_SYSTEM : public k8BaseEvent -{ - k8Event_DATA_CACHE_REFILLS_FROM_SYSTEM() - { - - event_id = 0x43; - unitEncode = DC; - - - eventMask = (EVENT_MASK(k8_cache) *)&m_eventMask; - - //UM(k7_um_moesi), - //_T("DATA_CACHE_REFILLS_FROM_SYSTEM"), - name = _T("Data cache refills from system"); - } - EVENT_MASK(k8_cache) * eventMask; - -}; - -class k8Event_DATA_CACHE_WRITEBACKS : public k8BaseEvent -{ - k8Event_DATA_CACHE_WRITEBACKS() - { - - event_id = 0x44; - unitEncode = DC; - - eventMask = (EVENT_MASK(k8_cache) *)&m_eventMask; - - //UM(k7_um_moesi), - //_T("DATA_CACHE_WRITEBACKS"), - name = _T("Data cache writebacks"); - } - EVENT_MASK(k8_cache) * eventMask; - - -}; - -class k8Event_L1_DTLB_MISSES_AND_L2_DTLB_HITS : public k8BaseEvent -{ - k8Event_L1_DTLB_MISSES_AND_L2_DTLB_HITS() - { - - event_id = 0x45; - unitEncode = DC; - - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - - name = _T("L1 DTLB misses and L2 DTLB hits"); - } - EVENT_MASK(NULL_MASK) * eventMask; - - -}; - -class k8Event_L1_AND_L2_DTLB_MISSES : public k8BaseEvent -{ - k8Event_L1_AND_L2_DTLB_MISSES() - { - - event_id = 0x46; - unitEncode = DC; - - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - - name = _T("L1 and L2 DTLB misses") ; - } - EVENT_MASK(NULL_MASK) * eventMask; - -}; - -class k8Event_MISALIGNED_DATA_REFERENCES : public k8BaseEvent -{ - k8Event_MISALIGNED_DATA_REFERENCES() - { - - event_id = 0x47; - unitEncode = DC; - - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - - //NULL, _T("MISALIGNED_DATA_REFERENCES"), - name = _T("Misaligned data references"); - } - EVENT_MASK(NULL_MASK) * eventMask; - -}; - - - -class k8Event_ACCESS_CANCEL_LATE : public k8BaseEvent -{ -public: - - k8Event_ACCESS_CANCEL_LATE() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Microarchitectural late cancel of an access"); - event_id = 0x48; - unitEncode = DC; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("ACCESS_CANCEL_LATE"); - - -}; -class k8Event_ACCESS_CANCEL_EARLY : public k8BaseEvent -{ -public: - - k8Event_ACCESS_CANCEL_EARLY() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Microarchitectural early cancel of an access"); - event_id = 0x49; - unitEncode = DC; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("ACCESS_CANCEL_EARLY"); - - -}; -typedef union EVENT_MASK( k8_ecc) -{ - struct - { - uint16 ScrubberError : 1; // Scrubber error" }, - uint16 PiggybackScrubberErrors : 1; // Piggyback scrubber errors" } } - }; - uint16 flat; - -}EVENT_MASK( k8_ecc); - - -class k8Event_ECC_BIT_ERR : public k8BaseEvent -{ -public: - - k8Event_ECC_BIT_ERR() - { - eventMask = (EVENT_MASK(k8_ecc) *)&m_eventMask; - name = _T("One bit ECC error recorded found by scrubber"); - event_id = 0x4A; - unitEncode = DC; - - } - EVENT_MASK(k8_ecc) * eventMask; - // name = _T("ECC_BIT_ERR"); - - -}; - -// 4B -typedef union EVENT_MASK( k8_distpatch_prefetch_instructions) -{ - struct - { - uint16 Load : 1; - uint16 Store : 1; - uint16 NTA : 1; - }; - uint16 flat; - - -}EVENT_MASK( k8_distpatch_prefetch_instructions); - -class k8Event_DISPATCHED_PRE_INSTRS : public k8BaseEvent -{ -public: - - k8Event_DISPATCHED_PRE_INSTRS() - { - eventMask = (EVENT_MASK(k8_distpatch_prefetch_instructions) *)&m_eventMask; - name = _T("Dispatched prefetch instructions"); - event_id = 0x4B; - unitEncode = DC; - - } - EVENT_MASK(k8_distpatch_prefetch_instructions) * eventMask; - // name = _T("DISPATCHED_PRE_INSTRS"); - - /* 0x4C: added in Revision C */ - -}; - - - -typedef union EVENT_MASK( k8_lock_accesses) -{ - struct - { - uint16 DcacheAccesses:1; // Number of dcache accesses by lock instructions" }, - uint16 DcacheMisses:1; // Number of dcache misses by lock instructions" } } - }; - uint16 flat; - -}EVENT_MASK( k8_lock_accesses); - - - -class k8Event_LOCK_ACCESSES : public k8BaseEvent -{ -public: - - k8Event_LOCK_ACCESSES() - { - eventMask = (EVENT_MASK(k8_lock_accesses) *)&m_eventMask; - name = _T("DCACHE accesses by locks") ; - event_id = 0x4C; - unitEncode = DC; - - revRequired = 'C'; - } - EVENT_MASK(k8_lock_accesses) * eventMask; - - -}; - - -class k8Event_CYCLES_PROCESSOR_IS_RUNNING : public k8BaseEvent -{ -public: - - k8Event_CYCLES_PROCESSOR_IS_RUNNING() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Cycles processor is running (not in HLT or STPCLK)"); - event_id = 0x76; - unitEncode = BU; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("CYCLES_PROCESSOR_IS_RUNNING"); /* undocumented *; - - -}; - - -typedef union EVENT_MASK( k8_internal_L2_request) -{ - struct - { - uint16 ICFill:1; // IC fill" }, - uint16 DCFill:1; // DC fill" }, - uint16 TLBReload:1; // TLB reload" }, - uint16 TagSnoopRequest:1; // Tag snoop request" }, - uint16 CancelledRequest:1; // Cancelled request" } } - }; - uint16 flat; - - -}EVENT_MASK( k8_internal_L2_request); - -class k8Event_BU_INT_L2_REQ : public k8BaseEvent -{ -public: - - k8Event_BU_INT_L2_REQ() - { - eventMask = (EVENT_MASK(k8_internal_L2_request) *)&m_eventMask; - name = _T("Internal L2 request"); - unitEncode = BU; - event_id = 0x7D; - } - - EVENT_MASK(k8_internal_L2_request) * eventMask; -} ; - - // name = _T("BU_INT_L2_REQ"); - - - -// 7E -typedef union EVENT_MASK( k8_fill_request_missed_L2) -{ - - struct - { - uint16 ICFill:1; // IC fill" }, - uint16 DCFill:1; // DC fill" }, - uint16 TLBReload:1; // TLB reload" }, - }; - uint16 flat; - -} EVENT_MASK( k8_fill_request_missed_L2); - - -class k8Event_BU_FILL_REQ : public k8BaseEvent -{ -public: - - k8Event_BU_FILL_REQ() - { - eventMask = (EVENT_MASK(k8_fill_request_missed_L2) *)&m_eventMask; - name = _T("Fill request that missed in L2"); - event_id = 0x7E; - unitEncode = BU; - - } - EVENT_MASK(k8_fill_request_missed_L2) * eventMask; - // name = _T("BU_FILL_REQ"); - - - -}; - - - - -// 7F -typedef union EVENT_MASK( k8_fill_into_L2) -{ - - struct - { - uint16 DirtyL2Victim:1; // Dirty L2 victim - uint16 VictimFromL2:1; // Victim from L2 - }; - uint16 flat; - -}EVENT_MASK( k8_fill_into_L2); - -class k8Event_BU_FILL_L2 : public k8BaseEvent -{ -public: - - k8Event_BU_FILL_L2() - { - eventMask = (EVENT_MASK(k8_fill_into_L2) *)&m_eventMask; - name = _T("Fill into L2"); - event_id = 0x7F; - unitEncode = BU; - - } - EVENT_MASK(k8_fill_into_L2) * eventMask; - // name = _T("BU_FILL_L2"); - - -}; - -class k8Event_INSTRUCTION_CACHE_FETCHES : public k8BaseEvent -{ -public: - k8Event_INSTRUCTION_CACHE_FETCHES() - { - event_id = 0x80; - unitEncode = IC; - - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - - name = _T("Instruction cache fetches"); - } - EVENT_MASK(NULL_MASK) * eventMask; - -}; - - -class k8Event_INSTRUCTION_CACHE_MISSES : public k8BaseEvent -{ -public: - k8Event_INSTRUCTION_CACHE_MISSES() - { - event_id = 0x81; - unitEncode = IC; - - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - - //0xF, NULL, _T("INSTRUCTION_CACHE_MISSES"), - name = _T("Instruction cache misses"); - } - EVENT_MASK(NULL_MASK) * eventMask; - -}; - - -class k8Event_IC_REFILL_FROM_L2 : public k8BaseEvent -{ -public: - - k8Event_IC_REFILL_FROM_L2() - { - eventMask = (EVENT_MASK(k8_cache) *)&m_eventMask; - name = _T("Refill from L2"); - event_id = 0x82; - unitEncode = IC; - - } - EVENT_MASK(k8_cache) * eventMask; - // name = _T("IC_REFILL_FROM_L2"); - - - -}; -class k8Event_IC_REFILL_FROM_SYS : public k8BaseEvent -{ -public: - - k8Event_IC_REFILL_FROM_SYS() - { - eventMask = (EVENT_MASK(k8_cache) *)&m_eventMask; - name = _T("Refill from system"); - event_id = 0x83; - unitEncode = IC; - - } - EVENT_MASK(k8_cache) * eventMask; - // name = _T("IC_REFILL_FROM_SYS"); - - - -}; -class k8Event_L1_ITLB_MISSES_AND_L2_ITLB_HITS : public k8BaseEvent -{ -public: - k8Event_L1_ITLB_MISSES_AND_L2_ITLB_HITS() - { - - event_id = 0x84; - unitEncode = IC; - - name = _T("L1 ITLB misses (and L2 ITLB hits)"); - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - - - } - EVENT_MASK(NULL_MASK) * eventMask; - - -}; - -class k8Event_L1_AND_L2_ITLB_MISSES : public k8BaseEvent -{ -public: - k8Event_L1_AND_L2_ITLB_MISSES() - { - event_id = 0x85; - unitEncode = IC; - - name = _T("(L1 and) L2 ITLB misses"); - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - - } - EVENT_MASK(NULL_MASK) * eventMask; - -}; - - - - -class k8Event_IC_RESYNC_BY_SNOOP : public k8BaseEvent -{ -public: - - k8Event_IC_RESYNC_BY_SNOOP() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - event_id = 0x86; - unitEncode = IC; - - name = _T("Microarchitectural resync caused by snoop"); - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("IC_RESYNC_BY_SNOOP"); - /* similar to 0x22; but IC unit instead of LS unit */ - - - -}; -class k8Event_IC_FETCH_STALL : public k8BaseEvent -{ -public: - - k8Event_IC_FETCH_STALL() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Instruction fetch stall"); - event_id = 0x87; - unitEncode = IC; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("IC_FETCH_STALL"); - - - -}; -class k8Event_IC_STACK_HIT : public k8BaseEvent -{ -public: - - k8Event_IC_STACK_HIT() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Return stack hit"); - event_id = 0x88; - unitEncode = IC; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("IC_STACK_HIT"); - - - -}; -class k8Event_IC_STACK_OVERFLOW : public k8BaseEvent -{ -public: - - k8Event_IC_STACK_OVERFLOW() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Return stack overflow"); - event_id = 0x89; - unitEncode = IC; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("IC_STACK_OVERFLOW"); - - - - -}; - - /* 0xC0-0xC7: from K7 official event set */ -class k8Event_RETIRED_INSTRUCTIONS : public k8BaseEvent -{ -public: - k8Event_RETIRED_INSTRUCTIONS() - { - event_id = 0xC0; - unitEncode = FR; - - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - - //0xF, NULL, _T("RETIRED_INSTRUCTIONS"), - name = _T("Retired instructions (includes exceptions, interrupts, resyncs)"); - } - EVENT_MASK(NULL_MASK) * eventMask; -}; - -class k8Event_RETIRED_OPS : public k8BaseEvent -{ -public: - k8Event_RETIRED_OPS() - { - event_id = 0xC1; - unitEncode = FR; - - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - //0xF, NULL, _T("RETIRED_OPS"), - name = _T("Retired Ops") ; - } - EVENT_MASK(NULL_MASK) * eventMask; -}; -class k8Event_RETIRED_BRANCHES : public k8BaseEvent -{ -public: - k8Event_RETIRED_BRANCHES() - { - event_id = 0xC2; - unitEncode = FR; - - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - //0xF, NULL, _T("RETIRED_BRANCHES"), - name = _T("Retired branches (conditional, unconditional, exceptions, interrupts)") ; - } - EVENT_MASK(NULL_MASK) * eventMask; -}; -class k8Event_RETIRED_BRANCHES_MISPREDICTED : public k8BaseEvent -{ -public: - k8Event_RETIRED_BRANCHES_MISPREDICTED() - { - event_id = 0xC3; - unitEncode = FR; - - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - //0xF, NULL, _T("RETIRED_BRANCHES_MISPREDICTED"), - name = _T("Retired branches mispredicted") ; - } - EVENT_MASK(NULL_MASK) * eventMask; -}; -class k8Event_RETIRED_TAKEN_BRANCHES : public k8BaseEvent -{ -public: - k8Event_RETIRED_TAKEN_BRANCHES() - { - event_id = 0xC4; - unitEncode = FR; - - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - //0xF, NULL, _T("RETIRED_TAKEN_BRANCHES"), - name = _T("Retired taken branches") ; - } - EVENT_MASK(NULL_MASK) * eventMask; -}; -class k8Event_RETIRED_TAKEN_BRANCHES_MISPREDICTED : public k8BaseEvent -{ -public: - k8Event_RETIRED_TAKEN_BRANCHES_MISPREDICTED() - { - event_id = 0xC5; - unitEncode = FR; - - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - //0xF, NULL, _T("RETIRED_TAKEN_BRANCHES_MISPREDICTED"), - name = _T("Retired taken branches mispredicted") ; - } - EVENT_MASK(NULL_MASK) * eventMask; -}; -class k8Event_RETIRED_FAR_CONTROL_TRANSFERS : public k8BaseEvent -{ -public: - k8Event_RETIRED_FAR_CONTROL_TRANSFERS() - { - event_id = 0xC6; - unitEncode = FR; - - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - //0xF, NULL, _T("RETIRED_FAR_CONTROL_TRANSFERS"), - name = _T("Retired far control transfers") ; - } - EVENT_MASK(NULL_MASK) * eventMask; -}; -class k8Event_RETIRED_RESYNC_BRANCHES : public k8BaseEvent -{ -public: - k8Event_RETIRED_RESYNC_BRANCHES() - { - event_id = 0xC7; - unitEncode = FR; - - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - //0xF, NULL, _T("RETIRED_RESYNC_BRANCHES"), - name = _T("Retired resync branches (only non-control transfer branches counted)") ; - } - EVENT_MASK(NULL_MASK) * eventMask; -}; - -class k8Event_RETIRED_NEAR_RETURNS : public k8BaseEvent -{ -public: - - k8Event_RETIRED_NEAR_RETURNS() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Retired near returns"); - event_id = 0xC8; - unitEncode = FR; - - } - EVENT_MASK(NULL_MASK) * eventMask; - - - -}; -class k8Event_RETIRED_RETURNS_MISPREDICT : public k8BaseEvent -{ -public: - - k8Event_RETIRED_RETURNS_MISPREDICT() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Retired near returns mispredicted"); - event_id = 0xC9; - unitEncode = FR; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("RETIRED_RETURNS_MISPREDICT"); - - -}; -class k8Event_RETIRED_BRANCH_MISCOMPARE : public k8BaseEvent -{ -public: - - k8Event_RETIRED_BRANCH_MISCOMPARE() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Retired taken branches mispredicted due to address miscompare"); - event_id = 0xCA; - unitEncode = FR; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("RETIRED_BRANCH_MISCOMPARE"); - - -}; - - - /* Revision B and later */ - -typedef union EVENT_MASK( k8_retired_fpu_instr) -{ - struct - { - uint16 DirtyL2Victim:1; // x87 instructions - uint16 CombinedMMX_3DNow:1; // Combined MMX & 3DNow! instructions" }, - uint16 CombinedPackedSSE_SSE2:1; // Combined packed SSE and SSE2 instructions" }, - uint16 CombinedScalarSSE_SSE2:1; // Combined scalar SSE and SSE2 instructions" } } - }; - uint16 flat; - - -}EVENT_MASK( k8_retired_fpu_instr); - - -class k8Event_RETIRED_FPU_INSTRS : public k8BaseEvent -{ -public: - - k8Event_RETIRED_FPU_INSTRS() - { - eventMask = (EVENT_MASK(k8_retired_fpu_instr) *)&m_eventMask; - event_id = 0xCB; - unitEncode = FR; - - name = _T("Retired FPU instructions"); - revRequired = 'B'; - } - EVENT_MASK(k8_retired_fpu_instr) * eventMask; - /* Revision B and later */ - - - -}; - -// CC -typedef union EVENT_MASK( k8_retired_fastpath_double_op_instr ) -{ - - struct - { - uint16 LowOpPosition0:1; // With low op in position 0" }, - uint16 LowOpPosition1:1; // With low op in position 1" }, - uint16 LowOpPosition2:1; // With low op in position 2" } } - }; - uint16 flat; - - -}EVENT_MASK( k8_retired_fastpath_double_op_instr); - -class k8Event_RETIRED_FASTPATH_INSTRS : public k8BaseEvent -{ -public: - - k8Event_RETIRED_FASTPATH_INSTRS() - { - eventMask = (EVENT_MASK(k8_retired_fastpath_double_op_instr) *)&m_eventMask; - event_id = 0xCC; - unitEncode = FR; - - name = _T("Retired fastpath double op instructions"); - revRequired = 'B'; - - } - EVENT_MASK(k8_retired_fastpath_double_op_instr) * eventMask; - - -}; - -class k8Event_INTERRUPTS_MASKED_CYCLES : public k8BaseEvent -{ -public: - k8Event_INTERRUPTS_MASKED_CYCLES() - { - event_id = 0xCD; - unitEncode = FR; - - //0xF, NULL, _T("INTERRUPTS_MASKED_CYCLES"), - name = _T("Interrupts masked cycles (IF=0)") ; - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - - } - EVENT_MASK(NULL_MASK) * eventMask; - -}; -class k8Event_INTERRUPTS_MASKED_WHILE_PENDING_CYCLES : public k8BaseEvent -{ -public: - k8Event_INTERRUPTS_MASKED_WHILE_PENDING_CYCLES() - { - event_id = 0xCE; - unitEncode = FR; - - //0xF, NULL, _T("INTERRUPTS_MASKED_WHILE_PENDING_CYCLES"), - name = _T("Interrupts masked while pending cycles (INTR while IF=0)") ; - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - } - EVENT_MASK(NULL_MASK) * eventMask; - -}; -class k8Event_NUMBER_OF_TAKEN_HARDWARE_INTERRUPTS : public k8BaseEvent -{ -public: - k8Event_NUMBER_OF_TAKEN_HARDWARE_INTERRUPTS() - { - event_id = 0xCF; - unitEncode = FR; - - //0xF, NULL, _T("NUMBER_OF_TAKEN_HARDWARE_INTERRUPTS"), - name = _T("Number of taken hardware interrupts") ; - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - } - EVENT_MASK(NULL_MASK) * eventMask; - -}; - - -class k8Event_DECODER_EMPTY : public k8BaseEvent -{ -public: - - k8Event_DECODER_EMPTY() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Nothing to dispatch (decoder empty)"); - event_id = 0xD0; - unitEncode = FR; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("DECODER_EMPTY"); - - -}; -class k8Event_DISPATCH_STALLS : public k8BaseEvent -{ -public: - - k8Event_DISPATCH_STALLS() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Dispatch stalls (events 0xD2-0xDA combined)"); - event_id = 0xD1; - unitEncode = FR; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("DISPATCH_STALLS"); - - - -}; -class k8Event_DISPATCH_STALL_FROM_BRANCH_ABORT : public k8BaseEvent -{ -public: - - k8Event_DISPATCH_STALL_FROM_BRANCH_ABORT() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Dispatch stall from branch abort to retire"); - event_id = 0xD2; - unitEncode = FR; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("DISPATCH_STALL_FROM_BRANCH_ABORT"); - - - -}; -class k8Event_DISPATCH_STALL_SERIALIZATION : public k8BaseEvent -{ -public: - - k8Event_DISPATCH_STALL_SERIALIZATION() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Dispatch stall for serialization"); - event_id = 0xD3; - unitEncode = FR; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("DISPATCH_STALL_SERIALIZATION"); - - -}; -class k8Event_DISPATCH_STALL_SEG_LOAD : public k8BaseEvent -{ -public: - - k8Event_DISPATCH_STALL_SEG_LOAD() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Dispatch stall for segment load"); - event_id = 0xD4; - unitEncode = FR; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("DISPATCH_STALL_SEG_LOAD"); - - - -}; -class k8Event_DISPATCH_STALL_REORDER_BUFFER : public k8BaseEvent -{ -public: - - k8Event_DISPATCH_STALL_REORDER_BUFFER() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Dispatch stall when reorder buffer is full"); - event_id = 0xD5; - unitEncode = FR; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("DISPATCH_STALL_REORDER_BUFFER"); - - -}; -class k8Event_DISPATCH_STALL_RESERVE_STATIONS : public k8BaseEvent -{ -public: - - k8Event_DISPATCH_STALL_RESERVE_STATIONS() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Dispatch stall when reservation stations are full"); - event_id = 0xD6; - unitEncode = FR; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("DISPATCH_STALL_RESERVE_STATIONS"); - - -}; -class k8Event_DISPATCH_STALL_FPU : public k8BaseEvent -{ -public: - - k8Event_DISPATCH_STALL_FPU() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Dispatch stall when FPU is full"); - event_id = 0xD7; - unitEncode = FR; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("DISPATCH_STALL_FPU"); - - -}; -class k8Event_DISPATCH_STALL_LS : public k8BaseEvent -{ -public: - - k8Event_DISPATCH_STALL_LS() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Dispatch stall when LS is full"); - event_id = 0xD8; - unitEncode = FR; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("DISPATCH_STALL_LS"); - - -}; -class k8Event_DISPATCH_STALL_QUIET_WAIT : public k8BaseEvent -{ -public: - - k8Event_DISPATCH_STALL_QUIET_WAIT() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Dispatch stall when waiting for all to be quiet"); - event_id = 0xD9; - unitEncode = FR; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("DISPATCH_STALL_QUIET_WAIT"); - - - -}; -class k8Event_DISPATCH_STALL_PENDING : public k8BaseEvent -{ -public: - - k8Event_DISPATCH_STALL_PENDING() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Dispatch stall when far control transfer or resync branch is pending"); - event_id = 0xDA; - unitEncode = FR; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("DISPATCH_STALL_PENDING"); - - - -}; - - -typedef union EVENT_MASK( k8_fpu_exceptions) -{ - - - - struct - { - uint16 x87ReclassMicrofaults:1; // x87 reclass microfaults" }, - uint16 SSERetypeMicrofaults:1; // SSE retype microfaults" }, - uint16 SSEReclassMicrofaults:1; // SSE reclass microfaults" }, - uint16 SSE_x87Microtraps:1; // SSE and x87 microtraps" } } - }; - uint16 flat; - - - -}EVENT_MASK( k8_fpu_exceptions); - -class k8Event_FPU_EXCEPTIONS : public k8BaseEvent -{ -public: - - k8Event_FPU_EXCEPTIONS() - { - eventMask = (EVENT_MASK(k8_fpu_exceptions) *)&m_eventMask; - event_id = 0xDB; - unitEncode = FR; - - name = _T("FPU exceptions"); - revRequired = 'B'; - - } - EVENT_MASK(k8_fpu_exceptions) * eventMask; - // name = _T("FPU_EXCEPTIONS"); - /* Revision B and later */ - - - -}; -class k8Event_DR0_BREAKPOINTS : public k8BaseEvent -{ -public: - - k8Event_DR0_BREAKPOINTS() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Number of breakpoints for DR0"); - event_id = 0xDC; - unitEncode = FR; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("DR0_BREAKPOINTS"); - - - -}; -class k8Event_DR1_BREAKPOINTS : public k8BaseEvent -{ -public: - - k8Event_DR1_BREAKPOINTS() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Number of breakpoints for DR1"); - event_id = 0xDD; - unitEncode = FR; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("DR1_BREAKPOINTS"); - - - -}; -class k8Event_DR2_BREAKPOINTS : public k8BaseEvent -{ -public: - - k8Event_DR2_BREAKPOINTS() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Number of breakpoints for DR2"); - event_id = 0xDE; - unitEncode = FR; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("DR2_BREAKPOINTS"); - - -}; -class k8Event_DR3_BREAKPOINTS : public k8BaseEvent -{ -public: - - k8Event_DR3_BREAKPOINTS() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Number of breakpoints for DR3"); - event_id = 0xDF; - unitEncode = FR; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("DR3_BREAKPOINTS"); - - -}; - - - -// E0 -typedef union EVENT_MASK( k8_page_access_event) -{ - struct - { - uint16 PageHit:1; // Page hit" }, - uint16 PageMiss:1; // Page miss" }, - uint16 PageConflict:1; // Page conflict" } } - }; - uint16 flat; - -}EVENT_MASK( k8_page_access_event); - -class k8Event_MEM_PAGE_ACCESS : public k8BaseEvent -{ -public: - - k8Event_MEM_PAGE_ACCESS() - { - eventMask = (EVENT_MASK(k8_page_access_event) *)&m_eventMask; - name = _T("Memory controller page access"); - event_id = 0xE0; - unitEncode = NB; - - } - EVENT_MASK(k8_page_access_event) * eventMask; - // name = _T("MEM_PAGE_ACCESS"); - - -}; -class k8Event_MEM_PAGE_TBL_OVERFLOW : public k8BaseEvent -{ -public: - - k8Event_MEM_PAGE_TBL_OVERFLOW() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Memory controller page table overflow"); - event_id = 0xE1; - unitEncode = NB; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("MEM_PAGE_TBL_OVERFLOW"); - - -}; -class k8Event_DRAM_SLOTS_MISSED : public k8BaseEvent -{ -public: - - k8Event_DRAM_SLOTS_MISSED() - { - eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask; - name = _T("Memory controller DRAM command slots missed (in MemClks)"); - event_id = 0xE2; - unitEncode = NB; - - } - EVENT_MASK(NULL_MASK) * eventMask; - // name = _T("DRAM_SLOTS_MISSED"); - - -}; - - -// e3 -typedef union EVENT_MASK( k8_turnaround) -{ - - struct - { - uint16 DIMMTurnaround:1; //DIMM turnaround" }, - uint16 ReadToWriteTurnaround:1; //Read to write turnaround" }, - uint16 WriteToReadTurnaround:1; //Write to read turnaround" } } - }; - uint16 flat; - - -}EVENT_MASK( k8_turnaround); - -class k8Event_MEM_TURNAROUND : public k8BaseEvent -{ -public: - - k8Event_MEM_TURNAROUND() - { - eventMask = (EVENT_MASK(k8_turnaround) *)&m_eventMask; - name = _T("Memory controller turnaround"); - event_id = 0xE3; - unitEncode = NB; - - } - EVENT_MASK(k8_turnaround) * eventMask; - // name = _T("MEM_TURNAROUND"); - - -}; - - - - -// E4 -typedef union EVENT_MASK( k8_bypass_counter_saturation) -{ - struct - { - uint16 MEM_HighPriorityBypass:1; // Memory controller high priority bypass" }, - uint16 MEM_LowPriorityBypass:1; // Memory controller low priority bypass" }, - uint16 DRAM_InterfaceBypass:1; // DRAM controller interface bypass" }, - uint16 DRAM_QueueBypass:1; // DRAM controller queue bypass" } } - }; - uint16 flat; - -}EVENT_MASK( k8_bypass_counter_saturation); - -class k8Event_MEM_BYPASS_SAT : public k8BaseEvent -{ -public: - - k8Event_MEM_BYPASS_SAT() - { - eventMask = (EVENT_MASK(k8_bypass_counter_saturation) *)&m_eventMask; - name = _T("Memory controller bypass counter saturation"); - event_id = 0xE4; - unitEncode = NB; - - } - EVENT_MASK(k8_bypass_counter_saturation) * eventMask; - // name = _T("MEM_BYPASS_SAT"); - - -}; - - - -//EB -typedef union EVENT_MASK( k8_sized_commands) -{ - - struct - { - uint16 NonPostWrSzByte:1; // NonPostWrSzByte" }, - uint16 NonPostWrSzDword:1; // NonPostWrSzDword" }, - uint16 PostWrSzByte:1; // PostWrSzByte" }, - uint16 PostWrSzDword:1; // PostWrSzDword" }, - uint16 RdSzByte:1; // RdSzByte" }, - uint16 RdSzDword:1; // RdSzDword" }, - uint16 RdModWr:1; // RdModWr" } } - }; - uint16 flat; - - -}EVENT_MASK( k8_sized_commands); - - -class k8Event_SIZED_COMMANDS : public k8BaseEvent -{ -public: - - k8Event_SIZED_COMMANDS() - { - eventMask = (EVENT_MASK(k8_sized_commands) *)&m_eventMask; - name = _T("Sized commands"); - event_id = 0xEB; - unitEncode = NB; - - } - EVENT_MASK(k8_sized_commands) * eventMask; - // name = _T("SIZED_COMMANDS"); - - -}; - -typedef union EVENT_MASK( k8_probe_result) -{ - struct - { - uint16 ProbeMiss:1; // Probe miss" }, - uint16 ProbeHit:1; // Probe hit" }, - uint16 ProbeHitDirtyWithoutMemoryCancel:1; // Probe hit dirty without memory cancel" }, - uint16 ProbeHitDirtyWithMemoryCancel:1; // Probe hit dirty with memory cancel" } } - uint16 UpstreamDisplayRefreshReads:1; // Rev D and later - uint16 UpstreamNonDisplayRefreshReads:1; // Rev D and later - uint16 UpstreamWrites:1; // Rev D and later - }; - uint16 flat; - - -}EVENT_MASK( k8_probe_result); - - -class k8Event_PROBE_RESULT : public k8BaseEvent -{ -public: - - k8Event_PROBE_RESULT() - { - eventMask = (EVENT_MASK(k8_probe_result) *)&m_eventMask; - name = _T("Probe result"); - event_id = 0xEC; - unitEncode = NB; - - } - EVENT_MASK(k8_probe_result) * eventMask; - // name = _T("PROBE_RESULT"); - - -}; - -typedef union EVENT_MASK( k8_ht) -{ - - struct - { - uint16 CommandSent:1; //Command sent" }, - uint16 DataSent:1; //Data sent" }, - uint16 BufferReleaseSent:1; //Buffer release sent" - uint16 NopSent:1; //Nop sent" } } - }; - uint16 flat; - - -}EVENT_MASK( k8_ht); - - -class k8Event_HYPERTRANSPORT_BUS0_WIDTH : public k8BaseEvent -{ -public: - - k8Event_HYPERTRANSPORT_BUS0_WIDTH() - { - eventMask = (EVENT_MASK(k8_ht) *)&m_eventMask; - name = _T("Hypertransport (tm) bus 0 bandwidth"); - event_id = 0xF6; - unitEncode = NB; - - } - EVENT_MASK(k8_ht) * eventMask; - // name = _T("HYPERTRANSPORT_BUS0_WIDTH"); - - -}; -class k8Event_HYPERTRANSPORT_BUS1_WIDTH : public k8BaseEvent -{ -public: - - k8Event_HYPERTRANSPORT_BUS1_WIDTH() - { - eventMask = (EVENT_MASK(k8_ht) *)&m_eventMask; - name = _T("Hypertransport (tm) bus 1 bandwidth"); - event_id = 0xF7; - unitEncode = NB; - - } - EVENT_MASK(k8_ht) * eventMask; - // name = _T("HYPERTRANSPORT_BUS1_WIDTH"); - - -}; -class k8Event_HYPERTRANSPORT_BUS2_WIDTH : public k8BaseEvent -{ -public: - - k8Event_HYPERTRANSPORT_BUS2_WIDTH() - { - eventMask = (EVENT_MASK(k8_ht) *)&m_eventMask; - name = _T("Hypertransport (tm) bus 2 bandwidth"); - event_id = 0xF8; - unitEncode = NB; - - } - EVENT_MASK(k8_ht) * eventMask; - // name = _T("HYPERTRANSPORT_BUS2_WIDTH"); - -}; - -// -//typedef union EVENT_MASK( perfctr_event_set k8_common_event_set) -//{ -// -// .cpu_type = PERFCTR_X86_AMD_K8, -// .event_prefix = _T("K8_"), -// .include = &k7_official_event_set, -// .nevents = ARRAY_SIZE(k8_common_events), -// .events = k8_common_events, -//}EVENT_MASK( perfctr_event_set k8_common_event_set); -// -//typedef union EVENT_MASK( perfctr_event k8_events[]) -//{ -// -// { 0x24, 0xF, UM(NULL), _T("LOCKED_OP"), /* unit mask changed in Rev. C */ -// _T("Locked operation") }, -//}EVENT_MASK( perfctr_event k8_events[]); - - - - -//const struct perfctr_event_set perfctr_k8_event_set) -//{ -// -// .cpu_type = PERFCTR_X86_AMD_K8, -// .event_prefix = _T("K8_"), -// .include = &k8_common_event_set, -// .nevents = ARRAY_SIZE(k8_events), -// .events = k8_events, -//}; -// -/* - * K8 Revision C. Starts at CPUID 0xF58 for Opteron/Athlon64FX and - * CPUID 0xF48 for Athlon64. (CPUID 0xF51 is Opteron Revision B3.) - */ - - - - - - - - -// -//typedef union EVENT_MASK( k8_lock_accesses) -//{ -// struct -// { -// uint16 DcacheAccesses:1; // Number of dcache accesses by lock instructions" }, -// uint16 DcacheMisses:1; // Number of dcache misses by lock instructions" } } -// }; -// uint16 flat; -// -//}EVENT_MASK( k8_lock_accesses); -// - -#endif // K8PERFORMANCECOUNTERS_H diff --git a/public/tier0/P4PerformanceCounters.h b/public/tier0/P4PerformanceCounters.h deleted file mode 100644 index 842a3860d..000000000 --- a/public/tier0/P4PerformanceCounters.h +++ /dev/null @@ -1,322 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef P4PERFORMANCECOUNTERS_H -#define P4PERFORMANCECOUNTERS_H - -#pragma once -// Pentium 4 support - -/* - http://developer.intel.com/design/Pentium4/documentation.htm - - IA-32 Intel Architecture Software Developer's Manual Volume 1: Basic Architecture - - IA-32 Intel Architecture Software Developer's Manual Volume 2A: Instruction Set Reference, A-M - - IA-32 Intel Architecture Software Developer's Manual Volume 2B: Instruction Set Reference, N-Z - - IA-32 Intel Architecture Software Developer's Manual Volume 3: System Programming Guide - - - From Mikael Pettersson's perfctr: - - http://user.it.uu.se/~mikpe/linux/perfctr/ - - * Known quirks: - - OVF_PMI+FORCE_OVF counters must have an ireset value of -1. - This allows the regular overflow check to also handle FORCE_OVF - counters. Not having this restriction would lead to MAJOR - complications in the driver's "detect overflow counters" code. - There is no loss of functionality since the ireset value doesn't - affect the counter's PMI rate for FORCE_OVF counters. - - - In experiments with FORCE_OVF counters, and regular OVF_PMI - counters with small ireset values between -8 and -1, it appears - that the faulting instruction is subjected to a new PMI before - it can complete, ad infinitum. This occurs even though the driver - clears the CCCR (and in testing also the ESCR) and invokes a - user-space signal handler before restoring the CCCR and resuming - the instruction. -*/ - -#define NCOUNTERS 18 - -// The 18 counters -enum Counters -{ - MSR_BPU_COUNTER0, - MSR_BPU_COUNTER1, - MSR_BPU_COUNTER2, - MSR_BPU_COUNTER3, - MSR_MS_COUNTER0, - MSR_MS_COUNTER1, - MSR_MS_COUNTER2, - MSR_MS_COUNTER3, - MSR_FLAME_COUNTER0, - MSR_FLAME_COUNTER1, - MSR_FLAME_COUNTER2, - MSR_FLAME_COUNTER3, - MSR_IQ_COUNTER0, - MSR_IQ_COUNTER1, - MSR_IQ_COUNTER2, - MSR_IQ_COUNTER3, - MSR_IQ_COUNTER4, - MSR_IQ_COUNTER5 -}; - -// register base for counters -#define MSR_COUNTER_BASE 0x300 - -// register base for CCCR register -#define MSR_CCCR_BASE 0x360 - -#pragma pack(push, 1) -// access to these bits is through the methods -typedef union ESCR -{ - struct - { - uint64 Reserved0_1 : 2; // - uint64 USR : 1; // - uint64 OS : 1; // - uint64 TagEnable : 1; // - uint64 TagValue : 4; // - uint64 EventMask : 16; // from event select - uint64 ESCREventSelect : 6; // 31:25 class of event - uint64 Reserved31 : 1; // - - uint64 Reserved32_63 : 32; // - }; - uint64 flat; - -} ESCR; - -typedef union CCCR -{ - struct - { - uint64 Reserved0_11 : 12;// 0 -11 - uint64 Enable : 1; // 12 - uint64 CCCRSelect : 3; // 13-15 - uint64 Reserved16_17 : 2; // 16 17 - - uint64 Compare : 1; // 18 - uint64 Complement : 1; // 19 - uint64 Threshold : 4; // 20-23 - uint64 Edge : 1; // 24 - uint64 FORCE_OVF : 1; // 25 - uint64 OVF_PMI : 1; // 26 - uint64 Reserved27_29 : 3; // 27-29 - uint64 Cascade : 1; // 30 - uint64 OVF : 1; // 31 - - uint64 Reserved32_63 : 32; // - }; - uint64 flat; - -} CCCR; - -#pragma pack(pop) - -extern const unsigned short cccr_escr_map[NCOUNTERS][8]; - -enum P4TagState -{ - TagDisable, // - TagEnable, // -}; - -enum P4ForceOverflow -{ - ForceOverflowDisable, - ForceOverflowEnable, -}; - -enum P4OverflowInterrupt -{ - OverflowInterruptDisable, - OverflowInterruptEnable, -}; - -// Turn off the no return value warning in ReadCounter. -#pragma warning( disable : 4035 ) -class P4BaseEvent -{ - int m_counter; - -protected: - - void SetCounter(int counter) - { - m_counter = counter; - cccrPort = MSR_CCCR_BASE + m_counter; - counterPort = MSR_COUNTER_BASE + m_counter; - escrPort = cccr_escr_map[m_counter][cccr.CCCRSelect]; - } - -public: - - unsigned short m_eventMask; - const tchar *description; - PME *pme; - ESCR escr; - CCCR cccr; - int counterPort; - int cccrPort; - int escrPort; - - P4BaseEvent() - { - pme = PME::Instance(); - m_eventMask = 0; - description = _T(""); - escr.flat = 0; - cccr.flat = 0; - cccr.Reserved16_17 = 3; // must be set - escrPort = 0; - m_counter = -1; - } - - void StartCounter() - { - cccr.Enable = 1; - pme->WriteMSR( cccrPort, cccr.flat ); - } - - void StopCounter() - { - cccr.Enable = 0; - pme->WriteMSR( cccrPort, cccr.flat ); - } - - void ClearCounter() - { - pme->WriteMSR( counterPort, 0ui64 ); // clear - } - - void WriteCounter( int64 value ) - { - pme->WriteMSR( counterPort, value ); // clear - } - - int64 ReadCounter() - { -#if PME_DEBUG - if ( escr.USR == 0 && escr.OS == 0 ) - return -1; // no area to collect, use SetCaptureMode - - if ( escr.EventMask == 0 ) - return -2; // no event mask set - - if ( m_counter == -1 ) - return -3; // counter not legal -#endif - - // ReadMSR should work here too, but RDPMC should be faster - int64 value = 0; - pme->ReadMSR( counterPort, &value ); - return value; -#if 0 - // we need to copy this into a temp for some reason - int temp = m_counter; - _asm - { - mov ecx, temp - RDPMC - } -#endif - } - - void SetCaptureMode( PrivilegeCapture priv ) - { - switch ( priv ) - { - case OS_Only: - { - escr.USR = 0; - escr.OS = 1; - break; - } - case USR_Only: - { - escr.USR = 1; - escr.OS = 0; - break; - } - case OS_and_USR: - { - escr.USR = 1; - escr.OS = 1; - break; - } - } - - escr.EventMask = m_eventMask; - pme->WriteMSR( escrPort, escr.flat ); - } - - void SetTagging( P4TagState tagEnable, uint8 tagValue ) - { - escr.TagEnable = tagEnable; - escr.TagValue = tagValue; - pme->WriteMSR( escrPort, escr.flat ); - } - - void SetFiltering( CompareState compareEnable, CompareMethod compareMethod, uint8 threshold, EdgeState edgeEnable ) - { - cccr.Compare = compareEnable; - cccr.Complement = compareMethod; - cccr.Threshold = threshold; - cccr.Edge = edgeEnable; - pme->WriteMSR( cccrPort, cccr.flat ); - } - - void SetOverflowEnables( P4ForceOverflow overflowEnable, P4OverflowInterrupt overflowInterruptEnable ) - { - cccr.FORCE_OVF = overflowEnable; - cccr.OVF_PMI = overflowInterruptEnable; - pme->WriteMSR( cccrPort, cccr.flat ); - } - - void SetOverflow() - { - cccr.OVF = 1; - pme->WriteMSR( cccrPort, cccr.flat ); - } - - void ClearOverflow() - { - cccr.OVF = 0; - pme->WriteMSR( cccrPort, cccr.flat ); - } - - bool isOverflow() - { - CCCR cccr_temp; - pme->ReadMSR( cccrPort, &cccr_temp.flat ); - return cccr_temp.OVF; - } - - void SetCascade() - { - cccr.Cascade = 1; - pme->WriteMSR( cccrPort, cccr.flat ); - } - - void ClearCascade() - { - cccr.Cascade = 0; - pme->WriteMSR( cccrPort, cccr.flat ); - } -}; -#pragma warning( default : 4035 ) - -#include "EventMasks.h" -#include "EventModes.h" - -#endif // P4PERFORMANCECOUNTERS_H diff --git a/public/tier0/P5P6PerformanceCounters.h b/public/tier0/P5P6PerformanceCounters.h deleted file mode 100644 index 6e2d8b144..000000000 --- a/public/tier0/P5P6PerformanceCounters.h +++ /dev/null @@ -1,225 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef P5P6PERFORMANCECOUNTERS_H -#define P5P6PERFORMANCECOUNTERS_H - -// defined for < Pentium 4 - -//--------------------------------------------------------------------------- -// Format of the performance event IDs within this header file in case you -// wish to add any additional events that may not be present here. -// -// BITS 0-8 Unit Mask, Unsed on P5 processors -// BIT 9 Set if event can be set on counter 0 -// BIT 10 Set if event can be set on counter 1 -// BITS 11-15 Unused Set to zero -// BITS 16-23 Event Select ID, Only bits 16-21 used on P5 Family -// BITS 24-27 Unused set to zero -// BITS 28-32 Process family that the event belong to, as returned by -// the CPUID instruction. -//--------------------------------------------------------------------------- - -//--------------------------------------------------------------------------- -// PENTIUM PERFORMANCE COUNTERS. -//--------------------------------------------------------------------------- -#define P5_DTCRD 0x50000300 //Data Cache Reads -#define P5_DWRIT 0x50010300 //Data Cache Writes -#define P5_DTTLB 0x50020300 //Data TLB Miss -#define P5_DTRMS 0x50030300 //Data Read Misses -#define P5_DWRMS 0x50040300 //Data Write Miss -#define P5_WHLCL 0x50050300 //Write (Hit) to M- or E-state line -#define P5_DCLWB 0x50060300 //Data Cache Lines Written Back -#define P5_DCSNP 0x50070300 //External Snoops -#define P5_DCSHT 0x50080300 //Data Cache Snoop Hits -#define P5_MAIBP 0x50090300 //Memory Access in Both Pipes -#define P5_BANKS 0x500A0300 //Bank Conflicts -#define P5_MISAL 0x500B0300 //Misaligned Data Memory Reference -#define P5_COCRD 0x500C0300 //Code Cache Reads -#define P5_COTLB 0x500D0300 //Code TLB Misses -#define P5_COCMS 0x500E0300 //Code Cache Misses -#define P5_ANYSG 0x500F0300 //Any Segment Register Loaded -#define P5_BRANC 0x50120300 //Branches -#define P5_BTBHT 0x50130300 //BTB Hits -#define P5_TBRAN 0x50140300 //Taken Branch or BTB hit -#define P5_PFLSH 0x50150300 //Pipeline flushes -#define P5_INSTR 0x50160300 //Instructions Executed -#define P5_INSTV 0x50170300 //Instructions Executed in the V-Pipe (Pairing) -#define P5_CLOCL 0x50180300 //Bus active -#define P5_PSDWR 0x50190300 //Full write buffers -#define P5_PSWDR 0x501A0300 //Waiting for Data Memory Read -#define P5_NCLSW 0x501B0300 //Clocks stalled writing an E or M state line -#define P5_IORWC 0x501D0300 //I/O Read or Write Cycle -#define P5_NOCMR 0x501E0300 //Non-Cacheable Memory Reads -#define P5_PSLDA 0x501F0300 //Clocks stalled due to AGI -#define P5_FLOPS 0x50220300 //Floating Point Operations -#define P5_DBGR0 0x50230300 //Breakpoint match on DR0 -#define P5_DBGR1 0x50240300 //Breakpoint match on DR1 -#define P5_DBGR2 0x50250300 //Breakpoint match on DR2 -#define P5_DBGR3 0x50260300 //Breakpoint match on DR3 -#define P5_HWINT 0x50270300 //Hardware interrupts -#define P5_DTRWR 0x50280300 //Data reads or writes -#define P5_DTRWM 0x50290300 //Data read or write miss -#define P5_BOLAT 0x502A0100 //Bus ownership latency -#define P5_BOTFR 0x502A0200 //Bus ownership transfer -#define P5_MMXA1 0x502B0100 //MMX Instruction Executed in U-pipe -#define P5_MMXA2 0x502B0200 //MMX Instruction Executed in V-pipe -#define P5_MMXMS 0x502C0100 //Cache M state line sharing -#define P5_MMSLS 0x502C0200 //Cache line sharing -#define P5_MMXB1 0x502D0100 //EMMS Instructions Executed -#define P5_MMXB2 0x502D0200 //Transition from MMX to FP instructions -#define P5_NOCMW 0x502E0200 //Non-Cacheable Memory Writes -#define P5_MMXC1 0x502F0100 //Saturated MMX Instructions Executed -#define P5_MMXC2 0x502F0200 //Saturations Performed -#define P5_MMXHS 0x50300100 //Cycles Not in HALT State -#define P5_MMXD2 0x50310100 //MMX Data Read -#define P5_MMXFP 0x50320100 //Floating Point Stalls -#define P5_MMXTB 0x50320200 //Taken Branches -#define P5_MMXD0 0x50330100 //D1 Starvation and FIFO Empty -#define P5_MMXD1 0x50330200 //D1 Starvation and one instruction in FIFO -#define P5_MMXE1 0x50340100 //MMX Data Writes -#define P5_MMXE2 0x50340200 //MMX Data Write Misses -#define P5_MMXWB 0x50350100 //Pipeline flushes, wrong branch prediction -#define P5_MMXWJ 0x50350200 //Pipeline flushes, branch prediction WB-stage -#define P5_MMXF1 0x50360100 //Misaligned MMX Data Memory Reference -#define P5_MMXF2 0x50360200 //Pipeline Stalled Waiting for MMX data read -#define P5_MMXRI 0x50370100 //Returns Predicted Incorrectly -#define P5_MMXRP 0x50370200 //Returns Predicted -#define P5_MMXG1 0x50380100 //MMX Multiply Unit Interlock -#define P5_MMXG2 0x50380200 //MOVD/MOVQ store stall, previous operation -#define P5_MMXRT 0x50390100 //Returns -#define P5_MMXRO 0x50390200 //RSB Overflows -#define P5_MMXBF 0x503A0100 //BTB False entries -#define P5_MMXBM 0x503A0200 //BTB misprediction on a Not-Taken Branch -#define P5_PXDWR 0x503B0100 //stalled due MMX Full write buffers -#define P5_PXZWR 0x503B0200 //stalled on MMX write to E or M state line - -#define P5_CLOCK 0x503F0300 //Special value to count clocks on P5 - - -//--------------------------------------------------------------------------- -// PENTIUM PRO / PENTIUM II PERFORMANCE COUNTERS. -//--------------------------------------------------------------------------- -#define P6_STRBB 0x60030300 //Store Buffer Block -#define P6_STBDC 0x60040300 //Store Buffer Drain Cycles -#define P6_MISMM 0x60050300 //Misaligned Data Memory Reference -#define P6_SEGLD 0x60060300 //Segment register loads -#define P6_FPOPE 0x60100100 //FP Computational Op. (COUNTER 0 ONLY) -#define P6_FPEOA 0x60110200 //FP Microcode Exceptions (COUNTER 1 ONLY) -#define P6_FMULT 0x60120200 //Multiplies (COUNTER 1 ONLY) -#define P6_FPDIV 0x60130200 //Divides (COUNTER 1 ONLY) -#define P6_DBUSY 0x60140200 //Cycles Divider Busy (COUNTER 1 ONLY) -#define P6_L2STR 0x60210300 //L2 address strobes => address bus utilization -#define P6_L2BBS 0x60220300 //Cycles L2 Bus Busy -#define P6_L2BBT 0x60230300 //Cycles L2 Bus Busy transferring data to CPU -#define P6_L2ALO 0x60240300 //L2 Lines Allocated -#define P6_L2MAL 0x60250300 //L2 M-state Lines Allocated -#define P6_L2CEV 0x60260300 //L2 Lines Evicted -#define P6_L2MEV 0x60270300 //L2 M-state Lines Evicted -#define P6_L2MCF 0x60280301 //L2 Cache Instruction Fetch Misses -#define P6_L2FET 0x6028030F //L2 Cache Instruction Fetches -#define P6_L2DRM 0x60290301 //L2 Cache Read Misses -#define P6_L2DMR 0x6029030F //L2 Cache Reads -#define P6_L2DWM 0x602A0301 //L2 Cache Write Misses -#define P6_L2DMW 0x602A030F //L2 Cache Writes -#define P6_L2CMS 0x602E0301 //L2 Cache Request Misses -#define P6_L2DCR 0x602E030F //L2 Cache Requests -#define P6_DMREF 0x60430300 //Data Memory References -#define P6_DCALO 0x6045030F //L1 Lines Allocated -#define P6_DCMAL 0x60460300 //L1 M-state Data Cache Lines Allocated -#define P6_DCMEV 0x60470300 //L1 M-state Data Cache Lines Evicted -#define P6_DCOUT 0x60480300 //L1 Misses outstanding -#define P6_TSMCD 0x60520300 //Time Self-Modifiying Code Detected -#define P6_BRWRA 0x60600300 //External Bus Cycles While Receive Active -#define P6_BRDCD 0x60600300 //External Bus Request Outstanding -#define P6_BRBNR 0x60610300 //External Bus Cycles While BNR Asserted -#define P6_BUSBS 0x60620300 //External Bus Cycles-DRDY Asserted (busy) -#define P6_BLOCK 0x60630300 //External Bus Cycles-LOCK signal asserted -#define P6_BBRCV 0x60640300 //External Bus Cycles-Processor receiving data -#define P6_BURST 0x60650300 //External Bus Burst Read Operations -#define P6_BRINV 0x60660300 //External Bus Read for Ownership Transaction -#define P6_BMLEV 0x60670300 //External Bus Writeback M-state Evicted -#define P6_BBIFT 0x60680300 //External Bus Burst Instruction Fetches -#define P6_BINVL 0x60690300 //External Bus Invalidate Transactions -#define P6_BPRBT 0x606A0300 //External Bus Partial Read Transactions -#define P6_BPTMO 0x606B0300 //External Bus Partial Memory Transactions -#define P6_BUSIO 0x606C0300 //External Bus I/O Bus Transactions -#define P6_BUSDF 0x606D0300 //External Bus Deferred Transactions -#define P6_BUSTB 0x606E0300 //External Bus Burst Transactions -#define P6_BMALL 0x606F0300 //External Bus Memory Transactions -#define P6_BSALL 0x60700300 //External Bus Transactions -#define P6_CLOCK 0x60790300 //Clockticks -#define P6_BRHIT 0x607A0300 //External Bus Cycles While HIT Asserted -#define P6_BRHTM 0x607B0300 //External Bus Cycles While HITM Asserted -#define P6_BRSST 0x607E0300 //External Bus Cycles While Snoop Stalled -#define P6_CMREF 0x60800300 //Total Instruction Fetches -#define P6_TOIFM 0x60810300 //Total Instruction Fetch Misses -#define P6_INTLB 0x60850300 //Instructions TLB Misses -#define P6_CSFET 0x60860300 //Cycles Instruction Fetch Stalled -#define P6_FTSTL 0x60870300 //Cycles Instruction Fetch stalled -#define P6_RSTAL 0x60A20300 //Resource Related Stalls -#define P6_MMXIE 0x60B00300 //MMX Instructions Executed -#define P6_SAISE 0x60B10300 //Saturated Arithmetic Instructions Executed -#define P6_PORT0 0x60B20301 //MMX micro-ops executed on Port 0 -#define P6_PORT1 0x60B20302 //MMX micro-ops executed on Port 1 -#define P6_PORT2 0x60B20304 //MMX micro-ops executed on Port 2 -#define P6_PORT3 0x60B20308 //MMX micro-ops executed on Port 3 -#define P6_MMXPA 0x60B30300 //MMX Packed Arithmetic -#define P6_MMXPM 0x60B30301 //MMX Packed Multiply -#define P6_MMXPS 0x60B30302 //MMX Packed Shift -#define P6_MMXPO 0x60B30304 //MMX Packed Operations -#define P6_MMXUO 0x60B30308 //MMX Unpacked Operations -#define P6_MMXPL 0x60B30310 //MMX Packed Logical -#define P6_INSTR 0x60C00300 //Instructions Retired -#define P6_FPOPS 0x60C10100 //FP operations retired (COUNTER 0 ONLY) -#define P6_UOPSR 0x60C20300 //Micro-Ops Retired -#define P6_BRRET 0x60C40300 //Branch Instructions Retired -#define P6_BRMSR 0x60C50300 //Branch Mispredictions Retired -#define P6_MASKD 0x60C60300 //Clocks while interrupts masked -#define P6_MSKPN 0x60C70300 //Clocks while interrupt is pending -#define P6_HWINT 0x60C80300 //Hardware Interrupts Received -#define P6_BTAKR 0x60C90300 //Taken Branch Retired -#define P6_BTAKM 0x60CA0300 //Taken Branch Mispredictions -#define P6_FPMMX 0x60CC0301 //Transitions from Floating Point to MMX -#define P6_MMXFP 0x60CC0300 //Transitions from MMX to Floating Point -#define P6_SIMDA 0x60CD0300 //SIMD Assists (EMMS Instructions Executed) -#define P6_MMXIR 0x60CE0300 //MMX Instructions Retired -#define P6_SAISR 0x60CF0300 //Saturated Arithmetic Instructions Retired -#define P6_INSTD 0x60D00300 //Instructions Decoded -#define P6_NPRTL 0x60D20300 //Renaming Stalls -#define P6_SRSES 0x60D40301 //Segment Rename Stalls - ES -#define P6_SRSDS 0x60D40302 //Segment Rename Stalls - DS -#define P6_SRSFS 0x60D40304 //Segment Rename Stalls - FS -#define P6_SRSGS 0x60D40308 //Segment Rename Stalls - GS -#define P6_SRSXS 0x60D4030F //Segment Rename Stalls - ES DS FS GS -#define P6_SRNES 0x60D50301 //Segment Renames - ES -#define P6_SRNDS 0x60D50302 //Segment Renames - DS -#define P6_SRNFS 0x60D50304 //Segment Renames - FS -#define P6_SRNGS 0x60D50308 //Segment Renames - GS -#define P6_SRNXS 0x60D5030F //Segment Renames - ES DS FS GS -#define P6_BRDEC 0x60E00300 //Branch Instructions Decoded -#define P6_BTBMS 0x60E20301 //BTB Misses -#define P6_RETDC 0x60E40300 //Bogus Branches -#define P6_BACLR 0x60E60300 //BACLEARS Asserted (Testing) - - - - - - -// INTEL -#define PENTIUM_FAMILY 5 // define for pentium -#define PENTIUMPRO_FAMILY 6 // define for pentium pro -#define PENTIUM4_FAMILY 15 // define for pentium 4 - - -// AMD -#define K6_FAMILY 5 -#define K8_FAMILY 6 -#define EXTENDED_FAMILY 15 // AMD 64 and AMD Opteron - -#endif // P5P6PERFORMANCECOUNTERS_H diff --git a/public/tier0/PMELib.h b/public/tier0/PMELib.h deleted file mode 100644 index 59b3fc174..000000000 --- a/public/tier0/PMELib.h +++ /dev/null @@ -1,195 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef PMELIB_H -#define PMELIB_H - -#include "Windows.h" -#include "tier0/platform.h" - -// Get rid of a bunch of STL warnings! -#pragma warning( push, 3 ) -#pragma warning( disable : 4018 ) - -#define VERSION "1.0.2" - -// uncomment this list to add some runtime checks -//#define PME_DEBUG - -#include "tier0/valve_off.h" -#include -#include "tier0/valve_on.h" - -using namespace std; - -// RDTSC Instruction macro -#define RDTSC(var) \ -_asm RDTSC \ -_asm mov DWORD PTR var,eax \ -_asm mov DWORD PTR var+4,edx - -// RDPMC Instruction macro -#define RDPMC(counter, var) \ -_asm mov ecx, counter \ -_asm RDPMC \ -_asm mov DWORD PTR var,eax \ -_asm mov DWORD PTR var+4,edx - -// RDPMC Instruction macro, for performance counter 1 (ecx = 1) -#define RDPMC0(var) \ -_asm mov ecx, 0 \ -_asm RDPMC \ -_asm mov DWORD PTR var,eax \ -_asm mov DWORD PTR var+4,edx - -#define RDPMC1(var) \ -_asm mov ecx, 1 \ -_asm RDPMC \ -_asm mov DWORD PTR var,eax \ -_asm mov DWORD PTR var+4,edx - -#define EVENT_TYPE(mode) EventType##mode -#define EVENT_MASK(mode) EventMask##mode - -#include "ia32detect.h" - -enum ProcessPriority -{ - ProcessPriorityNormal, - ProcessPriorityHigh, -}; - -enum PrivilegeCapture -{ - OS_Only, // ring 0, kernel level - USR_Only, // app level - OS_and_USR, // all levels -}; - -enum CompareMethod -{ - CompareGreater, // - CompareLessEqual, // -}; - -enum EdgeState -{ - RisingEdgeDisabled, // - RisingEdgeEnabled, // -}; - -enum CompareState -{ - CompareDisable, // - CompareEnable, // -}; - -// Singletion Class -class PME : public ia32detect -{ -public: -//private: - - static PME* _singleton; - - HANDLE hFile; - bool bDriverOpen; - double m_CPUClockSpeed; - - //ia32detect detect; - HRESULT Init(); - HRESULT Close(); - -protected: - - PME() - { - hFile = NULL; - bDriverOpen = FALSE; - m_CPUClockSpeed = 0; - Init(); - } - -public: - - static PME* Instance(); // gives back a real object - - ~PME() - { - Close(); - } - - double GetCPUClockSpeedSlow( void ); - double GetCPUClockSpeedFast( void ); - - HRESULT SelectP5P6PerformanceEvent( uint32 dw_event, uint32 dw_counter, bool b_user, bool b_kernel ); - - HRESULT ReadMSR( uint32 dw_reg, int64 * pi64_value ); - HRESULT ReadMSR( uint32 dw_reg, uint64 * pi64_value ); - - HRESULT WriteMSR( uint32 dw_reg, const int64 & i64_value ); - HRESULT WriteMSR( uint32 dw_reg, const uint64 & i64_value ); - - void SetProcessPriority( ProcessPriority priority ) - { - switch( priority ) - { - case ProcessPriorityNormal: - { - SetPriorityClass (GetCurrentProcess(),NORMAL_PRIORITY_CLASS); - SetThreadPriority (GetCurrentThread(),THREAD_PRIORITY_NORMAL); - break; - } - case ProcessPriorityHigh: - { - SetPriorityClass (GetCurrentProcess(),REALTIME_PRIORITY_CLASS); - SetThreadPriority (GetCurrentThread(),THREAD_PRIORITY_HIGHEST); - break; - } - } - } - - //--------------------------------------------------------------------------- - // Return the family of the processor - //--------------------------------------------------------------------------- - CPUVendor GetVendor(void) - { - return vendor; - } - - int GetProcessorFamily(void) - { - return version.Family; - } - -#ifdef DBGFLAG_VALIDATE - void Validate( CValidator &validator, tchar *pchName ); // Validate our internal structures -#endif // DBGFLAG_VALIDATE - -}; - -#include "P5P6PerformanceCounters.h" -#include "P4PerformanceCounters.h" -#include "K8PerformanceCounters.h" - -enum PerfErrors -{ - E_UNKNOWN_CPU_VENDOR = -1, - E_BAD_COUNTER = -2, - E_UNKNOWN_CPU = -3, - E_CANT_OPEN_DRIVER = -4, - E_DRIVER_ALREADY_OPEN = -5, - E_DRIVER_NOT_OPEN = -6, - E_DISABLED = -7, - E_BAD_DATA = -8, - E_CANT_CLOSE = -9, - E_ILLEGAL_OPERATION = -10, -}; - -#pragma warning( pop ) - -#endif // PMELIB_H diff --git a/public/tier0/afxmem_override.cpp b/public/tier0/afxmem_override.cpp deleted file mode 100644 index f19cf2eac..000000000 --- a/public/tier0/afxmem_override.cpp +++ /dev/null @@ -1,460 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -// File extracted from MFC due to symbol conflicts - -// This is a part of the Microsoft Foundation Classes C++ library. -// Copyright (C) Microsoft Corporation -// All rights reserved. -// -// This source code is only intended as a supplement to the -// Microsoft Foundation Classes Reference and related -// electronic documentation provided with the library. -// See these sources for detailed information regarding the -// Microsoft Foundation Classes product. - -#include "stdafx.h" - -#ifdef AFX_CORE1_SEG -#pragma code_seg(AFX_CORE1_SEG) -#endif - - -///////////////////////////////////////////////////////////////////////////// -// Debug memory globals and implementation helpers - -#ifdef _DEBUG // most of this file is for debugging - -void* __cdecl operator new(size_t nSize, int nType, LPCSTR lpszFileName, int nLine); -#if _MSC_VER >= 1210 -void* __cdecl operator new[](size_t nSize, int nType, LPCSTR lpszFileName, int nLine); -#endif - -///////////////////////////////////////////////////////////////////////////// -// test allocation routines - -void* PASCAL CObject::operator new(size_t nSize) -{ -#ifdef _AFX_NO_DEBUG_CRT - return ::operator new(nSize); -#else - return ::operator new(nSize, _AFX_CLIENT_BLOCK, NULL, 0); -#endif // _AFX_NO_DEBUG_CRT -} - -void PASCAL CObject::operator delete(void* p) -{ -#ifdef _AFX_NO_DEBUG_CRT - free(p); -#else - _free_dbg(p, _AFX_CLIENT_BLOCK); -#endif -} - -#if _MSC_VER >= 1200 -void PASCAL CObject::operator delete(void* p, void*) -{ -#ifdef _AFX_NO_DEBUG_CRT - free(p); -#else - _free_dbg(p, _AFX_CLIENT_BLOCK); -#endif -} -#endif - -#ifndef _AFX_NO_DEBUG_CRT - -void* __cdecl operator new(size_t nSize, LPCSTR lpszFileName, int nLine) -{ - return ::operator new(nSize, _NORMAL_BLOCK, lpszFileName, nLine); -} - -#if _MSC_VER >= 1210 -void* __cdecl operator new[](size_t nSize, LPCSTR lpszFileName, int nLine) -{ - return ::operator new[](nSize, _NORMAL_BLOCK, lpszFileName, nLine); -} -#endif - -#if _MSC_VER >= 1200 -void __cdecl operator delete(void* pData, LPCSTR /* lpszFileName */, - int /* nLine */) -{ - ::operator delete(pData); -} -#endif - -#if _MSC_VER >= 1210 -void __cdecl operator delete[](void* pData, LPCSTR /* lpszFileName */, - int /* nLine */) -{ - ::operator delete(pData); -} -#endif - -void* PASCAL -CObject::operator new(size_t nSize, LPCSTR lpszFileName, int nLine) -{ - return ::operator new(nSize, _AFX_CLIENT_BLOCK, lpszFileName, nLine); -} - -#if _MSC_VER >= 1200 -void PASCAL -CObject::operator delete(void *pObject, LPCSTR /* lpszFileName */, - int /* nLine */) -{ -#ifdef _AFX_NO_DEBUG_CRT - free(pObject); -#else - _free_dbg(pObject, _AFX_CLIENT_BLOCK); -#endif -} -#endif - -void* AFXAPI AfxAllocMemoryDebug(size_t nSize, BOOL bIsObject, LPCSTR lpszFileName, int nLine) -{ - return _malloc_dbg(nSize, bIsObject ? _AFX_CLIENT_BLOCK : _NORMAL_BLOCK, - lpszFileName, nLine); -} - -void AFXAPI AfxFreeMemoryDebug(void* pbData, BOOL bIsObject) -{ - _free_dbg(pbData, bIsObject ? _AFX_CLIENT_BLOCK : _NORMAL_BLOCK); -} - -///////////////////////////////////////////////////////////////////////////// -// allocation failure hook, tracking turn on - -BOOL AFXAPI _AfxDefaultAllocHook(size_t, BOOL, LONG) - { return TRUE; } - -AFX_STATIC_DATA AFX_ALLOC_HOOK pfnAllocHook = _AfxDefaultAllocHook; - -AFX_STATIC_DATA _CRT_ALLOC_HOOK pfnCrtAllocHook = NULL; -#if _MSC_VER >= 1200 -int __cdecl _AfxAllocHookProxy(int nAllocType, void * pvData, size_t nSize, - int nBlockUse, long lRequest, const unsigned char * szFilename, int nLine) -#else -int __cdecl _AfxAllocHookProxy(int nAllocType, void * pvData, size_t nSize, - int nBlockUse, long lRequest, const char * szFilename, int nLine) -#endif -{ -#if _MSC_VER >= 1200 - if (nAllocType != _HOOK_ALLOC) - return (pfnCrtAllocHook)(nAllocType, pvData, nSize, - nBlockUse, lRequest, (const unsigned char*) szFilename, nLine); - if ((pfnAllocHook)(nSize, _BLOCK_TYPE(nBlockUse) == _AFX_CLIENT_BLOCK, lRequest)) - return (pfnCrtAllocHook)(nAllocType, pvData, nSize, - nBlockUse, lRequest, (const unsigned char*) szFilename, nLine); -#else - if (nAllocType != _HOOK_ALLOC) - return (pfnCrtAllocHook)(nAllocType, pvData, nSize, - nBlockUse, lRequest, szFilename, nLine); - if ((pfnAllocHook)(nSize, _BLOCK_TYPE(nBlockUse) == _AFX_CLIENT_BLOCK, lRequest)) - return (pfnCrtAllocHook)(nAllocType, pvData, nSize, - nBlockUse, lRequest, szFilename, nLine); -#endif - return FALSE; -} - -AFX_ALLOC_HOOK AFXAPI AfxSetAllocHook(AFX_ALLOC_HOOK pfnNewHook) -{ - if (pfnCrtAllocHook == NULL) - pfnCrtAllocHook = _CrtSetAllocHook(_AfxAllocHookProxy); - - AFX_ALLOC_HOOK pfnOldHook = pfnAllocHook; - pfnAllocHook = pfnNewHook; - return pfnOldHook; -} - -// This can be set to TRUE to override all AfxEnableMemoryTracking calls, -// allowing all allocations, even MFC internal allocations to be tracked. -BOOL _afxMemoryLeakOverride = FALSE; - -BOOL AFXAPI AfxEnableMemoryTracking(BOOL bTrack) -{ - if (_afxMemoryLeakOverride) - return TRUE; - - int nOldState = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); - if (bTrack) - _CrtSetDbgFlag(nOldState | _CRTDBG_ALLOC_MEM_DF); - else - _CrtSetDbgFlag(nOldState & ~_CRTDBG_ALLOC_MEM_DF); - return nOldState & _CRTDBG_ALLOC_MEM_DF; -} - -///////////////////////////////////////////////////////////////////////////// -// stop on a specific memory request - -// Obsolete API -void AFXAPI AfxSetAllocStop(LONG lRequestNumber) -{ - _CrtSetBreakAlloc(lRequestNumber); -} - -BOOL AFXAPI AfxCheckMemory() - // check all of memory (look for memory tromps) -{ - return _CrtCheckMemory(); -} - -// -- true if block of exact size, allocated on the heap -// -- set *plRequestNumber to request number (or 0) -BOOL AFXAPI AfxIsMemoryBlock(const void* pData, UINT nBytes, - LONG* plRequestNumber) -{ - return _CrtIsMemoryBlock(pData, nBytes, plRequestNumber, NULL, NULL); -} - -///////////////////////////////////////////////////////////////////////////// -// CMemoryState - -CMemoryState::CMemoryState() -{ - memset(this, 0, sizeof(*this)); -} - -void CMemoryState::UpdateData() -{ - for(int i = 0; i < nBlockUseMax; i++) - { - m_lCounts[i] = m_memState.lCounts[i]; - m_lSizes[i] = m_memState.lSizes[i]; - } - m_lHighWaterCount = m_memState.lHighWaterCount; - m_lTotalCount = m_memState.lTotalCount; -} - -// fills 'this' with the difference, returns TRUE if significant -BOOL CMemoryState::Difference(const CMemoryState& oldState, - const CMemoryState& newState) -{ - int nResult = _CrtMemDifference(&m_memState, &oldState.m_memState, &newState.m_memState); - UpdateData(); - return nResult != 0; -} - -void CMemoryState::DumpStatistics() const -{ - _CrtMemDumpStatistics(&m_memState); -} - -// -- fill with current memory state -void CMemoryState::Checkpoint() -{ - _CrtMemCheckpoint(&m_memState); - UpdateData(); -} - -// Dump objects created after this memory state was checkpointed -// Will dump all objects if this memory state wasn't checkpointed -// Dump all objects, report about non-objects also -// List request number in {} -void CMemoryState::DumpAllObjectsSince() const -{ - _CrtMemDumpAllObjectsSince(&m_memState); -} - -///////////////////////////////////////////////////////////////////////////// -// Enumerate all objects allocated in the diagnostic memory heap - -struct _AFX_ENUM_CONTEXT -{ - void (*m_pfn)(CObject*,void*); - void* m_pContext; -}; - -AFX_STATIC void _AfxDoForAllObjectsProxy(void* pObject, void* pContext) -{ - _AFX_ENUM_CONTEXT* p = (_AFX_ENUM_CONTEXT*)pContext; - (*p->m_pfn)((CObject*)pObject, p->m_pContext); -} - -void AFXAPI -AfxDoForAllObjects(void (AFX_CDECL *pfn)(CObject*, void*), void* pContext) -{ - if (pfn == NULL) - { - AfxThrowInvalidArgException(); - } - _AFX_ENUM_CONTEXT context; - context.m_pfn = pfn; - context.m_pContext = pContext; - _CrtDoForAllClientObjects(_AfxDoForAllObjectsProxy, &context); -} - -///////////////////////////////////////////////////////////////////////////// -// Automatic debug memory diagnostics - -BOOL AFXAPI AfxDumpMemoryLeaks() -{ - return _CrtDumpMemoryLeaks(); -} - -#endif // _AFX_NO_DEBUG_CRT -#endif // _DEBUG - -///////////////////////////////////////////////////////////////////////////// -// Non-diagnostic memory routines - -int AFX_CDECL AfxNewHandler(size_t /* nSize */) -{ - AfxThrowMemoryException(); -} - -#pragma warning(disable: 4273) - -#ifndef _AFXDLL -_PNH _afxNewHandler = &AfxNewHandler; -#endif - -_PNH AFXAPI AfxGetNewHandler(void) -{ -#ifdef _AFXDLL - AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState(); - return pState->m_pfnNewHandler; -#else - return _afxNewHandler; -#endif -} - -_PNH AFXAPI AfxSetNewHandler(_PNH pfnNewHandler) -{ -#ifdef _AFXDLL - AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState(); - _PNH pfnOldHandler = pState->m_pfnNewHandler; - pState->m_pfnNewHandler = pfnNewHandler; - return pfnOldHandler; -#else - _PNH pfnOldHandler = _afxNewHandler; - _afxNewHandler = pfnNewHandler; - return pfnOldHandler; -#endif -} - -AFX_STATIC_DATA const _PNH _pfnUninitialized = (_PNH)-1; - -void* __cdecl operator new(size_t nSize) -{ - void* pResult; -#ifdef _AFXDLL - _PNH pfnNewHandler = _pfnUninitialized; -#endif - for (;;) - { -#if !defined(_AFX_NO_DEBUG_CRT) && defined(_DEBUG) - pResult = _malloc_dbg(nSize, _NORMAL_BLOCK, NULL, 0); -#else - pResult = malloc(nSize); -#endif - if (pResult != NULL) - return pResult; - -#ifdef _AFXDLL - if (pfnNewHandler == _pfnUninitialized) - { - AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState(); - pfnNewHandler = pState->m_pfnNewHandler; - } - if (pfnNewHandler == NULL || (*pfnNewHandler)(nSize) == 0) - break; -#else - if (_afxNewHandler == NULL || (*_afxNewHandler)(nSize) == 0) - break; -#endif - } - return pResult; -} - -void __cdecl operator delete(void* p) -{ -#if !defined(_AFX_NO_DEBUG_CRT) && defined(_DEBUG) - _free_dbg(p, _NORMAL_BLOCK); -#else - free(p); -#endif -} - -#if _MSC_VER >= 1210 -void* __cdecl operator new[](size_t nSize) -{ - return ::operator new(nSize); -} - -void __cdecl operator delete[](void* p) -{ - ::operator delete(p); -} -#endif - -#ifdef _DEBUG - -void* __cdecl operator new(size_t nSize, int nType, LPCSTR lpszFileName, int nLine) -{ -#ifdef _AFX_NO_DEBUG_CRT - UNUSED_ALWAYS(nType); - UNUSED_ALWAYS(lpszFileName); - UNUSED_ALWAYS(nLine); - return ::operator new(nSize); -#else - void* pResult; -#ifdef _AFXDLL - _PNH pfnNewHandler = _pfnUninitialized; -#endif - for (;;) - { - pResult = _malloc_dbg(nSize, nType, lpszFileName, nLine); - if (pResult != NULL) - return pResult; - -#ifdef _AFXDLL - if (pfnNewHandler == _pfnUninitialized) - { - AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState(); - pfnNewHandler = pState->m_pfnNewHandler; - } - if (pfnNewHandler == NULL || (*pfnNewHandler)(nSize) == 0) - break; -#else - if (_afxNewHandler == NULL || (*_afxNewHandler)(nSize) == 0) - break; -#endif - } - return pResult; -#endif -} - -#if 0 -#if _MSC_VER >= 1200 -void __cdecl operator delete(void* p, int nType, LPCSTR /* lpszFileName */, int /* nLine */) -{ -#if !defined(_AFX_NO_DEBUG_CRT) && defined(_DEBUG) - _free_dbg(p, nType); -#else - free(p); -#endif -} -#endif // _MSC_VER >= 1200 -#endif - -#if _MSC_VER >= 1210 -void* __cdecl operator new[](size_t nSize, int nType, LPCSTR lpszFileName, int nLine) -{ - return ::operator new(nSize, nType, lpszFileName, nLine); -} -#if 0 -void __cdecl operator delete[](void* p, int nType, LPCSTR lpszFileName, int nLine) -{ - ::operator delete(p, nType, lpszFileName, nLine); -} -#endif -#endif // _MSC_VER >= 1210 - -#endif //_DEBUG - -///////////////////////////////////////////////////////////////////////////// diff --git a/public/tier0/basetypes.h b/public/tier0/basetypes.h deleted file mode 100644 index 712f48450..000000000 --- a/public/tier0/basetypes.h +++ /dev/null @@ -1,395 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef BASETYPES_H -#define BASETYPES_H - -#include "tier0/platform.h" -#include "commonmacros.h" -#include "wchartypes.h" - -#include "tier0/valve_off.h" - -#ifdef _WIN32 -#pragma once -#endif - - -#include "protected_things.h" - -// There's a different version of this file in the xbox codeline -// so the PC version built in the xbox branch includes things like -// tickrate changes. -#include "xbox_codeline_defines.h" - -#ifdef IN_XBOX_CODELINE -#define XBOX_CODELINE_ONLY() -#else -#define XBOX_CODELINE_ONLY() Error_Compiling_Code_Only_Valid_in_Xbox_Codeline -#endif - -// stdio.h -#ifndef NULL -#define NULL 0 -#endif - -#if defined _LINUX && !defined __APPLE__ -typedef unsigned int uintptr_t; -#elif defined __APPLE__ -#include -#endif - -#define ExecuteNTimes( nTimes, x ) \ - { \ - static int __executeCount=0;\ - if ( __executeCount < nTimes )\ - { \ - x; \ - ++__executeCount; \ - } \ - } - - -#define ExecuteOnce( x ) ExecuteNTimes( 1, x ) - - -template -inline T AlignValue( T val, unsigned alignment ) -{ - return (T)( ( (uintptr_t)val + alignment - 1 ) & ~( alignment - 1 ) ); -} - - -// Pad a number so it lies on an N byte boundary. -// So PAD_NUMBER(0,4) is 0 and PAD_NUMBER(1,4) is 4 -#define PAD_NUMBER(number, boundary) \ - ( ((number) + ((boundary)-1)) / (boundary) ) * (boundary) - -// In case this ever changes -#if defined M_PI -# undef M_PI -#endif -#define M_PI 3.14159265358979323846 - -// #define COMPILETIME_MAX and COMPILETIME_MIN for max/min in constant expressions -#define COMPILETIME_MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) ) -#define COMPILETIME_MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) -#ifndef MIN -#define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) ) -#endif - -#ifndef MAX -#define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) -#endif - -#if !defined(_X360) -FORCEINLINE float fpmin( float a, float b ) -{ - return ( a < b ) ? a : b; -} - -FORCEINLINE float fpmax( float a, float b ) -{ - return ( a > b ) ? a : b; -} -#endif - -#ifdef __cplusplus - template< class T > - inline T clamp( T const &val, T const &minVal, T const &maxVal ) - { - if( val < minVal ) - return minVal; - else if( val > maxVal ) - return maxVal; - else - return val; - } -#endif - -#ifndef FALSE -#define FALSE 0 -#define TRUE (!FALSE) -#endif - - -typedef int BOOL; -typedef int qboolean; -typedef unsigned long ULONG; -typedef unsigned char BYTE; -typedef unsigned char byte; -typedef unsigned short word; - -#if !defined __APPLE__ -typedef unsigned int uintptr_t; -#endif - - -enum ThreeState_t -{ - TRS_FALSE, - TRS_TRUE, - TRS_NONE, -}; - -typedef float vec_t; - - -// FIXME: this should move -#ifndef __cplusplus -#define true TRUE -#define false FALSE -#endif - -//----------------------------------------------------------------------------- -// look for NANs, infinities, and underflows. -// This assumes the ANSI/IEEE 754-1985 standard -//----------------------------------------------------------------------------- - -#ifdef __cplusplus - -inline unsigned long& FloatBits( vec_t& f ) -{ - return *reinterpret_cast(&f); -} - -inline unsigned long const& FloatBits( vec_t const& f ) -{ - return *reinterpret_cast(&f); -} - -inline vec_t BitsToFloat( unsigned long i ) -{ - return *reinterpret_cast(&i); -} - -inline bool IsFinite( vec_t f ) -{ - return ((FloatBits(f) & 0x7F800000) != 0x7F800000); -} - -inline unsigned long FloatAbsBits( vec_t f ) -{ - return FloatBits(f) & 0x7FFFFFFF; -} - -inline float FloatMakeNegative( vec_t f ) -{ - return BitsToFloat( FloatBits(f) | 0x80000000 ); -} - -#if defined( WIN32 ) - -//#include -// Just use prototype from math.h -#ifdef __cplusplus -extern "C" -{ -#endif - double __cdecl fabs(double); -#ifdef __cplusplus -} -#endif - -// In win32 try to use the intrinsic fabs so the optimizer can do it's thing inline in the code -#pragma intrinsic( fabs ) -// Also, alias float make positive to use fabs, too -// NOTE: Is there a perf issue with double<->float conversion? -inline float FloatMakePositive( vec_t f ) -{ - return (float)fabs( f ); -} -#else -inline float FloatMakePositive( vec_t f ) -{ - return BitsToFloat( FloatBits(f) & 0x7FFFFFFF ); -} -#endif - -inline float FloatNegate( vec_t f ) -{ - return BitsToFloat( FloatBits(f) ^ 0x80000000 ); -} - - -#define FLOAT32_NAN_BITS (unsigned long)0x7FC00000 // not a number! -#define FLOAT32_NAN BitsToFloat( FLOAT32_NAN_BITS ) - -#define VEC_T_NAN FLOAT32_NAN - -#endif - -// FIXME: why are these here? Hardly anyone actually needs them. -struct color24 -{ - byte r, g, b; -}; - -typedef struct color32_s -{ - bool operator!=( const struct color32_s &other ) const; - - byte r, g, b, a; -} color32; - -inline bool color32::operator!=( const color32 &other ) const -{ - return r != other.r || g != other.g || b != other.b || a != other.a; -} - -struct colorVec -{ - unsigned r, g, b, a; -}; - - -#ifndef NOTE_UNUSED -#define NOTE_UNUSED(x) (x = x) // for pesky compiler / lint warnings -#endif -#ifdef __cplusplus - -struct vrect_t -{ - int x,y,width,height; - vrect_t *pnext; -}; - -#endif - - -//----------------------------------------------------------------------------- -// MaterialRect_t struct - used for DrawDebugText -//----------------------------------------------------------------------------- -struct Rect_t -{ - int x, y; - int width, height; -}; - - -//----------------------------------------------------------------------------- -// Interval, used by soundemittersystem + the game -//----------------------------------------------------------------------------- -struct interval_t -{ - float start; - float range; -}; - - -//----------------------------------------------------------------------------- -// Declares a type-safe handle type; you can't assign one handle to the next -//----------------------------------------------------------------------------- - -// 32-bit pointer handles. - -// Typesafe 8-bit and 16-bit handles. -template< class HandleType > -class CBaseIntHandle -{ -public: - - inline bool operator==( const CBaseIntHandle &other ) { return m_Handle == other.m_Handle; } - inline bool operator!=( const CBaseIntHandle &other ) { return m_Handle != other.m_Handle; } - - // Only the code that doles out these handles should use these functions. - // Everyone else should treat them as a transparent type. - inline HandleType GetHandleValue() { return m_Handle; } - inline void SetHandleValue( HandleType val ) { m_Handle = val; } - - typedef HandleType HANDLE_TYPE; - -protected: - - HandleType m_Handle; -}; - -template< class DummyType > -class CIntHandle16 : public CBaseIntHandle< unsigned short > -{ -public: - inline CIntHandle16() {} - - static inline CIntHandle16 MakeHandle( HANDLE_TYPE val ) - { - return CIntHandle16( val ); - } - -protected: - inline CIntHandle16( HANDLE_TYPE val ) - { - m_Handle = val; - } -}; - - -template< class DummyType > -class CIntHandle32 : public CBaseIntHandle< unsigned long > -{ -public: - inline CIntHandle32() {} - - static inline CIntHandle32 MakeHandle( HANDLE_TYPE val ) - { - return CIntHandle32( val ); - } - -protected: - inline CIntHandle32( HANDLE_TYPE val ) - { - m_Handle = val; - } -}; - - -// NOTE: This macro is the same as windows uses; so don't change the guts of it -#define DECLARE_HANDLE_16BIT(name) typedef CIntHandle16< struct name##__handle * > name; -#define DECLARE_HANDLE_32BIT(name) typedef CIntHandle32< struct name##__handle * > name; - -#define DECLARE_POINTER_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name -#define FORWARD_DECLARE_HANDLE(name) typedef struct name##__ *name - -// @TODO: Find a better home for this -#if !defined(_STATIC_LINKED) && !defined(PUBLISH_DLL_SUBSYSTEM) -// for platforms built with dynamic linking, the dll interface does not need spoofing -#define PUBLISH_DLL_SUBSYSTEM() -#endif - -#define UID_PREFIX generated_id_ -#define UID_CAT1(a,c) a ## c -#define UID_CAT2(a,c) UID_CAT1(a,c) -#define EXPAND_CONCAT(a,c) UID_CAT1(a,c) -#ifdef _MSC_VER -#define UNIQUE_ID UID_CAT2(UID_PREFIX,__COUNTER__) -#else -#define UNIQUE_ID UID_CAT2(UID_PREFIX,__LINE__) -#endif - -// this allows enumerations to be used as flags, and still remain type-safe! -#define DEFINE_ENUM_BITWISE_OPERATORS( Type ) \ - inline Type operator| ( Type a, Type b ) { return Type( int( a ) | int( b ) ); } \ - inline Type operator& ( Type a, Type b ) { return Type( int( a ) & int( b ) ); } \ - inline Type operator^ ( Type a, Type b ) { return Type( int( a ) ^ int( b ) ); } \ - inline Type operator<< ( Type a, int b ) { return Type( int( a ) << b ); } \ - inline Type operator>> ( Type a, int b ) { return Type( int( a ) >> b ); } \ - inline Type &operator|= ( Type &a, Type b ) { return a = a | b; } \ - inline Type &operator&= ( Type &a, Type b ) { return a = a & b; } \ - inline Type &operator^= ( Type &a, Type b ) { return a = a ^ b; } \ - inline Type &operator<<=( Type &a, int b ) { return a = a << b; } \ - inline Type &operator>>=( Type &a, int b ) { return a = a >> b; } \ - inline Type operator~( Type a ) { return Type( ~int( a ) ); } - -// defines increment/decrement operators for enums for easy iteration -#define DEFINE_ENUM_INCREMENT_OPERATORS( Type ) \ - inline Type &operator++( Type &a ) { return a = Type( int( a ) + 1 ); } \ - inline Type &operator--( Type &a ) { return a = Type( int( a ) - 1 ); } \ - inline Type operator++( Type &a, int ) { Type t = a; ++a; return t; } \ - inline Type operator--( Type &a, int ) { Type t = a; --a; return t; } - -#include "tier0/valve_on.h" - -#endif // BASETYPES_H diff --git a/public/tier0/commonmacros.h b/public/tier0/commonmacros.h deleted file mode 100644 index 1040107fc..000000000 --- a/public/tier0/commonmacros.h +++ /dev/null @@ -1,144 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef COMMONMACROS_H -#define COMMONMACROS_H - -#ifdef _WIN32 -#pragma once -#endif - -// ------------------------------------------------------- -// -// commonmacros.h -// -// This should contain ONLY general purpose macros that are -// appropriate for use in engine/launcher/all tools -// -// ------------------------------------------------------- - -// Makes a 4-byte "packed ID" int out of 4 characters -#define MAKEID(d,c,b,a) ( ((int)(a) << 24) | ((int)(b) << 16) | ((int)(c) << 8) | ((int)(d)) ) - -// Compares a string with a 4-byte packed ID constant -#define STRING_MATCHES_ID( p, id ) ( (*((int *)(p)) == (id) ) ? true : false ) -#define ID_TO_STRING( id, p ) ( (p)[3] = (((id)>>24) & 0xFF), (p)[2] = (((id)>>16) & 0xFF), (p)[1] = (((id)>>8) & 0xFF), (p)[0] = (((id)>>0) & 0xFF) ) - -#define Q_ARRAYSIZE(p) (sizeof(p)/sizeof(p[0])) - -#define SETBITS(iBitVector, bits) ((iBitVector) |= (bits)) -#define CLEARBITS(iBitVector, bits) ((iBitVector) &= ~(bits)) -#define FBitSet(iBitVector, bit) ((iBitVector) & (bit)) - -inline bool IsPowerOfTwo( int value ) -{ - return (value & ( value - 1 )) == 0; -} - -#define CONST_INTEGER_AS_STRING(x) #x //Wraps the integer in quotes, allowing us to form constant strings with it -#define __HACK_LINE_AS_STRING__(x) CONST_INTEGER_AS_STRING(x) //__LINE__ can only be converted to an actual number by going through this, otherwise the output is literally "__LINE__" -#define __LINE__AS_STRING __HACK_LINE_AS_STRING__(__LINE__) //Gives you the line number in constant string form - -// Using ARRAYSIZE implementation from winnt.h: -#ifdef ARRAYSIZE -#undef ARRAYSIZE -#endif - -// Return the number of elements in a statically sized array. -// DWORD Buffer[100]; -// RTL_NUMBER_OF(Buffer) == 100 -// This is also popularly known as: NUMBER_OF, ARRSIZE, _countof, NELEM, etc. -// -#define RTL_NUMBER_OF_V1(A) (sizeof(A)/sizeof((A)[0])) - -#if defined(__cplusplus) && \ - !defined(MIDL_PASS) && \ - !defined(RC_INVOKED) && \ - !defined(_PREFAST_) && \ - (_MSC_FULL_VER >= 13009466) && \ - !defined(SORTPP_PASS) - -// From crtdefs.h -#if !defined(UNALIGNED) -#if defined(_M_IA64) || defined(_M_AMD64) -#define UNALIGNED __unaligned -#else -#define UNALIGNED -#endif -#endif - -// RtlpNumberOf is a function that takes a reference to an array of N Ts. -// -// typedef T array_of_T[N]; -// typedef array_of_T &reference_to_array_of_T; -// -// RtlpNumberOf returns a pointer to an array of N chars. -// We could return a reference instead of a pointer but older compilers do not accept that. -// -// typedef char array_of_char[N]; -// typedef array_of_char *pointer_to_array_of_char; -// -// sizeof(array_of_char) == N -// sizeof(*pointer_to_array_of_char) == N -// -// pointer_to_array_of_char RtlpNumberOf(reference_to_array_of_T); -// -// We never even call RtlpNumberOf, we just take the size of dereferencing its return type. -// We do not even implement RtlpNumberOf, we just decare it. -// -// Attempts to pass pointers instead of arrays to this macro result in compile time errors. -// That is the point. -extern "C++" // templates cannot be declared to have 'C' linkage -template -char (*RtlpNumberOf( UNALIGNED T (&)[N] ))[N]; - -#define RTL_NUMBER_OF_V2(A) (sizeof(*RtlpNumberOf(A))) - -// This does not work with: -// -// void Foo() -// { -// struct { int x; } y[2]; -// RTL_NUMBER_OF_V2(y); // illegal use of anonymous local type in template instantiation -// } -// -// You must instead do: -// -// struct Foo1 { int x; }; -// -// void Foo() -// { -// Foo1 y[2]; -// RTL_NUMBER_OF_V2(y); // ok -// } -// -// OR -// -// void Foo() -// { -// struct { int x; } y[2]; -// RTL_NUMBER_OF_V1(y); // ok -// } -// -// OR -// -// void Foo() -// { -// struct { int x; } y[2]; -// _ARRAYSIZE(y); // ok -// } - -#else -#define RTL_NUMBER_OF_V2(A) RTL_NUMBER_OF_V1(A) -#endif - -// ARRAYSIZE is more readable version of RTL_NUMBER_OF_V2 -// _ARRAYSIZE is a version useful for anonymous types -#define ARRAYSIZE(A) RTL_NUMBER_OF_V2(A) -#define _ARRAYSIZE(A) RTL_NUMBER_OF_V1(A) - -#endif // COMMONMACROS_H diff --git a/public/tier0/dbg.h b/public/tier0/dbg.h deleted file mode 100644 index f83b45609..000000000 --- a/public/tier0/dbg.h +++ /dev/null @@ -1,735 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ========// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef DBG_H -#define DBG_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "basetypes.h" -#include "dbgflag.h" -#include "platform.h" -#include -#include -#include - -#if defined _LINUX || defined __APPLE__ -#define __cdecl -#endif - -//----------------------------------------------------------------------------- -// dll export stuff -//----------------------------------------------------------------------------- -#ifndef STATIC_TIER0 - -#ifdef TIER0_DLL_EXPORT -#define DBG_INTERFACE DLL_EXPORT -#define DBG_OVERLOAD DLL_GLOBAL_EXPORT -#define DBG_CLASS DLL_CLASS_EXPORT -#else -#define DBG_INTERFACE DLL_IMPORT -#define DBG_OVERLOAD DLL_GLOBAL_IMPORT -#define DBG_CLASS DLL_CLASS_IMPORT -#endif - -#else // BUILD_AS_DLL - -#define DBG_INTERFACE extern -#define DBG_OVERLOAD -#define DBG_CLASS -#endif // BUILD_AS_DLL - - -class Color; - - -//----------------------------------------------------------------------------- -// Usage model for the Dbg library -// -// 1. Spew. -// -// Spew can be used in a static and a dynamic mode. The static -// mode allows us to display assertions and other messages either only -// in debug builds, or in non-release builds. The dynamic mode allows us to -// turn on and off certain spew messages while the application is running. -// -// Static Spew messages: -// -// Assertions are used to detect and warn about invalid states -// Spews are used to display a particular status/warning message. -// -// To use an assertion, use -// -// Assert( (f == 5) ); -// AssertMsg( (f == 5), ("F needs to be %d here!\n", 5) ); -// AssertFunc( (f == 5), BadFunc() ); -// AssertEquals( f, 5 ); -// AssertFloatEquals( f, 5.0f, 1e-3 ); -// -// The first will simply report that an assertion failed on a particular -// code file and line. The second version will display a print-f formatted message -// along with the file and line, the third will display a generic message and -// will also cause the function BadFunc to be executed, and the last two -// will report an error if f is not equal to 5 (the last one asserts within -// a particular tolerance). -// -// To use a warning, use -// -// Warning("Oh I feel so %s all over\n", "yummy"); -// -// Warning will do its magic in only Debug builds. To perform spew in *all* -// builds, use RelWarning. -// -// Three other spew types, Msg, Log, and Error, are compiled into all builds. -// These error types do *not* need two sets of parenthesis. -// -// Msg( "Isn't this exciting %d?", 5 ); -// Error( "I'm just thrilled" ); -// -// Dynamic Spew messages -// -// It is possible to dynamically turn spew on and off. Dynamic spew is -// identified by a spew group and priority level. To turn spew on for a -// particular spew group, use SpewActivate( "group", level ). This will -// cause all spew in that particular group with priority levels <= the -// level specified in the SpewActivate function to be printed. Use DSpew -// to perform the spew: -// -// DWarning( "group", level, "Oh I feel even yummier!\n" ); -// -// Priority level 0 means that the spew will *always* be printed, and group -// '*' is the default spew group. If a DWarning is encountered using a group -// whose priority has not been set, it will use the priority of the default -// group. The priority of the default group is initially set to 0. -// -// Spew output -// -// The output of the spew system can be redirected to an externally-supplied -// function which is responsible for outputting the spew. By default, the -// spew is simply printed using printf. -// -// To redirect spew output, call SpewOutput. -// -// SpewOutputFunc( OutputFunc ); -// -// This will cause OutputFunc to be called every time a spew message is -// generated. OutputFunc will be passed a spew type and a message to print. -// It must return a value indicating whether the debugger should be invoked, -// whether the program should continue running, or whether the program -// should abort. -// -// 2. Code activation -// -// To cause code to be run only in debug builds, use DBG_CODE: -// An example is below. -// -// DBG_CODE( -// { -// int x = 5; -// ++x; -// } -// ); -// -// Code can be activated based on the dynamic spew groups also. Use -// -// DBG_DCODE( "group", level, -// { int x = 5; ++x; } -// ); -// -// 3. Breaking into the debugger. -// -// To cause an unconditional break into the debugger in debug builds only, use DBG_BREAK -// -// DBG_BREAK(); -// -// You can force a break in any build (release or debug) using -// -// DebuggerBreak(); -//----------------------------------------------------------------------------- - -/* Various types of spew messages */ -// I'm sure you're asking yourself why SPEW_ instead of DBG_ ? -// It's because DBG_ is used all over the place in windows.h -// For example, DBG_CONTINUE is defined. Feh. -enum SpewType_t -{ - SPEW_MESSAGE = 0, - SPEW_WARNING, - SPEW_ASSERT, - SPEW_ERROR, - SPEW_LOG, - - SPEW_TYPE_COUNT -}; - -enum SpewRetval_t -{ - SPEW_DEBUGGER = 0, - SPEW_CONTINUE, - SPEW_ABORT -}; - -/* type of externally defined function used to display debug spew */ -typedef SpewRetval_t (*SpewOutputFunc_t)( SpewType_t spewType, const tchar *pMsg ); - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunknown-pragmas" -#pragma clang diagnostic ignored "-Wreturn-type-c-linkage" -#endif - -/* Used to redirect spew output */ -DBG_INTERFACE void SpewOutputFunc( SpewOutputFunc_t func ); - -/* Used to get the current spew output function */ -DBG_INTERFACE SpewOutputFunc_t GetSpewOutputFunc( void ); - -/* Should be called only inside a SpewOutputFunc_t, returns groupname, level, color */ -DBG_INTERFACE const tchar* GetSpewOutputGroup( void ); -DBG_INTERFACE int GetSpewOutputLevel( void ); -DBG_INTERFACE const Color& GetSpewOutputColor( void ); - -/* Used to manage spew groups and subgroups */ -DBG_INTERFACE void SpewActivate( const tchar* pGroupName, int level ); -DBG_INTERFACE bool IsSpewActive( const tchar* pGroupName, int level ); - -/* Used to display messages, should never be called directly. */ -DBG_INTERFACE void _SpewInfo( SpewType_t type, const tchar* pFile, int line ); -DBG_INTERFACE SpewRetval_t _SpewMessage( const tchar* pMsg, ... ); -DBG_INTERFACE SpewRetval_t _DSpewMessage( const tchar *pGroupName, int level, const tchar* pMsg, ... ); -DBG_INTERFACE SpewRetval_t ColorSpewMessage( SpewType_t type, const Color *pColor, const tchar* pMsg, ... ); -DBG_INTERFACE void _ExitOnFatalAssert( const tchar* pFile, int line ); -DBG_INTERFACE bool ShouldUseNewAssertDialog(); - -DBG_INTERFACE bool SetupWin32ConsoleIO(); - -// Returns true if they want to break in the debugger. -DBG_INTERFACE bool DoNewAssertDialog( const tchar *pFile, int line, const tchar *pExpression ); - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -/* Used to define macros, never use these directly. */ - -#define _AssertMsg( _exp, _msg, _executeExp, _bFatal ) \ - do { \ - if (!(_exp)) \ - { \ - _SpewInfo( SPEW_ASSERT, __TFILE__, __LINE__ ); \ - SpewRetval_t ret = _SpewMessage("%s", _msg); \ - _executeExp; \ - if ( ret == SPEW_DEBUGGER) \ - { \ - if ( !ShouldUseNewAssertDialog() || DoNewAssertDialog( __TFILE__, __LINE__, _msg ) ) \ - DebuggerBreak(); \ - if ( _bFatal ) \ - _ExitOnFatalAssert( __TFILE__, __LINE__ ); \ - } \ - } \ - } while (0) - -#define _AssertMsgOnce( _exp, _msg, _bFatal ) \ - do { \ - static bool fAsserted; \ - if (!fAsserted ) \ - { \ - _AssertMsg( _exp, _msg, (fAsserted = true), _bFatal ); \ - } \ - } while (0) - -/* Spew macros... */ - -// AssertFatal macros -// AssertFatal is used to detect an unrecoverable error condition. -// If enabled, it may display an assert dialog (if DBGFLAG_ASSERTDLG is turned on or running under the debugger), -// and always terminates the application - -#ifdef DBGFLAG_ASSERTFATAL - -#define AssertFatal( _exp ) _AssertMsg( _exp, _T("Assertion Failed: ") _T(#_exp), ((void)0), true ) -#define AssertFatalOnce( _exp ) _AssertMsgOnce( _exp, _T("Assertion Failed: ") _T(#_exp), true ) -#define AssertFatalMsg( _exp, _msg ) _AssertMsg( _exp, _msg, ((void)0), true ) -#define AssertFatalMsgOnce( _exp, _msg ) _AssertMsgOnce( _exp, _msg, true ) -#define AssertFatalFunc( _exp, _f ) _AssertMsg( _exp, _T("Assertion Failed: " _T(#_exp), _f, true ) -#define AssertFatalEquals( _exp, _expectedValue ) AssertFatalMsg2( (_exp) == (_expectedValue), _T("Expected %d but got %d!"), (_expectedValue), (_exp) ) -#define AssertFatalFloatEquals( _exp, _expectedValue, _tol ) AssertFatalMsg2( fabs((_exp) - (_expectedValue)) <= (_tol), _T("Expected %f but got %f!"), (_expectedValue), (_exp) ) -#define VerifyFatal( _exp ) AssertFatal( _exp ) -#define VerifyEqualsFatal( _exp, _expectedValue ) AssertFatalEquals( _exp, _expectedValue ) - -#define AssertFatalMsg1( _exp, _msg, a1 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1 ))) -#define AssertFatalMsg2( _exp, _msg, a1, a2 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2 ))) -#define AssertFatalMsg3( _exp, _msg, a1, a2, a3 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3 ))) -#define AssertFatalMsg4( _exp, _msg, a1, a2, a3, a4 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4 ))) -#define AssertFatalMsg5( _exp, _msg, a1, a2, a3, a4, a5 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5 ))) -#define AssertFatalMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6 ))) -#define AssertFatalMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6 ))) -#define AssertFatalMsg7( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6, a7 ))) -#define AssertFatalMsg8( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6, a7, a8 ))) -#define AssertFatalMsg9( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 ))) - -#else // DBGFLAG_ASSERTFATAL - -#define AssertFatal( _exp ) ((void)0) -#define AssertFatalOnce( _exp ) ((void)0) -#define AssertFatalMsg( _exp, _msg ) ((void)0) -#define AssertFatalMsgOnce( _exp, _msg ) ((void)0) -#define AssertFatalFunc( _exp, _f ) ((void)0) -#define AssertFatalEquals( _exp, _expectedValue ) ((void)0) -#define AssertFatalFloatEquals( _exp, _expectedValue, _tol ) ((void)0) -#define VerifyFatal( _exp ) (_exp) -#define VerifyEqualsFatal( _exp, _expectedValue ) (_exp) - -#define AssertFatalMsg1( _exp, _msg, a1 ) ((void)0) -#define AssertFatalMsg2( _exp, _msg, a1, a2 ) ((void)0) -#define AssertFatalMsg3( _exp, _msg, a1, a2, a3 ) ((void)0) -#define AssertFatalMsg4( _exp, _msg, a1, a2, a3, a4 ) ((void)0) -#define AssertFatalMsg5( _exp, _msg, a1, a2, a3, a4, a5 ) ((void)0) -#define AssertFatalMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) ((void)0) -#define AssertFatalMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) ((void)0) -#define AssertFatalMsg7( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 ) ((void)0) -#define AssertFatalMsg8( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 ) ((void)0) -#define AssertFatalMsg9( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 ) ((void)0) - -#endif // DBGFLAG_ASSERTFATAL - -// Assert macros -// Assert is used to detect an important but survivable error. -// It's only turned on when DBGFLAG_ASSERT is true. - -#ifdef DBGFLAG_ASSERT - -#define Assert( _exp ) _AssertMsg( _exp, _T("Assertion Failed: ") _T(#_exp), ((void)0), false ) -#define AssertMsg( _exp, _msg ) _AssertMsg( _exp, _msg, ((void)0), false ) -#define AssertOnce( _exp ) _AssertMsgOnce( _exp, _T("Assertion Failed: ") _T(#_exp), false ) -#define AssertMsgOnce( _exp, _msg ) _AssertMsgOnce( _exp, _msg, false ) -#define AssertFunc( _exp, _f ) _AssertMsg( _exp, _T("Assertion Failed: ") _T(#_exp), _f, false ) -#define AssertEquals( _exp, _expectedValue ) AssertMsg2( (_exp) == (_expectedValue), _T("Expected %d but got %d!"), (_expectedValue), (_exp) ) -#define AssertFloatEquals( _exp, _expectedValue, _tol ) AssertMsg2( fabs((_exp) - (_expectedValue)) <= (_tol), _T("Expected %f but got %f!"), (_expectedValue), (_exp) ) -#define Verify( _exp ) Assert( _exp ) -#define VerifyEquals( _exp, _expectedValue ) AssertEquals( _exp, _expectedValue ) - -#define AssertMsg1( _exp, _msg, a1 ) AssertMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1 )) ) -#define AssertMsg2( _exp, _msg, a1, a2 ) AssertMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2 )) ) -#define AssertMsg3( _exp, _msg, a1, a2, a3 ) AssertMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3 )) ) -#define AssertMsg4( _exp, _msg, a1, a2, a3, a4 ) AssertMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4 )) ) -#define AssertMsg5( _exp, _msg, a1, a2, a3, a4, a5 ) AssertMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5 )) ) -#define AssertMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) AssertMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6 )) ) -#define AssertMsg7( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 ) AssertMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6, a7 )) ) -#define AssertMsg8( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 ) AssertMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6, a7, a8 )) ) -#define AssertMsg9( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 ) AssertMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 )) ) - -#else // DBGFLAG_ASSERT - -#define Assert( _exp ) ((void)0) -#define AssertOnce( _exp ) ((void)0) -#define AssertMsg( _exp, _msg ) ((void)0) -#define AssertMsgOnce( _exp, _msg ) ((void)0) -#define AssertFunc( _exp, _f ) ((void)0) -#define AssertEquals( _exp, _expectedValue ) ((void)0) -#define AssertFloatEquals( _exp, _expectedValue, _tol ) ((void)0) -#define Verify( _exp ) (_exp) -#define VerifyEquals( _exp, _expectedValue ) (_exp) - -#define AssertMsg1( _exp, _msg, a1 ) ((void)0) -#define AssertMsg2( _exp, _msg, a1, a2 ) ((void)0) -#define AssertMsg3( _exp, _msg, a1, a2, a3 ) ((void)0) -#define AssertMsg4( _exp, _msg, a1, a2, a3, a4 ) ((void)0) -#define AssertMsg5( _exp, _msg, a1, a2, a3, a4, a5 ) ((void)0) -#define AssertMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) ((void)0) -#define AssertMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) ((void)0) -#define AssertMsg7( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 ) ((void)0) -#define AssertMsg8( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 ) ((void)0) -#define AssertMsg9( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 ) ((void)0) - -#endif // DBGFLAG_ASSERT - - -#if !defined( _X360 ) || !defined( _RETAIL ) - -/* These are always compiled in */ -DBG_INTERFACE void Msg( const tchar* pMsg, ... ); -DBG_INTERFACE void DMsg( const tchar *pGroupName, int level, const tchar *pMsg, ... ); - -DBG_INTERFACE void Warning( const tchar *pMsg, ... ); -DBG_INTERFACE void DWarning( const tchar *pGroupName, int level, const tchar *pMsg, ... ); - -DBG_INTERFACE void Log( const tchar *pMsg, ... ); -DBG_INTERFACE void DLog( const tchar *pGroupName, int level, const tchar *pMsg, ... ); - -DBG_INTERFACE void Error( const tchar *pMsg, ... ); - -#else - -inline void Msg( ... ) {} -inline void DMsg( ... ) {} -inline void Warning( const tchar *pMsg, ... ) {} -inline void DWarning( ... ) {} -inline void Log( ... ) {} -inline void DLog( ... ) {} -inline void Error( ... ) {} - -#endif - -// You can use this macro like a runtime assert macro. -// If the condition fails, then Error is called with the message. This macro is called -// like AssertMsg, where msg must be enclosed in parenthesis: -// -// ErrorIfNot( bCondition, ("a b c %d %d %d", 1, 2, 3) ); -#define ErrorIfNot( condition, msg ) \ - if ( (condition) ) \ - ; \ - else \ - { \ - Error msg; \ - } - -#if !defined( _X360 ) || !defined( _RETAIL ) - -/* A couple of super-common dynamic spew messages, here for convenience */ -/* These looked at the "developer" group */ -DBG_INTERFACE void DevMsg( int level, const tchar* pMsg, ... ); -DBG_INTERFACE void DevWarning( int level, const tchar *pMsg, ... ); -DBG_INTERFACE void DevLog( int level, const tchar *pMsg, ... ); - -/* default level versions (level 1) */ -DBG_OVERLOAD void DevMsg( const tchar* pMsg, ... ); -DBG_OVERLOAD void DevWarning( const tchar *pMsg, ... ); -DBG_OVERLOAD void DevLog( const tchar *pMsg, ... ); - -/* These looked at the "console" group */ -DBG_INTERFACE void ConColorMsg( int level, const Color& clr, const tchar* pMsg, ... ); -DBG_INTERFACE void ConMsg( int level, const tchar* pMsg, ... ); -DBG_INTERFACE void ConWarning( int level, const tchar *pMsg, ... ); -DBG_INTERFACE void ConLog( int level, const tchar *pMsg, ... ); - -/* default console version (level 1) */ -DBG_OVERLOAD void ConColorMsg( const Color& clr, const tchar* pMsg, ... ); -DBG_OVERLOAD void ConMsg( const tchar* pMsg, ... ); -DBG_OVERLOAD void ConWarning( const tchar *pMsg, ... ); -DBG_OVERLOAD void ConLog( const tchar *pMsg, ... ); - -/* developer console version (level 2) */ -DBG_INTERFACE void ConDColorMsg( const Color& clr, const tchar* pMsg, ... ); -DBG_INTERFACE void ConDMsg( const tchar* pMsg, ... ); -DBG_INTERFACE void ConDWarning( const tchar *pMsg, ... ); -DBG_INTERFACE void ConDLog( const tchar *pMsg, ... ); - -/* These looked at the "network" group */ -DBG_INTERFACE void NetMsg( int level, const tchar* pMsg, ... ); -DBG_INTERFACE void NetWarning( int level, const tchar *pMsg, ... ); -DBG_INTERFACE void NetLog( int level, const tchar *pMsg, ... ); - -void ValidateSpew( class CValidator &validator ); - -#else - -inline void DevMsg( ... ) {} -inline void DevWarning( ... ) {} -inline void DevLog( ... ) {} -inline void ConMsg( ... ) {} -inline void ConLog( ... ) {} -inline void NetMsg( ... ) {} -inline void NetWarning( ... ) {} -inline void NetLog( ... ) {} - -#endif - -DBG_INTERFACE void COM_TimestampedLog( char const *fmt, ... ); - -/* Code macros, debugger interface */ - -#ifdef _DEBUG - -#define DBG_CODE( _code ) if (0) ; else { _code } -#define DBG_CODE_NOSCOPE( _code ) _code -#define DBG_DCODE( _g, _l, _code ) if (IsSpewActive( _g, _l )) { _code } else {} -#define DBG_BREAK() DebuggerBreak() /* defined in platform.h */ - -#else /* not _DEBUG */ - -#define DBG_CODE( _code ) ((void)0) -#define DBG_CODE_NOSCOPE( _code ) -#define DBG_DCODE( _g, _l, _code ) ((void)0) -#define DBG_BREAK() ((void)0) - -#endif /* _DEBUG */ - -//----------------------------------------------------------------------------- - -#ifndef _RETAIL -class CScopeMsg -{ -public: - CScopeMsg( const char *pszScope ) - { - m_pszScope = pszScope; - Msg( "%s { ", pszScope ); - } - ~CScopeMsg() - { - Msg( "} %s", m_pszScope ); - } - const char *m_pszScope; -}; -#define SCOPE_MSG( msg ) CScopeMsg scopeMsg( msg ) -#else -#define SCOPE_MSG( msg ) -#endif - - -//----------------------------------------------------------------------------- -// Macro to assist in asserting constant invariants during compilation - -#ifdef _DEBUG - #define COMPILE_TIME_ASSERT( pred ) switch(0){case 0:case pred:;} - #ifdef _MSC_VER - #define ASSERT_INVARIANT( pred ) static void UNIQUE_ID() { COMPILE_TIME_ASSERT( pred ) } - #elif defined __GNUC__ - #define ASSERT_INVARIANT( pred ) __attribute__((unused)) static void UNIQUE_ID() { COMPILE_TIME_ASSERT( pred ) } - #endif -#else - #define COMPILE_TIME_ASSERT( pred ) - #define ASSERT_INVARIANT( pred ) -#endif - -// Member function pointer size -#ifdef _MSC_VER - #define MFP_SIZE 4 -#elif __GNUC__ - #define MFP_SIZE 8 -#endif - -#ifdef _DEBUG -template -inline DEST_POINTER_TYPE assert_cast(SOURCE_POINTER_TYPE* pSource) -{ - Assert( static_cast(pSource) == dynamic_cast(pSource) ); - return static_cast(pSource); -} -#else -#define assert_cast static_cast -#endif - -//----------------------------------------------------------------------------- -// Templates to assist in validating pointers: - -// Have to use these stubs so we don't have to include windows.h here. -DBG_INTERFACE void _AssertValidReadPtr( void* ptr, int count = 1 ); -DBG_INTERFACE void _AssertValidWritePtr( void* ptr, int count = 1 ); -DBG_INTERFACE void _AssertValidReadWritePtr( void* ptr, int count = 1 ); - -DBG_INTERFACE void AssertValidStringPtr( const tchar* ptr, int maxchar = 0xFFFFFF ); -template inline void AssertValidReadPtr( T* ptr, int count = 1 ) { _AssertValidReadPtr( (void*)ptr, count ); } -template inline void AssertValidWritePtr( T* ptr, int count = 1 ) { _AssertValidWritePtr( (void*)ptr, count ); } -template inline void AssertValidReadWritePtr( T* ptr, int count = 1 ) { _AssertValidReadWritePtr( (void*)ptr, count ); } - -#define AssertValidThis() AssertValidReadWritePtr(this,sizeof(*this)) - -//----------------------------------------------------------------------------- -// Macro to protect functions that are not reentrant - -#ifdef _DEBUG -class CReentryGuard -{ -public: - CReentryGuard(int *pSemaphore) - : m_pSemaphore(pSemaphore) - { - ++(*m_pSemaphore); - } - - ~CReentryGuard() - { - --(*m_pSemaphore); - } - -private: - int *m_pSemaphore; -}; - -#define ASSERT_NO_REENTRY() \ - static int fSemaphore##__LINE__; \ - Assert( !fSemaphore##__LINE__ ); \ - CReentryGuard ReentryGuard##__LINE__( &fSemaphore##__LINE__ ) -#else -#define ASSERT_NO_REENTRY() -#endif - -//----------------------------------------------------------------------------- -// -// Purpose: Inline string formatter -// - -#include "tier0/valve_off.h" -class CDbgFmtMsg -{ -public: - CDbgFmtMsg(const tchar *pszFormat, ...) - { - va_list arg_ptr; - - va_start(arg_ptr, pszFormat); - _vsntprintf(m_szBuf, sizeof(m_szBuf)-1, pszFormat, arg_ptr); - va_end(arg_ptr); - - m_szBuf[sizeof(m_szBuf)-1] = 0; - } - - operator const tchar *() const - { - return m_szBuf; - } - -private: - tchar m_szBuf[256]; -}; -#include "tier0/valve_on.h" - -//----------------------------------------------------------------------------- -// -// Purpose: Embed debug info in each file. -// -#if defined( _WIN32 ) && !defined( _X360 ) - - #ifdef _DEBUG - #pragma comment(compiler) - #endif - -#endif - -//----------------------------------------------------------------------------- -// -// Purpose: Wrap around a variable to create a simple place to put a breakpoint -// - -#ifdef _DEBUG - -template< class Type > -class CDataWatcher -{ -public: - const Type& operator=( const Type &val ) - { - return Set( val ); - } - - const Type& operator=( const CDataWatcher &val ) - { - return Set( val.m_Value ); - } - - const Type& Set( const Type &val ) - { - // Put your breakpoint here - m_Value = val; - return m_Value; - } - - Type& GetForModify() - { - return m_Value; - } - - const Type& operator+=( const Type &val ) - { - return Set( m_Value + val ); - } - - const Type& operator-=( const Type &val ) - { - return Set( m_Value - val ); - } - - const Type& operator/=( const Type &val ) - { - return Set( m_Value / val ); - } - - const Type& operator*=( const Type &val ) - { - return Set( m_Value * val ); - } - - const Type& operator^=( const Type &val ) - { - return Set( m_Value ^ val ); - } - - const Type& operator|=( const Type &val ) - { - return Set( m_Value | val ); - } - - const Type& operator++() - { - return (*this += 1); - } - - Type operator--() - { - return (*this -= 1); - } - - Type operator++( int ) // postfix version.. - { - Type val = m_Value; - (*this += 1); - return val; - } - - Type operator--( int ) // postfix version.. - { - Type val = m_Value; - (*this -= 1); - return val; - } - - // For some reason the compiler only generates type conversion warnings for this operator when used like - // CNetworkVarBase = 0x1 - // (it warns about converting from an int to an unsigned char). - template< class C > - const Type& operator&=( C val ) - { - return Set( m_Value & val ); - } - - operator const Type&() const - { - return m_Value; - } - - const Type& Get() const - { - return m_Value; - } - - const Type* operator->() const - { - return &m_Value; - } - - Type m_Value; - -}; - -#else - -template< class Type > -class CDataWatcher -{ -private: - CDataWatcher(); // refuse to compile in non-debug builds -}; - -#endif - -//----------------------------------------------------------------------------- - -#endif /* DBG_H */ diff --git a/public/tier0/dbgflag.h b/public/tier0/dbgflag.h deleted file mode 100644 index 85b754b96..000000000 --- a/public/tier0/dbgflag.h +++ /dev/null @@ -1,65 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: This file sets all of our debugging flags. It should be -// called before all other header files. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef DBGFLAG_H -#define DBGFLAG_H -#ifdef _WIN32 -#pragma once -#endif - - -// Here are all the flags we support: -// DBGFLAG_MEMORY: Enables our memory debugging system, which overrides malloc & free -// DBGFLAG_MEMORY_NEWDEL: Enables new / delete tracking for memory debug system. Requires DBGFLAG_MEMORY to be enabled. -// DBGFLAG_VALIDATE: Enables our recursive validation system for checking integrity and memory leaks -// DBGFLAG_ASSERT: Turns Assert on or off (when off, it isn't compiled at all) -// DBGFLAG_ASSERTFATAL: Turns AssertFatal on or off (when off, it isn't compiled at all) -// DBGFLAG_ASSERTDLG: Turns assert dialogs on or off and debug breaks on or off when not under the debugger. -// (Dialogs will always be on when process is being debugged.) -// DBGFLAG_STRINGS: Turns on hardcore string validation (slow but safe) - -#undef DBGFLAG_MEMORY -#undef DBGFLAG_MEMORY_NEWDEL -#undef DBGFLAG_VALIDATE -#undef DBGFLAG_ASSERT -#undef DBGFLAG_ASSERTFATAL -#undef DBGFLAG_ASSERTDLG -#undef DBGFLAG_STRINGS - -//----------------------------------------------------------------------------- -// Default flags for debug builds -//----------------------------------------------------------------------------- -#ifdef _DEBUG - -#define DBGFLAG_MEMORY -#ifdef _SERVER // only enable new & delete tracking for server; on client it conflicts with CRT mem leak tracking -#define DBGFLAG_MEMORY_NEWDEL -#endif -#ifdef STEAM -#define DBGFLAG_VALIDATE -#endif -#define DBGFLAG_ASSERT -#define DBGFLAG_ASSERTFATAL -#define DBGFLAG_ASSERTDLG -#define DBGFLAG_STRINGS - - -//----------------------------------------------------------------------------- -// Default flags for release builds -//----------------------------------------------------------------------------- -#else // _DEBUG - -#ifdef STEAM -#define DBGFLAG_ASSERT -#endif -#define DBGFLAG_ASSERTFATAL // note: fatal asserts are enabled in release builds -#define DBGFLAG_ASSERTDLG - -#endif // _DEBUG - -#endif // DBGFLAG_H diff --git a/public/tier0/fasttimer.h b/public/tier0/fasttimer.h deleted file mode 100644 index 4ab983725..000000000 --- a/public/tier0/fasttimer.h +++ /dev/null @@ -1,594 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef FASTTIMER_H -#define FASTTIMER_H -#ifdef _WIN32 -#pragma once -#endif - -#include -#include "tier0/platform.h" - -PLATFORM_INTERFACE int64 g_ClockSpeed; -PLATFORM_INTERFACE unsigned long g_dwClockSpeed; -#if defined( _X360 ) && defined( _CERT ) -PLATFORM_INTERFACE unsigned long g_dwFakeFastCounter; -#endif - -PLATFORM_INTERFACE double g_ClockSpeedMicrosecondsMultiplier; -PLATFORM_INTERFACE double g_ClockSpeedMillisecondsMultiplier; -PLATFORM_INTERFACE double g_ClockSpeedSecondsMultiplier; - -class CCycleCount -{ -friend class CFastTimer; - -public: - CCycleCount(); - CCycleCount( int64 cycles ); - - void Sample(); // Sample the clock. This takes about 34 clocks to execute (or 26,000 calls per millisecond on a P900). - - void Init(); // Set to zero. - void Init( float initTimeMsec ); - void Init( double initTimeMsec ) { Init( (float)initTimeMsec ); } - void Init( int64 cycles ); - bool IsLessThan( CCycleCount const &other ) const; // Compare two counts. - - // Convert to other time representations. These functions are slow, so it's preferable to call them - // during display rather than inside a timing block. - unsigned long GetCycles() const; - int64 GetLongCycles() const; - - unsigned long GetMicroseconds() const; - uint64 GetUlMicroseconds() const; - double GetMicrosecondsF() const; - void SetMicroseconds( unsigned long nMicroseconds ); - - unsigned long GetMilliseconds() const; - double GetMillisecondsF() const; - - double GetSeconds() const; - - CCycleCount& operator+=( CCycleCount const &other ); - - // dest = rSrc1 + rSrc2 - static void Add( CCycleCount const &rSrc1, CCycleCount const &rSrc2, CCycleCount &dest ); // Add two samples together. - - // dest = rSrc1 - rSrc2 - static void Sub( CCycleCount const &rSrc1, CCycleCount const &rSrc2, CCycleCount &dest ); // Add two samples together. - - static int64 GetTimestamp(); - - int64 m_Int64; -}; - -class CClockSpeedInit -{ -public: - CClockSpeedInit() - { - Init(); - } - - static void Init() - { -#if defined( _X360 ) && !defined( _CERT ) - PMCStart(); - PMCInitIntervalTimer( 0 ); -#endif - const CPUInformation& pi = GetCPUInformation(); - - g_ClockSpeed = pi.m_Speed; - g_dwClockSpeed = (unsigned long)g_ClockSpeed; - - g_ClockSpeedMicrosecondsMultiplier = 1000000.0 / (double)g_ClockSpeed; - g_ClockSpeedMillisecondsMultiplier = 1000.0 / (double)g_ClockSpeed; - g_ClockSpeedSecondsMultiplier = 1.0f / (double)g_ClockSpeed; - } -}; - -class CFastTimer -{ -public: - // These functions are fast to call and should be called from your sampling code. - void Start(); - void End(); - - const CCycleCount & GetDuration() const; // Get the elapsed time between Start and End calls. - CCycleCount GetDurationInProgress() const; // Call without ending. Not that cheap. - - // Return number of cycles per second on this processor. - static inline unsigned long GetClockSpeed(); - -private: - CCycleCount m_Duration; -#ifdef DEBUG_FASTTIMER - bool m_bRunning; // Are we currently running? -#endif -}; - - -// This is a helper class that times whatever block of code it's in -class CTimeScope -{ -public: - CTimeScope( CFastTimer *pTimer ); - ~CTimeScope(); - -private: - CFastTimer *m_pTimer; -}; - -inline CTimeScope::CTimeScope( CFastTimer *pTotal ) -{ - m_pTimer = pTotal; - m_pTimer->Start(); -} - -inline CTimeScope::~CTimeScope() -{ - m_pTimer->End(); -} - -// This is a helper class that times whatever block of code it's in and -// adds the total (int microseconds) to a global counter. -class CTimeAdder -{ -public: - CTimeAdder( CCycleCount *pTotal ); - ~CTimeAdder(); - - void End(); - -private: - CCycleCount *m_pTotal; - CFastTimer m_Timer; -}; - -inline CTimeAdder::CTimeAdder( CCycleCount *pTotal ) -{ - m_pTotal = pTotal; - m_Timer.Start(); -} - -inline CTimeAdder::~CTimeAdder() -{ - End(); -} - -inline void CTimeAdder::End() -{ - if( m_pTotal ) - { - m_Timer.End(); - *m_pTotal += m_Timer.GetDuration(); - m_pTotal = 0; - } -} - - - -// -------------------------------------------------------------------------- // -// Simple tool to support timing a block of code, and reporting the results on -// program exit or at each iteration -// -// Macros used because dbg.h uses this header, thus Msg() is unavailable -// -------------------------------------------------------------------------- // - -#define PROFILE_SCOPE(name) \ - class C##name##ACC : public CAverageCycleCounter \ - { \ - public: \ - ~C##name##ACC() \ - { \ - Msg("%-48s: %6.3f avg (%8.1f total, %7.3f peak, %5d iters)\n", \ - #name, \ - GetAverageMilliseconds(), \ - GetTotalMilliseconds(), \ - GetPeakMilliseconds(), \ - GetIters() ); \ - } \ - }; \ - static C##name##ACC name##_ACC; \ - CAverageTimeMarker name##_ATM( &name##_ACC ) - -#define TIME_SCOPE(name) \ - class CTimeScopeMsg_##name \ - { \ - public: \ - CTimeScopeMsg_##name() { m_Timer.Start(); } \ - ~CTimeScopeMsg_##name() \ - { \ - m_Timer.End(); \ - Msg( #name "time: %.4fms\n", m_Timer.GetDuration().GetMillisecondsF() ); \ - } \ - private: \ - CFastTimer m_Timer; \ - } name##_TSM; - - -// -------------------------------------------------------------------------- // - -class CAverageCycleCounter -{ -public: - CAverageCycleCounter(); - - void Init(); - void MarkIter( const CCycleCount &duration ); - - unsigned GetIters() const; - - double GetAverageMilliseconds() const; - double GetTotalMilliseconds() const; - double GetPeakMilliseconds() const; - -private: - unsigned m_nIters; - CCycleCount m_Total; - CCycleCount m_Peak; - bool m_fReport; - const tchar *m_pszName; -}; - -// -------------------------------------------------------------------------- // - -class CAverageTimeMarker -{ -public: - CAverageTimeMarker( CAverageCycleCounter *pCounter ); - ~CAverageTimeMarker(); - -private: - CAverageCycleCounter *m_pCounter; - CFastTimer m_Timer; -}; - - -// -------------------------------------------------------------------------- // -// CCycleCount inlines. -// -------------------------------------------------------------------------- // - -inline CCycleCount::CCycleCount() -{ - Init( (int64)0 ); -} - -inline CCycleCount::CCycleCount( int64 cycles ) -{ - Init( cycles ); -} - -inline void CCycleCount::Init() -{ - Init( (int64)0 ); -} - -inline void CCycleCount::Init( float initTimeMsec ) -{ - if ( g_ClockSpeedMillisecondsMultiplier > 0 ) - Init( (int64)(initTimeMsec / g_ClockSpeedMillisecondsMultiplier) ); - else - Init( (int64)0 ); -} - -inline void CCycleCount::Init( int64 cycles ) -{ - m_Int64 = cycles; -} - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4189) // warning C4189: local variable is initialized but not referenced -#endif - -inline void CCycleCount::Sample() -{ -#if defined( _X360 ) -#if !defined( _CERT ) - // read the highest resolution timer directly (ticks at native 3.2GHz), bypassing any calls into PMC - // can only resolve 32 bits, rollover is ~1.32 secs - // based on PMCGetIntervalTimer() from the April 2007 XDK - int64 temp; - __asm - { - lis r11,08FFFh - ld r11,011E0h(r11) - rldicl r11,r11,32,32 - // unforunate can't get the inline assembler to write directly into desired target - std r11,temp - } - m_Int64 = temp; -#else - m_Int64 = ++g_dwFakeFastCounter; -#endif -#elif defined( _WIN32 ) - unsigned long* pSample = (unsigned long *)&m_Int64; - __asm - { - // force the cpu to synchronize the instruction queue - // NJS: CPUID can really impact performance in tight loops. - //cpuid - //cpuid - //cpuid - mov ecx, pSample - rdtsc - mov [ecx], eax - mov [ecx+4], edx - } -#elif defined( _LINUX ) - unsigned long* pSample = (unsigned long *)&m_Int64; - __asm__ __volatile__ ( - "rdtsc\n\t" - "movl %%eax, (%0)\n\t" - "movl %%edx, 4(%0)\n\t" - : /* no output regs */ - : "D" (pSample) - : "%eax", "%edx" ); -#endif -} - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -inline CCycleCount& CCycleCount::operator+=( CCycleCount const &other ) -{ - m_Int64 += other.m_Int64; - return *this; -} - - -inline void CCycleCount::Add( CCycleCount const &rSrc1, CCycleCount const &rSrc2, CCycleCount &dest ) -{ - dest.m_Int64 = rSrc1.m_Int64 + rSrc2.m_Int64; -} - -inline void CCycleCount::Sub( CCycleCount const &rSrc1, CCycleCount const &rSrc2, CCycleCount &dest ) -{ - dest.m_Int64 = rSrc1.m_Int64 - rSrc2.m_Int64; -} - -inline int64 CCycleCount::GetTimestamp() -{ - CCycleCount c; - c.Sample(); - return c.GetLongCycles(); -} - -inline bool CCycleCount::IsLessThan(CCycleCount const &other) const -{ - return m_Int64 < other.m_Int64; -} - - -inline unsigned long CCycleCount::GetCycles() const -{ - return (unsigned long)m_Int64; -} - -inline int64 CCycleCount::GetLongCycles() const -{ - return m_Int64; -} - -inline unsigned long CCycleCount::GetMicroseconds() const -{ - return (unsigned long)((m_Int64 * 1000000) / g_ClockSpeed); -} - -inline uint64 CCycleCount::GetUlMicroseconds() const -{ - return ((m_Int64 * 1000000) / g_ClockSpeed); -} - - -inline double CCycleCount::GetMicrosecondsF() const -{ - return (double)( m_Int64 * g_ClockSpeedMicrosecondsMultiplier ); -} - - -inline void CCycleCount::SetMicroseconds( unsigned long nMicroseconds ) -{ - m_Int64 = ((int64)nMicroseconds * g_ClockSpeed) / 1000000; -} - - -inline unsigned long CCycleCount::GetMilliseconds() const -{ - return (unsigned long)((m_Int64 * 1000) / g_ClockSpeed); -} - - -inline double CCycleCount::GetMillisecondsF() const -{ - return (double)( m_Int64 * g_ClockSpeedMillisecondsMultiplier ); -} - - -inline double CCycleCount::GetSeconds() const -{ - return (double)( m_Int64 * g_ClockSpeedSecondsMultiplier ); -} - - -// -------------------------------------------------------------------------- // -// CFastTimer inlines. -// -------------------------------------------------------------------------- // -inline void CFastTimer::Start() -{ - m_Duration.Sample(); -#ifdef DEBUG_FASTTIMER - m_bRunning = true; -#endif -} - - -inline void CFastTimer::End() -{ - CCycleCount cnt; - cnt.Sample(); - if ( IsX360() ) - { - // have to handle rollover, hires timer is only accurate to 32 bits - // more than one overflow should not have occured, otherwise caller should use a slower timer - if ( (uint64)cnt.m_Int64 <= (uint64)m_Duration.m_Int64 ) - { - // rollover occured - cnt.m_Int64 += 0x100000000LL; - } - } - - m_Duration.m_Int64 = cnt.m_Int64 - m_Duration.m_Int64; - -#ifdef DEBUG_FASTTIMER - m_bRunning = false; -#endif -} - -inline CCycleCount CFastTimer::GetDurationInProgress() const -{ - CCycleCount cnt; - cnt.Sample(); - if ( IsX360() ) - { - // have to handle rollover, hires timer is only accurate to 32 bits - // more than one overflow should not have occured, otherwise caller should use a slower timer - if ( (uint64)cnt.m_Int64 <= (uint64)m_Duration.m_Int64 ) - { - // rollover occured - cnt.m_Int64 += 0x100000000LL; - } - } - - CCycleCount result; - result.m_Int64 = cnt.m_Int64 - m_Duration.m_Int64; - - return result; -} - - -inline unsigned long CFastTimer::GetClockSpeed() -{ - return g_dwClockSpeed; -} - - -inline CCycleCount const& CFastTimer::GetDuration() const -{ -#ifdef DEBUG_FASTTIMER - assert( !m_bRunning ); -#endif - return m_Duration; -} - - -// -------------------------------------------------------------------------- // -// CAverageCycleCounter inlines - -inline CAverageCycleCounter::CAverageCycleCounter() - : m_nIters( 0 ) -{ -} - -inline void CAverageCycleCounter::Init() -{ - m_Total.Init(); - m_Peak.Init(); - m_nIters = 0; -} - -inline void CAverageCycleCounter::MarkIter( const CCycleCount &duration ) -{ - ++m_nIters; - m_Total += duration; - if ( m_Peak.IsLessThan( duration ) ) - m_Peak = duration; -} - -inline unsigned CAverageCycleCounter::GetIters() const -{ - return m_nIters; -} - -inline double CAverageCycleCounter::GetAverageMilliseconds() const -{ - if ( m_nIters ) - return (m_Total.GetMillisecondsF() / (double)m_nIters); - else - return 0; -} - -inline double CAverageCycleCounter::GetTotalMilliseconds() const -{ - return m_Total.GetMillisecondsF(); -} - -inline double CAverageCycleCounter::GetPeakMilliseconds() const -{ - return m_Peak.GetMillisecondsF(); -} - -// -------------------------------------------------------------------------- // - -inline CAverageTimeMarker::CAverageTimeMarker( CAverageCycleCounter *pCounter ) -{ - m_pCounter = pCounter; - m_Timer.Start(); -} - -inline CAverageTimeMarker::~CAverageTimeMarker() -{ - m_Timer.End(); - m_pCounter->MarkIter( m_Timer.GetDuration() ); -} - - -// CLimitTimer -// Use this to time whether a desired interval of time has passed. It's extremely fast -// to check while running. -class CLimitTimer -{ -public: - void SetLimit( uint64 m_cMicroSecDuration ); - bool BLimitReached( void ); - -private: - int64 m_lCycleLimit; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Initializes the limit timer with a period of time to measure. -// Input : cMicroSecDuration - How long a time period to measure -//----------------------------------------------------------------------------- -inline void CLimitTimer::SetLimit( uint64 m_cMicroSecDuration ) -{ - int64 dlCycles = ( ( uint64 ) m_cMicroSecDuration * ( int64 ) g_dwClockSpeed ) / ( int64 ) 1000000L; - CCycleCount cycleCount; - cycleCount.Sample( ); - m_lCycleLimit = cycleCount.GetLongCycles( ) + dlCycles; -} - - -//----------------------------------------------------------------------------- -// Purpose: Determines whether our specified time period has passed -// Output: true if at least the specified time period has passed -//----------------------------------------------------------------------------- -inline bool CLimitTimer::BLimitReached( ) -{ - CCycleCount cycleCount; - cycleCount.Sample( ); - return ( cycleCount.GetLongCycles( ) >= m_lCycleLimit ); -} - - - -#endif // FASTTIMER_H diff --git a/public/tier0/ia32detect.h b/public/tier0/ia32detect.h deleted file mode 100644 index 8f5662da4..000000000 --- a/public/tier0/ia32detect.h +++ /dev/null @@ -1,351 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -#ifndef IA32DETECT_H -#define IA32DETECT_H - -/* - This section from http://iss.cs.cornell.edu/ia32.htm - - - */ -typedef unsigned bit; - -enum CPUVendor -{ - INTEL, - AMD, - UNKNOWN_VENDOR -}; -class ia32detect -{ -public: - - enum type_t - { - type_OEM, - type_OverDrive, - type_Dual, - type_reserved - }; - - enum brand_t - { - brand_na, - brand_Celeron, - brand_PentiumIII, - brand_PentiumIIIXeon, - brand_reserved1, - brand_reserved2, - brand_PentiumIIIMobile, - brand_reserved3, - brand_Pentium4, - brand_invalid - }; - -# pragma pack(push, 1) - - struct version_t - { - bit Stepping : 4; - bit Model : 4; - bit Family : 4; - bit Type : 2; - bit Reserved1 : 2; - bit XModel : 4; - bit XFamily : 8; - bit Reserved2 : 4; - }; - - struct misc_t - { - byte Brand; - byte CLFLUSH; - byte Reserved; - byte APICId; - }; - - struct feature_t - { - bit FPU : 1; // Floating Point Unit On-Chip - bit VME : 1; // Virtual 8086 Mode Enhancements - bit DE : 1; // Debugging Extensions - bit PSE : 1; // Page Size Extensions - bit TSC : 1; // Time Stamp Counter - bit MSR : 1; // Model Specific Registers - bit PAE : 1; // Physical Address Extension - bit MCE : 1; // Machine Check Exception - bit CX8 : 1; // CMPXCHG8 Instruction - bit APIC : 1; // APIC On-Chip - bit Reserved1 : 1; - bit SEP : 1; // SYSENTER and SYSEXIT instructions - bit MTRR : 1; // Memory Type Range Registers - bit PGE : 1; // PTE Global Bit - bit MCA : 1; // Machine Check Architecture - bit CMOV : 1; // Conditional Move Instructions - bit PAT : 1; // Page Attribute Table - bit PSE36 : 1; // 32-bit Page Size Extension - bit PSN : 1; // Processor Serial Number - bit CLFSH : 1; // CLFLUSH Instruction - bit Reserved2 : 1; - bit DS : 1; // Debug Store - bit ACPI : 1; // Thermal Monitor and Software Controlled Clock Facilities - bit MMX : 1; // Intel MMX Technology - bit FXSR : 1; // FXSAVE and FXRSTOR Instructions - bit SSE : 1; // Intel SSE Technology - bit SSE2 : 1; // Intel SSE2 Technology - bit SS : 1; // Self Snoop - bit HTT : 1; // Hyper Threading - bit TM : 1; // Thermal Monitor - bit Reserved3 : 1; - bit PBE : 1; // Pending Brk. EN. - }; - -# pragma pack(pop) - - tstring vendor_name; - CPUVendor vendor; - tstring brand; - version_t version; - misc_t misc; - feature_t feature; - byte *cache; - - ia32detect () - { - - cache = 0; - uint32 m = init0(); - - uint32 *d = new uint32[m * 4]; - - for (uint32 i = 1; i <= m; i++) - { - uint32 *t = d + (i - 1) * 4; - - __asm - { - mov eax, i; - mov esi, t; - - cpuid; - - mov dword ptr [esi + 0x0], eax; - mov dword ptr [esi + 0x4], ebx; - mov dword ptr [esi + 0x8], ecx; - mov dword ptr [esi + 0xC], edx; - } - } - - if (m >= 1) - init1(d); - - if (m >= 2) - init2(d[4] & 0xFF); - - delete [] d; - - init0x80000000(); - - - //----------------------------------------------------------------------- - // Get the vendor of the processor - //----------------------------------------------------------------------- - if (_tcscmp(vendor_name.c_str(), _T("GenuineIntel")) == 0) - { - vendor = INTEL; - - } - else if (_tcscmp(vendor_name.c_str(), _T("AuthenticAMD")) == 0) - { - vendor = AMD; - - } - else - { - vendor = UNKNOWN_VENDOR; - } - } - - const tstring version_text () const - { - tchar b[128]; - - _stprintf(b, _T("%d.%d.%d %s XVersion(%d.%d)"), - version.Family, version.Model, version.Stepping, type_text(), version.XFamily, version.XModel); - - return tstring(b); - } - -protected: - - const tchar * type_text () const - { - static const tchar *text[] = - { - _T("Intel OEM Processor"), - _T("Intel OverDrive(R) Processor"), - _T("Intel Dual Processor"), - _T("reserved") - }; - - return text[version.Type]; - } - - const tstring brand_text () const - { - static const tchar *text[] = - { - _T("n/a"), - _T("Celeron"), - _T("Pentium III"), - _T("Pentium III Xeon"), - _T("reserved (4)"), - _T("reserved (5)"), - _T("Pentium III Mobile"), - _T("reserved (7)"), - _T("Pentium 4") - }; - - if (misc.Brand < brand_invalid) - return tstring(text[misc.Brand]); - else - { - tchar b[32]; - - _stprintf(b, _T("Brand %d (Update)"), misc.Brand); - - return tstring(b); - } - } - -private: - - uint32 init0 () - { - uint32 m; - tchar s1[13]; - - s1[12] = '\0'; - - __asm - { - xor eax, eax; - cpuid; - mov m, eax; - mov dword ptr s1 + 0, ebx; - mov dword ptr s1 + 4, edx; - mov dword ptr s1 + 8, ecx; - } - - vendor_name = s1; - - return m; - } - - void init1 (uint32 *d) - { - version = *(version_t *)&d[0]; - misc = *(misc_t *)&d[1]; - feature = *(feature_t *)&d[3]; - } - - void process2 (uint32 d, bool c[]) - { - if ((d & 0x80000000) == 0) - for (int i = 0; i < 32; i += 8) - c[(d >> i) & 0xFF] = true; - } - - void init2 (byte count) - { - uint32 d[4]; - bool c[256]; - - for (int ci1 = 0; ci1 < 256; ci1++) - c[ci1] = false; - - for (int i = 0; i < count; i++) - { - __asm - { - mov eax, 2; - lea esi, d; - cpuid; - mov [esi + 0x0], eax; - mov [esi + 0x4], ebx; - mov [esi + 0x8], ecx; - mov [esi + 0xC], edx; - } - - if (i == 0) - d[0] &= 0xFFFFFF00; - - process2(d[0], c); - process2(d[1], c); - process2(d[2], c); - process2(d[3], c); - } - - int m = 0; - - for (int ci2 = 0; ci2 < 256; ci2++) - if (c[ci2]) - m++; - - cache = new byte[m]; - - m = 0; - - for (int ci3 = 1; ci3 < 256; ci3++) - if (c[ci3]) - cache[m++] = ci3; - - cache[m] = 0; - } - - void init0x80000000 () - { - uint32 m; - - __asm - { - mov eax, 0x80000000; - cpuid; - mov m, eax - } - - if ((m & 0x80000000) != 0) - { - uint32 *d = new uint32[(m - 0x80000000) * 4]; - - for (uint32 i = 0x80000001; i <= m; i++) - { - uint32 *t = d + (i - 0x80000001) * 4; - - __asm - { - mov eax, i; - mov esi, t; - cpuid; - mov dword ptr [esi + 0x0], eax; - mov dword ptr [esi + 0x4], ebx; - mov dword ptr [esi + 0x8], ecx; - mov dword ptr [esi + 0xC], edx; - } - } - - if (m >= 0x80000002) - brand = (tchar *)(d + 4); - - // note the assignment to brand above does a copy, we need to delete - delete[] d; - } - } -}; - -#endif // IA32DETECT_H diff --git a/public/tier0/icommandline.h b/public/tier0/icommandline.h deleted file mode 100644 index 36c4d65cc..000000000 --- a/public/tier0/icommandline.h +++ /dev/null @@ -1,53 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#ifndef TIER0_ICOMMANDLINE_H -#define TIER0_ICOMMANDLINE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/platform.h" - - -//----------------------------------------------------------------------------- -// Purpose: Interface to engine command line -//----------------------------------------------------------------------------- -abstract_class ICommandLine -{ -public: - virtual void CreateCmdLine( const char *commandline ) = 0; - virtual void CreateCmdLine( int argc, char **argv ) = 0; - virtual const char *GetCmdLine( void ) const = 0; - - // Check whether a particular parameter exists - virtual const char *CheckParm( const char *psz, const char **ppszValue = 0 ) const = 0; - virtual void RemoveParm( const char *parm ) = 0; - virtual void AppendParm( const char *pszParm, const char *pszValues ) = 0; - - // Returns the argument after the one specified, or the default if not found - virtual const char *ParmValue( const char *psz, const char *pDefaultVal = 0 ) const = 0; - virtual int ParmValue( const char *psz, int nDefaultVal ) const = 0; - virtual float ParmValue( const char *psz, float flDefaultVal ) const = 0; - - // Gets at particular parameters - virtual int ParmCount() const = 0; - virtual int FindParm( const char *psz ) const = 0; // Returns 0 if not found. - virtual const char* GetParm( int nIndex ) const = 0; -}; - -//----------------------------------------------------------------------------- -// Gets a singleton to the commandline interface -// NOTE: The #define trickery here is necessary for backwards compat: -// this interface used to lie in the vstdlib library. -//----------------------------------------------------------------------------- -PLATFORM_INTERFACE ICommandLine *CommandLine_Tier0(); - -#if !defined( VSTDLIB_BACKWARD_COMPAT ) -#define CommandLine CommandLine_Tier0 -#endif - -#endif // TIER0_ICOMMANDLINE_H diff --git a/public/tier0/l2cache.h b/public/tier0/l2cache.h deleted file mode 100644 index 4ca2dc591..000000000 --- a/public/tier0/l2cache.h +++ /dev/null @@ -1,46 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// -#ifndef CL2CACHE_H -#define CL2CACHE_H -#ifdef _WIN32 -#pragma once -#endif - -class P4Event_BSQ_cache_reference; - -class CL2Cache -{ -public: - - CL2Cache(); - ~CL2Cache(); - - void Start( void ); - void End( void ); - - //------------------------------------------------------------------------- - // GetL2CacheMisses - //------------------------------------------------------------------------- - int GetL2CacheMisses( void ) - { - return m_iL2CacheMissCount; - } - -#ifdef DBGFLAG_VALIDATE - void Validate( CValidator &validator, tchar *pchName ); // Validate our internal structures -#endif // DBGFLAG_VALIDATE - -private: - - int m_nID; - - P4Event_BSQ_cache_reference *m_pL2CacheEvent; - int64 m_i64Start; - int64 m_i64End; - int m_iL2CacheMissCount; -}; - -#endif // CL2CACHE_H diff --git a/public/tier0/mem.h b/public/tier0/mem.h deleted file mode 100644 index cb59c92a8..000000000 --- a/public/tier0/mem.h +++ /dev/null @@ -1,45 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Memory allocation! -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef TIER0_MEM_H -#define TIER0_MEM_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include "tier0/platform.h" - -#if !defined(STATIC_TIER0) && !defined(_STATIC_LINKED) - -#ifdef TIER0_DLL_EXPORT -# define MEM_INTERFACE DLL_EXPORT -#else -# define MEM_INTERFACE DLL_IMPORT -#endif - -#else // BUILD_AS_DLL - -#define MEM_INTERFACE extern - -#endif // BUILD_AS_DLL - - - -//----------------------------------------------------------------------------- -// DLL-exported methods for particular kinds of memory -//----------------------------------------------------------------------------- -MEM_INTERFACE void *MemAllocScratch( int nMemSize ); -MEM_INTERFACE void MemFreeScratch(); - -#ifdef _LINUX -MEM_INTERFACE void ZeroMemory( void *mem, size_t length ); -#endif - - -#endif /* TIER0_MEM_H */ diff --git a/public/tier0/memalloc.h b/public/tier0/memalloc.h deleted file mode 100644 index 61167dd2e..000000000 --- a/public/tier0/memalloc.h +++ /dev/null @@ -1,358 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: This header should never be used directly from leaf code!!! -// Instead, just add the file memoverride.cpp into your project and all this -// will automagically be used -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef TIER0_MEMALLOC_H -#define TIER0_MEMALLOC_H - -#ifdef _WIN32 -#pragma once -#endif - -#if defined(_LINUX) || defined(__APPLE__) -#define NO_MALLOC_OVERRIDE -#endif - -// Define this in release to get memory tracking even in release builds -//#define USE_MEM_DEBUG 1 - -#if defined( _MEMTEST ) -#define USE_MEM_DEBUG 1 -#endif - -// Undefine this if using a compiler lacking threadsafe RTTI (like vc6) -#define MEM_DEBUG_CLASSNAME 1 - -#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE) - -#include -#include "tier0/mem.h" - -struct _CrtMemState; - -#define MEMALLOC_VERSION 1 - -typedef size_t (*MemAllocFailHandler_t)( size_t ); - -//----------------------------------------------------------------------------- -// NOTE! This should never be called directly from leaf code -// Just use new,delete,malloc,free etc. They will call into this eventually -//----------------------------------------------------------------------------- -abstract_class IMemAlloc -{ -public: - // Release versions - virtual void *Alloc( size_t nSize ) = 0; - virtual void *Realloc( void *pMem, size_t nSize ) = 0; - virtual void Free( void *pMem ) = 0; - virtual void *Expand_NoLongerSupported( void *pMem, size_t nSize ) = 0; - - // Debug versions - virtual void *Alloc( size_t nSize, const char *pFileName, int nLine ) = 0; - virtual void *Realloc( void *pMem, size_t nSize, const char *pFileName, int nLine ) = 0; - virtual void Free( void *pMem, const char *pFileName, int nLine ) = 0; - virtual void *Expand_NoLongerSupported( void *pMem, size_t nSize, const char *pFileName, int nLine ) = 0; - - // Returns size of a particular allocation - virtual size_t GetSize( void *pMem ) = 0; - - // Force file + line information for an allocation - virtual void PushAllocDbgInfo( const char *pFileName, int nLine ) = 0; - virtual void PopAllocDbgInfo() = 0; - - // FIXME: Remove when we have our own allocator - // these methods of the Crt debug code is used in our codebase currently - virtual long CrtSetBreakAlloc( long lNewBreakAlloc ) = 0; - virtual int CrtSetReportMode( int nReportType, int nReportMode ) = 0; - virtual int CrtIsValidHeapPointer( const void *pMem ) = 0; - virtual int CrtIsValidPointer( const void *pMem, unsigned int size, int access ) = 0; - virtual int CrtCheckMemory( void ) = 0; - virtual int CrtSetDbgFlag( int nNewFlag ) = 0; - virtual void CrtMemCheckpoint( _CrtMemState *pState ) = 0; - - // FIXME: Make a better stats interface - virtual void DumpStats() = 0; - virtual void DumpStatsFileBase( char const *pchFileBase ) = 0; - - // FIXME: Remove when we have our own allocator - virtual void* CrtSetReportFile( int nRptType, void* hFile ) = 0; - virtual void* CrtSetReportHook( void* pfnNewHook ) = 0; - virtual int CrtDbgReport( int nRptType, const char * szFile, - int nLine, const char * szModule, const char * pMsg ) = 0; - - virtual int heapchk() = 0; - - virtual bool IsDebugHeap() = 0; - - virtual void GetActualDbgInfo( const char *&pFileName, int &nLine ) = 0; - virtual void RegisterAllocation( const char *pFileName, int nLine, int nLogicalSize, int nActualSize, unsigned nTime ) = 0; - virtual void RegisterDeallocation( const char *pFileName, int nLine, int nLogicalSize, int nActualSize, unsigned nTime ) = 0; - - virtual int GetVersion() = 0; - - virtual void CompactHeap() = 0; - - // Function called when malloc fails or memory limits hit to attempt to free up memory (can come in any thread) - virtual MemAllocFailHandler_t SetAllocFailHandler( MemAllocFailHandler_t pfnMemAllocFailHandler ) = 0; - - virtual void DumpBlockStats( void * ) = 0; - -#if defined( _MEMTEST ) - virtual void SetStatsExtraInfo( const char *pMapName, const char *pComment ) = 0; -#endif - - // Returns 0 if no failure, otherwise the size_t of the last requested chunk - virtual size_t MemoryAllocFailed() = 0; -}; - -//----------------------------------------------------------------------------- -// Singleton interface -//----------------------------------------------------------------------------- -MEM_INTERFACE IMemAlloc *g_pMemAlloc; - -//----------------------------------------------------------------------------- - -inline void *MemAlloc_AllocAligned( size_t size, size_t align ) -{ - unsigned char *pAlloc, *pResult; - - if (!IsPowerOfTwo(uint(align))) - return NULL; - - align = (align > sizeof(void *) ? align : sizeof(void *)) - 1; - - if ( (pAlloc = (unsigned char*)g_pMemAlloc->Alloc( sizeof(void *) + align + size ) ) == (unsigned char*)NULL) - return NULL; - - pResult = (unsigned char*)( (size_t)(pAlloc + sizeof(void *) + align ) & ~align ); - ((unsigned char**)(pResult))[-1] = pAlloc; - - return (void *)pResult; -} - -inline void *MemAlloc_AllocAligned( size_t size, size_t align, const char *pszFile, int nLine ) -{ - unsigned char *pAlloc, *pResult; - - if (!IsPowerOfTwo(uint(align))) - return NULL; - - align = (align > sizeof(void *) ? align : sizeof(void *)) - 1; - - if ( (pAlloc = (unsigned char*)g_pMemAlloc->Alloc( sizeof(void *) + align + size, pszFile, nLine ) ) == (unsigned char*)NULL) - return NULL; - - pResult = (unsigned char*)( (size_t)(pAlloc + sizeof(void *) + align ) & ~align ); - ((unsigned char**)(pResult))[-1] = pAlloc; - - return (void *)pResult; -} - -inline void *MemAlloc_ReallocAligned( void *ptr, size_t size, size_t align ) -{ - if ( !IsPowerOfTwo( uint(align) ) ) - return NULL; - - // Don't change alignment between allocation + reallocation. - if ( ( (size_t)ptr & ( align - 1 ) ) != 0 ) - return NULL; - - if ( !ptr ) - return MemAlloc_AllocAligned( size, align ); - - void *pAlloc, *pResult; - - // Figure out the actual allocation point - pAlloc = ptr; - pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *)); - pAlloc = *( (void **)pAlloc ); - - // See if we have enough space - size_t nOffset = (size_t)ptr - (size_t)pAlloc; - size_t nOldSize = g_pMemAlloc->GetSize( pAlloc ); - if ( nOldSize >= size + nOffset ) - return ptr; - - pResult = MemAlloc_AllocAligned( size, align ); - memcpy( pResult, ptr, nOldSize - nOffset ); - g_pMemAlloc->Free( pAlloc ); - return pResult; -} - -inline void MemAlloc_FreeAligned( void *pMemBlock ) -{ - void *pAlloc; - - if ( pMemBlock == NULL ) - return; - - pAlloc = pMemBlock; - - // pAlloc points to the pointer to starting of the memory block - pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *)); - - // pAlloc is the pointer to the start of memory block - pAlloc = *( (void **)pAlloc ); - g_pMemAlloc->Free( pAlloc ); -} - -inline size_t MemAlloc_GetSizeAligned( void *pMemBlock ) -{ - void *pAlloc; - - if ( pMemBlock == NULL ) - return 0; - - pAlloc = pMemBlock; - - // pAlloc points to the pointer to starting of the memory block - pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *)); - - // pAlloc is the pointer to the start of memory block - pAlloc = *((void **)pAlloc ); - return g_pMemAlloc->GetSize( pAlloc ) - ( (byte *)pMemBlock - (byte *)pAlloc ); -} - -//----------------------------------------------------------------------------- - -#if (defined(_DEBUG) || defined(USE_MEM_DEBUG)) -#define MEM_ALLOC_CREDIT_(tag) CMemAllocAttributeAlloction memAllocAttributeAlloction( tag, __LINE__ ) -#define MemAlloc_PushAllocDbgInfo( pszFile, line ) g_pMemAlloc->PushAllocDbgInfo( pszFile, line ) -#define MemAlloc_PopAllocDbgInfo() g_pMemAlloc->PopAllocDbgInfo() -#define MemAlloc_RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) g_pMemAlloc->RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) -#define MemAlloc_RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) g_pMemAlloc->RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) -#else -#define MEM_ALLOC_CREDIT_(tag) ((void)0) -#define MemAlloc_PushAllocDbgInfo( pszFile, line ) ((void)0) -#define MemAlloc_PopAllocDbgInfo() ((void)0) -#define MemAlloc_RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0) -#define MemAlloc_RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0) -#endif - -//----------------------------------------------------------------------------- - -class CMemAllocAttributeAlloction -{ -public: - CMemAllocAttributeAlloction( const char *pszFile, int line ) - { - MemAlloc_PushAllocDbgInfo( pszFile, line ); - } - - ~CMemAllocAttributeAlloction() - { - MemAlloc_PopAllocDbgInfo(); - } -}; - -#define MEM_ALLOC_CREDIT() MEM_ALLOC_CREDIT_(__FILE__) - -//----------------------------------------------------------------------------- - -#if defined(_WIN32) && ( defined(_DEBUG) || defined(USE_MEM_DEBUG) ) - - #pragma warning(disable:4290) - #pragma warning(push) - #include - - // MEM_DEBUG_CLASSNAME is opt-in. - // Note: typeid().name() is not threadsafe, so if the project needs to access it in multiple threads - // simultaneously, it'll need a mutex. - #if defined(_CPPRTTI) && defined(MEM_DEBUG_CLASSNAME) - #define MEM_ALLOC_CREDIT_CLASS() MEM_ALLOC_CREDIT_( typeid(*this).name() ) - #define MEM_ALLOC_CLASSNAME(type) (typeid((type*)(0)).name()) - #else - #define MEM_ALLOC_CREDIT_CLASS() MEM_ALLOC_CREDIT_( __FILE__ ) - #define MEM_ALLOC_CLASSNAME(type) (__FILE__) - #endif - - // MEM_ALLOC_CREDIT_FUNCTION is used when no this pointer is available ( inside 'new' overloads, for example ) - #ifdef _MSC_VER - #define MEM_ALLOC_CREDIT_FUNCTION() MEM_ALLOC_CREDIT_( __FUNCTION__ ) - #else - #define MEM_ALLOC_CREDIT_FUNCTION() (__FILE__) - #endif - - #pragma warning(pop) -#else - #define MEM_ALLOC_CREDIT_CLASS() - #define MEM_ALLOC_CLASSNAME(type) NULL - #define MEM_ALLOC_CREDIT_FUNCTION() -#endif - -//----------------------------------------------------------------------------- - -#if (defined(_DEBUG) || defined(USE_MEM_DEBUG)) -struct MemAllocFileLine_t -{ - const char *pszFile; - int line; -}; - -#define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag ) \ - static CUtlMap g_##tag##Allocs( DefLessFunc( void *) ); \ - static const char *g_psz##tag##Alloc = strcpy( (char *)g_pMemAlloc->Alloc( strlen( #tag "Alloc" ) + 1, "intentional leak", 0 ), #tag "Alloc" ); - -#define MemAlloc_RegisterExternalAllocation( tag, p, size ) \ - if ( !p ) \ - ; \ - else \ - { \ - MemAllocFileLine_t fileLine = { g_psz##tag##Alloc, 0 }; \ - g_pMemAlloc->GetActualDbgInfo( fileLine.pszFile, fileLine.line ); \ - if ( fileLine.pszFile != g_psz##tag##Alloc ) \ - { \ - g_##tag##Allocs.Insert( p, fileLine ); \ - } \ - \ - MemAlloc_RegisterAllocation( fileLine.pszFile, fileLine.line, size, size, 0); \ - } - -#define MemAlloc_RegisterExternalDeallocation( tag, p, size ) \ - if ( !p ) \ - ; \ - else \ - { \ - MemAllocFileLine_t fileLine = { g_psz##tag##Alloc, 0 }; \ - CUtlMap::IndexType_t iRecordedFileLine = g_##tag##Allocs.Find( p ); \ - if ( iRecordedFileLine != g_##tag##Allocs.InvalidIndex() ) \ - { \ - fileLine = g_##tag##Allocs[iRecordedFileLine]; \ - g_##tag##Allocs.RemoveAt( iRecordedFileLine ); \ - } \ - \ - MemAlloc_RegisterDeallocation( fileLine.pszFile, fileLine.line, size, size, 0); \ - } - -#else - -#define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag ) -#define MemAlloc_RegisterExternalAllocation( tag, p, size ) ((void)0) -#define MemAlloc_RegisterExternalDeallocation( tag, p, size ) ((void)0) - -#endif - -//----------------------------------------------------------------------------- - -#endif // !STEAM && !NO_MALLOC_OVERRIDE - -//----------------------------------------------------------------------------- - -#if !defined(STEAM) && defined(NO_MALLOC_OVERRIDE) - -#define MEM_ALLOC_CREDIT_(tag) ((void)0) -#define MEM_ALLOC_CREDIT() MEM_ALLOC_CREDIT_(__FILE__) -#define MEM_ALLOC_CREDIT_CLASS() -#define MEM_ALLOC_CLASSNAME(type) NULL -#define MEM_ALLOC_CREDIT_FUNCTION() - -#endif // !STEAM && NO_MALLOC_OVERRIDE - -//----------------------------------------------------------------------------- - -#endif /* TIER0_MEMALLOC_H */ diff --git a/public/tier0/memdbgoff.h b/public/tier0/memdbgoff.h deleted file mode 100644 index 4d2c0219f..000000000 --- a/public/tier0/memdbgoff.h +++ /dev/null @@ -1,25 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: This header, which must be the final line of a .h file, -// causes all crt methods to stop using debugging versions of the memory allocators. -// NOTE: Use memdbgon.h to re-enable memory debugging. -// -// $NoKeywords: $ -//=============================================================================// - -#ifdef MEM_OVERRIDE_ON - -#undef malloc -#undef realloc -#undef calloc -#undef free -#undef _expand -#undef _msize -#undef new -#undef _aligned_malloc -#undef _aligned_free -#undef _malloc_dbg - -#undef MEM_OVERRIDE_ON - -#endif diff --git a/public/tier0/memdbgon.h b/public/tier0/memdbgon.h deleted file mode 100644 index ef77147cd..000000000 --- a/public/tier0/memdbgon.h +++ /dev/null @@ -1,251 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: This header, which must be the final include in a .cpp (or .h) file, -// causes all crt methods to use debugging versions of the memory allocators. -// NOTE: Use memdbgoff.h to disable memory debugging. -// -// $NoKeywords: $ -//=============================================================================// - -// SPECIAL NOTE! This file must *not* use include guards; we need to be able -// to include this potentially multiple times (since we can deactivate debugging -// by including memdbgoff.h) - -#if defined(_LINUX) || defined(__APPLE__) -#define NO_MALLOC_OVERRIDE -#endif - -#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE) - -// SPECIAL NOTE #2: This must be the final include in a .cpp or .h file!!! - -#if defined(_DEBUG) && !defined(USE_MEM_DEBUG) -#define USE_MEM_DEBUG 1 -#endif - -// If debug build or ndebug and not already included MS custom alloc files, or already included this file -#if (defined(_DEBUG) || !defined(_INC_CRTDBG)) || defined(MEMDBGON_H) - -#include "basetypes.h" -#ifdef _WIN32 -#include -#else -#include -#endif -#include -#if defined __APPLE__ -#include -#else -#include -#endif -#include "commonmacros.h" -#include "memalloc.h" - -#if defined(USE_MEM_DEBUG) - #if defined(_LINUX) || defined(__APPLE__) - - #define _NORMAL_BLOCK 1 - - #include - #include - #include - #include - - #if !defined( DID_THE_OPERATOR_NEW ) - #define DID_THE_OPERATOR_NEW - inline void* operator new( size_t nSize, int blah, const char *pFileName, int nLine ) - { - return g_pMemAlloc->Alloc( nSize, pFileName, nLine ); - } - inline void* operator new[]( size_t nSize, int blah, const char *pFileName, int nLine ) - { - return g_pMemAlloc->Alloc( nSize, pFileName, nLine ); - } - #endif - - #else // defined(_LINUX) - - // Include crtdbg.h and make sure _DEBUG is set to 1. - #if !defined(_DEBUG) - #define _DEBUG 1 - #include - #undef _DEBUG - #else - #include - #endif // !defined(_DEBUG) - - #endif // defined(_LINUX) -#endif - -#include "tier0/memdbgoff.h" - -// -------------------------------------------------------- -// Debug/non-debug agnostic elements - -#define MEM_OVERRIDE_ON 1 - -#undef malloc -#undef realloc -#undef calloc -#undef _expand -#undef free -#undef _msize -#undef _aligned_malloc -#undef _aligned_free - -#ifndef MEMDBGON_H -inline void *MemAlloc_InlineCallocMemset( void *pMem, size_t nCount, size_t nElementSize) -{ - memset(pMem, 0, nElementSize * nCount); - return pMem; -} -#endif - -#define calloc(c, s) MemAlloc_InlineCallocMemset(malloc(c*s), c, s) -#define free(p) g_pMemAlloc->Free( p ) -#define _msize(p) g_pMemAlloc->GetSize( p ) -#define _expand(p, s) _expand_NoLongerSupported(p, s) -#define _aligned_free( p ) MemAlloc_FreeAligned( p ) - -// -------------------------------------------------------- -// Debug path -#if defined(USE_MEM_DEBUG) - -#define malloc(s) g_pMemAlloc->Alloc( s, __FILE__, __LINE__) -#define realloc(p, s) g_pMemAlloc->Realloc( p, s, __FILE__, __LINE__ ) -#define _aligned_malloc( s, a ) MemAlloc_AllocAligned( s, a, __FILE__, __LINE__ ) - -#define _malloc_dbg(s, t, f, l) WHYCALLINGTHISDIRECTLY(s) - -#if defined(__AFX_H__) && defined(DEBUG_NEW) - #define new DEBUG_NEW -#else - #undef new - #define MEMALL_DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) - #define new MEMALL_DEBUG_NEW -#endif - -#undef _strdup -#undef strdup -#undef _wcsdup -#undef wcsdup - -#define _strdup(s) MemAlloc_StrDup(s, __FILE__, __LINE__) -#define strdup(s) MemAlloc_StrDup(s, __FILE__, __LINE__) -#define _wcsdup(s) MemAlloc_WcStrDup(s, __FILE__, __LINE__) -#define wcsdup(s) MemAlloc_WcStrDup(s, __FILE__, __LINE__) - -// Make sure we don't define strdup twice -#if !defined(MEMDBGON_H) - -inline char *MemAlloc_StrDup(const char *pString, const char *pFileName, unsigned nLine) -{ - char *pMemory; - - if (!pString) - return NULL; - - size_t len = strlen(pString) + 1; - if ((pMemory = (char *)g_pMemAlloc->Alloc(len, pFileName, nLine)) != NULL) - { - return strcpy( pMemory, pString ); - } - - return NULL; -} - -inline wchar_t *MemAlloc_WcStrDup(const wchar_t *pString, const char *pFileName, unsigned nLine) -{ - wchar_t *pMemory; - - if (!pString) - return NULL; - - size_t len = (wcslen(pString) + 1); - if ((pMemory = (wchar_t *)g_pMemAlloc->Alloc(len * sizeof(wchar_t), pFileName, nLine)) != NULL) - { - return wcscpy( pMemory, pString ); - } - - return NULL; -} - -#endif // DBMEM_DEFINED_STRDUP - -#else -// -------------------------------------------------------- -// Release path - -#define malloc(s) g_pMemAlloc->Alloc( s ) -#define realloc(p, s) g_pMemAlloc->Realloc( p, s ) -#define _aligned_malloc( s, a ) MemAlloc_AllocAligned( s, a ) - -#ifndef _malloc_dbg -#define _malloc_dbg(s, t, f, l) WHYCALLINGTHISDIRECTLY(s) -#endif - -#undef new - -#undef _strdup -#undef strdup -#undef _wcsdup -#undef wcsdup - -#define _strdup(s) MemAlloc_StrDup(s) -#define strdup(s) MemAlloc_StrDup(s) -#define _wcsdup(s) MemAlloc_WcStrDup(s) -#define wcsdup(s) MemAlloc_WcStrDup(s) - -// Make sure we don't define strdup twice -#if !defined(MEMDBGON_H) - -inline char *MemAlloc_StrDup(const char *pString) -{ - char *pMemory; - - if (!pString) - return NULL; - - size_t len = strlen(pString) + 1; - if ((pMemory = (char *)g_pMemAlloc->Alloc(len)) != NULL) - { - return strcpy( pMemory, pString ); - } - - return NULL; -} - -inline wchar_t *MemAlloc_WcStrDup(const wchar_t *pString) -{ - wchar_t *pMemory; - - if (!pString) - return NULL; - - size_t len = (wcslen(pString) + 1); - if ((pMemory = (wchar_t *)g_pMemAlloc->Alloc(len * sizeof(wchar_t))) != NULL) - { - return wcscpy( pMemory, pString ); - } - - return NULL; -} - -#endif // DBMEM_DEFINED_STRDUP - -#endif // USE_MEM_DEBUG - -#define MEMDBGON_H // Defined here so can be used above - -#else - -#if defined(USE_MEM_DEBUG) -#ifndef _STATIC_LINKED -#pragma message ("Note: file includes crtdbg.h directly, therefore will cannot use memdbgon.h in non-debug build") -#else -#error "Error: file includes crtdbg.h directly, therefore will cannot use memdbgon.h in non-debug build. Not recoverable in static build" -#endif -#endif -#endif // _INC_CRTDBG - -#endif // !STEAM && !NO_MALLOC_OVERRIDE diff --git a/public/tier0/memoverride.cpp b/public/tier0/memoverride.cpp deleted file mode 100644 index cbc07b305..000000000 --- a/public/tier0/memoverride.cpp +++ /dev/null @@ -1,1385 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Insert this file into all projects using the memory system -// It will cause that project to use the shader memory allocator -// -// $NoKeywords: $ -//=============================================================================// - - -#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE) - -#undef PROTECTED_THINGS_ENABLE // allow use of _vsnprintf - -#if defined( _WIN32 ) && !defined( _X360 ) -#define WIN_32_LEAN_AND_MEAN -#include -#endif - -#include "tier0/dbg.h" -#include "tier0/memalloc.h" -#include -#include -#include "memdbgoff.h" - -// Tags this DLL as debug -#if defined( _DEBUG ) && !defined( _X360 ) -DLL_EXPORT void BuiltDebug() {} -#endif - -#ifdef _WIN32 -// ARG: crtdbg is necessary for certain definitions below, -// but it also redefines malloc as a macro in release. -// To disable this, we gotta define _DEBUG before including it.. BLEAH! -#define _DEBUG 1 -#include "crtdbg.h" -#ifdef NDEBUG -#undef _DEBUG -#endif - -// Turn this back off in release mode. -#ifdef NDEBUG -#undef _DEBUG -#endif -#elif _LINUX -#define __cdecl -#endif - -#if defined( _WIN32 ) && !defined( _X360 ) -const char *MakeModuleFileName() -{ - if ( g_pMemAlloc->IsDebugHeap() ) - { - char *pszModuleName = (char *)HeapAlloc( GetProcessHeap(), 0, MAX_PATH ); // small leak, debug only - - MEMORY_BASIC_INFORMATION mbi; - static int dummy; - VirtualQuery( &dummy, &mbi, sizeof(mbi) ); - - GetModuleFileName( reinterpret_cast(mbi.AllocationBase), pszModuleName, MAX_PATH ); - char *pDot = strrchr( pszModuleName, '.' ); - if ( pDot ) - { - char *pSlash = strrchr( pszModuleName, '\\' ); - if ( pSlash ) - { - pszModuleName = pSlash + 1; - *pDot = 0; - } - } - - return pszModuleName; - } - return NULL; -} - -static void *AllocUnattributed( size_t nSize ) -{ - static const char *pszOwner = MakeModuleFileName(); - - if ( !pszOwner ) - return g_pMemAlloc->Alloc(nSize); - else - return g_pMemAlloc->Alloc(nSize, pszOwner, 0); -} - -static void *ReallocUnattributed( void *pMem, size_t nSize ) -{ - static const char *pszOwner = MakeModuleFileName(); - - if ( !pszOwner ) - return g_pMemAlloc->Realloc(pMem, nSize); - else - return g_pMemAlloc->Realloc(pMem, nSize, pszOwner, 0); -} - -#else -#define MakeModuleFileName() NULL -inline void *AllocUnattributed( size_t nSize ) -{ - return g_pMemAlloc->Alloc(nSize); -} - -inline void *ReallocUnattributed( void *pMem, size_t nSize ) -{ - return g_pMemAlloc->Realloc(pMem, nSize); -} -#endif - -//----------------------------------------------------------------------------- -// Standard functions in the CRT that we're going to override to call our allocator -//----------------------------------------------------------------------------- -#if defined(_WIN32) && !defined(_STATIC_LINKED) -// this magic only works under win32 -// under linux this malloc() overrides the libc malloc() and so we -// end up in a recursion (as g_pMemAlloc->Alloc() calls malloc) -#if _MSC_VER >= 1400 -#define ALLOC_CALL _CRTNOALIAS _CRTRESTRICT -#define FREE_CALL _CRTNOALIAS -#else -#define ALLOC_CALL -#define FREE_CALL -#endif - -extern "C" -{ - -ALLOC_CALL void *malloc( size_t nSize ) -{ - return AllocUnattributed( nSize ); -} - -FREE_CALL void free( void *pMem ) -{ - g_pMemAlloc->Free(pMem); -} - -ALLOC_CALL void *realloc( void *pMem, size_t nSize ) -{ - return ReallocUnattributed( pMem, nSize ); -} - -ALLOC_CALL void *calloc( size_t nCount, size_t nElementSize ) -{ - void *pMem = AllocUnattributed( nElementSize * nCount ); - memset(pMem, 0, nElementSize * nCount); - return pMem; -} - -} // end extern "C" - -//----------------------------------------------------------------------------- -// Non-standard MSVC functions that we're going to override to call our allocator -//----------------------------------------------------------------------------- -extern "C" -{ - -// 64-bit -#ifdef _WIN64 -void* __cdecl _malloc_base( size_t nSize ) -{ - return AllocUnattributed( nSize ); -} -#else -void *_malloc_base( size_t nSize ) -{ - return AllocUnattributed( nSize ); -} -#endif - -void *_calloc_base( size_t nSize ) -{ - void *pMem = AllocUnattributed( nSize ); - memset(pMem, 0, nSize); - return pMem; -} - -void *_realloc_base( void *pMem, size_t nSize ) -{ - return ReallocUnattributed( pMem, nSize ); -} - -void *_recalloc_base( void *pMem, size_t nSize ) -{ - void *pMemOut = ReallocUnattributed( pMem, nSize ); - memset(pMemOut, 0, nSize); - return pMemOut; -} - -void _free_base( void *pMem ) -{ - g_pMemAlloc->Free(pMem); -} - -void *__cdecl _expand_base( void *pMem, size_t nNewSize, int nBlockUse ) -{ - Assert( 0 ); - return NULL; -} - -// crt -void * __cdecl _malloc_crt(size_t size) -{ - return AllocUnattributed( size ); -} - -void * __cdecl _calloc_crt(size_t count, size_t size) -{ - return _calloc_base( count * size ); -} - -void * __cdecl _realloc_crt(void *ptr, size_t size) -{ - return _realloc_base( ptr, size ); -} - -void * __cdecl _recalloc_crt(void *ptr, size_t count, size_t size) -{ - return _recalloc_base( ptr, size * count ); -} - -ALLOC_CALL void * __cdecl _recalloc ( void * memblock, size_t count, size_t size ) -{ - void *pMem = ReallocUnattributed( memblock, size * count ); - memset( pMem, 0, size * count ); - return pMem; -} - -size_t _msize_base( void *pMem ) -{ - return g_pMemAlloc->GetSize(pMem); -} - -size_t _msize( void *pMem ) -{ - return _msize_base(pMem); -} - -size_t msize( void *pMem ) -{ - return g_pMemAlloc->GetSize(pMem); -} - -void *__cdecl _heap_alloc( size_t nSize ) -{ - return AllocUnattributed( nSize ); -} - -void *__cdecl _nh_malloc( size_t nSize, int ) -{ - return AllocUnattributed( nSize ); -} - -void *__cdecl _expand( void *pMem, size_t nSize ) -{ - Assert( 0 ); - return NULL; -} - -unsigned int _amblksiz = 16; //BYTES_PER_PARA; - -#if _MSC_VER >= 1400 -HANDLE _crtheap = (HANDLE)1; // PatM Can't be 0 or CRT pukes -int __active_heap = 1; -#endif // _MSC_VER >= 1400 - -size_t __cdecl _get_sbh_threshold( void ) -{ - return 0; -} - -int __cdecl _set_sbh_threshold( size_t ) -{ - return 0; -} - -int _heapchk() -{ - return g_pMemAlloc->heapchk(); -} - -int _heapmin() -{ - return 1; -} - -int __cdecl _heapadd( void *, size_t ) -{ - return 0; -} - -int __cdecl _heapset( unsigned int ) -{ - return 0; -} - -size_t __cdecl _heapused( size_t *, size_t * ) -{ - return 0; -} - -#ifdef _WIN32 -int __cdecl _heapwalk( _HEAPINFO * ) -{ - return 0; -} -#endif - -} // end extern "C" - - -//----------------------------------------------------------------------------- -// Debugging functions that we're going to override to call our allocator -// NOTE: These have to be here for release + debug builds in case we -// link to a debug static lib!!! -//----------------------------------------------------------------------------- - -extern "C" -{ - -void *malloc_db( size_t nSize, const char *pFileName, int nLine ) -{ - return g_pMemAlloc->Alloc(nSize, pFileName, nLine); -} - -void free_db( void *pMem, const char *pFileName, int nLine ) -{ - g_pMemAlloc->Free(pMem, pFileName, nLine); -} - -void *realloc_db( void *pMem, size_t nSize, const char *pFileName, int nLine ) -{ - return g_pMemAlloc->Realloc(pMem, nSize, pFileName, nLine); -} - -} // end extern "C" - -//----------------------------------------------------------------------------- -// These methods are standard MSVC heap initialization + shutdown methods -//----------------------------------------------------------------------------- -extern "C" -{ - -#if !defined( _X360 ) - int __cdecl _heap_init() - { - return g_pMemAlloc != NULL; - } - - void __cdecl _heap_term() - { - } -#endif - -} -#endif - - -//----------------------------------------------------------------------------- -// Prevents us from using an inappropriate new or delete method, -// ensures they are here even when linking against debug or release static libs -//----------------------------------------------------------------------------- -#ifndef NO_MEMOVERRIDE_NEW_DELETE -void *__cdecl operator new( unsigned int nSize ) -{ - return AllocUnattributed( nSize ); -} - -void *__cdecl operator new( unsigned int nSize, int nBlockUse, const char *pFileName, int nLine ) -{ - return g_pMemAlloc->Alloc(nSize, pFileName, nLine); -} - -void __cdecl operator delete( void *pMem ) -{ - g_pMemAlloc->Free( pMem ); -} - -void *__cdecl operator new[] ( unsigned int nSize ) -{ - return AllocUnattributed( nSize ); -} - -void *__cdecl operator new[] ( unsigned int nSize, int nBlockUse, const char *pFileName, int nLine ) -{ - return g_pMemAlloc->Alloc(nSize, pFileName, nLine); -} - -void __cdecl operator delete[] ( void *pMem ) -{ - g_pMemAlloc->Free( pMem ); -} -#endif - - -//----------------------------------------------------------------------------- -// Override some debugging allocation methods in MSVC -// NOTE: These have to be here for release + debug builds in case we -// link to a debug static lib!!! -//----------------------------------------------------------------------------- -#ifndef _STATIC_LINKED -#ifdef _WIN32 - -// This here just hides the internal file names, etc of allocations -// made in the c runtime library -#define CRT_INTERNAL_FILE_NAME "C-runtime internal" - -class CAttibCRT -{ -public: - CAttibCRT(int nBlockUse) : m_nBlockUse(nBlockUse) - { - if (m_nBlockUse == _CRT_BLOCK) - { - g_pMemAlloc->PushAllocDbgInfo(CRT_INTERNAL_FILE_NAME, 0); - } - } - - ~CAttibCRT() - { - if (m_nBlockUse == _CRT_BLOCK) - { - g_pMemAlloc->PopAllocDbgInfo(); - } - } - -private: - int m_nBlockUse; -}; - - -#define AttribIfCrt() CAttibCRT _attrib(nBlockUse) -#elif defined(_LINUX) -#define AttribIfCrt() -#endif // _WIN32 - - -extern "C" -{ - -void *__cdecl _nh_malloc_dbg( size_t nSize, int nFlag, int nBlockUse, - const char *pFileName, int nLine ) -{ - AttribIfCrt(); - return g_pMemAlloc->Alloc(nSize, pFileName, nLine); -} - -void *__cdecl _malloc_dbg( size_t nSize, int nBlockUse, - const char *pFileName, int nLine ) -{ - AttribIfCrt(); - return g_pMemAlloc->Alloc(nSize, pFileName, nLine); -} - -void *__cdecl _calloc_dbg( size_t nNum, size_t nSize, int nBlockUse, - const char *pFileName, int nLine ) -{ - AttribIfCrt(); - void *pMem = g_pMemAlloc->Alloc(nSize * nNum, pFileName, nLine); - memset(pMem, 0, nSize * nNum); - return pMem; -} - -void *__cdecl _realloc_dbg( void *pMem, size_t nNewSize, int nBlockUse, - const char *pFileName, int nLine ) -{ - AttribIfCrt(); - return g_pMemAlloc->Realloc(pMem, nNewSize, pFileName, nLine); -} - -void *__cdecl _expand_dbg( void *pMem, size_t nNewSize, int nBlockUse, - const char *pFileName, int nLine ) -{ - Assert( 0 ); - return NULL; -} - -void __cdecl _free_dbg( void *pMem, int nBlockUse ) -{ - AttribIfCrt(); - g_pMemAlloc->Free(pMem); -} - -size_t __cdecl _msize_dbg( void *pMem, int nBlockUse ) -{ -#ifdef _WIN32 - return _msize(pMem); -#elif _LINUX - Assert( "_msize_dbg unsupported" ); - return 0; -#endif -} - - -#ifdef _WIN32 - -#if defined(_DEBUG) && _MSC_VER >= 1300 -// X360TBD: aligned and offset allocations may be important on the 360 - -// aligned base -ALLOC_CALL void *__cdecl _aligned_malloc_base( size_t size, size_t align ) -{ - return MemAlloc_AllocAligned( size, align ); -} - -ALLOC_CALL void *__cdecl _aligned_realloc_base( void *ptr, size_t size, size_t align ) -{ - return MemAlloc_ReallocAligned( ptr, size, align ); -} - -ALLOC_CALL void *__cdecl _aligned_recalloc_base( void *ptr, size_t size, size_t align ) -{ - Error( "Unsupported function\n" ); - return NULL; -} - -FREE_CALL void __cdecl _aligned_free_base( void *ptr ) -{ - MemAlloc_FreeAligned( ptr ); -} - -// aligned -ALLOC_CALL void * __cdecl _aligned_malloc( size_t size, size_t align ) -{ - return _aligned_malloc_base(size, align); -} - -ALLOC_CALL void *__cdecl _aligned_realloc(void *memblock, size_t size, size_t align) -{ - return _aligned_realloc_base(memblock, size, align); -} - -ALLOC_CALL void * __cdecl _aligned_recalloc( void * memblock, size_t count, size_t size, size_t align ) -{ - return _aligned_recalloc_base(memblock, count * size, align); -} - -FREE_CALL void __cdecl _aligned_free( void *memblock ) -{ - _aligned_free_base(memblock); -} - -// aligned offset base -ALLOC_CALL void * __cdecl _aligned_offset_malloc_base( size_t size, size_t align, size_t offset ) -{ - Assert( IsPC() || 0 ); - return NULL; -} - -ALLOC_CALL void * __cdecl _aligned_offset_realloc_base( void * memblock, size_t size, size_t align, size_t offset) -{ - Assert( IsPC() || 0 ); - return NULL; -} - -ALLOC_CALL void * __cdecl _aligned_offset_recalloc_base( void * memblock, size_t size, size_t align, size_t offset) -{ - Assert( IsPC() || 0 ); - return NULL; -} - -// aligned offset -ALLOC_CALL void *__cdecl _aligned_offset_malloc(size_t size, size_t align, size_t offset) -{ - return _aligned_offset_malloc_base( size, align, offset ); -} - -ALLOC_CALL void *__cdecl _aligned_offset_realloc(void *memblock, size_t size, size_t align, size_t offset) -{ - return _aligned_offset_realloc_base( memblock, size, align, offset ); -} - -ALLOC_CALL void * __cdecl _aligned_offset_recalloc( void * memblock, size_t count, size_t size, size_t align, size_t offset ) -{ - return _aligned_offset_recalloc_base( memblock, count * size, align, offset ); -} - -#endif // _MSC_VER >= 1400 - -#endif - -} // end extern "C" - - -//----------------------------------------------------------------------------- -// Override some the _CRT debugging allocation methods in MSVC -//----------------------------------------------------------------------------- -#ifdef _WIN32 - -extern "C" -{ - -int _CrtDumpMemoryLeaks(void) -{ - return 0; -} - -_CRT_DUMP_CLIENT _CrtSetDumpClient( _CRT_DUMP_CLIENT dumpClient ) -{ - return NULL; -} - -int _CrtSetDbgFlag( int nNewFlag ) -{ - return g_pMemAlloc->CrtSetDbgFlag( nNewFlag ); -} - -// 64-bit port. -#define AFNAME(var) __p_ ## var -#define AFRET(var) &var - -int _crtDbgFlag = _CRTDBG_ALLOC_MEM_DF; -int* AFNAME(_crtDbgFlag)(void) -{ - return AFRET(_crtDbgFlag); -} - -long _crtBreakAlloc; /* Break on this allocation */ -long* AFNAME(_crtBreakAlloc) (void) -{ - return AFRET(_crtBreakAlloc); -} - -void __cdecl _CrtSetDbgBlockType( void *pMem, int nBlockUse ) -{ - DebuggerBreak(); -} - -_CRT_ALLOC_HOOK __cdecl _CrtSetAllocHook( _CRT_ALLOC_HOOK pfnNewHook ) -{ - DebuggerBreak(); - return NULL; -} - -long __cdecl _CrtSetBreakAlloc( long lNewBreakAlloc ) -{ - return g_pMemAlloc->CrtSetBreakAlloc( lNewBreakAlloc ); -} - -int __cdecl _CrtIsValidHeapPointer( const void *pMem ) -{ - return g_pMemAlloc->CrtIsValidHeapPointer( pMem ); -} - -int __cdecl _CrtIsValidPointer( const void *pMem, unsigned int size, int access ) -{ - return g_pMemAlloc->CrtIsValidPointer( pMem, size, access ); -} - -int __cdecl _CrtCheckMemory( void ) -{ - // FIXME: Remove this when we re-implement the heap - return g_pMemAlloc->CrtCheckMemory( ); -} - -int __cdecl _CrtIsMemoryBlock( const void *pMem, unsigned int nSize, - long *plRequestNumber, char **ppFileName, int *pnLine ) -{ - DebuggerBreak(); - return 1; -} - -int __cdecl _CrtMemDifference( _CrtMemState *pState, const _CrtMemState * oldState, const _CrtMemState * newState ) -{ - DebuggerBreak(); - return FALSE; -} - -void __cdecl _CrtMemDumpStatistics( const _CrtMemState *pState ) -{ - DebuggerBreak(); -} - -void __cdecl _CrtMemCheckpoint( _CrtMemState *pState ) -{ - // FIXME: Remove this when we re-implement the heap - g_pMemAlloc->CrtMemCheckpoint( pState ); -} - -void __cdecl _CrtMemDumpAllObjectsSince( const _CrtMemState *pState ) -{ - DebuggerBreak(); -} - -void __cdecl _CrtDoForAllClientObjects( void (*pfn)(void *, void *), void * pContext ) -{ - DebuggerBreak(); -} - - -//----------------------------------------------------------------------------- -// Methods in dbgrpt.cpp -//----------------------------------------------------------------------------- -long _crtAssertBusy = -1; - -int __cdecl _CrtSetReportMode( int nReportType, int nReportMode ) -{ - return g_pMemAlloc->CrtSetReportMode( nReportType, nReportMode ); -} - -_HFILE __cdecl _CrtSetReportFile( int nRptType, _HFILE hFile ) -{ - return (_HFILE)g_pMemAlloc->CrtSetReportFile( nRptType, hFile ); -} - -_CRT_REPORT_HOOK __cdecl _CrtSetReportHook( _CRT_REPORT_HOOK pfnNewHook ) -{ - return (_CRT_REPORT_HOOK)g_pMemAlloc->CrtSetReportHook( pfnNewHook ); -} - -int __cdecl _CrtDbgReport( int nRptType, const char * szFile, - int nLine, const char * szModule, const char * szFormat, ... ) -{ - static char output[1024]; - va_list args; - va_start( args, szFormat ); - _vsnprintf( output, sizeof( output )-1, szFormat, args ); - va_end( args ); - - return g_pMemAlloc->CrtDbgReport( nRptType, szFile, nLine, szModule, output ); -} - -#if _MSC_VER >= 1400 - -#if defined( _DEBUG ) - -// wrapper which passes no debug info; not available in debug -void __cdecl _invalid_parameter_noinfo(void) -{ - Assert(0); -} - -#endif /* defined( _DEBUG ) */ - -#if defined( _DEBUG ) || defined( USE_MEM_DEBUG ) - -int __cdecl __crtMessageWindowW( int nRptType, const wchar_t * szFile, const wchar_t * szLine, - const wchar_t * szModule, const wchar_t * szUserMessage ) -{ - Assert(0); - return 0; -} - -int __cdecl _CrtDbgReportV( int nRptType, const wchar_t *szFile, int nLine, - const wchar_t *szModule, const wchar_t *szFormat, va_list arglist ) -{ - Assert(0); - return 0; -} - -int __cdecl _CrtDbgReportW( int nRptType, const wchar_t *szFile, int nLine, - const wchar_t *szModule, const wchar_t *szFormat, ...) -{ - Assert(0); - return 0; -} - -int __cdecl _VCrtDbgReportA( int nRptType, const wchar_t * szFile, int nLine, - const wchar_t * szModule, const wchar_t * szFormat, va_list arglist ) -{ - Assert(0); - return 0; -} - -int __cdecl _CrtSetReportHook2( int mode, _CRT_REPORT_HOOK pfnNewHook ) -{ - _CrtSetReportHook( pfnNewHook ); - return 0; -} - - -#endif /* defined( _DEBUG ) || defined( USE_MEM_DEBUG ) */ - -extern "C" int __crtDebugCheckCount = FALSE; - -extern "C" int __cdecl _CrtSetCheckCount( int fCheckCount ) -{ - int oldCheckCount = __crtDebugCheckCount; - return oldCheckCount; -} - -extern "C" int __cdecl _CrtGetCheckCount( void ) -{ - return __crtDebugCheckCount; -} - -// aligned offset debug -extern "C" void * __cdecl _aligned_offset_recalloc_dbg( void * memblock, size_t count, size_t size, size_t align, size_t offset, const char * f_name, int line_n ) -{ - Assert( IsPC() || 0 ); - void *pMem = ReallocUnattributed( memblock, size * count ); - memset( pMem, 0, size * count ); - return pMem; -} - -extern "C" void * __cdecl _aligned_recalloc_dbg( void *memblock, size_t count, size_t size, size_t align, const char * f_name, int line_n ) -{ - return _aligned_offset_recalloc_dbg(memblock, count, size, align, 0, f_name, line_n); -} - -extern "C" void * __cdecl _recalloc_dbg ( void * memblock, size_t count, size_t size, int nBlockUse, const char * szFileName, int nLine ) -{ - return _aligned_offset_recalloc_dbg(memblock, count, size, 0, 0, szFileName, nLine); -} - -_CRT_REPORT_HOOK __cdecl _CrtGetReportHook( void ) -{ - return NULL; -} - -#endif -int __cdecl _CrtReportBlockType(const void * pUserData) -{ - return 0; -} - - -} // end extern "C" -#endif // _WIN32 - -// Most files include this file, so when it's used it adds an extra .ValveDbg section, -// to help identify debug binaries. -#ifdef _WIN32 - #ifndef NDEBUG // _DEBUG - #pragma data_seg("ValveDBG") - volatile const char* DBG = "*** DEBUG STUB ***"; - #endif -#endif - -#endif - -// Extras added prevent dbgheap.obj from being included - DAL -#ifdef _WIN32 - -extern "C" -{ -size_t __crtDebugFillThreshold = 0; - -extern "C" void * __cdecl _heap_alloc_base (size_t size) { - assert(0); - return NULL; -} - - -void * __cdecl _heap_alloc_dbg( size_t nSize, int nBlockUse, const char * szFileName, int nLine) -{ - return _heap_alloc(nSize); -} - -// 64-bit -#ifdef _WIN64 -static void * __cdecl realloc_help( void * pUserData, size_t * pnNewSize, int nBlockUse,const char * szFileName, - int nLine, int fRealloc ) -{ - assert(0); // Shouldn't be needed - return NULL; -} -#else -static void * __cdecl realloc_help( void * pUserData, size_t nNewSize, int nBlockUse, const char * szFileName, - int nLine, int fRealloc) -{ - assert(0); // Shouldn't be needed - return NULL; -} -#endif - -void __cdecl _free_nolock( void * pUserData) -{ - // I don't think the second param is used in memoverride - _free_dbg(pUserData, 0); -} - -void __cdecl _free_dbg_nolock( void * pUserData, int nBlockUse) -{ - _free_dbg(pUserData, 0); -} - -_CRT_ALLOC_HOOK __cdecl _CrtGetAllocHook ( void) -{ - assert(0); - return NULL; -} - -static int __cdecl CheckBytes( unsigned char * pb, unsigned char bCheck, size_t nSize) -{ - int bOkay = TRUE; - return bOkay; -} - - -_CRT_DUMP_CLIENT __cdecl _CrtGetDumpClient ( void) -{ - assert(0); - return NULL; -} - -#if _MSC_VER >= 1400 -static void __cdecl _printMemBlockData( _locale_t plocinfo, _CrtMemBlockHeader * pHead) -{ -} - -static void __cdecl _CrtMemDumpAllObjectsSince_stat( const _CrtMemState * state, _locale_t plocinfo) -{ -} -#endif -void * __cdecl _aligned_malloc_dbg( size_t size, size_t align, const char * f_name, int line_n) -{ - return _aligned_malloc(size, align); -} - -void * __cdecl _aligned_realloc_dbg( void *memblock, size_t size, size_t align, - const char * f_name, int line_n) -{ - return _aligned_realloc(memblock, size, align); -} - -void * __cdecl _aligned_offset_malloc_dbg( size_t size, size_t align, size_t offset, - const char * f_name, int line_n) -{ - return _aligned_offset_malloc(size, align, offset); -} - -void * __cdecl _aligned_offset_realloc_dbg( void * memblock, size_t size, size_t align, - size_t offset, const char * f_name, int line_n) -{ - return _aligned_offset_realloc(memblock, size, align, offset); -} - -void __cdecl _aligned_free_dbg( void * memblock) -{ - _aligned_free(memblock); -} - -size_t __cdecl _CrtSetDebugFillThreshold( size_t _NewDebugFillThreshold) -{ - assert(0); - return 0; -} - -//=========================================== -// NEW!!! 64-bit - -char * __cdecl _strdup ( const char * string ) -{ - int nSize = strlen(string) + 1; - char *pCopy = (char*)AllocUnattributed( nSize ); - if ( pCopy ) - memcpy( pCopy, string, nSize ); - return pCopy; -} - -#if 0 -_TSCHAR * __cdecl _tfullpath_dbg ( _TSCHAR *UserBuf, const _TSCHAR *path, size_t maxlen, int nBlockUse, const char * szFileName, int nLine ) -{ - Assert(0); - return NULL; -} - -_TSCHAR * __cdecl _tfullpath ( _TSCHAR *UserBuf, const _TSCHAR *path, size_t maxlen ) -{ - Assert(0); - return NULL; -} - -_TSCHAR * __cdecl _tgetdcwd_lk_dbg ( int drive, _TSCHAR *pnbuf, int maxlen, int nBlockUse, const char * szFileName, int nLine ) -{ - Assert(0); - return NULL; -} - -_TSCHAR * __cdecl _tgetdcwd_nolock ( int drive, _TSCHAR *pnbuf, int maxlen ) -{ - Assert(0); - return NULL; -} - -errno_t __cdecl _tdupenv_s_helper ( _TSCHAR **pBuffer, size_t *pBufferSizeInTChars, const _TSCHAR *varname, int nBlockUse, const char * szFileName, int nLine ) -{ - Assert(0); - return 0; -} - -errno_t __cdecl _tdupenv_s_helper ( _TSCHAR **pBuffer, size_t *pBufferSizeInTChars, const _TSCHAR *varname ) -{ - Assert(0); - return 0; -} - -_TSCHAR * __cdecl _ttempnam_dbg ( const _TSCHAR *dir, const _TSCHAR *pfx, int nBlockUse, const char * szFileName, int nLine ) -{ - Assert(0); - return 0; -} - -_TSCHAR * __cdecl _ttempnam ( const _TSCHAR *dir, const _TSCHAR *pfx ) -{ - Assert(0); - return 0; -} -#endif - -wchar_t * __cdecl _wcsdup_dbg ( const wchar_t * string, int nBlockUse, const char * szFileName, int nLine ) -{ - Assert(0); - return 0; -} - -wchar_t * __cdecl _wcsdup ( const wchar_t * string ) -{ - Assert(0); - return 0; -} - -} // end extern "C" - -#if _MSC_VER >= 1400 - -//----------------------------------------------------------------------------- -// XBox Memory Allocator Override -//----------------------------------------------------------------------------- -#if defined( _X360 ) -#if defined( _DEBUG ) || defined( USE_MEM_DEBUG ) -#include "UtlMap.h" - -MEMALLOC_DEFINE_EXTERNAL_TRACKING( XMem ); - -CThreadFastMutex g_XMemAllocMutex; - -void XMemAlloc_RegisterAllocation( void *p, DWORD dwAllocAttributes ) -{ - if ( !g_pMemAlloc ) - { - // core xallocs cannot be journaled until system is ready - return; - } - - AUTO_LOCK_FM( g_XMemAllocMutex ); - int size = XMemSize( p, dwAllocAttributes ); - MemAlloc_RegisterExternalAllocation( XMem, p, size ); -} - -void XMemAlloc_RegisterDeallocation( void *p, DWORD dwAllocAttributes ) -{ - if ( !g_pMemAlloc ) - { - // core xallocs cannot be journaled until system is ready - return; - } - - AUTO_LOCK_FM( g_XMemAllocMutex ); - int size = XMemSize( p, dwAllocAttributes ); - MemAlloc_RegisterExternalDeallocation( XMem, p, size ); -} - -#else - -#define XMemAlloc_RegisterAllocation( p, a ) ((void)0) -#define XMemAlloc_RegisterDeallocation( p, a ) ((void)0) - -#endif - -//----------------------------------------------------------------------------- -// XMemAlloc -// -// XBox Memory Allocator Override -//----------------------------------------------------------------------------- -LPVOID WINAPI XMemAlloc( SIZE_T dwSize, DWORD dwAllocAttributes ) -{ - LPVOID ptr; - XALLOC_ATTRIBUTES *pAttribs = (XALLOC_ATTRIBUTES *)&dwAllocAttributes; - bool bPhysical = ( pAttribs->dwMemoryType == XALLOC_MEMTYPE_PHYSICAL ); - - if ( !bPhysical && !pAttribs->dwHeapTracksAttributes && pAttribs->dwAllocatorId != eXALLOCAllocatorId_XUI ) - { - MEM_ALLOC_CREDIT(); - switch ( pAttribs->dwAlignment ) - { - case XALLOC_ALIGNMENT_4: - ptr = g_pMemAlloc->Alloc( dwSize ); - break; - case XALLOC_ALIGNMENT_8: - ptr = MemAlloc_AllocAligned( dwSize, 8 ); - break; - case XALLOC_ALIGNMENT_DEFAULT: - case XALLOC_ALIGNMENT_16: - default: - ptr = MemAlloc_AllocAligned( dwSize, 16 ); - break; - } - if ( pAttribs->dwZeroInitialize != 0 ) - { - memset( ptr, 0, XMemSize( ptr, dwAllocAttributes ) ); - } - return ptr; - } - - ptr = XMemAllocDefault( dwSize, dwAllocAttributes ); - if ( ptr ) - { - XMemAlloc_RegisterAllocation( ptr, dwAllocAttributes ); - } - - return ptr; -} - -//----------------------------------------------------------------------------- -// XMemFree -// -// XBox Memory Allocator Override -//----------------------------------------------------------------------------- -VOID WINAPI XMemFree( PVOID pAddress, DWORD dwAllocAttributes ) -{ - if ( !pAddress ) - { - return; - } - - XALLOC_ATTRIBUTES *pAttribs = (XALLOC_ATTRIBUTES *)&dwAllocAttributes; - bool bPhysical = ( pAttribs->dwMemoryType == XALLOC_MEMTYPE_PHYSICAL ); - - if ( !bPhysical && !pAttribs->dwHeapTracksAttributes && pAttribs->dwAllocatorId != eXALLOCAllocatorId_XUI ) - { - switch ( pAttribs->dwAlignment ) - { - case XALLOC_ALIGNMENT_4: - return g_pMemAlloc->Free( pAddress ); - default: - return MemAlloc_FreeAligned( pAddress ); - } - return; - } - - XMemAlloc_RegisterDeallocation( pAddress, dwAllocAttributes ); - - XMemFreeDefault( pAddress, dwAllocAttributes ); -} - -//----------------------------------------------------------------------------- -// XMemSize -// -// XBox Memory Allocator Override -//----------------------------------------------------------------------------- -SIZE_T WINAPI XMemSize( PVOID pAddress, DWORD dwAllocAttributes ) -{ - XALLOC_ATTRIBUTES *pAttribs = (XALLOC_ATTRIBUTES *)&dwAllocAttributes; - bool bPhysical = ( pAttribs->dwMemoryType == XALLOC_MEMTYPE_PHYSICAL ); - - if ( !bPhysical && !pAttribs->dwHeapTracksAttributes && pAttribs->dwAllocatorId != eXALLOCAllocatorId_XUI ) - { - switch ( pAttribs->dwAlignment ) - { - case XALLOC_ALIGNMENT_4: - return g_pMemAlloc->GetSize( pAddress ); - default: - return MemAlloc_GetSizeAligned( pAddress ); - } - } - - return XMemSizeDefault( pAddress, dwAllocAttributes ); -} -#endif // _X360 - -#define MAX_LANG_LEN 64 /* max language name length */ -#define MAX_CTRY_LEN 64 /* max country name length */ -#define MAX_MODIFIER_LEN 0 /* max modifier name length - n/a */ -#define MAX_LC_LEN (MAX_LANG_LEN+MAX_CTRY_LEN+MAX_MODIFIER_LEN+3) - -struct _is_ctype_compatible { - unsigned long id; - int is_clike; -}; -typedef struct setloc_struct { - /* getqloc static variables */ - char *pchLanguage; - char *pchCountry; - int iLcidState; - int iPrimaryLen; - BOOL bAbbrevLanguage; - BOOL bAbbrevCountry; - LCID lcidLanguage; - LCID lcidCountry; - /* expand_locale static variables */ - LC_ID _cacheid; - UINT _cachecp; - char _cachein[MAX_LC_LEN]; - char _cacheout[MAX_LC_LEN]; - /* _setlocale_set_cat (LC_CTYPE) static variable */ - struct _is_ctype_compatible _Lcid_c[5]; -} _setloc_struct, *_psetloc_struct; - -struct _tiddata { - unsigned long _tid; /* thread ID */ - - - uintptr_t _thandle; /* thread handle */ - - int _terrno; /* errno value */ - unsigned long _tdoserrno; /* _doserrno value */ - unsigned int _fpds; /* Floating Point data segment */ - unsigned long _holdrand; /* rand() seed value */ - char * _token; /* ptr to strtok() token */ - wchar_t * _wtoken; /* ptr to wcstok() token */ - unsigned char * _mtoken; /* ptr to _mbstok() token */ - - /* following pointers get malloc'd at runtime */ - char * _errmsg; /* ptr to strerror()/_strerror() buff */ - wchar_t * _werrmsg; /* ptr to _wcserror()/__wcserror() buff */ - char * _namebuf0; /* ptr to tmpnam() buffer */ - wchar_t * _wnamebuf0; /* ptr to _wtmpnam() buffer */ - char * _namebuf1; /* ptr to tmpfile() buffer */ - wchar_t * _wnamebuf1; /* ptr to _wtmpfile() buffer */ - char * _asctimebuf; /* ptr to asctime() buffer */ - wchar_t * _wasctimebuf; /* ptr to _wasctime() buffer */ - void * _gmtimebuf; /* ptr to gmtime() structure */ - char * _cvtbuf; /* ptr to ecvt()/fcvt buffer */ - unsigned char _con_ch_buf[MB_LEN_MAX]; - /* ptr to putch() buffer */ - unsigned short _ch_buf_used; /* if the _con_ch_buf is used */ - - /* following fields are needed by _beginthread code */ - void * _initaddr; /* initial user thread address */ - void * _initarg; /* initial user thread argument */ - - /* following three fields are needed to support signal handling and - * runtime errors */ - void * _pxcptacttab; /* ptr to exception-action table */ - void * _tpxcptinfoptrs; /* ptr to exception info pointers */ - int _tfpecode; /* float point exception code */ - - /* pointer to the copy of the multibyte character information used by - * the thread */ - pthreadmbcinfo ptmbcinfo; - - /* pointer to the copy of the locale informaton used by the thead */ - pthreadlocinfo ptlocinfo; - int _ownlocale; /* if 1, this thread owns its own locale */ - - /* following field is needed by NLG routines */ - unsigned long _NLG_dwCode; - - /* - * Per-Thread data needed by C++ Exception Handling - */ - void * _terminate; /* terminate() routine */ - void * _unexpected; /* unexpected() routine */ - void * _translator; /* S.E. translator */ - void * _purecall; /* called when pure virtual happens */ - void * _curexception; /* current exception */ - void * _curcontext; /* current exception context */ - int _ProcessingThrow; /* for uncaught_exception */ - void * _curexcspec; /* for handling exceptions thrown from std::unexpected */ -#if defined (_M_IA64) || defined (_M_AMD64) - void * _pExitContext; - void * _pUnwindContext; - void * _pFrameInfoChain; - unsigned __int64 _ImageBase; -#if defined (_M_IA64) - unsigned __int64 _TargetGp; -#endif /* defined (_M_IA64) */ - unsigned __int64 _ThrowImageBase; - void * _pForeignException; -#elif defined (_M_IX86) - void * _pFrameInfoChain; -#endif /* defined (_M_IX86) */ - _setloc_struct _setloc_data; - - void * _encode_ptr; /* EncodePointer() routine */ - void * _decode_ptr; /* DecodePointer() routine */ - - void * _reserved1; /* nothing */ - void * _reserved2; /* nothing */ - void * _reserved3; /* nothing */ - - int _cxxReThrow; /* Set to True if it's a rethrown C++ Exception */ - - unsigned long __initDomain; /* initial domain used by _beginthread[ex] for managed function */ -}; - -typedef struct _tiddata * _ptiddata; - -class _LocaleUpdate -{ - _locale_tstruct localeinfo; - _ptiddata ptd; - bool updated; - public: - _LocaleUpdate(_locale_t plocinfo) - : updated(false) - { - /* - if (plocinfo == NULL) - { - ptd = _getptd(); - localeinfo.locinfo = ptd->ptlocinfo; - localeinfo.mbcinfo = ptd->ptmbcinfo; - - __UPDATE_LOCALE(ptd, localeinfo.locinfo); - __UPDATE_MBCP(ptd, localeinfo.mbcinfo); - if (!(ptd->_ownlocale & _PER_THREAD_LOCALE_BIT)) - { - ptd->_ownlocale |= _PER_THREAD_LOCALE_BIT; - updated = true; - } - } - else - { - localeinfo=*plocinfo; - } - */ - } - ~_LocaleUpdate() - { -// if (updated) -// ptd->_ownlocale = ptd->_ownlocale & ~_PER_THREAD_LOCALE_BIT; - } - _locale_t GetLocaleT() - { - return &localeinfo; - } -}; - - -#pragma warning(push) -#pragma warning(disable: 4483) -#if _MSC_FULL_VER >= 140050415 -#define _NATIVE_STARTUP_NAMESPACE __identifier("") -#else /* _MSC_FULL_VER >= 140050415 */ -#define _NATIVE_STARTUP_NAMESPACE __CrtImplementationDetails -#endif /* _MSC_FULL_VER >= 140050415 */ - -namespace _NATIVE_STARTUP_NAMESPACE -{ - class NativeDll - { - private: - static const unsigned int ProcessDetach = 0; - static const unsigned int ProcessAttach = 1; - static const unsigned int ThreadAttach = 2; - static const unsigned int ThreadDetach = 3; - static const unsigned int ProcessVerifier = 4; - - public: - - inline static bool IsInDllMain() - { - return false; - } - - inline static bool IsInProcessAttach() - { - return false; - } - - inline static bool IsInProcessDetach() - { - return false; - } - - inline static bool IsInVcclrit() - { - return false; - } - - inline static bool IsSafeForManagedCode() - { - if (!IsInDllMain()) - { - return true; - } - - if (IsInVcclrit()) - { - return true; - } - - return !IsInProcessAttach() && !IsInProcessDetach(); - } - }; -} -#pragma warning(pop) - -#endif // _MSC_VER >= 1400 - -#endif // !STEAM && !NO_MALLOC_OVERRIDE - -#endif // _WIN32 diff --git a/public/tier0/minidump.h b/public/tier0/minidump.h deleted file mode 100644 index c8639d71b..000000000 --- a/public/tier0/minidump.h +++ /dev/null @@ -1,53 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef MINIDUMP_H -#define MINIDUMP_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/platform.h" - -// writes out a minidump of the current stack trace with a unique filename -PLATFORM_INTERFACE void WriteMiniDump(); - -typedef void (*FnWMain)( int , tchar *[] ); - -#if defined(_WIN32) && !defined(_X360) - -// calls the passed in function pointer and catches any exceptions/crashes thrown by it, and writes a minidump -// use from wmain() to protect the whole program - -PLATFORM_INTERFACE void CatchAndWriteMiniDump( FnWMain pfn, int argc, tchar *argv[] ); - -#include - -// Replaces the current function pointer with the one passed in. -// Returns the previously-set function. -// The function is called internally by WriteMiniDump() and CatchAndWriteMiniDump() -// The default is the built-in function that uses DbgHlp.dll's MiniDumpWriteDump function -typedef void (*FnMiniDump)( unsigned int uStructuredExceptionCode, _EXCEPTION_POINTERS * pExceptionInfo ); -PLATFORM_INTERFACE FnMiniDump SetMiniDumpFunction( FnMiniDump pfn ); - -// Use this to write a minidump explicitly. -// Some of the tools choose to catch the minidump themselves instead of using CatchAndWriteMinidump -// so they can show their own dialog. -// -// ptchMinidumpFileNameBuffer if not-NULL should be a writable tchar buffer of length at -// least _MAX_PATH and on return will contain the name of the minidump file written. -// If ptchMinidumpFileNameBuffer is NULL the name of the minidump file written will not -// be available after the function returns. -// -PLATFORM_INTERFACE bool WriteMiniDumpUsingExceptionInfo( - unsigned int uStructuredExceptionCode, - _EXCEPTION_POINTERS * pExceptionInfo, - MINIDUMP_TYPE minidumpType, - tchar *ptchMinidumpFileNameBuffer = NULL - ); -#endif - -#endif // MINIDUMP_H diff --git a/public/tier0/platform.h b/public/tier0/platform.h deleted file mode 100644 index 1f94663cf..000000000 --- a/public/tier0/platform.h +++ /dev/null @@ -1,1182 +0,0 @@ -//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// - -#ifndef PLATFORM_H -#define PLATFORM_H - -#if defined( _X360 ) -#define NO_STEAM -#define NO_VOICE -// for the 360, the ppc platform and the rtos are tightly coupled -// setup the 360 environment here !once! for much less leaf module include wackiness -// these are critical order and purposely appear *before* anything else -#define _XBOX -#include -#include -#include -#include -#include -#include -#include -#undef _XBOX -#endif - -#include "wchartypes.h" -#include "tier0/valve_off.h" - -#ifdef _WIN32 -#pragma once -#endif - -// feature enables -#define NEW_SOFTWARE_LIGHTING - -#if defined(_LINUX) || defined(__APPLE__) -// need this for _alloca -#include -#endif // _LINUX - -#if defined __APPLE__ -#include -#else -#include -#endif -#ifdef _MSC_VER -#include -#elif defined __GNUC__ -#include -#endif - -// need this for memset -#include - -#ifdef _RETAIL -#define IsRetail() true -#else -#define IsRetail() false -#endif - -#ifdef _DEBUG -#define IsRelease() false -#define IsDebug() true -#else -#define IsRelease() true -#define IsDebug() false -#endif - -// Deprecating, infavor of IsX360() which will revert to IsXbox() -// after confidence of xbox 1 code flush -#define IsXbox() false - -#ifdef _WIN32 - #define IsLinux() false - #ifndef _X360 - #define IsPC() true - #define IsConsole() false - #define IsX360() false - #define IsPS3() false - #define IS_WINDOWS_PC - #else - #ifndef _CONSOLE - #define _CONSOLE - #endif - #define IsPC() false - #define IsConsole() true - #define IsX360() true - #define IsPS3() false - #endif -#elif defined(_LINUX) || defined(__APPLE__) - #define IsPC() true - #define IsConsole() false - #define IsX360() false - #define IsPS3() false - #define IsLinux() true -#else - #error -#endif - -typedef unsigned char uint8; -typedef signed char int8; - -#ifdef __x86_64__ -#define X64BITS -#endif - -#if defined( _WIN32 ) - -typedef __int16 int16; -typedef unsigned __int16 uint16; -typedef __int32 int32; -typedef unsigned __int32 uint32; -typedef __int64 int64; -typedef unsigned __int64 uint64; - -#ifdef X64BITS -typedef __int64 intp; // intp is an integer that can accomodate a pointer -typedef unsigned __int64 uintp; // (ie, sizeof(intp) >= sizeof(int) && sizeof(intp) >= sizeof(void *) -#else -typedef __int32 intp; -typedef unsigned __int32 uintp; -#endif - -#if defined( _X360 ) -#ifdef __m128 - #undef __m128 -#endif -#define __m128 __vector4 -#endif - -#else // _WIN32 - -typedef short int16; -typedef unsigned short uint16; -typedef int int32; -typedef unsigned int uint32; -typedef long long int64; -typedef unsigned long long uint64; -#ifdef X64BITS -typedef long long intp; -typedef unsigned long long uintp; -#else -typedef int intp; -typedef unsigned int uintp; -#endif - -#endif // else _WIN32 - - -typedef float float32; -typedef double float64; - -// for when we don't care about how many bits we use -typedef unsigned int uint; - -// This can be used to ensure the size of pointers to members when declaring -// a pointer type for a class that has only been forward declared -#ifdef _MSC_VER -#define SINGLE_INHERITANCE __single_inheritance -#define MULTIPLE_INHERITANCE __multiple_inheritance -#else -#define SINGLE_INHERITANCE -#define MULTIPLE_INHERITANCE -#endif - -#ifdef _MSC_VER -#define NO_VTABLE __declspec( novtable ) -#else -#define NO_VTABLE -#endif - -// This can be used to declare an abstract (interface only) class. -// Classes marked abstract should not be instantiated. If they are, and access violation will occur. -// -// Example of use: -// -// abstract_class CFoo -// { -// ... -// } -// -// MSDN __declspec(novtable) documentation: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_langref_novtable.asp -// -// Note: NJS: This is not enabled for regular PC, due to not knowing the implications of exporting a class with no no vtable. -// It's probable that this shouldn't be an issue, but an experiment should be done to verify this. -// -#ifndef _X360 -#define abstract_class class -#else -#define abstract_class class NO_VTABLE -#endif - -/* -FIXME: Enable this when we no longer fear change =) - -// need these for the limits -#include -#include - -// Maximum and minimum representable values -#define INT8_MAX SCHAR_MAX -#define INT16_MAX SHRT_MAX -#define INT32_MAX LONG_MAX -#define INT64_MAX (((int64)~0) >> 1) - -#define INT8_MIN SCHAR_MIN -#define INT16_MIN SHRT_MIN -#define INT32_MIN LONG_MIN -#define INT64_MIN (((int64)1) << 63) - -#define UINT8_MAX ((uint8)~0) -#define UINT16_MAX ((uint16)~0) -#define UINT32_MAX ((uint32)~0) -#define UINT64_MAX ((uint64)~0) - -#define UINT8_MIN 0 -#define UINT16_MIN 0 -#define UINT32_MIN 0 -#define UINT64_MIN 0 - -#ifndef UINT_MIN -#define UINT_MIN UINT32_MIN -#endif - -#define FLOAT32_MAX FLT_MAX -#define FLOAT64_MAX DBL_MAX - -#define FLOAT32_MIN FLT_MIN -#define FLOAT64_MIN DBL_MIN -*/ - -// portability / compiler settings -#if defined(_WIN32) && !defined(WINDED) - -#if defined(_M_IX86) -#define __i386__ 1 -#endif - -#elif defined(_LINUX) || defined(__APPLE__) -typedef unsigned int DWORD; -typedef unsigned short WORD; -typedef void * HINSTANCE; -#define _MAX_PATH PATH_MAX -#endif // defined(_WIN32) && !defined(WINDED) - - -// Defines MAX_PATH -#ifndef MAX_PATH -#define MAX_PATH 260 -#endif - -#define ALIGN_VALUE( val, alignment ) ( ( val + alignment - 1 ) & ~( alignment - 1 ) ) // need macro for constant expression - -// Used to step into the debugger -#if defined( _WIN32 ) && !defined( _X360 ) -#define DebuggerBreak() __asm { int 3 } -#elif defined( _X360 ) -#define DebuggerBreak() DebugBreak() -#else -#define DebuggerBreak() {} -#endif -#define DebuggerBreakIfDebugging() if ( !Plat_IsInDebugSession() ) ; else DebuggerBreak() - -// C functions for external declarations that call the appropriate C++ methods -#ifndef EXPORT - #ifdef _WIN32 - #define EXPORT _declspec( dllexport ) - #else - #define EXPORT /* */ - #endif -#endif - -#if defined __i386__ && !defined __linux__ - #define id386 1 -#else - #define id386 0 -#endif // __i386__ - -// decls for aligning data -#ifdef _WIN32 - #define DECL_ALIGN(x) __declspec(align(x)) - -#elif defined(_LINUX) || defined(__APPLE__) - #define DECL_ALIGN(x) __attribute__((aligned(x))) -#else - #define DECL_ALIGN(x) /* */ -#endif - -#define ALIGN8 DECL_ALIGN(8) -#define ALIGN16 DECL_ALIGN(16) -#define ALIGN32 DECL_ALIGN(32) -#define ALIGN128 DECL_ALIGN(128) - - -// Linux had a few areas where it didn't construct objects in the same order that Windows does. -// So when CVProfile::CVProfile() would access g_pMemAlloc, it would crash because the allocator wasn't initalized yet. -#if defined(_LINUX) || defined(__APPLE__) - #define CONSTRUCT_EARLY __attribute__((init_priority(101))) -#else - #define CONSTRUCT_EARLY -#endif - -#ifdef _WIN32 - #define SELECTANY __declspec(selectany) -#elif defined(_LINUX) || defined(__APPLE__) - #define SELECTANY __attribute__((weak)) -#else - #define SELECTANY static -#endif - -#if defined( _WIN32 ) - -// Used for dll exporting and importing -#define DLL_EXPORT extern "C" __declspec( dllexport ) -#define DLL_IMPORT extern "C" __declspec( dllimport ) - -// Can't use extern "C" when DLL exporting a class -#define DLL_CLASS_EXPORT __declspec( dllexport ) -#define DLL_CLASS_IMPORT __declspec( dllimport ) - -// Can't use extern "C" when DLL exporting a global -#define DLL_GLOBAL_EXPORT extern __declspec( dllexport ) -#define DLL_GLOBAL_IMPORT extern __declspec( dllimport ) - -#elif defined(_LINUX) || defined(__APPLE__) -// Used for dll exporting and importing -#define DLL_EXPORT extern "C" __attribute__ ((visibility("default"))) -#define DLL_IMPORT extern "C" - -// Can't use extern "C" when DLL exporting a class -#define DLL_CLASS_EXPORT __attribute__ ((visibility("default"))) -#define DLL_CLASS_IMPORT - -// Can't use extern "C" when DLL exporting a global -#define DLL_GLOBAL_EXPORT extern __attribute ((visibility("default"))) -#define DLL_GLOBAL_IMPORT extern - -#else -#error "Unsupported Platform." -#endif - -// Used for standard calling conventions -#if defined( _WIN32 ) && !defined( _X360 ) - #define STDCALL __stdcall - #define FASTCALL __fastcall - #define FORCEINLINE __forceinline - // GCC 3.4.1 has a bug in supporting forced inline of templated functions - // this macro lets us not force inlining in that case - #define FORCEINLINE_TEMPLATE __forceinline -#elif defined( _X360 ) - #define STDCALL __stdcall - #ifdef FORCEINLINE - #undef FORCEINLINE - #endif - #define FORCEINLINE __forceinline - #define FORCEINLINE_TEMPLATE __forceinline -#else - #define STDCALL - #define FASTCALL - #ifdef _LINUX_DEBUGGABLE - #define FORCEINLINE - #else - #define FORCEINLINE inline - #endif - // GCC 3.4.1 has a bug in supporting forced inline of templated functions - // this macro lets us not force inlining in that case - #define FORCEINLINE_TEMPLATE inline - #define __stdcall __attribute__ ((__stdcall__)) -#endif - -// Force a function call site -not- to inlined. (useful for profiling) -#define DONT_INLINE(a) (((int)(a)+1)?(a):(a)) - -// Pass hints to the compiler to prevent it from generating unnessecary / stupid code -// in certain situations. Several compilers other than MSVC also have an equivilent -// construct. -// -// Essentially the 'Hint' is that the condition specified is assumed to be true at -// that point in the compilation. If '0' is passed, then the compiler assumes that -// any subsequent code in the same 'basic block' is unreachable, and thus usually -// removed. -#ifdef _MSC_VER - #define HINT(THE_HINT) __assume((THE_HINT)) -#else - #define HINT(THE_HINT) 0 -#endif - -// Marks the codepath from here until the next branch entry point as unreachable, -// and asserts if any attempt is made to execute it. -#define UNREACHABLE() { Assert(0); HINT(0); } - -// In cases where no default is present or appropriate, this causes MSVC to generate -// as little code as possible, and throw an assertion in debug. -#define NO_DEFAULT default: UNREACHABLE(); - -#ifdef _WIN32 -// Alloca defined for this platform -#define stackalloc( _size ) _alloca( ALIGN_VALUE( _size, 16 ) ) -#define stackfree( _p ) -#elif defined(_LINUX) || defined(__APPLE__) -// Alloca defined for this platform -#define stackalloc( _size ) _alloca( ALIGN_VALUE( _size, 16 ) ) -#define stackfree( _p ) -#endif - -#ifdef _WIN32 -#define RESTRICT __restrict -#define RESTRICT_FUNC __declspec(restrict) -#else -#define RESTRICT -#define RESTRICT_FUNC -#endif - - -#ifdef _WIN32 -// Remove warnings from warning level 4. -#pragma warning(disable : 4514) // warning C4514: 'acosl' : unreferenced inline function has been removed -#pragma warning(disable : 4100) // warning C4100: 'hwnd' : unreferenced formal parameter -#pragma warning(disable : 4127) // warning C4127: conditional expression is constant -#pragma warning(disable : 4512) // warning C4512: 'InFileRIFF' : assignment operator could not be generated -#pragma warning(disable : 4611) // warning C4611: interaction between '_setjmp' and C++ object destruction is non-portable -#pragma warning(disable : 4710) // warning C4710: function 'x' not inlined -#pragma warning(disable : 4702) // warning C4702: unreachable code -#pragma warning(disable : 4505) // unreferenced local function has been removed -#pragma warning(disable : 4239) // nonstandard extension used : 'argument' ( conversion from class Vector to class Vector& ) -#pragma warning(disable : 4097) // typedef-name 'BaseClass' used as synonym for class-name 'CFlexCycler::CBaseFlex' -#pragma warning(disable : 4324) // Padding was added at the end of a structure -#pragma warning(disable : 4244) // type conversion warning. -#pragma warning(disable : 4305) // truncation from 'const double ' to 'float ' -#pragma warning(disable : 4786) // Disable warnings about long symbol names -#pragma warning(disable : 4250) // 'X' : inherits 'Y::Z' via dominance -#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union - -#if _MSC_VER >= 1300 -#pragma warning(disable : 4511) // Disable warnings about private copy constructors -#pragma warning(disable : 4121) // warning C4121: 'symbol' : alignment of a member was sensitive to packing -#pragma warning(disable : 4530) // warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc (disabled due to std headers having exception syntax) -#endif - -#if _MSC_VER >= 1400 -#pragma warning(disable : 4996) // functions declared deprecated -#endif - - -#endif - -// When we port to 64 bit, we'll have to resolve the int, ptr vs size_t 32/64 bit problems... -#if !defined( _WIN64 ) && defined _MSC_VER -#pragma warning( disable : 4267 ) // conversion from 'size_t' to 'int', possible loss of data -#pragma warning( disable : 4311 ) // pointer truncation from 'char *' to 'int' -#pragma warning( disable : 4312 ) // conversion from 'unsigned int' to 'memhandle_t' of greater size -#endif - - -//----------------------------------------------------------------------------- -// fsel -//----------------------------------------------------------------------------- -#ifndef _X360 - -static FORCEINLINE float fsel(float fComparand, float fValGE, float fLT) -{ - return fComparand >= 0 ? fValGE : fLT; -} -static FORCEINLINE double fsel(double fComparand, double fValGE, double fLT) -{ - return fComparand >= 0 ? fValGE : fLT; -} - -#else - -// __fsel(double fComparand, double fValGE, double fLT) == fComparand >= 0 ? fValGE : fLT -// this is much faster than if ( aFloat > 0 ) { x = .. } -#define fsel __fsel - -#endif - - -//----------------------------------------------------------------------------- -// FP exception handling -//----------------------------------------------------------------------------- -//#define CHECK_FLOAT_EXCEPTIONS 1 - -#if !defined( _X360 ) -#if defined( _MSC_VER ) - -inline void SetupFPUControlWordForceExceptions() -{ - // use local to get and store control word - uint16 tmpCtrlW; - __asm - { - fnclex /* clear all current exceptions */ - fnstcw word ptr [tmpCtrlW] /* get current control word */ - and [tmpCtrlW], 0FCC0h /* Keep infinity control + rounding control */ - or [tmpCtrlW], 0230h /* set to 53-bit, mask only inexact, underflow */ - fldcw word ptr [tmpCtrlW] /* put new control word in FPU */ - } -} - -#ifdef CHECK_FLOAT_EXCEPTIONS - -inline void SetupFPUControlWord() -{ - SetupFPUControlWordForceExceptions(); -} - -#else - -inline void SetupFPUControlWord() -{ - // use local to get and store control word - uint16 tmpCtrlW; - __asm - { - fnstcw word ptr [tmpCtrlW] /* get current control word */ - and [tmpCtrlW], 0FCC0h /* Keep infinity control + rounding control */ - or [tmpCtrlW], 023Fh /* set to 53-bit, mask only inexact, underflow */ - fldcw word ptr [tmpCtrlW] /* put new control word in FPU */ - } -} - -#endif - -#else - -inline void SetupFPUControlWord() -{ - __volatile unsigned short int __cw; - __asm __volatile ("fnstcw %0" : "=m" (__cw)); - __cw = __cw & 0x0FCC0; // keep infinity control, keep rounding mode - __cw = __cw | 0x023F; // set 53-bit, no exceptions - __asm __volatile ("fldcw %0" : : "m" (__cw)); -} - -#endif // _MSC_VER - -#else - -#ifdef _DEBUG -FORCEINLINE bool IsFPUControlWordSet() -{ - float f = 0.996f; - union - { - double flResult; - int pResult[2]; - }; - flResult = __fctiw( f ); - return ( pResult[1] == 1 ); -} -#endif - -inline void SetupFPUControlWord() -{ - // Set round-to-nearest in FPSCR - // (cannot assemble, must use op-code form) - __emit( 0xFF80010C ); // mtfsfi 7,0 - - // Favour compatibility over speed (make sure the VPU set to Java-compliant mode) - // NOTE: the VPU *always* uses round-to-nearest - __vector4 a = { 0.0f, 0.0f, 0.0f, 0.0f }; - a; // Avoid compiler warning - __asm - { - mtvscr a; // Clear the Vector Status & Control Register to zero - } -} - -#endif // _X360 - -//----------------------------------------------------------------------------- -// Purpose: Standard functions for handling endian-ness -//----------------------------------------------------------------------------- - -//------------------------------------- -// Basic swaps -//------------------------------------- - -template -inline T WordSwapC( T w ) -{ - uint16 temp; - - temp = ((*((uint16 *)&w) & 0xff00) >> 8); - temp |= ((*((uint16 *)&w) & 0x00ff) << 8); - - return *((T*)&temp); -} - -template -inline T DWordSwapC( T dw ) -{ - uint32 temp; - - temp = *((uint32 *)&dw) >> 24; - temp |= ((*((uint32 *)&dw) & 0x00FF0000) >> 8); - temp |= ((*((uint32 *)&dw) & 0x0000FF00) << 8); - temp |= ((*((uint32 *)&dw) & 0x000000FF) << 24); - - return *((T*)&temp); -} - -//------------------------------------- -// Fast swaps -//------------------------------------- - -#if defined( _X360 ) - -#define WordSwap WordSwap360Intr -#define DWordSwap DWordSwap360Intr - -template -inline T WordSwap360Intr( T w ) -{ - T output; - __storeshortbytereverse( w, 0, &output ); - return output; -} - -template -inline T DWordSwap360Intr( T dw ) -{ - T output; - __storewordbytereverse( dw, 0, &output ); - return output; -} - -#elif defined( _MSC_VER ) - -#define WordSwap WordSwapAsm -#define DWordSwap DWordSwapAsm - -#pragma warning(push) -#pragma warning (disable:4035) // no return value - -template -inline T WordSwapAsm( T w ) -{ - __asm - { - mov ax, w - xchg al, ah - } -} - -template -inline T DWordSwapAsm( T dw ) -{ - __asm - { - mov eax, dw - bswap eax - } -} - -#pragma warning(pop) - -#else - -#define WordSwap WordSwapC -#define DWordSwap DWordSwapC - -#endif - -//------------------------------------- -// The typically used methods. -//------------------------------------- - -#if defined(__i386__) && !defined LITTLE_ENDIAN -#define LITTLE_ENDIAN 1 -#endif - -#if (defined( _SGI_SOURCE ) || defined( _X360 )) && !defined BIG_ENDIAN -#define BIG_ENDIAN 1 -#endif - -// If a swapped float passes through the fpu, the bytes may get changed. -// Prevent this by swapping floats as DWORDs. -#define SafeSwapFloat( pOut, pIn ) (*((uint*)pOut) = DWordSwap( *((uint*)pIn) )) - -#if defined(LITTLE_ENDIAN) - -#define BigShort( val ) WordSwap( val ) -#define BigWord( val ) WordSwap( val ) -#define BigLong( val ) DWordSwap( val ) -#define BigDWord( val ) DWordSwap( val ) -#define LittleShort( val ) ( val ) -#define LittleWord( val ) ( val ) -#define LittleLong( val ) ( val ) -#define LittleDWord( val ) ( val ) -#define SwapShort( val ) BigShort( val ) -#define SwapWord( val ) BigWord( val ) -#define SwapLong( val ) BigLong( val ) -#define SwapDWord( val ) BigDWord( val ) - -// Pass floats by pointer for swapping to avoid truncation in the fpu -#define BigFloat( pOut, pIn ) SafeSwapFloat( pOut, pIn ) -#define LittleFloat( pOut, pIn ) ( *pOut = *pIn ) -#define SwapFloat( pOut, pIn ) BigFloat( pOut, pIn ) - -#elif defined(BIG_ENDIAN) - -#define BigShort( val ) ( val ) -#define BigWord( val ) ( val ) -#define BigLong( val ) ( val ) -#define BigDWord( val ) ( val ) -#define LittleShort( val ) WordSwap( val ) -#define LittleWord( val ) WordSwap( val ) -#define LittleLong( val ) DWordSwap( val ) -#define LittleDWord( val ) DWordSwap( val ) -#define SwapShort( val ) LittleShort( val ) -#define SwapWord( val ) LittleWord( val ) -#define SwapLong( val ) LittleLong( val ) -#define SwapDWord( val ) LittleDWord( val ) - -// Pass floats by pointer for swapping to avoid truncation in the fpu -#define BigFloat( pOut, pIn ) ( *pOut = *pIn ) -#define LittleFloat( pOut, pIn ) SafeSwapFloat( pOut, pIn ) -#define SwapFloat( pOut, pIn ) LittleFloat( pOut, pIn ) - -#else - -// @Note (toml 05-02-02): this technique expects the compiler to -// optimize the expression and eliminate the other path. On any new -// platform/compiler this should be tested. -inline short BigShort( short val ) { int test = 1; return ( *(char *)&test == 1 ) ? WordSwap( val ) : val; } -inline uint16 BigWord( uint16 val ) { int test = 1; return ( *(char *)&test == 1 ) ? WordSwap( val ) : val; } -inline long BigLong( long val ) { int test = 1; return ( *(char *)&test == 1 ) ? DWordSwap( val ) : val; } -inline uint32 BigDWord( uint32 val ) { int test = 1; return ( *(char *)&test == 1 ) ? DWordSwap( val ) : val; } -inline short LittleShort( short val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : WordSwap( val ); } -inline uint16 LittleWord( uint16 val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : WordSwap( val ); } -inline long LittleLong( long val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : DWordSwap( val ); } -inline uint32 LittleDWord( uint32 val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : DWordSwap( val ); } -inline short SwapShort( short val ) { return WordSwap( val ); } -inline uint16 SwapWord( uint16 val ) { return WordSwap( val ); } -inline long SwapLong( long val ) { return DWordSwap( val ); } -inline uint32 SwapDWord( uint32 val ) { return DWordSwap( val ); } - -// Pass floats by pointer for swapping to avoid truncation in the fpu -inline void BigFloat( float *pOut, const float *pIn ) { int test = 1; ( *(char *)&test == 1 ) ? SafeSwapFloat( pOut, pIn ) : ( *pOut = *pIn ); } -inline void LittleFloat( float *pOut, const float *pIn ) { int test = 1; ( *(char *)&test == 1 ) ? ( *pOut = *pIn ) : SafeSwapFloat( pOut, pIn ); } -inline void SwapFloat( float *pOut, const float *pIn ) { SafeSwapFloat( pOut, pIn ); } - -#endif - -#if _X360 -inline unsigned long LoadLittleDWord( unsigned long *base, unsigned int dwordIndex ) -{ - return __loadwordbytereverse( dwordIndex<<2, base ); -} - -inline void StoreLittleDWord( unsigned long *base, unsigned int dwordIndex, unsigned long dword ) -{ - __storewordbytereverse( dword, dwordIndex<<2, base ); -} -#else -inline unsigned long LoadLittleDWord( unsigned long *base, unsigned int dwordIndex ) -{ - return LittleDWord( base[dwordIndex] ); -} - -inline void StoreLittleDWord( unsigned long *base, unsigned int dwordIndex, unsigned long dword ) -{ - base[dwordIndex] = LittleDWord(dword); -} -#endif - - -#ifndef STATIC_TIER0 - -#ifdef TIER0_DLL_EXPORT - #define PLATFORM_INTERFACE DLL_EXPORT - #define PLATFORM_OVERLOAD DLL_GLOBAL_EXPORT -#else - #define PLATFORM_INTERFACE DLL_IMPORT - #define PLATFORM_OVERLOAD DLL_GLOBAL_IMPORT -#endif - -#else // BUILD_AS_DLL - -#define PLATFORM_INTERFACE extern -#define PLATFORM_OVERLOAD - -#endif // BUILD_AS_DLL - - -// When in benchmark mode, the timer returns a simple incremented value each time you call it. -// -// It should not be changed after startup unless you really know what you're doing. The only place -// that should do this is the benchmark code itself so it can output a legit duration. -PLATFORM_INTERFACE void Plat_SetBenchmarkMode( bool bBenchmarkMode ); -PLATFORM_INTERFACE bool Plat_IsInBenchmarkMode(); - - -PLATFORM_INTERFACE double Plat_FloatTime(); // Returns time in seconds since the module was loaded. -PLATFORM_INTERFACE unsigned long Plat_MSTime(); // Time in milliseconds. - -// b/w compatibility -#define Sys_FloatTime Plat_FloatTime - - -// Processor Information: -struct CPUInformation -{ - int m_Size; // Size of this structure, for forward compatability. - - bool m_bRDTSC : 1, // Is RDTSC supported? - m_bCMOV : 1, // Is CMOV supported? - m_bFCMOV : 1, // Is FCMOV supported? - m_bSSE : 1, // Is SSE supported? - m_bSSE2 : 1, // Is SSE2 Supported? - m_b3DNow : 1, // Is 3DNow! Supported? - m_bMMX : 1, // Is MMX supported? - m_bHT : 1; // Is HyperThreading supported? - - uint8 m_nLogicalProcessors; // Number op logical processors. - uint8 m_nPhysicalProcessors; // Number of physical processors - - int64 m_Speed; // In cycles per second. - - tchar* m_szProcessorID; // Processor vendor Identification. -}; - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunknown-pragmas" -#pragma clang diagnostic ignored "-Wreturn-type-c-linkage" -#endif - -PLATFORM_INTERFACE const CPUInformation& GetCPUInformation(); - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -PLATFORM_INTERFACE void GetCurrentDate( int *pDay, int *pMonth, int *pYear ); - -// ---------------------------------------------------------------------------------- // -// Performance Monitoring Events - L2 stats etc... -// ---------------------------------------------------------------------------------- // -PLATFORM_INTERFACE void InitPME(); -PLATFORM_INTERFACE void ShutdownPME(); - -//----------------------------------------------------------------------------- -// Thread related functions -//----------------------------------------------------------------------------- -// Registers the current thread with Tier0's thread management system. -// This should be called on every thread created in the game. -PLATFORM_INTERFACE unsigned long Plat_RegisterThread( const tchar *pName = _T("Source Thread")); - -// Registers the current thread as the primary thread. -PLATFORM_INTERFACE unsigned long Plat_RegisterPrimaryThread(); - -// VC-specific. Sets the thread's name so it has a friendly name in the debugger. -// This should generally only be handled by Plat_RegisterThread and Plat_RegisterPrimaryThread -PLATFORM_INTERFACE void Plat_SetThreadName( unsigned long dwThreadID, const tchar *pName ); - -// These would be private if it were possible to export private variables from a .DLL. -// They need to be variables because they are checked by inline functions at performance -// critical places. -PLATFORM_INTERFACE unsigned long Plat_PrimaryThreadID; - -// Returns the ID of the currently executing thread. -PLATFORM_INTERFACE unsigned long Plat_GetCurrentThreadID(); - -// Returns the ID of the primary thread. -inline unsigned long Plat_GetPrimaryThreadID() -{ - return Plat_PrimaryThreadID; -} - -// Returns true if the current thread is the primary thread. -inline bool Plat_IsPrimaryThread() -{ - //return true; - return (Plat_GetPrimaryThreadID() == Plat_GetCurrentThreadID() ); -} - -//----------------------------------------------------------------------------- -// Process related functions -//----------------------------------------------------------------------------- -PLATFORM_INTERFACE const tchar *Plat_GetCommandLine(); -#ifndef _WIN32 -// helper function for OS's that don't have a ::GetCommandLine() call -PLATFORM_INTERFACE void Plat_SetCommandLine( const char *cmdLine ); -#endif -PLATFORM_INTERFACE const char *Plat_GetCommandLineA(); - -//----------------------------------------------------------------------------- -// Security related functions -//----------------------------------------------------------------------------- -// Ensure that the hardware key's drivers have been installed. -PLATFORM_INTERFACE bool Plat_VerifyHardwareKeyDriver(); - -// Ok, so this isn't a very secure way to verify the hardware key for now. It -// is primarially depending on the fact that all the binaries have been wrapped -// with the secure wrapper provided by the hardware keys vendor. -PLATFORM_INTERFACE bool Plat_VerifyHardwareKey(); - -// The same as above, but notifies user with a message box when the key isn't in -// and gives him an opportunity to correct the situation. -PLATFORM_INTERFACE bool Plat_VerifyHardwareKeyPrompt(); - -// Can be called in real time, doesn't perform the verify every frame. Mainly just -// here to allow the game to drop out quickly when the key is removed, rather than -// allowing the wrapper to pop up it's own blocking dialog, which the engine doesn't -// like much. -PLATFORM_INTERFACE bool Plat_FastVerifyHardwareKey(); - -//----------------------------------------------------------------------------- -// Just logs file and line to simple.log -//----------------------------------------------------------------------------- -PLATFORM_INTERFACE void* Plat_SimpleLog( const tchar* file, int line ); - -//----------------------------------------------------------------------------- -// Returns true if debugger attached, false otherwise -//----------------------------------------------------------------------------- -#if defined(_WIN32) -PLATFORM_INTERFACE bool Plat_IsInDebugSession(); -PLATFORM_INTERFACE void Plat_DebugString( const char * ); -#else -#define Plat_IsInDebugSession() (false) -#define Plat_DebugString(s) ((void)0) -#endif - -//----------------------------------------------------------------------------- -// XBOX Components valid in PC compilation space -//----------------------------------------------------------------------------- - -#define XBOX_DVD_SECTORSIZE 2048 -#define XBOX_DVD_ECC_SIZE 32768 // driver reads in quantum ECC blocks -#define XBOX_HDD_SECTORSIZE 512 - -// Custom windows messages for Xbox input -#define WM_XREMOTECOMMAND (WM_USER + 100) -#define WM_XCONTROLLER_KEY (WM_USER + 101) -#define WM_SYS_UI (WM_USER + 102) -#define WM_SYS_SIGNINCHANGED (WM_USER + 103) -#define WM_SYS_STORAGEDEVICESCHANGED (WM_USER + 104) -#define WM_SYS_PROFILESETTINGCHANGED (WM_USER + 105) -#define WM_SYS_MUTELISTCHANGED (WM_USER + 106) -#define WM_SYS_INPUTDEVICESCHANGED (WM_USER + 107) -#define WM_SYS_INPUTDEVICECONFIGCHANGED (WM_USER + 108) -#define WM_LIVE_CONNECTIONCHANGED (WM_USER + 109) -#define WM_LIVE_INVITE_ACCEPTED (WM_USER + 110) -#define WM_LIVE_LINK_STATE_CHANGED (WM_USER + 111) -#define WM_LIVE_CONTENT_INSTALLED (WM_USER + 112) -#define WM_LIVE_MEMBERSHIP_PURCHASED (WM_USER + 113) -#define WM_LIVE_VOICECHAT_AWAY (WM_USER + 114) -#define WM_LIVE_PRESENCE_CHANGED (WM_USER + 115) -#define WM_FRIENDS_PRESENCE_CHANGED (WM_USER + 116) -#define WM_FRIENDS_FRIEND_ADDED (WM_USER + 117) -#define WM_FRIENDS_FRIEND_REMOVED (WM_USER + 118) -#define WM_CUSTOM_GAMEBANNERPRESSED (WM_USER + 119) -#define WM_CUSTOM_ACTIONPRESSED (WM_USER + 120) -#define WM_XMP_STATECHANGED (WM_USER + 121) -#define WM_XMP_PLAYBACKBEHAVIORCHANGED (WM_USER + 122) -#define WM_XMP_PLAYBACKCONTROLLERCHANGED (WM_USER + 123) - -inline const char *GetPlatformExt( void ) -{ - return IsX360() ? ".360" : ""; -} - -// flat view, 6 hw threads -#define XBOX_PROCESSOR_0 ( 1<<0 ) -#define XBOX_PROCESSOR_1 ( 1<<1 ) -#define XBOX_PROCESSOR_2 ( 1<<2 ) -#define XBOX_PROCESSOR_3 ( 1<<3 ) -#define XBOX_PROCESSOR_4 ( 1<<4 ) -#define XBOX_PROCESSOR_5 ( 1<<5 ) - -// core view, 3 cores with 2 hw threads each -#define XBOX_CORE_0_HWTHREAD_0 XBOX_PROCESSOR_0 -#define XBOX_CORE_0_HWTHREAD_1 XBOX_PROCESSOR_1 -#define XBOX_CORE_1_HWTHREAD_0 XBOX_PROCESSOR_2 -#define XBOX_CORE_1_HWTHREAD_1 XBOX_PROCESSOR_3 -#define XBOX_CORE_2_HWTHREAD_0 XBOX_PROCESSOR_4 -#define XBOX_CORE_2_HWTHREAD_1 XBOX_PROCESSOR_5 - -//----------------------------------------------------------------------------- -// Include additional dependant header components. -//----------------------------------------------------------------------------- -#include "tier0/fasttimer.h" - -#if defined( _X360 ) -#include "xbox/xbox_core.h" -#endif - -//----------------------------------------------------------------------------- -// Methods to invoke the constructor, copy constructor, and destructor -//----------------------------------------------------------------------------- - -template -inline void Construct( T* pMemory ) -{ - ::new( pMemory ) T; -} - -template -inline void CopyConstruct( T* pMemory, T const& src ) -{ - ::new( pMemory ) T(src); -} - -template -inline void Destruct( T* pMemory ) -{ - pMemory->~T(); - -#ifdef _DEBUG - memset( pMemory, 0xDD, sizeof(T) ); -#endif -} - - -// -// GET_OUTER() -// -// A platform-independent way for a contained class to get a pointer to its -// owner. If you know a class is exclusively used in the context of some -// "outer" class, this is a much more space efficient way to get at the outer -// class than having the inner class store a pointer to it. -// -// class COuter -// { -// class CInner // Note: this does not need to be a nested class to work -// { -// void PrintAddressOfOuter() -// { -// printf( "Outer is at 0x%x\n", GET_OUTER( COuter, m_Inner ) ); -// } -// }; -// -// CInner m_Inner; -// friend class CInner; -// }; - -#define GET_OUTER( OuterType, OuterMember ) \ - ( ( OuterType * ) ( (uint8 *)this - offsetof( OuterType, OuterMember ) ) ) - - -/* TEMPLATE_FUNCTION_TABLE() - - (Note added to platform.h so platforms that correctly support templated - functions can handle portions as templated functions rather than wrapped - functions) - - Helps automate the process of creating an array of function - templates that are all specialized by a single integer. - This sort of thing is often useful in optimization work. - - For example, using TEMPLATE_FUNCTION_TABLE, this: - - TEMPLATE_FUNCTION_TABLE(int, Function, ( int blah, int blah ), 10) - { - return argument * argument; - } - - is equivilent to the following: - - (NOTE: the function has to be wrapped in a class due to code - generation bugs involved with directly specializing a function - based on a constant.) - - template - class FunctionWrapper - { - public: - int Function( int blah, int blah ) - { - return argument*argument; - } - } - - typedef int (*FunctionType)( int blah, int blah ); - - class FunctionName - { - public: - enum { count = 10 }; - FunctionType functions[10]; - }; - - FunctionType FunctionName::functions[] = - { - FunctionWrapper<0>::Function, - FunctionWrapper<1>::Function, - FunctionWrapper<2>::Function, - FunctionWrapper<3>::Function, - FunctionWrapper<4>::Function, - FunctionWrapper<5>::Function, - FunctionWrapper<6>::Function, - FunctionWrapper<7>::Function, - FunctionWrapper<8>::Function, - FunctionWrapper<9>::Function - }; -*/ - -PLATFORM_INTERFACE bool vtune( bool resume ); - - -#define TEMPLATE_FUNCTION_TABLE(RETURN_TYPE, NAME, ARGS, COUNT) \ - \ -typedef RETURN_TYPE (FASTCALL *__Type_##NAME) ARGS; \ - \ -template \ -struct __Function_##NAME \ -{ \ - static RETURN_TYPE FASTCALL Run ARGS; \ -}; \ - \ -template \ -struct __MetaLooper_##NAME : __MetaLooper_##NAME \ -{ \ - __Type_##NAME func; \ - inline __MetaLooper_##NAME() { func = __Function_##NAME::Run; } \ -}; \ - \ -template<> \ -struct __MetaLooper_##NAME<0> \ -{ \ - __Type_##NAME func; \ - inline __MetaLooper_##NAME() { func = __Function_##NAME<0>::Run; } \ -}; \ - \ -class NAME \ -{ \ -private: \ - static const __MetaLooper_##NAME m; \ -public: \ - enum { count = COUNT }; \ - static const __Type_##NAME* functions; \ -}; \ -const __MetaLooper_##NAME NAME::m; \ -const __Type_##NAME* NAME::functions = (__Type_##NAME*)&m; \ -template \ -RETURN_TYPE FASTCALL __Function_##NAME::Run ARGS - - -#define LOOP_INTERCHANGE(BOOLEAN, CODE)\ - if( (BOOLEAN) )\ - {\ - CODE;\ - } else\ - {\ - CODE;\ - } - -//----------------------------------------------------------------------------- - -#if defined(_INC_WINDOWS) && defined(_WIN32) -template -class CDynamicFunction -{ -public: - CDynamicFunction( const char *pszModule, const char *pszName, FUNCPTR_TYPE pfnFallback = NULL ) - { - m_pfn = pfnFallback; - - HMODULE hModule = ::LoadLibrary( pszModule ); - if ( hModule ) - m_pfn = (FUNCPTR_TYPE)::GetProcAddress( hModule, pszName ); - } - - operator bool() { return m_pfn != NULL; } - bool operator !() { return !m_pfn; } - operator FUNCPTR_TYPE() { return m_pfn; } - -private: - FUNCPTR_TYPE m_pfn; -}; -#endif - -//----------------------------------------------------------------------------- - -#include "tier0/valve_on.h" - -#endif /* PLATFORM_H */ diff --git a/public/tier0/pmc360.h b/public/tier0/pmc360.h deleted file mode 100644 index 94b5ec01d..000000000 --- a/public/tier0/pmc360.h +++ /dev/null @@ -1,73 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Analogous to l2cache.h, this class represents information gleaned -// from the 360's Performance Monitor Counters. In particular we -// are interested in l2 cache misses and load-hit-stores. -// -//=============================================================================// -#ifndef CPMCDATA_H -#define CPMCDATA_H -#ifdef _WIN32 -#pragma once -#endif - -#ifndef _X360 -#error This file must only be compiled for XBOX360! -#endif - - -// Warning: -// As written, this class only supports profiling thread 0, processor 0. - -class CPMCData -{ -public: - - CPMCData(); - ~CPMCData() {}; - - void Start( void ); - void End( void ); - - /// This function should be called exactly once during the lifespan of the program; - /// it will set up the counters to record the information we are interested in. - /// This will stomp on whoever else might have set the performance counters elsewhere - /// in the game. - static void InitializeOnceProgramWide( void ); - static bool IsInitialized(); - - //------------------------------------------------------------------------- - // GetL2CacheMisses - //------------------------------------------------------------------------- - uint64 GetL2CacheMisses( void ) const - { - return m_Delta.L2CacheMiss; - } - - uint64 GetLHS( void ) const - { - return m_Delta.LHS; - } - -/* -#ifdef DBGFLAG_VALIDATE - void Validate( CValidator &validator, tchar *pchName ); // Validate our internal structures -#endif // DBGFLAG_VALIDATE -*/ - -private: - /// represents saved numbers from the counters we are interested in - struct PMCounters - { - uint64 L2CacheMiss; - uint64 LHS; ///< load hit store - - PMCounters(int64 _l2cm, int64 _lhs ) : L2CacheMiss(_l2cm), LHS(_lhs) {}; - PMCounters() : L2CacheMiss(0), LHS(0) {}; - }; - - PMCounters m_OnStart; ///< values when we began the timer - PMCounters m_Delta ; ///< computed total delta between start/stop -}; - -#endif // CPMCDATA_H diff --git a/public/tier0/progressbar.h b/public/tier0/progressbar.h deleted file mode 100644 index 865c1aec0..000000000 --- a/public/tier0/progressbar.h +++ /dev/null @@ -1,23 +0,0 @@ -//========= Copyright 1996-2006, Valve Corporation, All rights reserved. ============// -// -// Purpose: Provide a shared place for library fucntions to report progress % for display -// -//=============================================================================// - -#ifndef PROGRESSBAR_H -#define PROGRESSBAR_H -#ifdef _WIN32 -#pragma once -#endif - - -PLATFORM_INTERFACE void ReportProgress(char const *job_name, int total_units_to_do, - int n_units_completed); - -typedef void (*ProgressReportHandler_t)( char const*, int, int ); - -// install your own handler. returns previous handler -PLATFORM_INTERFACE ProgressReportHandler_t InstallProgressReportHandler( ProgressReportHandler_t pfn); - - -#endif diff --git a/public/tier0/protected_things.h b/public/tier0/protected_things.h deleted file mode 100644 index 6954065a6..000000000 --- a/public/tier0/protected_things.h +++ /dev/null @@ -1,284 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PROTECTED_THINGS_H -#define PROTECTED_THINGS_H -#ifdef _WIN32 -#pragma once -#endif - - -// This header tries to prevent people from using potentially dangerous functions -// (like the notorious non-null-terminating strncpy) and functions that will break -// VCR mode (like time, input, registry, etc). -// -// This header should be included by ALL of our source code. - -// Eventually, ALL of these should be protected, but one man can only accomplish so much in -// one day AND work on features too! -#if defined( PROTECTED_STRINGS_ENABLE ) - - #if defined( printf ) - #undef printf - #endif - #define printf printf__HEY_YOU__USE_VSTDLIB - - #if defined( wprintf ) - #undef wprintf - #endif - #define wprintf wprintf__HEY_YOU__USE_VSTDLIB - - #if defined( strcmp ) - #undef strcmp - #endif - #define strcmp strcmp__HEY_YOU__USE_VSTDLIB - - #if defined( wcscmp ) - #undef wcscmp - #endif - #define wcscmp wcscmp__HEY_YOU__USE_VSTDLIB - - #if defined( strncpy ) - #undef strncpy - #endif - #define strncpy strncpy__HEY_YOU__USE_VSTDLIB - - #if defined( wcsncpy ) - #undef wcsncpy - #endif - #define wcsncpy wcsncpy__HEY_YOU__USE_VSTDLIB - - #if defined( strlen ) - #undef strlen - #endif - #define strlen strlen__HEY_YOU__USE_VSTDLIB - - #if defined( wcslen ) - #undef wcslen - #endif - #define wcslen wcslen__HEY_YOU__USE_VSTDLIB - - #if defined( Q_strlen ) - #undef Q_strlen - #endif - #define Q_strlen Q_strlen__HEY_YOU__USE_VSTDLIB - - #if defined( _snprintf ) - #undef _snprintf - #endif - #define _snprintf snprintf__HEY_YOU__USE_VSTDLIB - - #if defined( _snwprintf ) - #undef _snwprintf - #endif - #define _snwprintf snwprintf__HEY_YOU__USE_VSTDLIB - - #if defined( sprintf ) - #undef sprintf - #endif - #define sprintf sprintf__HEY_YOU__USE_VSTDLIB - - #if defined( swprintf ) - #undef swprintf - #endif - #define swprintf swprintf__HEY_YOU__USE_VSTDLIB - - #if defined( vsprintf ) - #undef vsprintf - #endif - #define vsprintf vsprintf__HEY_YOU__USE_VSTDLIB - - #if defined( vswprintf ) - #undef vswprintf - #endif - #define vswprintf vswprintf__HEY_YOU__USE_VSTDLIB - - #if defined( _vsnprintf ) - #undef _vsnprintf - #endif - #define _vsnprintf vsnprintf__HEY_YOU__USE_VSTDLIB - - #if defined( _vsnwprintf ) - #undef _vsnwprintf - #endif - #define _vsnwprintf vsnwprintf__HEY_YOU__USE_VSTDLIB - - #if defined( strcat ) - #undef strcat - #endif - #define strcat strcat__HEY_YOU__USE_VSTDLIB - - #if defined( wcscat ) - #undef wcscat - #endif - #define wcscat wcscat__HEY_YOU__USE_VSTDLIB - - #if defined( strncat ) - #undef strncat - #endif - #define strncat strncat__HEY_YOU__USE_VSTDLIB - - #if defined( wcsncat ) - #undef wcsncat - #endif - #define wcsncat wcsncat__HEY_YOU__USE_VSTDLIB - -#endif - - -#if defined( PROTECT_FILEIO_FUNCTIONS ) && ( ! defined( _LINUX ) ) - #if defined( fopen ) - #undef fopen - #endif - #define fopen fopen_USE_FILESYSTEM_INSTEAD - - #if defined( _wfopen ) - #undef _wfopen - #endif - #define _wfopen _wfopen_USE_FILESYSTEM_INSTEAD -#endif - - -#if defined( PROTECTED_THINGS_ENABLE ) && !defined( _X360 ) - - #if defined( GetTickCount ) - #undef GetTickCount - #endif - #define GetTickCount GetTickCount__USE_VCR_MODE - - - #if defined( timeGetTime ) - #undef timeGetTime - #endif - #define timeGetTime timeGetTime__USE_VCR_MODE - #if defined( clock ) - #undef clock - #endif - #define time time__USE_VCR_MODE - - - #if defined( recvfrom ) - #undef recvfrom - #endif - #define recvfrom recvfrom__USE_VCR_MODE - - - #if defined( GetCursorPos ) - #undef GetCursorPos - #endif - #define GetCursorPos GetCursorPos__USE_VCR_MODE - - - #if defined( ScreenToClient ) - #undef ScreenToClient - #endif - #define ScreenToClient ScreenToClient__USE_VCR_MODE - - - #if defined( GetCommandLine ) - #undef GetCommandLine - #endif - #define GetCommandLine GetCommandLine__USE_VCR_MODE - - - #if defined( RegOpenKeyEx ) - #undef RegOpenKeyEx - #endif - #define RegOpenKeyEx RegOpenKeyEx__USE_VCR_MODE - - - #if defined( RegOpenKey ) - #undef RegOpenKey - #endif - #define RegOpenKey RegOpenKey__USE_VCR_MODE - - - #if defined( RegSetValueEx ) - #undef RegSetValueEx - #endif - #define RegSetValueEx RegSetValueEx__USE_VCR_MODE - - - #if defined( RegSetValue ) - #undef RegSetValue - #endif - #define RegSetValue RegSetValue__USE_VCR_MODE - - - #if defined( RegQueryValueEx ) - #undef RegQueryValueEx - #endif - #define RegQueryValueEx RegQueryValueEx__USE_VCR_MODE - - - #if defined( RegQueryValue ) - #undef RegQueryValue - #endif - #define RegQueryValue RegQueryValue__USE_VCR_MODE - - - #if defined( RegCreateKeyEx ) - #undef RegCreateKeyEx - #endif - #define RegCreateKeyEx RegCreateKeyEx__USE_VCR_MODE - - - #if defined( RegCreateKey ) - #undef RegCreateKey - #endif - #define RegCreateKey RegCreateKey__USE_VCR_MODE - - - #if defined( RegCloseKey ) - #undef RegCloseKey - #endif - #define RegCloseKey RegCloseKey__USE_VCR_MODE - - - #if defined( GetNumberOfConsoleInputEvents ) - #undef GetNumberOfConsoleInputEvents - #endif - #define GetNumberOfConsoleInputEvents GetNumberOfConsoleInputEvents__USE_VCR_MODE - - - #if defined( ReadConsoleInput ) - #undef ReadConsoleInput - #endif - #define ReadConsoleInput ReadConsoleInput__USE_VCR_MODE - - - #if defined( GetAsyncKeyState ) - #undef GetAsyncKeyState - #endif - #define GetAsyncKeyState GetAsyncKeyState__USE_VCR_MODE - - - #if defined( GetKeyState ) - #undef GetKeyState - #endif - #define GetKeyState GetKeyState__USE_VCR_MODE - - - #if defined( CreateThread ) - #undef CreateThread - #endif - #define CreateThread CreateThread__USE_VCR_MODE - - #if defined( WaitForSingleObject ) - #undef WaitForSingleObject - #endif - #define WaitForSingleObject WaitForSingleObject__USE_VCR_MODE - - #if defined( EnterCriticalSection ) - #undef EnterCriticalSection - #endif - #define EnterCriticalSection EnterCriticalSection__USE_VCR_MODE - -#endif - - -#endif // PROTECTED_THINGS_H diff --git a/public/tier0/systeminformation.h b/public/tier0/systeminformation.h deleted file mode 100644 index af5809e6b..000000000 --- a/public/tier0/systeminformation.h +++ /dev/null @@ -1,56 +0,0 @@ -//====== Copyright c 1996-2007, Valve Corporation, All rights reserved. =======// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef SYSTEMINFORMATION_H -#define SYSTEMINFORMATION_H - -#ifdef _WIN32 - #pragma once -#endif - -#ifndef PLATFORM_INTERFACE - #define PLATFORM_INTERFACE -#endif - -// -// Defines a possible outcome of a system call -// -enum SYSTEM_CALL_RESULT_t -{ - SYSCALL_SUCCESS = 0, // System call succeeded - SYSCALL_FAILED = 1, // System call failed - SYSCALL_NOPROC = 2, // Failed to find required system procedure - SYSCALL_NODLL = 3, // Failed to find or load required system module - SYSCALL_UNSUPPORTED = 4, // System call unsupported on the OS -}; - - -// -// Information about paged pool memory -// -struct PAGED_POOL_INFO_t -{ - unsigned long numPagesUsed; // Number of Paged Pool pages used - unsigned long numPagesFree; // Number of Paged Pool pages free -}; - -// -// Plat_GetMemPageSize -// Returns the size of a memory page in kilobytes. -// -PLATFORM_INTERFACE unsigned long Plat_GetMemPageSize(); - -// -// Plat_GetPagedPoolInfo -// Fills in the paged pool info structure if successful. -// -PLATFORM_INTERFACE SYSTEM_CALL_RESULT_t Plat_GetPagedPoolInfo( PAGED_POOL_INFO_t *pPPI ); - - - -#endif // #ifndef SYSTEMINFORMATION_H diff --git a/public/tier0/testthread.h b/public/tier0/testthread.h deleted file mode 100644 index 218e8dd69..000000000 --- a/public/tier0/testthread.h +++ /dev/null @@ -1,60 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: exposes testing thread functions -// -//============================================================================= - -#ifndef TESTTHREAD_H -#define TESTTHREAD_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/dbg.h" - -// test callback -typedef void (STDCALL *TestFunc)(void *pv); - -// runs the test function -DBG_INTERFACE void Test_RunTest(TestFunc func, void *pvArg); - -// call to give the test thread a chance to run -// calling thread will block until the test thread yields -// doesn't do anything if no tests are running -DBG_INTERFACE void Test_RunFrame(); - -// true if any tests are running, or have ran -DBG_INTERFACE bool Test_IsActive(); - -// sets that the test has failed -DBG_INTERFACE void Test_SetFailed(); - -// true if any tests have failed, due to an assert, warning, or explicit fail -DBG_INTERFACE bool Test_HasFailed(); - -// true if any tests have completed -DBG_INTERFACE bool Test_HasFinished(); - -// terminates the test thread -DBG_INTERFACE void Test_TerminateThread(); - -// the following functions should only be called from the test thread - -// yields to the main thread for a single frame -// passing in is a count of the number of frames that have been yielded by this yield macro -// can be used to assert if a test thread is blocked foor -DBG_INTERFACE void TestThread_Yield(); - -// utility functions to pause the test frame until the selected condition is true -#define YIELD_UNTIL(x) { int iYieldCount = 0; while (!(x)) { TestThread_Yield(); iYieldCount++; if ( iYieldCount >= 100 ) { AssertMsg( false, #x ); break; } } } - -// use this like a while(1) loop, with break; to stop yielding -#define YIELD_UNTIL_BREAK() for (; true; TestThread_Yield()) - -// yields for a single frame -#define YIELD_FRAME() { TestThread_Yield(); } -#define YIELD_TWO_FRAMES() { TestThread_Yield(); TestThread_Yield(); } - - - -#endif // TESTTHREAD_H diff --git a/public/tier0/threadtools.h b/public/tier0/threadtools.h deleted file mode 100644 index 7f0f76c3f..000000000 --- a/public/tier0/threadtools.h +++ /dev/null @@ -1,1579 +0,0 @@ -//========== Copyright 2005, Valve Corporation, All rights reserved. ======== -// -// Purpose: A collection of utility classes to simplify thread handling, and -// as much as possible contain portability problems. Here avoiding -// including windows.h. -// -//============================================================================= - -#ifndef THREADTOOLS_H -#define THREADTOOLS_H - -#include - -#include "tier0/platform.h" -#include "tier0/dbg.h" -#include "tier0/vcrmode.h" - -#if defined _LINUX || defined __APPLE__ -#include -#include -#endif - -#if defined( _WIN32 ) -#pragma once -#pragma warning(push) -#pragma warning(disable:4251) -#endif - -// #define THREAD_PROFILER 1 - -#ifndef STATIC_TIER0 - -#ifdef TIER0_DLL_EXPORT -#define TT_INTERFACE DLL_EXPORT -#define TT_OVERLOAD DLL_GLOBAL_EXPORT -#define TT_CLASS DLL_CLASS_EXPORT -#else -#define TT_INTERFACE DLL_IMPORT -#define TT_OVERLOAD DLL_GLOBAL_IMPORT -#define TT_CLASS DLL_CLASS_IMPORT -#endif - -#else // BUILD_AS_DLL - -#define TT_INTERFACE extern -#define TT_OVERLOAD -#define TT_CLASS -#endif // BUILD_AS_DLL - -#ifndef _RETAIL -#define THREAD_MUTEX_TRACING_SUPPORTED -#if defined(_WIN32) && defined(_DEBUG) -#define THREAD_MUTEX_TRACING_ENABLED -#endif -#endif - -#ifdef _WIN32 -typedef void *HANDLE; -#endif - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- - -const unsigned TT_INFINITE = 0xffffffff; - -#ifndef NO_THREAD_LOCAL - -#ifndef THREAD_LOCAL -#ifdef _WIN32 -#define THREAD_LOCAL __declspec(thread) -#elif defined _LINUX || defined __APPLE__ -#define THREAD_LOCAL __thread -#endif -#endif - -#endif // NO_THREAD_LOCAL - -typedef unsigned long ThreadId_t; - -//----------------------------------------------------------------------------- -// -// Simple thread creation. Differs from VCR mode/CreateThread/_beginthreadex -// in that it accepts a standard C function rather than compiler specific one. -// -//----------------------------------------------------------------------------- -FORWARD_DECLARE_HANDLE( ThreadHandle_t ); -typedef unsigned (*ThreadFunc_t)( void *pParam ); - -TT_OVERLOAD ThreadHandle_t CreateSimpleThread( ThreadFunc_t, void *pParam, ThreadId_t *pID, unsigned stackSize = 0 ); -TT_INTERFACE ThreadHandle_t CreateSimpleThread( ThreadFunc_t, void *pParam, unsigned stackSize = 0 ); -TT_INTERFACE bool ReleaseThreadHandle( ThreadHandle_t ); - - -//----------------------------------------------------------------------------- - -TT_INTERFACE void ThreadSleep(unsigned duration = 0); -TT_INTERFACE uint ThreadGetCurrentId(); -TT_INTERFACE ThreadHandle_t ThreadGetCurrentHandle(); -TT_INTERFACE int ThreadGetPriority( ThreadHandle_t hThread = NULL ); -TT_INTERFACE bool ThreadSetPriority( ThreadHandle_t hThread, int priority ); -inline bool ThreadSetPriority( int priority ) { return ThreadSetPriority( NULL, priority ); } -TT_INTERFACE bool ThreadInMainThread(); -TT_INTERFACE void DeclareCurrentThreadIsMainThread(); - -// NOTE: ThreadedLoadLibraryFunc_t needs to return the sleep time in milliseconds or TT_INFINITE -typedef int (*ThreadedLoadLibraryFunc_t)(); -TT_INTERFACE void SetThreadedLoadLibraryFunc( ThreadedLoadLibraryFunc_t func ); -TT_INTERFACE ThreadedLoadLibraryFunc_t GetThreadedLoadLibraryFunc(); - -#if defined( _WIN32 ) && !defined( _WIN64 ) && !defined( _X360 ) -extern "C" unsigned long __declspec(dllimport) __stdcall GetCurrentThreadId(); -#define ThreadGetCurrentId GetCurrentThreadId -#endif - -inline void ThreadPause() -{ -#if defined( _WIN32 ) && !defined( _X360 ) - __asm pause; -#elif defined _LINUX || defined __APPLE__ - __asm __volatile("pause"); -#elif defined( _X360 ) -#else -#error "implement me" -#endif -} - -TT_INTERFACE bool ThreadJoin( ThreadHandle_t, unsigned timeout = TT_INFINITE ); - -TT_INTERFACE void ThreadSetDebugName( ThreadId_t id, const char *pszName ); -inline void ThreadSetDebugName( const char *pszName ) { ThreadSetDebugName( (ThreadId_t)-1, pszName ); } - -TT_INTERFACE void ThreadSetAffinity( ThreadHandle_t hThread, int nAffinityMask ); - -//----------------------------------------------------------------------------- - -enum ThreadWaitResult_t -{ - TW_FAILED = 0xffffffff, // WAIT_FAILED - TW_TIMEOUT = 0x00000102, // WAIT_TIMEOUT -}; - -#ifdef _WIN32 -TT_INTERFACE int ThreadWaitForObjects( int nEvents, const HANDLE *pHandles, bool bWaitAll = true, unsigned timeout = TT_INFINITE ); -inline int ThreadWaitForObject( HANDLE handle, bool bWaitAll = true, unsigned timeout = TT_INFINITE ) { return ThreadWaitForObjects( 1, &handle, bWaitAll, timeout ); } -#endif - -//----------------------------------------------------------------------------- -// -// Interlock methods. These perform very fast atomic thread -// safe operations. These are especially relevant in a multi-core setting. -// -//----------------------------------------------------------------------------- - -#ifdef _WIN32 -#define NOINLINE -#elif defined _LINUX || defined __APPLE__ -#define NOINLINE __attribute__ ((noinline)) -#endif - -#if defined(_WIN32) && !defined(_X360) -#if ( _MSC_VER >= 1310 ) -#define USE_INTRINSIC_INTERLOCKED -#endif -#endif - -#ifdef USE_INTRINSIC_INTERLOCKED -extern "C" -{ - long __cdecl _InterlockedIncrement(volatile long*); - long __cdecl _InterlockedDecrement(volatile long*); - long __cdecl _InterlockedExchange(volatile long*, long); - long __cdecl _InterlockedExchangeAdd(volatile long*, long); - long __cdecl _InterlockedCompareExchange(volatile long*, long, long); -} - -#pragma intrinsic( _InterlockedCompareExchange ) -#pragma intrinsic( _InterlockedDecrement ) -#pragma intrinsic( _InterlockedExchange ) -#pragma intrinsic( _InterlockedExchangeAdd ) -#pragma intrinsic( _InterlockedIncrement ) - -inline long ThreadInterlockedIncrement( long volatile *p ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedIncrement( p ); } -inline long ThreadInterlockedDecrement( long volatile *p ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedDecrement( p ); } -inline long ThreadInterlockedExchange( long volatile *p, long value ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedExchange( p, value ); } -inline long ThreadInterlockedExchangeAdd( long volatile *p, long value ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedExchangeAdd( p, value ); } -inline long ThreadInterlockedCompareExchange( long volatile *p, long value, long comperand ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedCompareExchange( p, value, comperand ); } -inline bool ThreadInterlockedAssignIf( long volatile *p, long value, long comperand ) { Assert( (size_t)p % 4 == 0 ); return ( _InterlockedCompareExchange( p, value, comperand ) == comperand ); } -#else -TT_INTERFACE long ThreadInterlockedIncrement( long volatile * ); -TT_INTERFACE long ThreadInterlockedDecrement( long volatile * ); -TT_INTERFACE long ThreadInterlockedExchange( long volatile *, long value ); -TT_INTERFACE long ThreadInterlockedExchangeAdd( long volatile *, long value ); -TT_INTERFACE long ThreadInterlockedCompareExchange( long volatile *, long value, long comperand ); -TT_INTERFACE bool ThreadInterlockedAssignIf( long volatile *, long value, long comperand ); -#endif - -inline unsigned ThreadInterlockedExchangeSubtract( long volatile *p, long value ) { return ThreadInterlockedExchangeAdd( (long volatile *)p, -value ); } - -#if defined( USE_INTRINSIC_INTERLOCKED ) && !defined( _WIN64 ) -#define TIPTR() -inline void *ThreadInterlockedExchangePointer( void * volatile *p, void *value ) { return (void *)_InterlockedExchange( reinterpret_cast(p), reinterpret_cast(value) ); } -inline void *ThreadInterlockedCompareExchangePointer( void * volatile *p, void *value, void *comperand ) { return (void *)_InterlockedCompareExchange( reinterpret_cast(p), reinterpret_cast(value), reinterpret_cast(comperand) ); } -inline bool ThreadInterlockedAssignPointerIf( void * volatile *p, void *value, void *comperand ) { return ( _InterlockedCompareExchange( reinterpret_cast(p), reinterpret_cast(value), reinterpret_cast(comperand) ) == reinterpret_cast(comperand) ); } -#else -TT_INTERFACE void *ThreadInterlockedExchangePointer( void * volatile *, void *value ); -TT_INTERFACE void *ThreadInterlockedCompareExchangePointer( void * volatile *, void *value, void *comperand ); -TT_INTERFACE bool ThreadInterlockedAssignPointerIf( void * volatile *, void *value, void *comperand ); -#endif - -inline void const *ThreadInterlockedExchangePointerToConst( void const * volatile *p, void const *value ) { return ThreadInterlockedExchangePointer( const_cast < void * volatile * > ( p ), const_cast < void * > ( value ) ); } -inline void const *ThreadInterlockedCompareExchangePointerToConst( void const * volatile *p, void const *value, void const *comperand ) { return ThreadInterlockedCompareExchangePointer( const_cast < void * volatile * > ( p ), const_cast < void * > ( value ), const_cast < void * > ( comperand ) ); } -inline bool ThreadInterlockedAssignPointerToConstIf( void const * volatile *p, void const *value, void const *comperand ) { return ThreadInterlockedAssignPointerIf( const_cast < void * volatile * > ( p ), const_cast < void * > ( value ), const_cast < void * > ( comperand ) ); } - -TT_INTERFACE int64 ThreadInterlockedIncrement64( int64 volatile * ); -TT_INTERFACE int64 ThreadInterlockedDecrement64( int64 volatile * ); -TT_INTERFACE int64 ThreadInterlockedCompareExchange64( int64 volatile *, int64 value, int64 comperand ); -TT_INTERFACE int64 ThreadInterlockedExchange64( int64 volatile *, int64 value ); -TT_INTERFACE int64 ThreadInterlockedExchangeAdd64( int64 volatile *, int64 value ); -TT_INTERFACE bool ThreadInterlockedAssignIf64(volatile int64 *pDest, int64 value, int64 comperand ); - -inline unsigned ThreadInterlockedExchangeSubtract( unsigned volatile *p, unsigned value ) { return ThreadInterlockedExchangeAdd( (long volatile *)p, value ); } -inline unsigned ThreadInterlockedIncrement( unsigned volatile *p ) { return ThreadInterlockedIncrement( (long volatile *)p ); } -inline unsigned ThreadInterlockedDecrement( unsigned volatile *p ) { return ThreadInterlockedDecrement( (long volatile *)p ); } -inline unsigned ThreadInterlockedExchange( unsigned volatile *p, unsigned value ) { return ThreadInterlockedExchange( (long volatile *)p, value ); } -inline unsigned ThreadInterlockedExchangeAdd( unsigned volatile *p, unsigned value ) { return ThreadInterlockedExchangeAdd( (long volatile *)p, value ); } -inline unsigned ThreadInterlockedCompareExchange( unsigned volatile *p, unsigned value, unsigned comperand ) { return ThreadInterlockedCompareExchange( (long volatile *)p, value, comperand ); } -inline bool ThreadInterlockedAssignIf( unsigned volatile *p, unsigned value, unsigned comperand ) { return ThreadInterlockedAssignIf( (long volatile *)p, value, comperand ); } - -inline int ThreadInterlockedExchangeSubtract( int volatile *p, int value ) { return ThreadInterlockedExchangeAdd( (long volatile *)p, value ); } -inline int ThreadInterlockedIncrement( int volatile *p ) { return ThreadInterlockedIncrement( (long volatile *)p ); } -inline int ThreadInterlockedDecrement( int volatile *p ) { return ThreadInterlockedDecrement( (long volatile *)p ); } -inline int ThreadInterlockedExchange( int volatile *p, int value ) { return ThreadInterlockedExchange( (long volatile *)p, value ); } -inline int ThreadInterlockedExchangeAdd( int volatile *p, int value ) { return ThreadInterlockedExchangeAdd( (long volatile *)p, value ); } -inline int ThreadInterlockedCompareExchange( int volatile *p, int value, int comperand ) { return ThreadInterlockedCompareExchange( (long volatile *)p, value, comperand ); } -inline bool ThreadInterlockedAssignIf( int volatile *p, int value, int comperand ) { return ThreadInterlockedAssignIf( (long volatile *)p, value, comperand ); } - -//----------------------------------------------------------------------------- -// Access to VTune thread profiling -//----------------------------------------------------------------------------- -#if defined(_WIN32) && defined(THREAD_PROFILER) -TT_INTERFACE void ThreadNotifySyncPrepare(void *p); -TT_INTERFACE void ThreadNotifySyncCancel(void *p); -TT_INTERFACE void ThreadNotifySyncAcquired(void *p); -TT_INTERFACE void ThreadNotifySyncReleasing(void *p); -#else -#define ThreadNotifySyncPrepare(p) ((void)0) -#define ThreadNotifySyncCancel(p) ((void)0) -#define ThreadNotifySyncAcquired(p) ((void)0) -#define ThreadNotifySyncReleasing(p) ((void)0) -#endif - -//----------------------------------------------------------------------------- -// Encapsulation of a thread local datum (needed because THREAD_LOCAL doesn't -// work in a DLL loaded with LoadLibrary() -//----------------------------------------------------------------------------- - -#ifndef __AFXTLS_H__ // not compatible with some Windows headers -#ifndef NO_THREAD_LOCAL - -class TT_CLASS CThreadLocalBase -{ -public: - CThreadLocalBase(); - ~CThreadLocalBase(); - - void * Get() const; - void Set(void *); - -private: -#ifdef _WIN32 - uint32 m_index; -#elif defined _LINUX || defined __APPLE__ - pthread_key_t m_index; -#endif -}; - -//--------------------------------------------------------- - -#ifndef __AFXTLS_H__ - -template -class CThreadLocal : public CThreadLocalBase -{ -public: - CThreadLocal() - { - COMPILE_TIME_ASSERT( sizeof(T) == sizeof(void *) ); - } - - T Get() const - { - return reinterpret_cast(CThreadLocalBase::Get()); - } - - void Set(T val) - { - CThreadLocalBase::Set(reinterpret_cast(val)); - } -}; - -#endif - -//--------------------------------------------------------- - -template -class CThreadLocalInt : public CThreadLocal -{ -public: - operator const T() const { return CThreadLocal::Get(); } - int operator=( T i ) { Set( i ); return i; } - - T operator++() { T i = CThreadLocal::Get(); Set( ++i ); return i; } - T operator++(int) { T i = CThreadLocal::Get(); Set( i + 1 ); return i; } - - T operator--() { T i = CThreadLocal::Get(); Set( --i ); return i; } - T operator--(int) { T i = CThreadLocal::Get(); Set( i - 1 ); return i; } -}; - -//--------------------------------------------------------- - -template -class CThreadLocalPtr : private CThreadLocalBase -{ -public: - CThreadLocalPtr() {} - - operator const void *() const { return (T *)Get(); } - operator void *() { return (T *)Get(); } - - operator const T *() const { return (T *)Get(); } - operator const T *() { return (T *)Get(); } - operator T *() { return (T *)Get(); } - - int operator=( int i ) { AssertMsg( i == 0, "Only NULL allowed on integer assign" ); Set( NULL ); return 0; } - T * operator=( T *p ) { Set( p ); return p; } - - bool operator !() const { return (!Get()); } - bool operator!=( int i ) const { AssertMsg( i == 0, "Only NULL allowed on integer compare" ); return (Get() != NULL); } - bool operator==( int i ) const { AssertMsg( i == 0, "Only NULL allowed on integer compare" ); return (Get() == NULL); } - bool operator==( const void *p ) const { return (Get() == p); } - bool operator!=( const void *p ) const { return (Get() != p); } - bool operator==( const T *p ) const { return operator==((void*)p); } - bool operator!=( const T *p ) const { return operator!=((void*)p); } - - T * operator->() { return (T *)Get(); } - T & operator *() { return *((T *)Get()); } - - const T * operator->() const { return (T *)Get(); } - const T & operator *() const { return *((T *)Get()); } - - const T & operator[]( int i ) const { return *((T *)Get() + i); } - T & operator[]( int i ) { return *((T *)Get() + i); } - -private: - // Disallowed operations - CThreadLocalPtr( T *pFrom ); - CThreadLocalPtr( const CThreadLocalPtr &from ); - T **operator &(); - T * const *operator &() const; - void operator=( const CThreadLocalPtr &from ); - bool operator==( const CThreadLocalPtr &p ) const; - bool operator!=( const CThreadLocalPtr &p ) const; -}; - -#endif // NO_THREAD_LOCAL -#endif // !__AFXTLS_H__ - -//----------------------------------------------------------------------------- -// -// A super-fast thread-safe integer A simple class encapsulating the notion of an -// atomic integer used across threads that uses the built in and faster -// "interlocked" functionality rather than a full-blown mutex. Useful for simple -// things like reference counts, etc. -// -//----------------------------------------------------------------------------- - -template -class CInterlockedIntT -{ -public: - CInterlockedIntT() : m_value( 0 ) { COMPILE_TIME_ASSERT( sizeof(T) == sizeof(long) ); } - CInterlockedIntT( T value ) : m_value( value ) {} - - operator T() const { return m_value; } - - bool operator!() const { return ( m_value == 0 ); } - bool operator==( T rhs ) const { return ( m_value == rhs ); } - bool operator!=( T rhs ) const { return ( m_value != rhs ); } - - T operator++() { return (T)ThreadInterlockedIncrement( (long *)&m_value ); } - T operator++(int) { return operator++() - 1; } - - T operator--() { return (T)ThreadInterlockedDecrement( (long *)&m_value ); } - T operator--(int) { return operator--() + 1; } - - bool AssignIf( T conditionValue, T newValue ) { return ThreadInterlockedAssignIf( (long *)&m_value, (long)newValue, (long)conditionValue ); } - - T operator=( T newValue ) { ThreadInterlockedExchange((long *)&m_value, newValue); return m_value; } - - void operator+=( T add ) { ThreadInterlockedExchangeAdd( (long *)&m_value, (long)add ); } - void operator-=( T subtract ) { operator+=( -subtract ); } - void operator*=( T multiplier ) { - T original, result; - do - { - original = m_value; - result = original * multiplier; - } while ( !AssignIf( original, result ) ); - } - void operator/=( T divisor ) { - T original, result; - do - { - original = m_value; - result = original / divisor; - } while ( !AssignIf( original, result ) ); - } - - T operator+( T rhs ) const { return m_value + rhs; } - T operator-( T rhs ) const { return m_value - rhs; } - -private: - volatile T m_value; -}; - -typedef CInterlockedIntT CInterlockedInt; -typedef CInterlockedIntT CInterlockedUInt; - -//----------------------------------------------------------------------------- - -template -class CInterlockedPtr -{ -public: - CInterlockedPtr() : m_value( 0 ) { COMPILE_TIME_ASSERT( sizeof(T *) == sizeof(long) ); /* Will need to rework operator+= for 64 bit */ } - CInterlockedPtr( T *value ) : m_value( value ) {} - - operator T *() const { return m_value; } - - bool operator!() const { return ( m_value == 0 ); } - bool operator==( T *rhs ) const { return ( m_value == rhs ); } - bool operator!=( T *rhs ) const { return ( m_value != rhs ); } - - T *operator++() { return ((T *)ThreadInterlockedExchangeAdd( (long *)&m_value, sizeof(T) )) + 1; } - T *operator++(int) { return (T *)ThreadInterlockedExchangeAdd( (long *)&m_value, sizeof(T) ); } - - T *operator--() { return ((T *)ThreadInterlockedExchangeAdd( (long *)&m_value, -sizeof(T) )) - 1; } - T *operator--(int) { return (T *)ThreadInterlockedExchangeAdd( (long *)&m_value, -sizeof(T) ); } - - bool AssignIf( T *conditionValue, T *newValue ) { return ThreadInterlockedAssignPointerToConstIf( (void const **) &m_value, (void const *) newValue, (void const *) conditionValue ); } - - T *operator=( T *newValue ) { ThreadInterlockedExchangePointerToConst( (void const **) &m_value, (void const *) newValue ); return newValue; } - - void operator+=( int add ) { ThreadInterlockedExchangeAdd( (long *)&m_value, add * sizeof(T) ); } - void operator-=( int subtract ) { operator+=( -subtract ); } - - T *operator+( int rhs ) const { return m_value + rhs; } - T *operator-( int rhs ) const { return m_value - rhs; } - T *operator+( unsigned rhs ) const { return m_value + rhs; } - T *operator-( unsigned rhs ) const { return m_value - rhs; } - size_t operator-( T *p ) const { return m_value - p; } - size_t operator-( const CInterlockedPtr &p ) const { return m_value - p.m_value; } - -private: - T * volatile m_value; -}; - - -//----------------------------------------------------------------------------- -// -// Platform independent for critical sections management -// -//----------------------------------------------------------------------------- - -class TT_CLASS CThreadMutex -{ -public: - CThreadMutex(); - ~CThreadMutex(); - - //------------------------------------------------------ - // Mutex acquisition/release. Const intentionally defeated. - //------------------------------------------------------ - void Lock(); - void Lock() const { (const_cast(this))->Lock(); } - void Unlock(); - void Unlock() const { (const_cast(this))->Unlock(); } - - bool TryLock(); - bool TryLock() const { return (const_cast(this))->TryLock(); } - - //------------------------------------------------------ - // Use this to make deadlocks easier to track by asserting - // when it is expected that the current thread owns the mutex - //------------------------------------------------------ - bool AssertOwnedByCurrentThread(); - - //------------------------------------------------------ - // Enable tracing to track deadlock problems - //------------------------------------------------------ - void SetTrace( bool ); - -private: - // Disallow copying - CThreadMutex( const CThreadMutex & ); - CThreadMutex &operator=( const CThreadMutex & ); - -#if defined( _WIN32 ) - // Efficient solution to breaking the windows.h dependency, invariant is tested. -#ifdef _WIN64 - #define TT_SIZEOF_CRITICALSECTION 40 -#else -#ifndef _X360 - #define TT_SIZEOF_CRITICALSECTION 24 -#else - #define TT_SIZEOF_CRITICALSECTION 28 -#endif // !_XBOX -#endif // _WIN64 - byte m_CriticalSection[TT_SIZEOF_CRITICALSECTION]; -#elif defined _LINUX || defined __APPLE__ - pthread_mutex_t m_Mutex; - pthread_mutexattr_t m_Attr; -#else -#error -#endif - -#ifdef THREAD_MUTEX_TRACING_SUPPORTED - // Debugging (always here to allow mixed debug/release builds w/o changing size) - uint m_currentOwnerID; - uint16 m_lockCount; - bool m_bTrace; -#endif -}; - -//----------------------------------------------------------------------------- -// -// An alternative mutex that is useful for cases when thread contention is -// rare, but a mutex is required. Instances should be declared volatile. -// Sleep of 0 may not be sufficient to keep high priority threads from starving -// lesser threads. This class is not a suitable replacement for a critical -// section if the resource contention is high. -// -//----------------------------------------------------------------------------- - -#if defined(_WIN32) && !defined(THREAD_PROFILER) - -class CThreadFastMutex -{ -public: - CThreadFastMutex() - : m_ownerID( 0 ), - m_depth( 0 ) - { - } - -private: - FORCEINLINE bool TryLockInline( const uint32 threadId ) volatile - { - if ( threadId != m_ownerID && !ThreadInterlockedAssignIf( (volatile long *)&m_ownerID, (long)threadId, 0 ) ) - return false; - - ++m_depth; - return true; - } - - bool TryLock( const uint32 threadId ) volatile - { - return TryLockInline( threadId ); - } - - TT_CLASS void Lock( const uint32 threadId, unsigned nSpinSleepTime ) volatile; - -public: - bool TryLock() volatile - { -#ifdef _DEBUG - if ( m_depth == INT_MAX ) - DebuggerBreak(); - - if ( m_depth < 0 ) - DebuggerBreak(); -#endif - return TryLockInline( ThreadGetCurrentId() ); - } - -#ifndef _DEBUG - FORCEINLINE -#endif - void Lock( unsigned nSpinSleepTime = 0 ) volatile - { - const uint32 threadId = ThreadGetCurrentId(); - - if ( !TryLockInline( threadId ) ) - { - ThreadPause(); - Lock( threadId, nSpinSleepTime ); - } -#ifdef _DEBUG - if ( m_ownerID != ThreadGetCurrentId() ) - DebuggerBreak(); - - if ( m_depth == INT_MAX ) - DebuggerBreak(); - - if ( m_depth < 0 ) - DebuggerBreak(); -#endif - } - -#ifndef _DEBUG - FORCEINLINE -#endif - void Unlock() volatile - { -#ifdef _DEBUG - if ( m_ownerID != ThreadGetCurrentId() ) - DebuggerBreak(); - - if ( m_depth <= 0 ) - DebuggerBreak(); -#endif - - --m_depth; - if ( !m_depth ) - ThreadInterlockedExchange( &m_ownerID, 0 ); - } - - bool TryLock() const volatile { return (const_cast(this))->TryLock(); } - void Lock(unsigned nSpinSleepTime = 1 ) const volatile { (const_cast(this))->Lock( nSpinSleepTime ); } - void Unlock() const volatile { (const_cast(this))->Unlock(); } - - // To match regular CThreadMutex: - bool AssertOwnedByCurrentThread() { return true; } - void SetTrace( bool ) {} - - uint32 GetOwnerId() const { return m_ownerID; } - int GetDepth() const { return m_depth; } -private: - volatile uint32 m_ownerID; - int m_depth; -}; - -class ALIGN128 CAlignedThreadFastMutex : public CThreadFastMutex -{ -public: - CAlignedThreadFastMutex() - { - Assert( (size_t)this % 128 == 0 && sizeof(*this) == 128 ); - } - -private: - uint8 pad[128-sizeof(CThreadFastMutex)]; -}; - -#else -typedef CThreadMutex CThreadFastMutex; -#endif - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- - -class CThreadNullMutex -{ -public: - static void Lock() {} - static void Unlock() {} - - static bool TryLock() { return true; } - static bool AssertOwnedByCurrentThread() { return true; } - static void SetTrace( bool b ) {} - - static uint32 GetOwnerId() { return 0; } - static int GetDepth() { return 0; } -}; - -//----------------------------------------------------------------------------- -// -// A mutex decorator class used to control the use of a mutex, to make it -// less expensive when not multithreading -// -//----------------------------------------------------------------------------- - -template -class CThreadConditionalMutex : public BaseClass -{ -public: - void Lock() { if ( *pCondition ) BaseClass::Lock(); } - void Lock() const { if ( *pCondition ) BaseClass::Lock(); } - void Unlock() { if ( *pCondition ) BaseClass::Unlock(); } - void Unlock() const { if ( *pCondition ) BaseClass::Unlock(); } - - bool TryLock() { if ( *pCondition ) return BaseClass::TryLock(); else return true; } - bool TryLock() const { if ( *pCondition ) return BaseClass::TryLock(); else return true; } - bool AssertOwnedByCurrentThread() { if ( *pCondition ) return BaseClass::AssertOwnedByCurrentThread(); else return true; } - void SetTrace( bool b ) { if ( *pCondition ) BaseClass::SetTrace( b ); } -}; - -//----------------------------------------------------------------------------- -// Mutex decorator that blows up if another thread enters -//----------------------------------------------------------------------------- - -template -class CThreadTerminalMutex : public BaseClass -{ -public: - bool TryLock() { if ( !BaseClass::TryLock() ) { DebuggerBreak(); return false; } return true; } - bool TryLock() const { if ( !BaseClass::TryLock() ) { DebuggerBreak(); return false; } return true; } - void Lock() { if ( !TryLock() ) BaseClass::Lock(); } - void Lock() const { if ( !TryLock() ) BaseClass::Lock(); } - -}; - -//----------------------------------------------------------------------------- -// -// Class to Lock a critical section, and unlock it automatically -// when the lock goes out of scope -// -//----------------------------------------------------------------------------- - -template -class CAutoLockT -{ -public: - FORCEINLINE CAutoLockT( MUTEX_TYPE &lock) - : m_lock(lock) - { - m_lock.Lock(); - } - - FORCEINLINE CAutoLockT(const MUTEX_TYPE &lock) - : m_lock(const_cast(lock)) - { - m_lock.Lock(); - } - - FORCEINLINE ~CAutoLockT() - { - m_lock.Unlock(); - } - - -private: - MUTEX_TYPE &m_lock; - - // Disallow copying - CAutoLockT( const CAutoLockT & ); - CAutoLockT &operator=( const CAutoLockT & ); -}; - -typedef CAutoLockT CAutoLock; - -//--------------------------------------------------------- - -template struct CAutoLockTypeDeducer {}; -template <> struct CAutoLockTypeDeducer { typedef CThreadMutex Type_t; }; -template <> struct CAutoLockTypeDeducer { typedef CThreadNullMutex Type_t; }; -#if defined(_WIN32) && !defined(THREAD_PROFILER) -template <> struct CAutoLockTypeDeducer { typedef CThreadFastMutex Type_t; }; -template <> struct CAutoLockTypeDeducer { typedef CAlignedThreadFastMutex Type_t; }; -#endif - -#define AUTO_LOCK_( type, mutex ) \ - CAutoLockT< type > UNIQUE_ID( static_cast( mutex ) ) - -#define AUTO_LOCK( mutex ) \ - AUTO_LOCK_( CAutoLockTypeDeducer::Type_t, mutex ) - - -#define AUTO_LOCK_FM( mutex ) \ - AUTO_LOCK_( CThreadFastMutex, mutex ) - -#define LOCAL_THREAD_LOCK_( tag ) \ - ; \ - static CThreadFastMutex autoMutex_##tag; \ - AUTO_LOCK( autoMutex_##tag ) - -#define LOCAL_THREAD_LOCK() \ - LOCAL_THREAD_LOCK_(_) - -//----------------------------------------------------------------------------- -// -// Base class for event, semaphore and mutex objects. -// -//----------------------------------------------------------------------------- - -class TT_CLASS CThreadSyncObject -{ -public: - ~CThreadSyncObject(); - - //----------------------------------------------------- - // Query if object is useful - //----------------------------------------------------- - bool operator!() const; - - //----------------------------------------------------- - // Access handle - //----------------------------------------------------- -#ifdef _WIN32 - operator HANDLE() { return m_hSyncObject; } -#endif - //----------------------------------------------------- - // Wait for a signal from the object - //----------------------------------------------------- - bool Wait( uint32 dwTimeout = TT_INFINITE ); - -protected: - CThreadSyncObject(); - void AssertUseable(); - -#ifdef _WIN32 - HANDLE m_hSyncObject; -#elif defined _LINUX || defined __APPLE__ - pthread_mutex_t m_Mutex; - pthread_cond_t m_Condition; - bool m_bInitalized; - int m_cSet; - bool m_bManualReset; -#else -#error "Implement me" -#endif - -private: - CThreadSyncObject( const CThreadSyncObject & ); - CThreadSyncObject &operator=( const CThreadSyncObject & ); -}; - - -//----------------------------------------------------------------------------- -// -// Wrapper for unnamed event objects -// -//----------------------------------------------------------------------------- - -#if defined( _WIN32 ) - -//----------------------------------------------------------------------------- -// -// CThreadSemaphore -// -//----------------------------------------------------------------------------- - -class TT_CLASS CThreadSemaphore : public CThreadSyncObject -{ -public: - CThreadSemaphore(long initialValue, long maxValue); - - //----------------------------------------------------- - // Increases the count of the semaphore object by a specified - // amount. Wait() decreases the count by one on return. - //----------------------------------------------------- - bool Release(long releaseCount = 1, long * pPreviousCount = NULL ); - -private: - CThreadSemaphore(const CThreadSemaphore &); - CThreadSemaphore &operator=(const CThreadSemaphore &); -}; - - -//----------------------------------------------------------------------------- -// -// A mutex suitable for out-of-process, multi-processor usage -// -//----------------------------------------------------------------------------- - -class TT_CLASS CThreadFullMutex : public CThreadSyncObject -{ -public: - CThreadFullMutex( bool bEstablishInitialOwnership = false, const char * pszName = NULL ); - - //----------------------------------------------------- - // Release ownership of the mutex - //----------------------------------------------------- - bool Release(); - - // To match regular CThreadMutex: - void Lock() { Wait(); } - void Lock( unsigned timeout ) { Wait( timeout ); } - void Unlock() { Release(); } - bool AssertOwnedByCurrentThread() { return true; } - void SetTrace( bool ) {} - -private: - CThreadFullMutex( const CThreadFullMutex & ); - CThreadFullMutex &operator=( const CThreadFullMutex & ); -}; -#endif - - -class TT_CLASS CThreadEvent : public CThreadSyncObject -{ -public: - CThreadEvent( bool fManualReset = false ); - - //----------------------------------------------------- - // Set the state to signaled - //----------------------------------------------------- - bool Set(); - - //----------------------------------------------------- - // Set the state to nonsignaled - //----------------------------------------------------- - bool Reset(); - - //----------------------------------------------------- - // Check if the event is signaled - //----------------------------------------------------- - bool Check(); - - bool Wait( uint32 dwTimeout = TT_INFINITE ); - -private: - CThreadEvent( const CThreadEvent & ); - CThreadEvent &operator=( const CThreadEvent & ); -#if defined _LINUX || defined __APPLE__ - CInterlockedInt m_cSet; -#endif -}; - -// Hard-wired manual event for use in array declarations -class CThreadManualEvent : public CThreadEvent -{ -public: - CThreadManualEvent() - : CThreadEvent( true ) - { - } -}; - -inline int ThreadWaitForEvents( int nEvents, const CThreadEvent *pEvents, bool bWaitAll = true, unsigned timeout = TT_INFINITE ) -{ -#if defined _LINUX || defined __APPLE__ - Assert(0); - return 0; -#else - return ThreadWaitForObjects( nEvents, (const HANDLE *)pEvents, bWaitAll, timeout ); -#endif -} - -//----------------------------------------------------------------------------- -// -// CThreadRWLock -// -//----------------------------------------------------------------------------- - -class TT_CLASS CThreadRWLock -{ -public: - CThreadRWLock(); - - void LockForRead(); - void UnlockRead(); - void LockForWrite(); - void UnlockWrite(); - - void LockForRead() const { const_cast(this)->LockForRead(); } - void UnlockRead() const { const_cast(this)->UnlockRead(); } - void LockForWrite() const { const_cast(this)->LockForWrite(); } - void UnlockWrite() const { const_cast(this)->UnlockWrite(); } - -private: - void WaitForRead(); - - CThreadFastMutex m_mutex; - CThreadEvent m_CanWrite; - CThreadEvent m_CanRead; - - int m_nWriters; - int m_nActiveReaders; - int m_nPendingReaders; -}; - -//----------------------------------------------------------------------------- -// -// CThreadSpinRWLock -// -//----------------------------------------------------------------------------- - -#define TFRWL_ALIGN ALIGN8 - -class TFRWL_ALIGN TT_CLASS CThreadSpinRWLock -{ -public: - CThreadSpinRWLock() { COMPILE_TIME_ASSERT( sizeof( LockInfo_t ) == sizeof( int64 ) ); Assert( (int)this % 8 == 0 ); memset( this, 0, sizeof( *this ) ); } - - bool TryLockForWrite(); - bool TryLockForRead(); - - void LockForRead(); - void UnlockRead(); - void LockForWrite(); - void UnlockWrite(); - - bool TryLockForWrite() const { return const_cast(this)->TryLockForWrite(); } - bool TryLockForRead() const { return const_cast(this)->TryLockForRead(); } - void LockForRead() const { const_cast(this)->LockForRead(); } - void UnlockRead() const { const_cast(this)->UnlockRead(); } - void LockForWrite() const { const_cast(this)->LockForWrite(); } - void UnlockWrite() const { const_cast(this)->UnlockWrite(); } - -private: - struct LockInfo_t - { - uint32 m_writerId; - int m_nReaders; - }; - - bool AssignIf( const LockInfo_t &newValue, const LockInfo_t &comperand ); - bool TryLockForWrite( const uint32 threadId ); - void SpinLockForWrite( const uint32 threadId ); - - volatile LockInfo_t m_lockInfo; - CInterlockedInt m_nWriters; -}; - -//----------------------------------------------------------------------------- -// -// A thread wrapper similar to a Java thread. -// -//----------------------------------------------------------------------------- - -class TT_CLASS CThread -{ -public: - CThread(); - virtual ~CThread(); - - //----------------------------------------------------- - - const char *GetName(); - void SetName( const char * ); - - size_t CalcStackDepth( void *pStackVariable ) { return ((byte *)m_pStackBase - (byte *)pStackVariable); } - - //----------------------------------------------------- - // Functions for the other threads - //----------------------------------------------------- - - // Start thread running - error if already running - virtual bool Start( unsigned nBytesStack = 0 ); - - // Returns true if thread has been created and hasn't yet exited - bool IsAlive(); - - // This method causes the current thread to wait until this thread - // is no longer alive. - bool Join( unsigned timeout = TT_INFINITE ); - -#ifdef _WIN32 - // Access the thread handle directly - HANDLE GetThreadHandle(); - uint GetThreadId(); -#endif - - //----------------------------------------------------- - - int GetResult(); - - //----------------------------------------------------- - // Functions for both this, and maybe, and other threads - //----------------------------------------------------- - - // Forcibly, abnormally, but relatively cleanly stop the thread - void Stop( int exitCode = 0 ); - - // Get the priority - int GetPriority() const; - - // Set the priority - bool SetPriority( int ); - - // Suspend a thread - unsigned Suspend(); - - // Resume a suspended thread - unsigned Resume(); - - // Force hard-termination of thread. Used for critical failures. - bool Terminate( int exitCode = 0 ); - - //----------------------------------------------------- - // Global methods - //----------------------------------------------------- - - // Get the Thread object that represents the current thread, if any. - // Can return NULL if the current thread was not created using - // CThread - static CThread *GetCurrentCThread(); - - // Offer a context switch. Under Win32, equivalent to Sleep(0) -#ifdef Yield -#undef Yield -#endif - static void Yield(); - - // This method causes the current thread to yield and not to be - // scheduled for further execution until a certain amount of real - // time has elapsed, more or less. - static void Sleep( unsigned duration ); - -protected: - - // Optional pre-run call, with ability to fail-create. Note Init() - // is forced synchronous with Start() - virtual bool Init(); - - // Thread will run this function on startup, must be supplied by - // derived class, performs the intended action of the thread. - virtual int Run() = 0; - - // Called when the thread exits - virtual void OnExit(); - -#ifdef _WIN32 - // Allow for custom start waiting - virtual bool WaitForCreateComplete( CThreadEvent *pEvent ); -#endif - - // "Virtual static" facility - typedef unsigned (__stdcall *ThreadProc_t)( void * ); - virtual ThreadProc_t GetThreadProc(); - - CThreadMutex m_Lock; - -private: - enum Flags - { - SUPPORT_STOP_PROTOCOL = 1 << 0 - }; - - // Thread initially runs this. param is actually 'this'. function - // just gets this and calls ThreadProc - struct ThreadInit_t - { - CThread * pThread; -#ifdef _WIN32 - CThreadEvent *pInitCompleteEvent; -#endif - bool * pfInitSuccess; - }; - - static unsigned __stdcall ThreadProc( void * pv ); - - // make copy constructor and assignment operator inaccessible - CThread( const CThread & ); - CThread &operator=( const CThread & ); - -#ifdef _WIN32 - HANDLE m_hThread; - ThreadId_t m_threadId; -#elif defined _LINUX || defined __APPLE__ - pthread_t m_threadId; -#endif - int m_result; - char m_szName[32]; - void * m_pStackBase; - unsigned m_flags; -}; - -//----------------------------------------------------------------------------- -// Simple thread class encompasses the notion of a worker thread, handing -// synchronized communication. -//----------------------------------------------------------------------------- - -#ifdef _WIN32 - -// These are internal reserved error results from a call attempt -enum WTCallResult_t -{ - WTCR_FAIL = -1, - WTCR_TIMEOUT = -2, - WTCR_THREAD_GONE = -3, -}; - -class TT_CLASS CWorkerThread : public CThread -{ -public: - CWorkerThread(); - - //----------------------------------------------------- - // - // Inter-thread communication - // - // Calls in either direction take place on the same "channel." - // Seperate functions are specified to make identities obvious - // - //----------------------------------------------------- - - // Master: Signal the thread, and block for a response - int CallWorker( unsigned, unsigned timeout = TT_INFINITE, bool fBoostWorkerPriorityToMaster = true ); - - // Worker: Signal the thread, and block for a response - int CallMaster( unsigned, unsigned timeout = TT_INFINITE ); - - // Wait for the next request - bool WaitForCall( unsigned dwTimeout, unsigned *pResult = NULL ); - bool WaitForCall( unsigned *pResult = NULL ); - - // Is there a request? - bool PeekCall( unsigned *pParam = NULL ); - - // Reply to the request - void Reply( unsigned ); - - // Wait for a reply in the case when CallWorker() with timeout != TT_INFINITE - int WaitForReply( unsigned timeout = TT_INFINITE ); - - // If you want to do WaitForMultipleObjects you'll need to include - // this handle in your wait list or you won't be responsive - HANDLE GetCallHandle(); - - // Find out what the request was - unsigned GetCallParam() const; - - // Boost the worker thread to the master thread, if worker thread is lesser, return old priority - int BoostPriority(); - -protected: - typedef uint32 (__stdcall *WaitFunc_t)( uint32 nHandles, const HANDLE*pHandles, int bWaitAll, uint32 timeout ); - int Call( unsigned, unsigned timeout, bool fBoost, WaitFunc_t = NULL ); - int WaitForReply( unsigned timeout, WaitFunc_t ); - -private: - CWorkerThread( const CWorkerThread & ); - CWorkerThread &operator=( const CWorkerThread & ); - -#ifdef _WIN32 - CThreadEvent m_EventSend; - CThreadEvent m_EventComplete; -#endif - - unsigned m_Param; - int m_ReturnVal; -}; - -#else - -typedef CThread CWorkerThread; - -#endif - -// a unidirectional message queue. A queue of type T. Not especially high speed since each message -// is malloced/freed. Note that if your message class has destructors/constructors, they MUST be -// thread safe! -template class CMessageQueue -{ - CThreadEvent SignalEvent; // signals presence of data - CThreadMutex QueueAccessMutex; - - // the parts protected by the mutex - struct MsgNode - { - MsgNode *Next; - T Data; - }; - - MsgNode *Head; - MsgNode *Tail; - -public: - CMessageQueue( void ) - { - Head = Tail = NULL; - } - - // check for a message. not 100% reliable - someone could grab the message first - bool MessageWaiting( void ) - { - return ( Head != NULL ); - } - - void WaitMessage( T *pMsg ) - { - for(;;) - { - while( ! MessageWaiting() ) - SignalEvent.Wait(); - QueueAccessMutex.Lock(); - if (! Head ) - { - // multiple readers could make this null - QueueAccessMutex.Unlock(); - continue; - } - *( pMsg ) = Head->Data; - MsgNode *remove_this = Head; - Head = Head->Next; - if (! Head) // if empty, fix tail ptr - Tail = NULL; - QueueAccessMutex.Unlock(); - delete remove_this; - break; - } - } - - void QueueMessage( T const &Msg) - { - MsgNode *new1=new MsgNode; - new1->Data=Msg; - new1->Next=NULL; - QueueAccessMutex.Lock(); - if ( Tail ) - { - Tail->Next=new1; - Tail = new1; - } - else - { - Head = new1; - Tail = new1; - } - SignalEvent.Set(); - QueueAccessMutex.Unlock(); - } -}; - - -//----------------------------------------------------------------------------- -// -// CThreadMutex. Inlining to reduce overhead and to allow client code -// to decide debug status (tracing) -// -//----------------------------------------------------------------------------- - -#ifdef _WIN32 -typedef struct _RTL_CRITICAL_SECTION RTL_CRITICAL_SECTION; -typedef RTL_CRITICAL_SECTION CRITICAL_SECTION; - -#ifndef _X360 -extern "C" -{ - void __declspec(dllimport) __stdcall InitializeCriticalSection(CRITICAL_SECTION *); - void __declspec(dllimport) __stdcall EnterCriticalSection(CRITICAL_SECTION *); - void __declspec(dllimport) __stdcall LeaveCriticalSection(CRITICAL_SECTION *); - void __declspec(dllimport) __stdcall DeleteCriticalSection(CRITICAL_SECTION *); -}; -#endif - -//--------------------------------------------------------- - -inline void CThreadMutex::Lock() -{ -#ifdef THREAD_MUTEX_TRACING_ENABLED - uint thisThreadID = ThreadGetCurrentId(); - if ( m_bTrace && m_currentOwnerID && ( m_currentOwnerID != thisThreadID ) ) - Msg( "Thread %u about to wait for lock %x owned by %u\n", ThreadGetCurrentId(), (CRITICAL_SECTION *)&m_CriticalSection, m_currentOwnerID ); -#endif - - VCRHook_EnterCriticalSection((CRITICAL_SECTION *)&m_CriticalSection); - -#ifdef THREAD_MUTEX_TRACING_ENABLED - if (m_lockCount == 0) - { - // we now own it for the first time. Set owner information - m_currentOwnerID = thisThreadID; - if ( m_bTrace ) - Msg( "Thread %u now owns lock 0x%x\n", m_currentOwnerID, (CRITICAL_SECTION *)&m_CriticalSection ); - } - m_lockCount++; -#endif -} - -//--------------------------------------------------------- - -inline void CThreadMutex::Unlock() -{ -#ifdef THREAD_MUTEX_TRACING_ENABLED - AssertMsg( m_lockCount >= 1, "Invalid unlock of thread lock" ); - m_lockCount--; - if (m_lockCount == 0) - { - if ( m_bTrace ) - Msg( "Thread %u releasing lock 0x%x\n", m_currentOwnerID, (CRITICAL_SECTION *)&m_CriticalSection ); - m_currentOwnerID = 0; - } -#endif - LeaveCriticalSection((CRITICAL_SECTION *)&m_CriticalSection); -} - -//--------------------------------------------------------- - -inline bool CThreadMutex::AssertOwnedByCurrentThread() -{ -#ifdef THREAD_MUTEX_TRACING_ENABLED - if (ThreadGetCurrentId() == m_currentOwnerID) - return true; - AssertMsg3( 0, "Expected thread %u as owner of lock 0x%x, but %u owns", ThreadGetCurrentId(), (CRITICAL_SECTION *)&m_CriticalSection, m_currentOwnerID ); - return false; -#else - return true; -#endif -} - -//--------------------------------------------------------- - -inline void CThreadMutex::SetTrace( bool bTrace ) -{ -#ifdef THREAD_MUTEX_TRACING_ENABLED - m_bTrace = bTrace; -#endif -} - -//--------------------------------------------------------- - -#elif defined _LINUX || defined __APPLE__ - -inline CThreadMutex::CThreadMutex() -{ - // enable recursive locks as we need them - pthread_mutexattr_init( &m_Attr ); -#if defined __APPLE__ -# define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE -#endif - pthread_mutexattr_settype( &m_Attr, PTHREAD_MUTEX_RECURSIVE_NP ); - pthread_mutex_init( &m_Mutex, &m_Attr ); -} - -//--------------------------------------------------------- - -inline CThreadMutex::~CThreadMutex() -{ - pthread_mutex_destroy( &m_Mutex ); -} - -//--------------------------------------------------------- - -inline void CThreadMutex::Lock() -{ - pthread_mutex_lock( &m_Mutex ); -} - -//--------------------------------------------------------- - -inline void CThreadMutex::Unlock() -{ - pthread_mutex_unlock( &m_Mutex ); -} - -//--------------------------------------------------------- - -inline bool CThreadMutex::AssertOwnedByCurrentThread() -{ - return true; -} - -//--------------------------------------------------------- - -inline void CThreadMutex::SetTrace(bool fTrace) -{ -} - -#endif // defined _LINUX || defined __APPLE__ - -//----------------------------------------------------------------------------- -// -// CThreadRWLock inline functions -// -//----------------------------------------------------------------------------- - -inline CThreadRWLock::CThreadRWLock() -: m_CanRead( true ), - m_nWriters( 0 ), - m_nActiveReaders( 0 ), - m_nPendingReaders( 0 ) -{ -} - -inline void CThreadRWLock::LockForRead() -{ - m_mutex.Lock(); - if ( m_nWriters) - { - WaitForRead(); - } - m_nActiveReaders++; - m_mutex.Unlock(); -} - -inline void CThreadRWLock::UnlockRead() -{ - m_mutex.Lock(); - m_nActiveReaders--; - if ( m_nActiveReaders == 0 && m_nWriters != 0 ) - { - m_CanWrite.Set(); - } - m_mutex.Unlock(); -} - - -//----------------------------------------------------------------------------- -// -// CThreadSpinRWLock inline functions -// -//----------------------------------------------------------------------------- - -inline bool CThreadSpinRWLock::AssignIf( const LockInfo_t &newValue, const LockInfo_t &comperand ) -{ - return ThreadInterlockedAssignIf64( (int64 *)&m_lockInfo, *((int64 *)&newValue), *((int64 *)&comperand) ); -} - -inline bool CThreadSpinRWLock::TryLockForWrite( const uint32 threadId ) -{ - // In order to grab a write lock, there can be no readers and no owners of the write lock - if ( m_lockInfo.m_nReaders > 0 || ( m_lockInfo.m_writerId && m_lockInfo.m_writerId != threadId ) ) - { - return false; - } - - static const LockInfo_t oldValue = { 0, 0 }; - LockInfo_t newValue = { threadId, 0 }; - const bool bSuccess = AssignIf( newValue, oldValue ); -#if defined(_X360) - if ( bSuccess ) - { - // X360TBD: Serious perf implications. Not Yet. __sync(); - } -#endif - return bSuccess; -} - -inline bool CThreadSpinRWLock::TryLockForWrite() -{ - m_nWriters++; - if ( !TryLockForWrite( ThreadGetCurrentId() ) ) - { - m_nWriters--; - return false; - } - return true; -} - -inline bool CThreadSpinRWLock::TryLockForRead() -{ - if ( m_nWriters != 0 ) - { - return false; - } - // In order to grab a write lock, the number of readers must not change and no thread can own the write - LockInfo_t oldValue; - LockInfo_t newValue; - - oldValue.m_nReaders = m_lockInfo.m_nReaders; - oldValue.m_writerId = 0; - newValue.m_nReaders = oldValue.m_nReaders + 1; - newValue.m_writerId = 0; - - const bool bSuccess = AssignIf( newValue, oldValue ); -#if defined(_X360) - if ( bSuccess ) - { - // X360TBD: Serious perf implications. Not Yet. __sync(); - } -#endif - return bSuccess; -} - -inline void CThreadSpinRWLock::LockForWrite() -{ - const uint32 threadId = ThreadGetCurrentId(); - - m_nWriters++; - - if ( !TryLockForWrite( threadId ) ) - { - ThreadPause(); - SpinLockForWrite( threadId ); - } -} - -//----------------------------------------------------------------------------- - -#if defined( _WIN32 ) -#pragma warning(pop) -#endif - -#endif // THREADTOOLS_H diff --git a/public/tier0/tslist.h b/public/tier0/tslist.h deleted file mode 100644 index 4b67ea330..000000000 --- a/public/tier0/tslist.h +++ /dev/null @@ -1,794 +0,0 @@ -//========== Copyright 2005, Valve Corporation, All rights reserved. ======== -// -// Purpose: -// -// LIFO from disassembly of Windows API and http://perso.wanadoo.fr/gmem/evenements/jim2002/articles/L17_Fober.pdf -// FIFO from http://perso.wanadoo.fr/gmem/evenements/jim2002/articles/L17_Fober.pdf -// -//============================================================================= - -#ifndef TSLIST_H -#define TSLIST_H - -#if defined( _WIN32 ) -#pragma once -#endif - -#if ( defined(_WIN64) || defined(_X360) ) -#define USE_NATIVE_SLIST -#endif - -#if defined( USE_NATIVE_SLIST ) && !defined( _X360 ) -#define WIN32_LEAN_AND_MEAN -#include -#endif - -#include "tier0/dbg.h" -#include "tier0/threadtools.h" - -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- - -#if defined(_WIN64) -#define TSLIST_HEAD_ALIGNMENT MEMORY_ALLOCATION_ALIGNMENT -#define TSLIST_NODE_ALIGNMENT MEMORY_ALLOCATION_ALIGNMENT -#else -#define TSLIST_HEAD_ALIGNMENT 8 -#define TSLIST_NODE_ALIGNMENT 8 -#endif - -#define TSLIST_HEAD_ALIGN DECL_ALIGN(TSLIST_HEAD_ALIGNMENT) -#define TSLIST_NODE_ALIGN DECL_ALIGN(TSLIST_NODE_ALIGNMENT) - -//----------------------------------------------------------------------------- - -PLATFORM_INTERFACE bool RunTSQueueTests( int nListSize = 10000, int nTests = 1 ); -PLATFORM_INTERFACE bool RunTSListTests( int nListSize = 10000, int nTests = 1 ); - -//----------------------------------------------------------------------------- -// Lock free list. -//----------------------------------------------------------------------------- -//#define USE_NATIVE_SLIST - -#ifdef USE_NATIVE_SLIST -typedef SLIST_ENTRY TSLNodeBase_t; -typedef SLIST_HEADER TSLHead_t; -#else -struct TSLIST_NODE_ALIGN TSLNodeBase_t -{ - TSLNodeBase_t *Next; // name to match Windows -}; - -union TSLHead_t -{ - struct Value_t - { - TSLNodeBase_t *Next; - int16 Depth; - int16 Sequence; - } value; - - int64 value64; -}; -#endif - -//------------------------------------- - -class TSLIST_HEAD_ALIGN CTSListBase -{ -public: - CTSListBase() - { - if ( ((size_t)&m_Head) % TSLIST_HEAD_ALIGNMENT != 0 ) - { - Error( "CTSListBase: Misaligned list\n" ); - DebuggerBreak(); - } - -#ifdef USE_NATIVE_SLIST - InitializeSListHead( &m_Head ); -#else - m_Head.value64 = (int64)0; -#endif - } - - ~CTSListBase() - { - Detach(); - } - - TSLNodeBase_t *Push( TSLNodeBase_t *pNode ) - { - if ( (size_t)pNode % TSLIST_NODE_ALIGNMENT != 0 ) - { - Error( "CTSListBase: Misaligned node\n" ); - DebuggerBreak(); - } - -#ifdef USE_NATIVE_SLIST -#ifdef _X360 - // integrated write-release barrier - return (TSLNodeBase_t *)InterlockedPushEntrySListRelease( &m_Head, pNode ); -#else - return (TSLNodeBase_t *)InterlockedPushEntrySList( &m_Head, pNode ); -#endif -#else - TSLHead_t oldHead; - TSLHead_t newHead; - - for (;;) - { - oldHead.value64 = m_Head.value64; - pNode->Next = oldHead.value.Next; - newHead.value.Next = pNode; - *((uint32 *)&newHead.value.Depth) = *((uint32 *)&oldHead.value.Depth) + 0x10001; - - if ( ThreadInterlockedAssignIf64( &m_Head.value64, newHead.value64, oldHead.value64 ) ) - { - break; - } - ThreadPause(); - }; - - return (TSLNodeBase_t *)oldHead.value.Next; -#endif - } - - TSLNodeBase_t *Pop() - { -#ifdef USE_NATIVE_SLIST -#ifdef _X360 - // integrated read-acquire barrier - TSLNodeBase_t *pNode = (TSLNodeBase_t *)InterlockedPopEntrySListAcquire( &m_Head ); -#else - TSLNodeBase_t *pNode = (TSLNodeBase_t *)InterlockedPopEntrySList( &m_Head ); -#endif - return pNode; -#else - TSLHead_t oldHead; - TSLHead_t newHead; - - for (;;) - { - oldHead.value64 = m_Head.value64; - if ( !oldHead.value.Next ) - return NULL; - - newHead.value.Next = oldHead.value.Next->Next; - *((uint32 *)&newHead.value.Depth) = *((uint32 *)&oldHead.value.Depth) - 1; - - if ( ThreadInterlockedAssignIf64( &m_Head.value64, newHead.value64, oldHead.value64 ) ) - { - break; - } - ThreadPause(); - }; - - return (TSLNodeBase_t *)oldHead.value.Next; -#endif - } - - TSLNodeBase_t *Detach() - { -#ifdef USE_NATIVE_SLIST - TSLNodeBase_t *pBase = (TSLNodeBase_t *)InterlockedFlushSList( &m_Head ); -#ifdef _X360 - __lwsync(); // read-acquire barrier -#endif - return pBase; -#else - TSLHead_t oldHead; - TSLHead_t newHead; - - do - { - ThreadPause(); - - oldHead.value64 = m_Head.value64; - if ( !oldHead.value.Next ) - return NULL; - - newHead.value.Next = NULL; - *((uint32 *)&newHead.value.Depth) = *((uint32 *)&oldHead.value.Depth) & 0xffff0000; - - } while( !ThreadInterlockedAssignIf64( &m_Head.value64, newHead.value64, oldHead.value64 ) ); - - return (TSLNodeBase_t *)oldHead.value.Next; -#endif - } - - int Count() const - { -#ifdef USE_NATIVE_SLIST - return QueryDepthSList( &m_Head ); -#else - return m_Head.value.Depth; -#endif - } - -private: - TSLHead_t m_Head; -}; - -//------------------------------------- - -template -class TSLIST_HEAD_ALIGN CTSSimpleList : public CTSListBase -{ -public: - void Push( T *pNode ) - { - Assert( sizeof(T) >= sizeof(TSLNodeBase_t) ); - CTSListBase::Push( (TSLNodeBase_t *)pNode ); - } - - T *Pop() - { - return (T *)CTSListBase::Pop(); - } -}; - -//------------------------------------- - -template -class TSLIST_HEAD_ALIGN CTSList : public CTSListBase -{ -public: - struct TSLIST_NODE_ALIGN Node_t : public TSLNodeBase_t - { - Node_t() {} - Node_t( const T &init ) : elem( init ) {} - - T elem; - - }; - - ~CTSList() - { - Purge(); - } - - void Purge() - { - Node_t *pCurrent = Detach(); - Node_t *pNext; - while ( pCurrent ) - { - pNext = (Node_t *)pCurrent->Next; - delete pCurrent; - pCurrent = pNext; - } - } - - void RemoveAll() - { - Purge(); - } - - Node_t *Push( Node_t *pNode ) - { - return (Node_t *)CTSListBase::Push( pNode ); - } - - Node_t *Pop() - { - return (Node_t *)CTSListBase::Pop(); - } - - void PushItem( const T &init ) - { - Push( new Node_t( init ) ); - } - - bool PopItem( T *pResult) - { - Node_t *pNode = Pop(); - if ( !pNode ) - return false; - *pResult = pNode->elem; - delete pNode; - return true; - } - - Node_t *Detach() - { - return (Node_t *)CTSListBase::Detach(); - } - -}; - -// this is a replacement for CTSList<> and CObjectPool<> that does not -// have a per-item, per-alloc new/delete overhead -// similar to CTSSimpleList except that it allocates it's own pool objects -// and frees them on destruct. Also it does not overlay the TSNodeBase_t memory -// on T's memory -template< class T > -class TSLIST_HEAD_ALIGN CTSPool : public CTSListBase -{ - // packs the node and the item (T) into a single struct and pools those - struct TSLIST_NODE_ALIGN simpleTSPoolStruct_t : public TSLNodeBase_t - { - T elem; - }; - -public: - - ~CTSPool() - { - simpleTSPoolStruct_t *pNode = NULL; - while ( 1 ) - { - pNode = (simpleTSPoolStruct_t *)CTSListBase::Pop(); - if ( !pNode ) - break; - delete pNode; - } - } - - void PutObject( T *pInfo ) - { - char *pElem = (char *)pInfo; - pElem -= offsetof(simpleTSPoolStruct_t,elem); - simpleTSPoolStruct_t *pNode = (simpleTSPoolStruct_t *)pElem; - - CTSListBase::Push( pNode ); - } - - T *GetObject() - { - simpleTSPoolStruct_t *pNode = (simpleTSPoolStruct_t *)CTSListBase::Pop(); - if ( !pNode ) - { - pNode = new simpleTSPoolStruct_t; - } - return &pNode->elem; - } -}; - -//------------------------------------- - -template -class TSLIST_HEAD_ALIGN CTSListWithFreeList : public CTSListBase -{ -public: - struct TSLIST_NODE_ALIGN Node_t : public TSLNodeBase_t - { - Node_t() {} - Node_t( const T &init ) : elem( init ) {} - - T elem; - }; - - ~CTSListWithFreeList() - { - Purge(); - } - - void Purge() - { - Node_t *pCurrent = Detach(); - Node_t *pNext; - while ( pCurrent ) - { - pNext = (Node_t *)pCurrent->Next; - delete pCurrent; - pCurrent = pNext; - } - pCurrent = (Node_t *)m_FreeList.Detach(); - while ( pCurrent ) - { - pNext = (Node_t *)pCurrent->Next; - delete pCurrent; - pCurrent = pNext; - } - } - - void RemoveAll() - { - Node_t *pCurrent = Detach(); - Node_t *pNext; - while ( pCurrent ) - { - pNext = (Node_t *)pCurrent->Next; - m_FreeList.Push( pCurrent ); - pCurrent = pNext; - } - } - - Node_t *Push( Node_t *pNode ) - { - return (Node_t *)CTSListBase::Push( pNode ); - } - - Node_t *Pop() - { - return (Node_t *)CTSListBase::Pop(); - } - - void PushItem( const T &init ) - { - Node_t *pNode = (Node_t *)m_FreeList.Pop(); - if ( !pNode ) - { - pNode = new Node_t; - } - pNode->elem = init; - Push( pNode ); - } - - bool PopItem( T *pResult) - { - Node_t *pNode = Pop(); - if ( !pNode ) - return false; - *pResult = pNode->elem; - m_FreeList.Push( pNode ); - return true; - } - - Node_t *Detach() - { - return (Node_t *)CTSListBase::Detach(); - } - - void FreeNode( Node_t *pNode ) - { - m_FreeList.Push( pNode ); - } - -private: - CTSListBase m_FreeList; -}; - -//----------------------------------------------------------------------------- -// Lock free queue -// -// A special consideration: the element type should be simple. This code -// actually dereferences freed nodes as part of pop, but later detects -// that. If the item in the queue is a complex type, only bad things can -// come of that. Also, therefore, if you're using Push/Pop instead of -// push item, be aware that the node memory cannot be freed until -// all threads that might have been popping have completed the pop. -// The PushItem()/PopItem() for handles this by keeping a persistent -// free list. Dont mix Push/PushItem. Note also nodes will be freed at the end, -// and are expected to have been allocated with operator new. -//----------------------------------------------------------------------------- - -template -class TSLIST_HEAD_ALIGN CTSQueue -{ -public: - struct TSLIST_NODE_ALIGN Node_t - { - Node_t() {} - Node_t( const T &init ) : elem( init ) {} - - Node_t *pNext; - T elem; - }; - - union TSLIST_HEAD_ALIGN NodeLink_t - { - struct Value_t - { - Node_t *pNode; - int32 sequence; - } value; - - int64 value64; - }; - - CTSQueue() - { - COMPILE_TIME_ASSERT( sizeof(Node_t) >= sizeof(TSLNodeBase_t) ); - if ( ((size_t)&m_Head) % TSLIST_HEAD_ALIGNMENT != 0 ) - { - Error( "CTSQueue: Misaligned queue\n" ); - DebuggerBreak(); - } - if ( ((size_t)&m_Tail) % TSLIST_HEAD_ALIGNMENT != 0 ) - { - Error( "CTSQueue: Misaligned queue\n" ); - DebuggerBreak(); - } - m_Count = 0; - m_Head.value.sequence = m_Tail.value.sequence = 0; - m_Head.value.pNode = m_Tail.value.pNode = new Node_t; // list always contains a dummy node - m_Head.value.pNode->pNext = End(); - } - - ~CTSQueue() - { - Purge(); - Assert( m_Count == 0 ); - Assert( m_Head.value.pNode == m_Tail.value.pNode ); - Assert( m_Head.value.pNode->pNext == End() ); - delete m_Head.value.pNode; - } - - // Note: Purge, RemoveAll, and Validate are *not* threadsafe - void Purge() - { - if ( IsDebug() ) - { - Validate(); - } - - Node_t *pNode; - while ( ( pNode = Pop() ) != NULL ) - { - delete pNode; - } - - while ( ( pNode = (Node_t *)m_FreeNodes.Pop() ) != NULL ) - { - delete pNode; - } - - Assert( m_Count == 0 ); - Assert( m_Head.value.pNode == m_Tail.value.pNode ); - Assert( m_Head.value.pNode->pNext == End() ); - - m_Head.value.sequence = m_Tail.value.sequence = 0; - } - - void RemoveAll() - { - if ( IsDebug() ) - { - Validate(); - } - - Node_t *pNode; - while ( ( pNode = Pop() ) != NULL ) - { - m_FreeNodes.Push( (TSLNodeBase_t *)pNode ); - } - } - - bool Validate() - { - bool bResult = true; - int nNodes = 0; - if ( m_Tail.value.pNode->pNext != End() ) - { - DebuggerBreakIfDebugging(); - bResult = false; - } - - if ( m_Count == 0 ) - { - if ( m_Head.value.pNode != m_Tail.value.pNode ) - { - DebuggerBreakIfDebugging(); - bResult = false; - } - } - - Node_t *pNode = m_Head.value.pNode; - while ( pNode != End() ) - { - nNodes++; - pNode = pNode->pNext; - } - - nNodes--;// skip dummy node - - if ( nNodes != m_Count ) - { - DebuggerBreakIfDebugging(); - bResult = false; - } - - if ( !bResult ) - { - Msg( "Corrupt CTSQueueDetected" ); - } - - return bResult; - } - - void FinishPush( Node_t *pNode, const NodeLink_t &oldTail ) - { - NodeLink_t newTail; - - newTail.value.pNode = pNode; - newTail.value.sequence = oldTail.value.sequence + 1; - -#ifdef _X360 - __lwsync(); // write-release barrier -#endif - InterlockedCompareExchangeNodeLink( &m_Tail, newTail, oldTail ); - } - - Node_t *Push( Node_t *pNode ) - { -#ifdef _DEBUG - if ( (size_t)pNode % TSLIST_NODE_ALIGNMENT != 0 ) - { - Error( "CTSListBase: Misaligned node\n" ); - DebuggerBreak(); - } -#endif - - NodeLink_t oldTail; - - pNode->pNext = End(); - - for (;;) - { - oldTail = m_Tail; - if ( InterlockedCompareExchangeNode( &(oldTail.value.pNode->pNext), pNode, End() ) == End() ) - { - break; - } - else - { - // Another thread is trying to push, help it along - FinishPush( oldTail.value.pNode->pNext, oldTail ); - } - } - - FinishPush( pNode, oldTail ); - - m_Count++; - - return oldTail.value.pNode; - } - - Node_t *Pop() - { - #define TSQUEUE_BAD_NODE_LINK ((Node_t *)0xdeadbeef) - NodeLink_t * volatile pHead = &m_Head; - NodeLink_t * volatile pTail = &m_Tail; - Node_t * volatile * pHeadNode = &m_Head.value.pNode; - volatile int * volatile pHeadSequence = &m_Head.value.sequence; - Node_t * volatile * pTailNode = &pTail->value.pNode; - - NodeLink_t head; - NodeLink_t newHead; - Node_t *pNext; - int tailSequence; - T elem; - - for (;;) - { - head.value.sequence = *pHeadSequence; // must grab sequence first, which allows condition below to ensure pNext is valid -#ifdef _X360 - __lwsync(); // 360 needs a barrier to prevent reordering of these assignments -#endif - head.value.pNode = *pHeadNode; - tailSequence = pTail->value.sequence; - pNext = head.value.pNode->pNext; - - if ( pNext && head.value.sequence == *pHeadSequence ) // Checking pNext only to force optimizer to not reorder the assignment to pNext and the compare of the sequence - { - if ( bTestOptimizer ) - { - if ( pNext == TSQUEUE_BAD_NODE_LINK ) - { - Msg( "Bad node link detected\n" ); - continue; - } - } - if ( head.value.pNode == *pTailNode ) - { - if ( pNext == End() ) - { - return NULL; - } - - // Another thread is trying to push, help it along - NodeLink_t &oldTail = head; // just reuse local memory for head to build old tail - oldTail.value.sequence = tailSequence; // reuse head pNode - FinishPush( pNext, oldTail ); - } - else if ( pNext != End() ) - { - elem = pNext->elem; // NOTE: next could be a freed node here, by design - newHead.value.pNode = pNext; - newHead.value.sequence = head.value.sequence + 1; - if ( InterlockedCompareExchangeNodeLink( pHead, newHead, head ) ) - { -#ifdef _X360 - __lwsync(); // read-acquire barrier -#endif - if ( bTestOptimizer ) - { - head.value.pNode->pNext = TSQUEUE_BAD_NODE_LINK; - } - break; - } - } - } - } - - m_Count--; - head.value.pNode->elem = elem; - return head.value.pNode; - } - - void FreeNode( Node_t *pNode ) - { - m_FreeNodes.Push( (TSLNodeBase_t *)pNode ); - } - - void PushItem( const T &init ) - { - Node_t *pNode = (Node_t *)m_FreeNodes.Pop(); - if ( pNode ) - { - pNode->elem = init; - } - else - { - pNode = new Node_t( init ); - } - Push( pNode ); - } - - bool PopItem( T *pResult) - { - Node_t *pNode = Pop(); - if ( !pNode ) - return false; - *pResult = pNode->elem; - m_FreeNodes.Push( (TSLNodeBase_t *)pNode ); - return true; - } - - int Count() - { - return m_Count; - } - -private: - Node_t *End() { return (Node_t *)this; } // just need a unique signifier - -#ifndef _WIN64 - Node_t *InterlockedCompareExchangeNode( Node_t * volatile *ppNode, Node_t *value, Node_t *comperand ) - { - return (Node_t *)::ThreadInterlockedCompareExchangePointer( (void **)ppNode, value, comperand ); - } - - bool InterlockedCompareExchangeNodeLink( NodeLink_t volatile *pLink, const NodeLink_t &value, const NodeLink_t &comperand ) - { - return ThreadInterlockedAssignIf64( (int64 *)pLink, value.value64, comperand.value64 ); - } - -#else - Node_t *InterlockedCompareExchangeNode( Node_t * volatile *ppNode, Node_t *value, Node_t *comperand ) - { - AUTO_LOCK( m_ExchangeMutex ); - Node_t *retVal = *ppNode; - if ( *ppNode == comperand ) - *ppNode = value; - return retVal; - } - - bool InterlockedCompareExchangeNodeLink( NodeLink_t volatile *pLink, const NodeLink_t &value, const NodeLink_t &comperand ) - { - AUTO_LOCK( m_ExchangeMutex ); - if ( pLink->value64 == comperand.value64 ) - { - pLink->value64 = value.value64; - return true; - } - return false; - } - - CThreadFastMutex m_ExchangeMutex; -#endif - - NodeLink_t m_Head; - NodeLink_t m_Tail; - - CInterlockedInt m_Count; - - CTSListBase m_FreeNodes; -}; - -#include "tier0/memdbgoff.h" - -#endif // TSLIST_H diff --git a/public/tier0/validator.h b/public/tier0/validator.h deleted file mode 100644 index a3b336ee5..000000000 --- a/public/tier0/validator.h +++ /dev/null @@ -1,73 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - - -#include "valobject.h" - -#ifndef VALIDATOR_H -#define VALIDATOR_H - -#ifdef _WIN32 -#pragma once -#endif - - -#ifdef DBGFLAG_VALIDATE - - -class CValidator -{ -public: - // Constructors & destructors - CValidator( void ); - ~CValidator( void ); - - // Call this each time we enter a new Validate function - void Push( tchar *pchType, void *pvObj, tchar *pchName ); - - // Call this each time we exit a Validate function - void Pop( void ); - - // Claim ownership of a memory block - void ClaimMemory( void *pvMem ); - - // Finish performing a check and perform necessary computations - void Finalize( void ); - - // Render our results to the console - void RenderObjects( int cubThreshold ); // Render all reported objects - void RenderLeaks( void ); // Render all memory leaks - - // List manipulation functions: - CValObject *FindObject( void *pvObj ); // Returns CValObject containing pvObj, or NULL. - void DiffAgainst( CValidator *pOtherValidator ); // Removes any entries from this validator that are also present in the other. - - // Accessors - bool BMemLeaks( void ) { return m_bMemLeaks; }; - CValObject *PValObjectFirst( void ) { return m_pValObjectFirst; }; - - void Validate( CValidator &validator, tchar *pchName ); // Validate our internal structures - - -private: - CValObject *m_pValObjectFirst; // Linked list of all ValObjects - CValObject *m_pValObjectLast; // Last ValObject on the linked list - - CValObject *m_pValObjectCur; // Object we're current processing - - int m_cpvOwned; // Total # of blocks owned - - int m_cpubLeaked; // # of leaked memory blocks - int m_cubLeaked; // Amount of leaked memory - bool m_bMemLeaks; // Has any memory leaked? -}; - - -#endif // DBGFLAG_VALIDATE - - -#endif // VALIDATOR_H diff --git a/public/tier0/valobject.h b/public/tier0/valobject.h deleted file mode 100644 index 8a2cbf0f5..000000000 --- a/public/tier0/valobject.h +++ /dev/null @@ -1,72 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: CValObject is used for tracking individual objects that report -// in to CValidator. Whenever a new object reports in (via CValidator::Push), -// we create a new CValObject to aggregate stats for it. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef VALOBJECT_H -#define VALOBJECT_H -#ifdef _WIN32 -#pragma once -#endif - - -#ifdef DBGFLAG_VALIDATE -class CValObject -{ -public: - // Constructors & destructors - CValObject( void ) { }; - ~CValObject( void ); - - void Init( tchar *pchType, void *pvObj, tchar *pchName, CValObject *pValObjectParent, - CValObject *pValObjectPrev ); - - // Our object has claimed ownership of a memory block - void ClaimMemoryBlock( void *pvMem ); - - // A child of ours has claimed ownership of a memory block - void ClaimChildMemoryBlock( int cubUser ); - - // Accessors - tchar *PchType( void ) { return m_rgchType; }; - void *PvObj( void ) { return m_pvObj; }; - tchar *PchName( void ) { return m_rgchName; }; - CValObject *PValObjectParent( void ) { return m_pValObjectParent; }; - int NLevel( void ) { return m_nLevel; }; - CValObject *PValObjectNext( void ) { return m_pValObjectNext; }; - int CpubMemSelf( void ) { return m_cpubMemSelf; }; - int CubMemSelf( void ) { return m_cubMemSelf; }; - int CpubMemTree( void ) { return m_cpubMemTree; }; - int CubMemTree( void ) { return m_cubMemTree; }; - int NUser( void ) { return m_nUser; }; - void SetNUser( int nUser ) { m_nUser = nUser; }; - void SetBNewSinceSnapshot( bool bNewSinceSnapshot ) { m_bNewSinceSnapshot = bNewSinceSnapshot; } - bool BNewSinceSnapshot( void ) { return m_bNewSinceSnapshot; } - -private: - bool m_bNewSinceSnapshot; // If this block is new since the snapshot. - tchar m_rgchType[64]; // Type of the object we represent - tchar m_rgchName[64]; // Name of this particular object - void *m_pvObj; // Pointer to the object we represent - - CValObject *m_pValObjectParent; // Our parent object in the tree. - int m_nLevel; // Our depth in the tree - - CValObject *m_pValObjectNext; // Next ValObject in the linked list - - int m_cpubMemSelf; // # of memory blocks we own directly - int m_cubMemSelf; // Total size of the memory blocks we own directly - - int m_cpubMemTree; // # of memory blocks owned by us and our children - int m_cubMemTree; // Total size of the memory blocks owned by us and our children - - int m_nUser; // Field provided for use by our users -}; -#endif // DBGFLAG_VALIDATE - - -#endif // VALOBJECT_H diff --git a/public/tier0/valve_minmax_off.h b/public/tier0/valve_minmax_off.h deleted file mode 100644 index 827ae2a9f..000000000 --- a/public/tier0/valve_minmax_off.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifdef min - #undef min -#endif - -#ifdef max - #undef max -#endif - diff --git a/public/tier0/valve_minmax_on.h b/public/tier0/valve_minmax_on.h deleted file mode 100644 index 99a2c5fef..000000000 --- a/public/tier0/valve_minmax_on.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef min - #define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -#ifndef max - #define max(a,b) (((a) > (b)) ? (a) : (b)) -#endif - diff --git a/public/tier0/valve_off.h b/public/tier0/valve_off.h deleted file mode 100644 index 87012d860..000000000 --- a/public/tier0/valve_off.h +++ /dev/null @@ -1,30 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: This turns off all Valve-specific #defines. Because we sometimes -// call external include files from inside .cpp files, we need to -// wrap those includes like this: -// #include "tier0/valve_off.h" -// #include -// #include "tier0/valve_on.h" -// -// $NoKeywords: $ -//=============================================================================// - - -#ifdef STEAM - -//----------------------------------------------------------------------------- -// Unicode-related #defines (see wchartypes.h) -//----------------------------------------------------------------------------- -#undef char - - -//----------------------------------------------------------------------------- -// Memory-related #defines -//----------------------------------------------------------------------------- -#undef malloc -#undef realloc -#undef _expand -#undef free - -#endif diff --git a/public/tier0/valve_on.h b/public/tier0/valve_on.h deleted file mode 100644 index a7d0d2187..000000000 --- a/public/tier0/valve_on.h +++ /dev/null @@ -1,31 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: This turns on all Valve-specific #defines. Because we sometimes -// call external include files from inside .cpp files, we need to -// wrap those includes like this: -// #include "tier0/valve_off.h" -// #include -// #include "tier0/valve_on.h" -// -// $NoKeywords: $ -//=============================================================================// - - -#ifdef STEAM -//----------------------------------------------------------------------------- -// Unicode-related #defines (see wchartypes.h) -//----------------------------------------------------------------------------- -#ifdef ENFORCE_WCHAR -#define char DontUseChar_SeeWcharOn.h -#endif - - -//----------------------------------------------------------------------------- -// Memory-related #defines -//----------------------------------------------------------------------------- -#define malloc( cub ) HEY_DONT_USE_MALLOC_USE_PVALLOC -#define realloc( pvOld, cub ) HEY_DONT_USE_REALLOC_USE_PVREALLOC -#define _expand( pvOld, cub ) HEY_DONT_USE_EXPAND_USE_PVEXPAND -#define free( pv ) HEY_DONT_USE_FREE_USE_FREEPV - -#endif diff --git a/public/tier0/vcr_shared.h b/public/tier0/vcr_shared.h deleted file mode 100644 index 026e95d35..000000000 --- a/public/tier0/vcr_shared.h +++ /dev/null @@ -1,54 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef VCR_SHARED_H -#define VCR_SHARED_H -#ifdef _WIN32 -#pragma once -#endif - - -#define VCRFILE_VERSION 2 - - -// Identifiers for the things we record. When playing back, these things should -// be asked for in the exact same order (otherwise, the engine isn't making all -// the calls in the same order). -typedef enum -{ - VCREvent_Sys_FloatTime=0, - VCREvent_recvfrom, - VCREvent_SyncToken, - VCREvent_GetCursorPos, - VCREvent_SetCursorPos, - VCREvent_ScreenToClient, - VCREvent_Cmd_Exec, - VCREvent_CmdLine, - VCREvent_RegOpenKeyEx, - VCREvent_RegSetValueEx, - VCREvent_RegQueryValueEx, - VCREvent_RegCreateKeyEx, - VCREvent_RegCloseKey, - VCREvent_PeekMessage, - VCREvent_GameMsg, - VCREvent_GetNumberOfConsoleInputEvents, - VCREvent_ReadConsoleInput, - VCREvent_GetKeyState, - VCREvent_recv, - VCREvent_send, - VCREvent_Generic, - VCREvent_CreateThread, - VCREvent_WaitForSingleObject, - VCREvent_EnterCriticalSection, - VCREvent_Time, - VCREvent_LocalTime, - VCREvent_GenericString, - VCREvent_NUMEVENTS -} VCREvent; - - -#endif // VCR_SHARED_H diff --git a/public/tier0/vcrmode.h b/public/tier0/vcrmode.h deleted file mode 100644 index eff3a7f54..000000000 --- a/public/tier0/vcrmode.h +++ /dev/null @@ -1,306 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: VCR mode records a client's game and allows you to -// play it back and reproduce it exactly. When playing it back, nothing -// is simulated on the server, but all server packets are recorded. -// -// Most of the VCR mode functionality is accomplished through hooks -// called at various points in the engine. -// -// $NoKeywords: $ -//===========================================================================// -#ifndef VCRMODE_H -#define VCRMODE_H - -#ifdef _WIN32 -#include -#endif - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/platform.h" -#include "tier0/vcr_shared.h" -#include "tier0/dbg.h" - -#if defined _LINUX || defined __APPLE__ -DBG_INTERFACE void BuildCmdLine( int argc, tchar **argv ); -tchar *GetCommandLine(); -#endif - -#ifdef _X360 -#define NO_VCR 1 -#endif - - -// Enclose lines of code in this if you don't want anything in them written to or read from the VCR file. -#ifndef NO_VCR -#define NOVCR(x) \ -{\ - VCRSetEnabled(0);\ - x;\ - VCRSetEnabled(1);\ -} -#else -#define NOVCR(x) \ -{\ - x;\ -} -#endif - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -struct InputEvent_t; - - -//----------------------------------------------------------------------------- -// Definitions. -//----------------------------------------------------------------------------- -enum VCRMode_t -{ - VCR_Invalid=-1, - VCR_Disabled=0, - VCR_Record, - VCR_Playback -}; - - -//----------------------------------------------------------------------------- -// Functions. -//----------------------------------------------------------------------------- -abstract_class IVCRHelpers -{ -public: - virtual void ErrorMessage( const tchar *pMsg ) = 0; - virtual void* GetMainWindow() = 0; -}; - - -// Used by the vcrtrace program. -abstract_class IVCRTrace -{ -public: - virtual VCREvent ReadEvent() = 0; - virtual void Read( void *pDest, int size ) = 0; -}; - -typedef struct VCR_s -{ - // Start VCR record or play. - int (*Start)( tchar const *pFilename, bool bRecord, IVCRHelpers *pHelpers ); - void (*End)(); - - // Used by the VCR trace app. - IVCRTrace* (*GetVCRTraceInterface)(); - - // Get the current mode the VCR is in. - VCRMode_t (*GetMode)(); - - // This can be used to block out areas of code that are unpredictable (like things triggered by WM_TIMER messages). - // Note: this enables/disables VCR mode usage on a PER-THREAD basis. The assumption is that you're marking out - // specific sections of code that you don't want to use VCR mode inside of, but you're not intending to - // stop all the other threads from using VCR mode. - void (*SetEnabled)(int bEnabled); - - // This can be called any time to put in a debug check to make sure things are synchronized. - void (*SyncToken)(tchar const *pToken); - - // Hook for Sys_FloatTime(). - double (*Hook_Sys_FloatTime)(double time); - - // Note: this makes no guarantees about msg.hwnd being the same on playback. If it needs to be, then we need to add - // an ID system for Windows and store the ID like in Goldsrc. - int (*Hook_PeekMessage)( - struct tagMSG *msg, - void *hWnd, - unsigned int wMsgFilterMin, - unsigned int wMsgFilterMax, - unsigned int wRemoveMsg - ); - - // Call this to record game messages. - void (*Hook_RecordGameMsg)( const InputEvent_t &event ); - void (*Hook_RecordEndGameMsg)(); - - // Call this to playback game messages until it returns false. - bool (*Hook_PlaybackGameMsg)( InputEvent_t *pEvent ); - - // Hook for recvfrom() calls. This replaces the recvfrom() call. - int (*Hook_recvfrom)(int s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen); - - void (*Hook_GetCursorPos)(struct tagPOINT *pt); - void (*Hook_ScreenToClient)(void *hWnd, struct tagPOINT *pt); - - void (*Hook_Cmd_Exec)(tchar **f); - - tchar* (*Hook_GetCommandLine)(); - - // Registry hooks. - long (*Hook_RegOpenKeyEx)( void *hKey, const tchar *lpSubKey, unsigned long ulOptions, unsigned long samDesired, void *pHKey ); - long (*Hook_RegSetValueEx)(void *hKey, tchar const *lpValueName, unsigned long Reserved, unsigned long dwType, uint8 const *lpData, unsigned long cbData); - long (*Hook_RegQueryValueEx)(void *hKey, tchar const *lpValueName, unsigned long *lpReserved, unsigned long *lpType, uint8 *lpData, unsigned long *lpcbData); - long (*Hook_RegCreateKeyEx)(void *hKey, tchar const *lpSubKey, unsigned long Reserved, tchar *lpClass, unsigned long dwOptions, unsigned long samDesired, void *lpSecurityAttributes, void *phkResult, unsigned long *lpdwDisposition); - void (*Hook_RegCloseKey)(void *hKey); - - // hInput is a HANDLE. - int (*Hook_GetNumberOfConsoleInputEvents)( void *hInput, unsigned long *pNumEvents ); - - // hInput is a HANDLE. - // pRecs is an INPUT_RECORD pointer. - int (*Hook_ReadConsoleInput)( void *hInput, void *pRecs, int nMaxRecs, unsigned long *pNumRead ); - - - // This calls time() then gives you localtime()'s result. - void (*Hook_LocalTime)( struct tm *today ); - - short (*Hook_GetKeyState)( int nVirtKey ); - - // TCP calls. - int (*Hook_recv)( int s, char *buf, int len, int flags ); - int (*Hook_send)( int s, const char *buf, int len, int flags ); - - // These can be used to add events without having to modify VCR mode. - // pEventName is used for verification to make sure it's playing back correctly. - // If pEventName is null, then verification is not performed. - void (*GenericRecord)( const tchar *pEventName, const void *pData, int len ); - - - // Returns the number of bytes written in the generic event. - // If bForceLenSame is true, then it will error out unless the value in the VCR file is the same as maxLen. - int (*GenericPlayback)( const tchar *pEventName, void *pOutData, int maxLen, bool bForceLenSame ); - - // If you just want to record and playback a value and not worry about whether or not you're - // recording or playing back, use this. It also will do nothing if you're not recording or playing back. - // - // NOTE: also see GenericValueVerify, which allows you to have it VERIFY that pData's contents are the same upon playback - // (rather than just copying whatever is in the VCR file into pData). - void (*GenericValue)( const tchar *pEventName, void *pData, int maxLen ); - - // Get the current percent (0.0 - 1.0) that it's played back through the file (only valid in playback). - double (*GetPercentCompleted)(); - - // If you use this, then any VCR stuff the thread does will work with VCR mode. - // This mirrors the Windows API CreateThread function and returns a HANDLE the same way. - void* (*Hook_CreateThread)( - void *lpThreadAttributes, - unsigned long dwStackSize, - void *lpStartAddress, - void *lpParameter, - unsigned long dwCreationFlags, - unsigned long *lpThreadID ); - - unsigned long (*Hook_WaitForSingleObject)( - void *handle, - unsigned long dwMilliseconds ); - - void (*Hook_EnterCriticalSection)( void *pCS ); - - void (*Hook_Time)( long *pTime ); - - // String value. Playback just verifies that the incoming string is the same as it was when recording. - void (*GenericString)( const char *pEventName, const char *pString ); - - // Works like GenericValue, except upon playback it will verify that pData's contents are the same as it was during recording. - void (*GenericValueVerify)( const tchar *pEventName, const void *pData, int maxLen ); - - unsigned long (*Hook_WaitForMultipleObjects)( uint32 nHandles, const void **pHandles, int bWaitAll, uint32 timeout ); - -} VCR_t; - -#ifndef NO_VCR - -// In the launcher, this is created by vcrmode.c. -// In the engine, this is set when the launcher initializes its DLL. -PLATFORM_INTERFACE VCR_t *g_pVCR; - -#endif - - -#ifndef NO_VCR -#define VCRStart g_pVCR->Start -#define VCREnd g_pVCR->End -#define VCRGetVCRTraceInterface g_pVCR->GetVCRTraceInterface -#define VCRGetMode g_pVCR->GetMode -#define VCRSetEnabled g_pVCR->SetEnabled -#define VCRSyncToken g_pVCR->SyncToken -#define VCRGenericString g_pVCR->GenericString -#define VCRGenericValueVerify g_pVCR->GenericValueVerify -#define VCRHook_Sys_FloatTime g_pVCR->Hook_Sys_FloatTime -#define VCRHook_PeekMessage g_pVCR->Hook_PeekMessage -#define VCRHook_RecordGameMsg g_pVCR->Hook_RecordGameMsg -#define VCRHook_RecordEndGameMsg g_pVCR->Hook_RecordEndGameMsg -#define VCRHook_PlaybackGameMsg g_pVCR->Hook_PlaybackGameMsg -#define VCRHook_recvfrom g_pVCR->Hook_recvfrom -#define VCRHook_GetCursorPos g_pVCR->Hook_GetCursorPos -#define VCRHook_ScreenToClient g_pVCR->Hook_ScreenToClient -#define VCRHook_Cmd_Exec g_pVCR->Hook_Cmd_Exec -#define VCRHook_GetCommandLine g_pVCR->Hook_GetCommandLine -#define VCRHook_RegOpenKeyEx g_pVCR->Hook_RegOpenKeyEx -#define VCRHook_RegSetValueEx g_pVCR->Hook_RegSetValueEx -#define VCRHook_RegQueryValueEx g_pVCR->Hook_RegQueryValueEx -#define VCRHook_RegCreateKeyEx g_pVCR->Hook_RegCreateKeyEx -#define VCRHook_RegCloseKey g_pVCR->Hook_RegCloseKey -#define VCRHook_GetNumberOfConsoleInputEvents g_pVCR->Hook_GetNumberOfConsoleInputEvents -#define VCRHook_ReadConsoleInput g_pVCR->Hook_ReadConsoleInput -#define VCRHook_LocalTime g_pVCR->Hook_LocalTime -#define VCRHook_GetKeyState g_pVCR->Hook_GetKeyState -#define VCRHook_recv g_pVCR->Hook_recv -#define VCRHook_send g_pVCR->Hook_send -#define VCRGenericRecord g_pVCR->GenericRecord -#define VCRGenericPlayback g_pVCR->GenericPlayback -#define VCRGenericValue g_pVCR->GenericValue -#define VCRGetPercentCompleted g_pVCR->GetPercentCompleted -#define VCRHook_CreateThread g_pVCR->Hook_CreateThread -#define VCRHook_WaitForSingleObject g_pVCR->Hook_WaitForSingleObject -#define VCRHook_EnterCriticalSection g_pVCR->Hook_EnterCriticalSection -#define VCRHook_Time g_pVCR->Hook_Time -#define VCRHook_WaitForMultipleObjects( a, b, c, d) g_pVCR->Hook_WaitForMultipleObjects( a, (const void **)b, c, d) -#else -#define VCRStart( a, b, c ) (1) -#define VCREnd ((void)(0)) -#define VCRGetVCRTraceInterface (NULL) -#define VCRGetMode() (VCR_Disabled) -#define VCRSetEnabled( a ) ((void)(0)) -#define VCRSyncToken( a ) ((void)(0)) -#define VCRGenericRecord MUST_IFDEF_OUT_GenericRecord -#define VCRGenericPlayback MUST_IFDEF_OUT_GenericPlayback -#define VCRGenericValue MUST_IFDEF_OUT_GenericValue -#define VCRGenericString MUST_IFDEF_OUT_GenericString -#define VCRGenericValueVerify MUST_IFDEF_OUT_GenericValueVerify -#define VCRGetPercentCompleted() (0.0f) -#define VCRHook_Sys_FloatTime Sys_FloatTime -#define VCRHook_PeekMessage PeekMessage -#define VCRHook_RecordGameMsg RecordGameMsg -#define VCRHook_RecordEndGameMsg RecordEndGameMsg -#define VCRHook_PlaybackGameMsg PlaybackGameMsg -#define VCRHook_recvfrom recvfrom -#define VCRHook_GetCursorPos GetCursorPos -#define VCRHook_ScreenToClient ScreenToClient -#define VCRHook_Cmd_Exec( a ) ((void)(0)) -#define VCRHook_GetCommandLine GetCommandLine -#define VCRHook_RegOpenKeyEx RegOpenKeyEx -#define VCRHook_RegSetValueEx RegSetValueEx -#define VCRHook_RegQueryValueEx RegQueryValueEx -#define VCRHook_RegCreateKeyEx RegCreateKeyEx -#define VCRHook_RegCloseKey RegCloseKey -#define VCRHook_GetNumberOfConsoleInputEvents GetNumberOfConsoleInputEvents -#define VCRHook_ReadConsoleInput ReadConsoleInput -#define VCRHook_LocalTime( a ) memset(a, 0, sizeof(*a)); -#define VCRHook_GetKeyState GetKeyState -#define VCRHook_recv recv -#define VCRHook_send send -#if defined( _X360 ) -#define VCRHook_CreateThread CreateThread -#else -#define VCRHook_CreateThread (void*)_beginthreadex -#endif -#define VCRHook_WaitForSingleObject WaitForSingleObject -#define VCRHook_EnterCriticalSection EnterCriticalSection -#define VCRHook_WaitForMultipleObjects( a, b, c, d) WaitForMultipleObjects( a, (const HANDLE *)b, c, d) -#define VCRHook_Time Time -#endif - -#endif // VCRMODE_H diff --git a/public/tier0/vprof.h b/public/tier0/vprof.h deleted file mode 100644 index 31b1128ef..000000000 --- a/public/tier0/vprof.h +++ /dev/null @@ -1,1186 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Real-Time Hierarchical Profiling -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef VPROF_H -#define VPROF_H - -#include "tier0/dbg.h" -#include "tier0/fasttimer.h" -#include "tier0/l2cache.h" -#include "tier0/threadtools.h" - -// VProf is enabled by default in all configurations -except- X360 Retail. -#if !( defined(_X360) && ( defined(_RETAIL) || defined(_CERT) ) ) -#define VPROF_ENABLED -#endif - -#if defined(_X360) && defined(VPROF_ENABLED) -#include "tier0/pmc360.h" -#ifndef USE_PIX -#define VPROF_UNDO_PIX -#undef _PIX_H_ -#undef PIXBeginNamedEvent -#undef PIXEndNamedEvent -#undef PIXSetMarker -#undef PIXNameThread -#define USE_PIX -#include -#undef USE_PIX -#else -#include -#endif -#endif - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4251) -#endif - -// enable this to get detailed nodes beneath budget -// #define VPROF_LEVEL 1 - -// enable this to use pix (360 only) -// #define VPROF_PIX 1 - -#if defined(VPROF_PIX) -#pragma comment( lib, "Xapilibi" ) -#endif - -//----------------------------------------------------------------------------- -// -// Profiling instrumentation macros -// - -#define MAXCOUNTERS 256 - - -#ifdef VPROF_ENABLED - -#define VPROF_VTUNE_GROUP - -#define VPROF( name ) VPROF_(name, 1, VPROF_BUDGETGROUP_OTHER_UNACCOUNTED, false, 0) -#define VPROF_ASSERT_ACCOUNTED( name ) VPROF_(name, 1, VPROF_BUDGETGROUP_OTHER_UNACCOUNTED, true, 0) -#define VPROF_( name, detail, group, bAssertAccounted, budgetFlags ) VPROF_##detail(name,group, bAssertAccounted, budgetFlags) - -#define VPROF_BUDGET( name, group ) VPROF_BUDGET_FLAGS(name, group, BUDGETFLAG_OTHER) -#define VPROF_BUDGET_FLAGS( name, group, flags ) VPROF_(name, 0, group, false, flags) - -#define VPROF_SCOPE_BEGIN( tag ) do { VPROF( tag ) -#define VPROF_SCOPE_END() } while (0) - -#define VPROF_ONLY( expression ) expression - -#define VPROF_ENTER_SCOPE( name ) g_VProfCurrentProfile.EnterScope( name, 1, VPROF_BUDGETGROUP_OTHER_UNACCOUNTED, false, 0 ) -#define VPROF_EXIT_SCOPE() g_VProfCurrentProfile.ExitScope() - -#define VPROF_BUDGET_GROUP_ID_UNACCOUNTED 0 - - -// Budgetgroup flags. These are used with VPROF_BUDGET_FLAGS. -// These control which budget panels the groups show up in. -// If a budget group uses VPROF_BUDGET, it gets the default -// which is BUDGETFLAG_OTHER. -#define BUDGETFLAG_CLIENT (1<<0) // Shows up in the client panel. -#define BUDGETFLAG_SERVER (1<<1) // Shows up in the server panel. -#define BUDGETFLAG_OTHER (1<<2) // Unclassified (the client shows these but the dedicated server doesn't). -#define BUDGETFLAG_HIDDEN (1<<15) -#define BUDGETFLAG_ALL 0xFFFF - - -// NOTE: You can use strings instead of these defines. . they are defined here and added -// in vprof.cpp so that they are always in the same order. -#define VPROF_BUDGETGROUP_OTHER_UNACCOUNTED _T("Unaccounted") -#define VPROF_BUDGETGROUP_WORLD_RENDERING _T("World Rendering") -#define VPROF_BUDGETGROUP_DISPLACEMENT_RENDERING _T("Displacement_Rendering") -#define VPROF_BUDGETGROUP_GAME _T("Game") -#define VPROF_BUDGETGROUP_NPCS _T("NPCs") -#define VPROF_BUDGETGROUP_SERVER_ANIM _T("Server Animation") -#define VPROF_BUDGETGROUP_PHYSICS _T("Physics") -#define VPROF_BUDGETGROUP_STATICPROP_RENDERING _T("Static_Prop_Rendering") -#define VPROF_BUDGETGROUP_MODEL_RENDERING _T("Other_Model_Rendering") -#define VPROF_BUDGETGROUP_BRUSHMODEL_RENDERING _T("Brush_Model_Rendering") -#define VPROF_BUDGETGROUP_SHADOW_RENDERING _T("Shadow_Rendering") -#define VPROF_BUDGETGROUP_DETAILPROP_RENDERING _T("Detail_Prop_Rendering") -#define VPROF_BUDGETGROUP_PARTICLE_RENDERING _T("Particle/Effect_Rendering") -#define VPROF_BUDGETGROUP_ROPES _T("Ropes") -#define VPROF_BUDGETGROUP_DLIGHT_RENDERING _T("Dynamic_Light_Rendering") -#define VPROF_BUDGETGROUP_OTHER_NETWORKING _T("Networking") -#define VPROF_BUDGETGROUP_CLIENT_ANIMATION _T("Client_Animation") -#define VPROF_BUDGETGROUP_OTHER_SOUND _T("Sound") -#define VPROF_BUDGETGROUP_OTHER_VGUI _T("VGUI") -#define VPROF_BUDGETGROUP_OTHER_FILESYSTEM _T("FileSystem") -#define VPROF_BUDGETGROUP_PREDICTION _T("Prediction") -#define VPROF_BUDGETGROUP_INTERPOLATION _T("Interpolation") -#define VPROF_BUDGETGROUP_SWAP_BUFFERS _T("Swap_Buffers") -#define VPROF_BUDGETGROUP_PLAYER _T("Player") -#define VPROF_BUDGETGROUP_OCCLUSION _T("Occlusion") -#define VPROF_BUDGETGROUP_OVERLAYS _T("Overlays") -#define VPROF_BUDGETGROUP_TOOLS _T("Tools") -#define VPROF_BUDGETGROUP_LIGHTCACHE _T("Light_Cache") -#define VPROF_BUDGETGROUP_DISP_HULLTRACES _T("Displacement_Hull_Traces") -#define VPROF_BUDGETGROUP_TEXTURE_CACHE _T("Texture_Cache") -#define VPROF_BUDGETGROUP_PARTICLE_SIMULATION _T("Particle Simulation") -#define VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING _T("Flashlight Shadows") -#define VPROF_BUDGETGROUP_CLIENT_SIM _T("Client Simulation") // think functions, tempents, etc. -#define VPROF_BUDGETGROUP_STEAM _T("Steam") - -#ifdef _X360 -// update flags -#define VPROF_UPDATE_BUDGET 0x01 // send budget data every frame -#define VPROF_UPDATE_TEXTURE_GLOBAL 0x02 // send global texture data every frame -#define VPROF_UPDATE_TEXTURE_PERFRAME 0x04 // send perframe texture data every frame -#endif - -//------------------------------------- - -#ifndef VPROF_LEVEL -#define VPROF_LEVEL 0 -#endif - -#define VPROF_0(name,group,assertAccounted,budgetFlags) CVProfScope VProf_(name, 0, group, assertAccounted, budgetFlags); - -#if VPROF_LEVEL > 0 -#define VPROF_1(name,group,assertAccounted,budgetFlags) CVProfScope VProf_(name, 1, group, assertAccounted, budgetFlags); -#else -#define VPROF_1(name,group,assertAccounted,budgetFlags) ((void)0) -#endif - -#if VPROF_LEVEL > 1 -#define VPROF_2(name,group,assertAccounted,budgetFlags) CVProfScope VProf_(name, 2, group, assertAccounted, budgetFlags); -#else -#define VPROF_2(name,group,assertAccounted,budgetFlags) ((void)0) -#endif - -#if VPROF_LEVEL > 2 -#define VPROF_3(name,group,assertAccounted,budgetFlags) CVProfScope VProf_(name, 3, group, assertAccounted, budgetFlags); -#else -#define VPROF_3(name,group,assertAccounted,budgetFlags) ((void)0) -#endif - -#if VPROF_LEVEL > 3 -#define VPROF_4(name,group,assertAccounted,budgetFlags) CVProfScope VProf_(name, 4, group, assertAccounted, budgetFlags); -#else -#define VPROF_4(name,group,assertAccounted,budgetFlags) ((void)0) -#endif - -//------------------------------------- - -#define VPROF_INCREMENT_COUNTER(name,amount) do { static CVProfCounter _counter( name ); _counter.Increment( amount ); } while( 0 ) -#define VPROF_INCREMENT_GROUP_COUNTER(name,group,amount) do { static CVProfCounter _counter( name, group ); _counter.Increment( amount ); } while( 0 ) - -#else - -#define VPROF( name ) ((void)0) -#define VPROF_ASSERT_ACCOUNTED( name ) ((void)0) -#define VPROF_( name, detail, group, bAssertAccounted ) ((void)0) -#define VPROF_BUDGET( name, group ) ((void)0) -#define VPROF_BUDGET_FLAGS( name, group, flags ) ((void)0) - -#define VPROF_SCOPE_BEGIN( tag ) do { -#define VPROF_SCOPE_END() } while (0) - -#define VPROF_ONLY( expression ) ((void)0) - -#define VPROF_ENTER_SCOPE( name ) -#define VPROF_EXIT_SCOPE() - -#define VPROF_INCREMENT_COUNTER(name,amount) ((void)0) -#define VPROF_INCREMENT_GROUP_COUNTER(name,group,amount) ((void)0) - -#endif - -//----------------------------------------------------------------------------- - -#ifdef VPROF_ENABLED - -//----------------------------------------------------------------------------- -// -// A node in the call graph hierarchy -// - -class DBG_CLASS CVProfNode -{ -friend class CVProfRecorder; -friend class CVProfile; - -public: - CVProfNode( const tchar * pszName, int detailLevel, CVProfNode *pParent, const tchar *pBudgetGroupName, int budgetFlags ); - ~CVProfNode(); - - CVProfNode *GetSubNode( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName, int budgetFlags ); - CVProfNode *GetSubNode( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName ); - CVProfNode *GetParent(); - CVProfNode *GetSibling(); - CVProfNode *GetPrevSibling(); - CVProfNode *GetChild(); - - void MarkFrame(); - void ResetPeak(); - - void Pause(); - void Resume(); - void Reset(); - - void EnterScope(); - bool ExitScope(); - - const tchar *GetName(); - - int GetBudgetGroupID() - { - return m_BudgetGroupID; - } - - // Only used by the record/playback stuff. - void SetBudgetGroupID( int id ) - { - m_BudgetGroupID = id; - } - - int GetCurCalls(); - double GetCurTime(); - int GetPrevCalls(); - double GetPrevTime(); - int GetTotalCalls(); - double GetTotalTime(); - double GetPeakTime(); - - double GetCurTimeLessChildren(); - double GetPrevTimeLessChildren(); - double GetTotalTimeLessChildren(); - - int GetPrevL2CacheMissLessChildren(); - int GetPrevLoadHitStoreLessChildren(); - - void ClearPrevTime(); - - int GetL2CacheMisses(); - - // Not used in the common case... - void SetCurFrameTime( unsigned long milliseconds ); - - void SetClientData( int iClientData ) { m_iClientData = iClientData; } - int GetClientData() const { return m_iClientData; } - -#ifdef DBGFLAG_VALIDATE - void Validate( CValidator &validator, tchar *pchName ); // Validate our internal structures -#endif // DBGFLAG_VALIDATE - - -// Used by vprof record/playback. -private: - - void SetUniqueNodeID( int id ) - { - m_iUniqueNodeID = id; - } - - int GetUniqueNodeID() const - { - return m_iUniqueNodeID; - } - - static int s_iCurrentUniqueNodeID; - - -private: - const tchar *m_pszName; - CFastTimer m_Timer; - - // L2 Cache data. - int m_iPrevL2CacheMiss; - int m_iCurL2CacheMiss; - int m_iTotalL2CacheMiss; - -#ifndef _X360 - // L2 Cache data. - CL2Cache m_L2Cache; -#else // 360: - - unsigned int m_iBitFlags; // see enum below for settings - CPMCData m_PMCData; - int m_iPrevLoadHitStores; - int m_iCurLoadHitStores; - int m_iTotalLoadHitStores; - - public: - enum FlagBits - { - kRecordL2 = 0x01, - kCPUTrace = 0x02, ///< cause a PIX trace inside this node. - }; - // call w/ true to enable L2 and LHS recording; false to turn it off - inline void EnableL2andLHS(bool enable) - { - if (enable) - m_iBitFlags |= kRecordL2; - else - m_iBitFlags &= (~kRecordL2); - } - - inline bool IsL2andLHSEnabled( void ) - { - return (m_iBitFlags & kRecordL2) != 0; - } - - int GetLoadHitStores(); - - private: - -#endif - - int m_nRecursions; - - unsigned m_nCurFrameCalls; - CCycleCount m_CurFrameTime; - - unsigned m_nPrevFrameCalls; - CCycleCount m_PrevFrameTime; - - unsigned m_nTotalCalls; - CCycleCount m_TotalTime; - - CCycleCount m_PeakTime; - - CVProfNode *m_pParent; - CVProfNode *m_pChild; - CVProfNode *m_pSibling; - - int m_BudgetGroupID; - - int m_iClientData; - int m_iUniqueNodeID; -}; - -//----------------------------------------------------------------------------- -// -// Coordinator and root node of the profile hierarchy tree -// - -enum VProfReportType_t -{ - VPRT_SUMMARY = ( 1 << 0 ), - VPRT_HIERARCHY = ( 1 << 1 ), - VPRT_HIERARCHY_TIME_PER_FRAME_AND_COUNT_ONLY = ( 1 << 2 ), - VPRT_LIST_BY_TIME = ( 1 << 3 ), - VPRT_LIST_BY_TIME_LESS_CHILDREN = ( 1 << 4 ), - VPRT_LIST_BY_AVG_TIME = ( 1 << 5 ), - VPRT_LIST_BY_AVG_TIME_LESS_CHILDREN = ( 1 << 6 ), - VPRT_LIST_BY_PEAK_TIME = ( 1 << 7 ), - VPRT_LIST_BY_PEAK_OVER_AVERAGE = ( 1 << 8 ), - VPRT_LIST_TOP_ITEMS_ONLY = ( 1 << 9 ), - - VPRT_FULL = (0xffffffff & ~(VPRT_HIERARCHY_TIME_PER_FRAME_AND_COUNT_ONLY|VPRT_LIST_TOP_ITEMS_ONLY)), -}; - -enum CounterGroup_t -{ - COUNTER_GROUP_DEFAULT=0, - COUNTER_GROUP_NO_RESET, // The engine doesn't reset these counters. Usually, they are used - // like global variables that can be accessed across modules. - COUNTER_GROUP_TEXTURE_GLOBAL, // Global texture usage counters (totals for what is currently in memory). - COUNTER_GROUP_TEXTURE_PER_FRAME // Per-frame texture usage counters. -}; - -class DBG_CLASS CVProfile -{ -public: - CVProfile(); - ~CVProfile(); - - void Term(); - - // - // Runtime operations - // - - void Start(); - void Stop(); - -#ifdef _X360 - enum VXConsoleReportMode_t - { - VXCONSOLE_REPORT_TIME = 0, - VXCONSOLE_REPORT_L2CACHE_MISSES, - VXCONSOLE_REPORT_LOAD_HIT_STORE, - - VXCONSOLE_REPORT_COUNT, - }; - - // piggyback to profiler - void VXProfileStart(); - void VXProfileUpdate(); - void VXEnableUpdateMode(int event, bool bEnable); - - void PMCDisableAllNodes(CVProfNode *pStartNode = NULL); ///< turn off l2 and lhs recording for everywhere - bool PMCEnableL2Upon(const tchar *pszNodeName, bool bRecursive = false); ///< enable l2 and lhs recording for one given node - bool PMCDisableL2Upon(const tchar *pszNodeName, bool bRecursive = false); ///< enable l2 and lhs recording for one given node - - void DumpEnabledPMCNodes( void ); - - void VXConsoleReportMode( VXConsoleReportMode_t mode ); - void VXConsoleReportScale( VXConsoleReportMode_t mode, float flScale ); - - // the CPU trace mode is actually a small state machine; it can be off, primed for - // single capture, primed for everything-in-a-frame capture, or currently in everything-in-a-frame - // capture. - enum CPUTraceState - { - kDisabled, - kFirstHitNode, /// < record from the first time we hit the node until that node ends - kAllNodesInFrame_WaitingForMark, ///< we're going to record all the times a node is hit in a frame, but are waiting for the frame to start - kAllNodesInFrame_Recording, ///< we're recording all hits on a node this frame. - }; - - /// Global switch to turn CPU tracing on or off at all. The idea is you set up a node first, - /// then trigger tracing by throwing this to true. It'll reset back to false after the trace - /// happens. - inline CPUTraceState GetCPUTraceMode(); - inline void SetCPUTraceEnabled(CPUTraceState enabled); - inline void IncrementMultiTraceIndex(); /// tick up the counter that gets appended to the multi-per-frame traces - inline unsigned int GetMultiTraceIndex(); /// return the counter - void CPUTraceDisableAllNodes(CVProfNode *pStartNode = NULL); //< disable the cpu trace flag wherever it may be - CVProfNode *CPUTraceEnableForNode(const tchar *pszNodeName); ///< enable cpu trace on this node only, disabling it wherever else it may be on. - CVProfNode *CPUTraceGetEnabledNode(CVProfNode *pStartNode = NULL); ///< return the node enabled for CPU tracing, or NULL. - const char *GetCPUTraceFilename(); ///< get the filename the trace should write into. - const char *SetCPUTraceFilename(const char *filename); ///< set the filename the trace should write into. (don't specify the extension; I'll do that.) - -#endif - - void EnterScope( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted ); - void EnterScope( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted, int budgetFlags ); - void ExitScope(); - - void MarkFrame(); - void ResetPeaks(); - - void Pause(); - void Resume(); - void Reset(); - - bool IsEnabled() const; - int GetDetailLevel() const; - - bool AtRoot() const; - - // - // Queries - // - -#ifdef VPROF_VTUNE_GROUP -# define MAX_GROUP_STACK_DEPTH 1024 - - void EnableVTuneGroup( const tchar *pGroupName ) - { - m_nVTuneGroupID = BudgetGroupNameToBudgetGroupID( pGroupName ); - m_bVTuneGroupEnabled = true; - } - void DisableVTuneGroup( void ) - { - m_bVTuneGroupEnabled = false; - } - - inline void PushGroup( int nGroupID ); - inline void PopGroup( void ); -#endif - - int NumFramesSampled() { return m_nFrames; } - double GetPeakFrameTime(); - double GetTotalTimeSampled(); - double GetTimeLastFrame(); - - CVProfNode *GetRoot(); - CVProfNode *FindNode( CVProfNode *pStartNode, const tchar *pszNode ); - - void OutputReport( int type = VPRT_FULL, const tchar *pszStartNode = NULL, int budgetGroupID = -1 ); - - const tchar *GetBudgetGroupName( int budgetGroupID ); - int GetBudgetGroupFlags( int budgetGroupID ) const; // Returns a combination of BUDGETFLAG_ defines. - int GetNumBudgetGroups( void ); - void GetBudgetGroupColor( int budgetGroupID, int &r, int &g, int &b, int &a ); - int BudgetGroupNameToBudgetGroupID( const tchar *pBudgetGroupName ); - int BudgetGroupNameToBudgetGroupID( const tchar *pBudgetGroupName, int budgetFlagsToORIn ); - void RegisterNumBudgetGroupsChangedCallBack( void (*pCallBack)(void) ); - - int BudgetGroupNameToBudgetGroupIDNoCreate( const tchar *pBudgetGroupName ) { return FindBudgetGroupName( pBudgetGroupName ); } - - void HideBudgetGroup( int budgetGroupID, bool bHide = true ); - void HideBudgetGroup( const char *pszName, bool bHide = true ) { HideBudgetGroup( BudgetGroupNameToBudgetGroupID( pszName), bHide ); } - - int *FindOrCreateCounter( const tchar *pName, CounterGroup_t eCounterGroup=COUNTER_GROUP_DEFAULT ); - void ResetCounters( CounterGroup_t eCounterGroup ); - - int GetNumCounters( void ) const; - - const tchar *GetCounterName( int index ) const; - int GetCounterValue( int index ) const; - const tchar *GetCounterNameAndValue( int index, int &val ) const; - CounterGroup_t GetCounterGroup( int index ) const; - - // Performance monitoring events. - void PMEInitialized( bool bInit ) { m_bPMEInit = bInit; } - void PMEEnable( bool bEnable ) { m_bPMEEnabled = bEnable; } - -#ifndef _X360 - bool UsePME( void ) { return ( m_bPMEInit && m_bPMEEnabled ); } -#else - bool UsePME( void ) { return ( CPMCData::IsInitialized() && m_bPMEEnabled ); } -#endif - -#ifdef DBGFLAG_VALIDATE - void Validate( CValidator &validator, tchar *pchName ); // Validate our internal structures -#endif // DBGFLAG_VALIDATE - -protected: - - void FreeNodes_R( CVProfNode *pNode ); - -#ifdef VPROF_VTUNE_GROUP - bool VTuneGroupEnabled() - { - return m_bVTuneGroupEnabled; - } - int VTuneGroupID() - { - return m_nVTuneGroupID; - } -#endif - - void SumTimes( const tchar *pszStartNode, int budgetGroupID ); - void SumTimes( CVProfNode *pNode, int budgetGroupID ); - void DumpNodes( CVProfNode *pNode, int indent, bool bAverageAndCountOnly ); - int FindBudgetGroupName( const tchar *pBudgetGroupName ); - int AddBudgetGroupName( const tchar *pBudgetGroupName, int budgetFlags ); - -#ifdef VPROF_VTUNE_GROUP - bool m_bVTuneGroupEnabled; - int m_nVTuneGroupID; - int m_GroupIDStack[MAX_GROUP_STACK_DEPTH]; - int m_GroupIDStackDepth; -#endif - int m_enabled; - bool m_fAtRoot; // tracked for efficiency of the "not profiling" case - CVProfNode *m_pCurNode; - CVProfNode m_Root; - int m_nFrames; - int m_ProfileDetailLevel; - int m_pausedEnabledDepth; - - class CBudgetGroup - { - public: - tchar *m_pName; - int m_BudgetFlags; - }; - - CBudgetGroup *m_pBudgetGroups; - int m_nBudgetGroupNamesAllocated; - int m_nBudgetGroupNames; - void (*m_pNumBudgetGroupsChangedCallBack)(void); - - // Performance monitoring events. - bool m_bPMEInit; - bool m_bPMEEnabled; - - int m_Counters[MAXCOUNTERS]; - char m_CounterGroups[MAXCOUNTERS]; // (These are CounterGroup_t's). - tchar *m_CounterNames[MAXCOUNTERS]; - int m_NumCounters; - -#ifdef _X360 - int m_UpdateMode; - CPUTraceState m_iCPUTraceEnabled; - char m_CPUTraceFilename[128]; - unsigned int m_iSuccessiveTraceIndex; - VXConsoleReportMode_t m_ReportMode; - float m_pReportScale[VXCONSOLE_REPORT_COUNT]; -#endif -}; - -//------------------------------------- - -DBG_INTERFACE CVProfile g_VProfCurrentProfile; - -//----------------------------------------------------------------------------- - -#ifdef VPROF_VTUNE_GROUP -inline void CVProfile::PushGroup( int nGroupID ) -{ - // There is always at least one item on the stack since we force - // the first element to be VPROF_BUDGETGROUP_OTHER_UNACCOUNTED. - Assert( m_GroupIDStackDepth > 0 ); - Assert( m_GroupIDStackDepth < MAX_GROUP_STACK_DEPTH ); - m_GroupIDStack[m_GroupIDStackDepth] = nGroupID; - m_GroupIDStackDepth++; - if( m_GroupIDStack[m_GroupIDStackDepth-2] != nGroupID && - VTuneGroupEnabled() && - nGroupID == VTuneGroupID() ) - { - vtune( true ); - } -} -#endif // VPROF_VTUNE_GROUP - -#ifdef VPROF_VTUNE_GROUP -inline void CVProfile::PopGroup( void ) -{ - m_GroupIDStackDepth--; - // There is always at least one item on the stack since we force - // the first element to be VPROF_BUDGETGROUP_OTHER_UNACCOUNTED. - Assert( m_GroupIDStackDepth > 0 ); - if( m_GroupIDStack[m_GroupIDStackDepth] != m_GroupIDStack[m_GroupIDStackDepth+1] && - VTuneGroupEnabled() && - m_GroupIDStack[m_GroupIDStackDepth+1] == VTuneGroupID() ) - { - vtune( false ); - } -} -#endif // VPROF_VTUNE_GROUP - -//----------------------------------------------------------------------------- - -class CVProfScope -{ -public: - CVProfScope( const tchar * pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted, int budgetFlags ); - ~CVProfScope(); -}; - -//----------------------------------------------------------------------------- -// -// CVProfNode, inline methods -// - -inline CVProfNode::CVProfNode( const tchar * pszName, int detailLevel, CVProfNode *pParent, const tchar *pBudgetGroupName, int budgetFlags ) - : m_pszName( pszName ), - m_nRecursions( 0 ), - m_nCurFrameCalls( 0 ), - m_nPrevFrameCalls( 0 ), - m_pParent( pParent ), - m_pChild( NULL ), - m_pSibling( NULL ), - m_iClientData( -1 ) -#ifdef _X360 - , m_iBitFlags( 0 ) -#endif -{ - m_iUniqueNodeID = s_iCurrentUniqueNodeID++; - - if ( m_iUniqueNodeID > 0 ) - { - m_BudgetGroupID = g_VProfCurrentProfile.BudgetGroupNameToBudgetGroupID( pBudgetGroupName, budgetFlags ); - } - else - { - m_BudgetGroupID = 0; // "m_Root" can't call BudgetGroupNameToBudgetGroupID because g_VProfCurrentProfile not yet initialized - } - - Reset(); - - if( m_pParent && ( m_BudgetGroupID == VPROF_BUDGET_GROUP_ID_UNACCOUNTED ) ) - { - m_BudgetGroupID = m_pParent->GetBudgetGroupID(); - } -} - - -//------------------------------------- - -inline CVProfNode *CVProfNode::GetParent() -{ - Assert( m_pParent ); - return m_pParent; -} - -//------------------------------------- - -inline CVProfNode *CVProfNode::GetSibling() -{ - return m_pSibling; -} - -//------------------------------------- -// Hacky way to the previous sibling, only used from vprof panel at the moment, -// so it didn't seem like it was worth the memory waste to add the reverse -// link per node. - -inline CVProfNode *CVProfNode::GetPrevSibling() -{ - CVProfNode* p = GetParent(); - - if(!p) - return NULL; - - CVProfNode* s; - for( s = p->GetChild(); - s && ( s->GetSibling() != this ); - s = s->GetSibling() ) - ; - - return s; -} - -//------------------------------------- - -inline CVProfNode *CVProfNode::GetChild() -{ - return m_pChild; -} - -//------------------------------------- - -inline const tchar *CVProfNode::GetName() -{ - Assert( m_pszName ); - return m_pszName; -} - -//------------------------------------- - -inline int CVProfNode::GetTotalCalls() -{ - return m_nTotalCalls; -} - -//------------------------------------- - -inline double CVProfNode::GetTotalTime() -{ - return m_TotalTime.GetMillisecondsF(); -} - -//------------------------------------- - -inline int CVProfNode::GetCurCalls() -{ - return m_nCurFrameCalls; -} - -//------------------------------------- - -inline double CVProfNode::GetCurTime() -{ - return m_CurFrameTime.GetMillisecondsF(); -} - -//------------------------------------- - -inline int CVProfNode::GetPrevCalls() -{ - return m_nPrevFrameCalls; -} - -//------------------------------------- - -inline double CVProfNode::GetPrevTime() -{ - return m_PrevFrameTime.GetMillisecondsF(); -} - -//------------------------------------- - -inline double CVProfNode::GetPeakTime() -{ - return m_PeakTime.GetMillisecondsF(); -} - -//------------------------------------- - -inline double CVProfNode::GetTotalTimeLessChildren() -{ - double result = GetTotalTime(); - CVProfNode *pChild = GetChild(); - while ( pChild ) - { - result -= pChild->GetTotalTime(); - pChild = pChild->GetSibling(); - } - return result; -} - -//------------------------------------- - -inline double CVProfNode::GetCurTimeLessChildren() -{ - double result = GetCurTime(); - CVProfNode *pChild = GetChild(); - while ( pChild ) - { - result -= pChild->GetCurTime(); - pChild = pChild->GetSibling(); - } - return result; -} - -inline double CVProfNode::GetPrevTimeLessChildren() -{ - double result = GetPrevTime(); - CVProfNode *pChild = GetChild(); - while ( pChild ) - { - result -= pChild->GetPrevTime(); - pChild = pChild->GetSibling(); - } - return result; -} - -//----------------------------------------------------------------------------- -inline int CVProfNode::GetPrevL2CacheMissLessChildren() -{ - int result = m_iPrevL2CacheMiss; - CVProfNode *pChild = GetChild(); - while ( pChild ) - { - result -= pChild->m_iPrevL2CacheMiss; - pChild = pChild->GetSibling(); - } - return result; -} - -//----------------------------------------------------------------------------- -inline int CVProfNode::GetPrevLoadHitStoreLessChildren() -{ -#ifndef _X360 - return 0; -#else - int result = m_iPrevLoadHitStores; - CVProfNode *pChild = GetChild(); - while ( pChild ) - { - result -= pChild->m_iPrevLoadHitStores; - pChild = pChild->GetSibling(); - } - return result; -#endif -} - - -//----------------------------------------------------------------------------- -inline void CVProfNode::ClearPrevTime() -{ - m_PrevFrameTime.Init(); -} - -//----------------------------------------------------------------------------- -inline int CVProfNode::GetL2CacheMisses( void ) -{ -#ifndef _X360 - return m_L2Cache.GetL2CacheMisses(); -#else - return m_iTotalL2CacheMiss; -#endif -} - -#ifdef _X360 -inline int CVProfNode::GetLoadHitStores( void ) -{ - return m_iTotalLoadHitStores; -} -#endif - -//----------------------------------------------------------------------------- -// -// CVProfile, inline methods -// - -//------------------------------------- - -inline bool CVProfile::IsEnabled() const -{ - return ( m_enabled != 0 ); -} - -//------------------------------------- - -inline int CVProfile::GetDetailLevel() const -{ - return m_ProfileDetailLevel; -} - - -//------------------------------------- - -inline bool CVProfile::AtRoot() const -{ - return m_fAtRoot; -} - -//------------------------------------- - -inline void CVProfile::Start() -{ - if ( ++m_enabled == 1 ) - { - m_Root.EnterScope(); -#ifdef _X360 - VXProfileStart(); - CPMCData::InitializeOnceProgramWide(); -#endif - } -} - -//------------------------------------- - -inline void CVProfile::Stop() -{ - if ( --m_enabled == 0 ) - m_Root.ExitScope(); -} - -//------------------------------------- - -inline void CVProfile::EnterScope( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted, int budgetFlags ) -{ - if ( ( m_enabled != 0 || !m_fAtRoot ) && ThreadInMainThread() ) // if became disabled, need to unwind back to root before stopping - { - // Only account for vprof stuff on the primary thread. - //if( !Plat_IsPrimaryThread() ) - // return; - - if ( pszName != m_pCurNode->GetName() ) - { - m_pCurNode = m_pCurNode->GetSubNode( pszName, detailLevel, pBudgetGroupName, budgetFlags ); - } - m_pBudgetGroups[m_pCurNode->GetBudgetGroupID()].m_BudgetFlags |= budgetFlags; - -#if defined( _DEBUG ) && !defined( _X360 ) - // 360 doesn't want this to allow tier0 debug/release .def files to match - if ( bAssertAccounted ) - { - // FIXME - AssertOnce( m_pCurNode->GetBudgetGroupID() != 0 ); - } -#endif - m_pCurNode->EnterScope(); - m_fAtRoot = false; - } -#if defined(_X360) && defined(VPROF_PIX) - if ( m_pCurNode->GetBudgetGroupID() != VPROF_BUDGET_GROUP_ID_UNACCOUNTED ) - PIXBeginNamedEvent( 0, pszName ); -#endif -} - -inline void CVProfile::EnterScope( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted ) -{ - EnterScope( pszName, detailLevel, pBudgetGroupName, bAssertAccounted, BUDGETFLAG_OTHER ); -} - -//------------------------------------- - -inline void CVProfile::ExitScope() -{ -#if defined(_X360) && defined(VPROF_PIX) -#ifdef PIXBeginNamedEvent -#error -#endif - if ( m_pCurNode->GetBudgetGroupID() != VPROF_BUDGET_GROUP_ID_UNACCOUNTED ) - PIXEndNamedEvent(); -#endif - if ( ( !m_fAtRoot || m_enabled != 0 ) && ThreadInMainThread() ) - { - // Only account for vprof stuff on the primary thread. - //if( !Plat_IsPrimaryThread() ) - // return; - - // ExitScope will indicate whether we should back up to our parent (we may - // be profiling a recursive function) - if (m_pCurNode->ExitScope()) - { - m_pCurNode = m_pCurNode->GetParent(); - } - m_fAtRoot = ( m_pCurNode == &m_Root ); - } -} - -//------------------------------------- - -inline void CVProfile::Pause() -{ - m_pausedEnabledDepth = m_enabled; - m_enabled = 0; - if ( !AtRoot() ) - m_Root.Pause(); -} - -//------------------------------------- - -inline void CVProfile::Resume() -{ - m_enabled = m_pausedEnabledDepth; - if ( !AtRoot() ) - m_Root.Resume(); -} - -//------------------------------------- - -inline void CVProfile::Reset() -{ - m_Root.Reset(); - m_nFrames = 0; -} - -//------------------------------------- - -inline void CVProfile::ResetPeaks() -{ - m_Root.ResetPeak(); -} - -//------------------------------------- - -inline void CVProfile::MarkFrame() -{ - if ( m_enabled ) - { - ++m_nFrames; - m_Root.ExitScope(); - m_Root.MarkFrame(); - m_Root.EnterScope(); - -#ifdef _X360 - // update the CPU trace state machine if enabled - switch ( GetCPUTraceMode() ) - { - case kAllNodesInFrame_WaitingForMark: - // mark! Start recording a zillion traces. - m_iCPUTraceEnabled = kAllNodesInFrame_Recording; - - break; - case kAllNodesInFrame_Recording: - // end of frame. stop recording. - m_iCPUTraceEnabled = kDisabled; - Msg("Frame ended. Recording no more CPU traces\n"); - - break; - - default: - // no default - break; - } -#endif - } -} - -//------------------------------------- - -inline double CVProfile::GetTotalTimeSampled() -{ - return m_Root.GetTotalTime(); -} - -//------------------------------------- - -inline double CVProfile::GetPeakFrameTime() -{ - return m_Root.GetPeakTime(); -} - -//------------------------------------- - -inline double CVProfile::GetTimeLastFrame() -{ - return m_Root.GetCurTime(); -} - -//------------------------------------- - -inline CVProfNode *CVProfile::GetRoot() -{ - return &m_Root; -} - - -inline const tchar *CVProfile::GetBudgetGroupName( int budgetGroupID ) -{ - Assert( budgetGroupID >= 0 && budgetGroupID < m_nBudgetGroupNames ); - return m_pBudgetGroups[budgetGroupID].m_pName; -} - -inline int CVProfile::GetBudgetGroupFlags( int budgetGroupID ) const -{ - Assert( budgetGroupID >= 0 && budgetGroupID < m_nBudgetGroupNames ); - return m_pBudgetGroups[budgetGroupID].m_BudgetFlags; -} - -#ifdef _X360 - -inline CVProfile::CPUTraceState CVProfile::GetCPUTraceMode() -{ - return m_iCPUTraceEnabled; -} - -inline void CVProfile::SetCPUTraceEnabled(CPUTraceState enabled) -{ - m_iCPUTraceEnabled = enabled; -} - -inline void CVProfile::IncrementMultiTraceIndex() -{ - ++m_iSuccessiveTraceIndex; -} - -inline unsigned int CVProfile::GetMultiTraceIndex() -{ - return m_iSuccessiveTraceIndex; -} - -#endif - - -//----------------------------------------------------------------------------- - -inline CVProfScope::CVProfScope( const tchar * pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted, int budgetFlags ) -{ - g_VProfCurrentProfile.EnterScope( pszName, detailLevel, pBudgetGroupName, bAssertAccounted, budgetFlags ); -} - -//------------------------------------- - -inline CVProfScope::~CVProfScope() -{ - g_VProfCurrentProfile.ExitScope(); -} - -class CVProfCounter -{ -public: - CVProfCounter( const tchar *pName, CounterGroup_t group=COUNTER_GROUP_DEFAULT ) - { - m_pCounter = g_VProfCurrentProfile.FindOrCreateCounter( pName, group ); - Assert( m_pCounter ); - } - ~CVProfCounter() - { - } - void Increment( int val ) - { - Assert( m_pCounter ); - *m_pCounter += val; - } -private: - int *m_pCounter; -}; - -#endif - -#ifdef VPROF_UNDO_PIX -#undef USE_PIX -#undef _PIX_H_ -#undef PIXBeginNamedEvent -#undef PIXEndNamedEvent -#undef PIXSetMarker -#undef PIXNameThread -#include -#endif - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#endif - -//============================================================================= diff --git a/public/tier0/wchartypes.h b/public/tier0/wchartypes.h deleted file mode 100644 index 71d63e47b..000000000 --- a/public/tier0/wchartypes.h +++ /dev/null @@ -1,104 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: All of our code is completely Unicode. Instead of char, you should -// use wchar, uint8, or char8, as explained below. -// -// $NoKeywords: $ -//=============================================================================// - - -#ifndef WCHARTYPES_H -#define WCHARTYPES_H -#ifdef _WIN32 -#pragma once -#endif - -#ifdef _INC_TCHAR -#error ("Must include tier0 type headers before tchar.h") -#endif - -// Temporarily turn off Valve defines -#include "tier0/valve_off.h" - -#if defined _WIN32 && !defined _WCHAR_T_DEFINED -typedef unsigned short wchar_t; -#define _WCHAR_T_DEFINED -#elif (defined _LINUX || defined __APPLE__) && !defined __WCHAR_TYPE__ -typedef unsigned short wchar_t; -#define __WCHAR_TYPE__ -#endif - -// char8 -// char8 is equivalent to char, and should be used when you really need a char -// (for example, when calling an external function that's declared to take -// chars). -typedef char char8; - -// uint8 -// uint8 is equivalent to byte (but is preferred over byte for clarity). Use this -// whenever you mean a byte (for example, one byte of a network packet). -typedef unsigned char uint8; -typedef unsigned char BYTE; -typedef unsigned char byte; - -// wchar -// wchar is a single character of text (currently 16 bits, as all of our text is -// Unicode). Use this whenever you mean a piece of text (for example, in a string). -typedef wchar_t wchar; -//typedef char wchar; - -// __WFILE__ -// This is a Unicode version of __FILE__ -#define WIDEN2(x) L ## x -#define WIDEN(x) WIDEN2(x) -#define __WFILE__ WIDEN(__FILE__) - -#ifdef STEAM -#ifndef _UNICODE -#define FORCED_UNICODE -#endif -#define _UNICODE -#endif - -#ifdef _WIN32 -#include -#else -#define _tcsstr strstr -#define _tcsicmp stricmp -#define _tcscmp strcmp -#define _tcscpy strcpy -#define _tcsncpy strncpy -#define _tcsrchr strrchr -#define _tcslen strlen -#define _tfopen fopen -#define _stprintf sprintf -#define _ftprintf fprintf -#define _vsntprintf _vsnprintf -#define _tprintf printf -#define _sntprintf _snprintf -#define _T(s) s -#endif - -#if defined(_UNICODE) -typedef wchar tchar; -#define tstring wstring -#define __TFILE__ __WFILE__ -#define TCHAR_IS_WCHAR -#else -typedef char tchar; -#define tstring string -#define __TFILE__ __FILE__ -#define TCHAR_IS_CHAR -#endif - -#ifdef FORCED_UNICODE -#undef _UNICODE -#endif - -// Turn valve defines back on -#include "tier0/valve_on.h" - - -#endif // WCHARTYPES - - diff --git a/public/tier0/xbox_codeline_defines.h b/public/tier0/xbox_codeline_defines.h deleted file mode 100644 index 3f7b544ad..000000000 --- a/public/tier0/xbox_codeline_defines.h +++ /dev/null @@ -1,16 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef XBOX_CODELINE_DEFINES_H -#define XBOX_CODELINE_DEFINES_H - - -// In the regular src_main codeline, we leave this out. -//#define IN_XBOX_CODELINE - - -#endif // XBOX_CODELINE_DEFINES_H diff --git a/public/tier1/CommandBuffer.h b/public/tier1/CommandBuffer.h deleted file mode 100644 index a918963a2..000000000 --- a/public/tier1/CommandBuffer.h +++ /dev/null @@ -1,160 +0,0 @@ -//===== Copyright 1996-2006, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//===========================================================================// - - -#ifndef COMMANDBUFFER_H -#define COMMANDBUFFER_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/utllinkedlist.h" -#include "tier1/convar.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class CUtlBuffer; - - -//----------------------------------------------------------------------------- -// Invalid command handle -//----------------------------------------------------------------------------- -typedef int CommandHandle_t; -enum -{ - COMMAND_BUFFER_INVALID_COMMAND_HANDLE = 0 -}; - - -//----------------------------------------------------------------------------- -// A command buffer class- a queue of argc/argv based commands associated -// with a particular time -//----------------------------------------------------------------------------- -class CCommandBuffer -{ -public: - // Constructor, destructor - CCommandBuffer( ); - ~CCommandBuffer(); - - // Inserts text into the command buffer - bool AddText( const char *pText, int nTickDelay = 0 ); - - // Used to iterate over all commands appropriate for the current time - void BeginProcessingCommands( int nDeltaTicks ); - bool DequeueNextCommand( ); - int DequeueNextCommand( const char **& ppArgv ); - int ArgC() const; - const char **ArgV() const; - const char *ArgS() const; // All args that occur after the 0th arg, in string form - const char *GetCommandString() const; // The entire command in string form, including the 0th arg - const CCommand& GetCommand() const; - void EndProcessingCommands(); - - // Are we in the middle of processing commands? - bool IsProcessingCommands(); - - // Delays all queued commands to execute at a later time - void DelayAllQueuedCommands( int nTickDelay ); - - // Indicates how long to delay when encoutering a 'wait' command - void SetWaitDelayTime( int nTickDelay ); - - // Returns a handle to the next command to process - // (useful when inserting commands into the buffer during processing - // of commands to force immediate execution of those commands, - // most relevantly, to implement a feature where you stream a file - // worth of commands into the buffer, where the file size is too large - // to entirely contain in the buffer). - CommandHandle_t GetNextCommandHandle(); - - // Specifies a max limit of the args buffer. For unittesting. Size == 0 means use default - void LimitArgumentBufferSize( int nSize ); - -private: - enum - { - ARGS_BUFFER_LENGTH = 8192, - }; - - struct Command_t - { - int m_nTick; - int m_nFirstArgS; - int m_nBufferSize; - }; - - // Insert a command into the command queue at the appropriate time - void InsertCommandAtAppropriateTime( int hCommand ); - - // Insert a command into the command queue - // Only happens if it's inserted while processing other commands - void InsertImmediateCommand( int hCommand ); - - // Insert a command into the command queue - bool InsertCommand( const char *pArgS, int nCommandSize, int nTick ); - - // Returns the length of the next command, as well as the offset to the next command - void GetNextCommandLength( const char *pText, int nMaxLen, int *pCommandLength, int *pNextCommandOffset ); - - // Compacts the command buffer - void Compact(); - - // Parses argv0 out of the buffer - bool ParseArgV0( CUtlBuffer &buf, char *pArgv0, int nMaxLen, const char **pArgs ); - - char m_pArgSBuffer[ ARGS_BUFFER_LENGTH ]; - int m_nLastUsedArgSSize; - int m_nArgSBufferSize; - CUtlFixedLinkedList< Command_t > m_Commands; - int m_nCurrentTick; - int m_nLastTickToProcess; - int m_nWaitDelayTicks; - int m_hNextCommand; - int m_nMaxArgSBufferLength; - bool m_bIsProcessingCommands; - - // NOTE: This is here to avoid the pointers returned by DequeueNextCommand - // to become invalid by calling AddText. Is there a way we can avoid the memcpy? - CCommand m_CurrentCommand; -}; - - -//----------------------------------------------------------------------------- -// Returns the next command -//----------------------------------------------------------------------------- -inline int CCommandBuffer::ArgC() const -{ - return m_CurrentCommand.ArgC(); -} - -inline const char **CCommandBuffer::ArgV() const -{ - return m_CurrentCommand.ArgV(); -} - -inline const char *CCommandBuffer::ArgS() const -{ - return m_CurrentCommand.ArgS(); -} - -inline const char *CCommandBuffer::GetCommandString() const -{ - return m_CurrentCommand.GetCommandString(); -} - -inline const CCommand& CCommandBuffer::GetCommand() const -{ - return m_CurrentCommand; -} - -#endif // COMMANDBUFFER_H diff --git a/public/tier1/KeyValues.h b/public/tier1/KeyValues.h deleted file mode 100644 index a617367b8..000000000 --- a/public/tier1/KeyValues.h +++ /dev/null @@ -1,357 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef KEYVALUES_H -#define KEYVALUES_H - -#ifdef _WIN32 -#pragma once -#endif - -// #include - -#ifndef NULL -#ifdef __cplusplus -#define NULL 0 -#else -#define NULL ((void *)0) -#endif -#endif - -#include "utlvector.h" -#include "Color.h" - -class IBaseFileSystem; -class CUtlBuffer; -class Color; -typedef void * FileHandle_t; - -//----------------------------------------------------------------------------- -// Purpose: Simple recursive data access class -// Used in vgui for message parameters and resource files -// Destructor deletes all child KeyValues nodes -// Data is stored in key (string names) - (string/int/float)value pairs called nodes. -// -// About KeyValues Text File Format: - -// It has 3 control characters '{', '}' and '"'. Names and values may be quoted or -// not. The quote '"' charater must not be used within name or values, only for -// quoting whole tokens. You may use escape sequences wile parsing and add within a -// quoted token a \" to add quotes within your name or token. When using Escape -// Sequence the parser must now that by setting KeyValues::UsesEscapeSequences( true ), -// which it's off by default. Non-quoted tokens ends with a whitespace, '{', '}' and '"'. -// So you may use '{' and '}' within quoted tokens, but not for non-quoted tokens. -// An open bracket '{' after a key name indicates a list of subkeys which is finished -// with a closing bracket '}'. Subkeys use the same definitions recursively. -// Whitespaces are space, return, newline and tabulator. Allowed Escape sequences -// are \n, \t, \\, \n and \". The number character '#' is used for macro purposes -// (eg #include), don't use it as first charater in key names. -//----------------------------------------------------------------------------- -class KeyValues -{ -public: - KeyValues( const char *setName ); - - // - // AutoDelete class to automatically free the keyvalues. - // Simply construct it with the keyvalues you allocated and it will free them when falls out of scope. - // When you decide that keyvalues shouldn't be deleted call Assign(NULL) on it. - // If you constructed AutoDelete(NULL) you can later assign the keyvalues to be deleted with Assign(pKeyValues). - // You can also pass temporary KeyValues object as an argument to a function by wrapping it into KeyValues::AutoDelete - // instance: call_my_function( KeyValues::AutoDelete( new KeyValues( "test" ) ) ) - // - class AutoDelete - { - public: - explicit inline AutoDelete( KeyValues *pKeyValues ) : m_pKeyValues( pKeyValues ) {} - inline ~AutoDelete( void ) { if( m_pKeyValues ) m_pKeyValues->deleteThis(); } - inline void Assign( KeyValues *pKeyValues ) { m_pKeyValues = pKeyValues; } - private: - AutoDelete( AutoDelete const &x ); // forbid - AutoDelete & operator= ( AutoDelete const &x ); // forbid - KeyValues *m_pKeyValues; - }; - - // Quick setup constructors - KeyValues( const char *setName, const char *firstKey, const char *firstValue ); - KeyValues( const char *setName, const char *firstKey, const wchar_t *firstValue ); - KeyValues( const char *setName, const char *firstKey, int firstValue ); - KeyValues( const char *setName, const char *firstKey, const char *firstValue, const char *secondKey, const char *secondValue ); - KeyValues( const char *setName, const char *firstKey, int firstValue, const char *secondKey, int secondValue ); - - // Section name - const char *GetName() const; - void SetName( const char *setName); - - // gets the name as a unique int - int GetNameSymbol() const; - - // File access. Set UsesEscapeSequences true, if resource file/buffer uses Escape Sequences (eg \n, \t) - void UsesEscapeSequences(bool state); // default false - bool LoadFromFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL ); - bool SaveToFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL); - - // Read from a buffer... Note that the buffer must be null terminated - bool LoadFromBuffer( char const *resourceName, const char *pBuffer, IBaseFileSystem* pFileSystem = NULL, const char *pPathID = NULL ); - - // Read from a utlbuffer... - bool LoadFromBuffer( char const *resourceName, CUtlBuffer &buf, IBaseFileSystem* pFileSystem = NULL, const char *pPathID = NULL ); - - // Find a keyValue, create it if it is not found. - // Set bCreate to true to create the key if it doesn't already exist (which ensures a valid pointer will be returned) - KeyValues *FindKey(const char *keyName, bool bCreate = false); - KeyValues *FindKey(int keySymbol) const; - KeyValues *CreateNewKey(); // creates a new key, with an autogenerated name. name is guaranteed to be an integer, of value 1 higher than the highest other integer key name - void AddSubKey( KeyValues *pSubkey ); // Adds a subkey. Make sure the subkey isn't a child of some other keyvalues - void RemoveSubKey(KeyValues *subKey); // removes a subkey from the list, DOES NOT DELETE IT - - // Key iteration. - // - // NOTE: GetFirstSubKey/GetNextKey will iterate keys AND values. Use the functions - // below if you want to iterate over just the keys or just the values. - // - KeyValues *GetFirstSubKey(); // returns the first subkey in the list - KeyValues *GetNextKey(); // returns the next subkey - void SetNextKey( KeyValues * pDat); - - // - // These functions can be used to treat it like a true key/values tree instead of - // confusing values with keys. - // - // So if you wanted to iterate all subkeys, then all values, it would look like this: - // for ( KeyValues *pKey = pRoot->GetFirstTrueSubKey(); pKey; pKey = pKey->GetNextTrueSubKey() ) - // { - // Msg( "Key name: %s\n", pKey->GetName() ); - // } - // for ( KeyValues *pValue = pRoot->GetFirstValue(); pKey; pKey = pKey->GetNextValue() ) - // { - // Msg( "Int value: %d\n", pValue->GetInt() ); // Assuming pValue->GetDataType() == TYPE_INT... - // } - KeyValues* GetFirstTrueSubKey(); - KeyValues* GetNextTrueSubKey(); - - KeyValues* GetFirstValue(); // When you get a value back, you can use GetX and pass in NULL to get the value. - KeyValues* GetNextValue(); - - - // Data access - int GetInt( const char *keyName = NULL, int defaultValue = 0 ); - uint64 GetUint64( const char *keyName = NULL, uint64 defaultValue = 0 ); - float GetFloat( const char *keyName = NULL, float defaultValue = 0.0f ); - const char *GetString( const char *keyName = NULL, const char *defaultValue = "" ); - const wchar_t *GetWString( const char *keyName = NULL, const wchar_t *defaultValue = L"" ); - void *GetPtr( const char *keyName = NULL, void *defaultValue = (void*)0 ); - Color GetColor( const char *keyName = NULL /* default value is all black */); - bool IsEmpty(const char *keyName = NULL); - - // Data access - int GetInt( int keySymbol, int defaultValue = 0 ); - float GetFloat( int keySymbol, float defaultValue = 0.0f ); - const char *GetString( int keySymbol, const char *defaultValue = "" ); - const wchar_t *GetWString( int keySymbol, const wchar_t *defaultValue = L"" ); - void *GetPtr( int keySymbol, void *defaultValue = (void*)0 ); - Color GetColor( int keySymbol /* default value is all black */); - bool IsEmpty( int keySymbol ); - - // Key writing - void SetWString( const char *keyName, const wchar_t *value ); - void SetString( const char *keyName, const char *value ); - void SetInt( const char *keyName, int value ); - void SetUint64( const char *keyName, uint64 value ); - void SetFloat( const char *keyName, float value ); - void SetPtr( const char *keyName, void *value ); - void SetColor( const char *keyName, Color value); - - // Memory allocation (optimized) - void *operator new( size_t iAllocSize ); - void *operator new( size_t iAllocSize, int nBlockUse, const char *pFileName, int nLine ); - void operator delete( void *pMem ); - void operator delete( void *pMem, int nBlockUse, const char *pFileName, int nLine ); - - KeyValues& operator=( KeyValues& src ); - - // Adds a chain... if we don't find stuff in this keyvalue, we'll look - // in the one we're chained to. - void ChainKeyValue( KeyValues* pChain ); - - void RecursiveSaveToFile( CUtlBuffer& buf, int indentLevel ); - - bool WriteAsBinary( CUtlBuffer &buffer ); - bool ReadAsBinary( CUtlBuffer &buffer ); - - // Allocate & create a new copy of the keys - KeyValues *MakeCopy( void ) const; - - // Make a new copy of all subkeys, add them all to the passed-in keyvalues - void CopySubkeys( KeyValues *pParent ) const; - - // Clear out all subkeys, and the current value - void Clear( void ); - - // Data type - enum types_t - { - TYPE_NONE = 0, - TYPE_STRING, - TYPE_INT, - TYPE_FLOAT, - TYPE_PTR, - TYPE_WSTRING, - TYPE_COLOR, - TYPE_UINT64, - TYPE_NUMTYPES, - }; - types_t GetDataType(const char *keyName = NULL); - - // Virtual deletion function - ensures that KeyValues object is deleted from correct heap - void deleteThis(); - - void SetStringValue( char const *strValue ); - - // unpack a key values list into a structure - void UnpackIntoStructure( struct KeyValuesUnpackStructure const *pUnpackTable, void *pDest ); - - // Process conditional keys for widescreen support. - bool ProcessResolutionKeys( const char *pResString ); - -private: - KeyValues( KeyValues& ); // prevent copy constructor being used - - // prevent delete being called except through deleteThis() - ~KeyValues(); - - KeyValues* CreateKey( const char *keyName ); - - void RecursiveCopyKeyValues( KeyValues& src ); - void RemoveEverything(); -// void RecursiveSaveToFile( IBaseFileSystem *filesystem, CUtlBuffer &buffer, int indentLevel ); -// void WriteConvertedString( CUtlBuffer &buffer, const char *pszString ); - - // NOTE: If both filesystem and pBuf are non-null, it'll save to both of them. - // If filesystem is null, it'll ignore f. - void RecursiveSaveToFile( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, int indentLevel ); - void WriteConvertedString( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, const char *pszString ); - - void RecursiveLoadFromBuffer( char const *resourceName, CUtlBuffer &buf ); - - // For handling #include "filename" - void AppendIncludedKeys( CUtlVector< KeyValues * >& includedKeys ); - void ParseIncludedKeys( char const *resourceName, const char *filetoinclude, - IBaseFileSystem* pFileSystem, const char *pPathID, CUtlVector< KeyValues * >& includedKeys ); - - // For handling #base "filename" - void MergeBaseKeys( CUtlVector< KeyValues * >& baseKeys ); - void RecursiveMergeKeyValues( KeyValues *baseKV ); - - // NOTE: If both filesystem and pBuf are non-null, it'll save to both of them. - // If filesystem is null, it'll ignore f. - void InternalWrite( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, const void *pData, int len ); - - void Init(); - const char * ReadToken( CUtlBuffer &buf, bool &wasQuoted, bool &wasConditional ); - void WriteIndents( IBaseFileSystem *filesystem, FileHandle_t f, CUtlBuffer *pBuf, int indentLevel ); - - void FreeAllocatedValue(); - void AllocateValueBlock(int size); - - int m_iKeyName; // keyname is a symbol defined in KeyValuesSystem - - // These are needed out of the union because the API returns string pointers - char *m_sValue; - wchar_t *m_wsValue; - - // we don't delete these - union - { - int m_iValue; - float m_flValue; - void *m_pValue; - unsigned char m_Color[4]; - }; - - char m_iDataType; - char m_bHasEscapeSequences; // true, if while parsing this KeyValue, Escape Sequences are used (default false) - char unused[2]; - - KeyValues *m_pPeer; // pointer to next key in list - KeyValues *m_pSub; // pointer to Start of a new sub key list - KeyValues *m_pChain;// Search here if it's not in our list -}; - -enum KeyValuesUnpackDestinationTypes_t -{ - UNPACK_TYPE_FLOAT, // dest is a float - UNPACK_TYPE_VECTOR, // dest is a Vector - UNPACK_TYPE_VECTOR_COLOR, // dest is a vector, src is a color - UNPACK_TYPE_STRING, // dest is a char *. unpacker will allocate. - UNPACK_TYPE_INT, // dest is an int - UNPACK_TYPE_FOUR_FLOATS, // dest is an array of 4 floats. source is a string like "1 2 3 4" - UNPACK_TYPE_TWO_FLOATS, // dest is an array of 2 floats. source is a string like "1 2" -}; - -#define UNPACK_FIXED( kname, kdefault, dtype, ofs ) { kname, kdefault, dtype, ofs, 0 } -#define UNPACK_VARIABLE( kname, kdefault, dtype, ofs, sz ) { kname, kdefault, dtype, ofs, sz } -#define UNPACK_END_MARKER { NULL, NULL, UNPACK_TYPE_FLOAT, 0 } - -struct KeyValuesUnpackStructure -{ - char const *m_pKeyName; // null to terminate tbl - char const *m_pKeyDefault; // null ok - KeyValuesUnpackDestinationTypes_t m_eDataType; // UNPACK_TYPE_INT, .. - size_t m_nFieldOffset; // use offsetof to set - size_t m_nFieldSize; // for strings or other variable length -}; - -//----------------------------------------------------------------------------- -// inline methods -//----------------------------------------------------------------------------- -inline int KeyValues::GetInt( int keySymbol, int defaultValue ) -{ - KeyValues *dat = FindKey( keySymbol ); - return dat ? dat->GetInt( (const char *)NULL, defaultValue ) : defaultValue; -} - -inline float KeyValues::GetFloat( int keySymbol, float defaultValue ) -{ - KeyValues *dat = FindKey( keySymbol ); - return dat ? dat->GetFloat( (const char *)NULL, defaultValue ) : defaultValue; -} - -inline const char *KeyValues::GetString( int keySymbol, const char *defaultValue ) -{ - KeyValues *dat = FindKey( keySymbol ); - return dat ? dat->GetString( (const char *)NULL, defaultValue ) : defaultValue; -} - -inline const wchar_t *KeyValues::GetWString( int keySymbol, const wchar_t *defaultValue ) -{ - KeyValues *dat = FindKey( keySymbol ); - return dat ? dat->GetWString( (const char *)NULL, defaultValue ) : defaultValue; -} - -inline void *KeyValues::GetPtr( int keySymbol, void *defaultValue ) -{ - KeyValues *dat = FindKey( keySymbol ); - return dat ? dat->GetPtr( (const char *)NULL, defaultValue ) : defaultValue; -} - -inline Color KeyValues::GetColor( int keySymbol ) -{ - Color defaultValue( 0, 0, 0, 0 ); - KeyValues *dat = FindKey( keySymbol ); - return dat ? dat->GetColor( ) : defaultValue; -} - -inline bool KeyValues::IsEmpty( int keySymbol ) -{ - KeyValues *dat = FindKey( keySymbol ); - return dat ? dat->IsEmpty( ) : true; -} - -bool EvaluateConditional( const char *str ); - -#endif // KEYVALUES_H diff --git a/public/tier1/UtlSortVector.h b/public/tier1/UtlSortVector.h deleted file mode 100644 index 10f231b5f..000000000 --- a/public/tier1/UtlSortVector.h +++ /dev/null @@ -1,311 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// $Header: $ -// $NoKeywords: $ -// -// A growable array class that keeps all elements in order using binary search -//===========================================================================// - -#ifndef UTLSORTVECTOR_H -#define UTLSORTVECTOR_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "utlvector.h" - - -//----------------------------------------------------------------------------- -// class CUtlSortVector: -// description: -// This in an sorted order-preserving vector. Items may be inserted or removed -// at any point in the vector. When an item is inserted, all elements are -// moved down by one element using memmove. When an item is removed, all -// elements are shifted back down. Items are searched for in the vector -// using a binary search technique. Clients must pass in a Less() function -// into the constructor of the vector to determine the sort order. -//----------------------------------------------------------------------------- - -#ifndef _WIN32 -// gcc has no qsort_s, so i need to use a static var to hold the sort context. this makes cutlsortvector _not_ thread sfae under linux -extern void *g_pUtlSortVectorQSortContext; -#endif - -template -class CUtlSortVector : public CUtlVector -{ -public: - - // constructor - CUtlSortVector( int nGrowSize = 0, int initSize = 0 ); - CUtlSortVector( T* pMemory, int numElements ); - - // inserts (copy constructs) an element in sorted order into the list - int Insert( const T& src ); - - // Finds an element within the list using a binary search - int Find( const T& search ) const; - int FindLessOrEqual( const T& search ) const; - int FindLess( const T& search ) const; - - // Removes a particular element - void Remove( const T& search ); - void Remove( int i ); - - // Allows methods to set a context to be used with the less function.. - void SetLessContext( void *pCtx ); - - // Note that you can only use this index until sorting is redone!!! - int InsertNoSort( const T& src ); - void RedoSort( bool bForceSort = false ); - -protected: - // No copy constructor - CUtlSortVector( const CUtlSortVector & ); - - // never call these; illegal for this class - int AddToHead(); - int AddToTail(); - int InsertBefore( int elem ); - int InsertAfter( int elem ); - int AddToHead( const T& src ); - int AddToTail( const T& src ); - int InsertBefore( int elem, const T& src ); - int InsertAfter( int elem, const T& src ); - int AddMultipleToHead( int num ); - int AddMultipleToTail( int num, const T *pToCopy=NULL ); - int InsertMultipleBefore( int elem, int num, const T *pToCopy=NULL ); - int InsertMultipleAfter( int elem, int num ); - int AddVectorToTail( CUtlVector const &src ); - - struct QSortContext_t - { - void *m_pLessContext; - LessFunc *m_pLessFunc; - }; - -#ifdef _WIN32 - static int CompareHelper( void *context, const T *lhs, const T *rhs ) - { - QSortContext_t *ctx = reinterpret_cast< QSortContext_t * >( context ); - if ( ctx->m_pLessFunc->Less( *lhs, *rhs, ctx->m_pLessContext ) ) - return -1; - if ( ctx->m_pLessFunc->Less( *rhs, *lhs, ctx->m_pLessContext ) ) - return 1; - return 0; - } -#else - static int CompareHelper( const T *lhs, const T *rhs ) - { - QSortContext_t *ctx = reinterpret_cast< QSortContext_t * >( g_pUtlSortVectorQSortContext ); - if ( ctx->m_pLessFunc->Less( *lhs, *rhs, ctx->m_pLessContext ) ) - return -1; - if ( ctx->m_pLessFunc->Less( *rhs, *lhs, ctx->m_pLessContext ) ) - return 1; - return 0; - } -#endif - - void *m_pLessContext; - bool m_bNeedsSort; - -private: - void QuickSort( LessFunc& less, int X, int I ); -}; - - -//----------------------------------------------------------------------------- -// constructor -//----------------------------------------------------------------------------- -template -CUtlSortVector::CUtlSortVector( int nGrowSize, int initSize ) : - CUtlVector( nGrowSize, initSize ), m_pLessContext(NULL), m_bNeedsSort( false ) -{ -} - -template -CUtlSortVector::CUtlSortVector( T* pMemory, int numElements ) : - CUtlVector( pMemory, numElements ), m_pLessContext(NULL), m_bNeedsSort( false ) -{ -} - -//----------------------------------------------------------------------------- -// Allows methods to set a context to be used with the less function.. -//----------------------------------------------------------------------------- -template -void CUtlSortVector::SetLessContext( void *pCtx ) -{ - m_pLessContext = pCtx; -} - -//----------------------------------------------------------------------------- -// grows the vector -//----------------------------------------------------------------------------- -template -int CUtlSortVector::Insert( const T& src ) -{ - AssertFatal( !m_bNeedsSort ); - - int pos = FindLessOrEqual( src ) + 1; - CUtlVector::GrowVector(); - CUtlVector::ShiftElementsRight(pos); - CopyConstruct( &CUtlVector::Element(pos), src ); - return pos; -} - -template -int CUtlSortVector::InsertNoSort( const T& src ) -{ - m_bNeedsSort = true; - int lastElement = CUtlVector::m_Size; - // Just stick the new element at the end of the vector, but don't do a sort - CUtlVector::GrowVector(); - CUtlVector::ShiftElementsRight(lastElement); - CopyConstruct( &CUtlVector::Element(lastElement), src ); - return lastElement; -} - -template -void CUtlSortVector::QuickSort( LessFunc& less, int nLower, int nUpper ) -{ -#ifdef _WIN32 - typedef int (__cdecl *QSortCompareFunc_t)(void *context, const void *, const void *); - if ( Count() > 1 ) - { - QSortContext_t ctx; - ctx.m_pLessContext = m_pLessContext; - ctx.m_pLessFunc = &less; - - qsort_s( Base(), Count(), sizeof(T), (QSortCompareFunc_t)&CUtlSortVector::CompareHelper, &ctx ); - } -#else - typedef int (__cdecl *QSortCompareFunc_t)( const void *, const void *); - if ( CUtlVector::Count() > 1 ) - { - QSortContext_t ctx; - ctx.m_pLessContext = m_pLessContext; - ctx.m_pLessFunc = &less; - g_pUtlSortVectorQSortContext = &ctx; - - qsort( CUtlVector::Base(), CUtlVector::Count(), sizeof(T), (QSortCompareFunc_t)&CUtlSortVector::CompareHelper ); - } -#endif -} - -template -void CUtlSortVector::RedoSort( bool bForceSort /*= false */ ) -{ - if ( !m_bNeedsSort && !bForceSort ) - return; - - m_bNeedsSort = false; - LessFunc less; - QuickSort( less, 0, CUtlVector::Count() - 1 ); -} - -//----------------------------------------------------------------------------- -// finds a particular element -//----------------------------------------------------------------------------- -template -int CUtlSortVector::Find( const T& src ) const -{ - AssertFatal( !m_bNeedsSort ); - - LessFunc less; - - int start = 0, end = CUtlVector::Count() - 1; - while (start <= end) - { - int mid = (start + end) >> 1; - if ( less.Less( CUtlVector::Element(mid), src, m_pLessContext ) ) - { - start = mid + 1; - } - else if ( less.Less( src, CUtlVector::Element(mid), m_pLessContext ) ) - { - end = mid - 1; - } - else - { - return mid; - } - } - return -1; -} - - -//----------------------------------------------------------------------------- -// finds a particular element -//----------------------------------------------------------------------------- -template -int CUtlSortVector::FindLessOrEqual( const T& src ) const -{ - AssertFatal( !m_bNeedsSort ); - - LessFunc less; - int start = 0, end = CUtlVector::Count() - 1; - while (start <= end) - { - int mid = (start + end) >> 1; - if ( less.Less( CUtlVector::Element(mid), src, m_pLessContext ) ) - { - start = mid + 1; - } - else if ( less.Less( src, CUtlVector::Element(mid), m_pLessContext ) ) - { - end = mid - 1; - } - else - { - return mid; - } - } - return end; -} - -template -int CUtlSortVector::FindLess( const T& src ) const -{ - AssertFatal( !m_bNeedsSort ); - - LessFunc less; - int start = 0, end = CUtlVector::Count() - 1; - while (start <= end) - { - int mid = (start + end) >> 1; - if ( less.Less( CUtlVector::Element(mid), src, m_pLessContext ) ) - { - start = mid + 1; - } - else - { - end = mid - 1; - } - } - return end; -} - - -//----------------------------------------------------------------------------- -// Removes a particular element -//----------------------------------------------------------------------------- -template -void CUtlSortVector::Remove( const T& search ) -{ - AssertFatal( !m_bNeedsSort ); - - int pos = Find(search); - if (pos != -1) - { - CUtlVector::Remove(pos); - } -} - -template -void CUtlSortVector::Remove( int i ) -{ - CUtlVector::Remove( i ); -} - -#endif // UTLSORTVECTOR_H diff --git a/public/tier1/UtlStringMap.h b/public/tier1/UtlStringMap.h deleted file mode 100644 index af60ecedb..000000000 --- a/public/tier1/UtlStringMap.h +++ /dev/null @@ -1,99 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#ifndef UTLSTRINGMAP_H -#define UTLSTRINGMAP_H -#ifdef _WIN32 -#pragma once -#endif - -#include "utlsymbol.h" - -template -class CUtlStringMap -{ -public: - CUtlStringMap( bool caseInsensitive = true ) : m_SymbolTable( 0, 32, caseInsensitive ) - { - } - - // Get data by the string itself: - T& operator[]( const char *pString ) - { - CUtlSymbol symbol = m_SymbolTable.AddString( pString ); - int index = ( int )( UtlSymId_t )symbol; - if( m_Vector.Count() <= index ) - { - m_Vector.EnsureCount( index + 1 ); - } - return m_Vector[index]; - } - - // Get data by the string's symbol table ID - only used to retrieve a pre-existing symbol, not create a new one! - T& operator[]( UtlSymId_t n ) - { - Assert( n <= m_Vector.Count() ); - return m_Vector[n]; - } - - const T& operator[]( UtlSymId_t n ) const - { - Assert( n <= m_Vector.Count() ); - return m_Vector[n]; - } - - bool Defined( const char *pString ) const - { - return m_SymbolTable.Find( pString ) != UTL_INVAL_SYMBOL; - } - - UtlSymId_t Find( const char *pString ) const - { - return m_SymbolTable.Find( pString ); - } - - static UtlSymId_t InvalidIndex() - { - return UTL_INVAL_SYMBOL; - } - - int GetNumStrings( void ) const - { - return m_SymbolTable.GetNumStrings(); - } - - const char *String( int n ) const - { - return m_SymbolTable.String( n ); - } - - // Clear all of the data from the map - void Clear() - { - m_Vector.RemoveAll(); - m_SymbolTable.RemoveAll(); - } - - void Purge() - { - m_Vector.Purge(); - m_SymbolTable.RemoveAll(); - } - - void PurgeAndDeleteElements() - { - m_Vector.PurgeAndDeleteElements(); - m_SymbolTable.RemoveAll(); - } - - - -private: - CUtlVector m_Vector; - CUtlSymbolTable m_SymbolTable; -}; - -#endif // UTLSTRINGMAP_H diff --git a/public/tier1/bitbuf.h b/public/tier1/bitbuf.h deleted file mode 100644 index 6d27f2d1d..000000000 --- a/public/tier1/bitbuf.h +++ /dev/null @@ -1,1506 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -// NOTE: old_bf_read is guaranteed to return zeros if it overflows. - -#ifndef BITBUF_H -#define BITBUF_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "mathlib/mathlib.h" -#include "mathlib/vector.h" -#include "basetypes.h" -#include "tier0/dbg.h" - - - - -//----------------------------------------------------------------------------- -// Forward declarations. -//----------------------------------------------------------------------------- - -class Vector; -class QAngle; - -//----------------------------------------------------------------------------- -// You can define a handler function that will be called in case of -// out-of-range values and overruns here. -// -// NOTE: the handler is only called in debug mode. -// -// Call SetBitBufErrorHandler to install a handler. -//----------------------------------------------------------------------------- - -typedef enum -{ - BITBUFERROR_VALUE_OUT_OF_RANGE=0, // Tried to write a value with too few bits. - BITBUFERROR_BUFFER_OVERRUN, // Was about to overrun a buffer. - - BITBUFERROR_NUM_ERRORS -} BitBufErrorType; - - -typedef void (*BitBufErrorHandler)( BitBufErrorType errorType, const char *pDebugName ); - - -#if defined( _DEBUG ) - extern void InternalBitBufErrorHandler( BitBufErrorType errorType, const char *pDebugName ); - #define CallErrorHandler( errorType, pDebugName ) InternalBitBufErrorHandler( errorType, pDebugName ); -#else - #define CallErrorHandler( errorType, pDebugName ) -#endif - - -// Use this to install the error handler. Call with NULL to uninstall your error handler. -void SetBitBufErrorHandler( BitBufErrorHandler fn ); - - -//----------------------------------------------------------------------------- -// Helpers. -//----------------------------------------------------------------------------- - -inline int BitByte( int bits ) -{ - // return PAD_NUMBER( bits, 8 ) >> 3; - return (bits + 7) >> 3; -} - -//----------------------------------------------------------------------------- -// Used for serialization -//----------------------------------------------------------------------------- - -class old_bf_write -{ -public: - old_bf_write(); - - // nMaxBits can be used as the number of bits in the buffer. - // It must be <= nBytes*8. If you leave it at -1, then it's set to nBytes * 8. - old_bf_write( void *pData, int nBytes, int nMaxBits = -1 ); - old_bf_write( const char *pDebugName, void *pData, int nBytes, int nMaxBits = -1 ); - - // Start writing to the specified buffer. - // nMaxBits can be used as the number of bits in the buffer. - // It must be <= nBytes*8. If you leave it at -1, then it's set to nBytes * 8. - void StartWriting( void *pData, int nBytes, int iStartBit = 0, int nMaxBits = -1 ); - - // Restart buffer writing. - void Reset(); - - // Get the base pointer. - unsigned char* GetBasePointer() { return m_pData; } - - // Enable or disable assertion on overflow. 99% of the time, it's a bug that we need to catch, - // but there may be the occasional buffer that is allowed to overflow gracefully. - void SetAssertOnOverflow( bool bAssert ); - - // This can be set to assign a name that gets output if the buffer overflows. - const char* GetDebugName(); - void SetDebugName( const char *pDebugName ); - - -// Seek to a specific position. -public: - - void SeekToBit( int bitPos ); - - -// Bit functions. -public: - - void WriteOneBit(int nValue); - void WriteOneBitNoCheck(int nValue); - void WriteOneBitAt( int iBit, int nValue ); - - // Write signed or unsigned. Range is only checked in debug. - void WriteUBitLong( unsigned int data, int numbits, bool bCheckRange=true ); - void WriteSBitLong( int data, int numbits ); - - // Tell it whether or not the data is unsigned. If it's signed, - // cast to unsigned before passing in (it will cast back inside). - void WriteBitLong(unsigned int data, int numbits, bool bSigned); - - // Write a list of bits in. - bool WriteBits(const void *pIn, int nBits); - - // writes an unsigned integer with variable bit length - void WriteUBitVar( unsigned int data ); - - // Copy the bits straight out of pIn. This seeks pIn forward by nBits. - // Returns an error if this buffer or the read buffer overflows. - bool WriteBitsFromBuffer( class bf_read *pIn, int nBits ); - - void WriteBitAngle( float fAngle, int numbits ); - void WriteBitCoord (const float f); - void WriteBitCoordMP( const float f, bool bIntegral, bool bLowPrecision ); - void WriteBitFloat(float val); - void WriteBitVec3Coord( const Vector& fa ); - void WriteBitNormal( float f ); - void WriteBitVec3Normal( const Vector& fa ); - void WriteBitAngles( const QAngle& fa ); - - -// Byte functions. -public: - - void WriteChar(int val); - void WriteByte(int val); - void WriteShort(int val); - void WriteWord(int val); - void WriteLong(long val); - void WriteLongLong(int64 val); - void WriteFloat(float val); - bool WriteBytes( const void *pBuf, int nBytes ); - - // Returns false if it overflows the buffer. - bool WriteString(const char *pStr); - - -// Status. -public: - - // How many bytes are filled in? - int GetNumBytesWritten(); - int GetNumBitsWritten(); - int GetMaxNumBits(); - int GetNumBitsLeft(); - int GetNumBytesLeft(); - unsigned char* GetData(); - - // Has the buffer overflowed? - bool CheckForOverflow(int nBits); - inline bool IsOverflowed() const {return m_bOverflow;} - - inline void SetOverflowFlag(); - - -public: - // The current buffer. - unsigned char* m_pData; - int m_nDataBytes; - int m_nDataBits; - - // Where we are in the buffer. - int m_iCurBit; - -private: - - // Errors? - bool m_bOverflow; - - bool m_bAssertOnOverflow; - const char *m_pDebugName; -}; - - -//----------------------------------------------------------------------------- -// Inlined methods -//----------------------------------------------------------------------------- - -// How many bytes are filled in? -inline int old_bf_write::GetNumBytesWritten() -{ - return BitByte(m_iCurBit); -} - -inline int old_bf_write::GetNumBitsWritten() -{ - return m_iCurBit; -} - -inline int old_bf_write::GetMaxNumBits() -{ - return m_nDataBits; -} - -inline int old_bf_write::GetNumBitsLeft() -{ - return m_nDataBits - m_iCurBit; -} - -inline int old_bf_write::GetNumBytesLeft() -{ - return GetNumBitsLeft() >> 3; -} - -inline unsigned char* old_bf_write::GetData() -{ - return m_pData; -} - -inline bool old_bf_write::CheckForOverflow(int nBits) -{ - if ( m_iCurBit + nBits > m_nDataBits ) - { - SetOverflowFlag(); - CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() ); - } - - return m_bOverflow; -} - -inline void old_bf_write::SetOverflowFlag() -{ - if ( m_bAssertOnOverflow ) - { - Assert( false ); - } - - m_bOverflow = true; -} - -inline void old_bf_write::WriteOneBitNoCheck(int nValue) -{ - if(nValue) - m_pData[m_iCurBit >> 3] |= (1 << (m_iCurBit & 7)); - else - m_pData[m_iCurBit >> 3] &= ~(1 << (m_iCurBit & 7)); - - ++m_iCurBit; -} - -inline void old_bf_write::WriteOneBit(int nValue) -{ - if( !CheckForOverflow(1) ) - WriteOneBitNoCheck( nValue ); -} - - -inline void old_bf_write::WriteOneBitAt( int iBit, int nValue ) -{ - if( iBit+1 > m_nDataBits ) - { - SetOverflowFlag(); - CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() ); - return; - } - - if( nValue ) - m_pData[iBit >> 3] |= (1 << (iBit & 7)); - else - m_pData[iBit >> 3] &= ~(1 << (iBit & 7)); -} - - -inline void old_bf_write::WriteUBitLong( unsigned int curData, int numbits, bool bCheckRange ) -{ -#ifdef _DEBUG - // Make sure it doesn't overflow. - if ( bCheckRange && numbits < 32 ) - { - if ( curData >= (unsigned long)(1 << numbits) ) - { - CallErrorHandler( BITBUFERROR_VALUE_OUT_OF_RANGE, GetDebugName() ); - } - } - Assert( numbits >= 0 && numbits <= 32 ); -#endif - - extern unsigned long g_BitWriteMasks[32][33]; - - // Bounds checking.. - if ((m_iCurBit+numbits) > m_nDataBits) - { - m_iCurBit = m_nDataBits; - SetOverflowFlag(); - CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() ); - return; - } - - int nBitsLeft = numbits; - int iCurBit = m_iCurBit; - - // Mask in a dword. - unsigned int iDWord = iCurBit >> 5; - Assert( (iDWord*4 + sizeof(long)) <= (unsigned int)m_nDataBytes ); - - unsigned long iCurBitMasked = iCurBit & 31; - - unsigned long dword = LoadLittleDWord( (unsigned long*)m_pData, iDWord ); - - dword &= g_BitWriteMasks[iCurBitMasked][nBitsLeft]; - dword |= curData << iCurBitMasked; - - // write to stream (lsb to msb ) properly - StoreLittleDWord( (unsigned long*)m_pData, iDWord, dword ); - - // Did it span a dword? - int nBitsWritten = 32 - iCurBitMasked; - if ( nBitsWritten < nBitsLeft ) - { - nBitsLeft -= nBitsWritten; - curData >>= nBitsWritten; - - // read from stream (lsb to msb) properly - dword = LoadLittleDWord( (unsigned long*)m_pData, iDWord+1 ); - - dword &= g_BitWriteMasks[0][nBitsLeft]; - dword |= curData; - - // write to stream (lsb to msb) properly - StoreLittleDWord( (unsigned long*)m_pData, iDWord+1, dword ); - } - - m_iCurBit += numbits; -} - - -//----------------------------------------------------------------------------- -// This is useful if you just want a buffer to write into on the stack. -//----------------------------------------------------------------------------- - -template -class old_bf_write_static : public old_bf_write -{ -public: - inline old_bf_write_static() : old_bf_write(m_StaticData, SIZE) {} - - char m_StaticData[SIZE]; -}; - - - -//----------------------------------------------------------------------------- -// Used for unserialization -//----------------------------------------------------------------------------- - -class old_bf_read -{ -public: - old_bf_read(); - - // nMaxBits can be used as the number of bits in the buffer. - // It must be <= nBytes*8. If you leave it at -1, then it's set to nBytes * 8. - old_bf_read( const void *pData, int nBytes, int nBits = -1 ); - old_bf_read( const char *pDebugName, const void *pData, int nBytes, int nBits = -1 ); - - // Start reading from the specified buffer. - // pData's start address must be dword-aligned. - // nMaxBits can be used as the number of bits in the buffer. - // It must be <= nBytes*8. If you leave it at -1, then it's set to nBytes * 8. - void StartReading( const void *pData, int nBytes, int iStartBit = 0, int nBits = -1 ); - - // Restart buffer reading. - void Reset(); - - // Enable or disable assertion on overflow. 99% of the time, it's a bug that we need to catch, - // but there may be the occasional buffer that is allowed to overflow gracefully. - void SetAssertOnOverflow( bool bAssert ); - - // This can be set to assign a name that gets output if the buffer overflows. - const char* GetDebugName(); - void SetDebugName( const char *pName ); - - void ExciseBits( int startbit, int bitstoremove ); - - -// Bit functions. -public: - - // Returns 0 or 1. - int ReadOneBit(); - - -protected: - - unsigned int CheckReadUBitLong(int numbits); // For debugging. - int ReadOneBitNoCheck(); // Faster version, doesn't check bounds and is inlined. - bool CheckForOverflow(int nBits); - - -public: - - // Get the base pointer. - const unsigned char* GetBasePointer() { return m_pData; } - - FORCEINLINE int TotalBytesAvailable( void ) const - { - return m_nDataBytes; - } - - // Read a list of bits in.. - void ReadBits(void *pOut, int nBits); - - float ReadBitAngle( int numbits ); - - unsigned int ReadUBitLong( int numbits ); - unsigned int PeekUBitLong( int numbits ); - int ReadSBitLong( int numbits ); - - // reads an unsigned integer with variable bit length - unsigned int ReadUBitVar(); - - // You can read signed or unsigned data with this, just cast to - // a signed int if necessary. - unsigned int ReadBitLong(int numbits, bool bSigned); - - float ReadBitCoord(); - float ReadBitCoordMP( bool bIntegral, bool bLowPrecision ); - float ReadBitFloat(); - float ReadBitNormal(); - void ReadBitVec3Coord( Vector& fa ); - void ReadBitVec3Normal( Vector& fa ); - void ReadBitAngles( QAngle& fa ); - - -// Byte functions (these still read data in bit-by-bit). -public: - - int ReadChar(); - int ReadByte(); - int ReadShort(); - int ReadWord(); - long ReadLong(); - int64 ReadLongLong(); - float ReadFloat(); - bool ReadBytes(void *pOut, int nBytes); - - // Returns false if bufLen isn't large enough to hold the - // string in the buffer. - // - // Always reads to the end of the string (so you can read the - // next piece of data waiting). - // - // If bLine is true, it stops when it reaches a '\n' or a null-terminator. - // - // pStr is always null-terminated (unless bufLen is 0). - // - // pOutNumChars is set to the number of characters left in pStr when the routine is - // complete (this will never exceed bufLen-1). - // - bool ReadString( char *pStr, int bufLen, bool bLine=false, int *pOutNumChars=NULL ); - - // Reads a string and allocates memory for it. If the string in the buffer - // is > 2048 bytes, then pOverflow is set to true (if it's not NULL). - char* ReadAndAllocateString( bool *pOverflow = 0 ); - -// Status. -public: - int GetNumBytesLeft(); - int GetNumBytesRead(); - int GetNumBitsLeft(); - int GetNumBitsRead() const; - - // Has the buffer overflowed? - inline bool IsOverflowed() const {return m_bOverflow;} - - inline bool Seek(int iBit); // Seek to a specific bit. - inline bool SeekRelative(int iBitDelta); // Seek to an offset from the current position. - - // Called when the buffer is overflowed. - inline void SetOverflowFlag(); - - -public: - - // The current buffer. - const unsigned char* m_pData; - int m_nDataBytes; - int m_nDataBits; - - // Where we are in the buffer. - int m_iCurBit; - - -private: - // used by varbit reads internally - inline int CountRunOfZeros(); - - // Errors? - bool m_bOverflow; - - // For debugging.. - bool m_bAssertOnOverflow; - - const char *m_pDebugName; -}; - -//----------------------------------------------------------------------------- -// Inlines. -//----------------------------------------------------------------------------- - -inline int old_bf_read::GetNumBytesRead() -{ - return BitByte(m_iCurBit); -} - -inline int old_bf_read::GetNumBitsLeft() -{ - return m_nDataBits - m_iCurBit; -} - -inline int old_bf_read::GetNumBytesLeft() -{ - return GetNumBitsLeft() >> 3; -} - -inline int old_bf_read::GetNumBitsRead() const -{ - return m_iCurBit; -} - -inline void old_bf_read::SetOverflowFlag() -{ - if ( m_bAssertOnOverflow ) - { - Assert( false ); - } - - m_bOverflow = true; -} - -inline bool old_bf_read::Seek(int iBit) -{ - if(iBit < 0 || iBit > m_nDataBits) - { - SetOverflowFlag(); - m_iCurBit = m_nDataBits; - return false; - } - else - { - m_iCurBit = iBit; - return true; - } -} - -// Seek to an offset from the current position. -inline bool old_bf_read::SeekRelative(int iBitDelta) -{ - return Seek(m_iCurBit+iBitDelta); -} - -inline bool old_bf_read::CheckForOverflow(int nBits) -{ - if( m_iCurBit + nBits > m_nDataBits ) - { - SetOverflowFlag(); - CallErrorHandler( BITBUFERROR_BUFFER_OVERRUN, GetDebugName() ); - } - - return m_bOverflow; -} - -inline int old_bf_read::ReadOneBitNoCheck() -{ - int value = m_pData[m_iCurBit >> 3] & (1 << (m_iCurBit & 7)); - ++m_iCurBit; - return !!value; -} - -inline int old_bf_read::ReadOneBit() -{ - return (!CheckForOverflow(1)) ? ReadOneBitNoCheck() : 0; -} - -inline float old_bf_read::ReadBitFloat() -{ - long val; - - Assert(sizeof(float) == sizeof(long)); - Assert(sizeof(float) == 4); - - if(CheckForOverflow(32)) - return 0.0f; - - int bit = m_iCurBit & 0x7; - int byte = m_iCurBit >> 3; - val = m_pData[byte] >> bit; - val |= ((int)m_pData[byte + 1]) << (8 - bit); - val |= ((int)m_pData[byte + 2]) << (16 - bit); - val |= ((int)m_pData[byte + 3]) << (24 - bit); - if (bit != 0) - val |= ((int)m_pData[byte + 4]) << (32 - bit); - m_iCurBit += 32; - return *((float*)&val); -} - - -inline unsigned int old_bf_read::ReadUBitLong( int numbits ) -{ - extern unsigned long g_ExtraMasks[32]; - - if ( (m_iCurBit+numbits) > m_nDataBits ) - { - m_iCurBit = m_nDataBits; - SetOverflowFlag(); - return 0; - } - - Assert( numbits > 0 && numbits <= 32 ); - - // Read the current dword. - int idword1 = m_iCurBit >> 5; - unsigned int dword1 = LoadLittleDWord( (unsigned long*)m_pData, idword1 ); - - dword1 >>= (m_iCurBit & 31); // Get the bits we're interested in. - - m_iCurBit += numbits; - unsigned int ret = dword1; - - // Does it span this dword? - if ( (m_iCurBit-1) >> 5 == idword1 ) - { - if (numbits != 32) - ret &= g_ExtraMasks[numbits]; - } - else - { - int nExtraBits = m_iCurBit & 31; - unsigned int dword2 = LoadLittleDWord( (unsigned long*)m_pData, idword1+1 ); - - dword2 &= g_ExtraMasks[nExtraBits]; - - // No need to mask since we hit the end of the dword. - // Shift the second dword's part into the high bits. - ret |= (dword2 << (numbits - nExtraBits)); - } - - return ret; -} - - -class CBitBuffer -{ -public: - char const * m_pDebugName; - bool m_bOverflow; - int m_nDataBits; - size_t m_nDataBytes; - - void SetDebugName( char const *pName ) - { - m_pDebugName = pName; - } - - CBitBuffer( void ) - { - m_bOverflow = false; - m_pDebugName = NULL; - m_nDataBits = -1; - m_nDataBytes = 0; - } - - FORCEINLINE void SetOverflowFlag( void ) - { - m_bOverflow = true; - } - - FORCEINLINE bool IsOverflowed( void ) const - { - return m_bOverflow; - } - - static const uint32 s_nMaskTable[33]; // 0 1 3 7 15 .. - -}; - - -class CBitWrite : public CBitBuffer -{ - uint32 m_nOutBufWord; - int m_nOutBitsAvail; - uint32 *m_pDataOut; - uint32 *m_pBufferEnd; - uint32 *m_pData; - bool m_bFlushed; - -public: - void StartWriting( void *pData, int nBytes, int iStartBit = 0, int nMaxBits = -1 ); - - - CBitWrite( void *pData, int nBytes, int nBits = -1 ) - { - m_bFlushed = false; - StartWriting( pData, nBytes, 0, nBits ); - } - - CBitWrite( const char *pDebugName, void *pData, int nBytes, int nBits = -1 ) - { - m_bFlushed = false; - SetDebugName( pDebugName ); - StartWriting( pData, nBytes, 0, nBits ); - } - - CBitWrite( void ) - { - m_bFlushed = false; - } - - ~CBitWrite( void ) - { - TempFlush(); - Assert( (! m_pData ) || m_bFlushed ); - } - FORCEINLINE int GetNumBitsLeft( void ) const - { - return m_nOutBitsAvail + ( 32 * ( m_pBufferEnd - m_pDataOut -1 ) ); - } - - FORCEINLINE void Reset( void ) - { - m_bOverflow = false; - m_nOutBitsAvail = 32; - m_pDataOut = m_pData; - m_nOutBufWord = 0; - - } - - FORCEINLINE void TempFlush( void ) - { - // someone wants to know how much data we have written, or the pointer to it, so we'd better make - // sure we write our data - if ( m_nOutBitsAvail != 32 ) - { - if ( m_pDataOut == m_pBufferEnd ) - { - SetOverflowFlag(); - } - else - { - *( m_pDataOut ) = (*m_pDataOut & ~s_nMaskTable[ 32 - m_nOutBitsAvail ] ) | m_nOutBufWord; - m_bFlushed = true; - } - } - } - - FORCEINLINE unsigned char *GetBasePointer() - { - TempFlush(); - return reinterpret_cast< unsigned char *>( m_pData ); - } - - FORCEINLINE unsigned char *GetData() - { - return GetBasePointer(); - } - - FORCEINLINE void Finish(); - FORCEINLINE void Flush(); - FORCEINLINE void FlushNoCheck(); - FORCEINLINE void WriteOneBit(int nValue); - FORCEINLINE void WriteOneBitNoCheck(int nValue); - FORCEINLINE void WriteUBitLong( unsigned int data, int numbits, bool bCheckRange=true ); - FORCEINLINE void WriteSBitLong( int data, int numbits ); - FORCEINLINE void WriteUBitVar( unsigned int data ); - FORCEINLINE void WriteBitFloat( float flValue ); - FORCEINLINE void WriteFloat( float flValue ); - bool WriteBits(const void *pInData, int nBits); - void WriteBytes( const void *pBuf, int nBytes ); - void SeekToBit( int nSeekPos ); - - FORCEINLINE int GetNumBitsWritten( void ) const - { - return ( 32 - m_nOutBitsAvail ) + ( 32 * ( m_pDataOut - m_pData ) ); - } - - FORCEINLINE int GetNumBytesWritten( void ) const - { - return ( GetNumBitsWritten() + 7 ) >> 3; - } - - - FORCEINLINE void WriteLong(long val) - { - WriteSBitLong( val, 32 ); - } - - - - FORCEINLINE void WriteChar( int val ) - { - WriteSBitLong(val, sizeof(char) << 3 ); - } - - FORCEINLINE void WriteByte( int val ) - { - WriteUBitLong(val, sizeof(unsigned char) << 3, false ); - } - - FORCEINLINE void WriteShort(int val) - { - WriteSBitLong(val, sizeof(short) << 3); - } - - FORCEINLINE void WriteWord(int val) - { - WriteUBitLong(val, sizeof(unsigned short) << 3); - } - - bool WriteString( const char *pStr ); - - void WriteLongLong( int64 val ); - - void WriteBitAngle( float fAngle, int numbits ); - void WriteBitCoord (const float f); - void WriteBitCoordMP( const float f, bool bIntegral, bool bLowPrecision ); - void WriteBitVec3Coord( const Vector& fa ); - void WriteBitNormal( float f ); - void WriteBitVec3Normal( const Vector& fa ); - void WriteBitAngles( const QAngle& fa ); - - // Copy the bits straight out of pIn. This seeks pIn forward by nBits. - // Returns an error if this buffer or the read buffer overflows. - bool WriteBitsFromBuffer( class bf_read *pIn, int nBits ); - -}; - -void CBitWrite::Finish( void ) -{ - if ( m_nOutBitsAvail != 32 ) - { - if ( m_pDataOut == m_pBufferEnd ) - { - SetOverflowFlag(); - } - *( m_pDataOut ) = m_nOutBufWord; - } -} - -void CBitWrite::FlushNoCheck( void ) -{ - *( m_pDataOut++ ) = m_nOutBufWord; - m_nOutBitsAvail = 32; - m_nOutBufWord = 0; // ugh - I need this because of 32 bit writes. a<<=32 is a nop - -} -void CBitWrite::Flush( void ) -{ - if ( m_pDataOut == m_pBufferEnd ) - { - SetOverflowFlag(); - } - else - *( m_pDataOut++ ) = m_nOutBufWord; - m_nOutBufWord = 0; // ugh - I need this because of 32 bit writes. a<<=32 is a nop - m_nOutBitsAvail = 32; - -} -void CBitWrite::WriteOneBitNoCheck( int nValue ) -{ - m_nOutBufWord |= ( nValue & 1 ) << ( 32 - m_nOutBitsAvail ); - if ( --m_nOutBitsAvail == 0 ) - { - FlushNoCheck(); - } -} - -void CBitWrite::WriteOneBit( int nValue ) -{ - m_nOutBufWord |= ( nValue & 1 ) << ( 32 - m_nOutBitsAvail ); - if ( --m_nOutBitsAvail == 0 ) - { - Flush(); - } -} - -FORCEINLINE void CBitWrite::WriteUBitLong( unsigned int nData, int nNumBits, bool bCheckRange ) -{ - -#ifdef _DEBUG - // Make sure it doesn't overflow. - if ( bCheckRange && nNumBits < 32 ) - { - Assert( nData <= (unsigned long)(1 << nNumBits ) ); - } - Assert( nNumBits >= 0 && nNumBits <= 32 ); -#endif - if ( nNumBits <= m_nOutBitsAvail ) - { - if ( bCheckRange ) - m_nOutBufWord |= ( nData ) << ( 32 - m_nOutBitsAvail ); - else - m_nOutBufWord |= ( nData & s_nMaskTable[ nNumBits] ) << ( 32 - m_nOutBitsAvail ); - m_nOutBitsAvail -= nNumBits; - if ( m_nOutBitsAvail == 0 ) - { - Flush(); - } - } - else - { - // split dwords case - int nOverflowBits = ( nNumBits - m_nOutBitsAvail ); - m_nOutBufWord |= ( nData & s_nMaskTable[m_nOutBitsAvail] ) << ( 32 - m_nOutBitsAvail ); - Flush(); - m_nOutBufWord = ( nData >> ( nNumBits - nOverflowBits ) ); - m_nOutBitsAvail = 32 - nOverflowBits; - } -} - -FORCEINLINE void CBitWrite::WriteSBitLong( int nData, int nNumBits ) -{ - WriteUBitLong( ( uint32 ) nData, nNumBits, false ); -} - -FORCEINLINE void CBitWrite::WriteUBitVar( unsigned int data ) -{ - if ( ( data &0xf ) == data ) - { - WriteUBitLong( 0, 2 ); - WriteUBitLong( data, 4 ); - } - else - { - if ( ( data & 0xff ) == data ) - { - WriteUBitLong( 1, 2 ); - WriteUBitLong( data, 8 ); - } - else - { - if ( ( data & 0xfff ) == data ) - { - WriteUBitLong( 2, 2 ); - WriteUBitLong( data, 12 ); - } - else - { - WriteUBitLong( 0x3, 2 ); - WriteUBitLong( data, 32 ); - } - } - } -} - -FORCEINLINE void CBitWrite::WriteBitFloat( float flValue ) -{ - WriteUBitLong( *((uint32 *) &flValue ), 32 ); -} - -FORCEINLINE void CBitWrite::WriteFloat( float flValue ) -{ - // Pre-swap the float, since WriteBits writes raw data - LittleFloat( &flValue, &flValue ); - WriteUBitLong( *((uint32 *) &flValue ), 32 ); -} - -class CBitRead : public CBitBuffer -{ - uint32 m_nInBufWord; - int m_nBitsAvail; - uint32 const *m_pDataIn; - uint32 const *m_pBufferEnd; - uint32 const *m_pData; - -public: - CBitRead( const void *pData, int nBytes, int nBits = -1 ) - { - StartReading( pData, nBytes, 0, nBits ); - } - - CBitRead( const char *pDebugName, const void *pData, int nBytes, int nBits = -1 ) - { - SetDebugName( pDebugName ); - StartReading( pData, nBytes, 0, nBits ); - } - - CBitRead( void ) : CBitBuffer() - { - } - - FORCEINLINE int Tell( void ) const - { - return GetNumBitsRead(); - } - - FORCEINLINE size_t TotalBytesAvailable( void ) const - { - return m_nDataBytes; - } - - FORCEINLINE int GetNumBitsLeft() const - { - return m_nDataBits - Tell(); - } - - FORCEINLINE int GetNumBytesLeft() const - { - return GetNumBitsLeft() >> 3; - } - - bool Seek( int nPosition ); - - FORCEINLINE bool SeekRelative( int nOffset ) - { - return Seek( GetNumBitsRead() + nOffset ); - } - - FORCEINLINE unsigned char const * GetBasePointer() - { - return reinterpret_cast< unsigned char const *>( m_pData ); - } - - void StartReading( const void *pData, int nBytes, int iStartBit = 0, int nBits = -1 ); - - FORCEINLINE int GetNumBitsRead( void ) const; - - FORCEINLINE void GrabNextDWord( bool bOverFlowImmediately = false ); - FORCEINLINE void FetchNext( void ); - FORCEINLINE unsigned int ReadUBitLong( int numbits ); - FORCEINLINE int ReadSBitLong( int numbits ); - FORCEINLINE unsigned int ReadUBitVar( void ); - FORCEINLINE unsigned int PeekUBitLong( int numbits ); - FORCEINLINE float ReadBitFloat( void ); - float ReadBitCoord(); - float ReadBitCoordMP( bool bIntegral, bool bLowPrecision ); - float ReadBitNormal(); - void ReadBitVec3Coord( Vector& fa ); - void ReadBitVec3Normal( Vector& fa ); - void ReadBitAngles( QAngle& fa ); - bool ReadBytes(void *pOut, int nBytes); - float ReadBitAngle( int numbits ); - - // Returns 0 or 1. - FORCEINLINE int ReadOneBit( void ); - FORCEINLINE int ReadLong( void ); - FORCEINLINE int ReadChar( void ); - FORCEINLINE int ReadByte( void ); - FORCEINLINE int ReadShort( void ); - FORCEINLINE int ReadWord( void ); - FORCEINLINE float ReadFloat( void ); - void ReadBits(void *pOut, int nBits); - - // Returns false if bufLen isn't large enough to hold the - // string in the buffer. - // - // Always reads to the end of the string (so you can read the - // next piece of data waiting). - // - // If bLine is true, it stops when it reaches a '\n' or a null-terminator. - // - // pStr is always null-terminated (unless bufLen is 0). - // - // pOutN m_pBufferEnd ) - { - SetOverflowFlag(); - m_nInBufWord = 0; - } - else - { - Assert( reinterpret_cast(m_pDataIn) + 3 < reinterpret_cast(m_pBufferEnd)); - m_nInBufWord = LittleDWord( *( m_pDataIn++ ) ); - } -} - -FORCEINLINE void CBitRead::FetchNext( void ) -{ - m_nBitsAvail = 32; - GrabNextDWord( false ); -} - -int CBitRead::ReadOneBit( void ) -{ - int nRet = m_nInBufWord & 1; - if ( --m_nBitsAvail == 0 ) - { - FetchNext(); - } - else - m_nInBufWord >>= 1; - return nRet; -} - - -unsigned int CBitRead::ReadUBitLong( int numbits ) -{ - if ( m_nBitsAvail >= numbits ) - { - unsigned int nRet = m_nInBufWord & s_nMaskTable[ numbits ]; - m_nBitsAvail -= numbits; - if ( m_nBitsAvail ) - { - m_nInBufWord >>= numbits; - } - else - { - FetchNext(); - } - return nRet; - } - else - { - // need to merge words - unsigned int nRet = m_nInBufWord; - numbits -= m_nBitsAvail; - GrabNextDWord( true ); - if ( m_bOverflow ) - return 0; - nRet |= ( ( m_nInBufWord & s_nMaskTable[numbits] ) << m_nBitsAvail ); - m_nBitsAvail = 32 - numbits; - m_nInBufWord >>= numbits; - return nRet; - } -} - -FORCEINLINE unsigned int CBitRead::PeekUBitLong( int numbits ) -{ - int nSaveBA = m_nBitsAvail; - int nSaveW = m_nInBufWord; - uint32 const *pSaveP = m_pDataIn; - unsigned int nRet = ReadUBitLong( numbits ); - m_nBitsAvail = nSaveBA; - m_nInBufWord = nSaveW; - m_pDataIn = pSaveP; - return nRet; -} - -FORCEINLINE int CBitRead::ReadSBitLong( int numbits ) -{ - int nRet = ReadUBitLong( numbits ); - // sign extend - return ( nRet << ( 32 - numbits ) ) >> ( 32 - numbits ); -} - -FORCEINLINE int CBitRead::ReadLong( void ) -{ - return ( int ) ReadUBitLong( sizeof(long) << 3 ); -} - -FORCEINLINE float CBitRead::ReadFloat( void ) -{ - uint32 nUval = ReadUBitLong( sizeof(long) << 3 ); - return * ( ( float * ) &nUval ); -} - -#ifdef _WIN32 -#pragma warning(push) -#pragma warning(disable : 4715) // disable warning on not all cases - // returning a value. throwing default: - // in measurably reduces perf in bit - // packing benchmark -#endif -FORCEINLINE unsigned int CBitRead::ReadUBitVar( void ) -{ - unsigned int ret = ReadUBitLong( 2 ); - switch( ret ) - { - case 0: - ret = ReadUBitLong( 4 ); - break; - - case 1: - ret = ReadUBitLong( 8 ); - break; - - case 2: - ret = ReadUBitLong( 12 ); - break; - - case 3: - ret = ReadUBitLong( 32 ); - break; - } - return ret; -} -#ifdef _WIN32 -#pragma warning(pop) -#endif - -FORCEINLINE float CBitRead::ReadBitFloat( void ) -{ - uint32 nvalue = ReadUBitLong( 32 ); - return *( ( float * ) &nvalue ); -} - -int CBitRead::ReadChar( void ) -{ - return ReadSBitLong(sizeof(char) << 3); -} - -int CBitRead::ReadByte( void ) -{ - return ReadUBitLong(sizeof(unsigned char) << 3); -} - -int CBitRead::ReadShort( void ) -{ - return ReadSBitLong(sizeof(short) << 3); -} - -int CBitRead::ReadWord( void ) -{ - return ReadUBitLong(sizeof(unsigned short) << 3); -} - -#define WRAP_READ( bc ) \ -class bf_read : public bc \ -{ \ -public: \ - FORCEINLINE bf_read( void ) : bc( ) \ - { \ - } \ - \ - FORCEINLINE bf_read( const void *pData, int nBytes, int nBits = -1 ) : bc( pData, nBytes, nBits ) \ - { \ - } \ - \ - FORCEINLINE bf_read( const char *pDebugName, const void *pData, int nBytes, int nBits = -1 ) : bc( pDebugName, pData, nBytes, nBits ) \ - { \ - } \ -}; - -#define WRAP_WRITE( bc ) \ -class bf_write : public bc \ -{ \ -public: \ - FORCEINLINE bf_write(void) : bc() \ - { \ - } \ - FORCEINLINE bf_write( void *pData, int nBytes, int nMaxBits = -1 ) : bc( pData, nBytes, nMaxBits ) \ - { \ - } \ - \ - FORCEINLINE bf_write( const char *pDebugName, void *pData, int nBytes, int nMaxBits = -1 ) : bc( pDebugName, pData, nBytes, nMaxBits ) \ - { \ - } \ -}; -#if 0 - - -#define DELEGATE0( t, m ) t m() \ -{ \ - Check(); \ - t nOld = old1.m(); \ - t nNew = new1.m(); \ - Assert( nOld == nNew ); \ - Check(); \ - return nOld; \ -} -#define DELEGATE1( t, m, t1 ) t m( t1 x) \ -{ \ - Check(); \ - t nOld = old1.m( x); \ - t nNew = new1.m( x ); \ - Assert( nOld == nNew ); \ - Check(); \ - return nOld; \ -} - -#define DELEGATE0I( m ) DELEGATE0( int, m ) -#define DELEGATE0LL( m ) DELEGATE0( int64, m ) - -class bf_read -{ - old_bf_read old1; - CBitRead new1; - - void Check( void ) const - { - int n=new1.GetNumBitsRead(); - int o=old1.GetNumBitsRead(); - Assert( n == o ); - Assert( old1.IsOverflowed() == new1.IsOverflowed() ); - } - -public: - FORCEINLINE bf_read( void ) : old1(), new1() - { - } - - FORCEINLINE bf_read( const void *pData, int nBytes, int nBits = -1 ) : old1( pData, nBytes, nBits ),new1( pData, nBytes, nBits ) - { - } - - FORCEINLINE bf_read( const char *pDebugName, const void *pData, int nBytes, int nBits = -1 ) : old1( pDebugName, pData, nBytes, nBits ), new1( pDebugName, pData, nBytes, nBits ) - { - } - - FORCEINLINE bool IsOverflowed( void ) const - { - bool bOld = old1.IsOverflowed(); - bool bNew = new1.IsOverflowed(); - Assert( bOld == bNew ); - Check(); - return bOld; - - } - - void ReadBits(void *pOut, int nBits) - { - old1.ReadBits( pOut, nBits ); - void *mem=stackalloc( 1+ ( nBits / 8 ) ); - new1.ReadBits( mem, nBits ); - Assert( memcmp( mem, pOut, nBits / 8 ) == 0 ); - } - - bool ReadBytes(void *pOut, int nBytes) - { - ReadBits(pOut, nBytes << 3); - return ! IsOverflowed(); - } - - - unsigned int ReadUBitLong( int numbits ) - { - unsigned int nOld = old1.ReadUBitLong( numbits ); - unsigned int nNew = new1.ReadUBitLong( numbits ); - Assert( nOld == nNew ); - Check(); - return nOld; - } - - unsigned const char* GetBasePointer() - { - Assert( old1.GetBasePointer() == new1.GetBasePointer() ); - Check(); - return old1.GetBasePointer(); - } - void SetDebugName( const char *pDebugName ) - { - old1.SetDebugName( pDebugName ); - new1.SetDebugName( pDebugName ); - Check(); - } - - void StartReading( const void *pData, int nBytes, int iStartBit = 0, int nBits = -1 ) - { - old1.StartReading( pData, nBytes, iStartBit, nBits ); - new1.StartReading( pData, nBytes, iStartBit, nBits ); - Check(); - } - - void SetAssertOnOverflow( bool bAssert ) - { - old1.SetAssertOnOverflow( bAssert ); -// new1.SetAssertOnOverflow( bAssert ); - Check(); - } - - DELEGATE0I( ReadOneBit ); - DELEGATE0I( ReadByte ); - DELEGATE0I( ReadWord ); - DELEGATE0I( ReadLong ); - DELEGATE0I( GetNumBytesLeft ); - DELEGATE0I( ReadShort ); - DELEGATE1( int, PeekUBitLong, int ); - DELEGATE0I( ReadChar ); - DELEGATE0I( GetNumBitsRead ); - DELEGATE0LL( ReadLongLong ); - DELEGATE0( float, ReadFloat); - DELEGATE0( unsigned int, ReadUBitVar ); - DELEGATE0( float, ReadBitCoord); - DELEGATE2( float, ReadBitCoordMP, bool, bool ); - DELEGATE0( float, ReadBitFloat); - DELEGATE0( float, ReadBitNormal); - DELEGATE1( bool,Seek, int ); - DELEGATE1( float, ReadBitAngle, int ); - DELEGATE1( bool,SeekRelative,int); - DELEGATE0I( GetNumBitsLeft ); - DELEGATE0I( TotalBytesAvailable ); - - void SetOverflowFlag() - { - old1.SetOverflowFlag(); - new1.SetOverflowFlag(); - Check(); - } - - bool ReadString( char *pStr, int bufLen, bool bLine=false, int *pOutNumChars=NULL ) - { - Check(); - int oldn, newn; - bool bOld = old1.ReadString( pStr, bufLen, bLine, &oldn ); - bool bNew = new1.ReadString( pStr, bufLen, bLine, &newn ); - Assert( bOld == bNew ); - Assert( oldn == newn ); - if ( pOutNumChars ) - *pOutNumChars = oldn; - Check(); - return bOld; - } - - void ReadBitVec3Coord( Vector& fa ) - { - Check(); - old1.ReadBitVec3Coord( fa ); - Vector test; - new1.ReadBitVec3Coord( test ); - Assert( VectorsAreEqual( fa, test )); - Check(); - } - void ReadBitVec3Normal( Vector& fa ) - { - Check(); - old1.ReadBitVec3Coord( fa ); - Vector test; - new1.ReadBitVec3Coord( test ); - Assert( VectorsAreEqual( fa, test )); - Check(); - } - - char* ReadAndAllocateString( bool *pOverflow = NULL ) - { - Check(); - bool bold, bnew; - char *pold = old1.ReadAndAllocateString( &bold ); - char *pnew = new1.ReadAndAllocateString( &bnew ); - Assert( bold == bnew ); - Assert(strcmp( pold, pnew ) == 0 ); - delete[] pnew; - Check(); - if ( pOverflow ) - *pOverflow = bold; - return pold; - - } - - DELEGATE1( int, ReadSBitLong, int ); - -}; -#endif - - -#if defined _LINUX || defined __APPLE__ -WRAP_READ( old_bf_read ); -#else -WRAP_READ( CBitRead ); -#endif -WRAP_WRITE( old_bf_write ); - - -#endif - - - diff --git a/public/tier1/byteswap.h b/public/tier1/byteswap.h deleted file mode 100644 index 63c86662b..000000000 --- a/public/tier1/byteswap.h +++ /dev/null @@ -1,249 +0,0 @@ -//========= Copyright 1996-2006, Valve LLC, All rights reserved. ============ -// -// Purpose: Low level byte swapping routines. -// -// $NoKeywords: $ -//============================================================================= -#ifndef BYTESWAP_H -#define BYTESWAP_H -#if defined(_WIN32) -#pragma once -#endif - -#include "datamap.h" // Needed for typedescription_t. Note datamap.h is tier1 as well. - -class CByteswap -{ -public: - CByteswap() - { - // Default behavior sets the target endian to match the machine native endian (no swap). - SetTargetBigEndian( IsMachineBigEndian() ); - } - - //----------------------------------------------------------------------------- - // Write a single field. - //----------------------------------------------------------------------------- - void SwapFieldToTargetEndian( void* pOutputBuffer, void *pData, typedescription_t *pField ); - - //----------------------------------------------------------------------------- - // Write a block of fields. Works a bit like the saverestore code. - //----------------------------------------------------------------------------- - void SwapFieldsToTargetEndian( void *pOutputBuffer, void *pBaseData, datamap_t *pDataMap ); - - // Swaps fields for the templated type to the output buffer. - template inline void SwapFieldsToTargetEndian( T* pOutputBuffer, void *pBaseData, unsigned int objectCount = 1 ) - { - for ( unsigned int i = 0; i < objectCount; ++i, ++pOutputBuffer ) - { - SwapFieldsToTargetEndian( (void*)pOutputBuffer, pBaseData, &T::m_DataMap ); - pBaseData = (byte*)pBaseData + sizeof(T); - } - } - - // Swaps fields for the templated type in place. - template inline void SwapFieldsToTargetEndian( T* pOutputBuffer, unsigned int objectCount = 1 ) - { - SwapFieldsToTargetEndian( pOutputBuffer, (void*)pOutputBuffer, objectCount ); - } - - //----------------------------------------------------------------------------- - // True if the current machine is detected as big endian. - // (Endienness is effectively detected at compile time when optimizations are - // enabled) - //----------------------------------------------------------------------------- - static bool IsMachineBigEndian() - { - short nIsBigEndian = 1; - - // if we are big endian, the first byte will be a 0, if little endian, it will be a one. - return (bool)(0 == *(char *)&nIsBigEndian ); - } - - //----------------------------------------------------------------------------- - // Sets the target byte ordering we are swapping to or from. - // - // Braindead Endian Reference: - // x86 is LITTLE Endian - // PowerPC is BIG Endian - //----------------------------------------------------------------------------- - inline void SetTargetBigEndian( bool bigEndian ) - { - m_bBigEndian = bigEndian; - m_bSwapBytes = IsMachineBigEndian() != bigEndian; - } - - // Changes target endian - inline void FlipTargetEndian( void ) - { - m_bSwapBytes = !m_bSwapBytes; - m_bBigEndian = !m_bBigEndian; - } - - // Forces byte swapping state, regardless of endianess - inline void ActivateByteSwapping( bool bActivate ) - { - SetTargetBigEndian( IsMachineBigEndian() != bActivate ); - } - - //----------------------------------------------------------------------------- - // Returns true if the target machine is the same as this one in endianness. - // - // Used to determine when a byteswap needs to take place. - //----------------------------------------------------------------------------- - inline bool IsSwappingBytes( void ) // Are bytes being swapped? - { - return m_bSwapBytes; - } - - inline bool IsTargetBigEndian( void ) // What is the current target endian? - { - return m_bBigEndian; - } - - //----------------------------------------------------------------------------- - // IsByteSwapped() - // - // When supplied with a chunk of input data and a constant or magic number - // (in native format) determines the endienness of the current machine in - // relation to the given input data. - // - // Returns: - // 1 if input is the same as nativeConstant. - // 0 if input is byteswapped relative to nativeConstant. - // -1 if input is not the same as nativeConstant and not byteswapped either. - // - // ( This is useful for detecting byteswapping in magic numbers in structure - // headers for example. ) - //----------------------------------------------------------------------------- - template inline int SourceIsNativeEndian( T input, T nativeConstant ) - { - // If it's the same, it isn't byteswapped: - if( input == nativeConstant ) - return 1; - - int output; - LowLevelByteSwap( &output, &input ); - if( output == nativeConstant ) - return 0; - - assert( 0 ); // if we get here, input is neither a swapped nor unswapped version of nativeConstant. - return -1; - } - - //----------------------------------------------------------------------------- - // Swaps an input buffer full of type T into the given output buffer. - // - // Swaps [count] items from the inputBuffer to the outputBuffer. - // If inputBuffer is omitted or NULL, then it is assumed to be the same as - // outputBuffer - effectively swapping the contents of the buffer in place. - //----------------------------------------------------------------------------- - template inline void SwapBuffer( T* outputBuffer, T* inputBuffer = NULL, int count = 1 ) - { - assert( count >= 0 ); - assert( outputBuffer ); - - // Fail gracefully in release: - if( count <=0 || !outputBuffer ) - return; - - // Optimization for the case when we are swapping in place. - if( inputBuffer == NULL ) - { - inputBuffer = outputBuffer; - } - - // Swap everything in the buffer: - for( int i = 0; i < count; i++ ) - { - LowLevelByteSwap( &outputBuffer[i], &inputBuffer[i] ); - } - } - - //----------------------------------------------------------------------------- - // Swaps an input buffer full of type T into the given output buffer. - // - // Swaps [count] items from the inputBuffer to the outputBuffer. - // If inputBuffer is omitted or NULL, then it is assumed to be the same as - // outputBuffer - effectively swapping the contents of the buffer in place. - //----------------------------------------------------------------------------- - template inline void SwapBufferToTargetEndian( T* outputBuffer, T* inputBuffer = NULL, int count = 1 ) - { - assert( count >= 0 ); - assert( outputBuffer ); - - // Fail gracefully in release: - if( count <=0 || !outputBuffer ) - return; - - // Optimization for the case when we are swapping in place. - if( inputBuffer == NULL ) - { - inputBuffer = outputBuffer; - } - - // Are we already the correct endienness? ( or are we swapping 1 byte items? ) - if( !m_bSwapBytes || ( sizeof(T) == 1 ) ) - { - // If we were just going to swap in place then return. - if( !inputBuffer ) - return; - - // Otherwise copy the inputBuffer to the outputBuffer: - memcpy( outputBuffer, inputBuffer, count * sizeof( T ) ); - return; - - } - - // Swap everything in the buffer: - for( int i = 0; i < count; i++ ) - { - LowLevelByteSwap( &outputBuffer[i], &inputBuffer[i] ); - } - } - -private: - //----------------------------------------------------------------------------- - // The lowest level byte swapping workhorse of doom. output always contains the - // swapped version of input. ( Doesn't compare machine to target endianness ) - //----------------------------------------------------------------------------- - template static void LowLevelByteSwap( T *output, T *input ) - { - T temp = *output; -#if defined( _X360 ) - // Intrinsics need the source type to be fixed-point - DWORD* word = (DWORD*)input; - switch( sizeof(T) ) - { - case 8: - { - __storewordbytereverse( *word, 0, &temp ); - __storewordbytereverse( *(word+1), 4, &temp ); - } - break; - - case 4: - __storewordbytereverse( *word, 0, &temp ); - break; - - case 2: - __storeshortbytereverse( *input, 0, &temp ); - break; - - default: - Assert( "Invalid size in CByteswap::LowLevelByteSwap" && 0 ); - } -#else - for( int i = 0; i < (int)sizeof(T); i++ ) - { - ((unsigned char* )&temp)[i] = ((unsigned char*)input)[sizeof(T)-(i+1)]; - } -#endif - Q_memcpy( output, &temp, sizeof(T) ); - } - - unsigned int m_bSwapBytes : 1; - unsigned int m_bBigEndian : 1; -}; - -#endif /* !BYTESWAP_H */ diff --git a/public/tier1/callqueue.h b/public/tier1/callqueue.h deleted file mode 100644 index b10d2afac..000000000 --- a/public/tier1/callqueue.h +++ /dev/null @@ -1,203 +0,0 @@ -//========== Copyright 2006, Valve Corporation, All rights reserved. ======== -// -// Purpose: -// -//============================================================================= - -#ifndef CALLQUEUE_H -#define CALLQUEUE_H - -#include "tier0/tslist.h" -#include "functors.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -//----------------------------------------------------- -// Avert thy eyes! Imagine rather: -// -// void QueueCall( , [args1, [arg2,]...] -// void QueueCall( , , [args1, [arg2,]...] -// void QueueRefCall( , <, [args1, [arg2,]...] -//----------------------------------------------------- - -#define DEFINE_CALLQUEUE_NONMEMBER_QUEUE_CALL(N) \ - template \ - void QueueCall(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - QueueFunctorInternal( CreateFunctor( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \ - } - -//------------------------------------- - -#define DEFINE_CALLQUEUE_MEMBER_QUEUE_CALL(N) \ - template \ - void QueueCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - QueueFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \ - } - -//------------------------------------- - -#define DEFINE_CALLQUEUE_CONST_MEMBER_QUEUE_CALL(N) \ - template \ - void QueueCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - QueueFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \ - } - -//------------------------------------- - -#define DEFINE_CALLQUEUE_REF_COUNTING_MEMBER_QUEUE_CALL(N) \ - template \ - void QueueRefCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - QueueFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \ - } - -//------------------------------------- - -#define DEFINE_CALLQUEUE_REF_COUNTING_CONST_MEMBER_QUEUE_CALL(N) \ - template \ - void QueueRefCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - QueueFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \ - \ - } - -#define FUNC_GENERATE_QUEUE_METHODS() \ - FUNC_GENERATE_ALL( DEFINE_CALLQUEUE_NONMEMBER_QUEUE_CALL ); \ - FUNC_GENERATE_ALL( DEFINE_CALLQUEUE_MEMBER_QUEUE_CALL ); \ - FUNC_GENERATE_ALL( DEFINE_CALLQUEUE_CONST_MEMBER_QUEUE_CALL );\ - FUNC_GENERATE_ALL( DEFINE_CALLQUEUE_REF_COUNTING_MEMBER_QUEUE_CALL ); \ - FUNC_GENERATE_ALL( DEFINE_CALLQUEUE_REF_COUNTING_CONST_MEMBER_QUEUE_CALL ) - -//----------------------------------------------------- - -template > -class CCallQueueT -{ -public: - CCallQueueT() - : m_bNoQueue( false ) - { -#ifdef _DEBUG - m_nCurSerialNumber = 0; - m_nBreakSerialNumber = (unsigned)-1; -#endif - } - - void DisableQueue( bool bDisable ) - { - if ( m_bNoQueue == bDisable ) - { - return; - } - if ( !m_bNoQueue ) - CallQueued(); - - m_bNoQueue = bDisable; - } - - bool IsDisabled() const - { - return m_bNoQueue; - } - - int Count() - { - return m_queue.Count(); - } - - void CallQueued() - { - if ( !m_queue.Count() ) - { - return; - } - - m_queue.PushItem( NULL ); - - CFunctor *pFunctor; - - while ( m_queue.PopItem( &pFunctor ) && pFunctor != NULL ) - { -#ifdef _DEBUG - if ( pFunctor->m_nUserID == m_nBreakSerialNumber) - { - m_nBreakSerialNumber = (unsigned)-1; - } -#endif - (*pFunctor)(); - pFunctor->Release(); - } - - } - - void QueueFunctor( CFunctor *pFunctor ) - { - Assert( pFunctor ); - QueueFunctorInternal( RetAddRef( pFunctor ) ); - } - - void Flush() - { - m_queue.PushItem( NULL ); - - CFunctor *pFunctor; - - while ( m_queue.PopItem( &pFunctor ) && pFunctor != NULL ) - { - pFunctor->Release(); - } - } - - FUNC_GENERATE_QUEUE_METHODS(); - -private: - void QueueFunctorInternal( CFunctor *pFunctor ) - { - if ( !m_bNoQueue ) - { -#ifdef _DEBUG - pFunctor->m_nUserID = m_nCurSerialNumber++; -#endif - m_queue.PushItem( pFunctor ); - } - else - { - (*pFunctor)(); - pFunctor->Release(); - } - } - - QUEUE_TYPE m_queue; - bool m_bNoQueue; - unsigned m_nCurSerialNumber; - unsigned m_nBreakSerialNumber; -}; - -class CCallQueue : public CCallQueueT<> -{ -}; - -//----------------------------------------------------- -// Optional interface that can be bound to concrete CCallQueue -//----------------------------------------------------- - -class ICallQueue -{ -public: - void QueueFunctor( CFunctor *pFunctor ) - { - QueueFunctorInternal( RetAddRef( pFunctor ) ); - } - - FUNC_GENERATE_QUEUE_METHODS(); - -private: - virtual void QueueFunctorInternal( CFunctor *pFunctor ) = 0; -}; - -#endif // CALLQUEUE_H diff --git a/public/tier1/characterset.h b/public/tier1/characterset.h deleted file mode 100644 index 731b42b9c..000000000 --- a/public/tier1/characterset.h +++ /dev/null @@ -1,43 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: Shared code for parsing / searching for characters in a string -// using lookup tables -// -// $Workfile: $ -// $Date: $ -// $NoKeywords: $ -//===========================================================================// - -#ifndef CHARACTERSET_H -#define CHARACTERSET_H - -#ifdef _WIN32 -#pragma once -#endif - - -struct characterset_t -{ - char set[256]; -}; - - -// This is essentially a strpbrk() using a precalculated lookup table -//----------------------------------------------------------------------------- -// Purpose: builds a simple lookup table of a group of important characters -// Input : *pSetBuffer - pointer to the buffer for the group -// *pSetString - list of characters to flag -//----------------------------------------------------------------------------- -extern void CharacterSetBuild( characterset_t *pSetBuffer, const char *pSetString ); - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pSetBuffer - pre-build group buffer -// character - character to lookup -// Output : int - 1 if the character was in the set -//----------------------------------------------------------------------------- -#define IN_CHARACTERSET( SetBuffer, character ) ((SetBuffer).set[static_cast(character)]) - - -#endif // CHARACTERSET_H diff --git a/public/tier1/checksum_crc.h b/public/tier1/checksum_crc.h deleted file mode 100644 index fa9a766ed..000000000 --- a/public/tier1/checksum_crc.h +++ /dev/null @@ -1,31 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Generic CRC functions -// -// $NoKeywords: $ -//=============================================================================// -#ifndef CHECKSUM_CRC_H -#define CHECKSUM_CRC_H -#ifdef _WIN32 -#pragma once -#endif - -typedef unsigned long CRC32_t; - -void CRC32_Init( CRC32_t *pulCRC ); -void CRC32_ProcessBuffer( CRC32_t *pulCRC, const void *p, int len ); -void CRC32_Final( CRC32_t *pulCRC ); -CRC32_t CRC32_GetTableEntry( unsigned int slot ); - -inline CRC32_t CRC32_ProcessSingleBuffer( const void *p, int len ) -{ - CRC32_t crc; - - CRC32_Init( &crc ); - CRC32_ProcessBuffer( &crc, p, len ); - CRC32_Final( &crc ); - - return crc; -} - -#endif // CHECKSUM_CRC_H diff --git a/public/tier1/checksum_md5.h b/public/tier1/checksum_md5.h deleted file mode 100644 index 3692cf133..000000000 --- a/public/tier1/checksum_md5.h +++ /dev/null @@ -1,33 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Generic MD5 hashing algo -// -//=============================================================================// - -#ifndef CHECKSUM_MD5_H -#define CHECKSUM_MD5_H - -#ifdef _WIN32 -#pragma once -#endif - -// 16 bytes == 128 bit digest -#define MD5_DIGEST_LENGTH 16 - -// MD5 Hash -typedef struct -{ - unsigned int buf[4]; - unsigned int bits[2]; - unsigned char in[64]; -} MD5Context_t; - -void MD5Init( MD5Context_t *context ); -void MD5Update( MD5Context_t *context, unsigned char const *buf, unsigned int len ); -void MD5Final( unsigned char digest[ MD5_DIGEST_LENGTH ], MD5Context_t *context ); - -char *MD5_Print(unsigned char *digest, int hashlen ); - -unsigned int MD5_PseudoRandom(unsigned int nSeed); - -#endif // CHECKSUM_MD5_H diff --git a/public/tier1/convar.h b/public/tier1/convar.h deleted file mode 100644 index bd23ef4ad..000000000 --- a/public/tier1/convar.h +++ /dev/null @@ -1,679 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $NoKeywords: $ -//===========================================================================// - -#ifndef CONVAR_H -#define CONVAR_H - -#if _WIN32 -#pragma once -#endif - -#include "tier0/dbg.h" -#include "tier1/iconvar.h" -#include "tier1/utlvector.h" -#include "tier1/utlstring.h" -#include "icvar.h" - -#ifdef _WIN32 -#define FORCEINLINE_CVAR FORCEINLINE -#elif defined _LINUX || defined __APPLE__ -#define FORCEINLINE_CVAR inline -#else -#error "implement me" -#endif - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class ConVar; -class CCommand; -class ConCommand; -class ConCommandBase; -struct characterset_t; - - - -//----------------------------------------------------------------------------- -// Any executable that wants to use ConVars need to implement one of -// these to hook up access to console variables. -//----------------------------------------------------------------------------- -class IConCommandBaseAccessor -{ -public: - // Flags is a combination of FCVAR flags in cvar.h. - // hOut is filled in with a handle to the variable. - virtual bool RegisterConCommandBase( ConCommandBase *pVar ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Helper method for console development -//----------------------------------------------------------------------------- -#if defined( _X360 ) && !defined( _RETAIL ) -void ConVar_PublishToVXConsole(); -#endif - - -//----------------------------------------------------------------------------- -// Called when a ConCommand needs to execute -//----------------------------------------------------------------------------- -typedef void ( *FnCommandCallbackV1_t )( void ); -typedef void ( *FnCommandCallback_t )( const CCommand &command ); - -#define COMMAND_COMPLETION_MAXITEMS 64 -#define COMMAND_COMPLETION_ITEM_LENGTH 64 - -//----------------------------------------------------------------------------- -// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings -//----------------------------------------------------------------------------- -typedef int ( *FnCommandCompletionCallback )( const char *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] ); - - -//----------------------------------------------------------------------------- -// Interface version -//----------------------------------------------------------------------------- -class ICommandCallback -{ -public: - virtual void CommandCallback( const CCommand &command ) = 0; -}; - -class ICommandCompletionCallback -{ -public: - virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands ) = 0; -}; - -//----------------------------------------------------------------------------- -// Purpose: The base console invoked command/cvar interface -//----------------------------------------------------------------------------- -class ConCommandBase -{ - friend class CCvar; - friend class ConVar; - friend class ConCommand; - friend void ConVar_Register( int nCVarFlag, IConCommandBaseAccessor *pAccessor ); - friend void ConVar_PublishToVXConsole(); - - // FIXME: Remove when ConVar changes are done - friend class CDefaultCvar; - -public: - ConCommandBase( void ); - ConCommandBase( const char *pName, const char *pHelpString = 0, - int flags = 0 ); - - virtual ~ConCommandBase( void ); - - virtual bool IsCommand( void ) const; - - // Check flag - virtual bool IsFlagSet( int flag ) const; - // Set flag - virtual void AddFlags( int flags ); - - // Return name of cvar - virtual const char *GetName( void ) const; - - // Return help text for cvar - virtual const char *GetHelpText( void ) const; - - // Deal with next pointer - const ConCommandBase *GetNext( void ) const; - ConCommandBase *GetNext( void ); - - inline void SetNext(ConCommandBase *pBase) - { - m_pNext = pBase; - } - - virtual bool IsRegistered( void ) const; - - // Returns the DLL identifier - virtual CVarDLLIdentifier_t GetDLLIdentifier() const; - -protected: - virtual void Create( const char *pName, const char *pHelpString = 0, - int flags = 0 ); - - // Used internally by OneTimeInit to initialize/shutdown - virtual void Init(); - void Shutdown(); - - // Internal copy routine ( uses new operator from correct module ) - char *CopyString( const char *from ); - -private: - // Next ConVar in chain - // Prior to register, it points to the next convar in the DLL. - // Once registered, though, m_pNext is reset to point to the next - // convar in the global list - ConCommandBase *m_pNext; - - // Has the cvar been added to the global list? - bool m_bRegistered; - - // Static data - const char *m_pszName; - const char *m_pszHelpString; - - // ConVar flags - int m_nFlags; - -protected: - // ConVars add themselves to this list for the executable. - // Then ConVar_Register runs through all the console variables - // and registers them into a global list stored in vstdlib.dll - static ConCommandBase *s_pConCommandBases; - - // ConVars in this executable use this 'global' to access values. - static IConCommandBaseAccessor *s_pAccessor; -}; - - -//----------------------------------------------------------------------------- -// Command tokenizer -//----------------------------------------------------------------------------- -class CCommand -{ -public: - CCommand(); - CCommand( int nArgC, const char **ppArgV ); - bool Tokenize( const char *pCommand, characterset_t *pBreakSet = NULL ); - void Reset(); - - int ArgC() const; - const char **ArgV() const; - const char *ArgS() const; // All args that occur after the 0th arg, in string form - const char *GetCommandString() const; // The entire command in string form, including the 0th arg - const char *operator[]( int nIndex ) const; // Gets at arguments - const char *Arg( int nIndex ) const; // Gets at arguments - - // Helper functions to parse arguments to commands. - const char* FindArg( const char *pName ) const; - int FindArgInt( const char *pName, int nDefaultVal ) const; - - static int MaxCommandLength(); - static characterset_t* DefaultBreakSet(); - -private: - enum - { - COMMAND_MAX_ARGC = 64, - COMMAND_MAX_LENGTH = 512, - }; - - int m_nArgc; - int m_nArgv0Size; - char m_pArgSBuffer[ COMMAND_MAX_LENGTH ]; - char m_pArgvBuffer[ COMMAND_MAX_LENGTH ]; - const char* m_ppArgv[ COMMAND_MAX_ARGC ]; -}; - -inline int CCommand::MaxCommandLength() -{ - return COMMAND_MAX_LENGTH - 1; -} - -inline int CCommand::ArgC() const -{ - return m_nArgc; -} - -inline const char **CCommand::ArgV() const -{ - return m_nArgc ? (const char**)m_ppArgv : NULL; -} - -inline const char *CCommand::ArgS() const -{ - return m_nArgv0Size ? &m_pArgSBuffer[m_nArgv0Size] : ""; -} - -inline const char *CCommand::GetCommandString() const -{ - return m_nArgc ? m_pArgSBuffer : ""; -} - -inline const char *CCommand::Arg( int nIndex ) const -{ - // FIXME: Many command handlers appear to not be particularly careful - // about checking for valid argc range. For now, we're going to - // do the extra check and return an empty string if it's out of range - if ( nIndex < 0 || nIndex >= m_nArgc ) - return ""; - return m_ppArgv[nIndex]; -} - -inline const char *CCommand::operator[]( int nIndex ) const -{ - return Arg( nIndex ); -} - - -//----------------------------------------------------------------------------- -// Purpose: The console invoked command -//----------------------------------------------------------------------------- -class ConCommand : public ConCommandBase -{ -friend class CCvar; - -public: - typedef ConCommandBase BaseClass; - - ConCommand( const char *pName, FnCommandCallbackV1_t callback, - const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ); - ConCommand( const char *pName, FnCommandCallback_t callback, - const char *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 ); - ConCommand( const char *pName, ICommandCallback *pCallback, - const char *pHelpString = 0, int flags = 0, ICommandCompletionCallback *pCommandCompletionCallback = 0 ); - - virtual ~ConCommand( void ); - - virtual bool IsCommand( void ) const; - - virtual int AutoCompleteSuggest( const char *partial, CUtlVector< CUtlString > &commands ); - - virtual bool CanAutoComplete( void ); - - // Invoke the function - virtual void Dispatch( const CCommand &command ); - -private: - // NOTE: To maintain backward compat, we have to be very careful: - // All public virtual methods must appear in the same order always - // since engine code will be calling into this code, which *does not match* - // in the mod code; it's using slightly different, but compatible versions - // of this class. Also: Be very careful about adding new fields to this class. - // Those fields will not exist in the version of this class that is instanced - // in mod code. - - // Call this function when executing the command - union - { - FnCommandCallbackV1_t m_fnCommandCallbackV1; - FnCommandCallback_t m_fnCommandCallback; - ICommandCallback *m_pCommandCallback; - }; - - union - { - FnCommandCompletionCallback m_fnCompletionCallback; - ICommandCompletionCallback *m_pCommandCompletionCallback; - }; - - bool m_bHasCompletionCallback : 1; - bool m_bUsingNewCommandCallback : 1; - bool m_bUsingCommandCallbackInterface : 1; -}; - - -//----------------------------------------------------------------------------- -// Purpose: A console variable -//----------------------------------------------------------------------------- -class ConVar : public ConCommandBase, public IConVar -{ -friend class CCvar; -friend class ConVarRef; - -public: - typedef ConCommandBase BaseClass; - - ConVar( const char *pName, const char *pDefaultValue, int flags = 0); - - ConVar( const char *pName, const char *pDefaultValue, int flags, - const char *pHelpString ); - ConVar( const char *pName, const char *pDefaultValue, int flags, - const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax ); - ConVar( const char *pName, const char *pDefaultValue, int flags, - const char *pHelpString, FnChangeCallback_t callback ); - ConVar( const char *pName, const char *pDefaultValue, int flags, - const char *pHelpString, bool bMin, float fMin, bool bMax, float fMax, - FnChangeCallback_t callback ); - - virtual ~ConVar( void ); - - virtual bool IsFlagSet( int flag ) const; - virtual const char* GetHelpText( void ) const; - virtual bool IsRegistered( void ) const; - virtual const char *GetName( void ) const; - virtual void AddFlags( int flags ); - virtual bool IsCommand( void ) const; - - // Install a change callback (there shouldn't already be one....) - void InstallChangeCallback( FnChangeCallback_t callback ); - - // Retrieve value - FORCEINLINE_CVAR float GetFloat( void ) const; - FORCEINLINE_CVAR int GetInt( void ) const; - FORCEINLINE_CVAR bool GetBool() const { return !!GetInt(); } - FORCEINLINE_CVAR char const *GetString( void ) const; - - // Any function that allocates/frees memory needs to be virtual or else you'll have crashes - // from alloc/free across dll/exe boundaries. - - // These just call into the IConCommandBaseAccessor to check flags and set the var (which ends up calling InternalSetValue). - virtual void SetValue( const char *value ); - virtual void SetValue( float value ); - virtual void SetValue( int value ); - - // Reset to default value - void Revert( void ); - - // True if it has a min/max setting - bool GetMin( float& minVal ) const; - bool GetMax( float& maxVal ) const; - const char *GetDefault( void ) const; - -private: - // Called by CCvar when the value of a var is changing. - virtual void InternalSetValue(const char *value); - // For CVARs marked FCVAR_NEVER_AS_STRING - virtual void InternalSetFloatValue( float fNewValue ); - virtual void InternalSetIntValue( int nValue ); - - virtual bool ClampValue( float& value ); - virtual void ChangeStringValue( const char *tempVal, float flOldValue ); - - virtual void Create( const char *pName, const char *pDefaultValue, int flags = 0, - const char *pHelpString = 0, bool bMin = false, float fMin = 0.0, - bool bMax = false, float fMax = false, FnChangeCallback_t callback = 0 ); - - // Used internally by OneTimeInit to initialize. - virtual void Init(); - -private: - - // This either points to "this" or it points to the original declaration of a ConVar. - // This allows ConVars to exist in separate modules, and they all use the first one to be declared. - // m_pParent->m_pParent must equal m_pParent (ie: m_pParent must be the root, or original, ConVar). - ConVar *m_pParent; - - // Static data - const char *m_pszDefaultValue; - - // Value - // Dynamically allocated - char *m_pszString; - int m_StringLength; - - // Values - float m_fValue; - int m_nValue; - - // Min/Max values - bool m_bHasMin; - float m_fMinVal; - bool m_bHasMax; - float m_fMaxVal; - - // Call this function when ConVar changes - FnChangeCallback_t m_fnChangeCallback; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Return ConVar value as a float -// Output : float -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR float ConVar::GetFloat( void ) const -{ - return m_pParent->m_fValue; -} - -//----------------------------------------------------------------------------- -// Purpose: Return ConVar value as an int -// Output : int -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR int ConVar::GetInt( void ) const -{ - return m_pParent->m_nValue; -} - - -//----------------------------------------------------------------------------- -// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc. -// Output : const char * -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR const char *ConVar::GetString( void ) const -{ - if ( m_nFlags & FCVAR_NEVER_AS_STRING ) - return "FCVAR_NEVER_AS_STRING"; - - return ( m_pParent->m_pszString ) ? m_pParent->m_pszString : ""; -} - - -//----------------------------------------------------------------------------- -// Used to read/write convars that already exist (replaces the FindVar method) -//----------------------------------------------------------------------------- -class ConVarRef -{ -public: - ConVarRef( const char *pName ); - ConVarRef( const char *pName, bool bIgnoreMissing ); - ConVarRef( IConVar *pConVar ); - - void Init( const char *pName, bool bIgnoreMissing ); - bool IsValid() const; - bool IsFlagSet( int nFlags ) const; - IConVar *GetLinkedConVar(); - - // Get/Set value - float GetFloat( void ) const; - int GetInt( void ) const; - bool GetBool() const { return !!GetInt(); } - const char *GetString( void ) const; - - void SetValue( const char *pValue ); - void SetValue( float flValue ); - void SetValue( int nValue ); - void SetValue( bool bValue ); - - const char *GetName() const; - - const char *GetDefault() const; - -private: - // High-speed method to read convar data - IConVar *m_pConVar; - ConVar *m_pConVarState; -}; - - -//----------------------------------------------------------------------------- -// Did we find an existing convar of that name? -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR bool ConVarRef::IsFlagSet( int nFlags ) const -{ - return ( m_pConVar->IsFlagSet( nFlags ) != 0 ); -} - -FORCEINLINE_CVAR IConVar *ConVarRef::GetLinkedConVar() -{ - return m_pConVar; -} - -FORCEINLINE_CVAR const char *ConVarRef::GetName() const -{ - return m_pConVar->GetName(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Return ConVar value as a float -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR float ConVarRef::GetFloat( void ) const -{ - return m_pConVarState->m_fValue; -} - -//----------------------------------------------------------------------------- -// Purpose: Return ConVar value as an int -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR int ConVarRef::GetInt( void ) const -{ - return m_pConVarState->m_nValue; -} - -//----------------------------------------------------------------------------- -// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc. -//----------------------------------------------------------------------------- -FORCEINLINE_CVAR const char *ConVarRef::GetString( void ) const -{ - Assert( !IsFlagSet( FCVAR_NEVER_AS_STRING ) ); - return m_pConVarState->m_pszString; -} - - -FORCEINLINE_CVAR void ConVarRef::SetValue( const char *pValue ) -{ - m_pConVar->SetValue( pValue ); -} - -FORCEINLINE_CVAR void ConVarRef::SetValue( float flValue ) -{ - m_pConVar->SetValue( flValue ); -} - -FORCEINLINE_CVAR void ConVarRef::SetValue( int nValue ) -{ - m_pConVar->SetValue( nValue ); -} - -FORCEINLINE_CVAR void ConVarRef::SetValue( bool bValue ) -{ - m_pConVar->SetValue( bValue ? 1 : 0 ); -} - -FORCEINLINE_CVAR const char *ConVarRef::GetDefault() const -{ - return m_pConVarState->m_pszDefaultValue; -} - - -//----------------------------------------------------------------------------- -// Called by the framework to register ConCommands with the ICVar -//----------------------------------------------------------------------------- -void ConVar_Register( int nCVarFlag = 0, IConCommandBaseAccessor *pAccessor = NULL ); -void ConVar_Unregister( ); - - -//----------------------------------------------------------------------------- -// Utility methods -//----------------------------------------------------------------------------- -void ConVar_PrintFlags( const ConCommandBase *var ); -void ConVar_PrintDescription( const ConCommandBase *pVar ); - - -//----------------------------------------------------------------------------- -// Purpose: Utility class to quickly allow ConCommands to call member methods -//----------------------------------------------------------------------------- -#ifdef _MSC_VER -#pragma warning (disable : 4355 ) -#endif - -template< class T > -class CConCommandMemberAccessor : public ConCommand, public ICommandCallback, public ICommandCompletionCallback -{ - typedef ConCommand BaseClass; - typedef void ( T::*FnMemberCommandCallback_t )( const CCommand &command ); - typedef int ( T::*FnMemberCommandCompletionCallback_t )( const char *pPartial, CUtlVector< CUtlString > &commands ); - -public: - CConCommandMemberAccessor( T* pOwner, const char *pName, FnMemberCommandCallback_t callback, const char *pHelpString = 0, - int flags = 0, FnMemberCommandCompletionCallback_t completionFunc = 0 ) : - BaseClass( pName, this, pHelpString, flags, ( completionFunc != 0 ) ? this : NULL ) - { - m_pOwner = pOwner; - m_Func = callback; - m_CompletionFunc = completionFunc; - } - - ~CConCommandMemberAccessor() - { - Shutdown(); - } - - void SetOwner( T* pOwner ) - { - m_pOwner = pOwner; - } - - virtual void CommandCallback( const CCommand &command ) - { - Assert( m_pOwner && m_Func ); - (m_pOwner->*m_Func)( command ); - } - - virtual int CommandCompletionCallback( const char *pPartial, CUtlVector< CUtlString > &commands ) - { - Assert( m_pOwner && m_CompletionFunc ); - return (m_pOwner->*m_CompletionFunc)( pPartial, commands ); - } - -private: - T* m_pOwner; - FnMemberCommandCallback_t m_Func; - FnMemberCommandCompletionCallback_t m_CompletionFunc; -}; - -#ifdef _MSC_VER -#pragma warning ( default : 4355 ) -#endif - -//----------------------------------------------------------------------------- -// Purpose: Utility macros to quicky generate a simple console command -//----------------------------------------------------------------------------- -#define CON_COMMAND( name, description ) \ - static void name( const CCommand &args ); \ - static ConCommand name##_command( #name, name, description ); \ - static void name( const CCommand &args ) - -#define CON_COMMAND_F( name, description, flags ) \ - static void name( const CCommand &args ); \ - static ConCommand name##_command( #name, name, description, flags ); \ - static void name( const CCommand &args ) - -#define CON_COMMAND_F_COMPLETION( name, description, flags, completion ) \ - static void name( const CCommand &args ); \ - static ConCommand name##_command( #name, name, description, flags, completion ); \ - static void name( const CCommand &args ) - -#define CON_COMMAND_EXTERN( name, _funcname, description ) \ - void _funcname( const CCommand &args ); \ - static ConCommand name##_command( #name, _funcname, description ); \ - void _funcname( const CCommand &args ) - -#define CON_COMMAND_EXTERN_F( name, _funcname, description, flags ) \ - void _funcname( const CCommand &args ); \ - static ConCommand name##_command( #name, _funcname, description, flags ); \ - void _funcname( const CCommand &args ) - -#define CON_COMMAND_MEMBER_F( _thisclass, name, _funcname, description, flags ) \ - void _funcname( const CCommand &args ); \ - friend class CCommandMemberInitializer_##_funcname; \ - class CCommandMemberInitializer_##_funcname \ - { \ - public: \ - CCommandMemberInitializer_##_funcname() : m_ConCommandAccessor( NULL, name, &_thisclass::_funcname, description, flags ) \ - { \ - m_ConCommandAccessor.SetOwner( GET_OUTER( _thisclass, m_##_funcname##_register ) ); \ - } \ - private: \ - CConCommandMemberAccessor< _thisclass > m_ConCommandAccessor; \ - }; \ - \ - CCommandMemberInitializer_##_funcname m_##_funcname##_register; \ - - -#endif // CONVAR_H diff --git a/public/tier1/convar_serverbounded.h b/public/tier1/convar_serverbounded.h deleted file mode 100644 index 36162395b..000000000 --- a/public/tier1/convar_serverbounded.h +++ /dev/null @@ -1,53 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Helper class for cvars that have restrictions on their value. -// -//=============================================================================// - -#ifndef CONVAR_SERVERBOUNDED_H -#define CONVAR_SERVERBOUNDED_H -#ifdef _WIN32 -#pragma once -#endif - - -// This class is used to virtualize a ConVar's value, so the client can restrict its -// value while connected to a server. When using this across modules, it's important -// to dynamic_cast it to a ConVar_ServerBounded or you won't get the restricted value. -// -// NOTE: FCVAR_USERINFO vars are not virtualized before they are sent to the server -// (we have no way to detect if the virtualized value would change), so -// if you want to use a bounded cvar's value on the server, you must rebound it -// the same way the client does. -class ConVar_ServerBounded : public ConVar -{ -public: - ConVar_ServerBounded( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString ) - : ConVar( pName, pDefaultValue, flags, pHelpString ) - { - } - - ConVar_ServerBounded( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, FnChangeCallback_t callback ) - : ConVar( pName, pDefaultValue, flags, pHelpString, callback ) - { - } - - ConVar_ServerBounded( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax ) - : ConVar( pName, pDefaultValue, flags, pHelpString, bMin, fMin, bMax, fMax ) {} - - // You must implement GetFloat. - virtual float GetFloat() const = 0; - - // You can optionally implement these. - virtual int GetInt() const { return (int)GetFloat(); } - virtual bool GetBool() const { return ( GetInt() != 0 ); } - - // Use this to get the underlying cvar's value. - float GetBaseFloatValue() const - { - return ConVar::GetFloat(); - } -}; - - -#endif // CONVAR_SERVERBOUNDED_H diff --git a/public/tier1/datamanager.h b/public/tier1/datamanager.h deleted file mode 100644 index f5960da49..000000000 --- a/public/tier1/datamanager.h +++ /dev/null @@ -1,277 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef RESOURCEMANAGER_H -#define RESOURCEMANAGER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/threadtools.h" -#include "utlmultilist.h" -#include "utlvector.h" - -FORWARD_DECLARE_HANDLE( memhandle_t ); - -#define INVALID_MEMHANDLE ((memhandle_t)0xffffffff) - -class CDataManagerBase -{ -public: - - // public API - // ----------------------------------------------------------------------------- - // memhandle_t CreateResource( params ) // implemented by derived class - void DestroyResource( memhandle_t handle ); - - // type-safe implementation in derived class - //void *LockResource( memhandle_t handle ); - int UnlockResource( memhandle_t handle ); - void TouchResource( memhandle_t handle ); - void MarkAsStale( memhandle_t handle ); // move to head of LRU - - int LockCount( memhandle_t handle ); - int BreakLock( memhandle_t handle ); - int BreakAllLocks(); - - // HACKHACK: For convenience - offers no lock protection - // type-safe implementation in derived class - //void *GetResource_NoLock( memhandle_t handle ); - - unsigned int TargetSize(); - unsigned int AvailableSize(); - unsigned int UsedSize(); - - void NotifySizeChanged( memhandle_t handle, unsigned int oldSize, unsigned int newSize ); - - void SetTargetSize( unsigned int targetSize ); - - // NOTE: flush is equivalent to Destroy - unsigned int FlushAllUnlocked(); - unsigned int FlushToTargetSize(); - unsigned int FlushAll(); - unsigned int Purge( unsigned int nBytesToPurge ); - unsigned int EnsureCapacity( unsigned int size ); - - // Thread lock - virtual void Lock() {} - virtual bool TryLock() { return true; } - virtual void Unlock() {} - - // Iteration - - // ----------------------------------------------------------------------------- - - // Debugging only!!!! - void GetLRUHandleList( CUtlVector< memhandle_t >& list ); - void GetLockHandleList( CUtlVector< memhandle_t >& list ); - - -protected: - // derived class must call these to implement public API - unsigned short CreateHandle( bool bCreateLocked ); - memhandle_t StoreResourceInHandle( unsigned short memoryIndex, void *pStore, unsigned int realSize ); - void *GetResource_NoLock( memhandle_t handle ); - void *GetResource_NoLockNoLRUTouch( memhandle_t handle ); - void *LockResource( memhandle_t handle ); - - // NOTE: you must call this from the destructor of the derived class! (will assert otherwise) - void FreeAllLists() { FlushAll(); m_listsAreFreed = true; } - - CDataManagerBase( unsigned int maxSize ); - virtual ~CDataManagerBase(); - - - inline unsigned int MemTotal_Inline() const { return m_targetMemorySize; } - inline unsigned int MemAvailable_Inline() const { return m_targetMemorySize - m_memUsed; } - inline unsigned int MemUsed_Inline() const { return m_memUsed; } - -// Implemented by derived class: - virtual void DestroyResourceStorage( void * ) = 0; - virtual unsigned int GetRealSize( void * ) = 0; - - memhandle_t ToHandle( unsigned short index ); - unsigned short FromHandle( memhandle_t handle ); - - void TouchByIndex( unsigned short memoryIndex ); - void * GetForFreeByIndex( unsigned short memoryIndex ); - - // One of these is stored per active allocation - struct resource_lru_element_t - { - resource_lru_element_t() - { - lockCount = 0; - serial = 1; - pStore = 0; - } - - unsigned short lockCount; - unsigned short serial; - void *pStore; - }; - - unsigned int m_targetMemorySize; - unsigned int m_memUsed; - - CUtlMultiList< resource_lru_element_t, unsigned short > m_memoryLists; - - unsigned short m_lruList; - unsigned short m_lockList; - unsigned short m_freeList; - unsigned short m_listsAreFreed : 1; - unsigned short m_unused : 15; - -}; - -template< class STORAGE_TYPE, class CREATE_PARAMS, class LOCK_TYPE = STORAGE_TYPE *, class MUTEX_TYPE = CThreadNullMutex> -class CDataManager : public CDataManagerBase -{ - typedef CDataManagerBase BaseClass; -public: - - CDataManager( unsigned int size = (unsigned)-1 ) : BaseClass(size) {} - - - ~CDataManager() - { - // NOTE: This must be called in all implementations of CDataManager - FreeAllLists(); - } - - // Use GetData() to translate pointer to LOCK_TYPE - LOCK_TYPE LockResource( memhandle_t hMem ) - { - void *pLock = BaseClass::LockResource( hMem ); - if ( pLock ) - { - return StoragePointer(pLock)->GetData(); - } - - return NULL; - } - - // Use GetData() to translate pointer to LOCK_TYPE - LOCK_TYPE GetResource_NoLock( memhandle_t hMem ) - { - void *pLock = const_cast(BaseClass::GetResource_NoLock( hMem )); - if ( pLock ) - { - return StoragePointer(pLock)->GetData(); - } - return NULL; - } - - // Use GetData() to translate pointer to LOCK_TYPE - // Doesn't touch the memory LRU - LOCK_TYPE GetResource_NoLockNoLRUTouch( memhandle_t hMem ) - { - void *pLock = const_cast(BaseClass::GetResource_NoLockNoLRUTouch( hMem )); - if ( pLock ) - { - return StoragePointer(pLock)->GetData(); - } - return NULL; - } - - // Wrapper to match implementation of allocation with typed storage & alloc params. - memhandle_t CreateResource( const CREATE_PARAMS &createParams, bool bCreateLocked = false ) - { - BaseClass::EnsureCapacity(STORAGE_TYPE::EstimatedSize(createParams)); - unsigned short memoryIndex = BaseClass::CreateHandle( bCreateLocked ); - STORAGE_TYPE *pStore = STORAGE_TYPE::CreateResource( createParams ); - return BaseClass::StoreResourceInHandle( memoryIndex, pStore, pStore->Size() ); - } - - // Iteration. Must lock first - memhandle_t GetFirstUnlocked() - { - unsigned node = m_memoryLists.Head(m_lruList); - if ( node == m_memoryLists.InvalidIndex() ) - { - return INVALID_MEMHANDLE; - } - return ToHandle( node ); - } - - memhandle_t GetFirstLocked() - { - unsigned node = m_memoryLists.Head(m_lockList); - if ( node == m_memoryLists.InvalidIndex() ) - { - return INVALID_MEMHANDLE; - } - return ToHandle( node ); - } - - memhandle_t GetNext( memhandle_t hPrev ) - { - if ( hPrev == INVALID_MEMHANDLE ) - { - return INVALID_MEMHANDLE; - } - - unsigned short iNext = m_memoryLists.Next( FromHandle( hPrev ) ); - if ( iNext == m_memoryLists.InvalidIndex() ) - { - return INVALID_MEMHANDLE; - } - - return ToHandle( iNext ); - } - - MUTEX_TYPE &AccessMutex() { return m_mutex; } - virtual void Lock() { m_mutex.Lock(); } - virtual bool TryLock() { return m_mutex.TryLock(); } - virtual void Unlock() { m_mutex.Unlock(); } - -private: - STORAGE_TYPE *StoragePointer( void *pMem ) - { - return static_cast(pMem); - } - - virtual void DestroyResourceStorage( void *pStore ) - { - StoragePointer(pStore)->DestroyResource(); - } - - virtual unsigned int GetRealSize( void *pStore ) - { - return StoragePointer(pStore)->Size(); - } - - MUTEX_TYPE m_mutex; -}; - -//----------------------------------------------------------------------------- - -inline unsigned short CDataManagerBase::FromHandle( memhandle_t handle ) -{ - unsigned int fullWord = (unsigned int)handle; - unsigned short serial = fullWord>>16; - unsigned short index = fullWord & 0xFFFF; - index--; - if ( m_memoryLists.IsValidIndex(index) && m_memoryLists[index].serial == serial ) - return index; - return m_memoryLists.InvalidIndex(); -} - -inline int CDataManagerBase::LockCount( memhandle_t handle ) -{ - Lock(); - int result = 0; - unsigned short memoryIndex = FromHandle(handle); - if ( memoryIndex != m_memoryLists.InvalidIndex() ) - { - result = m_memoryLists[memoryIndex].lockCount; - } - Unlock(); - return result; -} - - -#endif // RESOURCEMANAGER_H diff --git a/public/tier1/delegates.h b/public/tier1/delegates.h deleted file mode 100644 index 9b715c0ac..000000000 --- a/public/tier1/delegates.h +++ /dev/null @@ -1,99 +0,0 @@ -//========== Copyright 2005, Valve Corporation, All rights reserved. ======== -// -// Purpose: Simple macros to generate delegation code -// -//============================================================================= - -#ifndef DELEGATES_H -#define DELEGATES_H - -#if defined( _WIN32 ) -#pragma once -#endif - -#define DELEGATE_TO_OBJECT_0( RetType, FuncName, pDelegated ) RetType FuncName() { return (pDelegated)->FuncName(); } -#define DELEGATE_TO_OBJECT_0V( FuncName, pDelegated ) void FuncName() { (pDelegated)->FuncName(); } -#define DELEGATE_TO_OBJECT_1( RetType, FuncName, ArgType1, pDelegated ) RetType FuncName( ArgType1 a1 ) { return (pDelegated)->FuncName( a1 ); } -#define DELEGATE_TO_OBJECT_1V( FuncName, ArgType1, pDelegated ) void FuncName( ArgType1 a1 ) { (pDelegated)->FuncName( a1 ); } -#define DELEGATE_TO_OBJECT_2( RetType, FuncName, ArgType1, ArgType2, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2 ) { return (pDelegated)->FuncName( a1, a2 ); } -#define DELEGATE_TO_OBJECT_2V( FuncName, ArgType1, ArgType2, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2 ) { (pDelegated)->FuncName( a1, a2 ); } -#define DELEGATE_TO_OBJECT_3( RetType, FuncName, ArgType1, ArgType2, ArgType3, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) { return (pDelegated)->FuncName( a1, a2, a3 ); } -#define DELEGATE_TO_OBJECT_3V( FuncName, ArgType1, ArgType2, ArgType3, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) { (pDelegated)->FuncName( a1, a2, a3 ); } -#define DELEGATE_TO_OBJECT_4( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) { return (pDelegated)->FuncName( a1, a2, a3, a4 ); } -#define DELEGATE_TO_OBJECT_4V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) { (pDelegated)->FuncName( a1, a2, a3, a4 ); } -#define DELEGATE_TO_OBJECT_5( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) { return (pDelegated)->FuncName( a1, a2, a3, a4, a5 ); } -#define DELEGATE_TO_OBJECT_5V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) { (pDelegated)->FuncName( a1, a2, a3, a4, a5 ); } -#define DELEGATE_TO_OBJECT_6( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6 ); } -#define DELEGATE_TO_OBJECT_6V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6 ); } -#define DELEGATE_TO_OBJECT_7( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7 ); } -#define DELEGATE_TO_OBJECT_7V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7 ); } -#define DELEGATE_TO_OBJECT_8( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); } -#define DELEGATE_TO_OBJECT_8V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); } -#define DELEGATE_TO_OBJECT_9( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); } -#define DELEGATE_TO_OBJECT_9V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); } -#define DELEGATE_TO_OBJECT_11V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9, ArgType10 a10, ArgType11 a11 ) { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11 ); } - -#define DELEGATE_TO_OBJECT_0C( RetType, FuncName, pDelegated ) RetType FuncName() const { return (pDelegated)->FuncName(); } -#define DELEGATE_TO_OBJECT_0VC( FuncName, pDelegated ) void FuncName() const { (pDelegated)->FuncName(); } -#define DELEGATE_TO_OBJECT_1C( RetType, FuncName, ArgType1, pDelegated ) RetType FuncName( ArgType1 a1 ) const { return (pDelegated)->FuncName( a1 ); } -#define DELEGATE_TO_OBJECT_1VC( FuncName, ArgType1, pDelegated ) void FuncName( ArgType1 a1 ) const { (pDelegated)->FuncName( a1 ); } -#define DELEGATE_TO_OBJECT_2C( RetType, FuncName, ArgType1, ArgType2, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2 ) const { return (pDelegated)->FuncName( a1, a2 ); } -#define DELEGATE_TO_OBJECT_2VC( FuncName, ArgType1, ArgType2, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2 ) const { (pDelegated)->FuncName( a1, a2 ); } -#define DELEGATE_TO_OBJECT_3C( RetType, FuncName, ArgType1, ArgType2, ArgType3, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) const { return (pDelegated)->FuncName( a1, a2, a3 ); } -#define DELEGATE_TO_OBJECT_3VC( FuncName, ArgType1, ArgType2, ArgType3, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) const { (pDelegated)->FuncName( a1, a2, a3 ); } -#define DELEGATE_TO_OBJECT_4C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) const { return (pDelegated)->FuncName( a1, a2, a3, a4 ); } -#define DELEGATE_TO_OBJECT_4VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) const { (pDelegated)->FuncName( a1, a2, a3, a4 ); } -#define DELEGATE_TO_OBJECT_5C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) const { return (pDelegated)->FuncName( a1, a2, a3, a4, a5 ); } -#define DELEGATE_TO_OBJECT_5VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) const { (pDelegated)->FuncName( a1, a2, a3, a4, a5 ); } -#define DELEGATE_TO_OBJECT_6C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) const { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6 ); } -#define DELEGATE_TO_OBJECT_6VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) const { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6 ); } -#define DELEGATE_TO_OBJECT_7C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) const { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7 ); } -#define DELEGATE_TO_OBJECT_7VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) const { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7 ); } -#define DELEGATE_TO_OBJECT_8C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) const { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); } -#define DELEGATE_TO_OBJECT_8VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) const { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); } -#define DELEGATE_TO_OBJECT_9C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, pDelegated ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) const { return (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); } -#define DELEGATE_TO_OBJECT_9VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, pDelegated ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) const { (pDelegated)->FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); } - -#define DELEGATE_TO_BASE_0( RetType, FuncName, BaseClass ) RetType FuncName() { return BaseClass::FuncName(); } -#define DELEGATE_TO_BASE_0V( FuncName, BaseClass ) void FuncName() { BaseClass::FuncName(); } -#define DELEGATE_TO_BASE_1( RetType, FuncName, ArgType1, BaseClass ) RetType FuncName( ArgType1 a1 ) { return BaseClass::FuncName( a1 ); } -#define DELEGATE_TO_BASE_1V( FuncName, ArgType1, BaseClass ) void FuncName( ArgType1 a1 ) { BaseClass::FuncName( a1 ); } -#define DELEGATE_TO_BASE_2( RetType, FuncName, ArgType1, ArgType2, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2 ) { return BaseClass::FuncName( a1, a2 ); } -#define DELEGATE_TO_BASE_2V( FuncName, ArgType1, ArgType2, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2 ) { BaseClass::FuncName( a1, a2 ); } -#define DELEGATE_TO_BASE_3( RetType, FuncName, ArgType1, ArgType2, ArgType3, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) { return BaseClass::FuncName( a1, a2, a3 ); } -#define DELEGATE_TO_BASE_3V( FuncName, ArgType1, ArgType2, ArgType3, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) { BaseClass::FuncName( a1, a2, a3 ); } -#define DELEGATE_TO_BASE_4( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) { return BaseClass::FuncName( a1, a2, a3, a4 ); } -#define DELEGATE_TO_BASE_4V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) { BaseClass::FuncName( a1, a2, a3, a4 ); } -#define DELEGATE_TO_BASE_5( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) { return BaseClass::FuncName( a1, a2, a3, a4, a5 ); } -#define DELEGATE_TO_BASE_5V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) { BaseClass::FuncName( a1, a2, a3, a4, a5 ); } -#define DELEGATE_TO_BASE_6( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6 ); } -#define DELEGATE_TO_BASE_6V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) { BaseClass::FuncName( a1, a2, a3, a4, a5, a6 ); } -#define DELEGATE_TO_BASE_7( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7 ); } -#define DELEGATE_TO_BASE_7V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) { BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7 ); } -#define DELEGATE_TO_BASE_8( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); } -#define DELEGATE_TO_BASE_8V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) { BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); } -#define DELEGATE_TO_BASE_9( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); } -#define DELEGATE_TO_BASE_9V( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) { BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); } - -#define DELEGATE_TO_BASE_0C( RetType, FuncName, BaseClass ) RetType FuncName() const { return BaseClass::FuncName(); } -#define DELEGATE_TO_BASE_0VC( FuncName, BaseClass ) void FuncName() const { BaseClass::FuncName(); } -#define DELEGATE_TO_BASE_1C( RetType, FuncName, ArgType1, BaseClass ) RetType FuncName( ArgType1 a1 ) const { return BaseClass::FuncName( a1 ); } -#define DELEGATE_TO_BASE_1VC( FuncName, ArgType1, BaseClass ) void FuncName( ArgType1 a1 ) const { BaseClass::FuncName( a1 ); } -#define DELEGATE_TO_BASE_2C( RetType, FuncName, ArgType1, ArgType2, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2 ) const { return BaseClass::FuncName( a1, a2 ); } -#define DELEGATE_TO_BASE_2VC( FuncName, ArgType1, ArgType2, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2 ) const { BaseClass::FuncName( a1, a2 ); } -#define DELEGATE_TO_BASE_3C( RetType, FuncName, ArgType1, ArgType2, ArgType3, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) const { return BaseClass::FuncName( a1, a2, a3 ); } -#define DELEGATE_TO_BASE_3VC( FuncName, ArgType1, ArgType2, ArgType3, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3 ) const { BaseClass::FuncName( a1, a2, a3 ); } -#define DELEGATE_TO_BASE_4C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) const { return BaseClass::FuncName( a1, a2, a3, a4 ); } -#define DELEGATE_TO_BASE_4VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4 ) const { BaseClass::FuncName( a1, a2, a3, a4 ); } -#define DELEGATE_TO_BASE_5C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) const { return BaseClass::FuncName( a1, a2, a3, a4, a5 ); } -#define DELEGATE_TO_BASE_5VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5 ) const { BaseClass::FuncName( a1, a2, a3, a4, a5 ); } -#define DELEGATE_TO_BASE_6C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) const { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6 ); } -#define DELEGATE_TO_BASE_6VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6 ) const { BaseClass::FuncName( a1, a2, a3, a4, a5, a6 ); } -#define DELEGATE_TO_BASE_7C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) const { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7 ); } -#define DELEGATE_TO_BASE_7VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7 ) const { BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7 ); } -#define DELEGATE_TO_BASE_8C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) const { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); } -#define DELEGATE_TO_BASE_8VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8 ) const { BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8 ); } -#define DELEGATE_TO_BASE_9C( RetType, FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, BaseClass ) RetType FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) const { return BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); } -#define DELEGATE_TO_BASE_9VC( FuncName, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, BaseClass ) void FuncName( ArgType1 a1, ArgType2 a2, ArgType3 a3, ArgType4 a4, ArgType5 a5, ArgType6 a6, ArgType7 a7, ArgType8 a8, ArgType9 a9 ) const { BaseClass::FuncName( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); } - -#endif // DELEGATES_H diff --git a/public/tier1/diff.h b/public/tier1/diff.h deleted file mode 100644 index 234894503..000000000 --- a/public/tier1/diff.h +++ /dev/null @@ -1,29 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -// Serialization/unserialization buffer -//=============================================================================// - -#ifndef DIFF_H -#define DIFF_H -#pragma once - -int FindDiffs(uint8 const *NewBlock, uint8 const *OldBlock, - int NewSize, int OldSize, int &DiffListSize,uint8 *Output,uint32 OutSize); - -int FindDiffsForLargeFiles(uint8 const *NewBlock, uint8 const *OldBlock, - int NewSize, int OldSize, int &DiffListSize,uint8 *Output, - uint32 OutSize, - int hashsize=65536); - -void ApplyDiffs(uint8 const *OldBlock, uint8 const *DiffList, - int OldSize, int DiffListSize, int &ResultListSize,uint8 *Output,uint32 OutSize); - -int FindDiffsLowMemory(uint8 const *NewBlock, uint8 const *OldBlock, - int NewSize, int OldSize, int &DiffListSize,uint8 *Output,uint32 OutSize); - -#endif - diff --git a/public/tier1/fmtstr.h b/public/tier1/fmtstr.h deleted file mode 100644 index adfe719c3..000000000 --- a/public/tier1/fmtstr.h +++ /dev/null @@ -1,82 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: A simple class for performing safe and in-expression sprintf-style -// string formatting -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef FMTSTR_H -#define FMTSTR_H - -#include -#include -#include "tier0/platform.h" -#include "tier1/strtools.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -//============================================================================= - -// using macro to be compatable with GCC -#define FmtStrVSNPrintf( szBuf, nBufSize, ppszFormat ) \ - do \ - { \ - int result; \ - va_list arg_ptr; \ - \ - va_start(arg_ptr, (*(ppszFormat))); \ - result = Q_vsnprintf((szBuf), (nBufSize)-1, (*(ppszFormat)), arg_ptr); \ - va_end(arg_ptr); \ - \ - (szBuf)[(nBufSize)-1] = 0; \ - } \ - while (0) - -//----------------------------------------------------------------------------- -// -// Purpose: String formatter with specified size -// - -template -class CFmtStrN -{ -public: - CFmtStrN() { m_szBuf[0] = 0; } - - // Standard C formatting - CFmtStrN(const char *pszFormat, ...) { FmtStrVSNPrintf(m_szBuf, SIZE_BUF, &pszFormat); } - - // Use this for pass-through formatting - CFmtStrN(const char ** ppszFormat, ...) { FmtStrVSNPrintf(m_szBuf, SIZE_BUF, ppszFormat); } - - // Explicit reformat - const char *sprintf(const char *pszFormat, ...) { FmtStrVSNPrintf(m_szBuf, SIZE_BUF, &pszFormat); return m_szBuf; } - - // Use this for pass-through formatting - void VSprintf(const char **ppszFormat, ...) { FmtStrVSNPrintf(m_szBuf, SIZE_BUF, ppszFormat); } - - // Use for access - operator const char *() const { return m_szBuf; } - char *Access() { return m_szBuf; } - - void Clear() { m_szBuf[0] = 0; } - -private: - char m_szBuf[SIZE_BUF]; -}; - -//----------------------------------------------------------------------------- -// -// Purpose: Default-sized string formatter -// - -#define FMTSTR_STD_LEN 256 - -typedef CFmtStrN CFmtStr; - -//============================================================================= - -#endif // FMTSTR_H diff --git a/public/tier1/functors.h b/public/tier1/functors.h deleted file mode 100644 index 0a8a40555..000000000 --- a/public/tier1/functors.h +++ /dev/null @@ -1,619 +0,0 @@ -//========== Copyright © 2006, Valve Corporation, All rights reserved. ======== -// -// Purpose: Implements a generic infrastucture for functors combining -// a number of techniques to provide transparent parameter type -// deduction and packaging. Supports both member and non-member functions. -// -// See also: http://en.wikipedia.org/wiki/Function_object -// -// Note that getting into the guts of this file is not for the -// feint of heart. The core concept here is that the compiler can -// figure out all the parameter types. -// -// E.g.: -// -// struct CMyClass -// { -// void foo( int i) {} -// }; -// -// int bar(int i) { return i; } -// -// CMyClass myInstance; -// -// CFunctor *pFunctor = CreateFunctor( &myInstance, CMyClass::foo, 8675 ); -// CFunctor *pFunctor2 = CreateFunctor( &bar, 309 ); -// -// void CallEm() -// { -// (*pFunctor)(); -// (*pFunctor2)(); -// } -// -//============================================================================= - -#ifndef FUNCTORS_H -#define FUNCTORS_H - -#include "tier0/platform.h" -#include "tier1/refcount.h" -#include "tier1/utlenvelope.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -//----------------------------------------------------------------------------- -// -// Macros used as basis for template generation. Just ignore the man behind the -// curtain -// -//----------------------------------------------------------------------------- - -#define FUNC_TEMPLATE_ARG_PARAMS_0 -#define FUNC_BASE_TEMPLATE_ARG_PARAMS_0 -#define FUNC_ARG_MEMBERS_0 -#define FUNC_ARG_FORMAL_PARAMS_0 -#define FUNC_PROXY_ARG_FORMAL_PARAMS_0 -#define FUNC_CALL_ARGS_INIT_0 -#define FUNC_CALL_MEMBER_ARGS_0 -#define FUNC_CALL_ARGS_0 -#define FUNC_FUNCTOR_CALL_ARGS_0 -#define FUNC_TEMPLATE_FUNC_PARAMS_0 -#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_0 - -#define FUNC_TEMPLATE_ARG_PARAMS_1 , typename ARG_TYPE_1 -#define FUNC_BASE_TEMPLATE_ARG_PARAMS_1 , ARG_TYPE_1 -#define FUNC_ARG_MEMBERS_1 ARG_TYPE_1 m_arg1 -#define FUNC_ARG_FORMAL_PARAMS_1 , const ARG_TYPE_1 &arg1 -#define FUNC_PROXY_ARG_FORMAL_PARAMS_1 const ARG_TYPE_1 &arg1 -#define FUNC_CALL_ARGS_INIT_1 , m_arg1( arg1 ) -#define FUNC_CALL_MEMBER_ARGS_1 m_arg1 -#define FUNC_CALL_ARGS_1 arg1 -#define FUNC_FUNCTOR_CALL_ARGS_1 , arg1 -#define FUNC_TEMPLATE_FUNC_PARAMS_1 , typename FUNC_ARG_TYPE_1 -#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_1 FUNC_ARG_TYPE_1 - -#define FUNC_TEMPLATE_ARG_PARAMS_2 , typename ARG_TYPE_1, typename ARG_TYPE_2 -#define FUNC_BASE_TEMPLATE_ARG_PARAMS_2 , ARG_TYPE_1, ARG_TYPE_2 -#define FUNC_ARG_MEMBERS_2 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2 -#define FUNC_ARG_FORMAL_PARAMS_2 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2 -#define FUNC_PROXY_ARG_FORMAL_PARAMS_2 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2 -#define FUNC_CALL_ARGS_INIT_2 , m_arg1( arg1 ), m_arg2( arg2 ) -#define FUNC_CALL_MEMBER_ARGS_2 m_arg1, m_arg2 -#define FUNC_CALL_ARGS_2 arg1, arg2 -#define FUNC_FUNCTOR_CALL_ARGS_2 , arg1, arg2 -#define FUNC_TEMPLATE_FUNC_PARAMS_2 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2 -#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_2 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2 - -#define FUNC_TEMPLATE_ARG_PARAMS_3 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3 -#define FUNC_BASE_TEMPLATE_ARG_PARAMS_3 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3 -#define FUNC_ARG_MEMBERS_3 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3 -#define FUNC_ARG_FORMAL_PARAMS_3 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3 -#define FUNC_PROXY_ARG_FORMAL_PARAMS_3 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3 -#define FUNC_CALL_ARGS_INIT_3 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ) -#define FUNC_CALL_MEMBER_ARGS_3 m_arg1, m_arg2, m_arg3 -#define FUNC_CALL_ARGS_3 arg1, arg2, arg3 -#define FUNC_FUNCTOR_CALL_ARGS_3 , arg1, arg2, arg3 -#define FUNC_TEMPLATE_FUNC_PARAMS_3 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3 -#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_3 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3 - -#define FUNC_TEMPLATE_ARG_PARAMS_4 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4 -#define FUNC_BASE_TEMPLATE_ARG_PARAMS_4 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4 -#define FUNC_ARG_MEMBERS_4 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4 -#define FUNC_ARG_FORMAL_PARAMS_4 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4 -#define FUNC_PROXY_ARG_FORMAL_PARAMS_4 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4 -#define FUNC_CALL_ARGS_INIT_4 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ) -#define FUNC_CALL_MEMBER_ARGS_4 m_arg1, m_arg2, m_arg3, m_arg4 -#define FUNC_CALL_ARGS_4 arg1, arg2, arg3, arg4 -#define FUNC_FUNCTOR_CALL_ARGS_4 , arg1, arg2, arg3, arg4 -#define FUNC_TEMPLATE_FUNC_PARAMS_4 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4 -#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_4 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4 - -#define FUNC_TEMPLATE_ARG_PARAMS_5 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5 -#define FUNC_BASE_TEMPLATE_ARG_PARAMS_5 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5 -#define FUNC_ARG_MEMBERS_5 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5 -#define FUNC_ARG_FORMAL_PARAMS_5 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5 -#define FUNC_PROXY_ARG_FORMAL_PARAMS_5 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5 -#define FUNC_CALL_ARGS_INIT_5 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ) -#define FUNC_CALL_MEMBER_ARGS_5 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5 -#define FUNC_CALL_ARGS_5 arg1, arg2, arg3, arg4, arg5 -#define FUNC_FUNCTOR_CALL_ARGS_5 , arg1, arg2, arg3, arg4, arg5 -#define FUNC_TEMPLATE_FUNC_PARAMS_5 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5 -#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_5 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5 - -#define FUNC_TEMPLATE_ARG_PARAMS_6 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6 -#define FUNC_BASE_TEMPLATE_ARG_PARAMS_6 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6 -#define FUNC_ARG_MEMBERS_6 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6 -#define FUNC_ARG_FORMAL_PARAMS_6 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6 -#define FUNC_PROXY_ARG_FORMAL_PARAMS_6 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6 -#define FUNC_CALL_ARGS_INIT_6 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ) -#define FUNC_CALL_MEMBER_ARGS_6 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6 -#define FUNC_CALL_ARGS_6 arg1, arg2, arg3, arg4, arg5, arg6 -#define FUNC_FUNCTOR_CALL_ARGS_6 , arg1, arg2, arg3, arg4, arg5, arg6 -#define FUNC_TEMPLATE_FUNC_PARAMS_6 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6 -#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_6 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6 - -#define FUNC_TEMPLATE_ARG_PARAMS_7 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7 -#define FUNC_BASE_TEMPLATE_ARG_PARAMS_7 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7 -#define FUNC_ARG_MEMBERS_7 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7; -#define FUNC_ARG_FORMAL_PARAMS_7 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7 -#define FUNC_PROXY_ARG_FORMAL_PARAMS_7 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7 -#define FUNC_CALL_ARGS_INIT_7 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ) -#define FUNC_CALL_MEMBER_ARGS_7 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7 -#define FUNC_CALL_ARGS_7 arg1, arg2, arg3, arg4, arg5, arg6, arg7 -#define FUNC_FUNCTOR_CALL_ARGS_7 , arg1, arg2, arg3, arg4, arg5, arg6, arg7 -#define FUNC_TEMPLATE_FUNC_PARAMS_7 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7 -#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_7 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7 - -#define FUNC_TEMPLATE_ARG_PARAMS_8 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8 -#define FUNC_BASE_TEMPLATE_ARG_PARAMS_8 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8 -#define FUNC_ARG_MEMBERS_8 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7; ARG_TYPE_8 m_arg8; -#define FUNC_ARG_FORMAL_PARAMS_8 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8 -#define FUNC_PROXY_ARG_FORMAL_PARAMS_8 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8 -#define FUNC_CALL_ARGS_INIT_8 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ) -#define FUNC_CALL_MEMBER_ARGS_8 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8 -#define FUNC_CALL_ARGS_8 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 -#define FUNC_FUNCTOR_CALL_ARGS_8 , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 -#define FUNC_TEMPLATE_FUNC_PARAMS_8 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7, typename FUNC_ARG_TYPE_8 -#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_8 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7, FUNC_ARG_TYPE_8 - -#define FUNC_TEMPLATE_ARG_PARAMS_9 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9 -#define FUNC_BASE_TEMPLATE_ARG_PARAMS_9 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9 -#define FUNC_ARG_MEMBERS_9 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7; ARG_TYPE_8 m_arg8; ARG_TYPE_9 m_arg9; -#define FUNC_ARG_FORMAL_PARAMS_9 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9 -#define FUNC_PROXY_ARG_FORMAL_PARAMS_9 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9 -#define FUNC_CALL_ARGS_INIT_9 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ) -#define FUNC_CALL_MEMBER_ARGS_9 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9 -#define FUNC_CALL_ARGS_9 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 -#define FUNC_FUNCTOR_CALL_ARGS_9 , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 -#define FUNC_TEMPLATE_FUNC_PARAMS_9 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7, typename FUNC_ARG_TYPE_8, typename FUNC_ARG_TYPE_9 -#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_9 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7, FUNC_ARG_TYPE_8, FUNC_ARG_TYPE_9 - -#define FUNC_TEMPLATE_ARG_PARAMS_10 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10 -#define FUNC_BASE_TEMPLATE_ARG_PARAMS_10 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10 -#define FUNC_ARG_MEMBERS_10 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7; ARG_TYPE_8 m_arg8; ARG_TYPE_9 m_arg9; ARG_TYPE_10 m_arg10; -#define FUNC_ARG_FORMAL_PARAMS_10 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10 -#define FUNC_PROXY_ARG_FORMAL_PARAMS_10 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10 -#define FUNC_CALL_ARGS_INIT_10 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 ) -#define FUNC_CALL_MEMBER_ARGS_10 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10 -#define FUNC_CALL_ARGS_10 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 -#define FUNC_FUNCTOR_CALL_ARGS_10 , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 -#define FUNC_TEMPLATE_FUNC_PARAMS_10 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7, typename FUNC_ARG_TYPE_8, typename FUNC_ARG_TYPE_9, typename FUNC_ARG_TYPE_10 -#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_10 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7, FUNC_ARG_TYPE_8, FUNC_ARG_TYPE_9, FUNC_ARG_TYPE_10 - -#define FUNC_TEMPLATE_ARG_PARAMS_11 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10, typename ARG_TYPE_11 -#define FUNC_BASE_TEMPLATE_ARG_PARAMS_11 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10, ARG_TYPE_11 -#define FUNC_ARG_MEMBERS_11 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7; ARG_TYPE_8 m_arg8; ARG_TYPE_9 m_arg9; ARG_TYPE_10 m_arg10; ARG_TYPE_11 m_arg11 -#define FUNC_ARG_FORMAL_PARAMS_11 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11 -#define FUNC_PROXY_ARG_FORMAL_PARAMS_11 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11 -#define FUNC_CALL_ARGS_INIT_11 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 ), m_arg11( arg11 ) -#define FUNC_CALL_MEMBER_ARGS_11 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11 -#define FUNC_CALL_ARGS_11 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11 -#define FUNC_FUNCTOR_CALL_ARGS_11 , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11 -#define FUNC_TEMPLATE_FUNC_PARAMS_11 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7, typename FUNC_ARG_TYPE_8, typename FUNC_ARG_TYPE_9, typename FUNC_ARG_TYPE_10, typename FUNC_ARG_TYPE_11 -#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_11 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7, FUNC_ARG_TYPE_8, FUNC_ARG_TYPE_9, FUNC_ARG_TYPE_10, FUNC_ARG_TYPE_11 - -#define FUNC_TEMPLATE_ARG_PARAMS_12 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10, typename ARG_TYPE_11, typename ARG_TYPE_12 -#define FUNC_BASE_TEMPLATE_ARG_PARAMS_12 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10, ARG_TYPE_11, ARG_TYPE_12 -#define FUNC_ARG_MEMBERS_12 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7; ARG_TYPE_8 m_arg8; ARG_TYPE_9 m_arg9; ARG_TYPE_10 m_arg10; ARG_TYPE_11 m_arg11; ARG_TYPE_12 m_arg12 -#define FUNC_ARG_FORMAL_PARAMS_12 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11, const ARG_TYPE_12 &arg12 -#define FUNC_PROXY_ARG_FORMAL_PARAMS_12 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11, const ARG_TYPE_12 &arg12 -#define FUNC_CALL_ARGS_INIT_12 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 ), m_arg11( arg11 ), m_arg12( arg12 ) -#define FUNC_CALL_MEMBER_ARGS_12 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12 -#define FUNC_CALL_ARGS_12 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12 -#define FUNC_FUNCTOR_CALL_ARGS_12 , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12 -#define FUNC_TEMPLATE_FUNC_PARAMS_12 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7, typename FUNC_ARG_TYPE_8, typename FUNC_ARG_TYPE_9, typename FUNC_ARG_TYPE_10, typename FUNC_ARG_TYPE_11, typename FUNC_ARG_TYPE_12 -#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_12 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7, FUNC_ARG_TYPE_8, FUNC_ARG_TYPE_9, FUNC_ARG_TYPE_10, FUNC_ARG_TYPE_11, FUNC_ARG_TYPE_12 - -#define FUNC_TEMPLATE_ARG_PARAMS_13 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10, typename ARG_TYPE_11, typename ARG_TYPE_12, typename ARG_TYPE_13 -#define FUNC_BASE_TEMPLATE_ARG_PARAMS_13 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10, ARG_TYPE_11, ARG_TYPE_12, ARG_TYPE_13 -#define FUNC_ARG_MEMBERS_13 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7; ARG_TYPE_8 m_arg8; ARG_TYPE_9 m_arg9; ARG_TYPE_10 m_arg10; ARG_TYPE_11 m_arg11; ARG_TYPE_12 m_arg12; ARG_TYPE_13 m_arg13 -#define FUNC_ARG_FORMAL_PARAMS_13 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11, const ARG_TYPE_12 &arg12, const ARG_TYPE_13 &arg13 -#define FUNC_PROXY_ARG_FORMAL_PARAMS_13 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11, const ARG_TYPE_12 &arg12, const ARG_TYPE_13 &arg13 -#define FUNC_CALL_ARGS_INIT_13 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 ), m_arg11( arg11 ), m_arg12( arg12 ), m_arg13( arg13 ) -#define FUNC_CALL_MEMBER_ARGS_13 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12, m_arg13 -#define FUNC_CALL_ARGS_13 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13 -#define FUNC_FUNCTOR_CALL_ARGS_13 , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13 -#define FUNC_TEMPLATE_FUNC_PARAMS_13 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7, typename FUNC_ARG_TYPE_8, typename FUNC_ARG_TYPE_9, typename FUNC_ARG_TYPE_10, typename FUNC_ARG_TYPE_11, typename FUNC_ARG_TYPE_12, typename FUNC_ARG_TYPE_13 -#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_13 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7, FUNC_ARG_TYPE_8, FUNC_ARG_TYPE_9, FUNC_ARG_TYPE_10, FUNC_ARG_TYPE_11, FUNC_ARG_TYPE_12, FUNC_ARG_TYPE_13 - -#define FUNC_TEMPLATE_ARG_PARAMS_14 , typename ARG_TYPE_1, typename ARG_TYPE_2, typename ARG_TYPE_3, typename ARG_TYPE_4, typename ARG_TYPE_5, typename ARG_TYPE_6, typename ARG_TYPE_7, typename ARG_TYPE_8, typename ARG_TYPE_9, typename ARG_TYPE_10, typename ARG_TYPE_11, typename ARG_TYPE_12, typename ARG_TYPE_13, typename ARG_TYPE_14 -#define FUNC_BASE_TEMPLATE_ARG_PARAMS_14 , ARG_TYPE_1, ARG_TYPE_2, ARG_TYPE_3, ARG_TYPE_4, ARG_TYPE_5, ARG_TYPE_6, ARG_TYPE_7, ARG_TYPE_8, ARG_TYPE_9, ARG_TYPE_10, ARG_TYPE_11, ARG_TYPE_12, ARG_TYPE_13, ARG_TYPE_14 -#define FUNC_ARG_MEMBERS_14 ARG_TYPE_1 m_arg1; ARG_TYPE_2 m_arg2; ARG_TYPE_3 m_arg3; ARG_TYPE_4 m_arg4; ARG_TYPE_5 m_arg5; ARG_TYPE_6 m_arg6; ARG_TYPE_7 m_arg7; ARG_TYPE_8 m_arg8; ARG_TYPE_9 m_arg9; ARG_TYPE_10 m_arg10; ARG_TYPE_11 m_arg11; ARG_TYPE_12 m_arg12; ARG_TYPE_13 m_arg13; ARG_TYPE_14 m_arg14 -#define FUNC_ARG_FORMAL_PARAMS_14 , const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11, const ARG_TYPE_12 &arg12, const ARG_TYPE_13 &arg13, const ARG_TYPE_14 &arg14 -#define FUNC_PROXY_ARG_FORMAL_PARAMS_14 const ARG_TYPE_1 &arg1, const ARG_TYPE_2 &arg2, const ARG_TYPE_3 &arg3, const ARG_TYPE_4 &arg4, const ARG_TYPE_5 &arg5, const ARG_TYPE_6 &arg6, const ARG_TYPE_7 &arg7, const ARG_TYPE_8 &arg8, const ARG_TYPE_9 &arg9, const ARG_TYPE_10 &arg10, const ARG_TYPE_11 &arg11, const ARG_TYPE_12 &arg12, const ARG_TYPE_13 &arg13, const ARG_TYPE_14 &arg14 -#define FUNC_CALL_ARGS_INIT_14 , m_arg1( arg1 ), m_arg2( arg2 ), m_arg3( arg3 ), m_arg4( arg4 ), m_arg5( arg5 ), m_arg6( arg6 ), m_arg7( arg7 ), m_arg8( arg8 ), m_arg9( arg9 ), m_arg10( arg10 ), m_arg11( arg11 ), m_arg12( arg12 ), m_arg13( arg13 ), m_arg14( arg14 ) -#define FUNC_CALL_MEMBER_ARGS_14 m_arg1, m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_arg9, m_arg10, m_arg11, m_arg12, m_arg13, m_arg14 -#define FUNC_CALL_ARGS_14 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14 -#define FUNC_FUNCTOR_CALL_ARGS_14 , arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14 -#define FUNC_TEMPLATE_FUNC_PARAMS_14 , typename FUNC_ARG_TYPE_1, typename FUNC_ARG_TYPE_2, typename FUNC_ARG_TYPE_3, typename FUNC_ARG_TYPE_4, typename FUNC_ARG_TYPE_5, typename FUNC_ARG_TYPE_6, typename FUNC_ARG_TYPE_7, typename FUNC_ARG_TYPE_8, typename FUNC_ARG_TYPE_9, typename FUNC_ARG_TYPE_10, typename FUNC_ARG_TYPE_11, typename FUNC_ARG_TYPE_12, typename FUNC_ARG_TYPE_13, typename FUNC_ARG_TYPE_14 -#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_14 FUNC_ARG_TYPE_1, FUNC_ARG_TYPE_2, FUNC_ARG_TYPE_3, FUNC_ARG_TYPE_4, FUNC_ARG_TYPE_5, FUNC_ARG_TYPE_6, FUNC_ARG_TYPE_7, FUNC_ARG_TYPE_8, FUNC_ARG_TYPE_9, FUNC_ARG_TYPE_10, FUNC_ARG_TYPE_11, FUNC_ARG_TYPE_12, FUNC_ARG_TYPE_13, FUNC_ARG_TYPE_14 - -#define FUNC_GENERATE_ALL( INNERMACRONAME ) \ - INNERMACRONAME(0); \ - INNERMACRONAME(1); \ - INNERMACRONAME(2); \ - INNERMACRONAME(3); \ - INNERMACRONAME(4); \ - INNERMACRONAME(5); \ - INNERMACRONAME(6); \ - INNERMACRONAME(7); \ - INNERMACRONAME(8); \ - INNERMACRONAME(9); \ - INNERMACRONAME(10);\ - INNERMACRONAME(11);\ - INNERMACRONAME(12);\ - INNERMACRONAME(13);\ - INNERMACRONAME(14) - -//----------------------------------------------------------------------------- -// -// Purpose: Base class of all function objects -// -//----------------------------------------------------------------------------- - -abstract_class CFunctor : public IRefCounted -{ -public: - CFunctor() - { -#ifdef DEBUG - m_nUserID = 0; -#endif - } - - virtual ~CFunctor() {} - - virtual void operator()() = 0; - - unsigned m_nUserID; // For debugging -}; - - -//----------------------------------------------------------------------------- -// When calling through a functor, care needs to be taken to not pass objects that might go away. -// Since this code determines the type to store in the functor based on the actual arguments, -// this is achieved by changing the point of call. -// -// See also CUtlEnvelope -//----------------------------------------------------------------------------- - -// convert a reference to a passable value -template -inline T RefToVal(const T &item) -{ - return item; -} - -//----------------------------------------------------------------------------- -// This class can be used to pass into a functor a proxy object for a pointer -// to be resolved later. For example, you can execute a "call" on a resource -// whose actual value is not known until a later time -//----------------------------------------------------------------------------- - -template -class CLateBoundPtr -{ -public: - CLateBoundPtr( T **ppObject ) - : m_ppObject( ppObject ) - { - } - - T *operator->() { return *m_ppObject; } - T &operator *() { return **m_ppObject; } - operator T *() const { return (T*)(*m_ppObject); } - operator void *() { return *m_ppObject; } - -private: - T **m_ppObject; -}; - -//----------------------------------------------------------------------------- -// -// Purpose: Classes to define memory management policies when operating -// on pointers to members -// -//----------------------------------------------------------------------------- - -class CFuncMemPolicyNone -{ -public: - static void OnAcquire(void *pObject) {} - static void OnRelease(void *pObject) {} -}; - -template -class CFuncMemPolicyRefCount -{ -public: - static void OnAcquire(OBJECT_TYPE_PTR pObject) { pObject->AddRef(); } - static void OnRelease(OBJECT_TYPE_PTR pObject) { pObject->Release(); } -}; - -//----------------------------------------------------------------------------- -// -// Purpose: Function proxy is a generic facility for holding a function -// pointer. Can be used on own, though primarily for use -// by this file -// -//----------------------------------------------------------------------------- - -template -class CMemberFuncProxyBase -{ -protected: - CMemberFuncProxyBase( OBJECT_TYPE_PTR pObject, FUNCTION_TYPE pfnProxied ) - : m_pfnProxied( pfnProxied ), m_pObject( pObject ) - { - MEM_POLICY::OnAcquire(m_pObject); - } - - ~CMemberFuncProxyBase() - { - MEM_POLICY::OnRelease(m_pObject); - } - - void Set( OBJECT_TYPE_PTR pObject, FUNCTION_TYPE pfnProxied ) - { - m_pfnProxied = pfnProxied; - m_pObject = pObject; - } - - void OnCall() - { - Assert( (void *)m_pObject != NULL ); - } - - FUNCTION_TYPE m_pfnProxied; - OBJECT_TYPE_PTR m_pObject; -}; - - -#define DEFINE_MEMBER_FUNC_PROXY( N ) \ - template \ - class CMemberFuncProxy##N : public CMemberFuncProxyBase \ - { \ - public: \ - CMemberFuncProxy##N( OBJECT_TYPE_PTR pObject = NULL, FUNCTION_TYPE pfnProxied = NULL ) \ - : CMemberFuncProxyBase( pObject, pfnProxied ) \ - { \ - } \ - \ - void operator()( FUNC_PROXY_ARG_FORMAL_PARAMS_##N ) \ - { \ - this->OnCall(); \ - ((*this->m_pObject).*this->m_pfnProxied)( FUNC_CALL_ARGS_##N ); \ - } \ - } - -FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNC_PROXY ); - - -//----------------------------------------------------------------------------- -// -// The actual functor implementation -// -//----------------------------------------------------------------------------- - -#include "tier0/memdbgon.h" - -typedef CRefCounted1 CFunctorBase; - -#define DEFINE_FUNCTOR_TEMPLATE(N) \ - template \ - class CFunctor##N : public CFunctorBase \ - { \ - public: \ - CFunctor##N( FUNC_TYPE pfnProxied FUNC_ARG_FORMAL_PARAMS_##N ) : m_pfnProxied( pfnProxied ) FUNC_CALL_ARGS_INIT_##N {} \ - void operator()() { m_pfnProxied(FUNC_CALL_MEMBER_ARGS_##N); } \ - \ - private: \ - FUNC_TYPE m_pfnProxied; \ - FUNC_ARG_MEMBERS_##N; \ - } - -FUNC_GENERATE_ALL( DEFINE_FUNCTOR_TEMPLATE ); - -#define DEFINE_MEMBER_FUNCTOR( N ) \ - template \ - class CMemberFunctor##N : public FUNCTOR_BASE \ - { \ - public: \ - CMemberFunctor##N( OBJECT_TYPE_PTR pObject, FUNCTION_TYPE pfnProxied FUNC_ARG_FORMAL_PARAMS_##N ) : m_Proxy( pObject, pfnProxied ) FUNC_CALL_ARGS_INIT_##N {} \ - void operator()() { m_Proxy(FUNC_CALL_MEMBER_ARGS_##N); } \ - \ - private: \ - CMemberFuncProxy##N m_Proxy; \ - FUNC_ARG_MEMBERS_##N; \ - }; - - -FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNCTOR ); - -//----------------------------------------------------------------------------- -// -// The real magic, letting the compiler figure out all the right template parameters -// -//----------------------------------------------------------------------------- - -#define DEFINE_NONMEMBER_FUNCTOR_FACTORY(N) \ - template \ - inline CFunctor *CreateFunctor(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - typedef FUNCTION_RETTYPE (*Func_t)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N); \ - return new CFunctor##N( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \ - } - -FUNC_GENERATE_ALL( DEFINE_NONMEMBER_FUNCTOR_FACTORY ); - -//------------------------------------- - -#define DEFINE_MEMBER_FUNCTOR_FACTORY(N) \ -template \ -inline CFunctor *CreateFunctor(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ -{ \ - return new CMemberFunctor##N(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \ -} - -FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNCTOR_FACTORY ); - -//------------------------------------- - -#define DEFINE_CONST_MEMBER_FUNCTOR_FACTORY(N) \ - template \ - inline CFunctor *CreateFunctor(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - return new CMemberFunctor##N(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \ - } - -FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_FUNCTOR_FACTORY ); - -//------------------------------------- - -#define DEFINE_REF_COUNTING_MEMBER_FUNCTOR_FACTORY(N) \ - template \ - inline CFunctor *CreateRefCountingFunctor(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - return new CMemberFunctor##N >(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \ - } - -FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_MEMBER_FUNCTOR_FACTORY ); - -//------------------------------------- - -#define DEFINE_REF_COUNTING_CONST_MEMBER_FUNCTOR_FACTORY(N) \ - template \ - inline CFunctor *CreateRefCountingFunctor(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - return new CMemberFunctor##N >(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \ - } - -FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_CONST_MEMBER_FUNCTOR_FACTORY ); - -//----------------------------------------------------------------------------- -// -// Templates to assist early-out direct call code -// -//----------------------------------------------------------------------------- - -#define DEFINE_NONMEMBER_FUNCTOR_DIRECT(N) \ - template \ - inline void FunctorDirectCall(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ -{ \ - (*pfnProxied)( FUNC_CALL_ARGS_##N ); \ -} - -FUNC_GENERATE_ALL( DEFINE_NONMEMBER_FUNCTOR_DIRECT ); - - -//------------------------------------- - -#define DEFINE_MEMBER_FUNCTOR_DIRECT(N) \ - template \ - inline void FunctorDirectCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ -{ \ - ((*pObject).*pfnProxied)(FUNC_CALL_ARGS_##N); \ -} - -FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNCTOR_DIRECT ); - -//------------------------------------- - -#define DEFINE_CONST_MEMBER_FUNCTOR_DIRECT(N) \ - template \ - inline void FunctorDirectCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \ -{ \ - ((*pObject).*pfnProxied)(FUNC_CALL_ARGS_##N); \ -} - -FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_FUNCTOR_DIRECT ); - -#include "tier0/memdbgoff.h" - -//----------------------------------------------------------------------------- -// Factory class useable as templated traits -//----------------------------------------------------------------------------- - -class CDefaultFunctorFactory -{ -public: - FUNC_GENERATE_ALL( DEFINE_NONMEMBER_FUNCTOR_FACTORY ); - FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNCTOR_FACTORY ); - FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_FUNCTOR_FACTORY ); - FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_MEMBER_FUNCTOR_FACTORY ); - FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_CONST_MEMBER_FUNCTOR_FACTORY ); -}; - -template -class CCustomizedFunctorFactory -{ -public: - void SetAllocator( CAllocator *pAllocator ) - { - m_pAllocator = pAllocator; - } - - #define DEFINE_NONMEMBER_FUNCTOR_FACTORY_CUSTOM(N) \ - template \ - inline CFunctor *CreateFunctor( FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - typedef FUNCTION_RETTYPE (*Func_t)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N); \ - return new (m_pAllocator->Alloc( sizeof(CFunctor##N) )) CFunctor##N( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \ - } - - FUNC_GENERATE_ALL( DEFINE_NONMEMBER_FUNCTOR_FACTORY_CUSTOM ); - - //------------------------------------- - - #define DEFINE_MEMBER_FUNCTOR_FACTORY_CUSTOM(N) \ - template \ - inline CFunctor *CreateFunctor(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - return new (m_pAllocator->Alloc( sizeof(CMemberFunctor##N) )) CMemberFunctor##N(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \ - } - - FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNCTOR_FACTORY_CUSTOM ); - - //------------------------------------- - - #define DEFINE_CONST_MEMBER_FUNCTOR_FACTORY_CUSTOM(N) \ - template \ - inline CFunctor *CreateFunctor( OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - return new (m_pAllocator->Alloc( sizeof(CMemberFunctor##N) )) CMemberFunctor##N(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \ - } - - FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_FUNCTOR_FACTORY_CUSTOM ); - - //------------------------------------- - - #define DEFINE_REF_COUNTING_MEMBER_FUNCTOR_FACTORY_CUSTOM(N) \ - template \ - inline CFunctor *CreateRefCountingFunctor( OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - return new (m_pAllocator->Alloc( sizeof(CMemberFunctor##N >) )) CMemberFunctor##N >(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \ - } - - FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_MEMBER_FUNCTOR_FACTORY_CUSTOM ); - - //------------------------------------- - - #define DEFINE_REF_COUNTING_CONST_MEMBER_FUNCTOR_FACTORY_CUSTOM(N) \ - template \ - inline CFunctor *CreateRefCountingFunctor( OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - return new (m_pAllocator->Alloc( sizeof(CMemberFunctor##N >) )) CMemberFunctor##N >(pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N); \ - } - - FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_CONST_MEMBER_FUNCTOR_FACTORY_CUSTOM ); - -private: - CAllocator *m_pAllocator; - -}; - -//----------------------------------------------------------------------------- - -#endif // FUNCTORS_H diff --git a/public/tier1/generichash.h b/public/tier1/generichash.h deleted file mode 100644 index dc796ee4c..000000000 --- a/public/tier1/generichash.h +++ /dev/null @@ -1,92 +0,0 @@ -//======= Copyright 2005, , Valve Corporation, All rights reserved. ========= -// -// Purpose: Variant Pearson Hash general purpose hashing algorithm described -// by Cargill in C++ Report 1994. Generates a 16-bit result. -// -//============================================================================= - -#ifndef GENERICHASH_H -#define GENERICHASH_H - -#if defined(_WIN32) -#pragma once -#endif - -//----------------------------------------------------------------------------- - -unsigned FASTCALL HashString( const char *pszKey ); -unsigned FASTCALL HashStringCaseless( const char *pszKey ); -unsigned FASTCALL HashStringCaselessConventional( const char *pszKey ); -unsigned FASTCALL Hash4( const void *pKey ); -unsigned FASTCALL Hash8( const void *pKey ); -unsigned FASTCALL Hash12( const void *pKey ); -unsigned FASTCALL Hash16( const void *pKey ); -unsigned FASTCALL HashBlock( const void *pKey, unsigned size ); - -unsigned FASTCALL HashInt( const int key ); - -inline unsigned HashIntConventional( const int n ) // faster but less effective -{ - // first byte - unsigned hash = 0xAAAAAAAA + (n & 0xFF); - // second byte - hash = ( hash << 5 ) + hash + ( (n >> 8) & 0xFF ); - // third byte - hash = ( hash << 5 ) + hash + ( (n >> 16) & 0xFF ); - // fourth byte - hash = ( hash << 5 ) + hash + ( (n >> 24) & 0xFF ); - - return hash; - - /* this is the old version, which would cause a load-hit-store on every - line on a PowerPC, and therefore took hundreds of clocks to execute! - - byte *p = (byte *)&n; - unsigned hash = 0xAAAAAAAA + *p++; - hash = ( ( hash << 5 ) + hash ) + *p++; - hash = ( ( hash << 5 ) + hash ) + *p++; - return ( ( hash << 5 ) + hash ) + *p; - */ -} - -//----------------------------------------------------------------------------- - -template -inline unsigned HashItem( const T &item ) -{ - // TODO: Confirm comiler optimizes out unused paths - if ( sizeof(item) == 4 ) - return Hash4( &item ); - else if ( sizeof(item) == 8 ) - return Hash8( &item ); - else if ( sizeof(item) == 12 ) - return Hash12( &item ); - else if ( sizeof(item) == 16 ) - return Hash16( &item ); - else - return HashBlock( &item, sizeof(item) ); -} - -template <> inline unsigned HashItem(const int &key ) -{ - return HashInt( key ); -} - -template <> inline unsigned HashItem(const unsigned &key ) -{ - return HashInt( (int)key ); -} - -template<> inline unsigned HashItem(const char * const &pszKey ) -{ - return HashString( pszKey ); -} - -template<> inline unsigned HashItem(char * const &pszKey ) -{ - return HashString( pszKey ); -} - -//----------------------------------------------------------------------------- - -#endif /* !GENERICHASH_H */ diff --git a/public/tier1/iconvar.h b/public/tier1/iconvar.h deleted file mode 100644 index 4a3c06bf3..000000000 --- a/public/tier1/iconvar.h +++ /dev/null @@ -1,114 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $NoKeywords: $ -//===========================================================================// - -#ifndef ICONVAR_H -#define ICONVAR_H - -#if _WIN32 -#pragma once -#endif - -#include "tier0/dbg.h" -#include "tier0/platform.h" -#include "tier1/strtools.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class IConVar; -class CCommand; - - -//----------------------------------------------------------------------------- -// ConVar flags -//----------------------------------------------------------------------------- -// The default, no flags at all -#define FCVAR_NONE 0 - -// Command to ConVars and ConCommands -// ConVar Systems -#define FCVAR_UNREGISTERED (1<<0) // If this is set, don't add to linked list, etc. -#define FCVAR_DEVELOPMENTONLY (1<<1) // Hidden in released products. Flag is removed automatically if ALLOW_DEVELOPMENT_CVARS is defined. -#define FCVAR_GAMEDLL (1<<2) // defined by the game DLL -#define FCVAR_CLIENTDLL (1<<3) // defined by the client DLL -#define FCVAR_HIDDEN (1<<4) // Hidden. Doesn't appear in find or autocomplete. Like DEVELOPMENTONLY, but can't be compiled out. - -// ConVar only -#define FCVAR_PROTECTED (1<<5) // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value -#define FCVAR_SPONLY (1<<6) // This cvar cannot be changed by clients connected to a multiplayer server. -#define FCVAR_ARCHIVE (1<<7) // set to cause it to be saved to vars.rc -#define FCVAR_NOTIFY (1<<8) // notifies players when changed -#define FCVAR_USERINFO (1<<9) // changes the client's info string -#define FCVAR_CHEAT (1<<14) // Only useable in singleplayer / debug / multiplayer & sv_cheats - -#define FCVAR_PRINTABLEONLY (1<<10) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ). -#define FCVAR_UNLOGGED (1<<11) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log -#define FCVAR_NEVER_AS_STRING (1<<12) // never try to print that cvar - -// It's a ConVar that's shared between the client and the server. -// At signon, the values of all such ConVars are sent from the server to the client (skipped for local -// client, of course ) -// If a change is requested it must come from the console (i.e., no remote client changes) -// If a value is changed while a server is active, it's replicated to all connected clients -#define FCVAR_REPLICATED (1<<13) // server setting enforced on clients, TODO rename to FCAR_SERVER at some time -#define FCVAR_DEMO (1<<16) // record this cvar when starting a demo file -#define FCVAR_DONTRECORD (1<<17) // don't record these command in demofiles - -#define FCVAR_NOT_CONNECTED (1<<22) // cvar cannot be changed by a client that is connected to a server - -#define FCVAR_ARCHIVE_XBOX (1<<24) // cvar written to config.cfg on the Xbox - -#define FCVAR_SERVER_CAN_EXECUTE (1<<28)// the server is allowed to execute this command on clients via ClientCommand/NET_StringCmd/CBaseClientState::ProcessStringCmd. -#define FCVAR_SERVER_CANNOT_QUERY (1<<29)// If this is set, then the server is not allowed to query this cvar's value (via IServerPluginHelpers::StartQueryCvarValue). -#define FCVAR_CLIENTCMD_CAN_EXECUTE (1<<30) // IVEngineClient::ClientCmd is allowed to execute this command. - // Note: IVEngineClient::ClientCmd_Unrestricted can run any client command. - -// #define FCVAR_AVAILABLE (1<<15) -// #define FCVAR_AVAILABLE (1<<18) -// #define FCVAR_AVAILABLE (1<<19) -// #define FCVAR_AVAILABLE (1<<20) -// #define FCVAR_AVAILABLE (1<<21) -// #define FCVAR_AVAILABLE (1<<23) -// #define FCVAR_AVAILABLE (1<<25) -// #define FCVAR_AVAILABLE (1<<26) -// #define FCVAR_AVAILABLE (1<<27) -// #define FCVAR_AVAILABLE (1<<31) - - -//----------------------------------------------------------------------------- -// Called when a ConVar changes value -// NOTE: For FCVAR_NEVER_AS_STRING ConVars, pOldValue == NULL -//----------------------------------------------------------------------------- -typedef void ( *FnChangeCallback_t )( IConVar *var, const char *pOldValue, float flOldValue ); - - -//----------------------------------------------------------------------------- -// Abstract interface for ConVars -//----------------------------------------------------------------------------- -abstract_class IConVar -{ -public: - // Value set - virtual void SetValue( const char *pValue ) = 0; - virtual void SetValue( float flValue ) = 0; - virtual void SetValue( int nValue ) = 0; - - // Return name of command - virtual const char *GetName( void ) const = 0; - - // Accessors.. not as efficient as using GetState()/GetInfo() - // if you call these methods multiple times on the same IConVar - virtual bool IsFlagSet( int nFlag ) const = 0; -}; - - -#endif // ICONVAR_H diff --git a/public/tier1/interface.h b/public/tier1/interface.h deleted file mode 100644 index 5e07a723b..000000000 --- a/public/tier1/interface.h +++ /dev/null @@ -1,226 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -// This header defines the interface convention used in the valve engine. -// To make an interface and expose it: -// 1. The interface must be ALL pure virtuals, and have no data members. -// 2. Define a name for it. -// 3. In its implementation file, use EXPOSE_INTERFACE or EXPOSE_SINGLE_INTERFACE. - -// Versioning -// There are two versioning cases that are handled by this: -// 1. You add functions to the end of an interface, so it is binary compatible with the previous interface. In this case, -// you need two EXPOSE_INTERFACEs: one to expose your class as the old interface and one to expose it as the new interface. -// 2. You update an interface so it's not compatible anymore (but you still want to be able to expose the old interface -// for legacy code). In this case, you need to make a new version name for your new interface, and make a wrapper interface and -// expose it for the old interface. - -// Static Linking: -// Must mimic unique seperate class 'InterfaceReg' constructors per subsystem. -// Each subsystem can then import and export interfaces as expected. -// This is achieved through unique namespacing 'InterfaceReg' via symbol _SUBSYSTEM. -// Static Linking also needs to generate unique symbols per interface so as to -// provide a 'stitching' method whereby these interface symbols can be referenced -// via the lib's primary module (usually the lib's interface exposure) -// therby stitching all of that lib's code/data together for eventual final exe link inclusion. - -#ifndef INTERFACE_H -#define INTERFACE_H - -#ifdef _WIN32 -#pragma once -#endif - -#if defined _LINUX || defined __APPLE__ -#include // dlopen,dlclose, et al -#include - -#ifndef HMODULE -#define HMODULE void * -#endif - -#ifndef GetProcAddress -#define GetProcAddress dlsym -#endif - -#ifndef _snprintf -#define _snprintf snprintf -#endif -#endif - -// TODO: move interface.cpp into tier0 library. -#include "tier0/platform.h" - -// All interfaces derive from this. -class IBaseInterface -{ -public: - virtual ~IBaseInterface() {} -}; - -#if !defined( _X360 ) -#define CREATEINTERFACE_PROCNAME "CreateInterface" -#else -// x360 only allows ordinal exports, .def files export "CreateInterface" at 1 -#define CREATEINTERFACE_PROCNAME ((const char*)1) -#endif - -typedef void* (*CreateInterfaceFn)(const char *pName, int *pReturnCode); -typedef void* (*InstantiateInterfaceFn)(); - -// Used internally to register classes. -class InterfaceReg -{ -public: - InterfaceReg(InstantiateInterfaceFn fn, const char *pName); - -public: - InstantiateInterfaceFn m_CreateFn; - const char *m_pName; - - InterfaceReg *m_pNext; // For the global list. - static InterfaceReg *s_pInterfaceRegs; -}; - -// Use this to expose an interface that can have multiple instances. -// e.g.: -// EXPOSE_INTERFACE( CInterfaceImp, IInterface, "MyInterface001" ) -// This will expose a class called CInterfaceImp that implements IInterface (a pure class) -// clients can receive a pointer to this class by calling CreateInterface( "MyInterface001" ) -// -// In practice, the shared header file defines the interface (IInterface) and version name ("MyInterface001") -// so that each component can use these names/vtables to communicate -// -// A single class can support multiple interfaces through multiple inheritance -// -// Use this if you want to write the factory function. -#if !defined(_STATIC_LINKED) || !defined(_SUBSYSTEM) -#define EXPOSE_INTERFACE_FN(functionName, interfaceName, versionName) \ - static InterfaceReg __g_Create##interfaceName##_reg(functionName, versionName); -#else -#define EXPOSE_INTERFACE_FN(functionName, interfaceName, versionName) \ - namespace _SUBSYSTEM \ - { \ - static InterfaceReg __g_Create##interfaceName##_reg(functionName, versionName); \ - } -#endif - -#if !defined(_STATIC_LINKED) || !defined(_SUBSYSTEM) -#define EXPOSE_INTERFACE(className, interfaceName, versionName) \ - static void* __Create##className##_interface() {return static_cast( new className );} \ - static InterfaceReg __g_Create##className##_reg(__Create##className##_interface, versionName ); -#else -#define EXPOSE_INTERFACE(className, interfaceName, versionName) \ - namespace _SUBSYSTEM \ - { \ - static void* __Create##className##_interface() {return static_cast( new className );} \ - static InterfaceReg __g_Create##className##_reg(__Create##className##_interface, versionName ); \ - } -#endif - -// Use this to expose a singleton interface with a global variable you've created. -#if !defined(_STATIC_LINKED) || !defined(_SUBSYSTEM) -#define EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, globalVarName) \ - static void* __Create##className##interfaceName##_interface() {return static_cast( &globalVarName );} \ - static InterfaceReg __g_Create##className##interfaceName##_reg(__Create##className##interfaceName##_interface, versionName); -#else -#define EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, globalVarName) \ - namespace _SUBSYSTEM \ - { \ - static void* __Create##className##interfaceName##_interface() {return static_cast( &globalVarName );} \ - static InterfaceReg __g_Create##className##interfaceName##_reg(__Create##className##interfaceName##_interface, versionName); \ - } -#endif - -// Use this to expose a singleton interface. This creates the global variable for you automatically. -#if !defined(_STATIC_LINKED) || !defined(_SUBSYSTEM) -#define EXPOSE_SINGLE_INTERFACE(className, interfaceName, versionName) \ - static className __g_##className##_singleton; \ - EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, __g_##className##_singleton) -#else -#define EXPOSE_SINGLE_INTERFACE(className, interfaceName, versionName) \ - namespace _SUBSYSTEM \ - { \ - static className __g_##className##_singleton; \ - } \ - EXPOSE_SINGLE_INTERFACE_GLOBALVAR(className, interfaceName, versionName, __g_##className##_singleton) -#endif - -// load/unload components -class CSysModule; - -// interface return status -enum -{ - IFACE_OK = 0, - IFACE_FAILED -}; - -//----------------------------------------------------------------------------- -// This function is automatically exported and allows you to access any interfaces exposed with the above macros. -// if pReturnCode is set, it will return one of the following values (IFACE_OK, IFACE_FAILED) -// extend this for other error conditions/code -//----------------------------------------------------------------------------- -DLL_EXPORT void* CreateInterface(const char *pName, int *pReturnCode); - -#if defined( _X360 ) -DLL_EXPORT void *CreateInterfaceThunk( const char *pName, int *pReturnCode ); -#endif - -//----------------------------------------------------------------------------- -// UNDONE: This is obsolete, use the module load/unload/get instead!!! -//----------------------------------------------------------------------------- -extern CreateInterfaceFn Sys_GetFactory( CSysModule *pModule ); -extern CreateInterfaceFn Sys_GetFactory( const char *pModuleName ); -extern CreateInterfaceFn Sys_GetFactoryThis( void ); - -//----------------------------------------------------------------------------- -// Load & Unload should be called in exactly one place for each module -// The factory for that module should be passed on to dependent components for -// proper versioning. -//----------------------------------------------------------------------------- -extern CSysModule *Sys_LoadModule( const char *pModuleName ); -extern void Sys_UnloadModule( CSysModule *pModule ); - -// This is a helper function to load a module, get its factory, and get a specific interface. -// You are expected to free all of these things. -// Returns false and cleans up if any of the steps fail. -bool Sys_LoadInterface( - const char *pModuleName, - const char *pInterfaceVersionName, - CSysModule **pOutModule, - void **pOutInterface ); - -bool Sys_IsDebuggerPresent(); - -//----------------------------------------------------------------------------- -// Purpose: Place this as a singleton at module scope (e.g.) and use it to get the factory from the specified module name. -// -// When the singleton goes out of scope (.dll unload if at module scope), -// then it'll call Sys_UnloadModule on the module so that the refcount is decremented -// and the .dll actually can unload from memory. -//----------------------------------------------------------------------------- -class CDllDemandLoader -{ -public: - CDllDemandLoader( char const *pchModuleName ); - virtual ~CDllDemandLoader(); - CreateInterfaceFn GetFactory(); - void Unload(); - -private: - - char const *m_pchModuleName; - CSysModule *m_hModule; - bool m_bLoadAttempted; -}; - -#endif - - - diff --git a/public/tier1/lzmaDecoder.h b/public/tier1/lzmaDecoder.h deleted file mode 100644 index c49d8c92f..000000000 --- a/public/tier1/lzmaDecoder.h +++ /dev/null @@ -1,42 +0,0 @@ -//========= Copyright 1996-2007, Valve Corporation, All rights reserved. ============// -// -// LZMA Decoder. Designed for run time decoding. -// -// LZMA SDK 4.43 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) -// http://www.7-zip.org/ -// -//=====================================================================================// - -#ifndef _LZMADECODER_H -#define _LZMADECODER_H -#pragma once - -#if !defined( _X360 ) -#define LZMA_ID (('A'<<24)|('M'<<16)|('Z'<<8)|('L')) -#else -#define LZMA_ID (('L'<<24)|('Z'<<16)|('M'<<8)|('A')) -#endif - -// bind the buffer for correct identification -#pragma pack(1) -struct lzma_header_t -{ - unsigned int id; - unsigned int actualSize; // always little endian - unsigned int lzmaSize; // always little endian - unsigned char properties[5]; -}; -#pragma pack() - -class CLZMA -{ -public: - unsigned int Uncompress( unsigned char *pInput, unsigned char *pOutput ); - bool IsCompressed( unsigned char *pInput ); - unsigned int GetActualSize( unsigned char *pInput ); - -private: -}; - -#endif - diff --git a/public/tier1/lzss.h b/public/tier1/lzss.h deleted file mode 100644 index 936f8ed9b..000000000 --- a/public/tier1/lzss.h +++ /dev/null @@ -1,67 +0,0 @@ -//========= Copyright 1996-2007, Valve Corporation, All rights reserved. ============// -// -// LZSS Codec. Designed for fast cheap gametime encoding/decoding. Compression results -// are not aggresive as other alogrithms, but gets 2:1 on most arbitrary uncompressed data. -// -//=====================================================================================// - -#ifndef _LZSS_H -#define _LZSS_H -#pragma once - -#if !defined( _X360 ) -#define LZSS_ID (('S'<<24)|('S'<<16)|('Z'<<8)|('L')) -#else -#define LZSS_ID (('L'<<24)|('Z'<<16)|('S'<<8)|('S')) -#endif - -// bind the buffer for correct identification -struct lzss_header_t -{ - unsigned int id; - unsigned int actualSize; // always little endian -}; - -#define DEFAULT_LZSS_WINDOW_SIZE 4096 - -class CLZSS -{ -public: - unsigned char* Compress( unsigned char *pInput, int inputlen, unsigned int *pOutputSize ); - unsigned char* CompressNoAlloc( unsigned char *pInput, int inputlen, unsigned char *pOutput, unsigned int *pOutputSize ); - unsigned int Uncompress( unsigned char *pInput, unsigned char *pOutput ); - bool IsCompressed( unsigned char *pInput ); - unsigned int GetActualSize( unsigned char *pInput ); - - // windowsize must be a power of two. - FORCEINLINE CLZSS( int nWindowSize = DEFAULT_LZSS_WINDOW_SIZE ); - -private: - // expected to be sixteen bytes - struct lzss_node_t - { - unsigned char *pData; - lzss_node_t *pPrev; - lzss_node_t *pNext; - char empty[4]; - }; - - struct lzss_list_t - { - lzss_node_t *pStart; - lzss_node_t *pEnd; - }; - - void BuildHash( unsigned char *pData ); - lzss_list_t *m_pHashTable; - lzss_node_t *m_pHashTarget; - int m_nWindowSize; - -}; - -FORCEINLINE CLZSS::CLZSS( int nWindowSize ) -{ - m_nWindowSize = nWindowSize; -} -#endif - diff --git a/public/tier1/mempool.h b/public/tier1/mempool.h deleted file mode 100644 index b3bd6da27..000000000 --- a/public/tier1/mempool.h +++ /dev/null @@ -1,541 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef MEMPOOL_H -#define MEMPOOL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/memalloc.h" -#include "tier0/tslist.h" -#include "tier0/platform.h" -#include "tier1/utlvector.h" -#include "tier1/utlrbtree.h" - -//----------------------------------------------------------------------------- -// Purpose: Optimized pool memory allocator -//----------------------------------------------------------------------------- - -typedef void (*MemoryPoolReportFunc_t)( char const* pMsg, ... ); - -class CMemoryPool -{ -public: - // Ways the memory pool can grow when it needs to make a new blob. - enum MemoryPoolGrowType_t - { - GROW_NONE=0, // Don't allow new blobs. - GROW_FAST=1, // New blob size is numElements * (i+1) (ie: the blocks it allocates - // get larger and larger each time it allocates one). - GROW_SLOW=2 // New blob size is numElements. - }; - - CMemoryPool( int blockSize, int numElements, int growMode = GROW_FAST, const char *pszAllocOwner = NULL, int nAlignment = 0 ); - ~CMemoryPool(); - - void* Alloc(); // Allocate the element size you specified in the constructor. - void* Alloc( size_t amount ); - void* AllocZero(); // Allocate the element size you specified in the constructor, zero the memory before construction - void* AllocZero( size_t amount ); - void Free(void *pMem); - - // Frees everything - void Clear(); - - // Error reporting... - static void SetErrorReportFunc( MemoryPoolReportFunc_t func ); - - // returns number of allocated blocks - int Count() { return m_BlocksAllocated; } - int PeakCount() { return m_PeakAlloc; } - -protected: - class CBlob - { - public: - CBlob *m_pPrev, *m_pNext; - int m_NumBytes; // Number of bytes in this blob. - char m_Data[1]; - }; - - // Resets the pool - void Init(); - void AddNewBlob(); - void ReportLeaks(); - - int m_BlockSize; - int m_BlocksPerBlob; - - int m_GrowMode; // GROW_ enum. - - // FIXME: Change m_ppMemBlob into a growable array? - CBlob m_BlobHead; - void *m_pHeadOfFreeList; - int m_BlocksAllocated; - int m_PeakAlloc; - unsigned short m_nAlignment; - unsigned short m_NumBlobs; - const char * m_pszAllocOwner; - - static MemoryPoolReportFunc_t g_ReportFunc; -}; - - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -class CMemoryPoolMT : public CMemoryPool -{ -public: - CMemoryPoolMT(int blockSize, int numElements, int growMode = GROW_FAST, const char *pszAllocOwner = NULL) : CMemoryPool( blockSize, numElements, growMode, pszAllocOwner) {} - - - void* Alloc() { AUTO_LOCK( m_mutex ); return CMemoryPool::Alloc(); } - void* Alloc( size_t amount ) { AUTO_LOCK( m_mutex ); return CMemoryPool::Alloc( amount ); } - void* AllocZero() { AUTO_LOCK( m_mutex ); return CMemoryPool::AllocZero(); } - void* AllocZero( size_t amount ) { AUTO_LOCK( m_mutex ); return CMemoryPool::AllocZero( amount ); } - void Free(void *pMem) { AUTO_LOCK( m_mutex ); CMemoryPool::Free( pMem ); } - - // Frees everything - void Clear() { AUTO_LOCK( m_mutex ); return CMemoryPool::Clear(); } -private: - CThreadFastMutex m_mutex; // @TODO: Rework to use tslist (toml 7/6/2007) -}; - - -//----------------------------------------------------------------------------- -// Wrapper macro to make an allocator that returns particular typed allocations -// and construction and destruction of objects. -//----------------------------------------------------------------------------- -template< class T > -class CClassMemoryPool : public CMemoryPool -{ -public: - CClassMemoryPool(int numElements, int growMode = GROW_FAST, int nAlignment = 0 ) : - CMemoryPool( sizeof(T), numElements, growMode, MEM_ALLOC_CLASSNAME(T), nAlignment ) {} - - T* Alloc(); - T* AllocZero(); - void Free( T *pMem ); - - void Clear(); -}; - - -//----------------------------------------------------------------------------- -// Specialized pool for aligned data management (e.g., Xbox cubemaps) -//----------------------------------------------------------------------------- -template -class CAlignedMemPool -{ - enum - { - BLOCK_SIZE = COMPILETIME_MAX( ALIGN_VALUE( ITEM_SIZE, ALIGNMENT ), 8 ), - }; - -public: - CAlignedMemPool(); - - void *Alloc(); - void Free( void *p ); - - static int __cdecl CompareChunk( void * const *ppLeft, void * const *ppRight ); - void Compact(); - - int NumTotal() { return m_Chunks.Count() * ( CHUNK_SIZE / BLOCK_SIZE ); } - int NumAllocated() { return NumTotal() - m_nFree; } - int NumFree() { return m_nFree; } - - int BytesTotal() { return NumTotal() * BLOCK_SIZE; } - int BytesAllocated() { return NumAllocated() * BLOCK_SIZE; } - int BytesFree() { return NumFree() * BLOCK_SIZE; } - - int ItemSize() { return ITEM_SIZE; } - int BlockSize() { return BLOCK_SIZE; } - int ChunkSize() { return CHUNK_SIZE; } - -private: - struct FreeBlock_t - { - FreeBlock_t *pNext; - byte reserved[ BLOCK_SIZE - sizeof( FreeBlock_t *) ]; - }; - - CUtlVector m_Chunks; // Chunks are tracked outside blocks (unlike CMemoryPool) to simplify alignment issues - FreeBlock_t * m_pFirstFree; - int m_nFree; - CAllocator m_Allocator; - float m_TimeLastCompact; -}; - -//----------------------------------------------------------------------------- -// Pool variant using standard allocation -//----------------------------------------------------------------------------- -template -class CObjectPool -{ -public: - CObjectPool() - { - int i = nInitialCount; - while ( i-- > 0 ) - { - m_AvailableObjects.PushItem( new T ); - } - } - - ~CObjectPool() - { - Purge(); - } - - int NumAvailable() - { - return m_AvailableObjects.Count(); - } - - void Purge() - { - T *p; - while ( m_AvailableObjects.PopItem( &p ) ) - { - delete p; - } - } - - T *GetObject( bool bCreateNewIfEmpty = bDefCreateNewIfEmpty ) - { - T *p; - if ( !m_AvailableObjects.PopItem( &p ) ) - { - p = ( bCreateNewIfEmpty ) ? new T : NULL; - } - return p; - } - - void PutObject( T *p ) - { - m_AvailableObjects.PushItem( p ); - } - -private: - CTSList m_AvailableObjects; -}; - -//----------------------------------------------------------------------------- - - -template< class T > -inline T* CClassMemoryPool::Alloc() -{ - T *pRet; - - { - MEM_ALLOC_CREDIT_(MEM_ALLOC_CLASSNAME(T)); - pRet = (T*)CMemoryPool::Alloc(); - } - - if ( pRet ) - { - Construct( pRet ); - } - return pRet; -} - -template< class T > -inline T* CClassMemoryPool::AllocZero() -{ - T *pRet; - - { - MEM_ALLOC_CREDIT_(MEM_ALLOC_CLASSNAME(T)); - pRet = (T*)CMemoryPool::AllocZero(); - } - - if ( pRet ) - { - Construct( pRet ); - } - return pRet; -} - -template< class T > -inline void CClassMemoryPool::Free(T *pMem) -{ - if ( pMem ) - { - Destruct( pMem ); - } - - CMemoryPool::Free( pMem ); -} - -template< class T > -inline void CClassMemoryPool::Clear() -{ - CUtlRBTree freeBlocks; - SetDefLessFunc( freeBlocks ); - - void *pCurFree = m_pHeadOfFreeList; - while ( pCurFree != NULL ) - { - freeBlocks.Insert( pCurFree ); - pCurFree = *((void**)pCurFree); - } - - for( CBlob *pCur=m_BlobHead.m_pNext; pCur != &m_BlobHead; pCur=pCur->m_pNext ) - { - T *p = (T *)pCur->m_Data; - T *pLimit = (T *)(pCur->m_Data + pCur->m_NumBytes); - while ( p < pLimit ) - { - if ( freeBlocks.Find( p ) == freeBlocks.InvalidIndex() ) - { - Destruct( p ); - } - p++; - } - } - - CMemoryPool::Clear(); -} - - -//----------------------------------------------------------------------------- -// Macros that make it simple to make a class use a fixed-size allocator -// Put DECLARE_FIXEDSIZE_ALLOCATOR in the private section of a class, -// Put DEFINE_FIXEDSIZE_ALLOCATOR in the CPP file -//----------------------------------------------------------------------------- -#define DECLARE_FIXEDSIZE_ALLOCATOR( _class ) \ - public: \ - inline void* operator new( size_t size ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_Allocator.Alloc(size); } \ - inline void* operator new( size_t size, int nBlockUse, const char *pFileName, int nLine ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_Allocator.Alloc(size); } \ - inline void operator delete( void* p ) { s_Allocator.Free(p); } \ - inline void operator delete( void* p, int nBlockUse, const char *pFileName, int nLine ) { s_Allocator.Free(p); } \ - private: \ - static CMemoryPool s_Allocator - -#define DEFINE_FIXEDSIZE_ALLOCATOR( _class, _initsize, _grow ) \ - CMemoryPool _class::s_Allocator(sizeof(_class), _initsize, _grow, #_class " pool") - -#define DEFINE_FIXEDSIZE_ALLOCATOR_ALIGNED( _class, _initsize, _grow, _alignment ) \ - CMemoryPool _class::s_Allocator(sizeof(_class), _initsize, _grow, #_class " pool", _alignment ) - -#define DECLARE_FIXEDSIZE_ALLOCATOR_MT( _class ) \ - public: \ - inline void* operator new( size_t size ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_Allocator.Alloc(size); } \ - inline void* operator new( size_t size, int nBlockUse, const char *pFileName, int nLine ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_Allocator.Alloc(size); } \ - inline void operator delete( void* p ) { s_Allocator.Free(p); } \ - inline void operator delete( void* p, int nBlockUse, const char *pFileName, int nLine ) { s_Allocator.Free(p); } \ - private: \ - static CMemoryPoolMT s_Allocator - -#define DEFINE_FIXEDSIZE_ALLOCATOR_MT( _class, _initsize, _grow ) \ - CMemoryPoolMT _class::s_Allocator(sizeof(_class), _initsize, _grow, #_class " pool") - -//----------------------------------------------------------------------------- -// Macros that make it simple to make a class use a fixed-size allocator -// This version allows us to use a memory pool which is externally defined... -// Put DECLARE_FIXEDSIZE_ALLOCATOR_EXTERNAL in the private section of a class, -// Put DEFINE_FIXEDSIZE_ALLOCATOR_EXTERNAL in the CPP file -//----------------------------------------------------------------------------- - -#define DECLARE_FIXEDSIZE_ALLOCATOR_EXTERNAL( _class ) \ - public: \ - inline void* operator new( size_t size ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_pAllocator->Alloc(size); } \ - inline void* operator new( size_t size, int nBlockUse, const char *pFileName, int nLine ) { MEM_ALLOC_CREDIT_(#_class " pool"); return s_pAllocator->Alloc(size); } \ - inline void operator delete( void* p ) { s_pAllocator->Free(p); } \ - private: \ - static CMemoryPool* s_pAllocator - -#define DEFINE_FIXEDSIZE_ALLOCATOR_EXTERNAL( _class, _allocator ) \ - CMemoryPool* _class::s_pAllocator = _allocator - - -template -inline CAlignedMemPool::CAlignedMemPool() - : m_pFirstFree( 0 ), - m_nFree( 0 ), - m_TimeLastCompact( 0 ) -{ - COMPILE_TIME_ASSERT( sizeof( FreeBlock_t ) >= BLOCK_SIZE ); - COMPILE_TIME_ASSERT( ALIGN_VALUE( sizeof( FreeBlock_t ), ALIGNMENT ) == sizeof( FreeBlock_t ) ); -} - -template -inline void *CAlignedMemPool::Alloc() -{ - if ( !m_pFirstFree ) - { - FreeBlock_t *pNew = (FreeBlock_t *)m_Allocator.Alloc( CHUNK_SIZE ); - Assert( (unsigned)pNew % ALIGNMENT == 0 ); - m_Chunks.AddToTail( pNew ); - m_nFree = CHUNK_SIZE / BLOCK_SIZE; - m_pFirstFree = pNew; - for ( int i = 0; i < m_nFree - 1; i++ ) - { - pNew->pNext = pNew + 1; - pNew++; - } - pNew->pNext = NULL; - } - - void *p = m_pFirstFree; - m_pFirstFree = m_pFirstFree->pNext; - m_nFree--; - - return p; -} - -template -inline void CAlignedMemPool::Free( void *p ) -{ - // Insertion sort to encourage allocation clusters in chunks - FreeBlock_t *pFree = ((FreeBlock_t *)p); - FreeBlock_t *pCur = m_pFirstFree; - FreeBlock_t *pPrev = NULL; - - while ( pCur && pFree > pCur ) - { - pPrev = pCur; - pCur = pCur->pNext; - } - - pFree->pNext = pCur; - - if ( pPrev ) - { - pPrev->pNext = pFree; - } - else - { - m_pFirstFree = pFree; - } - m_nFree++; - - if ( m_nFree >= ( CHUNK_SIZE / BLOCK_SIZE ) * COMPACT_THRESHOLD ) - { - float time = Plat_FloatTime(); - float compactTime = ( m_nFree >= ( CHUNK_SIZE / BLOCK_SIZE ) * COMPACT_THRESHOLD * 4 ) ? 15.0 : 30.0; - if ( m_TimeLastCompact > time || m_TimeLastCompact + compactTime < Plat_FloatTime() ) - { - Compact(); - m_TimeLastCompact = time; - } - } -} - -template -inline int __cdecl CAlignedMemPool::CompareChunk( void * const *ppLeft, void * const *ppRight ) -{ - return ((unsigned)*ppLeft) - ((unsigned)*ppRight); -} - -template -inline void CAlignedMemPool::Compact() -{ - FreeBlock_t *pCur = m_pFirstFree; - FreeBlock_t *pPrev = NULL; - - m_Chunks.Sort( CompareChunk ); - -#ifdef VALIDATE_ALIGNED_MEM_POOL - { - FreeBlock_t *p = m_pFirstFree; - while ( p ) - { - if ( p->pNext && p > p->pNext ) - { - __asm { int 3 } - } - p = p->pNext; - } - - for ( int i = 0; i < m_Chunks.Count(); i++ ) - { - if ( i + 1 < m_Chunks.Count() ) - { - if ( m_Chunks[i] > m_Chunks[i + 1] ) - { - __asm { int 3 } - } - } - } - } -#endif - - int i; - - for ( i = 0; i < m_Chunks.Count(); i++ ) - { - int nBlocksPerChunk = CHUNK_SIZE / BLOCK_SIZE; - FreeBlock_t *pChunkLimit = ((FreeBlock_t *)m_Chunks[i]) + nBlocksPerChunk; - int nFromChunk = 0; - if ( pCur == m_Chunks[i] ) - { - FreeBlock_t *pFirst = pCur; - while ( pCur && pCur >= m_Chunks[i] && pCur < pChunkLimit ) - { - pCur = pCur->pNext; - nFromChunk++; - } - pCur = pFirst; - - } - - while ( pCur && pCur >= m_Chunks[i] && pCur < pChunkLimit ) - { - if ( nFromChunk != nBlocksPerChunk ) - { - if ( pPrev ) - { - pPrev->pNext = pCur; - } - else - { - m_pFirstFree = pCur; - } - pPrev = pCur; - } - else if ( pPrev ) - { - pPrev->pNext = NULL; - } - else - { - m_pFirstFree = NULL; - } - - pCur = pCur->pNext; - } - - if ( nFromChunk == nBlocksPerChunk ) - { - m_Allocator.Free( m_Chunks[i] ); - m_nFree -= nBlocksPerChunk; - m_Chunks[i] = 0; - } - } - - for ( i = m_Chunks.Count() - 1; i >= 0 ; i-- ) - { - if ( !m_Chunks[i] ) - { - m_Chunks.FastRemove( i ); - } - } -} - -#endif // MEMPOOL_H diff --git a/public/tier1/memstack.h b/public/tier1/memstack.h deleted file mode 100644 index 7a8e78394..000000000 --- a/public/tier1/memstack.h +++ /dev/null @@ -1,204 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: A fast stack memory allocator that uses virtual memory if available -// -//=============================================================================// - -#ifndef MEMSTACK_H -#define MEMSTACK_H - -#if defined( _WIN32 ) -#pragma once -#endif - -//----------------------------------------------------------------------------- - -typedef unsigned MemoryStackMark_t; - -class CMemoryStack -{ -public: - CMemoryStack(); - ~CMemoryStack(); - - bool Init( unsigned maxSize = 0, unsigned commitSize = 0, unsigned initialCommit = 0, unsigned alignment = 16 ); -#ifdef _X360 - bool InitPhysical( unsigned size = 0, unsigned alignment = 16 ); -#endif - void Term(); - - int GetSize(); - int GetMaxSize(); - int GetUsed(); - - void *Alloc( unsigned bytes, bool bClear = false ) RESTRICT; - - MemoryStackMark_t GetCurrentAllocPoint(); - void FreeToAllocPoint( MemoryStackMark_t mark, bool bDecommit = true ); - void FreeAll( bool bDecommit = true ); - - void Access( void **ppRegion, unsigned *pBytes ); - - void PrintContents(); - - void *GetBase(); - const void *GetBase() const { return const_cast(this)->GetBase(); } - -private: - bool CommitTo( byte * ) RESTRICT; - - byte *m_pNextAlloc; - byte *m_pCommitLimit; - byte *m_pAllocLimit; - - byte *m_pBase; - - unsigned m_maxSize; - unsigned m_alignment; -#ifdef _WIN32 - unsigned m_commitSize; - unsigned m_minCommit; -#endif -#ifdef _X360 - bool m_bPhysical; -#endif -}; - -//------------------------------------- - -FORCEINLINE void *CMemoryStack::Alloc( unsigned bytes, bool bClear ) RESTRICT -{ - Assert( m_pBase ); - - int alignment = m_alignment; - if ( bytes ) - { - bytes = AlignValue( bytes, alignment ); - } - else - { - bytes = alignment; - } - - - void *pResult = m_pNextAlloc; - byte *pNextAlloc = m_pNextAlloc + bytes; - - if ( pNextAlloc > m_pCommitLimit ) - { - if ( !CommitTo( pNextAlloc ) ) - { - return NULL; - } - } - - if ( bClear ) - { - memset( pResult, 0, bytes ); - } - - m_pNextAlloc = pNextAlloc; - - return pResult; -} - -//------------------------------------- - -inline int CMemoryStack::GetMaxSize() -{ - return m_maxSize; -} - -//------------------------------------- - -inline int CMemoryStack::GetUsed() -{ - return ( m_pNextAlloc - m_pBase ); -} - -//------------------------------------- - -inline void *CMemoryStack::GetBase() -{ - return m_pBase; -} - -//------------------------------------- - -inline MemoryStackMark_t CMemoryStack::GetCurrentAllocPoint() -{ - return ( m_pNextAlloc - m_pBase ); -} - -//----------------------------------------------------------------------------- -// The CUtlMemoryStack class: -// A fixed memory class -//----------------------------------------------------------------------------- -template< typename T, typename I, size_t MAX_SIZE, size_t COMMIT_SIZE = 0, size_t INITIAL_COMMIT = 0 > -class CUtlMemoryStack -{ -public: - // constructor, destructor - CUtlMemoryStack( int nGrowSize = 0, int nInitSize = 0 ) { m_MemoryStack.Init( MAX_SIZE * sizeof(T), COMMIT_SIZE * sizeof(T), INITIAL_COMMIT * sizeof(T), 4 ); COMPILE_TIME_ASSERT( sizeof(T) % 4 == 0 ); } - CUtlMemoryStack( T* pMemory, int numElements ) { Assert( 0 ); } - - // Can we use this index? - bool IsIdxValid( I i ) const { return (i >= 0) && (i < m_nAllocated); } - static int InvalidIndex() { return -1; } - - class Iterator_t - { - Iterator_t( I i ) : index( i ) {} - I index; - friend class CUtlMemoryStack; - public: - bool operator==( const Iterator_t it ) const { return index == it.index; } - bool operator!=( const Iterator_t it ) const { return index != it.index; } - }; - Iterator_t First() const { return Iterator_t( m_nAllocated ? 0 : InvalidIndex() ); } - Iterator_t Next( const Iterator_t &it ) const { return Iterator_t( it.index < m_nAllocated ? it.index + 1 : InvalidIndex() ); } - I GetIndex( const Iterator_t &it ) const { return it.index; } - bool IsIdxAfter( I i, const Iterator_t &it ) const { return i > it.index; } - bool IsValidIterator( const Iterator_t &it ) const { return it.index >= 0 && it.index < m_nAllocated; } - Iterator_t InvalidIterator() const { return Iterator_t( InvalidIndex() ); } - - // Gets the base address - T* Base() { return (T*)m_MemoryStack.GetBase(); } - const T* Base() const { return (const T*)m_MemoryStack.GetBase(); } - - // element access - T& operator[]( I i ) { Assert( IsIdxValid(i) ); return Base()[i]; } - const T& operator[]( I i ) const { Assert( IsIdxValid(i) ); return Base()[i]; } - T& Element( I i ) { Assert( IsIdxValid(i) ); return Base()[i]; } - const T& Element( I i ) const { Assert( IsIdxValid(i) ); return Base()[i]; } - - // Attaches the buffer to external memory.... - void SetExternalBuffer( T* pMemory, int numElements ) { Assert( 0 ); } - - // Size - int NumAllocated() const { return m_nAllocated; } - int Count() const { return m_nAllocated; } - - // Grows the memory, so that at least allocated + num elements are allocated - void Grow( int num = 1 ) { Assert( num > 0 ); m_nAllocated += num; m_MemoryStack.Alloc( num * sizeof(T) ); } - - // Makes sure we've got at least this much memory - void EnsureCapacity( int num ) { Assert( num <= MAX_SIZE ); if ( m_nAllocated < num ) Grow( num - m_nAllocated ); } - - // Memory deallocation - void Purge() { m_MemoryStack.FreeAll(); m_nAllocated = 0; } - - // is the memory externally allocated? - bool IsExternallyAllocated() const { return false; } - - // Set the size by which the memory grows - void SetGrowSize( int size ) {} - -private: - CMemoryStack m_MemoryStack; - int m_nAllocated; -}; - -//----------------------------------------------------------------------------- - -#endif // MEMSTACK_H diff --git a/public/tier1/netadr.h b/public/tier1/netadr.h deleted file mode 100644 index b4f955f54..000000000 --- a/public/tier1/netadr.h +++ /dev/null @@ -1,70 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -// netadr.h -#ifndef NETADR_H -#define NETADR_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/platform.h" -#undef SetPort - -typedef enum -{ - NA_NULL = 0, - NA_LOOPBACK, - NA_BROADCAST, - NA_IP, -} netadrtype_t; - -typedef struct netadr_s -{ -public: - netadr_s() { SetIP( 0 ); SetPort( 0 ); SetType( NA_IP ); } - netadr_s( uint unIP, uint16 usPort ) { SetIP( unIP ); SetPort( usPort ); SetType( NA_IP ); } - netadr_s( const char *pch ) { SetFromString( pch ); } - void Clear(); // invalids Address - - void SetType( netadrtype_t type ); - void SetPort( unsigned short port ); - bool SetFromSockadr(const struct sockaddr *s); - void SetIP(uint8 b1, uint8 b2, uint8 b3, uint8 b4); - void SetIP(uint unIP); // Sets IP. unIP is in host order (little-endian) - void SetIPAndPort( uint unIP, unsigned short usPort ) { SetIP( unIP ); SetPort( usPort ); } - void SetFromString(const char *pch, bool bUseDNS = false ); // if bUseDNS is true then do a DNS lookup if needed - - bool CompareAdr (const netadr_s &a, bool onlyBase = false) const; - bool CompareClassBAdr (const netadr_s &a) const; - bool CompareClassCAdr (const netadr_s &a) const; - - netadrtype_t GetType() const; - unsigned short GetPort() const; - const char* ToString( bool onlyBase = false ) const; // returns xxx.xxx.xxx.xxx:ppppp - void ToSockadr(struct sockaddr *s) const; - unsigned int GetIP() const; - - bool IsLocalhost() const; // true, if this is the localhost IP - bool IsLoopback() const; // true if engine loopback buffers are used - bool IsReservedAdr() const; // true, if this is a private LAN IP - bool IsValid() const; // ip & port != 0 - void SetFromSocket( int hSocket ); - // These function names are decorated because the Xbox360 defines macros for ntohl and htonl - unsigned long addr_ntohl() const; - unsigned long addr_htonl() const; - bool operator==(const netadr_s &netadr) const {return ( CompareAdr( netadr ) );} - bool operator<(const netadr_s &netadr) const; - -public: // members are public to avoid to much changes - - netadrtype_t type; - unsigned char ip[4]; - unsigned short port; -} netadr_t; - -#endif // NETADR_H diff --git a/public/tier1/processor_detect.h b/public/tier1/processor_detect.h deleted file mode 100644 index 7d12045a0..000000000 --- a/public/tier1/processor_detect.h +++ /dev/null @@ -1,12 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: functions to expose CPU capabilities -// -// $NoKeywords: $ -//=============================================================================// - -bool CheckMMXTechnology(void); -bool CheckSSETechnology(void); -bool CheckSSE2Technology(void); -bool Check3DNowTechnology(void); - diff --git a/public/tier1/rangecheckedvar.h b/public/tier1/rangecheckedvar.h deleted file mode 100644 index f7533941d..000000000 --- a/public/tier1/rangecheckedvar.h +++ /dev/null @@ -1,113 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef RANGECHECKEDVAR_H -#define RANGECHECKEDVAR_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "tier0/dbg.h" -#include "tier0/threadtools.h" -#include "mathlib/vector.h" -#include - - -// Use this to disable range checks within a scope. -class CDisableRangeChecks -{ -public: - CDisableRangeChecks(); - ~CDisableRangeChecks(); -}; - - -template< class T > -inline void RangeCheck( const T &value, int minValue, int maxValue ) -{ -#ifdef _DEBUG - extern bool g_bDoRangeChecks; - if ( ThreadInMainThread() && g_bDoRangeChecks ) - { - // Ignore the min/max stuff for now.. just make sure it's not a NAN. - Assert( _finite( value ) ); - } -#endif -} - -inline void RangeCheck( const Vector &value, int minValue, int maxValue ) -{ -#ifdef _DEBUG - RangeCheck( value.x, minValue, maxValue ); - RangeCheck( value.y, minValue, maxValue ); - RangeCheck( value.z, minValue, maxValue ); -#endif -} - - -template< class T, int minValue, int maxValue, int startValue > -class CRangeCheckedVar -{ -public: - - inline CRangeCheckedVar() - { - m_Val = startValue; - } - - inline CRangeCheckedVar( const T &value ) - { - *this = value; - } - - // Clamp the value to its limits. Interpolation code uses this after interpolating. - inline void Clamp() - { - if ( m_Val < minValue ) - m_Val = minValue; - else if ( m_Val > maxValue ) - m_Val = maxValue; - } - - inline operator const T&() const - { - return m_Val; - } - - inline CRangeCheckedVar& operator=( const T &value ) - { - RangeCheck( value, minValue, maxValue ); - m_Val = value; - return *this; - } - - inline CRangeCheckedVar& operator+=( const T &value ) - { - return (*this = m_Val + value); - } - - inline CRangeCheckedVar& operator-=( const T &value ) - { - return (*this = m_Val - value); - } - - inline CRangeCheckedVar& operator*=( const T &value ) - { - return (*this = m_Val * value); - } - - inline CRangeCheckedVar& operator/=( const T &value ) - { - return (*this = m_Val / value); - } - -private: - - T m_Val; -}; - -#endif // RANGECHECKEDVAR_H diff --git a/public/tier1/refcount.h b/public/tier1/refcount.h deleted file mode 100644 index 3c7d31fcb..000000000 --- a/public/tier1/refcount.h +++ /dev/null @@ -1,387 +0,0 @@ -//========== Copyright 2005, Valve Corporation, All rights reserved. ======== -// -// Purpose: Tools for correctly implementing & handling reference counted -// objects -// -//============================================================================= - -#ifndef REFCOUNT_H -#define REFCOUNT_H - -#include "tier0/threadtools.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -//----------------------------------------------------------------------------- -// Purpose: Implement a standard reference counted interface. Use of this -// is optional insofar as all the concrete tools only require -// at compile time that the function signatures match. -//----------------------------------------------------------------------------- - -class IRefCounted -{ -public: - virtual int AddRef() = 0; - virtual int Release() = 0; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Release a pointer and mark it NULL -//----------------------------------------------------------------------------- - -template -inline int SafeRelease( REFCOUNTED_ITEM_PTR &pRef ) -{ - // Use funny syntax so that this works on "auto pointers" - REFCOUNTED_ITEM_PTR *ppRef = &pRef; - if ( *ppRef ) - { - int result = (*ppRef)->Release(); - *ppRef = NULL; - return result; - } - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: Maintain a reference across a scope -//----------------------------------------------------------------------------- - -template -class CAutoRef -{ -public: - CAutoRef( T *pRef ) - : m_pRef( pRef ) - { - if ( m_pRef ) - m_pRef->AddRef(); - } - - ~CAutoRef() - { - if (m_pRef) - m_pRef->Release(); - } - -private: - T *m_pRef; -}; - -//----------------------------------------------------------------------------- -// Purpose: Do a an inline AddRef then return the pointer, useful when -// returning an object from a function -//----------------------------------------------------------------------------- - -#define RetAddRef( p ) ( (p)->AddRef(), (p) ) -#define InlineAddRef( p ) ( (p)->AddRef(), (p) ) - - -//----------------------------------------------------------------------------- -// Purpose: A class to both hold a pointer to an object and its reference. -// Base exists to support other cleanup models -//----------------------------------------------------------------------------- - -template -class CBaseAutoPtr -{ -public: - CBaseAutoPtr() : m_pObject(0) {} - CBaseAutoPtr(T *pFrom) : m_pObject(pFrom) {} - - operator const void *() const { return m_pObject; } - operator void *() { return m_pObject; } - - operator const T *() const { return m_pObject; } - operator const T *() { return m_pObject; } - operator T *() { return m_pObject; } - - int operator=( int i ) { AssertMsg( i == 0, "Only NULL allowed on integer assign" ); m_pObject = 0; return 0; } - T * operator=( T *p ) { m_pObject = p; return p; } - - bool operator !() const { return ( !m_pObject ); } - bool operator!=( int i ) const { AssertMsg( i == 0, "Only NULL allowed on integer compare" ); return (m_pObject != NULL); } - bool operator==( const void *p ) const { return ( m_pObject == p ); } - bool operator!=( const void *p ) const { return ( m_pObject != p ); } - bool operator==( T *p ) const { return operator==( (void *)p ); } - bool operator!=( T *p ) const { return operator!=( (void *)p ); } - bool operator==( const CBaseAutoPtr &p ) const { return operator==( (const void *)p ); } - bool operator!=( const CBaseAutoPtr &p ) const { return operator!=( (const void *)p ); } - - T * operator->() { return m_pObject; } - T & operator *() { return *m_pObject; } - T ** operator &() { return &m_pObject; } - - const T * operator->() const { return m_pObject; } - const T & operator *() const { return *m_pObject; } - T * const * operator &() const { return &m_pObject; } - -protected: - CBaseAutoPtr( const CBaseAutoPtr &from ) : m_pObject( from.m_pObject ) {} - void operator=( const CBaseAutoPtr &from ) { m_pObject = from.m_pObject; } - - T *m_pObject; -}; - -//--------------------------------------------------------- - -template -class CRefPtr : public CBaseAutoPtr -{ - typedef CBaseAutoPtr BaseClass; -public: - CRefPtr() {} - CRefPtr( T *pInit ) : BaseClass( pInit ) {} - CRefPtr( const CRefPtr &from ) : BaseClass( from ) {} - ~CRefPtr() { if ( BaseClass::m_pObject ) BaseClass::m_pObject->Release(); } - - void operator=( const CRefPtr &from ) { BaseClass::operator=( from ); } - - int operator=( int i ) { return BaseClass::operator=( i ); } - T *operator=( T *p ) { return BaseClass::operator=( p ); } - - operator bool() const { return !BaseClass::operator!(); } - operator bool() { return !BaseClass::operator!(); } - - void SafeRelease() { if ( BaseClass::m_pObject ) BaseClass::m_pObject->Release(); BaseClass::m_pObject = 0; } - void AssignAddRef( T *pFrom ) { SafeRelease(); if (pFrom) pFrom->AddRef(); BaseClass::m_pObject = pFrom; } - void AddRefAssignTo( T *&pTo ) { ::SafeRelease( pTo ); if ( BaseClass::m_pObject ) BaseClass::m_pObject->AddRef(); pTo = BaseClass::m_pObject; } -}; - - -//----------------------------------------------------------------------------- -// Purpose: Traits classes defining reference count threading model -//----------------------------------------------------------------------------- - -class CRefMT -{ -public: - static int Increment( int *p) { return ThreadInterlockedIncrement( (long *)p ); } - static int Decrement( int *p) { return ThreadInterlockedDecrement( (long *)p ); } -}; - -class CRefST -{ -public: - static int Increment( int *p) { return ++(*p); } - static int Decrement( int *p) { return --(*p); } -}; - -//----------------------------------------------------------------------------- -// Purpose: Actual reference counting implementation. Pulled out to reduce -// code bloat. -//----------------------------------------------------------------------------- - -template -class NO_VTABLE CRefCountServiceBase -{ -protected: - CRefCountServiceBase() - : m_iRefs( 1 ) - { - } - - virtual ~CRefCountServiceBase() - { - } - - virtual bool OnFinalRelease() - { - return true; - } - - int GetRefCount() const - { - return m_iRefs; - } - - int DoAddRef() - { - return CRefThreading::Increment( &m_iRefs ); - } - - int DoRelease() - { - int result = CRefThreading::Decrement( &m_iRefs ); - if ( result ) - return result; - if ( OnFinalRelease() && bSelfDelete ) - delete this; - return 0; - } - -private: - int m_iRefs; -}; - -class CRefCountServiceNull -{ -protected: - static int DoAddRef() { return 1; } - static int DoRelease() { return 1; } -}; - -template -class NO_VTABLE CRefCountServiceDestruct -{ -protected: - CRefCountServiceDestruct() - : m_iRefs( 1 ) - { - } - - virtual ~CRefCountServiceDestruct() - { - } - - int GetRefCount() const - { - return m_iRefs; - } - - int DoAddRef() - { - return CRefThreading::Increment( &m_iRefs ); - } - - int DoRelease() - { - int result = CRefThreading::Decrement( &m_iRefs ); - if ( result ) - return result; - this->~CRefCountServiceDestruct(); - return 0; - } - -private: - int m_iRefs; -}; - - -typedef CRefCountServiceBase CRefCountServiceST; -typedef CRefCountServiceBase CRefCountServiceNoDeleteST; - -typedef CRefCountServiceBase CRefCountServiceMT; -typedef CRefCountServiceBase CRefCountServiceNoDeleteMT; - -// Default to threadsafe -typedef CRefCountServiceNoDeleteMT CRefCountServiceNoDelete; -typedef CRefCountServiceMT CRefCountService; - -//----------------------------------------------------------------------------- -// Purpose: Base classes to implement reference counting -//----------------------------------------------------------------------------- - -template < class REFCOUNT_SERVICE = CRefCountService > -class NO_VTABLE CRefCounted : public REFCOUNT_SERVICE -{ -public: - virtual ~CRefCounted() {} - int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); } - int Release() { return REFCOUNT_SERVICE::DoRelease(); } -}; - -//------------------------------------- - -template < class BASE1, class REFCOUNT_SERVICE = CRefCountService > -class NO_VTABLE CRefCounted1 : public BASE1, - public REFCOUNT_SERVICE -{ -public: - virtual ~CRefCounted1() {} - int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); } - int Release() { return REFCOUNT_SERVICE::DoRelease(); } -}; - -//------------------------------------- - -template < class BASE1, class BASE2, class REFCOUNT_SERVICE = CRefCountService > -class NO_VTABLE CRefCounted2 : public BASE1, public BASE2, - public REFCOUNT_SERVICE -{ -public: - virtual ~CRefCounted2() {} - int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); } - int Release() { return REFCOUNT_SERVICE::DoRelease(); } -}; - -//------------------------------------- - -template < class BASE1, class BASE2, class BASE3, class REFCOUNT_SERVICE = CRefCountService > -class NO_VTABLE CRefCounted3 : public BASE1, public BASE2, public BASE3, - public REFCOUNT_SERVICE -{ - virtual ~CRefCounted3() {} - int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); } - int Release() { return REFCOUNT_SERVICE::DoRelease(); } -}; - -//------------------------------------- - -template < class BASE1, class BASE2, class BASE3, class BASE4, class REFCOUNT_SERVICE = CRefCountService > -class NO_VTABLE CRefCounted4 : public BASE1, public BASE2, public BASE3, public BASE4, - public REFCOUNT_SERVICE -{ -public: - virtual ~CRefCounted4() {} - int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); } - int Release() { return REFCOUNT_SERVICE::DoRelease(); } -}; - -//------------------------------------- - -template < class BASE1, class BASE2, class BASE3, class BASE4, class BASE5, class REFCOUNT_SERVICE = CRefCountService > -class NO_VTABLE CRefCounted5 : public BASE1, public BASE2, public BASE3, public BASE4, public BASE5, - public REFCOUNT_SERVICE -{ -public: - virtual ~CRefCounted5() {} - int AddRef() { return REFCOUNT_SERVICE::DoAddRef(); } - int Release() { return REFCOUNT_SERVICE::DoRelease(); } -}; - -//----------------------------------------------------------------------------- -// Purpose: Class to throw around a reference counted item to debug -// referencing problems -//----------------------------------------------------------------------------- - -#if 0 -template -class CRefDebug : public BASE_REFCOUNTED -{ -public: -#ifdef _DEBUG - CRefDebug() - { - AssertMsg( this->GetRefCount() == 1, "Expected initial ref count of 1" ); - DevMsg( "%s:create 0x%x\n", ( pszName ) ? pszName : "", this ); - } - - virtual ~CRefDebug() - { - AssertDevMsg( this->GetRefCount() == FINAL_REFS, "Object still referenced on destroy?" ); - DevMsg( "%s:destroy 0x%x\n", ( pszName ) ? pszName : "", this ); - } - - int AddRef() - { - DevMsg( "%s:(0x%x)->AddRef() --> %d\n", ( pszName ) ? pszName : "", this, this->GetRefCount() + 1 ); - return BASE_REFCOUNTED::AddRef(); - } - - int Release() - { - DevMsg( "%s:(0x%x)->Release() --> %d\n", ( pszName ) ? pszName : "", this, this->GetRefCount() - 1 ); - Assert( this->GetRefCount() > 0 ); - return BASE_REFCOUNTED::Release(); - } -#endif -}; -#endif - -//----------------------------------------------------------------------------- - -#endif // REFCOUNT_H diff --git a/public/tier1/smartptr.h b/public/tier1/smartptr.h deleted file mode 100644 index 8eb5e6900..000000000 --- a/public/tier1/smartptr.h +++ /dev/null @@ -1,279 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SMARTPTR_H -#define SMARTPTR_H -#ifdef _WIN32 -#pragma once -#endif - - -class CRefCountAccessor -{ -public: - template< class T > - static void AddRef( T *pObj ) - { - pObj->AddRef(); - } - - template< class T > - static void Release( T *pObj ) - { - pObj->Release(); - } -}; - -// This can be used if your objects use AddReference/ReleaseReference function names. -class CRefCountAccessorLongName -{ -public: - template< class T > - static void AddRef( T *pObj ) - { - pObj->AddReference(); - } - - template< class T > - static void Release( T *pObj ) - { - pObj->ReleaseReference(); - } -}; - - -// -// CPlainAutoPtr -// is a smart wrapper for a pointer on the stack that performs "delete" upon destruction. -// -// No reference counting is performed, copying is prohibited "s_p2.Attach( s_p1.Detach() )" should be used -// for readability and ease of maintenance. -// -// Auto pointer supports an "arrow" operator for invoking methods on the pointee and a "dereference" operator -// for getting a pointee reference. -// -// No automatic casting to bool/ptrtype is performed to avoid bugs and problems (read on "safe bool idiom" -// if casting to bool or pointer happens to be useful). -// -// Test for validity with "IsValid", get the pointer with "Get". -// -template < typename T > -class CPlainAutoPtr -{ -public: - explicit CPlainAutoPtr( T *p = NULL ) : m_p( p ) {} - ~CPlainAutoPtr( void ) { Delete(); } - -public: - void Delete( void ) { delete Detach(); } - -private: // Disallow copying, use Detach() instead to avoid ambiguity - CPlainAutoPtr( CPlainAutoPtr const &x ); - CPlainAutoPtr & operator = ( CPlainAutoPtr const &x ); - -public: - void Attach( T *p ) { m_p = p; } - T * Detach( void ) { T * p( m_p ); m_p = NULL; return p; } - -public: - bool IsValid( void ) const { return m_p != NULL; } - T * Get( void ) const { return m_p; } - T * operator -> ( void ) const { return Get(); } - T & operator * ( void ) const { return *Get(); } - -private: - T * m_p; -}; - -// -// CArrayAutoPtr -// is a smart wrapper for an array pointer on the stack that performs "delete []" upon destruction. -// -// No reference counting is performed, copying is prohibited "s_p2.Attach( s_p1.Detach() )" should be used -// for readability and ease of maintenance. -// -// Auto pointer supports an "indexing" operator for accessing array elements. -// -// No automatic casting to bool/ptrtype is performed to avoid bugs and problems (read on "safe bool idiom" -// if casting to bool or pointer happens to be useful). -// -// Test for validity with "IsValid", get the array pointer with "Get". -// -template < typename T > -class CArrayAutoPtr : public CPlainAutoPtr < T > // Warning: no polymorphic destructor (delete on base class will be a mistake) -{ -public: - explicit CArrayAutoPtr( T *p = NULL ) { Attach( p ); } - ~CArrayAutoPtr( void ) { Delete(); } - -public: - void Delete( void ) { delete [] Detach(); } - -public: - T & operator [] ( int k ) const { return Get()[ k ]; } -}; - - -// Smart pointers can be used to automatically free an object when nobody points -// at it anymore. Things contained in smart pointers must implement AddRef and Release -// functions. If those functions are private, then the class must make -// CRefCountAccessor a friend. -template -class CSmartPtr -{ -public: - CSmartPtr(); - CSmartPtr( T *pObj ); - CSmartPtr( const CSmartPtr &other ); - ~CSmartPtr(); - - T* operator=( T *pObj ); - void operator=( const CSmartPtr &other ); - const T* operator->() const; - T* operator->(); - bool operator!() const; - bool operator==( const T *pOther ) const; - bool IsValid() const; // Tells if the pointer is valid. - T* GetObject() const; // Get temporary object pointer, don't store it for later reuse! - void MarkDeleted(); - -private: - T *m_pObj; -}; - - -template< class T, class RefCountAccessor > -inline CSmartPtr::CSmartPtr() -{ - m_pObj = NULL; -} - -template< class T, class RefCountAccessor > -inline CSmartPtr::CSmartPtr( T *pObj ) -{ - m_pObj = NULL; - *this = pObj; -} - -template< class T, class RefCountAccessor > -inline CSmartPtr::CSmartPtr( const CSmartPtr &other ) -{ - m_pObj = NULL; - *this = other; -} - -template< class T, class RefCountAccessor > -inline CSmartPtr::~CSmartPtr() -{ - if ( m_pObj ) - { - RefCountAccessor::Release( m_pObj ); - } -} - -template< class T, class RefCountAccessor > -inline T* CSmartPtr::operator=( T *pObj ) -{ - if ( pObj == m_pObj ) - return pObj; - - if ( pObj ) - { - RefCountAccessor::AddRef( pObj ); - } - if ( m_pObj ) - { - RefCountAccessor::Release( m_pObj ); - } - m_pObj = pObj; - return pObj; -} - -template< class T, class RefCountAccessor > -inline void CSmartPtr::MarkDeleted() -{ - m_pObj = NULL; -} - -template< class T, class RefCountAccessor > -inline void CSmartPtr::operator=( const CSmartPtr &other ) -{ - *this = other.m_pObj; -} - -template< class T, class RefCountAccessor > -inline const T* CSmartPtr::operator->() const -{ - return m_pObj; -} - -template< class T, class RefCountAccessor > -inline T* CSmartPtr::operator->() -{ - return m_pObj; -} - -template< class T, class RefCountAccessor > -inline bool CSmartPtr::operator!() const -{ - return !m_pObj; -} - -template< class T, class RefCountAccessor > -inline bool CSmartPtr::operator==( const T *pOther ) const -{ - return m_pObj == pOther; -} - -template< class T, class RefCountAccessor > -inline bool CSmartPtr::IsValid() const -{ - return m_pObj != NULL; -} - -template< class T, class RefCountAccessor > -inline T* CSmartPtr::GetObject() const -{ - return m_pObj; -} - - -// -// CAutoPushPop -// allows you to set value of a variable upon construction and destruction. -// Constructors: -// CAutoPushPop x( myvar ) -// saves the value and restores upon destruction. -// CAutoPushPop x( myvar, newvalue ) -// saves the value, assigns new value upon construction, restores saved value upon destruction. -// CAutoPushPop x( myvar, newvalue, restorevalue ) -// assigns new value upon construction, assignes restorevalue upon destruction. -// -template < typename T > -class CAutoPushPop -{ -public: - explicit CAutoPushPop( T& var ) : m_rVar( var ), m_valPop( var ) {} - CAutoPushPop( T& var, T const &valPush ) : m_rVar( var ), m_valPop( var ) { m_rVar = valPush; } - CAutoPushPop( T& var, T const &valPush, T const &valPop ) : m_rVar( var ), m_valPop( var ) { m_rVar = valPush; } - - ~CAutoPushPop() { m_rVar = m_valPop; } - -private: // forbid copying - CAutoPushPop( CAutoPushPop const &x ); - CAutoPushPop & operator = ( CAutoPushPop const &x ); - -public: - T & Get() { return m_rVar; } - -private: - T &m_rVar; - T m_valPop; -}; - - -#endif // SMARTPTR_H diff --git a/public/tier1/stringpool.h b/public/tier1/stringpool.h deleted file mode 100644 index 70d589c19..000000000 --- a/public/tier1/stringpool.h +++ /dev/null @@ -1,91 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef STRINGPOOL_H -#define STRINGPOOL_H - -#if defined( _WIN32 ) -#pragma once -#endif - -#include "utlrbtree.h" -#include "utlvector.h" - -//----------------------------------------------------------------------------- -// Purpose: Allocates memory for strings, checking for duplicates first, -// reusing exising strings if duplicate found. -//----------------------------------------------------------------------------- - -class CStringPool -{ -public: - CStringPool(); - ~CStringPool(); - - unsigned int Count() const; - - const char * Allocate( const char *pszValue ); - void FreeAll(); - - // searches for a string already in the pool - const char * Find( const char *pszValue ); - -protected: - typedef CUtlRBTree CStrSet; - - CStrSet m_Strings; -}; - -//----------------------------------------------------------------------------- -// Purpose: A reference counted string pool. -// -// Elements are stored more efficiently than in the conventional string pool, -// quicker to look up, and storage is tracked via reference counts. -// -// At some point this should replace CStringPool -//----------------------------------------------------------------------------- -class CCountedStringPool -{ -public: // HACK, hash_item_t structure should not be public. - - struct hash_item_t - { - char* pString; - unsigned short nNextElement; - unsigned char nReferenceCount; - unsigned char pad; - }; - - enum - { - INVALID_ELEMENT = 0, - MAX_REFERENCE = 0xFF, - HASH_TABLE_SIZE = 1024 - }; - - CUtlVector m_HashTable; // Points to each element - CUtlVector m_Elements; - unsigned short m_FreeListStart; - -public: - CCountedStringPool(); - virtual ~CCountedStringPool(); - - void FreeAll(); - - char *FindString( const char* pIntrinsic ); - char *ReferenceString( const char* pIntrinsic ); - void DereferenceString( const char* pIntrinsic ); - - // These are only reliable if there are less than 64k strings in your string pool - unsigned short FindStringHandle( const char* pIntrinsic ); - unsigned short ReferenceStringHandle( const char* pIntrinsic ); - char *HandleToString( unsigned short handle ); - void SpewStrings(); -}; - -#endif // STRINGPOOL_H diff --git a/public/tier1/strtools.h b/public/tier1/strtools.h deleted file mode 100644 index e69972e0f..000000000 --- a/public/tier1/strtools.h +++ /dev/null @@ -1,462 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// - -#ifndef TIER1_STRTOOLS_H -#define TIER1_STRTOOLS_H - -#include "tier0/platform.h" - -#ifdef _WIN32 -#pragma once -#elif defined(_LINUX) || defined(__APPLE__) -#include -#include -#include -#endif - -#include -#include - -template< class T, class I > class CUtlMemory; -template< class T, class A > class CUtlVector; - -#if defined(_LINUX) || defined(__APPLE__) -inline char *strupr( char *start ) -{ - char *str = start; - while( str && *str ) - { - *str = (char)toupper(*str); - str++; - } - return start; -} - -inline char *strlwr( char *start ) -{ - char *str = start; - while( str && *str ) - { - *str = (char)tolower(*str); - str++; - } - return start; -} - -#endif // _LINUX - -//----------------------------------------------------------------------------- -// Portable versions of standard string functions -//----------------------------------------------------------------------------- -void _V_memset ( const char* file, int line, void *dest, int fill, int count ); -void _V_memcpy ( const char* file, int line, void *dest, const void *src, int count ); -void _V_memmove ( const char* file, int line, void *dest, const void *src, int count ); -int _V_memcmp ( const char* file, int line, const void *m1, const void *m2, int count ); -int _V_strlen ( const char* file, int line, const char *str ); -void _V_strcpy ( const char* file, int line, char *dest, const char *src ); -char* _V_strrchr ( const char* file, int line, const char *s, char c ); -int _V_strcmp ( const char* file, int line, const char *s1, const char *s2 ); -int _V_wcscmp ( const char* file, int line, const wchar_t *s1, const wchar_t *s2 ); -int _V_stricmp ( const char* file, int line, const char *s1, const char *s2 ); -char* _V_strstr ( const char* file, int line, const char *s1, const char *search ); -char* _V_strupr ( const char* file, int line, char *start ); -char* _V_strlower ( const char* file, int line, char *start ); -int _V_wcslen ( const char* file, int line, const wchar_t *pwch ); - - -#ifdef _DEBUG - -#define V_memset(dest, fill, count) _V_memset (__FILE__, __LINE__, (dest), (fill), (count)) -#define V_memcpy(dest, src, count) _V_memcpy (__FILE__, __LINE__, (dest), (src), (count)) -#define V_memmove(dest, src, count) _V_memmove (__FILE__, __LINE__, (dest), (src), (count)) -#define V_memcmp(m1, m2, count) _V_memcmp (__FILE__, __LINE__, (m1), (m2), (count)) -#define V_strlen(str) _V_strlen (__FILE__, __LINE__, (str)) -#define V_strcpy(dest, src) _V_strcpy (__FILE__, __LINE__, (dest), (src)) -#define V_strrchr(s, c) _V_strrchr (__FILE__, __LINE__, (s), (c)) -#define V_strcmp(s1, s2) _V_strcmp (__FILE__, __LINE__, (s1), (s2)) -#define V_wcscmp(s1, s2) _V_wcscmp (__FILE__, __LINE__, (s1), (s2)) -#define V_stricmp(s1, s2 ) _V_stricmp (__FILE__, __LINE__, (s1), (s2) ) -#define V_strstr(s1, search ) _V_strstr (__FILE__, __LINE__, (s1), (search) ) -#define V_strupr(start) _V_strupr (__FILE__, __LINE__, (start)) -#define V_strlower(start) _V_strlower (__FILE__, __LINE__, (start)) -#define V_wcslen(pwch) _V_wcslen (__FILE__, __LINE__, (pwch)) - -#else - -inline void V_memset (void *dest, int fill, int count) { memset( dest, fill, count ); } -inline void V_memcpy (void *dest, const void *src, int count) { memcpy( dest, src, count ); } -inline void V_memmove (void *dest, const void *src, int count) { memmove( dest, src, count ); } -inline int V_memcmp (const void *m1, const void *m2, int count){ return memcmp( m1, m2, count ); } -inline int V_strlen (const char *str) { return (int) strlen ( str ); } -inline void V_strcpy (char *dest, const char *src) { strcpy( dest, src ); } -inline int V_wcslen(const wchar_t *pwch) { return (int)wcslen(pwch); } -inline char* V_strrchr (const char *s, char c) { return (char*)strrchr( s, c ); } -inline int V_strcmp (const char *s1, const char *s2) { return strcmp( s1, s2 ); } -inline int V_wcscmp (const wchar_t *s1, const wchar_t *s2) { return wcscmp( s1, s2 ); } -inline int V_stricmp( const char *s1, const char *s2 ) { return stricmp( s1, s2 ); } -inline char* V_strstr( const char *s1, const char *search ) { return (char*)strstr( s1, search ); } -inline char* V_strupr (char *start) { return strupr( start ); } -inline char* V_strlower (char *start) { return strlwr( start ); } - -#endif - -int V_strncmp (const char *s1, const char *s2, int count); -int V_strcasecmp (const char *s1, const char *s2); -int V_strncasecmp (const char *s1, const char *s2, int n); -int V_strnicmp (const char *s1, const char *s2, int n); -int V_atoi (const char *str); -float V_atof (const char *str); -char* V_stristr( char* pStr, const char* pSearch ); -const char* V_stristr( const char* pStr, const char* pSearch ); -const char* V_strnistr( const char* pStr, const char* pSearch, int n ); -const char* V_strnchr( const char* pStr, char c, int n ); - -// returns string immediately following prefix, (ie str+strlen(prefix)) or NULL if prefix not found -const char *StringAfterPrefix ( const char *str, const char *prefix ); -const char *StringAfterPrefixCaseSensitive( const char *str, const char *prefix ); -inline bool StringHasPrefix ( const char *str, const char *prefix ) { return StringAfterPrefix ( str, prefix ) != NULL; } -inline bool StringHasPrefixCaseSensitive( const char *str, const char *prefix ) { return StringAfterPrefixCaseSensitive( str, prefix ) != NULL; } - - -// Normalizes a float string in place. -// (removes leading zeros, trailing zeros after the decimal point, and the decimal point itself where possible) -void V_normalizeFloatString( char* pFloat ); - - - -// These are versions of functions that guarantee NULL termination. -// -// maxLen is the maximum number of bytes in the destination string. -// pDest[maxLen-1] is always NULL terminated if pSrc's length is >= maxLen. -// -// This means the last parameter can usually be a sizeof() of a string. -void V_strncpy( char *pDest, const char *pSrc, int maxLen ); -int V_snprintf( char *pDest, int destLen, const char *pFormat, ... ); -void V_wcsncpy( wchar_t *pDest, wchar_t const *pSrc, int maxLenInBytes ); -int V_snwprintf( wchar_t *pDest, int destLen, const wchar_t *pFormat, ... ); - -#define COPY_ALL_CHARACTERS -1 -char *V_strncat(char *, const char *, size_t destBufferSize, int max_chars_to_copy=COPY_ALL_CHARACTERS ); -char *V_strnlwr(char *, size_t); - - -// UNDONE: Find a non-compiler-specific way to do this -#ifdef _WIN32 -#ifndef _VA_LIST_DEFINED - -#ifdef _M_ALPHA - -struct va_list -{ - char *a0; /* pointer to first homed integer argument */ - int offset; /* byte offset of next parameter */ -}; - -#else // !_M_ALPHA - -typedef char * va_list; - -#endif // !_M_ALPHA - -#define _VA_LIST_DEFINED - -#endif // _VA_LIST_DEFINED - -#elif defined(_LINUX) || defined(__APPLE__) -#include -#endif - -#ifdef _WIN32 -#define CORRECT_PATH_SEPARATOR '\\' -#define INCORRECT_PATH_SEPARATOR '/' -#elif defined(_LINUX) || defined(__APPLE__) -#define CORRECT_PATH_SEPARATOR '/' -#define INCORRECT_PATH_SEPARATOR '\\' -#endif - -int V_vsnprintf( char *pDest, int maxLen, const char *pFormat, va_list params ); - -// Prints out a pretified memory counter string value ( e.g., 7,233.27 Mb, 1,298.003 Kb, 127 bytes ) -char *V_pretifymem( float value, int digitsafterdecimal = 2, bool usebinaryonek = false ); - -// Prints out a pretified integer with comma separators (eg, 7,233,270,000) -char *V_pretifynum( int64 value ); - -// conversion functions wchar_t <-> char, returning the number of characters converted -int V_UTF8ToUnicode( const char *pUTF8, wchar_t *pwchDest, int cubDestSizeInBytes ); -int V_UnicodeToUTF8( const wchar_t *pUnicode, char *pUTF8, int cubDestSizeInBytes ); - -// Functions for converting hexidecimal character strings back into binary data etc. -// -// e.g., -// int output; -// V_hextobinary( "ffffffff", 8, &output, sizeof( output ) ); -// would make output == 0xfffffff or -1 -// Similarly, -// char buffer[ 9 ]; -// V_binarytohex( &output, sizeof( output ), buffer, sizeof( buffer ) ); -// would put "ffffffff" into buffer (note null terminator!!!) -void V_hextobinary( char const *in, int numchars, byte *out, int maxoutputbytes ); -void V_binarytohex( const byte *in, int inputbytes, char *out, int outsize ); - -// Tools for working with filenames -// Extracts the base name of a file (no path, no extension, assumes '/' or '\' as path separator) -void V_FileBase( const char *in, char *out,int maxlen ); -// Remove the final characters of ppath if it's '\' or '/'. -void V_StripTrailingSlash( char *ppath ); -// Remove any extension from in and return resulting string in out -void V_StripExtension( const char *in, char *out, int outLen ); -// Make path end with extension if it doesn't already have an extension -void V_DefaultExtension( char *path, const char *extension, int pathStringLength ); -// Strips any current extension from path and ensures that extension is the new extension -void V_SetExtension( char *path, const char *extension, int pathStringLength ); -// Removes any filename from path ( strips back to previous / or \ character ) -void V_StripFilename( char *path ); -// Remove the final directory from the path -bool V_StripLastDir( char *dirName, int maxlen ); -// Returns a pointer to the unqualified file name (no path) of a file name -const char * V_UnqualifiedFileName( const char * in ); -// Given a path and a filename, composes "path\filename", inserting the (OS correct) separator if necessary -void V_ComposeFileName( const char *path, const char *filename, char *dest, int destSize ); - -// Copy out the path except for the stuff after the final pathseparator -bool V_ExtractFilePath( const char *path, char *dest, int destSize ); -// Copy out the file extension into dest -void V_ExtractFileExtension( const char *path, char *dest, int destSize ); - -const char *V_GetFileExtension( const char * path ); - -// This removes "./" and "../" from the pathname. pFilename should be a full pathname. -// Returns false if it tries to ".." past the root directory in the drive (in which case -// it is an invalid path). -bool V_RemoveDotSlashes( char *pFilename, char separator = CORRECT_PATH_SEPARATOR ); - -// If pPath is a relative path, this function makes it into an absolute path -// using the current working directory as the base, or pStartingDir if it's non-NULL. -// Returns false if it runs out of room in the string, or if pPath tries to ".." past the root directory. -void V_MakeAbsolutePath( char *pOut, int outLen, const char *pPath, const char *pStartingDir = NULL ); - -// Creates a relative path given two full paths -// The first is the full path of the file to make a relative path for. -// The second is the full path of the directory to make the first file relative to -// Returns false if they can't be made relative (on separate drives, for example) -bool V_MakeRelativePath( const char *pFullPath, const char *pDirectory, char *pRelativePath, int nBufLen ); - -// Fixes up a file name, removing dot slashes, fixing slashes, converting to lowercase, etc. -void V_FixupPathName( char *pOut, size_t nOutLen, const char *pPath ); - -// Adds a path separator to the end of the string if there isn't one already. Returns false if it would run out of space. -void V_AppendSlash( char *pStr, int strSize ); - -// Returns true if the path is an absolute path. -bool V_IsAbsolutePath( const char *pPath ); - -// Scans pIn and replaces all occurences of pMatch with pReplaceWith. -// Writes the result to pOut. -// Returns true if it completed successfully. -// If it would overflow pOut, it fills as much as it can and returns false. -bool V_StrSubst( const char *pIn, const char *pMatch, const char *pReplaceWith, - char *pOut, int outLen, bool bCaseSensitive=false ); - -// Split the specified string on the specified separator. -// Returns a list of strings separated by pSeparator. -// You are responsible for freeing the contents of outStrings (call outStrings.PurgeAndDeleteElements). -void V_SplitString( const char *pString, const char *pSeparator, CUtlVector > &outStrings ); - -// Just like V_SplitString, but it can use multiple possible separators. -void V_SplitString2( const char *pString, const char **pSeparators, int nSeparators, CUtlVector > &outStrings ); - -// Returns false if the buffer is not large enough to hold the working directory name. -bool V_GetCurrentDirectory( char *pOut, int maxLen ); - -// Set the working directory thus. -bool V_SetCurrentDirectory( const char *pDirName ); - - -// This function takes a slice out of pStr and stores it in pOut. -// It follows the Python slice convention: -// Negative numbers wrap around the string (-1 references the last character). -// Large numbers are clamped to the end of the string. -void V_StrSlice( const char *pStr, int firstChar, int lastCharNonInclusive, char *pOut, int outSize ); - -// Chop off the left nChars of a string. -void V_StrLeft( const char *pStr, int nChars, char *pOut, int outSize ); - -// Chop off the right nChars of a string. -void V_StrRight( const char *pStr, int nChars, char *pOut, int outSize ); - -// change "special" characters to have their c-style backslash sequence. like \n, \r, \t, ", etc. -// returns a pointer to a newly allocated string, which you must delete[] when finished with. -char *V_AddBackSlashesToSpecialChars( char const *pSrc ); - -// Force slashes of either type to be = separator character -void V_FixSlashes( char *pname, char separator = CORRECT_PATH_SEPARATOR ); - -// This function fixes cases of filenames like materials\\blah.vmt or somepath\otherpath\\ and removes the extra double slash. -void V_FixDoubleSlashes( char *pStr ); - -// Convert multibyte to wchar + back -// Specify -1 for nInSize for null-terminated string -void V_strtowcs( const char *pString, int nInSize, wchar_t *pWString, int nOutSize ); -void V_wcstostr( const wchar_t *pWString, int nInSize, char *pString, int nOutSize ); - -// buffer-safe strcat -inline void V_strcat( char *dest, const char *src, int cchDest ) -{ - V_strncat( dest, src, cchDest, COPY_ALL_CHARACTERS ); -} - - -//----------------------------------------------------------------------------- -// generic unique name helper functions -//----------------------------------------------------------------------------- - -// returns startindex if none found, 2 if "prefix" found, and n+1 if "prefixn" found -template < class NameArray > -int V_GenerateUniqueNameIndex( const char *prefix, const NameArray &nameArray, int startindex = 0 ) -{ - if ( prefix == NULL ) - return 0; - - int freeindex = startindex; - - int nNames = nameArray.Count(); - for ( int i = 0; i < nNames; ++i ) - { - const char *pName = nameArray[ i ]; - if ( !pName ) - continue; - - const char *pIndexStr = StringAfterPrefix( pName, prefix ); - if ( pIndexStr ) - { - int index = *pIndexStr ? atoi( pIndexStr ) : 1; - if ( index >= freeindex ) - { - // TODO - check that there isn't more junk after the index in pElementName - freeindex = index + 1; - } - } - } - - return freeindex; -} - -template < class NameArray > -bool V_GenerateUniqueName( char *name, int memsize, const char *prefix, const NameArray &nameArray ) -{ - if ( name == NULL || memsize == 0 ) - return false; - - if ( prefix == NULL ) - { - name[ 0 ] = '\0'; - return false; - } - - int prefixLength = V_strlen( prefix ); - if ( prefixLength + 1 > memsize ) - { - name[ 0 ] = '\0'; - return false; - } - - int i = V_GenerateUniqueNameIndex( prefix, nameArray ); - if ( i <= 0 ) - { - V_strncpy( name, prefix, memsize ); - return true; - } - - int newlen = prefixLength + ( int )log10( ( float )i ) + 1; - if ( newlen + 1 > memsize ) - { - V_strncpy( name, prefix, memsize ); - return false; - } - - V_snprintf( name, memsize, "%s%d", prefix, i ); - return true; -} - - - -// NOTE: This is for backward compatability! -// We need to DLL-export the Q methods in vstdlib but not link to them in other projects -#if !defined( VSTDLIB_BACKWARD_COMPAT ) - -#define Q_memset V_memset -#define Q_memcpy V_memcpy -#define Q_memmove V_memmove -#define Q_memcmp V_memcmp -#define Q_strlen V_strlen -#define Q_strcpy V_strcpy -#define Q_strrchr V_strrchr -#define Q_strcmp V_strcmp -#define Q_wcscmp V_wcscmp -#define Q_stricmp V_stricmp -#define Q_strstr V_strstr -#define Q_strupr V_strupr -#define Q_strlower V_strlower -#define Q_wcslen V_wcslen -#define Q_strncmp V_strncmp -#define Q_strcasecmp V_strcasecmp -#define Q_strncasecmp V_strncasecmp -#define Q_strnicmp V_strnicmp -#define Q_atoi V_atoi -#define Q_atof V_atof -#define Q_stristr V_stristr -#define Q_strnistr V_strnistr -#define Q_strnchr V_strnchr -#define Q_normalizeFloatString V_normalizeFloatString -#define Q_strncpy V_strncpy -#define Q_snprintf V_snprintf -#define Q_wcsncpy V_wcsncpy -#define Q_strncat V_strncat -#define Q_strnlwr V_strnlwr -#define Q_vsnprintf V_vsnprintf -#define Q_pretifymem V_pretifymem -#define Q_pretifynum V_pretifynum -#define Q_UTF8ToUnicode V_UTF8ToUnicode -#define Q_UnicodeToUTF8 V_UnicodeToUTF8 -#define Q_hextobinary V_hextobinary -#define Q_binarytohex V_binarytohex -#define Q_FileBase V_FileBase -#define Q_StripTrailingSlash V_StripTrailingSlash -#define Q_StripExtension V_StripExtension -#define Q_DefaultExtension V_DefaultExtension -#define Q_SetExtension V_SetExtension -#define Q_StripFilename V_StripFilename -#define Q_StripLastDir V_StripLastDir -#define Q_UnqualifiedFileName V_UnqualifiedFileName -#define Q_ComposeFileName V_ComposeFileName -#define Q_ExtractFilePath V_ExtractFilePath -#define Q_ExtractFileExtension V_ExtractFileExtension -#define Q_GetFileExtension V_GetFileExtension -#define Q_RemoveDotSlashes V_RemoveDotSlashes -#define Q_MakeAbsolutePath V_MakeAbsolutePath -#define Q_AppendSlash V_AppendSlash -#define Q_IsAbsolutePath V_IsAbsolutePath -#define Q_StrSubst V_StrSubst -#define Q_SplitString V_SplitString -#define Q_SplitString2 V_SplitString2 -#define Q_StrSlice V_StrSlice -#define Q_StrLeft V_StrLeft -#define Q_StrRight V_StrRight -#define Q_FixSlashes V_FixSlashes -#define Q_strtowcs V_strtowcs -#define Q_wcstostr V_wcstostr -#define Q_strcat V_strcat -#define Q_GenerateUniqueNameIndex V_GenerateUniqueNameIndex -#define Q_GenerateUniqueName V_GenerateUniqueName -#define Q_MakeRelativePath V_MakeRelativePath - -#endif // !defined( VSTDLIB_DLL_EXPORT ) - - -#endif // TIER1_STRTOOLS_H diff --git a/public/tier1/tier1.h b/public/tier1/tier1.h deleted file mode 100644 index 1b02c84e3..000000000 --- a/public/tier1/tier1.h +++ /dev/null @@ -1,106 +0,0 @@ -//===== Copyright 2005-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: A higher level link library for general use in the game and tools. -// -//===========================================================================// - - -#ifndef TIER1_H -#define TIER1_H - -#if defined( _WIN32 ) -#pragma once -#endif - -#include "appframework/IAppSystem.h" -#include "tier1/convar.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class ICvar; -class IProcessUtils; - - -//----------------------------------------------------------------------------- -// These tier1 libraries must be set by any users of this library. -// They can be set by calling ConnectTier1Libraries. -// It is hoped that setting this, and using this library will be the common mechanism for -// allowing link libraries to access tier1 library interfaces -//----------------------------------------------------------------------------- - -// These are marked DLL_EXPORT for Linux. -DLL_EXPORT ICvar *cvar; -DLL_EXPORT ICvar *g_pCVar; -extern IProcessUtils *g_pProcessUtils; - - -//----------------------------------------------------------------------------- -// Call this to connect to/disconnect from all tier 1 libraries. -// It's up to the caller to check the globals it cares about to see if ones are missing -//----------------------------------------------------------------------------- -void ConnectTier1Libraries( CreateInterfaceFn *pFactoryList, int nFactoryCount ); -void DisconnectTier1Libraries(); - - -//----------------------------------------------------------------------------- -// Helper empty implementation of an IAppSystem for tier2 libraries -//----------------------------------------------------------------------------- -template< class IInterface, int ConVarFlag = 0 > -class CTier1AppSystem : public CTier0AppSystem< IInterface > -{ - typedef CTier0AppSystem< IInterface > BaseClass; - -public: - CTier1AppSystem( bool bIsPrimaryAppSystem = true ) : BaseClass( bIsPrimaryAppSystem ) - { - } - - virtual bool Connect( CreateInterfaceFn factory ) - { - if ( !BaseClass::Connect( factory ) ) - return false; - - if ( CTier0AppSystem::IsPrimaryAppSystem() ) - { - ConnectTier1Libraries( &factory, 1 ); - } - return true; - } - - virtual void Disconnect() - { - if ( CTier0AppSystem::IsPrimaryAppSystem() ) - { - DisconnectTier1Libraries(); - } - BaseClass::Disconnect(); - } - - virtual InitReturnVal_t Init() - { - InitReturnVal_t nRetVal = BaseClass::Init(); - if ( nRetVal != INIT_OK ) - return nRetVal; - - if ( g_pCVar && CTier0AppSystem::IsPrimaryAppSystem() ) - { - ConVar_Register( ConVarFlag ); - } - return INIT_OK; - } - - virtual void Shutdown() - { - if ( g_pCVar && CTier0AppSystem::IsPrimaryAppSystem() ) - { - ConVar_Unregister( ); - } - BaseClass::Shutdown( ); - } -}; - - -#endif // TIER1_H - diff --git a/public/tier1/tokenreader.h b/public/tier1/tokenreader.h deleted file mode 100644 index 7407a579c..000000000 --- a/public/tier1/tokenreader.h +++ /dev/null @@ -1,107 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef TOKENREADER_H -#define TOKENREADER_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/basetypes.h" - -#ifdef _WIN32 -#pragma warning(push, 1) -#pragma warning(disable:4701 4702 4530) -#endif - -#include - -#ifdef _WIN32 -#pragma warning(pop) -#endif - -#include - - -typedef enum -{ - TOKENSTRINGTOOLONG = -4, - TOKENERROR = -3, - TOKENNONE = -2, - TOKENEOF = -1, - OPERATOR, - INTEGER, - STRING, - IDENT -} trtoken_t; - - -#define IsToken(s1, s2) !strcmpi(s1, s2) - -#define MAX_TOKEN 128 + 1 -#define MAX_IDENT 64 + 1 -#define MAX_STRING 128 + 1 - - -class TokenReader : private std::ifstream -{ -public: - - TokenReader(); - - bool Open(const char *pszFilename); - trtoken_t NextToken(char *pszStore, int nSize); - trtoken_t NextTokenDynamic(char **ppszStore); - void Close(); - - void IgnoreTill(trtoken_t ttype, const char *pszToken); - void Stuff(trtoken_t ttype, const char *pszToken); - bool Expecting(trtoken_t ttype, const char *pszToken); - const char *Error(char *error, ...); - trtoken_t PeekTokenType(char* = NULL, int maxlen = 0); - - inline int GetErrorCount(void); - -#if !defined _LINUX && !defined __APPLE__ - inline TokenReader(TokenReader const &) - { - // prevent vc7 warning. compiler can't generate a copy constructor since descended from - // std::ifstream - assert(0); - } - inline int operator=(TokenReader const &) - { - // prevent vc7 warning. compiler can't generate an assignment operator since descended from - // std::ifstream - assert(0); - } -#endif -private: - - trtoken_t GetString(char *pszStore, int nSize); - bool SkipWhiteSpace(void); - - int m_nLine; - int m_nErrorCount; - - char m_szFilename[128]; - char m_szStuffed[128]; - bool m_bStuffed; - trtoken_t m_eStuffed; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Returns the total number of parsing errors since this file was opened. -//----------------------------------------------------------------------------- -int TokenReader::GetErrorCount(void) -{ - return(m_nErrorCount); -} - - -#endif // TOKENREADER_H diff --git a/public/tier1/uniqueid.h b/public/tier1/uniqueid.h deleted file mode 100644 index 64aae9418..000000000 --- a/public/tier1/uniqueid.h +++ /dev/null @@ -1,56 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======// -// -// Purpose: -// -// $NoKeywords: $ -// -// Utilities for globally unique IDs -//=============================================================================// - -#ifndef UNIQUEID_H -#define UNIQUEID_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/utlvector.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -struct UniqueId_t; -class CUtlBuffer; - - -//----------------------------------------------------------------------------- -// Defines a globally unique ID -//----------------------------------------------------------------------------- -struct UniqueId_t -{ - unsigned char m_Value[16]; -}; - - -//----------------------------------------------------------------------------- -// Methods related to unique ids -//----------------------------------------------------------------------------- -void CreateUniqueId( UniqueId_t *pDest ); -void InvalidateUniqueId( UniqueId_t *pDest ); -bool IsUniqueIdValid( const UniqueId_t &id ); -bool IsUniqueIdEqual( const UniqueId_t &id1, const UniqueId_t &id2 ); -void UniqueIdToString( const UniqueId_t &id, char *pBuf, int nMaxLen ); -bool UniqueIdFromString( UniqueId_t *pDest, const char *pBuf, int nMaxLen = 0 ); -void CopyUniqueId( const UniqueId_t &src, UniqueId_t *pDest ); -bool Serialize( CUtlBuffer &buf, const UniqueId_t &src ); -bool Unserialize( CUtlBuffer &buf, UniqueId_t &dest ); - -inline bool operator ==( const UniqueId_t& lhs, const UniqueId_t& rhs ) -{ - return !Q_memcmp( (void *)&lhs.m_Value[ 0 ], (void *)&rhs.m_Value[ 0 ], sizeof( lhs.m_Value ) ); -} - - -#endif // UNIQUEID_H - diff --git a/public/tier1/utlbidirectionalset.h b/public/tier1/utlbidirectionalset.h deleted file mode 100644 index b733029a1..000000000 --- a/public/tier1/utlbidirectionalset.h +++ /dev/null @@ -1,381 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Bi-directional set. A Bucket knows about the elements that lie -// in it, and the elements know about the buckets they lie in. -// -// $Revision: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef UTLBIDIRECTIONALSET_H -#define UTLBIDIRECTIONALSET_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/dbg.h" -#include "utllinkedlist.h" - -//----------------------------------------------------------------------------- -// Templatized helper class to deal with the kinds of things that spatial -// partition code always seems to have; buckets with lists of lots of elements -// and elements that live in lots of buckets. This makes it really quick to -// add and remove elements, and to iterate over all elements in a bucket. -// -// For this to work, you must initialize the set with two functions one that -// maps from bucket to the index of the first element in that bucket, and one -// that maps from element to the index of the first bucket that element lies in. -// The set will completely manage the index, it's just expected that those -// indices will be stored outside the set. -// -// S is the storage type of the index; it is the type that you may use to -// save indices into memory. I is the local iterator type, which you should -// use in any local scope (eg, inside a for() loop.) The reason for this is -// that you may wish to use unsigned shorts inside the structs you are -// saving with a CBidirectionalSet; but 16-bit arithmetic is catastrophically -// slow on a PowerPC -- during testing we saw CBidirectionalSet:: operations -// consume as much as 8% of the frame. -// -// For this reason, on the 360, the handles have been typedef'd to native -// register types (U32) which are accepted as parameters by the functions. -// The implicit assumption is that CBucketHandle and CElementHandle can -// be safely cast to ints! You can increase to U64 without performance -// penalty if necessary; the PowerPC is a 64-bit processor. -//----------------------------------------------------------------------------- -template< class CBucketHandle, class CElementHandle, class S, class I = S > -class CBidirectionalSet -{ -public: - // Install methods to get at the first bucket given a element - // and vice versa... - typedef S& (*FirstElementFunc_t)(CBucketHandle); - typedef S& (*FirstBucketFunc_t)(CElementHandle); - -#ifdef _X360 - typedef uint32 CBucketHandlePram; - typedef uint32 CElementHandlePram; -#else - typedef CBucketHandle CBucketHandlePram; - typedef CElementHandle CElementHandlePram; -#endif - - // Constructor - CBidirectionalSet(); - - // Call this before using the set - void Init( FirstElementFunc_t elemFunc, FirstBucketFunc_t bucketFunc ); - - // Add an element to a particular bucket - void AddElementToBucket( CBucketHandlePram bucket, CElementHandlePram element ); - - // Prevalidate an add to a particular bucket - // NOTE: EXPENSIVE!!! - void ValidateAddElementToBucket( CBucketHandlePram bucket, CElementHandlePram element ); - - // Test if an element is in a particular bucket. - // NOTE: EXPENSIVE!!! - bool IsElementInBucket( CBucketHandlePram bucket, CElementHandlePram element ); - - // Remove an element from a particular bucket - void RemoveElementFromBucket( CBucketHandlePram bucket, CElementHandlePram element ); - - // Remove an element from all buckets - void RemoveElement( CElementHandlePram element ); - void RemoveBucket( CBucketHandlePram element ); - - // Used to iterate elements in a bucket; I is the iterator - I FirstElement( CBucketHandlePram bucket ) const; - I NextElement( I idx ) const; - CElementHandle Element( I idx ) const; - - // Used to iterate buckets associated with an element; I is the iterator - I FirstBucket( CElementHandlePram bucket ) const; - I NextBucket( I idx ) const; - CBucketHandle Bucket( I idx ) const; - - static S InvalidIndex(); - - // Ensure capacity - void EnsureCapacity( int count ); - - // Deallocate.... - void Purge(); - -private: - struct BucketListInfo_t - { - CElementHandle m_Element; - S m_BucketListIndex; // what's the m_BucketsUsedByElement index of the entry? - }; - - struct ElementListInfo_t - { - CBucketHandle m_Bucket; - S m_ElementListIndex; // what's the m_ElementsInBucket index of the entry? - }; - - // Maintains a list of all elements in a particular bucket - CUtlLinkedList< BucketListInfo_t, S, true, I > m_ElementsInBucket; - - // Maintains a list of all buckets a particular element lives in - CUtlLinkedList< ElementListInfo_t, S, true, I > m_BucketsUsedByElement; - - FirstBucketFunc_t m_FirstBucket; - FirstElementFunc_t m_FirstElement; -}; - - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -template< class CBucketHandle, class CElementHandle, class S, class I > -CBidirectionalSet::CBidirectionalSet( ) -{ - m_FirstBucket = NULL; - m_FirstElement = NULL; -} - - -//----------------------------------------------------------------------------- -// Call this before using the set -//----------------------------------------------------------------------------- -template< class CBucketHandle, class CElementHandle, class S, class I > -void CBidirectionalSet::Init( FirstElementFunc_t elemFunc, FirstBucketFunc_t bucketFunc ) -{ - m_FirstBucket = bucketFunc; - m_FirstElement = elemFunc; -} - - -//----------------------------------------------------------------------------- -// Adds an element to the bucket -//----------------------------------------------------------------------------- -template< class CBucketHandle, class CElementHandle, class S, class I > -void CBidirectionalSet::ValidateAddElementToBucket( CBucketHandlePram bucket, CElementHandlePram element ) -{ -#ifdef _DEBUG - // Make sure that this element doesn't already exist in the list of elements in the bucket - I elementInBucket = m_FirstElement( bucket ); - while( elementInBucket != m_ElementsInBucket.InvalidIndex() ) - { - // If you hit an Assert here, fix the calling code. It's too expensive to ensure - // that each item only shows up once here. Hopefully you can do something better - // outside of here. - Assert( m_ElementsInBucket[elementInBucket].m_Element != element ); - elementInBucket = m_ElementsInBucket.Next( elementInBucket ); - } - // Make sure that this bucket doesn't already exist in the element's list of buckets. - I bucketInElement = m_FirstBucket( element ); - while( bucketInElement != m_BucketsUsedByElement.InvalidIndex() ) - { - // If you hit an Assert here, fix the calling code. It's too expensive to ensure - // that each item only shows up once here. Hopefully you can do something better - // outside of here. - Assert( m_BucketsUsedByElement[bucketInElement].m_Bucket != bucket ); - bucketInElement = m_BucketsUsedByElement.Next( bucketInElement ); - } -#endif -} - - -//----------------------------------------------------------------------------- -// Adds an element to the bucket -//----------------------------------------------------------------------------- -template< class CBucketHandle, class CElementHandle, class S, class I > -void CBidirectionalSet::AddElementToBucket( CBucketHandlePram bucket, CElementHandlePram element ) -{ - Assert( m_FirstBucket && m_FirstElement ); - - // Allocate new element + bucket entries - I idx = m_ElementsInBucket.Alloc(true); - I list = m_BucketsUsedByElement.Alloc( true ); - - // Store off the element data - m_ElementsInBucket[idx].m_Element = element; - m_ElementsInBucket[idx].m_BucketListIndex = list; - - // Here's the bucket data - m_BucketsUsedByElement[list].m_Bucket = bucket; - m_BucketsUsedByElement[list].m_ElementListIndex = idx; - - // Insert the element into the list of elements in the bucket - S& firstElementInBucket = m_FirstElement( bucket ); - if ( firstElementInBucket != m_ElementsInBucket.InvalidIndex() ) - m_ElementsInBucket.LinkBefore( firstElementInBucket, idx ); - firstElementInBucket = idx; - - // Insert the bucket into the element's list of buckets - S& firstBucketInElement = m_FirstBucket( element ); - if ( firstBucketInElement != m_BucketsUsedByElement.InvalidIndex() ) - m_BucketsUsedByElement.LinkBefore( firstBucketInElement, list ); - firstBucketInElement = list; -} - -//----------------------------------------------------------------------------- -// Test if an element is in a particular bucket. -// NOTE: EXPENSIVE!!! -//----------------------------------------------------------------------------- -template< class CBucketHandle, class CElementHandle, class S, class I > -bool CBidirectionalSet::IsElementInBucket( CBucketHandlePram bucket, CElementHandlePram element ) -{ - // Search through all elements in this bucket to see if element is in there. - I elementInBucket = m_FirstElement( bucket ); - while( elementInBucket != m_ElementsInBucket.InvalidIndex() ) - { - if( m_ElementsInBucket[elementInBucket].m_Element == element ) - { - return true; - } - elementInBucket = m_ElementsInBucket.Next( elementInBucket ); - } - return false; -} - - -//----------------------------------------------------------------------------- -// Remove an element from a particular bucket -//----------------------------------------------------------------------------- -template< class CBucketHandle, class CElementHandle, class S, class I > -void CBidirectionalSet::RemoveElementFromBucket( CBucketHandlePram bucket, CElementHandlePram element ) -{ - // FIXME: Implement me! - Assert(0); -} - - -//----------------------------------------------------------------------------- -// Removes an element from all buckets -//----------------------------------------------------------------------------- -template< class CBucketHandle, class CElementHandle, class S, class I > -void CBidirectionalSet::RemoveElement( CElementHandlePram element ) -{ - Assert( m_FirstBucket && m_FirstElement ); - - // Iterate over the list of all buckets the element is in - I i = m_FirstBucket( element ); - while (i != m_BucketsUsedByElement.InvalidIndex()) - { - CBucketHandlePram bucket = m_BucketsUsedByElement[i].m_Bucket; - I elementListIndex = m_BucketsUsedByElement[i].m_ElementListIndex; - - // Unhook the element from the bucket's list of elements - if (elementListIndex == m_FirstElement(bucket)) - m_FirstElement(bucket) = m_ElementsInBucket.Next(elementListIndex); - m_ElementsInBucket.Free(elementListIndex); - - I prevNode = i; - i = m_BucketsUsedByElement.Next(i); - m_BucketsUsedByElement.Free(prevNode); - } - - // Mark the list as empty - m_FirstBucket( element ) = m_BucketsUsedByElement.InvalidIndex(); -} - -//----------------------------------------------------------------------------- -// Removes a bucket from all elements -//----------------------------------------------------------------------------- -template< class CBucketHandle, class CElementHandle, class S, class I > -void CBidirectionalSet::RemoveBucket( CBucketHandlePram bucket ) -{ - // Iterate over the list of all elements in the bucket - I i = m_FirstElement( bucket ); - while (i != m_ElementsInBucket.InvalidIndex()) - { - CElementHandlePram element = m_ElementsInBucket[i].m_Element; - I bucketListIndex = m_ElementsInBucket[i].m_BucketListIndex; - - // Unhook the bucket from the element's list of buckets - if (bucketListIndex == m_FirstBucket(element)) - m_FirstBucket(element) = m_BucketsUsedByElement.Next(bucketListIndex); - m_BucketsUsedByElement.Free(bucketListIndex); - - // Remove the list element - I prevNode = i; - i = m_ElementsInBucket.Next(i); - m_ElementsInBucket.Free(prevNode); - } - - // Mark the bucket list as empty - m_FirstElement( bucket ) = m_ElementsInBucket.InvalidIndex(); -} - - -//----------------------------------------------------------------------------- -// Ensure capacity -//----------------------------------------------------------------------------- -template< class CBucketHandle, class CElementHandle, class S, class I > -void CBidirectionalSet::EnsureCapacity( int count ) -{ - m_ElementsInBucket.EnsureCapacity( count ); - m_BucketsUsedByElement.EnsureCapacity( count ); -} - - -//----------------------------------------------------------------------------- -// Deallocate.... -//----------------------------------------------------------------------------- -template< class CBucketHandle, class CElementHandle, class S, class I > -void CBidirectionalSet::Purge() -{ - m_ElementsInBucket.Purge( ); - m_BucketsUsedByElement.Purge( ); -} - - -//----------------------------------------------------------------------------- -// Invalid index for iteration.. -//----------------------------------------------------------------------------- -template< class CBucketHandle, class CElementHandle, class S, class I > -inline S CBidirectionalSet::InvalidIndex() -{ - return CUtlLinkedList< CElementHandle, I >::InvalidIndex(); -} - - -//----------------------------------------------------------------------------- -// Used to iterate elements in a bucket; I is the iterator -//----------------------------------------------------------------------------- -template< class CBucketHandle, class CElementHandle, class S, class I > -inline I CBidirectionalSet::FirstElement( CBucketHandlePram bucket ) const -{ - Assert( m_FirstElement ); - return m_FirstElement(bucket); -} - -template< class CBucketHandle, class CElementHandle, class S, class I > -inline I CBidirectionalSet::NextElement( I idx ) const -{ - return m_ElementsInBucket.Next(idx); -} - -template< class CBucketHandle, class CElementHandle, class S, class I > -inline CElementHandle CBidirectionalSet::Element( I idx ) const -{ - return m_ElementsInBucket[idx].m_Element; -} - -//----------------------------------------------------------------------------- -// Used to iterate buckets an element lies in; I is the iterator -//----------------------------------------------------------------------------- -template< class CBucketHandle, class CElementHandle, class S, class I > -inline I CBidirectionalSet::FirstBucket( CElementHandlePram element ) const -{ - Assert( m_FirstBucket ); - return m_FirstBucket(element); -} - -template< class CBucketHandle, class CElementHandle, class S, class I > -inline I CBidirectionalSet::NextBucket( I idx ) const -{ - return m_BucketsUsedByElement.Next(idx); -} - -template< class CBucketHandle, class CElementHandle, class S, class I > -inline CBucketHandle CBidirectionalSet::Bucket( I idx ) const -{ - return m_BucketsUsedByElement[idx].m_Bucket; -} - -#endif // UTLBIDIRECTIONALSET_H diff --git a/public/tier1/utlblockmemory.h b/public/tier1/utlblockmemory.h deleted file mode 100644 index 02061d406..000000000 --- a/public/tier1/utlblockmemory.h +++ /dev/null @@ -1,351 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -// A growable memory class. -//===========================================================================// - -#ifndef UTLBLOCKMEMORY_H -#define UTLBLOCKMEMORY_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/dbg.h" -#include "tier0/platform.h" -#include "mathlib/mathlib.h" - -#include "tier0/memalloc.h" -#include "tier0/memdbgon.h" - -#ifdef _MSC_VER -#pragma warning (disable:4100) -#pragma warning (disable:4514) -#endif - -//----------------------------------------------------------------------------- - -#ifdef UTLMEMORY_TRACK -#define UTLMEMORY_TRACK_ALLOC() MemAlloc_RegisterAllocation( "Sum of all UtlBlockMemory", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 ) -#define UTLMEMORY_TRACK_FREE() if ( !m_pMemory ) ; else MemAlloc_RegisterDeallocation( "Sum of all UtlBlockMemory", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 ) -#else -#define UTLMEMORY_TRACK_ALLOC() ((void)0) -#define UTLMEMORY_TRACK_FREE() ((void)0) -#endif - - -//----------------------------------------------------------------------------- -// The CUtlBlockMemory class: -// A growable memory class that allocates non-sequential blocks, but is indexed sequentially -//----------------------------------------------------------------------------- -template< class T, class I > -class CUtlBlockMemory -{ -public: - // constructor, destructor - CUtlBlockMemory( int nGrowSize = 0, int nInitSize = 0 ); - ~CUtlBlockMemory(); - - // Set the size by which the memory grows - round up to the next power of 2 - void Init( int nGrowSize = 0, int nInitSize = 0 ); - - // here to match CUtlMemory, but only used by ResetDbgInfo, so it can just return NULL - T* Base() { return NULL; } - const T* Base() const { return NULL; } - - class Iterator_t - { - public: - Iterator_t( I i ) : index( i ) {} - I index; - - bool operator==( const Iterator_t it ) const { return index == it.index; } - bool operator!=( const Iterator_t it ) const { return index != it.index; } - }; - Iterator_t First() const { return Iterator_t( IsIdxValid( 0 ) ? 0 : InvalidIndex() ); } - Iterator_t Next( const Iterator_t &it ) const { return Iterator_t( IsIdxValid( it.index + 1 ) ? it.index + 1 : InvalidIndex() ); } - I GetIndex( const Iterator_t &it ) const { return it.index; } - bool IsIdxAfter( I i, const Iterator_t &it ) const { return i > it.index; } - bool IsValidIterator( const Iterator_t &it ) const { return IsIdxValid( it.index ); } - Iterator_t InvalidIterator() const { return Iterator_t( InvalidIndex() ); } - - // element access - T& operator[]( I i ); - const T& operator[]( I i ) const; - T& Element( I i ); - const T& Element( I i ) const; - - // Can we use this index? - bool IsIdxValid( I i ) const; - static I InvalidIndex() { return ( I )-1; } - - void Swap( CUtlBlockMemory< T, I > &mem ); - - // Size - int NumAllocated() const; - int Count() const { return NumAllocated(); } - - // Grows memory by MAX(num,growsize) rounded up to the next power of 2, and returns the allocation index/ptr - void Grow( int num = 1 ); - - // Makes sure we've got at least this much memory - void EnsureCapacity( int num ); - - // Memory deallocation - void Purge(); - - // Purge all but the given number of elements - void Purge( int numElements ); - -protected: - int Index( int major, int minor ) const { return ( major << m_nIndexShift ) | minor; } - int MajorIndex( int i ) const { return i >> m_nIndexShift; } - int MinorIndex( int i ) const { return i & m_nIndexMask; } - void ChangeSize( int nBlocks ); - int NumElementsInBlock() const { return m_nIndexMask + 1; } - - T** m_pMemory; - int m_nBlocks; - int m_nIndexMask : 27; - int m_nIndexShift : 5; -}; - -//----------------------------------------------------------------------------- -// constructor, destructor -//----------------------------------------------------------------------------- - -template< class T, class I > -CUtlBlockMemory::CUtlBlockMemory( int nGrowSize, int nInitAllocationCount ) -: m_pMemory( 0 ), m_nBlocks( 0 ), m_nIndexMask( 0 ), m_nIndexShift( 0 ) -{ - Init( nGrowSize, nInitAllocationCount ); -} - -template< class T, class I > -CUtlBlockMemory::~CUtlBlockMemory() -{ - Purge(); -} - - -//----------------------------------------------------------------------------- -// Fast swap -//----------------------------------------------------------------------------- -template< class T, class I > -void CUtlBlockMemory::Swap( CUtlBlockMemory< T, I > &mem ) -{ - swap( m_pMemory, mem.m_pMemory ); - swap( m_nBlocks, mem.m_nBlocks ); - swap( m_nIndexMask, mem.m_nIndexMask ); - swap( m_nIndexShift, mem.m_nIndexShift ); -} - - -//----------------------------------------------------------------------------- -// Set the size by which the memory grows - round up to the next power of 2 -//----------------------------------------------------------------------------- -template< class T, class I > -void CUtlBlockMemory::Init( int nGrowSize /* = 0 */, int nInitSize /* = 0 */ ) -{ - Purge(); - - if ( nGrowSize == 0) - { - // default grow size is smallest size s.t. c++ allocation overhead is ~6% of block size - nGrowSize = ( 127 + sizeof( T ) ) / sizeof( T ); - } - nGrowSize = SmallestPowerOfTwoGreaterOrEqual( nGrowSize ); - m_nIndexMask = nGrowSize - 1; - - m_nIndexShift = 0; - while ( nGrowSize > 1 ) - { - nGrowSize >>= 1; - ++m_nIndexShift; - } - Assert( m_nIndexMask + 1 == ( 1 << m_nIndexShift ) ); - - Grow( nInitSize ); -} - - -//----------------------------------------------------------------------------- -// element access -//----------------------------------------------------------------------------- -template< class T, class I > -inline T& CUtlBlockMemory::operator[]( I i ) -{ - Assert( IsIdxValid(i) ); - T *pBlock = m_pMemory[ MajorIndex( i ) ]; - return pBlock[ MinorIndex( i ) ]; -} - -template< class T, class I > -inline const T& CUtlBlockMemory::operator[]( I i ) const -{ - Assert( IsIdxValid(i) ); - const T *pBlock = m_pMemory[ MajorIndex( i ) ]; - return pBlock[ MinorIndex( i ) ]; -} - -template< class T, class I > -inline T& CUtlBlockMemory::Element( I i ) -{ - Assert( IsIdxValid(i) ); - T *pBlock = m_pMemory[ MajorIndex( i ) ]; - return pBlock[ MinorIndex( i ) ]; -} - -template< class T, class I > -inline const T& CUtlBlockMemory::Element( I i ) const -{ - Assert( IsIdxValid(i) ); - const T *pBlock = m_pMemory[ MajorIndex( i ) ]; - return pBlock[ MinorIndex( i ) ]; -} - - -//----------------------------------------------------------------------------- -// Size -//----------------------------------------------------------------------------- -template< class T, class I > -inline int CUtlBlockMemory::NumAllocated() const -{ - return m_nBlocks * NumElementsInBlock(); -} - - -//----------------------------------------------------------------------------- -// Is element index valid? -//----------------------------------------------------------------------------- -template< class T, class I > -inline bool CUtlBlockMemory::IsIdxValid( I i ) const -{ - return ( i >= 0 ) && ( MajorIndex( i ) < m_nBlocks ); -} - -template< class T, class I > -void CUtlBlockMemory::Grow( int num ) -{ - if ( num <= 0 ) - return; - - int nBlockSize = NumElementsInBlock(); - int nBlocks = ( num + nBlockSize - 1 ) / nBlockSize; - - ChangeSize( m_nBlocks + nBlocks ); -} - -template< class T, class I > -void CUtlBlockMemory::ChangeSize( int nBlocks ) -{ - UTLMEMORY_TRACK_FREE(); // this must stay before the recalculation of m_nBlocks, since it implicitly uses the old value - - int nBlocksOld = m_nBlocks; - m_nBlocks = nBlocks; - - UTLMEMORY_TRACK_ALLOC(); // this must stay after the recalculation of m_nBlocks, since it implicitly uses the new value - - // free old blocks if shrinking - for ( int i = m_nBlocks; i < nBlocksOld; ++i ) - { - UTLMEMORY_TRACK_FREE(); - free( (void*)m_pMemory[ i ] ); - } - - if ( m_pMemory ) - { - MEM_ALLOC_CREDIT_CLASS(); - m_pMemory = (T**)realloc( m_pMemory, m_nBlocks * sizeof(T*) ); - Assert( m_pMemory ); - } - else - { - MEM_ALLOC_CREDIT_CLASS(); - m_pMemory = (T**)malloc( m_nBlocks * sizeof(T*) ); - Assert( m_pMemory ); - } - - if ( !m_pMemory ) - { - Error( "CUtlBlockMemory overflow!\n" ); - } - - // allocate new blocks if growing - int nBlockSize = NumElementsInBlock(); - for ( int i = nBlocksOld; i < m_nBlocks; ++i ) - { - MEM_ALLOC_CREDIT_CLASS(); - m_pMemory[ i ] = (T*)malloc( nBlockSize * sizeof( T ) ); - Assert( m_pMemory[ i ] ); - } -} - - -//----------------------------------------------------------------------------- -// Makes sure we've got at least this much memory -//----------------------------------------------------------------------------- -template< class T, class I > -inline void CUtlBlockMemory::EnsureCapacity( int num ) -{ - Grow( num - NumAllocated() ); -} - - -//----------------------------------------------------------------------------- -// Memory deallocation -//----------------------------------------------------------------------------- -template< class T, class I > -void CUtlBlockMemory::Purge() -{ - if ( !m_pMemory ) - return; - - for ( int i = 0; i < m_nBlocks; ++i ) - { - UTLMEMORY_TRACK_FREE(); - free( (void*)m_pMemory[ i ] ); - } - m_nBlocks = 0; - - UTLMEMORY_TRACK_FREE(); - free( (void*)m_pMemory ); - m_pMemory = 0; -} - -template< class T, class I > -void CUtlBlockMemory::Purge( int numElements ) -{ - Assert( numElements >= 0 ); - - int nAllocated = NumAllocated(); - if ( numElements > nAllocated ) - { - // Ensure this isn't a grow request in disguise. - Assert( numElements <= nAllocated ); - return; - } - - if ( numElements <= 0 ) - { - Purge(); - return; - } - - int nBlockSize = NumElementsInBlock(); - int nBlocksOld = m_nBlocks; - int nBlocks = ( numElements + nBlockSize - 1 ) / nBlockSize; - - // If the number of blocks is the same as the allocated number of blocks, we are done. - if ( nBlocks == m_nBlocks ) - return; - - ChangeSize( nBlocks ); -} - -#include "tier0/memdbgoff.h" - -#endif // UTLBLOCKMEMORY_H diff --git a/public/tier1/utlbuffer.h b/public/tier1/utlbuffer.h deleted file mode 100644 index 4ce941166..000000000 --- a/public/tier1/utlbuffer.h +++ /dev/null @@ -1,1028 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======// -// -// Purpose: -// -// $NoKeywords: $ -// -// Serialization/unserialization buffer -//=============================================================================// - -#ifndef UTLBUFFER_H -#define UTLBUFFER_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/utlmemory.h" -#include "tier1/byteswap.h" -#include - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -struct characterset_t; - - -//----------------------------------------------------------------------------- -// Description of character conversions for string output -// Here's an example of how to use the macros to define a character conversion -// BEGIN_CHAR_CONVERSION( CStringConversion, '\\' ) -// { '\n', "n" }, -// { '\t', "t" } -// END_CHAR_CONVERSION( CStringConversion, '\\' ) -//----------------------------------------------------------------------------- -class CUtlCharConversion -{ -public: - struct ConversionArray_t - { - char m_nActualChar; - const char *m_pReplacementString; - }; - - CUtlCharConversion( char nEscapeChar, const char *pDelimiter, int nCount, ConversionArray_t *pArray ); - char GetEscapeChar() const; - const char *GetDelimiter() const; - int GetDelimiterLength() const; - - const char *GetConversionString( char c ) const; - int GetConversionLength( char c ) const; - int MaxConversionLength() const; - - // Finds a conversion for the passed-in string, returns length - virtual char FindConversion( const char *pString, int *pLength ); - -protected: - struct ConversionInfo_t - { - int m_nLength; - const char *m_pReplacementString; - }; - - char m_nEscapeChar; - const char *m_pDelimiter; - int m_nDelimiterLength; - int m_nCount; - int m_nMaxConversionLength; - char m_pList[255]; - ConversionInfo_t m_pReplacements[255]; -}; - -#define BEGIN_CHAR_CONVERSION( _name, _delimiter, _escapeChar ) \ - static CUtlCharConversion::ConversionArray_t s_pConversionArray ## _name[] = { - -#define END_CHAR_CONVERSION( _name, _delimiter, _escapeChar ) \ - }; \ - CUtlCharConversion _name( _escapeChar, _delimiter, sizeof( s_pConversionArray ## _name ) / sizeof( CUtlCharConversion::ConversionArray_t ), s_pConversionArray ## _name ); - -#define BEGIN_CUSTOM_CHAR_CONVERSION( _className, _name, _delimiter, _escapeChar ) \ - static CUtlCharConversion::ConversionArray_t s_pConversionArray ## _name[] = { - -#define END_CUSTOM_CHAR_CONVERSION( _className, _name, _delimiter, _escapeChar ) \ - }; \ - _className _name( _escapeChar, _delimiter, sizeof( s_pConversionArray ## _name ) / sizeof( CUtlCharConversion::ConversionArray_t ), s_pConversionArray ## _name ); - -//----------------------------------------------------------------------------- -// Character conversions for C strings -//----------------------------------------------------------------------------- -CUtlCharConversion *GetCStringCharConversion(); - -//----------------------------------------------------------------------------- -// Character conversions for quoted strings, with no escape sequences -//----------------------------------------------------------------------------- -CUtlCharConversion *GetNoEscCharConversion(); - - -//----------------------------------------------------------------------------- -// Macro to set overflow functions easily -//----------------------------------------------------------------------------- -#define SetUtlBufferOverflowFuncs( _get, _put ) \ - SetOverflowFuncs( static_cast ( _get ), static_cast ( _put ) ) - - -//----------------------------------------------------------------------------- -// Command parsing.. -//----------------------------------------------------------------------------- -class CUtlBuffer -{ -public: - enum SeekType_t - { - SEEK_HEAD = 0, - SEEK_CURRENT, - SEEK_TAIL - }; - - // flags - enum BufferFlags_t - { - TEXT_BUFFER = 0x1, // Describes how get + put work (as strings, or binary) - EXTERNAL_GROWABLE = 0x2, // This is used w/ external buffers and causes the utlbuf to switch to reallocatable memory if an overflow happens when Putting. - CONTAINS_CRLF = 0x4, // For text buffers only, does this contain \n or \n\r? - READ_ONLY = 0x8, // For external buffers; prevents null termination from happening. - AUTO_TABS_DISABLED = 0x10, // Used to disable/enable push/pop tabs - }; - - // Overflow functions when a get or put overflows - typedef bool (CUtlBuffer::*UtlBufferOverflowFunc_t)( int nSize ); - - // Constructors for growable + external buffers for serialization/unserialization - CUtlBuffer( int growSize = 0, int initSize = 0, int nFlags = 0 ); - CUtlBuffer( const void* pBuffer, int size, int nFlags = 0 ); - // This one isn't actually defined so that we catch contructors that are trying to pass a bool in as the third param. - CUtlBuffer( const void *pBuffer, int size, bool crap ); - - unsigned char GetFlags() const; - - // NOTE: This will assert if you attempt to recast it in a way that - // is not compatible. The only valid conversion is binary-> text w/CRLF - void SetBufferType( bool bIsText, bool bContainsCRLF ); - - // Makes sure we've got at least this much memory - void EnsureCapacity( int num ); - - // Attaches the buffer to external memory.... - void SetExternalBuffer( void* pMemory, int nSize, int nInitialPut, int nFlags = 0 ); - bool IsExternallyAllocated() const; - void AssumeMemory( void *pMemory, int nSize, int nInitialPut, int nFlags = 0 ); - - FORCEINLINE void ActivateByteSwappingIfBigEndian( void ) - { - if ( IsX360() ) - ActivateByteSwapping( true ); - } - - - // Controls endian-ness of binary utlbufs - default matches the current platform - void ActivateByteSwapping( bool bActivate ); - void SetBigEndian( bool bigEndian ); - bool IsBigEndian( void ); - - // Resets the buffer; but doesn't free memory - void Clear(); - - // Clears out the buffer; frees memory - void Purge(); - - // Read stuff out. - // Binary mode: it'll just read the bits directly in, and characters will be - // read for strings until a null character is reached. - // Text mode: it'll parse the file, turning text #s into real numbers. - // GetString will read a string until a space is reached - char GetChar( ); - unsigned char GetUnsignedChar( ); - short GetShort( ); - unsigned short GetUnsignedShort( ); - int GetInt( ); - int GetIntHex( ); - unsigned int GetUnsignedInt( ); - float GetFloat( ); - double GetDouble( ); - void GetString( char* pString, int nMaxChars = 0 ); - void Get( void* pMem, int size ); - void GetLine( char* pLine, int nMaxChars = 0 ); - - // Used for getting objects that have a byteswap datadesc defined - template void GetObjects( T *dest, int count = 1 ); - - // This will get at least 1 byte and up to nSize bytes. - // It will return the number of bytes actually read. - int GetUpTo( void *pMem, int nSize ); - - // This version of GetString converts \" to \\ and " to \, etc. - // It also reads a " at the beginning and end of the string - void GetDelimitedString( CUtlCharConversion *pConv, char *pString, int nMaxChars = 0 ); - char GetDelimitedChar( CUtlCharConversion *pConv ); - - // This will return the # of characters of the string about to be read out - // NOTE: The count will *include* the terminating 0!! - // In binary mode, it's the number of characters until the next 0 - // In text mode, it's the number of characters until the next space. - int PeekStringLength(); - - // This version of PeekStringLength converts \" to \\ and " to \, etc. - // It also reads a " at the beginning and end of the string - // NOTE: The count will *include* the terminating 0!! - // In binary mode, it's the number of characters until the next 0 - // In text mode, it's the number of characters between "s (checking for \") - // Specifying false for bActualSize will return the pre-translated number of characters - // including the delimiters and the escape characters. So, \n counts as 2 characters when bActualSize == false - // and only 1 character when bActualSize == true - int PeekDelimitedStringLength( CUtlCharConversion *pConv, bool bActualSize = true ); - - // Just like scanf, but doesn't work in binary mode - int Scanf( const char* pFmt, ... ); - int VaScanf( const char* pFmt, va_list list ); - - // Eats white space, advances Get index - void EatWhiteSpace(); - - // Eats C++ style comments - bool EatCPPComment(); - - // (For text buffers only) - // Parse a token from the buffer: - // Grab all text that lies between a starting delimiter + ending delimiter - // (skipping whitespace that leads + trails both delimiters). - // If successful, the get index is advanced and the function returns true, - // otherwise the index is not advanced and the function returns false. - bool ParseToken( const char *pStartingDelim, const char *pEndingDelim, char* pString, int nMaxLen ); - - // Advance the get index until after the particular string is found - // Do not eat whitespace before starting. Return false if it failed - // String test is case-insensitive. - bool GetToken( const char *pToken ); - - // Parses the next token, given a set of character breaks to stop at - // Returns the length of the token parsed in bytes (-1 if none parsed) - int ParseToken( characterset_t *pBreaks, char *pTokenBuf, int nMaxLen, bool bParseComments = true ); - - // Write stuff in - // Binary mode: it'll just write the bits directly in, and strings will be - // written with a null terminating character - // Text mode: it'll convert the numbers to text versions - // PutString will not write a terminating character - void PutChar( char c ); - void PutUnsignedChar( unsigned char uc ); - void PutShort( short s ); - void PutUnsignedShort( unsigned short us ); - void PutInt( int i ); - void PutUnsignedInt( unsigned int u ); - void PutFloat( float f ); - void PutDouble( double d ); - void PutString( const char* pString ); - void Put( const void* pMem, int size ); - - // Used for putting objects that have a byteswap datadesc defined - template void PutObjects( T *src, int count = 1 ); - - // This version of PutString converts \ to \\ and " to \", etc. - // It also places " at the beginning and end of the string - void PutDelimitedString( CUtlCharConversion *pConv, const char *pString ); - void PutDelimitedChar( CUtlCharConversion *pConv, char c ); - - // Just like printf, writes a terminating zero in binary mode - void Printf( const char* pFmt, ... ); - void VaPrintf( const char* pFmt, va_list list ); - - // What am I writing (put)/reading (get)? - void* PeekPut( int offset = 0 ); - const void* PeekGet( int offset = 0 ) const; - const void* PeekGet( int nMaxSize, int nOffset ); - - // Where am I writing (put)/reading (get)? - int TellPut( ) const; - int TellGet( ) const; - - // What's the most I've ever written? - int TellMaxPut( ) const; - - // How many bytes remain to be read? - // NOTE: This is not accurate for streaming text files; it overshoots - int GetBytesRemaining() const; - - // Change where I'm writing (put)/reading (get) - void SeekPut( SeekType_t type, int offset ); - void SeekGet( SeekType_t type, int offset ); - - // Buffer base - const void* Base() const; - void* Base(); - - // memory allocation size, does *not* reflect size written or read, - // use TellPut or TellGet for that - int Size() const; - - // Am I a text buffer? - bool IsText() const; - - // Can I grow if I'm externally allocated? - bool IsGrowable() const; - - // Am I valid? (overflow or underflow error), Once invalid it stays invalid - bool IsValid() const; - - // Do I contain carriage return/linefeeds? - bool ContainsCRLF() const; - - // Am I read-only - bool IsReadOnly() const; - - // Converts a buffer from a CRLF buffer to a CR buffer (and back) - // Returns false if no conversion was necessary (and outBuf is left untouched) - // If the conversion occurs, outBuf will be cleared. - bool ConvertCRLF( CUtlBuffer &outBuf ); - - // Push/pop pretty-printing tabs - void PushTab(); - void PopTab(); - - // Temporarily disables pretty print - void EnableTabs( bool bEnable ); - -protected: - // error flags - enum - { - PUT_OVERFLOW = 0x1, - GET_OVERFLOW = 0x2, - MAX_ERROR_FLAG = GET_OVERFLOW, - }; - - void SetOverflowFuncs( UtlBufferOverflowFunc_t getFunc, UtlBufferOverflowFunc_t putFunc ); - - bool OnPutOverflow( int nSize ); - bool OnGetOverflow( int nSize ); - -protected: - // Checks if a get/put is ok - bool CheckPut( int size ); - bool CheckGet( int size ); - - void AddNullTermination( ); - - // Methods to help with pretty-printing - bool WasLastCharacterCR(); - void PutTabs(); - - // Help with delimited stuff - char GetDelimitedCharInternal( CUtlCharConversion *pConv ); - void PutDelimitedCharInternal( CUtlCharConversion *pConv, char c ); - - // Default overflow funcs - bool PutOverflow( int nSize ); - bool GetOverflow( int nSize ); - - // Does the next bytes of the buffer match a pattern? - bool PeekStringMatch( int nOffset, const char *pString, int nLen ); - - // Peek size of line to come, check memory bound - int PeekLineLength(); - - // How much whitespace should I skip? - int PeekWhiteSpace( int nOffset ); - - // Checks if a peek get is ok - bool CheckPeekGet( int nOffset, int nSize ); - - // Call this to peek arbitrarily long into memory. It doesn't fail unless - // it can't read *anything* new - bool CheckArbitraryPeekGet( int nOffset, int &nIncrement ); - - template void GetType( T& dest, const char *pszFmt ); - template void GetTypeBin( T& dest ); - template void GetObject( T *src ); - - template void PutType( T src, const char *pszFmt ); - template void PutTypeBin( T src ); - template void PutObject( T *src ); - - CUtlMemory m_Memory; - int m_Get; - int m_Put; - - unsigned char m_Error; - unsigned char m_Flags; - unsigned char m_Reserved; -#if defined( _X360 ) - unsigned char pad; -#endif - - int m_nTab; - int m_nMaxPut; - int m_nOffset; - - UtlBufferOverflowFunc_t m_GetOverflowFunc; - UtlBufferOverflowFunc_t m_PutOverflowFunc; - - CByteswap m_Byteswap; -}; - - -// Stream style output operators for CUtlBuffer -inline CUtlBuffer &operator<<( CUtlBuffer &b, char v ) -{ - b.PutChar( v ); - return b; -} - -inline CUtlBuffer &operator<<( CUtlBuffer &b, unsigned char v ) -{ - b.PutUnsignedChar( v ); - return b; -} - -inline CUtlBuffer &operator<<( CUtlBuffer &b, short v ) -{ - b.PutShort( v ); - return b; -} - -inline CUtlBuffer &operator<<( CUtlBuffer &b, unsigned short v ) -{ - b.PutUnsignedShort( v ); - return b; -} - -inline CUtlBuffer &operator<<( CUtlBuffer &b, int v ) -{ - b.PutInt( v ); - return b; -} - -inline CUtlBuffer &operator<<( CUtlBuffer &b, unsigned int v ) -{ - b.PutUnsignedInt( v ); - return b; -} - -inline CUtlBuffer &operator<<( CUtlBuffer &b, float v ) -{ - b.PutFloat( v ); - return b; -} - -inline CUtlBuffer &operator<<( CUtlBuffer &b, double v ) -{ - b.PutDouble( v ); - return b; -} - -inline CUtlBuffer &operator<<( CUtlBuffer &b, const char *pv ) -{ - b.PutString( pv ); - return b; -} - -inline CUtlBuffer &operator<<( CUtlBuffer &b, const Vector &v ) -{ - b << v.x << " " << v.y << " " << v.z; - return b; -} - -inline CUtlBuffer &operator<<( CUtlBuffer &b, const Vector2D &v ) -{ - b << v.x << " " << v.y; - return b; -} - - -class CUtlInplaceBuffer : public CUtlBuffer -{ -public: - CUtlInplaceBuffer( int growSize = 0, int initSize = 0, int nFlags = 0 ); - - // - // Routines returning buffer-inplace-pointers - // -public: - // - // Upon success, determines the line length, fills out the pointer to the - // beginning of the line and the line length, advances the "get" pointer - // offset by the line length and returns "true". - // - // If end of file is reached or upon error returns "false". - // - // Note: the returned length of the line is at least one character because the - // trailing newline characters are also included as part of the line. - // - // Note: the pointer returned points into the local memory of this buffer, in - // case the buffer gets relocated or destroyed the pointer becomes invalid. - // - // e.g.: ------------- - // - // char *pszLine; - // int nLineLen; - // while ( pUtlInplaceBuffer->InplaceGetLinePtr( &pszLine, &nLineLen ) ) - // { - // ... - // } - // - // ------------- - // - // @param ppszInBufferPtr on return points into this buffer at start of line - // @param pnLineLength on return holds num bytes accessible via (*ppszInBufferPtr) - // - // @returns true if line was successfully read - // false when EOF is reached or error occurs - // - bool InplaceGetLinePtr( /* out */ char **ppszInBufferPtr, /* out */ int *pnLineLength ); - - // - // Determines the line length, advances the "get" pointer offset by the line length, - // replaces the newline character with null-terminator and returns the initial pointer - // to now null-terminated line. - // - // If end of file is reached or upon error returns NULL. - // - // Note: the pointer returned points into the local memory of this buffer, in - // case the buffer gets relocated or destroyed the pointer becomes invalid. - // - // e.g.: ------------- - // - // while ( char *pszLine = pUtlInplaceBuffer->InplaceGetLinePtr() ) - // { - // ... - // } - // - // ------------- - // - // @returns ptr-to-zero-terminated-line if line was successfully read and buffer modified - // NULL when EOF is reached or error occurs - // - char * InplaceGetLinePtr( void ); -}; - - -//----------------------------------------------------------------------------- -// Where am I reading? -//----------------------------------------------------------------------------- -inline int CUtlBuffer::TellGet( ) const -{ - return m_Get; -} - - -//----------------------------------------------------------------------------- -// How many bytes remain to be read? -//----------------------------------------------------------------------------- -inline int CUtlBuffer::GetBytesRemaining() const -{ - return m_nMaxPut - TellGet(); -} - - -//----------------------------------------------------------------------------- -// What am I reading? -//----------------------------------------------------------------------------- -inline const void* CUtlBuffer::PeekGet( int offset ) const -{ - return &m_Memory[ m_Get + offset - m_nOffset ]; -} - - -//----------------------------------------------------------------------------- -// Unserialization -//----------------------------------------------------------------------------- - -template -inline void CUtlBuffer::GetObject( T *dest ) -{ - if ( CheckGet( sizeof(T) ) ) - { - if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) ) - { - *dest = *(T *)PeekGet(); - } - else - { - m_Byteswap.SwapFieldsToTargetEndian( dest, (T*)PeekGet() ); - } - m_Get += sizeof(T); - } - else - { - Q_memset( &dest, 0, sizeof(T) ); - } -} - - -template -inline void CUtlBuffer::GetObjects( T *dest, int count ) -{ - for ( int i = 0; i < count; ++i, ++dest ) - { - GetObject( dest ); - } -} - - -template -inline void CUtlBuffer::GetTypeBin( T &dest ) -{ - if ( CheckGet( sizeof(T) ) ) - { - if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) ) - { - dest = *(T *)PeekGet(); - } - else - { - m_Byteswap.SwapBufferToTargetEndian( &dest, (T*)PeekGet() ); - } - m_Get += sizeof(T); - } - else - { - dest = 0; - } -} - -template <> -inline void CUtlBuffer::GetTypeBin< float >( float &dest ) -{ - if ( CheckGet( sizeof( float ) ) ) - { - unsigned int pData = (unsigned int)PeekGet(); - if ( IsX360() && ( pData & 0x03 ) ) - { - // handle unaligned read - ((unsigned char*)&dest)[0] = ((unsigned char*)pData)[0]; - ((unsigned char*)&dest)[1] = ((unsigned char*)pData)[1]; - ((unsigned char*)&dest)[2] = ((unsigned char*)pData)[2]; - ((unsigned char*)&dest)[3] = ((unsigned char*)pData)[3]; - } - else - { - // aligned read - dest = *(float *)pData; - } - if ( m_Byteswap.IsSwappingBytes() ) - { - m_Byteswap.SwapBufferToTargetEndian< float >( &dest, &dest ); - } - m_Get += sizeof( float ); - } - else - { - dest = 0; - } -} - -template -inline void CUtlBuffer::GetType( T &dest, const char *pszFmt ) -{ - if (!IsText()) - { - GetTypeBin( dest ); - } - else - { - dest = 0; - Scanf( pszFmt, &dest ); - } -} - -inline char CUtlBuffer::GetChar( ) -{ - char c; - GetType( c, "%c" ); - return c; -} - -inline unsigned char CUtlBuffer::GetUnsignedChar( ) -{ - unsigned char c; - GetType( c, "%u" ); - return c; -} - -inline short CUtlBuffer::GetShort( ) -{ - short s; - GetType( s, "%d" ); - return s; -} - -inline unsigned short CUtlBuffer::GetUnsignedShort( ) -{ - unsigned short s; - GetType( s, "%u" ); - return s; -} - -inline int CUtlBuffer::GetInt( ) -{ - int i; - GetType( i, "%d" ); - return i; -} - -inline int CUtlBuffer::GetIntHex( ) -{ - int i; - GetType( i, "%x" ); - return i; -} - -inline unsigned int CUtlBuffer::GetUnsignedInt( ) -{ - unsigned int u; - GetType( u, "%u" ); - return u; -} - -inline float CUtlBuffer::GetFloat( ) -{ - float f; - GetType( f, "%f" ); - return f; -} - -inline double CUtlBuffer::GetDouble( ) -{ - double d; - GetType( d, "%f" ); - return d; -} - - -//----------------------------------------------------------------------------- -// Where am I writing? -//----------------------------------------------------------------------------- -inline unsigned char CUtlBuffer::GetFlags() const -{ - return m_Flags; -} - - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -inline bool CUtlBuffer::IsExternallyAllocated() const -{ - return m_Memory.IsExternallyAllocated(); -} - - -//----------------------------------------------------------------------------- -// Where am I writing? -//----------------------------------------------------------------------------- -inline int CUtlBuffer::TellPut( ) const -{ - return m_Put; -} - - -//----------------------------------------------------------------------------- -// What's the most I've ever written? -//----------------------------------------------------------------------------- -inline int CUtlBuffer::TellMaxPut( ) const -{ - return m_nMaxPut; -} - - -//----------------------------------------------------------------------------- -// What am I reading? -//----------------------------------------------------------------------------- -inline void* CUtlBuffer::PeekPut( int offset ) -{ - return &m_Memory[m_Put + offset - m_nOffset]; -} - - -//----------------------------------------------------------------------------- -// Various put methods -//----------------------------------------------------------------------------- - -template -inline void CUtlBuffer::PutObject( T *src ) -{ - if ( CheckPut( sizeof(T) ) ) - { - if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) ) - { - *(T *)PeekPut() = *src; - } - else - { - m_Byteswap.SwapFieldsToTargetEndian( (T*)PeekPut(), src ); - } - m_Put += sizeof(T); - AddNullTermination(); - } -} - - -template -inline void CUtlBuffer::PutObjects( T *src, int count ) -{ - for ( int i = 0; i < count; ++i, ++src ) - { - PutObject( src ); - } -} - - -template -inline void CUtlBuffer::PutTypeBin( T src ) -{ - if ( CheckPut( sizeof(T) ) ) - { - if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) ) - { - *(T *)PeekPut() = src; - } - else - { - m_Byteswap.SwapBufferToTargetEndian( (T*)PeekPut(), &src ); - } - m_Put += sizeof(T); - AddNullTermination(); - } -} - -template -inline void CUtlBuffer::PutType( T src, const char *pszFmt ) -{ - if (!IsText()) - { - PutTypeBin( src ); - } - else - { - Printf( pszFmt, src ); - } -} - -//----------------------------------------------------------------------------- -// Methods to help with pretty-printing -//----------------------------------------------------------------------------- -inline bool CUtlBuffer::WasLastCharacterCR() -{ - if ( !IsText() || (TellPut() == 0) ) - return false; - return ( *( const char * )PeekPut( -1 ) == '\n' ); -} - -inline void CUtlBuffer::PutTabs() -{ - int nTabCount = ( m_Flags & AUTO_TABS_DISABLED ) ? 0 : m_nTab; - for (int i = nTabCount; --i >= 0; ) - { - PutTypeBin( '\t' ); - } -} - - -//----------------------------------------------------------------------------- -// Push/pop pretty-printing tabs -//----------------------------------------------------------------------------- -inline void CUtlBuffer::PushTab( ) -{ - ++m_nTab; -} - -inline void CUtlBuffer::PopTab() -{ - if ( --m_nTab < 0 ) - { - m_nTab = 0; - } -} - - -//----------------------------------------------------------------------------- -// Temporarily disables pretty print -//----------------------------------------------------------------------------- -inline void CUtlBuffer::EnableTabs( bool bEnable ) -{ - if ( bEnable ) - { - m_Flags &= ~AUTO_TABS_DISABLED; - } - else - { - m_Flags |= AUTO_TABS_DISABLED; - } -} - -inline void CUtlBuffer::PutChar( char c ) -{ - if ( WasLastCharacterCR() ) - { - PutTabs(); - } - - PutTypeBin( c ); -} - -inline void CUtlBuffer::PutUnsignedChar( unsigned char c ) -{ - PutType( c, "%u" ); -} - -inline void CUtlBuffer::PutShort( short s ) -{ - PutType( s, "%d" ); -} - -inline void CUtlBuffer::PutUnsignedShort( unsigned short s ) -{ - PutType( s, "%u" ); -} - -inline void CUtlBuffer::PutInt( int i ) -{ - PutType( i, "%d" ); -} - -inline void CUtlBuffer::PutUnsignedInt( unsigned int u ) -{ - PutType( u, "%u" ); -} - -inline void CUtlBuffer::PutFloat( float f ) -{ - PutType( f, "%f" ); -} - -inline void CUtlBuffer::PutDouble( double d ) -{ - PutType( d, "%f" ); -} - - -//----------------------------------------------------------------------------- -// Am I a text buffer? -//----------------------------------------------------------------------------- -inline bool CUtlBuffer::IsText() const -{ - return (m_Flags & TEXT_BUFFER) != 0; -} - - -//----------------------------------------------------------------------------- -// Can I grow if I'm externally allocated? -//----------------------------------------------------------------------------- -inline bool CUtlBuffer::IsGrowable() const -{ - return (m_Flags & EXTERNAL_GROWABLE) != 0; -} - - -//----------------------------------------------------------------------------- -// Am I valid? (overflow or underflow error), Once invalid it stays invalid -//----------------------------------------------------------------------------- -inline bool CUtlBuffer::IsValid() const -{ - return m_Error == 0; -} - - -//----------------------------------------------------------------------------- -// Do I contain carriage return/linefeeds? -//----------------------------------------------------------------------------- -inline bool CUtlBuffer::ContainsCRLF() const -{ - return IsText() && ((m_Flags & CONTAINS_CRLF) != 0); -} - - -//----------------------------------------------------------------------------- -// Am I read-only -//----------------------------------------------------------------------------- -inline bool CUtlBuffer::IsReadOnly() const -{ - return (m_Flags & READ_ONLY) != 0; -} - - -//----------------------------------------------------------------------------- -// Buffer base and size -//----------------------------------------------------------------------------- -inline const void* CUtlBuffer::Base() const -{ - return m_Memory.Base(); -} - -inline void* CUtlBuffer::Base() -{ - return m_Memory.Base(); -} - -inline int CUtlBuffer::Size() const -{ - return m_Memory.NumAllocated(); -} - - -//----------------------------------------------------------------------------- -// Clears out the buffer; frees memory -//----------------------------------------------------------------------------- -inline void CUtlBuffer::Clear() -{ - m_Get = 0; - m_Put = 0; - m_Error = 0; - m_nOffset = 0; - m_nMaxPut = -1; - AddNullTermination(); -} - -inline void CUtlBuffer::Purge() -{ - m_Get = 0; - m_Put = 0; - m_nOffset = 0; - m_nMaxPut = 0; - m_Error = 0; - m_Memory.Purge(); -} - - -#endif // UTLBUFFER_H - diff --git a/public/tier1/utlbufferutil.h b/public/tier1/utlbufferutil.h deleted file mode 100644 index 629f0dd5e..000000000 --- a/public/tier1/utlbufferutil.h +++ /dev/null @@ -1,192 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======// -// -// Purpose: -// -// $NoKeywords: $ -// -// Utilities for serialization/unserialization buffer -//=============================================================================// - -#ifndef UTLBUFFERUTIL_H -#define UTLBUFFERUTIL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/utlvector.h" -#include "tier1/utlbuffer.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class Vector2D; -class Vector; -class Vector4D; -class QAngle; -class Quaternion; -class VMatrix; -class Color; -class CUtlBinaryBlock; -class CUtlString; -class CUtlCharConversion; - - -//----------------------------------------------------------------------------- -// For string serialization, set the delimiter rules -//----------------------------------------------------------------------------- -void SetSerializationDelimiter( CUtlCharConversion *pConv ); -void SetSerializationArrayDelimiter( const char *pDelimiter ); - - -//----------------------------------------------------------------------------- -// Standard serialization methods for basic types -//----------------------------------------------------------------------------- -bool Serialize( CUtlBuffer &buf, const bool &src ); -bool Unserialize( CUtlBuffer &buf, bool &dest ); - -bool Serialize( CUtlBuffer &buf, const int &src ); -bool Unserialize( CUtlBuffer &buf, int &dest ); - -bool Serialize( CUtlBuffer &buf, const float &src ); -bool Unserialize( CUtlBuffer &buf, float &dest ); - -bool Serialize( CUtlBuffer &buf, const Vector2D &src ); -bool Unserialize( CUtlBuffer &buf, Vector2D &dest ); - -bool Serialize( CUtlBuffer &buf, const Vector &src ); -bool Unserialize( CUtlBuffer &buf, Vector &dest ); - -bool Serialize( CUtlBuffer &buf, const Vector4D &src ); -bool Unserialize( CUtlBuffer &buf, Vector4D &dest ); - -bool Serialize( CUtlBuffer &buf, const QAngle &src ); -bool Unserialize( CUtlBuffer &buf, QAngle &dest ); - -bool Serialize( CUtlBuffer &buf, const Quaternion &src ); -bool Unserialize( CUtlBuffer &buf, Quaternion &dest ); - -bool Serialize( CUtlBuffer &buf, const VMatrix &src ); -bool Unserialize( CUtlBuffer &buf, VMatrix &dest ); - -bool Serialize( CUtlBuffer &buf, const Color &src ); -bool Unserialize( CUtlBuffer &buf, Color &dest ); - -bool Serialize( CUtlBuffer &buf, const CUtlBinaryBlock &src ); -bool Unserialize( CUtlBuffer &buf, CUtlBinaryBlock &dest ); - -bool Serialize( CUtlBuffer &buf, const CUtlString &src ); -bool Unserialize( CUtlBuffer &buf, CUtlString &dest ); - - -//----------------------------------------------------------------------------- -// You can use this to check if a type serializes on multiple lines -//----------------------------------------------------------------------------- -template< class T > -inline bool SerializesOnMultipleLines() -{ - return false; -} - -template< > -inline bool SerializesOnMultipleLines() -{ - return true; -} - -template< > -inline bool SerializesOnMultipleLines() -{ - return true; -} - - -//----------------------------------------------------------------------------- -// Vector serialization -//----------------------------------------------------------------------------- -template< class T > -bool Serialize( CUtlBuffer &buf, const CUtlVector &src ) -{ - extern const char *s_pUtlBufferUtilArrayDelim; - - int nCount = src.Count(); - - if ( !buf.IsText() ) - { - buf.PutInt( nCount ); - for ( int i = 0; i < nCount; ++i ) - { - ::Serialize( buf, src[i] ); - } - return buf.IsValid(); - } - - if ( !SerializesOnMultipleLines() ) - { - buf.PutChar('\n'); - for ( int i = 0; i < nCount; ++i ) - { - ::Serialize( buf, src[i] ); - if ( s_pUtlBufferUtilArrayDelim && (i != nCount-1) ) - { - buf.PutString( s_pUtlBufferUtilArrayDelim ); - } - buf.PutChar('\n'); - } - } - else - { - for ( int i = 0; i < nCount; ++i ) - { - ::Serialize( buf, src[i] ); - if ( s_pUtlBufferUtilArrayDelim && (i != nCount-1) ) - { - buf.PutString( s_pUtlBufferUtilArrayDelim ); - } - buf.PutChar(' '); - } - } - - return buf.IsValid(); -} - -template< class T > -bool Unserialize( CUtlBuffer &buf, CUtlVector &dest ) -{ - dest.RemoveAll(); - - MEM_ALLOC_CREDIT_FUNCTION(); - - if ( !buf.IsText() ) - { - int nCount = buf.GetInt(); - if ( nCount ) - { - dest.EnsureCapacity( nCount ); - for ( int i = 0; i < nCount; ++i ) - { - VerifyEquals( dest.AddToTail(), i ); - if ( !::Unserialize( buf, dest[i] ) ) - return false; - } - } - return buf.IsValid(); - } - - while ( true ) - { - buf.EatWhiteSpace(); - if ( !buf.IsValid() ) - break; - - int i = dest.AddToTail( ); - if ( ! ::Unserialize( buf, dest[i] ) ) - return false; - } - return true; -} - - -#endif // UTLBUFFERUTIL_H - diff --git a/public/tier1/utldict.h b/public/tier1/utldict.h deleted file mode 100644 index aeb083ddb..000000000 --- a/public/tier1/utldict.h +++ /dev/null @@ -1,320 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======// -// -// Purpose: A dictionary mapping from symbol to structure -// -// $Header: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef UTLDICT_H -#define UTLDICT_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/dbg.h" -#include "tier1/utlmap.h" - -// Include this because tons of code was implicitly getting utlsymbol or utlvector via utldict.h -#include "tier1/utlsymbol.h" - -#include "tier0/memdbgon.h" - -enum EDictCompareType -{ - k_eDictCompareTypeCaseSensitive=0, - k_eDictCompareTypeCaseInsensitive=1, - k_eDictCompareTypeFilenames // Slashes and backslashes count as the same character.. -}; - -//----------------------------------------------------------------------------- -// A dictionary mapping from symbol to structure -//----------------------------------------------------------------------------- -template -class CUtlDict -{ -public: - // constructor, destructor - // Left at growSize = 0, the memory will first allocate 1 element and double in size - // at each increment. - CUtlDict( int compareType = k_eDictCompareTypeCaseInsensitive, int growSize = 0, int initSize = 0 ); - ~CUtlDict( ); - - void EnsureCapacity( int ); - - // gets particular elements - T& Element( I i ); - const T& Element( I i ) const; - T& operator[]( I i ); - const T& operator[]( I i ) const; - - // gets element names - char *GetElementName( I i ); - char const *GetElementName( I i ) const; - - void SetElementName( I i, char const *pName ); - - // Number of elements - unsigned int Count() const; - - // Checks if a node is valid and in the tree - bool IsValidIndex( I i ) const; - - // Invalid index - static I InvalidIndex(); - - // Insert method (inserts in order) - I Insert( const char *pName, const T &element ); - I Insert( const char *pName ); - - // Find method - I Find( const char *pName ) const; - - // Remove methods - void RemoveAt( I i ); - void Remove( const char *pName ); - void RemoveAll( ); - - // Purge memory - void Purge(); - void PurgeAndDeleteElements(); // Call delete on each element. - - // Iteration methods - I First() const; - I Next( I i ) const; - -protected: - typedef CUtlMap DictElementMap_t; - DictElementMap_t m_Elements; -}; - - -//----------------------------------------------------------------------------- -// constructor, destructor -//----------------------------------------------------------------------------- -template -CUtlDict::CUtlDict( int compareType, int growSize, int initSize ) : m_Elements( growSize, initSize ) -{ - if ( compareType == k_eDictCompareTypeFilenames ) - { - m_Elements.SetLessFunc( CaselessStringLessThanIgnoreSlashes ); - } - else if ( compareType == k_eDictCompareTypeCaseInsensitive ) - { - m_Elements.SetLessFunc( CaselessStringLessThan ); - } - else - { - m_Elements.SetLessFunc( StringLessThan ); - } -} - -template -CUtlDict::~CUtlDict() -{ - Purge(); -} - -template -inline void CUtlDict::EnsureCapacity( int num ) -{ - return m_Elements.EnsureCapacity( num ); -} - -//----------------------------------------------------------------------------- -// gets particular elements -//----------------------------------------------------------------------------- -template -inline T& CUtlDict::Element( I i ) -{ - return m_Elements[i]; -} - -template -inline const T& CUtlDict::Element( I i ) const -{ - return m_Elements[i]; -} - -//----------------------------------------------------------------------------- -// gets element names -//----------------------------------------------------------------------------- -template -inline char *CUtlDict::GetElementName( I i ) -{ - return (char *)m_Elements.Key( i ); -} - -template -inline char const *CUtlDict::GetElementName( I i ) const -{ - return m_Elements.Key( i ); -} - -template -inline T& CUtlDict::operator[]( I i ) -{ - return Element(i); -} - -template -inline const T & CUtlDict::operator[]( I i ) const -{ - return Element(i); -} - -template -inline void CUtlDict::SetElementName( I i, char const *pName ) -{ - MEM_ALLOC_CREDIT_CLASS(); - // TODO: This makes a copy of the old element - // TODO: This relies on the rb tree putting the most recently - // removed element at the head of the insert list - free( (void *)m_Elements.Key( i ) ); - m_Elements.Reinsert( strdup( pName ), i ); -} - -//----------------------------------------------------------------------------- -// Num elements -//----------------------------------------------------------------------------- -template -inline unsigned int CUtlDict::Count() const -{ - return m_Elements.Count(); -} - - -//----------------------------------------------------------------------------- -// Checks if a node is valid and in the tree -//----------------------------------------------------------------------------- -template -inline bool CUtlDict::IsValidIndex( I i ) const -{ - return m_Elements.IsValidIndex(i); -} - - -//----------------------------------------------------------------------------- -// Invalid index -//----------------------------------------------------------------------------- -template -inline I CUtlDict::InvalidIndex() -{ - return DictElementMap_t::InvalidIndex(); -} - - -//----------------------------------------------------------------------------- -// Delete a node from the tree -//----------------------------------------------------------------------------- -template -void CUtlDict::RemoveAt(I elem) -{ - free( (void *)m_Elements.Key( elem ) ); - m_Elements.RemoveAt(elem); -} - - -//----------------------------------------------------------------------------- -// remove a node in the tree -//----------------------------------------------------------------------------- -template void CUtlDict::Remove( const char *search ) -{ - I node = Find( search ); - if (node != InvalidIndex()) - { - RemoveAt(node); - } -} - - -//----------------------------------------------------------------------------- -// Removes all nodes from the tree -//----------------------------------------------------------------------------- -template -void CUtlDict::RemoveAll() -{ - typename DictElementMap_t::IndexType_t index = m_Elements.FirstInorder(); - while ( index != m_Elements.InvalidIndex() ) - { - free( (void *)m_Elements.Key( index ) ); - index = m_Elements.NextInorder( index ); - } - - m_Elements.RemoveAll(); -} - -template -void CUtlDict::Purge() -{ - RemoveAll(); -} - - -template -void CUtlDict::PurgeAndDeleteElements() -{ - // Delete all the elements. - I index = m_Elements.FirstInorder(); - while ( index != m_Elements.InvalidIndex() ) - { - free( (void *)m_Elements.Key( index ) ); - delete m_Elements[index]; - index = m_Elements.NextInorder( index ); - } - - m_Elements.RemoveAll(); -} - - -//----------------------------------------------------------------------------- -// inserts a node into the tree -//----------------------------------------------------------------------------- -template -I CUtlDict::Insert( const char *pName, const T &element ) -{ - MEM_ALLOC_CREDIT_CLASS(); - return m_Elements.Insert( strdup( pName ), element ); -} - -template -I CUtlDict::Insert( const char *pName ) -{ - MEM_ALLOC_CREDIT_CLASS(); - return m_Elements.Insert( strdup( pName ) ); -} - - -//----------------------------------------------------------------------------- -// finds a node in the tree -//----------------------------------------------------------------------------- -template -I CUtlDict::Find( const char *pName ) const -{ - MEM_ALLOC_CREDIT_CLASS(); - if ( pName ) - return m_Elements.Find( pName ); - else - return InvalidIndex(); -} - - -//----------------------------------------------------------------------------- -// Iteration methods -//----------------------------------------------------------------------------- -template -I CUtlDict::First() const -{ - return m_Elements.FirstInorder(); -} - -template -I CUtlDict::Next( I i ) const -{ - return m_Elements.NextInorder(i); -} - -#include "tier0/memdbgoff.h" - -#endif // UTLDICT_H diff --git a/public/tier1/utlenvelope.h b/public/tier1/utlenvelope.h deleted file mode 100644 index 22de522fe..000000000 --- a/public/tier1/utlenvelope.h +++ /dev/null @@ -1,241 +0,0 @@ -//========== Copyright 2005, Valve Corporation, All rights reserved. ======== -// -// Purpose: A class to wrap data for transport over a boundary like a thread -// or window. -// -//============================================================================= - -#include "tier1/utlstring.h" -#include "tier0/basetypes.h" - -#ifndef UTLENVELOPE_H -#define UTLENVELOPE_H - -#if defined( _WIN32 ) -#pragma once -#endif - -//----------------------------------------------------------------------------- - -class CUtlDataEnvelope -{ -public: - CUtlDataEnvelope( const void *pData, int nBytes ); - CUtlDataEnvelope( const CUtlDataEnvelope &from ); - ~CUtlDataEnvelope(); - - CUtlDataEnvelope &operator=( const CUtlDataEnvelope &from ); - - operator void *(); - operator void *() const; - -private: - void Assign( const void *pData, int nBytes ); - void Assign( const CUtlDataEnvelope &from ); - void Purge(); - - // TODO: switch to a reference counted array? - union - { - byte *m_pData; - byte m_data[4]; - }; - int m_nBytes; -}; - - -//----------------------------------------------------------------------------- - -template -class CUtlEnvelope : protected CUtlDataEnvelope -{ -public: - CUtlEnvelope( const T *pData, int nElems = 1 ); - CUtlEnvelope( const CUtlEnvelope &from ); - - CUtlEnvelope &operator=( const CUtlEnvelope &from ); - - operator T *(); - operator T *() const; - - operator void *(); - operator void *() const; -}; - -//----------------------------------------------------------------------------- - -template <> -class CUtlEnvelope -{ -public: - CUtlEnvelope( const char *pData ) - { - m_string = pData; - } - - CUtlEnvelope( const CUtlEnvelope &from ) - { - m_string = from.m_string; - } - - CUtlEnvelope &operator=( const CUtlEnvelope &from ) - { - m_string = from.m_string; - return *this; - } - - operator char *() - { - return (char *) m_string.Get(); - } - - operator char *() const - { - return (char *) m_string.Get(); - } - - operator void *() - { - return (void *) m_string.Get(); - } - - operator void *() const - { - return (void *) m_string.Get(); - } - -private: - CUtlString m_string; -}; - -//----------------------------------------------------------------------------- - -#include "tier0/memdbgon.h" - -inline void CUtlDataEnvelope::Assign( const void *pData, int nBytes ) -{ - if ( pData ) - { - m_nBytes = nBytes; - if ( m_nBytes > 4 ) - { - m_pData = new byte[nBytes]; - memcpy( m_pData, pData, nBytes ); - } - else - { - memcpy( m_data, pData, nBytes ); - } - } - else - { - m_pData = NULL; - m_nBytes = 0; - } -} - -inline void CUtlDataEnvelope::Assign( const CUtlDataEnvelope &from ) -{ - Assign( from.operator void *(), from.m_nBytes ); -} - -inline void CUtlDataEnvelope::Purge() -{ - if (m_nBytes > 4) - delete [] m_pData; - m_nBytes = 0; -} - -inline CUtlDataEnvelope::CUtlDataEnvelope( const void *pData, int nBytes ) -{ - Assign( pData, nBytes ); -} - -inline CUtlDataEnvelope::CUtlDataEnvelope( const CUtlDataEnvelope &from ) -{ - Assign( from ); -} - -inline CUtlDataEnvelope::~CUtlDataEnvelope() -{ - Purge(); -} - -inline CUtlDataEnvelope &CUtlDataEnvelope::operator=( const CUtlDataEnvelope &from ) -{ - Purge(); - Assign( from ); - return *this; -} - -inline CUtlDataEnvelope::operator void *() -{ - if ( !m_nBytes ) - { - return NULL; - } - - return ( m_nBytes > 4) ? m_pData : m_data; -} - -inline CUtlDataEnvelope::operator void *() const -{ - if ( !m_nBytes ) - { - return NULL; - } - - return ( m_nBytes > 4) ? (void *)m_pData : (void *)m_data; -} - -//----------------------------------------------------------------------------- - -template -inline CUtlEnvelope::CUtlEnvelope( const T *pData, int nElems ) - : CUtlDataEnvelope( pData, sizeof(T) * nElems ) -{ -} - -template -inline CUtlEnvelope::CUtlEnvelope( const CUtlEnvelope &from ) - : CUtlDataEnvelope( from ) -{ - -} - -template -inline CUtlEnvelope &CUtlEnvelope::operator=( const CUtlEnvelope &from ) -{ - CUtlDataEnvelope::operator=( from ); - return *this; -} - -template -inline CUtlEnvelope::operator T *() -{ - return (T *)CUtlDataEnvelope::operator void *(); -} - -template -inline CUtlEnvelope::operator T *() const -{ - return (T *)( (const_cast *>(this))->operator T *() ); -} - -template -inline CUtlEnvelope::operator void *() -{ - return CUtlDataEnvelope::operator void *(); -} - -template -inline CUtlEnvelope::operator void *() const -{ - return ( (const_cast *>(this))->operator void *() ); -} - -//----------------------------------------------------------------------------- - -#include "tier0/memdbgoff.h" - -#endif // UTLENVELOPE_H diff --git a/public/tier1/utlfixedmemory.h b/public/tier1/utlfixedmemory.h deleted file mode 100644 index 86fbb0b75..000000000 --- a/public/tier1/utlfixedmemory.h +++ /dev/null @@ -1,358 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -// A growable memory class. -//===========================================================================// - -#ifndef UTLFIXEDMEMORY_H -#define UTLFIXEDMEMORY_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/dbg.h" -#include "tier0/platform.h" - -#include "tier0/memalloc.h" -#include "tier0/memdbgon.h" - -#ifdef _MSC_VER -#pragma warning (disable:4100) -#pragma warning (disable:4514) -#endif - -//----------------------------------------------------------------------------- - -#ifdef UTLMEMORY_TRACK -#define UTLMEMORY_TRACK_ALLOC() MemAlloc_RegisterAllocation( "Sum of all UtlFixedMemory", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 ) -#define UTLMEMORY_TRACK_FREE() if ( !m_pMemory ) ; else MemAlloc_RegisterDeallocation( "Sum of all UtlFixedMemory", 0, NumAllocated() * sizeof(T), NumAllocated() * sizeof(T), 0 ) -#else -#define UTLMEMORY_TRACK_ALLOC() ((void)0) -#define UTLMEMORY_TRACK_FREE() ((void)0) -#endif - - -//----------------------------------------------------------------------------- -// The CUtlFixedMemory class: -// A growable memory class that allocates non-sequential blocks, but is indexed sequentially -//----------------------------------------------------------------------------- -template< class T > -class CUtlFixedMemory -{ -public: - // constructor, destructor - CUtlFixedMemory( int nGrowSize = 0, int nInitSize = 0 ); - ~CUtlFixedMemory(); - - // Set the size by which the memory grows - void Init( int nGrowSize = 0, int nInitSize = 0 ); - - // here to match CUtlMemory, but only used by ResetDbgInfo, so it can just return NULL - T* Base() { return NULL; } - const T* Base() const { return NULL; } - -protected: - struct BlockHeader_t; - -public: - class Iterator_t - { - public: - Iterator_t( BlockHeader_t *p, int i ) : m_pBlockHeader( p ), m_nIndex( i ) {} - BlockHeader_t *m_pBlockHeader; - int m_nIndex; - - bool operator==( const Iterator_t it ) const { return m_pBlockHeader == it.m_pBlockHeader && m_nIndex == it.m_nIndex; } - bool operator!=( const Iterator_t it ) const { return m_pBlockHeader != it.m_pBlockHeader || m_nIndex != it.m_nIndex; } - }; - Iterator_t First() const { return m_pBlocks ? Iterator_t( m_pBlocks, 0 ) : InvalidIterator(); } - Iterator_t Next( const Iterator_t &it ) const - { - Assert( IsValidIterator( it ) ); - if ( !IsValidIterator( it ) ) - return InvalidIterator(); - - BlockHeader_t * RESTRICT pHeader = it.m_pBlockHeader; - if ( it.m_nIndex + 1 < pHeader->m_nBlockSize ) - return Iterator_t( pHeader, it.m_nIndex + 1 ); - - return pHeader->m_pNext ? Iterator_t( pHeader->m_pNext, 0 ) : InvalidIterator(); - } - int GetIndex( const Iterator_t &it ) const - { - Assert( IsValidIterator( it ) ); - if ( !IsValidIterator( it ) ) - return InvalidIndex(); - - return ( int )( HeaderToBlock( it.m_pBlockHeader ) + it.m_nIndex ); - } - bool IsIdxAfter( int i, const Iterator_t &it ) const - { - Assert( IsValidIterator( it ) ); - if ( !IsValidIterator( it ) ) - return false; - - if ( IsInBlock( i, it.m_pBlockHeader ) ) - return i > GetIndex( it ); - - for ( BlockHeader_t * RESTRICT pbh = it.m_pBlockHeader->m_pNext; pbh; pbh = pbh->m_pNext ) - { - if ( IsInBlock( i, pbh ) ) - return true; - } - return false; - } - bool IsValidIterator( const Iterator_t &it ) const { return it.m_pBlockHeader && it.m_nIndex >= 0 && it.m_nIndex < it.m_pBlockHeader->m_nBlockSize; } - Iterator_t InvalidIterator() const { return Iterator_t( NULL, -1 ); } - - // element access - T& operator[]( int i ); - const T& operator[]( int i ) const; - T& Element( int i ); - const T& Element( int i ) const; - - // Can we use this index? - bool IsIdxValid( int i ) const; - static int InvalidIndex() { return 0; } - - // Size - int NumAllocated() const; - int Count() const { return NumAllocated(); } - - // Grows memory by MAX(num,growsize), and returns the allocation index/ptr - void Grow( int num = 1 ); - - // Makes sure we've got at least this much memory - void EnsureCapacity( int num ); - - // Memory deallocation - void Purge(); - -protected: - // Fast swap - WARNING: Swap invalidates all ptr-based indices!!! - void Swap( CUtlFixedMemory< T > &mem ); - - bool IsInBlock( int i, BlockHeader_t *pBlockHeader ) const - { - T *p = ( T* )i; - const T *p0 = HeaderToBlock( pBlockHeader ); - return p >= p0 && p < p0 + pBlockHeader->m_nBlockSize; - } - - struct BlockHeader_t - { - BlockHeader_t *m_pNext; - int m_nBlockSize; - }; - - const T *HeaderToBlock( const BlockHeader_t *pHeader ) const { return ( T* )( pHeader + 1 ); } - const BlockHeader_t *BlockToHeader( const T *pBlock ) const { return ( BlockHeader_t* )( pBlock ) - 1; } - - BlockHeader_t* m_pBlocks; - int m_nAllocationCount; - int m_nGrowSize; -}; - -//----------------------------------------------------------------------------- -// constructor, destructor -//----------------------------------------------------------------------------- - -template< class T > -CUtlFixedMemory::CUtlFixedMemory( int nGrowSize, int nInitAllocationCount ) -: m_pBlocks( 0 ), m_nAllocationCount( 0 ), m_nGrowSize( 0 ) -{ - Init( nGrowSize, nInitAllocationCount ); -} - -template< class T > -CUtlFixedMemory::~CUtlFixedMemory() -{ - Purge(); -} - - -//----------------------------------------------------------------------------- -// Fast swap - WARNING: Swap invalidates all ptr-based indices!!! -//----------------------------------------------------------------------------- -template< class T > -void CUtlFixedMemory::Swap( CUtlFixedMemory< T > &mem ) -{ - swap( m_pBlocks, mem.m_pBlocks ); - swap( m_nAllocationCount, mem.m_nAllocationCount ); - swap( m_nGrowSize, mem.m_nGrowSize ); -} - - -//----------------------------------------------------------------------------- -// Set the size by which the memory grows - round up to the next power of 2 -//----------------------------------------------------------------------------- -template< class T > -void CUtlFixedMemory::Init( int nGrowSize /* = 0 */, int nInitSize /* = 0 */ ) -{ - Purge(); - - if ( nGrowSize == 0) - { - // Compute an allocation which is at least as big as a cache line... - nGrowSize = ( 31 + sizeof( T ) ) / sizeof( T ); - } - m_nGrowSize = nGrowSize; - - Grow( nInitSize ); -} - -//----------------------------------------------------------------------------- -// element access -//----------------------------------------------------------------------------- -template< class T > -inline T& CUtlFixedMemory::operator[]( int i ) -{ - Assert( IsIdxValid(i) ); - return *( T* )i; -} - -template< class T > -inline const T& CUtlFixedMemory::operator[]( int i ) const -{ - Assert( IsIdxValid(i) ); - return *( T* )i; -} - -template< class T > -inline T& CUtlFixedMemory::Element( int i ) -{ - Assert( IsIdxValid(i) ); - return *( T* )i; -} - -template< class T > -inline const T& CUtlFixedMemory::Element( int i ) const -{ - Assert( IsIdxValid(i) ); - return *( T* )i; -} - - -//----------------------------------------------------------------------------- -// Size -//----------------------------------------------------------------------------- -template< class T > -inline int CUtlFixedMemory::NumAllocated() const -{ - return m_nAllocationCount; -} - - -//----------------------------------------------------------------------------- -// Is element index valid? -//----------------------------------------------------------------------------- -template< class T > -inline bool CUtlFixedMemory::IsIdxValid( int i ) const -{ -#ifdef _DEBUG - for ( BlockHeader_t *pbh = m_pBlocks; pbh; pbh = pbh->m_pNext ) - { - if ( IsInBlock( i, pbh ) ) - return true; - } - return false; -#else - return i != InvalidIndex(); -#endif -} - -template< class T > -void CUtlFixedMemory::Grow( int num ) -{ - if ( num <= 0 ) - return; - - int nBlockSize = m_nGrowSize; - if ( nBlockSize == 0 ) - { - if ( m_nAllocationCount ) - { - nBlockSize = m_nAllocationCount; - } - else - { - // Compute an allocation which is at least as big as a cache line... - nBlockSize = ( 31 + sizeof( T ) ) / sizeof( T ); - Assert( nBlockSize ); - } - } - if ( nBlockSize < num ) - { - int n = ( num + nBlockSize -1 ) / nBlockSize; - Assert( n * nBlockSize >= num ); - Assert( ( n - 1 ) * nBlockSize < num ); - nBlockSize *= n; - } - m_nAllocationCount += nBlockSize; - - MEM_ALLOC_CREDIT_CLASS(); - BlockHeader_t * RESTRICT pBlockHeader = ( BlockHeader_t* )malloc( sizeof( BlockHeader_t ) + nBlockSize * sizeof( T ) ); - if ( !pBlockHeader ) - { - Error( "CUtlFixedMemory overflow!\n" ); - } - pBlockHeader->m_pNext = NULL; - pBlockHeader->m_nBlockSize = nBlockSize; - - if ( !m_pBlocks ) - { - m_pBlocks = pBlockHeader; - } - else - { -#if 1 // IsIdxAfter assumes that newly allocated blocks are at the end - BlockHeader_t * RESTRICT pbh = m_pBlocks; - while ( pbh->m_pNext ) - { - pbh = pbh->m_pNext; - } - pbh->m_pNext = pBlockHeader; -#else - pBlockHeader = m_pBlocks; - pBlockHeader->m_pNext = m_pBlocks; -#endif - } -} - - -//----------------------------------------------------------------------------- -// Makes sure we've got at least this much memory -//----------------------------------------------------------------------------- -template< class T > -inline void CUtlFixedMemory::EnsureCapacity( int num ) -{ - Grow( num - NumAllocated() ); -} - - -//----------------------------------------------------------------------------- -// Memory deallocation -//----------------------------------------------------------------------------- -template< class T > -void CUtlFixedMemory::Purge() -{ - if ( !m_pBlocks ) - return; - - for ( BlockHeader_t *pbh = m_pBlocks; pbh; ) - { - BlockHeader_t *pFree = pbh; - pbh = pbh->m_pNext; - free( pFree ); - } - m_pBlocks = NULL; - m_nAllocationCount = 0; -} - -#include "tier0/memdbgoff.h" - -#endif // UTLFIXEDMEMORY_H diff --git a/public/tier1/utlflags.h b/public/tier1/utlflags.h deleted file mode 100644 index 893a5c788..000000000 --- a/public/tier1/utlflags.h +++ /dev/null @@ -1,124 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: Simple class to make it easier to deal with flags -// -//============================================================================= - -#ifndef UTLFLAGS_H -#define UTLFLAGS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/dbg.h" - - -//----------------------------------------------------------------------------- -// Simple class to make it easier to deal with flags -//----------------------------------------------------------------------------- -template< class T > -class CUtlFlags -{ -public: - CUtlFlags( int nInitialFlags = 0 ); - - // Flag setting - void SetFlag( int nFlagMask ); - void SetFlag( int nFlagMask, bool bEnable ); - - // Flag clearing - void ClearFlag( int nFlagMask ); - void ClearAllFlags(); - bool IsFlagSet( int nFlagMask ) const; - - // Is any flag set? - bool IsAnyFlagSet() const; - -private: - T m_nFlags; -}; - - -//----------------------------------------------------------------------------- -// Constructor -//----------------------------------------------------------------------------- -template< class T > -CUtlFlags::CUtlFlags( int nInitialFlags ) -{ - // Makes sure we didn't truncate - Assert( nInitialFlags == (T)nInitialFlags ); - - m_nFlags = (T)nInitialFlags; -} - - -//----------------------------------------------------------------------------- -// Set flags -//----------------------------------------------------------------------------- -template< class T > -void CUtlFlags::SetFlag( int nFlagMask ) -{ - // Makes sure we didn't truncate - Assert( nFlagMask == (T)nFlagMask ); - - m_nFlags |= (T)nFlagMask; -} - -template< class T > -void CUtlFlags::SetFlag( int nFlagMask, bool bEnable ) -{ - // Makes sure we didn't truncate - Assert( nFlagMask == (T)nFlagMask ); - - if ( bEnable ) - { - m_nFlags |= (T)nFlagMask; - } - else - { - m_nFlags &= ~((T)nFlagMask); - } -} - - -//----------------------------------------------------------------------------- -// Clear flags -//----------------------------------------------------------------------------- -template< class T > -void CUtlFlags::ClearFlag( int nFlagMask ) -{ - // Makes sure we didn't truncate - Assert( nFlagMask == (T)nFlagMask ); - m_nFlags &= ~((T)nFlagMask); -} - -template< class T > -void CUtlFlags::ClearAllFlags() -{ - m_nFlags = 0; -} - - -//----------------------------------------------------------------------------- -// Is a flag set? -//----------------------------------------------------------------------------- -template< class T > -bool CUtlFlags::IsFlagSet( int nFlagMask ) const -{ - // Makes sure we didn't truncate - Assert( nFlagMask == (T)nFlagMask ); - return ( m_nFlags & nFlagMask ) != 0; -} - - -//----------------------------------------------------------------------------- -// Is any flag set? -//----------------------------------------------------------------------------- -template< class T > -bool CUtlFlags::IsAnyFlagSet() const -{ - return m_nFlags != 0; -} - - -#endif // UTLFLAGS_H diff --git a/public/tier1/utlhandletable.h b/public/tier1/utlhandletable.h deleted file mode 100644 index 27764dd2f..000000000 --- a/public/tier1/utlhandletable.h +++ /dev/null @@ -1,586 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef UTLHANDLETABLE_H -#define UTLHANDLETABLE_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "tier1/utlvector.h" -#include "tier1/utlqueue.h" - - -//----------------------------------------------------------------------------- -// Handles are 32 bits. Invalid handles are all 1s -//----------------------------------------------------------------------------- -typedef unsigned int UtlHandle_t; -#define UTLHANDLE_INVALID ((UtlHandle_t)~0) - - -//----------------------------------------------------------------------------- -// Purpose: This is a table used to allocate handles -// HandleBits specifies the max # of simultaneously allocated handles. -// An extra bit is used for the validity state -// The rest of the 32 bits are used for a serial number -//----------------------------------------------------------------------------- -template< class T, int HandleBits > -class CUtlHandleTable -{ -public: - CUtlHandleTable(); - - // Allocate, deallocate handles - UtlHandle_t AddHandle(); - void RemoveHandle( UtlHandle_t h ); - - // Set/get handle values - void SetHandle( UtlHandle_t h, T *pData ); - T *GetHandle( UtlHandle_t h ) const; - T *GetHandle( UtlHandle_t h, bool checkValidity ) const; - - // Is a handle valid? - bool IsHandleValid( UtlHandle_t h ) const; - - // Iterate over handles; they may not be valid - unsigned int GetValidHandleCount() const; - unsigned int GetHandleCount() const; - UtlHandle_t GetHandleFromIndex( int i ) const; - int GetIndexFromHandle( UtlHandle_t h ) const; - - void MarkHandleInvalid( UtlHandle_t h ); - void MarkHandleValid( UtlHandle_t h ); - -private: - struct HandleType_t - { - HandleType_t( unsigned int i, unsigned int s ) : nIndex( i ), nSerial( s ) - { - Assert( i < ( 1 << HandleBits ) ); - Assert( s < ( 1 << ( 31 - HandleBits ) ) ); - } - unsigned int nIndex : HandleBits; - unsigned int nSerial : 31 - HandleBits; - }; - - struct EntryType_t - { - EntryType_t() : m_nSerial( 0 ), nInvalid( 0 ), m_pData( 0 ) {} - unsigned int m_nSerial : 31; - unsigned int nInvalid : 1; - T *m_pData; - }; - - static unsigned int GetSerialNumber( UtlHandle_t handle ); - static unsigned int GetListIndex( UtlHandle_t handle ); - static UtlHandle_t CreateHandle( unsigned int nSerial, unsigned int nIndex ); - const EntryType_t *GetEntry( UtlHandle_t handle, bool checkValidity ) const; - - unsigned int m_nValidHandles; - CUtlVector< EntryType_t > m_list; - CUtlQueue< int > m_unused; -}; - - -//----------------------------------------------------------------------------- -// Constructor, destructor -//----------------------------------------------------------------------------- -template< class T, int HandleBits > -CUtlHandleTable::CUtlHandleTable() : m_nValidHandles( 0 ) -{ -} - - -//----------------------------------------------------------------------------- -// Allocate, deallocate handles -//----------------------------------------------------------------------------- -template< class T, int HandleBits > -UtlHandle_t CUtlHandleTable::AddHandle() -{ - unsigned int nIndex = ( m_unused.Count() > 0 ) ? m_unused.RemoveAtHead() : m_list.AddToTail(); - - EntryType_t &entry = m_list[ nIndex ]; - entry.nInvalid = 0; - entry.m_pData = NULL; - - ++m_nValidHandles; - - return CreateHandle( entry.m_nSerial, nIndex ); -} - -template< class T, int HandleBits > -void CUtlHandleTable::RemoveHandle( UtlHandle_t handle ) -{ - unsigned int nIndex = GetListIndex( handle ); - Assert( nIndex < ( unsigned int )m_list.Count() ); - if ( nIndex >= ( unsigned int )m_list.Count() ) - return; - - EntryType_t &entry = m_list[ nIndex ]; - ++entry.m_nSerial; // mark old serial# invalid - if ( !entry.nInvalid ) - { - entry.nInvalid = 1; - --m_nValidHandles; - } - entry.m_pData = NULL; - - - // If a handle has been used this many times, then we need to take it out of service, otherwise if the - // serial # wraps around we'll possibly revalidate old handles and they'll start to point at the wrong objects. Unlikely, but possible. - bool bStopUsing = ( entry.m_nSerial >= ( (1 << ( 31 - HandleBits ) ) - 1 ) ); - if ( !bStopUsing ) - { - m_unused.Insert( nIndex ); - } -} - - -//----------------------------------------------------------------------------- -// Set/get handle values -//----------------------------------------------------------------------------- -template< class T, int HandleBits > -void CUtlHandleTable::SetHandle( UtlHandle_t handle, T *pData ) -{ - EntryType_t *entry = const_cast< EntryType_t* >( GetEntry( handle, false ) ); - Assert( entry ); - if ( entry == NULL ) - return; - - // Validate the handle - if ( entry->nInvalid ) - { - ++m_nValidHandles; - entry->nInvalid = 0; - } - entry->m_pData = pData; -} - -template< class T, int HandleBits > -T *CUtlHandleTable::GetHandle( UtlHandle_t handle ) const -{ - const EntryType_t *entry = GetEntry( handle, true ); - return entry ? entry->m_pData : NULL; -} - -template< class T, int HandleBits > -T *CUtlHandleTable::GetHandle( UtlHandle_t handle, bool checkValidity ) const -{ - const EntryType_t *entry = GetEntry( handle, checkValidity ); - return entry ? entry->m_pData : NULL; -} - - -//----------------------------------------------------------------------------- -// Is a handle valid? -//----------------------------------------------------------------------------- -template< class T, int HandleBits > -bool CUtlHandleTable::IsHandleValid( UtlHandle_t handle ) const -{ - if ( handle == UTLHANDLE_INVALID ) - return false; - - unsigned int nIndex = GetListIndex( handle ); - AssertOnce( nIndex < ( unsigned int )m_list.Count() ); - if ( nIndex >= ( unsigned int )m_list.Count() ) - return false; - - const EntryType_t &entry = m_list[ nIndex ]; - if ( entry.m_nSerial != GetSerialNumber( handle ) ) - return false; - - if ( 1 == entry.nInvalid ) - return false; - - return true; -} - - -//----------------------------------------------------------------------------- -// Current max handle -//----------------------------------------------------------------------------- -template< class T, int HandleBits > -unsigned int CUtlHandleTable::GetValidHandleCount() const -{ - return m_nValidHandles; -} - -template< class T, int HandleBits > -unsigned int CUtlHandleTable::GetHandleCount() const -{ - return m_list.Count(); -} - -template< class T, int HandleBits > -UtlHandle_t CUtlHandleTable::GetHandleFromIndex( int i ) const -{ - if ( m_list[i].m_pData ) - return CreateHandle( m_list[i].m_nSerial, i ); - return UTLHANDLE_INVALID; -} - -template< class T, int HandleBits > -int CUtlHandleTable::GetIndexFromHandle( UtlHandle_t h ) const -{ - if ( h == UTLHANDLE_INVALID ) - return -1; - - return GetListIndex( h ); -} - - - -//----------------------------------------------------------------------------- -// Cracking handles into indices + serial numbers -//----------------------------------------------------------------------------- -template< class T, int HandleBits > -unsigned int CUtlHandleTable::GetSerialNumber( UtlHandle_t handle ) -{ - return ( ( HandleType_t* )&handle )->nSerial; -} - -template< class T, int HandleBits > -unsigned int CUtlHandleTable::GetListIndex( UtlHandle_t handle ) -{ - return ( ( HandleType_t* )&handle )->nIndex; -} - -template< class T, int HandleBits > -UtlHandle_t CUtlHandleTable::CreateHandle( unsigned int nSerial, unsigned int nIndex ) -{ - HandleType_t h( nIndex, nSerial ); - return *( UtlHandle_t* )&h; -} - - -//----------------------------------------------------------------------------- -// Looks up a entry by handle -//----------------------------------------------------------------------------- -template< class T, int HandleBits > -const typename CUtlHandleTable::EntryType_t *CUtlHandleTable::GetEntry( UtlHandle_t handle, bool checkValidity ) const -{ - if ( handle == UTLHANDLE_INVALID ) - return NULL; - - unsigned int nIndex = GetListIndex( handle ); - Assert( nIndex < ( unsigned int )m_list.Count() ); - if ( nIndex >= ( unsigned int )m_list.Count() ) - return NULL; - - const EntryType_t &entry = m_list[ nIndex ]; - if ( entry.m_nSerial != GetSerialNumber( handle ) ) - return NULL; - - if ( checkValidity && - ( 1 == entry.nInvalid ) ) - return NULL; - - return &entry; -} - -template< class T, int HandleBits > -void CUtlHandleTable::MarkHandleInvalid( UtlHandle_t handle ) -{ - if ( handle == UTLHANDLE_INVALID ) - return; - - unsigned int nIndex = GetListIndex( handle ); - Assert( nIndex < ( unsigned int )m_list.Count() ); - if ( nIndex >= ( unsigned int )m_list.Count() ) - return; - - EntryType_t &entry = m_list[ nIndex ]; - if ( entry.m_nSerial != GetSerialNumber( handle ) ) - return; - - if ( !entry.nInvalid ) - { - --m_nValidHandles; - entry.nInvalid = 1; - } -} - -template< class T, int HandleBits > -void CUtlHandleTable::MarkHandleValid( UtlHandle_t handle ) -{ - if ( handle == UTLHANDLE_INVALID ) - return; - - unsigned int nIndex = GetListIndex( handle ); - Assert( nIndex < ( unsigned int )m_list.Count() ); - if ( nIndex >= ( unsigned int )m_list.Count() ) - return; - - EntryType_t &entry = m_list[ nIndex ]; - if ( entry.m_nSerial != GetSerialNumber( handle ) ) - return; - - if ( entry.nInvalid ) - { - ++m_nValidHandles; - entry.nInvalid = 0; - } -} - - -//----------------------------------------------------------------------------- -// Handle wrapper. Assumes 2 things -// 1) That class T has a non-static method called GetHandle which returns a UtlHandle_t -// 2) That class T has a static method called GetPtrFromHandle which returns a T* given a UtlHandle_t -// 3) That class T has a static method called IsHandleValid which accepts a UtlHandle_t -//----------------------------------------------------------------------------- -template< class T > -class CUtlHandle -{ -public: - // Constructors - CUtlHandle(); - explicit CUtlHandle( T *pObject ); - CUtlHandle( UtlHandle_t h ); - CUtlHandle( const CUtlHandle &h ); - - // Assignment - void Set( T *pObject ); - void Set( UtlHandle_t h ); - const CUtlHandle &operator=( UtlHandle_t h ); - const CUtlHandle &operator=( T *pObject ); - - // Retrieval - T *Get(); - const T* Get() const; - - // Is the handle valid? - bool IsValid() const; - - // Casting - operator T*(); - operator UtlHandle_t(); - operator bool(); - T* operator->(); - const T* operator->() const; - - // Equality - bool operator==( CUtlHandle h ) const; - bool operator==( T *pObject ) const; - bool operator==( UtlHandle_t h ) const; - bool operator!=( CUtlHandle h ) const; - bool operator!=( T *pObject ) const; - bool operator!=( UtlHandle_t h ) const; - -private: - UtlHandle_t m_handle; -}; - - -//----------------------------------------------------------------------------- -// Constructors -//----------------------------------------------------------------------------- -template< class T > -CUtlHandle::CUtlHandle() : m_handle( UTLHANDLE_INVALID ) -{ -} - -template< class T > -CUtlHandle::CUtlHandle( T *pObject ) -{ - Set( pObject ); -} - -template< class T > -CUtlHandle::CUtlHandle( UtlHandle_t h ) -{ - m_handle = h; -} - -template< class T > -CUtlHandle::CUtlHandle( const CUtlHandle &h ) -{ - m_handle = h.m_handle; -} - - -//----------------------------------------------------------------------------- -// Assignment -//----------------------------------------------------------------------------- -template< class T > -void CUtlHandle::Set( T *pObject ) -{ - // Assumes T has a member function GetHandle - m_handle = pObject ? pObject->GetHandle() : UTLHANDLE_INVALID; -} - -template< class T > -void CUtlHandle::Set( UtlHandle_t h ) -{ - m_handle = h; -} - -template< class T > -const CUtlHandle &CUtlHandle::operator=( UtlHandle_t h ) -{ - Set( h ); - return *this; -} - -template< class T > -const CUtlHandle &CUtlHandle::operator=( T *pObject ) -{ - Set( pObject ); - return *this; -} - - -//----------------------------------------------------------------------------- -// Is the handle valid? -//----------------------------------------------------------------------------- -template< class T > -bool CUtlHandle::IsValid() const -{ - // Assumes T has a static member function IsHandleValid - return T::IsHandleValid( m_handle ); -} - - -//----------------------------------------------------------------------------- -// Retrieval -//----------------------------------------------------------------------------- -template< class T > -T *CUtlHandle::Get() -{ - // Assumes T has a static member function GetPtrFromHandle - return T::GetPtrFromHandle( m_handle ); -} - -template< class T > -const T* CUtlHandle::Get() const -{ - // Assumes T has a static member function GetPtrFromHandle - return T::GetPtrFromHandle( m_handle ); -} - - -//----------------------------------------------------------------------------- -// Casting -//----------------------------------------------------------------------------- -template< class T > -CUtlHandle::operator T*() -{ - return Get(); -} - -template< class T > -CUtlHandle::operator UtlHandle_t() -{ - return m_handle; -} - -template< class T > -T* CUtlHandle::operator->() -{ - return Get(); -} - -template< class T > -const T* CUtlHandle::operator->() const -{ - return Get(); -} - -template< class T > -CUtlHandle::operator bool() -{ - return m_handle != UTLHANDLE_INVALID; -} - - -//----------------------------------------------------------------------------- -// Equality -//----------------------------------------------------------------------------- -template< class T > -bool CUtlHandle::operator==( CUtlHandle h ) const -{ - return m_handle == h.m_handle; -} - -template< class T > -bool CUtlHandle::operator==( T *pObject ) const -{ - UtlHandle_t h = pObject ? pObject->GetHandle() : UTLHANDLE_INVALID; - return m_handle == h; -} - -template< class T > -bool CUtlHandle::operator==( UtlHandle_t h ) const -{ - return m_handle == h; -} - -template< class T > -bool CUtlHandle::operator!=( CUtlHandle h ) const -{ - return m_handle != h.m_handle; -} - -template< class T > -bool CUtlHandle::operator!=( T *pObject ) const -{ - UtlHandle_t h = pObject ? pObject->GetHandle() : UTLHANDLE_INVALID; - return m_handle != h; -} - -template< class T > -bool CUtlHandle::operator!=( UtlHandle_t h ) const -{ - return m_handle != h; -} - - -//----------------------------------------------------------------------------- -// Add this macro to a class definition to hook in handles for it! -//----------------------------------------------------------------------------- -#define DECLARE_HANDLES( _className, _handleBitCount ) \ - public: \ - UtlHandle_t GetHandle() \ - { \ - return m_Handle; \ - } \ - static _className* GetPtrFromHandle( UtlHandle_t h ) \ - { \ - return m_HandleTable.GetHandle( h ); \ - } \ - static bool IsHandleValid( UtlHandle_t h ) \ - { \ - return m_HandleTable.IsHandleValid( h ); \ - } \ - private: \ - UtlHandle_t m_Handle; \ - static CUtlHandleTable< _className, _handleBitCount > m_HandleTable - - -//----------------------------------------------------------------------------- -// Add this macro to a .cpp file to hook in handles for it! -//----------------------------------------------------------------------------- -#define IMPLEMENT_HANDLES( _className, _handleBitCount ) \ - CUtlHandleTable< _className, _handleBitCount > _className::m_HandleTable; - - -//----------------------------------------------------------------------------- -// Add these macro to the class constructor + destructor -//----------------------------------------------------------------------------- -#define CONSTRUCT_HANDLE( ) \ - m_Handle = m_HandleTable.AddHandle(); \ - m_HandleTable.SetHandle( m_Handle, this ) - -#define DESTRUCT_HANDLE() \ - m_HandleTable.RemoveHandle( m_Handle ); \ - m_Handle = UTLHANDLE_INVALID - - - -#endif // UTLHANDLETABLE_H - diff --git a/public/tier1/utlhash.h b/public/tier1/utlhash.h deleted file mode 100644 index e15437822..000000000 --- a/public/tier1/utlhash.h +++ /dev/null @@ -1,936 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -// Serialization/unserialization buffer -//=============================================================================// - -#ifndef UTLHASH_H -#define UTLHASH_H -#pragma once - -#include -#include -#include "utlmemory.h" -#include "utlvector.h" -#include "utllinkedlist.h" -#include "utllinkedlist.h" -#include "commonmacros.h" -#include "generichash.h" - -typedef unsigned int UtlHashHandle_t; - -template -class CUtlHash -{ -public: - // compare and key functions - implemented by the - typedef C CompareFunc_t; - typedef K KeyFunc_t; - - // constructor/deconstructor - CUtlHash( int bucketCount = 0, int growCount = 0, int initCount = 0, - CompareFunc_t compareFunc = 0, KeyFunc_t keyFunc = 0 ); - ~CUtlHash(); - - // invalid handle - static UtlHashHandle_t InvalidHandle( void ) { return ( UtlHashHandle_t )~0; } - bool IsValidHandle( UtlHashHandle_t handle ) const; - - // size - int Count( void ) const; - - // memory - void Purge( void ); - - // insertion methods - UtlHashHandle_t Insert( Data const &src ); - UtlHashHandle_t Insert( Data const &src, bool *pDidInsert ); - UtlHashHandle_t AllocEntryFromKey( Data const &src ); - - // removal methods - void Remove( UtlHashHandle_t handle ); - void RemoveAll(); - - // retrieval methods - UtlHashHandle_t Find( Data const &src ) const; - - Data &Element( UtlHashHandle_t handle ); - Data const &Element( UtlHashHandle_t handle ) const; - Data &operator[]( UtlHashHandle_t handle ); - Data const &operator[]( UtlHashHandle_t handle ) const; - - UtlHashHandle_t GetFirstHandle() const; - UtlHashHandle_t GetNextHandle( UtlHashHandle_t h ) const; - - // debugging!! - void Log( const char *filename ); - -protected: - - int GetBucketIndex( UtlHashHandle_t handle ) const; - int GetKeyDataIndex( UtlHashHandle_t handle ) const; - UtlHashHandle_t BuildHandle( int ndxBucket, int ndxKeyData ) const; - - bool DoFind( Data const &src, unsigned int *pBucket, int *pIndex ) const; - -protected: - - // handle upper 16 bits = bucket index (bucket heads) - // handle lower 16 bits = key index (bucket list) - typedef CUtlVector HashBucketList_t; - CUtlVector m_Buckets; - - CompareFunc_t m_CompareFunc; // function used to handle unique compares on data - KeyFunc_t m_KeyFunc; // function used to generate the key value - - bool m_bPowerOfTwo; // if the bucket value is a power of two, - unsigned int m_ModMask; // use the mod mask to "mod" -}; - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -CUtlHash::CUtlHash( int bucketCount, int growCount, int initCount, - CompareFunc_t compareFunc, KeyFunc_t keyFunc ) : - m_CompareFunc( compareFunc ), - m_KeyFunc( keyFunc ) -{ - m_Buckets.SetSize( bucketCount ); - for( int ndxBucket = 0; ndxBucket < bucketCount; ndxBucket++ ) - { - m_Buckets[ndxBucket].SetSize( initCount ); - m_Buckets[ndxBucket].SetGrowSize( growCount ); - } - - // check to see if the bucket count is a power of 2 and set up - // optimizations appropriately - m_bPowerOfTwo = IsPowerOfTwo( bucketCount ); - m_ModMask = m_bPowerOfTwo ? (bucketCount-1) : 0; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -CUtlHash::~CUtlHash() -{ - Purge(); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline bool CUtlHash::IsValidHandle( UtlHashHandle_t handle ) const -{ - int ndxBucket = GetBucketIndex( handle ); - int ndxKeyData = GetKeyDataIndex( handle ); - - // ndxBucket and ndxKeyData can't possibly be less than zero -- take a - // look at the definition of the Get..Index functions for why. However, - // if you override those functions, you will need to override this one - // as well. - if( /*( ndxBucket >= 0 ) && */ ( ndxBucket < m_Buckets.Count() ) ) - { - if( /*( ndxKeyData >= 0 ) && */ ( ndxKeyData < m_Buckets[ndxBucket].Count() ) ) - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline int CUtlHash::Count( void ) const -{ - int count = 0; - - int bucketCount = m_Buckets.Count(); - for( int ndxBucket = 0; ndxBucket < bucketCount; ndxBucket++ ) - { - count += m_Buckets[ndxBucket].Count(); - } - - return count; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline int CUtlHash::GetBucketIndex( UtlHashHandle_t handle ) const -{ - return ( ( ( handle >> 16 ) & 0x0000ffff ) ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline int CUtlHash::GetKeyDataIndex( UtlHashHandle_t handle ) const -{ - return ( handle & 0x0000ffff ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline UtlHashHandle_t CUtlHash::BuildHandle( int ndxBucket, int ndxKeyData ) const -{ - assert( ( ndxBucket >= 0 ) && ( ndxBucket < 65536 ) ); - assert( ( ndxKeyData >= 0 ) && ( ndxKeyData < 65536 ) ); - - UtlHashHandle_t handle = ndxKeyData; - handle |= ( ndxBucket << 16 ); - - return handle; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline void CUtlHash::Purge( void ) -{ - int bucketCount = m_Buckets.Count(); - for( int ndxBucket = 0; ndxBucket < bucketCount; ndxBucket++ ) - { - m_Buckets[ndxBucket].Purge(); - } -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline bool CUtlHash::DoFind( Data const &src, unsigned int *pBucket, int *pIndex ) const -{ - // generate the data "key" - unsigned int key = m_KeyFunc( src ); - - // hash the "key" - get the correct hash table "bucket" - unsigned int ndxBucket; - if( m_bPowerOfTwo ) - { - *pBucket = ndxBucket = ( key & m_ModMask ); - } - else - { - int bucketCount = m_Buckets.Count(); - *pBucket = ndxBucket = key % bucketCount; - } - - int ndxKeyData; - const CUtlVector &bucket = m_Buckets[ndxBucket]; - int keyDataCount = bucket.Count(); - for( ndxKeyData = 0; ndxKeyData < keyDataCount; ndxKeyData++ ) - { - if( m_CompareFunc( bucket.Element( ndxKeyData ), src ) ) - break; - } - - if( ndxKeyData == keyDataCount ) - return false; - - *pIndex = ndxKeyData; - return true; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline UtlHashHandle_t CUtlHash::Find( Data const &src ) const -{ - unsigned int ndxBucket; - int ndxKeyData; - - if ( DoFind( src, &ndxBucket, &ndxKeyData ) ) - { - return ( BuildHandle( ndxBucket, ndxKeyData ) ); - } - return ( InvalidHandle() ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline UtlHashHandle_t CUtlHash::Insert( Data const &src ) -{ - unsigned int ndxBucket; - int ndxKeyData; - - if ( DoFind( src, &ndxBucket, &ndxKeyData ) ) - { - return ( BuildHandle( ndxBucket, ndxKeyData ) ); - } - - ndxKeyData = m_Buckets[ndxBucket].AddToTail( src ); - - return ( BuildHandle( ndxBucket, ndxKeyData ) ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline UtlHashHandle_t CUtlHash::Insert( Data const &src, bool *pDidInsert ) -{ - unsigned int ndxBucket; - int ndxKeyData; - - if ( DoFind( src, &ndxBucket, &ndxKeyData ) ) - { - *pDidInsert = false; - return ( BuildHandle( ndxBucket, ndxKeyData ) ); - } - - *pDidInsert = true; - ndxKeyData = m_Buckets[ndxBucket].AddToTail( src ); - - return ( BuildHandle( ndxBucket, ndxKeyData ) ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline UtlHashHandle_t CUtlHash::AllocEntryFromKey( Data const &src ) -{ - unsigned int ndxBucket; - int ndxKeyData; - - if ( DoFind( src, &ndxBucket, &ndxKeyData ) ) - { - return ( BuildHandle( ndxBucket, ndxKeyData ) ); - } - - ndxKeyData = m_Buckets[ndxBucket].AddToTail(); - - return ( BuildHandle( ndxBucket, ndxKeyData ) ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline void CUtlHash::Remove( UtlHashHandle_t handle ) -{ - assert( IsValidHandle( handle ) ); - - // check to see if the bucket exists - int ndxBucket = GetBucketIndex( handle ); - int ndxKeyData = GetKeyDataIndex( handle ); - - if( m_Buckets[ndxBucket].IsValidIndex( ndxKeyData ) ) - { - m_Buckets[ndxBucket].FastRemove( ndxKeyData ); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline void CUtlHash::RemoveAll() -{ - int bucketCount = m_Buckets.Count(); - for( int ndxBucket = 0; ndxBucket < bucketCount; ndxBucket++ ) - { - m_Buckets[ndxBucket].RemoveAll(); - } -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline Data &CUtlHash::Element( UtlHashHandle_t handle ) -{ - int ndxBucket = GetBucketIndex( handle ); - int ndxKeyData = GetKeyDataIndex( handle ); - - return ( m_Buckets[ndxBucket].Element( ndxKeyData ) ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline Data const &CUtlHash::Element( UtlHashHandle_t handle ) const -{ - int ndxBucket = GetBucketIndex( handle ); - int ndxKeyData = GetKeyDataIndex( handle ); - - return ( m_Buckets[ndxBucket].Element( ndxKeyData ) ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline Data &CUtlHash::operator[]( UtlHashHandle_t handle ) -{ - int ndxBucket = GetBucketIndex( handle ); - int ndxKeyData = GetKeyDataIndex( handle ); - - return ( m_Buckets[ndxBucket].Element( ndxKeyData ) ); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline Data const &CUtlHash::operator[]( UtlHashHandle_t handle ) const -{ - int ndxBucket = GetBucketIndex( handle ); - int ndxKeyData = GetKeyDataIndex( handle ); - - return ( m_Buckets[ndxBucket].Element( ndxKeyData ) ); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline UtlHashHandle_t CUtlHash::GetFirstHandle() const -{ - return GetNextHandle( ( UtlHashHandle_t )-1 ); -} - -template -inline UtlHashHandle_t CUtlHash::GetNextHandle( UtlHashHandle_t handle ) const -{ - ++handle; // start at the first possible handle after the one given - - int bi = GetBucketIndex( handle ); - int ki = GetKeyDataIndex( handle ); - - int nBuckets = m_Buckets.Count(); - for ( ; bi < nBuckets; ++bi ) - { - if ( ki < m_Buckets[ bi ].Count() ) - return BuildHandle( bi, ki ); - - ki = 0; - } - - return InvalidHandle(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template -inline void CUtlHash::Log( const char *filename ) -{ - FILE *pDebugFp; - pDebugFp = fopen( filename, "w" ); - if( !pDebugFp ) - return; - - int maxBucketSize = 0; - int numBucketsEmpty = 0; - - int bucketCount = m_Buckets.Count(); - fprintf( pDebugFp, "\n%d Buckets\n", bucketCount ); - - for( int ndxBucket = 0; ndxBucket < bucketCount; ndxBucket++ ) - { - int count = m_Buckets[ndxBucket].Count(); - - if( count > maxBucketSize ) { maxBucketSize = count; } - if( count == 0 ) - numBucketsEmpty++; - - fprintf( pDebugFp, "Bucket %d: %d\n", ndxBucket, count ); - } - - fprintf( pDebugFp, "\nBucketHeads Used: %d\n", bucketCount - numBucketsEmpty ); - fprintf( pDebugFp, "Max Bucket Size: %d\n", maxBucketSize ); - - fclose( pDebugFp ); -} - -//============================================================================= -// -// Fast Hash -// -// Number of buckets must be a power of 2. -// Key must be 32-bits (unsigned int). -// -typedef int UtlHashFastHandle_t; - -#define UTLHASH_POOL_SCALAR 2 - -class CUtlHashFastNoHash -{ -public: - static int Hash( int key, int bucketMask ) - { - return ( key & bucketMask ); - } -}; - -class CUtlHashFastGenericHash -{ -public: - static int Hash( int key, int bucketMask ) - { - return ( HashIntConventional( key ) & bucketMask ); - } -}; - -template -class CUtlHashFast -{ -public: - - // Constructor/Deconstructor. - CUtlHashFast(); - ~CUtlHashFast(); - - // Memory. - void Purge( void ); - - // Invalid handle. - static UtlHashFastHandle_t InvalidHandle( void ) { return ( UtlHashFastHandle_t )~0; } - - // Initialize. - bool Init( int nBucketCount ); - - // Size. - int Count( void ); - - // Insertion. - UtlHashFastHandle_t Insert( unsigned int uiKey, const Data &data ); - UtlHashFastHandle_t FastInsert( unsigned int uiKey, const Data &data ); - - // Removal. - void Remove( UtlHashFastHandle_t hHash ); - void RemoveAll( void ); - - // Retrieval. - UtlHashFastHandle_t Find( unsigned int uiKey ); - - Data &Element( UtlHashFastHandle_t hHash ); - Data const &Element( UtlHashFastHandle_t hHash ) const; - Data &operator[]( UtlHashFastHandle_t hHash ); - Data const &operator[]( UtlHashFastHandle_t hHash ) const; - -//protected: - - // Templatized for memory tracking purposes - template - struct HashFastData_t_ - { - unsigned int m_uiKey; - HashData m_Data; - }; - - typedef HashFastData_t_ HashFastData_t; - - unsigned int m_uiBucketMask; - CUtlVector m_aBuckets; - CUtlFixedLinkedList m_aDataPool; -}; - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -template CUtlHashFast::CUtlHashFast() -{ - Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: Deconstructor -//----------------------------------------------------------------------------- -template CUtlHashFast::~CUtlHashFast() -{ - Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: Destroy dynamically allocated hash data. -//----------------------------------------------------------------------------- -template inline void CUtlHashFast::Purge( void ) -{ - m_aBuckets.Purge(); - m_aDataPool.Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: Initialize the hash - set bucket count and hash grow amount. -//----------------------------------------------------------------------------- -template bool CUtlHashFast::Init( int nBucketCount ) -{ - // Verify the bucket count is power of 2. - if ( !IsPowerOfTwo( nBucketCount ) ) - return false; - - // Set the bucket size. - m_aBuckets.SetSize( nBucketCount ); - for ( int iBucket = 0; iBucket < nBucketCount; ++iBucket ) - { - m_aBuckets[iBucket] = m_aDataPool.InvalidIndex(); - } - - // Set the mod mask. - m_uiBucketMask = nBucketCount - 1; - - // Calculate the grow size. - int nGrowSize = UTLHASH_POOL_SCALAR * nBucketCount; - m_aDataPool.SetGrowSize( nGrowSize ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Return the number of elements in the hash. -//----------------------------------------------------------------------------- -template inline int CUtlHashFast::Count( void ) -{ - return m_aDataPool.Count(); -} - -//----------------------------------------------------------------------------- -// Purpose: Insert data into the hash table given its key (unsigned int), with -// a check to see if the element already exists within the tree. -//----------------------------------------------------------------------------- -template inline UtlHashFastHandle_t CUtlHashFast::Insert( unsigned int uiKey, const Data &data ) -{ - // Check to see if that key already exists in the buckets (should be unique). - UtlHashFastHandle_t hHash = Find( uiKey ); - if( hHash != InvalidHandle() ) - return hHash; - - return FastInsert( uiKey, data ); -} - -//----------------------------------------------------------------------------- -// Purpose: Insert data into the hash table given its key (unsigned int), -// without a check to see if the element already exists within the tree. -//----------------------------------------------------------------------------- -template inline UtlHashFastHandle_t CUtlHashFast::FastInsert( unsigned int uiKey, const Data &data ) -{ - // Get a new element from the pool. - int iHashData = m_aDataPool.Alloc( true ); - HashFastData_t *pHashData = &m_aDataPool[iHashData]; - if ( !pHashData ) - return InvalidHandle(); - - // Add data to new element. - pHashData->m_uiKey = uiKey; - pHashData->m_Data = data; - - // Link element. - int iBucket = HashFuncs::Hash( uiKey, m_uiBucketMask ); - m_aDataPool.LinkBefore( m_aBuckets[iBucket], iHashData ); - m_aBuckets[iBucket] = iHashData; - - return iHashData; -} - -//----------------------------------------------------------------------------- -// Purpose: Remove a given element from the hash. -//----------------------------------------------------------------------------- -template inline void CUtlHashFast::Remove( UtlHashFastHandle_t hHash ) -{ - int iBucket = HashFuncs::Hash( m_aDataPool[hHash].m_uiKey, m_uiBucketMask ); - if ( m_aBuckets[iBucket] == hHash ) - { - // It is a bucket head. - m_aBuckets[iBucket] = m_aDataPool.Next( hHash ); - } - else - { - // Not a bucket head. - m_aDataPool.Unlink( hHash ); - } - - // Remove the element. - m_aDataPool.Remove( hHash ); -} - -//----------------------------------------------------------------------------- -// Purpose: Remove all elements from the hash -//----------------------------------------------------------------------------- -template inline void CUtlHashFast::RemoveAll( void ) -{ - m_aBuckets.RemoveAll(); - m_aDataPool.RemoveAll(); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template inline UtlHashFastHandle_t CUtlHashFast::Find( unsigned int uiKey ) -{ - // hash the "key" - get the correct hash table "bucket" - int iBucket = HashFuncs::Hash( uiKey, m_uiBucketMask ); - - for ( int iElement = m_aBuckets[iBucket]; iElement != m_aDataPool.InvalidIndex(); iElement = m_aDataPool.Next( iElement ) ) - { - if ( m_aDataPool[iElement].m_uiKey == uiKey ) - return iElement; - } - - return InvalidHandle(); -} - -//----------------------------------------------------------------------------- -// Purpose: Return data given a hash handle. -//----------------------------------------------------------------------------- -template inline Data &CUtlHashFast::Element( UtlHashFastHandle_t hHash ) -{ - return ( m_aDataPool[hHash].m_Data ); -} - -//----------------------------------------------------------------------------- -// Purpose: Return data given a hash handle. -//----------------------------------------------------------------------------- -template inline Data const &CUtlHashFast::Element( UtlHashFastHandle_t hHash ) const -{ - return ( m_aDataPool[hHash].m_Data ); -} - -//----------------------------------------------------------------------------- -// Purpose: Return data given a hash handle. -//----------------------------------------------------------------------------- -template inline Data &CUtlHashFast::operator[]( UtlHashFastHandle_t hHash ) -{ - return ( m_aDataPool[hHash].m_Data ); -} - -//----------------------------------------------------------------------------- -// Purpose: Return data given a hash handle. -//----------------------------------------------------------------------------- -template inline Data const &CUtlHashFast::operator[]( UtlHashFastHandle_t hHash ) const -{ - return ( m_aDataPool[hHash].m_Data ); -} - -//============================================================================= -// -// Fixed Hash -// -// Number of buckets must be a power of 2. -// Key must be 32-bits (unsigned int). -// -typedef int UtlHashFixedHandle_t; - -template -class CUtlHashFixedGenericHash -{ -public: - static int Hash( int key, int bucketMask ) - { - int hash = HashIntConventional( key ); - if ( NUM_BUCKETS <= USHRT_MAX ) - { - hash ^= ( hash >> 16 ); - } - if ( NUM_BUCKETS <= UCHAR_MAX ) - { - hash ^= ( hash >> 8 ); - } - return ( hash & bucketMask ); - } -}; - -template -class CUtlHashFixed -{ -public: - - // Constructor/Deconstructor. - CUtlHashFixed(); - ~CUtlHashFixed(); - - // Memory. - void Purge( void ); - - // Invalid handle. - static UtlHashFixedHandle_t InvalidHandle( void ) { return ( UtlHashFixedHandle_t )~0; } - - // Size. - int Count( void ); - - // Insertion. - UtlHashFixedHandle_t Insert( unsigned int uiKey, const Data &data ); - UtlHashFixedHandle_t FastInsert( unsigned int uiKey, const Data &data ); - - // Removal. - void Remove( UtlHashFixedHandle_t hHash ); - void RemoveAll( void ); - - // Retrieval. - UtlHashFixedHandle_t Find( unsigned int uiKey ); - - Data &Element( UtlHashFixedHandle_t hHash ); - Data const &Element( UtlHashFixedHandle_t hHash ) const; - Data &operator[]( UtlHashFixedHandle_t hHash ); - Data const &operator[]( UtlHashFixedHandle_t hHash ) const; - - //protected: - - // Templatized for memory tracking purposes - template - struct HashFixedData_t_ - { - unsigned int m_uiKey; - Data_t m_Data; - }; - - typedef HashFixedData_t_ HashFixedData_t; - - enum - { - BUCKET_MASK = NUM_BUCKETS - 1 - }; - CUtlPtrLinkedList m_aBuckets[NUM_BUCKETS]; - int m_nElements; -}; - -//----------------------------------------------------------------------------- -// Purpose: Constructor -//----------------------------------------------------------------------------- -template CUtlHashFixed::CUtlHashFixed() -{ - Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: Deconstructor -//----------------------------------------------------------------------------- -template CUtlHashFixed::~CUtlHashFixed() -{ - Purge(); -} - -//----------------------------------------------------------------------------- -// Purpose: Destroy dynamically allocated hash data. -//----------------------------------------------------------------------------- -template inline void CUtlHashFixed::Purge( void ) -{ - RemoveAll(); -} - -//----------------------------------------------------------------------------- -// Purpose: Return the number of elements in the hash. -//----------------------------------------------------------------------------- -template inline int CUtlHashFixed::Count( void ) -{ - return m_nElements; -} - -//----------------------------------------------------------------------------- -// Purpose: Insert data into the hash table given its key (unsigned int), with -// a check to see if the element already exists within the tree. -//----------------------------------------------------------------------------- -template inline UtlHashFixedHandle_t CUtlHashFixed::Insert( unsigned int uiKey, const Data &data ) -{ - // Check to see if that key already exists in the buckets (should be unique). - UtlHashFixedHandle_t hHash = Find( uiKey ); - if( hHash != InvalidHandle() ) - return hHash; - - return FastInsert( uiKey, data ); -} - -//----------------------------------------------------------------------------- -// Purpose: Insert data into the hash table given its key (unsigned int), -// without a check to see if the element already exists within the tree. -//----------------------------------------------------------------------------- -template inline UtlHashFixedHandle_t CUtlHashFixed::FastInsert( unsigned int uiKey, const Data &data ) -{ - int iBucket = HashFuncs::Hash( uiKey, NUM_BUCKETS - 1 ); - UtlPtrLinkedListIndex_t iElem = m_aBuckets[iBucket].AddToHead(); - - HashFixedData_t *pHashData = &m_aBuckets[iBucket][iElem]; - - Assert( (UtlPtrLinkedListIndex_t)pHashData == iElem ); - - // Add data to new element. - pHashData->m_uiKey = uiKey; - pHashData->m_Data = data; - - m_nElements++; - return (UtlHashFixedHandle_t)pHashData; -} - -//----------------------------------------------------------------------------- -// Purpose: Remove a given element from the hash. -//----------------------------------------------------------------------------- -template inline void CUtlHashFixed::Remove( UtlHashFixedHandle_t hHash ) -{ - HashFixedData_t *pHashData = (HashFixedData_t *)hHash; - Assert( Find(pHashData->m_uiKey) != InvalidHandle() ); - int iBucket = HashFuncs::Hash( pHashData->m_uiKey, NUM_BUCKETS - 1 ); - m_aBuckets[iBucket].Remove( (UtlPtrLinkedListIndex_t)pHashData ); - m_nElements--; -} - -//----------------------------------------------------------------------------- -// Purpose: Remove all elements from the hash -//----------------------------------------------------------------------------- -template inline void CUtlHashFixed::RemoveAll( void ) -{ - for ( int i = 0; i < NUM_BUCKETS; i++ ) - { - m_aBuckets[i].RemoveAll(); - } - m_nElements = 0; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -template inline UtlHashFixedHandle_t CUtlHashFixed::Find( unsigned int uiKey ) -{ - int iBucket = HashFuncs::Hash( uiKey, NUM_BUCKETS - 1 ); - CUtlPtrLinkedList &bucket = m_aBuckets[iBucket]; - - for ( UtlPtrLinkedListIndex_t iElement = bucket.Head(); iElement != bucket.InvalidIndex(); iElement = bucket.Next( iElement ) ) - { - if ( bucket[iElement].m_uiKey == uiKey ) - return (UtlHashFixedHandle_t)iElement; - } - - return InvalidHandle(); -} - -//----------------------------------------------------------------------------- -// Purpose: Return data given a hash handle. -//----------------------------------------------------------------------------- -template inline Data &CUtlHashFixed::Element( UtlHashFixedHandle_t hHash ) -{ - return ((HashFixedData_t *)hHash)->m_Data; -} - -//----------------------------------------------------------------------------- -// Purpose: Return data given a hash handle. -//----------------------------------------------------------------------------- -template inline Data const &CUtlHashFixed::Element( UtlHashFixedHandle_t hHash ) const -{ - return ((HashFixedData_t *)hHash)->m_Data; -} - -//----------------------------------------------------------------------------- -// Purpose: Return data given a hash handle. -//----------------------------------------------------------------------------- -template inline Data &CUtlHashFixed::operator[]( UtlHashFixedHandle_t hHash ) -{ - return ((HashFixedData_t *)hHash)->m_Data; -} - -//----------------------------------------------------------------------------- -// Purpose: Return data given a hash handle. -//----------------------------------------------------------------------------- -template inline Data const &CUtlHashFixed::operator[]( UtlHashFixedHandle_t hHash ) const -{ - return ((HashFixedData_t *)hHash)->m_Data; -} - -#endif // UTLHASH_H diff --git a/public/tier1/utlhashdict.h b/public/tier1/utlhashdict.h deleted file mode 100644 index 0d1f96a53..000000000 --- a/public/tier1/utlhashdict.h +++ /dev/null @@ -1,342 +0,0 @@ -//========== Copyright 2005, Valve Corporation, All rights reserved. ======== -// -// Purpose: -// -//============================================================================= - -#ifndef UTLHASHDICT_H -#define UTLHASHDICT_H - -#if defined( _WIN32 ) -#pragma once -#endif - -#include "tier1/utlhash.h" -#include "tier1/generichash.h" -#include "mathlib/mathlib.h" - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -template -class CUtlHashDict -{ -public: - // constructor, destructor - CUtlHashDict( int bucketCount = 16, int growCount = 0, int initCount = 0 ); - ~CUtlHashDict( ); - - // gets particular elements - T& Element( unsigned i ); - const T& Element( unsigned i ) const; - T& operator[]( unsigned i ); - const T& operator[]( unsigned i ) const; - - // gets element names - char const *GetElementName( unsigned i ) const; - - // Number of elements - int Count() const; - - // Checks if a node is valid and in the tree - bool IsValidIndex( unsigned i ) const; - - // Invalid index - static unsigned InvalidHandle(); - - // Insert method (inserts in order) - unsigned Insert( const char *pName, const T &element ); - unsigned Insert( const char *pName ); - - // Find method - unsigned Find( const char *pName ) const; - - // Remove methods - void RemoveAt( unsigned i ); - void Remove( const char *pName ); - void RemoveAll( ); - - // Purge memory - void Purge(); - void PurgeAndDeleteElements(); // Call delete on each element. - - // Iteration methods - unsigned First() const; - unsigned Next( unsigned i ) const; - -protected: - struct Entry_t - { - const char *pszSymbol; - T value; - }; - - template - class CCompare - { - public: - CCompare( int ignored ) {} - - bool operator()( const Entry_t &entry1, const Entry_t &entry2 ) const - { - return !( ( bCaseInsensitive ) ? stricmp( entry1.pszSymbol, entry2.pszSymbol ) : strcmp( entry1.pszSymbol, entry2.pszSymbol ) ); - } - }; - - template - class CHash - { - public: - CHash( int ignored ) {} - - unsigned operator()( const Entry_t &entry ) const - { - return !( ( bCaseInsensitive ) ? HashStringCaseless( entry.pszSymbol ) : HashString( entry.pszSymbol ) ); - } - }; - - typedef CUtlHash, CHash > CHashTable; - CHashTable m_Elements; - int m_nCount; -}; - -//----------------------------------------------------------------------------- -// constructor, destructor -//----------------------------------------------------------------------------- -template -CUtlHashDict::CUtlHashDict( int bucketCount = 16, int growCount = 0, int initCount = 0 ) : - m_Elements( SmallestPowerOfTwoGreaterOrEqual(bucketCount), growCount, initCount ) -{ - Assert( SmallestPowerOfTwoGreaterOrEqual(bucketCount) <= 0xffff ); -} - -template -CUtlHashDict::~CUtlHashDict() -{ - Purge(); -} - -//----------------------------------------------------------------------------- -// gets particular elements -//----------------------------------------------------------------------------- -template -inline T& CUtlHashDict::Element( unsigned i ) -{ - return m_Elements[i].value; -} - -template -inline const T& CUtlHashDict::Element( unsigned i ) const -{ - return m_Elements[i].value; -} - -//----------------------------------------------------------------------------- -// gets element names -//----------------------------------------------------------------------------- -template -inline char const *CUtlHashDict::GetElementName( unsigned i ) const -{ - return m_Elements[i].pszSymbol; -} - -template -inline T& CUtlHashDict::operator[]( unsigned i ) -{ - return m_Elements[i].value; -} - -template -inline const T & CUtlHashDict::operator[]( unsigned i ) const -{ - return m_Elements[i].value; -} - -//----------------------------------------------------------------------------- -// Num elements -//----------------------------------------------------------------------------- -template -inline int CUtlHashDict::Count() const -{ - Assert( m_nCount == m_Elements.Count() ); - return m_nCount; -} - - -//----------------------------------------------------------------------------- -// Checks if a node is valid and in the tree -//----------------------------------------------------------------------------- -template -inline bool CUtlHashDict::IsValidIndex( unsigned i ) const -{ - return m_Elements.IsValidHandle(i); -} - - -//----------------------------------------------------------------------------- -// Invalid index -//----------------------------------------------------------------------------- -template -inline unsigned CUtlHashDict::InvalidHandle() -{ - return CHashTable::InvalidHandle(); -} - - -//----------------------------------------------------------------------------- -// Delete a node from the tree -//----------------------------------------------------------------------------- -template -void CUtlHashDict::RemoveAt(unsigned elem) -{ - if ( bDupeStrings ) - { - free( (void *)m_Elements[elem].pszSymbol ); - } - m_Elements.Remove(elem); - m_nCount--; -} - - -//----------------------------------------------------------------------------- -// remove a node in the tree -//----------------------------------------------------------------------------- -template void CUtlHashDict::Remove( const char *search ) -{ - unsigned node = Find( search ); - if (node != InvalidHandle()) - { - RemoveAt(node); - } -} - - -//----------------------------------------------------------------------------- -// Removes all nodes from the tree -//----------------------------------------------------------------------------- -template -void CUtlHashDict::RemoveAll() -{ - if ( bDupeStrings ) - { - typename UtlHashHandle_t index = m_Elements.GetFirstHandle(); - while ( index != m_Elements.InvalidHandle() ) - { - free( (void *)m_Elements[index].pszSymbol ); - index = m_Elements.GetNextHandle( index ); - } - } - - m_Elements.RemoveAll(); - m_nCount = 0; -} - -template -void CUtlHashDict::Purge() -{ - if ( bDupeStrings ) - { - typename UtlHashHandle_t index = m_Elements.GetFirstHandle(); - while ( index != m_Elements.InvalidHandle() ) - { - free( (void *)m_Elements[index].pszSymbol ); - index = m_Elements.GetNextHandle( index ); - } - } - - m_Elements.Purge(); - m_nCount = 0; -} - - -template -void CUtlHashDict::PurgeAndDeleteElements() -{ - // Delete all the elements. - unsigned index = m_Elements.GetFirstHandle(); - while ( index != m_Elements.InvalidHandle() ) - { - if ( bDupeStrings ) - { - free( (void *)m_Elements[index].pszSymbol ); - } - delete m_Elements[index].value; - index = m_Elements.GetNextHandle( index ); - } - - m_Elements.RemoveAll(); - m_nCount = 0; -} - - -//----------------------------------------------------------------------------- -// inserts a node into the tree -//----------------------------------------------------------------------------- -template -unsigned CUtlHashDict::Insert( const char *pName, const T &element ) -{ - MEM_ALLOC_CREDIT_CLASS(); - m_nCount++; - Entry_t entry = - { - (bDupeStrings) ? strdup( pName ) : pName, - element - }; - bool bInserted; - unsigned result = m_Elements.Insert( entry, &bInserted ); - if ( bDupeStrings && !bInserted ) - { - free( (void *)entry.pszSymbol ); - } - return result; -} - -template -unsigned CUtlHashDict::Insert( const char *pName ) -{ - MEM_ALLOC_CREDIT_CLASS(); - m_nCount++; - Entry_t entry = - { - (bDupeStrings) ? strdup( pName ) : pName - }; - bool bInserted; - unsigned result = m_Elements.Insert( entry, &bInserted ); - if ( bDupeStrings && !bInserted ) - { - free( (void *)entry.pszSymbol ); - } - return result; -} - - -//----------------------------------------------------------------------------- -// finds a node in the tree -//----------------------------------------------------------------------------- -template -unsigned CUtlHashDict::Find( const char *pName ) const -{ - MEM_ALLOC_CREDIT_CLASS(); - if ( pName ) - return m_Elements.Find( *((Entry_t *)&pName) ); - else - return InvalidHandle(); -} - - -//----------------------------------------------------------------------------- -// Iteration methods -//----------------------------------------------------------------------------- -template -unsigned CUtlHashDict::First() const -{ - return m_Elements.GetFirstHandle(); -} - -template -unsigned CUtlHashDict::Next( unsigned i ) const -{ - return m_Elements.GetNextHandle(i); -} - -#endif // UTLHASHDICT_H diff --git a/public/tier1/utlintrusivelist.h b/public/tier1/utlintrusivelist.h deleted file mode 100644 index c33819a2e..000000000 --- a/public/tier1/utlintrusivelist.h +++ /dev/null @@ -1,774 +0,0 @@ -//===== Copyright 1996-2006, Valve Corporation, All rights reserved. ======// -// -// Purpose: Intrusive linked list templates, both for singly and doubly linked lists -// -// $Revision: $ -// $NoKeywords: $ -//===========================================================================// - -#ifndef UTILINTRUSIVELIST_H -#define UTILINTRUSIVELIST_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "basetypes.h" -#include "utlmemory.h" -#include "tier0/dbg.h" - - -// -// These templates are used for intrusive linked list classes. Intrusive linked list templates -// force the structs and classes contained within them to have their own m_pNext, (optionally), -// m_pPrev, and other fileds contained within. All memory management is up to the caller and -// their classes. No data will ever be copied. Nodes can only exist on one list at a time, because -// of only having on m_Next field, and manipulating the list while walking it requires that care on -// the part of the caller. All accessing and searching functions work by passing and returning -// pointers. -// -// -// -// naming and field conventions: -// functions referring to a DList are for doubly linked lists. nodes must have m_pHead and -// m_pPrev pointer fields. -// Functions using Priority require an m_Priority field, which must be comparable. -// -// Some functions are meanto for use with lists which maintain both a head and tail pointer -// in order to support fast adding to the end. - - -/// validates that the doubly linked list has the proper structure, pointer-wise - -namespace IntrusiveList -{ -#ifdef SUPERSLOW_DEBUG_VERSION - template inline void ValidateDList(T *head) - { - if (head) - { - Assert(head->m_pPrev==0); - } - while(head) - { - if (head->m_pNext) - { - Assert(head->m_pNext->m_pPrev==head); - } - if (head->m_pPrev) - { - Assert(head->m_pPrev->m_pNext==head); - } - head=head->m_pNext; - } - } -#else - template inline void ValidateDList(T * /*head*/) - { - } -#endif - - - -// move a node in a doubly linked list backwards one step. - template inline void MoveDNodeBackwards( T *which, T * &head) - { - if (which->m_pPrev) - { - T *p=which->m_pPrev; - T *pp=p->m_pPrev; - T *n=which->m_pNext; - Assert(p->m_pNext == which); - if (n) - { - Assert(n->m_pPrev==which); - n->m_pPrev=p; - } - if (pp) - { - Assert(pp->m_pNext==p); - pp->m_pNext=which; - } - else - { - head=which; // this node is the new root! - } - which->m_pNext=p; - which->m_pPrev=pp; - p->m_pNext=n; - p->m_pPrev=which; - } - ValidateDList(head); - } - - - - // removes node 'which' from doubly linked list with 'head' - template inline void RemoveFromDList(T * &head, T *which) - { - if (which->m_pPrev) - { - Assert(which->m_pPrev->m_pNext==which); - which->m_pPrev->m_pNext=which->m_pNext; - if (which->m_pNext) - { - Assert(which->m_pNext->m_pPrev==which); - which->m_pNext->m_pPrev=which->m_pPrev; - } - } - else - { - if (head==which) - { - head=which->m_pNext; - if (head) - { - Assert(head->m_pPrev==which); - head->m_pPrev=0; - } - } - } - which->m_pNext=which->m_pPrev=0; - ValidateDList(head); - - } - - //checks to see if node is in doubly linked list - template bool OnDList(T const *head, T const *which) - { - return (head==which) || (which->m_pNext !=0) || (which->m_pPrev !=0); - } - - // add a node to the end of a singly linked list - template void AddToDTail(T * & head, T * node) - { - node->m_pNext=0; - if (! head) - { - head=node; - } - else - { - T *ptr=head; - while(ptr->m_pNext) - { - ptr=ptr->m_pNext; - } - ptr->m_pNext=node; - node->m_pPrev=ptr; // - } - } - - // add a node to end of doubly linked list. - template inline void AddToDHead(T * &head, T *which) - { - which->m_pNext=head; - if (head) - { - head->m_pPrev=which; - } - which->m_pPrev=0; - head=which; - ValidateDList(head); - } - - // add a node to front of doubly linked list which maintains a tail ptr - template inline void AddToDHeadWithTailPtr(T * &head, T *which, T * &tailptr) - { - which->m_pNext=head; - if (head) - { - head->m_pPrev=which; - } - else - { - tailptr=which; - } - which->m_pPrev=0; - head=which; - ValidateDList(head); - } - - // add a node to end of doubly linked list which maintains a tail ptr - template inline void AddToDTailWithTailPtr(T * &head, T *which, T * & tailptr) - { - if (! tailptr) - { - Assert(! head); - which->m_pPrev=which->m_pNext=0; - tailptr=head=which; - } - else - { - which->m_pNext=0; - which->m_pPrev=tailptr; - tailptr->m_pNext=which; - tailptr=which; - } - } - - // Remove a node from a dlist , maintaining the tail ptr. node is not 'delete' d - template inline void RemoveFromDListWithTailPtr(T * &head, T *which, T * & tailptr) - { - if (which==tailptr) - { - tailptr=which->m_pPrev; - } - if (which->m_pPrev) - { - Assert(which->m_pPrev->m_pNext==which); - which->m_pPrev->m_pNext=which->m_pNext; - if (which->m_pNext) - { - Assert(which->m_pNext->m_pPrev==which); - which->m_pNext->m_pPrev=which->m_pPrev; - } - } - else - { - if (head==which) - { - head=which->m_pNext; - if (head) - { - Assert(head->m_pPrev==which); - head->m_pPrev=0; - } - } - } - which->m_pNext=which->m_pPrev=0; - ValidateDList(head); - - } - - // this function removes a node, and delete's the node - template inline void DeleteFromDListWithTailPtr(T * &head, T *which, T * & tailptr) - { - T *tmp=which; - if (which==tailptr) - { - tailptr=which->m_pPrev; - } - if (which->m_pPrev) - { - Assert(which->m_pPrev->m_pNext==which); - which->m_pPrev->m_pNext=which->m_pNext; - if (which->m_pNext) - { - Assert(which->m_pNext->m_pPrev==which); - which->m_pNext->m_pPrev=which->m_pPrev; - } - } - else - { - if (head==which) - { - head=which->m_pNext; - if (head) - { - Assert(head->m_pPrev==which); - head->m_pPrev=0; - } - } - } - which->m_pNext=which->m_pPrev=0; - delete tmp; - ValidateDList(head); - } - - // Add a node to a d-list, keeping the highest priority nodes first. This is a simple - // linear search to insert, NOT a O(logn) heap. - template inline void AddToDPriority(T * &head, T *which) - { - T* prevnode=0; - for(T *curnode=head;curnode;curnode=curnode->m_pNext) - { - if (which->m_Priority>=curnode->m_Priority) - break; - prevnode=curnode; - } - // now, we have either run out of list, or we have found an - // element to add this one before - if (! prevnode) - { - AddToDHead(head,which); - } - else - { - which->m_pNext=prevnode->m_pNext; - prevnode->m_pNext=which; - which->m_pPrev=prevnode; - if (which->m_pNext) - which->m_pNext->m_pPrev=which; - } - } - - // same as AddToDPriority, except with reverse order - template inline void AddToDPriorityLowestFirst(T * &head, T *which) - { - T* prevnode=0; - for(T *curnode=head;curnode;curnode=curnode->m_pNext) - { - if (which->m_Priority<=curnode->m_Priority) - break; - prevnode=curnode; - } - // now, we have either run out of list, or we have found an - // element to add this one before - if (! prevnode) - { - AddToDHead(head,which); - } - else - { - which->m_pNext=prevnode->m_pNext; - prevnode->m_pNext=which; - which->m_pPrev=prevnode; - if (which->m_pNext) - which->m_pNext->m_pPrev=which; - } - } - - - // return a pointer to the last node in a singly-linked (or doubly) list - template T * LastNode(T * head) - { - if (head) - { - while(head->m_pNext) - { - head=head->m_pNext; - } - } - return head; - } - - - // Remove from a singly linked list. no delete called. - template void RemoveFromList(T * & head, V *which) - { - if (head==which) - { - head=which->m_pNext; - } - else - { - for(T * i=head; i; i=i->m_pNext) - { - if (i->m_pNext==which) - { - i->m_pNext=which->m_pNext; - return; - } - } - } - } - - // same as RemoveFromList, but 'delete' is called. - template void DeleteFromList(T * & head, V *which) - { - T *tmp; - if (head==which) - { - tmp=which->m_pNext; - delete(head); - head=tmp; - } - else - { - for(T * i=head; i; i=i->m_pNext) - { - if (i->m_pNext==which) - { - tmp=which->m_pNext; - delete(which); - i->m_pNext=tmp; - return; - } - } - } - } - - // find the position in a list of a node. -1 if not found. Linear search. - // nodes must have comparison functions - template int PositionInList(T *head, V *node) - { - int pos=0; - while(head) - { - if (head==node) return pos; - head=head->m_pNext; - pos++; - } - return -1; - } - - // find the Nth node in a list. null if index too high. - template T *NthNode(T * head, int idx) - { - while(idx && head) - { - idx--; - head=head->m_pNext; - } - return head; - } - - //Add a node to the head of a singly-linked - // Note that the head var passed to this will be modified. - template static inline void AddToHead(T * & head, V * node) - { - node->m_pNext=head; - head=node; - } - - //Add a node to the tail of a singly-linked. Not fast - // Note that the head var passed to this will be modified. - template static inline void AddToTail(T * & head, V * node) - { - node->m_pNext = NULL; - if ( ! head ) - head = node; - else - { - T *pLastNode = head; - while( pLastNode->m_pNext ) - pLastNode = pLastNode->m_pNext; - pLastNode->m_pNext = node; - } - } - - //Add a node to the head of a singly-linked list, maintaining a tail pointer - template static inline void AddToHead(T * & head, T * &tail,V * node) - { - if (! head) - { - tail=node; - } - node->m_pNext=head; - head=node; - } - - - - // return the node in head before in a singly linked list. returns null if head is empty, n is - // null, or if n is the first node. not fast. - template static inline T * PrevNode(T *head, T *node) - { - T *i; - for(i=head;i;i=i->m_pNext) - { - if (i->m_pNext == node) - break; - } - return i; - } - - - // add a node to the end of a singly linked list. Not fast. - template void AddToEnd(T * & head, V * node) - { - node->m_pNext=0; - if (! head) - { - head=node; - } - else - { - T *ptr=head; - while(ptr->m_pNext) - { - ptr=ptr->m_pNext; - } - ptr->m_pNext=node; - } - } - - // add a node to the end of a singly linked list, maintaining a tail pointer. - // the head and tail pointer can be modified by this routine. - template void AddToEndWithTail(T * & head, T * & tail,V * node) - { - Assert((head && tail) || ((!head) && (!tail))); - node->m_pNext=0; - if (! head) - { - head=tail=node; - } - else - { - tail->m_pNext=node; - tail=node; - } - } - - // Add a node to a singly linked list, sorting by the m_Name field - template void AddSortedByName(T * & head, T * node) - { - if ( (! head) || // empty list? - (stricmp(node->m_Name,head->m_Name)==-1)) // or we should be first? - { - node->m_pNext=head; // make us head - head=node; - } - else - { - T *t; - for(t=head;t->m_pNext;t=t->m_pNext) // find the node we should be before - if (stricmp(t->m_pNext->m_Name,node->m_Name)>=0) - break; - node->m_pNext=t->m_pNext; - t->m_pNext=node; - } - } - - // count # of elements in list - template int ListLength(T *head) - { - int len=0; - while(head) - { - len++; - head=head->m_pNext; - } - return len; - } - - // this will kill a list if the list is of objects which automatically - // remove themselves from the list when delete is called - template void KillList(T * & head) - { - while(head) - { - delete head; - } - } - - - // this will kill all elements in a list if - // the elements are of a type which does NOT remove itself from - // the list when the destructor is called. - template void DeleteList(T * & head) - { - while (head) - { - T* tmp=head->m_pNext; - delete head; - head=tmp; - } - } - - // find a named node in any list which has both a Next field and a Name field. - template static inline T * FindNamedNode(T * head, char const *name) - { - for(;head && stricmp(head->m_Name,name); head=head->m_pNext) - { - } - return head; - } - - template static inline T * FindNamedNodeCaseSensitive(T * head, char const *name) - { - for(;head && strcmp(head->m_Name,name); head=head->m_pNext) - { - } - return head; - } - - // find data in a singly linked list, using equality match on any field - // usage: FindNodeByField(listptr,data,&list::fieldname) - template static inline T * FindNodeByField(T * head, U data, U V::*field) - { - while(head) - { - if (data==(*head).*field) - return head; - head=head->m_pNext; - } - return 0; - } - - // find a node and its predecessor, matching on equality of a given field. - // usage: FindNodeByFieldWithPrev(listptr,data,&list::fieldname, prevptr) - template static inline T * FindNodeByFieldWithPrev(T * head, U data, U V::*field, T * & prev) - { - prev=0; - for(T *i=head; i; i=i->m_pNext) - { - if(data==(*i).*field) - return i; - prev=i; - } - prev=0; - return 0; - } - - - /// sort a list. comparefn should return 0 if the items are equal, 1 if A goes first, and -1 if A goes last. - // NOT fast. - template void SortList(T * &head, int (*comparefn)(T * a, T * b)) - { - int didswap=1; - while(didswap) - { - didswap=0; - T *prev=0; - for(T *i=head;i && i->m_pNext; i=i->m_pNext) - { - /// compare i and i+1 - int rslt=(*comparefn)(i,i->m_pNext); - if (rslt==-1) - { - /// need to swap - didswap=1; - T *newfirst=i->m_pNext; - if (prev) - { - prev->m_pNext=newfirst; - i->m_pNext=newfirst->m_pNext; - newfirst->m_pNext=i; - } - else - { - head=i->m_pNext; - i->m_pNext=newfirst->m_pNext; - newfirst->m_pNext=i; - } - i=newfirst; - } - prev=i; - } - } - } - - // sort a doubly linked list. NOt fast. - template void SortDList(T * & head, int (*comparefn)(T * a, T * b)) - { - SortList(head,comparefn); - /// now, regen prev ptrs - T *prev=0; - for(T *i=head;i;i=i->m_pNext) - { - i->m_pPrev=prev; - prev=i; - } - } - - // reverse a singly linked list. not recommended for anything other than valve programming - // interview :-) - template T *ReversedList( T * head ) - { - T * pNewHead=NULL; - while( head ) - { - T *pNext=head->m_pNext; -#ifdef INTERVIEW_QUESTION - head->m_pNext=pNewHead; - pNewHead = head; -#else - AddToHead( pNewHead, head ); -#endif - head = pNext; - } - return pNewHead; - } -}; - -// singly linked list -template class CUtlIntrusiveList -{ -public: - T *m_pHead; - - FORCEINLINE CUtlIntrusiveList(void) - { - m_pHead = NULL; - } - - FORCEINLINE void AddToHead( T * node ) - { - IntrusiveList::AddToHead( m_pHead, node ); - } - - FORCEINLINE void AddToTail( T * node ) - { - IntrusiveList::AddToTail( m_pHead, node ); - } - - void RemoveNode(T *which) - { - IntrusiveList::RemoveFromList( m_pHead, which ); - } - - // this will kill a list if the list is of objects which automatically - // remove themselves from the list when delete is called - void KillList( void ) - { - while(m_pHead) - { - delete m_pHead; - } - } - - - // return the node in head before in a singly linked list. returns null if head is empty, n is - // null, or if n is the first node. not fast. Fast for dlists - T * PrevNode(T *node) - { - return IntrusiveList::PrevNode( m_pHead, node ); - } - - int NthNode( int n ) - { - return NthNode( m_pHead, n ); - } - - // this will kill all elements in a list if - // the elements are of a type which does NOT remove itself from - // the list when the destructor is called. - void Purge( void ) - { - while (m_pHead) - { - T* tmp=m_pHead->m_pNext; - delete m_pHead; - m_pHead=tmp; - } - } - - int Count( void ) - { - return IntrusiveList::ListLength( m_pHead ); - } - -}; - -// doubly linked list -template class CUtlIntrusiveDList : public CUtlIntrusiveList -{ -public: - - FORCEINLINE void AddToHead( T * node ) - { - IntrusiveList::AddToDHead( CUtlIntrusiveList::m_pHead, node ); - } - FORCEINLINE void AddToTail( T * node ) - { - IntrusiveList::AddToDTail( CUtlIntrusiveList::m_pHead, node ); - } - - void RemoveNode(T *which) - { - IntrusiveList::RemoveFromDList( CUtlIntrusiveList::m_pHead, which ); - } - - T * PrevNode(T *node) - { - return ( node )?node->m_Prev:NULL; - } - -}; - - - - -#endif diff --git a/public/tier1/utllinkedlist.h b/public/tier1/utllinkedlist.h deleted file mode 100644 index 8c5ef21cb..000000000 --- a/public/tier1/utllinkedlist.h +++ /dev/null @@ -1,1018 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Linked list container class -// -// $Revision: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef UTLLINKEDLIST_H -#define UTLLINKEDLIST_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/basetypes.h" -#include "utlmemory.h" -#include "utlfixedmemory.h" -#include "utlblockmemory.h" -#include "tier0/dbg.h" - - -// This is a useful macro to iterate from head to tail in a linked list. -#define FOR_EACH_LL( listName, iteratorName ) \ - for( int iteratorName=listName.Head(); iteratorName != listName.InvalidIndex(); iteratorName = listName.Next( iteratorName ) ) - -//----------------------------------------------------------------------------- -// class CUtlLinkedList: -// description: -// A lovely index-based linked list! T is the class type, I is the index -// type, which usually should be an unsigned short or smaller. However, -// you must avoid using 16- or 8-bit arithmetic on PowerPC architectures; -// therefore you should not use UtlLinkedListElem_t::I as the type of -// a local variable... ever. PowerPC integer arithmetic must be 32- or -// 64-bit only; otherwise performance plummets. -//----------------------------------------------------------------------------- - -template -struct UtlLinkedListElem_t -{ - T m_Element; - I m_Previous; - I m_Next; - -private: - // No copy constructor for these... - UtlLinkedListElem_t( const UtlLinkedListElem_t& ); -}; - - -// Class S is the storage type; the type you can use to save off indices in -// persistent memory. Class I is the iterator type, which is what should be used -// in local scopes. I defaults to be S, but be aware that on the 360, 16-bit -// arithmetic is catastrophically slow. Therefore you should try to save shorts -// in memory, but always operate on 32's or 64's in local scope. -// The ideal parameter order would be TSMI (you are more likely to override M than I) -// but since M depends on I we can't have the defaults in that order, alas. -template , I > > -class CUtlLinkedList -{ -public: - typedef T ElemType_t; - typedef S IndexType_t; // should really be called IndexStorageType_t, but that would be a huge change -typedef I IndexLocalType_t; - typedef M MemoryAllocator_t; - - // constructor, destructor - CUtlLinkedList( int growSize = 0, int initSize = 0 ); - ~CUtlLinkedList(); - - // gets particular elements - T& Element( I i ); - T const& Element( I i ) const; - T& operator[]( I i ); - T const& operator[]( I i ) const; - - // Make sure we have a particular amount of memory - void EnsureCapacity( int num ); - - void SetGrowSize( int growSize ); - - // Memory deallocation - void Purge(); - - // Delete all the elements then call Purge. - void PurgeAndDeleteElements(); - - // Insertion methods.... - I InsertBefore( I before ); - I InsertAfter( I after ); - I AddToHead( ); - I AddToTail( ); - - I InsertBefore( I before, T const& src ); - I InsertAfter( I after, T const& src ); - I AddToHead( T const& src ); - I AddToTail( T const& src ); - - // Find an element and return its index or InvalidIndex() if it couldn't be found. - I Find( const T &src ) const; - - // Look for the element. If it exists, remove it and return true. Otherwise, return false. - bool FindAndRemove( const T &src ); - - // Removal methods - void Remove( I elem ); - void RemoveAll(); - - // Allocation/deallocation methods - // If multilist == true, then list list may contain many - // non-connected lists, and IsInList and Head + Tail are meaningless... - I Alloc( bool multilist = false ); - void Free( I elem ); - - // list modification - void LinkBefore( I before, I elem ); - void LinkAfter( I after, I elem ); - void Unlink( I elem ); - void LinkToHead( I elem ); - void LinkToTail( I elem ); - - // invalid index - inline static S InvalidIndex() { return ( S )M::InvalidIndex(); } - inline static size_t ElementSize() { return sizeof( ListElem_t ); } - - // list statistics - int Count() const; - I MaxElementIndex() const; - - // Traversing the list - I Head() const; - I Tail() const; - I Previous( I i ) const; - I Next( I i ) const; - - // Are nodes in the list or valid? - bool IsValidIndex( I i ) const; - bool IsInList( I i ) const; - -protected: - - // What the linked list element looks like - typedef UtlLinkedListElem_t ListElem_t; - - // constructs the class - I AllocInternal( bool multilist = false ); - void ConstructList(); - - // Gets at the list element.... - ListElem_t& InternalElement( I i ) { return m_Memory[i]; } - ListElem_t const& InternalElement( I i ) const { return m_Memory[i]; } - - // copy constructors not allowed - CUtlLinkedList( CUtlLinkedList const& list ) { Assert(0); } - - M m_Memory; - I m_Head; - I m_Tail; - I m_FirstFree; - I m_ElementCount; // The number actually in the list - typename M::Iterator_t m_LastAlloc; // the last index allocated - - // For debugging purposes; - // it's in release builds so this can be used in libraries correctly - ListElem_t *m_pElements; - - FORCEINLINE M const &Memory( void ) const - { - return m_Memory; - } - - void ResetDbgInfo() - { - m_pElements = m_Memory.Base(); - } -}; - - -// this is kind of ugly, but until C++ gets templatized typedefs in C++0x, it's our only choice -template < class T > -class CUtlFixedLinkedList : public CUtlLinkedList< T, int, true, int, CUtlFixedMemory< UtlLinkedListElem_t< T, int > > > -{ -public: - CUtlFixedLinkedList( int growSize = 0, int initSize = 0 ) - : CUtlLinkedList< T, int, true, int, CUtlFixedMemory< UtlLinkedListElem_t< T, int > > >( growSize, initSize ) {} - - bool IsValidIndex( int i ) const - { - if ( !this->Memory().IsIdxValid( i ) ) - return false; - -#ifdef _DEBUG // it's safe to skip this here, since the only way to get indices after m_LastAlloc is to use MaxElementIndex - if ( this->Memory().IsIdxAfter( i, this->m_LastAlloc ) ) - { - Assert( 0 ); - return false; // don't read values that have been allocated, but not constructed - } -#endif - - return ( this->Memory()[ i ].m_Previous != i ) || ( this->Memory()[ i ].m_Next == i ); - } - -private: - int MaxElementIndex() const { Assert( 0 ); return this->InvalidIndex(); } // fixedmemory containers don't support iteration from 0..maxelements-1 - void ResetDbgInfo() {} -}; - -// this is kind of ugly, but until C++ gets templatized typedefs in C++0x, it's our only choice -template < class T, class I = unsigned short > -class CUtlBlockLinkedList : public CUtlLinkedList< T, I, true, I, CUtlBlockMemory< UtlLinkedListElem_t< T, I >, I > > -{ -public: - CUtlBlockLinkedList( int growSize = 0, int initSize = 0 ) - : CUtlLinkedList< T, I, true, I, CUtlBlockMemory< UtlLinkedListElem_t< T, I >, I > >( growSize, initSize ) {} -protected: - void ResetDbgInfo() {} -}; - - -//----------------------------------------------------------------------------- -// constructor, destructor -//----------------------------------------------------------------------------- - -template -CUtlLinkedList::CUtlLinkedList( int growSize, int initSize ) : - m_Memory( growSize, initSize ), m_LastAlloc( m_Memory.InvalidIterator() ) -{ - // Prevent signed non-int datatypes - COMPILE_TIME_ASSERT( sizeof(S) == 4 || ( ( (S)-1 ) > 0 ) ); - ConstructList(); - ResetDbgInfo(); -} - -template -CUtlLinkedList::~CUtlLinkedList( ) -{ - RemoveAll(); -} - -template -void CUtlLinkedList::ConstructList() -{ - m_Head = InvalidIndex(); - m_Tail = InvalidIndex(); - m_FirstFree = InvalidIndex(); - m_ElementCount = 0; -} - - -//----------------------------------------------------------------------------- -// gets particular elements -//----------------------------------------------------------------------------- - -template -inline T& CUtlLinkedList::Element( I i ) -{ - return m_Memory[i].m_Element; -} - -template -inline T const& CUtlLinkedList::Element( I i ) const -{ - return m_Memory[i].m_Element; -} - -template -inline T& CUtlLinkedList::operator[]( I i ) -{ - return m_Memory[i].m_Element; -} - -template -inline T const& CUtlLinkedList::operator[]( I i ) const -{ - return m_Memory[i].m_Element; -} - -//----------------------------------------------------------------------------- -// list statistics -//----------------------------------------------------------------------------- - -template -inline int CUtlLinkedList::Count() const -{ - return m_ElementCount; -} - -template -inline I CUtlLinkedList::MaxElementIndex() const -{ - return m_Memory.NumAllocated(); -} - - -//----------------------------------------------------------------------------- -// Traversing the list -//----------------------------------------------------------------------------- - -template -inline I CUtlLinkedList::Head() const -{ - return m_Head; -} - -template -inline I CUtlLinkedList::Tail() const -{ - return m_Tail; -} - -template -inline I CUtlLinkedList::Previous( I i ) const -{ - Assert( IsValidIndex(i) ); - return InternalElement(i).m_Previous; -} - -template -inline I CUtlLinkedList::Next( I i ) const -{ - Assert( IsValidIndex(i) ); - return InternalElement(i).m_Next; -} - - -//----------------------------------------------------------------------------- -// Are nodes in the list or valid? -//----------------------------------------------------------------------------- - -template -inline bool CUtlLinkedList::IsValidIndex( I i ) const -{ - if ( !m_Memory.IsIdxValid( i ) ) - return false; - - if ( m_Memory.IsIdxAfter( i, m_LastAlloc ) ) - return false; // don't read values that have been allocated, but not constructed - - return ( m_Memory[ i ].m_Previous != i ) || ( m_Memory[ i ].m_Next == i ); -} - -template -inline bool CUtlLinkedList::IsInList( I i ) const -{ - if ( !m_Memory.IsIdxValid( i ) || m_Memory.IsIdxAfter( i, m_LastAlloc ) ) - return false; // don't read values that have been allocated, but not constructed - - return Previous( i ) != i; -} - -/* -template -inline bool CUtlFixedLinkedList::IsInList( int i ) const -{ - return m_Memory.IsIdxValid( i ) && (Previous( i ) != i); -} -*/ - -//----------------------------------------------------------------------------- -// Makes sure we have enough memory allocated to store a requested # of elements -//----------------------------------------------------------------------------- - -template< class T, class S, bool ML, class I, class M > -void CUtlLinkedList::EnsureCapacity( int num ) -{ - MEM_ALLOC_CREDIT_CLASS(); - m_Memory.EnsureCapacity(num); - ResetDbgInfo(); -} - -template< class T, class S, bool ML, class I, class M > -void CUtlLinkedList::SetGrowSize( int growSize ) -{ - RemoveAll(); - m_Memory.Init( growSize ); - ResetDbgInfo(); -} - - -//----------------------------------------------------------------------------- -// Deallocate memory -//----------------------------------------------------------------------------- - -template -void CUtlLinkedList::Purge() -{ - RemoveAll(); - - m_Memory.Purge(); - m_FirstFree = InvalidIndex(); - - //Routing "m_LastAlloc = m_Memory.InvalidIterator();" through a local const to sidestep an internal compiler error on 360 builds - const typename M::Iterator_t scInvalidIterator = m_Memory.InvalidIterator(); - m_LastAlloc = scInvalidIterator; - ResetDbgInfo(); -} - - -template -void CUtlLinkedList::PurgeAndDeleteElements() -{ - int iNext; - for( int i=Head(); i != InvalidIndex(); i=iNext ) - { - iNext = Next(i); - delete Element(i); - } - - Purge(); -} - - -//----------------------------------------------------------------------------- -// Node allocation/deallocation -//----------------------------------------------------------------------------- -template -I CUtlLinkedList::AllocInternal( bool multilist ) RESTRICT -{ - Assert( !multilist || ML ); - I elem; - if ( m_FirstFree == InvalidIndex() ) - { - Assert( m_Memory.IsValidIterator( m_LastAlloc ) || m_ElementCount == 0 ); - typename M::Iterator_t it = m_Memory.IsValidIterator( m_LastAlloc ) ? m_Memory.Next( m_LastAlloc ) : m_Memory.First(); - if ( !m_Memory.IsValidIterator( it ) ) - { - MEM_ALLOC_CREDIT_CLASS(); - m_Memory.Grow(); - - it = m_Memory.IsValidIterator( m_LastAlloc ) ? m_Memory.Next( m_LastAlloc ) : m_Memory.First(); - - Assert( m_Memory.IsValidIterator( it ) ); - if ( !m_Memory.IsValidIterator( it ) ) - { - Error( "CUtlLinkedList overflow!\n" ); - } - } - m_LastAlloc = it; - elem = m_Memory.GetIndex( m_LastAlloc ); - } - else - { - elem = m_FirstFree; - m_FirstFree = InternalElement( m_FirstFree ).m_Next; - } - - if ( !multilist ) - { - InternalElement( elem ).m_Next = elem; - InternalElement( elem ).m_Previous = elem; - } - else - { - InternalElement( elem ).m_Next = InvalidIndex(); - InternalElement( elem ).m_Previous = InvalidIndex(); - } - - ResetDbgInfo(); - - return elem; -} - -template -I CUtlLinkedList::Alloc( bool multilist ) -{ - I elem = AllocInternal( multilist ); - Construct( &Element(elem) ); - - return elem; -} - -template -void CUtlLinkedList::Free( I elem ) -{ - Assert( IsValidIndex(elem) ); - Unlink(elem); - - ListElem_t &internalElem = InternalElement(elem); - Destruct( &internalElem.m_Element ); - internalElem.m_Next = m_FirstFree; - m_FirstFree = elem; -} - -//----------------------------------------------------------------------------- -// Insertion methods; allocates and links (uses default constructor) -//----------------------------------------------------------------------------- - -template -I CUtlLinkedList::InsertBefore( I before ) -{ - // Make a new node - I newNode = AllocInternal(); - - // Link it in - LinkBefore( before, newNode ); - - // Construct the data - Construct( &Element(newNode) ); - - return newNode; -} - -template -I CUtlLinkedList::InsertAfter( I after ) -{ - // Make a new node - I newNode = AllocInternal(); - - // Link it in - LinkAfter( after, newNode ); - - // Construct the data - Construct( &Element(newNode) ); - - return newNode; -} - -template -inline I CUtlLinkedList::AddToHead( ) -{ - return InsertAfter( InvalidIndex() ); -} - -template -inline I CUtlLinkedList::AddToTail( ) -{ - return InsertBefore( InvalidIndex() ); -} - - -//----------------------------------------------------------------------------- -// Insertion methods; allocates and links (uses copy constructor) -//----------------------------------------------------------------------------- - -template -I CUtlLinkedList::InsertBefore( I before, T const& src ) -{ - // Make a new node - I newNode = AllocInternal(); - - // Link it in - LinkBefore( before, newNode ); - - // Construct the data - CopyConstruct( &Element(newNode), src ); - - return newNode; -} - -template -I CUtlLinkedList::InsertAfter( I after, T const& src ) -{ - // Make a new node - I newNode = AllocInternal(); - - // Link it in - LinkAfter( after, newNode ); - - // Construct the data - CopyConstruct( &Element(newNode), src ); - - return newNode; -} - -template -inline I CUtlLinkedList::AddToHead( T const& src ) -{ - return InsertAfter( InvalidIndex(), src ); -} - -template -inline I CUtlLinkedList::AddToTail( T const& src ) -{ - return InsertBefore( InvalidIndex(), src ); -} - - -//----------------------------------------------------------------------------- -// Removal methods -//----------------------------------------------------------------------------- - -template -I CUtlLinkedList::Find( const T &src ) const -{ - for ( I i=Head(); i != InvalidIndex(); i = Next( i ) ) - { - if ( Element( i ) == src ) - return i; - } - return InvalidIndex(); -} - - -template -bool CUtlLinkedList::FindAndRemove( const T &src ) -{ - I i = Find( src ); - if ( i == InvalidIndex() ) - { - return false; - } - else - { - Remove( i ); - return true; - } -} - - -template -void CUtlLinkedList::Remove( I elem ) -{ - Free( elem ); -} - -template -void CUtlLinkedList::RemoveAll() -{ - // Have to do some convoluted stuff to invoke the destructor on all - // valid elements for the multilist case (since we don't have all elements - // connected to each other in a list). - - if ( m_LastAlloc == m_Memory.InvalidIterator() ) - { - Assert( m_Head == InvalidIndex() ); - Assert( m_Tail == InvalidIndex() ); - Assert( m_FirstFree == InvalidIndex() ); - Assert( m_ElementCount == 0 ); - return; - } - - if ( ML ) - { - for ( typename M::Iterator_t it = m_Memory.First(); it != m_Memory.InvalidIterator(); it = m_Memory.Next( it ) ) - { - I i = m_Memory.GetIndex( it ); - if ( IsValidIndex( i ) ) // skip elements already in the free list - { - ListElem_t &internalElem = InternalElement( i ); - Destruct( &internalElem.m_Element ); - internalElem.m_Previous = i; - internalElem.m_Next = m_FirstFree; - m_FirstFree = i; - } - - if ( it == m_LastAlloc ) - break; // don't destruct elements that haven't ever been constructed - } - } - else - { - I i = Head(); - I next; - while ( i != InvalidIndex() ) - { - next = Next( i ); - ListElem_t &internalElem = InternalElement( i ); - Destruct( &internalElem.m_Element ); - internalElem.m_Previous = i; - internalElem.m_Next = next == InvalidIndex() ? m_FirstFree : next; - i = next; - } - if ( Head() != InvalidIndex() ) - { - m_FirstFree = Head(); - } - } - - // Clear everything else out - m_Head = InvalidIndex(); - m_Tail = InvalidIndex(); - m_ElementCount = 0; -} - - -//----------------------------------------------------------------------------- -// list modification -//----------------------------------------------------------------------------- - -template -void CUtlLinkedList::LinkBefore( I before, I elem ) -{ - Assert( IsValidIndex(elem) ); - - // Unlink it if it's in the list at the moment - Unlink(elem); - - ListElem_t * RESTRICT pNewElem = &InternalElement(elem); - - // The element *after* our newly linked one is the one we linked before. - pNewElem->m_Next = before; - - S newElem_mPrevious; // we need to hang on to this for the compairson against InvalidIndex() - // below; otherwise we get a a load-hit-store on pNewElem->m_Previous, even - // with RESTRICT - if (before == InvalidIndex()) - { - // In this case, we're linking to the end of the list, so reset the tail - newElem_mPrevious = m_Tail; - pNewElem->m_Previous = m_Tail; - m_Tail = elem; - } - else - { - // Here, we're not linking to the end. Set the prev pointer to point to - // the element we're linking. - Assert( IsInList(before) ); - ListElem_t * RESTRICT beforeElem = &InternalElement(before); - pNewElem->m_Previous = newElem_mPrevious = beforeElem->m_Previous; - beforeElem->m_Previous = elem; - } - - // Reset the head if we linked to the head of the list - if (newElem_mPrevious == InvalidIndex()) - m_Head = elem; - else - InternalElement(newElem_mPrevious).m_Next = elem; - - // one more element baby - ++m_ElementCount; -} - -template -void CUtlLinkedList::LinkAfter( I after, I elem ) -{ - Assert( IsValidIndex(elem) ); - - // Unlink it if it's in the list at the moment - if ( IsInList(elem) ) - Unlink(elem); - - ListElem_t& newElem = InternalElement(elem); - - // The element *before* our newly linked one is the one we linked after - newElem.m_Previous = after; - if (after == InvalidIndex()) - { - // In this case, we're linking to the head of the list, reset the head - newElem.m_Next = m_Head; - m_Head = elem; - } - else - { - // Here, we're not linking to the end. Set the next pointer to point to - // the element we're linking. - Assert( IsInList(after) ); - ListElem_t& afterElem = InternalElement(after); - newElem.m_Next = afterElem.m_Next; - afterElem.m_Next = elem; - } - - // Reset the tail if we linked to the tail of the list - if (newElem.m_Next == InvalidIndex()) - m_Tail = elem; - else - InternalElement(newElem.m_Next).m_Previous = elem; - - // one more element baby - ++m_ElementCount; -} - -template -void CUtlLinkedList::Unlink( I elem ) -{ - Assert( IsValidIndex(elem) ); - if (IsInList(elem)) - { - ListElem_t * RESTRICT pOldElem = &m_Memory[ elem ]; - - // If we're the first guy, reset the head - // otherwise, make our previous node's next pointer = our next - if ( pOldElem->m_Previous != InvalidIndex() ) - { - m_Memory[ pOldElem->m_Previous ].m_Next = pOldElem->m_Next; - } - else - { - m_Head = pOldElem->m_Next; - } - - // If we're the last guy, reset the tail - // otherwise, make our next node's prev pointer = our prev - if ( pOldElem->m_Next != InvalidIndex() ) - { - m_Memory[ pOldElem->m_Next ].m_Previous = pOldElem->m_Previous; - } - else - { - m_Tail = pOldElem->m_Previous; - } - - // This marks this node as not in the list, - // but not in the free list either - pOldElem->m_Previous = pOldElem->m_Next = elem; - - // One less puppy - --m_ElementCount; - } -} - -template -inline void CUtlLinkedList::LinkToHead( I elem ) -{ - LinkAfter( InvalidIndex(), elem ); -} - -template -inline void CUtlLinkedList::LinkToTail( I elem ) -{ - LinkBefore( InvalidIndex(), elem ); -} - - -//----------------------------------------------------------------------------- -// Class to drop in to replace a CUtlLinkedList that needs to be more memory agressive -//----------------------------------------------------------------------------- - -DECLARE_POINTER_HANDLE( UtlPtrLinkedListIndex_t ); // to enforce correct usage - -template < typename T > -class CUtlPtrLinkedList -{ -public: - CUtlPtrLinkedList() - : m_pFirst( NULL ), - m_nElems( 0 ) - { - COMPILE_TIME_ASSERT( sizeof(IndexType_t) == sizeof(Node_t *) ); - } - - ~CUtlPtrLinkedList() - { - RemoveAll(); - } - - typedef UtlPtrLinkedListIndex_t IndexType_t; - - T &operator[]( IndexType_t i ) - { - return (( Node_t * )i)->elem; - } - - const T &operator[]( IndexType_t i ) const - { - return (( Node_t * )i)->elem; - } - - IndexType_t AddToTail() - { - return DoInsertBefore( (IndexType_t)m_pFirst, NULL ); - } - - IndexType_t AddToTail( T const& src ) - { - return DoInsertBefore( (IndexType_t)m_pFirst, &src ); - } - - IndexType_t AddToHead() - { - IndexType_t result = DoInsertBefore( (IndexType_t)m_pFirst, NULL ); - m_pFirst = ((Node_t *)result); - return result; - } - - IndexType_t AddToHead( T const& src ) - { - IndexType_t result = DoInsertBefore( (IndexType_t)m_pFirst, &src ); - m_pFirst = ((Node_t *)result); - return result; - } - - IndexType_t InsertBefore( IndexType_t before ) - { - return DoInsertBefore( before, NULL ); - } - - IndexType_t InsertAfter( IndexType_t after ) - { - Node_t *pBefore = ((Node_t *)after)->next; - return DoInsertBefore( pBefore, NULL ); - } - - IndexType_t InsertBefore( IndexType_t before, T const& src ) - { - return DoInsertBefore( before, &src ); - } - - IndexType_t InsertAfter( IndexType_t after, T const& src ) - { - Node_t *pBefore = ((Node_t *)after)->next; - return DoInsertBefore( pBefore, &src ); - } - - void Remove( IndexType_t elem ) - { - Node_t *p = (Node_t *)elem; - - if ( p->pNext == p ) - { - m_pFirst = NULL; - } - else - { - if ( m_pFirst == p ) - { - m_pFirst = p->pNext; - } - p->pNext->pPrev = p->pPrev; - p->pPrev->pNext = p->pNext; - } - - delete p; - m_nElems--; - } - - void RemoveAll() - { - Node_t *p = m_pFirst; - if ( p ) - { - do - { - Node_t *pNext = p->pNext; - delete p; - p = pNext; - } while( p != m_pFirst ); - } - - m_pFirst = NULL; - m_nElems = 0; - } - - int Count() const - { - return m_nElems; - } - - IndexType_t Head() const - { - return (IndexType_t)m_pFirst; - } - - IndexType_t Next( IndexType_t i ) const - { - Node_t *p = ((Node_t *)i)->pNext; - if ( p != m_pFirst ) - { - return (IndexType_t)p; - } - return NULL; - } - - bool IsValidIndex( IndexType_t i ) const - { - Node_t *p = ((Node_t *)i); - return ( p && p->pNext && p->pPrev ); - } - - inline static IndexType_t InvalidIndex() - { - return NULL; - } -private: - - struct Node_t - { - Node_t() {} - Node_t( const T &elem ) : elem( elem ) {} - - T elem; - Node_t *pPrev, *pNext; - }; - - Node_t *AllocNode( const T *pCopyFrom ) - { - MEM_ALLOC_CREDIT_CLASS(); - Node_t *p; - - if ( !pCopyFrom ) - { - p = new Node_t; - } - else - { - p = new Node_t( *pCopyFrom ); - } - - return p; - } - - IndexType_t DoInsertBefore( IndexType_t before, const T *pCopyFrom ) - { - Node_t *p = AllocNode( pCopyFrom ); - Node_t *pBefore = (Node_t *)before; - if ( pBefore ) - { - p->pNext = pBefore; - p->pPrev = pBefore->pPrev; - pBefore->pPrev = p; - p->pPrev->pNext = p; - } - else - { - Assert( !m_pFirst ); - m_pFirst = p->pNext = p->pPrev = p; - } - - m_nElems++; - return (IndexType_t)p; - } - - Node_t *m_pFirst; - unsigned m_nElems; -}; - -//----------------------------------------------------------------------------- - -#endif // UTLLINKEDLIST_H diff --git a/public/tier1/utlmap.h b/public/tier1/utlmap.h deleted file mode 100644 index 992a57e00..000000000 --- a/public/tier1/utlmap.h +++ /dev/null @@ -1,203 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Header: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef UTLMAP_H -#define UTLMAP_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/dbg.h" -#include "utlrbtree.h" - -//----------------------------------------------------------------------------- -// -// Purpose: An associative container. Pretty much identical to std::map. -// -//----------------------------------------------------------------------------- - -// This is a useful macro to iterate from start to end in order in a map -#define FOR_EACH_MAP( mapName, iteratorName ) \ - for ( int iteratorName = mapName.FirstInorder(); iteratorName != mapName.InvalidIndex(); iteratorName = mapName.NextInorder( iteratorName ) ) - -// faster iteration, but in an unspecified order -#define FOR_EACH_MAP_FAST( mapName, iteratorName ) \ - for ( int iteratorName = 0; iteratorName < mapName.MaxElement(); ++iteratorName ) if ( !mapName.IsValidIndex( iteratorName ) ) continue; else - -template -class CUtlMap -{ -public: - typedef K KeyType_t; - typedef T ElemType_t; - typedef I IndexType_t; - - // Less func typedef - // Returns true if the first parameter is "less" than the second - typedef bool (*LessFunc_t)( const KeyType_t &, const KeyType_t & ); - - // constructor, destructor - // Left at growSize = 0, the memory will first allocate 1 element and double in size - // at each increment. - // LessFunc_t is required, but may be set after the constructor using SetLessFunc() below - CUtlMap( int growSize = 0, int initSize = 0, LessFunc_t lessfunc = 0 ) - : m_Tree( growSize, initSize, CKeyLess( lessfunc ) ) - { - } - - CUtlMap( LessFunc_t lessfunc ) - : m_Tree( CKeyLess( lessfunc ) ) - { - } - - void EnsureCapacity( int num ) { m_Tree.EnsureCapacity( num ); } - - // gets particular elements - ElemType_t & Element( IndexType_t i ) { return m_Tree.Element( i ).elem; } - const ElemType_t & Element( IndexType_t i ) const { return m_Tree.Element( i ).elem; } - ElemType_t & operator[]( IndexType_t i ) { return m_Tree.Element( i ).elem; } - const ElemType_t & operator[]( IndexType_t i ) const { return m_Tree.Element( i ).elem; } - KeyType_t & Key( IndexType_t i ) { return m_Tree.Element( i ).key; } - const KeyType_t & Key( IndexType_t i ) const { return m_Tree.Element( i ).key; } - - - // Num elements - unsigned int Count() const { return m_Tree.Count(); } - - // Max "size" of the vector - IndexType_t MaxElement() const { return m_Tree.MaxElement(); } - - // Checks if a node is valid and in the map - bool IsValidIndex( IndexType_t i ) const { return m_Tree.IsValidIndex( i ); } - - // Checks if the map as a whole is valid - bool IsValid() const { return m_Tree.IsValid(); } - - // Invalid index - static IndexType_t InvalidIndex() { return CTree::InvalidIndex(); } - - // Sets the less func - void SetLessFunc( LessFunc_t func ) - { - m_Tree.SetLessFunc( CKeyLess( func ) ); - } - - // Insert method (inserts in order) - IndexType_t Insert( const KeyType_t &key, const ElemType_t &insert ) - { - Node_t node; - node.key = key; - node.elem = insert; - return m_Tree.Insert( node ); - } - - IndexType_t Insert( const KeyType_t &key ) - { - Node_t node; - node.key = key; - return m_Tree.Insert( node ); - } - - // Find method - IndexType_t Find( const KeyType_t &key ) const - { - Node_t dummyNode; - dummyNode.key = key; - return m_Tree.Find( dummyNode ); - } - - // Remove methods - void RemoveAt( IndexType_t i ) { m_Tree.RemoveAt( i ); } - bool Remove( const KeyType_t &key ) - { - Node_t dummyNode; - dummyNode.key = key; - return m_Tree.Remove( dummyNode ); - } - - void RemoveAll( ) { m_Tree.RemoveAll(); } - void Purge( ) { m_Tree.Purge(); } - - // Iteration - IndexType_t FirstInorder() const { return m_Tree.FirstInorder(); } - IndexType_t NextInorder( IndexType_t i ) const { return m_Tree.NextInorder( i ); } - IndexType_t PrevInorder( IndexType_t i ) const { return m_Tree.PrevInorder( i ); } - IndexType_t LastInorder() const { return m_Tree.LastInorder(); } - - // If you change the search key, this can be used to reinsert the - // element into the map. - void Reinsert( const KeyType_t &key, IndexType_t i ) - { - m_Tree[i].key = key; - m_Tree.Reinsert(i); - } - - IndexType_t InsertOrReplace( const KeyType_t &key, const ElemType_t &insert ) - { - IndexType_t i = Find( key ); - if ( i != InvalidIndex() ) - { - Element( i ) = insert; - return i; - } - - return Insert( key, insert ); - } - - void Swap( CUtlMap< K, T, I > &that ) - { - m_Tree.Swap( that.m_Tree ); - } - - - struct Node_t - { - Node_t() - { - } - - Node_t( const Node_t &from ) - : key( from.key ), - elem( from.elem ) - { - } - - KeyType_t key; - ElemType_t elem; - }; - - class CKeyLess - { - public: - CKeyLess( LessFunc_t lessFunc ) : m_LessFunc(lessFunc) {} - - bool operator!() const - { - return !m_LessFunc; - } - - bool operator()( const Node_t &left, const Node_t &right ) const - { - return m_LessFunc( left.key, right.key ); - } - - LessFunc_t m_LessFunc; - }; - - typedef CUtlRBTree CTree; - - CTree *AccessTree() { return &m_Tree; } - -protected: - CTree m_Tree; -}; - -//----------------------------------------------------------------------------- - -#endif // UTLMAP_H diff --git a/public/tier1/utlmemory.h b/public/tier1/utlmemory.h deleted file mode 100644 index becce73d1..000000000 --- a/public/tier1/utlmemory.h +++ /dev/null @@ -1,947 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -// A growable memory class. -//===========================================================================// - -#ifndef UTLMEMORY_H -#define UTLMEMORY_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/dbg.h" -#include -#include "tier0/platform.h" - -#include "tier0/memalloc.h" -#include "tier0/memdbgon.h" - -#ifdef _MSC_VER -#pragma warning (disable:4100) -#pragma warning (disable:4514) -#endif - -//----------------------------------------------------------------------------- - - -#ifdef UTLMEMORY_TRACK -#define UTLMEMORY_TRACK_ALLOC() MemAlloc_RegisterAllocation( "Sum of all UtlMemory", 0, m_nAllocationCount * sizeof(T), m_nAllocationCount * sizeof(T), 0 ) -#define UTLMEMORY_TRACK_FREE() if ( !m_pMemory ) ; else MemAlloc_RegisterDeallocation( "Sum of all UtlMemory", 0, m_nAllocationCount * sizeof(T), m_nAllocationCount * sizeof(T), 0 ) -#else -#define UTLMEMORY_TRACK_ALLOC() ((void)0) -#define UTLMEMORY_TRACK_FREE() ((void)0) -#endif - -#if defined(_LINUX) || defined(__APPLE__) -inline void *_aligned_malloc( size_t size, size_t align ) -{ - unsigned char *pAlloc, *pResult; - - if (!IsPowerOfTwo(uint(align))) - return NULL; - - align = (align > sizeof(void *) ? align : sizeof(void *)) - 1; - - if ( (pAlloc = (unsigned char*)malloc( sizeof(void *) + align + size ) ) == (unsigned char*)NULL) - return NULL; - - pResult = (unsigned char*)( (size_t)(pAlloc + sizeof(void *) + align ) & ~align ); - ((unsigned char**)(pResult))[-1] = pAlloc; - - return (void *)pResult; -} -#endif - - -//----------------------------------------------------------------------------- -// The CUtlMemory class: -// A growable memory class which doubles in size by default. -//----------------------------------------------------------------------------- -template< class T, class I = int > -class CUtlMemory -{ -public: - // constructor, destructor - CUtlMemory( int nGrowSize = 0, int nInitSize = 0 ); - CUtlMemory( T* pMemory, int numElements ); - CUtlMemory( const T* pMemory, int numElements ); - ~CUtlMemory(); - - // Set the size by which the memory grows - void Init( int nGrowSize = 0, int nInitSize = 0 ); - - class Iterator_t - { - public: - Iterator_t( I i ) : index( i ) {} - I index; - - bool operator==( const Iterator_t it ) const { return index == it.index; } - bool operator!=( const Iterator_t it ) const { return index != it.index; } - }; - Iterator_t First() const { return Iterator_t( IsIdxValid( 0 ) ? 0 : InvalidIndex() ); } - Iterator_t Next( const Iterator_t &it ) const { return Iterator_t( IsIdxValid( it.index + 1 ) ? it.index + 1 : InvalidIndex() ); } - I GetIndex( const Iterator_t &it ) const { return it.index; } - bool IsIdxAfter( I i, const Iterator_t &it ) const { return i > it.index; } - bool IsValidIterator( const Iterator_t &it ) const { return IsIdxValid( it.index ); } - Iterator_t InvalidIterator() const { return Iterator_t( InvalidIndex() ); } - - // element access - T& operator[]( I i ); - const T& operator[]( I i ) const; - T& Element( I i ); - const T& Element( I i ) const; - - // Can we use this index? - bool IsIdxValid( I i ) const; - static I InvalidIndex() { return ( I )-1; } - - // Gets the base address (can change when adding elements!) - T* Base(); - const T* Base() const; - - // Attaches the buffer to external memory.... - void SetExternalBuffer( T* pMemory, int numElements ); - void SetExternalBuffer( const T* pMemory, int numElements ); - void AssumeMemory( T *pMemory, int nSize ); - - // Fast swap - void Swap( CUtlMemory< T, I > &mem ); - - // Switches the buffer from an external memory buffer to a reallocatable buffer - // Will copy the current contents of the external buffer to the reallocatable buffer - void ConvertToGrowableMemory( int nGrowSize ); - - // Size - int NumAllocated() const; - int Count() const; - - // Grows the memory, so that at least allocated + num elements are allocated - void Grow( int num = 1 ); - - // Makes sure we've got at least this much memory - void EnsureCapacity( int num ); - - // Memory deallocation - void Purge(); - - // Purge all but the given number of elements - void Purge( int numElements ); - - // is the memory externally allocated? - bool IsExternallyAllocated() const; - - // is the memory read only? - bool IsReadOnly() const; - - // Set the size by which the memory grows - void SetGrowSize( int size ); - -protected: - void ValidateGrowSize() - { -#ifdef _X360 - if ( m_nGrowSize && m_nGrowSize != EXTERNAL_BUFFER_MARKER ) - { - // Max grow size at 128 bytes on XBOX - const int MAX_GROW = 128; - if ( m_nGrowSize * sizeof(T) > MAX_GROW ) - { - m_nGrowSize = MAX( 1, MAX_GROW / sizeof(T) ); - } - } -#endif - } - - enum - { - EXTERNAL_BUFFER_MARKER = -1, - EXTERNAL_CONST_BUFFER_MARKER = -2, - }; - - T* m_pMemory; - int m_nAllocationCount; - int m_nGrowSize; -}; - - -//----------------------------------------------------------------------------- -// The CUtlMemory class: -// A growable memory class which doubles in size by default. -//----------------------------------------------------------------------------- -template< class T, size_t SIZE, class I = int > -class CUtlMemoryFixedGrowable : public CUtlMemory< T, I > -{ - typedef CUtlMemory< T, I > BaseClass; - -public: - CUtlMemoryFixedGrowable( int nGrowSize = 0, int nInitSize = SIZE ) : BaseClass( m_pFixedMemory, SIZE ) - { - Assert( nInitSize == 0 || nInitSize == SIZE ); - m_nMallocGrowSize = nGrowSize; - } - - void Grow( int nCount = 1 ) - { - if ( CUtlMemory::IsExternallyAllocated() ) - { - CUtlMemory::ConvertToGrowableMemory( m_nMallocGrowSize ); - } - BaseClass::Grow( nCount ); - } - - void EnsureCapacity( int num ) - { - if ( CUtlMemory::m_nAllocationCount >= num ) - return; - - if ( CUtlMemory::IsExternallyAllocated() ) - { - // Can't grow a buffer whose memory was externally allocated - CUtlMemory::ConvertToGrowableMemory( m_nMallocGrowSize ); - } - - BaseClass::EnsureCapacity( num ); - } - -private: - int m_nMallocGrowSize; - T m_pFixedMemory[ SIZE ]; -}; - -//----------------------------------------------------------------------------- -// The CUtlMemoryFixed class: -// A fixed memory class -//----------------------------------------------------------------------------- -template< typename T, size_t SIZE, int nAlignment = 0 > -class CUtlMemoryFixed -{ -public: - // constructor, destructor - CUtlMemoryFixed( int nGrowSize = 0, int nInitSize = 0 ) { Assert( nInitSize == 0 || nInitSize == SIZE ); } - CUtlMemoryFixed( T* pMemory, int numElements ) { Assert( 0 ); } - - // Can we use this index? - bool IsIdxValid( int i ) const { return (i >= 0) && (i < (int)SIZE); } - static int InvalidIndex() { return -1; } - - // Gets the base address - T* Base() { if ( nAlignment == 0 ) return (T*)(&m_Memory[0]); else return (T*)AlignValue( &m_Memory[0], nAlignment ); } - const T* Base() const { if ( nAlignment == 0 ) return (T*)(&m_Memory[0]); else return (T*)AlignValue( &m_Memory[0], nAlignment ); } - - // element access - T& operator[]( int i ) { Assert( IsIdxValid(i) ); return Base()[i]; } - const T& operator[]( int i ) const { Assert( IsIdxValid(i) ); return Base()[i]; } - T& Element( int i ) { Assert( IsIdxValid(i) ); return Base()[i]; } - const T& Element( int i ) const { Assert( IsIdxValid(i) ); return Base()[i]; } - - // Attaches the buffer to external memory.... - void SetExternalBuffer( T* pMemory, int numElements ) { Assert( 0 ); } - - // Size - int NumAllocated() const { return SIZE; } - int Count() const { return SIZE; } - - // Grows the memory, so that at least allocated + num elements are allocated - void Grow( int num = 1 ) { Assert( 0 ); } - - // Makes sure we've got at least this much memory - void EnsureCapacity( int num ) { Assert( num <= (int)SIZE ); } - - // Memory deallocation - void Purge() {} - - // Purge all but the given number of elements (NOT IMPLEMENTED IN CUtlMemoryFixed) - void Purge( int numElements ) { Assert( 0 ); } - - // is the memory externally allocated? - bool IsExternallyAllocated() const { return false; } - - // Set the size by which the memory grows - void SetGrowSize( int size ) {} - - class Iterator_t - { - public: - Iterator_t( int i ) : index( i ) {} - int index; - bool operator==( const Iterator_t it ) const { return index == it.index; } - bool operator!=( const Iterator_t it ) const { return index != it.index; } - }; - Iterator_t First() const { return Iterator_t( IsIdxValid( 0 ) ? 0 : InvalidIndex() ); } - Iterator_t Next( const Iterator_t &it ) const { return Iterator_t( IsIdxValid( it.index + 1 ) ? it.index + 1 : InvalidIndex() ); } - int GetIndex( const Iterator_t &it ) const { return it.index; } - bool IsIdxAfter( int i, const Iterator_t &it ) const { return i > it.index; } - bool IsValidIterator( const Iterator_t &it ) const { return IsIdxValid( it.index ); } - Iterator_t InvalidIterator() const { return Iterator_t( InvalidIndex() ); } - -private: - char m_Memory[ SIZE*sizeof(T) + nAlignment ]; -}; - -//----------------------------------------------------------------------------- -// constructor, destructor -//----------------------------------------------------------------------------- - -template< class T, class I > -CUtlMemory::CUtlMemory( int nGrowSize, int nInitAllocationCount ) : m_pMemory(0), - m_nAllocationCount( nInitAllocationCount ), m_nGrowSize( nGrowSize ) -{ - ValidateGrowSize(); - Assert( nGrowSize >= 0 ); - if (m_nAllocationCount) - { - UTLMEMORY_TRACK_ALLOC(); - MEM_ALLOC_CREDIT_CLASS(); - m_pMemory = (T*)malloc( m_nAllocationCount * sizeof(T) ); - } -} - -template< class T, class I > -CUtlMemory::CUtlMemory( T* pMemory, int numElements ) : m_pMemory(pMemory), - m_nAllocationCount( numElements ) -{ - // Special marker indicating externally supplied modifyable memory - m_nGrowSize = EXTERNAL_BUFFER_MARKER; -} - -template< class T, class I > -CUtlMemory::CUtlMemory( const T* pMemory, int numElements ) : m_pMemory( (T*)pMemory ), - m_nAllocationCount( numElements ) -{ - // Special marker indicating externally supplied modifyable memory - m_nGrowSize = EXTERNAL_CONST_BUFFER_MARKER; -} - -template< class T, class I > -CUtlMemory::~CUtlMemory() -{ - Purge(); -} - -template< class T, class I > -void CUtlMemory::Init( int nGrowSize /*= 0*/, int nInitSize /*= 0*/ ) -{ - Purge(); - - m_nGrowSize = nGrowSize; - m_nAllocationCount = nInitSize; - ValidateGrowSize(); - Assert( nGrowSize >= 0 ); - if (m_nAllocationCount) - { - UTLMEMORY_TRACK_ALLOC(); - MEM_ALLOC_CREDIT_CLASS(); - m_pMemory = (T*)malloc( m_nAllocationCount * sizeof(T) ); - } -} - -//----------------------------------------------------------------------------- -// Fast swap -//----------------------------------------------------------------------------- -template< class T, class I > -void CUtlMemory::Swap( CUtlMemory &mem ) -{ - swap( m_nGrowSize, mem.m_nGrowSize ); - swap( m_pMemory, mem.m_pMemory ); - swap( m_nAllocationCount, mem.m_nAllocationCount ); -} - - -//----------------------------------------------------------------------------- -// Switches the buffer from an external memory buffer to a reallocatable buffer -//----------------------------------------------------------------------------- -template< class T, class I > -void CUtlMemory::ConvertToGrowableMemory( int nGrowSize ) -{ - if ( !IsExternallyAllocated() ) - return; - - m_nGrowSize = nGrowSize; - if (m_nAllocationCount) - { - UTLMEMORY_TRACK_ALLOC(); - MEM_ALLOC_CREDIT_CLASS(); - - int nNumBytes = m_nAllocationCount * sizeof(T); - T *pMemory = (T*)malloc( nNumBytes ); - memcpy( pMemory, m_pMemory, nNumBytes ); - m_pMemory = pMemory; - } - else - { - m_pMemory = NULL; - } -} - - -//----------------------------------------------------------------------------- -// Attaches the buffer to external memory.... -//----------------------------------------------------------------------------- -template< class T, class I > -void CUtlMemory::SetExternalBuffer( T* pMemory, int numElements ) -{ - // Blow away any existing allocated memory - Purge(); - - m_pMemory = pMemory; - m_nAllocationCount = numElements; - - // Indicate that we don't own the memory - m_nGrowSize = EXTERNAL_BUFFER_MARKER; -} - -template< class T, class I > -void CUtlMemory::SetExternalBuffer( const T* pMemory, int numElements ) -{ - // Blow away any existing allocated memory - Purge(); - - m_pMemory = const_cast( pMemory ); - m_nAllocationCount = numElements; - - // Indicate that we don't own the memory - m_nGrowSize = EXTERNAL_CONST_BUFFER_MARKER; -} - -template< class T, class I > -void CUtlMemory::AssumeMemory( T* pMemory, int numElements ) -{ - // Blow away any existing allocated memory - Purge(); - - // Simply take the pointer but don't mark us as external - m_pMemory = pMemory; - m_nAllocationCount = numElements; -} - - -//----------------------------------------------------------------------------- -// element access -//----------------------------------------------------------------------------- -template< class T, class I > -inline T& CUtlMemory::operator[]( I i ) -{ - Assert( !IsReadOnly() ); - Assert( IsIdxValid(i) ); - return m_pMemory[i]; -} - -template< class T, class I > -inline const T& CUtlMemory::operator[]( I i ) const -{ - Assert( IsIdxValid(i) ); - return m_pMemory[i]; -} - -template< class T, class I > -inline T& CUtlMemory::Element( I i ) -{ - Assert( !IsReadOnly() ); - Assert( IsIdxValid(i) ); - return m_pMemory[i]; -} - -template< class T, class I > -inline const T& CUtlMemory::Element( I i ) const -{ - Assert( IsIdxValid(i) ); - return m_pMemory[i]; -} - - -//----------------------------------------------------------------------------- -// is the memory externally allocated? -//----------------------------------------------------------------------------- -template< class T, class I > -bool CUtlMemory::IsExternallyAllocated() const -{ - return (m_nGrowSize < 0); -} - - -//----------------------------------------------------------------------------- -// is the memory read only? -//----------------------------------------------------------------------------- -template< class T, class I > -bool CUtlMemory::IsReadOnly() const -{ - return (m_nGrowSize == EXTERNAL_CONST_BUFFER_MARKER); -} - - -template< class T, class I > -void CUtlMemory::SetGrowSize( int nSize ) -{ - Assert( !IsExternallyAllocated() ); - Assert( nSize >= 0 ); - m_nGrowSize = nSize; - ValidateGrowSize(); -} - - -//----------------------------------------------------------------------------- -// Gets the base address (can change when adding elements!) -//----------------------------------------------------------------------------- -template< class T, class I > -inline T* CUtlMemory::Base() -{ - Assert( !IsReadOnly() ); - return m_pMemory; -} - -template< class T, class I > -inline const T *CUtlMemory::Base() const -{ - return m_pMemory; -} - - -//----------------------------------------------------------------------------- -// Size -//----------------------------------------------------------------------------- -template< class T, class I > -inline int CUtlMemory::NumAllocated() const -{ - return m_nAllocationCount; -} - -template< class T, class I > -inline int CUtlMemory::Count() const -{ - return m_nAllocationCount; -} - - -//----------------------------------------------------------------------------- -// Is element index valid? -//----------------------------------------------------------------------------- -template< class T, class I > -inline bool CUtlMemory::IsIdxValid( I i ) const -{ - int idx = (int)i; - return idx >= 0 && idx < m_nAllocationCount; -} - -//----------------------------------------------------------------------------- -// Grows the memory -//----------------------------------------------------------------------------- -inline int UtlMemory_CalcNewAllocationCount( int nAllocationCount, int nGrowSize, int nNewSize, int nBytesItem ) -{ - if ( nGrowSize ) - { - nAllocationCount = ((1 + ((nNewSize - 1) / nGrowSize)) * nGrowSize); - } - else - { - if ( !nAllocationCount ) - { - // Compute an allocation which is at least as big as a cache line... - nAllocationCount = (31 + nBytesItem) / nBytesItem; - } - - while (nAllocationCount < nNewSize) - { -#ifndef _X360 - nAllocationCount *= 2; -#else - int nNewAllocationCount = ( nAllocationCount * 9) / 8; // 12.5 % - if ( nNewAllocationCount > nAllocationCount ) - nAllocationCount = nNewAllocationCount; - else - nAllocationCount *= 2; -#endif - } - } - - return nAllocationCount; -} - -template< class T, class I > -void CUtlMemory::Grow( int num ) -{ - Assert( num > 0 ); - - if ( IsExternallyAllocated() ) - { - // Can't grow a buffer whose memory was externally allocated - Assert(0); - return; - } - - // Make sure we have at least numallocated + num allocations. - // Use the grow rules specified for this memory (in m_nGrowSize) - int nAllocationRequested = m_nAllocationCount + num; - - UTLMEMORY_TRACK_FREE(); - - m_nAllocationCount = UtlMemory_CalcNewAllocationCount( m_nAllocationCount, m_nGrowSize, nAllocationRequested, sizeof(T) ); - - // if m_nAllocationRequested wraps index type I, recalculate - if ( ( int )( I )m_nAllocationCount < nAllocationRequested ) - { - if ( ( int )( I )m_nAllocationCount == 0 && ( int )( I )( m_nAllocationCount - 1 ) >= nAllocationRequested ) - { - --m_nAllocationCount; // deal w/ the common case of m_nAllocationCount == MAX_USHORT + 1 - } - else - { - if ( ( int )( I )nAllocationRequested != nAllocationRequested ) - { - // we've been asked to grow memory to a size s.t. the index type can't address the requested amount of memory - Assert( 0 ); - return; - } - while ( ( int )( I )m_nAllocationCount < nAllocationRequested ) - { - m_nAllocationCount = ( m_nAllocationCount + nAllocationRequested ) / 2; - } - } - } - - UTLMEMORY_TRACK_ALLOC(); - - if (m_pMemory) - { - MEM_ALLOC_CREDIT_CLASS(); - m_pMemory = (T*)realloc( m_pMemory, m_nAllocationCount * sizeof(T) ); - Assert( m_pMemory ); - } - else - { - MEM_ALLOC_CREDIT_CLASS(); - m_pMemory = (T*)malloc( m_nAllocationCount * sizeof(T) ); - Assert( m_pMemory ); - } -} - - -//----------------------------------------------------------------------------- -// Makes sure we've got at least this much memory -//----------------------------------------------------------------------------- -template< class T, class I > -inline void CUtlMemory::EnsureCapacity( int num ) -{ - if (m_nAllocationCount >= num) - return; - - if ( IsExternallyAllocated() ) - { - // Can't grow a buffer whose memory was externally allocated - Assert(0); - return; - } - - UTLMEMORY_TRACK_FREE(); - - m_nAllocationCount = num; - - UTLMEMORY_TRACK_ALLOC(); - - if (m_pMemory) - { - MEM_ALLOC_CREDIT_CLASS(); - m_pMemory = (T*)realloc( m_pMemory, m_nAllocationCount * sizeof(T) ); - } - else - { - MEM_ALLOC_CREDIT_CLASS(); - m_pMemory = (T*)malloc( m_nAllocationCount * sizeof(T) ); - } -} - - -//----------------------------------------------------------------------------- -// Memory deallocation -//----------------------------------------------------------------------------- -template< class T, class I > -void CUtlMemory::Purge() -{ - if ( !IsExternallyAllocated() ) - { - if (m_pMemory) - { - UTLMEMORY_TRACK_FREE(); - free( (void*)m_pMemory ); - m_pMemory = 0; - } - m_nAllocationCount = 0; - } -} - -template< class T, class I > -void CUtlMemory::Purge( int numElements ) -{ - Assert( numElements >= 0 ); - - if( numElements > m_nAllocationCount ) - { - // Ensure this isn't a grow request in disguise. - Assert( numElements <= m_nAllocationCount ); - return; - } - - // If we have zero elements, simply do a purge: - if( numElements == 0 ) - { - Purge(); - return; - } - - if ( IsExternallyAllocated() ) - { - // Can't shrink a buffer whose memory was externally allocated, fail silently like purge - return; - } - - // If the number of elements is the same as the allocation count, we are done. - if( numElements == m_nAllocationCount ) - { - return; - } - - - if( !m_pMemory ) - { - // Allocation count is non zero, but memory is null. - Assert( m_pMemory ); - return; - } - - UTLMEMORY_TRACK_FREE(); - - m_nAllocationCount = numElements; - - UTLMEMORY_TRACK_ALLOC(); - - // Allocation count > 0, shrink it down. - MEM_ALLOC_CREDIT_CLASS(); - m_pMemory = (T*)realloc( m_pMemory, m_nAllocationCount * sizeof(T) ); -} - -//----------------------------------------------------------------------------- -// The CUtlMemory class: -// A growable memory class which doubles in size by default. -//----------------------------------------------------------------------------- -template< class T, int nAlignment > -class CUtlMemoryAligned : public CUtlMemory -{ -public: - // constructor, destructor - CUtlMemoryAligned( int nGrowSize = 0, int nInitSize = 0 ); - CUtlMemoryAligned( T* pMemory, int numElements ); - CUtlMemoryAligned( const T* pMemory, int numElements ); - ~CUtlMemoryAligned(); - - // Attaches the buffer to external memory.... - void SetExternalBuffer( T* pMemory, int numElements ); - void SetExternalBuffer( const T* pMemory, int numElements ); - - // Grows the memory, so that at least allocated + num elements are allocated - void Grow( int num = 1 ); - - // Makes sure we've got at least this much memory - void EnsureCapacity( int num ); - - // Memory deallocation - void Purge(); - - // Purge all but the given number of elements (NOT IMPLEMENTED IN CUtlMemoryAligned) - void Purge( int numElements ) { Assert( 0 ); } - -private: - void *Align( const void *pAddr ); -}; - - -//----------------------------------------------------------------------------- -// Aligns a pointer -//----------------------------------------------------------------------------- -template< class T, int nAlignment > -void *CUtlMemoryAligned::Align( const void *pAddr ) -{ - size_t nAlignmentMask = nAlignment - 1; - return (void*)( ((size_t)pAddr + nAlignmentMask) & (~nAlignmentMask) ); -} - - -//----------------------------------------------------------------------------- -// constructor, destructor -//----------------------------------------------------------------------------- -template< class T, int nAlignment > -CUtlMemoryAligned::CUtlMemoryAligned( int nGrowSize, int nInitAllocationCount ) -{ - CUtlMemory::m_pMemory = 0; - CUtlMemory::m_nAllocationCount = nInitAllocationCount; - CUtlMemory::m_nGrowSize = nGrowSize; - CUtlMemory::ValidateGrowSize(); - - // Alignment must be a power of two - COMPILE_TIME_ASSERT( (nAlignment & (nAlignment-1)) == 0 ); - Assert( (nGrowSize >= 0) && (nGrowSize != CUtlMemory::EXTERNAL_BUFFER_MARKER) ); - if ( CUtlMemory::m_nAllocationCount ) - { - UTLMEMORY_TRACK_ALLOC(); - MEM_ALLOC_CREDIT_CLASS(); - CUtlMemory::m_pMemory = (T*)_aligned_malloc( nInitAllocationCount * sizeof(T), nAlignment ); - } -} - -template< class T, int nAlignment > -CUtlMemoryAligned::CUtlMemoryAligned( T* pMemory, int numElements ) -{ - // Special marker indicating externally supplied memory - CUtlMemory::m_nGrowSize = CUtlMemory::EXTERNAL_BUFFER_MARKER; - - CUtlMemory::m_pMemory = (T*)Align( pMemory ); - CUtlMemory::m_nAllocationCount = ( (int)(pMemory + numElements) - (int)CUtlMemory::m_pMemory ) / sizeof(T); -} - -template< class T, int nAlignment > -CUtlMemoryAligned::CUtlMemoryAligned( const T* pMemory, int numElements ) -{ - // Special marker indicating externally supplied memory - CUtlMemory::m_nGrowSize = CUtlMemory::EXTERNAL_CONST_BUFFER_MARKER; - - CUtlMemory::m_pMemory = (T*)Align( pMemory ); - CUtlMemory::m_nAllocationCount = ( (int)(pMemory + numElements) - (int)CUtlMemory::m_pMemory ) / sizeof(T); -} - -template< class T, int nAlignment > -CUtlMemoryAligned::~CUtlMemoryAligned() -{ - Purge(); -} - - -//----------------------------------------------------------------------------- -// Attaches the buffer to external memory.... -//----------------------------------------------------------------------------- -template< class T, int nAlignment > -void CUtlMemoryAligned::SetExternalBuffer( T* pMemory, int numElements ) -{ - // Blow away any existing allocated memory - Purge(); - - CUtlMemory::m_pMemory = (T*)Align( pMemory ); - CUtlMemory::m_nAllocationCount = ( (int)(pMemory + numElements) - (int)CUtlMemory::m_pMemory ) / sizeof(T); - - // Indicate that we don't own the memory - CUtlMemory::m_nGrowSize = CUtlMemory::EXTERNAL_BUFFER_MARKER; -} - -template< class T, int nAlignment > -void CUtlMemoryAligned::SetExternalBuffer( const T* pMemory, int numElements ) -{ - // Blow away any existing allocated memory - Purge(); - - CUtlMemory::m_pMemory = (T*)Align( pMemory ); - CUtlMemory::m_nAllocationCount = ( (int)(pMemory + numElements) - (int)CUtlMemory::m_pMemory ) / sizeof(T); - - // Indicate that we don't own the memory - CUtlMemory::m_nGrowSize = CUtlMemory::EXTERNAL_CONST_BUFFER_MARKER; -} - - -//----------------------------------------------------------------------------- -// Grows the memory -//----------------------------------------------------------------------------- -template< class T, int nAlignment > -void CUtlMemoryAligned::Grow( int num ) -{ - Assert( num > 0 ); - - if ( CUtlMemory::IsExternallyAllocated() ) - { - // Can't grow a buffer whose memory was externally allocated - Assert(0); - return; - } - - UTLMEMORY_TRACK_FREE(); - - // Make sure we have at least numallocated + num allocations. - // Use the grow rules specified for this memory (in m_nGrowSize) - int nAllocationRequested = CUtlMemory::m_nAllocationCount + num; - - CUtlMemory::m_nAllocationCount = UtlMemory_CalcNewAllocationCount( CUtlMemory::m_nAllocationCount, CUtlMemory::m_nGrowSize, nAllocationRequested, sizeof(T) ); - - UTLMEMORY_TRACK_ALLOC(); - - if ( CUtlMemory::m_pMemory ) - { - MEM_ALLOC_CREDIT_CLASS(); - CUtlMemory::m_pMemory = (T*)_aligned_realloc( CUtlMemory::m_pMemory, CUtlMemory::m_nAllocationCount * sizeof(T), nAlignment ); - Assert( CUtlMemory::m_pMemory ); - } - else - { - MEM_ALLOC_CREDIT_CLASS(); - CUtlMemory::m_pMemory = (T*)_aligned_malloc( CUtlMemory::m_nAllocationCount * sizeof(T), nAlignment ); - Assert( CUtlMemory::m_pMemory ); - } -} - - -//----------------------------------------------------------------------------- -// Makes sure we've got at least this much memory -//----------------------------------------------------------------------------- -template< class T, int nAlignment > -inline void CUtlMemoryAligned::EnsureCapacity( int num ) -{ - if ( CUtlMemory::m_nAllocationCount >= num ) - return; - - if ( CUtlMemory::IsExternallyAllocated() ) - { - // Can't grow a buffer whose memory was externally allocated - Assert(0); - return; - } - - UTLMEMORY_TRACK_FREE(); - - CUtlMemory::m_nAllocationCount = num; - - UTLMEMORY_TRACK_ALLOC(); - - if ( CUtlMemory::m_pMemory ) - { - MEM_ALLOC_CREDIT_CLASS(); - CUtlMemory::m_pMemory = (T*)_aligned_realloc( CUtlMemory::m_pMemory, CUtlMemory::m_nAllocationCount * sizeof(T), nAlignment ); - } - else - { - MEM_ALLOC_CREDIT_CLASS(); - CUtlMemory::m_pMemory = (T*)_aligned_malloc( CUtlMemory::m_nAllocationCount * sizeof(T), nAlignment ); - } -} - - -//----------------------------------------------------------------------------- -// Memory deallocation -//----------------------------------------------------------------------------- -template< class T, int nAlignment > -void CUtlMemoryAligned::Purge() -{ - if ( !CUtlMemory::IsExternallyAllocated() ) - { - if ( CUtlMemory::m_pMemory ) - { - UTLMEMORY_TRACK_FREE(); - _aligned_free( CUtlMemory::m_pMemory ); - CUtlMemory::m_pMemory = 0; - } - CUtlMemory::m_nAllocationCount = 0; - } -} - -#include "tier0/memdbgoff.h" - -#endif // UTLMEMORY_H diff --git a/public/tier1/utlmultilist.h b/public/tier1/utlmultilist.h deleted file mode 100644 index 41e21819d..000000000 --- a/public/tier1/utlmultilist.h +++ /dev/null @@ -1,805 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Multiple linked list container class -// -// $Revision: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef UTLMULTILIST_H -#define UTLMULTILIST_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "utllinkedlist.h" - -// memdbgon must be the last include file in a .h file!!! -#include "tier0/memdbgon.h" - -// This is a useful macro to iterate from head to tail in a linked list. -#define FOR_EACH_LL( listName, iteratorName ) \ - for( int iteratorName=listName.Head(); iteratorName != listName.InvalidIndex(); iteratorName = listName.Next( iteratorName ) ) - -template -struct validindex_t; - -//----------------------------------------------------------------------------- -// class CUtlMultiList: -// description: -// A lovely index-based linked list! T is the class type, I is the index -// type, which usually should be an unsigned short or smaller. -// This list can contain multiple lists -//----------------------------------------------------------------------------- -template -class CUtlMultiList -{ - friend struct validindex_t; -public: - typedef I ListHandle_t; - - // constructor, destructor - CUtlMultiList( int growSize = 0, int initSize = 0 ); - CUtlMultiList( void *pMemory, int memsize ); - ~CUtlMultiList( ); - - // gets particular elements - T& Element( I i ); - T const& Element( I i ) const; - T& operator[]( I i ); - T const& operator[]( I i ) const; - - // Make sure we have a particular amount of memory - void EnsureCapacity( int num ); - - // Memory deallocation - void Purge(); - - // List Creation/deletion - ListHandle_t CreateList(); - void DestroyList( ListHandle_t list ); - bool IsValidList( ListHandle_t list ) const; - - // Insertion methods (call default constructor).... - I InsertBefore( ListHandle_t list, I before ); - I InsertAfter( ListHandle_t list, I after ); - I AddToHead( ListHandle_t list ); - I AddToTail( ListHandle_t list ); - - // Insertion methods (call copy constructor).... - I InsertBefore( ListHandle_t list, I before, T const& src ); - I InsertAfter( ListHandle_t list, I after, T const& src ); - I AddToHead( ListHandle_t list, T const& src ); - I AddToTail( ListHandle_t list, T const& src ); - - // Removal methods - void Remove( ListHandle_t list, I elem ); - - // Removes all items in a single list - void RemoveAll( ListHandle_t list ); - - // Removes all items in all lists - void RemoveAll(); - - // Allocation/deallocation methods - // NOTE: To free, it must *not* be in a list! - I Alloc( ); - void Free( I elem ); - - // list modification - void LinkBefore( ListHandle_t list, I before, I elem ); - void LinkAfter( ListHandle_t list, I after, I elem ); - void Unlink( ListHandle_t list, I elem ); - void LinkToHead( ListHandle_t list, I elem ); - void LinkToTail( ListHandle_t list, I elem ); - - // invalid index - static I InvalidIndex() { return (I)~0; } - static size_t ElementSize() { return sizeof(ListElem_t); } - - // list statistics - int Count( ListHandle_t list ) const; - int TotalCount( ) const; - I MaxElementIndex() const; - - // Traversing the list - I Head( ListHandle_t list ) const; - I Tail( ListHandle_t list ) const; - I Previous( I element ) const; - I Next( I element ) const; - - // Are nodes in a list or valid? - bool IsValidIndex( I i ) const; - bool IsInList( I i ) const; - -protected: - // What the linked list element looks like - struct ListElem_t - { - T m_Element; - I m_Previous; - I m_Next; - }; - - struct List_t - { - I m_Head; - I m_Tail; - I m_Count; - }; - - // constructs the class - void ConstructList( ); - - // Gets at the list element.... - ListElem_t& InternalElement( I i ) { return m_Memory[i]; } - ListElem_t const& InternalElement( I i ) const { return m_Memory[i]; } - - // A test for debug mode only... - bool IsElementInList( ListHandle_t list, I elem ) const; - - // copy constructors not allowed - CUtlMultiList( CUtlMultiList const& list ) { Assert(0); } - - CUtlMemory m_Memory; - CUtlLinkedList m_List; - I* m_pElementList; - - I m_FirstFree; - I m_TotalElements; - I m_MaxElementIndex; // The number allocated - - void ResetDbgInfo() - { - m_pElements = m_Memory.Base(); - -#ifdef _DEBUG - // Allocate space for the element list (which list is each element in) - if (m_Memory.NumAllocated() > 0) - { - if (!m_pElementList) - { - m_pElementList = (I*)malloc( m_Memory.NumAllocated() * sizeof(I) ); - } - else - { - m_pElementList = (I*)realloc( m_pElementList, m_Memory.NumAllocated() * sizeof(I) ); - } - } -#endif - } - - // For debugging purposes; - // it's in release builds so this can be used in libraries correctly - ListElem_t *m_pElements; -}; - -//----------------------------------------------------------------------------- -// constructor, destructor -//----------------------------------------------------------------------------- - -template -CUtlMultiList::CUtlMultiList( int growSize, int initSize ) : - m_Memory(growSize, initSize), m_pElementList(0) -{ - ConstructList(); -} - -template -CUtlMultiList::CUtlMultiList( void* pMemory, int memsize ) : - m_Memory((ListElem_t *)pMemory, memsize/sizeof(ListElem_t)), m_pElementList(0) -{ - ConstructList(); -} - -template -CUtlMultiList::~CUtlMultiList( ) -{ - RemoveAll(); - if (m_pElementList) - free(m_pElementList); -} - -template -void CUtlMultiList::ConstructList( ) -{ - m_FirstFree = InvalidIndex(); - m_TotalElements = 0; - m_MaxElementIndex = 0; - ResetDbgInfo(); -} - - -//----------------------------------------------------------------------------- -// gets particular elements -//----------------------------------------------------------------------------- -template -inline T& CUtlMultiList::Element( I i ) -{ - return m_Memory[i].m_Element; -} - -template -inline T const& CUtlMultiList::Element( I i ) const -{ - return m_Memory[i].m_Element; -} - -template -inline T& CUtlMultiList::operator[]( I i ) -{ - return m_Memory[i].m_Element; -} - -template -inline T const& CUtlMultiList::operator[]( I i ) const -{ - return m_Memory[i].m_Element; -} - - -//----------------------------------------------------------------------------- -// list creation/destruction -//----------------------------------------------------------------------------- -template -typename CUtlMultiList::ListHandle_t CUtlMultiList::CreateList() -{ - ListHandle_t l = m_List.AddToTail(); - m_List[l].m_Head = m_List[l].m_Tail = InvalidIndex(); - m_List[l].m_Count = 0; - return l; -} - -template -void CUtlMultiList::DestroyList( ListHandle_t list ) -{ - Assert( IsValidList(list) ); - RemoveAll( list ); - m_List.Remove(list); -} - -template -bool CUtlMultiList::IsValidList( ListHandle_t list ) const -{ - return m_List.IsValidIndex(list); -} - - -//----------------------------------------------------------------------------- -// list statistics -//----------------------------------------------------------------------------- -template -inline int CUtlMultiList::TotalCount() const -{ - return m_TotalElements; -} - -template -inline int CUtlMultiList::Count( ListHandle_t list ) const -{ - Assert( IsValidList(list) ); - return m_List[list].m_Count; -} - -template -inline I CUtlMultiList::MaxElementIndex() const -{ - return m_MaxElementIndex; -} - - -//----------------------------------------------------------------------------- -// Traversing the list -//----------------------------------------------------------------------------- -template -inline I CUtlMultiList::Head(ListHandle_t list) const -{ - Assert( IsValidList(list) ); - return m_List[list].m_Head; -} - -template -inline I CUtlMultiList::Tail(ListHandle_t list) const -{ - Assert( IsValidList(list) ); - return m_List[list].m_Tail; -} - -template -inline I CUtlMultiList::Previous( I i ) const -{ - Assert( IsValidIndex(i) ); - return InternalElement(i).m_Previous; -} - -template -inline I CUtlMultiList::Next( I i ) const -{ - Assert( IsValidIndex(i) ); - return InternalElement(i).m_Next; -} - -//----------------------------------------------------------------------------- -// Workaround for doing partial specialization of function templates -// This was done to "fix" the following warning: -// comparison is always true due to limited range of data type -//----------------------------------------------------------------------------- -template -struct validindex_t -{ - static inline bool IsValidIndex(const CUtlMultiList *list, I i) - { - return (i < list->m_MaxElementIndex) && (i >= 0) && - ((list->m_Memory[i].m_Previous != i) || (list->m_Memory[i].m_Next == i)); - } - - static inline bool IsInList(const CUtlMultiList *list, I i) - { - return (i < list->m_MaxElementIndex) && (i >= 0) && (list->Previous(i) != i); - } -}; - -template -struct validindex_t -{ - static inline bool IsValidIndex(const CUtlMultiList *list, unsigned char i) - { - return (i < list->m_MaxElementIndex) && ((list->m_Memory[i].m_Previous != i) || - (list->m_Memory[i].m_Next == i)); - } - - static inline bool IsInList(const CUtlMultiList *list, unsigned char i) - { - return (i < list->m_MaxElementIndex) && (list->Previous(i) != i); - } -}; - -template -struct validindex_t -{ - static inline bool IsValidIndex(const CUtlMultiList *list, unsigned short i) - { - return (i < list->m_MaxElementIndex) && ((list->m_Memory[i].m_Previous != i) || - (list->m_Memory[i].m_Next == i)); - } - - static inline bool IsInList(const CUtlMultiList *list, unsigned short i) - { - return (i < list->m_MaxElementIndex) && (list->Previous(i) != i); - } -}; - -template -struct validindex_t -{ - static inline bool IsValidIndex(const CUtlMultiList *list, unsigned int i) - { - return (i < list->m_MaxElementIndex) && ((list->m_Memory[i].m_Previous != i) || - (list->m_Memory[i].m_Next == i)); - } - - static inline bool IsInList(const CUtlMultiList *list, unsigned int i) - { - return (i < list->m_MaxElementIndex) && (list->Previous(i) != i); - } -}; - -template -struct validindex_t -{ - static inline bool IsValidIndex(const CUtlMultiList *list, unsigned long i) - { - return (i < list->m_MaxElementIndex) && ((list->m_Memory[i].m_Previous != i) || - (list->m_Memory[i].m_Next == i)); - } - - static inline bool IsInList(const CUtlMultiList *list, unsigned long i) - { - return (i < list->m_MaxElementIndex) && (list->Previous(i) != i); - } -}; - -//----------------------------------------------------------------------------- -// Are nodes in the list or valid? -//----------------------------------------------------------------------------- -template -inline bool CUtlMultiList::IsValidIndex( I i ) const -{ - return validindex_t::IsValidIndex(this, i); -} - -template -inline bool CUtlMultiList::IsInList( I i ) const -{ - return validindex_t::IsInList(this, i); -} - - -//----------------------------------------------------------------------------- -// Makes sure we have enough memory allocated to store a requested # of elements -//----------------------------------------------------------------------------- -template< class T, class I > -void CUtlMultiList::EnsureCapacity( int num ) -{ - m_Memory.EnsureCapacity(num); - ResetDbgInfo(); -} - - -//----------------------------------------------------------------------------- -// Deallocate memory -//----------------------------------------------------------------------------- -template -void CUtlMultiList::Purge() -{ - RemoveAll(); - m_List.Purge(); - m_Memory.Purge( ); - m_List.Purge(); - m_FirstFree = InvalidIndex(); - m_TotalElements = 0; - m_MaxElementIndex = 0; - ResetDbgInfo(); -} - - -//----------------------------------------------------------------------------- -// Node allocation/deallocation -//----------------------------------------------------------------------------- -template -I CUtlMultiList::Alloc( ) -{ - I elem; - if (m_FirstFree == InvalidIndex()) - { - // Nothing in the free list; add. - // Since nothing is in the free list, m_TotalElements == total # of elements - // the list knows about. - if (m_MaxElementIndex == m_Memory.NumAllocated()) - { - m_Memory.Grow(); - ResetDbgInfo(); - } - - elem = (I)m_MaxElementIndex; - ++m_MaxElementIndex; - } - else - { - elem = m_FirstFree; - m_FirstFree = InternalElement(m_FirstFree).m_Next; - } - - // Mark the element as not being in a list - InternalElement(elem).m_Next = InternalElement(elem).m_Previous = elem; - - ++m_TotalElements; - - Construct( &Element(elem) ); - - return elem; -} - -template -void CUtlMultiList::Free( I elem ) -{ - Assert( IsValidIndex(elem) && !IsInList(elem) ); - Destruct( &Element(elem) ); - InternalElement(elem).m_Next = m_FirstFree; - m_FirstFree = elem; - --m_TotalElements; -} - - -//----------------------------------------------------------------------------- -// A test for debug mode only... -//----------------------------------------------------------------------------- -template -inline bool CUtlMultiList::IsElementInList( ListHandle_t list, I elem ) const -{ - if (!m_pElementList) - return true; - - return m_pElementList[elem] == list; -} - - -//----------------------------------------------------------------------------- -// list modification -//----------------------------------------------------------------------------- -template -void CUtlMultiList::LinkBefore( ListHandle_t list, I before, I elem ) -{ - Assert( IsValidIndex(elem) && IsValidList(list) ); - - // Unlink it if it's in the list at the moment - Unlink(list, elem); - - ListElem_t& newElem = InternalElement(elem); - - // The element *after* our newly linked one is the one we linked before. - newElem.m_Next = before; - - if (before == InvalidIndex()) - { - // In this case, we're linking to the end of the list, so reset the tail - newElem.m_Previous = m_List[list].m_Tail; - m_List[list].m_Tail = elem; - } - else - { - // Here, we're not linking to the end. Set the prev pointer to point to - // the element we're linking. - Assert( IsInList(before) ); - ListElem_t& beforeElem = InternalElement(before); - newElem.m_Previous = beforeElem.m_Previous; - beforeElem.m_Previous = elem; - } - - // Reset the head if we linked to the head of the list - if (newElem.m_Previous == InvalidIndex()) - m_List[list].m_Head = elem; - else - InternalElement(newElem.m_Previous).m_Next = elem; - - // one more element baby - ++m_List[list].m_Count; - - // Store the element into the list - if (m_pElementList) - m_pElementList[elem] = list; -} - -template -void CUtlMultiList::LinkAfter( ListHandle_t list, I after, I elem ) -{ - Assert( IsValidIndex(elem) ); - - // Unlink it if it's in the list at the moment - Unlink(list, elem); - - ListElem_t& newElem = InternalElement(elem); - - // The element *before* our newly linked one is the one we linked after - newElem.m_Previous = after; - if (after == InvalidIndex()) - { - // In this case, we're linking to the head of the list, reset the head - newElem.m_Next = m_List[list].m_Head; - m_List[list].m_Head = elem; - } - else - { - // Here, we're not linking to the end. Set the next pointer to point to - // the element we're linking. - Assert( IsInList(after) ); - ListElem_t& afterElem = InternalElement(after); - newElem.m_Next = afterElem.m_Next; - afterElem.m_Next = elem; - } - - // Reset the tail if we linked to the tail of the list - if (newElem.m_Next == InvalidIndex()) - m_List[list].m_Tail = elem; - else - InternalElement(newElem.m_Next).m_Previous = elem; - - // one more element baby - ++m_List[list].m_Count; - - // Store the element into the list - if (m_pElementList) - m_pElementList[elem] = list; -} - -template -void CUtlMultiList::Unlink( ListHandle_t list, I elem ) -{ - Assert( IsValidIndex(elem) && IsValidList(list) ); - - if (IsInList(elem)) - { - // Make sure the element is in the right list - Assert( IsElementInList( list, elem ) ); - ListElem_t& oldElem = InternalElement(elem); - - // If we're the first guy, reset the head - // otherwise, make our previous node's next pointer = our next - if (oldElem.m_Previous != InvalidIndex()) - InternalElement(oldElem.m_Previous).m_Next = oldElem.m_Next; - else - m_List[list].m_Head = oldElem.m_Next; - - // If we're the last guy, reset the tail - // otherwise, make our next node's prev pointer = our prev - if (oldElem.m_Next != InvalidIndex()) - InternalElement(oldElem.m_Next).m_Previous = oldElem.m_Previous; - else - m_List[list].m_Tail = oldElem.m_Previous; - - // This marks this node as not in the list, - // but not in the free list either - oldElem.m_Previous = oldElem.m_Next = elem; - - // One less puppy - --m_List[list].m_Count; - - // Store the element into the list - if (m_pElementList) - m_pElementList[elem] = m_List.InvalidIndex(); - } -} - -template -inline void CUtlMultiList::LinkToHead( ListHandle_t list, I elem ) -{ - LinkAfter( list, InvalidIndex(), elem ); -} - -template -inline void CUtlMultiList::LinkToTail( ListHandle_t list, I elem ) -{ - LinkBefore( list, InvalidIndex(), elem ); -} - - -//----------------------------------------------------------------------------- -// Insertion methods; allocates and links (uses default constructor) -//----------------------------------------------------------------------------- -template -I CUtlMultiList::InsertBefore( ListHandle_t list, I before ) -{ - // Make a new node - I newNode = Alloc(); - - // Link it in - LinkBefore( list, before, newNode ); - - // Construct the data - Construct( &Element(newNode) ); - - return newNode; -} - -template -I CUtlMultiList::InsertAfter( ListHandle_t list, I after ) -{ - // Make a new node - I newNode = Alloc(); - - // Link it in - LinkAfter( list, after, newNode ); - - // Construct the data - Construct( &Element(newNode) ); - - return newNode; -} - -template -inline I CUtlMultiList::AddToHead( ListHandle_t list ) -{ - return InsertAfter( list, InvalidIndex() ); -} - -template -inline I CUtlMultiList::AddToTail( ListHandle_t list ) -{ - return InsertBefore( list, InvalidIndex() ); -} - - -//----------------------------------------------------------------------------- -// Insertion methods; allocates and links (uses copy constructor) -//----------------------------------------------------------------------------- -template -I CUtlMultiList::InsertBefore( ListHandle_t list, I before, T const& src ) -{ - // Make a new node - I newNode = Alloc(); - - // Link it in - LinkBefore( list, before, newNode ); - - // Construct the data - CopyConstruct( &Element(newNode), src ); - - return newNode; -} - -template -I CUtlMultiList::InsertAfter( ListHandle_t list, I after, T const& src ) -{ - // Make a new node - I newNode = Alloc(); - - // Link it in - LinkAfter( list, after, newNode ); - - // Construct the data - CopyConstruct( &Element(newNode), src ); - - return newNode; -} - -template -inline I CUtlMultiList::AddToHead( ListHandle_t list, T const& src ) -{ - return InsertAfter( list, InvalidIndex(), src ); -} - -template -inline I CUtlMultiList::AddToTail( ListHandle_t list, T const& src ) -{ - return InsertBefore( list, InvalidIndex(), src ); -} - - -//----------------------------------------------------------------------------- -// Removal methods -//----------------------------------------------------------------------------- -template -void CUtlMultiList::Remove( ListHandle_t list, I elem ) -{ - if (IsInList(elem)) - Unlink(list, elem); - Free( elem ); -} - -// Removes all items in a single list -template -void CUtlMultiList::RemoveAll( ListHandle_t list ) -{ - Assert( IsValidList(list) ); - I i = Head(list); - I next; - while( i != InvalidIndex() ) - { - next = Next(i); - Remove(list, i); - i = next; - } -} - - -template -void CUtlMultiList::RemoveAll() -{ - if (m_MaxElementIndex == 0) - return; - - // Put everything into the free list - I prev = InvalidIndex(); - for (int i = (int)m_MaxElementIndex; --i >= 0; ) - { - // Invoke the destructor - if (IsValidIndex((I)i)) - Destruct( &Element((I)i) ); - - // next points to the next free list item - InternalElement((I)i).m_Next = prev; - - // Indicates it's in the free list - InternalElement((I)i).m_Previous = (I)i; - prev = (I)i; - } - - // First free points to the first element - m_FirstFree = 0; - - // Clear everything else out - for (I list = m_List.Head(); list != m_List.InvalidIndex(); list = m_List.Next(list) ) - { - m_List[list].m_Head = InvalidIndex(); - m_List[list].m_Tail = InvalidIndex(); - m_List[list].m_Count = 0; - } - - m_TotalElements = 0; -} - - -#include "tier0/memdbgoff.h" - -#endif // UTLMULTILIST_H diff --git a/public/tier1/utlntree.h b/public/tier1/utlntree.h deleted file mode 100644 index 58ca4d706..000000000 --- a/public/tier1/utlntree.h +++ /dev/null @@ -1,624 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: N-way tree container class -// -// $Revision: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef UTLNTREE_H -#define UTLNTREE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "basetypes.h" -#include "utlmemory.h" -#include "tier0/dbg.h" - - -#define INVALID_NTREE_IDX ((I)~0) - -//----------------------------------------------------------------------------- -// class CUtlNTree: -// description: -// A lovely index-based linked list! T is the class type, I is the index -// type, which usually should be an unsigned short or smaller. -//----------------------------------------------------------------------------- -template -class CUtlNTree -{ -public: - typedef T ElemType_t; - typedef I IndexType_t; - - // constructor, destructor - CUtlNTree( int growSize = 0, int initSize = 0 ); - CUtlNTree( void *pMemory, int memsize ); - ~CUtlNTree( ); - - // gets particular elements - T& Element( I i ); - const T& Element( I i ) const; - T& operator[]( I i ); - const T& operator[]( I i ) const; - - // Make sure we have a particular amount of memory - void EnsureCapacity( int num ); - - // Clears the tree, doesn't deallocate memory - void RemoveAll(); - - // Memory deallocation - void Purge(); - - // Allocation/deallocation methods - I Alloc( ); - void Free( I elem ); - void FreeSubTree( I elem ); - - // list modification - void SetRoot( I root ); - void LinkChildBefore( I parent, I before, I elem ); - void LinkChildAfter( I parent, I after, I elem ); - void Unlink( I elem ); - - // Alloc + link combined - I InsertChildBefore( I parent, I before ); - I InsertChildAfter( I parent, I after ); - I InsertChildBefore( I parent, I before, const T &elem ); - I InsertChildAfter( I parent, I after, const T &elem ); - - // Unlink + free combined - void Remove( I elem ); - void RemoveSubTree( I elem ); - - // invalid index - inline static I InvalidIndex() { return INVALID_NTREE_IDX; } - inline static size_t ElementSize() { return sizeof(Node_t); } - - // list statistics - int Count() const; - I MaxElementIndex() const; - - // Traversing the list - I Root() const; - I FirstChild( I i ) const; - I PrevSibling( I i ) const; - I NextSibling( I i ) const; - I Parent( I i ) const; - - // Are nodes in the list or valid? - bool IsValidIndex( I i ) const; - bool IsInTree( I i ) const; - -protected: - // What the linked list element looks like - struct Node_t - { - T m_Element; - I m_Parent; - I m_FirstChild; - I m_PrevSibling; - I m_NextSibling; - - private: - // No copy constructor for these... - Node_t( const Node_t& ); - }; - - // constructs the class - void ConstructList(); - - // Allocates the element, doesn't call the constructor - I AllocInternal(); - - // Gets at the node element.... - Node_t& InternalNode( I i ) { return m_Memory[i]; } - const Node_t& InternalNode( I i ) const { return m_Memory[i]; } - - void ResetDbgInfo() - { - m_pElements = m_Memory.Base(); - } - - // copy constructors not allowed - CUtlNTree( CUtlNTree const& tree ) { Assert(0); } - - CUtlMemory m_Memory; - I m_Root; - I m_FirstFree; - I m_ElementCount; // The number actually in the tree - I m_MaxElementIndex; // The max index we've ever assigned - - // For debugging purposes; - // it's in release builds so this can be used in libraries correctly - Node_t *m_pElements; -}; - - -//----------------------------------------------------------------------------- -// constructor, destructor -//----------------------------------------------------------------------------- - -template -CUtlNTree::CUtlNTree( int growSize, int initSize ) : - m_Memory(growSize, initSize) -{ - ConstructList(); - ResetDbgInfo(); -} - -template -CUtlNTree::CUtlNTree( void* pMemory, int memsize ) : - m_Memory((ListElem_t *)pMemory, memsize/sizeof(ListElem_t)) -{ - ConstructList(); - ResetDbgInfo(); -} - -template -CUtlNTree::~CUtlNTree( ) -{ - RemoveAll(); -} - -template -void CUtlNTree::ConstructList() -{ - m_Root = InvalidIndex(); - m_FirstFree = InvalidIndex(); - m_ElementCount = m_MaxElementIndex = 0; -} - - -//----------------------------------------------------------------------------- -// gets particular elements -//----------------------------------------------------------------------------- -template -inline T& CUtlNTree::Element( I i ) -{ - return m_Memory[i].m_Element; -} - -template -inline const T& CUtlNTree::Element( I i ) const -{ - return m_Memory[i].m_Element; -} - -template -inline T& CUtlNTree::operator[]( I i ) -{ - return m_Memory[i].m_Element; -} - -template -inline const T& CUtlNTree::operator[]( I i ) const -{ - return m_Memory[i].m_Element; -} - - -//----------------------------------------------------------------------------- -// list statistics -//----------------------------------------------------------------------------- -template -inline int CUtlNTree::Count() const -{ - return m_ElementCount; -} - -template -inline I CUtlNTree::MaxElementIndex() const -{ - return m_MaxElementIndex; -} - - -//----------------------------------------------------------------------------- -// Traversing the list -//----------------------------------------------------------------------------- -template -inline I CUtlNTree::Root() const -{ - return m_Root; -} - -template -inline I CUtlNTree::FirstChild( I i ) const -{ - Assert( IsInTree(i) ); - return InternalNode(i).m_FirstChild; -} - -template -inline I CUtlNTree::PrevSibling( I i ) const -{ - Assert( IsInTree(i) ); - return InternalNode(i).m_PrevSibling; -} - -template -inline I CUtlNTree::NextSibling( I i ) const -{ - Assert( IsInTree(i) ); - return InternalNode(i).m_NextSibling; -} - -template -inline I CUtlNTree::Parent( I i ) const -{ - Assert( IsInTree(i) ); - return InternalNode(i).m_Parent; -} - - -//----------------------------------------------------------------------------- -// Are nodes in the list or valid? -//----------------------------------------------------------------------------- -template -inline bool CUtlNTree::IsValidIndex( I i ) const -{ - return (i < m_MaxElementIndex) && (i >= 0); -} - -template -inline bool CUtlNTree::IsInTree( I i ) const -{ - return (i < m_MaxElementIndex) && (i >= 0) && (InternalNode(i).m_PrevSibling != i); -} - - -//----------------------------------------------------------------------------- -// Makes sure we have enough memory allocated to store a requested # of elements -//----------------------------------------------------------------------------- -template< class T, class I > -void CUtlNTree::EnsureCapacity( int num ) -{ - MEM_ALLOC_CREDIT_CLASS(); - m_Memory.EnsureCapacity(num); - ResetDbgInfo(); -} - - -//----------------------------------------------------------------------------- -// Deallocate memory -//----------------------------------------------------------------------------- -template -void CUtlNTree::Purge() -{ - RemoveAll(); - m_Memory.Purge( ); - m_FirstFree = InvalidIndex(); - m_MaxElementIndex = 0; - ResetDbgInfo(); -} - - -//----------------------------------------------------------------------------- -// Node allocation/deallocation -//----------------------------------------------------------------------------- -template -I CUtlNTree::AllocInternal( ) -{ - I elem; - if ( m_FirstFree == INVALID_NTREE_IDX ) - { - // Nothing in the free list; add. - // Since nothing is in the free list, m_MaxElementIndex == total # of elements - // the list knows about. - if ((int)m_MaxElementIndex == m_Memory.NumAllocated()) - { - MEM_ALLOC_CREDIT_CLASS(); - m_Memory.Grow(); - } - - Assert( m_MaxElementIndex != INVALID_NTREE_IDX ); - - elem = (I)m_MaxElementIndex; - ++m_MaxElementIndex; - - if ( elem == InvalidIndex() ) - { - Error("CUtlNTree overflow!\n"); - } - } - else - { - elem = m_FirstFree; - m_FirstFree = InternalNode( m_FirstFree ).m_NextSibling; - } - - Node_t &node = InternalNode( elem ); - node.m_NextSibling = node.m_PrevSibling = node.m_Parent = node.m_FirstChild = INVALID_NTREE_IDX; - ResetDbgInfo(); - - // one more element baby - ++m_ElementCount; - - return elem; -} - -template -I CUtlNTree::Alloc( ) -{ - I elem = AllocInternal(); - Construct( &Element(elem) ); - return elem; -} - -template -void CUtlNTree::Free( I elem ) -{ - Assert( IsInTree( elem ) ); - Unlink( elem ); - - // If there's children, this will result in leaks. Use FreeSubTree instead. - Assert( FirstChild( elem ) == INVALID_NTREE_IDX ); - - Node_t &node = InternalNode( elem ); - Destruct( &node.m_Element ); - node.m_NextSibling = m_FirstFree; - node.m_PrevSibling = elem; // Marks it as being in the free list - node.m_Parent = node.m_FirstChild = INVALID_NTREE_IDX; - m_FirstFree = elem; - - // one less element baby - --m_ElementCount; -} - -template -void CUtlNTree::FreeSubTree( I elem ) -{ - Assert( IsValidIndex( elem ) ); - - I child = FirstChild( elem ); - while ( child != INVALID_NTREE_IDX ) - { - I next = NextSibling( child ); - FreeSubTree( child ); - child = next; - } - - Free( elem ); -} - - -//----------------------------------------------------------------------------- -// Clears the tree -//----------------------------------------------------------------------------- -template -void CUtlNTree::RemoveAll() -{ - if ( m_MaxElementIndex == 0 ) - return; - - // Put everything into the free list (even unlinked things ) - I prev = InvalidIndex(); - for (int i = (int)m_MaxElementIndex; --i >= 0; prev = (I)i ) - { - Node_t &node = InternalNode( i ); - if ( IsInTree( i ) ) - { - Destruct( &node.m_Element ); - } - - node.m_NextSibling = prev; - node.m_PrevSibling = (I)i; // Marks it as being in the free list - node.m_Parent = node.m_FirstChild = INVALID_NTREE_IDX; - } - - // First free points to the first element - m_FirstFree = 0; - - // Clear everything else out - m_Root = INVALID_NTREE_IDX; - m_ElementCount = 0; -} - - -//----------------------------------------------------------------------------- -// list modification -//----------------------------------------------------------------------------- -template -void CUtlNTree::SetRoot( I root ) -{ - // Resetting the root while it's got stuff in it is bad... - Assert( m_Root == InvalidIndex() ); - m_Root = root; -} - - -//----------------------------------------------------------------------------- -// Links a node after a particular node -//----------------------------------------------------------------------------- -template -void CUtlNTree::LinkChildAfter( I parent, I after, I elem ) -{ - Assert( IsInTree(elem) ); - - // Unlink it if it's in the list at the moment - Unlink(elem); - - Node_t& newElem = InternalNode(elem); - newElem.m_Parent = parent; - newElem.m_PrevSibling = after; - if ( after != INVALID_NTREE_IDX ) - { - Node_t& prevSiblingNode = InternalNode( after ); - newElem.m_NextSibling = prevSiblingNode.m_NextSibling; - prevSiblingNode.m_NextSibling = elem; - } - else - { - if ( parent != INVALID_NTREE_IDX ) - { - Node_t& parentNode = InternalNode( parent ); - newElem.m_NextSibling = parentNode.m_FirstChild; - parentNode.m_FirstChild = elem; - } - else - { - newElem.m_NextSibling = m_Root; - if ( m_Root != INVALID_NTREE_IDX ) - { - Node_t& rootNode = InternalNode( m_Root ); - rootNode.m_PrevSibling = elem; - } - m_Root = elem; - } - } - - if ( newElem.m_NextSibling != INVALID_NTREE_IDX ) - { - Node_t& nextSiblingNode = InternalNode( newElem.m_NextSibling ); - nextSiblingNode.m_PrevSibling = elem; - } -} - - -//----------------------------------------------------------------------------- -// Links a node before a particular node -//----------------------------------------------------------------------------- -template -void CUtlNTree::LinkChildBefore( I parent, I before, I elem ) -{ - Assert( IsValidIndex(elem) ); - - if ( before != INVALID_NTREE_IDX ) - { - LinkChildAfter( parent, InternalNode( before ).m_PrevSibling, elem ); - return; - } - - // NOTE: I made the choice to do an O(n) operation here - // instead of store more data per node (LastChild). - // This might not be the right choice. Revisit if we get perf problems. - I after; - if ( parent != INVALID_NTREE_IDX ) - { - after = InternalNode( parent ).m_FirstChild; - } - else - { - after = m_Root; - } - - if ( after == INVALID_NTREE_IDX ) - { - LinkChildAfter( parent, after, elem ); - return; - } - - I next = InternalNode( after ).m_NextSibling; - while ( next != InvalidIndex() ) - { - after = next; - next = InternalNode( next ).m_NextSibling; - } - - LinkChildAfter( parent, after, elem ); -} - - -//----------------------------------------------------------------------------- -// Unlinks a node from the tree -//----------------------------------------------------------------------------- -template -void CUtlNTree::Unlink( I elem ) -{ - Assert( IsInTree(elem) ); - - Node_t *pOldNode = &InternalNode( elem ); - - // If we're the first guy, reset the head - // otherwise, make our previous node's next pointer = our next - if ( pOldNode->m_PrevSibling != INVALID_NTREE_IDX ) - { - InternalNode( pOldNode->m_PrevSibling ).m_NextSibling = pOldNode->m_NextSibling; - } - else - { - if ( pOldNode->m_Parent != INVALID_NTREE_IDX ) - { - InternalNode( pOldNode->m_Parent ).m_FirstChild = pOldNode->m_NextSibling; - } - else if ( m_Root == elem ) - { - m_Root = pOldNode->m_NextSibling; - } - } - - // If we're the last guy, reset the tail - // otherwise, make our next node's prev pointer = our prev - if ( pOldNode->m_NextSibling != INVALID_NTREE_IDX ) - { - InternalNode( pOldNode->m_NextSibling ).m_PrevSibling = pOldNode->m_PrevSibling; - } - - // Unlink everything except children - pOldNode->m_Parent = pOldNode->m_PrevSibling = pOldNode->m_NextSibling = INVALID_NTREE_IDX; -} - - -//----------------------------------------------------------------------------- -// Alloc + link combined -//----------------------------------------------------------------------------- -template -I CUtlNTree::InsertChildBefore( I parent, I before ) -{ - I elem = AllocInternal(); - Construct( &Element( elem ) ); - LinkChildBefore( parent, before, elem ); - return elem; -} - -template -I CUtlNTree::InsertChildAfter( I parent, I after ) -{ - I elem = AllocInternal(); - Construct( &Element( elem ) ); - LinkChildAfter( parent, after, elem ); - return elem; -} - -template -I CUtlNTree::InsertChildBefore( I parent, I before, const T &data ) -{ - I elem = AllocInternal(); - CopyConstruct( &Element( elem ), data ); - LinkChildBefore( parent, before, elem ); - return elem; -} - -template -I CUtlNTree::InsertChildAfter( I parent, I after, const T &data ) -{ - I elem = AllocInternal(); - CopyConstruct( &Element( elem ), data ); - LinkChildAfter( parent, after, elem ); - return elem; -} - - -//----------------------------------------------------------------------------- -// Unlink + free combined -//----------------------------------------------------------------------------- -template -void CUtlNTree::Remove( I elem ) -{ - Unlink( elem ); - Free( elem ); -} - -template -void CUtlNTree::RemoveSubTree( I elem ) -{ - UnlinkSubTree( elem ); - Free( elem ); -} - - -#endif // UTLNTREE_H diff --git a/public/tier1/utlobjectreference.h b/public/tier1/utlobjectreference.h deleted file mode 100644 index 5ec974cf1..000000000 --- a/public/tier1/utlobjectreference.h +++ /dev/null @@ -1,165 +0,0 @@ -//===== Copyright 1996-2006, Valve Corporation, All rights reserved. ======// -// -// $Revision: $ -// $NoKeywords: $ -//===========================================================================// - -#ifndef UTLOBJECTREFERENCE_H -#define UTLOBJECTREFERENCE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/utlintrusivelist.h" -#include "mathlib/mathlib.h" - - -// Purpose: class for keeping track of all the references that exist to an object. When the object -// being referenced is freed, all of the references pointing at it will become null. -// -// To Use: -// Add a DECLARE_REFERENCED_CLASS to the class that you want to use CutlReferences with. -// Replace pointers to that class with CUtlReferences. -// Check these references for null in appropriate places. -// -// NOTE : You can still happily use pointers instead of references where you want to - these -// pointers will not magically become null like references would, but if you know no one is going -// to delete the underlying object during a partcular section of code, it doesn't -// matter. Basically, CUtlReferences don't rely on every use of an object using one. - - - - -template class CUtlReference -{ -public: - FORCEINLINE CUtlReference(void) - { - m_pNext = m_pPrev = NULL; - m_pObject = NULL; - } - - FORCEINLINE CUtlReference(T *pObj) - { - m_pNext = m_pPrev = NULL; - AddRef( pObj ); - } - - FORCEINLINE ~CUtlReference(void) - { - KillRef(); - } - - FORCEINLINE void Set(T *pObj) - { - if ( m_pObject != pObj ) - { - KillRef(); - AddRef( pObj ); - } - } - - FORCEINLINE T * operator()(void) const - { - return m_pObject; - } - - FORCEINLINE operator T*() - { - return m_pObject; - } - - FORCEINLINE operator const T*() const - { - return m_pObject; - } - - FORCEINLINE T* operator->() - { - return m_pObject; - } - - FORCEINLINE const T* operator->() const - { - return m_pObject; - } - - FORCEINLINE CUtlReference &operator=( const CUtlReference& otherRef ) - { - Set( otherRef.m_pObject ); - return *this; - } - - FORCEINLINE CUtlReference &operator=( T *pObj ) - { - Set( pObj ); - return *this; - } - - - FORCEINLINE bool operator==( const CUtlReference& o ) const - { - return ( o.m_pObject == m_pObject ); - } - -public: - CUtlReference *m_pNext; - CUtlReference *m_pPrev; - - T *m_pObject; - - FORCEINLINE void AddRef( T *pObj ) - { - m_pObject = pObj; - if ( pObj ) - { - pObj->m_References.AddToHead( this ); - } - } - - FORCEINLINE void KillRef(void) - { - if ( m_pObject ) - { - m_pObject->m_References.RemoveNode( this ); - m_pObject = NULL; - } - } - -}; - -template class CUtlReferenceList : public CUtlIntrusiveDList< CUtlReference > -{ -public: - ~CUtlReferenceList( void ) - { - CUtlReference *i = CUtlIntrusiveDList >::m_pHead; - while( i ) - { - CUtlReference *n = i->m_pNext; - i->m_pNext = NULL; - i->m_pPrev = NULL; - i->m_pObject = NULL; - i = n; - } - CUtlIntrusiveDList >::m_pHead = NULL; - } -}; - - -//----------------------------------------------------------------------------- -// Put this macro in classes that are referenced by CUtlReference -//----------------------------------------------------------------------------- -#define DECLARE_REFERENCED_CLASS( _className ) \ - private: \ - CUtlReferenceList< _className > m_References; \ - template friend class CUtlReference; - - -#endif - - - - - diff --git a/public/tier1/utlpriorityqueue.h b/public/tier1/utlpriorityqueue.h deleted file mode 100644 index 92f20c11a..000000000 --- a/public/tier1/utlpriorityqueue.h +++ /dev/null @@ -1,198 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef UTLPRIORITYQUEUE_H -#define UTLPRIORITYQUEUE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "utlvector.h" - -// T is the type stored in the queue, it must include the priority -// The head of the list contains the element with GREATEST priority -// configure the LessFunc_t to get the desired queue order -template< class T > -class CUtlPriorityQueue -{ -public: - // Less func typedef - // Returns true if the first parameter is "less priority" than the second - // Items that are "less priority" sort toward the tail of the queue - typedef bool (*LessFunc_t)( T const&, T const& ); - - typedef T ElemType_t; - - // constructor: lessfunc is required, but may be set after the constructor with - // SetLessFunc - CUtlPriorityQueue( int growSize = 0, int initSize = 0, LessFunc_t lessfunc = 0 ); - CUtlPriorityQueue( T *pMemory, int numElements, LessFunc_t lessfunc = 0 ); - - // gets particular elements - inline T const& ElementAtHead() const { return m_heap.Element(0); } - - inline bool IsValidIndex(int index) { return m_heap.IsValidIndex(index); } - - // O(lgn) to rebalance the heap - void RemoveAtHead(); - void RemoveAt( int index ); - - // O(lgn) to rebalance heap - void Insert( T const &element ); - // Sets the less func - void SetLessFunc( LessFunc_t func ); - - // Returns the count of elements in the queue - inline int Count() const { return m_heap.Count(); } - - // doesn't deallocate memory - void RemoveAll() { m_heap.RemoveAll(); } - - // Memory deallocation - void Purge() { m_heap.Purge(); } - - inline const T & Element( int index ) const { return m_heap.Element(index); } - -protected: - CUtlVector m_heap; - - void Swap( int index1, int index2 ); - - // Used for sorting. - LessFunc_t m_LessFunc; -}; - -template< class T > -inline CUtlPriorityQueue::CUtlPriorityQueue( int growSize, int initSize, LessFunc_t lessfunc ) : - m_heap(growSize, initSize), m_LessFunc(lessfunc) -{ -} - -template< class T > -inline CUtlPriorityQueue::CUtlPriorityQueue( T *pMemory, int numElements, LessFunc_t lessfunc ) : - m_heap(pMemory, numElements), m_LessFunc(lessfunc) -{ -} - -template -void CUtlPriorityQueue::RemoveAtHead() -{ - m_heap.FastRemove( 0 ); - int index = 0; - - int count = Count(); - if ( !count ) - return; - - int half = count/2; - int larger = index; - while ( index < half ) - { - int child = ((index+1) * 2) - 1; // if we wasted an element, this math would be more compact (1 based array) - if ( child < count ) - { - // Item has been filtered down to its proper place, terminate. - if ( m_LessFunc( m_heap[index], m_heap[child] ) ) - { - // mark the potential swap and check the other child - larger = child; - } - } - // go to sibling - child++; - if ( child < count ) - { - // If this child is larger, swap it instead - if ( m_LessFunc( m_heap[larger], m_heap[child] ) ) - larger = child; - } - - if ( larger == index ) - break; - - // swap with the larger child - Swap( index, larger ); - index = larger; - } -} - - -template -void CUtlPriorityQueue::RemoveAt( int index ) -{ - Assert(m_heap.IsValidIndex(index)); - m_heap.FastRemove( index ); - - int count = Count(); - if ( !count ) - return; - - int half = count/2; - int larger = index; - while ( index < half ) - { - int child = ((index+1) * 2) - 1; // if we wasted an element, this math would be more compact (1 based array) - if ( child < count ) - { - // Item has been filtered down to its proper place, terminate. - if ( m_LessFunc( m_heap[index], m_heap[child] ) ) - { - // mark the potential swap and check the other child - larger = child; - } - } - // go to sibling - child++; - if ( child < count ) - { - // If this child is larger, swap it instead - if ( m_LessFunc( m_heap[larger], m_heap[child] ) ) - larger = child; - } - - if ( larger == index ) - break; - - // swap with the larger child - Swap( index, larger ); - index = larger; - } -} - -template -void CUtlPriorityQueue::Insert( T const &element ) -{ - int index = m_heap.AddToTail(); - m_heap[index] = element; - - while ( index != 0 ) - { - int parent = ((index+1) / 2) - 1; - if ( m_LessFunc( m_heap[index], m_heap[parent] ) ) - break; - - // swap with parent and repeat - Swap( parent, index ); - index = parent; - } -} - -template -void CUtlPriorityQueue::Swap( int index1, int index2 ) -{ - T tmp = m_heap[index1]; - m_heap[index1] = m_heap[index2]; - m_heap[index2] = tmp; -} - -template -void CUtlPriorityQueue::SetLessFunc( LessFunc_t lessfunc ) -{ - m_LessFunc = lessfunc; -} - -#endif // UTLPRIORITYQUEUE_H diff --git a/public/tier1/utlqueue.h b/public/tier1/utlqueue.h deleted file mode 100644 index 3ea43780e..000000000 --- a/public/tier1/utlqueue.h +++ /dev/null @@ -1,114 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef UTLQUEUE_H -#define UTLQUEUE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "utlvector.h" - -// T is the type stored in the stack -template< class T > -class CUtlQueue -{ -public: - - // constructor: lessfunc is required, but may be set after the constructor with - // SetLessFunc - CUtlQueue( int growSize = 0, int initSize = 0 ); - CUtlQueue( T *pMemory, int numElements ); - - // return the item from the front of the queue and delete it - T const& RemoveAtHead(); - // return the item from the end of the queue and delete it - T const& RemoveAtTail(); - - // return item at the front of the queue - T const& Head(); - // return item at the end of the queue - T const& Tail(); - - // put a new item on the stack - void Insert( T const &element ); - - // checks if an element of this value already exists on the stack, returns true if it does - bool Check( T const element ); - - // Returns the count of elements in the stack - int Count() const { return m_heap.Count(); } - - // doesn't deallocate memory - void RemoveAll() { m_heap.RemoveAll(); } - - // Memory deallocation - void Purge() { m_heap.Purge(); } - -protected: - CUtlVector m_heap; - T m_current; -}; - -template< class T > -inline CUtlQueue::CUtlQueue( int growSize, int initSize ) : - m_heap(growSize, initSize) -{ -} - -template< class T > -inline CUtlQueue::CUtlQueue( T *pMemory, int numElements ) : - m_heap(pMemory, numElements) -{ -} - -template -inline T const& CUtlQueue::RemoveAtHead() -{ - m_current = m_heap[0]; - m_heap.Remove((int)0); - return m_current; -} - -template -inline T const& CUtlQueue::RemoveAtTail() -{ - m_current = m_heap[ m_heap.Count() - 1 ]; - m_heap.Remove((int)(m_heap.Count() - 1)); - return m_current; -} - -template -inline T const& CUtlQueue::Head() -{ - m_current = m_heap[0]; - return m_current; -} - -template -inline T const& CUtlQueue::Tail() -{ - m_current = m_heap[ m_heap.Count() - 1 ]; - return m_current; -} - -template -void CUtlQueue::Insert( T const &element ) -{ - int index = m_heap.AddToTail(); - m_heap[index] = element; -} - -template -bool CUtlQueue::Check( T const element ) -{ - int index = m_heap.Find(element); - return ( index != -1 ); -} - - -#endif // UTLQUEUE_H diff --git a/public/tier1/utlrbtree.h b/public/tier1/utlrbtree.h deleted file mode 100644 index 5d0cc653c..000000000 --- a/public/tier1/utlrbtree.h +++ /dev/null @@ -1,1561 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Header: $ -// $NoKeywords: $ -//=============================================================================// - -#ifndef UTLRBTREE_H -#define UTLRBTREE_H - -#include "tier1/utlmemory.h" -#include "tier1/utlfixedmemory.h" -#include "tier1/utlblockmemory.h" - -//----------------------------------------------------------------------------- -// Tool to generate a default compare function for any type that implements -// operator<, including all simple types -//----------------------------------------------------------------------------- - -template -class CDefOps -{ -public: - static bool LessFunc( const T &lhs, const T &rhs ) { return ( lhs < rhs ); } -}; - -#define DefLessFunc( type ) CDefOps< type >::LessFunc - -//------------------------------------- - -inline bool StringLessThan( const char * const &lhs, const char * const &rhs) { return ( strcmp( lhs, rhs) < 0 ); } -inline bool CaselessStringLessThan( const char * const &lhs, const char * const &rhs ) { return ( stricmp( lhs, rhs) < 0 ); } - -// Same as CaselessStringLessThan, but it ignores differences in / and \. -inline bool CaselessStringLessThanIgnoreSlashes( const char * const &lhs, const char * const &rhs ) -{ - const char *pa = lhs; - const char *pb = rhs; - while ( *pa && *pb ) - { - char a = *pa; - char b = *pb; - - // Check for dir slashes. - if ( a == '/' || a == '\\' ) - { - if ( b != '/' && b != '\\' ) - return ('/' < b); - } - else - { - if ( a >= 'a' && a <= 'z' ) - a = 'A' + (a - 'a'); - - if ( b >= 'a' && b <= 'z' ) - b = 'A' + (b - 'a'); - - if ( a > b ) - return false; - else if ( a < b ) - return true; - } - ++pa; - ++pb; - } - - return false; -} - -//------------------------------------- -// inline these two templates to stop multiple definitions of the same code -template <> inline bool CDefOps::LessFunc( const char * const &lhs, const char * const &rhs ) { return StringLessThan( lhs, rhs ); } -template <> inline bool CDefOps::LessFunc( char * const &lhs, char * const &rhs ) { return StringLessThan( lhs, rhs ); } - -//------------------------------------- - -template -void SetDefLessFunc( RBTREE_T &RBTree ) -{ -#ifdef _WIN32 - RBTree.SetLessFunc( DefLessFunc( RBTREE_T::KeyType_t ) ); -#elif defined _LINUX || defined __APPLE__ - RBTree.SetLessFunc( DefLessFunc( typename RBTREE_T::KeyType_t ) ); -#endif -} - -//----------------------------------------------------------------------------- -// A red-black binary search tree -//----------------------------------------------------------------------------- - -template < class I > -struct UtlRBTreeLinks_t -{ - I m_Left; - I m_Right; - I m_Parent; - I m_Tag; -}; - -template < class T, class I > -struct UtlRBTreeNode_t : public UtlRBTreeLinks_t< I > -{ - T m_Data; -}; - -template < class T, class I = unsigned short, typename L = bool (*)( const T &, const T & ), class M = CUtlMemory< UtlRBTreeNode_t< T, I >, I > > -class CUtlRBTree -{ -public: - - typedef T KeyType_t; - typedef T ElemType_t; - typedef I IndexType_t; - - // Less func typedef - // Returns true if the first parameter is "less" than the second - typedef L LessFunc_t; - - // constructor, destructor - // Left at growSize = 0, the memory will first allocate 1 element and double in size - // at each increment. - // LessFunc_t is required, but may be set after the constructor using SetLessFunc() below - CUtlRBTree( int growSize = 0, int initSize = 0, const LessFunc_t &lessfunc = 0 ); - CUtlRBTree( const LessFunc_t &lessfunc ); - ~CUtlRBTree( ); - - void EnsureCapacity( int num ); - - void CopyFrom( const CUtlRBTree &other ); - - // gets particular elements - T& Element( I i ); - T const &Element( I i ) const; - T& operator[]( I i ); - T const &operator[]( I i ) const; - - // Gets the root - I Root() const; - - // Num elements - unsigned int Count() const; - - // Max "size" of the vector - // it's not generally safe to iterate from index 0 to MaxElement()-1 - // it IS safe to do so when using CUtlMemory as the allocator, - // but we should really remove patterns using this anyways, for safety and generality - I MaxElement() const; - - // Gets the children - I Parent( I i ) const; - I LeftChild( I i ) const; - I RightChild( I i ) const; - - // Tests if a node is a left or right child - bool IsLeftChild( I i ) const; - bool IsRightChild( I i ) const; - - // Tests if root or leaf - bool IsRoot( I i ) const; - bool IsLeaf( I i ) const; - - // Checks if a node is valid and in the tree - bool IsValidIndex( I i ) const; - - // Checks if the tree as a whole is valid - bool IsValid() const; - - // Invalid index - static I InvalidIndex(); - - // returns the tree depth (not a very fast operation) - int Depth( I node ) const; - int Depth() const; - - // Sets the less func - void SetLessFunc( const LessFunc_t &func ); - - // Allocation method - I NewNode(); - - // Insert method (inserts in order) - I Insert( T const &insert ); - void Insert( const T *pArray, int nItems ); - I InsertIfNotFound( T const &insert ); - - // Find method - I Find( T const &search ) const; - - // Remove methods - void RemoveAt( I i ); - bool Remove( T const &remove ); - void RemoveAll( ); - void Purge(); - - // Allocation, deletion - void FreeNode( I i ); - - // Iteration - I FirstInorder() const; - I NextInorder( I i ) const; - I PrevInorder( I i ) const; - I LastInorder() const; - - I FirstPreorder() const; - I NextPreorder( I i ) const; - I PrevPreorder( I i ) const; - I LastPreorder( ) const; - - I FirstPostorder() const; - I NextPostorder( I i ) const; - - // If you change the search key, this can be used to reinsert the - // element into the tree. - void Reinsert( I elem ); - - // swap in place - void Swap( CUtlRBTree< T, I, L > &that ); - -private: - // Can't copy the tree this way! - CUtlRBTree& operator=( const CUtlRBTree &other ); - -protected: - enum NodeColor_t - { - RED = 0, - BLACK - }; - - typedef UtlRBTreeNode_t< T, I > Node_t; - typedef UtlRBTreeLinks_t< I > Links_t; - - // Sets the children - void SetParent( I i, I parent ); - void SetLeftChild( I i, I child ); - void SetRightChild( I i, I child ); - void LinkToParent( I i, I parent, bool isLeft ); - - // Gets at the links - Links_t const &Links( I i ) const; - Links_t &Links( I i ); - - // Checks if a link is red or black - bool IsRed( I i ) const; - bool IsBlack( I i ) const; - - // Sets/gets node color - NodeColor_t Color( I i ) const; - void SetColor( I i, NodeColor_t c ); - - // operations required to preserve tree balance - void RotateLeft(I i); - void RotateRight(I i); - void InsertRebalance(I i); - void RemoveRebalance(I i); - - // Insertion, removal - I InsertAt( I parent, bool leftchild ); - - // copy constructors not allowed - CUtlRBTree( CUtlRBTree const &tree ); - - // Inserts a node into the tree, doesn't copy the data in. - void FindInsertionPosition( T const &insert, I &parent, bool &leftchild ); - - // Remove and add back an element in the tree. - void Unlink( I elem ); - void Link( I elem ); - - // Used for sorting. - LessFunc_t m_LessFunc; - - M m_Elements; - I m_Root; - I m_NumElements; - I m_FirstFree; - typename M::Iterator_t m_LastAlloc; // the last index allocated - - Node_t* m_pElements; - - FORCEINLINE M const &Elements( void ) const - { - return m_Elements; - } - - - void ResetDbgInfo() - { - m_pElements = (Node_t*)m_Elements.Base(); - } -}; - -// this is kind of ugly, but until C++ gets templatized typedefs in C++0x, it's our only choice -template < class T, class I = int, typename L = bool (*)( const T &, const T & ) > -class CUtlFixedRBTree : public CUtlRBTree< T, I, L, CUtlFixedMemory< UtlRBTreeNode_t< T, I > > > -{ -public: - - typedef L LessFunc_t; - - CUtlFixedRBTree( int growSize = 0, int initSize = 0, const LessFunc_t &lessfunc = 0 ) - : CUtlRBTree< T, I, L, CUtlFixedMemory< UtlRBTreeNode_t< T, I > > >( growSize, initSize, lessfunc ) {} - CUtlFixedRBTree( const LessFunc_t &lessfunc ) - : CUtlRBTree< T, I, L, CUtlFixedMemory< UtlRBTreeNode_t< T, I > > >( lessfunc ) {} - - bool IsValidIndex( I i ) const - { - if ( !CUtlRBTree::Elements().IsIdxValid( i ) ) - return false; - -#ifdef _DEBUG // it's safe to skip this here, since the only way to get indices after m_LastAlloc is to use MaxElement() - if ( CUtlRBTree::Elements().IsIdxAfter( i, this->m_LastAlloc ) ) - { - Assert( 0 ); - return false; // don't read values that have been allocated, but not constructed - } -#endif - - return LeftChild(i) != i; - } - -protected: - void ResetDbgInfo() {} - -private: - // this doesn't make sense for fixed rbtrees, since there's no useful max pointer, and the index space isn't contiguous anyways - I MaxElement() const; -}; - -// this is kind of ugly, but until C++ gets templatized typedefs in C++0x, it's our only choice -template < class T, class I = unsigned short, typename L = bool (*)( const T &, const T & ) > -class CUtlBlockRBTree : public CUtlRBTree< T, I, L, CUtlBlockMemory< UtlRBTreeNode_t< T, I >, I > > -{ -public: - typedef L LessFunc_t; - CUtlBlockRBTree( int growSize = 0, int initSize = 0, const LessFunc_t &lessfunc = 0 ) - : CUtlRBTree< T, I, L, CUtlBlockMemory< UtlRBTreeNode_t< T, I >, I > >( growSize, initSize, lessfunc ) {} - CUtlBlockRBTree( const LessFunc_t &lessfunc ) - : CUtlRBTree< T, I, L, CUtlBlockMemory< UtlRBTreeNode_t< T, I >, I > >( lessfunc ) {} -protected: - void ResetDbgInfo() {} -}; - - -//----------------------------------------------------------------------------- -// constructor, destructor -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -inline CUtlRBTree::CUtlRBTree( int growSize, int initSize, const LessFunc_t &lessfunc ) : -m_LessFunc( lessfunc ), -m_Elements( growSize, initSize ), -m_Root( InvalidIndex() ), -m_NumElements( 0 ), -m_FirstFree( InvalidIndex() ), -m_LastAlloc( m_Elements.InvalidIterator() ) -{ - ResetDbgInfo(); -} - -template < class T, class I, typename L, class M > -inline CUtlRBTree::CUtlRBTree( const LessFunc_t &lessfunc ) : -m_LessFunc( lessfunc ), -m_Elements( 0, 0 ), -m_Root( InvalidIndex() ), -m_NumElements( 0 ), -m_FirstFree( InvalidIndex() ), -m_LastAlloc( m_Elements.InvalidIterator() ) -{ - ResetDbgInfo(); -} - -template < class T, class I, typename L, class M > -inline CUtlRBTree::~CUtlRBTree() -{ - Purge(); -} - -template < class T, class I, typename L, class M > -inline void CUtlRBTree::EnsureCapacity( int num ) -{ - m_Elements.EnsureCapacity( num ); -} - -template < class T, class I, typename L, class M > -inline void CUtlRBTree::CopyFrom( const CUtlRBTree &other ) -{ - Purge(); - m_Elements.EnsureCapacity( other.m_Elements.Count() ); - memcpy( m_Elements.Base(), other.m_Elements.Base(), other.m_Elements.Count() * sizeof( T ) ); - m_LessFunc = other.m_LessFunc; - m_Root = other.m_Root; - m_NumElements = other.m_NumElements; - m_FirstFree = other.m_FirstFree; - m_LastAlloc = other.m_LastAlloc; - ResetDbgInfo(); -} - -//----------------------------------------------------------------------------- -// gets particular elements -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -inline T &CUtlRBTree::Element( I i ) -{ - return m_Elements[i].m_Data; -} - -template < class T, class I, typename L, class M > -inline T const &CUtlRBTree::Element( I i ) const -{ - return m_Elements[i].m_Data; -} - -template < class T, class I, typename L, class M > -inline T &CUtlRBTree::operator[]( I i ) -{ - return Element(i); -} - -template < class T, class I, typename L, class M > -inline T const &CUtlRBTree::operator[]( I i ) const -{ - return Element(i); -} - -//----------------------------------------------------------------------------- -// -// various accessors -// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// Gets the root -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -inline I CUtlRBTree::Root() const -{ - return m_Root; -} - -//----------------------------------------------------------------------------- -// Num elements -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -inline unsigned int CUtlRBTree::Count() const -{ - return (unsigned int)m_NumElements; -} - -//----------------------------------------------------------------------------- -// Max "size" of the vector -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -inline I CUtlRBTree::MaxElement() const -{ - return ( I )m_Elements.NumAllocated(); -} - - -//----------------------------------------------------------------------------- -// Gets the children -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -inline I CUtlRBTree::Parent( I i ) const -{ - return Links(i).m_Parent; -} - -template < class T, class I, typename L, class M > -inline I CUtlRBTree::LeftChild( I i ) const -{ - return Links(i).m_Left; -} - -template < class T, class I, typename L, class M > -inline I CUtlRBTree::RightChild( I i ) const -{ - return Links(i).m_Right; -} - -//----------------------------------------------------------------------------- -// Tests if a node is a left or right child -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -inline bool CUtlRBTree::IsLeftChild( I i ) const -{ - return LeftChild(Parent(i)) == i; -} - -template < class T, class I, typename L, class M > -inline bool CUtlRBTree::IsRightChild( I i ) const -{ - return RightChild(Parent(i)) == i; -} - - -//----------------------------------------------------------------------------- -// Tests if root or leaf -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -inline bool CUtlRBTree::IsRoot( I i ) const -{ - return i == m_Root; -} - -template < class T, class I, typename L, class M > -inline bool CUtlRBTree::IsLeaf( I i ) const -{ - return (LeftChild(i) == InvalidIndex()) && (RightChild(i) == InvalidIndex()); -} - - -//----------------------------------------------------------------------------- -// Checks if a node is valid and in the tree -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -inline bool CUtlRBTree::IsValidIndex( I i ) const -{ - if ( !m_Elements.IsIdxValid( i ) ) - return false; - - if ( m_Elements.IsIdxAfter( i, m_LastAlloc ) ) - return false; // don't read values that have been allocated, but not constructed - - return LeftChild(i) != i; -} - - -//----------------------------------------------------------------------------- -// Invalid index -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -inline I CUtlRBTree::InvalidIndex() -{ - return ( I )M::InvalidIndex(); -} - - -//----------------------------------------------------------------------------- -// returns the tree depth (not a very fast operation) -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -inline int CUtlRBTree::Depth() const -{ - return Depth(Root()); -} - -//----------------------------------------------------------------------------- -// Sets the children -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -inline void CUtlRBTree::SetParent( I i, I parent ) -{ - Links(i).m_Parent = parent; -} - -template < class T, class I, typename L, class M > -inline void CUtlRBTree::SetLeftChild( I i, I child ) -{ - Links(i).m_Left = child; -} - -template < class T, class I, typename L, class M > -inline void CUtlRBTree::SetRightChild( I i, I child ) -{ - Links(i).m_Right = child; -} - -//----------------------------------------------------------------------------- -// Gets at the links -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -inline typename CUtlRBTree::Links_t const &CUtlRBTree::Links( I i ) const -{ - // Sentinel node, makes life easier - static Links_t s_Sentinel = - { - InvalidIndex(), InvalidIndex(), InvalidIndex(), CUtlRBTree::BLACK - }; - - return (i != InvalidIndex()) ? *(Links_t*)&m_Elements[i] : *(Links_t*)&s_Sentinel; -} - -template < class T, class I, typename L, class M > -inline typename CUtlRBTree::Links_t &CUtlRBTree::Links( I i ) -{ - Assert(i != InvalidIndex()); - return *(Links_t *)&m_Elements[i]; -} - -//----------------------------------------------------------------------------- -// Checks if a link is red or black -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -inline bool CUtlRBTree::IsRed( I i ) const -{ - return (Links(i).m_Tag == RED); -} - -template < class T, class I, typename L, class M > -inline bool CUtlRBTree::IsBlack( I i ) const -{ - return (Links(i).m_Tag == BLACK); -} - - -//----------------------------------------------------------------------------- -// Sets/gets node color -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -inline typename CUtlRBTree::NodeColor_t CUtlRBTree::Color( I i ) const -{ - return (NodeColor_t)Links(i).m_Tag; -} - -template < class T, class I, typename L, class M > -inline void CUtlRBTree::SetColor( I i, typename CUtlRBTree::NodeColor_t c ) -{ - Links(i).m_Tag = (I)c; -} - -//----------------------------------------------------------------------------- -// Allocates/ deallocates nodes -//----------------------------------------------------------------------------- -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4389) // '==' : signed/unsigned mismatch -#endif -template < class T, class I, typename L, class M > -I CUtlRBTree::NewNode() -{ - I elem; - - // Nothing in the free list; add. - if ( m_FirstFree == InvalidIndex() ) - { - Assert( m_Elements.IsValidIterator( m_LastAlloc ) || m_NumElements == 0 ); - typename M::Iterator_t it = m_Elements.IsValidIterator( m_LastAlloc ) ? m_Elements.Next( m_LastAlloc ) : m_Elements.First(); - if ( !m_Elements.IsValidIterator( it ) ) - { - MEM_ALLOC_CREDIT_CLASS(); - m_Elements.Grow(); - - it = m_Elements.IsValidIterator( m_LastAlloc ) ? m_Elements.Next( m_LastAlloc ) : m_Elements.First(); - - Assert( m_Elements.IsValidIterator( it ) ); - if ( !m_Elements.IsValidIterator( it ) ) - { - Error( "CUtlRBTree overflow!\n" ); - } - } - m_LastAlloc = it; - elem = m_Elements.GetIndex( m_LastAlloc ); - Assert( m_Elements.IsValidIterator( m_LastAlloc ) ); - } - else - { - elem = m_FirstFree; - m_FirstFree = Links( m_FirstFree ).m_Right; - } - -#ifdef _DEBUG - // reset links to invalid.... - Links_t &node = Links( elem ); - node.m_Left = node.m_Right = node.m_Parent = InvalidIndex(); -#endif - - Construct( &Element( elem ) ); - ResetDbgInfo(); - - return elem; -} -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -template < class T, class I, typename L, class M > -void CUtlRBTree::FreeNode( I i ) -{ - Assert( IsValidIndex(i) && (i != InvalidIndex()) ); - Destruct( &Element(i) ); - SetLeftChild( i, i ); // indicates it's in not in the tree - SetRightChild( i, m_FirstFree ); - m_FirstFree = i; -} - - -//----------------------------------------------------------------------------- -// Rotates node i to the left -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -void CUtlRBTree::RotateLeft(I elem) -{ - I rightchild = RightChild(elem); - SetRightChild( elem, LeftChild(rightchild) ); - if (LeftChild(rightchild) != InvalidIndex()) - SetParent( LeftChild(rightchild), elem ); - - if (rightchild != InvalidIndex()) - SetParent( rightchild, Parent(elem) ); - if (!IsRoot(elem)) - { - if (IsLeftChild(elem)) - SetLeftChild( Parent(elem), rightchild ); - else - SetRightChild( Parent(elem), rightchild ); - } - else - m_Root = rightchild; - - SetLeftChild( rightchild, elem ); - if (elem != InvalidIndex()) - SetParent( elem, rightchild ); -} - - -//----------------------------------------------------------------------------- -// Rotates node i to the right -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -void CUtlRBTree::RotateRight(I elem) -{ - I leftchild = LeftChild(elem); - SetLeftChild( elem, RightChild(leftchild) ); - if (RightChild(leftchild) != InvalidIndex()) - SetParent( RightChild(leftchild), elem ); - - if (leftchild != InvalidIndex()) - SetParent( leftchild, Parent(elem) ); - if (!IsRoot(elem)) - { - if (IsRightChild(elem)) - SetRightChild( Parent(elem), leftchild ); - else - SetLeftChild( Parent(elem), leftchild ); - } - else - m_Root = leftchild; - - SetRightChild( leftchild, elem ); - if (elem != InvalidIndex()) - SetParent( elem, leftchild ); -} - - -//----------------------------------------------------------------------------- -// Rebalances the tree after an insertion -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -void CUtlRBTree::InsertRebalance(I elem) -{ - while ( !IsRoot(elem) && (Color(Parent(elem)) == RED) ) - { - I parent = Parent(elem); - I grandparent = Parent(parent); - - /* we have a violation */ - if (IsLeftChild(parent)) - { - I uncle = RightChild(grandparent); - if (IsRed(uncle)) - { - /* uncle is RED */ - SetColor(parent, BLACK); - SetColor(uncle, BLACK); - SetColor(grandparent, RED); - elem = grandparent; - } - else - { - /* uncle is BLACK */ - if (IsRightChild(elem)) - { - /* make x a left child, will change parent and grandparent */ - elem = parent; - RotateLeft(elem); - parent = Parent(elem); - grandparent = Parent(parent); - } - /* recolor and rotate */ - SetColor(parent, BLACK); - SetColor(grandparent, RED); - RotateRight(grandparent); - } - } - else - { - /* mirror image of above code */ - I uncle = LeftChild(grandparent); - if (IsRed(uncle)) - { - /* uncle is RED */ - SetColor(parent, BLACK); - SetColor(uncle, BLACK); - SetColor(grandparent, RED); - elem = grandparent; - } - else - { - /* uncle is BLACK */ - if (IsLeftChild(elem)) - { - /* make x a right child, will change parent and grandparent */ - elem = parent; - RotateRight(parent); - parent = Parent(elem); - grandparent = Parent(parent); - } - /* recolor and rotate */ - SetColor(parent, BLACK); - SetColor(grandparent, RED); - RotateLeft(grandparent); - } - } - } - SetColor( m_Root, BLACK ); -} - - -//----------------------------------------------------------------------------- -// Insert a node into the tree -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -I CUtlRBTree::InsertAt( I parent, bool leftchild ) -{ - I i = NewNode(); - LinkToParent( i, parent, leftchild ); - ++m_NumElements; - - Assert(IsValid()); - - return i; -} - -template < class T, class I, typename L, class M > -void CUtlRBTree::LinkToParent( I i, I parent, bool isLeft ) -{ - Links_t &elem = Links(i); - elem.m_Parent = parent; - elem.m_Left = elem.m_Right = InvalidIndex(); - elem.m_Tag = RED; - - /* insert node in tree */ - if (parent != InvalidIndex()) - { - if (isLeft) - Links(parent).m_Left = i; - else - Links(parent).m_Right = i; - } - else - { - m_Root = i; - } - - InsertRebalance(i); -} - -//----------------------------------------------------------------------------- -// Rebalance the tree after a deletion -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -void CUtlRBTree::RemoveRebalance(I elem) -{ - while (elem != m_Root && IsBlack(elem)) - { - I parent = Parent(elem); - - // If elem is the left child of the parent - if (elem == LeftChild(parent)) - { - // Get our sibling - I sibling = RightChild(parent); - if (IsRed(sibling)) - { - SetColor(sibling, BLACK); - SetColor(parent, RED); - RotateLeft(parent); - - // We may have a new parent now - parent = Parent(elem); - sibling = RightChild(parent); - } - if ( (IsBlack(LeftChild(sibling))) && (IsBlack(RightChild(sibling))) ) - { - if (sibling != InvalidIndex()) - SetColor(sibling, RED); - elem = parent; - } - else - { - if (IsBlack(RightChild(sibling))) - { - SetColor(LeftChild(sibling), BLACK); - SetColor(sibling, RED); - RotateRight(sibling); - - // rotation may have changed this - parent = Parent(elem); - sibling = RightChild(parent); - } - SetColor( sibling, Color(parent) ); - SetColor( parent, BLACK ); - SetColor( RightChild(sibling), BLACK ); - RotateLeft( parent ); - elem = m_Root; - } - } - else - { - // Elem is the right child of the parent - I sibling = LeftChild(parent); - if (IsRed(sibling)) - { - SetColor(sibling, BLACK); - SetColor(parent, RED); - RotateRight(parent); - - // We may have a new parent now - parent = Parent(elem); - sibling = LeftChild(parent); - } - if ( (IsBlack(RightChild(sibling))) && (IsBlack(LeftChild(sibling))) ) - { - if (sibling != InvalidIndex()) - SetColor( sibling, RED ); - elem = parent; - } - else - { - if (IsBlack(LeftChild(sibling))) - { - SetColor( RightChild(sibling), BLACK ); - SetColor( sibling, RED ); - RotateLeft( sibling ); - - // rotation may have changed this - parent = Parent(elem); - sibling = LeftChild(parent); - } - SetColor( sibling, Color(parent) ); - SetColor( parent, BLACK ); - SetColor( LeftChild(sibling), BLACK ); - RotateRight( parent ); - elem = m_Root; - } - } - } - SetColor( elem, BLACK ); -} - -template < class T, class I, typename L, class M > -void CUtlRBTree::Unlink( I elem ) -{ - if ( elem != InvalidIndex() ) - { - I x, y; - - if ((LeftChild(elem) == InvalidIndex()) || - (RightChild(elem) == InvalidIndex())) - { - /* y has a NIL node as a child */ - y = elem; - } - else - { - /* find tree successor with a NIL node as a child */ - y = RightChild(elem); - while (LeftChild(y) != InvalidIndex()) - y = LeftChild(y); - } - - /* x is y's only child */ - if (LeftChild(y) != InvalidIndex()) - x = LeftChild(y); - else - x = RightChild(y); - - /* remove y from the parent chain */ - if (x != InvalidIndex()) - SetParent( x, Parent(y) ); - if (!IsRoot(y)) - { - if (IsLeftChild(y)) - SetLeftChild( Parent(y), x ); - else - SetRightChild( Parent(y), x ); - } - else - m_Root = x; - - // need to store this off now, we'll be resetting y's color - NodeColor_t ycolor = Color(y); - if (y != elem) - { - // Standard implementations copy the data around, we cannot here. - // Hook in y to link to the same stuff elem used to. - SetParent( y, Parent(elem) ); - SetRightChild( y, RightChild(elem) ); - SetLeftChild( y, LeftChild(elem) ); - - if (!IsRoot(elem)) - if (IsLeftChild(elem)) - SetLeftChild( Parent(elem), y ); - else - SetRightChild( Parent(elem), y ); - else - m_Root = y; - - if (LeftChild(y) != InvalidIndex()) - SetParent( LeftChild(y), y ); - if (RightChild(y) != InvalidIndex()) - SetParent( RightChild(y), y ); - - SetColor( y, Color(elem) ); - } - - if ((x != InvalidIndex()) && (ycolor == BLACK)) - RemoveRebalance(x); - } -} - -template < class T, class I, typename L, class M > -void CUtlRBTree::Link( I elem ) -{ - if ( elem != InvalidIndex() ) - { - I parent; - bool leftchild; - - FindInsertionPosition( Element( elem ), parent, leftchild ); - - LinkToParent( elem, parent, leftchild ); - - Assert(IsValid()); - } -} - -//----------------------------------------------------------------------------- -// Delete a node from the tree -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -void CUtlRBTree::RemoveAt(I elem) -{ - if ( elem != InvalidIndex() ) - { - Unlink( elem ); - - FreeNode(elem); - --m_NumElements; - - Assert(IsValid()); - } -} - - -//----------------------------------------------------------------------------- -// remove a node in the tree -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > bool CUtlRBTree::Remove( T const &search ) -{ - I node = Find( search ); - if (node != InvalidIndex()) - { - RemoveAt(node); - return true; - } - return false; -} - - -//----------------------------------------------------------------------------- -// Removes all nodes from the tree -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -void CUtlRBTree::RemoveAll() -{ - // Have to do some convoluted stuff to invoke the destructor on all - // valid elements for the multilist case (since we don't have all elements - // connected to each other in a list). - - if ( m_LastAlloc == m_Elements.InvalidIterator() ) - { - Assert( m_Root == InvalidIndex() ); - Assert( m_FirstFree == InvalidIndex() ); - Assert( m_NumElements == 0 ); - return; - } - - for ( typename M::Iterator_t it = m_Elements.First(); it != m_Elements.InvalidIterator(); it = m_Elements.Next( it ) ) - { - I i = m_Elements.GetIndex( it ); - if ( IsValidIndex( i ) ) // skip elements in the free list - { - Destruct( &Element( i ) ); - SetRightChild( i, m_FirstFree ); - SetLeftChild( i, i ); - m_FirstFree = i; - } - - if ( it == m_LastAlloc ) - break; // don't destruct elements that haven't ever been constucted - } - - // Clear everything else out - m_Root = InvalidIndex(); - m_NumElements = 0; - - Assert( IsValid() ); -} - -//----------------------------------------------------------------------------- -// Removes all nodes from the tree and purges memory -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -void CUtlRBTree::Purge() -{ - RemoveAll(); - m_FirstFree = InvalidIndex(); - m_Elements.Purge(); - m_LastAlloc = m_Elements.InvalidIterator(); -} - - -//----------------------------------------------------------------------------- -// iteration -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -I CUtlRBTree::FirstInorder() const -{ - I i = m_Root; - while (LeftChild(i) != InvalidIndex()) - i = LeftChild(i); - return i; -} - -template < class T, class I, typename L, class M > -I CUtlRBTree::NextInorder( I i ) const -{ - Assert(IsValidIndex(i)); - - if (RightChild(i) != InvalidIndex()) - { - i = RightChild(i); - while (LeftChild(i) != InvalidIndex()) - i = LeftChild(i); - return i; - } - - I parent = Parent(i); - while (IsRightChild(i)) - { - i = parent; - if (i == InvalidIndex()) break; - parent = Parent(i); - } - return parent; -} - -template < class T, class I, typename L, class M > -I CUtlRBTree::PrevInorder( I i ) const -{ - Assert(IsValidIndex(i)); - - if (LeftChild(i) != InvalidIndex()) - { - i = LeftChild(i); - while (RightChild(i) != InvalidIndex()) - i = RightChild(i); - return i; - } - - I parent = Parent(i); - while (IsLeftChild(i)) - { - i = parent; - if (i == InvalidIndex()) break; - parent = Parent(i); - } - return parent; -} - -template < class T, class I, typename L, class M > -I CUtlRBTree::LastInorder() const -{ - I i = m_Root; - while (RightChild(i) != InvalidIndex()) - i = RightChild(i); - return i; -} - -template < class T, class I, typename L, class M > -I CUtlRBTree::FirstPreorder() const -{ - return m_Root; -} - -template < class T, class I, typename L, class M > -I CUtlRBTree::NextPreorder( I i ) const -{ - if (LeftChild(i) != InvalidIndex()) - return LeftChild(i); - - if (RightChild(i) != InvalidIndex()) - return RightChild(i); - - I parent = Parent(i); - while( parent != InvalidIndex()) - { - if (IsLeftChild(i) && (RightChild(parent) != InvalidIndex())) - return RightChild(parent); - i = parent; - parent = Parent(parent); - } - return InvalidIndex(); -} - -template < class T, class I, typename L, class M > -I CUtlRBTree::PrevPreorder( I i ) const -{ - Assert(0); // not implemented yet - return InvalidIndex(); -} - -template < class T, class I, typename L, class M > -I CUtlRBTree::LastPreorder() const -{ - I i = m_Root; - while (1) - { - while (RightChild(i) != InvalidIndex()) - i = RightChild(i); - - if (LeftChild(i) != InvalidIndex()) - i = LeftChild(i); - else - break; - } - return i; -} - -template < class T, class I, typename L, class M > -I CUtlRBTree::FirstPostorder() const -{ - I i = m_Root; - while (!IsLeaf(i)) - { - if (LeftChild(i)) - i = LeftChild(i); - else - i = RightChild(i); - } - return i; -} - -template < class T, class I, typename L, class M > -I CUtlRBTree::NextPostorder( I i ) const -{ - I parent = Parent(i); - if (parent == InvalidIndex()) - return InvalidIndex(); - - if (IsRightChild(i)) - return parent; - - if (RightChild(parent) == InvalidIndex()) - return parent; - - i = RightChild(parent); - while (!IsLeaf(i)) - { - if (LeftChild(i)) - i = LeftChild(i); - else - i = RightChild(i); - } - return i; -} - - -template < class T, class I, typename L, class M > -void CUtlRBTree::Reinsert( I elem ) -{ - Unlink( elem ); - Link( elem ); -} - - -//----------------------------------------------------------------------------- -// returns the tree depth (not a very fast operation) -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -int CUtlRBTree::Depth( I node ) const -{ - if (node == InvalidIndex()) - return 0; - - int depthright = Depth( RightChild(node) ); - int depthleft = Depth( LeftChild(node) ); - return MAX(depthright, depthleft) + 1; -} - - -//#define UTLTREE_PARANOID - -//----------------------------------------------------------------------------- -// Makes sure the tree is valid after every operation -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -bool CUtlRBTree::IsValid() const -{ - if ( !Count() ) - return true; - - if ( m_LastAlloc == m_Elements.InvalidIterator() ) - return false; - - if ( !m_Elements.IsIdxValid( Root() ) ) - return false; - - if ( Parent( Root() ) != InvalidIndex() ) - return false; - -#ifdef UTLTREE_PARANOID - - // First check to see that mNumEntries matches reality. - // count items on the free list - int numFree = 0; - for ( int i = m_FirstFree; i != InvalidIndex(); i = RightChild( i ) ) - { - ++numFree; - if ( !m_Elements.IsIdxValid( i ) ) - return false; - } - - // iterate over all elements, looking for validity - // based on the self pointers - int nElements = 0; - int numFree2 = 0; - for ( M::Iterator_t it = m_Elements.First(); it != m_Elements.InvalidIterator(); it = m_Elements.Next( it ) ) - { - I i = m_Elements.GetIndex( it ); - if ( !IsValidIndex( i ) ) - { - ++numFree2; - } - else - { - ++nElements; - - int right = RightChild( i ); - int left = LeftChild( i ); - if ( ( right == left ) && ( right != InvalidIndex() ) ) - return false; - - if ( right != InvalidIndex() ) - { - if ( !IsValidIndex( right ) ) - return false; - if ( Parent( right ) != i ) - return false; - if ( IsRed( i ) && IsRed( right ) ) - return false; - } - - if ( left != InvalidIndex() ) - { - if ( !IsValidIndex( left ) ) - return false; - if ( Parent( left ) != i ) - return false; - if ( IsRed( i ) && IsRed( left ) ) - return false; - } - } - - if ( it == m_LastAlloc ) - break; - } - if ( numFree2 != numFree ) - return false; - - if ( nElements != m_NumElements ) - return false; - -#endif // UTLTREE_PARANOID - - return true; -} - - -//----------------------------------------------------------------------------- -// Sets the less func -//----------------------------------------------------------------------------- - -template < class T, class I, typename L, class M > -void CUtlRBTree::SetLessFunc( const typename CUtlRBTree::LessFunc_t &func ) -{ - if (!m_LessFunc) - { - m_LessFunc = func; - } - else if ( Count() > 0 ) - { - // need to re-sort the tree here.... - Assert(0); - } -} - - -//----------------------------------------------------------------------------- -// inserts a node into the tree -//----------------------------------------------------------------------------- - -// Inserts a node into the tree, doesn't copy the data in. -template < class T, class I, typename L, class M > -void CUtlRBTree::FindInsertionPosition( T const &insert, I &parent, bool &leftchild ) -{ - Assert( m_LessFunc ); - - /* find where node belongs */ - I current = m_Root; - parent = InvalidIndex(); - leftchild = false; - while (current != InvalidIndex()) - { - parent = current; - if (m_LessFunc( insert, Element(current) )) - { - leftchild = true; current = LeftChild(current); - } - else - { - leftchild = false; current = RightChild(current); - } - } -} - -template < class T, class I, typename L, class M > -I CUtlRBTree::Insert( T const &insert ) -{ - // use copy constructor to copy it in - I parent; - bool leftchild; - FindInsertionPosition( insert, parent, leftchild ); - I newNode = InsertAt( parent, leftchild ); - CopyConstruct( &Element( newNode ), insert ); - return newNode; -} - - -template < class T, class I, typename L, class M > -void CUtlRBTree::Insert( const T *pArray, int nItems ) -{ - while ( nItems-- ) - { - Insert( *pArray++ ); - } -} - - -template < class T, class I, typename L, class M > -I CUtlRBTree::InsertIfNotFound( T const &insert ) -{ - // use copy constructor to copy it in - I parent; - bool leftchild; - - I current = m_Root; - parent = InvalidIndex(); - leftchild = false; - while (current != InvalidIndex()) - { - parent = current; - if (m_LessFunc( insert, Element(current) )) - { - leftchild = true; current = LeftChild(current); - } - else if (m_LessFunc( Element(current), insert )) - { - leftchild = false; current = RightChild(current); - } - else - // Match found, no insertion - return InvalidIndex(); - } - - I newNode = InsertAt( parent, leftchild ); - CopyConstruct( &Element( newNode ), insert ); - return newNode; -} - - -//----------------------------------------------------------------------------- -// finds a node in the tree -//----------------------------------------------------------------------------- -template < class T, class I, typename L, class M > -I CUtlRBTree::Find( T const &search ) const -{ - Assert( m_LessFunc ); - - I current = m_Root; - while (current != InvalidIndex()) - { - if (m_LessFunc( search, Element(current) )) - current = LeftChild(current); - else if (m_LessFunc( Element(current), search )) - current = RightChild(current); - else - break; - } - return current; -} - - -//----------------------------------------------------------------------------- -// swap in place -//----------------------------------------------------------------------------- -template < class T, class I, typename L, class M > -void CUtlRBTree::Swap( CUtlRBTree< T, I, L > &that ) -{ - m_Elements.Swap( that.m_Elements ); - swap( m_LessFunc, that.m_LessFunc ); - swap( m_Root, that.m_Root ); - swap( m_NumElements, that.m_NumElements ); - swap( m_FirstFree, that.m_FirstFree ); - swap( m_pElements, that.m_pElements ); - swap( m_LastAlloc, that.m_LastAlloc ); - Assert( IsValid() ); - Assert( m_Elements.IsValidIterator( m_LastAlloc ) || ( m_NumElements == 0 && m_FirstFree == InvalidIndex() ) ); -} - - -#endif // UTLRBTREE_H diff --git a/public/tier1/utlsoacontainer.h b/public/tier1/utlsoacontainer.h deleted file mode 100644 index 5ec14c54e..000000000 --- a/public/tier1/utlsoacontainer.h +++ /dev/null @@ -1,334 +0,0 @@ -//====== Copyright 1996-2007, Valve Corporation, All rights reserved. =======// -// -// Purpose: -// -// $NoKeywords: $ -// -// A Fixed-allocation class for maintaining a 1d or 2d or 3d array of data in a structure-of-arrays -// (SOA) sse-friendly manner. -// =============================================================================// - -#ifndef UTLSOACONTAINER_H -#define UTLSOACONTAINER_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "tier0/platform.h" -#include "tier0/dbg.h" -#include "tier0/threadtools.h" -#include "tier1/utlmemory.h" -#include "tier1/utlblockmemory.h" -#include "mathlib/ssemath.h" - - -// strided pointers. gives you a class that acts like a pointer, but the ++ and += operators do the -// right thing -template class CStridedPtr -{ -protected: - T *m_pData; - size_t m_nStride; - -public: - FORCEINLINE CStridedPtr( void *pData, size_t nByteStride ) - { - m_pData = reinterpret_cast( pData ); - m_nStride = nByteStride / sizeof( T ); - } - - FORCEINLINE CStridedPtr( void ) {} - T *operator->(void) const - { - return m_pData; - } - - T & operator*(void) const - { - return *m_pData; - } - - FORCEINLINE operator T *(void) - { - return m_pData; - } - - FORCEINLINE CStridedPtr & operator++(void) - { - m_pData += m_nStride; - return *this; - } - - FORCEINLINE void operator+=( size_t nNumElements ) - { - m_pData += nNumElements * m_nStride; - } - -}; - -template class CStridedConstPtr -{ -protected: - const T *m_pData; - size_t m_nStride; - -public: - FORCEINLINE CStridedConstPtr( void const *pData, size_t nByteStride ) - { - m_pData = reinterpret_cast( pData ); - m_nStride = nByteStride / sizeof( T ); - } - - FORCEINLINE CStridedConstPtr( void ) {} - - const T *operator->(void) const - { - return m_pData; - } - - const T & operator*(void) const - { - return *m_pData; - } - - FORCEINLINE operator const T *(void) const - { - return m_pData; - } - - FORCEINLINE CStridedConstPtr &operator++(void) - { - m_pData += m_nStride; - return *this; - } - FORCEINLINE void operator+=( size_t nNumElements ) - { - m_pData += nNumElements*m_nStride; - } -}; - -// allowed field data types. if you change these values, you need to change the tables in the .cpp file -enum EAttributeDataType -{ - ATTRDATATYPE_FLOAT = 0, // a float attribute - ATTRDATATYPE_4V = 1, // vector data type, stored as class FourVectors - ATTRDATATYPE_INT = 2, // integer. not especially sse-able on - // all architectures. - ATTRDATATYPE_POINTER = 3, // a pointer. - ATTRDATATYPE_NONE = -1, // pad and varargs ender -}; - -#define MAX_SOA_FIELDS 32 - -class CSOAContainer -{ - -protected: - int m_nColumns; // # of rows and columns created with - int m_nRows; - int m_nSlices; - - int m_nPaddedColumns; // # of columns rounded up for sse - int m_nNumQuadsPerRow; // # of groups of 4 elements per row - - uint8 *m_pDataMemory; // the actual data memory - uint8 *m_pAttributePtrs[MAX_SOA_FIELDS]; - - EAttributeDataType m_nDataType[MAX_SOA_FIELDS]; - - size_t m_nStrideInBytes[MAX_SOA_FIELDS]; // stride from one field datum to another - size_t m_nRowStrideInBytes[MAX_SOA_FIELDS]; // stride from one row datum to another per field - size_t m_nSliceStrideInBytes[MAX_SOA_FIELDS]; // stride from one slice datum to another per field - - - - uint32 m_nFieldPresentMask; - - FORCEINLINE void Init( void ) - { - memset( m_nDataType, 0xff, sizeof( m_nDataType ) ); - m_pDataMemory = 0; - m_nColumns = m_nPaddedColumns = m_nRows = m_nSlices = 0; - m_nFieldPresentMask = 0; - } -public: - - - CSOAContainer( void ) // an empoty one with no attributes - { - Init(); - } - - void Purge( void ); // set back to un-initted state, freeing memory - - ~CSOAContainer( void ); - - // easy constructor for 2d using varargs. call like - // #define ATTR_RED 0 - // #define ATTR_GREEN 1 - // #define ATTR_BLUE 2 - // CSOAContainer myimage( 256, 256, ATTR_RED, ATTRDATATYPE_FLOAT, ATTR_GREEN, ATTRDATATYPE_FLOAT, - // ATTR_BLUE, ATTRDATATYPE_FLOAT, -1 ); - - CSOAContainer( int nCols, int nRows, ... ); - - size_t ElementSize( void ) const; // total bytes per element. not super fast. - - // set the data type for an attribute. If you set the data type, but tell it not to allocate, - // the data type will be set but writes will assert, and reads will give you back zeros. - FORCEINLINE void SetAttributeType( int nAttrIdx, EAttributeDataType nDataType, bool bAllocateMemory = true ) - { - Assert( !m_pDataMemory ); // can't change after memory allocated - Assert( nAttrIdx < MAX_SOA_FIELDS ); - m_nDataType[nAttrIdx] = nDataType; - if ( ( m_nDataType[nAttrIdx] != ATTRDATATYPE_NONE ) && bAllocateMemory ) - m_nFieldPresentMask |= ( 1 << nAttrIdx ); - else - m_nFieldPresentMask &= ~( 1 << nAttrIdx ); - } - - FORCEINLINE int NumRows( void ) const - { - return m_nRows; - } - - FORCEINLINE int NumCols( void ) const - { - return m_nColumns; - } - FORCEINLINE int NumSlices( void ) const - { - return m_nSlices; - } - - - FORCEINLINE void AssertDataType( int nAttrIdx, EAttributeDataType nDataType ) const - { - Assert( nAttrIdx >= 0 ); - Assert( nAttrIdx < MAX_SOA_FIELDS ); - Assert( m_nStrideInBytes[nAttrIdx] ); - } - - - // # of groups of 4 elements per row - FORCEINLINE int NumQuadsPerRow( void ) const - { - return m_nNumQuadsPerRow; - } - - FORCEINLINE int Count( void ) const // for 1d data - { - return NumCols(); - } - - FORCEINLINE int NumElements( void ) const - { - return NumCols() * NumRows() * NumSlices(); - } - - - // how much to step to go from the end of one row to the start of the next one. Basically, how - // many bytes to add at the end of a row when iterating over the whole 2d array with ++ - FORCEINLINE size_t RowToRowStep( int nAttrIdx ) const - { - return 0; - } - - FORCEINLINE void *RowPtr( int nAttributeIdx, int nRowNumber, int nSliceNumber = 0 ) const - { - Assert( nRowNumber < m_nRows ); - Assert( nAttributeIdx < MAX_SOA_FIELDS ); - Assert( m_nDataType[nAttributeIdx] != ATTRDATATYPE_NONE ); - Assert( m_nFieldPresentMask & ( 1 << nAttributeIdx ) ); - return m_pAttributePtrs[nAttributeIdx] + - + nRowNumber * m_nRowStrideInBytes[nAttributeIdx] - + nSliceNumber * m_nSliceStrideInBytes[nAttributeIdx]; - } - - FORCEINLINE void const *ConstRowPtr( int nAttributeIdx, int nRowNumber, int nSliceNumber = 0 ) const - { - Assert( nRowNumber < m_nRows ); - Assert( nAttributeIdx < MAX_SOA_FIELDS ); - Assert( m_nDataType[nAttributeIdx] != ATTRDATATYPE_NONE ); - return m_pAttributePtrs[nAttributeIdx] - + nRowNumber * m_nRowStrideInBytes[nAttributeIdx] - + nSliceNumber * m_nSliceStrideInBytes[nAttributeIdx]; - } - - - template FORCEINLINE T *ElementPointer( int nAttributeIdx, - int nX = 0, int nY = 0, int nZ = 0 ) const - { - Assert( nAttributeIdx < MAX_SOA_FIELDS ); - Assert( nX < m_nColumns ); - Assert( nY < m_nRows ); - Assert( nZ < m_nSlices ); - Assert( m_nDataType[nAttributeIdx] != ATTRDATATYPE_NONE ); - Assert( m_nDataType[nAttributeIdx] != ATTRDATATYPE_4V ); - return reinterpret_cast( m_pAttributePtrs[nAttributeIdx] - + nX * sizeof( float ) - + nY * m_nRowStrideInBytes[nAttributeIdx] - + nZ * m_nSliceStrideInBytes[nAttributeIdx] - ); - } - - FORCEINLINE size_t ItemByteStride( int nAttributeIdx ) const - { - Assert( nAttributeIdx < MAX_SOA_FIELDS ); - Assert( m_nDataType[nAttributeIdx] != ATTRDATATYPE_NONE ); - return m_nStrideInBytes[ nAttributeIdx ]; - } - - // copy the attribute data from another soacontainer. must be compatible geometry - void CopyAttrFrom( CSOAContainer const &other, int nAttributeIdx ); - - // copy the attribute data from another attribute. must be compatible data format - void CopyAttrToAttr( int nSrcAttributeIndex, int nDestAttributeIndex); - - // move all the data from one csoacontainer to another, leaving the source empty. - // this is just a pointer copy. - FORCEINLINE void MoveDataFrom( CSOAContainer other ) - { - (*this) = other; - other.Init(); - } - - - - void AllocateData( int nNCols, int nNRows, int nSlices = 1 ); // actually allocate the memory and set the pointers up - - // arithmetic and data filling functions. All SIMD and hopefully fast - - // set all elements of a float attribute to random #s - void RandomizeAttribute( int nAttr, float flMin, float flMax ) const ; - - // fill 2d a rectangle with values interpolated from 4 corner values. - void FillAttrWithInterpolatedValues( int nAttr, float flValue00, float flValue10, float flValue01, float flValue11 ) const; - void FillAttrWithInterpolatedValues( int nAttr, Vector flValue00, Vector flValue10, - Vector const &flValue01, Vector const &flValue11 ) const; - -}; - -class CFltX4AttributeIterator : public CStridedConstPtr -{ - FORCEINLINE CFltX4AttributeIterator( CSOAContainer const *pContainer, int nAttribute, int nRowNumber = 0 ) - : CStridedConstPtr( pContainer->ConstRowPtr( nAttribute, nRowNumber), - pContainer->ItemByteStride( nAttribute ) ) - { - } -}; - -class CFltX4AttributeWriteIterator : public CStridedPtr -{ - FORCEINLINE CFltX4AttributeWriteIterator( CSOAContainer const *pContainer, int nAttribute, int nRowNumber = 0 ) - : CStridedPtr( pContainer->RowPtr( nAttribute, nRowNumber), - pContainer->ItemByteStride( nAttribute ) ) - { - } - -}; - - -#endif diff --git a/public/tier1/utlstack.h b/public/tier1/utlstack.h deleted file mode 100644 index c7ab48d8b..000000000 --- a/public/tier1/utlstack.h +++ /dev/null @@ -1,331 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -// A stack based on a growable array -//=============================================================================// - -#ifndef UTLSTACK_H -#define UTLSTACK_H - -#include -#include -#include "utlmemory.h" - - -//----------------------------------------------------------------------------- -// The CUtlStack class: -// A growable stack class which doubles in size by default. -// It will always keep all elements consecutive in memory, and may move the -// elements around in memory (via a realloc) when elements are pushed or -// popped. Clients should therefore refer to the elements of the stack -// by index (they should *never* maintain pointers to elements in the stack). -//----------------------------------------------------------------------------- - -template< class T, class M = CUtlMemory< T > > -class CUtlStack -{ -public: - // constructor, destructor - CUtlStack( int growSize = 0, int initSize = 0 ); - ~CUtlStack(); - - void CopyFrom( const CUtlStack &from ); - - // element access - T& operator[]( int i ); - T const& operator[]( int i ) const; - T& Element( int i ); - T const& Element( int i ) const; - - // Gets the base address (can change when adding elements!) - T* Base(); - T const* Base() const; - - // Looks at the stack top - T& Top(); - T const& Top() const; - - // Size - int Count() const; - - // Is element index valid? - bool IsIdxValid( int i ) const; - - // Adds an element, uses default constructor - int Push(); - - // Adds an element, uses copy constructor - int Push( T const& src ); - - // Pops the stack - void Pop(); - void Pop( T& oldTop ); - void PopMultiple( int num ); - - // Makes sure we have enough memory allocated to store a requested # of elements - void EnsureCapacity( int num ); - - // Clears the stack, no deallocation - void Clear(); - - // Memory deallocation - void Purge(); - -private: - // Grows the stack allocation - void GrowStack(); - - // For easier access to the elements through the debugger - void ResetDbgInfo(); - - M m_Memory; - int m_Size; - - // For easier access to the elements through the debugger - T* m_pElements; -}; - - -//----------------------------------------------------------------------------- -// For easier access to the elements through the debugger -//----------------------------------------------------------------------------- - -template< class T, class M > -inline void CUtlStack::ResetDbgInfo() -{ - m_pElements = m_Memory.Base(); -} - -//----------------------------------------------------------------------------- -// constructor, destructor -//----------------------------------------------------------------------------- - -template< class T, class M > -CUtlStack::CUtlStack( int growSize, int initSize ) : - m_Memory(growSize, initSize), m_Size(0) -{ - ResetDbgInfo(); -} - -template< class T, class M > -CUtlStack::~CUtlStack() -{ - Purge(); -} - - -//----------------------------------------------------------------------------- -// copy into -//----------------------------------------------------------------------------- - -template< class T, class M > -void CUtlStack::CopyFrom( const CUtlStack &from ) -{ - Purge(); - EnsureCapacity( from.Count() ); - for ( int i = 0; i < from.Count(); i++ ) - { - Push( from[i] ); - } -} - -//----------------------------------------------------------------------------- -// element access -//----------------------------------------------------------------------------- - -template< class T, class M > -inline T& CUtlStack::operator[]( int i ) -{ - assert( IsIdxValid(i) ); - return m_Memory[i]; -} - -template< class T, class M > -inline T const& CUtlStack::operator[]( int i ) const -{ - assert( IsIdxValid(i) ); - return m_Memory[i]; -} - -template< class T, class M > -inline T& CUtlStack::Element( int i ) -{ - assert( IsIdxValid(i) ); - return m_Memory[i]; -} - -template< class T, class M > -inline T const& CUtlStack::Element( int i ) const -{ - assert( IsIdxValid(i) ); - return m_Memory[i]; -} - - -//----------------------------------------------------------------------------- -// Gets the base address (can change when adding elements!) -//----------------------------------------------------------------------------- - -template< class T, class M > -inline T* CUtlStack::Base() -{ - return m_Memory.Base(); -} - -template< class T, class M > -inline T const* CUtlStack::Base() const -{ - return m_Memory.Base(); -} - -//----------------------------------------------------------------------------- -// Returns the top of the stack -//----------------------------------------------------------------------------- - -template< class T, class M > -inline T& CUtlStack::Top() -{ - assert( m_Size > 0 ); - return Element(m_Size-1); -} - -template< class T, class M > -inline T const& CUtlStack::Top() const -{ - assert( m_Size > 0 ); - return Element(m_Size-1); -} - -//----------------------------------------------------------------------------- -// Size -//----------------------------------------------------------------------------- - -template< class T, class M > -inline int CUtlStack::Count() const -{ - return m_Size; -} - - -//----------------------------------------------------------------------------- -// Is element index valid? -//----------------------------------------------------------------------------- - -template< class T, class M > -inline bool CUtlStack::IsIdxValid( int i ) const -{ - return (i >= 0) && (i < m_Size); -} - -//----------------------------------------------------------------------------- -// Grows the stack -//----------------------------------------------------------------------------- - -template< class T, class M > -void CUtlStack::GrowStack() -{ - if (m_Size >= m_Memory.NumAllocated()) - m_Memory.Grow(); - - ++m_Size; - - ResetDbgInfo(); -} - -//----------------------------------------------------------------------------- -// Makes sure we have enough memory allocated to store a requested # of elements -//----------------------------------------------------------------------------- - -template< class T, class M > -void CUtlStack::EnsureCapacity( int num ) -{ - m_Memory.EnsureCapacity(num); - ResetDbgInfo(); -} - - -//----------------------------------------------------------------------------- -// Adds an element, uses default constructor -//----------------------------------------------------------------------------- - -template< class T, class M > -int CUtlStack::Push() -{ - GrowStack(); - Construct( &Element(m_Size-1) ); - return m_Size - 1; -} - -//----------------------------------------------------------------------------- -// Adds an element, uses copy constructor -//----------------------------------------------------------------------------- - -template< class T, class M > -int CUtlStack::Push( T const& src ) -{ - GrowStack(); - CopyConstruct( &Element(m_Size-1), src ); - return m_Size - 1; -} - - -//----------------------------------------------------------------------------- -// Pops the stack -//----------------------------------------------------------------------------- - -template< class T, class M > -void CUtlStack::Pop() -{ - assert( m_Size > 0 ); - Destruct( &Element(m_Size-1) ); - --m_Size; -} - -template< class T, class M > -void CUtlStack::Pop( T& oldTop ) -{ - assert( m_Size > 0 ); - oldTop = Top(); - Pop(); -} - -template< class T, class M > -void CUtlStack::PopMultiple( int num ) -{ - assert( m_Size >= num ); - for ( int i = 0; i < num; ++i ) - Destruct( &Element( m_Size - i - 1 ) ); - m_Size -= num; -} - - -//----------------------------------------------------------------------------- -// Element removal -//----------------------------------------------------------------------------- - -template< class T, class M > -void CUtlStack::Clear() -{ - for (int i = m_Size; --i >= 0; ) - Destruct(&Element(i)); - - m_Size = 0; -} - - -//----------------------------------------------------------------------------- -// Memory deallocation -//----------------------------------------------------------------------------- - -template< class T, class M > -void CUtlStack::Purge() -{ - Clear(); - m_Memory.Purge( ); - ResetDbgInfo(); -} - -#endif // UTLSTACK_H diff --git a/public/tier1/utlstring.h b/public/tier1/utlstring.h deleted file mode 100644 index cb49ebb37..000000000 --- a/public/tier1/utlstring.h +++ /dev/null @@ -1,160 +0,0 @@ -//====== Copyright 1996-2004, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef UTLSTRING_H -#define UTLSTRING_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "tier1/utlmemory.h" - - -//----------------------------------------------------------------------------- -// Base class, containing simple memory management -//----------------------------------------------------------------------------- -class CUtlBinaryBlock -{ -public: - CUtlBinaryBlock( int growSize = 0, int initSize = 0 ); - - // NOTE: nInitialLength indicates how much of the buffer starts full - CUtlBinaryBlock( void* pMemory, int nSizeInBytes, int nInitialLength ); - CUtlBinaryBlock( const void* pMemory, int nSizeInBytes ); - CUtlBinaryBlock( const CUtlBinaryBlock& src ); - - void Get( void *pValue, int nMaxLen ) const; - void Set( const void *pValue, int nLen ); - const void *Get( ) const; - void *Get( ); - - unsigned char& operator[]( int i ); - const unsigned char& operator[]( int i ) const; - - int Length() const; - void SetLength( int nLength ); // Undefined memory will result - bool IsEmpty() const; - - bool IsReadOnly() const; - - CUtlBinaryBlock &operator=( const CUtlBinaryBlock &src ); - - // Test for equality - bool operator==( const CUtlBinaryBlock &src ) const; - -private: - CUtlMemory m_Memory; - int m_nActualLength; -}; - - -//----------------------------------------------------------------------------- -// class inlines -//----------------------------------------------------------------------------- -inline const void *CUtlBinaryBlock::Get( ) const -{ - return m_Memory.Base(); -} - -inline void *CUtlBinaryBlock::Get( ) -{ - return m_Memory.Base(); -} - -inline int CUtlBinaryBlock::Length() const -{ - return m_nActualLength; -} - -inline unsigned char& CUtlBinaryBlock::operator[]( int i ) -{ - return m_Memory[i]; -} - -inline const unsigned char& CUtlBinaryBlock::operator[]( int i ) const -{ - return m_Memory[i]; -} - -inline bool CUtlBinaryBlock::IsReadOnly() const -{ - return m_Memory.IsReadOnly(); -} - -inline bool CUtlBinaryBlock::IsEmpty() const -{ - return Length() == 0; -} - - -//----------------------------------------------------------------------------- -// Simple string class. -// NOTE: This is *not* optimal! Use in tools, but not runtime code -//----------------------------------------------------------------------------- -class CUtlString -{ -public: - CUtlString(); - CUtlString( const char *pString ); - CUtlString( const CUtlString& string ); - - // Attaches the string to external memory. Useful for avoiding a copy - CUtlString( void* pMemory, int nSizeInBytes, int nInitialLength ); - CUtlString( const void* pMemory, int nSizeInBytes ); - - const char *Get( ) const; - void Set( const char *pValue ); - - // Converts to c-strings - operator const char*() const; - - // for compatibility switching items from UtlSymbol - const char *String() const { return Get(); } - - // Returns strlen - int Length() const; - bool IsEmpty() const; - - // Sets the length (used to serialize into the buffer ) - void SetLength( int nLen ); - char *Get(); - - // Strips the trailing slash - void StripTrailingSlash(); - - CUtlString &operator=( const CUtlString &src ); - CUtlString &operator=( const char *src ); - - // Test for equality - bool operator==( const CUtlString &src ) const; - bool operator==( const char *src ) const; - bool operator!=( const CUtlString &src ) const { return !operator==( src ); } - bool operator!=( const char *src ) const { return !operator==( src ); } - - CUtlString &operator+=( const CUtlString &rhs ); - CUtlString &operator+=( const char *rhs ); - CUtlString &operator+=( char c ); - CUtlString &operator+=( int rhs ); - CUtlString &operator+=( double rhs ); - - int Format( const char *pFormat, ... ); - -private: - CUtlBinaryBlock m_Storage; -}; - - -//----------------------------------------------------------------------------- -// Inline methods -//----------------------------------------------------------------------------- -inline bool CUtlString::IsEmpty() const -{ - return Length() == 0; -} - - -#endif // UTLSTRING_H diff --git a/public/tier1/utlsymbol.h b/public/tier1/utlsymbol.h deleted file mode 100644 index a37d8bb6e..000000000 --- a/public/tier1/utlsymbol.h +++ /dev/null @@ -1,261 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: Defines a symbol table -// -// $Header: $ -// $NoKeywords: $ -//===========================================================================// - -#ifndef UTLSYMBOL_H -#define UTLSYMBOL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/threadtools.h" -#include "tier1/utlrbtree.h" -#include "tier1/utlvector.h" -#include "tier1/stringpool.h" - - -//----------------------------------------------------------------------------- -// forward declarations -//----------------------------------------------------------------------------- -class CUtlSymbolTable; -class CUtlSymbolTableMT; - - -//----------------------------------------------------------------------------- -// This is a symbol, which is a easier way of dealing with strings. -//----------------------------------------------------------------------------- -typedef unsigned short UtlSymId_t; - -#define UTL_INVAL_SYMBOL ((UtlSymId_t)~0) - -class CUtlSymbol -{ -public: - // constructor, destructor - CUtlSymbol() : m_Id(UTL_INVAL_SYMBOL) {} - CUtlSymbol( UtlSymId_t id ) : m_Id(id) {} - CUtlSymbol( const char* pStr ); - CUtlSymbol( CUtlSymbol const& sym ) : m_Id(sym.m_Id) {} - - // operator= - CUtlSymbol& operator=( CUtlSymbol const& src ) { m_Id = src.m_Id; return *this; } - - // operator== - bool operator==( CUtlSymbol const& src ) const { return m_Id == src.m_Id; } - bool operator==( const char* pStr ) const; - - // Is valid? - bool IsValid() const { return m_Id != UTL_INVAL_SYMBOL; } - - // Gets at the symbol - operator UtlSymId_t const() const { return m_Id; } - - // Gets the string associated with the symbol - const char* String( ) const; - - // Modules can choose to disable the static symbol table so to prevent accidental use of them. - static void DisableStaticSymbolTable(); - -protected: - UtlSymId_t m_Id; - - // Initializes the symbol table - static void Initialize(); - - // returns the current symbol table - static CUtlSymbolTableMT* CurrTable(); - - // The standard global symbol table - static CUtlSymbolTableMT* s_pSymbolTable; - - static bool s_bAllowStaticSymbolTable; - - friend class CCleanupUtlSymbolTable; -}; - - -//----------------------------------------------------------------------------- -// CUtlSymbolTable: -// description: -// This class defines a symbol table, which allows us to perform mappings -// of strings to symbols and back. The symbol class itself contains -// a static version of this class for creating global strings, but this -// class can also be instanced to create local symbol tables. -//----------------------------------------------------------------------------- - -class CUtlSymbolTable -{ -public: - // constructor, destructor - CUtlSymbolTable( int growSize = 0, int initSize = 32, bool caseInsensitive = false ); - ~CUtlSymbolTable(); - - // Finds and/or creates a symbol based on the string - CUtlSymbol AddString( const char* pString ); - - // Finds the symbol for pString - CUtlSymbol Find( const char* pString ) const; - - // Look up the string associated with a particular symbol - const char* String( CUtlSymbol id ) const; - - // Remove all symbols in the table. - void RemoveAll(); - - int GetNumStrings( void ) const - { - return m_Lookup.Count(); - } - -protected: - class CStringPoolIndex - { - public: - inline CStringPoolIndex() - { - } - - inline CStringPoolIndex( unsigned short iPool, unsigned short iOffset ) - { - m_iPool = iPool; - m_iOffset = iOffset; - } - - inline bool operator==( const CStringPoolIndex &other ) const - { - return m_iPool == other.m_iPool && m_iOffset == other.m_iOffset; - } - - unsigned short m_iPool; // Index into m_StringPools. - unsigned short m_iOffset; // Index into the string pool. - }; - - class CLess - { - public: - CLess( int ignored = 0 ) {} // permits default initialization to NULL in CUtlRBTree - bool operator!() const { return false; } - bool operator()( const CStringPoolIndex &left, const CStringPoolIndex &right ) const; - }; - - // Stores the symbol lookup - class CTree : public CUtlRBTree - { - public: - CTree( int growSize, int initSize ) : CUtlRBTree( growSize, initSize ) {} - friend class CUtlSymbolTable::CLess; // Needed to allow CLess to calculate pointer to symbol table - }; - - struct StringPool_t - { - int m_TotalLen; // How large is - int m_SpaceUsed; - char m_Data[1]; - }; - - CTree m_Lookup; - bool m_bInsensitive; - mutable const char* m_pUserSearchString; - - // stores the string data - CUtlVector m_StringPools; - -private: - int FindPoolWithSpace( int len ) const; - const char* StringFromIndex( const CStringPoolIndex &index ) const; - - friend class CLess; -}; - -class CUtlSymbolTableMT : private CUtlSymbolTable -{ -public: - CUtlSymbolTableMT( int growSize = 0, int initSize = 32, bool caseInsensitive = false ) - : CUtlSymbolTable( growSize, initSize, caseInsensitive ) - { - } - - CUtlSymbol AddString( const char* pString ) - { - m_lock.LockForWrite(); - CUtlSymbol result = CUtlSymbolTable::AddString( pString ); - m_lock.UnlockWrite(); - return result; - } - - CUtlSymbol Find( const char* pString ) const - { - m_lock.LockForWrite(); - CUtlSymbol result = CUtlSymbolTable::Find( pString ); - m_lock.UnlockWrite(); - return result; - } - - const char* String( CUtlSymbol id ) const - { - m_lock.LockForRead(); - const char *pszResult = CUtlSymbolTable::String( id ); - m_lock.UnlockRead(); - return pszResult; - } - -private: - mutable CThreadSpinRWLock m_lock; -}; - - - -//----------------------------------------------------------------------------- -// CUtlFilenameSymbolTable: -// description: -// This class defines a symbol table of individual filenames, stored more -// efficiently than a standard symbol table. Internally filenames are broken -// up into file and path entries, and a file handle class allows convenient -// access to these. -//----------------------------------------------------------------------------- - -// The handle is a CUtlSymbol for the dirname and the same for the filename, the accessor -// copies them into a static char buffer for return. -typedef void* FileNameHandle_t; - -// Symbol table for more efficiently storing filenames by breaking paths and filenames apart. -// Refactored from BaseFileSystem.h -class CUtlFilenameSymbolTable -{ - // Internal representation of a FileHandle_t - // If we get more than 64K filenames, we'll have to revisit... - // Right now CUtlSymbol is a short, so this packs into an int/void * pointer size... - struct FileNameHandleInternal_t - { - FileNameHandleInternal_t() - { - path = 0; - file = 0; - } - - // Part before the final '/' character - unsigned short path; - // Part after the final '/', including extension - unsigned short file; - }; - -public: - FileNameHandle_t FindOrAddFileName( const char *pFileName ); - FileNameHandle_t FindFileName( const char *pFileName ); - int PathIndex(const FileNameHandle_t &handle) { return (( const FileNameHandleInternal_t * )&handle)->path; } - bool String( const FileNameHandle_t& handle, char *buf, int buflen ); - void RemoveAll(); - void SpewStrings(); - -private: - CCountedStringPool m_StringPool; - mutable CThreadSpinRWLock m_lock; -}; - - -#endif // UTLSYMBOL_H diff --git a/public/tier1/utlvector.h b/public/tier1/utlvector.h deleted file mode 100644 index 19383d331..000000000 --- a/public/tier1/utlvector.h +++ /dev/null @@ -1,794 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======// -// -// Purpose: -// -// $NoKeywords: $ -// -// A growable array class that maintains a free list and keeps elements -// in the same location -//=============================================================================// - -#ifndef UTLVECTOR_H -#define UTLVECTOR_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include -#include "tier0/platform.h" -#include "tier0/dbg.h" -#include "tier0/threadtools.h" -#include "tier1/utlmemory.h" -#include "tier1/utlblockmemory.h" -#include "tier1/strtools.h" - -#define FOR_EACH_VEC( vecName, iteratorName ) \ - for ( int iteratorName = 0; iteratorName < vecName.Count(); iteratorName++ ) - -//----------------------------------------------------------------------------- -// The CUtlVector class: -// A growable array class which doubles in size by default. -// It will always keep all elements consecutive in memory, and may move the -// elements around in memory (via a PvRealloc) when elements are inserted or -// removed. Clients should therefore refer to the elements of the vector -// by index (they should *never* maintain pointers to elements in the vector). -//----------------------------------------------------------------------------- -template< class T, class A = CUtlMemory > -class CUtlVector -{ - typedef A CAllocator; -public: - typedef T ElemType_t; - - // constructor, destructor - CUtlVector( int growSize = 0, int initSize = 0 ); - CUtlVector( T* pMemory, int allocationCount, int numElements = 0 ); - ~CUtlVector(); - - // Copy the array. - CUtlVector& operator=( const CUtlVector &other ); - - // element access - T& operator[]( int i ); - const T& operator[]( int i ) const; - T& Element( int i ); - const T& Element( int i ) const; - T& Head(); - const T& Head() const; - T& Tail(); - const T& Tail() const; - - // Gets the base address (can change when adding elements!) - T* Base() { return m_Memory.Base(); } - const T* Base() const { return m_Memory.Base(); } - - // Returns the number of elements in the vector - // SIZE IS DEPRECATED! - int Count() const; - int Size() const; // don't use me! - - // Is element index valid? - bool IsValidIndex( int i ) const; - static int InvalidIndex(); - - // Adds an element, uses default constructor - int AddToHead(); - int AddToTail(); - int InsertBefore( int elem ); - int InsertAfter( int elem ); - - // Adds an element, uses copy constructor - int AddToHead( const T& src ); - int AddToTail( const T& src ); - int InsertBefore( int elem, const T& src ); - int InsertAfter( int elem, const T& src ); - - // Adds multiple elements, uses default constructor - int AddMultipleToHead( int num ); - int AddMultipleToTail( int num, const T *pToCopy=NULL ); - int InsertMultipleBefore( int elem, int num, const T *pToCopy=NULL ); // If pToCopy is set, then it's an array of length 'num' and - int InsertMultipleAfter( int elem, int num ); - - // Calls RemoveAll() then AddMultipleToTail. - void SetSize( int size ); - void SetCount( int count ); - - // Calls SetSize and copies each element. - void CopyArray( const T *pArray, int size ); - - // Fast swap - void Swap( CUtlVector< T, A > &vec ); - - // Add the specified array to the tail. - int AddVectorToTail( CUtlVector const &src ); - - // Finds an element (element needs operator== defined) - int Find( const T& src ) const; - - bool HasElement( const T& src ) const; - - // Makes sure we have enough memory allocated to store a requested # of elements - void EnsureCapacity( int num ); - - // Makes sure we have at least this many elements - void EnsureCount( int num ); - - // Element removal - void FastRemove( int elem ); // doesn't preserve order - void Remove( int elem ); // preserves order, shifts elements - bool FindAndRemove( const T& src ); // removes first occurrence of src, preserves order, shifts elements - void RemoveMultiple( int elem, int num ); // preserves order, shifts elements - void RemoveAll(); // doesn't deallocate memory - - // Memory deallocation - void Purge(); - - // Purges the list and calls delete on each element in it. - void PurgeAndDeleteElements(); - - // Compacts the vector to the number of elements actually in use - void Compact(); - - // Set the size by which it grows when it needs to allocate more memory. - void SetGrowSize( int size ) { m_Memory.SetGrowSize( size ); } - - int NumAllocated() const; // Only use this if you really know what you're doing! - - void Sort( int (__cdecl *pfnCompare)(const T *, const T *) ); - -#ifdef DBGFLAG_VALIDATE - void Validate( CValidator &validator, char *pchName ); // Validate our internal structures -#endif // DBGFLAG_VALIDATE - -protected: - // Can't copy this unless we explicitly do it! - CUtlVector( CUtlVector const& vec ) { Assert(0); } - - // Grows the vector - void GrowVector( int num = 1 ); - - // Shifts elements.... - void ShiftElementsRight( int elem, int num = 1 ); - void ShiftElementsLeft( int elem, int num = 1 ); - - CAllocator m_Memory; - int m_Size; - - // For easier access to the elements through the debugger - // it's in release builds so this can be used in libraries correctly - T *m_pElements; - - inline void ResetDbgInfo() - { - m_pElements = Base(); - } -}; - - -// this is kind of ugly, but until C++ gets templatized typedefs in C++0x, it's our only choice -template < class T > -class CUtlBlockVector : public CUtlVector< T, CUtlBlockMemory< T, int > > -{ -public: - CUtlBlockVector( int growSize = 0, int initSize = 0 ) - : CUtlVector< T, CUtlBlockMemory< T, int > >( growSize, initSize ) {} -}; - -//----------------------------------------------------------------------------- -// The CUtlVectorFixed class: -// A array class with a fixed allocation scheme -//----------------------------------------------------------------------------- - -template< class BASE_UTLVECTOR, class MUTEX_TYPE = CThreadFastMutex > -class CUtlVectorMT : public BASE_UTLVECTOR, public MUTEX_TYPE -{ - typedef BASE_UTLVECTOR BaseClass; -public: - MUTEX_TYPE Mutex_t; - - // constructor, destructor - CUtlVectorMT( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {} - CUtlVectorMT( typename BaseClass::ElemType_t* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {} -}; - - -//----------------------------------------------------------------------------- -// The CUtlVectorFixed class: -// A array class with a fixed allocation scheme -//----------------------------------------------------------------------------- -template< class T, size_t MAX_SIZE > -class CUtlVectorFixed : public CUtlVector< T, CUtlMemoryFixed > -{ - typedef CUtlVector< T, CUtlMemoryFixed > BaseClass; -public: - - // constructor, destructor - CUtlVectorFixed( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {} - CUtlVectorFixed( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {} -}; - - -//----------------------------------------------------------------------------- -// The CUtlVectorFixed class: -// A array class with a fixed allocation scheme -//----------------------------------------------------------------------------- -template< class T, size_t MAX_SIZE > -class CUtlVectorFixedGrowable : public CUtlVector< T, CUtlMemoryFixedGrowable > -{ - typedef CUtlVector< T, CUtlMemoryFixedGrowable > BaseClass; - -public: - // constructor, destructor - CUtlVectorFixedGrowable( int growSize = 0 ) : BaseClass( growSize, MAX_SIZE ) {} -}; - - -//----------------------------------------------------------------------------- -// The CCopyableUtlVector class: -// A array class that allows copy construction (so you can nest a CUtlVector inside of another one of our containers) -// WARNING - this class lets you copy construct which can be an expensive operation if you don't carefully control when it happens -// Only use this when nesting a CUtlVector() inside of another one of our container classes (i.e a CUtlMap) -//----------------------------------------------------------------------------- -template< class T > -class CCopyableUtlVector : public CUtlVector< T, CUtlMemory > -{ - typedef CUtlVector< T, CUtlMemory > BaseClass; -public: - CCopyableUtlVector( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {} - CCopyableUtlVector( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {} - virtual ~CCopyableUtlVector() {} - CCopyableUtlVector( CCopyableUtlVector const& vec ) { CopyArray( vec.Base(), vec.Count() ); } -}; - -//----------------------------------------------------------------------------- -// constructor, destructor -//----------------------------------------------------------------------------- -template< typename T, class A > -inline CUtlVector::CUtlVector( int growSize, int initSize ) : - m_Memory(growSize, initSize), m_Size(0) -{ - ResetDbgInfo(); -} - -template< typename T, class A > -inline CUtlVector::CUtlVector( T* pMemory, int allocationCount, int numElements ) : - m_Memory(pMemory, allocationCount), m_Size(numElements) -{ - ResetDbgInfo(); -} - -template< typename T, class A > -inline CUtlVector::~CUtlVector() -{ - Purge(); -} - -template< typename T, class A > -inline CUtlVector& CUtlVector::operator=( const CUtlVector &other ) -{ - int nCount = other.Count(); - SetSize( nCount ); - for ( int i = 0; i < nCount; i++ ) - { - (*this)[ i ] = other[ i ]; - } - return *this; -} - - -//----------------------------------------------------------------------------- -// element access -//----------------------------------------------------------------------------- -template< typename T, class A > -inline T& CUtlVector::operator[]( int i ) -{ - return m_Memory[ i ]; -} - -template< typename T, class A > -inline const T& CUtlVector::operator[]( int i ) const -{ - return m_Memory[ i ]; -} - -template< typename T, class A > -inline T& CUtlVector::Element( int i ) -{ - return m_Memory[ i ]; -} - -template< typename T, class A > -inline const T& CUtlVector::Element( int i ) const -{ - return m_Memory[ i ]; -} - -template< typename T, class A > -inline T& CUtlVector::Head() -{ - Assert( m_Size > 0 ); - return m_Memory[ 0 ]; -} - -template< typename T, class A > -inline const T& CUtlVector::Head() const -{ - Assert( m_Size > 0 ); - return m_Memory[ 0 ]; -} - -template< typename T, class A > -inline T& CUtlVector::Tail() -{ - Assert( m_Size > 0 ); - return m_Memory[ m_Size - 1 ]; -} - -template< typename T, class A > -inline const T& CUtlVector::Tail() const -{ - Assert( m_Size > 0 ); - return m_Memory[ m_Size - 1 ]; -} - - -//----------------------------------------------------------------------------- -// Count -//----------------------------------------------------------------------------- -template< typename T, class A > -inline int CUtlVector::Size() const -{ - return m_Size; -} - -template< typename T, class A > -inline int CUtlVector::Count() const -{ - return m_Size; -} - - -//----------------------------------------------------------------------------- -// Is element index valid? -//----------------------------------------------------------------------------- -template< typename T, class A > -inline bool CUtlVector::IsValidIndex( int i ) const -{ - return (i >= 0) && (i < m_Size); -} - - -//----------------------------------------------------------------------------- -// Returns in invalid index -//----------------------------------------------------------------------------- -template< typename T, class A > -inline int CUtlVector::InvalidIndex() -{ - return -1; -} - - -//----------------------------------------------------------------------------- -// Grows the vector -//----------------------------------------------------------------------------- -template< typename T, class A > -void CUtlVector::GrowVector( int num ) -{ - if (m_Size + num > m_Memory.NumAllocated()) - { - MEM_ALLOC_CREDIT_CLASS(); - m_Memory.Grow( m_Size + num - m_Memory.NumAllocated() ); - } - - m_Size += num; - ResetDbgInfo(); -} - - -//----------------------------------------------------------------------------- -// Sorts the vector -//----------------------------------------------------------------------------- -template< typename T, class A > -void CUtlVector::Sort( int (__cdecl *pfnCompare)(const T *, const T *) ) -{ - typedef int (__cdecl *QSortCompareFunc_t)(const void *, const void *); - if ( Count() <= 1 ) - return; - - if ( Base() ) - { - qsort( Base(), Count(), sizeof(T), (QSortCompareFunc_t)(pfnCompare) ); - } - else - { - Assert( 0 ); - // this path is untested - // if you want to sort vectors that use a non-sequential memory allocator, - // you'll probably want to patch in a quicksort algorithm here - // I just threw in this bubble sort to have something just in case... - - for ( int i = m_Size - 1; i >= 0; --i ) - { - for ( int j = 1; j <= i; ++j ) - { - if ( pfnCompare( &Element( j - 1 ), &Element( j ) ) < 0 ) - { - swap( Element( j - 1 ), Element( j ) ); - } - } - } - } -} - -//----------------------------------------------------------------------------- -// Makes sure we have enough memory allocated to store a requested # of elements -//----------------------------------------------------------------------------- -template< typename T, class A > -void CUtlVector::EnsureCapacity( int num ) -{ - MEM_ALLOC_CREDIT_CLASS(); - m_Memory.EnsureCapacity(num); - ResetDbgInfo(); -} - - -//----------------------------------------------------------------------------- -// Makes sure we have at least this many elements -//----------------------------------------------------------------------------- -template< typename T, class A > -void CUtlVector::EnsureCount( int num ) -{ - if (Count() < num) - AddMultipleToTail( num - Count() ); -} - - -//----------------------------------------------------------------------------- -// Shifts elements -//----------------------------------------------------------------------------- -template< typename T, class A > -void CUtlVector::ShiftElementsRight( int elem, int num ) -{ - Assert( IsValidIndex(elem) || ( m_Size == 0 ) || ( num == 0 )); - int numToMove = m_Size - elem - num; - if ((numToMove > 0) && (num > 0)) - Q_memmove( &Element(elem+num), &Element(elem), numToMove * sizeof(T) ); -} - -template< typename T, class A > -void CUtlVector::ShiftElementsLeft( int elem, int num ) -{ - Assert( IsValidIndex(elem) || ( m_Size == 0 ) || ( num == 0 )); - int numToMove = m_Size - elem - num; - if ((numToMove > 0) && (num > 0)) - { - Q_memmove( &Element(elem), &Element(elem+num), numToMove * sizeof(T) ); - -#ifdef _DEBUG - Q_memset( &Element(m_Size-num), 0xDD, num * sizeof(T) ); -#endif - } -} - - -//----------------------------------------------------------------------------- -// Adds an element, uses default constructor -//----------------------------------------------------------------------------- -template< typename T, class A > -inline int CUtlVector::AddToHead() -{ - return InsertBefore(0); -} - -template< typename T, class A > -inline int CUtlVector::AddToTail() -{ - return InsertBefore( m_Size ); -} - -template< typename T, class A > -inline int CUtlVector::InsertAfter( int elem ) -{ - return InsertBefore( elem + 1 ); -} - -template< typename T, class A > -int CUtlVector::InsertBefore( int elem ) -{ - // Can insert at the end - Assert( (elem == Count()) || IsValidIndex(elem) ); - - GrowVector(); - ShiftElementsRight(elem); - Construct( &Element(elem) ); - return elem; -} - - -//----------------------------------------------------------------------------- -// Adds an element, uses copy constructor -//----------------------------------------------------------------------------- -template< typename T, class A > -inline int CUtlVector::AddToHead( const T& src ) -{ - // Can't insert something that's in the list... reallocation may hose us - Assert( (Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count()) ) ); - return InsertBefore( 0, src ); -} - -template< typename T, class A > -inline int CUtlVector::AddToTail( const T& src ) -{ - // Can't insert something that's in the list... reallocation may hose us - Assert( (Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count()) ) ); - return InsertBefore( m_Size, src ); -} - -template< typename T, class A > -inline int CUtlVector::InsertAfter( int elem, const T& src ) -{ - // Can't insert something that's in the list... reallocation may hose us - Assert( (Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count()) ) ); - return InsertBefore( elem + 1, src ); -} - -template< typename T, class A > -int CUtlVector::InsertBefore( int elem, const T& src ) -{ - // Can't insert something that's in the list... reallocation may hose us - Assert( (Base() == NULL) || (&src < Base()) || (&src >= (Base() + Count()) ) ); - - // Can insert at the end - Assert( (elem == Count()) || IsValidIndex(elem) ); - - GrowVector(); - ShiftElementsRight(elem); - CopyConstruct( &Element(elem), src ); - return elem; -} - - -//----------------------------------------------------------------------------- -// Adds multiple elements, uses default constructor -//----------------------------------------------------------------------------- -template< typename T, class A > -inline int CUtlVector::AddMultipleToHead( int num ) -{ - return InsertMultipleBefore( 0, num ); -} - -template< typename T, class A > -inline int CUtlVector::AddMultipleToTail( int num, const T *pToCopy ) -{ - // Can't insert something that's in the list... reallocation may hose us - Assert( (Base() == NULL) || !pToCopy || (pToCopy + num < Base()) || (pToCopy >= (Base() + Count()) ) ); - - return InsertMultipleBefore( m_Size, num, pToCopy ); -} - -template< typename T, class A > -int CUtlVector::InsertMultipleAfter( int elem, int num ) -{ - return InsertMultipleBefore( elem + 1, num ); -} - - -template< typename T, class A > -void CUtlVector::SetCount( int count ) -{ - RemoveAll(); - AddMultipleToTail( count ); -} - -template< typename T, class A > -inline void CUtlVector::SetSize( int size ) -{ - SetCount( size ); -} - -template< typename T, class A > -void CUtlVector::CopyArray( const T *pArray, int size ) -{ - // Can't insert something that's in the list... reallocation may hose us - Assert( (Base() == NULL) || !pArray || (Base() >= (pArray + size)) || (pArray >= (Base() + Count()) ) ); - - SetSize( size ); - for( int i=0; i < size; i++ ) - { - (*this)[i] = pArray[i]; - } -} - -template< typename T, class A > -void CUtlVector::Swap( CUtlVector< T, A > &vec ) -{ - m_Memory.Swap( vec.m_Memory ); - swap( m_Size, vec.m_Size ); - swap( m_pElements, vec.m_pElements ); -} - -template< typename T, class A > -int CUtlVector::AddVectorToTail( CUtlVector const &src ) -{ - Assert( &src != this ); - - int base = Count(); - - // Make space. - AddMultipleToTail( src.Count() ); - - // Copy the elements. - for ( int i=0; i < src.Count(); i++ ) - { - (*this)[base + i] = src[i]; - } - - return base; -} - -template< typename T, class A > -inline int CUtlVector::InsertMultipleBefore( int elem, int num, const T *pToInsert ) -{ - if( num == 0 ) - return elem; - - // Can insert at the end - Assert( (elem == Count()) || IsValidIndex(elem) ); - - GrowVector(num); - ShiftElementsRight(elem, num); - - // Invoke default constructors - for (int i = 0; i < num; ++i) - Construct( &Element(elem+i) ); - - // Copy stuff in? - if ( pToInsert ) - { - for ( int i=0; i < num; i++ ) - { - Element( elem+i ) = pToInsert[i]; - } - } - - return elem; -} - - -//----------------------------------------------------------------------------- -// Finds an element (element needs operator== defined) -//----------------------------------------------------------------------------- -template< typename T, class A > -int CUtlVector::Find( const T& src ) const -{ - for ( int i = 0; i < Count(); ++i ) - { - if (Element(i) == src) - return i; - } - return -1; -} - -template< typename T, class A > -bool CUtlVector::HasElement( const T& src ) const -{ - return ( Find(src) >= 0 ); -} - - -//----------------------------------------------------------------------------- -// Element removal -//----------------------------------------------------------------------------- -template< typename T, class A > -void CUtlVector::FastRemove( int elem ) -{ - Assert( IsValidIndex(elem) ); - - Destruct( &Element(elem) ); - if (m_Size > 0) - { - memcpy( &Element(elem), &Element(m_Size-1), sizeof(T) ); - --m_Size; - } -} - -template< typename T, class A > -void CUtlVector::Remove( int elem ) -{ - Destruct( &Element(elem) ); - ShiftElementsLeft(elem); - --m_Size; -} - -template< typename T, class A > -bool CUtlVector::FindAndRemove( const T& src ) -{ - int elem = Find( src ); - if ( elem != -1 ) - { - Remove( elem ); - return true; - } - return false; -} - -template< typename T, class A > -void CUtlVector::RemoveMultiple( int elem, int num ) -{ - Assert( elem >= 0 ); - Assert( elem + num <= Count() ); - - for (int i = elem + num; --i >= elem; ) - Destruct(&Element(i)); - - ShiftElementsLeft(elem, num); - m_Size -= num; -} - -template< typename T, class A > -void CUtlVector::RemoveAll() -{ - for (int i = m_Size; --i >= 0; ) - { - Destruct(&Element(i)); - } - - m_Size = 0; -} - - -//----------------------------------------------------------------------------- -// Memory deallocation -//----------------------------------------------------------------------------- - -template< typename T, class A > -inline void CUtlVector::Purge() -{ - RemoveAll(); - m_Memory.Purge(); - ResetDbgInfo(); -} - - -template< typename T, class A > -inline void CUtlVector::PurgeAndDeleteElements() -{ - for( int i=0; i < m_Size; i++ ) - { - delete Element(i); - } - Purge(); -} - -template< typename T, class A > -inline void CUtlVector::Compact() -{ - m_Memory.Purge(m_Size); -} - -template< typename T, class A > -inline int CUtlVector::NumAllocated() const -{ - return m_Memory.NumAllocated(); -} - - -//----------------------------------------------------------------------------- -// Data and memory validation -//----------------------------------------------------------------------------- -#ifdef DBGFLAG_VALIDATE -template< typename T, class A > -void CUtlVector::Validate( CValidator &validator, char *pchName ) -{ - validator.Push( typeid(*this).name(), this, pchName ); - - m_Memory.Validate( validator, "m_Memory" ); - - validator.Pop(); -} -#endif // DBGFLAG_VALIDATE - - -#endif // CCVECTOR_H diff --git a/public/tier2/beamsegdraw.h b/public/tier2/beamsegdraw.h deleted file mode 100644 index fc81177a9..000000000 --- a/public/tier2/beamsegdraw.h +++ /dev/null @@ -1,119 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// -#if !defined( BEAMSEGDRAW_H ) -#define BEAMSEGDRAW_H -#ifdef _WIN32 -#pragma once -#endif - -#define NOISE_DIVISIONS 128 - - -#include "mathlib/vector.h" -#include "materialsystem/imesh.h" - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -struct BeamTrail_t; -class IMaterial; - - -//----------------------------------------------------------------------------- -// CBeamSegDraw is a simple interface to beam rendering. -//----------------------------------------------------------------------------- -struct BeamSeg_t -{ - Vector m_vPos; - Vector m_vColor; - float m_flTexCoord; // Y texture coordinate - float m_flWidth; - float m_flAlpha; -}; - -class CBeamSegDraw -{ -public: - CBeamSegDraw() : m_pRenderContext( NULL ) {} - // Pass null for pMaterial if you have already set the material you want. - void Start( IMatRenderContext *pRenderContext, int nSegs, IMaterial *pMaterial=0, CMeshBuilder *pMeshBuilder = NULL, int nMeshVertCount = 0 ); - virtual void NextSeg( BeamSeg_t *pSeg ); - void End(); - -protected: - void SpecifySeg( const Vector &vecCameraPos, const Vector &vNextPos ); - void ComputeNormal( const Vector &vecCameraPos, const Vector &vStartPos, const Vector &vNextPos, Vector *pNormal ); - - CMeshBuilder *m_pMeshBuilder; - int m_nMeshVertCount; - - CMeshBuilder m_Mesh; - BeamSeg_t m_Seg; - - int m_nTotalSegs; - int m_nSegsDrawn; - - Vector m_vNormalLast; - IMatRenderContext *m_pRenderContext; -}; - -class CBeamSegDrawArbitrary : public CBeamSegDraw -{ -public: - void SetNormal( const Vector &normal ); - void NextSeg( BeamSeg_t *pSeg ); - -protected: - void SpecifySeg( const Vector &vNextPos ); - - BeamSeg_t m_PrevSeg; -}; - -#if 0 -int ScreenTransform( const Vector& point, Vector& screen ); - -void DrawSegs( int noise_divisions, float *prgNoise, const model_t* spritemodel, - float frame, int rendermode, const Vector& source, const Vector& delta, - float startWidth, float endWidth, float scale, float freq, float speed, int segments, - int flags, float* color, float fadeLength, float flHDRColorScale = 1.0f ); -void DrawTeslaSegs( int noise_divisions, float *prgNoise, const model_t* spritemodel, - float frame, int rendermode, const Vector& source, const Vector& delta, - float startWidth, float endWidth, float scale, float freq, float speed, int segments, - int flags, float* color, float fadeLength, float flHDRColorScale = 1.0f ); -void DrawSplineSegs( int noise_divisions, float *prgNoise, - const model_t* beammodel, const model_t* halomodel, float flHaloScale, - float frame, int rendermode, int numAttachments, Vector* attachment, - float startWidth, float endWidth, float scale, float freq, float speed, int segments, - int flags, float* color, float fadeLength, float flHDRColorScale = 1.0f ); -void DrawHalo(IMaterial* pMaterial, const Vector& source, float scale, float const* color, float flHDRColorScale = 1.0f ); -void BeamDrawHalo( const model_t* spritemodel, float frame, int rendermode, const Vector& source, - float scale, float* color, float flHDRColorScale = 1.0f ); -void DrawDisk( int noise_divisions, float *prgNoise, const model_t* spritemodel, - float frame, int rendermode, const Vector& source, const Vector& delta, - float width, float scale, float freq, float speed, - int segments, float* color, float flHDRColorScale = 1.0f ); -void DrawCylinder( int noise_divisions, float *prgNoise, const model_t* spritemodel, - float frame, int rendermode, const Vector& source, - const Vector& delta, float width, float scale, float freq, - float speed, int segments, float* color, float flHDRColorScale = 1.0f ); -void DrawRing( int noise_divisions, float *prgNoise, void (*pfnNoise)( float *noise, int divs, float scale ), - const model_t* spritemodel, float frame, int rendermode, - const Vector& source, const Vector& delta, float width, float amplitude, - float freq, float speed, int segments, float* color, float flHDRColorScale = 1.0f ); -void DrawBeamFollow( const model_t* spritemodel, BeamTrail_t* pHead, int frame, int rendermode, Vector& delta, - Vector& screen, Vector& screenLast, float die, const Vector& source, - int flags, float width, float amplitude, float freq, float* color, float flHDRColorScale = 1.0f ); - -void DrawBeamQuadratic( const Vector &start, const Vector &control, const Vector &end, float width, const Vector &color, float scrollOffset, float flHDRColorScale = 1.0f ); -#endif - -//----------------------------------------------------------------------------- -// Assumes the material has already been bound -//----------------------------------------------------------------------------- -void DrawSprite( const Vector &vecOrigin, float flWidth, float flHeight, color32 color ); - -#endif // BEAMDRAW_H diff --git a/public/tier2/camerautils.h b/public/tier2/camerautils.h deleted file mode 100644 index 491988c1f..000000000 --- a/public/tier2/camerautils.h +++ /dev/null @@ -1,57 +0,0 @@ -//===== Copyright 2005-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: A set of utilities to deal with camera transforms -// -//===========================================================================// - -#ifndef CAMERAUTILS_H -#define CAMERAUTILS_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier2/tier2.h" -#include "Color.h" - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class Vector; -class QAngle; -class IMaterial; -struct matrix3x4_t; -class VMatrix; - - -//----------------------------------------------------------------------------- -// Camera state -// TODO: Maybe this should be a base class of CViewSetup? -//----------------------------------------------------------------------------- -struct Camera_t -{ - Vector m_origin; - QAngle m_angles; - float m_flFOV; - float m_flZNear; - float m_flZFar; -}; - - -//----------------------------------------------------------------------------- -// accessors for generated matrices -//----------------------------------------------------------------------------- -void ComputeViewMatrix( VMatrix *pWorldToCamera, const Camera_t& camera ); -void ComputeViewMatrix( matrix3x4_t *pWorldToCamera, const Camera_t& camera ); -void ComputeProjectionMatrix( VMatrix *pCameraToProjection, const Camera_t& camera, int width, int height ); - - -//----------------------------------------------------------------------------- -// Computes the screen space position given a screen size -//----------------------------------------------------------------------------- -void ComputeScreenSpacePosition( Vector2D *pScreenPosition, const Vector &vecWorldPosition, - const Camera_t &camera, int width, int height ); - - -#endif // CAMERAUTILS_H - diff --git a/public/tier2/fileutils.h b/public/tier2/fileutils.h deleted file mode 100644 index 00aecf50c..000000000 --- a/public/tier2/fileutils.h +++ /dev/null @@ -1,249 +0,0 @@ -//===== Copyright 2005-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: A higher level link library for general use in the game and tools. -// -//===========================================================================// - - -#ifndef FILEUTILS_H -#define FILEUTILS_H - -#if defined( _WIN32 ) -#pragma once -#endif - -#ifndef TIER2_H -#include "tier2/tier2.h" -#endif - -#ifndef FILESYSTEM_H -#include "filesystem.h" -#endif - -#include "tier0/platform.h" - -// Builds a directory which is a subdirectory of the current mod -void GetModSubdirectory( const char *pSubDir, char *pBuf, int nBufLen ); - -// Builds a directory which is a subdirectory of the current mod's *content* -void GetModContentSubdirectory( const char *pSubDir, char *pBuf, int nBufLen ); - -// Builds a list of all files under a directory with a particular extension -void AddFilesToList( CUtlVector< CUtlString > &list, const char *pDirectory, const char *pPath, const char *pExtension ); - -// Returns the search path as a list of paths -void GetSearchPath( CUtlVector< CUtlString > &path, const char *pPathID ); - -// Generates a .360 file if it doesn't exist or is out of sync with the pc source file -#define UOC_FAIL -1 -#define UOC_NOT_CREATED 0 -#define UOC_CREATED 1 -typedef bool ( *CreateCallback_t )( const char *pSourceName, const char *pTargetName, const char *pPathID, void *pExtraData ); -int UpdateOrCreate( const char *pSourceName, char *pTargetName, int targetLen, const char *pPathID, CreateCallback_t pfnCreate, bool bForce = false, void *pExtraData = NULL ); - -char *CreateX360Filename( const char *pSourceName, char *pTargetName, int targetLen ); - -// simple file classes. File I/O mode (text/binary, read/write) is based upon the subclass chosen. -// classes with the word Required on them abort with a message if the file can't be opened. -// destructores close the file handle, or it can be explicitly closed with the Close() method. - -class CBaseFile -{ -public: - FileHandle_t m_FileHandle; - - CBaseFile(void) - { - m_FileHandle = FILESYSTEM_INVALID_HANDLE; - } - - ~CBaseFile( void ) - { - Close(); - } - - void Close( void ) - { - if ( m_FileHandle != FILESYSTEM_INVALID_HANDLE ) - g_pFullFileSystem->Close( m_FileHandle ); - m_FileHandle = FILESYSTEM_INVALID_HANDLE; - } - - void Open( char const *fname, char const *modes ) - { - Close(); - m_FileHandle = g_pFullFileSystem->Open( fname, modes ); - } - - char *ReadLine( char *pOutput, int maxChars ) - { - return g_pFullFileSystem->ReadLine( pOutput, maxChars, m_FileHandle ); - } - - int Read( void* pOutput, int size ) - { - return g_pFullFileSystem->Read( pOutput, size, m_FileHandle ); - } - - void MustRead( void* pOutput, int size ) - { - int ret=Read( pOutput, size ); - if (ret != size ) - Error("failed to read %d bytes\n"); - } - - int Write( void const* pInput, int size) - { - return g_pFullFileSystem->Write( pInput, size, m_FileHandle ); - } - - - // {Get|Put}{Int|Float} read and write ints and floats from a file in x86 order, swapping on - // input for big-endian systems. - void PutInt( int n ) - { - int n1=LittleDWord( n ); - Write(&n1, sizeof( n1 ) ); - } - - int GetInt( void ) - { - int ret; - MustRead( &ret, sizeof( ret )); - return LittleDWord( ret ); - } - - float GetFloat( void ) - { - float ret; - MustRead( &ret, sizeof( ret )); - LittleFloat( &ret, &ret ); - return ret; - } - void PutFloat( float f ) - { - LittleFloat( &f, &f ); - Write( &f, sizeof( f ) ); - } - - bool IsOk( void ) - { - return ( m_FileHandle != FILESYSTEM_INVALID_HANDLE) && - ( g_pFullFileSystem->IsOk( m_FileHandle ) ); - } -}; - -class COutputFile : public CBaseFile -{ -public: - void Open( char const *pFname ) - { - CBaseFile::Open( pFname, "wb" ); - } - - COutputFile( char const *pFname ) : CBaseFile() - { - Open( pFname ); - } - - COutputFile( void ) : CBaseFile() - { - } -}; - -class COutputTextFile : public CBaseFile -{ -public: - void Open( char const *pFname ) - { - CBaseFile::Open( pFname, "w" ); - } - - COutputTextFile( char const *pFname ) : CBaseFile() - { - Open( pFname ); - } - - COutputTextFile( void ) : CBaseFile() - { - } -}; - -class CInputFile : public CBaseFile -{ -public: - void Open( char const *pFname ) - { - CBaseFile::Open( pFname, "rb" ); - } - - CInputFile( char const *pFname ) : CBaseFile() - { - Open( pFname ); - } - CInputFile( void ) : CBaseFile() - { - } -}; - -class CInputTextFile : public CBaseFile -{ -public: - void Open( char const *pFname ) - { - CBaseFile::Open( pFname, "r" ); - } - - CInputTextFile( char const *pFname ) : CBaseFile() - { - Open( pFname ); - } - CInputTextFile( void ) : CBaseFile() - { - } -}; - -class CRequiredInputTextFile : public CBaseFile -{ -public: - void Open( char const *pFname ) - { - CBaseFile::Open( pFname, "r" ); - if ( ! IsOk() ) - { - Error("error opening required file %s\n", pFname ); - } - } - - CRequiredInputTextFile( char const *pFname ) : CBaseFile() - { - Open( pFname ); - } - CRequiredInputTextFile( void ) : CBaseFile() - { - } -}; - -class CRequiredInputFile : public CBaseFile -{ -public: - void Open( char const *pFname ) - { - CBaseFile::Open( pFname, "rb" ); - if ( ! IsOk() ) - { - Error("error opening required file %s\n", pFname ); - } - } - - CRequiredInputFile( char const *pFname ) : CBaseFile() - { - Open( pFname ); - } - CRequiredInputFile( void ) : CBaseFile() - { - } -}; - -#endif // FILEUTILS_H - diff --git a/public/tier2/keybindings.h b/public/tier2/keybindings.h deleted file mode 100644 index e74b740b9..000000000 --- a/public/tier2/keybindings.h +++ /dev/null @@ -1,42 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -// -//===========================================================================// - -#ifndef KEYBINDINGS_H -#define KEYBINDINGS_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/utlstring.h" -#include "inputsystem/ButtonCode.h" - -class CUtlBuffer; - - -class CKeyBindings -{ -public: - void SetBinding( ButtonCode_t code, const char *pBinding ); - void SetBinding( const char *pButtonName, const char *pBinding ); - - void Unbind( ButtonCode_t code ); - void Unbind( const char *pButtonName ); - void UnbindAll(); - - int GetBindingCount() const; - void WriteBindings( CUtlBuffer &buf ); - const char *ButtonNameForBinding( const char *pBinding ); - const char *GetBindingForButton( ButtonCode_t code ); - -private: - CUtlString m_KeyInfo[ BUTTON_CODE_LAST ]; -}; - - -#endif // KEYBINDINGS_H diff --git a/public/tier2/meshutils.h b/public/tier2/meshutils.h deleted file mode 100644 index 8907c6dcd..000000000 --- a/public/tier2/meshutils.h +++ /dev/null @@ -1,26 +0,0 @@ -//===== Copyright 2005-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: A set of utilities to help with generating meshes -// -//===========================================================================// - -#ifndef MESHUTILS_H -#define MESHUTILS_H - -#ifdef _WIN32 -#pragma once -#endif - - -//----------------------------------------------------------------------------- -// Helper methods to create various standard index buffer types -//----------------------------------------------------------------------------- -void GenerateSequentialIndexBuffer( unsigned short* pIndexMemory, int nIndexCount, int nFirstVertex ); -void GenerateQuadIndexBuffer( unsigned short* pIndexMemory, int nIndexCount, int nFirstVertex ); -void GeneratePolygonIndexBuffer( unsigned short* pIndexMemory, int nIndexCount, int nFirstVertex ); -void GenerateLineStripIndexBuffer( unsigned short* pIndexMemory, int nIndexCount, int nFirstVertex ); -void GenerateLineLoopIndexBuffer( unsigned short* pIndexMemory, int nIndexCount, int nFirstVertex ); - - -#endif // MESHUTILS_H - diff --git a/public/tier2/p4helpers.h b/public/tier2/p4helpers.h deleted file mode 100644 index c8fdad3e7..000000000 --- a/public/tier2/p4helpers.h +++ /dev/null @@ -1,138 +0,0 @@ -//====== Copyright c 1996-2007, Valve Corporation, All rights reserved. =======// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef P4HELPERS_H -#define P4HELPERS_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "tier1/utlstring.h" -#include "tier1/smartptr.h" - - -// -// Class representing file operations -// -class CP4File -{ -public: - explicit CP4File( char const *szFilename ); - virtual ~CP4File(); - -public: - // Opens the file for edit - virtual bool Edit( void ); - - // Opens the file for add - virtual bool Add( void ); - - // Is the file in perforce? - virtual bool IsFileInPerforce(); - -protected: - // The filename that this class instance represents - CUtlString m_sFilename; -}; - -// -// An override of CP4File performing no Perforce interaction -// -class CP4File_Dummy : public CP4File -{ -public: - explicit CP4File_Dummy( char const *szFilename ) : CP4File( szFilename ) {} - -public: - virtual bool Edit( void ) { return true; } - virtual bool Add( void ) { return true; } - virtual bool IsFileInPerforce() { return false; } -}; - - -// -// Class representing a factory for creating other helper objects -// -class CP4Factory -{ -public: - CP4Factory(); - ~CP4Factory(); - -public: - // Sets whether dummy objects are created by the factory. - // Returns the old state of the dummy mode. - bool SetDummyMode( bool bDummyMode ); - -public: - // Sets the name of the changelist to open files under, - // NULL for "Default" changelist. - void SetOpenFileChangeList( const char *szChangeListName ); - -public: - // Creates a file access object for the given filename. - CP4File *AccessFile( char const *szFilename ) const; - -protected: - // Whether the factory is in the "dummy mode" and is creating dummy objects - bool m_bDummyMode; -}; - -// Default p4 factory -extern CP4Factory *g_p4factory; - - -// -// CP4AutoEditFile - edits the file upon construction -// -class CP4AutoEditFile -{ -public: - explicit CP4AutoEditFile( char const *szFilename ) : m_spImpl( g_p4factory->AccessFile( szFilename ) ) { m_spImpl->Edit(); } - - CP4File * File() const { return m_spImpl.Get(); } - -protected: - CPlainAutoPtr< CP4File > m_spImpl; -}; - -// -// CP4AutoAddFile - adds the file upon construction -// -class CP4AutoAddFile -{ -public: - explicit CP4AutoAddFile( char const *szFilename ) : m_spImpl( g_p4factory->AccessFile( szFilename ) ) { m_spImpl->Add(); } - - CP4File * File() const { return m_spImpl.Get(); } - -protected: - CPlainAutoPtr< CP4File > m_spImpl; -}; - -// -// CP4AutoEditAddFile - edits the file upon construction / adds upon destruction -// -class CP4AutoEditAddFile -{ -public: - explicit CP4AutoEditAddFile( char const *szFilename ) : m_spImpl( g_p4factory->AccessFile( szFilename ) ) - { - m_spImpl->Edit(); - } - ~CP4AutoEditAddFile( void ) { m_spImpl->Add(); } - - CP4File * File() const { return m_spImpl.Get(); } - -protected: - CPlainAutoPtr< CP4File > m_spImpl; -}; - - -#endif // #ifndef P4HELPERS_H diff --git a/public/tier2/renderutils.h b/public/tier2/renderutils.h deleted file mode 100644 index 211a58999..000000000 --- a/public/tier2/renderutils.h +++ /dev/null @@ -1,68 +0,0 @@ -//===== Copyright 2005-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: A set of utilities to render standard shapes -// -//===========================================================================// - -#ifndef RENDERUTILS_H -#define RENDERUTILS_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier2/tier2.h" -#include "Color.h" - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class Vector; -class QAngle; -class IMaterial; -struct matrix3x4_t; - - -// Renders a wireframe sphere -void RenderWireframeSphere( const Vector &vCenter, float flRadius, int nTheta, int nPhi, Color c, bool bZBuffer ); - -// Renders a sphere -void RenderSphere( const Vector &vCenter, float flRadius, int nTheta, int nPhi, Color c, bool bZBuffer ); -void RenderSphere( const Vector &vCenter, float flRadius, int nTheta, int nPhi, Color c, IMaterial *pMaterial ); - -// Renders a wireframe box relative to an origin -void RenderWireframeBox( const Vector &vOrigin, const QAngle& angles, const Vector &vMins, const Vector &vMaxs, Color c, bool bZBuffer ); - -// Renders a swept wireframe box -void RenderWireframeSweptBox( const Vector &vStart, const Vector &vEnd, const QAngle &angles, const Vector &vMins, const Vector &vMaxs, Color c, bool bZBuffer ); - -// Renders a solid box -void RenderBox( const Vector& origin, const QAngle& angles, const Vector& mins, const Vector& maxs, Color c, bool bZBuffer, bool bInsideOut = false ); -void RenderBox( const Vector& origin, const QAngle& angles, const Vector& mins, const Vector& maxs, Color c, IMaterial *pMaterial, bool bInsideOut = false ); - -// Renders axes, red->x, green->y, blue->z (axis aligned) -void RenderAxes( const Vector &vOrigin, float flScale, bool bZBuffer ); -void RenderAxes( const matrix3x4_t &transform, float flScale, bool bZBuffer ); - -// Render a line -void RenderLine( const Vector& v1, const Vector& v2, Color c, bool bZBuffer ); - -// Draws a triangle -void RenderTriangle( const Vector& p1, const Vector& p2, const Vector& p3, Color c, bool bZBuffer ); -void RenderTriangle( const Vector& p1, const Vector& p2, const Vector& p3, Color c, IMaterial *pMaterial ); - -// Draws a axis-aligned quad -void RenderQuad( IMaterial *pMaterial, float x, float y, float w, float h, float z, float s0, float t0, float s1, float t1, const Color& clr ); - -// Renders a screen space quad -void DrawScreenSpaceRectangle( IMaterial *pMaterial, - int nDestX, int nDestY, int nWidth, int nHeight, // Rect to draw into in screen space - float flSrcTextureX0, float flSrcTextureY0, // which texel you want to appear at destx/y - float flSrcTextureX1, float flSrcTextureY1, // which texel you want to appear at destx+width-1, desty+height-1 - int nSrcTextureWidth, int nSrcTextureHeight, // needed for fixup - void *pClientRenderable = NULL, // Used to pass to the bind proxies - int nXDice = 1, - int nYDice = 1 ); - -#endif // RENDERUTILS_H - diff --git a/public/tier2/riff.h b/public/tier2/riff.h deleted file mode 100644 index 872954003..000000000 --- a/public/tier2/riff.h +++ /dev/null @@ -1,202 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef RIFF_H -#define RIFF_H -#pragma once - -#include "commonmacros.h" - - -//----------------------------------------------------------------------------- -// Purpose: This is a simple abstraction that the RIFF classes use to read from -// files/memory -//----------------------------------------------------------------------------- -class IFileReadBinary -{ -public: - virtual int open( const char *pFileName ) = 0; - virtual int read( void *pOutput, int size, int file ) = 0; - virtual void close( int file ) = 0; - virtual void seek( int file, int pos ) = 0; - virtual unsigned int tell( int file ) = 0; - virtual unsigned int size( int file ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Used to read/parse a RIFF format file -//----------------------------------------------------------------------------- -class InFileRIFF -{ -public: - InFileRIFF( const char *pFileName, IFileReadBinary &io ); - ~InFileRIFF( void ); - - unsigned int RIFFName( void ) { return m_riffName; } - unsigned int RIFFSize( void ) { return m_riffSize; } - - int ReadInt( void ); - int ReadData( void *pOutput, int dataSize ); - int PositionGet( void ); - void PositionSet( int position ); - bool IsValid( void ) { return m_file != 0; } - -private: - const InFileRIFF & operator=( const InFileRIFF & ); - - IFileReadBinary &m_io; - int m_file; - unsigned int m_riffName; - unsigned int m_riffSize; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Used to iterate over an InFileRIFF -//----------------------------------------------------------------------------- -class IterateRIFF -{ -public: - IterateRIFF( InFileRIFF &riff, int size ); - IterateRIFF( IterateRIFF &parent ); - - bool ChunkAvailable( void ); - bool ChunkNext( void ); - - unsigned int ChunkName( void ); - unsigned int ChunkSize( void ); - int ChunkRead( void *pOutput ); - int ChunkReadPartial( void *pOutput, int dataSize ); - int ChunkReadInt( void ); - int ChunkFilePosition( void ) { return m_chunkPosition; } - -private: - const IterateRIFF & operator=( const IterateRIFF & ); - - void ChunkSetup( void ); - void ChunkClear( void ); - - InFileRIFF &m_riff; - int m_start; - int m_size; - - unsigned int m_chunkName; - int m_chunkSize; - int m_chunkPosition; -}; - -class IFileWriteBinary -{ -public: - virtual int create( const char *pFileName ) = 0; - virtual int write( void *pData, int size, int file ) = 0; - virtual void close( int file ) = 0; - virtual void seek( int file, int pos ) = 0; - virtual unsigned int tell( int file ) = 0; -}; -//----------------------------------------------------------------------------- -// Purpose: Used to write a RIFF format file -//----------------------------------------------------------------------------- -class OutFileRIFF -{ -public: - OutFileRIFF( const char *pFileName, IFileWriteBinary &io ); - ~OutFileRIFF( void ); - - bool WriteInt( int number ); - bool WriteData( void *pOutput, int dataSize ); - int PositionGet( void ); - void PositionSet( int position ); - bool IsValid( void ) { return m_file != 0; } - - void HasLISETData( int position ); - -private: - const OutFileRIFF & operator=( const OutFileRIFF & ); - - IFileWriteBinary &m_io; - int m_file; - unsigned int m_riffName; - unsigned int m_riffSize; - unsigned int m_nNamePos; - - // hack to make liset work correctly - bool m_bUseIncorrectLISETLength; - int m_nLISETSize; - - -}; - -//----------------------------------------------------------------------------- -// Purpose: Used to iterate over an InFileRIFF -//----------------------------------------------------------------------------- -class IterateOutputRIFF -{ -public: - IterateOutputRIFF( OutFileRIFF &riff ); - IterateOutputRIFF( IterateOutputRIFF &parent ); - - void ChunkStart( unsigned int chunkname ); - void ChunkFinish( void ); - - void ChunkWrite( unsigned int chunkname, void *pOutput, int size ); - void ChunkWriteInt( int number ); - void ChunkWriteData( void *pOutput, int size ); - - int ChunkFilePosition( void ) { return m_chunkPosition; } - - unsigned int ChunkGetPosition( void ); - void ChunkSetPosition( int position ); - - void CopyChunkData( IterateRIFF& input ); - - void SetLISETData( int position ); - -private: - - const IterateOutputRIFF & operator=( const IterateOutputRIFF & ); - - OutFileRIFF &m_riff; - int m_start; - int m_size; - - unsigned int m_chunkName; - int m_chunkSize; - int m_chunkPosition; - int m_chunkStart; -}; - -#define RIFF_ID MAKEID('R','I','F','F') -#define RIFF_WAVE MAKEID('W','A','V','E') -#define WAVE_FMT MAKEID('f','m','t',' ') -#define WAVE_DATA MAKEID('d','a','t','a') -#define WAVE_FACT MAKEID('f','a','c','t') -#define WAVE_CUE MAKEID('c','u','e',' ') -#define WAVE_SAMPLER MAKEID('s','m','p','l') -#define WAVE_VALVEDATA MAKEID('V','D','A','T') -#define WAVE_PADD MAKEID('P','A','D','D') -#define WAVE_LIST MAKEID('L','I','S','T') - -#ifndef WAVE_FORMAT_PCM -#define WAVE_FORMAT_PCM 0x0001 -#endif -#ifndef WAVE_FORMAT_ADPCM -#define WAVE_FORMAT_ADPCM 0x0002 -#endif -#define WAVE_FORMAT_XBOX_ADPCM 0x0069 -#ifndef WAVE_FORMAT_XMA -#define WAVE_FORMAT_XMA 0x0165 -#endif - -#endif // RIFF_H diff --git a/public/tier2/soundutils.h b/public/tier2/soundutils.h deleted file mode 100644 index c44fbbff1..000000000 --- a/public/tier2/soundutils.h +++ /dev/null @@ -1,31 +0,0 @@ -//===== Copyright 2005-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: Helper methods + classes for sound -// -//===========================================================================// - -#ifndef SOUNDUTILS_H -#define SOUNDUTILS_H - -#if defined( _WIN32 ) -#pragma once -#endif - -#include "tier2/riff.h" - - -//----------------------------------------------------------------------------- -// RIFF reader/writers that use the file system -//----------------------------------------------------------------------------- -extern IFileReadBinary *g_pFSIOReadBinary; -extern IFileWriteBinary *g_pFSIOWriteBinary; - - -//----------------------------------------------------------------------------- -// Returns the duration of a wav file -//----------------------------------------------------------------------------- -float GetWavSoundDuration( const char *pWavFile ); - - -#endif // SOUNDUTILS_H - diff --git a/public/tier2/tier2.h b/public/tier2/tier2.h deleted file mode 100644 index 0f7b0f7c4..000000000 --- a/public/tier2/tier2.h +++ /dev/null @@ -1,128 +0,0 @@ -//===== Copyright 2005-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: A higher level link library for general use in the game and tools. -// -//===========================================================================// - - -#ifndef TIER2_H -#define TIER2_H - -#if defined( _WIN32 ) -#pragma once -#endif - -#include "tier1/tier1.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class IFileSystem; -class IMaterialSystem; -class IColorCorrectionSystem; -class IMaterialSystemHardwareConfig; -class IDebugTextureInfo; -class IVBAllocTracker; -class IInputSystem; -class INetworkSystem; -class IP4; -class IMdlLib; -class IQueuedLoader; - - -//----------------------------------------------------------------------------- -// These tier2 libraries must be set by any users of this library. -// They can be set by calling ConnectTier2Libraries or InitDefaultFileSystem. -// It is hoped that setting this, and using this library will be the common mechanism for -// allowing link libraries to access tier2 library interfaces -//----------------------------------------------------------------------------- -extern IFileSystem *g_pFullFileSystem; -extern IMaterialSystem *materials; -extern IMaterialSystem *g_pMaterialSystem; -extern IInputSystem *g_pInputSystem; -extern INetworkSystem *g_pNetworkSystem; -extern IMaterialSystemHardwareConfig *g_pMaterialSystemHardwareConfig; -extern IDebugTextureInfo *g_pMaterialSystemDebugTextureInfo; -extern IVBAllocTracker *g_VBAllocTracker; -extern IColorCorrectionSystem *colorcorrection; -extern IP4 *p4; -extern IMdlLib *mdllib; -extern IQueuedLoader *g_pQueuedLoader; - - -//----------------------------------------------------------------------------- -// Call this to connect to/disconnect from all tier 2 libraries. -// It's up to the caller to check the globals it cares about to see if ones are missing -//----------------------------------------------------------------------------- -void ConnectTier2Libraries( CreateInterfaceFn *pFactoryList, int nFactoryCount ); -void DisconnectTier2Libraries(); - - -//----------------------------------------------------------------------------- -// Call this to get the file system set up to stdio for utilities, etc: -//----------------------------------------------------------------------------- -void InitDefaultFileSystem(void); -void ShutdownDefaultFileSystem(void); - - -//----------------------------------------------------------------------------- -// for simple utilities using valve libraries, call the entry point below in main(). It will -// init a filesystem for you, init mathlib, and create the command line. -//----------------------------------------------------------------------------- -void InitCommandLineProgram( int argc, char **argv ); - - -//----------------------------------------------------------------------------- -// Helper empty implementation of an IAppSystem for tier2 libraries -//----------------------------------------------------------------------------- -template< class IInterface, int ConVarFlag = 0 > -class CTier2AppSystem : public CTier1AppSystem< IInterface, ConVarFlag > -{ - typedef CTier1AppSystem< IInterface, ConVarFlag > BaseClass; - -public: - CTier2AppSystem( bool bIsPrimaryAppSystem = true ) : BaseClass( bIsPrimaryAppSystem ) - { - } - - virtual bool Connect( CreateInterfaceFn factory ) - { - if ( !BaseClass::Connect( factory ) ) - return false; - - if ( CTier0AppSystem::IsPrimaryAppSystem() ) - { - ConnectTier2Libraries( &factory, 1 ); - } - - return true; - } - - virtual InitReturnVal_t Init() - { - InitReturnVal_t nRetVal = BaseClass::Init(); - if ( nRetVal != INIT_OK ) - return nRetVal; - - return INIT_OK; - } - - virtual void Shutdown() - { - BaseClass::Shutdown(); - } - - virtual void Disconnect() - { - if ( CTier0AppSystem::IsPrimaryAppSystem() ) - { - DisconnectTier2Libraries(); - } - BaseClass::Disconnect(); - } -}; - - -#endif // TIER2_H - diff --git a/public/tier2/tier2dm.h b/public/tier2/tier2dm.h deleted file mode 100644 index a45844140..000000000 --- a/public/tier2/tier2dm.h +++ /dev/null @@ -1,76 +0,0 @@ -//===== Copyright 2005-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: A higher level link library for general use in the game and tools. -// -//===========================================================================// - - -#ifndef TIER2DM_H -#define TIER2DM_H - -#if defined( _WIN32 ) -#pragma once -#endif - -#include "tier2/tier2.h" - -//----------------------------------------------------------------------------- -// Set up methods related to datamodel interfaces -//----------------------------------------------------------------------------- -bool ConnectDataModel( CreateInterfaceFn factory ); -InitReturnVal_t InitDataModel(); -void ShutdownDataModel(); -void DisconnectDataModel(); - -//----------------------------------------------------------------------------- -// Helper empty implementation of an IAppSystem for tier2 libraries -//----------------------------------------------------------------------------- -template< class IInterface, int ConVarFlag = 0 > -class CTier2DmAppSystem : public CTier2AppSystem< IInterface, ConVarFlag > -{ - typedef CTier2AppSystem< IInterface, ConVarFlag > BaseClass; - -public: - CTier2DmAppSystem( bool bIsPrimaryAppSystem = true ) : BaseClass( bIsPrimaryAppSystem ) - { - } - - virtual bool Connect( CreateInterfaceFn factory ) - { - if ( !BaseClass::Connect( factory ) ) - return false; - - ConnectDataModel( factory ); - - return true; - } - - virtual InitReturnVal_t Init() - { - InitReturnVal_t nRetVal = BaseClass::Init(); - if ( nRetVal != INIT_OK ) - return nRetVal; - - nRetVal = InitDataModel(); - if ( nRetVal != INIT_OK ) - return nRetVal; - - return INIT_OK; - } - - virtual void Shutdown() - { - ShutdownDataModel(); - BaseClass::Shutdown(); - } - - virtual void Disconnect() - { - DisconnectDataModel(); - BaseClass::Disconnect(); - } -}; - - -#endif // TIER2DM_H - diff --git a/public/tier2/utlstreambuffer.h b/public/tier2/utlstreambuffer.h deleted file mode 100644 index 5086e5f4a..000000000 --- a/public/tier2/utlstreambuffer.h +++ /dev/null @@ -1,70 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======// -// -// Purpose: -// -// $NoKeywords: $ -// -// Serialization/unserialization buffer -//=============================================================================// - -#ifndef UTLSTREAMBUFFER_H -#define UTLSTREAMBUFFER_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/utlbuffer.h" -#include "filesystem.h" - - -//----------------------------------------------------------------------------- -// Command parsing.. -//----------------------------------------------------------------------------- -class CUtlStreamBuffer : public CUtlBuffer -{ - typedef CUtlBuffer BaseClass; - -public: - // See CUtlBuffer::BufferFlags_t for flags - CUtlStreamBuffer( ); - CUtlStreamBuffer( const char *pFileName, const char *pPath, int nFlags = 0, bool bDelayOpen = false ); - ~CUtlStreamBuffer(); - - // Open the file. normally done in constructor - void Open( const char *pFileName, const char *pPath, int nFlags ); - - // close the file. normally done in destructor - void Close(); - - // Is the file open? - bool IsOpen() const; - -private: - // error flags - enum - { - FILE_OPEN_ERROR = MAX_ERROR_FLAG << 1, - }; - - // Overflow functions - bool StreamPutOverflow( int nSize ); - bool StreamGetOverflow( int nSize ); - - // Grow allocation size to fit requested size - void GrowAllocatedSize( int nSize ); - - // Reads bytes from the file; fixes up maxput if necessary and null terminates - int ReadBytesFromFile( int nBytesToRead, int nReadOffset ); - - FileHandle_t OpenFile( const char *pFileName, const char *pPath ); - - FileHandle_t m_hFileHandle; - - char *m_pFileName; - char *m_pPath; -}; - - -#endif // UTLSTREAMBUFFER_H - diff --git a/public/tier2/vconfig.h b/public/tier2/vconfig.h deleted file mode 100644 index 7492bdd2c..000000000 --- a/public/tier2/vconfig.h +++ /dev/null @@ -1,27 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: Utilities for setting vproject settings -// -//===========================================================================// - -#ifndef _VCONFIG_H -#define _VCONFIG_H - -#ifdef _WIN32 -#pragma once -#endif - - -// The registry keys that vconfig uses to store the current vproject directory. -#define VPROJECT_REG_KEY "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment" - -// For accessing the environment variables we store the current vproject in. -void SetVConfigRegistrySetting( const char *pName, const char *pValue, bool bNotify = true ); -bool GetVConfigRegistrySetting( const char *pName, char *pReturn, int size ); -#ifdef _WIN32 -bool RemoveObsoleteVConfigRegistrySetting( const char *pValueName, char *pOldValue = NULL , int size = 0 ); -#endif -bool ConvertObsoleteVConfigRegistrySetting( const char *pValueName ); - - -#endif // _VCONFIG_H diff --git a/public/tier3/choreoutils.h b/public/tier3/choreoutils.h deleted file mode 100644 index 55d35afbe..000000000 --- a/public/tier3/choreoutils.h +++ /dev/null @@ -1,39 +0,0 @@ -//===== Copyright 2005-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: Helper methods + classes for choreo -// -//===========================================================================// - -#ifndef CHOREOUTILS_H -#define CHOREOUTILS_H - -#if defined( _WIN32 ) -#pragma once -#endif - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class CChoreoScene; -class CChoreoEvent; -class CStudioHdr; - - -//----------------------------------------------------------------------------- -// Finds sound files associated with events -//----------------------------------------------------------------------------- -const char *GetSoundForEvent( CChoreoEvent *pEvent, CStudioHdr *pStudioHdr ); - - -//----------------------------------------------------------------------------- -// Fixes up the duration of a choreo scene based on wav files + animations -// Returns true if a change needed to be made -//----------------------------------------------------------------------------- -bool AutoAddGestureKeys( CChoreoEvent *e, CStudioHdr *pStudioHdr, float *pPoseParameters, bool bCheckOnly ); -bool UpdateGestureLength( CChoreoEvent *e, CStudioHdr *pStudioHdr, float *pPoseParameters, bool bCheckOnly ); -bool UpdateSequenceLength( CChoreoEvent *e, CStudioHdr *pStudioHdr, float *pPoseParameters, bool bCheckOnly, bool bVerbose ); - - -#endif // CHOREOUTILS_H - diff --git a/public/tier3/mdlutils.h b/public/tier3/mdlutils.h deleted file mode 100644 index 9397ddf75..000000000 --- a/public/tier3/mdlutils.h +++ /dev/null @@ -1,88 +0,0 @@ -//===== Copyright 2005-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: A higher level link library for general use in the game and tools. -// -//===========================================================================// - - -#ifndef MDLUTILS_H -#define MDLUTILS_H - -#if defined( _WIN32 ) -#pragma once -#endif - -#include "datacache/imdlcache.h" -#include "mathlib/vector.h" -#include "Color.h" -#include "studio.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -struct matrix3x4_t; - - -//----------------------------------------------------------------------------- -// Class containing simplistic MDL state for use in rendering -//----------------------------------------------------------------------------- -class CMDL -{ -public: - CMDL(); - ~CMDL(); - - void SetMDL( MDLHandle_t h ); - MDLHandle_t GetMDL() const; - - // Simple version of drawing; sets up bones for you - void Draw( const matrix3x4_t& rootToWorld ); - - // NOTE: This version of draw assumes you've filled in the bone to world - // matrix yourself by calling IStudioRender::LockBoneMatrices. The pointer - // returned by that method needs to be passed into here - void Draw( const matrix3x4_t& rootToWorld, const matrix3x4_t *pBoneToWorld ); - - void SetUpBones( const matrix3x4_t& shapeToWorld, int nMaxBoneCount, matrix3x4_t *pOutputMatrices ); - void SetupBonesWithBoneMerge( const CStudioHdr *pMergeHdr, matrix3x4_t *pMergeBoneToWorld, - const CStudioHdr *pFollow, const matrix3x4_t *pFollowBoneToWorld, const matrix3x4_t &matModelToWorld ); - - studiohdr_t *GetStudioHdr(); - -private: - void UnreferenceMDL(); - -public: - MDLHandle_t m_MDLHandle; - Color m_Color; - int m_nSkin; - int m_nBody; - int m_nSequence; - int m_nLOD; - float m_flPlaybackRate; - float m_flTime; - float m_pFlexControls[ MAXSTUDIOFLEXCTRL * 4 ]; - Vector m_vecViewTarget; - bool m_bWorldSpaceViewTarget; -}; - - -//----------------------------------------------------------------------------- -// Returns the bounding box for the model -//----------------------------------------------------------------------------- -void GetMDLBoundingBox( Vector *pMins, Vector *pMaxs, MDLHandle_t h, int nSequence ); - -//----------------------------------------------------------------------------- -// Returns the radius of the model as measured from the origin -//----------------------------------------------------------------------------- -float GetMDLRadius( MDLHandle_t h, int nSequence ); - -//----------------------------------------------------------------------------- -// Returns a more accurate bounding sphere -//----------------------------------------------------------------------------- -void GetMDLBoundingSphere( Vector *pVecCenter, float *pRadius, MDLHandle_t h, int nSequence ); - - -#endif // MDLUTILS_H - diff --git a/public/tier3/scenetokenprocessor.h b/public/tier3/scenetokenprocessor.h deleted file mode 100644 index 55c7f7f08..000000000 --- a/public/tier3/scenetokenprocessor.h +++ /dev/null @@ -1,18 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef SCENETOKENPROCESSOR_H -#define SCENETOKENPROCESSOR_H -#ifdef _WIN32 -#pragma once -#endif - -class ISceneTokenProcessor; - -ISceneTokenProcessor *GetTokenProcessor(); -void SetTokenProcessorBuffer( const char *buf ); - -#endif // SCENETOKENPROCESSOR_H diff --git a/public/tier3/tier3.h b/public/tier3/tier3.h deleted file mode 100644 index 6d6d3a40f..000000000 --- a/public/tier3/tier3.h +++ /dev/null @@ -1,114 +0,0 @@ -//===== Copyright 2005-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: A higher level link library for general use in the game and tools. -// -//===========================================================================// - - -#ifndef TIER3_H -#define TIER3_H - -#if defined( _WIN32 ) -#pragma once -#endif - -#include "tier2/tier2.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class IStudioRender; -class IMatSystemSurface; -class IDataCache; -class IMDLCache; -class IAvi; -class IBik; -class IDmeMakefileUtils; -class IPhysicsCollision; -class ISoundEmitterSystemBase; - -namespace vgui -{ - class ISurface; - class IVGui; - class IInput; - class IPanel; - class ILocalize; - class ISchemeManager; - class ISystem; -} - - -//----------------------------------------------------------------------------- -// These tier3 libraries must be set by any users of this library. -// They can be set by calling ConnectTier3Libraries. -// It is hoped that setting this, and using this library will be the common mechanism for -// allowing link libraries to access tier3 library interfaces -//----------------------------------------------------------------------------- -extern IStudioRender *g_pStudioRender; -extern IStudioRender *studiorender; -extern IMatSystemSurface *g_pMatSystemSurface; -extern vgui::ISurface *g_pVGuiSurface; -extern vgui::IInput *g_pVGuiInput; -extern vgui::IVGui *g_pVGui; -extern vgui::IPanel *g_pVGuiPanel; -extern vgui::ILocalize *g_pVGuiLocalize; -extern vgui::ISchemeManager *g_pVGuiSchemeManager; -extern vgui::ISystem *g_pVGuiSystem; -extern IDataCache *g_pDataCache; // FIXME: Should IDataCache be in tier2? -extern IMDLCache *g_pMDLCache; -extern IMDLCache *mdlcache; -extern IAvi *g_pAVI; -extern IBik *g_pBIK; -extern IDmeMakefileUtils *g_pDmeMakefileUtils; -extern IPhysicsCollision *g_pPhysicsCollision; -extern ISoundEmitterSystemBase *g_pSoundEmitterSystem; - - -//----------------------------------------------------------------------------- -// Call this to connect to/disconnect from all tier 3 libraries. -// It's up to the caller to check the globals it cares about to see if ones are missing -//----------------------------------------------------------------------------- -void ConnectTier3Libraries( CreateInterfaceFn *pFactoryList, int nFactoryCount ); -void DisconnectTier3Libraries(); - - -//----------------------------------------------------------------------------- -// Helper empty implementation of an IAppSystem for tier2 libraries -//----------------------------------------------------------------------------- -template< class IInterface, int ConVarFlag = 0 > -class CTier3AppSystem : public CTier2AppSystem< IInterface, ConVarFlag > -{ - typedef CTier2AppSystem< IInterface, ConVarFlag > BaseClass; - -public: - CTier3AppSystem( bool bIsPrimaryAppSystem = true ) : BaseClass( bIsPrimaryAppSystem ) - { - } - - virtual bool Connect( CreateInterfaceFn factory ) - { - if ( !BaseClass::Connect( factory ) ) - return false; - - if ( CTier0AppSystem::IsPrimaryAppSystem() ) - { - ConnectTier3Libraries( &factory, 1 ); - } - return true; - } - - virtual void Disconnect() - { - if ( CTier0AppSystem::IsPrimaryAppSystem() ) - { - DisconnectTier3Libraries(); - } - BaseClass::Disconnect(); - } -}; - - -#endif // TIER3_H - diff --git a/public/tier3/tier3dm.h b/public/tier3/tier3dm.h deleted file mode 100644 index 299d81f5c..000000000 --- a/public/tier3/tier3dm.h +++ /dev/null @@ -1,55 +0,0 @@ -//===== Copyright 2005-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: A higher level link library for general use in the game and tools. -// -//===========================================================================// - - -#ifndef TIER3DM_H -#define TIER3DM_H - -#if defined( _WIN32 ) -#pragma once -#endif - -#include "tier3/tier3.h" -#include "tier2/tier2dm.h" - -//----------------------------------------------------------------------------- -// Helper empty implementation of an IAppSystem for tier2 libraries -//----------------------------------------------------------------------------- -template< class IInterface, int ConVarFlag = 0 > -class CTier3DmAppSystem : public CTier2DmAppSystem< IInterface, ConVarFlag > -{ - typedef CTier2DmAppSystem< IInterface, ConVarFlag > BaseClass; - -public: - CTier3DmAppSystem( bool bIsPrimaryAppSystem = true ) : BaseClass( bIsPrimaryAppSystem ) - { - } - - virtual bool Connect( CreateInterfaceFn factory ) - { - if ( !BaseClass::Connect( factory ) ) - return false; - - if ( CTier0AppSystem::IsPrimaryAppSystem() ) - { - ConnectTier3Libraries( &factory, 1 ); - } - return true; - } - - virtual void Disconnect() - { - if ( CTier0AppSystem::IsPrimaryAppSystem() ) - { - DisconnectTier3Libraries(); - } - BaseClass::Disconnect(); - } -}; - - -#endif // TIER3DM_H - diff --git a/public/toolframework/iclientenginetools.h b/public/toolframework/iclientenginetools.h deleted file mode 100644 index 4d4f6cf61..000000000 --- a/public/toolframework/iclientenginetools.h +++ /dev/null @@ -1,59 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef ICLIENTENGINETOOLS_H -#define ICLIENTENGINETOOLS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "interface.h" -#include "toolframework/itoolentity.h" // HTOOLHANDLE - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class KeyValues; -struct AudioState_t; - - -//----------------------------------------------------------------------------- -// Purpose: Exported from engine to client .dll to marshall tool framework calls -// into IToolSystems -//----------------------------------------------------------------------------- -class IClientEngineTools : public IBaseInterface -{ -public: - // Level init, shutdown - virtual void LevelInitPreEntityAllTools() = 0; - // entities are created / spawned / precached here - virtual void LevelInitPostEntityAllTools() = 0; - - virtual void LevelShutdownPreEntityAllTools() = 0; - // Entities are deleted / released here... - virtual void LevelShutdownPostEntityAllTools() = 0; - - virtual void PreRenderAllTools() = 0; - virtual void PostRenderAllTools() = 0; - - virtual void PostToolMessage( HTOOLHANDLE hEntity, KeyValues *msg ) = 0; - - virtual void AdjustEngineViewport( int& x, int& y, int& width, int& height ) = 0; - virtual bool SetupEngineView( Vector &origin, QAngle &angles, float &fov ) = 0; - virtual bool SetupAudioState( AudioState_t &audioState ) = 0; - - // Paintmode is an enum declared in ienginevgui.h - virtual void VGui_PreRenderAllTools( int paintMode ) = 0; - virtual void VGui_PostRenderAllTools( int paintMode ) = 0; - - virtual bool IsThirdPersonCamera( ) = 0; - - virtual bool InToolMode() = 0; -}; - -#define VCLIENTENGINETOOLS_INTERFACE_VERSION "VCLIENTENGINETOOLS001" - -#endif // ICLIENTENGINETOOLS_H diff --git a/public/toolframework/ienginetool.h b/public/toolframework/ienginetool.h deleted file mode 100644 index 49c0a4ef8..000000000 --- a/public/toolframework/ienginetool.h +++ /dev/null @@ -1,233 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef IENGINETOOL_H -#define IENGINETOOL_H -#ifdef _WIN32 -#pragma once -#endif - -#include "interface.h" -#include "soundflags.h" -#include "avi/iavi.h" -#include "ispatialpartition.h" - -class CViewSetup; -class IToolSystem; -class KeyValues; -class ITraceFilter; -class CBaseTrace; -struct dlight_t; -struct Ray_t; -struct AudioState_t; - - -typedef bool (*FnQuitHandler)( void *pvUserData ); - -#ifndef MAX_DLIGHTS -#define MAX_DLIGHTS 32 -#endif - -// Exposed from engine to all tools, simplest interface -class IEngineToolFramework : public IBaseInterface -{ -public: - // Input system overrides TBD - // Something like this - //virtual void AddMessageHandler( int wm_message, bool (*pfnCallback)( int wm_message, int wParam, int lParam ) ) = 0; - //virtual void RemoveMessageHanlder( int wm_message, bool (*pfnCallbackToRemove)( int wm_message, int wParam, int lParam ) ) = 0; - - // Helpers for implementing a tool switching UI - virtual int GetToolCount() const = 0; - virtual char const *GetToolName( int index ) const = 0; - virtual void SwitchToTool( int index ) = 0; - - virtual bool IsTopmostTool( const IToolSystem *sys ) const = 0; - - virtual const IToolSystem *GetToolSystem( int index ) const = 0; - virtual IToolSystem *GetTopmostTool() = 0; - - // Take over input - virtual void ShowCursor( bool show ) = 0; - virtual bool IsCursorVisible() const = 0; -}; - -#define VENGINETOOLFRAMEWORK_INTERFACE_VERSION "VENGINETOOLFRAMEWORK003" - -struct model_t; -struct studiohdr_t; - -#include "toolframework/itoolentity.h" - -// Exposed from engine to tools via, more involved version of above -class IEngineTool : public IEngineToolFramework -{ -public: - virtual void GetServerFactory( CreateInterfaceFn& factory ) = 0; - virtual void GetClientFactory( CreateInterfaceFn& factory ) = 0; - - virtual float GetSoundDuration( const char *pszName ) = 0; - virtual bool IsSoundStillPlaying( int guid ) = 0; - // Returns the guid of the sound - virtual int StartSound( - int iUserData, - bool staticsound, - int iEntIndex, - int iChannel, - const char *pSample, - float flVolume, - soundlevel_t iSoundlevel, - const Vector& origin, - const Vector& direction, - int iFlags = 0, - int iPitch = PITCH_NORM, - bool bUpdatePositions = true, - float delay = 0.0f, - int speakerentity = -1 ) = 0; - - virtual void StopSoundByGuid( int guid ) = 0; - - // Returns how long the sound is - virtual float GetSoundDuration( int guid ) = 0; - - // Returns if the sound is looping - virtual bool IsLoopingSound( int guid ) = 0; - virtual void ReloadSound( const char *pSample ) = 0; - virtual void StopAllSounds( ) = 0; - virtual float GetMono16Samples( const char *pszName, CUtlVector< short >& sampleList ) = 0; - virtual void SetAudioState( const AudioState_t &audioState ) = 0; - - // Issue a console command - virtual void Command( char const *cmd ) = 0; - // Flush console command buffer right away - virtual void Execute() = 0; - - virtual char const *GetCurrentMap() = 0; - virtual void ChangeToMap( char const *mapname ) = 0; - virtual bool IsMapValid( char const *mapname ) = 0; - - // Method for causing engine to call client to render scene with no view model or overlays - // See cdll_int.h for enum RenderViewInfo_t for specifying whatToRender - virtual void RenderView( CViewSetup &view, int nFlags, int whatToRender ) = 0; - - // Returns true if the player is fully connected and active in game (i.e, not still loading) - virtual bool IsInGame() = 0; - // Returns true if the player is connected, but not necessarily active in game (could still be loading) - virtual bool IsConnected() = 0; - - virtual int GetMaxClients() = 0; // Tools might want to ensure single player, e.g. - - virtual bool IsGamePaused() = 0; - virtual void SetGamePaused( bool paused ) = 0; - - virtual float GetTimescale() = 0; // Could do this via ConVar system, too - virtual void SetTimescale( float scale ) = 0; - - // Real time is unscaled, but is updated once per frame - virtual float GetRealTime() = 0; - virtual float GetRealFrameTime() = 0; // unscaled - - // Get high precision timer (for profiling?) - virtual float Time() = 0; - - // Host time is scaled - virtual float HostFrameTime() = 0; // host_frametime - virtual float HostTime() = 0; // host_time - virtual int HostTick() = 0; // host_tickcount - virtual int HostFrameCount() = 0; // total famecount - - virtual float ServerTime() = 0; // gpGlobals->curtime on server - virtual float ServerFrameTime() = 0; // gpGlobals->frametime on server - virtual int ServerTick() = 0; // gpGlobals->tickcount on server - virtual float ServerTickInterval() = 0; // tick interval on server - - virtual float ClientTime() = 0; // gpGlobals->curtime on client - virtual float ClientFrameTime() = 0; // gpGlobals->frametime on client - virtual int ClientTick() = 0; // gpGlobals->tickcount on client - - virtual void SetClientFrameTime( float frametime ) = 0; // gpGlobals->frametime on client - - // Currently the engine doesn't like to do networking when it's paused, but if a tool changes entity state, it can be useful to force - // a network update to get that state over to the client - virtual void ForceUpdateDuringPause() = 0; - - // Maybe through modelcache??? - virtual model_t *GetModel( HTOOLHANDLE hEntity ) = 0; - // Get the .mdl file used by entity (if it's a cbaseanimating) - virtual studiohdr_t *GetStudioModel( HTOOLHANDLE hEntity ) = 0; - - // SINGLE PLAYER/LISTEN SERVER ONLY (just matching the client .dll api for this) - // Prints the formatted string to the notification area of the screen ( down the right hand edge - // numbered lines starting at position 0 - virtual void Con_NPrintf( int pos, const char *fmt, ... ) = 0; - // SINGLE PLAYER/LISTEN SERVER ONLY(just matching the client .dll api for this) - // Similar to Con_NPrintf, but allows specifying custom text color and duration information - virtual void Con_NXPrintf( const struct con_nprint_s *info, const char *fmt, ... ) = 0; - - // Get the current game directory (hl2, tf2, hl1, cstrike, etc.) - virtual void GetGameDir( char *szGetGameDir, int maxlength ) = 0; - -// Do we need separate rects for the 3d "viewport" vs. the tools surface??? and can we control viewports from - virtual void GetScreenSize( int& width, int &height ) = 0; - - // GetRootPanel(VPANEL) - - // Sets the location of the main view - virtual void SetMainView( const Vector &vecOrigin, const QAngle &angles ) = 0; - - // Gets the player view - virtual bool GetPlayerView( CViewSetup &playerView, int x, int y, int w, int h ) = 0; - - // From a location on the screen, figure out the vector into the world - virtual void CreatePickingRay( const CViewSetup &viewSetup, int x, int y, Vector& org, Vector& forward ) = 0; - - // precache methods - virtual bool PrecacheSound( const char *pName, bool bPreload = false ) = 0; - virtual bool PrecacheModel( const char *pName, bool bPreload = false ) = 0; - - virtual void InstallQuitHandler( void *pvUserData, FnQuitHandler func ) = 0; - virtual void TakeTGAScreenShot( char const *filename, int width, int height ) = 0; - // Even if game is paused, force networking to update to get new server state down to client - virtual void ForceSend() = 0; - - virtual bool IsRecordingMovie() = 0; - - // NOTE: Params can contain file name, frame rate, output avi, output raw, and duration - virtual void StartMovieRecording( KeyValues *pMovieParams ) = 0; - virtual void EndMovieRecording() = 0; - virtual void CancelMovieRecording() = 0; - virtual AVIHandle_t GetRecordingAVIHandle() = 0; - - virtual void StartRecordingVoiceToFile( char const *filename, char const *pPathID = 0 ) = 0; - virtual void StopRecordingVoiceToFile() = 0; - virtual bool IsVoiceRecording() = 0; - - // A version that simply accepts a ray (can work as a traceline or tracehull) - virtual void TraceRay( const Ray_t &ray, unsigned int fMask, ITraceFilter *pTraceFilter, CBaseTrace *pTrace ) = 0; // client version - virtual void TraceRayServer( const Ray_t &ray, unsigned int fMask, ITraceFilter *pTraceFilter, CBaseTrace *pTrace ) = 0; - - virtual bool IsConsoleVisible() = 0; - - virtual int GetPointContents( const Vector &vecPosition ) = 0; - - virtual int GetActiveDLights( dlight_t *pList[MAX_DLIGHTS] ) = 0; - virtual int GetLightingConditions( const Vector &vecPosition, Vector *pColors, int nMaxLocalLights, LightDesc_t *pLocalLights ) = 0; - - virtual void GetWorldToScreenMatrixForView( const CViewSetup &view, VMatrix *pVMatrix ) = 0; - - // Collision support - virtual SpatialPartitionHandle_t CreatePartitionHandle( IHandleEntity *pEntity, - SpatialPartitionListMask_t listMask, const Vector& mins, const Vector& maxs ) = 0; - virtual void DestroyPartitionHandle( SpatialPartitionHandle_t hPartition ) = 0; - virtual void InstallPartitionQueryCallback( IPartitionQueryCallback *pQuery ) = 0; - virtual void RemovePartitionQueryCallback( IPartitionQueryCallback *pQuery ) = 0; - virtual void ElementMoved( SpatialPartitionHandle_t handle, - const Vector& mins, const Vector& maxs ) = 0; -}; - -#define VENGINETOOL_INTERFACE_VERSION "VENGINETOOL003" - -#endif // IENGINETOOL_H diff --git a/public/toolframework/iserverenginetools.h b/public/toolframework/iserverenginetools.h deleted file mode 100644 index c43bc878e..000000000 --- a/public/toolframework/iserverenginetools.h +++ /dev/null @@ -1,50 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef ISERVERENGINETOOLS_H -#define ISERVERENGINETOOLS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "interface.h" - -//----------------------------------------------------------------------------- -// Purpose: exposed from engine to game .dll -//----------------------------------------------------------------------------- -class IServerEngineTools : public IBaseInterface -{ -public: - // Level init, shutdown - virtual void LevelInitPreEntityAllTools() = 0; - // entities are created / spawned / precached here - virtual void LevelInitPostEntityAllTools() = 0; - - virtual void LevelShutdownPreEntityAllTools() = 0; - // Entities are deleted / released here... - virtual void LevelShutdownPostEntityAllTools() = 0; - // end of level shutdown - - // Called each frame before entities think - virtual void FrameUpdatePreEntityThinkAllTools() = 0; - // called after entities think - virtual void FrameUpdatePostEntityThinkAllTools() = 0; - - virtual void PreClientUpdateAllTools() = 0; - // FIXME: PostClientUpdateAllTools()??? - - // The server uses this to call into the tools to get the actual - // entities to spawn on startup - virtual const char* GetEntityData( const char *pActualEntityData ) = 0; - - virtual void PreSetupVisibilityAllTools() = 0; - - virtual bool InToolMode() = 0; -}; - -#define VSERVERENGINETOOLS_INTERFACE_VERSION "VSERVERENGINETOOLS001" - -#endif // ISERVERENGINETOOLS_H diff --git a/public/toolframework/itooldictionary.h b/public/toolframework/itooldictionary.h deleted file mode 100644 index 3b6e4f687..000000000 --- a/public/toolframework/itooldictionary.h +++ /dev/null @@ -1,39 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef ITOOLDICTIONARY_H -#define ITOOLDICTIONARY_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "appframework/IAppSystem.h" - -//----------------------------------------------------------------------------- -// Forward declaration -//----------------------------------------------------------------------------- -class IToolSystem; - - -//----------------------------------------------------------------------------- -// Purpose: Every tool dll sitting in bin\tools must expose this interface -// The engine will load the .dll, get this interface, and then ask for all -// tools in the .dll -// The engine will call CreateTools just before querying for the tools, so you -// can instance any dynamically instanced tools during that call -//----------------------------------------------------------------------------- -class IToolDictionary : public IAppSystem -{ -public: - virtual void CreateTools() = 0; - virtual int GetToolCount() const = 0; - virtual IToolSystem *GetTool( int index ) = 0; -}; - -#define VTOOLDICTIONARY_INTERFACE_VERSION "VTOOLDICTIONARY002" - -#endif // ITOOLDICTIONARY_H diff --git a/public/toolframework/itoolentity.h b/public/toolframework/itoolentity.h deleted file mode 100644 index 4951538b3..000000000 --- a/public/toolframework/itoolentity.h +++ /dev/null @@ -1,248 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef ITOOLENTITY_H -#define ITOOLENTITY_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/interface.h" -#include "tier1/utlvector.h" -#include "Color.h" -#include "basehandle.h" -#include "iclientrenderable.h" -#include "engine/ishadowmgr.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class IServerEntity; -class IClientEntity; -class IToolSystem; -class IClientRenderable; -class Vector; -class QAngle; -class CBaseEntity; -class CBaseAnimating; -class CTakeDamageInfo; -class ITempEntsSystem; -class IEntityFactoryDictionary; - - -//----------------------------------------------------------------------------- -// Safe accessor to an entity -//----------------------------------------------------------------------------- -typedef unsigned int HTOOLHANDLE; -enum -{ - HTOOLHANDLE_INVALID = 0 -}; - - -//----------------------------------------------------------------------------- -// If you change this, change the flags in IClientShadowMgr.h also -//----------------------------------------------------------------------------- -enum ClientShadowFlags_t -{ - SHADOW_FLAGS_USE_RENDER_TO_TEXTURE = (SHADOW_FLAGS_LAST_FLAG<<1), - SHADOW_FLAGS_ANIMATING_SOURCE = (SHADOW_FLAGS_LAST_FLAG<<2), - SHADOW_FLAGS_USE_DEPTH_TEXTURE = (SHADOW_FLAGS_LAST_FLAG<<3), - // Update this if you add flags - CLIENT_SHADOW_FLAGS_LAST_FLAG = SHADOW_FLAGS_USE_DEPTH_TEXTURE -}; - - -//----------------------------------------------------------------------------- -// Opaque pointer returned from Find* methods, don't store this, you need to -// Attach it to a tool entity or discard after searching -//----------------------------------------------------------------------------- -typedef void *EntitySearchResult; - - -//----------------------------------------------------------------------------- -// Purpose: Client side tool interace (right now just handles IClientRenderables). -// In theory could support hooking into client side entities directly -//----------------------------------------------------------------------------- -class IClientTools : public IBaseInterface -{ -public: - // Allocates or returns the handle to an entity previously found using the Find* APIs below - virtual HTOOLHANDLE AttachToEntity( EntitySearchResult entityToAttach ) = 0; - virtual void DetachFromEntity( EntitySearchResult entityToDetach ) = 0; - - // Checks whether a handle is still valid. - virtual bool IsValidHandle( HTOOLHANDLE handle ) = 0; - - // Iterates the list of entities which have been associated with tools - virtual int GetNumRecordables() = 0; - virtual HTOOLHANDLE GetRecordable( int index ) = 0; - - // Iterates through ALL entities (separate list for client vs. server) - virtual EntitySearchResult NextEntity( EntitySearchResult currentEnt ) = 0; - EntitySearchResult FirstEntity() { return NextEntity( NULL ); } - - // Use this to turn on/off the presence of an underlying game entity - virtual void SetEnabled( HTOOLHANDLE handle, bool enabled ) = 0; - // Use this to tell an entity to post "state" to all listening tools - virtual void SetRecording( HTOOLHANDLE handle, bool recording ) = 0; - // Some entities are marked with ShouldRecordInTools false, such as ui entities, etc. - virtual bool ShouldRecord( HTOOLHANDLE handle ) = 0; - - virtual HTOOLHANDLE GetToolHandleForEntityByIndex( int entindex ) = 0; - - virtual int GetModelIndex( HTOOLHANDLE handle ) = 0; - virtual const char* GetModelName ( HTOOLHANDLE handle ) = 0; - virtual const char* GetClassname ( HTOOLHANDLE handle ) = 0; - - virtual void AddClientRenderable( IClientRenderable *pRenderable, int renderGroup ) = 0; - virtual void RemoveClientRenderable( IClientRenderable *pRenderable ) = 0; - virtual void SetRenderGroup( IClientRenderable *pRenderable, int renderGroup ) = 0; - virtual void MarkClientRenderableDirty( IClientRenderable *pRenderable ) = 0; - virtual void UpdateProjectedTexture( ClientShadowHandle_t h, bool bForce ) = 0; - - virtual bool DrawSprite( IClientRenderable *pRenderable, float scale, float frame, int rendermode, int renderfx, const Color &color, float flProxyRadius, int *pVisHandle ) = 0; - - virtual EntitySearchResult GetLocalPlayer() = 0; - virtual bool GetLocalPlayerEyePosition( Vector& org, QAngle& ang, float &fov ) = 0; - - // See ClientShadowFlags_t above - virtual ClientShadowHandle_t CreateShadow( CBaseHandle handle, int nFlags ) = 0; - virtual void DestroyShadow( ClientShadowHandle_t h ) = 0; - - virtual ClientShadowHandle_t CreateFlashlight( const FlashlightState_t &lightState ) = 0; - virtual void DestroyFlashlight( ClientShadowHandle_t h ) = 0; - virtual void UpdateFlashlightState( ClientShadowHandle_t h, const FlashlightState_t &lightState ) = 0; - - virtual void AddToDirtyShadowList( ClientShadowHandle_t h, bool force = false ) = 0; - virtual void MarkRenderToTextureShadowDirty( ClientShadowHandle_t h ) = 0; - - // Global toggle for recording - virtual void EnableRecordingMode( bool bEnable ) = 0; - virtual bool IsInRecordingMode() const = 0; - - // Trigger a temp entity - virtual void TriggerTempEntity( KeyValues *pKeyValues ) = 0; - - // get owning weapon (for viewmodels) - virtual int GetOwningWeaponEntIndex( int entindex ) = 0; - virtual int GetEntIndex( EntitySearchResult entityToAttach ) = 0; - - virtual int FindGlobalFlexcontroller( char const *name ) = 0; - virtual char const *GetGlobalFlexControllerName( int idx ) = 0; - - // helper for traversing ownership hierarchy - virtual EntitySearchResult GetOwnerEntity( EntitySearchResult currentEnt ) = 0; - - // common and useful types to query for hierarchically - virtual bool IsPlayer ( EntitySearchResult currentEnt ) = 0; - virtual bool IsBaseCombatCharacter( EntitySearchResult currentEnt ) = 0; - virtual bool IsNPC ( EntitySearchResult currentEnt ) = 0; - - virtual Vector GetAbsOrigin( HTOOLHANDLE handle ) = 0; - virtual QAngle GetAbsAngles( HTOOLHANDLE handle ) = 0; - - // This reloads a portion or all of a particle definition file. - // It's up to the client to decide if it cares about this file - // Use a UtlBuffer to crack the data - virtual void ReloadParticleDefintions( const char *pFileName, const void *pBufData, int nLen ) = 0; - - // Sends a mesage from the tool to the client - virtual void PostToolMessage( KeyValues *pKeyValues ) = 0; - - // Indicates whether the client should render particle systems - virtual void EnableParticleSystems( bool bEnable ) = 0; - - // Is the game rendering in 3rd person mode? - virtual bool IsRenderingThirdPerson() const = 0; -}; - -#define VCLIENTTOOLS_INTERFACE_VERSION "VCLIENTTOOLS001" - - -//----------------------------------------------------------------------------- -// Purpose: Interface from engine to tools for manipulating entities -//----------------------------------------------------------------------------- -class IServerTools : public IBaseInterface -{ -public: - virtual IServerEntity *GetIServerEntity( IClientEntity *pClientEntity ) = 0; - virtual bool SnapPlayerToPosition( const Vector &org, const QAngle &ang, IClientEntity *pClientPlayer = NULL ) = 0; - virtual bool GetPlayerPosition( Vector &org, QAngle &ang, IClientEntity *pClientPlayer = NULL ) = 0; - virtual bool SetPlayerFOV( int fov, IClientEntity *pClientPlayer = NULL ) = 0; - virtual int GetPlayerFOV( IClientEntity *pClientPlayer = NULL ) = 0; - virtual bool IsInNoClipMode( IClientEntity *pClientPlayer = NULL ) = 0; - - // entity searching - virtual CBaseEntity *FirstEntity( void ) = 0; - virtual CBaseEntity *NextEntity( CBaseEntity *pEntity ) = 0; - virtual CBaseEntity *FindEntityByHammerID( int iHammerID ) = 0; - - // entity query - virtual bool GetKeyValue( CBaseEntity *pEntity, const char *szField, char *szValue, int iMaxLen ) = 0; - virtual bool SetKeyValue( CBaseEntity *pEntity, const char *szField, const char *szValue ) = 0; - virtual bool SetKeyValue( CBaseEntity *pEntity, const char *szField, float flValue ) = 0; - virtual bool SetKeyValue( CBaseEntity *pEntity, const char *szField, const Vector &vecValue ) = 0; - - // entity spawning - virtual CBaseEntity *CreateEntityByName( const char *szClassName ) = 0; - virtual void DispatchSpawn( CBaseEntity *pEntity ) = 0; - - // This reloads a portion or all of a particle definition file. - // It's up to the server to decide if it cares about this file - // Use a UtlBuffer to crack the data - virtual void ReloadParticleDefintions( const char *pFileName, const void *pBufData, int nLen ) = 0; - - virtual void AddOriginToPVS( const Vector &org ) = 0; - virtual void MoveEngineViewTo( const Vector &vPos, const QAngle &vAngles ) = 0; - - virtual bool DestroyEntityByHammerId( int iHammerID ) = 0; - virtual CBaseEntity *GetBaseEntityByEntIndex( int iEntIndex ) = 0; - virtual void RemoveEntity( CBaseEntity *pEntity ) = 0; - virtual void RemoveEntityImmediate( CBaseEntity *pEntity ) = 0; - virtual IEntityFactoryDictionary *GetEntityFactoryDictionary( void ) = 0; - - virtual void SetMoveType( CBaseEntity *pEntity, int val ) = 0; - virtual void SetMoveType( CBaseEntity *pEntity, int val, int moveCollide ) = 0; - virtual void ResetSequence( CBaseAnimating *pEntity, int nSequence ) = 0; - virtual void ResetSequenceInfo( CBaseAnimating *pEntity ) = 0; - - virtual void ClearMultiDamage( void ) = 0; - virtual void ApplyMultiDamage( void ) = 0; - virtual void AddMultiDamage( const CTakeDamageInfo &pTakeDamageInfo, CBaseEntity *pEntity ) = 0; - virtual void RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrc, float flRadius, int iClassIgnore, CBaseEntity *pEntityIgnore ) = 0; - - virtual ITempEntsSystem *GetTempEntsSystem( void ) = 0; -}; - -typedef IServerTools IServerTools001; - -#define VSERVERTOOLS_INTERFACE_VERSION_1 "VSERVERTOOLS001" -#define VSERVERTOOLS_INTERFACE_VERSION "VSERVERTOOLS002" -#define VSERVERTOOLS_INTERFACE_VERSION_INT 2 - -//----------------------------------------------------------------------------- -// Purpose: Client side tool interace (right now just handles IClientRenderables). -// In theory could support hooking into client side entities directly -//----------------------------------------------------------------------------- -class IServerChoreoTools : public IBaseInterface -{ -public: - - // Iterates through ALL entities (separate list for client vs. server) - virtual EntitySearchResult NextChoreoEntity( EntitySearchResult currentEnt ) = 0; - EntitySearchResult FirstChoreoEntity() { return NextChoreoEntity( NULL ); } - virtual const char *GetSceneFile( EntitySearchResult sr ) = 0; - - // For interactive editing - virtual int GetEntIndex( EntitySearchResult sr ) = 0; - virtual void ReloadSceneFromDisk( int entindex ) = 0; -}; - -#define VSERVERCHOREOTOOLS_INTERFACE_VERSION "VSERVERCHOREOTOOLS001" - -#endif // ITOOLENTITY_H diff --git a/public/toolframework/itoolframework.h b/public/toolframework/itoolframework.h deleted file mode 100644 index 61863a2d7..000000000 --- a/public/toolframework/itoolframework.h +++ /dev/null @@ -1,265 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef ITOOLFRAMEWORK_H -#define ITOOLFRAMEWORK_H -#ifdef _WIN32 -#pragma once -#endif - -#include "appframework/IAppSystem.h" -#include "materialsystem/imaterialproxy.h" -#include "toolframework/itoolentity.h" -#include "mathlib/vector.h" -#include "Color.h" -#include "toolframework/itoolentity.h" // HTOOLHANDLE defn - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class IToolSystem; -struct SpatializationInfo_t; -class KeyValues; -class CBoneList; - - -//----------------------------------------------------------------------------- -// Standard messages -//----------------------------------------------------------------------------- -struct BaseEntityRecordingState_t -{ - BaseEntityRecordingState_t() : - m_flTime( 0.0f ), - m_pModelName( 0 ), - m_nOwner( -1 ), - m_nEffects( 0 ), - m_bVisible( false ), - m_bRecordFinalVisibleSample( false ) - { - m_vecRenderOrigin.Init(); - m_vecRenderAngles.Init(); - } - - float m_flTime; - const char *m_pModelName; - int m_nOwner; - int m_nEffects; - bool m_bVisible : 1; - bool m_bRecordFinalVisibleSample : 1; - Vector m_vecRenderOrigin; - QAngle m_vecRenderAngles; -}; - -struct SpriteRecordingState_t -{ - float m_flRenderScale; - float m_flFrame; - int m_nRenderMode; - bool m_nRenderFX; - Color m_Color; - float m_flProxyRadius; -}; - -struct BaseAnimatingRecordingState_t -{ - int m_nSkin; - int m_nBody; - int m_nSequence; - CBoneList *m_pBoneList; -}; - -struct BaseFlexRecordingState_t -{ - int m_nFlexCount; - float *m_pDestWeight; - Vector m_vecViewTarget; -}; - -struct CameraRecordingState_t -{ - bool m_bThirdPerson; - float m_flFOV; - Vector m_vecEyePosition; - QAngle m_vecEyeAngles; -}; - -struct MonitorRecordingState_t -{ - bool m_bActive; - float m_flFOV; - bool m_bFogEnabled; - float m_flFogStart; - float m_flFogEnd; - Color m_FogColor; -}; - -struct EntityTeleportedRecordingState_t -{ - Vector m_vecTo; - QAngle m_qaTo; - bool m_bTeleported; - bool m_bViewOverride; - matrix3x4_t m_teleportMatrix; -}; - -struct PortalRecordingState_t -{ - int m_nPortalId; - int m_nLinkedPortalId; - float m_fStaticAmount; - float m_fSecondaryStaticAmount; - float m_fOpenAmount; - bool m_bIsPortal2; //for any set of portals, one must be portal 1, and the other portal 2. Uses different render targets -}; - -struct ParticleSystemCreatedState_t -{ - int m_nParticleSystemId; - const char * m_pName; - float m_flTime; - int m_nOwner; -}; - -struct ParticleSystemDestroyedState_t -{ - int m_nParticleSystemId; - float m_flTime; -}; - -struct ParticleSystemStopEmissionState_t -{ - int m_nParticleSystemId; - float m_flTime; - bool m_bInfiniteOnly; -}; - -struct ParticleSystemSetControlPointObjectState_t -{ - int m_nParticleSystemId; - float m_flTime; - int m_nControlPoint; - int m_nObject; -}; - -struct ParticleSystemSetControlPointPositionState_t -{ - int m_nParticleSystemId; - float m_flTime; - int m_nControlPoint; - Vector m_vecPosition; -}; - -struct ParticleSystemSetControlPointOrientationState_t -{ - int m_nParticleSystemId; - float m_flTime; - int m_nControlPoint; - Quaternion m_qOrientation; -}; - - -//----------------------------------------------------------------------------- -// Purpose: This interface lives in the engine and handles loading up/unloading all -// available tools -//----------------------------------------------------------------------------- -class IToolFrameworkInternal : public IAppSystem -{ -public: // Client Hooks - virtual bool ClientInit( CreateInterfaceFn clientFactory ) = 0; - virtual void ClientShutdown() = 0; - - // Level init, shutdown - virtual void ClientLevelInitPreEntityAllTools() = 0; - // entities are created / spawned / precached here - virtual void ClientLevelInitPostEntityAllTools() = 0; - - virtual void ClientLevelShutdownPreEntityAllTools() = 0; - // Entities are deleted / released here... - virtual void ClientLevelShutdownPostEntityAllTools() = 0; - - virtual void ClientPreRenderAllTools() = 0; - virtual void ClientPostRenderAllTools() = 0; - - // Should we render with a thirdperson camera? - virtual bool IsThirdPersonCamera() = 0; - - // is the current tool recording? - virtual bool IsToolRecording() = 0; - -public: // Server Hooks - // Level init, shutdown - virtual bool ServerInit( CreateInterfaceFn serverFactory ) = 0; - virtual void ServerShutdown() = 0; - - virtual void ServerLevelInitPreEntityAllTools() = 0; - // entities are created / spawned / precached here - virtual void ServerLevelInitPostEntityAllTools() = 0; - - virtual void ServerLevelShutdownPreEntityAllTools() = 0; - // Entities are deleted / released here... - virtual void ServerLevelShutdownPostEntityAllTools() = 0; - // end of level shutdown - - // Called each frame before entities think - virtual void ServerFrameUpdatePreEntityThinkAllTools() = 0; - // called after entities think - virtual void ServerFrameUpdatePostEntityThinkAllTools() = 0; - virtual void ServerPreClientUpdateAllTools() = 0; - - virtual void ServerPreSetupVisibilityAllTools() = 0; - -public: // Other Hooks - // If any tool returns false, the engine will not actually quit - // FIXME: Not implemented yet - virtual bool CanQuit() = 0; - - // Called at end of Host_Init - virtual bool PostInit() = 0; - - virtual void Think( bool finalTick ) = 0; - - virtual void PostMessage( KeyValues *msg ) = 0; - - virtual bool GetSoundSpatialization( int iUserData, int guid, SpatializationInfo_t& info ) = 0; - - virtual void HostRunFrameBegin() = 0; - virtual void HostRunFrameEnd() = 0; - - virtual void RenderFrameBegin() = 0; - virtual void RenderFrameEnd() = 0; - - // Paintmode is an enum declared in enginevgui.h - virtual void VGui_PreRenderAllTools( int paintMode ) = 0; - virtual void VGui_PostRenderAllTools( int paintMode ) = 0; - - virtual void VGui_PreSimulateAllTools() = 0; - virtual void VGui_PostSimulateAllTools() = 0; - - // Are we using tools? - virtual bool InToolMode() = 0; - - // Should the game be allowed to render the world? - virtual bool ShouldGameRenderView() = 0; - - virtual IMaterialProxy *LookupProxy( const char *proxyName ) = 0; - -public: // general framework hooks - virtual int GetToolCount() = 0; - virtual char const *GetToolName( int index ) = 0; - virtual void SwitchToTool( int index ) = 0; - virtual IToolSystem *SwitchToTool( const char *pToolName ) = 0; - virtual bool IsTopmostTool( const IToolSystem *sys ) = 0; - virtual const IToolSystem *GetToolSystem( int index ) const = 0; - virtual IToolSystem *GetTopmostTool() = 0; -}; - -// Expose to rest of engine as a singleton -extern IToolFrameworkInternal *toolframework; - -// Exposed to launcher to automatically add AppSystemGroup hooks -#define VTOOLFRAMEWORK_INTERFACE_VERSION "VTOOLFRAMEWORKVERSION002" - -#endif // ITOOLFRAMEWORK_H diff --git a/public/toolframework/itoolsystem.h b/public/toolframework/itoolsystem.h deleted file mode 100644 index 9517a5836..000000000 --- a/public/toolframework/itoolsystem.h +++ /dev/null @@ -1,146 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef ITOOLSYSTEM_H -#define ITOOLSYSTEM_H -#ifdef _WIN32 -#pragma once -#endif - -#include "itoolentity.h" -#include "interface.h" -#include "materialsystem/imaterialproxy.h" -#include "inputsystem/iinputsystem.h" - -class KeyValues; -struct SpatializationInfo_t; -struct AudioState_t; - -//----------------------------------------------------------------------------- -// Purpose: All tools expose this interface, which includes both client and server -// related hooks -//----------------------------------------------------------------------------- -class IToolSystem -{ -public: - // Name describing the tool - virtual char const *GetToolName() = 0; - - // Called at the end of engine startup (after client .dll and server .dll have been loaded) - virtual bool Init() = 0; - - // Called during RemoveTool or when engine is shutting down - virtual void Shutdown() = 0; - - // Called after server.dll is loaded - virtual bool ServerInit( CreateInterfaceFn serverFactory ) = 0; - // Called after client.dll is loaded - virtual bool ClientInit( CreateInterfaceFn clientFactory ) = 0; - - virtual void ServerShutdown() = 0; - virtual void ClientShutdown() = 0; - - // Allow tool to override quitting, called before Shutdown(), return no to abort quitting - virtual bool CanQuit() = 0; - - // Called when another system wiches to post a message to the tool and/or a specific entity - // FIXME: Are KeyValues too inefficient here? - virtual void PostMessage( HTOOLHANDLE hEntity, KeyValues *message ) = 0; - - // Called oncer per frame even when no level is loaded... (call ProcessMessages()) - virtual void Think( bool finalTick ) = 0; - -// Server calls: - - // Level init, shutdown - virtual void ServerLevelInitPreEntity() = 0; - // entities are created / spawned / precached here - virtual void ServerLevelInitPostEntity() = 0; - - virtual void ServerLevelShutdownPreEntity() = 0; - // Entities are deleted / released here... - virtual void ServerLevelShutdownPostEntity() = 0; - // end of level shutdown - - // Called each frame before entities think - virtual void ServerFrameUpdatePreEntityThink() = 0; - // called after entities think - virtual void ServerFrameUpdatePostEntityThink() = 0; - virtual void ServerPreClientUpdate() = 0; - virtual void ServerPreSetupVisibility() = 0; - - // Used to allow the tool to spawn different entities when it's active - virtual const char* GetEntityData( const char *pActualEntityData ) = 0; - -// Client calls: - // Level init, shutdown - virtual void ClientLevelInitPreEntity() = 0; - // entities are created / spawned / precached here - virtual void ClientLevelInitPostEntity() = 0; - - virtual void ClientLevelShutdownPreEntity() = 0; - // Entities are deleted / released here... - virtual void ClientLevelShutdownPostEntity() = 0; - // end of level shutdown - // Called before rendering - virtual void ClientPreRender() = 0; - virtual void ClientPostRender() = 0; - - // Let tool override viewport for engine - virtual void AdjustEngineViewport( int& x, int& y, int& width, int& height ) = 0; - - // let tool override view/camera - virtual bool SetupEngineView( Vector &origin, QAngle &angles, float &fov ) = 0; - - // let tool override microphone - virtual bool SetupAudioState( AudioState_t &audioState ) = 0; - - // Should the client be allowed to render the view normally? - virtual bool ShouldGameRenderView() = 0; - virtual bool IsThirdPersonCamera() = 0; - - // is the current tool recording? - virtual bool IsToolRecording() = 0; - - virtual IMaterialProxy *LookupProxy( const char *proxyName ) = 0; - - // Possible hooks for rendering - // virtual void Think( float curtime, float frametime ) = 0; - // virtual void Prerender() = 0; - // virtual void Render3D() = 0; - // virtual void Render2D() = 0; -// Tool activation/deactivation - - // This tool is being activated - virtual void OnToolActivate() = 0; - // Another tool is being activated - virtual void OnToolDeactivate() = 0; - - virtual bool TrapKey( ButtonCode_t key, bool down ) = 0; - - virtual bool GetSoundSpatialization( int iUserData, int guid, SpatializationInfo_t& info ) = 0; - - // Unlike the client .dll pre/post render stuff, these get called no matter whether a map is loaded and they only get called once per frame!!! - virtual void RenderFrameBegin() = 0; - virtual void RenderFrameEnd() = 0; - - // wraps the entire frame - surrounding all other begin/end and pre/post calls - virtual void HostRunFrameBegin() = 0; - virtual void HostRunFrameEnd() = 0; - - // See enginevgui.h for paintmode_t enum definitions - virtual void VGui_PreRender( int paintMode ) = 0; - virtual void VGui_PostRender( int paintMode ) = 0; - - virtual void VGui_PreSimulate() = 0; - virtual void VGui_PostSimulate() = 0; -}; - -// Pointer to a member method of IGameSystem -typedef void (IToolSystem::*ToolSystemFunc_t)(); -typedef void (IToolSystem::*ToolSystemFunc_Int_t)( int arg ); - -#endif // ITOOLSYSTEM_H diff --git a/public/toolframework/toolframework.cpp b/public/toolframework/toolframework.cpp deleted file mode 100644 index 263a8ceaa..000000000 --- a/public/toolframework/toolframework.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "toolframework/itooldictionary.h" -#include "utlvector.h" - -class CToolDictionary : public IToolDictionary -{ -public: - virtual int GetToolCount() const - { - return m_Tools.Count(); - } - - virtual IToolSystem *GetTool( int index ) - { - if ( index < 0 || index >= m_Tools.Count() ) - { - return NULL; - } - return m_Tools[ index ]; - } - -public: - - void RegisterTool( IToolSystem *tool ) - { - m_Tools.AddToTail( tool ); - } -private: - - CUtlVector< IToolSystem * > m_Tools; -}; - -static CToolDictionary g_ToolDictionary; - -EXPOSE_SINGLE_INTERFACE_GLOBALVAR( IToolDictionary, CToolDictionary, VTOOLDICTIONARY_INTERFACE_VERSION, g_ToolDictionary ); - -void RegisterTool( IToolSystem *tool ) -{ - g_ToolDictionary.RegisterTool( tool ); -} - diff --git a/public/tools/bonelist.cpp b/public/tools/bonelist.cpp deleted file mode 100644 index fd1bb94d0..000000000 --- a/public/tools/bonelist.cpp +++ /dev/null @@ -1,72 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include "cbase.h" -#include "bonelist.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -CBoneList::CBoneList() -{ - m_bShouldDelete = false; - m_nBones = 0; - Q_memset( m_vecPos, 0, sizeof( m_vecPos ) ); - Q_memset( m_quatRot, 0, sizeof( m_quatRot ) ); -} - -void CBoneList::Release() -{ - if (m_bShouldDelete ) - { - delete this; - } - else - { - Warning( "Called Release() on CBoneList not allocated via Alloc() method\n" ); - } -} - -CBoneList *CBoneList::Alloc() -{ - CBoneList *newList = new CBoneList; - Assert( newList ); - if ( newList ) - { - newList->m_bShouldDelete = true; - } - return newList; -} - -CFlexList::CFlexList() -{ - m_bShouldDelete = false; - m_nNumFlexes = 0; - Q_memset( m_flexWeights, 0, sizeof( m_flexWeights ) ); -} - -void CFlexList::Release() -{ - if (m_bShouldDelete ) - { - delete this; - } - else - { - Warning( "Called Release() on CFlexList not allocated via Alloc() method\n" ); - } -} - -CFlexList *CFlexList::Alloc() -{ - CFlexList *newList = new CFlexList; - Assert( newList ); - if ( newList ) - { - newList->m_bShouldDelete = true; - } - return newList; -} diff --git a/public/tools/bonelist.h b/public/tools/bonelist.h deleted file mode 100644 index f4e29b074..000000000 --- a/public/tools/bonelist.h +++ /dev/null @@ -1,54 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef BONELIST_H -#define BONELIST_H -#ifdef _WIN32 -#pragma once -#endif - -#include "studio.h" - -class CBoneList -{ -public: - - CBoneList(); - - void Release(); - - static CBoneList *Alloc(); - -public: - - int m_nBones; - Vector m_vecPos[ MAXSTUDIOBONES ]; - Quaternion m_quatRot[ MAXSTUDIOBONES ]; - -private: - bool m_bShouldDelete; -}; - -class CFlexList -{ -public: - - CFlexList(); - - void Release(); - - static CFlexList *Alloc(); - -public: - - int m_nNumFlexes; - float m_flexWeights[ MAXSTUDIOFLEXCTRL ]; - -private: - bool m_bShouldDelete; -}; - -#endif // BONELIST_H diff --git a/public/trace.h b/public/trace.h deleted file mode 100644 index 92429f66e..000000000 --- a/public/trace.h +++ /dev/null @@ -1,69 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $Workfile: $ -// $Date: $ -// -//----------------------------------------------------------------------------- -// $Log: $ -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef TRACE_H -#define TRACE_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "mathlib/mathlib.h" - -// Note: These flags need to match the bspfile.h DISPTRI_TAG_* flags. -#define DISPSURF_FLAG_SURFACE (1<<0) -#define DISPSURF_FLAG_WALKABLE (1<<1) -#define DISPSURF_FLAG_BUILDABLE (1<<2) -#define DISPSURF_FLAG_SURFPROP1 (1<<3) -#define DISPSURF_FLAG_SURFPROP2 (1<<4) - -//============================================================================= -// Base Trace Structure -// - shared between engine/game dlls and tools (vrad) -//============================================================================= - -class CBaseTrace -{ -public: - - // Displacement flags tests. - bool IsDispSurface( void ) { return ( ( dispFlags & DISPSURF_FLAG_SURFACE ) != 0 ); } - bool IsDispSurfaceWalkable( void ) { return ( ( dispFlags & DISPSURF_FLAG_WALKABLE ) != 0 ); } - bool IsDispSurfaceBuildable( void ) { return ( ( dispFlags & DISPSURF_FLAG_BUILDABLE ) != 0 ); } - bool IsDispSurfaceProp1( void ) { return ( ( dispFlags & DISPSURF_FLAG_SURFPROP1 ) != 0 ); } - bool IsDispSurfaceProp2( void ) { return ( ( dispFlags & DISPSURF_FLAG_SURFPROP2 ) != 0 ); } - -public: - - // these members are aligned!! - Vector startpos; // start position - Vector endpos; // final position - cplane_t plane; // surface normal at impact - - float fraction; // time completed, 1.0 = didn't hit anything - - int contents; // contents on other side of surface hit - unsigned short dispFlags; // displacement flags for marking surfaces with data - - bool allsolid; // if true, plane is not valid - bool startsolid; // if true, the initial point was in a solid area - - CBaseTrace() {} - -private: - // No copy constructors allowed - CBaseTrace(const CBaseTrace& vOther); -}; - -#endif // TRACE_H diff --git a/public/unicode/unicode.h b/public/unicode/unicode.h deleted file mode 100644 index 236164c0e..000000000 --- a/public/unicode/unicode.h +++ /dev/null @@ -1,65 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef UNICODE_H -#define UNICODE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "interface.h" - -#define WIN32_LEAN_AND_MEAN -#if !defined( _X360 ) -#include -#endif -#if defined( _X360 ) -#include "xbox/xbox_win32stubs.h" -#endif - -class IUnicodeWindows : public IBaseInterface -{ -public: - virtual LRESULT DefWindowProcW - ( - HWND hWnd, - UINT Msg, - WPARAM wParam, - LPARAM lParam - ) = 0; - - virtual HWND CreateWindowExW - ( - DWORD dwExStyle, - LPCWSTR lpClassName, - LPCWSTR lpWindowName, - DWORD dwStyle, - int x, - int y, - int nWidth, - int nHeight, - HWND hWndParent, - HMENU hMenu, - HINSTANCE hInstance, - LPVOID lpParam - ) = 0; - - virtual ATOM RegisterClassW - ( - CONST WNDCLASSW *lpWndClass - ) = 0; - - virtual BOOL UnregisterClassW - ( - LPCWSTR lpClassName, - HINSTANCE hInstance - ) = 0; -}; - -#define VENGINE_UNICODEINTERFACE_VERSION "VENGINEUNICODE001" - - -#endif // UNICODE_H diff --git a/public/unitlib/unitlib.h b/public/unitlib/unitlib.h deleted file mode 100644 index 26d28a5d7..000000000 --- a/public/unitlib/unitlib.h +++ /dev/null @@ -1,270 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef UNITLIB_H -#define UNITLIB_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/platform.h" -#include "tier1/interface.h" -#include "appframework/IAppSystem.h" - - -//----------------------------------------------------------------------------- -// Usage model for the UnitTest library -// -// The general methodology here is that clients are expected to create unit -// test DLLs that statically link to the unit test DLL and which implement -// tests of various libraries. The unit test application will dynamically -// load all DLLs in a directory, which causes them to install their test cases -// into the unit test system. The application then runs through all tests and -// executes them all, displaying the results. -// -// *** NOTE: The test suites are compiled in both debug and release builds, -// even though it's expected to only be useful in debug builds. This is because -// I couldn't come up with a good way of disabling the code in release builds. -// (The only options I could come up with would still compile in the functions, -// just not install them into the unit test library, or would make it so that -// you couldn't step through the unit test code). -// -// Even though this is the case, there's no reason not to add test cases -// directly into your shipping DLLs, as long as you surround the code with -// #ifdef _DEBUG. To error check a project to make sure it's not compiling -// in unit tests in Release build, just don't link in unitlib.lib in Release. -// You can of course also put your test suites into separate DLLs. -// -// All tests inherit from the ITestCase interface. There are two major kinds -// of tests; the first is a single test case meant to run a piece of -// code and check its results match expected values using the Assert macros. -// The second kind is a test suite which is simply a list of other tests. -// -// The following classes and macros are used to easily create unit test cases -// and suites: -// -// Use DEFINE_TESTSUITE to define a particular test suite, and DEFINE_TESTCASE -// to add as many test cases as you like to that test suite, as follows: -// -// DEFINE_TESTSUITE( VectorTestSuite ) -// -// DEFINE_TESTCASE( VectorAdditionTest, VectorTestSuite ) -// { -// .. test code here .. -// } -// -// Note that the definition of the test suite can occur in a different file -// as the test case. A link error will occur if the test suite to which a -// test case is added has not been defined. -// -// To create a test case that is not part of a suite, use... -// -// DEFINE_TESTCASE_NOSUITE( VectorAdditionTest ) -// { -// .. test code here .. -// } -// -// You can also create a suite which is a child of another suite using -// -// DEFINE_SUBSUITE( VectorTestSuite, MathTestSuite ) -// -//----------------------------------------------------------------------------- - - - -//----------------------------------------------------------------------------- -// dll export stuff -//----------------------------------------------------------------------------- - -#ifdef UNITLIB_DLL_EXPORT -#define UNITLIB_INTERFACE DLL_EXPORT -#define UNITLIB_CLASS_INTERFACE DLL_CLASS_EXPORT -#define UNITLIB_GLOBAL_INTERFACE DLL_GLOBAL_EXPORT -#else -#define UNITLIB_INTERFACE DLL_IMPORT -#define UNITLIB_CLASS_INTERFACE DLL_CLASS_IMPORT -#define UNITLIB_GLOBAL_INTERFACE DLL_GLOBAL_IMPORT -#endif - - -//----------------------------------------------------------------------------- -// All unit test libraries can be asked for a unit test -// AppSystem to perform connection -//----------------------------------------------------------------------------- -#define UNITTEST_INTERFACE_VERSION "UnitTestV001" - - -//----------------------------------------------------------------------------- -// -// NOTE: All classes and interfaces below you shouldn't use directly. -// Use the DEFINE_TESTSUITE and DEFINE_TESTCASE macros instead. -// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// Test case + suite interface -//----------------------------------------------------------------------------- -class ITestCase -{ -public: - // This returns the test name - virtual char const* GetName() = 0; - - // This runs the test - virtual void RunTest() = 0; -}; - -class ITestSuite : public ITestCase -{ -public: - // Add a test to the suite... - virtual void AddTest( ITestCase* pTest ) = 0; -}; - - - -//----------------------------------------------------------------------------- -// This is the main function exported by the unit test library used by -// unit test DLLs to install their test cases into a list to be run -//----------------------------------------------------------------------------- -UNITLIB_INTERFACE void UnitTestInstallTestCase( ITestCase* pTest ); - - -//----------------------------------------------------------------------------- -// These are the methods used by the unit test running program to run all tests -//----------------------------------------------------------------------------- -UNITLIB_INTERFACE int UnitTestCount(); -UNITLIB_INTERFACE ITestCase* GetUnitTest( int i ); - - -//----------------------------------------------------------------------------- -// Helper for unit test DLLs to expose IAppSystems -//----------------------------------------------------------------------------- -#define USE_UNITTEST_APPSYSTEM( _className ) \ - static _className s_UnitTest ## _className; \ - EXPOSE_SINGLE_INTERFACE_GLOBALVAR( _className, IAppSystem, UNITTEST_INTERFACE_VERSION, s_UnitTest ## _className ); - - -//----------------------------------------------------------------------------- -// Base class for test cases -//----------------------------------------------------------------------------- -class UNITLIB_CLASS_INTERFACE CTestCase : public ITestCase -{ -public: - CTestCase( char const* pName, ITestSuite* pParent = 0 ); - ~CTestCase(); - - // Returns the test name - char const* GetName(); - -private: - char* m_pName; -}; - - -//----------------------------------------------------------------------------- -// Test suite class -//----------------------------------------------------------------------------- -class UNITLIB_CLASS_INTERFACE CTestSuite : public ITestSuite -{ -public: - CTestSuite( char const* pName, ITestSuite* pParent = 0 ); - ~CTestSuite(); - - // This runs the test - void RunTest(); - - // Add a test to the suite... - void AddTest( ITestCase* pTest ); - - // Returns the test name - char const* GetName(); - -protected: - int m_TestCount; - ITestCase** m_ppTestCases; - char* m_pName; -}; - -#define TESTSUITE_CLASS( _suite ) \ - class CTS ## _suite : public CTestSuite \ - { \ - public: \ - CTS ## _suite(); \ - }; - -#define TESTSUITE_ACCESSOR( _suite ) \ - CTS ## _suite* GetTS ## _suite() \ - { \ - static CTS ## _suite s_TS ## _suite; \ - return &s_TS ## _suite; \ - } - -#define FWD_DECLARE_TESTSUITE( _suite ) \ - class CTS ## _suite; \ - CTS ## _suite* GetTS ## _suite(); - -#define DEFINE_TESTSUITE( _suite ) \ - TESTSUITE_CLASS( _suite ) \ - TESTSUITE_ACCESSOR( _suite ) \ - CTS ## _suite::CTS ## _suite() : CTestSuite( #_suite ) {} - -#define DEFINE_SUBSUITE( _suite, _parent ) \ - TESTSUITE_CLASS( _suite ) \ - TESTSUITE_ACCESSOR( _suite ) \ - FWD_DECLARE_TESTSUITE( _parent ) \ - CTS ## _suite::CTS ## _suite() : CTestSuite( #_suite, GetTS ## _parent() ) {} - -#define TESTCASE_CLASS( _case ) \ - class CTC ## _case : public CTestCase \ - { \ - public: \ - CTC ## _case (); \ - void RunTest(); \ - }; - -#define DEFINE_TESTCASE_NOSUITE( _case ) \ - TESTCASE_CLASS( _case ) \ - CTC ## _case::CTC ## _case () : CTestCase( #_case ) {} \ - \ - CTC ## _case s_TC ## _case; \ - \ - void CTC ## _case ::RunTest() - -#define DEFINE_TESTCASE( _case, _suite ) \ - TESTCASE_CLASS( _case ) \ - FWD_DECLARE_TESTSUITE( _suite ) \ - CTC ## _case::CTC ## _case () : CTestCase( #_case, GetTS ## _suite() ) {} \ - \ - CTC ## _case s_TC ## _case; \ - \ - void CTC ## _case ::RunTest() - - -#define _Shipping_AssertMsg( _exp, _msg, _executeExp, _bFatal ) \ - do { \ - if (!(_exp)) \ - { \ - _SpewInfo( SPEW_ASSERT, __TFILE__, __LINE__ ); \ - SpewRetval_t ret = _SpewMessage(_msg); \ - _executeExp; \ - if ( ret == SPEW_DEBUGGER) \ - { \ - if ( !ShouldUseNewAssertDialog() || DoNewAssertDialog( __TFILE__, __LINE__, _msg ) ) \ - DebuggerBreak(); \ - if ( _bFatal ) \ - _ExitOnFatalAssert( __TFILE__, __LINE__ ); \ - } \ - } \ - } while (0) - -#define Shipping_Assert( _exp ) _Shipping_AssertMsg( _exp, _T("Assertion Failed: ") _T(#_exp), ((void)0), false ) - - -#endif // UNITLIB_H diff --git a/public/vallocator.cpp b/public/vallocator.cpp deleted file mode 100644 index 269408ddb..000000000 --- a/public/vallocator.cpp +++ /dev/null @@ -1,36 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#if !defined(_STATIC_LINKED) || defined(_SHARED_LIB) - -#include -#include "vallocator.h" -#include "basetypes.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -VStdAllocator g_StdAllocator; - -void* VStdAllocator::Alloc(unsigned long size) -{ - if(size) - { - void *ret = malloc(size); - return ret; - } - else - return 0; -} - -void VStdAllocator::Free(void *ptr) -{ - free(ptr); -} - -#endif // !_STATIC_LINKED || _SHARED_LIB diff --git a/public/vallocator.h b/public/vallocator.h deleted file mode 100644 index 980bb8b32..000000000 --- a/public/vallocator.h +++ /dev/null @@ -1,84 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -// These classes let you write your own allocators to be used with new and delete. -// If you have an allocator: VAllocator *pAlloc, you can call new and delete like this: -// -// ptr = VNew(pAlloc) ClassName; -// VDelete(pAlloc, ptr); -// -// Note: allocating and freeing arrays of objects will not work using VAllocators. - - - -#ifndef VALLOCATOR_H -#define VALLOCATOR_H - - -class VAllocator -{ -public: - virtual void* Alloc(unsigned long size)=0; - virtual void Free(void *ptr)=0; -}; - - -// This allocator just uses malloc and free. -class VStdAllocator : public VAllocator -{ -public: - virtual void* Alloc(unsigned long size); - virtual void Free(void *ptr); -}; -extern VStdAllocator g_StdAllocator; - - - -// Use these to allocate classes through VAllocator. -// Allocating arrays of classes is not supported. -#define VNew(pAlloc) new -#define VDelete(pAlloc, ptr) delete ptr - -// Used internally.. just makes sure we call the right operator new. -class DummyAllocatorHelper -{ -public: - int x; -}; - -inline void* operator new(size_t size, void *ptr, DummyAllocatorHelper *asdf) -{ - asdf=asdf; // compiler warning. - size=size; - return ptr; -} - -inline void operator delete(void *ptrToDelete, void *ptr, DummyAllocatorHelper *asdf) -{ - asdf=asdf; // compiler warning. - ptr=ptr; - ptrToDelete=ptrToDelete; -} - -// Use these to manually construct and destruct lists of objects. -template -inline void VAllocator_CallConstructors(T *pObjects, int count=1) -{ - for(int i=0; i < count; i++) - new(&pObjects[i], (DummyAllocatorHelper*)0) T; -} - -template -inline void VAllocator_CallDestructors(T *pObjects, int count) -{ - for(int i=0; i < count; i++) - pObjects[i].~T(); -} - -#endif - diff --git a/public/vaudio/ivaudio.h b/public/vaudio/ivaudio.h deleted file mode 100644 index d26663d31..000000000 --- a/public/vaudio/ivaudio.h +++ /dev/null @@ -1,60 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IVAUDIO_H -#define IVAUDIO_H -#ifdef _WIN32 -#pragma once -#endif - -class IAudioStreamEvent -{ -public: - // called by the stream to request more data - // seek the source to position "offset" - // -1 indicates previous position - // copy the data to pBuffer and return the number of bytes copied - // you may return less than bytesRequested if the end of the stream - // is encountered. - virtual int StreamRequestData( void *pBuffer, int bytesRequested, int offset ) = 0; -}; - - -class IAudioStream -{ -public: - // Decode another bufferSize output bytes from the stream - // returns number of bytes decoded - virtual int Decode( void *pBuffer, unsigned int bufferSize ) = 0; - - // output sampling bits (8/16) - virtual int GetOutputBits() = 0; - // output sampling rate in Hz - virtual int GetOutputRate() = 0; - // output channels (1=mono,2=stereo) - virtual int GetOutputChannels() = 0; - - // seek - virtual unsigned int GetPosition() = 0; - - // NOTE: BUGBUG: Only supports seeking forward currently! - virtual void SetPosition( unsigned int position ) = 0; - - // reset? -}; - - -#define VAUDIO_INTERFACE_VERSION "VAudio002" -class IVAudio -{ -public: - virtual IAudioStream *CreateMP3StreamDecoder( IAudioStreamEvent *pEventHandler ) = 0; - virtual void DestroyMP3StreamDecoder( IAudioStream *pDecoder ) = 0; -}; - - -#endif // IVAUDIO_H diff --git a/public/vcollide.h b/public/vcollide.h deleted file mode 100644 index 369d129ac..000000000 --- a/public/vcollide.h +++ /dev/null @@ -1,26 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef VCOLLIDE_H -#define VCOLLIDE_H -#ifdef _WIN32 -#pragma once -#endif - -class CPhysCollide; - -struct vcollide_t -{ - unsigned short solidCount : 15; - unsigned short isPacked : 1; - unsigned short descSize; - // VPhysicsSolids - CPhysCollide **solids; - char *pKeyValues; -}; - -#endif // VCOLLIDE_H diff --git a/public/vcollide_parse.h b/public/vcollide_parse.h deleted file mode 100644 index 74b6e90db..000000000 --- a/public/vcollide_parse.h +++ /dev/null @@ -1,68 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef VCOLLIDE_PARSE_H -#define VCOLLIDE_PARSE_H -#ifdef _WIN32 -#pragma once -#endif - -#include "vphysics_interface.h" - -struct solid_t -{ - int index; - char name[512]; - char parent[512]; - char surfaceprop[512]; - Vector massCenterOverride; - objectparams_t params; -}; - -struct fluid_t -{ - int index; - char surfaceprop[512]; - - fluidparams_t params; - - fluid_t() {} - fluid_t( fluid_t const& src ) : params(src.params) - { - index = src.index; - } -}; - -//----------------------------------------------------------------------------- -// Purpose: Pass this into the parser to handle the keys that vphysics does not -// parse. -//----------------------------------------------------------------------------- -class IVPhysicsKeyHandler -{ -public: - virtual void ParseKeyValue( void *pData, const char *pKey, const char *pValue ) = 0; - virtual void SetDefaults( void *pData ) = 0; -}; - - -class IVPhysicsKeyParser -{ -public: - virtual ~IVPhysicsKeyParser() {} - - virtual const char *GetCurrentBlockName( void ) = 0; - virtual bool Finished( void ) = 0; - virtual void ParseSolid( solid_t *pSolid, IVPhysicsKeyHandler *unknownKeyHandler ) = 0; - virtual void ParseFluid( fluid_t *pFluid, IVPhysicsKeyHandler *unknownKeyHandler ) = 0; - virtual void ParseRagdollConstraint( constraint_ragdollparams_t *pConstraint, IVPhysicsKeyHandler *unknownKeyHandler ) = 0; - virtual void ParseSurfaceTable( int *table, IVPhysicsKeyHandler *unknownKeyHandler ) = 0; - virtual void ParseCustom( void *pCustom, IVPhysicsKeyHandler *unknownKeyHandler ) = 0; - virtual void ParseVehicle( vehicleparams_t *pVehicle, IVPhysicsKeyHandler *unknownKeyHandler ) = 0; - virtual void SkipBlock( void ) = 0; -}; - -#endif // VCOLLIDE_PARSE_H diff --git a/public/vgui/Cursor.h b/public/vgui/Cursor.h deleted file mode 100644 index 3aa5fc143..000000000 --- a/public/vgui/Cursor.h +++ /dev/null @@ -1,45 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Holds the enumerated list of default cursors -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef CURSOR_H -#define CURSOR_H - -#ifdef _WIN32 -#pragma once -#endif - -#include - -namespace vgui -{ - -enum CursorCode -{ - dc_user, - dc_none, - dc_arrow, - dc_ibeam, - dc_hourglass, - dc_waitarrow, - dc_crosshair, - dc_up, - dc_sizenwse, - dc_sizenesw, - dc_sizewe, - dc_sizens, - dc_sizeall, - dc_no, - dc_hand, - dc_blank, // don't show any custom vgui cursor, just let windows do it stuff (for HTML widget) - dc_last, -}; - -typedef unsigned long HCursor; - -} - -#endif // CURSOR_H diff --git a/public/vgui/Dar.h b/public/vgui/Dar.h deleted file mode 100644 index 669cbda05..000000000 --- a/public/vgui/Dar.h +++ /dev/null @@ -1,134 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Holds the enumerated list of default cursors -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef DAR_H -#define DAR_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include -#include "tier1/utlvector.h" - -#include "tier0/memdbgon.h" - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Simple lightweight dynamic array implementation -//----------------------------------------------------------------------------- -template class Dar : public CUtlVector< ELEMTYPE > -{ - typedef CUtlVector< ELEMTYPE > BaseClass; - -public: - Dar() - { - } - Dar(int initialCapacity) : - BaseClass( 0, initialCapacity ) - { - } - -public: - void SetCount(int count) - { - EnsureCount( count ); - } - int GetCount() - { - return Count(); - } - int AddElement(ELEMTYPE elem) - { - return AddToTail( elem ); - } - void MoveElementToEnd( ELEMTYPE elem ) - { - if ( Count() == 0 ) - return; - - // quick check to see if it's already at the end - if ( Element( Count() - 1 ) == elem ) - return; - - int idx = Find( elem ); - if ( idx == InvalidIndex() ) - return; - - Remove( idx ); - AddToTail( elem ); - } - // returns the index of the element in the array, -1 if not found - int FindElement(ELEMTYPE elem) - { - return Find( elem ); - } - bool HasElement(ELEMTYPE elem) - { - if ( FindElement(elem) != InvalidIndex() ) - { - return true; - } - return false; - } - int PutElement(ELEMTYPE elem) - { - int index = FindElement(elem); - if (index >= 0) - { - return index; - } - return AddElement(elem); - } - // insert element at index and move all the others down 1 - void InsertElementAt(ELEMTYPE elem,int index) - { - InsertBefore( index, elem ); - } - void SetElementAt(ELEMTYPE elem,int index) - { - EnsureCount( index + 1 ); - Element( index ) = elem; - } - void RemoveElementAt(int index) - { - Remove( index ); - } - - void RemoveElementsBefore(int index) - { - if ( index <= 0 ) - return; - RemoveMultiple( 0, index - 1 ); - } - - void RemoveElement(ELEMTYPE elem) - { - FindAndRemove( elem ); - } - - void *GetBaseData() - { - return Base(); - } - - void CopyFrom(Dar &dar) - { - CoypArray( dar.Base(), dar.Count() ); - } -}; - -} - -#include "tier0/memdbgoff.h" - -#endif // DAR_H diff --git a/public/vgui/IBorder.h b/public/vgui/IBorder.h deleted file mode 100644 index 1dd190776..000000000 --- a/public/vgui/IBorder.h +++ /dev/null @@ -1,63 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IBORDER_H -#define IBORDER_H - -#ifdef _WIN32 -#pragma once -#endif - -#include - -class KeyValues; - -namespace vgui -{ - -class IScheme; - -//----------------------------------------------------------------------------- -// Purpose: Interface to panel borders -// Borders have a close relationship with panels -// They are the edges of the panel. -//----------------------------------------------------------------------------- -class IBorder -{ -public: - virtual void Paint(VPANEL panel) = 0; - virtual void Paint(int x0, int y0, int x1, int y1) = 0; - virtual void Paint(int x0, int y0, int x1, int y1, int breakSide, int breakStart, int breakStop) = 0; - virtual void SetInset(int left, int top, int right, int bottom) = 0; - virtual void GetInset(int &left, int &top, int &right, int &bottom) = 0; - virtual void ApplySchemeSettings(IScheme *pScheme, KeyValues *inResourceData) = 0; - virtual const char *GetName() = 0; - virtual void SetName(const char *name) = 0; - - enum backgroundtype_e - { - BACKGROUND_FILLED, - BACKGROUND_TEXTURED, - BACKGROUND_ROUNDEDCORNERS, - }; - virtual backgroundtype_e GetBackgroundType() = 0; - - enum sides_e - { - SIDE_LEFT = 0, - SIDE_TOP = 1, - SIDE_RIGHT = 2, - SIDE_BOTTOM = 3 - }; - - virtual bool PaintFirst( void ) = 0; -}; - -} // namespace vgui - - -#endif // IBORDER_H diff --git a/public/vgui/IClientPanel.h b/public/vgui/IClientPanel.h deleted file mode 100644 index 2199eae96..000000000 --- a/public/vgui/IClientPanel.h +++ /dev/null @@ -1,92 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ICLIENTPANEL_H -#define ICLIENTPANEL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include - -#ifdef GetClassName -#undef GetClassName -#endif - -class KeyValues; - -namespace vgui -{ - -class Panel; -class SurfaceBase; - -enum EInterfaceID -{ - ICLIENTPANEL_STANDARD_INTERFACE = 0, -}; - -//----------------------------------------------------------------------------- -// Purpose: Interface from vgui panels -> Client panels -// This interface cannot be changed without rebuilding all vgui projects -// Primarily this interface handles dispatching messages from core vgui to controls -// The additional functions are all their for debugging or optimization reasons -// To add to this later, use QueryInterface() to see if they support new interfaces -//----------------------------------------------------------------------------- -class IClientPanel -{ -public: - virtual VPANEL GetVPanel() = 0; - - // straight interface to Panel functions - virtual void Think() = 0; - virtual void PerformApplySchemeSettings() = 0; - virtual void PaintTraverse(bool forceRepaint, bool allowForce) = 0; - virtual void Repaint() = 0; - virtual VPANEL IsWithinTraverse(int x, int y, bool traversePopups) = 0; - virtual void GetInset(int &top, int &left, int &right, int &bottom) = 0; - virtual void GetClipRect(int &x0, int &y0, int &x1, int &y1) = 0; - virtual void OnChildAdded(VPANEL child) = 0; - virtual void OnSizeChanged(int newWide, int newTall) = 0; - - virtual void InternalFocusChanged(bool lost) = 0; - virtual bool RequestInfo(KeyValues *outputData) = 0; - virtual void RequestFocus(int direction) = 0; - virtual bool RequestFocusPrev(VPANEL existingPanel) = 0; - virtual bool RequestFocusNext(VPANEL existingPanel) = 0; - virtual void OnMessage(const KeyValues *params, VPANEL ifromPanel) = 0; - virtual VPANEL GetCurrentKeyFocus() = 0; - virtual int GetTabPosition() = 0; - - // for debugging purposes - virtual const char *GetName() = 0; - virtual const char *GetClassName() = 0; - - // get scheme handles from panels - virtual HScheme GetScheme() = 0; - // gets whether or not this panel should scale with screen resolution - virtual bool IsProportional() = 0; - // auto-deletion - virtual bool IsAutoDeleteSet() = 0; - // deletes this - virtual void DeletePanel() = 0; - - // interfaces - virtual void *QueryInterface(EInterfaceID id) = 0; - - // returns a pointer to the vgui controls baseclass Panel * - virtual Panel *GetPanel() = 0; - - // returns the name of the module this panel is part of - virtual const char *GetModuleName() = 0; -}; - -} // namespace vgui - - -#endif // ICLIENTPANEL_H diff --git a/public/vgui/IHTML.h b/public/vgui/IHTML.h deleted file mode 100644 index 75f091c61..000000000 --- a/public/vgui/IHTML.h +++ /dev/null @@ -1,86 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IHTML_H -#define IHTML_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include -#include - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: basic interface for a HTML window -//----------------------------------------------------------------------------- -class IHTML -{ -public: - // open a new page - virtual void OpenURL(const char *)=0; - - // stops the existing page from loading - virtual bool StopLoading()=0; - - // refreshes the current page - virtual bool Refresh()=0; - - // display the control - virtual bool Show(bool shown)=0; - - // return the currently opened page - virtual char *GetOpenedPage()=0; - - // called when the browser needs to be resized - virtual void OnSize(int x,int y, int w,int h)=0; - - // returns the width and height (in pixels) of the HTML page - virtual void GetHTMLSize(int &wide,int &tall)=0; - - // clear the text in an existing control - virtual void Clear()=0; - - // add text to the browser control (as a HTML formated string) - virtual void AddText(const char *text)=0; - - - enum MOUSE_STATE { UP,DOWN,MOVE }; - - virtual void OnMouse(MouseCode code,MOUSE_STATE s,int x,int y)=0; - virtual void OnChar(wchar_t unichar)=0; - virtual void OnKeyDown(KeyCode code)=0; - - virtual vgui::IImage *GetBitmap()=0; - - virtual void SetVisible( bool state ) = 0; -}; - -//----------------------------------------------------------------------------- -// Purpose: basic callback interface for a HTML window -//----------------------------------------------------------------------------- -class IHTMLEvents -{ -public: - // call backs for events - virtual bool OnStartURL(const char *url, const char *target, bool first)=0; - virtual void OnFinishURL(const char *url)=0; - virtual void OnProgressURL(long current, long maximum)=0; - virtual void OnSetStatusText(const char *text) =0; - virtual void OnUpdate() =0; - virtual void OnLink()=0; - virtual void OffLink()=0; -}; - -} - -#endif // IHTML_H diff --git a/public/vgui/IImage.h b/public/vgui/IImage.h deleted file mode 100644 index 999d96e41..000000000 --- a/public/vgui/IImage.h +++ /dev/null @@ -1,54 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IIMAGE_H -#define IIMAGE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include - -class Color; - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Interface to drawing an image -//----------------------------------------------------------------------------- -class IImage -{ -public: - // Call to Paint the image - // Image will draw within the current panel context at the specified position - virtual void Paint() = 0; - - // Set the position of the image - virtual void SetPos(int x, int y) = 0; - - // Gets the size of the content - virtual void GetContentSize(int &wide, int &tall) = 0; - - // Get the size the image will actually draw in (usually defaults to the content size) - virtual void GetSize(int &wide, int &tall) = 0; - - // Sets the size of the image - virtual void SetSize(int wide, int tall) = 0; - - // Set the draw color - virtual void SetColor(Color col) = 0; - - // virtual destructor - virtual ~IImage() {} -}; - -} // namespace vgui - - -#endif // IIMAGE_H diff --git a/public/vgui/IInput.h b/public/vgui/IInput.h deleted file mode 100644 index 64bdc0ee0..000000000 --- a/public/vgui/IInput.h +++ /dev/null @@ -1,188 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef VGUI_IINPUT_H -#define VGUI_IINPUT_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include "tier1/interface.h" -#include "vgui/MouseCode.h" -#include "vgui/KeyCode.h" - -namespace vgui -{ - -class Cursor; -typedef unsigned long HCursor; - -#define VGUI_GCS_COMPREADSTR 0x0001 -#define VGUI_GCS_COMPREADATTR 0x0002 -#define VGUI_GCS_COMPREADCLAUSE 0x0004 -#define VGUI_GCS_COMPSTR 0x0008 -#define VGUI_GCS_COMPATTR 0x0010 -#define VGUI_GCS_COMPCLAUSE 0x0020 -#define VGUI_GCS_CURSORPOS 0x0080 -#define VGUI_GCS_DELTASTART 0x0100 -#define VGUI_GCS_RESULTREADSTR 0x0200 -#define VGUI_GCS_RESULTREADCLAUSE 0x0400 -#define VGUI_GCS_RESULTSTR 0x0800 -#define VGUI_GCS_RESULTCLAUSE 0x1000 -// style bit flags for WM_IME_COMPOSITION -#define VGUI_CS_INSERTCHAR 0x2000 -#define VGUI_CS_NOMOVECARET 0x4000 - -class IInput : public IBaseInterface -{ -public: - virtual void SetMouseFocus(VPANEL newMouseFocus) = 0; - virtual void SetMouseCapture(VPANEL panel) = 0; - - // returns the string name of a scan code - virtual void GetKeyCodeText(KeyCode code, char *buf, int buflen) = 0; - - // focus - virtual VPANEL GetFocus() = 0; - virtual VPANEL GetMouseOver() = 0; // returns the panel the mouse is currently over, ignoring mouse capture - - // mouse state - virtual void SetCursorPos(int x, int y) = 0; - virtual void GetCursorPos(int &x, int &y) = 0; - virtual bool WasMousePressed(MouseCode code) = 0; - virtual bool WasMouseDoublePressed(MouseCode code) = 0; - virtual bool IsMouseDown(MouseCode code) = 0; - - // cursor override - virtual void SetCursorOveride(HCursor cursor) = 0; - virtual HCursor GetCursorOveride() = 0; - - // key state - virtual bool WasMouseReleased(MouseCode code) = 0; - virtual bool WasKeyPressed(KeyCode code) = 0; - virtual bool IsKeyDown(KeyCode code) = 0; - virtual bool WasKeyTyped(KeyCode code) = 0; - virtual bool WasKeyReleased(KeyCode code) = 0; - - virtual VPANEL GetAppModalSurface() = 0; - // set the modal dialog panel. - // all events will go only to this panel and its children. - virtual void SetAppModalSurface(VPANEL panel) = 0; - // release the modal dialog panel - // do this when your modal dialog finishes. - virtual void ReleaseAppModalSurface() = 0; - - virtual void GetCursorPosition( int &x, int &y ) = 0; - - virtual void SetIMEWindow( void *hwnd ) = 0; - virtual void *GetIMEWindow() = 0; - - virtual void OnChangeIME( bool forward ) = 0; - virtual int GetCurrentIMEHandle() = 0; - virtual int GetEnglishIMEHandle() = 0; - - // Returns the Language Bar label (Chinese, Korean, Japanese, Russion, Thai, etc.) - virtual void GetIMELanguageName( wchar_t *buf, int unicodeBufferSizeInBytes ) = 0; - // Returns the short code for the language (EN, CH, KO, JP, RU, TH, etc. ). - virtual void GetIMELanguageShortCode( wchar_t *buf, int unicodeBufferSizeInBytes ) = 0; - - struct LanguageItem - { - wchar_t shortname[ 4 ]; - wchar_t menuname[ 128 ]; - int handleValue; - bool active; // true if this is the active language - }; - - struct ConversionModeItem - { - wchar_t menuname[ 128 ]; - int handleValue; - bool active; // true if this is the active conversion mode - }; - - struct SentenceModeItem - { - wchar_t menuname[ 128 ]; - int handleValue; - bool active; // true if this is the active sentence mode - }; - - // Call with NULL dest to get item count - virtual int GetIMELanguageList( LanguageItem *dest, int destcount ) = 0; - virtual int GetIMEConversionModes( ConversionModeItem *dest, int destcount ) = 0; - virtual int GetIMESentenceModes( SentenceModeItem *dest, int destcount ) = 0; - - virtual void OnChangeIMEByHandle( int handleValue ) = 0; - virtual void OnChangeIMEConversionModeByHandle( int handleValue ) = 0; - virtual void OnChangeIMESentenceModeByHandle( int handleValue ) = 0; - - virtual void OnInputLanguageChanged() = 0; - virtual void OnIMEStartComposition() = 0; - virtual void OnIMEComposition( int flags ) = 0; - virtual void OnIMEEndComposition() = 0; - - virtual void OnIMEShowCandidates() = 0; - virtual void OnIMEChangeCandidates() = 0; - virtual void OnIMECloseCandidates() = 0; - virtual void OnIMERecomputeModes() = 0; - - virtual int GetCandidateListCount() = 0; - virtual void GetCandidate( int num, wchar_t *dest, int destSizeBytes ) = 0; - virtual int GetCandidateListSelectedItem() = 0; - virtual int GetCandidateListPageSize() = 0; - virtual int GetCandidateListPageStart() = 0; - - //NOTE: We render our own candidate lists most of the time... - virtual void SetCandidateWindowPos( int x, int y ) = 0; - - virtual bool GetShouldInvertCompositionString() = 0; - virtual bool CandidateListStartsAtOne() = 0; - - virtual void SetCandidateListPageStart( int start ) = 0; - - // Passes in a keycode which allows hitting other mouse buttons w/o cancelling capture mode - virtual void SetMouseCaptureEx(VPANEL panel, MouseCode captureStartMouseCode ) = 0; - - // Because OnKeyCodeTyped uses CallParentFunction and is therefore message based, there's no way - // to know if handler actually swallowed the specified keycode. To get around this, I set a global before calling the - // kb focus OnKeyCodeTyped function and if we ever get to a Panel::OnKeyCodeTypes we know that nobody handled the message - // and in that case we can post a message to any "unhandled keycode" listeners - // This will generate an MESSAGE_FUNC_INT( "KeyCodeUnhandled" "code" code ) message to each such listener - virtual void RegisterKeyCodeUnhandledListener( VPANEL panel ) = 0; - virtual void UnregisterKeyCodeUnhandledListener( VPANEL panel ) = 0; - - // Posts unhandled message to all interested panels - virtual void OnKeyCodeUnhandled( int keyCode ) = 0; - - // Assumes subTree is a child panel of the root panel for the vgui contect - // if restrictMessagesToSubTree is true, then mouse and kb messages are only routed to the subTree and it's children and mouse/kb focus - // can only be on one of the subTree children, if a mouse click occurs outside of the subtree, and "UnhandledMouseClick" message is sent to unhandledMouseClickListener panel - // if it's set - // if restrictMessagesToSubTree is false, then mouse and kb messages are routed as normal except that they are not routed down into the subtree - // however, if a mouse click occurs outside of the subtree, and "UnhandleMouseClick" message is sent to unhandledMouseClickListener panel - // if it's set - virtual void SetModalSubTree( VPANEL subTree, VPANEL unhandledMouseClickListener, bool restrictMessagesToSubTree = true ) = 0; - virtual void ReleaseModalSubTree() = 0; - virtual VPANEL GetModalSubTree() = 0; - - // These toggle whether the modal subtree is exclusively receiving messages or conversely whether it's being excluded from receiving messages - // Sends a "ModalSubTree", state message - virtual void SetModalSubTreeReceiveMessages( bool state ) = 0; - virtual bool ShouldModalSubTreeReceiveMessages() const = 0; - - virtual VPANEL GetMouseCapture() = 0; -}; - -#define VGUI_INPUT_INTERFACE_VERSION "VGUI_Input005" - -} // namespace vgui - - -#endif // VGUI_IINPUT_H diff --git a/public/vgui/IInputInternal.h b/public/vgui/IInputInternal.h deleted file mode 100644 index 56d66aaab..000000000 --- a/public/vgui/IInputInternal.h +++ /dev/null @@ -1,86 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef IINPUTINTERNAL_H -#define IINPUTINTERNAL_H -#ifdef _WIN32 -#pragma once -#endif - -#include - -namespace vgui -{ - -enum MouseCodeState_t -{ - BUTTON_RELEASED = 0, - BUTTON_PRESSED, - BUTTON_DOUBLECLICKED, -}; - -typedef int HInputContext; - -#define DEFAULT_INPUT_CONTEXT ((vgui::HInputContext)~0) - -class IInputInternal : public IInput -{ -public: - // processes input for a frame - virtual void RunFrame() = 0; - - virtual void UpdateMouseFocus(int x, int y) = 0; - - // called when a panel becomes invalid - virtual void PanelDeleted(VPANEL panel) = 0; - - // inputs into vgui input handling - virtual bool InternalCursorMoved(int x,int y) = 0; //expects input in surface space - virtual bool InternalMousePressed(MouseCode code) = 0; - virtual bool InternalMouseDoublePressed(MouseCode code) = 0; - virtual bool InternalMouseReleased(MouseCode code) = 0; - virtual bool InternalMouseWheeled(int delta) = 0; - virtual bool InternalKeyCodePressed(KeyCode code) = 0; - virtual void InternalKeyCodeTyped(KeyCode code) = 0; - virtual void InternalKeyTyped(wchar_t unichar) = 0; - virtual bool InternalKeyCodeReleased(KeyCode code) = 0; - - // Creates/ destroys "input" contexts, which contains information - // about which controls have mouse + key focus, for example. - virtual HInputContext CreateInputContext() = 0; - virtual void DestroyInputContext( HInputContext context ) = 0; - - // Associates a particular panel with an input context - // Associating NULL is valid; it disconnects the panel from the context - virtual void AssociatePanelWithInputContext( HInputContext context, VPANEL pRoot ) = 0; - - // Activates a particular input context, use DEFAULT_INPUT_CONTEXT - // to get the one normally used by VGUI - virtual void ActivateInputContext( HInputContext context ) = 0; - - // This method is called to post a cursor message to the current input context - virtual void PostCursorMessage() = 0; - - // Cursor position; this is the current position read from the input queue. - // We need to set it because client code may read this during Mouse Pressed - // events, etc. - virtual void UpdateCursorPosInternal( int x, int y ) = 0; - - // Called to handle explicit calls to CursorSetPos after input processing is complete - virtual void HandleExplicitSetCursor( ) = 0; - - // Updates the internal key/mouse state associated with the current input context without sending messages - virtual void SetKeyCodeState( KeyCode code, bool bPressed ) = 0; - virtual void SetMouseCodeState( MouseCode code, MouseCodeState_t state ) = 0; - virtual void UpdateButtonState( const InputEvent_t &event ) = 0; -}; - -} // namespace vgui - -#define VGUI_INPUTINTERNAL_INTERFACE_VERSION "VGUI_InputInternal001" - -#endif // IINPUTINTERNAL_H diff --git a/public/vgui/ILocalize.h b/public/vgui/ILocalize.h deleted file mode 100644 index 44e780e84..000000000 --- a/public/vgui/ILocalize.h +++ /dev/null @@ -1,105 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef ILOCALIZE_H -#define ILOCALIZE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include "appframework/IAppSystem.h" -#include - -// unicode character type -// for more unicode manipulation functions #include -#ifndef _WCHAR_T_DEFINED -typedef unsigned short wchar_t; -#define _WCHAR_T_DEFINED -#endif - - -namespace vgui -{ -// direct references to localized strings -typedef unsigned long StringIndex_t; -const unsigned long INVALID_STRING_INDEX = (unsigned long) -1; - -//----------------------------------------------------------------------------- -// Purpose: Handles localization of text -// looks up string names and returns the localized unicode text -//----------------------------------------------------------------------------- -abstract_class ILocalize -{ -public: - // adds the contents of a file to the localization table - virtual bool AddFile( const char *fileName, const char *pPathID = NULL, bool bIncludeFallbackSearchPaths = false ) = 0; - - // Remove all strings from the table - virtual void RemoveAll() = 0; - - // Finds the localized text for tokenName - virtual wchar_t *Find(char const *tokenName) = 0; - - // converts an english string to unicode - // returns the number of wchar_t in resulting string, including null terminator - virtual int ConvertANSIToUnicode(const char *ansi, wchar_t *unicode, int unicodeBufferSizeInBytes) = 0; - - // converts an unicode string to an english string - // unrepresentable characters are converted to system default - // returns the number of characters in resulting string, including null terminator - virtual int ConvertUnicodeToANSI(const wchar_t *unicode, char *ansi, int ansiBufferSize) = 0; - - // finds the index of a token by token name, INVALID_STRING_INDEX if not found - virtual StringIndex_t FindIndex(const char *tokenName) = 0; - - // builds a localized formatted string - // uses the format strings first: %s1, %s2, ... unicode strings (wchar_t *) - virtual void ConstructString(wchar_t *unicodeOuput, int unicodeBufferSizeInBytes, wchar_t *formatString, int numFormatParameters, ...) = 0; - - // gets the values by the string index - virtual const char *GetNameByIndex(StringIndex_t index) = 0; - virtual wchar_t *GetValueByIndex(StringIndex_t index) = 0; - - /////////////////////////////////////////////////////////////////// - // the following functions should only be used by localization editors - - // iteration functions - virtual StringIndex_t GetFirstStringIndex() = 0; - // returns the next index, or INVALID_STRING_INDEX if no more strings available - virtual StringIndex_t GetNextStringIndex(StringIndex_t index) = 0; - - // adds a single name/unicode string pair to the table - virtual void AddString( const char *tokenName, wchar_t *unicodeString, const char *fileName ) = 0; - - // changes the value of a string - virtual void SetValueByIndex(StringIndex_t index, wchar_t *newValue) = 0; - - // saves the entire contents of the token tree to the file - virtual bool SaveToFile( const char *fileName ) = 0; - - // iterates the filenames - virtual int GetLocalizationFileCount() = 0; - virtual const char *GetLocalizationFileName(int index) = 0; - - // returns the name of the file the specified localized string is stored in - virtual const char *GetFileNameByIndex(StringIndex_t index) = 0; - - // for development only, reloads localization files - virtual void ReloadLocalizationFiles( ) = 0; - - // need to replace the existing ConstructString with this - virtual void ConstructString(wchar_t *unicodeOutput, int unicodeBufferSizeInBytes, const char *tokenName, KeyValues *localizationVariables) = 0; - virtual void ConstructString(wchar_t *unicodeOutput, int unicodeBufferSizeInBytes, StringIndex_t unlocalizedTextSymbol, KeyValues *localizationVariables) = 0; -}; - -#define VGUI_LOCALIZE_INTERFACE_VERSION "VGUI_Localize004" - -}; // namespace vgui - -#endif // ILOCALIZE_H diff --git a/public/vgui/IPanel.h b/public/vgui/IPanel.h deleted file mode 100644 index b2e786ef9..000000000 --- a/public/vgui/IPanel.h +++ /dev/null @@ -1,133 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IPANEL_H -#define IPANEL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include "tier1/interface.h" - -#ifdef SendMessage -#undef SendMessage -#endif - -class KeyValues; - -namespace vgui -{ - -class SurfacePlat; -class IClientPanel; - -//!! must be removed -class Panel; - -//----------------------------------------------------------------------------- -// Purpose: interface from Client panels -> vgui panels -//----------------------------------------------------------------------------- -class IPanel : public IBaseInterface -{ -public: - virtual void Init(VPANEL vguiPanel, IClientPanel *panel) = 0; - - // methods - virtual void SetPos(VPANEL vguiPanel, int x, int y) = 0; - virtual void GetPos(VPANEL vguiPanel, int &x, int &y) = 0; - virtual void SetSize(VPANEL vguiPanel, int wide,int tall) = 0; - virtual void GetSize(VPANEL vguiPanel, int &wide, int &tall) = 0; - virtual void SetMinimumSize(VPANEL vguiPanel, int wide, int tall) = 0; - virtual void GetMinimumSize(VPANEL vguiPanel, int &wide, int &tall) = 0; - virtual void SetZPos(VPANEL vguiPanel, int z) = 0; - virtual int GetZPos(VPANEL vguiPanel) = 0; - - virtual void GetAbsPos(VPANEL vguiPanel, int &x, int &y) = 0; - virtual void GetClipRect(VPANEL vguiPanel, int &x0, int &y0, int &x1, int &y1) = 0; - virtual void SetInset(VPANEL vguiPanel, int left, int top, int right, int bottom) = 0; - virtual void GetInset(VPANEL vguiPanel, int &left, int &top, int &right, int &bottom) = 0; - - virtual void SetVisible(VPANEL vguiPanel, bool state) = 0; - virtual bool IsVisible(VPANEL vguiPanel) = 0; - virtual void SetParent(VPANEL vguiPanel, VPANEL newParent) = 0; - virtual int GetChildCount(VPANEL vguiPanel) = 0; - virtual VPANEL GetChild(VPANEL vguiPanel, int index) = 0; - virtual VPANEL GetParent(VPANEL vguiPanel) = 0; - virtual void MoveToFront(VPANEL vguiPanel) = 0; - virtual void MoveToBack(VPANEL vguiPanel) = 0; - virtual bool HasParent(VPANEL vguiPanel, VPANEL potentialParent) = 0; - virtual bool IsPopup(VPANEL vguiPanel) = 0; - virtual void SetPopup(VPANEL vguiPanel, bool state) = 0; - virtual bool IsFullyVisible( VPANEL vguiPanel ) = 0; - - // gets the scheme this panel uses - virtual HScheme GetScheme(VPANEL vguiPanel) = 0; - // gets whether or not this panel should scale with screen resolution - virtual bool IsProportional(VPANEL vguiPanel) = 0; - // returns true if auto-deletion flag is set - virtual bool IsAutoDeleteSet(VPANEL vguiPanel) = 0; - // deletes the Panel * associated with the vpanel - virtual void DeletePanel(VPANEL vguiPanel) = 0; - - // input interest - virtual void SetKeyBoardInputEnabled(VPANEL vguiPanel, bool state) = 0; - virtual void SetMouseInputEnabled(VPANEL vguiPanel, bool state) = 0; - virtual bool IsKeyBoardInputEnabled(VPANEL vguiPanel) = 0; - virtual bool IsMouseInputEnabled(VPANEL vguiPanel) = 0; - - // calculates the panels current position within the hierarchy - virtual void Solve(VPANEL vguiPanel) = 0; - - // gets names of the object (for debugging purposes) - virtual const char *GetName(VPANEL vguiPanel) = 0; - virtual const char *GetClassName(VPANEL vguiPanel) = 0; - - // delivers a message to the panel - virtual void SendMessage(VPANEL vguiPanel, KeyValues *params, VPANEL ifromPanel) = 0; - - // these pass through to the IClientPanel - virtual void Think(VPANEL vguiPanel) = 0; - virtual void PerformApplySchemeSettings(VPANEL vguiPanel) = 0; - virtual void PaintTraverse(VPANEL vguiPanel, bool forceRepaint, bool allowForce = true) = 0; - virtual void Repaint(VPANEL vguiPanel) = 0; - virtual VPANEL IsWithinTraverse(VPANEL vguiPanel, int x, int y, bool traversePopups) = 0; - virtual void OnChildAdded(VPANEL vguiPanel, VPANEL child) = 0; - virtual void OnSizeChanged(VPANEL vguiPanel, int newWide, int newTall) = 0; - - virtual void InternalFocusChanged(VPANEL vguiPanel, bool lost) = 0; - virtual bool RequestInfo(VPANEL vguiPanel, KeyValues *outputData) = 0; - virtual void RequestFocus(VPANEL vguiPanel, int direction = 0) = 0; - virtual bool RequestFocusPrev(VPANEL vguiPanel, VPANEL existingPanel) = 0; - virtual bool RequestFocusNext(VPANEL vguiPanel, VPANEL existingPanel) = 0; - virtual VPANEL GetCurrentKeyFocus(VPANEL vguiPanel) = 0; - virtual int GetTabPosition(VPANEL vguiPanel) = 0; - - // used by ISurface to store platform-specific data - virtual SurfacePlat *Plat(VPANEL vguiPanel) = 0; - virtual void SetPlat(VPANEL vguiPanel, SurfacePlat *Plat) = 0; - - // returns a pointer to the vgui controls baseclass Panel * - // destinationModule needs to be passed in to verify that the returned Panel * is from the same module - // it must be from the same module since Panel * vtbl may be different in each module - virtual Panel *GetPanel(VPANEL vguiPanel, const char *destinationModule) = 0; - - virtual bool IsEnabled(VPANEL vguiPanel) = 0; - virtual void SetEnabled(VPANEL vguiPanel, bool state) = 0; - - // Used by the drag/drop manager to always draw on top - virtual bool IsTopmostPopup( VPANEL vguiPanel) = 0; - virtual void SetTopmostPopup( VPANEL vguiPanel, bool state ) = 0; -}; - -#define VGUI_PANEL_INTERFACE_VERSION "VGUI_Panel009" - -} // namespace vgui - - -#endif // IPANEL_H diff --git a/public/vgui/IScheme.h b/public/vgui/IScheme.h deleted file mode 100644 index 541f82cbc..000000000 --- a/public/vgui/IScheme.h +++ /dev/null @@ -1,112 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ISCHEME_H -#define ISCHEME_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include "tier1/interface.h" - -class Color; - -namespace vgui -{ - -typedef unsigned long HScheme; -typedef unsigned long HTexture; - -class IBorder; -class IImage; - -//----------------------------------------------------------------------------- -// Purpose: Holds all panel rendering data -// This functionality is all wrapped in the Panel::GetScheme*() functions -//----------------------------------------------------------------------------- -class IScheme : public IBaseInterface -{ -public: - // gets a string from the default settings section - virtual const char *GetResourceString(const char *stringName) = 0; - - // returns a pointer to an existing border - virtual IBorder *GetBorder(const char *borderName) = 0; - - // returns a pointer to an existing font - virtual HFont GetFont(const char *fontName, bool proportional = false) = 0; - - // inverse font lookup - virtual char const *GetFontName( const HFont& font ) = 0; - - // colors - virtual Color GetColor(const char *colorName, Color defaultColor) = 0; -}; - - - -class ISchemeManager: public IBaseInterface -{ -public: - // loads a scheme from a file - // first scheme loaded becomes the default scheme, and all subsequent loaded scheme are derivitives of that - virtual HScheme LoadSchemeFromFile(const char *fileName, const char *tag) = 0; - - // reloads the scheme from the file - should only be used during development - virtual void ReloadSchemes() = 0; - - // reloads scheme fonts - virtual void ReloadFonts() = 0; - - // returns a handle to the default (first loaded) scheme - virtual HScheme GetDefaultScheme() = 0; - - // returns a handle to the scheme identified by "tag" - virtual HScheme GetScheme(const char *tag) = 0; - - // returns a pointer to an image - virtual IImage *GetImage(const char *imageName, bool hardwareFiltered) = 0; - virtual HTexture GetImageID(const char *imageName, bool hardwareFiltered) = 0; - - // This can only be called at certain times, like during paint() - // It will assert-fail if you call it at the wrong time... - - // FIXME: This interface should go away!!! It's an icky back-door - // If you're using this interface, try instead to cache off the information - // in ApplySchemeSettings - virtual IScheme *GetIScheme( HScheme scheme ) = 0; - - // unload all schemes - virtual void Shutdown( bool full = true ) = 0; - - // gets the proportional coordinates for doing screen-size independant panel layouts - // use these for font, image and panel size scaling (they all use the pixel height of the display for scaling) - virtual int GetProportionalScaledValue( int normalizedValue) = 0; - virtual int GetProportionalNormalizedValue(int scaledValue) = 0; - - // loads a scheme from a file - // first scheme loaded becomes the default scheme, and all subsequent loaded scheme are derivitives of that - virtual HScheme LoadSchemeFromFileEx( VPANEL sizingPanel, const char *fileName, const char *tag) = 0; - // gets the proportional coordinates for doing screen-size independant panel layouts - // use these for font, image and panel size scaling (they all use the pixel height of the display for scaling) - virtual int GetProportionalScaledValueEx( HScheme scheme, int normalizedValue ) = 0; - virtual int GetProportionalNormalizedValueEx( HScheme scheme, int scaledValue ) = 0; - -#ifdef _XBOX - virtual void DeleteImage( const char *pImageName ) = 0; -#endif -}; - -#define VGUI_SCHEME_INTERFACE_VERSION "VGUI_Scheme010" - - -} // namespace vgui - - -#endif // ISCHEME_H diff --git a/public/vgui/ISurface.h b/public/vgui/ISurface.h deleted file mode 100644 index fc294ff8c..000000000 --- a/public/vgui/ISurface.h +++ /dev/null @@ -1,359 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef ISURFACE_H -#define ISURFACE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include // CreateHTML, PaintHTML -#include "tier1/interface.h" -#include "bitmap/imageformat.h" - -#include "appframework/IAppSystem.h" -#include "mathlib/vector2d.h" // must be before the namespace line - -#include "IVguiMatInfo.h" - -#ifdef CreateFont -#undef CreateFont -#endif - -#ifdef PlaySound -#undef PlaySound -#endif - -class Color; - -namespace vgui -{ - -class IImage; -class Image; -class Point; - -// handles -typedef unsigned long HCursor; -typedef unsigned long HTexture; -typedef unsigned long HFont; - - -//SRC only defines - - -struct Vertex_t -{ - Vertex_t() {} - Vertex_t( const Vector2D &pos, const Vector2D &coord = Vector2D( 0, 0 ) ) - { - m_Position = pos; - m_TexCoord = coord; - } - void Init( const Vector2D &pos, const Vector2D &coord = Vector2D( 0, 0 ) ) - { - m_Position = pos; - m_TexCoord = coord; - } - - Vector2D m_Position; - Vector2D m_TexCoord; -}; - - -enum FontDrawType_t -{ - // Use the "additive" value from the scheme file - FONT_DRAW_DEFAULT = 0, - - // Overrides - FONT_DRAW_NONADDITIVE, - FONT_DRAW_ADDITIVE, - - FONT_DRAW_TYPE_COUNT = 2, -}; - - -// Refactor these two -struct CharRenderInfo -{ - // In: - FontDrawType_t drawType; - wchar_t ch; - - // Out - bool valid; - - // In/Out (true by default) - bool shouldclip; - // Text pos - int x, y; - // Top left and bottom right - Vertex_t verts[ 2 ]; - int textureId; - int abcA; - int abcB; - int abcC; - int fontTall; - HFont currentFont; -}; - - -struct IntRect -{ - int x0; - int y0; - int x1; - int y1; -}; - -//----------------------------------------------------------------------------- -// Purpose: Wraps contextless windows system functions -//----------------------------------------------------------------------------- -class ISurface : public IAppSystem -{ -public: - // call to Shutdown surface; surface can no longer be used after this is called - virtual void Shutdown() = 0; - - // frame - virtual void RunFrame() = 0; - - // hierarchy root - virtual VPANEL GetEmbeddedPanel() = 0; - virtual void SetEmbeddedPanel( VPANEL pPanel ) = 0; - - // drawing context - virtual void PushMakeCurrent(VPANEL panel, bool useInsets) = 0; - virtual void PopMakeCurrent(VPANEL panel) = 0; - - // rendering functions - virtual void DrawSetColor(int r, int g, int b, int a) = 0; - virtual void DrawSetColor(Color col) = 0; - - virtual void DrawFilledRect(int x0, int y0, int x1, int y1) = 0; - virtual void DrawFilledRectArray( IntRect *pRects, int numRects ) = 0; - virtual void DrawOutlinedRect(int x0, int y0, int x1, int y1) = 0; - - virtual void DrawLine(int x0, int y0, int x1, int y1) = 0; - virtual void DrawPolyLine(int *px, int *py, int numPoints) = 0; - - virtual void DrawSetTextFont(HFont font) = 0; - virtual void DrawSetTextColor(int r, int g, int b, int a) = 0; - virtual void DrawSetTextColor(Color col) = 0; - virtual void DrawSetTextPos(int x, int y) = 0; - virtual void DrawGetTextPos(int& x,int& y) = 0; - virtual void DrawPrintText(const wchar_t *text, int textLen, FontDrawType_t drawType = FONT_DRAW_DEFAULT ) = 0; - virtual void DrawUnicodeChar(wchar_t wch, FontDrawType_t drawType = FONT_DRAW_DEFAULT ) = 0; - - virtual void DrawFlushText() = 0; // flushes any buffered text (for rendering optimizations) - virtual IHTML *CreateHTMLWindow(vgui::IHTMLEvents *events,VPANEL context)=0; - virtual void PaintHTMLWindow(vgui::IHTML *htmlwin) =0; - virtual void DeleteHTMLWindow(IHTML *htmlwin)=0; - - virtual int DrawGetTextureId( char const *filename ) = 0; - virtual bool DrawGetTextureFile(int id, char *filename, int maxlen ) = 0; - virtual void DrawSetTextureFile(int id, const char *filename, int hardwareFilter, bool forceReload) = 0; - virtual void DrawSetTextureRGBA(int id, const unsigned char *rgba, int wide, int tall, int hardwareFilter, bool forceReload)=0; - virtual void DrawSetTexture(int id) = 0; - virtual void DrawGetTextureSize(int id, int &wide, int &tall) = 0; - virtual void DrawTexturedRect(int x0, int y0, int x1, int y1) = 0; - virtual bool IsTextureIDValid(int id) = 0; - - virtual int CreateNewTextureID( bool procedural = false ) = 0; -#ifdef _X360 - virtual void DestroyTextureID( int id ) = 0; - virtual void UncacheUnusedMaterials() = 0; -#endif - - virtual void GetScreenSize(int &wide, int &tall) = 0; - virtual void SetAsTopMost(VPANEL panel, bool state) = 0; - virtual void BringToFront(VPANEL panel) = 0; - virtual void SetForegroundWindow (VPANEL panel) = 0; - virtual void SetPanelVisible(VPANEL panel, bool state) = 0; - virtual void SetMinimized(VPANEL panel, bool state) = 0; - virtual bool IsMinimized(VPANEL panel) = 0; - virtual void FlashWindow(VPANEL panel, bool state) = 0; - virtual void SetTitle(VPANEL panel, const wchar_t *title) = 0; - virtual void SetAsToolBar(VPANEL panel, bool state) = 0; // removes the window's task bar entry (for context menu's, etc.) - - // windows stuff - virtual void CreatePopup(VPANEL panel, bool minimised, bool showTaskbarIcon = true, bool disabled = false, bool mouseInput = true , bool kbInput = true) = 0; - virtual void SwapBuffers(VPANEL panel) = 0; - virtual void Invalidate(VPANEL panel) = 0; - virtual void SetCursor(HCursor cursor) = 0; - virtual bool IsCursorVisible() = 0; - virtual void ApplyChanges() = 0; - virtual bool IsWithin(int x, int y) = 0; - virtual bool HasFocus() = 0; - - // returns true if the surface supports minimize & maximize capabilities - enum SurfaceFeature_e - { - ANTIALIASED_FONTS = 1, - DROPSHADOW_FONTS = 2, - ESCAPE_KEY = 3, - OPENING_NEW_HTML_WINDOWS = 4, - FRAME_MINIMIZE_MAXIMIZE = 5, - OUTLINE_FONTS = 6, - DIRECT_HWND_RENDER = 7, - }; - virtual bool SupportsFeature(SurfaceFeature_e feature) = 0; - - // restricts what gets drawn to one panel and it's children - // currently only works in the game - virtual void RestrictPaintToSinglePanel(VPANEL panel) = 0; - - // these two functions obselete, use IInput::SetAppModalSurface() instead - virtual void SetModalPanel(VPANEL ) = 0; - virtual VPANEL GetModalPanel() = 0; - - virtual void UnlockCursor() = 0; - virtual void LockCursor() = 0; - virtual void SetTranslateExtendedKeys(bool state) = 0; - virtual VPANEL GetTopmostPopup() = 0; - - // engine-only focus handling (replacing WM_FOCUS windows handling) - virtual void SetTopLevelFocus(VPANEL panel) = 0; - - // fonts - // creates an empty handle to a vgui font. windows fonts can be add to this via SetFontGlyphSet(). - virtual HFont CreateFont() = 0; - - // adds to the font - enum EFontFlags - { - FONTFLAG_NONE, - FONTFLAG_ITALIC = 0x001, - FONTFLAG_UNDERLINE = 0x002, - FONTFLAG_STRIKEOUT = 0x004, - FONTFLAG_SYMBOL = 0x008, - FONTFLAG_ANTIALIAS = 0x010, - FONTFLAG_GAUSSIANBLUR = 0x020, - FONTFLAG_ROTARY = 0x040, - FONTFLAG_DROPSHADOW = 0x080, - FONTFLAG_ADDITIVE = 0x100, - FONTFLAG_OUTLINE = 0x200, - FONTFLAG_CUSTOM = 0x400, // custom generated font - never fall back to asian compatibility mode - FONTFLAG_BITMAP = 0x800, // compiled bitmap font - no fallbacks - }; - - virtual bool SetFontGlyphSet(HFont font, const char *windowsFontName, int tall, int weight, int blur, int scanlines, int flags, int nRangeMin = 0, int nRangeMax = 0) = 0; - - // adds a custom font file (only supports true type font files (.ttf) for now) - virtual bool AddCustomFontFile(const char *fontFileName) = 0; - - // returns the details about the font - virtual int GetFontTall(HFont font) = 0; - virtual int GetFontAscent(HFont font, wchar_t wch) = 0; - virtual bool IsFontAdditive(HFont font) = 0; - virtual void GetCharABCwide(HFont font, int ch, int &a, int &b, int &c) = 0; - virtual int GetCharacterWidth(HFont font, int ch) = 0; - virtual void GetTextSize(HFont font, const wchar_t *text, int &wide, int &tall) = 0; - - // notify icons?!? - virtual VPANEL GetNotifyPanel() = 0; - virtual void SetNotifyIcon(VPANEL context, HTexture icon, VPANEL panelToReceiveMessages, const char *text) = 0; - - // plays a sound - virtual void PlaySound(const char *fileName) = 0; - - //!! these functions should not be accessed directly, but only through other vgui items - //!! need to move these to seperate interface - virtual int GetPopupCount() = 0; - virtual VPANEL GetPopup(int index) = 0; - virtual bool ShouldPaintChildPanel(VPANEL childPanel) = 0; - virtual bool RecreateContext(VPANEL panel) = 0; - virtual void AddPanel(VPANEL panel) = 0; - virtual void ReleasePanel(VPANEL panel) = 0; - virtual void MovePopupToFront(VPANEL panel) = 0; - virtual void MovePopupToBack(VPANEL panel) = 0; - - virtual void SolveTraverse(VPANEL panel, bool forceApplySchemeSettings = false) = 0; - virtual void PaintTraverse(VPANEL panel) = 0; - - virtual void EnableMouseCapture(VPANEL panel, bool state) = 0; - - // returns the size of the workspace - virtual void GetWorkspaceBounds(int &x, int &y, int &wide, int &tall) = 0; - - // gets the absolute coordinates of the screen (in windows space) - virtual void GetAbsoluteWindowBounds(int &x, int &y, int &wide, int &tall) = 0; - - // gets the base resolution used in proportional mode - virtual void GetProportionalBase( int &width, int &height ) = 0; - - virtual void CalculateMouseVisible() = 0; - virtual bool NeedKBInput() = 0; - - virtual bool HasCursorPosFunctions() = 0; - virtual void SurfaceGetCursorPos(int &x, int &y) = 0; - virtual void SurfaceSetCursorPos(int x, int y) = 0; - - - // SRC only functions!!! - virtual void DrawTexturedLine( const Vertex_t &a, const Vertex_t &b ) = 0; - virtual void DrawOutlinedCircle(int x, int y, int radius, int segments) = 0; - virtual void DrawTexturedPolyLine( const Vertex_t *p,int n ) = 0; // (Note: this connects the first and last points). - virtual void DrawTexturedSubRect( int x0, int y0, int x1, int y1, float texs0, float text0, float texs1, float text1 ) = 0; - virtual void DrawTexturedPolygon(int n, Vertex_t *pVertices) = 0; - virtual const wchar_t *GetTitle(VPANEL panel) = 0; - virtual bool IsCursorLocked( void ) const = 0; - virtual void SetWorkspaceInsets( int left, int top, int right, int bottom ) = 0; - - // Lower level char drawing code, call DrawGet then pass in info to DrawRender - virtual bool DrawGetUnicodeCharRenderInfo( wchar_t ch, CharRenderInfo& info ) = 0; - virtual void DrawRenderCharFromInfo( const CharRenderInfo& info ) = 0; - - // global alpha setting functions - // affect all subsequent draw calls - shouldn't normally be used directly, only in Panel::PaintTraverse() - virtual void DrawSetAlphaMultiplier( float alpha /* [0..1] */ ) = 0; - virtual float DrawGetAlphaMultiplier() = 0; - - // web browser - virtual void SetAllowHTMLJavaScript( bool state ) = 0; - - // video mode changing - virtual void OnScreenSizeChanged( int nOldWidth, int nOldHeight ) = 0; - - virtual vgui::HCursor CreateCursorFromFile( char const *curOrAniFile, char const *pPathID = 0 ) = 0; - - // create IVguiMatInfo object ( IMaterial wrapper in VguiMatSurface, NULL in CWin32Surface ) - virtual IVguiMatInfo *DrawGetTextureMatInfoFactory( int id ) = 0; - - virtual void PaintTraverseEx(VPANEL panel, bool paintPopups = false ) = 0; - - virtual float GetZPos() const = 0; - - // From the Xbox - virtual void SetPanelForInput( VPANEL vpanel ) = 0; - virtual void DrawFilledRectFade( int x0, int y0, int x1, int y1, unsigned int alpha0, unsigned int alpha1, bool bHorizontal ) = 0; - virtual void DrawSetTextureRGBAEx(int id, const unsigned char *rgba, int wide, int tall, ImageFormat imageFormat ) = 0; - virtual void DrawSetTextScale(float sx, float sy) = 0; - virtual bool SetBitmapFontGlyphSet(HFont font, const char *windowsFontName, float scalex, float scaley, int flags) = 0; - // adds a bitmap font file - virtual bool AddBitmapFontFile(const char *fontFileName) = 0; - // sets a symbol for the bitmap font - virtual void SetBitmapFontName( const char *pName, const char *pFontFilename ) = 0; - // gets the bitmap font filename - virtual const char *GetBitmapFontName( const char *pName ) = 0; - virtual void ClearTemporaryFontCache( void ) = 0; - - virtual IImage *GetIconImageForFullPath( char const *pFullPath ) = 0; - virtual void DrawUnicodeString( const wchar_t *pwString, FontDrawType_t drawType = FONT_DRAW_DEFAULT ) = 0; - virtual void PrecacheFontCharacters(HFont font, wchar_t *pCharacters) = 0; - // Console-only. Get the string to use for the current video mode for layout files. - virtual const char *GetResolutionKey( void ) const = 0; -}; - -} - -#define VGUI_SURFACE_INTERFACE_VERSION "VGUI_Surface030" - -#endif // ISURFACE_H diff --git a/public/vgui/ISurfaceV30.h b/public/vgui/ISurfaceV30.h deleted file mode 100644 index 90d9e5434..000000000 --- a/public/vgui/ISurfaceV30.h +++ /dev/null @@ -1,375 +0,0 @@ -//========= Copyright 1996-2003, Valve LLC, All rights reserved. ============ -// -// The copyright to the contents herein is the property of Valve, L.L.C. -// The contents may be used and/or copied only with the written permission of -// Valve, L.L.C., or in accordance with the terms and conditions stipulated in -// the agreement/contract under which the contents have been supplied. -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#ifndef ISURFACE_V30_H -#define ISURFACE_V30_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include // CreateHTML, PaintHTML -#include "interface.h" -#include "IVguiMatInfo.h" - -#include "appframework/IAppSystem.h" -#include "bitmap/ImageFormat.h" -#include "Vector2D.h" // must be before the namespace line - -#ifdef CreateFont -#undef CreateFont -#endif - -#ifdef PlaySound -#undef PlaySound -#endif - -class Color; - -namespace vgui -{ - - class Image; - class Point; - - // handles - typedef unsigned long HCursor; - typedef unsigned long HTexture; - typedef unsigned long HFont; -} - - - -namespace SurfaceV30 -{ - - //SRC only defines - - - struct Vertex_t - { - Vertex_t() {} - Vertex_t( const Vector2D &pos, const Vector2D &coord = Vector2D( 0, 0 ) ) - { - m_Position = pos; - m_TexCoord = coord; - } - void Init( const Vector2D &pos, const Vector2D &coord = Vector2D( 0, 0 ) ) - { - m_Position = pos; - m_TexCoord = coord; - } - - Vector2D m_Position; - Vector2D m_TexCoord; - }; - - - enum FontDrawType_t - { - // Use the "additive" value from the scheme file - FONT_DRAW_DEFAULT = 0, - - // Overrides - FONT_DRAW_NONADDITIVE, - FONT_DRAW_ADDITIVE, - - FONT_DRAW_TYPE_COUNT = 2, - }; - - - // Refactor these two - struct CharRenderInfo - { - // In: - FontDrawType_t drawType; - wchar_t ch; - - // Out - bool valid; - - // In/Out (true by default) - bool shouldclip; - // Text pos - int x, y; - // Top left and bottom right - Vertex_t verts[ 2 ]; - int textureId; - int abcA; - int abcB; - int abcC; - int fontTall; - vgui::HFont currentFont; - }; - - - struct IntRect - { - int x0; - int y0; - int x1; - int y1; - }; - - - //----------------------------------------------------------------------------- - // Purpose: Wraps contextless windows system functions - //----------------------------------------------------------------------------- - class ISurface : public IAppSystem - { - public: - // call to Shutdown surface; surface can no longer be used after this is called - virtual void Shutdown() = 0; - - // frame - virtual void RunFrame() = 0; - - // hierarchy root - virtual vgui::VPANEL GetEmbeddedPanel() = 0; - virtual void SetEmbeddedPanel( vgui::VPANEL pPanel ) = 0; - - // drawing context - virtual void PushMakeCurrent(vgui::VPANEL panel, bool useInsets) = 0; - virtual void PopMakeCurrent(vgui::VPANEL panel) = 0; - - // rendering functions - virtual void DrawSetColor(int r, int g, int b, int a) = 0; - virtual void DrawSetColor(Color col) = 0; - - virtual void DrawFilledRect(int x0, int y0, int x1, int y1) = 0; - virtual void DrawFilledRectArray( IntRect *pRects, int numRects ) = 0; - virtual void DrawOutlinedRect(int x0, int y0, int x1, int y1) = 0; - - virtual void DrawLine(int x0, int y0, int x1, int y1) = 0; - virtual void DrawPolyLine(int *px, int *py, int numPoints) = 0; - - virtual void DrawSetTextFont(vgui::HFont font) = 0; - virtual void DrawSetTextColor(int r, int g, int b, int a) = 0; - virtual void DrawSetTextColor(Color col) = 0; - virtual void DrawSetTextPos(int x, int y) = 0; - virtual void DrawGetTextPos(int& x,int& y) = 0; - virtual void DrawPrintText(const wchar_t *text, int textLen, FontDrawType_t drawType = FONT_DRAW_DEFAULT ) = 0; - virtual void DrawUnicodeChar(wchar_t wch, FontDrawType_t drawType = FONT_DRAW_DEFAULT ) = 0; - - virtual void DrawFlushText() = 0; // flushes any buffered text (for rendering optimizations) - virtual vgui::IHTML *CreateHTMLWindow(vgui::IHTMLEvents *events,vgui::VPANEL context)=0; - virtual void PaintHTMLWindow(vgui::IHTML *htmlwin) =0; - virtual void DeleteHTMLWindow(vgui::IHTML *htmlwin)=0; - - virtual int DrawGetTextureId( char const *filename ) = 0; - virtual bool DrawGetTextureFile(int id, char *filename, int maxlen ) = 0; - virtual void DrawSetTextureFile(int id, const char *filename, int hardwareFilter, bool forceReload) = 0; - virtual void DrawSetTextureRGBA(int id, const unsigned char *rgba, int wide, int tall, int hardwareFilter, bool forceReload)=0; - virtual void DrawSetTexture(int id) = 0; - virtual void DrawGetTextureSize(int id, int &wide, int &tall) = 0; - virtual void DrawTexturedRect(int x0, int y0, int x1, int y1) = 0; - virtual bool IsTextureIDValid(int id) = 0; - - virtual int CreateNewTextureID( bool procedural = false ) = 0; -#ifdef _XBOX - virtual void DestroyTextureID( int id ) = 0; - virtual bool IsCachedForRendering( int id, bool bSyncWait ) = 0; - virtual void CopyFrontBufferToBackBuffer() = 0; - virtual void UncacheUnusedMaterials() = 0; -#endif - - virtual void GetScreenSize(int &wide, int &tall) = 0; - virtual void SetAsTopMost(vgui::VPANEL panel, bool state) = 0; - virtual void BringToFront(vgui::VPANEL panel) = 0; - virtual void SetForegroundWindow (vgui::VPANEL panel) = 0; - virtual void SetPanelVisible(vgui::VPANEL panel, bool state) = 0; - virtual void SetMinimized(vgui::VPANEL panel, bool state) = 0; - virtual bool IsMinimized(vgui::VPANEL panel) = 0; - virtual void FlashWindow(vgui::VPANEL panel, bool state) = 0; - virtual void SetTitle(vgui::VPANEL panel, const wchar_t *title) = 0; - virtual void SetAsToolBar(vgui::VPANEL panel, bool state) = 0; // removes the window's task bar entry (for context menu's, etc.) - - // windows stuff - virtual void CreatePopup(vgui::VPANEL panel, bool minimised, bool showTaskbarIcon = true, bool disabled = false, bool mouseInput = true , bool kbInput = true) = 0; - virtual void SwapBuffers(vgui::VPANEL panel) = 0; - virtual void Invalidate(vgui::VPANEL panel) = 0; - virtual void SetCursor(vgui::HCursor cursor) = 0; - virtual bool IsCursorVisible() = 0; - virtual void ApplyChanges() = 0; - virtual bool IsWithin(int x, int y) = 0; - virtual bool HasFocus() = 0; - - // returns true if the surface supports minimize & maximize capabilities - enum SurfaceFeature_e - { - ANTIALIASED_FONTS = 1, - DROPSHADOW_FONTS = 2, - ESCAPE_KEY = 3, - OPENING_NEW_HTML_WINDOWS = 4, - FRAME_MINIMIZE_MAXIMIZE = 5, - OUTLINE_FONTS = 6, - DIRECT_HWND_RENDER = 7, - }; - virtual bool SupportsFeature(SurfaceFeature_e feature) = 0; - - // restricts what gets drawn to one panel and it's children - // currently only works in the game - virtual void RestrictPaintToSinglePanel(vgui::VPANEL panel) = 0; - - // these two functions obselete, use IInput::SetAppModalSurface() instead - virtual void SetModalPanel(vgui::VPANEL ) = 0; - virtual vgui::VPANEL GetModalPanel() = 0; - - virtual void UnlockCursor() = 0; - virtual void LockCursor() = 0; - virtual void SetTranslateExtendedKeys(bool state) = 0; - virtual vgui::VPANEL GetTopmostPopup() = 0; - - // engine-only focus handling (replacing WM_FOCUS windows handling) - virtual void SetTopLevelFocus(vgui::VPANEL panel) = 0; - - // fonts - // creates an empty handle to a vgui font. windows fonts can be add to this via SetFontGlyphSet(). - virtual vgui::HFont CreateFont() = 0; - - // adds to the font - enum EFontFlags - { - FONTFLAG_NONE, - FONTFLAG_ITALIC = 0x001, - FONTFLAG_UNDERLINE = 0x002, - FONTFLAG_STRIKEOUT = 0x004, - FONTFLAG_SYMBOL = 0x008, - FONTFLAG_ANTIALIAS = 0x010, - FONTFLAG_GAUSSIANBLUR = 0x020, - FONTFLAG_ROTARY = 0x040, - FONTFLAG_DROPSHADOW = 0x080, - FONTFLAG_ADDITIVE = 0x100, - FONTFLAG_OUTLINE = 0x200, - FONTFLAG_CUSTOM = 0x400, // custom generated font - never fall back to asian compatibility mode - FONTFLAG_BITMAP = 0x800, // compiled bitmap font - no fallbacks - }; - - virtual bool SetFontGlyphSet(vgui::HFont font, const char *windowsFontName, int tall, int weight, int blur, int scanlines, int flags) = 0; - - // adds a custom font file (only supports true type font files (.ttf) for now) - virtual bool AddCustomFontFile(const char *fontFileName) = 0; - - // returns the details about the font - virtual int GetFontTall(vgui::HFont font) = 0; - virtual int GetFontAscent(vgui::HFont font, wchar_t wch) = 0; - virtual bool IsFontAdditive(vgui::HFont font) = 0; - virtual void GetCharABCwide(vgui::HFont font, int ch, int &a, int &b, int &c) = 0; - virtual int GetCharacterWidth(vgui::HFont font, int ch) = 0; - virtual void GetTextSize(vgui::HFont font, const wchar_t *text, int &wide, int &tall) = 0; - - // notify icons?!? - virtual vgui::VPANEL GetNotifyPanel() = 0; - virtual void SetNotifyIcon(vgui::VPANEL context, vgui::HTexture icon, vgui::VPANEL panelToReceiveMessages, const char *text) = 0; - - // plays a sound - virtual void PlaySound(const char *fileName) = 0; - - //!! these functions should not be accessed directly, but only through other vgui items - //!! need to move these to seperate interface - virtual int GetPopupCount() = 0; - virtual vgui::VPANEL GetPopup(int index) = 0; - virtual bool ShouldPaintChildPanel(vgui::VPANEL childPanel) = 0; - virtual bool RecreateContext(vgui::VPANEL panel) = 0; - virtual void AddPanel(vgui::VPANEL panel) = 0; - virtual void ReleasePanel(vgui::VPANEL panel) = 0; - virtual void MovePopupToFront(vgui::VPANEL panel) = 0; - virtual void MovePopupToBack(vgui::VPANEL panel) = 0; - - virtual void SolveTraverse(vgui::VPANEL panel, bool forceApplySchemeSettings = false) = 0; - virtual void PaintTraverse(vgui::VPANEL panel) = 0; - - virtual void EnableMouseCapture(vgui::VPANEL panel, bool state) = 0; - - // returns the size of the workspace - virtual void GetWorkspaceBounds(int &x, int &y, int &wide, int &tall) = 0; - - // gets the absolute coordinates of the screen (in windows space) - virtual void GetAbsoluteWindowBounds(int &x, int &y, int &wide, int &tall) = 0; - - // gets the base resolution used in proportional mode - virtual void GetProportionalBase( int &width, int &height ) = 0; - - virtual void CalculateMouseVisible() = 0; - virtual bool NeedKBInput() = 0; - - virtual bool HasCursorPosFunctions() = 0; - virtual void SurfaceGetCursorPos(int &x, int &y) = 0; - virtual void SurfaceSetCursorPos(int x, int y) = 0; - - - // SRC only functions!!! - virtual void DrawTexturedLine( const Vertex_t &a, const Vertex_t &b ) = 0; - virtual void DrawOutlinedCircle(int x, int y, int radius, int segments) = 0; - virtual void DrawTexturedPolyLine( const Vertex_t *p,int n ) = 0; // (Note: this connects the first and last points). - virtual void DrawTexturedSubRect( int x0, int y0, int x1, int y1, float texs0, float text0, float texs1, float text1 ) = 0; - virtual void DrawTexturedPolygon(int n, Vertex_t *pVertices) = 0; - virtual const wchar_t *GetTitle(vgui::VPANEL panel) = 0; - virtual bool IsCursorLocked( void ) const = 0; - virtual void SetWorkspaceInsets( int left, int top, int right, int bottom ) = 0; - - // Lower level char drawing code, call DrawGet then pass in info to DrawRender - virtual bool DrawGetUnicodeCharRenderInfo( wchar_t ch, CharRenderInfo& info ) = 0; - virtual void DrawRenderCharFromInfo( const CharRenderInfo& info ) = 0; - - // global alpha setting functions - // affect all subsequent draw calls - shouldn't normally be used directly, only in Panel::PaintTraverse() - virtual void DrawSetAlphaMultiplier( float alpha /* [0..1] */ ) = 0; - virtual float DrawGetAlphaMultiplier() = 0; - - // web browser - virtual void SetAllowHTMLJavaScript( bool state ) = 0; - - // video mode changing - virtual void OnScreenSizeChanged( int nOldWidth, int nOldHeight ) = 0; -#if !defined( _XBOX ) - virtual vgui::HCursor CreateCursorFromFile( char const *curOrAniFile, char const *pPathID = 0 ) = 0; -#endif - // create IVguiMatInfo object ( IMaterial wrapper in VguiMatSurface, NULL in CWin32Surface ) - virtual IVguiMatInfo *DrawGetTextureMatInfoFactory( int id ) = 0; - - virtual void PaintTraverseEx(vgui::VPANEL panel, bool paintPopups = false ) = 0; - - virtual float GetZPos() const = 0; - - // From the Xbox - virtual void SetPanelForInput( vgui::VPANEL vpanel ) = 0; - virtual void DrawFilledRectFade( int x0, int y0, int x1, int y1, unsigned int alpha0, unsigned int alpha1, bool bHorizontal ) = 0; - virtual void DrawSetTextureRGBAEx(int id, const unsigned char *rgba, int wide, int tall, ImageFormat imageFormat ) = 0; - virtual void DrawSetTextScale(float sx, float sy) = 0; - virtual bool SetBitmapFontGlyphSet(vgui::HFont font, const char *windowsFontName, float scalex, float scaley, int flags) = 0; - // adds a bitmap font file - virtual bool AddBitmapFontFile(const char *fontFileName) = 0; - // sets a symbol for the bitmap font - virtual void SetBitmapFontName( const char *pName, const char *pFontFilename ) = 0; - // gets the bitmap font filename - virtual const char *GetBitmapFontName( const char *pName ) = 0; - - virtual vgui::IImage *GetIconImageForFullPath( char const *pFullPath ) = 0; - virtual void DrawUnicodeString( const wchar_t *pwString, FontDrawType_t drawType = FONT_DRAW_DEFAULT ) = 0; - }; - -} // end namespace - -//----------------------------------------------------------------------------- -// FIXME: This works around using scoped interfaces w/ EXPOSE_SINGLE_INTERFACE -//----------------------------------------------------------------------------- -class ISurfaceV30 : public SurfaceV30::ISurface -{ -public: -}; - - -#define VGUI_SURFACE_INTERFACE_VERSION_30 "VGUI_Surface030" - -#endif // ISURFACE_V30_H diff --git a/public/vgui/ISystem.h b/public/vgui/ISystem.h deleted file mode 100644 index b009b4fc4..000000000 --- a/public/vgui/ISystem.h +++ /dev/null @@ -1,134 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ISYSTEM_H -#define ISYSTEM_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/interface.h" -#include -#include - -#ifdef PlaySound -#undef PlaySound -#endif - -class KeyValues; - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Wraps contextless windows system functions -//----------------------------------------------------------------------------- -class ISystem : public IBaseInterface -{ -public: - // call when done with ISystem to clean up any memory allocation - virtual void Shutdown() = 0; - - // called every frame - virtual void RunFrame() = 0; - - // use this with the "open" command to launch web browsers/explorer windows, eg. ShellExecute("open", "www.valvesoftware.com") - virtual void ShellExecute(const char *command, const char *file) = 0; - - // returns the time at the start of the frame, in seconds - virtual double GetFrameTime() = 0; - - // returns the current time, in seconds - virtual double GetCurrentTime() = 0; - - // returns the current time, in milliseconds - virtual long GetTimeMillis() = 0; - - // clipboard access - virtual int GetClipboardTextCount() = 0; - virtual void SetClipboardText(const char *text, int textLen) = 0; - virtual void SetClipboardText(const wchar_t *text, int textLen) = 0; - virtual int GetClipboardText(int offset, char *buf, int bufLen) = 0; - virtual int GetClipboardText(int offset, wchar_t *buf, int bufLen) = 0; - - // windows registry - virtual bool SetRegistryString(const char *key, const char *value) = 0; - virtual bool GetRegistryString(const char *key, char *value, int valueLen) = 0; - virtual bool SetRegistryInteger(const char *key, int value) = 0; - virtual bool GetRegistryInteger(const char *key, int &value) = 0; - - // user config - virtual KeyValues *GetUserConfigFileData(const char *dialogName, int dialogID) = 0; - // sets the name of the config file to save/restore from. Settings are loaded immediately. - virtual void SetUserConfigFile(const char *fileName, const char *pathName) = 0; - // saves all the current settings to the user config file - virtual void SaveUserConfigFile() = 0; - - // sets the watch on global computer use - // returns true if supported - virtual bool SetWatchForComputerUse(bool state) = 0; - // returns the time, in seconds, since the last computer use. - virtual double GetTimeSinceLastUse() = 0; - - // Get a string containing the available drives - // If the function succeeds, the return value is the length, in characters, - // of the strings copied to the buffer, - // not including the terminating null character. - virtual int GetAvailableDrives(char *buf, int bufLen) = 0; - - // exe command line options accessors - // returns whether or not the parameter was on the command line - virtual bool CommandLineParamExists(const char *paramName) = 0; - - // returns the full command line, including the exe name - virtual const char *GetFullCommandLine() = 0; - - // Convert a windows virtual key code to a VGUI key code. - virtual KeyCode KeyCode_VirtualKeyToVGUI( int keyCode ) = 0; - - // returns the current local time and date - // fills in every field that a pointer is given to it for - virtual bool GetCurrentTimeAndDate(int *year, int *month, int *dayOfWeek, int *day, int *hour, int *minute, int *second) = 0; - - // returns the amount of available disk space, in bytes, on the drive - // path can be any path, drive letter is stripped out - virtual double GetFreeDiskSpace(const char *path) = 0; - - // shortcut (.lnk) modification functions - virtual bool CreateShortcut(const char *linkFileName, const char *targetPath, const char *arguments, const char *workingDirectory, const char *iconFile) = 0; - virtual bool GetShortcutTarget(const char *linkFileName, char *targetPath, char *arguments, int destBufferSizes) = 0; - virtual bool ModifyShortcutTarget(const char *linkFileName, const char *targetPath, const char *arguments, const char *workingDirectory) = 0; - - // gets the string following a command line param - //!! move this function up on changing interface version number - virtual bool GetCommandLineParamValue(const char *paramName, char *value, int valueBufferSize) = 0; - - // recursively deletes a registry key and all it's subkeys - //!! move this function next to other registry function on changing interface version number - virtual bool DeleteRegistryKey(const char *keyName) = 0; - - virtual const char *GetDesktopFolderPath() = 0; - - // use this with the "open" command to launch web browsers/explorer windows, eg. ShellExecute("open", "www.valvesoftware.com") - virtual void ShellExecuteEx( const char *command, const char *file, const char *pParams ) = 0; - - // Copy a portion of the application client area to the clipboard - // (x1,y1) specifies the top-left corner of the client rect to copy - // (x2,y2) specifies the bottom-right corner of the client rect to copy - // Requires: x2 > x1 && y2 > y1 - // Dimensions of the copied rectangle are (x2 - x1) x (y2 - y1) - // Pixel at (x1,y1) is copied, pixels at column x2 and row y2 are *not* copied - virtual void SetClipboardImage( void *pWnd, int x1, int y1, int x2, int y2 ) = 0; -}; - -} - -#define VGUI_SYSTEM_INTERFACE_VERSION "VGUI_System010" - - -#endif // ISYSTEM_H diff --git a/public/vgui/IVGui.h b/public/vgui/IVGui.h deleted file mode 100644 index 328208338..000000000 --- a/public/vgui/IVGui.h +++ /dev/null @@ -1,105 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef IVGUI_H -#define IVGUI_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/interface.h" -#include - -#include "appframework/IAppSystem.h" - -class KeyValues; - -namespace vgui -{ - -// safe handle to a panel - can be converted to and from a VPANEL -typedef unsigned long HPanel; -typedef int HContext; - -enum -{ - DEFAULT_VGUI_CONTEXT = ((vgui::HContext)~0) -}; - -// safe handle to a panel - can be converted to and from a VPANEL -typedef unsigned long HPanel; - -//----------------------------------------------------------------------------- -// Purpose: Interface to core vgui components -//----------------------------------------------------------------------------- -class IVGui : public IAppSystem -{ -public: - // activates vgui message pump - virtual void Start() = 0; - - // signals vgui to Stop running - virtual void Stop() = 0; - - // returns true if vgui is current active - virtual bool IsRunning() = 0; - - // runs a single frame of vgui - virtual void RunFrame() = 0; - - // broadcasts "ShutdownRequest" "id" message to all top-level panels in the app - virtual void ShutdownMessage(unsigned int shutdownID) = 0; - - // panel allocation - virtual VPANEL AllocPanel() = 0; - virtual void FreePanel(VPANEL panel) = 0; - - // debugging prints - virtual void DPrintf(const char *format, ...) = 0; - virtual void DPrintf2(const char *format, ...) = 0; - virtual void SpewAllActivePanelNames() = 0; - - // safe-pointer handle methods - virtual HPanel PanelToHandle(VPANEL panel) = 0; - virtual VPANEL HandleToPanel(HPanel index) = 0; - virtual void MarkPanelForDeletion(VPANEL panel) = 0; - - // makes panel receive a 'Tick' message every frame (~50ms, depending on sleep times/framerate) - // panel is automatically removed from tick signal list when it's deleted - virtual void AddTickSignal(VPANEL panel, int intervalMilliseconds = 0 ) = 0; - virtual void RemoveTickSignal(VPANEL panel) = 0; - - // message sending - virtual void PostMessage(VPANEL target, KeyValues *params, VPANEL from, float delaySeconds = 0.0f) = 0; - - // Creates/ destroys vgui contexts, which contains information - // about which controls have mouse + key focus, for example. - virtual HContext CreateContext() = 0; - virtual void DestroyContext( HContext context ) = 0; - - // Associates a particular panel with a vgui context - // Associating NULL is valid; it disconnects the panel from the context - virtual void AssociatePanelWithContext( HContext context, VPANEL pRoot ) = 0; - - // Activates a particular context, use DEFAULT_VGUI_CONTEXT - // to get the one normally used by VGUI - virtual void ActivateContext( HContext context ) = 0; - - // whether to sleep each frame or not, true = sleep - virtual void SetSleep( bool state) = 0; - - // data accessor for above - virtual bool GetShouldVGuiControlSleep() = 0; -}; - -#define VGUI_IVGUI_INTERFACE_VERSION "VGUI_ivgui008" - -}; - - -#endif // IVGUI_H diff --git a/public/vgui/IVguiMatInfo.h b/public/vgui/IVguiMatInfo.h deleted file mode 100644 index 0ce462154..000000000 --- a/public/vgui/IVguiMatInfo.h +++ /dev/null @@ -1,25 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IVGUIMATINFO_H -#define IVGUIMATINFO_H - -#include "IVguiMatInfoVar.h" - -// wrapper for IMaterial -class IVguiMatInfo -{ -public: - // make sure to delete the returned object after use! - virtual IVguiMatInfoVar* FindVarFactory ( const char *varName, bool *found ) = 0; - - virtual int GetNumAnimationFrames ( ) = 0; - - // todo: if you need to add more IMaterial functions add them here -}; - -#endif //IVGUIMATINFO_H diff --git a/public/vgui/IVguiMatInfoVar.h b/public/vgui/IVguiMatInfoVar.h deleted file mode 100644 index 63f38269f..000000000 --- a/public/vgui/IVguiMatInfoVar.h +++ /dev/null @@ -1,22 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IVGUIMATINFOVAR_H -#define IVGUIMATINFOVAR_H - - -// wrapper for IMaterialVar -class IVguiMatInfoVar -{ -public: - virtual int GetIntValue ( void ) const = 0; - virtual void SetIntValue ( int val ) = 0; - - // todo: if you need to add more IMaterialVar functions add them here -}; - -#endif //IVGUIMATINFOVAR_H diff --git a/public/vgui/KeyCode.h b/public/vgui/KeyCode.h deleted file mode 100644 index 61025e7dc..000000000 --- a/public/vgui/KeyCode.h +++ /dev/null @@ -1,24 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: this is a map for virtual key codes -// virtual key codes may exist outside this range for other languages -// NOTE: Button codes also contain mouse codes, but we won't worry about that -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef KEYCODE_H -#define KEYCODE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "inputsystem/ButtonCode.h" - -namespace vgui -{ -typedef ButtonCode_t KeyCode; -} - -#endif // KEYCODE_H diff --git a/public/vgui/MouseCode.h b/public/vgui/MouseCode.h deleted file mode 100644 index 2dfc10dfc..000000000 --- a/public/vgui/MouseCode.h +++ /dev/null @@ -1,23 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: names mouse button inputs -// NOTE: Button codes also contain key codes, but we won't worry about that -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef MOUSECODE_H -#define MOUSECODE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "inputsystem/ButtonCode.h" - -namespace vgui -{ -typedef ButtonCode_t MouseCode; -} - -#endif // MOUSECODE_H diff --git a/public/vgui/Point.h b/public/vgui/Point.h deleted file mode 100644 index ed87fb417..000000000 --- a/public/vgui/Point.h +++ /dev/null @@ -1,61 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef POINT_H -#define POINT_H - -#ifdef _WIN32 -#pragma once -#endif - -#include - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Basic handler for a Points in 2 dimensions -// This class is fully inline -//----------------------------------------------------------------------------- -class Point -{ -public: - // constructors - Point() - { - SetPoint(0, 0); - } - Point(int x,int y) - { - SetPoint(x,y); - } - - void SetPoint(int x1, int y1) - { - x=x1; - y=y1; - } - - void GetPoint(int &x1, int &y1) const - { - x1 = x; - y1 = y; - - } - - bool operator == (Point &rhs) const - { - return (x == rhs.x && y == rhs.y); - } - -private: - int x, y; -}; - -} // namespace vgui - -#endif // POINT_H diff --git a/public/vgui/VGUI.h b/public/vgui/VGUI.h deleted file mode 100644 index 9205b520b..000000000 --- a/public/vgui/VGUI.h +++ /dev/null @@ -1,71 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Basic header for using vgui -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef VGUI_H -#define VGUI_H - -#ifdef _WIN32 -#pragma once -#endif - -#define null 0L - -#ifndef NULL -#ifdef __cplusplus -#define NULL 0 -#else -#define NULL ((void *)0) -#endif -#endif - -#ifdef _MSC_VER -#pragma warning( disable: 4800 ) // disables 'performance warning converting int to bool' -#pragma warning( disable: 4786 ) // disables 'identifier truncated in browser information' warning -#pragma warning( disable: 4355 ) // disables 'this' : used in base member initializer list -#pragma warning( disable: 4097 ) // warning C4097: typedef-name 'BaseClass' used as synonym for class-name -#pragma warning( disable: 4514 ) // warning C4514: 'Color::Color' : unreferenced inline function has been removed -#pragma warning( disable: 4100 ) // warning C4100: 'code' : unreferenced formal parameter -#pragma warning( disable: 4127 ) // warning C4127: conditional expression is constant -#endif - -typedef unsigned char uchar; -typedef unsigned short ushort; -typedef unsigned int uint; -typedef unsigned long ulong; - -#ifndef _WCHAR_T_DEFINED -// DAL - wchar_t is a built in define in gcc 3.2 with a size of 4 bytes -#if !defined( __x86_64__ ) && !defined( __WCHAR_TYPE__ ) -typedef unsigned short wchar_t; -#define _WCHAR_T_DEFINED -#endif -#endif - -// do this in GOLDSRC only!!! -//#define Assert assert - -namespace vgui -{ -// handle to an internal vgui panel -// this is the only handle to a panel that is valid across dll boundaries -typedef unsigned int VPANEL; - -// handles to vgui objects -// NULL values signify an invalid value -typedef unsigned long HScheme; -typedef unsigned long HTexture; -typedef unsigned long HCursor; -typedef unsigned long HPanel; -const HPanel INVALID_PANEL = 0xffffffff; -typedef unsigned long HFont; -const HFont INVALID_FONT = 0; // the value of an invalid font handle -} - -#include "tier1/strtools.h" - - -#endif // VGUI_H diff --git a/public/vgui_controls/AnalogBar.h b/public/vgui_controls/AnalogBar.h deleted file mode 100644 index cd1a956ad..000000000 --- a/public/vgui_controls/AnalogBar.h +++ /dev/null @@ -1,109 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ANALOGBAR_H -#define ANALOGBAR_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Status bar that visually displays discrete analogValue in the form -// of a segmented strip -//----------------------------------------------------------------------------- -class AnalogBar : public Panel -{ - DECLARE_CLASS_SIMPLE( AnalogBar, Panel ); - -public: - AnalogBar(Panel *parent, const char *panelName); - ~AnalogBar(); - - // 'analogValue' is in the range [0.0f, 1.0f] - MESSAGE_FUNC_FLOAT( SetAnalogValue, "SetAnalogValue", analogValue ); - float GetAnalogValue(); - virtual void SetSegmentInfo( int gap, int width ); - - // utility function for calculating a time remaining string - static bool ConstructTimeRemainingString(wchar_t *output, int outputBufferSizeInBytes, float startTime, float currentTime, float currentAnalogValue, float lastAnalogValueUpdateTime, bool addRemainingSuffix); - - void SetBarInset( int pixels ); - int GetBarInset( void ); - - virtual void ApplySettings(KeyValues *inResourceData); - virtual void GetSettings(KeyValues *outResourceData); - virtual const char *GetDescription(); - - // returns the number of segment blocks drawn - int GetDrawnSegmentCount(); - int GetTotalSegmentCount(); - - enum AnalogValueDir_e - { - PROGRESS_EAST, - PROGRESS_WEST, - PROGRESS_NORTH, - PROGRESS_SOUTH - }; - - int GetAnalogValueDirection() const { return m_iAnalogValueDirection; } - void SetAnalogValueDirection( int val ) { m_iAnalogValueDirection = val; } - - void SetHomeValue( float val ) { m_fHomeValue = val; } - - const Color& GetHomeColor( void ) { return m_HomeColor; } - void SetHomeColor( const Color &color ) { m_HomeColor = color; } - -protected: - virtual void Paint(); - void PaintSegment( int &x, int &y, int tall, int wide, Color color, bool bHome ); - virtual void PaintBackground(); - virtual void ApplySchemeSettings(IScheme *pScheme); - MESSAGE_FUNC_PARAMS( OnDialogVariablesChanged, "DialogVariables", dialogVariables ); - /* CUSTOM MESSAGE HANDLING - "SetAnalogValue" - input: "analogValue" - float value of the analogValue to set - */ - -protected: - int m_iAnalogValueDirection; - float _analogValue; - -private: - int _segmentCount; - int _segmentGap; - int _segmentWide; - int m_iBarInset; - char *m_pszDialogVar; - - float m_fHomeValue; - Color m_HomeColor; -}; - -//----------------------------------------------------------------------------- -// Purpose: Non-segmented analogValue bar -//----------------------------------------------------------------------------- -class ContinuousAnalogBar : public AnalogBar -{ - DECLARE_CLASS_SIMPLE( ContinuousAnalogBar, AnalogBar ); - -public: - ContinuousAnalogBar(Panel *parent, const char *panelName); - - virtual void Paint(); -}; - -} // namespace vgui - -#endif // ANALOGBAR_H diff --git a/public/vgui_controls/AnimatingImagePanel.h b/public/vgui_controls/AnimatingImagePanel.h deleted file mode 100644 index ccd862f64..000000000 --- a/public/vgui_controls/AnimatingImagePanel.h +++ /dev/null @@ -1,66 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ANIMATINGIMAGEPANEL_H -#define ANIMATINGIMAGEPANEL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Animating image -//----------------------------------------------------------------------------- -class AnimatingImagePanel : public Panel -{ - DECLARE_CLASS_SIMPLE( AnimatingImagePanel, Panel ); - -public: - AnimatingImagePanel(Panel *parent, const char *name); - - // Add an image to the end of the list of animations - // image - pointer to the image to add to the end of the list - virtual void AddImage(IImage *image); - - // Load a set of animations by name. - // baseName - The name of the animations without their frame number or file extension, (e.g. c1.tga becomes just c.) - // framecount: number of frames in the animation - virtual void LoadAnimation(const char *baseName, int frameCount); - - virtual void StartAnimation(); - virtual void StopAnimation(); - virtual void ResetAnimation(int frame = 0); - -protected: - virtual void OnTick(); - virtual void PerformLayout(); - virtual void PaintBackground(); - - virtual void GetSettings(KeyValues *outResourceData); - virtual void ApplySettings(KeyValues *inResourceData); - virtual const char *GetDescription(); - -private: - int m_iCurrentImage; - int m_iNextFrameTime; - int m_iFrameTimeMillis; - CUtlVector m_Frames; - char *m_pImageName; - bool m_bAnimating; - bool m_bFiltered; - bool m_bScaleImage; -}; - -}; // namespace vgui - -#endif // ANIMATINGIMAGEPANEL_H diff --git a/public/vgui_controls/AnimationController.h b/public/vgui_controls/AnimationController.h deleted file mode 100644 index 785b92100..000000000 --- a/public/vgui_controls/AnimationController.h +++ /dev/null @@ -1,267 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ANIMATIONCONTROLLER_H -#define ANIMATIONCONTROLLER_H -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -#include "tier1/utlsymbol.h" -#include "tier1/utlvector.h" - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Handles controlling panel animation -// It is never visible, but needs to be a panel so that can receive messages -//----------------------------------------------------------------------------- -class AnimationController : public Panel -{ - DECLARE_CLASS_SIMPLE( AnimationController, Panel ); - -public: - AnimationController(Panel *parent); - ~AnimationController(); - - // sets which script file to use - bool SetScriptFile( VPANEL sizingPanel, const char *fileName, bool wipeAll = false ); - - // reloads the currently set script file - void ReloadScriptFile(); - - // runs a frame of animation (time is passed in so slow motion, etc. works) - void UpdateAnimations( float curtime ); - - // plays all animations to completion instantly - void RunAllAnimationsToCompletion(); - - // stops all animations - void CancelAllAnimations(); - - // starts an animation sequence script - bool StartAnimationSequence(const char *sequenceName); - bool StartAnimationSequence(Panel *pWithinParent, const char *sequenceName); - - // gets the length of an animation sequence, in seconds - float GetAnimationSequenceLength(const char *sequenceName); - - // sets that the script file should be reloaded each time a script is ran - // used for development - void SetAutoReloadScript(bool state); - - enum Interpolators_e - { - INTERPOLATOR_LINEAR, - INTERPOLATOR_ACCEL, - INTERPOLATOR_DEACCEL, - INTERPOLATOR_PULSE, - INTERPOLATOR_FLICKER, - INTERPOLATOR_SIMPLESPLINE, // ease in / out - }; - - // runs the specific animation command (doesn't use script file at all) - void RunAnimationCommand(vgui::Panel *panel, const char *variable, float targetValue, float startDelaySeconds, float durationSeconds, Interpolators_e interpolator, float animParameter = 0 ); - void RunAnimationCommand(vgui::Panel *panel, const char *variable, Color targetValue, float startDelaySeconds, float durationSeconds, Interpolators_e interpolator, float animParameter = 0 ); - -private: - bool UpdateScreenSize(); - - bool LoadScriptFile(const char *fileName); - bool ParseScriptFile(char *pMem, int length); - - void UpdatePostedMessages(bool bRunToCompletion); - void UpdateActiveAnimations(bool bRunToCompletion); - - bool m_bAutoReloadScript; - float m_flCurrentTime; - - enum AnimCommandType_e - { - CMD_ANIMATE, - CMD_RUNEVENT, - CMD_STOPEVENT, - CMD_STOPANIMATION, - CMD_STOPPANELANIMATIONS, - CMD_SETFONT, - CMD_SETTEXTURE, - CMD_SETSTRING, - }; - - enum RelativeAlignment - { - a_northwest = 0, - a_north, - a_northeast, - a_west, - a_center, - a_east, - a_southwest, - a_south, - a_southeast, - }; - - struct RelativeAlignmentLookup - { - RelativeAlignment align; - char const *name; - }; - - // a single animatable value - // some var types use 1, 2, 3 or all 4 of the values - struct Value_t - { - float a, b, c, d; - }; - - struct AnimAlign_t - { - // For Position, Xpos, YPos - bool relativePosition; - UtlSymId_t alignPanel; - RelativeAlignment alignment; - }; - - // info for the animate command - struct AnimCmdAnimate_t - { - UtlSymId_t panel; - UtlSymId_t variable; - Value_t target; - int interpolationFunction; - float interpolationParameter; - float startTime; - float duration; - - AnimAlign_t align; - - }; - - // info for the run event command - struct AnimCmdEvent_t - { - UtlSymId_t event; - UtlSymId_t variable; - UtlSymId_t variable2; - float timeDelay; - }; - - // holds a single command from an animation sequence - struct AnimCommand_t - { - AnimCommandType_e commandType; - union - { - AnimCmdAnimate_t animate; - AnimCmdEvent_t runEvent; - } cmdData; - }; - - // holds a full sequence - struct AnimSequence_t - { - UtlSymId_t name; - float duration; - CUtlVector cmdList; - }; - - // holds the list of sequences - CUtlVector m_Sequences; - - // list of active animations - struct ActiveAnimation_t - { - PHandle panel; - UtlSymId_t seqName; // the sequence this belongs to - UtlSymId_t variable; - bool started; - Value_t startValue; - Value_t endValue; - int interpolator; - float interpolatorParam; - float startTime; - float endTime; - - AnimAlign_t align; - }; - CUtlVector m_ActiveAnimations; - - // posted messages - struct PostedMessage_t - { - AnimCommandType_e commandType; - UtlSymId_t seqName; - UtlSymId_t event; - UtlSymId_t variable; - UtlSymId_t variable2; - float startTime; - PHandle parent; - }; - CUtlVector m_PostedMessages; - - struct RanEvent_t - { - UtlSymId_t event; - Panel *pParent; - - bool operator==( const RanEvent_t &other ) const - { - return ( event == other.event && pParent == other.pParent ); - } - }; - - // variable names - UtlSymId_t m_sPosition, m_sSize, m_sFgColor, m_sBgColor; - UtlSymId_t m_sXPos, m_sYPos, m_sWide, m_sTall; - - // file name - CUtlVector m_ScriptFileNames; - - // runs a single line of the script - void ExecAnimationCommand(UtlSymId_t seqName, AnimCommand_t &animCommand, Panel *pWithinParent); - // removes all commands belonging to a script - void RemoveQueuedAnimationCommands(UtlSymId_t seqName, vgui::Panel *panel = NULL); - // removes an existing instance of a command - void RemoveQueuedAnimationByType(vgui::Panel *panel, UtlSymId_t variable, UtlSymId_t sequenceToIgnore); - - // handlers - void StartCmd_Animate(UtlSymId_t seqName, AnimCmdAnimate_t &cmd, Panel *pWithinParent); - void StartCmd_Animate(Panel *panel, UtlSymId_t seqName, AnimCmdAnimate_t &cmd); - void RunCmd_RunEvent(PostedMessage_t &msg); - void RunCmd_StopEvent(PostedMessage_t &msg); - void RunCmd_StopPanelAnimations(PostedMessage_t &msg); - void RunCmd_StopAnimation(PostedMessage_t &msg); - void RunCmd_SetFont(PostedMessage_t &msg); - void RunCmd_SetTexture(PostedMessage_t &msg); - void RunCmd_SetString(PostedMessage_t &msg); - - // value access - Value_t GetValue(ActiveAnimation_t& anim, Panel *panel, UtlSymId_t var); - void SetValue(ActiveAnimation_t& anim, Panel *panel, UtlSymId_t var, Value_t &value); - - // interpolation - Value_t GetInterpolatedValue(int interpolator, float interpolatorParam, float currentTime, float startTime, float endTime, Value_t &startValue, Value_t &endValue); - - void SetupPosition( AnimCmdAnimate_t& cmd, float *output, char const *psz, int screendimension ); - static RelativeAlignment LookupAlignment( char const *token ); - static RelativeAlignmentLookup g_AlignmentLookup[]; - - int GetRelativeOffset( AnimAlign_t& cmd, bool xcoord ); - - VPANEL m_hSizePanel; - int m_nScreenBounds[ 4 ]; -}; - -// singleton accessor for use only by other vgui_controls -extern AnimationController *GetAnimationController(); - -} // namespace vgui - -#endif // ANIMATIONCONTROLLER_H diff --git a/public/vgui_controls/BitmapImagePanel.h b/public/vgui_controls/BitmapImagePanel.h deleted file mode 100644 index ee026d323..000000000 --- a/public/vgui_controls/BitmapImagePanel.h +++ /dev/null @@ -1,56 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef BITMAPIMAGEPANEL_H -#define BITMAPIMAGEPANEL_H -#ifdef _WIN32 -#pragma once -#endif - -#include - -namespace vgui { - -class CBitmapImagePanel : public vgui::Panel -{ -public: - CBitmapImagePanel( vgui::Panel *parent, char const *panelName, char const *filename = NULL ); - - virtual void PaintBackground(); - - virtual void setTexture( char const *filename, bool hardwareFiltered = true ); - - void setImageColor( Color color ) { m_bgColor = color; } - - // Set how the image aligns itself within the panel - virtual void SetContentAlignment(Label::Alignment alignment); - -protected: - virtual void GetSettings(KeyValues *outResourceData); - virtual void ApplySettings(KeyValues *inResourceData); - virtual const char *GetDescription(); - virtual void ApplySchemeSettings( IScheme *pScheme ); - virtual void PaintBorder(); - -private: - typedef vgui::Panel BaseClass; - - virtual void ComputeImagePosition(int &x, int &y, int &w, int &h); - Label::Alignment m_contentAlignment; - - bool m_preserveAspectRatio; - bool m_hardwareFiltered; - - IImage *m_pImage; - Color m_bgColor; - char *m_pszImageName; - char *m_pszColorName; -}; - -}; - -#endif // BITMAPIMAGEPANEL_H diff --git a/public/vgui_controls/BuildGroup.h b/public/vgui_controls/BuildGroup.h deleted file mode 100644 index 243268f74..000000000 --- a/public/vgui_controls/BuildGroup.h +++ /dev/null @@ -1,181 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef VGUI_BUILDGROUP_H -#define VGUI_BUILDGROUP_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/utlvector.h" -#include "tier1/utlsymbol.h" -#include -#include -#include -#include -#include -#include -#include "tier1/utlhandletable.h" - -class KeyValues; - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: a BuildGroup is a list of panels contained in a window (the contextPanel) -// Members of this group are viewable and editable in Build Mode, via the BuildModeDialog wizard -//----------------------------------------------------------------------------- -class BuildGroup -{ - DECLARE_HANDLES( BuildGroup, 20 ); - -public: - BuildGroup(Panel *parentPanel, Panel *contextPanel); - ~BuildGroup(); - - // Toggle build mode on/off - virtual void SetEnabled(bool state); - - // Check if buildgroup is enabled - virtual bool IsEnabled(); - - // Return the currently selected panel - virtual Panel *GetCurrentPanel(); - - // Load the control settings from file - virtual void LoadControlSettings(const char *controlResourceName, const char *pathID = NULL, KeyValues *pPreloadedKeyValues = NULL); - - // Reload the control settings from file - void ReloadControlSettings(); - - // changes which control settings are currently loaded - void ChangeControlSettingsFile(const char *controlResourceName); - - // Save control settings from file, using the same resource - // name as what LoadControlSettings() was called with - virtual bool SaveControlSettings(); - - // Serialize settings from a resource data container - virtual void ApplySettings(KeyValues *resourceData); - - // Serialize settings to a resource data container - virtual void GetSettings(KeyValues *resourceData); - - // Remove all objects in the current control group - virtual void RemoveSettings(); - - // Get a new unique fieldname for a new control - void GetNewFieldName(char *newFieldName, int newFieldNameSize, Panel *newPanel); - - // Check if a control name is already taken - Panel *FieldNameTaken(const char *fieldName); - - // Add a new control (via the BuildModeDialog) - Panel *NewControl( KeyValues *controlKeys, int x=0, int y=0); - Panel *NewControl( const char *name, int x=0, int y=0); - - // Set the panel from which the build group gets all it's object creation information - virtual void SetContextPanel(Panel *contextPanel); - - //Get the panel that build group is pointed at. - virtual Panel *GetContextPanel(); - - // Get the list of panels in the buildgroup - CUtlVector *GetPanelList(); - - // Get the resource file name used - virtual const char *GetResourceName(void) { return m_pResourceName; } - - virtual void PanelAdded(Panel* panel); - - virtual bool MousePressed(MouseCode code,Panel* panel); - virtual bool MouseReleased(MouseCode code,Panel* panel); - - // Get the list of panels that are currently selected - virtual CUtlVector *GetControlGroup(); - - // Toggle ruler display on/off - virtual void ToggleRulerDisplay(); - - // Toggle visibility of ruler number labels - virtual void SetRulerLabelsVisible(bool state); - - // Check if ruler display is activated - virtual bool HasRulersOn(); - - // Draw Rulers on screen - virtual void DrawRulers(); - - // registers that a control settings file may be loaded - // use when the dialog may have multiple states and the editor will need to be able to switch between them - void RegisterControlSettingsFile(const char *controlResourceName, const char *pathID = NULL); - - // iterator for registered files - int GetRegisteredControlSettingsFileCount(); - const char *GetRegisteredControlSettingsFileByIndex(int index); - - // dialog variables - KeyValues *GetDialogVariables(); - -protected: - virtual bool CursorMoved(int x, int y, Panel *panel); - virtual bool MouseDoublePressed(MouseCode code, Panel *panel); - virtual bool KeyCodeTyped(KeyCode code, Panel *panel); - virtual bool KeyCodeReleased(KeyCode code, Panel *panel ); - virtual void ApplySchemeSettings(IScheme *pScheme); - virtual bool KeyTyped( wchar_t unichar, Panel *panel ); - - virtual HCursor GetCursor(Panel *panel); - -private: - void ApplySnap(Panel* panel); - Panel *CreateBuildDialog(); - void ActivateBuildDialog(); - void DeleteAllControlsCreatedByControlSettingsFile(); - - bool _enabled; - int _snapX; - int _snapY; - HCursor _cursor_sizenwse; - HCursor _cursor_sizenesw; - HCursor _cursor_sizewe; - HCursor _cursor_sizens; - HCursor _cursor_sizeall; - bool _dragging; - MouseCode _dragMouseCode; - int _dragStartPanelPos[2]; - int _dragStartCursorPos[2]; - int _dragStartPanelSize[ 2 ]; - Panel * _currentPanel; - CUtlVector _panelDar; - char *m_pResourceName; - char *m_pResourcePathID; - PHandle m_hBuildDialog; - Panel *m_pBuildContext; // the panel from which the build dialog gets all the information it needs - Panel *m_pParentPanel; // panel to create new controls in - CUtlVector _controlGroup; // grouped panels - CUtlVector _groupDeltaX; // x offsets of panels in group from the selected panel - CUtlVector _groupDeltaY; // y offsets of panels in group from the selected panel - Label *_rulerNumber[4]; // 4 numbers to label rulers with - bool _showRulers; // toggles ruler display - CUtlVector m_RegisteredControlSettingsFiles; - - friend class Panel; -}; - - -//----------------------------------------------------------------------------- -// Handle to a build group -//----------------------------------------------------------------------------- -typedef CUtlHandle HBuildGroup; - - -} // namespace vgui - -#endif // VGUI_BUILDGROUP_H diff --git a/public/vgui_controls/BuildModeDialog.h b/public/vgui_controls/BuildModeDialog.h deleted file mode 100644 index 29859a2f9..000000000 --- a/public/vgui_controls/BuildModeDialog.h +++ /dev/null @@ -1,136 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef BUILDMODEDIALOG_H -#define BUILDMODEDIALOG_H - -#ifdef _WIN32 -#pragma once -#endif - -#include - -struct PanelItem_t; - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Dialog for use in build mode editing -//----------------------------------------------------------------------------- -class BuildModeDialog : public Frame -{ - DECLARE_CLASS_SIMPLE( BuildModeDialog, Frame ); - -public: - BuildModeDialog( BuildGroup *buildGroup ); - ~BuildModeDialog(); - - // Set the current control to edit - MESSAGE_FUNC_PTR( SetActiveControl, "SetActiveControl", panelPtr ); - - // Update the current control with the current resource settings. - MESSAGE_FUNC_PTR( UpdateControlData, "UpdateControlData", panel ); - - // Store the current settings of all panels in the build group. - virtual KeyValues *StoreSettings(); - - // Store the current settings of the current panel - MESSAGE_FUNC( StoreUndoSettings, "StoreUndo" ); - - /* CUSTOM MESSAGE HANDLING - "SetActiveControl" - input: "PanelPtr" - panel to set active control to edit to - */ - - MESSAGE_FUNC( OnShowNewControlMenu, "ShowNewControlMenu" ); - -protected: - virtual void PerformLayout(); - virtual void OnClose(); - virtual void OnCommand( const char *command ); - virtual void ApplySchemeSettings( vgui::IScheme *pScheme ); - virtual bool IsBuildGroupEnabled(); - -private: - void CreateControls(); - - void OnKeyCodeTyped(KeyCode code); - MESSAGE_FUNC( ApplyDataToControls, "ApplyDataToControls" ); - MESSAGE_FUNC_PTR( OnTextChanged, "TextChanged", panel ); - MESSAGE_FUNC( OnDeletePanel, "DeletePanel" ); - void ExitBuildMode(); - Panel *OnNewControl(const char *name, int x = 0, int y = 0); - MESSAGE_FUNC( DoUndo, "Undo" ); - MESSAGE_FUNC( DoCopy, "Copy" ); - MESSAGE_FUNC( DoPaste, "Paste" ); - MESSAGE_FUNC( EnableSaveButton, "EnableSaveButton" ); - void RevertToSaved(); - void ShowHelp(); - MESSAGE_FUNC( ShutdownBuildMode, "Close" ); - MESSAGE_FUNC( OnPanelMoved, "PanelMoved" ); - MESSAGE_FUNC( OnTextKillFocus, "TextKillFocus" ); - MESSAGE_FUNC( OnReloadLocalization, "ReloadLocalization" ); - MESSAGE_FUNC_CHARPTR( OnCreateNewControl, "CreateNewControl", text ); - - MESSAGE_FUNC_CHARPTR( OnSetClipboardText, "SetClipboardText", text ); - - MESSAGE_FUNC_INT( OnChangeChild, "OnChangeChild", direction ); - - Panel *m_pCurrentPanel; - BuildGroup *m_pBuildGroup; - Label *m_pStatusLabel; - ComboBox *m_pFileSelectionCombo; - Divider *m_pDivider; - - class PanelList; - PanelList *m_pPanelList; - - Button *m_pSaveButton; - Button *m_pApplyButton; - Button *m_pExitButton; - Button *m_pDeleteButton; - Button *m_pReloadLocalization; - MenuButton *m_pVarsButton; - - bool _autoUpdate; - - ComboBox *m_pAddNewControlCombo; // combo box for adding new controls - KeyValues *_undoSettings; // settings for the Undo command - KeyValues *_copySettings; // settings for the Copy/Paste command - char _copyClassName[255]; - int m_nClick[ 2 ]; - - void RemoveAllControls( void ); - void UpdateEditControl(PanelItem_t &panelItem, const char *datstring); - - enum { - TYPE_STRING, - TYPE_INTEGER, - TYPE_COLOR, - TYPE_ALIGNMENT, - TYPE_AUTORESIZE, - TYPE_CORNER, - TYPE_LOCALIZEDSTRING, - }; - - vgui::DHANDLE< Menu > m_hContextMenu; - - ComboBox *m_pEditableParents; - ComboBox *m_pEditableChildren; - - Button *m_pNextChild; - Button *m_pPrevChild; - - friend class PanelList; -}; - -} // namespace vgui - - -#endif // BUILDMODEDIALOG_H - diff --git a/public/vgui_controls/Button.h b/public/vgui_controls/Button.h deleted file mode 100644 index 469fa1eff..000000000 --- a/public/vgui_controls/Button.h +++ /dev/null @@ -1,220 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef BUTTON_H -#define BUTTON_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include -#include -#include "vgui/MouseCode.h" - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class Button : public Label -{ - DECLARE_CLASS_SIMPLE( Button, Label ); - -public: - // You can optionally pass in the panel to send the click message to and the name of the command to send to that panel. - Button(Panel *parent, const char *panelName, const char *text, Panel *pActionSignalTarget=NULL, const char *pCmd=NULL); - Button(Panel *parent, const char *panelName, const wchar_t *text, Panel *pActionSignalTarget=NULL, const char *pCmd=NULL); - ~Button(); -private: - void Init(); -public: - // Set armed state. - virtual void SetArmed(bool state); - // Check armed state - virtual bool IsArmed( void ); - - // Check depressed state - virtual bool IsDepressed(); - // Set button force depressed state. - virtual void ForceDepressed(bool state); - // Set button depressed state with respect to the force depressed state. - virtual void RecalculateDepressedState( void ); - - // Set button selected state. - virtual void SetSelected(bool state); - // Check selected state - virtual bool IsSelected( void ); - - virtual void SetBlink(bool state); - virtual bool IsBlinking( void ); - - //Set whether or not the button captures all mouse input when depressed. - virtual void SetUseCaptureMouse( bool state ); - // Check if mouse capture is enabled. - virtual bool IsUseCaptureMouseEnabled( void ); - - // Activate a button click. - MESSAGE_FUNC( DoClick, "PressButton" ); - MESSAGE_FUNC( OnHotkey, "Hotkey" ) - { - DoClick(); - } - - // Set button to be mouse clickable or not. - virtual void SetMouseClickEnabled( MouseCode code, bool state ); - // Check if button is mouse clickable - virtual bool IsMouseClickEnabled( MouseCode code ); - // sets the how this button activates - enum ActivationType_t - { - ACTIVATE_ONPRESSEDANDRELEASED, // normal button behaviour - ACTIVATE_ONPRESSED, // menu buttons, toggle buttons - ACTIVATE_ONRELEASED, // menu items - }; - virtual void SetButtonActivationType(ActivationType_t activationType); - - // Message targets that the button has been pressed - virtual void FireActionSignal( void ); - // Perform graphical layout of button - virtual void PerformLayout(); - - virtual bool RequestInfo(KeyValues *data); - - virtual bool CanBeDefaultButton(void); - - // Set this button to be the button that is accessed by default when the user hits ENTER or SPACE - MESSAGE_FUNC_INT( SetAsDefaultButton, "SetAsDefaultButton", state ); - // Set this button to be the button that is currently accessed by default when the user hits ENTER or SPACE - MESSAGE_FUNC_INT( SetAsCurrentDefaultButton, "SetAsCurrentDefaultButton", state ); - - // Respond when key focus is received - virtual void OnSetFocus(); - // Respond when focus is killed - virtual void OnKillFocus(); - - // Set button border attribute enabled, controls display of button. - virtual void SetButtonBorderEnabled( bool state ); - - // Set default button colors. - virtual void SetDefaultColor(Color fgColor, Color bgColor); - // Set armed button colors - virtual void SetArmedColor(Color fgColor, Color bgColor); - // Set depressed button colors - virtual void SetDepressedColor(Color fgColor, Color bgColor); - // Set blink button color - virtual void SetBlinkColor(Color fgColor); - - // Get button foreground color - virtual Color GetButtonFgColor(); - // Get button background color - virtual Color GetButtonBgColor(); - - // Set default button border attributes. - virtual void SetDefaultBorder(IBorder *border); - // Set depressed button border attributes. - virtual void SetDepressedBorder(IBorder *border); - // Set key focused button border attributes. - virtual void SetKeyFocusBorder(IBorder *border); - - // Set the command to send when the button is pressed - // Set the panel to send the command to with AddActionSignalTarget() - virtual void SetCommand( const char *command ); - // Set the message to send when the button is pressed - virtual void SetCommand( KeyValues *message ); - - // sound handling - void SetArmedSound(const char *sound); - void SetDepressedSound(const char *sound); - void SetReleasedSound(const char *sound); - - /* CUSTOM MESSAGE HANDLING - "PressButton" - makes the button act as if it had just been pressed by the user (just like DoClick()) - input: none - */ - - virtual void OnCursorEntered(); - virtual void OnCursorExited(); - virtual void SizeToContents(); - - virtual KeyValues *GetCommand(); - - bool IsDrawingFocusBox(); - void DrawFocusBox( bool bEnable ); - - bool ShouldPaint(){ return _paint; } - void SetShouldPaint( bool paint ){ _paint = paint; } - - virtual void ApplySettings( KeyValues *inResourceData ); - -protected: - virtual void DrawFocusBorder(int tx0, int ty0, int tx1, int ty1); - - // Paint button on screen - virtual void Paint(void); - // Get button border attributes. - virtual IBorder *GetBorder(bool depressed, bool armed, bool selected, bool keyfocus); - - virtual void ApplySchemeSettings(IScheme *pScheme); - MESSAGE_FUNC_INT( OnSetState, "SetState", state ); - - virtual void OnMousePressed(MouseCode code); - virtual void OnMouseDoublePressed(MouseCode code); - virtual void OnMouseReleased(MouseCode code); - virtual void OnKeyCodePressed(KeyCode code); - virtual void OnKeyCodeReleased(KeyCode code); - - // Get control settings for editing - virtual void GetSettings( KeyValues *outResourceData ); - virtual const char *GetDescription( void ); - - KeyValues *GetActionMessage(); - void PlayButtonReleasedSound(); - -private: - enum ButtonFlags_t - { - ARMED = 0x0001, - DEPRESSED = 0x0002, - FORCE_DEPRESSED = 0x0004, - BUTTON_BORDER_ENABLED = 0x0008, - USE_CAPTURE_MOUSE = 0x0010, - BUTTON_KEY_DOWN = 0x0020, - DEFAULT_BUTTON = 0x0040, - SELECTED = 0x0080, - DRAW_FOCUS_BOX = 0x0100, - BLINK = 0x0200, - ALL_FLAGS = 0xFFFF, - }; - - CUtlFlags< unsigned short > _buttonFlags; // see ButtonFlags_t - int _mouseClickMask; - KeyValues *_actionMessage; - ActivationType_t _activationType; - - IBorder *_defaultBorder; - IBorder *_depressedBorder; - IBorder *_keyFocusBorder; - - Color _defaultFgColor, _defaultBgColor; - Color _armedFgColor, _armedBgColor; - Color _depressedFgColor, _depressedBgColor; - Color _keyboardFocusColor; - Color _blinkFgColor; - - bool _paint; - - unsigned short m_sArmedSoundName, m_sDepressedSoundName, m_sReleasedSoundName; - bool m_bSelectionStateSaved; -}; - -} // namespace vgui - -#endif // BUTTON_H diff --git a/public/vgui_controls/CheckButton.h b/public/vgui_controls/CheckButton.h deleted file mode 100644 index 121ead273..000000000 --- a/public/vgui_controls/CheckButton.h +++ /dev/null @@ -1,70 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef CHECKBUTTON_H -#define CHECKBUTTON_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -class CheckImage; - -namespace vgui -{ - -class TextImage; - -//----------------------------------------------------------------------------- -// Purpose: Tick-box button -//----------------------------------------------------------------------------- -class CheckButton : public ToggleButton -{ - DECLARE_CLASS_SIMPLE( CheckButton, ToggleButton ); - -public: - CheckButton(Panel *parent, const char *panelName, const char *text); - ~CheckButton(); - - // Check the button - virtual void SetSelected(bool state ); - - // sets whether or not the state of the check can be changed - // if this is set to false, then no input in the code or by the user can change it's state - virtual void SetCheckButtonCheckable(bool state); - - Color GetDisabledFgColor() { return _disabledFgColor; } - Color GetDisabledBgColor() { return _disabledBgColor; } - -protected: - virtual void ApplySchemeSettings(IScheme *pScheme); - MESSAGE_FUNC_PTR( OnCheckButtonChecked, "CheckButtonChecked", panel ); - virtual Color GetButtonFgColor(); - - virtual IBorder *GetBorder(bool depressed, bool armed, bool selected, bool keyfocus); - - /* MESSAGES SENT - "CheckButtonChecked" - sent when the check button state is changed - "state" - button state: 1 is checked, 0 is unchecked - */ - -private: - enum { CHECK_INSET = 6 }; - CheckImage *_checkBoxImage; - bool m_bCheckButtonCheckable; - Color _selectedFgColor; - Color _disabledFgColor; - Color _disabledBgColor; - friend class CheckImage; -}; - -} // namespace vgui - -#endif // CHECKBUTTON_H diff --git a/public/vgui_controls/CheckButtonList.h b/public/vgui_controls/CheckButtonList.h deleted file mode 100644 index fefcc24c0..000000000 --- a/public/vgui_controls/CheckButtonList.h +++ /dev/null @@ -1,74 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef CHECKBUTTONLIST_H -#define CHECKBUTTONLIST_H -#ifdef _WIN32 -#pragma once -#endif - -#include -#include "UtlVector.h" - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Contains a list of check boxes, displaying scrollbars if necessary -//----------------------------------------------------------------------------- -class CheckButtonList : public EditablePanel -{ - DECLARE_CLASS_SIMPLE( CheckButtonList, EditablePanel ); - -public: - CheckButtonList(Panel *parent, const char *name); - ~CheckButtonList(); - - // adds a check button to the list - int AddItem(const char *itemText, bool startsSelected, KeyValues *userData); - - // clears the list - void RemoveAll(); - - // number of items in list that are checked - int GetCheckedItemCount(); - - // item iteration - bool IsItemIDValid(int itemID); - int GetHighestItemID(); - int GetItemCount(); - - // item info - KeyValues *GetItemData(int itemID); - bool IsItemChecked(int itemID); - void SetItemCheckable(int itemID, bool state); - - /* MESSAGES SENT - "CheckButtonChecked" - sent when one of the check buttons state has changed - - */ - -protected: - virtual void PerformLayout(); - virtual void ApplySchemeSettings(IScheme *pScheme); - virtual void OnMouseWheeled(int delta); - -private: - MESSAGE_FUNC_PARAMS( OnCheckButtonChecked, "CheckButtonChecked", pParams ); - MESSAGE_FUNC( OnScrollBarSliderMoved, "ScrollBarSliderMoved" ); - - struct CheckItem_t - { - vgui::CheckButton *checkButton; - KeyValues *userData; - }; - CUtlVector m_CheckItems; - vgui::ScrollBar *m_pScrollBar; -}; - -} - -#endif // CHECKBUTTONLIST_H diff --git a/public/vgui_controls/CircularProgressBar.h b/public/vgui_controls/CircularProgressBar.h deleted file mode 100644 index d485b3389..000000000 --- a/public/vgui_controls/CircularProgressBar.h +++ /dev/null @@ -1,72 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef CIRCULARPROGRESSBAR_H -#define CIRCULARPROGRESSBAR_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include - -enum progress_textures_t -{ - PROGRESS_TEXTURE_FG, - PROGRESS_TEXTURE_BG, - - NUM_PROGRESS_TEXTURES, -}; - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Progress Bar in the shape of a pie graph -//----------------------------------------------------------------------------- -class CircularProgressBar : public ProgressBar -{ - DECLARE_CLASS_SIMPLE( CircularProgressBar, ProgressBar ); - -public: - CircularProgressBar(Panel *parent, const char *panelName); - ~CircularProgressBar(); - - virtual void ApplySettings(KeyValues *inResourceData); - virtual void ApplySchemeSettings(IScheme *pScheme); - - void SetFgImage(const char *imageName) { SetImage( imageName, PROGRESS_TEXTURE_FG ); } - void SetBgImage(const char *imageName) { SetImage( imageName, PROGRESS_TEXTURE_BG ); } - int GetProgressDirection() const { return m_iProgressDirection; } - void SetProgressDirection( int val ) { m_iProgressDirection = val; } - -protected: - virtual void Paint(); - virtual void PaintBackground(); - - void DrawCircleSegment( Color c, float flEndDegrees, bool clockwise /* = true */ ); - void SetImage(const char *imageName, progress_textures_t iPos); - -private: - enum CircularProgressDir_e - { - PROGRESS_CW, - PROGRESS_CCW - }; - - int m_iProgressDirection; - - int m_nTextureId[NUM_PROGRESS_TEXTURES]; - char *m_pszImageName[NUM_PROGRESS_TEXTURES]; - int m_lenImageName[NUM_PROGRESS_TEXTURES]; -}; - -} // namespace vgui - -#endif // CIRCULARPROGRESSBAR_H diff --git a/public/vgui_controls/ComboBox.h b/public/vgui_controls/ComboBox.h deleted file mode 100644 index 4a0e52b5d..000000000 --- a/public/vgui_controls/ComboBox.h +++ /dev/null @@ -1,143 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef COMBOBOX_H -#define COMBOBOX_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -namespace vgui -{ - -class ComboBoxButton; - -//----------------------------------------------------------------------------- -// Purpose: Text entry with drop down options list -//----------------------------------------------------------------------------- -class ComboBox : public TextEntry -{ - DECLARE_CLASS_SIMPLE( ComboBox, TextEntry ); - -public: - ComboBox(Panel *parent, const char *panelName, int numLines, bool allowEdit); - ~ComboBox(); - - // functions designed to be overriden - virtual void OnShowMenu(Menu *menu) {} - virtual void OnHideMenu(Menu *menu) {} - - // Set the number of items in the drop down menu. - virtual void SetNumberOfEditLines( int numLines ); - - // Add an item to the drop down - virtual int AddItem(const char *itemText, const KeyValues *userData); - virtual int AddItem(const wchar_t *itemText, const KeyValues *userData); - - virtual int GetItemCount(); - int GetItemIDFromRow( int row ); - - // update the item - virtual bool UpdateItem(int itemID, const char *itemText,const KeyValues *userData); - virtual bool UpdateItem(int itemID, const wchar_t *itemText, const KeyValues *userData); - virtual bool IsItemIDValid(int itemID); - - // set the enabled state of an item - virtual void SetItemEnabled(const char *itemText, bool state); - virtual void SetItemEnabled(int itemID, bool state); - - // Removes a single item - void DeleteItem( int itemID ); - - // Remove all items from the drop down menu - void RemoveAll(); - // deprecated, use above - void DeleteAllItems() { RemoveAll(); } - - // Sorts the items in the list - FIXME does nothing - virtual void SortItems(); - - // Set the visiblity of the drop down menu button. - virtual void SetDropdownButtonVisible(bool state); - - // Return true if the combobox current has the dropdown menu open - virtual bool IsDropdownVisible(); - - // Activate the item in the menu list,as if that - // menu item had been selected by the user - MESSAGE_FUNC_INT( ActivateItem, "ActivateItem", itemID ); - void ActivateItemByRow(int row); - - int GetActiveItem(); - KeyValues *GetActiveItemUserData(); - KeyValues *GetItemUserData(int itemID); - void GetItemText( int itemID, wchar_t *text, int bufLenInBytes ); - void GetItemText( int itemID, char *text, int bufLenInBytes ); - - // sets a custom menu to use for the dropdown - virtual void SetMenu( Menu *menu ); - virtual Menu *GetMenu() { return m_pDropDown; } - - // Layout the format of the combo box for drawing on screen - virtual void PerformLayout(); - - /* action signals - "TextChanged" - signals that the text has changed in the combo box - - */ - - virtual void ShowMenu(); - virtual void HideMenu(); - virtual void OnKillFocus(); - MESSAGE_FUNC( OnMenuClose, "MenuClose" ); - virtual void DoClick(); - virtual void OnSizeChanged(int wide, int tall); - - virtual void SetOpenDirection(Menu::MenuDirection_e direction); - - virtual void SetFont( HFont font ); - - virtual void SetUseFallbackFont( bool bState, HFont hFallback ); - -protected: - // overrides - virtual void OnMousePressed(MouseCode code); - virtual void OnMouseDoublePressed(MouseCode code); - MESSAGE_FUNC( OnMenuItemSelected, "MenuItemSelected" ); - virtual void OnCommand( const char *command ); - virtual void ApplySchemeSettings(IScheme *pScheme); - virtual void OnCursorEntered(); - virtual void OnCursorExited(); - - // custom message handlers - MESSAGE_FUNC_WCHARPTR( OnSetText, "SetText", text ); - virtual void OnSetFocus(); // called after the panel receives the keyboard focus - virtual void OnKeyCodeTyped(KeyCode code); - virtual void OnKeyTyped(wchar_t unichar); - - void MoveAlongMenuItemList(int direction); - - -private: - void DoMenuLayout(); - - Menu *m_pDropDown; - ComboBoxButton *m_pButton; - - bool m_bAllowEdit; - bool m_bHighlight; - Menu::MenuDirection_e m_iDirection; - int m_iOpenOffsetY; -}; - -} // namespace vgui - -#endif // COMBOBOX_H diff --git a/public/vgui_controls/ControllerMap.h b/public/vgui_controls/ControllerMap.h deleted file mode 100644 index 04287f51e..000000000 --- a/public/vgui_controls/ControllerMap.h +++ /dev/null @@ -1,48 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef CONTROLLERMAP_H -#define CONTROLLERMAP_H -#ifdef _WIN32 -#pragma once -#endif - -#include "Panel.h" -#include "UtlMap.h" -#include "UtlSymbol.h" - -class CControllerMap : public vgui::Panel -{ - DECLARE_CLASS_SIMPLE( CControllerMap, vgui::Panel ) - - virtual void OnKeyCodeTyped( vgui::KeyCode code ); - -public: - CControllerMap( vgui::Panel *parent, const char *name ); - - virtual void ApplySettings( KeyValues *inResourceData ); - - int NumButtons( void ) - { - return m_buttonMap.Count(); - } - - const char *GetBindingText( int idx ); - const char *GetBindingIcon( int idx ); - -private: - - struct button_t - { - CUtlSymbol cmd; - CUtlSymbol text; - CUtlSymbol icon; - }; - CUtlMap< int, button_t > m_buttonMap; -}; - -#endif // CONTROLLERMAP_H diff --git a/public/vgui_controls/Controls.h b/public/vgui_controls/Controls.h deleted file mode 100644 index 7d350cb21..000000000 --- a/public/vgui_controls/Controls.h +++ /dev/null @@ -1,158 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef CONTROLS_H -#define CONTROLS_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include - -#include "tier1/interface.h" -#include "vgui/MouseCode.h" -#include "vgui/KeyCode.h" -#include "tier3/tier3.h" - - -namespace vgui -{ - -// handles the initialization of the vgui interfaces -// interfaces (listed below) are first attempted to be loaded from primaryProvider, then secondaryProvider -// moduleName should be the name of the module that this instance of the vgui_controls has been compiled into -bool VGui_InitInterfacesList( const char *moduleName, CreateInterfaceFn *factoryList, int numFactories ); - -// returns the name of the module as specified above -const char *GetControlsModuleName(); - -class IPanel; -class IInput; -class ISchemeManager; -class ISurface; -class ISystem; -class IVGui; - -//----------------------------------------------------------------------------- -// Backward compat interfaces, use the interfaces grabbed in tier3 -// set of accessor functions to vgui interfaces -// the appropriate header file for each is listed above the item -//----------------------------------------------------------------------------- - -// #include -inline vgui::IInput *input() -{ - return g_pVGuiInput; -} - -// #include -inline vgui::ISchemeManager *scheme() -{ - return g_pVGuiSchemeManager; -} - -// #include -inline vgui::ISurface *surface() -{ - return g_pVGuiSurface; -} - -// #include -inline vgui::ISystem *system() -{ - return g_pVGuiSystem; -} - -// #include -inline vgui::IVGui *ivgui() -{ - return g_pVGui; -} - -// #include -inline vgui::IPanel *ipanel() -{ - return g_pVGuiPanel; -} - -// predeclare all the vgui control class names -class AnalogBar; -class AnimatingImagePanel; -class AnimationController; -class BuildModeDialog; -class Button; -class CheckButton; -class CheckButtonList; -class ComboBox; -class DirectorySelectDialog; -class Divider; -class EditablePanel; -class FileOpenDialog; -class Frame; -class GraphPanel; -class HTML; -class ImagePanel; -class Label; -class ListPanel; -class ListViewPanel; -class Menu; -class MenuBar; -class MenuButton; -class MenuItem; -class MessageBox; -class Panel; -class PanelListPanel; -class ProgressBar; -class ProgressBox; -class PropertyDialog; -class PropertyPage; -class PropertySheet; -class QueryBox; -class RadioButton; -class RichText; -class ScalableImagePanel; -class ScrollBar; -class ScrollBarSlider; -class SectionedListPanel; -class Slider; -class Splitter; -class TextEntry; -class ToggleButton; -class Tooltip; -class TreeView; -class CTreeViewListControl; -class URLLabel; -class WizardPanel; -class WizardSubPanel; - -// vgui controls helper classes -class BuildGroup; -class FocusNavGroup; -class IBorder; -class IImage; -class Image; -class ImageList; -class TextImage; - -} // namespace vgui - -// hotkeys disabled until we work out exactly how we want to do them -#define VGUI_HOTKEYS_ENABLED -// #define VGUI_DRAW_HOTKEYS_ENABLED - -#define USING_BUILD_FACTORY( className ) \ - extern className *g_##className##LinkerHack; \ - className *g_##className##PullInModule = g_##className##LinkerHack; - -#define USING_BUILD_FACTORY_ALIAS( className, factoryName ) \ - extern className *g_##factoryName##LinkerHack; \ - className *g_##factoryName##PullInModule = g_##factoryName##LinkerHack; - -#endif // CONTROLS_H diff --git a/public/vgui_controls/DialogManager.h b/public/vgui_controls/DialogManager.h deleted file mode 100644 index 545dc459f..000000000 --- a/public/vgui_controls/DialogManager.h +++ /dev/null @@ -1,196 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef DIALOGMANAGER_H -#define DIALOGMANAGER_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: utility class, maps a set of ID's to dialogs -// used to manage sets of similar dialogs (object property dialogs, etc.) -//----------------------------------------------------------------------------- -template -class DialogManager -{ -public: - // new dialog factory function - typedef TDialog *(*CreateNewDialogFunc_t)(I dialogID); - - // constructor - DialogManager(CreateNewDialogFunc_t createDialogFunc); - - // finds the dialog by the specified ID - TDialog *FindDialog(I dialogID, bool bCreate); - - // opens the dialog; creating it if specified - TDialog *ActivateDialog(I dialogID, bool bCreate); - - // closes all the dialogs - void CloseAll(); - - // closes and deletes all the dialogs - void CloseAndDeleteAll(); - - // returns number of active dialogs - int Count(); - - // sets parent to use - void SetParent( vgui::VPANEL parent ); - -private: - // checks if an index in the dialog list is valid; if it has been deleted, removes the entry - bool ValidateIndex(int index); - - struct DialogItem_t - { - I id; - DHANDLE dlg; - }; - - CUtlLinkedList m_Dialogs; - CreateNewDialogFunc_t m_CreateFunc; - vgui::VPANEL m_pVGUIParentPanel; -}; - - -// constructor -template -inline DialogManager::DialogManager(CreateNewDialogFunc_t createDialogFunc) -{ - m_CreateFunc = createDialogFunc; - m_pVGUIParentPanel = NULL; -} - -// finds the dialog; creating it if necessary -template -inline TDialog *DialogManager::FindDialog(I dialogID, bool bCreate) -{ - for (int i = 0; i < m_Dialogs.MaxElementIndex(); i++) - { - if (ValidateIndex(i) && m_Dialogs[i].id == dialogID) - { - return m_Dialogs[i].dlg; - } - } - - if (bCreate) - { - int newIndex = m_Dialogs.AddToTail(); - if (m_CreateFunc) - { - m_Dialogs[newIndex].dlg = m_CreateFunc(dialogID); - } - else - { - m_Dialogs[newIndex].dlg = new TDialog(NULL, dialogID); - } - Assert(m_pVGUIParentPanel); - m_Dialogs[newIndex].dlg->SetParent( m_pVGUIParentPanel ); - - m_Dialogs[newIndex].id = dialogID; - return m_Dialogs[newIndex].dlg; - } - - // dlg not found, not created - return NULL; -} - -// opens the dialog; creating it if necessary -template -inline TDialog *DialogManager::ActivateDialog(I dialogID, bool bCreate) -{ - TDialog *dlg = FindDialog(dialogID, bCreate); - if (dlg) - { - dlg->Activate(); - } - return dlg; -} - -// count -template -inline int DialogManager::Count() -{ - // validate all the indexes first - for (int i = 0; i < m_Dialogs.MaxElementIndex(); i++) - { - if (ValidateIndex(i)) - { - } - } - - // return the (remaining) count - return m_Dialogs.Count(); -} - -// closes all the dialogs -template -inline void DialogManager::CloseAll() -{ - for (int i = 0; i < m_Dialogs.MaxElementIndex(); i++) - { - if (ValidateIndex(i)) - { - m_Dialogs[i].dlg->PostMessage(m_Dialogs[i].dlg, new KeyValues("Close")); - } - } -} - -// closes and deletes all the dialogs -template -inline void DialogManager::CloseAndDeleteAll() -{ - CloseAll(); - for (int i = 0; i < m_Dialogs.MaxElementIndex(); i++) - { - if (ValidateIndex(i)) - { - m_Dialogs[i].dlg->MarkForDeletion(); - } - } - m_Dialogs.RemoveAll(); -} - -// checks if a dialog is valid; if it has been deleted, removes the entry -template -inline bool DialogManager::ValidateIndex(int index) -{ - if (m_Dialogs.IsValidIndex(index)) - { - if (m_Dialogs[index].dlg.Get()) - { - return true; - } - else - { - // entry has been deleted; removed - m_Dialogs.Remove(index); - } - } - return false; -} - -template -inline void DialogManager::SetParent( vgui::VPANEL parent ) -{ - m_pVGUIParentPanel = parent; -} - - -} // namespace vgui - -#endif // DIALOGMANAGER_H diff --git a/public/vgui_controls/DirectorySelectDialog.h b/public/vgui_controls/DirectorySelectDialog.h deleted file mode 100644 index b1e2d74ba..000000000 --- a/public/vgui_controls/DirectorySelectDialog.h +++ /dev/null @@ -1,84 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef DIRECTORYSELECTDIALOG_H -#define DIRECTORYSELECTDIALOG_H -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -class DirectoryTreeView; - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Utility dialog, used to let user select a directory (like during install) -//----------------------------------------------------------------------------- -class DirectorySelectDialog : public Frame -{ - DECLARE_CLASS_SIMPLE( DirectorySelectDialog, Frame ); - -public: - DirectorySelectDialog(vgui::Panel *parent, const char *title); - - // sets where it should start searching - void SetStartDirectory(const char *path); - - // sets what name should show up by default in the create directory dialog - void SetDefaultCreateDirectoryName(const char *defaultCreateDirName); - - // opens the dialog - void DoModal(); - - /* action signals - - "DirectorySelected" - "dir" - the directory that was selected - - */ - - // Expand the tree nodes to match a supplied path, optionally selecting the final directory - void ExpandTreeToPath( const char *lpszPath, bool bSelectFinalDirectory = true ); - -protected: - virtual void PerformLayout(); - virtual void ApplySchemeSettings(IScheme *pScheme); - virtual void OnClose(); - - // command buttons - virtual void OnCommand(const char *command); - -private: - MESSAGE_FUNC( OnTextChanged, "TextChanged" ); - MESSAGE_FUNC( OnTreeViewItemSelected, "TreeViewItemSelected" ); - MESSAGE_FUNC_CHARPTR( OnCreateDirectory, "CreateDirectory", dir ); - void BuildDirTree(); - void BuildDriveChoices(); - void ExpandTreeNode(const char *path, int parentNodeIndex); - void GenerateChildrenOfDirectoryNode(int nodeIndex); - void GenerateFullPathForNode(int nodeIndex, char *path, int pathBufferSize); - bool DoesDirectoryHaveSubdirectories(const char *path, const char *dir); - - char m_szCurrentDir[512]; - char m_szDefaultCreateDirName[64]; - char m_szCurrentDrive[16]; - vgui::TreeView *m_pDirTree; - vgui::ComboBox *m_pDriveCombo; - vgui::Button *m_pCancelButton; - vgui::Button *m_pSelectButton; - vgui::Button *m_pCreateButton; - - friend class DirectoryTreeView; -}; - -} // namespace vgui - - -#endif // DIRECTORYSELECTDIALOG_H diff --git a/public/vgui_controls/Divider.h b/public/vgui_controls/Divider.h deleted file mode 100644 index cc32932ea..000000000 --- a/public/vgui_controls/Divider.h +++ /dev/null @@ -1,38 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef DIVIDER_H -#define DIVIDER_H - -#ifdef _WIN32 -#pragma once -#endif - -#include - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Thin line used to divide sections in dialogs -//----------------------------------------------------------------------------- -class Divider : public Panel -{ - DECLARE_CLASS_SIMPLE( Divider, Panel ); - -public: - Divider(Panel *parent, const char *name); - ~Divider(); - - virtual void ApplySchemeSettings(IScheme *pScheme); -}; - - -} // namespace vgui - - -#endif // DIVIDER_H diff --git a/public/vgui_controls/EditablePanel.h b/public/vgui_controls/EditablePanel.h deleted file mode 100644 index 879bb96cf..000000000 --- a/public/vgui_controls/EditablePanel.h +++ /dev/null @@ -1,160 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef EDITABLEPANEL_H -#define EDITABLEPANEL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Panel that supports editing via the build dialog -//----------------------------------------------------------------------------- -class EditablePanel : public Panel -{ - DECLARE_CLASS_SIMPLE( EditablePanel, Panel ); - -public: - EditablePanel(Panel *parent, const char *panelName); - EditablePanel::EditablePanel(Panel *parent, const char *panelName, HScheme hScheme); - - virtual ~EditablePanel(); - - // Load the control settings - should be done after all the children are added - // If you pass in pPreloadedKeyValues, it won't actually load the file. That way, you can cache - // the keyvalues outside of here if you want to prevent file accesses in the middle of the game. - virtual void LoadControlSettings(const char *dialogResourceName, const char *pathID = NULL, KeyValues *pPreloadedKeyValues = NULL); - virtual void ApplySettings(KeyValues *inResourceData); - - // sets the name of this dialog so it can be saved in the user config area - // use dialogID to differentiate multiple instances of the same dialog - virtual void LoadUserConfig(const char *configName, int dialogID = 0); - virtual void SaveUserConfig(); - - // combines both of the above, LoadControlSettings & LoadUserConfig - virtual void LoadControlSettingsAndUserConfig(const char *dialogResourceName, int dialogID = 0); - - // Override to change how build mode is activated - virtual void ActivateBuildMode(); - - // Return the buildgroup that this panel is part of. - virtual BuildGroup *GetBuildGroup(); - - // Virtual factory for control creation - // controlName is a string which is the same as the class name - virtual Panel *CreateControlByName(const char *controlName); - - // Shortcut function to set data in child controls - virtual void SetControlString(const char *controlName, const char *string); - // Shortcut function to set data in child controls - virtual void SetControlInt(const char *controlName, int state); - // Shortcut function to get data in child controls - virtual int GetControlInt(const char *controlName, int defaultState); - // Shortcut function to get data in child controls - // Returns a maximum of 511 characters in the string - virtual const char *GetControlString(const char *controlName, const char *defaultString = ""); - // as above, but copies the result into the specified buffer instead of a static buffer - virtual void GetControlString(const char *controlName, char *buf, int bufSize, const char *defaultString = ""); - // sets the enabled state of a control - virtual void SetControlEnabled(const char *controlName, bool enabled); - virtual void SetControlVisible(const char *controlName, bool visible); - - // localization variables (used in constructing UI strings) - // after the variable is set, causes all the necessary sub-panels to update - virtual void SetDialogVariable(const char *varName, const char *value); - virtual void SetDialogVariable(const char *varName, const wchar_t *value); - virtual void SetDialogVariable(const char *varName, int value); - virtual void SetDialogVariable(const char *varName, float value); - - // Focus handling - // Delegate focus to a sub panel - virtual void RequestFocus(int direction = 0); - virtual bool RequestFocusNext(VPANEL panel); - virtual bool RequestFocusPrev(VPANEL panel); - // Pass the focus down onto the last used panel - virtual void OnSetFocus(); - // Update focus info for navigation - virtual void OnRequestFocus(VPANEL subFocus, VPANEL defaultPanel); - // Get the panel that currently has keyfocus - virtual VPANEL GetCurrentKeyFocus(); - // Get the panel with the specified hotkey - virtual Panel *HasHotkey(wchar_t key); - - virtual void OnKeyCodeTyped( KeyCode code ); - - // Handle information requests - virtual bool RequestInfo(KeyValues *data); - /* INFO HANDLING - "BuildDialog" - input: - "BuildGroupPtr" - pointer to the panel/dialog to edit - returns: - "PanelPtr" - pointer to a new BuildModeDialog() - - "ControlFactory" - input: - "ControlName" - class name of the control to create - returns: - "PanelPtr" - pointer to the newly created panel, or NULL if no such class exists - */ - // registers a file in the list of control settings, so the vgui dialog can choose between them to edit - virtual void RegisterControlSettingsFile(const char *dialogResourceName, const char *pathID = NULL); - - // localization variables - only use this if you need to iterate the variables, use the SetLoc*() to set them - KeyValues *GetDialogVariables(); - -protected: - virtual void PaintBackground(); - - // nav group access - virtual FocusNavGroup &GetFocusNavGroup(); - - // called when default button has been set - MESSAGE_FUNC_HANDLE( OnDefaultButtonSet, "DefaultButtonSet", button ); - // called when the current default button has been set - MESSAGE_FUNC_HANDLE( OnCurrentDefaultButtonSet, "CurrentDefaultButtonSet", button ); - MESSAGE_FUNC( OnFindDefaultButton, "FindDefaultButton" ); - - // overrides - virtual void OnChildAdded(VPANEL child); - virtual void OnSizeChanged(int wide, int tall); - virtual void OnClose(); - - // user configuration settings - // this is used for any control details the user wants saved between sessions - // eg. dialog positions, last directory opened, list column width - virtual void ApplyUserConfigSettings(KeyValues *userConfig); - - // returns user config settings for this control - virtual void GetUserConfigSettings(KeyValues *userConfig); - - // optimization for text rendering, returns true if text should be rendered immediately after Paint() - // disabled for now - // virtual bool ShouldFlushText(); - -private: - void ForceSubPanelsToUpdateWithNewDialogVariables(); - - BuildGroup *_buildGroup; - FocusNavGroup m_NavGroup; - KeyValues *m_pDialogVariables; - - // the wide and tall to which all controls are locked - used for autolayout deltas - char *m_pszConfigName; - int m_iConfigID; -}; - -} // namespace vgui - -#endif // EDITABLEPANEL_H diff --git a/public/vgui_controls/ExpandButton.h b/public/vgui_controls/ExpandButton.h deleted file mode 100644 index 34d627591..000000000 --- a/public/vgui_controls/ExpandButton.h +++ /dev/null @@ -1,61 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: A button with no borders that shows a left-pointing or down-pointing triangle -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef EXPANDBUTTON_H -#define EXPANDBUTTON_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: A button with no borders that shows a left-pointing or down-pointing arrow -//----------------------------------------------------------------------------- -class ExpandButton : public ToggleButton -{ - DECLARE_CLASS_SIMPLE( ExpandButton, ToggleButton ); - -public: - ExpandButton( Panel *parent, const char *panelName ); - ~ExpandButton(); - - // Expand the button (selected == expanded) - virtual void SetSelected( bool bExpand ); - - // sets whether or not the state of the check can be changed - // if this is set to false, then no input in the code or by the user can change it's state - void SetExpandable(bool state); - - virtual void Paint(); - -protected: - virtual void ApplySchemeSettings(IScheme *pScheme); - MESSAGE_FUNC_PTR( OnExpanded, "Expanded", panel ); - - virtual IBorder *GetBorder(bool depressed, bool armed, bool selected, bool keyfocus); - - /* MESSAGES SENT - "Expanded" - sent when the expand button state is changed - "state" - button state: 1 is expanded, 0 is unexpanded - */ - -private: - bool m_bExpandable; - HFont m_hFont; - Color m_Color; -}; - -} // namespace vgui - -#endif // EXPANDBUTTON_H diff --git a/public/vgui_controls/FileOpenDialog.h b/public/vgui_controls/FileOpenDialog.h deleted file mode 100644 index 6f410f480..000000000 --- a/public/vgui_controls/FileOpenDialog.h +++ /dev/null @@ -1,160 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: Declaration of FileOpenDialog class, a generic open/save as file dialog -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef FILEOPENDIALOG_H -#define FILEOPENDIALOG_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "vgui_controls/Frame.h" - -namespace vgui -{ - -class FileCompletionEdit; // local -class InputDialog; - -//----------------------------------------------------------------------------- -// Purpose: generic open/save as file dialog -//----------------------------------------------------------------------------- -enum FileOpenDialogType_t -{ - FOD_SAVE = 0, - FOD_OPEN, - FOD_SELECT_DIRECTORY, -}; - - -class FileOpenDialog : public vgui::Frame -{ - DECLARE_CLASS_SIMPLE( FileOpenDialog, Frame ); - -public: - // NOTE: Backward compat constructor - FileOpenDialog( Panel *parent, const char *title, bool bOpenFile, KeyValues *pContextKeyValues = 0 ); - - // The context keyvalues are added to all messages sent by this dialog if they are specified - FileOpenDialog( Panel *parent, const char *title, FileOpenDialogType_t type, KeyValues *pContextKeyValues = 0 ); - ~FileOpenDialog(); - - // Set the directory the file search starts in - void SetStartDirectory(const char *dir); - - // Sets the start directory context (and resets the start directory in the process) - // NOTE: If you specify a startdir context, then if you've already opened - // a file with that same start dir context before, it will start in the - // same directory it ended up in. - void SetStartDirectoryContext( const char *pContext, const char *pDefaultDir ); - - // Add filters for the drop down combo box - // The filter info, if specified, gets sent back to the app in the FileSelected message - void AddFilter( const char *filter, const char *filterName, bool bActive, const char *pFilterInfo = NULL ); - - // Activate the dialog - // NOTE: The argument is there for backward compat - void DoModal( bool bUnused = false ); - - // Get the directory this is currently in - void GetCurrentDirectory( char *buf, int bufSize ); - - // Get the last selected file name - void GetSelectedFileName( char *buf, int bufSize ); - - /* - messages sent: - "FileSelected" - "fullpath" // specifies the fullpath of the file - "filterinfo" // Returns the filter info associated with the active filter - "FileSelectionCancelled" - */ - -protected: - virtual void OnCommand( const char *command ); - virtual void ApplySchemeSettings(IScheme *pScheme); - virtual void OnClose(); - virtual void OnKeyCodeTyped(KeyCode code); - - // handles the open button being pressed - // checks on what has changed and acts accordingly - MESSAGE_FUNC( OnOpen, "OnOpen" ); - MESSAGE_FUNC( OnSelectFolder, "SelectFolder" ); - MESSAGE_FUNC( OnFolderUp, "OnFolderUp" ); - MESSAGE_FUNC( OnNewFolder, "OnNewFolder" ); - MESSAGE_FUNC( OnOpenInExplorer, "OpenInExplorer" ); - - MESSAGE_FUNC( PopulateFileList, "PopulateFileList" ); - MESSAGE_FUNC( PopulateDriveList, "PopulateDriveList" ); - MESSAGE_FUNC( PopulateFileNameCompletion, "PopulateFileNameCompletion" ); - - // moves the directory structure up - virtual void MoveUpFolder(); - - // validates that the current path is valid - virtual void ValidatePath(); - - // handles an item in the list being selected - MESSAGE_FUNC( OnItemSelected, "ItemSelected" ); - MESSAGE_FUNC( OnListItemSelected, "ListItemSelected" ) - { - OnItemSelected(); - } - - // changes directories in response to selecting drives from the combo box - MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", kv ); - - MESSAGE_FUNC( OnInputCanceled, "InputCanceled" ); - MESSAGE_FUNC_PARAMS( OnInputCompleted, "InputCompleted", data ); - -private: - // Necessary because we have 2 constructors - void Init( const char *title, KeyValues *pContextKeyValues ); - - // Does the specified extension match something in the filter list? - bool ExtensionMatchesFilter( const char *pExt ); - - // Choose the first non *.* filter in the filter list - void ChooseExtension( char *pExt, int nBufLen ); - - // Saves the file to the start dir context - void SaveFileToStartDirContext( const char *pFullPath ); - - // Posts a file selected message - void PostFileSelectedMessage( const char *pFileName ); - - // Creates a new folder - void NewFolder( char const *folderName ); - - vgui::ComboBox *m_pFullPathEdit; - vgui::ListPanel *m_pFileList; - - FileCompletionEdit *m_pFileNameEdit; - - vgui::ComboBox *m_pFileTypeCombo; - vgui::Button *m_pOpenButton; - vgui::Button *m_pCancelButton; - vgui::Button *m_pFolderUpButton; - vgui::Button *m_pNewFolderButton; - vgui::Button *m_pOpenInExplorerButton; - vgui::ImagePanel *m_pFolderIcon; - vgui::Label *m_pFileTypeLabel; - - KeyValues *m_pContextKeyValues; - - char m_szLastPath[1024]; - unsigned short m_nStartDirContext; - FileOpenDialogType_t m_DialogType; - bool m_bFileSelected : 1; - - VPANEL m_SaveModal; - vgui::DHANDLE< vgui::InputDialog > m_hInputDialog; -}; - -} // namespace vgui - -#endif // FILEOPENDIALOG_H diff --git a/public/vgui_controls/FileOpenStateMachine.h b/public/vgui_controls/FileOpenStateMachine.h deleted file mode 100644 index f5b917fb2..000000000 --- a/public/vgui_controls/FileOpenStateMachine.h +++ /dev/null @@ -1,172 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// This is a helper class designed to help with the chains of modal dialogs -// encountered when trying to open or save a particular file -// -//============================================================================= - -#ifndef FILEOPENSTATEMACHINE_H -#define FILEOPENSTATEMACHINE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "vgui_controls/panel.h" -#include "tier1/utlstring.h" - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- - - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Interface for things using the file open state machine -//----------------------------------------------------------------------------- -abstract_class IFileOpenStateMachineClient -{ -public: - // Called by to allow clients to set up the save dialog - virtual void SetupFileOpenDialog( vgui::FileOpenDialog *pDialog, bool bOpenFile, const char *pFileFormat, KeyValues *pContextKeyValues ) = 0; - - // Called by to allow clients to actually read the file in - virtual bool OnReadFileFromDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues ) = 0; - - // Called by to allow clients to actually write the file out - virtual bool OnWriteFileToDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues ) = 0; -}; - - -//----------------------------------------------------------------------------- -// This is a helper class designed to help with chains of modal dialogs -//----------------------------------------------------------------------------- -enum FileOpenStateMachineFlags_t -{ - FOSM_SHOW_PERFORCE_DIALOGS = 0x1, - FOSM_SHOW_SAVE_QUERY = 0x2, -}; - -class FileOpenStateMachine : public Panel -{ - DECLARE_CLASS_SIMPLE( FileOpenStateMachine, Panel ); - -public: - enum CompletionState_t - { - IN_PROGRESS = 0, // Still not finished, not successful or error - SUCCESSFUL, // Operation finished successfully - FILE_SAVE_CANCELLED, // The user chose 'cancel' in the dialog asking if he wanted to save - FILE_SAVE_NAME_NOT_SPECIFIED, // User hit cancel in the SaveAs dialog - FILE_NOT_OVERWRITTEN, // Operation aborted; existed file and user chose to not write over it - FILE_NOT_CHECKED_OUT, // Operation aborted; file wasn't checked out so couldn't be written over - ERROR_WRITING_FILE, // Error occurred writing the file out - ERROR_MAKING_FILE_WRITEABLE, // Error occurred when making the file writeable - FILE_NOT_MADE_WRITEABLE, // User chose to not make the file be writeable - FILE_OPEN_NAME_NOT_SPECIFIED, // User hit cancel in the Open dialog - ERROR_READING_FILE, // Error occurred reading the file in - }; - - FileOpenStateMachine( vgui::Panel *pParent, IFileOpenStateMachineClient *pClient ); - virtual ~FileOpenStateMachine(); - - // Opens a file, saves an existing one if necessary - void OpenFile( const char *pOpenFileType, KeyValues *pContextKeyValues, const char *pSaveFileName = NULL, const char *pSaveFileType = NULL, int nFlags = 0 ); - - // Version of OpenFile that skips browsing for a particular file to open - void OpenFile( const char *pOpenFileName, const char *pOpenFileType, KeyValues *pContextKeyValues, const char *pSaveFileName = NULL, const char *pSaveFileType = NULL, int nFlags = 0 ); - - // Used to save a specified file, and deal with all the lovely dialogs - // Pass in NULL to get a dialog to choose a filename to save - void SaveFile( KeyValues *pContextKeyValues, const char *pFileName, const char *pFileType, int nFlags = FOSM_SHOW_PERFORCE_DIALOGS ); - - // Returns the state machine completion state - CompletionState_t GetCompletionState(); - - /* MESSAGES SENT - "FileStateMachineFinished" - Called when we exit the state machine for any reason - "completionState" - See the CompletionState_t enum above - "wroteFile" - Indicates whether a file was written or not - "fullPath" - Indicates the full path of the file read for OpenFile or written for SaveFile - "fileType" - Indicates the file type of the file read for OpenFile or written for SaveFile - Use GetFirstTrueSubKey() to get the context passed into the OpenFile/SaveFile methods - */ - -private: - enum FOSMState_t - { - STATE_NONE = -1, - STATE_SHOWING_SAVE_DIRTY_FILE_DIALOG = 0, - STATE_SHOWING_SAVE_DIALOG, - STATE_SHOWING_OVERWRITE_DIALOG, - STATE_SHOWING_CHECK_OUT_DIALOG, - STATE_SHOWING_MAKE_FILE_WRITEABLE_DIALOG, - STATE_WRITING_FILE, - STATE_SHOWING_PERFORCE_ADD_DIALOG, - STATE_SHOWING_OPEN_DIALOG, - STATE_READING_FILE, - }; - - MESSAGE_FUNC_PARAMS( OnFileSelected, "FileSelected", pKeyValues ); - MESSAGE_FUNC( OnFileSelectionCancelled, "FileSelectionCancelled" ); - MESSAGE_FUNC_PARAMS( OnPerforceQueryCompleted, "PerforceQueryCompleted", pKeyValues ); - MESSAGE_FUNC( OnMakeFileWriteable, "MakeFileWriteable" ); - MESSAGE_FUNC( OnCancelMakeFileWriteable, "CancelMakeFileWriteable" ); - - // These messages are related to the dialog in OverwriteFileDialog - MESSAGE_FUNC( OnOverwriteFile, "OverwriteFile" ); - MESSAGE_FUNC( OnCancelOverwriteFile, "CancelOverwriteFile" ); - - // These messages come from the savedocumentquery dialog - MESSAGE_FUNC( OnSaveFile, "OnSaveFile" ); - MESSAGE_FUNC( OnMarkNotDirty, "OnMarkNotDirty" ); - MESSAGE_FUNC( OnCancelSaveDocument, "OnCancelSaveDocument" ); - - // Cleans up keyvalues - void CleanUpContextKeyValues(); - - // Utility to set the completion state - void SetCompletionState( CompletionState_t state ); - - // Show the save document query dialog - void ShowSaveQuery( ); - - // Shows the overwrite existing file dialog - void OverwriteFileDialog( ); - - // Shows the open file for edit dialog - void CheckOutDialog( ); - - // Shows the make file writeable dialog - void MakeFileWriteableDialog( ); - - // Writes the file out - void WriteFile(); - - // Shows the open file dialog - void OpenFileDialog( ); - - // Reads the file in - void ReadFile(); - - IFileOpenStateMachineClient *m_pClient; - KeyValues *m_pContextKeyValues; - FOSMState_t m_CurrentState; - CompletionState_t m_CompletionState; - CUtlString m_FileName; - CUtlString m_SaveFileType; - CUtlString m_OpenFileType; - CUtlString m_OpenFileName; - bool m_bShowPerforceDialogs : 1; - bool m_bShowSaveQuery : 1; - bool m_bIsOpeningFile : 1; - bool m_bWroteFile : 1; -}; - -} // end namespace vgui - - - -#endif // FILEOPENSTATEMACHINE_H diff --git a/public/vgui_controls/FocusNavGroup.h b/public/vgui_controls/FocusNavGroup.h deleted file mode 100644 index 6fb3ea5e7..000000000 --- a/public/vgui_controls/FocusNavGroup.h +++ /dev/null @@ -1,61 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef FOCUSNAVGROUP_H -#define FOCUSNAVGROUP_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -namespace vgui -{ - -class Panel; - -//----------------------------------------------------------------------------- -// Purpose: Handles navigation through a set of panels, with tab order & hotkeys -//----------------------------------------------------------------------------- -class FocusNavGroup -{ -public: - FocusNavGroup(Panel *panel); - ~FocusNavGroup(); - virtual Panel *GetDefaultPanel(); // returns a pointer to the panel with the default focus - - virtual void SetDefaultButton(Panel *panel); // sets which panel should receive input when ENTER is hit - virtual VPANEL GetDefaultButton(); // panel which receives default input when ENTER is hit, if current focused item cannot accept ENTER - virtual VPANEL GetCurrentDefaultButton(); // panel which receives input when ENTER is hit - virtual Panel *FindPanelByHotkey(wchar_t key); // finds the panel which is activated by the specified key - virtual bool RequestFocusPrev(VPANEL panel = NULL); // if panel is NULL, then the tab increment is based last known panel that had key focus - virtual bool RequestFocusNext(VPANEL panel = NULL); - - virtual Panel *GetCurrentFocus(); - virtual VPANEL SetCurrentFocus(VPANEL panel, VPANEL defaultPanel); // returns the Default panel - - // sets the panel that owns this FocusNavGroup to be the root in the focus traversal heirarchy - // focus change via KEY_TAB will only travel to children of this main panel - virtual void SetFocusTopLevel(bool state); - - virtual void SetCurrentDefaultButton(VPANEL panel, bool sendCurrentDefaultButtonMessage = true); -private: - bool CanButtonBeDefault(VPANEL panel); - - VPanelHandle _defaultButton; - VPanelHandle _currentDefaultButton; - VPanelHandle _currentFocus; - - Panel *_mainPanel; - bool _topLevelFocus; -}; - -} // namespace vgui - -#endif // FOCUSNAVGROUP_H diff --git a/public/vgui_controls/Frame.h b/public/vgui_controls/Frame.h deleted file mode 100644 index 4e46b196f..000000000 --- a/public/vgui_controls/Frame.h +++ /dev/null @@ -1,251 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef VGUI_FRAME_H -#define VGUI_FRAME_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include -#include -#include - -namespace vgui -{ - -class FrameButton; -class FrameSystemButton; - -//----------------------------------------------------------------------------- -// Purpose: Windowed frame -//----------------------------------------------------------------------------- -class Frame : public EditablePanel -{ - DECLARE_CLASS_SIMPLE( Frame, EditablePanel ); - -public: - Frame(Panel *parent, const char *panelName, bool showTaskbarIcon = true); - virtual ~Frame(); - - // Set the text in the title bar. Set surfaceTitle=true if you want this to be the taskbar text as well. - virtual void SetTitle(const char *title, bool surfaceTitle); - virtual void SetTitle(const wchar_t *title, bool surfaceTitle); - - // Bring the frame to the front and requests focus, ensures it's not minimized - virtual void Activate(); - - // activates the dialog; if dialog is not currently visible it starts it minimized and flashing in the taskbar - virtual void ActivateMinimized(); - - // closes the dialog - MESSAGE_FUNC( Close, "Close" ); - MESSAGE_FUNC( CloseModal, "CloseModal" ); - - // sets the dialog to delete self on close - virtual void SetDeleteSelfOnClose( bool state ); - - // Move the dialog to the center of the screen - virtual void MoveToCenterOfScreen(); - - // Set the movability of the panel - virtual void SetMoveable(bool state); - // Check the movability of the panel - virtual bool IsMoveable(); - - // Set the resizability of the panel - virtual void SetSizeable(bool state); - // Check the resizability of the panel - virtual bool IsSizeable(); - // Toggle visibility of the system menu button - virtual void SetMenuButtonVisible(bool state); - void SetMenuButtonResponsive(bool state); - - // Toggle visibility of the minimize button - virtual void SetMinimizeButtonVisible(bool state); - // Toggle visibility of the maximize button - virtual void SetMaximizeButtonVisible(bool state); - // Toggles visibility of the minimize-to-systray icon (defaults to false) - virtual void SetMinimizeToSysTrayButtonVisible(bool state); - - // Toggle visibility of the close button - virtual void SetCloseButtonVisible(bool state); - - // returns true if the dialog is currently minimized - virtual bool IsMinimized(); - // Flash the window system tray button until the frame gets focus - virtual void FlashWindow(); - // Stops any window flashing - virtual void FlashWindowStop(); - // command handling - virtual void OnCommand(const char *command); - - // Get the system menu - virtual Menu *GetSysMenu(); - // Set the system menu - virtual void SetSysMenu(Menu *menu); - - // Set the system menu images - void SetImages( const char *pEnabledImage, const char *pDisabledImage = NULL ); - - // set whether the title bar should be rendered - virtual void SetTitleBarVisible( bool state ); - - // When moving via caption, don't let any part of window go outside parent's bounds - virtual void SetClipToParent( bool state ); - virtual bool GetClipToParent() const; - - // Set to true to make the caption height small - virtual void SetSmallCaption( bool state ); - virtual bool IsSmallCaption() const; - - virtual int GetDraggerSize(); - virtual int GetCornerSize(); - virtual int GetBottomRightSize(); - virtual int GetCaptionHeight(); - - /* CUSTOM MESSAGE HANDLING - "SetTitle" - input: "text" - string to set the title to be - */ - - // Load the control settings - virtual void LoadControlSettings( const char *dialogResourceName, const char *pathID = NULL, KeyValues *pPreloadedKeyValues = NULL ); - - void SetChainKeysToParent( bool state ); - bool CanChainKeysToParent() const; - - // Shows the dialog in a modal fashion - virtual void DoModal(); - - void PlaceUnderCursor( ); - - // Disables the fade-in/out-effect even if configured in the scheme settings - void DisableFadeEffect( void ); - -protected: - // Respond to mouse presses - virtual void OnMousePressed(MouseCode code); - // Respond to Key typing - virtual void OnKeyCodeTyped(KeyCode code); - virtual void OnKeyTyped(wchar_t unichar); - // Respond to Key releases - virtual void OnKeyCodeReleased(KeyCode code); - // Respond to Key focus ticks - virtual void OnKeyFocusTicked(); - virtual void ApplySchemeSettings(IScheme *pScheme); - // Recalculate the position of all items - virtual void PerformLayout(); - // Respond when a close message is recieved. Can be called directly to close a frame. - virtual void OnClose(); - // Respond to a window finishing its closure. i.e. when a fading window has fully finished its fadeout. - virtual void OnFinishedClose(); - // Minimize the window on the taskbar. - MESSAGE_FUNC( OnMinimize, "Minimize" ); - // Called when minimize-to-systray button is pressed (does nothing by default) - virtual void OnMinimizeToSysTray(); - // the frame close button was pressed - MESSAGE_FUNC( OnCloseFrameButtonPressed, "CloseFrameButtonPressed" ); - // Add the child to the focus nav group - virtual void OnChildAdded(VPANEL child); - // settings - virtual void ApplySettings(KeyValues *inResourceData); - // records the settings into the resource data - virtual void GetSettings(KeyValues *outResourceData); - virtual const char *GetDescription( void ); - - // gets the default position and size on the screen to appear the first time (defaults to centered) - virtual bool GetDefaultScreenPosition(int &x, int &y, int &wide, int &tall); - - // painting - virtual void PaintBackground(); - - // per-frame thinking, used for transition effects - virtual void OnThink(); - - // screen size - virtual void OnScreenSizeChanged(int iOldWide, int iOldTall); - - // Get the size of the panel inside the frame edges. - virtual void GetClientArea(int &x, int &y, int &wide, int &tall); - - // user configuration settings - // this is used for any control details the user wants saved between sessions - // eg. dialog positions, last directory opened, list column width - virtual void ApplyUserConfigSettings(KeyValues *userConfig); - - // returns user config settings for this control - virtual void GetUserConfigSettings(KeyValues *userConfig); - - // optimization, return true if this control has any user config settings - virtual bool HasUserConfigSettings(); - -private: - MESSAGE_FUNC_CHARPTR( InternalSetTitle, "SetTitle", text ); - MESSAGE_FUNC( InternalFlashWindow, "FlashWindow" ); - MESSAGE_FUNC_PARAMS( OnDialogVariablesChanged, "DialogVariables", dialogVariables ); - - void SetupResizeCursors(); - void LayoutProportional( FrameButton *bt); - void FinishClose(); - void OnFrameFocusChanged(bool bHasFocus); - - Color _titleBarBgColor; - Color _titleBarDisabledBgColor; - Color _titleBarFgColor; - Color _titleBarDisabledFgColor; - Color m_InFocusBgColor; - Color m_OutOfFocusBgColor; - TextImage *_title; - Panel * _topGrip; - Panel *_bottomGrip; - Panel *_leftGrip; - Panel *_rightGrip; - Panel *_topLeftGrip; - Panel *_topRightGrip; - Panel *_bottomLeftGrip; - Panel *_bottomRightGrip; - Panel *_captionGrip; - FrameButton *_minimizeButton; - FrameButton *_maximizeButton; - FrameButton *_minimizeToSysTrayButton; - FrameButton *_closeButton; - FrameSystemButton *_menuButton; - Frame *_resizeable; - bool _sizeable; - bool _moveable; - bool m_bHasFocus; - bool _flashWindow; - bool _nextFlashState; - bool _drawTitleBar; - bool m_bPreviouslyVisible; - bool m_bFadingOut; - bool m_bDeleteSelfOnClose; - float m_flTransitionEffectTime; - float m_flFocusTransitionEffectTime; - int m_iClientInsetX, m_iClientInsetY; - bool m_iClientInsetXOverridden; - int m_iTitleTextInsetX; - Menu *_sysMenu; - bool m_bClipToParent; - bool m_bSmallCaption; - int m_nGripperWidth; - bool m_bChainKeysToParent; - bool m_bPrimed; - VPANEL m_hPreviousModal; - HFont m_hCustomTitleFont; - - CPanelAnimationVarAliasType( int, m_iTitleTextInsetXOverride, "titletextinsetX", "0", "proportional_int" ); - CPanelAnimationVarAliasType( int, m_iTitleTextInsetYOverride, "titletextinsetY", "0", "proportional_int" ); -}; - -} // namespace vgui - -#endif // VGUI_FRAME_H diff --git a/public/vgui_controls/GraphPanel.h b/public/vgui_controls/GraphPanel.h deleted file mode 100644 index 31d23eae4..000000000 --- a/public/vgui_controls/GraphPanel.h +++ /dev/null @@ -1,81 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef GRAPHPANEL_H -#define GRAPHPANEL_H -#ifdef _WIN32 -#pragma once -#endif - -#include -#include "UtlLinkedList.h" -#include "UtlVector.h" - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Holds and displays a chart -//----------------------------------------------------------------------------- -class GraphPanel : public Panel -{ - DECLARE_CLASS_SIMPLE( GraphPanel, Panel ); - -public: - GraphPanel(Panel *parent, const char *name); - - // domain settings (x-axis settings) - // sets the window of samples to display - void SetDisplayDomainSize(float size); - // sets the range of samples the graph should keep - // should be set to the max you would set the display domain size - void SetMaxDomainSize(float size); - // sets the minimum domain that will be displayed; used to collapse samples - void SetMinDomainSize(float size); - - // range settings (y-axis settings) - void SetUseFixedRange(float lowRange, float highRange); - void SetUseDynamicRange(float *rangeList, int numRanges); - void GetDisplayedRange(float &lowRange, float &highRange); - - // adds an item to the end of the list - // sampleEnd is assumed to be the trailing edge of the sample - // assumes that the samples are fairly evenly spaced (not much more work to do to fix this though) - void AddItem(float sampleEnd, float sampleValue); - -protected: - virtual void Paint(); - virtual void PerformLayout(); - virtual void ApplySchemeSettings(IScheme *pScheme); - -private: - int GetVisibleItemCount(); - - struct Sample_t - { - float sampleEnd; - float value; - }; - CUtlLinkedList m_Samples; - - // the window to show - float m_flDomainSize; - float m_flMaxDomainSize, m_flMinDomainSize; - bool m_bMaxDomainSizeSet; - - // range - float m_flLowRange, m_flHighRange; - bool m_bUseDynamicRange; - CUtlVector m_RangeList; - - // rendering - int m_iGraphBarWidth; - int m_iGraphBarGapWidth; -}; - -} // namespace vgui - -#endif // GRAPHPANEL_H diff --git a/public/vgui_controls/HTML.h b/public/vgui_controls/HTML.h deleted file mode 100644 index 9a9972136..000000000 --- a/public/vgui_controls/HTML.h +++ /dev/null @@ -1,135 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Creates a HTML control -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef HTML_H -#define HTML_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include -#include -#include - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Control to display HTML content -// This control utilises a hidden IE window to render a HTML page for you. -// It can load any valid URL (i.e local files or web pages), you cannot dynamically change the -// content however (internally to the control that is). -//----------------------------------------------------------------------------- -class HTML: public Panel, public IHTMLEvents -{ - DECLARE_CLASS_SIMPLE( HTML, Panel ); - -public: - - HTML(Panel *parent,const char *name, bool allowJavaScript = false); - ~HTML(); - - // start and stop the HTML control repainting itself periodically - void StartAnimate(int time); - void StopAnimate(); - - // IHTML pass through functions - virtual void OpenURL(const char *URL, bool force = false); // force means ignore the offline mod override - virtual bool StopLoading(); - virtual bool Refresh(); - virtual void Clear(); - virtual void AddText(const char *text); - virtual void SetVisible( bool state ); - virtual void OnMove(); - - // configuration - virtual void SetScrollbarsEnabled(bool state); - virtual void SetContextMenuEnabled(bool state); - virtual void NewWindowsOnly( bool state ); - - // events callbacks - // Called when the control wishes to go to a new URL (either through the OpenURL() method or internally triggered). - // Return TRUE to allow it to continue and FALSE to stop it loading the URL. Target is the frame this page will load in - virtual bool OnStartURL(const char *url, const char *target, bool first); - // Called when a page has finished loading an is being render. If you derive from this make SURE to - // call this method also (i.e call Baseclass::OnFinishURL(url) in your derived version). - virtual void OnFinishURL(const char *url); - // Called as a page is loading. Maximum is the total number of "tick" events in the progress count, - // current is the current amount you are into the progress. This can be used to update another - // on screen control to show that the browser is active. - virtual void OnProgressURL(long current, long maximum); - // Called when IE has some status text it wishes to display. You can use this to provide status information - // in another control. - virtual void OnSetStatusText(const char *text); - virtual void OnUpdate(); - virtual void OnLink(); - virtual void OffLink(); - - // url handlers, lets you have web page links fire vgui events - // use to have custom web page links, eg. "steam://open/subscriptionpage" - // everything after the "://" is sent to the watcher in a message "CustomURL", "url", "protocol" - virtual void AddCustomURLHandler(const char *customProtocolName, vgui::Panel *target); - - // overridden to paint our special web browser texture - virtual void PaintBackground(); - - // pass messages to the texture component to tell it about resizes - virtual void OnSizeChanged(int wide,int tall); - // for animation task - virtual void OnTick(); - - // pass mouse clicks through - virtual void OnMousePressed(MouseCode code); - virtual void OnMouseReleased(MouseCode code); - virtual void OnCursorMoved(int x,int y); - virtual void OnMouseDoublePressed(MouseCode code); - virtual void OnKeyTyped(wchar_t unichar); - virtual void OnKeyCodePressed(KeyCode code); - virtual void PerformLayout(); - virtual void OnMouseWheeled(int delta); - -protected: - virtual void ApplySchemeSettings(IScheme *pScheme); - -private: - virtual void BrowserResize(); - virtual void CalcScrollBars(int w,int h); - MESSAGE_FUNC( OnSliderMoved, "ScrollBarSliderMoved" ); - - IHTML *browser; // the interface to the browser itself - - vgui::Label *loading; - IImage *picture; - vgui::ScrollBar *_hbar,*_vbar; - - int m_iMouseX,m_iMouseY; // where the mouse is on the control - long m_iNextFrameTime; // next time (in milliseconds) to repaint - int m_iAnimTime; // the time between repaints (in milliseconds) - int m_iScrollX,m_iScrollY; - int m_iScrollBorderX,m_iScrollBorderY; - bool m_bRegenerateHTMLBitmap; - - bool m_bScrollBarEnabled; - bool m_bContextMenuEnabled; - int m_iScrollbarSize; - bool m_bNewWindowsOnly; - bool m_bSetVisibleOnPerformLayout; - - struct CustomURLHandler_t - { - PHandle hPanel; - char url[32]; - }; - CUtlVector m_CustomURLHandlers; -}; - -} // namespace vgui - -#endif // HTML_H diff --git a/public/vgui_controls/Image.h b/public/vgui_controls/Image.h deleted file mode 100644 index 183a0c555..000000000 --- a/public/vgui_controls/Image.h +++ /dev/null @@ -1,75 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IMAGE_H -#define IMAGE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include - -namespace vgui -{ - -class Panel; - -//----------------------------------------------------------------------------- -// Purpose: Basic image control -//----------------------------------------------------------------------------- -class Image : public IImage -{ -public: - Image(); - virtual ~Image(); - - // Set the position of the image - virtual void SetPos(int x,int y); - // Get the position of the image - virtual void GetPos(int& x,int& y); - // Get the size of the image - virtual void GetSize(int& wide,int& tall); - virtual void GetContentSize(int& wide,int& tall); - // Set the draw color - virtual void SetColor(Color color); - // set the background color - virtual void SetBkColor(Color color) { DrawSetColor(color); } - // Get the draw color - virtual Color GetColor(); - -protected: - virtual void SetSize(int wide, int tall); - virtual void DrawSetColor(Color color); - virtual void DrawSetColor(int r, int g, int b, int a); - virtual void DrawFilledRect(int x0, int y0, int x1, int y1); - virtual void DrawOutlinedRect(int x0, int y0, int x1, int y1); - virtual void DrawLine(int x0,int y0,int x1,int y1); - virtual void DrawPolyLine(int *px, int *py, int numPoints); - virtual void DrawSetTextFont(HFont font); - virtual void DrawSetTextColor(Color color); - virtual void DrawSetTextColor(int r, int g, int b, int a); - virtual void DrawSetTextPos(int x,int y); - virtual void DrawPrintText(const wchar_t *str, int strlen); - virtual void DrawPrintText(int x, int y, const wchar_t *str, int strlen); - virtual void DrawPrintChar(wchar_t ch); - virtual void DrawPrintChar(int x, int y, wchar_t ch); - virtual void DrawSetTexture(int id); - virtual void DrawTexturedRect(int x0, int y0, int x1, int y1); - virtual void Paint() = 0; - -private: - int _pos[2]; - int _size[2]; - Color _color; -}; - -} // namespace vgui - -#endif // IMAGE_H diff --git a/public/vgui_controls/ImageList.h b/public/vgui_controls/ImageList.h deleted file mode 100644 index be4f12f46..000000000 --- a/public/vgui_controls/ImageList.h +++ /dev/null @@ -1,56 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IMAGELIST_H -#define IMAGELIST_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: holds a collection of images -// used by controls so that images can be refered to by indices -//----------------------------------------------------------------------------- -class ImageList -{ -public: - ImageList(bool deleteImagesWhenDone); - ~ImageList(); - - // adds a new image to the list, returning the index it was placed at - int AddImage(vgui::IImage *image); - - // returns the number of images - int GetImageCount(); - - // returns true if an index is valid - bool IsValidIndex(int imageIndex); - - // sets an image at a specified index, growing and adding NULL images if necessary - void SetImageAtIndex(int index, vgui::IImage *image); - - // gets an image, imageIndex is of range [0, GetImageCount) - // image index 0 is always the blank image - vgui::IImage *GetImage(int imageIndex); - -private: - CUtlVector m_Images; - bool m_bDeleteImagesWhenDone; -}; - - -} // namespace vgui - -#endif // IMAGELIST_H diff --git a/public/vgui_controls/ImagePanel.h b/public/vgui_controls/ImagePanel.h deleted file mode 100644 index 8fdaeba4d..000000000 --- a/public/vgui_controls/ImagePanel.h +++ /dev/null @@ -1,73 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef IMAGEPANEL_H -#define IMAGEPANEL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -namespace vgui -{ - -class IImage; - -//----------------------------------------------------------------------------- -// Purpose: Panel that holds a single image -//----------------------------------------------------------------------------- -class ImagePanel : public Panel -{ - DECLARE_CLASS_SIMPLE( ImagePanel, Panel ); -public: - ImagePanel(Panel *parent, const char *name); - ~ImagePanel(); - - virtual void SetImage(IImage *image); - virtual void SetImage(const char *imageName); - virtual IImage *GetImage(); - char *GetImageName(); - - // sets whether or not the image should scale to fit the size of the ImagePanel (defaults to false) - void SetShouldScaleImage( bool state ); - void SetScaleAmount( float scale ); - float GetScaleAmount( void ); - - // set the color to fill with, if no image is specified - void SetFillColor( Color col ); - Color GetFillColor(); - - virtual Color GetDrawColor( void ); - virtual void SetDrawColor( Color drawColor ); - -protected: - virtual void PaintBackground(); - virtual void GetSettings(KeyValues *outResourceData); - virtual void ApplySettings(KeyValues *inResourceData); - virtual const char *GetDescription(); - virtual void OnSizeChanged(int newWide, int newTall); - virtual void ApplySchemeSettings( IScheme *pScheme ); - -private: - IImage *m_pImage; - char *m_pszImageName; - char *m_pszColorName; - bool m_bScaleImage; - bool m_bTileImage; - bool m_bTileHorizontally; - bool m_bTileVertically; - float m_fScaleAmount; - Color m_FillColor; - Color m_DrawColor; -}; - -} // namespace vgui - -#endif // IMAGEPANEL_H diff --git a/public/vgui_controls/InputDialog.h b/public/vgui_controls/InputDialog.h deleted file mode 100644 index 791e432d5..000000000 --- a/public/vgui_controls/InputDialog.h +++ /dev/null @@ -1,106 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef INPUTDIALOG_H -#define INPUTDIALOG_H -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -namespace vgui -{ - -class Label; -class Button; -class TextEntry; - - -//----------------------------------------------------------------------------- -// Purpose: Utility dialog base class - just has context kv and ok/cancel buttons -//----------------------------------------------------------------------------- -class BaseInputDialog : public Frame -{ - DECLARE_CLASS_SIMPLE( BaseInputDialog, Frame ); - -public: - BaseInputDialog( vgui::Panel *parent, const char *title ); - ~BaseInputDialog(); - - void DoModal( KeyValues *pContextKeyValues = NULL ); - -protected: - virtual void PerformLayout(); - virtual void PerformLayout( int x, int y, int w, int h ) {} - - // command buttons - virtual void OnCommand( const char *command ); - - void CleanUpContextKeyValues(); - KeyValues *m_pContextKeyValues; - -private: - vgui::Button *m_pCancelButton; - vgui::Button *m_pOKButton; -}; - -//----------------------------------------------------------------------------- -// Purpose: Utility dialog, used to ask yes/no questions of the user -//----------------------------------------------------------------------------- -class InputMessageBox : public BaseInputDialog -{ - DECLARE_CLASS_SIMPLE( InputMessageBox, BaseInputDialog ); - -public: - InputMessageBox( vgui::Panel *parent, const char *title, char const *prompt ); - ~InputMessageBox(); - -protected: - virtual void PerformLayout( int x, int y, int w, int h ); - -private: - vgui::Label *m_pPrompt; -}; - -//----------------------------------------------------------------------------- -// Purpose: Utility dialog, used to let user type in some text -//----------------------------------------------------------------------------- -class InputDialog : public BaseInputDialog -{ - DECLARE_CLASS_SIMPLE( InputDialog, BaseInputDialog ); - -public: - InputDialog( vgui::Panel *parent, const char *title, char const *prompt, char const *defaultValue = "" ); - ~InputDialog(); - - void SetMultiline( bool state ); - - /* action signals - - "InputCompleted" - "text" - the text entered - - "InputCanceled" - */ - void AllowNumericInputOnly( bool bOnlyNumeric ); - -protected: - virtual void PerformLayout( int x, int y, int w, int h ); - - // command buttons - virtual void OnCommand(const char *command); - -private: - vgui::Label *m_pPrompt; - vgui::TextEntry *m_pInput; -}; - -} // namespace vgui - - -#endif // INPUTDIALOG_H diff --git a/public/vgui_controls/KeyBindingHelpDialog.h b/public/vgui_controls/KeyBindingHelpDialog.h deleted file mode 100644 index 5814daedd..000000000 --- a/public/vgui_controls/KeyBindingHelpDialog.h +++ /dev/null @@ -1,63 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef KEYBINDINGHELPDIALOG_H -#define KEYBINDINGHELPDIALOG_H -#ifdef _WIN32 -#pragma once -#endif - -#include "vgui_controls/Frame.h" -#include "vgui/KeyCode.h" - -namespace vgui -{ - -class ListPanel; -class CKeyBoardEditorDialog; - -//----------------------------------------------------------------------------- -// Purpose: Dialog for use in editing keybindings -//----------------------------------------------------------------------------- -class CKeyBindingHelpDialog : public Frame -{ - DECLARE_CLASS_SIMPLE( CKeyBindingHelpDialog, Frame ); - -public: - CKeyBindingHelpDialog( Panel *parent, Panel *panelToView, KeyBindingContextHandle_t handle, KeyCode code, int modifiers ); - ~CKeyBindingHelpDialog(); - - virtual void OnCommand( char const *cmd ); - virtual void OnKeyCodeTyped(vgui::KeyCode code); - - // The key originally bound to help was pressed - void HelpKeyPressed(); -private: - - virtual void OnTick(); - - bool IsHelpKeyStillBeingHeld(); - - void PopulateList(); - void GetMappingList( Panel *panel, CUtlVector< PanelKeyBindingMap * >& maps ); - - void AnsiText( char const *token, char *out, size_t buflen ); - - vgui::PHandle m_hPanel; - KeyBindingContextHandle_t m_Handle; - KeyCode m_KeyCode; - int m_Modifiers; - - ListPanel *m_pList; - double m_flShowTime; - bool m_bPermanent; - - DHANDLE< CKeyBoardEditorDialog > m_hKeyBindingsEditor; -}; - -} - -#endif // KEYBINDINGHELPDIALOG_H diff --git a/public/vgui_controls/KeyBindingMap.h b/public/vgui_controls/KeyBindingMap.h deleted file mode 100644 index caa304f2a..000000000 --- a/public/vgui_controls/KeyBindingMap.h +++ /dev/null @@ -1,224 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef KEYBINDINGMAP_H -#define KEYBINDINGMAP_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/utlvector.h" - -// more flexible than default pointers to members code required for casting member function pointers -#pragma pointers_to_members( full_generality, virtual_inheritance ) - -namespace vgui -{ - -class Panel; - -enum -{ - MODIFIER_SHIFT = ( 1 << 0 ), - MODIFIER_CONTROL = ( 1 << 1 ), - MODIFIER_ALT = ( 1 << 2 ), -}; - -//----------------------------------------------------------------------------- -// Purpose: An actual keybinding, where bindingname references a bindingmap mentioned below -//----------------------------------------------------------------------------- -struct BoundKey_t -{ - BoundKey_t(); - BoundKey_t( const BoundKey_t& src ); - ~BoundKey_t(); - BoundKey_t& operator =( const BoundKey_t& src ); - - bool isbuiltin; // whether this was by the #DECLARE macros or via code/parsing a config file - char const *bindingname; // what it's bound to - int keycode; // vgui keycode - int modifiers; // which modifiers -}; - -//----------------------------------------------------------------------------- -// Purpose: Single item in a message map -// Contains the information to map a string message name with parameters -// to a function call -//----------------------------------------------------------------------------- -struct KeyBindingMap_t -{ - KeyBindingMap_t(); - KeyBindingMap_t( const KeyBindingMap_t& src ); - ~KeyBindingMap_t(); - - char const *bindingname; // for the script file - ALIGN16 MessageFunc_t func; - char const *helpstring; // e.g., #KeybindingPasteHelp - char const *docstring; // e.g., #KeybindingPasteHelp - bool passive; // dispatch command, but still chain -}; - -#define DECLARE_KEYBINDINGMAP( className ) \ - static void KB_AddToMap \ - ( \ - char const *bindingname, \ - vgui::KeyCode defaultcode, \ - int default_modifiers, \ - vgui::MessageFunc_t function, \ - char const *helpstring, \ - char const *docstring, \ - bool passive \ - ) \ - { \ - vgui::PanelKeyBindingMap *map = vgui::FindOrAddPanelKeyBindingMap( GetPanelClassName() ); \ - \ - vgui::KeyBindingMap_t entry; \ - entry.bindingname = bindingname; \ - \ - entry.func = function; \ - \ - entry.helpstring = helpstring; \ - entry.docstring = docstring; \ - \ - entry.passive = passive; \ - \ - map->entries.AddToTail( entry ); \ - \ - vgui::BoundKey_t kb; \ - kb.isbuiltin = true; \ - kb.bindingname = bindingname; \ - kb.keycode = defaultcode; \ - kb.modifiers = default_modifiers; \ - map->defaultkeys.AddToTail( kb ); \ - map->boundkeys.AddToTail( kb ); \ - } \ - \ - static void KB_ChainToMap( void ) \ - { \ - static bool chained = false; \ - if ( chained ) \ - return; \ - chained = true; \ - vgui::PanelKeyBindingMap *map = vgui::FindOrAddPanelKeyBindingMap( GetPanelClassName() ); \ - map->pfnClassName = &GetPanelClassName; \ - if ( map && GetPanelBaseClassName() && GetPanelBaseClassName()[0] ) \ - { \ - map->baseMap = vgui::FindOrAddPanelKeyBindingMap( GetPanelBaseClassName() ); \ - } \ - } \ - \ - static void KB_AddBoundKey \ - ( \ - char const *bindingname, \ - int keycode, \ - int modifiers \ - ) \ - { \ - vgui::PanelKeyBindingMap *map = vgui::FindOrAddPanelKeyBindingMap( GetPanelClassName() ); \ - vgui::BoundKey_t kb; \ - kb.isbuiltin = true; \ - kb.bindingname = bindingname; \ - kb.keycode = keycode; \ - kb.modifiers = modifiers; \ - map->defaultkeys.AddToTail( kb ); \ - map->boundkeys.AddToTail( kb ); \ - } \ - \ - class className##_RegisterKBMap; \ - friend class className##_RegisterKBMap; \ - class className##_RegisterKBMap \ - { \ - public: \ - className##_RegisterKBMap() \ - { \ - className::KB_ChainToMap(); \ - } \ - }; \ - className##_RegisterKBMap m_RegisterClassKB; \ - \ - virtual vgui::PanelKeyBindingMap *GetKBMap() \ - { \ - static vgui::PanelKeyBindingMap *s_pMap = vgui::FindOrAddPanelKeyBindingMap( GetPanelClassName() ); \ - return s_pMap; \ - } - -#define _KBMapFuncCommonFunc( name, keycode, modifiers, function, help, doc, passive ) \ - class PanelKBMapFunc_##name; \ - friend class PanelKBMapFunc_##name; \ - class PanelKBMapFunc_##name \ - { \ - public: \ - static void InitVar() \ - { \ - static bool bAdded = false; \ - if ( !bAdded ) \ - { \ - bAdded = true; \ - KB_AddToMap( #name, keycode, modifiers, (vgui::MessageFunc_t)&ThisClass::##function, help, doc, passive ); \ - } \ - } \ - PanelKBMapFunc_##name() \ - { \ - PanelKBMapFunc_##name::InitVar(); \ - } \ - }; \ - PanelKBMapFunc_##name m_##name##_register; - -#define _KBBindKeyCommon( name, keycode, modifiers, _classname ) \ - class PanelKBBindFunc_##_classname; \ - friend class PanelKBBindFunc_##_classname; \ - class PanelKBBindFunc_##_classname \ - { \ - public: \ - static void InitVar() \ - { \ - static bool bAdded = false; \ - if ( !bAdded ) \ - { \ - bAdded = true; \ - KB_AddBoundKey( #name, keycode, modifiers ); \ - } \ - } \ - PanelKBBindFunc_##_classname() \ - { \ - PanelKBBindFunc_##_classname::InitVar(); \ - } \ - }; \ - PanelKBBindFunc_##_classname m_##_classname##_bindkey_register; - -#define KEYBINDING_FUNC( name, keycode, modifiers, function, help, doc ) _KBMapFuncCommonFunc( name, keycode, modifiers, function, help, doc, false ); virtual void function() -#define KEYBINDING_FUNC_NODECLARE( name, keycode, modifiers, function, help, doc ) _KBMapFuncCommonFunc( name, keycode, modifiers, function, help, doc, false ); -#define KEYBINDING_FUNC_PASSIVE( name, keycode, modifiers, function, help, doc ) _KBMapFuncCommonFunc( name, keycode, modifiers, function, help, doc, true ); virtual void function() -#define KEYBINDING_FUNC_PASSIVE_NODECLARE( name, keycode, modifiers, function, help, doc ) _KBMapFuncCommonFunc( name, keycode, modifiers, function, help, doc, true ); - -// For definding additional (non-default) keybindings -#define KEYBINDING_ADDBINDING( name, keycode, modifiers ) _KBBindKeyCommon( name, keycode, modifiers, name ); -#define KEYBINDING_ADDBINDING_MULTIPLE( name, keycode, modifiers, _classname ) _KBBindKeyCommon( name, keycode, modifiers, _classname ); - -// mapping, one per class -struct PanelKeyBindingMap -{ - PanelKeyBindingMap() - { - baseMap = NULL; - pfnClassName = NULL; - processed = false; - } - - CUtlVector< KeyBindingMap_t > entries; - bool processed; - PanelKeyBindingMap *baseMap; - CUtlVector< BoundKey_t > defaultkeys; - CUtlVector< BoundKey_t > boundkeys; - char const *(*pfnClassName)( void ); -}; - -PanelKeyBindingMap *FindPanelKeyBindingMap( char const *className ); -PanelKeyBindingMap *FindOrAddPanelKeyBindingMap( char const *className ); - -} // namespace vgui - -#endif // KEYBINDINGMAP_H diff --git a/public/vgui_controls/KeyBoardEditorDialog.h b/public/vgui_controls/KeyBoardEditorDialog.h deleted file mode 100644 index ce61890db..000000000 --- a/public/vgui_controls/KeyBoardEditorDialog.h +++ /dev/null @@ -1,138 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef KEYBOARDEDITORDIALOG_H -#define KEYBOARDEDITORDIALOG_H -#ifdef _WIN32 -#pragma once -#endif - -#include "vgui_controls/Frame.h" -#include "vgui_controls/PropertySheet.h" -#include "vgui_controls/PropertyPage.h" - -class VControlsListPanel; - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Dialog for use in editing keybindings -//----------------------------------------------------------------------------- -class CKeyBoardEditorPage : public EditablePanel -{ - DECLARE_CLASS_SIMPLE( CKeyBoardEditorPage, EditablePanel ); - -public: - CKeyBoardEditorPage( Panel *parent, Panel *panelToEdit, KeyBindingContextHandle_t handle ); - ~CKeyBoardEditorPage(); - - void SetKeybindingsSaveFile( char const *filename, char const *pathID = 0 ); - - virtual void OnKeyCodeTyped(vgui::KeyCode code); - - virtual void ApplySchemeSettings( IScheme *scheme ); - - void OnSaveChanges(); - void OnRevert(); - void OnUseDefaults(); - -protected: - - virtual void OnPageHide(); - - virtual void OnCommand( char const *cmd ); - - void PopulateList(); - - void GetMappingList( Panel *panel, CUtlVector< PanelKeyBindingMap * >& maps ); - int GetMappingCount( Panel *panel ); - - void BindKey( vgui::KeyCode code ); - - // Trap row selection message - MESSAGE_FUNC( ItemSelected, "ItemSelected" ); - MESSAGE_FUNC_INT( OnClearBinding, "ClearBinding", item ); - - void SaveMappings(); - void UpdateCurrentMappings(); - void RestoreMappings(); - void ApplyMappings(); - -protected: - void AnsiText( char const *token, char *out, size_t buflen ); - - Panel *m_pPanel; - KeyBindingContextHandle_t m_Handle; - - VControlsListPanel *m_pList; - - struct SaveMapping_t - { - SaveMapping_t(); - SaveMapping_t( const SaveMapping_t& src ); - - PanelKeyBindingMap *map; - CUtlVector< BoundKey_t > current; - CUtlVector< BoundKey_t > original; - }; - - CUtlVector< SaveMapping_t * > m_Save; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Dialog for use in editing keybindings -//----------------------------------------------------------------------------- -class CKeyBoardEditorSheet : public PropertySheet -{ - DECLARE_CLASS_SIMPLE( CKeyBoardEditorSheet, PropertySheet ); - -public: - CKeyBoardEditorSheet( Panel *parent, Panel *panelToEdit, KeyBindingContextHandle_t handle ); - - void SetKeybindingsSaveFile( char const *filename, char const *pathID = 0 ); - - void OnSaveChanges(); - void OnRevert(); - void OnUseDefaults(); - -protected: - - vgui::PHandle m_hPanel; - KeyBindingContextHandle_t m_Handle; - bool m_bSaveToExternalFile; - CUtlSymbol m_SaveFileName; - CUtlSymbol m_SaveFilePathID; - Color m_clrAlteredItem; -}; - -//----------------------------------------------------------------------------- -// Purpose: Dialog for use in editing keybindings -//----------------------------------------------------------------------------- -class CKeyBoardEditorDialog : public Frame -{ - DECLARE_CLASS_SIMPLE( CKeyBoardEditorDialog, Frame ); - -public: - CKeyBoardEditorDialog( Panel *parent, Panel *panelToEdit, KeyBindingContextHandle_t handle ); - - void SetKeybindingsSaveFile( char const *filename, char const *pathID = 0 ); - - virtual void OnCommand( char const *cmd ); - -private: - CKeyBoardEditorSheet *m_pKBEditor; - - Button *m_pSave; - Button *m_pCancel; - Button *m_pRevert; - Button *m_pUseDefaults; -}; - -} - -#endif // KEYBOARDEDITORDIALOG_H diff --git a/public/vgui_controls/KeyRepeat.h b/public/vgui_controls/KeyRepeat.h deleted file mode 100644 index 3b4f89dbf..000000000 --- a/public/vgui_controls/KeyRepeat.h +++ /dev/null @@ -1,79 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef KEYREPEAT_H -#define KEYREPEAT_H -#ifdef _WIN32 -#pragma once -#endif - -#include - -namespace vgui -{ - -enum KEYREPEAT_ALIASES -{ - KR_ALIAS_UP, - KR_ALIAS_DOWN, - KR_ALIAS_LEFT, - KR_ALIAS_RIGHT, - - FM_NUM_KEYREPEAT_ALIASES, -}; - -class CKeyRepeatHandler -{ -public: - CKeyRepeatHandler() - { - Reset(); - for ( int i = 0; i < FM_NUM_KEYREPEAT_ALIASES; i++ ) - { - m_flRepeatTimes[i] = 0.16; - } - } - - void Reset( void ) { memset( m_bAliasDown, 0, sizeof(bool) * FM_NUM_KEYREPEAT_ALIASES ); m_bHaveKeyDown = false; } - void KeyDown( vgui::KeyCode code ); - void KeyUp( vgui::KeyCode code ); - vgui::KeyCode KeyRepeated( void ); - void SetKeyRepeatTime( vgui::KeyCode code, float flRepeat ); - -private: - int GetIndexForCode( vgui::KeyCode code ) - { - switch ( code ) - { - case KEY_XBUTTON_DOWN: - case KEY_XSTICK1_DOWN: - return KR_ALIAS_DOWN; break; - case KEY_XBUTTON_UP: - case KEY_XSTICK1_UP: - return KR_ALIAS_UP; break; - case KEY_XBUTTON_LEFT: - case KEY_XSTICK1_LEFT: - return KR_ALIAS_LEFT; break; - case KEY_XBUTTON_RIGHT: - case KEY_XSTICK1_RIGHT: - return KR_ALIAS_RIGHT; break; - default: - break; - } - return -1; - } - -private: - bool m_bAliasDown[FM_NUM_KEYREPEAT_ALIASES]; - float m_flRepeatTimes[FM_NUM_KEYREPEAT_ALIASES]; - float m_flNextKeyRepeat; - bool m_bHaveKeyDown; -}; - - -} // namespace vgui - -#endif // KEYREPEAT_H diff --git a/public/vgui_controls/Label.h b/public/vgui_controls/Label.h deleted file mode 100644 index 121d227ef..000000000 --- a/public/vgui_controls/Label.h +++ /dev/null @@ -1,214 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef LABEL_H -#define LABEL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "utlvector.h" -#include "vgui/VGUI.h" -#include "vgui_controls/Panel.h" -#include "vgui_controls/PHandle.h" - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Contains and displays a set of images -// By default starts with one TextImage -//----------------------------------------------------------------------------- -class Label : public Panel -{ - DECLARE_CLASS_SIMPLE( Label, Panel ); - -public: - // Constructors - Label(Panel *parent, const char *panelName, const char *text); - Label(Panel *parent, const char *panelName, const wchar_t *wszText); - ~Label(); - -public: - // Take the string and looks it up in the localization file to convert it to unicode - virtual void SetText(const char *tokenName); - - // Set unicode text directly - virtual void SetText(const wchar_t *unicodeString, bool bClearUnlocalizedSymbol = false ); - - // Get the current text - virtual void GetText(char *textOut, int bufferLen); - virtual void GetText(wchar_t *textOut, int bufLenInBytes); - - // Content alignment - // Get the size of the content within the label - virtual void GetContentSize(int &wide, int &tall); - - // Set how the content aligns itself within the label - // alignment code, used to determine how the images are layed out within the Label - enum Alignment - { - a_northwest = 0, - a_north, - a_northeast, - a_west, - a_center, - a_east, - a_southwest, - a_south, - a_southeast, - }; - - virtual void SetContentAlignment(Alignment alignment); - virtual void SetEnabled(bool state); - // Additional offset at the Start of the text (from whichever sides it is aligned) - virtual void SetTextInset(int xInset, int yInset); - - // Text colors - virtual void SetFgColor(Color color); - virtual Color GetFgColor(); - - // colors to use when the label is disabled - virtual void SetDisabledFgColor1(Color color); - virtual void SetDisabledFgColor2(Color color); - virtual Color GetDisabledFgColor1(); - virtual Color GetDisabledFgColor2(); - - // Set whether the text is displayed bright or dull - enum EColorState - { - CS_NORMAL, - CS_DULL, - CS_BRIGHT, - }; - virtual void SetTextColorState(EColorState state); - - // Font - virtual void SetFont(HFont font); - virtual HFont GetFont(); - - // Hotkey - virtual Panel *HasHotkey(wchar_t key); - virtual void SetHotkey(wchar_t key); - - // Labels can be associated with controls, and alter behaviour based on the associates behaviour - // If the associate is disabled, so are we - // If the associate has focus, we may alter how we draw - // If we get a hotkey press or focus message, we forward the focus to the associate - virtual void SetAssociatedControl(Panel *control); - - // Multiple image handling - // Images are drawn from left to right across the label, ordered by index - // By default there is a TextImage in position 0 (see GetTextImage()/SetTextImageIndex()) - virtual int AddImage(IImage *image, int preOffset); // Return the index the image was placed in - virtual void SetImageAtIndex(int index, IImage *image, int preOffset); - virtual void SetImagePreOffset(int index, int preOffset); // Set the offset in pixels before the image - virtual IImage *GetImageAtIndex(int index); - virtual int GetImageCount(); - virtual void ClearImages(); - virtual void ResetToSimpleTextImage(); - // fixes the layout bounds of the image within the label - virtual void SetImageBounds(int index, int x, int width); - - // Teturns a pointer to the default text image - virtual TextImage *GetTextImage(); - - // Moves where the default text image is within the image array (it starts in position 0) - // Setting it to -1 removes it from the image list - // Returns the index the default text image was previously in - virtual int SetTextImageIndex(int newIndex); - - // Message handling - // outputData - keyName is the name of the attribute requested. - // for Labels "text" is an option that returns the default text image text - // returns true on success in finding the requested value. false on failure. - virtual bool RequestInfo(KeyValues *outputData); - /* INFO HANDLING - "GetText" - returns: - "text" - text contained in the label - */ - - /* CUSTOM MESSAGE HANDLING - "SetText" - input: "text" - label text is set to be this string - */ - - virtual void SizeToContents(); - - // the +8 is padding to the content size - // the code which uses it should really set that itself; - // however a lot of existing code relies on this - enum Padding - { - Content = 8, - }; - - void SetWrap( bool bWrap ); - void SetCenterWrap( bool bWrap ); - -protected: - virtual void PerformLayout(); - virtual wchar_t CalculateHotkey(const char *text); - virtual wchar_t CalculateHotkey(const wchar_t *text); - virtual void ComputeAlignment(int &tx0, int &ty0, int &tx1, int &ty1); - virtual void Paint(); - MESSAGE_FUNC_PARAMS( OnSetText, "SetText", params ); - virtual void DrawDashedLine(int x0, int y0, int x1, int y1, int dashLen, int gapLen); - virtual void OnRequestFocus(VPANEL subFocus, VPANEL defaultPanel); - MESSAGE_FUNC( OnHotkeyPressed, "Hotkey" ); - virtual void OnMousePressed(MouseCode code); - virtual void OnSizeChanged(int wide, int tall); - - // makes sure that the maxIndex will be a valid index - virtual void EnsureImageCapacity(int maxIndex); - - // editing - virtual void ApplySchemeSettings(IScheme *pScheme); - virtual void GetSettings( KeyValues *outResourceData ); - virtual void ApplySettings( KeyValues *inResourceData ); - virtual const char *GetDescription( void ); - - MESSAGE_FUNC_PARAMS( OnDialogVariablesChanged, "DialogVariables", dialogVariables ); - -private: - void Init(); - - Alignment _contentAlignment; - TextImage *_textImage; // this is the textImage, if the full text will not - // fit we put as much as we can and add an elipsis (...) - struct TImageInfo - { - IImage *image; - short offset; - short xpos; - short width; - }; - CUtlVector _imageDar; - - int _textInset[2]; - Color _disabledFgColor1; - Color _disabledFgColor2; - Color _associateColor; - int _textImageIndex; // index in the image array that the default _textimage resides - EColorState _textColorState; - - PHandle _associate; - char *_associateName; - - char *_fontOverrideName; - - wchar_t _hotkey; // the hotkey contained in the text - - bool m_bWrap; - bool m_bCenterWrap; -}; - -} // namespace vgui - -#endif // LABEL_H diff --git a/public/vgui_controls/ListPanel.h b/public/vgui_controls/ListPanel.h deleted file mode 100644 index 8624580df..000000000 --- a/public/vgui_controls/ListPanel.h +++ /dev/null @@ -1,358 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef LISTPANEL_H -#define LISTPANEL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include -#include -#include - -class KeyValues; - -namespace vgui -{ - -class ScrollBar; -class TextImage; -class ImagePanel; -class Label; -class Button; -class IDraggerEvent; -class FastSortListPanelItem; - -//----------------------------------------------------------------------------- -// Purpose: Generic class for ListPanel items -//----------------------------------------------------------------------------- -class ListPanelItem -{ -public: - ListPanelItem() : - kv( 0 ), - userData( 0 ), - m_pDragData( 0 ), - m_bImage( false ), - m_nImageIndex( -1 ), - m_nImageIndexSelected( -1 ), - m_pIcon( 0 ) - { - } - - KeyValues *kv; - unsigned int userData; - KeyValues *m_pDragData; - bool m_bImage; - int m_nImageIndex; - int m_nImageIndexSelected; - IImage *m_pIcon; -}; - -typedef int __cdecl SortFunc( - ListPanel *pPanel, - const ListPanelItem &item1, - const ListPanelItem &item2 ); - -//----------------------------------------------------------------------------- -// Purpose: A spread-sheet type data view, similar to MFC's -//----------------------------------------------------------------------------- -class ListPanel : public Panel -{ - DECLARE_CLASS_SIMPLE( ListPanel, Panel ); -public: - ListPanel(Panel *parent, const char *panelName); - ~ListPanel(); - - // COLUMN HANDLING - // all indices are 0 based, limit of 255 columns - // columns are resizable by default - enum ColumnFlags_e - { - COLUMN_FIXEDSIZE = 0x01, // set to have the column be a fixed size - COLUMN_RESIZEWITHWINDOW = 0x02, // set to have the column grow with the parent dialog growing - COLUMN_IMAGE = 0x04, // set if the column data is not text, but instead the index of the image to display - COLUMN_HIDDEN = 0x08, // column is hidden by default - COLUMN_UNHIDABLE = 0x10, // column is unhidable - }; - - // adds a column header - virtual void AddColumnHeader(int index, const char *columnName, const char *columnText, int startingWidth, int minWidth, int maxWidth, int columnFlags = 0); - virtual void AddColumnHeader(int index, const char *columnName, const char *columnText, int width, int columnFlags = 0); - - virtual void RemoveColumn(int column); // removes a column - virtual int FindColumn(const char *columnName); - virtual void SetColumnHeaderHeight( int height ); - virtual void SetColumnHeaderText(int column, const char *text); - virtual void SetColumnHeaderText(int column, wchar_t *text); - virtual void SetColumnHeaderImage(int column, int imageListIndex); - virtual void SetColumnHeaderTooltip(int column, const char *tooltipText); - virtual void SetColumnTextAlignment( int column, int align ); - - // Get information about the column headers. - virtual int GetNumColumnHeaders() const; - virtual bool GetColumnHeaderText( int index, char *pOut, int maxLen ); - - virtual void SetSortFunc(int column, SortFunc *func); - virtual void SetSortColumn(int column); - virtual void SortList( void ); - virtual void SetColumnSortable(int column, bool sortable); - virtual void SetColumnVisible(int column, bool visible); - int GetSortColumn() const; - - // sets whether the user can add/remove columns (defaults to off) - virtual void SetAllowUserModificationOfColumns(bool allowed); - - // DATA HANDLING - // data->GetName() is used to uniquely identify an item - // data sub items are matched against column header name to be used in the table - virtual int AddItem(const KeyValues *data, unsigned int userData, bool bScrollToItem, bool bSortOnAdd); // Takes a copy of the data for use in the table. Returns the index the item is at. - void SetItemDragData( int itemID, const KeyValues *data ); // Makes a copy of the keyvalues to store in the table. Used when dragging from the table. Only used if the caller enables drag support - virtual int GetItemCount( void ); // returns the number of VISIBLE items - virtual int GetItem(const char *itemName); // gets the row index of an item by name (data->GetName()) - virtual KeyValues *GetItem(int itemID); // returns pointer to data the row holds - virtual int GetItemCurrentRow(int itemID); // returns -1 if invalid index or item not visible - virtual int GetItemIDFromRow(int currentRow); // returns -1 if invalid row - virtual unsigned int GetItemUserData(int itemID); - virtual ListPanelItem *GetItemData(int itemID); - virtual void SetUserData( int itemID, unsigned int userData ); - virtual int GetItemIDFromUserData( unsigned int userData ); - virtual void ApplyItemChanges(int itemID); // applies any changes to the data, performed by modifying the return of GetItem() above - virtual void RemoveItem(int itemID); // removes an item from the table (changing the indices of all following items) - virtual void RereadAllItems(); // updates the view with the new data - - virtual void RemoveAll(); // clears and deletes all the memory used by the data items - virtual void DeleteAllItems(); // obselete, use RemoveAll(); - - virtual void GetCellText(int itemID, int column, wchar_t *buffer, int bufferSize); // returns the data held by a specific cell - virtual IImage *GetCellImage(int itemID, int column); //, ImagePanel *&buffer); // returns the image held by a specific cell - - // Use these until they return InvalidItemID to iterate all the items. - virtual int FirstItem() const; - virtual int NextItem( int iItem ) const; - - virtual int InvalidItemID() const; - virtual bool IsValidItemID(int itemID); - - // sets whether the dataitem is visible or not - // it is removed from the row list when it becomes invisible, but stays in the indexes - // this is much faster than a normal remove - virtual void SetItemVisible(int itemID, bool state); - virtual void SetItemDisabled(int itemID, bool state ); - bool IsItemVisible( int itemID ); - - virtual void SetFont(HFont font); - - // image handling - virtual void SetImageList(ImageList *imageList, bool deleteImageListWhenDone); - - // SELECTION - - // returns the count of selected items - virtual int GetSelectedItemsCount(); - - // returns the selected item by selection index, valid in range [0, GetNumSelectedRows) - virtual int GetSelectedItem(int selectionIndex); - - // sets no item as selected - virtual void ClearSelectedItems(); - - virtual bool IsItemSelected( int itemID ); - - // adds a item to the select list - virtual void AddSelectedItem( int itemID ); - - // sets this single item as the only selected item - virtual void SetSingleSelectedItem( int itemID ); - - // returns the selected column, -1 for particular column selected - virtual int GetSelectedColumn(); - - // whether or not to select specific cells (off by default) - virtual void SetSelectIndividualCells(bool state); - - // whether or not multiple cells/rows can be selected - void SetMultiselectEnabled( bool bState ); - bool IsMultiselectEnabled() const; - - // sets a single cell - all other previous rows are cleared - virtual void SetSelectedCell(int row, int column); - - virtual bool GetCellAtPos(int x, int y, int &row, int &column); // returns true if any found, row and column are filled out. x, y are in screen space - virtual bool GetCellBounds( int row, int column, int& x, int& y, int& wide, int& tall ); - - // sets the text which is displayed when the list is empty - virtual void SetEmptyListText(const char *text); - virtual void SetEmptyListText(const wchar_t *text); - - // relayout the scroll bar in response to changing the items in the list panel - // do this if you RemoveAll() - void ResetScrollBar(); - - // Attaches drag data to a particular item - virtual void OnCreateDragData( KeyValues *msg ); - - void SetIgnoreDoubleClick( bool state ); - - // set up a field for editing - virtual void EnterEditMode(int itemID, int column, vgui::Panel *editPanel); - - // leaves editing mode - virtual void LeaveEditMode(); - - // returns true if we are currently in inline editing mode - virtual bool IsInEditMode(); - - MESSAGE_FUNC_INT( ResizeColumnToContents, "ResizeColumnToContents", column ); - -protected: - // PAINTING - virtual Panel *GetCellRenderer(int row, int column); - - // overrides - virtual void OnMouseWheeled(int delta); - virtual void OnSizeChanged(int wide, int tall); - virtual void PerformLayout(); - virtual void Paint(); - virtual void PaintBackground(); - virtual void ApplySchemeSettings(IScheme *pScheme); - virtual void OnMousePressed( MouseCode code ); - virtual void OnMouseDoublePressed( MouseCode code ); - virtual void OnKeyCodeTyped( KeyCode code ); - MESSAGE_FUNC( OnSliderMoved, "ScrollBarSliderMoved" ); - MESSAGE_FUNC_INT_INT( OnColumnResized, "ColumnResized", column, delta ); - MESSAGE_FUNC_INT( OnSetSortColumn, "SetSortColumn", column ); - MESSAGE_FUNC( OpenColumnChoiceMenu, "OpenColumnChoiceMenu" ); - MESSAGE_FUNC_INT( OnToggleColumnVisible, "ToggleColumnVisible", col ); - virtual float GetRowsPerPage(); - virtual int GetStartItem(); - - // user configuration - virtual void ApplyUserConfigSettings(KeyValues *userConfig); - virtual void GetUserConfigSettings(KeyValues *userConfig); - virtual bool HasUserConfigSettings(); - - /* MESSAGES SENT - "ItemSelected" - query which items are selected - "ItemDeselected" - query which items are selected - */ - -public: - virtual void SetSortColumnEx( int iPrimarySortColumn, int iSecondarySortColumn, bool bSortAscending ); - void GetSortColumnEx( int &iPrimarySortColumn, int &iSecondarySortColumn, bool &bSortAscending ) const; - -private: - // Cleans up allocations associated with a particular item - void CleanupItem( FastSortListPanelItem *data ); - - // adds the item into the column indexes - void IndexItem(int itemID); - - // Purpose: - void UpdateSelection( vgui::MouseCode code, int x, int y, int row, int column ); - - // Handles multiselect - void HandleMultiSelection( int itemID, int row, int column ); - - // Handles addselect - void HandleAddSelection( int itemID, int row, int column ); - - // pre-sorted columns - struct IndexItem_t - { - ListPanelItem *dataItem; - int duplicateIndex; - }; - typedef CUtlRBTree IndexRBTree_t; - - struct column_t - { - Button *m_pHeader; - int m_iMinWidth; - int m_iMaxWidth; - bool m_bResizesWithWindow; - Panel *m_pResizer; - SortFunc *m_pSortFunc; - bool m_bTypeIsText; - bool m_bHidden; - bool m_bUnhidable; - IndexRBTree_t m_SortedTree; - int m_nContentAlignment; - }; - - // list of the column headers - CUtlLinkedList m_ColumnsData; - - // persistent list of all columns ever created, indexes into m_ColumnsData - used for matching up DATAITEM m_SortedTreeIndexes - CUtlVector m_ColumnsHistory; - - // current list of columns, indexes into m_ColumnsData - CUtlVector m_CurrentColumns; - - int m_iColumnDraggerMoved; // which column dragger was moved->which header to resize - int m_lastBarWidth; - - CUtlLinkedList m_DataItems; - CUtlVector m_VisibleItems; - - // set to true if the table needs to be sorted before it's drawn next - int m_iSortColumn; - int m_iSortColumnSecondary; - - void ResortColumnRBTree(int col); - static bool RBTreeLessFunc(vgui::ListPanel::IndexItem_t &item1, vgui::ListPanel::IndexItem_t &item2); - - TextImage *m_pTextImage; // used in rendering - ImagePanel *m_pImagePanel; // used in rendering - Label *m_pLabel; // used in rendering - ScrollBar *m_hbar; - ScrollBar *m_vbar; - - int m_iSelectedColumn; - - bool m_bNeedsSort : 1; - bool m_bSortAscending : 1; - bool m_bSortAscendingSecondary : 1; - bool m_bCanSelectIndividualCells : 1; - bool m_bShiftHeldDown : 1; - bool m_bMultiselectEnabled : 1; - bool m_bAllowUserAddDeleteColumns : 1; - bool m_bDeleteImageListWhenDone : 1; - bool m_bIgnoreDoubleClick : 1; - - int m_iHeaderHeight; - int m_iRowHeight; - - // selection data - CUtlVector m_SelectedItems; // array of selected rows - int m_LastItemSelected; // remember the last row selected for future shift clicks - - int m_iTableStartX; - int m_iTableStartY; - - Color m_LabelFgColor; - Color m_DisabledColor; - Color m_SelectionFgColor; - Color m_DisabledSelectionFgColor; - - ImageList *m_pImageList; - TextImage *m_pEmptyListText; - - PHandle m_hEditModePanel; - int m_iEditModeItemID; - int m_iEditModeColumn; - - void ResetColumnHeaderCommands(); -}; - -} - -#endif // LISTPANEL_H diff --git a/public/vgui_controls/ListViewPanel.h b/public/vgui_controls/ListViewPanel.h deleted file mode 100644 index 8eb025348..000000000 --- a/public/vgui_controls/ListViewPanel.h +++ /dev/null @@ -1,121 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef LISTVIEWPANEL_H -#define LISTVIEWPANEL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -namespace vgui -{ - -class ListViewPanel; -typedef bool (*ListViewSortFunc_t)(KeyValues *kv1, KeyValues *kv2); - -class ListViewItem; - -//----------------------------------------------------------------------------- -// Purpose: List Ctrl Panel with each item having an icon and text after it -//----------------------------------------------------------------------------- -class ListViewPanel : public Panel -{ - DECLARE_CLASS_SIMPLE( ListViewPanel, Panel ); - -public: - ListViewPanel(Panel *parent, const char *panelName); - ~ListViewPanel(); - - virtual int AddItem(const KeyValues *data, bool bScrollToItem, bool bSortOnAdd); - virtual int GetItemCount(); - virtual KeyValues *GetItem(int itemID); - virtual void ApplyItemChanges(int itemID); - virtual void RemoveItem(int itemID); - virtual void DeleteAllItems(); - virtual int GetItemIDFromPos(int iPos); // valid from [0, GetItemCount) - - virtual int InvalidItemID(); - virtual bool IsValidItemID(int itemID); - - virtual void ScrollToItem(int itemID); - - virtual void SetSortFunc(ListViewSortFunc_t func); - virtual void SortList(); - - // image handling - virtual void SetImageList(ImageList *imageList, bool deleteImageListWhenDone); - - virtual void SetFont(HFont font); - - // returns the count of selected items - virtual int GetSelectedItemsCount(); - - // returns the selected item by selection index, valid in range [0, GetNumSelectedRows) - virtual int GetSelectedItem(int selectionIndex); - - // sets no item as selected - virtual void ClearSelectedItems(); - - // adds a item to the select list - virtual void AddSelectedItem(int itemID); - - // sets this single item as the only selected item - virtual void SetSingleSelectedItem(int itemID); - -protected: - // overrides - virtual void OnMouseWheeled(int delta); - virtual void OnSizeChanged(int wide, int tall); - virtual void PerformLayout(); - virtual void Paint(); - virtual void ApplySchemeSettings(IScheme *pScheme); - virtual void OnMousePressed( MouseCode code); - virtual void OnMouseDoublePressed( MouseCode code); - virtual void OnKeyCodeTyped( KeyCode code); - virtual void OnKeyTyped(wchar_t unichar); - MESSAGE_FUNC( OnSliderMoved, "ScrollBarSliderMoved" ); - virtual int GetItemsPerColumn(); - -private: - ScrollBar *m_hbar; - - friend class ListViewItem; - void OnItemMousePressed(ListViewItem* pItem, MouseCode code); - void OnItemMouseDoublePressed(ListViewItem* pItem, MouseCode code); - int GetItemsMaxWidth(); - int GetItemIndex(int itemID); - void OnShiftSelect(int itemID); - void FinishKeyPress(int itemID); - - CUtlLinkedList m_DataItems; - CUtlVector m_SortedItems; - ListViewSortFunc_t m_pSortFunc; - - int m_iRowHeight; - HFont m_hFont; - - Color m_LabelFgColor; - Color m_SelectionFgColor; - - // selection data - CUtlVector m_SelectedItems; - int m_LastSelectedItemID; - int m_ShiftStartItemID; - - bool m_bNeedsSort; - bool m_bDeleteImageListWhenDone; - ImageList *m_pImageList; -}; - - -} - -#endif // LISTVIEWPANEL_H diff --git a/public/vgui_controls/Menu.h b/public/vgui_controls/Menu.h deleted file mode 100644 index f716c6466..000000000 --- a/public/vgui_controls/Menu.h +++ /dev/null @@ -1,331 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef MENU_H -#define MENU_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include -#include - -namespace vgui -{ - -class MenuItem; -class ScrollBar; -class MenuSeparator; - -//----------------------------------------------------------------------------- -// Purpose: A menu is a list of items that can be selected with one click, navigated -// with arrow keys and/or hot keys, and have a lit behavior when mouse over. -// It is NOT the button which opens the menu, but only the menu itself. -// -// Behaviour spec: -// Menu navigation can be done in 2 modes, via keyboard keys and via mouse. -// Clicking on menu button opens menu. -// Only one item in a menu is highlighted at a time. -// Only one submenu in a menu is open at a time. -// Disabled menuitems get highlighted via mouse and keys but will not activate. -// -// Mouse: -// Moving mouse into a menuitem highlights it. -// If the menuitem has a cascading menu, the menu opens when the mouse enters -// the menuitem. The cascading menuitem stays highlighted while its menu is open. -// No submenu items are highlighted by default. -// Moving the mouse into another menuitem closes any previously open submenus in the list. -// Clicking once in the menu item activates the menu item and closes all menus. -// Moving the mouse off a menuitem unhighlights it. -// The scroll bar arrows can be used to move up/down the menu one item at a time. -// The clicking and dragging on the scroll bar nob also scrolls the menu items. -// If a highlighed menuitem scrolls off, and the user then begins navigating via keys, -// the menu will snap the scroll bar so the highlighted item is visible. -// If user has been navigating via keys, moving the mouse over a menu item -// highlights it. -// Mousewheel: -// You must have the mouse inside the menu/scroll bar to use the wheel. -// The mouse wheel moves the highlighted menuitem up or down the list. -// If the list has no scroll bar the wheel will cycle from the bottom of the list -// to the top of the list and vice versa. -// If the list has a scrollbar the mouse wheel will stop at the top or bottom -// of the list. -// If the mouse is over the scroll bar no items are highlighted. -// Keyboard: -// When a menu is opened, no items are highlighted. -// If a menuitem has a cascading menu it does not open when the item is highlighted. -// The down arrow selects the next item in the list. -// (first item if none are highlighted and there is a scrollbar). -// The up arrow selects the previous item in the list -// (first item if none are highlighted and there is a scrollbar, last item if none are -// highlighted and there is no scrollbar). -// Selecting a new menuitem closes any previously open submenus in the list. -// The enter key activates the selected item and closes all menus. -// If the selected item has a cascading menu, activating it opens its submenu. -// These may also be activated by pressing the right arrow. -// Pressing the left arrow closes the submenu. -// When the submenu is opened the cascading menuitem stays highlighted. -// No items in the submenu are highlighted when it is opened. -// -// Note: Cascading menuitems in menus with a scrollbar is not supported. -// Its a clunky UI and if we want this we should design a better solution, -// perhaps along the lines of how explorer's bookmarks does it. -// It currently functions, but there are some arm/disarm bugs. -// -// -//----------------------------------------------------------------------------- -class Menu : public Panel -{ - DECLARE_CLASS_SIMPLE( Menu, Panel ); - friend class MenuItem; -public: - enum MenuDirection_e - { - LEFT, - RIGHT, - UP, - DOWN, - CURSOR, // make the menu appear under the mouse cursor - ALIGN_WITH_PARENT, // make the menu appear under the parent - }; - - Menu(Panel *parent, const char *panelName); - ~Menu(); - - static void PlaceContextMenu( Panel *parent, Menu *menu ); - static void OnInternalMousePressed( Panel *other, MouseCode code ); - - virtual void PositionRelativeToPanel( Panel *reference, MenuDirection_e direction, int nAdditionalYOffset = 0, bool showMenu = false ); - - // the menu. For combo boxes, it's the edit/field, etc. etc. - - // Add a simple text item to the menu - virtual int AddMenuItem( const char *itemName, const char *itemText, const char *command, Panel *target, const KeyValues *userData = NULL ); - virtual int AddMenuItem( const char *itemName, const wchar_t *wszItemText, const char *command, Panel *target, const KeyValues *userData = NULL ); - - virtual int AddMenuItem( const char *itemName, const char *itemText, KeyValues *message, Panel *target , const KeyValues *userData = NULL); - virtual int AddMenuItem( const char *itemName, const wchar_t *wszItemText, KeyValues *message, Panel *target , const KeyValues *userData = NULL); - - virtual int AddMenuItem( const char *itemText, const char *command, Panel *target , const KeyValues *userData = NULL); - virtual int AddMenuItem( const char *itemText, KeyValues *message, Panel *target, const KeyValues *userData = NULL ); - virtual int AddMenuItem( const char *itemText, Panel *target, const KeyValues *userData = NULL ); - - // Add a checkable item to the menu - virtual int AddCheckableMenuItem( const char *itemName, const char *itemText, const char *command, Panel *target, const KeyValues *userData = NULL ); - virtual int AddCheckableMenuItem( const char *itemName, const wchar_t *wszItemText, const char *command, Panel *target, const KeyValues *userData = NULL ); - - virtual int AddCheckableMenuItem( const char *itemName, const char *itemText, KeyValues *message, Panel *target, const KeyValues *userData = NULL ); - virtual int AddCheckableMenuItem( const char *itemName, const wchar_t *wszItemText, KeyValues *message, Panel *target, const KeyValues *userData = NULL ); - - virtual int AddCheckableMenuItem( const char *itemText, const char *command, Panel *target , const KeyValues *userData = NULL); - virtual int AddCheckableMenuItem( const char *itemText, KeyValues *message, Panel *target, const KeyValues *userData = NULL ); - virtual int AddCheckableMenuItem( const char *itemText, Panel *target, const KeyValues *userData = NULL ); - - // Add a cascading menu item to the menu - virtual int AddCascadingMenuItem( const char *itemName, const char *itemText, const char *command, Panel *target, Menu *cascadeMenu, const KeyValues *userData = NULL ); - virtual int AddCascadingMenuItem( const char *itemName, const wchar_t *wszItemText, const char *command, Panel *target, Menu *cascadeMenu, const KeyValues *userData = NULL ); - - virtual int AddCascadingMenuItem( const char *itemName, const char *itemText, KeyValues *message, Panel *target, Menu *cascadeMenu, const KeyValues *userData = NULL ); - virtual int AddCascadingMenuItem( const char *itemName, const wchar_t *wszItemText, KeyValues *message, Panel *target, Menu *cascadeMenu, const KeyValues *userData = NULL ); - - virtual int AddCascadingMenuItem( const char *itemText, const char *command, Panel *target, Menu *cascadeMenu, const KeyValues *userData = NULL ); - virtual int AddCascadingMenuItem( const char *itemText, KeyValues *message, Panel *target, Menu *cascadeMenu, const KeyValues *userData = NULL ); - virtual int AddCascadingMenuItem( const char *itemText, Panel *target, Menu *cascadeMenu, const KeyValues *userData = NULL ); - - // Add a custom panel to the menu - virtual int AddMenuItem( MenuItem *panel ); - - virtual void AddSeparator(); - virtual void AddSeparatorAfterItem( int itemID ); - - // Sets the values of a menu item at the specified index - virtual void UpdateMenuItem(int itemID, const char *itemText,KeyValues *message, const KeyValues *userData = NULL); - virtual void UpdateMenuItem(int itemID, const wchar_t *wszItemText,KeyValues *message, const KeyValues *userData = NULL); - - virtual void MoveMenuItem( int itemID, int moveBeforeThisItemID ); - - virtual bool IsValidMenuID(int itemID); - virtual int GetInvalidMenuID(); - - KeyValues *GetItemUserData(int itemID); - void GetItemText(int itemID, wchar_t *text, int bufLenInBytes); - void GetItemText(int itemID, char *text, int bufLenInBytes); - - virtual void SetItemEnabled(const char *itemName, bool state); - virtual void SetItemEnabled(int itemID, bool state); - virtual void SetItemVisible(const char *itemName, bool visible); - virtual void SetItemVisible(int itemID, bool visible); - - // Remove a single item - void DeleteItem( int itemID ); - - // Clear the menu, deleting all the menu items within - void DeleteAllItems(); - - // Override the auto-width setting with a single fixed width - virtual void SetFixedWidth( int width ); - - // Sets the content alignment of all items in the menu - void SetContentAlignment( Label::Alignment alignment ); - - // sets the height of each menu item - virtual void SetMenuItemHeight(int itemHeight); - virtual int GetMenuItemHeight() const; - - // Set the max number of items visible (scrollbar appears with more) - virtual void SetNumberOfVisibleItems( int numItems ); - - // Set up the menu items layout - virtual void PerformLayout( void ); - - virtual void SetBorder(class IBorder *border); - virtual void ApplySchemeSettings(IScheme *pScheme); - - // Hotkey handling - virtual void OnKeyTyped(wchar_t unichar); - // Menu nagivation etc. - virtual void OnKeyCodeTyped( KeyCode code ); - - // Visibility - virtual void SetVisible(bool state); - - // Activates item in the menu list, as if that menu item had been selected by the user - virtual void ActivateItem(int itemID); - virtual void ActivateItemByRow(int row); - virtual int GetActiveItem(); // returns the itemID (not the row) of the active item - - // Return the number of items currently in the menu list - virtual int GetItemCount(); - - // return the menuID of the n'th item in the menu list, valid from [0, GetItemCount) - virtual int GetMenuID(int index); - - // Return the number of items currently visible in the menu list - int GetCurrentlyVisibleItemsCount(); - - MenuItem *GetMenuItem(int itemID); - void CloseOtherMenus(MenuItem *item); - virtual void OnKillFocus(); - - int GetMenuMode(); - enum MenuMode - { - MOUSE = 0, - KEYBOARD, - }; - - void SetCurrentlyHighlightedItem(int itemID); - int GetCurrentlyHighlightedItem(); - void ClearCurrentlyHighlightedItem(); - - // Set the checked state of a checkable menuItem - void SetMenuItemChecked(int itemID, bool state); - bool IsChecked(int index); // check if item is checked. - - - void SetMinimumWidth(int width); - int GetMinimumWidth(); - - // baseclass overrides to chain colors through to cascade menus - virtual void SetFgColor( Color newColor ); - virtual void SetBgColor( Color newColor ); - - virtual void SetFont( HFont font ); - - // Pass in NULL hotkey to remove hotkey - void SetCurrentKeyBinding( int itemID, char const *hotkey ); - - void ForceCalculateWidth(); - - void SetUseFallbackFont( bool bState, HFont hFallback ); - -protected: - // helper functions - int AddMenuItemCharCommand(MenuItem *item, const char *command, Panel *target, const KeyValues *userData); - int AddMenuItemKeyValuesCommand(MenuItem *item, KeyValues *message, Panel *target, const KeyValues *userData); - - // vgui result reporting - virtual void OnCommand( const char *command ); - MESSAGE_FUNC_PTR( OnMenuItemSelected, "MenuItemSelected", panel ); - virtual void AddScrollBar(); - virtual void RemoveScrollBar(); - MESSAGE_FUNC( OnSliderMoved, "ScrollBarSliderMoved" ); - virtual void Paint(); - virtual void LayoutMenuBorder(); - virtual void MakeItemsVisibleInScrollRange( int maxVisibleItems, int nNumPixelsAvailable ); - virtual void OnMouseWheeled(int delta); - - int CountVisibleItems(); - void ComputeWorkspaceSize( int& workWide, int& workTall ); - int ComputeFullMenuHeightWithInsets(); - - void CalculateWidth(); - - void LayoutScrollBar(); - void PositionCascadingMenu(); - void SizeMenuItems(); - void OnCursorMoved(int x, int y); - void OnKeyCodePressed(KeyCode code); - void OnMenuClose(); - MESSAGE_FUNC( OnKeyModeSet, "KeyModeSet" ); - - void SetCurrentlySelectedItem(MenuItem *item); - void SetCurrentlySelectedItem(int itemID); - MESSAGE_FUNC_INT( OnCursorEnteredMenuItem, "CursorEnteredMenuItem", VPanel); - MESSAGE_FUNC_INT( OnCursorExitedMenuItem, "CursorExitedMenuItem", VPanel); - - void MoveAlongMenuItemList(int direction, int loopCount); - - enum - { - DEFAULT_MENU_ITEM_HEIGHT = 22, // height of items in the menu - MENU_UP = -1, // used for moving up/down list of menu items in the menu - MENU_DOWN = 1 - }; - -#ifdef DBGFLAG_VALIDATE - virtual void Validate( CValidator &validator, char *pchName ); -#endif // DBGFLAG_VALIDATE - -private: - MenuItem *GetParentMenuItem(); - - int m_iMenuItemHeight; - int m_iFixedWidth; - int m_iMinimumWidth; // a minimum width the menu has to be if it is not fixed width - int m_iNumVisibleLines; // number of items in menu before scroll bar adds on - ScrollBar *m_pScroller; - - CUtlLinkedList m_MenuItems; - - CUtlVector m_VisibleSortedItems; - CUtlVector m_SortedItems; // used for visual - CUtlVector m_Separators; // menu item ids after which separators should be shown - CUtlVector m_SeparatorPanels; - - bool _sizedForScrollBar: 1 ; // whether menu has been sized for a scrollbar - bool m_bUseFallbackFont : 1; - bool _recalculateWidth : 1; - - int _menuWide; - int m_iCurrentlySelectedItemID; - int m_iInputMode; - int m_iCheckImageWidth; // the size of the check box spot on a checkable menu. - int m_iProportionalScrollBarSize; - Label::Alignment m_Alignment; - Color _borderDark; - int m_iActivatedItem; - HFont m_hItemFont; - HFont m_hFallbackItemFont; -}; - -} // namespace vgui - -#endif // MENU_H diff --git a/public/vgui_controls/MenuBar.h b/public/vgui_controls/MenuBar.h deleted file mode 100644 index b1f780c29..000000000 --- a/public/vgui_controls/MenuBar.h +++ /dev/null @@ -1,54 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef MENUBAR_H -#define MENUBAR_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -class MenuBar : public Panel -{ - DECLARE_CLASS_SIMPLE( MenuBar, Panel ); - -public: - MenuBar(Panel *parent, const char *panelName); - ~MenuBar(); - - virtual void AddButton(MenuButton *button); // add button to end of menu list - virtual void AddMenu( const char *pButtonName, Menu *pMenu ); - - virtual void GetContentSize( int& w, int&h ); - -protected: - virtual void OnKeyCodeTyped(KeyCode code); - virtual void OnKeyTyped(wchar_t unichar); - virtual void ApplySchemeSettings(IScheme *pScheme); - virtual void PerformLayout(); - virtual void Paint(); - MESSAGE_FUNC( OnMenuClose, "MenuClose" ); - MESSAGE_FUNC_INT( OnCursorEnteredMenuButton, "CursorEnteredMenuButton", VPanel); - -private: - CUtlVector m_pMenuButtons; - int m_nRightEdge; -}; - -} // namespace vgui - -#endif // MENUBAR_H - diff --git a/public/vgui_controls/MenuButton.h b/public/vgui_controls/MenuButton.h deleted file mode 100644 index f7be3bc14..000000000 --- a/public/vgui_controls/MenuButton.h +++ /dev/null @@ -1,82 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef MENUBUTTON_H -#define MENUBUTTON_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include "vgui_controls/Menu.h" - -namespace vgui -{ - -class Menu; -class TextImage; - -//----------------------------------------------------------------------------- -// Purpose: Button that displays a menu when pressed -//----------------------------------------------------------------------------- -class MenuButton : public Button -{ - DECLARE_CLASS_SIMPLE( MenuButton, Button ); - -public: - MenuButton(Panel *parent, const char *panelName, const char *text); - ~MenuButton(); - - // functions designed to be overriden - virtual void OnShowMenu(Menu *menu) {} - virtual void OnHideMenu(Menu *menu) {} - virtual int OnCheckMenuItemCount() { return 0; } - - virtual void SetMenu(Menu *menu); - virtual void HideMenu(void); - virtual void DrawFocusBorder(int tx0, int ty0, int tx1, int ty1); - MESSAGE_FUNC( OnMenuClose, "MenuClose" ); - MESSAGE_FUNC_PARAMS( OnKillFocus, "KillFocus", kv ); // called after the panel loses the keyboard focus - virtual void DoClick(); - virtual void SetOpenOffsetY(int yOffset); - - virtual bool CanBeDefaultButton(void); - - // sets the direction in which the menu opens from the button, defaults to down - virtual void SetOpenDirection(Menu::MenuDirection_e direction); - - virtual void OnKeyCodeTyped(KeyCode code); - virtual void OnCursorEntered(); - - virtual void Paint(); - virtual void PerformLayout(); - virtual void ApplySchemeSettings( IScheme *pScheme ); - virtual void OnCursorMoved( int x, int y ); - - // This style is like the IE "back" button where the left side acts like a regular button, the the right side has a little - // combo box dropdown indicator and presents and submenu - void SetDropMenuButtonStyle( bool state ); - bool IsDropMenuButtonStyle() const; - - Menu *GetMenu(); - -private: - - Menu *m_pMenu; - Menu::MenuDirection_e m_iDirection; - - int _openOffsetY; // vertical offset of menu from the menu button - - bool m_bDropMenuButtonStyle : 1; - TextImage *m_pDropMenuImage; - int m_nImageIndex; -}; - -}; // namespace vgui - -#endif // MENUBUTTON_H diff --git a/public/vgui_controls/MenuItem.h b/public/vgui_controls/MenuItem.h deleted file mode 100644 index 2524170e8..000000000 --- a/public/vgui_controls/MenuItem.h +++ /dev/null @@ -1,136 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef MENUITEM_H -#define MENUITEM_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include - -namespace vgui -{ - -class IBorder; -class TextImage; -class Menu; -class Image; - -//----------------------------------------------------------------------------- -// Purpose: The items in a menu -// MenuItems MUST have the Menu class as parents. -//----------------------------------------------------------------------------- -class MenuItem : public Button -{ - DECLARE_CLASS_SIMPLE( MenuItem, Button ); - -public: - MenuItem(Menu *parent, const char *panelName, const char *text, Menu *cascadeMenu = NULL, bool checkable = false); - MenuItem(Menu *parent, const char *panelName, const wchar_t *wszText, Menu *cascadeMenu = NULL, bool checkable = false); - ~MenuItem(); - - virtual void Paint(); - - // Activate the menu item as if it had been selected by the user - virtual void FireActionSignal(); - - virtual bool CanBeDefaultButton(void); - - // Handle mouse cursor entering a MenuItem. - void OnCursorEntered(); - // Handle mouse cursor exiting a MenuItem. - void OnCursorExited(); - - // Close the cascading menu if we have one. - void CloseCascadeMenu(); - - // Pass kill focus events up to parent on loss of focus - MESSAGE_FUNC( OnKillFocus, "MenuClose" ); - - // Return true if this item triggers a cascading menu - bool HasMenu(); - - // Set the size of the text portion of the label. - void SetTextImageSize(int wide, int tall); - - //Return the size of the text portion of the label. - void GetTextImageSize(int &wide, int &tall); - - // Return the size of the arrow portion of the label. - void GetArrowImageSize(int &wide, int &tall); - - // Return the size of the check portion of the label. - void GetCheckImageSize(int &wide, int &tall); - - // Return the menu that this menuItem contains - Menu *GetMenu(); - - virtual void PerformLayout(); - - // Respond to cursor movement - void OnCursorMoved(int x, int y); - - // Highlight item - MESSAGE_FUNC( ArmItem, "ArmItem" ); - // Unhighlight item. - MESSAGE_FUNC( DisarmItem, "DisarmItem" ); - - // is the item highlighted? - bool IsItemArmed(); - - // Open cascading menu if there is one. - void OpenCascadeMenu(); - - bool IsCheckable(); - bool IsChecked(); - - // Set a checkable menuItem checked or unchecked. - void SetChecked(bool state); - - KeyValues *GetUserData(); - void SetUserData(const KeyValues *kv); - - int GetActiveItem() { if ( m_pCascadeMenu ) { return m_pCascadeMenu->GetActiveItem(); } else { return 0; }} - - Menu *GetParentMenu(); - - void SetCurrentKeyBinding( char const *keyName ); - - virtual void GetContentSize( int& cw, int &ch ); - -protected: - void OnKeyCodeReleased(KeyCode code); - void OnMenuClose(); - MESSAGE_FUNC( OnKeyModeSet, "KeyModeSet" ); - - // vgui overrides - virtual void Init( void ); - virtual void ApplySchemeSettings(IScheme *pScheme); - virtual IBorder *GetBorder(bool depressed, bool armed, bool selected, bool keyfocus); - -private: - enum { CHECK_INSET = 6 }; - Menu *m_pCascadeMenu; // menu triggered to open upon selecting this menu item - bool m_bCheckable; // can this menu item have a little check to the left of it when you select it? - bool m_bChecked; // whether item is checked or not. - TextImage *m_pCascadeArrow; // little arrow that appears to the right of menuitems that open a menu - Image *m_pCheck; // the check that appears to the left of checked menu items - TextImage *m_pBlankCheck; // a blank image same size as the check for when items are not checked. - - TextImage *m_pCurrentKeyBinding; // An optional indicator for the key currently bound to this menu item - - KeyValues *m_pUserData; - -}; - -} // namespace vgui - -#endif // MENUITEM_H diff --git a/public/vgui_controls/MessageBox.h b/public/vgui_controls/MessageBox.h deleted file mode 100644 index c46464255..000000000 --- a/public/vgui_controls/MessageBox.h +++ /dev/null @@ -1,98 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef MESSAGEBOX_H -#define MESSAGEBOX_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -// prevent windows macros from messing with the class -#ifdef MessageBox -#undef MessageBox -#endif - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Popup discardable message box -//----------------------------------------------------------------------------- -class MessageBox : public Frame -{ - DECLARE_CLASS_SIMPLE( MessageBox, Frame ); - -public: - // title - Text to be displayed in the title bar of the window - // text - Text message in the message box - // startMinimized - wether message box starts minimized. Starts invisible by default - // parent - parent panel of the message box, by default it has no parent. This will keep the box visible until the OK button is pressed. - MessageBox(const char *title, const char *text, Panel *parent = NULL); - MessageBox(const wchar_t *wszTitle, const wchar_t *wszText, Panel *parent = NULL); - ~MessageBox(); - - // Put the message box into a modal state - virtual void DoModal(Frame *pFrameOver = NULL); - - // make the message box appear and in a modeless state - virtual void ShowWindow(Frame *pFrameOver = NULL); - - // Set a string command to be sent when the OK button is pressed - // Use AddActionSignalTarget() to mark yourself as a recipient of the command - virtual void SetCommand(const char *command); - virtual void SetCommand(KeyValues *command); - - // Set the visibility of the OK button. - virtual void SetOKButtonVisible(bool state); - - // Set the text on the OK button - virtual void SetOKButtonText(const char *buttonText); - virtual void SetOKButtonText(const wchar_t *wszButtonText); - - // Cancel button (off by default) - void SetCancelButtonVisible(bool state); - void SetCancelButtonText(const char *buttonText); - void SetCancelButtonText(const wchar_t *wszButtonText); - void SetCancelCommand( KeyValues *command ); - - // Toggles visibility of the close box. - virtual void DisableCloseButton(bool state); - - virtual void OnCommand( const char *pCommand ); - - // Shows the message box over the cursor - void ShowMessageBoxOverCursor( bool bEnable ); - -protected: - virtual void PerformLayout(); - virtual void ApplySchemeSettings(IScheme *pScheme); - -protected: - Button *m_pOkButton; - Button *m_pCancelButton; - Label *m_pMessageLabel; - -private: - MESSAGE_FUNC( OnShutdownRequest, "ShutdownRequest" ); - - void Init(); - - KeyValues *m_OkCommand; - KeyValues *m_CancelCommand; - vgui::Frame *m_pFrameOver; - bool m_bNoAutoClose : 1; - bool m_bShowMessageBoxOverCursor : 1; -}; - -} // namespace vgui - - -#endif // MESSAGEBOX_H diff --git a/public/vgui_controls/MessageDialog.h b/public/vgui_controls/MessageDialog.h deleted file mode 100644 index ec800b9ec..000000000 --- a/public/vgui_controls/MessageDialog.h +++ /dev/null @@ -1,154 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Contains the CMessageDialog declaration -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef MESSAGEDIALOG_H -#define MESSAGEDIALOG_H -#ifdef _WIN32 -#pragma once -#endif - -// styles -#define MD_WARNING 0x0001 -#define MD_ERROR 0x0002 - -// button configurations -#define MD_OK 0x0004 // 1 button - OK -#define MD_CANCEL 0x0008 // 1 button - CANCEL -#define MD_OKCANCEL 0x0010 // 2 buttons - OK and CANCEL -#define MD_YESNO 0x0020 // 2 buttons - YES and NO - -// behavior -#define MD_SIMPLEFRAME 0x0100 // legacy corners -#define MD_COMMANDAFTERCLOSE 0x0200 // send command at dialog termination (i.e. after fade) -#define MD_RESTRICTPAINT 0x0400 // only paint this dialog (hide any other ui elements) -#define MD_COMMANDONFORCECLOSE 0x0800 // send command when the dialog is closed assuming A input - -// dialog type -enum EDialogType -{ - MD_SAVE_BEFORE_QUIT, - MD_QUIT_CONFIRMATION, - MD_QUIT_CONFIRMATION_TF, - MD_KICK_CONFIRMATION, - MD_CLIENT_KICKED, - MD_LOST_HOST, - MD_LOST_SERVER, - MD_SEARCHING_FOR_GAMES, - MD_CREATING_GAME, - MD_MODIFYING_SESSION, - MD_SESSION_SEARCH_FAILED, - MD_SESSION_CREATE_FAILED, - MD_SESSION_CONNECTING, - MD_SESSION_CONNECT_NOTAVAILABLE, - MD_SESSION_CONNECT_SESSIONFULL, - MD_SESSION_CONNECT_FAILED, - MD_EXIT_SESSION_CONFIRMATION, - MD_STORAGE_DEVICES_NEEDED, - MD_STORAGE_DEVICES_CHANGED, - MD_STORAGE_DEVICES_TOO_FULL, - MD_NOT_ONLINE_ENABLED, - MD_NOT_ONLINE_SIGNEDIN, - MD_DEFAULT_CONTROLS_CONFIRM, - MD_AUTOSAVE_EXPLANATION, - MD_COMMENTARY_EXPLANATION, - MD_COMMENTARY_EXPLANATION_MULTI, - MD_COMMENTARY_CHAPTER_UNLOCK_EXPLANATION, - MD_SAVE_BEFORE_LANGUAGE_CHANGE, - MD_SAVE_BEFORE_NEW_GAME, - MD_SAVE_BEFORE_LOAD, - MD_DELETE_SAVE_CONFIRM, - MD_SAVE_OVERWRITE, - MD_SAVING_WARNING, - MD_SAVE_COMPLETE, - MD_STANDARD_SAMPLE, - MD_WARNING_SAMPLE, - MD_ERROR_SAMPLE, - MD_PROMPT_SIGNIN, - MD_PROMPT_SIGNIN_REQUIRED, - MD_PROMPT_STORAGE_DEVICE, - MD_PROMPT_STORAGE_DEVICE_REQUIRED, - MD_DISCONNECT_CONFIRMATION, - MD_DISCONNECT_CONFIRMATION_HOST, - MD_LOAD_FAILED_WARNING, - MD_OPTION_CHANGE_FROM_X360_DASHBOARD, - MD_STORAGE_DEVICES_CORRUPT, - MD_CHECKING_STORAGE_DEVICE -}; - -#include "vgui_controls/Frame.h" -#include "vgui_controls/Label.h" -#include "vgui_controls/AnimatingImagePanel.h" -#include "vgui_controls/ImagePanel.h" - -//----------------------------------------------------------------------------- -// Purpose: Simple modal dialog box for Xbox 360 warnings and messages -//----------------------------------------------------------------------------- -class CMessageDialog : public vgui::Frame -{ - DECLARE_CLASS_SIMPLE( CMessageDialog, vgui::Frame ); - -public: - CMessageDialog( vgui::Panel *parent, const uint nType, const char *pTitle, const char *pMsg, const char *pCmdA, const char *pCmdB, vgui::Panel *pParent, bool bShowActivity ); - ~CMessageDialog(); - - enum - { - BTN_INVALID = -1, - BTN_B, - BTN_A, - MAX_BUTTONS, - }; - - struct ButtonLabel_s - { - vgui::Label *pIcon; - vgui::Label *pText; - int nWide; - bool bCreated; - }; - - virtual void OnKeyCodePressed( vgui::KeyCode code ); - virtual void ApplySchemeSettings( vgui::IScheme *pScheme ); - virtual void ApplySettings( KeyValues *inResourceData ); - virtual void PaintBackground(); - uint GetType( void ); - void SetControlSettingsKeys( KeyValues *pKeys ); - -private: - void CreateButtonLabel( ButtonLabel_s *pButton, const char *pIcon, const char *pText ); - void DoCommand( int button ); - - vgui::Panel *m_pCreator; - - vgui::Label *m_pTitle; - vgui::Label *m_pMsg; - vgui::ImagePanel *m_pBackground; - - vgui::AnimatingImagePanel *m_pAnimatingPanel; - - vgui::HFont m_hButtonFont; - vgui::HFont m_hTextFont; - uint m_nType; - Color m_ButtonTextColor; - int m_ButtonPressed; - KeyValues *m_pControlSettings; - - int m_FooterTall; - int m_ButtonMargin; - Color m_clrNotSimpleBG; - Color m_clrNotSimpleBGBlack; - int m_ButtonIconLabelSpace; - - int m_ActivityIndent; - - bool m_bShowActivity; // should we show an animating image panel? - - ButtonLabel_s m_Buttons[MAX_BUTTONS]; - char *m_pCommands[MAX_BUTTONS]; -}; - -#endif // MESSAGEDIALOG_H diff --git a/public/vgui_controls/MessageMap.h b/public/vgui_controls/MessageMap.h deleted file mode 100644 index ad4f5ba28..000000000 --- a/public/vgui_controls/MessageMap.h +++ /dev/null @@ -1,386 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef MESSAGEMAP_H -#define MESSAGEMAP_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/utlvector.h" - -// more flexible than default pointers to members code required for casting member function pointers -#pragma pointers_to_members( full_generality, virtual_inheritance ) - -namespace vgui -{ - -////////////// MESSAGEMAP DEFINITIONS ////////////// - -#ifndef offsetof -#define offsetof(s,m) (size_t)&(((s *)0)->m) -#endif - -#ifndef ARRAYSIZE -#define ARRAYSIZE(p) (sizeof(p)/sizeof(p[0])) -#endif - - -//----------------------------------------------------------------------------- -// Purpose: parameter data type enumeration -// used internal but the shortcut macros require this to be exposed -//----------------------------------------------------------------------------- -enum DataType_t -{ - DATATYPE_VOID, - DATATYPE_CONSTCHARPTR, - DATATYPE_INT, - DATATYPE_FLOAT, - DATATYPE_PTR, - DATATYPE_BOOL, - DATATYPE_KEYVALUES, - DATATYPE_CONSTWCHARPTR, - DATATYPE_UINT64, - DATATYPE_HANDLE, // It's an int, really -}; - -class Panel; -typedef unsigned int VPANEL; - -typedef void (Panel::*MessageFunc_t)(void); - -//----------------------------------------------------------------------------- -// Purpose: Single item in a message map -// Contains the information to map a string message name with parameters -// to a function call -//----------------------------------------------------------------------------- -#pragma warning(disable:4121) -struct MessageMapItem_t -{ - const char *name; - // VC6 aligns this to 16-bytes. Since some of the code has been compiled with VC6, - // we need to enforce the alignment on later compilers to remain compatible. - ALIGN16 MessageFunc_t func; - - int numParams; - - DataType_t firstParamType; - const char *firstParamName; - - DataType_t secondParamType; - const char *secondParamName; - - int nameSymbol; - int firstParamSymbol; - int secondParamSymbol; -}; - -#define DECLARE_PANELMESSAGEMAP( className ) \ - static void AddToMap( char const *scriptname, vgui::MessageFunc_t function, int paramCount, int p1type, const char *p1name, int p2type, const char *p2name ) \ - { \ - vgui::PanelMessageMap *map = vgui::FindOrAddPanelMessageMap( GetPanelClassName() ); \ - \ - vgui::MessageMapItem_t entry; \ - entry.name = scriptname; \ - entry.func = function; \ - entry.numParams = paramCount; \ - entry.firstParamType = (vgui::DataType_t)p1type; \ - entry.firstParamName = p1name; \ - entry.secondParamType = (vgui::DataType_t)p2type; \ - entry.secondParamName = p2name; \ - entry.nameSymbol = 0; \ - entry.firstParamSymbol = 0; \ - entry.secondParamSymbol = 0; \ - \ - map->entries.AddToTail( entry ); \ - } \ - \ - static void ChainToMap( void ) \ - { \ - static bool chained = false; \ - if ( chained ) \ - return; \ - chained = true; \ - vgui::PanelMessageMap *map = vgui::FindOrAddPanelMessageMap( GetPanelClassName() ); \ - map->pfnClassName = &GetPanelClassName; \ - if ( map && GetPanelBaseClassName() && GetPanelBaseClassName()[0] ) \ - { \ - map->baseMap = vgui::FindOrAddPanelMessageMap( GetPanelBaseClassName() ); \ - } \ - } \ - \ - class className##_RegisterMap; \ - friend class className##_RegisterMap; \ - class className##_RegisterMap \ - { \ - public: \ - className##_RegisterMap() \ - { \ - className::ChainToMap(); \ - } \ - }; \ - className##_RegisterMap m_RegisterClass; \ - \ - virtual vgui::PanelMessageMap *GetMessageMap() \ - { \ - static vgui::PanelMessageMap *s_pMap = vgui::FindOrAddPanelMessageMap( GetPanelClassName() ); \ - return s_pMap; \ - } - -#if !defined( _XBOX ) -#define VGUI_USEKEYBINDINGMAPS 1 -#endif - -#if defined( VGUI_USEKEYBINDINGMAPS ) - -#define DECLARE_CLASS_SIMPLE( className, baseClassName ) \ - typedef baseClassName BaseClass; \ - typedef className ThisClass; \ -public: \ - DECLARE_PANELMESSAGEMAP( className ); \ - DECLARE_PANELANIMATION( className ); \ - DECLARE_KEYBINDINGMAP( className ); \ - static char const *GetPanelClassName() { return #className; } \ - static char const *GetPanelBaseClassName() { return #baseClassName; } - -#define DECLARE_CLASS_SIMPLE_NOBASE( className ) \ - typedef className ThisClass; \ -public: \ - DECLARE_PANELMESSAGEMAP( className ); \ - DECLARE_PANELANIMATION( className ); \ - DECLARE_KEYBINDINGMAP( className ); \ - static char const *GetPanelClassName() { return #className; } \ - static char const *GetPanelBaseClassName() { return NULL; } - -#else // no keybinding maps - -#define DECLARE_CLASS_SIMPLE( className, baseClassName ) \ - typedef baseClassName BaseClass; \ - typedef className ThisClass; \ -public: \ - DECLARE_PANELMESSAGEMAP( className ); \ - DECLARE_PANELANIMATION( className ); \ - static char const *GetPanelClassName() { return #className; } \ - static char const *GetPanelBaseClassName() { return #baseClassName; } - -#define DECLARE_CLASS_SIMPLE_NOBASE( className ) \ - typedef className ThisClass; \ -public: \ - DECLARE_PANELMESSAGEMAP( className ); \ - DECLARE_PANELANIMATION( className ); \ - static char const *GetPanelClassName() { return #className; } \ - static char const *GetPanelBaseClassName() { return NULL; } - -#endif // !VGUI_USEKEYBINDINGMAPS - -#define _MessageFuncCommon( name, scriptname, paramCount, p1type, p1name, p2type, p2name ) \ - class PanelMessageFunc_##name; \ - friend class PanelMessageFunc_##name; \ - class PanelMessageFunc_##name \ - { \ - public: \ - static void InitVar() \ - { \ - static bool bAdded = false; \ - if ( !bAdded ) \ - { \ - bAdded = true; \ - AddToMap( scriptname, (vgui::MessageFunc_t)&ThisClass::name, paramCount, p1type, p1name, p2type, p2name ); \ - } \ - } \ - PanelMessageFunc_##name() \ - { \ - PanelMessageFunc_##name::InitVar(); \ - } \ - }; \ - PanelMessageFunc_##name m_##name##_register; \ - -// Use this macro to define a message mapped function -// must end with a semicolon ';', or with a function -// no parameter -#define MESSAGE_FUNC( name, scriptname ) _MessageFuncCommon( name, scriptname, 0, 0, 0, 0, 0 ); virtual void name( void ) - -// one parameter -#define MESSAGE_FUNC_INT( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_INT, #p1, 0, 0 ); virtual void name( int p1 ) -#define MESSAGE_FUNC_UINT64( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_UINT64, #p1, 0, 0 ); virtual void name( uint64 p1 ) -#define MESSAGE_FUNC_PTR( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_PTR, #p1, 0, 0 ); virtual void name( vgui::Panel *p1 ) -#define MESSAGE_FUNC_HANDLE( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_HANDLE, #p1, 0, 0 ); virtual void name( vgui::VPANEL p1 ) -#define MESSAGE_FUNC_ENUM( name, scriptname, t1, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_INT, #p1, 0, 0 ); virtual void name( t1 p1 ) -#define MESSAGE_FUNC_FLOAT( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_FLOAT, #p1, 0, 0 ); virtual void name( float p1 ) -#define MESSAGE_FUNC_CHARPTR( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_CONSTCHARPTR, #p1, 0, 0 ); virtual void name( const char *p1 ) -#define MESSAGE_FUNC_WCHARPTR( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_CONSTWCHARPTR, #p1, 0, 0 ); virtual void name( const wchar_t *p1 ) - -// two parameters -#define MESSAGE_FUNC_INT_INT( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_INT, #p1, vgui::DATATYPE_INT, #p2 ); virtual void name( int p1, int p2 ) -#define MESSAGE_FUNC_PTR_INT( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_PTR, #p1, vgui::DATATYPE_INT, #p2 ); virtual void name( vgui::Panel *p1, int p2 ) -#define MESSAGE_FUNC_HANDLE_INT( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_HANDLE, #p1, vgui::DATATYPE_INT, #p2 ); virtual void name( vgui::VPANEL p1, int p2 ) -#define MESSAGE_FUNC_ENUM_ENUM( name, scriptname, t1, p1, t2, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_INT, #p1, vgui::DATATYPE_INT, #p2 ); virtual void name( t1 p1, t2 p2 ) -#define MESSAGE_FUNC_INT_CHARPTR( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_INT, #p1, vgui::DATATYPE_CONSTCHARPTR, #p2 ); virtual void name( int p1, const char *p2 ) -#define MESSAGE_FUNC_PTR_CHARPTR( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_PTR, #p1, vgui::DATATYPE_CONSTCHARPTR, #p2 ); virtual void name( vgui::Panel *p1, const char *p2 ) -#define MESSAGE_FUNC_HANDLE_CHARPTR( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_HANDLE, #p1, vgui::DATATYPE_CONSTCHARPTR, #p2 ); virtual void name( vgui::VPANEL p1, const char *p2 ) -#define MESSAGE_FUNC_PTR_WCHARPTR( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_PTR, #p1, vgui::DATATYPE_CONSTWCHARPTR, #p2 ); virtual void name( vgui::Panel *p1, const wchar_t *p2 ) -#define MESSAGE_FUNC_HANDLE_WCHARPTR( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_HANDLE, #p1, vgui::DATATYPE_CONSTWCHARPTR, #p2 ); virtual void name( vgui::VPANEL p1, const wchar_t *p2 ) -#define MESSAGE_FUNC_CHARPTR_CHARPTR( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_CONSTCHARPTR, #p1, vgui::DATATYPE_CONSTCHARPTR, #p2 ); virtual void name( const char *p1, const char *p2 ) - -// unlimited parameters (passed in the whole KeyValues) -#define MESSAGE_FUNC_PARAMS( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_KEYVALUES, NULL, 0, 0 ); virtual void name( KeyValues *p1 ) - -// no-virtual function version -#define MESSAGE_FUNC_NV( name, scriptname ) _MessageFuncCommon( name, scriptname, 0, 0, 0, 0, 0 ); void name( void ) -#define MESSAGE_FUNC_NV_INT( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_INT, #p1, 0, 0 ); void name( int p1 ) -#define MESSAGE_FUNC_NV_INT_INT( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_INT, #p1, vgui::DATATYPE_INT, #p2 ); void name( int p1, int p2 ) - - -// mapping, one per class -struct PanelMessageMap -{ - PanelMessageMap() - { - baseMap = NULL; - pfnClassName = NULL; - processed = false; - } - - CUtlVector< MessageMapItem_t > entries; - bool processed; - PanelMessageMap *baseMap; - char const *(*pfnClassName)( void ); -}; - -PanelMessageMap *FindPanelMessageMap( char const *className ); -PanelMessageMap *FindOrAddPanelMessageMap( char const *className ); - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// OBSELETE MAPPING FUNCTIONS, USE ABOVE -// -/////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// no parameters -#define MAP_MESSAGE( type, name, func ) { name, (vgui::MessageFunc_t)(&type::func), 0 } - -// implicit single parameter (params is the data store) -#define MAP_MESSAGE_PARAMS( type, name, func ) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_KEYVALUES, NULL } - -// single parameter -#define MAP_MESSAGE_PTR( type, name, func, param1 ) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_PTR, param1 } -#define MAP_MESSAGE_INT( type, name, func, param1 ) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_INT, param1 } -#define MAP_MESSAGE_BOOL( type, name, func, param1 ) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_BOOL, param1 } -#define MAP_MESSAGE_FLOAT( type, name, func, param1 ) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_FLOAT, param1 } -#define MAP_MESSAGE_PTR( type, name, func, param1 ) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_PTR, param1 } -#define MAP_MESSAGE_CONSTCHARPTR( type, name, func, param1) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_CONSTCHARPTR, param1 } -#define MAP_MESSAGE_CONSTWCHARPTR( type, name, func, param1) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_CONSTWCHARPTR, param1 } - -// two parameters -#define MAP_MESSAGE_INT_INT( type, name, func, param1, param2 ) { name, (vgui::MessageFunc_t)&type::func, 2, vgui::DATATYPE_INT, param1, vgui::DATATYPE_INT, param2 } -#define MAP_MESSAGE_PTR_INT( type, name, func, param1, param2 ) { name, (vgui::MessageFunc_t)&type::func, 2, vgui::DATATYPE_PTR, param1, vgui::DATATYPE_INT, param2 } -#define MAP_MESSAGE_INT_CONSTCHARPTR( type, name, func, param1, param2 ) { name, (vgui::MessageFunc_t)&type::func, 2, vgui::DATATYPE_INT, param1, vgui::DATATYPE_CONSTCHARPTR, param2 } -#define MAP_MESSAGE_PTR_CONSTCHARPTR( type, name, func, param1, param2 ) { name, (vgui::MessageFunc_t)&type::func, 2, vgui::DATATYPE_PTR, param1, vgui::DATATYPE_CONSTCHARPTR, param2 } -#define MAP_MESSAGE_PTR_CONSTWCHARPTR( type, name, func, param1, param2 ) { name, (vgui::MessageFunc_t)&type::func, 2, vgui::DATATYPE_PTR, param1, vgui::DATATYPE_CONSTWCHARPTR, param2 } -#define MAP_MESSAGE_CONSTCHARPTR_CONSTCHARPTR( type, name, func, param1, param2 ) { name, (vgui::MessageFunc_t)&type::func, 2, vgui::DATATYPE_CONSTCHARPTR, param1, vgui::DATATYPE_CONSTCHARPTR, param2 } - -// if more parameters are needed, just use MAP_MESSAGE_PARAMS() and pass the keyvalue set into the function - - -//----------------------------------------------------------------------------- -// Purpose: stores the list of objects in the hierarchy -// used to iterate through an object's message maps -//----------------------------------------------------------------------------- -struct PanelMap_t -{ - MessageMapItem_t *dataDesc; - int dataNumFields; - const char *dataClassName; - PanelMap_t *baseMap; - int processed; -}; - -// for use in class declarations -// declares the static variables and functions needed for the data description iteration -#define DECLARE_PANELMAP() \ - static vgui::PanelMap_t m_PanelMap; \ - static vgui::MessageMapItem_t m_MessageMap[]; \ - virtual vgui::PanelMap_t *GetPanelMap( void ); - -// could embed typeid() into here as well? -#define IMPLEMENT_PANELMAP( derivedClass, baseClass ) \ - vgui::PanelMap_t derivedClass::m_PanelMap = { derivedClass::m_MessageMap, ARRAYSIZE(derivedClass::m_MessageMap), #derivedClass, &baseClass::m_PanelMap }; \ - vgui::PanelMap_t *derivedClass::GetPanelMap( void ) { return &m_PanelMap; } - -typedef vgui::Panel *( *PANELCREATEFUNC )( void ); - -//----------------------------------------------------------------------------- -// Purpose: Used by DECLARE_BUILD_FACTORY macro to create a linked list of -// instancing functions -//----------------------------------------------------------------------------- -class CBuildFactoryHelper -{ -public: - // Static list of helpers - static CBuildFactoryHelper *m_sHelpers; - -public: - // Construction - CBuildFactoryHelper( char const *className, PANELCREATEFUNC func ); - - // Accessors - CBuildFactoryHelper *GetNext( void ); - - char const *GetClassName() const; - - vgui::Panel *CreatePanel(); - - static vgui::Panel *InstancePanel( char const *className ); - static void GetFactoryNames( CUtlVector< char const * >& list ); -private: - - static bool HasFactory( char const *className ); - - // Next factory in list - CBuildFactoryHelper *m_pNext; - - int m_Type; - PANELCREATEFUNC m_CreateFunc; - char const *m_pClassName; -}; - -// This is the macro which implements creation of each type of panel -// It creates a function which instances an object of the specified type -// It them hooks that function up to the helper list so that the CHud objects can create -// the elements by name, with no header file dependency, etc. -#define DECLARE_BUILD_FACTORY( className ) \ - static vgui::Panel *Create_##className##( void ) \ - { \ - return new className( NULL, NULL ); \ - }; \ - static vgui::CBuildFactoryHelper g_##className##_Helper( #className, Create_##className## );\ - className *g_##className##LinkerHack = NULL; - -#define DECLARE_BUILD_FACTORY_DEFAULT_TEXT( className, defaultText ) \ - static vgui::Panel *Create_##className##( void ) \ - { \ - return new className( NULL, NULL, #defaultText ); \ - }; \ - static vgui::CBuildFactoryHelper g_##className##_Helper( #className, Create_##className## );\ - className *g_##className##LinkerHack = NULL; - -// This one allows passing in a special function with calls new panel( xxx ) with arbitrary default parameters -#define DECLARE_BUILD_FACTORY_CUSTOM( className, createFunc ) \ - static vgui::CBuildFactoryHelper g_##className##_Helper( #className, createFunc );\ - className *g_##className##LinkerHack = NULL; - -#define DECLARE_BUILD_FACTORY_CUSTOM_ALIAS( className, factoryName, createFunc ) \ - static vgui::CBuildFactoryHelper g_##factoryName##_Helper( #factoryName, createFunc );\ - className *g_##factoryName##LinkerHack = NULL; - -} // namespace vgui - - -#endif // MESSAGEMAP_H diff --git a/public/vgui_controls/PHandle.h b/public/vgui_controls/PHandle.h deleted file mode 100644 index 18d7302b5..000000000 --- a/public/vgui_controls/PHandle.h +++ /dev/null @@ -1,86 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PHANDLE_H -#define PHANDLE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include - -namespace vgui -{ - -class Panel; - -//----------------------------------------------------------------------------- -// Purpose: Safe pointer class for handling Panel or derived panel classes -//----------------------------------------------------------------------------- -class PHandle -{ -public: - PHandle() : m_iPanelID(INVALID_PANEL) {} //m_iSerialNumber(0), m_pListEntry(0) {} - - Panel *Get(); - Panel *Set( Panel *pPanel ); - Panel *Set( HPanel hPanel ); - - operator Panel *() { return Get(); } - Panel * operator ->() { return Get(); } - Panel * operator = (Panel *pPanel) { return Set(pPanel); } - - bool operator == (Panel *pPanel) { return (Get() == pPanel); } - operator bool () { return Get() != 0; } - -private: - HPanel m_iPanelID; -}; - -//----------------------------------------------------------------------------- -// Purpose: Safe pointer class to just convert between VPANEL's and PHandle -//----------------------------------------------------------------------------- -class VPanelHandle -{ -public: - VPanelHandle() : m_iPanelID(INVALID_PANEL) {} - - VPANEL Get(); - VPANEL Set( VPANEL pPanel ); - - operator VPANEL () { return Get(); } - VPANEL operator = (VPANEL pPanel) { return Set(pPanel); } - - bool operator == (VPANEL pPanel) { return (Get() == pPanel); } - operator bool () { return Get() != 0; } - -private: - HPanel m_iPanelID; -}; - -//----------------------------------------------------------------------------- -// Purpose: DHANDLE is a templated version of PHandle -//----------------------------------------------------------------------------- -template< class PanelType > -class DHANDLE : public PHandle -{ -public: - PanelType *Get() { return (PanelType *)PHandle::Get(); } - PanelType *Set( PanelType *pPanel ) { return (PanelType *)PHandle::Set(pPanel); } - PanelType *Set( HPanel hPanel ) { return (PanelType *)PHandle::Set(hPanel); } - - operator PanelType *() { return (PanelType *)PHandle::Get(); } - PanelType * operator ->() { return (PanelType *)PHandle::Get(); } - PanelType * operator = (PanelType *pPanel) { return (PanelType *)PHandle::Set(pPanel); } - bool operator == (Panel *pPanel) { return (PHandle::Get() == pPanel); } - operator bool () { return PHandle::Get() != NULL; } -}; - -}; - -#endif // PHANDLE_H diff --git a/public/vgui_controls/Panel.h b/public/vgui_controls/Panel.h deleted file mode 100644 index c9468ae4e..000000000 --- a/public/vgui_controls/Panel.h +++ /dev/null @@ -1,745 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef PANEL_H -#define PANEL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/utlflags.h" -#include "vgui/VGUI.h" -#include "vgui/Dar.h" -#include "vgui_controls/MessageMap.h" -#if defined( VGUI_USEKEYBINDINGMAPS ) -#include "vgui_controls/KeyBindingMap.h" -#endif -#include "vgui/IClientPanel.h" -#include "vgui/IScheme.h" -#include "vgui_controls/Controls.h" -#include "vgui_controls/PHandle.h" -#include "vgui_controls/PanelAnimationVar.h" -#include "Color.h" -#include "vstdlib/IKeyValuesSystem.h" -#include "tier1/utlsymbol.h" -#include "vgui_controls/BuildGroup.h" - -// undefine windows function macros that overlap -#ifdef PostMessage -#undef PostMessage -#endif - -#ifdef SetCursor -#undef SetCursor -#endif - -class CUtlBuffer; - -namespace vgui -{ - -#if !defined( _X360 ) -#define VGUI_USEDRAGDROP 1 -#endif - -#if defined( VGUI_USEKEYBINDINGMAPS ) -struct PanelKeyBindingMap; -#endif -//----------------------------------------------------------------------------- -// Purpose: Helper functions to construct vgui panels -// -// SETUP_PANEL - will make a panel ready for use right now (i.e setup its colors, borders, fonts, etc) -// -template< class T > -inline T *SETUP_PANEL(T *panel) -{ - panel->MakeReadyForUse(); - return panel; -} - -// -// CREATE_PANEL - creates a panel that is ready to use right now -// -// example of use = to set the FG Color of a panel inside of a constructor (i.e before ApplySchemeSettings() has been run on the child) -// -#define CREATE_PANEL(type, parent, name) (SETUP_PANEL(new type(parent, name))) - -//----------------------------------------------------------------------------- -// Purpose: Drag/drop support context info (could defined within Panel...) -//----------------------------------------------------------------------------- -#if defined( VGUI_USEDRAGDROP ) -struct DragDrop_t; -class Menu; -#endif - -//----------------------------------------------------------------------------- -// Purpose: Macro to handle Colors that can be overridden in .res files -//----------------------------------------------------------------------------- -struct OverridableColorEntry -{ - char const *name() { return m_pszScriptName; } - - char const *m_pszScriptName; - Color *m_pColor; - Color m_colFromScript; - bool m_bOverridden; -}; - -#define REGISTER_COLOR_AS_OVERRIDABLE( name, scriptname ) \ - AddToOverridableColors( &name, scriptname ); - - - -//----------------------------------------------------------------------------- -// Purpose: For hudanimations.txt scripting of vars -//----------------------------------------------------------------------------- -class IPanelAnimationPropertyConverter -{ -public: - virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) = 0; - virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) = 0; - virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry ) = 0; -}; - -#if defined( VGUI_USEKEYBINDINGMAPS ) -enum KeyBindingContextHandle_t -{ - INVALID_KEYBINDINGCONTEXT_HANDLE = 0xffffffff, -}; -#endif -//----------------------------------------------------------------------------- -// Purpose: Base interface to all vgui windows -// All vgui controls that receive message and/or have a physical presence -// on screen are be derived from Panel. -// This is designed as an easy-access to the vgui-functionality; for more -// low-level access to vgui functions use the IPanel/IClientPanel interfaces directly -//----------------------------------------------------------------------------- -class Panel : public IClientPanel -{ - DECLARE_CLASS_SIMPLE_NOBASE( Panel ); - -public: - // For property mapping - static void InitPropertyConverters( void ); - static void AddPropertyConverter( char const *typeName, IPanelAnimationPropertyConverter *converter ); - - //----------------------------------------------------------------------------- - // CONSTRUCTORS - // these functions deal with the creation of the Panel - // the Panel automatically gets a handle to a vgui-internal panel, the ipanel(), upon construction - // vgui interfaces deal only with ipanel(), not Panel directly - Panel(); - Panel(Panel *parent); - Panel(Panel *parent, const char *panelName); - Panel(Panel *parent, const char *panelName, HScheme scheme); - - virtual ~Panel(); - - // returns pointer to Panel's vgui VPanel interface handle - virtual VPANEL GetVPanel() { return _vpanel; } - HPanel ToHandle() const; - - //----------------------------------------------------------------------------- - // PANEL METHODS - // these functions all manipulate panels - // they cannot be derived from - void SetName(const char *panelName); // sets the name of the panel - used as an identifier - const char *GetName(); // returns the name of this panel... never NULL - const char *GetClassName(); // returns the class name of the panel (eg. Panel, Label, Button, etc.) - - void MakeReadyForUse(); // fully construct this panel so its ready for use right now (i.e fonts loaded, colors set, default label text set, ...) - - // panel position & size - // all units are in pixels - void SetPos(int x,int y); // sets position of panel, in local space (ie. relative to parent's position) - void GetPos(int &x,int &y); // gets local position of panel - void SetSize(int wide,int tall); // sets size of panel - void GetSize(int &wide, int &tall); // gets size of panel - void SetBounds(int x, int y, int wide, int tall); // combination of SetPos/SetSize - void GetBounds(int &x, int &y, int &wide, int &tall); // combination of GetPos/GetSize - int GetWide(); // returns width of panel - void SetWide(int wide); // sets width of panel - int GetTall(); // returns height of panel - void SetTall(int tall); // sets height of panel - void SetMinimumSize(int wide,int tall); // sets the minimum size the panel can go - void GetMinimumSize(int& wide,int& tall); // gets the minimum size - bool IsBuildModeEditable(); // editable in the buildModeDialog? - void SetBuildModeEditable(bool state); // set buildModeDialog editable - bool IsBuildModeDeletable(); // deletable in the buildModeDialog? - void SetBuildModeDeletable(bool state); // set buildModeDialog deletable - bool IsBuildModeActive(); // true if we're currently in edit mode - void SetZPos(int z); // sets Z ordering - lower numbers are always behind higher z's - int GetZPos( void ); - void SetAlpha(int alpha); // sets alpha modifier for panel and all child panels [0..255] - int GetAlpha(); // returns the current alpha - - // panel visibility - // invisible panels and their children do not drawn, updated, or receive input messages - virtual void SetVisible(bool state); - virtual bool IsVisible(); - - // painting - virtual VPANEL IsWithinTraverse(int x, int y, bool traversePopups); // recursive; returns a pointer to the panel at those coordinates - MESSAGE_FUNC( Repaint, "Repaint" ); // marks the panel as needing to be repainted - virtual void PostMessage(VPANEL target, KeyValues *message, float delaySeconds = 0.0f); - - bool IsWithin(int x, int y); //in screen space - void LocalToScreen(int &x, int &y); - void ScreenToLocal(int &x, int &y); - void ParentLocalToScreen(int &x, int &y); - void MakePopup(bool showTaskbarIcon = true,bool disabled = false); // turns the panel into a popup window (ie. can draw outside of it's parents space) - virtual void OnMove(); - - // panel hierarchy - virtual Panel *GetParent(); - virtual VPANEL GetVParent(); - virtual void SetParent(Panel *newParent); - virtual void SetParent(VPANEL newParent); - virtual bool HasParent(VPANEL potentialParent); - - int GetChildCount(); - Panel *GetChild(int index); - int FindChildIndexByName( const char *childName ); - Panel *FindChildByName(const char *childName, bool recurseDown = false); - Panel *FindSiblingByName(const char *siblingName); - void CallParentFunction(KeyValues *message); - - virtual void SetAutoDelete(bool state); // if set to true, panel automatically frees itself when parent is deleted - virtual bool IsAutoDeleteSet(); - virtual void DeletePanel(); // simply does a { delete this; } - - // messaging - virtual void AddActionSignalTarget(Panel *messageTarget); - virtual void AddActionSignalTarget(VPANEL messageTarget); - virtual void RemoveActionSignalTarget(Panel *oldTarget); - virtual void PostActionSignal(KeyValues *message); // sends a message to the current actionSignalTarget(s) - virtual bool RequestInfoFromChild(const char *childName, KeyValues *outputData); - virtual void PostMessageToChild(const char *childName, KeyValues *messsage); - virtual void PostMessage(Panel *target, KeyValues *message, float delaySeconds = 0.0f); - virtual bool RequestInfo(KeyValues *outputData); // returns true if output is successfully written. You should always chain back to the base class if info request is not handled - virtual bool SetInfo(KeyValues *inputData); // sets a specified value in the control - inverse of the above - virtual void SetSilentMode( bool bSilent ); //change the panel's silent mode; if silent, the panel will not post any action signals - - // drawing state - virtual void SetEnabled(bool state); - virtual bool IsEnabled(); - virtual bool IsPopup(); // has a parent, but is in it's own space - virtual void GetClipRect(int &x0, int &y0, int &x1, int &y1); - virtual void MoveToFront(); - - // pin positions for auto-layout - enum PinCorner_e - { - PIN_TOPLEFT = 0, - PIN_TOPRIGHT, - PIN_BOTTOMLEFT, - PIN_BOTTOMRIGHT, - }; - - // specifies the auto-resize directions for the panel - enum AutoResize_e - { - AUTORESIZE_NO = 0, - AUTORESIZE_RIGHT, - AUTORESIZE_DOWN, - AUTORESIZE_DOWNANDRIGHT, - }; - - // Sets the pin corner for non-resizing panels - void SetPinCorner( PinCorner_e pinCorner, int nOffsetX, int nOffsetY ); - - // Sets the pin corner + resize mode for resizing panels - void SetAutoResize( PinCorner_e pinCorner, AutoResize_e resizeDir, int nPinOffsetX, int nPinOffsetY, int nUnpinnedCornerOffsetX, int nUnpinnedCornerOffsetY ); - - AutoResize_e GetAutoResize(); - PinCorner_e GetPinCorner(); - - // Gets the relative offset of the control from the pinned + non-pinned corner (for resizing) - void GetPinOffset( int &dx, int &dy ); - void GetResizeOffset( int &dx, int &dy ); - - // colors - virtual void SetBgColor(Color color); - virtual void SetFgColor(Color color); - virtual Color GetBgColor(); - virtual Color GetFgColor(); - - virtual void SetCursor(HCursor cursor); - virtual HCursor GetCursor(); - virtual void RequestFocus(int direction = 0); - virtual bool HasFocus(); - virtual void InvalidateLayout(bool layoutNow = false, bool reloadScheme = false); - virtual bool RequestFocusPrev(VPANEL panel = NULL); - virtual bool RequestFocusNext(VPANEL panel = NULL); - // tab positioning - virtual void SetTabPosition(int position); - virtual int GetTabPosition(); - // border - virtual void SetBorder(IBorder *border); - virtual IBorder *GetBorder(); - virtual void SetPaintBorderEnabled(bool state); - virtual void SetPaintBackgroundEnabled(bool state); - virtual void SetPaintEnabled(bool state); - virtual void SetPostChildPaintEnabled(bool state); - virtual void SetPaintBackgroundType(int type); // 0 for normal(opaque), 1 for single texture from Texture1, and 2 for rounded box w/ four corner textures - virtual void GetInset(int &left, int &top, int &right, int &bottom); - virtual void GetPaintSize(int &wide, int &tall); - virtual void SetBuildGroup(BuildGroup *buildGroup); - virtual bool IsBuildGroupEnabled(); - virtual bool IsCursorNone(); - virtual bool IsCursorOver(); // returns true if the cursor is currently over the panel - virtual void MarkForDeletion(); // object will free it's memory next tick - virtual bool IsLayoutInvalid(); // does this object require a perform layout? - virtual Panel *HasHotkey(wchar_t key); // returns the panel that has this hotkey - virtual bool IsOpaque(); - bool IsRightAligned(); // returns true if the settings are aligned to the right of the screen - bool IsBottomAligned(); // returns true if the settings are aligned to the bottom of the screen - - // scheme access functions - virtual HScheme GetScheme(); - virtual void SetScheme(const char *tag); - virtual void SetScheme(HScheme scheme); - virtual Color GetSchemeColor(const char *keyName,IScheme *pScheme); - virtual Color GetSchemeColor(const char *keyName, Color defaultColor,IScheme *pScheme); - - // called when scheme settings need to be applied; called the first time before the panel is painted - virtual void ApplySchemeSettings(IScheme *pScheme); - - // interface to build settings - // takes a group of settings and applies them to the control - virtual void ApplySettings(KeyValues *inResourceData); - - // records the settings into the resource data - virtual void GetSettings(KeyValues *outResourceData); - - // gets a description of the resource for use in the UI - // format: ... - // unknown types as just displayed as strings in the UI (for future UI expansion) - virtual const char *GetDescription(); - - // returns the name of the module that this instance of panel was compiled into - virtual const char *GetModuleName(); - - // user configuration settings - // this is used for any control details the user wants saved between sessions - // eg. dialog positions, last directory opened, list column width - virtual void ApplyUserConfigSettings(KeyValues *userConfig); - - // returns user config settings for this control - virtual void GetUserConfigSettings(KeyValues *userConfig); - - // optimization, return true if this control has any user config settings - virtual bool HasUserConfigSettings(); - - // message handlers - // override to get access to the message - // override to get access to the message - virtual void OnMessage(const KeyValues *params, VPANEL fromPanel); // called when panel receives message; must chain back - MESSAGE_FUNC_CHARPTR( OnCommand, "Command", command ); // called when a panel receives a command - MESSAGE_FUNC( OnMouseCaptureLost, "MouseCaptureLost" ); // called after the panel loses mouse capture - MESSAGE_FUNC( OnSetFocus, "SetFocus" ); // called after the panel receives the keyboard focus - MESSAGE_FUNC( OnKillFocus, "KillFocus" ); // called after the panel loses the keyboard focus - MESSAGE_FUNC( OnDelete, "Delete" ); // called to delete the panel; Panel::OnDelete() does simply { delete this; } - virtual void OnThink(); // called every frame before painting, but only if panel is visible - virtual void OnChildAdded(VPANEL child); // called when a child has been added to this panel - virtual void OnSizeChanged(int newWide, int newTall); // called after the size of a panel has been changed - - // called every frame if ivgui()->AddTickSignal() is called - MESSAGE_FUNC( OnTick, "Tick" ); - - // input messages - MESSAGE_FUNC_INT_INT( OnCursorMoved, "OnCursorMoved", x, y ); - virtual void OnCursorEntered(); - virtual void OnCursorExited(); - virtual void OnMousePressed(MouseCode code); - virtual void OnMouseDoublePressed(MouseCode code); - virtual void OnMouseReleased(MouseCode code); - virtual void OnMouseWheeled(int delta); - - // Trip pressing (e.g., select all text in a TextEntry) requires this to be enabled - virtual void SetTriplePressAllowed( bool state ); - virtual bool IsTriplePressAllowed() const; - virtual void OnMouseTriplePressed( MouseCode code ); - - static char const *KeyCodeToString( KeyCode code ); - static wchar_t const *KeyCodeToDisplayString( KeyCode code ); - static wchar_t const *KeyCodeModifiersToDisplayString( KeyCode code, int modifiers ); // L"Ctrl+Alt+Shift+Backspace" - - static KeyCode StringToKeyCode( char const *str ); -#if defined( VGUI_USEKEYBINDINGMAPS ) - static KeyBindingContextHandle_t CreateKeyBindingsContext( char const *filename, char const *pathID = 0 ); - virtual void SetKeyBindingsContext( KeyBindingContextHandle_t handle ); - virtual KeyBindingContextHandle_t GetKeyBindingsContext() const; - virtual bool IsValidKeyBindingsContext() const; - - static int GetPanelsWithKeyBindingsCount( KeyBindingContextHandle_t handle ); - static Panel *GetPanelWithKeyBindings( KeyBindingContextHandle_t handle, int index ); - - static void RevertKeyBindings( KeyBindingContextHandle_t handle ); - - static void ReloadKeyBindings( KeyBindingContextHandle_t handle ); - static void SaveKeyBindings( KeyBindingContextHandle_t handle ); - static void SaveKeyBindingsToFile( KeyBindingContextHandle_t handle, char const *filename, char const *pathID = 0 ); - static void LoadKeyBindings( KeyBindingContextHandle_t handle ); - static void LoadKeyBindingsForOnePanel( KeyBindingContextHandle_t handle, Panel *panelOfInterest ); - - // OnKeyCodeTyped hooks into here for action - virtual bool IsKeyRebound( KeyCode code, int modifiers ); - // If a panel implements this and returns true, then the IsKeyRebound check will fail and OnKeyCodeTyped messages will pass through.. - // sort of like setting the SetAllowKeyBindingChainToParent flag to false for specific keys - virtual bool IsKeyOverridden( KeyCode code, int modifiers ); - - virtual void AddKeyBinding( char const *bindingName, int keycode, int modifiers ); - - KeyBindingMap_t *LookupBinding( char const *bindingName ); - KeyBindingMap_t *LookupBindingByKeyCode( KeyCode code, int modifiers ); - void LookupBoundKeys( char const *bindingName, CUtlVector< BoundKey_t * >& list ); - BoundKey_t *LookupDefaultKey( char const *bindingName ); - PanelKeyBindingMap *LookupMapForBinding( char const *bindingName ); - - // Returns the number of keybindings - int GetKeyMappingCount( ); - - void RevertKeyBindingsToDefault(); - void RemoveAllKeyBindings(); - void ReloadKeyBindings(); - virtual void EditKeyBindings(); - - // calls RevertKeyBindingsToDefault() and then LoadKeyBindingsForOnePanel( GetKeyBindingsContext(), this ); - void SaveKeyBindingsToBuffer( int level, CUtlBuffer& buf ); - bool ParseKeyBindings( KeyValues *kv ); - - virtual char const *GetKeyBindingsFile() const; - virtual char const *GetKeyBindingsFilePathID() const; - - // Set this to false to disallow IsKeyRebound chaining to GetParent() Panels... - void SetAllowKeyBindingChainToParent( bool state ); - bool IsKeyBindingChainToParentAllowed() const; -#endif // VGUI_USEKEYBINDINGMAPS - - // base implementation forwards Key messages to the Panel's parent - // - override to 'swallow' the input - virtual void OnKeyCodePressed(KeyCode code); - virtual void OnKeyCodeTyped(KeyCode code); - virtual void OnKeyTyped(wchar_t unichar); - virtual void OnKeyCodeReleased(KeyCode code); - virtual void OnKeyFocusTicked(); // every window gets key ticked events - - // forwards mouse messages to the panel's parent - MESSAGE_FUNC( OnMouseFocusTicked, "OnMouseFocusTicked" ); - - // message handlers that don't go through the message pump - virtual void PaintBackground(); - virtual void Paint(); - virtual void PaintBorder(); - virtual void PaintBuildOverlay(); // the extra drawing for when in build mode - virtual void PostChildPaint(); - virtual void PerformLayout(); - - // this enables message mapping for this class - requires matching IMPLEMENT_PANELDESC() in the .cpp file - DECLARE_PANELMAP(); - - virtual VPANEL GetCurrentKeyFocus(); - - // returns a pointer to the tooltip object associated with the panel - // creates a new one if none yet exists - Tooltip *GetTooltip(); - - // proportional mode settings - virtual bool IsProportional() { return _flags.IsFlagSet( IS_PROPORTIONAL ); } - virtual void SetProportional(bool state); - - // input interest - virtual void SetMouseInputEnabled( bool state ); - virtual void SetKeyBoardInputEnabled( bool state ); - virtual bool IsMouseInputEnabled(); - virtual bool IsKeyBoardInputEnabled(); - - virtual void DrawTexturedBox( int x, int y, int wide, int tall, Color color, float normalizedAlpha ); - virtual void DrawBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha, bool hollow = false ); - virtual void DrawBoxFade(int x, int y, int wide, int tall, Color color, float normalizedAlpha, unsigned int alpha0, unsigned int alpha1, bool bHorizontal, bool hollow = false ); - virtual void DrawHollowBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha ); - -// Drag Drop Public interface - - virtual void SetDragEnabled( bool enabled ); - virtual bool IsDragEnabled() const; - - // Called if drag drop is started but not dropped on top of droppable panel... - virtual void OnDragFailed( CUtlVector< KeyValues * >& msglist ); - - // Use this to prevent chaining up from a parent which can mess with mouse functionality if you don't want to chain up from a child panel to the best - // draggable parent. - virtual void SetBlockDragChaining( bool block ); - virtual bool IsBlockingDragChaining() const; - - virtual int GetDragStartTolerance() const; - virtual void SetDragSTartTolerance( int nTolerance ); - - // If hover context time is non-zero, then after the drop cursor is hovering over the panel for that amount of time - // the Show hover context menu function will be invoked - virtual void SetDropEnabled( bool enabled, float m_flHoverContextTime = 0.0f ); - virtual bool IsDropEnabled() const; - - // Called if m_flHoverContextTime was non-zero, allows droppee to preview the drop data and show an appropriate menu - // Return false if not using context menu - virtual bool GetDropContextMenu( Menu *menu, CUtlVector< KeyValues * >& msglist ); - virtual void OnDropContextHoverShow( CUtlVector< KeyValues * >& msglist ); - virtual void OnDropContextHoverHide( CUtlVector< KeyValues * >& msglist ); - -#if defined( VGUI_USEDRAGDROP ) - virtual DragDrop_t *GetDragDropInfo(); -#endif - // For handling multiple selections... - virtual void OnGetAdditionalDragPanels( CUtlVector< Panel * >& dragabbles ); - - virtual void OnCreateDragData( KeyValues *msg ); - // Called to see if a drop enabled panel can accept the specified data blob - virtual bool IsDroppable( CUtlVector< KeyValues * >& msglist ); - - // Mouse is on draggable panel and has started moving, but is not over a droppable panel yet - virtual void OnDraggablePanelPaint(); - // Mouse is now over a droppable panel - virtual void OnDroppablePanelPaint( CUtlVector< KeyValues * >& msglist, CUtlVector< Panel * >& dragPanels ); - - virtual void OnPanelDropped( CUtlVector< KeyValues * >& msglist ); - - // called on droptarget when draggable panel entered/exited droptarget - virtual void OnPanelEnteredDroppablePanel( CUtlVector< KeyValues * >& msglist ); - virtual void OnPanelExitedDroppablePanel ( CUtlVector< KeyValues * >& msglist ); - - // Chains up to any parent marked DropEnabled - virtual Panel *GetDropTarget( CUtlVector< KeyValues * >& msglist ); - // Chains up to first parent marked DragEnabled - virtual Panel *GetDragPanel(); - virtual bool IsBeingDragged(); - virtual HCursor GetDropCursor( CUtlVector< KeyValues * >& msglist ); - - Color GetDropFrameColor(); - Color GetDragFrameColor(); - - // Can override to require custom behavior to start the drag state - virtual bool CanStartDragging( int startx, int starty, int mx, int my ); - - // Draws a filled rect of specified bounds, but omits the bounds of the skip panel from those bounds - virtual void FillRectSkippingPanel( Color& clr, int x, int y, int w, int h, Panel *skipPanel ); - - virtual int GetPaintBackgroundType(); - virtual void GetCornerTextureSize( int& w, int& h ); - - bool IsChildOfModalSubTree(); - bool IsChildOfSurfaceModalPanel(); - - bool ShouldHandleInputMessage(); - - virtual void SetSkipChildDuringPainting( Panel *child ); - - // If this is set, then the drag drop won't occur until the mouse leaves the drag panels current rectangle - void SetStartDragWhenMouseExitsPanel( bool state ); - bool IsStartDragWhenMouseExitsPanel() const; - - void DisableMouseInputForThisPanel( bool bDisable ); - bool IsMouseInputDisabledForThisPanel() const; - -// Drag Drop protected/internal interface -protected: - - virtual void OnStartDragging(); - virtual void OnContinueDragging(); - virtual void OnFinishDragging( bool mousereleased, MouseCode code, bool aborted = false ); - - virtual void DragDropStartDragging(); - - virtual void GetDragData( CUtlVector< KeyValues * >& list ); - virtual void CreateDragData(); - - virtual void PaintTraverse(bool Repaint, bool allowForce = true); - -protected: - MESSAGE_FUNC_ENUM_ENUM( OnRequestFocus, "OnRequestFocus", VPANEL, subFocus, VPANEL, defaultPanel); - MESSAGE_FUNC_INT_INT( OnScreenSizeChanged, "OnScreenSizeChanged", oldwide, oldtall ); - virtual void *QueryInterface(EInterfaceID id); - - void AddToOverridableColors( Color *pColor, char const *scriptname ) - { - int iIdx = m_OverridableColorEntries.AddToTail(); - m_OverridableColorEntries[iIdx].m_pszScriptName = scriptname; - m_OverridableColorEntries[iIdx].m_pColor = pColor; - m_OverridableColorEntries[iIdx].m_bOverridden = false; - } - - void ApplyOverridableColors( void ); - void SetOverridableColor( Color *pColor, Color &newColor ); - -private: - enum BuildModeFlags_t - { - BUILDMODE_EDITABLE = 0x01, - BUILDMODE_DELETABLE = 0x02, - BUILDMODE_SAVE_XPOS_RIGHTALIGNED = 0x04, - BUILDMODE_SAVE_XPOS_CENTERALIGNED = 0x08, - BUILDMODE_SAVE_YPOS_BOTTOMALIGNED = 0x10, - BUILDMODE_SAVE_YPOS_CENTERALIGNED = 0x20, - BUILDMODE_SAVE_WIDE_FULL = 0x40, - }; - - enum PanelFlags_t - { - MARKED_FOR_DELETION = 0x0001, - NEEDS_REPAINT = 0x0002, - PAINT_BORDER_ENABLED = 0x0004, - PAINT_BACKGROUND_ENABLED = 0x0008, - PAINT_ENABLED = 0x0010, - POST_CHILD_PAINT_ENABLED = 0x0020, - AUTODELETE_ENABLED = 0x0040, - NEEDS_LAYOUT = 0x0080, - NEEDS_SCHEME_UPDATE = 0x0100, - NEEDS_DEFAULT_SETTINGS_APPLIED = 0x0200, -#if defined( VGUI_USEKEYBINDINGMAPS ) - ALLOW_CHAIN_KEYBINDING_TO_PARENT = 0x0400, -#endif - IN_PERFORM_LAYOUT = 0x0800, - IS_PROPORTIONAL = 0x1000, - TRIPLE_PRESS_ALLOWED = 0x2000, - DRAG_REQUIRES_PANEL_EXIT = 0x4000, - IS_MOUSE_DISABLED_FOR_THIS_PANEL_ONLY = 0x8000, - ALL_FLAGS = 0xFFFF, - }; - - // used to get the Panel * for users with only IClientPanel - virtual Panel *GetPanel() { return this; } - - // private methods - void Think(); - void PerformApplySchemeSettings(); - - void InternalPerformLayout(); - void InternalSetCursor(); - - MESSAGE_FUNC_INT_INT( InternalCursorMoved, "CursorMoved", xpos, ypos ); - MESSAGE_FUNC( InternalCursorEntered, "CursorEntered" ); - MESSAGE_FUNC( InternalCursorExited, "CursorExited" ); - - MESSAGE_FUNC_INT( InternalMousePressed, "MousePressed", code ); - MESSAGE_FUNC_INT( InternalMouseDoublePressed, "MouseDoublePressed", code ); - // Triple presses are synthesized - MESSAGE_FUNC_INT( InternalMouseTriplePressed, "MouseTriplePressed", code ); - MESSAGE_FUNC_INT( InternalMouseReleased, "MouseReleased", code ); - MESSAGE_FUNC_INT( InternalMouseWheeled, "MouseWheeled", delta ); - MESSAGE_FUNC_INT( InternalKeyCodePressed, "KeyCodePressed", code ); - MESSAGE_FUNC_INT( InternalKeyCodeTyped, "KeyCodeTyped", code ); - MESSAGE_FUNC_INT( InternalKeyTyped, "KeyTyped", unichar ); - MESSAGE_FUNC_INT( InternalKeyCodeReleased, "KeyCodeReleased", code ); - - MESSAGE_FUNC( InternalKeyFocusTicked, "KeyFocusTicked" ); - MESSAGE_FUNC( InternalMouseFocusTicked, "MouseFocusTicked" ); - - MESSAGE_FUNC( InternalInvalidateLayout, "Invalidate" ); - - MESSAGE_FUNC( InternalMove, "Move" ); - virtual void InternalFocusChanged(bool lost); // called when the focus gets changed - - void Init( int x, int y, int wide, int tall ); - void PreparePanelMap( PanelMap_t *panelMap ); - - bool InternalRequestInfo( PanelAnimationMap *map, KeyValues *outputData ); - bool InternalSetInfo( PanelAnimationMap *map, KeyValues *inputData ); - - PanelAnimationMapEntry *FindPanelAnimationEntry( char const *scriptname, PanelAnimationMap *map ); - - // Recursively invoke settings for PanelAnimationVars - void InternalApplySettings( PanelAnimationMap *map, KeyValues *inResourceData); - void InternalInitDefaultValues( PanelAnimationMap *map ); - - // Purpose: Loads panel details related to autoresize from the resource info - void ApplyAutoResizeSettings(KeyValues *inResourceData); - - void FindDropTargetPanel_R( CUtlVector< VPANEL >& panelList, int x, int y, VPANEL check ); - Panel *FindDropTargetPanel(); - -#if defined( VGUI_USEDRAGDROP ) - DragDrop_t *m_pDragDrop; - Color m_clrDragFrame; - Color m_clrDropFrame; -#endif - - Tooltip *m_pTooltips; - - PHandle m_SkipChild; - long m_lLastDoublePressTime; - HFont m_infoFont; - -#if defined( VGUI_USEKEYBINDINGMAPS ) - KeyBindingContextHandle_t m_hKeyBindingsContext; -#endif - - // data - VPANEL _vpanel; // handle to a vgui panel - char *_panelName; // string name of the panel - only unique within the current context - IBorder *_border; - - CUtlFlags< unsigned short > _flags; // see PanelFlags_t - Dar _actionSignalTargetDar; // the panel to direct notify messages to ("Command", "TextChanged", etc.) - - CUtlVector m_OverridableColorEntries; - - Color _fgColor; // foreground color - Color _bgColor; // background color - - HBuildGroup _buildGroup; - - short m_nPinDeltaX; // Relative position of the pinned corner to the edge - short m_nPinDeltaY; - short m_nResizeDeltaX; // Relative position of the non-pinned corner to the edge - short m_nResizeDeltaY; - - HCursor _cursor; - unsigned short _buildModeFlags; // flags that control how the build mode dialog handles this panel - - byte _pinCorner : 4; // the corner of the dialog this panel is pinned to - byte _autoResizeDirection : 4; // the directions in which the panel will auto-resize to - - unsigned char _tabPosition; // the panel's place in the tab ordering - HScheme m_iScheme; // handle to the scheme to use - - bool m_bIsSilent; // should this panel PostActionSignals? - - CPanelAnimationVar( float, m_flAlpha, "alpha", "255" ); - - // 1 == Textured (TextureId1 only) - // 2 == Rounded Corner Box - CPanelAnimationVar( int, m_nPaintBackgroundType, "PaintBackgroundType", "0" ); - CPanelAnimationVarAliasType( int, m_nBgTextureId1, "Texture1", "vgui/hud/800corner1", "textureid" ); - CPanelAnimationVarAliasType( int, m_nBgTextureId2, "Texture2", "vgui/hud/800corner2", "textureid" ); - CPanelAnimationVarAliasType( int, m_nBgTextureId3, "Texture3", "vgui/hud/800corner3", "textureid" ); - CPanelAnimationVarAliasType( int, m_nBgTextureId4, "Texture4", "vgui/hud/800corner4", "textureid" ); - - friend class Panel; - friend class BuildGroup; - friend class BuildModeDialog; - friend class PHandle; - - // obselete, remove soon - void OnOldMessage(KeyValues *params, VPANEL ifromPanel); -}; - -inline void Panel::DisableMouseInputForThisPanel( bool bDisable ) -{ - _flags.SetFlag( IS_MOUSE_DISABLED_FOR_THIS_PANEL_ONLY, bDisable ); -} - -inline bool Panel::IsMouseInputDisabledForThisPanel() const -{ - return _flags.IsFlagSet( IS_MOUSE_DISABLED_FOR_THIS_PANEL_ONLY ); -} - - -} // namespace vgui - - -#endif // PANEL_H diff --git a/public/vgui_controls/PanelAnimationVar.h b/public/vgui_controls/PanelAnimationVar.h deleted file mode 100644 index fb52ec2ac..000000000 --- a/public/vgui_controls/PanelAnimationVar.h +++ /dev/null @@ -1,161 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef PANELANIMATIONVAR_H -#define PANELANIMATIONVAR_H -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/utlvector.h" -#include - -#define DECLARE_PANELANIMATION( className ) \ - static void AddToAnimationMap( char const *scriptname, char const *type, char const *var, \ - char const *defaultvalue, bool array, PANELLOOKUPFUNC func ) \ - { \ - PanelAnimationMap *map = FindOrAddPanelAnimationMap( GetPanelClassName() ); \ - \ - PanelAnimationMapEntry entry; \ - entry.m_pszScriptName = scriptname; \ - entry.m_pszVariable = var; \ - entry.m_pszType = type; \ - entry.m_pszDefaultValue = defaultvalue; \ - entry.m_pfnLookup = func; \ - entry.m_bArray = array; \ - \ - map->entries.AddToTail( entry ); \ - } \ - \ - static void ChainToAnimationMap( void ) \ - { \ - static bool chained = false; \ - if ( chained ) \ - return; \ - chained = true; \ - PanelAnimationMap *map = FindOrAddPanelAnimationMap( GetPanelClassName() ); \ - map->pfnClassName = GetPanelClassName; \ - if ( map && GetPanelBaseClassName() && GetPanelBaseClassName()[0] ) \ - { \ - map->baseMap = FindOrAddPanelAnimationMap( GetPanelBaseClassName() ); \ - } \ - } \ - \ - class className##_Register; \ - friend class className##_Register; \ - class className##_Register \ - { \ - public: \ - className##_Register() \ - { \ - className::ChainToAnimationMap(); \ - } \ - }; \ - className##_Register m_RegisterAnimationClass; \ - \ - virtual PanelAnimationMap *GetAnimMap() \ - { \ - return FindOrAddPanelAnimationMap( GetPanelClassName() ); \ - } - -typedef void *( *PANELLOOKUPFUNC )( vgui::Panel *panel ); - -// Use this macro to define a variable which hudanimations.txt and hudlayout.res scripts can access -#define CPanelAnimationVarAliasType( type, name, scriptname, defaultvalue, typealias ) \ - class PanelAnimationVar_##name; \ - friend class PanelAnimationVar_##name; \ - static void *GetVar_##name( vgui::Panel *panel ) \ - { \ - return &(( ThisClass *)panel)->name; \ - } \ - class PanelAnimationVar_##name \ - { \ - public: \ - static void InitVar() \ - { \ - static bool bAdded = false; \ - if ( !bAdded ) \ - { \ - bAdded = true; \ - AddToAnimationMap( scriptname, typealias, #name, defaultvalue, false, ThisClass::GetVar_##name ); \ - } \ - } \ - PanelAnimationVar_##name() \ - { \ - PanelAnimationVar_##name::InitVar(); \ - } \ - }; \ - PanelAnimationVar_##name m_##name##_register; \ - type name; - -#define CPanelAnimationVar( type, name, scriptname, defaultvalue ) \ - CPanelAnimationVarAliasType( type, name, scriptname, defaultvalue, #type ) - -// Use this macro to define a variable which hudanimations.txt and hudlayout.res scripts can access -#define CPanelAnimationStringVarAliasType( count, name, scriptname, defaultvalue, typealias ) \ - class PanelAnimationVar_##name; \ - friend class PanelAnimationVar_##name; \ - static void *GetVar_##name( vgui::Panel *panel ) \ - { \ - return &(( ThisClass *)panel)->name; \ - } \ - class PanelAnimationVar_##name \ - { \ - public: \ - static void InitVar() \ - { \ - static bool bAdded = false; \ - if ( !bAdded ) \ - { \ - bAdded = true; \ - AddToAnimationMap( scriptname, typealias, #name, defaultvalue, true, ThisClass::GetVar_##name ); \ - } \ - } \ - PanelAnimationVar_##name() \ - { \ - PanelAnimationVar_##name::InitVar(); \ - } \ - }; \ - PanelAnimationVar_##name m_##name##_register; \ - char name[ count ]; - -#define CPanelAnimationStringVar( count, name, scriptname, defaultvalue ) \ - CPanelAnimationStringVarAliasType( count, name, scriptname, defaultvalue, "string" ) - -struct PanelAnimationMapEntry -{ - char const *name() { return m_pszScriptName; } - char const *type() { return m_pszType; } - char const *defaultvalue() { return m_pszDefaultValue; } - bool isarray() { return m_bArray; } - - char const *m_pszScriptName; - char const *m_pszVariable; - char const *m_pszType; - char const *m_pszDefaultValue; - bool m_bArray; - - PANELLOOKUPFUNC m_pfnLookup; -}; - -struct PanelAnimationMap -{ - PanelAnimationMap() - { - baseMap = NULL; - pfnClassName = NULL; - } - - CUtlVector< PanelAnimationMapEntry > entries; - PanelAnimationMap *baseMap; - char const *(*pfnClassName)( void ); -}; - -PanelAnimationMap *FindPanelAnimationMap( char const *className ); -PanelAnimationMap *FindOrAddPanelAnimationMap( char const *className ); -void PanelAnimationDumpVars( char const *className ); - -#endif // PANELANIMATIONVAR_H diff --git a/public/vgui_controls/PanelListPanel.h b/public/vgui_controls/PanelListPanel.h deleted file mode 100644 index db4412f33..000000000 --- a/public/vgui_controls/PanelListPanel.h +++ /dev/null @@ -1,115 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PANELLISTPANEL_H -#define PANELLISTPANEL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include -#include - -class KeyValues; - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: A list of variable height child panels -// each list item consists of a label-panel pair. Height of the item is -// determined from the lable. -//----------------------------------------------------------------------------- -class PanelListPanel : public Panel -{ - DECLARE_CLASS_SIMPLE( PanelListPanel, Panel ); - -public: - PanelListPanel( vgui::Panel *parent, char const *panelName ); - ~PanelListPanel(); - - // DATA & ROW HANDLING - // The list now owns the panel - virtual int AddItem( Panel *labelPanel, Panel *panel ); - int GetItemCount() const; - int GetItemIDFromRow( int nRow ) const; - - // Iteration. Use these until they return InvalidItemID to iterate all the items. - int FirstItem() const; - int NextItem( int nItemID ) const; - int InvalidItemID() const; - - virtual Panel *GetItemLabel(int itemID); - virtual Panel *GetItemPanel(int itemID); - - virtual void RemoveItem(int itemID); // removes an item from the table (changing the indices of all following items) - virtual void DeleteAllItems(); // clears and deletes all the memory used by the data items - void RemoveAll(); - - // painting - virtual vgui::Panel *GetCellRenderer( int row ); - - // layout - void SetFirstColumnWidth( int width ); - int GetFirstColumnWidth(); - void SetNumColumns( int iNumColumns ); - int GetNumColumns( void ); - void MoveScrollBarToTop(); - - // selection - void SetSelectedPanel( Panel *panel ); - Panel *GetSelectedPanel(); - /* - On a panel being selected, a message gets sent to it - "PanelSelected" int "state" - where state is 1 on selection, 0 on deselection - */ - - void SetVerticalBufferPixels( int buffer ); - - void ScrollToItem( int itemNumber ); - -protected: - // overrides - virtual void OnSizeChanged(int wide, int tall); - MESSAGE_FUNC_INT( OnSliderMoved, "ScrollBarSliderMoved", position ); - virtual void PerformLayout(); - virtual void ApplySchemeSettings(vgui::IScheme *pScheme); - virtual void OnMouseWheeled(int delta); - -private: - int ComputeVPixelsNeeded(); - - enum { DEFAULT_HEIGHT = 24, PANELBUFFER = 5 }; - - typedef struct dataitem_s - { - // Always store a panel pointer - Panel *panel; - Panel *labelPanel; - } DATAITEM; - - // list of the column headers - - CUtlLinkedList m_DataItems; - CUtlVector m_SortedItems; - - ScrollBar *m_vbar; - Panel *m_pPanelEmbedded; - - PHandle m_hSelectedItem; - int m_iFirstColumnWidth; - int m_iNumColumns; - int m_iDefaultHeight; - int m_iPanelBuffer; -}; - -} -#endif // PANELLISTPANEL_H diff --git a/public/vgui_controls/PerforceFileExplorer.h b/public/vgui_controls/PerforceFileExplorer.h deleted file mode 100644 index af5a88b90..000000000 --- a/public/vgui_controls/PerforceFileExplorer.h +++ /dev/null @@ -1,67 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: Allows you to browse a directory structure, showing perforce files -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef PERFORCEFILEEXPLORER_H -#define PERFORCEFILEEXPLORER_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "tier1\utlstring.h" -#include "vgui_controls/Frame.h" - - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class PerforceFileList; -class ComboBox; -class Button; - - -//----------------------------------------------------------------------------- -// Contains a list of files, determines their perforce status -//----------------------------------------------------------------------------- -class PerforceFileExplorer : public vgui::Frame -{ - DECLARE_CLASS_SIMPLE( PerforceFileExplorer, Frame ); - -public: - // The context keyvalues are added to all messages sent by this dialog if they are specified - PerforceFileExplorer( Panel *parent, const char *pPanelName ); - ~PerforceFileExplorer(); - - // Inherited from Frame - virtual void ApplySchemeSettings( IScheme *pScheme ); - virtual void PerformLayout(); - -protected: - MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", kv ); - MESSAGE_FUNC( OnItemDoubleClicked, "ItemDoubleClicked" ); - MESSAGE_FUNC( OnFolderUp, "FolderUp" ); - - void PopulateFileList(); - void PopulateDriveList(); - - // Returns the current directory - void SetCurrentDirectory( const char *pCurrentDirectory ); - - Button *m_pFolderUpButton; - ComboBox *m_pFullPathCombo; - PerforceFileList *m_pFileList; - CUtlString m_CurrentDirectory; -}; - - -} // namespace vgui - -#endif // PERFORCEFILEEXPLORER_H diff --git a/public/vgui_controls/PerforceFileList.h b/public/vgui_controls/PerforceFileList.h deleted file mode 100644 index efc69118d..000000000 --- a/public/vgui_controls/PerforceFileList.h +++ /dev/null @@ -1,114 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: Contains a list of files, determines their perforce status -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef PERFORCEFILELIST_H -#define PERFORCEFILELIST_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier1/utlstring.h" -#include "tier1/utlstringmap.h" -#include "vgui_controls/ListPanel.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -struct P4File_t; - -namespace vgui -{ - class ListPanel; -} - - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Contains a list of files, determines their perforce status -//----------------------------------------------------------------------------- -class PerforceFileList : public vgui::ListPanel -{ - DECLARE_CLASS_SIMPLE( PerforceFileList, ListPanel ); - -public: - // The context keyvalues are added to all messages sent by this dialog if they are specified - PerforceFileList( Panel *parent, const char *pPanelName ); - ~PerforceFileList(); - - // Add a file to the file list. Note that this file may exist on disk or not - // and it may exist in perforce or not. It's specified as a full path on disk though. - // In the case where a file doesn't exist on disk, but it does exist in perforce - // specify where that file would appear on disk. - // This function returns the itemID of the added file - // If you already know the file exists or is a directory (or not), specify that in the call. - // -1 means autodetect whether the file exists or is a directory - int AddFile( const char *pFullPath, int nFileExists = -1, int nIsDirectory = -1 ); - - // Is a file already in the list? - bool IsFileInList( const char *pFullPath ); - - // Find the item ID associated with a particular file - int FindFile( const char *pFullPath ); - - // Remove all files from the list - void RemoveAllFiles(); - - // Refresh perforce information - void Refresh(); - - // Refresh perforce information manually - void RefreshPerforceState( int nItemID, bool bFileExists, P4File_t *pFileInfo ); - - // Is a particular list item a directory? - bool IsDirectoryItem( int nItemID ); - - // Returns the file associated with a particular item ID - const char *GetFile( int nItemID ); - - // Toggle showing deleted files or not - void ShowDeletedFiles( bool bShowDeletedFiles ); - - // Inherited from vgui::EditablePanel - virtual void ApplySchemeSettings( IScheme *pScheme ); - virtual void OnMouseDoublePressed( MouseCode code ); - - /* - messages sent: - "ItemDoubleClicked" // Called when an item is double-clicked - */ - -protected: - struct DirectoryInfo_t - { - CUtlString m_ClientSpec; - CUtlVector< int > m_ItemIDs; - }; - - // Add a file to the file list. - int AddFileToFileList( const char *pFullPath, bool bExistsOnDisk ); - - // Add a directory to the file list. - int AddDirectoryToFileList( const char *pFullPath, bool bExistsOnDisk ); - - // Add a directory to the directory list, returns client spec - void AddItemToDirectoryList( const char *pFullPath, int nItemID, bool bIsDirectory ); - - // Used to look up directories -> client specs - CUtlStringMap< DirectoryInfo_t > m_Directories; - - // Show deleted files? - bool m_bShowDeletedFiles; -}; - - -} // namespace vgui - -#endif // PERFORCEFILELIST_H diff --git a/public/vgui_controls/ProgressBar.h b/public/vgui_controls/ProgressBar.h deleted file mode 100644 index 26c5bf57b..000000000 --- a/public/vgui_controls/ProgressBar.h +++ /dev/null @@ -1,100 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PROGRESSBAR_H -#define PROGRESSBAR_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Status bar that visually displays discrete progress in the form -// of a segmented strip -//----------------------------------------------------------------------------- -class ProgressBar : public Panel -{ - DECLARE_CLASS_SIMPLE( ProgressBar, Panel ); - -public: - ProgressBar(Panel *parent, const char *panelName); - ~ProgressBar(); - - // 'progress' is in the range [0.0f, 1.0f] - MESSAGE_FUNC_FLOAT( SetProgress, "SetProgress", progress ); - float GetProgress(); - virtual void SetSegmentInfo( int gap, int width ); - - // utility function for calculating a time remaining string - static bool ConstructTimeRemainingString(wchar_t *output, int outputBufferSizeInBytes, float startTime, float currentTime, float currentProgress, float lastProgressUpdateTime, bool addRemainingSuffix); - - void SetBarInset( int pixels ); - int GetBarInset( void ); - - virtual void ApplySettings(KeyValues *inResourceData); - virtual void GetSettings(KeyValues *outResourceData); - virtual const char *GetDescription(); - - // returns the number of segment blocks drawn - int GetDrawnSegmentCount(); - - enum ProgressDir_e - { - PROGRESS_EAST, - PROGRESS_WEST, - PROGRESS_NORTH, - PROGRESS_SOUTH - }; - - int GetProgressDirection() const { return m_iProgressDirection; } - void SetProgressDirection( int val ) { m_iProgressDirection = val; } - -protected: - virtual void Paint(); - void PaintSegment( int &x, int &y, int tall, int wide ); - virtual void PaintBackground(); - virtual void ApplySchemeSettings(IScheme *pScheme); - MESSAGE_FUNC_PARAMS( OnDialogVariablesChanged, "DialogVariables", dialogVariables ); - /* CUSTOM MESSAGE HANDLING - "SetProgress" - input: "progress" - float value of the progress to set - */ - -protected: - int m_iProgressDirection; - float _progress; - -private: - int _segmentCount; - int _segmentGap; - int _segmentWide; - int m_iBarInset; - char *m_pszDialogVar; -}; - -//----------------------------------------------------------------------------- -// Purpose: Non-segmented progress bar -//----------------------------------------------------------------------------- -class ContinuousProgressBar : public ProgressBar -{ - DECLARE_CLASS_SIMPLE( ContinuousProgressBar, ProgressBar ); - -public: - ContinuousProgressBar(Panel *parent, const char *panelName); - - virtual void Paint(); -}; - -} // namespace vgui - -#endif // PROGRESSBAR_H diff --git a/public/vgui_controls/ProgressBox.h b/public/vgui_controls/ProgressBox.h deleted file mode 100644 index 65ea1457b..000000000 --- a/public/vgui_controls/ProgressBox.h +++ /dev/null @@ -1,99 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PROGRESSBOX_H -#define PROGRESSBOX_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -// prevent windows macros from messing with the class -#ifdef ProgressBox -#undef ProgressBox -#endif - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Popup discardable message box -//----------------------------------------------------------------------------- -class ProgressBox : public Frame -{ - DECLARE_CLASS_SIMPLE( ProgressBox, Frame ); - -public: - // title - Text to be displayed in the title bar of the window - // text - Text message in the message box - // parent - parent panel of the message box, by default it has no parent. - ProgressBox(const char *title, const char *text, const char *pszUnknownTimeString, Panel *parent = NULL); - ProgressBox(const wchar_t *wszTitle, const wchar_t *wszText, const wchar_t *wszUnknownTimeString, Panel *parent = NULL); - ~ProgressBox(); - - // Put the message box into a modal state - virtual void DoModal(Frame *pFrameOver = NULL); - - // make the message box appear and in a modeless state - virtual void ShowWindow(Frame *pFrameOver = NULL); - - // updates progress bar, range [0, 1] - virtual void SetProgress(float progress); - - // sets the info text - virtual void SetText(const char *text); - - // toggles visibility of the close box. - virtual void SetCancelButtonVisible(bool state); - - // toggles the enabled state of the cancel button (for if it needs to be disabled part way through a process) - virtual void SetCancelButtonEnabled(bool state); - - /* custom messages: - - "ProgressBoxCancelled" - sent if the user pressed the cancel button (must be enabled & visible for this to happen) - - */ - -protected: - virtual void PerformLayout(); - virtual void OnClose(); - virtual void OnCloseFrameButtonPressed(); - virtual void ApplySchemeSettings(IScheme *pScheme); - virtual void OnThink(); - virtual void OnCommand(const char *command); - virtual void OnTick(); - - // called when the update has been cancelled - virtual void OnCancel(); - -private: - MESSAGE_FUNC( OnShutdownRequest, "ShutdownRequest" ); - void Init(); - void UpdateTitle(); - - Label *m_pMessageLabel; - ProgressBar *m_pProgressBar; - Button *m_pCancelButton; - - wchar_t m_wszTitleString[128]; - wchar_t m_wcsInfoString[128]; - wchar_t m_wszUnknownTimeString[128]; - - float m_flFirstProgressUpdate; - float m_flLastProgressUpdate; - float m_flCurrentProgress; -}; - -} // namespace vgui - - -#endif // PROGRESSBOX_H diff --git a/public/vgui_controls/PropertyDialog.h b/public/vgui_controls/PropertyDialog.h deleted file mode 100644 index 2c3d14496..000000000 --- a/public/vgui_controls/PropertyDialog.h +++ /dev/null @@ -1,84 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PROPERTYDIALOG_H -#define PROPERTYDIALOG_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Simple frame that holds a property sheet -//----------------------------------------------------------------------------- -class PropertyDialog : public Frame -{ - DECLARE_CLASS_SIMPLE( PropertyDialog, Frame ); - -public: - PropertyDialog(Panel *parent, const char *panelName); - ~PropertyDialog(); - - // returns a pointer to the PropertySheet this dialog encapsulates - virtual PropertySheet *GetPropertySheet(); - - // wrapper for PropertySheet interface - virtual void AddPage(Panel *page, const char *title); - virtual Panel *GetActivePage(); - virtual void ResetAllData(); - virtual void ApplyChanges(); - - // sets the text on the OK/Cancel buttons, overriding the default - void SetOKButtonText(const char *text); - void SetCancelButtonText(const char *text); - void SetApplyButtonText(const char *text); - - // changes the visibility of the buttons - void SetOKButtonVisible(bool state); - void SetCancelButtonVisible(bool state); - void SetApplyButtonVisible(bool state); - - /* MESSAGES SENT - "ResetData" - sent when page is loaded. Data should be reloaded from document into controls. - "ApplyChanges" - sent when the OK / Apply button is pressed. Changed data should be written into document. - */ - -protected: - // Called when the OK button is pressed. Simply closes the dialog. - virtual bool OnOK(bool applyOnly); - - // called when the Cancel button is pressed - virtual void OnCancel(); - - // vgui overrides - virtual void PerformLayout(); - virtual void OnCommand(const char *command); - virtual void ActivateBuildMode(); - virtual void OnKeyCodeTyped(KeyCode code); - virtual void RequestFocus(int direction = 0); - - MESSAGE_FUNC( OnApplyButtonEnable, "ApplyButtonEnable" ); - void EnableApplyButton(bool bEnable); - -private: - PropertySheet *_propertySheet; - Button *_okButton; - Button *_cancelButton; - Button *_applyButton; - - CPanelAnimationVar( int, m_iSheetInsetBottom, "sheetinset_bottom", "32" ); -}; - -}; // vgui - -#endif // PROPERTYDIALOG_H diff --git a/public/vgui_controls/PropertyPage.h b/public/vgui_controls/PropertyPage.h deleted file mode 100644 index 7faedfec0..000000000 --- a/public/vgui_controls/PropertyPage.h +++ /dev/null @@ -1,58 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PROPERTYPAGE_H -#define PROPERTYPAGE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Property page, as held by a set of property sheets -//----------------------------------------------------------------------------- -class PropertyPage : public EditablePanel -{ - DECLARE_CLASS_SIMPLE( PropertyPage, EditablePanel ); - -public: - PropertyPage(Panel *parent, const char *panelName); - ~PropertyPage(); - - // Called when page is loaded. Data should be reloaded from document into controls. - MESSAGE_FUNC( OnResetData, "ResetData" ); - - // Called when the OK / Apply button is pressed. Changed data should be written into document. - MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); - - // called when the page is shown/hidden - MESSAGE_FUNC( OnPageShow, "PageShow" ); - MESSAGE_FUNC( OnPageHide, "PageHide" ); - - virtual void OnKeyCodeTyped(KeyCode code); - virtual bool HasUserConfigSettings() { return true; } - - virtual void SetVisible(bool state); - -protected: - // called to be notified of the tab button used to Activate this page - // if overridden this must be chained back to - MESSAGE_FUNC_PTR( OnPageTabActivated, "PageTabActivated", panel ); - -private: - PHandle _pageTab; -}; - -} // namespace vgui - -#endif // PROPERTYPAGE_H diff --git a/public/vgui_controls/PropertySheet.h b/public/vgui_controls/PropertySheet.h deleted file mode 100644 index 8b46b4f00..000000000 --- a/public/vgui_controls/PropertySheet.h +++ /dev/null @@ -1,189 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PROPERTYSHEET_H -#define PROPERTYSHEET_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "vgui/VGUI.h" -#include "vgui_controls/EditablePanel.h" -#include "vgui_controls/PHandle.h" -#include "utlvector.h" - -namespace vgui -{ - -class PageTab; -class ImagePanel; - -//----------------------------------------------------------------------------- -// Purpose: Tabbed property sheet. Holds and displays a set of Panel's -//----------------------------------------------------------------------------- -class PropertySheet : public EditablePanel -{ - DECLARE_CLASS_SIMPLE( PropertySheet, EditablePanel ); - -public: - PropertySheet(Panel *parent, const char *panelName, bool draggableTabs = false ); - PropertySheet(Panel *parent, const char *panelName,ComboBox *combo); - ~PropertySheet(); - - virtual bool IsDraggableTab() const; - void SetDraggableTabs( bool state ); - - // Adds a page to the sheet. The first page added becomes the active sheet. - virtual void AddPage(Panel *page, const char *title, char const *imageName = NULL, bool showContextMenu = false ); - - // sets the current page - virtual void SetActivePage(Panel *page); - - // sets the width, in pixels, of the page tab buttons. - virtual void SetTabWidth(int pixels); - - // Gets a pointer to the currently active page. - virtual Panel *GetActivePage(); - - // Removes (but doesn't delete) all pages - virtual void RemoveAllPages(); - - // reloads the data in all the property page - virtual void ResetAllData(); - - // writes out any changed data to the doc - virtual void ApplyChanges(); - - // focus handling - passed on to current active page - virtual void RequestFocus(int direction = 0); - virtual bool RequestFocusPrev(VPANEL panel = NULL); - virtual bool RequestFocusNext(VPANEL panel = NULL); - - // returns the ith panel - virtual Panel *GetPage(int i); - - // deletes this panel from the sheet - virtual void DeletePage(Panel *panel); - // removes this panel from the sheet, sets its parent to NULL, but does not delete it - virtual void RemovePage(Panel *panel); - - // returns the current activated tab - virtual Panel *GetActiveTab(); - - // returns the title text of the tab - virtual void GetActiveTabTitle(char *textOut, int bufferLen); - - // returns the title of tab "i" - virtual bool GetTabTitle(int i,char *textOut, int bufferLen); - - // returns the index of the active page - virtual int GetActivePageNum(); - - // returns the number of pages in the sheet - virtual int GetNumPages(); - - // disable the page with title "title" - virtual void DisablePage(const char *title); - - // enable the page with title "title" - virtual void EnablePage(const char *title); - - virtual void SetSmallTabs( bool state ); - virtual bool IsSmallTabs() const; - - /* MESSAGES SENT TO PAGES - "PageShow" - sent when a page is shown - "PageHide" - sent when a page is hidden - "ResetData" - sent when the data should be reloaded from doc - "ApplyChanges" - sent when data should be written to doc - */ - - virtual void OnPanelDropped( CUtlVector< KeyValues * >& msglist ); - virtual bool IsDroppable( CUtlVector< KeyValues * >& msglist ); - // Mouse is now over a droppable panel - virtual void OnDroppablePanelPaint( CUtlVector< KeyValues * >& msglist, CUtlVector< Panel * >& dragPanels ); - - void ShowContextButtons( bool state ); - bool ShouldShowContextButtons() const; - - int FindPage( Panel *page ) const; - - bool PageHasContextMenu( Panel *page ) const; - - void SetKBNavigationEnabled( bool state ); - bool IsKBNavigationEnabled() const; - - virtual bool HasUserConfigSettings() { return true; } - -protected: - virtual void PaintBorder(); - virtual void PerformLayout(); - virtual Panel *HasHotkey(wchar_t key); - virtual void ChangeActiveTab(int index); - virtual void OnKeyCodeTyped(KeyCode code); - virtual void OnCommand(const char *command); - virtual void ApplySchemeSettings(IScheme *pScheme); - virtual void ApplySettings(KeyValues *inResourceData); - - // internal message handlers - MESSAGE_FUNC_PTR( OnTabPressed, "TabPressed", panel ); - MESSAGE_FUNC_PTR_WCHARPTR( OnTextChanged, "TextChanged", panel, text ); - MESSAGE_FUNC_PARAMS( OnOpenContextMenu, "OpenContextMenu", params ); - MESSAGE_FUNC( OnApplyButtonEnable, "ApplyButtonEnable" ); - // called when default button has been set - MESSAGE_FUNC_HANDLE( OnDefaultButtonSet, "DefaultButtonSet", button ); - // called when the current default button has been set - MESSAGE_FUNC_HANDLE( OnCurrentDefaultButtonSet, "CurrentDefaultButtonSet", button); - MESSAGE_FUNC( OnFindDefaultButton, "FindDefaultButton" ); - -private: - - // enable/disable the page with title "title" - virtual void SetPageEnabled(const char *title,bool state); - - struct Page_t - { - Page_t() : - page( 0 ), - contextMenu( false ) - { - } - - Panel *page; - bool contextMenu; - }; - - CUtlVector m_Pages; - CUtlVector m_PageTabs; - Panel *_activePage; - PageTab *_activeTab; - int _tabWidth; - int _activeTabIndex; - ComboBox *_combo; - bool _showTabs; - bool _tabFocus; - - PHandle m_hPreviouslyActivePage; - float m_flPageTransitionEffectTime; - bool m_bSmallTabs; - HFont m_tabFont; - bool m_bDraggableTabs; - bool m_bContextButton; - bool m_bKBNavigationEnabled; - - CPanelAnimationVarAliasType( int, m_iTabXIndent, "tabxindent", "0", "proportional_int" ); - CPanelAnimationVarAliasType( int, m_iTabXDelta, "tabxdelta", "0", "proportional_int" ); - CPanelAnimationVarAliasType( int, m_iTabHeight, "tabheight", "28", "proportional_int" ); - CPanelAnimationVarAliasType( int, m_iTabHeightSmall, "tabheight_small", "14", "proportional_int" ); - - KeyValues *m_pTabKV; -}; - -}; // namespace vgui - -#endif // PROPERTYSHEET_H diff --git a/public/vgui_controls/QueryBox.h b/public/vgui_controls/QueryBox.h deleted file mode 100644 index 123819ccf..000000000 --- a/public/vgui_controls/QueryBox.h +++ /dev/null @@ -1,61 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Creates a Message box with a question in it and yes/no buttons -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef QUERYBOX_H -#define QUERYBOX_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Creates A Message box with a question in it and yes/no buttons -//----------------------------------------------------------------------------- -class QueryBox : public MessageBox -{ - DECLARE_CLASS_SIMPLE( QueryBox, MessageBox ); - -public: - QueryBox(const char *title, const char *queryText,vgui::Panel *parent = NULL ); - QueryBox(const wchar_t *wszTitle, const wchar_t *wszQueryText,vgui::Panel *parent = NULL); - ~QueryBox(); - - // Layout the window for drawing - virtual void PerformLayout(); - - // Set the keyvalues to send when ok button is hit - void SetOKCommand(KeyValues *keyValues); - - // Set the keyvalues to send when the cancel button is hit - void SetCancelCommand(KeyValues *keyValues); - - // Set the text on the Cancel button - void SetCancelButtonText(const char *buttonText); - void SetCancelButtonText(const wchar_t *wszButtonText); - - // Set a value of the ok command - void SetOKCommandValue(const char *keyName, int value); - -protected: - virtual void OnKeyCodeTyped(KeyCode code); - virtual void OnCommand(const char *command); - Button *m_pCancelButton; - -private: - KeyValues *m_pCancelCommand; - KeyValues *m_pOkCommand; -}; - -} -#endif // QUERYBOX_H diff --git a/public/vgui_controls/RadioButton.h b/public/vgui_controls/RadioButton.h deleted file mode 100644 index d4e963c09..000000000 --- a/public/vgui_controls/RadioButton.h +++ /dev/null @@ -1,75 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef RADIOBUTTON_H -#define RADIOBUTTON_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -class RadioImage; - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Radio buttons are automatically selected into groups by who their -// parent is. At most one radio button is active at any time. -//----------------------------------------------------------------------------- -class RadioButton : public ToggleButton -{ - DECLARE_CLASS_SIMPLE( RadioButton, ToggleButton ); - -public: - RadioButton(Panel *parent, const char *panelName, const char *text); - ~RadioButton(); - - // Set the radio button checked. When a radio button is checked, a - // message is sent to all other radio buttons in the same group so - // they will become unchecked. - virtual void SetSelected(bool state); - - // Get the tab position of the radio button with the set of radio buttons - // A group of RadioButtons must have the same TabPosition, with [1, n] subtabpositions - virtual int GetSubTabPosition(); - virtual void SetSubTabPosition(int position); - - // Return the RadioButton's real tab position (its Panel one changes) - virtual int GetRadioTabPosition(); - -protected: - virtual void DoClick(); - - virtual void Paint(); - virtual void ApplySchemeSettings(IScheme *pScheme); - MESSAGE_FUNC_INT( OnRadioButtonChecked, "RadioButtonChecked", tabposition); - virtual void OnKeyCodeTyped(KeyCode code); - - virtual IBorder *GetBorder(bool depressed, bool armed, bool selected, bool keyfocus); - - virtual void ApplySettings(KeyValues *inResourceData); - virtual void GetSettings(KeyValues *outResourceData); - virtual const char *GetDescription(); - virtual void PerformLayout(); - - RadioButton *FindBestRadioButton(int direction); - -private: - RadioImage *_radioBoxImage; - int _oldTabPosition; - Color _selectedFgColor; - - int _subTabPosition; // tab position with the radio button list -}; - -}; // namespace vgui - -#endif // RADIOBUTTON_H diff --git a/public/vgui_controls/RichText.h b/public/vgui_controls/RichText.h deleted file mode 100644 index 1948d280a..000000000 --- a/public/vgui_controls/RichText.h +++ /dev/null @@ -1,285 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef RICHTEXT_H -#define RICHTEXT_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -namespace vgui -{ - -class ClickPanel; - -//----------------------------------------------------------------------------- -// Purpose: Non-editable display of a rich text control -//----------------------------------------------------------------------------- -class RichText : public Panel -{ - DECLARE_CLASS_SIMPLE( RichText, Panel ); - -public: - RichText(Panel *parent, const char *panelName); - ~RichText(); - - // text manipulation - void SetText(const char *text); - void SetText(const wchar_t *text); - void GetText(int offset, wchar_t *buf, int bufLenInBytes); - void GetText(int offset, char *pch, int bufLenInBytes); - - // configuration - void SetFont(HFont font); - - // inserts characters at the end of the stream - void InsertChar(wchar_t ch); - void InsertString(const char *text); - void InsertString(const wchar_t *wszText); - - // selection - void SelectNone(); - void SelectAllText(); - void SelectNoText(); - MESSAGE_FUNC( CutSelected, "DoCutSelected" ); - MESSAGE_FUNC( CopySelected, "DoCopySelected" ); - - // sets the RichText control interactive or not (meaning you can select/copy text in the window) - void SetPanelInteractive( bool bInteractive ){ m_bInteractive = bInteractive; } - - // sets the RichText scrollbar invisible if it's not going to be used - void SetUnusedScrollbarInvisible( bool bInvis ){ m_bUnusedScrollbarInvis = bInvis; } - - // cursor movement - void GotoTextStart(); // go to start of text buffer - void GotoTextEnd(); // go to end of text buffer - - // configuration - // sets visibility of scrollbar - void SetVerticalScrollbar(bool state); - // sets limit of number of characters insertable into field; set to -1 to remove maximum - // only works with if rich-edit is NOT enabled - void SetMaximumCharCount(int maxChars); - - // rich edit commands - void InsertColorChange(Color col); - // IndentChange doesn't take effect until the next newline character - void InsertIndentChange(int pixelsIndent); - // clickable text - // notification that text was clicked is through "TextClicked" message - void InsertClickableTextStart( const char *pchClickAction = NULL ); - void InsertClickableTextEnd(); - // inserts a string that needs to be scanned for urls/mailto commands to be made clickable - void InsertPossibleURLString(const char *text, Color URLTextColor, Color normalTextColor); - - void InsertFade( float flSustain, float flLength ); - - void ResetAllFades( bool bHold, bool bOnlyExpired = false, float flNewSustain = -1.0f ); - - // sets the height of the window so all text is visible. - // used by tooltips - void SetToFullHeight(); - int GetNumLines(); - - /* CUSTOM MESSAGE HANDLING - "SetText" - input: "text" - text is set to be this string - */ - - /* MESSAGE SENDING (to action signal targets) - "TextChanged" - sent when the text is edited by the user - - - "TextClicked" - sent when clickable text has been clicked on - "text" - the text that was clicked on - */ - - virtual bool RequestInfo(KeyValues *outputData); - /* INFO HANDLING - "GetText" - returns: - "text" - text contained in the text box - */ - virtual void SetFgColor( Color color ); - virtual void SetDrawOffsets( int ofsx, int ofsy ); - bool IsScrollbarVisible(); - - void SetUnderlineFont( HFont font ); - -protected: - virtual void OnThink(); - virtual void PerformLayout(); // layout the text in the window - virtual void ApplySchemeSettings(IScheme *pScheme); - virtual void Paint(); - - virtual void ApplySettings( KeyValues *inResourceData ); - virtual void GetSettings( KeyValues *outResourceData ); - virtual const char *GetDescription( void ); - MESSAGE_FUNC_WCHARPTR( OnSetText, "SetText", text ); - MESSAGE_FUNC( OnSliderMoved, "ScrollBarSliderMoved" ); // respond to scroll bar events - virtual void OnKillFocus(); - virtual void OnMouseWheeled(int delta); // respond to mouse wheel events - virtual void OnKeyCodeTyped(KeyCode code); //respond to keyboard events - - MESSAGE_FUNC_INT( OnClickPanel, "ClickPanel", index); - - virtual void OnCursorMoved(int x, int y); // respond to moving the cursor with mouse button down - virtual void OnMousePressed(MouseCode code); // respond to mouse down events - virtual void OnMouseDoublePressed(MouseCode code); - virtual void OnMouseReleased(MouseCode code); // respond to mouse up events - - virtual void OnMouseFocusTicked(); // do while window has mouse focus - virtual void OnCursorEntered(); // handle cursor entering window - virtual void OnCursorExited(); // handle cursor exiting window - - virtual void OnMouseCaptureLost(); - virtual void OnSizeChanged(int newWide, int newTall); - virtual void OnSetFocus(); - - // clickable url handling - int ParseTextStringForUrls(const char *text, int startPos, char *pchURLText, int cchURLText, char *pchURL, int cchURL, bool &clickable); - virtual void OnTextClicked(const wchar_t *text); - -#ifdef DBGFLAG_VALIDATE - virtual void Validate( CValidator &validator, char *pchName ); -#endif // DBGFLAG_VALIDATE - - void SetDrawTextOnly(); - -protected: - ScrollBar *_vertScrollBar; // the scroll bar used in the window - -private: - const wchar_t *ResolveLocalizedTextAndVariables( char const *pchLookup, wchar_t *outbuf, size_t outbufsizeinbytes ); - void CheckRecalcLineBreaks(); - - void GotoWordRight(); // move cursor to start of next word - void GotoWordLeft(); // move cursor to start of prev word - - void TruncateTextStream(); - bool GetSelectedRange(int& cx0,int& cx1); - void CursorToPixelSpace(int cursorPos, int &cx, int &cy); - int PixelToCursorSpace(int cx, int cy); - void AddAnotherLine(int &cx, int &cy); - void RecalculateDefaultState(int startIndex); - - void LayoutVerticalScrollBarSlider(); - void OpenEditMenu(); - void FinishingURL(int x, int y); - // Returns the character index the drawing should Start at - int GetStartDrawIndex(int &lineBreakIndexIndex); - int GetCursorLine(); - int GetClickableTextIndexStart(int startIndex); - void CreateEditMenu(); // create copy/cut/paste menu - - MESSAGE_FUNC_INT( MoveScrollBar, "MoveScrollBar", delta ); - MESSAGE_FUNC_INT( MoveScrollBarDirect, "MoveScrollBarDirect", delta ); - - // linebreak stream functions - void InvalidateLineBreakStream(); - void RecalculateLineBreaks(); - - struct TFade - { - float flFadeStartTime; - float flFadeLength; - float flFadeSustain; - int iOriginalAlpha; - }; - - // format stream - describes changes in formatting for the text stream - struct TFormatStream - { - // render state - Color color; - int pixelsIndent; - bool textClickable; - CUtlSymbol m_sClickableTextAction; - - TFade fade; - - // position in TextStream that these changes take effect - int textStreamIndex; - }; - - bool m_bResetFades; - bool m_bInteractive; - bool m_bUnusedScrollbarInvis; - - // data - CUtlVector m_TextStream; // the text in the text window is stored in this buffer - CUtlVector m_LineBreaks; // an array that holds the index in the buffer to wrap lines at - CUtlVector m_FormatStream; // list of format changes - - bool m_bRecalcLineBreaks; - - int _recalculateBreaksIndex; // tells next linebreakindex index to Start recalculating line breaks - bool _invalidateVerticalScrollbarSlider; - int _cursorPos; // the position in the text buffer of the blinking cursor - bool _mouseSelection; // whether we are highlighting text or not (selecting text) - bool _mouseDragSelection; // tells weather mouse is outside window and button is down so we select text - int _select[2]; // select[1] is the offset in the text to where the cursor is currently - // select[0] is the offset to where the cursor was dragged to. or -1 if no drag. - int _pixelsIndent; - int _maxCharCount; // max number of chars that can be in the text buffer - HFont _font; // font of chars in the text buffer - HFont m_hFontUnderline; - Color _selectionColor; - Color _selectionTextColor; // color of the highlighted text - bool _currentTextClickable; - CUtlVector _clickableTextPanels; - int _clickableTextIndex; - Color _defaultTextColor; - int _drawOffsetX; - int _drawOffsetY; - - Panel *m_pInterior; - - - // sub-controls - Menu *m_pEditMenu; // cut/copy/paste popup - - char *m_pszInitialText; // initial text - - // saved state - bool _recalcSavedRenderState; - - struct TRenderState - { - // rendering positions - int x, y; - - // basic state - Color textColor; - int pixelsIndent; - bool textClickable; - - // index into our current position in the formatting stream - int formatStreamIndex; - }; - TRenderState m_CachedRenderState; // cached render state for the beginning of painting - - // updates a render state based on the formatting and color streams - // returns true if any state changed - bool UpdateRenderState(int textStreamPos, TRenderState &renderState); - void CalculateFade( TRenderState &renderState ); - - void GenerateRenderStateForTextStreamIndex(int textStreamIndex, TRenderState &renderState); - int FindFormatStreamIndexForTextStreamPos(int textStreamIndex); - - // draws a string of characters with the same formatting using the current render state - int DrawString(int iFirst, int iLast, TRenderState &renderState, HFont font); -}; - -} // namespace vgui - - -#endif // RICHTEXT_H diff --git a/public/vgui_controls/RotatingProgressBar.h b/public/vgui_controls/RotatingProgressBar.h deleted file mode 100644 index 9bb931721..000000000 --- a/public/vgui_controls/RotatingProgressBar.h +++ /dev/null @@ -1,67 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef ROTATINGPROGRESSBAR_H -#define ROTATINGPROGRESSBAR_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include - -namespace vgui -{ - - //----------------------------------------------------------------------------- - // Purpose: Progress Bar that rotates an image around its center - //----------------------------------------------------------------------------- - class RotatingProgressBar : public ProgressBar - { - DECLARE_CLASS_SIMPLE( RotatingProgressBar, ProgressBar ); - - public: - RotatingProgressBar(Panel *parent, const char *panelName); - ~RotatingProgressBar(); - - virtual void ApplySettings(KeyValues *inResourceData); - virtual void ApplySchemeSettings(IScheme *pScheme); - - void SetImage( const char *imageName ); - - protected: - virtual void Paint(); - virtual void PaintBackground(); - virtual void OnTick(); - - private: - int m_nTextureId; - char *m_pszImageName; - - float m_flStartRadians; - float m_flEndRadians; - - float m_flLastAngle; - - float m_flTickDelay; - float m_flApproachSpeed; - - float m_flRotOriginX; - float m_flRotOriginY; - - float m_flRotatingX; - float m_flRotatingY; - float m_flRotatingWide; - float m_flRotatingTall; - - }; - -} // namespace vgui - -#endif // ROTATINGPROGRESSBAR_H diff --git a/public/vgui_controls/ScalableImagePanel.h b/public/vgui_controls/ScalableImagePanel.h deleted file mode 100644 index 7c822bc2e..000000000 --- a/public/vgui_controls/ScalableImagePanel.h +++ /dev/null @@ -1,54 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SCALABLEIMAGEPANEL_H -#define SCALABLEIMAGEPANEL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -namespace vgui -{ - //----------------------------------------------------------------------------- - // Purpose: 9-way Segmented background - //----------------------------------------------------------------------------- - class ScalableImagePanel : public Panel - { - DECLARE_CLASS_SIMPLE( ScalableImagePanel, Panel ); - public: - ScalableImagePanel(Panel *parent, const char *name); - - virtual void SetImage(const char *imageName); - - protected: - virtual void PaintBackground(); - virtual void GetSettings(KeyValues *outResourceData); - virtual void ApplySettings(KeyValues *inResourceData); - virtual void PerformLayout( void ); - virtual const char *GetDescription(); - - private: - int m_iSrcCornerHeight; // in pixels, how tall is the corner inside the image - int m_iSrcCornerWidth; // same for width - int m_iCornerHeight; // output size of the corner height in pixels - int m_iCornerWidth; // same for width - - int m_iTextureID; - - float m_flCornerWidthPercent; // corner width as percentage of image width - float m_flCornerHeightPercent; // same for height - - char *m_pszImageName; - }; - -} // namespace vgui - -#endif // SCALABLEIMAGEPANEL_H diff --git a/public/vgui_controls/ScrollBar.h b/public/vgui_controls/ScrollBar.h deleted file mode 100644 index fb708d712..000000000 --- a/public/vgui_controls/ScrollBar.h +++ /dev/null @@ -1,116 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SCROLLBAR_H -#define SCROLLBAR_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -namespace vgui -{ - -class Button; -class ScrollBarSlider; - -//----------------------------------------------------------------------------- -// Purpose: Generic scrollbar -// Uses Buttons & SliderBars for the main functionality -//----------------------------------------------------------------------------- -class ScrollBar : public Panel -{ - DECLARE_CLASS_SIMPLE( ScrollBar, Panel ); - -public: - ScrollBar(Panel *parent, const char *panelName, bool vertical); - - // Set the value of the scroll bar slider. - virtual void SetValue(int value); - - // Get the value of the scroll bar slider. - virtual int GetValue(); - - // Set the rangeof numbers the slider can scroll through - virtual void SetRange(int min,int max); - - virtual void GetRange(int &min, int &max); - - // Set how many lines are displayed at one time - // in the window the scroll bar is attached to. - virtual void SetRangeWindow(int rangeWindow); - - // Get how many lines are displayed at one time - // in the window the scroll bar is attached to. - virtual int GetRangeWindow(); - - // Check if the scrollbar is vertical or horizontal - virtual bool IsVertical(); - - // Purpose: Check if the slider can move through one or more pixels per - // unit of its range. - virtual bool HasFullRange(); - - // Setup the indexed scroll bar button with the input params. - virtual void SetButton(Button* button,int index); - // Return the indexed scroll bar button - virtual Button *GetButton(int index); - // Set up the slider. - virtual void SetSlider(ScrollBarSlider* slider); - // Return a pointer to the slider. - virtual ScrollBarSlider *GetSlider(); - // Set how far the scroll bar slider moves - // when a scroll bar button is pressed - virtual void SetButtonPressedScrollValue(int value); - - virtual void Validate(); - - // Update and look for clicks when mouse is in the scroll bar window. - virtual void OnMouseFocusTicked(); - - // Set the slider's Paint border enabled. - virtual void SetPaintBorderEnabled(bool state); - // Set the slider's Paint background enabled. - virtual void SetPaintBackgroundEnabled(bool state); - // Set the slider's Paint enabled. - virtual void SetPaintEnabled(bool state); - - // Sets the scrollbar buttons visible or not - virtual void SetScrollbarButtonsVisible(bool visible); - - void SetAutohideButtons( bool bAutohide ) { m_bAutoHideButtons = bAutohide; } - - /* MESSAGES SENT: - "ScrollBarSliderMoved" - "position" - new value of the slider - */ - -protected: - - virtual void PerformLayout(); - virtual void SendSliderMoveMessage(int value); - virtual void ApplySchemeSettings(IScheme *pScheme); - virtual void OnSizeChanged(int wide, int tall); - - MESSAGE_FUNC_INT( OnSliderMoved, "ScrollBarSliderMoved", position ); - virtual void RespondToScrollArrow(int const direction); - -private: - Button* _button[2]; - ScrollBarSlider* _slider; - int _buttonPressedScrollValue; - int _scrollDelay; // used to control delays in scrolling - bool _respond; - CPanelAnimationVar( bool, m_bAutoHideButtons, "autohide_buttons", "0" ); -}; - -} - -#endif // SCROLLBAR_H diff --git a/public/vgui_controls/ScrollBarSlider.h b/public/vgui_controls/ScrollBarSlider.h deleted file mode 100644 index 8a2942f4c..000000000 --- a/public/vgui_controls/ScrollBarSlider.h +++ /dev/null @@ -1,92 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef SCROLLBARSLIDER_H -#define SCROLLBARSLIDER_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -namespace vgui -{ - -class IBorder; - -//----------------------------------------------------------------------------- -// Purpose: ScrollBarSlider bar, as used in ScrollBar's -//----------------------------------------------------------------------------- -class ScrollBarSlider : public Panel -{ - DECLARE_CLASS_SIMPLE( ScrollBarSlider, Panel ); - -public: - ScrollBarSlider(Panel *parent, const char *panelName, bool vertical); - - // Set the ScrollBarSlider value of the nob. - virtual void SetValue(int value); - virtual int GetValue(); - - // Check whether the scroll bar is vertical or not - virtual bool IsVertical(); - - // Set max and min range of lines to display - virtual void SetRange(int min, int max); - - virtual void GetRange(int &min, int &max); - - // Set number of rows that can be displayed in window - virtual void SetRangeWindow(int rangeWindow); - - // Get number of rows that can be displayed in window - virtual int GetRangeWindow(); - - // Set the size of the ScrollBarSlider nob - virtual void SetSize(int wide, int tall); - - // Get current ScrollBarSlider bounds - virtual void GetNobPos(int &min, int &max); - - virtual bool HasFullRange(); - virtual void SetButtonOffset(int buttonOffset); - virtual void OnCursorMoved(int x, int y); - virtual void OnMousePressed(MouseCode code); - virtual void OnMouseDoublePressed(MouseCode code); - virtual void OnMouseReleased(MouseCode code); - - // Return true if this slider is actually drawing itself - virtual bool IsSliderVisible( void ); - -protected: - virtual void Paint(); - virtual void PaintBackground(); - virtual void PerformLayout(); - virtual void ApplySchemeSettings(IScheme *pScheme); - -private: - virtual void RecomputeNobPosFromValue(); - virtual void RecomputeValueFromNobPos(); - virtual void SendScrollBarSliderMovedMessage(); - - bool _vertical; - bool _dragging; - int _nobPos[2]; - int _nobDragStartPos[2]; - int _dragStartPos[2]; - int _range[2]; - int _value; // the position of the ScrollBarSlider, in coordinates as specified by SetRange/SetRangeWindow - int _rangeWindow; - int _buttonOffset; - IBorder *_ScrollBarSliderBorder; -}; - -} // namespace vgui - -#endif // SCROLLBARSLIDER_H diff --git a/public/vgui_controls/ScrollableEditablePanel.h b/public/vgui_controls/ScrollableEditablePanel.h deleted file mode 100644 index 1f3db496b..000000000 --- a/public/vgui_controls/ScrollableEditablePanel.h +++ /dev/null @@ -1,52 +0,0 @@ -//========= Copyright 1996-2001, Valve LLC, All rights reserved. ============ -// -// Purpose: -// -// $NoKeywords: $ -//============================================================================= - -#ifndef SCROLLABLEEDITABLEPANEL_H -#define SCROLLABLEEDITABLEPANEL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "vgui_controls/EditablePanel.h" - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -namespace vgui -{ - class ScrollBar; -} - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// An editable panel that has a scrollbar -//----------------------------------------------------------------------------- -class ScrollableEditablePanel : public vgui::EditablePanel -{ - DECLARE_CLASS_SIMPLE( ScrollableEditablePanel, vgui::EditablePanel ); - -public: - ScrollableEditablePanel( vgui::Panel *pParent, vgui::EditablePanel *pChild, const char *pName ); - virtual ~ScrollableEditablePanel() {} - virtual void PerformLayout(); - - vgui::ScrollBar *GetScrollbar( void ) { return m_pScrollBar; } - - MESSAGE_FUNC( OnScrollBarSliderMoved, "ScrollBarSliderMoved" ); - -private: - vgui::ScrollBar *m_pScrollBar; - vgui::EditablePanel *m_pChild; -}; - - -} // end namespace vgui - -#endif // SCROLLABLEEDITABLEPANEL_H diff --git a/public/vgui_controls/SectionedListPanel.h b/public/vgui_controls/SectionedListPanel.h deleted file mode 100644 index a751be3f2..000000000 --- a/public/vgui_controls/SectionedListPanel.h +++ /dev/null @@ -1,230 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SECTIONEDLISTPANEL_H -#define SECTIONEDLISTPANEL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include -#include -#include - -namespace vgui -{ - -class CSectionHeader; -class CItemButton; - -// sorting function, should return true if itemID1 should be displayed before itemID2 -typedef bool (*SectionSortFunc_t)(SectionedListPanel *list, int itemID1, int itemID2); - -//----------------------------------------------------------------------------- -// Purpose: List panel control that is divided up into discrete sections -//----------------------------------------------------------------------------- -class SectionedListPanel : public Panel -{ - DECLARE_CLASS_SIMPLE( SectionedListPanel, Panel ); - -public: - SectionedListPanel(vgui::Panel *parent, const char *name); - ~SectionedListPanel(); - - // adds a new section; returns false if section already exists - virtual void AddSection(int sectionID, const char *name, SectionSortFunc_t sortFunc = NULL); - virtual void AddSection(int sectionID, const wchar_t *name, SectionSortFunc_t sortFunc = NULL); - - // clears all the sections - leaves the items in place - virtual void RemoveAllSections(); - - // modifies section info - virtual void SetSectionFgColor(int sectionID, Color color); - // forces a section to always be visible - virtual void SetSectionAlwaysVisible(int sectionID, bool visible = true); - - // adds a new column to a section - enum ColumnFlags_e - { - HEADER_IMAGE = 0x01, // set if the header for the column is an image instead of text - COLUMN_IMAGE = 0x02, // set if the column contains an image instead of text (images are looked up by index from the ImageList) (see SetImageList below) - COLUMN_BRIGHT = 0x04, // set if the column text should be the bright color - COLUMN_CENTER = 0x08, // set to center the text/image in the column - COLUMN_RIGHT = 0x10, // set to right-align the text in the column - }; - virtual bool AddColumnToSection(int sectionID, const char *columnName, const char *columnText, int columnFlags, int width, HFont fallbackFont = INVALID_FONT ); - virtual bool AddColumnToSection(int sectionID, const char *columnName, const wchar_t *columnText, int columnFlags, int width, HFont fallbackFont = INVALID_FONT ); - - // modifies the text in an existing column - virtual bool ModifyColumn(int sectionID, const char *columnName, const wchar_t *columnText); - - // adds an item to the list; returns the itemID of the new item - virtual int AddItem(int sectionID, const KeyValues *data); - - // modifies an existing item; returns false if the item does not exist - virtual bool ModifyItem(int itemID, int sectionID, const KeyValues *data); - - // removes an item from the list; returns false if the item does not exist or is already removed - virtual bool RemoveItem(int itemID); - - // clears the list - virtual void RemoveAll() { DeleteAllItems(); } - // DeleteAllItems() is deprecated, use RemoveAll(); - virtual void DeleteAllItems(); - - // set the text color of an item - virtual void SetItemFgColor(int itemID, Color color); - - /* MESSAGES SENT: - "RowSelected" - "itemID" - the selected item id, -1 if nothing selected - - // when an item has been clicked on - "RowContextMenu" "itemID" - "RowLeftClick" "itemID" - "RowDoubleLeftClick" "itemID" - */ - - // returns the number of columns in a section - virtual int GetColumnCountBySection(int sectionID); - - // returns the name of a column by section and column index; returns NULL if there are no more columns - // valid range of columnIndex is [0, GetColumnCountBySection) - virtual const char *GetColumnNameBySection(int sectionID, int columnIndex); - virtual const wchar_t *GetColumnTextBySection(int sectionID, int columnIndex); - virtual int GetColumnFlagsBySection(int sectionID, int columnIndex); - virtual int GetColumnWidthBySection(int sectionID, int columnIndex); - virtual HFont GetColumnFallbackFontBySection( int sectionID, int columnIndex ); - - // returns the id of the currently selected item, -1 if nothing is selected - virtual int GetSelectedItem(); - - // sets which item is currently selected - virtual void SetSelectedItem(int itemID); - - // remove selection - virtual void ClearSelection( void ); - - // returns the data of a selected item - // InvalidateItem(itemID) needs to be called if the KeyValues are modified - virtual KeyValues *GetItemData(int itemID); - - // returns what section an item is in - virtual int GetItemSection(int itemID); - - // forces an item to redraw (use when keyvalues have been modified) - virtual void InvalidateItem(int itemID); - - // returns true if the itemID is valid for use - virtual bool IsItemIDValid(int itemID); - virtual int GetHighestItemID(); - - // returns the number of items (ignoring section dividers) - virtual int GetItemCount(); - - // returns the item ID from the row, again ignoring section dividers - valid from [0, GetItemCount ) - virtual int GetItemIDFromRow(int row); - - // returns the row that this itemID occupies. -1 if the itemID is invalid - virtual int GetRowFromItemID(int itemID); - - // gets the local coordinates of a cell - virtual bool GetCellBounds(int itemID, int column, int &x, int &y, int &wide, int &tall); - - // set up a field for editing - virtual void EnterEditMode(int itemID, int column, vgui::Panel *editPanel); - - // leaves editing mode - virtual void LeaveEditMode(); - - // returns true if we are currently in inline editing mode - virtual bool IsInEditMode(); - - // sets whether or not the vertical scrollbar should ever be displayed - virtual void SetVerticalScrollbar(bool state); - - // returns the size required to fully draw the contents of the panel - virtual void GetContentSize(int &wide, int &tall); - - // image handling - virtual void SetImageList(ImageList *imageList, bool deleteImageListWhenDone); - - virtual void ScrollToItem(int iItem); - - virtual void SetProportional(bool state); - - void MoveSelectionDown( void ); - void MoveSelectionUp( void ); - -protected: - virtual void PerformLayout(); - virtual void ApplySchemeSettings(IScheme *pScheme); - virtual void ApplySettings(KeyValues *inResourceData); - virtual void OnSizeChanged(int wide, int tall); - virtual void OnMouseWheeled(int delta); - virtual void OnMousePressed( MouseCode code); - virtual void OnKeyCodeTyped( KeyCode code); - virtual void OnSetFocus(); // called after the panel receives the keyboard focus - -private: - MESSAGE_FUNC( OnSliderMoved, "ScrollBarSliderMoved" ); - - void AddSectionHelper(int sectionID, CSectionHeader *header, SectionSortFunc_t sortFunc); - int GetSectionTall(); - void LayoutPanels(int &contentTall); - - // Returns the index of a new item button, reusing an existing item button if possible - int GetNewItemButton(); - - friend CItemButton; - void SetSelectedItem(CItemButton *item); - DHANDLE m_hSelectedItem; - - struct column_t - { - char m_szColumnName[32]; - wchar_t m_szColumnText[64]; - int m_iColumnFlags; - int m_iWidth; - HFont m_hFallbackFont; - }; - struct section_t - { - int m_iID; - bool m_bAlwaysVisible; - CSectionHeader *m_pHeader; - CUtlVector m_Columns; - SectionSortFunc_t m_pSortFunc; - }; - - CUtlVector m_Sections; - CUtlLinkedList m_Items; - CUtlLinkedList m_FreeItems; - CUtlVector m_SortedItems; - - PHandle m_hEditModePanel; - int m_iEditModeItemID; - int m_iEditModeColumn; - int m_iContentHeight; - int m_iLineSpacing; - - int FindSectionIndexByID(int sectionID); - void ReSortList(); - - ScrollBar *m_pScrollBar; - ImageList *m_pImageList; - bool m_bDeleteImageListWhenDone; - bool m_bSortNeeded; - bool m_bVerticalScrollbarEnabled; -}; - -} // namespace vgui - -#endif // SECTIONEDLISTPANEL_H diff --git a/public/vgui_controls/Slider.h b/public/vgui_controls/Slider.h deleted file mode 100644 index 910fa099f..000000000 --- a/public/vgui_controls/Slider.h +++ /dev/null @@ -1,116 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef SLIDER_H -#define SLIDER_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Labeled horizontal slider -//----------------------------------------------------------------------------- -class Slider : public Panel -{ - DECLARE_CLASS_SIMPLE( Slider, Panel ); - -public: - Slider(Panel *parent, const char *panelName); - - // interface - virtual void SetValue(int value, bool bTriggerChangeMessage = true); - virtual int GetValue(); - virtual void SetRange(int min, int max); // set to max and min range of rows to display - virtual void GetRange(int &min, int &max); - virtual void GetNobPos(int &min, int &max); // get current Slider position - virtual void SetButtonOffset(int buttonOffset); - virtual void OnCursorMoved(int x, int y); - virtual void OnMousePressed(MouseCode code); - virtual void OnMouseDoublePressed(MouseCode code); - virtual void OnMouseReleased(MouseCode code); - virtual void SetTickCaptions(const wchar_t *left, const wchar_t *right); - virtual void SetTickCaptions(const char *left, const char *right); - virtual void SetNumTicks(int ticks); - virtual void SetThumbWidth( int width ); - virtual int EstimateValueAtPos( int localMouseX, int localMouseY ); - virtual void SetInverted( bool bInverted ); - - // If you click on the slider outside of the nob, the nob jumps - // to the click position, and if this setting is enabled, the nob - // is then draggable from the new position until the mouse is released - virtual void SetDragOnRepositionNob( bool state ); - virtual bool IsDragOnRepositionNob() const; - - // Get if the slider nob is being dragged by user, usually the application - // should refuse from forcefully setting slider value if it is being dragged - // by user since the next frame the nob will pop back to mouse position - virtual bool IsDragged( void ) const; - - // This allows the slider to behave like it's larger than what's actually being drawn - virtual void SetSliderThumbSubRange( bool bEnable, int nMin = 0, int nMax = 100 ); - -protected: - virtual void OnSizeChanged(int wide, int tall); - virtual void Paint(); - virtual void PaintBackground(); - virtual void PerformLayout(); - virtual void ApplySchemeSettings(IScheme *pScheme); - virtual void GetSettings(KeyValues *outResourceData); - virtual void ApplySettings(KeyValues *inResourceData); - virtual const char *GetDescription(); - virtual void OnKeyCodeTyped(KeyCode code); - - virtual void DrawNob(); - virtual void DrawTicks(); - virtual void DrawTickLabels(); - - virtual void GetTrackRect( int &x, int &y, int &w, int &h ); - -protected: - virtual void RecomputeNobPosFromValue(); - virtual void RecomputeValueFromNobPos(); - - virtual void SendSliderMovedMessage(); - virtual void SendSliderDragStartMessage(); - virtual void SendSliderDragEndMessage(); - - bool _dragging; - int _nobPos[2]; - int _nobDragStartPos[2]; - int _dragStartPos[2]; - int _range[2]; - int _subrange[ 2 ]; - int _value; // the position of the Slider, in coordinates as specified by SetRange/SetRangeWindow - int _buttonOffset; - IBorder *_sliderBorder; - IBorder *_insetBorder; - float _nobSize; - - TextImage *_leftCaption; - TextImage *_rightCaption; - - Color m_TickColor; - Color m_TrackColor; - Color m_DisabledTextColor1; - Color m_DisabledTextColor2; - - int m_nNumTicks; - bool m_bIsDragOnRepositionNob : 1; - bool m_bUseSubRange : 1; - bool m_bInverted : 1; -}; - -} - -#endif // SLIDER_H diff --git a/public/vgui_controls/Splitter.h b/public/vgui_controls/Splitter.h deleted file mode 100644 index dc9a45ab7..000000000 --- a/public/vgui_controls/Splitter.h +++ /dev/null @@ -1,98 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef SPLITTER_H -#define SPLITTER_H - -#ifdef _WIN32 -#pragma once -#endif - -#include - -namespace vgui -{ - -enum SplitterMode_t -{ - SPLITTER_MODE_HORIZONTAL = 0, - SPLITTER_MODE_VERTICAL -}; - - -class SplitterHandle; -class SplitterChildPanel; - -//----------------------------------------------------------------------------- -// Purpose: Thin line used to divide sections, can be moved dragged! -//----------------------------------------------------------------------------- -class Splitter : public EditablePanel -{ - DECLARE_CLASS_SIMPLE( Splitter, EditablePanel ); - -public: - // nCount is the number of splitters to create. - // NOTE: The constructor here will create (nCount+1) EditablePanel children - // and name them child0...childN for .res file purposes. - Splitter( Panel *parent, const char *name, SplitterMode_t mode, int nCount ); - ~Splitter(); - - // Evenly respace all splitters - void EvenlyRespaceSplitters(); - - // respace splitters using given fractions (must sum to 1) - void RespaceSplitters( float *flFractions ); - - // Inherited from Panel - virtual void ApplySettings(KeyValues *inResourceData); - virtual void GetSettings( KeyValues *outResourceData ); - virtual void PerformLayout(); - virtual void OnSizeChanged(int newWide, int newTall); - virtual void ApplyUserConfigSettings(KeyValues *userConfig); - virtual void GetUserConfigSettings(KeyValues *userConfig); - virtual bool HasUserConfigSettings() { return true; } - - // Sets the splitter color - void SetSplitterColor( Color c ); - - // Enables borders on the splitters - void EnableBorders( bool bEnable ); - - // Locks the size of a particular child in pixels. - void LockChildSize( int nChildIndex, int nSize ); - void UnlockChildSize( int nChildIndex ); - -private: - void RecreateSplitters( int nCount ); - - struct SplitterInfo_t - { - SplitterChildPanel *m_pPanel; // This panel is to the left or above the handle - SplitterHandle *m_pHandle; - float m_flPos; - bool m_bLocked; - int m_nLockedSize; - }; - - int GetPosRange(); - int GetSplitterCount() const; - int GetSplitterPosition( int nIndex ); - void SetSplitterPosition( int nIndex, int nPos ); - int GetSubPanelCount() const; - int ComputeLockedSize( int nStartingIndex ); - - CUtlVector< SplitterInfo_t > m_Splitters; - SplitterMode_t m_Mode; - - friend class SplitterHandle; -}; - - -} // namespace vgui - - -#endif // SPLITTER_H diff --git a/public/vgui_controls/TextEntry.h b/public/vgui_controls/TextEntry.h deleted file mode 100644 index 9b465eba6..000000000 --- a/public/vgui_controls/TextEntry.h +++ /dev/null @@ -1,389 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: A Class to create a window that you can type and edit text in. -// Window can hold single line or multiline text. -// If it is single it can scroll horizontally in response to -// key input and mouse selection. -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef TEXTENTRY_H -#define TEXTENTRY_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include -#include -#include - -#include - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Text-input handler -// Behaviour Specs: -// This class handles input from mouse and keyboard. -// TextEntry classes support several box styles, horizontal scrolling with no scrollbar -// vertical scrolling with or without a scrollbar, single line, multiline, -// editable and noneditable. -// -// Shared behaviour: -// URL's are a different text color and are clickable. Clicking them brings up a web browser. -// For vertical scroll bars, up and down arrows scroll one line at a time. -// Clicking and dragging the nob scrolls through text lines. -// Mouse wheel also moves the nob. -// User can select and highlight text in the window. -// Double clicking on a word selects it. -// -// Non editable: -// No blinking cursor in non editable windows. -// Right clicking mouse opens copy menu. Menu's top left corner is where mouse is. -// Ctrl-c will also copy the text. -// Editable: -// Blinking cursor is positioned where text will be inserted. -// Text keys type chars in the window. -// ctrl-c copy highlighted text -// ctrl-v paste highlighted text -// ctrl-x cut highlighted text -// ctrl-right arrow move cursor to the start of the next word -// ctrl-left arrow move cursor to the start of the prev word -// ctrl-enter delete the selected text (and inserts a newline if _catchEnterKey is true) -// insert delete selected text and pastes text from the clipboard -// delete delete the selected text -// ctrl-home move cursor to the start of the text -// ctrl-end move cursor to the end of the text. -// left arrow move cursor before prev char -// ctrl-shift left/right arrow selects text a word at a time -// right arrow move cursor before next char -// up arrow move cursor up one line. -// down arrow move cursor down one line. -// home move cursor to start of current line -// end move cursor to end of current line -// backspace delete prev char or selected text. -// Trying to move to the prev/next char/line/word when there is none moves the cursor to the -// start/end of the text. -// Horizontal scrolling: -// Trying to move to the prev/next char/line/word when there is none scrolls the text -// horizontally in the window so the new text displays at the correct side. -// When moving to prev chars scrolling is staggered. To next chars it is one char at a time. -// Cut/Copy/Paste Menu: -// Right clicking mouse brings up cut/copy/paste menu. -// If no text is highlighted the cut/copy options are dimmed. Cut is dimmed in non editable panels -// If there is no text in the clipboard or panel is not editable the paste option is dimmed. -// If the mouse is right clicked over selected text, the text stays selected. -// If the mouse is right clicked over unselected text, any selected text is deselected. -// -// -//----------------------------------------------------------------------------- -class TextEntry : public Panel -{ - DECLARE_CLASS_SIMPLE( TextEntry, Panel ); - -public: - TextEntry(Panel *parent, const char *panelName); - virtual ~TextEntry(); - - virtual void SetText(const wchar_t *wszText); - virtual void SetText(const char *text); - virtual void GetText(char *buf, int bufLen); - virtual void GetText(wchar_t *buf, int bufLen); - virtual int GetTextLength() const; - virtual bool IsTextFullySelected() const; - - // editing - virtual void GotoLeft(); // move cursor one char left - virtual void GotoRight(); // move cursor one char right - virtual void GotoUp(); // move cursor one line up - virtual void GotoDown(); // move cursor one line down - virtual void GotoWordRight(); // move cursor to Start of next word - virtual void GotoWordLeft(); // move cursor to Start of prev word - virtual void GotoFirstOfLine(); // go to Start of the current line - virtual void GotoEndOfLine(); // go to end of the current line - virtual void GotoTextStart(); // go to Start of text buffer - virtual void GotoTextEnd(); // go to end of text buffer - - virtual void InsertChar(wchar_t ch); - virtual void InsertString(const char *text); - virtual void InsertString(wchar_t *wszText); - virtual void Backspace(); - virtual void Delete(); - virtual void SelectNone(); - virtual void OpenEditMenu(); - MESSAGE_FUNC( CutSelected, "DoCutSelected" ); - MESSAGE_FUNC( CopySelected, "DoCopySelected" ); - MESSAGE_FUNC( Paste, "DoPaste" ); - - MESSAGE_FUNC_INT( LanguageChanged, "DoLanguageChanged", handle ); - MESSAGE_FUNC_INT( ConversionModeChanged, "DoConversionModeChanged", handle ); - MESSAGE_FUNC_INT( SentenceModeChanged, "DoSentenceModeChanged", handle ); - - MESSAGE_FUNC_WCHARPTR( CompositionString, "DoCompositionString", string ); - - MESSAGE_FUNC( ShowIMECandidates, "DoShowIMECandidates" ); - MESSAGE_FUNC( HideIMECandidates, "DoHideIMECandidates" ); - MESSAGE_FUNC( UpdateIMECandidates, "DoUpdateIMECandidates" ); - - virtual void DeleteSelected(); - virtual void Undo(); - virtual void SaveUndoState(); - virtual void SetFont(HFont font); - virtual void SetTextHidden(bool bHideText); - virtual void SetEditable(bool state); - virtual bool IsEditable(); - virtual void SetEnabled(bool state); - // move the cursor to line 'line', given how many pixels are in a line - virtual void MoveCursor(int line, int pixelsAcross); - - // sets the color of the background when the control is disabled - virtual void SetDisabledBgColor(Color col); - - // set whether the box handles more than one line of entry - virtual void SetMultiline(bool state); - virtual bool IsMultiline(); - - // sets visibility of scrollbar - virtual void SetVerticalScrollbar(bool state); - - // sets whether or not the edit catches and stores ENTER key presses - virtual void SetCatchEnterKey(bool state); - - // sets whether or not to send "TextNewLine" msgs when ENTER key is pressed - virtual void SendNewLine(bool send); - - // sets limit of number of characters insertable into field; set to -1 to remove maximum - // only works with if rich-edit is NOT enabled - virtual void SetMaximumCharCount(int maxChars); - virtual int GetMaximumCharCount(); - virtual void SetAutoProgressOnHittingCharLimit(bool state); - - // sets whether to wrap text once maxChars is reached (on a line by line basis) - virtual void SetWrap(bool wrap); - - virtual void RecalculateLineBreaks(); - virtual void LayoutVerticalScrollBarSlider(); - - virtual bool RequestInfo(KeyValues *outputData); - - // sets the height of the window so all text is visible. - // used by tooltips - void SetToFullHeight(); - - // sets the width of the window so all text is visible. (will create one line) - // used by tooltips - void SetToFullWidth(); - - int GetNumLines(); - - /* INFO HANDLING - "GetText" - returns: - "text" - text contained in the text box - */ - - /* CUSTOM MESSAGE HANDLING - "SetText" - input: "text" - text is set to be this string - */ - - /* MESSAGE SENDING (to action signal targets) - "TextChanged" - sent when the text is edited by the user - - "TextNewLine" - sent when the end key is pressed in the text entry AND _sendNewLines is true - - "TextKillFocus" - sent when focus leaves textentry field - */ - - // Selects all the text in the text entry. - void SelectAllText(bool bResetCursorPos); - void SelectNoText(); - void SelectAllOnFirstFocus( bool status ); - void SetDrawWidth(int width); // width from right side of window we have to draw in - int GetDrawWidth(); - void SetHorizontalScrolling(bool status); // turn horizontal scrolling on or off. - - // sets whether non-asci characters (unicode chars > 127) are allowed in the control - defaults to OFF - void SetAllowNonAsciiCharacters(bool state); - - // sets whether or not number input only is allowed - void SetAllowNumericInputOnly(bool state); - - // By default, we draw the language shortname on the right hand side of the control - void SetDrawLanguageIDAtLeft( bool state ); - - virtual bool GetDropContextMenu( Menu *menu, CUtlVector< KeyValues * >& data ); - virtual bool IsDroppable( CUtlVector< KeyValues * >& data ); - virtual void OnPanelDropped( CUtlVector< KeyValues * >& data ); - virtual Panel *GetDragPanel(); - virtual void OnCreateDragData( KeyValues *msg ); - - void SelectAllOnFocusAlways( bool status ); - void SetSelectionTextColor( const Color& clr ); - void SetSelectionBgColor( const Color& clr ); - void SetSelectionUnfocusedBgColor( const Color& clr ); - - void SetUseFallbackFont( bool bState, HFont hFallback ); - -protected: - virtual void ResetCursorBlink(); - virtual void PerformLayout(); // layout the text in the window - virtual void ApplySchemeSettings(IScheme *pScheme); - virtual void PaintBackground(); - virtual int DrawChar(wchar_t ch, HFont font, int index, int x, int y); - virtual bool DrawCursor(int x, int y); - - virtual void SetCharAt(wchar_t ch, int index); // set the value of a char in the text buffer - virtual void ApplySettings( KeyValues *inResourceData ); - virtual void GetSettings( KeyValues *outResourceData ); - virtual const char *GetDescription( void ); - virtual void FireActionSignal(); - virtual bool GetSelectedRange(int& cx0,int& cx1); - virtual void CursorToPixelSpace(int cursorPos, int &cx, int &cy); - virtual int PixelToCursorSpace(int cx, int cy); - virtual void AddAnotherLine(int &cx, int &cy); - virtual int GetYStart(); // works out ypixel position drawing started at - - virtual bool SelectCheck( bool fromMouse = false ); // check if we are in text selection mode - MESSAGE_FUNC_WCHARPTR( OnSetText, "SetText", text ); - MESSAGE_FUNC( OnSliderMoved, "ScrollBarSliderMoved" ); // respond to scroll bar events - virtual void OnKillFocus(); - virtual void OnMouseWheeled(int delta); // respond to mouse wheel events - virtual void OnKeyCodeTyped(KeyCode code); //respond to keyboard events - virtual void OnKeyTyped(wchar_t unichar); //respond to keyboard events - - virtual void OnCursorMoved(int x, int y); // respond to moving the cursor with mouse button down - virtual void OnMousePressed(MouseCode code); // respond to mouse down events - virtual void OnMouseDoublePressed( MouseCode code ); - virtual void OnMouseTriplePressed( MouseCode code ); - virtual void OnMouseReleased( MouseCode code ); // respond to mouse up events - - virtual void OnKeyFocusTicked(); // do while window has keyboard focus - virtual void OnMouseFocusTicked(); // do while window has mouse focus - virtual void OnCursorEntered(); // handle cursor entering window - virtual void OnCursorExited(); // handle cursor exiting window - - virtual void OnMouseCaptureLost(); - virtual void OnSizeChanged(int newWide, int newTall); - - // Returns the character index the drawing should Start at - virtual int GetStartDrawIndex(int &lineBreakIndexIndex); - -public: - // helper accessors for common gets - virtual float GetValueAsFloat(); - virtual int GetValueAsInt(); - -protected: - void ScrollRight(); // scroll to right until cursor is visible - void ScrollLeft(); // scroll to left - bool IsCursorOffRightSideOfWindow(int cursorPos); // check if cursor is off right side of window - bool IsCursorOffLeftSideOfWindow(int cursorPos); // check if cursor is off left side of window - void ScrollLeftForResize(); - - void OnSetFocus(); - // Change keyboard layout type - void OnChangeIME( bool forward ); - - bool NeedsEllipses( HFont font, int *pIndex ); - -private: - MESSAGE_FUNC_INT( OnSetState, "SetState", state ); - // get index in buffer of the Start of the current line we are on - int GetCurrentLineStart(); - // get index in buffer of the end of the current line we are on - int GetCurrentLineEnd(); - bool IsLineBreak(int index); - int GetCursorLine(); - void MoveScrollBar(int delta); - void CalcBreakIndex(); // calculate _recalculateLineBreaksIndex - void CreateEditMenu(); // create copy/cut/paste menu - -public: - Menu *GetEditMenu(); // retrieve copy/cut/paste menu - -private: - void FlipToLastIME(); - -public: - virtual void GetTextRange( wchar_t *buf, int from, int numchars ); // copy a portion of the text to the buffer and add zero-termination - virtual void GetTextRange( char *buf, int from, int numchars ); // copy a portion of the text to the buffer and add zero-termination - -private: - - CUtlVector m_TextStream; // the text in the text window is stored in this buffer - CUtlVector m_UndoTextStream; // a copy of the text buffer to revert changes - CUtlVector m_LineBreaks; // an array that holds the index in the buffer to wrap lines at - - int _cursorPos; // the position in the text buffer of the blinking cursor - bool _cursorIsAtEnd; - bool _putCursorAtEnd; - int _undoCursorPos; // a copy of the cursor position to revert changes - bool _cursorBlink; // whether cursor is blinking or not - bool _hideText; // whether text is visible on screen or not - bool _editable; // whether text is editable or not - bool _mouseSelection; // whether we are highlighting text or not (selecting text) - bool _mouseDragSelection; // tells weather mouse is outside window and button is down so we select text - int _mouseSelectCursorStart; // where mouse button was pressed down in text window - long _cursorNextBlinkTime; // time of next cursor blink - int _cursorBlinkRate; // speed of cursor blinking - int _select[2]; // select[1] is the offset in the text to where the cursor is currently - // select[0] is the offset to where the cursor was dragged to. or -1 if no drag. - int _pixelsIndent; - int _charCount; - int _maxCharCount; // max number of chars that can be in the text buffer - HFont _font; // font of chars in the text buffer - HFont _smallfont; - bool _dataChanged; // whether anything in the window has changed. - bool _multiline; // whether buffer is multiline or just a single line - bool _verticalScrollbar; // whether window has a vertical scroll bar - ScrollBar *_vertScrollBar; // the scroll bar used in the window - Color _cursorColor; // color of the text cursor - Color _disabledFgColor; - Color _disabledBgColor; - Color _selectionColor; - Color _selectionTextColor; // color of the highlighted text - Color _defaultSelectionBG2Color; - int _currentStartLine; // use for checking vertical text scrolling (multiline) - int _currentStartIndex; // use for horizontal text scrolling (!multiline) - bool _horizScrollingAllowed; // use to disable horizontal text scrolling period. - Color _focusEdgeColor; - bool _catchEnterKey; - bool _wrap; - bool _sendNewLines; - int _drawWidth; - - // selection data - Menu *m_pEditMenu; ///cut/copy/paste popup - - int _recalculateBreaksIndex; // tells next linebreakindex index to Start recalculating line breaks - bool _selectAllOnFirstFocus : 1; // highlights all text in window when focus is gained. - bool _selectAllOnFocusAlways : 1; - bool _firstFocusStatus; // keep track if we've had that first focus or not - bool m_bAllowNumericInputOnly; - bool m_bAllowNonAsciiCharacters; - bool m_bAutoProgressOnHittingCharLimit; - - enum - { - MAX_COMPOSITION_STRING = 256, - }; - - wchar_t m_szComposition[ MAX_COMPOSITION_STRING ]; - Menu *m_pIMECandidates; - int m_hPreviousIME; - bool m_bDrawLanguageIDAtLeft; - int m_nLangInset; - - bool m_bUseFallbackFont : 1; - HFont m_hFallbackFont; -}; - -} - -#endif // TEXTENTRY_H diff --git a/public/vgui_controls/TextImage.h b/public/vgui_controls/TextImage.h deleted file mode 100644 index 0b851efea..000000000 --- a/public/vgui_controls/TextImage.h +++ /dev/null @@ -1,112 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef TEXTIMAGE_H -#define TEXTIMAGE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include - -#include - -class KeyValues; - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Image that handles drawing of a text string -//----------------------------------------------------------------------------- -class TextImage : public Image -{ -public: - TextImage(const char *text); - TextImage(const wchar_t *wszText); - ~TextImage(); - -public: - // takes the string and looks it up in the localization file to convert it to unicode - virtual void SetText(const char *text); - // sets unicode text directly - virtual void SetText(const wchar_t *text, bool bClearUnlocalizedSymbol = false); - // get the full text in the image - virtual void GetText(char *buffer, int bufferSize); - virtual void GetText(wchar_t *buffer, int bufferLength); - // get the text in it's unlocalized form - virtual void GetUnlocalizedText(char *buffer, int bufferSize); - virtual StringIndex_t GetUnlocalizedTextSymbol(); - - // set the font of the text - virtual void SetFont(vgui::HFont font); - // get the font of the text - virtual vgui::HFont GetFont(); - - // set the width of the text to be drawn - // use this function if the textImage is in another window to cause - // the text to be truncated to the width of the window (elipsis added) - void SetDrawWidth(int width); - // get the width of the text to be drawn - void GetDrawWidth(int &width); - - void ResizeImageToContent(); - void ResizeImageToContentMaxWidth( int nMaxWidth ); - - // set the size of the image - virtual void SetSize(int wide,int tall); - - // get the full size of a text string - virtual void GetContentSize(int &wide, int &tall); - - // draws the text - virtual void Paint(); - - void SetWrap( bool bWrap ); - void RecalculateNewLinePositions(); - - void SetUseFallbackFont( bool bState, HFont hFallback ); - - void SetCenterWrap( bool bWrap ); - void RecalculateCenterWrapIndents(); - -protected: - // truncate the _text string to fit into the draw width - void SizeText(wchar_t *tempText, int stringLength); - // gets the size of a specified piece of text - virtual void GetTextSize(int &wide, int &tall); - -private: - void RecalculateEllipsesPosition(); - - wchar_t *_utext; // unicode version of the text - short _textBufferLen; // size of the text buffer - short _textLen; // length of the text string - vgui::HFont _font; // font of the text string - vgui::HFont _fallbackFont; - int _drawWidth; // this is the width of the window we are drawing into. - // if there is not enough room truncate the txt and add an elipsis - - StringIndex_t _unlocalizedTextSymbol; // store off the unlocalized text index for build mode - wchar_t *m_pwszEllipsesPosition; - - bool m_bRecalculateTruncation : 1; - bool m_bWrap : 1; - bool m_bUseFallbackFont : 1; - bool m_bRenderUsingFallbackFont : 1; - CUtlVector m_LineBreaks; // an array that holds the index in the buffer to wrap lines at - - bool m_bWrapCenter; // Separate from m_bWrap to ensure it doesn't break legacy code. - CUtlVector m_LineXIndent; // For centered word wrap. The X indent for each line. -}; - -} // namespace vgui - -#endif // TEXTIMAGE_H diff --git a/public/vgui_controls/ToggleButton.h b/public/vgui_controls/ToggleButton.h deleted file mode 100644 index 6368d70b0..000000000 --- a/public/vgui_controls/ToggleButton.h +++ /dev/null @@ -1,54 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef TOGGLEBUTTON_H -#define TOGGLEBUTTON_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Type of button that when pressed stays selected & depressed until pressed again -//----------------------------------------------------------------------------- -class ToggleButton : public Button -{ - DECLARE_CLASS_SIMPLE( ToggleButton, Button ); - -public: - ToggleButton(Panel *parent, const char *panelName, const char *text); - - virtual void DoClick(); - - /* messages sent (get via AddActionSignalTarget()): - "ButtonToggled" - int "state" - */ - -protected: - // overrides - virtual void OnMouseDoublePressed(MouseCode code); - - virtual Color GetButtonFgColor(); - virtual void ApplySchemeSettings(IScheme *pScheme); - - virtual bool CanBeDefaultButton(void); - virtual void OnKeyCodePressed(KeyCode code); - -private: - Color _selectedColor; -}; - -} // namespace vgui - -#endif // TOGGLEBUTTON_H diff --git a/public/vgui_controls/ToolWindow.h b/public/vgui_controls/ToolWindow.h deleted file mode 100644 index f95d5737d..000000000 --- a/public/vgui_controls/ToolWindow.h +++ /dev/null @@ -1,78 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef TOOLWINDOW_H -#define TOOLWINDOW_H -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -namespace vgui -{ - -class ToolWindow; - -// So that an app can have a "custom" tool window class created during window drag/drop operations on the property sheet -class IToolWindowFactory -{ -public: - virtual ToolWindow *InstanceToolWindow( Panel *parent, bool contextLabel, Panel *firstPage, char const *title, bool contextMenu ) = 0; -}; - -//----------------------------------------------------------------------------- -// Purpose: Simple frame that holds a property sheet -//----------------------------------------------------------------------------- -class ToolWindow : public Frame -{ - DECLARE_CLASS_SIMPLE( ToolWindow, Frame ); - -public: - ToolWindow(Panel *parent, bool contextLabel, IToolWindowFactory *factory = 0, Panel *page = NULL, char const *title = NULL, bool contextMenu = false, bool inGlobalList = true ); - - ~ToolWindow(); - - virtual bool IsDraggableTabContainer() const; - - // returns a pointer to the PropertySheet this dialog encapsulates - PropertySheet *GetPropertySheet(); - - // wrapper for PropertySheet interface - void AddPage(Panel *page, const char *title, bool contextMenu ); - void RemovePage( Panel *page ); - Panel *GetActivePage(); - void SetActivePage( Panel *page ); - - void SetToolWindowFactory( IToolWindowFactory *factory ); - IToolWindowFactory *GetToolWindowFactory(); - - static int GetToolWindowCount(); - static ToolWindow *GetToolWindow( int index ); - - static CUtlVector< ToolWindow * > s_ToolWindows; - - virtual void Grow( int edge = 0, int from_x = -1, int from_y = -1 ); - virtual void GrowFromClick(); - -protected: - // vgui overrides - virtual void PerformLayout(); - virtual void ActivateBuildMode(); - virtual void RequestFocus(int direction = 0); - virtual void OnMousePressed(MouseCode code); - virtual void OnMouseDoublePressed(MouseCode code); - -private: - PropertySheet *m_pPropertySheet; - IToolWindowFactory *m_pFactory; -}; - -}; // vgui - - -#endif // TOOLWINDOW_H diff --git a/public/vgui_controls/Tooltip.h b/public/vgui_controls/Tooltip.h deleted file mode 100644 index f5c83b42f..000000000 --- a/public/vgui_controls/Tooltip.h +++ /dev/null @@ -1,56 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Creates a Message box with a question in it and yes/no buttons -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef TOOLTIP_H -#define TOOLTIP_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Tooltip for a panel - shows text when cursor hovers over a panel -//----------------------------------------------------------------------------- -class Tooltip -{ -public: - Tooltip(Panel *parent, const char *text = NULL); - ~Tooltip(); - - void SetText(const char *text); - const char *GetText(); - void ShowTooltip(Panel *currentPanel); - void HideTooltip(); - void SizeTextWindow(); - void ResetDelay(); - void PerformLayout(); - - void SetTooltipFormatToSingleLine(); - void SetTooltipFormatToMultiLine(); - void SetTooltipDelay(int tooltipDelayMilliseconds); - int GetTooltipDelay(); - -private: - virtual void ApplySchemeSettings(IScheme *pScheme); - CUtlVector m_Text; - int _delay; // delay that counts down - int _tooltipDelay; // delay before tooltip comes up. - bool _makeVisible : 1; - bool _displayOnOneLine : 1; - bool _isDirty : 1; -}; - -}; - -#endif // TOOLTIP_H diff --git a/public/vgui_controls/TreeView.h b/public/vgui_controls/TreeView.h deleted file mode 100644 index 4a76840d6..000000000 --- a/public/vgui_controls/TreeView.h +++ /dev/null @@ -1,203 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef TREEVIEW_H -#define TREEVIEW_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include -#include -#include - -class KeyValues; - -namespace vgui -{ - -class ExpandButton; -class TreeNode; -class TreeViewSubPanel; - -// sorting function, should return true if node1 should be displayed before node2 -typedef bool (*TreeViewSortFunc_t)(KeyValues *node1, KeyValues *node2); - -class TreeView : public Panel -{ - DECLARE_CLASS_SIMPLE( TreeView, Panel ); - -public: - TreeView(Panel *parent, const char *panelName); - ~TreeView(); - - void SetSortFunc(TreeViewSortFunc_t pSortFunc); - - virtual int AddItem(KeyValues *data, int parentItemIndex); - - virtual int GetRootItemIndex(); - virtual int GetNumChildren( int itemIndex ); - virtual int GetChild( int iParentItemIndex, int iChild ); // between 0 and GetNumChildren( iParentItemIndex ). - - virtual int GetItemCount(void); - virtual KeyValues *GetItemData(int itemIndex); - virtual void RemoveItem(int itemIndex, bool bPromoteChildren, bool bRecursivelyRemove = false ); - virtual void RemoveAll(); - virtual bool ModifyItem(int itemIndex, KeyValues *data); - virtual int GetItemParent(int itemIndex); - - virtual void SetFont(HFont font); - - virtual void SetImageList(ImageList *imageList, bool deleteImageListWhenDone); - - void SetAllowMultipleSelections( bool state ); - bool IsMultipleSelectionAllowed() const; - - virtual void ClearSelection(); - virtual void AddSelectedItem( int itemIndex, bool clearCurrentSelection, bool requestFocus = true, bool bMakeItemVisible = true ); - virtual void RemoveSelectedItem( int itemIndex ); - virtual void SelectAll(); - - virtual bool IsItemSelected( int itemIndex ); - virtual void RangeSelectItems( int clickedItem ); - virtual void FindNodesInRange( int startItem, int endItem, CUtlVector< int >& itemIndices ); - - // returns the id of the currently selected item, -1 if nothing is selected - virtual int GetSelectedItemCount() const; - virtual int GetFirstSelectedItem() const; - virtual void GetSelectedItems( CUtlVector< int >& list ); - virtual void GetSelectedItemData( CUtlVector< KeyValues * >& list ); - - // set colors for individual elments - virtual void SetItemFgColor(int itemIndex, const Color& color); - virtual void SetItemBgColor(int itemIndex, const Color& color); - virtual void SetItemSelectionTextColor( int itemIndex, const Color& clr ); - virtual void SetItemSelectionBgColor( int itemIndex, const Color& clr ); - virtual void SetItemSelectionUnfocusedBgColor( int itemIndex, const Color& clr ); - - // returns true if the itemID is valid for use - virtual bool IsItemIDValid(int itemIndex); - - // item iterators - // iterate from [0..GetHighestItemID()], - // and check each with IsItemIDValid() before using - virtual int GetHighestItemID(); - - virtual void ExpandItem(int itemIndex, bool bExpand); - virtual bool IsItemExpanded( int itemIndex ); - - virtual void MakeItemVisible(int itemIndex); - - // This tells which of the visible items is the top one. - virtual void GetVBarInfo( int &top, int &nItemsVisible, bool& hbarVisible ); - - virtual HFont GetFont(); - - virtual void GenerateDragDataForItem( int itemIndex, KeyValues *msg ); - virtual void SetDragEnabledItems( bool state ); - - virtual void OnLabelChanged( int itemIndex, char const *oldString, char const *newString ); - virtual bool IsLabelEditingAllowed() const; - virtual bool IsLabelBeingEdited() const; - virtual void SetAllowLabelEditing( bool state ); - - /* message sent - - "TreeViewItemSelected" int "itemIndex" - called when the selected item changes - "TreeViewItemDeselected" int "itemIndex" - called when item is deselected - */ - int GetRowHeight(); - int GetVisibleMaxWidth(); - virtual void OnMousePressed(MouseCode code); - - // By default, the tree view expands nodes on left-click. This enables/disables that feature - void EnableExpandTreeOnLeftClick( bool bEnable ); - - virtual void SetLabelEditingAllowed( int itemIndex, bool state ); - virtual void StartEditingLabel( int itemIndex ); - - virtual bool IsItemDroppable( int itemIndex, CUtlVector< KeyValues * >& msglist ); - virtual void OnItemDropped( int itemIndex, CUtlVector< KeyValues * >& msglist ); - virtual bool GetItemDropContextMenu( int itemIndex, Menu *menu, CUtlVector< KeyValues * >& msglist ); - virtual HCursor GetItemDropCursor( int itemIndex, CUtlVector< KeyValues * >& msglist ); - - virtual int GetPrevChildItemIndex( int itemIndex ); - virtual int GetNextChildItemIndex( int itemIndex ); - - virtual void PerformLayout(); - - // Makes the scrollbar parented to some other panel... - ScrollBar *SetScrollBarExternal( bool vertical, Panel *newParent ); - void GetScrollBarSize( bool vertical, int& w, int& h ); - - void SetMultipleItemDragEnabled( bool state ); // if this is set, then clicking on one row and dragging will select a run or items, etc. - bool IsMultipleItemDragEnabled() const; - - int FindItemUnderMouse( int mx, int my ); - -protected: - // functions to override - // called when a node, marked as "Expand", needs to generate it's child nodes when expanded - virtual void GenerateChildrenOfNode(int itemIndex) {} - - // override to open a custom context menu on a node being selected and right-clicked - virtual void GenerateContextMenu( int itemIndex, int x, int y ) {} - - // overrides - virtual void OnMouseWheeled(int delta); - virtual void OnSizeChanged(int wide, int tall); - virtual void ApplySchemeSettings(IScheme *pScheme); - MESSAGE_FUNC_INT( OnSliderMoved, "ScrollBarSliderMoved", position ); - virtual void SetBgColor( Color color ); - -private: - friend class TreeNode; - friend class TreeNodeText; - - TreeNode* GetItem( int itemIndex ); - virtual void RemoveChildrenOfNode( int itemIndex ); - void SetLabelBeingEdited( bool state ); - - // Clean up the image list - void CleanUpImageList( ); - - // to be accessed by TreeNodes - IImage* GetImage(int index); - - // bools - bool m_bAllowLabelEditing : 1; - bool m_bDragEnabledItems : 1; - bool m_bDeleteImageListWhenDone : 1; - bool m_bLeftClickExpandsTree : 1; - bool m_bLabelBeingEdited : 1; - bool m_bMultipleItemDragging : 1; - bool m_bAllowMultipleSelections : 1; - - // cross reference - no hierarchy ordering in this list - CUtlLinkedList m_NodeList; - ScrollBar *m_pHorzScrollBar, *m_pVertScrollBar; - int m_nRowHeight; - - ImageList *m_pImageList; - TreeNode *m_pRootNode; - TreeViewSortFunc_t m_pSortFunc; - HFont m_Font; - - CUtlVector< TreeNode * > m_SelectedItems; - TreeViewSubPanel *m_pSubPanel; - - int m_nMostRecentlySelectedItem; - bool m_bScrollbarExternal[ 2 ]; // 0 = vert, 1 = horz -}; - -} - -#endif // TREEVIEW_H diff --git a/public/vgui_controls/TreeViewListControl.h b/public/vgui_controls/TreeViewListControl.h deleted file mode 100644 index 87fa14126..000000000 --- a/public/vgui_controls/TreeViewListControl.h +++ /dev/null @@ -1,130 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef TREEVIEWLISTCONTROL_H -#define TREEVIEWLISTCONTROL_H -#ifdef _WIN32 -#pragma once -#endif - - -#include -#include -#include -#include -#include "utlsymbol.h" - - -namespace vgui -{ - -// --------------------------------------------------------------------------------- // -// CTreeViewListControl -// -// This control has N columns, with a tree view in the leftmost column. -// --------------------------------------------------------------------------------- // - -class CTreeViewListControl : public vgui::Panel -{ - DECLARE_CLASS_SIMPLE( CTreeViewListControl, Panel ); - -public: - - CTreeViewListControl( vgui::Panel *pParent, const char *pName ); - - // Set the tree view to be displayed on the left. If this isn't set, then nothing displays in here. - virtual void SetTreeView( vgui::TreeView *pTree ); - - // Set the height of the title bar. - virtual void SetTitleBarInfo( vgui::HFont hFont, int titleBarHeight ); - - // Set the color to draw the border lines in. - virtual void SetBorderColor( Color clr ); - - // Initialize the column headers.. This info includes the tree view on the left, so this - virtual void SetNumColumns( int nColumns ); - virtual int GetNumColumns() const; - // ciFlags is a combination of CI_ flags. - virtual void SetColumnInfo( int iColumn, const char *pTitle, int width, int ciFlags=0 ); - - // Use this to render your stuff. Iterate over the rows in the tree view and - virtual int GetNumRows(); - virtual int GetTreeItemAtRow( int iRow ); // You can use m_pTree->GetItemData to get at the data for the row. - - // Use this to find out the client area to render in for each grid element. - // The returned box is inclusive. - // The rule is that the the top and left pixels in each grid element are reserved for lines. - virtual void GetGridElementBounds( int iColumn, int iRow, int &left, int &top, int &right, int &bottom ); - - virtual vgui::TreeView *GetTree(); - - virtual int GetTitleBarHeight(); - - virtual int GetScrollBarSize(); - -// Overrides. -public: - - // This is where it recalculates the row infos. - virtual void PerformLayout(); - - // Usually, you'll want to override paint. After calling the base, use GetNumRows() to - // iterate over the data in the tree control and fill in the other columns. - virtual void Paint(); - virtual void PostChildPaint(); - - // You can override this to change the way the title bars are drawn. - virtual void DrawTitleBars(); - - -public: - - enum - { - // By default, column header text is centered. - CI_HEADER_LEFTALIGN =0x0001 - }; - - -protected: - - void RecalculateRows(); - void RecalculateRows_R( int index ); - void RecalculateColumns(); - -private: - - vgui::TreeView *m_pTree; - - class CColumnInfo - { - public: - CColumnInfo() - { - m_Width = m_Left = m_Right = m_ciFlags = 0; - } - - CUtlSymbol m_Title; - int m_Width; - int m_Left; - int m_Right; - int m_ciFlags; // Combination of CI_ flags. - }; - CUtlVector m_Columns; - - vgui::HFont m_TitleBarFont; - int m_TitleBarHeight; - - // These are indices into the tree view. - CUtlVector m_Rows; - - Color m_BorderColor; -}; - -} // namespace - - -#endif // TREEVIEWLISTCONTROL_H diff --git a/public/vgui_controls/URLLabel.h b/public/vgui_controls/URLLabel.h deleted file mode 100644 index 68c92f631..000000000 --- a/public/vgui_controls/URLLabel.h +++ /dev/null @@ -1,49 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef URLLABEL_H -#define URLLABEL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include -#include - -namespace vgui -{ - -class URLLabel : public Label -{ - DECLARE_CLASS_SIMPLE( URLLabel, Label ); - -public: - URLLabel(Panel *parent, const char *panelName, const char *text, const char *pszURL); - URLLabel(Panel *parent, const char *panelName, const wchar_t *wszText, const char *pszURL); - ~URLLabel(); - - void SetURL(const char *pszURL); - -protected: - virtual void OnMousePressed(MouseCode code); - virtual void ApplySettings( KeyValues *inResourceData ); - virtual void GetSettings( KeyValues *outResourceData ); - virtual void ApplySchemeSettings(IScheme *pScheme); - virtual const char *GetDescription( void ); - - const char *GetURL( void ) { return m_pszURL; } - -private: - char *m_pszURL; - int m_iURLSize; - bool m_bUnderline; -}; - -} - -#endif // URLLABEL_H diff --git a/public/vgui_controls/WizardPanel.h b/public/vgui_controls/WizardPanel.h deleted file mode 100644 index 12fdca6b7..000000000 --- a/public/vgui_controls/WizardPanel.h +++ /dev/null @@ -1,127 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef WIZARDPANEL_H -#define WIZARDPANEL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include - -namespace vgui -{ - -class WizardSubPanel; - -//----------------------------------------------------------------------------- -// Purpose: Type of dialog that supports moving back and forth through a series -// of sub-dialogs, WizardSubPanels -//----------------------------------------------------------------------------- -class WizardPanel : public Frame -{ - DECLARE_CLASS_SIMPLE( WizardPanel, Frame ); - -public: - WizardPanel(Panel *parent, const char *panelName); - ~WizardPanel(); - - // Start the wizard, starting with the startPanel - virtual void Run(WizardSubPanel *startPanel); - - // Called when the buttons are pressed - // WizardSubPanels can also call these functions to simulate a button being pressed - MESSAGE_FUNC( OnNextButton, "NextButton" ); - MESSAGE_FUNC( OnPrevButton, "PrevButton" ); - MESSAGE_FUNC( OnFinishButton, "FinishButton" ); - MESSAGE_FUNC( OnCancelButton, "CancelButton" ); - - // sets whether or not a button is enabled - // this state is managed, and will be reset whenever going to a new page - virtual void SetNextButtonEnabled(bool state); - virtual void SetPrevButtonEnabled(bool state); - virtual void SetFinishButtonEnabled(bool state); - virtual void SetCancelButtonEnabled(bool state); - - // sets whether or not a button is visible - // this state is unmanaged, the user needs to ensure that the buttons state - // is correct when going both back and prev through the wizard - virtual void SetNextButtonVisible(bool state); - virtual void SetPrevButtonVisible(bool state); - virtual void SetFinishButtonVisible(bool state); - virtual void SetCancelButtonVisible(bool state); - - // sets the text for a button - // setting the text to be NULL resets the text to it's default state - // this state is unmanaged, the user needs to ensure that the buttons state - // is correct when going both back and prev through the wizard - virtual void SetNextButtonText(const char *text); - virtual void SetPrevButtonText(const char *text); - virtual void SetFinishButtonText(const char *text); - virtual void SetCancelButtonText(const char *text); - - // general wizard state for all the subpanels to access - virtual KeyValues *GetWizardData(); - - // recalculates where the key focus should be in the wizard - virtual void ResetKeyFocus(); - virtual void ResetDefaultButton(); - - // resets the sub panel history for the control - virtual void ResetHistory(); - - // returns a page by name - virtual WizardSubPanel *GetSubPanelByName(const char *pageName); - - virtual void ShowButtons(bool state); - virtual void GetClientArea(int &x, int &y, int &wide, int &tall); - -protected: - MESSAGE_FUNC_PTR( InternalActivateNextSubPanel, "ActivateNextSubPanel", panel ) - { - ActivateNextSubPanel( (WizardSubPanel *)panel ); - } - - virtual void ActivateNextSubPanel(WizardSubPanel *subPanel); - virtual void ActivatePrevSubPanel(); - virtual void CreateButtons(); - virtual void RecalculateTabOrdering(); - virtual vgui::WizardSubPanel *GetCurrentSubPanel() { return _currentSubPanel; } - - // overrides - virtual void PerformLayout(); - virtual void ApplySchemeSettings(IScheme *pScheme); - - // reroute build messages to the currently active sub panel - virtual void ActivateBuildMode(); - - // close maps to the cancel button - virtual void OnClose(); - virtual void OnCommand(const char *command); - virtual void OnCloseFrameButtonPressed(); - -private: - WizardSubPanel *FindNextValidSubPanel(WizardSubPanel *currentPanel); - - Button *_prevButton; - Button *_nextButton; - Button *_cancelButton; - Button *_finishButton; - - WizardSubPanel *_currentSubPanel; - KeyValues *_currentData; - - Dar _subPanelStack; // contains a list of all the subpanels (not including the current one) - - bool _showButtons; -}; - -} // namespace vgui - - -#endif // WIZARDPANEL_H diff --git a/public/vgui_controls/WizardSubPanel.h b/public/vgui_controls/WizardSubPanel.h deleted file mode 100644 index 6db14b9f8..000000000 --- a/public/vgui_controls/WizardSubPanel.h +++ /dev/null @@ -1,91 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef WIZARDSUBPANEL_H -#define WIZARDSUBPANEL_H - -#ifdef _WIN32 -#pragma once -#endif - -#include - -namespace vgui -{ - -//----------------------------------------------------------------------------- -// Purpose: Base panel for use in Wizards and in property sheets -//----------------------------------------------------------------------------- -class WizardSubPanel : public EditablePanel -{ - DECLARE_CLASS_SIMPLE( WizardSubPanel, EditablePanel ); - -public: - // constructor - WizardSubPanel(Panel *parent, const char *panelName); - ~WizardSubPanel(); - - // called when the subpanel is displayed - // All controls & data should be reinitialized at this time - virtual void OnDisplayAsNext() {} - - // called anytime the panel is first displayed, whether the user is moving forward or back - // called immediately after OnDisplayAsNext/OnDisplayAsPrev - virtual void OnDisplay() {} - - // called when displayed as previous - virtual void OnDisplayAsPrev() {} - - // called when one of the wizard buttons are pressed - // returns true if the wizard should advance, false otherwise - virtual bool OnNextButton() { return true; } - virtual bool OnPrevButton() { return true; } - virtual bool OnFinishButton() { return true; } - virtual bool OnCancelButton() { return true; } - - // returns true if this panel should be displayed, or if we should just skip over it - virtual bool ShouldDisplayPanel() { return true; } - - // return true if this subpanel doesn't need the next/prev/finish/cancel buttons or will do it itself - virtual bool isNonWizardPanel() { return false; } - - // returns a pointer to the next subpanel that should be displayed - virtual WizardSubPanel *GetNextSubPanel() = 0; - - // returns a pointer to the panel to return to - // it must be a panel that is already in the wizards panel history - // returning NULL tells it to use the immediate previous panel in the history - virtual WizardSubPanel *GetPrevSubPanel() { return NULL; } - - virtual WizardPanel *GetWizardPanel() { return _wizardPanel; } - virtual void SetWizardPanel(WizardPanel *wizardPanel) { _wizardPanel = wizardPanel; } - - // returns a pointer to the wizard's doc - virtual KeyValues *GetWizardData(); - - // returns a pointer - virtual WizardSubPanel *GetSiblingSubPanelByName(const char *pageName); - - // gets the size this subpanel would like the wizard to be - // returns true if it has a desired size - virtual bool GetDesiredSize(int &wide, int &tall); - -protected: - virtual void ApplySettings(KeyValues *inResourceData); - virtual void GetSettings( KeyValues *outResourceData ); - virtual void ApplySchemeSettings(IScheme *pScheme); - virtual const char *GetDescription(); - -private: - WizardPanel *_wizardPanel; - int m_iDesiredWide, m_iDesiredTall; -}; - -} // namespace vgui - - -#endif // WIZARDSUBPANEL_H diff --git a/public/vgui_controls/consoledialog.h b/public/vgui_controls/consoledialog.h deleted file mode 100644 index 0c806e120..000000000 --- a/public/vgui_controls/consoledialog.h +++ /dev/null @@ -1,166 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef CONSOLEDIALOG_H -#define CONSOLEDIALOG_H -#ifdef _WIN32 -#pragma once -#endif - -#include -#include "tier1/UtlVector.h" -#include "vgui_controls/EditablePanel.h" -#include "vgui_controls/Frame.h" -#include "icvar.h" - -class ConCommandBase; - - -namespace vgui -{ - -// Things the user typed in and hit submit/return with -class CHistoryItem -{ -public: - CHistoryItem( void ); - CHistoryItem( const char *text, const char *extra = NULL ); - CHistoryItem( const CHistoryItem& src ); - ~CHistoryItem( void ); - - const char *GetText() const; - const char *GetExtra() const; - void SetText( const char *text, const char *extra ); - bool HasExtra() { return m_bHasExtra; } - -private: - char *m_text; - char *m_extraText; - bool m_bHasExtra; -}; - -//----------------------------------------------------------------------------- -// Purpose: Game/dev console dialog -//----------------------------------------------------------------------------- -class CConsolePanel : public vgui::EditablePanel, public IConsoleDisplayFunc -{ - DECLARE_CLASS_SIMPLE( CConsolePanel, vgui::EditablePanel ); - -public: - CConsolePanel( Panel *pParent, const char *pName, bool bStatusVersion ); - ~CConsolePanel(); - - // Inherited from IConsoleDisplayFunc - virtual void ColorPrint( const Color& clr, const char *pMessage ); - virtual void Print( const char *pMessage ); - virtual void DPrint( const char *pMessage ); - - // clears the console - void Clear(); - - // writes console to a file - void DumpConsoleTextToFile(); - - // Hides the console - void Hide(); - - bool TextEntryHasFocus() const; - void TextEntryRequestFocus(); - -private: - enum - { - MAX_HISTORY_ITEMS = 100, - }; - - class CompletionItem - { - public: - CompletionItem( void ); - CompletionItem( const CompletionItem& src ); - CompletionItem& CompletionItem::operator =( const CompletionItem& src ); - ~CompletionItem( void ); - const char *GetItemText( void ); - const char *GetCommand( void ) const; - const char *GetName() const; - - bool m_bIsCommand; - ConCommandBase *m_pCommand; - CHistoryItem *m_pText; - }; - -protected: - // methods - void OnAutoComplete(bool reverse); - MESSAGE_FUNC_PTR( OnTextChanged, "TextChanged", panel ); - void RebuildCompletionList(const char *partialText); - void UpdateCompletionListPosition(); - MESSAGE_FUNC( CloseCompletionList, "CloseCompletionList" ); - MESSAGE_FUNC_CHARPTR( OnMenuItemSelected, "CompletionCommand", command ); - void ClearCompletionList(); - void AddToHistory( const char *commandText, const char *extraText ); - - // vgui overrides - virtual void PerformLayout(); - virtual void ApplySchemeSettings(vgui::IScheme *pScheme); - virtual void OnCommand(const char *command); - virtual void OnKeyCodeTyped(vgui::KeyCode code); - virtual void OnThink(); - - vgui::RichText *m_pHistory; - vgui::TextEntry *m_pEntry; - vgui::Button *m_pSubmit; - vgui::Menu *m_pCompletionList; - Color m_PrintColor; - Color m_DPrintColor; - - int m_iNextCompletion; // the completion that we'll next go to - char m_szPartialText[256]; - char m_szPreviousPartialText[256]; - bool m_bAutoCompleteMode; // true if the user is currently tabbing through completion options - bool m_bWasBackspacing; - bool m_bStatusVersion; - - CUtlVector< CompletionItem * > m_CompletionList; - CUtlVector< CHistoryItem > m_CommandHistory; - - friend class CConsoleDialog; -}; - - -class CConsoleDialog : public vgui::Frame -{ - DECLARE_CLASS_SIMPLE( CConsoleDialog, vgui::Frame ); - -public: - CConsoleDialog( vgui::Panel *pParent, const char *pName, bool bStatusVersion ); - - virtual void OnScreenSizeChanged( int iOldWide, int iOldTall ); - virtual void Close(); - virtual void PerformLayout(); - - // brings dialog to the fore - MESSAGE_FUNC( Activate, "Activate" ); - MESSAGE_FUNC_CHARPTR( OnCommandSubmitted, "CommandSubmitted", command ); - - // hides the console - void Hide(); - - // Chain to the page - void Print( const char *msg ); - void DPrint( const char *msg ); - void ColorPrint( const Color& clr, const char *msg ); - void Clear(); - void DumpConsoleTextToFile(); - -protected: - CConsolePanel *m_pConsolePanel; -}; - -} // end namespace vgui - -#endif // CONSOLEDIALOG_H diff --git a/public/vgui_controls/pch_vgui_controls.h b/public/vgui_controls/pch_vgui_controls.h deleted file mode 100644 index 135df5f32..000000000 --- a/public/vgui_controls/pch_vgui_controls.h +++ /dev/null @@ -1,115 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef PCH_VGUI_CONTROLS_H -#define PCH_VGUI_CONTROLS_H - -#ifdef _WIN32 -#pragma once -#endif - -// general includes -#include -#include -#include "tier0/dbg.h" -#include "tier0/valve_off.h" -#include "tier1/KeyValues.h" - -#include "tier0/valve_on.h" -#include "tier0/memdbgon.h" - -#include "FileSystem.h" -#include "tier0/validator.h" - -// vgui includes -#include "vgui/IBorder.h" -#include "vgui/IInput.h" -#include "vgui/ILocalize.h" -#include "vgui/IPanel.h" -#include "vgui/IScheme.h" -#include "vgui/ISurface.h" -#include "vgui/ISystem.h" -#include "vgui/IVGui.h" -#include "vgui/KeyCode.h" -#include "vgui/Cursor.h" -#include "vgui/MouseCode.h" - -// vgui controls includes -#include "vgui_controls/controls.h" - -#include "vgui_controls/AnimatingImagePanel.h" -#include "vgui_controls/AnimationController.h" -#include "vgui_controls/BitmapImagePanel.h" -#include "vgui_controls/BuildGroup.h" -#include "vgui_controls/BuildModeDialog.h" -#include "vgui_controls/Button.h" -#include "vgui_controls/CheckButton.h" -#include "vgui_controls/CheckButtonList.h" -#include "vgui_controls/ComboBox.h" -#include "vgui_controls/Controls.h" -#include "vgui_controls/DialogManager.h" -#include "vgui_controls/DirectorySelectDialog.h" -#include "vgui_controls/Divider.h" -#include "vgui_controls/EditablePanel.h" -#include "vgui_controls/FileOpenDialog.h" -#include "vgui_controls/FocusNavGroup.h" -#include "vgui_controls/Frame.h" -#include "vgui_controls/GraphPanel.h" -#include "vgui_controls/HTML.h" -#include "vgui_controls/Image.h" -#include "vgui_controls/ImageList.h" -#include "vgui_controls/ImagePanel.h" -#include "vgui_controls/Label.h" -#include "vgui_controls/ListPanel.h" -#include "vgui_controls/ListViewPanel.h" -#include "vgui_controls/Menu.h" -#include "vgui_controls/MenuBar.h" -#include "vgui_controls/MenuButton.h" -#include "vgui_controls/MenuItem.h" -#include "vgui_controls/MessageBox.h" -#include "vgui_controls/Panel.h" -#ifndef HL1 -#include "vgui_controls/PanelAnimationVar.h" -#endif -#include "vgui_controls/PanelListPanel.h" -#include "vgui_controls/PHandle.h" -#include "vgui_controls/ProgressBar.h" -#include "vgui_controls/ProgressBox.h" -#include "vgui_controls/PropertyDialog.h" -#include "vgui_controls/PropertyPage.h" -#include "vgui_controls/PropertySheet.h" -#include "vgui_controls/QueryBox.h" -#include "vgui_controls/RadioButton.h" -#include "vgui_controls/RichText.h" -#include "vgui_controls/ScrollBar.h" -#include "vgui_controls/ScrollBarSlider.h" -#include "vgui_controls/SectionedListPanel.h" -#include "vgui_controls/Slider.h" -#ifndef HL1 -#include "vgui_controls/Splitter.h" -#endif -#include "vgui_controls/TextEntry.h" -#include "vgui_controls/TextImage.h" -#include "vgui_controls/ToggleButton.h" -#include "vgui_controls/Tooltip.h" -#ifndef HL1 -#include "vgui_controls/ToolWindow.h" -#endif -#include "vgui_controls/TreeView.h" -#ifndef HL1 -#include "vgui_controls/TreeViewListControl.h" -#endif -#include "vgui_controls/URLLabel.h" -#include "vgui_controls/WizardPanel.h" -#include "vgui_controls/WizardSubPanel.h" - -#ifndef HL1 -#include "vgui_controls/KeyBoardEditorDialog.h" -#include "vgui_controls/InputDialog.h" -#endif - -#endif // PCH_VGUI_CONTROLS_H diff --git a/public/vgui_controls/perforcefilelistframe.h b/public/vgui_controls/perforcefilelistframe.h deleted file mode 100644 index faf1e2bdf..000000000 --- a/public/vgui_controls/perforcefilelistframe.h +++ /dev/null @@ -1,152 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// List of perforce files and operations -// -//============================================================================= - -#ifndef PERFORCEFILELISTFRAME_H -#define PERFORCEFILELISTFRAME_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "vgui_controls/frame.h" -#include "tier1/utlvector.h" -#include "tier1/utlstring.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -struct P4File_t; -enum P4FileState_t; - - -//----------------------------------------------------------------------------- -// Enumeration of operation dialog ids -//----------------------------------------------------------------------------- -enum -{ - OPERATION_DIALOG_ID_PERFORCE = 0, - - OPERATION_DIALOG_STANDARD_ID_COUNT, - OPERATION_DIALOG_STANDARD_ID_MAX = OPERATION_DIALOG_STANDARD_ID_COUNT - 1, -}; - - -//----------------------------------------------------------------------------- -// Purpose: Modal dialog for a list of files + an operation to perform -//----------------------------------------------------------------------------- -class COperationFileListFrame : public vgui::Frame -{ - DECLARE_CLASS_SIMPLE( COperationFileListFrame, vgui::Frame ); - -public: - // NOTE: The dialog ID is used to allow dialogs to have different configurations saved - COperationFileListFrame( vgui::Panel *pParent, const char *pTitle, const char *pColumnHeader, bool bShowDescription, bool bShowOkOnly = false, int nDialogID = 1 ); - virtual ~COperationFileListFrame(); - - // Command handler - virtual void OnCommand( const char *pCommand ); - virtual void PerformLayout(); - - // Adds files to the frame - void ClearAllOperations(); - void AddOperation( const char *pOperation, const char *pFileName ); - void AddOperation( const char *pOperation, const char *pFileName, const Color& clr ); - - // Resizes the operation column to fit the operation text - void ResizeOperationColumnToContents(); - - // Sets the column header for the 'operation' column - void SetOperationColumnHeaderText( const char *pText ); - - // Shows the panel - void DoModal( KeyValues *pContextKeyValues = NULL, const char *pMessage = NULL ); - - // Retrieves the number of files, the file names, and operations - int GetOperationCount(); - const char *GetFileName( int i ); - const char *GetOperation( int i ); - - // Retreives the description (only if it was shown) - const char *GetDescription(); - -private: - virtual bool PerformOperation() { return true; } - const char *CompletionMessage(); - void CleanUpMessage(); - - vgui::ListPanel *m_pFileBrowser; - vgui::Splitter *m_pSplitter; - vgui::TextEntry *m_pDescription; - vgui::Button *m_pYesButton; - vgui::Button *m_pNoButton; - KeyValues *m_pContextKeyValues; - CUtlString m_MessageName; - char *m_pText; -}; - - -//----------------------------------------------------------------------------- -// Purpose: Modal dialog for picker -//----------------------------------------------------------------------------- -enum PerforceAction_t -{ - PERFORCE_ACTION_NONE = -1, - PERFORCE_ACTION_FILE_ADD = 0, - PERFORCE_ACTION_FILE_EDIT, - PERFORCE_ACTION_FILE_DELETE, - PERFORCE_ACTION_FILE_REVERT, - PERFORCE_ACTION_FILE_SUBMIT, -}; - - -//----------------------------------------------------------------------------- -// Purpose: Modal dialog for picker -//----------------------------------------------------------------------------- -class CPerforceFileListFrame : public COperationFileListFrame -{ - DECLARE_CLASS_SIMPLE( CPerforceFileListFrame, COperationFileListFrame ); - -public: - CPerforceFileListFrame( vgui::Panel *pParent, const char *pTitle, const char *pColumnHeader, PerforceAction_t action ); - virtual ~CPerforceFileListFrame(); - - // Adds files to the frame - void ClearAllFiles(); - void AddFile( const char *pFullPath ); - void AddFile( const char *pRelativePath, const char *pPathId ); - - void DoModal( KeyValues *pContextKeys = NULL, const char *pMessage = NULL ); - -private: - virtual bool PerformOperation(); - - // Adds files for open, submit - void AddFileForOpen( const char *pFullPath ); - void AddFileForSubmit( const char *pFullPath, P4FileState_t state ); - - // Does the perforce operation - void PerformPerforceAction( ); - - PerforceAction_t m_Action; - CUtlVector< P4File_t > m_OpenedFiles; - CUtlString m_LastOpenedFilePathId; -}; - - -//----------------------------------------------------------------------------- -// Show the perforce query dialog -// The specified keyvalues message will be sent either -// 1) If you open the file for add/edit -// 2) If you indicate to not add a file for add but don't hit cancel -// If a specific perforce action is specified, then the dialog will only -// be displayed if that action is appropriate -//----------------------------------------------------------------------------- -void ShowPerforceQuery( vgui::Panel *pParent, const char *pFileName, vgui::Panel *pActionSignalTarget, KeyValues *pKeyValues, PerforceAction_t actionFilter = PERFORCE_ACTION_NONE ); - - -#endif // PERFORCEFILELISTFRAME_H - diff --git a/public/vgui_controls/savedocumentquery.h b/public/vgui_controls/savedocumentquery.h deleted file mode 100644 index 589f640ad..000000000 --- a/public/vgui_controls/savedocumentquery.h +++ /dev/null @@ -1,37 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// This dialog asks if you want to save your work -// -//============================================================================= - -#ifndef SAVEDOCUMENTQUERY_H -#define SAVEDOCUMENTQUERY_H - -#ifdef _WIN32 -#pragma once -#endif - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class KeyValues; -namespace vgui -{ -class Panel; -} - - -//----------------------------------------------------------------------------- -// Show the save document query dialog -// NOTE: The following commands will be posted to the action signal target: -// "OnExit" - when we want to quit -// "OnSave" - when we want to save the file -// "OnCloseNoSave" - when we want to close the file without saving it -// "commandname" - additional command send after saving (SAVEDOC_POSTCOMMAND_AFTER_SAVE) -// "OnMarkNotDirty" - when we want to mark the file not dirty -//----------------------------------------------------------------------------- -void ShowSaveDocumentQuery( vgui::Panel *pParent, const char *pFileName, const char *pFileType, int nContext, vgui::Panel *pActionSignalTarget, KeyValues *pPostSaveCommand ); - - -#endif // SAVEDOCUMENTQUERY_H diff --git a/public/vgui_controls/subrectimage.h b/public/vgui_controls/subrectimage.h deleted file mode 100644 index 3025df099..000000000 --- a/public/vgui_controls/subrectimage.h +++ /dev/null @@ -1,51 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef SUBRECTIMAGE_H -#define SUBRECTIMAGE_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "vgui_controls/Image.h" -#include "vgui/vgui.h" - - -//----------------------------------------------------------------------------- -// Purpose: Check box image -//----------------------------------------------------------------------------- -class CSubRectImage : public vgui::Image -{ -public: - CSubRectImage( const char *filename, bool hardwareFiltered, int subx, int suby, int subw, int subh ); - virtual ~CSubRectImage(); - - void GetSize( int &wide, int &tall ); - void GetContentSize( int &wide, int &tall ); - void SetSize( int x, int y ); - void SetPos( int x, int y ); - void SetColor( Color col ); - const char *GetName(); - void Paint(); - void ForceUpload(); - vgui::HTexture GetID(); - bool IsValid(); - -private: - vgui::HTexture _id; - int sub[ 4 ]; - char *_filename; - int _pos[2]; - int _wide,_tall; - Color _color; - bool _uploaded; - bool _valid; - bool _filtered; -}; - - -#endif // SUBRECTIMAGE_H diff --git a/public/vgui_controls/vgui_controls.cpp b/public/vgui_controls/vgui_controls.cpp deleted file mode 100644 index c15ccc9f4..000000000 --- a/public/vgui_controls/vgui_controls.cpp +++ /dev/null @@ -1,55 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= -#ifdef _WIN32 -#include "vgui/IVgui.h" -#include "vgui_controls/Controls.h" - -#include "vgui_controls/AnimatingImagePanel.h" -#include "vgui_controls/BitmapImagePanel.h" -#include "vgui_controls/ExpandButton.h" -#include "vgui_controls/TreeViewListControl.h" -#include "vgui_controls/HTML.h" - -using namespace vgui; - -USING_BUILD_FACTORY( Button ); -USING_BUILD_FACTORY( EditablePanel ); -USING_BUILD_FACTORY( ImagePanel ); -USING_BUILD_FACTORY( Label ); -USING_BUILD_FACTORY( Panel ); -USING_BUILD_FACTORY( ToggleButton ); -USING_BUILD_FACTORY( AnimatingImagePanel ); -USING_BUILD_FACTORY( CBitmapImagePanel ); -USING_BUILD_FACTORY( CheckButton ); -USING_BUILD_FACTORY( ComboBox ); -USING_BUILD_FACTORY( Divider ); -USING_BUILD_FACTORY( ExpandButton ); -USING_BUILD_FACTORY( GraphPanel ); -//USING_BUILD_FACTORY_ALIAS( HTML, HTML_NoJavascript ); -//USING_BUILD_FACTORY_ALIAS( HTML, HTML_Javascript ); -USING_BUILD_FACTORY( ListPanel ); -USING_BUILD_FACTORY( ListViewPanel ); -USING_BUILD_FACTORY( Menu ); -USING_BUILD_FACTORY( MenuBar ); -USING_BUILD_FACTORY( MenuButton ); -USING_BUILD_FACTORY( MenuItem ); -USING_BUILD_FACTORY( MessageBox ); -USING_BUILD_FACTORY( ProgressBar ); -USING_BUILD_FACTORY( RadioButton ); -USING_BUILD_FACTORY( RichText ); -USING_BUILD_FACTORY( ScalableImagePanel ); -USING_BUILD_FACTORY_ALIAS( ScrollBar, ScrollBar_Vertical ); -USING_BUILD_FACTORY_ALIAS( ScrollBar, ScrollBar_Horizontal ); -USING_BUILD_FACTORY( ScrollBar ); -USING_BUILD_FACTORY( TextEntry ); -USING_BUILD_FACTORY( TreeView ); -USING_BUILD_FACTORY( CTreeViewListControl ); -USING_BUILD_FACTORY( URLLabel ); - -int g_nYou_Must_Add_Public_Vgui_Controls_Vgui_ControlsCpp_To_Your_Project = 0; - -#endif // _WIN32 - diff --git a/public/view_shared.h b/public/view_shared.h deleted file mode 100644 index e74a2f8fd..000000000 --- a/public/view_shared.h +++ /dev/null @@ -1,114 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======// -// -// Purpose: -// -//=============================================================================// - -#ifndef VIEW_SHARED_H -#define VIEW_SHARED_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "convar.h" -#include "mathlib/vector.h" -#include "materialsystem/MaterialSystemUtil.h" - - -//----------------------------------------------------------------------------- -// Flags passed in with view setup -//----------------------------------------------------------------------------- -enum ClearFlags_t -{ - VIEW_CLEAR_COLOR = 0x1, - VIEW_CLEAR_DEPTH = 0x2, - VIEW_CLEAR_FULL_TARGET = 0x4, - VIEW_NO_DRAW = 0x8, - VIEW_CLEAR_OBEY_STENCIL = 0x10, // Draws a quad allowing stencil test to clear through portals - VIEW_CLEAR_STENCIL = 0x20, -}; - - -//----------------------------------------------------------------------------- -// Purpose: Renderer setup data. -//----------------------------------------------------------------------------- -class CViewSetup -{ -public: - CViewSetup() - { - m_flAspectRatio = 0.0f; - m_bRenderToSubrectOfLargerScreen = false; - m_bDoBloomAndToneMapping = true; - m_bOffCenter = false; - m_bCacheFullSceneState = false; -// m_bUseExplicitViewVector = false; - } - -// shared by 2D & 3D views - - // left side of view window - int x; - // top side of view window - int y; - // width of view window - int width; - // height of view window - int height; - -// the rest are only used by 3D views - - // Orthographic projection? - bool m_bOrtho; - // View-space rectangle for ortho projection. - float m_OrthoLeft; - float m_OrthoTop; - float m_OrthoRight; - float m_OrthoBottom; - - // horizontal FOV in degrees - float fov; - // horizontal FOV in degrees for in-view model - float fovViewmodel; - - // 3D origin of camera - Vector origin; - - // heading of camera (pitch, yaw, roll) - QAngle angles; - // local Z coordinate of near plane of camera - float zNear; - // local Z coordinate of far plane of camera - float zFar; - - // local Z coordinate of near plane of camera ( when rendering view model ) - float zNearViewmodel; - // local Z coordinate of far plane of camera ( when rendering view model ) - float zFarViewmodel; - - // set to true if this is to draw into a subrect of the larger screen - // this really is a hack, but no more than the rest of the way this class is used - bool m_bRenderToSubrectOfLargerScreen; - - // The aspect ratio to use for computing the perspective projection matrix - // (0.0f means use the viewport) - float m_flAspectRatio; - - // Controls for off-center projection (needed for poster rendering) - bool m_bOffCenter; - float m_flOffCenterTop; - float m_flOffCenterBottom; - float m_flOffCenterLeft; - float m_flOffCenterRight; - - // Control that the SFM needs to tell the engine not to do certain post-processing steps - bool m_bDoBloomAndToneMapping; - - // Cached mode for certain full-scene per-frame varying state such as sun entity coverage - bool m_bCacheFullSceneState; -}; - - - -#endif // VIEW_SHARED_H diff --git a/public/vphysics/collision_set.h b/public/vphysics/collision_set.h deleted file mode 100644 index 249aef408..000000000 --- a/public/vphysics/collision_set.h +++ /dev/null @@ -1,20 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -// A set of collision rules -// NOTE: Defaults to all indices disabled -class IPhysicsCollisionSet -{ -public: - ~IPhysicsCollisionSet() {} - - virtual void EnableCollisions( int index0, int index1 ) = 0; - virtual void DisableCollisions( int index0, int index1 ) = 0; - - virtual bool ShouldCollide( int index0, int index1 ) = 0; -}; diff --git a/public/vphysics/constraints.h b/public/vphysics/constraints.h deleted file mode 100644 index f9e7acdd4..000000000 --- a/public/vphysics/constraints.h +++ /dev/null @@ -1,345 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef CONSTRAINTS_H -#define CONSTRAINTS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "vphysics_interface.h" -#include "mathlib/mathlib.h" - -// constraint groups -struct constraint_groupparams_t -{ - int additionalIterations; // additional solver iterations make the constraint system more stable - int minErrorTicks; // minimum number of ticks with an error before it's reported - float errorTolerance; // error tolerance in HL units - - inline void Defaults() - { - additionalIterations = 0; - minErrorTicks = 15; - errorTolerance = 3.0f; - } -}; - -// Breakable constraints; -// -// forceLimit - kg * in / s limit (N * conversion(in/m)) -// torqueLimit - kg * in^2 / s (Nm * conversion(in^2/m^2)) - -// -// strength 0 - 1 -struct constraint_breakableparams_t -{ - float strength; // strength of the constraint 0.0 - 1.0 - float forceLimit; // constraint force limit to break (0 means never break) - float torqueLimit; // constraint torque limit to break (0 means never break) - float bodyMassScale[2]; // scale applied to mass of reference/attached object before solving constriant - bool isActive; - - inline void Defaults() - { - forceLimit = 0.0f; - torqueLimit = 0.0f; - strength = 1.0f; - bodyMassScale[0] = 1.0f; - bodyMassScale[1] = 1.0f; - isActive = true; - } -}; - -//----------------------------------------------------------------------------- -// Purpose: constraint limit on a single rotation axis -//----------------------------------------------------------------------------- -struct constraint_axislimit_t -{ - float minRotation; - float maxRotation; - float angularVelocity; // desired angular velocity around hinge - float torque; // torque to achieve angular velocity (use 0, torque for "friction") - - inline void SetAxisFriction( float rmin, float rmax, float friction ) - { - minRotation = rmin; - maxRotation = rmax; - angularVelocity = 0; - torque = friction; - } - inline void Defaults() - { - SetAxisFriction(0,0,0); - } -}; - -// Builds a transform which maps points in the input object's local space -// to the output object's local space -inline void BuildObjectRelativeXform( IPhysicsObject *pOutputSpace, IPhysicsObject *pInputSpace, matrix3x4_t &xformInToOut ) -{ - matrix3x4_t outInv, tmp, input; - pOutputSpace->GetPositionMatrix( &tmp ); - MatrixInvert( tmp, outInv ); - pInputSpace->GetPositionMatrix( &input ); - ConcatTransforms( outInv, input, xformInToOut ); -} - - -//----------------------------------------------------------------------------- -// Purpose: special limited ballsocket constraint for ragdolls. -// Has axis limits for all 3 axes. -//----------------------------------------------------------------------------- -struct constraint_ragdollparams_t -{ - constraint_breakableparams_t constraint; - matrix3x4_t constraintToReference;// xform constraint space to refobject space - matrix3x4_t constraintToAttached; // xform constraint space to attached object space - int parentIndex; // NOTE: only used for parsing. NEED NOT BE SET for create - int childIndex; // NOTE: only used for parsing. NEED NOT BE SET for create - - constraint_axislimit_t axes[3]; - bool onlyAngularLimits; // only angular limits (not translation as well?) - bool isActive; - bool useClockwiseRotations; // HACKHACK: Did this wrong in version one. Fix in the future. - - inline void Defaults() - { - constraint.Defaults(); - isActive = true; - SetIdentityMatrix( constraintToReference ); - SetIdentityMatrix( constraintToAttached ); - parentIndex = -1; - childIndex = -1; - axes[0].Defaults(); - axes[1].Defaults(); - axes[2].Defaults(); - onlyAngularLimits = false; - useClockwiseRotations = false; - } -}; - -//----------------------------------------------------------------------------- -// Purpose: Used to init a hinge restricting the relative position and orientation -// of two objects to rotation around a single axis -//----------------------------------------------------------------------------- -struct constraint_hingeparams_t -{ - Vector worldPosition; // position in world space on the hinge axis - Vector worldAxisDirection; // unit direction vector of the hinge axis in world space - constraint_axislimit_t hingeAxis; - constraint_breakableparams_t constraint; - - inline void Defaults() - { - worldPosition.Init(); - worldAxisDirection.Init(); - hingeAxis.Defaults(); - constraint.Defaults(); - } -}; - -struct constraint_limitedhingeparams_t : public constraint_hingeparams_t -{ - Vector referencePerpAxisDirection; // unit direction vector vector perpendicular to the hinge axis in world space - Vector attachedPerpAxisDirection; // unit direction vector vector perpendicular to the hinge axis in world space - - constraint_limitedhingeparams_t() {} - constraint_limitedhingeparams_t( const constraint_hingeparams_t &hinge ) - { - static_cast(*this) = hinge; - referencePerpAxisDirection.Init(); - attachedPerpAxisDirection.Init(); - } - - inline void Defaults() - { - this->constraint_hingeparams_t::Defaults(); - referencePerpAxisDirection.Init(); - attachedPerpAxisDirection.Init(); - } -}; - -//----------------------------------------------------------------------------- -// Purpose: Used to init a constraint that fixes the position and orientation -// of two objects relative to each other (like glue) -//----------------------------------------------------------------------------- -struct constraint_fixedparams_t -{ - matrix3x4_t attachedRefXform; // xform attached object space to ref object space - constraint_breakableparams_t constraint; - - inline void InitWithCurrentObjectState( IPhysicsObject *pRef, IPhysicsObject *pAttached ) - { - BuildObjectRelativeXform( pRef, pAttached, attachedRefXform ); - } - - inline void Defaults() - { - SetIdentityMatrix( attachedRefXform ); - constraint.Defaults(); - } -}; - - -//----------------------------------------------------------------------------- -// Purpose: Same parameters as fixed constraint, but torqueLimit has no effect -//----------------------------------------------------------------------------- -struct constraint_ballsocketparams_t -{ - Vector constraintPosition[2]; // position of the constraint in each object's space - constraint_breakableparams_t constraint; - inline void Defaults() - { - constraint.Defaults(); - constraintPosition[0].Init(); - constraintPosition[1].Init(); - } - - void InitWithCurrentObjectState( IPhysicsObject *pRef, IPhysicsObject *pAttached, const Vector &ballsocketOrigin ) - { - pRef->WorldToLocal( &constraintPosition[0], ballsocketOrigin ); - pAttached->WorldToLocal( &constraintPosition[1], ballsocketOrigin ); - } -}; - -struct constraint_slidingparams_t -{ - matrix3x4_t attachedRefXform; // xform attached object space to ref object space - Vector slideAxisRef; // unit direction vector of the slide axis in ref object space - constraint_breakableparams_t constraint; - // NOTE: if limitMin == limitMax there is NO limit set! - float limitMin; // minimum limit coordinate refAxisDirection space - float limitMax; // maximum limit coordinate refAxisDirection space - float friction; // friction on sliding - float velocity; // desired velocity - - inline void Defaults() - { - SetIdentityMatrix( attachedRefXform ); - slideAxisRef.Init(); - limitMin = limitMax = 0; - friction = 0; - velocity = 0; - constraint.Defaults(); - } - - inline void SetFriction( float inputFriction ) - { - friction = inputFriction; - velocity = 0; - } - - inline void SetLinearMotor( float inputVelocity, float maxForce ) - { - friction = maxForce; - velocity = inputVelocity; - } - - inline void InitWithCurrentObjectState( IPhysicsObject *pRef, IPhysicsObject *pAttached, const Vector &slideDirWorldspace ) - { - BuildObjectRelativeXform( pRef, pAttached, attachedRefXform ); - matrix3x4_t tmp; - pRef->GetPositionMatrix( &tmp ); - VectorIRotate( slideDirWorldspace, tmp, slideAxisRef ); - } -}; - -struct constraint_pulleyparams_t -{ - constraint_breakableparams_t constraint; - Vector pulleyPosition[2]; // These are the pulley positions for the reference and attached objects in world space - Vector objectPosition[2]; // local positions of attachments to the ref,att objects - float totalLength; // total rope length (include gearing!) - float gearRatio; // gearing affects attached object ALWAYS - bool isRigid; - - inline void Defaults() - { - constraint.Defaults(); - totalLength = 1.0; - gearRatio = 1.0; - pulleyPosition[0].Init(); - pulleyPosition[1].Init(); - objectPosition[0].Init(); - objectPosition[1].Init(); - isRigid = false; - } -}; - - -struct constraint_lengthparams_t -{ - constraint_breakableparams_t constraint; - Vector objectPosition[2]; // These are the positions for the reference and attached objects in local space - float totalLength; // Length of rope/spring/constraint. Distance to maintain - float minLength; // if rigid, objects are not allowed to move closer than totalLength either - - void InitWorldspace( IPhysicsObject *pRef, IPhysicsObject *pAttached, const Vector &refPosition, const Vector &attachedPosition, bool rigid = false ) - { - pRef->WorldToLocal( &objectPosition[0], refPosition ); - pAttached->WorldToLocal( &objectPosition[1], attachedPosition ); - totalLength = (refPosition - attachedPosition).Length(); - minLength = rigid ? totalLength : 0; - } - - inline void Defaults() - { - constraint.Defaults(); - objectPosition[0].Init(); - objectPosition[1].Init(); - totalLength = 1; - minLength = 0; - } -}; - -class IPhysicsConstraint -{ -public: - virtual ~IPhysicsConstraint( void ) {} - - // NOTE: Constraints are active when created. You can temporarily enable/disable them with these functions - virtual void Activate( void ) = 0; - virtual void Deactivate( void ) = 0; - - // set a pointer to the game object - virtual void SetGameData( void *gameData ) = 0; - - // get a pointer to the game object - virtual void *GetGameData( void ) const = 0; - - // Get the parent/referenced object - virtual IPhysicsObject *GetReferenceObject( void ) const = 0; - - // Get the attached object - virtual IPhysicsObject *GetAttachedObject( void ) const = 0; - - virtual void SetLinearMotor( float speed, float maxLinearImpulse ) = 0; - virtual void SetAngularMotor( float rotSpeed, float maxAngularImpulse ) = 0; - - virtual void UpdateRagdollTransforms( const matrix3x4_t &constraintToReference, const matrix3x4_t &constraintToAttached ) = 0; - virtual bool GetConstraintTransform( matrix3x4_t *pConstraintToReference, matrix3x4_t *pConstraintToAttached ) const = 0; - virtual bool GetConstraintParams( constraint_breakableparams_t *pParams ) const = 0; - - virtual void OutputDebugInfo() = 0; -}; - - -class IPhysicsConstraintGroup -{ -public: - virtual ~IPhysicsConstraintGroup( void ) {} - virtual void Activate() = 0; - virtual bool IsInErrorState() = 0; - virtual void ClearErrorState() = 0; - virtual void GetErrorParams( constraint_groupparams_t *pParams ) = 0; - virtual void SetErrorParams( const constraint_groupparams_t ¶ms ) = 0; - virtual void SolvePenetration( IPhysicsObject *pObj0, IPhysicsObject *pObj1 ) = 0; -}; - - -#endif // CONSTRAINTS_H diff --git a/public/vphysics/friction.h b/public/vphysics/friction.h deleted file mode 100644 index ef45a684d..000000000 --- a/public/vphysics/friction.h +++ /dev/null @@ -1,51 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef FRICTION_H -#define FRICTION_H -#ifdef _WIN32 -#pragma once -#endif - -// NOTE: This is an iterator for the contact points on an object -// NOTE: This should only be used temporarily. Holding one of these -// NOTE: across collision callbacks or calls into simulation will cause errors! -// NOTE: VPHYSICS may choose to make the data contained within this object invalid -// NOTE: any time simulation is run. -class IPhysicsFrictionSnapshot -{ -public: - virtual ~IPhysicsFrictionSnapshot() {} - - virtual bool IsValid() = 0; - - // Object 0 is this object, Object 1 is the other object - virtual IPhysicsObject *GetObject( int index ) = 0; - virtual int GetMaterial( int index ) = 0; - - virtual void GetContactPoint( Vector &out ) = 0; - - // points away from source object - virtual void GetSurfaceNormal( Vector &out ) = 0; - virtual float GetNormalForce() = 0; - virtual float GetEnergyAbsorbed() = 0; - - // recompute friction (useful if dynamically altering materials/mass) - virtual void RecomputeFriction() = 0; - // clear all friction force at this contact point - virtual void ClearFrictionForce() = 0; - - virtual void MarkContactForDelete() = 0; - virtual void DeleteAllMarkedContacts( bool wakeObjects ) = 0; - - // Move to the next friction data for this object - virtual void NextFrictionData() = 0; - virtual float GetFrictionCoefficient() = 0; -}; - - - -#endif // FRICTION_H diff --git a/public/vphysics/object_hash.h b/public/vphysics/object_hash.h deleted file mode 100644 index e44de536e..000000000 --- a/public/vphysics/object_hash.h +++ /dev/null @@ -1,29 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef OBJECT_HASH_H -#define OBJECT_HASH_H -#ifdef _WIN32 -#pragma once -#endif - -class IPhysicsObjectPairHash -{ -public: - virtual ~IPhysicsObjectPairHash() {} - virtual void AddObjectPair( void *pObject0, void *pObject1 ) = 0; - virtual void RemoveObjectPair( void *pObject0, void *pObject1 ) = 0; - virtual bool IsObjectPairInHash( void *pObject0, void *pObject1 ) = 0; - virtual void RemoveAllPairsForObject( void *pObject0 ) = 0; - virtual bool IsObjectInHash( void *pObject0 ) = 0; - - // Used to iterate over all pairs an object is part of - virtual int GetPairCountForObject( void *pObject0 ) = 0; - virtual int GetPairListForObject( void *pObject0, int nMaxCount, void **ppObjectList ) = 0; -}; - - -#endif // OBJECT_HASH_H diff --git a/public/vphysics/performance.h b/public/vphysics/performance.h deleted file mode 100644 index 7fc0ee6a0..000000000 --- a/public/vphysics/performance.h +++ /dev/null @@ -1,40 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef PERFORMANCE_H -#define PERFORMANCE_H -#ifdef _WIN32 -#pragma once -#endif - -const float DEFAULT_MIN_FRICTION_MASS = 10.0f; -const float DEFAULT_MAX_FRICTION_MASS = 2500.0f; -struct physics_performanceparams_t -{ - int maxCollisionsPerObjectPerTimestep; // object will be frozen after this many collisions (visual hitching vs. CPU cost) - int maxCollisionChecksPerTimestep; // objects may penetrate after this many collision checks (can be extended in AdditionalCollisionChecksThisTick) - float maxVelocity; // limit world space linear velocity to this (in / s) - float maxAngularVelocity; // limit world space angular velocity to this (degrees / s) - float lookAheadTimeObjectsVsWorld; // predict collisions this far (seconds) into the future - float lookAheadTimeObjectsVsObject; // predict collisions this far (seconds) into the future - float minFrictionMass; // min mass for friction solves (constrains dynamic range of mass to improve stability) - float maxFrictionMass; // mas mass for friction solves - - void Defaults() - { - maxCollisionsPerObjectPerTimestep = 6; - maxCollisionChecksPerTimestep = 250; - maxVelocity = 2000.0f; - maxAngularVelocity = 360.0f * 10.0f; - lookAheadTimeObjectsVsWorld = 1.0f; - lookAheadTimeObjectsVsObject = 0.5f; - minFrictionMass = DEFAULT_MIN_FRICTION_MASS; - maxFrictionMass = DEFAULT_MAX_FRICTION_MASS; - } -}; - - -#endif // PERFORMANCE_H diff --git a/public/vphysics/player_controller.h b/public/vphysics/player_controller.h deleted file mode 100644 index 2f7749c09..000000000 --- a/public/vphysics/player_controller.h +++ /dev/null @@ -1,47 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef PLAYER_CONTROLLER_H -#define PLAYER_CONTROLLER_H -#ifdef _WIN32 -#pragma once -#endif - -class IPhysicsPlayerControllerEvent -{ -public: - virtual int ShouldMoveTo( IPhysicsObject *pObject, const Vector &position ) = 0; -}; - -class IPhysicsPlayerController -{ -public: - virtual ~IPhysicsPlayerController( void ) {} - - virtual void Update( const Vector &position, const Vector &velocity, float secondsToArrival, bool onground, IPhysicsObject *ground ) = 0; - virtual void SetEventHandler( IPhysicsPlayerControllerEvent *handler ) = 0; - virtual bool IsInContact( void ) = 0; - virtual void MaxSpeed( const Vector &maxVelocity ) = 0; - - // allows game code to change collision models - virtual void SetObject( IPhysicsObject *pObject ) = 0; - // UNDONE: Refactor this and shadow controllers into a single class/interface through IPhysicsObject - virtual int GetShadowPosition( Vector *position, QAngle *angles ) = 0; - virtual void StepUp( float height ) = 0; - virtual void Jump() = 0; - virtual void GetShadowVelocity( Vector *velocity ) = 0; - virtual IPhysicsObject *GetObject() = 0; - virtual void GetLastImpulse( Vector *pOut ) = 0; - - virtual void SetPushMassLimit( float maxPushMass ) = 0; - virtual void SetPushSpeedLimit( float maxPushSpeed ) = 0; - - virtual float GetPushMassLimit() = 0; - virtual float GetPushSpeedLimit() = 0; - virtual bool WasFrozen() = 0; -}; - -#endif // PLAYER_CONTROLLER_H diff --git a/public/vphysics/stats.h b/public/vphysics/stats.h deleted file mode 100644 index f1a596e8b..000000000 --- a/public/vphysics/stats.h +++ /dev/null @@ -1,40 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef STATS_H -#define STATS_H -#ifdef _WIN32 -#pragma once -#endif - -// internal counters to measure cost of physics simulation -struct physics_stats_t -{ - float maxRescueSpeed; - float maxSpeedGain; - - int impactSysNum; - int impactCounter; - int impactSumSys; - int impactHardRescueCount; - int impactRescueAfterCount; - int impactDelayedCount; - int impactCollisionChecks; - int impactStaticCount; - - double totalEnergyDestroyed; - int collisionPairsTotal; - int collisionPairsCreated; - int collisionPairsDestroyed; - - int potentialCollisionsObjectVsObject; - int potentialCollisionsObjectVsWorld; - - int frictionEventsProcessed; -}; - - -#endif // STATS_H diff --git a/public/vphysics/vehicles.h b/public/vphysics/vehicles.h deleted file mode 100644 index f09811c84..000000000 --- a/public/vphysics/vehicles.h +++ /dev/null @@ -1,250 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef VEHICLES_H -#define VEHICLES_H -#ifdef _WIN32 -#pragma once -#endif - -#include "datamap.h" - - -#define VEHICLE_TYPE_CAR_WHEELS (1<<0) -#define VEHICLE_TYPE_CAR_RAYCAST (1<<1) -#define VEHICLE_TYPE_JETSKI_RAYCAST (1<<2) -#define VEHICLE_TYPE_AIRBOAT_RAYCAST (1<<3) - -#define VEHICLE_MAX_AXLE_COUNT 4 -#define VEHICLE_MAX_GEAR_COUNT 6 -#define VEHICLE_MAX_WHEEL_COUNT (2*VEHICLE_MAX_AXLE_COUNT) - -#define VEHICLE_TIRE_NORMAL 0 -#define VEHICLE_TIRE_BRAKING 1 -#define VEHICLE_TIRE_POWERSLIDE 2 - -struct vehicle_controlparams_t -{ - float throttle; - float steering; - float brake; - float boost; - bool handbrake; - bool handbrakeLeft; - bool handbrakeRight; - bool brakepedal; - bool bHasBrakePedal; - bool bAnalogSteering; -}; - -struct vehicle_operatingparams_t -{ - DECLARE_SIMPLE_DATADESC(); - - float speed; - float engineRPM; - int gear; - float boostDelay; - int boostTimeLeft; - float skidSpeed; - int skidMaterial; - float steeringAngle; - int wheelsNotInContact; - int wheelsInContact; - bool isTorqueBoosting; -}; - -// Debug! -#define VEHICLE_DEBUGRENDERDATA_MAX_WHEELS 10 -#define VEHICLE_DEBUGRENDERDATA_MAX_AXLES 3 - -struct vehicle_debugcarsystem_t -{ - Vector vecAxlePos[VEHICLE_DEBUGRENDERDATA_MAX_AXLES]; - - Vector vecWheelPos[VEHICLE_DEBUGRENDERDATA_MAX_WHEELS]; - Vector vecWheelRaycasts[VEHICLE_DEBUGRENDERDATA_MAX_WHEELS][2]; - Vector vecWheelRaycastImpacts[VEHICLE_DEBUGRENDERDATA_MAX_WHEELS]; -}; - -struct vehicleparams_t; - -class IPhysicsVehicleController -{ -public: - virtual ~IPhysicsVehicleController() {} - // call this from the game code with the control parameters - virtual void Update( float dt, vehicle_controlparams_t &controls ) = 0; - virtual const vehicle_operatingparams_t &GetOperatingParams() = 0; - virtual const vehicleparams_t &GetVehicleParams() = 0; - virtual vehicleparams_t &GetVehicleParamsForChange() = 0; - virtual float UpdateBooster(float dt) = 0; - virtual int GetWheelCount(void) = 0; - virtual IPhysicsObject *GetWheel(int index) = 0; - virtual bool GetWheelContactPoint( int index, Vector *pContactPoint, int *pSurfaceProps ) = 0; - virtual void SetSpringLength(int wheelIndex, float length) = 0; - virtual void SetWheelFriction(int wheelIndex, float friction) = 0; - - virtual void OnVehicleEnter( void ) = 0; - virtual void OnVehicleExit( void ) = 0; - - virtual void SetEngineDisabled( bool bDisable ) = 0; - virtual bool IsEngineDisabled( void ) = 0; - - // Debug - virtual void GetCarSystemDebugData( vehicle_debugcarsystem_t &debugCarSystem ) = 0; - virtual void VehicleDataReload() = 0; -}; - - -// parameters for the body object control of the vehicle -struct vehicle_bodyparams_t -{ - DECLARE_SIMPLE_DATADESC(); - - Vector massCenterOverride; // leave at vec3_origin for no override - float massOverride; // leave at 0 for no override - float addGravity; // keeps car down - float tiltForce; // keeps car down when not on flat ground - float tiltForceHeight; // where the tilt force pulls relative to center of mass - float counterTorqueFactor; - float keepUprightTorque; - float maxAngularVelocity; // clamp the car angular velocity separately from other objects to keep stable -}; - -// wheel objects are created by vphysics, these are the parameters for those objects -// NOTE: They are paired, so only one set of parameters is necessary per axle -struct vehicle_wheelparams_t -{ - DECLARE_SIMPLE_DATADESC(); - - float radius; - float mass; - float inertia; - float damping; // usually 0 - float rotdamping; // usually 0 - float frictionScale; // 1.5 front, 1.8 rear - int materialIndex; - int brakeMaterialIndex; - int skidMaterialIndex; - float springAdditionalLength; // 0 means the spring is at it's rest length -}; - -struct vehicle_suspensionparams_t -{ - DECLARE_SIMPLE_DATADESC(); - - float springConstant; - float springDamping; - float stabilizerConstant; - float springDampingCompression; - float maxBodyForce; -}; - -// NOTE: both raytrace and wheel data here because jetski uses both. -struct vehicle_axleparams_t -{ - DECLARE_SIMPLE_DATADESC(); - - Vector offset; // center of this axle in vehicle object space - Vector wheelOffset; // offset to wheel (assume other wheel is symmetric at -wheelOffset) from axle center - Vector raytraceCenterOffset; // offset to center of axle for the raytrace data. - Vector raytraceOffset; // offset to raytrace for non-wheel (some wheeled) vehicles - vehicle_wheelparams_t wheels; - vehicle_suspensionparams_t suspension; - float torqueFactor; // normalized to 1 across all axles - // e.g. 0,1 for rear wheel drive - 0.5,0.5 for 4 wheel drive - float brakeFactor; // normalized to 1 across all axles -}; - -struct vehicle_steeringparams_t -{ - DECLARE_SIMPLE_DATADESC(); - - float degreesSlow; // angle in degrees of steering at slow speed - float degreesFast; // angle in degrees of steering at fast speed - float degreesBoost; // angle in degrees of steering at fast speed - float steeringRateSlow; // this is the speed the wheels are steered when the vehicle is slow - float steeringRateFast; // this is the speed the wheels are steered when the vehicle is "fast" - float steeringRestRateSlow; // this is the speed at which the wheels move toward their resting state (straight ahead) at slow speed - float steeringRestRateFast; // this is the speed at which the wheels move toward their resting state (straight ahead) at fast speed - float speedSlow; // this is the max speed of "slow" - float speedFast; // this is the min speed of "fast" - float turnThrottleReduceSlow; // this is the amount of throttle reduction to apply at the maximum steering angle - float turnThrottleReduceFast; // this is the amount of throttle reduction to apply at the maximum steering angle - float brakeSteeringRateFactor; // this scales the steering rate when the brake/handbrake is down - float throttleSteeringRestRateFactor; // this scales the steering rest rate when the throttle is down - float powerSlideAccel; // scale of speed to acceleration - float boostSteeringRestRateFactor; // this scales the steering rest rate when boosting - float boostSteeringRateFactor; // this scales the steering rest rate when boosting - float steeringExponent; // this makes the steering response non-linear. The steering function is linear, then raised to this power - - bool isSkidAllowed; // true/false skid flag - bool dustCloud; // flag for creating a dustcloud behind vehicle -}; - -struct vehicle_engineparams_t -{ - DECLARE_SIMPLE_DATADESC(); - - float horsepower; - float maxSpeed; - float maxRevSpeed; - float maxRPM; // redline RPM limit - float axleRatio; // ratio of engine rev to axle rev - float throttleTime; // time to reach full throttle in seconds - - // transmission - int gearCount; // gear count - max 10 - float gearRatio[VEHICLE_MAX_GEAR_COUNT]; // ratio for each gear - - // automatic transmission (simple auto-shifter - switches at fixed RPM limits) - float shiftUpRPM; // max RPMs to switch to a higher gear - float shiftDownRPM; // min RPMs to switch to a lower gear - float boostForce; - float boostDuration; - float boostDelay; - float boostMaxSpeed; - float autobrakeSpeedGain; - float autobrakeSpeedFactor; - bool torqueBoost; - bool isAutoTransmission; // true for auto, false for manual -}; - -struct vehicleparams_t -{ - DECLARE_SIMPLE_DATADESC(); - - int axleCount; - int wheelsPerAxle; - vehicle_bodyparams_t body; - vehicle_axleparams_t axles[VEHICLE_MAX_AXLE_COUNT]; - vehicle_engineparams_t engine; - vehicle_steeringparams_t steering; -}; - -// Iterator for queries -class CPassengerSeatTransition; -typedef CUtlVector< CPassengerSeatTransition> PassengerSeatAnims_t; - -// Seat query types -enum VehicleSeatQuery_e -{ - VEHICLE_SEAT_ANY, // Any available seat for our role - VEHICLE_SEAT_NEAREST, // Seat closest to our starting point -}; - -// Seat anim types for return -enum PassengerSeatAnimType_t -{ - PASSENGER_SEAT_ENTRY, - PASSENGER_SEAT_EXIT -}; - -#define VEHICLE_SEAT_INVALID -1 // An invalid seat - -#endif // VEHICLES_H diff --git a/public/vphysics/virtualmesh.h b/public/vphysics/virtualmesh.h deleted file mode 100644 index 08c3df579..000000000 --- a/public/vphysics/virtualmesh.h +++ /dev/null @@ -1,46 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef VIRTUALMESH_H -#define VIRTUALMESH_H -#ifdef _WIN32 -#pragma once -#endif - -// NOTE: These are fixed length to make it easy to fill these out without memory allocation or storage -const int MAX_VIRTUAL_TRIANGLES = 1024; -struct virtualmeshlist_t -{ - Vector *pVerts; - int indexCount; - int triangleCount; - int vertexCount; - int surfacePropsIndex; - byte *pHull; - unsigned short indices[MAX_VIRTUAL_TRIANGLES*3]; -}; - -struct virtualmeshtrianglelist_t -{ - int triangleCount; - unsigned short triangleIndices[MAX_VIRTUAL_TRIANGLES*3]; -}; - -class IVirtualMeshEvent -{ -public: - virtual void GetVirtualMesh( void *userData, virtualmeshlist_t *pList ) = 0; - virtual void GetWorldspaceBounds( void *userData, Vector *pMins, Vector *pMaxs ) = 0; - virtual void GetTrianglesInSphere( void *userData, const Vector ¢er, float radius, virtualmeshtrianglelist_t *pList ) = 0; -}; -struct virtualmeshparams_t -{ - IVirtualMeshEvent *pMeshEventHandler; - void *userData; - bool buildOuterHull; -}; - -#endif // VIRTUALMESH_H diff --git a/public/vphysics_interface.h b/public/vphysics_interface.h deleted file mode 100644 index 4cfc35573..000000000 --- a/public/vphysics_interface.h +++ /dev/null @@ -1,1152 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: Public interfaces to vphysics DLL -// -// $NoKeywords: $ -//=============================================================================// - -#ifndef VPHYSICS_INTERFACE_H -#define VPHYSICS_INTERFACE_H -#ifdef _WIN32 -#pragma once -#endif - - -#include "tier1/interface.h" -#include "appframework/IAppSystem.h" -#include "mathlib/vector.h" -#include "mathlib/vector4d.h" -#include "vcollide.h" - - -// ------------------------------------------------------------------------------------ -// UNITS: -// ------------------------------------------------------------------------------------ -// NOTE: Coordinates are in HL units. 1 unit == 1 inch. X is east (forward), Y is north (left), Z is up (up) -// QAngle are pitch (around y), Yaw (around Z), Roll (around X) -// AngularImpulse are exponetial maps (an axis in HL units scaled by a "twist" angle in degrees) -// They can be transformed like normals/covectors and added linearly -// mass is kg, volume is in^3, acceleration is in/s^2, velocity is in/s - -// density is kg/m^3 (water ~= 998 at room temperature) -// preferably, these would be in kg/in^3, but the range of those numbers makes them not very human readable -// having water be about 1000 is really convenient for data entry. -// Since volume is in in^3 and density is in kg/m^3: -// density = (mass / volume) * CUBIC_METERS_PER_CUBIC_INCH -// Force is applied using impulses (kg*in/s) -// Torque is applied using impulses (kg*degrees/s) -// ------------------------------------------------------------------------------------ - -#define METERS_PER_INCH (0.0254f) -#define CUBIC_METERS_PER_CUBIC_INCH (METERS_PER_INCH*METERS_PER_INCH*METERS_PER_INCH) -// 2.2 lbs / kg -#define POUNDS_PER_KG (2.2f) -#define KG_PER_POUND (1.0f/POUNDS_PER_KG) - -// convert from pounds to kg -#define lbs2kg(x) ((x)*KG_PER_POUND) -#define kg2lbs(x) ((x)*POUNDS_PER_KG) - -const float VPHYSICS_MIN_MASS = 0.1f; -const float VPHYSICS_MAX_MASS = 5e4f; - -class IPhysicsObject; -class IPhysicsEnvironment; -class IPhysicsSurfaceProps; -class IPhysicsConstraint; -class IPhysicsConstraintGroup; -class IPhysicsFluidController; -class IPhysicsSpring; -class IPhysicsVehicleController; -class IConvexInfo; -class IPhysicsObjectPairHash; -class IPhysicsCollisionSet; -class IPhysicsPlayerController; -class IPhysicsFrictionSnapshot; - -struct Ray_t; -struct constraint_ragdollparams_t; -struct constraint_hingeparams_t; -struct constraint_fixedparams_t; -struct constraint_ballsocketparams_t; -struct constraint_slidingparams_t; -struct constraint_pulleyparams_t; -struct constraint_lengthparams_t; -struct constraint_groupparams_t; - -struct vehicleparams_t; -struct matrix3x4_t; - -struct fluidparams_t; -struct springparams_t; -struct objectparams_t; -struct debugcollide_t; -class CGameTrace; -typedef CGameTrace trace_t; -struct physics_stats_t; -struct physics_performanceparams_t; -struct virtualmeshparams_t; - -//enum PhysInterfaceId_t; -struct physsaveparams_t; -struct physrestoreparams_t; -struct physprerestoreparams_t; - -enum PhysInterfaceId_t -{ - PIID_UNKNOWN, - PIID_IPHYSICSOBJECT, - PIID_IPHYSICSFLUIDCONTROLLER, - PIID_IPHYSICSSPRING, - PIID_IPHYSICSCONSTRAINTGROUP, - PIID_IPHYSICSCONSTRAINT, - PIID_IPHYSICSSHADOWCONTROLLER, - PIID_IPHYSICSPLAYERCONTROLLER, - PIID_IPHYSICSMOTIONCONTROLLER, - PIID_IPHYSICSVEHICLECONTROLLER, - PIID_IPHYSICSGAMETRACE, - - PIID_NUM_TYPES -}; - - -class ISave; -class IRestore; - - -#define VPHYSICS_DEBUG_OVERLAY_INTERFACE_VERSION "VPhysicsDebugOverlay001" - -abstract_class IVPhysicsDebugOverlay -{ -public: - virtual void AddEntityTextOverlay(int ent_index, int line_offset, float duration, int r, int g, int b, int a, const char *format, ...) = 0; - virtual void AddBoxOverlay(const Vector& origin, const Vector& mins, const Vector& max, QAngle const& orientation, int r, int g, int b, int a, float duration) = 0; - virtual void AddTriangleOverlay(const Vector& p1, const Vector& p2, const Vector& p3, int r, int g, int b, int a, bool noDepthTest, float duration) = 0; - virtual void AddLineOverlay(const Vector& origin, const Vector& dest, int r, int g, int b,bool noDepthTest, float duration) = 0; - virtual void AddTextOverlay(const Vector& origin, float duration, const char *format, ...) = 0; - virtual void AddTextOverlay(const Vector& origin, int line_offset, float duration, const char *format, ...) = 0; - virtual void AddScreenTextOverlay(float flXPos, float flYPos,float flDuration, int r, int g, int b, int a, const char *text) = 0; - virtual void AddSweptBoxOverlay(const Vector& start, const Vector& end, const Vector& mins, const Vector& max, const QAngle & angles, int r, int g, int b, int a, float flDuration) = 0; - virtual void AddTextOverlayRGB(const Vector& origin, int line_offset, float duration, float r, float g, float b, float alpha, const char *format, ...) = 0; -}; - -#define VPHYSICS_INTERFACE_VERSION "VPhysics031" - -abstract_class IPhysics : public IAppSystem -{ -public: - virtual IPhysicsEnvironment *CreateEnvironment( void ) = 0; - virtual void DestroyEnvironment( IPhysicsEnvironment * ) = 0; - virtual IPhysicsEnvironment *GetActiveEnvironmentByIndex( int index ) = 0; - - // Creates a fast hash of pairs of objects - // Useful for maintaining a table of object relationships like pairs that do not collide. - virtual IPhysicsObjectPairHash *CreateObjectPairHash() = 0; - virtual void DestroyObjectPairHash( IPhysicsObjectPairHash *pHash ) = 0; - - // holds a cache of these by id. So you can get by id to search for the previously created set - // UNDONE: Sets are currently limited to 32 elements. More elements will return NULL in create. - // NOTE: id is not allowed to be zero. - virtual IPhysicsCollisionSet *FindOrCreateCollisionSet( unsigned int id, int maxElementCount ) = 0; - virtual IPhysicsCollisionSet *FindCollisionSet( unsigned int id ) = 0; - virtual void DestroyAllCollisionSets() = 0; -}; - - -// CPhysConvex is a single convex solid -class CPhysConvex; -// CPhysPolysoup is an abstract triangle soup mesh -class CPhysPolysoup; -class ICollisionQuery; -class IVPhysicsKeyParser; -struct convertconvexparams_t; -class CPackedPhysicsDescription; - -class CPolyhedron; - -// UNDONE: Find a better place for this? Should be in collisionutils, but it's needs VPHYSICS' solver. -struct truncatedcone_t -{ - Vector origin; - Vector normal; - float h; // height of the cone (hl units) - float theta; // cone angle (degrees) -}; - - -#define VPHYSICS_COLLISION_INTERFACE_VERSION "VPhysicsCollision007" - -abstract_class IPhysicsCollision -{ -public: - virtual ~IPhysicsCollision( void ) {} - - // produce a convex element from verts (convex hull around verts) - virtual CPhysConvex *ConvexFromVerts( Vector **pVerts, int vertCount ) = 0; - // produce a convex element from planes (csg of planes) - virtual CPhysConvex *ConvexFromPlanes( float *pPlanes, int planeCount, float mergeDistance ) = 0; - // calculate volume of a convex element - virtual float ConvexVolume( CPhysConvex *pConvex ) = 0; - - virtual float ConvexSurfaceArea( CPhysConvex *pConvex ) = 0; - // store game-specific data in a convex solid - virtual void SetConvexGameData( CPhysConvex *pConvex, unsigned int gameData ) = 0; - // If not converted, free the convex elements with this call - virtual void ConvexFree( CPhysConvex *pConvex ) = 0; - virtual CPhysConvex *BBoxToConvex( const Vector &mins, const Vector &maxs ) = 0; - // produce a convex element from a convex polyhedron - virtual CPhysConvex *ConvexFromConvexPolyhedron( const CPolyhedron &ConvexPolyhedron ) = 0; - // produce a set of convex triangles from a convex polygon, normal is assumed to be on the side with forward point ordering, which should be clockwise, output will need to be able to hold exactly (iPointCount-2) convexes - virtual void ConvexesFromConvexPolygon( const Vector &vPolyNormal, const Vector *pPoints, int iPointCount, CPhysConvex **pOutput ) = 0; - - // concave objects - // create a triangle soup - virtual CPhysPolysoup *PolysoupCreate( void ) = 0; - // destroy the container and memory - virtual void PolysoupDestroy( CPhysPolysoup *pSoup ) = 0; - // add a triangle to the soup - virtual void PolysoupAddTriangle( CPhysPolysoup *pSoup, const Vector &a, const Vector &b, const Vector &c, int materialIndex7bits ) = 0; - // convert the convex into a compiled collision model - virtual CPhysCollide *ConvertPolysoupToCollide( CPhysPolysoup *pSoup, bool useMOPP ) = 0; - - // Convert an array of convex elements to a compiled collision model (this deletes the convex elements) - virtual CPhysCollide *ConvertConvexToCollide( CPhysConvex **pConvex, int convexCount ) = 0; - virtual CPhysCollide *ConvertConvexToCollideParams( CPhysConvex **pConvex, int convexCount, const convertconvexparams_t &convertParams ) = 0; - // Free a collide that was created with ConvertConvexToCollide() - virtual void DestroyCollide( CPhysCollide *pCollide ) = 0; - - // Get the memory size in bytes of the collision model for serialization - virtual int CollideSize( CPhysCollide *pCollide ) = 0; - // serialize the collide to a block of memory - virtual int CollideWrite( char *pDest, CPhysCollide *pCollide, bool bSwap = false ) = 0; - // unserialize the collide from a block of memory - virtual CPhysCollide *UnserializeCollide( char *pBuffer, int size, int index ) = 0; - - // compute the volume of a collide - virtual float CollideVolume( CPhysCollide *pCollide ) = 0; - // compute surface area for tools - virtual float CollideSurfaceArea( CPhysCollide *pCollide ) = 0; - - // Get the support map for a collide in the given direction - virtual Vector CollideGetExtent( const CPhysCollide *pCollide, const Vector &collideOrigin, const QAngle &collideAngles, const Vector &direction ) = 0; - - // Get an AABB for an oriented collision model - virtual void CollideGetAABB( Vector *pMins, Vector *pMaxs, const CPhysCollide *pCollide, const Vector &collideOrigin, const QAngle &collideAngles ) = 0; - - virtual void CollideGetMassCenter( CPhysCollide *pCollide, Vector *pOutMassCenter ) = 0; - virtual void CollideSetMassCenter( CPhysCollide *pCollide, const Vector &massCenter ) = 0; - // get the approximate cross-sectional area projected orthographically on the bbox of the collide - // NOTE: These are fractional areas - unitless. Basically this is the fraction of the OBB on each axis that - // would be visible if the object were rendered orthographically. - // NOTE: This has been precomputed when the collide was built or this function will return 1,1,1 - virtual Vector CollideGetOrthographicAreas( const CPhysCollide *pCollide ) = 0; - virtual void CollideSetOrthographicAreas( CPhysCollide *pCollide, const Vector &areas ) = 0; - - // query the vcollide index in the physics model for the instance - virtual int CollideIndex( const CPhysCollide *pCollide ) = 0; - - // Convert a bbox to a collide - virtual CPhysCollide *BBoxToCollide( const Vector &mins, const Vector &maxs ) = 0; - virtual int GetConvexesUsedInCollideable( const CPhysCollide *pCollideable, CPhysConvex **pOutputArray, int iOutputArrayLimit ) = 0; - - - // Trace an AABB against a collide - virtual void TraceBox( const Vector &start, const Vector &end, const Vector &mins, const Vector &maxs, const CPhysCollide *pCollide, const Vector &collideOrigin, const QAngle &collideAngles, trace_t *ptr ) = 0; - virtual void TraceBox( const Ray_t &ray, const CPhysCollide *pCollide, const Vector &collideOrigin, const QAngle &collideAngles, trace_t *ptr ) = 0; - virtual void TraceBox( const Ray_t &ray, unsigned int contentsMask, IConvexInfo *pConvexInfo, const CPhysCollide *pCollide, const Vector &collideOrigin, const QAngle &collideAngles, trace_t *ptr ) = 0; - - // Trace one collide against another - virtual void TraceCollide( const Vector &start, const Vector &end, const CPhysCollide *pSweepCollide, const QAngle &sweepAngles, const CPhysCollide *pCollide, const Vector &collideOrigin, const QAngle &collideAngles, trace_t *ptr ) = 0; - - // relatively slow test for box vs. truncated cone - virtual bool IsBoxIntersectingCone( const Vector &boxAbsMins, const Vector &boxAbsMaxs, const truncatedcone_t &cone ) = 0; - - // loads a set of solids into a vcollide_t - virtual void VCollideLoad( vcollide_t *pOutput, int solidCount, const char *pBuffer, int size, bool swap = false ) = 0; - // destroyts the set of solids created by VCollideLoad - virtual void VCollideUnload( vcollide_t *pVCollide ) = 0; - - // begins parsing a vcollide. NOTE: This keeps pointers to the text - // If you free the text and call members of IVPhysicsKeyParser, it will crash - virtual IVPhysicsKeyParser *VPhysicsKeyParserCreate( const char *pKeyData ) = 0; - // Free the parser created by VPhysicsKeyParserCreate - virtual void VPhysicsKeyParserDestroy( IVPhysicsKeyParser *pParser ) = 0; - - // creates a list of verts from a collision mesh - virtual int CreateDebugMesh( CPhysCollide const *pCollisionModel, Vector **outVerts ) = 0; - // destroy the list of verts created by CreateDebugMesh - virtual void DestroyDebugMesh( int vertCount, Vector *outVerts ) = 0; - - // create a queryable version of the collision model - virtual ICollisionQuery *CreateQueryModel( CPhysCollide *pCollide ) = 0; - // destroy the queryable version - virtual void DestroyQueryModel( ICollisionQuery *pQuery ) = 0; - - virtual IPhysicsCollision *ThreadContextCreate( void ) = 0; - virtual void ThreadContextDestroy( IPhysicsCollision *pThreadContex ) = 0; - - virtual CPhysCollide *CreateVirtualMesh( const virtualmeshparams_t ¶ms ) = 0; - virtual bool SupportsVirtualMesh() = 0; - - - virtual bool GetBBoxCacheSize( int *pCachedSize, int *pCachedCount ) = 0; - - - // extracts a polyhedron that defines a CPhysConvex's shape - virtual CPolyhedron *PolyhedronFromConvex( CPhysConvex * const pConvex, bool bUseTempPolyhedron ) = 0; - - // dumps info about the collide to Msg() - virtual void OutputDebugInfo( const CPhysCollide *pCollide ) = 0; - virtual unsigned int ReadStat( int statID ) = 0; -}; - -// this can be used to post-process a collision model -abstract_class ICollisionQuery -{ -public: - virtual ~ICollisionQuery() {} - // number of convex pieces in the whole solid - virtual int ConvexCount( void ) = 0; - // triangle count for this convex piece - virtual int TriangleCount( int convexIndex ) = 0; - // get the stored game data - virtual unsigned int GetGameData( int convexIndex ) = 0; - // Gets the triangle's verts to an array - virtual void GetTriangleVerts( int convexIndex, int triangleIndex, Vector *verts ) = 0; - - // UNDONE: This doesn't work!!! - virtual void SetTriangleVerts( int convexIndex, int triangleIndex, const Vector *verts ) = 0; - - // returns the 7-bit material index - virtual int GetTriangleMaterialIndex( int convexIndex, int triangleIndex ) = 0; - // sets a 7-bit material index for this triangle - virtual void SetTriangleMaterialIndex( int convexIndex, int triangleIndex, int index7bits ) = 0; -}; - -//----------------------------------------------------------------------------- -// Purpose: Ray traces from game engine. -//----------------------------------------------------------------------------- -abstract_class IPhysicsGameTrace -{ -public: - virtual void VehicleTraceRay( const Ray_t &ray, void *pVehicle, trace_t *pTrace ) = 0; - virtual void VehicleTraceRayWithWater( const Ray_t &ray, void *pVehicle, trace_t *pTrace ) = 0; - virtual bool VehiclePointInWater( const Vector &vecPoint ) = 0; -}; - -// The caller should implement this to return contents masks per convex on a collide -abstract_class IConvexInfo -{ -public: - virtual unsigned int GetContents( int convexGameData ) = 0; -}; - -class CPhysicsEventHandler; -abstract_class IPhysicsCollisionData -{ -public: - virtual void GetSurfaceNormal( Vector &out ) = 0; // normal points toward second object (object index 1) - virtual void GetContactPoint( Vector &out ) = 0; // contact point of collision (in world space) - virtual void GetContactSpeed( Vector &out ) = 0; // speed of surface 1 relative to surface 0 (in world space) -}; - - -struct vcollisionevent_t -{ - IPhysicsObject *pObjects[2]; - int surfaceProps[2]; - bool isCollision; - bool isShadowCollision; - float deltaCollisionTime; - - float collisionSpeed; // only valid at postCollision - IPhysicsCollisionData *pInternalData; // may change pre/post collision -}; - -abstract_class IPhysicsCollisionEvent -{ -public: - // returns the two objects that collided, time between last collision of these objects - // and an opaque data block of collision information - // NOTE: PreCollision/PostCollision ALWAYS come in matched pairs!!! - virtual void PreCollision( vcollisionevent_t *pEvent ) = 0; - virtual void PostCollision( vcollisionevent_t *pEvent ) = 0; - - // This is a scrape event. The object has scraped across another object consuming the indicated energy - virtual void Friction( IPhysicsObject *pObject, float energy, int surfaceProps, int surfacePropsHit, IPhysicsCollisionData *pData ) = 0; - - virtual void StartTouch( IPhysicsObject *pObject1, IPhysicsObject *pObject2, IPhysicsCollisionData *pTouchData ) = 0; - virtual void EndTouch( IPhysicsObject *pObject1, IPhysicsObject *pObject2, IPhysicsCollisionData *pTouchData ) = 0; - - virtual void FluidStartTouch( IPhysicsObject *pObject, IPhysicsFluidController *pFluid ) = 0; - virtual void FluidEndTouch( IPhysicsObject *pObject, IPhysicsFluidController *pFluid ) = 0; - - virtual void PostSimulationFrame() = 0; - - virtual void ObjectEnterTrigger( IPhysicsObject *pTrigger, IPhysicsObject *pObject ) {} - virtual void ObjectLeaveTrigger( IPhysicsObject *pTrigger, IPhysicsObject *pObject ) {} -}; - - -abstract_class IPhysicsObjectEvent -{ -public: - // these can be used to optimize out queries on sleeping objects - // Called when an object is woken after sleeping - virtual void ObjectWake( IPhysicsObject *pObject ) = 0; - // called when an object goes to sleep (no longer simulating) - virtual void ObjectSleep( IPhysicsObject *pObject ) = 0; -}; - -abstract_class IPhysicsConstraintEvent -{ -public: - // the constraint is now inactive, the game code is required to delete it or re-activate it. - virtual void ConstraintBroken( IPhysicsConstraint * ) = 0; -}; - -struct hlshadowcontrol_params_t -{ - Vector targetPosition; - QAngle targetRotation; - float maxAngular; - float maxDampAngular; - float maxSpeed; - float maxDampSpeed; - float dampFactor; - float teleportDistance; -}; - -// UNDONE: At some point allow this to be parameterized using hlshadowcontrol_params_t. -// All of the infrastructure is in place to do that. -abstract_class IPhysicsShadowController -{ -public: - virtual ~IPhysicsShadowController( void ) {} - - virtual void Update( const Vector &position, const QAngle &angles, float timeOffset ) = 0; - virtual void MaxSpeed( float maxSpeed, float maxAngularSpeed ) = 0; - virtual void StepUp( float height ) = 0; - - // If the teleport distance is non-zero, the object will be teleported to - // the target location when the error exceeds this quantity. - virtual void SetTeleportDistance( float teleportDistance ) = 0; - virtual bool AllowsTranslation() = 0; - virtual bool AllowsRotation() = 0; - - // There are two classes of shadow objects: - // 1) Game physics controlled, shadow follows game physics (this is the default) - // 2) Physically controlled - shadow position is a target, but the game hasn't guaranteed that the space can be occupied by this object - virtual void SetPhysicallyControlled( bool isPhysicallyControlled ) = 0; - virtual bool IsPhysicallyControlled() = 0; - virtual void GetLastImpulse( Vector *pOut ) = 0; - virtual void UseShadowMaterial( bool bUseShadowMaterial ) = 0; - virtual void ObjectMaterialChanged( int materialIndex ) = 0; - - - //Basically get the last inputs to IPhysicsShadowController::Update(), returns last input to timeOffset in Update() - virtual float GetTargetPosition( Vector *pPositionOut, QAngle *pAnglesOut ) = 0; - - virtual float GetTeleportDistance( void ) = 0; - virtual void GetMaxSpeed( float *pMaxSpeedOut, float *pMaxAngularSpeedOut ) = 0; -}; - -class CPhysicsSimObject; -class IPhysicsMotionController; - -// Callback for simulation -class IMotionEvent -{ -public: - // These constants instruct the simulator as to how to apply the values copied to linear & angular - // GLOBAL/LOCAL refer to the coordinate system of the values, whereas acceleration/force determine whether or not - // mass is divided out (forces must be divided by mass to compute acceleration) - enum simresult_e { SIM_NOTHING = 0, SIM_LOCAL_ACCELERATION, SIM_LOCAL_FORCE, SIM_GLOBAL_ACCELERATION, SIM_GLOBAL_FORCE }; - virtual simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) = 0; -}; - - - -abstract_class IPhysicsMotionController -{ -public: - virtual ~IPhysicsMotionController( void ) {} - virtual void SetEventHandler( IMotionEvent *handler ) = 0; - virtual void AttachObject( IPhysicsObject *pObject, bool checkIfAlreadyAttached ) = 0; - virtual void DetachObject( IPhysicsObject *pObject ) = 0; - - // returns the number of objects currently attached to the controller - virtual int CountObjects( void ) = 0; - // NOTE: pObjectList is an array with at least CountObjects() allocated - virtual void GetObjects( IPhysicsObject **pObjectList ) = 0; - // detaches all attached objects - virtual void ClearObjects( void ) = 0; - // wakes up all attached objects - virtual void WakeObjects( void ) = 0; - - enum priority_t - { - LOW_PRIORITY = 0, - MEDIUM_PRIORITY = 1, - HIGH_PRIORITY = 2, - }; - virtual void SetPriority( priority_t priority ) = 0; -}; - -// ------------------- -// Collision filter function. Return 0 if objects should not be tested for collisions, nonzero otherwise -// Install with IPhysicsEnvironment::SetCollisionFilter() -// ------------------- -abstract_class IPhysicsCollisionSolver -{ -public: - virtual int ShouldCollide( IPhysicsObject *pObj0, IPhysicsObject *pObj1, void *pGameData0, void *pGameData1 ) = 0; - virtual int ShouldSolvePenetration( IPhysicsObject *pObj0, IPhysicsObject *pObj1, void *pGameData0, void *pGameData1, float dt ) = 0; - - // pObject has already done the max number of collisions this tick, should we freeze it to save CPU? - virtual bool ShouldFreezeObject( IPhysicsObject *pObject ) = 0; - - // The system has already done too many collision checks, performance will suffer. - // How many more should it do? - virtual int AdditionalCollisionChecksThisTick( int currentChecksDone ) = 0; - - // This list of objects is in a connected contact graph that is too large to solve quickly - // return true to freeze the system, false to solve it - virtual bool ShouldFreezeContacts( IPhysicsObject **pObjectList, int objectCount ) = 0; -}; - -enum PhysicsTraceType_t -{ - VPHYSICS_TRACE_EVERYTHING = 0, - VPHYSICS_TRACE_STATIC_ONLY, - VPHYSICS_TRACE_MOVING_ONLY, - VPHYSICS_TRACE_TRIGGERS_ONLY, - VPHYSICS_TRACE_STATIC_AND_MOVING, -}; - -abstract_class IPhysicsTraceFilter -{ -public: - virtual bool ShouldHitObject( IPhysicsObject *pObject, int contentsMask ) = 0; - virtual PhysicsTraceType_t GetTraceType() const = 0; -}; - -abstract_class IPhysicsEnvironment -{ -public: - virtual ~IPhysicsEnvironment( void ) {} - - virtual void SetDebugOverlay( CreateInterfaceFn debugOverlayFactory ) = 0; - virtual IVPhysicsDebugOverlay *GetDebugOverlay( void ) = 0; - - // gravity is a 3-vector in in/s^2 - virtual void SetGravity( const Vector &gravityVector ) = 0; - virtual void GetGravity( Vector *pGravityVector ) const = 0; - - // air density is in kg / m^3 (water is 1000) - // This controls drag, air that is more dense has more drag. - virtual void SetAirDensity( float density ) = 0; - virtual float GetAirDensity( void ) const = 0; - - // object creation - // create a polygonal object. pCollisionModel was created by the physics builder DLL in a pre-process. - virtual IPhysicsObject *CreatePolyObject( const CPhysCollide *pCollisionModel, int materialIndex, const Vector &position, const QAngle &angles, objectparams_t *pParams ) = 0; - // same as above, but this one cannot move or rotate (infinite mass/inertia) - virtual IPhysicsObject *CreatePolyObjectStatic( const CPhysCollide *pCollisionModel, int materialIndex, const Vector &position, const QAngle &angles, objectparams_t *pParams ) = 0; - // Create a perfectly spherical object - virtual IPhysicsObject *CreateSphereObject( float radius, int materialIndex, const Vector &position, const QAngle &angles, objectparams_t *pParams, bool isStatic ) = 0; - // destroy an object created with CreatePolyObject() or CreatePolyObjectStatic() - virtual void DestroyObject( IPhysicsObject * ) = 0; - - // Create a polygonal fluid body out of the specified collision model - // This object will affect any other objects that collide with the collision model - virtual IPhysicsFluidController *CreateFluidController( IPhysicsObject *pFluidObject, fluidparams_t *pParams ) = 0; - // Destroy an object created with CreateFluidController() - virtual void DestroyFluidController( IPhysicsFluidController * ) = 0; - - // Create a simulated spring that connects 2 objects - virtual IPhysicsSpring *CreateSpring( IPhysicsObject *pObjectStart, IPhysicsObject *pObjectEnd, springparams_t *pParams ) = 0; - virtual void DestroySpring( IPhysicsSpring * ) = 0; - - // Create a constraint in the space of pReferenceObject which is attached by the constraint to pAttachedObject - virtual IPhysicsConstraint *CreateRagdollConstraint( IPhysicsObject *pReferenceObject, IPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_ragdollparams_t &ragdoll ) = 0; - virtual IPhysicsConstraint *CreateHingeConstraint( IPhysicsObject *pReferenceObject, IPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_hingeparams_t &hinge ) = 0; - virtual IPhysicsConstraint *CreateFixedConstraint( IPhysicsObject *pReferenceObject, IPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_fixedparams_t &fixed ) = 0; - virtual IPhysicsConstraint *CreateSlidingConstraint( IPhysicsObject *pReferenceObject, IPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_slidingparams_t &sliding ) = 0; - virtual IPhysicsConstraint *CreateBallsocketConstraint( IPhysicsObject *pReferenceObject, IPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_ballsocketparams_t &ballsocket ) = 0; - virtual IPhysicsConstraint *CreatePulleyConstraint( IPhysicsObject *pReferenceObject, IPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_pulleyparams_t &pulley ) = 0; - virtual IPhysicsConstraint *CreateLengthConstraint( IPhysicsObject *pReferenceObject, IPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_lengthparams_t &length ) = 0; - - virtual void DestroyConstraint( IPhysicsConstraint * ) = 0; - - virtual IPhysicsConstraintGroup *CreateConstraintGroup( const constraint_groupparams_t &groupParams ) = 0; - virtual void DestroyConstraintGroup( IPhysicsConstraintGroup *pGroup ) = 0; - - virtual IPhysicsShadowController *CreateShadowController( IPhysicsObject *pObject, bool allowTranslation, bool allowRotation ) = 0; - virtual void DestroyShadowController( IPhysicsShadowController * ) = 0; - - virtual IPhysicsPlayerController *CreatePlayerController( IPhysicsObject *pObject ) = 0; - virtual void DestroyPlayerController( IPhysicsPlayerController * ) = 0; - - virtual IPhysicsMotionController *CreateMotionController( IMotionEvent *pHandler ) = 0; - virtual void DestroyMotionController( IPhysicsMotionController *pController ) = 0; - - virtual IPhysicsVehicleController *CreateVehicleController( IPhysicsObject *pVehicleBodyObject, const vehicleparams_t ¶ms, unsigned int nVehicleType, IPhysicsGameTrace *pGameTrace ) = 0; - virtual void DestroyVehicleController( IPhysicsVehicleController * ) = 0; - - // install a function to filter collisions/penentration - virtual void SetCollisionSolver( IPhysicsCollisionSolver *pSolver ) = 0; - - // run the simulator for deltaTime seconds - virtual void Simulate( float deltaTime ) = 0; - // true if currently running the simulator (i.e. in a callback during physenv->Simulate()) - virtual bool IsInSimulation() const = 0; - - // Manage the timestep (period) of the simulator. The main functions are all integrated with - // this period as dt. - virtual float GetSimulationTimestep() const = 0; - virtual void SetSimulationTimestep( float timestep ) = 0; - - // returns the current simulation clock's value. This is an absolute time. - virtual float GetSimulationTime() const = 0; - virtual void ResetSimulationClock() = 0; - // returns the current simulation clock's value at the next frame. This is an absolute time. - virtual float GetNextFrameTime( void ) const = 0; - - // Collision callbacks (game code collision response) - virtual void SetCollisionEventHandler( IPhysicsCollisionEvent *pCollisionEvents ) = 0; - virtual void SetObjectEventHandler( IPhysicsObjectEvent *pObjectEvents ) = 0; - virtual void SetConstraintEventHandler( IPhysicsConstraintEvent *pConstraintEvents ) = 0; - - virtual void SetQuickDelete( bool bQuick ) = 0; - - virtual int GetActiveObjectCount() const = 0; - virtual void GetActiveObjects( IPhysicsObject **pOutputObjectList ) const = 0; - virtual const IPhysicsObject **GetObjectList( int *pOutputObjectCount ) const = 0; - virtual bool TransferObject( IPhysicsObject *pObject, IPhysicsEnvironment *pDestinationEnvironment ) = 0; - - virtual void CleanupDeleteList( void ) = 0; - virtual void EnableDeleteQueue( bool enable ) = 0; - - // Save/Restore methods - virtual bool Save( const physsaveparams_t ¶ms ) = 0; - virtual void PreRestore( const physprerestoreparams_t ¶ms ) = 0; - virtual bool Restore( const physrestoreparams_t ¶ms ) = 0; - virtual void PostRestore() = 0; - - // Debugging: - virtual bool IsCollisionModelUsed( CPhysCollide *pCollide ) const = 0; - - // Physics world version of the enginetrace API: - virtual void TraceRay( const Ray_t &ray, unsigned int fMask, IPhysicsTraceFilter *pTraceFilter, trace_t *pTrace ) = 0; - virtual void SweepCollideable( const CPhysCollide *pCollide, const Vector &vecAbsStart, const Vector &vecAbsEnd, - const QAngle &vecAngles, unsigned int fMask, IPhysicsTraceFilter *pTraceFilter, trace_t *pTrace ) = 0; - - // performance tuning - virtual void GetPerformanceSettings( physics_performanceparams_t *pOutput ) const = 0; - virtual void SetPerformanceSettings( const physics_performanceparams_t *pSettings ) = 0; - - // perf/cost statistics - virtual void ReadStats( physics_stats_t *pOutput ) = 0; - virtual void ClearStats() = 0; - - virtual unsigned int GetObjectSerializeSize( IPhysicsObject *pObject ) const = 0; - virtual void SerializeObjectToBuffer( IPhysicsObject *pObject, unsigned char *pBuffer, unsigned int bufferSize ) = 0; - virtual IPhysicsObject *UnserializeObjectFromBuffer( void *pGameData, unsigned char *pBuffer, unsigned int bufferSize, bool enableCollisions ) = 0; - - - virtual void EnableConstraintNotify( bool bEnable ) = 0; - virtual void DebugCheckContacts(void) = 0; -}; - -enum callbackflags -{ - CALLBACK_GLOBAL_COLLISION = 0x0001, - CALLBACK_GLOBAL_FRICTION = 0x0002, - CALLBACK_GLOBAL_TOUCH = 0x0004, - CALLBACK_GLOBAL_TOUCH_STATIC = 0x0008, - CALLBACK_SHADOW_COLLISION = 0x0010, - CALLBACK_GLOBAL_COLLIDE_STATIC = 0x0020, - CALLBACK_IS_VEHICLE_WHEEL = 0x0040, - CALLBACK_FLUID_TOUCH = 0x0100, - CALLBACK_NEVER_DELETED = 0x0200, // HACKHACK: This means this object will never be deleted (set on the world) - CALLBACK_MARKED_FOR_DELETE = 0x0400, // This allows vphysics to skip some work for this object since it will be - // deleted later this frame. (Set automatically by destroy calls) - CALLBACK_ENABLING_COLLISION = 0x0800, // This is active during the time an object is enabling collisions - // allows us to skip collisions between "new" objects and objects marked for delete - CALLBACK_DO_FLUID_SIMULATION = 0x1000, // remove this to opt out of fluid simulations - CALLBACK_IS_PLAYER_CONTROLLER= 0x2000, // HACKHACK: Set this on players until player cotrollers are unified with shadow controllers - CALLBACK_CHECK_COLLISION_DISABLE = 0x4000, - CALLBACK_MARKED_FOR_TEST = 0x8000, // debug -- marked object is being debugged -}; - -abstract_class IPhysicsObject -{ -public: - virtual ~IPhysicsObject( void ) {} - - // returns true if this object is static/unmoveable - // NOTE: returns false for objects that are not created static, but set EnableMotion(false); - // Call IsMoveable() to find if the object is static OR has motion disabled - virtual bool IsStatic() const = 0; - virtual bool IsAsleep() const = 0; - virtual bool IsTrigger() const = 0; - virtual bool IsFluid() const = 0; // fluids are special triggers with fluid controllers attached, they return true to IsTrigger() as well! - virtual bool IsHinged() const = 0; - virtual bool IsCollisionEnabled() const = 0; - virtual bool IsGravityEnabled() const = 0; - virtual bool IsDragEnabled() const = 0; - virtual bool IsMotionEnabled() const = 0; - virtual bool IsMoveable() const = 0; // legacy: IsMotionEnabled() && !IsStatic() - virtual bool IsAttachedToConstraint(bool bExternalOnly) const = 0; - - // Enable / disable collisions for this object - virtual void EnableCollisions( bool enable ) = 0; - // Enable / disable gravity for this object - virtual void EnableGravity( bool enable ) = 0; - // Enable / disable air friction / drag for this object - virtual void EnableDrag( bool enable ) = 0; - // Enable / disable motion (pin / unpin the object) - virtual void EnableMotion( bool enable ) = 0; - - // Game can store data in each object (link back to game object) - virtual void SetGameData( void *pGameData ) = 0; - virtual void *GetGameData( void ) const = 0; - // This flags word can be defined by the game as well - virtual void SetGameFlags( unsigned short userFlags ) = 0; - virtual unsigned short GetGameFlags( void ) const = 0; - virtual void SetGameIndex( unsigned short gameIndex ) = 0; - virtual unsigned short GetGameIndex( void ) const = 0; - - // setup various callbacks for this object - virtual void SetCallbackFlags( unsigned short callbackflags ) = 0; - // get the current callback state for this object - virtual unsigned short GetCallbackFlags( void ) const = 0; - - // "wakes up" an object - // NOTE: ALL OBJECTS ARE "Asleep" WHEN CREATED - virtual void Wake( void ) = 0; - virtual void Sleep( void ) = 0; - // call this when the collision filter conditions change due to this - // object's state (e.g. changing solid type or collision group) - virtual void RecheckCollisionFilter() = 0; - // NOTE: Contact points aren't updated when collision rules change, call this to force an update - // UNDONE: Force this in RecheckCollisionFilter() ? - virtual void RecheckContactPoints() = 0; - - // mass accessors - virtual void SetMass( float mass ) = 0; - virtual float GetMass( void ) const = 0; - // get 1/mass (it's cached) - virtual float GetInvMass( void ) const = 0; - virtual Vector GetInertia( void ) const = 0; - virtual Vector GetInvInertia( void ) const = 0; - virtual void SetInertia( const Vector &inertia ) = 0; - - virtual void SetDamping( const float *speed, const float *rot ) = 0; - virtual void GetDamping( float *speed, float *rot ) const = 0; - - // coefficients are optional, pass either - virtual void SetDragCoefficient( float *pDrag, float *pAngularDrag ) = 0; - virtual void SetBuoyancyRatio( float ratio ) = 0; // Override bouyancy - - // material index - virtual int GetMaterialIndex() const = 0; - virtual void SetMaterialIndex( int materialIndex ) = 0; - - // contents bits - virtual unsigned int GetContents() const = 0; - virtual void SetContents( unsigned int contents ) = 0; - - // Get the radius if this is a sphere object (zero if this is a polygonal mesh) - virtual float GetSphereRadius() const = 0; - virtual float GetEnergy() const = 0; - virtual Vector GetMassCenterLocalSpace() const = 0; - - // NOTE: This will teleport the object - virtual void SetPosition( const Vector &worldPosition, const QAngle &angles, bool isTeleport ) = 0; - virtual void SetPositionMatrix( const matrix3x4_t&matrix, bool isTeleport ) = 0; - - virtual void GetPosition( Vector *worldPosition, QAngle *angles ) const = 0; - virtual void GetPositionMatrix( matrix3x4_t *positionMatrix ) const = 0; - // force the velocity to a new value - // NOTE: velocity is in worldspace, angularVelocity is relative to the object's - // local axes (just like pev->velocity, pev->avelocity) - virtual void SetVelocity( const Vector *velocity, const AngularImpulse *angularVelocity ) = 0; - - // like the above, but force the change into the simulator immediately - virtual void SetVelocityInstantaneous( const Vector *velocity, const AngularImpulse *angularVelocity ) = 0; - - // NOTE: velocity is in worldspace, angularVelocity is relative to the object's - // local axes (just like pev->velocity, pev->avelocity) - virtual void GetVelocity( Vector *velocity, AngularImpulse *angularVelocity ) const = 0; - - // NOTE: These are velocities, not forces. i.e. They will have the same effect regardless of - // the object's mass or inertia - virtual void AddVelocity( const Vector *velocity, const AngularImpulse *angularVelocity ) = 0; - // gets a velocity in the object's local frame of reference at a specific point - virtual void GetVelocityAtPoint( const Vector &worldPosition, Vector *pVelocity ) const = 0; - // gets the velocity actually moved by the object in the last simulation update - virtual void GetImplicitVelocity( Vector *velocity, AngularImpulse *angularVelocity ) const = 0; - // NOTE: These are here for convenience, but you can do them yourself by using the matrix - // returned from GetPositionMatrix() - // convenient coordinate system transformations (params - dest, src) - virtual void LocalToWorld( Vector *worldPosition, const Vector &localPosition ) const = 0; - virtual void WorldToLocal( Vector *localPosition, const Vector &worldPosition ) const = 0; - - // transforms a vector (no translation) from object-local to world space - virtual void LocalToWorldVector( Vector *worldVector, const Vector &localVector ) const = 0; - // transforms a vector (no translation) from world to object-local space - virtual void WorldToLocalVector( Vector *localVector, const Vector &worldVector ) const = 0; - - // push on an object - // force vector is direction & magnitude of impulse kg in / s - virtual void ApplyForceCenter( const Vector &forceVector ) = 0; - virtual void ApplyForceOffset( const Vector &forceVector, const Vector &worldPosition ) = 0; - // apply torque impulse. This will change the angular velocity on the object. - // HL Axes, kg degrees / s - virtual void ApplyTorqueCenter( const AngularImpulse &torque ) = 0; - - // Calculates the force/torque on the center of mass for an offset force impulse (pass output to ApplyForceCenter / ApplyTorqueCenter) - virtual void CalculateForceOffset( const Vector &forceVector, const Vector &worldPosition, Vector *centerForce, AngularImpulse *centerTorque ) const = 0; - // Calculates the linear/angular velocities on the center of mass for an offset force impulse (pass output to AddVelocity) - virtual void CalculateVelocityOffset( const Vector &forceVector, const Vector &worldPosition, Vector *centerVelocity, AngularImpulse *centerAngularVelocity ) const = 0; - // calculate drag scale - virtual float CalculateLinearDrag( const Vector &unitDirection ) const = 0; - virtual float CalculateAngularDrag( const Vector &objectSpaceRotationAxis ) const = 0; - - // returns true if the object is in contact with another object - // if true, puts a point on the contact surface in contactPoint, and - // a pointer to the object in contactObject - // NOTE: You can pass NULL for either to avoid computations - // BUGBUG: Use CreateFrictionSnapshot instead of this - this is a simple hack - virtual bool GetContactPoint( Vector *contactPoint, IPhysicsObject **contactObject ) const = 0; - - // refactor this a bit - move some of this to IPhysicsShadowController - virtual void SetShadow( float maxSpeed, float maxAngularSpeed, bool allowPhysicsMovement, bool allowPhysicsRotation ) = 0; - virtual void UpdateShadow( const Vector &targetPosition, const QAngle &targetAngles, bool tempDisableGravity, float timeOffset ) = 0; - - // returns number of ticks since last Update() call - virtual int GetShadowPosition( Vector *position, QAngle *angles ) const = 0; - virtual IPhysicsShadowController *GetShadowController( void ) const = 0; - virtual void RemoveShadowController() = 0; - // applies the math of the shadow controller to this object. - // for use in your own controllers - // returns the new value of secondsToArrival with dt time elapsed - virtual float ComputeShadowControl( const hlshadowcontrol_params_t ¶ms, float secondsToArrival, float dt ) = 0; - - - virtual const CPhysCollide *GetCollide( void ) const = 0; - virtual const char *GetName() const = 0; - - virtual void BecomeTrigger() = 0; - virtual void RemoveTrigger() = 0; - - // sets the object to be hinged. Fixed it place, but able to rotate around one axis. - virtual void BecomeHinged( int localAxis ) = 0; - // resets the object to original state - virtual void RemoveHinged() = 0; - - // used to iterate the contact points of an object - virtual IPhysicsFrictionSnapshot *CreateFrictionSnapshot() = 0; - virtual void DestroyFrictionSnapshot( IPhysicsFrictionSnapshot *pSnapshot ) = 0; - - // dumps info about the object to Msg() - virtual void OutputDebugInfo() const = 0; - -}; - - -abstract_class IPhysicsSpring -{ -public: - virtual ~IPhysicsSpring( void ) {} - virtual void GetEndpoints( Vector *worldPositionStart, Vector *worldPositionEnd ) = 0; - virtual void SetSpringConstant( float flSpringContant) = 0; - virtual void SetSpringDamping( float flSpringDamping) = 0; - virtual void SetSpringLength( float flSpringLenght) = 0; - - // Get the starting object - virtual IPhysicsObject *GetStartObject( void ) = 0; - - // Get the end object - virtual IPhysicsObject *GetEndObject( void ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Purpose: These properties are defined per-material. This is accessible at -// each triangle in a collision mesh -//----------------------------------------------------------------------------- -struct surfacephysicsparams_t -{ -// vphysics physical properties - float friction; - float elasticity; // collision elasticity - used to compute coefficient of restitution - float density; // physical density (in kg / m^3) - float thickness; // material thickness if not solid (sheet materials) in inches - float dampening; -}; - -struct surfaceaudioparams_t -{ -// sounds / audio data - float reflectivity; // like elasticity, but how much sound should be reflected by this surface - float hardnessFactor; // like elasticity, but only affects impact sound choices - float roughnessFactor; // like friction, but only affects scrape sound choices - -// audio thresholds - float roughThreshold; // surface roughness > this causes "rough" scrapes, < this causes "smooth" scrapes - float hardThreshold; // surface hardness > this causes "hard" impacts, < this causes "soft" impacts - float hardVelocityThreshold; // collision velocity > this causes "hard" impacts, < this causes "soft" impacts - // NOTE: Hard impacts must meet both hardnessFactor AND velocity thresholds -}; - -struct surfacesoundnames_t -{ - unsigned short stepleft; - unsigned short stepright; - - unsigned short impactSoft; - unsigned short impactHard; - - unsigned short scrapeSmooth; - unsigned short scrapeRough; - - unsigned short bulletImpact; - unsigned short rolling; - - unsigned short breakSound; - unsigned short strainSound; -}; - -struct surfacesoundhandles_t -{ - short stepleft; - short stepright; - - short impactSoft; - short impactHard; - - short scrapeSmooth; - short scrapeRough; - - short bulletImpact; - short rolling; - - short breakSound; - short strainSound; -}; - -struct surfacegameprops_t -{ -// game movement data - float maxSpeedFactor; // Modulates player max speed when walking on this surface - float jumpFactor; // Indicates how much higher the player should jump when on the surface -// Game-specific data - unsigned short material; - // Indicates whether or not the player is on a ladder. - unsigned char climbable; - unsigned char pad; -}; - -//----------------------------------------------------------------------------- -// Purpose: Each different material has an entry like this -//----------------------------------------------------------------------------- -struct surfacedata_t -{ - surfacephysicsparams_t physics; // physics parameters - surfaceaudioparams_t audio; // audio parameters - surfacesoundnames_t sounds; // names of linked sounds - surfacegameprops_t game; // Game data / properties - - surfacesoundhandles_t soundhandles; -}; - -#define VPHYSICS_SURFACEPROPS_INTERFACE_VERSION "VPhysicsSurfaceProps001" -abstract_class IPhysicsSurfaceProps -{ -public: - virtual ~IPhysicsSurfaceProps( void ) {} - - // parses a text file containing surface prop keys - virtual int ParseSurfaceData( const char *pFilename, const char *pTextfile ) = 0; - // current number of entries in the database - virtual int SurfacePropCount( void ) const = 0; - - virtual int GetSurfaceIndex( const char *pSurfacePropName ) const = 0; - virtual void GetPhysicsProperties( int surfaceDataIndex, float *density, float *thickness, float *friction, float *elasticity ) const = 0; - - virtual surfacedata_t *GetSurfaceData( int surfaceDataIndex ) = 0; - virtual const char *GetString( unsigned short stringTableIndex ) const = 0; - - - virtual const char *GetPropName( int surfaceDataIndex ) const = 0; - - // sets the global index table for world materials - // UNDONE: Make this per-CPhysCollide - virtual void SetWorldMaterialIndexTable( int *pMapArray, int mapSize ) = 0; - - // NOTE: Same as GetPhysicsProperties, but maybe more convenient - virtual void GetPhysicsParameters( int surfaceDataIndex, surfacephysicsparams_t *pParamsOut ) const = 0; -}; - -abstract_class IPhysicsFluidController -{ -public: - virtual ~IPhysicsFluidController( void ) {} - - virtual void SetGameData( void *pGameData ) = 0; - virtual void *GetGameData( void ) const = 0; - - virtual void GetSurfacePlane( Vector *pNormal, float *pDist ) const = 0; - virtual float GetDensity() const = 0; - virtual void WakeAllSleepingObjects() = 0; - virtual int GetContents() const = 0; -}; - - -//----------------------------------------------------------------------------- -// Purpose: parameter block for creating fluid dynamic motion -// UNDONE: Expose additional fluid model paramters? -//----------------------------------------------------------------------------- -struct fluidparams_t -{ - Vector4D surfacePlane; // x,y,z normal, dist (plane constant) fluid surface - Vector currentVelocity; // velocity of the current in inches/second - float damping; // damping factor for buoyancy (tweak) - float torqueFactor; - float viscosityFactor; - void *pGameData; - bool useAerodynamics;// true if this controller should calculate surface pressure - int contents; - - fluidparams_t() {} - fluidparams_t( fluidparams_t const& src ) - { - Vector4DCopy( src.surfacePlane, surfacePlane ); - VectorCopy( src.currentVelocity, currentVelocity ); - damping = src.damping; - torqueFactor = src.torqueFactor; - viscosityFactor = src.viscosityFactor; - contents = src.contents; - } -}; - -//----------------------------------------------------------------------------- -// Purpose: parameter block for creating linear springs -// UNDONE: Expose additional spring model paramters? -//----------------------------------------------------------------------------- -struct springparams_t -{ - springparams_t() - { - memset( this, 0, sizeof(*this) ); - } - float constant; // spring constant - float naturalLength;// relaxed length - float damping; // damping factor - float relativeDamping; // relative damping (damping proportional to the change in the relative position of the objects) - Vector startPosition; - Vector endPosition; - bool useLocalPositions; // start & end Position are in local space to start and end objects if this is true - bool onlyStretch; // only apply forces when the length is greater than the natural length -}; - -//----------------------------------------------------------------------------- -// Purpose: parameter block for creating polygonal objects -//----------------------------------------------------------------------------- -struct objectparams_t -{ - Vector *massCenterOverride; - float mass; - float inertia; - float damping; - float rotdamping; - float rotInertiaLimit; - const char *pName; // used only for debugging - void *pGameData; - float volume; - float dragCoefficient; - bool enableCollisions; -}; - -struct convertconvexparams_t -{ - bool buildOuterConvexHull; - bool buildDragAxisAreas; - bool buildOptimizedTraceTables; - float dragAreaEpsilon; - CPhysConvex *pForcedOuterHull; - - void Defaults() - { - dragAreaEpsilon = 0.25f; // 0.5in x 0.5in square - buildOuterConvexHull = false; - buildDragAxisAreas = false; - buildOptimizedTraceTables = false; - pForcedOuterHull = NULL; - } -}; - -//----------------------------------------------------------------------------- -// Physics interface IDs -// -// Note that right now the order of the enum also defines the order of save/load - - -//----------------------------------------------------------------------------- -// Purpose: parameter blocks for save and load operations -//----------------------------------------------------------------------------- -struct physsaveparams_t -{ - ISave *pSave; - void *pObject; - PhysInterfaceId_t type; -}; - -struct physrestoreparams_t -{ - IRestore *pRestore; - void **ppObject; - PhysInterfaceId_t type; - void *pGameData; - const char *pName; // used only for debugging - const CPhysCollide *pCollisionModel; - IPhysicsEnvironment *pEnvironment; - IPhysicsGameTrace *pGameTrace; -}; - -struct physrecreateparams_t -{ - void *pOldObject; - void *pNewObject; -}; - -struct physprerestoreparams_t -{ - int recreatedObjectCount; - physrecreateparams_t recreatedObjectList[1]; -}; - -//------------------------------------- - -#define DEFINE_PIID( type, enumval ) \ - template <> inline PhysInterfaceId_t GetPhysIID( type ** ) { return enumval; } - -template inline PhysInterfaceId_t GetPhysIID(PHYSPTR **); // will get link error if no match - -DEFINE_PIID( IPhysicsObject, PIID_IPHYSICSOBJECT ); -DEFINE_PIID( IPhysicsFluidController, PIID_IPHYSICSFLUIDCONTROLLER ); -DEFINE_PIID( IPhysicsSpring, PIID_IPHYSICSSPRING ); -DEFINE_PIID( IPhysicsConstraintGroup, PIID_IPHYSICSCONSTRAINTGROUP ); -DEFINE_PIID( IPhysicsConstraint, PIID_IPHYSICSCONSTRAINT ); -DEFINE_PIID( IPhysicsShadowController, PIID_IPHYSICSSHADOWCONTROLLER ); -DEFINE_PIID( IPhysicsPlayerController, PIID_IPHYSICSPLAYERCONTROLLER ); -DEFINE_PIID( IPhysicsMotionController, PIID_IPHYSICSMOTIONCONTROLLER ); -DEFINE_PIID( IPhysicsVehicleController, PIID_IPHYSICSVEHICLECONTROLLER ); -DEFINE_PIID( IPhysicsGameTrace, PIID_IPHYSICSGAMETRACE ); - -//----------------------------------------------------------------------------- - -#endif // VPHYSICS_INTERFACE_H diff --git a/public/vphysics_interfaceV30.h b/public/vphysics_interfaceV30.h deleted file mode 100644 index ec65b6660..000000000 --- a/public/vphysics_interfaceV30.h +++ /dev/null @@ -1,1064 +0,0 @@ -//========= Copyright 1996-2004, Valve LLC, All rights reserved. ============ -// -// Purpose: Public interfaces to vphysics DLL -// -// $NoKeywords: $ -//============================================================================= - -#ifndef VPHYSICS_INTERFACE_V30_H -#define VPHYSICS_INTERFACE_V30_H -#ifdef _WIN32 -#pragma once -#endif - -#include "interface.h" -#include "mathlib/vector.h" -#include "mathlib/vector4d.h" -#include "vcollide.h" - - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class IPhysicsObjectPairHash; -class IPhysicsConstraint; -class IPhysicsConstraintGroup; -class IPhysicsFluidController; -class IPhysicsSpring; -class IPhysicsVehicleController; -class IPhysicsCollisionSet; -class IPhysicsPlayerController; -class IPhysicsFrictionSnapshot; -struct Ray_t; -struct constraint_ragdollparams_t; -struct constraint_hingeparams_t; -struct constraint_fixedparams_t; -struct constraint_ballsocketparams_t; -struct constraint_slidingparams_t; -struct constraint_pulleyparams_t; -struct constraint_lengthparams_t; -struct constraint_groupparams_t; -struct vehicleparams_t; -struct matrix3x4_t; -struct fluidparams_t; -struct springparams_t; -struct objectparams_t; -struct debugcollide_t; -class CGameTrace; -typedef CGameTrace trace_t; -struct physics_stats_t; -struct physics_performanceparams_t; -struct physsaveparams_t; -struct physrestoreparams_t; -struct physprerestoreparams_t; - -namespace VPhysicsInterfaceV30 -{ - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class IPhysicsObject; -class IPhysicsEnvironment; -class IPhysicsSurfaceProps; -class IConvexInfo; - -enum PhysInterfaceId_t -{ - PIID_UNKNOWN, - PIID_IPHYSICSOBJECT, - PIID_IPHYSICSFLUIDCONTROLLER, - PIID_IPHYSICSSPRING, - PIID_IPHYSICSCONSTRAINTGROUP, - PIID_IPHYSICSCONSTRAINT, - PIID_IPHYSICSSHADOWCONTROLLER, - PIID_IPHYSICSPLAYERCONTROLLER, - PIID_IPHYSICSMOTIONCONTROLLER, - PIID_IPHYSICSVEHICLECONTROLLER, - PIID_IPHYSICSGAMETRACE, - - PIID_NUM_TYPES -}; - - -class ISave; -class IRestore; - - -#define VPHYSICS_DEBUG_OVERLAY_INTERFACE_VERSION_1 "VPhysicsDebugOverlay001" - -abstract_class IVPhysicsDebugOverlay -{ -public: - virtual void AddEntityTextOverlay(int ent_index, int line_offset, float duration, int r, int g, int b, int a, const char *format, ...) = 0; - virtual void AddBoxOverlay(const Vector& origin, const Vector& mins, const Vector& max, QAngle const& orientation, int r, int g, int b, int a, float duration) = 0; - virtual void AddTriangleOverlay(const Vector& p1, const Vector& p2, const Vector& p3, int r, int g, int b, int a, bool noDepthTest, float duration) = 0; - virtual void AddLineOverlay(const Vector& origin, const Vector& dest, int r, int g, int b,bool noDepthTest, float duration) = 0; - virtual void AddTextOverlay(const Vector& origin, float duration, const char *format, ...) = 0; - virtual void AddTextOverlay(const Vector& origin, int line_offset, float duration, const char *format, ...) = 0; - virtual void AddScreenTextOverlay(float flXPos, float flYPos,float flDuration, int r, int g, int b, int a, const char *text) = 0; - virtual void AddSweptBoxOverlay(const Vector& start, const Vector& end, const Vector& mins, const Vector& max, const QAngle & angles, int r, int g, int b, int a, float flDuration) = 0; - virtual void AddTextOverlayRGB(const Vector& origin, int line_offset, float duration, float r, float g, float b, float alpha, const char *format, ...) = 0; -}; - -#define VPHYSICS_INTERFACE_VERSION_30 "VPhysics030" - -abstract_class IPhysics -{ -public: - virtual IPhysicsEnvironment *CreateEnvironment( void ) = 0; - virtual void DestroyEnvironment( IPhysicsEnvironment * ) = 0; - virtual IPhysicsEnvironment *GetActiveEnvironmentByIndex( int index ) = 0; - - // Creates a fast hash of pairs of objects - // Useful for maintaining a table of object relationships like pairs that do not collide. - virtual IPhysicsObjectPairHash *CreateObjectPairHash() = 0; - virtual void DestroyObjectPairHash( IPhysicsObjectPairHash *pHash ) = 0; - - // holds a cache of these by id. So you can get by id to search for the previously created set - // UNDONE: Sets are currently limited to 32 elements. More elements will return NULL in create. - // NOTE: id is not allowed to be zero. - virtual IPhysicsCollisionSet *FindOrCreateCollisionSet( unsigned int id, int maxElementCount ) = 0; - virtual IPhysicsCollisionSet *FindCollisionSet( unsigned int id ) = 0; - virtual void DestroyAllCollisionSets() = 0; -}; - - -// CPhysConvex is a single convex solid -class CPhysConvex; -// CPhysPolysoup is an abstract triangle soup mesh -class CPhysPolysoup; -class ICollisionQuery; -class IVPhysicsKeyParser; -struct convertconvexparams_t; - -// UNDONE: Find a better place for this? Should be in collisionutils, but it's needs VPHYSICS' solver. -struct truncatedcone_t -{ - Vector origin; - Vector normal; - float h; // height of the cone (hl units) - float theta; // cone angle (degrees) -}; - - -#define VPHYSICS_COLLISION_INTERFACE_VERSION_7 "VPhysicsCollision007" - -abstract_class IPhysicsCollision -{ -public: - virtual ~IPhysicsCollision( void ) {} - - // produce a convex element from verts (convex hull around verts) - virtual CPhysConvex *ConvexFromVerts( Vector **pVerts, int vertCount ) = 0; - // produce a convex element from planes (csg of planes) - virtual CPhysConvex *ConvexFromPlanes( float *pPlanes, int planeCount, float mergeDistance ) = 0; - // calculate volume of a convex element - virtual float ConvexVolume( CPhysConvex *pConvex ) = 0; - - // Convert an array of convex elements to a compiled collision model (this deletes the convex elements) - virtual CPhysCollide *ConvertConvexToCollide( CPhysConvex **pConvex, int convexCount ) = 0; - - virtual float ConvexSurfaceArea( CPhysConvex *pConvex ) = 0; - // store game-specific data in a convex solid - virtual void SetConvexGameData( CPhysConvex *pConvex, unsigned int gameData ) = 0; - // If not converted, free the convex elements with this call - virtual void ConvexFree( CPhysConvex *pConvex ) = 0; - - // concave objects - // create a triangle soup - virtual CPhysPolysoup *PolysoupCreate( void ) = 0; - // destroy the container and memory - virtual void PolysoupDestroy( CPhysPolysoup *pSoup ) = 0; - // add a triangle to the soup - virtual void PolysoupAddTriangle( CPhysPolysoup *pSoup, const Vector &a, const Vector &b, const Vector &c, int materialIndex7bits ) = 0; - // convert the convex into a compiled collision model - virtual CPhysCollide *ConvertPolysoupToCollide( CPhysPolysoup *pSoup, bool useMOPP ) = 0; - - // Get the memory size in bytes of the collision model for serialization - virtual int CollideSize( CPhysCollide *pCollide ) = 0; - // serialize the collide to a block of memory - virtual int CollideWrite( char *pDest, CPhysCollide *pCollide ) = 0; - - // Free a collide that was created with ConvertConvexToCollide() - // UNDONE: Move this up near the other Collide routines when the version is changed - virtual void DestroyCollide( CPhysCollide *pCollide ) = 0; - // compute the volume of a collide - virtual float CollideVolume( CPhysCollide *pCollide ) = 0; - // compute surface area for tools - virtual float CollideSurfaceArea( CPhysCollide *pCollide ) = 0; - - // Get the support map for a collide in the given direction - virtual Vector CollideGetExtent( const CPhysCollide *pCollide, const Vector &collideOrigin, const QAngle &collideAngles, const Vector &direction ) = 0; - - // Get an AABB for an oriented collision model - virtual void CollideGetAABB( Vector &mins, Vector &maxs, const CPhysCollide *pCollide, const Vector &collideOrigin, const QAngle &collideAngles ) = 0; - - // Convert a bbox to a collide - virtual CPhysCollide *BBoxToCollide( const Vector &mins, const Vector &maxs ) = 0; - - - // Trace an AABB against a collide - virtual void TraceBox( const Vector &start, const Vector &end, const Vector &mins, const Vector &maxs, const CPhysCollide *pCollide, const Vector &collideOrigin, const QAngle &collideAngles, trace_t *ptr ) = 0; - virtual void TraceBox( const Ray_t &ray, const CPhysCollide *pCollide, const Vector &collideOrigin, const QAngle &collideAngles, trace_t *ptr ) = 0; - - // Trace one collide against another - virtual void TraceCollide( const Vector &start, const Vector &end, const CPhysCollide *pSweepCollide, const QAngle &sweepAngles, const CPhysCollide *pCollide, const Vector &collideOrigin, const QAngle &collideAngles, trace_t *ptr ) = 0; - - // loads a set of solids into a vcollide_t - virtual void VCollideLoad( vcollide_t *pOutput, int solidCount, const char *pBuffer, int size ) = 0; - // destroyts the set of solids created by VCollideLoad - virtual void VCollideUnload( vcollide_t *pVCollide ) = 0; - - // begins parsing a vcollide. NOTE: This keeps pointers to the text - // If you free the text and call members of IVPhysicsKeyParser, it will crash - virtual IVPhysicsKeyParser *VPhysicsKeyParserCreate( const char *pKeyData ) = 0; - // Free the parser created by VPhysicsKeyParserCreate - virtual void VPhysicsKeyParserDestroy( IVPhysicsKeyParser *pParser ) = 0; - - // creates a list of verts from a collision mesh - virtual int CreateDebugMesh( CPhysCollide const *pCollisionModel, Vector **outVerts ) = 0; - // destroy the list of verts created by CreateDebugMesh - virtual void DestroyDebugMesh( int vertCount, Vector *outVerts ) = 0; - - // create a queryable version of the collision model - virtual ICollisionQuery *CreateQueryModel( CPhysCollide *pCollide ) = 0; - // destroy the queryable version - virtual void DestroyQueryModel( ICollisionQuery *pQuery ) = 0; - - virtual IPhysicsCollision *ThreadContextCreate( void ) = 0; - virtual void ThreadContextDestroy( IPhysicsCollision *pThreadContex ) = 0; - - virtual unsigned int ReadStat( int statID ) = 0; - - // UNDONE: Move this up when changing the interface version - virtual void TraceBox( const Ray_t &ray, unsigned int contentsMask, IConvexInfo *pConvexInfo, const CPhysCollide *pCollide, const Vector &collideOrigin, const QAngle &collideAngles, trace_t *ptr ) = 0; - virtual void CollideGetMassCenter( CPhysCollide *pCollide, Vector *pOutMassCenter ) = 0; - virtual void CollideSetMassCenter( CPhysCollide *pCollide, const Vector &massCenter ) = 0; - - // query the collide index in the physics model for the instance - virtual int CollideIndex( const CPhysCollide *pCollide ) = 0; - - virtual CPhysCollide *ConvertConvexToCollideParams( CPhysConvex **pConvex, int convexCount, const convertconvexparams_t &convertParams ) = 0; - virtual CPhysConvex *BBoxToConvex( const Vector &mins, const Vector &maxs ) = 0; - - // get the approximate cross-sectional area projected orthographically on the bbox of the collide - // NOTE: These are fractional areas - unitless. Basically this is the fraction of the OBB on each axis that - // would be visible if the object were rendered orthographically. - // NOTE: This has been precomputed when the collide was built or this function will return 1,1,1 - virtual Vector CollideGetOrthographicAreas( const CPhysCollide *pCollide ) = 0; - - // dumps info about the collide to Msg() - virtual void OutputDebugInfo( const CPhysCollide *pCollide ) = 0; - - // relatively slow test for box vs. truncated cone - virtual bool IsBoxIntersectingCone( const Vector &boxAbsMins, const Vector &boxAbsMaxs, const truncatedcone_t &cone ) = 0; -}; - -// this can be used to post-process a collision model -abstract_class ICollisionQuery -{ -public: - virtual ~ICollisionQuery() {} - // number of convex pieces in the whole solid - virtual int ConvexCount( void ) = 0; - // triangle count for this convex piece - virtual int TriangleCount( int convexIndex ) = 0; - // get the stored game data - virtual unsigned int GetGameData( int convexIndex ) = 0; - // Gets the triangle's verts to an array - virtual void GetTriangleVerts( int convexIndex, int triangleIndex, Vector *verts ) = 0; - - // UNDONE: This doesn't work!!! - virtual void SetTriangleVerts( int convexIndex, int triangleIndex, const Vector *verts ) = 0; - - // returns the 7-bit material index - virtual int GetTriangleMaterialIndex( int convexIndex, int triangleIndex ) = 0; - // sets a 7-bit material index for this triangle - virtual void SetTriangleMaterialIndex( int convexIndex, int triangleIndex, int index7bits ) = 0; -}; - -//----------------------------------------------------------------------------- -// Purpose: Ray traces from game engine. -//----------------------------------------------------------------------------- -abstract_class IPhysicsGameTrace -{ -public: - virtual void VehicleTraceRay( const Ray_t &ray, void *pVehicle, trace_t *pTrace ) = 0; - virtual void VehicleTraceRayWithWater( const Ray_t &ray, void *pVehicle, trace_t *pTrace ) = 0; - virtual bool VehiclePointInWater( const Vector &vecPoint ) = 0; -}; - -// The caller should implement this to return contents masks per convex on a collide -abstract_class IConvexInfo -{ -public: - virtual unsigned int GetContents( int convexGameData ) = 0; -}; - -class CPhysicsEventHandler; -abstract_class IPhysicsCollisionData -{ -public: - virtual void GetSurfaceNormal( Vector &out ) = 0; // normal points toward second object (object index 1) - virtual void GetContactPoint( Vector &out ) = 0; // contact point of collision (in world space) - virtual void GetContactSpeed( Vector &out ) = 0; // speed of surface 1 relative to surface 0 (in world space) -}; - - -struct vcollisionevent_t -{ - IPhysicsObject *pObjects[2]; - int surfaceProps[2]; - bool isCollision; - bool isShadowCollision; - float deltaCollisionTime; - - float collisionSpeed; // only valid at postCollision - IPhysicsCollisionData *pInternalData; // may change pre/post collision -}; - -abstract_class IPhysicsCollisionEvent -{ -public: - // returns the two objects that collided, time between last collision of these objects - // and an opaque data block of collision information - // NOTE: PreCollision/PostCollision ALWAYS come in matched pairs!!! - virtual void PreCollision( vcollisionevent_t *pEvent ) = 0; - virtual void PostCollision( vcollisionevent_t *pEvent ) = 0; - - // This is a scrape event. The object has scraped across another object consuming the indicated energy - virtual void Friction( IPhysicsObject *pObject, float energy, int surfaceProps, int surfacePropsHit, IPhysicsCollisionData *pData ) = 0; - - virtual void StartTouch( IPhysicsObject *pObject1, IPhysicsObject *pObject2, IPhysicsCollisionData *pTouchData ) = 0; - virtual void EndTouch( IPhysicsObject *pObject1, IPhysicsObject *pObject2, IPhysicsCollisionData *pTouchData ) = 0; - - virtual void FluidStartTouch( IPhysicsObject *pObject, IPhysicsFluidController *pFluid ) = 0; - virtual void FluidEndTouch( IPhysicsObject *pObject, IPhysicsFluidController *pFluid ) = 0; - - virtual void PostSimulationFrame() = 0; - - virtual void ObjectEnterTrigger( IPhysicsObject *pTrigger, IPhysicsObject *pObject ) {} - virtual void ObjectLeaveTrigger( IPhysicsObject *pTrigger, IPhysicsObject *pObject ) {} -}; - - -abstract_class IPhysicsObjectEvent -{ -public: - // these can be used to optimize out queries on sleeping objects - // Called when an object is woken after sleeping - virtual void ObjectWake( IPhysicsObject *pObject ) = 0; - // called when an object goes to sleep (no longer simulating) - virtual void ObjectSleep( IPhysicsObject *pObject ) = 0; -}; - -class IPhysicsConstraintEvent -{ -public: - // the constraint is now inactive, the game code is required to delete it or re-activate it. - virtual void ConstraintBroken( IPhysicsConstraint * ) = 0; -}; - -struct hlshadowcontrol_params_t -{ - Vector targetPosition; - QAngle targetRotation; - float maxAngular; - float maxDampAngular; - float maxSpeed; - float maxDampSpeed; - float dampFactor; - float teleportDistance; -}; - -// UNDONE: At some point allow this to be parameterized using hlshadowcontrol_params_t. -// All of the infrastructure is in place to do that. -abstract_class IPhysicsShadowController -{ -public: - virtual ~IPhysicsShadowController( void ) {} - - virtual void Update( const Vector &position, const QAngle &angles, float timeOffset ) = 0; - virtual void MaxSpeed( float maxSpeed, float maxAngularSpeed ) = 0; - virtual void StepUp( float height ) = 0; - - // If the teleport distance is non-zero, the object will be teleported to - // the target location when the error exceeds this quantity. - virtual void SetTeleportDistance( float teleportDistance ) = 0; - virtual bool AllowsTranslation() = 0; - virtual bool AllowsRotation() = 0; - - // There are two classes of shadow objects: - // 1) Game physics controlled, shadow follows game physics (this is the default) - // 2) Physically controlled - shadow position is a target, but the game hasn't guaranteed that the space can be occupied by this object - virtual void SetPhysicallyControlled( bool isPhysicallyControlled ) = 0; - virtual bool IsPhysicallyControlled() = 0; - virtual void GetLastImpulse( Vector *pOut ) = 0; - virtual void UseShadowMaterial( bool bUseShadowMaterial ) = 0; - virtual void ObjectMaterialChanged( int materialIndex ) = 0; -}; - -class CPhysicsSimObject; -class IPhysicsMotionController; - -// Callback for simulation -class IMotionEvent -{ -public: - // These constants instruct the simulator as to how to apply the values copied to linear & angular - // GLOBAL/LOCAL refer to the coordinate system of the values, whereas acceleration/force determine whether or not - // mass is divided out (forces must be divided by mass to compute acceleration) - enum simresult_e { SIM_NOTHING = 0, SIM_LOCAL_ACCELERATION, SIM_LOCAL_FORCE, SIM_GLOBAL_ACCELERATION, SIM_GLOBAL_FORCE }; - virtual simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular ) = 0; -}; - - - -abstract_class IPhysicsMotionController -{ -public: - virtual ~IPhysicsMotionController( void ) {} - virtual void SetEventHandler( IMotionEvent *handler ) = 0; - virtual void AttachObject( IPhysicsObject *pObject, bool checkIfAlreadyAttached ) = 0; - virtual void DetachObject( IPhysicsObject *pObject ) = 0; - - // returns the number of objects currently attached to the controller - virtual int CountObjects( void ) = 0; - // NOTE: pObjectList is an array with at least CountObjects() allocated - virtual void GetObjects( IPhysicsObject **pObjectList ) = 0; - // detaches all attached objects - virtual void ClearObjects( void ) = 0; - - // wakes up all attached objects - virtual void WakeObjects( void ) = 0; - enum priority_t - { - LOW_PRIORITY = 0, - MEDIUM_PRIORITY = 1, - HIGH_PRIORITY = 2, - }; - virtual void SetPriority( priority_t priority ) = 0; -}; - -// ------------------- -// Collision filter function. Return 0 if objects should not be tested for collisions, nonzero otherwise -// Install with IPhysicsEnvironment::SetCollisionFilter() -// ------------------- -abstract_class IPhysicsCollisionSolver -{ -public: - virtual int ShouldCollide( IPhysicsObject *pObj0, IPhysicsObject *pObj1, void *pGameData0, void *pGameData1 ) = 0; - virtual int ShouldSolvePenetration( IPhysicsObject *pObj0, IPhysicsObject *pObj1, void *pGameData0, void *pGameData1, float dt ) = 0; - - // pObject has already done the max number of collisions this tick, should we freeze it to save CPU? - virtual bool ShouldFreezeObject( IPhysicsObject *pObject ) = 0; - - // The system has already done too many collision checks, performance will suffer. - // How many more should it do? - virtual int AdditionalCollisionChecksThisTick( int currentChecksDone ) = 0; -}; - -enum PhysicsTraceType_t -{ - VPHYSICS_TRACE_EVERYTHING = 0, - VPHYSICS_TRACE_STATIC_ONLY, - VPHYSICS_TRACE_MOVING_ONLY, - VPHYSICS_TRACE_TRIGGERS_ONLY, - VPHYSICS_TRACE_STATIC_AND_MOVING, -}; - -abstract_class IPhysicsTraceFilter -{ -public: - virtual bool ShouldHitObject( IPhysicsObject *pObject, int contentsMask ) = 0; - virtual PhysicsTraceType_t GetTraceType() const = 0; -}; - -abstract_class IPhysicsEnvironment -{ -public: - virtual ~IPhysicsEnvironment( void ) {} - - virtual void SetDebugOverlay( CreateInterfaceFn debugOverlayFactory ) = 0; - virtual IVPhysicsDebugOverlay *GetDebugOverlay( void ) = 0; - - // gravity is a 3-vector in in/s^2 - virtual void SetGravity( const Vector &gravityVector ) = 0; - virtual void GetGravity( Vector &gravityVector ) = 0; - - // air density is in kg / m^3 (water is 1000) - // This controls drag, air that is more dense has more drag. - virtual void SetAirDensity( float density ) = 0; - virtual float GetAirDensity( void ) = 0; - - // object creation - // create a polygonal object. pCollisionModel was created by the physics builder DLL in a pre-process. - virtual IPhysicsObject *CreatePolyObject( const CPhysCollide *pCollisionModel, int materialIndex, const Vector &position, const QAngle &angles, objectparams_t *pParams ) = 0; - // same as above, but this one cannot move or rotate (infinite mass/inertia) - virtual IPhysicsObject *CreatePolyObjectStatic( const CPhysCollide *pCollisionModel, int materialIndex, const Vector &position, const QAngle &angles, objectparams_t *pParams ) = 0; - // Create a perfectly spherical object - virtual IPhysicsObject *CreateSphereObject( float radius, int materialIndex, const Vector &position, const QAngle &angles, objectparams_t *pParams, bool isStatic ) = 0; - // Create a polygonal fluid body out of the specified collision model - // This object will affect any other objects that collide with the collision model - virtual IPhysicsFluidController *CreateFluidController( IPhysicsObject *pFluidObject, fluidparams_t *pParams ) = 0; - - // Create a simulated spring that connects 2 objects - virtual IPhysicsSpring *CreateSpring( IPhysicsObject *pObjectStart, IPhysicsObject *pObjectEnd, springparams_t *pParams ) = 0; - - // Create a constraint in the space of pReferenceObject which is attached by the constraint to pAttachedObject - virtual IPhysicsConstraint *CreateRagdollConstraint( IPhysicsObject *pReferenceObject, IPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_ragdollparams_t &ragdoll ) = 0; - virtual IPhysicsConstraint *CreateHingeConstraint( IPhysicsObject *pReferenceObject, IPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_hingeparams_t &hinge ) = 0; - virtual IPhysicsConstraint *CreateFixedConstraint( IPhysicsObject *pReferenceObject, IPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_fixedparams_t &fixed ) = 0; - virtual IPhysicsConstraint *CreateSlidingConstraint( IPhysicsObject *pReferenceObject, IPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_slidingparams_t &sliding ) = 0; - virtual IPhysicsConstraint *CreateBallsocketConstraint( IPhysicsObject *pReferenceObject, IPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_ballsocketparams_t &ballsocket ) = 0; - virtual IPhysicsConstraint *CreatePulleyConstraint( IPhysicsObject *pReferenceObject, IPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_pulleyparams_t &pulley ) = 0; - virtual IPhysicsConstraint *CreateLengthConstraint( IPhysicsObject *pReferenceObject, IPhysicsObject *pAttachedObject, IPhysicsConstraintGroup *pGroup, const constraint_lengthparams_t &length ) = 0; - - virtual IPhysicsConstraintGroup *CreateConstraintGroup( const constraint_groupparams_t &groupParams ) = 0; - - // destroy an object created with CreatePolyObject() or CreatePolyObjectStatic() - virtual void DestroyObject( IPhysicsObject * ) = 0; - virtual void DestroySpring( IPhysicsSpring * ) = 0; - // Destroy an object created with CreateFluidController() - virtual void DestroyFluidController( IPhysicsFluidController * ) = 0; - virtual void DestroyConstraint( IPhysicsConstraint * ) = 0; - virtual void DestroyConstraintGroup( IPhysicsConstraintGroup *pGroup ) = 0; - - // install a function to filter collisions/penentration - virtual void SetCollisionSolver( IPhysicsCollisionSolver *pSolver ) = 0; - - // run the simulator for deltaTime seconds - virtual void Simulate( float deltaTime ) = 0; - // true if currently running the simulator (i.e. in a callback during physenv->Simulate()) - virtual bool IsInSimulation( void ) const = 0; - - // Manage the timestep (period) of the simulator. The main functions are all integrated with - // this period as dt. - virtual float GetSimulationTimestep( void ) = 0; - virtual void SetSimulationTimestep( float timestep ) = 0; - - // returns the current simulation clock's value. This is an absolute time. - virtual float GetSimulationTime( void ) = 0; - virtual void ResetSimulationClock( void ) = 0; - - // Collision callbacks (game code collision response) - virtual void SetCollisionEventHandler( IPhysicsCollisionEvent *pCollisionEvents ) = 0; - virtual void SetObjectEventHandler( IPhysicsObjectEvent *pObjectEvents ) = 0; - virtual void SetConstraintEventHandler( IPhysicsConstraintEvent *pConstraintEvents ) = 0; - - virtual IPhysicsShadowController *CreateShadowController( IPhysicsObject *pObject, bool allowTranslation, bool allowRotation ) = 0; - virtual void DestroyShadowController( IPhysicsShadowController * ) = 0; - - virtual IPhysicsPlayerController *CreatePlayerController( IPhysicsObject *pObject ) = 0; - virtual void DestroyPlayerController( IPhysicsPlayerController * ) = 0; - - virtual IPhysicsMotionController *CreateMotionController( IMotionEvent *pHandler ) = 0; - virtual void DestroyMotionController( IPhysicsMotionController *pController ) = 0; - - virtual IPhysicsVehicleController *CreateVehicleController( IPhysicsObject *pVehicleBodyObject, const vehicleparams_t ¶ms, unsigned int nVehicleType, IPhysicsGameTrace *pGameTrace ) = 0; - virtual void DestroyVehicleController( IPhysicsVehicleController * ) = 0; - - virtual void SetQuickDelete( bool bQuick ) = 0; - - virtual int GetActiveObjectCount( void ) = 0; - virtual void GetActiveObjects( IPhysicsObject **pOutputObjectList ) = 0; - - virtual void CleanupDeleteList( void ) = 0; - virtual void EnableDeleteQueue( bool enable ) = 0; - - // Save/Restore methods - virtual bool Save( const physsaveparams_t ¶ms ) = 0; - virtual void PreRestore( const physprerestoreparams_t ¶ms ) = 0; - virtual bool Restore( const physrestoreparams_t ¶ms ) = 0; - virtual void PostRestore() = 0; - - // Debugging: - virtual bool IsCollisionModelUsed( CPhysCollide *pCollide ) = 0; - - // Physics world version of the enginetrace API: - virtual void TraceRay( const Ray_t &ray, unsigned int fMask, IPhysicsTraceFilter *pTraceFilter, trace_t *pTrace ) = 0; - virtual void SweepCollideable( const CPhysCollide *pCollide, const Vector &vecAbsStart, const Vector &vecAbsEnd, - const QAngle &vecAngles, unsigned int fMask, IPhysicsTraceFilter *pTraceFilter, trace_t *pTrace ) = 0; - - // performance tuning - virtual void GetPerformanceSettings( physics_performanceparams_t *pOutput ) = 0; - virtual void SetPerformanceSettings( const physics_performanceparams_t *pSettings ) = 0; - - // perf/cost statistics - virtual void ReadStats( physics_stats_t *pOutput ) = 0; - virtual void ClearStats() = 0; -}; - -enum callbackflags -{ - CALLBACK_GLOBAL_COLLISION = 0x0001, - CALLBACK_GLOBAL_FRICTION = 0x0002, - CALLBACK_GLOBAL_TOUCH = 0x0004, - CALLBACK_GLOBAL_TOUCH_STATIC = 0x0008, - CALLBACK_SHADOW_COLLISION = 0x0010, - CALLBACK_GLOBAL_COLLIDE_STATIC = 0x0020, - CALLBACK_IS_VEHICLE_WHEEL = 0x0040, - CALLBACK_FLUID_TOUCH = 0x0100, - CALLBACK_NEVER_DELETED = 0x0200, // HACKHACK: This means this object will never be deleted (set on the world) - CALLBACK_MARKED_FOR_DELETE = 0x0400, // This allows vphysics to skip some work for this object since it will be - // deleted later this frame. (Set automatically by destroy calls) - CALLBACK_ENABLING_COLLISION = 0x0800, // This is active during the time an object is enabling collisions - // allows us to skip collisions between "new" objects and objects marked for delete - CALLBACK_DO_FLUID_SIMULATION = 0x1000, // remove this to opt out of fluid simulations - CALLBACK_IS_PLAYER_CONTROLLER= 0x2000, // HACKHACK: Set this on players until player cotrollers are unified with shadow controllers - CALLBACK_CHECK_COLLISION_DISABLE = 0x4000, - CALLBACK_MARKED_FOR_TEST = 0x8000, // debug -- marked object is being debugged -}; - -abstract_class IPhysicsObject -{ -public: - virtual ~IPhysicsObject( void ) {} - - // returns true if this object is static/unmoveable - // NOTE: returns false for objects that are not created static, but set EnableMotion(false); - // Call IsMoveable() to find if the object is static OR has motion disabled - virtual bool IsStatic( void ) = 0; - - // "wakes up" an object - // NOTE: ALL OBJECTS ARE "Asleep" WHEN CREATED - virtual void Wake( void ) = 0; - virtual void Sleep( void ) = 0; - virtual bool IsAsleep( void ) = 0; - - // Game can store data in each object (link back to game object) - virtual void SetGameData( void *pGameData ) = 0; - virtual void *GetGameData( void ) const = 0; - // This flags word can be defined by the game as well - virtual void SetGameFlags( unsigned short userFlags ) = 0; - virtual unsigned short GetGameFlags( void ) const = 0; - virtual void SetGameIndex( unsigned short gameIndex ) = 0; - virtual unsigned short GetGameIndex( void ) const = 0; - - // setup various callbacks for this object - virtual void SetCallbackFlags( unsigned short callbackflags ) = 0; - // get the current callback state for this object - virtual unsigned short GetCallbackFlags( void ) = 0; - - // mass accessors - virtual void SetMass( float mass ) = 0; - virtual float GetMass( void ) const = 0; - // get 1/mass (it's cached) - virtual float GetInvMass( void ) const = 0; - virtual Vector GetInertia( void ) const = 0; - virtual Vector GetInvInertia( void ) const = 0; - virtual void SetInertia( const Vector &inertia ) = 0; - - virtual void SetDamping( const float *speed, const float *rot ) = 0; - virtual void GetDamping( float *speed, float *rot ) = 0; - - // material index - virtual int GetMaterialIndex() const = 0; - virtual void SetMaterialIndex( int materialIndex ) = 0; - - // Enable / disable collisions for this object - virtual void EnableCollisions( bool enable ) = 0; - // Enable / disable gravity for this object - virtual void EnableGravity( bool enable ) = 0; - // Enable / disable air friction / drag for this object - virtual void EnableDrag( bool enable ) = 0; - // Enable / disable motion (pin / unpin the object) - virtual void EnableMotion( bool enable ) = 0; - - // call this when the collision filter conditions change due to this - // object's state (e.g. changing solid type or collision group) - virtual void RecheckCollisionFilter() = 0; - - // NOTE: These are here for convenience, but you can do them yourself by using the matrix - // returned from GetPositionMatrix() - // convenient coordinate system transformations (params - dest, src) - virtual void LocalToWorld( Vector *worldPosition, const Vector &localPosition ) = 0; - virtual void WorldToLocal( Vector *localPosition, const Vector &worldPosition ) = 0; - - // transforms a vector (no translation) from object-local to world space - virtual void LocalToWorldVector( Vector *worldVector, const Vector &localVector ) = 0; - // transforms a vector (no translation) from world to object-local space - virtual void WorldToLocalVector( Vector *localVector, const Vector &worldVector ) = 0; - - // push on an object - // force vector is direction & magnitude of impulse kg in / s - virtual void ApplyForceCenter( const Vector &forceVector ) = 0; - virtual void ApplyForceOffset( const Vector &forceVector, const Vector &worldPosition ) = 0; - - // Calculates the force/torque on the center of mass for an offset force impulse (pass output to ApplyForceCenter / ApplyTorqueCenter) - virtual void CalculateForceOffset( const Vector &forceVector, const Vector &worldPosition, Vector *centerForce, AngularImpulse *centerTorque ) = 0; - // Calculates the linear/angular velocities on the center of mass for an offset force impulse (pass output to AddVelocity) - virtual void CalculateVelocityOffset( const Vector &forceVector, const Vector &worldPosition, Vector *centerVelocity, AngularImpulse *centerAngularVelocity ) = 0; - - // apply torque impulse. This will change the angular velocity on the object. - // HL Axes, kg degrees / s - virtual void ApplyTorqueCenter( const AngularImpulse &torque ) = 0; - - // NOTE: This will teleport the object - virtual void SetPosition( const Vector &worldPosition, const QAngle &angles, bool isTeleport ) = 0; - virtual void SetPositionMatrix( const matrix3x4_t&matrix, bool isTeleport ) = 0; - - virtual void GetPosition( Vector *worldPosition, QAngle *angles ) = 0; - virtual void GetPositionMatrix( matrix3x4_t *positionMatrix ) = 0; - // force the velocity to a new value - // NOTE: velocity is in worldspace, angularVelocity is relative to the object's - // local axes (just like pev->velocity, pev->avelocity) - virtual void SetVelocity( const Vector *velocity, const AngularImpulse *angularVelocity ) = 0; - - // like the above, but force the change into the simulator immediately - virtual void SetVelocityInstantaneous( const Vector *velocity, const AngularImpulse *angularVelocity ) = 0; - - // NOTE: velocity is in worldspace, angularVelocity is relative to the object's - // local axes (just like pev->velocity, pev->avelocity) - virtual void GetVelocity( Vector *velocity, AngularImpulse *angularVelocity ) = 0; - - // NOTE: These are velocities, not forces. i.e. They will have the same effect regardless of - // the object's mass or inertia - virtual void AddVelocity( const Vector *velocity, const AngularImpulse *angularVelocity ) = 0; - virtual void GetVelocityAtPoint( const Vector &worldPosition, Vector &velocity ) = 0; - - virtual float GetEnergy() = 0; - - // returns true if the object is in contact with another object - // if true, puts a point on the contact surface in contactPoint, and - // a pointer to the object in contactObject - // NOTE: You can pass NULL for either to avoid computations - // JAY: This is still an experiment - virtual bool GetContactPoint( Vector *contactPoint, IPhysicsObject **contactObject ) = 0; - - // refactor this a bit - move some of this to IPhysicsShadowController - virtual void SetShadow( float maxSpeed, float maxAngularSpeed, bool allowPhysicsMovement, bool allowPhysicsRotation ) = 0; - virtual void UpdateShadow( const Vector &targetPosition, const QAngle &targetAngles, bool tempDisableGravity, float timeOffset ) = 0; - - // returns number of ticks since last Update() call - virtual int GetShadowPosition( Vector *position, QAngle *angles ) = 0; - virtual IPhysicsShadowController *GetShadowController( void ) const = 0; - - - virtual const CPhysCollide *GetCollide( void ) const = 0; - virtual const char *GetName() = 0; - virtual void RemoveShadowController() = 0; - virtual bool IsMoveable() = 0; - - // applies the math of the shadow controller to this object. - // for use in your own controllers - // returns the new value of secondsToArrival with dt time elapsed - virtual float ComputeShadowControl( const hlshadowcontrol_params_t ¶ms, float secondsToArrival, float dt ) = 0; - - // coefficients are optional, pass either - virtual void SetDragCoefficient( float *pDrag, float *pAngularDrag ) = 0; - - // Get the radius if this is a sphere object (zero if this is a polygonal mesh) - virtual float GetSphereRadius() = 0; - - virtual float CalculateLinearDrag( const Vector &unitDirection ) const = 0; - virtual float CalculateAngularDrag( const Vector &objectSpaceRotationAxis ) const = 0; - virtual void SetBuoyancyRatio( float ratio ) = 0; // Override bouyancy - - virtual void BecomeTrigger() = 0; - virtual void RemoveTrigger() = 0; - virtual bool IsTrigger() = 0; - virtual bool IsFluid() = 0; // fluids are special triggers with fluid controllers attached, they return true to IsTrigger() as well! - - // sets the object to be hinged. Fixed it place, but able to rotate around one axis. - virtual void BecomeHinged( int localAxis ) = 0; - // resets the object to original state - virtual void RemoveHinged() = 0; - virtual bool IsHinged() = 0; - - virtual unsigned int GetContents() = 0; - virtual void SetContents( unsigned int contents ) = 0; - virtual Vector GetMassCenterLocalSpace() = 0; - - // used to iterate the contact points of an object - virtual IPhysicsFrictionSnapshot *CreateFrictionSnapshot() = 0; - virtual void DestroyFrictionSnapshot( IPhysicsFrictionSnapshot *pSnapshot ) = 0; - - // dumps info about the object to Msg() - virtual void OutputDebugInfo() = 0; - virtual void GetImplicitVelocity( Vector *velocity, AngularImpulse *angularVelocity ) = 0; - // this is a hack to recheck current contacts - // some of them may not be valid if the object's collision rules have recently changed - // UNDONE: Force this in RecheckCollisionFilter() ? - virtual void RecheckContactPoints() = 0; -}; - - -abstract_class IPhysicsSpring -{ -public: - virtual ~IPhysicsSpring( void ) {} - virtual void GetEndpoints( Vector *worldPositionStart, Vector *worldPositionEnd ) = 0; - virtual void SetSpringConstant( float flSpringContant) = 0; - virtual void SetSpringDamping( float flSpringDamping) = 0; - virtual void SetSpringLength( float flSpringLenght) = 0; - - // Get the starting object - virtual IPhysicsObject *GetStartObject( void ) = 0; - - // Get the end object - virtual IPhysicsObject *GetEndObject( void ) = 0; -}; - - -//----------------------------------------------------------------------------- -// Purpose: These properties are defined per-material. This is accessible at -// each triangle in a collision mesh -//----------------------------------------------------------------------------- -struct surfacephysicsparams_t -{ -// vphysics physical properties - float friction; - float elasticity; // collision elasticity - used to compute coefficient of restitution - float density; // physical density (in kg / m^3) - float thickness; // material thickness if not solid (sheet materials) in inches - float dampening; -}; - -struct surfaceaudioparams_t -{ -// sounds / audio data - float reflectivity; // like elasticity, but how much sound should be reflected by this surface - float hardnessFactor; // like elasticity, but only affects impact sound choices - float roughnessFactor; // like friction, but only affects scrape sound choices - -// audio thresholds - float roughThreshold; // surface roughness > this causes "rough" scrapes, < this causes "smooth" scrapes - float hardThreshold; // surface hardness > this causes "hard" impacts, < this causes "soft" impacts - float hardVelocityThreshold; // collision velocity > this causes "hard" impacts, < this causes "soft" impacts - // NOTE: Hard impacts must meet both hardnessFactor AND velocity thresholds -}; - -struct surfacesoundnames_t -{ - unsigned short stepleft; - unsigned short stepright; - - unsigned short impactSoft; - unsigned short impactHard; - - unsigned short scrapeSmooth; - unsigned short scrapeRough; - - unsigned short bulletImpact; - unsigned short rolling; - - unsigned short breakSound; - unsigned short strainSound; -}; - -struct surfacegameprops_t -{ -// game movement data - float maxSpeedFactor; // Modulates player max speed when walking on this surface - float jumpFactor; // Indicates how much higher the player should jump when on the surface -// Game-specific data - unsigned short material; - // Indicates whether or not the player is on a ladder. - unsigned char climbable; - unsigned char pad; -}; - -//----------------------------------------------------------------------------- -// Purpose: Each different material has an entry like this -//----------------------------------------------------------------------------- -struct surfacedata_t -{ - surfacephysicsparams_t physics; // physics parameters - surfaceaudioparams_t audio; // audio parameters - surfacesoundnames_t sounds; // names of linked sounds - surfacegameprops_t game; // Game data / properties - - -}; - -#define VPHYSICS_SURFACEPROPS_INTERFACE_VERSION_1 "VPhysicsSurfaceProps001" -abstract_class IPhysicsSurfaceProps -{ -public: - virtual ~IPhysicsSurfaceProps( void ) {} - - // parses a text file containing surface prop keys - virtual int ParseSurfaceData( const char *pFilename, const char *pTextfile ) = 0; - // current number of entries in the database - virtual int SurfacePropCount( void ) = 0; - - virtual int GetSurfaceIndex( const char *pSurfacePropName ) = 0; - virtual void GetPhysicsProperties( int surfaceDataIndex, float *density, float *thickness, float *friction, float *elasticity ) = 0; - - virtual surfacedata_t *GetSurfaceData( int surfaceDataIndex ) = 0; - virtual const char *GetString( unsigned short stringTableIndex ) = 0; - - - virtual const char *GetPropName( int surfaceDataIndex ) = 0; - - // sets the global index table for world materials - virtual void SetWorldMaterialIndexTable( int *pMapArray, int mapSize ) = 0; - - // NOTE: Same as GetPhysicsProperties, but maybe more convenient - virtual void GetPhysicsParameters( int surfaceDataIndex, surfacephysicsparams_t *pParamsOut ) = 0; -}; - -abstract_class IPhysicsFluidController -{ -public: - virtual ~IPhysicsFluidController( void ) {} - - virtual void SetGameData( void *pGameData ) = 0; - virtual void *GetGameData( void ) const = 0; - - virtual void GetSurfacePlane( Vector *pNormal, float *pDist ) = 0; - virtual float GetDensity() = 0; - virtual void WakeAllSleepingObjects() = 0; - virtual int GetContents() const = 0; -}; - - -//----------------------------------------------------------------------------- -// Purpose: parameter block for creating fluid dynamic motion -// UNDONE: Expose additional fluid model paramters? -//----------------------------------------------------------------------------- -struct fluidparams_t -{ - Vector4D surfacePlane; // x,y,z normal, dist (plane constant) fluid surface - Vector currentVelocity; // velocity of the current in inches/second - float damping; // damping factor for buoyancy (tweak) - float torqueFactor; - float viscosityFactor; - void *pGameData; - bool useAerodynamics;// true if this controller should calculate surface pressure - int contents; - - fluidparams_t() {} - fluidparams_t( fluidparams_t const& src ) - { - Vector4DCopy( src.surfacePlane, surfacePlane ); - VectorCopy( src.currentVelocity, currentVelocity ); - damping = src.damping; - torqueFactor = src.torqueFactor; - viscosityFactor = src.viscosityFactor; - contents = src.contents; - } -}; - -//----------------------------------------------------------------------------- -// Purpose: parameter block for creating linear springs -// UNDONE: Expose additional spring model paramters? -//----------------------------------------------------------------------------- -struct springparams_t -{ - springparams_t() - { - memset( this, 0, sizeof(*this) ); - } - float constant; // spring constant - float naturalLength;// relaxed length - float damping; // damping factor - float relativeDamping; // relative damping (damping proportional to the change in the relative position of the objects) - Vector startPosition; - Vector endPosition; - bool useLocalPositions; // start & end Position are in local space to start and end objects if this is true - bool onlyStretch; // only apply forces when the length is greater than the natural length -}; - -//----------------------------------------------------------------------------- -// Purpose: parameter block for creating polygonal objects -//----------------------------------------------------------------------------- -struct objectparams_t -{ - Vector *massCenterOverride; - float mass; - float inertia; - float damping; - float rotdamping; - float rotInertiaLimit; - const char *pName; // used only for debugging - void *pGameData; - float volume; - float dragCoefficient; - bool enableCollisions; -}; - -struct convertconvexparams_t -{ - bool buildOuterConvexHull; - bool buildDragAxisAreas; - bool buildOptimizedTraceTables; - float dragAreaEpsilon; - CPhysConvex *pForcedOuterHull; - - void Defaults() - { - dragAreaEpsilon = 0.25f; // 0.5in x 0.5in square - buildOuterConvexHull = false; - buildDragAxisAreas = false; - buildOptimizedTraceTables = false; - pForcedOuterHull = NULL; - } -}; - -//----------------------------------------------------------------------------- -// Physics interface IDs -// -// Note that right now the order of the enum also defines the order of save/load - - -//----------------------------------------------------------------------------- -// Purpose: parameter blocks for save and load operations -//----------------------------------------------------------------------------- -struct physsaveparams_t -{ - ISave *pSave; - void *pObject; - PhysInterfaceId_t type; -}; - -struct physrestoreparams_t -{ - IRestore *pRestore; - void **ppObject; - PhysInterfaceId_t type; - void *pGameData; - const char *pName; // used only for debugging - const CPhysCollide *pCollisionModel; - IPhysicsEnvironment *pEnvironment; - IPhysicsGameTrace *pGameTrace; -}; - -struct physrecreateparams_t -{ - void *pOldObject; - void *pNewObject; -}; - -struct physprerestoreparams_t -{ - int recreatedObjectCount; - physrecreateparams_t recreatedObjectList[1]; -}; - - -//------------------------------------- - -#define DEFINE_PIID( type, enumval ) \ - template <> inline PhysInterfaceId_t GetPhysIID( type ** ) { return enumval; } - -template inline PhysInterfaceId_t GetPhysIID(PHYSPTR **); // will get link error if no match - -DEFINE_PIID( IPhysicsObject, PIID_IPHYSICSOBJECT ); -DEFINE_PIID( IPhysicsFluidController, PIID_IPHYSICSFLUIDCONTROLLER ); -DEFINE_PIID( IPhysicsSpring, PIID_IPHYSICSSPRING ); -DEFINE_PIID( IPhysicsConstraintGroup, PIID_IPHYSICSCONSTRAINTGROUP ); -DEFINE_PIID( IPhysicsConstraint, PIID_IPHYSICSCONSTRAINT ); -DEFINE_PIID( IPhysicsShadowController, PIID_IPHYSICSSHADOWCONTROLLER ); -DEFINE_PIID( IPhysicsPlayerController, PIID_IPHYSICSPLAYERCONTROLLER ); -DEFINE_PIID( IPhysicsMotionController, PIID_IPHYSICSMOTIONCONTROLLER ); -DEFINE_PIID( IPhysicsVehicleController, PIID_IPHYSICSVEHICLECONTROLLER ); -DEFINE_PIID( IPhysicsGameTrace, PIID_IPHYSICSGAMETRACE ); - -//----------------------------------------------------------------------------- - -} // end namespace VPhysicsInterfaceV30 - -#endif // VPHYSICS_INTERFACE_V30_H diff --git a/public/vstdlib/IKeyValuesSystem.h b/public/vstdlib/IKeyValuesSystem.h deleted file mode 100644 index db30899bf..000000000 --- a/public/vstdlib/IKeyValuesSystem.h +++ /dev/null @@ -1,48 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -//=============================================================================// -#ifndef VSTDLIB_IKEYVALUESSYSTEM_H -#define VSTDLIB_IKEYVALUESSYSTEM_H -#ifdef _WIN32 -#pragma once -#endif - -#include "vstdlib/vstdlib.h" - -// handle to a KeyValues key name symbol -typedef int HKeySymbol; -#define INVALID_KEY_SYMBOL (-1) - -//----------------------------------------------------------------------------- -// Purpose: Interface to shared data repository for KeyValues (included in vgui_controls.lib) -// allows for central data storage point of KeyValues symbol table -//----------------------------------------------------------------------------- -class IKeyValuesSystem -{ -public: - // registers the size of the KeyValues in the specified instance - // so it can build a properly sized memory pool for the KeyValues objects - // the sizes will usually never differ but this is for versioning safety - virtual void RegisterSizeofKeyValues(int size) = 0; - - // allocates/frees a KeyValues object from the shared mempool - virtual void *AllocKeyValuesMemory(int size) = 0; - virtual void FreeKeyValuesMemory(void *pMem) = 0; - - // symbol table access (used for key names) - virtual HKeySymbol GetSymbolForString( const char *name, bool bCreate = true ) = 0; - virtual const char *GetStringForSymbol(HKeySymbol symbol) = 0; - - // for debugging, adds KeyValues record into global list so we can track memory leaks - virtual void AddKeyValuesToMemoryLeakList(void *pMem, HKeySymbol name) = 0; - virtual void RemoveKeyValuesFromMemoryLeakList(void *pMem) = 0; -}; - -VSTDLIB_INTERFACE IKeyValuesSystem *KeyValuesSystem(); - -// #define KEYVALUESSYSTEM_INTERFACE_VERSION "KeyValuesSystem002" - -#endif // VSTDLIB_IKEYVALUESSYSTEM_H diff --git a/public/vstdlib/cvar.h b/public/vstdlib/cvar.h deleted file mode 100644 index 1f26e0daf..000000000 --- a/public/vstdlib/cvar.h +++ /dev/null @@ -1,25 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#if !defined( CVAR_H ) -#define CVAR_H -#ifdef _WIN32 -#pragma once -#endif - -#include "vstdlib/vstdlib.h" -#include "icvar.h" - - -//----------------------------------------------------------------------------- -// Returns a CVar dictionary for tool usage -//----------------------------------------------------------------------------- -VSTDLIB_INTERFACE CreateInterfaceFn VStdLib_GetICVarFactory(); - - -#endif // CVAR_H diff --git a/public/vstdlib/iprocessutils.h b/public/vstdlib/iprocessutils.h deleted file mode 100644 index 2fea14e5b..000000000 --- a/public/vstdlib/iprocessutils.h +++ /dev/null @@ -1,64 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -//===========================================================================// - -#ifndef IPROCESSUTILS_H -#define IPROCESSUTILS_H - -#ifdef _WIN32 -#pragma once -#endif - - -#include "appframework/IAppSystem.h" - - -//----------------------------------------------------------------------------- -// Handle to a process -//----------------------------------------------------------------------------- -typedef int ProcessHandle_t; -enum -{ - PROCESS_HANDLE_INVALID = 0, -}; - - -//----------------------------------------------------------------------------- -// Interface version -//----------------------------------------------------------------------------- -#define PROCESS_UTILS_INTERFACE_VERSION "VProcessUtils001" - - -//----------------------------------------------------------------------------- -// Interface for makefiles to build differently depending on where they are run from -//----------------------------------------------------------------------------- -abstract_class IProcessUtils : public IAppSystem -{ -public: - // Starts, stops a process - virtual ProcessHandle_t StartProcess( const char *pCommandLine, bool bConnectStdPipes ) = 0; - virtual ProcessHandle_t StartProcess( int argc, const char **argv, bool bConnectStdPipes ) = 0; - virtual void CloseProcess( ProcessHandle_t hProcess ) = 0; - virtual void AbortProcess( ProcessHandle_t hProcess ) = 0; - - // Returns true if a process is complete - virtual bool IsProcessComplete( ProcessHandle_t hProcess ) = 0; - - // Waits until a process is complete - virtual void WaitUntilProcessCompletes( ProcessHandle_t hProcess ) = 0; - - // Methods used to write input into a process - virtual int SendProcessInput( ProcessHandle_t hProcess, char *pBuf, int nBufLen ) = 0; - - // Methods used to read output back from a process - virtual int GetProcessOutputSize( ProcessHandle_t hProcess ) = 0; - virtual int GetProcessOutput( ProcessHandle_t hProcess, char *pBuf, int nBufLen ) = 0; - - // Returns the exit code for the process. Doesn't work unless the process is complete - virtual int GetProcessExitCode( ProcessHandle_t hProcess ) = 0; -}; - - -#endif // IPROCESSUTILS_H diff --git a/public/vstdlib/jobthread.h b/public/vstdlib/jobthread.h deleted file mode 100644 index 77dcc512d..000000000 --- a/public/vstdlib/jobthread.h +++ /dev/null @@ -1,1325 +0,0 @@ -//========== Copyright ? 2005, Valve Corporation, All rights reserved. ======== -// -// Purpose: A utility for a discrete job-oriented worker thread. -// -// The class CThreadPool is both the job queue, and the -// worker thread. Except when the main thread attempts to -// synchronously execute a job, most of the inter-thread locking -// on the queue. -// -// The queue threading model uses a manual reset event for optimal -// throughput. Adding to the queue is guarded by a semaphore that -// will block the inserting thread if the queue has overflown. -// This prevents the worker thread from being starved out even if -// not running at a higher priority than the master thread. -// -// The thread function waits for jobs, services jobs, and manages -// communication between the worker and master threads. The nature -// of the work is opaque to the Executer. -// -// CJob instances actually do the work. The base class -// calls virtual methods for job primitives, so derivations don't -// need to worry about threading models. All of the variants of -// job and OS can be expressed in this hierarchy. Instances of -// CJob are the items placed in the queue, and by -// overriding the job primitives they are the manner by which -// users of the Executer control the state of the job. -// -//============================================================================= - -#include -#include "tier0/threadtools.h" -#include "tier1/refcount.h" -#include "tier1/utllinkedlist.h" -#include "tier1/utlvector.h" -#include "tier1/functors.h" - -#include "vstdlib/vstdlib.h" - -#ifndef JOBTHREAD_H -#define JOBTHREAD_H - -#ifdef AddJob // windows.h print function collisions -#undef AddJob -#undef GetJob -#endif - -#ifdef VSTDLIB_DLL_EXPORT -#define JOB_INTERFACE DLL_EXPORT -#define JOB_OVERLOAD DLL_GLOBAL_EXPORT -#define JOB_CLASS DLL_CLASS_EXPORT -#else -#define JOB_INTERFACE DLL_IMPORT -#define JOB_OVERLOAD DLL_GLOBAL_IMPORT -#define JOB_CLASS DLL_CLASS_IMPORT -#endif - -#if defined( _WIN32 ) -#pragma once -#endif - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- - -class CJob; - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -enum JobStatusEnum_t -{ - // Use negative for errors - JOB_OK, // operation is successful - JOB_STATUS_PENDING, // file is properly queued, waiting for service - JOB_STATUS_INPROGRESS, // file is being accessed - JOB_STATUS_ABORTED, // file was aborted by caller - JOB_STATUS_UNSERVICED, // file is not yet queued -}; - -typedef int JobStatus_t; - -enum JobFlags_t -{ - JF_IO = ( 1 << 0 ), // The job primarily blocks on IO or hardware - JF_BOOST_THREAD = ( 1 << 1 ), // Up the thread priority to max allowed while processing task - JF_SERIAL = ( 1 << 2 ), // Job cannot be executed out of order relative to other "strict" jobs - JF_QUEUE = ( 1 << 3 ), // Queue it, even if not an IO job -}; - -enum JobPriority_t -{ - JP_LOW, - JP_NORMAL, - JP_HIGH -}; - -#define TP_MAX_POOL_THREADS 64 -struct ThreadPoolStartParams_t -{ - ThreadPoolStartParams_t( bool bIOThreads = false, unsigned nThreads = -1, int *pAffinities = NULL, ThreeState_t fDistribute = TRS_NONE, unsigned nStackSize = -1, int iThreadPriority = SHRT_MIN ) - : bIOThreads( bIOThreads ), nThreads( nThreads ), fDistribute( fDistribute ), nStackSize( nStackSize ), iThreadPriority( iThreadPriority ), nThreadsMax( -1 ) - { - bUseAffinityTable = ( pAffinities != NULL ) && ( fDistribute == TRS_TRUE ) && ( nThreads != -1 ); - if ( bUseAffinityTable ) - { - // user supplied an optional 1:1 affinity mapping to override normal distribute behavior - nThreads = MIN( TP_MAX_POOL_THREADS, nThreads ); - for ( unsigned int i = 0; i < nThreads; i++ ) - { - iAffinityTable[i] = pAffinities[i]; - } - } - } - - int nThreads; - int nThreadsMax; - ThreeState_t fDistribute; - int nStackSize; - int iThreadPriority; - int iAffinityTable[TP_MAX_POOL_THREADS]; - - bool bIOThreads : 1; - bool bUseAffinityTable : 1; -}; - -//----------------------------------------------------------------------------- -// -// IThreadPool -// -//----------------------------------------------------------------------------- - -typedef bool (*JobFilter_t)( CJob * ); - -//--------------------------------------------------------- -// Messages supported through the CallWorker() method -//--------------------------------------------------------- -enum ThreadPoolMessages_t -{ - TPM_EXIT, // Exit the thread - TPM_SUSPEND, // Suspend after next operation - TPM_RUNFUNCTOR, // Run functor, reply when done. -}; - -//--------------------------------------------------------- - -abstract_class IThreadPool : public IRefCounted -{ -public: - virtual ~IThreadPool() {}; - - //----------------------------------------------------- - // Thread functions - //----------------------------------------------------- - virtual bool Start( const ThreadPoolStartParams_t &startParams = ThreadPoolStartParams_t() ) = 0; - virtual bool Stop( int timeout = TT_INFINITE ) = 0; - - //----------------------------------------------------- - // Functions for any thread - //----------------------------------------------------- - virtual unsigned GetJobCount() = 0; - virtual int NumThreads() = 0; - virtual int NumIdleThreads() = 0; - - //----------------------------------------------------- - // Pause/resume processing jobs - //----------------------------------------------------- - virtual int SuspendExecution() = 0; - virtual int ResumeExecution() = 0; - - //----------------------------------------------------- - // Offer the current thread to the pool - //----------------------------------------------------- - virtual int YieldWait( CThreadEvent **pEvents, int nEvents, bool bWaitAll = true, unsigned timeout = TT_INFINITE ) = 0; - virtual int YieldWait( CJob **, int nJobs, bool bWaitAll = true, unsigned timeout = TT_INFINITE ) = 0; - virtual void Yield( unsigned timeout ) = 0; - - bool YieldWait( CThreadEvent &event, unsigned timeout = TT_INFINITE ); - bool YieldWait( CJob *, unsigned timeout = TT_INFINITE ); - - //----------------------------------------------------- - // Add a native job to the queue (master thread) - //----------------------------------------------------- - virtual void AddJob( CJob * ) = 0; - - //----------------------------------------------------- - // All threads execute pFunctor asap. Thread will either wake up - // and execute or execute pFunctor right after completing current job and - // before looking for another job. - //----------------------------------------------------- - virtual void ExecuteHighPriorityFunctor( CFunctor *pFunctor ) = 0; - - //----------------------------------------------------- - // Add an function object to the queue (master thread) - //----------------------------------------------------- - virtual void AddFunctor( CFunctor *pFunctor, CJob **ppJob = NULL, const char *pszDescription = NULL, unsigned flags = 0 ) { AddFunctorInternal( RetAddRef( pFunctor ), ppJob, pszDescription, flags ); } - - //----------------------------------------------------- - // Change the priority of an active job - //----------------------------------------------------- - virtual void ChangePriority( CJob *p, JobPriority_t priority ) = 0; - - //----------------------------------------------------- - // Bulk job manipulation (blocking) - //----------------------------------------------------- - int ExecuteAll( JobFilter_t pfnFilter = NULL ) { return ExecuteToPriority( JP_LOW, pfnFilter ); } - virtual int ExecuteToPriority( JobPriority_t toPriority, JobFilter_t pfnFilter = NULL ) = 0; - virtual int AbortAll() = 0; - - //----------------------------------------------------- - virtual void Reserved1() = 0; - - //----------------------------------------------------- - // Add an arbitrary call to the queue (master thread) - // - // Avert thy eyes! Imagine rather: - // - // CJob *AddCall( , [args1, [arg2,]...] - // CJob *AddCall( , , [args1, [arg2,]...] - // CJob *AddRefCall( , , [args1, [arg2,]...] - // CJob *QueueCall( , [args1, [arg2,]...] - // CJob *QueueCall( , , [args1, [arg2,]...] - //----------------------------------------------------- - - #define DEFINE_NONMEMBER_ADD_CALL(N) \ - template \ - CJob *AddCall(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - CJob *pJob; \ - if ( !NumIdleThreads() ) \ - { \ - pJob = GetDummyJob(); \ - FunctorDirectCall( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \ - } \ - else \ - { \ - AddFunctorInternal( CreateFunctor( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob ); \ - } \ - \ - return pJob; \ - } - - //------------------------------------- - - #define DEFINE_MEMBER_ADD_CALL(N) \ - template \ - CJob *AddCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - CJob *pJob; \ - if ( !NumIdleThreads() ) \ - { \ - pJob = GetDummyJob(); \ - FunctorDirectCall( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \ - } \ - else \ - { \ - AddFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob ); \ - } \ - \ - return pJob; \ - } - - //------------------------------------- - - #define DEFINE_CONST_MEMBER_ADD_CALL(N) \ - template \ - CJob *AddCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - CJob *pJob; \ - if ( !NumIdleThreads() ) \ - { \ - pJob = GetDummyJob(); \ - FunctorDirectCall( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \ - } \ - else \ - { \ - AddFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob ); \ - } \ - \ - return pJob; \ - } - - //------------------------------------- - - #define DEFINE_REF_COUNTING_MEMBER_ADD_CALL(N) \ - template \ - CJob *AddRefCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - CJob *pJob; \ - if ( !NumIdleThreads() ) \ - { \ - pJob = GetDummyJob(); \ - FunctorDirectCall( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \ - } \ - else \ - { \ - AddFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob ); \ - } \ - \ - return pJob; \ - } - - //------------------------------------- - - #define DEFINE_REF_COUNTING_CONST_MEMBER_ADD_CALL(N) \ - template \ - CJob *AddRefCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - CJob *pJob; \ - if ( !NumIdleThreads() ) \ - { \ - pJob = GetDummyJob(); \ - FunctorDirectCall( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \ - } \ - else \ - { \ - AddFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob ); \ - } \ - \ - return pJob; \ - } - - //----------------------------------------------------------------------------- - - #define DEFINE_NONMEMBER_QUEUE_CALL(N) \ - template \ - CJob *QueueCall(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - CJob *pJob; \ - AddFunctorInternal( CreateFunctor( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob, NULL, JF_QUEUE ); \ - return pJob; \ - } - - //------------------------------------- - - #define DEFINE_MEMBER_QUEUE_CALL(N) \ - template \ - CJob *QueueCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - CJob *pJob; \ - AddFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob, NULL, JF_QUEUE ); \ - return pJob; \ - } - - //------------------------------------- - - #define DEFINE_CONST_MEMBER_QUEUE_CALL(N) \ - template \ - CJob *QueueCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - CJob *pJob; \ - AddFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob, NULL, JF_QUEUE ); \ - return pJob; \ - } - - //------------------------------------- - - #define DEFINE_REF_COUNTING_MEMBER_QUEUE_CALL(N) \ - template \ - CJob *QueueRefCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - CJob *pJob; \ - AddFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob, NULL, JF_QUEUE ); \ - return pJob; \ - } - - //------------------------------------- - - #define DEFINE_REF_COUNTING_CONST_MEMBER_QUEUE_CALL(N) \ - template \ - CJob *QueueRefCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - CJob *pJob; \ - AddFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob, NULL, JF_QUEUE ); \ - \ - return pJob; \ - } - - FUNC_GENERATE_ALL( DEFINE_NONMEMBER_ADD_CALL ); - FUNC_GENERATE_ALL( DEFINE_MEMBER_ADD_CALL ); - FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_ADD_CALL ); - FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_MEMBER_ADD_CALL ); - FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_CONST_MEMBER_ADD_CALL ); - FUNC_GENERATE_ALL( DEFINE_NONMEMBER_QUEUE_CALL ); - FUNC_GENERATE_ALL( DEFINE_MEMBER_QUEUE_CALL ); - FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_QUEUE_CALL ); - FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_MEMBER_QUEUE_CALL ); - FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_CONST_MEMBER_QUEUE_CALL ); - - #undef DEFINE_NONMEMBER_ADD_CALL - #undef DEFINE_MEMBER_ADD_CALL - #undef DEFINE_CONST_MEMBER_ADD_CALL - #undef DEFINE_REF_COUNTING_MEMBER_ADD_CALL - #undef DEFINE_REF_COUNTING_CONST_MEMBER_ADD_CALL - #undef DEFINE_NONMEMBER_QUEUE_CALL - #undef DEFINE_MEMBER_QUEUE_CALL - #undef DEFINE_CONST_MEMBER_QUEUE_CALL - #undef DEFINE_REF_COUNTING_MEMBER_QUEUE_CALL - #undef DEFINE_REF_COUNTING_CONST_MEMBER_QUEUE_CALL - -private: - virtual void AddFunctorInternal( CFunctor *, CJob ** = NULL, const char *pszDescription = NULL, unsigned flags = 0 ) = 0; - - //----------------------------------------------------- - // Services for internal use by job instances - //----------------------------------------------------- - friend class CJob; - - virtual CJob *GetDummyJob() = 0; - -public: - virtual void Distribute( bool bDistribute = true, int *pAffinityTable = NULL ) = 0; - - virtual bool Start( const ThreadPoolStartParams_t &startParams, const char *pszNameOverride ) = 0; -}; - -//----------------------------------------------------------------------------- - -JOB_INTERFACE IThreadPool *CreateThreadPool(); -JOB_INTERFACE void DestroyThreadPool( IThreadPool *pPool ); - -//------------------------------------- - -JOB_INTERFACE void RunThreadPoolTests(); - -//----------------------------------------------------------------------------- - -JOB_INTERFACE IThreadPool *g_pThreadPool; - -//----------------------------------------------------------------------------- -// Class to combine the metadata for an operation and the ability to perform -// the operation. Meant for inheritance. All functions inline, defers to executor -//----------------------------------------------------------------------------- -DECLARE_POINTER_HANDLE( ThreadPoolData_t ); -#define JOB_NO_DATA ((ThreadPoolData_t)-1) - -class CJob : public CRefCounted1 -{ -public: - CJob( JobPriority_t priority = JP_NORMAL ) - : m_status( JOB_STATUS_UNSERVICED ), - m_ThreadPoolData( JOB_NO_DATA ), - m_priority( priority ), - m_flags( 0 ), - m_pThreadPool( NULL ), - m_CompleteEvent( true ), - m_iServicingThread( -1 ) - { - m_szDescription[ 0 ] = 0; - } - - //----------------------------------------------------- - // Priority (not thread safe) - //----------------------------------------------------- - void SetPriority( JobPriority_t priority ) { m_priority = priority; } - JobPriority_t GetPriority() const { return m_priority; } - - //----------------------------------------------------- - - void SetFlags( unsigned flags ) { m_flags = flags; } - unsigned GetFlags() const { return m_flags; } - - //----------------------------------------------------- - - void SetServiceThread( int iServicingThread ) { m_iServicingThread = (char)iServicingThread; } - int GetServiceThread() const { return m_iServicingThread; } - void ClearServiceThread() { m_iServicingThread = -1; } - - //----------------------------------------------------- - // Fast queries - //----------------------------------------------------- - bool Executed() const { return ( m_status == JOB_OK ); } - bool CanExecute() const { return ( m_status == JOB_STATUS_PENDING || m_status == JOB_STATUS_UNSERVICED ); } - bool IsFinished() const { return ( m_status != JOB_STATUS_PENDING && m_status != JOB_STATUS_INPROGRESS && m_status != JOB_STATUS_UNSERVICED ); } - JobStatus_t GetStatus() const { return m_status; } - - /// Slam the status to a particular value. This is named "slam" instead of "set," - /// to warn you that it should only be used in unusual situations. Otherwise, the - /// job manager really should manage the status for you, and you should not manhandle it. - void SlamStatus(JobStatus_t s) { m_status = s; } - - //----------------------------------------------------- - // Try to acquire ownership (to satisfy). If you take the lock, you must either execute or abort. - //----------------------------------------------------- - bool TryLock() { return m_mutex.TryLock(); } - void Lock() { m_mutex.Lock(); } - void Unlock() { m_mutex.Unlock(); } - - //----------------------------------------------------- - // Thread event support (safe for NULL this to simplify code ) - //----------------------------------------------------- - bool WaitForFinish( uint32 dwTimeout = TT_INFINITE ) { if (!this) return true; return ( !IsFinished() ) ? g_pThreadPool->YieldWait( this, dwTimeout ) : true; } - bool WaitForFinishAndRelease( uint32 dwTimeout = TT_INFINITE ) { if (!this) return true; bool bResult = WaitForFinish( dwTimeout); Release(); return bResult; } - CThreadEvent *AccessEvent() { return &m_CompleteEvent; } - - //----------------------------------------------------- - // Perform the job - //----------------------------------------------------- - JobStatus_t Execute(); - JobStatus_t TryExecute(); - JobStatus_t ExecuteAndRelease() { JobStatus_t status = Execute(); Release(); return status; } - JobStatus_t TryExecuteAndRelease() { JobStatus_t status = TryExecute(); Release(); return status; } - - //----------------------------------------------------- - // Terminate the job, discard if partially or wholly fulfilled - //----------------------------------------------------- - JobStatus_t Abort( bool bDiscard = true ); - - virtual char const *Describe() { return m_szDescription[ 0 ] ? m_szDescription : "Job"; } - virtual void SetDescription( const char *pszDescription ) - { - if( pszDescription ) - { - Q_strncpy( m_szDescription, pszDescription, sizeof( m_szDescription ) ); - } - else - { - m_szDescription[ 0 ] = 0; - } - } - -private: - //----------------------------------------------------- - friend class CThreadPool; - - JobStatus_t m_status; - JobPriority_t m_priority; - CThreadMutex m_mutex; - unsigned char m_flags; - char m_iServicingThread; - short m_reserved; - ThreadPoolData_t m_ThreadPoolData; - IThreadPool * m_pThreadPool; - CThreadEvent m_CompleteEvent; - char m_szDescription[ 32 ]; - -private: - //----------------------------------------------------- - CJob( const CJob &fromRequest ); - void operator=(const CJob &fromRequest ); - - virtual JobStatus_t DoExecute() = 0; - virtual JobStatus_t DoAbort( bool bDiscard ) { return JOB_STATUS_ABORTED; } - virtual void DoCleanup() {} -}; - -//----------------------------------------------------------------------------- - -class CFunctorJob : public CJob -{ -public: - CFunctorJob( CFunctor *pFunctor, const char *pszDescription = NULL ) - : m_pFunctor( pFunctor ) - { - if ( pszDescription ) - { - Q_strncpy( m_szDescription, pszDescription, sizeof(m_szDescription) ); - } - else - { - m_szDescription[0] = 0; - } - } - - virtual JobStatus_t DoExecute() - { - (*m_pFunctor)(); - return JOB_OK; - } - - const char *Describe() - { - return m_szDescription; - } - -private: - CRefPtr m_pFunctor; - char m_szDescription[16]; -}; - -//----------------------------------------------------------------------------- -// Utility for managing multiple jobs -//----------------------------------------------------------------------------- - -class CJobSet -{ -public: - CJobSet( CJob *pJob = NULL ) - { - if ( pJob ) - { - m_jobs.AddToTail( pJob ); - } - } - - CJobSet( CJob **ppJobs, int nJobs ) - { - if ( ppJobs ) - { - m_jobs.AddMultipleToTail( nJobs, ppJobs ); - } - } - - ~CJobSet() - { - for ( int i = 0; i < m_jobs.Count(); i++ ) - { - m_jobs[i]->Release(); - } - } - - void operator+=( CJob *pJob ) - { - m_jobs.AddToTail( pJob ); - } - - void operator-=( CJob *pJob ) - { - m_jobs.FindAndRemove( pJob ); - } - - void Execute( bool bRelease = true ) - { - for ( int i = 0; i < m_jobs.Count(); i++ ) - { - m_jobs[i]->Execute(); - if ( bRelease ) - { - m_jobs[i]->Release(); - } - } - - if ( bRelease ) - { - m_jobs.RemoveAll(); - } - } - - void Abort( bool bRelease = true ) - { - for ( int i = 0; i < m_jobs.Count(); i++ ) - { - m_jobs[i]->Abort(); - if ( bRelease ) - { - m_jobs[i]->Release(); - } - } - - if ( bRelease ) - { - m_jobs.RemoveAll(); - } - } - - void WaitForFinish( bool bRelease = true ) - { - for ( int i = 0; i < m_jobs.Count(); i++ ) - { - m_jobs[i]->WaitForFinish(); - if ( bRelease ) - { - m_jobs[i]->Release(); - } - } - - if ( bRelease ) - { - m_jobs.RemoveAll(); - } - } - - void WaitForFinish( IThreadPool *pPool, bool bRelease = true ) - { - pPool->YieldWait( m_jobs.Base(), m_jobs.Count() ); - - if ( bRelease ) - { - for ( int i = 0; i < m_jobs.Count(); i++ ) - { - m_jobs[i]->Release(); - } - - m_jobs.RemoveAll(); - } - } - -private: - CUtlVectorFixed m_jobs; -}; - -//----------------------------------------------------------------------------- -// Job helpers -//----------------------------------------------------------------------------- - -#define ThreadExecute g_pThreadPool->QueueCall -#define ThreadExecuteRef g_pThreadPool->QueueRefCall - -#define BeginExecuteParallel() do { CJobSet jobSet -#define EndExecuteParallel() jobSet.WaitForFinish( g_pThreadPool ); } while (0) - -#define ExecuteParallel jobSet += g_pThreadPool->QueueCall -#define ExecuteRefParallel jobSet += g_pThreadPool->QueueCallRef - - -//----------------------------------------------------------------------------- -// Work splitting: array split, best when cost per item is roughly equal -//----------------------------------------------------------------------------- - -#pragma warning(push) -#pragma warning(disable:4389) -#pragma warning(disable:4018) -#pragma warning(disable:4701) - -#if !defined(__clang__) && ( !defined( GNUC ) || ( defined( GNUC ) && __GNUC_MINOR__ < 3 ) ) -#define DEFINE_NON_MEMBER_ITER_RANGE_PARALLEL(N) \ - template \ - void IterRangeParallel(FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( ITERTYPE1, ITERTYPE2 FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ), ITERTYPE1 from, ITERTYPE2 to FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - const int MAX_THREADS = 16; \ - int nIdle = g_pThreadPool->NumIdleThreads(); \ - ITERTYPE1 range = to - from; \ - int nThreads = MIN( nIdle + 1, range ); \ - if ( nThreads > MAX_THREADS ) \ - { \ - nThreads = MAX_THREADS; \ - } \ - if ( nThreads < 2 ) \ - { \ - FunctorDirectCall( pfnProxied, from, to FUNC_FUNCTOR_CALL_ARGS_##N ); \ - } \ - else \ - { \ - ITERTYPE1 nIncrement = range / nThreads; \ - \ - CJobSet jobSet; \ - while ( --nThreads ) \ - { \ - ITERTYPE2 thisTo = from + nIncrement; \ - jobSet += g_pThreadPool->AddCall( pfnProxied, from, thisTo FUNC_FUNCTOR_CALL_ARGS_##N ); \ - from = thisTo; \ - } \ - FunctorDirectCall( pfnProxied, from, to FUNC_FUNCTOR_CALL_ARGS_##N ); \ - jobSet.WaitForFinish( g_pThreadPool ); \ - } \ - \ - } - -FUNC_GENERATE_ALL( DEFINE_NON_MEMBER_ITER_RANGE_PARALLEL ); - -#define DEFINE_MEMBER_ITER_RANGE_PARALLEL(N) \ - template \ - void IterRangeParallel(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( ITERTYPE1, ITERTYPE2 FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ), ITERTYPE1 from, ITERTYPE2 to FUNC_ARG_FORMAL_PARAMS_##N ) \ - { \ - const int MAX_THREADS = 16; \ - int nIdle = g_pThreadPool->NumIdleThreads(); \ - ITERTYPE1 range = to - from; \ - int nThreads = MIN( nIdle + 1, range ); \ - if ( nThreads > MAX_THREADS ) \ - { \ - nThreads = MAX_THREADS; \ - } \ - if ( nThreads < 2 ) \ - { \ - FunctorDirectCall( pObject, pfnProxied, from, to FUNC_FUNCTOR_CALL_ARGS_##N ); \ - } \ - else \ - { \ - ITERTYPE1 nIncrement = range / nThreads; \ - \ - CJobSet jobSet; \ - while ( --nThreads ) \ - { \ - ITERTYPE2 thisTo = from + nIncrement; \ - jobSet += g_pThreadPool->AddCall( pObject, pfnProxied, from, thisTo FUNC_FUNCTOR_CALL_ARGS_##N ); \ - from = thisTo; \ - } \ - FunctorDirectCall( pObject, pfnProxied, from, to FUNC_FUNCTOR_CALL_ARGS_##N ); \ - jobSet.WaitForFinish( g_pThreadPool ); \ - } \ - \ - } - -FUNC_GENERATE_ALL( DEFINE_MEMBER_ITER_RANGE_PARALLEL ); -#endif // GCC - -//----------------------------------------------------------------------------- -// Work splitting: competitive, best when cost per item varies a lot -//----------------------------------------------------------------------------- - -template -class CJobItemProcessor -{ -public: - typedef T ItemType_t; - void Begin() {} - // void Process( ItemType_t & ) {} - void End() {} -}; - -template -class CFuncJobItemProcessor : public CJobItemProcessor -{ -public: - void Init(void (*pfnProcess)( T & ), void (*pfnBegin)() = NULL, void (*pfnEnd)() = NULL ) - { - m_pfnProcess = pfnProcess; - m_pfnBegin = pfnBegin; - m_pfnEnd = pfnEnd; - } - - //CFuncJobItemProcessor(OBJECT_TYPE_PTR pObject, void (FUNCTION_CLASS::*pfnProcess)( ITEM_TYPE & ), void (*pfnBegin)() = NULL, void (*pfnEnd)() = NULL ); - void Begin() { if ( m_pfnBegin ) (*m_pfnBegin)(); } - void Process( T &item ) { (*m_pfnProcess)( item ); } - void End() { if ( m_pfnEnd ) (*m_pfnEnd)(); } - -protected: - void (*m_pfnProcess)( T & ); - void (*m_pfnBegin)(); - void (*m_pfnEnd)(); -}; - -template -class CMemberFuncJobItemProcessor : public CJobItemProcessor -{ -public: - void Init( OBJECT_TYPE *pObject, void (FUNCTION_CLASS::*pfnProcess)( T & ), void (FUNCTION_CLASS::*pfnBegin)() = NULL, void (FUNCTION_CLASS::*pfnEnd)() = NULL ) - { - m_pObject = pObject; - m_pfnProcess = pfnProcess; - m_pfnBegin = pfnBegin; - m_pfnEnd = pfnEnd; - } - - void Begin() { if ( m_pfnBegin ) ((*m_pObject).*m_pfnBegin)(); } - void Process( T &item ) { ((*m_pObject).*m_pfnProcess)( item ); } - void End() { if ( m_pfnEnd ) ((*m_pObject).*m_pfnEnd)(); } - -protected: - OBJECT_TYPE *m_pObject; - void (FUNCTION_CLASS::*m_pfnProcess)( T & ); - void (FUNCTION_CLASS::*m_pfnBegin)(); - void (FUNCTION_CLASS::*m_pfnEnd)(); -}; - -template -class CParallelProcessor -{ -public: - CParallelProcessor( const char *pszDescription ) - { - m_pItems = m_pLimit= 0; - m_szDescription = pszDescription; - } - - void Run( ITEM_TYPE *pItems, unsigned nItems, int nMaxParallel = INT_MAX, IThreadPool *pThreadPool = NULL ) - { - if ( nItems == 0 ) - return; - - if ( !pThreadPool ) - { - pThreadPool = g_pThreadPool; - } - - m_pItems = pItems; - m_pLimit = pItems + nItems; - - int nJobs = nItems - 1; - - if ( nJobs > nMaxParallel ) - { - nJobs = nMaxParallel; - } - - if (! pThreadPool ) // only possible on linux - { - DoExecute( ); - return; - } - - int nThreads = pThreadPool->NumThreads(); - if ( nJobs > nThreads ) - { - nJobs = nThreads; - } - - if ( nJobs > 1 ) - { - CJob **jobs = (CJob **)stackalloc( nJobs * sizeof(CJob **) ); - int i = nJobs; - - while( i-- ) - { - jobs[i] = pThreadPool->QueueCall( this, &CParallelProcessor::DoExecute ); - jobs[i]->SetDescription( m_szDescription ); - } - - DoExecute(); - - for ( i = 0; i < nJobs; i++ ) - { - jobs[i]->Abort(); // will either abort ones that never got a thread, or noop on ones that did - jobs[i]->Release(); - } - } - else - { - DoExecute(); - } - } - - ITEM_PROCESSOR_TYPE m_ItemProcessor; - -private: - void DoExecute() - { - if ( m_pItems < m_pLimit ) - { - m_ItemProcessor.Begin(); - - ITEM_TYPE *pLimit = m_pLimit; - - for (;;) - { - ITEM_TYPE *pCurrent = m_pItems++; - if ( pCurrent < pLimit ) - { - m_ItemProcessor.Process( *pCurrent ); - } - else - { - break; - } - } - - m_ItemProcessor.End(); - } - } - CInterlockedPtr m_pItems; - ITEM_TYPE * m_pLimit; - const char * m_szDescription; -}; - -template -inline void ParallelProcess( const char *pszDescription, ITEM_TYPE *pItems, unsigned nItems, void (*pfnProcess)( ITEM_TYPE & ), void (*pfnBegin)() = NULL, void (*pfnEnd)() = NULL, int nMaxParallel = INT_MAX ) -{ - CParallelProcessor > processor( pszDescription ); - processor.m_ItemProcessor.Init( pfnProcess, pfnBegin, pfnEnd ); - processor.Run( pItems, nItems, nMaxParallel ); - -} - -template -inline void ParallelProcess( const char *pszDescription, ITEM_TYPE *pItems, unsigned nItems, OBJECT_TYPE *pObject, void (FUNCTION_CLASS::*pfnProcess)( ITEM_TYPE & ), void (FUNCTION_CLASS::*pfnBegin)() = NULL, void (FUNCTION_CLASS::*pfnEnd)() = NULL, int nMaxParallel = INT_MAX ) -{ - CParallelProcessor > processor( pszDescription ); - processor.m_ItemProcessor.Init( pObject, pfnProcess, pfnBegin, pfnEnd ); - processor.Run( pItems, nItems, nMaxParallel ); -} - -// Parallel Process that lets you specify threadpool -template -inline void ParallelProcess( const char *pszDescription, IThreadPool *pPool, ITEM_TYPE *pItems, unsigned nItems, void (*pfnProcess)( ITEM_TYPE & ), void (*pfnBegin)() = NULL, void (*pfnEnd)() = NULL, int nMaxParallel = INT_MAX ) -{ - CParallelProcessor > processor( pszDescription ); - processor.m_ItemProcessor.Init( pfnProcess, pfnBegin, pfnEnd ); - processor.Run( pItems, nItems, nMaxParallel, pPool ); -} - - -template -class CParallelLoopProcessor -{ -public: - CParallelLoopProcessor( const char *pszDescription ) - { - m_lIndex = m_lLimit= 0; - m_nActive = 0; - m_szDescription = pszDescription; - } - - void Run( long lBegin, long nItems, int nMaxParallel = INT_MAX ) - { - if ( nItems ) - { - m_lIndex = lBegin; - m_lLimit = lBegin + nItems; - int i = g_pThreadPool->NumIdleThreads(); - - if ( nMaxParallel < i) - { - i = nMaxParallel; - } - - while( i-- ) - { - ++m_nActive; - ThreadExecute( this, &CParallelLoopProcessor::DoExecute )->Release(); - } - - ++m_nActive; - DoExecute(); - - while ( m_nActive ) - { - ThreadPause(); - } - } - } - - ITEM_PROCESSOR_TYPE m_ItemProcessor; - -private: - void DoExecute() - { - m_ItemProcessor.Begin(); - - long lLimit = m_lLimit; - - for (;;) - { - long lIndex = m_lIndex ++; - if ( lIndex < lLimit ) - { - m_ItemProcessor.Process( lIndex ); - } - else - { - break; - } - } - - m_ItemProcessor.End(); - - --m_nActive; - } - CInterlockedInt m_lIndex; - long m_lLimit; - CInterlockedInt m_nActive; - const char * m_szDescription; -}; - -inline void ParallelLoopProcess( const char *szDescription, long lBegin, unsigned nItems, void (*pfnProcess)( long const & ), void (*pfnBegin)() = NULL, void (*pfnEnd)() = NULL, int nMaxParallel = INT_MAX ) -{ - CParallelLoopProcessor< CFuncJobItemProcessor< long const > > processor( szDescription ); - processor.m_ItemProcessor.Init( pfnProcess, pfnBegin, pfnEnd ); - processor.Run( lBegin, nItems, nMaxParallel ); - -} - -template < typename OBJECT_TYPE, typename FUNCTION_CLASS > -inline void ParallelLoopProcess( const char *szDescription, long lBegin, unsigned nItems, OBJECT_TYPE *pObject, void (FUNCTION_CLASS::*pfnProcess)( long const & ), void (FUNCTION_CLASS::*pfnBegin)() = NULL, void (FUNCTION_CLASS::*pfnEnd)() = NULL, int nMaxParallel = INT_MAX ) -{ - CParallelLoopProcessor< CMemberFuncJobItemProcessor > processor( szDescription ); - processor.m_ItemProcessor.Init( pObject, pfnProcess, pfnBegin, pfnEnd ); - processor.Run( lBegin, nItems, nMaxParallel ); -} - - -template -class CParallelProcessorBase -{ -protected: - typedef CParallelProcessorBase ThisParallelProcessorBase_t; - typedef Derived ThisParallelProcessorDerived_t; - -public: - CParallelProcessorBase() - { - m_nActive = 0; - m_szDescription = NULL; - } - void SetDescription( const char *pszDescription ) - { - m_szDescription = pszDescription; - } - -protected: - void Run( int nMaxParallel = INT_MAX, int threadOverride = -1 ) - { - int i = g_pThreadPool->NumIdleThreads(); - - if ( nMaxParallel < i) - { - i = nMaxParallel; - } - - while( i -- > 0 ) - { - if ( threadOverride == -1 || i == threadOverride - 1 ) - { - ++ m_nActive; - ThreadExecute( this, &ThisParallelProcessorBase_t::DoExecute )->Release(); - } - } - - if ( threadOverride == -1 || threadOverride == 0 ) - { - ++ m_nActive; - DoExecute(); - } - - while ( m_nActive ) - { - ThreadPause(); - } - } - -protected: - void OnBegin() {} - bool OnProcess() { return false; } - void OnEnd() {} - -private: - void DoExecute() - { - static_cast( this )->OnBegin(); - - while ( static_cast( this )->OnProcess() ) - continue; - - static_cast(this)->OnEnd(); - - -- m_nActive; - } - - CInterlockedInt m_nActive; - const char * m_szDescription; -}; - - - - -//----------------------------------------------------------------------------- -// Raw thread launching -//----------------------------------------------------------------------------- - -inline unsigned FunctorExecuteThread( void *pParam ) -{ - CFunctor *pFunctor = (CFunctor *)pParam; - (*pFunctor)(); - pFunctor->Release(); - return 0; -} - -inline ThreadHandle_t ThreadExecuteSoloImpl( CFunctor *pFunctor, const char *pszName = NULL ) -{ - ThreadHandle_t hThread; - ThreadId_t threadId; - hThread = CreateSimpleThread( FunctorExecuteThread, pFunctor, &threadId ); - if ( pszName ) - { - ThreadSetDebugName( threadId, pszName ); - } - return hThread; -} - -inline ThreadHandle_t ThreadExecuteSolo( CJob *pJob ) { return ThreadExecuteSoloImpl( CreateFunctor( pJob, &CJob::Execute ), pJob->Describe() ); } - -template -inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1 ), pszName ); } - -template -inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1, T2 a2 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1, a2 ), pszName ); } - -template -inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1, T2 a2, T3 a3 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1, a2, a3 ), pszName ); } - -template -inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1, a2, a3, a4 ), pszName ); } - -template -inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1, a2, a3, a4, a5 ), pszName ); } - -template -inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1, a2, a3, a4, a5, a6 ), pszName ); } - -template -inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1, a2, a3, a4, a5, a6, a7 ), pszName ); } - -template -inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1, a2, a3, a4, a5, a6, a7, a8 ), pszName ); } - -template -inline ThreadHandle_t ThreadExecuteSoloRef( const char *pszName, T1 a1, T2 a2 ) { return ThreadExecuteSoloImpl( CreateRefCountingFunctor(a1, a2 ), pszName ); } - -template -inline ThreadHandle_t ThreadExecuteSoloRef( const char *pszName, T1 a1, T2 a2, T3 a3 ) { return ThreadExecuteSoloImpl( CreateRefCountingFunctor(a1, a2, a3 ), pszName ); } - -template -inline ThreadHandle_t ThreadExecuteSoloRef( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4 ) { return ThreadExecuteSoloImpl( CreateRefCountingFunctor(a1, a2, a3, a4 ), pszName ); } - -template -inline ThreadHandle_t ThreadExecuteSoloRef( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5 ) { return ThreadExecuteSoloImpl( CreateRefCountingFunctor(a1, a2, a3, a4, a5 ), pszName ); } - -template -inline ThreadHandle_t ThreadExecuteSoloRef( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6 ) { return ThreadExecuteSoloImpl( CreateRefCountingFunctor(a1, a2, a3, a4, a5, a6 ), pszName ); } - -template -inline ThreadHandle_t ThreadExecuteSoloRef( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7 ) { return ThreadExecuteSoloImpl( CreateRefCountingFunctor(a1, a2, a3, a4, a5, a6, a7 ), pszName ); } - -template -inline ThreadHandle_t ThreadExecuteSoloRef( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8 ) { return ThreadExecuteSoloImpl( CreateRefCountingFunctor(a1, a2, a3, a4, a5, a6, a7, a8 ), pszName ); } - -//----------------------------------------------------------------------------- - -inline bool IThreadPool::YieldWait( CThreadEvent &event, unsigned timeout ) -{ - CThreadEvent *pEvent = &event; - return ( YieldWait( &pEvent, 1, true, timeout ) != TW_TIMEOUT ); -} - -inline bool IThreadPool::YieldWait( CJob *pJob, unsigned timeout ) -{ - return ( YieldWait( &pJob, 1, true, timeout ) != TW_TIMEOUT ); -} - -//----------------------------------------------------------------------------- - -inline JobStatus_t CJob::Execute() -{ - if ( IsFinished() ) - { - return m_status; - } - - AUTO_LOCK( m_mutex ); - AddRef(); - - JobStatus_t result; - - switch ( m_status ) - { - case JOB_STATUS_UNSERVICED: - case JOB_STATUS_PENDING: - { - // Service it - m_status = JOB_STATUS_INPROGRESS; - result = m_status = DoExecute(); - DoCleanup(); - m_CompleteEvent.Set(); - break; - } - - case JOB_STATUS_INPROGRESS: - AssertMsg(0, "Mutex Should have protected use while processing"); - // fall through... - - case JOB_OK: - case JOB_STATUS_ABORTED: - result = m_status; - break; - - default: - AssertMsg( m_status < JOB_OK, "Unknown job state"); - result = m_status; - } - - Release(); - - return result; -} - - -//--------------------------------------------------------- - -inline JobStatus_t CJob::TryExecute() -{ - // TryLock() would only fail if another thread has entered - // Execute() or Abort() - if ( !IsFinished() && TryLock() ) - { - // ...service the request - Execute(); - Unlock(); - } - return m_status; -} - -//--------------------------------------------------------- - -inline JobStatus_t CJob::Abort( bool bDiscard ) -{ - if ( IsFinished() ) - { - return m_status; - } - - AUTO_LOCK( m_mutex ); - AddRef(); - - JobStatus_t result; - - switch ( m_status ) - { - case JOB_STATUS_UNSERVICED: - case JOB_STATUS_PENDING: - { - result = m_status = DoAbort( bDiscard ); - if ( bDiscard ) - DoCleanup(); - m_CompleteEvent.Set(); - } - break; - - case JOB_STATUS_ABORTED: - case JOB_STATUS_INPROGRESS: - case JOB_OK: - result = m_status; - break; - - default: - AssertMsg( m_status < JOB_OK, "Unknown job state"); - result = m_status; - } - - Release(); - - return result; -} - -//----------------------------------------------------------------------------- - -#endif // JOBTHREAD_H - diff --git a/public/vstdlib/pch_vstdlib.h b/public/vstdlib/pch_vstdlib.h deleted file mode 100644 index 3340650ad..000000000 --- a/public/vstdlib/pch_vstdlib.h +++ /dev/null @@ -1,56 +0,0 @@ -//======== (C) Copyright 1999, 2000 Valve, L.L.C. All rights reserved. ======== -// -// The copyright to the contents herein is the property of Valve, L.L.C. -// The contents may be used and/or copied only with the written permission of -// Valve, L.L.C., or in accordance with the terms and conditions stipulated in -// the agreement/contract under which the contents have been supplied. -// -// Purpose: -// -// $Workfile: $ -// $NoKeywords: $ -//============================================================================= - - -#pragma warning(disable: 4514) - -// First include standard libraries -#include -#include -#include -#include -#include -#include -#ifdef _LINUX -#include -#include -#define _MAX_PATH PATH_MAX -#endif - -// Next, include public -#include "tier0/basetypes.h" -#include "tier0/dbg.h" -#include "tier0/valobject.h" - -// Next, include vstdlib -#include "vstdlib/vstdlib.h" -#include "tier1/strtools.h" -#include "vstdlib/random.h" -#include "tier1/KeyValues.h" -#include "tier1/utlmemory.h" -#include "tier1/utlrbtree.h" -#include "tier1/utlvector.h" -#include "tier1/utllinkedlist.h" -#include "tier1/utlmultilist.h" -#include "tier1/utlsymbol.h" -#include "tier0/icommandline.h" -#include "tier1/netadr.h" -#include "tier1/mempool.h" -#include "tier1/utlbuffer.h" -#include "tier1/utlstring.h" -#include "tier1/utlmap.h" - -#include "tier0/memdbgon.h" - - - diff --git a/public/vstdlib/random.h b/public/vstdlib/random.h deleted file mode 100644 index b0c7bcaf7..000000000 --- a/public/vstdlib/random.h +++ /dev/null @@ -1,114 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: Random number generator -// -// $Workfile: $ -// $NoKeywords: $ -//===========================================================================// - -#ifndef VSTDLIB_RANDOM_H -#define VSTDLIB_RANDOM_H - -#include "vstdlib/vstdlib.h" -#include "tier0/basetypes.h" -#include "tier0/threadtools.h" -#include "tier1/interface.h" - -#define NTAB 32 - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning( disable:4251 ) -#endif - -//----------------------------------------------------------------------------- -// A generator of uniformly distributed random numbers -//----------------------------------------------------------------------------- -class IUniformRandomStream -{ -public: - // Sets the seed of the random number generator - virtual void SetSeed( int iSeed ) = 0; - - // Generates random numbers - virtual float RandomFloat( float flMinVal = 0.0f, float flMaxVal = 1.0f ) = 0; - virtual int RandomInt( int iMinVal, int iMaxVal ) = 0; - virtual float RandomFloatExp( float flMinVal = 0.0f, float flMaxVal = 1.0f, float flExponent = 1.0f ) = 0; -}; - - -//----------------------------------------------------------------------------- -// The standard generator of uniformly distributed random numbers -//----------------------------------------------------------------------------- -class VSTDLIB_CLASS CUniformRandomStream : public IUniformRandomStream -{ -public: - CUniformRandomStream(); - - // Sets the seed of the random number generator - virtual void SetSeed( int iSeed ); - - // Generates random numbers - virtual float RandomFloat( float flMinVal = 0.0f, float flMaxVal = 1.0f ); - virtual int RandomInt( int iMinVal, int iMaxVal ); - virtual float RandomFloatExp( float flMinVal = 0.0f, float flMaxVal = 1.0f, float flExponent = 1.0f ); - -private: - int GenerateRandomNumber(); - - int m_idum; - int m_iy; - int m_iv[NTAB]; - - CThreadFastMutex m_mutex; -}; - - -//----------------------------------------------------------------------------- -// A generator of gaussian distributed random numbers -//----------------------------------------------------------------------------- -class VSTDLIB_CLASS CGaussianRandomStream -{ -public: - // Passing in NULL will cause the gaussian stream to use the - // installed global random number generator - CGaussianRandomStream( IUniformRandomStream *pUniformStream = NULL ); - - // Attaches to a random uniform stream - void AttachToStream( IUniformRandomStream *pUniformStream = NULL ); - - // Generates random numbers - float RandomFloat( float flMean = 0.0f, float flStdDev = 1.0f ); - -private: - IUniformRandomStream *m_pUniformStream; - bool m_bHaveValue; - float m_flRandomValue; - - CThreadFastMutex m_mutex; -}; - - -//----------------------------------------------------------------------------- -// A couple of convenience functions to access the library's global uniform stream -//----------------------------------------------------------------------------- -VSTDLIB_INTERFACE void RandomSeed( int iSeed ); -VSTDLIB_INTERFACE float RandomFloat( float flMinVal = 0.0f, float flMaxVal = 1.0f ); -VSTDLIB_INTERFACE float RandomFloatExp( float flMinVal = 0.0f, float flMaxVal = 1.0f, float flExponent = 1.0f ); -VSTDLIB_INTERFACE int RandomInt( int iMinVal, int iMaxVal ); -VSTDLIB_INTERFACE float RandomGaussianFloat( float flMean = 0.0f, float flStdDev = 1.0f ); - - -//----------------------------------------------------------------------------- -// Installs a global random number generator, which will affect the Random functions above -//----------------------------------------------------------------------------- -VSTDLIB_INTERFACE void InstallUniformRandomStream( IUniformRandomStream *pStream ); - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#endif // VSTDLIB_RANDOM_H - - - diff --git a/public/vstdlib/vcover.h b/public/vstdlib/vcover.h deleted file mode 100644 index cb62790ae..000000000 --- a/public/vstdlib/vcover.h +++ /dev/null @@ -1,125 +0,0 @@ -//========== Copyright 2005, Valve Corporation, All rights reserved. ======== -// -// Purpose: A simple tool for coverage tests -// -//============================================================================= - -#ifndef VCOVER_H -#define VCOVER_H - -#include "tier1/utlrbtree.h" -#include "vstdlib.h" - -#if defined( _WIN32 ) -#pragma once -#endif - -class CVCoverage -{ -public: - CVCoverage() : - m_bActive( false ), - m_depth( 0 ), - m_token( 1 ) - { - } - - bool IsActive() const - { - return m_bActive; - } - - void SetActive( bool bActive ) - { - Assert( bActive != m_bActive ); - m_bActive = bActive; - if ( bActive ) - ++m_token; - } - - void Begin() - { - ++m_depth; - } - - void End() - { - --m_depth; - } - - void Reset() - { - m_locations.RemoveAll(); - } - - bool ShouldCover( unsigned token ) const - { - return ( m_bActive && m_depth > 0 && token != m_token ); - } - - unsigned Cover( const char *pszFile, int line ) - { - Location_t location = { pszFile, line }; - - m_locations.Insert( location ); - - return m_token; - } - - void Report() - { - for ( int i = m_locations.FirstInorder(); i != m_locations.InvalidIndex(); i = m_locations.NextInorder( i ) ) - { - Msg( "%s(%d) :\n", m_locations[i].pszFile, m_locations[i].line ); - } - } - -private: - struct Location_t - { - const char *pszFile; - int line; - - }; - - class CLocationLess - { - public: - CLocationLess( int ignored ) {} - bool operator!() { return false; } - - bool operator()( const Location_t &lhs, const Location_t &rhs ) const - { - if ( lhs.line < rhs.line ) - { - return true; - } - - return CaselessStringLessThan( lhs.pszFile, rhs.pszFile ); - } - }; - - bool m_bActive; - int m_depth; - unsigned m_token; - - CUtlRBTree< Location_t, unsigned short, CLocationLess > m_locations; -}; - -VSTDLIB_INTERFACE CVCoverage g_VCoverage; - -#ifdef VCOVER_ENABLED -#define VCOVER() \ - do \ - { \ - static token; \ - if ( g_VCoverage.ShouldCover( token ) ) \ - { \ - token = g_VCoverage.Cover( __FILE__, __LINE__ ); \ - } \ - } while( 0 ) -#else -#define VCOVER() ((void)0) -#endif - -#endif // VCOVER_H diff --git a/public/vstdlib/vstdlib.h b/public/vstdlib/vstdlib.h deleted file mode 100644 index e5ef3db72..000000000 --- a/public/vstdlib/vstdlib.h +++ /dev/null @@ -1,33 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// - -#ifndef VSTDLIB_H -#define VSTDLIB_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "tier0/platform.h" - -//----------------------------------------------------------------------------- -// dll export stuff -//----------------------------------------------------------------------------- -#ifdef VSTDLIB_DLL_EXPORT -#define VSTDLIB_INTERFACE DLL_EXPORT -#define VSTDLIB_OVERLOAD DLL_GLOBAL_EXPORT -#define VSTDLIB_CLASS DLL_CLASS_EXPORT -#define VSTDLIB_GLOBAL DLL_GLOBAL_EXPORT -#else -#define VSTDLIB_INTERFACE DLL_IMPORT -#define VSTDLIB_OVERLOAD DLL_GLOBAL_IMPORT -#define VSTDLIB_CLASS DLL_CLASS_IMPORT -#define VSTDLIB_GLOBAL DLL_GLOBAL_IMPORT -#endif - -#endif // VSTDLIB_H diff --git a/public/vtf/vtf.h b/public/vtf/vtf.h deleted file mode 100644 index c56aa99f3..000000000 --- a/public/vtf/vtf.h +++ /dev/null @@ -1,606 +0,0 @@ -//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: -// -// $NoKeywords: $ -//===========================================================================// - -#ifndef VTF_H -#define VTF_H - -#ifdef _WIN32 -#pragma once -#endif - -#include "bitmap/imageformat.h" -#include "tier0/platform.h" - -// #define VTF_FILE_FORMAT_ONLY to just include the vtf header and none of the code declaration -#ifndef VTF_FILE_FORMAT_ONLY - -//----------------------------------------------------------------------------- -// Forward declarations -//----------------------------------------------------------------------------- -class CUtlBuffer; -class Vector; -struct Rect_t; -class IFileSystem; - -//----------------------------------------------------------------------------- -// Texture flags -//----------------------------------------------------------------------------- -enum CompiledVtfFlags -{ - // flags from the *.txt config file - TEXTUREFLAGS_POINTSAMPLE = 0x00000001, - TEXTUREFLAGS_TRILINEAR = 0x00000002, - TEXTUREFLAGS_CLAMPS = 0x00000004, - TEXTUREFLAGS_CLAMPT = 0x00000008, - TEXTUREFLAGS_ANISOTROPIC = 0x00000010, - TEXTUREFLAGS_HINT_DXT5 = 0x00000020, - TEXTUREFLAGS_SRGB = 0x00000040, - TEXTUREFLAGS_NORMAL = 0x00000080, - TEXTUREFLAGS_NOMIP = 0x00000100, - TEXTUREFLAGS_NOLOD = 0x00000200, - TEXTUREFLAGS_ALL_MIPS = 0x00000400, - TEXTUREFLAGS_PROCEDURAL = 0x00000800, - - // These are automatically generated by vtex from the texture data. - TEXTUREFLAGS_ONEBITALPHA = 0x00001000, - TEXTUREFLAGS_EIGHTBITALPHA = 0x00002000, - - // newer flags from the *.txt config file - TEXTUREFLAGS_ENVMAP = 0x00004000, - TEXTUREFLAGS_RENDERTARGET = 0x00008000, - TEXTUREFLAGS_DEPTHRENDERTARGET = 0x00010000, - TEXTUREFLAGS_NODEBUGOVERRIDE = 0x00020000, - TEXTUREFLAGS_SINGLECOPY = 0x00040000, - - TEXTUREFLAGS_UNUSED_00080000 = 0x00080000, - TEXTUREFLAGS_UNUSED_00100000 = 0x00100000, - TEXTUREFLAGS_UNUSED_00200000 = 0x00200000, - TEXTUREFLAGS_UNUSED_00400000 = 0x00400000, - - TEXTUREFLAGS_NODEPTHBUFFER = 0x00800000, - - TEXTUREFLAGS_UNUSED_01000000 = 0x01000000, - - TEXTUREFLAGS_CLAMPU = 0x02000000, - - TEXTUREFLAGS_VERTEXTEXTURE = 0x04000000, // Useable as a vertex texture - - TEXTUREFLAGS_SSBUMP = 0x08000000, - - TEXTUREFLAGS_UNUSED_10000000 = 0x10000000, - - // Clamp to border color on all texture coordinates - TEXTUREFLAGS_BORDER = 0x20000000, - - TEXTUREFLAGS_UNUSED_40000000 = 0x40000000, - TEXTUREFLAGS_UNUSED_80000000 = 0x80000000, -}; - -enum VersionedVtfFlags -{ - VERSIONED_VTF_FLAGS_MASK_7_3 = ~0xD1780400, // For a ver 7.3 or earlier only these flags are valid -}; - - -struct VtfProcessingOptions -{ - uint32 cbSize; // Set to sizeof( VtfProcessingOptions ) - - // - // Flags0 - // - enum Flags0 - { - // Have a channel decaying to a given decay goal for the given last number of mips - OPT_DECAY_R = 0x00000001, // Red decays - OPT_DECAY_G = 0x00000002, // Green decays - OPT_DECAY_B = 0x00000004, // Blue decays - OPT_DECAY_A = 0x00000008, // Alpha decays - - OPT_DECAY_EXP_R = 0x00000010, // Channel R decays exponentially (otherwise linearly) - OPT_DECAY_EXP_G = 0x00000020, // Channel G decays exponentially (otherwise linearly) - OPT_DECAY_EXP_B = 0x00000040, // Channel B decays exponentially (otherwise linearly) - OPT_DECAY_EXP_A = 0x00000080, // Channel A decays exponentially (otherwise linearly) - - OPT_NOCOMPRESS = 0x00000100, // Use uncompressed image format - OPT_NORMAL_DUDV = 0x00000200, // dU dV normal map - OPT_FILTER_NICE = 0x00000400, // Use nice filtering - - OPT_SET_ALPHA_ONEOVERMIP = 0x00001000, // Alpha = 1/miplevel - OPT_PREMULT_COLOR_ONEOVERMIP = 0x00002000, // Color *= 1/miplevel - OPT_MIP_ALPHATEST = 0x00004000, // Alpha-tested mip generation - }; - - uint32 flags0; // A combination of "Flags0" - - // - // Decay settings - // - uint8 clrDecayGoal[4]; // Goal colors for R G B A - uint8 numNotDecayMips[4]; // Number of first mips unaffected by decay (0 means all below mip0) - float fDecayExponentBase[4]; // For exponential decay the base number (e.g. 0.75) -}; - - -//----------------------------------------------------------------------------- -// Cubemap face indices -//----------------------------------------------------------------------------- -enum CubeMapFaceIndex_t -{ - CUBEMAP_FACE_RIGHT = 0, - CUBEMAP_FACE_LEFT, - CUBEMAP_FACE_BACK, // NOTE: This face is in the +y direction?!?!? - CUBEMAP_FACE_FRONT, // NOTE: This face is in the -y direction!?!? - CUBEMAP_FACE_UP, - CUBEMAP_FACE_DOWN, - - // This is the fallback for low-end - CUBEMAP_FACE_SPHEREMAP, - - // NOTE: Cubemaps have *7* faces; the 7th is the fallback spheremap - CUBEMAP_FACE_COUNT -}; - - -//----------------------------------------------------------------------------- -// Enumeration used for spheremap generation -//----------------------------------------------------------------------------- -enum LookDir_t -{ - LOOK_DOWN_X = 0, - LOOK_DOWN_NEGX, - LOOK_DOWN_Y, - LOOK_DOWN_NEGY, - LOOK_DOWN_Z, - LOOK_DOWN_NEGZ, -}; - - -//----------------------------------------------------------------------------- -// Use this image format if you want to perform tool operations on the texture -//----------------------------------------------------------------------------- -#define IMAGE_FORMAT_DEFAULT ((ImageFormat)-2) - -//----------------------------------------------------------------------------- -// Interface to get at various bits of a VTF texture -//----------------------------------------------------------------------------- -class IVTFTexture -{ -public: - // Initializes the texture and allocates space for the bits - // In most cases, you shouldn't force the mip count. - virtual bool Init( int nWidth, int nHeight, int nDepth, ImageFormat fmt, int nFlags, int iFrameCount, int nForceMipCount = -1 ) = 0; - - // Methods to set other texture fields - virtual void SetBumpScale( float flScale ) = 0; - virtual void SetReflectivity( const Vector &vecReflectivity ) = 0; - - // Methods to initialize the low-res image - virtual void InitLowResImage( int nWidth, int nHeight, ImageFormat fmt ) = 0; - - // set the resource data (for writers). pass size=0 to delete data. if pdata is not null, - // the resource data will be copied from *pData - virtual void *SetResourceData( uint32 eType, void const *pData, size_t nDataSize ) = 0; - - // find the resource data and return a pointer to it. The data pointed to by this pointer will - // go away when the ivtftexture does. retruns null if resource not present - virtual void *GetResourceData( uint32 eType, size_t *pDataSize ) const = 0; - - // Locates the resource entry info if it's present, easier than crawling array types - virtual bool HasResourceEntry( uint32 eType ) const = 0; - - // Retrieve available resource types of this IVTFTextures - // arrTypesBuffer buffer to be filled with resource types available. - // numTypesBufferElems how many resource types the buffer can accomodate. - // Returns: - // number of resource types available (can be greater than "numTypesBufferElems" - // in which case only first "numTypesBufferElems" are copied to "arrTypesBuffer") - virtual unsigned int GetResourceTypes( uint32 *arrTypesBuffer, int numTypesBufferElems ) const = 0; - - // When unserializing, we can skip a certain number of mip levels, - // and we also can just load everything but the image data - // NOTE: If you load only the buffer header, you'll need to use the - // VTFBufferHeaderSize() method below to only read that much from the file - // NOTE: If you skip mip levels, the height + width of the texture will - // change to reflect the size of the largest read in mip level - virtual bool Unserialize( CUtlBuffer &buf, bool bHeaderOnly = false, int nSkipMipLevels = 0 ) = 0; - virtual bool Serialize( CUtlBuffer &buf ) = 0; - - // These are methods to help with optimization: - // Once the header is read in, they indicate where to start reading - // other data (measured from file start), and how many bytes to read.... - virtual void LowResFileInfo( int *pStartLocation, int *pSizeInBytes) const = 0; - virtual void ImageFileInfo( int nFrame, int nFace, int nMip, int *pStartLocation, int *pSizeInBytes) const = 0; - virtual int FileSize( int nMipSkipCount = 0 ) const = 0; - - // Attributes... - virtual int Width() const = 0; - virtual int Height() const = 0; - virtual int Depth() const = 0; - virtual int MipCount() const = 0; - - // returns the size of one row of a particular mip level - virtual int RowSizeInBytes( int nMipLevel ) const = 0; - - // returns the size of one face of a particular mip level - virtual int FaceSizeInBytes( int nMipLevel ) const = 0; - - virtual ImageFormat Format() const = 0; - virtual int FaceCount() const = 0; - virtual int FrameCount() const = 0; - virtual int Flags() const = 0; - - virtual float BumpScale() const = 0; - - virtual int LowResWidth() const = 0; - virtual int LowResHeight() const = 0; - virtual ImageFormat LowResFormat() const = 0; - - // NOTE: reflectivity[0] = blue, [1] = greem, [2] = red - virtual const Vector &Reflectivity() const = 0; - - virtual bool IsCubeMap() const = 0; - virtual bool IsNormalMap() const = 0; - virtual bool IsVolumeTexture() const = 0; - - // Computes the dimensions of a particular mip level - virtual void ComputeMipLevelDimensions( int iMipLevel, int *pMipWidth, int *pMipHeight, int *pMipDepth ) const = 0; - - // Computes the size (in bytes) of a single mipmap of a single face of a single frame - virtual int ComputeMipSize( int iMipLevel ) const = 0; - - // Computes the size of a subrect (specified at the top mip level) at a particular lower mip level - virtual void ComputeMipLevelSubRect( Rect_t* pSrcRect, int nMipLevel, Rect_t *pSubRect ) const = 0; - - // Computes the size (in bytes) of a single face of a single frame - // All mip levels starting at the specified mip level are included - virtual int ComputeFaceSize( int iStartingMipLevel = 0 ) const = 0; - - // Computes the total size (in bytes) of all faces, all frames - virtual int ComputeTotalSize() const = 0; - - // Returns the base address of the image data - virtual unsigned char *ImageData() = 0; - - // Returns a pointer to the data associated with a particular frame, face, and mip level - virtual unsigned char *ImageData( int iFrame, int iFace, int iMipLevel ) = 0; - - // Returns a pointer to the data associated with a particular frame, face, mip level, and offset - virtual unsigned char *ImageData( int iFrame, int iFace, int iMipLevel, int x, int y, int z = 0 ) = 0; - - // Returns the base address of the low-res image data - virtual unsigned char *LowResImageData() = 0; - - // Converts the textures image format. Use IMAGE_FORMAT_DEFAULT - // if you want to be able to use various tool functions below - virtual void ConvertImageFormat( ImageFormat fmt, bool bNormalToDUDV ) = 0; - - // NOTE: The following methods only work on textures using the - // IMAGE_FORMAT_DEFAULT! - - // Generate spheremap based on the current cube faces (only works for cubemaps) - // The look dir indicates the direction of the center of the sphere - // NOTE: Only call this *after* cube faces have been correctly - // oriented (using FixCubemapFaceOrientation) - virtual void GenerateSpheremap( LookDir_t lookDir = LOOK_DOWN_Z ) = 0; - - // Generate spheremap based on the current cube faces (only works for cubemaps) - // The look dir indicates the direction of the center of the sphere - // NOTE: Only call this *after* cube faces have been correctly - // oriented (using FixCubemapFaceOrientation) - virtual void GenerateHemisphereMap( unsigned char *pSphereMapBitsRGBA, int targetWidth, - int targetHeight, LookDir_t lookDir, int iFrame ) = 0; - - // Fixes the cubemap faces orientation from our standard to the - // standard the material system needs. - virtual void FixCubemapFaceOrientation( ) = 0; - - // Generates mipmaps from the base mip levels - virtual void GenerateMipmaps() = 0; - - // Put 1/miplevel (1..n) into alpha. - virtual void PutOneOverMipLevelInAlpha() = 0; - - // Computes the reflectivity - virtual void ComputeReflectivity( ) = 0; - - // Computes the alpha flags - virtual void ComputeAlphaFlags() = 0; - - // Generate the low-res image bits - virtual bool ConstructLowResImage() = 0; - - // Gets the texture all internally consistent assuming you've loaded - // mip 0 of all faces of all frames - virtual void PostProcess(bool bGenerateSpheremap, LookDir_t lookDir = LOOK_DOWN_Z, bool bAllowFixCubemapOrientation = true) = 0; - - // Blends adjacent pixels on cubemap borders, since the card doesn't do it. If the texture - // is S3TC compressed, then it has to do it AFTER the texture has been compressed to prevent - // artifacts along the edges. - // - // If bSkybox is true, it assumes the faces are oriented in the way the engine draws the skybox - // (which happens to be different from the way cubemaps have their faces). - virtual void MatchCubeMapBorders( int iStage, ImageFormat finalFormat, bool bSkybox ) = 0; - - // Sets threshhold values for alphatest mipmapping - virtual void SetAlphaTestThreshholds( float flBase, float flHighFreq ) = 0; - -#if defined( _X360 ) - virtual int UpdateOrCreate( const char *pFilename, const char *pPathID = NULL, bool bForce = false ) = 0; - virtual bool UnserializeFromBuffer( CUtlBuffer &buf, bool bBufferIsVolatile, bool bHeaderOnly, bool bPreloadOnly, int nMipSkipCount ) = 0; - virtual int FileSize( bool bPreloadOnly, int nMipSkipCount ) const = 0; - virtual int MappingWidth() const = 0; - virtual int MappingHeight() const = 0; - virtual int MappingDepth() const = 0; - virtual int MipSkipCount() const = 0; - virtual bool IsPreTiled() const = 0; - virtual unsigned char *LowResImageSample() = 0; - virtual void ReleaseImageMemory() = 0; -#endif - - // Sets post-processing flags (settings are copied, pointer passed to distinguish between structure versions) - virtual void SetPostProcessingSettings( VtfProcessingOptions const *pOptions ) = 0; -}; - -//----------------------------------------------------------------------------- -// Class factory -//----------------------------------------------------------------------------- -IVTFTexture *CreateVTFTexture(); -void DestroyVTFTexture( IVTFTexture *pTexture ); - -//----------------------------------------------------------------------------- -// Allows us to only load in the first little bit of the VTF file to get info -// Clients should read this much into a UtlBuffer and then pass it in to -// Unserialize -//----------------------------------------------------------------------------- -int VTFFileHeaderSize( int nMajorVersion = -1, int nMinorVersion = -1 ); - -//----------------------------------------------------------------------------- -// 360 Conversion -//----------------------------------------------------------------------------- -typedef bool (*CompressFunc_t)( CUtlBuffer &inputBuffer, CUtlBuffer &outputBuffer ); -bool ConvertVTFTo360Format( const char *pDebugName, CUtlBuffer &sourceBuf, CUtlBuffer &targetBuf, CompressFunc_t pCompressFunc ); - -//----------------------------------------------------------------------------- -// 360 Preload -//----------------------------------------------------------------------------- -bool GetVTFPreload360Data( const char *pDebugName, CUtlBuffer &fileBufferIn, CUtlBuffer &preloadBufferOut ); - -#include "mathlib/vector.h" - -#endif // VTF_FILE_FORMAT_ONLY - -//----------------------------------------------------------------------------- -// Disk format for VTF files ver. 7.2 and earlier -// -// NOTE: After the header is the low-res image data -// Then follows image data, which is sorted in the following manner -// -// for each mip level (starting with 1x1, and getting larger) -// for each animation frame -// for each face -// store the image data for the face -// -// NOTE: In memory, we store the data in the following manner: -// for each animation frame -// for each face -// for each mip level (starting with the largest, and getting smaller) -// store the image data for the face -// -// This is done because the various image manipulation function we have -// expect this format -//----------------------------------------------------------------------------- -// Disk format for VTF files ver. 7.3 -// -// NOTE: After the header is the array of ResourceEntryInfo structures, -// number of elements in the array is defined by "numResources". -// there are entries for: -// eRsrcLowResImage = low-res image data -// eRsrcSheet = sheet data -// eRsrcImage = image data -// { -// for each mip level (starting with 1x1, and getting larger) -// for each animation frame -// for each face -// store the image data for the face -// -// NOTE: In memory, we store the data in the following manner: -// for each animation frame -// for each face -// for each mip level (starting with the largest, and getting smaller) -// store the image data for the face -// } -// -//----------------------------------------------------------------------------- - - -#include "datamap.h" - -#pragma pack(1) - -// version number for the disk texture cache -#define VTF_MAJOR_VERSION 7 -#define VTF_MINOR_VERSION 4 - -//----------------------------------------------------------------------------- -// !!!!CRITICAL!!!! BEFORE YOU CHANGE THE FORMAT -// -// The structure sizes ARE NOT what they appear, regardless of Pack(1). -// The "VectorAligned" causes invisible padding in the FINAL derived structure. -// -// Each VTF format has been silently plagued by this. -// -// LOOK AT A 7.3 FILE. The 7.3 structure ends at 0x48 as you would expect by -// counting structure bytes. But, the "Infos" start at 0x50! because the PC -// compiler pads, the 360 compiler does NOT. -//----------------------------------------------------------------------------- - -struct VTFFileBaseHeader_t -{ - DECLARE_BYTESWAP_DATADESC(); - char fileTypeString[4]; // "VTF" Valve texture file - int version[2]; // version[0].version[1] - int headerSize; -}; - -struct VTFFileHeaderV7_1_t : public VTFFileBaseHeader_t -{ - DECLARE_BYTESWAP_DATADESC(); - unsigned short width; - unsigned short height; - unsigned int flags; - unsigned short numFrames; - unsigned short startFrame; -#if !defined( _X360 ) - VectorAligned reflectivity; -#else - // must manually align in order to maintain pack(1) expected layout with existing binaries - char pad1[4]; - Vector reflectivity; - char pad2[4]; -#endif - float bumpScale; - ImageFormat imageFormat; - unsigned char numMipLevels; - ImageFormat lowResImageFormat; - unsigned char lowResImageWidth; - unsigned char lowResImageHeight; -}; - -struct VTFFileHeaderV7_2_t : public VTFFileHeaderV7_1_t -{ - DECLARE_BYTESWAP_DATADESC(); - - unsigned short depth; -}; - -#define BYTE_POS( byteVal, shft ) uint32( uint32(uint8(byteVal)) << uint8(shft * 8) ) -#if !defined( _X360 ) -#define MK_VTF_RSRC_ID(a, b, c) uint32( BYTE_POS(a, 0) | BYTE_POS(b, 1) | BYTE_POS(c, 2) ) -#define MK_VTF_RSRCF(d) BYTE_POS(d, 3) -#else -#define MK_VTF_RSRC_ID(a, b, c) uint32( BYTE_POS(a, 3) | BYTE_POS(b, 2) | BYTE_POS(c, 1) ) -#define MK_VTF_RSRCF(d) BYTE_POS(d, 0) -#endif - -// Special section for stock resources types -enum ResourceEntryType -{ - // Legacy stock resources, readin/writing are handled differently (i.e. they do not have the length tag word!) - VTF_LEGACY_RSRC_LOW_RES_IMAGE = MK_VTF_RSRC_ID( 0x01, 0, 0 ), // Low-res image data - VTF_LEGACY_RSRC_IMAGE = MK_VTF_RSRC_ID( 0x30, 0, 0 ), // Image data - - // New extended resource - VTF_RSRC_SHEET = MK_VTF_RSRC_ID( 0x10, 0, 0 ), // Sheet data -}; - -// Bytes with special meaning when set in a resource type -enum ResourceEntryTypeFlag -{ - RSRCF_HAS_NO_DATA_CHUNK = MK_VTF_RSRCF( 0x02 ), // Resource doesn't have a corresponding data chunk - RSRCF_MASK = MK_VTF_RSRCF( 0xFF ) // Mask for all the flags -}; - -// Header details constants -enum HeaderDetails -{ - MAX_RSRC_DICTIONARY_ENTRIES = 32, // Max number of resources in dictionary - MAX_X360_RSRC_DICTIONARY_ENTRIES = 4, // 360 needs this to be slim, otherwise preload size suffers -}; - -struct ResourceEntryInfo -{ - union - { - unsigned int eType; // Use MK_VTF_??? macros to be endian compliant with the type - unsigned char chTypeBytes[4]; - }; - unsigned int resData; // Resource data or offset from the beginning of the file -}; - -struct VTFFileHeaderV7_3_t : public VTFFileHeaderV7_2_t -{ - DECLARE_BYTESWAP_DATADESC(); - - char pad4[3]; - unsigned int numResources; - -#if defined( _X360 ) - // must manually align in order to maintain pack(1) expected layout with existing binaries - char pad5[8]; -#endif - - // AFTER THE IMPLICIT PADDING CAUSED BY THE COMPILER.... - // *** followed by *** ResourceEntryInfo resources[0]; - // Array of resource entry infos sorted ascending by type -}; - -struct VTFFileHeader_t : public VTFFileHeaderV7_3_t -{ - DECLARE_BYTESWAP_DATADESC(); -}; - -#define VTF_X360_MAJOR_VERSION 0x0360 -#define VTF_X360_MINOR_VERSION 8 -struct VTFFileHeaderX360_t : public VTFFileBaseHeader_t -{ - DECLARE_BYTESWAP_DATADESC(); - unsigned int flags; - unsigned short width; // actual width of data in file - unsigned short height; // actual height of data in file - unsigned short depth; // actual depth of data in file - unsigned short numFrames; - unsigned short preloadDataSize; // exact size of preload data (may extend into image!) - unsigned char mipSkipCount; // used to resconstruct mapping dimensions - unsigned char numResources; - Vector reflectivity; // Resides on 16 byte boundary! - float bumpScale; - ImageFormat imageFormat; - unsigned char lowResImageSample[4]; - unsigned int compressedSize; - - // *** followed by *** ResourceEntryInfo resources[0]; -}; - -/////////////////////////// -// Resource Extensions // -/////////////////////////// - -// extended texture lod control: -#define VTF_RSRC_TEXTURE_LOD_SETTINGS ( MK_VTF_RSRC_ID( 'L','O','D' ) ) -struct TextureLODControlSettings_t -{ - // What to clamp the dimenstions to, mip-map wise, when at picmip 0. keeps texture from - // exceeding (1< -#pragma warning(pop) -#endif -#undef PostMessage - -#pragma warning( disable: 4800 ) // forcing value to bool 'true' or 'false' (performance warning) - -#endif // WINLITE_H diff --git a/public/worldsize.h b/public/worldsize.h deleted file mode 100644 index 4f9bba0c8..000000000 --- a/public/worldsize.h +++ /dev/null @@ -1,42 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -// $NoKeywords: $ -// -//=============================================================================// -// worldsize.h -- extent of world and resolution/size of coordinate messages used in engine - -#ifndef WORLDSIZE_H -#define WORLDSIZE_H -#pragma once - - -// These definitions must match the coordinate message sizes in coordsize.h - -// Following values should be +16384, -16384, +15/16, -15/16 -// NOTE THAT IF THIS GOES ANY BIGGER THEN DISK NODES/LEAVES CANNOT USE SHORTS TO STORE THE BOUNDS -#define MAX_COORD_INTEGER (16384) -#define MIN_COORD_INTEGER (-MAX_COORD_INTEGER) -#define MAX_COORD_FRACTION (1.0-(1.0/16.0)) -#define MIN_COORD_FRACTION (-1.0+(1.0/16.0)) - -#define MAX_COORD_FLOAT (16384.0f) -#define MIN_COORD_FLOAT (-MAX_COORD_FLOAT) - -// Width of the coord system, which is TOO BIG to send as a client/server coordinate value -#define COORD_EXTENT (2*MAX_COORD_INTEGER) - -// Maximum traceable distance ( assumes cubic world and trace from one corner to opposite ) -// COORD_EXTENT * sqrt(3) -#define MAX_TRACE_LENGTH ( 1.732050807569 * COORD_EXTENT ) - -// This value is the LONGEST possible range (limited by max valid coordinate number, not 2x) -#define MAX_COORD_RANGE (MAX_COORD_INTEGER) - -#define ASSERT_COORD( v ) Assert( (v.x>=MIN_COORD_INTEGER*2) && (v.x<=MAX_COORD_INTEGER*2) && \ - (v.y>=MIN_COORD_INTEGER*2) && (v.y<=MAX_COORD_INTEGER*2) && \ - (v.z>=MIN_COORD_INTEGER*2) && (v.z<=MAX_COORD_INTEGER*2) ); \ - - -#endif // WORLDSIZE_H diff --git a/public/xwvfile.h b/public/xwvfile.h deleted file mode 100644 index f5d139ebd..000000000 --- a/public/xwvfile.h +++ /dev/null @@ -1,85 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#ifndef XWVFILE_H -#define XWVFILE_H -#ifdef _WIN32 -#pragma once -#endif - -#pragma pack(1) - -#define XWV_ID (('X'<<24)|('W'<<16)|('V'<<8)|(' '<<0)) -#define XWV_VERSION 4 - -enum xwvSampleRate_t -{ - XWV_RATE_11025 = 0, - XWV_RATE_22050 = 1, - XWV_RATE_44100 = 2, -}; - -enum xwvFormat_t -{ - XWV_FORMAT_PCM = 0, - XWV_FORMAT_XMA = 1, - XWV_FORMAT_ADPCM = 2, -}; - -// generated in big-endian -struct xwvHeader_t -{ - unsigned int id; - unsigned int version; - unsigned int headerSize; // header only - unsigned int staticDataSize; // follows header - unsigned int dataOffset; // start of samples, possibly sector aligned - unsigned int dataSize; // length of samples in bytes - unsigned int numDecodedSamples; // for duration calcs - int loopStart; // -1 = no loop, offset of loop in samples - unsigned short loopBlock; // the xma block where the loop starts - unsigned short numLeadingSamples; // number of leading samples in the loop block to discard - unsigned short numTrailingSamples; // number of trailing samples at the final block to discard - unsigned short vdatSize; // follows seek table - byte format; - byte bitsPerSample; - byte sampleRate; - byte channels; - byte quality; - byte bHasSeekTable; // indicates presence, follows header - byte padding[2]; // created as 0 - - inline unsigned int GetPreloadSize() { return headerSize + staticDataSize; } - - inline int GetBitsPerSample() const { return bitsPerSample; } - - int GetSampleRate() const - { - int rates[] = {11025, 22050, 44100}; - int rate = sampleRate; - return rates[rate]; - } - - inline int GetChannels() const { return channels; } - - void SetSampleRate( int sampleRateIn ) - { - byte rate = ( sampleRateIn == 11025 ) ? XWV_RATE_11025 : ( sampleRateIn==22050 )? XWV_RATE_22050 : XWV_RATE_44100; - sampleRate = rate; - } - - inline void SetChannels( int channelsIn ) { channels = channelsIn; } - - inline int GetSeekTableSize() - { - // seek table is indexed by packets - return bHasSeekTable ? ( dataSize / 2048 ) * sizeof( int ) : 0; - } -}; - -#pragma pack() - -#endif // XWVFILE_H diff --git a/public/xzp.cpp b/public/xzp.cpp deleted file mode 100644 index 461bcc6a1..000000000 --- a/public/xzp.cpp +++ /dev/null @@ -1,1323 +0,0 @@ -//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= -// -// Purpose: -// -//============================================================================= - -#include -#include -#include -#include -#include -#ifdef _WIN32 -#include -#include -#endif -#include -#include -#include -#include -#include "UtlBuffer.h" -#include "tier1/strtools.h" -#include "tier2/riff.h" - -#if defined( _WIN32 ) && !defined( _X360 ) -#include -#endif - -#ifdef MAKE_GAMEDATA_TOOL - #include "../public/materialsystem/shader_vcs_version.h" - #include "../public/materialsystem/imaterial.h" - #include "../public/materialsystem/hardwareverts.h" - #include "../public/vtf/vtf.h" -#else - #include "materialsystem/shader_vcs_version.h" - #include "materialsystem/imaterial.h" - #include "materialsystem/hardwareverts.h" -#endif - -#include "xwvfile.h" -#include "xzp.h" - -CByteswap g_xzpSwap; -extern IFileReadBinary *g_pSndIO; - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -//----------------------------------------------------------------------------- -// Datadesc blocks for byteswapping: -//----------------------------------------------------------------------------- -BEGIN_BYTESWAP_DATADESC( xZipHeader_t ) - DEFINE_FIELD( Magic, FIELD_INTEGER ), - DEFINE_FIELD( Version, FIELD_INTEGER ), - DEFINE_FIELD( PreloadDirectoryEntries, FIELD_INTEGER ), - DEFINE_FIELD( DirectoryEntries, FIELD_INTEGER ), - DEFINE_FIELD( PreloadBytes, FIELD_INTEGER ), - DEFINE_FIELD( HeaderLength, FIELD_INTEGER ), - DEFINE_FIELD( FilenameEntries, FIELD_INTEGER ), - DEFINE_FIELD( FilenameStringsOffset, FIELD_INTEGER ), - DEFINE_FIELD( FilenameStringsLength, FIELD_INTEGER ), -END_BYTESWAP_DATADESC() - -BEGIN_BYTESWAP_DATADESC( xZipDirectoryEntry_t ) - DEFINE_FIELD( FilenameCRC, FIELD_INTEGER ), - DEFINE_FIELD( Length, FIELD_INTEGER ), - DEFINE_FIELD( StoredOffset, FIELD_INTEGER ), -END_BYTESWAP_DATADESC() - -BEGIN_BYTESWAP_DATADESC( xZipFilenameEntry_t ) - DEFINE_FIELD( FilenameCRC, FIELD_INTEGER ), - DEFINE_FIELD( FilenameOffset, FIELD_INTEGER ), - DEFINE_FIELD( TimeStamp, FIELD_INTEGER ), -END_BYTESWAP_DATADESC() - -BEGIN_BYTESWAP_DATADESC( xZipFooter_t ) - DEFINE_FIELD( Size, FIELD_INTEGER ), - DEFINE_FIELD( Magic, FIELD_INTEGER ), -END_BYTESWAP_DATADESC() - -CXZip::CXZip() -{ - // Ensure that the header doesn't contain a valid magic yet. - m_Header.Magic = 0; - m_pPreloadedData = NULL; - m_nPreloadStart = 0; - m_pDirectory = NULL; - m_pPreloadDirectory = NULL; - m_nRegular2PreloadEntryMapping = NULL; - - m_bByteSwapped = false; - - m_pFilenames = NULL; - m_hZip = NULL; - - m_pRead = NULL; - m_hUser = 0; - m_nMonitorLevel = 0; -} - -CXZip::CXZip( const char* filename ) -{ - // Ensure that the header doesn't contain a valid magic yet. - m_Header.Magic = 0; - m_nPreloadStart = 0; - m_pPreloadedData = NULL; - m_pDirectory = NULL; - m_pPreloadDirectory = NULL; - m_nRegular2PreloadEntryMapping = NULL; - - m_bByteSwapped = false; - - m_pFilenames = NULL; - m_hZip = NULL; - - m_pRead = NULL; - m_hUser = 0; - m_nMonitorLevel = 0; - - Load( filename ); -} - -CXZip::CXZip( FILE* handle, int offset, int size ) // file handle and offset of the zip file -{ - m_pRead = NULL; - m_hUser = 0; - m_nPreloadStart = 0; - m_pDirectory = NULL; - m_pPreloadDirectory = NULL; - m_nRegular2PreloadEntryMapping = NULL; - - m_bByteSwapped = false; - - m_pFilenames = NULL; - m_pPreloadedData = NULL; - m_nMonitorLevel = 0; - - Load( handle, offset, size ); -} - -CXZip::~CXZip() -{ - Unload(); -} - -bool CXZip::InstallAlternateIO( int (*read)( void* buffer, int offset, int length, int nDestLength, int hUser), int hUser ) -{ - m_pRead = read; - m_hUser = hUser; - return true; -} - - -// Loads an xZip file into memory: -bool CXZip::Load( const char* filename, bool bPreload ) -{ - FILE* hZip = fopen( filename, "rb" ); - fseek(hZip,0,SEEK_END); - int nSize = ftell( hZip ); - return Load( hZip, 0, nSize, bPreload ); -} - -bool CXZip::Load( FILE* handle, int nOffset, int nSize, bool bPreload ) // Load a pack file into this instance. Returns true on success. -{ - Unload(); - - m_bByteSwapped = false; - - m_hZip = handle; - m_nOffset = nOffset; - m_nSize = nSize; - - // Hacky, clean up: - if( m_hZip && !m_pRead ) - { - InstallAlternateIO( defaultRead, (int)m_hZip ); - } - - if( m_hZip == NULL && m_pRead == NULL ) - { - return false; - } - - // Read the header: - m_pRead( &m_Header, 0, -1, sizeof(m_Header), m_hUser ); - - // Validate the Magic number and at the same time determine if I am reading a regular or swappped xZip file: - switch( m_Swap.SourceIsNativeEndian( m_Header.Magic, xZipHeader_t::MAGIC ) ) - { - // Does the magic match exactly? - case 1: - m_Swap.ActivateByteSwapping( false ); - m_bByteSwapped = false; - break; - - // Does the magic match, but is swapped? - case 0: - m_bByteSwapped = true; - m_Swap.ActivateByteSwapping( true ); // We must be reading the opposite endianness. - m_Swap.SwapFieldsToTargetEndian( &m_Header ); - break; - - default: - assert( 0 ); - // Fail gently in release: - - // The magic doesn't match in any respect: - case -1: - { - printf("Invalid xZip file\n"); - - if( m_hZip ) - { - fclose( m_hZip ); - m_hZip = NULL; - } - return false; - } - } - - // Validate the archive version: - if( m_Header.Version != xZipHeader_t::VERSION ) - { - // Backward compatable support for version 1 - Msg("Incorrect xZip version found %u - expected %u\n", m_Header.Version, xZipHeader_t::VERSION ); - if( m_hZip ) - { - fclose( m_hZip ); - m_hZip = NULL; - } - - m_Header.Magic = xZipHeader_t::FREE; - return false; - } - - // Read the directory: - { - MEM_ALLOC_CREDIT(); - - m_pDirectory = (xZipDirectoryEntry_t*)malloc( sizeof(xZipDirectoryEntry_t) * m_Header.DirectoryEntries ); - m_pRead( m_pDirectory, m_Header.HeaderLength, -1, sizeof( xZipDirectoryEntry_t ) * m_Header.DirectoryEntries, m_hUser ); - - // Swap the directory entries if nessecary - if( m_bByteSwapped ) - { - for( unsigned nDirectoryEntry = 0; nDirectoryEntry < m_Header.DirectoryEntries; nDirectoryEntry++ ) - { - m_Swap.SwapFieldsToTargetEndian( &( m_pDirectory[nDirectoryEntry] ) ); - } - } - - - m_nPreloadStart = m_Header.HeaderLength + ( sizeof( xZipDirectoryEntry_t ) * m_Header.DirectoryEntries ); - } - - // Preload the preload chunk if desired: - if( bPreload ) - { - PreloadData(); - } - - return true; -} - -void CXZip::Unload() -{ - DiscardPreloadedData(); - - // Dump the directory: - if( m_pDirectory ) - { - free( m_pDirectory ); - m_pDirectory = NULL; - } - - if( m_pFilenames ) - { - free( m_pFilenames ); - m_pFilenames = NULL; - } - - // Invalidate the header: - m_Header.Magic = 0; - - if( m_hZip ) - { - fclose( m_hZip ); - m_hZip = NULL; - } - -} - -//----------------------------------------------------------------------------- -// CXZip::PreloadData -// -// Loads the preloaded data if it isn't already. -//----------------------------------------------------------------------------- - -void CXZip::PreloadData() -{ - Assert( IsValid() ); - - // Ensure it isn't already preloaded - if( m_pPreloadedData ) - return; - - // If I don't have a preloaded section, ignore the request. - if( !m_Header.PreloadBytes || !m_Header.PreloadDirectoryEntries ) - return; - - // Allocate and read the data block in: -#ifndef _X360 - MEM_ALLOC_CREDIT_( "xZip" ); - m_pPreloadedData = malloc( m_Header.PreloadBytes ); - - // Just drop out if allocation fails; - if ( !m_pPreloadedData ) - return; - - m_pRead( m_pPreloadedData, m_nPreloadStart, -1, m_Header.PreloadBytes, m_hUser ); -#else - int nAlignedStart = AlignValue( ( m_nPreloadStart - XBOX_HDD_SECTORSIZE ) + 1, XBOX_HDD_SECTORSIZE ); - int nBytesToRead = AlignValue( ( m_nPreloadStart - nAlignedStart ) + m_Header.PreloadBytes, XBOX_HDD_SECTORSIZE ); - int nBytesBuffer = AlignValue( nBytesToRead, XBOX_HDD_SECTORSIZE ); - byte *pReadData = (byte *)malloc( nBytesBuffer ); - - // Just drop out if allocation fails; - if ( !pReadData ) - return; - - MEM_ALLOC_CREDIT_( "xZip" ); - m_pRead( pReadData, nAlignedStart, nBytesBuffer,nBytesToRead, m_hUser ); - m_pPreloadedData = pReadData + ( m_nPreloadStart - nAlignedStart ); -#endif - - // Set up the preload directory: - m_pPreloadDirectory = (xZipDirectoryEntry_t*)m_pPreloadedData; - - // Swap the preload directory: - if ( m_bByteSwapped ) - { - for ( unsigned nDirectoryEntry = 0; nDirectoryEntry < m_Header.PreloadDirectoryEntries; nDirectoryEntry++ ) - { - m_Swap.SwapFieldsToTargetEndian( &( m_pPreloadDirectory[nDirectoryEntry] ) ); - } - } - - // Set up the regular 2 preload mapping section: - m_nRegular2PreloadEntryMapping = (unsigned short*)(((unsigned char*)m_pPreloadDirectory) + ( sizeof(xZipDirectoryEntry_t) * m_Header.PreloadDirectoryEntries )); - - // Swap the regular to preload mapping - if ( m_bByteSwapped ) - { - m_Swap.SwapBufferToTargetEndian( (short *)m_nRegular2PreloadEntryMapping, (short *)m_nRegular2PreloadEntryMapping, m_Header.DirectoryEntries ); - } - -} - -//----------------------------------------------------------------------------- -// CXZip::DiscardPreloadedData -// -// frees the preloaded data cache if it's present. -//----------------------------------------------------------------------------- - -void CXZip::DiscardPreloadedData() -{ - if ( m_pPreloadedData ) - { -#ifndef _X360 - free( m_pPreloadedData ); -#else - int nAlignedStart = AlignValue( ( m_nPreloadStart - XBOX_HDD_SECTORSIZE ) + 1, XBOX_HDD_SECTORSIZE ); - byte *pReadData = (byte *)m_pPreloadedData - ( m_nPreloadStart - nAlignedStart ); - free( pReadData ); -#endif - m_pPreloadedData = NULL; - m_pPreloadDirectory = NULL; - m_nRegular2PreloadEntryMapping = NULL; - } -} - -int CXZip::defaultRead( void* buffer, int offset, int destLength, int length, int hUser) -{ - fseek( (FILE*)hUser, offset, SEEK_SET ); - return fread( buffer, 1, length, (FILE*)hUser ); -} - -char* CXZip::GetEntryFileName( unsigned CRC, char* pDefault ) -{ - Assert( IsValid() ); - - if( IsRetail() ) - { - return pDefault; - } - else - { - - // Make sure I have a filename section: - if( m_Header.FilenameStringsOffset == 0 || m_Header.FilenameEntries == 0 || CRC == 0 ) - { - return pDefault; - } - - // If the filename chunk isn't here, load it up: - if( !m_pFilenames ) - { - MEM_ALLOC_CREDIT_("xZip"); - m_pFilenames = (xZipFilenameEntry_t*)malloc( m_Header.FilenameStringsLength ); - m_pRead( m_pFilenames, m_Header.FilenameStringsOffset, -1, m_Header.FilenameStringsLength, m_hUser ); - - // TODO: Swap! - for( unsigned int i=0; i< m_Header.FilenameEntries;i++ ) - { - m_Swap.SwapFieldsToTargetEndian(&m_pFilenames[i]); - } - } - - // Find this entry in the preload directory - xZipFilenameEntry_t entry; - entry.FilenameCRC = CRC; - - xZipFilenameEntry_t* found = (xZipFilenameEntry_t*)bsearch( &entry, m_pFilenames, m_Header.FilenameEntries, sizeof(xZipFilenameEntry_t), xZipFilenameEntry_t::xZipFilenameEntryCompare ); - - if( !found ) - return pDefault; - - return (((char*)m_pFilenames) + found->FilenameOffset) - m_Header.FilenameStringsOffset; - } -} - -// Sanity checks that the zip file is ready and readable: -bool CXZip::IsValid() -{ - if( m_Header.Magic != xZipHeader_t::MAGIC ) - return false; - - if( m_Header.Version > xZipHeader_t::VERSION ) - return false; - - if( !m_pDirectory ) - return false; - - return true; -} - -void CXZip::WarningDir() -{ - Assert( IsValid()); - - for( unsigned i = 0; i< m_Header.DirectoryEntries; i++ ) - { - Msg( GetEntryFileName( m_pDirectory[i].FilenameCRC ) ); - } -} - - -int CXZip::ReadIndex( int nEntryIndex, int nFileOffset, int nDestBytes, int nLength, void* pBuffer ) -{ - Assert( IsValid() ); - - if( nLength <=0 || nEntryIndex < 0 ) - return 0; - - // HACK HACK HACK - convert the pack file index to a local file index (ie, assuming the full file index is being passed in) - nFileOffset -= m_pDirectory[nEntryIndex].StoredOffset; - // HACK HACK HACK - - // If I've got my preload section loaded, first check there: - xZipDirectoryEntry_t* pPreloadEntry = GetPreloadEntry(nEntryIndex); - - if( pPreloadEntry ) - { - Assert( pPreloadEntry->FilenameCRC == m_pDirectory[nEntryIndex].FilenameCRC ); - - if( nFileOffset + nLength <= (int)pPreloadEntry->Length ) - { - if( m_nMonitorLevel >= 2 ) - { - char* filename = GetEntryFileName( m_pDirectory[nEntryIndex].FilenameCRC, "(!!! unknown !!!)" ); - - Msg("PACK(preload) %s: length:%i offset:%i",filename,nLength, nFileOffset); - - } - - memcpy( pBuffer, (char*)m_pPreloadedData + pPreloadEntry->StoredOffset + nFileOffset - m_nPreloadStart, nLength ); - return nLength; - } - } - - // Offset int the zip to start the read: - int ZipOffset = m_pDirectory[nEntryIndex].StoredOffset + nFileOffset; - int nBytesRead = m_pRead( pBuffer, ZipOffset, nDestBytes, nLength, m_hUser); - - if( m_nMonitorLevel ) - { - char* filename = GetEntryFileName( m_pDirectory[nEntryIndex].FilenameCRC, "(!!! unknown !!!)" ); - - unsigned preload = 0; - if( m_pPreloadedData && m_nRegular2PreloadEntryMapping[nEntryIndex] != 0xFFFF ) - { - // Find this entry in the preload directory - xZipDirectoryEntry_t* entry = &(m_pPreloadDirectory[m_nRegular2PreloadEntryMapping[nEntryIndex]]); - Assert(entry->FilenameCRC == m_pDirectory[nEntryIndex].FilenameCRC); - - preload = entry->Length; - } - - Msg("PACK %s: length:%i offset:%i (preload bytes:%i)",filename,nLength, nFileOffset, preload); - } - - return nBytesRead; -} - -bool CXZip::GetSimpleFileOffsetLength( const char* FileName, int& nBaseIndex, int &nFileOffset, int &nLength ) -{ - Assert( IsValid() ); - - xZipDirectoryEntry_t entry; - entry.FilenameCRC = xZipCRCFilename( FileName ); - - xZipDirectoryEntry_t* found = (xZipDirectoryEntry_t*)bsearch( &entry, m_pDirectory, m_Header.DirectoryEntries, sizeof(xZipDirectoryEntry_t), xZipDirectoryEntry_t::xZipDirectoryEntryFindCompare ); - - if( found == NULL ) - return false; - - nFileOffset = found[0].StoredOffset; - nLength = found[0].Length; - nBaseIndex = (((int)((char*)found - (char*)m_pDirectory))/sizeof(xZipDirectoryEntry_t)); - - return true; -} - -bool CXZip::ExtractFile( const char* FileName ) -{ - return false; -} - -// Compares to xZipDirectoryEntries. -// -// Sorts in the following order: -// FilenameCRC -// FileOffset -// Length -// StoredOffset -// -// The sort function may look overly complex, but it is actually useful for locating different pieces of -// the same file in a meaningful order. -// -int __cdecl xZipDirectoryEntry_t::xZipDirectoryEntrySortCompare( const void* left, const void* right ) -{ - xZipDirectoryEntry_t *l = (xZipDirectoryEntry_t*)left, - *r = (xZipDirectoryEntry_t*)right; - - if( l->FilenameCRC < r->FilenameCRC ) - { - return -1; - } - - else if( l->FilenameCRC > r->FilenameCRC ) - { - return 1; - } - - // else l->FileOffset == r->FileOffset - if( l->Length < r->Length ) - { - return -1; - } - else if( l->Length > r->Length ) - { - return 1; - } - - // else l->Length == r->Length - if( l->StoredOffset < r->StoredOffset ) - { - return -1; - } - else if( l->StoredOffset > r->StoredOffset ) - { - return 1; - } - - // else everything is identical: - return 0; - -} - -// Find an entry with matching CRC only -int __cdecl xZipDirectoryEntry_t::xZipDirectoryEntryFindCompare( const void* left, const void* right ) -{ - xZipDirectoryEntry_t *l = (xZipDirectoryEntry_t*)left, - *r = (xZipDirectoryEntry_t*)right; - - if( l->FilenameCRC < r->FilenameCRC ) - { - return -1; - } - - else if( l->FilenameCRC > r->FilenameCRC ) - { - return 1; - } - - return 0; - -} - -int __cdecl xZipFilenameEntry_t::xZipFilenameEntryCompare( const void* left, const void* right ) -{ - xZipFilenameEntry_t *l = (xZipFilenameEntry_t*)left, - *r = (xZipFilenameEntry_t*)right; - - if( l->FilenameCRC < r->FilenameCRC ) - { - return -1; - } - - else if( l->FilenameCRC > r->FilenameCRC ) - { - return 1; - } - - return 0; - -} - - -// CRC's an individual xZip filename: -unsigned xZipCRCFilename( const char* filename ) -{ - unsigned hash = 0xAAAAAAAA; // Alternating 1's and 0's - - for( ; *filename ; filename++ ) - { - char c = *filename; - - // Fix slashes - if( c == '/' ) - c = '\\'; - else - c = (char)tolower(c); - - hash = hash * 33 + c; - } - - return hash; -} - -#if defined( MAKE_GAMEDATA_TOOL ) - -// ------------ -xZipHeader_t Header; -xZipDirectoryEntry_t *pDirectoryEntries = NULL; -xZipDirectoryEntry_t *pPreloadDirectoryEntries = NULL; -xZipFilenameEntry_t *pFilenameEntries = NULL; -char *pFilenameData = NULL; -unsigned nFilenameDataLength = 0; - -unsigned InputFileBytes = 0; - -char* CleanFilename( char* filename ) -{ - // Trim leading white space: - while( isspace(*filename) ) - filename++; - - // Trim trailing white space: - while( isspace( filename[strlen(filename)-1] ) ) - { - filename[strlen(filename)-1] = '\0'; - } - - return filename; -} - - -bool CopyFileBytes( FILE* hDestination, FILE* hSource, unsigned nBytes ) -{ - char buffer[16384]; - - while( nBytes > 0 ) - { - int nBytesRead = fread( buffer, 1, nBytes > sizeof(buffer) ? sizeof(buffer) : nBytes, hSource ); - fwrite(buffer, 1, nBytesRead, hDestination ); - nBytes -= nBytesRead; - } - - return true; -} - -bool WriteFileBytes( FILE* hDestination, CUtlBuffer &source, unsigned nBytes ) -{ - unsigned int nBytesWritten = fwrite(source.Base(), 1, nBytes, hDestination ); - return (nBytesWritten == nBytes); -} - -void PadFileBytes(FILE* hFile, int nPreloadPadding ) -{ - if( nPreloadPadding < 0 || nPreloadPadding >= 512) - { - puts("Invalid padding"); - return; - } - - char padding[512]; - memset(padding,0,nPreloadPadding); - fwrite(padding,1,nPreloadPadding,hFile); -} - -void AddFilename( const char* filename ) -{ - unsigned CRCfilename = xZipCRCFilename( filename ); - - // If we already have this filename don't add it again: - for( int i = 0; i < (int)Header.FilenameEntries; i++ ) - { - if( pFilenameEntries[i].FilenameCRC == CRCfilename ) - { - return; - } - } - - Header.FilenameEntries++; - - // Add the file to the file string table: - pFilenameEntries = (xZipFilenameEntry_t*)realloc( pFilenameEntries, sizeof(xZipFilenameEntry_t) * Header.FilenameEntries ); - - int filenameLength = (int)strlen(filename) + 1; - pFilenameEntries[Header.FilenameEntries-1].FilenameCRC = CRCfilename; - pFilenameEntries[Header.FilenameEntries-1].FilenameOffset = nFilenameDataLength; - - // Grab the timestamp for the file: - struct stat buf; - if( stat( filename, &buf ) != -1 ) - { - pFilenameEntries[Header.FilenameEntries - 1].TimeStamp = buf.st_mtime; - } - else - { - pFilenameEntries[Header.FilenameEntries - 1].TimeStamp = 0; - } - - nFilenameDataLength += filenameLength; - pFilenameData = (char*)realloc(pFilenameData, nFilenameDataLength); - memcpy(pFilenameData + nFilenameDataLength - filenameLength, filename, filenameLength); -} - -FILE* hTempFilePreload; -FILE* hTempFileData; -FILE* hOutputFile; - -bool xZipAddFile( const char* filename, CUtlBuffer &fileBuff, bool bPrecacheEntireFile, bool bProcessPrecacheHeader, bool bProcessPrecacheHeaderOnly ) -{ - unsigned int fileSize = fileBuff.TellMaxPut(); - - // Track total input bytes for stats reasons - InputFileBytes += fileSize; - - unsigned customPreloadSize = 0; - - if( bPrecacheEntireFile ) - { - customPreloadSize = fileSize; - } - else if( bProcessPrecacheHeader ) - { - customPreloadSize = xZipComputeCustomPreloads( filename ); - } - else if( bProcessPrecacheHeaderOnly ) - { - customPreloadSize = xZipComputeCustomPreloads( filename ); - fileSize = MIN( fileSize, customPreloadSize ); - } - - unsigned CRC = xZipCRCFilename( filename ); - - // Does this file have a split header? - if( customPreloadSize > 0 ) - { - // Initialize the entry header: - xZipDirectoryEntry_t entry; - memset( &entry, 0, sizeof( entry ) ); - - entry.FilenameCRC = CRC; - entry.Length = customPreloadSize; - entry.StoredOffset = ftell(hTempFilePreload); - - // Add the directory entry to the preload table: - Header.PreloadDirectoryEntries++; - pPreloadDirectoryEntries = (xZipDirectoryEntry_t*)realloc( pPreloadDirectoryEntries, sizeof( xZipDirectoryEntry_t ) * Header.PreloadDirectoryEntries ); - memcpy( pPreloadDirectoryEntries + Header.PreloadDirectoryEntries - 1, &entry, sizeof( entry ) ); - - // Concatenate the data in the preload file: - fileBuff.SeekGet( CUtlBuffer::SEEK_HEAD, 0 ); - WriteFileBytes( hTempFilePreload, fileBuff, entry.Length ); - fileBuff.SeekGet( CUtlBuffer::SEEK_HEAD, 0 ); - - - // Add the filename entry: - AddFilename( filename ); - - // Spew it: - printf("+Preload: \"%s\": Length:%u\n", filename, entry.Length ); - } - - // Copy the file to the regular data region: - xZipDirectoryEntry_t entry; - memset(&entry,0,sizeof(entry)); - entry.FilenameCRC = CRC; - entry.Length = fileSize; - entry.StoredOffset = ftell(hTempFileData); - - // Add the directory entry to the table: - Header.DirectoryEntries++; - pDirectoryEntries = (xZipDirectoryEntry_t*)realloc( pDirectoryEntries, sizeof( xZipDirectoryEntry_t ) * Header.DirectoryEntries ); - memcpy( pDirectoryEntries + Header.DirectoryEntries - 1, &entry, sizeof( entry ) ); - - WriteFileBytes( hTempFileData, fileBuff, entry.Length ); - - // Align the data region to a 512 byte boundry: (has to be on last entry as well to ensure enough space to perform the final read, - // and initial alignment is taken careof by assembexzip) - int nPadding = ( XBOX_HDD_SECTORSIZE - ( ftell( hTempFileData ) % XBOX_HDD_SECTORSIZE) ) % XBOX_HDD_SECTORSIZE; - - PadFileBytes( hTempFileData, nPadding ); - - // Add the file to the file string table: - AddFilename( filename ); - - // Print a summary - printf("+File: \"%s\": Length:%u Padding:%i\n", filename, entry.Length, nPadding ); - - return true; -} - -bool xZipAddFile( const char* zipname, bool bPrecacheEntireFile, bool bProcessPrecacheHeader, bool bProcessPrecacheHeaderOnly ) -{ - // Clean up the filename: - char buffer[MAX_PATH]; - strcpy(buffer, zipname); - - // Fix slashes and convert it to lower case: - char *filename; - for( filename = buffer; *filename; filename++ ) - { - if( *filename == '/' ) - *filename = '\\'; - else - { - *filename = (char)tolower(*filename); - } - } - - // Skip leading white space: - for( filename = buffer; isspace(*filename); filename++ ) - ; - - // Obliterate trailing white space: - for(;;) - { - int len = (int)strlen( filename ); - if( len <= 0 ) - { - printf("!!!! BAD FILENAME: \"%s\"\n", filename ); - return false; - } - - if( isspace( filename[len-1] ) ) - filename[len-1]='\0'; - else - break; - } - - // Ensure we don't already have this file: - unsigned CRC = xZipCRCFilename( filename ); - - for( unsigned i=0; i < Header.DirectoryEntries; i++ ) - { - if( pDirectoryEntries[i].FilenameCRC == CRC ) - { - printf("!!!! NOT ADDING DUPLICATE FILENAME: \"%s\"\n", filename ); - return false; - } - } - - // Attempt to open the file: - FILE* hFile = fopen( filename, "rb" ); - if( !hFile ) - { - printf("!!!! FAILED TO OPEN FILE: \"%s\"\n", filename ); - return false; - } - - // Get the length of the file: - fseek(hFile,0,SEEK_END); - unsigned fileSize = ftell(hFile); - fseek(hFile,0,SEEK_SET); - - CUtlBuffer fileBuff; - fileBuff.EnsureCapacity( fileSize ); - fread( fileBuff.Base(), fileSize, 1, hFile ); - fclose( hFile ); - - fileBuff.SeekPut( CUtlBuffer::SEEK_HEAD, fileSize ); - - return xZipAddFile( zipname, fileBuff, bPrecacheEntireFile, bProcessPrecacheHeader, bProcessPrecacheHeaderOnly ); -} - -int xZipBegin( const char* fileNameXzip ) -{ - // Create and initialize the header: - memset( &Header, 0, sizeof(Header) ); // Zero out the header: - Header.Magic = xZipHeader_t::MAGIC; - Header.Version = xZipHeader_t::VERSION; - Header.HeaderLength = sizeof(Header); - - // Open the output file: - hOutputFile = fopen(fileNameXzip,"wb+"); - if( !hOutputFile ) - { - printf("Failed to open \"%s\" for writing.\n", fileNameXzip); - exit( EXIT_FAILURE); - } - - // Create a temporary file for storing the preloaded data: - hTempFilePreload = tmpfile(); - if( !hTempFilePreload ) - { - printf( "Error: failed to create temporary file\n" ); - return EXIT_FAILURE; - } - - // Create a temporary file for storing the non preloaded data - hTempFileData = tmpfile(); - if( !hTempFileData ) - { - printf( "Error: failed to create temporary file\n"); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} - -bool xZipEnd() -{ - int nPreloadDirectorySize = sizeof(xZipDirectoryEntry_t)*Header.PreloadDirectoryEntries; - int nRegular2PreloadSize = sizeof(unsigned short) * Header.DirectoryEntries; - - // Compute the size of the preloaded section: - if( Header.PreloadDirectoryEntries ) - { - fseek( hTempFilePreload, 0, SEEK_END ); - Header.PreloadBytes = ftell(hTempFilePreload) + nPreloadDirectorySize + nRegular2PreloadSize; // Raw# of bytes to preload - fseek( hTempFilePreload, 0, SEEK_SET ); - } - else - { - Header.PreloadBytes = 0; - } - - // Number of bytes preceeding the preloaded section: - int nPreloadOffset = sizeof( Header ) + ( sizeof( xZipDirectoryEntry_t ) * Header.DirectoryEntries ); - - // Number of bytes to pad between the end of the preload section and the start of the data section: - int nPadding = ( 512 - ( ( nPreloadOffset + Header.PreloadBytes ) % 512) ) %512; // Number of alignment bytes after the preload section - - // Offset past the preload section: - int nDataOffset = nPreloadOffset + Header.PreloadBytes + nPadding; - - // Write out the header: (will need to be rewritten at the end as well) - note: not even bothering to byteswap at this point - fwrite(&Header,sizeof(Header),1,hOutputFile); - - - // Fixup each of the directory entries to make them relative to the beginning of the file. - for( unsigned i=0; i< Header.DirectoryEntries;i++ ) - { - xZipDirectoryEntry_t* pDir = &(pDirectoryEntries[i]); - - // Adjust files in the regular data area: - pDir->StoredOffset = nDataOffset + pDir->StoredOffset; - } - - // Sort and write the directory: - printf("Sorting and writing %i directory entries...\n",Header.DirectoryEntries); - qsort(pDirectoryEntries,Header.DirectoryEntries,sizeof(xZipDirectoryEntry_t),&xZipDirectoryEntry_t::xZipDirectoryEntrySortCompare); - - // Swap the directory entries: - for( unsigned i=0; i < Header.DirectoryEntries; i++ ) - { - g_xzpSwap.SwapFieldsToTargetEndian(&pDirectoryEntries[i]); - } - - fwrite(pDirectoryEntries,Header.DirectoryEntries*sizeof(xZipDirectoryEntry_t),1, hOutputFile); - - // Swap the directory back for later use: - for( unsigned i=0; i < Header.DirectoryEntries; i++ ) - { - g_xzpSwap.SwapFieldsToTargetEndian(&pDirectoryEntries[i]); - } - - // Copy the preload section: - if( Header.PreloadBytes > 0 ) - { - printf("Generating the preload section...(%u)\n", Header.PreloadBytes); - - - // Fixup each of the directory entries to make them relative to the beginning of the file. - for( unsigned i=0; i< Header.PreloadDirectoryEntries;i++ ) - { - xZipDirectoryEntry_t* pDir = &(pPreloadDirectoryEntries[i]); - - // Shift preload data down by preload bytes (and skipping over the directory): - pDir->StoredOffset += nPreloadOffset + nPreloadDirectorySize + nRegular2PreloadSize; - } - - printf("Sorting %u preload directory entries...\n",Header.PreloadDirectoryEntries); - qsort(pPreloadDirectoryEntries,Header.PreloadDirectoryEntries,sizeof(xZipDirectoryEntry_t),&xZipDirectoryEntry_t::xZipDirectoryEntrySortCompare); - - printf("Building regular to preload mapping table for %u entries...\n", Header.DirectoryEntries ); - unsigned short* Regular2Preload = (unsigned short*)malloc( nRegular2PreloadSize ); - for( unsigned i = 0; i < Header.DirectoryEntries; i++ ) - { - unsigned short j; - for( j = 0; j < Header.PreloadDirectoryEntries; j++ ) - { - if( pDirectoryEntries[i].FilenameCRC == pPreloadDirectoryEntries[j].FilenameCRC ) - break; - } - - // If I couldn't find it mark it as non-existant: - if( j == Header.PreloadDirectoryEntries ) - j = 0xFFFF; - - Regular2Preload[i] = j; - } - - printf("Writing preloaded directory entreis...\n" ); - - // Swap the preload directory entries: - for( unsigned i=0; i < Header.PreloadDirectoryEntries; i++ ) - { - g_xzpSwap.SwapFieldsToTargetEndian(&pPreloadDirectoryEntries[i]); - } - - fwrite( pPreloadDirectoryEntries, Header.PreloadDirectoryEntries*sizeof(xZipDirectoryEntry_t),1, hOutputFile ); - - // Swap them back: - for( unsigned i=0; i < Header.PreloadDirectoryEntries; i++ ) - { - g_xzpSwap.SwapFieldsToTargetEndian(&pPreloadDirectoryEntries[i]); - } - - printf("Writing regular to preload mapping (%u bytes)...\n", sizeof(unsigned short)*Header.DirectoryEntries ); - - // Swap regular to preload mapping: - g_xzpSwap.SwapBufferToTargetEndian((short*)Regular2Preload, (short*)Regular2Preload, nRegular2PreloadSize / sizeof(short) ); - - fwrite( Regular2Preload, nRegular2PreloadSize,1,hOutputFile ); - - // Swap it back - g_xzpSwap.SwapBufferToTargetEndian((short*)Regular2Preload, (short*)Regular2Preload, nRegular2PreloadSize / sizeof(short) ); - - printf("Copying %u Preloadable Bytes...\n", Header.PreloadBytes - nPreloadDirectorySize - nRegular2PreloadSize ); - fseek(hTempFilePreload,0,SEEK_SET); - CopyFileBytes(hOutputFile, hTempFilePreload, Header.PreloadBytes - nPreloadDirectorySize - nRegular2PreloadSize ); - } - - // Align the data section following the preload section: - if( nPadding ) - { - printf("Aligning Data Section Start by %u bytes...\n", nPadding ); - PadFileBytes(hOutputFile, nPadding ); - } - - // Copy the data section: - fseek(hTempFileData, 0, SEEK_END ); - unsigned length = ftell( hTempFileData ); - fseek(hTempFileData, 0, SEEK_SET ); - printf("Copying %u Bytes...\n",length); - - CopyFileBytes(hOutputFile, hTempFileData, length); - - // Write out the filename data if present: - if( nFilenameDataLength && Header.FilenameEntries ) - { - Header.FilenameStringsOffset = ftell(hOutputFile); - Header.FilenameStringsLength = (Header.FilenameEntries*sizeof(xZipFilenameEntry_t)) + nFilenameDataLength; - - // Adjust the offset in each of the filename offsets to absolute position in the file. - for( unsigned i=0;i(&pFilenameEntries[i]); - } - - fwrite(pFilenameEntries,1,Header.FilenameEntries*sizeof(xZipFilenameEntry_t),hOutputFile); - - // Swap them back: - for( unsigned int i = 0; i < Header.FilenameEntries; i++ ) - { - g_xzpSwap.SwapFieldsToTargetEndian(&pFilenameEntries[i]); - } - - printf("Writing %u bytes of filename data...\n",nFilenameDataLength); - fwrite(pFilenameData,1,nFilenameDataLength,hOutputFile); - } - - // Compute the total file size, including the size of the footer: - unsigned OutputFileBytes = ftell(hOutputFile) + sizeof(xZipFooter_t); - - // Write the footer: (block used to keep possibly swapped footer from being used later) - { - xZipFooter_t footer; - footer.Magic = xZipFooter_t::MAGIC; - footer.Size = OutputFileBytes; - - g_xzpSwap.SwapFieldsToTargetEndian( &footer ); // Swap the footer - fwrite( &footer, 1, sizeof(footer), hOutputFile ); - } - - // Seek back and rewrite the header (filename data changes it for example) - fseek(hOutputFile,0,SEEK_SET); - g_xzpSwap.SwapFieldsToTargetEndian( &Header ); // Swap it to write out: - fwrite(&Header,1,sizeof(Header),hOutputFile); - g_xzpSwap.SwapFieldsToTargetEndian( &Header ); // But then swap it back so we can use it in memory - - // Shut down - fclose(hOutputFile); - - // Print the summary - printf("\n\nSummary: Input:%u, XZip:%u, Directory Entries:%u (%u preloaded), Preloaded Bytes:%u\n\n",InputFileBytes,OutputFileBytes,Header.DirectoryEntries, Header.PreloadDirectoryEntries, Header.PreloadBytes); - - // Shut down: - fclose(hTempFileData); - fclose(hTempFilePreload); - - return true; -} - -#define PADD_ID MAKEID('P','A','D','D') - -//----------------------------------------------------------------------------- -// xZipComputeWAVPreload -// -// Returns the number of bytes from a xbox compliant WAV file that should go into -// the preload section: -//----------------------------------------------------------------------------- -unsigned xZipComputeWAVPreload( char *pFileName ) -{ - InFileRIFF riff( pFileName, *g_pSndIO ); - if ( riff.RIFFName() != RIFF_WAVE ) - { - return 0; - } - - IterateRIFF walk( riff, riff.RIFFSize() ); - - while ( walk.ChunkAvailable() ) - { - // xbox compliant wavs have a single PADD chunk - if ( walk.ChunkName() == PADD_ID ) - { - // want to preload data up through PADD chunk header - // and not the actual pad bytes - return walk.ChunkFilePosition() + 2*sizeof( int ); - } - walk.ChunkNext(); - } - - return 0; -} - - -//----------------------------------------------------------------------------- -// xZipComputeXWVPreload -// -// Returns the number of bytes from a XWV file that should go into the preload -// section: -//----------------------------------------------------------------------------- -unsigned xZipComputeXWVPreload( const char* filename ) -{ - FILE* hFile = fopen( filename, "rb" ); - if ( !hFile ) - { - printf( "Failed to open xwv file: %s\n", filename ); - return 0; - } - - // Read and validate the XWV header: - xwvHeader_t header; - memset( &header, 0, sizeof(header) ); - fread( &header, 1, sizeof(header), hFile ); - fclose( hFile ); - - if ( header.id != XWV_ID || header.headerSize != sizeof(header) ) - return 0; - - return header.GetPreloadSize(); -} - -unsigned xZipComputeXTFPreload( const char* filename ) -{ -#if 0 // X360TBD: Not using XTF anymore - FILE* hFile = fopen( filename, "rb" ); - if ( !hFile ) - { - printf("Failed to open file: %s\n", filename); - return 0; - } - - XTFFileHeader_t header; - memset( &header,0, sizeof( header ) ); - fread( &header,1,sizeof(header),hFile); - - fclose(hFile); - - if ( !strncmp( header.fileTypeString, "XTF", 4 ) ) - return header.preloadDataSize; -#endif - return 0; -} - -// TODO: ONLY store them in the preload section: -unsigned xZipComputeVMTPreload( const char* filename ) -{ - // Store VMT's entirely - if ( !strstr(filename,".vmt") ) - return 0; - - FILE* hFile = fopen( filename, "rb" ); - if ( !hFile ) - { - printf("Failed to open file: %s\n", filename); - return 0; - } - - fseek( hFile, 0, SEEK_END ); - unsigned offset = ftell( hFile ); - fclose( hFile ); - return offset; -} - -// TODO: ONLY store them in the preload section: -unsigned xZipComputeVHVPreload( const char* filename ) -{ - // Store VMT's entirely - if ( !strstr(filename,".vhv") ) - return 0; - - FILE* hFile = fopen( filename, "rb" ); - if ( !hFile ) - { - printf("Failed to open file: %s\n", filename); - return 0; - } - - fclose( hFile ); - - // Just load the header: - return sizeof(HardwareVerts::FileHeader_t); -} - -unsigned xZipComputeXCSPreload( const char* filename ) -{ - if( !strstr(filename,".vcs") ) - return 0; - - FILE* hFile = fopen( filename, "rb" ); - if ( !hFile ) - { - printf("Failed to open file: %s\n", filename); - return 0; - } - - XShaderHeader_t header; - fread(&header,1,sizeof(XShaderHeader_t), hFile); - fseek(hFile,0,SEEK_END); - fclose(hFile); - - if (!header.IsValid()) - return 0; - - return header.BytesToPreload(); -} - -unsigned xZipComputeCustomPreloads( const char* filename ) -{ - // X360TBD: These all need to act on a utlbuffer - Assert( 0 ); - return 0; - -// strlwr(filename); - - unsigned offset = xZipComputeXWVPreload( filename ); - if ( offset ) - return offset; - - offset = xZipComputeVMTPreload( filename ); - if ( offset ) - return offset; - - offset = xZipComputeXCSPreload( filename ); - if ( offset ) - return offset; - - offset = xZipComputeVHVPreload( filename ); - if ( offset ) - return offset; - - return xZipComputeXTFPreload( filename ); -} - -#endif // MAKE_GAMEDATA_TOOL diff --git a/public/zip/XUnzip.h b/public/zip/XUnzip.h deleted file mode 100644 index eb6fd2f27..000000000 --- a/public/zip/XUnzip.h +++ /dev/null @@ -1,389 +0,0 @@ -// XUnzip.h Version 1.1 -// -// Authors: Mark Adler et al. (see below) -// -// Modified by: Lucian Wischik -// lu@wischik.com -// -// Version 1.0 - Turned C files into just a single CPP file -// - Made them compile cleanly as C++ files -// - Gave them simpler APIs -// - Added the ability to zip/unzip directly in memory without -// any intermediate files -// -// Modified by: Hans Dietrich -// hdietrich2@hotmail.com -// -// Version 1.1: - Added Unicode support to CreateZip() and ZipAdd() -// - Changed file names to avoid conflicts with Lucian's files -// -/////////////////////////////////////////////////////////////////////////////// -// -// Lucian Wischik's comments: -// -------------------------- -// THIS FILE is almost entirely based upon code by info-zip. -// It has been modified by Lucian Wischik. -// The original code may be found at http://www.info-zip.org -// The original copyright text follows. -// -/////////////////////////////////////////////////////////////////////////////// -// -// Original authors' comments: -// --------------------------- -// This is version 2002-Feb-16 of the Info-ZIP copyright and license. The -// definitive version of this document should be available at -// ftp://ftp.info-zip.org/pub/infozip/license.html indefinitely. -// -// Copyright (c) 1990-2002 Info-ZIP. All rights reserved. -// -// For the purposes of this copyright and license, "Info-ZIP" is defined as -// the following set of individuals: -// -// Mark Adler, John Bush, Karl Davis, Harald Denker, Jean-Michel Dubois, -// Jean-loup Gailly, Hunter Goatley, Ian Gorman, Chris Herborth, Dirk Haase, -// Greg Hartwig, Robert Heath, Jonathan Hudson, Paul Kienitz, -// David Kirschbaum, Johnny Lee, Onno van der Linden, Igor Mandrichenko, -// Steve P. Miller, Sergio Monesi, Keith Owens, George Petrov, Greg Roelofs, -// Kai Uwe Rommel, Steve Salisbury, Dave Smith, Christian Spieler, -// Antoine Verheijen, Paul von Behren, Rich Wales, Mike White -// -// This software is provided "as is", without warranty of any kind, express -// or implied. In no event shall Info-ZIP or its contributors be held liable -// for any direct, indirect, incidental, special or consequential damages -// arising out of the use of or inability to use this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. Redistributions of source code must retain the above copyright notice, -// definition, disclaimer, and this list of conditions. -// -// 2. Redistributions in binary form (compiled executables) must reproduce -// the above copyright notice, definition, disclaimer, and this list of -// conditions in documentation and/or other materials provided with the -// distribution. The sole exception to this condition is redistribution -// of a standard UnZipSFX binary as part of a self-extracting archive; -// that is permitted without inclusion of this license, as long as the -// normal UnZipSFX banner has not been removed from the binary or disabled. -// -// 3. Altered versions--including, but not limited to, ports to new -// operating systems, existing ports with new graphical interfaces, and -// dynamic, shared, or static library versions--must be plainly marked -// as such and must not be misrepresented as being the original source. -// Such altered versions also must not be misrepresented as being -// Info-ZIP releases--including, but not limited to, labeling of the -// altered versions with the names "Info-ZIP" (or any variation thereof, -// including, but not limited to, different capitalizations), -// "Pocket UnZip", "WiZ" or "MacZip" without the explicit permission of -// Info-ZIP. Such altered versions are further prohibited from -// misrepresentative use of the Zip-Bugs or Info-ZIP e-mail addresses or -// of the Info-ZIP URL(s). -// -// 4. Info-ZIP retains the right to use the names "Info-ZIP", "Zip", "UnZip", -// "UnZipSFX", "WiZ", "Pocket UnZip", "Pocket Zip", and "MacZip" for its -// own source and binary releases. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef XUNZIP_H -#define XUNZIP_H - - -#ifndef DECLARE_XZIP_HANDLE -#define DECLARE_XZIP_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name -#endif - -#ifndef XZIP_H -DECLARE_XZIP_HANDLE(HZIP); // An HZIP identifies a zip file that has been opened -#endif - -typedef DWORD ZRESULT; -// return codes from any of the zip functions. Listed later. - -#define ZIP_HANDLE 1 -#define ZIP_FILENAME 2 -#define ZIP_MEMORY 3 - -typedef struct -{ int index; // index of this file within the zip - char name[MAX_PATH]; // filename within the zip - DWORD attr; // attributes, as in GetFileAttributes. - FILETIME atime,ctime,mtime;// access, create, modify filetimes - long comp_size; // sizes of item, compressed and uncompressed. These - long unc_size; // may be -1 if not yet known (e.g. being streamed in) -} ZIPENTRY; - -typedef struct -{ int index; // index of this file within the zip - TCHAR name[MAX_PATH]; // filename within the zip - DWORD attr; // attributes, as in GetFileAttributes. - FILETIME atime,ctime,mtime;// access, create, modify filetimes - long comp_size; // sizes of item, compressed and uncompressed. These - long unc_size; // may be -1 if not yet known (e.g. being streamed in) -} ZIPENTRYW; - - -/////////////////////////////////////////////////////////////////////////////// -// -// OpenZip() -// -// Purpose: Open an existing zip archive file -// -// Parameters: z - archive file name if flags is ZIP_FILENAME; for other -// uses see below -// len - for memory (ZIP_MEMORY) should be the buffer size; -// for other uses, should be 0 -// flags - indicates usage, see below; for files, this will be -// ZIP_FILENAME -// -// Returns: HZIP - non-zero if zip archive opened ok, otherwise 0 -// -HZIP OpenZip(void *z, unsigned int len, DWORD flags); -// OpenZip - opens a zip file and returns a handle with which you can -// subsequently examine its contents. You can open a zip file from: -// from a pipe: OpenZip(hpipe_read,0, ZIP_HANDLE); -// from a file (by handle): OpenZip(hfile,0, ZIP_HANDLE); -// from a file (by name): OpenZip("c:\\test.zip",0, ZIP_FILENAME); -// from a memory block: OpenZip(bufstart, buflen, ZIP_MEMORY); -// If the file is opened through a pipe, then items may only be -// accessed in increasing order, and an item may only be unzipped once, -// although GetZipItem can be called immediately before and after unzipping -// it. If it's opened i n any other way, then full random access is possible. -// Note: pipe input is not yet implemented. - - -/////////////////////////////////////////////////////////////////////////////// -// -// GetZipItem() -// -// Purpose: Get information about an item in an open zip archive -// -// Parameters: hz - handle of open zip archive -// index - index number (0 based) of item in zip -// ze - pointer to a ZIPENTRY (if ANSI) or ZIPENTRYW struct -// (if Unicode) -// -// Returns: ZRESULT - ZR_OK if success, otherwise some other value -// - -#ifdef _UNICODE -#define GetZipItem GetZipItemW -#else -#define GetZipItem GetZipItemA -#endif - -ZRESULT GetZipItemA(HZIP hz, int index, ZIPENTRY *ze); -ZRESULT GetZipItemW(HZIP hz, int index, ZIPENTRYW *ze); -// GetZipItem - call this to get information about an item in the zip. -// If index is -1 and the file wasn't opened through a pipe, -// then it returns information about the whole zipfile -// (and in particular ze.index returns the number of index items). -// Note: the item might be a directory (ze.attr & FILE_ATTRIBUTE_DIRECTORY) -// See below for notes on what happens when you unzip such an item. -// Note: if you are opening the zip through a pipe, then random access -// is not possible and GetZipItem(-1) fails and you can't discover the number -// of items except by calling GetZipItem on each one of them in turn, -// starting at 0, until eventually the call fails. Also, in the event that -// you are opening through a pipe and the zip was itself created into a pipe, -// then then comp_size and sometimes unc_size as well may not be known until -// after the item has been unzipped. - - -/////////////////////////////////////////////////////////////////////////////// -// -// FindZipItem() -// -// Purpose: Find item by name and return information about it -// -// Parameters: hz - handle of open zip archive -// name - name of file to look for inside zip archive -// ic - TRUE = case insensitive -// index - pointer to index number returned, or -1 -// ze - pointer to a ZIPENTRY (if ANSI) or ZIPENTRYW struct -// (if Unicode) -// -// Returns: ZRESULT - ZR_OK if success, otherwise some other value -// - -#ifdef _UNICODE -#define FindZipItem FindZipItemW -#else -#define FindZipItem FindZipItemA -#endif - -ZRESULT FindZipItemA(HZIP hz, const TCHAR *name, bool ic, int *index, ZIPENTRY *ze); -ZRESULT FindZipItemW(HZIP hz, const TCHAR *name, bool ic, int *index, ZIPENTRYW *ze); -// FindZipItem - finds an item by name. ic means 'insensitive to case'. -// It returns the index of the item, and returns information about it. -// If nothing was found, then index is set to -1 and the function returns -// an error code. - - -/////////////////////////////////////////////////////////////////////////////// -// -// UnzipItem() -// -// Purpose: Find item by index and unzip it -// -// Parameters: hz - handle of open zip archive -// index - index number of file to unzip -// dst - target file name of unzipped file -// len - for memory (ZIP_MEMORY. length of buffer; -// otherwise 0 -// flags - indicates usage, see below; for files, this will be -// ZIP_FILENAME -// -// Returns: ZRESULT - ZR_OK if success, otherwise some other value -// - -ZRESULT UnzipItem(HZIP hz, int index, void *dst, unsigned int len, DWORD flags); -// UnzipItem - given an index to an item, unzips it. You can unzip to: -// to a pipe: UnzipItem(hz,i, hpipe_write,0,ZIP_HANDLE); -// to a file (by handle): UnzipItem(hz,i, hfile,0,ZIP_HANDLE); -// to a file (by name): UnzipItem(hz,i, ze.name,0,ZIP_FILENAME); -// to a memory block: UnzipItem(hz,i, buf,buflen,ZIP_MEMORY); -// In the final case, if the buffer isn't large enough to hold it all, -// then the return code indicates that more is yet to come. If it was -// large enough, and you want to know precisely how big, GetZipItem. -// Note: zip files are normally stored with relative pathnames. If you -// unzip with ZIP_FILENAME a relative pathname then the item gets created -// relative to the current directory - it first ensures that all necessary -// subdirectories have been created. Also, the item may itself be a directory. -// If you unzip a directory with ZIP_FILENAME, then the directory gets created. -// If you unzip it to a handle or a memory block, then nothing gets created -// and it emits 0 bytes. - - -/////////////////////////////////////////////////////////////////////////////// -// -// CloseZip() -// -// Purpose: Close an open zip archive -// -// Parameters: hz - handle to an open zip archive -// -// Returns: ZRESULT - ZR_OK if success, otherwise some other value -// -ZRESULT CloseZip(HZIP hz); -// CloseZip - the zip handle must be closed with this function. - -unsigned int FormatZipMessage(ZRESULT code, char *buf,unsigned int len); -// FormatZipMessage - given an error code, formats it as a string. -// It returns the length of the error message. If buf/len points -// to a real buffer, then it also writes as much as possible into there. - - -// These are the result codes: -#define ZR_OK 0x00000000 // nb. the pseudo-code zr-recent is never returned, -#define ZR_RECENT 0x00000001 // but can be passed to FormatZipMessage. -// The following come from general system stuff (e.g. files not openable) -#define ZR_GENMASK 0x0000FF00 -#define ZR_NODUPH 0x00000100 // couldn't duplicate the handle -#define ZR_NOFILE 0x00000200 // couldn't create/open the file -#define ZR_NOALLOC 0x00000300 // failed to allocate some resource -#define ZR_WRITE 0x00000400 // a general error writing to the file -#define ZR_NOTFOUND 0x00000500 // couldn't find that file in the zip -#define ZR_MORE 0x00000600 // there's still more data to be unzipped -#define ZR_CORRUPT 0x00000700 // the zipfile is corrupt or not a zipfile -#define ZR_READ 0x00000800 // a general error reading the file -// The following come from mistakes on the part of the caller -#define ZR_CALLERMASK 0x00FF0000 -#define ZR_ARGS 0x00010000 // general mistake with the arguments -#define ZR_NOTMMAP 0x00020000 // tried to ZipGetMemory, but that only works on mmap zipfiles, which yours wasn't -#define ZR_MEMSIZE 0x00030000 // the memory size is too small -#define ZR_FAILED 0x00040000 // the thing was already failed when you called this function -#define ZR_ENDED 0x00050000 // the zip creation has already been closed -#define ZR_MISSIZE 0x00060000 // the indicated input file size turned out mistaken -#define ZR_PARTIALUNZ 0x00070000 // the file had already been partially unzipped -#define ZR_ZMODE 0x00080000 // tried to mix creating/opening a zip -// The following come from bugs within the zip library itself -#define ZR_BUGMASK 0xFF000000 -#define ZR_NOTINITED 0x01000000 // initialisation didn't work -#define ZR_SEEK 0x02000000 // trying to seek in an unseekable file -#define ZR_NOCHANGE 0x04000000 // changed its mind on storage, but not allowed -#define ZR_FLATE 0x05000000 // an internal error in the de/inflation code - - - - - -// e.g. -// -// SetCurrentDirectory("c:\\docs\\stuff"); -// HZIP hz = OpenZip("c:\\stuff.zip",0,ZIP_FILENAME); -// ZIPENTRY ze; GetZipItem(hz,-1,&ze); int numitems=ze.index; -// for (int i=0; i -#ifdef IS_WINDOWS_PC -#include -#endif -#include "utlbuffer.h" -#include "utllinkedlist.h" -#include "zip_utils.h" -#include "zip_uncompressed.h" -#include "checksum_crc.h" -#include "byteswap.h" -#include "utlstring.h" - -// Data descriptions for byte swapping - only needed -// for structures that are written to file for use by the game. -BEGIN_BYTESWAP_DATADESC( ZIP_EndOfCentralDirRecord ) - DEFINE_FIELD( signature, FIELD_INTEGER ), - DEFINE_FIELD( numberOfThisDisk, FIELD_SHORT ), - DEFINE_FIELD( numberOfTheDiskWithStartOfCentralDirectory, FIELD_SHORT ), - DEFINE_FIELD( nCentralDirectoryEntries_ThisDisk, FIELD_SHORT ), - DEFINE_FIELD( nCentralDirectoryEntries_Total, FIELD_SHORT ), - DEFINE_FIELD( centralDirectorySize, FIELD_INTEGER ), - DEFINE_FIELD( startOfCentralDirOffset, FIELD_INTEGER ), - DEFINE_FIELD( commentLength, FIELD_SHORT ), -END_BYTESWAP_DATADESC() - -BEGIN_BYTESWAP_DATADESC( ZIP_FileHeader ) - DEFINE_FIELD( signature, FIELD_INTEGER ), - DEFINE_FIELD( versionMadeBy, FIELD_SHORT ), - DEFINE_FIELD( versionNeededToExtract, FIELD_SHORT ), - DEFINE_FIELD( flags, FIELD_SHORT ), - DEFINE_FIELD( compressionMethod, FIELD_SHORT ), - DEFINE_FIELD( lastModifiedTime, FIELD_SHORT ), - DEFINE_FIELD( lastModifiedDate, FIELD_SHORT ), - DEFINE_FIELD( crc32, FIELD_INTEGER ), - DEFINE_FIELD( compressedSize, FIELD_INTEGER ), - DEFINE_FIELD( uncompressedSize, FIELD_INTEGER ), - DEFINE_FIELD( fileNameLength, FIELD_SHORT ), - DEFINE_FIELD( extraFieldLength, FIELD_SHORT ), - DEFINE_FIELD( fileCommentLength, FIELD_SHORT ), - DEFINE_FIELD( diskNumberStart, FIELD_SHORT ), - DEFINE_FIELD( internalFileAttribs, FIELD_SHORT ), - DEFINE_FIELD( externalFileAttribs, FIELD_INTEGER ), - DEFINE_FIELD( relativeOffsetOfLocalHeader, FIELD_INTEGER ), -END_BYTESWAP_DATADESC() - -#if !defined( SWDS ) - -BEGIN_BYTESWAP_DATADESC( ZIP_LocalFileHeader ) - DEFINE_FIELD( signature, FIELD_INTEGER ), - DEFINE_FIELD( versionNeededToExtract, FIELD_SHORT ), - DEFINE_FIELD( flags, FIELD_SHORT ), - DEFINE_FIELD( compressionMethod, FIELD_SHORT ), - DEFINE_FIELD( lastModifiedTime, FIELD_SHORT ), - DEFINE_FIELD( lastModifiedDate, FIELD_SHORT ), - DEFINE_FIELD( crc32, FIELD_INTEGER ), - DEFINE_FIELD( compressedSize, FIELD_INTEGER ), - DEFINE_FIELD( uncompressedSize, FIELD_INTEGER ), - DEFINE_FIELD( fileNameLength, FIELD_SHORT ), - DEFINE_FIELD( extraFieldLength, FIELD_SHORT ), -END_BYTESWAP_DATADESC() - -BEGIN_BYTESWAP_DATADESC( ZIP_PreloadHeader ) - DEFINE_FIELD( Version, FIELD_INTEGER ), - DEFINE_FIELD( DirectoryEntries, FIELD_INTEGER ), - DEFINE_FIELD( PreloadDirectoryEntries, FIELD_INTEGER ), - DEFINE_FIELD( Alignment, FIELD_INTEGER ), -END_BYTESWAP_DATADESC() - -BEGIN_BYTESWAP_DATADESC( ZIP_PreloadDirectoryEntry ) - DEFINE_FIELD( Length, FIELD_INTEGER ), - DEFINE_FIELD( DataOffset, FIELD_INTEGER ), -END_BYTESWAP_DATADESC() - -//----------------------------------------------------------------------------- -// For >2 GB File Support -//----------------------------------------------------------------------------- -class CWin32File -{ -public: - static HANDLE CreateTempFile( CUtlString &WritePath, CUtlString &FileName ) - { - char tempFileName[MAX_PATH]; - if ( WritePath.IsEmpty() ) - { - // use a safe name in the cwd - char *pBuffer = tmpnam( NULL ); - if ( !pBuffer ) - { - return INVALID_HANDLE_VALUE; - } - if ( pBuffer[0] == '\\' ) - { - pBuffer++; - } - if ( pBuffer[strlen( pBuffer )-1] == '.' ) - { - pBuffer[strlen( pBuffer )-1] = '\0'; - } - V_snprintf( tempFileName, sizeof( tempFileName ), "_%s.tmp", pBuffer ); - } - else - { - // generate safe name at the desired prefix - char uniqueFilename[MAX_PATH]; - SYSTEMTIME sysTime; \ - GetLocalTime( &sysTime ); - sprintf( uniqueFilename, "%d_%d_%d_%d_%d.tmp", sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds ); \ - V_ComposeFileName( WritePath.String(), uniqueFilename, tempFileName, sizeof( tempFileName ) ); - } - - FileName = tempFileName; - HANDLE hFile = CreateFile( tempFileName, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); - - return hFile; - } - - static unsigned int FileSeek( HANDLE hFile, unsigned int distance, DWORD MoveMethod ) - { - LARGE_INTEGER li; - - li.QuadPart = distance; - li.LowPart = SetFilePointer( hFile, li.LowPart, &li.HighPart, MoveMethod); - if ( li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR ) - { - li.QuadPart = -1; - } - - return ( unsigned int )li.QuadPart; - } - - static unsigned int FileTell( HANDLE hFile ) - { - return FileSeek( hFile, 0, FILE_CURRENT ); - } - - static bool FileRead( HANDLE hFile, void *pBuffer, unsigned int size ) - { - DWORD numBytesRead; - BOOL bSuccess = ::ReadFile( hFile, pBuffer, size, &numBytesRead, NULL ); - return bSuccess && ( numBytesRead == size ); - } - - static bool FileWrite( HANDLE hFile, void *pBuffer, unsigned int size ) - { - DWORD numBytesWritten; - BOOL bSuccess = WriteFile( hFile, pBuffer, size, &numBytesWritten, NULL ); - return bSuccess && ( numBytesWritten == size ); - } -}; - -//----------------------------------------------------------------------------- -// Purpose: Interface to allow abstraction of zip file output methods, and -// avoid duplication of code. Files may be written to a CUtlBuffer or a filestream -//----------------------------------------------------------------------------- -abstract_class IWriteStream -{ -public: - virtual void Put( const void* pMem, int size ) = 0; - virtual unsigned int Tell( void ) = 0; -}; - -//----------------------------------------------------------------------------- -// Purpose: Wrapper for CUtlBuffer methods -//----------------------------------------------------------------------------- -class CBufferStream : public IWriteStream -{ -public: - CBufferStream( CUtlBuffer& buff ) : IWriteStream(), m_buff( &buff ) {} - - // Implementing IWriteStream method - virtual void Put( const void* pMem, int size ) { m_buff->Put( pMem, size ); } - - // Implementing IWriteStream method - virtual unsigned int Tell( void ) { return m_buff->TellPut(); } - -private: - CUtlBuffer *m_buff; -}; - -//----------------------------------------------------------------------------- -// Purpose: Wrapper for file I/O methods -//----------------------------------------------------------------------------- -class CFileStream : public IWriteStream -{ -public: - CFileStream( FILE *fout ) : IWriteStream(), m_file( fout ), m_hFile( INVALID_HANDLE_VALUE ) {} - CFileStream( HANDLE hOutFile ) : IWriteStream(), m_file( NULL ), m_hFile( hOutFile ) {} - - // Implementing IWriteStream method - virtual void Put( const void* pMem, int size ) - { - if ( m_file ) - { - fwrite( pMem, size, 1, m_file ); - } - else - { - DWORD numBytesWritten; - WriteFile( m_hFile, pMem, size, &numBytesWritten, NULL ); - } - } - - // Implementing IWriteStream method - virtual unsigned int Tell( void ) - { - if ( m_file ) - { - return ftell( m_file ); - } - else - { - return CWin32File::FileTell( m_hFile ); - } - } - -private: - FILE *m_file; - HANDLE m_hFile; -}; - -//----------------------------------------------------------------------------- -// Purpose: Container for modifiable pak file which is embedded inside the .bsp file -// itself. It's used to allow one-off files to be stored local to the map and it is -// hooked into the file system as an override for searching for named files. -//----------------------------------------------------------------------------- -class CZipFile -{ -public: - // Construction - CZipFile( const char *pDiskCacheWritePath, bool bSortByName ); - ~CZipFile( void ); - - // Public API - // Clear all existing data - void Reset( void ); - - // Add file to zip under relative name - void AddFileToZip( const char *relativename, const char *fullpath ); - - // Delete file from zip - void RemoveFileFromZip( const char *relativename ); - - // Add buffer to zip as a file with given name - void AddBufferToZip( const char *relativename, void *data, int length, bool bTextMode ); - - // Check if a file already exists in the zip. - bool FileExistsInZip( const char *relativename ); - - // Reads a file from a zip file - bool ReadFileFromZip( const char *relativename, bool bTextMode, CUtlBuffer &buf ); - bool ReadFileFromZip( HANDLE hZipFile, const char *relativename, bool bTextMode, CUtlBuffer &buf ); - - // Initialize the zip file from a buffer - void ParseFromBuffer( void *buffer, int bufferlength ); - HANDLE ParseFromDisk( const char *pFilename ); - - // Estimate the size of the zip file (including header, padding, etc.) - unsigned int EstimateSize(); - - // Print out a directory of files in the zip. - void PrintDirectory( void ); - - // Use to iterate directory, pass 0 for first element - // returns nonzero element id with filled buffer, or -1 at list conclusion - int GetNextFilename( int id, char *pBuffer, int bufferSize, int &fileSize ); - - // Write the zip to a buffer - void SaveToBuffer( CUtlBuffer& buffer ); - // Write the zip to a filestream - void SaveToDisk( FILE *fout ); - void SaveToDisk( HANDLE hOutFile ); - - unsigned int CalculateSize( void ); - - void ForceAlignment( bool aligned, bool bCompatibleFormat, unsigned int alignmentSize ); - - unsigned int GetAlignment(); - - void SetBigEndian( bool bigEndian ); - void ActivateByteSwapping( bool bActivate ); - -private: - enum - { - MAX_FILES_IN_ZIP = 32768, - }; - - typedef struct - { - CUtlSymbol m_Name; - unsigned int filepos; - int filelen; - } TmpFileInfo_t; - - CByteswap m_Swap; - unsigned int m_AlignmentSize; - bool m_bForceAlignment; - bool m_bCompatibleFormat; - - unsigned short CalculatePadding( unsigned int filenameLen, unsigned int pos ); - void SaveDirectory( IWriteStream& stream ); - int MakeXZipCommentString( char *pComment ); - void ParseXZipCommentString( const char *pComment ); - - // Internal entry for faster searching, etc. - class CZipEntry - { - public: - CZipEntry( void ); - ~CZipEntry( void ); - - CZipEntry( const CZipEntry& src ); - - // RB tree compare function - static bool ZipFileLessFunc( CZipEntry const& src1, CZipEntry const& src2 ); - static bool ZipFileLessFunc_CaselessSort( CZipEntry const& src1, CZipEntry const& src2 ); - - // Name of entry - CUtlSymbol m_Name; - - // Lenth of data element - int m_Length; - // Raw data, could be null and data may be in disk write cache - void *m_pData; - - // Offset in Zip ( set and valid during final write ) - unsigned int m_ZipOffset; - // CRC of blob ( set and valid during final write ) - CRC32_t m_ZipCRC; - - // Location of data in disk cache - unsigned int m_DiskCacheOffset; - unsigned int m_SourceDiskOffset; - }; - - // For fast name lookup and sorting - CUtlRBTree< CZipEntry, int > m_Files; - - // Used to buffer zip data, instead of ram - bool m_bUseDiskCacheForWrites; - HANDLE m_hDiskCacheWriteFile; - CUtlString m_DiskCacheName; - CUtlString m_DiskCacheWritePath; -}; - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -CZipFile::CZipEntry::CZipEntry( void ) -{ - m_Name = ""; - m_Length = 0; - m_pData = NULL; - m_ZipOffset = 0; - m_ZipCRC = 0; - m_DiskCacheOffset = 0; - m_SourceDiskOffset = 0; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : src - -//----------------------------------------------------------------------------- -CZipFile::CZipEntry::CZipEntry( const CZipFile::CZipEntry& src ) -{ - m_Name = src.m_Name; - m_Length = src.m_Length; - - if ( src.m_Length > 0 && src.m_pData ) - { - m_pData = malloc( src.m_Length ); - memcpy( m_pData, src.m_pData, src.m_Length ); - } - else - { - m_pData = NULL; - } - - m_ZipOffset = src.m_ZipOffset; - m_ZipCRC = src.m_ZipCRC; - m_DiskCacheOffset = src.m_DiskCacheOffset; - m_SourceDiskOffset = src.m_SourceDiskOffset; -} - -//----------------------------------------------------------------------------- -// Purpose: Clear any leftover data -//----------------------------------------------------------------------------- -CZipFile::CZipEntry::~CZipEntry( void ) -{ - if ( m_pData ) - { - free( m_pData ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Construction -//----------------------------------------------------------------------------- -CZipFile::CZipFile( const char *pDiskCacheWritePath, bool bSortByName ) -: m_Files( 0, 32 ) -{ - m_AlignmentSize = 0; - m_bForceAlignment = false; - m_bCompatibleFormat = true; - - m_bUseDiskCacheForWrites = ( pDiskCacheWritePath != NULL ); - m_DiskCacheWritePath = pDiskCacheWritePath; - m_hDiskCacheWriteFile = INVALID_HANDLE_VALUE; - - if ( bSortByName ) - { - m_Files.SetLessFunc( CZipEntry::ZipFileLessFunc_CaselessSort ); - } - else - { - m_Files.SetLessFunc( CZipEntry::ZipFileLessFunc ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Destroy zip data -//----------------------------------------------------------------------------- -CZipFile::~CZipFile( void ) -{ - m_bUseDiskCacheForWrites = false; - Reset(); -} - -//----------------------------------------------------------------------------- -// Purpose: Delete all current data -//----------------------------------------------------------------------------- -void CZipFile::Reset( void ) -{ - m_Files.RemoveAll(); - - if ( m_hDiskCacheWriteFile != INVALID_HANDLE_VALUE ) - { - CloseHandle( m_hDiskCacheWriteFile ); - DeleteFile( m_DiskCacheName.String() ); - m_hDiskCacheWriteFile = INVALID_HANDLE_VALUE; - } - - if ( m_bUseDiskCacheForWrites ) - { - m_hDiskCacheWriteFile = CWin32File::CreateTempFile( m_DiskCacheWritePath, m_DiskCacheName ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Comparison for sorting entries -// Input : src1 - -// src2 - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool CZipFile::CZipEntry::ZipFileLessFunc( CZipEntry const& src1, CZipEntry const& src2 ) -{ - return ( src1.m_Name < src2.m_Name ); -} - -bool CZipFile::CZipEntry::ZipFileLessFunc_CaselessSort( CZipEntry const& src1, CZipEntry const& src2 ) -{ - return ( V_stricmp( src1.m_Name.String(), src2.m_Name.String() ) < 0 ); -} - -void CZipFile::ForceAlignment( bool bAligned, bool bCompatibleFormat, unsigned int alignment ) -{ - m_bForceAlignment = bAligned; - m_AlignmentSize = alignment; - m_bCompatibleFormat = bCompatibleFormat; - - if ( !bAligned ) - { - m_AlignmentSize = 0; - } - else if ( !IsPowerOfTwo( m_AlignmentSize ) ) - { - m_AlignmentSize = 0; - } -} - -unsigned int CZipFile::GetAlignment() -{ - if ( !m_bForceAlignment || !m_AlignmentSize ) - { - return 0; - } - - return m_AlignmentSize; -} - -void CZipFile::SetBigEndian( bool bigEndian ) -{ - m_Swap.SetTargetBigEndian( bigEndian ); -} - -void CZipFile::ActivateByteSwapping( bool bActivate ) -{ - m_Swap.ActivateByteSwapping( bActivate ); -} - -//----------------------------------------------------------------------------- -// Purpose: Load pak file from raw buffer -// Input : *buffer - -// bufferlength - -//----------------------------------------------------------------------------- -void CZipFile::ParseFromBuffer( void *buffer, int bufferlength ) -{ - // Throw away old data - Reset(); - - // Initialize a buffer - CUtlBuffer buf( 0, bufferlength +1 ); // +1 for null termination - - // need to swap bytes, so set the buffer opposite the machine's endian - buf.ActivateByteSwapping( m_Swap.IsSwappingBytes() ); - - buf.Put( buffer, bufferlength ); - - buf.SeekGet( CUtlBuffer::SEEK_TAIL, 0 ); - unsigned int fileLen = buf.TellGet(); - - // Start from beginning - buf.SeekGet( CUtlBuffer::SEEK_HEAD, 0 ); - - unsigned int offset; - ZIP_EndOfCentralDirRecord rec = { 0 }; - - bool bFoundEndOfCentralDirRecord = false; - for ( offset = fileLen - sizeof( ZIP_EndOfCentralDirRecord ); offset >= 0; offset-- ) - { - buf.SeekGet( CUtlBuffer::SEEK_HEAD, offset ); - buf.GetObjects( &rec ); - if ( rec.signature == PKID( 5, 6 ) ) - { - bFoundEndOfCentralDirRecord = true; - - // Set any xzip configuration - if ( rec.commentLength ) - { - char commentString[128]; - int commentLength = MIN( rec.commentLength, sizeof( commentString ) ); - buf.Get( commentString, commentLength ); - commentString[commentLength] = '\0'; - ParseXZipCommentString( commentString ); - } - break; - } - else - { - // wrong record - rec.nCentralDirectoryEntries_Total = 0; - } - } - Assert( bFoundEndOfCentralDirRecord ); - - // Make sure there are some files to parse - int numzipfiles = rec.nCentralDirectoryEntries_Total; - if ( numzipfiles <= 0 ) - { - // No files - return; - } - - buf.SeekGet( CUtlBuffer::SEEK_HEAD, rec.startOfCentralDirOffset ); - - // Allocate space for directory - TmpFileInfo_t *newfiles = new TmpFileInfo_t[numzipfiles]; - Assert( newfiles ); - - // build directory - int i; - for ( i = 0; i < rec.nCentralDirectoryEntries_Total; i++ ) - { - ZIP_FileHeader zipFileHeader; - buf.GetObjects( &zipFileHeader ); - Assert( zipFileHeader.signature == PKID( 1, 2 ) ); - Assert( zipFileHeader.compressionMethod == 0 ); - - char tmpString[1024]; - buf.Get( tmpString, zipFileHeader.fileNameLength ); - tmpString[zipFileHeader.fileNameLength] = '\0'; - Q_strlower( tmpString ); - - // can determine actual filepos, assuming a well formed zip - newfiles[i].m_Name = tmpString; - newfiles[i].filelen = zipFileHeader.compressedSize; - newfiles[i].filepos = zipFileHeader.relativeOffsetOfLocalHeader + - sizeof( ZIP_LocalFileHeader ) + - zipFileHeader.fileNameLength + - zipFileHeader.extraFieldLength; - - int nextOffset; - if ( m_bCompatibleFormat ) - { - nextOffset = zipFileHeader.extraFieldLength + zipFileHeader.fileCommentLength; - } - else - { - nextOffset = 0; - } - buf.SeekGet( CUtlBuffer::SEEK_CURRENT, nextOffset ); - } - - // Insert current data into rb tree - for ( i=0; i 0 ) - { - e.m_pData = malloc( e.m_Length ); - - // Copy in data - buf.SeekGet( CUtlBuffer::SEEK_HEAD, newfiles[i].filepos ); - buf.Get( e.m_pData, e.m_Length ); - } - else - { - e.m_pData = NULL; - } - - // Add to tree - m_Files.Insert( e ); - } - - // Through away directory - delete[] newfiles; -} - -//----------------------------------------------------------------------------- -// Purpose: Mount pak file from disk -//----------------------------------------------------------------------------- -HANDLE CZipFile::ParseFromDisk( const char *pFilename ) -{ - HANDLE hFile = CreateFile( pFilename, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); - if ( !hFile ) - { - // not found - return NULL; - } - - unsigned int fileLen = CWin32File::FileSeek( hFile, 0, FILE_END ); - CWin32File::FileSeek( hFile, 0, FILE_BEGIN ); - if ( fileLen < sizeof( ZIP_EndOfCentralDirRecord ) ) - { - // bad format - CloseHandle( hFile ); - return NULL; - } - - // need to get the central dir - unsigned int offset; - ZIP_EndOfCentralDirRecord rec = { 0 }; - for ( offset = fileLen - sizeof( ZIP_EndOfCentralDirRecord ); offset >= 0; offset-- ) - { - CWin32File::FileSeek( hFile, offset, FILE_BEGIN ); - - CWin32File::FileRead( hFile, &rec, sizeof( rec ) ); - m_Swap.SwapFieldsToTargetEndian( &rec ); - - if ( rec.signature == PKID( 5, 6 ) ) - { - // Set any xzip configuration - if ( rec.commentLength ) - { - char commentString[128]; - int commentLength = MIN( rec.commentLength, sizeof( commentString ) ); - CWin32File::FileRead( hFile, commentString, commentLength ); - commentString[commentLength] = '\0'; - ParseXZipCommentString( commentString ); - } - break; - } - else - { - // wrong record - rec.nCentralDirectoryEntries_Total = 0; - } - } - - // Make sure there are some files to parse - int numZipFiles = rec.nCentralDirectoryEntries_Total; - if ( numZipFiles <= 0 ) - { - // No files - CloseHandle( hFile ); - return NULL; - } - - CWin32File::FileSeek( hFile, rec.startOfCentralDirOffset, FILE_BEGIN ); - - // read entire central dir into memory - CUtlBuffer zipDirBuff( 0, rec.centralDirectorySize, 0 ); - zipDirBuff.ActivateByteSwapping( m_Swap.IsSwappingBytes() ); - CWin32File::FileRead( hFile, zipDirBuff.Base(), rec.centralDirectorySize ); - zipDirBuff.SeekPut( CUtlBuffer::SEEK_HEAD, rec.centralDirectorySize ); - - // build directory - for ( int i = 0; i < numZipFiles; i++ ) - { - ZIP_FileHeader zipFileHeader; - zipDirBuff.GetObjects( &zipFileHeader ); - - if ( zipFileHeader.signature != PKID( 1, 2 ) || zipFileHeader.compressionMethod != 0 ) - { - // bad contents - CloseHandle( hFile ); - return NULL; - } - - char fileName[1024]; - zipDirBuff.Get( fileName, zipFileHeader.fileNameLength ); - fileName[zipFileHeader.fileNameLength] = '\0'; - Q_strlower( fileName ); - - // can determine actual filepos, assuming a well formed zip - CZipEntry e; - e.m_Name = fileName; - e.m_Length = zipFileHeader.compressedSize; - e.m_SourceDiskOffset = zipFileHeader.relativeOffsetOfLocalHeader + - sizeof( ZIP_LocalFileHeader ) + - zipFileHeader.fileNameLength + - zipFileHeader.extraFieldLength; - // Add to tree - m_Files.Insert( e ); - - int nextOffset; - if ( m_bCompatibleFormat ) - { - nextOffset = zipFileHeader.extraFieldLength + zipFileHeader.fileCommentLength; - } - else - { - nextOffset = 0; - } - - zipDirBuff.SeekGet( CUtlBuffer::SEEK_CURRENT, nextOffset ); - } - - return hFile; -} - -static int GetLengthOfBinStringAsText( const char *pSrc, int srcSize ) -{ - const char *pSrcScan = pSrc; - const char *pSrcEnd = pSrc + srcSize; - int numChars = 0; - for( ; pSrcScan < pSrcEnd; pSrcScan++ ) - { - if( *pSrcScan == '\n' ) - { - numChars += 2; - } - else - { - numChars++; - } - } - return numChars; -} - - -//----------------------------------------------------------------------------- -// Copies text data from a form appropriate for disk to a normal string -//----------------------------------------------------------------------------- -static void ReadTextData( const char *pSrc, int nSrcSize, CUtlBuffer &buf ) -{ - buf.EnsureCapacity( nSrcSize + 1 ); - const char *pSrcEnd = pSrc + nSrcSize; - for ( const char *pSrcScan = pSrc; pSrcScan < pSrcEnd; ++pSrcScan ) - { - if ( *pSrcScan == '\r' ) - { - if ( pSrcScan[1] == '\n' ) - { - buf.PutChar( '\n' ); - ++pSrcScan; - continue; - } - } - - buf.PutChar( *pSrcScan ); - } - - // Null terminate - buf.PutChar( '\0' ); -} - - -//----------------------------------------------------------------------------- -// Copies text data into a form appropriate for disk -//----------------------------------------------------------------------------- -static void CopyTextData( char *pDst, const char *pSrc, int dstSize, int srcSize ) -{ - const char *pSrcScan = pSrc; - const char *pSrcEnd = pSrc + srcSize; - char *pDstScan = pDst; - -#ifdef _DEBUG - char *pDstEnd = pDst + dstSize; -#endif - - for ( ; pSrcScan < pSrcEnd; pSrcScan++ ) - { - if ( *pSrcScan == '\n' ) - { - *pDstScan = '\r'; - pDstScan++; - *pDstScan = '\n'; - pDstScan++; - } - else - { - *pDstScan = *pSrcScan; - pDstScan++; - } - } - Assert( pSrcScan == pSrcEnd ); - Assert( pDstScan == pDstEnd ); -} - -//----------------------------------------------------------------------------- -// Purpose: Adds a new lump, or overwrites existing one -// Input : *relativename - -// *data - -// length - -//----------------------------------------------------------------------------- -void CZipFile::AddBufferToZip( const char *relativename, void *data, int length, bool bTextMode ) -{ - // Lower case only - char name[512]; - Q_strcpy( name, relativename ); - Q_strlower( name ); - - int dstLength = length; - if ( bTextMode ) - { - dstLength = GetLengthOfBinStringAsText( ( const char * )data, length ); - } - - // See if entry is in list already - CZipEntry e; - e.m_Name = name; - int index = m_Files.Find( e ); - - // If already existing, throw away old data and update data and length - if ( index != m_Files.InvalidIndex() ) - { - CZipEntry *update = &m_Files[ index ]; - if ( update->m_pData ) - { - free( update->m_pData ); - } - - if ( bTextMode ) - { - update->m_pData = malloc( dstLength ); - CopyTextData( ( char * )update->m_pData, ( char * )data, dstLength, length ); - update->m_Length = dstLength; - } - else - { - update->m_pData = malloc( length ); - memcpy( update->m_pData, data, length ); - update->m_Length = length; - } - - if ( m_hDiskCacheWriteFile != INVALID_HANDLE_VALUE ) - { - update->m_DiskCacheOffset = CWin32File::FileTell( m_hDiskCacheWriteFile ); - CWin32File::FileWrite( m_hDiskCacheWriteFile, update->m_pData, update->m_Length ); - free( update->m_pData ); - update->m_pData = NULL; - } - } - else - { - // Create a new entry - e.m_Length = dstLength; - if ( dstLength > 0 ) - { - if ( bTextMode ) - { - e.m_pData = malloc( dstLength ); - CopyTextData( (char *)e.m_pData, ( char * )data, dstLength, length ); - } - else - { - e.m_pData = malloc( length ); - memcpy( e.m_pData, data, length ); - } - - if ( m_hDiskCacheWriteFile != INVALID_HANDLE_VALUE ) - { - e.m_DiskCacheOffset = CWin32File::FileTell( m_hDiskCacheWriteFile ); - CWin32File::FileWrite( m_hDiskCacheWriteFile, e.m_pData, e.m_Length ); - free( e.m_pData ); - e.m_pData = NULL; - } - } - else - { - e.m_pData = NULL; - } - - m_Files.Insert( e ); - } -} - - -//----------------------------------------------------------------------------- -// Reads a file from the zip -//----------------------------------------------------------------------------- -bool CZipFile::ReadFileFromZip( const char *pRelativeName, bool bTextMode, CUtlBuffer &buf ) -{ - // Lower case only - char pName[512]; - Q_strncpy( pName, pRelativeName, 512 ); - Q_strlower( pName ); - - // See if entry is in list already - CZipEntry e; - e.m_Name = pName; - int nIndex = m_Files.Find( e ); - if ( nIndex == m_Files.InvalidIndex() ) - { - // not found - return false; - } - - CZipEntry *pEntry = &m_Files[ nIndex ]; - if ( bTextMode ) - { - buf.SetBufferType( true, false ); - ReadTextData( (char*)pEntry->m_pData, pEntry->m_Length, buf ); - } - else - { - buf.SetBufferType( false, false ); - buf.Put( pEntry->m_pData, pEntry->m_Length ); - } - - return true; -} - -//----------------------------------------------------------------------------- -// Reads a file from the zip -//----------------------------------------------------------------------------- -bool CZipFile::ReadFileFromZip( HANDLE hZipFile, const char *pRelativeName, bool bTextMode, CUtlBuffer &buf ) -{ - // Lower case only - char pName[512]; - Q_strncpy( pName, pRelativeName, 512 ); - Q_strlower( pName ); - - // See if entry is in list already - CZipEntry e; - e.m_Name = pName; - int nIndex = m_Files.Find( e ); - if ( nIndex == m_Files.InvalidIndex() ) - { - // not found - return false; - } - - CZipEntry *pEntry = &m_Files[nIndex]; - - void *pData = malloc( pEntry->m_Length ); - CWin32File::FileSeek( hZipFile, pEntry->m_SourceDiskOffset, FILE_BEGIN ); - if ( !CWin32File::FileRead( hZipFile, pData, pEntry->m_Length ) ) - { - free( pData ); - return false; - } - - if ( bTextMode ) - { - buf.SetBufferType( true, false ); - ReadTextData( (const char *)pData, pEntry->m_Length, buf ); - } - else - { - buf.SetBufferType( false, false ); - buf.Put( pData, pEntry->m_Length ); - } - - free( pData ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Check if a file already exists in the zip. -// Input : *relativename - -//----------------------------------------------------------------------------- -bool CZipFile::FileExistsInZip( const char *pRelativeName ) -{ - // Lower case only - char pName[512]; - Q_strncpy( pName, pRelativeName, 512 ); - Q_strlower( pName ); - - // See if entry is in list already - CZipEntry e; - e.m_Name = pName; - int nIndex = m_Files.Find( e ); - - // If it is, then it exists in the pack! - return nIndex != m_Files.InvalidIndex(); -} - - -//----------------------------------------------------------------------------- -// Purpose: Adds a new file to the zip. -//----------------------------------------------------------------------------- -void CZipFile::AddFileToZip( const char *relativename, const char *fullpath ) -{ - FILE *temp = fopen( fullpath, "rb" ); - if ( !temp ) - return; - - // Determine length - fseek( temp, 0, SEEK_END ); - int size = ftell( temp ); - fseek( temp, 0, SEEK_SET ); - byte *buf = (byte *)malloc( size + 1 ); - - // Read data - fread( buf, size, 1, temp ); - fclose( temp ); - - // Now add as a buffer - AddBufferToZip( relativename, buf, size, false ); - - free( buf ); -} - -//----------------------------------------------------------------------------- -// Purpose: Removes a file from the zip. -//----------------------------------------------------------------------------- -void CZipFile::RemoveFileFromZip( const char *relativename ) -{ - CZipEntry e; - e.m_Name = relativename; - int index = m_Files.Find( e ); - - if ( index != m_Files.InvalidIndex() ) - { - CZipEntry update = m_Files[index]; - m_Files.Remove( update ); - } -} - -//--------------------------------------------------------------- -// Purpose: Calculates how many bytes should be added to the extra field -// to push the start of the file data to the next aligned boundary -// Output: Required padding size -//--------------------------------------------------------------- -unsigned short CZipFile::CalculatePadding( unsigned int filenameLen, unsigned int pos ) -{ - if ( m_AlignmentSize == 0 ) - { - return 0; - } - - unsigned int headerSize = sizeof( ZIP_LocalFileHeader ) + filenameLen; - return (unsigned short)( m_AlignmentSize - ( ( pos + headerSize ) % m_AlignmentSize ) ); -} - -//----------------------------------------------------------------------------- -// Purpose: Create the XZIP identifying comment string -// Output : Length -//----------------------------------------------------------------------------- -int CZipFile::MakeXZipCommentString( char *pCommentString ) -{ - char tempString[XZIP_COMMENT_LENGTH]; - - memset( tempString, 0, sizeof( tempString ) ); - V_snprintf( tempString, sizeof( tempString ), "XZP%c %d", m_bCompatibleFormat ? '1' : '2', m_AlignmentSize ); - if ( pCommentString ) - { - memcpy( pCommentString, tempString, sizeof( tempString ) ); - } - - // expected fixed length - return XZIP_COMMENT_LENGTH; -} - -//----------------------------------------------------------------------------- -// Purpose: An XZIP has its configuration in the ascii comment -//----------------------------------------------------------------------------- -void CZipFile::ParseXZipCommentString( const char *pCommentString ) -{ - if ( !V_strnicmp( pCommentString, "XZP", 3 ) ) - { - m_bCompatibleFormat = true; - if ( pCommentString[3] == '2' ) - { - m_bCompatibleFormat = false; - } - - // parse out the alignement configuration - if ( !m_bForceAlignment ) - { - m_AlignmentSize = 0; - sscanf( pCommentString + 4, "%d", &m_AlignmentSize ); - if ( !IsPowerOfTwo( m_AlignmentSize ) ) - { - m_AlignmentSize = 0; - } - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Calculate the exact size of zip file, with headers and padding -// Output : int -//----------------------------------------------------------------------------- -unsigned int CZipFile::CalculateSize( void ) -{ - unsigned int size = 0; - unsigned int dirHeaders = 0; - for ( int i = m_Files.FirstInorder(); i != m_Files.InvalidIndex(); i = m_Files.NextInorder( i ) ) - { - CZipEntry *e = &m_Files[ i ]; - - if ( e->m_Length == 0 ) - continue; - - // local file header - size += sizeof( ZIP_LocalFileHeader ); - size += strlen( e->m_Name.String() ); - - // every file has a directory header that duplicates the filename - dirHeaders += sizeof( ZIP_FileHeader ) + strlen( e->m_Name.String() ); - - // calculate padding - if ( m_AlignmentSize != 0 ) - { - // round up to next boundary - unsigned int nextBoundary = ( size + m_AlignmentSize ) & ~( m_AlignmentSize - 1 ); - - // the directory header also duplicates the padding - dirHeaders += nextBoundary - size; - - size = nextBoundary; - } - - // data size - size += e->m_Length; - } - - size += dirHeaders; - - // All processed zip files will have a comment string - size += sizeof( ZIP_EndOfCentralDirRecord ) + MakeXZipCommentString( NULL ); - - return size; -} - -//----------------------------------------------------------------------------- -// Purpose: Print a directory of files in the zip -//----------------------------------------------------------------------------- -void CZipFile::PrintDirectory( void ) -{ - for ( int i = m_Files.FirstInorder(); i != m_Files.InvalidIndex(); i = m_Files.NextInorder( i ) ) - { - CZipEntry *e = &m_Files[ i ]; - - Msg( "%s\n", e->m_Name.String() ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: Iterate through directory -//----------------------------------------------------------------------------- -int CZipFile::GetNextFilename( int id, char *pBuffer, int bufferSize, int &fileSize ) -{ - if ( id == -1 ) - { - id = m_Files.FirstInorder(); - } - else - { - id = m_Files.NextInorder( id ); - } - if ( id == m_Files.InvalidIndex() ) - { - // list is empty - return -1; - } - - CZipEntry *e = &m_Files[id]; - - Q_strncpy( pBuffer, e->m_Name.String(), bufferSize ); - fileSize = e->m_Length; - - return id; -} - -//----------------------------------------------------------------------------- -// Purpose: Store data out to disk -//----------------------------------------------------------------------------- -void CZipFile::SaveToDisk( FILE *fout ) -{ - CFileStream stream( fout ); - SaveDirectory( stream ); -} - -void CZipFile::SaveToDisk( HANDLE hOutFile ) -{ - CFileStream stream( hOutFile ); - SaveDirectory( stream ); -} - -//----------------------------------------------------------------------------- -// Purpose: Store data out to a CUtlBuffer -//----------------------------------------------------------------------------- -void CZipFile::SaveToBuffer( CUtlBuffer& buf ) -{ - CBufferStream stream( buf ); - SaveDirectory( stream ); -} - -//----------------------------------------------------------------------------- -// Purpose: Store data back out to a stream (could be CUtlBuffer or filestream) -//----------------------------------------------------------------------------- -void CZipFile::SaveDirectory( IWriteStream& stream ) -{ - void *pPaddingBuffer = NULL; - if ( m_AlignmentSize ) - { - // get a temp buffer for all padding work - pPaddingBuffer = malloc( m_AlignmentSize ); - memset( pPaddingBuffer, 0x00, m_AlignmentSize ); - } - - if ( m_hDiskCacheWriteFile != INVALID_HANDLE_VALUE ) - { - FlushFileBuffers( m_hDiskCacheWriteFile ); - } - - int i; - for ( i = m_Files.FirstInorder(); i != m_Files.InvalidIndex(); i = m_Files.NextInorder( i ) ) - { - CZipEntry *e = &m_Files[i]; - Assert( e ); - - // Fix up the offset - e->m_ZipOffset = stream.Tell(); - - if ( e->m_Length > 0 && ( m_hDiskCacheWriteFile != INVALID_HANDLE_VALUE ) ) - { - // get the data back from the write cache - e->m_pData = malloc( e->m_Length ); - if ( e->m_pData ) - { - CWin32File::FileSeek( m_hDiskCacheWriteFile, e->m_DiskCacheOffset, FILE_BEGIN ); - CWin32File::FileRead( m_hDiskCacheWriteFile, e->m_pData, e->m_Length ); - } - } - - if ( e->m_Length > 0 && e->m_pData != NULL ) - { - ZIP_LocalFileHeader hdr = { 0 }; - hdr.signature = PKID( 3, 4 ); - hdr.versionNeededToExtract = 10; // This is the version that the winzip that I have writes. - hdr.flags = 0; - hdr.compressionMethod = 0; // NO COMPRESSION! - hdr.lastModifiedTime = 0; - hdr.lastModifiedDate = 0; - - CRC32_Init( &e->m_ZipCRC ); - CRC32_ProcessBuffer( &e->m_ZipCRC, e->m_pData, e->m_Length ); - CRC32_Final( &e->m_ZipCRC ); - hdr.crc32 = e->m_ZipCRC; - - const char *pFilename = e->m_Name.String(); - hdr.compressedSize = e->m_Length; - hdr.uncompressedSize = e->m_Length; - hdr.fileNameLength = strlen( pFilename ); - hdr.extraFieldLength = CalculatePadding( hdr.fileNameLength, e->m_ZipOffset ); - int extraFieldLength = hdr.extraFieldLength; - - // Swap header in place - m_Swap.SwapFieldsToTargetEndian( &hdr ); - stream.Put( &hdr, sizeof( hdr ) ); - stream.Put( pFilename, strlen( pFilename ) ); - stream.Put( pPaddingBuffer, extraFieldLength ); - stream.Put( e->m_pData, e->m_Length ); - - if ( m_hDiskCacheWriteFile != INVALID_HANDLE_VALUE ) - { - free( e->m_pData ); - - // temp hackery for the logic below to succeed - e->m_pData = (void*)0xFFFFFFFF; - } - } - } - - if ( m_hDiskCacheWriteFile != INVALID_HANDLE_VALUE ) - { - CWin32File::FileSeek( m_hDiskCacheWriteFile, 0, FILE_END ); - } - - unsigned int centralDirStart = stream.Tell(); - if ( m_AlignmentSize ) - { - // align the central directory starting position - unsigned int newDirStart = AlignValue( centralDirStart, m_AlignmentSize ); - int padLength = newDirStart - centralDirStart; - if ( padLength ) - { - stream.Put( pPaddingBuffer, padLength ); - centralDirStart = newDirStart; - } - } - - int realNumFiles = 0; - for ( i = m_Files.FirstInorder(); i != m_Files.InvalidIndex(); i = m_Files.NextInorder( i ) ) - { - CZipEntry *e = &m_Files[i]; - Assert( e ); - - if ( e->m_Length > 0 && e->m_pData != NULL ) - { - ZIP_FileHeader hdr = { 0 }; - hdr.signature = PKID( 1, 2 ); - hdr.versionMadeBy = 20; // This is the version that the winzip that I have writes. - hdr.versionNeededToExtract = 10; // This is the version that the winzip that I have writes. - hdr.flags = 0; - hdr.compressionMethod = 0; - hdr.lastModifiedTime = 0; - hdr.lastModifiedDate = 0; - hdr.crc32 = e->m_ZipCRC; - - hdr.compressedSize = e->m_Length; - hdr.uncompressedSize = e->m_Length; - hdr.fileNameLength = strlen( e->m_Name.String() ); - hdr.extraFieldLength = CalculatePadding( hdr.fileNameLength, e->m_ZipOffset ); - hdr.fileCommentLength = 0; - hdr.diskNumberStart = 0; - hdr.internalFileAttribs = 0; - hdr.externalFileAttribs = 0; // This is usually something, but zero is OK as if the input came from stdin - hdr.relativeOffsetOfLocalHeader = e->m_ZipOffset; - int extraFieldLength = hdr.extraFieldLength; - - // Swap the header in place - m_Swap.SwapFieldsToTargetEndian( &hdr ); - stream.Put( &hdr, sizeof( hdr ) ); - stream.Put( e->m_Name.String(), strlen( e->m_Name.String() ) ); - if ( m_bCompatibleFormat ) - { - stream.Put( pPaddingBuffer, extraFieldLength ); - } - - realNumFiles++; - - if ( m_hDiskCacheWriteFile != INVALID_HANDLE_VALUE ) - { - // clear out temp hackery - e->m_pData = NULL; - } - } - } - - unsigned int centralDirEnd = stream.Tell(); - if ( m_AlignmentSize ) - { - // align the central directory starting position - unsigned int newDirEnd = AlignValue( centralDirEnd, m_AlignmentSize ); - int padLength = newDirEnd - centralDirEnd; - if ( padLength ) - { - stream.Put( pPaddingBuffer, padLength ); - centralDirEnd = newDirEnd; - } - } - - ZIP_EndOfCentralDirRecord rec = { 0 }; - rec.signature = PKID( 5, 6 ); - rec.numberOfThisDisk = 0; - rec.numberOfTheDiskWithStartOfCentralDirectory = 0; - rec.nCentralDirectoryEntries_ThisDisk = realNumFiles; - rec.nCentralDirectoryEntries_Total = realNumFiles; - rec.centralDirectorySize = centralDirEnd - centralDirStart; - rec.startOfCentralDirOffset = centralDirStart; - - char commentString[128]; - int commentLength = MakeXZipCommentString( commentString ); - rec.commentLength = commentLength; - - // Swap the header in place - m_Swap.SwapFieldsToTargetEndian( &rec ); - stream.Put( &rec, sizeof( rec ) ); - stream.Put( commentString, commentLength ); - - if ( pPaddingBuffer ) - { - free( pPaddingBuffer ); - } -} - -class CZip : public IZip -{ -public: - CZip( const char *pDiskCacheWritePath, bool bSortByName ); - virtual ~CZip(); - - virtual void Reset(); - - // Add a single file to a zip - maintains the zip's previous alignment state - virtual void AddFileToZip( const char *relativename, const char *fullpath ); - - // Whether a file is contained in a zip - maintains alignment - virtual bool FileExistsInZip( const char *pRelativeName ); - - // Reads a file from the zip - maintains alignement - virtual bool ReadFileFromZip( const char *pRelativeName, bool bTextMode, CUtlBuffer &buf ); - virtual bool ReadFileFromZip( HANDLE hZipFile, const char *relativename, bool bTextMode, CUtlBuffer &buf ); - - // Removes a single file from the zip - maintains alignment - virtual void RemoveFileFromZip( const char *relativename ); - - // Gets next filename in zip, for walking the directory - maintains alignment - virtual int GetNextFilename( int id, char *pBuffer, int bufferSize, int &fileSize ); - - // Prints the zip's contents - maintains alignment - virtual void PrintDirectory( void ); - - // Estimate the size of the Zip (including header, padding, etc.) - virtual unsigned int EstimateSize( void ); - - // Add buffer to zip as a file with given name - uses current alignment size, default 0 (no alignment) - virtual void AddBufferToZip( const char *relativename, void *data, int length, bool bTextMode ); - - // Writes out zip file to a buffer - uses current alignment size - // (set by file's previous alignment, or a call to ForceAlignment) - virtual void SaveToBuffer( CUtlBuffer& outbuf ); - - // Writes out zip file to a filestream - uses current alignment size - // (set by file's previous alignment, or a call to ForceAlignment) - virtual void SaveToDisk( FILE *fout ); - virtual void SaveToDisk( HANDLE hOutFile ); - - // Reads a zip file from a buffer into memory - sets current alignment size to - // the file's alignment size, unless overridden by a ForceAlignment call) - virtual void ParseFromBuffer( void *buffer, int bufferlength ); - virtual HANDLE ParseFromDisk( const char *pFilename ); - - // Forces a specific alignment size for all subsequent file operations, overriding files' previous alignment size. - // Return to using files' individual alignment sizes by passing FALSE. - virtual void ForceAlignment( bool aligned, bool bCompatibleFormat, unsigned int alignmentSize ); - - // Sets the endianess of the zip - virtual void SetBigEndian( bool bigEndian ); - virtual void ActivateByteSwapping( bool bActivate ); - - virtual unsigned int GetAlignment(); - -private: - CZipFile m_ZipFile; -}; - -static CUtlLinkedList< CZip* > g_ZipUtils; - -IZip *IZip::CreateZip( const char *pDiskCacheWritePath, bool bSortByName ) -{ - CZip *pZip = new CZip( pDiskCacheWritePath, bSortByName ); - g_ZipUtils.AddToTail( pZip ); - - return pZip; -} - -void IZip::ReleaseZip( IZip *pZip ) -{ - g_ZipUtils.FindAndRemove( (CZip *)pZip ); - - delete ((CZip *)pZip); -} - -CZip::CZip( const char *pDiskCacheWritePath, bool bSortByName ) : m_ZipFile( pDiskCacheWritePath, bSortByName ) -{ - m_ZipFile.Reset(); -} - -CZip::~CZip() -{ -} - -void CZip::SetBigEndian( bool bigEndian ) -{ - m_ZipFile.SetBigEndian( bigEndian ); -} - -void CZip::ActivateByteSwapping( bool bActivate ) -{ - m_ZipFile.ActivateByteSwapping( bActivate ); -} - -void CZip::AddFileToZip( const char *relativename, const char *fullpath ) -{ - m_ZipFile.AddFileToZip( relativename, fullpath ); -} - -bool CZip::FileExistsInZip( const char *pRelativeName ) -{ - return m_ZipFile.FileExistsInZip( pRelativeName ); -} - -bool CZip::ReadFileFromZip( const char *pRelativeName, bool bTextMode, CUtlBuffer &buf ) -{ - return m_ZipFile.ReadFileFromZip( pRelativeName, bTextMode, buf ); -} - -bool CZip::ReadFileFromZip( HANDLE hZipFile, const char *pRelativeName, bool bTextMode, CUtlBuffer &buf ) -{ - return m_ZipFile.ReadFileFromZip( hZipFile, pRelativeName, bTextMode, buf ); -} - -void CZip::RemoveFileFromZip( const char *relativename ) -{ - m_ZipFile.RemoveFileFromZip( relativename ); -} - -int CZip::GetNextFilename( int id, char *pBuffer, int bufferSize, int &fileSize ) -{ - return m_ZipFile.GetNextFilename( id, pBuffer, bufferSize, fileSize ); -} - -void CZip::PrintDirectory( void ) -{ - m_ZipFile.PrintDirectory(); -} - -void CZip::Reset() -{ - m_ZipFile.Reset(); -} - -unsigned int CZip::EstimateSize( void ) -{ - return m_ZipFile.CalculateSize(); -} - -// Add buffer to zip as a file with given name -void CZip::AddBufferToZip( const char *relativename, void *data, int length, bool bTextMode ) -{ - m_ZipFile.AddBufferToZip( relativename, data, length, bTextMode ); -} - -void CZip::SaveToBuffer( CUtlBuffer& outbuf ) -{ - m_ZipFile.SaveToBuffer( outbuf ); -} - -void CZip::SaveToDisk( FILE *fout ) -{ - m_ZipFile.SaveToDisk( fout ); -} - -void CZip::SaveToDisk( HANDLE hOutFile ) -{ - m_ZipFile.SaveToDisk( hOutFile ); -} - -void CZip::ParseFromBuffer( void *buffer, int bufferlength ) -{ - m_ZipFile.Reset(); - m_ZipFile.ParseFromBuffer( buffer, bufferlength ); -} - -HANDLE CZip::ParseFromDisk( const char *pFilename ) -{ - m_ZipFile.Reset(); - return m_ZipFile.ParseFromDisk( pFilename ); -} - -void CZip::ForceAlignment( bool aligned, bool bCompatibleFormat, unsigned int alignmentSize ) -{ - m_ZipFile.ForceAlignment( aligned, bCompatibleFormat, alignmentSize ); -} - -unsigned int CZip::GetAlignment() -{ - return m_ZipFile.GetAlignment(); -} - -#endif // SWDS diff --git a/public/zip_utils.h b/public/zip_utils.h deleted file mode 100644 index 6f9ec0f97..000000000 --- a/public/zip_utils.h +++ /dev/null @@ -1,87 +0,0 @@ -//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//=============================================================================// - -#ifndef ZIP_UTILS_H -#define ZIP_UTILS_H -#ifdef _WIN32 -#pragma once -#endif - -#include "utlsymbol.h" - -class CUtlBuffer; -#include "tier0/dbg.h" - -abstract_class IZip -{ -public: - virtual void Reset() = 0; - - // Add a single file to a zip - maintains the zip's previous alignment state - virtual void AddFileToZip ( const char *relativename, const char *fullpath ) = 0; - - // Whether a file is contained in a zip - maintains alignment - virtual bool FileExistsInZip ( const char *pRelativeName ) = 0; - - // Reads a file from the zip - maintains alignement - virtual bool ReadFileFromZip ( const char *pRelativeName, bool bTextMode, CUtlBuffer &buf ) = 0; -#ifdef _WIN32 - virtual bool ReadFileFromZip ( HANDLE hFile, const char *pRelativeName, bool bTextMode, CUtlBuffer &buf ) = 0; -#endif - - // Removes a single file from the zip - maintains alignment - virtual void RemoveFileFromZip ( const char *relativename ) = 0; - - // Gets next filename in zip, for walking the directory - maintains alignment - virtual int GetNextFilename ( int id, char *pBuffer, int bufferSize, int &fileSize ) = 0; - - // Prints the zip's contents - maintains alignment - virtual void PrintDirectory ( void ) = 0; - - // Estimate the size of the Zip (including header, padding, etc.) - virtual unsigned int EstimateSize ( void ) = 0; - - // Add buffer to zip as a file with given name - uses current alignment size, default 0 (no alignment) - virtual void AddBufferToZip ( const char *relativename, void *data, int length, bool bTextMode ) = 0; - - // Writes out zip file to a buffer - uses current alignment size - // (set by file's previous alignment, or a call to ForceAlignment) - virtual void SaveToBuffer ( CUtlBuffer& outbuf ) = 0; - - // Writes out zip file to a filestream - uses current alignment size - // (set by file's previous alignment, or a call to ForceAlignment) - virtual void SaveToDisk ( FILE *fout ) = 0; -#ifdef _WIN32 - virtual void SaveToDisk ( HANDLE hFileOut ) = 0; -#endif - - // Reads a zip file from a buffer into memory - sets current alignment size to - // the file's alignment size, unless overridden by a ForceAlignment call) - virtual void ParseFromBuffer ( void *buffer, int bufferlength ) = 0; - - // Mounts a zip file from the disk - // Only ReadFileFromZip() is supported because the zip file could be >2GB -#ifdef _WIN32 - virtual HANDLE ParseFromDisk ( const char *pFilename ) = 0; -#endif - - // Forces a specific alignment size for all subsequent file operations, overriding files' previous alignment size. - // Return to using files' individual alignment sizes by passing FALSE. - virtual void ForceAlignment ( bool aligned, bool bCompatibleFormat, unsigned int alignmentSize=0 ) = 0; - - virtual unsigned int GetAlignment() = 0; - - // Sets the endianess of the zip - virtual void SetBigEndian( bool bigEndian ) = 0; - virtual void ActivateByteSwapping( bool bActivate ) = 0; - - // Create/Release additional instances - // Disk Caching is necessary for large zips - static IZip *CreateZip( const char *pDiskCacheWritePath = NULL, bool bSortByName = false ); - static void ReleaseZip( IZip *zip ); -}; - -#endif // ZIP_UTILS_H diff --git a/rcbot/entprops.cpp b/rcbot/entprops.cpp new file mode 100644 index 000000000..79f79ee31 --- /dev/null +++ b/rcbot/entprops.cpp @@ -0,0 +1,2653 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +/** + * vim: set ts=4 : + * ============================================================================= + * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + */ + +#pragma push_macro("clamp") //Fix for C++17 [APG]RoboCop[CL] +#undef clamp +#include +#pragma pop_macro("clamp") + +#include +#include +#include "entprops.h" + +#include +#include +#include +#include + +#include "bot_sm_ext.h" +#include "logging.h" +#include "helper.h" +#include "smsdk_config.h" + +// From game/server/variant_t.h, same on all supported games. +class variant_t +{ +public: + union + { + bool bVal; + string_t iszVal; + int iVal; + float flVal; + float vecVal[3]; + color32 rgbaVal; + }; + + CBaseHandle eVal; + fieldtype_t fieldType; +}; + +enum PropEntType : std::uint8_t +{ + PropEnt_Unknown, + PropEnt_Handle, + PropEnt_Entity, + PropEnt_Edict, + PropEnt_Variant, +}; + +static CBotEntProp s_entprops; +CBotEntProp *entprops = &s_entprops; + +#define SET_TYPE_IF_VARIANT(type) \ + if (td->fieldType == FIELD_CUSTOM && (td->flags & FTYPEDESC_OUTPUT) == FTYPEDESC_OUTPUT) \ + { \ + auto *pVariant = (variant_t *)((std::intptr_t)pEntity + offset); \ + pVariant->fieldType = type; \ + } + +#define PROP_TYPE_SWITCH(type, type_name, returnval) \ + switch (pProp->GetType()) \ + { \ + case type: \ + { \ + if (element != 0) \ + { \ + logger->Log(LogLevel::ERROR, "SendProp %s is not an array. Element %d is invalid.", prop, element); \ + return returnval; \ + } \ + \ + break; \ + } \ + case DPT_Array: \ + { \ + int elementCount = pProp->GetNumElements(); \ + int elementStride = pProp->GetElementStride(); \ + if (element < 0 || element >= elementCount) \ + { \ + logger->Log(LogLevel::ERROR, "Element %d is out of bounds (Prop %s has %d elements).", element, prop, elementCount); \ + return returnval; \ + } \ + \ + pProp = pProp->GetArrayProp(); \ + if (!pProp) { \ + logger->Log(LogLevel::ERROR, "Error looking up ArrayProp for prop %s", prop); \ + return returnval; \ + } \ + \ + if (pProp->GetType() != (type)) \ + { \ + logger->Log(LogLevel::ERROR, "SendProp %s type is not \"integer\" ([%d,%d] != %d)", prop, pProp->GetType(), pProp->m_nBits, type); \ + return returnval; \ + } \ + \ + offset += pProp->GetOffset() + (elementStride * element); \ + bit_count = pProp->m_nBits; \ + break; \ + } \ + case DPT_DataTable: \ + { \ + SendTable *pTable = pProp->GetDataTable(); \ + if (!pTable) \ + { \ + logger->Log(LogLevel::ERROR, "Error looking up DataTable for prop %s", prop); \ + return returnval; \ + } \ + \ + int elementCount = pTable->GetNumProps(); \ + if (element < 0 || element >= elementCount) \ + { \ + logger->Log(LogLevel::ERROR, "Element %d is out of bounds (Prop %s has %d elements).", element, prop, elementCount); \ + return returnval; \ + } \ + \ + pProp = pTable->GetProp(element); \ + if (pProp->GetType() != (type)) \ + { \ + if (pProp->GetType() != (type)) \ + { \ + logger->Log(LogLevel::ERROR, "SendProp %s type is not " type_name " ([%d,%d] != %d)", prop, pProp->GetType(), pProp->m_nBits, type); \ + return returnval; \ + } \ + } \ + \ + offset += pProp->GetOffset(); \ + bit_count = pProp->m_nBits; \ + break; \ + } \ + default: \ + { \ + logger->Log(LogLevel::ERROR, "Invalid SendPropType %d for \"%s\"", pProp->GetType(), prop); \ + return returnval; \ + break; \ + } \ + } + +#define CHECK_TYPE_VALID_IF_VARIANT(type, typeName, returnval) \ + if (td->fieldType == FIELD_CUSTOM && (td->flags & FTYPEDESC_OUTPUT) == FTYPEDESC_OUTPUT) \ + { \ + auto *pVariant = (variant_t *)((std::intptr_t)pEntity + offset); \ + if (pVariant->fieldType != (type)) \ + { \ + logger->Log(LogLevel::ERROR, "Variant value for %s is not a %s (%d)", prop, typeName, pVariant->fieldType); \ + return returnval; \ + } \ + } + +#define CHECK_SET_PROP_DATA_OFFSET(returnval) \ + if (element < 0 || element >= td->fieldSize) \ + { \ + logger->Log(LogLevel::ERROR, "Element %d is out of bounds (Prop %s has %d elements).", element, prop, td->fieldSize); \ + return returnval; \ + } \ + \ + offset = dinfo.actual_offset + (element * (td->fieldSizeInBytes / td->fieldSize)); + +#define GAMERULES_FIND_PROP_SEND(type, type_name, retval) \ + SourceMod::sm_sendprop_info_t info;\ + SendProp *pProp; \ + if (!sm_gamehelpers->FindSendPropInfo(grclassname, prop, &info)) \ + { \ + logger->Log(LogLevel::ERROR, "Property \"%s\" not found on Game Rules", prop); \ + return retval; \ + } \ + \ + offset = info.actual_offset; \ + pProp = info.prop; \ + bit_count = pProp->m_nBits; \ + \ + switch (pProp->GetType()) \ + { \ + case type: \ + { \ + if (element != 0) \ + { \ + return retval; \ + } \ + break; \ + } \ + case DPT_Array: \ + { \ + int elementCount = pProp->GetNumElements(); \ + int elementStride = pProp->GetElementStride(); \ + if (element < 0 || element >= elementCount) \ + { \ + return retval; \ + } \ + \ + pProp = pProp->GetArrayProp(); \ + if (!pProp) { \ + return retval; \ + } \ + \ + if (pProp->GetType() != (type)) \ + { \ + return retval; \ + } \ + \ + offset += pProp->GetOffset() + (elementStride * element); \ + bit_count = pProp->m_nBits; \ + break; \ + } \ + case DPT_DataTable: \ + { \ + GAMERULES_FIND_PROP_SEND_IN_SENDTABLE(info, pProp, element, type, type_name, retval); \ + \ + offset += pProp->GetOffset(); \ + bit_count = pProp->m_nBits; \ + break; \ + } \ + default: \ + { \ + return retval; \ + } \ + } \ + +#define GAMERULES_FIND_PROP_SEND_IN_SENDTABLE(info, pProp, element, type, type_name, retval) \ + SendTable *pTable = (pProp)->GetDataTable(); \ + if (!pTable) \ + { \ + return retval; \ + } \ + \ + int elementCount = pTable->GetNumProps(); \ + if ((element) < 0 || (element) >= elementCount) \ + { \ + return retval; \ + } \ + \ + (pProp) = pTable->GetProp(element); \ + if ((pProp)->GetType() != (type)) \ + { \ + return retval; \ + } + +void CBotEntProp::Init(const bool reset) +{ + if (initialized && !reset) + return; + + SourceMod::IGameConfig *gamedata; + char *error = nullptr; + constexpr std::size_t maxlength = 0; + grclassname = nullptr; + + if (!sm_gameconfs->LoadGameConfigFile("sdktools.games", &gamedata, error, maxlength)) + { + logger->Log(LogLevel::ERROR, "CBotEntProp::Init -- Failed to load sdktools.game from SourceMod gamedata"); + return; + } + + grclassname = gamedata->GetKeyValue("GameRulesProxy"); + + if (!grclassname) + { + logger->Log(LogLevel::ERROR, "CBotEntProp::Init -- Failed to get game rules proxy classname"); + } + else + { + logger->Log(LogLevel::DEBUG, "CBotEntProp::Init -- Retrieved game rules proxy classname \"%s\"", grclassname); + } + + sm_gameconfs->CloseGameConfigFile(gamedata); + initialized = true; + logger->Log(LogLevel::DEBUG, "CBotEntProp::Init done"); +} + +/// @brief Checks if the given entity is a networked entity +/// @param pEntity Entity to check +/// @return true if the entity is networked, false otherwise +bool CBotEntProp::IsNetworkedEntity(CBaseEntity *pEntity) +{ + IServerUnknown *pUnk = reinterpret_cast(pEntity); + const IServerNetworkable *pNet = pUnk->GetNetworkable(); + + if (!pNet) + { + return false; + } + + return true; +} + +bool CBotEntProp::FindSendProp(SourceMod::sm_sendprop_info_t *info, CBaseEntity *pEntity, const char *prop, const int entity) +{ + IServerUnknown *pUnk = reinterpret_cast(pEntity); + IServerNetworkable *pNet = pUnk->GetNetworkable(); + + if (!pNet) + { + logger->Log(LogLevel::ERROR, "Edict %d is not networkable", entity); + return false; + } + + if (!sm_gamehelpers->FindSendPropInfo(pNet->GetServerClass()->GetName(), prop, info)) + { + logger->Log(LogLevel::ERROR, "Failed to look up property \"%s\" for entity %d (%s)", prop, entity, pNet->GetServerClass()->GetName()); + return false; + } + + return true; +} + +/* Given an entity reference or index, fill out a CBaseEntity and/or edict. + If lookup is successful, returns true and writes back the two parameters. + If lookup fails, returns false and doesn't touch the params. */ +bool CBotEntProp::IndexToAThings(const int num, CBaseEntity** pEntData, edict_t** pEdictData) +{ + if (num <= 0) { + logger->Log(LogLevel::ERROR, "Invalid entity reference %d", num); + return false; + } + + CBaseEntity* pEntity = sm_gamehelpers->ReferenceToEntity(num); + + if (!pEntity) + { + logger->Log(LogLevel::ERROR, "ReferenceToEntity(%d) returned nullptr", num); + return false; + } + + const int index = sm_gamehelpers->ReferenceToIndex(num); + if (index > 0 && index <= sm_players->GetMaxClients()) + { + SourceMod::IGamePlayer* pPlayer = sm_players->GetGamePlayer(index); + if (!pPlayer || !pPlayer->IsConnected()) + { + logger->Log(LogLevel::ERROR, "Player %d is not connected", index); + return false; + } + } + + if (pEntData) + { + *pEntData = pEntity; + } + + if (pEdictData) + { + edict_t* pEdict = BaseEntityToEdict(pEntity); + if (!pEdict || pEdict->IsFree()) + { + logger->Log(LogLevel::ERROR, "BaseEntityToEdict returned nullptr or free edict for entity %d", num); + pEdict = nullptr; + } + + *pEdictData = pEdict; + } + + return true; +} + +/// @brief Retrieves an integer value in an entity's property. +/// @param entity Entity/edict index. +/// @param proptype Property type. +/// @param prop Property name. +/// @param size Number of bytes to write (valid values are 1, 2, or 4). This value is auto-detected, and the size parameter is only used as a fallback in case detection fails. +/// @param element Element # (starting from 0) if property is an array. +/// @return Value at the given property offset. +int CBotEntProp::GetEntProp(const int entity, const PropType proptype, const char *prop, const int size, const int element) +{ + edict_t *pEdict; + CBaseEntity *pEntity; + SourceMod::sm_sendprop_info_t info; + SendProp *pProp; + int bit_count; + int offset; + bool is_unsigned = false; + + if (!IndexToAThings(entity, &pEntity, &pEdict)) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return 0; + } + + switch (proptype) + { + case Prop_Data: + typedescription_t *td; + datamap_t *pMap; + + if ((pMap = sm_gamehelpers->GetDataMap(pEntity)) == nullptr) + { + logger->Log(LogLevel::ERROR, "Could not retrieve datamap for %s", pEdict->GetClassName()); + return 0; + } + + SourceMod::sm_datatable_info_t dinfo; + + if (!sm_gamehelpers->FindDataMapInfo(pMap, prop, &dinfo)) + { + const char *classname = sm_gamehelpers->GetEntityClassname(pEntity); + logger->Log(LogLevel::ERROR, "Property \"%s\" not found (entity %d/%s)", prop, entity, (classname ? classname : "")); + return 0; + } + + td = dinfo.prop; + + if ((bit_count = MatchTypeDescAsInteger(td->fieldType, td->flags)) == 0) + { + logger->Log(LogLevel::ERROR, "Data field %s is not an integer (%d)", prop, td->fieldType); + return 0; + } + + CHECK_SET_PROP_DATA_OFFSET(0) + + if (td->fieldType == FIELD_CUSTOM && (td->flags & FTYPEDESC_OUTPUT) == FTYPEDESC_OUTPUT) + { + const variant_t* pVariant = reinterpret_cast(reinterpret_cast(pEntity) + offset); + + if ((bit_count = MatchTypeDescAsInteger(pVariant->fieldType, 0)) == 0) + { + logger->Log(LogLevel::ERROR, "Variant value for %s is not an integer (%d)", prop, pVariant->fieldType); + return 0; + } + } + + break; + + case Prop_Send: + + if (!FindSendProp(&info, pEntity, prop, entity)) + { + logger->Log(LogLevel::ERROR, "Failed to look up \"%s\" property.", prop); + return 0; + } + + offset = info.actual_offset; + pProp = info.prop; + bit_count = pProp->m_nBits; + + //PROP_TYPE_SWITCH(DPT_Int, "integer", 0) + +#if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS \ + || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_TF2 \ + || SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_PVKII + if (pProp->GetFlags() & SPROP_VARINT) + { + bit_count = sizeof(int) * 8; + } + #endif + + is_unsigned = ((pProp->GetFlags() & SPROP_UNSIGNED) == SPROP_UNSIGNED); + + break; + + default: + logger->Log(LogLevel::ERROR, "Invalid PropType %d", proptype); + return 0; + //break; + } + + if (bit_count < 1) + { + bit_count = size * 8; + } + + if (bit_count >= 17) + { + return *reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)); + } + + if (bit_count >= 9) + { + if (is_unsigned) + { + return *reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)); + } + return *reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)); + } + + if (bit_count >= 2) + { + if (is_unsigned) + { + return *(reinterpret_cast(pEntity) + static_cast(offset)); + } + return *reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)); + } + return *reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)) ? 1 : 0; +} + +/// @brief Retrieves an integer pointer in an entity's property. +/// @param entity Entity/edict index. +/// @param proptype Property type. +/// @param prop Property name. +/// @param size Number of bytes to write (valid values are 1, 2, or 4). This value is auto-detected, and the size parameter is only used as a fallback in case detection fails. +/// @param element Element # (starting from 0) if property is an array. +/// @return Pointer at the given property offset. +int *CBotEntProp::GetEntPropPointer(const int entity, const PropType proptype, const char *prop, const int size, const int element) +{ + edict_t *pEdict; + CBaseEntity *pEntity; + SourceMod::sm_sendprop_info_t info; + SendProp *pProp; + int bit_count; + int offset; + bool is_unsigned = false; + + if (!IndexToAThings(entity, &pEntity, &pEdict)) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return nullptr; + } + + switch (proptype) + { + case Prop_Data: + typedescription_t *td; + datamap_t *pMap; + + if ((pMap = sm_gamehelpers->GetDataMap(pEntity)) == nullptr) + { + logger->Log(LogLevel::ERROR, "Could not retrieve datamap for %s", pEdict->GetClassName()); + return nullptr; + } + + SourceMod::sm_datatable_info_t dinfo; + + if (!sm_gamehelpers->FindDataMapInfo(pMap, prop, &dinfo)) + { + const char *classname = sm_gamehelpers->GetEntityClassname(pEntity); + logger->Log(LogLevel::ERROR, "Property \"%s\" not found (entity %d/%s)", prop, entity, (classname ? classname : "")); + return nullptr; + } + + td = dinfo.prop; + + if ((bit_count = MatchTypeDescAsInteger(td->fieldType, td->flags)) == 0) + { + logger->Log(LogLevel::ERROR, "Data field %s is not an integer (%d)", prop, td->fieldType); + return nullptr; + } + + CHECK_SET_PROP_DATA_OFFSET(0) + + if (td->fieldType == FIELD_CUSTOM && (td->flags & FTYPEDESC_OUTPUT) == FTYPEDESC_OUTPUT) + { + const variant_t* pVariant = reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)); + if ((bit_count = MatchTypeDescAsInteger(pVariant->fieldType, 0)) == 0) + { + logger->Log(LogLevel::ERROR, "Variant value for %s is not an integer (%d)", prop, pVariant->fieldType); + return nullptr; + } + } + + break; + + case Prop_Send: + + if (!FindSendProp(&info, pEntity, prop, entity)) + { + logger->Log(LogLevel::ERROR, "Failed to look up \"%s\" property.", prop); + return nullptr; + } + + offset = info.actual_offset; + pProp = info.prop; + bit_count = pProp->m_nBits; + + //PROP_TYPE_SWITCH(DPT_Int, "integer", nullptr) + +#if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS \ + || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_TF2 \ + || SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_PVKII + if (pProp->GetFlags() & SPROP_VARINT) + { + bit_count = sizeof(int) * 8; + } + #endif + + is_unsigned = ((pProp->GetFlags() & SPROP_UNSIGNED) == SPROP_UNSIGNED); + + break; + + default: + logger->Log(LogLevel::ERROR, "Invalid PropType %d", proptype); + return nullptr; + //break; + } + + if (bit_count < 1) + { + bit_count = size * 8; + } + + if (bit_count >= 17) + { + return reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)); + } + + if (bit_count >= 9) + { + uint8_t* base = reinterpret_cast(pEntity) + static_cast(offset); + + assert(reinterpret_cast(base) % alignof(int16_t) == 0 && "Pointer is not properly aligned for 16-bit access"); + return reinterpret_cast(base); + } + + if (bit_count >= 2) + { + if (is_unsigned) + { + return reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)); + } + return reinterpret_cast(reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset))); + } + + return reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)); +} + +/// @brief Retrieves a boolean value in an entity's property. +/// @param entity Entity/edict index. +/// @param proptype Property type. +/// @param prop Property name. +/// @param element Element # (starting from 0) if property is an array. +/// @return Value at the given property offset. +bool CBotEntProp::GetEntPropBool(const int entity, const PropType proptype, const char *prop, const int element) +{ + return GetEntProp(entity, proptype, prop, 1, element) != 0; +} + +/// @brief Retrieves a boolean pointer in an entity's property. +/// @attention This will return nullptr if the property bit_count is higher than 1. Use SourceMod's sm_dump_netprops to double check the property +/// you are accessing has a size of 1. Or just use GetEntPropPointer instead. +/// @param entity Entity/edict index. +/// @param proptype Property type. +/// @param prop Property name. +/// @param element Element # (starting from 0) if property is an array. +/// @return Pointer at the given property offset. +bool *CBotEntProp::GetEntPropBoolPointer(const int entity, const PropType proptype, const char *prop, const int element) +{ + edict_t *pEdict; + CBaseEntity *pEntity; + SourceMod::sm_sendprop_info_t info; + const SendProp *pProp = nullptr; //Unused? [APG]RoboCop[CL] + int bit_count; + int offset; + bool is_unsigned = false; //Unused? [APG]RoboCop[CL] + + if (!IndexToAThings(entity, &pEntity, &pEdict)) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return nullptr; + } + + switch (proptype) + { + case Prop_Data: + typedescription_t *td; + datamap_t *pMap; + + if ((pMap = sm_gamehelpers->GetDataMap(pEntity)) == nullptr) + { + logger->Log(LogLevel::ERROR, "Could not retrieve datamap for %s", pEdict->GetClassName()); + return nullptr; + } + + SourceMod::sm_datatable_info_t dinfo; + + if (!sm_gamehelpers->FindDataMapInfo(pMap, prop, &dinfo)) + { + const char *classname = sm_gamehelpers->GetEntityClassname(pEntity); + + logger->Log(LogLevel::ERROR, "Property \"%s\" not found (entity %d/%s)", prop, entity, (classname ? classname : "")); + return nullptr; + } + + td = dinfo.prop; + + if ((bit_count = MatchTypeDescAsInteger(td->fieldType, td->flags)) == 0) + { + logger->Log(LogLevel::ERROR, "Data field %s is not an integer (%d)", prop, td->fieldType); + return nullptr; + } + + CHECK_SET_PROP_DATA_OFFSET(0) + + if (td->fieldType == FIELD_CUSTOM && (td->flags & FTYPEDESC_OUTPUT) == FTYPEDESC_OUTPUT) + { + const variant_t* pVariant = reinterpret_cast(reinterpret_cast(pEntity) + offset); + + if ((bit_count = MatchTypeDescAsInteger(pVariant->fieldType, 0)) == 0) + { + logger->Log(LogLevel::ERROR, "Variant value for %s is not an integer (%d)", prop, pVariant->fieldType); + return nullptr; + } + } + + break; + + case Prop_Send: + + if (!FindSendProp(&info, pEntity, prop, entity)) + { + logger->Log(LogLevel::ERROR, "Failed to look up \"%s\" property.", prop); + return nullptr; + } + + offset = info.actual_offset; + pProp = info.prop; + bit_count = pProp->m_nBits; + + //PROP_TYPE_SWITCH(DPT_Int, "integer", nullptr) + +#if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS \ + || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_TF2 \ + || SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_PVKII + if (pProp->GetFlags() & SPROP_VARINT) + { + bit_count = sizeof(int) * 8; + } + #endif + + is_unsigned = ((pProp->GetFlags() & SPROP_UNSIGNED) == SPROP_UNSIGNED); // `is_unsigned` unused? [APG]RoboCop[CL] + + break; + + default: + logger->Log(LogLevel::ERROR, "Invalid PropType %d", proptype); + return nullptr; + //break; + } + + if (bit_count < 1) + { + bit_count = 1 * 8; + } + + if (bit_count > 1) + { + logger->Log(LogLevel::ERROR, "Property %s has bit_count %d > 1. Use GetEntPropPointer", prop, bit_count); + return nullptr; + } + return reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)); +} + +/// @brief Sets an integer value in an entity's property. +/// @param entity Entity/edict index. +/// @param proptype Property type. +/// @param prop Property name. +/// @param value Value to set. +/// @param size Number of bytes to write (valid values are 1, 2, or 4). This value is auto-detected, and the size parameter is only used as a fallback in case detection fails. +/// @param element Element # (starting from 0) if property is an array. +/// @return true if the value was changed, false if an error occurred +bool CBotEntProp::SetEntProp(const int entity, const PropType proptype, const char *prop, const int value, const int size, const int element) +{ + edict_t *pEdict; + CBaseEntity *pEntity; + SourceMod::sm_sendprop_info_t info; + const SendProp *pProp = nullptr; //Unused? [APG]RoboCop[CL] + int bit_count; + int offset; + bool is_unsigned = false; //Unused? [APG]RoboCop[CL] + + if (!IndexToAThings(entity, &pEntity, &pEdict)) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return false; + } + + switch (proptype) + { + case Prop_Data: + typedescription_t *td; + datamap_t *pMap; + + if ((pMap = sm_gamehelpers->GetDataMap(pEntity)) == nullptr) + { + logger->Log(LogLevel::ERROR, "Could not retrieve datamap for %s", pEdict->GetClassName()); + return false; + } + + SourceMod::sm_datatable_info_t dinfo; + + if (!sm_gamehelpers->FindDataMapInfo(pMap, prop, &dinfo)) + { + const char *classname = sm_gamehelpers->GetEntityClassname(pEntity); + logger->Log(LogLevel::ERROR, "Property \"%s\" not found (entity %d/%s)", prop, entity, (classname ? classname : "")); + return false; + } + + td = dinfo.prop; + + if ((bit_count = MatchTypeDescAsInteger(td->fieldType, td->flags)) == 0) + { + logger->Log(LogLevel::ERROR, "Data field %s is not an integer (%d)", prop, td->fieldType); + return false; + } + + CHECK_SET_PROP_DATA_OFFSET(false) + + if (td->fieldType == FIELD_CUSTOM && (td->flags & FTYPEDESC_OUTPUT) == FTYPEDESC_OUTPUT) + { + variant_t* pVariant = reinterpret_cast(reinterpret_cast(pEntity) + offset); + // These are the only three int-ish types that variants support. If set to valid one that isn't + // (32-bit) integer, leave it alone. It's probably the intended type. + if (pVariant->fieldType != FIELD_COLOR32 && pVariant->fieldType != FIELD_BOOLEAN) + { + pVariant->fieldType = FIELD_INTEGER; + } + + bit_count = MatchTypeDescAsInteger(pVariant->fieldType, 0); + } + + SET_TYPE_IF_VARIANT(FIELD_INTEGER) + + break; + + case Prop_Send: + + if (!FindSendProp(&info, pEntity, prop, entity)) + { + logger->Log(LogLevel::ERROR, "Failed to look up \"%s\" property.", prop); + return false; + } + + offset = info.actual_offset; + pProp = info.prop; + bit_count = pProp->m_nBits; + + //PROP_TYPE_SWITCH(DPT_Int, "integer", false) + +#if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS \ + || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_TF2 \ + || SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_PVKII + if (pProp->GetFlags() & SPROP_VARINT) + { + bit_count = sizeof(int) * 8; + } + #endif + + is_unsigned = ((pProp->GetFlags() & SPROP_UNSIGNED) == SPROP_UNSIGNED); + + break; + + default: + logger->Log(LogLevel::ERROR, "Invalid PropType %d", proptype); + return false; + //break; + } + + if (bit_count < 1) + { + bit_count = size * 8; + } + + if (bit_count >= 17) + { + *reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)) = value; + } + else if (bit_count >= 9) + { + *reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)) = static_cast(value); + } + else if (bit_count >= 2) + { + *reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)) = static_cast(value); + } + else + { + *reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)) = value ? true : false; + } + + if (proptype == Prop_Send && (pEdict != nullptr)) + { + sm_gamehelpers->SetEdictStateChanged(pEdict, static_cast(offset)); + } + + return true; +} + +/// @brief Sets a float value in an entity's property. +/// @param entity Entity/edict index. +/// @param proptype Property type. +/// @param prop Property name. +/// @param element Element # (starting from 0) if property is an array. +/// @return Value at the given property offset. +float CBotEntProp::GetEntPropFloat(const int entity, const PropType proptype, const char *prop, const int element) +{ + edict_t *pEdict; + CBaseEntity *pEntity; + SourceMod::sm_sendprop_info_t info; + const SendProp *pProp = nullptr; //Unused? [APG]RoboCop[CL] + int bit_count; //Unused? [APG]RoboCop[CL] + int offset; + + if (!IndexToAThings(entity, &pEntity, &pEdict)) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return 0.0f; + } + + switch (proptype) + { + case Prop_Data: + typedescription_t *td; + datamap_t *pMap; + + if ((pMap = sm_gamehelpers->GetDataMap(pEntity)) == nullptr) + { + logger->Log(LogLevel::ERROR, "Could not retrieve datamap for %s", pEdict->GetClassName()); + return 0.0f; + } + + SourceMod::sm_datatable_info_t dinfo; + + if (!sm_gamehelpers->FindDataMapInfo(pMap, prop, &dinfo)) + { + const char *classname = sm_gamehelpers->GetEntityClassname(pEntity); + logger->Log(LogLevel::ERROR, "Property \"%s\" not found (entity %d/%s)", prop, entity, (classname ? classname : "")); + return 0.0f; + } + + td = dinfo.prop; + + CHECK_SET_PROP_DATA_OFFSET(0.0f) + + CHECK_TYPE_VALID_IF_VARIANT(FIELD_FLOAT, "float", 0.0f) + + break; + + case Prop_Send: + + if (!FindSendProp(&info, pEntity, prop, entity)) + { + logger->Log(LogLevel::ERROR, "Failed to look up \"%s\" property.", prop); + return 0.0f; + } + + offset = info.actual_offset; + pProp = info.prop; + bit_count = pProp->m_nBits; // `bit_count` unused? [APG]RoboCop[CL] + + //PROP_TYPE_SWITCH(DPT_Float, "float", 0.0f) + + break; + + default: + logger->Log(LogLevel::ERROR, "Invalid PropType %d", proptype); + return 0.0f; + //break; + } + + return *reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)); +} + +/// @brief Retrieves a float pointer in an entity's property. +/// @param entity Entity/edict index. +/// @param proptype Property type. +/// @param prop Property name. +/// @param element Element # (starting from 0) if property is an array. +/// @return Pointer at the given property offset. +float *CBotEntProp::GetEntPropFloatPointer(const int entity, const PropType proptype, const char *prop, const int element) +{ + edict_t *pEdict; + CBaseEntity *pEntity; + SourceMod::sm_sendprop_info_t info; + const SendProp *pProp = nullptr; //Unused? [APG]RoboCop[CL] + int bit_count; //Unused? [APG]RoboCop[CL] + int offset; + + if (!IndexToAThings(entity, &pEntity, &pEdict)) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return nullptr; + } + + switch (proptype) + { + case Prop_Data: + typedescription_t *td; + datamap_t *pMap; + + if ((pMap = sm_gamehelpers->GetDataMap(pEntity)) == nullptr) + { + logger->Log(LogLevel::ERROR, "Could not retrieve datamap for %s", pEdict->GetClassName()); + return nullptr; + } + + SourceMod::sm_datatable_info_t dinfo; + + if (!sm_gamehelpers->FindDataMapInfo(pMap, prop, &dinfo)) + { + const char *classname = sm_gamehelpers->GetEntityClassname(pEntity); + logger->Log(LogLevel::ERROR, "Property \"%s\" not found (entity %d/%s)", prop, entity, (classname ? classname : "")); + return nullptr; + } + + td = dinfo.prop; + + CHECK_SET_PROP_DATA_OFFSET(nullptr) + + CHECK_TYPE_VALID_IF_VARIANT(FIELD_FLOAT, "float", nullptr) + + break; + + case Prop_Send: + + if (!FindSendProp(&info, pEntity, prop, entity)) + { + logger->Log(LogLevel::ERROR, "Failed to look up \"%s\" property.", prop); + return nullptr; + } + + offset = info.actual_offset; + pProp = info.prop; + bit_count = pProp->m_nBits; // `bit_count` unused? [APG]RoboCop[CL] + + //PROP_TYPE_SWITCH(DPT_Float, "float", nullptr) + + break; + + default: + logger->Log(LogLevel::ERROR, "Invalid PropType %d", proptype); + return nullptr; + //break; + } + + return reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)); +} + +/// @brief Sets a float value in an entity's property. +/// @param entity Entity/edict index. +/// @param proptype Property type. +/// @param prop Property name. +/// @param value Value to set. +/// @param element Element # (starting from 0) if property is an array. +/// @return true if the value was changed, false if an error occurred +bool CBotEntProp::SetEntPropFloat(const int entity, const PropType proptype, const char *prop, const float value, const int element) +{ + edict_t *pEdict; + CBaseEntity *pEntity; + SourceMod::sm_sendprop_info_t info; + const SendProp *pProp = nullptr; //Unused? [APG]RoboCop[CL] + int bit_count; //Unused? [APG]RoboCop[CL] + int offset; + + if (!IndexToAThings(entity, &pEntity, &pEdict)) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return false; + } + + switch (proptype) + { + case Prop_Data: + typedescription_t *td; + datamap_t *pMap; + + if ((pMap = sm_gamehelpers->GetDataMap(pEntity)) == nullptr) + { + logger->Log(LogLevel::ERROR, "Could not retrieve datamap for %s", pEdict->GetClassName()); + return false; + } + + SourceMod::sm_datatable_info_t dinfo; + + if (!sm_gamehelpers->FindDataMapInfo(pMap, prop, &dinfo)) + { + const char *classname = sm_gamehelpers->GetEntityClassname(pEntity); + logger->Log(LogLevel::ERROR, "Property \"%s\" not found (entity %d/%s)", prop, entity, (classname ? classname : "")); + return false; + } + + td = dinfo.prop; + + if (td->fieldType != FIELD_FLOAT + && td->fieldType != FIELD_TIME + && (td->fieldType != FIELD_CUSTOM || (td->flags & FTYPEDESC_OUTPUT) != FTYPEDESC_OUTPUT)) + { + logger->Log(LogLevel::ERROR, "Data field %s is not a float (%d != [%d,%d,%d]", prop, td->fieldType, FIELD_FLOAT, FIELD_TICK, FIELD_CUSTOM); + return false; + } + + CHECK_SET_PROP_DATA_OFFSET(false) + + SET_TYPE_IF_VARIANT(FIELD_FLOAT) + + break; + + case Prop_Send: + + if (!FindSendProp(&info, pEntity, prop, entity)) + { + logger->Log(LogLevel::ERROR, "Failed to look up \"%s\" property.", prop); + return false; + } + + offset = info.actual_offset; + pProp = info.prop; + bit_count = pProp->m_nBits; // `bit_count` unused? [APG]RoboCop[CL] + + //PROP_TYPE_SWITCH(DPT_Float, "float", false) + + break; + + default: + logger->Log(LogLevel::ERROR, "Invalid PropType %d", proptype); + return false; + //break; + } + + *reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)) = value; + + if (proptype == Prop_Send && (pEdict != nullptr)) + { + sm_gamehelpers->SetEdictStateChanged(pEdict, static_cast(offset)); + } + + return true; +} + +/// @brief Retrieves an entity index from an entity's property. +/// @param entity Entity/edict index. +/// @param proptype Property type. +/// @param prop Property name. +/// @param element Element # (starting from 0) if property is an array. +/// @return Entity index at the given property. If there is no entity, or the entity is not valid, then -1 is returned. +int CBotEntProp::GetEntPropEnt(const int entity, const PropType proptype, const char *prop, const int element) +{ + edict_t *pEdict; + CBaseEntity *pEntity; + SourceMod::sm_sendprop_info_t info; + const SendProp *pProp = nullptr; //Unused? [APG]RoboCop[CL] + int bit_count; //Unused? [APG]RoboCop[CL] + int offset; + PropEntType type = PropEnt_Unknown; + + if (!IndexToAThings(entity, &pEntity, &pEdict)) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return -1; + } + + switch (proptype) + { + case Prop_Data: + typedescription_t *td; + datamap_t *pMap; + + if ((pMap = sm_gamehelpers->GetDataMap(pEntity)) == nullptr) + { + logger->Log(LogLevel::ERROR, "Could not retrieve datamap for %s", pEdict->GetClassName()); + return -1; + } + + SourceMod::sm_datatable_info_t dinfo; + + if (!sm_gamehelpers->FindDataMapInfo(pMap, prop, &dinfo)) + { + const char *classname = sm_gamehelpers->GetEntityClassname(pEntity); + logger->Log(LogLevel::ERROR, "Property \"%s\" not found (entity %d/%s)", prop, entity, (classname ? classname : "")); + return -1; + } + + td = dinfo.prop; + + switch (td->fieldType) + { + case FIELD_EHANDLE: + type = PropEnt_Handle; + break; + case FIELD_CLASSPTR: + type = PropEnt_Entity; + break; + case FIELD_EDICT: + type = PropEnt_Edict; + break; + case FIELD_CUSTOM: + if ((td->flags & FTYPEDESC_OUTPUT) == FTYPEDESC_OUTPUT) + { + type = PropEnt_Variant; + } + break; + /*case FIELD_VOID: + break; + case FIELD_FLOAT: + break; + case FIELD_STRING: + break; + case FIELD_VECTOR: + break; + case FIELD_QUATERNION: + break; + case FIELD_INTEGER: + break; + case FIELD_BOOLEAN: + break; + case FIELD_SHORT: + break; + case FIELD_CHARACTER: + break; + case FIELD_COLOR32: + break; + case FIELD_EMBEDDED: + break; + case FIELD_POSITION_VECTOR: + break; + case FIELD_TIME: + break; + case FIELD_TICK: + break; + case FIELD_MODELNAME: + break; + case FIELD_SOUNDNAME: + break; + case FIELD_INPUT: + break; + case FIELD_FUNCTION: + break; + case FIELD_VMATRIX: + break; + case FIELD_VMATRIX_WORLDSPACE: + break; + case FIELD_MATRIX3X4_WORLDSPACE: + break; + case FIELD_INTERVAL: + break; + case FIELD_MODELINDEX: + break; + case FIELD_MATERIALINDEX: + break; + case FIELD_VECTOR2D: + break; + case FIELD_TYPECOUNT: + break;*/ + } + + if (type == PropEnt_Unknown) + { + logger->Log(LogLevel::ERROR, "Data field %s is not an entity nor edict (%d)", prop, td->fieldType); + return -1; + } + + CHECK_SET_PROP_DATA_OFFSET(0) + + CHECK_TYPE_VALID_IF_VARIANT(FIELD_EHANDLE, "ehandle", 0) + + break; + + case Prop_Send: + + type = PropEnt_Handle; + + if (!FindSendProp(&info, pEntity, prop, entity)) + { + logger->Log(LogLevel::ERROR, "Failed to look up \"%s\" property.", prop); + return -1; + } + + offset = info.actual_offset; + pProp = info.prop; + bit_count = pProp->m_nBits; // `bit_count` unused? [APG]RoboCop[CL] + + //PROP_TYPE_SWITCH(DPT_Int, "integer", -1) + + break; + + default: + logger->Log(LogLevel::ERROR, "Invalid PropType %d", proptype); + return -1; + //break; + } + + switch (type) + { + case PropEnt_Handle: + case PropEnt_Variant: + { + CBaseHandle *hndl; + if (type == PropEnt_Handle) + { + hndl = reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)); + } + else // PropEnt_Variant + { + variant_t* pVariant = reinterpret_cast(reinterpret_cast(pEntity) + offset); + + hndl = &pVariant->eVal; + } + + CBaseEntity *pHandleEntity = sm_gamehelpers->ReferenceToEntity(hndl->GetEntryIndex()); + + if (!pHandleEntity || *hndl != reinterpret_cast(pHandleEntity)->GetRefEHandle()) + return -1; + + return sm_gamehelpers->EntityToBCompatRef(pHandleEntity); + } + case PropEnt_Entity: + { + CBaseEntity* pPropEntity = *reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)); + + return sm_gamehelpers->EntityToBCompatRef(pPropEntity); + } + case PropEnt_Edict: + { + edict_t* _pEdict = *reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)); + + if (!_pEdict || _pEdict->IsFree()) + return -1; + + return sm_gamehelpers->IndexOfEdict(_pEdict); + } + } + + return -1; +} + +/// @brief Sets an entity index in an entity's property. +/// @param entity Entity/edict index. +/// @param proptype Property type. +/// @param prop Property name. +/// @param other Entity index to set, or -1 to unset. +/// @param element Element # (starting from 0) if property is an array. +/// @return true if the value was changed, false if an error occurred +bool CBotEntProp::SetEntPropEnt(const int entity, const PropType proptype, const char *prop, const int other, const int element) +{ + edict_t *pEdict; + CBaseEntity *pEntity; + SourceMod::sm_sendprop_info_t info; + const SendProp *pProp = nullptr; //Unused? [APG]RoboCop[CL] + int bit_count; //Unused? [APG]RoboCop[CL] + int offset; + PropEntType type = PropEnt_Unknown; + + if (!IndexToAThings(entity, &pEntity, &pEdict)) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return false; + } + + switch (proptype) + { + case Prop_Data: + typedescription_t *td; + datamap_t *pMap; + + if ((pMap = sm_gamehelpers->GetDataMap(pEntity)) == nullptr) + { + logger->Log(LogLevel::ERROR, "Could not retrieve datamap for %s", pEdict->GetClassName()); + return false; + } + + SourceMod::sm_datatable_info_t dinfo; + + if (!sm_gamehelpers->FindDataMapInfo(pMap, prop, &dinfo)) + { + const char *classname = sm_gamehelpers->GetEntityClassname(pEntity); + logger->Log(LogLevel::ERROR, "Property \"%s\" not found (entity %d/%s)", prop, entity, (classname ? classname : "")); + return false; + } + + td = dinfo.prop; + + switch (td->fieldType) + { + case FIELD_EHANDLE: + type = PropEnt_Handle; + break; + case FIELD_CLASSPTR: + type = PropEnt_Entity; + break; + case FIELD_EDICT: + type = PropEnt_Edict; + break; + case FIELD_CUSTOM: + if ((td->flags & FTYPEDESC_OUTPUT) == FTYPEDESC_OUTPUT) + { + type = PropEnt_Variant; + } + break; + } + + if (type == PropEnt_Unknown) + { + logger->Log(LogLevel::ERROR, "Data field %s is not an entity nor edict (%d)", prop, td->fieldType); + return false; + } + + CHECK_SET_PROP_DATA_OFFSET(false) + + CHECK_TYPE_VALID_IF_VARIANT(FIELD_EHANDLE, "ehandle", false) + + break; + + case Prop_Send: + + type = PropEnt_Handle; + + if (!FindSendProp(&info, pEntity, prop, entity)) + { + logger->Log(LogLevel::ERROR, "Failed to look up \"%s\" property.", prop); + return false; + } + + offset = info.actual_offset; + pProp = info.prop; + bit_count = pProp->m_nBits; // `bit_count` unused? [APG]RoboCop[CL] + + //PROP_TYPE_SWITCH(DPT_Int, "integer", false) + + break; + + default: + logger->Log(LogLevel::ERROR, "Invalid PropType %d", proptype); + return false; + //break; + } + + CBaseEntity *pOther = GetEntity(other); + if (!pOther && other != -1) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(other), other); + return false; + } + + switch (type) + { + case PropEnt_Handle: + case PropEnt_Variant: + { + CBaseHandle *hndl; + if (type == PropEnt_Handle) + { + hndl = reinterpret_cast(reinterpret_cast(pEntity) + offset); + } + else // PropEnt_Variant + { + variant_t* pVariant = reinterpret_cast(reinterpret_cast(pEntity) + offset); + + hndl = &pVariant->eVal; + } + + hndl->Set(reinterpret_cast(pOther)); + + if (proptype == Prop_Send && (pEdict != nullptr)) + { + sm_gamehelpers->SetEdictStateChanged(pEdict, static_cast(offset)); + } + } + + break; + + case PropEnt_Entity: + { + *reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)) = pOther; + + break; + } + + case PropEnt_Edict: + { + edict_t *pOtherEdict = nullptr; + if (pOther) + { + const IServerNetworkable *pNetworkable = reinterpret_cast(pOther)->GetNetworkable(); + if (!pNetworkable) + { + logger->Log(LogLevel::ERROR, "Entity %d does not have a valid edict", sm_gamehelpers->EntityToBCompatRef(pOther)); + return false; + } + + pOtherEdict = pNetworkable->GetEdict(); + if (!pOtherEdict || pOtherEdict->IsFree()) + { + logger->Log(LogLevel::ERROR, "Entity %d does not have a valid edict", sm_gamehelpers->EntityToBCompatRef(pOther)); + return false; + } + } + + *reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)) = pOtherEdict; + + break; + } + //case PropEnt_Unknown: + // break; + } + + return true; +} + +/// @brief Retrieves a vector of floats from an entity, given a named network property. +/// @param entity Entity/edict index. +/// @param proptype Property type. +/// @param prop Property name. +/// @param element Element # (starting from 0) if property is an array. +/// @return Value at the given property offset. +Vector CBotEntProp::GetEntPropVector(const int entity, const PropType proptype, const char *prop, const int element) +{ + edict_t *pEdict; + CBaseEntity *pEntity; + SourceMod::sm_sendprop_info_t info; + const SendProp *pProp = nullptr; //Unused? [APG]RoboCop[CL] + int bit_count; //Unused? [APG]RoboCop[CL] + int offset; + bool is_unsigned = false; //Unused? [APG]RoboCop[CL] + + if (!IndexToAThings(entity, &pEntity, &pEdict)) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return {0,0,0}; + } + + switch (proptype) + { + case Prop_Data: + typedescription_t *td; + datamap_t *pMap; + + if ((pMap = sm_gamehelpers->GetDataMap(pEntity)) == nullptr) + { + logger->Log(LogLevel::ERROR, "Could not retrieve datamap for %s", pEdict->GetClassName()); + return {0,0,0}; + } + + SourceMod::sm_datatable_info_t dinfo; + + if (!sm_gamehelpers->FindDataMapInfo(pMap, prop, &dinfo)) + { + const char *classname = sm_gamehelpers->GetEntityClassname(pEntity); + logger->Log(LogLevel::ERROR, "Property \"%s\" not found (entity %d/%s)", prop, entity, (classname ? classname : "")); + return {0,0,0}; + } + + td = dinfo.prop; + + if (td->fieldType != FIELD_VECTOR && td->fieldType != FIELD_POSITION_VECTOR) + { + logger->Log(LogLevel::ERROR, "Data field %s is not a vector (%d != [%d,%d])", prop, td->fieldType, FIELD_VECTOR, FIELD_POSITION_VECTOR); + return {0,0,0}; + } + + CHECK_SET_PROP_DATA_OFFSET(Vector(0,0,0)) + + if (td->fieldType == FIELD_CUSTOM && (td->flags & FTYPEDESC_OUTPUT) == FTYPEDESC_OUTPUT) + { + const variant_t* pVariant = reinterpret_cast(reinterpret_cast(pEntity) + offset); + + if (pVariant->fieldType != FIELD_VECTOR && pVariant->fieldType != FIELD_POSITION_VECTOR) + { + logger->Log(LogLevel::ERROR, "Variant value for %s is not vector (%d)", prop, pVariant->fieldType); + return {0,0,0}; + } + } + + break; + + case Prop_Send: + + if (!FindSendProp(&info, pEntity, prop, entity)) + { + logger->Log(LogLevel::ERROR, "Failed to look up \"%s\" property.", prop); + return {0,0,0}; + } + + offset = info.actual_offset; + pProp = info.prop; + bit_count = pProp->m_nBits; // `bit_count` unused? [APG]RoboCop[CL] + + //PROP_TYPE_SWITCH(DPT_Vector, "vector", Vector(0,0,0)) + + break; + + default: + logger->Log(LogLevel::ERROR, "Invalid PropType %d", proptype); + return {0,0,0}; + //break; + } + + Vector* v = reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)); + + return *v; +} + +/// @brief Retrieves a vector from an entity, given a named network property. +/// @param entity Entity/edict index. +/// @param proptype Property type. +/// @param prop Property name. +/// @param element Element # (starting from 0) if property is an array. +/// @return Vector pointer from the property +Vector *CBotEntProp::GetEntPropVectorPointer(const int entity, const PropType proptype, const char *prop, const int element) +{ + edict_t *pEdict; + CBaseEntity *pEntity; + SourceMod::sm_sendprop_info_t info; + const SendProp *pProp = nullptr; //Unused? [APG]RoboCop[CL] + int bit_count; //Unused? [APG]RoboCop[CL] + int offset; + bool is_unsigned = false; //Unused? [APG]RoboCop[CL] + + if (!IndexToAThings(entity, &pEntity, &pEdict)) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return nullptr; + } + + switch (proptype) + { + case Prop_Data: + typedescription_t *td; + datamap_t *pMap; + + if ((pMap = sm_gamehelpers->GetDataMap(pEntity)) == nullptr) + { + logger->Log(LogLevel::ERROR, "Could not retrieve datamap for %s", pEdict->GetClassName()); + return nullptr; + } + + SourceMod::sm_datatable_info_t dinfo; + + if (!sm_gamehelpers->FindDataMapInfo(pMap, prop, &dinfo)) + { + const char *classname = sm_gamehelpers->GetEntityClassname(pEntity); + logger->Log(LogLevel::ERROR, "Property \"%s\" not found (entity %d/%s)", prop, entity, (classname ? classname : "")); + return nullptr; + } + + td = dinfo.prop; + + if (td->fieldType != FIELD_VECTOR && td->fieldType != FIELD_POSITION_VECTOR) + { + logger->Log(LogLevel::ERROR, "Data field %s is not a vector (%d != [%d,%d])", prop, td->fieldType, FIELD_VECTOR, FIELD_POSITION_VECTOR); + return nullptr; + } + + CHECK_SET_PROP_DATA_OFFSET(nullptr) + + if (td->fieldType == FIELD_CUSTOM && (td->flags & FTYPEDESC_OUTPUT) == FTYPEDESC_OUTPUT) + { + const variant_t* pVariant = reinterpret_cast(reinterpret_cast(pEntity) + offset); + + if (pVariant->fieldType != FIELD_VECTOR && pVariant->fieldType != FIELD_POSITION_VECTOR) + { + logger->Log(LogLevel::ERROR, "Variant value for %s is not vector (%d)", prop, pVariant->fieldType); + return nullptr; + } + } + + break; + + case Prop_Send: + + if (!FindSendProp(&info, pEntity, prop, entity)) + { + logger->Log(LogLevel::ERROR, "Failed to look up \"%s\" property.", prop); + return nullptr; + } + + offset = info.actual_offset; + pProp = info.prop; + bit_count = pProp->m_nBits; // `bit_count` unused? [APG]RoboCop[CL] + + //PROP_TYPE_SWITCH(DPT_Vector, "vector", nullptr) + + break; + + default: + logger->Log(LogLevel::ERROR, "Invalid PropType %d", proptype); + return nullptr; + //break; + } + + Vector* v = reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)); + + return v; +} + +/// @brief Sets a vector of floats in an entity, given a named network property. +/// @param entity Entity/edict index. +/// @param proptype Property type. +/// @param prop Property name. +/// @param value Vector to set. +/// @param element Element # (starting from 0) if property is an array. +/// @return true if the value was changed, false if an error occurred +bool CBotEntProp::SetEntPropVector(const int entity, const PropType proptype, const char *prop, const Vector& value, const int element) +{ + edict_t *pEdict; + CBaseEntity *pEntity; + SourceMod::sm_sendprop_info_t info; + const SendProp *pProp = nullptr; //Unused? [APG]RoboCop[CL] + int bit_count; //Unused? [APG]RoboCop[CL] + int offset; + bool is_unsigned = false; //Unused? [APG]RoboCop[CL] + + if (!IndexToAThings(entity, &pEntity, &pEdict)) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return false; + } + + switch (proptype) + { + case Prop_Data: + typedescription_t *td; + datamap_t *pMap; + + if ((pMap = sm_gamehelpers->GetDataMap(pEntity)) == nullptr) + { + logger->Log(LogLevel::ERROR, "Could not retrieve datamap for %s", pEdict->GetClassName()); + return false; + } + + SourceMod::sm_datatable_info_t dinfo; + + if (!sm_gamehelpers->FindDataMapInfo(pMap, prop, &dinfo)) + { + const char *classname = sm_gamehelpers->GetEntityClassname(pEntity); + logger->Log(LogLevel::ERROR, "Property \"%s\" not found (entity %d/%s)", prop, entity, (classname ? classname : "")); + return false; + } + + td = dinfo.prop; + + if (td->fieldType != FIELD_VECTOR && td->fieldType != FIELD_POSITION_VECTOR) + { + logger->Log(LogLevel::ERROR, "Data field %s is not a vector (%d != [%d,%d])", prop, td->fieldType, FIELD_VECTOR, FIELD_POSITION_VECTOR); + return false; + } + + CHECK_SET_PROP_DATA_OFFSET(false) + + if (td->fieldType == FIELD_CUSTOM && (td->flags & FTYPEDESC_OUTPUT) == FTYPEDESC_OUTPUT) + { + variant_t* pVariant = reinterpret_cast(reinterpret_cast(pEntity) + offset); + + // Both of these are supported and we don't know which is intended. But, if it's already + // a pos vector, we probably want to keep that. + if (pVariant->fieldType != FIELD_POSITION_VECTOR) + { + pVariant->fieldType = FIELD_VECTOR; + } + } + + break; + + case Prop_Send: + + if (!FindSendProp(&info, pEntity, prop, entity)) + { + logger->Log(LogLevel::ERROR, "Failed to look up \"%s\" property.", prop); + return false; + } + + offset = info.actual_offset; + pProp = info.prop; + bit_count = pProp->m_nBits; //Unused? [APG]RoboCop[CL] + + //PROP_TYPE_SWITCH(DPT_Vector, "vector", false) + + break; + + default: + logger->Log(LogLevel::ERROR, "Invalid PropType %d", proptype); + return false; + //break; + } + + Vector* v = reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)); + + *v = value; + + if (proptype == Prop_Send && (pEdict != nullptr)) + { + sm_gamehelpers->SetEdictStateChanged(pEdict, static_cast(offset)); + } + + return true; +} + +/// @brief Gets a network property as a string. +/// @param entity Edict index. +/// @param proptype Property type. +/// @param prop Property to use. +/// @param maxlen +/// @param len +/// @param element Element # (starting from 0) if property is an array. +/// @return Value at the given property offset. +char *CBotEntProp::GetEntPropString(const int entity, const PropType proptype, const char *prop, const int maxlen, std::size_t *len, const int element) +{ + edict_t *pEdict; + CBaseEntity *pEntity; + SourceMod::sm_sendprop_info_t info; + const SendProp *pProp = nullptr; //Unused? [APG]RoboCop[CL] + int bit_count; //Unused? [APG]RoboCop[CL] + int offset; + const char *src; + char *dest = nullptr; + bool bIsStringIndex = false; //Unused? [APG]RoboCop[CL] + + if (!IndexToAThings(entity, &pEntity, &pEdict)) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return nullptr; + } + + switch (proptype) + { + case Prop_Data: + typedescription_t *td; + datamap_t *pMap; + + if ((pMap = sm_gamehelpers->GetDataMap(pEntity)) == nullptr) + { + logger->Log(LogLevel::ERROR, "Could not retrieve datamap for %s", pEdict->GetClassName()); + return nullptr; + } + + SourceMod::sm_datatable_info_t dinfo; + + if (!sm_gamehelpers->FindDataMapInfo(pMap, prop, &dinfo)) + { + const char *classname = sm_gamehelpers->GetEntityClassname(pEntity); + logger->Log(LogLevel::ERROR, "Property \"%s\" not found (entity %d/%s)", prop, entity, (classname ? classname : "")); + return nullptr; + } + + td = dinfo.prop; + + if ((td->fieldType != FIELD_CHARACTER + && td->fieldType != FIELD_STRING + && td->fieldType != FIELD_MODELNAME + && td->fieldType != FIELD_SOUNDNAME) + || (td->fieldType == FIELD_CUSTOM && (td->flags & FTYPEDESC_OUTPUT) != FTYPEDESC_OUTPUT)) + { + logger->Log(LogLevel::ERROR, "Data field %s is not a string (%d != %d)", prop, td->fieldType, FIELD_CHARACTER); + return nullptr; + } + + bIsStringIndex = (td->fieldType != FIELD_CHARACTER); + + if (element != 0) + { + if (bIsStringIndex) + { + if (element < 0 || element >= td->fieldSize) + { + logger->Log(LogLevel::ERROR, "Element %d is out of bounds (Prop %s has %d elements).", element, prop, td->fieldSize); + return nullptr; + } + } + else + { + logger->Log(LogLevel::ERROR, "Prop %s is not an array. Element %d is invalid.", prop, element); + return nullptr; + } + } + + offset = dinfo.actual_offset; + + if (bIsStringIndex) + { + offset += (element * (td->fieldSizeInBytes / td->fieldSize)); + + const string_t idx = *reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)); + + src = (idx == NULL_STRING) ? "" : STRING(idx); + } + else + { + src = reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)); + } + + break; + + case Prop_Send: + + if (!FindSendProp(&info, pEntity, prop, entity)) + { + logger->Log(LogLevel::ERROR, "Failed to look up \"%s\" property.", prop); + return nullptr; + } + + offset = info.actual_offset; + pProp = info.prop; + bit_count = pProp->m_nBits; // `bit_count` unused? [APG]RoboCop[CL] + + //PROP_TYPE_SWITCH(DPT_String, "string", nullptr) + + if (pProp->GetProxyFn()) + { + DVariant var; + + pProp->GetProxyFn()(pProp, pEntity,reinterpret_cast(reinterpret_cast(pEntity) + offset), &var, element, entity); + + src = var.m_pString; // hack because SDK 2013 declares this as const char* + } + else + { + src = *reinterpret_cast(reinterpret_cast(pEntity) + static_cast(offset)); + } + + break; + + default: + logger->Log(LogLevel::ERROR, "Invalid PropType %d", proptype); + return nullptr; + //break; + } + + const std::size_t length = ke::SafeStrcpy(dest, static_cast(maxlen), src); + + *len = length; + + return dest; +} + + +/// @brief Sets a network property as a string. +/// @warning This is not implemented yet! +bool CBotEntProp::SetEntPropString(int entity, PropType proptype, const char *prop, const char *value, int element) +{ + logger->Log(LogLevel::ERROR, "SetEntPropString is not supported for now"); + return false; + +#if false // Not supported for now + + edict_t *pEdict; + CBaseEntity *pEntity; + SourceMod::sm_sendprop_info_t info; + SendProp *pProp = nullptr; + int bit_count; + int offset; + int maxlen; + bool bIsStringIndex = false; + + if (!IndexToAThings(entity, &pEntity, &pEdict)) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return false; + } + + switch (proptype) + { + case Prop_Data: + typedescription_t *td; + datamap_t *pMap; + + if ((pMap = sm_gamehelpers->GetDataMap(pEntity)) == NULL) + { + logger->Log(LogLevel::ERROR, "Could not retrieve datamap for %s", pEdict->GetClassName()); + return false; + } + + SourceMod::sm_datatable_info_t dinfo; + + if (!sm_gamehelpers->FindDataMapInfo(pMap, prop, &dinfo)) + { + const char *classname = sm_gamehelpers->GetEntityClassname(pEntity); + logger->Log(LogLevel::ERROR, "Property \"%s\" not found (entity %d/%s)", prop, entity, (classname ? classname : "")); + return false; + } + + td = dinfo.prop; + + if ((td->fieldType != FIELD_CHARACTER + && td->fieldType != FIELD_STRING + && td->fieldType != FIELD_MODELNAME + && td->fieldType != FIELD_SOUNDNAME) + || (td->fieldType == FIELD_CUSTOM && (td->flags & FTYPEDESC_OUTPUT) != FTYPEDESC_OUTPUT)) + { + logger->Log(LogLevel::ERROR, "Data field %s is not a string (%d != %d)", prop, td->fieldType, FIELD_CHARACTER); + return false; + } + + bIsStringIndex = (td->fieldType != FIELD_CHARACTER); + + if (element != 0) + { + if (bIsStringIndex) + { + if (element < 0 || element >= td->fieldSize) + { + logger->Log(LogLevel::ERROR, "Element %d is out of bounds (Prop %s has %d elements).", element, prop, td->fieldSize); + return false; + } + } + else + { + logger->Log(LogLevel::ERROR, "Prop %s is not an array. Element %d is invalid.", prop, element); + return false; + } + } + + offset = dinfo.actual_offset; + + if (bIsStringIndex) + { + offset += (element * (td->fieldSizeInBytes / td->fieldSize)); + } + else + { + maxlen = td->fieldSize; + } + + SET_TYPE_IF_VARIANT(FIELD_STRING); + + break; + + case Prop_Send: + + if (!FindSendProp(&info, pEntity, prop, entity)) + { + logger->Log(LogLevel::ERROR, "Failed to look up \"%s\" property.", prop); + return false; + } + + offset = info.actual_offset; + pProp = info.prop; + bit_count = pProp->m_nBits; + + PROP_TYPE_SWITCH(DPT_String, "string", false); + + bIsStringIndex = false; + if (pProp->GetProxyFn()) + { + DVariant var; + pProp->GetProxyFn()(pProp, pEntity, (const void *) ((std::intptr_t) pEntity + offset), &var, element, entity); + if (var.m_pString == ((string_t *) ((std::intptr_t) pEntity + offset))->ToCStr()) + { + bIsStringIndex = true; + } + } + + // Only used if not string index. + maxlen = DT_MAX_STRING_BUFFERSIZE; + + break; + + default: + logger->Log(LogLevel::ERROR, "Invalid PropType %d", proptype); + return false; + break; + } + + std::size_t len; + + if (bIsStringIndex) + { + *(string_t *) ((std::intptr_t) pEntity + offset) = g_HL2.AllocPooledString(value); + len = strlen(value); + } + else + { + char *dest = (char *) ((uint8_t *) pEntity + offset); + len = ke::SafeStrcpy(dest, maxlen, value); + } + + if (proptype == Prop_Send && (pEdict != NULL)) + { + g_HL2.SetEdictStateChanged(pEdict, offset); + } + + return true; + +#endif +} + +/// @brief Peeks into an entity's object data and retrieves the integer value at the given offset. +/// @param entity Edict index. +/// @param offset Offset to use. +/// @param size Number of bytes to read (valid values are 1, 2, or 4). +/// @return Value at the given memory location. +int CBotEntProp::GetEntData(const int entity, const int offset, const int size) +{ + CBaseEntity *pEntity = GetEntity(entity); + + if (!pEntity) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return 0; + } + + if (offset <= 0 || offset > 32768) + { + logger->Log(LogLevel::ERROR, "Offset %d is invalid", offset); + return 0; + } + + switch (size) + { + case 4: + return *reinterpret_cast(reinterpret_cast(pEntity) + offset); + case 2: + return *reinterpret_cast(reinterpret_cast(pEntity) + offset); + case 1: + return *(reinterpret_cast(pEntity) + offset); + default: + logger->Log(LogLevel::ERROR, "Integer size %d is invalid", size); + return 0; + } +} + +/// @brief Peeks into an entity's object data and sets the integer value at the given offset. +/// @param entity Edict index. +/// @param offset Offset to use. +/// @param value Value to set. +/// @param size Number of bytes to write (valid values are 1, 2, or 4). +/// @param changeState If true, change will be sent over the network. +/// @return true on success, false on failure +bool CBotEntProp::SetEntData(const int entity, const int offset, const int value, const int size, const bool changeState) +{ + CBaseEntity *pEntity; + edict_t *pEdict; + + if (!IndexToAThings(entity, &pEntity, &pEdict)) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return false; + } + + if (offset <= 0 || offset > 32768) + { + logger->Log(LogLevel::ERROR, "Offset %d is invalid", offset); + return false; + } + + if (changeState && (pEdict != nullptr)) + { + sm_gamehelpers->SetEdictStateChanged(pEdict, static_cast(offset)); + } + + switch (size) + { + case 4: + { + *reinterpret_cast(reinterpret_cast(pEntity) + offset) = value; + break; + } + case 2: + { + *reinterpret_cast(reinterpret_cast(pEntity) + offset) = static_cast(value); + break; + } + case 1: + { + *(reinterpret_cast(pEntity) + offset) = static_cast(value); + break; + } + default: + logger->Log(LogLevel::ERROR, "Integer size %d is invalid", size); + return false; + } + + return true; +} + +/// @brief Peeks into an entity's object data and retrieves the float value at the given offset. +/// @param entity Edict index. +/// @param offset Offset to use. +/// @return Value at the given memory location. +float CBotEntProp::GetEntDataFloat(const int entity, const int offset) +{ + CBaseEntity *pEntity = GetEntity(entity); + + if (!pEntity) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return 0.0f; + } + + if (offset <= 0 || offset > 32768) + { + logger->Log(LogLevel::ERROR, "Offset %d is invalid", offset); + return 0.0f; + } + + return *reinterpret_cast(reinterpret_cast(pEntity) + offset); +} + +/// @brief Peeks into an entity's object data and sets the float value at the given offset. +/// @param entity Edict index. +/// @param offset Offset to use. +/// @param value Value to set. +/// @param changeState If true, change will be sent over the network. +/// @return true on success, false on failure +bool CBotEntProp::SetEntDataFloat(const int entity, const int offset, const float value, const bool changeState) +{ + CBaseEntity *pEntity; + edict_t *pEdict; + + if (!IndexToAThings(entity, &pEntity, &pEdict)) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return false; + } + + if (offset <= 0 || offset > 32768) + { + logger->Log(LogLevel::ERROR, "Offset %d is invalid", offset); + return false; + } + + *reinterpret_cast(reinterpret_cast(pEntity) + offset) = value; + + if (changeState && (pEdict != nullptr)) + { + sm_gamehelpers->SetEdictStateChanged(pEdict, static_cast(offset)); + } + + return true; +} + +/// @brief Peeks into an entity's object data and retrieves the entity index at the given offset. +/// Note: This will only work on offsets that are stored as "entity +/// handles" (which usually looks like m_h* in properties). These +/// are not SourceMod Handles, but internal Source structures. +/// @param entity Edict index. +/// @param offset Offset to use. +/// @return Entity index at the given location. If there is no entity, or the stored entity is invalid, then -1 is returned. +int CBotEntProp::GetEntDataEnt(const int entity, const int offset) +{ + CBaseEntity *pEntity = GetEntity(entity); + + if (!pEntity) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return -1; + } + + if (offset <= 0 || offset > 32768) + { + logger->Log(LogLevel::ERROR, "Offset %d is invalid", offset); + return -1; + } + + const CBaseHandle &hndl = *reinterpret_cast(reinterpret_cast(pEntity) + offset); + CBaseEntity *pHandleEntity = sm_gamehelpers->ReferenceToEntity(hndl.GetEntryIndex()); + + if (!pHandleEntity || hndl != reinterpret_cast(pHandleEntity)->GetRefEHandle()) + return -1; + + return sm_gamehelpers->EntityToBCompatRef(pHandleEntity); +} + +/// @brief Peeks into an entity's object data and sets the entity index at the given offset. +/// Note: This will only work on offsets that are stored as "entity +/// handles" (which usually looks like m_h* in properties). These +/// are not SourceMod Handles, but internal Source structures. +/// @param entity Edict index. +/// @param offset Offset to use. +/// @param value Entity index to set, or -1 to clear. +/// @param changeState If true, change will be sent over the network. +/// @return true on success, false on failure +bool CBotEntProp::SetEntDataEnt(const int entity, const int offset, const int value, const bool changeState) +{ + CBaseEntity *pEntity; + edict_t *pEdict; + + if (!IndexToAThings(entity, &pEntity, &pEdict)) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return false; + } + + if (offset <= 0 || offset > 32768) + { + logger->Log(LogLevel::ERROR, "Offset %d is invalid", offset); + return false; + } + + CBaseHandle &hndl = *reinterpret_cast(reinterpret_cast(pEntity) + offset); + + if (static_cast(value) == INVALID_EHANDLE_INDEX) + { + hndl.Set(nullptr); + } + else + { + CBaseEntity *pOther = GetEntity(value); + + if (!pOther) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(value), value); + return false; + } + + const IHandleEntity *pHandleEnt = reinterpret_cast(pOther); + hndl.Set(pHandleEnt); + } + + if (changeState && (pEdict != nullptr)) + { + sm_gamehelpers->SetEdictStateChanged(pEdict, static_cast(offset)); + } + + return true; +} + +/// @brief Peeks into an entity's object data and retrieves the vector at the given offset. +/// @param entity Edict index. +/// @param offset Offset to use. +/// @return Vector value at the given memory location. +Vector CBotEntProp::GetEntDataVector(const int entity, const int offset) +{ + CBaseEntity *pEntity = GetEntity(entity); + + if (!pEntity) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return {0,0,0}; + } + + if (offset <= 0 || offset > 32768) + { + logger->Log(LogLevel::ERROR, "Offset %d is invalid", offset); + return {0,0,0}; + } + + Vector *v = reinterpret_cast(reinterpret_cast(pEntity) + offset); + + return *v; +} + +/// @brief Peeks into an entity's object data and sets the vector at the given offset. +/// @param entity Edict index. +/// @param offset Offset to use. +/// @param value Vector to set. +/// @param changeState If true, change will be sent over the network. +/// @return true on success, false on failure +bool CBotEntProp::SetEntDataVector(const int entity, const int offset, const Vector& value, const bool changeState) +{ + CBaseEntity *pEntity; + edict_t *pEdict; + + if (!IndexToAThings(entity, &pEntity, &pEdict)) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return false; + } + + if (offset <= 0 || offset > 32768) + { + logger->Log(LogLevel::ERROR, "Offset %d is invalid", offset); + return false; + } + + Vector *v = reinterpret_cast(reinterpret_cast(pEntity) + offset); + + *v = value; + + if (changeState && (pEdict != nullptr)) + { + sm_gamehelpers->SetEdictStateChanged(pEdict, static_cast(offset)); + } + + return true; +} + +/// @brief Peeks into an entity's object data and retrieves the string at the given offset. +/// @param entity Edict index. +/// @param offset Offset to use. +/// @param maxlen Maximum length of output string buffer. +/// @param len Number of non-null bytes written. +/// @return String pointer at the given memory location. +char *CBotEntProp::GetEntDataString(const int entity, const int offset, const int maxlen, std::size_t *len) +{ + CBaseEntity *pEntity = GetEntity(entity); + + if (!pEntity) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return nullptr; + } + + if (offset <= 0 || offset > 32768) + { + logger->Log(LogLevel::ERROR, "Offset %d is invalid", offset); + return nullptr; + } + + if (maxlen <= 0) + { + logger->Log(LogLevel::ERROR, "String length should be at least 1, is %d", maxlen); + return nullptr; + } + + const char *src = reinterpret_cast(reinterpret_cast(pEntity) + offset); + char *dest = nullptr; + + const std::size_t length = ke::SafeStrcpy(dest, static_cast(maxlen), src); + + *len = length; + + return dest; +} + +/// @brief +/// @param entity Edict index. +/// @param offset Offset to use. +/// @param value String to set. +/// @param maxlen Maximum length of output string buffer. +/// @param changeState If true, change will be sent over the network. +/// @return true on success, false on failure +bool CBotEntProp::SetEntDataString(const int entity, const int offset, const char *value, const int maxlen, const bool changeState) +{ + CBaseEntity *pEntity; + edict_t *pEdict; + + if (!IndexToAThings(entity, &pEntity, &pEdict)) + { + logger->Log(LogLevel::ERROR, "Entity %d (%d) is invalid", sm_gamehelpers->ReferenceToIndex(entity), entity); + return false; + } + + if (offset <= 0 || offset > 32768) + { + logger->Log(LogLevel::ERROR, "Offset %d is invalid", offset); + return false; + } + + const char *src = nullptr; + char *dest = reinterpret_cast(reinterpret_cast(pEntity) + offset); + + ke::SafeStrcpy(dest, static_cast(maxlen), src); + + if (changeState && (pEdict != nullptr)) + { + sm_gamehelpers->SetEdictStateChanged(pEdict, static_cast(offset)); + } + + return true; +} + +CBaseEntity *CBotEntProp::GetGameRulesProxyEntity() +{ + static int proxyEntRef = -1; + CBaseEntity *pProxy; + if (proxyEntRef == -1 || (pProxy = sm_gamehelpers->ReferenceToEntity(proxyEntRef)) == nullptr) + { + pProxy = GetEntity(bot_helper->FindEntityByNetClass(sm_players->GetMaxClients(), grclassname)); + if (pProxy) + proxyEntRef = sm_gamehelpers->EntityToReference(pProxy); + } + + return pProxy; +} + +/// @brief Retrieves an integer value from a property of the gamerules entity. +/// @param prop Property name. +/// @param size Number of bytes to read (valid values are 1, 2, or 4). This value is auto-detected, and the size parameter is only used as a fallback in case detection fails. +/// @param element Element # (starting from 0) if property is an array. +/// @return Value at the given property offset. +int CBotEntProp::GameRules_GetProp(const char *prop, const int size, const int element) const +{ + int offset; + int bit_count; + bool is_unsigned = false; //Unused? [APG]RoboCop[CL] + void *pGameRules = sm_sdktools->GetGameRules(); + + if (!pGameRules || !grclassname || !strcmp(grclassname, "")) + { + logger->Log(LogLevel::ERROR, "Gamerules lookup failed"); + return -1; + } + + int elementCount = 1; //Unused? [APG]RoboCop[CL] + GAMERULES_FIND_PROP_SEND(DPT_Int, "integer", -1) + is_unsigned = ((pProp->GetFlags() & SPROP_UNSIGNED) == SPROP_UNSIGNED); + + // This isn't in CS:S yet, but will be, doesn't hurt to add now, and will save us a build later +#if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_TF2 \ + || SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE || SOURCE_ENGINE == SE_PVKII + if (pProp->GetFlags() & SPROP_VARINT) + { + bit_count = sizeof(int) * 8; + } +#endif + + if (bit_count < 1) + { + bit_count = size * 8; + } + + if (bit_count >= 17) + { + return *reinterpret_cast(reinterpret_cast(pGameRules) + offset); + } + + if (bit_count >= 9) + { + if (is_unsigned) + { + return *reinterpret_cast(reinterpret_cast(pGameRules) + offset); + } + return *reinterpret_cast(reinterpret_cast(pGameRules) + offset); + } + + if (bit_count >= 2) + { + if (is_unsigned) + { + return *reinterpret_cast(reinterpret_cast(pGameRules) + offset); + } + return *reinterpret_cast(reinterpret_cast(pGameRules) + offset); + } + + return *reinterpret_cast(reinterpret_cast(pGameRules) + offset) ? 1 : 0; + + //return -1; +} + +/// @brief Retrieves a float value from a property of the gamerules entity. +/// @param prop Property name. +/// @param element Element # (starting from 0) if property is an array. +/// @return Value at the given property offset. +float CBotEntProp::GameRules_GetPropFloat(const char *prop, const int element) const +{ + int offset; + int bit_count; //Unused? [APG]RoboCop[CL] + void *pGameRules = sm_sdktools->GetGameRules(); + + if (!pGameRules || !grclassname || !strcmp(grclassname, "")) + { + logger->Log(LogLevel::ERROR, "Gamerules lookup failed"); + return 0.0f; + } + + int elementCount = 1; //Unused? [APG]RoboCop[CL] + GAMERULES_FIND_PROP_SEND(DPT_Float, "float", 0.0f) + + return *reinterpret_cast(reinterpret_cast(pGameRules) + offset); +} + +/// @brief Retrieves a entity index from a property of the gamerules entity. +/// @param prop Property name. +/// @param element Element # (starting from 0) if property is an array. +/// @return Entity index at the given property. If there is no entity, or the entity is not valid, then -1 is returned. +int CBotEntProp::GameRules_GetPropEnt(const char *prop, const int element) const +{ + int offset; + int bit_count; //Unused? [APG]RoboCop[CL] + void *pGameRules = sm_sdktools->GetGameRules(); + + if (!pGameRules || !grclassname || !strcmp(grclassname, "")) + { + logger->Log(LogLevel::ERROR, "Gamerules lookup failed"); + return 0.0f; + } + + int elementCount = 1; //Unused? [APG]RoboCop[CL] + GAMERULES_FIND_PROP_SEND(DPT_Int, "Integer", 0.0f) + + const CBaseHandle& hndl = *reinterpret_cast(reinterpret_cast(pGameRules) + offset); + + CBaseEntity *pEntity = sm_gamehelpers->ReferenceToEntity(hndl.GetEntryIndex()); + + if (!pEntity || reinterpret_cast(pEntity)->GetRefEHandle() != hndl) + { + return -1; + } + + return sm_gamehelpers->EntityToBCompatRef(pEntity); +} + +/// @brief Retrieves a vector from the gamerules entity, given a named network property. +/// @param prop Property name. +/// @param element Element # (starting from 0) if property is an array. +/// @return Value at the given property offset. +Vector CBotEntProp::GameRules_GetPropVector(const char *prop, const int element) const +{ + int offset; + int bit_count; //Unused? [APG]RoboCop[CL] + void *pGameRules = sm_sdktools->GetGameRules(); + + if (!pGameRules || !grclassname || !strcmp(grclassname, "")) + { + logger->Log(LogLevel::ERROR, "Gamerules lookup failed"); + return {0,0,0}; + } + + int elementCount = 1; //Unused? [APG]RoboCop[CL] + GAMERULES_FIND_PROP_SEND(DPT_Vector, "vector", Vector(0,0,0)) + + return *reinterpret_cast(reinterpret_cast(pGameRules) + offset); +} + +/// @brief Gets a gamerules property as a string. +/// @param prop Property to use. +/// @param len Number of non-null bytes written. +/// @param maxlen Maximum length of output string buffer. +/// @param element Element # (starting from 0) if property is an array. +/// @return Value at the given property offset. +char *CBotEntProp::GameRules_GetPropString(const char *prop, std::size_t *len, const int maxlen, const int element) const +{ + int offset; + int bit_count; //Unused? [APG]RoboCop[CL] + void *pGameRules = sm_sdktools->GetGameRules(); + + if (!pGameRules || !grclassname || !strcmp(grclassname, "")) + { + logger->Log(LogLevel::ERROR, "Gamerules lookup failed"); + return nullptr; + } + + int elementCount = 1; //Unused? [APG]RoboCop[CL] + GAMERULES_FIND_PROP_SEND(DPT_String, "string", nullptr) + + const char *src; + char *dest = nullptr; + if (pProp->GetProxyFn()) + { + DVariant var; + pProp->GetProxyFn()(pProp, pGameRules, reinterpret_cast(reinterpret_cast(pGameRules) + offset), &var, element, 0 /* TODO */); + src = var.m_pString; + } + else + { + src = *reinterpret_cast(static_cast(pGameRules) + static_cast(offset)); + } + + if (src) + { + const std::size_t length = ke::SafeStrcpy(dest, static_cast(maxlen), src); + *len = length; + } + + return dest; +} + +RoundState CBotEntProp::GameRules_GetRoundState() const +{ + char roundState[] = "m_iRoundState"; + return static_cast(GameRules_GetProp(roundState)); +} \ No newline at end of file diff --git a/rcbot/entprops.h b/rcbot/entprops.h new file mode 100644 index 000000000..c4b35340a --- /dev/null +++ b/rcbot/entprops.h @@ -0,0 +1,161 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + */ +#ifndef __RCBOT2_ENTPROPS_H__ +#define __RCBOT2_ENTPROPS_H__ + +#include "bot_plugin_meta.h" +#include "bot_const.h" +#include +#include +#include +#include + +enum : std::uint32_t +{ + INVALID_ENT_REFERENCE = 0xFFFFFFFF // TODO: replace magic number [APG]RoboCop[CL] +}; + +enum PropType : std::uint8_t +{ + Prop_Send = 0, + Prop_Data +}; + +class CBotEntProp +{ +public: + void Init(bool reset = false); + int GetEntProp(int entity, PropType proptype, const char *prop, int size = 4, int element = 0); + int *GetEntPropPointer(int entity, PropType proptype, const char *prop, int size = 4, int element = 0); + bool GetEntPropBool(int entity, PropType proptype, const char *prop, int element = 0); + bool *GetEntPropBoolPointer(int entity, PropType proptype, const char *prop, int element = 0); + bool SetEntProp(int entity, PropType proptype, const char *prop, int value, int size = 4, int element = 0); + float GetEntPropFloat(int entity, PropType proptype, const char *prop, int element = 0); + float *GetEntPropFloatPointer(int entity, PropType proptype, const char *prop, int element = 0); + bool SetEntPropFloat(int entity, PropType proptype, const char *prop, float value, int element = 0); + int GetEntPropEnt(int entity, PropType proptype, const char *prop, int element = 0); + bool SetEntPropEnt(int entity, PropType proptype, const char *prop, int other, int element = 0); + Vector GetEntPropVector(int entity, PropType proptype, const char *prop, int element = 0); + Vector *GetEntPropVectorPointer(int entity, PropType proptype, const char *prop, int element = 0); + bool SetEntPropVector(int entity, PropType proptype, const char *prop, const Vector& value, int element = 0); + char *GetEntPropString(int entity, PropType proptype, const char* prop, int maxlen, std::size_t* len, int element = 0); + bool SetEntPropString(int entity, PropType proptype, const char *prop, const char *value, int element = 0); + int GetEntData(int entity, int offset, int size = 4); + bool SetEntData(int entity, int offset, int value, int size = 4, bool changeState = false); + float GetEntDataFloat(int entity, int offset); + bool SetEntDataFloat(int entity, int offset, float value, bool changeState = false); + int GetEntDataEnt(int entity, int offset); + bool SetEntDataEnt(int entity, int offset, int value, bool changeState = false); + Vector GetEntDataVector(int entity, int offset); + bool SetEntDataVector(int entity, int offset, const Vector& value, bool changeState = false); + char *GetEntDataString(int entity, int offset, int maxlen, std::size_t* len); + bool SetEntDataString(int entity, int offset, const char *value, int maxlen, bool changeState = false); + int GameRules_GetProp(const char *prop, int size = 4, int element = 0) const; + float GameRules_GetPropFloat(const char *prop, int element = 0) const; + int GameRules_GetPropEnt(const char *prop, int element = 0) const; + Vector GameRules_GetPropVector(const char *prop, int element = 0) const; + char *GameRules_GetPropString(const char* prop, std::size_t* len, int maxlen, int element = 0) const; + RoundState GameRules_GetRoundState() const; + +private: + bool IsNetworkedEntity(CBaseEntity *pEntity); + edict_t *BaseEntityToEdict(CBaseEntity *pEntity); + bool FindSendProp(SourceMod::sm_sendprop_info_t *info, CBaseEntity *pEntity, const char *prop, int entity); + int MatchTypeDescAsInteger(_fieldtypes type, int flags); + bool IndexToAThings(int num, CBaseEntity **pEntData, edict_t **pEdictData); + CBaseEntity *GetEntity(int entity); + CBaseEntity *GetGameRulesProxyEntity(); + + const char* grclassname = nullptr; // game rules proxy net class + bool initialized = false; +}; + +inline int CBotEntProp::MatchTypeDescAsInteger(const _fieldtypes type, const int flags) +{ + switch (type) + { + case FIELD_TICK: + case FIELD_MODELINDEX: + case FIELD_MATERIALINDEX: + case FIELD_INTEGER: + case FIELD_COLOR32: + return 32; + case FIELD_CUSTOM: + if ((flags & FTYPEDESC_OUTPUT) == FTYPEDESC_OUTPUT) + { + // Variant, read as int32. + return 32; + } + break; + case FIELD_SHORT: + return 16; + case FIELD_CHARACTER: + return 8; + case FIELD_BOOLEAN: + return 1; + default: + return 0; + } + + return 0; +} + +/// @brief Converts a CBaseEntity to an edict_t +/// @param pEntity CBaseEntity pointer +/// @return edict_t pointer +inline edict_t *CBotEntProp::BaseEntityToEdict(CBaseEntity *pEntity) +{ + IServerUnknown *pUnk = reinterpret_cast(pEntity); + const IServerNetworkable *pNet = pUnk->GetNetworkable(); + + if (!pNet) + { + return nullptr; + } + + return pNet->GetEdict(); +} + +/// @brief Gets a CBaseEntity from an entity index +/// @param entity Entity/Edict index +/// @return CBaseEntity pointer +inline CBaseEntity *CBotEntProp::GetEntity(const int entity) +{ + CBaseEntity *pEntity; + if (!IndexToAThings(entity, &pEntity, nullptr)) + { + return nullptr; + } + + return pEntity; +} + +extern CBotEntProp *entprops; + +#endif \ No newline at end of file diff --git a/rcbot/helper.cpp b/rcbot/helper.cpp new file mode 100644 index 000000000..390322a6c --- /dev/null +++ b/rcbot/helper.cpp @@ -0,0 +1,238 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +/* + * This file is part of RCBot. + * + * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. + * + * RCBot is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * RCBot is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RCBot; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + */ + +#pragma push_macro("clamp") //Fix for C++17 [APG]RoboCop[CL] +#undef clamp +#include +#pragma pop_macro("clamp") + +#include "helper.h" + +#include +#include "IEngineTrace.h" +#include "toolframework/itoolentity.h" +#include + +#include "smsdk_config.h" + +static CBotHelper s_bot_helper; +CBotHelper *bot_helper = &s_bot_helper; + +extern IEngineTrace *enginetrace; +extern IServerTools *servertools; + +/* Given an entity reference or index, fill out a CBaseEntity and/or edict. + If lookup is successful, returns true and writes back the two parameters. + If lookup fails, returns false and doesn't touch the params. */ +bool CBotHelper::IndexToAThings(const int num, CBaseEntity **pEntData, edict_t **pEdictData) +{ + CBaseEntity *pEntity = sm_gamehelpers->ReferenceToEntity(num); + + if (!pEntity) + { + return false; + } + + const int index = sm_gamehelpers->ReferenceToIndex(num); + if (index > 0 && index <= sm_players->GetMaxClients()) + { + SourceMod::IGamePlayer *pPlayer = sm_players->GetGamePlayer(index); + if (!pPlayer || !pPlayer->IsConnected()) + { + return false; + } + } + + if (pEntData) + { + *pEntData = pEntity; + } + + if (pEdictData) + { + edict_t *pEdict = BaseEntityToEdict(pEntity); + if (!pEdict || pEdict->IsFree()) + { + pEdict = nullptr; + } + + *pEdictData = pEdict; + } + + return true; +} + +/** + * Clone of CCollisionProperty::OBBCenter( ) --- see game/shared/collisionproperty.h + * + * @param pEntity Entity to get OBB center + **/ +Vector CBotHelper::getOBBCenter( edict_t *pEntity ) +{ + Vector result = Vector(0,0,0); + VectorLerp(pEntity->GetCollideable()->OBBMins(), pEntity->GetCollideable()->OBBMaxs(), 0.5f, result); + return result; +} + +Vector CBotHelper::collisionToWorldSpace( const Vector &in, edict_t *pEntity ) +{ + Vector result = Vector(0,0,0); + + if(!isBoundsDefinedInEntitySpace(pEntity) || pEntity->GetCollideable()->GetCollisionAngles() == vec3_angle) + { + VectorAdd(in, pEntity->GetCollideable()->GetCollisionOrigin(), result); + } + else + { + VectorTransform(in, pEntity->GetCollideable()->CollisionToWorldTransform(), result); + } + + return result; +} + +/** + * Gets the entity world center. Clone of WorldSpaceCenter() + * @param pEntity The entity to get the center from + * @return Center vector + **/ +Vector CBotHelper::worldCenter( edict_t *pEntity ) +{ + Vector result = getOBBCenter(pEntity); + result = collisionToWorldSpace(result, pEntity); + return result; +} + +/** + * Checks if a point is within a trigger + * + * @param pEntity The trigger entity + * @param vPoint The point to be tested + * @return True if the given point is within pEntity + **/ +bool CBotHelper::pointIsWithin( edict_t *pEntity, const Vector &vPoint ) +{ + Ray_t ray; + trace_t tr; + ICollideable *pCollide = pEntity->GetCollideable(); + ray.Init(vPoint, vPoint); + enginetrace->ClipRayToCollideable(ray, MASK_ALL, pCollide, &tr); + return (tr.startsolid); +} + +/// @brief Checks if the given edict is a brush model +/// @param pEntity Edict to check +/// @return True if brush model +bool CBotHelper::isBrushEntity( edict_t *pEntity ) +{ + const char* szModel = pEntity->GetIServerEntity()->GetModelName().ToCStr(); + return szModel[0] == '*'; +} + +/// @brief Searches for entities by classname +/// @return Entity index/reference or INVALID_EHANDLE_INDEX if none is found +int CBotHelper::FindEntityByClassname(const int start,const char *classname) +{ + CBaseEntity *pEntity = servertools->FindEntityByClassname(GetEntity(start), classname); + return sm_gamehelpers->EntityToBCompatRef(pEntity); +} + +/// @brief Searches for entities in a sphere +/// @return Entity index/reference or INVALID_EHANDLE_INDEX if none is found +int CBotHelper::FindEntityInSphere(const int start, const Vector& center, const float radius) +{ + CBaseEntity *pEntity = servertools->FindEntityInSphere(GetEntity(start), center, radius); + return sm_gamehelpers->EntityToBCompatRef(pEntity); +} + +/// @brief Searches for entities by their networkable class +/// @return Entity index or INVALID_EHANDLE_INDEX if none is found +int CBotHelper::FindEntityByNetClass(const int start, const char *classname) +{ + for (int i = ((start != -1) ? start : 0); i < gpGlobals->maxEntities; i++) + { + edict_t* current = engine->PEntityOfEntIndex(i); + if (current == nullptr || current->IsFree()) + { + continue; + } + + IServerNetworkable *network = current->GetNetworkable(); + + if (network == nullptr) + { + continue; + } + + ServerClass *sClass = network->GetServerClass(); + const char *name = sClass->GetName(); + + + if (strcmp(name, classname) == 0) + { + return i; + } + } + + return INVALID_EHANDLE_INDEX; +} + +/// @brief check if a point is in the field of a view of an object. supports up to 180 degree fov. +/// @param vecSrcPosition Source position of the view. +/// @param vecTargetPosition Point to check if within view angle. +/// @param vecLookDirection The direction to look towards. Note that this must be a forward angle vector. +/// @param flCosHalfFOV The width of the forward view cone as a dot product result. +/// @return True if the point is within view from the source position at the specified FOV. +/// @note https://github.com/ValveSoftware/source-sdk-2013/blob/beaae8ac45a2f322a792404092d4482065bef7ef/sp/src/public/mathlib/vector.h#L462-L477 +bool CBotHelper::PointWithinViewAngle(Vector const &vecSrcPosition, Vector const &vecTargetPosition, Vector const &vecLookDirection, const float flCosHalfFOV) +{ + const Vector vecDelta = vecTargetPosition - vecSrcPosition; + const float cosDiff = DotProduct( vecLookDirection, vecDelta ); + + if ( cosDiff < 0 ) + return false; + + const float flLen2 = vecDelta.LengthSqr(); + + // a/sqrt(b) > c == a^2 > b * c ^2 + return ( cosDiff * cosDiff > flLen2 * flCosHalfFOV * flCosHalfFOV ); + +} + +/// @brief Calculates the width of the forward view cone as a dot product result from the given angle. +/// This manually calculates the value of CBaseCombatCharacter's `m_flFieldOfView` data property. +/// @param angle The FOV value in degree +/// @return Width of the forward view cone as a dot product result +float CBotHelper::GetForwardViewCone(const float angle) +{ + return cosf(DEG2RAD(angle) / 2.0f); +} \ No newline at end of file diff --git a/rcbot/helper.h b/rcbot/helper.h new file mode 100644 index 000000000..65a8c6df7 --- /dev/null +++ b/rcbot/helper.h @@ -0,0 +1,99 @@ +/* + * This file is part of RCBot. + * + * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. + * + * RCBot is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * RCBot is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RCBot; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + */ +#ifndef __RCBOT2_UTIL_FUNC_H__ +#define __RCBOT2_UTIL_FUNC_H__ + +#include "bot_plugin_meta.h" + +// General Utility functions + + +/// @brief General utility/helper class, alternative to CBotGlobals +class CBotHelper +{ +public: + bool IndexToAThings(int num, CBaseEntity **pEntData, edict_t **pEdictData); + CBaseEntity *GetEntity(int entity); + edict_t *BaseEntityToEdict(CBaseEntity *pEntity); + Vector worldCenter( edict_t *pEntity ); + bool pointIsWithin( edict_t *pEntity, const Vector &vPoint ); + bool isBrushEntity( edict_t *pEntity ); + int FindEntityByClassname(int start, const char *classname); + int FindEntityInSphere(int start, const Vector& center, float radius); + int FindEntityByNetClass(int start, const char *classname); + bool PointWithinViewAngle(Vector const &vecSrcPosition, Vector const &vecTargetPosition, Vector const &vecLookDirection, float flCosHalfFOV); + float GetForwardViewCone(float angle); + +private: + bool isBoundsDefinedInEntitySpace(edict_t* pEntity) + { + const ICollideable* pCollideable = pEntity->GetCollideable(); // Cache the result in a local pointer + return ((pCollideable->GetSolidFlags() & FSOLID_FORCE_WORLD_ALIGNED) == 0 && + pCollideable->GetSolid() != SOLID_BBOX && pCollideable->GetSolid() != SOLID_NONE); + } + + static Vector getOBBCenter( edict_t *pEntity ); + Vector collisionToWorldSpace( const Vector &in, edict_t *pEntity ); +}; + +/// @brief Converts a CBaseEntity to an edict_t +/// @param pEntity CBaseEntity pointer +/// @return edict_t pointer +inline edict_t *CBotHelper::BaseEntityToEdict(CBaseEntity *pEntity) +{ + IServerUnknown *pUnk = reinterpret_cast(pEntity); + const IServerNetworkable *pNet = pUnk->GetNetworkable(); + + if (!pNet) + { + return nullptr; + } + + return pNet->GetEdict(); +} + +/// @brief Gets a CBaseEntity from an entity index +/// @param entity Entity/Edict index +/// @return CBaseEntity pointer +inline CBaseEntity *CBotHelper::GetEntity(const int entity) +{ + CBaseEntity *pEntity; + if (!IndexToAThings(entity, &pEntity, nullptr)) + { + return nullptr; + } + + return pEntity; +} + +extern CBotHelper *bot_helper; + +#endif diff --git a/rcbot/logging.cpp b/rcbot/logging.cpp new file mode 100644 index 000000000..5ffdd8905 --- /dev/null +++ b/rcbot/logging.cpp @@ -0,0 +1,160 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +/** + * Copyright 2021 nosoop + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA + * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "logging.h" + +#if defined(_WIN64) || defined(_WIN32) +// for SetConsoleTextAttribute and co. +#define WIN32_LEAN_AND_MEAN +#include +#endif + +#include +#include +#include + +#include "convar.h" +#include "icvar.h" + +#include "engine_wrappers.h" + +#include "tier0/dbg.h" +#include "tier0/icommandline.h" + +static CBotLogger s_Logger; +CBotLogger *logger = &s_Logger; + +ConVar rcbot_loglevel("rcbot_loglevel", "2", 0, + "Display logging messages with increasing verbosity (higher number = more messages)"); + +const char *LOGLEVEL_STRINGS[] = { "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" }; + +const char *LOGLEVEL_ANSI_COLORS[] = { "\x1B[1;31m", "\x1B[1;91m", "\x1B[1;33m", + "\x1B[1;92m", "\x1B[1;94m", "\x1B[1;96m" }; + +#if defined(_WIN64) || defined(_WIN32) +#define FOREGROUND_YELLOW (FOREGROUND_GREEN | FOREGROUND_RED) +#define FOREGROUND_WHITE (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE) +//Supposed to be `WORD` not `DWORD`? [APG]RoboCop[CL] +constexpr WORD LOGLEVEL_WINCON_COLORS[] = { FOREGROUND_RED, + FOREGROUND_RED | FOREGROUND_INTENSITY, + FOREGROUND_YELLOW, + FOREGROUND_GREEN | FOREGROUND_INTENSITY, + FOREGROUND_BLUE | FOREGROUND_INTENSITY, + FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY }; +#endif + +// colors based on https://www.codeproject.com/Tips/5255355/How-to-Put-Color-on-Windows-Console +const Color LOGLEVEL_CONSOLE_COLORS[] = { + { 197, 15, 31, 255 }, { 231, 72, 75, 255 }, { 193, 156, 0, 255 }, + { 19, 198, 13, 255 }, { 59, 120, 255, 255 }, { 97, 214, 214, 255 }, +}; + +enum MessageColorizationMode : std::uint8_t +{ + Colorize_None, + + // ANSI escapes + Colorize_ANSI, + +#if defined(_WIN64) || defined(_WIN32) + // windows console -- uses console text attributes + Colorize_WinConsole, +#endif + + Colorize_ClientConsole, +}; + +MessageColorizationMode GetMessageColorizationMode() +{ +#ifdef _LINUX + if (!engine->IsDedicatedServer()) + { + return Colorize_ClientConsole; + } + else + { + return Colorize_ANSI; + } +#elif defined(_WIN64) || defined(_WIN32) + if (!engine->IsDedicatedServer()) + { + return Colorize_ClientConsole; + } + if (CommandLine()->CheckParm("-console") != nullptr) + { + return Colorize_WinConsole; + } +#endif + return Colorize_None; +} + +void CBotLogger::Log(const LogLevel level, const char *fmt, ...) +{ + if (level > static_cast(rcbot_loglevel.GetInt())) + { + return; + } + + char buf[1024]; + + va_list argptr; + va_start(argptr, fmt); + vsnprintf(buf, sizeof(buf), fmt, argptr); + va_end(argptr); + + switch (GetMessageColorizationMode()) + { + case Colorize_ANSI: + if (level <= LogLevel::WARN) + { + Warning("%s[RCBot] %s: %s\x1B[0m\n", LOGLEVEL_ANSI_COLORS[level], LOGLEVEL_STRINGS[level], buf); + } + else + { + Msg("%s[RCBot] %s: %s\x1B[0m\n", LOGLEVEL_ANSI_COLORS[level], LOGLEVEL_STRINGS[level], buf); + } + break; +#if defined(_WIN64) || defined(_WIN32) + case Colorize_WinConsole: + HANDLE hConsoleHandle; + hConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); + + SetConsoleTextAttribute(hConsoleHandle, LOGLEVEL_WINCON_COLORS[level]); + + Msg("[RCBot] %s: %s\n", LOGLEVEL_STRINGS[level], buf); + SetConsoleTextAttribute(hConsoleHandle, FOREGROUND_WHITE); + break; +#endif + case Colorize_ClientConsole: + extern ICvar *icvar; + icvar->ConsoleColorPrintf(LOGLEVEL_CONSOLE_COLORS[level], "[RCBot] %s: %s\n", LOGLEVEL_STRINGS[level], buf); + break; + case Colorize_None: + //default: + if (level <= LogLevel::WARN) + { + Warning("[RCBot] %s: %s\n", LOGLEVEL_STRINGS[level], buf); + } + else + { + Msg("[RCBot] %s: %s\n", LOGLEVEL_STRINGS[level], buf); + } + break; + } +} diff --git a/rcbot/logging.h b/rcbot/logging.h new file mode 100644 index 000000000..59099c4ad --- /dev/null +++ b/rcbot/logging.h @@ -0,0 +1,62 @@ +/** + * Copyright 2021 nosoop + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA + * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __RCBOT2_LOGGER_H__ +#define __RCBOT2_LOGGER_H__ + +#include + +// Undefine potential conflicting macros +#ifdef FATAL +#undef FATAL +#endif + +#ifdef ERROR +#undef ERROR +#endif + +#ifdef WARN +#undef WARN +#endif + +#ifdef INFO +#undef INFO +#endif + +#ifdef DEBUG +#undef DEBUG +#endif + +#ifdef TRACE +#undef TRACE +#endif + +/** + * Log levels in ascending order. + */ +enum LogLevel : std::uint8_t { + FATAL, ERROR, WARN, INFO, DEBUG, TRACE +}; + +class CBotLogger +{ + public: + void Log(LogLevel level, const char *fmt, ...); +}; + +extern CBotLogger *logger; + +#endif diff --git a/rcbot/math_fix.cpp b/rcbot/math_fix.cpp new file mode 100644 index 000000000..a1389f17f --- /dev/null +++ b/rcbot/math_fix.cpp @@ -0,0 +1,42 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +#include + +#ifdef MATH_LIB_FIX +// GCC9 Developers broke compatibility with math options so we need to redeclare them +// https://stackoverflow.com/questions/63261220/link-errors-with-ffast-math-ffinite-math-only-and-glibc-2-31 +// https://forums.developer.nvidia.com/t/problems-on-ubuntu-20-04-linuxpower/136507/3 +// from https://gitlab.com/counterstrikesource/sm-exts/sm-ext-common/-/blob/master/mathstubs.c +// -sappho + +// Fix for missing functions in mathlib +// Thanks to sappho from AM discord +// Is bot.cpp the best place for this? IDK. It just works. -caxanga334 +extern "C" +{ + double __acos_finite(double x) { return acos(x); } + float __acosf_finite(float x) { return acosf(x); } + double __acosh_finite(double x) { return acosh(x); } + float __acoshf_finite(float x) { return acoshf(x); } + double __asin_finite(double x) { return asin(x); } + float __asinf_finite(float x) { return asinf(x); } + double __atanh_finite(double x) { return atanh(x); } + float __atanhf_finite(float x) { return atanhf(x); } + double __cosh_finite(double x) { return cosh(x); } + float __coshf_finite(float x) { return coshf(x); } + double __sinh_finite(double x) { return sinh(x); } + float __sinhf_finite(float x) { return sinhf(x); } + double __exp_finite(double x) { return exp(x); } + float __expf_finite(float x) { return expf(x); } + double __log10_finite(double x) { return log10(x); } + float __log10f_finite(float x) { return log10f(x); } + double __log_finite(double x) { return log(x); } + float __logf_finite(float x) { return logf(x); } + double __atan2_finite(double x, double y) { return atan2(x, y); } + float __atan2f_finite(float x, double y) { return atan2f(x, y); } + double __pow_finite(double x, double y) { return pow(x, y); } + float __powf_finite(float x, double y) { return powf(x, y); } + double __remainder_finite(double x, double y) { return remainder(x, y); } + float __remainderf_finite(float x, double y) { return remainderf(x, y); } +} +#endif \ No newline at end of file diff --git a/rcbot/propvar.cpp b/rcbot/propvar.cpp new file mode 100644 index 000000000..c7ebdcebe --- /dev/null +++ b/rcbot/propvar.cpp @@ -0,0 +1,107 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +/* + * This file is part of RCBot. + * + * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. + * + * RCBot is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * RCBot is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RCBot; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + */ + +#pragma push_macro("clamp") //Fix for C++17 [APG]RoboCop[CL] +#undef clamp +#include +#pragma pop_macro("clamp") + +#include "propvar.h" +#include "helper.h" +#include "logging.h" + +#if defined(_WIN64) || defined(_WIN32) +#include +#endif + +CPropertyVarBase::CPropertyVarBase(): m_type() +{ + m_initialized = false; +} + +CPropertyVarBase::~CPropertyVarBase() +{ + m_initialized = false; +} + +void CPropertyVarBase::Init(const char *propname, const PropType type, const int entity) +{ + CBaseEntity* baseentity = bot_helper->GetEntity(entity); + + if (!baseentity) + { + logger->Log(LogLevel::ERROR, "Initialization failed for PropertyVar \"%s\"! Entity of index %i is NULL!", propname, entity); +#if defined(_WIN64) || defined(_WIN32) // TODO: verify of runtime_error works fine under linux + throw std::runtime_error("Initialization failed for PropertyVar!"); +#endif + //return; + } + + m_propname = std::string(propname); + m_type = type; + m_entity.Set(reinterpret_cast(baseentity)); + m_initialized = true; +} + +void CPropertyVarBase::Term() +{ + m_initialized = false; +} + +int CPropertyVarInt::Get() const +{ + return entprops->GetEntProp(m_entity.GetEntryIndex(), m_type, m_propname.c_str()); +} + +bool CPropertyVarBool::Get() const +{ + return entprops->GetEntPropBool(m_entity.GetEntryIndex(), m_type, m_propname.c_str()); +} + +float CPropertyVarFloat::Get() const +{ + return entprops->GetEntPropFloat(m_entity.GetEntryIndex(), m_type, m_propname.c_str()); +} + +Vector CPropertyVarVector::Get() const +{ + return entprops->GetEntPropVector(m_entity.GetEntryIndex(), m_type, m_propname.c_str()); +} + +void CPropertyVarVector::Get(Vector &dest) const +{ + const Vector source = entprops->GetEntPropVector(m_entity.GetEntryIndex(), m_type, m_propname.c_str()); + dest.x = source.x; + dest.y = source.y; + dest.z = source.z; +} \ No newline at end of file diff --git a/rcbot/propvar.h b/rcbot/propvar.h new file mode 100644 index 000000000..87d8f1ff1 --- /dev/null +++ b/rcbot/propvar.h @@ -0,0 +1,88 @@ +/* + * This file is part of RCBot. + * + * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. + * + * RCBot is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * RCBot is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RCBot; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + */ + +#ifndef _PROPERTY_VARIABLE_H_ +#define _PROPERTY_VARIABLE_H_ + +#include +#include "entprops.h" +#include "vector.h" + +/// @brief Base class for easy access to entity network propteries and datamaps. +class CPropertyVarBase +{ +public: + CPropertyVarBase(); + virtual ~CPropertyVarBase(); + + /// @brief Initializes the property variable + /// @param propname Property name. Get a netprops and datamaps dump for a list of available property names. + /// @param type Property type. Prop_Send for network propertys and Prop_Data for datamaps. + /// @param entity Entity index to read the property from. + virtual void Init(const char* propname, PropType type, int entity); + /// @brief Checks if the property is initialized with a property name, type and entity index. + bool IsInitialized() const { return m_initialized; } + /// @brief Marks this as not initialized. + virtual void Term(); +protected: + + std::string m_propname; + PropType m_type; + CBaseHandle m_entity; + bool m_initialized; +}; + +class CPropertyVarInt : public CPropertyVarBase +{ +public: + int Get() const; +}; + +class CPropertyVarBool : public CPropertyVarBase +{ +public: + bool Get() const; +}; + +class CPropertyVarFloat : public CPropertyVarBase +{ +public: + float Get() const; +}; + +class CPropertyVarVector : public CPropertyVarBase +{ +public: + Vector Get() const; + void Get(Vector &dest) const; +}; + +#endif \ No newline at end of file diff --git a/rcbot/rb-platform.h b/rcbot/rb-platform.h new file mode 100644 index 000000000..d66e6b625 --- /dev/null +++ b/rcbot/rb-platform.h @@ -0,0 +1,55 @@ +// +// Copyright (C) 2013, David Anderson and AlliedModders LLC +// All rights reserved. +// +// Original code from AMTL: https://github.com/alliedmodders/amtl/blob/2d3b1a3378a3728637f26660c9ffc2df3189cf62/amtl/am-platform.h +// Borrowed for RCBot2 +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of AlliedModders LLC nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef __RCBOT2_PLATFORM_H_ +#define __RCBOT2_PLATFORM_H_ + +#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__amd64) || \ + (defined(_MSC_VER) && defined(_M_X64)) +# define RCBOT_ARCH_X64 +# define RCBOT_ARCH_TAG "x86-64" +#elif defined(__i686) || defined(__i686__) || defined(__i386) || defined(__i386__) || \ + defined(i386) || (defined(_MSC_VER) && defined(_M_IX86)) +# define RCBOT_ARCH_X86 +# define RCBOT_ARCH_TAG "x86" +#elif defined(__aarch64__) || defined(_M_ARM64) +# define RCBOT_ARCH_ARM64 +# define RCBOT_ARCH_TAG "ARM64" +#elif defined(__arm__) || defined(_M_ARM) +# define RCBOT_ARCH_ARM +# define RCBOT_ARCH_TAG "ARM" +#else +# define RCBOT_ARCH_UNKNOWN +# define RCBOT_ARCH_TAG "UNKNOWN-ARCH" +#endif + +#endif // !__RCBOT2_PLATFORM_H_ + diff --git a/rcbot/tf2/conditions.cpp b/rcbot/tf2/conditions.cpp new file mode 100644 index 000000000..d580363a2 --- /dev/null +++ b/rcbot/tf2/conditions.cpp @@ -0,0 +1,116 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id$ + */ + +#pragma push_macro("clamp") //Fix for C++17 [APG]RoboCop[CL] +#undef clamp +#include +#pragma pop_macro("clamp") + +#include "rcbot/tf2/conditions.h" +#include "rcbot/entprops.h" +#include "rcbot/logging.h" + +static CTF2Conditions s_tf2_conditions; +CTF2Conditions *tf2_conditions = &s_tf2_conditions; + +constexpr int CONDITION_BITS = 32; + +/// @brief Checks if the player is in a specific condition +/// @param client Client/Player entity index to check +/// @param cond Condition number to check +/// @return TRUE if the given condition is active on the player +bool CTF2Conditions::TF2_IsPlayerInCondition(const int client, const TFCond cond) +{ + const int iCond = cond; + + switch (iCond / CONDITION_BITS) + { + case 0: + { + const int bit = 1 << iCond; + if ((entprops->GetEntProp(client, Prop_Send, "m_nPlayerCond") & bit) == bit) + { + return true; + } + + if ((entprops->GetEntProp(client, Prop_Send, "_condition_bits") & bit) == bit) + { + return true; + } + break; + } + case 1: + { + const int bit = (1 << (iCond - CONDITION_BITS)); + if ((entprops->GetEntProp(client, Prop_Send, "m_nPlayerCondEx") & bit) == bit) + { + return true; + } + break; + } + case 2: + { + const int bit = (1 << (iCond - (CONDITION_BITS * 2))); + if ((entprops->GetEntProp(client, Prop_Send, "m_nPlayerCondEx2") & bit) == bit) + { + return true; + } + break; + } + case 3: + { + const int bit = (1 << (iCond - (CONDITION_BITS * 3))); + if ((entprops->GetEntProp(client, Prop_Send, "m_nPlayerCondEx3") & bit) == bit) + { + return true; + } + break; + } + case 4: + { + const int bit = (1 << (iCond - (CONDITION_BITS * 4))); + if ((entprops->GetEntProp(client, Prop_Send, "m_nPlayerCondEx4") & bit) == bit) + { + return true; + } + break; + } + default: + { + logger->Log(LogLevel::ERROR, "Invalid TFCond value %d", iCond); + return false; + //break; + } + } + + return false; +} diff --git a/rcbot/tf2/conditions.h b/rcbot/tf2/conditions.h new file mode 100644 index 000000000..647807fb2 --- /dev/null +++ b/rcbot/tf2/conditions.h @@ -0,0 +1,191 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id$ + */ +#ifndef __RCBOT2_TF2_CONDITIONS_H__ +#define __RCBOT2_TF2_CONDITIONS_H__ + +#include + +typedef enum : std::uint8_t +{ + TFCond_Slowed = 0, //0: Revving Minigun, Sniper Rifle. Gives zoomed/revved pose + TFCond_Zoomed = 1, //1: Sniper Rifle zooming + TFCond_Disguising = 2, //2: Disguise smoke + TFCond_Disguised = 3, //3: Disguise + TFCond_Cloaked = 4, //4: Cloak effect + TFCond_Ubercharged = 5, //5: Invulnerability, removed when being healed or by another Uber effect + TFCond_TeleportedGlow = 6, //6: Teleport trail effect + TFCond_Taunting = 7, //7: Used for taunting, can remove to stop taunting + TFCond_UberchargeFading = 8, //8: Invulnerability expiration effect + TFCond_Unknown1 = 9, //9 + TFCond_CloakFlicker = 9, //9: Cloak flickering effect + TFCond_Teleporting = 10, //10: Used for teleporting, does nothing applying + TFCond_Kritzkrieged = 11, //11: Crit boost, removed when being healed or another Uber effect + TFCond_Unknown2 = 12, //12 + TFCond_TmpDamageBonus = 12, //12: Temporary damage buff, something along with attribute 19 + TFCond_DeadRingered = 13, //13: Dead Ringer damage resistance, gives TFCond_Cloaked + TFCond_Bonked = 14, //14: Bonk! Atomic Punch effect + TFCond_Dazed = 15, //15: Slow effect, can remove to remove stun effects + TFCond_Buffed = 16, //16: Buff Banner mini-crits, icon, and glow + TFCond_Charging = 17, //17: Forced forward, charge effect + TFCond_DemoBuff = 18, //18: Eyelander eye glow + TFCond_CritCola = 19, //19: Mini-crit effect + TFCond_InHealRadius = 20, //20: Ring effect, rings disappear after a taunt ends + TFCond_Healing = 21, //21: Used for healing, does nothing applying + TFCond_OnFire = 22, //22: Ignite sound and vocals, can remove to remove afterburn + TFCond_Overhealed = 23, //23: Used for overheal, does nothing applying + TFCond_Jarated = 24, //24: Jarate effect + TFCond_Bleeding = 25, //25: Bleed effect + TFCond_DefenseBuffed = 26, //26: Battalion's Backup's defense, icon, and glow + TFCond_Milked = 27, //27: Mad Milk effect + TFCond_MegaHeal = 28, //28: Quick-Fix Ubercharge's knockback/stun immunity and visual effect + TFCond_RegenBuffed = 29, //29: Concheror's speed boost, heal on hit, icon, and glow + TFCond_MarkedForDeath = 30, //30: Fan o' War marked-for-death effect + TFCond_NoHealingDamageBuff = 31, //31: Mini-crits, blocks healing, glow, no weapon mini-crit effects + TFCond_SpeedBuffAlly = 32, //32: Disciplinary Action speed boost + TFCond_HalloweenCritCandy = 33, //33: Halloween pumpkin crit-boost + TFCond_CritCanteen = 34, //34: Crit-boost and doubles Sentry Gun fire-rate + TFCond_CritDemoCharge = 35, //35: Crit glow, adds TFCond_Charging when charge meter is below 75% + TFCond_CritHype = 36, //36: Soda Popper multi-jump effect + TFCond_CritOnFirstBlood = 37, //37: Arena first blood crit-boost + TFCond_CritOnWin = 38, //38: End-of-round crit-boost (May not remove correctly?) + TFCond_CritOnFlagCapture = 39, //39: Intelligence capture crit-boost + TFCond_CritOnKill = 40, //40: Crit-boost from crit-on-kill weapons + TFCond_RestrictToMelee = 41, //41: Prevents switching once melee is out + TFCond_DefenseBuffNoCritBlock = 42, + //42: MvM Bomb Carrier defense buff (TFCond_DefenseBuffed without crit resistance) + TFCond_Reprogrammed = 43, //43: No longer functions + TFCond_CritMmmph = 44, //44: Phlogistinator crit-boost + TFCond_DefenseBuffMmmph = 45, //45: Old Phlogistinator defense buff + TFCond_FocusBuff = 46, //46: Hitman's Heatmaker no-unscope and faster Sniper charge + TFCond_DisguiseRemoved = 47, //47: Enforcer damage bonus removed + TFCond_MarkedForDeathSilent = 48, //48: Marked-for-death without sound effect + TFCond_DisguisedAsDispenser = 49, + //49: Dispenser disguise when crouching, max movement speed, sentries ignore player + TFCond_Sapped = 50, //50: Sapper sparkle effect in MvM + TFCond_UberchargedHidden = 51, //51: Out-of-bounds robot invulnerability effect + TFCond_UberchargedCanteen = 52, //52: Invulnerability effect and Sentry Gun damage resistance + TFCond_HalloweenBombHead = 53, //53: Bomb head effect (does not explode) + TFCond_HalloweenThriller = 54, //54: Forced Thriller taunting + TFCond_RadiusHealOnDamage = 55, + //55: Radius healing, adds TFCond_InHealRadius, TFCond_Healing. Removed when a taunt ends, but this condition stays but does nothing + TFCond_CritOnDamage = 56, //56: Miscellaneous crit-boost + TFCond_UberchargedOnTakeDamage = 57, //57: Miscellaneous invulnerability + TFCond_UberBulletResist = 58, //58: Vaccinator Uber bullet resistance + TFCond_UberBlastResist = 59, //59: Vaccinator Uber blast resistance + TFCond_UberFireResist = 60, //60: Vaccinator Uber fire resistance + TFCond_SmallBulletResist = 61, //61: Vaccinator healing bullet resistance + TFCond_SmallBlastResist = 62, //62: Vaccinator healing blast resistance + TFCond_SmallFireResist = 63, //63: Vaccinator healing fire resistance + TFCond_Stealthed = 64, //64: Cloaked until next attack + TFCond_MedigunDebuff = 65, //65: Unknown + TFCond_StealthedUserBuffFade = 66, //66: Cloaked, will appear for a few seconds on attack and cloak again + TFCond_BulletImmune = 67, //67: Full bullet immunity + TFCond_BlastImmune = 68, //68: Full blast immunity + TFCond_FireImmune = 69, //69: Full fire immunity + TFCond_PreventDeath = 70, //70: Survive to 1 health, then the condition is removed + TFCond_MVMBotRadiowave = 71, //71: Stuns bots and applies radio effect + TFCond_HalloweenSpeedBoost = 72, //72: Speed boost, non-melee fire rate and reload, infinite air jumps + TFCond_HalloweenQuickHeal = 73, //73: Healing effect, adds TFCond_Healing along with TFCond_MegaHeal temporarily + TFCond_HalloweenGiant = 74, //74: Double size, x10 max health increase, ammo regeneration, and forced thirdperson + TFCond_HalloweenTiny = 75, //75: Half size and increased head size + TFCond_HalloweenInHell = 76, //76: Applies TFCond_HalloweenGhostMode when the player dies + TFCond_HalloweenGhostMode = 77, //77: Becomes a ghost unable to attack but can fly + TFCond_MiniCritOnKill = 78, //78: Mini-crits effect + TFCond_DodgeChance = 79, //79 + TFCond_ObscuredSmoke = 79, //79: 75% chance to dodge an attack + TFCond_Parachute = 80, //80: Parachute effect, removed when touching the ground + TFCond_BlastJumping = 81, //81: Player is blast jumping + TFCond_HalloweenKart = 82, //82: Player forced into a Halloween kart + TFCond_HalloweenKartDash = 83, //83: Forced forward if in TFCond_HalloweenKart, zoom in effect, and dash animations + TFCond_BalloonHead = 84, //84: Big head and lowered gravity + TFCond_MeleeOnly = 85, //85: Forced melee, along with TFCond_SpeedBuffAlly and TFCond_HalloweenTiny + TFCond_SwimmingCurse = 86, //86: Swim in the air with Jarate overlay + TFCond_HalloweenKartNoTurn = 87, //87 + TFCond_FreezeInput = 87, //87: Prevents player from using controls + TFCond_HalloweenKartCage = 88, //88: Puts a cage around the player if in TFCond_HalloweenKart, otherwise crashes + TFCond_HasRune = 89, //89: Has a powerup + TFCond_RuneStrength = 90, //90: Double damage and no damage falloff + TFCond_RuneHaste = 91, //91: Double fire rate, reload speed, clip and ammo size, and 30% faster movement speed + TFCond_RuneRegen = 92, //92: Regen ammo, health, and metal + TFCond_RuneResist = 93, //93: Takes 1/2 damage and critical immunity + TFCond_RuneVampire = 94, //94: Takes 3/4 damage, gain health on damage, and 40% increase in max health + TFCond_RuneWarlock = 95, + //95: Attacker takes damage and knockback on hitting the player and 50% increase in max health + TFCond_RunePrecision = 96, + //96: Less bullet spread, no damage falloff, 250% faster projectiles, and double damage, faster charge, and faster re-zoom for Sniper Rifles + TFCond_RuneAgility = 97, + //97: Increased movement speed, grappling hook speed, jump height, and instant weapon switch + TFCond_GrapplingHook = 98, //98: Used when a player fires their grappling hook, no effect applying or removing + TFCond_GrapplingHookSafeFall = 99, + //99: Used when a player is pulled by their grappling hook, no effect applying or removing + TFCond_GrapplingHookLatched = 100, //100: Used when a player latches onto a wall, no effect applying or removing + TFCond_GrapplingHookBleeding = 101, //101: Used when a player is hit by attacker's grappling hook + TFCond_AfterburnImmune = 102, //102: Deadringer afterburn immunity + TFCond_RuneKnockout = 103, + //103: Melee and grappling hook only, increased max health, knockback immunity, x4 more damage against buildings, and knockbacks a powerup off a victim on hit + TFCond_RuneImbalance = 104, //104: Prevents gaining a crit-boost or Uber powerups + TFCond_CritRuneTemp = 105, //105: Crit-boost effect + TFCond_PasstimeInterception = 106, //106: Used when a player intercepts the Jack/Ball + TFCond_SwimmingNoEffects = 107, //107: Swimming in the air without animations or overlay + TFCond_EyeaductUnderworld = 108, //108: Refills max health, short Uber, escaped the underworld message on removal + TFCond_KingRune = 109, //109: Increased max health and applies TFCond_KingAura + TFCond_PlagueRune = 110, //110: Radius health kit stealing, increased max health, TFCond_Plague on touching a victim + TFCond_SupernovaRune = 111, + //111: Charge meter passively increasing, when charged activiated causes radius Bonk stun + TFCond_Plague = 112, //112: Plague sound effect and message, blocks King powerup health regen + TFCond_KingAura = 113, //113: Increased fire rate, reload speed, and health regen to players in a radius + TFCond_SpawnOutline = 114, //114: Outline and health meter of teammates (and disguised spies) + TFCond_KnockedIntoAir = 115, //115: Used when a player is airblasted + TFCond_CompetitiveWinner = 116, //116: Unknown + TFCond_CompetitiveLoser = 117, //117: Unknown + TFCond_NoTaunting_DEPRECATED = 118, //118 + TFCond_HealingDebuff = 118, //118: Healing debuff from Medics and dispensers + TFCond_PasstimePenaltyDebuff = 119, //119: Marked-for-death effect + TFCond_GrappledToPlayer = 120, //120: Prevents taunting and some Grappling Hook actions + TFCond_GrappledByPlayer = 121, //121: Unknown + TFCond_ParachuteDeployed = 122, //122: Parachute deployed, prevents reopening it + TFCond_Gas = 123, //123: Gas Passer effect + TFCond_BurningPyro = 124, //124: Dragon's Fury afterburn on Pyros + TFCond_RocketPack = 125, //125: Thermal Thruster launched effects, prevents reusing + TFCond_LostFooting = 126, //126: Less ground friction + TFCond_AirCurrent = 127, //127: Reduced air control and friction + TFCond_HalloweenHellHeal = 128, // 128: Used when a player gets teleported to hell + TFCond_PowerupModeDominant = 129 // 129: Reduces effects of certain powerups +}TFCond; + +class CTF2Conditions +{ +public: + static bool TF2_IsPlayerInCondition(int client, TFCond cond); +}; + +extern CTF2Conditions *tf2_conditions; + +#endif \ No newline at end of file diff --git a/rcbot/utils.cpp b/rcbot/utils.cpp new file mode 100644 index 000000000..9091dc890 --- /dev/null +++ b/rcbot/utils.cpp @@ -0,0 +1,204 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +#include "eiface.h" +#include "basehandle.h" +#include "IEngineTrace.h" +#include "IStaticPropMgr.h" +#include "bot_plugin_meta.h" +#include "bot.h" +#include "utils.h" + +// interfaces of interest + +extern ICvar* icvar; +extern IVEngineServer* engine; +extern IPlayerInfoManager* playerinfomanager; +extern IServerPluginHelpers* helpers; +extern IServerGameClients* gameclients; +extern IEngineTrace* enginetrace; +extern IBotManager* g_pBotManager; +extern CGlobalVars* gpGlobals; +extern IServerGameEnts* servergameents; +extern IServerGameDLL* servergamedll; +extern IServerTools* servertools; +extern IStaticPropMgrServer* staticpropmgr; + +namespace private_utils +{ + static Vector GetOBBCenter(const ICollideable* collider) + { + Vector result(0.0f, 0.0f, 0.0f); + VectorLerp(collider->OBBMins(), collider->OBBMaxs(), 0.5f, result); + return result; + } + + static bool isBoundsDefinedInEntitySpace(const ICollideable* collider) + { + return ((collider->GetSolidFlags() & FSOLID_FORCE_WORLD_ALIGNED) == 0 && collider->GetSolid() != SOLID_BBOX && collider->GetSolid() != SOLID_NONE); + } + + static Vector collisionToWorldSpace(const Vector& in, const ICollideable* collider) + { + Vector result(0.0f, 0.0f, 0.0f); + + if (!isBoundsDefinedInEntitySpace(collider) || collider->GetCollisionAngles() == vec3_angle) + { + VectorAdd(in, collider->GetCollisionOrigin(), result); + } + else + { + VectorTransform(in, collider->CollisionToWorldTransform(), result); + } + + return result; + } +} + +bool rcbot2utils::IsValidEdict(const edict_t* edict) +{ + if (edict == nullptr || edict->IsFree() || edict->GetIServerEntity() == nullptr) + { + return false; + } + + return true; +} + +int rcbot2utils::IndexOfEdict(const edict_t* edict) +{ +#if SOURCE_ENGINE >= SE_LEFT4DEAD + return static_cast(edict - engine->PEntityOfEntIndex(0)); +#else + return engine->IndexOfEdict(edict); +#endif // SOURCE_ENGINE >= SE_LEFT4DEAD +} + +edict_t* rcbot2utils::EdictOfIndex(const int index) +{ +#if SOURCE_ENGINE >= SE_LEFT4DEAD + if (index >= 0 && index < gpGlobals->maxEntities) + { + return engine->PEntityOfEntIndex(index); + } + + return nullptr; +#else + return engine->PEntityOfEntIndex(index); +#endif // SOURCE_ENGINE >= SE_LEFT4DEAD +} + +edict_t* rcbot2utils::BaseEntityToEdict(CBaseEntity* entity) +{ + return servergameents->BaseEntityToEdict(entity); +} + +CBaseEntity* rcbot2utils::EdictToBaseEntity(edict_t* edict) +{ + return servergameents->EdictToBaseEntity(edict); +} + +edict_t* rcbot2utils::GetEdictFromHandleEntity(const IHandleEntity* pHandleEntity) +{ + IHandleEntity* pHE = const_cast(pHandleEntity); + + if (staticpropmgr->IsStaticProp(pHE)) + { + return nullptr; + } + + IServerUnknown* pUnk = reinterpret_cast(pHE); + CBaseEntity* pBE = pUnk->GetBaseEntity(); + + return BaseEntityToEdict(pBE); +} + +CBaseEntity* rcbot2utils::GetEntityFromHandleEntity(const IHandleEntity* pHandleEntity) +{ + IHandleEntity* pHE = const_cast(pHandleEntity); + + if (staticpropmgr->IsStaticProp(pHE)) + { + return nullptr; + } + + IServerUnknown* pUnk = reinterpret_cast(pHE); + + return pUnk->GetBaseEntity(); +} + +edict_t* rcbot2utils::GetHandleEdict(const CBaseHandle& handle) +{ + if (!handle.IsValid()) + { + return nullptr; + } + + int index = handle.GetEntryIndex(); + edict_t* pEdict = EdictOfIndex(index); + + if (!IsValidEdict(pEdict)) + { + return nullptr; + } + + IServerEntity* pServerEntity = pEdict->GetIServerEntity(); + + if (pServerEntity->GetRefEHandle() != handle) + { + return nullptr; + } + + return pEdict; +} + +void rcbot2utils::SetHandleEdict(CBaseHandle& handle, const edict_t* edict) +{ + const IServerEntity* pServerEntity = edict->GetIServerEntity(); + handle.Set(pServerEntity); +} + +const Vector& rcbot2utils::GetEntityOrigin(edict_t* entity) +{ + return entity->GetCollideable()->GetCollisionOrigin(); +} + +const Vector& rcbot2utils::GetEntityOrigin(CBaseEntity* entity) +{ + return reinterpret_cast(entity)->GetCollideable()->GetCollisionOrigin(); +} + +const QAngle& rcbot2utils::GetEntityAngles(edict_t* entity) +{ + return entity->GetCollideable()->GetCollisionAngles(); +} + +const QAngle& rcbot2utils::GetEntityAngles(CBaseEntity* entity) +{ + return reinterpret_cast(entity)->GetCollideable()->GetCollisionAngles(); +} + +Vector rcbot2utils::GetWorldSpaceCenter(edict_t* entity) +{ + ICollideable* collider = entity->GetCollideable(); + Vector result = private_utils::GetOBBCenter(collider); + result = private_utils::collisionToWorldSpace(result, collider); + return result; +} + +Vector rcbot2utils::GetWorldSpaceCenter(CBaseEntity* entity) +{ + ICollideable* collider = reinterpret_cast(entity)->GetCollideable(); + Vector result = private_utils::GetOBBCenter(collider); + result = private_utils::collisionToWorldSpace(result, collider); + return result; +} + +bool rcbot2utils::PointIsWithinTrigger(edict_t* pEntity, const Vector& vPoint) +{ + Ray_t ray; + trace_t tr; + ICollideable* pCollide = pEntity->GetCollideable(); + ray.Init(vPoint, vPoint); + enginetrace->ClipRayToCollideable(ray, MASK_ALL, pCollide, &tr); + return (tr.startsolid); +} diff --git a/rcbot/utils.h b/rcbot/utils.h new file mode 100644 index 000000000..429cdd1b3 --- /dev/null +++ b/rcbot/utils.h @@ -0,0 +1,139 @@ +/* + * part of https://rcbot2.svn.sourceforge.net/svnroot/rcbot2 + * + * This file is part of RCBot. + * + * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. + * + * RCBot is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * RCBot is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RCBot; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + */ + +#ifndef __RCBOT2_UTIL_FUNCTIONS_H_ +#define __RCBOT2_UTIL_FUNCTIONS_H_ + +/** + * @brief General RCBot2 utility functions. + */ +namespace rcbot2utils +{ + // TO-DO: Migrate functions from CBotGlobals to here. + + /** + * @brief Checks if the given edict is valid. + * @param edict Edict to check. + * @return True if valid, false otherwise. + */ + bool IsValidEdict(const edict_t* edict); + /** + * @brief Gets the index of an edict. + * @param edict Edict ptr. + * @return Index of the edict. + */ + int IndexOfEdict(const edict_t* edict); + /** + * @brief Gets an edict from an index. + * @param index Entity index. + * @return Edict pointer or NULL on failure. + */ + edict_t* EdictOfIndex(int index); + // Converts a CBaseEntity into an edict_t + edict_t* BaseEntityToEdict(CBaseEntity* entity); + // Converts an edict_t into a CBaseEntity + CBaseEntity* EdictToBaseEntity(edict_t* edict); + /** + * @brief Converts an IHandleEntity to edict_t. Used to get entities in the trace filter callback function. + * @param pHandleEntity Entity to convert. + * @return edict_t* pointer. May be NULL. + */ + edict_t* GetEdictFromHandleEntity(const IHandleEntity* pHandleEntity); + /** + * @brief Converts an IHandleEntity to CBaseEntity. Used to get entities in the trace filter callback function. + * @param pHandleEntity Entity to convert. + * @return CBaseEntity pointer. May be NULL. + */ + CBaseEntity* GetEntityFromHandleEntity(const IHandleEntity* pHandleEntity); + /** + * @brief Dereferences the given handle and converts to an edict_t. + * @param handle Handle to dereference. + * @return Edict pointer or NULL if the entity stored is no longer valid. + */ + edict_t* GetHandleEdict(const CBaseHandle& handle); + /** + * @brief Stores an edict on a handle. + * @param handle Handle to store the entity. + * @param edict Edict to store. + */ + void SetHandleEdict(CBaseHandle& handle, const edict_t* edict); + /** + * @brief Returns the entity origin (generally this calls GetAbsOrigin). + * + * For brush entities, this will generally always return 0,0,0. Use WorldSpaceCenter for brush entities. + * @param entity Entity to get the origin from. + * @return Entity position. + */ + const Vector& GetEntityOrigin(edict_t* entity); + /** + * @brief Returns the entity origin (generally this calls GetAbsOrigin). + * + * For brush entities, this will generally always return 0,0,0. Use WorldSpaceCenter for brush entities. + * @param entity Entity to get the origin from. + * @return Entity position. + */ + const Vector& GetEntityOrigin(CBaseEntity* entity); + /** + * @brief Returns the entity angles (generally this calls GetAbsAngles). + * @param entity Entity to get the angles from. + * @return Entity Angles. + */ + const QAngle& GetEntityAngles(edict_t* entity); + /** + * @brief Returns the entity angles (generally this calls GetAbsAngles). + * @param entity Entity to get the angles from. + * @return Entity Angles. + */ + const QAngle& GetEntityAngles(CBaseEntity* entity); + /** + * @brief Gets the entity World Space Center. + * @param entity Entity to get the WSC from. + * @return Entity's world space center position. + */ + Vector GetWorldSpaceCenter(edict_t* entity); + /** + * @brief Gets the entity World Space Center. + * @param entity Entity to get the WSC from. + * @return Entity's world space center position. + */ + Vector GetWorldSpaceCenter(CBaseEntity* entity); + /** + * @brief Checks if a given point is within the trigger bounds of an entity. + * @param pEntity Entity to test. + * @param vPoint Point to test. + * @return True if the given point is within, false otherwise. + */ + bool PointIsWithinTrigger(edict_t* pEntity, const Vector& vPoint); +} + +#endif // !__RCBOT2_UTIL_FUNCTIONS_H_ diff --git a/rcbot_subcmds/config.cpp b/rcbot_subcmds/config.cpp new file mode 100644 index 000000000..8f3d27ef6 --- /dev/null +++ b/rcbot_subcmds/config.cpp @@ -0,0 +1,119 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +/* + * This file is part of RCBot. + * + * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. + * + * RCBot is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * RCBot is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RCBot; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + */ + +#pragma push_macro("clamp") //Fix for C++17 [APG]RoboCop[CL] +#undef clamp +#include +#include +#pragma pop_macro("clamp") + +//caxanga334: SDK 2013 contains macros for std::min and std::max which causes errors when compiling +//#if SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_BMS +#include "valve_minmax_off.h" +//#endif + +constexpr int INVALID_BOT_COUNT = -1; + +CBotCommandInline GameEventVersion("event_version", CMD_ACCESS_CONFIG, [](CClient* pClient, const BotCommandArgs& args) + { + if (!args[0] || !*args[0]) + return COMMAND_ERROR; + + CBotGlobals::setEventVersion(std::atoi(args[0])); + + return COMMAND_ACCESSED; + }); + +namespace +{ + void SetBotLimit(const CClient* pClient, const BotCommandArgs& args, const char* commandName, + const std::function& setter, const std::function& getter, + const std::function& validation, const char* validationMessage) + { + edict_t* pEntity = pClient ? pClient->getPlayer() : nullptr; + + if (args[0] && *args[0]) + { + int value = std::atoi(args[0]); + bool hasError = false; + + if (value <= INVALID_BOT_COUNT) + { + value = INVALID_BOT_COUNT; + } + else if (validation(value, getter())) + { + CBotGlobals::botMessage(pEntity, 0, validationMessage, static_cast(getter())); + hasError = true; + } + + value = std::min(value, CBotGlobals::maxClients()); + + if (!hasError) + { + setter(value); + CBotGlobals::botMessage(pEntity, 0, "%s set to %d", commandName, value); + } + } + else + { + CBotGlobals::botMessage(pEntity, 0, "%s is currently %d", commandName, static_cast(getter())); + } + } +} + +CBotCommandInline MaxBotsCommand("max_bots", CMD_ACCESS_CONFIG | CMD_ACCESS_DEDICATED, [](const CClient* pClient, const BotCommandArgs& args) + { + SetBotLimit(pClient, args, "max_bots", + CBots::setMaxBots, CBots::getMinBots, + [](int maxBots, int minBots) { return (minBots >= 0) && (maxBots <= minBots); }, + "max_bots must be greater than min_bots (min_bots is currently: %d)"); + + return COMMAND_ACCESSED; + }); + +CBotCommandInline MinBotsCommand("min_bots", CMD_ACCESS_CONFIG | CMD_ACCESS_DEDICATED, [](const CClient* pClient, const BotCommandArgs& args) + { + SetBotLimit(pClient, args, "min_bots", + CBots::setMinBots, CBots::getMaxBots, + [](int minBots, int maxBots) { return (maxBots >= 0) && (minBots >= maxBots); }, + "min_bots must be less than max_bots (max_bots is currently: %d)"); + + return COMMAND_ACCESSED; + }); + +CBotSubcommands ConfigSubcommands("config", CMD_ACCESS_DEDICATED, { +&GameEventVersion, +&MaxBotsCommand, +&MinBotsCommand +}); \ No newline at end of file diff --git a/rcbot_subcmds/debug.cpp b/rcbot_subcmds/debug.cpp new file mode 100644 index 000000000..1d06c4d82 --- /dev/null +++ b/rcbot_subcmds/debug.cpp @@ -0,0 +1,848 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +/* + * This file is part of RCBot. + * + * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. + * + * RCBot is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * RCBot is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RCBot; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + */ + +#include +#include + +#include "bot_commands.h" +#include "bot_fortress.h" +#include "bot_globals.h" +#include "bot_waypoint.h" + +CBotCommandInline DebugGameEventCommand("gameevent", CMD_ACCESS_DEBUG, [](CClient* pClient, const BotCommandArgs& args) +{ + if (!args[0] || !*args[0]) { + return COMMAND_ERROR; + } + pClient->setDebug(BOT_DEBUG_GAME_EVENT, std::atoi(args[0]) > 0); + return COMMAND_ACCESSED; +}, "usage \"gameevent 1 or 0, 1 on, 0 off\" : shows event output"); + +CBotCommandInline DebugBotCommand("bot", CMD_ACCESS_DEBUG, [](CClient* pClient, const BotCommandArgs& args) +{ + if (!args[0] || !*args[0]) { + // do a traceline in front of player + + const Vector vOrigin = pClient->getOrigin(); + const QAngle angles = CBotGlobals::entityEyeAngles(pClient->getPlayer()); + Vector forward; + + AngleVectors(angles, &forward); + + CBotGlobals::quickTraceline(pClient->getPlayer(), vOrigin, vOrigin + forward * 1024.0f); + CBaseEntity* pEntity; + + if ((pEntity = CBotGlobals::getTraceResult()->m_pEnt) != nullptr) + { + extern IServerGameEnts* servergameents; + if (edict_t* pEdict = servergameents->BaseEntityToEdict(pEntity); CBots::getBotPointer(pEdict) != nullptr) + { + pClient->setDebugBot(pEdict); + CBotGlobals::botMessage(pClient->getPlayer(), 0, "debug bot set to bot you are looking at"); + return COMMAND_ACCESSED; + } + pClient->setDebugBot(nullptr); + CBotGlobals::botMessage(pClient->getPlayer(), 0, "debug bot cleared"); + } + else + { + pClient->setDebugBot(nullptr); + CBotGlobals::botMessage(pClient->getPlayer(), 0, "debug bot cleared"); + } + return COMMAND_ERROR; + } + + const edict_t* pEnt = CBotGlobals::findPlayerByTruncName(args[0]); + + if (!pEnt) + { + CBotGlobals::botMessage(pClient->getPlayer(), 0, "can't find a player with that name"); + return COMMAND_ERROR; + } + + const CBot* pBot = CBots::getBotPointer(pEnt); + + if (!pBot) + { + CBotGlobals::botMessage(pClient->getPlayer(), 0, "can't find a bot with that name"); + return COMMAND_ERROR; + } + + pClient->setDebugBot(pBot->getEdict()); + + return COMMAND_ACCESSED; +}, "usage \"bot , or just bot to switch off : shows bot debug output on listen server"); + +CBotCommandInline DebugNavCommand("nav", CMD_ACCESS_DEBUG, [](CClient* pClient, const BotCommandArgs& args) +{ + if (!args[0] || !*args[0]) + return COMMAND_ERROR; + + pClient->setDebug(BOT_DEBUG_NAV, std::atoi(args[0]) > 0); + + return COMMAND_ACCESSED; +}, "usage \"nav 1 or 0, 1 on, 0 off\" : shows navigation output"); + +CBotCommandInline DebugVisCommand("vis", CMD_ACCESS_DEBUG, [](CClient* pClient, const BotCommandArgs& args) +{ + if (!args[0] || !*args[0]) + return COMMAND_ERROR; + + pClient->setDebug(BOT_DEBUG_VIS, std::atoi(args[0]) > 0); + + return COMMAND_ACCESSED; +}, "usage \"vis 1 or 0, 1 on, 0 off\" : shows bot visibility output"); + +CBotCommandInline DebugThinkCommand("think", CMD_ACCESS_DEBUG, [](CClient* pClient, const BotCommandArgs& args) +{ + if (!args[0] || !*args[0]) + return COMMAND_ERROR; + + pClient->setDebug(BOT_DEBUG_THINK, std::atoi(args[0]) > 0); + + return COMMAND_ACCESSED; +}, "usage \"think 1 or 0, 1 on, 0 off\" : shows bot thinking output"); + +CBotCommandInline DebugLookCommand("look", CMD_ACCESS_DEBUG, [](CClient* pClient, const BotCommandArgs& args) +{ + if (!args[0] || !*args[0]) + return COMMAND_ERROR; + + pClient->setDebug(BOT_DEBUG_LOOK, std::atoi(args[0]) > 0); + + return COMMAND_ACCESSED; +}, "usage \"look 1 or 0, 1 on, 0 off\" : shows bot look output"); + +CBotCommandInline DebugHudCommand("hud", CMD_ACCESS_DEBUG, [](CClient* pClient, const BotCommandArgs& args) +{ + if (!args[0] || !*args[0]) + return COMMAND_ERROR; + + pClient->setDebug(BOT_DEBUG_HUD, std::atoi(args[0]) > 0); + + return COMMAND_ACCESSED; +}, "usage \"hud 1 or 0, 1 on, 0 off\" : displays most important info about bot on the hud"); + +CBotCommandInline DebugAimCommand("aim", CMD_ACCESS_DEBUG, [](CClient* pClient, const BotCommandArgs& args) +{ + if (!args[0] || !*args[0]) + return COMMAND_ERROR; + + pClient->setDebug(BOT_DEBUG_AIM, std::atoi(args[0]) > 0); + + return COMMAND_ACCESSED; +}, "usage \"aim 1 or 0, 1 on, 0 off\" : displays aiming accuracy info on the hud"); + +CBotCommandInline DebugChatCommand("chat", CMD_ACCESS_DEBUG, [](CClient* pClient, const BotCommandArgs& args) +{ + if (!args[0] || !*args[0]) + return COMMAND_ERROR; + + pClient->setDebug(BOT_DEBUG_CHAT, std::atoi(args[0]) > 0); + + return COMMAND_ACCESSED; +}, "usage \"chat 1 or 0, 1 on, 0 off\" : displays logs in chat"); + +CBotCommandInline BotGoto("bot_goto", CMD_ACCESS_DEBUG, [](CClient* pClient, const BotCommandArgs& args) +{ + if (pClient && pClient->getDebugBot() != nullptr) + { + const edict_t* pEdict = pClient->getDebugBot(); + const CBot* pBot = CBots::getBotPointer(pEdict); + + if (pBot->inUse()) + { + int iWpt; + + if (args[0] && *args[0]) + { + iWpt = std::atoi(args[0]); + + if ((iWpt < 0) || (iWpt >= CWaypoints::numWaypoints())) + iWpt = -1; + } + else + iWpt = pClient->currentWaypoint(); + + if (iWpt != -1) + pBot->forceGotoWaypoint(iWpt); + } + } + + return COMMAND_ACCESSED; +}, "set a debug bot first and then stand near a waypoint to force your bot to go there"); + +CBotCommandInline BotFlush("bot_flush", CMD_ACCESS_DEBUG, [](CClient* pClient, const BotCommandArgs& args) +{ + if (pClient && pClient->getDebugBot() != nullptr) + { + const edict_t* pEdict = pClient->getDebugBot(); + const CBot* pBot = CBots::getBotPointer(pEdict); + + if (pBot->inUse()) + { + CBotSchedules* pSched = pBot->getSchedule(); + pSched->freeMemory(); + } + } + + return COMMAND_ACCESSED; +}, "flush bot tasks"); + +CBotCommandInline DebugTaskCommand("task", CMD_ACCESS_DEBUG, [](CClient* pClient, const BotCommandArgs& args) +{ + if (!args[0] || !*args[0]) + return COMMAND_ERROR; + + pClient->setDebug(BOT_DEBUG_TASK, std::atoi(args[0]) > 0); + + return COMMAND_ACCESSED; +}, "usage \"nav 1 or 0, 1 on, 0 off\" : shows navigation output"); + +CBotCommandInline BotTaskCommand("givetask", CMD_ACCESS_DEBUG, [](CClient* pClient, const BotCommandArgs& args) +{ +#ifndef __linux__ + + if (pClient && pClient->getDebugBot() != nullptr) + { + const edict_t* pEdict = pClient->getDebugBot(); + CBot* pBot = CBots::getBotPointer(pEdict); + + if (pBot->inUse()) + { + CBotSchedules* pSched = pBot->getSchedule(); + + if (args[0] && *args[0]) + { + //int task = atoi(args[0]); + + pSched->freeMemory(); + + // 83 + if (!strcmp(args[0], "pipe")) + { + CBotUtility util = CBotUtility(pBot, BOT_UTIL_PIPE_LAST_ENEMY, true, 1.0f); + pBot->setLastEnemy(pClient->getPlayer()); + pBot->getSchedule()->freeMemory(); + static_cast(pBot)->executeAction(&util); + } + // 71 + else if (!strcmp(args[0], "gren")) + { + CBotWeapons* pWeapons = pBot->getWeapons(); + + if (CBotWeapon* gren = pWeapons->getGrenade()) + { + CBotSchedule* sched = new CBotSchedule( + new CThrowGrenadeTask(gren, pBot->getAmmo(static_cast(gren->getWeaponInfo()->getAmmoIndex1())), + pClient->getOrigin())); + + pSched->add(sched); + } + } + else if (!strcmp(args[0], "snipe")) + { + if (pClient) + { + if (CWaypoint* pWaypoint = CWaypoints::getWaypoint(CWaypoints::nearestWaypointGoal(CWaypointTypes::W_FL_SNIPER, pClient->getOrigin(), 200.0f, pBot->getTeam()))) + { +#if SOURCE_ENGINE == SE_TF2 + //if ( CClassInterface::getTF2Class() ) +#else + CBotSchedule* snipe = new CBotSchedule(); + CBotTask* findpath = new CFindPathTask(CWaypoints::getWaypointIndex(pWaypoint)); + + CBotWeapons* m_pWeapons = pBot->getWeapons(); + CBotWeapon* pWeapon = m_pWeapons->hasWeapon(DOD_WEAPON_K98_SCOPED) + ? m_pWeapons->getWeapon(CWeapons::getWeapon(DOD_WEAPON_K98_SCOPED)) + : m_pWeapons->getWeapon(CWeapons::getWeapon(DOD_WEAPON_SPRING)); + + if (pWeapon) + { + // linux fix - copy origin onto vector here + const Vector vOrigin = pWaypoint->getOrigin(); + CBotTask* snipetask = new CBotDODSnipe(pWeapon, vOrigin, pWaypoint->getAimYaw(), false, 0, pWaypoint->getFlags()); + + findpath->setCompleteInterrupt(CONDITION_PUSH); + snipetask->setCompleteInterrupt(CONDITION_PUSH); + + snipe->setID(SCHED_DEFENDPOINT); + snipe->addTask(findpath); + snipe->addTask(snipetask); + + pSched->add(snipe); + } + else + CBotGlobals::botMessage(nullptr, 0, "Bot is not a sniper"); +#endif + } + else + CBotGlobals::botMessage(nullptr, 0, "Sniper waypoint not found"); + } + } + } + } + } + +#endif + return COMMAND_ACCESSED; +}, "gives a bot a task : usage "); + +CBotCommandInline DebugButtonsCommand("buttons", CMD_ACCESS_DEBUG, [](CClient* pClient, const BotCommandArgs& args) +{ + if (!args[0] || !*args[0]) + return COMMAND_ERROR; + + pClient->setDebug(BOT_DEBUG_BUTTONS, std::atoi(args[0]) > 0); + + return COMMAND_ACCESSED; +}, "usage \"buttons 1 or 0, 1 on, 0 off\" : shows buttons bitmask"); + +CBotCommandInline DebugSpeedCommand("speed", CMD_ACCESS_DEBUG, [](CClient* pClient, const BotCommandArgs& args) +{ + if (!args[0] || !*args[0]) + return COMMAND_ERROR; + + pClient->setDebug(BOT_DEBUG_SPEED, std::atoi(args[0]) > 0); + + return COMMAND_ACCESSED; +}, "usage \"speed 1 or 0, 1 on, 0 off\" : shows speed"); + +CBotCommandInline DebugUsercmdCommand("usercmd", CMD_ACCESS_DEBUG, [](CClient* pClient, const BotCommandArgs& args) +{ + if (!args[0] || !*args[0]) + return COMMAND_ERROR; + + pClient->setDebug(BOT_DEBUG_USERCMD, std::atoi(args[0]) > 0); + + return COMMAND_ACCESSED; +}, "usage \"usercmd 1 or 0, 1 on, 0 off\" : shows last user command output"); + +CBotCommandInline DebugUtilCommand("util", CMD_ACCESS_DEBUG, [](CClient* pClient, const BotCommandArgs& args) +{ + if (!args[0] || !*args[0]) + return COMMAND_ERROR; + + pClient->setDebug(BOT_DEBUG_UTIL, std::atoi(args[0]) > 0); + + return COMMAND_ACCESSED; +}, "usage \"util 1 or 0, 1 on, 0 off\" : shows utility/action output"); + +CBotCommandInline DebugProfilingCommand("profiling", CMD_ACCESS_DEBUG, [](CClient* pClient, const BotCommandArgs& args) +{ + if (!args[0] || !*args[0]) + return COMMAND_ERROR; + + pClient->setDebug(BOT_DEBUG_PROFILE, std::atoi(args[0]) > 0); + + return COMMAND_ACCESSED; +}, "usage \"profiling 1 or 0, 1 on, 0 off\" : shows performance profiling"); + +CBotCommandInline DebugEdictsCommand("edicts", CMD_ACCESS_DEBUG, [](CClient* pClient, const BotCommandArgs& args) +{ + if (!args[0] || !*args[0]) + return COMMAND_ERROR; + + pClient->setDebug(BOT_DEBUG_EDICTS, std::atoi(args[0]) > 0); + + return COMMAND_ACCESSED; +}, "usage \"edicts 1 or 0, 1 on, 0 off\" : shows allocated/freed edicts"); + +CBotCommandInline PrintProps("printprops", CMD_ACCESS_DEBUG, + [](const CClient* pClient, const BotCommandArgs& args) + { + if (pClient) + { + + if (args[0] && *args[0]) + { + extern bool g_PrintProps; + unsigned m_offset; + g_PrintProps = true; + + if (const ServerClass* sc = UTIL_FindServerClass(args[0])) + UTIL_FindSendPropInfo(sc, "", &m_offset); + + g_PrintProps = false; + } + + return COMMAND_ACCESSED; + } + + return COMMAND_ERROR; + }); + +CBotCommandInline SetProp("setprop", CMD_ACCESS_DEBUG, [](const CClient* pClient, const BotCommandArgs& args) +{ + if (pClient) + { + // classname // key // type //value + if ((args[0] && *args[0]) && (args[1] && *args[1]) && (args[2] && *args[2]) && (args[3] && *args[3])) + { + edict_t* pPlayer = pClient->getPlayer(); + edict_t* pNearest = nullptr; + + pNearest = CClassInterface::FindEntityByNetClassNearest(pClient->getOrigin(), args[0]); + + if (pNearest) + { + extern bool g_PrintProps; + unsigned m_offset; + + if (const ServerClass* sc = UTIL_FindServerClass(args[0])) + { + UTIL_FindSendPropInfo(sc, args[1], &m_offset); + + if (m_offset) + { + static IServerUnknown* pUnknown; + static CBaseEntity* pEntity; + + pUnknown = pNearest->GetUnknown(); + pEntity = pUnknown->GetBaseEntity(); + + if (void* data = reinterpret_cast(pEntity) + m_offset) + { + bool* booldata = static_cast(data); + int* intdata = static_cast(data); + float* floatdata = static_cast(data); + + if (strcmp(args[2], "int") == 0) + *intdata = std::atoi(args[3]); + else if (strcmp(args[2], "bool") == 0) + *booldata = (std::atoi(args[3]) == 1); + else if (strcmp(args[2], "float") == 0) + *floatdata = static_cast(std::atof(args[3])); + } + else + CBotGlobals::botMessage(pPlayer, 0, "NULL"); + } + else + CBotGlobals::botMessage(nullptr, 0, "OFFSET NOT FOUND"); + } + else + CBotGlobals::botMessage(nullptr, 0, "CLASS NOT FOUND"); + } + else + CBotGlobals::botMessage(nullptr, 0, "EDICT NOT FOUND"); + } + else + CBotGlobals::botMessage(nullptr, 0, "Usage: getprop CLASSNAME KEY TYPE(int,bool,float) VALUE"); + + return COMMAND_ACCESSED; + } + + return COMMAND_ERROR; +}); + +CBotCommandInline GetProp("getprop", CMD_ACCESS_DEBUG, [](const CClient* pClient, const BotCommandArgs& args) +{ + if (pClient) + { + if ((args[0] && *args[0]) && (args[1] && *args[1])) + { + edict_t* pPlayer = pClient->getPlayer(); + + if (edict_t* pNearest = CClassInterface::FindEntityByNetClassNearest(pClient->getOrigin(), args[0])) + { + extern bool g_PrintProps; + unsigned m_offset = 0; + + if (const ServerClass* sc = UTIL_FindServerClass(args[0])) + { + UTIL_FindSendPropInfo(sc, args[1], &m_offset); + + if (m_offset) + { + IServerUnknown* pUnknown = pNearest->GetUnknown(); + CBaseEntity* pEntity = pUnknown->GetBaseEntity(); + + int preoffs = 0; + if (args[2] && *args[2]) + { + preoffs = std::atoi(args[2]); + } + + if (void* data = reinterpret_cast(pEntity) + m_offset) + { + const Vector vdata = *(static_cast(data) + preoffs); + + CBotGlobals::botMessage(pPlayer, 0, "int = %d, float = %f, bool = %s, Vector = (%0.4f,%0.4f,%0.4f)", + *(static_cast(data) + preoffs), + *(static_cast(data) + preoffs), + (*(static_cast(data) + preoffs) ? "true" : "false"), + vdata.x, vdata.y, vdata.z); + } + else + { + CBotGlobals::botMessage(pPlayer, 0, "NULL"); + } + } + else + { + CBotGlobals::botMessage(nullptr, 0, "OFFSET NOT FOUND"); + } + } + else + { + CBotGlobals::botMessage(nullptr, 0, "CLASS NOT FOUND"); + } + } + else + { + CBotGlobals::botMessage(nullptr, 0, "EDICT NOT FOUND"); + } + } + else + { + CBotGlobals::botMessage(nullptr, 0, "Usage: getprop CLASS CLASSNAME KEY"); + } + + return COMMAND_ACCESSED; + } + + return COMMAND_ERROR; +}); + +CBotCommandInline FindClass("findclass", CMD_ACCESS_DEBUG, [](const CClient* pClient, const BotCommandArgs& args) +{ + if (pClient) + { + if (args[0] && *args[0]) + { + UTIL_FindServerClassPrint(args[0]); + } + + return COMMAND_ACCESSED; + } + + return COMMAND_ERROR; +}); + +CBotCommandInline FindClassname("findclassname", CMD_ACCESS_DEBUG, [](const CClient* pClient, const BotCommandArgs& args) +{ + if (pClient) + { + if (args[0] && *args[0]) + { + if (const char* pclass = CClassInterface::FindEntityNetClass(0, args[0])) + { + CBotGlobals::botMessage(pClient->getPlayer(), 0, "%s network name = %s", args[0], pclass); + } + else + { + CBotGlobals::botMessage(pClient->getPlayer(), 0, "%s network name not found", args[0]); + } + } + + return COMMAND_ACCESSED; + } + + return COMMAND_ERROR; +}); + +CBotCommandInline FindProp("findprop", CMD_ACCESS_DEBUG, [](CClient* pClient, const BotCommandArgs& args) +{ + if (args[0] && *args[0]) + { + UTIL_FindPropPrint(args[0]); + return COMMAND_ACCESSED; + } + + return COMMAND_ERROR; +}, "Usage: findprop "); + +enum : std::uint8_t +{ + MEMSEARCH_BYTE = 1, + MEMSEARCH_INT = 2, + MEMSEARCH_FLOAT = 3, + MEMSEARCH_STRING = 4 +}; + +enum : std::uint16_t +{ + MAX_MEM_SEARCH = 8192 +}; + +typedef union +{ + struct + { + unsigned searched : 1; // already searched + unsigned found : 1; // offset found + unsigned unused : 6; + } b1; + + byte data; +} u_MEMSEARCH; + +static u_MEMSEARCH stored_offsets[MAX_MEM_SEARCH]; +static unsigned m_size; + +CBotCommandInline DebugMemoryScanCommand("memoryscan", CMD_ACCESS_DEBUG, [](const CClient* pClient, const BotCommandArgs& args) +{ + NEED_ARG(args[0]) + NEED_ARG(args[1]) + NEED_ARG(args[2]) + + const unsigned m_prev_size = m_size; + + if ((strcmp(args[2], "bool") == 0) || (strcmp(args[2], "byte") == 0)) + m_size = MEMSEARCH_BYTE; + else if (strcmp(args[2], "int") == 0) + m_size = MEMSEARCH_INT; + else if (strcmp(args[2], "float") == 0) + m_size = MEMSEARCH_FLOAT; + else if (strcmp(args[2], "string") == 0) + m_size = MEMSEARCH_STRING; + else + m_size = 0; + + if ((m_prev_size != m_size) || ((m_size == 0) || !args[3] || !*args[3]) || (std::atoi(args[3]) == 0)) + { + std::memset(stored_offsets, 0, sizeof(u_MEMSEARCH) * MAX_MEM_SEARCH); + } + + edict_t* pEdict = CClassInterface::FindEntityByClassnameNearest(pClient->getOrigin(), args[0]); + + if (pEdict == nullptr) + { + CBotGlobals::botMessage(pClient->getPlayer(), 0, "Edict not found"); + return COMMAND_ERROR; + } + + CBaseEntity* pent = pEdict->GetUnknown()->GetBaseEntity(); + + byte* mempoint = reinterpret_cast(pent); + const byte value = static_cast(std::atoi(args[1])); + const int ivalue = (std::atoi(args[1])); + const float fvalue = static_cast(std::atof(args[1])); + + for (u_MEMSEARCH& stored_offset : stored_offsets) + { + bool bfound = false; + + if (m_size == MEMSEARCH_BYTE) + bfound = (value == *mempoint); + else if (m_size == MEMSEARCH_INT) + bfound = (ivalue == *reinterpret_cast(mempoint)); + else if (m_size == MEMSEARCH_FLOAT) + bfound = (fvalue == *reinterpret_cast(mempoint)); + else if (m_size == MEMSEARCH_STRING) + { + try + { + const string_t* str = reinterpret_cast(mempoint); + + if (str != nullptr) + { + if (const char* pszstr = STRING(*str)) + bfound = (strcmp(pszstr, args[1]) == 0); + } + } + catch (...) + { + CBotGlobals::botMessage(pClient->getPlayer(), 0, "Invalid string"); + } + } + + if (bfound) + { + if (!stored_offset.b1.searched) + stored_offset.b1.found = 1; + } + else if (stored_offset.b1.searched) + stored_offset.b1.found = 0; + + stored_offset.b1.searched = 1; + + mempoint++; + } + + for (int i = 0; i < MAX_MEM_SEARCH; i++) + { + if (stored_offsets[i].data != 0) + { + if (stored_offsets[i].b1.found) + CBotGlobals::botMessage(pClient->getPlayer(), 0, "%d", i); + } + } + + return COMMAND_ACCESSED; +}, "usage \"memoryscan [store last = 1]\""); + +CBotCommandInline DebugMemoryCheckCommand("memorycheck", CMD_ACCESS_DEBUG, [](const CClient* pClient, const BotCommandArgs& args) +{ + NEED_ARG(args[0]) + NEED_ARG(args[1]) + NEED_ARG(args[2]) + + edict_t* pEdict = CClassInterface::FindEntityByClassnameNearest(pClient->getOrigin(), args[0]); + + if (pEdict == nullptr) + { + CBotGlobals::botMessage(pClient->getPlayer(), 0, "Edict not found"); + return COMMAND_ERROR; + } + + CBaseEntity* pent = pEdict->GetUnknown()->GetBaseEntity(); + + const unsigned offset = std::atoi(args[1]); + + if ((strcmp(args[2], "bool") == 0) || (strcmp(args[2], "byte") == 0)) + { + CBotGlobals::botMessage( + pClient->getPlayer(), + 0, + "%s - offset %d - Value(byte) = %d", + args[0], + offset, + *reinterpret_cast(reinterpret_cast(pent) + offset) + ); + } + else if (strcmp(args[2], "int") == 0) + { + CBotGlobals::botMessage( + pClient->getPlayer(), + 0, + "%s - offset %d - Value(int) = %d", + args[0], + offset, + *reinterpret_cast(reinterpret_cast(pent) + offset) + ); + } + else if (strcmp(args[2], "float") == 0) + { + CBotGlobals::botMessage( + pClient->getPlayer(), + 0, + "%s - offset %d - Value(float) = %0.6f", + args[0], + offset, + *reinterpret_cast(reinterpret_cast(pent) + offset) + ); + } + else if (strcmp(args[2], "string") == 0) + { + if (const string_t* str = reinterpret_cast(reinterpret_cast(pent) + offset * sizeof(string_t))) + CBotGlobals::botMessage(pClient->getPlayer(), 0, "%s - offset %d - Value(string) = %s", args[0], offset, STRING(*str)); + else + CBotGlobals::botMessage(pClient->getPlayer(), 0, "%s - offset %d - INVALID string", args[0], offset); + } + else + { + return COMMAND_ERROR; + } + + return COMMAND_ACCESSED; +}, "usage \"memorycheck \""); + +CBotCommandInline DebugMstrOffsetSearch("mstr_offset_search", CMD_ACCESS_DEBUG, [](const CClient* pClient, const BotCommandArgs& args) +{ + if (strcmp("cp_dustbowl", STRING(gpGlobals->mapname)) != 0) + { + CBotGlobals::botMessage(pClient->getPlayer(), 0, "Command can only be used on cp_dustbowl -- change the map first"); + return COMMAND_ERROR; + } + + edict_t* pMaster = CClassInterface::FindEntityByClassnameNearest(Vector(0, 0, 0), "team_control_point_master", 65535); + + if (pMaster == nullptr) + { + CBotGlobals::botMessage(pClient->getPlayer(), 0, "pMaster not found -- have you started the game yet?"); + return COMMAND_ERROR; + } + + extern IServerGameEnts* servergameents; + + CBaseEntity* pMasterEntity = servergameents->EdictToBaseEntity(pMaster); + + unsigned long offset = 800; + + while (offset < 1000) + { + const std::uintptr_t mempoint = reinterpret_cast(pMasterEntity) + offset; + const CTeamControlPointMaster* PointMaster = reinterpret_cast(mempoint); + + try + { + if (PointMaster->m_iTeamBaseIcons[0] == 0 && PointMaster->m_iTeamBaseIcons[2] == 5 && PointMaster->m_iTeamBaseIcons[3] == 6) + { + if (strcmp(PointMaster->m_iszTeamBaseIcons[3].ToCStr(), "sprites/obj_icons/icon_base_blu") == 0) + { + CBotGlobals::botMessage(pClient->getPlayer(), 0, "pMaster offset is %d", offset); + return COMMAND_ACCESSED; + } + } + } + catch (...) + { + // SEH handling + } + + offset++; + } + return COMMAND_ACCESSED; +}, "usage \"mstr_offset_search\" must be run on cp_dustbowl only"); + +CBotSubcommands DebugSubcommands("debug", CMD_ACCESS_DEBUG | CMD_ACCESS_DEDICATED, { + &DebugGameEventCommand, + &DebugBotCommand, + &DebugNavCommand, + &DebugVisCommand, + &DebugThinkCommand, + &DebugLookCommand, + &DebugHudCommand, + &DebugAimCommand, + &DebugChatCommand, + &BotGoto, + &BotFlush, + &DebugTaskCommand, + &BotTaskCommand, + &DebugButtonsCommand, + &DebugSpeedCommand, + &DebugUsercmdCommand, + &DebugUtilCommand, + &DebugProfilingCommand, + &DebugEdictsCommand, + &PrintProps, + &GetProp, + &SetProp, + &FindClass, + &FindClassname, + &FindProp, + &DebugMemoryScanCommand, + &DebugMemoryCheckCommand, + &DebugMstrOffsetSearch, +}); \ No newline at end of file diff --git a/rcbot_subcmds/pathwaypoint.cpp b/rcbot_subcmds/pathwaypoint.cpp new file mode 100644 index 000000000..73f2e2d16 --- /dev/null +++ b/rcbot_subcmds/pathwaypoint.cpp @@ -0,0 +1,250 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +/* + * This file is part of RCBot. + * + * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. + * + * RCBot is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * RCBot is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RCBot; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + */ + +namespace { // Use an anonymous namespace to limit the scope of the helper function + eBotCommandResult PerformWaypointPathAction(CClient* pClient, const BotCommandArgs& args, + const std::function& pathAction, + const char* successMessage, const char* successSound) + { + if (!pClient || !args[0] || !*args[0] || !args[1] || !*args[1]) + { + CBotGlobals::botMessage(pClient ? pClient->getPlayer() : nullptr, 0, "missing args "); + return COMMAND_ERROR; + } + + const int id1 = std::atoi(args[0]); + const int id2 = std::atoi(args[1]); + + if (CWaypoint* pWaypoint1 = CWaypoints::getWaypoint(id1)) + { + if (pWaypoint1->isUsed()) + { + if (CWaypoint* pWaypoint2 = CWaypoints::getWaypoint(id2)) + { + if (pWaypoint2->isUsed()) + { + pathAction(pWaypoint1, id2); + CBotGlobals::botMessage(pClient->getPlayer(), 0, successMessage, id1, id2); + + pWaypoint1->draw(pClient->getPlayer(), true, DRAWTYPE_DEBUGENGINE); + pWaypoint1->info(pClient->getPlayer()); + pWaypoint2->draw(pClient->getPlayer(), true, DRAWTYPE_DEBUGENGINE); + pWaypoint2->info(pClient->getPlayer()); + + pClient->playSound(successSound); + + return COMMAND_ACCESSED; + } + } + CBotGlobals::botMessage(pClient->getPlayer(), 0, "Waypoint id <%d> not found", id2); + } + else + { + CBotGlobals::botMessage(pClient->getPlayer(), 0, "Waypoint id <%d> not found", id1); + } + } + else + { + CBotGlobals::botMessage(pClient->getPlayer(), 0, "Waypoint id <%d> not found", id1); + } + + return COMMAND_ERROR; + } +} + +CBotCommandInline PathWaypointOnCommand("on", CMD_ACCESS_WAYPOINT, [](CClient* pClient, const BotCommandArgs& args) + { + if (!pClient) return COMMAND_ERROR; + pClient->setPathWaypoint(true); + pClient->giveMessage("Pathwaypoints visible"); + return COMMAND_ACCESSED; + }); + +CBotCommandInline PathWaypointOffCommand("off", CMD_ACCESS_WAYPOINT, [](CClient* pClient, const BotCommandArgs& args) + { + if (!pClient) return COMMAND_ERROR; + pClient->setPathWaypoint(false); + pClient->giveMessage("Pathwaypoints hidden"); + return COMMAND_ACCESSED; + }); + +CBotCommandInline PathWaypointAutoOnCommand("enable", CMD_ACCESS_WAYPOINT, [](CClient* pClient, const BotCommandArgs& args) + { + if (!pClient) return COMMAND_ERROR; + pClient->setAutoPath(true); + return COMMAND_ACCESSED; + }); + +CBotCommandInline PathWaypointAutoOffCommand("disable", CMD_ACCESS_WAYPOINT, [](CClient* pClient, const BotCommandArgs& args) + { + if (!pClient) return COMMAND_ERROR; + pClient->setAutoPath(false); + return COMMAND_ACCESSED; + }); + +CBotCommandInline PathWaypointCreate1Command("create1", CMD_ACCESS_WAYPOINT, [](CClient* pClient, const BotCommandArgs& args) + { + if (!pClient) return COMMAND_ERROR; + + pClient->updateCurrentWaypoint(); + + if (pClient->currentWaypoint() == -1) + { + pClient->playSound("common/wpn_denyselect.wav"); + } + else + { + pClient->setPathFrom(pClient->currentWaypoint()); + pClient->playSound("common/wpn_hudoff.wav"); + } + + return COMMAND_ACCESSED; + }); + +CBotCommandInline PathWaypointCreate2Command("create2", CMD_ACCESS_WAYPOINT, [](CClient* pClient, const BotCommandArgs& args) + { + if (!pClient) return COMMAND_ERROR; + + pClient->updateCurrentWaypoint(); + pClient->setPathTo(pClient->currentWaypoint()); + + if (CWaypoint* pWpt = CWaypoints::getWaypoint(pClient->getPathFrom())) + { + pWpt->addPathTo(pClient->getPathTo()); + pClient->playSound("buttons/button9"); + } + else + { + pClient->playSound("common/wpn_denyselect"); + } + + return COMMAND_ACCESSED; + }); + +CBotCommandInline PathWaypointRemove1Command("remove1", CMD_ACCESS_WAYPOINT, [](CClient* pClient, const BotCommandArgs& args) + { + if (!pClient) return COMMAND_ERROR; + + pClient->updateCurrentWaypoint(); + + if (pClient->currentWaypoint() != -1) + { + pClient->setPathFrom(pClient->currentWaypoint()); + pClient->playSound("common/wpn_hudoff.wav"); + } + else + { + pClient->playSound("common/wpn_moveselect.wav"); + } + + return COMMAND_ACCESSED; + }); + +CBotCommandInline PathWaypointRemove2Command("remove2", CMD_ACCESS_WAYPOINT, [](CClient* pClient, const BotCommandArgs& args) + { + if (!pClient) return COMMAND_ERROR; + + pClient->updateCurrentWaypoint(); + pClient->setPathTo(pClient->currentWaypoint()); + + if (CWaypoint* pWpt = CWaypoints::getWaypoint(pClient->getPathFrom())) + { + pWpt->removePathTo(pClient->getPathTo()); + pClient->playSound("buttons/button9"); + } + else + { + pClient->playSound("common/wpn_moveselect"); + } + + return COMMAND_ACCESSED; + }); + +CBotCommandInline PathWaypointDeleteToCommand("deleteto", 0, [](CClient* pClient, const BotCommandArgs& args) + { + if (!pClient) return COMMAND_ERROR; + + pClient->updateCurrentWaypoint(); + + if (CWaypoints::validWaypointIndex(pClient->currentWaypoint())) + { + CWaypoints::deletePathsTo(pClient->currentWaypoint()); + } + + return COMMAND_ACCESSED; + }); + +CBotCommandInline PathWaypointDeleteFromCommand("deletefrom", 0, [](CClient* pClient, const BotCommandArgs& args) + { + if (!pClient) return COMMAND_ERROR; + + pClient->updateCurrentWaypoint(); + + if (CWaypoints::validWaypointIndex(pClient->currentWaypoint())) + { + CWaypoints::deletePathsFrom(pClient->currentWaypoint()); + } + + return COMMAND_ACCESSED; + }); + +CBotCommandInline PathWaypointCreateFromToCommand("createfromto", CMD_ACCESS_WAYPOINT, [](CClient* pClient, const BotCommandArgs& args) + { + return PerformWaypointPathAction(pClient, args, + [](CWaypoint* pWpt, const int id) { pWpt->addPathTo(id); }, + "Added path from <%d> to <%d>", + "buttons/button9"); + }); + +CBotCommandInline PathWaypointRemoveFromToCommand("removefromto", CMD_ACCESS_WAYPOINT, [](CClient* pClient, const BotCommandArgs& args) + { + return PerformWaypointPathAction(pClient, args, + [](CWaypoint* pWpt, const int id) { pWpt->removePathTo(id); }, + "Removed path from <%d> to <%d>", + "buttons/button24"); + }); + +CBotSubcommands PathWaypointSubcommands("pathwaypoint", CMD_ACCESS_WAYPOINT | CMD_ACCESS_DEDICATED, { + &PathWaypointOnCommand, + &PathWaypointOffCommand, + &PathWaypointAutoOnCommand, + &PathWaypointAutoOffCommand, + &PathWaypointCreate1Command, + &PathWaypointCreate2Command, + &PathWaypointRemove1Command, + &PathWaypointRemove2Command, + &PathWaypointDeleteToCommand, + &PathWaypointDeleteFromCommand, + &PathWaypointCreateFromToCommand, + &PathWaypointRemoveFromToCommand, + }); \ No newline at end of file diff --git a/rcbot_subcmds/users.cpp b/rcbot_subcmds/users.cpp new file mode 100644 index 000000000..756d0a186 --- /dev/null +++ b/rcbot_subcmds/users.cpp @@ -0,0 +1,56 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +/* + * This file is part of RCBot. + * + * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. + * + * RCBot is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * RCBot is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RCBot; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + */ + +#include "bot_commands.h" + +#include "rcbot/logging.h" + +// Command to show users +CBotCommandInline ShowUsersCommand("show", CMD_ACCESS_USERS | CMD_ACCESS_DEDICATED, [](const CClient* pClient, + const BotCommandArgs& args) + { + if (!pClient) + { + logger->Log(LogLevel::ERROR, "Error: pClient is null"); + return COMMAND_ERROR; + } + + edict_t* pEntity = pClient->getPlayer(); + CAccessClients::showUsers(pEntity); + + return COMMAND_ACCESSED; + }); + +// Subcommands for user-related commands +CBotSubcommands UserSubcommands("users", CMD_ACCESS_DEDICATED, { + &ShowUsersCommand + }); \ No newline at end of file diff --git a/rcbot_subcmds/util.cpp b/rcbot_subcmds/util.cpp new file mode 100644 index 000000000..69577be62 --- /dev/null +++ b/rcbot_subcmds/util.cpp @@ -0,0 +1,192 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +/* + * This file is part of RCBot. + * + * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. + * + * RCBot is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * RCBot is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RCBot; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + */ + +#include +#include + +CBotCommandInline SearchCommand("search", CMD_ACCESS_UTIL, [](const CClient* pClient, const BotCommandArgs& args) + { + edict_t* pPlayer = pClient->getPlayer(); + + for (int i = 0; i < gpGlobals->maxEntities; ++i) + { + edict_t* pEdict = INDEXENT(i); + + if (pEdict && !pEdict->IsFree() && pEdict->m_pNetworkable && pEdict->GetIServerEntity()) + { + float fDistance = (CBotGlobals::entityOrigin(pEdict) - CBotGlobals::entityOrigin(pPlayer)).Length(); + if (fDistance < 128) + { + float fVelocity; + Vector v; + + if (CClassInterface::getVelocity(pEdict, &v)) + fVelocity = v.Length(); + else + fVelocity = 0; + + string_t model = pEdict->GetIServerEntity()->GetModelName(); + + CBotGlobals::botMessage(pPlayer, 0, "(%d) D:%.2f C:'%s', Mid:%d, Mn:'%s' Health=%d, Tm:%d, Fl:%d, Spd=%.2f", + i, fDistance, pEdict->GetClassName(), pEdict->GetIServerEntity()->GetModelIndex(), model.ToCStr(), + static_cast(CClassInterface::getPlayerHealth(pEdict)), CClassInterface::getTeam(pEdict), + pEdict->m_fStateFlags, fVelocity); + } + } + } + + return COMMAND_ACCESSED; + }); + +CBotCommandInline SetTeleportUtilCommand("set_teleport", CMD_ACCESS_UTIL, [](CClient* pClient, const BotCommandArgs& args) + { + if (pClient) + { + pClient->setTeleportVector(); + engine->ClientPrintf(pClient->getPlayer(), "Teleport Position Remembered!"); + return COMMAND_ACCESSED; + } + + return COMMAND_ERROR; + }, "usage: remembers where you want to teleport"); + +CBotCommandInline TeleportUtilCommand("teleport", CMD_ACCESS_UTIL, [](CClient* pClient, const BotCommandArgs& args) + { + if (pClient) + { + const Vector* vTeleport = pClient->getTeleportVector(); + + if (vTeleport != nullptr) + { + CBotGlobals::teleportPlayer(pClient->getPlayer(), *vTeleport); + CBotGlobals::botMessage(pClient->getPlayer(), 0, "teleported to your remembered location"); + + return COMMAND_ACCESSED; + } + else + { + CBotGlobals::botMessage(pClient->getPlayer(), 0, "You need to set a teleport location first with set_teleport."); + } + } + + return COMMAND_ERROR; + }, "usage: first use set_teleport, then this command to go there"); + +CBotCommandInline NoClipCommand("noclip", CMD_ACCESS_UTIL, [](const CClient* pClient, const BotCommandArgs& args) + { + if (pClient) + { + if (edict_t* pEntity = pClient->getPlayer()) + { + byte* movetype = CClassInterface::getMoveTypePointer(pEntity); + if (!movetype) + return COMMAND_ERROR; + + constexpr byte MOVETYPE_MASK = 15; + bool bNoClipEnabled; + + if ((*movetype & MOVETYPE_MASK) != MOVETYPE_NOCLIP) + { + *movetype &= ~MOVETYPE_MASK; + *movetype |= MOVETYPE_NOCLIP; + bNoClipEnabled = true; + } + else + { + *movetype &= ~MOVETYPE_MASK; + *movetype |= MOVETYPE_WALK; + bNoClipEnabled = false; + } + + std::array msg; + snprintf(msg.data(), msg.size(), "%s used no_clip, which is now %s", pClient->getName(), bNoClipEnabled ? "enabled" : "disabled"); + + CBotGlobals::botMessage(pEntity, 0, msg.data()); + return COMMAND_ACCESSED; + } + } + return COMMAND_ERROR; + }, "fly through walls , yeah!"); + +CBotCommandInline GodModeUtilCommand("god", CMD_ACCESS_UTIL, [](const CClient* pClient, const BotCommandArgs& args) + { + if (pClient) + { + if (edict_t* pEntity = pClient->getPlayer()) + { + if (int* playerflags = CClassInterface::getPlayerFlagsPointer(pEntity)) + { + *playerflags ^= FL_GODMODE; + + std::array msg; + snprintf(msg.data(), msg.size(), "god mode %s", (*playerflags & FL_GODMODE) ? "enabled" : "disabled"); + + CBotGlobals::botMessage(pEntity, 0, msg.data()); + + return COMMAND_ACCESSED; + } + } + } + + return COMMAND_ERROR; + }, "usage: toggle for invulnerability!"); + +CBotCommandInline NoTouchCommand("notouch", CMD_ACCESS_UTIL, [](const CClient* pClient, const BotCommandArgs& args) + { + if (pClient) + { + if (edict_t* pEntity = pClient->getPlayer()) + { + if (int* playerflags = CClassInterface::getPlayerFlagsPointer(pEntity)) + { + *playerflags ^= FL_DONTTOUCH; + + std::array msg; + snprintf(msg.data(), msg.size(), "notouch mode %s", (*playerflags & FL_DONTTOUCH) ? "enabled" : "disabled"); + CBotGlobals::botMessage(pEntity, 0, msg.data()); + + return COMMAND_ACCESSED; + } + } + } + + return COMMAND_ERROR; + }, "don't set off capture points etc"); + +CBotSubcommands UtilSubcommands("util", CMD_ACCESS_DEDICATED, { + &SearchCommand, + &SetTeleportUtilCommand, + &TeleportUtilCommand, + &NoClipCommand, + &GodModeUtilCommand, + &NoTouchCommand + }); \ No newline at end of file diff --git a/rcbot_subcmds/waypoint.cpp b/rcbot_subcmds/waypoint.cpp new file mode 100644 index 000000000..6e2d084e5 --- /dev/null +++ b/rcbot_subcmds/waypoint.cpp @@ -0,0 +1,708 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +/* + * This file is part of RCBot. + * + * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. + * + * RCBot is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * RCBot is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RCBot; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + */ + +#include "bot_waypoint.h" + +CBotCommandInline WaypointOnCommand("on", CMD_ACCESS_WAYPOINT, [](CClient *pClient, const BotCommandArgs& args) +{ + if ( pClient ) + { + pClient->setWaypointOn(true); + pClient->giveMessage("Waypoints On"); + } + + return COMMAND_ACCESSED; +}); + +CBotCommandInline WaypointOffCommand("off", CMD_ACCESS_WAYPOINT, [](CClient *pClient, const BotCommandArgs& args) +{ + pClient->setWaypointOn(false); + pClient->giveMessage("Waypoints Off"); + CBotGlobals::botMessage(pClient->getPlayer(),0,"waypoints off"); + + return COMMAND_ACCESSED; +}); + +CBotCommandInline WaypointAddCommand("add", CMD_ACCESS_WAYPOINT, [](CClient *pClient, const BotCommandArgs& args) +{ + CWaypoints::addWaypoint(pClient,args[0],args[1],args[2],args[3]); + + return COMMAND_ACCESSED; +}); + +CBotCommandInline WaypointDeleteCommand("delete", CMD_ACCESS_WAYPOINT, [](CClient* pClient, const BotCommandArgs& args) +{ + if (!pClient) + return COMMAND_ERROR; + + auto deleteWaypointsInRange = [&](const float radius) + { + int numDeleted = 0; + const Vector vOrigin = pClient->getOrigin(); + WaypointList pWpt; + CWaypointLocations::GetAllInArea(vOrigin, &pWpt, -1); + + for (const int i : pWpt) + { + const CWaypoint* pWaypoint = CWaypoints::getWaypoint(i); + if (pWaypoint && pWaypoint->distanceFrom(vOrigin) < radius) + { + CWaypoints::deleteWaypoint(i); + numDeleted++; + } + } + + if (numDeleted > 0) + { + CBotGlobals::botMessage(pClient->getPlayer(), 0, "%d waypoints within range of %.0f deleted", numDeleted, radius); + pClient->updateCurrentWaypoint(); + pClient->playSound("buttons/combine_button_locked"); + pClient->giveMessage("Waypoints deleted"); + } + else + { + CBotGlobals::botMessage(pClient->getPlayer(), 0, "No waypoints within range of %.0f", radius); + pClient->playSound("weapons/wpn_denyselect"); + pClient->giveMessage("No waypoints deleted"); + } + }; + + if (args[0] && *args[0]) + { + const float radius = static_cast(std::atof(args[0])); + if (radius > 0) + { + deleteWaypointsInRange(radius); + } + else + { + CBotGlobals::botMessage(pClient->getPlayer(), 0, "Invalid radius value"); + return COMMAND_ERROR; + } + } + else + { + pClient->updateCurrentWaypoint(); + if (CWaypoints::validWaypointIndex(pClient->currentWaypoint())) + { + CWaypoints::deleteWaypoint(pClient->currentWaypoint()); + CBotGlobals::botMessage(pClient->getPlayer(), 0, "Waypoint %d deleted", pClient->currentWaypoint()); + pClient->updateCurrentWaypoint(); + pClient->playSound("buttons/combine_button_locked"); + pClient->giveMessage("Waypoint deleted"); + } + else + { + CBotGlobals::botMessage(pClient->getPlayer(), 0, "No waypoint nearby to delete"); + pClient->playSound("weapons/wpn_denyselect"); + pClient->giveMessage("No Waypoint"); + } + } + + return COMMAND_ACCESSED; +}); + +CBotCommandInline WaypointInfoCommand("info", CMD_ACCESS_WAYPOINT, [](CClient *pClient, const BotCommandArgs& args) +{ + pClient->updateCurrentWaypoint(); + + if ( CWaypoint *pWpt = CWaypoints::getWaypoint(pClient->currentWaypoint()) ) + pWpt->info(pClient->getPlayer()); + + return COMMAND_ACCESSED; +}); + +CBotCommandInline WaypointSaveCommand("save", CMD_ACCESS_WAYPOINT, [](CClient *pClient, const BotCommandArgs& args) +{ + if ( CWaypoints::save(false,(pClient!= nullptr)?pClient->getPlayer(): nullptr,((args[0]!= nullptr) && (*args[0]!=0))?args[0]: nullptr,((args[1]!= nullptr) && (*args[1]!=0))?args[1]: nullptr) ) + { + CBotGlobals::botMessage(nullptr,0,"waypoints saved"); + if ( pClient ) + pClient->giveMessage("Waypoints Saved"); + } + else + CBotGlobals::botMessage(nullptr,0,"error: could not save waypoints"); + + return COMMAND_ACCESSED; +}); + +CBotCommandInline WaypointLoadCommand("load", CMD_ACCESS_WAYPOINT, [](CClient* pClient, const BotCommandArgs& args) +{ + const char* mapNameToLoad = (args[0] && *args[0]) ? args[0] : CBotGlobals::getMapName(); + const bool bLoadOK = CWaypoints::load(mapNameToLoad); + + if (bLoadOK) + CBotGlobals::botMessage(nullptr, 0, "waypoints %s loaded", mapNameToLoad); + else + CBotGlobals::botMessage(nullptr, 0, "error: could not load %s waypoints", mapNameToLoad); + + return COMMAND_ACCESSED; +}); + + +CBotCommandInline WaypointClearCommand("clear", CMD_ACCESS_WAYPOINT, [](const CClient *pClient, const BotCommandArgs& args) +{ + CWaypoints::init(); + CBotGlobals::botMessage(pClient->getPlayer(),0,"waypoints cleared"); + + return COMMAND_ACCESSED; +}); + +CBotCommandInline WaypointGiveTypeCommand("givetype", CMD_ACCESS_WAYPOINT, [](CClient *pClient, const BotCommandArgs& args) +{ + edict_t *pEntity = pClient->getPlayer(); + + if ( args[0] && *args[0] ) + { + if ( pClient->currentWaypoint() == -1 ) + CBotGlobals::botMessage(pEntity,0,"No waypoint nearby to give types (move closer to the waypoint you want to give types)"); + else + { + char *type = nullptr; + constexpr int NUM_ARGS = 4; + + for (int i = 0; i < NUM_ARGS; i++) + { + if ( i == 0 ) + type = const_cast(args[0]); + else if ( i == 1 ) + type = const_cast(args[1]); + else if ( i == 2 ) + type = const_cast(args[2]); + else if ( i == 3 ) + type = const_cast(args[3]); + + if ( !type || !*type ) + break; + + if ( const CWaypointType *pType = CWaypointTypes::getType(type) ) + { + if ( CWaypoint *pWaypoint = CWaypoints::getWaypoint(pClient->currentWaypoint()) ) + { + if ( pWaypoint->hasFlag(pType->getBits()) ) + { + pWaypoint->removeFlag(pType->getBits()); + CBotGlobals::botMessage(pEntity,0,"type %s removed from waypoint %d",type,CWaypoints::getWaypointIndex(pWaypoint)); + pClient->playSound("UI/buttonrollover"); + } + else + { + pWaypoint->addFlag(pType->getBits()); + + if ( pType->getBits() & CWaypointTypes::W_FL_UNREACHABLE ) + { + CWaypoints::deletePathsTo(CWaypoints::getWaypointIndex(pWaypoint)); + CWaypoints::deletePathsFrom(CWaypoints::getWaypointIndex(pWaypoint)); + } + + CBotGlobals::botMessage(pEntity,0,"type %s added to waypoint %d",type,CWaypoints::getWaypointIndex(pWaypoint)); + + pClient->playSound("UI/buttonclickrelease"); + } + + } + } + else + { + CBotGlobals::botMessage(pEntity,0,"type '%s' not found",type); + CWaypointTypes::showTypesOnConsole(pEntity); + } + + } + } + } + else + { + CWaypointTypes::showTypesOnConsole(pEntity); + } + + return COMMAND_ACCESSED; +}); + +CBotCommandInline WaypointDrawTypeCommand("drawtype", CMD_ACCESS_WAYPOINT, [](CClient* pClient, const BotCommandArgs& args) +{ + if (pClient) + { + if (args[0] && *args[0]) + { + int drawType = std::atoi(args[0]); + if (drawType >= 0 && drawType <= std::numeric_limits::max()) + { + pClient->setDrawType(static_cast(drawType)); + return COMMAND_ACCESSED; + } + // Handle out-of-range value + return COMMAND_ERROR; + } + } + return COMMAND_ERROR; +}, "0: for effects engine (maximum limit of beams)\n1: for debug overlay (no limit of beams) [LISTEN SERVER CLIENT ONLY]"); + +CBotCommandInline WaypointAngleCommand("angle", CMD_ACCESS_WAYPOINT, [](CClient *pClient, const BotCommandArgs& args) +{ + if ( pClient && pClient->getPlayer() ) + { + pClient->updateCurrentWaypoint(); + + if ( CWaypoint *pWpt = CWaypoints::getWaypoint(pClient->currentWaypoint()) ) + { + const QAngle eye = CBotGlobals::playerAngles(pClient->getPlayer()); + CBotGlobals::botMessage(pClient->getPlayer(),0,"Waypoint Angle == %0.3f deg, (Eye == %0.3f)",CBotGlobals::yawAngleFromEdict(pClient->getPlayer(),pWpt->getOrigin()),eye.y); + pClient->playSound("buttons/combine_button1"); + } + } + + return COMMAND_ACCESSED; +}); + +CBotCommandInline WaypointSetAngleCommand("updateyaw", CMD_ACCESS_WAYPOINT, [](CClient *pClient, const BotCommandArgs& args) +{ + pClient->updateCurrentWaypoint(); + + if ( CWaypoints::validWaypointIndex(pClient->currentWaypoint()) ) + { + CWaypoint *pWpt = CWaypoints::getWaypoint(pClient->currentWaypoint()); + + (pWpt->setAim(CBotGlobals::playerAngles(pClient->getPlayer()).y)); + } + + return COMMAND_ACCESSED; +}); + +CBotCommandInline WaypointSetAreaCommand("setarea", CMD_ACCESS_WAYPOINT, [](CClient *pClient, const BotCommandArgs& args) +{ + pClient->updateCurrentWaypoint(); + + if ( args[0] && *args[0] && ( CWaypoints::validWaypointIndex(pClient->currentWaypoint()) ) ) + { + CWaypoint *pWpt = CWaypoints::getWaypoint(pClient->currentWaypoint()); + + pWpt->setArea(std::atoi(args[0])); + } + else + return COMMAND_ERROR; + + return COMMAND_ACCESSED; +}, "Go to a waypoint, use setarea "); + +CBotCommandInline WaypointSetRadiusCommand("setradius", CMD_ACCESS_WAYPOINT, [](CClient *pClient, const BotCommandArgs& args) +{ + pClient->updateCurrentWaypoint(); + + if ( args[0] && *args[0] && ( CWaypoints::validWaypointIndex(pClient->currentWaypoint()) ) ) + { + CWaypoint *pWpt = CWaypoints::getWaypoint(pClient->currentWaypoint()); + + pWpt->setRadius(static_cast(std::atof(args[0]))); + } + else + return COMMAND_ERROR; + + return COMMAND_ACCESSED; +}, "Go to a waypoint, use setradius "); + +CBotCommandInline WaypointMenuCommand("menu", CMD_ACCESS_WAYPOINT, [](CClient *pClient, const BotCommandArgs& args) +{ + pClient->setCurrentMenu(CBotMenuList::getMenu(BOT_MENU_WPT)); + + return COMMAND_ACCESSED; + /* + if ( pClient ) + { + // number of waypoint types to show per menu + unsigned const int iNumToShow = 7; + + unsigned i = 0; + // menu level .. ? + unsigned iLevel = 0; + // number of possible waypoint types to show + unsigned iNumTypes = CWaypointTypes::getNumTypes(); + + char num[64], msg[64], cmd[128]; + CWaypointType *p; + CWaypoint *pWpt; + + // get current waypoint types on current waypoint + pClient->updateCurrentWaypoint(); + pWpt = CWaypoints::getWaypoint(pClient->currentWaypoint()); + + if ( !pWpt ) + { + CBotGlobals::botMessage(pClient->getPlayer(),0,"Not next to any waypoints to show a menu for"); + return COMMAND_ERROR; + } + + // Menu level to start, 0 = beginning + if ( args[0] && *args[0] ) + { + iLevel = atoi(args[0]); + } + else + { + iLevel = 0; + } + + //pClient->update + + KeyValues *kv = new KeyValues( "menu" ); + kv->SetString( "title", "Waypoint Menu" ); + kv->SetInt( "level", 1 ); + kv->SetColor( "color", Color( 255, 0, 0, 255 )); + kv->SetInt( "time", 15 ); + kv->SetString( "msg", "Select Waypoint Type" ); + + // start at this waypoint type index + unsigned iIndex = iLevel*iNumToShow; + + // run through a small number + while ( (i < iNumToShow) && (iIndex < iNumTypes) ) + { + p = CWaypointTypes::getTypeByIndex(iIndex); + + Q_snprintf( num, sizeof(num), "%i", i ); + + // if waypoint has this type show it by putting a "[x]" next to it + if ( pWpt->getFlags() & p->getBits() ) + Q_snprintf( msg, sizeof(msg), "%s [x]", p->getName() ); + else + Q_snprintf( msg, sizeof(msg), "%s [ ]", p->getName() ); + + Q_snprintf( cmd, sizeof(cmd), "rcbot waypoint givetype %s", p->getName() ); + + KeyValues *item1 = kv->FindKey( num, true ); + item1->SetString( "msg", msg ); + item1->SetString( "command", cmd ); + + iIndex ++; + i++; + } + + // finally show "More" option if available + if ( iIndex < iNumTypes ) + { + Q_snprintf( num, sizeof(num), "%i", i ); + Q_snprintf( msg, sizeof(msg), "More..." ); + Q_snprintf( cmd, sizeof(cmd), "rcbot waypoint menu %d", iLevel+1 ); + + KeyValues *item1 = kv->FindKey( num, true ); + item1->SetString( "msg", msg ); + item1->SetString( "command", cmd ); + } + + helpers->CreateMessage( pClient->getPlayer(), DIALOG_MENU, kv, &g_RCBOTServerPlugin ); + kv->deleteThis(); + + //pClient->showMenu(); + + return COMMAND_ACCESSED; + } + + return COMMAND_ERROR;*/ +}); + +CBotCommandInline WaypointCut("cut", CMD_ACCESS_WAYPOINT, [](CClient *pClient, const BotCommandArgs& args) +{ + if ( pClient ) + { + pClient->updateCurrentWaypoint(); + + if ( const CWaypoint *pWpt = CWaypoints::getWaypoint(pClient->currentWaypoint()) ) + { + pClient->setWaypointCut(pWpt); + CWaypoints::deleteWaypoint(pClient->currentWaypoint()); + } + + return COMMAND_ACCESSED; + } + + return COMMAND_ERROR; +}, "allows you to move a waypoint by cutting it and pasting it"); + +CBotCommandInline WaypointCopy("copy", CMD_ACCESS_WAYPOINT, [](CClient *pClient, const BotCommandArgs& args) +{ + if ( pClient ) + { + pClient->updateCurrentWaypoint(); + + if ( const CWaypoint *pWpt = CWaypoints::getWaypoint(pClient->currentWaypoint()) ) + { + pClient->setWaypointCopy(pWpt); + return COMMAND_ACCESSED; + } + } + + return COMMAND_ERROR; +}, "Go to a waypoint, and copy to hold its properties, then use paste to make a new waypoint with the same properties"); + +CBotCommandInline WaypointPaste("paste", CMD_ACCESS_WAYPOINT, [](CClient *pClient, const BotCommandArgs& args) +{ + if ( pClient ) + { + CWaypoints::addWaypoint(pClient, nullptr, nullptr, nullptr, nullptr,true); + return COMMAND_ACCESSED; + } + + return COMMAND_ERROR; +}, "first copy a waypoint using the copy command and then use paste to make a new waypoint with the same properties"); + +CBotCommandInline WaypointShiftAreas("shiftareas", CMD_ACCESS_WAYPOINT, [](const CClient *pClient, const BotCommandArgs& args) +{ + if ( pClient ) + { + int val = 1; + + if ( args[0] && *args[0] ) + val = std::atoi(args[0]); + + if ( args[1] && *args[1] ) + { + const int newarea = std::atoi(args[1]); + + if ( pClient ) + { + // change area val to newarea + CWaypoints::shiftVisibleAreas(pClient->getPlayer(),val,newarea); + } + } + else + CWaypoints::shiftAreas(val); + + return COMMAND_ACCESSED; + } + + return COMMAND_ERROR; +}, "shift the areas of flagged waypoints to a different area/only use this once"); + +CBotCommandInline WaypointTeleportCommand("teleport", CMD_ACCESS_WAYPOINT | CMD_ACCESS_DEDICATED, [](CClient *pClient, const BotCommandArgs& args) +{ + if ( pClient && args[0] && *args[0] ) + { + CWaypoint *pWpt; + bool bTele = false; + + const int id = std::atoi(args[0]); + + if ( (pWpt=CWaypoints::getWaypoint(id)) != nullptr) + { + if ( pWpt->isUsed() ) + { + pClient->teleportTo(pWpt->getOrigin()+Vector(0,0,8)); + bTele = true; + } + } + + if ( bTele ) + { + CBotGlobals::botMessage(pClient->getPlayer(),0,"Teleported to waypoint %d",id); + } + else + { + CBotGlobals::botMessage(pClient->getPlayer(),0,"Invalid waypoint id %d",id); + } + + return COMMAND_ACCESSED; + } + + return COMMAND_ERROR; +}); + +CBotCommandInline WaypointAreaSetToNearest("setareatonearest", CMD_ACCESS_WAYPOINT, [](const CClient *pClient, const BotCommandArgs& args) +{ + if ( pClient ) + { + CWaypoint *pWpt; + bool bOk = false; + int setarea = 0; + + const int id = pClient->currentWaypoint(); + + if ( (pWpt=CWaypoints::getWaypoint(id)) != nullptr) + { + if ( pWpt->isUsed() ) + { + + #if SOURCE_ENGINE == SE_TF2 + setarea = CTeamFortress2Mod::m_ObjectiveResource.NearestArea(pWpt->getOrigin()); + #elif SOURCE_ENGINE == SE_DODS + setarea = CDODMod::m_Flags.findNearestObjective(pWpt->getOrigin()); + #endif + + if ( setarea > 0 ) + pWpt->setArea(setarea); + + bOk = true; + } + } + + if ( bOk ) + { + if ( setarea > 0 ) + CBotGlobals::botMessage(pClient->getPlayer(),0,"Changed waypoint %d area to %d",id,setarea); + else + CBotGlobals::botMessage(pClient->getPlayer(),0,"No nearest area to wpt id %d",id); + } + else + { + CBotGlobals::botMessage(pClient->getPlayer(),0,"Invalid waypoint id %d",id); + } + return COMMAND_ACCESSED; + } + + return COMMAND_ERROR; +}); + +CBotCommandInline WaypointShowCommand("show", CMD_ACCESS_WAYPOINT, [](const CClient *pClient, const BotCommandArgs& args) +{ + if ( pClient ) + { + const int wpt = std::atoi(args[0]); + + if ( CWaypoint *pWpt = CWaypoints::getWaypoint(wpt) ) + { + g_pEffects->Beam( CBotGlobals::entityOrigin(pClient->getPlayer()), pWpt->getOrigin(), CWaypoints::waypointTexture(), + 0, 0, 1, + 5, 12, 12, 255, + 10, 255, 255, 255, 200, 10); + + //pClient->setShowWpt(wpt); + + return COMMAND_ACCESSED; + } + //else + //pClient->setShowWpt(-1); + } + + return COMMAND_ERROR; +}, "show , shows you to this waypoint"); + +CBotCommandInline WaypointCheckCommand("check", CMD_ACCESS_WAYPOINT, [](const CClient *pClient, const BotCommandArgs& args) +{ + // loop through every waypoint and check the areas are not outside the number of control points + + CWaypoints::checkAreas((pClient== nullptr)? nullptr :pClient->getPlayer()); + + return COMMAND_ACCESSED; +}); + +CBotCommandInline WaypointShowVisCommand("showvis", CMD_ACCESS_WAYPOINT, [](CClient *pClient, const BotCommandArgs& args) +{ +#ifndef __linux__ + pClient->updateCurrentWaypoint(); + + if ( CWaypoints::validWaypointIndex(pClient->currentWaypoint()) ) + { + CWaypoint *pWpt = CWaypoints::getWaypoint(pClient->currentWaypoint()); + + const float ftime = (args[0] && *args[0]) ? static_cast(std::atof(args[0])) : 5.0f; + + if ( pWpt ) + { + const int index = CWaypoints::getWaypointIndex(pWpt); + const CWaypointVisibilityTable *pTable = CWaypoints::getVisiblity(); + + for ( int i = 0; i < CWaypoints::numWaypoints(); i ++ ) + { + CWaypoint *pOther = CWaypoints::getWaypoint(i); + + if ( !pOther->isUsed() ) + continue; + + if ( pOther->distanceFrom(pWpt) > 1024.0f ) + continue; + + const bool bVis = pTable->GetVisibilityFromTo(index, i); + + debugoverlay->AddTextOverlayRGB(pOther->getOrigin(),0,ftime,bVis ? 0 : 255,bVis ? 255 : 0,0,200,bVis ? "VIS" : "INV" ); + } + } + + } + else + return COMMAND_ERROR; +#endif + return COMMAND_ACCESSED; +}, "Go to a waypoint, use showvis to see visibility"); + +CBotCommandInline WaypointAutoWaypointCommand("autowaypoint", CMD_ACCESS_WAYPOINT, [](CClient *pClient, + const BotCommandArgs& args) +{ + if ( pClient ) + { + const int temp = std::atoi(args[0]); + pClient->setAutoWaypointMode(temp > 0, temp == 2); + CBotGlobals::botMessage(pClient->getPlayer(), 0, "Autowaypointing Mode %s, Debug %s", (temp > 0) ? "ON" : "OFF", (temp == 2) ? "ON" : "OFF"); + } + return COMMAND_ACCESSED; +}); + +CBotCommandInline WaypointAutoFix("autofix", CMD_ACCESS_WAYPOINT, [](CClient *pClient, const BotCommandArgs& args) +{ + bool bFixSentry_Sniper_Defend_TeleExtWpts = false; + + if ( args[0] && *args[0] ) + { + bFixSentry_Sniper_Defend_TeleExtWpts = ( std::atoi(args[0]) == 1 ); + } + + CWaypoints::autoFix(bFixSentry_Sniper_Defend_TeleExtWpts); + + return COMMAND_ACCESSED; +}); + +CBotSubcommands WaypointSubcommands("waypoint", CMD_ACCESS_DEDICATED, { + &WaypointOnCommand, + &WaypointOffCommand, + &WaypointAddCommand, + &WaypointDeleteCommand, + &WaypointInfoCommand, + &WaypointSaveCommand, + &WaypointLoadCommand, + &WaypointClearCommand, + &WaypointGiveTypeCommand, + &WaypointDrawTypeCommand, + &WaypointAngleCommand, + &WaypointSetAngleCommand, + &WaypointSetAreaCommand, + &WaypointSetRadiusCommand, + &WaypointMenuCommand, + &WaypointCut, + &WaypointCopy, + &WaypointPaste, + &WaypointShiftAreas, + &WaypointTeleportCommand, + &WaypointAreaSetToNearest, + &WaypointShowCommand, + &WaypointCheckCommand, + &WaypointShowVisCommand, + &WaypointAutoWaypointCommand, + &WaypointAutoFix +}); diff --git a/scripting/include/rcbot2.inc b/scripting/include/rcbot2.inc new file mode 100644 index 000000000..68f3768bb --- /dev/null +++ b/scripting/include/rcbot2.inc @@ -0,0 +1,98 @@ +#if defined __rcbot_included + #endinput +#endif + +#define __rcbot_included + +enum RCBotProfileVar { + // speed of recognizing non-player entities (NPCs / teleporters) + RCBotProfile_iVisionTicks, + + // speed of finding a path + RCBotProfile_iPathTicks, + + // speed of recognizing other players + RCBotProfile_iVisionTicksClients, + + // sensitivity of bot's "mouse"; integer between 1 and 20 + RCBotProfile_iSensitivity, + + // sensitivity to danger (brave = less sensitive); float between 0.0 to 1.0 + RCBotProfile_fBraveness, + + // ability to predict player movements; float between 0.0 to 1.0 + RCBotProfile_fAimSkill, + + // preferred player class + RCBotProfile_iClass, +}; + +/** + * Returns true if a waypoint is available for the current map. + */ +native bool RCBot2_IsWaypointAvailable(); + +/** + * Instantiates an RCBot2 bot for the current mod with a copy of the default profile. + * + * @return RCBot2 client index, or -1 on failure + */ +native int RCBot2_CreateBot(const char[] name); + +/** + * Returns true if the client index is an RCBot2 bot. This does not currently true until after + * the bot is in the game. + * + * @error Client not in game or invalid client index. + */ +native int IsRCBot2Client(int client); + +/** + * Sets the profile property to the given integer value. + * + * @noreturn + * @error Client is not an RCBot2 bot or specified property is not an integer value + */ +native void RCBot2_SetProfileInt(int client, RCBotProfileVar property, int value); + +/** + * Gets the float value for a given bot's profile property. + * + * @error Client is not an RCBot2 bot or specified property is not an integer value + */ +native int RCBot2_GetProfileInt(int client, RCBotProfileVar property); + +/** + * Sets the profile property to the given float value. + * + * @noreturn + * @error Client is not an RCBot2 bot or specified property is not a float value + */ +native void RCBot2_SetProfileFloat(int client, RCBotProfileVar property, float value); + +/** + * Gets the float value for a given bot's profile property. + * + * @error Client is not an RCBot2 bot or specified property is not a float value + */ +native float RCBot2_GetProfileFloat(int client, RCBotProfileVar property); + +public Extension __ext_rcbot2 = { + name = "RCBot2", + file = "rcbot2.ext", +#if defined AUTOLOAD_EXTENSIONS + autoload = 1, +#else + autoload = 0, +#endif +#if defined REQUIRE_EXTENSIONS + required = 1, +#else + required = 0, +#endif +}; + +#if !defined REQUIRE_EXTENSIONS +public void __ext_rcbot2_SetNTVOptional() { +} +#endif diff --git a/scripting/rcbot_sample.sp b/scripting/rcbot_sample.sp new file mode 100644 index 000000000..d28573ce4 --- /dev/null +++ b/scripting/rcbot_sample.sp @@ -0,0 +1,40 @@ +/** + * Sample plugin for native calls to RCBot2 from SourceMod. + */ +#pragma semicolon 1 +#include + +#pragma newdecls required + +#include + +public void OnPluginStart() { + RegAdminCmd("sm_addrcbot", AddRCBot, ADMFLAG_ROOT); + RegAdminCmd("sm_rcbot_supported", TestRCBotSupport, ADMFLAG_ROOT); +} + +public Action TestRCBotSupport(int client, int argc) { + ReplyToCommand(client, "RCBot waypoint available: %b", RCBot2_IsWaypointAvailable()); + return Plugin_Handled; +} + +public Action AddRCBot(int client, int argc) { + char name[64]; + if (argc) { + GetCmdArg(1, name, sizeof(name)); + } + + int bot = RCBot2_CreateBot(name); + if (bot == -1) { + ReplyToCommand(client, "Failed to create RCBot."); + } else { + ReplyToCommand(client, "Created RCBot '%N', slot %d", bot, bot); + PrintToServer("%N->AimSkill = %.2f", bot, RCBot2_GetProfileFloat(bot, RCBotProfile_fAimSkill)); + PrintToServer("%N->Braveness = %.2f", bot, RCBot2_GetProfileFloat(bot, RCBotProfile_fBraveness)); + PrintToServer("%N->PathTicks: %d", bot, RCBot2_GetProfileInt(bot, RCBotProfile_iPathTicks)); + PrintToServer("%N->Sensitivity: %d", bot, RCBot2_GetProfileInt(bot, RCBotProfile_iSensitivity)); + PrintToServer("%N->VisionTicks: %d", bot, RCBot2_GetProfileInt(bot, RCBotProfile_iVisionTicks)); + PrintToServer("%N->VisionTicksClients: %d", bot, RCBot2_GetProfileInt(bot, RCBotProfile_iVisionTicksClients)); + } + return Plugin_Handled; +} diff --git a/sm_ext/LICENSE b/sm_ext/LICENSE new file mode 100644 index 000000000..eeb29b4a0 --- /dev/null +++ b/sm_ext/LICENSE @@ -0,0 +1,38 @@ +SOURCEMOD LICENSE INFORMATION +VERSION: JUNE-13-2008 +----------------------------- + +SourceMod is licensed under the GNU General Public License, version 3. + +As a special exception, AlliedModders LLC gives you permission to link the code +of this program (as well as its derivative works) to "Half-Life 2," the "Source +Engine," the "SourcePawn JIT," and any Game MODs that run on software by the +Valve Corporation. You must obey the GNU General Public License in all +respects for all other code used. Additionally, AlliedModders LLC grants this +exception to all derivative works. + +As an additional special exception to the GNU General Public License 3.0, +AlliedModders LLC permits dual-licensing of DERIVATIVE WORKS ONLY (that is, +SourcePawn/SourceMod Plugins and SourceMod Extensions, or any software built +from the SourceMod SDK or header files) under the GNU General Public License +version 2 "or any higher version." As such, you may choose for your derivative +work(s) to be compatible with the GNU General Public License version 2 as long +as it is also compatible with the GNU General Public License version 3, via the +"or any higher version" clause. This is intended for compatibility with other +software. + +As a final exception to the above, any derivative works created prior to this +date (July 31, 2007) may be exclusively licensed under the GNU General Public +License version 2 (without an "or any higher version" clause) if and only if +the work was already GNU General Public License 2.0 exclusive. This clause is +provided for backwards compatibility only. + +A copy of the JIT License is available in JIT.txt. +A copy of the GNU General Public License 2.0 is available in GPLv2.txt. +A copy of the GNU General Public License 3.0 is available in GPLv3.txt. + +SourcePawn is Copyright (C) 2006-2008 AlliedModders LLC. All rights reserved. +SourceMod is Copyright (C) 2006-2008 AlliedModders LLC. All rights reserved. +Pawn and SMALL are Copyright (C) 1997-2008 ITB CompuPhase. +Source is Copyright (C) Valve Corporation. +All trademarks are property of their respective owners in the US and other diff --git a/sm_ext/bot_sm_ext.cpp b/sm_ext/bot_sm_ext.cpp new file mode 100644 index 000000000..b67974d24 --- /dev/null +++ b/sm_ext/bot_sm_ext.cpp @@ -0,0 +1,114 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +#include "bot_sm_ext.h" +#include "bot_sm_natives.h" + +//SourceMod::IBinTools *sm_bintools = nullptr; +SourceMod::ISDKTools *sm_sdktools = nullptr; +//SourceMod::ISDKHooks *sm_sdkhooks = nullptr; + +using namespace SourceMod; + +RCBotSourceModExt g_RCBotSourceMod; + +bool RCBotSourceModExt::OnExtensionLoad(IExtension *me, IShareSys *sys, char *error, + const std::size_t maxlength, bool late) { + sharesys = sys; + myself = me; + + /* Get the default interfaces from our configured SDK header */ + if (!SM_AcquireInterfaces(error, maxlength)) { + return false; + } + + sharesys->RegisterLibrary(myself, "RCBot2"); + sharesys->AddNatives(myself, g_RCBotNatives); + return true; +} + +void RCBotSourceModExt::OnExtensionUnload() { + SM_UnsetInterfaces(); +} + +void RCBotSourceModExt::OnExtensionsAllLoaded() { +} + +void RCBotSourceModExt::OnExtensionPauseChange(bool pause) { + +} + +bool RCBotSourceModExt::QueryRunning(char *error, std::size_t maxlength) { + return true; +} + +bool RCBotSourceModExt::IsMetamodExtension() { + return false; +} + +/// @brief caxanga334: Trying to get the interface for other SM extensions on RCBotSourceModExt::OnExtensionsAllLoaded() seems to always fail. +/// My guess is since RCBot2 is loaded from MM first, it loads before every other SM extension. +/// So we call this function from RCBotPluginMeta::Hook_LevelInit +void RCBotSourceModExt::LateLoadExtensions() { + //SM_FIND_IFACE(BINTOOLS, sm_bintools); + SM_FIND_IFACE(SDKTOOLS, sm_sdktools) + //SM_FIND_IFACE(SDKHOOKS, sm_sdkhooks); + + if (sm_sdktools) + { + sm_main->LogMessage(myself, "Loaded extensions interface"); + } +} + +const char *RCBotSourceModExt::GetExtensionName() { + return g_RCBotPluginMeta.GetName(); +} +const char *RCBotSourceModExt::GetExtensionURL() { + return g_RCBotPluginMeta.GetURL(); +} +const char *RCBotSourceModExt::GetExtensionTag() { + return g_RCBotPluginMeta.GetLogTag(); +} +const char *RCBotSourceModExt::GetExtensionAuthor() { + return g_RCBotPluginMeta.GetAuthor(); +} +const char *RCBotSourceModExt::GetExtensionVerString() { + return g_RCBotPluginMeta.GetVersion(); +} +const char *RCBotSourceModExt::GetExtensionDescription() { + return g_RCBotPluginMeta.GetDescription(); +} +const char *RCBotSourceModExt::GetExtensionDateString() { + return g_RCBotPluginMeta.GetDate(); +} + +bool SM_LoadExtension(char *error, const std::size_t maxlength) { + if ((smexts = static_cast(g_SMAPI-> + MetaFactory(SOURCEMOD_INTERFACE_EXTENSIONS, nullptr, nullptr))) == nullptr) + { + if (error && maxlength) { + snprintf(error, maxlength, SOURCEMOD_INTERFACE_EXTENSIONS " interface not found"); + } + return false; + } + + /* This could be more dynamic */ + char path[256]; + g_SMAPI->PathFormat(path, sizeof(path), "addons/rcbot2/bin/RCBot2Meta%s", +#ifdef __linux__ + "_i486.so" +#else + ".dll" +#endif + ); + + if ((myself = smexts->LoadExternal(&g_RCBotSourceMod, path, "rcbot2.ext", error, maxlength)) + == nullptr) { + SM_UnsetInterfaces(); + return false; + } + return true; +} + +void SM_UnloadExtension() { + smexts->UnloadExtension(myself); +} diff --git a/sm_ext/bot_sm_ext.h b/sm_ext/bot_sm_ext.h new file mode 100644 index 000000000..e0d1bdacc --- /dev/null +++ b/sm_ext/bot_sm_ext.h @@ -0,0 +1,53 @@ +#ifndef __BOT_EXT_SOURCEMOD_H__ +#define __BOT_EXT_SOURCEMOD_H__ + +#include +#include +//#include +//#include +#include + +#include "bot_plugin_meta.h" + +using SourceMod::IExtension; +using SourceMod::IExtensionManager; +using SourceMod::IShareSys; + +class RCBotSourceModExt : public SourceMod::IExtensionInterface +{ +public: + virtual ~RCBotSourceModExt() = default; + bool OnExtensionLoad(IExtension *me, IShareSys *sys, char* error, std::size_t maxlength, bool late) override; + void OnExtensionUnload() override; + void OnExtensionsAllLoaded() override; + void OnExtensionPauseChange(bool pause) override; + bool QueryRunning(char *error, std::size_t maxlength) override; + bool IsMetamodExtension() override; + const char *GetExtensionName() override; + const char *GetExtensionURL() override; + const char *GetExtensionTag() override; + const char *GetExtensionAuthor() override; + const char *GetExtensionVerString() override; + const char *GetExtensionDescription() override; + const char *GetExtensionDateString() override; + + virtual void LateLoadExtensions(); +}; + +bool SM_AcquireInterfaces(char *error, std::size_t maxlength); +bool SM_LoadExtension(char *error, std::size_t maxlength); +void SM_UnloadExtension(); +void SM_UnsetInterfaces(); + +extern RCBotSourceModExt g_RCBotSourceMod; + +extern SourceMod::IExtensionManager *smexts; + +extern SourceMod::IShareSys *sharesys; +extern SourceMod::IExtension *myself; + +//extern SourceMod::IBinTools *sm_bintools; +extern SourceMod::ISDKTools *sm_sdktools; +//extern SourceMod::ISDKHooks *sm_sdkhooks; + +#endif diff --git a/sm_ext/bot_sm_natives.cpp b/sm_ext/bot_sm_natives.cpp new file mode 100644 index 000000000..935bbd76a --- /dev/null +++ b/sm_ext/bot_sm_natives.cpp @@ -0,0 +1,168 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +#include "bot_sm_natives.h" +#include "bot_sm_ext.h" + +#include "bot.h" +#include "bot_profile.h" +#include "bot_waypoint.h" + +enum RCBotProfileVar : std::uint8_t { + RCBotProfile_iVisionTicks, + RCBotProfile_iPathTicks, + RCBotProfile_iVisionTicksClients, + RCBotProfile_iSensitivity, + RCBotProfile_fBraveness, + RCBotProfile_fAimSkill, + RCBotProfile_iClass, +}; + +int* GetIntProperty(CBotProfile* profile, RCBotProfileVar profileVar); +float* GetFloatProperty(CBotProfile* profile, RCBotProfileVar profileVar); + +cell_t sm_RCBotIsWaypointAvailable(IPluginContext *pContext, const cell_t *params) { + return CWaypoints::numWaypoints() > 0; +} + +cell_t sm_RCBotCreate(IPluginContext *pContext, const cell_t *params) { + char *name; + pContext->LocalToString(params[1], &name); + + const int slot = CBots::createDefaultBot(name); + + // player slots are off-by-one (though this calculation is performed in the function) + return (slot != -1)? slot + 1 : -1; +} + +/* native void RCBot2_SetProfileInt(int client, RCBotProfileVar property, int value); */ +cell_t sm_RCBotSetProfileInt(IPluginContext* pContext, const cell_t* params) { + const int client = params[1]; + const RCBotProfileVar profileVar = static_cast(params[2]); + if (client < 1 || client > gpGlobals->maxClients) { + pContext->ThrowNativeError("Invalid client index %d", client); + return 0; // Ensure the function exits + } + + const CBot* bot = CBots::getBot(client - 1); + if (!bot) { + pContext->ThrowNativeError("Client index %d is not a RCBot", client); + return 0; // Ensure the function exits + } + + CBotProfile* profile = bot->getProfile(); + int* value = GetIntProperty(profile, profileVar); + if (!value) { + pContext->ThrowNativeError("RCBot property %d is not an integer property", profileVar); + return 0; + } + *value = params[3]; + + return 0; +} + +/* native void RCBot2_SetProfileFloat(int client, RCBotProfileVar property, float value); */ +cell_t sm_RCBotSetProfileFloat(IPluginContext *pContext, const cell_t *params) { + const int client = params[1]; + const RCBotProfileVar profileVar = static_cast(params[2]); + if (client < 1 || client > gpGlobals->maxClients) { + pContext->ThrowNativeError("Invalid client index %d", client); + } + + const CBot* bot = CBots::getBot(client - 1); + if (!bot) { + return pContext->ThrowNativeError("Client index %d is not a RCBot", client); + } + + CBotProfile* profile = bot->getProfile(); + float* value = GetFloatProperty(profile, profileVar); + if (!value) { + pContext->ThrowNativeError("RCBot property %d is not a float property", profileVar); + return 0; + } + *value = sp_ctof(params[3]); + + return 0; +} + +/* native int RCBot2_GetProfileInt(int client, RCBotProfileVar property); */ +cell_t sm_RCBotGetProfileInt(IPluginContext *pContext, const cell_t *params) { + const int client = params[1]; + const RCBotProfileVar profileVar = static_cast(params[2]); + if (client < 1 || client > gpGlobals->maxClients) { + pContext->ThrowNativeError("Invalid client index %d", client); + return 0; + } + + const CBot* bot = CBots::getBot(client - 1); + if (!bot) { + pContext->ThrowNativeError("Client index %d is not a RCBot", client); + return 0; + } + + CBotProfile* profile = bot->getProfile(); + const int* value = GetIntProperty(profile, profileVar); + if (!value) { + pContext->ThrowNativeError("RCBot property %d is not an integer property", profileVar); + return 0; + } + return *value; +} + +/* native float RCBot2_GetProfileFloat(int client, RCBotProfileVar property); */ +cell_t sm_RCBotGetProfileFloat(IPluginContext* pContext, const cell_t* params) { + const int client = params[1]; + const RCBotProfileVar profileVar = static_cast(params[2]); + if (client < 1 || client > gpGlobals->maxClients) { + pContext->ThrowNativeError("Invalid client index %d", client); + return 0; + } + + const CBot* bot = CBots::getBot(client - 1); + if (!bot) { + pContext->ThrowNativeError("Client index %d is not a RCBot", client); + return 0; + } + + CBotProfile* profile = bot->getProfile(); + const float* value = GetFloatProperty(profile, profileVar); + if (!value) { + pContext->ThrowNativeError("RCBot property %d is not a float property", profileVar); + return 0; + } + return sp_ftoc(*value); +} + +cell_t sm_RCBotIsClientBot(IPluginContext *pContext, const cell_t *params) { + const int client = params[1]; + if (client < 1 || client > gpGlobals->maxClients) { + pContext->ThrowNativeError("Invalid client index %d", client); + return 0; + } + return CBots::getBot(client - 1) != nullptr; +} + +int* GetIntProperty(CBotProfile* profile, const RCBotProfileVar profileVar) { + switch (profileVar) { + case RCBotProfile_iVisionTicks: + return &profile->m_iVisionTicks; + case RCBotProfile_iPathTicks: + return &profile->m_iPathTicks; + case RCBotProfile_iClass: + return &profile->m_iClass; + case RCBotProfile_iVisionTicksClients: + return &profile->m_iVisionTicksClients; + case RCBotProfile_iSensitivity: + return &profile->m_iSensitivity; + } + return nullptr; +} + +float* GetFloatProperty(CBotProfile* profile, const RCBotProfileVar profileVar) { + switch (profileVar) { + case RCBotProfile_fBraveness: + return &profile->m_fBraveness; + case RCBotProfile_fAimSkill: + return &profile->m_fAimSkill; + } + return nullptr; +} diff --git a/sm_ext/bot_sm_natives.h b/sm_ext/bot_sm_natives.h new file mode 100644 index 000000000..96fc5a627 --- /dev/null +++ b/sm_ext/bot_sm_natives.h @@ -0,0 +1,32 @@ +#pragma once + +#include + +using namespace SourceMod; +using namespace SourcePawn; + +cell_t sm_RCBotIsWaypointAvailable(IPluginContext *pContext, const cell_t *params); + +cell_t sm_RCBotCreate(IPluginContext *pContext, const cell_t *params); +cell_t sm_RCBotIsClientBot(IPluginContext *pContext, const cell_t *params); + +cell_t sm_RCBotSetProfileInt(IPluginContext *pContext, const cell_t *params); +cell_t sm_RCBotGetProfileInt(IPluginContext *pContext, const cell_t *params); + +cell_t sm_RCBotSetProfileFloat(IPluginContext *pContext, const cell_t *params); +cell_t sm_RCBotGetProfileFloat(IPluginContext *pContext, const cell_t *params); + +const sp_nativeinfo_t g_RCBotNatives[] = { + { "RCBot2_IsWaypointAvailable", sm_RCBotIsWaypointAvailable }, + + { "RCBot2_CreateBot", sm_RCBotCreate }, + { "IsRCBot2Client", sm_RCBotIsClientBot }, + + { "RCBot2_SetProfileInt", sm_RCBotSetProfileInt }, + { "RCBot2_GetProfileInt", sm_RCBotGetProfileInt }, + + { "RCBot2_SetProfileFloat", sm_RCBotSetProfileFloat }, + { "RCBot2_GetProfileFloat", sm_RCBotGetProfileFloat }, + + {nullptr, nullptr}, +}; diff --git a/sm_ext/smsdk_config.cpp b/sm_ext/smsdk_config.cpp new file mode 100644 index 000000000..6c412f88c --- /dev/null +++ b/sm_ext/smsdk_config.cpp @@ -0,0 +1,192 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod Extension Code for Metamod:Source + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id$ + */ + +#include "smsdk_config.h" + +using namespace SourceMod; + +bool SM_AcquireInterfaces(char *error, std::size_t maxlength) +{ + SM_FIND_IFACE_OR_FAIL(SOURCEMOD, sm_main, error, maxlength); + +#ifdef SMEXT_ENABLE_FORWARDSYS + SM_FIND_IFACE_OR_FAIL(FORWARDMANAGER, sm_forwards, error, maxlength); +#endif +#ifdef SMEXT_ENABLE_HANDLESYS + SM_FIND_IFACE_OR_FAIL(HANDLESYSTEM, sm_handlesys, error, maxlength); +#endif +#ifdef SMEXT_ENABLE_PLAYERHELPERS + SM_FIND_IFACE_OR_FAIL(PLAYERMANAGER, sm_players, error, maxlength); +#endif +#ifdef SMEXT_ENABLE_DBMANAGER + SM_FIND_IFACE_OR_FAIL(DBI, sm_dbi, error, maxlength); +#endif +#ifdef SMEXT_ENABLE_GAMECONF + SM_FIND_IFACE_OR_FAIL(GAMECONFIG, sm_gameconfs, error, maxlength); +#endif +#ifdef SMEXT_ENABLE_MEMUTILS + SM_FIND_IFACE_OR_FAIL(MEMORYUTILS, sm_memutils, error, maxlength); +#endif +#ifdef SMEXT_ENABLE_GAMEHELPERS + SM_FIND_IFACE_OR_FAIL(GAMEHELPERS, sm_gamehelpers, error, maxlength); +#endif +#ifdef SMEXT_ENABLE_TIMERSYS + SM_FIND_IFACE_OR_FAIL(TIMERSYS, sm_timersys, error, maxlength); +#endif +#ifdef SMEXT_ENABLE_THREADER + SM_FIND_IFACE_OR_FAIL(THREADER, sm_threader, error, maxlength); +#endif +#ifdef SMEXT_ENABLE_LIBSYS + SM_FIND_IFACE_OR_FAIL(LIBRARYSYS, sm_libsys, error, maxlength); +#endif +#ifdef SMEXT_ENABLE_PLUGINSYS + SM_FIND_IFACE_OR_FAIL(PLUGINSYSTEM, sm_plsys, error, maxlength); +#endif +#ifdef SMEXT_ENABLE_MENUS + SM_FIND_IFACE_OR_FAIL(MENUMANAGER, sm_menus, error, maxlength); +#endif +#ifdef SMEXT_ENABLE_ADMINSYS + SM_FIND_IFACE_OR_FAIL(ADMINSYS, sm_adminsys, error, maxlength); +#endif +#ifdef SMEXT_ENABLE_TEXTPARSERS + SM_FIND_IFACE_OR_FAIL(TEXTPARSERS, sm_text, error, maxlength); +#endif +#ifdef SMEXT_ENABLE_TRANSLATOR + SM_FIND_IFACE_OR_FAIL(TRANSLATOR, sm_translator, error, maxlength); +#endif + + return true; +} + +void SM_UnsetInterfaces() +{ + myself = nullptr; + smexts = nullptr; + sharesys = nullptr; + sm_main = nullptr; +#ifdef SMEXT_ENABLE_FORWARDSYS + sm_forwards = nullptr; +#endif +#ifdef SMEXT_ENABLE_HANDLESYS + sm_handlesys = nullptr; +#endif +#ifdef SMEXT_ENABLE_PLAYERHELPERS + sm_players = nullptr; +#endif +#ifdef SMEXT_ENABLE_DBMANAGER + sm_dbi = nullptr; +#endif +#ifdef SMEXT_ENABLE_GAMECONF + sm_gameconfs = nullptr; +#endif +#ifdef SMEXT_ENABLE_MEMUTILS + sm_memutils = nullptr; +#endif +#ifdef SMEXT_ENABLE_GAMEHELPERS + sm_gamehelpers = nullptr; +#endif +#ifdef SMEXT_ENABLE_TIMERSYS + sm_timersys = nullptr; +#endif +#ifdef SMEXT_ENABLE_THREADER + sm_threader = nullptr; +#endif +#ifdef SMEXT_ENABLE_LIBSYS + sm_libsys = nullptr; +#endif +#ifdef SMEXT_ENABLE_PLUGINSYS + sm_plsys = nullptr; +#endif +#ifdef SMEXT_ENABLE_MENUS + sm_menus = nullptr; +#endif +#ifdef SMEXT_ENABLE_ADMINSYS + sm_adminsys = nullptr; +#endif +#ifdef SMEXT_ENABLE_TEXTPARSERS + sm_text = nullptr; +#endif +#ifdef SMEXT_ENABLE_TRANSLATOR + sm_translator = nullptr; +#endif +} + +IExtension *myself = nullptr; +IExtensionManager *smexts = nullptr; +IShareSys *sharesys = nullptr; +SourceMod::ISourceMod *sm_main = nullptr; +#ifdef SMEXT_ENABLE_FORWARDSYS +SourceMod::IForwardManager *sm_forwards = nullptr; +#endif +#ifdef SMEXT_ENABLE_HANDLESYS +SourceMod::IHandleSys *sm_handlesys = nullptr; +#endif +#ifdef SMEXT_ENABLE_PLAYERHELPERS +SourceMod::IPlayerManager *sm_players = nullptr; +#endif +#ifdef SMEXT_ENABLE_DBMANAGER +SourceMod::IDBManager *sm_dbi = nullptr; +#endif +#ifdef SMEXT_ENABLE_GAMECONF +SourceMod::IGameConfigManager *sm_gameconfs = nullptr; +#endif +#ifdef SMEXT_ENABLE_MEMUTILS +SourceMod::IMemoryUtils *sm_memutils = nullptr; +#endif +#ifdef SMEXT_ENABLE_GAMEHELPERS +SourceMod::IGameHelpers *sm_gamehelpers = nullptr; +#endif +#ifdef SMEXT_ENABLE_TIMERSYS +SourceMod::ITimerSystem *sm_timersys = nullptr; +#endif +#ifdef SMEXT_ENABLE_THREADER +SourceMod::IThreader *sm_threader = nullptr; +#endif +#ifdef SMEXT_ENABLE_LIBSYS +SourceMod::ILibrarySys *sm_libsys = nullptr; +#endif +#ifdef SMEXT_ENABLE_PLUGINSYS +SourceMod::IPluginManager *sm_plsys = nullptr; +#endif +#ifdef SMEXT_ENABLE_MENUS +SourceMod::IMenuManager *sm_menus = nullptr; +#endif +#ifdef SMEXT_ENABLE_ADMINSYS +SourceMod::IAdminSystem *sm_adminsys = nullptr; +#endif +#ifdef SMEXT_ENABLE_TEXTPARSERS +SourceMod::ITextParsers *sm_text = nullptr; +#endif +#ifdef SMEXT_ENABLE_TRANSLATOR +SourceMod::ITranslator *sm_translator = nullptr; +#endif diff --git a/sm_ext/smsdk_config.h b/sm_ext/smsdk_config.h new file mode 100644 index 000000000..966631b2d --- /dev/null +++ b/sm_ext/smsdk_config.h @@ -0,0 +1,165 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod Extension Code for Metamod:Source + * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. + * ============================================================================= + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, version 3.0, as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + * As a special exception, AlliedModders LLC gives you permission to link the + * code of this program (as well as its derivative works) to "Half-Life 2," the + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software + * by the Valve Corporation. You must obey the GNU General Public License in + * all respects for all other code used. Additionally, AlliedModders LLC grants + * this exception to all derivative works. AlliedModders LLC defines further + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), + * or . + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_SOURCEMOD_CONFIG_H_ +#define _INCLUDE_SOURCEMOD_CONFIG_H_ + +#include + +/** + * @brief Acquires the interfaces enabled at the bottom of this header. + * + * @param error Buffer to store error message. + * @param maxlength Maximum size of the error buffer. + * @return True on success, false on failure. + * On failure, a null-terminated string will be stored + * in the error buffer, if the buffer is non-NULL and + * greater than 0 bytes in size. + */ +bool SM_AcquireInterfaces(char *error, std::size_t maxlength); + +/** + * @brief Sets each acquired interface to NULL. + */ +void SM_UnsetInterfaces(); + +/** + * Enable interfaces you want to use here by uncommenting lines. + * These interfaces are all part of SourceMod's core. + */ +//#define SMEXT_ENABLE_FORWARDSYS +//#define SMEXT_ENABLE_HANDLESYS +#define SMEXT_ENABLE_PLAYERHELPERS +//#define SMEXT_ENABLE_DBMANAGER +#define SMEXT_ENABLE_GAMECONF +//#define SMEXT_ENABLE_MEMUTILS +#define SMEXT_ENABLE_GAMEHELPERS +#define SMEXT_ENABLE_TIMERSYS +//#define SMEXT_ENABLE_THREADER +//#define SMEXT_ENABLE_LIBSYS +//#define SMEXT_ENABLE_MENUS +//#define SMEXT_ENABLE_ADTFACTORY +//#define SMEXT_ENABLE_PLUGINSYS +#define SMEXT_ENABLE_ADMINSYS +//#define SMEXT_ENABLE_TEXTPARSERS +//#define SMEXT_ENABLE_TRANSLATOR + + +/** + * There is no need to edit below. + */ + +#include +#include +extern SourceMod::IExtension *myself; +extern SourceMod::IExtensionManager *smexts; +extern SourceMod::IShareSys *sharesys; + +#include +extern SourceMod::ISourceMod *sm_main; + +#ifdef SMEXT_ENABLE_FORWARDSYS +#include +extern SourceMod::IForwardManager *sm_forwards; +#endif + +#ifdef SMEXT_ENABLE_HANDLESYS +#include +extern SourceMod::IHandleSys *sm_handlesys; +#endif + +#ifdef SMEXT_ENABLE_PLAYERHELPERS +#include +extern SourceMod::IPlayerManager *sm_players; +#endif + +#ifdef SMEXT_ENABLE_DBMANAGER +#include +extern SourceMod::IDBManager *sm_dbi; +#endif + +#ifdef SMEXT_ENABLE_GAMECONF +#include +extern SourceMod::IGameConfigManager *sm_gameconfs; +#endif + +#ifdef SMEXT_ENABLE_MEMUTILS +#include +extern SourceMod::IMemoryUtils *sm_memutils; +#endif + +#ifdef SMEXT_ENABLE_GAMEHELPERS +#include +extern SourceMod::IGameHelpers *sm_gamehelpers; +#endif + +#ifdef SMEXT_ENABLE_TIMERSYS +#include +extern SourceMod::ITimerSystem *sm_timersys; +#endif + +#ifdef SMEXT_ENABLE_THREADER +#include +extern SourceMod::IThreader *sm_threader; +#endif + +#ifdef SMEXT_ENABLE_LIBSYS +#include +extern SourceMod::ILibrarySys *sm_libsys; +#endif + +#ifdef SMEXT_ENABLE_PLUGINSYS +#include +extern SourceMod::IPluginManager *sm_plsys; +#endif + +#ifdef SMEXT_ENABLE_MENUS +#include +extern SourceMod::IMenuManager *sm_menus; +#endif + +#ifdef SMEXT_ENABLE_ADMINSYS +#include +extern SourceMod::IAdminSystem *sm_adminsys; +#endif + +#ifdef SMEXT_ENABLE_TEXTPARSERS +#include +extern SourceMod::ITextParsers *sm_text; +#endif + +#ifdef SMEXT_ENABLE_TRANSLATOR +#include +extern SourceMod::ITranslator *sm_translator; +#endif + +#endif //_INCLUDE_SOURCEMOD_CONFIG_H_ + diff --git a/tests/always_dirty/AMBuildScript b/tests/always_dirty/AMBuildScript new file mode 100644 index 000000000..7dd9305b0 --- /dev/null +++ b/tests/always_dirty/AMBuildScript @@ -0,0 +1,8 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: +import os + +_, outputs = builder.AddCommand( + inputs = builder.ALWAYS_DIRTY, + outputs = ['sample.h'], + argv = ['python', os.path.join(builder.sourcePath, 'generate.py')] +) diff --git a/tests/always_dirty/configure.py b/tests/always_dirty/configure.py new file mode 100644 index 000000000..5e2d62a95 --- /dev/null +++ b/tests/always_dirty/configure.py @@ -0,0 +1,15 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et: +API_VERSION = '2.1' + +import sys +try: + from ambuild2 import run + if not run.HasAPI(API_VERSION): + raise Exception() +except: + sys.stderr.write('AMBuild {0} must be installed to build this project.\n'.format(API_VERSION)) + sys.stderr.write('http://www.alliedmods.net/ambuild\n') + sys.exit(1) + +builder = run.BuildParser(sourcePath = sys.path[0], api=API_VERSION) +builder.Configure() diff --git a/tests/always_dirty/generate.py b/tests/always_dirty/generate.py new file mode 100644 index 000000000..ce75b0043 --- /dev/null +++ b/tests/always_dirty/generate.py @@ -0,0 +1,9 @@ +# vim: set ts=2 sw=2 tw=99 et: +import datetime + +def main(): + with open('sample.h', 'w') as fp: + fp.write("const char* DATE = {0};\n".format(datetime.datetime.now())) + +if __name__ == '__main__': + main() diff --git a/tests/autoinclude/AMBuildScript b/tests/autoinclude/AMBuildScript new file mode 100644 index 000000000..fa982f89d --- /dev/null +++ b/tests/autoinclude/AMBuildScript @@ -0,0 +1,32 @@ +# vim: set ts=8 sts=2 tw=99 et ft=python: +import os, sys + +builder.DetectCompilers() + +argv = [ + sys.executable, + os.path.join(builder.sourcePath, 'generate_header.py'), + os.path.join(builder.buildPath, 'output.h') +] + +outputs = [ + os.path.join(builder.buildFolder, 'output.h') +] + +sources = [ + os.path.join(builder.sourcePath, 'activate.txt'), + argv[1] +] +cmd_node, (output_header,) = builder.AddCommand( + inputs = sources, + argv = argv, + outputs = outputs +) + +program = builder.compiler.Library("hello") +program.compiler.includes += [builder.buildPath] +program.compiler.sourcedeps += [output_header] +program.sources = [ + 'main.cpp' +] +builder.Add(program) diff --git a/tests/autoinclude/activate.txt b/tests/autoinclude/activate.txt new file mode 100644 index 000000000..39e23e2d3 --- /dev/null +++ b/tests/autoinclude/activate.txt @@ -0,0 +1 @@ +I don't do anything. diff --git a/tests/autoinclude/configure.py b/tests/autoinclude/configure.py new file mode 100644 index 000000000..0afeac539 --- /dev/null +++ b/tests/autoinclude/configure.py @@ -0,0 +1,6 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et: +import sys +from ambuild2 import run + +builder = run.BuildParser(sourcePath = sys.path[0], api='2.1') +builder.Configure() diff --git a/tests/autoinclude/generate_header.py b/tests/autoinclude/generate_header.py new file mode 100644 index 000000000..b5cd09cf7 --- /dev/null +++ b/tests/autoinclude/generate_header.py @@ -0,0 +1,9 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et: +import sys + +with open(sys.argv[1], 'w') as fp: + fp.write(""" +#ifndef HELLO_STRING +# define HELLO_STRING "HELLO!" +#endif +""") diff --git a/tests/autoinclude/main.cpp b/tests/autoinclude/main.cpp new file mode 100644 index 000000000..90f8f4fc0 --- /dev/null +++ b/tests/autoinclude/main.cpp @@ -0,0 +1,8 @@ +#include +#include + +int main() +{ + printf("%s\n", HELLO_STRING); +} + diff --git a/tests/cx_paths/AMBuildScript b/tests/cx_paths/AMBuildScript new file mode 100644 index 000000000..e7a99f90b --- /dev/null +++ b/tests/cx_paths/AMBuildScript @@ -0,0 +1,9 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: +builder.DetectCompilers() +if builder.compiler.family == 'gcc': + builder.compiler.cflags += [ + '-Wall', + '-Werror' + ] + +builder.RunBuildScript('helper/helper.ambuild') diff --git a/tests/cx_paths/configure.py b/tests/cx_paths/configure.py new file mode 100644 index 000000000..26ceaef00 --- /dev/null +++ b/tests/cx_paths/configure.py @@ -0,0 +1,6 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et: +import sys +from ambuild2 import run + +builder = run.BuildParser(sourcePath = sys.path[0], api="2.1") +builder.Configure() diff --git a/tests/cx_paths/helper/helper.ambuild b/tests/cx_paths/helper/helper.ambuild new file mode 100644 index 000000000..2071859a7 --- /dev/null +++ b/tests/cx_paths/helper/helper.ambuild @@ -0,0 +1,3 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: + +builder.RunBuildScript('/program.ambuild') diff --git a/tests/cx_paths/main.cpp b/tests/cx_paths/main.cpp new file mode 100644 index 000000000..19c60390b --- /dev/null +++ b/tests/cx_paths/main.cpp @@ -0,0 +1,6 @@ +#include + +int main(int argc, char** argv) +{ + printf("hello!\n"); +} diff --git a/tests/cx_paths/program.ambuild b/tests/cx_paths/program.ambuild new file mode 100644 index 000000000..585c92ca6 --- /dev/null +++ b/tests/cx_paths/program.ambuild @@ -0,0 +1,6 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: +program = builder.compiler.Program('sample') +program.sources += [ + 'main.cpp', +] +builder.Add(program) diff --git a/tests/dsymutil/AMBuildScript b/tests/dsymutil/AMBuildScript new file mode 100644 index 000000000..2ea37aedb --- /dev/null +++ b/tests/dsymutil/AMBuildScript @@ -0,0 +1,10 @@ +# vim: set ts=8 sts=2 tw=99 et ft=python: +import os, sys + +builder.DetectCompilers() + +program = builder.compiler.Program("hello") +program.sources = [ + 'main.cpp' +] +builder.Add(program) diff --git a/tests/dsymutil/configure.py b/tests/dsymutil/configure.py new file mode 100644 index 000000000..8cc418bf8 --- /dev/null +++ b/tests/dsymutil/configure.py @@ -0,0 +1,6 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et: +import sys +from ambuild2 import run + +builder = run.PrepareBuild(sourcePath = sys.path[0]) +builder.Configure() diff --git a/tests/dsymutil/main.cpp b/tests/dsymutil/main.cpp new file mode 100644 index 000000000..289602988 --- /dev/null +++ b/tests/dsymutil/main.cpp @@ -0,0 +1,7 @@ +#include + +int main() +{ + return printf("hello!\n"); +} + diff --git a/tests/invalid_symlink/AMBuildScript b/tests/invalid_symlink/AMBuildScript new file mode 100644 index 000000000..99a70313b --- /dev/null +++ b/tests/invalid_symlink/AMBuildScript @@ -0,0 +1,11 @@ +# vim: set ts=8 sts=2 tw=99 et ft=python: +import os, sys + +builder.DetectCompilers() + +program = builder.compiler.Program("hello") +program.sources = [ + 'main.cpp' +] +out = builder.Add(program) +builder.AddSymlink(out.binary, 'hello.bin') diff --git a/tests/invalid_symlink/configure.py b/tests/invalid_symlink/configure.py new file mode 100644 index 000000000..8cc418bf8 --- /dev/null +++ b/tests/invalid_symlink/configure.py @@ -0,0 +1,6 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et: +import sys +from ambuild2 import run + +builder = run.PrepareBuild(sourcePath = sys.path[0]) +builder.Configure() diff --git a/tests/invalid_symlink/main.cpp b/tests/invalid_symlink/main.cpp new file mode 100644 index 000000000..b0b948e7d --- /dev/null +++ b/tests/invalid_symlink/main.cpp @@ -0,0 +1,7 @@ +#include + +int main(int argc, char **argv) +{ + return printf("hello!\n"); +} + diff --git a/tests/modules/AMBuildScript b/tests/modules/AMBuildScript new file mode 100644 index 000000000..5fcc94f75 --- /dev/null +++ b/tests/modules/AMBuildScript @@ -0,0 +1,8 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: +builder.DetectCxx() +builder.cxx.cflags += [ + '-Wall', + '-Werror' +] + +builder.Build('core/AMBuild') diff --git a/tests/modules/configure.py b/tests/modules/configure.py new file mode 100644 index 000000000..26ceaef00 --- /dev/null +++ b/tests/modules/configure.py @@ -0,0 +1,6 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et: +import sys +from ambuild2 import run + +builder = run.BuildParser(sourcePath = sys.path[0], api="2.1") +builder.Configure() diff --git a/tests/modules/core/AMBuild b/tests/modules/core/AMBuild new file mode 100644 index 000000000..14b5c690b --- /dev/null +++ b/tests/modules/core/AMBuild @@ -0,0 +1,15 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: + +program = builder.cxx.Program('sample') +program.sources += [ + 'main.cc', +] + +m1 = program.Module(builder, 'm1') +m1.sources += [ + 'main2.cc', +] + +builder.Build('m2/AMBuild', { 'program': program }) + +builder.Add(program) diff --git a/tests/modules/core/m2/AMBuild b/tests/modules/core/m2/AMBuild new file mode 100644 index 000000000..888cddae4 --- /dev/null +++ b/tests/modules/core/m2/AMBuild @@ -0,0 +1,7 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: + +m2 = program.Module(builder, 'm2') +m2.compiler.cflags = [] +m2.sources += [ + 'm2.cc', +] diff --git a/tests/modules/core/m2/m2.cc b/tests/modules/core/m2/m2.cc new file mode 100644 index 000000000..9195d1fae --- /dev/null +++ b/tests/modules/core/m2/m2.cc @@ -0,0 +1,4 @@ +int m2() +{ + return 0; +} diff --git a/tests/modules/core/main.cc b/tests/modules/core/main.cc new file mode 100644 index 000000000..fc850bb10 --- /dev/null +++ b/tests/modules/core/main.cc @@ -0,0 +1,9 @@ + +#include + +extern int m1(); + +int main() +{ + return m1(); +} diff --git a/tests/modules/core/main2.cc b/tests/modules/core/main2.cc new file mode 100644 index 000000000..4d028d043 --- /dev/null +++ b/tests/modules/core/main2.cc @@ -0,0 +1,5 @@ + +int m1() +{ + return 0; +} diff --git a/tests/originalcwd/AMBuildScript b/tests/originalcwd/AMBuildScript new file mode 100644 index 000000000..07dd540b4 --- /dev/null +++ b/tests/originalcwd/AMBuildScript @@ -0,0 +1,6 @@ +# vim: set ts=8 sts=2 tw=99 et ft=python: +import os, sys + +# This should print the same thing as when configure.py'd, no matter where +# we build from, when AMBuildScript changes. +print(builder.originalCwd) diff --git a/tests/originalcwd/configure.py b/tests/originalcwd/configure.py new file mode 100644 index 000000000..8cc418bf8 --- /dev/null +++ b/tests/originalcwd/configure.py @@ -0,0 +1,6 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et: +import sys +from ambuild2 import run + +builder = run.PrepareBuild(sourcePath = sys.path[0]) +builder.Configure() diff --git a/tests/shaders/AMBuildScript b/tests/shaders/AMBuildScript new file mode 100644 index 000000000..fdb400674 --- /dev/null +++ b/tests/shaders/AMBuildScript @@ -0,0 +1,25 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: +import os +builder.DetectCxx() + +shaders = builder.tools.FXC('shaders', 'my::stuff') +shaders.listDefineName = 'SHADER_MAP' +shaders.shaders += [ + { + 'source': 'code/image_vs.hlsl', + 'variable': 'sImageVS', + 'profile': 'vs_4_0', + }, + { + 'source': 'code/image_ps.hlsl', + 'variable': 'sImagePS', + 'profile': 'ps_4_0', + }, +] + +program = builder.cxx.Program('sample') +program.sources += [ + 'code/include-shaders.cc', +] +program.custom += [shaders] +builder.Add(program) diff --git a/tests/shaders/code/common.hlsl b/tests/shaders/code/common.hlsl new file mode 100644 index 000000000..62a17771d --- /dev/null +++ b/tests/shaders/code/common.hlsl @@ -0,0 +1,3 @@ +// (C) 2015 AlliedModders LLC +// All rights reserved. +// diff --git a/tests/shaders/code/image_common.hlsl b/tests/shaders/code/image_common.hlsl new file mode 100644 index 000000000..5dfcf6d52 --- /dev/null +++ b/tests/shaders/code/image_common.hlsl @@ -0,0 +1,6 @@ + +struct IMAGE_VS_OUTPUT { + float4 pos : SV_Position; + float2 source_uv : TEXCOORD0; + float4 image_rect : TEXCOORD1; +}; diff --git a/tests/shaders/code/image_ps.hlsl b/tests/shaders/code/image_ps.hlsl new file mode 100644 index 000000000..b91d5ee56 --- /dev/null +++ b/tests/shaders/code/image_ps.hlsl @@ -0,0 +1,13 @@ +#include "common.hlsl" +#include "image_common.hlsl" + +Texture2D tImage : register(ps, t0); +sampler sSampler : register(ps, s0); + +float4 main(const IMAGE_VS_OUTPUT v) : SV_Target +{ + float2 image_offset = v.image_rect.xy; + float2 image_size = v.image_rect.zw; + float2 uv = image_offset + image_size * frac(v.source_uv); + return tImage.Sample(sSampler, uv); +} diff --git a/tests/shaders/code/image_vs.hlsl b/tests/shaders/code/image_vs.hlsl new file mode 100644 index 000000000..a54a716f6 --- /dev/null +++ b/tests/shaders/code/image_vs.hlsl @@ -0,0 +1,32 @@ +#include "common.hlsl" +#include "vs_common.hlsl" +#include "image_common.hlsl" + +struct Image { + float4 source_uv; + float4 dest; + uint tile_index; + uint3 padding; +}; + +cbuffer imageBuffer : register(b4) { + Image images[1365]; +}; + +IMAGE_VS_OUTPUT main(const VS_INPUT input) +{ + Image image = images[input.id]; + + QuadVertexInfo vi = ComputeQuadVertex( + image.tile_index, + image.dest, + input.pos); + + float2 uv = (vi.clipped_pos - vi.dest_rect.xy) / vi.dest_rect.zw; + + IMAGE_VS_OUTPUT v; + v.pos = vi.out_vertex; + v.source_uv = uv; //TexturizeQuadVertex(image.source_uv, input.pos); + v.image_rect = image.source_uv; + return v; +} diff --git a/tests/shaders/code/include-shaders.cc b/tests/shaders/code/include-shaders.cc new file mode 100644 index 000000000..a6bb1708f --- /dev/null +++ b/tests/shaders/code/include-shaders.cc @@ -0,0 +1,11 @@ +#include +#include +#include "shaders-include.h" + +int main() +{ +#define _(name) \ + printf("%p %d\n", my::stuff::name##_Bytes, int(my::stuff::name##_Length)); + SHADER_MAP(_) +#undef _ +} diff --git a/tests/shaders/code/vs_common.hlsl b/tests/shaders/code/vs_common.hlsl new file mode 100644 index 000000000..6d6500191 --- /dev/null +++ b/tests/shaders/code/vs_common.hlsl @@ -0,0 +1,67 @@ + +// Group #1: Updates on Window size changes. +cbuffer worldBuffer : register(b0) { + float4x4 kProjection; +}; + +struct Tile { + float4 screenRect; +}; + +// Group #2: Updated on tile buffer changes. +cbuffer tileBuffer : register(b1) { + Tile tiles[4096]; +}; + +struct VS_INPUT { + float2 pos : POSITION; + uint id : SV_InstanceID; +}; + +struct QuadVertexInfo { + // The vertex to pass to the pixel shader. + float4 out_vertex; + // Destination rect, in screen space. + float4 dest_rect; + // Destination vertex, clipped to tile bounds. + float2 clipped_pos; +}; + +QuadVertexInfo ComputeQuadVertex(uint tile_index, float4 dest_rect, float2 vertex) +{ + float4 tile_screen_rect = tiles[tile_index].screenRect; + + // Convert the vertex to screen space. +#if 0 + float2 screen_vertex = lerp( + dest_rect.xy, // Top-left vertex. + dest_rect.zw, // Bottom-right vertex. + vertex); +#else + float2 screen_vertex = float2( + dest_rect.x + vertex.x * dest_rect.z, + dest_rect.y + vertex.y * dest_rect.w); +#endif + + // Clamp the vertex to inside the tile. +#if 1 + screen_vertex = clamp( + screen_vertex, + tile_screen_rect.xy, + tile_screen_rect.xy + tile_screen_rect.zw); +#endif + + QuadVertexInfo info; + info.out_vertex = mul(kProjection, float4(screen_vertex, 0, 1)); + info.dest_rect = dest_rect; + info.clipped_pos = screen_vertex; + + return info; +} + +float2 TexturizeQuadVertex(float4 uv_rect, float2 pos) +{ + return float2( + uv_rect.x + pos.x * uv_rect.z, + uv_rect.y + pos.y * uv_rect.w); +} diff --git a/tests/shaders/configure.py b/tests/shaders/configure.py new file mode 100644 index 000000000..5e2d62a95 --- /dev/null +++ b/tests/shaders/configure.py @@ -0,0 +1,15 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et: +API_VERSION = '2.1' + +import sys +try: + from ambuild2 import run + if not run.HasAPI(API_VERSION): + raise Exception() +except: + sys.stderr.write('AMBuild {0} must be installed to build this project.\n'.format(API_VERSION)) + sys.stderr.write('http://www.alliedmods.net/ambuild\n') + sys.exit(1) + +builder = run.BuildParser(sourcePath = sys.path[0], api=API_VERSION) +builder.Configure() diff --git a/tests/shared_outputs/basic/AMBuildScript b/tests/shared_outputs/basic/AMBuildScript new file mode 100644 index 000000000..a0f8fa939 --- /dev/null +++ b/tests/shared_outputs/basic/AMBuildScript @@ -0,0 +1,25 @@ +# vim: set ts=8 sts=2 tw=99 et ft=python: +import os, sys + +argv = [ + sys.executable, + os.path.join(builder.sourcePath, 'generate_header.py'), + 'output.h' +] + +shared_outputs = [ +# Comment for reconfigure test #1. + os.path.join(builder.buildFolder, 'output.h') +] + +# Comment all below for reconfigure test #2. +work_folder = builder.AddFolder('work') + +builder.AddCommand( + inputs = [], + argv = argv, + outputs = [], + folder = work_folder, + shared_outputs = shared_outputs +) + diff --git a/tests/shared_outputs/basic/configure.py b/tests/shared_outputs/basic/configure.py new file mode 100644 index 000000000..8cc418bf8 --- /dev/null +++ b/tests/shared_outputs/basic/configure.py @@ -0,0 +1,6 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et: +import sys +from ambuild2 import run + +builder = run.PrepareBuild(sourcePath = sys.path[0]) +builder.Configure() diff --git a/tests/shared_outputs/basic/generate_header.py b/tests/shared_outputs/basic/generate_header.py new file mode 100644 index 000000000..b5cd09cf7 --- /dev/null +++ b/tests/shared_outputs/basic/generate_header.py @@ -0,0 +1,9 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et: +import sys + +with open(sys.argv[1], 'w') as fp: + fp.write(""" +#ifndef HELLO_STRING +# define HELLO_STRING "HELLO!" +#endif +""") diff --git a/tests/shared_outputs/duplicates/AMBuildScript b/tests/shared_outputs/duplicates/AMBuildScript new file mode 100644 index 000000000..52e584dc4 --- /dev/null +++ b/tests/shared_outputs/duplicates/AMBuildScript @@ -0,0 +1,40 @@ +# vim: set ts=8 sts=2 tw=99 et ft=python: +import os, sys + +argv = [ + sys.executable, + os.path.join(builder.sourcePath, 'generate_header.py'), + 'output.h' +] + +shared_outputs = [ + os.path.join(builder.buildFolder, 'output.h') +] + +def FailTest1(): + builder.AddCommand( + inputs = [], + argv = argv, + outputs = [], + shared_outputs = shared_outputs + shared_outputs + ) + +def FailTest2(): + builder.AddCommand( + inputs = [], + argv = argv, + outputs = shared_outputs + shared_outputs + ) + +def FailTest3(): + builder.AddCommand( + inputs = [], + argv = argv, + outputs = shared_outputs, + shared_outputs = shared_outputs + ) + +# All of these should fail. +FailTest1() +#FailTest2() +#FailTest3() diff --git a/tests/shared_outputs/duplicates/configure.py b/tests/shared_outputs/duplicates/configure.py new file mode 100644 index 000000000..8cc418bf8 --- /dev/null +++ b/tests/shared_outputs/duplicates/configure.py @@ -0,0 +1,6 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et: +import sys +from ambuild2 import run + +builder = run.PrepareBuild(sourcePath = sys.path[0]) +builder.Configure() diff --git a/tests/shared_outputs/duplicates/generate_header.py b/tests/shared_outputs/duplicates/generate_header.py new file mode 100644 index 000000000..b5cd09cf7 --- /dev/null +++ b/tests/shared_outputs/duplicates/generate_header.py @@ -0,0 +1,9 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et: +import sys + +with open(sys.argv[1], 'w') as fp: + fp.write(""" +#ifndef HELLO_STRING +# define HELLO_STRING "HELLO!" +#endif +""") diff --git a/tests/shared_outputs/mixup/AMBuildScript b/tests/shared_outputs/mixup/AMBuildScript new file mode 100644 index 000000000..99831840a --- /dev/null +++ b/tests/shared_outputs/mixup/AMBuildScript @@ -0,0 +1,70 @@ +# vim: set ts=8 sts=2 tw=99 et ft=python: +import os, sys + +argv = [ + sys.executable, + os.path.join(builder.sourcePath, 'generate_header.py'), + 'output.h' +] + +shared_outputs = [ + os.path.join(builder.buildFolder, 'output.h') +] + +def Test1(): + builder.AddCommand( + inputs = [], + argv = argv, + outputs = [], + shared_outputs = shared_outputs + ) + +def Test2(): + # Change the output to a normal output. + builder.AddCommand( + inputs = [], + argv = argv, + outputs = shared_outputs + ) + +def Test3(): + # Change back to a shared output. + Test1() + +def Test4(): + # Change to a folder. + builder.AddFolder('output.h') + +def Test5(): + # Change back to a shared output. + Test1() + +def TestFail1(): + Test2() + Test1() + +def TestFail2(): + Test1() + Test2() + +def TestFail3(): + Test1() + Test4() + +def TestFail4(): + Test4() + Test1() + +# Uncomment 1, run, recomment, uncomment 2 to test. Repeat. Each time using +# refactoring mode should fail. +Test1() +#Test2() +#Test3() +#Test4() +#Test5() + +# These tests should all fail. +#TestFail1() +#TestFail2() +#TestFail3() +#TestFail4() diff --git a/tests/shared_outputs/mixup/configure.py b/tests/shared_outputs/mixup/configure.py new file mode 100644 index 000000000..8cc418bf8 --- /dev/null +++ b/tests/shared_outputs/mixup/configure.py @@ -0,0 +1,6 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et: +import sys +from ambuild2 import run + +builder = run.PrepareBuild(sourcePath = sys.path[0]) +builder.Configure() diff --git a/tests/shared_outputs/mixup/generate_header.py b/tests/shared_outputs/mixup/generate_header.py new file mode 100644 index 000000000..b5cd09cf7 --- /dev/null +++ b/tests/shared_outputs/mixup/generate_header.py @@ -0,0 +1,9 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et: +import sys + +with open(sys.argv[1], 'w') as fp: + fp.write(""" +#ifndef HELLO_STRING +# define HELLO_STRING "HELLO!" +#endif +""") diff --git a/tests/shared_outputs/multiples/AMBuildScript b/tests/shared_outputs/multiples/AMBuildScript new file mode 100644 index 000000000..a5ade94d2 --- /dev/null +++ b/tests/shared_outputs/multiples/AMBuildScript @@ -0,0 +1,34 @@ +# vim: set ts=8 sts=2 tw=99 et ft=python: +import os, sys + +argv = [ + sys.executable, + os.path.join(builder.sourcePath, 'generate_header.py'), + 'output.h' +] + +shared_outputs = [ + os.path.join(builder.buildFolder, 'output.h') +] + +# Comment anything below to test reconfiguring. +builder.AddCommand( + inputs = [], + argv = argv, + outputs = [], + shared_outputs = shared_outputs +) + +builder.AddCommand( + inputs = [], + argv = argv, + outputs = [], + shared_outputs = shared_outputs +) + +builder.AddCommand( + inputs = [], + argv = argv, + outputs = [], + shared_outputs = shared_outputs +) diff --git a/tests/shared_outputs/multiples/configure.py b/tests/shared_outputs/multiples/configure.py new file mode 100644 index 000000000..8cc418bf8 --- /dev/null +++ b/tests/shared_outputs/multiples/configure.py @@ -0,0 +1,6 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et: +import sys +from ambuild2 import run + +builder = run.PrepareBuild(sourcePath = sys.path[0]) +builder.Configure() diff --git a/tests/shared_outputs/multiples/generate_header.py b/tests/shared_outputs/multiples/generate_header.py new file mode 100644 index 000000000..b5cd09cf7 --- /dev/null +++ b/tests/shared_outputs/multiples/generate_header.py @@ -0,0 +1,9 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et: +import sys + +with open(sys.argv[1], 'w') as fp: + fp.write(""" +#ifndef HELLO_STRING +# define HELLO_STRING "HELLO!" +#endif +""") diff --git a/tests/staticlib/AMBuildScript b/tests/staticlib/AMBuildScript new file mode 100644 index 000000000..ed33b9962 --- /dev/null +++ b/tests/staticlib/AMBuildScript @@ -0,0 +1,10 @@ +# vim: set ts=8 sts=2 tw=99 et ft=python: +import os, sys + +builder.DetectCompilers() + +program = builder.compiler.StaticLibrary("hello") +program.sources = [ + 'main.cpp' +] +builder.Add(program) diff --git a/tests/staticlib/configure.py b/tests/staticlib/configure.py new file mode 100644 index 000000000..300f4dd56 --- /dev/null +++ b/tests/staticlib/configure.py @@ -0,0 +1,6 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et: +import sys +from ambuild2 import run + +builder = run.BuildParser(sourcePath = sys.path[0], api = '2.1') +builder.Configure() diff --git a/tests/staticlib/main.cpp b/tests/staticlib/main.cpp new file mode 100644 index 000000000..4a2e3494a --- /dev/null +++ b/tests/staticlib/main.cpp @@ -0,0 +1,7 @@ +#include + +extern "C" int egg() +{ + return printf("hello!\n"); +} + diff --git a/tests/vcfiles/AMBuildScript b/tests/vcfiles/AMBuildScript new file mode 100644 index 000000000..f0c8a0f5a --- /dev/null +++ b/tests/vcfiles/AMBuildScript @@ -0,0 +1,12 @@ +# vim: set ts=8 sts=2 tw=99 et ft=python: +import os, sys + +builder.DetectCompilers() + +program = builder.compiler.Library("hello") +program.sources = [ + 'main.cpp' +] + +# Comment below to test successful folder removal. +builder.Add(program) diff --git a/tests/vcfiles/configure.py b/tests/vcfiles/configure.py new file mode 100644 index 000000000..8cc418bf8 --- /dev/null +++ b/tests/vcfiles/configure.py @@ -0,0 +1,6 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et: +import sys +from ambuild2 import run + +builder = run.PrepareBuild(sourcePath = sys.path[0]) +builder.Configure() diff --git a/tests/vcfiles/main.cpp b/tests/vcfiles/main.cpp new file mode 100644 index 000000000..4a2e3494a --- /dev/null +++ b/tests/vcfiles/main.cpp @@ -0,0 +1,7 @@ +#include + +extern "C" int egg() +{ + return printf("hello!\n"); +} + diff --git a/utils/RCBot2_meta/HPB_Bot2.sln b/utils/RCBot2_meta/HPB_Bot2.sln deleted file mode 100644 index 0d2e6c532..000000000 --- a/utils/RCBot2_meta/HPB_Bot2.sln +++ /dev/null @@ -1,34 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26430.6 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RCBot2Meta", "HPB_Bot2.vcxproj", "{B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x86 = Debug|x86 - Release_NonHomeFolder|Win32 = Release_NonHomeFolder|Win32 - Release_NonHomeFolder|x86 = Release_NonHomeFolder|x86 - Release|Win32 = Release|Win32 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Debug|Win32.ActiveCfg = Debug|Win32 - {B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Debug|Win32.Build.0 = Debug|Win32 - {B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Debug|x86.ActiveCfg = Debug|Win32 - {B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Debug|x86.Build.0 = Debug|Win32 - {B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Release_NonHomeFolder|Win32.ActiveCfg = Release_NonHomeFolder|Win32 - {B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Release_NonHomeFolder|Win32.Build.0 = Release_NonHomeFolder|Win32 - {B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Release_NonHomeFolder|x86.ActiveCfg = Release_NonHomeFolder|Win32 - {B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Release_NonHomeFolder|x86.Build.0 = Release_NonHomeFolder|Win32 - {B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Release|Win32.ActiveCfg = Release|Win32 - {B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Release|Win32.Build.0 = Release|Win32 - {B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Release|x86.ActiveCfg = Release|Win32 - {B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/utils/RCBot2_meta/HPB_Bot2.tags b/utils/RCBot2_meta/HPB_Bot2.tags deleted file mode 100644 index 7f92bd321..000000000 Binary files a/utils/RCBot2_meta/HPB_Bot2.tags and /dev/null differ diff --git a/utils/RCBot2_meta/HPB_Bot2.vcproj b/utils/RCBot2_meta/HPB_Bot2.vcproj deleted file mode 100644 index 8bdb9ef17..000000000 --- a/utils/RCBot2_meta/HPB_Bot2.vcproj +++ /dev/null @@ -1,843 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/utils/RCBot2_meta/HPB_Bot2.vcxproj b/utils/RCBot2_meta/HPB_Bot2.vcxproj index acbcd7380..2674ea083 100644 --- a/utils/RCBot2_meta/HPB_Bot2.vcxproj +++ b/utils/RCBot2_meta/HPB_Bot2.vcxproj @@ -5,14 +5,26 @@ Debug Win32 + + Debug + x64 + Release_NonHomeFolder Win32 + + Release_NonHomeFolder + x64 + Release Win32 + + Release + x64 + {B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64} @@ -22,24 +34,44 @@ Svn SubversionScc RCBot2Meta - 10.0.17134.0 + 10.0 DynamicLibrary - v120 + v145 + false + MultiByte + Spectre + + + DynamicLibrary false MultiByte + Spectre + v145 DynamicLibrary - v120 + v145 + false + MultiByte + + + DynamicLibrary + v145 false MultiByte DynamicLibrary - v120 + v145 + false + MultiByte + + + DynamicLibrary + v145 false MultiByte @@ -50,14 +82,26 @@ + + + + + + + + + + + + <_ProjectFileVersion>11.0.50727.1 @@ -66,12 +110,22 @@ false $(ProjectName)Debug + + false + $(ProjectName)Debug + false + + false + false + + false + @@ -87,18 +141,19 @@ Disabled - ..\..\public\mathlib;..\..\public;..\..\public\engine;..\..\public\tier0;..\..\public\tier1;..\..\dlls;..\..\game_shared;..\..\game\shared;..\..\game\server;..\..\public\game\server;..\mmsource\core\;..\mmsource\core\sourcehook\;..\mmsource\public\;%(AdditionalIncludeDirectories) - SOURCE_ENGINE=4;WIN32;_DEBUG;_WINDOWS;HOMEFOLDER;%(PreprocessorDefinitions) + ..\..\alliedmodders\hl2sdk-tf2\public\mathlib;..\..\alliedmodders\hl2sdk-tf2\public;..\..\alliedmodders\hl2sdk-tf2\public\engine;..\..\alliedmodders\hl2sdk-tf2\public\tier0;..\..\alliedmodders\hl2sdk-tf2\public\tier1;..\..\alliedmodders\hl2sdk-tf2\game\shared;..\..\alliedmodders\hl2sdk-tf2\game\server;..\..\alliedmodders\hl2sdk-tf2\public\game\server;..\..\alliedmodders\metamod-source\core\;..\..\alliedmodders\metamod-source\core\sourcehook\;..\..\alliedmodders\metamod-source\public\;..\..\alliedmodders\sourcemod\sourcepawn\include;..\..\alliedmodders\sourcemod\public\amtl;..\..\alliedmodders\sourcemod\public\amtl\amtl;..\..\alliedmodders\sourcemod\public\extensions;..\..\alliedmodders\sourcemod\public;..\..\sm_ext\;..\..\rcbot\;..\..\rcbot\tf2;..\..\rcbot_subcmds;..\..\utils\RCBot2_meta;..\..\versioning;..\..\;%(AdditionalIncludeDirectories) + SOURCE_ENGINE=11;SE_TF2=11;WIN32;_DEBUG;_WINDOWS;HOMEFOLDER;_CRT_SECURE_NO_WARNINGS;RCBOT_MAXPLAYERS=101;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug - true + false true Level4 true EditAndContinue Default - /D SE_EPISODEONE=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_ORANGEBOXVALVE=4 /D SE_LEFT4DEAD=5 /D SE_LEFT4DEAD2=6 /D SE_ALIENSWARM=7 + /D SE_EPISODEONE=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_ORANGEBOXVALVE=4 /D SE_LEFT4DEAD=5 /D SE_LEFT4DEAD2=6 /D SE_ALIENSWARM=7 /FS StreamingSIMDExtensions2 + stdcpp17 _DEBUG;%(PreprocessorDefinitions) @@ -119,6 +174,53 @@ + + + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + .\Debug/HPB_bot2.tlb + + + + + Disabled + ..\..\alliedmodders\hl2sdk-tf2\public\mathlib;..\..\alliedmodders\hl2sdk-tf2\public;..\..\alliedmodders\hl2sdk-tf2\public\engine;..\..\alliedmodders\hl2sdk-tf2\public\tier0;..\..\alliedmodders\hl2sdk-tf2\public\tier1;..\..\alliedmodders\hl2sdk-tf2\game\shared;..\..\alliedmodders\hl2sdk-tf2\game\server;..\..\alliedmodders\hl2sdk-tf2\public\game\server;..\..\alliedmodders\metamod-source\core\;..\..\alliedmodders\metamod-source\core\sourcehook\;..\..\alliedmodders\metamod-source\public\;..\..\alliedmodders\sourcemod\sourcepawn\include;..\..\alliedmodders\sourcemod\public\amtl;..\..\alliedmodders\sourcemod\public\amtl\amtl;..\..\alliedmodders\sourcemod\public\extensions;..\..\alliedmodders\sourcemod\public;..\..\sm_ext\;..\..\rcbot\;..\..\rcbot\tf2;..\..\rcbot_subcmds;..\..\utils\RCBot2_meta;..\..\versioning;..\..\;%(AdditionalIncludeDirectories) + SOURCE_ENGINE=11;SE_TF2=11;WIN64;_DEBUG;_WINDOWS;HOMEFOLDER;_CRT_SECURE_NO_WARNINGS;RCBOT_MAXPLAYERS=101;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + false + true + Level4 + true + ProgramDatabase + Default + /D SE_EPISODEONE=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_ORANGEBOXVALVE=4 /D SE_LEFT4DEAD=5 /D SE_LEFT4DEAD2=6 /D SE_ALIENSWARM=7 /FS + StreamingSIMDExtensions2 + stdcpp17 + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + + + true + ..\..\lib\public;..\..\lib\common;%(AdditionalLibraryDirectories) + false + libc;libcd;libcmt;%(IgnoreSpecificDefaultLibraries) + true + true + Windows + + + + @@ -134,12 +236,12 @@ OnlyExplicitInline true Speed - ..\..\public\mathlib;..\..\public;..\..\public\engine;..\..\public\tier0;..\..\public\tier1;..\..\dlls;..\..\game_shared;..\..\game\shared;..\..\game\server;..\..\public\game\server;..\mmsource\core\;..\mmsource\core\sourcehook\;..\mmsource\public\;%(AdditionalIncludeDirectories) - SOURCE_ENGINE=4;WIN32;NDEBUG;_WINDOWS;HOMEFOLDER;%(PreprocessorDefinitions) + ..\..\alliedmodders\hl2sdk-tf2\public\mathlib;..\..\alliedmodders\hl2sdk-tf2\public;..\..\alliedmodders\hl2sdk-tf2\public\engine;..\..\alliedmodders\hl2sdk-tf2\public\tier0;..\..\alliedmodders\hl2sdk-tf2\public\tier1;..\..\alliedmodders\hl2sdk-tf2\game\shared;..\..\alliedmodders\hl2sdk-tf2\game\server;..\..\alliedmodders\hl2sdk-tf2\public\game\server;..\..\alliedmodders\metamod-source\core\;..\..\alliedmodders\metamod-source\core\sourcehook\;..\..\alliedmodders\metamod-source\public\;..\..\alliedmodders\sourcemod\sourcepawn\include;..\..\alliedmodders\sourcemod\public\amtl;..\..\alliedmodders\sourcemod\public\amtl\amtl;..\..\alliedmodders\sourcemod\public\extensions;..\..\alliedmodders\sourcemod\public;..\..\sm_ext\;..\..\rcbot\;..\..\rcbot\tf2;..\..\rcbot_subcmds;..\..\utils\RCBot2_meta;..\..\versioning;..\..\;%(AdditionalIncludeDirectories) + SOURCE_ENGINE=11;SE_TF2=11;WIN32;NDEBUG;_WINDOWS;HOMEFOLDER;_CRT_SECURE_NO_WARNINGS;RCBOT_MAXPLAYERS=101;%(PreprocessorDefinitions) true MultiThreaded true - true + false Level3 false @@ -149,6 +251,7 @@ false /D SE_EPISODEONE=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_ORANGEBOXVALVE=4 /D SE_LEFT4DEAD=5 /D SE_LEFT4DEAD2=6 /D SE_ALIENSWARM=7 StreamingSIMDExtensions2 + stdcpp17 NDEBUG;%(PreprocessorDefinitions) @@ -165,6 +268,53 @@ MachineX86 + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + .\Release/HPB_bot2.tlb + + + + + MaxSpeed + OnlyExplicitInline + true + Speed + ..\..\alliedmodders\hl2sdk-tf2\public\mathlib;..\..\alliedmodders\hl2sdk-tf2\public;..\..\alliedmodders\hl2sdk-tf2\public\engine;..\..\alliedmodders\hl2sdk-tf2\public\tier0;..\..\alliedmodders\hl2sdk-tf2\public\tier1;..\..\alliedmodders\hl2sdk-tf2\game\shared;..\..\alliedmodders\hl2sdk-tf2\game\server;..\..\alliedmodders\hl2sdk-tf2\public\game\server;..\..\alliedmodders\metamod-source\core\;..\..\alliedmodders\metamod-source\core\sourcehook\;..\..\alliedmodders\metamod-source\public\;..\..\alliedmodders\sourcemod\sourcepawn\include;..\..\alliedmodders\sourcemod\public\amtl;..\..\alliedmodders\sourcemod\public\amtl\amtl;..\..\alliedmodders\sourcemod\public\extensions;..\..\alliedmodders\sourcemod\public;..\..\sm_ext\;..\..\rcbot\;..\..\rcbot\tf2;..\..\rcbot_subcmds;..\..\utils\RCBot2_meta;..\..\versioning;..\..\;%(AdditionalIncludeDirectories) + SOURCE_ENGINE=11;SE_TF2=11;WIN64;NDEBUG;_WINDOWS;HOMEFOLDER;_CRT_SECURE_NO_WARNINGS;RCBOT_MAXPLAYERS=101;%(PreprocessorDefinitions) + true + MultiThreaded + true + false + + + Level4 + false + true + ProgramDatabase + Default + false + /D SE_EPISODEONE=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_ORANGEBOXVALVE=4 /D SE_LEFT4DEAD=5 /D SE_LEFT4DEAD2=6 /D SE_ALIENSWARM=7 + StreamingSIMDExtensions2 + stdcpp17 + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + tier0.lib;tier1.lib;tier2.lib;tier3.lib;mathlib.lib;vstdlib.lib; + true + ..\..\lib\public;..\..\lib\common;%(AdditionalLibraryDirectories) + LIBC;LIBCD;%(IgnoreSpecificDefaultLibraries) + true + true + Windows + + @@ -176,24 +326,28 @@ - MaxSpeed - ..\..\public\mathlib;..\..\public;..\..\public\engine;..\..\public\tier0;..\..\public\tier1;..\..\dlls;..\..\game_shared;..\..\game\shared;..\..\game\server;..\..\public\game\server;..\mmsource\core\;..\mmsource\core\sourcehook\;..\mmsource\public\;%(AdditionalIncludeDirectories) - SOURCE_ENGINE=4;WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + Full + ..\..\alliedmodders\hl2sdk-tf2\public\mathlib;..\..\alliedmodders\hl2sdk-tf2\public;..\..\alliedmodders\hl2sdk-tf2\public\engine;..\..\alliedmodders\hl2sdk-tf2\public\tier0;..\..\alliedmodders\hl2sdk-tf2\public\tier1;..\..\alliedmodders\hl2sdk-tf2\game\shared;..\..\alliedmodders\hl2sdk-tf2\game\server;..\..\alliedmodders\hl2sdk-tf2\public\game\server;..\..\alliedmodders\metamod-source\core\;..\..\alliedmodders\metamod-source\core\sourcehook\;..\..\alliedmodders\metamod-source\public\;..\..\alliedmodders\sourcemod\sourcepawn\include;..\..\alliedmodders\sourcemod\public\amtl;..\..\alliedmodders\sourcemod\public\amtl\amtl;..\..\alliedmodders\sourcemod\public\extensions;..\..\alliedmodders\sourcemod\public;..\..\sm_ext\;..\..\rcbot\;..\..\rcbot\tf2;..\..\rcbot_subcmds;..\..\utils\RCBot2_meta;..\..\versioning;..\..\;%(AdditionalIncludeDirectories) + SOURCE_ENGINE=11;SE_TF2=11;WIN32;NDEBUG;_WINDOWS;NOMINMAX;_CRT_SECURE_NO_WARNINGS;RCBOT_MAXPLAYERS=101;%(PreprocessorDefinitions) true MultiThreaded true - true + false - Level3 false true ProgramDatabase Default false - /D SE_EPISODEONE=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_ORANGEBOXVALVE=4 /D SE_LEFT4DEAD=5 /D SE_LEFT4DEAD2=6 /D SE_ALIENSWARM=7 %(AdditionalOptions) + /D SE_EPISODEONE=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_ORANGEBOXVALVE=4 /D SE_LEFT4DEAD=5 /D SE_LEFT4DEAD2=6 /D SE_ALIENSWARM=7 /FS %(AdditionalOptions) StreamingSIMDExtensions2 - OnlyExplicitInline - Fast + AnySuitable + 4005;4028;4058;4061;4062;4242;4265;4365;4464;4471;4625;4710;4820;4996;5045;5204;5219;5220;5264;%(DisableSpecificWarnings) + Default + stdcpp17 + Level4 + Speed + true NDEBUG;%(PreprocessorDefinitions) @@ -208,17 +362,88 @@ true Windows MachineX86 + true + true + + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + .\Release/HPB_bot2.tlb + + + + + MaxSpeed + ..\..\alliedmodders\hl2sdk-tf2\public\mathlib;..\..\alliedmodders\hl2sdk-tf2\public;..\..\alliedmodders\hl2sdk-tf2\public\engine;..\..\alliedmodders\hl2sdk-tf2\public\tier0;..\..\alliedmodders\hl2sdk-tf2\public\tier1;..\..\alliedmodders\hl2sdk-tf2\game\shared;..\..\alliedmodders\hl2sdk-tf2\game\server;..\..\alliedmodders\hl2sdk-tf2\public\game\server;..\..\alliedmodders\metamod-source\core\;..\..\alliedmodders\metamod-source\core\sourcehook\;..\..\alliedmodders\metamod-source\public\;..\..\alliedmodders\sourcemod\sourcepawn\include;..\..\alliedmodders\sourcemod\public\amtl;..\..\alliedmodders\sourcemod\public\amtl\amtl;..\..\alliedmodders\sourcemod\public\extensions;..\..\alliedmodders\sourcemod\public;..\..\sm_ext\;..\..\rcbot\;..\..\rcbot\tf2;..\..\rcbot_subcmds;..\..\utils\RCBot2_meta;..\..\versioning;..\..\;%(AdditionalIncludeDirectories) + SOURCE_ENGINE=11;SE_TF2=11;WIN64;NDEBUG;_WINDOWS;NOMINMAX;_CRT_SECURE_NO_WARNINGS;RCBOT_MAXPLAYERS=101;%(PreprocessorDefinitions) + true + MultiThreaded + true + false + + + false + true + ProgramDatabase + Default + false + /D SE_EPISODEONE=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_ORANGEBOXVALVE=4 /D SE_LEFT4DEAD=5 /D SE_LEFT4DEAD2=6 /D SE_ALIENSWARM=7 /FS %(AdditionalOptions) + StreamingSIMDExtensions2 + AnySuitable + 4005;4028;4058;4061;4062;4242;4265;4365;4464;4471;4625;4710;4820;4996;5045;5204;5219;5220;5264;%(DisableSpecificWarnings) + stdcpp17 + Level4 + Speed + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + tier0.lib;tier1.lib;tier2.lib;tier3.lib;mathlib.lib;vstdlib.lib + true + ..\..\lib\public;..\..\lib\common;%(AdditionalLibraryDirectories) + LIBC;LIBCD;%(IgnoreSpecificDefaultLibraries) + true + true + Windows + true + true + + + + + + + + + + + + + + + + + + + @@ -241,10 +466,11 @@ + + - @@ -258,17 +484,28 @@ + + + + + + + + + + + - + @@ -276,18 +513,19 @@ + - + @@ -297,6 +535,7 @@ + @@ -308,42 +547,15 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - + + + + + diff --git a/utils/RCBot2_meta/HPB_Bot2.vcxproj.filters b/utils/RCBot2_meta/HPB_Bot2.vcxproj.filters index 94e26b4eb..821ab81c1 100644 --- a/utils/RCBot2_meta/HPB_Bot2.vcxproj.filters +++ b/utils/RCBot2_meta/HPB_Bot2.vcxproj.filters @@ -9,8 +9,20 @@ {16586188-ff32-4199-a515-f5a8fb020e68} h;hpp;hxx;hm;inl - - {3933157c-eb73-42a0-8f99-381e563f566c} + + {5df9d7b3-aea9-4a2c-8469-bb75515290ae} + + + {e6487d5d-1015-4df5-8b5f-038779fe57e8} + + + {5fc43177-eeaf-41e5-a623-5a472eac464c} + + + {6884231c-53d4-4673-9b74-c1811a727656} + + + {64422f0c-16cb-4913-acca-78f7f22042de} @@ -101,9 +113,6 @@ Source Files - - Source Files - Source Files @@ -149,6 +158,69 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files\sm_ext + + + Source Files\sm_ext + + + Source Files\sm_ext + + + Source Files\rcbot_subcmds + + + Source Files\rcbot_subcmds + + + Source Files\rcbot_subcmds + + + Source Files\rcbot_subcmds + + + Source Files\rcbot + + + Source Files\rcbot + + + Source Files\rcbot + + + Source Files\rcbot + + + Source Files\rcbot\tf2 + + + Source Files\rcbot + + + Source Files\loader + + + Source Files\rcbot_subcmds + + + Source Files\rcbot_subcmds + + + Source Files + + + Source Files\rcbot + @@ -169,9 +241,6 @@ Header Files - - Header Files - Header Files @@ -283,113 +352,78 @@ Header Files - - Header Files - - - Header Files - - - Header Files - - + Header Files - + Header Files - + Header Files - + Header Files - + Header Files - + Header Files - + Header Files - + Header Files - - Header Files + + Source Files\sm_ext - - Header Files + + Source Files\sm_ext - - Header Files + + Source Files\sm_ext - - Header Files + + Source Files\rcbot - - Header Files + + Source Files\rcbot - - Header Files + + Source Files\rcbot - - Header Files + + Source Files\rcbot\tf2 - - Header Files + + Source Files\rcbot - + Header Files - + Header Files - + Header Files - + Header Files - - Header Files + + Source Files\rcbot - - Header Files + + Source Files\rcbot - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - text - - - text - - - - - - + + + + + \ No newline at end of file diff --git a/utils/RCBot2_meta/HPB_Bot2.workspace.session b/utils/RCBot2_meta/HPB_Bot2.workspace.session deleted file mode 100644 index a5e665e34..000000000 --- a/utils/RCBot2_meta/HPB_Bot2.workspace.session +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/utils/RCBot2_meta/Makefile b/utils/RCBot2_meta/Makefile deleted file mode 100644 index f7d7ec5e9..000000000 --- a/utils/RCBot2_meta/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -.PHONY: clean All - -All: - @echo "----------Building project:[ RCBot2Meta - Release_NonHomeFolder_Win32 ]----------" - @"$(MAKE)" -f "RCBot2Meta.mk" -clean: - @echo "----------Cleaning project:[ RCBot2Meta - Release_NonHomeFolder_Win32 ]----------" - @"$(MAKE)" -f "RCBot2Meta.mk" clean diff --git a/utils/RCBot2_meta/Packages.dgml b/utils/RCBot2_meta/Packages.dgml deleted file mode 100644 index 07e97ea86..000000000 --- a/utils/RCBot2_meta/Packages.dgml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/utils/RCBot2_meta/RCBot2.sln b/utils/RCBot2_meta/RCBot2.sln new file mode 100644 index 000000000..109a9c7ac --- /dev/null +++ b/utils/RCBot2_meta/RCBot2.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34607.119 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RCBot2Meta", "HPB_Bot2.vcxproj", "{B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Debug|x64.ActiveCfg = Release_NonHomeFolder|x64 + {B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Debug|x64.Build.0 = Release_NonHomeFolder|x64 + {B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Debug|x86.ActiveCfg = Release_NonHomeFolder|Win32 + {B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Debug|x86.Build.0 = Release_NonHomeFolder|Win32 + {B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Release|x64.ActiveCfg = Release|x64 + {B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Release|x64.Build.0 = Release|x64 + {B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Release|x86.ActiveCfg = Release_NonHomeFolder|Win32 + {B6572CBE-7C7F-4FFF-94DE-AFBBBAB11C64}.Release|x86.Build.0 = Release_NonHomeFolder|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {31DCFF09-B6BC-4E5E-BF8E-8124DD0516C9} + EndGlobalSection +EndGlobal diff --git a/utils/RCBot2_meta/RCBot2Meta.mk b/utils/RCBot2_meta/RCBot2Meta.mk deleted file mode 100644 index 0d41b5bdf..000000000 --- a/utils/RCBot2_meta/RCBot2Meta.mk +++ /dev/null @@ -1,475 +0,0 @@ -## -## Auto Generated makefile by CodeLite IDE -## any manual changes will be erased -## -## Release_NonHomeFolder_Win32 -ProjectName :=RCBot2Meta -ConfigurationName :=Release_NonHomeFolder_Win32 -WorkspacePath :=/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta -ProjectPath :=/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta -IntermediateDirectory :=$(VS_Configuration)/ -OutDir := $(IntermediateDirectory) -CurrentFileName := -CurrentFilePath := -CurrentFileFullPath := -User :=mint -Date :=04/11/17 -CodeLitePath :=/home/mint/.codelite -LinkerName :=/usr/bin/i686-linux-gnu-g++ -SharedObjectLinkerName :=/usr/bin/i686-linux-gnu-g++ -shared -fPIC -ObjectSuffix :=.o -DependSuffix :=.o.d -PreprocessSuffix :=.i -DebugSwitch :=-g -IncludeSwitch :=-I -LibrarySwitch :=-l -OutputSwitch :=-o -LibraryPathSwitch :=-L -PreprocessorSwitch :=-D -SourceSwitch :=-c -OutputFile :=./Release_NonHomeFolder/HPB_bot2o.dll -Preprocessors :=$(PreprocessorSwitch)WIN32 $(PreprocessorSwitch)NDEBUG $(PreprocessorSwitch)_WINDOWS -ObjectSwitch :=-o -ArchiveOutputSwitch := -PreprocessOnlySwitch :=-E -ObjectsFileList :="RCBot2Meta.txt" -PCHCompileFlags := -MakeDirCommand :=mkdir -p -LinkOptions := -O0 -IncludePath := $(IncludeSwitch). $(IncludeSwitch)../../public/mathlib $(IncludeSwitch)../../public $(IncludeSwitch)../../public/engine $(IncludeSwitch)../../public/tier0 $(IncludeSwitch)../../public/tier1 $(IncludeSwitch)../../dlls $(IncludeSwitch)../../game_shared $(IncludeSwitch)../../game/shared $(IncludeSwitch)../../game/server $(IncludeSwitch)../../public/game/server -IncludePCH := -RcIncludePath := -Libs := $(LibrarySwitch)tier0 $(LibrarySwitch)tier1 $(LibrarySwitch)tier2 $(LibrarySwitch)tier3 $(LibrarySwitch)mathlib $(LibrarySwitch)vstdlib -ArLibs := "tier0.a" "tier1.a" "tier2.a" "tier3.a" "mathlib.a" "vstdlib.a" -LibPath := $(LibraryPathSwitch). $(LibraryPathSwitch)..\..\lib\public $(LibraryPathSwitch)..\..\lib\common - -## -## Common variables -## AR, CXX, CC, AS, CXXFLAGS and CFLAGS can be overriden using an environment variables -## -AR := /usr/bin/i686-linux-gnu-ar rcu -CXX := /usr/bin/i686-linux-gnu-g++ -CC := /usr/bin/i686-linux-gnu-gcc -CXXFLAGS := -g -Wall $(Preprocessors) -CFLAGS := $(Preprocessors) -ASFLAGS := -AS := /usr/bin/i686-linux-gnu-as - - -## -## User defined environment variables -## -CodeLiteDir:=/usr/share/codelite -VS_Configuration:=Release_NonHomeFolder -VS_IntDir:=$(VS_Configuration)/ -VS_OutDir:=$(VS_Configuration)/ -VS_Platform:=Win32 -VS_ProjectDir:=/home/desktop/Dropbox/src/rcbot2/utils/RCBot2_meta/ -VS_ProjectName:=RCBot2Meta -VS_SolutionDir:=/home/desktop/Dropbox/src/rcbot2/utils/RCBot2_meta/ -Objects0=$(IntermediateDirectory)/bot.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_accessclient.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_buttons.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_client.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_commands.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_configfile.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_coop.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_css_bot.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_dod_bot.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_dod_mod.cpp$(ObjectSuffix) \ - $(IntermediateDirectory)/bot_events.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_fortress.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_ga.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_ga_ind.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_getprop.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_globals.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_hl1dmsrc.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_hldm_bot.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_kv.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_menu.cpp$(ObjectSuffix) \ - $(IntermediateDirectory)/bot_mods.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_mtrand.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_navmesh.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_perceptron.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_profile.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_profiling.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_schedule.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_som.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_squads.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_strings.cpp$(ObjectSuffix) \ - $(IntermediateDirectory)/bot_task.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_tf2_mod.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_tf2_points.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_usercmd.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_utility.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_visibles.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_waypoint.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_waypoint_locations.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_waypoint_visibility.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_weapons.cpp$(ObjectSuffix) \ - $(IntermediateDirectory)/bot_wpt_dist.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_zombie.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_sigscan.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_cvars.cpp$(ObjectSuffix) $(IntermediateDirectory)/bot_plugin_meta.cpp$(ObjectSuffix) - - - -Objects=$(Objects0) - -## -## Main Build Targets -## -.PHONY: all clean PreBuild PrePreBuild PostBuild MakeIntermediateDirs -all: $(OutputFile) - -$(OutputFile): $(IntermediateDirectory)/.d $(Objects) - @$(MakeDirCommand) $(@D) - @echo "" > $(IntermediateDirectory)/.d - @echo $(Objects0) > $(ObjectsFileList) - $(SharedObjectLinkerName) $(OutputSwitch)$(OutputFile) @$(ObjectsFileList) $(LibPath) $(Libs) $(LinkOptions) - @$(MakeDirCommand) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/.build-release" - @echo rebuilt > "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/.build-release/RCBot2Meta" - -MakeIntermediateDirs: - @test -d $(VS_Configuration)/ || $(MakeDirCommand) $(VS_Configuration)/ - - -$(IntermediateDirectory)/.d: - @test -d $(VS_Configuration)/ || $(MakeDirCommand) $(VS_Configuration)/ - -PreBuild: - - -## -## Objects -## -$(IntermediateDirectory)/bot.cpp$(ObjectSuffix): bot.cpp $(IntermediateDirectory)/bot.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot.cpp$(DependSuffix): bot.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot.cpp$(DependSuffix) -MM bot.cpp - -$(IntermediateDirectory)/bot.cpp$(PreprocessSuffix): bot.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot.cpp$(PreprocessSuffix) bot.cpp - -$(IntermediateDirectory)/bot_accessclient.cpp$(ObjectSuffix): bot_accessclient.cpp $(IntermediateDirectory)/bot_accessclient.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_accessclient.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_accessclient.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_accessclient.cpp$(DependSuffix): bot_accessclient.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_accessclient.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_accessclient.cpp$(DependSuffix) -MM bot_accessclient.cpp - -$(IntermediateDirectory)/bot_accessclient.cpp$(PreprocessSuffix): bot_accessclient.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_accessclient.cpp$(PreprocessSuffix) bot_accessclient.cpp - -$(IntermediateDirectory)/bot_buttons.cpp$(ObjectSuffix): bot_buttons.cpp $(IntermediateDirectory)/bot_buttons.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_buttons.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_buttons.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_buttons.cpp$(DependSuffix): bot_buttons.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_buttons.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_buttons.cpp$(DependSuffix) -MM bot_buttons.cpp - -$(IntermediateDirectory)/bot_buttons.cpp$(PreprocessSuffix): bot_buttons.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_buttons.cpp$(PreprocessSuffix) bot_buttons.cpp - -$(IntermediateDirectory)/bot_client.cpp$(ObjectSuffix): bot_client.cpp $(IntermediateDirectory)/bot_client.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_client.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_client.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_client.cpp$(DependSuffix): bot_client.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_client.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_client.cpp$(DependSuffix) -MM bot_client.cpp - -$(IntermediateDirectory)/bot_client.cpp$(PreprocessSuffix): bot_client.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_client.cpp$(PreprocessSuffix) bot_client.cpp - -$(IntermediateDirectory)/bot_commands.cpp$(ObjectSuffix): bot_commands.cpp $(IntermediateDirectory)/bot_commands.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_commands.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_commands.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_commands.cpp$(DependSuffix): bot_commands.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_commands.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_commands.cpp$(DependSuffix) -MM bot_commands.cpp - -$(IntermediateDirectory)/bot_commands.cpp$(PreprocessSuffix): bot_commands.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_commands.cpp$(PreprocessSuffix) bot_commands.cpp - -$(IntermediateDirectory)/bot_configfile.cpp$(ObjectSuffix): bot_configfile.cpp $(IntermediateDirectory)/bot_configfile.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_configfile.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_configfile.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_configfile.cpp$(DependSuffix): bot_configfile.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_configfile.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_configfile.cpp$(DependSuffix) -MM bot_configfile.cpp - -$(IntermediateDirectory)/bot_configfile.cpp$(PreprocessSuffix): bot_configfile.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_configfile.cpp$(PreprocessSuffix) bot_configfile.cpp - -$(IntermediateDirectory)/bot_coop.cpp$(ObjectSuffix): bot_coop.cpp $(IntermediateDirectory)/bot_coop.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_coop.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_coop.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_coop.cpp$(DependSuffix): bot_coop.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_coop.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_coop.cpp$(DependSuffix) -MM bot_coop.cpp - -$(IntermediateDirectory)/bot_coop.cpp$(PreprocessSuffix): bot_coop.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_coop.cpp$(PreprocessSuffix) bot_coop.cpp - -$(IntermediateDirectory)/bot_css_bot.cpp$(ObjectSuffix): bot_css_bot.cpp $(IntermediateDirectory)/bot_css_bot.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_css_bot.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_css_bot.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_css_bot.cpp$(DependSuffix): bot_css_bot.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_css_bot.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_css_bot.cpp$(DependSuffix) -MM bot_css_bot.cpp - -$(IntermediateDirectory)/bot_css_bot.cpp$(PreprocessSuffix): bot_css_bot.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_css_bot.cpp$(PreprocessSuffix) bot_css_bot.cpp - -$(IntermediateDirectory)/bot_dod_bot.cpp$(ObjectSuffix): bot_dod_bot.cpp $(IntermediateDirectory)/bot_dod_bot.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_dod_bot.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_dod_bot.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_dod_bot.cpp$(DependSuffix): bot_dod_bot.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_dod_bot.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_dod_bot.cpp$(DependSuffix) -MM bot_dod_bot.cpp - -$(IntermediateDirectory)/bot_dod_bot.cpp$(PreprocessSuffix): bot_dod_bot.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_dod_bot.cpp$(PreprocessSuffix) bot_dod_bot.cpp - -$(IntermediateDirectory)/bot_dod_mod.cpp$(ObjectSuffix): bot_dod_mod.cpp $(IntermediateDirectory)/bot_dod_mod.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_dod_mod.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_dod_mod.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_dod_mod.cpp$(DependSuffix): bot_dod_mod.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_dod_mod.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_dod_mod.cpp$(DependSuffix) -MM bot_dod_mod.cpp - -$(IntermediateDirectory)/bot_dod_mod.cpp$(PreprocessSuffix): bot_dod_mod.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_dod_mod.cpp$(PreprocessSuffix) bot_dod_mod.cpp - -$(IntermediateDirectory)/bot_events.cpp$(ObjectSuffix): bot_events.cpp $(IntermediateDirectory)/bot_events.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_events.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_events.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_events.cpp$(DependSuffix): bot_events.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_events.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_events.cpp$(DependSuffix) -MM bot_events.cpp - -$(IntermediateDirectory)/bot_events.cpp$(PreprocessSuffix): bot_events.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_events.cpp$(PreprocessSuffix) bot_events.cpp - -$(IntermediateDirectory)/bot_fortress.cpp$(ObjectSuffix): bot_fortress.cpp $(IntermediateDirectory)/bot_fortress.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_fortress.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_fortress.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_fortress.cpp$(DependSuffix): bot_fortress.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_fortress.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_fortress.cpp$(DependSuffix) -MM bot_fortress.cpp - -$(IntermediateDirectory)/bot_fortress.cpp$(PreprocessSuffix): bot_fortress.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_fortress.cpp$(PreprocessSuffix) bot_fortress.cpp - -$(IntermediateDirectory)/bot_ga.cpp$(ObjectSuffix): bot_ga.cpp $(IntermediateDirectory)/bot_ga.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_ga.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_ga.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_ga.cpp$(DependSuffix): bot_ga.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_ga.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_ga.cpp$(DependSuffix) -MM bot_ga.cpp - -$(IntermediateDirectory)/bot_ga.cpp$(PreprocessSuffix): bot_ga.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_ga.cpp$(PreprocessSuffix) bot_ga.cpp - -$(IntermediateDirectory)/bot_ga_ind.cpp$(ObjectSuffix): bot_ga_ind.cpp $(IntermediateDirectory)/bot_ga_ind.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_ga_ind.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_ga_ind.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_ga_ind.cpp$(DependSuffix): bot_ga_ind.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_ga_ind.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_ga_ind.cpp$(DependSuffix) -MM bot_ga_ind.cpp - -$(IntermediateDirectory)/bot_ga_ind.cpp$(PreprocessSuffix): bot_ga_ind.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_ga_ind.cpp$(PreprocessSuffix) bot_ga_ind.cpp - -$(IntermediateDirectory)/bot_getprop.cpp$(ObjectSuffix): bot_getprop.cpp $(IntermediateDirectory)/bot_getprop.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_getprop.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_getprop.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_getprop.cpp$(DependSuffix): bot_getprop.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_getprop.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_getprop.cpp$(DependSuffix) -MM bot_getprop.cpp - -$(IntermediateDirectory)/bot_getprop.cpp$(PreprocessSuffix): bot_getprop.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_getprop.cpp$(PreprocessSuffix) bot_getprop.cpp - -$(IntermediateDirectory)/bot_globals.cpp$(ObjectSuffix): bot_globals.cpp $(IntermediateDirectory)/bot_globals.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_globals.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_globals.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_globals.cpp$(DependSuffix): bot_globals.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_globals.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_globals.cpp$(DependSuffix) -MM bot_globals.cpp - -$(IntermediateDirectory)/bot_globals.cpp$(PreprocessSuffix): bot_globals.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_globals.cpp$(PreprocessSuffix) bot_globals.cpp - -$(IntermediateDirectory)/bot_hl1dmsrc.cpp$(ObjectSuffix): bot_hl1dmsrc.cpp $(IntermediateDirectory)/bot_hl1dmsrc.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_hl1dmsrc.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_hl1dmsrc.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_hl1dmsrc.cpp$(DependSuffix): bot_hl1dmsrc.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_hl1dmsrc.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_hl1dmsrc.cpp$(DependSuffix) -MM bot_hl1dmsrc.cpp - -$(IntermediateDirectory)/bot_hl1dmsrc.cpp$(PreprocessSuffix): bot_hl1dmsrc.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_hl1dmsrc.cpp$(PreprocessSuffix) bot_hl1dmsrc.cpp - -$(IntermediateDirectory)/bot_hldm_bot.cpp$(ObjectSuffix): bot_hldm_bot.cpp $(IntermediateDirectory)/bot_hldm_bot.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_hldm_bot.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_hldm_bot.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_hldm_bot.cpp$(DependSuffix): bot_hldm_bot.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_hldm_bot.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_hldm_bot.cpp$(DependSuffix) -MM bot_hldm_bot.cpp - -$(IntermediateDirectory)/bot_hldm_bot.cpp$(PreprocessSuffix): bot_hldm_bot.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_hldm_bot.cpp$(PreprocessSuffix) bot_hldm_bot.cpp - -$(IntermediateDirectory)/bot_kv.cpp$(ObjectSuffix): bot_kv.cpp $(IntermediateDirectory)/bot_kv.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_kv.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_kv.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_kv.cpp$(DependSuffix): bot_kv.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_kv.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_kv.cpp$(DependSuffix) -MM bot_kv.cpp - -$(IntermediateDirectory)/bot_kv.cpp$(PreprocessSuffix): bot_kv.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_kv.cpp$(PreprocessSuffix) bot_kv.cpp - -$(IntermediateDirectory)/bot_menu.cpp$(ObjectSuffix): bot_menu.cpp $(IntermediateDirectory)/bot_menu.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_menu.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_menu.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_menu.cpp$(DependSuffix): bot_menu.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_menu.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_menu.cpp$(DependSuffix) -MM bot_menu.cpp - -$(IntermediateDirectory)/bot_menu.cpp$(PreprocessSuffix): bot_menu.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_menu.cpp$(PreprocessSuffix) bot_menu.cpp - -$(IntermediateDirectory)/bot_mods.cpp$(ObjectSuffix): bot_mods.cpp $(IntermediateDirectory)/bot_mods.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_mods.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_mods.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_mods.cpp$(DependSuffix): bot_mods.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_mods.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_mods.cpp$(DependSuffix) -MM bot_mods.cpp - -$(IntermediateDirectory)/bot_mods.cpp$(PreprocessSuffix): bot_mods.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_mods.cpp$(PreprocessSuffix) bot_mods.cpp - -$(IntermediateDirectory)/bot_mtrand.cpp$(ObjectSuffix): bot_mtrand.cpp $(IntermediateDirectory)/bot_mtrand.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_mtrand.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_mtrand.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_mtrand.cpp$(DependSuffix): bot_mtrand.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_mtrand.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_mtrand.cpp$(DependSuffix) -MM bot_mtrand.cpp - -$(IntermediateDirectory)/bot_mtrand.cpp$(PreprocessSuffix): bot_mtrand.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_mtrand.cpp$(PreprocessSuffix) bot_mtrand.cpp - -$(IntermediateDirectory)/bot_navmesh.cpp$(ObjectSuffix): bot_navmesh.cpp $(IntermediateDirectory)/bot_navmesh.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_navmesh.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_navmesh.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_navmesh.cpp$(DependSuffix): bot_navmesh.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_navmesh.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_navmesh.cpp$(DependSuffix) -MM bot_navmesh.cpp - -$(IntermediateDirectory)/bot_navmesh.cpp$(PreprocessSuffix): bot_navmesh.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_navmesh.cpp$(PreprocessSuffix) bot_navmesh.cpp - -$(IntermediateDirectory)/bot_perceptron.cpp$(ObjectSuffix): bot_perceptron.cpp $(IntermediateDirectory)/bot_perceptron.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_perceptron.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_perceptron.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_perceptron.cpp$(DependSuffix): bot_perceptron.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_perceptron.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_perceptron.cpp$(DependSuffix) -MM bot_perceptron.cpp - -$(IntermediateDirectory)/bot_perceptron.cpp$(PreprocessSuffix): bot_perceptron.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_perceptron.cpp$(PreprocessSuffix) bot_perceptron.cpp - -$(IntermediateDirectory)/bot_profile.cpp$(ObjectSuffix): bot_profile.cpp $(IntermediateDirectory)/bot_profile.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_profile.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_profile.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_profile.cpp$(DependSuffix): bot_profile.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_profile.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_profile.cpp$(DependSuffix) -MM bot_profile.cpp - -$(IntermediateDirectory)/bot_profile.cpp$(PreprocessSuffix): bot_profile.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_profile.cpp$(PreprocessSuffix) bot_profile.cpp - -$(IntermediateDirectory)/bot_profiling.cpp$(ObjectSuffix): bot_profiling.cpp $(IntermediateDirectory)/bot_profiling.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_profiling.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_profiling.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_profiling.cpp$(DependSuffix): bot_profiling.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_profiling.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_profiling.cpp$(DependSuffix) -MM bot_profiling.cpp - -$(IntermediateDirectory)/bot_profiling.cpp$(PreprocessSuffix): bot_profiling.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_profiling.cpp$(PreprocessSuffix) bot_profiling.cpp - -$(IntermediateDirectory)/bot_schedule.cpp$(ObjectSuffix): bot_schedule.cpp $(IntermediateDirectory)/bot_schedule.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_schedule.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_schedule.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_schedule.cpp$(DependSuffix): bot_schedule.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_schedule.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_schedule.cpp$(DependSuffix) -MM bot_schedule.cpp - -$(IntermediateDirectory)/bot_schedule.cpp$(PreprocessSuffix): bot_schedule.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_schedule.cpp$(PreprocessSuffix) bot_schedule.cpp - -$(IntermediateDirectory)/bot_som.cpp$(ObjectSuffix): bot_som.cpp $(IntermediateDirectory)/bot_som.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_som.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_som.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_som.cpp$(DependSuffix): bot_som.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_som.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_som.cpp$(DependSuffix) -MM bot_som.cpp - -$(IntermediateDirectory)/bot_som.cpp$(PreprocessSuffix): bot_som.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_som.cpp$(PreprocessSuffix) bot_som.cpp - -$(IntermediateDirectory)/bot_squads.cpp$(ObjectSuffix): bot_squads.cpp $(IntermediateDirectory)/bot_squads.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_squads.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_squads.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_squads.cpp$(DependSuffix): bot_squads.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_squads.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_squads.cpp$(DependSuffix) -MM bot_squads.cpp - -$(IntermediateDirectory)/bot_squads.cpp$(PreprocessSuffix): bot_squads.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_squads.cpp$(PreprocessSuffix) bot_squads.cpp - -$(IntermediateDirectory)/bot_strings.cpp$(ObjectSuffix): bot_strings.cpp $(IntermediateDirectory)/bot_strings.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_strings.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_strings.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_strings.cpp$(DependSuffix): bot_strings.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_strings.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_strings.cpp$(DependSuffix) -MM bot_strings.cpp - -$(IntermediateDirectory)/bot_strings.cpp$(PreprocessSuffix): bot_strings.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_strings.cpp$(PreprocessSuffix) bot_strings.cpp - -$(IntermediateDirectory)/bot_task.cpp$(ObjectSuffix): bot_task.cpp $(IntermediateDirectory)/bot_task.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_task.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_task.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_task.cpp$(DependSuffix): bot_task.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_task.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_task.cpp$(DependSuffix) -MM bot_task.cpp - -$(IntermediateDirectory)/bot_task.cpp$(PreprocessSuffix): bot_task.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_task.cpp$(PreprocessSuffix) bot_task.cpp - -$(IntermediateDirectory)/bot_tf2_mod.cpp$(ObjectSuffix): bot_tf2_mod.cpp $(IntermediateDirectory)/bot_tf2_mod.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_tf2_mod.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_tf2_mod.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_tf2_mod.cpp$(DependSuffix): bot_tf2_mod.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_tf2_mod.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_tf2_mod.cpp$(DependSuffix) -MM bot_tf2_mod.cpp - -$(IntermediateDirectory)/bot_tf2_mod.cpp$(PreprocessSuffix): bot_tf2_mod.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_tf2_mod.cpp$(PreprocessSuffix) bot_tf2_mod.cpp - -$(IntermediateDirectory)/bot_tf2_points.cpp$(ObjectSuffix): bot_tf2_points.cpp $(IntermediateDirectory)/bot_tf2_points.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_tf2_points.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_tf2_points.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_tf2_points.cpp$(DependSuffix): bot_tf2_points.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_tf2_points.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_tf2_points.cpp$(DependSuffix) -MM bot_tf2_points.cpp - -$(IntermediateDirectory)/bot_tf2_points.cpp$(PreprocessSuffix): bot_tf2_points.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_tf2_points.cpp$(PreprocessSuffix) bot_tf2_points.cpp - -$(IntermediateDirectory)/bot_usercmd.cpp$(ObjectSuffix): bot_usercmd.cpp $(IntermediateDirectory)/bot_usercmd.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_usercmd.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_usercmd.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_usercmd.cpp$(DependSuffix): bot_usercmd.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_usercmd.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_usercmd.cpp$(DependSuffix) -MM bot_usercmd.cpp - -$(IntermediateDirectory)/bot_usercmd.cpp$(PreprocessSuffix): bot_usercmd.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_usercmd.cpp$(PreprocessSuffix) bot_usercmd.cpp - -$(IntermediateDirectory)/bot_utility.cpp$(ObjectSuffix): bot_utility.cpp $(IntermediateDirectory)/bot_utility.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_utility.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_utility.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_utility.cpp$(DependSuffix): bot_utility.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_utility.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_utility.cpp$(DependSuffix) -MM bot_utility.cpp - -$(IntermediateDirectory)/bot_utility.cpp$(PreprocessSuffix): bot_utility.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_utility.cpp$(PreprocessSuffix) bot_utility.cpp - -$(IntermediateDirectory)/bot_visibles.cpp$(ObjectSuffix): bot_visibles.cpp $(IntermediateDirectory)/bot_visibles.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_visibles.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_visibles.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_visibles.cpp$(DependSuffix): bot_visibles.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_visibles.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_visibles.cpp$(DependSuffix) -MM bot_visibles.cpp - -$(IntermediateDirectory)/bot_visibles.cpp$(PreprocessSuffix): bot_visibles.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_visibles.cpp$(PreprocessSuffix) bot_visibles.cpp - -$(IntermediateDirectory)/bot_waypoint.cpp$(ObjectSuffix): bot_waypoint.cpp $(IntermediateDirectory)/bot_waypoint.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_waypoint.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_waypoint.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_waypoint.cpp$(DependSuffix): bot_waypoint.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_waypoint.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_waypoint.cpp$(DependSuffix) -MM bot_waypoint.cpp - -$(IntermediateDirectory)/bot_waypoint.cpp$(PreprocessSuffix): bot_waypoint.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_waypoint.cpp$(PreprocessSuffix) bot_waypoint.cpp - -$(IntermediateDirectory)/bot_waypoint_locations.cpp$(ObjectSuffix): bot_waypoint_locations.cpp $(IntermediateDirectory)/bot_waypoint_locations.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_waypoint_locations.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_waypoint_locations.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_waypoint_locations.cpp$(DependSuffix): bot_waypoint_locations.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_waypoint_locations.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_waypoint_locations.cpp$(DependSuffix) -MM bot_waypoint_locations.cpp - -$(IntermediateDirectory)/bot_waypoint_locations.cpp$(PreprocessSuffix): bot_waypoint_locations.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_waypoint_locations.cpp$(PreprocessSuffix) bot_waypoint_locations.cpp - -$(IntermediateDirectory)/bot_waypoint_visibility.cpp$(ObjectSuffix): bot_waypoint_visibility.cpp $(IntermediateDirectory)/bot_waypoint_visibility.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_waypoint_visibility.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_waypoint_visibility.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_waypoint_visibility.cpp$(DependSuffix): bot_waypoint_visibility.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_waypoint_visibility.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_waypoint_visibility.cpp$(DependSuffix) -MM bot_waypoint_visibility.cpp - -$(IntermediateDirectory)/bot_waypoint_visibility.cpp$(PreprocessSuffix): bot_waypoint_visibility.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_waypoint_visibility.cpp$(PreprocessSuffix) bot_waypoint_visibility.cpp - -$(IntermediateDirectory)/bot_weapons.cpp$(ObjectSuffix): bot_weapons.cpp $(IntermediateDirectory)/bot_weapons.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_weapons.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_weapons.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_weapons.cpp$(DependSuffix): bot_weapons.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_weapons.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_weapons.cpp$(DependSuffix) -MM bot_weapons.cpp - -$(IntermediateDirectory)/bot_weapons.cpp$(PreprocessSuffix): bot_weapons.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_weapons.cpp$(PreprocessSuffix) bot_weapons.cpp - -$(IntermediateDirectory)/bot_wpt_dist.cpp$(ObjectSuffix): bot_wpt_dist.cpp $(IntermediateDirectory)/bot_wpt_dist.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_wpt_dist.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_wpt_dist.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_wpt_dist.cpp$(DependSuffix): bot_wpt_dist.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_wpt_dist.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_wpt_dist.cpp$(DependSuffix) -MM bot_wpt_dist.cpp - -$(IntermediateDirectory)/bot_wpt_dist.cpp$(PreprocessSuffix): bot_wpt_dist.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_wpt_dist.cpp$(PreprocessSuffix) bot_wpt_dist.cpp - -$(IntermediateDirectory)/bot_zombie.cpp$(ObjectSuffix): bot_zombie.cpp $(IntermediateDirectory)/bot_zombie.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_zombie.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_zombie.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_zombie.cpp$(DependSuffix): bot_zombie.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_zombie.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_zombie.cpp$(DependSuffix) -MM bot_zombie.cpp - -$(IntermediateDirectory)/bot_zombie.cpp$(PreprocessSuffix): bot_zombie.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_zombie.cpp$(PreprocessSuffix) bot_zombie.cpp - -$(IntermediateDirectory)/bot_sigscan.cpp$(ObjectSuffix): bot_sigscan.cpp $(IntermediateDirectory)/bot_sigscan.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_sigscan.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_sigscan.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_sigscan.cpp$(DependSuffix): bot_sigscan.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_sigscan.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_sigscan.cpp$(DependSuffix) -MM bot_sigscan.cpp - -$(IntermediateDirectory)/bot_sigscan.cpp$(PreprocessSuffix): bot_sigscan.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_sigscan.cpp$(PreprocessSuffix) bot_sigscan.cpp - -$(IntermediateDirectory)/bot_cvars.cpp$(ObjectSuffix): bot_cvars.cpp $(IntermediateDirectory)/bot_cvars.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_cvars.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_cvars.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_cvars.cpp$(DependSuffix): bot_cvars.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_cvars.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_cvars.cpp$(DependSuffix) -MM bot_cvars.cpp - -$(IntermediateDirectory)/bot_cvars.cpp$(PreprocessSuffix): bot_cvars.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_cvars.cpp$(PreprocessSuffix) bot_cvars.cpp - -$(IntermediateDirectory)/bot_plugin_meta.cpp$(ObjectSuffix): bot_plugin_meta.cpp $(IntermediateDirectory)/bot_plugin_meta.cpp$(DependSuffix) - $(CXX) $(IncludePCH) $(SourceSwitch) "/home/mint/Dropbox/src/rcbot2/utils/RCBot2_meta/bot_plugin_meta.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/bot_plugin_meta.cpp$(ObjectSuffix) $(IncludePath) -$(IntermediateDirectory)/bot_plugin_meta.cpp$(DependSuffix): bot_plugin_meta.cpp - @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/bot_plugin_meta.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/bot_plugin_meta.cpp$(DependSuffix) -MM bot_plugin_meta.cpp - -$(IntermediateDirectory)/bot_plugin_meta.cpp$(PreprocessSuffix): bot_plugin_meta.cpp - $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/bot_plugin_meta.cpp$(PreprocessSuffix) bot_plugin_meta.cpp - - --include $(IntermediateDirectory)/*$(DependSuffix) -## -## Clean -## -clean: - $(RM) -r $(VS_Configuration)/ - - diff --git a/utils/RCBot2_meta/bot.cpp b/utils/RCBot2_meta/bot.cpp index 9649b6d09..6ec74e022 100644 --- a/utils/RCBot2_meta/bot.cpp +++ b/utils/RCBot2_meta/bot.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * part of https://rcbot2.svn.sourceforge.net/svnroot/rcbot2 * @@ -36,39 +38,31 @@ // //============================================================================// -#include -#include +#include +#include +#include -//#define GAME_DLL - -//#include "cbase.h" #include "mathlib.h" #include "vector.h" -#include "vplane.h" #include "eiface.h" + #ifdef __linux__ #include "shareddefs.h" //bir3yk #endif -#include "usercmd.h" -#include "bitbuf.h" + #include "in_buttons.h" #include "ndebugoverlay.h" -#include "tier0/threadtools.h" // for critical sections -#include "vstdlib/vstdlib.h" -#include "vstdlib/random.h" // for random functions -#include "iservernetworkable.h" // may come in handy + #ifdef __linux__ #include "shake.h" //bir3yk #endif -//#include "cbase.h" -//#include "basehlcombatweapon.h" -//#include "basecombatcharacter.h" - #include "bot.h" +#include "bot_cvars.h" #include "bot_schedule.h" #include "bot_buttons.h" #include "bot_navigator.h" +//#include "bot_black_mesa.h" #include "bot_css_bot.h" #include "bot_coop.h" #include "bot_zombie.h" @@ -76,12 +70,8 @@ #include "bot_hldm_bot.h" #include "bot_hl1dmsrc_bot.h" #include "bot_fortress.h" +#include "bot_synergy.h" #include "bot_visibles.h" -//#include "bot_memory.h" -//#include "bot_ga.h" -//#include "bot_ga_ind.h" -//#include "bot_perceptron.h" -#include "bot_ga_nn_const.h" #include "bot_weapons.h" #include "bot_profile.h" #include "bot_waypoint_locations.h" @@ -89,33 +79,33 @@ #include "bot_squads.h" #include "bot_mtrand.h" -//#include "vstdlib/random.h" // for random functions #include "bot_getprop.h" #include "bot_profiling.h" -#define DEG_TO_RAD(x) (x)*0.0174533 -#define RAD_TO_DEG(x) (x)*57.29578 +#include "rcbot/logging.h" -// for critical sections -CThreadMutex g_MutexAddBot; -CThreadMutex g_MutexBotThink; +#include +#include +#include + +//caxanga334: SDK 2013 contains macros for std::min and std::max which causes errors when compiling +//#if SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_BMS +#include "valve_minmax_off.h" +//#endif + +constexpr float DEG_TO_RAD(const float x) { return x * 0.0174533f; } +constexpr float RAD_TO_DEG(const float x) { return x * 57.29578f; } //extern void HookPlayerRunCommand ( edict_t *edict ); // instantiate bots -- make different for different mods -CBot **CBots::m_Bots = NULL; +CBot **CBots::m_Bots = nullptr; const float CBot :: m_fAttackLowestHoldTime = 0.1f; const float CBot :: m_fAttackHighestHoldTime = 0.6f; const float CBot :: m_fAttackLowestLetGoTime = 0.1f; const float CBot :: m_fAttackHighestLetGoTime = 0.5f; -bool CBots :: m_bControlBotsOnly = false; -bool CBots :: m_bControlNext = false; -queue CBots::m_AddBotQueue; -CBotProfile *CBots :: m_pNextProfile = NULL; -queue CBots :: m_ControlQueue; -char CBots :: m_szNextName[64]; int CBots :: m_iMaxBots = -1; int CBots :: m_iMinBots = -1; @@ -126,8 +116,6 @@ float CBots :: m_flAddKickBotTime = 0; #define TIME_TO_TICKS( dt ) ( (int)( 0.5f + (float)(dt) / TICK_INTERVAL ) ) extern IVDebugOverlay *debugoverlay; -extern ConVar bot_use_vc_commands; -extern ConVar rcbot_dont_move; const char *g_szLookTaskToString[LOOK_MAX] = { @@ -150,29 +138,29 @@ const char *g_szLookTaskToString[LOOK_MAX] = // Borrowed from RCBot1 bool BotFunc_BreakableIsEnemy ( edict_t *pBreakable, edict_t *pEdict ) { - int flags = CClassInterface::getPlayerFlags(pBreakable); + const int flags = CClassInterface::getPlayerFlags(pBreakable); // i. explosives required to blow breakable // ii. OR is not a world brush (non breakable) and can be broken by shooting if ( !(flags & FL_WORLDBRUSH) ) { - Vector vSize = pBreakable->GetCollideable()->OBBMaxs() - pBreakable->GetCollideable()->OBBMins(); - Vector vMySize = pEdict->GetCollideable()->OBBMaxs() - pEdict->GetCollideable()->OBBMins(); + const Vector vSize = pBreakable->GetCollideable()->OBBMaxs() - pBreakable->GetCollideable()->OBBMins(); + const Vector vMySize = pEdict->GetCollideable()->OBBMaxs() - pEdict->GetCollideable()->OBBMins(); - if ( (vSize.x >= vMySize.x) || - (vSize.y >= vMySize.y) || - (vSize.z >= (vMySize.z/2)) ) // this breakable could block my path + if ( vSize.x >= vMySize.x || + vSize.y >= vMySize.y || + vSize.z >= vMySize.z/2 ) // this breakable could block my path { // 00000000001111111111222222222233333333334 // 01234567890123456789012345678901234567890 // models/props_c17/oildrum001_explosive.mdl const char *model = pBreakable->GetIServerEntity()->GetModelName().ToCStr(); - if ( (model[13] == 'c') && (model[17] == 'o') && (model[20] == 'd') && (model[28]== 'e') ) // explosive + if ( model[13] == 'c' && model[17] == 'o' && model[20] == 'd' && model[28]== 'e' ) // explosive return false; // Only shoot breakables that are bigger than me (crouch size) // or that target something... - return ( CClassInterface::getPlayerHealth(pBreakable)<1000 ); // breakable still visible (not broken yet) + return CClassInterface::getPlayerHealth(pBreakable)<1000; // breakable still visible (not broken yet) } } @@ -193,25 +181,22 @@ void CBroadcastVoiceCommand :: execute ( CBot *pBot ) if ( pBot->isEnemy(m_pPlayer,false) ) { // listen to enemy voice commands if they are nearby - if ( pBot->wantToListen() && pBot->wantToListenToPlayerAttack(m_pPlayer) && (pBot->distanceFrom(m_pPlayer) < CWaypointLocations::REACHABLE_RANGE) ) + if ( pBot->wantToListen() && pBot->wantToListenToPlayerAttack(m_pPlayer) && pBot->distanceFrom(m_pPlayer) < CWaypointLocations::REACHABLE_RANGE ) pBot->listenToPlayer(m_pPlayer,true,false); } else pBot->hearVoiceCommand(m_pPlayer,m_VoiceCmd); } /////////////////////////////////////// -void CBot :: runPlayerMove() +void CBot::runPlayerMove() { - extern ConVar rcbot_move_forward; - extern ConVar bot_attack; - - int cmdnumbr = cmd.command_number+1; + const int cmdnumbr = cmd.command_number + 1; ////////////////////////////////// - Q_memset( &cmd, 0, sizeof( cmd ) ); + Q_memset(&cmd, 0, sizeof cmd); ////////////////////////////////// - if ( rcbot_dont_move.GetBool() ) + if (rcbot_dont_move.GetBool()) { cmd.forwardmove = 0; cmd.sidemove = 0; @@ -230,25 +215,27 @@ void CBot :: runPlayerMove() cmd.tick_count = gpGlobals->tickcount; cmd.command_number = cmdnumbr; - if ( bot_attack.GetInt() == 1 ) + if (bot_attack.GetInt() == 1) { cmd.buttons = IN_ATTACK; + } m_iSelectWeapon = 0; m_iImpulse = 0; - if ( CClients::clientsDebugging(BOT_DEBUG_BUTTONS) ) + if (CClients::clientsDebugging(BOT_DEBUG_BUTTONS)) { - char dbg[512]; + char dbg[512]; - sprintf(dbg,"m_pButtons = %d/%x, Weapon Select = %d, impulse = %d",cmd.buttons,cmd.buttons,cmd.weaponselect,cmd.impulse); + snprintf(dbg, sizeof(dbg), "m_pButtons = %d/%x, Weapon Select = %d, impulse = %d", cmd.buttons, cmd.buttons, cmd.weaponselect, cmd.impulse); - CClients::clientDebugMsg(BOT_DEBUG_BUTTONS,dbg,this); + CClients::clientDebugMsg(BOT_DEBUG_BUTTONS, dbg, this); } - // Controlling will be done in the PlayerRunCommand hook if controlling puppet bots - // see bot_main.cpp - if ( !CBots::controlBots() ) - m_pController->RunPlayerMove(&cmd); +#ifndef OVERRIDE_RUNCMD + // Controlling will be done in the RCBotPluginMeta::Hook_PlayerRunCmd hook if controlling puppet bots + // see bot_plugin_meta.cpp + m_pController->RunPlayerMove(&cmd); +#endif } bool CBot :: startGame () @@ -273,9 +260,22 @@ bool CBot :: walkingTowardsWaypoint ( CWaypoint *pWaypoint, bool *bOffsetApplied removeCondition(CONDITION_LIFT); } + /* //TODO: Add bot condition when on ladders? [APG]RoboCop[CL] + if (pWaypoint->hasFlag(CWaypointTypes::W_FL_LADDER)) + { + if (onLadder()) + { + updateCondition(CONDITION_LADDER); + } + else + { + removeCondition(CONDITION_LADDER); + } + }*/ + if ( !*bOffsetApplied ) { - float fRadius = pWaypoint->getRadius(); + const float fRadius = pWaypoint->getRadius(); if ( fRadius > 0 ) vOffset = Vector(randomFloat(-fRadius,fRadius),randomFloat(-fRadius,fRadius),0); @@ -295,7 +295,7 @@ bool CBot :: walkingTowardsWaypoint ( CWaypoint *pWaypoint, bool *bOffsetApplied return false; } -void CBot :: setEdict ( edict_t *pEdict) +void CBot :: setEdict (edict_t *pEdict) { m_pEdict = pEdict; m_bUsed = true; @@ -305,7 +305,7 @@ void CBot :: setEdict ( edict_t *pEdict) { m_pPlayerInfo = playerinfomanager->GetPlayerInfo(m_pEdict); m_pController = g_pBotManager->GetBotController(m_pEdict); - strncpy(m_szBotName,m_pPlayerInfo->GetName(),63); + std::strncpy(m_szBotName,m_pPlayerInfo->GetName(),63); m_szBotName[63]=0; } else @@ -316,7 +316,7 @@ void CBot :: setEdict ( edict_t *pEdict) spawnInit(); } -bool CBot :: isUnderWater () +bool CBot :: isUnderWater () const //Needs to be const to prevent losing mobility? [APG]RoboCop[CL] { return CClassInterface::getWaterLevel(m_pEdict) > 1; //m_pController->IsEFlagSet(EFL_TOUCHING_FLUID); } @@ -335,15 +335,20 @@ bool CBot :: createBotFromEdict(edict_t *pEdict, CBotProfile *pProfile) m_pProfile = pProfile; - CBotGlobals::botMessage(NULL, 0, "==================================="); - CBotGlobals::botMessage(NULL, 0, "Creating Bot: %s", m_pProfile->m_szName); - CBotGlobals::botMessage(NULL, 0, "AimSkill: %f", m_pProfile->m_fAimSkill); - CBotGlobals::botMessage(NULL, 0, "Braveness: %f", m_pProfile->m_fBraveness); - CBotGlobals::botMessage(NULL, 0, "PathTicks: %d", m_pProfile->m_iPathTicks); - CBotGlobals::botMessage(NULL, 0, "Sensitivity: %d", m_pProfile->m_iSensitivity); - CBotGlobals::botMessage(NULL, 0, "VisionTicks: %d", m_pProfile->m_iVisionTicks); - CBotGlobals::botMessage(NULL, 0, "VisionTicksClients: %d", m_pProfile->m_iVisionTicksClients); - CBotGlobals::botMessage(NULL, 0, "==================================="); + if (!pEdict || !pProfile) { + logger->Log(LogLevel::ERROR, "Invalid edict or profile"); + return false; + } + + logger->Log(LogLevel::TRACE, "==================================="); + logger->Log(LogLevel::TRACE, "Creating Bot: %s", m_pProfile->m_szName); + logger->Log(LogLevel::TRACE, "AimSkill: %f", m_pProfile->m_fAimSkill); + logger->Log(LogLevel::TRACE, "Braveness: %f", m_pProfile->m_fBraveness); + logger->Log(LogLevel::TRACE, "PathTicks: %d", m_pProfile->m_iPathTicks); + logger->Log(LogLevel::TRACE, "Sensitivity: %d", m_pProfile->m_iSensitivity); + logger->Log(LogLevel::TRACE, "VisionTicks: %d", m_pProfile->m_iVisionTicks); + logger->Log(LogLevel::TRACE, "VisionTicksClients: %d", m_pProfile->m_iVisionTicksClients); + logger->Log(LogLevel::TRACE, "==================================="); engine->SetFakeClientConVarValue(pEdict,"cl_team","default"); engine->SetFakeClientConVarValue(pEdict,"cl_defaultweapon","pistol"); @@ -351,28 +356,28 @@ bool CBot :: createBotFromEdict(edict_t *pEdict, CBotProfile *pProfile) engine->SetFakeClientConVarValue(pEdict,"tf_medigun_autoheal","0"); // joining name not the same as the profile name, change name - if (strcmp(m_szBotName,pProfile->m_szName) ) + if (std::strcmp(m_szBotName,pProfile->m_szName) != 0) { engine->SetFakeClientConVarValue(pEdict,"name",pProfile->m_szName); - strcpy(m_szBotName,pProfile->m_szName); + std::strcpy(m_szBotName,pProfile->m_szName); } - if ( m_pPlayerInfo && (pProfile->m_iTeam != -1) ) + if ( m_pPlayerInfo && pProfile->m_iTeam != -1 ) m_pPlayerInfo->ChangeTeam(pProfile->m_iTeam); ///////////////////////////// // safe copy - strncpy(szModel,pProfile->m_szModel,127); + std::strncpy(szModel,pProfile->m_szModel,127); szModel[127] = 0; if ( FStrEq(szModel,"default") ) { - int iModel = randomInt(1,7); + const int iModel = randomInt(1,7); if ( randomInt(0,1) ) - sprintf(szModel,"models/humans/Group03/Male_0%d.mdl",iModel); + snprintf(szModel, sizeof(szModel), "models/humans/Group03/Male_0%d.mdl", iModel); else - sprintf(szModel,"models/humans/Group03/female_0%d.mdl",iModel); + snprintf(szModel, sizeof(szModel), "models/humans/Group03/female_0%d.mdl", iModel); } m_iDesiredTeam = pProfile->m_iTeam; @@ -380,12 +385,41 @@ bool CBot :: createBotFromEdict(edict_t *pEdict, CBotProfile *pProfile) engine->SetFakeClientConVarValue(pEdict,"cl_playermodel",szModel); engine->SetFakeClientConVarValue(pEdict,"hud_fastswitch","1"); + + #if SOURCE_ENGINE == SE_TF2 + helpers->ClientCommand(pEdict, "jointeam auto"); + + //"heavy" should be "heavyweapons" in TF2? + // + //the class names should be changed to the slot names [APG]RoboCop[CL] + + //char classNames[32][10] = { + //"auto", "scout", "soldier", "pyro", "demoman", "heavy", "medic", + //"engineer", "sniper", "spy", + //}; + + char command[32]; + + //TODO: To reduce any instability issues that could cause crashes [APG]RoboCop[CL] + if (m_iDesiredClass >= 0 && static_cast(m_iDesiredClass) < 10) { + char classNames[10][10] = { + "auto", "scout", "sniper", "soldier", "demoman", "medic", "heavy", + "pyro", "spy", "engineer" + }; + snprintf(command, sizeof(command), "joinclass %s", classNames[m_iDesiredClass]); + } + else { + snprintf(command, sizeof(command), "joinclass auto"); + } + + helpers->ClientCommand(pEdict, command); + #endif ///////////////////////////// return true; } -bool CBot :: FVisible ( Vector &vOrigin, edict_t *pDest ) +bool CBot :: FVisible (const Vector &vOrigin, edict_t *pDest) const { //return CBotGlobals::isVisible(m_pEdict,getEyePosition(),vOrigin); // fix bots seeing through gates/doors @@ -393,20 +427,17 @@ bool CBot :: FVisible ( Vector &vOrigin, edict_t *pDest ) } -bool CBot :: FVisible ( edict_t *pEdict, bool bCheckHead ) +bool CBot :: FVisible ( edict_t *pEdict, const bool bCheckHead ) { static Vector eye; // use special hit traceline for players so bots dont shoot through things // For players -- do two tracelines -- one at the origin and one at the head (for headshots) - if ( bCheckHead || (pEdict == m_pEnemy) || CBotGlobals::isPlayer(pEdict) ) + if ( bCheckHead || pEdict == m_pEnemy || CBotGlobals::isPlayer(pEdict) ) { - Vector vOrigin; - Vector vHead; - // use this method to get origin -- quicker - vOrigin = pEdict->GetCollideable()->GetCollisionOrigin(); - vHead = vOrigin+Vector(0,0,pEdict->GetCollideable()->OBBMaxs().z); + const Vector vOrigin = pEdict->GetCollideable()->GetCollisionOrigin(); + const Vector vHead = vOrigin + Vector(0, 0, pEdict->GetCollideable()->OBBMaxs().z); if ( FVisible(vHead,pEdict) ) { @@ -441,11 +472,8 @@ bool CBot :: FVisible ( edict_t *pEdict, bool bCheckHead ) updateCondition(CONDITION_SEE_ENEMY_GROUND); return true; } - else - { - removeCondition(CONDITION_SEE_ENEMY_GROUND); - return false; - } + removeCondition(CONDITION_SEE_ENEMY_GROUND); + return false; } return FVisible(vOrigin,pEdict); @@ -457,14 +485,13 @@ bool CBot :: FVisible ( edict_t *pEdict, bool bCheckHead ) return CBotGlobals::isVisible(m_pEdict,eye,pEdict);//CBotGlobals::entityOrigin(pEdict)+Vector(0,0,50.0f)); } -inline QAngle CBot :: eyeAngles () +inline QAngle CBot :: eyeAngles () const { return CBotGlobals::playerAngles(m_pEdict); } -Vector CBot :: getEyePosition () +Vector CBot :: getEyePosition () const { - Vector vOrigin;//'/ = getOrigin(); //vOrigin.z = m_pPlayerInfo->GetPlayerMaxs().z; @@ -477,9 +504,6 @@ bool CBot :: checkStuck () { static float fTime; - float fSpeed; - float fIdealSpeed; - if ( !moveToIsValid() ) return false; if ( rcbot_dont_move.GetBool() ) // bots not moving @@ -489,7 +513,7 @@ bool CBot :: checkStuck () fTime = engine->Time(); - if ( m_fLastWaypointVisible == 0 ) + if ( m_fLastWaypointVisible == 0.0f ) { m_bFailNextMove = false; @@ -499,12 +523,12 @@ bool CBot :: checkStuck () else { if ( hasSomeConditions(CONDITION_SEE_WAYPOINT) ) - m_fLastWaypointVisible = 0; + m_fLastWaypointVisible = 0.0f; else { - if ( (m_fLastWaypointVisible + 2.0) < fTime ) + if ( m_fLastWaypointVisible + 2.0f < fTime ) { - m_fLastWaypointVisible = 0; + m_fLastWaypointVisible = 0.0f; m_bFailNextMove = true; return true; @@ -512,28 +536,28 @@ bool CBot :: checkStuck () } } - if ( m_fWaypointStuckTime && (m_fWaypointStuckTime < engine->Time()) ) + if (m_fWaypointStuckTime > 0.0f && m_fWaypointStuckTime < engine->Time()) { m_bFailNextMove = true; - m_fWaypointStuckTime = engine->Time() + randomFloat(15.0f,20.0f); + m_fWaypointStuckTime = engine->Time() + randomFloat(15.0f, 20.0f); } if ( m_fCheckStuckTime > fTime ) return m_bThinkStuck; - if ( hasSomeConditions(CONDITION_LIFT) || (onLadder() ))//fabs(m_vMoveTo.z - getOrigin().z) > 48 ) + if ( hasSomeConditions(CONDITION_LIFT) || onLadder())//fabs(m_vMoveTo.z - getOrigin().z) > 48 ) { if ( m_vVelocity.z != 0.0f ) return false; } - fSpeed = m_vVelocity.Length(); - fIdealSpeed = m_fIdealMoveSpeed; + const float fSpeed = m_vVelocity.Length(); + float fIdealSpeed = m_fIdealMoveSpeed; if ( m_pButtons->holdingButton(IN_DUCK) ) fIdealSpeed /= 2; - if ( fIdealSpeed == 0 ) + if ( fIdealSpeed == 0.0f ) { m_bThinkStuck = false; // not stuck m_fPercentMoved = 1.0f; @@ -541,7 +565,7 @@ bool CBot :: checkStuck () else { // alpha percentage check - m_fPercentMoved = (m_fPercentMoved/2) + ((fSpeed/fIdealSpeed)/2); + m_fPercentMoved = m_fPercentMoved/2 + fSpeed/fIdealSpeed/2; if ( m_fPercentMoved < 0.1f ) { @@ -604,7 +628,7 @@ bool CBot :: checkStuck () m_fSideSpeed = m_fIdealMoveSpeed/2; m_fStrafeTime = engine->Time() + 2.0f; -*/ + */ } @@ -618,18 +642,13 @@ bool CBot :: checkStuck () return m_bThinkStuck; } -bool CBot :: isVisible ( edict_t *pEdict ) +bool CBot :: isVisible (const edict_t *pEdict) const { return m_pVisibles->isVisible(pEdict); } bool CBot :: canAvoid ( edict_t *pEntity ) { - float distance; - Vector vAvoidOrigin; - - extern ConVar bot_avoid_radius; - if ( !CBotGlobals::entityIsValid(pEntity) ) return false; if ( m_pEdict == pEntity ) // can't avoid self!!! @@ -639,15 +658,15 @@ bool CBot :: canAvoid ( edict_t *pEntity ) if ( m_pLastEnemy == pEntity ) return false; - vAvoidOrigin = CBotGlobals::entityOrigin(pEntity); + const Vector vAvoidOrigin = CBotGlobals::entityOrigin(pEntity); - distance = distanceFrom(vAvoidOrigin); + const float distance = distanceFrom(vAvoidOrigin); - if ( ( distance > 1 ) && ( distance < bot_avoid_radius.GetFloat() ) && (fabs(getOrigin().z - vAvoidOrigin.z) < 32) ) + if ( distance > 1 && distance < bot_avoid_radius.GetFloat() && std::fabs(getOrigin().z - vAvoidOrigin.z) < 32 ) { - SolidType_t solid = pEntity->GetCollideable()->GetSolid() ; + const SolidType_t solid = pEntity->GetCollideable()->GetSolid() ; - if ( (solid == SOLID_BBOX) || (solid == SOLID_VPHYSICS) ) + if ( solid == SOLID_BBOX || solid == SOLID_VPHYSICS ) { return isEnemy(pEntity,false); } @@ -658,26 +677,26 @@ bool CBot :: canAvoid ( edict_t *pEntity ) void CBot :: reachedCoverSpot (int flags) { - + } // something now visiable or not visible anymore -bool CBot :: setVisible ( edict_t *pEntity, bool bVisible ) +bool CBot :: setVisible ( edict_t *pEntity, const bool bVisible ) { - bool bValid = CBotGlobals::entityIsValid(pEntity); + const bool bValid = CBotGlobals::entityIsValid(pEntity); if ( bValid && bVisible ) { if ( canAvoid(pEntity) ) { - if ( (m_pAvoidEntity.get()==NULL) || (distanceFrom(pEntity) < distanceFrom(m_pAvoidEntity)) ) + if ( m_pAvoidEntity.get()== nullptr || distanceFrom(pEntity) < distanceFrom(m_pAvoidEntity) ) m_pAvoidEntity = pEntity; } } else { if ( m_pAvoidEntity == pEntity ) - m_pAvoidEntity = NULL; + m_pAvoidEntity = nullptr; if ( m_pEnemy == pEntity ) { m_pLastEnemy = m_pEnemy; @@ -688,9 +707,9 @@ bool CBot :: setVisible ( edict_t *pEntity, bool bVisible ) return bValid; } -bool CBot :: isUsingProfile ( CBotProfile *pProfile ) +bool CBot :: isUsingProfile (const CBotProfile *pProfile) const { - return (m_pProfile == pProfile); + return m_pProfile == pProfile; } void CBot :: currentlyDead () @@ -705,8 +724,6 @@ void CBot :: currentlyDead () // keep updating until alive m_fSpawnTime = engine->Time(); - - return; } CBotWeapon *CBot::getCurrentWeapon() @@ -714,38 +731,28 @@ CBotWeapon *CBot::getCurrentWeapon() return m_pWeapons->getActiveWeapon(m_pPlayerInfo->GetWeaponName()); } -void CBot :: selectWeaponName ( const char *szWeapon ) -{ - m_pController->SetActiveWeapon(szWeapon); -} - -void CBot :: selectWeaponSlot ( int iSlot ) +void CBot :: selectWeaponName ( const char *szWeaponName ) const { - char cmd[16]; - - sprintf(cmd,"slot%d",iSlot); - - helpers->ClientCommand(m_pEdict,cmd); - //m_iSelectWeapon = iSlot; + m_pController->SetActiveWeapon(szWeaponName); } -CBotWeapon *CBot :: getBestWeapon (edict_t *pEnemy,bool bAllowMelee, bool bAllowMeleeFallback, bool bMeleeOnly, bool bExplosivesOnly ) +CBotWeapon *CBot :: getBestWeapon (edict_t *pEnemy, const bool bAllowMelee, const bool bAllowMeleeFallback, const bool bMeleeOnly, const bool bExplosivesOnly ) const { return m_pWeapons->getBestWeapon(pEnemy,bAllowMelee,bAllowMeleeFallback,bMeleeOnly,bExplosivesOnly); } -bool CBot::isHoldingPrimaryAttack() +bool CBot::isHoldingPrimaryAttack() const { return m_pButtons->holdingButton(IN_ATTACK); } -void CBot :: debugMsg ( int iLev, const char *szMsg ) +void CBot :: debugMsg (const int iLev, const char *szMsg) const { if ( CClients::clientsDebugging () ) { char szMsg2[512]; - sprintf(szMsg2,"(%s):%s",m_pPlayerInfo->GetName(),szMsg); + snprintf(szMsg2, sizeof(szMsg2), "(%s):%s", m_pPlayerInfo->GetName(), szMsg); CClients::clientDebugMsg (iLev,szMsg2,this); } @@ -761,7 +768,7 @@ void CBot::SquadInPosition () } } -void CBot :: kill () +void CBot :: kill () const { helpers->ClientCommand(m_pEdict,"kill\n"); } @@ -769,9 +776,6 @@ void CBot :: kill () void CBot :: think () { static float fTime; - extern ConVar rcbot_debug_iglev; - extern ConVar rcbot_debug_dont_shoot; - extern ConVar rcbot_debug_notasks; //static bool debug; //static bool battack; @@ -788,10 +792,10 @@ void CBot :: think () m_iMoveSpeedPriority = 0; // re-added - if ( !CBotGlobals::entityIsValid(m_pEdict) || m_pPlayerInfo == NULL ) + if ( !CBotGlobals::entityIsValid(m_pEdict) || m_pPlayerInfo == nullptr) { m_pPlayerInfo = playerinfomanager->GetPlayerInfo(m_pEdict); - CBotGlobals::botMessage(NULL,0,"%s : m_pPlayerInfo = NULL; Waiting for player info...",m_szBotName); + logger->Log(LogLevel::INFO, "%s : m_pPlayerInfo = NULL; Waiting for player info...", m_szBotName); return; } @@ -889,8 +893,6 @@ void CBot :: think () m_bWantToListen = true; m_bWantToChangeWeapon = true; - - // if ( !rcbot_debug_notasks.GetBool() ) { #ifdef _DEBUG @@ -915,7 +917,7 @@ void CBot :: think () if ( rcbot_debug_iglev.GetInt() != 6 ) { #endif - if ( m_bWantToListen && !hasEnemy() && !hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && (m_fWantToListenTimeTime()) ) + if ( m_bWantToListen && !hasEnemy() && !hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && m_fWantToListenTimeTime() ) { setMoveLookPriority(MOVELOOK_LISTEN); listenForPlayers(); @@ -924,7 +926,7 @@ void CBot :: think () else if ( hasEnemy() ) { // got an enemy -- reset - m_PlayerListeningTo = MyEHandle(NULL); + m_PlayerListeningTo = MyEHandle(nullptr); m_fLookSetTime = 0.0f; m_fListenTime = 0.0f; m_bListenPositionValid = false; @@ -944,7 +946,7 @@ void CBot :: think () m_vGoal = m_pNavigator->getGoalOrigin(); if ( m_pNavigator->hasNextPoint() ) - { + { m_pNavigator->updatePosition(); } else @@ -961,7 +963,7 @@ void CBot :: think () #endif // update m_pEnemy with findEnemy() m_pOldEnemy = m_pEnemy; - m_pEnemy = NULL; + m_pEnemy = nullptr; if ( m_pOldEnemy ) findEnemy(m_pOldEnemy); // any better enemies than this one? @@ -978,7 +980,7 @@ void CBot :: think () #endif if ( m_fUpdateOriginTime < fTime ) { - Vector vOrigin = getOrigin(); + const Vector vOrigin = getOrigin(); m_vVelocity = m_vLastOrigin-vOrigin; m_vLastOrigin = vOrigin; @@ -1036,16 +1038,16 @@ void CBot :: think () // deal with voice commands bot wants to say, // incase that he wants to use it in between frames (e.g. during an event call) // deal with it here - if ( (m_fNextVoiceCommand < engine->Time()) && !m_nextVoicecmd.empty() ) + if ( m_fNextVoiceCommand < engine->Time() && !m_nextVoicecmd.empty() ) { - byte cmd = m_nextVoicecmd.front(); + const byte voiceCmd = static_cast(m_nextVoicecmd.front()); m_fNextVoiceCommand = engine->Time() + randomFloat(0.4f,1.2f); - if ( m_fLastVoiceCommand[cmd] < engine->Time() ) + if ( m_fLastVoiceCommand[voiceCmd] < engine->Time() ) { - voiceCommand(cmd); - m_fLastVoiceCommand[cmd] = engine->Time() + randomFloat(8.0f,16.0f); + voiceCommand(voiceCmd); + m_fLastVoiceCommand[voiceCmd] = engine->Time() + randomFloat(8.0f,16.0f); } m_nextVoicecmd.pop(); @@ -1054,18 +1056,44 @@ void CBot :: think () m_iPrevHealth = m_pPlayerInfo->GetHealth(); m_bInitAlive = false; + + if (!m_pEnemy || m_pEnemy != m_pOldEnemy) + m_fEnemyAimLerp = 0.0f; + else + { + Vector vEnemyAimLerpVelocity; + CClassInterface::getVelocity(m_pEnemy.get(), &vEnemyAimLerpVelocity); + + const float fLerpTimeDelta = engine->Time() - m_fEnemyAimLerpTime; + + // Reset multiplier if enemy's velocity has changed drastically + constexpr float fMaxDifference = 600.0f; + const float fMaxDifferenceAdjusted = fMaxDifference * fLerpTimeDelta; + + m_fEnemyAimLerp = !vEnemyAimLerpVelocity.IsValid() || vEnemyAimLerpVelocity.Length() == 0.0f + || (std::fabs(vEnemyAimLerpVelocity.x - m_vEnemyAimLerpVelocity.x) + + std::fabs(vEnemyAimLerpVelocity.y - m_vEnemyAimLerpVelocity.y) + + std::fabs(vEnemyAimLerpVelocity.z - m_vEnemyAimLerpVelocity.z)) + * fLerpTimeDelta + > fMaxDifferenceAdjusted + ? 0.0f + : std::min(std::max(0.0f, m_fEnemyAimLerp + fLerpTimeDelta), 1.0f); + + m_vEnemyAimLerpVelocity = vEnemyAimLerpVelocity; + } + + m_fEnemyAimLerpTime = engine->Time(); } -void CBot :: addVoiceCommand ( int cmd ) +void CBot :: addVoiceCommand (const byte voiceCmd) { - if ( bot_use_vc_commands.GetBool() && (m_fLastVoiceCommand[cmd] < engine->Time()) ) + if ( bot_use_vc_commands.GetBool() && m_fLastVoiceCommand[voiceCmd] < engine->Time() ) { - m_nextVoicecmd.push(cmd); + m_nextVoicecmd.push(voiceCmd); m_fNextVoiceCommand = engine->Time() + randomFloat(0.2f,1.0f); } } - void CBot :: handleWeapons () { // @@ -1075,13 +1103,10 @@ void CBot :: handleWeapons () hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && wantToShoot() && isVisible(m_pEnemy) && isEnemy(m_pEnemy) ) { - CBotWeapon *pWeapon; + CBotWeapon* pWeapon = getBestWeapon(m_pEnemy); - pWeapon = getBestWeapon(m_pEnemy); - - if ( m_bWantToChangeWeapon && (pWeapon != NULL) && (pWeapon != getCurrentWeapon()) && pWeapon->getWeaponIndex() ) + if ( m_bWantToChangeWeapon && pWeapon != nullptr && pWeapon != getCurrentWeapon() && pWeapon->getWeaponIndex() ) { - //selectWeaponSlot(pWeapon->getWeaponInfo()->getSlot()); selectWeapon(pWeapon->getWeaponIndex()); } @@ -1089,8 +1114,8 @@ void CBot :: handleWeapons () if ( !handleAttack ( pWeapon, m_pEnemy ) ) { - m_pEnemy = NULL; - m_pOldEnemy = NULL; + m_pEnemy = nullptr; + m_pOldEnemy = nullptr; wantToShoot(false); } } @@ -1098,7 +1123,11 @@ void CBot :: handleWeapons () CBot :: CBot() { - init(true); + CBot::init(true); + m_iMovePriority = 0; + m_iLookPriority = 0; + m_iMoveSpeedPriority = 0; + m_iMoveLookPriority = 0; } /* * init() @@ -1106,30 +1135,30 @@ CBot :: CBot() * initialize all bot variables * (this is called when bot is made for the first time) */ -void CBot :: init (bool bVarInit) +void CBot :: init (const bool bVarInit) { //m_bNeedToInit = false; // doing this now m_fLastHurtTime = 0.0f; - m_iAmmo = NULL; - m_pButtons = NULL; - m_pNavigator = NULL; - m_pSchedules = NULL; - m_pVisibles = NULL; - m_pEdict = NULL; + m_iAmmo = nullptr; + m_pButtons = nullptr; + m_pNavigator = nullptr; + m_pSchedules = nullptr; + m_pVisibles = nullptr; + m_pEdict = nullptr; // m_pBaseEdict = NULL; - m_pFindEnemyFunc = NULL; + m_pFindEnemyFunc = nullptr; m_bUsed = false; - m_pController = NULL; - m_pPlayerInfo = NULL; + m_pController = nullptr; + m_pPlayerInfo = nullptr; - m_pWeapons = NULL; + m_pWeapons = nullptr; m_fTimeCreated = 0; - m_pProfile = NULL; + m_pProfile = nullptr; m_szBotName[0] = 0; m_fIdealMoveSpeed = 320; m_fFov = BOT_DEFAULT_FOV; m_bOpenFire = true; - m_pSquad = NULL; + m_pSquad = nullptr; cmd.command_number = 0; @@ -1137,24 +1166,24 @@ void CBot :: init (bool bVarInit) spawnInit(); } -edict_t *CBot :: getEdict () +edict_t *CBot :: getEdict () const { return m_pEdict; } -bool CBot :: isSquadLeader ( void ) +bool CBot :: isSquadLeader () const { - return (m_pSquad->GetLeader() == m_pEdict); + return m_pSquad->GetLeader() == m_pEdict; } void CBot :: updateConditions () { - if ( m_pEnemy.get() != NULL ) + if ( m_pEnemy.get() != nullptr) { if ( !CBotGlobals::entityIsAlive(m_pEnemy) ) { updateCondition(CONDITION_ENEMY_DEAD); - m_pEnemy = NULL; + m_pEnemy = nullptr; } else { @@ -1168,7 +1197,7 @@ void CBot :: updateConditions () } else { - if ( !m_pLastEnemy || (m_pLastEnemy != m_pEnemy )) + if ( !m_pLastEnemy || m_pLastEnemy != m_pEnemy) enemyLost(m_pEnemy); setLastEnemy(m_pEnemy); @@ -1203,8 +1232,6 @@ void CBot :: updateConditions () if ( CBotGlobals::entityIsValid(pLeader) && CBotGlobals::entityIsAlive(pLeader) ) { - extern ConVar rcbot_squad_idle_time; - removeCondition(CONDITION_SQUAD_LEADER_DEAD); if ( distanceFrom(pLeader) <= 400.0f ) @@ -1218,19 +1245,18 @@ void CBot :: updateConditions () removeCondition(CONDITION_SEE_SQUAD_LEADER); float fSpeed = 0.0f; - CClient *pClient = CClients::get(pLeader); - if ( pClient ) + if ( const CClient *pClient = CClients::get(pLeader) ) fSpeed = pClient->getSpeed(); // update squad idle condition. If squad is idle, bot can move around a small radius // around the leader and do what they want, e.g. defend or snipe - if ( (hasEnemy() || ((fSpeed > 10.0f) && ( CClassInterface::getMoveType(pLeader) != MOVETYPE_LADDER ))) ) + if (hasEnemy() || (fSpeed > 10.0f && CClassInterface::getMoveType(pLeader) != MOVETYPE_LADDER)) { setSquadIdleTime(engine->Time()); removeCondition(CONDITION_SQUAD_IDLE); } - else if ( (engine->Time() - m_fSquadIdleTime) > rcbot_squad_idle_time.GetFloat() ) + else if ( engine->Time() - m_fSquadIdleTime > rcbot_squad_idle_time.GetFloat() ) updateCondition(CONDITION_SQUAD_IDLE); } @@ -1268,29 +1294,26 @@ void CBot :: updateConditions () } // Called when working out route -bool CBot :: canGotoWaypoint ( Vector vPrevWaypoint, CWaypoint *pWaypoint, CWaypoint *pPrev ) +bool CBot::canGotoWaypoint(const Vector& vPrevWaypoint, CWaypoint* pWaypoint, CWaypoint* pPrev) { - if ( pWaypoint->hasFlag(CWaypointTypes::W_FL_UNREACHABLE) ) + if (pWaypoint->hasFlag(CWaypointTypes::W_FL_UNREACHABLE)) return false; - - if ( !pWaypoint->forTeam(getTeam()) ) + if (!pWaypoint->forTeam(getTeam())) return false; - - if ( pWaypoint->hasFlag(CWaypointTypes::W_FL_OPENS_LATER) ) + if (pWaypoint->hasFlag(CWaypointTypes::W_FL_OPENS_LATER)) { - if ( pPrev != NULL ) + if (pPrev != nullptr) { return pPrev->isPathOpened(pWaypoint->getOrigin()); } - else if ( (vPrevWaypoint != pWaypoint->getOrigin()) && !CBotGlobals::checkOpensLater(vPrevWaypoint,pWaypoint->getOrigin()) ) + if (vPrevWaypoint != pWaypoint->getOrigin() && !CBotGlobals::checkOpensLater(vPrevWaypoint, pWaypoint->getOrigin())) return false; } - - if ( pWaypoint->hasFlag(CWaypointTypes::W_FL_FALL) ) + if (pWaypoint->hasFlag(CWaypointTypes::W_FL_FALL)) { - if ( getHealthPercent() <= 0.1f ) + if (getHealthPercent() <= 0.1f) { - if ( (vPrevWaypoint.z - pWaypoint->getOrigin().z) > 200.0f ) + if (vPrevWaypoint.z - pWaypoint->getOrigin().z > 200.0f) return false; } } @@ -1298,7 +1321,7 @@ bool CBot :: canGotoWaypoint ( Vector vPrevWaypoint, CWaypoint *pWaypoint, CWayp return true; } -void CBot::updatePosition() +void CBot::updatePosition() const { m_pNavigator->rollBackPosition(); } @@ -1323,34 +1346,34 @@ bool CBot::handleAttack ( CBotWeapon *pWeapon, edict_t *pEnemy ) return true; } -int CBot :: getHealth () +int CBot :: getHealth () const { return m_pPlayerInfo->GetHealth(); } -float CBot :: getHealthPercent () +float CBot :: getHealthPercent () const { - return (((float)m_pPlayerInfo->GetHealth())/m_pPlayerInfo->GetMaxHealth()); + return static_cast(m_pPlayerInfo->GetHealth()) / static_cast(m_pPlayerInfo->GetMaxHealth()); } -bool CBot ::isOnLift() +bool CBot ::isOnLift() const { - return ((m_vVelocity.z < -8.0f)||(m_vVelocity.z >= 8.0f));//&&(CClassInterface::getFlags(m_pEdict) & FL_ONGROUND); + return m_vVelocity.z < -8.0f || m_vVelocity.z >= 8.0f;//&&(CClassInterface::getFlags(m_pEdict) & FL_ONGROUND); } edict_t *CBot :: getVisibleSpecial () { - return NULL; + return nullptr; } bool CBot::wantToInvestigateSound () { - return ((m_fSpawnTime + 10.0f) < engine->Time()) && !hasEnemy() && m_bWantToInvestigateSound; + return m_fSpawnTime + 10.0f < engine->Time() && !hasEnemy() && m_bWantToInvestigateSound; } -bool CBot :: recentlyHurt ( float fTime ) +bool CBot :: recentlyHurt (const float fTime) const { - return (m_fLastHurtTime>0) && (m_fLastHurtTime>(engine->Time()-fTime)); + return m_fLastHurtTime>0 && m_fLastHurtTime>engine->Time()-fTime; } void CBot :: spawnInit () @@ -1360,19 +1383,19 @@ void CBot :: spawnInit () m_fSpawnTime = engine->Time(); m_bIncreaseSensitivity = false; m_fLastSeeEnemyPlayer = 0.0f; - m_PlayerListeningTo = NULL; - m_pPrimaryWeapon = NULL; + m_PlayerListeningTo = nullptr; + m_pPrimaryWeapon = nullptr; m_uSquadDetail.dat = 0; m_bStatsCanUse = false; m_StatsCanUse.data = 0; m_Stats.data = 0; m_iStatsIndex = 0; - m_fStatsTime = 0; + m_fStatsTime = 0.0f; - m_fWantToListenTime = 0; + m_fWantToListenTime = 0.0f; resetTouchDistance(48.0f); - m_pLastCoverFrom = MyEHandle(NULL); + m_pLastCoverFrom = MyEHandle(nullptr); m_vAimOffset = Vector(1.0f,1.0f,1.0f); @@ -1380,20 +1403,20 @@ void CBot :: spawnInit () m_fAimMoment = 0.0f; - memset(m_fLastVoiceCommand,0,sizeof(float)*MAX_VOICE_CMDS); + std::memset(m_fLastVoiceCommand,0,sizeof(float)*MAX_VOICE_CMDS); - m_fLastUpdateLastSeeEnemy = 0; + m_fLastUpdateLastSeeEnemy = 0.0f; m_fPercentMoved = 1.0f; - for ( register short int i = 0; i < BOT_UTIL_MAX; i ++ ) - m_fUtilTimes[i] = 0; + for (float& m_fUtilTime : m_fUtilTimes) + m_fUtilTime = 0; - if ( m_pSchedules != NULL ) + if ( m_pSchedules != nullptr) m_pSchedules->freeMemory(); // clear tasks, im dead now!! - if ( m_pVisibles != NULL ) + if ( m_pVisibles != nullptr) m_pVisibles->reset(); - if ( m_pEdict && (m_iAmmo == NULL) ) + if ( m_pEdict && m_iAmmo == nullptr) m_iAmmo = CClassInterface::getAmmoList(m_pEdict); m_fCurrentDanger = 0.0f; @@ -1405,54 +1428,53 @@ void CBot :: spawnInit () m_fListenTime = 0.0f; m_bListenPositionValid = false; m_bPrevAimVectorValid = false; - m_fLastSeeEnemy = 0; - m_fAvoidTime = 0; + m_fLastSeeEnemy = 0.0f; + m_fAvoidTime = 0.0f; m_vLookAroundOffset = Vector(0,0,0); m_fWaypointStuckTime = 0.0f; - m_pPickup = NULL; - m_pAvoidEntity = NULL; + m_pPickup = nullptr; + m_pAvoidEntity = nullptr; m_bThinkStuck = false; - m_pLookEdict = NULL; + m_pLookEdict = nullptr; m_fLookAroundTime = 0.0f; - m_pAvoidEntity = NULL; m_bLookedForEnemyLast = false; //////////////////////// m_iPrevHealth = 0; // //////////////////////// m_vStuckPos = Vector(0,0,0); //m_iTimesStuck = 0; - m_fUpdateDamageTime = 0; + m_fUpdateDamageTime = 0.0f; m_iAccumulatedDamage = 0; m_fCheckStuckTime = engine->Time() + 8.0f; - m_fStuckTime = 0; + m_fStuckTime = 0.0f; m_vLastOrigin = Vector(0,0,0); m_vVelocity = Vector(0,0,0); - m_fUpdateOriginTime = 0; - m_fNextUpdateAimVector = 0; + m_fUpdateOriginTime = 0.0f; + m_fNextUpdateAimVector = 0.0f; m_vAimVector = Vector(0,0,0); m_fLookSetTime = 0.0f; m_vHurtOrigin = Vector(0,0,0); - m_pOldEnemy = NULL; - m_pEnemy = NULL; + m_pOldEnemy = nullptr; + m_pEnemy = nullptr; m_vLastSeeEnemy = Vector(0,0,0); - m_pLastEnemy = NULL; // enemy we were fighting before we lost it + m_pLastEnemy = nullptr; // enemy we were fighting before we lost it //m_pAvoidEntity = NULL; // avoid this guy - m_fLastWaypointVisible = 0; + m_fLastWaypointVisible = 0.0f; m_vGoal = Vector(0,0,0); m_bHasGoal = false; - m_fLookAtTimeStart = 0; - m_fLookAtTimeEnd = 0; - m_fNextThink = 0; + m_fLookAtTimeStart = 0.0f; + m_fLookAtTimeEnd = 0.0f; + m_fNextThink = 0.0f; m_iImpulse = 0; m_iButtons = 0; - m_fForwardSpeed = 0; - m_fSideSpeed = 0; - m_fUpSpeed = 0; + m_fForwardSpeed = 0.0f; + m_fSideSpeed = 0.0f; + m_fUpSpeed = 0.0f; m_iConditions = 0; - m_fStrafeTime = 0; + m_fStrafeTime = 0.0f; m_bInitAlive = true; @@ -1464,35 +1486,38 @@ void CBot :: spawnInit () m_fAvoidSideSwitch = 0.0f; - m_bAvoidRight = (randomInt(0,1)==0); + m_bAvoidRight = randomInt(0,1)==0; m_iLookTask = LOOK_WAYPOINT; // m_vViewAngles = QAngle(0,0,0); - if ( m_pVisibles != NULL ) + if ( m_pVisibles != nullptr) m_pVisibles->reset(); + + m_fEnemyAimLerp = 0.0f; + m_fEnemyAimLerpTime = 0.0f; + m_vEnemyAimLerpVelocity = Vector(0.0f, 0.0f, 0.0f); } void CBot::setLastEnemy(edict_t *pEnemy) { - CWaypoint *pWpt; - - if ( pEnemy == NULL ) + if ( pEnemy == nullptr) { m_fLastSeeEnemy = 0.0f; - m_pLastEnemy = NULL; + m_pLastEnemy = nullptr; return; } m_fLastSeeEnemy = engine->Time(); m_pLastEnemy = pEnemy; - m_fLastUpdateLastSeeEnemy = 0; + m_fLastUpdateLastSeeEnemy = 0.0f; m_vLastSeeEnemy = CBotGlobals::entityOrigin(m_pLastEnemy); m_vLastSeeEnemyBlastWaypoint = m_vLastSeeEnemy; - pWpt = CWaypoints::getWaypoint(CWaypointLocations::NearestBlastWaypoint(m_vLastSeeEnemy,getOrigin(),8192.0,-1,true,true,false,false,0,false)); + CWaypoint* pWpt = CWaypoints::getWaypoint(CWaypointLocations::NearestBlastWaypoint(m_vLastSeeEnemy, getOrigin(), + 8192.0f, -1, true, true, false, false, 0, false)); if ( pWpt ) m_vLastSeeEnemyBlastWaypoint = pWpt->getOrigin(); @@ -1501,9 +1526,7 @@ void CBot::setLastEnemy(edict_t *pEnemy) bool CBot :: selectBotWeapon ( CBotWeapon *pBotWeapon ) { - int id = pBotWeapon->getWeaponIndex(); - - if ( id ) + if ( const int id = pBotWeapon->getWeaponIndex() ) { selectWeapon(id); return true; @@ -1532,9 +1555,9 @@ void CBot :: touchedWpt ( CWaypoint *pWaypoint, int iNextWaypoint, int iPrevWayp updateDanger(m_pNavigator->getBelief(CWaypoints::getWaypointIndex(pWaypoint))); } -void CBot :: updateDanger ( float fBelief ) +void CBot :: updateDanger (const float fBelief) { - m_fCurrentDanger = (m_fCurrentDanger * m_pProfile->m_fBraveness) + (fBelief * (1.0f-m_pProfile->m_fBraveness)); + m_fCurrentDanger = m_fCurrentDanger * m_pProfile->m_fBraveness + fBelief * (1.0f - m_pProfile->m_fBraveness); } // setup buttons and data structures void CBot :: setup () @@ -1567,7 +1590,7 @@ void CBot :: died ( edict_t *pKiller, const char *pszWeapon ) { spawnInit(); - if ( m_pSquad != NULL ) + if ( m_pSquad != nullptr) { // died CBotSquads::removeSquadMember(m_pSquad,m_pEdict); @@ -1582,21 +1605,27 @@ void CBot :: died ( edict_t *pKiller, const char *pszWeapon ) void CBot :: killed ( edict_t *pVictim, char *weapon ) { if ( pVictim == m_pLastEnemy ) - m_pLastEnemy = NULL; + m_pLastEnemy = nullptr; } // called when bot shoots a wall or similar object -i.e. not the enemy void CBot :: shotmiss () { - } -// shot an enemy (or teammate?) + +// shot an enemy (or teammate?) //TODO: Experimental [APG]RoboCop[CL] void CBot :: shot ( edict_t *pEnemy ) { + if ( pEnemy == nullptr ) + return; + + if ( CClassInterface::getTeam(pEnemy) == getTeam() ) + friendlyFire(pEnemy); } + // got shot by someone -bool CBot :: hurt ( edict_t *pAttacker, int iHealthNow, bool bDontHide ) +bool CBot :: hurt ( edict_t *pAttacker, const int iHealthNow, const bool bDontHide ) { if ( !pAttacker ) return false; @@ -1608,26 +1637,26 @@ bool CBot :: hurt ( edict_t *pAttacker, int iHealthNow, bool bDontHide ) if ( !hasSomeConditions(CONDITION_SEE_CUR_ENEMY) ) { - m_fLookSetTime = 0; + m_fLookSetTime = 0.0f; setLookAtTask(LOOK_HURT_ORIGIN); - m_fLookSetTime = engine->Time() + randomFloat(3.0,8.0); + m_fLookSetTime = engine->Time() + randomFloat(3.0f,8.0f); } - float fTime = engine->Time(); + const float fTime = engine->Time(); if ( m_fUpdateDamageTime < fTime ) { - m_fUpdateDamageTime = fTime + 0.5; - m_fCurrentDanger += (((float)m_iAccumulatedDamage)/m_pPlayerInfo->GetMaxHealth())*MAX_BELIEF; + m_fUpdateDamageTime = fTime + 0.5f; + m_fCurrentDanger += static_cast(m_iAccumulatedDamage)/m_pPlayerInfo->GetMaxHealth()*MAX_BELIEF; m_iAccumulatedDamage = 0; } m_fLastHurtTime = engine->Time(); - m_iAccumulatedDamage += (m_iPrevHealth-iHealthNow); + m_iAccumulatedDamage += m_iPrevHealth-iHealthNow; m_iPrevHealth = iHealthNow; - // TO DO: replace with perceptron method - if ( m_iAccumulatedDamage > (m_pPlayerInfo->GetMaxHealth()*m_pProfile->m_fBraveness) ) + // TODO: replace with perceptron method + if ( m_iAccumulatedDamage > m_pPlayerInfo->GetMaxHealth() * m_pProfile->m_fBraveness ) { if ( !bDontHide ) { @@ -1636,7 +1665,7 @@ bool CBot :: hurt ( edict_t *pAttacker, int iHealthNow, bool bDontHide ) } m_iAccumulatedDamage = 0; - m_fUpdateDamageTime = 0; + m_fUpdateDamageTime = 0.0f; return true; } @@ -1647,7 +1676,7 @@ bool CBot :: hurt ( edict_t *pAttacker, int iHealthNow, bool bDontHide ) void CBot :: checkEntity ( edict_t **pEdict ) { if ( pEdict && *pEdict && !CBotGlobals::entityIsValid(*pEdict) ) - *pEdict = NULL; + *pEdict = nullptr; } void CBot :: checkDependantEntities () @@ -1686,7 +1715,7 @@ void CBot :: findEnemy ( edict_t *pOldEnemy ) m_pEnemy = m_pFindEnemyFunc->getBestEnemy(); - if ( m_pEnemy && (m_pEnemy != pOldEnemy) ) + if ( m_pEnemy && m_pEnemy != pOldEnemy ) { enemyFound(m_pEnemy); } @@ -1702,7 +1731,7 @@ int CBot :: getTeam () return m_pPlayerInfo->GetTeamIndex(); } -const char *pszConditionsDebugStrings[CONDITION_MAX_BITS+1] = +const char *pszConditionsDebugStrings[NUM_CONDITIONS] = {"CONDITION_ENEMY_OBSCURED", "CONDITION_NO_WEAPON", "CONDITION_OUT_OF_AMMO", @@ -1739,54 +1768,54 @@ void CBot :: clearSquad () //if ( m_pSquad != NULL ) // CBotSquads::removeSquadMember(m_pSquad,m_pEdict); - m_pSquad = NULL; + m_pSquad = nullptr; } -bool CBot :: isFacing ( Vector vOrigin ) +bool CBot :: isFacing (const Vector& vOrigin) const { - return (DotProductFromOrigin(vOrigin) > 0.97f); + return DotProductFromOrigin(vOrigin) > 0.97f; } void CBot ::debugBot(char *msg) { - bool hastask = m_pSchedules->getCurrentTask()!=NULL; - int iEnemyID = 0; + const bool hastask = m_pSchedules->getCurrentTask()!= nullptr; char szConditions[512]; - int iBit = 0; - int iMask; + //int iBit = 0; szConditions[0] = 0; // initialise string - for ( iMask = 1; iMask <= CONDITION_MAX; iBit++ ) + for (std::size_t iCond = 0; iCond < NUM_CONDITIONS; iCond++) { - if ( m_iConditions & iMask ) + if ( m_iConditions[iCond] ) { - strcat(szConditions,pszConditionsDebugStrings[iBit]); - strcat(szConditions,"\n"); + std::strcat(szConditions, pszConditionsDebugStrings[iCond]); + std::strcat(szConditions, "\n"); } - - iMask *= 2; } char task_string[256]; - extern const char *g_szUtils[BOT_UTIL_MAX+1]; + extern const char *g_szUtils[BOT_UTIL_MAX+1]; //Redundant? [APG]RoboCopCL] edict_t *pEnemy = m_pEnemy.get(); - IPlayerInfo *p = NULL; + IPlayerInfo *p = nullptr; - iEnemyID = ENTINDEX(pEnemy); + const int iEnemyID = ENTINDEX(pEnemy); - if ( (iEnemyID > 0) && (iEnemyID <= gpGlobals->maxClients) ) + if ( iEnemyID > 0 && iEnemyID <= gpGlobals->maxClients ) p = playerinfomanager->GetPlayerInfo(pEnemy); if ( hastask ) - m_pSchedules->getCurrentTask()->debugString(task_string); + m_pSchedules->getCurrentTask()->debugString(task_string, {}); - sprintf(msg,"Debugging bot: %s\n \ + const bool hasNextPoint = m_pNavigator->hasNextPoint(); + const int currentWaypointID = hasNextPoint ? m_pNavigator->getCurrentWaypointID() : -1; + const int currentGoalID = hasNextPoint ? m_pNavigator->getCurrentGoalID() : -1; + + std::sprintf(msg, "Debugging bot: %s\n \ Current Util: %s \n \ Current Schedule: %s\n \ Current Task: {%s}\n \ @@ -1795,32 +1824,29 @@ void CBot ::debugBot(char *msg) Current Goal: %d\n \ Danger: %0.2f pc\n \ Enemy: %s (name = '%s')\n \ - ---CONDITIONS---\n%s", - m_szBotName, - (m_CurrentUtil>=0)?g_szUtils[m_CurrentUtil]:"none", + ---CONDITIONS---\n%s", + m_szBotName, + m_CurrentUtil < BOT_UTIL_MAX + 1 ? g_szUtils[m_CurrentUtil] : "none", m_pSchedules->isEmpty() ? "none" : m_pSchedules->getCurrentSchedule()->getIDString(), hastask ? task_string : "none", - g_szLookTaskToString[m_iLookTask], - m_pNavigator->hasNextPoint() ? m_pNavigator->getCurrentWaypointID() : -1, - m_pNavigator->hasNextPoint() ? m_pNavigator->getCurrentGoalID() : -1, - (m_fCurrentDanger/MAX_BELIEF)*100, - (pEnemy!=NULL)?pEnemy->GetClassName():"none", - (p!=NULL)?p->GetName():"none", + g_szLookTaskToString[m_iLookTask], + currentWaypointID, + currentGoalID, + m_fCurrentDanger / MAX_BELIEF * 100, + pEnemy != nullptr ? pEnemy->GetClassName() : "none", + p != nullptr ? p->GetName() : "none", szConditions - ); - + ); } -int CBot :: nearbyFriendlies (float fDistance) +int CBot :: nearbyFriendlies (const float fDistance) { int num = 0; - register short int i = 0; - register short int maxclients = (short int)CBotGlobals::maxClients(); - edict_t *pEdict; + const int maxclients = CBotGlobals::maxClients(); - for ( i = 0; i <= maxclients; i ++ ) + for ( int i = 0; i <= maxclients; i ++ ) { - pEdict = INDEXENT(i); + edict_t* pEdict = INDEXENT(i); if ( !CBotGlobals::entityIsValid(pEdict) ) continue; @@ -1845,60 +1871,58 @@ void CBot :: freeMapMemory () // we can save things here // ///////////////////////////////// - if ( m_pButtons != NULL ) + if ( m_pButtons != nullptr) { m_pButtons->freeMemory(); delete m_pButtons; - m_pButtons = NULL; + m_pButtons = nullptr; } ///////////////////////////////// - if ( m_pSchedules != NULL ) + if ( m_pSchedules != nullptr) { m_pSchedules->freeMemory(); delete m_pSchedules; - m_pSchedules = NULL; + m_pSchedules = nullptr; } ///////////////////////////////// - if ( m_pNavigator != NULL ) + if ( m_pNavigator != nullptr) { m_pNavigator->beliefSave(true); m_pNavigator->freeMapMemory(); delete m_pNavigator; - m_pNavigator = NULL; + m_pNavigator = nullptr; } ///////////////////////////////// - if ( m_pVisibles != NULL ) + if ( m_pVisibles != nullptr) { m_pVisibles->reset(); delete m_pVisibles; - m_pVisibles = NULL; + m_pVisibles = nullptr; } ///////////////////////////////// - if ( m_pFindEnemyFunc != NULL ) + if ( m_pFindEnemyFunc != nullptr) { delete m_pFindEnemyFunc; - m_pFindEnemyFunc = NULL; + m_pFindEnemyFunc = nullptr; } ///////////////////////////////// - if ( m_pWeapons != NULL ) + if ( m_pWeapons != nullptr) { delete m_pWeapons; - m_pWeapons = NULL; + m_pWeapons = nullptr; } - m_iAmmo = NULL; + m_iAmmo = nullptr; ///////////////////////////////// init(); } void CBot :: updateStatistics () { - bool bVisible = false; - bool bIsEnemy = false; - - extern ConVar rcbot_stats_inrange_dist; + bool bVisible; + bool bIsEnemy; - if ( (m_iStatsIndex == 0) || ( m_iStatsIndex > gpGlobals->maxClients ) ) + if ( m_iStatsIndex == 0 || m_iStatsIndex > gpGlobals->maxClients ) { if ( m_iStatsIndex != 0 ) m_bStatsCanUse = true; @@ -1907,16 +1931,20 @@ void CBot :: updateStatistics () m_Stats.data = 0; m_iStatsIndex = 0; // reset to be sure in case of m_iStatsIndex > gpGlobals->maxClients - if ( !m_uSquadDetail.b1.said_area_clear && (m_StatsCanUse.stats.m_iEnemiesInRange == 0) && (m_StatsCanUse.stats.m_iEnemiesVisible == 0) && (m_StatsCanUse.stats.m_iTeamMatesInRange > 0)) + if (!m_uSquadDetail.b1.said_area_clear && m_StatsCanUse.stats.m_iEnemiesInRange == 0 && + m_StatsCanUse.stats.m_iEnemiesVisible == 0 && m_StatsCanUse.stats.m_iTeamMatesInRange > 0) { - if ( !inSquad() || isSquadLeader() && (m_fLastSeeEnemy && ((m_fLastSeeEnemy + 10.0f)Time())) ) + if (!inSquad() || (isSquadLeader() && + (m_fLastSeeEnemy > 0.0f && m_fLastSeeEnemy + 10.0f < engine->Time()))) + { areaClear(); + } m_uSquadDetail.b1.said_area_clear = true; } } - CClient *pClient = CClients::get(m_iStatsIndex++); + const CClient *pClient = CClients::get(m_iStatsIndex++); if ( !pClient->isUsed() ) return; @@ -1962,31 +1990,21 @@ void CBot :: updateStatistics () } } -bool CBot :: wantToListen () +bool CBot :: wantToListen () const { - return (m_bWantToListen && (m_fWantToListenTime < engine->Time()) && ((m_fLastSeeEnemy+2.5f) < engine->Time())); + return m_bWantToListen && m_fWantToListenTime < engine->Time() && m_fLastSeeEnemy+2.5f < engine->Time(); } // Listen for players who are shooting void CBot :: listenForPlayers () { //m_fNextListenTime = engine->Time() + randomFloat(0.5f,2.0f); - edict_t *pListenNearest = NULL; - CClient *pClient; - edict_t *pPlayer; - CBotCmd cmd; - IPlayerInfo *p; - float fFactor = 0; - float fMaxFactor = 0; - //float fMinDist = 1024.0f; - float fDist; - float fVelocity; + edict_t *pListenNearest = nullptr; + float fMaxFactor = 0.0f; Vector vVelocity; - extern ConVar rcbot_listen_dist; - extern ConVar rcbot_footstep_speed; bool bIsNearestAttacking = false; - if ( m_bListenPositionValid && (m_fListenTime > engine->Time()) ) // already listening to something ? + if ( m_bListenPositionValid && m_fListenTime > engine->Time() ) // already listening to something ? { setLookAtTask(LOOK_NOISE); return; @@ -1994,9 +2012,9 @@ void CBot :: listenForPlayers () m_bListenPositionValid = false; - for ( register short int i = 1; i <= gpGlobals->maxClients; i ++ ) + for (int i = 1; i <= gpGlobals->maxClients; i ++ ) { - pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(i); if ( pPlayer == m_pEdict ) continue; // don't listen to self @@ -2004,38 +2022,38 @@ void CBot :: listenForPlayers () if ( pPlayer->IsFree() ) continue; - pClient = CClients::get(pPlayer); + const CClient* pClient = CClients::get(pPlayer); if ( !pClient->isUsed() ) continue; - p = playerinfomanager->GetPlayerInfo(pPlayer); + IPlayerInfo* p = playerinfomanager->GetPlayerInfo(pPlayer); // 05/07/09 fix crash bug if ( !p || !p->IsConnected() || p->IsDead() || p->IsObserver() || !p->IsPlayer() ) continue; - fDist = distanceFrom(pPlayer); + const float fDist = distanceFrom(pPlayer); if ( fDist > rcbot_listen_dist.GetFloat() ) continue; - fFactor = 0.0f; + float fFactor = 0.0f; - cmd = p->GetLastUserCommand(); + const CBotCmd command = p->GetLastUserCommand(); - if ( (cmd.buttons & IN_ATTACK) ) + if ( command.buttons & IN_ATTACK ) { if ( wantToListenToPlayerAttack(pPlayer) ) fFactor += 1000.0f; } // can't see this player and I'm on my own - if ( wantToListenToPlayerFootsteps(pPlayer) && !isVisible(pPlayer) && ( m_bStatsCanUse && ((m_StatsCanUse.stats.m_iTeamMatesVisible==0)/* && (m_fSeeTeamMateTime ...) */)) ) + if ( wantToListenToPlayerFootsteps(pPlayer) && !isVisible(pPlayer) && ( m_bStatsCanUse && m_StatsCanUse.stats.m_iTeamMatesVisible==0/* && (m_fSeeTeamMateTime ...) */) ) { CClassInterface::getVelocity(pPlayer,&vVelocity); - - fVelocity = vVelocity.Length(); + + const float fVelocity = vVelocity.Length(); if ( fVelocity > rcbot_footstep_speed.GetFloat() ) fFactor += vVelocity.Length(); @@ -2045,17 +2063,17 @@ void CBot :: listenForPlayers () continue; // add inverted distance to the factor (i.e. closer = better) - fFactor += (rcbot_listen_dist.GetFloat() - fDist); + fFactor += rcbot_listen_dist.GetFloat() - fDist; if ( fFactor > fMaxFactor ) { fMaxFactor = fFactor; pListenNearest = pPlayer; - bIsNearestAttacking = (cmd.buttons & IN_ATTACK); + bIsNearestAttacking = command.buttons & IN_ATTACK; } } - if ( pListenNearest != NULL ) + if ( pListenNearest != nullptr) { listenToPlayer(pListenNearest,false,bIsNearestAttacking); } @@ -2067,9 +2085,9 @@ void CBot :: hearPlayerAttack( edict_t *pAttacker, int iWeaponID ) listenToPlayer(pAttacker,false,true); } -void CBot :: listenToPlayer ( edict_t *pPlayer, bool bIsEnemy, bool bIsAttacking ) +void CBot :: listenToPlayer ( edict_t *pPlayer, bool bIsEnemy, const bool bIsAttacking ) { - bool bIsVisible = isVisible(pPlayer); + const bool bIsVisible = isVisible(pPlayer); if ( CBotGlobals::isPlayer( pPlayer ) ) { @@ -2085,22 +2103,22 @@ void CBot :: listenToPlayer ( edict_t *pPlayer, bool bIsEnemy, bool bIsAttacking } else if ( bIsAttacking ) { - if ( !bIsEnemy && wantToInvestigateSound() ) + if ( wantToInvestigateSound() ) { - QAngle angle = p->GetAbsAngles(); + const QAngle angle = p->GetAbsAngles(); Vector forward; AngleVectors( angle, &forward ); // look where team mate is shooting - m_vListenPosition = p->GetAbsOrigin() + (forward*1024.0f); + m_vListenPosition = p->GetAbsOrigin() + forward*1024.0f; // not investigating any noise right now -- depending on my braveness I will check it out - if ( !m_pSchedules->isCurrentSchedule(SCHED_INVESTIGATE_NOISE) && (randomFloat(0.0f,0.75f) < m_pProfile->m_fBraveness) ) + if ( !m_pSchedules->isCurrentSchedule(SCHED_INVESTIGATE_NOISE) && randomFloat(0.0f,0.75f) < m_pProfile->m_fBraveness ) { - trace_t *TraceResult = CBotGlobals::getTraceResult(); - - Vector vAttackerOrigin = CBotGlobals::entityOrigin(pPlayer); + const trace_t *TraceResult = CBotGlobals::getTraceResult(); + + const Vector vAttackerOrigin = CBotGlobals::entityOrigin(pPlayer); if ( distanceFrom(vAttackerOrigin) > 96.0f ) { @@ -2113,17 +2131,14 @@ void CBot :: listenToPlayer ( edict_t *pPlayer, bool bIsEnemy, bool bIsAttacking CBotGlobals::quickTraceline(m_pEdict,getOrigin(),m_vListenPosition); // can't see what my teammate is shooting -- go there - if ( (TraceResult->fraction < 1.0f) && (TraceResult->m_pEnt != m_pEdict->GetIServerEntity()->GetBaseEntity() ) ) + if ( TraceResult->fraction < 1.0f && TraceResult->m_pEnt != m_pEdict->GetIServerEntity()->GetBaseEntity() ) { m_pSchedules->removeSchedule(SCHED_INVESTIGATE_NOISE); - - Vector vecLOS; - float flDot; - vecLOS = getOrigin() - vAttackerOrigin; + Vector vecLOS = getOrigin() - vAttackerOrigin; vecLOS = vecLOS/vecLOS.Length(); - - flDot = DotProduct (vecLOS , forward ); + + const float flDot = DotProduct(vecLOS, forward); if ( flDot > 0.5f ) { @@ -2159,7 +2174,7 @@ void CBot :: listenToPlayer ( edict_t *pPlayer, bool bIsEnemy, bool bIsAttacking } -bool CBot :: onLadder () +bool CBot :: onLadder () const // onLadder needs to be constant? [APG]RoboCop[CL] { return CClassInterface::isMoveType(m_pEdict,MOVETYPE_LADDER); } @@ -2167,10 +2182,9 @@ bool CBot :: onLadder () void CBot :: freeAllMemory () { freeMapMemory(); - return; } -void CBot :: forceGotoWaypoint ( int wpt ) +void CBot :: forceGotoWaypoint (const int wpt) const { if ( wpt != -1 ) { @@ -2193,31 +2207,20 @@ void CBot :: doMove () if ( moveToIsValid () ) { Vector2D move; - float flMove = 0.0; - float flSide = 0.0; - // fAngle is got from world realting to bots origin, not angles - float fAngle; - float radians; - float fDist; - if ( m_pAvoidEntity && (m_fAvoidTime < engine->Time()) ) + if ( m_pAvoidEntity && m_fAvoidTime < engine->Time() ) { if ( canAvoid(m_pAvoidEntity) ) { - extern ConVar bot_avoid_strength; - - Vector m_vAvoidOrigin = CBotGlobals::entityOrigin(m_pAvoidEntity); - //m_vMoveTo = getOrigin() + ((m_vMoveTo-getOrigin())-((m_vAvoidOrigin-getOrigin())*bot_avoid_strength.GetFloat())); //float fAvoidDist = distanceFrom(m_pAvoidEntity); - Vector vMove = m_vMoveTo-getOrigin(); - Vector vLeft; + const Vector vMove = m_vMoveTo-getOrigin(); if ( vMove.Length2D() > bot_avoid_strength.GetFloat() ) { - vLeft = vMove.Cross(Vector(0,0,1)); - vLeft = (vLeft/vLeft.Length()); + Vector vLeft = vMove.Cross(Vector(0, 0, 1)); + vLeft = vLeft/vLeft.Length(); if ( m_fAvoidSideSwitch < engine->Time() ) { @@ -2227,46 +2230,45 @@ void CBot :: doMove () #ifndef __linux__ if ( CClients::clientsDebugging(BOT_DEBUG_THINK) ) { + const Vector m_vAvoidOrigin = CBotGlobals::entityOrigin(m_pAvoidEntity); + debugoverlay->AddLineOverlay (getOrigin(), m_vAvoidOrigin, 0,0,255, false, 0.05f); - debugoverlay->AddLineOverlay (getOrigin(), m_bAvoidRight ? (getOrigin()+(vLeft*bot_avoid_strength.GetFloat())):(getOrigin()-(vLeft*bot_avoid_strength.GetFloat())), 0,255,0, false, 0.05f); - debugoverlay->AddLineOverlay (getOrigin(), getOrigin() + ((vMove/vMove.Length())*bot_avoid_strength.GetFloat()), 255,0,0, false, 0.05f); - debugoverlay->AddTextOverlayRGB(getOrigin()+Vector(0,0,100),0,0.05,255,255,255,255,"Avoiding: %s",m_pAvoidEntity.get()->GetClassName()); + debugoverlay->AddLineOverlay (getOrigin(), m_bAvoidRight ? getOrigin()+vLeft*bot_avoid_strength.GetFloat():getOrigin()-vLeft*bot_avoid_strength.GetFloat(), 0,255,0, false, 0.05f); + debugoverlay->AddLineOverlay (getOrigin(), getOrigin() + vMove/vMove.Length()*bot_avoid_strength.GetFloat(), 255,0,0, false, 0.05f); + debugoverlay->AddTextOverlayRGB(getOrigin()+Vector(0,0,100),0,0.05f,255,255,255,255,"Avoiding: %s",m_pAvoidEntity.get()->GetClassName()); } #endif - //*/ //debugoverlay->AddLineOverlay (getOrigin(), m_vAvoidOrigin, 0,0,255, false, 0.05f); //debugoverlay->AddLineOverlay (getOrigin(), m_bAvoidRight ? (getOrigin()+(vLeft*bot_avoid_strength.GetFloat())):(getOrigin()-(vLeft*bot_avoid_strength.GetFloat())), 0,255,0, false, 0.05f); //debugoverlay->AddLineOverlay (getOrigin(), m_vMoveTo, 255,0,0, false, 0.05f); if ( m_bAvoidRight ) - m_vMoveTo = getOrigin() + ((vMove/vMove.Length())*bot_avoid_strength.GetFloat()) + (vLeft*bot_avoid_strength.GetFloat()); + m_vMoveTo = getOrigin() + vMove/vMove.Length()*bot_avoid_strength.GetFloat() + vLeft*bot_avoid_strength.GetFloat(); else - m_vMoveTo = getOrigin() + ((vMove/vMove.Length())*bot_avoid_strength.GetFloat()) - (vLeft*bot_avoid_strength.GetFloat()); + m_vMoveTo = getOrigin() + vMove/vMove.Length()*bot_avoid_strength.GetFloat() - vLeft*bot_avoid_strength.GetFloat(); } - - } else - m_pAvoidEntity = NULL; + m_pAvoidEntity = nullptr; } - fAngle = CBotGlobals::yawAngleFromEdict(m_pEdict,m_vMoveTo); - fDist = (getOrigin()-m_vMoveTo).Length2D(); + const float fAngle = CBotGlobals::yawAngleFromEdict(m_pEdict, m_vMoveTo); + const float fDist = (getOrigin() - m_vMoveTo).Length2D(); - radians = DEG_TO_RAD(fAngle); + const float radians = DEG_TO_RAD(fAngle); //radians = fAngle * 3.141592f / 180.0f; // degrees to radians - // fl Move is percentage (0 to 1) of forward speed, - // flSide is percentage (0 to 1) of side speed. + // fl Move is percentage (0 to 1) of forward speed, + // flSide is percentage (0 to 1) of side speed. // quicker SinCos(radians,&move.y,&move.x); move = move / move.Length(); - flMove = move.x; - flSide = move.y; + const float flMove = move.x; + const float flSide = move.y; m_fForwardSpeed = m_fIdealMoveSpeed * flMove; @@ -2280,21 +2282,21 @@ void CBot :: doMove () if ( hasSomeConditions(CONDITION_LIFT) )//fabs(m_vMoveTo.z - getOrigin().z) > 48 ) { - if ( fabs(m_vVelocity.z) > 16.0f ) + if ( std::fabs(m_vVelocity.z) > 16.0f ) { - m_fForwardSpeed = 0; - m_fSideSpeed = 0; + m_fForwardSpeed = 0.0f; + m_fSideSpeed = 0.0f; } } // moving less than 1.0 units/sec? just stop to // save bot jerking around.. - if ( fabs(m_fForwardSpeed) < 1.0 ) - m_fForwardSpeed = 0.0; - if ( fabs(m_fSideSpeed) < 1.0 ) - m_fSideSpeed = 0.0; + if ( std::fabs(m_fForwardSpeed) < 1.0f ) + m_fForwardSpeed = 0.0f; + if ( std::fabs(m_fSideSpeed) < 1.0f ) + m_fSideSpeed = 0.0f; - if ( (m_fForwardSpeed < 1.0f) && (m_fSideSpeed < 1.0f) ) + if ( m_fForwardSpeed < 1.0f && m_fSideSpeed < 1.0f ) { if ( m_pButtons->holdingButton(IN_SPEED) && m_pButtons->holdingButton(IN_FORWARD) ) { @@ -2303,7 +2305,7 @@ void CBot :: doMove () } } - if ( (!onLadder() && !m_pNavigator->nextPointIsOnLadder()) && (fDist < 8.0f) ) + if ( !onLadder() && !m_pNavigator->nextPointIsOnLadder() && fDist < 8.0f ) { m_fForwardSpeed = 0.0f; m_fSideSpeed = 0.0f; @@ -2311,45 +2313,47 @@ void CBot :: doMove () if ( isUnderWater() || onLadder() ) { - if ( m_vMoveTo.z > (getOrigin().z + 32.0) ) + if ( m_vMoveTo.z > getOrigin().z + 32.0f ) m_fUpSpeed = m_fIdealMoveSpeed; - else if ( m_vMoveTo.z < (getOrigin().z - 32.0) ) + else if ( m_vMoveTo.z < getOrigin().z - 32.0f ) m_fUpSpeed = -m_fIdealMoveSpeed; } } else { - m_fForwardSpeed = 0; + m_fForwardSpeed = 0.0f; // bots side move speed - m_fSideSpeed = 0; + m_fSideSpeed = 0.0f; // bots upward move speed (e.g in water) - m_fUpSpeed = 0; + m_fUpSpeed = 0.0f; } } -bool CBot :: recentlySpawned ( float fTime ) +bool CBot :: recentlySpawned (const float fTime) const { - return ( ( m_fSpawnTime + fTime ) > engine->Time()); + return m_fSpawnTime + fTime > engine->Time(); } -bool CBot :: FInViewCone ( edict_t *pEntity ) +bool CBot :: FInViewCone ( edict_t *pEntity ) const { static Vector origin; + if ( CBotGlobals::isBrushEntity(pEntity) ) + origin = CBotGlobals::worldCenter(pEntity); + else origin = CBotGlobals::entityOrigin(pEntity); - return ( ((origin - getEyePosition()).Length()>1) && (DotProductFromOrigin(origin) > 0) ); // 90 degree !! 0.422618f ); // 65 degree field of view + return (origin - getEyePosition()).Length()>1 && DotProductFromOrigin(origin) > 0; // 90 degree !! 0.422618f ); // 65 degree field of view } -float CBot :: DotProductFromOrigin ( Vector pOrigin ) +float CBot :: DotProductFromOrigin (const Vector& pOrigin) const { static Vector vecLOS; static float flDot; Vector vForward; - QAngle eyes; - eyes = eyeAngles(); + const QAngle eyes = eyeAngles(); // in fov? Check angle to edict AngleVectors(eyes,&vForward); @@ -2362,7 +2366,7 @@ float CBot :: DotProductFromOrigin ( Vector pOrigin ) return flDot; } -void CBot :: updateUtilTime ( int util ) +void CBot :: updateUtilTime (const int util) { m_fUtilTimes[util] = engine->Time() + 0.5f; } @@ -2381,36 +2385,42 @@ Vector CBot::getAimVector ( edict_t *pEntity ) return m_vAimVector; } + if ( CBotGlobals::isBrushEntity(pEntity) ) + { + v_origin = CBotGlobals::worldCenter(pEntity); + fDist = distanceFrom(v_origin); + fDist2D = distanceFrom2D(v_origin); + } + else + { fDist = distanceFrom(pEntity); fDist2D = distanceFrom2D(pEntity); + v_origin = CBotGlobals::entityOrigin(pEntity); + } v_size = pEntity->GetCollideable()->OBBMaxs() - pEntity->GetCollideable()->OBBMins(); v_size = v_size * 0.5f; - fSensitivity = (float)m_pProfile->m_iSensitivity/20; - - v_origin = CBotGlobals::entityOrigin(pEntity); + fSensitivity = static_cast(m_pProfile->m_iSensitivity)/20; modAim(pEntity,v_origin,&v_desired_offset,v_size,fDist,fDist2D); // post aim // update - extern ConVar rcbot_supermode; - if ( rcbot_supermode.GetBool() ) { m_vAimOffset = v_desired_offset; } else { - m_vAimOffset.x = ((1.0f-fSensitivity)*m_vAimOffset.x) + fSensitivity*v_desired_offset.x; - m_vAimOffset.y = ((1.0f-fSensitivity)*m_vAimOffset.y) + fSensitivity*v_desired_offset.y; - m_vAimOffset.z = ((1.0f-fSensitivity)*m_vAimOffset.z) + fSensitivity*v_desired_offset.z; + m_vAimOffset.x = (1.0f-fSensitivity)*m_vAimOffset.x + fSensitivity*v_desired_offset.x; + m_vAimOffset.y = (1.0f-fSensitivity)*m_vAimOffset.y + fSensitivity*v_desired_offset.y; + m_vAimOffset.z = (1.0f-fSensitivity)*m_vAimOffset.z + fSensitivity*v_desired_offset.z; // check for QNAN - if ( (m_vAimOffset.x != m_vAimOffset.x) || - (m_vAimOffset.y != m_vAimOffset.y) || - (m_vAimOffset.z != m_vAimOffset.z) ) + if ( m_vAimOffset.x != m_vAimOffset.x || + m_vAimOffset.y != m_vAimOffset.y || + m_vAimOffset.z != m_vAimOffset.z ) { m_vAimOffset = Vector(1.0f,1.0f,1.0f); } @@ -2429,7 +2439,7 @@ Vector CBot::getAimVector ( edict_t *pEntity ) if ( CClients::get(0)->getDebugBot() == getEdict() ) { int line = 0; - float ftime = m_fNextUpdateAimVector-engine->Time(); + const float ftime = m_fNextUpdateAimVector-engine->Time(); debugoverlay->AddTextOverlayRGB(m_vAimVector,line++,ftime,255,200,100,230,"x Aiming Info"); debugoverlay->AddTextOverlayRGB(m_vAimVector,line++,ftime,255,200,100,230,"fDist = %0.2f",fDist); @@ -2437,6 +2447,8 @@ Vector CBot::getAimVector ( edict_t *pEntity ) debugoverlay->AddTextOverlayRGB(m_vAimVector,line++,ftime,255,200,100,230,"v_size = (%0.2f,%0.2f,%0.2f)",v_size.x,v_size.y,v_size.z); debugoverlay->AddTextOverlayRGB(m_vAimVector,line++,ftime,255,200,100,230,"v_desired_offset = (%0.2f,%0.2f,%0.2f)",v_desired_offset.x,v_desired_offset.y,v_desired_offset.z); debugoverlay->AddTextOverlayRGB(m_vAimVector,line++,ftime,255,200,100,230,"m_vAimOffset = (%0.2f,%0.2f,%0.2f)",m_vAimOffset.x,m_vAimOffset.y,m_vAimOffset.z); + debugoverlay->AddLineOverlayAlpha(getEyePosition(), m_vAimVector, 255, 0, 0, 255, true, ftime); + debugoverlay->AddLineOverlayAlpha(getEyePosition(), v_origin, 0, 0, 255, 255, true, ftime); } } #endif @@ -2444,7 +2456,7 @@ Vector CBot::getAimVector ( edict_t *pEntity ) return m_vAimVector; } -void CBot::modAim ( edict_t *pEntity, Vector &v_origin, Vector *v_desired_offset, Vector &v_size, float fDist, float fDist2D ) +void CBot::modAim ( edict_t *pEntity, Vector &v_origin, Vector *v_desired_offset, Vector &v_size, const float fDist, float fDist2D ) { static Vector vel; static Vector myvel; @@ -2452,11 +2464,9 @@ void CBot::modAim ( edict_t *pEntity, Vector &v_origin, Vector *v_desired_offset static float fDistFactor; static float fHeadOffset; - extern ConVar rcbot_supermode; - - int iPlayerFlags = CClassInterface::getPlayerFlags(pEntity); + const int iPlayerFlags = CClassInterface::getPlayerFlags(pEntity); - fHeadOffset = 0; + fHeadOffset = 0.0f; if ( rcbot_supermode.GetBool() ) { @@ -2467,21 +2477,21 @@ void CBot::modAim ( edict_t *pEntity, Vector &v_origin, Vector *v_desired_offset return; } - CBotWeapon *pWp = getCurrentWeapon(); + const CBotWeapon *pWp = getCurrentWeapon(); float fVelFactor = 0.003125f; if ( pWp && pWp->isMelee() ) { - fDistFactor = 0; - fVelFactor = 0; + fDistFactor = 0.0f; + fVelFactor = 0.0f; } else { - if ( fDist < 160 ) + if ( fDist < 160.0f ) fVelFactor = 0.001f; - fDistFactor = (1.0f - m_pProfile->m_fAimSkill) + (fDist*0.000125f)*(m_fFov/90.0f); + fDistFactor = 1.0f - m_pProfile->m_fAimSkill + fDist * 0.000125f * (m_fFov / 90.0f); } // origin is always the bottom part of the entity // add body height @@ -2490,7 +2500,7 @@ void CBot::modAim ( edict_t *pEntity, Vector &v_origin, Vector *v_desired_offset if ( ENTINDEX(pEntity) <= gpGlobals->maxClients ) // add body height { // aim for head - if ( !(iPlayerFlags & FL_DUCKING) && hasSomeConditions(CONDITION_SEE_ENEMY_HEAD) && (m_fFov < BOT_DEFAULT_FOV) ) + if ( !(iPlayerFlags & FL_DUCKING) && hasSomeConditions(CONDITION_SEE_ENEMY_HEAD) && m_fFov < BOT_DEFAULT_FOV ) fHeadOffset += v_size.z-1; } @@ -2500,7 +2510,7 @@ void CBot::modAim ( edict_t *pEntity, Vector &v_origin, Vector *v_desired_offset // change in velocity if ( CClassInterface::getVelocity(pEntity,&enemyvel) && CClassInterface::getVelocity(m_pEdict,&myvel) ) { - vel = (enemyvel - myvel); // relative velocity + vel = enemyvel - myvel; // relative velocity vel = vel * fVelFactor;//0.003125f; @@ -2518,28 +2528,36 @@ void CBot::modAim ( edict_t *pEntity, Vector &v_origin, Vector *v_desired_offset v_desired_offset->z = randomFloat(-vel.z,vel.z)*fDistFactor*v_size.z; // target - v_desired_offset->z += (fHeadOffset * m_pProfile->m_fAimSkill) + (randomFloat(0.0,1.0f-m_pProfile->m_fAimSkill)*fHeadOffset); + v_desired_offset->z += fHeadOffset * m_pProfile->m_fAimSkill + randomFloat(0.0f,1.0f-m_pProfile->m_fAimSkill)*fHeadOffset; } +void CBot::hearVoiceCommand(edict_t* pPlayer, byte voiceCmd) //Needs properly implemented? [APG]RoboCop[CL] +{ +} + void CBot :: grenadeThrown () { } -void CBot :: checkCanPickup ( edict_t *pPickup ) +void CBot::voiceCommand(byte voiceCmd) { +} + +void CBot :: checkCanPickup ( edict_t *pPickup ) +{ } -Vector CBot::snipe (Vector &vAiming ) +Vector CBot::snipe (const Vector& vAiming) { if ( m_fLookAroundTime < engine->Time() ) { - CTraceFilterWorldAndPropsOnly filter; + CTraceFilterWorldAndPropsOnly filter; //Unused? [APG]RoboCop[CL] float fTime; - Vector vOrigin = getOrigin(); + Vector vOrigin = getOrigin(); //Unused? [APG]RoboCop[CL] //trace_t *tr = CBotGlobals::getTraceResult(); @@ -2596,7 +2614,7 @@ void CBot :: getLookAtVector () try { - if (m_pLookEdict.get() != NULL) + if (m_pLookEdict.get() != nullptr) setLookAt(getAimVector(m_pLookEdict)); //setLookAt(CBotGlobals::entityOrigin(m_pLookEdict)+Vector(0,0,32)); @@ -2606,7 +2624,7 @@ void CBot :: getLookAtVector () } catch (...) { - m_pLookEdict = NULL; + m_pLookEdict = nullptr; setLookAtTask(LOOK_NONE); } } @@ -2624,7 +2642,7 @@ void CBot :: getLookAtVector () try { - if (m_pEnemy.get() != NULL) + if (m_pEnemy.get() != nullptr) { setLookAt(getAimVector(m_pEnemy)); } @@ -2636,7 +2654,7 @@ void CBot :: getLookAtVector () } catch (...) { - m_pEnemy = NULL; + m_pEnemy = nullptr; setLookAtTask(LOOK_NONE); } } @@ -2663,16 +2681,15 @@ void CBot :: getLookAtVector () if ( m_pNavigator->nextPointIsOnLadder() ) { - QAngle angle; Vector vforward; vLook = m_pNavigator->getNextPoint(); - angle = QAngle(0,m_pNavigator->getNextYaw(),0); + const QAngle angle = QAngle(0, m_pNavigator->getNextYaw(), 0); AngleVectors(angle,&vforward); - vforward = (vforward/vforward.Length())*64; + vforward = vforward/vforward.Length()*64; vforward.z = 64.0f; @@ -2689,9 +2706,9 @@ void CBot :: getLookAtVector () CClients::clientDebugMsg(BOT_DEBUG_AIM,"no valid route point",this); } } - else if ( (m_pLastEnemy.get()!=NULL) && ((m_fLastSeeEnemy + 5.0f) > engine->Time()) ) + else if ( m_pLastEnemy.get()!= nullptr && m_fLastSeeEnemy + 5.0f > engine->Time() ) setLookAt(m_vLastSeeEnemy); - else if ( (m_fCurrentDanger >= 20.0f) && m_pNavigator->getDangerPoint(&vLook) ) + else if ( m_fCurrentDanger >= 20.0f && m_pNavigator->getDangerPoint(&vLook) ) setLookAt(vLook); else if ( m_pNavigator->getNextRoutePoint(&vLook) ) setLookAt(vLook); @@ -2719,7 +2736,7 @@ void CBot :: getLookAtVector () //} if ( m_fLookAroundTime < engine->Time() ) { - float fTime = randomFloat(2.0f,4.0f); + const float fTime = randomFloat(2.0f,4.0f); m_fLookAroundTime = engine->Time() + fTime; m_vLookAroundOffset = Vector(randomFloat(-64.0f,64.0f),randomFloat(-64.0f,64.0f),randomFloat(-64.0f,32.0f)); @@ -2743,12 +2760,12 @@ void CBot :: getLookAtVector () { if ( m_pEnemy && hasSomeConditions(CONDITION_SEE_CUR_ENEMY) ) { - setLookAtTask((LOOK_ENEMY)); + setLookAtTask(LOOK_ENEMY); return; } - else if ( !m_bListenPositionValid || (m_fListenTime < engine->Time()) ) // already listening to something ? + if ( !m_bListenPositionValid || m_fListenTime < engine->Time() ) // already listening to something ? { - setLookAtTask((LOOK_WAYPOINT)); + setLookAtTask(LOOK_WAYPOINT); return; } @@ -2764,7 +2781,7 @@ void CBot :: getLookAtVector () { if ( m_fLookAroundTime < engine->Time() ) { - if ( (m_fCurrentDanger < 10.0f) || ((m_pNavigator->numPaths() == 0) || !m_pNavigator->randomDangerPath(&m_vLookAroundOffset)) ) + if ( m_fCurrentDanger < 10.0f || (m_pNavigator->numPaths() == 0 || !m_pNavigator->randomDangerPath(&m_vLookAroundOffset)) ) { // random m_vLookAroundOffset = getEyePosition(); @@ -2789,56 +2806,57 @@ void CBot :: getLookAtVector () CClients::clientDebugMsg(BOT_DEBUG_LOOK,"LOOK_HURT_ORIGIN",this); } break; + //case LOOK_MAX: + // break; default: break; } } -int CBot :: getPlayerID () +int CBot :: getPlayerID () const { return m_pPlayerInfo->GetUserID(); } -void CBot :: letGoOfButton ( int button ) +void CBot :: letGoOfButton (const int button) const { m_pButtons->letGo(button); } -void CBot :: changeAngles ( float fSpeed, float *fIdeal, float *fCurrent, float *fUpdate ) +void CBot :: changeAngles (float fSpeed, const float* fIdeal, float* fCurrent, float* fUpdate) { float current = *fCurrent; - float ideal = *fIdeal; - float diff; - float delta; - float alpha; - float alphaspeed; - - extern ConVar bot_anglespeed; + const float ideal = *fIdeal; if (bot_anglespeed.GetFloat() < 0.01f) bot_anglespeed.SetValue(0.16f); - alphaspeed = (fSpeed/20); + // Really not needed for bigger sensitivities + // Also this does not take the skill system into account + if (fSpeed < 15.0f) + fSpeed = Lerp(m_fEnemyAimLerp, fSpeed, 15.0f); - alpha = alphaspeed * bot_anglespeed.GetFloat(); + const float alphaspeed = fSpeed / 20; + + const float alpha = alphaspeed * bot_anglespeed.GetFloat(); - diff = ideal - current; + float diff = ideal - current; if ( diff < -180.0f ) diff += 360.0f; else if ( diff > 180.0f ) diff -= 360.0f; - delta = (diff*alpha) + (m_fAimMoment*alphaspeed); + float delta = diff * alpha + m_fAimMoment * alphaspeed; //check for QNAN - if ( delta != delta ) + if ( delta != delta ) //Not required? [APG]RoboCop[CL] delta = 1.0f; - m_fAimMoment = (m_fAimMoment * alphaspeed) + (delta * (1.0f-alphaspeed)); + m_fAimMoment = m_fAimMoment * alphaspeed + delta * (1.0f-alphaspeed); //check for QNAN - if ( m_fAimMoment != m_fAimMoment ) + if ( m_fAimMoment != m_fAimMoment ) //Not required? [APG]RoboCop[CL] m_fAimMoment = 1.0f; current = current + delta; @@ -2858,13 +2876,9 @@ void CBot :: changeAngles ( float fSpeed, float *fIdeal, float *fCurrent, float bool CBot :: select_CWeapon ( CWeapon *pWeapon ) { - CBotWeapon *pSelect = m_pWeapons->getWeapon(pWeapon); - - if ( pSelect ) + if ( const CBotWeapon *pSelect = m_pWeapons->getWeapon(pWeapon) ) { - int id = pSelect->getWeaponIndex(); - - if ( id ) + if ( const int id = pSelect->getWeaponIndex() ) { failWeaponSelect(); selectWeapon(id); @@ -2882,15 +2896,13 @@ void CBot :: doLook () getLookAtVector(); // looking at something? - if ( lookAtIsValid () ) + if ( lookAtIsValid () ) { float fSensitivity; - extern ConVar rcbot_supermode; - if ( rcbot_supermode.GetBool() || m_bIncreaseSensitivity || onLadder() ) fSensitivity = 15.0f; else - fSensitivity = (float)m_pProfile->m_iSensitivity; + fSensitivity = static_cast(m_pProfile->m_iSensitivity); QAngle requiredAngles; @@ -2901,16 +2913,16 @@ void CBot :: doLook () if ( m_iLookTask == LOOK_GROUND ) requiredAngles.x = 89.0f; - CBotCmd cmd = m_pPlayerInfo->GetLastUserCommand(); + const CBotCmd command = m_pPlayerInfo->GetLastUserCommand(); - m_vViewAngles = cmd.viewangles; + m_vViewAngles = command.viewangles; if (m_vViewAngles.x == 0.0f && m_vViewAngles.y == 0.0f) { CClients::clientDebugMsg(BOT_DEBUG_AIM, "view angle invalid", this); } - changeAngles(fSensitivity,&requiredAngles.x,&m_vViewAngles.x,NULL); - changeAngles(fSensitivity,&requiredAngles.y,&m_vViewAngles.y,NULL); + changeAngles(fSensitivity,&requiredAngles.x,&m_vViewAngles.x, nullptr); + changeAngles(fSensitivity,&requiredAngles.y,&m_vViewAngles.y, nullptr); CBotGlobals::fixFloatAngle(&m_vViewAngles.x); CBotGlobals::fixFloatAngle(&m_vViewAngles.y); @@ -2935,15 +2947,19 @@ void CBot :: doButtons () m_iButtons = m_pButtons->getBitMask(); } -void CBot :: secondaryAttack ( bool bHold ) +void CBot :: secondaryAttack (const bool bHold, const float fTime) const { - float fLetGoTime = 0.15; - float fHoldTime = 0.12; + float fLetGoTime = 0.15f; + float fHoldTime = 0.12f; if ( bHold ) { - fLetGoTime = 0.0; - fHoldTime = 1.0; + fLetGoTime = 0.0f; + + if ( fTime ) + fHoldTime = fTime; + else + fHoldTime = 1.0f; } // not currently in "letting go" stage? @@ -2959,7 +2975,7 @@ void CBot :: secondaryAttack ( bool bHold ) } } -void CBot :: primaryAttack ( bool bHold, float fTime ) +void CBot :: primaryAttack (const bool bHold, const float fTime) const { float fLetGoTime = 0.15f; float fHoldTime = 0.12f; @@ -2987,44 +3003,45 @@ void CBot :: primaryAttack ( bool bHold, float fTime ) } } -void CBot :: tapButton ( int iButton ) +void CBot :: tapButton (const int iButton) const { m_pButtons->tap(iButton); } -void CBot :: reload () +void CBot :: reload () const { if ( m_pButtons->canPressButton(IN_RELOAD) ) m_pButtons->tap(IN_RELOAD); } -void CBot :: use () +void CBot :: use () const { if ( m_pButtons->canPressButton(IN_USE) ) m_pButtons->tap(IN_USE); } -void CBot :: jump () +void CBot :: jump () const { if ( m_pButtons->canPressButton(IN_JUMP) ) { - m_pButtons->holdButton(IN_JUMP,0/* time to press*/,0.5/* hold time*/,0.5/*let go time*/); + m_pButtons->holdButton(IN_JUMP,0.0f/* time to press*/,0.5f/* hold time*/,0.5f/*let go time*/); // do the trademark jump & duck - m_pButtons->holdButton(IN_DUCK,0.2/* time to press*/,0.3/* hold time*/,0.5/*let go time*/); + m_pButtons->holdButton(IN_DUCK,0.2f/* time to press*/,0.3f/* hold time*/,0.5f/*let go time*/); } } -void CBot :: duck ( bool hold ) +void CBot :: duck (const bool hold) const { if ( hold || m_pButtons->canPressButton(IN_DUCK) ) - m_pButtons->holdButton(IN_DUCK,0.0/* time to press*/,1.0/* hold time*/,0.5/*let go time*/); + m_pButtons->holdButton(IN_DUCK,0.0f/* time to press*/,1.0f/* hold time*/,0.5f/*let go time*/); } -// TO DO: perceptron method +// TODO: perceptron method bool CBot::wantToFollowEnemy () { - return getHealthPercent() > (1.0f - m_pProfile->m_fBraveness); + return getHealthPercent() > 1.0f - m_pProfile->m_fBraveness; } + //////////////////////////// -void CBot :: getTasks (unsigned int iIgnore) +void CBot :: getTasks (unsigned iIgnore) { if ( !m_bLookedForEnemyLast && m_pLastEnemy && CBotGlobals::entityIsAlive(m_pLastEnemy) ) { @@ -3055,9 +3072,8 @@ void CBot :: getTasks (unsigned int iIgnore) return; // already got some tasks left // roam - CWaypoint *pWaypoint = CWaypoints::getWaypoint(CWaypoints::randomFlaggedWaypoint(getTeam())); - if ( pWaypoint ) + if ( CWaypoint *pWaypoint = CWaypoints::getWaypoint(CWaypoints::randomFlaggedWaypoint(getTeam())) ) { m_pSchedules->add(new CBotGotoOriginSched(pWaypoint->getOrigin())); } @@ -3066,206 +3082,186 @@ void CBot :: getTasks (unsigned int iIgnore) /////////////////////// -bool CBots :: controlBot ( edict_t *pEdict ) +bool CBots::controlBot(edict_t* pEdict) { - CBotProfile *pBotProfile = CBotProfiles::getRandomFreeProfile(); + CBotProfile* pBotProfile = CBotProfiles::getRandomFreeProfile(); + + const int slot = slotOfEdict(pEdict); + if (slot < 0) { + logger->Log(LogLevel::ERROR, "Invalid slot value"); + } - if ( m_Bots[slotOfEdict(pEdict)]->getEdict() == pEdict ) + const std::size_t slotIndex = static_cast(slot); + + if (m_Bots[static_cast(slotIndex)]->getEdict() == pEdict) { return false; } - - if ( pBotProfile == NULL ) + if (pBotProfile == nullptr) { - CBotGlobals::botMessage(NULL,0,"No bot profiles are free, creating a default bot..."); + logger->Log(LogLevel::INFO, "No bot profiles are free, creating a default bot..."); pBotProfile = CBotProfiles::getDefaultProfile(); - if ( pBotProfile == NULL ) + if (pBotProfile == nullptr) return false; } - m_Bots[slotOfEdict(pEdict)]->createBotFromEdict(pEdict,pBotProfile); + m_Bots[slotIndex]->createBotFromEdict(pEdict, pBotProfile); return true; } -#define SET_PROFILE_DATA_INT(varname,membername) if ( varname && *varname ) { pBotProfile->membername = atoi(varname); } -#define SET_PROFILE_STRING(varname,localname,membername) if ( varname && *varname ) { localname = (char*)varname; } else { localname = pBotProfile->membername; } +#define SET_PROFILE_DATA_INT(varname,membername) if ( (varname) && *(varname) ) { pBotProfile->membername = std::atoi(varname); } +#define SET_PROFILE_STRING(varname,localname,membername) if ( (varname) && *(varname) ) { (localname) = (char*)(varname); } else { (localname) = pBotProfile->membername; } -bool CBots :: controlBot ( const char *szOldName, const char *szName, const char *szTeam, const char *szClass ) +bool CBots::controlBot(const char* szOldName, const char* szName, const char* szTeam, const char* szClass) { - edict_t *pEdict; - CBotProfile *pBotProfile; + edict_t* pEdict; - char *szOVName = ""; + const char* szOVName = ""; - if ( (pEdict = CBotGlobals::findPlayerByTruncName(szOldName)) == NULL ) + if ((pEdict = CBotGlobals::findPlayerByTruncName(szOldName)) == nullptr) { - CBotGlobals::botMessage(NULL,0,"Can't find player"); + logger->Log(LogLevel::ERROR, "Can't find player"); return false; } - if ( m_Bots[slotOfEdict(pEdict)]->getEdict() == pEdict ) + const int slot = slotOfEdict(pEdict); + + if (slot < 0) { + logger->Log(LogLevel::ERROR, "Invalid slot value"); + } + + const std::size_t botIndex = static_cast(slot); + + if (m_Bots[botIndex]->getEdict() == pEdict) { - CBotGlobals::botMessage(NULL,0,"already controlling player"); + logger->Log(LogLevel::ERROR, "already controlling player"); return false; } - if ( (m_iMaxBots != -1) && (CBotGlobals::numClients() >= m_iMaxBots) ) + if (m_iMaxBots != -1 && CBotGlobals::numPlayersPlaying() >= m_iMaxBots) { - CBotGlobals::botMessage(NULL,0,"Can't create bot, max_bots reached"); + logger->Log(LogLevel::ERROR, "Can't create bot, max_bots reached"); return false; } m_flAddKickBotTime = engine->Time() + 2.0f; - pBotProfile = CBotProfiles::getRandomFreeProfile(); + CBotProfile* pBotProfile = CBotProfiles::getRandomFreeProfile(); - if ( pBotProfile == NULL ) + if (pBotProfile == nullptr) { - CBotGlobals::botMessage(NULL,0,"No bot profiles are free, creating a default bot..."); + logger->Log(LogLevel::INFO, "No bot profiles are free, creating a default bot..."); pBotProfile = CBotProfiles::getDefaultProfile(); - if ( pBotProfile == NULL ) + if (pBotProfile == nullptr) return false; } - SET_PROFILE_DATA_INT(szClass,m_iClass); - SET_PROFILE_DATA_INT(szTeam,m_iTeam); - SET_PROFILE_STRING(szName,szOVName,m_szName); + + SET_PROFILE_DATA_INT(szClass, m_iClass) + SET_PROFILE_DATA_INT(szTeam, m_iTeam) + SET_PROFILE_STRING(szName, szOVName, m_szName) //IBotController *p = g_pBotManager->GetBotController(pEdict); - return m_Bots[slotOfEdict(pEdict)]->createBotFromEdict(pEdict,pBotProfile); - + return m_Bots[botIndex]->createBotFromEdict(pEdict, pBotProfile); } bool CBots :: createBot (const char *szClass, const char *szTeam, const char *szName) -{ - edict_t *pEdict; - CBotProfile *pBotProfile; - CBotMod *pMod = CBotGlobals::getCurrentMod(); - extern ConVar rcbot_addbottime; - - char *szOVName = ""; +{ + CBotMod *pMod = CBotGlobals::getCurrentMod(); // `*pMod` Unused? [APG]RoboCop[CL] + const char *szOVName = ""; // `szOVName` Unused? [APG]RoboCop[CL] - if ( (m_iMaxBots != -1) && (CBotGlobals::numClients() >= m_iMaxBots) ) - CBotGlobals::botMessage(NULL,0,"Can't create bot, max_bots reached"); + if ( m_iMaxBots != -1 && CBotGlobals::numPlayersPlaying() >= m_iMaxBots ) + logger->Log(LogLevel::ERROR, "Can't create bot, max_bots reached"); m_flAddKickBotTime = engine->Time() + rcbot_addbottime.GetFloat(); - pBotProfile = CBotProfiles::getRandomFreeProfile(); + CBotProfile* pBotProfile; + if (rcbot_nonrandom_profile.GetBool()) { + pBotProfile = CBotProfiles::getChosenFreeProfile(); + } else { + pBotProfile = CBotProfiles::getRandomFreeProfile(); + } - if ( pBotProfile == NULL ) + if ( pBotProfile == nullptr) { - CBotGlobals::botMessage(NULL,0,"No bot profiles are free, creating a default bot..."); + logger->Log(LogLevel::WARN, "No bot profiles are free, creating a default bot..."); pBotProfile = CBotProfiles::getDefaultProfile(); - if ( pBotProfile == NULL ) + if ( pBotProfile == nullptr) return false; } - m_pNextProfile = pBotProfile; - - SET_PROFILE_DATA_INT(szClass,m_iClass); - SET_PROFILE_DATA_INT(szTeam,m_iTeam); - SET_PROFILE_STRING(szName,szOVName,m_szName); + SET_PROFILE_DATA_INT(szClass,m_iClass) + SET_PROFILE_DATA_INT(szTeam,m_iTeam) + SET_PROFILE_STRING(szName,szOVName,m_szName) - strncpy(m_szNextName,szOVName,63); - m_szNextName[63] = 0; + edict_t* pEdict = g_pBotManager->CreateBot(szOVName); - if ( CBots::controlBots() ) - { - extern ConVar bot_sv_cheats_auto; - - char cmd[128]; - memset(cmd, 0, sizeof(cmd)); - - extern ConCommandBase *puppet_bot_cmd; - - // Attempt to make puppet bot command cheat free - if ( puppet_bot_cmd != NULL ) - { - if ( /*bot_cmd_nocheats.GetBool() &&*/ puppet_bot_cmd->IsFlagSet(FCVAR_CHEAT) ) - { - int *m_nFlags = (int*)((unsigned long)puppet_bot_cmd + BOT_CONVAR_FLAGS_OFFSET); // 20 is offset to flags - //nPrevFlags = *m_nFlags; - *m_nFlags &= ~FCVAR_CHEAT; - //bChangedFlags = true; - } - } - - extern ConVar *sv_cheats; - - // const char *pparg[1]; - // pparg[0] = cmd; - - sprintf(cmd,"%s -name \"%s\"\n",BOT_ADD_PUPPET_COMMAND,szOVName); - - // CCommand *com = new CCommand(1,pparg); - - int *m_nFlags = (int*)((unsigned long)sv_cheats + BOT_CONVAR_FLAGS_OFFSET); // 20 is offset to flags - - if ( sv_cheats->IsFlagSet(FCVAR_NOTIFY) ) - *m_nFlags &= ~FCVAR_NOTIFY; - - if ( pMod->needCheatsHack() ) - sv_cheats->SetValue(1); + if ( pEdict == nullptr) + return false; - m_bControlNext = true; + return m_Bots[static_cast(slotOfEdict(pEdict))]->createBotFromEdict(pEdict, pBotProfile); +} - engine->ServerCommand(cmd); - engine->ServerExecute(); +int CBots::createDefaultBot(const char* szName) { + edict_t* pEdict = g_pBotManager->CreateBot(szName); - // ((ConCommand*)puppet_bot_cmd)->Dispatch(*com); + if (!pEdict) { + return -1; + } - if ( pMod->needCheatsHack() ) - sv_cheats->SetValue(0); + // hack: there's no way to remove names / profiles here + CBotProfile* pBotProfile = new CBotProfile(*CBotProfiles::getDefaultProfile()); + pBotProfile->m_szName = CStrings::getString(szName); - *m_nFlags |= FCVAR_NOTIFY; + int slotInt = slotOfEdict(pEdict); // Get the slot as an int - // delete com; + if (slotInt < 0) { + // Handle invalid slot case + delete pBotProfile; - return true; + return -1; } - else - { - pEdict = g_pBotManager->CreateBot( szOVName ); - if ( pEdict == NULL ) - return false; + const std::size_t slot = static_cast(slotInt); // Convert to std::size_t explicitly - return ( m_Bots[slotOfEdict(pEdict)]->createBotFromEdict(pEdict,pBotProfile) ); - } + m_Bots[slot]->createBotFromEdict(pEdict, pBotProfile); + + return slotInt; // Return the original int slot value } void CBots :: botFunction ( IBotFunction *function ) { - for ( unsigned int i = 0; i < MAX_PLAYERS; i ++ ) + for ( unsigned i = 0; i < RCBOT_MAXPLAYERS; i ++ ) { if ( m_Bots[i]->inUse() && m_Bots[i]->getEdict() ) function->execute (m_Bots[i]); } } -int CBots :: slotOfEdict ( edict_t *pEdict ) +int CBots :: slotOfEdict (const edict_t* pEdict) { return engine->IndexOfEdict(pEdict) - 1; } void CBots :: init () { - unsigned int i; - - m_Bots = new CBot*[MAX_PLAYERS]; - //m_Bots = (CBot**)malloc(sizeof(CBot*) * MAX_PLAYERS); + m_Bots = new CBot*[RCBOT_MAXPLAYERS]; + //m_Bots = (CBot**)malloc(sizeof(CBot*) * RCBOT_MAXPLAYERS); - for ( i = 0; i < MAX_PLAYERS; i ++ ) + for ( unsigned i = 0; i < RCBOT_MAXPLAYERS; i ++ ) { switch ( CBotGlobals::getCurrentMod()->getBotType() ) { + case BOTTYPE_GENERIC: + m_Bots[i] = new CBot(); + break; case BOTTYPE_DOD: m_Bots[i] = new CDODBot(); break; @@ -3282,7 +3278,7 @@ void CBots :: init () m_Bots[i] = new CBotCoop(); break; case BOTTYPE_TF2: - m_Bots[i] = new CBotTF2();//MAX_PLAYERS]; + m_Bots[i] = new CBotTF2();//[RCBOT_MAXPLAYERS]; //CBotGlobals::setEventVersion(2); break; case BOTTYPE_FF: @@ -3291,6 +3287,16 @@ void CBots :: init () case BOTTYPE_ZOMBIE: m_Bots[i] = new CBotZombie(); break; + case BOTTYPE_SYN: + m_Bots[i] = new CBotSynergy(); + break; + //case BOTTYPE_BMS: //TODO: Add Black Mesa Support [APG]RoboCop[CL] + // m_Bots[i] = new CBotBMS(); + // break; + //case BOTTYPE_NS2: + // break; + //case BOTTYPE_MAX: + // break; default: m_Bots[i] = new CBot(); break; @@ -3303,7 +3309,7 @@ int CBots :: numBots () int iCount = 0; - for ( short int i = 0; i < MAX_PLAYERS; i ++ ) + for ( short i = 0; i < RCBOT_MAXPLAYERS; i ++ ) { pBot = m_Bots[i]; @@ -3314,13 +3320,11 @@ int CBots :: numBots () return iCount; } -CBot *CBots :: findBotByProfile ( CBotProfile *pProfile ) -{ - CBot *pBot = NULL; - - for ( short int i = 0; i < MAX_PLAYERS; i ++ ) +CBot *CBots :: findBotByProfile (const CBotProfile *pProfile) +{ + for ( short i = 0; i < RCBOT_MAXPLAYERS; i ++ ) { - pBot = m_Bots[i]; + CBot* pBot = m_Bots[i]; if ( pBot->inUse() ) { @@ -3329,15 +3333,13 @@ CBot *CBots :: findBotByProfile ( CBotProfile *pProfile ) } } - return NULL; + return nullptr; } void CBots :: runPlayerMoveAll () { static CBot *pBot; - extern ConVar bot_stop; - - for ( short int i = 0; i < MAX_PLAYERS; i ++ ) + for ( short i = 0; i < RCBOT_MAXPLAYERS; i ++ ) { pBot = m_Bots[i]; @@ -3348,23 +3350,24 @@ void CBots :: runPlayerMoveAll () } } +//TODO: Experimental [APG]RoboCop[CL] +int CBots::levelInit() +{ + return 0; +} + #define CHECK_STRING(str) (((str)==NULL)?"NULL":(str)) void CBots :: botThink () { static CBot *pBot; - extern ConVar bot_stop; - extern ConVar bot_command; - - bool bBotStop = bot_stop.GetInt() > 0; + const bool bBotStop = bot_stop.GetInt() > 0; #ifdef _DEBUG - CProfileTimer *CBotsBotThink; - CProfileTimer *CBotThink; - CBotsBotThink = CProfileTimers::getTimer(BOTS_THINK_TIMER); - CBotThink = CProfileTimers::getTimer(BOT_THINK_TIMER); + CProfileTimer* CBotsBotThink = CProfileTimers::getTimer(BOTS_THINK_TIMER); + CProfileTimer* CBotThink = CProfileTimers::getTimer(BOT_THINK_TIMER); if ( CClients::clientsDebugging(BOT_DEBUG_PROFILE) ) { @@ -3373,7 +3376,7 @@ void CBots :: botThink () #endif - for ( short int i = 0; i < MAX_PLAYERS; i ++ ) + for ( short i = 0; i < RCBOT_MAXPLAYERS; i ++ ) { pBot = m_Bots[i]; @@ -3390,11 +3393,9 @@ void CBots :: botThink () #endif - g_MutexBotThink.Lock(); pBot->setMoveLookPriority(MOVELOOK_THINK); pBot->think(); pBot->setMoveLookPriority(MOVELOOK_EVENT); - g_MutexBotThink.Unlock(); #ifdef _DEBUG @@ -3405,9 +3406,12 @@ void CBots :: botThink () #endif } - if ( bot_command.GetString() && *bot_command.GetString() ) + + const char* command = bot_command.GetString(); + + if (command && *command) { - helpers->ClientCommand(pBot->getEdict(),bot_command.GetString()); + helpers->ClientCommand(pBot->getEdict(), command); // Use the cached value [APG]RoboCop[CL] bot_command.SetValue(""); } @@ -3425,93 +3429,58 @@ void CBots :: botThink () #endif - if ( (m_flAddKickBotTime < engine->Time()) && (needToAddBot () || (m_AddBotQueue.size()>0)) ) + if ( m_flAddKickBotTime < engine->Time() && needToAddBot() ) { - // lock the critical section - g_MutexAddBot.Lock(); - - if ( m_AddBotQueue.size() > 0 ) { - CAddbot newbot = m_AddBotQueue.front(); - m_AddBotQueue.pop(); - - CBotGlobals::botMessage(NULL,0,"adding bot %s %s %s",CHECK_STRING(newbot.m_szClass),CHECK_STRING(newbot.m_szTeam),CHECK_STRING(newbot.m_szBotName)); - createBot(newbot.m_szClass,newbot.m_szTeam,newbot.m_szBotName); - } else { - createBot(NULL,NULL,NULL); - } - - // unlock the critical section - g_MutexAddBot.Unlock(); + createBot(nullptr, nullptr, nullptr); } else if ( needToKickBot () ) { - kickRandomBot(); - - /*if ( m_iMaxBots >= 0 ) - { - m_iMaxBots--; - CBotGlobals::botMessage(NULL,0,"max bots changed to %d",m_iMaxBots); - }*/ + if (rcbot_nonrandom_kicking.GetBool()) { + kickChosenBot(); + } else { + kickRandomBot(); + } } } -bool CBots :: addBot ( const char *szClass, const char *szTeam, const char *szName ) +CBot* CBots::getBotPointer(const edict_t* pEdict) { - // lock the critical section - g_MutexAddBot.Lock(); + if (!pEdict) + return nullptr; - int numClients = CBotGlobals::numClients(); - int botQueueSize = m_AddBotQueue.size(); - int maxClients = gpGlobals->maxClients; + const int slot = slotOfEdict(pEdict); - bool successful = false; + if (slot < 0 || slot >= RCBOT_MAXPLAYERS) + return nullptr; - if ( (numClients + botQueueSize) < maxClients ) - { - CAddbot newbot; + CBot* pBot = m_Bots[static_cast(slot)]; - newbot.m_szClass = CStrings::getString(szClass); - newbot.m_szTeam = CStrings::getString(szTeam); - newbot.m_szBotName = CStrings::getString(szName); - - m_AddBotQueue.push(newbot); - successful = true; - } - - // unlock the critical section - g_MutexAddBot.Unlock(); + if (pBot->inUse()) + return pBot; - return successful; + return nullptr; } -CBot *CBots :: getBotPointer ( edict_t *pEdict ) +CBot* CBots::getBot(const int slot) { - int slot; - - if ( !pEdict ) - return NULL; - - slot = slotOfEdict(pEdict); - - if ( (slot < 0) || (slot >= MAX_PLAYERS) ) - return NULL; - - CBot *pBot = m_Bots[slot]; - - if ( pBot->inUse() ) + if (slot < 0 || slot >= RCBOT_MAXPLAYERS) + return nullptr; //TODO: Experimental - Return nullptr for invalid slot values [APG]RoboCop[CL] + + CBot* pBot = m_Bots[static_cast(slot)]; + if (pBot->inUse()) return pBot; - return NULL; + return nullptr; } void CBots :: freeMapMemory () { - if ( m_Bots == NULL ) + if (m_Bots == nullptr) return; //bots should have been freed when they disconnected // just incase do this - for ( short int i = 0; i < MAX_PLAYERS; i ++ ) + for ( short int i = 0; i < RCBOT_MAXPLAYERS; i ++ ) { if ( m_Bots[i] ) m_Bots[i]->freeMapMemory(); @@ -3520,26 +3489,26 @@ void CBots :: freeMapMemory () void CBots :: freeAllMemory () { - if ( m_Bots == NULL ) + if (m_Bots == nullptr) return; - for ( short int i = 0; i < MAX_PLAYERS; i ++ ) + for ( short i = 0; i < RCBOT_MAXPLAYERS; i ++ ) { - if ( m_Bots[i] != NULL ) + if (m_Bots[i] != nullptr) { m_Bots[i]->freeAllMemory(); delete m_Bots[i]; - m_Bots[i] = NULL; + m_Bots[i] = nullptr; } } delete[] m_Bots; - m_Bots = NULL; + m_Bots = nullptr; } void CBots :: roundStart () { - for ( short int i = 0; i < MAX_PLAYERS; i ++ ) + for ( short i = 0; i < RCBOT_MAXPLAYERS; i ++ ) { if ( m_Bots[i]->inUse() ) m_Bots[i]->spawnInit(); @@ -3553,150 +3522,219 @@ void CBots :: mapInit () bool CBots :: needToAddBot () { - int iClients = CBotGlobals::numClients(); + if (rcbot_bot_quota_interval.GetFloat() > 0.0f) { + return false; + } + + const int iClients = CBotGlobals::numPlayersPlaying(); + const int iBots = CBots::numBots(); - return (((m_iMinBots!=-1)&&(CBots::numBots() < m_iMinBots)) || ((iClients < m_iMaxBots)&&(m_iMaxBots!=-1))); + if ((m_iMinBots!=-1 && iBots < m_iMinBots) || (iClients < m_iMaxBots && m_iMaxBots != -1)) { + return true; + } + + return false; } bool CBots :: needToKickBot () { + if (rcbot_bot_quota_interval.GetFloat() > 0.0f) { + return false; + } + + const int iClients = CBotGlobals::numPlayersPlaying(); + const int iBots = CBots::numBots(); + if ( m_flAddKickBotTime < engine->Time() ) { - if ( ((m_iMinBots != -1 ) && (CBots::numBots() <= m_iMinBots)) ) + if ( m_iMinBots != -1 && iBots <= m_iMinBots ) return false; - if ( (m_iMaxBots > 0 ) && (CBotGlobals::numClients() > m_iMaxBots) ) + if ( m_iMaxBots > 0 && iClients > m_iMaxBots ) { return true; + } } return false; } -void CBots :: kickRandomBot () +void CBots :: kickChosenBot (const unsigned count) { - dataUnconstArray list; - int index; - CBot *tokick; - char szCommand[512]; - //gather list of bots - for ( short int i = 0; i < MAX_PLAYERS; i ++ ) - { + std::vector botList; + //gather list of bots + for ( unsigned i = 0; i < RCBOT_MAXPLAYERS; i ++ ) + { if ( m_Bots[i]->inUse() ) - list.Add(i); - } + botList.emplace_back(m_Bots[i]); + } - if ( list.IsEmpty() ) - { - CBotGlobals::botMessage(NULL,0,"kickRandomBot() : No bots to kick"); - return; - } + if ( botList.empty() ) + { + logger->Log(LogLevel::DEBUG, "kickChosenBot() : No bots to kick"); + return; + } - index = list.Random(); - list.Clear(); - - tokick = m_Bots[index]; + int team; + int teamA = CBotGlobals::numPlayersOnTeam(2,false); + int teamB = CBotGlobals::numPlayersOnTeam(3,false); + + unsigned numBotsKicked = 0; - sprintf(szCommand,"kickid %d\n",tokick->getPlayerID()); + while (numBotsKicked < count && !botList.empty()) { + // check numBotsOnTeam in case all the remaining bots are on the smaller team + if ((teamA > teamB) && (CBotGlobals::numBotsOnTeam(2,false) > 0)) { + team = 2; + } else if ((teamA < teamB) && (CBotGlobals::numBotsOnTeam(3,false) > 0)) { + team = 3; + } else { + team = 0; + } - m_flAddKickBotTime = engine->Time() + 2.0f; + CBot* pBot = nullptr; + for (CBot* tBot : botList) { + if ((team < 2) || (tBot->getTeam() == team)) { + if ((pBot == nullptr) || ( pBot->getCreateTime() < tBot->getCreateTime() )) + pBot = tBot; + } + } - engine->ServerCommand(szCommand); + if (pBot == nullptr) { + logger->Log(LogLevel::DEBUG, "kickChosenBot() : No bot to kick"); + return; + } + + if (pBot->getTeam() == 2) + teamA--; + else if (pBot->getTeam() == 3) + teamB--; + + char szCommand[512]; + + snprintf(szCommand, sizeof(szCommand), "kickid %d\n", pBot->getPlayerID()); + engine->ServerCommand(szCommand); + + botList.erase(std::remove(botList.begin(), botList.end(), pBot), + botList.end()); + + numBotsKicked++; + } + + m_flAddKickBotTime = engine->Time() + 2.0f; } -void CBots :: kickRandomBotOnTeam ( int team ) +void CBots :: kickRandomBot (const unsigned count) { - dataUnconstArray list; - int index; - CBot *tokick; - char szCommand[512]; + std::vector botList; //gather list of bots - for ( short int i = 0; i < MAX_PLAYERS; i ++ ) + for ( unsigned i = 0; i < RCBOT_MAXPLAYERS; i ++ ) { if ( m_Bots[i]->inUse() ) - { - if ( m_Bots[i]->getTeam() == team ) - list.Add(i); - } + botList.emplace_back(m_Bots[i]->getPlayerID()); } - if ( list.IsEmpty() ) + if ( botList.empty() ) { - CBotGlobals::botMessage(NULL,0,"kickRandomBotOnTeam() : No bots to kick"); + logger->Log(LogLevel::DEBUG, "kickRandomBot() : No bots to kick"); return; } - index = list.Random(); - list.Clear(); - - tokick = m_Bots[index]; - - sprintf(szCommand,"kickid %d\n",tokick->getPlayerID()); + std::shuffle( botList.begin(), botList.end(), std::mt19937(std::random_device()())); - m_flAddKickBotTime = engine->Time() + 2.0f; + // std::random_shuffle was removed in C++17 + // std::random_shuffle ( botList.begin(), botList.end() ); - engine->ServerCommand(szCommand); + //std::random_device rd; + //std::mt19937 g(rd()); + //std::shuffle(botList.begin(), botList.end(), g); + + unsigned numBotsKicked = 0; + while (numBotsKicked < count && !botList.empty()) { + char szCommand[512]; + + snprintf(szCommand, sizeof(szCommand), "kickid %d\n", botList.back()); + engine->ServerCommand(szCommand); + numBotsKicked++; + + botList.pop_back(); + } + + m_flAddKickBotTime = engine->Time() + 2.0f; } -//////////////////////// -bool CBots :: handlePlayerJoin ( edict_t *pEdict, const char *name ) +void CBots::kickChosenBotOnTeam(const int team) { - static int botnum; + std::vector botList; + //gather list of bots + for ( unsigned i = 0; i < RCBOT_MAXPLAYERS; i ++ ) + { + if ( m_Bots[i]->inUse() && m_Bots[i]->getTeam() == team) + botList.emplace_back(m_Bots[i]); + } - if ( m_bControlNext && - ((strcmp(&name[strlen(name)-strlen(m_szNextName)],m_szNextName) == 0) || (sscanf(name,"Bot%d",&botnum) == 1)) ) + if ( botList.empty() ) { - m_ControlQueue.push(pEdict); - m_bControlNext = false; + logger->Log(LogLevel::DEBUG, "kickChosenBotOnTeam() : No bots to kick"); + return; + } - return true; + CBot* pBot = nullptr; + for (CBot* tBot : botList) { + if ((pBot == nullptr) || ( pBot->getCreateTime() < tBot->getCreateTime() )) + pBot = tBot; } - return false; + char szCommand[512]; + + snprintf(szCommand, sizeof(szCommand), "kickid %d\n", pBot->getPlayerID()); + engine->ServerCommand(szCommand); + + m_flAddKickBotTime = engine->Time() + 2.0f; } -void CBots :: handleAutomaticControl () +void CBots::kickRandomBotOnTeam(const int team) { - if ( !m_ControlQueue.empty() ) - { - edict_t *pEdict = (edict_t*)m_ControlQueue.front(); - - IPlayerInfo *p = playerinfomanager->GetPlayerInfo(pEdict); + std::vector botList; + char szCommand[512]; - // wait until fake client flag is set - if ( p && p->IsFakeClient() ) + //gather list of bots + for (short int i = 0; i < RCBOT_MAXPLAYERS; i++) + { + if (m_Bots[i]->inUse() && m_Bots[i]->getTeam() == team) { - // until it has an 'unknown' remove from queue and create bot - if ( pEdict->GetUnknown() ) - { - //extern ConVar rcbot_runplayercmd; - - m_ControlQueue.pop(); + botList.emplace_back(m_Bots[i]->getPlayerID()); + } + } - //HookPlayerRunCommand(pEdict); + if (botList.empty()) + { + logger->Log(LogLevel::DEBUG, "kickRandomBotOnTeam() : No bots to kick"); + return; + } - //engine->SetFakeClientConVarValue( pEdict, "name",m_pNextProfile->getName() ); + const std::size_t botListSize = botList.size(); // Use std::size_t for size - m_Bots[slotOfEdict(pEdict)]->createBotFromEdict(pEdict,m_pNextProfile); - } - } - + if (botListSize > 0) { + const int index = randomInt(0, static_cast(botListSize) - 1); + snprintf(szCommand, sizeof(szCommand), "kickid %d\n", botList[static_cast(index)]); } -} + m_flAddKickBotTime = engine->Time() + 2.0f; + engine->ServerCommand(szCommand); +} +//////////////////////// -CBotLastSee :: CBotLastSee ( edict_t *pEdict ) +CBotLastSee :: CBotLastSee ( edict_t *pEdict ) : m_pLastSee(pEdict) { - m_pLastSee = pEdict; update(); } void CBotLastSee :: update () { - if ( (m_pLastSee.get() == NULL) || !CBotGlobals::entityIsAlive(m_pLastSee) ) + if ( m_pLastSee.get() == nullptr || !CBotGlobals::entityIsAlive(m_pLastSee) ) { m_fLastSeeTime = 0.0f; - m_pLastSee = NULL; + m_pLastSee = nullptr; } else { @@ -3706,14 +3744,14 @@ void CBotLastSee :: update () } } -bool CBotLastSee :: hasSeen ( float fTime ) +bool CBotLastSee :: hasSeen (const float fTime) { - return (m_pLastSee.get() != NULL) && ((m_fLastSeeTime + fTime) > engine->Time()); + return m_pLastSee.get() != nullptr && m_fLastSeeTime + fTime > engine->Time(); } -Vector CBotLastSee :: getLocation () +Vector CBotLastSee :: getLocation () const { - return (m_vLastSeeLoc + m_vLastSeeVel); + return m_vLastSeeLoc + m_vLastSeeVel; } //MyEHandle m_pLastSee; // edict diff --git a/utils/RCBot2_meta/bot.h b/utils/RCBot2_meta/bot.h index a01f63d3f..8d65a56fd 100644 --- a/utils/RCBot2_meta/bot.h +++ b/utils/RCBot2_meta/bot.h @@ -40,8 +40,10 @@ #ifndef __RCBOT2_H__ #define __RCBOT2_H__ +#include //#include "cbase.h" //#include "baseentity.h" +#include "toolframework/itoolentity.h" #include "filesystem.h" #include "interface.h" #include "engine/iserverplugin.h" @@ -58,170 +60,75 @@ #endif #include "igameevents.h" #include "Color.h" +class CBasePlayer; // forward declaration required by imovehelper.h (included by usercmd.h) -caxanga334 #include "usercmd.h" #include "bot_utility.h" #include "bot_const.h" #include "bot_ehandle.h" + #include +#include +#include -#if defined WIN32 && !defined snprintf +#if defined(_WIN64) || defined(_WIN32) && !defined snprintf #define snprintf _snprintf #endif -using namespace std; - #define MAX_AMMO_TYPES 32 -#define MAX_VOICE_CMDS 32 -#define MIN_WPT_TOUCH_DIST 16.0f + +constexpr int MAX_VOICE_CMDS = 32; +constexpr float MIN_WPT_TOUCH_DIST = 16.0f; // Interfaces from the engine -//using namespace VEngineServerV21; -//using namespace ServerGameClientsV3; extern IVEngineServer *engine; // helper functions (messaging clients, loading content, making entities, running commands, etc) extern IFileSystem *filesystem; // file I/O -//extern IGameEventManager *gameeventmanager; // game events interface extern IGameEventManager2 *gameeventmanager; extern IPlayerInfoManager *playerinfomanager; // game dll interface to interact with players extern IServerPluginHelpers *helpers; // special 3rd party plugin helpers from the engine extern IServerGameClients* gameclients; extern IEngineTrace *enginetrace; -extern IEffects *g_pEffects; +extern IEffects *g_pEffects; //Redundant? [APG]RoboCopCL] extern IBotManager *g_pBotManager; extern CGlobalVars *gpGlobals; -#define GET_HEALTH 0 -#define GET_TEAM 1 -#define GET_AMMO 2 +enum : std::uint8_t +{ + GET_HEALTH = 0, + GET_TEAM = 1, + GET_AMMO = 2, + T_OFFSETMAX = 3 +}; -#define T_OFFSETMAX 3 +// use a fixed bitset for all the conditions in bot_const.h +using ConditionBitSet = std::bitset; class CBotSquad; +// static function bool BotFunc_BreakableIsEnemy ( edict_t *pBreakable, edict_t *pEdict ); -//----------------------------------------------------------------------------- -// Purpose: This is a backward compatible IServerGameDLL -//----------------------------------------------------------------------------- -abstract_class IServerGameDLL_004 +// TODO: this is from game/server/util.h, remove once we can get it included +// Misc useful +inline bool FStrEq(const char *sz1, const char *sz2) { -public: - // Initialize the game (one-time call when the DLL is first loaded ) - // Return false if there is an error during startup. - virtual bool DLLInit( CreateInterfaceFn engineFactory, - CreateInterfaceFn physicsFactory, - CreateInterfaceFn fileSystemFactory, - CGlobalVars *pGlobals) = 0; - - // This is called when a new game is started. (restart, map) - virtual bool GameInit( void ) = 0; - - // Called any time a new level is started (after GameInit() also on level transitions within a game) - virtual bool LevelInit( char const *pMapName, - char const *pMapEntities, char const *pOldLevel, - char const *pLandmarkName, bool loadGame, bool background ) = 0; - - // The server is about to activate - virtual void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax ) = 0; - - // The server should run physics/think on all edicts - virtual void GameFrame( bool simulating ) = 0; - - // Called once per simulation frame on the final tick - virtual void PreClientUpdate( bool simulating ) = 0; - - // Called when a level is shutdown (including changing levels) - virtual void LevelShutdown( void ) = 0; - // This is called when a game ends (server disconnect, death, restart, load) - // NOT on level transitions within a game - virtual void GameShutdown( void ) = 0; - - // Called once during DLL shutdown - virtual void DLLShutdown( void ) = 0; - - // Get the simulation interval (must be compiled with identical values into both client and game .dll for MOD!!!) - // Right now this is only requested at server startup time so it can't be changed on the fly, etc. - virtual float GetTickInterval( void ) const = 0; - - // Give the list of datatable classes to the engine. The engine matches class names from here with - // edict_t::classname to figure out how to encode a class's data for networking - virtual ServerClass* GetAllServerClasses( void ) = 0; - - // Returns string describing current .dll. e.g., TeamFortress 2, Half-Life 2. - // Hey, it's more descriptive than just the name of the game directory - virtual const char *GetGameDescription( void ) = 0; - - // Let the game .dll allocate it's own network/shared string tables - virtual void CreateNetworkStringTables( void ) = 0; - - // Save/restore system hooks - virtual CSaveRestoreData *SaveInit( int size ) = 0; - virtual void SaveWriteFields( CSaveRestoreData *, const char *, void *, datamap_t *, typedescription_t *, int ) = 0; - virtual void SaveReadFields( CSaveRestoreData *, const char *, void *, datamap_t *, typedescription_t *, int ) = 0; - virtual void SaveGlobalState( CSaveRestoreData * ) = 0; - virtual void RestoreGlobalState( CSaveRestoreData * ) = 0; - virtual void PreSave( CSaveRestoreData * ) = 0; - virtual void Save( CSaveRestoreData * ) = 0; - virtual void GetSaveComment( char *comment, int maxlength, float flMinutes, float flSeconds, bool bNoTime = false ) = 0; - virtual void WriteSaveHeaders( CSaveRestoreData * ) = 0; - virtual void ReadRestoreHeaders( CSaveRestoreData * ) = 0; - virtual void Restore( CSaveRestoreData *, bool ) = 0; - virtual bool IsRestoring() = 0; - - // Returns the number of entities moved across the transition - virtual int CreateEntityTransitionList( CSaveRestoreData *, int ) = 0; - // Build the list of maps adjacent to the current map - virtual void BuildAdjacentMapList( void ) = 0; - - // Retrieve info needed for parsing the specified user message - virtual bool GetUserMessageInfo( int msg_type, char *name, int maxnamelength, int& size ) = 0; - - // Hand over the StandardSendProxies in the game DLL's module. - virtual CStandardSendProxies* GetStandardSendProxies() = 0; - - // Called once during startup, after the game .dll has been loaded and after the client .dll has also been loaded - virtual void PostInit() = 0; - // Called once per frame even when no level is loaded... - virtual void Think( bool finalTick ) = 0; - -#ifdef _XBOX - virtual void GetTitleName( const char *pMapName, char* pTitleBuff, int titleBuffSize ) = 0; -#endif - - virtual void PreSaveGameLoaded( char const *pSaveName, bool bCurrentlyInGame ) = 0; - - // Returns true if the game DLL wants the server not to be made public. - // Used by commentary system to hide multiplayer commentary servers from the master. - virtual bool ShouldHideServer( void ) = 0; - - virtual void InvalidateMdlCache() = 0; - - // * This function is new with version 6 of the interface. - // - // This is called when a query from IServerPluginHelpers::StartQueryCvarValue is finished. - // iCookie is the value returned by IServerPluginHelpers::StartQueryCvarValue. - // Added with version 2 of the interface. - virtual void OnQueryCvarValueFinished( QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue ) = 0; - - // Called after the steam API has been activated post-level startup - virtual void GameServerSteamAPIActivated( void ) = 0; - - virtual void GameServerSteamAPIShutdown( void ) = 0; -}; + return sz1 == sz2 || Q_stricmp(sz1, sz2) == 0; +} /////////// Voice commands class IBotFunction { public: + virtual ~IBotFunction() = default; virtual void execute ( CBot *pBot ) = 0; }; class CBroadcastVoiceCommand : public IBotFunction { public: - CBroadcastVoiceCommand (edict_t *pPlayer, byte voicecmd) { m_pPlayer = pPlayer; m_VoiceCmd = voicecmd; }; - void execute ( CBot *pBot ); + CBroadcastVoiceCommand (edict_t *pPlayer, const byte voicecmd) { m_pPlayer = pPlayer; m_VoiceCmd = voicecmd; } + void execute ( CBot *pBot ) override; private: edict_t *m_pPlayer; @@ -261,35 +168,36 @@ class CRCBotEventListener : public IGameEventListener2 //extern IVDebugOverlay *debugoverlay; +class CBotButtons; +class CBotGAValues; +//class CBotMemoryNode; +//class CBotMemoryPop; +class CBotNeuralNet; +class CBotProfile; +class CBotSchedules; +class CBotStuckValues; class CBotVisibles; +class CBotWeapon; +class CBotWeapons; class CFindEnemyFunc; -class IBotNavigator; -class CBotMemoryNode; -class CBotMemoryPop; class CGA; class CPerceptron; -class CBotSchedules; -class CBotGAValues; -class CBotStuckValues; -class CBotButtons; -class IBotNavigator; -class CFindEnemyFunc; -class CBotWeapons; -class CBotProfile; +class CTrainingSet; class CWaypoint; -class CBotWeapon; class CWeapon; -class CBotNeuralNet; -class CTrainingSet; +class IBotNavigator; -#define MOVELOOK_DEFAULT 0 -#define MOVELOOK_THINK 1 -#define MOVELOOK_MODTHINK 2 -#define MOVELOOK_TASK 3 -#define MOVELOOK_LISTEN 4 -#define MOVELOOK_EVENT 5 -#define MOVELOOK_ATTACK 6 -#define MOVELOOK_OVERRIDE 6 +enum : std::uint8_t +{ + MOVELOOK_DEFAULT = 0, + MOVELOOK_THINK = 1, + MOVELOOK_MODTHINK = 2, + MOVELOOK_TASK = 3, + MOVELOOK_LISTEN = 4, + MOVELOOK_EVENT = 5, + MOVELOOK_ATTACK = 6, + MOVELOOK_OVERRIDE = 6 +}; class CBotLastSee { @@ -299,9 +207,9 @@ class CBotLastSee reset(); } - inline void reset () + void reset () { - m_pLastSee = NULL; // edict + m_pLastSee = nullptr; // edict m_fLastSeeTime = 0.0f; // time } @@ -309,14 +217,14 @@ class CBotLastSee void update (); - inline bool check ( edict_t *pEdict ) + bool check (const edict_t *pEdict) { - return (pEdict == (m_pLastSee.get())); + return pEdict == m_pLastSee.get(); } bool hasSeen ( float fTime ); - Vector getLocation (); + Vector getLocation () const; private: MyEHandle m_pLastSee; // edict float m_fLastSeeTime; // time @@ -347,7 +255,7 @@ class CBotSquads void freeMapMemory() { - unsigned int i; + unsigned i; for ( i = 0; i < m_theSquads.size(); i ++ ) m_theSquads[i].freeMapMemory(); @@ -369,7 +277,7 @@ class CBotSquad void addMember ( edict_t *pMember ) { - m_Members.push_back(MyEHandle(pMember)); + m_Members.emplace_back(MyEHandle(pMember)); } void think () @@ -379,7 +287,7 @@ class CBotSquad m_Leader = NULL; // find a new leader - unsigned int i; + unsigned i; for ( i = 0; i < m_Members.size(); i ++ ) { @@ -403,51 +311,57 @@ class CBotSquad class CBot { public: + virtual ~CBot() = default; - static const float m_fAttackLowestHoldTime; + static const float m_fAttackLowestHoldTime; static const float m_fAttackHighestHoldTime; static const float m_fAttackLowestLetGoTime; static const float m_fAttackHighestLetGoTime; CBot(); - inline void clearFailedWeaponSelect () { m_iPrevWeaponSelectFailed = 0; } - inline void failWeaponSelect () { m_iPrevWeaponSelectFailed ++; } + void clearFailedWeaponSelect () { m_iPrevWeaponSelectFailed = 0; } + void failWeaponSelect () { m_iPrevWeaponSelectFailed ++; } - void debugMsg ( int iLev, const char *szMsg ); + void debugMsg ( int iLev, const char *szMsg ) const; - virtual unsigned int maxEntityIndex ( ) { return MAX_PLAYERS; } + virtual unsigned maxEntityIndex ( ) { return RCBOT_MAXPLAYERS; } // linux fix 1 virtual void onInventoryApplication (){} - - + // return distance from this origin - int isDesiredClass ( int iclass ) + int isDesiredClass (const int iClass) const { - return m_iDesiredClass == iclass; + return m_iDesiredClass == iClass; } virtual void handleWeapons (); - inline Vector getOrigin () - { + Vector getOrigin () const + { return m_pController->GetLocalOrigin(); } + // linux fix 2 - inline float distanceFrom(Vector vOrigin) - { + float distanceFrom(const Vector& vOrigin) const + { return (vOrigin - m_pController->GetLocalOrigin()).Length(); } - inline float distanceFrom(edict_t *pEntity) - { + + float distanceFrom(edict_t *pEntity) const + { return (pEntity->GetCollideable()->GetCollisionOrigin() - m_pController->GetLocalOrigin()).Length(); //return distanceFrom(CBotGlobals::entityOrigin(pEntity)); } - - inline float distanceFrom2D(edict_t *pEntity) + float distanceFrom2D(const Vector& vOrigin) const { + return (vOrigin - m_pController->GetLocalOrigin()).Length2D(); + } + + float distanceFrom2D(edict_t *pEntity) const + { return (pEntity->GetCollideable()->GetCollisionOrigin() - m_pController->GetLocalOrigin()).Length2D(); //return distanceFrom(CBotGlobals::entityOrigin(pEntity)); } @@ -478,61 +392,65 @@ class CBot virtual int getTeam (); - bool isUnderWater ( ); + float getCreateTime() const + { + return m_fTimeCreated; + } - CBotWeapon *getBestWeapon ( edict_t *pEnemy, bool bAllowMelee = true, bool bAllowMeleeFallback = true, bool bMeleeOnly = false, bool bExplosivesOnly = false ); + bool isUnderWater ( ) const; - virtual void modThink () { return; } + CBotWeapon *getBestWeapon ( edict_t *pEnemy, bool bAllowMelee = true, bool bAllowMeleeFallback = true, bool bMeleeOnly = false, bool bExplosivesOnly = false ) const; + + virtual void modThink () { + } virtual bool isEnemy ( edict_t *pEdict, bool bCheckWeapons = true ) { return false; } - inline bool hasSomeConditions ( int iConditions ) - { - return (m_iConditions & iConditions) > 0; + bool hasSomeConditions (const int iConditions) const + { + return (m_iConditions & static_cast(iConditions)).any(); } virtual bool handleAttack ( CBotWeapon *pWeapon, edict_t *pEnemy ); - float DotProductFromOrigin ( Vector pOrigin ); + float DotProductFromOrigin (const Vector& pOrigin ) const; bool FVisible ( edict_t *pEdict, bool bCheckHead = false ); + bool isVisible (const edict_t *pEdict ) const; - bool isVisible ( edict_t *pEdict ); - - inline void setEnemy ( edict_t *pEnemy ) + void setEnemy ( edict_t *pEnemy ) { m_pEnemy = pEnemy; } - inline int getConditions () - { - return m_iConditions; + int getConditions () const + { + static_assert(NUM_CONDITIONS <= std::numeric_limits::digits, "Condition bitset is larger than int"); + return static_cast(m_iConditions.to_ulong()); } - inline bool hasAllConditions ( int iConditions ) - { - return (m_iConditions & iConditions) == iConditions; + bool hasAllConditions (const int iConditions) const + { + return (m_iConditions & static_cast(iConditions)) == iConditions; } - inline void updateCondition ( int iCondition ) + void updateCondition (const int iCondition) { m_iConditions |= iCondition; } - inline void removeCondition ( int iCondition ) + void removeCondition (const int iCondition) { m_iConditions &= ~iCondition; } - bool FInViewCone ( edict_t *pEntity ); + bool FInViewCone ( edict_t *pEntity ) const; /* * make bot start the gmae, e.g join a team first */ virtual bool startGame (); - virtual bool checkStuck (); - virtual void currentlyDead (); /* @@ -543,54 +461,51 @@ class CBot /* * returns true if bot is used in game */ - inline bool inUse () - { - return (m_bUsed && (m_pEdict!=NULL)); + bool inUse () const + { + return m_bUsed && m_pEdict!= nullptr; } - edict_t *getEdict (); + edict_t *getEdict () const; void setEdict ( edict_t *pEdict); - bool FVisible ( Vector &vOrigin, edict_t *pDest = NULL ); + bool FVisible (const Vector &vOrigin, edict_t *pDest = nullptr) const; - Vector getEyePosition (); + Vector getEyePosition () const; void think (); - virtual void friendlyFire( edict_t *pEdict ) { }; + virtual void friendlyFire( edict_t *pEdict ) {} virtual void freeMapMemory (); - virtual void freeAllMemory (); /////////////////////////////// - inline bool moveToIsValid () - { + bool moveToIsValid () const + { return m_bMoveToIsValid; } - inline bool lookAtIsValid () - { + bool lookAtIsValid () const + { return m_bLookAtIsValid; } - inline Vector getMoveTo () + Vector getMoveTo() const { return m_vMoveTo; } - inline bool moveFailed () + bool moveFailed () { - bool ret = m_bFailNextMove; + const bool ret = m_bFailNextMove; m_bFailNextMove = false; return ret; } - void selectWeaponSlot ( int iSlot ); - edict_t *getAvoidEntity () { return m_pAvoidEntity; } void setAvoidEntity ( edict_t *pEntity ) { m_pAvoidEntity = pEntity; } @@ -599,11 +514,11 @@ class CBot virtual bool canAvoid ( edict_t *pEntity ); - inline bool hasEnemy () { return m_pEnemy && hasSomeConditions(CONDITION_SEE_CUR_ENEMY); } - inline edict_t *getEnemy () { return m_pEnemy; } + bool hasEnemy () { return m_pEnemy && hasSomeConditions(CONDITION_SEE_CUR_ENEMY); } + edict_t *getEnemy () { return m_pEnemy; } - inline void setMoveTo ( Vector vNew ) + void setMoveTo ( const Vector& vNew ) { if ( m_iMoveLookPriority >= m_iMovePriority ) { @@ -614,7 +529,7 @@ class CBot } // this allows move speed to be changed in tasks - inline void setMoveSpeed ( float fNewSpeed ) + void setMoveSpeed (const float fNewSpeed) { if ( m_iMoveLookPriority >= m_iMoveSpeedPriority ) { @@ -623,16 +538,16 @@ class CBot } } - void findEnemy ( edict_t *pOldEnemy = NULL ); + void findEnemy ( edict_t *pOldEnemy = nullptr); virtual void enemyFound ( edict_t *pEnemy ); virtual void checkDependantEntities (); - inline IBotNavigator *getNavigator () { return m_pNavigator; } + IBotNavigator *getNavigator () const { return m_pNavigator; } - inline void setMoveLookPriority ( int iPriority ) { m_iMoveLookPriority = iPriority; } + void setMoveLookPriority (const int iPriority) { m_iMoveLookPriority = iPriority; } - inline void stopMoving () + void stopMoving () { if ( m_iMoveLookPriority >= m_iMovePriority ) { @@ -643,7 +558,7 @@ class CBot } } - inline void stopLooking () + void stopLooking () { if ( m_iMoveLookPriority >= m_iLookPriority ) { @@ -652,9 +567,9 @@ class CBot } } - inline void setLookAtTask ( eLookTask lookTask, float fTime = 0 ) + void setLookAtTask (const eLookTask lookTask, const float fTime = 0) { - if ( (m_iMoveLookPriority >= m_iLookPriority) && ((fTime > 0) || ( m_fLookSetTime < engine->Time())) ) + if ( m_iMoveLookPriority >= m_iLookPriority && (fTime > 0 || m_fLookSetTime < engine->Time()) ) { m_iLookPriority = m_iMoveLookPriority; m_iLookTask = lookTask; @@ -664,7 +579,7 @@ class CBot } } - virtual void enemyLost (edict_t *pEnemy) {}; + virtual void enemyLost (edict_t *pEnemy) {} void setLastEnemy (edict_t *pEnemy); @@ -674,47 +589,48 @@ class CBot updateCondition(CONDITION_ENEMY_DEAD); if ( pEnemy == m_pLastEnemy ) { - m_pLastEnemy = NULL; + m_pLastEnemy = nullptr; } } ////////////////////// virtual bool isCSS () { return false; } virtual bool isHLDM () { return false; } virtual bool isTF () { return false; } + virtual bool isSYN () { return false; } virtual void spawnInit (); - QAngle eyeAngles (); + QAngle eyeAngles () const; virtual bool isAlive (); - bool onLadder (); + bool onLadder () const; - inline bool currentEnemy ( edict_t *pEntity ) { return m_pEnemy == pEntity; } + bool currentEnemy ( edict_t *pEntity ) { return m_pEnemy == pEntity; } Vector getAimVector ( edict_t *pEntity ); virtual void modAim ( edict_t *pEntity, Vector &v_origin, Vector *v_desired_offset, Vector &v_size, float fDist, float fDist2D); - inline Vector *getGoalOrigin () + Vector *getGoalOrigin () { return &m_vGoal; } - inline bool hasGoal () - { + bool hasGoal () const + { return m_bHasGoal; } - bool isHoldingPrimaryAttack(); + bool isHoldingPrimaryAttack() const; - void primaryAttack ( bool bHold=false, float fTime =0.0f ); - void secondaryAttack(bool bHold=false); - void jump (); - void duck ( bool hold = false ); - void use (); - void reload(); + void primaryAttack (bool bHold=false, float fTime =0.0f) const; + void secondaryAttack(bool bHold=false, float fTime = 0.0f) const; + void jump () const; + void duck (bool hold = false) const; + void use () const; + void reload() const; virtual bool setVisible ( edict_t *pEntity, bool bVisible ); @@ -723,50 +639,54 @@ class CBot virtual void shotmiss (); //inline void setAvoidEntity (edict_t *pEntity) { m_pAvoidEntity = pEntity; }; - int getPlayerID (); // return player ID on server - int getHealth (); + int getPlayerID () const; // return player ID on server + int getHealth () const; - float getHealthPercent (); + float getHealthPercent () const; - inline CBotSchedules *getSchedule () { return m_pSchedules; } + CBotSchedules *getSchedule () const { return m_pSchedules; } virtual void reachedCoverSpot (int flags); virtual bool wantToFollowEnemy (); - virtual void seeFriendlyHurtEnemy ( edict_t *pTeammate, edict_t *pEnemy, CWeapon *pWeapon ) { }; - virtual void seeEnemyHurtFriendly ( edict_t *pTeammate, edict_t *pEnemy, CWeapon *pWeapon ) { }; - virtual void seeFriendlyDie ( edict_t *pDied, edict_t *pKiller, CWeapon *pWeapon ) { }; - virtual void seeFriendlyKill ( edict_t *pTeamMate, edict_t *pDied, CWeapon *pWeapon ) { }; + virtual void seeFriendlyHurtEnemy ( edict_t *pTeammate, edict_t *pEnemy, CWeapon *pWeapon ) {} + virtual void seeEnemyHurtFriendly ( edict_t *pTeammate, edict_t *pEnemy, CWeapon *pWeapon ) {} + virtual void seeFriendlyDie ( edict_t *pDied, edict_t *pKiller, CWeapon *pWeapon ) {} + virtual void seeFriendlyKill ( edict_t *pTeamMate, edict_t *pDied, CWeapon *pWeapon ) {} - inline void selectWeapon ( int iWeaponId ) { m_iSelectWeapon = iWeaponId; } + void selectWeapon (const int iWeaponId ) { m_iSelectWeapon = iWeaponId; } - void selectWeaponName ( const char *szWeaponName ); + void selectWeaponName ( const char *szWeaponName ) const; virtual CBotWeapon *getCurrentWeapon(); - void kill (); + void kill () const; - bool isUsingProfile ( CBotProfile *pProfile ); + bool isUsingProfile (const CBotProfile *pProfile ) const; - inline CBotProfile *getProfile () { return m_pProfile; } + CBotProfile *getProfile () const { return m_pProfile; } - virtual bool canGotoWaypoint ( Vector vPrevWaypoint, CWaypoint *pWaypoint, CWaypoint *pPrev = NULL ); + virtual bool canGotoWaypoint (const Vector& vPrevWaypoint, CWaypoint* pWaypoint, CWaypoint* pPrev = nullptr); + + void updatePosition() const; - void tapButton ( int iButton ); + void tapButton ( int iButton ) const; - inline int getAmmo ( int iIndex ) { if ( !m_iAmmo ) return 0; else if ( iIndex == -1 ) return 0; return m_iAmmo[iIndex]; } + int getAmmo(const std::size_t iIndex) const { + if (!m_iAmmo) return 0; + if (iIndex == static_cast(-1)) return 0; // Ensure this check is meaningful + return m_iAmmo[iIndex]; + } - inline void lookAtEdict ( edict_t *pEdict ) { m_pLookEdict = pEdict; } + void lookAtEdict ( edict_t *pEdict ) { m_pLookEdict = pEdict; } virtual bool select_CWeapon ( CWeapon *pWeapon ); virtual bool selectBotWeapon ( CBotWeapon *pBotWeapon ); - void updatePosition (); - MyEHandle m_pLookEdict; - CBotWeapons *getWeapons () { return m_pWeapons; } + CBotWeapons *getWeapons () const { return m_pWeapons; } virtual float getEnemyFactor ( edict_t *pEnemy ); @@ -774,47 +694,46 @@ class CBot virtual void touchedWpt ( CWaypoint *pWaypoint, int iNextWaypoint = -1, int iPrevWaypoint = -1 ); - inline void setAiming ( Vector aiming ) { m_vWaypointAim = aiming; } + void setAiming (const Vector& aiming) { m_vWaypointAim = aiming; } - inline Vector getAiming () { return m_vWaypointAim; } + Vector getAiming() const { return m_vWaypointAim; } - inline void setLookVector ( Vector vLook ) { m_vLookVector = vLook; } + void setLookVector (const Vector& vLook) { m_vLookVector = vLook; } - inline Vector getLookVector () { return m_vLookVector; } + Vector getLookVector() const { return m_vLookVector; } - inline void resetLookAroundTime () { m_fLookAroundTime = 0.0f; } + void resetLookAroundTime () { m_fLookAroundTime = 0.0f; } - Vector snipe ( Vector &vAiming ); + Vector snipe (const Vector& vAiming); //inline void dontAvoid () { m_fAvoidTime = engine->Time() + 1.0f; } float m_fWaypointStuckTime; - inline float getSpeed () { return m_vVelocity.Length2D(); } + float getSpeed () const { return m_vVelocity.Length2D(); } void updateStatistics (); // updates number of teammates/enemies nearby/visible virtual void listenForPlayers (); // listens to this player - void listenToPlayer (edict_t *pListenTo, bool bIsEnemy = false, bool bIsAttacking = false ); + void listenToPlayer (edict_t *pPlayer, bool bIsEnemy = false, bool bIsAttacking = false ); virtual bool wantToListenToPlayerAttack ( edict_t *pPlayer, int iWeaponID = -1 ) { return true; } virtual bool wantToListenToPlayerFootsteps ( edict_t *pPlayer ) { return true; } virtual bool wantToInvestigateSound (); - inline void wantToInvestigateSound ( bool bSet ) { m_bWantToInvestigateSound = bSet; } - inline bool wantToShoot ( void ) { return m_bOpenFire; } - inline void wantToShoot ( bool bSet ) { m_bOpenFire = bSet; } - inline void wantToListen ( bool bSet ) { m_bWantToListen = bSet; } - bool wantToListen (); - inline void wantToChangeWeapon ( bool bSet ) { m_bWantToChangeWeapon = bSet; } + void wantToInvestigateSound (const bool bSet) { m_bWantToInvestigateSound = bSet; } + bool wantToShoot () const { return m_bOpenFire; } + void wantToShoot (const bool bSet) { m_bOpenFire = bSet; } + void wantToListen (const bool bSet) { m_bWantToListen = bSet; } + bool wantToListen () const; + void wantToChangeWeapon (const bool bSet) { m_bWantToChangeWeapon = bSet; } int nearbyFriendlies (float fDistance); - bool isFacing ( Vector vOrigin ); + bool isFacing (const Vector& vOrigin) const; - bool isOnLift (void); + bool isOnLift () const; virtual bool isDOD () { return false; } - virtual bool isTF2 () { return false; } // return an enemy sentry gun / special visible (e.g.) for quick checking - voffset is the 'head' @@ -822,28 +741,31 @@ class CBot void updateDanger ( float fBelief ); - inline void reduceTouchDistance ( ) { if ( m_fWaypointTouchDistance > MIN_WPT_TOUCH_DIST ) { m_fWaypointTouchDistance *= 0.9; } } + void reduceTouchDistance() + { + if (m_fWaypointTouchDistance > MIN_WPT_TOUCH_DIST) { m_fWaypointTouchDistance *= 0.9f; } + } - inline void resetTouchDistance ( float fDist ) { m_fWaypointTouchDistance = fDist; } + void resetTouchDistance (const float fDist) { m_fWaypointTouchDistance = fDist; } - inline float getTouchDistance () { return m_fWaypointTouchDistance; } + float getTouchDistance () const { return m_fWaypointTouchDistance; } - inline CBotCmd *getUserCMD () { return &cmd; } + CBotCmd *getUserCMD () { return &cmd; } - void forceGotoWaypoint ( int wpt ); + void forceGotoWaypoint ( int wpt ) const; // bot is defending -- mod specific stuff virtual void defending () {} - virtual void hearVoiceCommand ( edict_t *pPlayer, byte cmd ) {}; + virtual void hearVoiceCommand ( edict_t *pPlayer, byte voiceCmd ); virtual void grenadeThrown (); - virtual void voiceCommand ( int cmd ) { }; + virtual void voiceCommand (byte voiceCmd); - void addVoiceCommand ( int cmd ); + void addVoiceCommand (byte voiceCmd); - void letGoOfButton ( int button ); + void letGoOfButton ( int button ) const; virtual bool overrideAmmoTypes () { return true; } @@ -855,29 +777,29 @@ class CBot virtual void areaClear( ) { } - inline void resetAreaClear () { m_uSquadDetail.b1.said_area_clear = false; } + void resetAreaClear () { m_uSquadDetail.b1.said_area_clear = false; } - inline bool inSquad ( CBotSquad *pSquad ) - { + bool inSquad (const CBotSquad *pSquad) const + { return m_pSquad == pSquad; } - inline bool inSquad ( void ) - { - return m_pSquad != NULL; + bool inSquad () const + { + return m_pSquad != nullptr; } - bool isSquadLeader ( void ); + bool isSquadLeader () const; - inline void setSquadIdleTime ( float fTime ) + void setSquadIdleTime (const float fTime) { m_fSquadIdleTime = fTime; } void clearSquad (); - inline void setSquad ( CBotSquad *pSquad ) + void setSquad ( CBotSquad *pSquad ) { m_pSquad = pSquad; } @@ -886,16 +808,16 @@ class CBot virtual void sayInPosition() { } virtual void sayMoveOut() { } - bot_statistics_t *getStats() { if ( m_bStatsCanUse ) return &m_StatsCanUse; return NULL; } + bot_statistics_t *getStats() { if ( m_bStatsCanUse ) return &m_StatsCanUse; return nullptr; } virtual void hearPlayerAttack( edict_t *pAttacker, int iWeaponID ); - inline bool isListeningToPlayer ( edict_t *pPlayer ) + bool isListeningToPlayer (const edict_t *pPlayer) { - return (m_PlayerListeningTo.get() == pPlayer); + return m_PlayerListeningTo.get() == pPlayer; } - inline IBotController *getController () const + IBotController *getController () const { return m_pController; } @@ -907,15 +829,14 @@ class CBot return false; } - bool recentlyHurt ( float fTime ); + bool recentlyHurt ( float fTime ) const; - eBotAction getCurrentUtil ( void ) { return m_CurrentUtil;} + eBotAction getCurrentUtil () const { return m_CurrentUtil;} - bool recentlySpawned ( float fTime ); + bool recentlySpawned ( float fTime ) const; protected: - - inline void setLookAt ( Vector vNew ) + void setLookAt (const Vector& vNew) { m_vLookAt = vNew; m_bLookAtIsValid = true; @@ -924,7 +845,6 @@ class CBot static void checkEntity ( edict_t **pEdict ); ///////////////////////// void doMove (); - void doLook (); virtual void getLookAtVector (); @@ -932,14 +852,13 @@ class CBot void doButtons (); ///////////////////////// - void changeAngles ( float fSpeed, float *fIdeal, float *fCurrent, float *fUpdate ); + void changeAngles (float fSpeed, const float* fIdeal, float* fCurrent, float* fUpdate); // look for new tasks - virtual void getTasks (unsigned int iIgnore=0); - + virtual void getTasks (unsigned iIgnore=0); // really only need 249 bits (32 bytes) + WEAPON_SUBTYPE_BITS (whatever that is) - static const int CMD_BUFFER_SIZE = 64; + static constexpr int CMD_BUFFER_SIZE = 64; /////////////////////////////////// // bots edict edict_t *m_pEdict; @@ -974,7 +893,7 @@ class CBot float m_fAvoidTime; /////////////////////////////////// // current impulse command - int m_iImpulse; + byte m_iImpulse; // buttons held int m_iButtons; // bots forward move speed @@ -1011,7 +930,8 @@ class CBot int m_iAccumulatedDamage; int m_iPrevHealth; /////////////////////////////////// - int m_iConditions; + ConditionBitSet m_iConditions; + // bot tasks etc -- complex actuators CBotSchedules *m_pSchedules; // buttons held -- simple actuators @@ -1085,7 +1005,7 @@ class CBot MyEHandle m_PlayerListeningTo; float m_fWantToListenTime; bool m_bOpenFire; - unsigned int m_iPrevWeaponSelectFailed; + unsigned m_iPrevWeaponSelectFailed; bool m_bWantToListen; float m_fListenFactor; // the current weight of bots listening vector (higher = better) @@ -1097,7 +1017,7 @@ class CBot float m_fAvoidSideSwitch; float m_fHealClickTime; - unsigned int m_iSpecialVisibleId; + int m_iSpecialVisibleId; float m_fCurrentDanger; float m_fLastHurtTime; @@ -1109,7 +1029,7 @@ class CBot //CBotNeuralNet *stucknet; //CTrainingSet *stucknet_tset; - queue m_nextVoicecmd; + std::queue m_nextVoicecmd; float m_fNextVoiceCommand; float m_fLastVoiceCommand[MAX_VOICE_CMDS]; @@ -1133,21 +1053,10 @@ class CBot bool m_bIncreaseSensitivity; float m_fSpawnTime; bool m_bWantToInvestigateSound; -}; - -class CAddbot -{ - -public: - CAddbot () - { - memset(this,sizeof(CAddbot),0); - }; - - const char *m_szClass; - const char *m_szTeam; - const char *m_szBotName; + float m_fEnemyAimLerp; + float m_fEnemyAimLerpTime; + Vector m_vEnemyAimLerpVelocity; }; class CBots @@ -1155,63 +1064,58 @@ class CBots public: static void botThink (); - static CBot *getBotPointer ( edict_t *pEdict ); + static CBot *getBotPointer (const edict_t *pEdict ); + static CBot *getBot ( int slot ); static void freeMapMemory (); - static void freeAllMemory (); - static CBot *findBotByProfile ( CBotProfile *pProfile ); + static CBot *findBotByProfile (const CBotProfile *pProfile ); static void init (); - static void controlBotSetup ( bool m_bSetting ) { m_bControlBotsOnly = m_bSetting; } - - // If true, then a puppet bot must be added to be controlled - static bool controlBots () { return m_bControlBotsOnly; } - static bool controlBot ( edict_t *pEdict ); - static bool controlBot ( const char *szOldName, const char *szName, const char *szTeam, const char *szClass ); static bool createBot (const char *szClass, const char *szTeam, const char *szName); + static int createDefaultBot(const char* szName); static int numBots (); - static bool handlePlayerJoin ( edict_t *pEdict, const char *name ); - - static int slotOfEdict ( edict_t *pEdict ); + static int slotOfEdict (const edict_t* pEdict); static void roundStart (); - static void kickRandomBot (); - + static void kickChosenBot (unsigned count = 1); + static void kickRandomBot (unsigned count = 1); + static void kickChosenBotOnTeam ( int team ); static void kickRandomBotOnTeam ( int team ); static void mapInit (); static bool needToAddBot (); - static bool needToKickBot (); - static void setMaxBots ( int iMax ) { m_iMaxBots = iMax; } - + static void setMaxBots (const int iMax) { m_iMaxBots = iMax; } static int getMaxBots () { return m_iMaxBots; } - static void setMinBots ( int iMin ) { m_iMinBots = iMin; } - + static void setMinBots (const int iMin) { m_iMinBots = iMin; } static int getMinBots () { return m_iMinBots; } - static void botFunction ( IBotFunction *function ); + static float getAddKickBotTime() { return m_flAddKickBotTime; } - static void handleAutomaticControl (); + static void botFunction ( IBotFunction *function ); static void runPlayerMoveAll (); - static bool addBot ( const char *szClass, const char *szTeam, const char *szName ); + static CBot* get(const std::size_t iIndex) { return m_Bots[iIndex]; } - static CBot *get ( int iIndex ) { return m_Bots[iIndex]; } - static CBot *get ( edict_t *pPlayer ) { return m_Bots[slotOfEdict(pPlayer)]; } + static CBot* get(const edict_t* pPlayer) + { + return m_Bots[static_cast(slotOfEdict(pPlayer))]; + } + + static int levelInit(); //TODO: Not implemented? [APG]RoboCop[CL] private: static CBot **m_Bots; @@ -1220,108 +1124,36 @@ class CBots static int m_iMaxBots; static int m_iMinBots; - // Workaround for add bot bug - // - static bool m_bControlBotsOnly; - static bool m_bControlNext; - static CBotProfile *m_pNextProfile; - static char m_szNextName[64]; - // End - workaround - // add or kick bot time static float m_flAddKickBotTime; - - static queue m_ControlQueue; - - static queue m_AddBotQueue; - }; -class IEntityFactoryDictionary; -class IClientEntity; -class CBaseAnimating; -class ITempEntsSystem; -class CTakeDamageInfo; -//----------------------------------------------------------------------------- -// Purpose: Interface from engine to tools for manipulating entities -//----------------------------------------------------------------------------- -class IServerTools : public IBaseInterface +// this is yoinked from server/util.h +abstract_class IEntityFactory { +protected: + ~IEntityFactory() = default; + public: - virtual IServerEntity *GetIServerEntity( IClientEntity *pClientEntity ) = 0; - virtual bool SnapPlayerToPosition( const Vector &org, const QAngle &ang, IClientEntity *pClientPlayer = NULL ) = 0; - virtual bool GetPlayerPosition( Vector &org, QAngle &ang, IClientEntity *pClientPlayer = NULL ) = 0; - virtual bool SetPlayerFOV( int fov, IClientEntity *pClientPlayer = NULL ) = 0; - virtual int GetPlayerFOV( IClientEntity *pClientPlayer = NULL ) = 0; - virtual bool IsInNoClipMode( IClientEntity *pClientPlayer = NULL ) = 0; - - // entity searching - virtual CBaseEntity *FirstEntity( void ) = 0; - virtual CBaseEntity *NextEntity( CBaseEntity *pEntity ) = 0; - virtual CBaseEntity *FindEntityByHammerID( int iHammerID ) = 0; - - // entity query - virtual bool GetKeyValue( CBaseEntity *pEntity, const char *szField, char *szValue, int iMaxLen ) = 0; - virtual bool SetKeyValue( CBaseEntity *pEntity, const char *szField, const char *szValue ) = 0; - virtual bool SetKeyValue( CBaseEntity *pEntity, const char *szField, float flValue ) = 0; - virtual bool SetKeyValue( CBaseEntity *pEntity, const char *szField, const Vector &vecValue ) = 0; - - // entity spawning - virtual CBaseEntity *CreateEntityByName( const char *szClassName ) = 0; - virtual void DispatchSpawn( CBaseEntity *pEntity ) = 0; - - // This reloads a portion or all of a particle definition file. - // It's up to the server to decide if it cares about this file - // Use a UtlBuffer to crack the data - virtual void ReloadParticleDefintions( const char *pFileName, const void *pBufData, int nLen ) = 0; - - virtual void AddOriginToPVS( const Vector &org ) = 0; - virtual void MoveEngineViewTo( const Vector &vPos, const QAngle &vAngles ) = 0; - - virtual bool DestroyEntityByHammerId( int iHammerID ) = 0; - virtual CBaseEntity *GetBaseEntityByEntIndex( int iEntIndex ) = 0; - virtual void RemoveEntity( CBaseEntity *pEntity ) = 0; - virtual void RemoveEntityImmediate( CBaseEntity *pEntity ) = 0; - virtual IEntityFactoryDictionary *GetEntityFactoryDictionary( void ) = 0; - - virtual void SetMoveType( CBaseEntity *pEntity, int val ) = 0; - virtual void SetMoveType( CBaseEntity *pEntity, int val, int moveCollide ) = 0; - virtual void ResetSequence( CBaseAnimating *pEntity, int nSequence ) = 0; - virtual void ResetSequenceInfo( CBaseAnimating *pEntity ) = 0; - - virtual void ClearMultiDamage( void ) = 0; - virtual void ApplyMultiDamage( void ) = 0; - virtual void AddMultiDamage( const CTakeDamageInfo &pTakeDamageInfo, CBaseEntity *pEntity ) = 0; - virtual void RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrc, float flRadius, int iClassIgnore, CBaseEntity *pEntityIgnore ) = 0; - - virtual ITempEntsSystem *GetTempEntsSystem( void ) = 0; + // TODO: Investigate why making this destructor virtual causes a crash - [APG]RoboCop[CL] + //virtual ~IEntityFactory() = default; //Unstable + virtual IServerNetworkable *Create( const char *pClassName ) = 0; + virtual void Destroy( IServerNetworkable *pNetworkable ) = 0; + virtual unsigned GetEntitySize() = 0; }; -typedef IServerTools IServerTools001; - -#define VSERVERTOOLS_INTERFACE_VERSION_1 "VSERVERTOOLS001" -#define VSERVERTOOLS_INTERFACE_VERSION "VSERVERTOOLS002" -#define VSERVERTOOLS_INTERFACE_VERSION_INT 2 - -void DrawLine ( const Vector &origin, const Vector &target, int r, int g, int b, bool noDepthTest, float duration ); - -void WriteUsercmd( bf_write *buf, CUserCmd *cmd ); -// useful helper funcs... -//int RANDOM_INT(int min, int max); -// Misc useful -inline bool FStrEq(const char *sz1, const char *sz2) +abstract_class IEntityFactoryDictionary { - return ( sz1 == sz2 || Q_stricmp(sz1, sz2) == 0 ); -} -//edict_t* INDEXENT( int iEdictNum ); -// get entity index -//int ENTINDEX( edict_t *pEdict ); -float VectorDistance(Vector &vec); -int Ceiling ( float fVal ); -bool FNullEnt(const edict_t* pent); -// ?? -//#define SAFE_STRCPY (to,from,siz)\ -// strncpy(to,from,siz-1);\ -// to[siz-1] = 0; +protected: + ~IEntityFactoryDictionary() = default; + +public: + //virtual ~IEntityFactoryDictionary() = default; + virtual void InstallFactory( IEntityFactory *pFactory, const char *pClassName ) = 0; + virtual IServerNetworkable *Create( const char *pClassName ) = 0; + virtual void Destroy( const char *pClassName, IServerNetworkable *pNetworkable ) = 0; + virtual IEntityFactory *FindFactory( const char *pClassName ) = 0; + virtual const char *GetCannonicalName( const char *pClassName ) = 0; +}; #endif // __RCBOT2_H__ diff --git a/utils/RCBot2_meta/bot_accessclient.cpp b/utils/RCBot2_meta/bot_accessclient.cpp index d33651c69..e19b8e8b4 100644 --- a/utils/RCBot2_meta/bot_accessclient.cpp +++ b/utils/RCBot2_meta/bot_accessclient.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -33,43 +35,45 @@ #include "bot_accessclient.h" #include "bot_globals.h" +#include "rcbot/logging.h" + +#include #include -using namespace std; /////////// -vector CAccessClients :: m_Clients; +std::vector CAccessClients :: m_Clients; /////////// -CAccessClient :: CAccessClient( char *szSteamId, int iAccessLevel ) +CAccessClient :: CAccessClient(const char *szSteamID, const int iAccessLevel) { m_iAccessLevel = iAccessLevel; - m_szSteamId = CStrings::getString(szSteamId); + m_szSteamID = CStrings::getString(szSteamID); } -bool CAccessClient :: forBot () +bool CAccessClient :: forBot () const { - return isForSteamId("BOT"); + return isForSteamID("BOT"); } -bool CAccessClient :: isForSteamId ( const char *szSteamId ) +bool CAccessClient :: isForSteamID (const char *szSteamID) const { - CBotGlobals::botMessage(NULL, 0, "AccessClient: '%s','%s'", m_szSteamId, szSteamId); - return FStrEq(m_szSteamId,szSteamId); + logger->Log(LogLevel::DEBUG, "AccessClient: '%s','%s'", m_szSteamID, szSteamID); + return FStrEq(m_szSteamID,szSteamID); } -void CAccessClient :: save ( FILE *fp ) +void CAccessClient::save(std::fstream& fp) const { - fprintf(fp,"\"%s\":%d\n",m_szSteamId,m_iAccessLevel); + fp << '"' << m_szSteamID << '"' << ":" << m_iAccessLevel << "\n"; } -void CAccessClient :: giveAccessToClient ( CClient *pClient ) +void CAccessClient :: giveAccessToClient ( CClient *pClient ) const { // notify player if ( !forBot() ) CBotGlobals::botMessage(pClient->getPlayer(),0,"%s authenticated for bot commands",pClient->getName()); // notify server - CBotGlobals::botMessage(NULL,0,"%s authenticated for bot commands",pClient->getName()); + logger->Log(LogLevel::INFO, "%s authenticated for bot commands", pClient->getName()); pClient->setAccessLevel(m_iAccessLevel); } @@ -78,21 +82,14 @@ void CAccessClient :: giveAccessToClient ( CClient *pClient ) void CAccessClients :: showUsers ( edict_t *pEntity ) { - CAccessClient *pPlayer; - CClient *pClient; - CBotGlobals::botMessage(pEntity,0,"showing users..."); if ( m_Clients.empty() ) - CBotGlobals::botMessage(NULL,0,"showUsers() : No users to show"); + logger->Log(LogLevel::DEBUG, "showUsers() : No users to show"); - for ( unsigned int i = 0; i < m_Clients.size(); i ++ ) + for (const CAccessClient* pPlayer : m_Clients) { - pPlayer = m_Clients[i]; - - pClient = CClients::findClientBySteamID(pPlayer->getSteamID()); - - if ( pClient ) + if ( const CClient* pClient = CClients::findClientBySteamID(pPlayer->getSteamID()) ) CBotGlobals::botMessage(pEntity,0,"[ID: %s]/[AL: %d] (currently playing as : %s)\n",pPlayer->getSteamID(),pPlayer->getAccessLevel(),pClient->getName()); else CBotGlobals::botMessage(pEntity,0,"[ID: %s]/[AL: %d]\n",pPlayer->getSteamID(),pPlayer->getAccessLevel()); @@ -100,41 +97,12 @@ void CAccessClients :: showUsers ( edict_t *pEntity ) } } -void CAccessClients :: createFile () -{ - char filename[1024]; - - CBotGlobals::buildFileName(filename,BOT_ACCESS_CLIENT_FILE,BOT_CONFIG_FOLDER,BOT_CONFIG_EXTENSION); - - FILE *fp = CBotGlobals::openFile(filename,"w"); - - CBotGlobals::botMessage(NULL,0,"Making an accessclients.ini file for you... Edit it in %s",filename); - - if ( fp ) - { - fprintf(fp,"# format is "); - fprintf(fp,"# \"\" \n"); - fprintf(fp,"# see http://rcbot.bots-united.com/accesslev.htm for access\n"); - fprintf(fp,"# levels\n"); - fprintf(fp,"#\n"); - fprintf(fp,"# example:\n"); - fprintf(fp,"#\n"); - fprintf(fp,"# \"STEAM_0:123456789\" 63\n"); - fprintf(fp,"# don't put one of '#' these before a line you want to be read \n"); - fprintf(fp,"# by the bot!\n"); - fprintf(fp,"# \n"); - fclose(fp); - } - else - CBotGlobals::botMessage(NULL,0,"Error! Couldn't create config file %s",filename); -} - void CAccessClients :: freeMemory () { - for ( unsigned int i = 0; i < m_Clients.size(); i ++ ) + for (CAccessClient*& m_Client : m_Clients) { - delete m_Clients[i]; - m_Clients[i] = NULL; + delete m_Client; + m_Client = nullptr; } m_Clients.clear(); @@ -146,22 +114,15 @@ void CAccessClients :: load () CBotGlobals::buildFileName(filename,BOT_ACCESS_CLIENT_FILE,BOT_CONFIG_FOLDER,BOT_CONFIG_EXTENSION); - FILE *fp = CBotGlobals::openFile(filename,"r"); - - if ( fp ) + if ( std::fstream fp = CBotGlobals::openFile(filename, std::fstream::in) ) { char buffer[256]; - char szSteamId[32]; - int iAccess; - - int i; - int len; - int n; + char szSteamID[32]; int iLine = 0; - while ( fgets(buffer,255,fp) != NULL ) + while (fp.getline(buffer, 255)) { iLine++; @@ -176,20 +137,20 @@ void CAccessClients :: load () if ( buffer[0] == '#' ) continue; - len = strlen(buffer); + const std::size_t len = std::strlen(buffer); - i = 0; + std::size_t i = 0; while (( i < len ) && ((buffer[i] == '\"') || (buffer[i] == ' '))) i++; - n = 0; + unsigned n = 0; // parse Steam ID while ( (n<31) && (i < len) && (buffer[i] != '\"') ) - szSteamId[n++] = buffer[i++]; + szSteamID[n++] = buffer[i++]; - szSteamId[n] = 0; + szSteamID[n] = 0; i++; @@ -198,31 +159,31 @@ void CAccessClients :: load () if ( i == len ) { - CBotGlobals::botMessage(NULL,0,"line %d invalid in access client config, missing access level",iLine); + logger->Log(LogLevel::WARN, "line %d invalid in access client config, missing access level", iLine); continue; // invalid } - iAccess = atoi(&buffer[i]); + const int iAccess = std::atoi(&buffer[i]); // invalid - if ( (szSteamId[0] == 0) || (szSteamId[0] == ' ' ) ) + if ( (szSteamID[0] == 0) || (szSteamID[0] == ' ' ) ) { - CBotGlobals::botMessage(NULL,0,"line %d invalid in access client config, steam id invalid",iLine); + logger->Log(LogLevel::WARN, "line %d invalid in access client config, steam id invalid", iLine); continue; } if ( iAccess == 0 ) { - CBotGlobals::botMessage(NULL,0,"line %d invalid in access client config, access level can't be 0",iLine); + logger->Log(LogLevel::WARN, "line %d invalid in access client config, access level can't be 0", iLine); continue; } - m_Clients.push_back(new CAccessClient(szSteamId,iAccess)); + m_Clients.emplace_back(new CAccessClient(szSteamID,iAccess)); } - - fclose(fp); } else - CAccessClients :: createFile(); + { + logger->Log(LogLevel::ERROR, "Failed to open file '%s' for reading", filename); + } } void CAccessClients :: save () @@ -231,26 +192,24 @@ void CAccessClients :: save () CBotGlobals::buildFileName(filename,BOT_ACCESS_CLIENT_FILE,BOT_CONFIG_FOLDER,BOT_CONFIG_EXTENSION); - FILE *fp = CBotGlobals::openFile(filename,"w"); - - if ( fp ) + if ( std::fstream fp = CBotGlobals::openFile(filename, std::fstream::out) ) { - for ( unsigned int i = 0; i < m_Clients.size(); i ++ ) + for (CAccessClient* const& m_Client : m_Clients) { - m_Clients[i]->save(fp); + m_Client->save(fp); } - - fclose(fp); + } + else + { + logger->Log(LogLevel::ERROR, "Failed to open file '%s' for writing", filename); } } void CAccessClients :: checkClientAccess ( CClient *pClient ) { - for ( unsigned int i = 0; i < m_Clients.size(); i ++ ) + for (const CAccessClient* pAC : m_Clients) { - CAccessClient *pAC = m_Clients[i]; - - if ( pAC->isForSteamId(pClient->getSteamID()) ) + if ( pAC->isForSteamID(pClient->getSteamID()) ) pAC->giveAccessToClient(pClient); } } diff --git a/utils/RCBot2_meta/bot_accessclient.h b/utils/RCBot2_meta/bot_accessclient.h index 9b03ca260..77437b4dc 100644 --- a/utils/RCBot2_meta/bot_accessclient.h +++ b/utils/RCBot2_meta/bot_accessclient.h @@ -33,28 +33,27 @@ #define __BOT_ACCESS_CLIENT_H__ #include -using namespace std; #include "bot_client.h" class CAccessClient { public: - CAccessClient( char *szSteamId, int iAccessLevel ); + CAccessClient( const char *szSteamID, int iAccessLevel ); - bool isForSteamId ( const char *szSteamId ); + bool isForSteamID ( const char *szSteamID ) const; - void giveAccessToClient ( CClient *pClient ); + void giveAccessToClient ( CClient *pClient ) const; - void save ( FILE *fp ); + void save (std::fstream &fp) const; - bool forBot (); + bool forBot () const; - inline char *getSteamID () { return m_szSteamId; } + char *getSteamID () const { return m_szSteamID; } - inline int getAccessLevel () { return m_iAccessLevel; } + int getAccessLevel () const { return m_iAccessLevel; } private: - char *m_szSteamId; + char *m_szSteamID; int m_iAccessLevel; }; @@ -70,10 +69,8 @@ class CAccessClients static void save (); static void checkClientAccess ( CClient *pClient ); - - static void createFile (); // create file if it doesn't exist (and mention of creation etc) private: - static vector m_Clients; + static std::vector m_Clients; }; #endif diff --git a/utils/RCBot2_meta/bot_baseentity_hack.h b/utils/RCBot2_meta/bot_baseentity_hack.h deleted file mode 100644 index 847d5232d..000000000 --- a/utils/RCBot2_meta/bot_baseentity_hack.h +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef __BOT_BASEENTITY_HACK_H__ -#define __BOT_BASEENTITY_HACK_H__ - -struct PVSInfo_t -{ - // number of clusters or -1 if too many - int m_nClusterCount; - - // cluster indices - int m_pClusters[ MAX_ENT_CLUSTERS ]; - - // headnode for the entity's bounding box - int m_nHeadNode; - - // For dynamic "area portals" - int m_nAreaNum; - int m_nAreaNum2; - - // current position - float m_vCenter[3]; -}; - -class CServerNetworkProperty : public IServerNetworkable, public IEventRegisterCallback -{ -public: - DECLARE_CLASS_NOBASE( CServerNetworkProperty ); - -public: - CServerNetworkProperty(); - virtual ~CServerNetworkProperty(); - -public: -// IServerNetworkable implementation. - virtual IHandleEntity *GetEntityHandle( ); - virtual int GetEFlags() const; - virtual void AddEFlags( int iEFlags ); - virtual edict_t *GetEdict() const; - virtual CBaseNetworkable* GetBaseNetworkable(); - virtual CBaseEntity* GetBaseEntity(); - virtual ServerClass* GetServerClass(); - virtual const char* GetClassName() const; - virtual void Release(); - virtual int AreaNum() const; - virtual PVSInfo_t* GetPVSInfo(); - -public: - // Other public methods - void Init( CBaseEntity *pEntity ); - - void AttachEdict( edict_t *pRequiredEdict = NULL ); - - // Methods to get the entindex + edict - int entindex() const; - edict_t *edict(); - const edict_t *edict() const; - - // Sets the edict pointer (for swapping edicts) - void SetEdict( edict_t *pEdict ); - - // All these functions call through to CNetStateMgr. - // See CNetStateMgr for details about these functions. - void NetworkStateForceUpdate(); - void NetworkStateChanged(); - - // This is useful for entities that don't change frequently or that the client - // doesn't need updates on very often. If you use this mode, the server will only try to - // detect state changes every N seconds, so it will save CPU cycles and bandwidth. - // - // Note: N must be less than AUTOUPDATE_MAX_TIME_LENGTH. - // - // Set back to zero to disable the feature. - // - // This feature works on top of manual mode. - // - If you turn it on and manual mode is off, it will autodetect changes every N seconds. - // - If you turn it on and manual mode is on, then every N seconds it will only say there - // is a change if you've called NetworkStateChanged. - void SetUpdateInterval( float N ); - - // You can use this to override any entity's ShouldTransmit behavior. - // void SetTransmitProxy( CBaseTransmitProxy *pProxy ); - - // This version does a PVS check which also checks for connected areas - bool IsInPVS( const CCheckTransmitInfo *pInfo ); - - // This version doesn't do the area check - bool IsInPVS( const edict_t *pRecipient, const void *pvs, int pvssize ); - - // Called by the timed event manager when it's time to detect a state change. - virtual void FireEvent(); - -private: - // Detaches the edict.. should only be called by CBaseNetworkable's destructor. - void DetachEdict(); - CBaseEntity *GetOuter(); - - // Recomputes PVS information - void RecomputePVSInformation(); - - // Marks the networkable that it will should transmit - void SetTransmit( CCheckTransmitInfo *pInfo ); - -private: - CBaseEntity *m_pOuter; - // CBaseTransmitProxy *m_pTransmitProxy; - edict_t *m_pPev; - PVSInfo_t m_PVSInfo; - - // Counters for SetUpdateInterval. - CEventRegister m_TimerEvent; - bool m_bPendingStateChange; - -// friend class CBaseTransmitProxy; -}; - -// IServerNetworkable is the interface the engine uses for all networkable data. -class IServerNetworkable -{ -// These functions are handled automatically by the server_class macros and CBaseNetworkable. -public: - // Gets at the entity handle associated with the collideable - virtual IHandleEntity *GetEntityHandle() = 0; - - // Tell the engine which class this object is. - virtual ServerClass* GetServerClass() = 0; - - // Return a combo of the EFL_ flags. - virtual int GetEFlags() const = 0; - virtual void AddEFlags( int iEFlags ) = 0; - - virtual edict_t *GetEdict() const = 0; - - virtual const char* GetClassName() const = 0; - virtual void Release() = 0; - - virtual int AreaNum() const = 0; - - // In place of a generic QueryInterface. - virtual CBaseNetworkable* GetBaseNetworkable() = 0; - virtual CBaseEntity* GetBaseEntity() = 0; // Only used by game code. - virtual PVSInfo_t* GetPVSInfo() = 0; // get current visibilty data - -protected: - // Should never call delete on this! - virtual ~IServerNetworkable() {} -}; - - -#endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_belief.h b/utils/RCBot2_meta/bot_belief.h index e8b69f5a7..cb587a65a 100644 --- a/utils/RCBot2_meta/bot_belief.h +++ b/utils/RCBot2_meta/bot_belief.h @@ -31,11 +31,11 @@ #ifndef __RCBOT_BELIEF_H__ #define __RCBOT_BELIEF_H__ -typedef enum +typedef enum : std::uint8_t { BELIEF_NONE = 0, - BELIEF_DANGER = (1<<0), - BELIEF_SAFETY = (1<<1) + BELIEF_DANGER = 1<<0, + BELIEF_SAFETY = 1<<1 }BotBelief; #endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_black_mesa.cpp b/utils/RCBot2_meta/bot_black_mesa.cpp new file mode 100644 index 000000000..28b05f69f --- /dev/null +++ b/utils/RCBot2_meta/bot_black_mesa.cpp @@ -0,0 +1,123 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +/* + * This file is part of RCBot. + * + * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. + * + * RCBot is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * RCBot is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RCBot; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + */ + +#include + +#include "bot.h" +#include "bot_black_mesa.h" +#include "bot_buttons.h" +#include "bot_globals.h" +#include "bot_profile.h" +#include "bot_mtrand.h" + + //caxanga334: SDK 2013 contains macros for std::min and std::max which causes errors when compiling +//#if SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_BMS +#include "valve_minmax_off.h" +//#endif + +void CBotBMS::init(const bool bVarInit) +{ + CBot::init(bVarInit); +} + +void CBotBMS::setup() +{ + CBot::setup(); +} + +bool CBotBMS::startGame() +{ + return true; +} + +void CBotBMS::killed(edict_t* pVictim) +{ + return; +} + +void CBotBMS::died(edict_t* pKiller, const char* pszWeapon) +{ + spawnInit(); + + if (randomInt(0, 1)) + m_pButtons->attack(); +} + +void CBotBMS::spawnInit() +{ + CBot::spawnInit(); +} + +bool CBotBMS::isEnemy(edict_t* pEdict, bool bCheckWeapons) +{ + if (!pEdict) + return false; + + if (pEdict == m_pEdict) + return false; + + if (!ENTINDEX(pEdict)) + return false; + + /*if (ENTINDEX(pEdict) > CBotGlobals::maxClients()) // monster + { + const char* cname = pEdict->GetNetworkable()->GetClassName(); + + if (std::strncmp("monster_", cname, 8) == 0) + { + if (std::strcmp(cname, "monster_barney") == 0) + return false; + if (std::strcmp(cname, "monster_scientist") == 0) + return false; + if (std::strcmp(cname, "monster_gman") == 0) + return false; + if (std::strcmp(cname, "monster_furniture") == 0) + return false; + + return true; + } + }*/ + + if (CBotGlobals::getTeamplayOn()) + { + if (CBotGlobals::getTeam(pEdict) == getTeam()) + return false; + } + + return true; +} + +void CBotBMS::modThink() +{ + // find weapons and neat stuff +} \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_black_mesa.h b/utils/RCBot2_meta/bot_black_mesa.h new file mode 100644 index 000000000..47d810aff --- /dev/null +++ b/utils/RCBot2_meta/bot_black_mesa.h @@ -0,0 +1,59 @@ +/* + * This file is part of RCBot. + * + * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. + * + * RCBot is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * RCBot is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RCBot; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + */ +#ifndef __BMS_RCBOT_H__ +#define __BMS_RCBOT_H__ + +#include "bot.h" // Ensure this header is included for the CBot base class + + // Bot for Black Mesa +class CBotBMS : public CBot +{ +public: + // Check if this is a Black Mesa bot + static bool isBMS() { return true; } + + // Override virtual functions from CBot + void modThink() override; + void init(bool bVarInit = false) override; + void setup() override; + bool startGame() override; + void died(edict_t* pKiller, const char* pszWeapon) override; + void spawnInit() override; + bool isEnemy(edict_t* pEdict, bool bCheckWeapons = true) override; + + // Static function to handle when a bot kills another entity + static void killed(edict_t* pVictim); + +private: + // Add any private members or methods here +}; + +#endif // __BMS_RCBOT_H__ diff --git a/utils/RCBot2_meta/bot_botprofile.h b/utils/RCBot2_meta/bot_botprofile.h deleted file mode 100644 index 1baf9c3a6..000000000 --- a/utils/RCBot2_meta/bot_botprofile.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is part of RCBot. - * - * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. - * - * RCBot is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * RCBot is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with RCBot; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * In addition, as a special exception, the author gives permission to - * link the code of this program with the Half-Life Game Engine ("HL - * Engine") and Modified Game Libraries ("MODs") developed by Valve, - * L.L.C ("Valve"). You must obey the GNU General Public License in all - * respects for all of the code used other than the HL Engine and MODs - * from Valve. If you modify this file, you may extend this exception - * to your version of the file, but you are not obligated to do so. If - * you do not wish to do so, delete this exception statement from your - * version. - * - */ -#ifndef __BOT_BOTPROFILE_H__ -#define __BOT_BOTPROFILE_H__ - -class CBotProfile -{ -public: - CBotProfile () - { - - } -private: - -}; - -#endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_buttons.cpp b/utils/RCBot2_meta/bot_buttons.cpp index 52d2d5c13..152904de2 100644 --- a/utils/RCBot2_meta/bot_buttons.cpp +++ b/utils/RCBot2_meta/bot_buttons.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -32,22 +34,22 @@ #include "bot_buttons.h" #include "in_buttons.h" -void CBotButtons :: attack (float fFor, float fFrom) +void CBotButtons :: attack (const float fFor, const float fFrom) const { - holdButton(IN_ATTACK,fFrom,fFor,0.1); + holdButton(IN_ATTACK,fFrom,fFor,0.1f); } -void CBotButtons :: jump (float fFor, float fFrom) +void CBotButtons :: jump (const float fFor, const float fFrom) const { - holdButton(IN_JUMP,fFrom,fFor,0.25); + holdButton(IN_JUMP,fFrom,fFor,0.25f); } -void CBotButtons :: duck (float fFor, float fFrom) +void CBotButtons :: duck (const float fFor, const float fFrom) const { holdButton(IN_DUCK,fFrom,fFor); } -void CBotButton :: hold ( float fFrom, float fFor, float fLetGoTime ) +void CBotButton :: hold (float fFrom, const float fFor, const float fLetGoTime) { fFrom += engine->Time(); m_fTimeStart = fFrom; @@ -71,88 +73,83 @@ CBotButtons :: CBotButtons() m_bLetGoAll = false; } -void CBotButtons :: holdButton ( int iButtonId, float fFrom, float fFor, float fLetGoTime ) +void CBotButtons :: holdButton (const int iButtonId, const float fFrom, const float fFor, const float fLetGoTime) const { - for (unsigned int i = 0; i < m_theButtons.size(); i ++ ) + for (CBotButton* const m_theButton : m_theButtons) { - if ( m_theButtons[i]->getID() == iButtonId ) + if (m_theButton->getID() == iButtonId ) { - m_theButtons[i]->hold(fFrom,fFor,fLetGoTime); + m_theButton->hold(fFrom,fFor,fLetGoTime); return; } } } -void CBotButtons :: letGo (int iButtonId) +void CBotButtons :: letGo (const int iButtonId) const { - for (unsigned int i = 0; i < m_theButtons.size(); i ++ ) + for (CBotButton* const m_theButton : m_theButtons) { - if ( m_theButtons[i]->getID() == iButtonId ) + if (m_theButton->getID() == iButtonId ) { - m_theButtons[i]->letGo(); + m_theButton->letGo(); return; } } } -int CBotButtons :: getBitMask () +int CBotButtons :: getBitMask () const { if ( m_bLetGoAll ) return 0; - else - { - - int iBitMask = 0; + int iBitMask = 0; - float fTime = engine->Time(); + const float fTime = engine->Time(); - for (unsigned int i = 0; i < m_theButtons.size(); i ++ ) - { - if ( m_theButtons[i]->held(fTime) ) - { - m_theButtons[i]->unTap(); - iBitMask |= m_theButtons[i]->getID(); - } - } - - return iBitMask; + for (CBotButton* const m_theButton : m_theButtons) + { + if (m_theButton->held(fTime) ) + { + m_theButton->unTap(); + iBitMask |= m_theButton->getID(); + } + } - } + return iBitMask; } -bool CBotButtons :: canPressButton ( int iButtonId ) +bool CBotButtons :: canPressButton (const int iButtonId) const { - for (unsigned int i = 0; i < m_theButtons.size(); i ++ ) + for (const CBotButton* m_theButton : m_theButtons) { - if ( m_theButtons[i]->getID() == iButtonId ) - return m_theButtons[i]->canPress(engine->Time()); + if (m_theButton->getID() == iButtonId ) + return m_theButton->canPress(engine->Time()); } return false; } void CBotButtons :: add ( CBotButton *theButton ) { - m_theButtons.push_back(theButton); + m_theButtons.emplace_back(theButton); } -bool CBotButtons :: holdingButton ( int iButtonId ) +bool CBotButtons :: holdingButton (const int iButtonId) const { - for ( unsigned int i = 0; i < m_theButtons.size(); i ++ ) + for (const CBotButton* m_theButton : m_theButtons) { - if ( m_theButtons[i]->getID() == iButtonId ) - return m_theButtons[i]->held(engine->Time()); + if (m_theButton->getID() == iButtonId ) + return m_theButton->held(engine->Time()); } return false; } -void CBotButtons :: tap ( int iButtonId ) +void CBotButtons :: tap (const int iButtonId) const { - for ( unsigned int i = 0; i < m_theButtons.size(); i ++ ) + for (CBotButton* const m_theButton : m_theButtons) { - if ( m_theButtons[i]->getID() == iButtonId ) + if (m_theButton->getID() == iButtonId ) { - m_theButtons[i]->tap(); + m_theButton->tap(); return; } diff --git a/utils/RCBot2_meta/bot_buttons.h b/utils/RCBot2_meta/bot_buttons.h index ac97d4a81..60df152f1 100644 --- a/utils/RCBot2_meta/bot_buttons.h +++ b/utils/RCBot2_meta/bot_buttons.h @@ -31,32 +31,32 @@ #ifndef __BOT_BUTTONS_H__ #define __BOT_BUTTONS_H__ +#include #include -using namespace std; class CBotButton { public: - CBotButton ( int iId ) + CBotButton (const int iId) { - memset(this,0,sizeof(CBotButton)); + std::memset(this,0,sizeof(CBotButton)); m_iButtonId = iId; m_bTapped = false; } - inline void tap () { m_bTapped = true; } + void tap () { m_bTapped = true; } - inline bool held ( float fTime ) + bool held (const float fTime) const { - return m_bTapped || ((fTime >= m_fTimeStart) && (fTime <= m_fTimeEnd));// && (!m_fLetGoTime||(fTime > m_fLetGoTime)); + return m_bTapped || (fTime >= m_fTimeStart && fTime <= m_fTimeEnd);// && (!m_fLetGoTime||(fTime > m_fLetGoTime)); } - inline bool canPress (float fTime) + bool canPress (const float fTime) const { - return !m_bTapped || (m_fLetGoTime < fTime); + return !m_bTapped || m_fLetGoTime < fTime; } - inline int getID () + int getID () const { return m_iButtonId; } @@ -69,9 +69,9 @@ class CBotButton m_bTapped = false; } - inline void unTap () { m_bTapped = false; } + void unTap () { m_bTapped = false; } - void hold ( float fFrom = 0.0, float fFor = 1.0f, float m_fLetGoTime = 0.0f ); + void hold (float fFrom = 0.0f, float fFor = 1.0f, float fLetGoTime = 0.0f); private: int m_iButtonId; float m_fTimeStart; @@ -88,36 +88,36 @@ class CBotButtons void freeMemory () { - for (unsigned int i = 0; i < m_theButtons.size(); i ++ ) + for (CBotButton* const& m_theButton : m_theButtons) { - delete m_theButtons[i]; + delete m_theButton; } m_theButtons.clear(); } - void letGo (int iButtonId); - void holdButton ( int iButtonId, float fFrom = 0.0, float fFor = 1.0f, float m_fLetGoTime = 0.0f ); + void letGo (int iButtonId) const; + void holdButton (int iButtonId, float fFrom = 0.0f, float fFor = 1.0f, float fLetGoTime = 0.0f) const; inline void add ( CBotButton *theButton ); - bool holdingButton ( int iButtonId ); - bool canPressButton ( int iButtonId ); + bool holdingButton ( int iButtonId ) const; + bool canPressButton ( int iButtonId ) const; - void tap ( int iButtonId ); + void tap ( int iButtonId ) const; - void letGoAllButtons ( bool bVal ) { m_bLetGoAll = bVal; } + void letGoAllButtons (const bool bVal) { m_bLetGoAll = bVal; } - int getBitMask (); + int getBitMask () const; //////////////////////////// - void attack (float fFor = 1.0, float fFrom = 0); - void jump (float fFor = 1.0, float fFrom = 0); - void duck (float fFor = 1.0, float fFrom = 0); + void attack (float fFor = 1.0f, float fFrom = 0) const; + void jump (float fFor = 1.0f, float fFrom = 0) const; + void duck (float fFor = 1.0f, float fFrom = 0) const; private: - vector m_theButtons; + std::vector m_theButtons; bool m_bLetGoAll; }; #endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_client.cpp b/utils/RCBot2_meta/bot_client.cpp index 07daaa6b2..6749d230c 100644 --- a/utils/RCBot2_meta/bot_client.cpp +++ b/utils/RCBot2_meta/bot_client.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -29,6 +31,9 @@ * */ #include "bot.h" +#include "bot_cvars.h" +#include "bot_squads.h" + #include "bot_client.h" #include "bot_waypoint_locations.h" #include "bot_accessclient.h" @@ -39,20 +44,19 @@ #include "bot_menu.h" // autowaypoint #include "bot_getprop.h" -#include "bot_waypoint_locations.h" //#include "bot_hooks.h" #include "in_buttons.h" #include "bot_plugin_meta.h" // setup static client array -CClient CClients::m_Clients[MAX_PLAYERS]; -CClient *CClients::m_pListenServerClient = NULL; +CClient CClients::m_Clients[RCBOT_MAXPLAYERS]; +CClient *CClients::m_pListenServerClient = nullptr; bool CClients::m_bClientsDebugging = false; extern IVDebugOverlay *debugoverlay; -void CToolTip::send(edict_t *pPlayer) +void CToolTip::send(edict_t *pPlayer) const { //CRCBotPlugin::HudTextMessage(pPlayer,m_pszMessage); @@ -65,10 +69,10 @@ void CToolTip::send(edict_t *pPlayer) void CClient :: init () { m_iWaypointShowFlags = 0; - m_fMonitorHighFiveTime = 0; - m_fSpeed = 0; - m_pPlayer = NULL; - m_szSteamID = NULL; + m_fMonitorHighFiveTime = 0.0f; + m_fSpeed = 0.0f; + m_pPlayer = nullptr; + m_szSteamID = nullptr; m_bWaypointOn = false; m_iCurrentWaypoint = -1; m_iAccessLevel = 0; @@ -77,36 +81,35 @@ void CClient :: init () m_iPathTo = -1; m_bPathWaypointOn = false; m_iDebugLevels = 0; - m_pPlayerInfo = NULL; + m_pPlayerInfo = nullptr; m_iWptArea = 0; m_iWaypointDrawType = 3; m_bShowMenu = false; m_fUpdatePos = 0.0f; - m_pDebugBot = NULL; + m_pDebugBot = nullptr; m_fCopyWptRadius = 0.0f; m_iCopyWptFlags = 0; m_iCopyWptArea = 0; - m_pMenu = NULL; + m_pMenu = nullptr; m_iMenuCommand = -1; m_fNextUpdateMenuTime = 0.0f; while ( !m_NextTooltip.empty() ) m_NextTooltip.pop(); - m_fNextBotServerMessage = 0; + m_fNextBotServerMessage = 0.0f; m_bSentWelcomeMessage = false; - m_fSpeed = 0; - m_fUpdatePos = 0; + m_fSpeed = 0.0f; + m_fUpdatePos = 0.0f; } -bool CClient :: needToRenderMenu () +bool CClient :: needToRenderMenu () const { return m_fNextUpdateMenuTime < engine->Time(); } void CClient :: updateRenderMenuTime () { - extern ConVar rcbot_menu_update_time2; m_fNextUpdateMenuTime = engine->Time() + rcbot_menu_update_time2.GetFloat(); } @@ -116,7 +119,7 @@ void CClient :: setEdict ( edict_t *pPlayer ) m_pPlayerInfo = playerinfomanager->GetPlayerInfo(pPlayer); } -void CClient :: setupMenuCommands () +void CClient :: setupMenuCommands () const { /*engine->ClientCommand(m_pPlayer,"alias \"rcbot_setup\" \"bind 0 menuselect0\""); engine->ClientCommand(m_pPlayer,"rcbot_setup");bind 2 \"menuselect 2\"");*/ @@ -132,7 +135,7 @@ void CClient :: setupMenuCommands () engine->ClientCommand(m_pPlayer,"bind 0 \"menuselect 0\""); } -void CClient :: resetMenuCommands () +void CClient :: resetMenuCommands () const { /*engine->ClientCommand(m_pPlayer,"alias \"rcbot_reset\" \"bind 0 slot10\""); engine->ClientCommand(m_pPlayer,"rcbot_reset");bind 2 \"menuselect 2\"");*/ @@ -150,16 +153,16 @@ void CClient :: resetMenuCommands () void CClient :: playSound ( const char *pszSound ) { - extern ConVar bot_cmd_enable_wpt_sounds; - if ( isWaypointOn() ) { - if ( bot_cmd_enable_wpt_sounds.GetBool() ) - sprintf(m_szSoundToPlay,"play \"%s\"",pszSound); + if (bot_cmd_enable_wpt_sounds.GetBool()) + { + snprintf(m_szSoundToPlay, sizeof(m_szSoundToPlay), "play \"%s\"", pszSound); + } } } -void CClient :: autoEventWaypoint ( int iType, float fRadius, bool bAtOtherOrigin, int iTeam, Vector vOrigin, bool bIgnoreTeam, bool bAutoType ) +void CClient :: autoEventWaypoint (const int iType, const float fRadius, const bool bAtOtherOrigin, int iTeam, const Vector& vOrigin, const bool bIgnoreTeam, const bool bAutoType) { m_iAutoEventWaypoint = iType; m_fAutoEventWaypointRadius = fRadius; @@ -187,7 +190,7 @@ void CClient :: autoEventWaypoint ( int iType, float fRadius, bool bAtOtherOrigi } } -void CClient :: teleportTo (Vector vOrigin) +void CClient :: teleportTo (const Vector& vOrigin) { m_bIsTeleporting = true; m_fTeleportTime = engine->Time()+0.1f; @@ -209,21 +212,21 @@ void CClient :: teleportTo (Vector vOrigin) class CBotFunc_HighFiveSearch : public IBotFunction { public: - CBotFunc_HighFiveSearch ( edict_t *pPlayer, int iTeam ) + CBotFunc_HighFiveSearch ( edict_t *pPlayer, const int iTeam ) { m_pPlayer = pPlayer; m_iTeam = iTeam; - m_pNearestBot = NULL; - m_fNearestDist = 0; + m_pNearestBot = nullptr; + m_fNearestDist = 0.0f; } - void execute ( CBot *pBot ) + void execute ( CBot *pBot ) override { - if ( (pBot->getEdict() != m_pPlayer) && (pBot->getTeam() == m_iTeam) && pBot->isVisible(m_pPlayer) ) + if ( pBot->getEdict() != m_pPlayer && pBot->getTeam() == m_iTeam && pBot->isVisible(m_pPlayer) ) { - float fDist = pBot->distanceFrom(m_pPlayer); + const float fDist = pBot->distanceFrom(m_pPlayer); - if ( !m_pNearestBot || (fDist < m_fNearestDist) ) + if ( !m_pNearestBot || fDist < m_fNearestDist ) { m_pNearestBot = pBot; m_fNearestDist = fDist; @@ -231,7 +234,7 @@ class CBotFunc_HighFiveSearch : public IBotFunction } } - CBot *getNearestBot () + CBot *getNearestBot () const { return m_pNearestBot; } @@ -246,8 +249,6 @@ class CBotFunc_HighFiveSearch : public IBotFunction // called each frame void CClient :: think () { - extern ConVar bot_cmd_enable_wpt_sounds; - //if ( m_pPlayer ) // HookGiveNamedItem(m_pPlayer); @@ -261,39 +262,35 @@ void CClient :: think () //if ( m_fMonitorHighFiveTime > engine->Time() ) //{ - if ( (m_pPlayer != NULL) && (m_pPlayerInfo == NULL) ) + if ( m_pPlayer != nullptr && m_pPlayerInfo == nullptr) { m_pPlayerInfo = playerinfomanager->GetPlayerInfo(m_pPlayer); } - if ( CBotGlobals::isMod(MOD_TF2) ) - { - if ( (m_fMonitorHighFiveTime < engine->Time()) && (m_pPlayer != NULL) && (m_pPlayerInfo != NULL) && m_pPlayerInfo->IsConnected() && - !m_pPlayerInfo->IsDead() && m_pPlayerInfo->IsPlayer() && !m_pPlayerInfo->IsObserver() && - CClassInterface::getTF2HighFiveReady(m_pPlayer) ) + #if SOURCE_ENGINE == SE_TF2 + if ( m_fMonitorHighFiveTime < engine->Time() && m_pPlayer != nullptr && m_pPlayerInfo != nullptr && m_pPlayerInfo->IsConnected() && + CClassInterface::getTF2HighFiveReady(m_pPlayer) && !m_pPlayerInfo->IsFakeClient() && !m_pPlayerInfo->IsDead() && !m_pPlayerInfo->IsObserver()) { m_fMonitorHighFiveTime = engine->Time() + 0.25f; - if ( CClassInterface::getHighFivePartner(m_pPlayer) == NULL ) + if ( CClassInterface::getHighFivePartner(m_pPlayer) == nullptr) { // wanting high five partner // search for bots nearby who can see this player - CBotFunc_HighFiveSearch *newFunc = new CBotFunc_HighFiveSearch(m_pPlayer,CClassInterface::getTeam(m_pPlayer)); + CBotFunc_HighFiveSearch func(m_pPlayer, CClassInterface::getTeam(m_pPlayer)); - CBots::botFunction(newFunc); + CBots::botFunction(&func); - CBot *pBot = newFunc->getNearestBot(); + CBot *pBot = func.getNearestBot(); - if ( pBot != NULL ) + if ( pBot != nullptr) { - ((CBotTF2*)pBot)->highFivePlayer(m_pPlayer,CClassInterface::getTF2TauntYaw(m_pPlayer)); + static_cast(pBot)->highFivePlayer(m_pPlayer,CClassInterface::getTF2TauntYaw(m_pPlayer)); m_fMonitorHighFiveTime = engine->Time() + 3.0f; - } - - delete newFunc; + } } } - } + #endif if ( m_szSoundToPlay[0] != 0 ) { @@ -308,7 +305,7 @@ void CClient :: think () if ( m_fTeleportTime < engine->Time() ) { m_bIsTeleporting = false; - m_fTeleportTime = 0; + m_fTeleportTime = 0.0f; //reset movetypes byte *pMoveType = CClassInterface::getMoveTypePointer(m_pPlayer); int *pPlayerFlags = CClassInterface::getPlayerFlagsPointer(m_pPlayer); @@ -327,7 +324,7 @@ void CClient :: think () engine->ClientCommand(m_pPlayer,"cancelselect"); } - if ( m_pMenu != NULL ) + if ( m_pMenu != nullptr) { if ( needToRenderMenu() ) m_pMenu->render(this); @@ -339,13 +336,12 @@ void CClient :: think () if ( m_fUpdatePos < engine->Time() ) { - m_vVelocity = (getOrigin()-m_vLastPos); + m_vVelocity = getOrigin()-m_vLastPos; m_fSpeed = m_vVelocity.Length(); m_vLastPos = getOrigin(); - if ( (m_fUpdatePos > 0) && (m_fSpeed > 0) ) + if ( m_fUpdatePos > 0 && m_fSpeed > 0 ) { - extern ConVar rcbot_show_welcome_msg; // Added by pongo1231 if ( !m_bSentWelcomeMessage && rcbot_show_welcome_msg.GetBool() ) { m_bSentWelcomeMessage = true; @@ -382,7 +378,7 @@ void CClient :: think () } - if ( (m_pDebugBot!=NULL) && isDebugOn(BOT_DEBUG_HUD) ) + if ( m_pDebugBot!= nullptr && isDebugOn(BOT_DEBUG_HUD) ) { if ( m_fNextPrintDebugInfo < engine->Time() ) { @@ -413,7 +409,7 @@ void CClient :: think () do { - while ( (msg[i]!=0) && (msg[i]!='\n') ) + while ( msg[i]!=0 && msg[i]!='\n' ) line[n++] = msg[i++]; line[n]=0; @@ -423,7 +419,7 @@ void CClient :: think () if ( msg[i] == 0 ) break; i++; - }while ( 1 ) ; + }while ( true ) ; //int ent_index, int line_offset, float duration, int r, int g, int b, int a, const char *format, ... // debugoverlay->AddEntityTextOverlay(); #endif @@ -438,14 +434,9 @@ void CClient :: think () { if ( !m_NextTooltip.empty() ) { - CToolTip *pTooltip = m_NextTooltip.front(); - - pTooltip->send(m_pPlayer); - + m_NextTooltip.front().send(m_pPlayer); m_NextTooltip.pop(); - delete pTooltip; - m_fNextBotServerMessage = engine->Time() + 11.0f; } else @@ -480,14 +471,14 @@ void CClient :: think () } m_vLastAutoWaypointPlacePos = getOrigin(); - m_bSetUpAutoWaypoint = TRUE; - m_fCanPlaceJump = 0; + m_bSetUpAutoWaypoint = true; + m_fCanPlaceJump = 0.0f; m_iLastButtons = 0; m_iLastJumpWaypointIndex = -1; m_iLastLadderWaypointIndex = -1; m_iLastMoveType = 0; - m_fCanPlaceLadder = 0; + m_fCanPlaceLadder = 0.0f; m_iJoinLadderWaypointIndex = -1; } else @@ -508,7 +499,7 @@ void CClient :: think () if ( m_iAutoEventWaypoint != 0 ) { - int iWpt = CWaypointLocations::NearestWaypoint(m_vAutoEventWaypointOrigin,m_fAutoEventWaypointRadius,-1,false,false,false,NULL,false,m_iAutoEventWaypointTeam,false,false,Vector(0,0,0),m_iAutoEventWaypoint); + int iWpt = CWaypointLocations::NearestWaypoint(m_vAutoEventWaypointOrigin,m_fAutoEventWaypointRadius,-1,false,false,false, nullptr,false,m_iAutoEventWaypointTeam,false,false,Vector(0,0,0),m_iAutoEventWaypoint); CWaypoint *pWpt = CWaypoints::getWaypoint(iWpt); @@ -523,15 +514,21 @@ void CClient :: think () if ( m_bAutoEventWaypointAutoType ) { - CWaypointType *pMainType = CWaypointTypes::getTypeByFlags(m_iAutoEventWaypoint); - - if ( pMainType ) + if ( CWaypointType *pMainType = CWaypointTypes::getTypeByFlags(m_iAutoEventWaypoint) ) CWaypoints::addWaypoint(this,pMainType->getName(),"","",""); else - CWaypoints::addWaypoint(m_pPlayer,m_vAutoEventWaypointOrigin,(m_iAutoEventWaypointTeam==0)?(m_iAutoEventWaypoint):((m_iAutoEventWaypoint|m_iAutoEventWaypointTeamOn)&~m_iAutoEventWaypointTeamOff),true,cmd.viewangles.y,0,32.0f); + CWaypoints::addWaypoint(m_pPlayer, m_vAutoEventWaypointOrigin, + m_iAutoEventWaypointTeam == 0 + ? m_iAutoEventWaypoint + : (m_iAutoEventWaypoint | m_iAutoEventWaypointTeamOn) & ~ + m_iAutoEventWaypointTeamOff, true, cmd.viewangles.y, 0, 32.0f); } else - CWaypoints::addWaypoint(m_pPlayer,m_vAutoEventWaypointOrigin,(m_iAutoEventWaypointTeam==0)?(m_iAutoEventWaypoint):((m_iAutoEventWaypoint|m_iAutoEventWaypointTeamOn)&~m_iAutoEventWaypointTeamOff),true,cmd.viewangles.y,0,32.0f); + CWaypoints::addWaypoint(m_pPlayer, m_vAutoEventWaypointOrigin, + m_iAutoEventWaypointTeam == 0 + ? m_iAutoEventWaypoint + : (m_iAutoEventWaypoint | m_iAutoEventWaypointTeamOn) & ~ + m_iAutoEventWaypointTeamOff, true, cmd.viewangles.y, 0, 32.0f); //} /*else { @@ -543,13 +540,11 @@ void CClient :: think () } //g_pBotManager->GetBotController(m_pPlayer)->IsEFlagSet(); - if ( /*(pev->waterlevel < 3) &&*/ (m_fCanPlaceJump < engine->Time()) ) - { - Vector v_floor; - - if ( (m_fCanPlaceJump != -1) && (m_iLastButtons & IN_JUMP) && !(iPlayerFlags & FL_ONGROUND) ) + if ( /*(pev->waterlevel < 3) &&*/ m_fCanPlaceJump < engine->Time() ) + { + if ( m_fCanPlaceJump != -1 && m_iLastButtons & IN_JUMP && !(iPlayerFlags & FL_ONGROUND) ) { - int iNearestWpt = CWaypointLocations::NearestWaypoint(vPlayerOrigin, 80.0, -1, true, false, false, NULL); + int iNearestWpt = CWaypointLocations::NearestWaypoint(vPlayerOrigin, 80.0f, -1, true, false, false, nullptr); m_iLastJumpWaypointIndex = -1; @@ -567,11 +562,11 @@ void CClient :: think () // **************************************************** // Join jump waypoint to the landed waypoint // **************************************************** - else if ( (m_fCanPlaceJump == -1) && (iPlayerFlags & FL_ONGROUND) ) + else if ( m_fCanPlaceJump == -1 && iPlayerFlags & FL_ONGROUND ) { if ( m_iLastJumpWaypointIndex != -1 ) { - int iNearestWpt = CWaypointLocations::NearestWaypoint(vPlayerOrigin, 80.0, -1, true, false, false, NULL); + int iNearestWpt = CWaypointLocations::NearestWaypoint(vPlayerOrigin, 80.0f, -1, true, false, false, nullptr); if ( iNearestWpt == -1 ) { @@ -579,6 +574,7 @@ void CClient :: think () if ( iNewWpt != -1 ) { + Vector v_floor; CWaypoint *pWpt = CWaypoints::getWaypoint(iNewWpt); CWaypoint *pJumpWpt = CWaypoints::getWaypoint(m_iLastJumpWaypointIndex); @@ -599,7 +595,7 @@ void CClient :: think () CBotGlobals::quickTraceline(m_pPlayer,v_src,v_src+Vector(0,0,144)); - len += (tr->endpos.z-v_src.z); + len += tr->endpos.z-v_src.z; if ( len > 72 ) { @@ -625,21 +621,21 @@ void CClient :: think () m_iLastJumpWaypointIndex = -1; // wait a sec after player lands before checking jump again - m_fCanPlaceJump = engine->Time() + 0.5; + m_fCanPlaceJump = engine->Time() + 0.5f; } } - bool bCheckDistance = (iMoveType != MOVETYPE_FLY) && (m_fCanPlaceLadder == 0); // always check distance unless ladder climbing + bool bCheckDistance = iMoveType != MOVETYPE_FLY && m_fCanPlaceLadder == 0.0f; // always check distance unless ladder climbing // **************************************************** // Ladder waypoint // make the frist waypoint (e.g. bottom waypoint) // **************************************************** - if ( (iMoveType == MOVETYPE_FLY) && !(m_iLastMoveType == MOVETYPE_FLY) ) + if ( iMoveType == MOVETYPE_FLY && m_iLastMoveType != MOVETYPE_FLY ) { // went ON to a ladder - int iNearestWpt = CWaypointLocations::NearestWaypoint(vPlayerOrigin, 80.0, -1, true, false, false, NULL); + int iNearestWpt = CWaypointLocations::NearestWaypoint(vPlayerOrigin, 80.0f, -1, true, false, false, nullptr); m_iLastLadderWaypointIndex = -1; @@ -658,15 +654,15 @@ void CClient :: think () bCheckDistance = false; - m_fCanPlaceLadder = 0; + m_fCanPlaceLadder = 0.0f; // need to unset every check point when going on ladder first time - for ( int i = 0; i < MAX_STORED_AUTOWAYPOINT; i ++ ) + for (CAutoWaypointCheck& m_vLastAutoWaypointCheckP : m_vLastAutoWaypointCheckPos) { - m_vLastAutoWaypointCheckPos[i].UnSetPoint(); + m_vLastAutoWaypointCheckP.UnSetPoint(); } } - else if ( !(iMoveType == MOVETYPE_FLY) && (m_iLastMoveType == MOVETYPE_FLY) ) + else if ( iMoveType != MOVETYPE_FLY && m_iLastMoveType == MOVETYPE_FLY ) { // went OFF a ladder m_fCanPlaceLadder = engine->Time() + 0.2f; @@ -676,12 +672,12 @@ void CClient :: think () // If we have walked off a ladder for a small amount of time // Make the top/bottom ladder waypoint // **************************************************** - if ( m_fCanPlaceLadder && (m_fCanPlaceLadder < engine->Time() ) ) + if ( m_fCanPlaceLadder && m_fCanPlaceLadder < engine->Time() ) { if ( m_iLastLadderWaypointIndex != -1 ) // place a ladder waypoint before jumping off { - int iNearestWpt = CWaypointLocations::NearestWaypoint(vPlayerOrigin, 80.0, -1, true, false, false, NULL); + int iNearestWpt = CWaypointLocations::NearestWaypoint(vPlayerOrigin, 80.0f, -1, true, false, false, nullptr); if ( iNearestWpt == -1 ) { @@ -710,15 +706,15 @@ void CClient :: think () bCheckDistance = false; - m_fCanPlaceLadder = 0; + m_fCanPlaceLadder = 0.0f; } // **************************************************** // Join top ladder waypoint to a ground waypoint // **************************************************** - if ( (m_iJoinLadderWaypointIndex != -1) && (iPlayerFlags & FL_ONGROUND) && (iMoveType == MOVETYPE_WALK) ) + if ( m_iJoinLadderWaypointIndex != -1 && iPlayerFlags & FL_ONGROUND && iMoveType == MOVETYPE_WALK ) { - int iNearestWpt = CWaypointLocations::NearestWaypoint(vPlayerOrigin, 40.0, m_iJoinLadderWaypointIndex, true, false, false, NULL); + int iNearestWpt = CWaypointLocations::NearestWaypoint(vPlayerOrigin, 40.0f, m_iJoinLadderWaypointIndex, true, false, false, nullptr); if ( iNearestWpt == -1 ) { @@ -779,7 +775,7 @@ void CClient :: think () if ( numset == MAX_STORED_AUTOWAYPOINT ) { // move check points down - for ( n = 0; n < (MAX_STORED_AUTOWAYPOINT-1); n ++ ) + for ( n = 0; n < MAX_STORED_AUTOWAYPOINT-1; n ++ ) { m_vLastAutoWaypointCheckPos[n] = m_vLastAutoWaypointCheckPos[n+1]; } @@ -804,10 +800,9 @@ void CClient :: think () m_vLastAutoWaypointCheckPos[last].SetPoint(vPlayerOrigin,iFlags); - if ( (m_iLastJumpWaypointIndex==-1) && bCheckDistance && ((vPlayerOrigin - m_vLastAutoWaypointPlacePos).Length() > 200) ) + if ( m_iLastJumpWaypointIndex==-1 && bCheckDistance && (vPlayerOrigin - m_vLastAutoWaypointPlacePos).Length() > 200 ) { - extern ConVar rcbot_autowaypoint_dist; - int iNearestWpt = CWaypointLocations::NearestWaypoint(vPlayerOrigin, rcbot_autowaypoint_dist.GetFloat(), -1, true, false, false, NULL); + int iNearestWpt = CWaypointLocations::NearestWaypoint(vPlayerOrigin, rcbot_autowaypoint_dist.GetFloat(), -1, true, false, false, nullptr); if ( iNearestWpt == -1 ) CWaypoints::addWaypoint(this,"","","",""); @@ -832,11 +827,11 @@ void CClient :: think () #ifndef __linux__ if ( m_bDebugAutoWaypoint && !engine->IsDedicatedServer() ) { - debugoverlay->AddLineOverlay(vCheckOrigin+Vector(0,0,16),vCheckOrigin-Vector(0,0,16),255,255,255,0,2); - debugoverlay->AddLineOverlay(vPlayerOrigin,vCheckOrigin,255,255,255,0,2); + debugoverlay->AddLineOverlay(vCheckOrigin+Vector(0,0,16),vCheckOrigin-Vector(0,0,16),255,255,255,false,2); + debugoverlay->AddLineOverlay(vPlayerOrigin,vCheckOrigin,255,255,255,false,2); } #endif - if ( tr->fraction < 1.0 ) + if ( tr->fraction < 1.0f ) { if ( tr->m_pEnt ) { @@ -847,7 +842,7 @@ void CClient :: think () if ( CClassInterface::getVelocity(pEdict,&vel) ) { // on a lift/train moving "fast" - if ( vel.Length() > 20.0 ) + if ( vel.Length() > 20.0f ) continue; } } @@ -867,9 +862,9 @@ void CClient :: think () if ( m_bDebugAutoWaypoint ) debugoverlay->AddLineOverlay(vPlayerOrigin,vCheckOrigin,255,255,255,false,2); #endif - if ( tr->fraction >= 1.0 ) + if ( tr->fraction >= 1.0f ) { - int iNearestWpt = CWaypointLocations::NearestWaypoint(vCheckOrigin, 100.0, -1, true, false, false, NULL); + int iNearestWpt = CWaypointLocations::NearestWaypoint(vCheckOrigin, 100.0f, -1, true, false, false, nullptr); if ( iNearestWpt == -1 ) { @@ -879,8 +874,6 @@ void CClient :: think () break; } - else - continue; } } @@ -891,12 +884,12 @@ void CClient :: think () { int inewwpt = CWaypoints::addWaypoint(m_pPlayer,vPlacePosition,iFlags,true); CWaypoint *pWpt = CWaypoints::getWaypoint(inewwpt); - Vector v_floor; + Vector v_floor; //Unused? [APG]RoboCop[CL] m_vLastAutoWaypointPlacePos = vPlacePosition; bool bCanStand; - trace_t *tr; + //trace_t *tr; Vector v_src = vPlacePosition; @@ -909,11 +902,11 @@ void CClient :: think () CBotGlobals::quickTraceline(m_pPlayer,v_src,v_src+Vector(0,0,144)); - len += (tr->endpos.z-v_src.z); + len += tr->endpos.z-v_src.z; - bCanStand = ( len > 72 ); + bCanStand = len > 72; - if ( (m_iLastJumpWaypointIndex != -1) && bCanStand ) + if ( m_iLastJumpWaypointIndex != -1 && bCanStand ) { pWpt->removeFlag(CWaypointTypes::W_FL_CROUCH); //waypoints[inewwpt].origin = v_floor+Vector(0,0,36); @@ -921,7 +914,7 @@ void CClient :: think () //clear from i int pos = n; - int n = 0; + //int n = 0; for ( n = 0; pos < MAX_STORED_AUTOWAYPOINT; n ++ ) { @@ -930,7 +923,7 @@ void CClient :: think () pos++; } - for ( n = n; n < MAX_STORED_AUTOWAYPOINT; n ++ ) + for ( n = 0; n < MAX_STORED_AUTOWAYPOINT; n ++ ) { m_vLastAutoWaypointCheckPos[n].UnSetPoint(); } @@ -942,50 +935,42 @@ void CClient :: think () } } -void CClient::giveMessage(char *msg,float fTime) +void CClient::giveMessage(const char *msg, const float fTime) { - extern ConVar rcbot_tooltips; - if ( rcbot_tooltips.GetBool() ) { - m_NextTooltip.push(new CToolTip(msg,NULL)); + m_NextTooltip.emplace(msg, nullptr); m_fNextBotServerMessage = engine->Time() + fTime; } } -void CClients::giveMessage(char *msg,float fTime, edict_t *pPlayer ) +void CClients::giveMessage(const char* msg, const float fTime, const edict_t* pPlayer) { - CClient *pClient; - - if ( pPlayer != NULL ) + if (pPlayer != nullptr) { - pClient = get(pPlayer); - - if ( pClient ) - pClient->giveMessage(msg,fTime); + if (CClient* pClient = get(pPlayer)) + { + pClient->giveMessage(msg, fTime); + } } else { - for ( int i = 0; i < 32; i ++ ) + for (int i = 0; i < 32; i++) { - pClient = get(i); - - if ( pClient ) + if (CClient* pClient = get(i)) { - pClient->giveMessage(msg,fTime); + pClient->giveMessage(msg, fTime); } } } } -const char *CClient :: getName () +const char *CClient :: getName () const { - IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( m_pPlayer ); - - if ( playerinfo ) + if ( IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( m_pPlayer ) ) return playerinfo->GetName(); - return NULL; + return nullptr; } void CClient ::setTeleportVector() @@ -999,12 +984,12 @@ void CClient :: clientActive () // get steam id IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( m_pPlayer ); - m_szSteamID = NULL; + m_szSteamID = nullptr; if ( playerinfo ) { // store steam id - m_szSteamID = (char*)playerinfo->GetNetworkIDString(); + m_szSteamID = const_cast(playerinfo->GetNetworkIDString()); // check my access levels CAccessClients::checkClientAccess(this); @@ -1020,7 +1005,7 @@ void CClient :: clientConnected ( edict_t *pPlayer ) void CClient :: updateCurrentWaypoint () { - setWaypoint(CWaypointLocations::NearestWaypoint(getOrigin(),50,-1,false,true,false,NULL,false,0,false,false,Vector(0,0,0),m_iWaypointShowFlags)); + setWaypoint(CWaypointLocations::NearestWaypoint(getOrigin(),50.0f,-1,false,true,false, nullptr,false,0,false,false,Vector(0,0,0),m_iWaypointShowFlags)); } // this player disconnects void CClient :: clientDisconnected () @@ -1028,10 +1013,20 @@ void CClient :: clientDisconnected () // is bot? CBot *pBot = CBots::getBotPointer(m_pPlayer); - if ( pBot != NULL ) + if ( pBot != nullptr) { if ( pBot->inUse() ) { + // If this bot is in a squad and is a squad leader, destroy the squad -caxanga334 + // Prevents crashes since RCBot2 tries to read the squad leader in some places without NULL checks. + if (pBot->inSquad() && pBot->isSquadLeader()) + { + if (CBotSquad* squad = CBotSquads::FindSquadByLeader(m_pPlayer)) + { + CBotSquads::RemoveSquad(squad); + } + } + // free bots memory and other stuff pBot->freeAllMemory(); } @@ -1041,7 +1036,7 @@ void CClient :: clientDisconnected () { if ( CClients::isListenServerClient(this) ) { - CClients::setListenServerClient(NULL); + CClients::setListenServerClient(nullptr); } } @@ -1055,21 +1050,19 @@ void CClient :: clientDisconnected () init(); } -int CClient :: accessLevel () +int CClient :: accessLevel () const { return m_iAccessLevel; } -bool CClient :: isUsed () +bool CClient :: isUsed () const { - return (m_pPlayer != NULL); + return m_pPlayer != nullptr; } -Vector CClient :: getOrigin () +Vector CClient :: getOrigin () const { - IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( m_pPlayer ); - - if ( playerinfo ) + if ( IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( m_pPlayer ) ) { return playerinfo->GetAbsOrigin() + Vector(0,0,32); } @@ -1077,7 +1070,7 @@ Vector CClient :: getOrigin () return CBotGlobals::entityOrigin(m_pPlayer) + Vector(0,0,32);//m_pPlayer->GetCollideable()->GetCollisionOrigin(); } -void CClients :: clientActive ( edict_t *pPlayer ) +void CClients :: clientActive (const edict_t *pPlayer) { CClient *pClient = &m_Clients[slotOfEdict(pPlayer)]; @@ -1093,12 +1086,12 @@ CClient *CClients :: clientConnected ( edict_t *pPlayer ) return pClient; } -void CClients :: init ( edict_t *pPlayer ) +void CClients :: init (const edict_t *pPlayer) { m_Clients[slotOfEdict(pPlayer)].init(); } -void CClients :: clientDisconnected ( edict_t *pPlayer ) +void CClients :: clientDisconnected (const edict_t *pPlayer) { CClient *pClient = &m_Clients[slotOfEdict(pPlayer)]; @@ -1109,33 +1102,29 @@ void CClients :: clientThink () { static CClient *pClient; - edict_t *pPlayer; - m_bClientsDebugging = false; - for ( int i = 0; i < MAX_PLAYERS; i ++ ) + for (CClient& m_Client : m_Clients) { - pClient = &m_Clients[i]; + pClient = &m_Client; if ( !pClient->isUsed() ) continue; if ( !m_bClientsDebugging && pClient->isDebugging() ) m_bClientsDebugging = true; - pPlayer = pClient->getPlayer(); + edict_t* pPlayer = pClient->getPlayer(); if ( pPlayer && pPlayer->GetIServerEntity() ) pClient->think(); } } -CClient *CClients :: findClientBySteamID ( char *szSteamID ) +CClient *CClients :: findClientBySteamID (const char* szSteamID) { - CClient *pClient; - - for ( int i = 0; i < MAX_PLAYERS; i ++ ) + for (CClient& m_Client : m_Clients) { - pClient = &m_Clients[i]; + CClient* pClient = &m_Client; if ( pClient->isUsed() ) { @@ -1144,48 +1133,45 @@ CClient *CClients :: findClientBySteamID ( char *szSteamID ) } } - return NULL; + return nullptr; } -void CClients::clientDebugMsg(CBot *pBot, int iLev, const char *fmt, ... ) +void CClients::clientDebugMsg(const CBot* pBot, const int iLev, const char* fmt, ...) { - va_list argptr; + va_list argptr; static char string[1024]; - va_start (argptr, fmt); - vsprintf (string, fmt, argptr); - va_end (argptr); + va_start(argptr, fmt); + vsnprintf(string, sizeof(string), fmt, argptr); + va_end(argptr); - clientDebugMsg(iLev,string,pBot); + clientDebugMsg(iLev, string, pBot); } const char *g_szDebugTags[15] = { -"GAME_EVENT", -"NAV", -"SPEED", -"VIS", -"TASK", -"BUTTONS", -"USERCMD", -"UTIL", -"PROFILE", -"EDICTS", -"THINK", -"LOOK", -"HUD", -"AIM", -"CHAT" + "GAME_EVENT", + "NAV", + "SPEED", + "VIS", + "TASK", + "BUTTONS", + "USERCMD", + "UTIL", + "PROFILE", + "EDICTS", + "THINK", + "LOOK", + "HUD", + "AIM", + "CHAT" }; - -void CClients :: clientDebugMsg ( int iLev, const char *szMsg, CBot *pBot ) +void CClients :: clientDebugMsg (const int iLev, const char *szMsg, const CBot *pBot) { - CClient *pClient; - - for ( int i = 0; i < MAX_PLAYERS; i ++ ) + for (CClient& m_Client : m_Clients) { - pClient = &m_Clients[i]; + CClient* pClient = &m_Client; if ( !pClient->isUsed() ) continue; @@ -1195,8 +1181,8 @@ void CClients :: clientDebugMsg ( int iLev, const char *szMsg, CBot *pBot ) continue; if (pClient->isDebugOn(BOT_DEBUG_CHAT)) { - char logmsg[128] = {0}; - snprintf(logmsg, sizeof(logmsg),"[DEBUG %s] %s",g_szDebugTags[iLev],szMsg); + char logmsg[128] = {}; + snprintf(logmsg, sizeof logmsg,"[DEBUG %s] %s",g_szDebugTags[iLev],szMsg); RCBotPluginMeta::HudTextMessage(pClient->getPlayer(), logmsg); } @@ -1204,24 +1190,21 @@ void CClients :: clientDebugMsg ( int iLev, const char *szMsg, CBot *pBot ) } } - // get index in array -int CClients :: slotOfEdict ( edict_t *pPlayer ) +// get index in array +int CClients :: slotOfEdict (const edict_t* pPlayer) { return ENTINDEX(pPlayer)-1; } -bool CClients :: clientsDebugging (int iLev) +bool CClients :: clientsDebugging (const int iLev) { if ( iLev == 0 ) return m_bClientsDebugging; - else if ( m_bClientsDebugging ) + if ( m_bClientsDebugging ) { - int i; - CClient *pClient; - - for ( i = 0; i < MAX_PLAYERS; i ++ ) + for ( int i = 0; i < RCBOT_MAXPLAYERS; i ++ ) { - pClient = CClients::get(i); + const CClient* pClient = CClients::get(i); if ( pClient->isUsed() ) { @@ -1234,26 +1217,24 @@ bool CClients :: clientsDebugging (int iLev) return false; } -void CClient :: setWaypointCut (CWaypoint *pWaypoint) +void CClient :: setWaypointCut (const CWaypoint *pWaypoint) { if ( pWaypoint ) { - register int i = 0; - setWaypointCopy(pWaypoint); m_WaypointCutPaths.clear(); - for ( i = 0; i < pWaypoint->numPaths(); i ++ ) + for ( int i = 0; i < pWaypoint->numPaths(); i ++ ) { - m_WaypointCutPaths.push_back(pWaypoint->getPath(i)); + m_WaypointCutPaths.emplace_back(pWaypoint->getPath(i)); } m_WaypointCopyType = WPT_COPY_CUT; } } -void CClient :: setWaypointCopy (CWaypoint *pWaypoint) +void CClient :: setWaypointCopy (const CWaypoint *pWaypoint) { if (pWaypoint) { diff --git a/utils/RCBot2_meta/bot_client.h b/utils/RCBot2_meta/bot_client.h index 36b5f27a9..57560f012 100644 --- a/utils/RCBot2_meta/bot_client.h +++ b/utils/RCBot2_meta/bot_client.h @@ -31,15 +31,19 @@ #ifndef __RCBOT_CLIENT_H__ #define __RCBOT_CLIENT_H__ +#include #include -using namespace std; #include "bot_const.h" //#include "bot_ehandle.h" +#include "bot_waypoint.h" -#define MAX_STORED_AUTOWAYPOINT 5 +enum : std::uint8_t +{ + MAX_STORED_AUTOWAYPOINT = 5 +}; -typedef enum eWptCopyType +typedef enum eWptCopyType : std::uint8_t { WPT_COPY_NONE = 0, WPT_COPY_COPY, @@ -62,72 +66,72 @@ class CTypeVector CTypeVector() { - memset(this,0,sizeof(CTypeVector)); + std::memset(this,0,sizeof(CTypeVector)); } void SetVector ( Vector vVec ) { - m_x = (T)vVec.x; - m_y = (T)vVec.y; - m_z = (T)vVec.z; + m_x = static_cast(vVec.x); + m_y = static_cast(vVec.y); + m_z = static_cast(vVec.z); - m_bVectorSet = TRUE; + m_bVectorSet = true; } - inline Vector GetVector ( void ) const + Vector GetVector () const { - return Vector((float)m_x,(float)m_y,(float)m_z); + return {static_cast(m_x),static_cast(m_y),static_cast(m_z)}; } - inline BOOL IsVectorSet () + bool IsVectorSet () const { return m_bVectorSet; } - inline void UnSet () + void UnSet () { - m_bVectorSet = FALSE; + m_bVectorSet = false; } protected: T m_x,m_y,m_z; - BOOL m_bVectorSet; + bool m_bVectorSet; }; class CAutoWaypointCheck : public CTypeVector { public: - void SetPoint ( Vector vec, int iFlags ) + void SetPoint (const Vector& vec, const int iFlags) { m_iFlags = iFlags; SetVector(vec); } - int getFlags () + int getFlags () const { return m_iFlags; } - inline void UnSetPoint () + void UnSetPoint () { - m_bVectorSet = FALSE; + m_bVectorSet = false; m_iFlags = 0; } private: - int m_iFlags; + int m_iFlags = 0; }; class CToolTip { public: - CToolTip ( const char *pszMessage, const char *pszSound = NULL ) + CToolTip ( const char *pszMessage, const char *pszSound = nullptr) { m_pszMessage = pszMessage; m_pszSound = pszSound; } - void send(edict_t *pPlayer); + void send(edict_t *pPlayer) const; private: const char *m_pszMessage; const char *m_pszSound; @@ -136,13 +140,48 @@ class CToolTip class CClient { public: - CClient () + CClient (): m_vLastAutoWaypointCheckPos{} { - m_szSteamID = NULL; - m_pPlayerInfo = NULL; - m_pDebugBot = NULL; + m_pPlayer = nullptr; + m_bWaypointOn = false; + m_iCurrentWaypoint = 0.0f; + m_iPathFrom = 0; + m_iPathTo = 0; + m_iAccessLevel = 0; + m_iWptArea = 0; + m_bAutoPaths = false; + m_bPathWaypointOn = false; + m_iDebugLevels = 0; + m_bShowMenu = false; + m_fCopyWptRadius = 0.0f; + m_iCopyWptFlags = 0; + m_iCopyWptArea = 0; + + m_fNextPrintDebugInfo = 0.0f; + m_iPrevMenu = 0; + m_bDebugAutoWaypoint = false; + m_bAutoWaypoint = false; + m_fLastAutoWaypointCheckTime = 0.0f; + m_bSetUpAutoWaypoint = false; + m_fCanPlaceJump = 0.0f; + m_iLastButtons = 0; + + m_iLastJumpWaypointIndex = 0; + m_iLastLadderWaypointIndex = 0; + m_iLastMoveType = 0; + m_fCanPlaceLadder = 0.0f; + m_iJoinLadderWaypointIndex = 0; + m_iAutoEventWaypointTeamOn = 0; + m_iAutoEventWaypointTeamOff = 0; + m_iAutoEventWaypointTeam = 0; + m_bIsTeleporting = false; + m_fTeleportTime = 0.0f; + + m_szSteamID = nullptr; + m_pPlayerInfo = nullptr; + m_pDebugBot = nullptr; m_WaypointCopyType = WPT_COPY_NONE; - m_pMenu = NULL; + m_pMenu = nullptr; m_iMenuCommand = -1; m_fNextUpdateMenuTime = 0.0f; m_iWaypointShowFlags = 0; @@ -153,13 +192,13 @@ class CClient m_vAutoEventWaypointOrigin = Vector(0,0,0); m_bAutoEventWaypointAutoType = false; m_iAutoEventWaypointArea = 0; - m_fNextBotServerMessage = 0; + m_fNextBotServerMessage = 0.0f; m_bSentWelcomeMessage = false; - m_fSpeed = 0; - m_fUpdatePos = 0; + m_fSpeed = 0.0f; + m_fUpdatePos = 0.0f; m_bTeleportVectorValid = false; m_vTeleportVector = Vector(0,0,0); - m_fMonitorHighFiveTime = 0; + m_fMonitorHighFiveTime = 0.0f; } void monitorHighFive () @@ -169,115 +208,120 @@ class CClient void init (); - void setupMenuCommands (); - void resetMenuCommands (); + void setupMenuCommands () const; + void resetMenuCommands () const; void setTeleportVector (); - Vector *getTeleportVector () { if ( m_bTeleportVectorValid ) return &m_vTeleportVector; return NULL; } + Vector *getTeleportVector () { if ( m_bTeleportVectorValid ) return &m_vTeleportVector; return nullptr; } - inline bool isUsingMenu () { return (m_pMenu != NULL); } - inline void setCurrentMenu ( CBotMenu *pMenu ) + bool isUsingMenu () const { return m_pMenu != nullptr; } + + void setCurrentMenu ( CBotMenu *pMenu ) { m_pMenu = pMenu; - if ( pMenu == NULL ) + if ( pMenu == nullptr) resetMenuCommands(); else setupMenuCommands(); } - inline CBotMenu *getCurrentMenu () { return m_pMenu; } - inline void setMenuCommand ( int iCommand ) { m_iMenuCommand = iCommand; } - inline int getLastMenuCommand () { return m_iMenuCommand; } - bool needToRenderMenu (); + + CBotMenu *getCurrentMenu () const { return m_pMenu; } + void setMenuCommand (const int iCommand) { m_iMenuCommand = iCommand; } + int getLastMenuCommand () const { return m_iMenuCommand; } + bool needToRenderMenu () const; void updateRenderMenuTime (); - int accessLevel (); + int accessLevel () const; // this player joins with pPlayer edict void clientConnected ( edict_t *pPlayer ); // this player disconnects - void clientDisconnected (); + void clientDisconnected (); - inline void showMenu () { m_bShowMenu = true; }; + void showMenu () { m_bShowMenu = true; } - bool isUsed (); + bool isUsed () const; - Vector getOrigin (); + Vector getOrigin () const; - inline float getSpeed () { return m_fSpeed; } - inline Vector getVelocity () { return m_vVelocity; } + float getSpeed () const { return m_fSpeed; } + Vector getVelocity () { return m_vVelocity; } - void setWaypointCut ( CWaypoint *pWaypoint ); - void setWaypointCopy (CWaypoint *pWaypoint); + void setWaypointCut (const CWaypoint *pWaypoint ); + void setWaypointCopy (const CWaypoint *pWaypoint); void setEdict ( edict_t *pPlayer ); - edict_t *getPlayer () { return m_pPlayer; } + edict_t *getPlayer () const { return m_pPlayer; } - inline bool isPlayer ( edict_t *pPlayer ) { return m_pPlayer == pPlayer; } + bool isPlayer (const edict_t *pPlayer) const { return m_pPlayer == pPlayer; } - inline bool isWaypointOn () { return m_bWaypointOn; } - inline void setWaypointOn ( bool bOn ) { m_bWaypointOn = bOn; } - inline void setWaypoint ( int iWpt ) { m_iCurrentWaypoint = iWpt; } - inline int currentWaypoint () { return m_iCurrentWaypoint; } + bool isWaypointOn () const { return m_bWaypointOn; } + void setWaypointOn (const bool bOn) { m_bWaypointOn = bOn; } + void setWaypoint (const int iWpt) { m_iCurrentWaypoint = iWpt; } + int currentWaypoint () const { return m_iCurrentWaypoint; } - inline void setAccessLevel ( int iLev ) { m_iAccessLevel = iLev; } + void setAccessLevel (const int iLev) { m_iAccessLevel = iLev; } - inline bool isAutoPathOn () { return m_bAutoPaths; } - inline void setAutoPath ( bool bOn ) { m_bAutoPaths = bOn; } - inline bool isPathWaypointOn () { return m_bPathWaypointOn; } - inline void setPathWaypoint ( bool bOn ) { m_bPathWaypointOn = bOn; } + bool isAutoPathOn () const { return m_bAutoPaths; } + void setAutoPath (const bool bOn) { m_bAutoPaths = bOn; } + bool isPathWaypointOn () const { return m_bPathWaypointOn; } + void setPathWaypoint (const bool bOn) { m_bPathWaypointOn = bOn; } - inline int getWptArea () { return m_iWptArea; } - inline void setWptArea ( int area ) { m_iWptArea = area; } + int getWptArea () const { return m_iWptArea; } + void setWptArea (const int area) { m_iWptArea = area; } - inline void setPathFrom ( int iWpt ) { m_iPathFrom = iWpt; } - inline void setPathTo ( int iWpt ) { m_iPathTo = iWpt; } + void setPathFrom (const int iWpt) { m_iPathFrom = iWpt; } + void setPathTo (const int iWpt) { m_iPathTo = iWpt; } - inline int getPathFrom () { return m_iPathFrom; } - inline int getPathTo () { return m_iPathTo; } + int getPathFrom () const { return m_iPathFrom; } + int getPathTo () const { return m_iPathTo; } - void teleportTo ( Vector vOrigin ); + void teleportTo (const Vector& vOrigin ); - inline const char *getSteamID () { return m_szSteamID; } - const char *getName (); + const char *getSteamID () const { return m_szSteamID; } + const char *getName () const; void updateCurrentWaypoint (); void clientActive (); - void setDebug ( int iLevel, bool bSet ) { if ( bSet ) { m_iDebugLevels |= (1<0; } + void setDebug (const int iLevel, const bool bSet) { if ( bSet ) { m_iDebugLevels |= 1<0; } void clearDebug ( ) { m_iDebugLevels = 0; } - bool isDebugging () { return (m_iDebugLevels != 0); } + bool isDebugging () const { return m_iDebugLevels != 0; } - inline void setDebugBot ( edict_t *pBot ) { m_pDebugBot = pBot; } - inline bool isDebuggingBot ( edict_t *pBot ) { return m_pDebugBot == pBot; } - inline edict_t *getDebugBot () { return m_pDebugBot; } + void setDebugBot ( edict_t *pBot ) { m_pDebugBot = pBot; } + bool isDebuggingBot ( edict_t *pBot ) { return m_pDebugBot == pBot; } + edict_t *getDebugBot () { return m_pDebugBot; } void think (); - inline void setDrawType ( unsigned short int iType ) { m_iWaypointDrawType = iType; } - inline unsigned short int getDrawType () { return m_iWaypointDrawType; } + void setDrawType (const unsigned short iType) { m_iWaypointDrawType = iType; } + unsigned short int getDrawType () const { return m_iWaypointDrawType; } - inline float getWptCopyRadius() { return m_fCopyWptRadius; } - inline int getWptCopyFlags () { return m_iCopyWptFlags; } - inline int getWptCopyArea () { return m_iCopyWptArea; } + float getWptCopyRadius() const { return m_fCopyWptRadius; } + int getWptCopyFlags () const { return m_iCopyWptFlags; } + int getWptCopyArea () const { return m_iCopyWptArea; } - inline eWptCopyType getWptCopyType () { return m_WaypointCopyType; } + eWptCopyType getWptCopyType () const { return m_WaypointCopyType; } - inline bool isShowingWaypoint ( int iFlags ) { return (m_iWaypointShowFlags & iFlags) > 0; } - inline void showWaypoints ( int iFlags ) { m_iWaypointShowFlags |= iFlags; } - inline void dontShowWaypoints ( int iFlags ) { m_iWaypointShowFlags &= ~iFlags; } - inline bool isShowingAllWaypoints () { return m_iWaypointShowFlags == 0; } - inline int getShowWaypointFlags () { return m_iWaypointShowFlags; } + bool isShowingWaypoint (const int iFlags) const { return (m_iWaypointShowFlags & iFlags) > 0; } + void showWaypoints (const int iFlags) { m_iWaypointShowFlags |= iFlags; } + void dontShowWaypoints (const int iFlags) { m_iWaypointShowFlags &= ~iFlags; } + bool isShowingAllWaypoints () const { return m_iWaypointShowFlags == 0; } + int getShowWaypointFlags () const { return m_iWaypointShowFlags; } void playSound ( const char *pszSound ); - inline void setAutoWaypointMode ( bool mode, bool debug ) + + void setAutoWaypointMode (const bool mode, const bool debug) { m_bAutoWaypoint = mode; m_bDebugAutoWaypoint = debug; } - inline bool autoWaypointOn () { return m_bAutoWaypoint; } - void autoEventWaypoint ( int iType, float fRadius, bool bAtOtherOrigin = false, int iTeam = 0, Vector vOrigin = Vector(0,0,0), bool bIgnoreTeam = false, bool bAutoType = false ); - void giveMessage(char*msg, float fTime=0.1f); + + bool autoWaypointOn () const { return m_bAutoWaypoint; } + void autoEventWaypoint (int iType, float fRadius, bool bAtOtherOrigin = false, int iTeam = 0, const Vector& vOrigin = Vector(0, 0, 0), bool + bIgnoreTeam = false, bool bAutoType = false); + void giveMessage(const char*msg, float fTime = 0.1f); private: edict_t *m_pPlayer; // steam id @@ -302,7 +346,7 @@ class CClient bool m_bPathWaypointOn; unsigned short int m_iWaypointDrawType; - unsigned int m_iDebugLevels; + unsigned m_iDebugLevels; IPlayerInfo *m_pPlayerInfo; @@ -317,10 +361,10 @@ class CClient int m_iCopyWptFlags; int m_iCopyWptArea; - vector m_WaypointCutPaths; + /* TODO m_WaypointCutPaths never gets read from -- only ::clear and ::emplace_back are used */ + WaypointList m_WaypointCutPaths; + eWptCopyType m_WaypointCopyType; - // TODO: tooltips queue - // vector tooltips float m_fNextPrintDebugInfo; @@ -362,7 +406,7 @@ class CClient int m_iAutoEventWaypointArea; bool m_bAutoEventWaypointAutoType; float m_fNextBotServerMessage; - queue m_NextTooltip; + std::queue m_NextTooltip; bool m_bSentWelcomeMessage; bool m_bTeleportVectorValid; @@ -379,28 +423,32 @@ class CClients public: // called when player joins static CClient *clientConnected ( edict_t *pPlayer ); - static void clientDisconnected ( edict_t *pPlayer ); + static void clientDisconnected (const edict_t *pPlayer ); // player starts game - static void clientActive ( edict_t *pPlayer ); + static void clientActive (const edict_t *pPlayer ); // get index in array - static int slotOfEdict ( edict_t *pPlayer ); - static void init ( edict_t *pPlayer ); - static CClient *get ( int iIndex ) { return &m_Clients[iIndex]; } - static CClient *get ( edict_t *pPlayer ) { return &m_Clients[slotOfEdict(pPlayer)]; } + static int slotOfEdict (const edict_t* pPlayer); + static void init (const edict_t *pPlayer ); + static CClient *get (const int iIndex) { return &m_Clients[iIndex]; } + static CClient *get (const edict_t *pPlayer) { return &m_Clients[slotOfEdict(pPlayer)]; } static void setListenServerClient ( CClient *pClient ) { m_pListenServerClient = pClient; } - static bool isListenServerClient ( CClient *pClient ) { return m_pListenServerClient == pClient; } - static bool noListenServerClient () { return m_pListenServerClient == NULL; } + static bool isListenServerClient (const CClient *pClient) { return m_pListenServerClient == pClient; } + static bool noListenServerClient () { return m_pListenServerClient == nullptr; } static void clientThink (); static bool clientsDebugging ( int iLev = 0 ); - static void clientDebugMsg ( int iLev, const char *szMsg, CBot *pBot = NULL ); - static void clientDebugMsg(CBot *pBot, int iLev, const char *fmt, ... ); - static CClient *findClientBySteamID ( char *szSteamID ); - static edict_t *getListenServerClient() { if ( m_pListenServerClient ) return m_pListenServerClient->getPlayer(); else return NULL; } + static void clientDebugMsg ( int iLev, const char *szMsg, const CBot *pBot = nullptr); + static void clientDebugMsg(const CBot *pBot, int iLev, const char *fmt, ... ); + static CClient *findClientBySteamID (const char* szSteamID); + static edict_t *getListenServerClient() + { + if ( m_pListenServerClient ) return m_pListenServerClient->getPlayer(); + return nullptr; + } - static void initall () { for ( int i = 0; i < MAX_PLAYERS; i ++ ) { m_Clients[i].init(); } } - static void giveMessage (char *msg, float fTime = 0.1, edict_t *pPlayer = NULL );// NULL to everyone + static void initall () { for (CClient& m_Client : m_Clients) { m_Client.init(); } } + static void giveMessage (const char* msg, float fTime = 0.1f, const edict_t* pPlayer = nullptr);// NULL to everyone private: - static CClient m_Clients[MAX_PLAYERS]; + static CClient m_Clients[RCBOT_MAXPLAYERS]; static CClient *m_pListenServerClient; static bool m_bClientsDebugging; }; diff --git a/utils/RCBot2_meta/bot_commands.cpp b/utils/RCBot2_meta/bot_commands.cpp index d3c642cc1..d9575d3d0 100644 --- a/utils/RCBot2_meta/bot_commands.cpp +++ b/utils/RCBot2_meta/bot_commands.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -28,2569 +30,267 @@ * version. * */ -#include "bot.h" -#include "bot_client.h" -#include "bot_strings.h" -#include "bot_commands.h" -#include "bot_globals.h" -#include "bot_accessclient.h" -#include "bot_schedule.h" -#include "bot_waypoint.h" // for waypoint commands -#include "bot_waypoint_locations.h" // for waypoint commands -#include "ndebugoverlay.h" -#include "bot_waypoint_visibility.h" -#include "bot_getprop.h" -#include "bot_weapons.h" -#include "bot_menu.h" - -#include "bot_tf2_points.h" - -CBotCommandContainer *CBotGlobals :: m_pCommands = new CRCBotCommand(); -extern IVDebugOverlay *debugoverlay; -/////////////////////////////////////////////////// -// Setup commands -CRCBotCommand :: CRCBotCommand () -{ - setName("rcbot"); - setAccessLevel(0); - add(new CWaypointCommand()); - add(new CAddBotCommand()); - add(new CControlCommand()); - add(new CPathWaypointCommand()); - add(new CDebugCommand()); - add(new CPrintCommands()); - add(new CConfigCommand()); - add(new CKickBotCommand()); - add(new CUsersCommand()); - add(new CUtilCommand()); -} - -CWaypointCommand :: CWaypointCommand() -{ - setName("waypoint"); - //setAccessLevel(CMD_ACCESS_WAYPOINT); - setAccessLevel(0); - add(new CWaypointOnCommand()); - add(new CWaypointOffCommand()); - add(new CWaypointAddCommand()); - add(new CWaypointDeleteCommand()); - add(new CWaypointInfoCommand()); - add(new CWaypointSaveCommand()); - add(new CWaypointLoadCommand()); - add(new CWaypointClearCommand()); - add(new CWaypointGiveTypeCommand()); - add(new CWaypointDrawTypeCommand()); - add(new CWaypointAngleCommand()); - add(new CWaypointSetAngleCommand()); - add(new CWaypointSetAreaCommand()); - add(new CWaypointSetRadiusCommand()); - add(new CWaypointMenuCommand()); - add(new CWaypointCut()); - add(new CWaypointCopy()); - add(new CWaypointPaste()); - add(new CWaypointShiftAreas()); - add(new CWaypointTeleportCommand()); - add(new CWaypointAreaSetToNearest()); - add(new CWaypointShowCommand()); - add(new CWaypointCheckCommand()); - add(new CWaypointShowVisCommand()); - add(new CWaypointAutoWaypointCommand()); - add(new CWaypointAutoFix()); -}/////////////// - -CWaypointShowCommand :: CWaypointShowCommand() -{ - setName("show"); - setHelp("show , shows you to this waypoint"); -} - -eBotCommandResult CWaypointShowCommand::execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient ) - { - int wpt = atoi(pcmd); - CWaypoint *pwpt = CWaypoints::getWaypoint(wpt); - - if ( pwpt ) - { - g_pEffects->Beam( CBotGlobals::entityOrigin(pClient->getPlayer()), pwpt->getOrigin(), CWaypoints::waypointTexture(), - 0, 0, 1, - 5, 12, 12, 255, - 10, 255, 255, 255, 200, 10); - - //pClient->setShowWpt(wpt); - - return COMMAND_ACCESSED; - } - //else - //pClient->setShowWpt(-1); - } - - return COMMAND_ERROR; -} - -////////////// - -CWaypointCopy :: CWaypointCopy() -{ - setName("copy"); - setHelp("Go to a waypoint, and copy to hold its properties, then use paste to make a new waypoint with the same properties"); -} - -eBotCommandResult CWaypointCopy :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient ) - { - pClient->updateCurrentWaypoint(); - - CWaypoint *pwpt = CWaypoints::getWaypoint(pClient->currentWaypoint()); - - if ( pwpt ) - { - pClient->setWaypointCopy(pwpt); - return COMMAND_ACCESSED; - } - } - - return COMMAND_ERROR; -} -////////////////////////////////////////// - -CWaypointCut :: CWaypointCut() -{ - setName("cut"); - setHelp("allows you to move a waypoint by cutting it and pasting it"); -} - -eBotCommandResult CWaypointCut :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient ) - { - pClient->updateCurrentWaypoint(); - - CWaypoint *pwpt = CWaypoints::getWaypoint(pClient->currentWaypoint()); - - if ( pwpt ) - { - pClient->setWaypointCut(pwpt); - CWaypoints::deleteWaypoint(pClient->currentWaypoint()); - } - - return COMMAND_ACCESSED; - } - - return COMMAND_ERROR; -} - -//////////////////////////////// -eBotCommandResult CSetProp :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient ) - { - // classname // key // type //value - if ( (pcmd && *pcmd) &&(arg1 && *arg1) && (arg2 && *arg2) && (arg3 && *arg3)) - { - //int i = 0; - - edict_t *pPlayer = pClient->getPlayer(); -// edict_t *pEdict; - edict_t *pNearest = NULL; -// float fDistance; -// float fNearest = 400.0f; - - pNearest = CClassInterface::FindEntityByNetClassNearest(pClient->getOrigin(),pcmd); - - if ( pNearest ) - { - void *data = NULL; - - extern bool g_PrintProps; - unsigned int m_offset = 0; - - ServerClass *sc = UTIL_FindServerClass(pcmd); - - if ( sc ) - { - UTIL_FindSendPropInfo(sc,arg1,&m_offset); - - if ( m_offset ) - { - static IServerUnknown *pUnknown; - static CBaseEntity *pEntity; - Vector vdata; - - pUnknown = (IServerUnknown *)pNearest->GetUnknown(); - - pEntity = pUnknown->GetBaseEntity(); - - data = (void *)((char *)pEntity + m_offset); - - if ( data ) - { - bool *booldata = (bool*)data; - int *intdata = (int*)data; - float *floatdata = (float*)data; - - if ( strcmp(arg2,"int")==0) - *intdata = atoi(arg3); - else if ( strcmp(arg2,"bool")==0 ) - *booldata = (atoi(arg3)==1); - else if ( strcmp(arg2,"float")==0 ) - *floatdata = atof(arg3); - } - else - CBotGlobals::botMessage(pPlayer,0,"NULL"); - } - else - CBotGlobals::botMessage(NULL,0,"OFFSET NOT FOUND"); - } - else - CBotGlobals::botMessage(NULL,0,"CLASS NOT FOUND"); - - } - else - CBotGlobals::botMessage(NULL,0,"EDICT NOT FOUND"); - } - else - CBotGlobals::botMessage(NULL,0,"Usage: getprop CLASSNAME KEY TYPE(int,bool,float) VALUE"); - - return COMMAND_ACCESSED; - } - - return COMMAND_ERROR; -} - -//////////////////////////////// -eBotCommandResult CGetProp :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient ) - { - if ( (pcmd && *pcmd) &&(arg1 && *arg1) ) - { - //int i = 0; - - edict_t *pPlayer = pClient->getPlayer(); -// edict_t *pEdict; - edict_t *pNearest = NULL; -// float fDistance; -// float fNearest = 400.0f; - - pNearest = CClassInterface::FindEntityByNetClassNearest(pClient->getOrigin(),pcmd); - - if ( pNearest ) - { - void *data = NULL; - - extern bool g_PrintProps; - unsigned int m_offset = 0; - - ServerClass *sc = UTIL_FindServerClass(pcmd); - - if ( sc ) - { - UTIL_FindSendPropInfo(sc,arg1,&m_offset); - - if ( m_offset ) - { - static IServerUnknown *pUnknown; - static CBaseEntity *pEntity; - Vector vdata; - - pUnknown = (IServerUnknown *)pNearest->GetUnknown(); - - pEntity = pUnknown->GetBaseEntity(); - - int preoffs = 0; - - if ( (arg2 && *arg2) ) - { - preoffs = atoi(arg2); - } - - data = (void *)((char *)pEntity + m_offset); - - if ( data ) - { - vdata = *((Vector*)data+preoffs); - - CBotGlobals::botMessage(pPlayer,0,"int = %d, float = %f, bool = %s, Vector = (%0.4f,%0.4f,%0.4f)",*((int*)data + preoffs),*((float*)data+preoffs),*((bool*)data+preoffs) ? ("true"):("false"),vdata.x,vdata.y,vdata.z ); - } - else - CBotGlobals::botMessage(pPlayer,0,"NULL"); - } - else - CBotGlobals::botMessage(NULL,0,"OFFSET NOT FOUND"); - } - else - CBotGlobals::botMessage(NULL,0,"CLASS NOT FOUND"); - - } - else - CBotGlobals::botMessage(NULL,0,"EDICT NOT FOUND"); - } - else - CBotGlobals::botMessage(NULL,0,"Usage: getprop CLASS CLASSNAME KEY"); - - return COMMAND_ACCESSED; - } - - return COMMAND_ERROR; -} -////////////////////////////// -eBotCommandResult CFindProp :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pcmd && *pcmd ) - { - UTIL_FindPropPrint(pcmd); - return COMMAND_ACCESSED; - } - - return COMMAND_ERROR; -} -/////////////////////////// -eBotCommandResult CFindClassname :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient ) - { - - if ( pcmd && *pcmd ) - { - const char *pclass = CClassInterface::FindEntityNetClass(0,pcmd); - - if ( pclass ) - CBotGlobals::botMessage(pClient->getPlayer(),0,"%s network name = %s",pcmd,pclass); - else - CBotGlobals::botMessage(pClient->getPlayer(),0,"%s network name not found",pcmd,pclass); - } - - - return COMMAND_ACCESSED; - } - - return COMMAND_ERROR; -} - -//////////////////////////////// -eBotCommandResult CFindClass :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient ) - { - - if ( pcmd && *pcmd ) - { - UTIL_FindServerClassPrint(pcmd); - } - - - return COMMAND_ACCESSED; - } - - return COMMAND_ERROR; -} -/////////////////////////////////////////// -//////////////////////////////// -eBotCommandResult CPrintProps :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient ) - { - - if ( pcmd && *pcmd ) - { - extern bool g_PrintProps; - unsigned int m_offset; - g_PrintProps = true; - - ServerClass *sc = UTIL_FindServerClass(pcmd); - - if ( sc ) - UTIL_FindSendPropInfo(sc,"",&m_offset); - - g_PrintProps = false; - } - - - return COMMAND_ACCESSED; - } - - return COMMAND_ERROR; -} -/////////////////////////////////////////// - -CWaypointPaste :: CWaypointPaste() -{ - setName("paste"); - setHelp("first copy a waypoint using the copy command and then use paste to make a new waypoint with the same properties"); -} - -eBotCommandResult CWaypointPaste :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient ) - { - CWaypoints::addWaypoint(pClient,NULL,NULL,NULL,NULL,true); - return COMMAND_ACCESSED; - } - - return COMMAND_ERROR; -} -////////////////////////////////// - -CWaypointShiftAreas :: CWaypointShiftAreas() -{ - setName("shiftareas"); - setHelp("shift the areas of flagged waypoints to a different area/only use this once"); -} - -eBotCommandResult CWaypointShiftAreas :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient ) - { - int val = 1; - - if ( pcmd && *pcmd ) - val = atoi(pcmd); - - if ( arg1 && *arg1 ) - { - int newarea = atoi(arg1); - - if ( pClient ) - { - // change area val to newarea - CWaypoints::shiftVisibleAreas(pClient->getPlayer(),val,newarea); - } - } - else - CWaypoints::shiftAreas(val); - - return COMMAND_ACCESSED; - } - - return COMMAND_ERROR; -} -//////////////////////////////////// -CWaypointSetAreaCommand :: CWaypointSetAreaCommand () -{ - setName("setarea"); - setHelp("Go to a waypoint, use setarea "); -} - -eBotCommandResult CWaypointSetAreaCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - pClient->updateCurrentWaypoint(); - - if ( pcmd && *pcmd && ( CWaypoints::validWaypointIndex(pClient->currentWaypoint()) ) ) - { - CWaypoint *pWpt = CWaypoints::getWaypoint(pClient->currentWaypoint()); - - pWpt->setArea(atoi(pcmd)); - } - else - return COMMAND_ERROR; - - return COMMAND_ACCESSED; -} -////////////// - -CWaypointShowVisCommand :: CWaypointShowVisCommand () -{ - setName("showvis"); - setHelp("Go to a waypoint, use showvis to see visibility"); -} - -eBotCommandResult CWaypointShowVisCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ -#ifndef __linux__ - pClient->updateCurrentWaypoint(); - - if ( CWaypoints::validWaypointIndex(pClient->currentWaypoint()) ) - { - CWaypoint *pWpt = CWaypoints::getWaypoint(pClient->currentWaypoint()); - - int i = 0; - int index; - bool bVis; - float ftime; - - ftime = (pcmd&&*pcmd) ? atof(pcmd) : 5.0f; - - if ( pWpt ) - { - index = CWaypoints::getWaypointIndex(pWpt); - CWaypointVisibilityTable *pTable = CWaypoints::getVisiblity(); - - for ( i = 0; i < CWaypoints::numWaypoints(); i ++ ) - { - CWaypoint *pOther = CWaypoints::getWaypoint(i); - - if ( !pOther->isUsed() ) - continue; - - if ( pOther->distanceFrom(pWpt) > 1024.0f ) - continue; - - bVis = pTable->GetVisibilityFromTo(index,i); - - debugoverlay->AddTextOverlayRGB(pOther->getOrigin(),0,ftime,bVis ? 0 : 255,bVis ? 255 : 0,0,200,bVis ? "VIS" : "INV" ); - } - } - - } - else - return COMMAND_ERROR; -#endif - return COMMAND_ACCESSED; -} - -/////////////// -CWaypointSetRadiusCommand :: CWaypointSetRadiusCommand () -{ - setName("setradius"); - setHelp("Go to a waypoint, use setradius "); -} - -eBotCommandResult CWaypointSetRadiusCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - pClient->updateCurrentWaypoint(); - - if ( pcmd && *pcmd && ( CWaypoints::validWaypointIndex(pClient->currentWaypoint()) ) ) - { - CWaypoint *pWpt = CWaypoints::getWaypoint(pClient->currentWaypoint()); - - pWpt->setRadius(atof(pcmd)); - } - else - return COMMAND_ERROR; - - return COMMAND_ACCESSED; -} -///////////////// - -CWaypointMenuCommand :: CWaypointMenuCommand() -{ - setName("menu"); -}; - -eBotCommandResult CWaypointMenuCommand:: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - pClient->setCurrentMenu(CBotMenuList::getMenu(BOT_MENU_WPT)); - - return COMMAND_ACCESSED; - /* - if ( pClient ) - { - // number of waypoint types to show per menu - unsigned const int iNumToShow = 7; - - unsigned int i = 0; - // menu level .. ? - unsigned int iLevel = 0; - // number of possible waypoint types to show - unsigned int iNumTypes = CWaypointTypes::getNumTypes(); - - char num[64], msg[64], cmd[128]; - CWaypointType *p; - CWaypoint *pWpt; - - // get current waypoint types on current waypoint - pClient->updateCurrentWaypoint(); - pWpt = CWaypoints::getWaypoint(pClient->currentWaypoint()); - - if ( !pWpt ) - { - CBotGlobals::botMessage(pClient->getPlayer(),0,"Not next to any waypoints to show a menu for"); - return COMMAND_ERROR; - } - - // Menu level to start, 0 = beginning - if ( pcmd && *pcmd ) - { - iLevel = atoi(pcmd); - } - else - { - iLevel = 0; - } - - //pClient->update - - KeyValues *kv = new KeyValues( "menu" ); - kv->SetString( "title", "Waypoint Menu" ); - kv->SetInt( "level", 1 ); - kv->SetColor( "color", Color( 255, 0, 0, 255 )); - kv->SetInt( "time", 15 ); - kv->SetString( "msg", "Select Waypoint Type" ); - - // start at this waypoint type index - unsigned int iIndex = iLevel*iNumToShow; - - // run through a small number - while ( (i < iNumToShow) && (iIndex < iNumTypes) ) - { - p = CWaypointTypes::getTypeByIndex(iIndex); - - Q_snprintf( num, sizeof(num), "%i", i ); - - // if waypoint has this type show it by putting a "[x]" next to it - if ( pWpt->getFlags() & p->getBits() ) - Q_snprintf( msg, sizeof(msg), "%s [x]", p->getName() ); - else - Q_snprintf( msg, sizeof(msg), "%s [ ]", p->getName() ); - - Q_snprintf( cmd, sizeof(cmd), "rcbot waypoint givetype %s", p->getName() ); - - KeyValues *item1 = kv->FindKey( num, true ); - item1->SetString( "msg", msg ); - item1->SetString( "command", cmd ); - - iIndex ++; - i++; - } - - // finally show "More" option if available - if ( iIndex < iNumTypes ) - { - Q_snprintf( num, sizeof(num), "%i", i ); - Q_snprintf( msg, sizeof(msg), "More..." ); - Q_snprintf( cmd, sizeof(cmd), "rcbot waypoint menu %d", iLevel+1 ); - - KeyValues *item1 = kv->FindKey( num, true ); - item1->SetString( "msg", msg ); - item1->SetString( "command", cmd ); - } - - helpers->CreateMessage( pClient->getPlayer(), DIALOG_MENU, kv, &g_RCBOTServerPlugin ); - kv->deleteThis(); - - //pClient->showMenu(); - - return COMMAND_ACCESSED; - } - - return COMMAND_ERROR;*/ -}; -//////////////////////////// - -CWaypointSetAngleCommand :: CWaypointSetAngleCommand() -{ - setName("updateyaw"); -} - -eBotCommandResult CWaypointSetAngleCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - pClient->updateCurrentWaypoint(); - - if ( CWaypoints::validWaypointIndex(pClient->currentWaypoint()) ) - { - CWaypoint *pWpt = CWaypoints::getWaypoint(pClient->currentWaypoint()); - - pWpt->setAim(CBotGlobals::playerAngles(pClient->getPlayer()).y); - } - - return COMMAND_ACCESSED; -} - - -CUsersCommand :: CUsersCommand () -{ - setName("users"); - setAccessLevel(0); - - add(new CShowUsersCommand()); -} - -CDebugCommand :: CDebugCommand() -{ - setName("debug"); - setAccessLevel(CMD_ACCESS_DEBUG); - - add(new CDebugGameEventCommand()); - add(new CDebugBotCommand()); - add(new CDebugNavCommand()); - add(new CDebugVisCommand()); - add(new CDebugThinkCommand()); - add(new CDebugLookCommand()); - add(new CDebugHudCommand()); - add(new CDebugAimCommand()); - add(new CDebugChatCommand()); - add(new CBotGoto()); - add(new CBotFlush()); - add(new CDebugTaskCommand()); - add(new CBotTaskCommand()); - add(new CDebugButtonsCommand()); - add(new CDebugSpeedCommand()); - add(new CDebugUsercmdCommand()); - add(new CDebugUtilCommand()); - add(new CDebugProfilingCommand()); - add(new CDebugEdictsCommand()); - add(new CPrintProps()); - add(new CGetProp()); - add(new CSetProp()); - add(new CFindClass()); - add(new CFindClassname()); - add(new CFindProp()); - add(new CDebugMemoryScanCommand()); - add(new CDebugMemoryCheckCommand()); - -} -///////////////////// -CWaypointOnCommand::CWaypointOnCommand() -{ - setName("on"); - setAccessLevel(CMD_ACCESS_WAYPOINT); -} - -CWaypointDrawTypeCommand::CWaypointDrawTypeCommand() -{ - setName("drawtype"); - setHelp("0: for effects engine (maximum limit of beams)\n1: for debug overlay (no limit of beams) [LISTEN SERVER CLIENT ONLY]"); - setAccessLevel(CMD_ACCESS_WAYPOINT); -} - -eBotCommandResult CWaypointDrawTypeCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient ) - { - if ( pcmd && *pcmd ) - { - pClient->setDrawType(atoi(pcmd)); - return COMMAND_ACCESSED; - } - } - - return COMMAND_ERROR; -} - -eBotCommandResult CWaypointOnCommand:: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient ) - { - pClient->setWaypointOn(true); - pClient->giveMessage("Waypoints On"); - } - - return COMMAND_ACCESSED; -} - -eBotCommandResult CWaypointGiveTypeCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - edict_t *pEntity = pClient->getPlayer(); - - if ( pcmd && *pcmd ) - { - if ( pClient->currentWaypoint() == -1 ) - CBotGlobals::botMessage(pEntity,0,"No waypoint nearby to give types (move closer to the waypoint you want to give types)"); - else - { - char *type = NULL; - - for ( int i = 0; i < 4; i ++ ) - { - if ( i == 0 ) - type = (char*)pcmd; - else if ( i == 1 ) - type = (char*)arg1; - else if ( i == 2 ) - type = (char*)arg2; - else if ( i == 3 ) - type = (char*)arg3; - - if ( !type || !*type ) - break; - - CWaypointType *pType = CWaypointTypes::getType(type); - - if ( pType ) - { - CWaypoint *pWaypoint = CWaypoints::getWaypoint(pClient->currentWaypoint()); - - if ( pWaypoint ) - { - if ( pWaypoint->hasFlag(pType->getBits()) ) - { - pWaypoint->removeFlag(pType->getBits()); - CBotGlobals::botMessage(pEntity,0,"type %s removed from waypoint %d",type,CWaypoints::getWaypointIndex(pWaypoint)); - pClient->playSound("UI/buttonrollover"); - } - else - { - pWaypoint->addFlag(pType->getBits()); - - if ( pType->getBits() & CWaypointTypes::W_FL_UNREACHABLE ) - { - CWaypoints::deletePathsTo(CWaypoints::getWaypointIndex(pWaypoint)); - CWaypoints::deletePathsFrom(CWaypoints::getWaypointIndex(pWaypoint)); - } - - CBotGlobals::botMessage(pEntity,0,"type %s added to waypoint %d",type,CWaypoints::getWaypointIndex(pWaypoint)); - - pClient->playSound("UI/buttonclickrelease"); - } - - } - } - else - { - CBotGlobals::botMessage(pEntity,0,"type '%s' not found",type); - CWaypointTypes::showTypesOnConsole(pEntity); - } - - } - } - } - else - { - CWaypointTypes::showTypesOnConsole(pEntity); - } - - return COMMAND_ACCESSED; -} - -////////////////// -CWaypointOffCommand::CWaypointOffCommand() -{ - setName("off"); - setAccessLevel(CMD_ACCESS_WAYPOINT); -} - -eBotCommandResult CWaypointClearCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - CWaypoints::init(); - CBotGlobals::botMessage(pClient->getPlayer(),0,"waypoints cleared"); - - return COMMAND_ACCESSED; -} - -eBotCommandResult CWaypointOffCommand:: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - pClient->setWaypointOn(false); - pClient->giveMessage("Waypoints Off"); - CBotGlobals::botMessage(pClient->getPlayer(),0,"waypoints off"); - - return COMMAND_ACCESSED; -} -//////////////////////// -CWaypointAddCommand::CWaypointAddCommand() -{ - setName("add"); - setAccessLevel(CMD_ACCESS_WAYPOINT); -} - -eBotCommandResult CWaypointAddCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - CWaypoints::addWaypoint(pClient,pcmd,arg1,arg2,arg3); - - return COMMAND_ACCESSED; -} -//////////////////// -CWaypointDeleteCommand ::CWaypointDeleteCommand() -{ - setName("delete"); - setAccessLevel(CMD_ACCESS_WAYPOINT); -} - -eBotCommandResult CWaypointDeleteCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient ) - { - if ( pcmd && *pcmd ) - { - float radius = atof(pcmd); - - if ( radius > 0 ) - { - vector pWpt; - int numdeleted = 0; - Vector vOrigin = pClient->getOrigin(); - - CWaypointLocations::GetAllInArea(vOrigin,&pWpt,-1); - - for ( unsigned short int i = 0; i < pWpt.size(); i ++ ) - { - CWaypoint *pWaypoint = CWaypoints::getWaypoint(pWpt[i]); - - if ( pWaypoint->distanceFrom(vOrigin) < radius) - { - CWaypoints::deleteWaypoint(pWpt[i]); - numdeleted++; - } - } - - if ( numdeleted > 0 ) - { - CBotGlobals::botMessage(pClient->getPlayer(),0,"%d waypoints within range of %0.0f deleted",numdeleted,radius); - pClient->updateCurrentWaypoint(); // waypoint deleted so get a new one - pClient->playSound("buttons/combine_button_locked"); - pClient->giveMessage("Waypoints deleted"); - } - else - { - CBotGlobals::botMessage(pClient->getPlayer(),0,"no waypoints within range of %0.0f",radius); - pClient->playSound("weapons/wpn_denyselect"); - pClient->giveMessage("Waypoints deleted"); - pClient->updateCurrentWaypoint(); // waypoint deleted so get a new one - } - } - } - else - { - pClient->updateCurrentWaypoint(); - - if ( CWaypoints::validWaypointIndex(pClient->currentWaypoint()) ) - { - CWaypoints::deleteWaypoint(pClient->currentWaypoint()); - CBotGlobals::botMessage(pClient->getPlayer(),0,"waypoint %d deleted",pClient->currentWaypoint()); - pClient->updateCurrentWaypoint(); // waypoint deleted so get a new one - pClient->playSound("buttons/combine_button_locked"); - pClient->giveMessage("Waypoint deleted"); - } - else - { - CBotGlobals::botMessage(pClient->getPlayer(),0,"no waypoint nearby to delete"); - pClient->playSound("weapons/wpn_denyselect"); - pClient->giveMessage("No Waypoint"); - } - } - } - - return COMMAND_ACCESSED; -} -///////////////////// -CControlCommand :: CControlCommand () -{ - setName("control"); - setAccessLevel(CMD_ACCESS_BOT); -} - -eBotCommandResult CControlCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - edict_t *pEntity = NULL; - - if ( pClient ) - pEntity = pClient->getPlayer(); - if ( pcmd && *pcmd ) - { - - if ( CBots::controlBot(pcmd,pcmd,arg2,arg3) ) - CBotGlobals::botMessage(pEntity,0,"bot added"); - else - CBotGlobals::botMessage(pEntity,0,"error: couldn't control bot '%s'",pcmd); - - return COMMAND_ACCESSED; - - } - else - return COMMAND_ERROR; -} -//////////////////// - -CAddBotCommand ::CAddBotCommand() -{ - setName("addbot"); - setAccessLevel(CMD_ACCESS_BOT); -} - -eBotCommandResult CAddBotCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ -// bool bOkay = false; - - edict_t *pEntity = NULL; - - if ( pClient ) - pEntity = pClient->getPlayer(); - - //extern ConVar *sv_cheats; - //extern ConVar bot_sv_cheats_auto; - //extern ConVar bot_sv_cheat_warning; - - //if ( !bot_sv_cheat_warning.GetBool() || bot_sv_cheats_auto.GetBool() || !CBots::controlBots() || (!sv_cheats || sv_cheats->GetBool()) ) - //{ - //if ( !pcmd || !*pcmd ) - // bOkay = CBots::createBot(); - //else - //bOkay = CBots::createBot(); - - ///if ( CBots::createBot(pcmd,arg1,arg2) ) - if ( CBots::addBot(pcmd,arg1,arg2) ) - CBotGlobals::botMessage(pEntity,0,"bot adding..."); - else - CBotGlobals::botMessage(pEntity,0,"error: couldn't create bot! (Check maxplayers)"); - //} - //else - // CBotGlobals::botMessage(pEntity,0,"error: sv_cheats must be 1 to add bots"); - - return COMMAND_ACCESSED; -} -////////////////////// -//edits schedules - -eBotCommandResult CBotTaskCommand::execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ -#ifndef __linux__ - - if ( pClient && pClient->getDebugBot()!=NULL ) - { - edict_t *pEdict = pClient->getDebugBot(); - CBot *pBot = CBots::getBotPointer(pEdict); - - if ( pBot->inUse() ) - { - CBotSchedules *pSched = pBot->getSchedule(); - - if ( pcmd && *pcmd ) - { - //int task = atoi(pcmd); - - pSched->freeMemory(); - - // 83 - if ( !strcmp(pcmd,"pipe") ) - { - CBotUtility util = CBotUtility(pBot,BOT_UTIL_PIPE_LAST_ENEMY,true,1.0f); - pBot->setLastEnemy(pClient->getPlayer()); - pBot->getSchedule()->freeMemory(); - ((CBotTF2*)pBot)->executeAction(&util); - } - // 71 - else if ( !strcmp(pcmd,"gren") ) - { - CBotWeapons *pWeapons; - CBotWeapon *gren; - - pWeapons = pBot->getWeapons(); - gren = pWeapons->getGrenade(); - - if ( gren ) - { - CBotSchedule *sched = new CBotSchedule(new CThrowGrenadeTask(gren,pBot->getAmmo(gren->getWeaponInfo()->getAmmoIndex1()),pClient->getOrigin())); - pSched->add(sched); - } - } - else if ( !strcmp(pcmd,"snipe") ) - { - if ( pClient ) - { - - CWaypoint *pWaypoint = CWaypoints::getWaypoint(CWaypoints::nearestWaypointGoal(CWaypointTypes::W_FL_SNIPER,pClient->getOrigin(),200.0f,pBot->getTeam())); - - if ( pWaypoint ) - { - if ( CBotGlobals::isMod(MOD_TF2) ) - { - //if ( CClassInterface::getTF2Class() ) - } - else - { - CBotWeapon *pWeapon; - CBotWeapons *m_pWeapons; - CBotSchedule *snipe = new CBotSchedule(); - CBotTask *findpath = new CFindPathTask(CWaypoints::getWaypointIndex(pWaypoint)); - CBotTask *snipetask; - - m_pWeapons = pBot->getWeapons(); - pWeapon = m_pWeapons->hasWeapon(DOD_WEAPON_K98_SCOPED) ? m_pWeapons->getWeapon(CWeapons::getWeapon(DOD_WEAPON_K98_SCOPED)) : m_pWeapons->getWeapon(CWeapons::getWeapon(DOD_WEAPON_SPRING)); - - if ( pWeapon ) - { - // linux fix - copy origin onto vector here - Vector vOrigin = pWaypoint->getOrigin(); - snipetask = new CBotDODSnipe(pWeapon,vOrigin,pWaypoint->getAimYaw(),false,0,pWaypoint->getFlags()); - - findpath->setCompleteInterrupt(CONDITION_PUSH); - snipetask->setCompleteInterrupt(CONDITION_PUSH); - - snipe->setID(SCHED_DEFENDPOINT); - snipe->addTask(findpath); - snipe->addTask(snipetask); - - pSched->add(snipe); - } - else - CBotGlobals::botMessage(NULL,0,"Bot is not a sniper"); - } - } - else - CBotGlobals::botMessage(NULL,0,"Sniper waypoint not found"); - - } - } - } - - } - } - -#endif - return COMMAND_ACCESSED; - -} -////////////////////// -//clear bots schedules - -eBotCommandResult CBotFlush :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient && pClient->getDebugBot()!=NULL ) - { - edict_t *pEdict = pClient->getDebugBot(); - CBot *pBot = CBots::getBotPointer(pEdict); - - if ( pBot->inUse() ) - { - CBotSchedules *pSched = pBot->getSchedule(); - pSched->freeMemory(); - } - } - - return COMMAND_ACCESSED; -} -/////////////////////// -eBotCommandResult CBotGoto :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient && pClient->getDebugBot()!=NULL ) - { - edict_t *pEdict = pClient->getDebugBot(); - CBot *pBot = CBots::getBotPointer(pEdict); - - if ( pBot->inUse() ) - { - int iWpt; - - if ( pcmd && *pcmd ) - { - iWpt = atoi(pcmd); - - if ( (iWpt < 0) || (iWpt >= CWaypoints::numWaypoints()) ) - iWpt = -1; - } - else - iWpt = pClient->currentWaypoint(); - - if ( iWpt != -1 ) - pBot->forceGotoWaypoint(iWpt); - } - } - - return COMMAND_ACCESSED; -} -///////////////////// - -CPathWaypointCommand :: CPathWaypointCommand () -{ - setName("pathwaypoint"); - setAccessLevel(CMD_ACCESS_WAYPOINT); - - add(new CPathWaypointOnCommand()); - add(new CPathWaypointOffCommand()); - add(new CPathWaypointAutoOnCommand()); - add(new CPathWaypointAutoOffCommand()); - add(new CPathWaypointCreate1Command()); - add(new CPathWaypointCreate2Command()); - add(new CPathWaypointRemove1Command()); - add(new CPathWaypointRemove2Command()); - add(new CPathWaypointDeleteToCommand()); - add(new CPathWaypointDeleteFromCommand()); - add(new CPathWaypointCreateFromToCommand()); - add(new CPathWaypointRemoveFromToCommand()); - -} - -CPathWaypointDeleteToCommand :: CPathWaypointDeleteToCommand() -{ - setName("deleteto"); -} - -eBotCommandResult CPathWaypointDeleteToCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - pClient->updateCurrentWaypoint(); - - if ( CWaypoints::validWaypointIndex(pClient->currentWaypoint()) ) - { - CWaypoints::deletePathsTo(pClient->currentWaypoint()); - } - - return COMMAND_ACCESSED;; -} - - -CPathWaypointDeleteFromCommand :: CPathWaypointDeleteFromCommand() -{ - setName("deletefrom"); -} - -eBotCommandResult CPathWaypointDeleteFromCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - pClient->updateCurrentWaypoint(); - - if ( CWaypoints::validWaypointIndex(pClient->currentWaypoint()) ) - { - CWaypoints::deletePathsFrom(pClient->currentWaypoint()); - } - - return COMMAND_ACCESSED; -} - -CPathWaypointOnCommand :: CPathWaypointOnCommand() -{ - setName("on"); - setAccessLevel(CMD_ACCESS_WAYPOINT); -} - -eBotCommandResult CPathWaypointOnCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - pClient->setPathWaypoint(true); - pClient->giveMessage("Pathwaypoints visible"); - return COMMAND_ACCESSED; -} - -CPathWaypointOffCommand :: CPathWaypointOffCommand() -{ - setName("off"); - setAccessLevel(CMD_ACCESS_WAYPOINT); -} - -eBotCommandResult CPathWaypointOffCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - pClient->setPathWaypoint(false); - pClient->giveMessage("Pathwaypoints hidden"); - return COMMAND_ACCESSED; -} - -CWaypointAutoWaypointCommand :: CWaypointAutoWaypointCommand() -{ - setName("autowaypoint"); - setAccessLevel(CMD_ACCESS_WAYPOINT); -} - -eBotCommandResult CWaypointAutoWaypointCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient ) - { - pClient->setAutoWaypointMode(atoi(pcmd)>0,atoi(pcmd)==2); - CBotGlobals::botMessage(pClient->getPlayer(),0,"Autowaypointing Mode %s, Debug %s",(atoi(pcmd)>0)?"ON":"OFF",(atoi(pcmd)==2)?"ON":"OFF"); - } - - return COMMAND_ACCESSED; -} - -CPathWaypointAutoOnCommand :: CPathWaypointAutoOnCommand() -{ - setName("enable"); - setAccessLevel(CMD_ACCESS_WAYPOINT); -} - -eBotCommandResult CPathWaypointAutoOnCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient ) - pClient->setAutoPath(true); - return COMMAND_ACCESSED; -} - -CPathWaypointAutoOffCommand :: CPathWaypointAutoOffCommand() -{ - setName("disable"); - setAccessLevel(CMD_ACCESS_WAYPOINT); -} - -eBotCommandResult CPathWaypointAutoOffCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient ) - pClient->setAutoPath(false); - return COMMAND_ACCESSED; -} - -CPathWaypointCreate1Command :: CPathWaypointCreate1Command() -{ - setName("create1"); - setAccessLevel(CMD_ACCESS_WAYPOINT); -} - -eBotCommandResult CPathWaypointCreate1Command :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( !pClient ) - return COMMAND_ERROR; - - pClient->updateCurrentWaypoint(); - - if ( pClient->currentWaypoint() == -1 ) - { - pClient->playSound("common/wpn_denyselect.wav"); - } - else - { - pClient->setPathFrom(pClient->currentWaypoint()); - - pClient->playSound("common/wpn_hudoff.wav"); - } - - return COMMAND_ACCESSED; -} - -CPathWaypointCreate2Command :: CPathWaypointCreate2Command() -{ - setName("create2"); - setAccessLevel(CMD_ACCESS_WAYPOINT); -} - -eBotCommandResult CPathWaypointCreate2Command :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - pClient->updateCurrentWaypoint(); - pClient->setPathTo(pClient->currentWaypoint()); - - CWaypoint *pWpt = CWaypoints::getWaypoint(pClient->getPathFrom()); - - // valid? - if ( pWpt ) - { - pWpt->addPathTo(pClient->getPathTo()); - pClient->playSound("buttons/button9"); - } - else - pClient->playSound("common/wpn_denyselect"); - - return COMMAND_ACCESSED; -} - -CPathWaypointCreateFromToCommand :: CPathWaypointCreateFromToCommand() -{ - setName("createfromto"); - setAccessLevel(CMD_ACCESS_WAYPOINT); -} - -eBotCommandResult CPathWaypointCreateFromToCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient && pcmd && *pcmd && arg1 && *arg1 ) - { - CWaypoint *pWaypoint = CWaypoints::getWaypoint(atoi(pcmd)); - - if ( pWaypoint && pWaypoint->isUsed() ) - { - CWaypoint *pWaypoint2 = CWaypoints::getWaypoint(atoi(arg1)); - - if ( pWaypoint2 && pWaypoint2->isUsed() ) - { - pWaypoint->addPathTo(atoi(arg1)); - CBotGlobals::botMessage(pClient!=NULL ? pClient->getPlayer() : NULL, - 0,"Added path from <%d> to <%d>",atoi(pcmd),atoi(arg1)); - - pWaypoint->draw(pClient->getPlayer(),true,DRAWTYPE_DEBUGENGINE); - pWaypoint->info(pClient->getPlayer()); - pWaypoint2->draw(pClient->getPlayer(),true,DRAWTYPE_DEBUGENGINE); - pWaypoint2->info(pClient->getPlayer()); - - pClient->playSound("buttons/button9"); - - return COMMAND_ACCESSED; - } - else - CBotGlobals::botMessage(pClient!=NULL ? pClient->getPlayer() : NULL, - 0,"Waypoint id <%d> not found",atoi(arg1)); - - } - else - CBotGlobals::botMessage(pClient!=NULL ? pClient->getPlayer() : NULL, - 0,"Waypoint id <%d> not found",atoi(pcmd)); - } - else - CBotGlobals::botMessage(pClient!=NULL ? pClient->getPlayer() : NULL, - 0,"missing args "); - - return COMMAND_ERROR; -} - -CPathWaypointRemoveFromToCommand :: CPathWaypointRemoveFromToCommand() -{ - setName("removefromto"); - setAccessLevel(CMD_ACCESS_WAYPOINT); -} - -eBotCommandResult CPathWaypointRemoveFromToCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient && pcmd && *pcmd && arg1 && *arg1 ) - { - CWaypoint *pWaypoint = CWaypoints::getWaypoint(atoi(pcmd)); - - if ( pWaypoint && pWaypoint->isUsed() ) - { - CWaypoint *pWaypoint2 = CWaypoints::getWaypoint(atoi(arg1)); - - if ( pWaypoint2 && pWaypoint2->isUsed() ) - { - pWaypoint->removePathTo(atoi(arg1)); - CBotGlobals::botMessage(pClient!=NULL ? pClient->getPlayer() : NULL, - 0,"Removed path from <%d> to <%d>",atoi(pcmd),atoi(arg1)); - - pWaypoint->draw(pClient->getPlayer(),true,DRAWTYPE_DEBUGENGINE); - pWaypoint->info(pClient->getPlayer()); - pWaypoint2->draw(pClient->getPlayer(),true,DRAWTYPE_DEBUGENGINE); - pWaypoint2->info(pClient->getPlayer()); - - pClient->playSound("buttons/button24"); - - return COMMAND_ACCESSED; - } - else - CBotGlobals::botMessage(pClient!=NULL ? pClient->getPlayer() : NULL, - 0,"Waypoint id <%d> not found",atoi(arg1)); - - } - else - CBotGlobals::botMessage(pClient!=NULL ? pClient->getPlayer() : NULL, - 0,"Waypoint id <%d> not found",atoi(pcmd)); - } - else - CBotGlobals::botMessage(pClient!=NULL ? pClient->getPlayer() : NULL, - 0,"missing args "); - - return COMMAND_ERROR; -} - -CPathWaypointRemove1Command :: CPathWaypointRemove1Command() -{ - setName("remove1"); - setAccessLevel(CMD_ACCESS_WAYPOINT); -} - -eBotCommandResult CPathWaypointRemove1Command :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - pClient->updateCurrentWaypoint(); - - if ( pClient->currentWaypoint() != -1 ) - { - pClient->setPathFrom(pClient->currentWaypoint()); - pClient->playSound("common/wpn_hudoff.wav"); - } - else - pClient->playSound("common/wpn_moveselect.wav"); - - return COMMAND_ACCESSED; -} - -CPathWaypointRemove2Command :: CPathWaypointRemove2Command() -{ - setName("remove2"); - setAccessLevel(CMD_ACCESS_WAYPOINT); -} - -eBotCommandResult CPathWaypointRemove2Command :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - pClient->updateCurrentWaypoint(); - pClient->setPathTo(pClient->currentWaypoint()); - - CWaypoint *pWpt = CWaypoints::getWaypoint(pClient->getPathFrom()); - - // valid? - if ( !pWpt ) - pClient->playSound("common/wpn_moveselect"); - else - { - pClient->playSound("buttons/button9"); - - pWpt->removePathTo(pClient->getPathTo()); - } - - return COMMAND_ACCESSED; -} -///////////// -CWaypointAutoFix :: CWaypointAutoFix () -{ - setName("autofix"); -} - -eBotCommandResult CWaypointAutoFix :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - bool bFixSentry_Sniper_Defend_TeleExtWpts = false; - - if ( pcmd && *pcmd ) - { - bFixSentry_Sniper_Defend_TeleExtWpts = ( atoi(pcmd) == 1 ); - } - - CWaypoints::autoFix(bFixSentry_Sniper_Defend_TeleExtWpts); - - return COMMAND_ACCESSED; -} - -//////////// - -CWaypointAreaSetToNearest::CWaypointAreaSetToNearest() -{ - setName("setareatonearest"); -} - -eBotCommandResult CWaypointAreaSetToNearest::execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient ) - { - int id; - CWaypoint *pWpt; - bool bOk = false; - int setarea = 0; - - id = pClient->currentWaypoint(); - - if ( (pWpt=CWaypoints::getWaypoint(id)) != NULL ) - { - if ( pWpt->isUsed() ) - { - - if ( CBotGlobals::isCurrentMod(MOD_TF2) ) - setarea = CTeamFortress2Mod::m_ObjectiveResource.NearestArea(pWpt->getOrigin()); - else if (CBotGlobals::isCurrentMod(MOD_DOD) ) - setarea = CDODMod::m_Flags.findNearestObjective(pWpt->getOrigin()); - - if ( setarea > 0 ) - pWpt->setArea(setarea); - - bOk = true; - } - } - - if ( bOk ) - { - if ( setarea > 0 ) - CBotGlobals::botMessage(pClient->getPlayer(),0,"Changed waypoint %d area to %d",id,setarea); - else - CBotGlobals::botMessage(pClient->getPlayer(),0,"No nearest area to wpt id %d",id); - } - else - { - CBotGlobals::botMessage(pClient->getPlayer(),0,"Invalid waypoint id %d",id); - } - return COMMAND_ACCESSED; - } - - return COMMAND_ERROR; -} - -/////////////// -CWaypointCheckCommand::CWaypointCheckCommand() -{ - setName("check"); -} - -eBotCommandResult CWaypointCheckCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - // loop through every waypoint and check the areas are not outside the number of control points - - CWaypoints::checkAreas((pClient==NULL)?NULL:pClient->getPlayer()); - - return COMMAND_ACCESSED; -} - -CWaypointTeleportCommand::CWaypointTeleportCommand() -{ - setName("teleport"); -} - -eBotCommandResult CWaypointTeleportCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient && pcmd && *pcmd ) - { - int id; - CWaypoint *pWpt; - bool bTele = false; - - id = atoi(pcmd); - - if ( (pWpt=CWaypoints::getWaypoint(id)) != NULL ) - { - if ( pWpt->isUsed() ) - { - pClient->teleportTo(pWpt->getOrigin()+Vector(0,0,8)); - bTele = true; - } - } - - if ( bTele ) - { - CBotGlobals::botMessage(pClient->getPlayer(),0,"Teleported to waypoint %d",id); - } - else - { - CBotGlobals::botMessage(pClient->getPlayer(),0,"Invalid waypoint id %d",id); - } - - return COMMAND_ACCESSED; - } - - return COMMAND_ERROR; -} -////////////// - -CWaypointAngleCommand :: CWaypointAngleCommand() -{ - setName("angle"); -} - -eBotCommandResult CWaypointAngleCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient && pClient->getPlayer() ) - { - pClient->updateCurrentWaypoint(); - - CWaypoint *pWpt = CWaypoints::getWaypoint(pClient->currentWaypoint()); - - if ( pWpt ) - { - QAngle eye = CBotGlobals::playerAngles(pClient->getPlayer()); - CBotGlobals::botMessage(pClient->getPlayer(),0,"Waypoint Angle == %0.3f deg, (Eye == %0.3f)",CBotGlobals::yawAngleFromEdict(pClient->getPlayer(),pWpt->getOrigin()),eye.y); - pClient->playSound("buttons/combine_button1"); - } - } - - return COMMAND_ACCESSED; -} - -CWaypointInfoCommand :: CWaypointInfoCommand() -{ - setName("info"); -} - -eBotCommandResult CWaypointInfoCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - pClient->updateCurrentWaypoint(); - - CWaypoint *pWpt = CWaypoints::getWaypoint(pClient->currentWaypoint()); - - if ( pWpt ) - pWpt->info(pClient->getPlayer()); - - return COMMAND_ACCESSED; -} - -eBotCommandResult CWaypointSaveCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( CWaypoints::save(false,(pClient!=NULL)?pClient->getPlayer():NULL,((pcmd!=NULL) && (*pcmd!=0))?pcmd:NULL,((arg1!=NULL) && (*arg1!=0))?arg1:NULL) ) - { - CBotGlobals::botMessage(NULL,0,"waypoints saved"); - if ( pClient ) - pClient->giveMessage("Waypoints Saved"); - } - else - CBotGlobals::botMessage(NULL,0,"error: could not save waypoints"); - - return COMMAND_ACCESSED; -} - -eBotCommandResult CWaypointLoadCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - char *szMapName = CBotGlobals::getMapName(); - bool bLoadOK = false; - - if ( pcmd && *pcmd ) - { - bLoadOK = CWaypoints::load(pcmd); - szMapName = (char*)pcmd; - } - else - bLoadOK = CWaypoints::load(); - - if ( bLoadOK ) - CBotGlobals::botMessage(NULL,0,"waypoints %s loaded",szMapName); - else - CBotGlobals::botMessage(NULL,0,"error: could not load %s waypoints",szMapName); - - return COMMAND_ACCESSED; -} - -//usage \"memorycheck \""); -eBotCommandResult CDebugMemoryCheckCommand:: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - // pcmd = classname - // arg1 = offset - // arg2 = type - NEED_ARG(pcmd); - NEED_ARG(arg1); - NEED_ARG(arg2); - // find edict - edict_t *pEdict = CClassInterface::FindEntityByClassnameNearest(pClient->getOrigin(),pcmd); - - if ( pEdict == NULL ) - { - CBotGlobals::botMessage(pClient->getPlayer(),0,"Edict not found"); - return COMMAND_ERROR; - } - - CBaseEntity *pent = pEdict->GetUnknown()->GetBaseEntity(); - - unsigned int offset = atoi(arg1); - - if ( ( strcmp(arg2,"bool") == 0 ) || ( strcmp(arg2,"byte") == 0 )) - { - CBotGlobals::botMessage(pClient->getPlayer(),0,"%s - offset %d - Value(byte) = %d",pcmd,offset,*(byte*)(((unsigned long)pent) + offset)); - } - else if ( strcmp(arg2,"int") == 0 ) - { - CBotGlobals::botMessage(pClient->getPlayer(),0,"%s - offset %d - Value(int) = %d",pcmd,offset,*(int*)(((unsigned long)pent) + offset)); - /* - if ( strcmp(pcmd,"team_control_point_master") == 0 ) - { - CTeamControlPointMaster *p; - CTeamControlPointMaster check; - - unsigned int knownoffset = (unsigned int)&check.m_iCurrentRoundIndex - (unsigned int)✓ - - p = (CTeamControlPointMaster*)((((unsigned long)pent) + offset) - knownoffset); //MAP_CLASS(CTeamControlPoint,(((unsigned long)pent) + offset),knownoffset); - } - else if ( strcmp(pcmd,"team_control_point") == 0 ) - { - extern ConVar rcbot_const_point_offset; - extern ConVar rcbot_const_point_data_offset; - - CTeamControlPoint *p = (CTeamControlPoint*)((((unsigned long)pent) + rcbot_const_point_offset.GetInt())); //MAP_CLASS(CTeamControlPoint,(((unsigned long)pent) + offset),knownoffset); -// CTeamControlPointData *d = (CTeamControlPointData*)((((unsigned long)pent) + rcbot_const_point_data_offset.GetInt())); - - CBotGlobals::botMessage(NULL,0,"NULL MSG"); - }*/ - - } - else if ( strcmp(arg2,"float") == 0 ) - CBotGlobals::botMessage(pClient->getPlayer(),0,"%s - offset %d - Value(float) = %0.6f",pcmd,offset,*(float*)(((unsigned long)pent) + offset)); - else if ( strcmp(arg2,"string") == 0 ) - { - string_t *str = (string_t*)(((unsigned long)pent) + offset); - if ( str ) - CBotGlobals::botMessage(pClient->getPlayer(),0,"%s - offset %d - Value(string) = %s",pcmd,offset,STRING(*str)); - else - CBotGlobals::botMessage(pClient->getPlayer(),0,"%s - offset %d - INVALID string",pcmd,offset); - } - else - return COMMAND_ERROR; - - return COMMAND_ACCESSED; -} - -#define MEMSEARCH_BYTE 1 -#define MEMSEARCH_INT 2 -#define MEMSEARCH_FLOAT 3 -#define MEMSEARCH_STRING 4 - -eBotCommandResult CDebugMemoryScanCommand:: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - //pcmd = classname - // arg1 = value - // arg2 = size in bytes - // arg3 = want to remember offsets or not - - NEED_ARG(pcmd); - NEED_ARG(arg1); - NEED_ARG(arg2); - - unsigned int m_prev_size = m_size; - - if ( ( strcmp(arg2,"bool") == 0 ) || ( strcmp(arg2,"byte") == 0 )) - m_size = MEMSEARCH_BYTE; - else if ( strcmp(arg2,"int") == 0 ) - m_size = MEMSEARCH_INT; - else if ( strcmp(arg2,"float") == 0 ) - m_size = MEMSEARCH_FLOAT; - else if ( strcmp(arg2,"string") == 0 ) - m_size = MEMSEARCH_STRING; - else - m_size = 0; - - if ( (m_prev_size != m_size) || ((m_size==0) || !arg3 || !*arg3) || ( atoi(arg3) == 0 ) ) - { - memset(stored_offsets,0,sizeof(u_MEMSEARCH)*MAX_MEM_SEARCH); - } - - - // find edict - edict_t *pEdict = CClassInterface::FindEntityByClassnameNearest(pClient->getOrigin(),pcmd); - - if ( pEdict == NULL ) - { - CBotGlobals::botMessage(pClient->getPlayer(),0,"Edict not found"); - return COMMAND_ERROR; - } - - // begin memory scan - CBaseEntity *pent = pEdict->GetUnknown()->GetBaseEntity(); - - byte *mempoint = (byte*)pent; - byte value = (byte)atoi(arg1); - int ivalue = (atoi(arg1)); - float fvalue = (atof(arg1)); - - bool bfound; - - for ( int i = 0; i < MAX_MEM_SEARCH; i ++ ) // 2KB search - { - bfound = false; - - if ( m_size == MEMSEARCH_BYTE ) - bfound = (value == *mempoint); - else if ( m_size == MEMSEARCH_INT ) - bfound = (ivalue == *(int*)mempoint); - else if ( m_size == MEMSEARCH_FLOAT ) - bfound = (fvalue == *(float*)mempoint); - else if ( m_size == MEMSEARCH_STRING ) - { - try - { - string_t *str = (string_t*) mempoint; - - if ( str != NULL ) - { - const char *pszstr = STRING(*str); - - if ( pszstr ) - bfound = ( strcmp(pszstr,arg1) == 0 ); - } - } - catch(...) - { - CBotGlobals::botMessage(pClient->getPlayer(),0,"Invalid string"); - } - } - - if ( bfound ) - { - if ( !stored_offsets[i].b1.searched ) - stored_offsets[i].b1.found = 1; - } - else if ( stored_offsets[i].b1.searched ) - stored_offsets[i].b1.found = 0; - - stored_offsets[i].b1.searched = 1; - - mempoint++; - } - - // Current valid offsets print - for ( int i = 0; i < MAX_MEM_SEARCH; i ++ ) - { - if ( stored_offsets[i].data != 0 ) - { - if ( stored_offsets[i].b1.found ) - CBotGlobals::botMessage(pClient->getPlayer(),0,"%d",i); - } - } - // - - return COMMAND_ACCESSED; -} - - -eBotCommandResult CDebugGameEventCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( !pcmd || !*pcmd ) - return COMMAND_ERROR; - - pClient->setDebug(BOT_DEBUG_GAME_EVENT,atoi(pcmd)>0); - - return COMMAND_ACCESSED; -} - -eBotCommandResult CDebugVisCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( !pcmd || !*pcmd ) - return COMMAND_ERROR; - - pClient->setDebug(BOT_DEBUG_VIS,atoi(pcmd)>0); - - return COMMAND_ACCESSED; -} - -eBotCommandResult CDebugThinkCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( !pcmd || !*pcmd ) - return COMMAND_ERROR; - - pClient->setDebug(BOT_DEBUG_THINK,atoi(pcmd)>0); - - return COMMAND_ACCESSED; -} - -eBotCommandResult CDebugLookCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( !pcmd || !*pcmd ) - return COMMAND_ERROR; - - pClient->setDebug(BOT_DEBUG_LOOK,atoi(pcmd)>0); - - return COMMAND_ACCESSED; -} - -eBotCommandResult CDebugHudCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( !pcmd || !*pcmd ) - return COMMAND_ERROR; - - pClient->setDebug(BOT_DEBUG_HUD,atoi(pcmd)>0); - - return COMMAND_ACCESSED; -} -eBotCommandResult CDebugAimCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( !pcmd || !*pcmd ) - return COMMAND_ERROR; - - pClient->setDebug(BOT_DEBUG_AIM,atoi(pcmd)>0); - - return COMMAND_ACCESSED; -} - -eBotCommandResult CDebugChatCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( !pcmd || !*pcmd ) - return COMMAND_ERROR; - - pClient->setDebug(BOT_DEBUG_CHAT,atoi(pcmd)>0); - - return COMMAND_ACCESSED; -} - -eBotCommandResult CDebugProfilingCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( !pcmd || !*pcmd ) - return COMMAND_ERROR; - - pClient->setDebug(BOT_DEBUG_PROFILE,atoi(pcmd)>0); - - return COMMAND_ACCESSED; -} - -eBotCommandResult CDebugNavCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( !pcmd || !*pcmd ) - return COMMAND_ERROR; - - pClient->setDebug(BOT_DEBUG_NAV,atoi(pcmd)>0); - - return COMMAND_ACCESSED; -} - -eBotCommandResult CDebugTaskCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( !pcmd || !*pcmd ) - return COMMAND_ERROR; - - pClient->setDebug(BOT_DEBUG_TASK,atoi(pcmd)>0); - - return COMMAND_ACCESSED; -} - -eBotCommandResult CGodModeUtilCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient ) - { - edict_t *pEntity = pClient->getPlayer(); - - if ( pEntity ) - { - int *playerflags = CClassInterface::getPlayerFlagsPointer(pEntity); - - if ( playerflags ) - { - char msg[256]; - - if ( *playerflags & FL_GODMODE ) - *playerflags &= ~FL_GODMODE; - else - *playerflags |= FL_GODMODE; - - sprintf(msg,"god mode %s",(*playerflags & FL_GODMODE)?"enabled":"disabled"); - - //CRCBotPlugin::HudTextMessage(pEntity,msg); - CBotGlobals::botMessage(pEntity,0,msg); +#include "bot_commands.h" +#include "bot.h" +#include "bot_accessclient.h" +#include "bot_client.h" +#include "bot_cvars.h" +#include "bot_getprop.h" +#include "bot_globals.h" +#include "bot_menu.h" +#include "bot_schedule.h" +#include "bot_strings.h" +#include "bot_waypoint.h" // for waypoint commands +#include "bot_waypoint_locations.h" // for waypoint commands +#include "bot_waypoint_visibility.h" +#include "bot_weapons.h" +#include "ndebugoverlay.h" - return COMMAND_ACCESSED; +#include "bot_tf2_points.h" - } - } - } +extern IVDebugOverlay* debugoverlay; - return COMMAND_ERROR; -} +// include our subcommands +#include "rcbot_subcmds/config.cpp" +#include "rcbot_subcmds/debug.cpp" +#include "rcbot_subcmds/pathwaypoint.cpp" +#include "rcbot_subcmds/users.cpp" +#include "rcbot_subcmds/util.cpp" +#include "rcbot_subcmds/waypoint.cpp" -eBotCommandResult CSetTeleportUtilCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient ) - { - pClient->setTeleportVector(); - engine->ClientPrintf(pClient->getPlayer(),"Teleport Position Remembered!"); - return COMMAND_ACCESSED; - } +// temporarily declared at the bottom +// CBotSubcommands *CBotGlobals :: m_pCommands; - return COMMAND_ERROR; +eBotCommandResult CBotCommandInline::execute(CClient* pClient, const BotCommandArgs& args) { + // fire off callback function + return m_Callback(pClient, args); } -eBotCommandResult CTeleportUtilCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( pClient ) +CBotCommandInline ControlCommand("control", CMD_ACCESS_BOT | CMD_ACCESS_DEDICATED, [](const CClient* pClient, + const BotCommandArgs& args) { - Vector *vTeleport; - - vTeleport = pClient->getTeleportVector(); + edict_t* pEntity = nullptr; - if ( vTeleport != NULL ) + if (pClient) + pEntity = pClient->getPlayer(); + if (args[0] && *args[0]) { - CBotGlobals::teleportPlayer(pClient->getPlayer(),*vTeleport); - //CRCBotPlugin::HudTextMessage(pClient->getPlayer(),"teleported to your remembered location"); - CBotGlobals::botMessage(pClient->getPlayer(),0,"teleported to your remembered location"); + if (CBots::controlBot(args[0], args[0], args[2], args[3])) + CBotGlobals::botMessage(pEntity, 0, "bot added"); + else + CBotGlobals::botMessage(pEntity, 0, "error: couldn't control bot '%s'", args[0]); return COMMAND_ACCESSED; - } - } - - return COMMAND_ERROR; -} - -eBotCommandResult CNoTouchCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - - if ( pClient ) - { - edict_t *pEntity = pClient->getPlayer(); - - if ( pEntity ) - { - int *playerflags = CClassInterface::getPlayerFlagsPointer(pEntity); - - if ( playerflags ) - { - char msg[256]; - - if ( *playerflags & FL_DONTTOUCH ) - *playerflags &= ~FL_DONTTOUCH; - else - *playerflags |= FL_DONTTOUCH; - - sprintf(msg,"notouch mode %s",(*playerflags & FL_DONTTOUCH)?"enabled":"disabled"); - CBotGlobals::botMessage(NULL,0,msg); - //CRCBotPlugin::HudTextMessage(pEntity,msg); - return COMMAND_ACCESSED; - - } } - } - - return COMMAND_ERROR; -} - -eBotCommandResult CNoClipCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - - edict_t *pEntity = NULL; - - if ( pClient ) - pEntity = pClient->getPlayer(); - - if ( pEntity ) - { - char msg[256]; - byte *movetype = CClassInterface::getMoveTypePointer(pEntity); - - - if ( (*movetype & 15) != MOVETYPE_NOCLIP ) - { - *movetype &= ~15; - *movetype |= MOVETYPE_NOCLIP; - } - else - { - *movetype &= ~15; - *movetype |= MOVETYPE_WALK; - } - - sprintf(msg,"%s used no_clip %d on self\n",pClient->getName(),((*movetype & 15) == MOVETYPE_NOCLIP)); - - // CRCBotPlugin::HudTextMessage(pEntity,msg); - CBotGlobals::botMessage(pEntity,0,msg); - return COMMAND_ACCESSED; - } - - return COMMAND_ERROR; -} - - -eBotCommandResult CDebugUtilCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( !pcmd || !*pcmd ) - return COMMAND_ERROR; - - pClient->setDebug(BOT_DEBUG_UTIL,atoi(pcmd)>0); - - return COMMAND_ACCESSED; -} - -eBotCommandResult CDebugEdictsCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( !pcmd || !*pcmd ) - return COMMAND_ERROR; - - pClient->setDebug(BOT_DEBUG_EDICTS,atoi(pcmd)>0); - - return COMMAND_ACCESSED; -} - -eBotCommandResult CDebugSpeedCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( !pcmd || !*pcmd ) - return COMMAND_ERROR; - - pClient->setDebug(BOT_DEBUG_SPEED,atoi(pcmd)>0); - - return COMMAND_ACCESSED; -} - -eBotCommandResult CDebugUsercmdCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( !pcmd || !*pcmd ) - return COMMAND_ERROR; - - pClient->setDebug(BOT_DEBUG_USERCMD,atoi(pcmd)>0); - - return COMMAND_ACCESSED; -} - - -eBotCommandResult CDebugButtonsCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( !pcmd || !*pcmd ) return COMMAND_ERROR; + }); - pClient->setDebug(BOT_DEBUG_BUTTONS,atoi(pcmd)>0); - - return COMMAND_ACCESSED; -} - -eBotCommandResult CDebugBotCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) +CBotCommandInline AddBotCommand("addbot", CMD_ACCESS_BOT | CMD_ACCESS_DEDICATED, [](const CClient* pClient, + const BotCommandArgs& args) { - if ( (!pcmd || !*pcmd) ) - { - extern IServerGameEnts *servergameents; - // do a traceline in front of player - - Vector vOrigin = pClient->getOrigin(); - QAngle angles = CBotGlobals::entityEyeAngles(pClient->getPlayer()); - Vector forward; +// bool bOkay = false; - AngleVectors(angles,&forward); + edict_t* pEntity = nullptr; - CBotGlobals::quickTraceline(pClient->getPlayer(),vOrigin,vOrigin+forward*1024.0f); - CBaseEntity *pEntity; + if (pClient) + pEntity = pClient->getPlayer(); - if ( (pEntity = CBotGlobals::getTraceResult()->m_pEnt) != NULL ) - { - edict_t *pEdict = servergameents->BaseEntityToEdict(pEntity); - if ( CBots::getBotPointer(pEdict) != NULL ) - { - pClient->setDebugBot(pEdict); - CBotGlobals::botMessage(pClient->getPlayer(),0,"debug bot set to bot you are looking at"); - return COMMAND_ACCESSED; - } - else - { - pClient->setDebugBot(NULL); - CBotGlobals::botMessage(pClient->getPlayer(),0,"debug bot cleared"); - } - } - else - { - pClient->setDebugBot(NULL); - CBotGlobals::botMessage(pClient->getPlayer(),0,"debug bot cleared"); - } - return COMMAND_ERROR; - } + // That breaks the bot quota system? [APG]RoboCop[CL] + /*if (rcbot_bot_quota_interval.GetFloat() > 0) { + CBotGlobals::botMessage(pEntity, 0, "error: cannot manually add bot while rcbot_bot_quota_interval is active"); + return COMMAND_ACCESSED; + }*/ - edict_t *pEnt = CBotGlobals::findPlayerByTruncName(pcmd); + //if ( !bot_sv_cheat_warning.GetBool() || bot_sv_cheats_auto.GetBool() || (!sv_cheats || sv_cheats->GetBool()) ) + //{ + //if ( !args[0] || !*args[0] ) + // bOkay = CBots::createBot(); + //else + //bOkay = CBots::createBot(); - if ( !pEnt ) - { - CBotGlobals::botMessage(pClient->getPlayer(),0,"can't find a player with that name"); - return COMMAND_ERROR; + if (CBots::createBot(args[0], args[1], args[2])) { + CBotGlobals::botMessage(pEntity, 0, "bot adding..."); } - - CBot *pBot = CBots::getBotPointer(pEnt); - - if ( !pBot ) - { - CBotGlobals::botMessage(pClient->getPlayer(),0,"can't find a bot with that name"); - return COMMAND_ERROR; + else { + CBotGlobals::botMessage(pEntity, 0, "error: couldn't create bot! (Check maxplayers)"); } - pClient->setDebugBot(pBot->getEdict()); - - return COMMAND_ACCESSED; -} - -/////////////////////// -// command - -CUtilCommand :: CUtilCommand() -{ - setName("util"); - add(new CSearchCommand()); - add(new CSetTeleportUtilCommand()); - add(new CTeleportUtilCommand()); - add(new CNoClipCommand()); - add(new CGodModeUtilCommand()); - add(new CNoTouchCommand()); -} - -CConfigCommand :: CConfigCommand() -{ - setName("config"); - add(new CGameEventVersion()); - add(new CMaxBotsCommand()); - add(new CMinBotsCommand()); -} - -eBotCommandResult CGameEventVersion :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - if ( !pcmd || !*pcmd ) - return COMMAND_ERROR; + //} + //else + // CBotGlobals::botMessage(pEntity,0,"error: sv_cheats must be 1 to add bots"); - CBotGlobals::setEventVersion(atoi(pcmd)); - return COMMAND_ACCESSED; -} + }); - -// kickbot -eBotCommandResult CKickBotCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) +CBotCommandInline KickBotCommand("kickbot", CMD_ACCESS_BOT | CMD_ACCESS_DEDICATED, [](CClient* pClient, + const BotCommandArgs& args) { - if ( !pcmd || !*pcmd ) + if (!args[0] || !*args[0]) { - //remove random bot - CBots::kickRandomBot(); + if (rcbot_nonrandom_kicking.GetBool()) { + CBots::kickChosenBot(); + } else { + CBots::kickRandomBot(); + } } else { - int team = atoi(pcmd); + const int team = std::atoi(args[0]); - CBots::kickRandomBotOnTeam(team); + if (rcbot_nonrandom_kicking.GetBool()) { + CBots::kickChosenBotOnTeam(team); + } else { + CBots::kickRandomBotOnTeam(team); + } } - return COMMAND_ACCESSED; -} +}, R"(usage "kickbot" or "kickbot " : kicks random bot or bot on team: )"); -eBotCommandResult CShowUsersCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) +bool CBotCommand::hasAccess(const CClient* pClient) const { - edict_t *pEntity = NULL; - - if ( pClient ) - pEntity = pClient->getPlayer(); - - CAccessClients::showUsers(pEntity); - - return COMMAND_ACCESSED; + // check access level excluding dedicated server flag + const int iClientAccessLevel = this->m_iAccessLevel & ~CMD_ACCESS_DEDICATED; + return (iClientAccessLevel & pClient->accessLevel()) == iClientAccessLevel; } -eBotCommandResult CMaxBotsCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) +bool CBotCommand::isCommand(const char* szCommand) const { - edict_t *pEntity = NULL; - - if ( pClient ) - pEntity = pClient->getPlayer(); + return FStrEq(szCommand, m_szCommand); +} - if ( pcmd && *pcmd ) - { - int max = atoi(pcmd); +eBotCommandResult CBotCommand::execute(CClient* pClient, const BotCommandArgs& args) { + return COMMAND_NOT_FOUND; +} - bool err = false; - int min_bots = CBots::getMinBots(); +eBotCommandResult CBotSubcommands::execute(CClient* pClient, const BotCommandArgs& args) { + BotCommandArgs mutableArgs = args; // Make a mutable copy + const char* subcmd = mutableArgs[0]; + mutableArgs.pop_front(); - if ( max <= -1 )// skip check for disabling max bots (require <=) - max = -1; - else if ( (min_bots >= 0) && (max <= min_bots) ) - { - CBotGlobals::botMessage(pEntity,0,"max_bots must be greater than min_bots (min_bots is currently : %d)",min_bots); - err = true; + for (CBotCommand* const cmd : m_theCommands) { + if (!cmd->isCommand(subcmd)) { + continue; } - if ( max > CBotGlobals::maxClients() ) - max = CBotGlobals::maxClients(); - - if ( !err ) - { - CBots :: setMaxBots(max); - CBotGlobals::botMessage(pEntity,0,"max_bots set to %d",max); + if (pClient && !cmd->hasAccess(pClient)) { + return COMMAND_REQUIRE_ACCESS; } - - } - else - CBotGlobals::botMessage(pEntity,0,"max_bots is currently %d",CBots::getMaxBots()); - - return COMMAND_ACCESSED; -} - -eBotCommandResult CMinBotsCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - edict_t *pEntity = NULL; - - if ( pClient ) - pEntity = pClient->getPlayer(); - - if ( pcmd && *pcmd ) - { - int min = atoi(pcmd); - int max_bots = CBots::getMaxBots(); - - bool err = false; - - if ( min > CBotGlobals::maxClients() ) - min = CBotGlobals::maxClients(); - - if ( min <= -1 ) // skip check for disabling min bots (require <=) - min = -1; - else if ( (max_bots >= 0) && (min >= CBots::getMaxBots()) ) - { - CBotGlobals::botMessage(pEntity,0,"min_bots must be less than max_bots (max_bots is currently : %d)",max_bots); - err = true; - } - - if ( !err ) - { - CBots :: setMinBots(min); - - CBotGlobals::botMessage(pEntity,0,"min_bots set to %d",min); + if (!pClient && !cmd->canbeUsedDedicated()) { + CBotGlobals::botMessage(nullptr, 0, "Sorry, this command cannot be used on a dedicated server"); + return COMMAND_ERROR; } - } - else - CBotGlobals::botMessage(pEntity,0,"min_bots is currently %d",CBots::getMinBots()); - - return COMMAND_ACCESSED; -} - -eBotCommandResult CSearchCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ - int i = 0; - - edict_t *pPlayer = pClient->getPlayer(); - edict_t *pEdict; - float fDistance; - string_t model; - - for ( i = 0; i < gpGlobals->maxEntities; i ++ ) - { - pEdict = INDEXENT(i); - - if ( pEdict ) - { - if ( !pEdict->IsFree() ) - { - if ( pEdict->m_pNetworkable && pEdict->GetIServerEntity() ) - { - if ( (fDistance=(CBotGlobals::entityOrigin(pEdict) - CBotGlobals::entityOrigin(pPlayer)).Length()) < 128 ) - { - float fVelocity; - Vector v; - - if ( CClassInterface::getVelocity(pEdict,&v) ) - fVelocity = v.Length(); - else - fVelocity = 0; - model = pEdict->GetIServerEntity()->GetModelName(); - - CBotGlobals::botMessage(pPlayer,0,"(%d) D:%0.2f C:'%s', Mid:%d, Mn:'%s' Health=%d, Tm:%d, Fl:%d, Spd=%0.2f",i,fDistance,pEdict->GetClassName(),pEdict->GetIServerEntity()->GetModelIndex(),model.ToCStr(),(int)CClassInterface::getPlayerHealth(pEdict),(int)CClassInterface::getTeam(pEdict),pEdict->m_fStateFlags,fVelocity ); - } - } - } + // shift arguments and call + const eBotCommandResult result = cmd->execute(pClient, mutableArgs); + if (result == COMMAND_ERROR) { + cmd->printHelp(pClient ? pClient->getPlayer() : nullptr); } + return COMMAND_ACCESSED; } - return COMMAND_ACCESSED; - -} -////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////// -void CBotCommand :: setName ( char *szName ) -{ - m_szCommand = CStrings::getString(szName); -} - -void CBotCommand :: setHelp ( char *szHelp ) -{ - m_szHelp = CStrings::getString(szHelp); -} - -void CBotCommand :: setAccessLevel ( int iAccessLevel ) -{ - m_iAccessLevel = iAccessLevel; -} - -CBotCommand :: CBotCommand ( char *szCommand, int iAccessLevel ) -{ - m_szCommand = CStrings::getString(szCommand); - m_iAccessLevel = iAccessLevel; -} - -void CBotCommand :: freeMemory () -{ - // nothing to free -- done in CStrings -} - -bool CBotCommand :: hasAccess ( CClient *pClient ) -{ - return (m_iAccessLevel & pClient->accessLevel()) == m_iAccessLevel; -} - -bool CBotCommand :: isCommand ( const char *szCommand ) -{ - return FStrEq(szCommand,m_szCommand); -} - -eBotCommandResult CBotCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) -{ + printHelp(pClient ? pClient->getPlayer() : nullptr); return COMMAND_NOT_FOUND; } - -//////////////////////////// -// container of commands -eBotCommandResult CBotCommandContainer :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) +void CBotSubcommands::printCommand(edict_t* pPrintTo, const int indent) { - for ( unsigned int i = 0; i < m_theCommands.size(); i ++ ) + if (indent) { - CBotCommand *pCommand = m_theCommands[i]; + constexpr int maxIndent = 64; + char szIndent[maxIndent] = {}; - if ( pCommand->isCommand(pcmd) ) - { - if ( pClient && !pCommand->hasAccess(pClient) ) - return COMMAND_REQUIRE_ACCESS; - if ( !pClient && !canbeUsedDedicated() ) - { - CBotGlobals::botMessage(NULL,0,"Sorry, this command cannot be used on a dedicated server"); - return COMMAND_ERROR; - } - // move arguments - eBotCommandResult iResult = pCommand->execute(pClient,arg1,arg2,arg3,arg4,arg5,NULL); + for (int i = 0; (i < (indent * 2)) && (i < maxIndent - 1); i++) + szIndent[i] = ' '; - if ( iResult == COMMAND_ERROR ) - { - if ( pClient ) - pCommand->printHelp(pClient->getPlayer()); - else - pCommand->printHelp(NULL); - } - - return COMMAND_ACCESSED; - } + CBotGlobals::botMessage(pPrintTo, 0, "%s[%s]", szIndent, m_szCommand); } - - if ( pClient ) - printHelp(pClient->getPlayer()); else - printHelp(NULL); - - return COMMAND_NOT_FOUND; -} + CBotGlobals::botMessage(pPrintTo, 0, "[%s]", m_szCommand); -void CBotCommandContainer :: freeMemory () -{ - for ( unsigned int i = 0; i < m_theCommands.size(); i ++ ) + for (CBotCommand* const& m_theCommand : m_theCommands) { - m_theCommands[i]->freeMemory(); - delete m_theCommands[i]; - m_theCommands[i] = NULL; + m_theCommand->printCommand(pPrintTo, indent + 1); } +} - m_theCommands.clear(); +void CBotSubcommands::printHelp(edict_t* pPrintTo) { + this->printCommand(pPrintTo); } -////////////////////////////////////////// -eBotCommandResult CPrintCommands ::execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) +CBotCommandInline PrintCommands("printcommands", CMD_ACCESS_DEDICATED, [](const CClient* pClient, const BotCommandArgs& args) { - if ( pClient != NULL ) + if ( pClient != nullptr) { CBotGlobals::botMessage(pClient->getPlayer(),0,"All bot commands:"); CBotGlobals::m_pCommands->printCommand(pClient->getPlayer()); } else { - CBotGlobals::botMessage(NULL,0,"All bot commands:"); - CBotGlobals::m_pCommands->printCommand(NULL); + CBotGlobals::botMessage(nullptr,0,"All bot commands:"); + CBotGlobals::m_pCommands->printCommand(nullptr); } return COMMAND_ACCESSED; -} +}); /////////////////////////////////////////// -void CBotCommand :: printCommand ( edict_t *pPrintTo, int indent ) +void CBotCommand::printCommand(edict_t* pPrintTo, const int indent) { - if ( indent ) + if (indent) { - const int maxIndent = 64; + constexpr int maxIndent = 64; char szIndent[maxIndent]; int i; - for ( i = 0; (i < (indent*2)) && (i < maxIndent-1); i ++ ) + for (i = 0; (i < (indent * 2)) && (i < maxIndent - 1); i++) szIndent[i] = ' '; - szIndent[maxIndent-1] = 0; - szIndent[i]=0; + szIndent[maxIndent - 1] = 0; + szIndent[i] = 0; - if ( !pPrintTo && !canbeUsedDedicated() ) - CBotGlobals::botMessage(pPrintTo,0,"%s%s [can't use]",szIndent,m_szCommand); + if (!pPrintTo && !canbeUsedDedicated()) + CBotGlobals::botMessage(pPrintTo, 0, "%s%s [can't use]", szIndent, m_szCommand); else - CBotGlobals::botMessage(pPrintTo,0,"%s%s",szIndent,m_szCommand); + CBotGlobals::botMessage(pPrintTo, 0, "%s%s", szIndent, m_szCommand); } else { - if ( !pPrintTo && !canbeUsedDedicated() ) - CBotGlobals::botMessage(pPrintTo,0,"%s [can't use]",m_szCommand); + if (!pPrintTo && !canbeUsedDedicated()) + CBotGlobals::botMessage(pPrintTo, 0, "%s [can't use]", m_szCommand); else - CBotGlobals::botMessage(pPrintTo,0,m_szCommand); + CBotGlobals::botMessage(pPrintTo, 0, m_szCommand); } } -void CBotCommand :: printHelp ( edict_t *pPrintTo ) -{ - if ( m_szHelp ) - CBotGlobals::botMessage(pPrintTo,0,m_szHelp); - else - CBotGlobals::botMessage(pPrintTo,0,"Sorry, no help for this command (yet)"); - - return; -} - -void CBotCommandContainer :: printCommand ( edict_t *pPrintTo, int indent ) +void CBotCommand::printHelp(edict_t* pPrintTo) { - //char cmd1[512]; - //char cmd2[512]; - - //sprintf(cmd1,"%%%ds",indent); - //sprintf(cmd2,cmd1,m_szCommand); - - if ( indent ) - { - const int maxIndent = 64; - char szIndent[maxIndent]; - - int i; - - for ( i = 0; (i < (indent*2)) && (i < maxIndent-1); i ++ ) - szIndent[i] = ' '; - - szIndent[maxIndent-1] = 0; - szIndent[i]=0; - - CBotGlobals::botMessage(pPrintTo,0,"%s[%s]",szIndent,m_szCommand); - } + if (m_szHelp) + CBotGlobals::botMessage(pPrintTo, 0, m_szHelp); else - CBotGlobals::botMessage(pPrintTo,0,"[%s]",m_szCommand); - - for ( unsigned int i = 0; i < m_theCommands.size(); i ++ ) - { - m_theCommands[i]->printCommand(pPrintTo,indent+1); - } -} + CBotGlobals::botMessage(pPrintTo, 0, "Sorry, no help for this command (yet)"); -void CBotCommandContainer :: printHelp ( edict_t *pPrintTo ) -{ - printCommand(pPrintTo); - return; + //return; } - -eBotCommandResult CTestCommand :: execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ) +CBotCommandInline CTestCommand("test", 0, [](CClient* pClient, const BotCommandArgs& args) { // for developers + // first argument is at args[0] return COMMAND_NOT_FOUND; -} +}); + +CBotSubcommands* CBotGlobals::m_pCommands = new CBotSubcommands("rcbot", CMD_ACCESS_DEDICATED, { + &WaypointSubcommands, + &AddBotCommand, + &ControlCommand, + &PathWaypointSubcommands, + &DebugSubcommands, + &PrintCommands, + &ConfigSubcommands, + &KickBotCommand, + &UserSubcommands, + &UtilSubcommands +}); diff --git a/utils/RCBot2_meta/bot_commands.h b/utils/RCBot2_meta/bot_commands.h index dee946683..1b70cfafb 100644 --- a/utils/RCBot2_meta/bot_commands.h +++ b/utils/RCBot2_meta/bot_commands.h @@ -31,58 +31,79 @@ #ifndef __BOT_COMMANDS_H__ #define __BOT_COMMANDS_H__ +#include "edict.h" +#include +#include +#include +#include #include -using namespace std; class CClient; -typedef enum +typedef enum : std::uint8_t { COMMAND_NOT_FOUND, // command not found COMMAND_ACCESSED, // okay - COMMAND_ERROR, // accessed but error occurred + COMMAND_ERROR, // accessed but error occurred COMMAND_REQUIRE_ACCESS // dont have access to command -}eBotCommandResult; +} eBotCommandResult; -#define NEED_ARG(x) if ( !x || !*x ) return COMMAND_ERROR; +#define NEED_ARG(x) if ( !(x) || !*(x) ) return COMMAND_ERROR; - -#define CMD_ACCESS_NONE 0 -#define CMD_ACCESS_WAYPOINT (1<<0) -#define CMD_ACCESS_BOT (1<<1) -#define CMD_ACCESS_UTIL (1<<2) -#define CMD_ACCESS_CONFIG (1<<3) -#define CMD_ACCESS_DEBUG (1<<4) -#define CMD_ACCESS_USERS (1<<5) +enum : std::uint8_t +{ + CMD_ACCESS_NONE = 0, + CMD_ACCESS_WAYPOINT = 1<<0, + CMD_ACCESS_BOT = 1<<1, + CMD_ACCESS_UTIL = 1<<2, + CMD_ACCESS_CONFIG = 1<<3, + CMD_ACCESS_DEBUG = 1<<4, + CMD_ACCESS_USERS = 1<<5, + CMD_ACCESS_DEDICATED = 1<<6 // replaces canbeUsedDedicated +}; #define CMD_ACCESS_ALL (CMD_ACCESS_WAYPOINT|CMD_ACCESS_UTIL|CMD_ACCESS_BOT|CMD_ACCESS_CONFIG|CMD_ACCESS_DEBUG|CMD_ACCESS_USERS) +/** + * This is just a deque that returns nullptr if we access an out-of-bounds array element. + */ +class BotCommandArgs : public std::deque { +public: + const char* operator[](const std::size_t at) const + { + if (at >= this->size()) { + return nullptr; + } + return std::deque::operator[](at); + } +}; + +using BotCommandCallback = std::function; + class CBotCommand { protected: - CBotCommand () - { - m_iAccessLevel = 0; - m_szCommand = NULL; - m_szHelp = NULL; - } + CBotCommand () : m_iAccessLevel{0}, m_szCommand{nullptr}, m_szHelp{nullptr} { } + public: + virtual ~CBotCommand() = default; + // initialise - CBotCommand ( char *szCommand, int iAccessLevel = 0 ); + //CBotCommand(const char *command, int iAccessLevel = 0) : + // m_iAccessLevel{iAccessLevel}, m_szCommand{command} {}; + + CBotCommand(const char* command, const int iAccessLevel = 0, const char* help = nullptr) : + m_iAccessLevel{iAccessLevel}, m_szCommand{command}, m_szHelp{help} {} // check command name - bool isCommand ( const char *szCommand ); + bool isCommand ( const char *szCommand ) const; // execute command - virtual eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); - - // delete command - virtual void freeMemory (); - - virtual void showStatus () { return; } - virtual void showHelp () { return; } + // we pass byval / copy the argument list so they can be pushed / shifted without + // affecting the original list + virtual eBotCommandResult execute(CClient* pClient, const BotCommandArgs& args); - bool hasAccess ( CClient *pClient ); + bool hasAccess (const CClient *pClient ) const; virtual void printCommand ( edict_t *pPrintTo, int indent = 0); @@ -90,991 +111,38 @@ class CBotCommand virtual bool isContainer () { return false; } - virtual bool canbeUsedDedicated () { return false; } + bool canbeUsedDedicated () const { return (this->m_iAccessLevel & CMD_ACCESS_DEDICATED) != 0; } protected: - void setName ( char *szName ); - void setAccessLevel ( int iAccessLevel ); - void setHelp ( char *pszHelp ); int m_iAccessLevel; - char *m_szCommand; - char *m_szHelp; -}; - -// container of commands -class CBotCommandContainer : public CBotCommand -{ -public: - CBotCommandContainer() {}; - - // call execute command - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); - - void freeMemory (); - - void add ( CBotCommand *newCommand ) { m_theCommands.push_back(newCommand); } - - void printCommand ( edict_t *pPrintTo, int indent = 0); - - bool isContainer () { return true; } - - virtual void printHelp ( edict_t *pPrintTo ); - - virtual bool canbeUsedDedicated () { return true; } -private: - vector m_theCommands; -}; - -///////////////////////////////////////////////// -class CRCBotCommand : public CBotCommandContainer -{ -public: - CRCBotCommand (); -}; - -class CUsersCommand : public CBotCommandContainer -{ -public: - CUsersCommand(); -}; - -class CWaypointCommand : public CBotCommandContainer -{ -public: - CWaypointCommand(); -}; - -class CPathWaypointCommand : public CBotCommandContainer -{ -public: - CPathWaypointCommand(); -}; - -class CConfigCommand : public CBotCommandContainer -{ -public: - CConfigCommand(); -}; - -class CUtilCommand : public CBotCommandContainer -{ -public: - CUtilCommand(); -}; - -/////////////////////// -// command -class CPrintProps : public CBotCommand -{ -public: - CPrintProps() - { - setName("printprops"); - setAccessLevel(CMD_ACCESS_DEBUG); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; -/////////////////////// -// command - -class CFindProp : public CBotCommand -{ -public: - CFindProp() - { - setName("findprop"); - setHelp("Usage: findprop "); - setAccessLevel(CMD_ACCESS_DEBUG); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CFindClass : public CBotCommand -{ -public: - CFindClass() - { - setName("findclass"); - setAccessLevel(CMD_ACCESS_DEBUG); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CFindClassname : public CBotCommand -{ -public: - CFindClassname() - { - setName("findclassname"); - setAccessLevel(CMD_ACCESS_DEBUG); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; -//clear bots schedules -class CBotTaskCommand : public CBotCommand -{ -public: - CBotTaskCommand() - { - setName("givetask"); - setAccessLevel(CMD_ACCESS_DEBUG); - setHelp("gives a bot a task : usage "); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -//clear bots schedules -class CBotFlush : public CBotCommand -{ -public: - CBotFlush() - { - setName("bot_flush"); - setAccessLevel(CMD_ACCESS_DEBUG); - setHelp("flush bot tasks"); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; -//bot goto -class CBotGoto : public CBotCommand -{ -public: - CBotGoto() - { - setName("bot_goto"); - setAccessLevel(CMD_ACCESS_DEBUG); - setHelp("set a debug bot first and then stand near a waypoint to force your bot to go there"); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; -/////////////////////// -// command -class CGetProp : public CBotCommand -{ -public: - CGetProp() - { - setName("getprop"); - setAccessLevel(CMD_ACCESS_DEBUG); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -/////////////////////// -// command -class CSetProp : public CBotCommand -{ -public: - CSetProp() - { - setName("setprop"); - setAccessLevel(CMD_ACCESS_DEBUG); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; -class CGameEventVersion : public CBotCommand -{ -public: - CGameEventVersion() - { - setName("event_version"); - setAccessLevel(CMD_ACCESS_CONFIG); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CMaxBotsCommand : public CBotCommand -{ -public: - CMaxBotsCommand() - { - setName("max_bots"); - setAccessLevel(CMD_ACCESS_CONFIG); - } - - virtual bool canbeUsedDedicated () { return true; } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); + const char *m_szCommand; + const char *m_szHelp; }; -class CMinBotsCommand : public CBotCommand +class CBotCommandInline : public CBotCommand { public: - CMinBotsCommand() - { - setName("min_bots"); - setAccessLevel(CMD_ACCESS_CONFIG); - } - - virtual bool canbeUsedDedicated () { return true; } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - - -/////////////////////// -// waypoint -class CWaypointSetRadiusCommand : public CBotCommand -{ -public: - CWaypointSetRadiusCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CWaypointShowVisCommand : public CBotCommand -{ -public: - CWaypointShowVisCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CWaypointSetAreaCommand : public CBotCommand -{ -public: - CWaypointSetAreaCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CWaypointShiftAreas : public CBotCommand -{ -public: - CWaypointShiftAreas(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CWaypointCopy : public CBotCommand -{ -public: - CWaypointCopy(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CWaypointCut : public CBotCommand -{ -public: - CWaypointCut(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CWaypointPaste : public CBotCommand -{ -public: - CWaypointPaste(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CWaypointMenuCommand : public CBotCommand -{ -public: - CWaypointMenuCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CWaypointCheckCommand : public CBotCommand -{ -public: - CWaypointCheckCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CWaypointAreaSetToNearest : public CBotCommand -{ -public: - CWaypointAreaSetToNearest(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CWaypointAutoFix : public CBotCommand -{ -public: - CWaypointAutoFix(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CWaypointShowCommand : public CBotCommand -{ -public: - CWaypointShowCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CWaypointSetAngleCommand : public CBotCommand -{ -public: - CWaypointSetAngleCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - - -class CWaypointAngleCommand : public CBotCommand -{ -public: - CWaypointAngleCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CWaypointInfoCommand : public CBotCommand -{ -public: - CWaypointInfoCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CWaypointDrawTypeCommand : public CBotCommand -{ -public: - CWaypointDrawTypeCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CWaypointGiveTypeCommand : public CBotCommand -{ -public: - CWaypointGiveTypeCommand() - { - setName("givetype"); - setAccessLevel(CMD_ACCESS_WAYPOINT); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CWaypointOnCommand : public CBotCommand -{ -public: - CWaypointOnCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - - - -class CWaypointOffCommand : public CBotCommand -{ -public: - CWaypointOffCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CWaypointAddCommand : public CBotCommand -{ -public: - CWaypointAddCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CWaypointTeleportCommand : public CBotCommand -{ -public: - CWaypointTeleportCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CWaypointDeleteCommand : public CBotCommand -{ -public: - CWaypointDeleteCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); + CBotCommandInline(const char* cmd, const int iAccessLevel, BotCommandCallback callback, const char* help = nullptr) : CBotCommand(cmd, iAccessLevel, help), m_Callback(std::move( + callback)) {} + + eBotCommandResult execute(CClient* pClient, const BotCommandArgs& args) override; + + BotCommandCallback m_Callback; }; -/////////////// -// control bot -class CControlCommand : public CBotCommand +class CBotSubcommands : public CBotCommand { public: - CControlCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); - - virtual bool canbeUsedDedicated () { return true; } + CBotSubcommands(const char* cmd, const int iAccessLevel, const std::vector& subcommands) : CBotCommand(cmd, iAccessLevel, nullptr), m_theCommands{subcommands} {} + + eBotCommandResult execute(CClient* pClient, const BotCommandArgs& args) override; + + void printCommand(edict_t *pPrintTo, int indent = 0) override; + void printHelp(edict_t *pPrintTo) override; + + bool isContainer() override { return true; } +private: + std::vector m_theCommands; }; -/////////////// -// addbot -class CAddBotCommand : public CBotCommand -{ -public: - CAddBotCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); - - virtual bool canbeUsedDedicated () { return true; } -}; - -/////////////// -// pathwaypoint - -class CPathWaypointDeleteToCommand : public CBotCommand -{ -public: - CPathWaypointDeleteToCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CPathWaypointDeleteFromCommand : public CBotCommand -{ -public: - CPathWaypointDeleteFromCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CPathWaypointOnCommand : public CBotCommand -{ -public: - CPathWaypointOnCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CPathWaypointOffCommand : public CBotCommand -{ -public: - CPathWaypointOffCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CWaypointAutoWaypointCommand : public CBotCommand -{ -public: - CWaypointAutoWaypointCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CPathWaypointAutoOnCommand : public CBotCommand -{ -public: - CPathWaypointAutoOnCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CPathWaypointAutoOffCommand : public CBotCommand -{ -public: - CPathWaypointAutoOffCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CPathWaypointCreateFromToCommand : public CBotCommand -{ -public: - CPathWaypointCreateFromToCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CPathWaypointRemoveFromToCommand : public CBotCommand -{ -public: - CPathWaypointRemoveFromToCommand(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CPathWaypointCreate1Command : public CBotCommand -{ -public: - CPathWaypointCreate1Command(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CPathWaypointCreate2Command : public CBotCommand -{ -public: - CPathWaypointCreate2Command(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CPathWaypointRemove1Command : public CBotCommand -{ -public: - CPathWaypointRemove1Command(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CPathWaypointRemove2Command : public CBotCommand -{ -public: - CPathWaypointRemove2Command(); - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -//////// - -class CWaypointClearCommand : public CBotCommand -{ -public: - CWaypointClearCommand() - { - setName("clear"); - setAccessLevel(CMD_ACCESS_WAYPOINT); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CWaypointSaveCommand : public CBotCommand -{ -public: - CWaypointSaveCommand() - { - setName("save"); - setAccessLevel(CMD_ACCESS_WAYPOINT); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CWaypointLoadCommand : public CBotCommand -{ -public: - CWaypointLoadCommand() - { - setName("load"); - setAccessLevel(CMD_ACCESS_WAYPOINT); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; -///////////////////////////////////////////////////// -class CDebugCommand : public CBotCommandContainer -{ -public: - CDebugCommand(); -}; - -class CDebugProfilingCommand : public CBotCommand -{ -public: - CDebugProfilingCommand () - { - setName("profiling"); - setHelp("usage \"profiling 1 or 0, 1 on, 0 off\" : shows performance profiling"); - setAccessLevel(CMD_ACCESS_DEBUG); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CDebugMemoryCheckCommand : public CBotCommand -{ -public: - CDebugMemoryCheckCommand () - { - setName("memorycheck"); - setHelp("usage \"memorycheck \""); - setAccessLevel(CMD_ACCESS_DEBUG); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -#define MAX_MEM_SEARCH 8192 - -typedef union -{ - struct - { - unsigned searched:1; // already searched - unsigned found:1; // offset found - unsigned unused:6; - }b1; - - byte data; -}u_MEMSEARCH; - -class CDebugMemoryScanCommand : public CBotCommand -{ -public: - CDebugMemoryScanCommand () - { - setName("memoryscan"); - setHelp("usage \"memoryscan [store last = 1]\""); - setAccessLevel(CMD_ACCESS_DEBUG); - memset(stored_offsets,0,sizeof(u_MEMSEARCH)*MAX_MEM_SEARCH); - m_size = 0; - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -private: - - u_MEMSEARCH stored_offsets[MAX_MEM_SEARCH]; - unsigned int m_size; -}; - -class CDebugNavCommand : public CBotCommand -{ -public: - CDebugNavCommand () - { - setName("nav"); - setHelp("usage \"nav 1 or 0, 1 on, 0 off\" : shows navigation output"); - setAccessLevel(CMD_ACCESS_DEBUG); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CDebugTaskCommand : public CBotCommand -{ -public: - CDebugTaskCommand () - { - setName("task"); - setHelp("usage \"task 1 or 0, 1 on, 0 off\" : shows task output"); - setAccessLevel(CMD_ACCESS_DEBUG); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CGodModeUtilCommand : public CBotCommand -{ -public: - CGodModeUtilCommand () - { - setName("god"); - setHelp("usage: toggle for invulnerability!"); - setAccessLevel(CMD_ACCESS_UTIL); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CSetTeleportUtilCommand : public CBotCommand -{ -public: - CSetTeleportUtilCommand () - { - setName("set_teleport"); - setHelp("usage: remembers where you want to teleport"); - setAccessLevel(CMD_ACCESS_UTIL); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CTeleportUtilCommand : public CBotCommand -{ -public: - CTeleportUtilCommand () - { - setName("teleport"); - setHelp("usage: first use set_teleport, then this command to go there"); - setAccessLevel(CMD_ACCESS_UTIL); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CNoTouchCommand : public CBotCommand -{ -public: - CNoTouchCommand () - { - setName("notouch"); - setHelp("don't set off capture points etc"); - setAccessLevel(CMD_ACCESS_UTIL); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - - -class CNoClipCommand : public CBotCommand -{ -public: - CNoClipCommand () - { - setName("noclip"); - setHelp("fly through walls , yeah!"); - setAccessLevel(CMD_ACCESS_UTIL); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CDebugUtilCommand : public CBotCommand -{ -public: - CDebugUtilCommand () - { - setName("util"); - setHelp("usage \"util 1 or 0, 1 on, 0 off\" : shows utility/action output"); - setAccessLevel(CMD_ACCESS_DEBUG); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - - -class CDebugUsercmdCommand : public CBotCommand -{ -public: - CDebugUsercmdCommand () - { - setName("usercmd"); - setHelp("usage \"usercmd 1 or 0, 1 on, 0 off\" : shows last user command output"); - setAccessLevel(CMD_ACCESS_DEBUG); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CDebugEdictsCommand : public CBotCommand -{ -public: - CDebugEdictsCommand () - { - setName("edicts"); - setHelp("usage \"edicts 1 or 0, 1 on, 0 off\" : shows allocated/freed edicts"); - setAccessLevel(CMD_ACCESS_DEBUG); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - - -class CDebugSpeedCommand : public CBotCommand -{ -public: - CDebugSpeedCommand () - { - setName("speed"); - setHelp("usage \"speed 1 or 0, 1 on, 0 off\" : shows speed"); - setAccessLevel(CMD_ACCESS_DEBUG); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CDebugAimCommand : public CBotCommand -{ -public: - CDebugAimCommand () - { - setName("aim"); - setHelp("usage \"aim 1 or 0, 1 on, 0 off\" : displays aiming accuracy info on the hud"); - setAccessLevel(CMD_ACCESS_DEBUG); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CDebugChatCommand : public CBotCommand -{ -public: - CDebugChatCommand () - { - setName("chat"); - setHelp("usage \"chat 1 or 0, 1 on, 0 off\" : displays logs in chat"); - setAccessLevel(CMD_ACCESS_DEBUG); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CDebugHudCommand : public CBotCommand -{ -public: - CDebugHudCommand () - { - setName("hud"); - setHelp("usage \"hud 1 or 0, 1 on, 0 off\" : displays most important info about bot on the hud"); - setAccessLevel(CMD_ACCESS_DEBUG); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CDebugButtonsCommand : public CBotCommand -{ -public: - CDebugButtonsCommand () - { - setName("buttons"); - setHelp("usage \"buttons 1 or 0, 1 on, 0 off\" : shows buttons bitmask"); - setAccessLevel(CMD_ACCESS_DEBUG); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CDebugLookCommand: public CBotCommand -{ -public: - CDebugLookCommand () - { - setName("look"); - setHelp("usage \"look 1 or 0, 1 on, 0 off\" : shows bot look output"); - setAccessLevel(CMD_ACCESS_DEBUG); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - - -class CDebugThinkCommand: public CBotCommand -{ -public: - CDebugThinkCommand () - { - setName("think"); - setHelp("usage \"think 1 or 0, 1 on, 0 off\" : shows bot thinking output"); - setAccessLevel(CMD_ACCESS_DEBUG); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CDebugVisCommand: public CBotCommand -{ -public: - CDebugVisCommand () - { - setName("vis"); - setHelp("usage \"vis 1 or 0, 1 on, 0 off\" : shows bot visibility output"); - setAccessLevel(CMD_ACCESS_DEBUG); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CDebugGameEventCommand : public CBotCommand -{ -public: - CDebugGameEventCommand () - { - setName("gameevent"); - setHelp("usage \"gameevent 1 or 0, 1 on, 0 off\" : shows event output"); - setAccessLevel(CMD_ACCESS_DEBUG); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -class CDebugBotCommand : public CBotCommand -{ -public: - CDebugBotCommand () - { - setName("bot"); - setHelp("usage \"bot , or just bot to switch off : shows bot debug output on listen server"); - setAccessLevel(CMD_ACCESS_DEBUG); - } - - bool canbeUsedDedicated () { return false; } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; -////////////////////////////////// - -class CSearchCommand : public CBotCommand -{ -public: - CSearchCommand () - { - setName("search"); - setAccessLevel(CMD_ACCESS_UTIL); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); -}; - -///////////////////////////////// -class CKickBotCommand : public CBotCommand -{ -public: - CKickBotCommand () - { - setName("kickbot"); - setHelp("usage \"kickbot\" or \"kickbot \" : kicks random bot or bot on team: "); - setAccessLevel(CMD_ACCESS_BOT); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); - - virtual bool canbeUsedDedicated () { return true; } -}; -//////////////////////////////////////// -class CShowUsersCommand : public CBotCommand -{ -public: - CShowUsersCommand () - { - setName("show"); - setAccessLevel(CMD_ACCESS_USERS); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); - - virtual bool canbeUsedDedicated () { return true; } -}; -/////////////////////////////////////// -class CPrintCommands : public CBotCommand -{ -public: - CPrintCommands () - { - setName("printcommands"); - setAccessLevel(0); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); - - virtual bool canbeUsedDedicated () { return true; } -}; - -class CTestCommand : public CBotCommand -{ -public: - CTestCommand () - { - setName("test"); - setAccessLevel(0); - } - - eBotCommandResult execute ( CClient *pClient, const char *pcmd, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5 ); - - virtual bool canbeUsedDedicated () { return false; } -}; #endif diff --git a/utils/RCBot2_meta/bot_config.h b/utils/RCBot2_meta/bot_config.h deleted file mode 100644 index 973c814c4..000000000 --- a/utils/RCBot2_meta/bot_config.h +++ /dev/null @@ -1,14 +0,0 @@ -// EXCLUDED -#ifndef __RCBOT_CONFIG_H__ -#define __RCBOT_CONFIG_H__ - -class CRCBotConfig : public CConfigFile -{ -public: - void loadConfig (); -private: - int m_iMaxBots; - int m_iMinBots; -}; - -#endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_configfile.cpp b/utils/RCBot2_meta/bot_configfile.cpp index 1f522dd07..00ea0a5f5 100644 --- a/utils/RCBot2_meta/bot_configfile.cpp +++ b/utils/RCBot2_meta/bot_configfile.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -29,229 +31,168 @@ * *///=================================================================================// -/// NOT WORKING - -#include -#include - -//#include "cbase.h" -//#include "baseentity.h" -#include "filesystem.h" -#include "interface.h" -#include "engine/iserverplugin.h" -#include "iplayerinfo.h" -#ifdef __linux__ -#include "shake.h" //bir3yk -#endif -#include "IEngineTrace.h" // for traceline functions -#include "tier2/tier2.h" -#include "IEffects.h" -#include "vplane.h" -#include "eiface.h" -#include "igameevents.h" -#include "icvar.h" -//#include "iconvar.h" -#include "convar.h" -#include "Color.h" -#include "ndebugoverlay.h" -#include "server_class.h" -#include "time.h" #include "bot.h" -#include "bot_commands.h" -#include "bot_client.h" #include "bot_globals.h" -#include "bot_accessclient.h" -#include "bot_waypoint_visibility.h" // for initializing table -#include "bot_event.h" -#include "bot_profile.h" -#include "bot_weapons.h" -#include "bot_mods.h" -#include "bot_profiling.h" -#include "vstdlib/random.h" // for random seed - -#include "bot_wpt_dist.h" - #include "bot_configfile.h" -#include "bot_strings.h" -#include "bot_fortress.h" +#include +#include +#include +#include + +#include "rcbot/logging.h" -vector CBotConfigFile::m_Commands; -unsigned int CBotConfigFile::m_iCmd = 0; // current command (time delayed) +std::vector CBotConfigFile::m_Commands; +std::size_t CBotConfigFile::m_iCmd = 0; // current command (time delayed) float CBotConfigFile::m_fNextCommandTime = 0.0f; // bot_util_t CRCBotTF2UtilFile::m_fUtils[UTIL_TYPE_MAX][BOT_UTIL_MAX][9]; -void CBotConfigFile :: load () +void CBotConfigFile::load() { char filename[512]; char line[256]; //int len; - m_Commands.clear(); + m_Commands.clear(); - CBotGlobals::buildFileName(filename,"config",BOT_CONFIG_FOLDER,BOT_CONFIG_EXTENSION); + CBotGlobals::buildFileName(filename, "config", BOT_CONFIG_FOLDER, BOT_CONFIG_EXTENSION); - FILE *fp = CBotGlobals::openFile(filename,"r"); + std::ifstream fp(filename); - if ( !fp ) - { - CBotGlobals::botMessage(NULL,0,"config file not found"); - return; - } + if (!fp) + { + logger->Log(LogLevel::WARN, "Config file not found"); + return; + } - while ( fgets(line,255,fp) != NULL ) - { + while (fp.getline(line, 255)) + { if ( line[0] == '#' ) - continue; + continue; - size_t len = strlen(line); + std::size_t len = std::strlen(line); - if (line[len-1] == '\n') { + if (len && line[len-1] == '\n') { line[--len] = '\0'; - } + } - if (line[len-1] == '\r') { + if (len && line[len-1] == '\r') { line[--len] = '\0'; - } + } - CBotGlobals::botMessage(NULL, 0, line); - m_Commands.push_back(CStrings::getString(line)); - } - - fclose(fp); + if(!len) + continue; + logger->Log(LogLevel::TRACE, "Config entry '%s' read", line); + m_Commands.emplace_back(CStrings::getString(line)); + } } -void CBotConfigFile :: doNextCommand () +void CBotConfigFile::doNextCommand() { - char cmd[64] = {0}; - - if ( (m_fNextCommandTime < engine->Time()) && (m_iCmd < m_Commands.size()) ) - { - snprintf(cmd, sizeof(cmd), "%s\n", m_Commands[m_iCmd]); - engine->ServerCommand(cmd); - - CBotGlobals::botMessage(NULL,0,"Bot Command '%s' executed",m_Commands[m_iCmd]); - m_iCmd ++; - m_fNextCommandTime = engine->Time() + 0.1f; - } + if (m_fNextCommandTime < engine->Time() && + m_iCmd < m_Commands.size()) + { + char cmd[64] = {}; + snprintf(cmd, sizeof(cmd), "%s\n", m_Commands[m_iCmd]); + engine->ServerCommand(cmd); + + logger->Log(LogLevel::TRACE, "Bot Command '%s' executed", m_Commands[m_iCmd]); + m_iCmd++; + m_fNextCommandTime = engine->Time() + 0.1f; + } } -void CBotConfigFile :: executeCommands () +void CBotConfigFile::executeCommands() { - char cmd[64] = {0}; - - while ( (m_iCmd < m_Commands.size()) ) - { - snprintf(cmd, sizeof(cmd), "%s\n", m_Commands[m_iCmd]); - engine->ServerCommand(cmd); + while (m_iCmd < m_Commands.size()) + { + char cmd[64] = {}; + snprintf(cmd, sizeof(cmd), "%s\n", m_Commands[m_iCmd]); // Directly use m_Commands[m_iCmd] as it is a char* + engine->ServerCommand(cmd); - CBotGlobals::botMessage(NULL,0,"Bot Command '%s' executed",m_Commands[m_iCmd]); - m_iCmd ++; - } + logger->Log(LogLevel::TRACE, "Bot Command '%s' executed", m_Commands[m_iCmd]); // Directly use m_Commands[m_iCmd] + m_iCmd++; + } - engine->ServerExecute(); + engine->ServerExecute(); } -void CRCBotTF2UtilFile :: init() +void CRCBotTF2UtilFile::init() { - short unsigned int i,j,k; - - for ( i = 0; i < UTIL_TYPE_MAX; i ++ ) - { - for ( j = 0; j < BOT_UTIL_MAX; j ++ ) - { - for ( k = 0; k < 9; k ++ ) - { - m_fUtils[i][j][k].min = 0; - m_fUtils[i][j][k].max = 0; - } - } - } + for (bot_util_t (&m_fUtil)[112][9] : m_fUtils) + { + for (bot_util_t (&j)[9] : m_fUtil) + { + for (bot_util_t& k : j) + { + k.min = 0; + k.max = 0; + } + } + } } -void CRCBotTF2UtilFile :: addUtilPerturbation (eBotAction iAction, eTF2UtilType iUtil, float fUtility[9][2]) +void CRCBotTF2UtilFile::addUtilPerturbation(const eBotAction iAction, const eTF2UtilType iUtil, float fUtility[9][2]) { - short unsigned int i; - - for ( i = 0; i < 9; i ++ ) - { - m_fUtils[iUtil][iAction][i].min = fUtility[i][0]; - m_fUtils[iUtil][iAction][i].max = fUtility[i][1]; - } + for (short unsigned i = 0; i < 9; i++) + { + m_fUtils[iUtil][iAction][i].min = fUtility[i][0]; + m_fUtils[iUtil][iAction][i].max = fUtility[i][1]; + } } -void CRCBotTF2UtilFile :: loadConfig() +void CRCBotTF2UtilFile::loadConfig() { - eTF2UtilType iFile; - char szFullFilename[512]; - char szFilename[64]; - char line[256]; - FILE *fp; - - init(); - - for ( iFile = BOT_ATT_UTIL; iFile < UTIL_TYPE_MAX; iFile = (eTF2UtilType)((int)iFile+1) ) - { - if ( iFile == BOT_ATT_UTIL ) - { - sprintf(szFilename,"attack_util.csv"); - } - else - { - sprintf(szFilename,"normal_util.csv"); - } - - CBotGlobals::buildFileName(szFullFilename,szFilename,BOT_CONFIG_FOLDER); - fp = CBotGlobals::openFile(szFullFilename,"r"); - - if ( fp ) - { - eBotAction iUtil = (eBotAction)0; - - while ( fgets(line,255,fp) != NULL ) - { - float iClassList[TF_CLASS_MAX][2]; - char utiltype[64]; - - if ( line[0] == 'B' && line[1] == 'O' && - line[2] == 'T' && line[3] == '_') // OK - { - - // Format: U, 1, 2, 3, 4, 5, 6, 7, 8, 9 - // - // s s s d m h p s e - // c n o e e w y p n - // o i l m d g r y g - // - - if ( sscanf(line,"%[^,],%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f\r\n",utiltype, - &(iClassList[0][0]),&(iClassList[0][1]), - &(iClassList[1][0]),&(iClassList[1][1]), - &(iClassList[2][0]),&(iClassList[2][1]), - &(iClassList[3][0]),&(iClassList[3][1]), - &(iClassList[4][0]),&(iClassList[4][1]), - &(iClassList[5][0]),&(iClassList[5][1]), - &(iClassList[6][0]),&(iClassList[6][1]), - &(iClassList[7][0]),&(iClassList[7][1]), - &(iClassList[8][0]),&(iClassList[8][1])) ) - { - - addUtilPerturbation(iUtil,iFile,iClassList); - - iUtil = (eBotAction)((int)iUtil+1); - - if ( iUtil >= BOT_UTIL_MAX ) - break; - - } - - } - } - - fclose(fp); - } - } - -} + init(); + + for (eTF2UtilType iFile = BOT_ATT_UTIL; iFile < UTIL_TYPE_MAX; iFile = static_cast(static_cast(iFile) + 1)) + { + char szFilename[64]; + char szFullFilename[512]; + if ( iFile == BOT_ATT_UTIL ) + { + snprintf(szFilename, sizeof(szFilename), "attack_util.csv"); + } + else + { + snprintf(szFilename, sizeof(szFilename), "normal_util.csv"); + } + + CBotGlobals::buildFileName(szFullFilename, szFilename, BOT_CONFIG_FOLDER); + + if (std::ifstream fp(szFullFilename); fp) + { + std::string line; + eBotAction iUtil = static_cast(0); + + while (std::getline(fp, line)) + { + if (line.substr(0, 4) == "BOT_") // OK + { + std::array iClassList; + std::string utiltype; + + std::istringstream ss(line); + std::getline(ss, utiltype, ','); + + for (float& val : iClassList) + { + std::string temp; + std::getline(ss, temp, ','); + val = std::stof(temp); + } + + //TODO: should be `iAction, iUtil, fUtility`? [APG]RoboCop[CL] + addUtilPerturbation(iUtil, iFile, reinterpret_cast(iClassList.data())); + + iUtil = static_cast(static_cast(iUtil) + 1); + + if (iUtil >= BOT_UTIL_MAX) + break; + } + } + } + } +} \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_configfile.h b/utils/RCBot2_meta/bot_configfile.h index b1e6a4e80..aa3d912de 100644 --- a/utils/RCBot2_meta/bot_configfile.h +++ b/utils/RCBot2_meta/bot_configfile.h @@ -36,9 +36,8 @@ #include "bot_utility.h" #include -using namespace std; -typedef enum +typedef enum : std::uint8_t { BOT_ATT_UTIL = 0, BOT_NORM_UTIL, @@ -54,6 +53,7 @@ typedef struct class CRCBotTF2UtilFile { public: + //TODO: should be `(eBotAction iUtil, eTF2UtilType iFile, float iClassList)? [APG]RoboCop[CL] static void addUtilPerturbation (eBotAction iAction, eTF2UtilType iUtil, float fUtility[9][2]); static void init (); @@ -79,8 +79,8 @@ class CBotConfigFile static void executeCommands (); private: - static vector m_Commands; - static unsigned int m_iCmd; // current command (time delayed) + static std::vector m_Commands; + static std::size_t m_iCmd; // current command (time delayed) static float m_fNextCommandTime; }; diff --git a/utils/RCBot2_meta/bot_const.h b/utils/RCBot2_meta/bot_const.h index 50e1cedc2..d081626aa 100644 --- a/utils/RCBot2_meta/bot_const.h +++ b/utils/RCBot2_meta/bot_const.h @@ -32,47 +32,58 @@ #define __BOT_CONST_H__ #include "shareddefs.h" +#include +#include #ifndef __linux__ -#define BOT_WELCOME_MESSAGE "Welcome to RCBot by Cheeseh" +constexpr char BOT_WELCOME_MESSAGE[] = "Welcome to RCBot by Cheeseh"; #else -#define BOT_WELCOME_MESSAGE "Welcome to RCBot by Cheeseh for Linux" +constexpr char BOT_WELCOME_MESSAGE[] = "Welcome to RCBot by Cheeseh for Linux"; #endif -#define BOT_DEFAULT_FOV 75.0f +constexpr float BOT_DEFAULT_FOV = 80.0f; #define __to_lower(a) (((a)>='A')&&((a)<='Z'))?('a'+((a)-'A')):(a) #define __strlow(str) { char *__strx = str; while ( __strx && *__strx ) { *__strx = __to_lower(*__strx); __strx++; } } //#define strlow(str) { unsigned short int len = strlen(str); unsigned short int i; for ( i = 0; i < len; i ++ ) { str[i] = to_lower(str[i]); } } -#define __round(a) (((a-(int)a) >= 0.5) ? ((int)a+1) : ((int)a)) +#define __round(a) ((((a)-(int)(a)) >= 0.5) ? ((int)(a)+1) : ((int)(a))) //#define RANDOM_INT(min,max) (min + round(((float)rand()/RAND_MAX)*(float)(max-min))) //#define RANDOM_FLOAT(min,max) (min + ((float)rand()/RAND_MAX)*(float)(max-min)) -#define DEFAULT_BOT_NAME "RCBot" +constexpr char DEFAULT_BOT_NAME[] = "RCBot"; -#define BOT_CONVAR_FLAGS_OFFSET 20 +enum : std::uint8_t +{ + BOT_CONVAR_FLAGS_OFFSET = 20 +}; -#define BOT_WPT_TOUCH_DIST 72 // distance for bot to touch waypoint +enum : std::uint8_t +{ + BOT_WPT_TOUCH_DIST = 72 // distance for bot to touch waypoint +}; -#define BOT_DEBUG_GAME_EVENT 0 -#define BOT_DEBUG_NAV 1 -#define BOT_DEBUG_SPEED 2 -#define BOT_DEBUG_VIS 3 -#define BOT_DEBUG_TASK 4 -#define BOT_DEBUG_BUTTONS 5 -#define BOT_DEBUG_USERCMD 6 -#define BOT_DEBUG_UTIL 7 -#define BOT_DEBUG_PROFILE 8 -#define BOT_DEBUG_EDICTS 9 -#define BOT_DEBUG_THINK 10 -#define BOT_DEBUG_LOOK 11 -#define BOT_DEBUG_HUD 12 -#define BOT_DEBUG_AIM 13 -#define BOT_DEBUG_CHAT 14 +enum : std::uint8_t +{ + BOT_DEBUG_GAME_EVENT = 0, + BOT_DEBUG_NAV = 1, + BOT_DEBUG_SPEED = 2, + BOT_DEBUG_VIS = 3, + BOT_DEBUG_TASK = 4, + BOT_DEBUG_BUTTONS = 5, + BOT_DEBUG_USERCMD = 6, + BOT_DEBUG_UTIL = 7, + BOT_DEBUG_PROFILE = 8, + BOT_DEBUG_EDICTS = 9, + BOT_DEBUG_THINK = 10, + BOT_DEBUG_LOOK = 11, + BOT_DEBUG_HUD = 12, + BOT_DEBUG_AIM = 13, + BOT_DEBUG_CHAT = 14 +}; // from sourcemod -enum RoundState +enum RoundState : std::uint8_t { // initialize the game, create teams RoundState_Init, @@ -99,7 +110,7 @@ enum RoundState RoundState_BetweenRounds, }; -typedef enum +typedef enum : std::uint8_t { LOOK_NONE = 0, LOOK_VECTOR, @@ -120,17 +131,21 @@ typedef enum extern const char *g_szLookTaskToString[LOOK_MAX]; -#define BOT_CONFIG_FOLDER "config" -#define BOT_MOD_FILE "bot_mods" -#define BOT_ACCESS_CLIENT_FILE "accessclients" -#define BOT_PROFILE_FOLDER "profiles" -#define BOT_WAYPOINT_FOLDER "waypoints" -#define BOT_CONFIG_EXTENSION "ini" +constexpr char BOT_CONFIG_FOLDER[] = "config"; +constexpr char BOT_MOD_FILE[] = "bot_mods"; +constexpr char BOT_ACCESS_CLIENT_FILE[] = "accessclients"; +constexpr char BOT_PROFILE_FOLDER[] = "profiles"; +constexpr char BOT_WAYPOINT_FOLDER[] = "waypoints"; +constexpr char BOT_AUXILERY_FOLDER[] = "aux_data"; +constexpr char BOT_CONFIG_EXTENSION[] = "ini"; + +constexpr char BOT_WAYPOINT_EXTENSION[] = "rcw"; // extension for waypoint files +constexpr char BOT_WAYPOINT_FILE_TYPE[] = "RCBot2\0"; // for waypoint file header -#define BOT_WAYPOINT_EXTENSION "rcw" // extension for waypoint files -#define BOT_WAYPOINT_FILE_TYPE "RCBot2\0" // for waypoint file header +constexpr char BOT_VISIBILITY_EXTENSION[] = "rcv"; // extension for visibility files + +constexpr char BOT_TAG[] = "[RCBot] "; // for printing messages -#define BOT_TAG "[RCBot] " // for printing messages /* // Engine player info, no game related infos here // If you change this, change the two byteswap defintions: @@ -158,7 +173,7 @@ typedef struct player_info_s unsigned char filesDownloaded; } player_info_t;*/ -typedef enum +typedef enum : std::uint8_t { MOD_UNSUPPORTED = 0, MOD_HLDM2, @@ -178,74 +193,68 @@ typedef enum #define BITS_MOD_ALL ~(1<PEntityOfEntIndex(iEdictNum) #undef ENTINDEX #define ENTINDEX(pEdict) engine->IndexOfEdict(pEdict) -/* -#define BUILDNAME "TF2/HL2DM/DOD:S" -#define BUILDVER "BETA" -#define BUILDNUM "365"*/ -#define BOT_NAME "RCBot" -#ifdef __linux__ -#define BOT_VER "TF2/HL2DM/DOD:S 1.04 META Linux 488-apg (merge) (BUILD " __DATE__ "-" __TIME__ ")" //bir3yk -#else -#define BOT_VER "TF2/HL2DM/DOD:S 1.04 META Win32 488-apg (merge) (BUILD " ## __DATE__ ## "-" ## __TIME__ ## ")" -#endif -#define BOT_NAME_VER "RCbot version" -#define BOT_VER_CVAR "rcbot_ver" -#define BOT_FOLDER "rcbot2" -typedef enum +constexpr char BOT_FOLDER[] = "rcbot2"; + +typedef enum : std::uint8_t { BOT_FUNC_FAIL = 0, - BOT_FUNC_CONTINUE, + BOT_FUNC_CONTINUE, BOT_FUNC_COMPLETE, }eBotFuncState; -////////////////////////////////// -#define CONDITION_ENEMY_OBSCURED 1 // bit 0 - bot lost sight of enemy and can't see clearly -#define CONDITION_NO_WEAPON 2 // bit 1 - bot doesn't have a weapon -#define CONDITION_OUT_OF_AMMO 4 // bit 2 - bot has no ammo -#define CONDITION_SEE_CUR_ENEMY 8 // bit 3 - bot can see current enemy -#define CONDITION_ENEMY_DEAD 16 // bit 4 - bot s enemy is dead -#define CONDITION_SEE_WAYPOINT 32 // bit 5 - bot can see the current waypoint -#define CONDITION_NEED_AMMO 64 // bit 6 - bot needs ammo (low) -#define CONDITION_NEED_HEALTH 128 // bit 7 - bot needs health -#define CONDITION_SEE_LOOK_VECTOR 256 // bit 8 - bot can see his 'look' vector -#define CONDITION_POINT_CAPTURED 512 // bit 9 a point has been captured recently -#define CONDITION_PUSH 1024 // bit 10 - bots are more likely to attack and stop sniping etc -#define CONDITION_LIFT 2048 // bit 11 - bot is on a lift -#define CONDITION_SEE_HEAL 4096 // bit 12 - medic bot (tf2) can see his player he wants to heal -#define CONDITION_SEE_PLAYERTOHELP 4096 // same thing as heal for other mods -#define CONDITION_SEE_LAST_ENEMY_POS 8192 // bit 13 - bots can see the last place they saw an enemy -#define CONDITION_CHANGED 16384 // bit 14 - bots want to change their course of action -#define CONDITION_COVERT 32768 // bit 15 - bots are more sensitive to enemies and more likely to take alternate paths -#define CONDITION_RUN 65536 // bit 16 - bots have to run e.g. there is a grenade nearby -#define CONDITION_GREN 131072 // bit 17 - bots will be more likely to throw a grenade -#define CONDITION_NEED_BOMB 262144 // bit 18 - bot needs a bomb for dod:s bomb maps -#define CONDITION_SEE_ENEMY_HEAD 524288 // bit 19 - bot can aim for a headshot -#define CONDITION_PRONE 1048576 // bit 20 - bot needs to go prone (lie down) -#define CONDITION_PARANOID 2097152 // bit 21 - bot is paranoid of spies or unknown enemy -#define CONDITION_SEE_SQUAD_LEADER 4194304 // bit 22 - bot can see his leader -#define CONDITION_SQUAD_LEADER_DEAD 8388608 // bit 23 - bots leader is dead -#define CONDITION_SQUAD_LEADER_INRANGE 16777216 // bit 24 - bots leader is in range -#define CONDITION_SQUAD_IDLE 33554432 // bit 25 - bots squad isn't doing anything fun -#define CONDITION_DEFENSIVE 67108864 // bit 26 - bot leader told me to defend -#define CONDITION_BUILDING_SAPPED 134217728 // bit 27 - one of engineers buildings sapped -#define CONDITION_SEE_ENEMY_GROUND 268435456 // bit 28 - can see enemy ground so aim for it if i have explosive -#define CONDITION_MAX CONDITION_SEE_ENEMY_GROUND -#define CONDITION_MAX_BITS 28 +// bot condition bits +constexpr int CONDITION_ENEMY_OBSCURED = 1 << 0; // bot lost sight of enemy and can't see clearly +constexpr int CONDITION_NO_WEAPON = 1 << 1; // bot doesn't have a weapon +constexpr int CONDITION_OUT_OF_AMMO = 1 << 2; // bot has no ammo +constexpr int CONDITION_SEE_CUR_ENEMY = 1 << 3; // bot can see current enemy +constexpr int CONDITION_ENEMY_DEAD = 1 << 4; // bot's enemy is dead +constexpr int CONDITION_SEE_WAYPOINT = 1 << 5; // bot can see the current waypoint +constexpr int CONDITION_NEED_AMMO = 1 << 6; // bot needs ammo (low) +constexpr int CONDITION_NEED_HEALTH = 1 << 7; // bot needs health +constexpr int CONDITION_SEE_LOOK_VECTOR = 1 << 8; // bot can see his 'look' vector +constexpr int CONDITION_POINT_CAPTURED = 1 << 9; // a point has been captured recently +constexpr int CONDITION_PUSH = 1 << 10; // bots are more likely to attack and stop sniping etc +constexpr int CONDITION_LIFT = 1 << 11; // bot is on a lift +constexpr int CONDITION_SEE_PLAYERTOHELP = 1 << 12; // heal for non-TF mods +constexpr int CONDITION_SEE_LAST_ENEMY_POS = 1 << 13; // bots can see the last place they saw an enemy +constexpr int CONDITION_CHANGED = 1 << 14; // bots want to change their course of action +constexpr int CONDITION_COVERT = 1 << 15; // bots are more sensitive to enemies and more likely to take alternate paths +constexpr int CONDITION_RUN = 1 << 16; // bots have to run e.g. there is a grenade nearby +constexpr int CONDITION_GREN = 1 << 17; // bots will be more likely to throw a grenade +constexpr int CONDITION_NEED_BOMB = 1 << 18; // bot needs a bomb for dod:s bomb maps +constexpr int CONDITION_SEE_ENEMY_HEAD = 1 << 19; // bot can aim for a headshot +constexpr int CONDITION_PRONE = 1 << 20; // bot needs to go prone (lie down) +constexpr int CONDITION_PARANOID = 1 << 21; // bot is paranoid of spies or unknown enemy +constexpr int CONDITION_SEE_SQUAD_LEADER = 1 << 22; // bot can see his leader +constexpr int CONDITION_SQUAD_LEADER_DEAD = 1 << 23; // bot's leader is dead +constexpr int CONDITION_SQUAD_LEADER_INRANGE = 1 << 24; // bot's leader is in range +constexpr int CONDITION_SQUAD_IDLE = 1 << 25; // bot's squad isn't doing anything fun +constexpr int CONDITION_DEFENSIVE = 1 << 26; // bot leader told me to defend +constexpr int CONDITION_BUILDING_SAPPED = 1 << 27; // one of engineer's buildings sapped +constexpr int CONDITION_SEE_ENEMY_GROUND = 1 << 28; // can see enemy ground so aim for it if i have explosive + +// Number of bits allocated to bot conditions (+1 from last bitshift) +constexpr int NUM_CONDITIONS = 29; + +// Alias for TF: medic bot can see his player he wants to heal +constexpr int CONDITION_SEE_HEAL = CONDITION_SEE_PLAYERTOHELP; //////////////////////// -#define BLAST_RADIUS 200 +constexpr float BLAST_RADIUS = 200.0f; /////////////////////// -typedef enum +typedef enum : std::uint8_t { STATE_IDLE = 0, STATE_RUNNING, diff --git a/utils/RCBot2_meta/bot_convar.cpp b/utils/RCBot2_meta/bot_convar.cpp deleted file mode 100644 index d9e389eec..000000000 --- a/utils/RCBot2_meta/bot_convar.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * This file is part of RCBot. - * - * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. - * - * RCBot is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * RCBot is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with RCBot; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * In addition, as a special exception, the author gives permission to - * link the code of this program with the Half-Life Game Engine ("HL - * Engine") and Modified Game Libraries ("MODs") developed by Valve, - * L.L.C ("Valve"). You must obey the GNU General Public License in all - * respects for all of the code used other than the HL Engine and MODs - * from Valve. If you modify this file, you may extend this exception - * to your version of the file, but you are not obligated to do so. If - * you do not wish to do so, delete this exception statement from your - * version. - * - */ -//===================================================================================// -// -// HPB_bot2_convar.cpp - bot source code file (Copyright 2004, Jeffrey "botman" Broome) -// -//===================================================================================// - -#include "icvar.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -static ICvar *s_pCVar; - -class CPluginConVarAccessor : public IConCommandBaseAccessor -{ -public: - virtual bool RegisterConCommandBase( ConCommandBase *pCommand ) - { - pCommand->AddFlags( FCVAR_PLUGIN ); - - // Unlink from plugin only list - pCommand->SetNext( 0 ); - - // Link to engine's list instead - s_pCVar->RegisterConCommandBase( pCommand ); - return true; - } - -}; - -CPluginConVarAccessor g_ConVarAccessor; - -void InitCVars( CreateInterfaceFn cvarFactory ) -{ - s_pCVar = (ICvar*)cvarFactory( VENGINE_CVAR_INTERFACE_VERSION, NULL ); - if ( s_pCVar ) - { - ConCommandBaseMgr::OneTimeInit( &g_ConVarAccessor ); - } -} - diff --git a/utils/RCBot2_meta/bot_coop.cpp b/utils/RCBot2_meta/bot_coop.cpp index a9f326afc..2aaf2b42f 100644 --- a/utils/RCBot2_meta/bot_coop.cpp +++ b/utils/RCBot2_meta/bot_coop.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com #include "bot.h" #include "bot_coop.h" #include "bot_buttons.h" @@ -6,31 +8,40 @@ #include "vstdlib/random.h" // for random functions +#include +#include +#include -void CBotCoop :: modThink () +void CBotCoop::modThink() { // find enemies and health stations / objectives etc } -bool CBotCoop :: isEnemy ( edict_t *pEdict,bool bCheckWeapons ) +bool CBotCoop::isEnemy(edict_t* pEdict, bool bCheckWeapons) { - const char *classname; - - if ( ENTINDEX(pEdict) == 0 ) + if (pEdict == nullptr || ENTINDEX(pEdict) == 0) return false; // no shooting players - if ( ENTINDEX(pEdict) <= CBotGlobals::maxClients() ) + if (ENTINDEX(pEdict) <= CBotGlobals::maxClients()) { return false; } - classname = pEdict->GetClassName(); + // List of friendly NPCs - if ( strncmp(classname,"npc_",4) == 0 ) + if (const char* classname = pEdict->GetClassName(); std::strncmp(classname, "npc_", 4) == 0) { - if ( !strcmp(classname,"npc_antlionguard") || !strcmp(classname,"npc_citizen") || - !strcmp(classname,"npc_barney") || !strcmp(classname,"npc_kliener") || !strcmp(classname,"npc_alyx") ) + constexpr std::array friendlyNPCs = { + "npc_antlionguard", + "npc_citizen", + "npc_barney", + "npc_kliener", + "npc_alyx" + }; + + if (std::any_of(friendlyNPCs.begin(), friendlyNPCs.end(), + [&](const char* friendly) { return std::strcmp(classname, friendly) == 0; })) { return false; // ally } @@ -41,8 +52,7 @@ bool CBotCoop :: isEnemy ( edict_t *pEdict,bool bCheckWeapons ) return false; } -bool CBotCoop :: startGame () +bool CBotCoop::startGame() { return true; -} - +} \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_coop.h b/utils/RCBot2_meta/bot_coop.h index 631fa150c..aabbf5079 100644 --- a/utils/RCBot2_meta/bot_coop.h +++ b/utils/RCBot2_meta/bot_coop.h @@ -33,14 +33,16 @@ #ifndef __BOT_COOP_H__ #define __BOT_COOP_H__ +#include "bot.h" + class CBotCoop : public CBot { public: - virtual void modThink (); + void modThink () override; - virtual bool isEnemy ( edict_t *pEdict, bool bCheckWeapons = true ); + bool isEnemy ( edict_t *pEdict, bool bCheckWeapons = true ) override; - virtual bool startGame (); + bool startGame () override; }; #endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_css_bot.cpp b/utils/RCBot2_meta/bot_css_bot.cpp index b57cf184d..3f664ccd5 100644 --- a/utils/RCBot2_meta/bot_css_bot.cpp +++ b/utils/RCBot2_meta/bot_css_bot.cpp @@ -1,18 +1,76 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +/* + * This file is part of RCBot. + * + * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. + * + * RCBot is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * RCBot is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RCBot; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + */ +#include "engine_wrappers.h" + #include "bot.h" +#include "bot_cvars.h" +#include "ndebugoverlay.h" +#include "bot_squads.h" #include "bot_css_bot.h" -#include "bot_schedule.h" +#include "bot_css_buying.h" +#include "in_buttons.h" +#include "bot_buttons.h" #include "bot_globals.h" - +#include "bot_profile.h" +#include "bot_getprop.h" #include "bot_mtrand.h" +#include "bot_mods.h" +#include "bot_task.h" +#include "bot_schedule.h" +#include "bot_weapons.h" +#include "bot_waypoint.h" +#include "bot_waypoint_locations.h" +#include "bot_navigator.h" +#include "bot_perceptron.h" +#include "bot_plugin_meta.h" +#include "bot_waypoint_visibility.h" +#include "bot_visibles.h" + +#include "rcbot/logging.h" -void CCSSBot :: init () +#include + +extern IServerGameEnts *servergameents; // for accessing the server game entities + +void CCSSBot::init(const bool bVarInit) { - CBot::init();// require this + CBot::init(bVarInit);// require this // initialize stuff for counter-strike source bot + m_pBuyManager = nullptr; } -void CCSSBot :: setup () +void CCSSBot::setup() { CBot::setup(); // require this @@ -21,60 +79,1047 @@ void CCSSBot :: setup () engine->SetFakeClientConVarValue(m_pEdict,"cl_team","default"); engine->SetFakeClientConVarValue(m_pEdict,"cl_autohelp","0"); + + m_pBuyManager = new CCSSBotBuying(this); } -bool CCSSBot :: isAlive () +void CCSSBot::freeMapMemory() { - if ( !CBot::isAlive() ) + CBot::freeMapMemory(); + + if(m_pBuyManager != nullptr) + { + m_pBuyManager->reset(); + delete m_pBuyManager; + m_pBuyManager = nullptr; + } +} + +void CCSSBot::updateConditions() +{ + CBot::updateConditions(); + + if(m_pEnemy.get() != nullptr) + { + if(m_pVisibles->isVisible(m_pEnemy)) + { + m_fVisibleEnemyTime = engine->Time(); + } + else if(m_fVisibleEnemyTime + 3.0f <= engine->Time()) + { + enemyLost(m_pEnemy); + setLastEnemy(m_pEnemy); + m_pEnemy = nullptr; + } + + if(engine->IndexOfEdict(m_pEnemy.get()) <= gpGlobals->maxClients) + { + // CSS Hack: Dead players are always "Alive" with 1 health. + if(CClassInterface::getPlayerLifeState(m_pEnemy.get()) == LIFE_DEAD || CClassInterface::getPlayerLifeState(m_pEnemy.get()) == LIFE_DYING) + { + updateCondition(CONDITION_ENEMY_DEAD); + m_pEnemy = nullptr; + } + } + } +} + +bool CCSSBot::isAlive() +{ + if (!CBot::isAlive()) return false; - return (getOrigin() != Vector(0,0,0)); + + if(CClassInterface::getPlayerLifeState(getEdict()) == LIFE_DEAD || CClassInterface::getPlayerLifeState(getEdict()) == LIFE_DYING) + return false; + + return getOrigin() != Vector(0,0,0); } -bool CCSSBot :: isEnemy ( edict_t *pEdict,bool bCheckWeapons ) +bool CCSSBot::isEnemy(edict_t *pEdict,bool bCheckWeapons) { - if ( ENTINDEX(pEdict) > CBotGlobals::maxClients() ) + if(rcbot_notarget.GetBool()) + return false; + + if(ENTINDEX(pEdict) > CBotGlobals::maxClients()) + { + if (pEdict->GetUnknown() && pEdict == INDEXENT(m_hNearestBreakable.GetEntryIndex()) && CClassInterface::getPlayerHealth(pEdict) > 0) + { + if (distanceFrom(CBotGlobals::worldCenter(pEdict)) < (rcbot_jump_obst_dist.GetFloat() * 2)) + { + if (BotFunc_BreakableIsEnemy(INDEXENT(m_hNearestBreakable.GetEntryIndex()), pEdict) || + ((CBotGlobals::worldCenter(pEdict) - m_vMoveTo).Length() + 48) < (getOrigin() - m_vMoveTo).Length()) + { + return true; + } + } + } return false; - if ( pEdict->IsFree() ) + } + + if(pEdict->IsFree()) return false; - if ( !CBotGlobals::isNetworkable(pEdict) ) + if(!CBotGlobals::isNetworkable(pEdict)) return false; IPlayerInfo *p = playerinfomanager->GetPlayerInfo(pEdict); - if ( p == NULL ) + if(p == nullptr) return false; - if ( m_pEdict == pEdict ) + + if(m_pEdict == pEdict) + return false; + + if(!CBotGlobals::entityIsAlive(pEdict)) return false; - if ( !CBotGlobals::entityIsAlive ( pEdict ) ) + + if(CClassInterface::getPlayerLifeState(pEdict) == LIFE_DEAD || CClassInterface::getPlayerLifeState(pEdict) == LIFE_DYING) return false; - return (p->GetTeamIndex() != getTeam()); + return p->GetTeamIndex() != getTeam(); } -bool CCSSBot :: startGame () +bool CCSSBot::startGame() { - // do whatever is necessary here to join the game... - IPlayerInfo* pInfo = playerinfomanager->GetPlayerInfo(m_pEdict); + const int team = m_pPlayerInfo->GetTeamIndex(); - if ( pInfo->GetTeamIndex() == 0 ) + if(team <= CS_TEAM_SPECTATOR) { - pInfo->ChangeTeam(randomInt(2,3)); + selectTeam(); + selectModel(); } - return (pInfo->GetTeamIndex() != 0); + return true; } -void CCSSBot :: died () +void CCSSBot::died(edict_t *pKiller, const char *pszWeapon) { spawnInit(); + if(m_pBuyManager) + { + m_pBuyManager->onDeath(); +} } -void CCSSBot :: spawnInit () +void CCSSBot::spawnInit() { CBot::spawnInit(); - if ( m_pSchedules ) - m_pSchedules->add(new CBotSchedule(new CAutoBuy())); - m_fCheckStuckTime = engine->Time() + 6.0; + if(m_pBuyManager) + { + m_pBuyManager->update(); + } + + m_fVisibleEnemyTime = 0.0f; + m_pCurrentWeapon = nullptr; + m_fNextAttackTime = engine->Time(); + m_fCheckStuckTime = engine->Time() + 6.0f; + m_fNextThinkSlow = engine->Time() + 1.0f; + m_hNearestBreakable.Term(); + updateCondition(CONDITION_CHANGED); // Re-execute the utility system +} + +void CCSSBot::listenForPlayers() +{ + edict_t *pListenNearest = nullptr; + float fMaxFactor = 0.0f; + Vector vVelocity; + bool bIsNearestAttacking = false; + + if(m_bListenPositionValid && m_fListenTime > engine->Time()) // already listening to something ? + { + setLookAtTask(LOOK_NOISE); + return; + } + + m_bListenPositionValid = false; + + for(int i = 1; i <= gpGlobals->maxClients; i ++) + { + edict_t* pPlayer = INDEXENT(i); + + if(pPlayer == m_pEdict) + continue; // don't listen to self + + if(pPlayer->IsFree()) + continue; + + const CClient* pClient = CClients::get(pPlayer); + + if(!pClient->isUsed()) + continue; + + IPlayerInfo* p = playerinfomanager->GetPlayerInfo(pPlayer); + + // 05/07/09 fix crash bug + if(!p || !p->IsConnected() || p->IsDead() || p->IsObserver() || !p->IsPlayer()) + continue; + + if(CClassInterface::getPlayerLifeState(pPlayer) == LIFE_DEAD || CClassInterface::getPlayerLifeState(pPlayer) == LIFE_DYING) + continue; + + // Ignore teammates + if(p->GetTeamIndex() == getTeam()) + continue; + + const float fDist = distanceFrom(pPlayer); + + if(fDist > rcbot_listen_dist.GetFloat()) + continue; + + float fFactor = 0.0f; + + const CBotCmd cmd = p->GetLastUserCommand(); + + if(cmd.buttons & IN_ATTACK) + { + if(wantToListenToPlayerAttack(pPlayer)) + fFactor += 1000.0f; + } + + // can't see this player and I'm on my own + if(wantToListenToPlayerFootsteps(pPlayer) && !isVisible(pPlayer) && ( m_bStatsCanUse && m_StatsCanUse.stats.m_iTeamMatesVisible==0)) + { + CClassInterface::getVelocity(pPlayer,&vVelocity); + + const float fVelocity = vVelocity.Length(); + + if(fVelocity > rcbot_footstep_speed.GetFloat()) + fFactor += vVelocity.Length(); + } + + if(fFactor == 0.0f) + continue; + + // add inverted distance to the factor (i.e. closer = better) + fFactor += rcbot_listen_dist.GetFloat() - fDist; + + if(fFactor > fMaxFactor) + { + fMaxFactor = fFactor; + pListenNearest = pPlayer; + bIsNearestAttacking = cmd.buttons & IN_ATTACK; + } + } + + if(pListenNearest != nullptr) + { + listenToPlayer(pListenNearest,false,bIsNearestAttacking); + } +} + +void CCSSBot::selectTeam() const +{ + const char* cmd = "jointeam 0"; + helpers->ClientCommand(m_pEdict,cmd); +} + +void CCSSBot::selectModel() const +{ + const char* cmd = "joinclass 0"; + helpers->ClientCommand(m_pEdict,cmd); +} + +/** + * Executes the 'say' command + * + * @param message The message the bot will say + * @return No return + **/ +void CCSSBot::say(const char *message) +{ + char buffer[256]; + snprintf(buffer, sizeof(buffer), "say \"%s\"", message); + helpers->ClientCommand(m_pEdict,buffer); +} + +/** + * Executes the 'say_team' command + * + * @param message The message the bot will say + * @return No return + **/ +void CCSSBot::sayteam(const char *message) +{ + char buffer[256]; + snprintf(buffer, sizeof(buffer), "say_team \"%s\"", message); + helpers->ClientCommand(m_pEdict,buffer); +} + +/** + * Executes the buy logic + **/ +void CCSSBot::runBuy() +{ + m_pBuyManager->update(); + m_pBuyManager->execute(); +} + +/** + * Update visible entities + **/ +bool CCSSBot::setVisible(edict_t *pEntity, const bool bVisible) +{ + static float fDist; + + const bool bValid = CBot::setVisible(pEntity, bVisible); + + if (CBotGlobals::isBrushEntity(pEntity)) + fDist = distanceFrom(CBotGlobals::worldCenter(pEntity)); + else + fDist = distanceFrom(pEntity); + + // if no draw effect it is invisible + if (bValid && bVisible && !(CClassInterface::getEffects(pEntity) & EF_NODRAW)) + { + const char* szClassname = pEntity->GetClassName(); + + if ((std::strncmp(szClassname, "func_breakable", 14) == 0 || std::strncmp(szClassname, "func_breakable_surf", 19) == 0)) + { + if ((INDEXENT(m_hNearestBreakable.GetEntryIndex()) == nullptr || fDist < distanceFrom(CBotGlobals::worldCenter(INDEXENT(m_hNearestBreakable.GetEntryIndex()))))) + { + m_hNearestBreakable.Init(engine->IndexOfEdict(pEntity), pEntity->m_NetworkSerialNumber); + } + } + } + else + { + if (INDEXENT(m_hNearestBreakable.GetEntryIndex()) == pEntity) + m_hNearestBreakable.Term(); + } + + return bValid; +} + +/** + * Gets the bot primary weapon (will fallback to secondary if the bot doesn't have a primary) + **/ +CBotWeapon *CCSSBot::getPrimaryWeapon() +{ + static CBotWeapon *primary; + static CBotWeapon *secondary; + primary = m_pWeapons->getCurrentWeaponInSlot(CS_WEAPON_SLOT_PRIMARY); + secondary = m_pWeapons->getCurrentWeaponInSlot(CS_WEAPON_SLOT_SECONDARY); + + if(primary) + return primary; + + if(secondary) + return secondary; + + return nullptr; +} + +/** + * Checks if the bot is carrying a sniper weapon + * + * @return TRUE if the bot is carrying a sniper, FALSE otherwise + **/ +bool CCSSBot::IsSniper() +{ + const CBotWeapon *weapon = getPrimaryWeapon(); + + if(!weapon) + return false; + + switch (weapon->getID()) + { + case CS_WEAPON_AWP: + case CS_WEAPON_SCOUT: + case CS_WEAPON_G3SG1: + case CS_WEAPON_SG550: + { + return true; + } + } + + return false; +} + +/** + * Custom primary attack function for Counter-Strike: Source bots + * + * @param hold Hold the attack button? (full-auto) + * @return No return + **/ +void CCSSBot::primaryattackCS(const bool hold) +{ + if(hold) + { + primaryAttack(hold); + } + else + { + if(m_fNextAttackTime <= engine->Time()) + { + tapButton(IN_ATTACK); + //CClients::clientDebugMsg(this, BOT_DEBUG_AIM, "[CSS-ATTACK] Primary Fire!"); + m_fNextAttackTime = engine->Time() + getNextAttackDelay(); // 50 ms delay between shots + } + else + { + //CClients::clientDebugMsg(this, BOT_DEBUG_AIM, "[CSS-ATTACK] Wait!"); + letGoOfButton(IN_ATTACK); + } + } +} + +void CCSSBot::handleWeapons() +{ + // + // Handle attacking at this point + // + if (m_pEnemy && !hasSomeConditions(CONDITION_ENEMY_DEAD) && + hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && wantToShoot() && + isVisible(m_pEnemy) && isEnemy(m_pEnemy)) + { + CBotWeapon* pWeapon = getBestWeapon(m_pEnemy, true, true, rcbot_melee_only.GetBool()); + + if(m_bWantToChangeWeapon && pWeapon != nullptr && pWeapon != getCurrentWeapon() && pWeapon->getWeaponIndex()) + { + selectWeapon(pWeapon->getWeaponIndex()); + } + + setLookAtTask(LOOK_ENEMY); + + if(!handleAttack(pWeapon, m_pEnemy)) + { + m_pEnemy = nullptr; + m_pOldEnemy = nullptr; + wantToShoot(false); + } + } +} + +bool CCSSBot::handleAttack(CBotWeapon *pWeapon, edict_t *pEnemy) +{ + if(pWeapon) + { + clearFailedWeaponSelect(); + + if(pWeapon->isMelee()) + { + if (CBotGlobals::isBrushEntity(pEnemy)) + { + setMoveTo(CBotGlobals::worldCenter(pEnemy)); + } + else + { + setMoveTo(CBotGlobals::entityOrigin(pEnemy)); + } + setMoveSpeed(CClassInterface::getMaxSpeed(m_pEdict)); // in case some task changed the move speed + } + + if(pWeapon->isZoomable() && !CCounterStrikeSourceMod::isScoped(this)) + secondaryAttack(false); + + primaryattackCS(false); + } + else + { + primaryattackCS(false); + } + + return true; +} + +float CCSSBot::getNextAttackDelay() +{ + static constexpr float max = 4096.0f; + static float dist; + static float delay; + delay = 0.050f; // Base delay + + dist = distanceFrom(getEnemy()); + delay = dist/max; + //clamp(delay, 0.050f, 0.300f); + delay = clamp(delay, 0.050f, 0.300f); // Uses the macro from mathlib.h [APG]RoboCop[CL] + + //CClients::clientDebugMsg(this, BOT_DEBUG_AIM, "[CSS-ATTACK] Next Attack Delay: %2.4f", delay); + + return delay; +} + +void CCSSBot::modAim(edict_t *pEntity, Vector &v_origin, Vector *v_desired_offset, Vector &v_size, const float fDist, const float fDist2D) +{ + static bool aimforhead; + static CBotWeapon* pWp; + + CBot::modAim(pEntity, v_origin, v_desired_offset, v_size, fDist, fDist2D); + + aimforhead = true; + pWp = getCurrentWeapon(); + + if (pWp) // Check if pWp is not nullptr - [APG]RoboCop[CL] + { + switch (pWp->getID()) + { + case CS_WEAPON_AWP: + case CS_WEAPON_SUPERSHOTGUN: + case CS_WEAPON_AUTOSHOTGUN: + { + aimforhead = false; + break; + } + } + + if (pWp->isMelee()) + { + aimforhead = false; + } + } + + if(hasSomeConditions(CONDITION_SEE_ENEMY_HEAD) && aimforhead) + { + v_desired_offset->z = v_desired_offset->z + (v_size.z-1); + } + else + { + v_desired_offset->z = v_desired_offset->z + (v_size.z-16); + } + + if (pEntity == INDEXENT(m_hNearestBreakable.GetEntryIndex())) + { + v_desired_offset->x = 0; + v_desired_offset->y = 0; + v_desired_offset->z = 0; + } +} + +void CCSSBot::modThink() +{ + m_pCurrentWeapon = CClassInterface::getCurrentWeapon(m_pEdict); + static int team; + team = getTeam(); + + if(m_pCurrentWeapon) + { + const CBotWeapon *weapon = m_pWeapons->getWeapon(CWeapons::getWeapon(m_pCurrentWeapon->GetClassName())); + if(weapon && weapon->getClip1(this) == 0 && !weapon->isMelee() && weapon->getID() != CS_WEAPON_C4) + { + letGoOfButton(IN_ATTACK); + tapButton(IN_RELOAD); + updateCondition(CONDITION_OUT_OF_AMMO); + } + else + { + removeCondition(CONDITION_OUT_OF_AMMO); + } + } + + if(onLadder()) + { + setMoveLookPriority(MOVELOOK_OVERRIDE); + setLookAtTask(LOOK_WAYPOINT); + m_pButtons->holdButton(IN_FORWARD,0,1,0); + setMoveLookPriority(MOVELOOK_MODTHINK); + } + + // Team Specific thinking + switch (team) + { + case CS_TEAM_COUNTERTERRORIST: + { + if(!CCounterStrikeSourceMod::wasBombFound() && CCounterStrikeSourceMod::canHearPlantedBomb(this)) + { + CCounterStrikeSourceMod::setBombFound(true); + updateCondition(CONDITION_CHANGED); + debugMsg(BOT_DEBUG_THINK, "[CSS-BOT] Found bomb!"); + } + break; + } + } + + if(m_fNextThinkSlow <= engine->Time()) + { + modThinkSlow(); + } + + if(getEnemy() != nullptr && isVisible(getEnemy())) + { + const CBotWeapon *currentweapon = getCurrentWeapon(); + + if(!hasSomeConditions(CONDITION_OUT_OF_AMMO)) + { + if(currentweapon && !currentweapon->isMelee()) + { + stopMoving(); + } + } + } +} + +void CCSSBot::modThinkSlow() +{ + static Vector velocity; + static float fvelocity; + + m_fNextThinkSlow = engine->Time() + 1.0f; + + velocity = Vector(0,0,0); + CClassInterface::getVelocity(getEdict(), &velocity); + fvelocity = velocity.Length(); + + if(fvelocity >= 16.0f && CCounterStrikeSourceMod::isScoped(this)) + { + secondaryAttack(false); + } +} + +void CCSSBot::getTasks(unsigned iIgnore) +{ + static CBotUtilities utils; + static CBotUtility* next; + static bool bCheckCurrent; + static int team; + + if(!hasSomeConditions(CONDITION_CHANGED) && !m_pSchedules->isEmpty()) + return; + + removeCondition(CONDITION_CHANGED); + bCheckCurrent = true; // important for checking current schedule + team = getTeam(); + setMoveSpeed(CClassInterface::getMaxSpeed(m_pEdict)); // Some tasks changes the bot move speed, reset it back. + + // Utilities + + switch (team) + { + case CS_TEAM_COUNTERTERRORIST: // CT specific utilities + { + if(CCounterStrikeSourceMod::isMapType(CS_MAP_BOMBDEFUSAL)) + { + ADD_UTILITY(BOT_UTIL_DEFEND_BOMB, !CCounterStrikeSourceMod::isBombPlanted() && bot_defrate.GetFloat() <= randomFloat(0.0f, 1.0f), 0.80f) + ADD_UTILITY(BOT_UTIL_SEARCH_FOR_BOMB, !CCounterStrikeSourceMod::wasBombFound() && CCounterStrikeSourceMod::isBombPlanted(), 0.81f) + ADD_UTILITY(BOT_UTIL_DEFUSE_BOMB, CCounterStrikeSourceMod::wasBombFound(), 0.85f) + } + else if(CCounterStrikeSourceMod::isMapType(CS_MAP_HOSTAGERESCUE)) + { + ADD_UTILITY(BOT_UTIL_GET_HOSTAGE, CCounterStrikeSourceMod::canRescueHostages(), 0.85f) + ADD_UTILITY(BOT_UTIL_RESCUE, IsLeadingHostage(), 0.84f) + } + break; + } + case CS_TEAM_TERRORIST: // TR specific utilities + { + if(CCounterStrikeSourceMod::isMapType(CS_MAP_BOMBDEFUSAL)) + { + ADD_UTILITY(BOT_UTIL_PLANT_BOMB, CCounterStrikeSourceMod::isBombCarrier(this), 0.80f) + ADD_UTILITY(BOT_UTIL_PICKUP_BOMB, CCounterStrikeSourceMod::isBombDropped(), 0.80f) + ADD_UTILITY(BOT_UTIL_DEFEND_NEAREST_BOMB, CCounterStrikeSourceMod::isBombPlanted(), 0.85f) + } + else if (CCounterStrikeSourceMod::isMapType(CS_MAP_HOSTAGERESCUE)) + { + ADD_UTILITY(BOT_UTIL_GUARD_RESCUE_ZONE, CCounterStrikeSourceMod::canRescueHostages(), 0.70f) + } + break; + } + } + + ADD_UTILITY(BOT_UTIL_SNIPE, IsSniper(), randomFloat(0.7900f, 0.8200f)) + + // Combat Utilities + ADD_UTILITY(BOT_UTIL_ENGAGE_ENEMY, hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && !hasSomeConditions(CONDITION_OUT_OF_AMMO), 1.00f) + ADD_UTILITY(BOT_UTIL_WAIT_LAST_ENEMY, hasSomeConditions(CONDITION_ENEMY_OBSCURED), 0.95f) + ADD_UTILITY(BOT_UTIL_HIDE_FROM_ENEMY, hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && hasSomeConditions(CONDITION_OUT_OF_AMMO), 0.98f) + + // Generic Utilities + ADD_UTILITY(BOT_UTIL_BUY, m_pBuyManager->wantsToBuy(), 1.0f) // Buy weapons + ADD_UTILITY(BOT_UTIL_ROAM, true, 0.001f) // Roam around + + utils.execute(); + + while ((next = utils.nextBest()) != nullptr) + { + if(!m_pSchedules->isEmpty() && bCheckCurrent) + { + if(m_CurrentUtil != next->getId()) + m_pSchedules->freeMemory(); + else + break; + } + + bCheckCurrent = false; + + if(executeAction(next->getId())) + { + m_CurrentUtil = next->getId(); + + if(m_fUtilTimes[next->getId()] < engine->Time()) + m_fUtilTimes[next->getId()] = engine->Time() + randomFloat(0.1f, 2.0f); // saves problems with consistent failing + + if(CClients::clientsDebugging(BOT_DEBUG_UTIL)) + { + int i = 0; + CClients::clientDebugMsg(this,BOT_DEBUG_UTIL,"-------- getTasks(%s) --------",m_szBotName); + + do + { + CClients::clientDebugMsg(this,BOT_DEBUG_UTIL,"%s = %0.3f",g_szUtils[next->getId()],next->getUtility(),this); + }while ((++i<20) && ((next = utils.nextBest()) != nullptr)); + + CClients::clientDebugMsg(this,BOT_DEBUG_UTIL,"----END---- getTasks(%s) ----END----",m_szBotName); + } + break; + } + } + + utils.freeMemory(); +} + +bool CCSSBot::executeAction(const eBotAction iAction) +{ + switch (iAction) + { + case BOT_UTIL_ENGAGE_ENEMY: + { + CBotSchedule* pSched = new CBotSchedule(); + pSched->setID(SCHED_ATTACK); + pSched->addTask(new CCSSEngageEnemyTask(m_pEnemy.get())); + m_pSchedules->add(pSched); + return true; + //break; + } + case BOT_UTIL_WAIT_LAST_ENEMY: + { + CBotSchedule* pSched = new CBotSchedule(); + CBotTask* pTask = new CBotWaitTask(randomFloat(2.0f, 4.0f), m_vLastSeeEnemy); + pTask->setCompleteInterrupt(CONDITION_ENEMY_DEAD); + pTask->setFailInterrupt(CONDITION_SEE_CUR_ENEMY); + pSched->setID(SCHED_WAIT_FOR_ENEMY); + pSched->addTask(pTask); + m_pSchedules->add(pSched); + return true; + //break; + } + case BOT_UTIL_HIDE_FROM_ENEMY: + { + CBotSchedule *pSched = new CBotSchedule(); + pSched->setID(SCHED_RUN_FOR_COVER); + const int cover = CWaypointLocations::GetCoverWaypoint(getOrigin(), CBotGlobals::entityOrigin(m_pEnemy.get()), nullptr, nullptr, 0, 8.0f, 1024.0f); + if(cover != -1) + { + CBotTask *pTask = new CFindPathTask(cover); + pTask->setCompleteInterrupt(CONDITION_ENEMY_DEAD, CONDITION_OUT_OF_AMMO); + pSched->addTask(pTask); + m_pSchedules->add(pSched); + return true; + } + break; + } + case BOT_UTIL_BUY: + { + CBotSchedule* pSched = new CBotSchedule(); + pSched->setID(SCHED_BUY); + pSched->addTask(new CCSSPerformBuyTask()); + m_pSchedules->add(pSched); + return true; + //break; + } + case BOT_UTIL_PLANT_BOMB: + { + if(CWaypoint* pWaypoint = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_GOAL)) + { + CWaypoint * pRoute = nullptr; + if(m_fUseRouteTime <= engine->Time()) + { + pRoute = CWaypoints::randomRouteWaypoint(this, getOrigin(), pWaypoint->getOrigin(), getTeam(), pWaypoint->getArea()); + } + m_pSchedules->add(new CCSSPlantBombSched(pWaypoint, pRoute)); + return true; + } + break; + } + case BOT_UTIL_PICKUP_BOMB: + { + if(edict_t *pBomb = CCounterStrikeSourceMod::getBomb()) + { + m_pSchedules->add(new CBotPickupSched(pBomb)); + return true; + } + break; + } + case BOT_UTIL_DEFEND_NEAREST_BOMB: /** T: Defend planted bomb **/ + { + CBotSchedule* pSched = new CBotSchedule(); + pSched->setID(SCHED_DEFENDPOINT); + edict_t *pBomb = CCounterStrikeSourceMod::getBomb(); + const Vector vBomb = CBotGlobals::entityOrigin(pBomb); + if(pBomb) + { + // Find the nearest bomb waypoint to retreive the area from + if(CWaypoint *pBombWpt = CWaypoints::getWaypoint(CWaypoints::nearestWaypointGoal(CWaypointTypes::W_FL_GOAL, vBomb, 256.0f, 0))) + { + if(CWaypoint *pDefend = CWaypoints::randomWaypointGoalNearestArea(CWaypointTypes::W_FL_DEFEND, getTeam(), pBombWpt->getArea(), true, this, false, &vBomb)) + { + pSched->addTask(new CFindPathTask(CWaypoints::getWaypointIndex(pDefend))); + pSched->addTask(new CCSSGuardTask(getPrimaryWeapon(), pDefend->getOrigin(), pDefend->getAimYaw(), false, 0.0f, pDefend->getFlags())); + m_pSchedules->add(pSched); + CClients::clientDebugMsg(this, BOT_DEBUG_UTIL, "[BOT_UTIL_DEFEND_NEAREST_BOMB] Bomb Waypoint (%i) Defend Waypoint (%i)", + CWaypoints::getWaypointIndex(pBombWpt), CWaypoints::getWaypointIndex(pDefend)); + return true; + } + } + } + break; + } + case BOT_UTIL_DEFEND_BOMB: /** CT: Defend bomb site **/ + { + CBotSchedule* pSched = new CBotSchedule(); + pSched->setID(SCHED_DEFENDPOINT); + if(const CWaypoint *pGoal = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_GOAL, getTeam())) + { + if(CWaypoint *pDefend = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_DEFEND, getTeam(), pGoal->getArea(), true, this)) + { + pSched->addTask(new CFindPathTask(CWaypoints::getWaypointIndex(pDefend))); + pSched->addTask(new CCSSGuardTask(getPrimaryWeapon(), pDefend->getOrigin(), pDefend->getAimYaw(), false, 0.0f, pDefend->getFlags())); + m_pSchedules->add(pSched); + return true; + } + } + break; + } + case BOT_UTIL_DEFUSE_BOMB: + { + if(edict_t *pBomb = CCounterStrikeSourceMod::getBomb()) + { + CBotSchedule *pSched = new CBotSchedule(); + CBotTask *pFindPath = new CFindPathTask(pBomb); + CBotTask *pMoveTask = new CMoveToTask(pBomb); + pFindPath->setFailInterrupt(CONDITION_SEE_CUR_ENEMY); + pMoveTask->setFailInterrupt(CONDITION_SEE_CUR_ENEMY); + pSched->setID(SCHED_BOMB); + pSched->addTask(pFindPath); + pSched->addTask(pMoveTask); + pSched->addTask(new CCSSDefuseTheBombTask(CBotGlobals::entityOrigin(pBomb))); + m_pSchedules->add(pSched); + return true; + } + break; + } + case BOT_UTIL_SEARCH_FOR_BOMB: + { + CBotSchedule* pSched = new CBotSchedule(); + + pSched->setID(SCHED_GOTO_ORIGIN); + + if(CWaypoint* pWaypoint = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_GOAL)) + { + CWaypoint* pRoute = CWaypoints::randomRouteWaypoint(this, getOrigin(), pWaypoint->getOrigin(), getTeam(), + pWaypoint->getArea()); + if(m_fUseRouteTime <= engine->Time()) + { + if(pRoute) + { + const int iRoute = CWaypoints::getWaypointIndex(pRoute); // Route waypoint + pSched->addTask(new CFindPathTask(iRoute, LOOK_WAYPOINT)); + pSched->addTask(new CMoveToTask(pRoute->getOrigin())); + m_pSchedules->add(pSched); + m_fUseRouteTime = engine->Time() + 30.0f; + } + } + + const int iWaypoint = CWaypoints::getWaypointIndex(pWaypoint); + pSched->addTask(new CFindPathTask(iWaypoint, LOOK_WAYPOINT)); + pSched->addTask(new CMoveToTask(pWaypoint->getOrigin())); + m_pSchedules->add(pSched); + + return true; + } + break; + } + case BOT_UTIL_GET_HOSTAGE: + { + // Select a random hostage to rescue + CBotSchedule* pSched = new CBotSchedule(); + edict_t* pHostage = CCounterStrikeSourceMod::getRandomHostage(); + pSched->setID(SCHED_GOTONEST); + + if (pHostage) + { + const Vector vHostage = CBotGlobals::entityOrigin(pHostage); + CWaypoint* pRoute = CWaypoints::randomRouteWaypoint(this, getOrigin(), vHostage, getTeam(), 0); + if((m_fUseRouteTime <= engine->Time())) + { + if(pRoute) + { + const int iRoute = CWaypoints::getWaypointIndex(pRoute); // Route waypoint + pSched->addTask(new CFindPathTask(iRoute, LOOK_WAYPOINT)); + m_fUseRouteTime = engine->Time() + 30.0f; + } + } + + pSched->addTask(new CFindPathTask(pHostage)); + pSched->addTask(new CMoveToTask(pHostage)); + pSched->addTask(new CBotHL2DMUseButton(pHostage)); + pSched->addTask(new CBotWaitTask(1.0f)); + m_pSchedules->add(pSched); + return true; + } + + break; + } + case BOT_UTIL_GUARD_RESCUE_ZONE: + { + edict_t* pRescueZone = CClassInterface::FindEntityByClassnameNearest(getOrigin(), "func_hostage_rescue"); + CBotSchedule* pSched = new CBotSchedule(); + pSched->setID(SCHED_GOTONEST); + m_fUtilTimes[BOT_UTIL_GUARD_RESCUE_ZONE] = engine->Time() + randomFloat(20.0f, 40.0f); + + if (pRescueZone) + { + const Vector vRescue = CBotGlobals::worldCenter(pRescueZone); + pSched->addTask(new CFindPathTask(vRescue)); + pSched->addTask(new CMoveToTask(vRescue)); + pSched->addTask(new CBotWaitTask(0.50f)); + m_pSchedules->add(pSched); + return true; + } + + break; + } + case BOT_UTIL_RESCUE: + { + CBotSchedule* pSched = new CBotSchedule(); + pSched->setID(SCHED_GOTO_ORIGIN); + + CWaypoint* pWaypoint = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_RESCUEZONE, getTeam(), 0, false, this, + false); + + if(pWaypoint) + { + CWaypoint* pRoute = CWaypoints::randomRouteWaypoint(this, getOrigin(), pWaypoint->getOrigin(), getTeam(), + pWaypoint->getArea()); + if((m_fUseRouteTime <= engine->Time())) + { + if(pRoute) + { + const int iRoute = CWaypoints::getWaypointIndex(pRoute); // Route waypoint + pSched->addTask(new CFindPathTask(iRoute, LOOK_WAYPOINT)); + m_fUseRouteTime = engine->Time() + 30.0f; + } + } + + pSched->addTask(new CFindPathTask(CWaypoints::getWaypointIndex(pWaypoint))); + pSched->addTask(new CBotWaitTask(3.0f)); + m_pSchedules->add(pSched); + return true; + } + break; + } + case BOT_UTIL_SNIPE: + { + CBotSchedule* pSched = new CBotSchedule(); + pSched->setID(SCHED_SNIPE); + + if(CWaypoint* pWaypoint = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_SNIPER, getTeam(), 0, false)) + { + CFindPathTask *pFindPath = new CFindPathTask(CWaypoints::getWaypointIndex(pWaypoint)); + //pFindPath->setInterruptFunction(new CBotCSSRoamInterrupt()); + CCSSGuardTask *pGuard = new CCSSGuardTask(getPrimaryWeapon(), pWaypoint->getOrigin(), pWaypoint->getAimYaw(), false, 0.0f, pWaypoint->getFlags()); + pSched->addTask(pFindPath); + pSched->addTask(pGuard); + m_pSchedules->add(pSched); + return true; + } + break; + } + case BOT_UTIL_ROAM: + { + CBotSchedule* pSched = new CBotSchedule(); + + pSched->setID(SCHED_GOTO_ORIGIN); + + if(CWaypoint* pWaypoint = CWaypoints::randomWaypointGoal(-1)) + { + const int iWaypoint = CWaypoints::getWaypointIndex(pWaypoint); + CFindPathTask *pFindPath = new CFindPathTask(iWaypoint); + //pFindPath->setInterruptFunction(new CBotCSSRoamInterrupt()); + pSched->addTask(pFindPath); + m_pSchedules->add(pSched); + + return true; + } + break; + } + } + + return false; +} + +// Called when the round starts +void CCSSBot::onRoundStart() +{ + m_pBuyManager->onRoundStart(); +} + +/** + * Checks if this bot is escorting/leading a hostage to a rescue zone + * + * @return TRUE if this bot is escorting/leading a hostage to a rescue zone + **/ +bool CCSSBot::IsLeadingHostage() +{ + const std::vector hostages = CCounterStrikeSourceMod::getHostageVector(); + //edict_t *pHostage = nullptr; + + if(getTeam() != CS_TEAM_COUNTERTERRORIST) + return false; + + if(hostages.empty()) + return false; + + for(const CBaseHandle& i : hostages) + { + edict_t *pHostage = INDEXENT(i.GetEntryIndex()); + + if(CBotGlobals::entityIsValid(pHostage) && CClassInterface::getCSHostageLeader(pHostage) == m_pEdict) + { + return true; + } + } + + return false; +} + +void CCSSBot::touchedWpt(CWaypoint *pWaypoint, const int iNextWaypoint, const int iPrevWaypoint) +{ + if(iNextWaypoint != -1 && pWaypoint->hasFlag(CWaypointTypes::W_FL_DOOR)) // Use waypoint: Check for door + { + if(CWaypoint *pNext = CWaypoints::getWaypoint(iNextWaypoint)) + { + /** + * Traces a line between the current waypoint and the next waypoint. If a door is blocking the path, try to open it. + **/ + CTraceFilterHitAll filter; + const trace_t *tr = CBotGlobals::getTraceResult(); + CBotGlobals::traceLine(pWaypoint->getOrigin() + Vector(0, 0, CWaypoint::WAYPOINT_HEIGHT / 2), + pNext->getOrigin() + Vector(0, 0, CWaypoint::WAYPOINT_HEIGHT / 2), MASK_PLAYERSOLID, + &filter); + if(tr->fraction < 1.0f) + { + if(tr->m_pEnt) + { + edict_t *pDoor = servergameents->BaseEntityToEdict(tr->m_pEnt); + const char *szclassname = pDoor->GetClassName(); + if(std::strncmp(szclassname, "prop_door_rotating", 18) == 0 || std::strncmp(szclassname, "func_door", 9) == 0 || std::strncmp(szclassname, "func_door_rotating", 18) == 0) + { + m_pSchedules->addFront(new CSynOpenDoorSched(pDoor)); + } + } + } + } + } + + CBot::touchedWpt(pWaypoint, iNextWaypoint, iPrevWaypoint); +} + +bool CCSSBot::canGotoWaypoint(const Vector& vPrevWaypoint, CWaypoint* pWaypoint, CWaypoint* pPrev) +{ + if (pWaypoint->hasFlag(CWaypointTypes::W_FL_NO_HOSTAGES) || pWaypoint->hasFlag(CWaypointTypes::W_FL_LADDER)) + { + return !IsLeadingHostage(); + } + + return CBot::canGotoWaypoint(vPrevWaypoint, pWaypoint, pPrev); } \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_css_bot.h b/utils/RCBot2_meta/bot_css_bot.h index 946ae91fc..4c3a4e9ab 100644 --- a/utils/RCBot2_meta/bot_css_bot.h +++ b/utils/RCBot2_meta/bot_css_bot.h @@ -31,27 +31,69 @@ #ifndef __CSS_RCBOT_H__ #define __CSS_RCBOT_H__ -// bot for CS Source -class CCSSBot : public CBot +enum : std::uint8_t { -public: - - bool isCSS () { return true; } - - void init (); - void setup(); - - bool startGame (); - - void died (); + CS_TEAM_UNASSIGNED = 0, + CS_TEAM_SPECTATOR = 1, + CS_TEAM_TERRORIST = 2, + CS_TEAM_COUNTERTERRORIST = 3 +}; - void spawnInit (); +enum : std::uint8_t +{ + CS_WEAPON_SLOT_PRIMARY = 0, + CS_WEAPON_SLOT_SECONDARY = 1, + CS_WEAPON_SLOT_MELEE = 2, + CS_WEAPON_SLOT_GRENADE = 3, + CS_WEAPON_SLOT_C4 = 4 +}; - bool isAlive (); +class CCSSBotBuying; - bool isEnemy ( edict_t *pEdict,bool bCheckWeapons = true ); +// bot for CS Source +class CCSSBot : public CBot +{ +public: + bool isCSS() override { return true; } + void init(bool bVarInit=false) override; + void spawnInit() override; + void died(edict_t *pKiller, const char *pszWeapon) override; + void setup() override; + void selectTeam() const; + void selectModel() const; + bool startGame() override; + bool isAlive() override; + bool isEnemy(edict_t *pEdict,bool bCheckWeapons = true) override; + void handleWeapons() override; + bool handleAttack(CBotWeapon *pWeapon, edict_t *pEnemy) override; + void modAim(edict_t *pEntity, Vector &v_origin, Vector *v_desired_offset, Vector &v_size, float fDist, float fDist2D) override; + void updateConditions() override; + void modThink() override; + void listenForPlayers() override; + void freeMapMemory() override; + void touchedWpt(CWaypoint *pWaypoint, int iNextWaypoint = -1, int iPrevWaypoint = -1) override; + bool canGotoWaypoint(const Vector& vPrevWaypoint, CWaypoint* pWaypoint, CWaypoint* pPrev = nullptr) override; + bool setVisible(edict_t *pEntity, bool bVisible) override; + virtual void modThinkSlow(); + unsigned maxEntityIndex() override { return gpGlobals->maxEntities; } + void getTasks (unsigned iIgnore=0) override; + virtual bool executeAction(eBotAction iAction); + virtual void runBuy(); + virtual void say(const char *message); + virtual void sayteam(const char *message); + virtual void primaryattackCS(bool hold = false); + virtual float getNextAttackDelay(); + virtual CBotWeapon *getPrimaryWeapon(); + virtual bool IsSniper(); + virtual void onRoundStart(); + virtual bool IsLeadingHostage(); private: - // blah blah + edict_t * m_pCurrentWeapon = nullptr; // The bot current weapon + float m_fNextAttackTime = 0.0f; // Control timer for bot primary attack + float m_fNextThinkSlow = 0.0f; // Control timer for slow think + float m_fVisibleEnemyTime = 0.0f; // The last time my enemy was visible + CBaseHandle m_hNearestBreakable; // Nearest breakable entity + CCSSBotBuying * m_pBuyManager = nullptr; // CSS Bot buy manager }; #endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_css_buying.cpp b/utils/RCBot2_meta/bot_css_buying.cpp new file mode 100644 index 000000000..e0bc38be7 --- /dev/null +++ b/utils/RCBot2_meta/bot_css_buying.cpp @@ -0,0 +1,675 @@ +/* + * This file is part of RCBot. + * + * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. + * + * RCBot is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * RCBot is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RCBot; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + */ + +#include "bot.h" +#include "bot_globals.h" +#include "bot_getprop.h" +#include "bot_css_buying.h" +#include "bot_css_bot.h" +#include "bot_weapons.h" +#include "bot_profile.h" +#include "bot_cvars.h" +#include "logging.h" + +const char *szCSSBuyItem[CS_BUY_MAX+1] = +{ + "primammo", + "secammo", + "vest", + "vesthelm", + "defuser", + "nvgs", // 5 + "usp", + "glock", + "p228", + "fiveseven", + "elite", // 10 + "deagle", + "m3", + "xm1014", + "tmp", + "mac10", // 15 + "mp5navy", + "ump45", + "p90", + "famas", + "galil", // 20 + "ak47", + "m4a1", + "aug", + "sg552", + "scout", // 25 + "awp", + "sg550", + "g3sg1", + "m249", + "hegrenade", // 30 + "smokegrenade", + "flashbang", + "MAX" +}; + +// Array with item prices +const int iCSSItemPrice[CS_BUY_MAX+1] = +{ + 0, // Primary Ammo + 0, // Secondary Ammo + 650, // Vest + 1000, // Vesthelm + 200, // DEFUSER + 1250, // 5 NV Goggles + 500, // USP + 400, // GLOCK + 600, // P228 + 750, // FIVE SEVEN + 800, // 10 Elites + 650, // DEAGLE + 1700, // M3 + 3000, // XM1014 + 1250, // TMP + 1400, // 15 Mac 10 + 1500, // MP5 + 1700, // UMP + 2350, // P90 + 2250, // FAMAS + 2000, // 20 GALIL + 2500, // AK47 + 3100, // M4A1 + 3500, // AUG + 3500, // SG 552 + 2750, // 25 Scout + 4750, // Awp + 4200, // SG 550 + 5000, // G3SG1 + 5750, // M249 + 300, // 30 HE GRENADE + 300, // SMOKE GRENADE + 200, // FLASHBANG GRENADE + 0, // MAX +}; + +CCSSBotBuying::CCSSBotBuying(CBot *pBot) +{ + m_pBot = pBot; + m_deaths = 0; + selectRandomBuyProfile(); +} + +CCSSBotBuying::~CCSSBotBuying() +{ + m_pBot = NULL; + m_money = 0; + m_fLastBuyTime = 0.0f; + m_pPrimaryWeapon = NULL; + m_pSecondaryWeapon = NULL; + m_eProfile = CS_BUY_PROFILE_INVALID; +} + +// Reset +void CCSSBotBuying::reset() +{ + m_money = 0; + m_deaths = 0; + m_fLastBuyTime = 0.0f; + m_pPrimaryWeapon = NULL; + m_pSecondaryWeapon = NULL; + m_eProfile = CS_BUY_PROFILE_INVALID; +} + +// Update +void CCSSBotBuying::update() +{ + m_money = CClassInterface::getCSPlayerMoney(m_pBot->getEdict()); + m_pPrimaryWeapon = m_pBot->getWeapons()->getCurrentWeaponInSlot(CS_WEAPON_SLOT_PRIMARY); + m_pSecondaryWeapon = m_pBot->getWeapons()->getCurrentWeaponInSlot(CS_WEAPON_SLOT_SECONDARY); +} + +// Runs the buying logic +void CCSSBotBuying::execute() +{ + m_fLastBuyTime = engine->Time(); + std::queue buyqueue; + int cost = 0; + + // Eco + if(m_money < rcbot_css_economy_eco_limit.GetInt()) + return; + + buildBuyList(buyqueue, cost); + processBuyList(buyqueue); + update(); +} + +/** + * Buys a single item + * + * @param item The item to buy + **/ +void CCSSBotBuying::buyItem(eCSSBuyItem item) +{ + char buffer[32]; + sprintf(buffer, "buy %s", szCSSBuyItem[item]); + helpers->ClientCommand(m_pBot->getEdict(), buffer); +} + +/** + * Gets how much an item costs to buy + * + * @param item The item to get the price + **/ +int CCSSBotBuying::getPrice(eCSSBuyItem item) +{ + return iCSSItemPrice[item]; +} + +/** + * Checks if the bot can buy this item + * + * @param item The item to check + * @param money Overrides the amount of money the bot has + **/ +bool CCSSBotBuying::canAfford(eCSSBuyItem item, int money) +{ + if(money == -1) + { + return m_money >= iCSSItemPrice[item]; + } + else + { + return money >= iCSSItemPrice[item]; + } +} + + +/** + * Does the bot wants to buy? + * + * @return TRUE if the bot wants to buy, FALSE otherwise + **/ +bool CCSSBotBuying::wantsToBuy() +{ + if(m_fLastBuyTime < 0.0f) + return true; + + return m_fLastBuyTime + 45.0f <= engine->Time() && CClassInterface::isCSPlayerInBuyZone(m_pBot->getEdict()); +} + +/** + * Selects a random buy profile + **/ +void CCSSBotBuying::selectRandomBuyProfile() +{ + m_eProfile = (eCSSBuyProfile)randomInt(CS_BUY_PROFILE_SMG, CS_BUY_PROFILE_MAX-1); +} + +void CCSSBotBuying::setBuyProfile(eCSSBuyProfile profile) +{ + m_eProfile = profile; +} + +eCSSBuyProfile CCSSBotBuying::getBuyProfile() +{ + return m_eProfile; +} + +/** + * Called when a round starts + **/ +void CCSSBotBuying::onRoundStart() +{ + m_fLastBuyTime = -1.0f; +} + +/** + * Called when the bot dies + **/ +void CCSSBotBuying::onDeath() +{ + m_deaths++; + + // Random chance to switch buying profile when killed + if(randomInt(1,50) <= 1 + m_deaths) + { + selectRandomBuyProfile(); + m_deaths = 0; + } +} + +bool CCSSBotBuying::shouldBuyArmor(eCSSBuyType buytype) +{ + int armor = CClassInterface::getCSPlayerArmor(m_pBot->getEdict()); + bool hashelm = CClassInterface::CSPlayerHasHelmet(m_pBot->getEdict()); + + if(buytype == CS_BUY_TYPE_ECO) + return false; + + if(!hashelm) + return true; + + // Low skill bots have a random chance to not buy armor + if(m_pBot->getProfile()->m_fAimSkill <= 0.25f && randomInt(0,1)) + return false; + + return armor < 70; +} + +bool CCSSBotBuying::shouldBuyDefuser(eCSSBuyType buytype) +{ + bool hasdefuser = CClassInterface::CSPlayerHasDefuser(m_pBot->getEdict()); + + if(hasdefuser) + return false; + + if(m_pBot->getTeam() != CS_TEAM_COUNTERTERRORIST) + return false; + + if(buytype == CS_BUY_TYPE_ECO) + return false; + + if(!CCounterStrikeSourceMod::isMapType(CS_MAP_BOMBDEFUSAL)) + return false; + + if(buytype == CS_BUY_TYPE_FORCE && m_pBot->getProfile()->m_fAimSkill >= 0.50f) + return randomInt(0,1) == 1; + + // Bots with higher skill are more likely to buy defuser + return randomFloat(0.0f, 1.0f) <= m_pBot->getProfile()->m_fAimSkill; +} + +eCSSBuyType CCSSBotBuying::determineBuyType() +{ + switch (m_eProfile) + { + case CS_BUY_PROFILE_SMG: + { + if(m_money >= 4000) + { + return CS_BUY_TYPE_FULL; + } + else if(m_money >= 2600) + { + return CS_BUY_TYPE_FORCE; + } + else + { + return CS_BUY_TYPE_ECO; + } + break; + } + case CS_BUY_PROFILE_SHOTGUNNER: + { + if(m_money >= 4500) + { + return CS_BUY_TYPE_FULL; + } + else if(m_money >= 2000) + { + return CS_BUY_TYPE_FORCE; + } + else + { + return CS_BUY_TYPE_ECO; + } + break; + } + case CS_BUY_PROFILE_RIFLE: + { + if(m_money >= 4500) + { + return CS_BUY_TYPE_FULL; + } + else if(m_money >= 3800) + { + return CS_BUY_TYPE_FORCE; + } + else + { + return CS_BUY_TYPE_ECO; + } + break; + } + case CS_BUY_PROFILE_SCOPEDRIFLE: + { + if(m_money >= 5000) + { + return CS_BUY_TYPE_FULL; + } + else if(m_money >= 3800) + { + return CS_BUY_TYPE_FORCE; + } + else + { + return CS_BUY_TYPE_ECO; + } + break; + } + case CS_BUY_PROFILE_SNIPER: + { + if(m_money >= 6000) + { + return CS_BUY_TYPE_FULL; + } + else if(m_money >= 2500) + { + return CS_BUY_TYPE_FORCE; + } + else + { + return CS_BUY_TYPE_ECO; + } + break; + } + case CS_BUY_PROFILE_AUTOSNIPER: + { + if(m_money >= 6500) + { + return CS_BUY_TYPE_FULL; + } + else if(m_money >= 5500) + { + return CS_BUY_TYPE_FORCE; + } + else + { + return CS_BUY_TYPE_ECO; + } + break; + } + case CS_BUY_PROFILE_MACHINEGUNNER: + { + if(m_money >= 7000) + { + return CS_BUY_TYPE_FULL; + } + else if(m_money >= 6500) + { + return CS_BUY_TYPE_FORCE; + } + else + { + return CS_BUY_TYPE_ECO; + } + break; + } + default: + { + if(m_money >= 5000) + { + return CS_BUY_TYPE_FULL; + } + else + { + return CS_BUY_TYPE_ECO; + } + break; + } + } +} + +void CCSSBotBuying::buildBuyList(std::queue &queue, int &cost) +{ + eCSSBuyType buytype = determineBuyType(); + bool buydefuser = shouldBuyDefuser(buytype); + + if(shouldBuyArmor(buytype)) + { + queue.push(CS_BUY_ARMOR_VESTHELM); + cost += getPrice(CS_BUY_ARMOR_VESTHELM); + } + + if(shouldBuyDefuser(buytype)) + { + queue.push(CS_BUY_MISC_DEFUSER); + cost += getPrice(CS_BUY_MISC_DEFUSER); + } + + if(!m_pPrimaryWeapon) + { + switch (m_eProfile) + { + case CS_BUY_PROFILE_SMG: + { + if(buytype == CS_BUY_TYPE_FULL) + { + queue.push(CS_BUY_SMG_P90); + cost += getPrice(CS_BUY_SMG_P90); + } + else if(buytype == CS_BUY_TYPE_FORCE) + { + if(canAfford(CS_BUY_SMG_UMP45, m_money - cost)) + { + queue.push(CS_BUY_SMG_UMP45); + cost += getPrice(CS_BUY_SMG_UMP45); + } + else if(canAfford(CS_BUY_SMG_MP5NAVY, m_money - cost)) + { + queue.push(CS_BUY_SMG_MP5NAVY); + cost += getPrice(CS_BUY_SMG_MP5NAVY); + } + else if(m_pBot->getTeam() == CS_TEAM_TERRORIST && canAfford(CS_BUY_SMG_MAC10, m_money - cost)) + { + queue.push(CS_BUY_SMG_MAC10); + cost += getPrice(CS_BUY_SMG_MAC10); + } + else if(m_pBot->getTeam() == CS_TEAM_COUNTERTERRORIST && canAfford(CS_BUY_SMG_TMP, m_money - cost)) + { + queue.push(CS_BUY_SMG_TMP); + cost += getPrice(CS_BUY_SMG_TMP); + } + } + break; + } + case CS_BUY_PROFILE_SHOTGUNNER: + { + if(buytype == CS_BUY_TYPE_FULL) + { + queue.push(CS_BUY_SHOTGUN_XM1014); + cost += getPrice(CS_BUY_SHOTGUN_XM1014); + } + else if(buytype == CS_BUY_TYPE_FORCE) + { + if(canAfford(CS_BUY_SHOTGUN_M3, m_money - cost)) + { + queue.push(CS_BUY_SHOTGUN_M3); + cost += getPrice(CS_BUY_SHOTGUN_M3); + } + else if(canAfford(CS_BUY_PISTOL_DEAGLE, m_money - cost)) + { + queue.push(CS_BUY_PISTOL_DEAGLE); + cost += getPrice(CS_BUY_PISTOL_DEAGLE); + } + } + break; + } + case CS_BUY_PROFILE_RIFLE: + { + if(buytype == CS_BUY_TYPE_FULL) + { + if(m_pBot->getTeam() == CS_TEAM_TERRORIST) + { + queue.push(CS_BUY_RIFLE_AK47); + cost += getPrice(CS_BUY_RIFLE_AK47); + } + else + { + queue.push(CS_BUY_RIFLE_M4A1); + cost += getPrice(CS_BUY_RIFLE_M4A1); + } + } + else if(buytype == CS_BUY_TYPE_FORCE) + { + if(m_pBot->getTeam() == CS_TEAM_TERRORIST && canAfford(CS_BUY_RIFLE_GALIL, m_money - cost)) + { + queue.push(CS_BUY_RIFLE_GALIL); + cost += getPrice(CS_BUY_RIFLE_GALIL); + } + else if(m_pBot->getTeam() == CS_TEAM_COUNTERTERRORIST && canAfford(CS_BUY_RIFLE_FAMAS, m_money - cost)) + { + queue.push(CS_BUY_RIFLE_FAMAS); + cost += getPrice(CS_BUY_RIFLE_FAMAS); + } + else if(canAfford(CS_BUY_SMG_MP5NAVY, m_money - cost)) + { + queue.push(CS_BUY_SMG_MP5NAVY); + cost += getPrice(CS_BUY_SMG_MP5NAVY); + } + } + break; + } + case CS_BUY_PROFILE_SCOPEDRIFLE: + { + if(buytype == CS_BUY_TYPE_FULL) + { + if(m_pBot->getTeam() == CS_TEAM_TERRORIST) + { + queue.push(CS_BUY_RIFLE_SG552); + cost += getPrice(CS_BUY_RIFLE_SG552); + } + else + { + queue.push(CS_BUY_RIFLE_AUG); + cost += getPrice(CS_BUY_RIFLE_AUG); + } + } + else if(buytype == CS_BUY_TYPE_FORCE) + { + if(m_pBot->getTeam() == CS_TEAM_TERRORIST && canAfford(CS_BUY_RIFLE_GALIL, m_money - cost)) + { + queue.push(CS_BUY_RIFLE_GALIL); + cost += getPrice(CS_BUY_RIFLE_GALIL); + } + else if(m_pBot->getTeam() == CS_TEAM_COUNTERTERRORIST && canAfford(CS_BUY_RIFLE_FAMAS, m_money - cost)) + { + queue.push(CS_BUY_RIFLE_FAMAS); + cost += getPrice(CS_BUY_RIFLE_FAMAS); + } + else if(canAfford(CS_BUY_SMG_MP5NAVY, m_money - cost)) + { + queue.push(CS_BUY_SMG_MP5NAVY); + cost += getPrice(CS_BUY_SMG_MP5NAVY); + } + } + break; + } + case CS_BUY_PROFILE_SNIPER: + { + if(buytype == CS_BUY_TYPE_FULL) + { + if(buytype == CS_BUY_TYPE_FULL) + { + queue.push(CS_BUY_SNIPER_AWP); + cost += getPrice(CS_BUY_SNIPER_AWP); + } + } + else if(buytype == CS_BUY_TYPE_FORCE) + { + if(canAfford(CS_BUY_SNIPER_SCOUT, m_money - cost)) + { + queue.push(CS_BUY_SNIPER_SCOUT); + cost += getPrice(CS_BUY_SNIPER_SCOUT); + } + else if(canAfford(CS_BUY_SMG_UMP45, m_money - cost)) + { + queue.push(CS_BUY_SMG_UMP45); + cost += getPrice(CS_BUY_SMG_UMP45); + } + } + break; + } + case CS_BUY_PROFILE_AUTOSNIPER: + { + if(buytype == CS_BUY_TYPE_FULL) + { + if(m_pBot->getTeam() == CS_TEAM_TERRORIST) + { + queue.push(CS_BUY_SNIPER_G3SG1); + cost += getPrice(CS_BUY_SNIPER_G3SG1); + } + else + { + queue.push(CS_BUY_SNIPER_SG550); + cost += getPrice(CS_BUY_SNIPER_SG550); + } + } + else if(buytype == CS_BUY_TYPE_FORCE) + { + if(m_pBot->getTeam() == CS_TEAM_TERRORIST && canAfford(CS_BUY_SMG_MAC10, m_money - cost)) + { + queue.push(CS_BUY_SMG_MAC10); + cost += getPrice(CS_BUY_SMG_MAC10); + } + else if(m_pBot->getTeam() == CS_TEAM_COUNTERTERRORIST && canAfford(CS_BUY_SMG_TMP, m_money - cost)) + { + queue.push(CS_BUY_SMG_TMP); + cost += getPrice(CS_BUY_SMG_TMP); + } + } + break; + } + case CS_BUY_PROFILE_MACHINEGUNNER: + { + if(buytype == CS_BUY_TYPE_FULL) + { + queue.push(CS_BUY_MG_M249); + cost += getPrice(CS_BUY_MG_M249); + } + else if(buytype == CS_BUY_TYPE_FORCE) + { + if(m_pBot->getTeam() == CS_TEAM_TERRORIST && canAfford(CS_BUY_PISTOL_ELITES, m_money - cost)) + { + queue.push(CS_BUY_PISTOL_ELITES); + cost += getPrice(CS_BUY_PISTOL_ELITES); + } + else if(m_pBot->getTeam() == CS_TEAM_COUNTERTERRORIST && canAfford(CS_BUY_PISTOL_FIVESEVEN, m_money - cost)) + { + queue.push(CS_BUY_PISTOL_FIVESEVEN); + cost += getPrice(CS_BUY_PISTOL_FIVESEVEN); + } + } + break; + } + } + } +} + +void CCSSBotBuying::processBuyList(std::queue &queue) +{ + eCSSBuyItem item = CS_BUY_MAX; + + while(!queue.empty()) + { + item = queue.front(); + buyItem(item); + queue.pop(); + logger->Log(LogLevel::DEBUG, "[CSS-BUY] Buying item \"%s\"", szCSSBuyItem[item]); + } +} \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_css_buying.h b/utils/RCBot2_meta/bot_css_buying.h new file mode 100644 index 000000000..28787b548 --- /dev/null +++ b/utils/RCBot2_meta/bot_css_buying.h @@ -0,0 +1,152 @@ +/* + * This file is part of RCBot. + * + * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. + * + * RCBot is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * RCBot is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RCBot; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + */ +#ifndef __BOT_CSS_BUYING_H__ +#define __BOT_CSS_BUYING_H__ + +/** + * Ammo: primammo, secammo + * Armor: vest, vesthelm + * Misc: defuser, nvgs + * Pistols: usp, glock, p228, fiveseven, elite, deagle + * Shotguns: m3, xm1014 + * SMGs: tmp, mac10, mp5navy, ump45, p90 + * Rifles: famas, galil, ak47, m4a1, aug, sg552 + * Snipers: scout, awp, sg550, g3sg1 + * Machine Guns: m249 + **/ + +typedef enum : std::uint8_t +{ + CS_BUY_AMMO_PRIMARY = 0, + CS_BUY_AMMO_SECONDARY, + CS_BUY_ARMOR_VEST, + CS_BUY_ARMOR_VESTHELM, + CS_BUY_MISC_DEFUSER, + CS_BUY_MISC_NVGOGGLES, + CS_BUY_PISTOL_USP, + CS_BUY_PISTOL_GLOCK, + CS_BUY_PISTOL_P228, + CS_BUY_PISTOL_FIVESEVEN, + CS_BUY_PISTOL_ELITES, + CS_BUY_PISTOL_DEAGLE, + CS_BUY_SHOTGUN_M3, + CS_BUY_SHOTGUN_XM1014, + CS_BUY_SMG_TMP, + CS_BUY_SMG_MAC10, + CS_BUY_SMG_MP5NAVY, + CS_BUY_SMG_UMP45, + CS_BUY_SMG_P90, + CS_BUY_RIFLE_FAMAS, + CS_BUY_RIFLE_GALIL, + CS_BUY_RIFLE_AK47, + CS_BUY_RIFLE_M4A1, + CS_BUY_RIFLE_AUG, + CS_BUY_RIFLE_SG552, + CS_BUY_SNIPER_SCOUT, + CS_BUY_SNIPER_AWP, + CS_BUY_SNIPER_SG550, + CS_BUY_SNIPER_G3SG1, + CS_BUY_MG_M249, + CS_BUY_GRENADE_EXPLOSIVE, + CS_BUY_GRENADE_SMOKE, + CS_BUY_GRENADE_FLASHBANG, + CS_BUY_MAX, +}eCSSBuyItem; + +/** + * CS Buy Profile + * Determines what kind of weapons the bot likes + * Currently it's selected randomly + **/ +typedef enum : std::int8_t +{ + CS_BUY_PROFILE_INVALID = -1, + CS_BUY_PROFILE_SMG = 0, + CS_BUY_PROFILE_SHOTGUNNER = 1, + CS_BUY_PROFILE_RIFLE = 2, + CS_BUY_PROFILE_SCOPEDRIFLE = 3, + CS_BUY_PROFILE_SNIPER = 4, + CS_BUY_PROFILE_AUTOSNIPER = 5, + CS_BUY_PROFILE_MACHINEGUNNER = 6, + CS_BUY_PROFILE_MAX = 7 +} eCSSBuyProfile; + +/** + * List of buy "types" for the bot + **/ +typedef enum : std::int8_t +{ + CS_BUY_TYPE_INVALID = -1, + CS_BUY_TYPE_ECO = 0, // Save money + CS_BUY_TYPE_FORCE = 1, // Save some money + CS_BUY_TYPE_FULL = 2, // Buy everything + CS_BUY_TYPE_UPGRADE = 3, // Upgrade current weapon + CS_BUY_TYPE_MAX = 4 +} eCSSBuyType; + +/** + * This class manages the Counter-Strike: Source bot buying logic + **/ +class CCSSBotBuying +{ +public: + CCSSBotBuying(CBot *pBot); + ~CCSSBotBuying(); + void reset(); + void update(); + void execute(); + void buyItem(eCSSBuyItem item); + int getPrice(eCSSBuyItem item); + bool canAfford(eCSSBuyItem item, int money = -1); + bool wantsToBuy(); + void selectRandomBuyProfile(); + void setBuyProfile(eCSSBuyProfile profile); + eCSSBuyProfile getBuyProfile(); + void onRoundStart(); + void onDeath(); + +private: + bool shouldBuyArmor(eCSSBuyType buytype); + bool shouldBuyDefuser(eCSSBuyType buytype); + void buildBuyList(std::queue &queue, int &cost); + eCSSBuyType determineBuyType(); + void processBuyList(std::queue &queue); + + CBot* m_pBot; // Bot pointer + CBotWeapon* m_pPrimaryWeapon; // Primary weapon + CBotWeapon* m_pSecondaryWeapon; // Secondary weapon + int m_money; // Amount of money the bot has + int m_deaths; // How many times the bot died + float m_fLastBuyTime; // The last time the bot bought something + eCSSBuyProfile m_eProfile; // Bot weapon preference profile +}; + +#endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_css_mod.cpp b/utils/RCBot2_meta/bot_css_mod.cpp new file mode 100644 index 000000000..d3c8960cf --- /dev/null +++ b/utils/RCBot2_meta/bot_css_mod.cpp @@ -0,0 +1,325 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +/* + * This file is part of RCBot. + * + * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. + * + * RCBot is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * RCBot is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RCBot; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + */ +#include "server_class.h" + +#include "bot.h" + +#include "in_buttons.h" + +#include "bot_mods.h" +#include "bot_globals.h" +#include "bot_weapons.h" +#include "bot_configfile.h" +#include "bot_getprop.h" +#include "bot_css_bot.h" +#include "bot_navigator.h" +#include "bot_waypoint.h" +#include "bot_waypoint_locations.h" +#include "bot_perceptron.h" + +#include "rcbot/logging.h" + +#include + +// For debug messages +const char *szMapTypes[CS_MAP_MAX+1] = +{ + "DEATHMATCH", + "BOMB DEFUSAL", + "HOSTAGE RESCUE", + "MAP TYPE MAX" +}; + +eCSSMapType CCounterStrikeSourceMod::m_MapType = CS_MAP_DEATHMATCH; +float CCounterStrikeSourceMod::m_fRoundStartTime = 0.0f; +float CCounterStrikeSourceMod::m_fBombPlantedTime = 0.0f; +bool CCounterStrikeSourceMod::m_bIsBombPlanted = false; +bool CCounterStrikeSourceMod::m_bBombWasFound = false; +CBaseHandle CCounterStrikeSourceMod::m_hBomb = NULL; +std::vector CCounterStrikeSourceMod::m_hHostages; + +void CCounterStrikeSourceMod::initMod() +{ + CWeapons::loadWeapons(m_szWeaponListName == nullptr ? "CSS" : m_szWeaponListName, CSSWeaps.data()); // Load weapon list + logger->Log(LogLevel::TRACE, "CCounterStrikeSourceMod::initMod()"); +} + +void CCounterStrikeSourceMod::mapInit() +{ + const string_t mapname = gpGlobals->mapname; + const char *szmapname = mapname.ToCStr(); + + if(std::strncmp(szmapname, "de_", 3) == 0) + m_MapType = CS_MAP_BOMBDEFUSAL; + else if(std::strncmp(szmapname, "cs_", 3) == 0) + m_MapType = CS_MAP_HOSTAGERESCUE; + else + m_MapType = CS_MAP_DEATHMATCH; + + logger->Log(LogLevel::TRACE, "CCounterStrikeSourceMod::mapInit()\nMap Type: %s", szMapTypes[m_MapType]); +} + +bool CCounterStrikeSourceMod::checkWaypointForTeam(CWaypoint *pWpt, const int iTeam) +{ + return (!pWpt->hasFlag(CWaypointTypes::W_FL_NOCOUNTERTR)||iTeam!=CS_TEAM_COUNTERTERRORIST)&&(!pWpt->hasFlag(CWaypointTypes::W_FL_NOTERRORIST)||iTeam!=CS_TEAM_TERRORIST); +} + +/** + * Checks if the given bot is a bomb carrier (has C4) + * + * @param pBot The bot to check + * @return TRUE if the bot is a bomb carrier + **/ +bool CCounterStrikeSourceMod::isBombCarrier(const CBot *pBot) +{ + return pBot->getWeapons()->hasWeapon(CS_WEAPON_C4); +} + +/** + * Checks if the C4 is dropped on the ground + * + * @return TRUE if dropped + **/ +bool CCounterStrikeSourceMod::isBombDropped() +{ + edict_t *pBomb = getBomb(); + + if(m_bIsBombPlanted) + return false; + + if(pBomb) + { + return CClassInterface::getWeaponState(pBomb) == WEAPON_NOT_CARRIED; + } + + return false; +} + +/** + * Checks if the C4 was defused + * + * @return TRUE if defused + **/ +bool CCounterStrikeSourceMod::isBombDefused() +{ + return !CClassInterface::isCSBombTicking(INDEXENT(m_hBomb.GetEntryIndex())); +} + +/** + * Checks if the given bot can hear the planted c4 ticking + * + * @param pBot The bot to check + * @return TRUE if the bot can hear + **/ +bool CCounterStrikeSourceMod::canHearPlantedBomb(const CBot *pBot) +{ + if(!isBombPlanted()) + return false; + + if(edict_t *pBomb = getBomb()) + { + return pBot->distanceFrom(pBomb) <= 2048.0f; + } + + return false; +} + +/** + * Checks if the given bot is scoped + * + * @param pBot The bot to check + * @return TRUE if the bot is scoped + **/ +bool CCounterStrikeSourceMod::isScoped(const CBot *pBot) +{ + const int fov = CClassInterface::getPlayerFOV(pBot->getEdict()); + return fov != 0 && fov != 90; // For bots, FOVs are 0 or 90 when not scoped. +} + +/** + * Called when a new round starts + **/ +void CCounterStrikeSourceMod::onRoundStart() +{ + // Empty for now, reset round based logic + logger->Log(LogLevel::TRACE, "CCounterStrikeSourceMod::OnRoundStart()"); + m_bIsBombPlanted = false; + setBombFound(false); + m_hBomb.Term(); + for(short int i = 0; i < RCBOT_MAXPLAYERS; i++) + { + CBot *pBot = CBots::get(i); + CCSSBot *pCSBot = static_cast(pBot); + + if(pCSBot && pCSBot->inUse()) + { + pCSBot->onRoundStart(); + } + } + + if(isMapType(CS_MAP_HOSTAGERESCUE)) + { + updateHostages(); + } +} + +/** + * Called when the freeze time ends. Note: This is always called even if freeze time is disabled. + **/ +void CCounterStrikeSourceMod::onFreezeTimeEnd() +{ + logger->Log(LogLevel::TRACE, "CCounterStrikeSourceMod::OnFreezeTimeEnd()"); + + if(const edict_t *pC4 = CClassInterface::FindEntityByClassnameNearest(Vector(0.0f, 0.0f, 0.0f), "weapon_c4", 32000.0f)) + { + m_hBomb.Init(engine->IndexOfEdict(pC4), pC4->m_NetworkSerialNumber); + } + + for(short int i = 0; i < RCBOT_MAXPLAYERS; i++) + { + CBot *pBot = CBots::get(i); + + if(pBot && pBot->inUse()) + { + pBot->select_CWeapon(CWeapons::getWeapon(CS_WEAPON_KNIFE)); + } + } +} + +/** + * Called when the bomb is planted + **/ +void CCounterStrikeSourceMod::onBombPlanted() +{ + logger->Log(LogLevel::TRACE, "CCounterStrikeSourceMod::OnBombPlanted()"); + m_bIsBombPlanted = true; + m_fBombPlantedTime = engine->Time(); + m_hBomb.Term(); + + if(const edict_t *pPlantedC4 = CClassInterface::FindEntityByNetClass(gpGlobals->maxClients+1, "CPlantedC4")) + { + m_hBomb.Init(engine->IndexOfEdict(pPlantedC4), pPlantedC4->m_NetworkSerialNumber); + } + + for(short i = 0; i < RCBOT_MAXPLAYERS; i++) + { + CBot *pBot = CBots::get(i); + + if(pBot && pBot->inUse()) + { + if(pBot->distanceFrom(getBomb()) >= 512.0f) + { + pBot->updateCondition(CONDITION_CHANGED); + } + } + } +} + +/** + * Hostage entities needs to be updated on round start since killed hostages gets their entity deleted. + **/ +void CCounterStrikeSourceMod::updateHostages() +{ + CBaseHandle bh; + m_hHostages.clear(); + + for(int i = gpGlobals->maxClients + 1; i < gpGlobals->maxEntities; i++) + { + bh.Term(); + edict_t* current = engine->PEntityOfEntIndex(i); + if (current == nullptr) + { + continue; + } + + IServerNetworkable *network = current->GetNetworkable(); + if (network == nullptr) + { + continue; + } + + //const char *classname = current->GetClassName(); + ServerClass *sClass = network->GetServerClass(); + const char *sname = sClass->GetName(); + + if(std::strcmp(sname, "CHostage") == 0) + { + bh.Init(i, current->m_NetworkSerialNumber); + m_hHostages.emplace_back(bh); + } + } +} + +/** + * Checks if there are hostages that can be rescued + **/ +bool CCounterStrikeSourceMod::canRescueHostages() +{ + if(m_hHostages.empty()) + return false; + + for(const CBaseHandle& i : m_hHostages) + { + edict_t* pHostage = INDEXENT(i.GetEntryIndex()); + + if (CBotGlobals::entityIsValid(pHostage) && !CClassInterface::isCSHostageRescued(pHostage) && CClassInterface::getCSHostageLeader(pHostage)) + { + return true; + } + } + + return false; +} + +edict_t *CCounterStrikeSourceMod::getRandomHostage() +{ + std::vector temp; + + // Build a new vector with hostages that are valid to be rescued + for(const CBaseHandle& i : m_hHostages) + { + edict_t* pEdict = INDEXENT(i.GetEntryIndex()); + + if (CBotGlobals::entityIsValid(pEdict) && !CClassInterface::isCSHostageRescued(pEdict) && CClassInterface::getCSHostageLeader(pEdict) && CClassInterface::getCSHostageHealth(pEdict) > 0) + { + temp.emplace_back(i); + } + } + + if (!temp.empty()) + { + return INDEXENT(temp.at(static_cast(randomInt(0, static_cast(temp.size() - 1)))).GetEntryIndex()); + } + + return nullptr; +} diff --git a/utils/RCBot2_meta/bot_cvars.cpp b/utils/RCBot2_meta/bot_cvars.cpp index 376076975..e1936ad36 100644 --- a/utils/RCBot2_meta/bot_cvars.cpp +++ b/utils/RCBot2_meta/bot_cvars.cpp @@ -1,161 +1,153 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +#include #include "icvar.h" //#include "iconvar.h" #include "convar.h" #include "bot_cvars.h" +#include "bot_const.h" -static ICvar *s_pCVar; - -ConVar rcbot_tf2_debug_spies_cloakdisguise("rcbot_tf2_debug_spies_cloakdisguise","1",0,"Debug command : allow spy bots to cloak and disguise"); -ConVar rcbot_tf2_medic_letgotime("rcbot_tf2_medic_letgotime","0.4",0,"Time for medic to let go of medigun to switch players"); -//ConVar rcbot_const_round_offset("rcbot_const_round_offset","844",0,"TF2 OFFSET for Round Class"); -ConVar rcbot_const_point_master_offset("rcbot_const_mstr_offset","844",0,"TF2 OFFSET for Point Master Class"); -//ConVar rcbot_const_point_offset("rcbot_const_pnt_offset","1140",0,"TF2 OFFSET for Point Class"); -//ConVar rcbot_const_point_data_offset("rcbot_const_pnt_data_offset","1642",0,"TF2 OFFSET for Point Class data"); -ConVar rcbot_tf2_pyro_airblast("rcbot_tf2_pyro_airblast_ammo","50",0,"Ammo must be above this to airblast -- if 200 airblast will be disabled"); -ConVar rcbot_projectile_tweak("rcbot_projtweak","0.05",0,"Tweaks the bots knowledge of projectiles and gravity"); -//ConVar bot_sv_cheat_warning("rcbot_sv_cheats_warning","0",0,"If disabled, bots will try to spawn even if sv_cheats is 0 - use only with admin cvar plugin"); -ConVar bot_cmd_enable_wpt_sounds("rcbot_enable_wpt_sounds","1",0,"Enable/disable sound effects when editing waypoints"); -//ConVar bot_cmd_nocheats("rcbot_botcmd_nocheats","1",0,"If 1 bots don't need cheats to play"); -ConVar bot_general_difficulty("rcbot_skill","0.6",0,"General difficulty of the bots. 0.5 = stock, < 0.5 easier, > 0.5 = harder"); -//ConVar bot_sv_cheats_auto("rcbot_sv_cheats_auto","0",0,"automatically put sv_cheats on and off for when adding bots only"); -ConVar bot_visrevs_clients("rcbot_visrevs_clients","4",0,"how many revs the bot searches for visible players and enemies, lower to reduce cpu usage"); -ConVar bot_spyknifefov("rcbot_spyknifefov","80",0,"the FOV from the enemy that spies must backstab from"); -ConVar bot_visrevs("rcbot_visrevs","9",0,"how many revs the bot searches for visible monsters, lower to reduce cpu usage min:5"); -ConVar bot_pathrevs("rcbot_pathrevs","40",0,"how many revs the bot searches for a path each frame, lower to reduce cpu usage, but causes bots to stand still more"); -ConVar bot_command("rcbot_cmd","",0,"issues a command to all bots"); -ConVar bot_attack( "rcbot_flipout", "0", 0, "Rcbots all attack" ); -ConVar bot_scoutdj( "rcbot_scoutdj", "0.28", 0, "time scout uses to double jump" ); -ConVar bot_anglespeed( "rcbot_anglespeed", "0.21", 0, "smaller number will make bots turn slower (1 = instant turn but may overshoot)" ); -ConVar bot_stop( "rcbot_stop", "0", 0, "Make bots stop thinking!"); -ConVar bot_waypointpathdist("rcbot_wpt_pathdist","400",0,"Length for waypoints to automatically add paths at"); -ConVar bot_rj("rcbot_rj","0.01",0,"time for soldier to fire rocket after jumping"); -ConVar bot_defrate("rcbot_defrate","0.24",0,"rate for bots to defend"); -ConVar bot_beliefmulti("rcbot_beliefmulti","20.0",0,"multiplier for increasing bot belief"); -ConVar bot_belief_fade("rcbot_belief_fade","0.75",0,"the multiplayer rate bot belief decreases"); -ConVar bot_change_class("rcbot_change_classes","0",0,"bots change classes at random intervals"); -ConVar bot_use_vc_commands("rcbot_voice_cmds","1",0,"bots use voice commands e.g. medic/spy etc"); -ConVar bot_use_disp_dist("rcbot_disp_dist","800.0",0,"distance that bots will go back to use a dispenser"); -ConVar bot_max_cc_time("rcbot_max_cc_time","240",0,"maximum time for bots to consider changing class "); -ConVar bot_min_cc_time("rcbot_min_cc_time","60",0,"minimum time for bots to consider changing class "); -ConVar bot_avoid_radius("rcbot_avoid_radius","80",0,"radius in units for bots to avoid things"); -ConVar bot_avoid_strength("rcbot_avoid_strength","100",0,"strength of avoidance (0 = disable)"); -ConVar bot_messaround("rcbot_messaround","1",0,"bots mess around at start up"); -ConVar bot_heavyaimoffset("rcbot_heavyaimoffset","0.1",0,"fraction of how much the heavy aims at a diagonal offset"); -ConVar bot_aimsmoothing("rcbot_aimsmoothing","1",0,"(0 = no smoothing)"); -ConVar bot_bossattackfactor("rcbot_bossattackfactor","1.0",0,"the higher the more often the bots will shoot the boss"); -ConVar rcbot_enemyshootfov("rcbot_enemyshootfov","0.97",0,"the fov dot product before the bot shoots an enemy 0.7 = 45 degrees"); -ConVar rcbot_enemyshoot_gravgun_fov("rcbot_enemyshoot_gravgun_fov","0.98",0,"the fov dot product before the bot shoots an enemy 0.98 = 11 degrees"); -ConVar rcbot_wptplace_width("rcbot_wpt_width","48",0,"width of the player, automatic paths won't connect unless there is enough space for a player"); -ConVar rcbot_wpt_autoradius("rcbot_wpt_autoradius","0",0,"every waypoint added is given this radius, 0 = no radius"); -ConVar rcbot_wpt_autotype("rcbot_wpt_autotype","1",0,"If 1, types will be automatically added to waypoints when they are added (only for resupply/health/capture/flag etc)\nIf 2: types will autoamtically be added even if the waypoint is cut/paste"); -ConVar rcbot_move_sentry_time("rcbot_move_sentry_time","120",0,"seconds for bots to start thinking about moving sentries"); -ConVar rcbot_move_sentry_kpm("rcbot_move_sentry_kpm","1",0,"kpm = kills per minute, if less than this, bots will think about moving the sentry"); -ConVar rcbot_smoke_time("rcbot_smoke_time","10",0,"seconds a smoke grenade stays active"); -ConVar rcbot_move_disp_time("rcbot_move_disp_time","120",0,"seconds for bots to start thinking about moving dispensers"); -ConVar rcbot_move_disp_healamount("rcbot_move_disp_healamount","100",0,"if dispenser heals less than this per minute, bot will move the disp"); -ConVar rcbot_demo_runup_dist("rcbot_demo_runup","99.0",0,"distance the demo bot will take to run up for a pipe jump"); -ConVar rcbot_demo_jump("rcbot_enable_pipejump","1",0,"Enable experimental pipe jumping at rocket jump waypoints"); -ConVar rcbot_move_tele_time("rcbot_move_tele_time","120",0,"seconds for bots to start thinking about moving teleporters"); -ConVar rcbot_move_tele_tpm("rcbot_move_tele_tpm","1",0,"if no of players teleported per minute is less than this, bot will move the teleport"); -ConVar rcbot_tf2_protect_cap_time("rcbot_tf2_prot_cap_time","12.5",0,"time that the bots will spend more attention to the cap point if attacked"); -ConVar rcbot_tf2_protect_cap_percent("rcbot_tf2_protect_cap_percent","0.25",0,"the percentage that bots defend the capture point by standing on the point"); -ConVar rcbot_tf2_spy_kill_on_cap_dist("rcbot_tf2_spy_kill_on_cap_dist","200.0",0,"the distance for spy bots to attack players capturing a point"); -ConVar rcbot_move_dist("rcbot_move_dist","800",0,"minimum distance to move objects to"); -ConVar rcbot_shoot_breakables("rcbot_shoot_breakables","1",0,"if 1, bots will shoot breakable objects"); -ConVar rcbot_shoot_breakable_dist("rcbot_shoot_breakable_dist","128.0",0,"The distance bots will shoot breakables at"); -ConVar rcbot_shoot_breakable_cos("rcbot_shoot_breakable_cos","0.9",0,"The cosine of the angle bots should worry about breaking objects at (default = 0.9) ~= 25 degrees"); -ConVar rcbot_move_obj("rcbot_move_obj","1",0,"if 1 rcbot engineers will move objects around"); -ConVar rcbot_taunt("rcbot_taunt","0",0,"enable/disable bots taunting"); -ConVar rcbot_notarget("rcbot_notarget","0",0,"bots don't shoot the host!"); -ConVar rcbot_nocapturing("rcbot_dontcapture","0",0,"bots don't capture flags in DOD:S"); -ConVar rcbot_jump_obst_dist("rcbot_jump_obst_dist","80",0,"the distance from an obstacle the bot will jump"); -ConVar rcbot_jump_obst_speed("rcbot_jump_obst_speed","100",0,"the speed of the bot for the bot to jump an obstacle"); -ConVar rcbot_speed_boost("rcbot_speed_boost","1",0,"multiplier for bots speed"); -ConVar rcbot_melee_only("rcbot_melee_only","0",0,"if 1 bots will only use melee weapons"); -ConVar rcbot_debug_iglev("rcbot_debug_iglev","0",0,"bot think ignores functions to test cpu speed"); -ConVar rcbot_dont_move("rcbot_dontmove","0",0,"if 1 , bots will all move forward"); -ConVar rcbot_runplayercmd_dods("rcbot_runplayer_cmd_dods","417",0,"offset of the DOD:S PlayerRunCommand function"); -ConVar rcbot_runplayercmd_tf2("rcbot_runplayer_cmd_tf2","418",0,"offset of the TF2 PlayerRunCommand function"); -ConVar rcbot_runplayercmd_hookonce("rcbot_runplayer_hookonce","1",0,"function will hook only once, if 0 it will unhook and rehook after every map"); -ConVar rcbot_ladder_offs("rcbot_ladder_offs","42",0,"difference in height for bot to think it has touched the ladder waypoint"); -ConVar rcbot_ffa("rcbot_ffa","0",0,"Free for all mode -- bots shoot everyone"); -ConVar rcbot_prone_enemy_only("rcbot_prone_enemy_only","1",0,"if 1 bots only prone in DOD:S when they have an enemy"); -ConVar rcbot_menu_update_time1("rcbot_menu_update_time1","0.04",0,"time to update menus [displaying message]"); -ConVar rcbot_menu_update_time2("rcbot_menu_update_time2","0.2",0,"time to update menus [interval]"); -ConVar rcbot_autowaypoint_dist("rcbot_autowpt_dist","150.0",0,"distance for autowaypoints to be placed"); -ConVar rcbot_stats_inrange_dist("rcbot_stats_inrange_dist","320.0",0,"distance for bots to realise they have other players in range (for particular radio commands in DOD:S)"); -ConVar rcbot_squad_idle_time("rcbot_squad_idle_time","3.0",0,"time for bots to do other things if squad leader is idle for a short time"); -ConVar rcbot_bots_form_squads("rcbot_bots_form_squads","1",0,"if 1, bots will form their own squads via voice commands"); -ConVar rcbot_listen_dist("rcbot_listen_dist","512",0,"the distance for bots to hear things"); -ConVar rcbot_footstep_speed("rcbot_footstep_speed","250",0,"the speed players can go when you first hear them make footsteps"); -ConVar rcbot_bot_squads_percent("rcbot_bot_squads_percent","50",0,"the percentage of time bots make squads with other bots"); -ConVar rcbot_tooltips("rcbot_tooltips","1",0,"Enables/disables help tooltips"); -ConVar rcbot_debug_notasks("rcbot_debug_notasks","0",0,"Debug command, stops bots from doing tasks by themselves"); -ConVar rcbot_debug_dont_shoot("rcbot_debug_dont_shoot","0",0,"Debug command, stops bots from shooting everyone"); -ConVar rcbot_debug_show_route("rcbot_debug_show_route","0",0,"Debug command, shows waypoint route to host"); -ConVar rcbot_tf2_autoupdate_point_time("rcbot_tf2_autoupdate_point_time","60",0,"Time to automatically update points in TF2 for any changes"); -ConVar rcbot_tf2_payload_dist_retreat("rcbot_tf2_payload_dist_retreat","512.0",0,"Distance for payload bomb to be greater than at cap before defend team retreats"); -ConVar rcbot_spy_runaway_health("rcbot_spy_runaway_health","70",0,"health which spies run away after attacking"); -ConVar rcbot_supermode("rcbot_supermode","0",0,"If 1 will make every bot skill and reaction much higher"); -ConVar rcbot_addbottime("rcbot_addbottime","3",0,"The time in seconds for bots to be added after another"); -ConVar rcbot_customloadouts("rcbot_customloadouts","0",0,"Enable/disable custom loadouts for bots"); -ConVar rcbot_givenameditem_offset("rcbot_givenameditem_offset","471",0,"offset of the GiveNamedItem function"); -ConVar rcbot_equipwearable_offset("rcbot_equipwearable_offset","426",0,"offset of the EquipWearable function"); -ConVar rcbot_rmplayeritem_offset("rcbot_rmplayeritem_offset","270",0,"offset of the RemovePlayerItem function"); -ConVar rcbot_enable_attributes("rcbot_enable_attributes","1",0,"Enable/disable attributes on TF2 weapon loadouts"); -ConVar rcbot_force_generation("rcbot_force_generation","0",0,"force generation of weapons"); -ConVar rcbot_equiphats("rcbot_equiphats", "0", 0, "Allow bots to quip a random hat (unstable)"); -ConVar rcbot_getweaponslot_offset("rcbot_getweaponslot_offset", "268", 0, "offset of the getweaponslot function"); -ConVar rcbot_removewearable_offset("rcbot_removewearable_offset", "427", 0, "offset of the removewearable function"); -ConVar rcbot_weaponequip_offset("rcbot_weaponequip_offset", "261", 0, "offset for weapon equip function"); +static ICvar* s_pCVar; //TODO: Unused? [APG]RoboCop[CL] + +ConVar rcbot_tf2_debug_spies_cloakdisguise("rcbot_tf2_debug_spies_cloakdisguise", "1", 0, "Debug command : allow spy bots to cloak and disguise"); +ConVar rcbot_tf2_medic_letgotime("rcbot_tf2_medic_letgotime", "0.5", 0, "Time for medic to let go of medigun to switch players"); +ConVar rcbot_tf2_pyro_airblast("rcbot_tf2_pyro_airblast_ammo", "50", 0, "Ammo must be above this to airblast -- if 200 airblast will be disabled"); +ConVar rcbot_projectile_tweak("rcbot_projtweak", "0.05", 0, "Tweaks the bots knowledge of projectiles and gravity"); + +ConVar bot_cmd_enable_wpt_sounds("rcbot_enable_wpt_sounds", "1", 0, "Enable/disable sound effects when editing waypoints"); +//ConVar bot_general_difficulty("rcbot_skill", "0.8", 0, "General difficulty of the bots. 0.5 = stock, < 0.5 easier, > 0.5 = harder");//TODO: Broken! [APG]RoboCop[CL] +ConVar bot_visrevs_clients("rcbot_visrevs_clients", "3", 0, "how many revs the bot searches for visible players and enemies, lower to reduce cpu usage"); +ConVar bot_spyknifefov("rcbot_spyknifefov", "80", 0, "the FOV from the enemy that spies must backstab from"); +ConVar bot_visrevs("rcbot_visrevs", "6", 0, "how many revs the bot searches for visible monsters, lower to reduce cpu usage min:5"); +ConVar bot_pathrevs("rcbot_pathrevs", "30", 0, "how many revs the bot searches for a path each frame, lower to reduce cpu usage, but causes bots to stand still more"); +ConVar bot_command("rcbot_cmd", "", 0, "issues a command to all bots"); +ConVar bot_attack("rcbot_flipout", "0", 0, "Rcbots all attack"); +ConVar bot_scoutdj("rcbot_scoutdj", "0.5", 0, "time scout uses to double jump"); +ConVar bot_anglespeed("rcbot_anglespeed", "0.25", 0, "smaller number will make bots turn slower (1 = instant turn but may overshoot)"); +ConVar bot_stop("rcbot_stop", "0", 0, "Make bots stop thinking!"); +ConVar bot_waypointpathdist("rcbot_wpt_pathdist", "400", 0, "Length for waypoints to automatically add paths at"); + +ConVar bot_rj("rcbot_rj", "0.01", 0, "time for soldier to fire rocket after jumping"); +ConVar bot_defrate("rcbot_defrate", "0.2", 0, "rate for bots to defend"); +ConVar bot_beliefmulti("rcbot_beliefmulti", "20.0", 0, "multiplier for increasing bot belief"); //Not referenced properly? [APG]RoboCop[CL] +ConVar bot_belief_fade("rcbot_belief_fade", "0.75", 0, "the multiplayer rate bot belief decreases"); +ConVar bot_change_class("rcbot_change_classes", "0", 0, "bots change classes at random intervals"); +ConVar bot_use_vc_commands("rcbot_voice_cmds", "1", 0, "bots use voice commands e.g. medic/spy etc"); +ConVar bot_use_disp_dist("rcbot_disp_dist", "800.0", 0, "distance that bots will go back to use a dispenser"); +ConVar bot_max_cc_time("rcbot_max_cc_time", "240", 0, "maximum time for bots to consider changing class "); +ConVar bot_min_cc_time("rcbot_min_cc_time", "60", 0, "minimum time for bots to consider changing class "); +ConVar bot_avoid_radius("rcbot_avoid_radius", "80", 0, "radius in units for bots to avoid things"); +ConVar bot_avoid_strength("rcbot_avoid_strength", "100", 0, "strength of avoidance (0 = disable)"); +ConVar bot_messaround("rcbot_messaround", "1", 0, "bots mess around at start up"); +ConVar bot_heavyaimoffset("rcbot_heavyaimoffset", "0.1", 0, "fraction of how much the heavy aims at a diagonal offset"); +ConVar bot_aimsmoothing("rcbot_aimsmoothing", "0", 0, "(0 = no smoothing)");//TODO: Broken! [APG]RoboCop[CL] +ConVar bot_bossattackfactor("rcbot_bossattackfactor", "1.0", 0, "the higher the more often the bots will shoot the boss"); + +ConVar rcbot_enemyshootfov("rcbot_enemyshootfov", "0.97", 0, "the fov dot product before the bot shoots an enemy 0.7 = 45 degrees"); +ConVar rcbot_enemyshoot_gravgun_fov("rcbot_enemyshoot_gravgun_fov", "0.98", 0, "the fov dot product before the bot shoots an enemy 0.98 = 11 degrees"); +ConVar rcbot_wptplace_width("rcbot_wpt_width", "48", 0, "width of the player, automatic paths won't connect unless there is enough space for a player"); +ConVar rcbot_wpt_autoradius("rcbot_wpt_autoradius", "0", 0, "every waypoint added is given this radius, 0 = no radius"); +ConVar rcbot_wpt_autotype("rcbot_wpt_autotype", "1", 0, "If 1, types will be automatically added to waypoints when they are added (only for resupply/health/capture/flag etc)\nIf 2: types will autoamtically be added even if the waypoint is cut/paste"); +ConVar rcbot_wpt_autotype_detection_range("rcbot_wpt_autotype_detection_range", "80", 0, "Maximum distance between entities and a waypoint for automatic type detection."); +ConVar rcbot_move_sentry_time("rcbot_move_sentry_time", "120", 0, "seconds for bots to start thinking about moving sentries"); +ConVar rcbot_move_sentry_kpm("rcbot_move_sentry_kpm", "1", 0, "kpm = kills per minute, if less than this, bots will think about moving the sentry"); +ConVar rcbot_smoke_time("rcbot_smoke_time", "10", 0, "seconds a smoke grenade stays active"); +ConVar rcbot_move_disp_time("rcbot_move_disp_time", "120", 0, "seconds for bots to start thinking about moving dispensers"); +ConVar rcbot_move_disp_healamount("rcbot_move_disp_healamount", "100", 0, "if dispenser heals less than this per minute, bot will move the disp"); +ConVar rcbot_demo_runup_dist("rcbot_demo_runup", "99.0", 0, "Distance the demo bot will take to run up for a pipe/sticky bomb jump"); +ConVar rcbot_demo_jump("rcbot_enable_pipejump", "1", 0, "Enable experimental pipe jumping at rocket jump waypoints"); +ConVar rcbot_move_tele_time("rcbot_move_tele_time", "120", 0, "seconds for bots to start thinking about moving teleporters"); +ConVar rcbot_move_tele_tpm("rcbot_move_tele_tpm", "1", 0, "if no of players teleported per minute is less than this, bot will move the teleport"); +ConVar rcbot_tf2_protect_cap_time("rcbot_tf2_prot_cap_time", "12.5", 0, "time that the bots will spend more attention to the cap point if attacked"); +ConVar rcbot_tf2_protect_cap_percent("rcbot_tf2_protect_cap_percent", "0.25", 0, "the percentage that bots defend the capture point by standing on the point"); +ConVar rcbot_tf2_spy_kill_on_cap_dist("rcbot_tf2_spy_kill_on_cap_dist", "200.0", 0, "the distance for spy bots to attack players capturing a point"); + +ConVar rcbot_move_dist("rcbot_move_dist", "800", 0, "minimum distance to move objects to"); +ConVar rcbot_shoot_breakables("rcbot_shoot_breakables", "1", 0, "if 1, bots will shoot breakable objects"); +ConVar rcbot_shoot_breakable_dist("rcbot_shoot_breakable_dist", "128.0", 0, "The distance bots will shoot breakables at"); +ConVar rcbot_shoot_breakable_cos("rcbot_shoot_breakable_cos", "0.9", 0, "The cosine of the angle bots should worry about breaking objects at (default = 0.9) ~= 25 degrees"); +ConVar rcbot_move_obj("rcbot_move_obj", "1", 0, "if 1 rcbot engineers will move objects around"); +ConVar rcbot_taunt("rcbot_taunt", "0", 0, "enable/disable bots taunting"); +ConVar rcbot_notarget("rcbot_notarget", "0", 0, "bots don't shoot the host!"); +ConVar rcbot_nocapturing("rcbot_dontcapture", "0", 0, "bots don't capture flags in DOD:S"); +ConVar rcbot_jump_obst_dist("rcbot_jump_obst_dist", "80", 0, "the distance from an obstacle the bot will jump"); +//ConVar rcbot_jump_obst_speed("rcbot_jump_obst_speed", "100", 0, "the speed of the bot for the bot to jump an obstacle"); +ConVar rcbot_speed_boost("rcbot_speed_boost", "1", 0, "multiplier for bots speed"); +ConVar rcbot_melee_only("rcbot_melee_only", "0", 0, "if 1 bots will only use melee weapons"); +ConVar rcbot_debug_iglev("rcbot_debug_iglev", "0", 0, "bot think ignores functions to test cpu speed"); //Not referenced properly? [APG]RoboCop[CL] +ConVar rcbot_dont_move("rcbot_dont_move", "0", 0, "if 1 , bots will all move forward"); + +ConVar rcbot_runplayercmd_dods("rcbot_runplayer_cmd_dods", "417", 0, "offset of the DOD:S PlayerRunCommand function"); +ConVar rcbot_ladder_offs("rcbot_ladder_offs", "42", 0, "difference in height for bot to think it has touched the ladder waypoint"); +ConVar rcbot_ffa("rcbot_ffa", "0", 0, "Free for all mode -- bots shoot everyone"); +ConVar rcbot_prone_enemy_only("rcbot_prone_enemy_only", "1", 0, "if 1 bots only prone in DOD:S when they have an enemy"); +ConVar rcbot_menu_update_time1("rcbot_menu_update_time1", "0.04", 0, "time to update menus [displaying message]"); +ConVar rcbot_menu_update_time2("rcbot_menu_update_time2", "0.2", 0, "time to update menus [interval]"); +ConVar rcbot_autowaypoint_dist("rcbot_autowpt_dist", "150.0", 0, "distance for autowaypoints to be placed"); +ConVar rcbot_stats_inrange_dist("rcbot_stats_inrange_dist", "320.0", 0, "distance for bots to realise they have other players in range (for particular radio commands in DOD:S)"); +ConVar rcbot_squad_idle_time("rcbot_squad_idle_time", "3.0", 0, "time for bots to do other things if squad leader is idle for a short time"); +ConVar rcbot_bots_form_squads("rcbot_bots_form_squads", "1", 0, "if 1, bots will form their own squads via voice commands"); +ConVar rcbot_listen_dist("rcbot_listen_dist", "512", 0, "the distance for bots to hear things"); +ConVar rcbot_footstep_speed("rcbot_footstep_speed", "250", 0, "the speed players can go when you first hear them make footsteps"); +ConVar rcbot_bot_squads_percent("rcbot_bot_squads_percent", "50", 0, "the percentage of time bots make squads with other bots"); +ConVar rcbot_tooltips("rcbot_tooltips", "1", 0, "Enables/disables help tooltips"); + +ConVar rcbot_debug_notasks("rcbot_debug_notasks", "0", 0, "Debug command, stops bots from doing tasks by themselves"); +ConVar rcbot_debug_dont_shoot("rcbot_debug_dont_shoot", "0", 0, "Debug command, stops bots from shooting everyone"); +ConVar rcbot_debug_show_route("rcbot_debug_show_route", "0", 0, "Debug command, shows waypoint route to host"); +ConVar rcbot_tf2_autoupdate_point_time("rcbot_tf2_autoupdate_point_time", "60", 0, "Time to automatically update points in TF2 for any changes"); +ConVar rcbot_tf2_payload_dist_retreat("rcbot_tf2_payload_dist_retreat", "512.0", 0, "Distance for payload bomb to be greater than at cap before defend team retreats"); +ConVar rcbot_spy_runaway_health("rcbot_spy_runaway_health", "70", 0, "health which spies run away after attacking"); +ConVar rcbot_supermode("rcbot_supermode", "0", 0, "If 1 will make every bot skill and reaction much higher"); +ConVar rcbot_addbottime("rcbot_addbottime", "5", 0, "The time in seconds for bots to be added after another"); ConVar rcbot_gamerules_offset("rcbot_gamerules_offset", "5", 0, "offset for gamerules object"); -ConVar rcbot_weaponswitch_offset("rcbot_weaponswitch_offset", "264", 0, "offset for weapon Switch function"); -ConVar rcbot_bot_quota_interval("rcbot_bot_quota_interval", "10", 0, "Interval between bot quota checks"); -//ConVar rcbot_bot_add_cmd("rcbot_bot_add_cmd","bot",0,"command to add puppet bots"); -//ConVar rcbot_bot_add_cmd("rcbot_hook_engine","1",0,"command to add puppet bots"); -ConVar rcbot_show_welcome_msg("rcbot_show_welcome_msg", "1", 0, "Show welcome message on player connect"); +ConVar rcbot_datamap_offset("rcbot_datamap_offset", "0", 0, "offset for datamaps"); +ConVar rcbot_bot_quota_interval("rcbot_bot_quota_interval", "10", 0, "Interval between bot quota checks, 0 or lower to disable"); +ConVar rcbot_show_welcome_msg("rcbot_show_welcome_msg", "1", 0, "Show welcome message on player connect");//Not referenced properly? [APG]RoboCop[CL] ConVar rcbot_force_class("rcbot_force_class", "0", 0, "Force bots to choose specified class, kills alive bots on change (1 - 9, set to 0 for none)"); +ConVar rcbot_ignore_spectators("rcbot_ignore_spectators", "0", 0, "Ignore spectators when calculating target number of bots"); +ConVar rcbot_nonrandom_kicking("rcbot_nonrandom_kicking", "0", 0, "Choose newest bot from largest team when kicking bots"); +ConVar rcbot_nonrandom_profile("rcbot_nonrandom_profile", "0", 0, "Choose first free bot from profile list when creating bots"); + +// Synergy CVars +ConVar rcbot_runplayercmd_syn("rcbot_runplayer_cmd_syn", "424", 0, "offset of the Synergy PlayerRunCommand function"); +ConVar rcbot_syn_use_search_range("rcbot_syn_use_search_range", "256", 0, "Sets the maximum button search range.", true, 150.0f, true, 1024.0f); + +// Counter-Strike:Source Cvars +ConVar rcbot_css_economy_eco_limit("rcbot_css_economy_eco_limit", "2000", 0, "If the bot money is less than this, it won't purchase anything."); -ConVar *sv_gravity = NULL; -ConVar *sv_cheats = NULL;//("sv_cheats"); -ConVar *mp_teamplay = NULL; -ConVar *sv_tags = NULL; -ConVar *mp_friendlyfire = NULL; -ConCommandBase *puppet_bot_cmd = NULL; -ConVar *mp_stalemate_enable = NULL; -ConVar *mp_stalemate_meleeonly = NULL; +ConVarRef sv_gravity("sv_gravity"); +ConVarRef mp_teamplay("mp_teamplay"); +ConVarRef sv_tags("sv_tags"); +ConVarRef mp_friendlyfire("mp_friendlyfire"); +ConVarRef mp_stalemate_enable("mp_stalemate_enable"); +ConVarRef mp_stalemate_meleeonly("mp_stalemate_meleeonly"); -void RCBOT2_Cvar_setup (ICvar *cvar) +// For CS:S +ConVarRef mp_roundtime("mp_roundtime"); +ConVarRef mp_c4timer("mp_c4timer"); + +void RCBOT2_Cvar_setup(ICvar* cvar) //'cvar' hides global declaration from /public/icvar.h [APG]RoboCop[CL] { - mp_stalemate_enable = cvar->FindVar("mp_stalemate_enable"); - mp_stalemate_meleeonly = cvar->FindVar("mp_stalemate_meleeonly"); - sv_cheats = cvar->FindVar("sv_cheats"); - sv_gravity = cvar->FindVar("sv_gravity"); - mp_friendlyfire = cvar->FindVar("mp_friendlyfire"); - sv_tags = cvar->FindVar("sv_tags"); - puppet_bot_cmd = cvar->FindCommand("bot"); - mp_teamplay = cvar->FindVar("mp_teamplay"); - - if ( sv_tags != NULL ) - { - char sv_tags_str[512]; - - strcpy(sv_tags_str,sv_tags->GetString()); - - // fix - if ( strstr(sv_tags_str,"rcbot2") == NULL ) - { - - if ( sv_tags_str[0] == 0 ) - strcat(sv_tags_str,"rcbot2"); - else - strcat(sv_tags_str,",rcbot2"); - - sv_tags->SetValue(sv_tags_str); - - } - } + if (cvar == nullptr) + { + return; // Handle null pointer gracefully + } + + ConVar* svTagsVar = cvar->FindVar("sv_tags"); + + if (svTagsVar == nullptr) + { + return; // Handle missing variable gracefully + } + std::string sv_tags = svTagsVar->GetString(); + if (sv_tags.find(BOT_TAG) == std::string::npos) + { + sv_tags += ","; + sv_tags += BOT_TAG; + svTagsVar->SetValue(sv_tags.c_str()); + } } diff --git a/utils/RCBot2_meta/bot_cvars.h b/utils/RCBot2_meta/bot_cvars.h index d76e9c77a..ac0b7dc6c 100644 --- a/utils/RCBot2_meta/bot_cvars.h +++ b/utils/RCBot2_meta/bot_cvars.h @@ -3,17 +3,11 @@ extern ConVar rcbot_tf2_debug_spies_cloakdisguise; extern ConVar rcbot_tf2_medic_letgotime; -//extern ConVar rcbot_const_round_offset; extern ConVar rcbot_const_point_master_offset; -//extern ConVar rcbot_const_point_offset; -//extern ConVar rcbot_const_point_data_offset; extern ConVar rcbot_tf2_pyro_airblast; extern ConVar rcbot_projectile_tweak; -//extern ConVar bot_sv_cheat_warning; extern ConVar bot_cmd_enable_wpt_sounds; -//extern ConVar bot_cmd_nocheats; -extern ConVar bot_general_difficulty; -//extern ConVar bot_sv_cheats_auto; +//extern ConVar bot_general_difficulty; extern ConVar bot_visrevs_clients; extern ConVar bot_spyknifefov; extern ConVar bot_visrevs; @@ -44,6 +38,7 @@ extern ConVar rcbot_enemyshoot_gravgun_fov; extern ConVar rcbot_wptplace_width; extern ConVar rcbot_wpt_autoradius; extern ConVar rcbot_wpt_autotype; +extern ConVar rcbot_wpt_autotype_detection_range; extern ConVar rcbot_move_sentry_time; extern ConVar rcbot_move_sentry_kpm; extern ConVar rcbot_smoke_time; @@ -71,8 +66,6 @@ extern ConVar rcbot_melee_only; extern ConVar rcbot_debug_iglev; extern ConVar rcbot_dont_move; extern ConVar rcbot_runplayercmd_dods; -extern ConVar rcbot_runplayercmd_tf2; -extern ConVar rcbot_runplayercmd_hookonce; extern ConVar rcbot_ladder_offs; extern ConVar rcbot_ffa; extern ConVar rcbot_prone_enemy_only; @@ -94,34 +87,37 @@ extern ConVar rcbot_tf2_payload_dist_retreat; extern ConVar rcbot_spy_runaway_health; extern ConVar rcbot_supermode; extern ConVar rcbot_addbottime; -extern ConVar rcbot_customloadouts; -extern ConVar rcbot_givenameditem_offset; -extern ConVar rcbot_equipwearable_offset; -extern ConVar rcbot_rmplayeritem_offset; -extern ConVar rcbot_enable_attributes; -extern ConVar rcbot_force_generation; -extern ConVar rcbot_equiphats; -extern ConVar rcbot_getweaponslot_offset; -extern ConVar rcbot_removewearable_offset; -extern ConVar rcbot_weaponequip_offset; extern ConVar rcbot_gamerules_offset; +extern ConVar rcbot_datamap_offset; extern ConVar rcbot_bot_quota_interval; -//extern ConVar rcbot_util_learning; -//extern ConVar rcbot_bot_add_cmd; +//extern ConVar rcbot_const_point_master_offset; +extern ConVar rcbot_util_learning; + +//Synergy Cvars +extern ConVar rcbot_runplayercmd_syn; +extern ConVar rcbot_syn_use_search_range; + +// Counter-Strike: Source Cvars +extern ConVar rcbot_css_economy_eco_limit; /** Additional convars by pongo1231 **/ extern ConVar rcbot_show_welcome_msg; extern ConVar rcbot_force_class; -extern ConVar *sv_gravity; -extern ConVar *sv_cheats; -extern ConVar *mp_teamplay; -extern ConVar *sv_tags; -extern ConVar *mp_friendlyfire; +extern ConVar rcbot_ignore_spectators; +extern ConVar rcbot_nonrandom_kicking; +extern ConVar rcbot_nonrandom_profile; -extern ConCommandBase *puppet_bot_cmd; +extern ConVarRef sv_gravity; +extern ConVarRef mp_teamplay; +extern ConVarRef sv_tags; +extern ConVarRef mp_friendlyfire; +extern ConVarRef mp_stalemate_enable; +// For CS:S +extern ConVarRef mp_roundtime; +extern ConVarRef mp_c4timer; -void RCBOT2_Cvar_setup (ICvar *cvar); +void RCBOT2_Cvar_setup (ICvar* cvar); #endif diff --git a/utils/RCBot2_meta/bot_dod_bot.cpp b/utils/RCBot2_meta/bot_dod_bot.cpp index ee93b2e49..42f117f56 100644 --- a/utils/RCBot2_meta/bot_dod_bot.cpp +++ b/utils/RCBot2_meta/bot_dod_bot.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -29,6 +31,7 @@ * */ #include "bot.h" +#include "bot_cvars.h" #include "ndebugoverlay.h" #include "bot_squads.h" #include "bot_dod_bot.h" @@ -47,21 +50,11 @@ #include "bot_perceptron.h" #include "bot_waypoint_visibility.h" -extern ConVar bot_beliefmulti; -extern ConVar bot_max_cc_time; -extern ConVar bot_min_cc_time; -extern ConVar bot_change_class; -extern ConVar rcbot_enemyshootfov; -extern ConVar bot_defrate; -extern ConVar rcbot_smoke_time; -extern ConVar rcbot_melee_only; -extern ConVar rcbot_shoot_breakables; -extern ConVar rcbot_shoot_breakable_dist; -extern ConVar rcbot_shoot_breakable_cos; -extern ConVar rcbot_nocapturing; -extern ConVar bot_messaround; -extern ConVar rcbot_speed_boost; -extern ConVar rcbot_projectile_tweak; +#include +#include +#include +#include +#include const char *g_DODClassCmd[2][6] = { {"cls_garand","cls_tommy","cls_bar","cls_spring","cls_30cal","cls_bazooka"}, @@ -70,7 +63,7 @@ const char *g_DODClassCmd[2][6] = // could be a bomb void CBroadcastBombEvent :: execute (CBot *pBot) { - CDODBot *pDODBot = (CDODBot*)pBot; + CDODBot *pDODBot = static_cast(pBot); pDODBot->bombEvent(DOD_BOMB_PLANT,m_iCP,m_iTeam); } @@ -89,9 +82,9 @@ float CDODBot :: getEnemyFactor ( edict_t *pEnemy ) // could be a bomb or flag capture event -void CDODBot :: bombEvent ( int iEvent, int iCP, int iTeam ) +void CDODBot :: bombEvent ( int iEvent, const int iCP, const int iTeam ) { - int iWaypoint = CDODMod::m_Flags.getWaypointAtFlag(iCP); + const int iWaypoint = CDODMod::m_Flags.getWaypointAtFlag(iCP); if ( iTeam && (iWaypoint != -1) ) { @@ -110,38 +103,36 @@ void CDODBot :: bombEvent ( int iEvent, int iCP, int iTeam ) CDODBot :: CDODBot() { - CBot(); - init(true); + CDODBot::init(true); } -void CDODBot :: init (bool bVarInit) +void CDODBot :: init (const bool bVarInit) { CBot::init(bVarInit); m_iSelectedClass = -1; m_bCheckClass = false; - m_pWantToProne = NULL; + m_pWantToProne = nullptr; } void CDODBot :: setup () { CBot::setup(); - if ( m_pWantToProne == NULL ) + if ( m_pWantToProne == nullptr) m_pWantToProne = new CPerceptron(3); // health , distance from enemy, danger out of 255 } void CDODBot :: freeMapMemory () { - if ( m_pWantToProne ) - delete m_pWantToProne; + delete m_pWantToProne; - m_pWantToProne = NULL; + m_pWantToProne = nullptr; CBot::freeMapMemory(); } -bool CDODBot::canGotoWaypoint(Vector vPrevWaypoint, CWaypoint *pWaypoint, CWaypoint *pPrev ) +bool CDODBot::canGotoWaypoint(const Vector& vPrevWaypoint, CWaypoint* pWaypoint, CWaypoint* pPrev) { if ( CBot::canGotoWaypoint(vPrevWaypoint,pWaypoint,pPrev) ) { @@ -149,11 +140,11 @@ bool CDODBot::canGotoWaypoint(Vector vPrevWaypoint, CWaypoint *pWaypoint, CWaypo { return false; } - else if ( (m_iTeam == TEAM_AXIS) && pWaypoint->hasFlag(CWaypointTypes::W_FL_NOAXIS) ) + if ( (m_iTeam == TEAM_AXIS) && pWaypoint->hasFlag(CWaypointTypes::W_FL_NOAXIS) ) { return false; } - else if ( pWaypoint->hasFlag(CWaypointTypes::W_FL_BREAKABLE) ) + if ( pWaypoint->hasFlag(CWaypointTypes::W_FL_BREAKABLE) ) { edict_t *pBreakable = CDODMod::getBreakable(pWaypoint); @@ -180,8 +171,8 @@ bool CDODBot::canGotoWaypoint(Vector vPrevWaypoint, CWaypoint *pWaypoint, CWaypo return false; } - else // entity invalid -- maybe blown up and freed by engine - return true; + // entity invalid -- maybe blown up and freed by engine + return true; } return true; @@ -190,23 +181,22 @@ bool CDODBot::canGotoWaypoint(Vector vPrevWaypoint, CWaypoint *pWaypoint, CWaypo return false; } -#define UPDATE_VISIBLE_OBJECT(visobj,pent) if ( !visobj.get() || (distanceFrom(pent)distance) ) { visobj = NULL; } } -#define NULLIFY_VISIBLE_CONDITION(visobj,pent,distance,condition) if ( visobj == pent ) { if ( !bValid || (distanceFrom(visobj)>distance) || (condition) ) { visobj = NULL; } } +#define UPDATE_VISIBLE_OBJECT(visobj,pent) if ( !(visobj).get() || (distanceFrom(pent)(distance)) ) { (visobj) = NULL; } } +#define NULLIFY_VISIBLE_CONDITION(visobj,pent,distance,condition) if ( (visobj) == (pent) ) { if ( !bValid || (distanceFrom(visobj)>(distance)) || (condition) ) { (visobj) = NULL; } } -bool CDODBot :: setVisible ( edict_t *pEntity, bool bVisible ) +bool CDODBot :: setVisible ( edict_t *pEntity, const bool bVisible ) { //static float fDist; static const char *szClassname; static bool bNoDraw; static bool bValid; static float fSmokeTime; - extern ConVar *mp_friendlyfire; static bool bFriendlyFire; - bFriendlyFire = (mp_friendlyfire!=NULL)?mp_friendlyfire->GetBool():false; + bFriendlyFire = mp_friendlyfire.IsValid()? mp_friendlyfire.GetBool() : false; bValid = CBot::setVisible(pEntity,bVisible); @@ -218,55 +208,55 @@ bool CDODBot :: setVisible ( edict_t *pEntity, bool bVisible ) { if ( (m_pNearestDeadTeamMate != pEntity) && (CClassInterface::getTeam(pEntity) == m_iTeam) && !CBotGlobals::entityIsAlive(pEntity) ) { - UPDATE_VISIBLE_OBJECT(m_pNearestDeadTeamMate,pEntity); + UPDATE_VISIBLE_OBJECT(m_pNearestDeadTeamMate,pEntity) } - else if ( (m_pNearestBreakable != pEntity) && (strncmp(pEntity->GetClassName(),"prop_physics",12)==0) ) + else if ( (m_pNearestBreakable != pEntity) && (std::strncmp(pEntity->GetClassName(),"prop_physics",12)==0) ) { - UPDATE_VISIBLE_OBJECT_CONDITION(m_pNearestBreakable,pEntity,CClassInterface::getPlayerHealth(pEntity) > 0); + UPDATE_VISIBLE_OBJECT_CONDITION(m_pNearestBreakable,pEntity,CClassInterface::getPlayerHealth(pEntity) > 0) } else if ( (m_pNearestFlag != pEntity) && CDODMod::m_Flags.isFlag(pEntity) ) { - UPDATE_VISIBLE_OBJECT(m_pNearestFlag,pEntity); + UPDATE_VISIBLE_OBJECT(m_pNearestFlag,pEntity) } else if ( (m_pNearestBomb != pEntity) && CDODMod::m_Flags.isBomb(pEntity) ) { - UPDATE_VISIBLE_OBJECT_CONDITION(m_pNearestBomb,pEntity,CClassInterface::getDODBombState(pEntity)!=0); + UPDATE_VISIBLE_OBJECT_CONDITION(m_pNearestBomb,pEntity,CClassInterface::getDODBombState(pEntity)!=0) } // grenade_smoke // 012345678 // don't run away from smoke grenades - else if ( (pEntity!=m_pEnemyGrenade) && (szClassname[8]!='s') && (strncmp(szClassname,"grenade",7) == 0 ) && + else if ( (pEntity!=m_pEnemyGrenade) && (szClassname[8]!='s') && (std::strncmp(szClassname,"grenade",7) == 0 ) && ((CClassInterface::getGrenadeThrower(pEntity) == m_pEdict) || ((CClassInterface::getTeam(pEntity) == m_iEnemyTeam)||bFriendlyFire))) { - UPDATE_VISIBLE_OBJECT(m_pEnemyGrenade,pEntity); + UPDATE_VISIBLE_OBJECT(m_pEnemyGrenade,pEntity) } - else if ( (pEntity!=m_pEnemyRocket) && (strncmp(szClassname,"rocket",6) == 0 ) && + else if ( (pEntity!=m_pEnemyRocket) && (std::strncmp(szClassname,"rocket",6) == 0 ) && (CClassInterface::getTeam(pEntity) == m_iEnemyTeam) ) { - UPDATE_VISIBLE_OBJECT(m_pEnemyRocket,pEntity); + UPDATE_VISIBLE_OBJECT(m_pEnemyRocket,pEntity) } else if ( (pEntity!=m_pNearestPathBomb) && CDODMod::isPathBomb(pEntity) && (CClassInterface::getDODBombState(pEntity)!=0) ) { - UPDATE_VISIBLE_OBJECT(m_pNearestPathBomb,pEntity); + UPDATE_VISIBLE_OBJECT(m_pNearestPathBomb,pEntity) } - else if ( (pEntity!=m_pNearestWeapon) && (strncmp(szClassname,"weapon_",7)==0) ) + else if ( (pEntity!=m_pNearestWeapon) && (std::strncmp(szClassname,"weapon_",7)==0) ) { - UPDATE_VISIBLE_OBJECT(m_pNearestWeapon,pEntity); + UPDATE_VISIBLE_OBJECT(m_pNearestWeapon,pEntity) } } else { - NULLIFY_VISIBLE(m_pNearestFlag,pEntity,512.0f); - NULLIFY_VISIBLE_CONDITION(m_pNearestBreakable,pEntity,CWaypointLocations::REACHABLE_RANGE,CClassInterface::getPlayerHealth(m_pNearestBreakable)<=0); - NULLIFY_VISIBLE(m_pEnemyGrenade,pEntity,BLAST_RADIUS*2); - NULLIFY_VISIBLE(m_pEnemyRocket,pEntity,BLAST_RADIUS*2); - NULLIFY_VISIBLE_CONDITION(m_pNearestBomb,pEntity,BLAST_RADIUS*2,CClassInterface::getDODBombState(m_pNearestBomb)==0); - NULLIFY_VISIBLE_CONDITION(m_pNearestPathBomb,pEntity,BLAST_RADIUS*2,CClassInterface::getDODBombState(m_pNearestPathBomb)==0); - NULLIFY_VISIBLE(m_pNearestWeapon,pEntity,CWaypointLocations::REACHABLE_RANGE); + NULLIFY_VISIBLE(m_pNearestFlag,pEntity,512.0f) + NULLIFY_VISIBLE_CONDITION(m_pNearestBreakable,pEntity,CWaypointLocations::REACHABLE_RANGE,CClassInterface::getPlayerHealth(m_pNearestBreakable)<=0) + NULLIFY_VISIBLE(m_pEnemyGrenade,pEntity,BLAST_RADIUS*2) + NULLIFY_VISIBLE(m_pEnemyRocket,pEntity,BLAST_RADIUS*2) + NULLIFY_VISIBLE_CONDITION(m_pNearestBomb,pEntity,BLAST_RADIUS*2,CClassInterface::getDODBombState(m_pNearestBomb)==0) + NULLIFY_VISIBLE_CONDITION(m_pNearestPathBomb,pEntity,BLAST_RADIUS*2,CClassInterface::getDODBombState(m_pNearestPathBomb)==0) + NULLIFY_VISIBLE(m_pNearestWeapon,pEntity,CWaypointLocations::REACHABLE_RANGE) } - if ( !bNoDraw && (pEntity != m_pNearestSmokeToEnemy) && (strncmp(szClassname,"grenade_smoke",13) == 0) ) + if ( !bNoDraw && (pEntity != m_pNearestSmokeToEnemy) && (std::strncmp(szClassname,"grenade_smoke",13) == 0) ) { fSmokeTime = gpGlobals->curtime - CClassInterface::getSmokeSpawnTime(pEntity); @@ -283,9 +273,9 @@ bool CDODBot :: setVisible ( edict_t *pEntity, bool bVisible ) { // math time - good lord! // choose the best smoke that is worthwhile for checking enemy - if ( m_pNearestSmokeToEnemy && (fabs(DotProductFromOrigin(CBotGlobals::entityOrigin(pEntity))- + if ( m_pNearestSmokeToEnemy && (std::fabs(DotProductFromOrigin(CBotGlobals::entityOrigin(pEntity))- DotProductFromOrigin(CBotGlobals::entityOrigin(m_pEnemy))) <= - fabs(DotProductFromOrigin(CBotGlobals::entityOrigin(m_pNearestSmokeToEnemy))- + std::fabs(DotProductFromOrigin(CBotGlobals::entityOrigin(m_pNearestSmokeToEnemy))- DotProductFromOrigin(CBotGlobals::entityOrigin(m_pEnemy)))) ) { m_pNearestSmokeToEnemy = pEntity; @@ -299,13 +289,13 @@ bool CDODBot :: setVisible ( edict_t *pEntity, bool bVisible ) fSmokeTime = gpGlobals->curtime - CClassInterface::getSmokeSpawnTime(pEntity); if ( bNoDraw || ((fSmokeTime < 1.0f) || (fSmokeTime > rcbot_smoke_time.GetFloat())) ) - m_pNearestSmokeToEnemy = NULL; + m_pNearestSmokeToEnemy = nullptr; } return bValid; } -void CDODBot :: selectedClass ( int iClass ) +void CDODBot :: selectedClass (const int iClass) { m_iSelectedClass = iClass; } @@ -336,6 +326,9 @@ bool CDODBot :: startGame () if ( (m_iDesiredClass < 0) || (m_iDesiredClass > 5) ) chooseClass(false); + if (CClassInterface::getPlayerClassDOD(m_pEdict) < 0) + return false; + // not the correct class? and desired class is valid? if ( (m_iDesiredClass >= 0) && (m_iDesiredClass <= 5) && (m_iDesiredClass != CClassInterface::getPlayerClassDOD(m_pEdict)) ) { @@ -355,7 +348,7 @@ bool CDODBot :: startGame () //else // engine->ClientCommand(m_pEdict,"joinclass %d",m_iDesiredClass); - /*switch ( m_iDesiredClass ) + switch ( m_iDesiredClass ) { case 1: case 2: @@ -398,8 +391,6 @@ void CDODBot :: killed ( edict_t *pVictim, char *weapon ) addVoiceCommand(DOD_VC_ENEMY_DOWN); //addVoiceCommand(DOD_VC_GOGOGO); } - - return; } void CDODBot :: died ( edict_t *pKiller, const char *pszWeapon ) @@ -429,31 +420,27 @@ void CDODBot :: died ( edict_t *pKiller, const char *pszWeapon ) m_pWantToProne->train(1.0f); } } - } // TO COMPLETE void CDODBot :: seeFriendlyDie ( edict_t *pDied, edict_t *pKiller, CWeapon *pWeapon ) { - static CWaypoint *pWpt; - extern ConVar rcbot_melee_only; - static CBotUtilities utils; utils.freeMemory(); if ( (pKiller != m_pEdict) && pKiller && !m_pEnemy && !hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && isEnemy(pKiller,false) ) { + static CWaypoint *pWpt; //bool bInvestigate = true; //bool bFollow = true; - Vector vecEnemy = CBotGlobals::entityOrigin(pKiller); - + if ( pWeapon ) { - DOD_Class pclass = (DOD_Class)CClassInterface::getPlayerClassDOD(pKiller); - + const DOD_Class pclass = static_cast(CClassInterface::getPlayerClassDOD(pKiller)); if ( (pclass == DOD_CLASS_SNIPER) && pWeapon->isZoomable() ) { + const Vector vecEnemy = CBotGlobals::entityOrigin(pKiller); if ( (m_LastHearVoiceCommand == DOD_VC_SNIPER) && m_pWeapons->hasWeapon(DOD_WEAPON_FRAG_US) && !m_pWeapons->hasWeapon(DOD_WEAPON_FRAG_GER) ) addVoiceCommand(DOD_VC_USE_GRENADE); else @@ -463,11 +450,18 @@ void CDODBot :: seeFriendlyDie ( edict_t *pDied, edict_t *pKiller, CWeapon *pWea //m_pNavigator->belief m_fCurrentDanger += 100.0f; // sniper danger //bInvestigate = false; + // Find Hide Spot - ADD_UTILITY_DATA_VECTOR(BOT_UTIL_SNIPE_POINT,!hasEnemy() && (m_iClass == DOD_CLASS_SNIPER) && getSniperRifle() && !getSniperRifle()->outOfAmmo(this),1.0f,(unsigned int)pKiller,vecEnemy); + // utility data is int32_t, casting as uintptr will crash on x64. -caxanga334 + ADD_UTILITY_DATA_VECTOR(BOT_UTIL_SNIPE_POINT, + !hasEnemy() && (m_iClass == DOD_CLASS_SNIPER) && getSniperRifle() && ! + getSniperRifle()->outOfAmmo(this), 1.0f, engine->IndexOfEdict(pKiller), + vecEnemy) + } else if ( (pclass == DOD_CLASS_MACHINEGUNNER) && pWeapon->isDeployable() ) { + const Vector vecEnemy = CBotGlobals::entityOrigin(pKiller); if ( (m_LastHearVoiceCommand == DOD_VC_MGAHEAD) && m_pWeapons->hasWeapon(DOD_WEAPON_FRAG_US) && !m_pWeapons->hasWeapon(DOD_WEAPON_FRAG_GER) ) addVoiceCommand(DOD_VC_USE_GRENADE); else @@ -479,7 +473,10 @@ void CDODBot :: seeFriendlyDie ( edict_t *pDied, edict_t *pKiller, CWeapon *pWea m_fCurrentDanger = MAX_BELIEF; // machine gun danger //bInvestigate = false; - ADD_UTILITY_DATA_VECTOR(BOT_UTIL_SNIPE_POINT,!hasEnemy() && (m_iClass == DOD_CLASS_SNIPER) && getSniperRifle() && !getSniperRifle()->outOfAmmo(this),1.0f,(unsigned int)pKiller,vecEnemy); + ADD_UTILITY_DATA_VECTOR(BOT_UTIL_SNIPE_POINT, + !hasEnemy() && (m_iClass == DOD_CLASS_SNIPER) && getSniperRifle() && !getSniperRifle()->outOfAmmo(this), + 1.0f, engine->IndexOfEdict(pKiller), vecEnemy) + //ADD_UTILITY_DATA_VECTOR(BOT_UTIL_MOVEUP_MG,!hasEnemy() && (m_iClass == DOD_CLASS_MACHINEGUNNER) && getMG() && !getMG()->outOfAmmo(this),1.0f,1,vecEnemy); } else @@ -488,26 +485,29 @@ void CDODBot :: seeFriendlyDie ( edict_t *pDied, edict_t *pKiller, CWeapon *pWea //ADD_UTILITY_DATA_VECTOR(BOT_UTIL_SNIPE_POINT,m_iClass == DOD_CLASS_SNIPER,1.0f,1,vecEnemy); } - if ( isVisible(pKiller) ) + if (isVisible(pKiller)) { - CWaypointVisibilityTable *pTable = CWaypoints::getVisiblity(); - int iCurrentWaypoint = m_pNavigator->getCurrentWaypointID(); - int iEnemyWaypoint = CWaypointLocations::NearestWaypoint(CBotGlobals::entityOrigin(pKiller),100.0f,-1,true,true); + const Vector vecEnemy = CBotGlobals::entityOrigin(pKiller); + + const CWaypointVisibilityTable* pTable = CWaypoints::getVisiblity(); + const int iCurrentWaypoint = m_pNavigator->getCurrentWaypointID(); + const int iEnemyWaypoint = CWaypointLocations::NearestWaypoint(CBotGlobals::entityOrigin(pKiller), 100.0f, -1, true, true); - if ( (iCurrentWaypoint!=-1) && (iEnemyWaypoint!=-1) && !pTable->GetVisibilityFromTo(iCurrentWaypoint,iEnemyWaypoint) ) + if ((iCurrentWaypoint != -1) && (iEnemyWaypoint != -1) && !pTable->GetVisibilityFromTo(iCurrentWaypoint, iEnemyWaypoint)) { - //bFollow = false; + int killerID = ENTINDEX(pKiller); // Convert edict_t* to an integer ID [APG]RoboCop[CL] - ADD_UTILITY_DATA_VECTOR(BOT_UTIL_COVER_POINT,m_pCurrentWeapon != NULL,0.8f,((unsigned int)pKiller),(vecEnemy)); + ADD_UTILITY_DATA_VECTOR(BOT_UTIL_COVER_POINT, m_pCurrentWeapon != nullptr, 0.8f, killerID, vecEnemy) } } + /*else if ( CBotGlobals::isPlayer(pDied) ) { // make a guess where the bullet came from IPlayerInfo *p = playerinfomanager->GetPlayerInfo(pDied); Vector v; CClassInterface::getVelocity(pDied,&v); - + if ( v.Length() > 0 ) v = v / v.Length(); @@ -560,10 +560,9 @@ void CDODBot :: seeFriendlyDie ( edict_t *pDied, edict_t *pKiller, CWeapon *pWea // move up MG if ( !rcbot_melee_only.GetBool() && pMachineGun && (m_iClass == DOD_CLASS_MACHINEGUNNER) && !pMachineGun->outOfAmmo(this) && pMachineGun->isDeployable() ) { - CWaypoint *pWaypoint; - if ( !m_pSchedules->hasSchedule(SCHED_DEPLOY_MACHINE_GUN) ) { + CWaypoint *pWaypoint; Vector vSearchForMachineGunPointOrigin = m_vListenPosition-getOrigin(); vSearchForMachineGunPointOrigin = vSearchForMachineGunPointOrigin/vSearchForMachineGunPointOrigin.Length(); @@ -576,13 +575,16 @@ void CDODBot :: seeFriendlyDie ( edict_t *pDied, edict_t *pKiller, CWeapon *pWea CWaypointLocations::REACHABLE_RANGE, -1, false,false, - false,NULL, + false, nullptr, false,m_iTeam, false,false, Vector(0,0,0), - CWaypointTypes::W_FL_MACHINEGUN))) != NULL) + CWaypointTypes::W_FL_MACHINEGUN))) != nullptr) { - ADD_UTILITY_WEAPON_DATA_VECTOR(BOT_UTIL_MOVEUP_MG,pMachineGun && !pMachineGun->outOfAmmo(this),1.0f,pMachineGun,CWaypoints::getWaypointIndex(pWaypoint),m_vListenPosition); + ADD_UTILITY_WEAPON_DATA_VECTOR(BOT_UTIL_MOVEUP_MG, + pMachineGun && !pMachineGun->outOfAmmo(this), 1.0f, + pMachineGun, CWaypoints::getWaypointIndex(pWaypoint), + m_vListenPosition) //m_pSchedules->add(new CDeployMachineGunSched(pMachineGun,pWaypoint,m_vListenPosition)); @@ -593,7 +595,10 @@ void CDODBot :: seeFriendlyDie ( edict_t *pDied, edict_t *pKiller, CWeapon *pWea if ( !m_pSchedules->isCurrentSchedule(SCHED_INVESTIGATE_NOISE) ) { - ADD_UTILITY_DATA_VECTOR(BOT_UTIL_INVESTIGATE_POINT,!m_pSchedules->hasSchedule(SCHED_DEPLOY_MACHINE_GUN)&&!m_pSchedules->hasSchedule(SCHED_SNIPE),0.5f,(unsigned int)pDied,m_vListenPosition); + ADD_UTILITY_DATA_VECTOR( + BOT_UTIL_INVESTIGATE_POINT, + !m_pSchedules->hasSchedule(SCHED_DEPLOY_MACHINE_GUN) && !m_pSchedules->hasSchedule(SCHED_SNIPE), 0.5f, + engine->IndexOfEdict(pDied), m_vListenPosition) //m_pSchedules->removeSchedule(SCHED_INVESTIGATE_NOISE); //m_pSchedules->addFront(new CBotInvestigateNoiseSched(CBotGlobals::entityOrigin(pDied),m_vListenPosition)); @@ -610,7 +615,7 @@ void CDODBot :: seeFriendlyDie ( edict_t *pDied, edict_t *pKiller, CWeapon *pWea utils.execute(); CBotUtility *next; - while ( (next = utils.nextBest()) != NULL ) + while ( (next = utils.nextBest()) != nullptr) { if ( executeAction(next) ) { @@ -645,11 +650,9 @@ void CDODBot :: seeFriendlyDie ( edict_t *pDied, edict_t *pKiller, CWeapon *pWea } } - void CDODBot :: seeFriendlyKill ( edict_t *pTeamMate, edict_t *pDied, CWeapon *pWeapon ) { - static CWaypoint *pWpt; - static CBotWeapon *pCurrentWeapon; + static CWaypoint *pWpt; //Unused? [APG]RoboCop[CL] if ( (pDied != m_pEdict) && pTeamMate && !hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && (CClassInterface::getTeam(pDied)!=m_iTeam) ) { @@ -657,7 +660,8 @@ void CDODBot :: seeFriendlyKill ( edict_t *pTeamMate, edict_t *pDied, CWeapon *p if ( pWeapon ) { - DOD_Class pclass = (DOD_Class)CClassInterface::getPlayerClassDOD(pTeamMate); + static CBotWeapon *pCurrentWeapon; + const DOD_Class pclass = static_cast(CClassInterface::getPlayerClassDOD(pTeamMate)); //DOD_Class pclassdead = (DOD_Class)CClassInterface::getPlayerClassDOD(pDied); pCurrentWeapon = getCurrentWeapon(); @@ -667,8 +671,7 @@ void CDODBot :: seeFriendlyKill ( edict_t *pTeamMate, edict_t *pDied, CWeapon *p else m_fCurrentDanger -= 20.0f; - if ( m_fCurrentDanger < 0 ) - m_fCurrentDanger = 0; + m_fCurrentDanger = std::max(m_fCurrentDanger, 0); if ( (pclass == DOD_CLASS_MACHINEGUNNER) && pWeapon->isDeployable() ) { @@ -681,7 +684,7 @@ void CDODBot :: seeFriendlyKill ( edict_t *pTeamMate, edict_t *pDied, CWeapon *p if ( pDied == m_pEnemy ) { - if ( ( getHealthPercent() < 0.2f ) && ( randomFloat(0.0,1.0) > 0.75f ) ) + if ( ( getHealthPercent() < 0.2f ) && ( randomFloat(0.0f,1.0f) > 0.75f ) ) addVoiceCommand(DOD_VC_NICE_SHOT); ga_nn_value inputs[3] = {distanceFrom(m_pEnemy)/1000.0f,getHealthPercent(),m_fCurrentDanger/MAX_BELIEF}; @@ -696,8 +699,8 @@ void CDODBot :: seeFriendlyKill ( edict_t *pTeamMate, edict_t *pDied, CWeapon *p if ( m_pLastEnemy == pDied ) { - m_pLastEnemy = NULL; - m_fLastSeeEnemy = 0; + m_pLastEnemy = nullptr; + m_fLastSeeEnemy = 0.0f; if ( inSquad() && isSquadLeader() ) { @@ -705,7 +708,6 @@ void CDODBot :: seeFriendlyKill ( edict_t *pTeamMate, edict_t *pDied, CWeapon *p //addVoiceCommand(DOD_VC_GOGOGO); } } - } } @@ -718,13 +720,11 @@ void CDODBot :: dropAmmo () // use weapon ID later, use getCurrentWeapon for now bool CDODBot :: wantToListenToPlayerAttack ( edict_t *pPlayer, int iWeaponID ) { - edict_t *pentWeapon = CClassInterface::getCurrentWeapon(pPlayer); + const edict_t *pentWeapon = CClassInterface::getCurrentWeapon(pPlayer); - if ( pentWeapon != NULL ) + if ( pentWeapon != nullptr) { - CWeapon *pWeapon = CWeapons::getWeapon(pentWeapon->GetClassName()); - - if ( pWeapon ) + if ( const CWeapon *pWeapon = CWeapons::getWeapon(pentWeapon->GetClassName()) ) { if ( pWeapon->isMelee() ) return false; @@ -734,7 +734,6 @@ bool CDODBot :: wantToListenToPlayerAttack ( edict_t *pPlayer, int iWeaponID ) // otherwise just random return true; } - } return false; @@ -756,116 +755,100 @@ void CDODBot :: spawnInit () m_fLastCaptureEvent = 0.0f; m_bHasBomb = false; - m_pNearestBreakable = NULL; + m_pNearestBreakable = nullptr; - m_pNearestPathBomb = NULL; + m_pNearestPathBomb = nullptr; - m_pNearestBomb = NULL; + m_pNearestBomb = nullptr; - memset(m_CheckSmoke,0,sizeof(smoke_t)*MAX_PLAYERS); + std::memset(m_CheckSmoke,0,sizeof(smoke_t)*RCBOT_MAXPLAYERS); while ( !m_nextVoicecmd.empty() ) m_nextVoicecmd.pop(); - m_fNextVoiceCommand = 0; + m_fNextVoiceCommand = 0.0f; - m_fDeployMachineGunTime = 0; - m_pNearestFlag = NULL; + m_fDeployMachineGunTime = 0.0f; + m_pNearestFlag = nullptr; - m_fShoutRocket = 0; - m_fShoutGrenade = 0; - m_pEnemyRocket = NULL; - m_pEnemyGrenade = NULL; + m_fShoutRocket = 0.0f; + m_fShoutGrenade = 0.0f; + m_pEnemyRocket = nullptr; + m_pEnemyGrenade = nullptr; - m_fShootTime = 0; - m_fProneTime = 0; - m_fZoomOrDeployTime = 0; + m_fShootTime = 0.0f; + m_fProneTime = 0.0f; + m_fZoomOrDeployTime = 0.0f; if ( m_pWeapons ) m_pWeapons->clearWeapons(); m_CurrentUtil = BOT_UTIL_MAX; // reset objects - m_flSprintTime = 0; - m_pCurrentWeapon = NULL; - m_fFixWeaponTime = 0; + m_flSprintTime = 0.0f; + m_pCurrentWeapon = nullptr; + m_fFixWeaponTime = 0.0f; m_LastHearVoiceCommand = DOD_VC_INVALID; } -bool CDODBot :: isEnemy ( edict_t *pEdict,bool bCheckWeapons ) +bool CDODBot::isEnemy(edict_t* pEdict, const bool bCheckWeapons) { - extern ConVar rcbot_notarget; - int entity_index = ENTINDEX(pEdict); +// const int entity_index = ENTINDEX(pEdict); //#ifdef _DEBUG // const char *pszClassname = pEdict->GetClassName(); //#endif - if ( entity_index == 0 ) + if (!pEdict) // Check for nullptr at the start + return false; + + const int entity_index = ENTINDEX(pEdict); + + if (entity_index == 0) return false; // worldspawn - if ( entity_index > gpGlobals->maxClients ) + if (entity_index > gpGlobals->maxClients) { - bool bRegisteredBreakable = CDODMod::isBreakableRegistered(pEdict, m_iTeam); - - if ( !CBotGlobals::isBreakableOpen(pEdict) && ((pEdict == m_pNearestBreakable) || bRegisteredBreakable) ) + const bool bRegisteredBreakable = CDODMod::isBreakableRegistered(pEdict, m_iTeam); + if (!CBotGlobals::isBreakableOpen(pEdict) && ((pEdict == m_pNearestBreakable) || bRegisteredBreakable)) { - - /*if ( strcmp("dod_ragdoll",pszClassname) == 0 ) + if (rcbot_shoot_breakables.GetBool()) { - // break; - return false; - }*/ - - if ( rcbot_shoot_breakables.GetBool() ) - { - if ( bRegisteredBreakable ) // this breakable is registered as explosive only + if (bRegisteredBreakable) // this breakable is registered as explosive only { return (distanceFrom(pEdict) > BLAST_RADIUS) && m_pWeapons->hasExplosives(); } - //else if ( (m_fLastSeeEnemy + 5.0f) > engine->Time() ) - else if ( DotProductFromOrigin(CBotGlobals::entityOrigin(pEdict)) > rcbot_shoot_breakable_cos.GetFloat() ) - return ((m_fLastSeeEnemyPlayer+3.0f) < engine->Time()) && (distanceFrom(pEdict) < rcbot_shoot_breakable_dist.GetFloat()) && (CClassInterface::getPlayerHealth(pEdict) > 0); + if (DotProductFromOrigin(CBotGlobals::entityOrigin(pEdict)) > rcbot_shoot_breakable_cos.GetFloat()) + return ((m_fLastSeeEnemyPlayer + 3.0f) < engine->Time()) && + (distanceFrom(pEdict) < rcbot_shoot_breakable_dist.GetFloat()) && + (CClassInterface::getPlayerHealth(pEdict) > 0); } } return false; } - - if ( !pEdict ) - return false; - - if ( !pEdict->GetUnknown() ) + if (!pEdict->GetUnknown()) return false; // left the server - - // if no target on - listen sever player is a non target - if ( rcbot_notarget.GetBool() && (entity_index == 1) ) + if (rcbot_notarget.GetBool() && (entity_index == 1)) return false; - - if ( pEdict == m_pEdict ) + if (pEdict == m_pEdict) return false; - - // not alive -- false - if ( !CBotGlobals::entityIsAlive(pEdict) ) + if (!CBotGlobals::entityIsAlive(pEdict)) return false; - - if ( CBotGlobals::getTeam(pEdict) == getTeam() ) + if (CBotGlobals::getTeam(pEdict) == getTeam()) { - extern ConVar rcbot_ffa; - - if ( rcbot_ffa.GetBool() == false ) + if (rcbot_ffa.GetBool() == false) return false; // if true continue down -- don't return } - - if ( bCheckWeapons && m_pNearestSmokeToEnemy ) + if (bCheckWeapons && m_pNearestSmokeToEnemy) { - if ( !isVisibleThroughSmoke(m_pNearestSmokeToEnemy,pEdict) ) + if (!isVisibleThroughSmoke(m_pNearestSmokeToEnemy, pEdict)) return false; } - return true; + return true; } void CDODBot :: handleWeapons () @@ -877,21 +860,18 @@ void CDODBot :: handleWeapons () hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && wantToShoot() && isVisible(m_pEnemy) && isEnemy(m_pEnemy,true) ) { - CBotWeapon *pWeapon; - - pWeapon = getCurrentWeapon(); + CBotWeapon* pWeapon = getCurrentWeapon(); if ( pWeapon && pWeapon->getWeaponEntity() && !rcbot_melee_only.GetBool() && pWeapon->isDeployable() && !pWeapon->outOfAmmo(this) && CClassInterface::isMachineGunDeployed(pWeapon->getWeaponEntity())) { - ; // keep current weapon on + // keep current weapon on } else pWeapon = getBestWeapon(m_pEnemy,true,true,rcbot_melee_only.GetBool(),!rcbot_melee_only.GetBool() && (((m_pEnemy == m_pNearestBreakable) || CDODMod::isBreakableRegistered(m_pEnemy,m_iTeam)))); - if ( m_bWantToChangeWeapon && (pWeapon != NULL) && (pWeapon != getCurrentWeapon()) && pWeapon->getWeaponIndex() ) + if ( m_bWantToChangeWeapon && (pWeapon != nullptr) && (pWeapon != getCurrentWeapon()) && pWeapon->getWeaponIndex() ) { - //selectWeaponSlot(pWeapon->getWeaponInfo()->getSlot()); selectBotWeapon(pWeapon); } @@ -899,18 +879,18 @@ void CDODBot :: handleWeapons () if ( !handleAttack ( pWeapon, m_pEnemy ) ) { - m_pEnemy = NULL; - m_pOldEnemy = NULL; + m_pEnemy = nullptr; + m_pOldEnemy = nullptr; wantToShoot(false); } } } -void CDODBot :: touchedWpt ( CWaypoint *pWaypoint, int iNextWaypoint, int iPrevWaypoint ) +void CDODBot :: touchedWpt ( CWaypoint *pWaypoint, const int iNextWaypoint, const int iPrevWaypoint ) { - static int wptindex; + static int wptindex; //Unused? [APG]RoboCop[CL] - CBot::touchedWpt(pWaypoint); + CBot::touchedWpt(pWaypoint, iNextWaypoint, iPrevWaypoint); wptindex = CWaypoints::getWaypointIndex(pWaypoint); @@ -921,51 +901,52 @@ void CDODBot :: touchedWpt ( CWaypoint *pWaypoint, int iNextWaypoint, int iPrevW } else if ( pWaypoint->hasFlag(CWaypointTypes::W_FL_BOMB_TO_OPEN) ) { - edict_t *pBombTarget = CDODMod::getBombTarget(pWaypoint); + edict_t* pBombTarget = CDODMod::getBombTarget(pWaypoint); - if ( CBotGlobals::entityIsValid(pBombTarget) ) + if (pBombTarget && CBotGlobals::entityIsValid(pBombTarget)) { - Vector vBombTarget = CBotGlobals::entityOrigin(pBombTarget); - int state = CClassInterface::getDODBombState(pBombTarget); + Vector vBombTarget = CBotGlobals::entityOrigin(pBombTarget); // `vBombTarget` Unused? [APG]RoboCop[CL] + const int state = CClassInterface::getDODBombState(pBombTarget); - if ( state != 0 ) + if (state != 0) m_pNearestPathBomb = pBombTarget; - // find bomb target for this waypoint and place bomb - if ( pBombTarget && (state != 0) && (CClassInterface::getDODBombTeam(pBombTarget) == m_iTeam) ) + // Additional checks and operations + if ((state != 0) && (CClassInterface::getDODBombTeam(pBombTarget) == m_iTeam)) { - // check if someone isn't bombing already - if ( (state == 2) || CDODMod::m_Flags.isTeamMatePlanting(m_pEdict,m_iTeam,pWaypoint->getOrigin()) ) - { - CBotSchedule *bombsched = new CBotSchedule(); - //todob - m_pSchedules->freeMemory(); + // check if someone isn't bombing already + // if ( (state == 2) || CDODMod::m_Flags.isTeamMatePlanting(m_pEdict,m_iTeam,pWaypoint->getOrigin()) ) + if ( (state == 2) || CDODFlags::isTeamMatePlanting(m_pEdict,m_iTeam,pWaypoint->getOrigin()) ) + { + CBotSchedule *bombsched = new CBotSchedule(); + //todob + m_pSchedules->freeMemory(); - bombsched->setID(SCHED_GOOD_HIDE_SPOT); + bombsched->setID(SCHED_GOOD_HIDE_SPOT); - bombsched->addTask(new CDODWaitForBombTask(pBombTarget,pWaypoint)); + bombsched->addTask(new CDODWaitForBombTask(pBombTarget,pWaypoint)); - m_pSchedules->add(bombsched); - } - else if ( m_bHasBomb ) // state must be 1 and no team mate planting - // plant - { - CBotSchedule *bombsched = new CBotSchedule(); - //todob - m_pSchedules->freeMemory(); + m_pSchedules->add(bombsched); + } + else if ( m_bHasBomb ) // state must be 1 and no team mate planting + // plant + { + CBotSchedule *bombsched = new CBotSchedule(); + //todob + m_pSchedules->freeMemory(); - bombsched->setID(SCHED_BOMB); + bombsched->setID(SCHED_BOMB); - bombsched->addTask(new CBotDODBomb(DOD_BOMB_PATH_PLANT,-1,pBombTarget,CBotGlobals::entityOrigin(pBombTarget),-1)); - bombsched->addTask(new CDODWaitForBombTask(pBombTarget,pWaypoint)); + bombsched->addTask(new CBotDODBomb(DOD_BOMB_PATH_PLANT,-1,pBombTarget,CBotGlobals::entityOrigin(pBombTarget),-1)); + bombsched->addTask(new CDODWaitForBombTask(pBombTarget,pWaypoint)); - m_pSchedules->add(bombsched); - } - else - { - updateCondition(CONDITION_NEED_BOMB); - updateCondition(CONDITION_CHANGED); - } + m_pSchedules->add(bombsched); + } + else + { + updateCondition(CONDITION_NEED_BOMB); + updateCondition(CONDITION_CHANGED); + } } } } @@ -976,28 +957,21 @@ void CDODBot :: touchedWpt ( CWaypoint *pWaypoint, int iNextWaypoint, int iPrevW // Check if current waypoint has a path which is invisible to my next waypoint if ( (iPrevWaypoint != -1) && (iNextWaypoint != -1) && (randomFloat(0,MAX_BELIEF) < m_pNavigator->getBelief(CWaypoints::getWaypointIndex(pWaypoint))) ) { - - int i; - int iPath; - CWaypointVisibilityTable *pTable = CWaypoints::getVisiblity(); - vector m_InvisPaths; - CWaypoint *pPath; - int iThisWaypoint = CWaypoints::getWaypointIndex(pWaypoint); + const CWaypointVisibilityTable *pTable = CWaypoints::getVisiblity(); + WaypointList m_InvisPaths; + const int iThisWaypoint = CWaypoints::getWaypointIndex(pWaypoint); //CWaypoint *pNextWaypoint = CWaypoints::getWaypoint(iNextWaypoint); - - extern IVDebugOverlay *debugoverlay; - - for ( i = 0; i < pWaypoint->numPaths(); i++ ) + for ( int i = 0; i < pWaypoint->numPaths(); i++ ) { - iPath = pWaypoint->getPath(i); + int iPath = pWaypoint->getPath(i); if ( iPath == iNextWaypoint ) continue; if ( iPath == iPrevWaypoint ) continue; - pPath = CWaypoints::getWaypoint(iPath); + CWaypoint* pPath = CWaypoints::getWaypoint(iPath); if ( pPath == pWaypoint ) continue; @@ -1007,7 +981,6 @@ void CDODBot :: touchedWpt ( CWaypoint *pWaypoint, int iNextWaypoint, int iPrevW /* static Vector vecLOS; static float flDot; - extern ConVar rcbot_dod_investigatepath_dp; Vector vForward = pNextWaypoint->getOrigin() - pWaypoint->getOrigin(); vForward = vForward/vForward.Length(); @@ -1022,26 +995,27 @@ void CDODBot :: touchedWpt ( CWaypoint *pWaypoint, int iNextWaypoint, int iPrevW if ( (pTable->GetVisibilityFromTo(iPrevWaypoint,iPath) == false) && (pTable->GetVisibilityFromTo(iThisWaypoint,iPath) == true) && (pTable->GetVisibilityFromTo(iNextWaypoint,iPath) == false) ) { - m_InvisPaths.push_back(iPath); + m_InvisPaths.emplace_back(iPath); #ifndef __linux__ if ( CClients::clientsDebugging(BOT_DEBUG_TASK) ) { + extern IVDebugOverlay *debugoverlay; debugoverlay->AddLineOverlay(CWaypoints::getWaypoint(iNextWaypoint)->getOrigin(),pPath->getOrigin(),255,120,120,false,7.0f); debugoverlay->AddLineOverlay(pWaypoint->getOrigin(),pPath->getOrigin(),255,255,255,false,7.0f); } #endif -// debugoverlay->AddTextOverlayRGB((pWaypoint->getOrigin()+pPath->getOrigin())/2,0,7.0f,255,255,255,255,"Dot: %0.3f",flDot); + //debugoverlay->AddTextOverlayRGB((pWaypoint->getOrigin()+pPath->getOrigin())/2,0,7.0f,255,255,255,255,"Dot: %0.3f",flDot); } } - if ( m_InvisPaths.size() > 0 ) + if (!m_InvisPaths.empty()) { - int iCheck = randomInt(0,m_InvisPaths.size()-1); + std::size_t iCheck = static_cast(randomInt(0, static_cast(m_InvisPaths.size() - 1))); - iCheck = m_InvisPaths[iCheck]; + iCheck = static_cast(m_InvisPaths[iCheck]); if ( !m_pSchedules->hasSchedule(SCHED_INVESTIGATE_HIDE) ) { @@ -1049,7 +1023,7 @@ void CDODBot :: touchedWpt ( CWaypoint *pWaypoint, int iNextWaypoint, int iPrevW CBotSchedule *pSched = new CBotSchedule(); pSched->setID(SCHED_INVESTIGATE_HIDE); - pSched->addTask(new CBotInvestigateHidePoint(iCheck,CWaypoints::getWaypointIndex(pWaypoint))); + pSched->addTask(new CBotInvestigateHidePoint(static_cast(iCheck), CWaypoints::getWaypointIndex(pWaypoint))); m_pSchedules->addFront(pSched); } @@ -1067,7 +1041,7 @@ void CDODBot :: touchedWpt ( CWaypoint *pWaypoint, int iNextWaypoint, int iPrevW void CDODBot :: changeClass () { - int iTeam = getTeam(); + const int iTeam = getTeam(); // change class //selectClass(); helpers->ClientCommand(m_pEdict,g_DODClassCmd[iTeam-2][m_iDesiredClass]); @@ -1075,57 +1049,84 @@ void CDODBot :: changeClass () m_fChangeClassTime = engine->Time() + randomFloat(bot_min_cc_time.GetFloat(),bot_max_cc_time.GetFloat()); } -void CDODBot :: chooseClass ( bool bIsChangingClass ) +void CDODBot :: chooseClass (const bool bIsChangingClass) { - float fClassFitness[6]; // 6 classes - float fTotalFitness = 0; - float fRandom; + const int _forcedClass = rcbot_force_class.GetInt(); + if (_forcedClass > 0 && _forcedClass < 10) + { + switch (_forcedClass) + { + case 1: + m_iDesiredClass = DOD_CLASS_RIFLEMAN; + break; + case 2: + m_iDesiredClass = DOD_CLASS_ASSAULT; + break; + case 3: + m_iDesiredClass = DOD_CLASS_SUPPORT; + break; + case 4: + m_iDesiredClass = DOD_CLASS_SNIPER; + break; + case 5: + m_iDesiredClass = DOD_CLASS_MACHINEGUNNER; + break; + case 6: + m_iDesiredClass = DOD_CLASS_ROCKET; + break; + } + } + else + { + std::array fClassFitness{ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; + float fTotalFitness = 0; - short int i = 0; - - int iTeam = getTeam(); - int iClass; - edict_t *pPlayer; + const int iTeam = getTeam(); - for ( i = 0; i < 6; i ++ ) - fClassFitness[i] = 1.0f; + //TODO: allow bots to choose less heavy classes [APG]RoboCop[CL] + fClassFitness[DOD_CLASS_RIFLEMAN] *= 1.5f; + fClassFitness[DOD_CLASS_ASSAULT] *= 1.2f; + fClassFitness[DOD_CLASS_SUPPORT] *= 1.0f; + fClassFitness[DOD_CLASS_SNIPER] *= 0.6f; + fClassFitness[DOD_CLASS_MACHINEGUNNER] *= 0.8f; + fClassFitness[DOD_CLASS_ROCKET] *= 0.5f; - if ( bIsChangingClass && ((m_iClass >= 0) && (m_iClass < 6)) ) - fClassFitness[m_iClass] = 0.1f; + if (bIsChangingClass && (m_iClass < 6)) + fClassFitness[m_iClass] = 0.1f; - for ( i = 1; i <= gpGlobals->maxClients; i ++ ) - { - pPlayer = INDEXENT(i); - - if ( CBotGlobals::entityIsValid(pPlayer) && (CClassInterface::getTeam(pPlayer) == iTeam)) + for (int i = 1; i <= gpGlobals->maxClients; i++) { - iClass = CClassInterface::getPlayerClassDOD(pPlayer); + edict_t* pPlayer = INDEXENT(i); - if ( (iClass >= 0) && (iClass < 6) ) - fClassFitness [iClass] *= 0.6f; - } - } + if (CBotGlobals::entityIsValid(pPlayer) && (CClassInterface::getTeam(pPlayer) == iTeam)) + { + const int iClass = CClassInterface::getPlayerClassDOD(pPlayer); - for ( int i = 0; i < 6; i ++ ) - fTotalFitness += fClassFitness[i]; + if ((iClass >= 0) && (iClass < 6)) + fClassFitness[iClass] *= 0.6f; + } + } - fRandom = randomFloat(0,fTotalFitness); + for (const float fClassFit : fClassFitness) + fTotalFitness += fClassFit; - fTotalFitness = 0; + const float fRandom = randomFloat(0, fTotalFitness); - m_iDesiredClass = 0; + fTotalFitness = 0.0f; - for ( int i = 0; i < 6; i ++ ) - { - fTotalFitness += fClassFitness[i]; + m_iDesiredClass = 0; - if ( fRandom <= fTotalFitness ) + for (int i = 0; i < 6; i++) { - m_iDesiredClass = i; - break; + fTotalFitness += fClassFitness[i]; + + if (fRandom <= fTotalFitness) + { + m_iDesiredClass = i; + break; + } } } - } void CDODBot :: prone () @@ -1136,6 +1137,7 @@ void CDODBot :: prone () m_fProneTime = engine->Time() + randomFloat(4.0f,8.0f); } } + void CDODBot :: unProne() { if ( m_bProne && (hasSomeConditions(CONDITION_RUN) || (m_fProneTime < engine->Time())) ) @@ -1158,7 +1160,7 @@ void CDODBot :: modThink () if ( bot_change_class.GetBool() && (m_fChangeClassTime < engine->Time()) ) { // get score for this class - float scoreValue = CDODMod::getScore(m_pEdict); + const float scoreValue = CDODMod::getScore(m_pEdict); // if I think I could do better if ( randomFloat(0.0f,1.0f) > (scoreValue / CDODMod::getHighestScore()) ) @@ -1174,7 +1176,7 @@ void CDODBot :: modThink () setMoveSpeed(fMaxSpeed); - m_iClass = (DOD_Class)CClassInterface::getPlayerClassDOD(m_pEdict); + m_iClass = static_cast(CClassInterface::getPlayerClassDOD(m_pEdict)); m_iTeam = getTeam(); m_bHasBomb = m_pWeapons->hasWeapon(DOD_WEAPON_BOMB); @@ -1195,7 +1197,7 @@ void CDODBot :: modThink () { if ( CClassInterface::isMachineGunDeployed(m_pCurrentWeapon) ) m_fDeployMachineGunTime = engine->Time(); - else if ( hasEnemy() & (m_StatsCanUse.stats.m_iEnemiesInRange>0) ) + else if (hasEnemy() && (m_StatsCanUse.stats.m_iEnemiesInRange>0)) { // Not deployed machine gun and within enemies -- run for cover // run for cover @@ -1211,8 +1213,6 @@ void CDODBot :: modThink () { m_fFov = 20.0f; } - - } @@ -1229,11 +1229,10 @@ void CDODBot :: modThink () // going prone if ( !isUnderWater() && !hasSomeConditions(CONDITION_RUN) && (m_fCurrentDanger >= 50.0f) ) { - extern ConVar rcbot_prone_enemy_only; // not sniper rifle or machine gun but can look down the sights if ( hasSomeConditions(CONDITION_COVERT) && m_pCurrentWeapon && pWeapon && (( pWeapon->getID() == DOD_WEAPON_K98 ) || (pWeapon->getID() == DOD_WEAPON_GARAND) )) { - bool bZoomed = false; + bool bZoomed; if ( pWeapon->getID() == DOD_WEAPON_K98 ) bZoomed = CClassInterface::isK98Zoomed(m_pCurrentWeapon); @@ -1248,11 +1247,11 @@ void CDODBot :: modThink () } // prone only if has enemy or last seen one a second ago // if rcbot_prone_enemy_only is true - if ( (hasSomeConditions(CONDITION_PRONE) || !rcbot_prone_enemy_only.GetBool() || ((m_pEnemy.get()!=NULL) || (m_fLastSeeEnemy + 5.0f > engine->Time()))) && (m_fCurrentDanger >= 80.0f) && !m_bProne && ( m_fProneTime < engine->Time() )) + if ( (hasSomeConditions(CONDITION_PRONE) || !rcbot_prone_enemy_only.GetBool() || ((m_pEnemy.get()!= nullptr) || (m_fLastSeeEnemy + 5.0f > engine->Time()))) && (m_fCurrentDanger >= 80.0f) && !m_bProne && ( m_fProneTime < engine->Time() )) { bool bProne = true; - if ( rcbot_prone_enemy_only.GetBool() && (m_pEnemy.get()!=NULL) ) + if ( rcbot_prone_enemy_only.GetBool() && (m_pEnemy.get()!= nullptr) ) { ga_nn_value inputs[3] = {distanceFrom(m_pEnemy)/1000.0f,getHealthPercent(),m_fCurrentDanger/MAX_BELIEF}; m_pWantToProne->input(inputs); @@ -1287,7 +1286,7 @@ void CDODBot :: modThink () } if ( (pWeapon && pWeapon->needToReload(this)) || - (m_fLastSeeEnemy && ((m_fLastSeeEnemy + 5.0)Time())) ) + (m_fLastSeeEnemy && ((m_fLastSeeEnemy + 5.0f)Time())) ) { m_fLastSeeEnemy = 0; m_pButtons->tap(IN_RELOAD); @@ -1337,7 +1336,7 @@ void CDODBot :: modThink () if ( m_pEnemyGrenade ) { - m_fShoutGrenade = m_fShoutGrenade/2 + 0.5f; + m_fShoutGrenade = m_fShoutGrenade / 2 + 0.5f; if ( m_fShoutGrenade > 0.95f ) { @@ -1372,10 +1371,7 @@ void CDODBot :: modThink () if ( !m_pSchedules->hasSchedule(SCHED_BOMB) && !m_pSchedules->hasSchedule(SCHED_GOOD_HIDE_SPOT) ) { - - CWaypoint *pWaypoint = CDODMod::getBombWaypoint(m_pNearestPathBomb); - - if ( pWaypoint ) + if ( CWaypoint *pWaypoint = CDODMod::getBombWaypoint(m_pNearestPathBomb) ) { CBotSchedule *runsched = new CBotSchedule(new CDODWaitForBombTask(m_pNearestPathBomb,pWaypoint)); runsched->setID(SCHED_GOOD_HIDE_SPOT); @@ -1392,7 +1388,7 @@ void CDODBot :: modThink () if ( m_pNearestBomb ) { - int iBombID = CDODMod::m_Flags.getBombID(m_pNearestBomb); + const int iBombID = CDODMod::m_Flags.getBombID(m_pNearestBomb); if ( CDODMod::m_Flags.canDefuseBomb(m_iTeam,iBombID) ) { @@ -1417,15 +1413,14 @@ void CDODBot :: modThink () CDODMod::m_Flags.isBombPlanted(iBombID) && CDODMod::m_Flags.isBombExplodeImminent(iBombID) ) { - Vector vNearestBomb = CBotGlobals::entityOrigin(m_pNearestBomb); + const Vector vNearestBomb = CBotGlobals::entityOrigin(m_pNearestBomb); if ( distanceFrom(vNearestBomb) < (BLAST_RADIUS*2) ) { - if ( !CDODMod::m_Flags.isTeamMatePlanting(m_pEdict,m_iTeam,vNearestBomb) ) + // if ( !CDODMod::m_Flags.isTeamMatePlanting(m_pEdict,m_iTeam,vNearestBomb) ) + if ( !CDODFlags::isTeamMatePlanting(m_pEdict,m_iTeam,vNearestBomb) ) { - CWaypoint *pWaypoint = CDODMod::getBombWaypoint(m_pNearestBomb); - - if ( pWaypoint ) + if ( CWaypoint *pWaypoint = CDODMod::getBombWaypoint(m_pNearestBomb) ) { CBotSchedule *runsched = new CBotSchedule(new CDODWaitForBombTask(m_pNearestBomb,pWaypoint)); runsched->setID(SCHED_GOOD_HIDE_SPOT); @@ -1446,7 +1441,7 @@ void CDODBot ::defending() // check to go prone or not } -void CDODBot ::voiceCommand ( int cmd ) +void CDODBot ::voiceCommand (const byte voiceCmd) { // find voice command extern eDODVoiceCommand_t g_DODVoiceCommands[DOD_VC_INVALID]; @@ -1454,18 +1449,18 @@ void CDODBot ::voiceCommand ( int cmd ) char scmd[64]; u_VOICECMD vcmd; - vcmd.voicecmd = cmd; + vcmd.voicecmd = voiceCmd; //not used? [APG]RoboCop[CL] - sprintf(scmd,"voice_%s",g_DODVoiceCommands[cmd].pcmd); + snprintf(scmd, sizeof(scmd), "voice_%s", g_DODVoiceCommands[voiceCmd].pcmd); helpers->ClientCommand(m_pEdict,scmd); } -void CDODBot ::signal ( const char *signal ) +void CDODBot ::signal ( const char *signal ) const { char scmd[64]; - sprintf(scmd,"signal_%s",signal); + snprintf(scmd, sizeof(scmd), "signal_%s", signal); helpers->ClientCommand(m_pEdict,scmd); } @@ -1480,16 +1475,14 @@ void CDODBot :: friendlyFire ( edict_t *pEdict ) #define IF_WANT_TO_LISTEN if ( isVisible(pPlayer) || (inSquad() && (m_pSquad->GetLeader()==pPlayer)) ) -void CDODBot :: hearVoiceCommand ( edict_t *pPlayer, byte cmd ) +void CDODBot::hearVoiceCommand(edict_t* pPlayer, byte voiceCmd) { - switch ( cmd ) + switch ( voiceCmd ) { case DOD_VC_CEASEFIRE: IF_WANT_TO_LISTEN { - extern ConVar *mp_friendlyfire; - - if ( mp_friendlyfire && mp_friendlyfire->GetBool() ) + if ( mp_friendlyfire.IsValid() && mp_friendlyfire.GetBool() ) { wantToShoot(false); // don't shoot this frame m_pButtons->letGo(IN_ATTACK); @@ -1528,7 +1521,8 @@ void CDODBot :: hearVoiceCommand ( edict_t *pPlayer, byte cmd ) CBotWeapon *pWeapon = getMG(); Vector vGoal = pWaypointAtFlag->getOrigin(); - snipetask = new CBotDODSnipe(pWeapon,pWaypoint->getOrigin(),pWaypoint->getAimYaw(),iFlagID!=-1,vGoal.z+48,pWaypoint->getFlags()); + snipetask = new CBotDODSnipe(pWeapon, pWaypoint->getOrigin(), pWaypoint->getAimYaw(), + iFlagID != -1, vGoal.z + 48, pWaypoint->getFlags()); removeCondition(CONDITION_PUSH); findpath->setCompleteInterrupt(CONDITION_PUSH); @@ -1545,7 +1539,7 @@ void CDODBot :: hearVoiceCommand ( edict_t *pPlayer, byte cmd ) break; } - else if ( randomFloat(0.0f,1.0f) < 0.8f ) + if ( randomFloat(0.0f,1.0f) < 0.8f ) addVoiceCommand(DOD_VC_NO); } else if ( randomFloat(0.0f,1.0f) < 0.6f ) @@ -1586,16 +1580,16 @@ void CDODBot :: hearVoiceCommand ( edict_t *pPlayer, byte cmd ) IF_WANT_TO_LISTEN { Vector vOrigin = CBotGlobals::entityOrigin(pPlayer); - QAngle angles; - CBotCmd usercmd; IPlayerInfo *p; Vector vForward,vUp,vRight; - Vector vCapSearchOrigin; p = playerinfomanager->GetPlayerInfo(pPlayer); if ( p ) { + Vector vCapSearchOrigin; + CBotCmd usercmd; + QAngle angles; usercmd = p->GetLastUserCommand(); angles = usercmd.viewangles; AngleVectors(angles,&vForward,&vRight,&vUp); @@ -1604,22 +1598,22 @@ void CDODBot :: hearVoiceCommand ( edict_t *pPlayer, byte cmd ) vCapSearchOrigin = vOrigin+(vForward*CWaypointLocations::BUCKET_SPACING*2); int iNearestPoint = CDODMod::m_Flags.findNearestObjective(vCapSearchOrigin); - if ( cmd == DOD_VC_GO_LEFT ) + if ( voiceCmd == DOD_VC_GO_LEFT ) vOrigin = vOrigin - (vRight*(CWaypointLocations::BUCKET_SPACING+1)) + (vForward*(CWaypointLocations::BUCKET_SPACING+1)); else vOrigin = vOrigin + (vRight*(CWaypointLocations::BUCKET_SPACING+1)) + (vForward*(CWaypointLocations::BUCKET_SPACING+1)); // find route waypoint to right of leader - CWaypoint *pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(vOrigin,768.0f,-1,false,false,false,NULL,false,0,false,false,Vector(0,0,0),CWaypointTypes::W_FL_ROUTE,NULL)); + CWaypoint *pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(vOrigin,768.0f,-1,false,false,false, nullptr,false,0,false,false,Vector(0,0,0),CWaypointTypes::W_FL_ROUTE, nullptr)); - if ( pWaypoint != NULL ) + if ( pWaypoint != nullptr) { if ( iNearestPoint != -1 ) { CWaypoint *pCap = CWaypoints::getWaypoint(CDODMod::m_Flags.getWaypointAtFlag(iNearestPoint)); - if ( pCap != NULL ) // go here after going through route + if ( pCap != nullptr) // go here after going through route m_pSchedules->addFront(new CBotGotoOriginSched(pCap->getOrigin())); } @@ -1628,11 +1622,11 @@ void CDODBot :: hearVoiceCommand ( edict_t *pPlayer, byte cmd ) else { // find capture waypoint to right of leader - CWaypoint *pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(vOrigin,768.0f,-1,false,false,false,NULL,false,0,false,false,Vector(0,0,0),CWaypointTypes::W_FL_CAPPOINT,NULL)); + CWaypoint *waypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(vOrigin,768.0f,-1,false,false,false, nullptr,false,0,false,false,Vector(0,0,0),CWaypointTypes::W_FL_CAPPOINT, nullptr)); - if ( pWaypoint != NULL ) + if ( waypoint != nullptr) { - m_pSchedules->addFront(new CBotGotoOriginSched(pWaypoint->getOrigin())); + m_pSchedules->addFront(new CBotGotoOriginSched(waypoint->getOrigin())); addVoiceCommand(DOD_VC_YES); } else @@ -1712,7 +1706,7 @@ void CDODBot :: hearVoiceCommand ( edict_t *pPlayer, byte cmd ) } break; case DOD_VC_NEED_AMMO: - // Todo: go to team mate and drop ammo + // TODO: go to team mate and drop ammo // should drop ammo to this person? if ( !m_bDroppedAmmoThisRound ) @@ -1731,10 +1725,8 @@ void CDODBot :: hearVoiceCommand ( edict_t *pPlayer, byte cmd ) pSched->setID(SCHED_DOD_DROPAMMO); if ( !isVisible(pPlayer) || (distanceFrom(pPlayer)>200.0f) ) - { - CWaypoint *pWpt = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(CBotGlobals::entityOrigin(pPlayer),200.0f,-1)); - - if ( pWpt ) + { + if ( CWaypoint *pWpt = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(CBotGlobals::entityOrigin(pPlayer),200.0f,-1)) ) { CFindPathTask *findpathtask = new CFindPathTask(pPlayer); @@ -1765,7 +1757,6 @@ void CDODBot :: hearVoiceCommand ( edict_t *pPlayer, byte cmd ) addVoiceCommand(DOD_VC_YES); } } - } else if ( randomFloat(0.0f,1.0f) > 0.75f ) { @@ -1779,7 +1770,6 @@ void CDODBot :: hearVoiceCommand ( edict_t *pPlayer, byte cmd ) break; case DOD_VC_STICK_TOGETHER: { - extern ConVar rcbot_bots_form_squads; IPlayerInfo *p = playerinfomanager->GetPlayerInfo(pPlayer); if ( inSquad() && (m_pSquad->GetLeader() == pPlayer) ) @@ -1801,8 +1791,6 @@ void CDODBot :: hearVoiceCommand ( edict_t *pPlayer, byte cmd ) fProb = 1.0f; else if ( rcbot_bots_form_squads.GetBool() ) { - extern ConVar rcbot_bot_squads_percent; - fProb = rcbot_bot_squads_percent.GetFloat()/100; /*if ( iClass == DOD_CLASS_SNIPER ) @@ -1879,8 +1867,6 @@ void CDODBot :: hearVoiceCommand ( edict_t *pPlayer, byte cmd ) case DOD_VC_NEED_BACKUP: if ( (!inSquad() ||( m_pSquad->GetLeader()==m_pEdict)) && m_pNearestFlag && isVisible(pPlayer) && !rcbot_nocapturing.GetBool() ) { - extern ConVar rcbot_bots_form_squads; - Vector vPoint = CBotGlobals::entityOrigin(m_pNearestFlag); Vector vPlayer = CBotGlobals::entityOrigin(pPlayer); @@ -1892,7 +1878,7 @@ void CDODBot :: hearVoiceCommand ( edict_t *pPlayer, byte cmd ) if ( CDODMod::isBombMap() ) { - CWaypoint *pWpt = CWaypoints::getWaypoint(CWaypointLocations::NearestBlastWaypoint(vPoint,vPlayer,1000.0,-1,true,false,true,false,m_iTeam,true)); + CWaypoint *pWpt = CWaypoints::getWaypoint(CWaypointLocations::NearestBlastWaypoint(vPoint,vPlayer,1000.0f,-1,true,false,true,false,m_iTeam,true)); attack->setID(SCHED_DEFENDPOINT); attack->addTask(new CFindPathTask(pWpt->getOrigin())); @@ -1929,14 +1915,14 @@ void CDODBot :: hearVoiceCommand ( edict_t *pPlayer, byte cmd ) break; } - m_LastHearVoiceCommand = (eDODVoiceCMD)cmd; + m_LastHearVoiceCommand = static_cast(voiceCmd); // don't say the same command for a second or two - if ( cmd < MAX_VOICE_CMDS ) - m_fLastVoiceCommand[cmd] = engine->Time() + randomFloat(1.0f,3.0f); + if ( voiceCmd < MAX_VOICE_CMDS ) + m_fLastVoiceCommand[voiceCmd] = engine->Time() + randomFloat(1.0f,3.0f); } -void CDODBot :: sayInPosition ( ) +void CDODBot :: sayInPosition () { signal("yes"); } @@ -1951,17 +1937,13 @@ void CDODBot :: sayMoveOut () updateCondition(CONDITION_CHANGED); } -bool CDODBot :: withinTeammate ( ) +bool CDODBot :: withinTeammate () const { // check if the bot is right next to a team mate (sometimes bots can't deploy if theyr are next to one already) - short int i; - edict_t *pPlayer; - IPlayerInfo *playerinfo; - - for ( i = 1; i <= gpGlobals->maxClients; i ++ ) + for ( int i = 1; i <= gpGlobals->maxClients; i ++ ) { - pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(i); // skip me if ( pPlayer == m_pEdict ) @@ -1969,9 +1951,7 @@ bool CDODBot :: withinTeammate ( ) if ( pPlayer && !pPlayer->IsFree() ) { - playerinfo = playerinfomanager->GetPlayerInfo(pPlayer); - - if ( playerinfo ) + if ( IPlayerInfo* playerinfo = playerinfomanager->GetPlayerInfo(pPlayer) ) { if ( playerinfo->IsConnected() && !playerinfo->IsDead() ) { @@ -2008,24 +1988,15 @@ void CDODBot :: listenForPlayers () // check for footsteps //m_fNextListenTime = engine->Time() + randomFloat(0.5f,2.0f); - edict_t *pListenNearest = NULL; - CClient *pClient; - edict_t *pPlayer; - IPlayerInfo *p; - float fFactor = 0; + edict_t *pListenNearest = nullptr; float fMaxFactor = 0; - //float fMinDist = 1024.0f; - float fDist; - float fVelocity; Vector vVelocity; - extern ConVar rcbot_listen_dist; - extern ConVar rcbot_footstep_speed; m_bListenPositionValid = false; - for ( register short int i = 1; i <= gpGlobals->maxClients; i ++ ) + for ( int i = 1; i <= gpGlobals->maxClients; i ++ ) { - pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(i); if ( pPlayer == m_pEdict ) continue; // don't listen to self @@ -2034,12 +2005,12 @@ void CDODBot :: listenForPlayers () continue; // get client network info - pClient = CClients::get(pPlayer); + const CClient* pClient = CClients::get(pPlayer); if ( !pClient->isUsed() ) continue; - p = playerinfomanager->GetPlayerInfo(pPlayer); + IPlayerInfo* p = playerinfomanager->GetPlayerInfo(pPlayer); // 05/07/09 fix crash bug if ( !p || !p->IsConnected() || p->IsDead() || p->IsObserver() || !p->IsPlayer() ) @@ -2048,18 +2019,18 @@ void CDODBot :: listenForPlayers () if ( isVisible(pPlayer) ) continue; // only listen to footsteps / don't care about people I can already see - fDist = distanceFrom(pPlayer); + const float fDist = distanceFrom(pPlayer); if ( fDist > rcbot_listen_dist.GetFloat() ) continue; - fFactor = (rcbot_listen_dist.GetFloat() - fDist); + float fFactor = (rcbot_listen_dist.GetFloat() - fDist); cmd = p->GetLastUserCommand(); CClassInterface::getVelocity(pPlayer,&vVelocity); - - fVelocity = vVelocity.Length(); + + const float fVelocity = vVelocity.Length(); if ( fVelocity > rcbot_footstep_speed.GetFloat() ) fFactor += vVelocity.Length(); @@ -2073,7 +2044,7 @@ void CDODBot :: listenForPlayers () } } - if ( pListenNearest != NULL ) + if ( pListenNearest != nullptr) { m_fListenFactor = fMaxFactor; listenToPlayer(pListenNearest,false,false); @@ -2087,52 +2058,78 @@ bool CDODBot :: executeAction ( CBotUtility *util ) int iBombType = 0; int id = -1; Vector vGoal; - edict_t *pBombTarget = NULL; + edict_t *pBombTarget = nullptr; switch ( util->getId() ) { case BOT_UTIL_INVESTIGATE_POINT: + { + edict_t* edict = engine->PEntityOfEntIndex(util->getIntData()); + + if (!edict || edict->IsFree() || edict->GetIServerEntity() == nullptr) + { + return false; + } + m_pSchedules->removeSchedule(SCHED_INVESTIGATE_NOISE); - m_pSchedules->addFront(new CBotInvestigateNoiseSched(CBotGlobals::entityOrigin((edict_t*)util->getIntData()),util->getVectorData())); + m_pSchedules->addFront(new CBotInvestigateNoiseSched(CBotGlobals::entityOrigin(edict), util->getVectorData())); return true; + } case BOT_UTIL_COVER_POINT: + { + edict_t* edict = engine->PEntityOfEntIndex(util->getIntData()); + + if (!edict || edict->IsFree() || edict->GetIServerEntity() == nullptr) + { + return false; + } + m_pSchedules->removeSchedule(SCHED_CROUCH_AND_HIDE); - m_pSchedules->addFront(new CCrouchHideSched((edict_t*)util->getIntData())); + m_pSchedules->addFront(new CCrouchHideSched(edict)); return true; + } case BOT_UTIL_SNIPE_POINT: // find sniper point facing the enemy { - edict_t *pEnemy = (edict_t*)util->getIntData(); + + edict_t* pEnemy = engine->PEntityOfEntIndex(util->getIntData()); + + if (!pEnemy || pEnemy->IsFree() || pEnemy->GetIServerEntity() == nullptr) + { + return false; + } + Vector vEnemyOrigin = CBotGlobals::entityOrigin(pEnemy); - int iEnemyWpt = CWaypointLocations::NearestWaypoint(CBotGlobals::entityOrigin(pEnemy),200.0f,-1,true,true,false,NULL,false,0,false); + int iEnemyWpt = CWaypointLocations::NearestWaypoint(CBotGlobals::entityOrigin(pEnemy), 200.0f, -1, true, + true, false, nullptr, false, 0, false); - vector pWaypointList; + WaypointList waypoints; Vector vOrigin = getOrigin(); // find all sniper points - CWaypointLocations::GetAllInArea(vOrigin,&pWaypointList,iEnemyWpt); + CWaypointLocations::GetAllInArea(vOrigin,&waypoints,iEnemyWpt); - unsigned int size = pWaypointList.size(); + std::size_t size = waypoints.size(); float fDist; float fNearest = 1024.0f; - CWaypoint *pNearest = NULL; + CWaypoint *pNearest = nullptr; - for ( unsigned short i = 0; i < size; i ++ ) + for (std::size_t i = 0; i < size; i++) { - CWaypoint *pWpt = CWaypoints::getWaypoint(pWaypointList[i]); + CWaypoint *pWpt = CWaypoints::getWaypoint(waypoints[i]); if ( pWpt->hasFlag(CWaypointTypes::W_FL_SNIPER) ) { // Check the yaw QAngle eyes; - float iYaw = pWpt->getAimYaw(); + float fYaw = pWpt->getAimYaw(); eyes.x = 0; - eyes.y = iYaw; + eyes.y = fYaw; eyes.z = 0; Vector vecLOS; @@ -2148,7 +2145,7 @@ bool CDODBot :: executeAction ( CBotUtility *util ) flDot = DotProduct (vecLOS , vForward ); - if ( flDot > 0 ) // 90 degrees + if ( flDot > 0.0f ) // 90 degrees { fDist = pWpt->distanceFrom(vOrigin); @@ -2161,7 +2158,7 @@ bool CDODBot :: executeAction ( CBotUtility *util ) } } - if ( pNearest != NULL ) + if (pNearest != nullptr) { m_pSchedules->freeMemory(); @@ -2188,8 +2185,8 @@ bool CDODBot :: executeAction ( CBotUtility *util ) // find a nearby friendly int i = 0; edict_t *pEdict; - edict_t *pNearby = NULL; - float fMaxDistance = 500; + edict_t *pNearby = nullptr; + float fMaxDistance = 500.0f; float fDistance; for ( i = 1; i <= CBotGlobals::maxClients(); i ++ ) @@ -2227,30 +2224,30 @@ bool CDODBot :: executeAction ( CBotUtility *util ) } case BOT_UTIL_DEFEND_NEAREST_POINT: { - Vector vGoal; - int id = util->getIntData(); + Vector v_goal; + int i_area = util->getIntData(); bool defend_wpt = true; - vGoal = util->getVectorData(); + v_goal = util->getVectorData(); if ( inSquad() && !isSquadLeader() ) { - if ( (m_pSquad->GetFormationVector(m_pEdict)-vGoal).Length() > 400.0f ) + if ( (m_pSquad->GetFormationVector(m_pEdict)-v_goal).Length() > 400.0f ) return false; } CWaypoint *pWaypoint; - pWaypoint = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_DEFEND,m_iTeam,id,true,this); + pWaypoint = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_DEFEND,m_iTeam,i_area,true,this); - if ( pWaypoint == NULL ) + if ( pWaypoint == nullptr) { defend_wpt = false; - if ( distanceFrom(vGoal) > 1024 ) // outside waypoint bucket of goal - pWaypoint = CWaypoints::getPinchPointFromWaypoint(vGoal,vGoal); + if ( distanceFrom(v_goal) > 1024 ) // outside waypoint bucket of goal + pWaypoint = CWaypoints::getPinchPointFromWaypoint(v_goal,v_goal); else - pWaypoint = CWaypoints::getPinchPointFromWaypoint(getOrigin(),vGoal); + pWaypoint = CWaypoints::getPinchPointFromWaypoint(getOrigin(),v_goal); } if ( pWaypoint ) @@ -2260,7 +2257,7 @@ bool CDODBot :: executeAction ( CBotUtility *util ) CBotSchedule *defend = new CBotSchedule(); CBotTask *findpath = new CFindPathTask(pWaypoint->getOrigin()); - CBotTask *deftask = new CBotDefendTask(pWaypoint->getOrigin(),randomFloat(7.5f,12.5f),0,true,vGoal,defend_wpt ? LOOK_SNIPE : LOOK_AROUND,pWaypoint->getFlags()); + CBotTask *deftask = new CBotDefendTask(pWaypoint->getOrigin(),randomFloat(7.5f,12.5f),0,true,v_goal,defend_wpt ? LOOK_SNIPE : LOOK_AROUND,pWaypoint->getFlags()); removeCondition(CONDITION_PUSH); findpath->setCompleteInterrupt(CONDITION_PUSH); @@ -2279,7 +2276,7 @@ bool CDODBot :: executeAction ( CBotUtility *util ) break; case BOT_UTIL_ATTACK_NEAREST_POINT: { - Vector vGoal; + Vector v_goal; int iFlagID; int iWaypointGoal; @@ -2287,14 +2284,14 @@ bool CDODBot :: executeAction ( CBotUtility *util ) iFlagID = util->getIntData(); iWaypointGoal = CDODMod::m_Flags.getWaypointAtFlag(iFlagID); - vGoal = util->getVectorData(); + v_goal = util->getVectorData(); if ( iWaypointGoal == -1 ) return false; if ( inSquad() && !isSquadLeader() ) { - if ( (m_pSquad->GetFormationVector(m_pEdict)-vGoal).Length() > 400.0f ) + if ( (m_pSquad->GetFormationVector(m_pEdict)-v_goal).Length() > 400.0f ) return false; } @@ -2303,7 +2300,7 @@ bool CDODBot :: executeAction ( CBotUtility *util ) attack->setID(SCHED_ATTACKPOINT); attack->addTask(new CFindPathTask(iWaypointGoal)); - attack->addTask(new CBotDODAttackPoint(iFlagID,vGoal,150.0f)); + attack->addTask(new CBotDODAttackPoint(iFlagID,v_goal,150.0f)); // add defend task m_pSchedules->add(attack); removeCondition(CONDITION_PUSH); @@ -2315,20 +2312,20 @@ bool CDODBot :: executeAction ( CBotUtility *util ) return true; } - break; + //break; case BOT_UTIL_SNIPE: // find snipe or machine gun waypoint { int iFlagID = -1; int iWaypointType = 0; - Vector vGoal; - CWaypoint *pWaypoint = NULL; + Vector v_goal; + CWaypoint *pWaypoint = nullptr; if ( hasMG() ) iWaypointType = CWaypointTypes::W_FL_MACHINEGUN; else iWaypointType = CWaypointTypes::W_FL_SNIPER; - if ( inSquad() && !isSquadLeader() ) + if ( inSquad() && !isSquadLeader() && m_pSquad->IsSquadLeaderValid() ) { edict_t *pSquadLeader = m_pSquad->GetLeader(); Vector vSquadLeaderOrigin = CBotGlobals::entityOrigin(pSquadLeader); @@ -2337,7 +2334,9 @@ bool CDODBot :: executeAction ( CBotUtility *util ) if ( iFlagID == -1 ) { - pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(m_pSquad->GetFormationVector(m_pEdict),250.0f,-1,false,false,true,NULL,false,m_iTeam,false,false,Vector(0,0,0),iWaypointType)); + pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint( + m_pSquad->GetFormationVector(m_pEdict), 250.0f, -1, false, false, true, nullptr, false, m_iTeam, + false, false, Vector(0, 0, 0), iWaypointType)); } else pWaypoint = CWaypoints::randomWaypointGoal(iWaypointType,m_iTeam,iFlagID,true,this); @@ -2348,7 +2347,7 @@ bool CDODBot :: executeAction ( CBotUtility *util ) { if ( !CDODMod::isBombMap() || !CDODMod::isCommunalBombPoint() ) { - if ( CDODMod::m_Flags.getRandomEnemyControlledFlag(this,&vGoal,getTeam(),&iFlagID) ) + if ( CDODMod::m_Flags.getRandomEnemyControlledFlag(this,&v_goal,getTeam(),&iFlagID) ) { pWaypoint = CWaypoints::randomWaypointGoal(iWaypointType,m_iTeam,iFlagID,true,this); } @@ -2357,7 +2356,7 @@ bool CDODBot :: executeAction ( CBotUtility *util ) { // attack the bomb point -- less chance if owned many bomb points already if ( randomFloat(0.0f,1.0f) < - ((float)CDODMod::m_Flags.getNumPlantableBombs(m_iTeam)/ + (static_cast(CDODMod::m_Flags.getNumPlantableBombs(m_iTeam))/ CDODMod::m_Flags.getNumBombsOnMap(m_iTeam)) ) { pWaypoint = CWaypoints::randomWaypointGoal(iWaypointType,m_iTeam,CDODMod::getBombPointArea(m_iTeam),true,this); @@ -2365,7 +2364,7 @@ bool CDODBot :: executeAction ( CBotUtility *util ) else { // attack a point - if ( CDODMod::m_Flags.getRandomEnemyControlledFlag(this,&vGoal,getTeam(),&iFlagID) ) + if ( CDODMod::m_Flags.getRandomEnemyControlledFlag(this,&v_goal,getTeam(),&iFlagID) ) { if ( hasMG() ) pWaypoint = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_MACHINEGUN,m_iTeam,iFlagID,true,this); @@ -2380,13 +2379,13 @@ bool CDODBot :: executeAction ( CBotUtility *util ) } else // defend { - if ( CDODMod::m_Flags.getRandomTeamControlledFlag(this,&vGoal,getTeam(),&iFlagID) ) + if ( CDODMod::m_Flags.getRandomTeamControlledFlag(this,&v_goal,getTeam(),&iFlagID) ) { pWaypoint = CWaypoints::randomWaypointGoal(iWaypointType,m_iTeam,iFlagID,true,this); } } - if ( pWaypoint == NULL ) + if ( pWaypoint == nullptr) { pWaypoint = CWaypoints::randomWaypointGoal(iWaypointType,m_iTeam); } @@ -2401,16 +2400,14 @@ bool CDODBot :: executeAction ( CBotUtility *util ) // find Z for goal if no flag id if ( (iFlagID == -1) && (pWaypoint->getArea() > 0) && CDODMod::isBombMap() && CDODMod::isCommunalBombPoint() ) { - CWaypoint *pBombs = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_BOMBS_HERE,m_iTeam,pWaypoint->getArea(),true); - - if ( pBombs ) + if ( CWaypoint *pBombs = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_BOMBS_HERE,m_iTeam,pWaypoint->getArea(),true) ) { iFlagID = pWaypoint->getArea(); - vGoal = pBombs->getOrigin(); + v_goal = pBombs->getOrigin(); } } - snipetask = new CBotDODSnipe(util->getWeaponChoice(),pWaypoint->getOrigin(),pWaypoint->getAimYaw(),iFlagID!=-1,vGoal.z+48,pWaypoint->getFlags()); + snipetask = new CBotDODSnipe(util->getWeaponChoice(),pWaypoint->getOrigin(),pWaypoint->getAimYaw(),iFlagID!=-1,v_goal.z+48,pWaypoint->getFlags()); removeCondition(CONDITION_PUSH); findpath->setCompleteInterrupt(CONDITION_PUSH); @@ -2428,27 +2425,29 @@ bool CDODBot :: executeAction ( CBotUtility *util ) break; case BOT_UTIL_DEFEND_NEAREST_BOMB: vGoal = util->getVectorData(); + [[fallthrough]]; // tell the compiler that fallthrough is the intended behavior here. (C++17 feature) -caxanga334 case BOT_UTIL_DEFEND_BOMB: // fall through -- no break if ( util->getId() == BOT_UTIL_DEFEND_BOMB ) CDODMod::m_Flags.getRandomBombToDefend(this,&vGoal,m_iTeam,&pBombTarget,&id); + [[fallthrough]]; case BOT_UTIL_DEFEND_POINT: { - int id = -1; - bool defend_wpt = true; + int i_area = -1; if ( util->getId() == BOT_UTIL_DEFEND_POINT ) { - if ( !CDODMod::m_Flags.getRandomTeamControlledFlag(this,&vGoal,getTeam(),&id) ) + if ( !CDODMod::m_Flags.getRandomTeamControlledFlag(this,&vGoal,getTeam(),&i_area) ) return false; } CWaypoint *pWaypoint; - pWaypoint = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_DEFEND,m_iTeam,id,true,this); + pWaypoint = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_DEFEND,m_iTeam,i_area,true,this); - if ( pWaypoint == NULL ) - { - defend_wpt = false; + if ( pWaypoint == nullptr) + { + bool defend_wpt = true; //Unused? [APG]RoboCop[CL] + //defend_wpt = false; if ( distanceFrom(vGoal) > 1024 ) // outside waypoint bucket of goal pWaypoint = CWaypoints::getPinchPointFromWaypoint(vGoal,vGoal); @@ -2483,6 +2482,7 @@ bool CDODBot :: executeAction ( CBotUtility *util ) if ( CDODMod::m_Flags.isTeamMateDefusing(m_pEdict,m_iTeam,util->getIntData()) ) return false; // teammate doing the job already + break; case BOT_UTIL_PLANT_NEAREST_BOMB: id = util->getIntData(); @@ -2494,11 +2494,12 @@ bool CDODBot :: executeAction ( CBotUtility *util ) if ( CDODMod::m_Flags.isTeamMatePlanting(m_pEdict,m_iTeam,id) ) return false; // teammate doing the job already + break; case BOT_UTIL_DEFUSE_BOMB: if ( util->getId() == BOT_UTIL_DEFUSE_BOMB ) { - if ( !CDODMod::m_Flags.getRandomBombToDefuse(&vGoal,m_iTeam,&pBombTarget,&id) ) + if ( !CDODMod::m_Flags.getRandomBombToDefuse(vGoal,m_iTeam,pBombTarget,&id) ) return false; if ( CDODMod::m_Flags.isTeamMateDefusing(m_pEdict,m_iTeam,id) ) @@ -2506,11 +2507,13 @@ bool CDODBot :: executeAction ( CBotUtility *util ) iBombType = DOD_BOMB_DEFUSE; } + break; + case BOT_UTIL_PLANT_BOMB: { if ( util->getId() == BOT_UTIL_PLANT_BOMB ) { - if ( !CDODMod::m_Flags.getRandomBombToPlant(this,&vGoal,m_iTeam,&pBombTarget,&id) ) + if ( !CDODMod::m_Flags.getRandomBombToPlant(this,vGoal,m_iTeam,pBombTarget,&id) ) return false; if ( CDODMod::m_Flags.isTeamMatePlanting(m_pEdict,m_iTeam,id) ) @@ -2519,7 +2522,6 @@ bool CDODBot :: executeAction ( CBotUtility *util ) iBombType = DOD_BOMB_PLANT; } - int iWptGoal = CDODMod::m_Flags.getWaypointAtFlag(id); if ( iWptGoal == -1 ) @@ -2554,13 +2556,13 @@ bool CDODBot :: executeAction ( CBotUtility *util ) return true; } - break; + //break; case BOT_UTIL_PICKUP_BOMB: { CWaypoint *pWaypoint; Vector vOrigin = getOrigin(); - pWaypoint = CWaypoints::getWaypoint(CWaypoints::nearestWaypointGoal(CWaypointTypes::W_FL_BOMBS_HERE,vOrigin,8192.0,m_iTeam)); + pWaypoint = CWaypoints::getWaypoint(CWaypoints::nearestWaypointGoal(CWaypointTypes::W_FL_BOMBS_HERE,vOrigin,8192.0f,m_iTeam)); if ( pWaypoint ) { @@ -2570,7 +2572,7 @@ bool CDODBot :: executeAction ( CBotUtility *util ) if ( !pWaypointPinch ) { - if ( distanceFrom(pWaypoint->getOrigin()) > 1024.0 ) + if ( distanceFrom(pWaypoint->getOrigin()) > 1024.0f ) pWaypointPinch = CWaypoints::getPinchPointFromWaypoint(pWaypoint->getOrigin(),pWaypoint->getOrigin()); else pWaypointPinch = CWaypoints::getPinchPointFromWaypoint(getOrigin(),pWaypoint->getOrigin()); @@ -2614,9 +2616,9 @@ bool CDODBot :: executeAction ( CBotUtility *util ) removeCondition(CONDITION_SEE_CUR_ENEMY); pFindPath->setCompleteInterrupt(CONDITION_SEE_CUR_ENEMY); - if ( !CClassInterface::getVelocity(m_pLastEnemy,&vVelocity) ) + if (!CClassInterface::getVelocity(m_pLastEnemy, &vVelocity)) { - if ( pClient ) + //if (pClient != nullptr) vVelocity = pClient->getVelocity(); } @@ -2635,15 +2637,14 @@ bool CDODBot :: executeAction ( CBotUtility *util ) case BOT_UTIL_THROW_GRENADE: { // find hide waypoint - CWaypoint *pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::GetCoverWaypoint(getOrigin(),m_vLastSeeEnemy,NULL)); - if ( pWaypoint ) + if ( CWaypoint *pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::GetCoverWaypoint(getOrigin(),m_vLastSeeEnemy, nullptr)) ) { CBotWeapon *pWeapon = util->getWeaponChoice(); CBotSchedule *pSched = new CBotSchedule(); CFindPathTask *pathtask = new CFindPathTask(pWaypoint->getOrigin()); - pSched->addTask(new CThrowGrenadeTask(pWeapon,getAmmo(pWeapon->getWeaponInfo()->getAmmoIndex1()),m_vLastSeeEnemyBlastWaypoint)); // first - throw + pSched->addTask(new CThrowGrenadeTask(pWeapon, getAmmo(static_cast(pWeapon->getWeaponInfo()->getAmmoIndex1())), m_vLastSeeEnemyBlastWaypoint)); // first - throw pSched->addTask(pathtask); // 2nd -- hide pathtask->setNoInterruptions(); @@ -2658,16 +2659,14 @@ bool CDODBot :: executeAction ( CBotUtility *util ) return true; } - break; + //break; case BOT_UTIL_ATTACK_POINT: { - Vector vGoal; + Vector v_goal; int iFlagID; - if ( CDODMod::m_Flags.getRandomEnemyControlledFlag(this,&vGoal,getTeam(),&iFlagID) ) + if ( CDODMod::m_Flags.getRandomEnemyControlledFlag(this,&v_goal,getTeam(),&iFlagID) ) { - CWaypoint *pWaypoint; - int iGoalWaypoint = CDODMod::m_Flags.getWaypointAtFlag(iFlagID); // no waypoint... @@ -2676,7 +2675,7 @@ bool CDODBot :: executeAction ( CBotUtility *util ) CBotSchedule *attack = new CBotSchedule(); - CWaypoint *pRoute = NULL; + CWaypoint *pRoute = nullptr; if ( (m_fUseRouteTime < engine->Time()) ) { @@ -2693,12 +2692,13 @@ bool CDODBot :: executeAction ( CBotUtility *util ) attack->setID(SCHED_ATTACKPOINT); - if ( (pRoute == NULL) && (randomFloat(0.0f,MAX_BELIEF) < m_pNavigator->getBelief(iGoalWaypoint)) ) + if ( (pRoute == nullptr) && (randomFloat(0.0f,MAX_BELIEF) < m_pNavigator->getBelief(iGoalWaypoint)) ) { - if ( distanceFrom(vGoal) > 1024 ) // outside waypoint bucket of goal - pWaypoint = CWaypoints::getPinchPointFromWaypoint(vGoal,vGoal); + CWaypoint *pWaypoint; + if ( distanceFrom(v_goal) > 1024 ) // outside waypoint bucket of goal + pWaypoint = CWaypoints::getPinchPointFromWaypoint(v_goal,v_goal); else - pWaypoint = CWaypoints::getPinchPointFromWaypoint(getOrigin(),vGoal); + pWaypoint = CWaypoints::getPinchPointFromWaypoint(getOrigin(),v_goal); if ( pWaypoint ) { @@ -2708,7 +2708,7 @@ bool CDODBot :: executeAction ( CBotUtility *util ) } attack->addTask(new CFindPathTask(iGoalWaypoint)); - attack->addTask(new CBotDODAttackPoint(iFlagID,vGoal,150.0f)); + attack->addTask(new CBotDODAttackPoint(iFlagID,v_goal,150.0f)); // add defend task m_pSchedules->add(attack); @@ -2735,24 +2735,23 @@ bool CDODBot :: executeAction ( CBotUtility *util ) return true; } - break; + //break; case BOT_UTIL_FOLLOW_SQUAD_LEADER: { - Vector pos = m_pSquad->GetFormationVector(m_pEdict); + Vector pos = m_pSquad->GetFormationVector(m_pEdict); // `pos` Unused? [APG]RoboCop[CL] m_pSchedules->add(new CBotSchedule(new CBotFollowSquadLeader(m_pSquad))); return true; } - break; + //break; case BOT_UTIL_ROAM: { // roam - CWaypoint *pWaypoint = CWaypoints::getWaypoint(CWaypoints::randomFlaggedWaypoint(getTeam())); - if ( pWaypoint ) + if ( CWaypoint *pWaypoint = CWaypoints::getWaypoint(CWaypoints::randomFlaggedWaypoint(getTeam())) ) { - if ( inSquad() && !isSquadLeader() ) + if ( inSquad() && !isSquadLeader() && m_pSquad->IsSquadLeaderValid() ) { if ( pWaypoint->distanceFrom(m_pSquad->GetFormationVector(m_pEdict)) > CWaypointLocations::REACHABLE_RANGE ) return false; @@ -2770,7 +2769,7 @@ bool CDODBot :: executeAction ( CBotUtility *util ) return false; } -void CDODBot :: reachedCoverSpot (int flags) +void CDODBot :: reachedCoverSpot (const int flags) { // reached cover // dont need to run there any more @@ -2785,24 +2784,25 @@ void CDODBot :: reachedCoverSpot (int flags) m_pButtons->tap(IN_RELOAD); } - //m_fFixWeaponTime = engine->Time() + 1.0f; //} CBotWeapon *pWeapon = getMG(); - if ( pWeapon != NULL ) + if ( pWeapon != nullptr) { bool bDontCrouchAndHide = false; - if ( pWeapon && pWeapon->isDeployable() && !pWeapon->outOfAmmo(this) ) + assert(pWeapon != nullptr); + + if ( pWeapon->isDeployable() && !pWeapon->outOfAmmo(this) ) { if ( flags & CWaypointTypes::W_FL_MACHINEGUN ) { - CWaypoint *pWpt = CWaypoints::getWaypoint(m_pNavigator->getCurrentGoalID()); + const CWaypoint *pWpt = CWaypoints::getWaypoint(m_pNavigator->getCurrentGoalID()); if ( pWpt && (pWpt->getFlags() == flags) ) { - m_pSchedules->addFront(new CBotSchedule(new CBotDODSnipe(pWeapon,getOrigin(),pWpt->getAimYaw(),false,false,flags))); + m_pSchedules->addFront(new CBotSchedule(new CBotDODSnipe(pWeapon, getOrigin(), pWpt->getAimYaw(), false, 0.0f, flags))); removeCondition(CONDITION_PRONE); bDontCrouchAndHide = true; } @@ -2815,7 +2815,7 @@ void CDODBot :: reachedCoverSpot (int flags) m_fCurrentDanger = MAX_BELIEF; } - if ( !bDontCrouchAndHide && (m_pLastCoverFrom.get() != NULL) ) + if ( !bDontCrouchAndHide && (m_pLastCoverFrom.get() != nullptr) ) { if ( CBotGlobals::entityIsAlive(m_pLastCoverFrom) ) { @@ -2833,9 +2833,9 @@ bool CDODBot:: checkStuck () { if ( CBot::checkStuck() ) { - CBotWeapon *pWeapon = getCurrentWeapon(); + const CBotWeapon *pWeapon = getCurrentWeapon(); - if ( pWeapon && (pWeapon->getWeaponEntity()!=NULL) ) + if ( pWeapon && (pWeapon->getWeaponEntity()!= nullptr) ) { if ( pWeapon->isZoomable() && CClassInterface::isSniperWeaponZoomed(pWeapon->getWeaponEntity()) ) secondaryAttack(); @@ -2848,11 +2848,9 @@ bool CDODBot:: checkStuck () } } - edict_t *pGroundEnt = CClassInterface::getGroundEntity(m_pEdict); - - if ( pGroundEnt ) // stuck on furniture? + if ( const edict_t *pGroundEnt = CClassInterface::getGroundEntity(m_pEdict) ) // stuck on furniture? { - if ( strncmp(pGroundEnt->GetClassName(),"prop_physics",12) ) + if ( std::strncmp(pGroundEnt->GetClassName(),"prop_physics",12) != 0 ) { // Duck if ( randomFloat(0.0f,1.0f) < 0.9f ) @@ -2868,17 +2866,14 @@ bool CDODBot :: handleAttack ( CBotWeapon *pWeapon, edict_t *pEnemy ) { static bool bAttack; static float fDelay; // delay to reduce recoil - static float fDist; - extern ConVar rcbot_melee_only; bAttack = true; fDelay = 0; if ( pWeapon ) { - Vector vEnemyOrigin; - - vEnemyOrigin = CBotGlobals::entityOrigin(pEnemy); + static float fDist; + const Vector vEnemyOrigin = CBotGlobals::entityOrigin(pEnemy); fDist = distanceFrom(vEnemyOrigin); @@ -2922,80 +2917,77 @@ bool CDODBot :: handleAttack ( CBotWeapon *pWeapon, edict_t *pEnemy ) return false; } - else - { - fDelay = randomFloat(0.05f,0.2f); + fDelay = randomFloat(0.05f,0.2f); - removeCondition(CONDITION_NEED_AMMO); + removeCondition(CONDITION_NEED_AMMO); - if ( !hasSomeConditions(CONDITION_RUN) ) - stopMoving(); + if ( !hasSomeConditions(CONDITION_RUN) ) + stopMoving(); - if ( pWeapon->needsDeployedOrZoomed() ) // && pWeapon->getID() ==... - { - //stopMoving(); + if ( pWeapon->needsDeployedOrZoomed() ) // && pWeapon->getID() ==... + { + //stopMoving(); - if ( pWeapon->isZoomable() ) + if ( pWeapon->isZoomable() ) + { + if ( !CClassInterface::isSniperWeaponZoomed(pWeaponEdict) ) + bAttack = false; + else + fDelay = randomFloat(0.5f,1.0f); + } + else if ( pWeapon->isDeployable() ) + { + if ( pWeapon->isExplosive() ) + bAttack = CClassInterface::isRocketDeployed(pWeaponEdict); + else { - if ( !CClassInterface::isSniperWeaponZoomed(pWeaponEdict) ) - bAttack = false; - else - fDelay = randomFloat(0.5f,1.0f); + bAttack = CClassInterface::isMachineGunDeployed(pWeaponEdict); } - else if ( pWeapon->isDeployable() ) - { - if ( pWeapon->isExplosive() ) - bAttack = CClassInterface::isRocketDeployed(pWeaponEdict); - else - { - bAttack = CClassInterface::isMachineGunDeployed(pWeaponEdict); - } - if ( !bAttack ) - fDelay = randomFloat(0.7f,1.2f); - //else - // fDelay = 0; - } + if ( !bAttack ) + fDelay = randomFloat(0.7f,1.2f); + //else + // fDelay = 0; + } - if ( !bAttack && (m_fZoomOrDeployTime < engine->Time()) ) + if ( !bAttack && (m_fZoomOrDeployTime < engine->Time()) ) + { + secondaryAttack(); // deploy / zoom + m_fZoomOrDeployTime = engine->Time() + randomFloat(0.5f,1.0f); + } + } + else if ( pWeapon->isDeployable() ) + { + if ( pWeapon->hasHighRecoil() && !CClassInterface::isMachineGunDeployed(pWeaponEdict) ) + { + if ( m_fZoomOrDeployTime < engine->Time() ) { secondaryAttack(); // deploy / zoom m_fZoomOrDeployTime = engine->Time() + randomFloat(0.5f,1.0f); } - } - else if ( pWeapon->isDeployable() ) - { - if ( pWeapon->hasHighRecoil() && !CClassInterface::isMachineGunDeployed(pWeaponEdict) ) - { - if ( m_fZoomOrDeployTime < engine->Time() ) - { - secondaryAttack(); // deploy / zoom - m_fZoomOrDeployTime = engine->Time() + randomFloat(0.5f,1.0f); - } - // not deployed for a while -- go prone to deploy - if ( !hasSomeConditions(CONDITION_RUN) && (m_fDeployMachineGunTime + 1.0f) < engine->Time() ) - { - // go prone - prone(); - - if ( fDist > 400.0f ) - return true; // keep enemy but don't shoot yet - } + // not deployed for a while -- go prone to deploy + if ( !hasSomeConditions(CONDITION_RUN) && (m_fDeployMachineGunTime + 1.0f) < engine->Time() ) + { + // go prone + prone(); - fDelay = randomFloat(0.7f,1.2f); + if ( fDist > 400.0f ) + return true; // keep enemy but don't shoot yet } + + fDelay = randomFloat(0.7f,1.2f); } - else if ( ((pWeapon->getID()==DOD_WEAPON_GARAND)||(pWeapon->getID()==DOD_WEAPON_K98)) && ( distanceFrom(pEnemy) > 1000 )) + } + else if ( ((pWeapon->getID()==DOD_WEAPON_GARAND)||(pWeapon->getID()==DOD_WEAPON_K98)) && ( distanceFrom(pEnemy) > 1000 )) + { + if ( !CClassInterface::isK98Zoomed(pWeaponEdict) && !CClassInterface::isGarandZoomed(pWeaponEdict) ) { - if ( !CClassInterface::isK98Zoomed(pWeaponEdict) && !CClassInterface::isGarandZoomed(pWeaponEdict) ) + if ( m_fZoomOrDeployTime < engine->Time() ) { - if ( m_fZoomOrDeployTime < engine->Time() ) - { - secondaryAttack(); // deploy / zoom - m_fZoomOrDeployTime = engine->Time() + randomFloat(0.1f,0.2f); - fDelay = randomFloat(0.2f,0.4f); - } + secondaryAttack(); // deploy / zoom + m_fZoomOrDeployTime = engine->Time() + randomFloat(0.1f,0.2f); + fDelay = randomFloat(0.2f,0.4f); } } } @@ -3017,65 +3009,56 @@ bool CDODBot :: handleAttack ( CBotWeapon *pWeapon, edict_t *pEnemy ) return true; } -CBotWeapon *CDODBot::getMG () +CBotWeapon *CDODBot::getMG () const { return m_pWeapons->hasWeapon(DOD_WEAPON_20CAL) ? m_pWeapons->getWeapon(CWeapons::getWeapon(DOD_WEAPON_20CAL)) : m_pWeapons->getWeapon(CWeapons::getWeapon(DOD_WEAPON_MG42)); } -bool CDODBot :: hasMG () +bool CDODBot :: hasMG () const { return m_pWeapons->hasWeapon(DOD_WEAPON_20CAL) || m_pWeapons->hasWeapon(DOD_WEAPON_MG42); } -CBotWeapon *CDODBot::getSniperRifle () +CBotWeapon *CDODBot::getSniperRifle () const { return m_pWeapons->hasWeapon(DOD_WEAPON_K98_SCOPED) ? m_pWeapons->getWeapon(CWeapons::getWeapon(DOD_WEAPON_K98_SCOPED)) : m_pWeapons->getWeapon(CWeapons::getWeapon(DOD_WEAPON_SPRING)); } -bool CDODBot :: hasSniperRifle () +bool CDODBot :: hasSniperRifle () const { return m_pWeapons->hasWeapon(DOD_WEAPON_K98_SCOPED) || m_pWeapons->hasWeapon(DOD_WEAPON_SPRING); } -#define BOT_DEFEND 0 -#define BOT_ATTACK 1 +enum : std::uint8_t +{ + BOT_DEFEND = 0, + BOT_ATTACK = 1 +}; -void CDODBot :: getTasks (unsigned int iIgnore) +void CDODBot :: getTasks (unsigned iIgnore) { static CBotUtilities utils; static CBotUtility *next; - static CBotWeapon *grenade; + static CBotWeapon *grenade; //Unused? [APG]RoboCop[CL] static CBotWeapon *pWeapon; static float fAttackUtil; static float fDefendUtil; - static float fDefRate; - static int numPlayersOnTeam; - static int numClassOnTeam; + static int numPlayersOnTeam; //Unused? [APG]RoboCop[CL] + static int numClassOnTeam; //Unused? [APG]RoboCop[CL] static bool bCheckCurrent; static int iFlagID; static int iFlagsOwned; - static int iEnemyFlagsOwned; + static int iEnemyFlagsOwned; //Unused? [APG]RoboCop[CL] static int iNumFlags; - static int iNumBombsToPlant; - static int iNumBombsOnMap; - static int iNumEnemyBombsOnMap; - static int iNumEnemyBombsStillToPlant; - static int iNumBombsToDefuse; - static int iNumBombsToDefend; - static float fDefendBombUtil; - static float fDefuseBombUtil; - static float fPlantUtil; - static int iEnemyTeam; static bool bCanMessAround; - extern ConVar rcbot_melee_only; // if condition has changed or no tasks if ( !hasSomeConditions(CONDITION_CHANGED) && !m_pSchedules->isEmpty() ) return; //squads - ADD_UTILITY(BOT_UTIL_FOLLOW_SQUAD_LEADER,!hasSomeConditions(CONDITION_DEFENSIVE) && hasSomeConditions(CONDITION_SQUAD_LEADER_INRANGE) && inSquad() && (m_pSquad->GetLeader()!=m_pEdict) && hasSomeConditions(CONDITION_SEE_SQUAD_LEADER),hasSomeConditions(CONDITION_SQUAD_IDLE)?0.1f:2.0f); - ADD_UTILITY(BOT_UTIL_FIND_SQUAD_LEADER,!hasSomeConditions(CONDITION_DEFENSIVE) && inSquad() && (m_pSquad->GetLeader()!=m_pEdict) && (!hasSomeConditions(CONDITION_SEE_SQUAD_LEADER) || !hasSomeConditions(CONDITION_SQUAD_LEADER_INRANGE)),hasSomeConditions(CONDITION_SQUAD_IDLE)?0.1f:2.0f); + ADD_UTILITY(BOT_UTIL_FOLLOW_SQUAD_LEADER,!hasSomeConditions(CONDITION_DEFENSIVE) && hasSomeConditions(CONDITION_SQUAD_LEADER_INRANGE) && inSquad() && (m_pSquad->GetLeader()!=m_pEdict) && hasSomeConditions(CONDITION_SEE_SQUAD_LEADER),hasSomeConditions(CONDITION_SQUAD_IDLE)?0.1f:2.0f) + ADD_UTILITY(BOT_UTIL_FIND_SQUAD_LEADER,!hasSomeConditions(CONDITION_DEFENSIVE) && inSquad() && (m_pSquad->GetLeader()!=m_pEdict) && (!hasSomeConditions(CONDITION_SEE_SQUAD_LEADER) || !hasSomeConditions(CONDITION_SQUAD_LEADER_INRANGE)),hasSomeConditions(CONDITION_SQUAD_IDLE)?0.1f:2.0f) bCheckCurrent = true; m_iTeam = getTeam(); // update team @@ -3087,15 +3070,15 @@ void CDODBot :: getTasks (unsigned int iIgnore) numClassOnTeam = CDODMod::numClassOnTeam(m_iTeam,m_iClass); numPlayersOnTeam = CBotGlobals::numPlayersOnTeam(m_iTeam,false); - pWeapon = NULL; + pWeapon = nullptr; removeCondition(CONDITION_CHANGED); // always able to roam around -- low utility - ADD_UTILITY(BOT_UTIL_ROAM,true,0.01f); + ADD_UTILITY(BOT_UTIL_ROAM,true,0.01f) // I had an enemy a minute ago - ADD_UTILITY(BOT_UTIL_FIND_LAST_ENEMY,wantToFollowEnemy() && !m_bLookedForEnemyLast && (m_pLastEnemy.get()!=NULL) && CBotGlobals::entityIsValid(m_pLastEnemy) && CBotGlobals::entityIsAlive(m_pLastEnemy),getHealthPercent()*0.89f); + ADD_UTILITY(BOT_UTIL_FIND_LAST_ENEMY,wantToFollowEnemy() && !m_bLookedForEnemyLast && (m_pLastEnemy.get()!=NULL) && CBotGlobals::entityIsValid(m_pLastEnemy) && CBotGlobals::entityIsAlive(m_pLastEnemy),getHealthPercent()*0.89f) // flag capture map if ( CDODMod::isFlagMap() && (CDODMod::m_Flags.getNumFlags() > 0) && !rcbot_nocapturing.GetBool() ) @@ -3105,18 +3088,21 @@ void CDODBot :: getTasks (unsigned int iIgnore) bCanMessAround = false; if ( inSquad() ) - { - iFlagID = CDODMod::m_Flags.findNearestObjective(m_pSquad->GetFormationPosition(m_pEdict)); + { + //caxanga334: SDK 2013 doesn't like to create a Vector from an int + //#if SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_TF2 + iFlagID = CDODMod::m_Flags.findNearestObjective(Vector(static_cast(m_pSquad->GetFormationPosition(m_pEdict)))); + //#else + //iFlagID = CDODMod::m_Flags.findNearestObjective(Vector(static_cast(m_pSquad->GetFormationPosition(m_pEdict)))); + //#endif m_pNearestFlag = CDODMod::m_Flags.getFlagByID(iFlagID); if ( hasSomeConditions(CONDITION_DEFENSIVE) ) { - CWaypoint *pWaypoint = CWaypoints::getWaypoint(CDODMod::m_Flags.getWaypointAtFlag(iFlagID)); - - if ( pWaypoint ) + if ( CWaypoint *pWaypoint = CWaypoints::getWaypoint(CDODMod::m_Flags.getWaypointAtFlag(iFlagID)) ) { // just following orders - ADD_UTILITY_DATA_VECTOR(BOT_UTIL_DEFEND_NEAREST_POINT,true,1.5f,iFlagID,pWaypoint->getOrigin()); + ADD_UTILITY_DATA_VECTOR(BOT_UTIL_DEFEND_NEAREST_POINT,true,1.5f,iFlagID,pWaypoint->getOrigin()) } } } @@ -3128,7 +3114,7 @@ void CDODBot :: getTasks (unsigned int iIgnore) bAttackNearestFlag = !CDODMod::m_Flags.ownsFlag(iFlagID,m_iTeam) && ((CDODMod::m_Flags.numCappersRequired(iFlagID,m_iTeam)-CDODMod::m_Flags.numFriendliesAtCap(iFlagID,m_iTeam))>0); } - if ( (m_pNearestFlag==NULL) || !bAttackNearestFlag ) + if ( (m_pNearestFlag.get() == nullptr) || !bAttackNearestFlag ) { if ( !hasSomeConditions(CONDITION_DEFENSIVE) && CDODMod::shouldAttack(m_iTeam) ) { @@ -3147,30 +3133,41 @@ void CDODBot :: getTasks (unsigned int iIgnore) fDefendUtil *= 2; // if we see a flag and we own it, don't worry about it - ADD_UTILITY(BOT_UTIL_ATTACK_POINT,true,fAttackUtil); - ADD_UTILITY(BOT_UTIL_DEFEND_POINT,true,fDefendUtil); + ADD_UTILITY(BOT_UTIL_ATTACK_POINT,true,fAttackUtil) + ADD_UTILITY(BOT_UTIL_DEFEND_POINT,true,fDefendUtil) } if ( m_pNearestFlag && (!inSquad() || (isSquadLeader() || (hasSomeConditions(CONDITION_SQUAD_IDLE) && (distanceFrom(m_pNearestFlag)0)||hasEnemy()), - (iFlagsOwned == 1) ? 0.9f : 0.75f,iFlagID,CBotGlobals::entityOrigin(m_pNearestFlag)); + (iFlagsOwned == 1) ? 0.9f : 0.75f,iFlagID,CBotGlobals::entityOrigin(m_pNearestFlag)) } if ( CDODMod::mapHasBombs() ) { - ADD_UTILITY(BOT_UTIL_PICKUP_BOMB,!m_bHasBomb,hasSomeConditions(CONDITION_NEED_BOMB) ? 1.0f : 0.75f); + ADD_UTILITY(BOT_UTIL_PICKUP_BOMB,!m_bHasBomb,hasSomeConditions(CONDITION_NEED_BOMB) ? 1.0f : 0.75f) } } // bomb map if ( CDODMod::isBombMap() && (CDODMod::m_Flags.getNumFlags() > 0) && !rcbot_nocapturing.GetBool() ) { + static int iEnemyTeam; + static float fPlantUtil; + static float fDefuseBombUtil; + static float fDefendBombUtil; + static int iNumEnemyBombsStillToPlant; + static int iNumBombsToDefend; + static int iNumBombsToDefuse; + static int iNumEnemyBombsOnMap; + static int iNumBombsOnMap; + static int iNumBombsToPlant; + static float fDefRate; bCanMessAround = false; // same thing as above except with bombs iFlagID = -1; @@ -3189,15 +3186,15 @@ void CDODBot :: getTasks (unsigned int iIgnore) fDefendUtil = 0.4f; if ( iNumEnemyBombsOnMap > 0 ) - fDefendUtil = 0.8f - ((float)iNumEnemyBombsStillToPlant/iNumEnemyBombsOnMap)*0.4f; + fDefendUtil = 0.8f - (static_cast(iNumEnemyBombsStillToPlant) / static_cast(iNumEnemyBombsOnMap)) * 0.4f; - if ( CDODMod::isFlagMap() && (iNumBombsToPlant>0) ) - fPlantUtil = 0.3f + ((((float)iFlagsOwned/iNumBombsToPlant)*0.6f)/iNumFlags); + if (CDODMod::isFlagMap() && (iNumBombsToPlant > 0)) + fPlantUtil = 0.3f + (((static_cast(iFlagsOwned) / static_cast(iNumBombsToPlant)) * 0.6f) / static_cast(iNumFlags)); else - fPlantUtil = 0.4f + (((float)iNumBombsToPlant/iNumBombsOnMap)*0.4f); - + fPlantUtil = 0.4f + ((static_cast(iNumBombsToPlant) / static_cast(iNumBombsOnMap)) * 0.4f); + fDefuseBombUtil = fDefendUtil * 2; - fDefendBombUtil = 0.8f - (((float)iNumBombsToDefend/iNumBombsOnMap)*0.8f); + fDefendBombUtil = 0.8f - ((static_cast(iNumBombsToDefend) / static_cast(iNumBombsOnMap)) * 0.8f); fPlantUtil += randomFloat(-0.25f,0.25f); // add some fuzz @@ -3220,15 +3217,15 @@ void CDODBot :: getTasks (unsigned int iIgnore) fDefendUtil *= 2.0f; } - ADD_UTILITY(BOT_UTIL_PLANT_BOMB,m_bHasBomb && (iNumBombsToPlant>0),fPlantUtil ); - ADD_UTILITY(BOT_UTIL_DEFUSE_BOMB,(iNumBombsToDefuse>0), fDefuseBombUtil); - ADD_UTILITY(BOT_UTIL_DEFEND_BOMB,(iNumBombsToDefend>0), fDefendBombUtil); + ADD_UTILITY(BOT_UTIL_PLANT_BOMB,m_bHasBomb && (iNumBombsToPlant>0),fPlantUtil ) + ADD_UTILITY(BOT_UTIL_DEFUSE_BOMB,(iNumBombsToDefuse>0), fDefuseBombUtil) + ADD_UTILITY(BOT_UTIL_DEFEND_BOMB,(iNumBombsToDefend>0), fDefendBombUtil) - ADD_UTILITY(BOT_UTIL_PICKUP_BOMB,!m_bHasBomb && (iNumBombsToPlant>0),hasSomeConditions(CONDITION_NEED_BOMB) ? 0.9f : fPlantUtil); + ADD_UTILITY(BOT_UTIL_PICKUP_BOMB,!m_bHasBomb && (iNumBombsToPlant>0),hasSomeConditions(CONDITION_NEED_BOMB) ? 0.9f : fPlantUtil) if ( iNumEnemyBombsOnMap > 0 ) { - ADD_UTILITY(BOT_UTIL_DEFEND_POINT,(iFlagsOwned>0)&&(m_pNearestFlag==NULL)||CDODMod::m_Flags.ownsFlag(iFlagID,m_iTeam),fDefendUtil); + ADD_UTILITY(BOT_UTIL_DEFEND_POINT, ((iFlagsOwned > 0) && (m_pNearestFlag == nullptr)) || CDODMod::m_Flags.ownsFlag(iFlagID, m_iTeam), fDefendUtil) /*if ( m_pNearestFlag ) { @@ -3241,35 +3238,35 @@ void CDODBot :: getTasks (unsigned int iIgnore) if ( m_pNearestBomb && (!inSquad() || (isSquadLeader() || (hasSomeConditions(CONDITION_SQUAD_IDLE) && (distanceFrom(m_pNearestBomb)0.75f), fAttackUtil ); + ADD_UTILITY(BOT_UTIL_MESSAROUND,(getHealthPercent()>0.75f), fAttackUtil ) } - if ( !rcbot_melee_only.GetBool() && (m_pNearestWeapon.get() != NULL) && hasSomeConditions(CONDITION_NEED_AMMO) ) + if ( !rcbot_melee_only.GetBool() && (m_pNearestWeapon.get() != nullptr) && hasSomeConditions(CONDITION_NEED_AMMO) ) { - CWeapon *pNearestWeapon = CWeapons::getWeapon(m_pNearestWeapon.get()->GetClassName()); - CBotWeapon *pHaveWeapon = (pNearestWeapon==NULL)?NULL:(m_pWeapons->getWeapon(pNearestWeapon)); + const CWeapon *pNearestWeapon = CWeapons::getWeapon(m_pNearestWeapon.get()->GetClassName()); + const CBotWeapon *pHaveWeapon = (pNearestWeapon== nullptr)? nullptr :(m_pWeapons->getWeapon(pNearestWeapon)); if ( pNearestWeapon && (!pHaveWeapon || !pHaveWeapon->hasWeapon() || pHaveWeapon->outOfAmmo(this) ) ) { - ADD_UTILITY(BOT_UTIL_PICKUP_WEAPON, true, 0.6f + pNearestWeapon->getPreference()*0.1f); + ADD_UTILITY(BOT_UTIL_PICKUP_WEAPON, true, 0.6f + pNearestWeapon->getPreference()*0.1f) } //BOT_UTIL_DOD_PICKUP_OBJ } @@ -3281,25 +3278,27 @@ void CDODBot :: getTasks (unsigned int iIgnore) pWeapon = getSniperRifle(); if ( pWeapon ) - ADD_UTILITY_WEAPON_DATA(BOT_UTIL_SNIPE,pWeapon->getAmmo(this)>0,hasSomeConditions(CONDITION_DEFENSIVE) ? 1.6f : (getHealthPercent() * randomFloat(0.75f,1.0f)),pWeapon,hasSomeConditions(CONDITION_DEFENSIVE) ? false : (fAttackUtil>fDefendUtil)); + ADD_UTILITY_WEAPON_DATA(BOT_UTIL_SNIPE,pWeapon->getAmmo(this)>0,hasSomeConditions(CONDITION_DEFENSIVE) ? 1.6f : (getHealthPercent() * randomFloat(0.75f,1.0f)),pWeapon,hasSomeConditions(CONDITION_DEFENSIVE) ? false : (fAttackUtil>fDefendUtil)) } else if ( !rcbot_melee_only.GetBool() && hasMG() ) { pWeapon = getMG(); if ( pWeapon ) - ADD_UTILITY_WEAPON_DATA(BOT_UTIL_SNIPE,pWeapon->getAmmo(this)>0,hasSomeConditions(CONDITION_DEFENSIVE) ? 1.6f : (getHealthPercent()),pWeapon,hasSomeConditions(CONDITION_DEFENSIVE) ? false : (fAttackUtil>fDefendUtil)); + ADD_UTILITY_WEAPON_DATA(BOT_UTIL_SNIPE,pWeapon->getAmmo(this)>0,hasSomeConditions(CONDITION_DEFENSIVE) ? 1.6f : (getHealthPercent()),pWeapon,hasSomeConditions(CONDITION_DEFENSIVE) ? false : (fAttackUtil>fDefendUtil)) } // grenades - if ( !rcbot_melee_only.GetBool() && !hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && hasSomeConditions(CONDITION_SEE_LAST_ENEMY_POS) && m_pLastEnemy && m_fLastSeeEnemy && ((m_fLastSeeEnemy + 10.0) > engine->Time()) && + if ( !rcbot_melee_only.GetBool() && !hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && hasSomeConditions(CONDITION_SEE_LAST_ENEMY_POS) && m_pLastEnemy && m_fLastSeeEnemy && ((m_fLastSeeEnemy + 10.0f) > engine->Time()) && (m_pWeapons->hasWeapon(DOD_WEAPON_FRAG_US) || m_pWeapons->hasWeapon(DOD_WEAPON_FRAG_GER) || m_pWeapons->hasWeapon(DOD_WEAPON_SMOKE_US) || m_pWeapons->hasWeapon(DOD_WEAPON_SMOKE_GER)) ) { - float fDistance = distanceFrom(m_vLastSeeEnemyBlastWaypoint); - float fGrenUtil = 0.85f + ( (1.0f - getHealthPercent()) * 0.15f); + const float fDistance = distanceFrom(m_vLastSeeEnemyBlastWaypoint); + const float fGrenUtil = 0.85f + ( (1.0f - getHealthPercent()) * 0.15f); - CBotWeapon *pBotWeapon = NULL; - CBotWeapon *pBotSmokeGren = m_pWeapons->hasWeapon(DOD_WEAPON_SMOKE_US) ? m_pWeapons->getWeapon(CWeapons::getWeapon(DOD_WEAPON_SMOKE_US)) : m_pWeapons->getWeapon(CWeapons::getWeapon(DOD_WEAPON_SMOKE_GER)); + CBotWeapon *pBotWeapon = nullptr; + CBotWeapon* pBotSmokeGren = m_pWeapons->hasWeapon(DOD_WEAPON_SMOKE_US) + ? m_pWeapons->getWeapon(CWeapons::getWeapon(DOD_WEAPON_SMOKE_US)) + : m_pWeapons->getWeapon(CWeapons::getWeapon(DOD_WEAPON_SMOKE_GER)); if ( (hasSomeConditions(CONDITION_COVERT)||(m_fCurrentDanger >= 25.0f)) && pBotSmokeGren && pBotSmokeGren->hasWeapon() ) pBotWeapon = pBotSmokeGren; @@ -3308,10 +3307,13 @@ void CDODBot :: getTasks (unsigned int iIgnore) else if ( m_pWeapons->hasWeapon(DOD_WEAPON_FRAG_GER) ) pBotWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(DOD_WEAPON_FRAG_GER)); - // if within throw distance and outside balst radius, I can throw it + // if within throw distance and outside blast radius, I can throw it if ( pBotWeapon && (!pBotWeapon->isExplosive() || (fDistance > BLAST_RADIUS)) && ( fDistance < (MAX_GREN_THROW_DIST+BLAST_RADIUS) ) ) { - ADD_UTILITY_WEAPON(BOT_UTIL_THROW_GRENADE, pBotWeapon && (pBotWeapon->getAmmo(this) > 0) ,hasSomeConditions(CONDITION_GREN) ? fGrenUtil*2 : fGrenUtil,pBotWeapon); + assert(pBotWeapon != nullptr); + + ADD_UTILITY_WEAPON(BOT_UTIL_THROW_GRENADE, pBotWeapon->getAmmo(this) > 0, + hasSomeConditions(CONDITION_GREN) ? fGrenUtil*2 : fGrenUtil, pBotWeapon) } } @@ -3328,7 +3330,7 @@ void CDODBot :: getTasks (unsigned int iIgnore) utils.execute(); - while ( (next = utils.nextBest()) != NULL ) + while ( (next = utils.nextBest()) != nullptr) { if ( !m_pSchedules->isEmpty() && bCheckCurrent ) { @@ -3366,7 +3368,7 @@ bool CDODBot :: select_CWeapon ( CWeapon *pWeapon ) { char cmd[128]; - sprintf(cmd,"use %s\n",pWeapon->getWeaponName()); + snprintf(cmd, sizeof(cmd), "use %s\n", pWeapon->getWeaponName()); helpers->ClientCommand(m_pEdict,cmd); @@ -3375,21 +3377,18 @@ bool CDODBot :: select_CWeapon ( CWeapon *pWeapon ) bool CDODBot :: selectBotWeapon ( CBotWeapon *pBotWeapon ) { - CWeapon *pSelect = pBotWeapon->getWeaponInfo(); - - if ( pSelect ) + if ( const CWeapon *pSelect = pBotWeapon->getWeaponInfo() ) { //int id = pSelect->getWeaponIndex(); char cmd[128]; - sprintf(cmd,"use %s\n",pSelect->getWeaponName()); + snprintf(cmd, sizeof(cmd), "use %s\n", pSelect->getWeaponName()); helpers->ClientCommand(m_pEdict,cmd); return true; } - else - failWeaponSelect(); + failWeaponSelect(); return false; } @@ -3398,7 +3397,7 @@ void CDODBot :: updateConditions () { CBot::updateConditions(); - if ( m_pPrimaryWeapon != NULL ) + if ( m_pPrimaryWeapon != nullptr) { if ( m_pPrimaryWeapon->outOfAmmo(this) ) { @@ -3433,22 +3432,20 @@ bool CDODBot :: walkingTowardsWaypoint ( CWaypoint *pWaypoint, bool *bOffsetAppl void CDODBot :: modAim ( edict_t *pEntity, Vector &v_origin, - Vector *v_desired_offset, Vector &v_size, - float fDist, float fDist2D ) + Vector *v_desired_offset, Vector &v_size, + const float fDist, const float fDist2D ) { //static Vector vAim; - static short int iSlot; - static smoke_t *smokeinfo; //static bool bProne; - static float fStamina; + + static float fStamina; //Unused? [APG]RoboCop[CL] static CBotWeapon *pWp; static Vector vel; static int index; bool bIsEnemyProne; float fEnemyStamina; - bool bAddHeadHeight; - bAddHeadHeight = false; + bool bAddHeadHeight = false; //Unused? [APG]RoboCop[CL] CBot::modAim(pEntity,v_origin,v_desired_offset,v_size,fDist,fDist2D); @@ -3464,7 +3461,7 @@ void CDODBot :: modAim ( edict_t *pEntity, Vector &v_origin, // .. so update if ( bIsEnemyProne ) { - v_desired_offset->z -= randomFloat(0.0,8.0f); + v_desired_offset->z -= randomFloat(0.0f,8.0f); } // aiming for head done in Cbot::getaimVector /*else if ( hasSomeConditions(CONDITION_SEE_ENEMY_HEAD) ) @@ -3476,7 +3473,7 @@ void CDODBot :: modAim ( edict_t *pEntity, Vector &v_origin, } // weapon is known - if ( pWp != NULL ) + if ( pWp != nullptr) { if ( pWp->isProjectile() ) { @@ -3489,16 +3486,11 @@ void CDODBot :: modAim ( edict_t *pEntity, Vector &v_origin, *v_desired_offset = *v_desired_offset - Vector(0,0,randomFloat(16.0f,32.0f)); } - if ( pWp->getProjectileSpeed() > 0 ) - { - extern ConVar *sv_gravity; - - if ( sv_gravity != NULL ) + if ( pWp->getProjectileSpeed() > 0 && sv_gravity.IsValid() ) { - float fTime = fDist2D/pWp->getProjectileSpeed(); - - v_desired_offset->z = (pow(2,fTime)*(sv_gravity->GetFloat()*rcbot_projectile_tweak.GetFloat()));// - (getOrigin().z - v_origin.z); - } + const float fTime = fDist2D/pWp->getProjectileSpeed(); + //TODO: Improve on the floating point precision conversion [APG]RoboCop[CL] + v_desired_offset->z = static_cast(std::pow(2, fTime)) * (sv_gravity.GetFloat() * rcbot_projectile_tweak.GetFloat());// - (getOrigin().z - v_origin.z); } //v_desired_offset->z += (distanceFrom(pEntity) * (randomFloat(0.05,0.15)*m_pProfile->m_fAimSkill)); } @@ -3507,10 +3499,12 @@ void CDODBot :: modAim ( edict_t *pEntity, Vector &v_origin, // if I know the enemy is near a smoke grenade i'll fire randomly into the cloud if ( m_pNearestSmokeToEnemy ) { - iSlot = ENTINDEX(pEntity)-1; + static int iSlot; + iSlot = ENTINDEX(pEntity) - 1; - if (( iSlot >= 0 ) && ( iSlot < MAX_PLAYERS )) + if (( iSlot >= 0 ) && ( iSlot < RCBOT_MAXPLAYERS )) { + static smoke_t *smokeinfo; smokeinfo = &(m_CheckSmoke[iSlot]); if ( smokeinfo->bInSmoke ) @@ -3526,58 +3520,58 @@ void CDODBot :: modAim ( edict_t *pEntity, Vector &v_origin, bool CDODBot :: isVisibleThroughSmoke ( edict_t *pSmoke, edict_t *pCheck ) { - //if ( isVisible(pCheck) ) -//{ - static float fSmokeDist,fDist; - static smoke_t *smokeinfo; - static float fTime, fProb; - static Vector vSmoke; - static Vector vCheckComp; + static float fTime = 0.0f; //Unused? [APG]RoboCop[CL] + static float fProb = 0.0f; //Unused? [APG]RoboCop[CL] - static short int iSlot; + static int iSlot; - iSlot = ENTINDEX(pCheck)-1; + iSlot = ENTINDEX(pCheck) - 1; // if pCheck is a player - if (( iSlot >= 0 ) && ( iSlot < MAX_PLAYERS )) + if (( iSlot >= 0 ) && ( iSlot < RCBOT_MAXPLAYERS )) { + static smoke_t *smokeinfo; smokeinfo = &(m_CheckSmoke[iSlot]); // last time i checked was long enough ago if ( smokeinfo->fLastTime < engine->Time() ) { + static float fDist; + static float fSmokeDist; + static Vector vSmoke; smokeinfo->bVisible = true; smokeinfo->bInSmoke = false; - vSmoke = CBotGlobals::entityOrigin(pSmoke); - fSmokeDist = distanceFrom(vSmoke); + vSmoke = CBotGlobals::entityOrigin(pSmoke); + fSmokeDist = distanceFrom(vSmoke); - // I'm outside smoke -- but maybe the enemy is inside the smoke - if ( fSmokeDist > SMOKE_RADIUS ) - { - fDist = (CBotGlobals::entityOrigin(pCheck) - vSmoke).Length(); + // I'm outside smoke -- but maybe the enemy is inside the smoke + if ( fSmokeDist > SMOKE_RADIUS ) + { + fDist = (CBotGlobals::entityOrigin(pCheck) - vSmoke).Length(); - // enemy outside the smoke radius - if ( fDist > SMOKE_RADIUS ) - { - // check if enemy is behind the smoke from my perspective - vCheckComp = CBotGlobals::entityOrigin(pCheck) - getOrigin(); - vCheckComp = (vCheckComp / vCheckComp.Length())*fSmokeDist; + // enemy outside the smoke radius + if ( fDist > SMOKE_RADIUS ) + { + static Vector vCheckComp; + // check if enemy is behind the smoke from my perspective + vCheckComp = CBotGlobals::entityOrigin(pCheck) - getOrigin(); + vCheckComp = (vCheckComp / vCheckComp.Length())*fSmokeDist; - fDist = (vSmoke - (getOrigin() + vCheckComp)).Length(); - } + fDist = (vSmoke - (getOrigin() + vCheckComp)).Length(); } - else - fDist = fSmokeDist; + } + else + fDist = fSmokeDist; - if ( fDist <= SMOKE_RADIUS ) - // smoke gets heavy at 1.0 seconds and diminishes at 10 secs - { - smokeinfo->fProb = 1.0f-(fDist/SMOKE_RADIUS); - smokeinfo->bVisible = (randomFloat(0.0f,0.33f) > smokeinfo->fProb ); - // smoke gets pretty heavy half way into the smoke grenade - smokeinfo->bInSmoke = true; - } + if ( fDist <= SMOKE_RADIUS ) + // smoke gets heavy at 1.0 seconds and diminishes at 10 secs + { + smokeinfo->fProb = 1.0f-(fDist/SMOKE_RADIUS); + smokeinfo->bVisible = (randomFloat(0.0f,0.33f) > smokeinfo->fProb ); + // smoke gets pretty heavy half way into the smoke grenade + smokeinfo->bInSmoke = true; + } #ifdef _DEBUG if ( CClients::clientsDebugging(BOT_DEBUG_THINK) ) diff --git a/utils/RCBot2_meta/bot_dod_bot.h b/utils/RCBot2_meta/bot_dod_bot.h index 146e55729..0a29ac4a1 100644 --- a/utils/RCBot2_meta/bot_dod_bot.h +++ b/utils/RCBot2_meta/bot_dod_bot.h @@ -31,32 +31,37 @@ #ifndef __DOD_RCBOT_H__ #define __DOD_RCBOT_H__ -#define TEAM_ALLIES 2 -#define TEAM_AXIS 3 +#include "bot.h" -#define MAX_GREN_THROW_DIST 1024.0f +enum : std::uint8_t +{ + TEAM_ALLIES = 2, + TEAM_AXIS = 3 +}; -#define SMOKE_RADIUS 150.0f -#define DOD_BOMB_EXPLODE_IMMINENT_TIME 7.0f +constexpr float MAX_GREN_THROW_DIST = 1024.0f; + +constexpr float SMOKE_RADIUS = 150.0f; +constexpr float DOD_BOMB_EXPLODE_IMMINENT_TIME = 7.0f; class CBroadcastBombEvent : public IBotFunction { public: - CBroadcastBombEvent ( int iEvent, int iCP, int iTeam ) + CBroadcastBombEvent (const int iEvent, const int iCP, const int iTeam) { m_iEvent = iEvent; m_iCP = iCP; m_iTeam = iTeam; - }; + } - void execute (CBot *pBot); + void execute (CBot *pBot) override; private: int m_iCP; int m_iTeam; int m_iEvent; }; -typedef enum +typedef enum : std::uint8_t { - DOD_VC_GOGOGO = 0, + DOD_VC_GOGOGO = 0, DOD_VC_YES = 1, DOD_VC_DROPWEAP = 2, DOD_VC_HOLD = 3, @@ -89,29 +94,35 @@ typedef enum typedef struct { eDODVoiceCMD id; - char *pcmd; + const char *pcmd; }eDODVoiceCommand_t; -typedef enum +typedef enum : std::uint8_t { - DOD_CLASS_RIFLEMAN = 0, - DOD_CLASS_ASSAULT, - DOD_CLASS_SUPPORT, - DOD_CLASS_SNIPER, - DOD_CLASS_MACHINEGUNNER, - DOD_CLASS_ROCKET + DOD_CLASS_RIFLEMAN = 1, + DOD_CLASS_ASSAULT = 2, + DOD_CLASS_SUPPORT = 3, + DOD_CLASS_SNIPER = 4, + DOD_CLASS_MACHINEGUNNER = 5, + DOD_CLASS_ROCKET = 6 }DOD_Class; -#define DOD_BOMB_STATE_UNAVAILABLE 0 -#define DOD_BOMB_STATE_AVAILABLE 1 -#define DOD_BOMB_STATE_ACTIVE 2 +enum : std::uint8_t +{ + DOD_BOMB_STATE_UNAVAILABLE = 0, + DOD_BOMB_STATE_AVAILABLE = 1, + DOD_BOMB_STATE_ACTIVE = 2 +}; -#define DOD_BOMB_EXPLODED 0 -#define DOD_BOMB_DEFUSE 1 -#define DOD_BOMB_PLANT 2 -#define DOD_BOMB_PATH_PLANT 3 -#define DOD_BOMB_PATH_DEFUSE 4 -#define DOD_POINT_CAPTURED 5 +enum : std::uint8_t +{ + DOD_BOMB_EXPLODED = 0, + DOD_BOMB_DEFUSE = 1, + DOD_BOMB_PLANT = 2, + DOD_BOMB_PATH_PLANT = 3, + DOD_BOMB_PATH_DEFUSE = 4, + DOD_POINT_CAPTURED = 5 +}; #define DOD_CLASSNAME_CONTROLPOINT "dod_control_point" #define DOD_CLASSNAME_BOMBTARGET "dod_bomb_target" @@ -131,86 +142,86 @@ class CDODBot : public CBot CDODBot(); - bool isDOD () { return true; } + bool isDOD () override { return true; } - bool withinTeammate ( ); + bool withinTeammate ( ) const; - bool hasBomb () { return m_bHasBomb; } + bool hasBomb () const { return m_bHasBomb; } void removeBomb () { m_bHasBomb = false; } void bombEvent ( int iEvent, int iCP, int iTeam ); - void friendlyFire ( edict_t *pEdict ); + void friendlyFire ( edict_t *pEdict ) override; - void modThink (); + void modThink () override; - virtual void init (bool bVarInit=false); - void setup (); + void init (bool bVarInit=false) override; + void setup () override; - virtual void freeMapMemory (); + void freeMapMemory () override; //Vector getAimVector ( edict_t *pEntity ); - virtual void modAim ( edict_t *pEntity, Vector &v_origin, - Vector *v_desired_offset, Vector &v_size, - float fDist, float fDist2D); + void modAim ( edict_t *pEntity, Vector &v_origin, + Vector *v_desired_offset, Vector &v_size, + float fDist, float fDist2D) override; - bool startGame (); + bool startGame () override; - void died ( edict_t *pKiller, const char *pszWeapon ); - void killed ( edict_t *pVictim, char *weapon ); + void died ( edict_t *pKiller, const char *pszWeapon ) override; + void killed ( edict_t *pVictim, char *weapon ) override; - void spawnInit (); + void spawnInit () override; - float getEnemyFactor ( edict_t *pEnemy ); + float getEnemyFactor ( edict_t *pEnemy ) override; - bool isEnemy ( edict_t *pEdict,bool bCheckWeapons = true ); + bool isEnemy ( edict_t *pEdict,bool bCheckWeapons = true ) override; - float getArmorPercent () { return (0.01f * m_pPlayerInfo->GetArmorValue()); } + float getArmorPercent () const { return 0.01f * static_cast(m_pPlayerInfo->GetArmorValue()); } - void getTasks (unsigned int iIgnore); + void getTasks (unsigned iIgnore) override; bool executeAction ( CBotUtility *util ); - void updateConditions (); + void updateConditions () override; void selectedClass ( int iClass ); - bool setVisible ( edict_t *pEntity, bool bVisible ); + bool setVisible ( edict_t *pEntity, bool bVisible ) override; - bool select_CWeapon ( CWeapon *pWeapon ); + bool select_CWeapon ( CWeapon *pWeapon ) override; - bool selectBotWeapon ( CBotWeapon *pBotWeapon ); + bool selectBotWeapon ( CBotWeapon *pBotWeapon ) override; - bool canGotoWaypoint (Vector vPrevWaypoint, CWaypoint *pWaypoint, CWaypoint *pPrev = NULL); + bool canGotoWaypoint (const Vector& vPrevWaypoint, CWaypoint* pWaypoint, CWaypoint* pPrev = nullptr) override; - void defending (); + void defending () override; - bool handleAttack ( CBotWeapon *pWeapon, edict_t *pEnemy ); + bool handleAttack ( CBotWeapon *pWeapon, edict_t *pEnemy ) override; - void hearVoiceCommand ( edict_t *pPlayer, byte cmd ); + void hearVoiceCommand ( edict_t *pPlayer, byte voiceCmd ) override; - void handleWeapons (); + void handleWeapons () override; - void reachedCoverSpot (int flags); + void reachedCoverSpot (int flags) override; - void touchedWpt ( CWaypoint *pWaypoint, int iNextWaypoint = -1, int iPrevWaypoint = -1 ); + void touchedWpt ( CWaypoint *pWaypoint, int iNextWaypoint = -1, int iPrevWaypoint = -1 ) override; - bool checkStuck (); + bool checkStuck () override; - bool hasMG (); - CBotWeapon *getMG(); - CBotWeapon *getSniperRifle (); - bool hasSniperRifle (); + bool hasMG () const; + CBotWeapon *getMG() const; + CBotWeapon *getSniperRifle () const; + bool hasSniperRifle () const; - void voiceCommand ( int cmd ); + void voiceCommand (byte voiceCmd) override; - virtual unsigned int maxEntityIndex ( ) { return gpGlobals->maxEntities; } + unsigned maxEntityIndex ( ) override { return gpGlobals->maxEntities; } - void seeFriendlyDie ( edict_t *pDied, edict_t *pKiller, CWeapon *pKillerWeapon ); - void seeFriendlyKill ( edict_t *pTeamMate, edict_t *pDied, CWeapon *pWeapon ); + void seeFriendlyDie ( edict_t *pDied, edict_t *pKiller, CWeapon *pWeapon ) override; + void seeFriendlyKill ( edict_t *pTeamMate, edict_t *pDied, CWeapon *pWeapon ) override; bool isVisibleThroughSmoke ( edict_t *pSmoke, edict_t *pCheck ); - void grenadeThrown () { addVoiceCommand(DOD_VC_FIRE_IN_THE_HOLE); } + void grenadeThrown () override { addVoiceCommand(DOD_VC_FIRE_IN_THE_HOLE); } void chooseClass( bool bIsChangingClass ); // updates m_iDesiredClass void changeClass(); // uses m_iDesiredClass @@ -219,19 +230,19 @@ class CDODBot : public CBot void prone (); void unProne(); - bool wantToListenToPlayerAttack ( edict_t *pPlayer, int iWeaponID = -1); + bool wantToListenToPlayerAttack ( edict_t *pPlayer, int iWeaponID = -1) override; - bool walkingTowardsWaypoint ( CWaypoint *pWaypoint, bool *bOffsetApplied, Vector &vOffset ); + bool walkingTowardsWaypoint ( CWaypoint *pWaypoint, bool *bOffsetApplied, Vector &vOffset ) override; - void listenForPlayers (); + void listenForPlayers () override; - void signal ( const char *signal ); + void signal ( const char *signal ) const; - void sayInPosition (); + void sayInPosition () override; - void sayMoveOut (); + void sayMoveOut () override; - void areaClear(); + void areaClear() override; void dropAmmo (); @@ -276,7 +287,7 @@ class CDODBot : public CBot bool m_bCheckClass; bool m_bHasBomb; - smoke_t m_CheckSmoke[MAX_PLAYERS]; + smoke_t m_CheckSmoke[RCBOT_MAXPLAYERS]; float m_fDeployMachineGunTime; MyEHandle m_pNearestBomb; // "capture" bomb diff --git a/utils/RCBot2_meta/bot_dod_mod.cpp b/utils/RCBot2_meta/bot_dod_mod.cpp index 8dc86680a..c84e76ff9 100644 --- a/utils/RCBot2_meta/bot_dod_mod.cpp +++ b/utils/RCBot2_meta/bot_dod_mod.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -45,19 +47,27 @@ #include "bot_waypoint_locations.h" #include "bot_perceptron.h" -edict_t *CDODMod::m_pResourceEntity = NULL; +#include +#include + + //Ignores the min/max macros in the windows headers +//#if SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_BMS +#include "valve_minmax_off.h" +//#endif + +edict_t *CDODMod::m_pResourceEntity = nullptr; CDODFlags CDODMod::m_Flags; -edict_t * CDODMod::m_pPlayerResourceEntity = NULL; +edict_t * CDODMod::m_pPlayerResourceEntity = nullptr; float CDODMod::m_fMapStartTime = 0.0f; -edict_t * CDODMod::m_pGameRules = NULL; +edict_t * CDODMod::m_pGameRules = nullptr; int CDODMod::m_iMapType = 0; bool CDODMod::m_bCommunalBombPoint = false; int CDODMod::m_iBombAreaAllies = 0; int CDODMod::m_iBombAreaAxis = 0; //CPerceptron *CDODMod::gNetAttackOrDefend = NULL; float CDODMod::fAttackProbLookUp[MAX_DOD_FLAGS+1][MAX_DOD_FLAGS+1]; -vector CDODMod::m_BombWaypoints; -vector CDODMod::m_BreakableWaypoints; +std::vector CDODMod::m_BombWaypoints; +std::vector CDODMod::m_BreakableWaypoints; eDODVoiceCommand_t g_DODVoiceCommands[DOD_VC_INVALID] = @@ -96,106 +106,102 @@ eDODVoiceCommand_t g_DODVoiceCommands[DOD_VC_INVALID] = // // Returns true if team can go to waypoint -bool CDODMod :: checkWaypointForTeam(CWaypoint *pWpt, int iTeam) +bool CDODMod :: checkWaypointForTeam(CWaypoint *pWpt, const int iTeam) { - return (!pWpt->hasFlag(CWaypointTypes::W_FL_NOALLIES)||(iTeam!=TEAM_ALLIES))&&(!pWpt->hasFlag(CWaypointTypes::W_FL_NOAXIS)||(iTeam!=TEAM_AXIS)); + return (!pWpt->hasFlag(CWaypointTypes::W_FL_NOALLIES)||iTeam!=TEAM_ALLIES)&&(!pWpt->hasFlag(CWaypointTypes::W_FL_NOAXIS)||iTeam!=TEAM_AXIS); } -bool CDODMod :: shouldAttack ( int iTeam ) +bool CDODMod :: shouldAttack (const int iTeam) // uses the perceptron to return probability of attack { - static short int iFlags_0; - static short int iFlags_1; - static short int iNumFlags; - + static int iFlags_0; + static int iFlags_1; + static int iNumFlags; iNumFlags = m_Flags.getNumFlags(); - iFlags_0 = (int) (((float)m_Flags.getNumFlagsOwned(iTeam == TEAM_ALLIES ? TEAM_AXIS : TEAM_ALLIES) / iNumFlags)*MAX_DOD_FLAGS); - iFlags_1 = (int) (((float)m_Flags.getNumFlagsOwned(iTeam) / iNumFlags)*MAX_DOD_FLAGS); + iFlags_0 = m_Flags.getNumFlagsOwned(iTeam == TEAM_ALLIES ? TEAM_AXIS : TEAM_ALLIES) / + (iNumFlags * MAX_DOD_FLAGS); + + iFlags_1 = m_Flags.getNumFlagsOwned(iTeam) / (iNumFlags * MAX_DOD_FLAGS); - return randomFloat(0.0,1.0) < fAttackProbLookUp[iFlags_0][iFlags_1];//gNetAttackOrDefend->getOutput(); + return randomFloat(0.0f,1.0f) < fAttackProbLookUp[iFlags_0][iFlags_1];//gNetAttackOrDefend->getOutput(); } + //////////////////////////////////////////////// -void CDODMod :: initMod () +void CDODMod::initMod() { ///------------------------------------------------- - CBotGlobals::botMessage(NULL,0,"Training DOD:S capture decision 'NN' ... hold on..."); + CBotGlobals::botMessage(nullptr, 0, "Training DOD:S capture decision 'NN' ... hold on..."); - CBotNeuralNet *nn = new CBotNeuralNet(2,2,2,1,0.4f); + const CBotNeuralNet nn(2, 2, 2, 1, 0.4f); - CTrainingSet *tset = new CTrainingSet(2,1,4); + CTrainingSet tset(2, 1, 4); - tset->setScale(0.0,1.0); + tset.setScale(0.0f, 1.0f); - tset->addSet(); - tset->in(1.0/5); // E - enemy flag ratio - tset->in(1.0/5); // T - team flag ratio - tset->out(0.9f); // probability of attack + tset.addSet(); + tset.in(1.0f / 5); // E - enemy flag ratio + tset.in(1.0f / 5); // T - team flag ratio + tset.out(0.9f); // probability of attack - tset->addSet(); - tset->in(4.0/5); // E - enemy flag ratio - tset->in(1.0/5); // T - team flag ratio - tset->out(0.2f); // probability of attack (mostly defend) + tset.addSet(); + tset.in(4.0f / 5); // E - enemy flag ratio + tset.in(1.0f / 5); // T - team flag ratio + tset.out(0.2f); // probability of attack (mostly defend) - tset->addSet(); - tset->in(1.0/5); // E - enemy flag ratio - tset->in(4.0/5); // T - team flag ratio - tset->out(0.9f); // probability of attack + tset.addSet(); + tset.in(1.0f / 5); // E - enemy flag ratio + tset.in(4.0f / 5); // T - team flag ratio + tset.out(0.9f); // probability of attack - tset->addSet(); - tset->in(0.5f); // E - enemy flag ratio - tset->in(0.5f); // T - team flag ratio - tset->out(0.6f); // probability of attack + tset.addSet(); + tset.in(0.5f); // E - enemy flag ratio + tset.in(0.5f); // T - team flag ratio + tset.out(0.6f); // probability of attack - nn->batch_train(tset,1000); + nn.batch_train(&tset, 1000); // create look up table for probabilities - for ( short int i = 0; i <= MAX_DOD_FLAGS; i ++ ) + for (short i = 0; i <= MAX_DOD_FLAGS; i++) { - for ( short int j = 0; j <= MAX_DOD_FLAGS; j ++ ) + for (short j = 0; j <= MAX_DOD_FLAGS; j++) { - tset->init(); - tset->addSet(); - tset->in(((float)i) / MAX_DOD_FLAGS); - tset->in(((float)j) / MAX_DOD_FLAGS); - nn->execute(tset->getBatches()->in,&(fAttackProbLookUp[i][j]),0.0f,1.0f); + tset.init(); + tset.addSet(); + tset.in(i / static_cast(MAX_DOD_FLAGS)); + tset.in(j / static_cast(MAX_DOD_FLAGS)); + nn.execute(tset.getBatches()->in, &fAttackProbLookUp[i][j], 0.0f, 1.0f); } } - tset->freeMemory(); - delete tset; - delete nn; - - CBotGlobals::botMessage(NULL,0,"... done!"); -///------------------------------------------------- + tset.freeMemory(); + CBotGlobals::botMessage(nullptr, 0, "... done!"); + ///------------------------------------------------- - CBots::controlBotSetup(true); - - CWeapons::loadWeapons((m_szWeaponListName == NULL) ? "DOD" : m_szWeaponListName, DODWeaps); + CWeapons::loadWeapons(m_szWeaponListName == nullptr ? "DOD" : m_szWeaponListName, DODWeaps.data()); //CWeapons::loadWeapons("DOD", DODWeaps); /* for ( i = 0; i < DOD_WEAPON_MAX; i ++ ) CWeapons::addWeapon(new CWeapon(DODWeaps[i]));*/ - m_pResourceEntity = NULL; + m_pResourceEntity = nullptr; } void CDODMod :: mapInit () { CBotMod::mapInit(); - m_pResourceEntity = NULL; - m_pGameRules = NULL; - m_pPlayerResourceEntity = NULL; + m_pResourceEntity = nullptr; + m_pGameRules = nullptr; + m_pPlayerResourceEntity = nullptr; m_Flags.init(); m_fMapStartTime = engine->Time(); m_iMapType = DOD_MAPTYPE_UNKNOWN; m_bCommunalBombPoint = false; } - float CDODMod::getMapStartTime () { //if ( !m_pGameRules ) @@ -210,46 +216,35 @@ int CDODMod::getHighestScore () return 0; int highest = 0; - int score; - short int i = 0; - edict_t *edict; - for ( i = 1; i <= gpGlobals->maxClients; i ++ ) + for ( int i = 1; i <= gpGlobals->maxClients; i ++ ) { - edict = INDEXENT(i); + edict_t* edict = INDEXENT(i); if ( edict && CBotGlobals::entityIsValid(edict) ) { - score = (short int)getScore(edict); - - if ( score > highest ) - { - highest = score; - } + const int score = static_cast(getScore(edict)); + + highest = std::max(score, highest); } } return highest; } -bool CDODFlags::isTeamMateDefusing ( edict_t *pIgnore, int iTeam, int id ) +bool CDODFlags::isTeamMateDefusing (const edict_t *pIgnore, const int iTeam, const int id) const { - if ( m_pBombs[id][0] != NULL ) + if ( m_pBombs[id][0] != nullptr) return isTeamMateDefusing(pIgnore,iTeam,CBotGlobals::entityOrigin(m_pBombs[id][0])); return false; } -bool CDODFlags::isTeamMateDefusing ( edict_t *pIgnore, int iTeam, Vector vOrigin ) +bool CDODFlags::isTeamMateDefusing (const edict_t *pIgnore, const int iTeam, const Vector& vOrigin) { - int i; - edict_t *pPlayer; - IPlayerInfo *pPlayerinfo; - CBotCmd cmd; - - for ( i = 1; i <= gpGlobals->maxClients; i ++ ) + for ( int i = 1; i <= gpGlobals->maxClients; i ++ ) { - pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(i); if ( pIgnore == pPlayer ) continue; @@ -257,10 +252,10 @@ bool CDODFlags::isTeamMateDefusing ( edict_t *pIgnore, int iTeam, Vector vOrigin if ( !CBotGlobals::entityIsValid(pPlayer) ) continue; - pPlayerinfo = playerinfomanager->GetPlayerInfo(pPlayer); - cmd = pPlayerinfo->GetLastUserCommand(); + IPlayerInfo* pPlayerinfo = playerinfomanager->GetPlayerInfo(pPlayer); + const CBotCmd cmd = pPlayerinfo->GetLastUserCommand(); - if ( CClassInterface::isPlayerDefusingBomb_DOD(pPlayer) || (cmd.buttons & IN_USE) ) + if ( CClassInterface::isPlayerDefusingBomb_DOD(pPlayer) || cmd.buttons & IN_USE ) { if ( CClassInterface::getTeam(pPlayer) != iTeam ) continue; @@ -275,15 +270,11 @@ bool CDODFlags::isTeamMateDefusing ( edict_t *pIgnore, int iTeam, Vector vOrigin return false; } - -bool CDODFlags::isTeamMatePlanting ( edict_t *pIgnore, int iTeam, Vector vOrigin ) +bool CDODFlags::isTeamMatePlanting (const edict_t *pIgnore, const int iTeam, const Vector& vOrigin) { - int i; - edict_t *pPlayer; - - for ( i = 1; i <= gpGlobals->maxClients; i ++ ) + for ( int i = 1; i <= gpGlobals->maxClients; i ++ ) { - pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(i); if ( pIgnore == pPlayer ) continue; @@ -306,7 +297,7 @@ bool CDODFlags::isTeamMatePlanting ( edict_t *pIgnore, int iTeam, Vector vOrigin return false; } -bool CDODFlags::isTeamMatePlanting ( edict_t *pIgnore, int iTeam, int id ) +bool CDODFlags::isTeamMatePlanting (const edict_t *pIgnore, const int iTeam, const int id) const { if ( m_pBombs[id][0] ) return isTeamMatePlanting(pIgnore,iTeam,CBotGlobals::entityOrigin(m_pBombs[id][0])); @@ -314,13 +305,13 @@ bool CDODFlags::isTeamMatePlanting ( edict_t *pIgnore, int iTeam, int id ) return false; } -int CDODFlags::findNearestObjective ( Vector vOrigin ) +int CDODFlags::findNearestObjective (const Vector& vOrigin) const { float fNearest = 1024.0f; float fDistance; int iNearest = -1; - for ( short int i = 0; i < m_iNumControlPoints; i ++ ) + for (int i = 0; i < m_iNumControlPoints; i++) { if ( m_iWaypoint[i] != -1 ) { @@ -333,66 +324,61 @@ int CDODFlags::findNearestObjective ( Vector vOrigin ) } return iNearest; - } // return the flag with the least danger (randomly) -bool CDODFlags::getRandomEnemyControlledFlag ( CBot *pBot, Vector *position, int iTeam, int *id ) +bool CDODFlags::getRandomEnemyControlledFlag (const CBot *pBot, Vector *position, const int iTeam, int *id) const { - IBotNavigator *pNav; - float fTotal; - float fRand; - if ( id ) *id = -1; - pNav = pBot->getNavigator(); + IBotNavigator* pNav = pBot->getNavigator(); - fTotal = 0.0f; + float fTotal = 0.0f; - for ( short int i = 0; i < m_iNumControlPoints; i ++ ) + for (int i = 0; i < m_iNumControlPoints; i++) { if ( m_iWaypoint[i] != -1 ) { - if ( ( m_pFlags[i] == NULL ) || ( m_iOwner[i] == iTeam ) ) + if (m_pFlags[i] == nullptr || m_iOwner[i] == iTeam) continue; - if ( (iTeam == TEAM_ALLIES) && (m_iAlliesReqCappers[i] == 0) ) + if ( iTeam == TEAM_ALLIES && m_iAlliesReqCappers[i] == 0 ) continue; - if ( (iTeam == TEAM_AXIS) && (m_iAxisReqCappers[i] == 0) ) + if ( iTeam == TEAM_AXIS && m_iAxisReqCappers[i] == 0 ) continue; if ( iTeam == TEAM_ALLIES ) - fTotal += (((MAX_BELIEF + 1.0f) - pNav->getBelief(m_iWaypoint[i])) / MAX_BELIEF) * (m_iNumAllies[i]+1); + fTotal += (MAX_BELIEF + 1.0f - pNav->getBelief(m_iWaypoint[i])) / MAX_BELIEF * static_cast(m_iNumAllies[i] + 1); else - fTotal += (((MAX_BELIEF + 1.0f) - pNav->getBelief(m_iWaypoint[i])) / MAX_BELIEF) * (m_iNumAxis[i]+1); + fTotal += (MAX_BELIEF + 1.0f - pNav->getBelief(m_iWaypoint[i])) / MAX_BELIEF * static_cast(m_iNumAxis[i] + 1); } } if ( fTotal == 0.0f ) return false; - fRand = randomFloat(0,fTotal); + const float fRand = randomFloat(0, fTotal); fTotal = 0.0f; - for ( short int i = 0; i < m_iNumControlPoints; i ++ ) + for (int i = 0; i < m_iNumControlPoints; i++) { if ( m_iWaypoint[i] != -1 ) { - if ( ( m_pFlags[i] == NULL ) || ( m_iOwner[i] == iTeam ) ) + if ( m_pFlags[i] == nullptr || m_iOwner[i] == iTeam ) continue; - if ( (iTeam == TEAM_ALLIES) && (m_iAlliesReqCappers[i] == 0) ) + if ( iTeam == TEAM_ALLIES && m_iAlliesReqCappers[i] == 0 ) continue; - if ( (iTeam == TEAM_AXIS) && (m_iAxisReqCappers[i] == 0) ) + if ( iTeam == TEAM_AXIS && m_iAxisReqCappers[i] == 0 ) continue; if ( iTeam == TEAM_ALLIES ) - fTotal += (((MAX_BELIEF + 1.0f) - pNav->getBelief(m_iWaypoint[i])) / MAX_BELIEF) * (m_iNumAllies[i]+1); + fTotal += (MAX_BELIEF + 1.0f - pNav->getBelief(m_iWaypoint[i])) / MAX_BELIEF * static_cast(m_iNumAllies[i] + 1); else - fTotal += (((MAX_BELIEF + 1.0f) - pNav->getBelief(m_iWaypoint[i])) / MAX_BELIEF) * (m_iNumAxis[i]+1); + fTotal += (MAX_BELIEF + 1.0f - pNav->getBelief(m_iWaypoint[i])) / MAX_BELIEF * static_cast(m_iNumAxis[i] + 1); } if ( fRand <= fTotal ) @@ -407,67 +393,74 @@ bool CDODFlags::getRandomEnemyControlledFlag ( CBot *pBot, Vector *position, int return false; } -bool CDODFlags::getRandomBombToDefuse ( Vector *position, int iTeam, edict_t **pBombTarget, int *id ) +bool CDODFlags::getRandomBombToDefuse(Vector& position, int iTeam, edict_t*& pBombTarget, int* id) const { - vector iPossible; - short int j; - int selection; - - if ( id ) + if (id) *id = -1; - // more possibility to return bomb targets with no bomb already - for ( short int i = 0; i < m_iNumControlPoints; i ++ ) - { - if ( (m_iOwner[i] == iTeam) && isBombPlanted(i) && !isBombBeingDefused(i) && (m_pBombs[i][0] != NULL) ) - for ( j = 0; j < getNumBombsRequired(i); j ++ ) { iPossible.push_back(i); } - } + std::vector possibleTargets; - if ( iPossible.size() > 0 ) + // Collect possible bomb targets + for (int i = 0; i < m_iNumControlPoints; ++i) { - selection = iPossible[randomInt(0,iPossible.size()-1)]; - - if ( m_pBombs[selection][1] != NULL ) + if (m_iOwner[i] == iTeam && isBombPlanted(i) && !isBombBeingDefused(i) && m_pBombs[i][0] != nullptr) { - if ( CClassInterface::getDODBombState(m_pBombs[selection][1]) == DOD_BOMB_STATE_ACTIVE ) - *pBombTarget = m_pBombs[selection][1]; - else - *pBombTarget = m_pBombs[selection][0]; + for (int j = 0; j < getNumBombsRequired(i); ++j) + { + possibleTargets.emplace_back(i); + } } - else - *pBombTarget = m_pBombs[selection][0]; + } + if (possibleTargets.empty()) + { + return false; + } - *position = CBotGlobals::entityOrigin(*pBombTarget); + // Select a random target + const int selection = possibleTargets[randomInt(0, static_cast(possibleTargets.size()) - 1)]; - if ( id ) // area of the capture point - *id = selection; + // Determine the bomb target + if (m_pBombs[selection][1] != nullptr && + CClassInterface::getDODBombState(m_pBombs[selection][1]) == DOD_BOMB_STATE_ACTIVE) + { + pBombTarget = m_pBombs[selection][1]; + } + else + { + pBombTarget = m_pBombs[selection][0]; + } + + // Set position and ID + position = CBotGlobals::entityOrigin(pBombTarget); + + if (id) + { + *id = selection; } - return (iPossible.size()>0); + return true; } //return random bomb with highest danger -bool CDODFlags:: getRandomBombToDefend ( CBot *pBot, Vector *position, int iTeam, edict_t **pBombTarget, int *id ) +bool CDODFlags:: getRandomBombToDefend ( CBot *pBot, Vector *position, const int iTeam, edict_t **pBombTarget, int *id ) const { - vector iPossible; - short int j; - int selection; + std::vector iPossible; // int is control point entry if ( id ) *id = -1; // more possibility to return bomb targets with no bomb already - for ( short int i = 0; i < m_iNumControlPoints; i ++ ) + for (int i = 0; i < m_iNumControlPoints; i++) { - if ( (m_iOwner[i] != iTeam) && isBombPlanted(i) && (m_pBombs[i][0] != NULL) ) - for ( j = 0; j < getNumBombsRequired(i); j ++ ) { iPossible.push_back(i); } + if ( m_iOwner[i] != iTeam && isBombPlanted(i) && m_pBombs[i][0] != nullptr) + for ( int j = 0; j < getNumBombsRequired(i); j ++ ) { iPossible.emplace_back(i); } } - if ( iPossible.size() > 0 ) + if (!iPossible.empty()) { - selection = iPossible[randomInt(0,iPossible.size()-1)]; + const int selection = iPossible[randomInt(0, static_cast(iPossible.size()) - 1)]; - if ( m_pBombs[selection][1] != NULL ) + if ( m_pBombs[selection][1] != nullptr) { if ( CClassInterface::getDODBombState(m_pBombs[selection][1]) != 0 ) *pBombTarget = m_pBombs[selection][1]; @@ -483,78 +476,72 @@ bool CDODFlags:: getRandomBombToDefend ( CBot *pBot, Vector *position, int iTeam *id = selection; } - return (iPossible.size()>0); + return !iPossible.empty(); } -// return rnaomd flag with lowest danger -bool CDODFlags:: getRandomBombToPlant ( CBot *pBot, Vector *position, int iTeam, edict_t **pBombTarget, int *id ) +// return random flag with lowest danger +bool CDODFlags::getRandomBombToPlant(CBot* pBot, Vector& position, const int iTeam, edict_t*& pBombTarget, int* id) const { - float fTotal; - float fRand; - - IBotNavigator *pNav; - -// short int j; - int selection; + assert(pBot != nullptr); - if ( id ) + if (id) *id = -1; - selection = -1; + IBotNavigator* pNav = pBot->getNavigator(); - pNav = pBot->getNavigator(); + assert(pNav != nullptr); - fTotal = 0.0f; + struct BombTargetCandidate + { + edict_t* target; + float weight; + int index; + }; - for ( short int i = 0; i < m_iNumControlPoints; i ++ ) + std::vector candidates; + float totalWeight = 0.0f; + + for (int i = 0; i < m_iNumControlPoints; ++i) { - // if no waypoint -- can't go there - if ( m_iWaypoint[i] != -1 ) + if (m_iWaypoint[i] == -1 || m_pBombs[i][0] == nullptr || m_iOwner[i] == iTeam || + isBombPlanted(i) || m_iBombsRemaining[i] == 0) { - if ( ( m_pBombs[i][0] == NULL ) || ( m_iOwner[i] == iTeam ) || isBombPlanted(i) || (m_iBombsRemaining[i] == 0) ) - continue; + continue; + } + + const float belief = pNav->getBelief(m_iWaypoint[i]); + const float weight = (MAX_BELIEF + 1.0f - belief) / MAX_BELIEF * static_cast(getNumBombsRemaining(i)); + + totalWeight += weight; + edict_t* target = m_pBombs[i][0]; - fTotal += (((MAX_BELIEF + 1.0f) - pNav->getBelief(m_iWaypoint[i])) / MAX_BELIEF) * getNumBombsRemaining(i); + if (m_pBombs[i][1] != nullptr && CClassInterface::getDODBombState(m_pBombs[i][1]) == DOD_BOMB_STATE_AVAILABLE) + { + target = m_pBombs[i][1]; } + + candidates.push_back({ target, weight, i }); //TODO: maybe use emplace_back? [APG]RoboCop[CL] } - if ( fTotal == 0.0f ) + if (candidates.empty()) + { return false; + } - fRand = randomFloat(0.0f,fTotal); + const float randomValue = randomFloat(0.0f, totalWeight); + float cumulativeWeight = 0.0f; - fTotal = 0.0f; - - for ( short int i = 0; i < m_iNumControlPoints; i ++ ) + for (const auto& [target, weight, index] : candidates) { - if ( m_iWaypoint[i] != -1 ) - { - if ( ( m_pBombs[i][0] == NULL ) || ( m_iOwner[i] == iTeam ) || isBombPlanted(i) ) - continue; - - fTotal += (((MAX_BELIEF + 1.0f) - pNav->getBelief(m_iWaypoint[i])) / MAX_BELIEF) * getNumBombsRemaining(i); - } - else - fTotal += 0.1f; + cumulativeWeight += weight; - if ( fRand <= fTotal ) + if (randomValue <= cumulativeWeight) { - selection = i; - - if ( m_pBombs[selection][1] != NULL ) - { - if ( CClassInterface::getDODBombState(m_pBombs[selection][1]) == DOD_BOMB_STATE_AVAILABLE ) - *pBombTarget = m_pBombs[selection][1]; - else - *pBombTarget = m_pBombs[selection][0]; - } - else - *pBombTarget = m_pBombs[selection][0]; - - *position = CBotGlobals::entityOrigin(*pBombTarget); + pBombTarget = target; + position = CBotGlobals::entityOrigin(pBombTarget); - if ( id ) // area of the capture point - *id = selection; + if (id) + *id = index; return true; } @@ -563,51 +550,46 @@ bool CDODFlags:: getRandomBombToPlant ( CBot *pBot, Vector *position, int iTeam, return false; } - -bool CDODFlags::getRandomTeamControlledFlag ( CBot *pBot, Vector *position, int iTeam, int *id ) +bool CDODFlags::getRandomTeamControlledFlag (const CBot *pBot, Vector *position, const int iTeam, int *id) const { - IBotNavigator *pNav; - float fTotal; - float fRand; - if ( id ) *id = -1; - pNav = pBot->getNavigator(); + IBotNavigator* pNav = pBot->getNavigator(); - fTotal = 0.0f; + float fTotal = 0.0f; - for ( short int i = 0; i < m_iNumControlPoints; i ++ ) + for (int i = 0; i < m_iNumControlPoints; i++) { if ( m_iWaypoint[i] != -1 ) { - if ( ( m_pFlags[i] == NULL ) || ( m_iOwner[i] != iTeam ) ) + if ( m_pFlags[i] == nullptr || m_iOwner[i] != iTeam ) continue; if ( iTeam == TEAM_AXIS ) - fTotal += ((pNav->getBelief(m_iWaypoint[i])+MAX_BELIEF)/(MAX_BELIEF*2)) * (m_iNumAllies[i]+1); + fTotal += (pNav->getBelief(m_iWaypoint[i])+MAX_BELIEF)/(MAX_BELIEF*2) * static_cast(m_iNumAllies[i] + 1); else - fTotal += ((pNav->getBelief(m_iWaypoint[i])+MAX_BELIEF)/(MAX_BELIEF*2)) * (m_iNumAxis[i]+1); + fTotal += (pNav->getBelief(m_iWaypoint[i])+MAX_BELIEF)/(MAX_BELIEF*2) * static_cast(m_iNumAxis[i] + 1); } } if ( fTotal == 0.0f ) return false; - fRand = randomFloat(0,fTotal); + const float fRand = randomFloat(0, fTotal); fTotal = 0.0f; - for ( short int i = 0; i < m_iNumControlPoints; i ++ ) + for (int i = 0; i < m_iNumControlPoints; i++) { if ( m_iWaypoint[i] != -1 ) { - if ( ( m_pFlags[i] == NULL ) || ( m_iOwner[i] != iTeam ) ) + if ( m_pFlags[i] == nullptr || m_iOwner[i] != iTeam ) continue; if ( iTeam == TEAM_AXIS ) - fTotal += ((pNav->getBelief(m_iWaypoint[i])+MAX_BELIEF)/(MAX_BELIEF*2)) * (m_iNumAllies[i]+1); + fTotal += (pNav->getBelief(m_iWaypoint[i])+MAX_BELIEF)/(MAX_BELIEF*2) * static_cast(m_iNumAllies[i] + 1); else - fTotal += ((pNav->getBelief(m_iWaypoint[i])+MAX_BELIEF)/(MAX_BELIEF*2)) * (m_iNumAxis[i]+1); + fTotal += (pNav->getBelief(m_iWaypoint[i])+MAX_BELIEF)/(MAX_BELIEF*2) * static_cast(m_iNumAxis[i] + 1); } if ( fRand <= fTotal ) @@ -624,7 +606,8 @@ bool CDODFlags::getRandomTeamControlledFlag ( CBot *pBot, Vector *position, int void CDODMod::freeMemory() { - + m_BombWaypoints.clear(); + m_BreakableWaypoints.clear(); } // returns map type @@ -636,7 +619,7 @@ int CDODFlags::setup(edict_t *pResourceEntity) m_iNumControlPoints = 0; - memset(m_bBombPlanted,0,sizeof(bool)*MAX_DOD_FLAGS); // all false + std::memset(m_bBombPlanted,0,sizeof(bool)*MAX_DOD_FLAGS); // all false //CPsVisible = CClassInterface::getDODCPVisible(pResourceEntity); @@ -651,32 +634,30 @@ int CDODFlags::setup(edict_t *pResourceEntity) } - short int i,j; - -// string_t model; -// const char *modelname; -// bool bVisible; + // string_t model; + // const char *modelname; + // bool bVisible; // find the edicts of the flags using the origin and classname - for ( j = 0; j < m_iNumControlPoints; j ++ ) + for ( int j = 0; j < m_iNumControlPoints; j ++ ) { edict_t *pent; Vector vOrigin; - i = gpGlobals->maxClients; + int i = gpGlobals->maxClients; // find visible flags -- with a model - while ( (++i < gpGlobals->maxEntities) && (m_pFlags[j] == NULL ) ) + while ( ++i < gpGlobals->maxEntities && m_pFlags[j] == nullptr) { pent = INDEXENT(i); if ( !pent || pent->IsFree() ) continue; - if ( strcmp(pent->GetClassName(),DOD_CLASSNAME_CONTROLPOINT) == 0 ) + if ( std::strcmp(pent->GetClassName(),DOD_CLASSNAME_CONTROLPOINT) == 0 ) { vOrigin = CBotGlobals::entityOrigin(pent); @@ -702,7 +683,7 @@ int CDODFlags::setup(edict_t *pResourceEntity) } // no flag for this point - if ( m_pFlags[j] == NULL ) + if ( m_pFlags[j] == nullptr) continue; // don't need to check for bombs @@ -712,20 +693,20 @@ int CDODFlags::setup(edict_t *pResourceEntity) // find bombs near flag i = gpGlobals->maxClients; - while ( (++i < gpGlobals->maxEntities) && ((m_pBombs[j][0]==NULL)||(m_pBombs[j][1]==NULL)) ) + while ( ++i < gpGlobals->maxEntities && (m_pBombs[j][0]== nullptr ||m_pBombs[j][1]== nullptr) ) { pent = INDEXENT(i); if ( !pent || pent->IsFree() ) continue; - if ( strcmp(pent->GetClassName(),DOD_CLASSNAME_BOMBTARGET) == 0 ) + if ( std::strcmp(pent->GetClassName(),DOD_CLASSNAME_BOMBTARGET) == 0 ) { vOrigin = CBotGlobals::entityOrigin(pent); if ( (vOrigin - m_vCPPositions[j]).Length() < 400.0f ) { - if ( m_pBombs[j][0] == NULL ) + if ( m_pBombs[j][0] == nullptr) { m_pBombs[j][0] = pent; } @@ -737,14 +718,14 @@ int CDODFlags::setup(edict_t *pResourceEntity) } // find waypoints - for ( short int i = 0; i < m_iNumControlPoints; i ++ ) + for ( int i = 0; i < m_iNumControlPoints; i ++ ) { // if we don't know any cap waypoint yet here find one if ( m_iWaypoint[i] == -1 ) { // get any nearby waypoint so the bot knows which waypoint to get danger from // look for the nearest waypoint which is a cap point - m_iWaypoint[i] = CWaypointLocations::NearestWaypoint(m_vCPPositions[i],400.0f,-1,false,false,false,0,false,0,false,false,Vector(0,0,0),CWaypointTypes::W_FL_CAPPOINT ); + m_iWaypoint[i] = CWaypointLocations::NearestWaypoint(m_vCPPositions[i],400.0f,-1,false,false,false,nullptr,false,0,false,false,Vector(0,0,0),CWaypointTypes::W_FL_CAPPOINT ); // still no waypoint, search for any capture waypoint with the same area if ( m_iWaypoint[i] == -1 ) @@ -758,13 +739,13 @@ int CDODFlags::setup(edict_t *pResourceEntity) m_iNumAlliesBombsOnMap = getNumPlantableBombs(TEAM_ALLIES); // sometimes m_iNumControlPoints is larger than it should be. check the number of flags and bombs we found on the map - for ( short int i = 0; i < m_iNumControlPoints; i ++ ) + for ( int i = 0; i < m_iNumControlPoints; i ++ ) { - if ( m_pFlags[i] != NULL ) + if ( m_pFlags[i] != nullptr) iNumFlags++; - if ( m_pBombs[i][0] != NULL ) + if ( m_pBombs[i][0] != nullptr) iNumBombCaps++; - if ( m_pBombs[i][1] != NULL ) + if ( m_pBombs[i][1] != nullptr) iNumBombCaps++; } @@ -787,68 +768,65 @@ int CDODMod ::getScore(edict_t *pPlayer) return 0; } -edict_t *CDODMod :: getBreakable ( CWaypoint *pWpt ) +edict_t *CDODMod :: getBreakable (const CWaypoint *pWpt) { - register unsigned short int size = m_BreakableWaypoints.size(); + const std::size_t size = m_BreakableWaypoints.size(); - for ( register unsigned short int i = 0; i < size; i ++ ) + for (std::size_t i = 0; i < size; i++) { if ( m_BreakableWaypoints[i].pWaypoint == pWpt ) return m_BreakableWaypoints[i].pEdict; } - return NULL; + return nullptr; } -edict_t *CDODMod :: getBombTarget ( CWaypoint *pWpt ) +edict_t *CDODMod :: getBombTarget (const CWaypoint *pWpt) { - register unsigned short int size = m_BombWaypoints.size(); + const std::size_t size = m_BombWaypoints.size(); - for ( register unsigned short int i = 0; i < size; i ++ ) + for (std::size_t i = 0; i < size; i++) { if ( m_BombWaypoints[i].pWaypoint == pWpt ) return m_BombWaypoints[i].pEdict; } - return NULL; + return nullptr; } -void CDODMod ::roundStart() +void CDODMod::roundStart() { if ( !m_pResourceEntity ) - m_pResourceEntity = CClassInterface::FindEntityByNetClass(gpGlobals->maxClients+1, "CDODObjectiveResource"); + m_pResourceEntity = CClassInterface::FindEntityByNetClass(gpGlobals->maxClients + 1, "CDODObjectiveResource"); if ( !m_pPlayerResourceEntity ) - m_pPlayerResourceEntity = CClassInterface::FindEntityByNetClass(gpGlobals->maxClients+1, "CDODPlayerResource"); + m_pPlayerResourceEntity = CClassInterface::FindEntityByNetClass(gpGlobals->maxClients + 1, "CDODPlayerResource"); if ( !m_pGameRules ) - m_pGameRules = CClassInterface::FindEntityByNetClass(gpGlobals->maxClients+1, "CDODGameRulesProxy"); + m_pGameRules = CClassInterface::FindEntityByNetClass(gpGlobals->maxClients + 1, "CDODGameRulesProxy"); // find main map type m_iMapType = m_Flags.setup(m_pResourceEntity); //if ( m_iMapType == DOD_MAPTYPE_UNKNOWN ) //{ - if ( CClassInterface::FindEntityByNetClass(gpGlobals->maxClients+1,"CDODBombDispenserMapIcon") != NULL ) + if ( CClassInterface::FindEntityByNetClass(gpGlobals->maxClients + 1,"CDODBombDispenserMapIcon") != nullptr) { - CWaypoint *pWaypointAllies; - CWaypoint *pWaypointAxis; - // add bitmask m_iMapType |= DOD_MAPTYPE_BOMB; -/* + /* if ( m_iMapType == DOD_MAPTYPE_FLAG) - CRCBotPlugin::HudTextMessage(CClients::get(0)->getPlayer(),"RCBot detected Flag map","RCBot2","RCbot2 detected a flag map"); + CRCBotPlugin::HudTextMessage(CClients::get(0)->getPlayer(),"RCBot detected Flag map","RCBot2","RCBot2 detected a flag map"); else if ( m_iMapType == DOD_MAPTYPE_BOMB ) - CRCBotPlugin::HudTextMessage(CClients::get(0)->getPlayer(),"RCBot detected bomb map","RCBot2","RCbot2 detected a bomb map"); + CRCBotPlugin::HudTextMessage(CClients::get(0)->getPlayer(),"RCBot detected bomb map","RCBot2","RCBot2 detected a bomb map"); else if ( m_iMapType == 3 ) - CRCBotPlugin::HudTextMessage(CClients::get(0)->getPlayer(),"RCBot detected flag map with bombs ","RCBot2","RCbot2 detected a flag capture map with bombs"); + CRCBotPlugin::HudTextMessage(CClients::get(0)->getPlayer(),"RCBot detected flag map with bombs ","RCBot2","RCBot2 detected a flag capture map with bombs"); + */ -*/ - pWaypointAllies = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_BOMBS_HERE,TEAM_ALLIES); - pWaypointAxis = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_BOMBS_HERE,TEAM_AXIS); + const CWaypoint* pWaypointAllies = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_BOMBS_HERE,TEAM_ALLIES); + const CWaypoint* pWaypointAxis = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_BOMBS_HERE,TEAM_AXIS); if ( pWaypointAllies && pWaypointAxis ) { - m_bCommunalBombPoint = (pWaypointAllies->getArea()>0) || (pWaypointAxis->getArea()>0); + m_bCommunalBombPoint = pWaypointAllies->getArea() > 0 || pWaypointAxis->getArea() > 0; m_iBombAreaAllies = pWaypointAllies->getArea(); m_iBombAreaAxis = pWaypointAxis->getArea(); @@ -871,14 +849,14 @@ void CDODMod ::roundStart() // find it and add it as a waypoint offset Vector CDODMod :: getGround ( CWaypoint *pWaypoint ) { - for ( unsigned int i = 0; i < m_BombWaypoints.size(); i ++ ) + for (edict_wpt_pair_t& m_BombWaypoint : m_BombWaypoints) { - if ( m_BombWaypoints[i].pWaypoint == pWaypoint ) + if (m_BombWaypoint.pWaypoint == pWaypoint ) { - if ( m_BombWaypoints[i].pEdict ) + if (m_BombWaypoint.pEdict ) { - if ( CClassInterface::getDODBombState(m_BombWaypoints[i].pEdict) == 0 ) - return m_BombWaypoints[i].v_ground; + if ( CClassInterface::getDODBombState(m_BombWaypoint.pEdict) == 0 ) + return m_BombWaypoint.v_ground; break; } @@ -888,11 +866,11 @@ Vector CDODMod :: getGround ( CWaypoint *pWaypoint ) return pWaypoint->getOrigin(); } -void CDODMod :: addWaypointFlags (edict_t *pPlayer, edict_t *pEdict, int *iFlags, int *iArea, float *fMaxDistance ) +void CDODMod :: addWaypointFlags (edict_t *pPlayer, edict_t *pEdict, int *iFlags, int *iArea, float *fMaxDistance) { - if ( isBombMap() ) + if (isBombMap()) { - int id = m_Flags.getBombID(pEdict); + const int id = m_Flags.getBombID(pEdict); if ( id != -1 ) { @@ -901,9 +879,9 @@ void CDODMod :: addWaypointFlags (edict_t *pPlayer, edict_t *pEdict, int *iFlags } } - if ( isFlagMap() ) + if (isFlagMap()) { - int id = m_Flags.getFlagID(pEdict); + const int id = m_Flags.getFlagID(pEdict); if ( id != -1 ) { @@ -911,24 +889,30 @@ void CDODMod :: addWaypointFlags (edict_t *pPlayer, edict_t *pEdict, int *iFlags *iArea = id; } } - } void CDODMod :: modFrame() { - + // Experimental and needs tested with maps [APG]RoboCop[CL] + /*if (!m_pResourceEntity) + m_pResourceEntity = CClassInterface::FindEntityByNetClass(gpGlobals->maxClients+1, "CDODObjectiveResource"); + if ( !m_pPlayerResourceEntity ) + m_pPlayerResourceEntity = CClassInterface::FindEntityByNetClass(gpGlobals->maxClients+1, "CDODPlayerResource"); + if ( !m_pGameRules ) + m_pGameRules = CClassInterface::FindEntityByNetClass(gpGlobals->maxClients+1, "CDODGameRulesProxy");*/ } -int CDODMod ::numClassOnTeam( int iTeam, int iClass ) +int CDODMod ::numClassOnTeam(const int iTeam, const int iClass) { - int i = 0; int num = 0; - edict_t *pEdict; - for ( i = 1; i <= CBotGlobals::numClients(); i ++ ) + for ( int i = 1; i <= CBotGlobals::maxClients(); i ++ ) { - pEdict = INDEXENT(i); + edict_t* pEdict = INDEXENT(i); + + if ( !pEdict ) + continue; if ( CBotGlobals::entityIsValid(pEdict) ) { @@ -943,20 +927,17 @@ int CDODMod ::numClassOnTeam( int iTeam, int iClass ) return num; } -void CDODMod ::clientCommand( edict_t *pEntity, int argc, const char *pcmd, const char *arg1, const char *arg2 ) +void CDODMod ::clientCommand( edict_t *pEntity, const int argc, const char *pcmd, const char *arg1, const char *arg2 ) { if ( argc == 1 ) { - if ( strncmp(pcmd,"voice_",6) == 0 ) + if ( std::strncmp(pcmd,"voice_",6) == 0 ) { - short int i; - // somebody said a voice command - u_VOICECMD vcmd; - - for ( i = 0; i < DOD_VC_INVALID; i ++ ) + for ( byte i = 0; i < DOD_VC_INVALID; i ++ ) { - if ( strcmp(&pcmd[6],g_DODVoiceCommands[i].pcmd) == 0 ) + if ( std::strcmp(&pcmd[6],g_DODVoiceCommands[i].pcmd) == 0 ) { + u_VOICECMD vcmd; vcmd.voicecmd = i; CBroadcastVoiceCommand voicecmd = CBroadcastVoiceCommand(pEntity,vcmd.voicecmd); @@ -970,19 +951,19 @@ void CDODMod ::clientCommand( edict_t *pEntity, int argc, const char *pcmd, cons } } -bool CDODMod :: isBreakableRegistered ( edict_t *pBreakable, int iTeam ) +bool CDODMod :: isBreakableRegistered ( edict_t *pBreakable, const int iTeam ) { static CWaypoint *pWpt; - for ( unsigned int i = 0; i < m_BreakableWaypoints.size(); i ++ ) + for (edict_wpt_pair_t& m_BreakableWaypoint : m_BreakableWaypoints) { - if ( m_BreakableWaypoints[i].pEdict == pBreakable ) + if (m_BreakableWaypoint.pEdict == pBreakable ) { - pWpt = m_BreakableWaypoints[i].pWaypoint; + pWpt = m_BreakableWaypoint.pWaypoint; if ( pWpt->hasFlag(CWaypointTypes::W_FL_NOALLIES) ) return iTeam != TEAM_ALLIES; - else if ( pWpt->hasFlag(CWaypointTypes::W_FL_NOAXIS) ) + if ( pWpt->hasFlag(CWaypointTypes::W_FL_NOAXIS) ) return iTeam != TEAM_AXIS; return true; @@ -992,7 +973,7 @@ bool CDODMod :: isBreakableRegistered ( edict_t *pBreakable, int iTeam ) return false; } -void CDODMod :: getTeamOnlyWaypointFlags ( int iTeam, int *iOn, int *iOff ) +void CDODMod :: getTeamOnlyWaypointFlags (const int iTeam, int *iOn, int *iOff) { if ( iTeam == TEAM_ALLIES ) { @@ -1004,6 +985,4 @@ void CDODMod :: getTeamOnlyWaypointFlags ( int iTeam, int *iOn, int *iOff ) *iOn = CWaypointTypes::W_FL_NOALLIES; *iOff = CWaypointTypes::W_FL_NOAXIS; } - - } diff --git a/utils/RCBot2_meta/bot_ehandle.h b/utils/RCBot2_meta/bot_ehandle.h index 7652178d0..df1fe2704 100644 --- a/utils/RCBot2_meta/bot_ehandle.h +++ b/utils/RCBot2_meta/bot_ehandle.h @@ -31,13 +31,20 @@ #ifndef __RCBOT_EHANDLE_H__ #define __RCBOT_EHANDLE_H__ +#include "edict.h" + + /** + * This is bad and should be nuked. + * The SDK's CBaseHandle should be used instead! -caxanga334 + */ + ////// entity handling in network class MyEHandle { public: MyEHandle () { - m_pEnt = NULL; + m_pEnt = nullptr; m_iSerialNumber = 0; } @@ -53,56 +60,56 @@ class MyEHandle m_iSerialNumber = 0; } - inline bool notValid () { return get() == NULL; } - inline bool isValid () { return get() != NULL; } + bool notValid () { return get() == nullptr; } + bool isValid () { return get() != nullptr; } - inline edict_t *get () + edict_t *get () { if ( m_iSerialNumber && m_pEnt ) { - if ( !m_pEnt->IsFree() && (m_iSerialNumber == m_pEnt->m_NetworkSerialNumber) ) + if ( !m_pEnt->IsFree() && m_iSerialNumber == m_pEnt->m_NetworkSerialNumber ) return m_pEnt; } else if ( m_pEnt ) - m_pEnt = NULL; + m_pEnt = nullptr; - return NULL; + return nullptr; } - inline edict_t *get_old () + edict_t *get_old () const { return m_pEnt; } - inline operator edict_t * const () + operator edict_t * const () { // same as get function (inlined for speed) if ( m_iSerialNumber && m_pEnt ) { - if ( !m_pEnt->IsFree() && (m_iSerialNumber == m_pEnt->m_NetworkSerialNumber) ) + if ( !m_pEnt->IsFree() && m_iSerialNumber == m_pEnt->m_NetworkSerialNumber ) return m_pEnt; } else if ( m_pEnt ) - m_pEnt = NULL; + m_pEnt = nullptr; - return NULL; + return nullptr; } - inline bool operator == ( int a ) + bool operator == (const std::intptr_t a) { - return ((int)get() == a); + return (reinterpret_cast(get()) == static_cast(a)); } - inline bool operator == ( edict_t *pent ) + bool operator == ( edict_t *pent ) { - return (get() == pent); + return get() == pent; } - inline bool operator == ( MyEHandle &other ) + bool operator == ( MyEHandle &other ) { - return (get() == other.get()); + return get() == other.get(); } - inline edict_t * operator = ( edict_t *pent ) + edict_t *operator = ( edict_t *pent ) { m_pEnt = pent; diff --git a/utils/RCBot2_meta/bot_event.h b/utils/RCBot2_meta/bot_event.h index e5b7b8f2b..d7deae680 100644 --- a/utils/RCBot2_meta/bot_event.h +++ b/utils/RCBot2_meta/bot_event.h @@ -34,7 +34,6 @@ #include "bot_const.h" #include -using namespace std; class CBotEventInterface; class IBotEventInterface; @@ -45,44 +44,48 @@ class IGameEvent; class CBotEvent { public: + virtual ~CBotEvent() = default; + CBotEvent() { + m_pActivator = nullptr; m_iEventId = -1; - m_szType = NULL; + m_szType = nullptr; m_iModId = MOD_ANY; } - void setMod ( eModId iModId ) + void setMod (const eModId iModId) { m_iModId = iModId; } - bool forCurrentMod (); + bool forCurrentMod () const; - void setType ( char *szType ); + void setType (const char* szType); - inline bool isType ( const char *szType ); + inline bool isType ( const char *szType ) const; - inline void setActivator ( edict_t *pEdict ) { m_pActivator = pEdict;} + void setActivator ( edict_t *pEdict ) { m_pActivator = pEdict;} - virtual void execute ( IBotEventInterface *pEvent ) { return; } + virtual void execute ( IBotEventInterface *pEvent ) { + } - inline void setEventId ( int iEventId ) + void setEventId (const int iEventId) { m_iEventId = iEventId; } - inline bool isEventId ( int iEventId ) + bool isEventId (const int iEventId) const { - return forCurrentMod() && (m_iEventId == iEventId); + return forCurrentMod() && m_iEventId == iEventId; } - inline bool hasEventId () + bool hasEventId () const { - return (m_iEventId != -1); + return m_iEventId != -1; } - const char *getName () + const char *getName () const { return m_szType; } @@ -103,8 +106,21 @@ class CRoundStartEvent : public CBotEvent setMod(MOD_CSS); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; + +class CRoundFreezeEndEvent : public CBotEvent +{ +public: + CRoundFreezeEndEvent() + { + setType("round_freeze_end"); + setMod(MOD_CSS); + } + + void execute ( IBotEventInterface *pEvent ) override; +}; + class CPostInventoryApplicationTF2 : public CBotEvent { public: @@ -114,7 +130,7 @@ class CPostInventoryApplicationTF2 : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CTF2RoundWinEvent : public CBotEvent @@ -126,7 +142,7 @@ class CTF2RoundWinEvent : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CPlayerHurtEvent : public CBotEvent @@ -137,7 +153,7 @@ class CPlayerHurtEvent : public CBotEvent setType("player_hurt"); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CPlayerDeathEvent : public CBotEvent @@ -148,7 +164,7 @@ class CPlayerDeathEvent : public CBotEvent setType("player_death"); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CBombPickupEvent : public CBotEvent @@ -160,7 +176,19 @@ class CBombPickupEvent : public CBotEvent setMod(MOD_CSS); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; +}; + +class CCSSBombPlantedEvent : public CBotEvent +{ +public: + CCSSBombPlantedEvent() + { + setType("bomb_planted"); + setMod(MOD_CSS); + } + + void execute ( IBotEventInterface *pEvent ) override; }; class CPlayerFootstepEvent : public CBotEvent @@ -171,7 +199,7 @@ class CPlayerFootstepEvent : public CBotEvent setType("player_footstep"); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CPlayerSpawnEvent : public CBotEvent @@ -183,7 +211,7 @@ class CPlayerSpawnEvent : public CBotEvent setMod(MOD_ANY); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CBombDroppedEvent : public CBotEvent @@ -195,7 +223,7 @@ class CBombDroppedEvent : public CBotEvent setMod(MOD_CSS); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class COverTimeBegin : public CBotEvent @@ -207,7 +235,7 @@ class COverTimeBegin : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CPlayerHealed : public CBotEvent @@ -219,7 +247,7 @@ class CPlayerHealed : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CPlayerTeleported : public CBotEvent @@ -231,7 +259,7 @@ class CPlayerTeleported : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CWeaponFireEvent : public CBotEvent @@ -242,7 +270,7 @@ class CWeaponFireEvent : public CBotEvent setType("weapon_fire"); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CTF2ObjectSapped : public CBotEvent @@ -254,7 +282,7 @@ class CTF2ObjectSapped : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CTF2ObjectDestroyed : public CBotEvent @@ -266,7 +294,7 @@ class CTF2ObjectDestroyed : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CTF2PointCaptured : public CBotEvent @@ -278,7 +306,7 @@ class CTF2PointCaptured : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CTF2RoundActive : public CBotEvent @@ -290,7 +318,7 @@ class CTF2RoundActive : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; @@ -304,7 +332,7 @@ class CTF2PointStopCapture : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CTF2PointBlockedCapture : public CBotEvent @@ -316,7 +344,7 @@ class CTF2PointBlockedCapture : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CTF2PointStartCapture : public CBotEvent @@ -328,7 +356,7 @@ class CTF2PointStartCapture : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; @@ -341,7 +369,7 @@ class CTF2MVMWaveFailedEvent : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CTF2MVMWaveCompleteEvent : public CBotEvent @@ -353,7 +381,7 @@ class CTF2MVMWaveCompleteEvent : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CTF2PointStartTouch : public CBotEvent @@ -365,7 +393,7 @@ class CTF2PointStartTouch : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CTF2PointEndTouch : public CBotEvent @@ -377,7 +405,7 @@ class CTF2PointEndTouch : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CTF2RoundStart : public CBotEvent @@ -389,7 +417,7 @@ class CTF2RoundStart : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CTF2SetupFinished : public CBotEvent @@ -401,7 +429,7 @@ class CTF2SetupFinished : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CBulletImpactEvent : public CBotEvent @@ -413,7 +441,7 @@ class CBulletImpactEvent : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CTF2ObjectDestroyedEvent : public CBotEvent @@ -425,7 +453,7 @@ class CTF2ObjectDestroyedEvent : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CTF2BuiltObjectEvent : public CBotEvent @@ -437,7 +465,7 @@ class CTF2BuiltObjectEvent : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CTF2UpgradeObjectEvent : public CBotEvent @@ -449,7 +477,7 @@ class CTF2UpgradeObjectEvent : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CTF2ChangeClass : public CBotEvent @@ -460,29 +488,29 @@ class CTF2ChangeClass : public CBotEvent setType("player_changeclass"); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CBossSummonedEvent : public CBotEvent { public: - CBossSummonedEvent(char *psztype) + CBossSummonedEvent(const char *psztype) { setType(psztype); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CBossKilledEvent : public CBotEvent { public: - CBossKilledEvent(char *psztype) + CBossKilledEvent(const char *psztype) { setType(psztype); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; @@ -495,7 +523,7 @@ class CTF2PointLocked : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CTF2PointUnlocked : public CBotEvent @@ -507,7 +535,7 @@ class CTF2PointUnlocked : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CTF2MannVsMachineAlarm : public CBotEvent @@ -519,7 +547,7 @@ class CTF2MannVsMachineAlarm : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; @@ -532,7 +560,7 @@ class CFlagEvent : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CFlagCaptured : public CBotEvent @@ -544,7 +572,7 @@ class CFlagCaptured : public CBotEvent setMod(MOD_TF2); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; /* @@ -561,7 +589,7 @@ class CDODFireWeaponEvent : public CBotEvent setMod(MOD_DOD); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CDODBombExploded : public CBotEvent @@ -573,7 +601,7 @@ class CDODBombExploded : public CBotEvent setMod(MOD_DOD); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CDODBombPlanted : public CBotEvent @@ -585,7 +613,7 @@ class CDODBombPlanted : public CBotEvent setMod(MOD_DOD); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CDODBombDefused : public CBotEvent @@ -597,7 +625,7 @@ class CDODBombDefused : public CBotEvent setMod(MOD_DOD); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CDODPointCaptured : public CBotEvent @@ -609,7 +637,7 @@ class CDODPointCaptured : public CBotEvent setMod(MOD_DOD); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CDODChangeClass : public CBotEvent @@ -621,7 +649,7 @@ class CDODChangeClass : public CBotEvent setMod(MOD_DOD); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CDODRoundStart : public CBotEvent @@ -633,7 +661,7 @@ class CDODRoundStart : public CBotEvent setMod(MOD_DOD); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CDODRoundActive : public CBotEvent @@ -645,7 +673,7 @@ class CDODRoundActive : public CBotEvent setMod(MOD_DOD); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CDODRoundWin : public CBotEvent @@ -657,7 +685,7 @@ class CDODRoundWin : public CBotEvent setMod(MOD_DOD); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; class CDODRoundOver : public CBotEvent @@ -669,10 +697,10 @@ class CDODRoundOver : public CBotEvent setMod(MOD_DOD); } - void execute ( IBotEventInterface *pEvent ); + void execute ( IBotEventInterface *pEvent ) override; }; -typedef enum +typedef enum : std::uint8_t { TYPE_KEYVALUES = 0, TYPE_IGAMEEVENT = 1 @@ -681,9 +709,10 @@ typedef enum class IBotEventInterface { public: - virtual float getFloat ( const char *keyName = 0, float defaultValue = 0 ) = 0; - virtual int getInt ( const char *keyName = 0, int defaultValue = 0 ) = 0; - virtual const char *getString ( const char *keyName = 0, const char *defaultValue = 0 ) = 0; + virtual ~IBotEventInterface() = default; + virtual float getFloat ( const char *keyName = nullptr, float defaultValue = 0 ) = 0; + virtual int getInt ( const char *keyName = nullptr, int defaultValue = 0 ) = 0; + virtual const char *getString ( const char *keyName = nullptr, const char *defaultValue = nullptr ) = 0; virtual const char *getName () = 0; virtual void setInt ( const char *keyName, int value ) = 0; }; @@ -696,23 +725,23 @@ class CGameEventInterface1 : public IBotEventInterface m_pEvent = pEvent; } - float getFloat ( const char *keyName = 0, float defaultValue = 0 ) + float getFloat ( const char *keyName = nullptr, const float defaultValue = 0 ) override { return m_pEvent->GetFloat(keyName,defaultValue); } - int getInt ( const char *keyName = 0, int defaultValue = 0 ) + int getInt ( const char *keyName = nullptr, const int defaultValue = 0 ) override { return m_pEvent->GetInt(keyName,defaultValue); } - void setInt ( const char *keyName, int value ) + void setInt ( const char *keyName, const int value ) override { m_pEvent->SetInt(keyName,value); } - const char *getString ( const char *keyName = 0, const char *defaultValue = 0 ) + const char *getString ( const char *keyName = nullptr, const char *defaultValue = nullptr ) override { return m_pEvent->GetString(keyName,defaultValue); } - const char *getName () + const char *getName () override { return m_pEvent->GetName(); } @@ -729,25 +758,46 @@ class CGameEventInterface2 : public IBotEventInterface m_pEvent = pEvent; } - float getFloat ( const char *keyName = 0, float defaultValue = 0 ) + bool isValid() const { - return m_pEvent->GetFloat(keyName,defaultValue); + return m_pEvent != nullptr; } - int getInt ( const char *keyName = 0, int defaultValue = 0 ) + + float getFloat(const char* keyName = nullptr, const float defaultValue = 0) override { - return m_pEvent->GetInt(keyName,defaultValue); + if (!isValid()) + return defaultValue; + + return m_pEvent->GetFloat(keyName, defaultValue); } - void setInt ( const char *keyName, int value ) + + int getInt(const char* keyName = nullptr, const int defaultValue = 0) override { - m_pEvent->SetInt(keyName,value); + if (!isValid()) + return defaultValue; + + return m_pEvent->GetInt(keyName, defaultValue); } - const char *getString ( const char *keyName = 0, const char *defaultValue = 0 ) + + void setInt(const char* keyName, const int value) override { - return m_pEvent->GetString(keyName,defaultValue); + if (isValid()) + m_pEvent->SetInt(keyName, value); + } + + const char* getString(const char* keyName = nullptr, const char* defaultValue = nullptr) override + { + if (!isValid()) + return defaultValue; + + return m_pEvent->GetString(keyName, defaultValue); } - //Arguments needing filled? [APG]RoboCop[CL] - const char *getName () + + const char* getName() override { + if (!isValid()) + return nullptr; + return m_pEvent->GetName(); } private: @@ -766,6 +816,6 @@ class CBotEvents static void addEvent ( CBotEvent *pEvent ); private: - static vector m_theEvents; + static std::vector m_theEvents; }; #endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_events.cpp b/utils/RCBot2_meta/bot_events.cpp index dbff9dbd7..99f191b3f 100644 --- a/utils/RCBot2_meta/bot_events.cpp +++ b/utils/RCBot2_meta/bot_events.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -29,11 +31,16 @@ * */ -#include "bot_plugin_meta.h" +#pragma push_macro("clamp") //Fix for C++17 [APG]RoboCop[CL] +#undef clamp +#include +#pragma pop_macro("clamp") +#include "bot_plugin_meta.h" #include "igameevents.h" #include "bot.h" +#include "bot_cvars.h" #include "bot_event.h" #include "bot_strings.h" #include "bot_globals.h" @@ -46,8 +53,7 @@ #include "bot_schedule.h" #include "bot_waypoint_locations.h" -vector CBotEvents :: m_theEvents; -extern ConVar bot_use_vc_commands; +std::vector CBotEvents :: m_theEvents; /////////////////////////////////////////////////////// class CBotSeeFriendlyKill : public IBotFunction @@ -59,7 +65,7 @@ class CBotSeeFriendlyKill : public IBotFunction m_pWeapon = CWeapons::getWeaponByShortName(szKillerWeapon); m_pDied = pDied; } - void execute ( CBot *pBot ) + void execute ( CBot *pBot ) override { if ( CClassInterface::getTeam(m_pTeammate) != pBot->getTeam() ) return; @@ -80,9 +86,9 @@ class CBotWaveCompleteMVM : public IBotFunction { public: - void execute ( CBot *pBot ) + void execute ( CBot *pBot ) override { - ((CBotTF2*)pBot)->MannVsMachineWaveComplete(); + static_cast(pBot)->MannVsMachineWaveComplete(); } }; @@ -90,14 +96,14 @@ class CBotWaveCompleteMVM : public IBotFunction class CBotSeeFriendlyHurtEnemy : public IBotFunction { public: - CBotSeeFriendlyHurtEnemy ( edict_t *pTeammate, edict_t *pEnemy, int iWeaponID ) + CBotSeeFriendlyHurtEnemy ( edict_t *pTeammate, edict_t *pEnemy, const int iWeaponID ) { m_pTeammate = pTeammate; m_pEnemy = pEnemy; m_pWeapon = CWeapons::getWeapon(iWeaponID); } - void execute ( CBot *pBot ) + void execute ( CBot *pBot ) override { if ( CClassInterface::getTeam(m_pTeammate) != pBot->getTeam() ) return; @@ -117,16 +123,16 @@ class CBotSeeFriendlyHurtEnemy : public IBotFunction class CBroadcastMVMAlarm : public IBotFunction { public: - CBroadcastMVMAlarm(float fRadius) + CBroadcastMVMAlarm(const float fRadius) { m_bValid = CTeamFortress2Mod::getMVMCapturePoint(&m_vLoc); m_fRadius = fRadius; } - void execute ( CBot *pBot ) + void execute ( CBot *pBot ) override { if ( m_bValid ) - ((CBotTF2*)pBot)->MannVsMachineAlarmTriggered(m_vLoc + Vector(randomFloat(-m_fRadius,m_fRadius),randomFloat(-m_fRadius,m_fRadius),0)); + static_cast(pBot)->MannVsMachineAlarmTriggered(m_vLoc + Vector(randomFloat(-m_fRadius,m_fRadius),randomFloat(-m_fRadius,m_fRadius),0)); } private: Vector m_vLoc; @@ -134,18 +140,17 @@ class CBroadcastMVMAlarm : public IBotFunction bool m_bValid; }; - class CBotSeeEnemyHurtFriendly : public IBotFunction { public: - CBotSeeEnemyHurtFriendly ( edict_t *pEnemy, edict_t *pTeammate, int iWeaponID ) + CBotSeeEnemyHurtFriendly ( edict_t *pEnemy, edict_t *pTeammate, const int iWeaponID ) { m_pTeammate = pTeammate; m_pEnemy = pEnemy; m_pWeapon = CWeapons::getWeapon(iWeaponID); } - void execute ( CBot *pBot ) + void execute ( CBot *pBot ) override { if ( CClassInterface::getTeam(m_pTeammate) != pBot->getTeam() ) return; @@ -172,7 +177,7 @@ class CBotSeeFriendlyDie : public IBotFunction m_pWeapon = CWeapons::getWeaponByShortName(szKillerWeapon); m_pKiller = pKiller; } - void execute ( CBot *pBot ) + void execute ( CBot *pBot ) override { if ( CClassInterface::getTeam(m_pDied) != pBot->getTeam() ) return; @@ -192,19 +197,17 @@ class CBotSeeFriendlyDie : public IBotFunction class CBotHearPlayerAttack : public IBotFunction { public: - CBotHearPlayerAttack ( edict_t *pAttacker, int iWeaponID ) + CBotHearPlayerAttack ( edict_t *pAttacker, const int iWeaponID ) { m_pAttacker = pAttacker; m_iWeaponID = iWeaponID; } - void execute ( CBot *pBot ) + void execute ( CBot *pBot ) override { - extern ConVar rcbot_listen_dist; - if ( !pBot->hasEnemy() && (pBot->wantToListen()||pBot->isListeningToPlayer(m_pAttacker)) && pBot->wantToListenToPlayerAttack(m_pAttacker,m_iWeaponID) ) { - float fDistance = pBot->distanceFrom(m_pAttacker); + const float fDistance = pBot->distanceFrom(m_pAttacker); // add some fuzz based on distance if ( randomFloat(0.0f,rcbot_listen_dist.GetFloat()) > fDistance ) @@ -219,15 +222,15 @@ class CBotHearPlayerAttack : public IBotFunction class CTF2BroadcastRoundWin : public IBotFunction { public: - CTF2BroadcastRoundWin ( int iTeamWon, bool bFullRound ) + CTF2BroadcastRoundWin (const int iTeamWon, const bool bFullRound) { m_iTeam = iTeamWon; m_bFullRound = bFullRound; } - void execute ( CBot *pBot ) + void execute ( CBot *pBot ) override { - ((CBotTF2*)pBot)->roundWon(m_iTeam,m_bFullRound); + static_cast(pBot)->roundWon(m_iTeam,m_bFullRound); } private: int m_iTeam; @@ -239,13 +242,21 @@ class CTF2BroadcastRoundWin : public IBotFunction void CRoundStartEvent :: execute ( IBotEventInterface *pEvent ) { CBots::roundStart(); + #if SOURCE_ENGINE == SE_CSS + CCounterStrikeSourceMod::onRoundStart(); + #endif +} + +void CRoundFreezeEndEvent :: execute ( IBotEventInterface *pEvent ) +{ + CCounterStrikeSourceMod::onFreezeTimeEnd(); } void CPlayerHurtEvent :: execute ( IBotEventInterface *pEvent ) { CBot *pBot = CBots::getBotPointer(m_pActivator); - int iAttacker = pEvent->getInt("attacker",0); - int iWeaponId = pEvent->getInt("weaponid",-1); + const int iAttacker = pEvent->getInt("attacker",0); + const int iWeaponId = pEvent->getInt("weaponid",-1); if ( iAttacker > 0 ) { @@ -268,7 +279,7 @@ void CPlayerHurtEvent :: execute ( IBotEventInterface *pEvent ) if ( m_pActivator != pAttacker ) { if ( pAttacker && (!pAttacker->m_pNetworkable || !pAttacker->m_NetworkSerialNumber) ) - pAttacker = NULL; + pAttacker = nullptr; if ( pBot ) { @@ -291,7 +302,6 @@ void CPlayerHurtEvent :: execute ( IBotEventInterface *pEvent ) CBots::botFunction(&func2); } } - } //CBots::botFunction() } @@ -299,22 +309,23 @@ void CPlayerHurtEvent :: execute ( IBotEventInterface *pEvent ) void CPlayerDeathEvent :: execute ( IBotEventInterface *pEvent ) { CBot *pBot = CBots::getBotPointer(m_pActivator); - const char *weapon = pEvent->getString("weapon",NULL); - CBotSquad *pPrevSquadLeadersSquad = NULL; - int iAttacker = pEvent->getInt("attacker",0); + const char *weapon = pEvent->getString("weapon", nullptr); + CBotSquad *pPrevSquadLeadersSquad; + const int iAttacker = pEvent->getInt("attacker",0); - edict_t *pAttacker = (iAttacker>0)?CBotGlobals::playerByUserId(iAttacker):NULL; + edict_t *pAttacker = iAttacker>0?CBotGlobals::playerByUserId(iAttacker): nullptr; - if ( pAttacker && ((CBotGlobals::entityOrigin(pAttacker)-CBotGlobals::entityOrigin(m_pActivator)).Length()>512.0f) ) + if ( pAttacker && (CBotGlobals::entityOrigin(pAttacker)-CBotGlobals::entityOrigin(m_pActivator)).Length()>512.0f ) { // killer CClient *pClient = CClients::get(pAttacker); - if ( pClient && pClient->autoWaypointOn() ) + assert(pClient != nullptr); + if ( pClient->autoWaypointOn() ) { - CWeapon *pWeapon = CWeapons::getWeaponByShortName(weapon); + const CWeapon *pWeapon = CWeapons::getWeaponByShortName(weapon); - if ( pWeapon != NULL ) + if ( pWeapon != nullptr) { if ( pWeapon->isScoped() ) { @@ -323,8 +334,7 @@ void CPlayerDeathEvent :: execute ( IBotEventInterface *pEvent ) else if ( pWeapon->isDeployable() ) { // non OO hack here - if ( CBotGlobals::isCurrentMod(MOD_DOD) ) - { + #if SOURCE_ENGINE == SE_DODS edict_t *pentWeapon = CWeapons::findWeapon(pAttacker,pWeapon->getWeaponName()); if ( CClassInterface::isMachineGunDeployed(pentWeapon) ) @@ -339,7 +349,7 @@ void CPlayerDeathEvent :: execute ( IBotEventInterface *pEvent ) pClient->autoEventWaypoint(CWaypointTypes::W_FL_MACHINEGUN,100.0f); } } - } + #endif //CClassInterface::isMachineGunDeployed(pWeapon->get) //pWeapon->isDeployed() } @@ -349,11 +359,12 @@ void CPlayerDeathEvent :: execute ( IBotEventInterface *pEvent ) // victim pClient = CClients::get(m_pActivator); - if ( CBotGlobals::isPlayer(pAttacker) && pClient && pClient->autoWaypointOn() ) + assert(pClient != nullptr); + if ( CBotGlobals::isPlayer(pAttacker) && pClient->autoWaypointOn() ) { - CWeapon *pWeapon = CWeapons::getWeaponByShortName(weapon); + const CWeapon *pWeapon = CWeapons::getWeaponByShortName(weapon); - if ( pWeapon != NULL ) + if ( pWeapon != nullptr) { if ( pWeapon->isScoped() ) { @@ -361,7 +372,6 @@ void CPlayerDeathEvent :: execute ( IBotEventInterface *pEvent ) } } } - } if ( pBot ) @@ -371,7 +381,7 @@ void CPlayerDeathEvent :: execute ( IBotEventInterface *pEvent ) if ( pBot ) { - pBot->killed(m_pActivator,(char*)weapon); + pBot->killed(m_pActivator,const_cast(weapon)); pBot->enemyDown(m_pActivator); } @@ -385,7 +395,7 @@ void CPlayerDeathEvent :: execute ( IBotEventInterface *pEvent ) CBots::botFunction(&func2); } - if ( (pPrevSquadLeadersSquad = CBotSquads::FindSquadByLeader (m_pActivator)) != NULL ) + if ( (pPrevSquadLeadersSquad = CBotSquads::FindSquadByLeader (m_pActivator)) != nullptr) { CBotSquads::ChangeLeader(pPrevSquadLeadersSquad); } @@ -403,32 +413,32 @@ void CBombDroppedEvent :: execute ( IBotEventInterface *pEvent ) { } +void CCSSBombPlantedEvent :: execute ( IBotEventInterface *pEvent ) +{ + CCounterStrikeSourceMod::onBombPlanted(); +} + void CWeaponFireEvent :: execute ( IBotEventInterface *pEvent ) { } void CPlayerSpawnEvent :: execute ( IBotEventInterface *pEvent ) { - CBot *pBot = CBots::getBotPointer(m_pActivator); - - if ( pBot ) + if ( CBot *pBot = CBots::getBotPointer(m_pActivator) ) pBot->spawnInit(); - if ( CBotGlobals::isCurrentMod(MOD_TF2) ) - { + #if SOURCE_ENGINE == SE_TF2 if ( pEvent->getInt("class") == TF_CLASS_MEDIC ) { // find medigun CTeamFortress2Mod::findMediGun(m_pActivator); } - } + #endif } void CBulletImpactEvent :: execute ( IBotEventInterface *pEvent ) { - CBot *pBot = CBots::getBotPointer(m_pActivator); - - if ( pBot ) + if ( CBot *pBot = CBots::getBotPointer(m_pActivator) ) { pBot->shotmiss(); } @@ -444,23 +454,22 @@ void CBulletImpactEvent :: execute ( IBotEventInterface *pEvent ) */ void CTF2ObjectSapped :: execute ( IBotEventInterface *pEvent ) { - int owner = pEvent->getInt("ownerid",-1); + const int owner = pEvent->getInt("ownerid",-1); int building = pEvent->getInt("object",-1); - int sapperid = pEvent->getInt("sapperid",-1); + const int sapperid = pEvent->getInt("sapperid",-1); - if ( m_pActivator && (owner>=0) && (building>=0) && (sapperid>=0) ) + if ( m_pActivator && owner>=0 && building>=0 && sapperid>=0 ) { edict_t *pSpy = m_pActivator; - edict_t *pOwner = CBotGlobals::playerByUserId(owner); + const edict_t *pOwner = CBotGlobals::playerByUserId(owner); edict_t *pSapper = INDEXENT(sapperid); - CBotTF2 *pBot = (CBotTF2*)CBots::getBotPointer(pOwner); - - if ( pBot ) + + if ( CBotTF2 *pBot = static_cast(CBots::getBotPointer(pOwner)) ) { - pBot->buildingSapped((eEngiBuild)building,pSapper,pSpy); + pBot->buildingSapped(static_cast(building),pSapper,pSpy); } - CTeamFortress2Mod::sapperPlaced(pOwner,(eEngiBuild)building,pSapper); + CTeamFortress2Mod::sapperPlaced(pOwner,static_cast(building),pSapper); CBroadcastSpySap spysap = CBroadcastSpySap(pSpy); @@ -496,17 +505,15 @@ void CBossKilledEvent :: execute ( IBotEventInterface *pEvent ) void CPlayerTeleported ::execute(IBotEventInterface *pEvent) { - int builderid = pEvent->getInt("builderid",-1); + const int builderid = pEvent->getInt("builderid",-1); if ( builderid >= 0 ) { - edict_t *pPlayer = CBotGlobals::playerByUserId(builderid); + const edict_t *pPlayer = CBotGlobals::playerByUserId(builderid); - CBot *pBot = CBots::getBotPointer(pPlayer); - - if ( pBot ) + if ( CBot *pBot = CBots::getBotPointer(pPlayer) ) { - ((CBotTF2*)pBot)->teleportedPlayer(); + static_cast(pBot)->teleportedPlayer(); } CTeamFortress2Mod::updateTeleportTime(pPlayer); @@ -516,23 +523,22 @@ void CPlayerTeleported ::execute(IBotEventInterface *pEvent) void CPlayerHealed ::execute(IBotEventInterface *pEvent) { - int patient = pEvent->getInt("patient",-1); - int healer = pEvent->getInt("healer",-1); - int amount = pEvent->getFloat("amount",0); + const int patient = pEvent->getInt("patient",-1); + const int healer = pEvent->getInt("healer",-1); + const float amount = pEvent->getFloat("amount",0); - if ( (healer != -1) && ( patient != -1 ) && (healer != patient) ) + if ( healer != -1 && patient != -1 && healer != patient ) { m_pActivator = CBotGlobals::playerByUserId(patient); if ( m_pActivator ) { - CBot *pBot = CBots::getBotPointer(m_pActivator); - - if ( pBot ) + if ( CBot *pBot = CBots::getBotPointer(m_pActivator) ) { - CBotTF2 *pBotTF2 = (CBotTF2*)pBot; + CBotTF2 *pBotTF2 = static_cast(pBot); - if ( pBotTF2 && randomInt(0,1) ) + assert(pBotTF2 != nullptr); + if ( randomInt(0,1) ) pBotTF2->addVoiceCommand(TF_VC_THANKS); } } @@ -541,7 +547,7 @@ void CPlayerHealed ::execute(IBotEventInterface *pEvent) if ( pBot && pBot->isTF2() ) { - ((CBotTF2*)pBot)->healedPlayer(m_pActivator,amount); + static_cast(pBot)->healedPlayer(m_pActivator,amount); } } } @@ -561,34 +567,31 @@ void CPlayerHealed ::execute(IBotEventInterface *pEvent) void CTF2ObjectDestroyed :: execute ( IBotEventInterface *pEvent ) { int type = pEvent->getInt("objecttype",-1); - int index = pEvent->getInt("index",-1); - int was_building = pEvent->getInt("was_building",-1); - int iAttacker = pEvent->getInt("attacker",-1); + const int index = pEvent->getInt("index",-1); + const int was_building = pEvent->getInt("was_building",-1); + const int iAttacker = pEvent->getInt("attacker",-1); if ( iAttacker != -1 ) { edict_t *pAttacker = CBotGlobals::playerByUserId(iAttacker); - if ( pAttacker && m_pActivator && (type>=0) && (index>=0) && (was_building>=0) ) + if ( pAttacker && m_pActivator && type>=0 && index>=0 && was_building>=0 ) { //if ( !was_building ) //{ // could be a sapper - if ( (eEngiBuild)type == ENGI_SAPPER ) + if ( static_cast(type) == ENGI_SAPPER ) { edict_t *pOwner = pAttacker; edict_t *pSapper = INDEXENT(index); - CBotTF2 *pBot = (CBotTF2*)CBots::getBotPointer(pOwner); - if ( pBot ) + if ( const CBotTF2 *pBot = static_cast(CBots::getBotPointer(pOwner)) ) pBot->sapperDestroyed(pSapper); - CTeamFortress2Mod::sapperDestroyed(pOwner,(eEngiBuild)type,pSapper); + CTeamFortress2Mod::sapperDestroyed(pOwner,static_cast(type),pSapper); } else { - CBotTF2 *pBot = (CBotTF2*)CBots::getBotPointer(m_pActivator); - - if ( pBot ) + if ( CBotTF2 *pBot = static_cast(CBots::getBotPointer(m_pActivator)) ) { edict_t *pBuilding = INDEXENT(index); @@ -597,22 +600,16 @@ void CTF2ObjectDestroyed :: execute ( IBotEventInterface *pEvent ) } //} } - } - - } - void CPostInventoryApplicationTF2 :: execute ( IBotEventInterface *pEvent ) { - int iUserID = pEvent->getInt( "userid" ); - - edict_t *pEdict = CBotGlobals::playerByUserId(iUserID); + const int iUserID = pEvent->getInt( "userid" ); - CBot *pBot = CBots::getBotPointer(pEdict); + const edict_t *pEdict = CBotGlobals::playerByUserId(iUserID); - if ( pBot ) + if ( CBot *pBot = CBots::getBotPointer(pEdict) ) { pBot->onInventoryApplication(); } @@ -630,17 +627,17 @@ void CTF2UpgradeObjectEvent :: execute ( IBotEventInterface *pEvent ) { if ( bot_use_vc_commands.GetBool() && randomInt(0,1) ) { - eEngiBuild object = (eEngiBuild)pEvent->getInt("object",0); - bool isbuilder = (pEvent->getInt("isbuilder")>0); - short index = pEvent->getInt("index"); + const eEngiBuild object = static_cast(pEvent->getInt("object", 0)); + const bool isbuilder = pEvent->getInt("isbuilder")>0; + const int index = pEvent->getInt("index"); if ( !isbuilder ) { // see if builder is a bot - edict_t *pOwner = CTeamFortress2Mod::getBuildingOwner (object, index); + const edict_t *pOwner = CTeamFortress2Mod::getBuildingOwner (object, index); CBotTF2 *pBot; - if ( (pBot = (CBotTF2*)CBots::getBotPointer(pOwner)) != NULL ) + if ( (pBot = static_cast(CBots::getBotPointer(pOwner))) != nullptr) { pBot->addVoiceCommand(TF_VC_THANKS); } @@ -650,17 +647,14 @@ void CTF2UpgradeObjectEvent :: execute ( IBotEventInterface *pEvent ) void CTF2RoundWinEvent :: execute (IBotEventInterface *pEvent ) { - int iWinningTeam = pEvent->getInt("team"); - CTF2BroadcastRoundWin *function = new CTF2BroadcastRoundWin(iWinningTeam,pEvent->getInt("full_round") == 1); - - CBots::botFunction(function); + const int iWinningTeam = pEvent->getInt("team"); + CTF2BroadcastRoundWin fn(iWinningTeam, pEvent->getInt("full_round") == 1); + CBots::botFunction(&fn); + CTeamFortress2Mod::roundWon(iWinningTeam); - - delete function; } - void CTF2SetupFinished ::execute(IBotEventInterface *pEvent ) { CTeamFortress2Mod::roundStarted(); @@ -668,8 +662,8 @@ void CTF2SetupFinished ::execute(IBotEventInterface *pEvent ) void CTF2BuiltObjectEvent :: execute ( IBotEventInterface *pEvent ) { - eEngiBuild type = (eEngiBuild)pEvent->getInt("object"); - int index = pEvent->getInt("index"); + const eEngiBuild type = static_cast(pEvent->getInt("object")); + const int index = pEvent->getInt("index"); edict_t *pBuilding = INDEXENT(index); CBot *pBot = CBots::getBotPointer(m_pActivator); @@ -679,7 +673,8 @@ void CTF2BuiltObjectEvent :: execute ( IBotEventInterface *pEvent ) { CTeamFortress2Mod::teleporterBuilt(m_pActivator,type,pBuilding); - if ( pClient && pClient->autoWaypointOn() ) + assert(pClient != nullptr); + if ( pClient->autoWaypointOn() ) { if ( CTeamFortress2Mod::isTeleporterEntrance(pBuilding,CTeamFortress2Mod::getTeam(m_pActivator)) ) pClient->autoEventWaypoint(CWaypointTypes::W_FL_TELE_ENTRANCE,400.0f); @@ -692,7 +687,8 @@ void CTF2BuiltObjectEvent :: execute ( IBotEventInterface *pEvent ) { CTeamFortress2Mod::sentryBuilt(m_pActivator,type,pBuilding); - if ( pClient && pClient->autoWaypointOn() ) + assert(pClient != nullptr); + if ( pClient->autoWaypointOn() ) { pClient->autoEventWaypoint(CWaypointTypes::W_FL_SENTRY,400.0f); } @@ -705,7 +701,7 @@ void CTF2BuiltObjectEvent :: execute ( IBotEventInterface *pEvent ) if ( pBot && pBot->isTF() ) { - ((CBotFortress*)pBot)->engiBuildSuccess((eEngiBuild)pEvent->getInt("object"),pEvent->getInt("index")); + static_cast(pBot)->engiBuildSuccess(static_cast(pEvent->getInt("object")),pEvent->getInt("index")); } } @@ -718,7 +714,7 @@ void CTF2ChangeClass :: execute ( IBotEventInterface *pEvent ) int _class = pEvent->getInt("class"); - ((CBotFortress*)pBot)->setClass((TF_Class)_class); + static_cast(pBot)->setClass(static_cast(_class)); } } @@ -771,7 +767,7 @@ float time_remaining */ void CTF2PointStopCapture :: execute ( IBotEventInterface *pEvent ) { - int capindex = pEvent->getInt("cp",0); + const int capindex = pEvent->getInt("cp",0); CTeamFortress2Mod::removeCappers(capindex); @@ -788,7 +784,7 @@ byte blocker index of the player that blocked the cap */ void CTF2PointBlockedCapture :: execute ( IBotEventInterface *pEvent ) { - int capindex = pEvent->getInt("cp",0); + const int capindex = pEvent->getInt("cp",0); CTeamFortress2Mod::removeCappers(capindex); } @@ -805,13 +801,13 @@ void CTF2PointLocked :: execute ( IBotEventInterface *pEvent ) void CTF2PointStartTouch :: execute ( IBotEventInterface *pEvent ) { - int capindex = pEvent->getInt("area",0); - int iplayerIndex = pEvent->getInt("player",-1); + const int capindex = pEvent->getInt("area",0); + const int iplayerIndex = pEvent->getInt("player",-1); // const char *cpname = pEvent->getString("cpname"); edict_t *pPlayer = INDEXENT(iplayerIndex); - if ( (capindex >= 0) && (CTeamFortress2Mod::m_ObjectiveResource.GetNumControlPoints() > 0) && + if ( capindex >= 0 && CTeamFortress2Mod::m_ObjectiveResource.GetNumControlPoints() > 0 && CTeamFortress2Mod::m_ObjectiveResource.GetOwningTeam(capindex) == CClassInterface::getTeam(pPlayer) ) { CTeamFortress2Mod::addCapDefender(pPlayer,capindex); @@ -820,13 +816,13 @@ void CTF2PointStartTouch :: execute ( IBotEventInterface *pEvent ) void CTF2PointEndTouch :: execute ( IBotEventInterface *pEvent ) { - int capindex = pEvent->getInt("area",0); - int iplayerIndex = pEvent->getInt("player",-1); + const int capindex = pEvent->getInt("area",0); + const int iplayerIndex = pEvent->getInt("player",-1); // const char *cpname = pEvent->getString("cpname"); edict_t *pPlayer = INDEXENT(iplayerIndex); - if ( (capindex >= 0) && (CTeamFortress2Mod::m_ObjectiveResource.GetNumControlPoints() > 0) && + if ( capindex >= 0 && CTeamFortress2Mod::m_ObjectiveResource.GetNumControlPoints() > 0 && CTeamFortress2Mod::m_ObjectiveResource.GetOwningTeam(capindex) == CClassInterface::getTeam(pPlayer) ) { CTeamFortress2Mod::removeCapDefender(pPlayer,capindex); @@ -844,18 +840,17 @@ void CTF2PointStartCapture :: execute ( IBotEventInterface *pEvent ) [RCBot] [DEBUG game_event] cappers =  [RCBot] [DEBUG game_event] priority = 7 */ - int capteam = pEvent->getInt("capteam",0); - int capindex = pEvent->getInt("cp",0); - const char *cappers = pEvent->getString("cappers",NULL); -// const char *cpname = pEvent->getString("cpname"); + const int capteam = pEvent->getInt("capteam",0); + const int capindex = pEvent->getInt("cp",0); + // const char *cpname = pEvent->getString("cpname"); - if ( cappers ) + if ( const char *cappers = pEvent->getString("cappers", nullptr) ) { - int i = 0; + std::size_t i = 0; // Use std::size_t for the index type [APG]RoboCop[CL] while ( cappers[i] != 0 ) { - CTeamFortress2Mod::addCapper(capindex,(int)cappers[i]); + CTeamFortress2Mod::addCapper(capindex,cappers[i]); i++; } } @@ -863,12 +858,8 @@ void CTF2PointStartCapture :: execute ( IBotEventInterface *pEvent ) CTeamFortress2Mod::m_ObjectiveResource.updateCaptureTime(capindex); //CPoints::pointBeingCaptured(capteam,cpname,cappers[0]); - CBotTF2FunctionEnemyAtIntel *function = new CBotTF2FunctionEnemyAtIntel(capteam,CTeamFortress2Mod::m_ObjectiveResource.GetCPPosition(capindex),EVENT_CAPPOINT,NULL,capindex); - - CBots::botFunction(function); - - delete function; - + CBotTF2FunctionEnemyAtIntel fn(capteam, CTeamFortress2Mod::m_ObjectiveResource.GetCPPosition(capindex), EVENT_CAPPOINT, nullptr, capindex); + CBots::botFunction(&fn); } void CTF2MannVsMachineAlarm :: execute ( IBotEventInterface *pEvent ) @@ -889,7 +880,7 @@ void CTF2PointCaptured :: execute ( IBotEventInterface *pEvent ) CTeamFortress2Mod::updatePointMaster(); // update points - CTeamFortress2Mod::m_ObjectiveResource.m_fUpdatePointTime = 0; + CTeamFortress2Mod::m_ObjectiveResource.m_fUpdatePointTime = 0.0f; CTeamFortress2Mod::m_ObjectiveResource.m_fNextCheckMonitoredPoint = engine->Time() + 0.2f; // MUST BE AFTER POINTS HAVE BEEN UPDATED! @@ -898,27 +889,34 @@ void CTF2PointCaptured :: execute ( IBotEventInterface *pEvent ) } /* Flag has been picked up or dropped */ -#define FLAG_PICKUP 1 -#define FLAG_CAPTURED 2 -#define FLAG_DEFEND 3 -#define FLAG_DROPPED 4 -#define FLAG_RETURN 5 +enum : std::uint8_t +{ + FLAG_PICKUP = 1, + FLAG_CAPTURED = 2, + FLAG_DEFEND = 3, + FLAG_DROPPED = 4, + FLAG_RETURN = 5 +}; void CFlagEvent :: execute ( IBotEventInterface *pEvent ) { // dropped / picked up ID - int type = pEvent->getInt("eventtype"); + const int type = pEvent->getInt("eventtype"); // player id - int player = pEvent->getInt("player"); + const int player = pEvent->getInt("player"); + + edict_t *pPlayer = nullptr; + CBot *pBot = nullptr; - edict_t *pPlayer = NULL; - CBot *pBot = NULL; - // Crash fix if ( player ) { pPlayer = INDEXENT(player); - pBot = CBots::getBotPointer(pPlayer); + + if ( pPlayer ) + { + pBot = CBots::getBotPointer(pPlayer); + } } switch ( type ) @@ -926,20 +924,19 @@ void CFlagEvent :: execute ( IBotEventInterface *pEvent ) case FLAG_PICKUP: // pickup if ( pBot && pBot->isTF() ) { - ((CBotTF2*)pBot)->pickedUpFlag(); + static_cast(pBot)->pickedUpFlag(); } if ( pPlayer ) { - int iTeam = CTeamFortress2Mod::getTeam(pPlayer); + const int iTeam = CTeamFortress2Mod::getTeam(pPlayer); if ( CTeamFortress2Mod::isFlagAtDefaultState() ) { - CClient *pClient; + CClient* pClient = CClients::get(pPlayer); - pClient = CClients::get(pPlayer); - - if ( pClient && pClient->autoWaypointOn() ) + assert(pClient != nullptr); + if ( pClient->autoWaypointOn() ) pClient->autoEventWaypoint(CWaypointTypes::W_FL_FLAG,200.0f,false); } @@ -951,13 +948,9 @@ void CFlagEvent :: execute ( IBotEventInterface *pEvent ) break; case FLAG_CAPTURED: // captured { - IPlayerInfo *p = NULL; - if( pPlayer ) { - p = playerinfomanager->GetPlayerInfo(pPlayer); - - if ( p ) + if ( IPlayerInfo* p = playerinfomanager->GetPlayerInfo(pPlayer) ) { CBroadcastFlagCaptured captured = CBroadcastFlagCaptured(p->GetTeamIndex()); CBots::botFunction(&captured); @@ -966,21 +959,20 @@ void CFlagEvent :: execute ( IBotEventInterface *pEvent ) if ( pBot && pBot->isTF() ) { - ((CBotTF2*)pBot)->capturedFlag(); - ((CBotTF2*)pBot)->droppedFlag(); + static_cast(pBot)->capturedFlag(); + static_cast(pBot)->droppedFlag(); } if ( pPlayer ) { - int iTeam = CTeamFortress2Mod::getTeam(pPlayer); + const int iTeam = CTeamFortress2Mod::getTeam(pPlayer); CTeamFortress2Mod::flagDropped(iTeam,Vector(0,0,0)); - CClient *pClient; + CClient* pClient = CClients::get(pPlayer); - pClient = CClients::get(pPlayer); - - if ( pClient && pClient->autoWaypointOn() ) - pClient->autoEventWaypoint(CWaypointTypes::W_FL_CAPPOINT,200.0f,false); + assert(pClient != nullptr); + if (pClient->autoWaypointOn()) + pClient->autoEventWaypoint(CWaypointTypes::W_FL_CAPPOINT, 200.0f, false); } CTeamFortress2Mod::resetFlagStateToDefault(); @@ -988,6 +980,8 @@ void CFlagEvent :: execute ( IBotEventInterface *pEvent ) } break; case FLAG_DROPPED: // drop + { + if ( pPlayer ) { IPlayerInfo *p = playerinfomanager->GetPlayerInfo(pPlayer); Vector vLoc; @@ -1000,13 +994,12 @@ void CFlagEvent :: execute ( IBotEventInterface *pEvent ) } if ( pBot && pBot->isTF() ) - ((CBotTF2*)pBot)->droppedFlag(); + static_cast(pBot)->droppedFlag(); - - if ( pPlayer ) - CTeamFortress2Mod::flagDropped(CTeamFortress2Mod::getTeam(pPlayer),vLoc); + CTeamFortress2Mod::flagDropped(CTeamFortress2Mod::getTeam(pPlayer),vLoc); } - break; + } + break; case FLAG_RETURN: { if ( CTeamFortress2Mod::isMapType(TF_MAP_SD) ) @@ -1023,36 +1016,34 @@ void CFlagEvent :: execute ( IBotEventInterface *pEvent ) default: break; } - } void CFlagCaptured :: execute ( IBotEventInterface *pEvent ) { - } ///////////////////////////////////////////////// void CDODPointCaptured :: execute ( IBotEventInterface *pEvent ) { - int cp = pEvent->getInt("cp"); - const char *szCappers = pEvent->getString("cappers",NULL); - edict_t *pPlayer; + const int cp = pEvent->getInt("cp"); + const char *szCappers = pEvent->getString("cappers", nullptr); // get a capper - int userid = szCappers[0]; + const char userid = szCappers[0]; int team = 0; // find the team - should be a player index - if ( (userid >= 0) && (userid <= gpGlobals->maxClients) ) + if ( userid >= 0 && userid <= gpGlobals->maxClients ) { - pPlayer = INDEXENT(userid); + edict_t* pPlayer = INDEXENT(userid); team = CClassInterface::getTeam(pPlayer); CClient *pClient = CClients::get(pPlayer); - if ( pClient && pClient->autoWaypointOn() ) + assert(pClient != nullptr); + if (pClient->autoWaypointOn()) { - pClient->autoEventWaypoint(CWaypointTypes::W_FL_CAPPOINT,150.0f,false,0,Vector(0,0,0),true); + pClient->autoEventWaypoint(CWaypointTypes::W_FL_CAPPOINT, 150.0f, false, 0, Vector(0, 0, 0), true); } } @@ -1066,8 +1057,8 @@ void CDODPointCaptured :: execute ( IBotEventInterface *pEvent ) void CDODBombExploded :: execute ( IBotEventInterface *pEvent ) { - int cp = pEvent->getInt("cp"); - int team = CClassInterface::getTeam(m_pActivator); + const int cp = pEvent->getInt("cp"); + const int team = CClassInterface::getTeam(m_pActivator); if ( m_pActivator ) { @@ -1081,8 +1072,8 @@ void CDODBombExploded :: execute ( IBotEventInterface *pEvent ) void CDODBombDefused :: execute ( IBotEventInterface *pEvent ) { - int cp = pEvent->getInt("cp"); - int team = pEvent->getInt("team"); + const int cp = pEvent->getInt("cp"); + const int team = pEvent->getInt("team"); CDODMod::m_Flags.setBombPlanted(cp,false); @@ -1093,8 +1084,8 @@ void CDODBombDefused :: execute ( IBotEventInterface *pEvent ) void CDODBombPlanted :: execute ( IBotEventInterface *pEvent ) { - int cp = pEvent->getInt("cp"); - int team = pEvent->getInt("team"); + const int cp = pEvent->getInt("cp"); + const int team = pEvent->getInt("team"); CBroadcastBombEvent func(DOD_BOMB_PLANT,cp,team); @@ -1135,16 +1126,16 @@ void CDODRoundOver :: execute ( IBotEventInterface *pEvent ) //CDODMod::m_Flags.reset(); } -void CDODChangeClass :: execute ( IBotEventInterface *pEvent ) +void CDODChangeClass::execute(IBotEventInterface* pEvent) { - if ( m_pActivator ) - { - CBot *pBot = CBots::getBotPointer(m_pActivator); + if (!pEvent || !m_pActivator) + return; - if ( pBot ) + if (CBot* pBot = CBots::getBotPointer(m_pActivator)) + { + if (pBot->isDOD()) { - CDODBot *pDODBot = (CDODBot*)pBot; - + CDODBot* pDODBot = static_cast(pBot); pDODBot->selectedClass(pEvent->getInt("class")); } } @@ -1158,17 +1149,15 @@ void CDODChangeClass :: execute ( IBotEventInterface *pEvent ) void CDODFireWeaponEvent :: execute ( IBotEventInterface *pEvent ) { - int iAttacker = pEvent->getInt("attacker",-1); + const int iAttacker = pEvent->getInt("attacker",-1); if ( iAttacker >= 0 ) { edict_t *pAttacker = CBotGlobals::playerByUserId(iAttacker); - int iWeaponID = pEvent->getInt("weapon",-1); - - CBotHearPlayerAttack *func = new CBotHearPlayerAttack(pAttacker,iWeaponID); + const int iWeaponID = pEvent->getInt("weapon",-1); - CBots::botFunction(func); - delete func; + CBotHearPlayerAttack func(pAttacker,iWeaponID); + CBots::botFunction(&func); } @@ -1176,17 +1165,17 @@ void CDODFireWeaponEvent :: execute ( IBotEventInterface *pEvent ) /////////////////////////////////////////////////////// -void CBotEvent :: setType ( char *szType ) +void CBotEvent :: setType (const char* szType) { m_szType = CStrings::getString(szType); } -bool CBotEvent :: forCurrentMod () +bool CBotEvent :: forCurrentMod () const { - return ((m_iModId == MOD_ANY) || (CBotGlobals::isMod(m_iModId))); + return m_iModId == MOD_ANY || CBotGlobals::isMod(m_iModId); } // should we execute this ?? -inline bool CBotEvent :: isType ( const char *szType ) +inline bool CBotEvent :: isType ( const char *szType ) const { return forCurrentMod() && FStrEq(m_szType,szType); } @@ -1197,9 +1186,11 @@ void CBotEvents :: setupEvents () addEvent(new CTF2MVMWaveCompleteEvent()); addEvent(new CTF2MVMWaveFailedEvent()); addEvent(new CRoundStartEvent()); + addEvent(new CRoundFreezeEndEvent()); addEvent(new CPlayerHurtEvent()); addEvent(new CPlayerDeathEvent()); addEvent(new CBombPickupEvent()); + addEvent(new CCSSBombPlantedEvent()); addEvent(new CPlayerFootstepEvent()); addEvent(new CBombDroppedEvent()); addEvent(new CWeaponFireEvent()); @@ -1262,68 +1253,71 @@ eyeball_boss_escaped */ void CBotEvents :: addEvent ( CBotEvent *pEvent ) { - extern IGameEventManager2 *gameeventmanager; + extern IGameEventManager2 *gameeventmanager; //redundant? [APG]RoboCop[CL] //extern CRCBotMetaPlugin g_RCBOTServerPlugin; - extern RCBotPluginMeta g_RCBotPluginMeta; + extern RCBotPluginMeta g_RCBotPluginMeta; //redundant? [APG]RoboCop[CL] //if ( gameeventmanager ) // gameeventmanager->AddListener( g_RCBotPluginMeta.getEventListener(), pEvent->getName(), true ); - m_theEvents.push_back(pEvent); + m_theEvents.emplace_back(pEvent); } void CBotEvents :: freeMemory () { - for ( unsigned int i = 0; i < m_theEvents.size(); i ++ ) + for (CBotEvent*& m_theEvent : m_theEvents) { - delete m_theEvents[i]; - m_theEvents[i] = NULL; + delete m_theEvent; + m_theEvent = nullptr; } m_theEvents.clear(); } -void CBotEvents :: executeEvent( void *pEvent, eBotEventType iType ) +void CBotEvents::executeEvent(void* pEvent, const eBotEventType iType) { - CBotEvent *pFound; - int iEventId = -1; - bool bFound; + // Early exit if event pointer is null (can happen when event is blocked by another plugin) - [APG]RoboCop[CL] + if (pEvent == nullptr) + return; + + int iEventId = -1; - IBotEventInterface *pInterface = NULL; + std::unique_ptr pInterface; - if ( iType == TYPE_KEYVALUES ) - pInterface = new CGameEventInterface1((KeyValues*)pEvent); - else if ( iType == TYPE_IGAMEEVENT ) - pInterface = new CGameEventInterface2((IGameEvent*)pEvent); + if (iType == TYPE_KEYVALUES) + pInterface = std::make_unique(static_cast(pEvent)); - if ( pInterface == NULL ) + else if (iType == TYPE_IGAMEEVENT) + pInterface = std::make_unique(static_cast(pEvent)); + + if (pInterface == nullptr) return; - if ( iType != TYPE_IGAMEEVENT ) + // Sanity check for event name - [APG]RoboCop[CL] + const char* eventName = pInterface->getName(); + if (eventName == nullptr) + return; + + if (iType != TYPE_IGAMEEVENT) iEventId = pInterface->getInt("eventid"); - for ( register unsigned short int i = 0; i < m_theEvents.size(); i ++ ) + for (CBotEvent* pFound : m_theEvents) { - pFound = m_theEvents[i]; - // if it has an pEvent id stored just check that //if ( ( iType != TYPE_IGAMEEVENT ) && pFound->hasEventId() ) // bFound = pFound->isEventId(iEventId); //else - bFound = pFound->forCurrentMod() && pFound->isType(pInterface->getName()); - if ( bFound ) + if ( const bool bFound = pFound->forCurrentMod() && pFound->isType(eventName) ) { - int userid = pInterface->getInt("userid",-1); + const int userid = pInterface->getInt("userid",-1); // set pEvent id for quick checking pFound->setEventId(iEventId); - pFound->setActivator((userid>=0)?CBotGlobals::playerByUserId(userid):NULL); + pFound->setActivator(userid >= 0 ? CBotGlobals::playerByUserId(userid) : nullptr); - pFound->execute(pInterface); + pFound->execute(pInterface.get()); break; } } - - delete pInterface; -} +} \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_exception.h b/utils/RCBot2_meta/bot_exception.h deleted file mode 100644 index e69de29bb..000000000 diff --git a/utils/RCBot2_meta/bot_fortress.cpp b/utils/RCBot2_meta/bot_fortress.cpp index 615dbbf20..e7a097a34 100644 --- a/utils/RCBot2_meta/bot_fortress.cpp +++ b/utils/RCBot2_meta/bot_fortress.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * part of https://rcbot2.svn.sourceforge.net/svnroot/rcbot2 * @@ -30,8 +32,16 @@ * version. * */ + +#pragma push_macro("clamp") //Fix for C++17 [APG]RoboCop[CL] +#undef clamp +#include +#pragma pop_macro("clamp") + #include "bot_plugin_meta.h" + #include "bot.h" +#include "bot_cvars.h" #include "ndebugoverlay.h" @@ -56,25 +66,28 @@ #include "bot_squads.h" //#include "bot_hooks.h" -extern ConVar bot_beliefmulti; -extern ConVar bot_spyknifefov; -extern ConVar bot_use_vc_commands; -extern ConVar bot_max_cc_time; -extern ConVar bot_min_cc_time; -extern ConVar bot_change_class; -extern ConVar rcbot_demo_jump; -extern ConVar rcbot_melee_only; -extern ConVar rcbot_tf2_protect_cap_time; -extern ConVar rcbot_tf2_protect_cap_percent; -extern ConVar rcbot_tf2_spy_kill_on_cap_dist; -extern ConVar rcbot_speed_boost; -extern ConVar rcbot_projectile_tweak; -extern ConVar rcbot_force_class; +#include +#include +#include +#include + +#include "rcbot/tf2/conditions.h" +#include "rcbot/entprops.h" +#include "rcbot/logging.h" + +//caxanga334: SDK 2013 contains macros for std::min and std::max which causes errors when compiling +//#if SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_BMS +#include "valve_minmax_off.h" +//#endif extern IVDebugOverlay *debugoverlay; -#define TF2_SPY_CLOAK_BELIEF 40 -#define TF2_HWGUY_REV_BELIEF 60 +enum : std::uint8_t +{ + TF2_SPY_CLOAK_BELIEF = 40, + TF2_HWGUY_REV_BELIEF = 60 +}; + //extern float g_fBotUtilityPerturb [TF_CLASS_MAX][BOT_UTIL_MAX]; // Payload stuff by The_Shadow @@ -88,10 +101,10 @@ void CBroadcastOvertime ::execute (CBot*pBot) } void CBroadcastCapturedPoint :: execute ( CBot *pBot ) { - ((CBotTF2*)pBot)->pointCaptured(m_iPoint,m_iTeam,m_szName); + static_cast(pBot)->pointCaptured(m_iPoint,m_iTeam,m_szName); } -CBroadcastCapturedPoint :: CBroadcastCapturedPoint ( int iPoint, int iTeam, const char *szName ) +CBroadcastCapturedPoint :: CBroadcastCapturedPoint (const int iPoint, const int iTeam, const char *szName) { m_iPoint = iPoint; m_iTeam = iTeam; @@ -103,7 +116,7 @@ void CBroadcastSpySap :: execute ( CBot *pBot ) if ( CTeamFortress2Mod::getTeam(m_pSpy) != pBot->getTeam() ) { if ( pBot->isVisible(m_pSpy) ) - ((CBotTF2*)pBot)->foundSpy(m_pSpy,CTeamFortress2Mod::getSpyDisguise(m_pSpy)); + static_cast(pBot)->foundSpy(m_pSpy,CTeamFortress2Mod::getSpyDisguise(m_pSpy)); } } // special delivery @@ -118,9 +131,9 @@ void CBroadcastFlagReturned :: execute ( CBot*pBot ) void CBroadcastFlagDropped :: execute ( CBot *pBot ) { if ( pBot->getTeam() == m_iTeam ) - ((CBotTF2*)pBot)->flagDropped(m_vOrigin); + static_cast(pBot)->flagDropped(m_vOrigin); else - ((CBotTF2*)pBot)->teamFlagDropped(m_vOrigin); + static_cast(pBot)->teamFlagDropped(m_vOrigin); } // flag picked up void CBotTF2FunctionEnemyAtIntel :: execute (CBot *pBot) @@ -135,15 +148,15 @@ void CBotTF2FunctionEnemyAtIntel :: execute (CBot *pBot) if ( pBot->getTeam() != m_iTeam ) { - ((CBotTF2*)pBot)->enemyAtIntel(m_vPos,m_iType,m_iCapIndex); + static_cast(pBot)->enemyAtIntel(m_vPos,m_iType,m_iCapIndex); } else - ((CBotTF2*)pBot)->teamFlagPickup(); + static_cast(pBot)->teamFlagPickup(); } -void CBotTF2 :: hearVoiceCommand ( edict_t *pPlayer, byte cmd ) +void CBotTF2 :: hearVoiceCommand ( edict_t *pPlayer, const byte voiceCmd ) { - switch ( cmd ) + switch ( voiceCmd ) { case TF_VC_SPY: // someone shouted spy, HACK the bot to think they saw a spy here too @@ -198,7 +211,7 @@ void CBotTF2 :: hearVoiceCommand ( edict_t *pPlayer, byte cmd ) updateCondition(CONDITION_PUSH); - if ( randomFloat(0,1.0) > 0.75f ) + if ( randomFloat(0.0f,1.0f) > 0.75f ) m_nextVoicecmd = TF_VC_YES; // don't break // flow down to uber if medic @@ -209,7 +222,7 @@ void CBotTF2 :: hearVoiceCommand ( edict_t *pPlayer, byte cmd ) { if ( !CTeamFortress2Mod::isFlagCarrier(pPlayer) ) secondaryAttack(); - else if ( randomFloat(0,1.0) > 0.5f ) + else if ( randomFloat(0.0f,1.0f) > 0.5f ) m_nextVoicecmd = TF_VC_NO; } } @@ -221,7 +234,7 @@ void CBotTF2 :: hearVoiceCommand ( edict_t *pPlayer, byte cmd ) updateCondition(CONDITION_PUSH); - if ( randomFloat(0,1.0) > 0.75f ) + if ( randomFloat(0.0f,1.0f) > 0.75f ) m_nextVoicecmd = TF_VC_YES; break; @@ -233,53 +246,103 @@ void CBotTF2 :: hearVoiceCommand ( edict_t *pPlayer, byte cmd ) void CBroadcastFlagCaptured :: execute ( CBot *pBot ) { if ( pBot->getTeam() == m_iTeam ) - ((CBotTF2*)pBot)->flagReset(); + static_cast(pBot)->flagReset(); else - ((CBotTF2*)pBot)->teamFlagReset(); + static_cast(pBot)->teamFlagReset(); } void CBroadcastRoundStart :: execute ( CBot *pBot ) { - ((CBotTF2*)pBot)->roundReset(m_bFullReset); + static_cast(pBot)->roundReset(m_bFullReset); } CBotFortress :: CBotFortress() -{ - CBot(); +{ + //CBot(); m_iLastFailSentryWpt = -1; m_iLastFailTeleExitWpt = -1; // remember prev spy disguised in game while playing - m_iPrevSpyDisguise = (TF_Class)0; + m_iPrevSpyDisguise = static_cast(0); + + m_fTaunting = 0.0f; + m_fDefendTime = 0.0f; + m_fHealFactor = 0.0f; + m_fFrenzyTime = 0.0f; + + m_fSpyCloakTime = 0.0f; + m_fSpyUncloakTime = 0.0f; + m_fLastSeeSpyTime = 0.0f; + m_fSpyDisguiseTime = 0.0f; + m_fLastSaySpy = 0.0f; + m_fPickupTime = 0.0f; + m_fLookAfterSentryTime = 0.0f; + + m_bSentryGunVectorValid = false; + m_bDispenserVectorValid = false; + m_bTeleportExitVectorValid = false; + m_fLastKnownTeamFlagTime = 0.0f; + m_fBackstabTime = 0.0f; + m_fUpdateClass = 0.0f; + m_fUseTeleporterTime = 0.0f; + m_fChangeClassTime = 0.0f; + m_bCheckClass = false; + + m_fMedicUpdatePosTime = 0.0f; + m_fCheckHealTime = 0.0f; + m_fDisguiseTime = 0.0f; + m_iDisguiseClass = 0; + m_fTeleporterEntPlacedTime = 0.0f; + m_fTeleporterExtPlacedTime = 0.0f; + m_iTeleportedPlayers = 0; + + m_iTeam = 0; + m_fWaitTurnSentry = 0.0f; + m_fHealingMoveTime = 0.0f; + m_fLastSentryEnemyTime = 0.0f; + + m_fSentryPlaceTime = 0.0f; + m_iSentryKills = 0.0f; + m_fSnipeAttackTime = 0.0f; + //m_fThisIsSpy = 0.0f; + m_pAmmo = nullptr; + m_pHealthkit = nullptr; + m_pFlag = nullptr; + //m_pBall = nullptr; + m_pHeal = nullptr; + m_fCallMedic = 0.0f; + m_fTauntTime = 0.0f; + m_fLastKnownFlagTime = 0.0f; + m_bHasFlag = false; + //m_hThrower = false; + //m_hCarrier = false; + + m_pSentryGun = nullptr; + m_pDispenser = nullptr; + m_pTeleExit = nullptr; + m_pTeleEntrance = nullptr; + m_pNearestDisp = nullptr; + m_pNearestEnemySentry = nullptr; + m_pNearestEnemyTeleporter = nullptr; + m_pNearestEnemyDisp = nullptr; + m_pNearestPipeGren = nullptr; + m_pPrevSpy = nullptr; - m_fSentryPlaceTime = 0; - m_iSentryKills = 0; - m_fSnipeAttackTime = 0; - m_pAmmo = NULL; - m_pHealthkit = NULL; - m_pFlag = NULL; - m_pHeal = NULL; - m_fCallMedic = 0; - m_fTauntTime = 0; - m_fLastKnownFlagTime = 0.0f; - m_bHasFlag = false; - m_pSentryGun = NULL; - m_pDispenser = NULL; - m_pTeleExit = NULL; - m_pTeleEntrance = NULL; - m_pNearestDisp = NULL; - m_pNearestEnemySentry = NULL; - m_pNearestEnemyTeleporter = NULL; - m_pNearestEnemyDisp = NULL; - m_pNearestPipeGren = NULL; - m_pPrevSpy = NULL; m_fSeeSpyTime = 0.0f; m_bEntranceVectorValid = false; - m_pLastCalledMedic = NULL; + m_pLastCalledMedic = nullptr; m_fLastCalledMedicTime = 0.0f; m_bIsBeingHealed = false; m_bCanBeUbered = false; + + m_iClass = TF_CLASS_MAX; + + std::memset(m_fClassDisguiseFitness, 0, sizeof(m_fClassDisguiseFitness)); + std::memset(m_fClassDisguiseTime, 0, sizeof(m_fClassDisguiseTime)); + std::memset(m_fSpyAttackedList, 0, sizeof(m_fSpyAttackedList)); + std::memset(m_fSpyLastUncloakedList, 0, sizeof(m_fSpyLastUncloakedList)); + std::memset(m_fCallMedicTime, 0, sizeof(m_fCallMedicTime)); } void CBotFortress :: checkDependantEntities () @@ -287,14 +350,13 @@ void CBotFortress :: checkDependantEntities () CBot::checkDependantEntities(); } -void CBotFortress :: init (bool bVarInit) +void CBotFortress :: init (const bool bVarInit) { CBot::init(bVarInit); m_bCheckClass = false; m_bHasFlag = false; m_iClass = TF_CLASS_MAX; // important - } void CBotFortress :: setup () @@ -305,67 +367,74 @@ void CBotFortress :: setup () bool CBotFortress::someoneCalledMedic() { return (getClass()==TF_CLASS_MEDIC) && - (m_pLastCalledMedic.get() != NULL) && + (m_pLastCalledMedic.get() != nullptr) && ((m_fLastCalledMedicTime+30.0f)>engine->Time()); } -bool CBotTF2 :: sentryRecentlyHadEnemy () +bool CBotTF2 :: sentryRecentlyHadEnemy () const { return (m_fLastSentryEnemyTime + 15.0f) > engine->Time(); } -bool CBotFortress :: startGame() +bool CBotFortress::startGame() { - int team = m_pPlayerInfo->GetTeamIndex(); - - m_iClass = (TF_Class)CClassInterface::getTF2Class(m_pEdict); + const string_t mapname = gpGlobals->mapname; + + const char* szmapname = mapname.ToCStr(); - if ( (team != TF2_TEAM_BLUE) && (team != TF2_TEAM_RED) ) + const int team = m_pPlayerInfo->GetTeamIndex(); + + m_iClass = static_cast(CClassInterface::getTF2Class(m_pEdict)); + if ((team != TF2_TEAM_BLUE) && (team != TF2_TEAM_RED)) { selectTeam(); } - else if ( m_iDesiredClass == -1 ) // invalid class + else if (m_iDesiredClass == -1) // invalid class { chooseClass(); } - else if ( (m_iDesiredClass>0 && (m_iClass != m_iDesiredClass)) || (m_iClass == TF_CLASS_MAX) ) + else if (m_iClass == TF_CLASS_MAX) + // Removed "(m_iDesiredClass > 0 && (m_iClass != m_iDesiredClass))" to avoid bots trying to change class when it was forced by something like in VSH and VIP maps { // can't change class in MVM during round! - if ( CTeamFortress2Mod::isMapType(TF_MAP_MVM) && CTeamFortress2Mod::hasRoundStarted() ) + if (CTeamFortress2Mod::isMapType(TF_MAP_MVM) && CTeamFortress2Mod::hasRoundStarted()) + { return true; - + } + if (CTeamFortress2Mod::isMapType(TF_MAP_SAXTON) || CTeamFortress2Mod::isMapType(TF_MAP_GG) || + std::strncmp(szmapname, "vip_", 4) == 0 || std::strncmp(szmapname, "cw_", 3) == 0 || + std::strncmp(szmapname, "ctf_2fort_sniperwars", 20) == 0 || std::strncmp(szmapname, "dm_", 3) == 0) + { + return true; + } selectClass(); } else + { return true; - + } return false; } void CBotFortress ::pickedUpFlag() { - m_bHasFlag = true; + m_bHasFlag = true; + //m_hCarrier = true; + //m_hThrower = true; // clear tasks m_pSchedules->freeMemory(); } void CBotFortress :: checkHealingValid () { - if ( m_pHeal ) + if (m_pHeal) { - if ( !CBotGlobals::entityIsValid(m_pHeal) || !CBotGlobals::entityIsAlive(m_pHeal) ) - { - m_pHeal = NULL; - removeCondition(CONDITION_SEE_HEAL); - } - else if ( !isVisible(m_pHeal) ) - { - m_pHeal = NULL; - removeCondition(CONDITION_SEE_HEAL); - } - else if ( getHealFactor(m_pHeal) == 0.0f ) + if (!CBotGlobals::entityIsValid(m_pHeal) || + !CBotGlobals::entityIsAlive(m_pHeal) || + !isVisible(m_pHeal) || + getHealFactor(m_pHeal) == 0.0f) { - m_pHeal = NULL; + m_pHeal = nullptr; removeCondition(CONDITION_SEE_HEAL); } } @@ -382,10 +451,9 @@ float CBotFortress :: getHealFactor ( edict_t *pPlayer ) // 4. player class // 5. etc float fFactor = 0.0f; - float fLastCalledMedic = 0.0f; + float fLastCalledMedic; bool bHeavyClass = false; edict_t *pMedigun = CTeamFortress2Mod::getMediGun(m_pEdict); - float fHealthPercent; Vector vVel = Vector(0,0,0); int iHighestScore = CTeamFortress2Mod::getHighestScore(); // adds extra factor to players who have recently shouted MEDIC! @@ -393,11 +461,12 @@ float CBotFortress :: getHealFactor ( edict_t *pPlayer ) { if (CTeamFortress2Mod::isMapType(TF_MAP_MVM)) { - if (strcmp(pPlayer->GetClassName(), "entity_revive_marker") == 0) + //TODO: MedicBots doesn't appear to revive players [APG]RoboCop[CL] + if (std::strcmp(pPlayer->GetClassName(), "entity_revive_marker") == 0) { - float fDistance = distanceFrom(pPlayer); + const float fDistance = distanceFrom(pPlayer); - if (fDistance < 0.1) + if (fDistance < 0.1f) return 1000; // in case of divide by zero return 200.0f / fDistance; @@ -409,7 +478,7 @@ float CBotFortress :: getHealFactor ( edict_t *pPlayer ) CClassInterface::getVelocity(pPlayer,&vVel); IPlayerInfo *p = playerinfomanager->GetPlayerInfo(pPlayer); - TF_Class iclass = (TF_Class)CClassInterface::getTF2Class(pPlayer); + const TF_Class iclass = static_cast(CClassInterface::getTF2Class(pPlayer)); if ( !CBotGlobals::entityIsAlive(pPlayer) || !p || p->IsDead() || p->IsObserver() || !p->IsConnected() ) return 0.0f; @@ -417,7 +486,7 @@ float CBotFortress :: getHealFactor ( edict_t *pPlayer ) if ( CClassInterface::getTF2NumHealers(pPlayer) > 1 ) return 0.0f; - fHealthPercent = (p->GetHealth()/p->GetMaxHealth()); + const float fHealthPercent = (static_cast(p->GetHealth()) / static_cast(p->GetMaxHealth())); switch ( iclass ) { @@ -433,40 +502,41 @@ float CBotFortress :: getHealFactor ( edict_t *pPlayer ) case TF_CLASS_HWGUY: case TF_CLASS_SOLDIER: case TF_CLASS_PYRO: - { - bHeavyClass = true; - - fFactor += 1.0f; - - if ( pMedigun ) - { - // overheal HWGUY/SOLDIER/DEMOMAN - fFactor += (float)(CClassInterface::getUberChargeLevel(pMedigun))/100; + { + bHeavyClass = true; //Unused? [APG]RoboCop[CL] + + fFactor += 1.0f; - if ( CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEdict) ) // uber deployed - fFactor += (1.0f - ((float)(CClassInterface::getUberChargeLevel(pMedigun))/100)); - } + if ( pMedigun ) + { + // overheal HWGUY/SOLDIER/DEMOMAN + fFactor += static_cast(CClassInterface::getUberChargeLevel(pMedigun))/100; + + if ( CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEdict) ) // uber deployed + fFactor += (1.0f - (static_cast(CClassInterface::getUberChargeLevel(pMedigun))/100)); } - // drop down + } + [[fallthrough]]; case TF_CLASS_SPY: - if ( iclass == TF_CLASS_SPY ) + if (iclass == TF_CLASS_SPY) { - int iClass,iTeam,iIndex,iHealth; + int iClass, iTeam, iIndex, iHealth; - if ( CClassInterface::getTF2SpyDisguised(pPlayer,&iClass,&iTeam,&iIndex,&iHealth) ) + if (CClassInterface::getTF2SpyDisguised(pPlayer, &iClass, &iTeam, &iIndex, &iHealth)) { - if ( iTeam != m_iTeam ) + if (iTeam != m_iTeam) return 0.0f; } - if ( CTeamFortress2Mod::TF2_IsPlayerCloaked(pPlayer) ) + if (CTeamFortress2Mod::TF2_IsPlayerCloaked(pPlayer)) return 0.0f; } + [[fallthrough]]; default: if ( !bHeavyClass && pMedigun ) // add more factor bassed on uber charge level - bot can gain more uber charge { - fFactor += (0.1f - ((float)(CClassInterface::getUberChargeLevel(pMedigun))/1000)); + fFactor += (0.1f - (static_cast(CClassInterface::getUberChargeLevel(pMedigun))/1000)); if ( (m_StatsCanUse.stats.m_iTeamMatesVisible == 1) && (fHealthPercent >= 1.0f) ) return 0.0f; // find another guy @@ -474,13 +544,9 @@ float CBotFortress :: getHealFactor ( edict_t *pPlayer ) if ( bHeavyClass ) { - IPlayerInfo *p; - - p = playerinfomanager->GetPlayerInfo(pPlayer); - - if ( p ) + if ( IPlayerInfo* info = playerinfomanager->GetPlayerInfo(pPlayer) ) { - if ( p->GetLastUserCommand().buttons & IN_ATTACK ) + if ( info->GetLastUserCommand().buttons & IN_ATTACK ) fFactor += 1.0f; } } @@ -494,16 +560,16 @@ float CBotFortress :: getHealFactor ( edict_t *pPlayer ) fFactor += (vVel.Length() / 1000); // favour big guys - fFactor += ((float)p->GetMaxHealth())/200; + fFactor += static_cast(p->GetMaxHealth())/200; // favour those with bigger scores if ( iHighestScore == 0 ) iHighestScore = 1; - fFactor += (((float)CClassInterface::getTF2Score(pPlayer))/iHighestScore)/2; + fFactor += (static_cast(CClassInterface::getTF2Score(pPlayer)) / static_cast(iHighestScore)) / 2; if ( (fLastCalledMedic = m_fCallMedicTime[ENTINDEX(pPlayer)-1]) > 0 ) - fFactor += MAX(0.0f,1.0f-((engine->Time() - fLastCalledMedic)/5)); + fFactor += std::max(0.0f,1.0f-((engine->Time() - fLastCalledMedic)/5)); if ( ((m_fLastCalledMedicTime + 5.0f) > engine->Time()) && ( m_pLastCalledMedic == pPlayer ) ) fFactor += 0.5f; @@ -515,16 +581,19 @@ float CBotFortress :: getHealFactor ( edict_t *pPlayer ) return fFactor; } - ///////////////////////////////////////////////////////////////////// // // When a new Entity becomes visible or Invisible this is called // // bVisible = true when pEntity is Visible // bVisible = false when pEntity becomes inVisible -bool CBotFortress :: setVisible ( edict_t *pEntity, bool bVisible ) +bool CBotFortress :: setVisible ( edict_t *pEntity, const bool bVisible ) { - bool bValid = CBot::setVisible(pEntity,bVisible); + const bool bValid = CBot::setVisible(pEntity,bVisible); + + const string_t mapname = gpGlobals->mapname; + + const char* szmapname = mapname.ToCStr(); // check for people to heal if ( m_iClass == TF_CLASS_MEDIC ) @@ -533,22 +602,22 @@ bool CBotFortress :: setVisible ( edict_t *pEntity, bool bVisible ) { if (CBotGlobals::isPlayer(pEntity) ) // player { - CBotWeapon *pMedigun = m_pWeapons->getWeapon(CWeapons::getWeapon(TF2_WEAPON_MEDIGUN)); - bool bIsSpy = CClassInterface::getTF2Class(pEntity)==TF_CLASS_SPY; + const CBotWeapon *pMedigun = m_pWeapons->getWeapon(CWeapons::getWeapon(TF2_WEAPON_MEDIGUN)); + const bool bIsSpy = CClassInterface::getTF2Class(pEntity)==TF_CLASS_SPY; int iDisguise = 0; if ( bIsSpy ) { - CClassInterface::getTF2SpyDisguised(pEntity,&iDisguise,NULL,NULL,NULL); + CClassInterface::getTF2SpyDisguised(pEntity,&iDisguise, nullptr, nullptr, nullptr); } if ( pMedigun && pMedigun->hasWeapon() && ( // Heal my team member or a spy if I think he is on my team (CBotGlobals::getTeam(pEntity) == getTeam()) || - ((bIsSpy&&!thinkSpyIsEnemy(pEntity,(TF_Class)iDisguise))) + ((bIsSpy&&!thinkSpyIsEnemy(pEntity,static_cast(iDisguise)))) ) ) { - Vector vPlayer = CBotGlobals::entityOrigin(pEntity); + const Vector vPlayer = CBotGlobals::entityOrigin(pEntity); if ( distanceFrom(vPlayer) <= CWaypointLocations::REACHABLE_RANGE ) { @@ -556,7 +625,7 @@ bool CBotFortress :: setVisible ( edict_t *pEntity, bool bVisible ) if ( (fFactor = getHealFactor(pEntity)) > 0 ) { - if ( m_pHeal.get() != NULL ) + if ( m_pHeal.get() != nullptr) { if ( m_pHeal != pEntity ) { @@ -597,10 +666,11 @@ bool CBotFortress :: setVisible ( edict_t *pEntity, bool bVisible ) } else { + //TODO: MedicBots doesn't appear to revive players [APG]RoboCop[CL] // I can see player recently shouted MEDIC! (and this is an MVM map) - if (CTeamFortress2Mod::isMapType(TF_MAP_MVM) && strcmp(pEntity->GetClassName(), "entity_revive_marker") == 0) + if (CTeamFortress2Mod::isMapType(TF_MAP_MVM) && std::strcmp(pEntity->GetClassName(), "entity_revive_marker") == 0) { - float fFactor = getHealFactor(pEntity); + const float fFactor = getHealFactor(pEntity); // add extra factor and ensure this guys actually being healed if (!m_pHeal || (m_pHeal == pEntity) || (fFactor < m_fHealFactor)) { @@ -620,14 +690,14 @@ bool CBotFortress :: setVisible ( edict_t *pEntity, bool bVisible ) } else if ( m_pHeal == pEntity ) { - m_pHeal = NULL; + m_pHeal = nullptr; removeCondition(CONDITION_SEE_HEAL); } } //else if ( m_iClass == TF_CLASS_SPY ) // Fix //{ // Look for nearest sentry to sap!!! - if ( bValid && bVisible ) + if ( (bValid && bVisible) && !(CTeamFortress2Mod::isMapType(TF_MAP_ZI) || CTeamFortress2Mod::isMapType(TF_MAP_SAXTON))) { if ( CTeamFortress2Mod::isSentry(pEntity,CTeamFortress2Mod::getEnemyTeam(getTeam())) ) { @@ -660,22 +730,24 @@ bool CBotFortress :: setVisible ( edict_t *pEntity, bool bVisible ) m_pNearestPipeGren = pEntity; } } + else if ((std::strncmp(szmapname, "koth_lakeside_event", 19) == 0 || std::strncmp(szmapname, "koth_viaduct_event", 18) == 0) && (CTeamFortress2Mod::isBossSummoned())) + return false; } else if ( pEntity == m_pNearestEnemySentry ) { - m_pNearestEnemySentry = NULL; + m_pNearestEnemySentry = nullptr; } else if ( pEntity == m_pNearestEnemyTeleporter ) { - m_pNearestEnemyTeleporter = NULL; + m_pNearestEnemyTeleporter = nullptr; } else if ( pEntity == m_pNearestEnemyDisp ) { - m_pNearestEnemyDisp = NULL; + m_pNearestEnemyDisp = nullptr; } else if ( pEntity == m_pNearestPipeGren ) { - m_pNearestPipeGren = NULL; + m_pNearestPipeGren = nullptr; } //} @@ -685,6 +757,10 @@ bool CBotFortress :: setVisible ( edict_t *pEntity, bool bVisible ) { if ( (m_pFlag!=pEntity) && CTeamFortress2Mod::isFlag(pEntity,getTeam()) ) m_pFlag = pEntity; + /*else if ((m_pFlag != pEntity) && CTeamFortress2Mod::isBall(pEntity, getTeam())) + { + m_pBall = pEntity; + }*/ else if ( (m_pNearestAllySentry != pEntity) && CTeamFortress2Mod::isSentry(pEntity,getTeam()) ) { if ( !m_pNearestAllySentry || (distanceFrom(pEntity) < distanceFrom(m_pNearestAllySentry))) @@ -706,7 +782,7 @@ bool CBotFortress :: setVisible ( edict_t *pEntity, bool bVisible ) fDistance = distanceFrom(pEntity); - if ( fDistance <= 200 ) + if ( fDistance <= 200.0f ) { if ( !m_pAmmo || (fDistance < distanceFrom(m_pAmmo))) m_pAmmo = pEntity; @@ -719,7 +795,7 @@ bool CBotFortress :: setVisible ( edict_t *pEntity, bool bVisible ) fDistance = distanceFrom(pEntity); - if ( fDistance <= 200 ) + if ( fDistance <= 200.0f ) { if ( !m_pHealthkit || (fDistance < distanceFrom(m_pHealthkit))) m_pHealthkit = pEntity; @@ -729,35 +805,36 @@ bool CBotFortress :: setVisible ( edict_t *pEntity, bool bVisible ) else { if ( pEntity == m_pFlag.get_old() ) - m_pFlag = NULL; + m_pFlag = nullptr; + /*else if (pEntity == m_pFlag.get_old()) + m_pBall = nullptr;*/ else if ( pEntity == m_pNearestDisp.get_old() ) - m_pNearestDisp = NULL; + m_pNearestDisp = nullptr; else if ( pEntity == m_pAmmo.get_old() ) - m_pAmmo = NULL; + m_pAmmo = nullptr; else if ( pEntity == m_pHealthkit.get_old() ) - m_pHealthkit = NULL; + m_pHealthkit = nullptr; else if ( pEntity == m_pHeal.get_old() ) - m_pHeal = NULL; + m_pHeal = nullptr; else if ( pEntity == m_pNearestPipeGren.get_old() ) - m_pNearestPipeGren = NULL; + m_pNearestPipeGren = nullptr; } return bValid; } -void CBotFortress :: medicCalled(edict_t *pPlayer ) +void CBotFortress :: medicCalled(edict_t *pPlayer) { - bool bGoto = true; - if ( pPlayer == m_pEdict ) return; // can't heal self! if ( m_iClass != TF_CLASS_MEDIC ) return; // nothing to do if ( distanceFrom(pPlayer) > 1024 ) // a bit far away return; // ignore - if ( (CBotGlobals::getTeam(pPlayer) == getTeam()) || (CClassInterface::getTF2Class(pPlayer) == TF_CLASS_SPY) && thinkSpyIsEnemy(pPlayer,CTeamFortress2Mod::getSpyDisguise(pPlayer)) ) + if ((CBotGlobals::getTeam(pPlayer) == getTeam()) || ((CClassInterface::getTF2Class(pPlayer) == TF_CLASS_SPY) && thinkSpyIsEnemy(pPlayer, CTeamFortress2Mod::getSpyDisguise(pPlayer)))) { - + bool bGoto = true; + m_pLastCalledMedic = pPlayer; m_fLastCalledMedicTime = engine->Time(); m_fCallMedicTime[ENTINDEX(pPlayer)-1] = m_fLastCalledMedicTime; @@ -778,14 +855,13 @@ void CBotFortress :: medicCalled(edict_t *pPlayer ) } m_pLastHeal = m_pHeal; - } } void CBotFortress ::waitBackstab () { m_fBackstabTime = engine->Time() + randomFloat(5.0f,10.0f); - m_pLastEnemy = NULL; + m_pLastEnemy = nullptr; } bool CBotFortress :: isAlive () @@ -798,20 +874,18 @@ void CBotFortress :: seeFriendlyHurtEnemy ( edict_t *pTeammate, edict_t *pEnemy, { if ( CBotGlobals::isPlayer(pEnemy) && (CClassInterface::getTF2Class(pEnemy) == TF_CLASS_SPY) ) { - m_fSpyList[ENTINDEX(pEnemy)-1] = engine->Time(); + m_fSpyAttackedList[ENTINDEX(pEnemy) - 1] = engine->Time(); } } void CBotFortress :: shot ( edict_t *pEnemy ) { - seeFriendlyHurtEnemy(m_pEdict,pEnemy,NULL); + seeFriendlyHurtEnemy(m_pEdict,pEnemy, nullptr); } void CBotFortress :: killed ( edict_t *pVictim, char *weapon ) { CBot::killed(pVictim,weapon); - - return; } void CBotFortress :: died ( edict_t *pKiller, const char *pszWeapon ) @@ -819,7 +893,7 @@ void CBotFortress :: died ( edict_t *pKiller, const char *pszWeapon ) CBot::died(pKiller,pszWeapon); if ( CBotGlobals::isPlayer(pKiller) && (CClassInterface::getTF2Class(pKiller) == TF_CLASS_SPY) ) - foundSpy(pKiller,(TF_Class)0); + foundSpy(pKiller,static_cast(0)); droppedFlag(); @@ -833,30 +907,30 @@ void CBotFortress :: died ( edict_t *pKiller, const char *pszWeapon ) void CBotTF2 :: buildingDestroyed ( int iType, edict_t *pAttacker, edict_t *pEdict ) { - eEngiBuild type = (eEngiBuild)iType; + const eEngiBuild type = static_cast(iType); switch ( type ) { case ENGI_DISP: - m_pDispenser = NULL; + m_pDispenser = nullptr; m_bDispenserVectorValid = false; m_iDispenserArea = 0; break; case ENGI_SENTRY : - m_pSentryGun = NULL; + m_pSentryGun = nullptr; m_bSentryGunVectorValid = false; m_iSentryArea = 0; break; case ENGI_ENTRANCE : - m_pTeleEntrance = NULL; + m_pTeleEntrance = nullptr; m_bEntranceVectorValid = false; m_iTeleEntranceArea = 0; break; case ENGI_EXIT : - m_pTeleExit = NULL; + m_pTeleExit = nullptr; m_bTeleportExitVectorValid = false; m_iTeleExitArea = 0; break; @@ -866,18 +940,24 @@ void CBotTF2 :: buildingDestroyed ( int iType, edict_t *pAttacker, edict_t *pEdi if ( pEdict && CBotGlobals::entityIsValid(pEdict) && pAttacker && CBotGlobals::entityIsValid(pAttacker) ) { - Vector vSentry = CBotGlobals::entityOrigin(pEdict); - Vector vAttacker = CBotGlobals::entityOrigin(pAttacker); + const Vector vSentry = CBotGlobals::entityOrigin(pEdict); + const Vector vAttacker = CBotGlobals::entityOrigin(pAttacker); m_pNavigator->belief(vSentry,vAttacker,bot_beliefmulti.GetFloat(),(vAttacker-vSentry).Length(),BELIEF_DANGER); } } -void CBotFortress ::wantToDisguise(bool bSet) +void CBotFortress ::wantToDisguise(const bool bSet) { - extern ConVar rcbot_tf2_debug_spies_cloakdisguise; + const string_t mapname = gpGlobals->mapname; - if ( rcbot_tf2_debug_spies_cloakdisguise.GetBool() ) + const char* szmapname = mapname.ToCStr(); + + if ((rcbot_tf2_debug_spies_cloakdisguise.GetBool() && + !(CTeamFortress2Mod::isMapType(TF_MAP_ZI) || CTeamFortress2Mod::isMapType(TF_MAP_SAXTON))) || + ((std::strncmp(szmapname, "koth_lakeside_event", 19) == 0 || + std::strncmp(szmapname, "koth_viaduct_event", 18) == 0) && + !CTeamFortress2Mod::isBossSummoned())) { if ( bSet ) m_fSpyDisguiseTime = 0.0f; @@ -889,27 +969,27 @@ void CBotFortress ::wantToDisguise(bool bSet) } -void CBotFortress :: detectedAsSpy( edict_t *pDetector, bool bDisguiseComprimised ) +void CBotFortress :: detectedAsSpy( edict_t *pDetector, const bool bDisguiseComprimised ) { if ( bDisguiseComprimised ) { - float fTime = engine->Time() - m_fDisguiseTime; + const float fTime = engine->Time() - m_fDisguiseTime; float fTotal = 0; if ( (m_fDisguiseTime < 1) || (fTime < 3.0f) ) return; - if ( m_fClassDisguiseTime[m_iDisguiseClass] == 0 ) + if ( m_fClassDisguiseTime[m_iDisguiseClass] == 0.0f ) m_fClassDisguiseTime [m_iDisguiseClass] = fTime; else m_fClassDisguiseTime [m_iDisguiseClass] = (m_fClassDisguiseTime [m_iDisguiseClass] * 0.5f) + (fTime * 0.5f); - for ( unsigned short int i = 0; i < 10; i ++ ) + for (const float i : m_fClassDisguiseTime) { - fTotal += m_fClassDisguiseTime[i]; + fTotal += i; } - for ( unsigned short int i = 0; i < 10; i ++ ) + for ( unsigned short i = 0; i < 10; i ++ ) { if ( m_fClassDisguiseTime[i] > 0 ) m_fClassDisguiseFitness[i] = (m_fClassDisguiseTime[i] / fTotal); @@ -937,48 +1017,50 @@ void CBotFortress :: spawnInit () m_fHealFactor = 0.0f; - m_pHealthkit = MyEHandle(NULL); - m_pFlag = MyEHandle(NULL); - m_pNearestDisp = MyEHandle(NULL); - m_pAmmo = MyEHandle(NULL); - m_pHeal = MyEHandle(NULL); - m_pNearestPipeGren = MyEHandle(NULL); + m_pHealthkit = MyEHandle(nullptr); + m_pFlag = MyEHandle(nullptr); + //m_pBall = MyEHandle(nullptr); + m_pNearestDisp = MyEHandle(nullptr); + m_pAmmo = MyEHandle(nullptr); + m_pHeal = MyEHandle(nullptr); + m_pNearestPipeGren = MyEHandle(nullptr); //m_bWantToZoom = false; - memset(m_fCallMedicTime,0,sizeof(float)*MAX_PLAYERS); + std::memset(m_fCallMedicTime,0,sizeof(float)*RCBOT_MAXPLAYERS); m_fWaitTurnSentry = 0.0f; - - + m_pLastSeeMedic.reset(); - memset(m_fSpyList,0,sizeof(float)*MAX_PLAYERS); + std::memset(m_fSpyAttackedList, 0, sizeof(float) * RCBOT_MAXPLAYERS); + std::memset(m_fSpyLastUncloakedList, 0, sizeof(float) * RCBOT_MAXPLAYERS); m_fTaunting = 0.0f; // bots not moving FIX m_fMedicUpdatePosTime = 0.0f; - m_pLastHeal = NULL; + m_pLastHeal = nullptr; m_fDisguiseTime = 0.0f; - m_pNearestEnemyTeleporter = NULL; - m_pNearestTeleEntrance = NULL; + m_pNearestEnemyTeleporter = nullptr; + m_pNearestTeleEntrance = nullptr; m_fBackstabTime = 0.0f; m_fPickupTime = 0.0f; m_fDefendTime = 0.0f; m_fLookAfterSentryTime = 0.0f; m_fSnipeAttackTime = 0.0f; + //m_fThisIsSpy = 0.0f; m_fSpyCloakTime = 0.0f; //engine->Time();// + randomFloat(5.0f,10.0f); m_fSpyUncloakTime = 0.0f; m_fLastSaySpy = 0.0f; m_fSpyDisguiseTime = 0.0f; - m_pHeal = NULL; - m_pNearestDisp = NULL; - m_pNearestEnemySentry = NULL; - m_pNearestAllySentry = NULL; + m_pHeal = nullptr; + m_pNearestDisp = nullptr; + m_pNearestEnemySentry = nullptr; + m_pNearestAllySentry = nullptr; m_bHasFlag = false; //m_pPrevSpy = NULL; //m_fSeeSpyTime = 0.0f; @@ -988,7 +1070,7 @@ void CBotFortress :: spawnInit () m_bTeleportExitVectorValid = false; } -bool CBotFortress :: isBuilding ( edict_t *pBuilding ) +bool CBotFortress :: isBuilding (const edict_t *pBuilding) { return (pBuilding == m_pSentryGun.get()) || (pBuilding == m_pDispenser.get()); } @@ -997,7 +1079,7 @@ bool CBotFortress :: isBuilding ( edict_t *pBuilding ) // return 1 : built ok // return 2 : next state // return 3 : another try -- restart -int CBotFortress :: engiBuildObject (int *iState, eEngiBuild iObject, float *fTime, int *iTries ) +int CBotFortress :: engiBuildObject (int *iState, const eEngiBuild iObject, float *fTime, int *iTries) { // can't build while standing on my building! if ( isBuilding(CClassInterface::getGroundEntity(m_pEdict)) ) @@ -1023,21 +1105,18 @@ int CBotFortress :: engiBuildObject (int *iState, eEngiBuild iObject, float *fTi break; case 1: { + // Fixed: EngiBots now face their SG Turrets in the correct direction - Ethan Bissbort CTraceFilterWorldAndPropsOnly filter; QAngle eyes = CBotGlobals::playerAngles(m_pEdict); - QAngle turn; + //QAngle turn; //Unused? [APG]RoboCop[CL] Vector forward; - Vector building; Vector vchosen; - Vector v_right, v_up, v_left; - Vector v_src = getEyePosition(); + Vector v_right, v_up; + const Vector v_src = getEyePosition(); // find best place to turn it to - trace_t *tr = CBotGlobals::getTraceResult(); - int iNextState = 2; - -// CBotWeapon *pWeapon = getCurrentWeapon(); + const trace_t *tr = CBotGlobals::getTraceResult(); - float bestfraction = 0.0f; + // CBotWeapon *pWeapon = getCurrentWeapon(); m_fWaitTurnSentry = 0.0f; // unselect current weapon @@ -1056,50 +1135,47 @@ int CBotFortress :: engiBuildObject (int *iState, eEngiBuild iObject, float *fTi }*/ *iTries = 0; - iNextState = 8; eyes.x = 0; // nullify pitch / we want yaw only AngleVectors(eyes,&forward,&v_right,&v_up); - building = v_src + (forward*100); + const Vector building = v_src + (forward * 100); ////////////////////////////////////////// // forward - CBotGlobals::traceLine(building,building + forward*4096.0,MASK_SOLID_BRUSHONLY,&filter); + CBotGlobals::traceLine(building,building + forward*4096.0f,MASK_SOLID_BRUSHONLY,&filter); - iNextState = 8; - bestfraction = tr->fraction; + int iNextState = 8; + float bestfraction = tr->fraction; //////////////////////////////////////// - - v_left = -v_right; - + // left - CBotGlobals::traceLine(building,building - v_right*4096.0,MASK_SOLID_BRUSHONLY,&filter); + CBotGlobals::traceLine(building,building - v_right*4096.0f,MASK_SOLID_BRUSHONLY,&filter); if ( tr->fraction > bestfraction ) { iNextState = 6; bestfraction = tr->fraction; - vchosen = building + v_right*4096.0; + vchosen = building - v_right*4096.0f; } //////////////////////////////////////// // back - CBotGlobals::traceLine(building,building - forward*4096.0,MASK_SOLID_BRUSHONLY,&filter); + CBotGlobals::traceLine(building,building - forward*4096.0f,MASK_SOLID_BRUSHONLY,&filter); if ( tr->fraction > bestfraction ) { iNextState = 4; bestfraction = tr->fraction; - vchosen = building - forward*4096.0; + vchosen = building - forward*4096.0f; } /////////////////////////////////// // right - CBotGlobals::traceLine(building,building + v_right*4096.0,MASK_SOLID_BRUSHONLY,&filter); + CBotGlobals::traceLine(building,building + v_right*4096.0f,MASK_SOLID_BRUSHONLY,&filter); if ( tr->fraction > bestfraction ) { iNextState = 2; bestfraction = tr->fraction; - vchosen = building + v_right*4096.0; + vchosen = building + v_right*4096.0f; } //////////////////////////////////// *iState = iNextState; @@ -1107,12 +1183,15 @@ int CBotFortress :: engiBuildObject (int *iState, eEngiBuild iObject, float *fTi #ifndef __linux__ if ( CClients::clientsDebugging(BOT_DEBUG_THINK) && !engine->IsDedicatedServer() ) { + const Vector v_left = -v_right; + debugoverlay->AddTriangleOverlay(v_src-v_left*32.0f,v_src+v_left*32.0f,v_src+(building-v_src),255,50,50,255,false,60.0f); debugoverlay->AddLineOverlay(building,vchosen,255,50,50,false,60.0f); debugoverlay->AddTextOverlayRGB(building+Vector(0,0,25),0,60.0f,255,255,255,255,"Chosen State: %d",iNextState); } #endif - } + } + break; case 2: { // let go @@ -1144,7 +1223,6 @@ int CBotFortress :: engiBuildObject (int *iState, eEngiBuild iObject, float *fTi } break; case 6: - { // let go m_pButtons->letGo(IN_ATTACK2); @@ -1220,7 +1298,7 @@ int CBotFortress :: engiBuildObject (int *iState, eEngiBuild iObject, float *fTi } else { - //*fTime = engine->Time() + randomFloat(0.5,1.0); + //*fTime = engine->Time() + randomFloat(0.5f,1.0f); *iTries = *iTries + 1; *iState = 1; @@ -1237,11 +1315,8 @@ int CBotFortress :: engiBuildObject (int *iState, eEngiBuild iObject, float *fTi removeCondition(CONDITION_COVERT); return 1; } - else - { - tapButton(IN_ATTACK); - duck(true);// crouch too - } + tapButton(IN_ATTACK); + duck(true);// crouch too // someone blew my sentry before I built it! if ( !hasEngineerBuilt(iObject) ) @@ -1253,12 +1328,12 @@ int CBotFortress :: engiBuildObject (int *iState, eEngiBuild iObject, float *fTi return 2; } -void CBotFortress :: setClass ( TF_Class _class ) +void CBotFortress :: setClass (const TF_Class _class) { m_iClass = _class; } -bool CBotFortress :: thinkSpyIsEnemy ( edict_t *pEdict, TF_Class iDisguise ) +bool CBotFortress :: thinkSpyIsEnemy (edict_t *pEdict, const TF_Class iDisguise) { return ( (m_fSeeSpyTime > engine->Time()) && // if bot is in spy check mode (m_pPrevSpy == pEdict) && // and its the last spy we saw @@ -1266,13 +1341,13 @@ bool CBotFortress :: thinkSpyIsEnemy ( edict_t *pEdict, TF_Class iDisguise ) ((m_iPrevSpyDisguise == iDisguise)||((engine->Time()-m_fLastSeeSpyTime)<3.0f)) ); } -bool CBotTF2 ::thinkSpyIsEnemy(edict_t *pEdict, TF_Class iDisguise) +bool CBotTF2 ::thinkSpyIsEnemy(edict_t *pEdict, const TF_Class iDisguise) { return CBotFortress::thinkSpyIsEnemy(pEdict,iDisguise) || (m_pCloakedSpy && (m_pCloakedSpy == pEdict) && !CTeamFortress2Mod::TF2_IsPlayerCloaked(m_pCloakedSpy)); // maybe i put him on fire } -bool CBotFortress :: isEnemy ( edict_t *pEdict,bool bCheckWeapons ) +bool CBotFortress :: isEnemy ( edict_t *pEdict, bool bCheckWeapons ) { if ( pEdict == m_pEdict ) return false; @@ -1294,57 +1369,47 @@ bool CBotFortress :: needAmmo () bool CBotFortress :: needHealth () { // don't need health if I'm being ubered or healed - return !m_bIsBeingHealed && !CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEdict) && ((getHealthPercent() < 0.7) || CTeamFortress2Mod::TF2_IsPlayerOnFire(m_pEdict)); + return !m_bIsBeingHealed && !CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEdict) && ((getHealthPercent() < 0.7f) || CTeamFortress2Mod::TF2_IsPlayerOnFire(m_pEdict)); } bool CBotTF2 :: needAmmo() { if ( getClass() == TF_CLASS_ENGINEER ) - { - CBotWeapon *pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(TF2_WEAPON_WRENCH)); - - if ( pWeapon ) + { + if ( const CBotWeapon *pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(TF2_WEAPON_WRENCH)) ) { - int iMetal = pWeapon->getAmmo(this); + const int iMetal = pWeapon->getAmmo(this); - if ( ( m_pSentryGun.get() == NULL ) || (CClassInterface::getTF2UpgradeLevel(m_pSentryGun) < 3) ) + if ( ( m_pSentryGun.get() == nullptr) || (CClassInterface::getTF2UpgradeLevel(m_pSentryGun) < 3) ) return ( iMetal < 200 ); // need 200 to upgrade sentry - else - return iMetal < 125; // need 125 for other stuff (e.g. teleporters) + return iMetal < 125; + // need 125 for other stuff (e.g. teleporters) } } else if ( getClass() == TF_CLASS_SOLDIER ) { - CBotWeapon *pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(TF2_WEAPON_ROCKETLAUNCHER)); - - if ( pWeapon ) + if ( const CBotWeapon *pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(TF2_WEAPON_ROCKETLAUNCHER)) ) { return ( pWeapon->getAmmo(this) < 1 ); } } else if ( getClass() == TF_CLASS_DEMOMAN ) { - CBotWeapon *pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(TF2_WEAPON_GRENADELAUNCHER)); - - if ( pWeapon ) + if ( const CBotWeapon *pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(TF2_WEAPON_GRENADELAUNCHER)) ) { return ( pWeapon->getAmmo(this) < 1 ); } } else if ( getClass() == TF_CLASS_HWGUY ) { - CBotWeapon *pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(TF2_WEAPON_MINIGUN)); - - if ( pWeapon ) + if ( const CBotWeapon *pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(TF2_WEAPON_MINIGUN)) ) { return ( pWeapon->getAmmo(this) < 1 ); } } else if ( getClass() == TF_CLASS_PYRO ) { - CBotWeapon *pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(TF2_WEAPON_FLAMETHROWER)); - - if ( pWeapon ) + if ( const CBotWeapon *pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(TF2_WEAPON_FLAMETHROWER)) ) { return ( pWeapon->getAmmo(this) < 1 ); } @@ -1363,7 +1428,7 @@ void CBotFortress :: currentlyDead () void CBotFortress :: modThink () { // get class - m_iClass = (TF_Class)CClassInterface::getTF2Class(m_pEdict); + m_iClass = static_cast(CClassInterface::getTF2Class(m_pEdict)); m_iTeam = getTeam(); //updateClass(); @@ -1372,20 +1437,22 @@ void CBotFortress :: modThink () else removeCondition(CONDITION_NEED_HEALTH); - if ( needAmmo() ) + if (needAmmo()) { updateCondition(CONDITION_NEED_AMMO); - else + } + else { removeCondition(CONDITION_NEED_AMMO); + } - //if ( !hasSomeConditions(CONDITION_PUSH) ) - ///{ - if ( CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEdict) || CTeamFortress2Mod::TF2_IsPlayerKrits(m_pEdict) ) - updateCondition(CONDITION_PUSH); + //if (!hasSomeConditions(CONDITION_PUSH)) { + if (CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEdict) || CTeamFortress2Mod::TF2_IsPlayerKrits(m_pEdict)) { + updateCondition(CONDITION_PUSH); + } //} if ( m_fCallMedic < engine->Time() ) { - if ( getHealthPercent() < 0.5 ) + if ( getHealthPercent() < 0.5f ) { m_fCallMedic = engine->Time() + randomFloat(10.0f,30.0f); @@ -1409,7 +1476,6 @@ void CBotFortress :: modThink () } } - // Check redundant tasks if ( !hasSomeConditions(CONDITION_NEED_AMMO) && m_pSchedules->isCurrentSchedule(SCHED_TF2_GET_AMMO) ) { @@ -1425,10 +1491,9 @@ void CBotFortress :: modThink () if ( m_bInitAlive ) { - Vector vOrigin = getOrigin(); - CWaypoint *pWpt = CWaypoints::getWaypoint(CWaypoints::nearestWaypointGoal(CWaypointTypes::W_FL_TELE_ENTRANCE,vOrigin,4096,m_iTeam)); + const Vector vOrigin = getOrigin(); - if ( pWpt ) + if ( CWaypoint *pWpt = CWaypoints::getWaypoint(CWaypoints::nearestWaypointGoal(CWaypointTypes::W_FL_TELE_ENTRANCE,vOrigin,4096.0f,m_iTeam)) ) { // Get the nearest waypoint outside spawn (flagged as a teleporter entrance) // useful for Engineers and medics who want to camp for players @@ -1446,7 +1511,7 @@ void CBotFortress :: modThink () m_pButtons->tap(IN_RELOAD); } - if ( !CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEdict) && (m_pNearestPipeGren.get() != NULL) ) + if ( !CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEdict) && (m_pNearestPipeGren.get() != nullptr) ) { if ( !m_pSchedules->hasSchedule(SCHED_GOOD_HIDE_SPOT) && (distanceFrom(m_pNearestPipeGren)getCurrentWaypointID()==-1)?CWaypointLocations::NearestWaypoint(getOrigin(),200.0f,-1,true):m_pNavigator->getCurrentWaypointID(); - int iTeleWpt = CTeamFortress2Mod::getTeleporterWaypoint(pExit); + const int iCurWpt = (m_pNavigator->getCurrentWaypointID()==-1)?CWaypointLocations::NearestWaypoint(getOrigin(),200.0f,-1,true):m_pNavigator->getCurrentWaypointID(); + const int iTeleWpt = CTeamFortress2Mod::getTeleporterWaypoint(pExit); - int iGoalId = m_pNavigator->getCurrentGoalID(); + const int iGoalId = m_pNavigator->getCurrentGoalID(); - float fGoalDistance = ((iCurWpt==-1)||(iGoalId==-1))?((m_vGoal-vEntrance).Length()+fEntranceDist) : CWaypointDistances::getDistance(iCurWpt,iGoalId); - float fTeleDistance = ((iTeleWpt==-1)||(iGoalId==-1))?((m_vGoal - vExit).Length()+fEntranceDist) : CWaypointDistances::getDistance(iTeleWpt,iGoalId); + const float fGoalDistance = ((iCurWpt==-1)||(iGoalId==-1))?((m_vGoal-vEntrance).Length()+fEntranceDist) : CWaypointDistances::getDistance(iCurWpt,iGoalId); + const float fTeleDistance = ((iTeleWpt==-1)||(iGoalId==-1))?((m_vGoal - vExit).Length()+fEntranceDist) : CWaypointDistances::getDistance(iTeleWpt,iGoalId); // still need to run to entrance then from exit if ( (fEntranceDist+fTeleDistance) < fGoalDistance )// ((m_vGoal - CBotGlobals::entityOrigin(pExit)).Length()+distanceFrom(pTele)) < fGoalDistance ) { // now check wait time based on how many players are waiting for the teleporter - float fMaxSpeed = CClassInterface::getMaxSpeed(m_pEdict); - float fDuration = CClassInterface::getTF2TeleRechargeDuration(pTele); + const float fMaxSpeed = CClassInterface::getMaxSpeed(m_pEdict); + const float fDuration = CClassInterface::getTF2TeleRechargeDuration(pTele); - edict_t *pOwner = CTeamFortress2Mod::getBuildingOwner(ENGI_TELE,ENTINDEX(pTele)); - float fRunTime; - float fWaitTime; - float fTime = engine->Time(); - - float fTeleRechargeTime = CTeamFortress2Mod::getTeleportTime(pOwner); + const edict_t *pOwner = CTeamFortress2Mod::getBuildingOwner(ENGI_TELE,ENTINDEX(pTele)); + const float fTime = engine->Time(); + + const float fTeleRechargeTime = CTeamFortress2Mod::getTeleportTime(pOwner); - fWaitTime = (fEntranceDist / fMaxSpeed); + float fWaitTime = (fEntranceDist / fMaxSpeed); // Teleporter never been used before and is ready to teleport - if ( fTeleRechargeTime > 0 ) + if ( fTeleRechargeTime > 0.0f ) { fWaitTime = (fEntranceDist / fMaxSpeed) + MAX(0,(fTeleRechargeTime - fTime) + fDuration); if ( countplayers > 0 ) - fWaitTime += fDuration * countplayers; + fWaitTime += fDuration * static_cast(countplayers); } // see if i can run it myself in this time - fRunTime = fGoalDistance / fMaxSpeed; + const float fRunTime = fGoalDistance / fMaxSpeed; return ( fWaitTime < fRunTime ); } @@ -1518,76 +1578,86 @@ bool CBotFortress :: isTeleporterUseful ( edict_t *pTele ) void CBotFortress :: selectTeam () { - char buffer[32]; + /*char buffer[32]; - int team = randomInt(1,2); + const int team = randomInt(1,2); - sprintf(buffer,"jointeam %d",team); + snprintf(buffer, sizeof(buffer), "jointeam %d", team); - helpers->ClientCommand(m_pEdict,buffer); + helpers->ClientCommand(m_pEdict,buffer);*/ + + helpers->ClientCommand(m_pEdict, "jointeam auto"); } void CBotFortress :: selectClass () { - char buffer[32]; + const char* cmd = nullptr; TF_Class _class; if ( m_iDesiredClass == 0 ) - _class = (TF_Class)randomInt(1,9); + _class = static_cast(randomInt(1, 9)); else - _class = (TF_Class)m_iDesiredClass; + _class = static_cast(m_iDesiredClass); + // only request class change if it doesn't match what the game is expecting + if ( CClassInterface::getTF2DesiredClass(m_pEdict) == m_iDesiredClass ) + { + return; + } + m_iClass = _class; if (_class == TF_CLASS_SCOUT) { - sprintf(buffer, "joinclass scout"); + cmd = "joinclass scout"; } else if (_class == TF_CLASS_ENGINEER) { - sprintf(buffer, "joinclass engineer"); + cmd = "joinclass engineer"; } else if (_class == TF_CLASS_DEMOMAN) { - sprintf(buffer, "joinclass demoman"); + cmd = "joinclass demoman"; } else if (_class == TF_CLASS_SOLDIER) { - sprintf(buffer, "joinclass soldier"); + cmd = "joinclass soldier"; } else if (_class == TF_CLASS_HWGUY) { - sprintf(buffer, "joinclass heavyweapons"); + cmd = "joinclass heavyweapons"; } else if (_class == TF_CLASS_MEDIC) { - sprintf(buffer, "joinclass medic"); + cmd = "joinclass medic"; } else if (_class == TF_CLASS_SPY) { - sprintf(buffer, "joinclass spy"); + cmd = "joinclass spy"; } else if (_class == TF_CLASS_PYRO) { - sprintf(buffer, "joinclass pyro"); + cmd = "joinclass pyro"; } - else + else if (_class == TF_CLASS_SNIPER) { - sprintf(buffer, "joinclass sniper"); + cmd = "joinclass sniper"; + } + if (cmd != nullptr) { + helpers->ClientCommand(m_pEdict, cmd); } - helpers->ClientCommand(m_pEdict, buffer); m_fChangeClassTime = engine->Time() + randomFloat(bot_min_cc_time.GetFloat(), bot_max_cc_time.GetFloat()); } -bool CBotFortress :: waitForFlag ( Vector *vOrigin, float *fWait, bool bFindFlag ) +bool CBotFortress :: waitForFlag ( Vector *vOrigin, float *fWait, const bool bFindFlag ) { // job calls! if ( someoneCalledMedic() ) return false; - if ( seeFlag(false) != NULL ) + if ( seeFlag(false) != nullptr) { - edict_t *m_pFlag = seeFlag(false); + //edict_t* m_pFlag = seeFlag(false); if ( CBotGlobals::entityIsValid(m_pFlag) ) { @@ -1596,6 +1666,13 @@ bool CBotFortress :: waitForFlag ( Vector *vOrigin, float *fWait, bool bFindFlag *vOrigin = CBotGlobals::entityOrigin(m_pFlag); *fWait = engine->Time() + 5.0f; } + /*else if (CBotGlobals::entityIsValid(m_pBall)) + { + lookAtEdict(m_pBall); + setLookAtTask(LOOK_EDICT); + *vOrigin = CBotGlobals::entityOrigin(m_pBall); + *fWait = engine->Time() + 5.0f; + }*/ else seeFlag(true); } @@ -1617,10 +1694,10 @@ bool CBotFortress :: waitForFlag ( Vector *vOrigin, float *fWait, bool bFindFlag return true; - //taunt(); + //taunt(); } -void CBotFortress :: foundSpy (edict_t *pEdict,TF_Class iDisguise) +void CBotFortress :: foundSpy (edict_t *pEdict, const TF_Class iDisguise) { m_pPrevSpy = pEdict; m_fSeeSpyTime = engine->Time() + randomFloat(9.0f,18.0f); @@ -1633,16 +1710,14 @@ void CBotFortress :: foundSpy (edict_t *pEdict,TF_Class iDisguise) }; // got shot by someone -bool CBotTF2 :: hurt ( edict_t *pAttacker, int iHealthNow, bool bDontHide ) +bool CBotTF2 :: hurt ( edict_t *pAttacker, const int iHealthNow, const bool bDontHide ) { - extern ConVar rcbot_spy_runaway_health; - if ( !pAttacker ) return false; if (( m_iClass != TF_CLASS_MEDIC ) || (!m_pHeal) ) { - if ( CBot::hurt(pAttacker,iHealthNow,true) ) + if (CBotFortress::hurt(pAttacker,iHealthNow,true) ) { if( m_bIsBeingHealed || m_bCanBeUbered ) { @@ -1661,9 +1736,8 @@ bool CBotTF2 :: hurt ( edict_t *pAttacker, int iHealthNow, bool bDontHide ) // run at flank while shooting CFindPathTask *pHideGoalPoint = new CFindPathTask(); - Vector vOrigin = CBotGlobals::entityOrigin(pAttacker); + const Vector vOrigin = CBotGlobals::entityOrigin(pAttacker); - pSchedule->addTask(new CFindGoodHideSpot(vOrigin)); pSchedule->addTask(pHideGoalPoint); pSchedule->addTask(new CBotNest()); @@ -1674,7 +1748,6 @@ bool CBotTF2 :: hurt ( edict_t *pAttacker, int iHealthNow, bool bDontHide ) pHideGoalPoint->getPassedVector(); pHideGoalPoint->setInterruptFunction(new CBotTF2CoverInterrupt()); - m_pSchedules->removeSchedule(SCHED_GOOD_HIDE_SPOT); m_pSchedules->addFront(pSchedule); } @@ -1696,7 +1769,7 @@ bool CBotTF2 :: hurt ( edict_t *pAttacker, int iHealthNow, bool bDontHide ) m_fFrenzyTime = 0.0f; if ( hasEnemy() ) setLastEnemy(m_pEnemy); - m_pEnemy = NULL; // reset enemy + m_pEnemy = nullptr; // reset enemy } } } @@ -1705,36 +1778,35 @@ bool CBotTF2 :: hurt ( edict_t *pAttacker, int iHealthNow, bool bDontHide ) } } - if ( pAttacker ) + if ((m_iClass == TF_CLASS_SPY) && !isCloaked() && + !CTeamFortress2Mod::isSentry(pAttacker, CTeamFortress2Mod::getEnemyTeam(m_iTeam))) { - if ( (m_iClass == TF_CLASS_SPY) && !isCloaked() && !CTeamFortress2Mod::isSentry(pAttacker,CTeamFortress2Mod::getEnemyTeam(m_iTeam)) ) - { - - // TO DO : make sure I'm not just caught in crossfire - // search for other team members - if ( !m_StatsCanUse.stats.m_iTeamMatesVisible || !m_StatsCanUse.stats.m_iTeamMatesInRange ) - m_fFrenzyTime = engine->Time() + randomFloat(2.0f,6.0f); + // TODO: make sure I'm not just caught in crossfire + // search for other team members + if (!m_StatsCanUse.stats.m_iTeamMatesVisible || !m_StatsCanUse.stats.m_iTeamMatesInRange) + m_fFrenzyTime = engine->Time() + randomFloat(2.0f, 6.0f); - if ( isDisguised() ) - detectedAsSpy(pAttacker,true); + if (isDisguised()) + detectedAsSpy(pAttacker, true); - if ( CBotGlobals::isPlayer(pAttacker) && (iHealthNow 0.3f) ) - { - // cloak and run - spyCloak(); - // hide and find health - m_pSchedules->removeSchedule(SCHED_GOOD_HIDE_SPOT); - m_pSchedules->addFront(new CGotoHideSpotSched(this,m_vHurtOrigin,new CBotTF2CoverInterrupt())); - wantToShoot(false); - m_fFrenzyTime = 0.0f; + if (CBotGlobals::isPlayer(pAttacker) && + (iHealthNow < rcbot_spy_runaway_health.GetInt()) && + (CClassInterface::getTF2SpyCloakMeter(m_pEdict) > 0.3f)) + { + // cloak and run + spyCloak(); + // hide and find health + m_pSchedules->removeSchedule(SCHED_GOOD_HIDE_SPOT); + m_pSchedules->addFront(new CGotoHideSpotSched(this, m_vHurtOrigin, new CBotTF2CoverInterrupt())); + wantToShoot(false); + m_fFrenzyTime = 0.0f; - if ( hasEnemy() ) - setLastEnemy(m_pEnemy); + if (hasEnemy()) + setLastEnemy(m_pEnemy); - m_pEnemy = NULL; // reset enemy + m_pEnemy = nullptr; // reset enemy - return true; - } + return true; } } @@ -1750,30 +1822,25 @@ void CBotTF2 :: spawnInit() CBotFortress::spawnInit(); m_iDesiredResistType = 0; - m_pMelee = NULL; - m_pPrimary = NULL; - m_pSecondary = NULL; - m_pHat = NULL; - m_pMisc = NULL; m_fUseBuffItemTime = 0.0f; //m_bHatEquipped = false; m_iTrapCPIndex = -1; - m_pHealer = NULL; + m_pHealer = nullptr; m_fCallMedic = engine->Time() + 10.0f; m_fCarryTime = 0.0f; m_bIsCarryingTeleExit = false; - m_bIsCarryingSentry = false;; - m_bIsCarryingDisp = false;; - m_bIsCarryingTeleEnt = false;; - m_bIsCarryingObj = false;; + m_bIsCarryingSentry = false; + m_bIsCarryingDisp = false; + m_bIsCarryingTeleEnt = false; + m_bIsCarryingObj = false; m_nextVoicecmd = TF_VC_INVALID; m_fAttackPointTime = 0.0f; m_fNextRevMiniGunTime = 0.0f; m_fRevMiniGunTime = 0.0f; - m_pCloakedSpy = NULL; + m_pCloakedSpy = nullptr; m_fRemoveSapTime = 0.0f; @@ -1797,9 +1864,9 @@ void CBotTF2 :: spawnInit() m_iPrevWeaponSelectFailed = 0; - m_fCheckNextCarrying = 0.0; + m_fCheckNextCarrying = 0.0f; - + m_iMvMUpdateTime = TIME_TO_TICKS(10.0f); // Wait about 10 seconds after spawning } // return true if we don't want to hang around on the point @@ -1814,31 +1881,30 @@ bool CBotTF2 ::checkAttackPoint() return false; } -void CBotTF2 :: setClass ( TF_Class _class ) +void CBotTF2 :: setClass (const TF_Class _class) { m_iClass = _class; } -void CBotTF2 :: highFivePlayer ( edict_t *pPlayer, float fYaw ) +void CBotTF2 :: highFivePlayer ( edict_t *pPlayer, const float fYaw ) const { if ( !m_pSchedules->isCurrentSchedule(SCHED_TAUNT) ) m_pSchedules->addFront(new CBotTauntSchedule(pPlayer,fYaw)); } // bOverride will be true in messaround mode -void CBotTF2 :: taunt ( bool bOverride ) +void CBotTF2 :: taunt (const bool bOverride) { - extern ConVar rcbot_taunt; // haven't taunted for a while, no emeny, not ubered, OK! Taunt! if ( bOverride || (!m_bHasFlag && rcbot_taunt.GetBool() && !CTeamFortress2Mod::TF2_IsPlayerOnFire(m_pEdict) && !m_pEnemy && (m_fTauntTime < engine->Time()) && (!CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEdict))) ) { helpers->ClientCommand(m_pEdict,"taunt"); - m_fTauntTime = engine->Time() + randomFloat(40.0,100.0); // Don't taunt for another minute or two - m_fTaunting = engine->Time() + 5.0; + m_fTauntTime = engine->Time() + randomFloat(40.0f,100.0f); // Don't taunt for another minute or two + m_fTaunting = engine->Time() + 5.0f; } } -void CBotTF2::healedPlayer(edict_t *pPlayer, float fAmount) +void CBotTF2::healedPlayer(edict_t *pPlayer, const float fAmount) { if ( m_iClass == TF_CLASS_ENGINEER ) // my dispenser was used { @@ -1855,11 +1921,11 @@ edict_t *CBotFortress::getVisibleSpecial() // this is a special visible which will return something important // that should be visible quickly, e.g. an enemy sentry gun // or teleporter entrance for bots to make decisions quickly - if ( (signed int)m_iSpecialVisibleId >= gpGlobals->maxClients ) + if ( m_iSpecialVisibleId >= gpGlobals->maxClients ) m_iSpecialVisibleId = 0; pPlayer = INDEXENT(m_iSpecialVisibleId+1); - pReturn = NULL; + pReturn = nullptr; if ( pPlayer && (CClassInterface::getTF2Class(pPlayer) == TF_CLASS_ENGINEER) ) { @@ -1883,7 +1949,6 @@ edict_t *CBotFortress::getVisibleSpecial() if ( !pTele || randomInt(0,1) ) pReturn = pSentry; } - } } @@ -1899,7 +1964,7 @@ NEW COMMAND SYNTAX: - "build 1 0" - Build teleporter entrance - "build 1 1" - Build teleporter exit */ -void CBotTF2 :: engineerBuild ( eEngiBuild iBuilding, eEngiCmd iEngiCmd ) +void CBotTF2 :: engineerBuild (const eEngiBuild iBuilding, const eEngiCmd iEngiCmd) { //char buffer[16]; //char cmd[256]; @@ -1926,9 +1991,9 @@ void CBotTF2 :: engineerBuild ( eEngiBuild iBuilding, eEngiCmd iEngiCmd ) //m_pTeleExit = NULL; helpers->ClientCommand(m_pEdict,"build 1 1"); break; - default: - return; - break; + //default: + //return; + //break; } } else @@ -1938,32 +2003,32 @@ void CBotTF2 :: engineerBuild ( eEngiBuild iBuilding, eEngiCmd iEngiCmd ) switch ( iBuilding ) { case ENGI_DISP : - m_pDispenser = NULL; + m_pDispenser = nullptr; m_bDispenserVectorValid = false; m_iDispenserArea = 0; helpers->ClientCommand(m_pEdict,"destroy 0 0"); break; case ENGI_SENTRY : - m_pSentryGun = NULL; + m_pSentryGun = nullptr; m_bSentryGunVectorValid = false; m_iSentryArea = 0; helpers->ClientCommand(m_pEdict,"destroy 2 0"); break; case ENGI_ENTRANCE : - m_pTeleEntrance = NULL; + m_pTeleEntrance = nullptr; m_bEntranceVectorValid = false; m_iTeleEntranceArea = 0; helpers->ClientCommand(m_pEdict,"destroy 1 0"); break; case ENGI_EXIT : - m_pTeleExit = NULL; + m_pTeleExit = nullptr; m_bTeleportExitVectorValid = false; m_iTeleExitArea = 0; helpers->ClientCommand(m_pEdict,"destroy 1 1"); break; - default: - return; - break; + //default: + //return; + //break; } } @@ -1976,9 +2041,7 @@ void CBotTF2 :: updateCarrying () { if ( (m_bIsCarryingObj = CClassInterface::isCarryingObj(m_pEdict)) == true ) { - edict_t *pCarriedObj = CClassInterface::getCarriedObj(m_pEdict); - - if ( pCarriedObj ) + if ( edict_t *pCarriedObj = CClassInterface::getCarriedObj(m_pEdict) ) { m_bIsCarryingTeleExit = CTeamFortress2Mod::isTeleporterExit(pCarriedObj,m_iTeam,true); m_bIsCarryingSentry = CTeamFortress2Mod::isSentry(pCarriedObj,m_iTeam,true); @@ -1988,32 +2051,127 @@ void CBotTF2 :: updateCarrying () } else { - m_bIsCarryingTeleExit = NULL; - m_bIsCarryingSentry = NULL; - m_bIsCarryingDisp = NULL; - m_bIsCarryingTeleEnt = NULL; + m_bIsCarryingTeleExit = false; + m_bIsCarryingSentry = false; + m_bIsCarryingDisp = false; + m_bIsCarryingTeleEnt = false; + } +} + +/// @brief TF2 Mann vs Machine update/think function +void CBotTF2::MvM_Update() +{ + if (CTeamFortress2Mod::isMapType(TF_MAP_MVM)) + { + if (getTeam() != TF2_TEAM_RED) + return; // ?? bots should be on RED team + + if (!MvM_IsReady() && entprops->GameRules_GetRoundState() == RoundState_BetweenRounds) + { + int num_players = 0, num_ready = 0; + const CBotSchedule* sched = m_pSchedules->getCurrentSchedule(); + + // Engineer: Doesn't have a dispenser and is not building something + if (getClass() == TF_CLASS_ENGINEER && m_pDispenser.get() == nullptr && sched && !sched->isID(SCHED_TF_BUILD)) + { + updateCondition(CONDITION_CHANGED); + } + + for (int i = 1; i <= gpGlobals->maxClients; i++) + { + edict_t* player = INDEXENT(i); + + if (!CBotGlobals::entityIsValid(player)) + continue; + + IPlayerInfo* info = playerinfomanager->GetPlayerInfo(player); + + if (!info) + continue; + + if (info->GetTeamIndex() != TF2_TEAM_RED) + continue; + + if (info->IsFakeClient()) + continue; + + // Engineer: Only ready up if my sentry is setup. TO-DO: Also do the same for dispenser and teleporter + if (getClass() == TF_CLASS_ENGINEER && m_pSentryGun.get() == nullptr) + { + num_players = 99; + logger->Log(LogLevel::DEBUG, "%3.2f - %s is skipping Ready Check. Reason: Sentry Gun not built!", gpGlobals->curtime, m_szBotName); + break; + } + + // Medic: Only ready up if my uber is near ready. + if (getClass() == TF_CLASS_MEDIC) + { + edict_t* medigun = CTeamFortress2Mod::getMediGun(m_pEdict); + if (medigun && CClassInterface::getUberChargeLevel(medigun) <= 98) + { + num_players = 99; + logger->Log(LogLevel::DEBUG, "%3.2f - %s is skipping Ready Check. Reason: Waiting to fill Ubercharge!", gpGlobals->curtime, m_szBotName); + break; + } + } + + // at this point we know the player is a human and is on RED team + num_players++; // increase player count + + char ready[] = "m_bPlayerReady"; + if (entprops->GameRules_GetProp(ready, 4, i) != 0) + num_ready++; + } + + logger->Log(LogLevel::DEBUG, "%3.2f - %s Ready Check - <%i/%i>", gpGlobals->curtime, m_szBotName, num_players, num_ready); + + if (num_players == num_ready) // All humans on RED team are ready + { + helpers->ClientCommand(m_pEdict, "tournament_player_readystate 1"); + logger->Log(LogLevel::INFO, "%3.2f - TF2 MvM RCBot \"<%s><>\" is ready.", gpGlobals->curtime, m_szBotName); + } + } + } +} + +bool CBotTF2::MvM_IsReady() const +{ + if (CTeamFortress2Mod::isMapType(TF_MAP_MVM)) + { + char ready[] = "m_bPlayerReady"; + return entprops->GameRules_GetProp(ready, 4, engine->IndexOfEdict(getEdict())) == 1; } + return false; +} + +// TODO: To allow bots to menuselect in order to buy upgrades? [APG]RoboCop[CL] +void CBotTF2::MvM_Upgrade() +{ } void CBotTF2 :: checkBuildingsValid (bool bForce) // force check carrying { + const string_t mapname = gpGlobals->mapname; + + const char* szmapname = mapname.ToCStr(); + if ( m_pSentryGun ) { - if ( !CBotGlobals::entityIsValid(m_pSentryGun) || !CBotGlobals::entityIsAlive(m_pSentryGun) || !CTeamFortress2Mod::isSentry(m_pSentryGun,m_iTeam) ) + if ( (!CBotGlobals::entityIsValid(m_pSentryGun) || !CBotGlobals::entityIsAlive(m_pSentryGun) || !CTeamFortress2Mod::isSentry(m_pSentryGun,m_iTeam)) && !((std::strncmp(szmapname, "koth_lakeside_event", 19) == 0 || std::strncmp(szmapname, "koth_viaduct_event", 18) == 0) && (CTeamFortress2Mod::isBossSummoned()))) { - m_pSentryGun = NULL; + m_pSentryGun = nullptr; m_prevSentryHealth = 0; m_iSentryArea = 0; } - else if ( CClassInterface::getSentryEnemy(m_pSentryGun) != NULL ) + else if ( CClassInterface::getSentryEnemy(m_pSentryGun) != nullptr) m_fLastSentryEnemyTime = engine->Time(); } if ( m_pDispenser ) { - if ( !CBotGlobals::entityIsValid(m_pDispenser) || !CBotGlobals::entityIsAlive(m_pDispenser) || !CTeamFortress2Mod::isDispenser(m_pDispenser,m_iTeam) ) + if ( (!CBotGlobals::entityIsValid(m_pDispenser) || !CBotGlobals::entityIsAlive(m_pDispenser) || !CTeamFortress2Mod::isDispenser(m_pDispenser,m_iTeam)) && !((std::strncmp(szmapname, "koth_lakeside_event", 19) == 0 || std::strncmp(szmapname, "koth_viaduct_event", 18) == 0) && (CTeamFortress2Mod::isBossSummoned()))) { - m_pDispenser = NULL; + m_pDispenser = nullptr; m_prevDispHealth = 0; m_iDispenserArea = 0; } @@ -2021,9 +2179,9 @@ void CBotTF2 :: checkBuildingsValid (bool bForce) // force check carrying if ( m_pTeleEntrance ) { - if ( !CBotGlobals::entityIsValid(m_pTeleEntrance) || !CBotGlobals::entityIsAlive(m_pTeleEntrance) || !CTeamFortress2Mod::isTeleporterEntrance(m_pTeleEntrance,m_iTeam) ) + if ( (!CBotGlobals::entityIsValid(m_pTeleEntrance) || !CBotGlobals::entityIsAlive(m_pTeleEntrance) || !CTeamFortress2Mod::isTeleporterEntrance(m_pTeleEntrance,m_iTeam)) && !((std::strncmp(szmapname, "koth_lakeside_event", 19) == 0 || std::strncmp(szmapname, "koth_viaduct_event", 18) == 0) && (CTeamFortress2Mod::isBossSummoned()))) { - m_pTeleEntrance = NULL; + m_pTeleEntrance = nullptr; m_prevTeleEntHealth = 0; m_iTeleEntranceArea = 0; } @@ -2031,9 +2189,9 @@ void CBotTF2 :: checkBuildingsValid (bool bForce) // force check carrying if ( m_pTeleExit ) { - if ( !CBotGlobals::entityIsValid(m_pTeleExit) || !CBotGlobals::entityIsAlive(m_pTeleExit) || !CTeamFortress2Mod::isTeleporterExit(m_pTeleExit,m_iTeam) ) + if ( (!CBotGlobals::entityIsValid(m_pTeleExit) || !CBotGlobals::entityIsAlive(m_pTeleExit) || !CTeamFortress2Mod::isTeleporterExit(m_pTeleExit,m_iTeam)) && !((std::strncmp(szmapname, "koth_lakeside_event", 19) == 0 || std::strncmp(szmapname, "koth_viaduct_event", 18) == 0) && (CTeamFortress2Mod::isBossSummoned()))) { - m_pTeleExit = NULL; + m_pTeleExit = nullptr; m_prevTeleExtHealth = 0; m_iTeleExitArea = 0; } @@ -2041,9 +2199,9 @@ void CBotTF2 :: checkBuildingsValid (bool bForce) // force check carrying } // Find the EDICT_T of the building that the engineer just built... -edict_t *CBotTF2 :: findEngineerBuiltObject ( eEngiBuild iBuilding, int index ) +edict_t *CBotTF2 :: findEngineerBuiltObject ( eEngiBuild iBuilding, const int index ) { - int team = getTeam(); + const int team = getTeam(); edict_t *pBest = INDEXENT(index); @@ -2074,7 +2232,7 @@ edict_t *CBotTF2 :: findEngineerBuiltObject ( eEngiBuild iBuilding, int index ) m_pSentryGun = pBest; break; default: - return NULL; + return nullptr; } } @@ -2091,7 +2249,7 @@ void CBotTF2 :: died ( edict_t *pKiller, const char *pszWeapon ) { m_pNavigator->belief(CBotGlobals::entityOrigin(pKiller),getEyePosition(),bot_beliefmulti.GetFloat(),distanceFrom(pKiller),BELIEF_DANGER); - if ( !strncmp(pszWeapon,"obj_sentrygun",13) || !strncmp(pszWeapon,"obj_minisentry",14) ) + if ( !std::strncmp(pszWeapon,"obj_sentrygun",13) || !std::strncmp(pszWeapon,"obj_minisentry",14) ) m_pLastEnemySentry = CTeamFortress2Mod::getMySentryGun(pKiller); } } @@ -2101,14 +2259,14 @@ void CBotTF2 :: killed ( edict_t *pVictim, char *weapon ) { CBotFortress::killed(pVictim,weapon); - if ( (m_pSentryGun.get() != NULL) && (m_iClass == TF_CLASS_ENGINEER) && weapon && *weapon && (strncmp(weapon,"obj_sentry",10) == 0) ) + if ( (m_pSentryGun.get() != nullptr) && (m_iClass == TF_CLASS_ENGINEER) && weapon && *weapon && (std::strncmp(weapon,"obj_sentry",10) == 0) ) { m_iSentryKills++; if ( pVictim && CBotGlobals::entityIsValid(pVictim) ) { - Vector vSentry = CBotGlobals::entityOrigin(m_pSentryGun); - Vector vVictim = CBotGlobals::entityOrigin(pVictim); + const Vector vSentry = CBotGlobals::entityOrigin(m_pSentryGun); + const Vector vVictim = CBotGlobals::entityOrigin(pVictim); m_pNavigator->belief(vVictim,vSentry,bot_beliefmulti.GetFloat(),(vSentry-vVictim).Length(),BELIEF_SAFETY); } @@ -2120,7 +2278,7 @@ void CBotTF2 :: killed ( edict_t *pVictim, char *weapon ) { if ( m_pPrevSpy == pVictim ) { - m_pPrevSpy = NULL; + m_pPrevSpy = nullptr; m_fLastSeeSpyTime = 0.0f; } @@ -2135,14 +2293,35 @@ void CBotTF2 :: capturedFlag () taunt(); } -void CBotTF2 :: spyDisguise ( int iTeam, int iClass ) +void CBotTF2 :: pointCaptured() +{ + taunt(); +} + +void CBotTF2 :: spyDisguise (const int iTeam, const int iClass) { + const string_t mapname = gpGlobals->mapname; + + const char* szmapname = mapname.ToCStr(); + //char cmd[256]; - if ( iTeam == 3 ) + if (((iTeam == 3) && + !(CTeamFortress2Mod::isMapType(TF_MAP_ZI) || CTeamFortress2Mod::isMapType(TF_MAP_SAXTON))) || + ((std::strncmp(szmapname, "koth_lakeside_event", 19) == 0 || + std::strncmp(szmapname, "koth_viaduct_event", 18) == 0) && + !CTeamFortress2Mod::isBossSummoned())) + { m_iImpulse = 230 + iClass; - else if ( iTeam == 2 ) + } + else if (((iTeam == 2) && + !(CTeamFortress2Mod::isMapType(TF_MAP_ZI) || CTeamFortress2Mod::isMapType(TF_MAP_SAXTON))) || + ((std::strncmp(szmapname, "koth_lakeside_event", 19) == 0 || + std::strncmp(szmapname, "koth_viaduct_event", 18) == 0) && + !CTeamFortress2Mod::isBossSummoned())) + { m_iImpulse = 220 + iClass; + } m_fDisguiseTime = engine->Time(); m_iDisguiseClass = iClass; @@ -2172,7 +2351,6 @@ bool CBotTF2 :: isDisguised () } return false; - } void CBotTF2 :: updateClass () @@ -2181,29 +2359,29 @@ void CBotTF2 :: updateClass () { /*const char *model = m_pPlayerInfo->GetModelName(); - if ( strcmp(model,"soldier") ) + if ( std::strcmp(model,"soldier") ) m_iClass = TF_CLASS_SOLDIER; - else if ( strcmp(model,"sniper") ) + else if ( std::strcmp(model,"sniper") ) m_iClass = TF_CLASS_SNIPER; - else if ( strcmp(model,"heavyweapons") ) + else if ( std::strcmp(model,"heavyweapons") ) m_iClass = TF_CLASS_HWGUY; - else if ( strcmp(model,"medic") ) + else if ( std::strcmp(model,"medic") ) m_iClass = TF_CLASS_MEDIC; - else if ( strcmp(model,"pyro") ) + else if ( std::strcmp(model,"pyro") ) m_iClass = TF_CLASS_PYRO; - else if ( strcmp(model,"spy") ) + else if ( std::strcmp(model,"spy") ) m_iClass = TF_CLASS_SPY; - else if ( strcmp(model,"scout") ) + else if ( std::strcmp(model,"scout") ) m_iClass = TF_CLASS_SCOUT; - else if ( strcmp(model,"engineer") ) + else if ( std::strcmp(model,"engineer") ) m_iClass = TF_CLASS_ENGINEER; - else if ( strcmp(model,"demoman") ) + else if ( std::strcmp(model,"demoman") ) m_iClass = TF_CLASS_DEMOMAN; else - m_iClass = TF_CLASS_CIVILIAN; + m_iClass = TF_CLASS_UNDEFINED; */ - m_fUpdateClass = 0; + m_fUpdateClass = 0.0f; } } @@ -2223,7 +2401,7 @@ void CBotTF2 :: seeFriendlyKill ( edict_t *pTeamMate, edict_t *pDied, CWeapon *p { if ( m_pPrevSpy == pDied ) { - m_pPrevSpy = NULL; + m_pPrevSpy = nullptr; m_fLastSeeSpyTime = 0.0f; } @@ -2231,19 +2409,19 @@ void CBotTF2 :: seeFriendlyKill ( edict_t *pTeamMate, edict_t *pDied, CWeapon *p } } - void CBotTF2 :: seeFriendlyDie ( edict_t *pDied, edict_t *pKiller, CWeapon *pWeapon ) { if ( pKiller && !m_pEnemy && !hasSomeConditions(CONDITION_SEE_CUR_ENEMY) ) { + const bool shouldReact = !isDisguised() && !isCloaked(); //if ( pWeapon ) //{ // DOD_Class pclass = (DOD_Class)CClassInterface::getPlayerClassDOD(pKiller); if ( pWeapon && (pWeapon->getID() == TF2_WEAPON_SENTRYGUN) ) { - if (!isDisguised && !isCloaked) - addVoiceCommand(TF_VC_SENTRYAHEAD); + if (shouldReact) + addVoiceCommand(TF_VC_SENTRYAHEAD); updateCondition(CONDITION_COVERT); m_fCurrentDanger += 100.0f; m_pLastEnemySentry = CTeamFortress2Mod::getMySentryGun(pKiller); @@ -2258,8 +2436,8 @@ void CBotTF2 :: seeFriendlyDie ( edict_t *pDied, edict_t *pKiller, CWeapon *pWea } else { - if (!isDisguised && !isCloaked) - addVoiceCommand(TF_VC_INCOMING); + if (shouldReact) + addVoiceCommand(TF_VC_INCOMING); updateCondition(CONDITION_COVERT); m_fCurrentDanger += 50.0f; } @@ -2269,21 +2447,18 @@ void CBotTF2 :: seeFriendlyDie ( edict_t *pDied, edict_t *pKiller, CWeapon *pWea // encourage bots to snoop out enemy or throw grenades m_fLastSeeEnemy = engine->Time(); m_pLastEnemy = pKiller; - m_fLastUpdateLastSeeEnemy = 0; + m_fLastUpdateLastSeeEnemy = 0.0f; m_vLastSeeEnemy = CBotGlobals::entityOrigin(m_pLastEnemy); m_vLastSeeEnemyBlastWaypoint = m_vLastSeeEnemy; - CWaypoint *pWpt = CWaypoints::getWaypoint(CWaypointLocations::NearestBlastWaypoint(m_vLastSeeEnemy,getOrigin(),4096.0,-1,true,true,false,false,0,false)); - - if ( pWpt ) + if ( CWaypoint *pWpt = CWaypoints::getWaypoint(CWaypointLocations::NearestBlastWaypoint(m_vLastSeeEnemy,getOrigin(),4096.0f,-1,true,true,false,false,0,false)) ) m_vLastSeeEnemyBlastWaypoint = pWpt->getOrigin(); updateCondition(CONDITION_CHANGED); } } - -void CBotTF2 :: engiBuildSuccess ( eEngiBuild iBuilding, int index ) +void CBotTF2 :: engiBuildSuccess (const eEngiBuild iBuilding, const int index) { edict_t *pEntity = findEngineerBuiltObject(iBuilding, index); @@ -2310,35 +2485,35 @@ void CBotTF2 :: engiBuildSuccess ( eEngiBuild iBuilding, int index ) { m_fTeleporterExtPlacedTime = engine->Time(); - if ( m_pTeleEntrance.get() == NULL ) // doesn't have entrance built + if ( m_pTeleEntrance.get() == nullptr) // doesn't have entrance built m_iTeleportedPlayers = 0; } } } -bool CBotTF2 :: hasEngineerBuilt ( eEngiBuild iBuilding ) +bool CBotTF2 :: hasEngineerBuilt (const eEngiBuild iBuilding) { switch ( iBuilding ) { case ENGI_SENTRY: - return m_pSentryGun!=NULL; // TODO - break; + return m_pSentryGun!= nullptr; // TODO + //break; case ENGI_DISP: - return m_pDispenser!=NULL; // TODO - break; + return m_pDispenser!= nullptr; // TODO + //break; case ENGI_ENTRANCE: - return m_pTeleEntrance!=NULL; // TODO - break; + return m_pTeleEntrance!= nullptr; // TODO + //break; case ENGI_EXIT: - return m_pTeleExit!=NULL; // TODO - break; + return m_pTeleExit!= nullptr; // TODO + //break; } return false; } // ENEMY Flag dropped -void CBotFortress :: flagDropped ( Vector vOrigin ) +void CBotFortress :: flagDropped (const Vector& vOrigin) { m_vLastKnownFlagPoint = vOrigin; m_fLastKnownFlagTime = engine->Time() + 60.0f; @@ -2347,7 +2522,7 @@ void CBotFortress :: flagDropped ( Vector vOrigin ) m_pSchedules->removeSchedule(SCHED_RETURN_TO_INTEL); } -void CBotFortress :: teamFlagDropped ( Vector vOrigin ) +void CBotFortress :: teamFlagDropped (const Vector& vOrigin) { m_vLastKnownTeamFlagPoint = vOrigin; @@ -2366,12 +2541,15 @@ void CBotFortress :: callMedic () helpers->ClientCommand (m_pEdict,"saveme"); } -bool CBotTF2 :: canGotoWaypoint (Vector vPrevWaypoint, CWaypoint *pWaypoint, CWaypoint *pPrev) +bool CBotTF2 :: canGotoWaypoint (const Vector& vPrevWaypoint, CWaypoint* pWaypoint, CWaypoint* pPrev) { - static edict_t *pSentry; + const string_t mapname = gpGlobals->mapname; - if ( CBot::canGotoWaypoint(vPrevWaypoint,pWaypoint,pPrev) ) + const char* szmapname = mapname.ToCStr(); + + if (CBotFortress::canGotoWaypoint(vPrevWaypoint,pWaypoint,pPrev) ) { + static edict_t *pSentry; if ( pWaypoint->hasFlag(CWaypointTypes::W_FL_OWNER_ONLY) ) { int area = pWaypoint->getArea(); @@ -2390,11 +2568,11 @@ bool CBotTF2 :: canGotoWaypoint (Vector vPrevWaypoint, CWaypoint *pWaypoint, CWa if ( pWaypoint->hasFlag(CWaypointTypes::W_FL_ROCKET_JUMP) ) { CBotWeapons *pWeapons = getWeapons(); - CBotWeapon *pWeapon; - // only roccket jump if more than 50% health - if (getHealthPercent() > 0.5) + // only rocket jump if more than 50% health + if (getHealthPercent() > 0.5f) { + CBotWeapon *pWeapon; // only soldiers or demomen can use these if ( getClass() == TF_CLASS_SOLDIER ) { @@ -2441,14 +2619,14 @@ bool CBotTF2 :: canGotoWaypoint (Vector vPrevWaypoint, CWaypoint *pWaypoint, CWa return hasFlag(); } - pSentry = NULL; + pSentry = nullptr; if ( m_iClass == TF_CLASS_ENGINEER ) pSentry = m_pSentryGun.get(); else if ( m_iClass == TF_CLASS_SPY ) pSentry = m_pNearestEnemySentry.get(); - if ( pSentry != NULL ) + if ( pSentry != nullptr) { Vector vWaypoint = pWaypoint->getOrigin(); Vector vWptMin = vWaypoint.Min(vPrevWaypoint) - Vector(32,32,32); @@ -2481,18 +2659,18 @@ bool CBotTF2 :: canGotoWaypoint (Vector vPrevWaypoint, CWaypoint *pWaypoint, CWa } - if ( CTeamFortress2Mod::isMapType(TF_MAP_CART) || CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE) ) + if ( CTeamFortress2Mod::isMapType(TF_MAP_CART) || CTeamFortress2Mod::isMapType(TF_MAP_CPPL) || CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE) || (std::strncmp(szmapname, "sd_offload", 10) == 0) || (std::strncmp(szmapname, "koth_namicott", 13) == 0) || (std::strncmp(szmapname, "ctf_system", 10) == 0) || (std::strncmp(szmapname, "cp_helmsdeep_v2", 15) == 0)) { - if ( m_pRedPayloadBomb.get() != NULL ) + if ( m_pRedPayloadBomb.get() != nullptr) { - edict_t *pSentry = m_pRedPayloadBomb.get(); + edict_t *p_sentry = m_pRedPayloadBomb.get(); // check path doesn't go through pay load bomb Vector vWaypoint = pWaypoint->getOrigin(); Vector vWptMin = vWaypoint.Min(vPrevWaypoint) - Vector(32,32,32); Vector vWptMax = vWaypoint.Max(vPrevWaypoint) + Vector(32,32,32); - Vector vSentry = CBotGlobals::entityOrigin(pSentry); + Vector vSentry = CBotGlobals::entityOrigin(p_sentry); Vector vMax = vSentry+Vector(32,32,32); Vector vMin = vSentry-Vector(32,32,32); @@ -2516,14 +2694,14 @@ bool CBotTF2 :: canGotoWaypoint (Vector vPrevWaypoint, CWaypoint *pWaypoint, CWa } } - if ( m_pBluePayloadBomb.get() != NULL ) + if ( m_pBluePayloadBomb.get() != nullptr) { - edict_t *pSentry = m_pBluePayloadBomb.get(); + edict_t *p_sentry = m_pBluePayloadBomb.get(); Vector vWaypoint = pWaypoint->getOrigin(); Vector vWptMin = vWaypoint.Min(vPrevWaypoint) - Vector(32,32,32); Vector vWptMax = vWaypoint.Max(vPrevWaypoint) + Vector(32,32,32); - Vector vSentry = CBotGlobals::entityOrigin(pSentry); + Vector vSentry = CBotGlobals::entityOrigin(p_sentry); Vector vMax = vSentry+Vector(32,32,32); Vector vMin = vSentry-Vector(32,32,32); @@ -2550,7 +2728,7 @@ bool CBotTF2 :: canGotoWaypoint (Vector vPrevWaypoint, CWaypoint *pWaypoint, CWa return true; } - else if ( pWaypoint->hasFlag(CWaypointTypes::W_FL_FALL) ) + if ( pWaypoint->hasFlag(CWaypointTypes::W_FL_FALL) ) { return ( getClass() == TF_CLASS_SCOUT ); } @@ -2569,14 +2747,12 @@ void CBotFortress ::waitCloak() } bool CBotFortress:: wantToCloak() -{ - extern ConVar rcbot_tf2_debug_spies_cloakdisguise; - +{ if ( rcbot_tf2_debug_spies_cloakdisguise.GetBool() ) - { + { if ( ( m_fFrenzyTime < engine->Time() ) && (!m_pEnemy || !hasSomeConditions(CONDITION_SEE_CUR_ENEMY)) ) { - return ( (!m_bStatsCanUse || (m_StatsCanUse.stats.m_iEnemiesVisible>0)) && (CClassInterface::getTF2SpyCloakMeter(m_pEdict) > 90.0f) && ( m_fCurrentDanger > TF2_SPY_CLOAK_BELIEF )); + return ( (!m_bStatsCanUse || (m_StatsCanUse.stats.m_iEnemiesVisible>0)) && (CClassInterface::getTF2SpyCloakMeter(m_pEdict) > 90.0f) && (static_cast(m_fCurrentDanger) > TF2_SPY_CLOAK_BELIEF)); } } @@ -2588,16 +2764,15 @@ bool CBotFortress:: wantToUnCloak () if ( wantToShoot() && m_pEnemy && hasSomeConditions(CONDITION_SEE_CUR_ENEMY) ) { // hopefully the enemy can't see me - if ( CBotGlobals::isAlivePlayer(m_pEnemy) && ( fabs(CBotGlobals::yawAngleFromEdict(m_pEnemy,getOrigin())) > bot_spyknifefov.GetFloat() ) ) + if ( CBotGlobals::isAlivePlayer(m_pEnemy) && ( std::fabs(CBotGlobals::yawAngleFromEdict(m_pEnemy,getOrigin())) > bot_spyknifefov.GetFloat() ) ) return true; - else if ( !m_pEnemy || !hasSomeConditions(CONDITION_SEE_CUR_ENEMY) ) + if ( !m_pEnemy || !hasSomeConditions(CONDITION_SEE_CUR_ENEMY) ) return (m_fCurrentDanger < 1.0f); } return (m_bStatsCanUse && (m_StatsCanUse.stats.m_iEnemiesVisible == 0)); } - void CBotTF2 :: spyUnCloak () { if ( CTeamFortress2Mod::TF2_IsPlayerCloaked(m_pEdict) && (m_fSpyCloakTime < engine->Time()) ) @@ -2658,32 +2833,28 @@ void CBotFortress::chooseClass() } else { - float fClassFitness[10]; - float fTotalFitness = 0; - float fRandom; + std::array fClassFitness; + float fTotalFitness = 0.0f; int iNumMedics = 0; - int i = 0; - int iTeam = getTeam(); - int iClass; - edict_t *pPlayer; + const int iTeam = getTeam(); - for (i = 1; i < 10; i++) + for (int i = 1; i < 10; ++i) fClassFitness[i] = 1.0f; - if ((m_iClass >= 0) && (m_iClass < 10)) + if (m_iClass < 10) fClassFitness[m_iClass] = 0.1f; - for (i = 1; i <= gpGlobals->maxClients; i++) + for (int i = 1; i <= gpGlobals->maxClients; ++i) { - pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(i); if (CBotGlobals::entityIsValid(pPlayer) && (CTeamFortress2Mod::getTeam(pPlayer) == iTeam)) { - iClass = CClassInterface::getTF2Class(pPlayer); + const int iClass = CClassInterface::getTF2Class(pPlayer); if (iClass == TF_CLASS_MEDIC) - iNumMedics++; + ++iNumMedics; if ((iClass >= 0) && (iClass < 10)) fClassFitness[iClass] *= 0.6f; @@ -2692,55 +2863,54 @@ void CBotFortress::chooseClass() if (CTeamFortress2Mod::isMapType(TF_MAP_MVM)) { - fClassFitness[TF_CLASS_ENGINEER] *= 1.5; - fClassFitness[TF_CLASS_SPY] *= 0.6; - fClassFitness[TF_CLASS_SCOUT] *= 0.6; - fClassFitness[TF_CLASS_HWGUY] *= 1.5; - fClassFitness[TF_CLASS_MEDIC] *= 1.1; - fClassFitness[TF_CLASS_SOLDIER] *= 1.5; - fClassFitness[TF_CLASS_DEMOMAN] *= 1.4; - fClassFitness[TF_CLASS_PYRO] *= 1.6; + fClassFitness[TF_CLASS_ENGINEER] *= 1.6f; + fClassFitness[TF_CLASS_SPY] *= 0.5f; + fClassFitness[TF_CLASS_SCOUT] *= 0.6f; + fClassFitness[TF_CLASS_HWGUY] *= 1.5f; + fClassFitness[TF_CLASS_MEDIC] *= 1.0f; + fClassFitness[TF_CLASS_SOLDIER] *= 1.5f; + fClassFitness[TF_CLASS_DEMOMAN] *= 1.4f; + fClassFitness[TF_CLASS_PYRO] *= 1.2f; // attacking team? } else if (CTeamFortress2Mod::isAttackDefendMap()) { - if (getTeam() == TF2_TEAM_BLUE) + if (iTeam == TF2_TEAM_BLUE) { - fClassFitness[TF_CLASS_ENGINEER] *= 0.75; - fClassFitness[TF_CLASS_SPY] *= 1.25; - fClassFitness[TF_CLASS_SCOUT] *= 1.05; + fClassFitness[TF_CLASS_ENGINEER] *= 0.75f; + fClassFitness[TF_CLASS_SPY] *= 1.25f; + fClassFitness[TF_CLASS_SCOUT] *= 1.05f; } else { - fClassFitness[TF_CLASS_ENGINEER] *= 2.0; - fClassFitness[TF_CLASS_SCOUT] *= 0.5; - fClassFitness[TF_CLASS_HWGUY] *= 1.5; - fClassFitness[TF_CLASS_MEDIC] *= 1.1; + fClassFitness[TF_CLASS_ENGINEER] *= 2.0f; + fClassFitness[TF_CLASS_SCOUT] *= 0.5f; + fClassFitness[TF_CLASS_HWGUY] *= 1.5f; + fClassFitness[TF_CLASS_MEDIC] *= 1.1f; } } - else if (CTeamFortress2Mod::isMapType(TF_MAP_CP)) + else if (CTeamFortress2Mod::isMapType(TF_MAP_CP) || CTeamFortress2Mod::isMapType(TF_MAP_CPPL)) fClassFitness[TF_CLASS_SCOUT] *= 1.2f; - if (m_pLastEnemySentry.get() != NULL) + if (m_pLastEnemySentry) { - fClassFitness[TF_CLASS_SPY] *= 1.25; - fClassFitness[TF_CLASS_DEMOMAN] *= 1.3; + fClassFitness[TF_CLASS_SPY] *= 1.25f; + fClassFitness[TF_CLASS_DEMOMAN] *= 1.3f; } if (iNumMedics == 0) fClassFitness[TF_CLASS_MEDIC] *= 2.0f; + for (const float& fitness : fClassFitness) + fTotalFitness += fitness; - for (int i = 1; i < 10; i++) - fTotalFitness += fClassFitness[i]; - - fRandom = randomFloat(0, fTotalFitness); + const float fRandom = randomFloat(0.0f, fTotalFitness); - fTotalFitness = 0; + fTotalFitness = 0.0f; m_iDesiredClass = 0; - for (int i = 1; i < 10; i++) + for (int i = 1; i < 10; ++i) { fTotalFitness += fClassFitness[i]; @@ -2777,222 +2947,30 @@ void CBotFortress::updateConditions() removeCondition(CONDITION_BUILDING_SAPPED); } } -void CBotTF2 :: giveWeapon ( int slot, int index ) -{ - /* - // GiveNamedItem - extern IServerGameEnts *servergameents; - edict_t *pWeapon; - CBaseEntity *pEnt = m_pEdict->GetUnknown()->GetBaseEntity(); - unsigned int gni_offset = 399; - unsigned int rpi_offset = 269; - extern IServerTools *servertools; - - GiveNamedItem_func *GiveNamedItem = (GiveNamedItem_func*)(&((unsigned long*)pEnt)[gni_offset]); - RemovePlayerItem_func *RemovePlayerItem = (RemovePlayerItem_func*)(&((unsigned long*)pEnt)[rpi_offset]); - CBaseHandle *m_Weapons = CClassInterface::getWeaponList(m_pEdict); - CBaseHandle *m_Weapon_iter; - - m_Weapon_iter = m_Weapons; - - bool bFound = false; - - m_pWeapons->update(overrideAmmoTypes()); - CBotWeapon *pWeaponInSlot = m_pWeapons->getCurrentWeaponInSlot(slot); +void CBotTF2 :: onInventoryApplication () +{ + //CBot::onInventoryApplication(); //TODO: [APG]RoboCop[CL] +} - if ( pWeaponInSlot->getWeaponEntity() ) - { - (*RemovePlayerItem)(pWeaponInSlot->getWeaponEntity()->GetUnknown()->GetBaseEntity()); +bool m_classWasForced = false; - // find classname for index (slot must also match) - const char *pWeaponName;// = CTeamFortress2Mod::findWeaponWithIndex(index,slot); +void CBotTF2::modThink() +{ + static bool bNeedHealth; + static bool bNeedAmmo; - if ( pWeaponName != NULL ) - { - CBaseEntity *pNewWeapon = (*GiveNamedItem)(pWeaponName,0); + const string_t mapname = gpGlobals->mapname; - edict_t *pEdict = servergameents->BaseEntityToEdict(pNewWeapon); + const char* szmapname = mapname.ToCStr(); - CClassInterface::setEntityIndex_Level_Quality(pEdict,index); - } + // FIX: MUST Update class + m_iClass = static_cast(CClassInterface::getTF2Class(m_pEdict)); - }*/ -} - -void CBotTF2 :: onInventoryApplication () -{ - m_fEquipHatTime = engine->Time() + 0.1f; -} - -void CBotTF2 :: PostGiveNamedItem ( CEconItemView *cscript ) -{ - m_pVTable = cscript->m_pVTable; - m_pVTable_Attributes = cscript->m_AttributeList.m_pVTable; -} -/* -void CBotTF2 :: addLoadoutWeapon ( CTF2Loadout *weap ) -{ - m_LoadoutsApplyAttributes.Push(weap); -} -*/ -void CBotTF2::upgradeWeapon(int iSlot) -{ - CTF2Loadout *wep = NULL; - // (const char *pszClassname, int iIndex, int iQuality, int iMinLevel, int iMaxLevel) - CTF2Loadout copy(wep->m_pszClassname, wep->m_iIndex, wep->m_iQuality, wep->m_iMinLevel, wep->m_iMaxLevel); - - switch (iSlot) - { - case TF2_SLOT_MELEE: - wep = m_pMelee; - break; - case TF2_SLOT_PRMRY: - wep = m_pPrimary; - break; - case TF2_SLOT_SCNDR: - wep = m_pSecondary; - break; - } - - RCBotPluginMeta::TF2_RemoveWeaponSlot(m_pEdict,iSlot); - - copy = *wep; - copy.m_bCanBeUsedInMedieval = wep->m_bCanBeUsedInMedieval; - - //copy.m_Attributes - - RCBotPluginMeta::givePlayerLoadOut(m_pEdict, ©, iSlot, m_pVTable, m_pVTable_Attributes); -} - -bool m_classWasForced = false; - -void CBotTF2::modThink() -{ - static bool bNeedHealth; - static bool bNeedAmmo; - static bool bIsCloaked; - - extern ConVar rcbot_customloadouts; - - // FIX: MUST Update class - m_iClass = (TF_Class)CClassInterface::getTF2Class(m_pEdict); - - if (rcbot_customloadouts.GetBool() && m_pVTable && m_pVTable_Attributes && (m_fEquipHatTime > 0.0f) && (m_fEquipHatTime < engine->Time())) - { - // Equip - if (isAlive()) - { - if (isDesiredClass(m_iClass)) - { - extern ConVar rcbot_melee_only; - bool bAdded = false; - - if ((m_iClass == TF_CLASS_ENGINEER) && !CTeamFortress2Mod::isMedievalMode()) - m_pMelee = NULL; - else if (m_pMelee == NULL) - m_pMelee = CTeamFortress2Mod::findRandomWeaponLoadOutInSlot(m_iClass, TF2_SLOT_MELEE); - - extern ConVar *mp_stalemate_meleeonly; - - if (!mp_stalemate_meleeonly || !mp_stalemate_meleeonly->GetBool() || !CTeamFortress2Mod::isSuddenDeath()) - { - // only add primary / secondary weapons if they are given them by the map - /*if (RCBotPluginMeta::TF2_getPlayerWeaponSlot(m_pEdict, TF2_SLOT_PRMRY) && - RCBotPluginMeta::TF2_getPlayerWeaponSlot(m_pEdict, TF2_SLOT_SCNDR)) - {*/ - if (m_pPrimary == NULL) - m_pPrimary = CTeamFortress2Mod::findRandomWeaponLoadOutInSlot(m_iClass, TF2_SLOT_PRMRY); - - if ((m_iClass == TF_CLASS_SPY) && !CTeamFortress2Mod::isMedievalMode()) - m_pSecondary = NULL; - else if (m_pSecondary == NULL) - m_pSecondary = CTeamFortress2Mod::findRandomWeaponLoadOutInSlot(m_iClass, TF2_SLOT_SCNDR); - } - else - { - // sudden death - m_pPrimary = NULL; - m_pSecondary = NULL; - } - - // adding this will remove the builder -- don't do it!!! - if ((m_iClass == TF_CLASS_ENGINEER) && !CTeamFortress2Mod::isMedievalMode()) - m_pHat = NULL; - else if (m_pHat == NULL) - m_pHat = CTeamFortress2Mod::findRandomWeaponLoadOutInSlot(m_iClass, TF2_SLOT_HAT); - - if (m_pMisc == NULL) - m_pMisc = CTeamFortress2Mod::findRandomWeaponLoadOutInSlot(m_iClass, TF2_SLOT_MISC); - - if (m_pMelee != NULL) - bAdded = RCBotPluginMeta::givePlayerLoadOut(m_pEdict, m_pMelee, TF2_SLOT_MELEE, m_pVTable, m_pVTable_Attributes); - if (m_pPrimary != NULL) - bAdded |= RCBotPluginMeta::givePlayerLoadOut(m_pEdict, m_pPrimary, TF2_SLOT_PRMRY, m_pVTable, m_pVTable_Attributes); - if (m_pSecondary != NULL) - bAdded |= RCBotPluginMeta::givePlayerLoadOut(m_pEdict, m_pSecondary, TF2_SLOT_SCNDR, m_pVTable, m_pVTable_Attributes); - if (m_pHat != NULL) - bAdded |= RCBotPluginMeta::givePlayerLoadOut(m_pEdict, m_pHat, TF2_SLOT_HAT, m_pVTable, m_pVTable_Attributes); - if (m_pMisc != NULL) - bAdded |= RCBotPluginMeta::givePlayerLoadOut(m_pEdict, m_pMisc, TF2_SLOT_MISC, m_pVTable, m_pVTable_Attributes); - - m_fEquipHatTime = 0.0f; - m_bHatEquipped = true; - - - if (bAdded) - { - m_pSchedules->freeMemory(); // Could mess up weapons - m_pWeapons->resetSignature(); - m_pWeapons->update(overrideAmmoTypes()); - } - } - } - } - /* - if ( rcbot_customloadouts.GetBool() ) - { - if ( !m_bMeleeAttempt && (m_pWeapons->getCurrentWeaponInSlot(TF2_SLOT_MELEE) == NULL) ) - { - m_bMeleeAttempt = true; - UTIL_TF2EquipStockWeapon(m_pEdict,TF2_SLOT_MELEE,m_pVTable,m_pVTable_Attributes); - } - else if ( !m_bPrimaryAttempt && (m_pWeapons->getCurrentWeaponInSlot(TF2_SLOT_PRMRY) == NULL) ) - { - m_bPrimaryAttempt = true; - UTIL_TF2EquipStockWeapon(m_pEdict,TF2_SLOT_PRMRY,m_pVTable,m_pVTable_Attributes); - } - else if ( !m_bSecondaryAttempt && (m_pWeapons->getCurrentWeaponInSlot(TF2_SLOT_SCNDR) == NULL) ) - { - m_bSecondaryAttempt = true; - UTIL_TF2EquipStockWeapon(m_pEdict,TF2_SLOT_SCNDR,m_pVTable,m_pVTable_Attributes); - } - }*/ - - /* - - if ( m_toApply.size() > 0 ) - { - CTF2LoadoutAdded *p = m_toApply.top(); - - p->m_loadout->applyAttributes(p->m_pEnt); - - m_toApply.pop(); - - delete p; - } - */ - /* if ( !m_LoadoutsApplyAttributes.IsEmpty() ) - { - CTF2Loadout - }*/ - - - - if (CTeamFortress2Mod::isLosingTeam(m_iTeam)) - wantToShoot(false); - //if ( m_pWeapons ) // done in bot.cpp - // m_pWeapons->update(false); // don't override ammo types from engine + if (CTeamFortress2Mod::isLosingTeam(m_iTeam)) + wantToShoot(false); + //if ( m_pWeapons ) // done in bot.cpp + // m_pWeapons->update(false); // don't override ammo types from engine bNeedHealth = hasSomeConditions(CONDITION_NEED_HEALTH); bNeedAmmo = hasSomeConditions(CONDITION_NEED_AMMO); @@ -3004,7 +2982,7 @@ void CBotTF2::modThink() if (wantToListen()) { - if ((m_pNearestAllySentry.get() != NULL) && (CClassInterface::getSentryEnemy(m_pNearestAllySentry) != NULL)) + if ((m_pNearestAllySentry.get() != nullptr) && (CClassInterface::getSentryEnemy(m_pNearestAllySentry) != nullptr)) { m_PlayerListeningTo = m_pNearestAllySentry; m_bListenPositionValid = true; @@ -3015,7 +2993,7 @@ void CBotTF2::modThink() } } - if (CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE)) + if (CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE) || (std::strncmp(szmapname, "ctf_system", 10) == 0)) { if (getTeam() == TF2_TEAM_BLUE) { @@ -3028,28 +3006,60 @@ void CBotTF2::modThink() m_pPushPayloadBomb = m_pRedPayloadBomb; } } - else if (CTeamFortress2Mod::isMapType(TF_MAP_CART)) + else if (CTeamFortress2Mod::isMapType(TF_MAP_CART) || CTeamFortress2Mod::isMapType(TF_MAP_CPPL) || (std::strncmp(szmapname, "cp_helmsdeep", 12) == 0)) { if (getTeam() == TF2_TEAM_BLUE) { m_pPushPayloadBomb = m_pBluePayloadBomb; - m_pDefendPayloadBomb = NULL; + m_pDefendPayloadBomb = nullptr; } else { - m_pPushPayloadBomb = NULL; + m_pPushPayloadBomb = nullptr; m_pDefendPayloadBomb = m_pBluePayloadBomb; } } + else if ((std::strncmp(szmapname, "sd_offload", 10) == 0)) + { + if ((getTeam() == TF2_TEAM_BLUE || getTeam() == TF2_TEAM_RED) && m_bHasFlag) + { + m_pPushPayloadBomb = m_pBluePayloadBomb; + } + } + else if ((std::strncmp(szmapname, "koth_namicott", 13) == 0) || (std::strncmp(szmapname, "ctf_system", 10) == 0) || (std::strncmp(szmapname, "kotc_", 5) == 0)) + { + if ((getTeam() == TF2_TEAM_BLUE || getTeam() == TF2_TEAM_RED)) + { + m_pPushPayloadBomb = m_pBluePayloadBomb; + } + } + /*else if (CTeamFortress2Mod::isMapType(TF_MAP_MVM)) + { + m_iMvMUpdateTime--; // update timer + + if (m_iMvMUpdateTime <= 0) + { + if (entprops->GameRules_GetRoundState() == RoundState_BetweenRounds) // MvM: Waiting for all players to be ready + { + m_iMvMUpdateTime = TIME_TO_TICKS(randomFloat(3.0f, 12.0f)); // Slower updates while the wave isn't running, makes the bot more 'human' when readying up + } + else + { + m_iMvMUpdateTime = TIME_TO_TICKS(randomFloat(2.0f, 4.0f)); // Faster updates while the wave is running + } + + MvM_Update(); // run MvM Think; + } + }*/ // when respawned -- check if I should change class if (!m_pPlayerInfo->IsDead()) { const int _forcedClass = rcbot_force_class.GetInt(); // Change class if not same class as forced one or class was forced but not anymore - if (m_iClass != _forcedClass && ((_forcedClass > 0 && _forcedClass < 10) || (m_classWasForced && (_forcedClass < 1 || _forcedClass > 9)))) + if (m_iClass != _forcedClass && (_forcedClass > 0 && _forcedClass < 10)) { - m_classWasForced = _forcedClass > 0 && _forcedClass < 10; + m_classWasForced = true; chooseClass(); selectClass(); } @@ -3057,7 +3067,8 @@ void CBotTF2::modThink() { m_bCheckClass = false; - if (bot_change_class.GetBool() && (m_fChangeClassTime < engine->Time()) && (!CTeamFortress2Mod::isMapType(TF_MAP_MVM) || !CTeamFortress2Mod::hasRoundStarted())) + if (bot_change_class.GetBool() && (m_fChangeClassTime < engine->Time()) && (! + CTeamFortress2Mod::isMapType(TF_MAP_MVM) || !CTeamFortress2Mod::hasRoundStarted())) { // get score for this class float scoreValue = CClassInterface::getTF2Score(m_pEdict); @@ -3077,24 +3088,20 @@ void CBotTF2::modThink() m_fChangeClassTime = engine->Time() + randomFloat(bot_min_cc_time.GetFloat() / 2, bot_max_cc_time.GetFloat() / 2); } - const int _forcedClass = rcbot_force_class.GetInt(); // Change class if either I think I could do better if (randomFloat(0.0f, 1.0f) > (scoreValue / CTeamFortress2Mod::getHighestScore())) { - chooseClass(); // edits m_iDesiredClass - - // change class - selectClass(); + // Use changeClass() which handles cleanup, class selection, and respawn - Ethan Bissborf + changeClass(); } } } } m_fIdealMoveSpeed = CTeamFortress2Mod::TF2_GetPlayerSpeed(m_pEdict, m_iClass)*rcbot_speed_boost.GetFloat(); - - + /* spy check code */ - if (((m_iClass != TF_CLASS_SPY) || (!isDisguised())) && ((m_pEnemy.get() == NULL) || !hasSomeConditions(CONDITION_SEE_CUR_ENEMY)) && (m_pPrevSpy.get() != NULL) && (m_fSeeSpyTime > engine->Time()) && + if (((m_iClass != TF_CLASS_SPY) || (!isDisguised())) && ((m_pEnemy.get() == nullptr) || !hasSomeConditions(CONDITION_SEE_CUR_ENEMY)) && (m_pPrevSpy.get() != nullptr) && (m_fSeeSpyTime > engine->Time()) && !m_bIsCarryingObj && CBotGlobals::isAlivePlayer(m_pPrevSpy) && !CTeamFortress2Mod::TF2_IsPlayerInvuln(getEdict())) { if ((m_iClass != TF_CLASS_ENGINEER) || !hasSomeConditions(CONDITION_BUILDING_SAPPED)) @@ -3135,14 +3142,14 @@ void CBotTF2::modThink() case TF_CLASS_SCOUT: if ( m_pWeapons->hasWeapon(TF2_WEAPON_LUNCHBOX_DRINK)) { - int pcond = CClassInterface::getTF2Conditions(m_pEdict); + const int pcond = CClassInterface::getTF2Conditions(m_pEdict); if ((pcond & TF2_PLAYER_BONKED) == TF2_PLAYER_BONKED) { wantToShoot(false); // clear enemy - m_pEnemy = NULL; - m_pOldEnemy = NULL; + m_pEnemy = nullptr; + m_pOldEnemy = nullptr; } else if (!hasEnemy() && !hasFlag() && (CClassInterface::TF2_getEnergyDrinkMeter(m_pEdict) > 99.99f)) { @@ -3212,21 +3219,19 @@ void CBotTF2::modThink() break; case TF_CLASS_HWGUY: { - bool bRevMiniGun; - - bRevMiniGun = false; + bool bRevMiniGun = false; // hwguys dont rev minigun if they have the flag if (wantToShoot() && !m_bHasFlag) { - CBotWeapon *pWeapon = getCurrentWeapon(); + const CBotWeapon *pWeapon = getCurrentWeapon(); if (pWeapon && (pWeapon->getID() == TF2_WEAPON_MINIGUN)) { if (!CTeamFortress2Mod::TF2_IsPlayerOnFire(m_pEdict) && !CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEdict)) { - if (m_fCurrentDanger >= TF2_HWGUY_REV_BELIEF) + if (static_cast(m_fCurrentDanger) >= TF2_HWGUY_REV_BELIEF) { if (pWeapon->getAmmo(this) > 100) { @@ -3241,9 +3246,9 @@ void CBotTF2::modThink() if (bRevMiniGun) { // record time when bot started revving up - if (m_fRevMiniGunTime == 0) + if (m_fRevMiniGunTime == 0.0f) { - float fMinTime = (m_fCurrentDanger / 200) * 10; + const float fMinTime = (m_fCurrentDanger / 200) * 10; m_fRevMiniGunTime = engine->Time(); m_fNextRevMiniGunTime = randomFloat(fMinTime, fMinTime + 5.0f); @@ -3255,15 +3260,15 @@ void CBotTF2::modThink() secondaryAttack(true); //m_fIdealMoveSpeed = 30.0f; Improve Max Speed here - if (m_fCurrentDanger < 1) + if (m_fCurrentDanger < 1.0f) { m_fRevMiniGunTime = 0.0f; m_fNextRevMiniGunTime = 0.0f; } } - else if ((m_fRevMiniGunTime + (2.0f*m_fNextRevMiniGunTime)) < engine->Time()) + else if ((m_fRevMiniGunTime + (2.0f * m_fNextRevMiniGunTime)) < engine->Time()) { - m_fRevMiniGunTime = 0.0; + m_fRevMiniGunTime = 0.0f; } } @@ -3301,16 +3306,15 @@ void CBotTF2::modThink() case TF_CLASS_SPY: if (!hasFlag()) { - extern ConVar rcbot_tf2_debug_spies_cloakdisguise; - + static bool bIsCloaked; if (rcbot_tf2_debug_spies_cloakdisguise.GetBool() && (m_fSpyDisguiseTime < engine->Time())) { // if previously detected or isn't disguised if ((m_fDisguiseTime == 0.0f) || !isDisguised()) { - int iteam = CTeamFortress2Mod::getEnemyTeam(getTeam()); + const int iTeam = CTeamFortress2Mod::getEnemyTeam(getTeam()); - spyDisguise(iteam, getSpyDisguiseClass(iteam)); + spyDisguise(iTeam, getSpyDisguiseClass(iTeam)); } m_fSpyDisguiseTime = engine->Time() + 5.0f; @@ -3326,7 +3330,7 @@ void CBotTF2::modThink() { spyCloak(); } - else if (bIsCloaked || isDisguised() && !hasEnemy()) + else if (bIsCloaked || (isDisguised() && !hasEnemy())) { updateCondition(CONDITION_COVERT); } @@ -3383,7 +3387,8 @@ void CBotTF2::modThink() { if ( (m_fPickupTimeTime()) && m_pNearestDisp && !m_pSchedules->isCurrentSchedule(SCHED_USE_DISPENSER) ) { - if ( fabs(CBotGlobals::entityOrigin(m_pNearestDisp).z - getOrigin().z) < BOT_JUMP_HEIGHT ) + if (std::fabs(CBotGlobals::entityOrigin(m_pNearestDisp).z - getOrigin().z) < static_cast(BOT_JUMP_HEIGHT)) + { m_pSchedules->removeSchedule(SCHED_USE_DISPENSER); m_pSchedules->addFront(new CBotUseDispSched(this,m_pNearestDisp)); @@ -3394,7 +3399,7 @@ void CBotTF2::modThink() } else if ( (m_fPickupTimeTime()) && bNeedHealth && m_pHealthkit && !m_pSchedules->isCurrentSchedule(SCHED_TF2_GET_HEALTH) ) { - if ( fabs(CBotGlobals::entityOrigin(m_pHealthkit).z - getOrigin().z) < BOT_JUMP_HEIGHT ) + if (std::fabs(CBotGlobals::entityOrigin(m_pHealthkit).z - getOrigin().z) < static_cast(BOT_JUMP_HEIGHT)) { m_pSchedules->removeSchedule(SCHED_TF2_GET_HEALTH); m_pSchedules->addFront(new CBotTF2GetHealthSched(CBotGlobals::entityOrigin(m_pHealthkit))); @@ -3407,7 +3412,7 @@ void CBotTF2::modThink() } else if ( (m_fPickupTimeTime()) && bNeedAmmo && m_pAmmo && !m_pSchedules->isCurrentSchedule(SCHED_PICKUP) ) { - if ( fabs(CBotGlobals::entityOrigin(m_pAmmo).z - getOrigin().z) < BOT_JUMP_HEIGHT ) + if ( std::fabs(CBotGlobals::entityOrigin(m_pAmmo).z - getOrigin().z) < static_cast(BOT_JUMP_HEIGHT) ) { m_pSchedules->removeSchedule(SCHED_TF2_GET_AMMO); m_pSchedules->addFront(new CBotTF2GetAmmoSched(CBotGlobals::entityOrigin(m_pAmmo))); @@ -3420,7 +3425,6 @@ void CBotTF2::modThink() } setMoveLookPriority(MOVELOOK_MODTHINK); - } void CBotTF2::handleWeapons() @@ -3435,15 +3439,14 @@ void CBotTF2::handleWeapons() if ( (getHealthPercent() > 0.9f) || ((m_fCarryTime + 3.0f) > engine->Time()) ) return; } - else if ( ( pSentry != NULL ) && !hasSomeConditions(CONDITION_PARANOID) ) + else if ( ( pSentry != nullptr) && !hasSomeConditions(CONDITION_PARANOID) ) { - if ( isVisible(pSentry) && (CClassInterface::getSentryEnemy(pSentry) != NULL) ) + if ( isVisible(pSentry) && (CClassInterface::getSentryEnemy(pSentry) != nullptr) ) { if ( distanceFrom(pSentry) < 100 ) return; // don't shoot -- i probably want to upgrade sentry } } - } // @@ -3453,17 +3456,15 @@ void CBotTF2::handleWeapons() hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && wantToShoot() && isVisible(m_pEnemy) && isEnemy(m_pEnemy) ) { - CBotWeapon *pWeapon; - - pWeapon = m_pWeapons->getBestWeapon(m_pEnemy,!hasFlag(),!hasFlag(),rcbot_melee_only.GetBool(),false,CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEdict)); + CBotWeapon* pWeapon = m_pWeapons->getBestWeapon(m_pEnemy, !hasFlag(), !hasFlag(), rcbot_melee_only.GetBool(), false, + CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEdict)); setLookAtTask(LOOK_ENEMY); - m_pAttackingEnemy = NULL; + m_pAttackingEnemy = nullptr; - if ( m_bWantToChangeWeapon && (pWeapon != NULL) && (pWeapon != getCurrentWeapon()) && pWeapon->getWeaponIndex() ) + if ( m_bWantToChangeWeapon && (pWeapon != nullptr) && (pWeapon != getCurrentWeapon()) && pWeapon->getWeaponIndex() ) { - //selectWeaponSlot(pWeapon->getWeaponInfo()->getSlot()); select_CWeapon(pWeapon->getWeaponInfo()); //selectWeapon(pWeapon->getWeaponIndex()); } @@ -3471,8 +3472,8 @@ void CBotTF2::handleWeapons() { if ( !handleAttack ( pWeapon, m_pEnemy ) ) { - m_pEnemy = NULL; - m_pOldEnemy = NULL; + m_pEnemy = nullptr; + m_pOldEnemy = nullptr; wantToShoot(false); } } @@ -3486,9 +3487,9 @@ void CBotTF2::enemyFound (edict_t *pEnemy) if ( m_pNearestEnemySentry == pEnemy ) { - CBotWeapon *pWeapon = m_pWeapons->getPrimaryWeapon(); + const CBotWeapon *pWeapon = m_pWeapons->getPrimaryWeapon(); - if ( (pWeapon != NULL) && (m_iClass != TF_CLASS_SPY) && !pWeapon->outOfAmmo(this) && pWeapon->primaryGreaterThanRange(TF2_MAX_SENTRYGUN_RANGE+32.0f) ) + if ( (pWeapon != nullptr) && (m_iClass != TF_CLASS_SPY) && !pWeapon->outOfAmmo(this) && pWeapon->primaryGreaterThanRange(static_cast(TF2_MAX_SENTRYGUN_RANGE)+32.0f) ) { updateCondition(CONDITION_CHANGED); } @@ -3502,12 +3503,6 @@ bool CBotFortress :: canAvoid ( edict_t *pEntity ) bool CBotTF2::canAvoid(edict_t *pEntity) { - extern ConVar bot_avoid_radius; - - float distance; - Vector vAvoidOrigin; - int index; - if ( !CBotGlobals::entityIsValid(pEntity) ) return false; if ( pEntity == m_pLookEdict ) @@ -3533,7 +3528,7 @@ bool CBotTF2::canAvoid(edict_t *pEntity) if (( pEntity == m_pTeleExit ) && ( CClassInterface::isObjectCarried(pEntity) )) return false; - edict_t *groundEntity = CClassInterface::getGroundEntity(m_pEdict); + const edict_t *groundEntity = CClassInterface::getGroundEntity(m_pEdict); // must stand on worldspawn if ( groundEntity && (ENTINDEX(groundEntity)>0) && (pEntity == groundEntity) ) @@ -3544,26 +3539,25 @@ bool CBotTF2::canAvoid(edict_t *pEntity) return true; } - index = ENTINDEX(pEntity); + const int index = ENTINDEX(pEntity); if ( !index ) return false; - vAvoidOrigin = CBotGlobals::entityOrigin(pEntity); + const Vector vAvoidOrigin = CBotGlobals::entityOrigin(pEntity); if ( vAvoidOrigin == m_vMoveTo ) return false; - distance = distanceFrom(vAvoidOrigin); - - - if ((distance > 1) && (distance < bot_avoid_radius.GetFloat()) && (vAvoidOrigin.z >= getOrigin().z) && (fabs(getOrigin().z - vAvoidOrigin.z) < 64)) + const float distance = distanceFrom(vAvoidOrigin); + + if ((distance > 1) && (distance < bot_avoid_radius.GetFloat()) && (vAvoidOrigin.z >= getOrigin().z) && (std::fabs(getOrigin().z - vAvoidOrigin.z) < 64)) { - if ((m_pAttackingEnemy.get() != NULL) && (m_pAttackingEnemy.get() == pEntity)) + if ((m_pAttackingEnemy.get() != nullptr) && (m_pAttackingEnemy.get() == pEntity)) return false; // I need to melee this guy probably - else if (isEnemy(pEntity, false)) + if (isEnemy(pEntity, false)) return true; - else if ((m_iClass == TF_CLASS_ENGINEER) && ((pEntity == m_pSentryGun.get()) || (pEntity == m_pDispenser.get()))) + if ((m_iClass == TF_CLASS_ENGINEER) && ((pEntity == m_pSentryGun.get()) || (pEntity == m_pDispenser.get()))) return true; } @@ -3572,18 +3566,17 @@ bool CBotTF2::canAvoid(edict_t *pEntity) bool CBotTF2 :: wantToInvestigateSound () { - if ( !CBot::wantToInvestigateSound() ) + if ( !CBotFortress::wantToInvestigateSound() ) return false; if ( CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEdict) ) return false; return (m_fLastSeeEnemy + 8.0f < engine->Time()) && !m_bHasFlag && ( (m_iClass!=TF_CLASS_ENGINEER) || - (!this->m_bIsCarryingObj && (m_pSentryGun.get()!=NULL) && ((CTeamFortress2Mod::getSentryLevel(m_pSentryGun)>2)&&(CClassInterface::getSentryHealth(m_pSentryGun)>90)))); + (!this->m_bIsCarryingObj && (m_pSentryGun.get()!= nullptr) && ((CTeamFortress2Mod::getSentryLevel(m_pSentryGun)>2)&&(CClassInterface::getSentryHealth(m_pSentryGun)>90)))); } bool CBotTF2 :: wantToListenToPlayerFootsteps ( edict_t *pPlayer ) { - extern ConVar rcbot_notarget; if ( rcbot_notarget.GetBool() && (CClients::isListenServerClient(CClients::get(pPlayer)) ) ) return false; @@ -3627,16 +3620,16 @@ bool CBotTF2:: wantToListenToPlayerAttack ( edict_t *pPlayer, int iWeaponID ) case TF_CLASS_MEDIC: { // don't listen to mediguns - if ( !strcmp("medigun",&szWeaponClassname[10]) ) + if ( !std::strcmp("medigun",&szWeaponClassname[10]) ) return false; } break; case TF_CLASS_ENGINEER: { // don't listen to engis upgrading stuff - if ( !strcmp("wrench",&szWeaponClassname[10]) ) + if ( !std::strcmp("wrench",&szWeaponClassname[10]) ) return false; - else if ( !strcmp("builder",&szWeaponClassname[10]) ) + if ( !std::strcmp("builder",&szWeaponClassname[10]) ) return false; } break; @@ -3645,7 +3638,7 @@ bool CBotTF2:: wantToListenToPlayerAttack ( edict_t *pPlayer, int iWeaponID ) // don't listen to cloaked spies if ( CTeamFortress2Mod::TF2_IsPlayerCloaked(pPlayer) ) return false; - if ( !strcmp("knife",&szWeaponClassname[10]) ) + if ( !std::strcmp("knife",&szWeaponClassname[10]) ) { // only hear spy knives if they know there are spies around // in 15% of cases @@ -3661,20 +3654,18 @@ bool CBotTF2:: wantToListenToPlayerAttack ( edict_t *pPlayer, int iWeaponID ) return true; } -void CBotTF2::checkStuckonSpy(void) +void CBotTF2::checkStuckonSpy() { - edict_t *pPlayer; - edict_t *pStuck = NULL; + edict_t *pStuck = nullptr; - int i = 0; - int iTeam = getTeam(); + const int iTeam = getTeam(); float fDistance; - float fMaxDistance = 80; + float fMaxDistance = 80.0f; - for ( i = 1; i <= gpGlobals->maxClients; i ++ ) + for ( int i = 1; i <= gpGlobals->maxClients; i ++ ) { - pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(i); if ( pPlayer == m_pEdict ) continue; @@ -3706,19 +3697,15 @@ void CBotTF2::checkStuckonSpy(void) m_fFrenzyTime = engine->Time() + randomFloat(0.0f,getHealthPercent()); detectedAsSpy(pStuck,false); - return; } } } -bool CBotFortress :: isClassOnTeam ( int iClass, int iTeam ) +bool CBotFortress :: isClassOnTeam (const int iClass, const int iTeam) { - int i = 0; - edict_t *pPlayer; - - for ( i = 1; i <= gpGlobals->maxClients; i ++ ) + for ( int i = 1; i <= gpGlobals->maxClients; i ++ ) { - pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(i); if ( CBotGlobals::entityIsValid(pPlayer) && (CTeamFortress2Mod::getTeam(pPlayer) == iTeam)) { @@ -3734,22 +3721,26 @@ bool CBotTF2 :: wantToFollowEnemy() { edict_t *pEnemy = m_pLastEnemy.get(); + const string_t mapname = gpGlobals->mapname; + + const char *szmapname = mapname.ToCStr(); + if (CTeamFortress2Mod::isLosingTeam(CTeamFortress2Mod::getEnemyTeam(m_iTeam))) return true; - else if ((m_iClass == TF_CLASS_SCOUT) && ((CClassInterface::getTF2Conditions(m_pEdict)&TF2_PLAYER_BONKED) == TF2_PLAYER_BONKED)) + if ((m_iClass == TF_CLASS_SCOUT) && ((CClassInterface::getTF2Conditions(m_pEdict)&TF2_PLAYER_BONKED) == TF2_PLAYER_BONKED)) return false; // currently can't shoot - else if ( !wantToInvestigateSound() ) // maybe capturing point right now + if ( !wantToInvestigateSound() ) // maybe capturing point right now return false; - else if ( (pEnemy != NULL) && CBotGlobals::isPlayer(pEnemy) && CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEdict) && (m_iClass != TF_CLASS_MEDIC) ) + if ( (pEnemy != nullptr) && CBotGlobals::isPlayer(pEnemy) && CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEdict) && (m_iClass != TF_CLASS_MEDIC) ) return true; // I am ubered GO!!! - else if ( (pEnemy != NULL) && CBotGlobals::isPlayer(pEnemy) && CTeamFortress2Mod::TF2_IsPlayerInvuln(pEnemy) ) + if ( (pEnemy != nullptr) && CBotGlobals::isPlayer(pEnemy) && CTeamFortress2Mod::TF2_IsPlayerInvuln(pEnemy) ) return false; // Enemy is UBERED -- don't follow - else if ( (m_iCurrentDefendArea != 0) && (pEnemy != NULL) && CTeamFortress2Mod::isMapType(TF_MAP_CP) && (CTeamFortress2Mod::m_ObjectiveResource.GetNumControlPoints() > 0) ) + if ( (m_iCurrentDefendArea != 0) && (pEnemy != nullptr) && (CTeamFortress2Mod::isMapType(TF_MAP_CP) || CTeamFortress2Mod::isMapType(TF_MAP_CPPL) || std::strncmp(szmapname, "ctf_chouhen", 11) == 0 || std::strncmp(szmapname, "ctf_haarp", 9) == 0 || std::strncmp(szmapname, "ctf_vector", 10) == 0 || std::strncmp(szmapname, "ctf_snowdrift", 13) == 0) && (CTeamFortress2Mod::m_ObjectiveResource.GetNumControlPoints() > 0) ) { - Vector vDefend = CTeamFortress2Mod::m_ObjectiveResource.GetCPPosition(CTeamFortress2Mod::m_ObjectiveResource.m_WaypointAreaToIndexTranslation[m_iCurrentDefendArea]); + const Vector vDefend = CTeamFortress2Mod::m_ObjectiveResource.GetCPPosition(CTeamFortress2Mod::m_ObjectiveResource.m_WaypointAreaToIndexTranslation[m_iCurrentDefendArea]); - Vector vEnemyOrigin = CBotGlobals::entityOrigin(pEnemy); - Vector vOrigin = getOrigin(); + const Vector vEnemyOrigin = CBotGlobals::entityOrigin(pEnemy); + const Vector vOrigin = getOrigin(); // He's trying to cap the point? Maybe! Go after him! if ( ((vDefend-vEnemyOrigin).Length()+80.0f) < (vDefend-vOrigin).Length() ) @@ -3758,12 +3749,12 @@ bool CBotTF2 :: wantToFollowEnemy() return true; } } - else if ( (m_fLastKnownTeamFlagTime > 0) && (pEnemy != NULL) && (CTeamFortress2Mod::isMapType(TF_MAP_CTF)||CTeamFortress2Mod::isMapType(TF_MAP_MVM)) ) + else if ( (m_fLastKnownTeamFlagTime > 0) && (pEnemy != nullptr) && (CTeamFortress2Mod::isMapType(TF_MAP_CTF)||CTeamFortress2Mod::isMapType(TF_MAP_MVM)||CTeamFortress2Mod::isMapType(TF_MAP_RD)||CTeamFortress2Mod::isMapType(TF_MAP_CP)||CTeamFortress2Mod::isMapType(TF_MAP_TC)) ) { - Vector vDefend = m_vLastKnownTeamFlagPoint; + const Vector vDefend = m_vLastKnownTeamFlagPoint; - Vector vEnemyOrigin = CBotGlobals::entityOrigin(pEnemy); - Vector vOrigin = getOrigin(); + const Vector vEnemyOrigin = CBotGlobals::entityOrigin(pEnemy); + const Vector vOrigin = getOrigin(); // He's trying to get the flag? Maybe! Go after him! if ( ((vDefend-vEnemyOrigin).Length()+80.0f) < (vDefend-vOrigin).Length() ) @@ -3794,51 +3785,56 @@ bool CBotTF2 :: wantToFollowEnemy() bool CBotFortress :: wantToFollowEnemy () { + const string_t mapname = gpGlobals->mapname; + + const char* szmapname = mapname.ToCStr(); + if ( hasSomeConditions(CONDITION_NEED_HEALTH) ) return false; if ( hasSomeConditions(CONDITION_NEED_AMMO) ) return false; - if ( !CTeamFortress2Mod::hasRoundStarted() ) + if ( !CTeamFortress2Mod::hasRoundStarted() /* && !(CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE) || std::strncmp(szmapname, "htf_", 4))*/) + return false; + if ( !m_pLastEnemy ) + return false; + if ( hasFlag() ) + return false; + if ( m_iClass == TF_CLASS_SCOUT ) return false; - if ( !m_pLastEnemy ) - return false; - if ( hasFlag() ) - return false; - if ( m_iClass == TF_CLASS_SCOUT ) - return false; - else if ( (m_iClass == TF_CLASS_MEDIC) && m_pHeal ) + if ( (m_iClass == TF_CLASS_MEDIC) && m_pHeal ) return false; - else if ( (m_iClass == TF_CLASS_SPY) && isDisguised() ) // sneak around the enemy - return true; - else if ( (m_iClass == TF_CLASS_SNIPER) && (distanceFrom(m_pLastEnemy)>CWaypointLocations::REACHABLE_RANGE) ) + if ( (m_iClass == TF_CLASS_SPY) && isDisguised() ) // sneak around the enemy + return true; + if ( (m_iClass == TF_CLASS_SNIPER) && (distanceFrom(m_pLastEnemy)>CWaypointLocations::REACHABLE_RANGE) ) return false; // don't bother! - else if ( CBotGlobals::isPlayer(m_pLastEnemy) && (CClassInterface::getTF2Class(m_pLastEnemy) == TF_CLASS_SPY) && (thinkSpyIsEnemy(m_pLastEnemy,CTeamFortress2Mod::getSpyDisguise(m_pLastEnemy))) ) - return true; // always find spies! - else if ( CTeamFortress2Mod::isFlagCarrier(m_pLastEnemy) ) + if ( CBotGlobals::isPlayer(m_pLastEnemy) && (CClassInterface::getTF2Class(m_pLastEnemy) == TF_CLASS_SPY) && (thinkSpyIsEnemy(m_pLastEnemy,CTeamFortress2Mod::getSpyDisguise(m_pLastEnemy))) ) + return true; // always find spies! + if ( CTeamFortress2Mod::isFlagCarrier(m_pLastEnemy) ) return true; // follow flag carriers to the death - else if ( m_iClass == TF_CLASS_ENGINEER ) - return false; // have work to do - + if ( m_iClass == TF_CLASS_ENGINEER ) + return false; + // have work to do + return CBot::wantToFollowEnemy(); } -void CBotTF2 ::voiceCommand ( int cmd ) +void CBotTF2 ::voiceCommand (const byte voiceCmd) { char scmd[64]; u_VOICECMD vcmd; - vcmd.voicecmd = cmd; - - sprintf(scmd,"voicemenu %d %d",vcmd.b1.v1,vcmd.b1.v2); + vcmd.voicecmd = voiceCmd; + + snprintf(scmd, sizeof(scmd), "voicemenu %d %d", static_cast(vcmd.b1.v1), static_cast(vcmd.b1.v2)); helpers->ClientCommand(m_pEdict,scmd); } -bool CBotTF2 ::checkStuck(void) +bool CBotTF2 ::checkStuck() { if ( !CTeamFortress2Mod::isAttackDefendMap() || (CTeamFortress2Mod::hasRoundStarted() || (getTeam()==TF2_TEAM_RED)) ) { - if ( CBot::checkStuck() ) + if (CBotFortress::checkStuck() ) { checkStuckonSpy(); @@ -3849,7 +3845,7 @@ bool CBotTF2 ::checkStuck(void) return false; } -void CBotTF2 :: foundSpy (edict_t *pEdict,TF_Class iDisguise) +void CBotTF2 :: foundSpy (edict_t *pEdict, const TF_Class iDisguise) { CBotFortress::foundSpy(pEdict,iDisguise); @@ -3861,76 +3857,66 @@ void CBotTF2 :: foundSpy (edict_t *pEdict,TF_Class iDisguise) } } -int CBotFortress :: getSpyDisguiseClass ( int iTeam ) +int CBotFortress :: getSpyDisguiseClass (const int iTeam) const { - int i = 0; - edict_t *pPlayer; - dataUnconstArray m_classes; - int _class; - float fTotal; - float fRand; + std::vector availableClasses; - for ( i = 1; i <= gpGlobals->maxClients; i ++ ) + for ( int i = 1; i <= gpGlobals->maxClients; i ++ ) { - pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(i); if ( CBotGlobals::entityIsValid(pPlayer) && (CTeamFortress2Mod::getTeam(pPlayer) == iTeam)) { - _class = CClassInterface::getTF2Class(pPlayer); - - if ( _class ) - m_classes.Add(_class); + if ( int _class = CClassInterface::getTF2Class(pPlayer) ) + availableClasses.emplace_back(_class); } } - - - if ( m_classes.IsEmpty() ) - return randomInt(1,9); - fTotal = 0; + if ( availableClasses.empty() ) + return randomInt(1,9); - for ( int i = 0; i < m_classes.Size(); i ++ ) - { - fTotal += m_fClassDisguiseFitness[m_classes.ReturnValueFromIndex(i)]; - } + float fTotal = std::accumulate(availableClasses.begin(), availableClasses.end(), 0.0f, + [this](const float current_total, const int available_class) + { + return current_total + m_fClassDisguiseFitness[available_class]; + }); - if ( fTotal > 0 ) + if ( fTotal > 0.0f ) { + const float fRand = randomFloat(0.0f, fTotal); - fRand = randomFloat(0.0,fTotal); + fTotal = 0.0f; - fTotal = 0; - - for ( int i = 0; i < m_classes.Size(); i ++ ) + for (const int availableClass : availableClasses) { - fTotal += m_fClassDisguiseFitness[m_classes.ReturnValueFromIndex(i)]; + fTotal += m_fClassDisguiseFitness[availableClass]; if ( fRand <= fTotal ) - return m_classes.ReturnValueFromIndex(i); + return availableClass; } } - return m_classes.Random(); + // choose one of the classes proportional to whatever's on the team + return availableClasses[static_cast(randomInt(0, static_cast(availableClasses.size()) - 1))]; } -bool CBotFortress :: incomingRocket ( float fRange ) +bool CBotFortress :: incomingRocket (const float fRange) { edict_t *pRocket = m_NearestEnemyRocket; - if ( pRocket != NULL ) + if ( pRocket != nullptr) { Vector vel; - Vector vorg = CBotGlobals::entityOrigin(pRocket); - Vector vcomp; - float fDist = distanceFrom(pRocket); + const Vector vorg = CBotGlobals::entityOrigin(pRocket); + const float fDist = distanceFrom(pRocket); if ( fDist < fRange ) { CClassInterface::getVelocity(pRocket,&vel); vel = vel/vel.Length(); - vcomp = vorg + vel*fDist; + const Vector vcomp = vorg + vel * fDist; return ( distanceFrom(vcomp) < BLAST_RADIUS ); } @@ -3941,12 +3927,12 @@ bool CBotFortress :: incomingRocket ( float fRange ) if ( pRocket ) { Vector vel; - Vector vorg = CBotGlobals::entityOrigin(pRocket); - Vector vcomp; - float fDist = distanceFrom(pRocket); + const Vector vorg = CBotGlobals::entityOrigin(pRocket); + const float fDist = distanceFrom(pRocket); if ( fDist < fRange ) { + Vector vcomp; CClassInterface::getVelocity(pRocket,&vel); if ( vel.Length() > 0 ) @@ -3977,19 +3963,19 @@ void CBotFortress :: enemyLost(edict_t *pEnemy) //CBot::enemyLost(pEnemy); } -bool CBotTF2 :: setVisible ( edict_t *pEntity, bool bVisible ) +bool CBotTF2 :: setVisible ( edict_t *pEntity, const bool bVisible ) { - bool bValid = CBotFortress::setVisible(pEntity,bVisible); + const bool bValid = CBotFortress::setVisible(pEntity,bVisible); if ( bValid ) { - if ( (m_pRedPayloadBomb.get() == NULL) && CTeamFortress2Mod::isPayloadBomb(pEntity,TF2_TEAM_RED) ) + if ( (m_pRedPayloadBomb.get() == nullptr) && CTeamFortress2Mod::isPayloadBomb(pEntity,TF2_TEAM_RED) ) { m_pRedPayloadBomb = pEntity; CTeamFortress2Mod::updateRedPayloadBomb(pEntity); //if ( CTeamFortress2Mod::se } - else if ( (m_pBluePayloadBomb.get() == NULL) && CTeamFortress2Mod::isPayloadBomb(pEntity,TF2_TEAM_BLUE) ) + else if ( (m_pBluePayloadBomb.get() == nullptr) && CTeamFortress2Mod::isPayloadBomb(pEntity,TF2_TEAM_BLUE) ) { m_pBluePayloadBomb = pEntity; CTeamFortress2Mod::updateBluePayloadBomb(pEntity); @@ -4006,21 +3992,21 @@ bool CBotTF2 :: setVisible ( edict_t *pEntity, bool bVisible ) if ( ((pTest = m_NearestEnemyRocket.get()) != pEntity) && CTeamFortress2Mod::isRocket ( pEntity, CTeamFortress2Mod::getEnemyTeam(m_iTeam) ) ) { - if ( ( pTest == NULL ) || (distanceFrom(pEntity) < distanceFrom(pTest)) ) + if ( ( pTest == nullptr) || (distanceFrom(pEntity) < distanceFrom(pTest)) ) m_NearestEnemyRocket = pEntity; } } else { if ( pEntity == m_NearestEnemyRocket.get_old() ) - m_NearestEnemyRocket = NULL; + m_NearestEnemyRocket = nullptr; } if ( (ENTINDEX(pEntity)<=gpGlobals->maxClients) && (ENTINDEX(pEntity)>0) ) { if ( bVisible ) { - TF_Class iPlayerclass = (TF_Class)CClassInterface::getTF2Class(pEntity); + const TF_Class iPlayerclass = static_cast(CClassInterface::getTF2Class(pEntity)); if ( iPlayerclass == TF_CLASS_SPY ) { @@ -4042,8 +4028,8 @@ bool CBotTF2 :: setVisible ( edict_t *pEntity, bool bVisible ) if ( !m_pLastSeeMedic.check(pEntity) && CBotGlobals::entityIsAlive(pEntity) ) { // i think this spy can cure me! - if ( (m_pLastSeeMedic.check(NULL) || (distanceFrom(pEntity) < distanceFrom(m_pLastSeeMedic.getLocation()))) && - !thinkSpyIsEnemy(pEntity,(TF_Class)iClass) ) + if ( (m_pLastSeeMedic.check(nullptr) || (distanceFrom(pEntity) < distanceFrom(m_pLastSeeMedic.getLocation()))) && + !thinkSpyIsEnemy(pEntity,static_cast(iClass)) ) { m_pLastSeeMedic = CBotLastSee(pEntity); /*m_pLastSeeMedic = pEntity; @@ -4066,36 +4052,33 @@ bool CBotTF2 :: setVisible ( edict_t *pEntity, bool bVisible ) } else { - if ( CBotGlobals::entityIsAlive(pEntity) && ((m_pLastSeeMedic.check(NULL)) || (distanceFrom(pEntity) < distanceFrom(m_pLastSeeMedic.getLocation()))) ) + if ( CBotGlobals::entityIsAlive(pEntity) && ((m_pLastSeeMedic.check(nullptr)) || (distanceFrom(pEntity) < distanceFrom(m_pLastSeeMedic.getLocation()))) ) { m_pLastSeeMedic = CBotLastSee(pEntity); //m_vLastSeeMedic = CBotGlobals::entityOrigin(pEntity); //m_fLastSeeMedicTime = engine->Time(); } - } } } else { if ( m_pCloakedSpy.get_old() == pEntity ) - m_pCloakedSpy = NULL; + m_pCloakedSpy = nullptr; } } return bValid; - } void CBotTF2 :: checkBeingHealed () { - static short i; + static int i; static edict_t *p; static edict_t *pWeapon; static IPlayerInfo *pi; static const char *szWeaponName; - if ( m_fCheckHealTime > engine->Time() ) return; @@ -4117,7 +4100,7 @@ void CBotTF2 :: checkBeingHealed () { szWeaponName = pi->GetWeaponName(); - if ( szWeaponName && *szWeaponName && strcmp(szWeaponName,"tf_weapon_medigun") == 0 ) + if ( szWeaponName && *szWeaponName && std::strcmp(szWeaponName,"tf_weapon_medigun") == 0 ) { pWeapon = CTeamFortress2Mod:: getMediGun(p); @@ -4135,22 +4118,18 @@ void CBotTF2 :: checkBeingHealed () } } } - } // Preconditions : Current weapon is Medigun // pPlayer is not NULL // -bool CBotTF2::healPlayer() +bool CBotTF2::healPlayer(edict_t* pPlayer, edict_t* pPrevPlayer) { static CBotWeapon *pWeap; static IPlayerInfo *p; static edict_t *pWeapon; static Vector vOrigin; static Vector vForward; - static QAngle eyes; - static float fSpeed; - static CClient *pClient; if (!m_pHeal.get()) return false; @@ -4165,7 +4144,7 @@ bool CBotTF2::healPlayer() { if (CBotGlobals::entityIsAlive(m_pHeal) && CBotGlobals::entityIsValid(m_pHeal)) { - if (strcmp(m_pHeal.get()->GetClassName(), "entity_revive_marker") == 0) + if (std::strcmp(m_pHeal.get()->GetClassName(), "entity_revive_marker") == 0) return true; } @@ -4180,20 +4159,19 @@ bool CBotTF2::healPlayer() if (m_fMedicUpdatePosTime < engine->Time()) { - float fRand; - - - fRand = randomFloat(1.0f, 2.0f); + static CClient* pClient; + static float fSpeed; + const float fRand = randomFloat(1.0f, 2.0f); pClient = CClients::get(m_pHeal); - if (pClient) - fSpeed = pClient->getSpeed(); + fSpeed = pClient->getSpeed(); // No need for the null check? [APG]RoboCop[CL] m_fMedicUpdatePosTime = engine->Time() + (fRand * (1.0f - (fSpeed / 320))); - if (p && (p->GetLastUserCommand().buttons & IN_ATTACK)) + if (p->GetLastUserCommand().buttons & IN_ATTACK) { + static QAngle eyes; // keep out of cross fire eyes = CBotGlobals::playerAngles(m_pHeal); AngleVectors(eyes, &vForward); @@ -4233,7 +4211,7 @@ bool CBotTF2::healPlayer() }*/ edict_t *pMedigun; - if ( (pWeap->getID() == TF2_WEAPON_MEDIGUN) && ((pMedigun = pWeap->getWeaponEntity()) != NULL) ) + if ( (pWeap->getID() == TF2_WEAPON_MEDIGUN) && ((pMedigun = pWeap->getWeaponEntity()) != nullptr) ) { if (CClassInterface::getChargeResistType(pMedigun) != m_iDesiredResistType) { @@ -4249,29 +4227,17 @@ bool CBotTF2::healPlayer() pWeapon = INDEXENT(pWeap->getWeaponIndex()); - if ( pWeapon == NULL ) + if ( pWeapon == nullptr) return false; m_bIncreaseSensitivity = true; - //!!!CRASH!!! - /*if ( !CClassInterface::getMedigunHealing(pWeapon) ) - { - if ( (m_fHealClickTime < engine->Time()) && (DotProductFromOrigin(vOrigin) > 0.98f) ) - primaryAttack(); - //else - //m_pButtons->letGo(IN_ATTACK); - } - else - {*/ - edict_t *pent; - - edict_t *pPlayer = NULL; + //const edict_t *pPlayer = nullptr; // Find the player I'm currently healing - for ( unsigned short i = 1; i <= gpGlobals->maxClients; i++ ) + for ( int i = 1; i <= gpGlobals->maxClients; i++ ) { - pent = INDEXENT(i); + edict_t* pent = INDEXENT(i); if ( pent && CBotGlobals::entityIsValid(pent) ) { @@ -4291,8 +4257,7 @@ bool CBotTF2::healPlayer() { // yes -- press fire to disconnect from player if ( m_fHealClickTime < engine->Time() ) - { - extern ConVar rcbot_tf2_medic_letgotime; + { m_fHealClickTime = engine->Time() + rcbot_tf2_medic_letgotime.GetFloat(); } @@ -4314,8 +4279,9 @@ bool CBotTF2::healPlayer() if (CBotGlobals::isPlayer(m_pHeal)) { // Simple UBER check : healing player not ubered already - if (!CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pHeal) && !CTeamFortress2Mod::isFlagCarrier(m_pHeal) && - (m_pEnemy&&isVisible(m_pEnemy)) || (((((float)m_pPlayerInfo->GetHealth()) / m_pPlayerInfo->GetMaxHealth()) < 0.33) || (getHealthPercent() < 0.33))) + if ((!CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pHeal) && !CTeamFortress2Mod::isFlagCarrier(m_pHeal) && + (m_pEnemy&&isVisible(m_pEnemy))) || ((static_cast(m_pPlayerInfo->GetHealth()) / + static_cast(m_pPlayerInfo->GetMaxHealth()) < 0.33f || getHealthPercent() < 0.33f))) { if (CTeamFortress2Mod::hasRoundStarted()) { @@ -4330,7 +4296,7 @@ bool CBotTF2::healPlayer() // The lower the better float CBotTF2 :: getEnemyFactor ( edict_t *pEnemy ) { - float fPreFactor = 0; + float fPreFactor = 0.0f; // Player if ( CBotGlobals::isPlayer(pEnemy) ) @@ -4354,7 +4320,7 @@ float CBotTF2 :: getEnemyFactor ( edict_t *pEnemy ) // dont shoot ubered player unlesss he's the only thing around for 2000 units fPreFactor = 2000.0f; } - else if ( (m_iClass == TF_CLASS_SPY) && isDisguised() && (p!=NULL) && (CBotGlobals::DotProductFromOrigin(CBotGlobals::entityOrigin(pEnemy),getOrigin(),p->GetLastUserCommand().viewangles) > 0.1f) ) + else if ( (m_iClass == TF_CLASS_SPY) && isDisguised() && (p!= nullptr) && (CBotGlobals::DotProductFromOrigin(CBotGlobals::entityOrigin(pEnemy),getOrigin(),p->GetLastUserCommand().viewangles) > 0.1f) ) { // I'm disguised as a spy but this guy can see me , better lay off the attack unless theres someone else around fPreFactor = 1000.0f; @@ -4369,7 +4335,7 @@ float CBotTF2 :: getEnemyFactor ( edict_t *pEnemy ) } else { - int iclass = CClassInterface::getTF2Class(pEnemy); + const int iclass = CClassInterface::getTF2Class(pEnemy); if ( iclass == TF_CLASS_MEDIC ) { @@ -4403,13 +4369,13 @@ float CBotTF2 :: getEnemyFactor ( edict_t *pEnemy ) // I'm a spy and I'm attacking an engineer! if ( m_iClass == TF_CLASS_SPY ) { - edict_t *pSentry = NULL; + edict_t *pSentry; fPreFactor = -400.0f; - if ( (pSentry = m_pNearestEnemySentry.get()) != NULL ) + if ( (pSentry = m_pNearestEnemySentry.get()) != nullptr) { - if ( (CTeamFortress2Mod::getSentryOwner(pSentry) == pEnemy) && CTeamFortress2Mod::isSentrySapped(pSentry) && (distanceFrom(pSentry)(TF2_MAX_SENTRYGUN_RANGE)) ) { // this guy is the owner of a disabled sentry gun -- take him out! fPreFactor = -1024.0f; @@ -4439,8 +4405,6 @@ float CBotTF2 :: getEnemyFactor ( edict_t *pEnemy ) } else if ( CTeamFortress2Mod::isBoss(pEnemy,&fBossFactor) ) { - extern ConVar bot_bossattackfactor; - fPreFactor = fBossFactor * bot_bossattackfactor.GetFloat(); } else if ( CTeamFortress2Mod::isPipeBomb(pEnemy,CTeamFortress2Mod::getEnemyTeam(m_iTeam)) ) @@ -4454,30 +4418,31 @@ float CBotTF2 :: getEnemyFactor ( edict_t *pEnemy ) return fPreFactor; } - bool CBotFortress :: wantToNest () { - return (!hasFlag() && ((getClass()!=TF_CLASS_ENGINEER)&&(m_pSentryGun.get()!=NULL)) && ((getClass() != TF_CLASS_MEDIC) || !m_pHeal) && (getHealthPercent() < 0.95) && (nearbyFriendlies(256.0f)<2)); + return (!hasFlag() && ((getClass()!=TF_CLASS_ENGINEER)&&(m_pSentryGun.get()!= nullptr)) && ((getClass() != TF_CLASS_MEDIC) || !m_pHeal) && (getHealthPercent() < 0.95) && (nearbyFriendlies(256.0f)<2)); } -void CBotTF2:: teleportedPlayer ( void ) +void CBotTF2:: teleportedPlayer () { m_iTeleportedPlayers++; } -void CBotTF2 :: getTasks ( unsigned int iIgnore ) +void CBotTF2 :: getTasks ( unsigned iIgnore ) { static bool bIsUbered; static TF_Class iClass; static int iMetal; static bool bNeedAmmo; static bool bNeedHealth; + static CBotUtilities utils; static CBotWeapon *pWeapon; static CWaypoint *pWaypointResupply; static CWaypoint *pWaypointAmmo; static CWaypoint *pWaypointHealth; static CBotUtility *next; + static float fResupplyDist; static float fHealthDist; static float fAmmoDist; @@ -4489,60 +4454,26 @@ void CBotTF2 :: getTasks ( unsigned int iIgnore ) static Vector vOrigin; static unsigned char *failedlist; - extern ConVar rcbot_move_sentry_kpm; - extern ConVar rcbot_move_sentry_time; - extern ConVar rcbot_move_disp_time; - extern ConVar rcbot_move_disp_healamount; - extern ConVar rcbot_move_tele_time; - extern ConVar rcbot_move_tele_tpm; - extern ConVar rcbot_move_obj; - - static bool bMoveObjs; - - static bool bSentryHasEnemy; - static int iSentryLevel; - static int iDispenserLevel; - static int iAllySentryLevel; - static int iAllyDispLevel; - - static float fEntranceDist; - static float fExitDist; - static float fUseDispFactor; - - static float fAllyDispenserHealthPercent; - static float fAllySentryHealthPercent; - - static float fSentryHealthPercent; - static float fDispenserHealthPercent; - static float fTeleporterEntranceHealthPercent; - static float fTeleporterExitHealthPercent; - - static float fSentryPlaceTime; - static float fDispenserPlaceTime; - static float fTeleporterEntPlaceTime; - static float fTeleporterExtPlaceTime; - static edict_t *pMedigun; - static float fSentryUtil; - static int iMetalInDisp; - static int numplayersonteam; static int numplayersonteam_alive; static bool bCheckCurrent; - - extern ConVar bot_messaround; - extern ConVar bot_defrate; - static CBotWeapon *pBWMediGun = NULL; - //static float fResupplyUtil = 0.5; - //static float fHealthUtil = 0.5; - //static float fAmmoUtil = 0.5; + static CBotWeapon *pBWMediGun = nullptr; + //static float fResupplyUtil = 0.5f; + //static float fHealthUtil = 0.5f; + //static float fAmmoUtil = 0.5f; + + const string_t mapname = gpGlobals->mapname; + + const char* szmapname = mapname.ToCStr(); // if in setup time this will tell bot not to shoot yet - wantToShoot(CTeamFortress2Mod::hasRoundStarted()); - wantToListen(CTeamFortress2Mod::hasRoundStarted()); + + wantToShoot(CTeamFortress2Mod::hasRoundStarted() || (CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE) || std::strncmp(szmapname, "htf_", 4) != 0)); + wantToListen(CTeamFortress2Mod::hasRoundStarted() || (CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE) || std::strncmp(szmapname, "htf_", 4) != 0)); if ( !hasSomeConditions(CONDITION_CHANGED) && !m_pSchedules->isEmpty() ) return; @@ -4556,33 +4487,30 @@ void CBotTF2 :: getTasks ( unsigned int iIgnore ) // keep attacking enemy -- no change to task return; } - - + bCheckCurrent = true; // important for checking the current schedule if not empty iMetal = 0; - pBWMediGun = NULL; + pBWMediGun = nullptr; vOrigin = getOrigin(); bNeedAmmo = false; bNeedHealth = false; - fResupplyDist = 1; - fHealthDist = 1; - fAmmoDist = 1; - bHasFlag = false; - fGetFlagUtility = 0.5; - fDefendFlagUtility = 0.5; + fResupplyDist = 1.0f; + fHealthDist = 1.0f; + fAmmoDist = 1.0f; + fGetFlagUtility = 0.5f; + fDefendFlagUtility = 0.5f; iTeam = m_iTeam; bHasFlag = hasFlag(); - failedlist = NULL; + failedlist = nullptr; numplayersonteam = CBotGlobals::numPlayersOnTeam(iTeam,false); numplayersonteam_alive = CBotGlobals::numPlayersOnTeam(iTeam,true); - - + // UNUSED // Shadow/Time must be Floating point /*if(m_fBlockPushTime < engine->Time()) { - m_bBlockPushing = (randomFloat(0.0,100)>50); // 50 % block pushing + m_bBlockPushing = (randomFloat(0.0f,100)>50); // 50 % block pushing m_fBlockPushTime = engine->Time() + randomFloat(10.0f,30.0f); // must be floating point }*/ @@ -4605,45 +4533,43 @@ void CBotTF2 :: getTasks ( unsigned int iIgnore ) if ( m_pHealthkit ) { if ( !CBotGlobals::entityIsValid(m_pHealthkit) ) - m_pHealthkit = NULL; + m_pHealthkit = nullptr; } if ( m_pAmmo ) { if ( !CBotGlobals::entityIsValid(m_pAmmo) ) - m_pAmmo = NULL; + m_pAmmo = nullptr; } pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(TF2_WEAPON_WRENCH)); - if (pWeapon != NULL) + if (pWeapon != nullptr) { iMetal = pWeapon->getAmmo(this); - fMetalPercent = (float)iMetal / 200; + fMetalPercent = static_cast(iMetal) / 200; } if ( bNeedAmmo || bNeedHealth ) { - dataUnconstArray *failed; - Vector vOrigin = getOrigin(); + vOrigin = getOrigin(); + WaypointList *failed; m_pNavigator->getFailedGoals(&failed); failedlist = CWaypointLocations :: resetFailedWaypoints ( failed ); - fResupplyDist = 1; - fHealthDist = 1; - fAmmoDist = 1; - - - + fResupplyDist = 1.0f; + fHealthDist = 1.0f; + fAmmoDist = 1.0f; + // don't go back to resupply if ubered if (!bIsUbered) pWaypointResupply = CWaypoints::getWaypoint(CWaypoints::getClosestFlagged(CWaypointTypes::W_FL_RESUPPLY, vOrigin, iTeam, &fResupplyDist, failedlist)); if ( bNeedAmmo ) - pWaypointAmmo = CWaypoints::getWaypoint(CWaypoints::getClosestFlagged(CWaypointTypes::W_FL_AMMO,vOrigin,iTeam,&fAmmoDist,failedlist)); - if ( bNeedHealth ) - pWaypointHealth = CWaypoints::getWaypoint(CWaypoints::getClosestFlagged(CWaypointTypes::W_FL_HEALTH,vOrigin,iTeam,&fHealthDist,failedlist)); + pWaypointAmmo = CWaypoints::getWaypoint(CWaypoints::getClosestFlagged(CWaypointTypes::W_FL_AMMO,vOrigin,getTeam(),&fAmmoDist,failedlist)); + if ( bNeedHealth && !CTeamFortress2Mod::isSuddenDeath()) + pWaypointHealth = CWaypoints::getWaypoint(CWaypoints::getClosestFlagged(CWaypointTypes::W_FL_HEALTH,vOrigin,getTeam(),&fHealthDist,failedlist)); } if ( iClass == TF_CLASS_ENGINEER ) @@ -4652,11 +4578,36 @@ void CBotTF2 :: getTasks ( unsigned int iIgnore ) updateCarrying(); } - ADD_UTILITY(BOT_UTIL_CAPTURE_FLAG,(CTeamFortress2Mod::isMapType(TF_MAP_CTF)||CTeamFortress2Mod::isMapType(TF_MAP_SD)) && bHasFlag,0.95f); + ADD_UTILITY(BOT_UTIL_CAPTURE_FLAG,(CTeamFortress2Mod::isMapType(TF_MAP_CTF)||CTeamFortress2Mod::isMapType(TF_MAP_SD)||CTeamFortress2Mod::isMapType(TF_MAP_TC)||CTeamFortress2Mod::isMapType(TF_MAP_CP)||CTeamFortress2Mod::isMapType(TF_MAP_RD)) && bHasFlag,0.95f) if ( iClass == TF_CLASS_ENGINEER ) { - bool bCanBuild = m_pWeapons->hasWeapon(TF2_WEAPON_BUILDER); + static int iMetalInDisp; + static float fSentryUtil; + static float fTeleporterExtPlaceTime; + static float fTeleporterEntPlaceTime; + static float fTeleporterExitHealthPercent; + static float fTeleporterEntranceHealthPercent; + static float fDispenserPlaceTime; + static float fSentryPlaceTime; + static float fDispenserHealthPercent; + static float fSentryHealthPercent; + static float fAllySentryHealthPercent; + static float fAllyDispenserHealthPercent; + static float fUseDispFactor; + static float fExitDist; + static float fEntranceDist; + static int iAllyDispLevel; + static int iAllySentryLevel; + static int iDispenserLevel; + static int iSentryLevel; + static bool bSentryHasEnemy; + static bool bMoveObjs; + const bool bCanBuild = m_pWeapons->hasWeapon(TF2_WEAPON_BUILDER); + + const string_t string = gpGlobals->mapname; + + const char* str1 = string.ToCStr(); bMoveObjs = rcbot_move_obj.GetBool(); @@ -4689,10 +4640,13 @@ void CBotTF2 :: getTasks ( unsigned int iIgnore ) fTeleporterExitHealthPercent = CClassInterface::getTeleporterHealth(m_pTeleExit)/180; - ADD_UTILITY(BOT_UTIL_ENGI_MOVE_EXIT,(CTeamFortress2Mod::hasRoundStarted()||CTeamFortress2Mod::isMapType(TF_MAP_MVM)) && (!m_bIsCarryingObj || m_bIsCarryingTeleExit) && bMoveObjs && m_pTeleEntrance && m_pTeleExit && + ADD_UTILITY(BOT_UTIL_ENGI_MOVE_EXIT, + (CTeamFortress2Mod::hasRoundStarted()||CTeamFortress2Mod::isMapType(TF_MAP_MVM)) && (! + m_bIsCarryingObj || m_bIsCarryingTeleExit) && bMoveObjs && m_pTeleEntrance && m_pTeleExit && m_fTeleporterExtPlacedTime && (fTeleporterExtPlaceTime > rcbot_move_tele_time.GetFloat()) && - (((60.0f * m_iTeleportedPlayers)/fTeleporterExtPlaceTime)(m_iTeleportedPlayers))/fTeleporterExtPlaceTime)( + m_bIsCarryingTeleExit))) } if ( m_pTeleEntrance.get() ) @@ -4701,50 +4655,78 @@ void CBotTF2 :: getTasks ( unsigned int iIgnore ) fTeleporterEntranceHealthPercent = CClassInterface::getTeleporterHealth(m_pTeleEntrance)/180; - ADD_UTILITY(BOT_UTIL_ENGI_MOVE_ENTRANCE,(!m_bIsCarryingObj || m_bIsCarryingTeleEnt) && bMoveObjs && m_bEntranceVectorValid && m_pTeleEntrance && m_pTeleExit && + ADD_UTILITY(BOT_UTIL_ENGI_MOVE_ENTRANCE, + (!m_bIsCarryingObj || m_bIsCarryingTeleEnt) && bMoveObjs && m_bEntranceVectorValid && + m_pTeleEntrance && m_pTeleExit && m_fTeleporterEntPlacedTime && (fTeleporterEntPlaceTime > rcbot_move_tele_time.GetFloat()) && - (((60.0f * m_iTeleportedPlayers)/fTeleporterEntPlaceTime)( + m_bIsCarryingTeleEnt))) } if ( m_pSentryGun.get() ) { - bSentryHasEnemy = (CClassInterface::getSentryEnemy(m_pSentryGun) != NULL); + bSentryHasEnemy = (CClassInterface::getSentryEnemy(m_pSentryGun) != nullptr); iSentryLevel = CClassInterface::getTF2UpgradeLevel(m_pSentryGun);//CTeamFortress2Mod::getSentryLevel(m_pSentryGun); - fSentryHealthPercent = ((float)CClassInterface::getSentryHealth(m_pSentryGun))/CClassInterface::getTF2GetBuildingMaxHealth(m_pSentryGun); + fSentryHealthPercent = CClassInterface::getSentryHealth(m_pSentryGun)/CClassInterface::getTF2GetBuildingMaxHealth(m_pSentryGun); // move sentry - ADD_UTILITY(BOT_UTIL_ENGI_MOVE_SENTRY,(CTeamFortress2Mod::hasRoundStarted()||CTeamFortress2Mod::isMapType(TF_MAP_MVM)) && (!m_bIsCarryingObj || m_bIsCarryingSentry) && - bMoveObjs && (m_fSentryPlaceTime>0.0f) && !bHasFlag && m_pSentryGun && (CClassInterface::getSentryEnemy(m_pSentryGun) == NULL) && ((m_fLastSentryEnemyTime + 15.0f) < engine->Time()) && - (!CTeamFortress2Mod::isMapType(TF_MAP_CP) || CTeamFortress2Mod::m_ObjectiveResource.testProbWptArea(m_iSentryArea,m_iTeam)) && - (fSentryPlaceTime>rcbot_move_sentry_time.GetFloat())&&(((60.0f*m_iSentryKills)/fSentryPlaceTime) 0.0f) && + !bHasFlag && m_pSentryGun && (CClassInterface::getSentryEnemy(m_pSentryGun) == nullptr) && + ((m_fLastSentryEnemyTime + 15.0f) < engine->Time()) && + (!CTeamFortress2Mod::isMapType(TF_MAP_CP) || std::strncmp(str1, "ctf_chouhen", 11) != 0 || std::strncmp(szmapname, "ctf_haarp", 9) != 0 || std::strncmp(szmapname, "ctf_vector", 10) != 0 || std::strncmp(szmapname, "ctf_snowdrift", 13) != 0 || + !CTeamFortress2Mod::isMapType(TF_MAP_CPPL) || + CTeamFortress2Mod::m_ObjectiveResource.testProbWptArea(m_iSentryArea, m_iTeam)) && + (fSentryPlaceTime > rcbot_move_sentry_time.GetFloat()) && + (((60.0f * m_iSentryKills) / fSentryPlaceTime) < rcbot_move_sentry_kpm.GetFloat()), + (fMetalPercent* getHealthPercent()* fSentryHealthPercent) + + (static_cast(m_bIsCarryingSentry))) } if ( m_pDispenser.get() ) { iMetalInDisp = CClassInterface::getTF2DispMetal(m_pDispenser); iDispenserLevel = CClassInterface::getTF2UpgradeLevel(m_pDispenser); // CTeamFortress2Mod::getDispenserLevel(m_pDispenser); - fDispenserHealthPercent = ((float)CClassInterface::getDispenserHealth(m_pDispenser)) / CClassInterface::getTF2GetBuildingMaxHealth(m_pDispenser); + fDispenserHealthPercent = CClassInterface::getDispenserHealth(m_pDispenser) / + CClassInterface::getTF2GetBuildingMaxHealth(m_pDispenser); - fUseDispFactor = (((float)iMetalInDisp)/400) * (1.0f-fMetalPercent) * ((float)iDispenserLevel/3) * (1000.0f/distanceFrom(m_pDispenser)); + fUseDispFactor = (static_cast(iMetalInDisp) / 400) * (1.0f - fMetalPercent) * (static_cast( + iDispenserLevel) / 3) * (1000.0f / distanceFrom(m_pDispenser)); // move disp - ADD_UTILITY(BOT_UTIL_ENGI_MOVE_DISP,(CTeamFortress2Mod::hasRoundStarted()||CTeamFortress2Mod::isMapType(TF_MAP_MVM)) && (!m_bIsCarryingObj || m_bIsCarryingDisp) && bMoveObjs && (m_fDispenserPlaceTime>0.0f) && !bHasFlag && m_pDispenser && (fDispenserPlaceTime>rcbot_move_disp_time.GetFloat())&&(((60.0f*m_fDispenserHealAmount)/fDispenserPlaceTime)0.0f) && ! + bHasFlag && m_pDispenser && (fDispenserPlaceTime>rcbot_move_disp_time.GetFloat())&&(((60.0f* + m_fDispenserHealAmount)/fDispenserPlaceTime)(iMetalInDisp))/400)*fMetalPercent*getHealthPercent()* + fDispenserHealthPercent) + (static_cast(m_bIsCarryingDisp))) } if ( m_pNearestDisp && (m_pNearestDisp.get() != m_pDispenser.get()) ) { iMetalInDisp = CClassInterface::getTF2DispMetal(m_pNearestDisp); iAllyDispLevel = CClassInterface::getTF2UpgradeLevel(m_pNearestDisp); // CTeamFortress2Mod::getDispenserLevel(m_pDispenser); - fAllyDispenserHealthPercent = ((float)CClassInterface::getDispenserHealth(m_pNearestDisp)) / CClassInterface::getTF2GetBuildingMaxHealth(m_pNearestDisp); - - fUseDispFactor = (((float)iMetalInDisp)/400) * (1.0f-fMetalPercent) * ((float)iAllyDispLevel/3) * (1000.0f/distanceFrom(m_pNearestDisp)); - - ADD_UTILITY(BOT_UTIL_GOTODISP,m_pNearestDisp && !CClassInterface::isObjectBeingBuilt(m_pNearestDisp) && (bNeedAmmo || bNeedHealth),fUseDispFactor + ((!CTeamFortress2Mod::hasRoundStarted() && CTeamFortress2Mod::isMapType(TF_MAP_MVM))?0.5f:0.0f)); - ADD_UTILITY(BOT_UTIL_REMOVE_TMDISP_SAPPER,!m_bIsCarryingObj && (m_fRemoveSapTimeTime()) &&m_pNearestDisp && CTeamFortress2Mod::isDispenserSapped(m_pNearestDisp),1.1f); - ADD_UTILITY(BOT_UTIL_UPGTMDISP,!m_bIsCarryingObj && (m_fRemoveSapTimeTime()) && (m_pNearestDisp!=NULL)&&(m_pNearestDisp!=m_pDispenser) && (iMetal>=(200-CClassInterface::getTF2SentryUpgradeMetal(m_pNearestDisp))) && ((iAllyDispLevel<3)||(fAllyDispenserHealthPercent<1.0f)),0.7+((1.0f-fAllyDispenserHealthPercent)*0.3)); + fAllyDispenserHealthPercent = CClassInterface::getDispenserHealth(m_pNearestDisp) / + CClassInterface::getTF2GetBuildingMaxHealth(m_pNearestDisp); + + fUseDispFactor = (static_cast(iMetalInDisp) / 400) * (1.0f - fMetalPercent) * (static_cast(iAllyDispLevel) / 3) * ( + 1000.0f / distanceFrom(m_pNearestDisp)); + + ADD_UTILITY(BOT_UTIL_GOTODISP, + m_pNearestDisp && !CClassInterface::isObjectBeingBuilt(m_pNearestDisp) && (bNeedAmmo || + bNeedHealth), + fUseDispFactor + ((!CTeamFortress2Mod::hasRoundStarted() && CTeamFortress2Mod::isMapType( + TF_MAP_MVM))?0.5f:0.0f)) + ADD_UTILITY(BOT_UTIL_REMOVE_TMDISP_SAPPER, + !m_bIsCarryingObj && (m_fRemoveSapTimeTime()) &&m_pNearestDisp && CTeamFortress2Mod:: + isDispenserSapped(m_pNearestDisp), 1.1f) + ADD_UTILITY(BOT_UTIL_UPGTMDISP, + !m_bIsCarryingObj && (m_fRemoveSapTimeTime()) && (m_pNearestDisp!=NULL)&&( + m_pNearestDisp!=m_pDispenser) && (iMetal>=(200-CClassInterface::getTF2SentryUpgradeMetal( + m_pNearestDisp))) && ((iAllyDispLevel<3)||(fAllyDispenserHealthPercent<1.0f)), + 0.7f+((1.0f-fAllyDispenserHealthPercent)*0.3f)) } if ( m_pNearestAllySentry && (m_pNearestAllySentry.get() != m_pSentryGun.get()) && !CClassInterface::getTF2BuildingIsMini(m_pNearestAllySentry) ) @@ -4753,34 +4735,35 @@ void CBotTF2 :: getTasks ( unsigned int iIgnore ) fAllySentryHealthPercent = CClassInterface::getSentryHealth(m_pNearestAllySentry); fAllySentryHealthPercent = fAllySentryHealthPercent / CClassInterface::getTF2GetBuildingMaxHealth(m_pNearestAllySentry); - ADD_UTILITY(BOT_UTIL_REMOVE_TMSENTRY_SAPPER,!m_bIsCarryingObj && (m_fRemoveSapTimeTime()) &&m_pNearestAllySentry && CTeamFortress2Mod::isSentrySapped(m_pNearestAllySentry),1.1f); - ADD_UTILITY(BOT_UTIL_UPGTMSENTRY,(fAllySentryHealthPercent > 0.0f) && !m_bIsCarryingObj && (m_fRemoveSapTimeTime()) && !bHasFlag && m_pNearestAllySentry && (m_pNearestAllySentry!=m_pSentryGun) && (iMetal>=(200-CClassInterface::getTF2SentryUpgradeMetal(m_pNearestAllySentry))) && ((iAllySentryLevel<3)||(fAllySentryHealthPercent<1.0f)),0.8+((1.0f-fAllySentryHealthPercent)*0.2)); + ADD_UTILITY(BOT_UTIL_REMOVE_TMSENTRY_SAPPER,!m_bIsCarryingObj && (m_fRemoveSapTimeTime()) &&m_pNearestAllySentry && CTeamFortress2Mod::isSentrySapped(m_pNearestAllySentry),1.1f) + ADD_UTILITY(BOT_UTIL_UPGTMSENTRY,(fAllySentryHealthPercent > 0.0f) && !m_bIsCarryingObj && (m_fRemoveSapTimeTime()) && !bHasFlag && m_pNearestAllySentry && (m_pNearestAllySentry!=m_pSentryGun) && (iMetal>=(200-CClassInterface::getTF2SentryUpgradeMetal(m_pNearestAllySentry))) && ((iAllySentryLevel<3)||(fAllySentryHealthPercent<1.0f)),0.8f+((1.0f-fAllySentryHealthPercent)*0.2f)) } - fSentryUtil = 0.8 + (((float)((int)bNeedAmmo))*0.1) + (((float)(int)bNeedHealth)*0.1); + fSentryUtil = 0.8f + (static_cast(static_cast(bNeedAmmo))*0.1f) + (static_cast(static_cast(bNeedHealth))*0.1f); - ADD_UTILITY(BOT_UTIL_PLACE_BUILDING, m_bIsCarryingObj, 1.0f); // something went wrong moving this- I still have it!!! + ADD_UTILITY(BOT_UTIL_PLACE_BUILDING, m_bIsCarryingObj, 1.0f) + // something went wrong moving this- I still have it!!! // destroy and build anew - ADD_UTILITY(BOT_UTIL_ENGI_DESTROY_SENTRY, !m_bIsCarryingObj && (iMetal>=130) && (m_pSentryGun.get()!=NULL) && !CTeamFortress2Mod::m_ObjectiveResource.isWaypointAreaValid(m_iSentryArea),fSentryUtil); - ADD_UTILITY(BOT_UTIL_ENGI_DESTROY_DISP, !m_bIsCarryingObj && (iMetal>=125) && (m_pDispenser.get()!=NULL) && !CTeamFortress2Mod::m_ObjectiveResource.isWaypointAreaValid(m_iDispenserArea),randomFloat(0.7,0.9)); - ADD_UTILITY(BOT_UTIL_ENGI_DESTROY_ENTRANCE, !m_bIsCarryingObj && (iMetal>=125) && (m_pTeleEntrance.get()!=NULL) && !CTeamFortress2Mod::m_ObjectiveResource.isWaypointAreaValid(m_iTeleEntranceArea),randomFloat(0.7,0.9)); + ADD_UTILITY(BOT_UTIL_ENGI_DESTROY_SENTRY, !m_bIsCarryingObj && (iMetal>=130) && (m_pSentryGun.get()!=NULL) && !CTeamFortress2Mod::m_ObjectiveResource.isWaypointAreaValid(m_iSentryArea),fSentryUtil) + ADD_UTILITY(BOT_UTIL_ENGI_DESTROY_DISP, !m_bIsCarryingObj && (iMetal>=125) && (m_pDispenser.get()!=NULL) && !CTeamFortress2Mod::m_ObjectiveResource.isWaypointAreaValid(m_iDispenserArea),randomFloat(0.7f,0.9f)) + ADD_UTILITY(BOT_UTIL_ENGI_DESTROY_ENTRANCE, !m_bIsCarryingObj && (iMetal>=125) && (m_pTeleEntrance.get()!=NULL) && !CTeamFortress2Mod::m_ObjectiveResource.isWaypointAreaValid(m_iTeleEntranceArea),randomFloat(0.7f,0.9f)) //ADD_UTILITY(BOT_UTIL_ENGI_DESTROY_EXIT, (iMetal>=125) && (m_pTeleExit.get()!=NULL) && !CPoints::isValidArea(m_iTeleExitArea),randomFloat(0.7,0.9)); if (bCanBuild) { - ADD_UTILITY(BOT_UTIL_BUILDSENTRY, !m_bIsCarryingObj && !bHasFlag && !m_pSentryGun && (iMetal >= 130), 0.9); - ADD_UTILITY(BOT_UTIL_BUILDDISP, !m_bIsCarryingObj && !bHasFlag&& m_pSentryGun && (CClassInterface::getSentryHealth(m_pSentryGun) > 125) && !m_pDispenser && (iMetal >= 100), fSentryUtil); + ADD_UTILITY(BOT_UTIL_BUILDSENTRY, !m_bIsCarryingObj && !bHasFlag && !m_pSentryGun && (iMetal >= 130), 0.9f) + ADD_UTILITY(BOT_UTIL_BUILDDISP, !m_bIsCarryingObj && !bHasFlag&& m_pSentryGun && (CClassInterface::getSentryHealth(m_pSentryGun) > 125) && !m_pDispenser && (iMetal >= 100), fSentryUtil) if (CTeamFortress2Mod::isAttackDefendMap() && (iTeam == TF2_TEAM_BLUE)) { - ADD_UTILITY(BOT_UTIL_BUILDTELEXT, (fSentryHealthPercent > 0.99f) && !m_bIsCarryingObj && !bHasFlag&&!m_pTeleExit && (iMetal >= 125), randomFloat(0.7f, 0.9f)); - ADD_UTILITY(BOT_UTIL_BUILDTELENT, !bSentryHasEnemy && (fSentryHealthPercent > 0.99f) && !m_bIsCarryingObj && !bHasFlag&&m_bEntranceVectorValid&&!m_pTeleEntrance && (iMetal >= 125), 0.7f); + ADD_UTILITY(BOT_UTIL_BUILDTELEXT, (fSentryHealthPercent > 0.99f) && !m_bIsCarryingObj && !bHasFlag&&!m_pTeleExit && (iMetal >= 125), randomFloat(0.7f, 0.9f)) + ADD_UTILITY(BOT_UTIL_BUILDTELENT, !bSentryHasEnemy && (fSentryHealthPercent > 0.99f) && !m_bIsCarryingObj && !bHasFlag&&m_bEntranceVectorValid&&!m_pTeleEntrance && (iMetal >= 125), 0.7f) } else { - ADD_UTILITY(BOT_UTIL_BUILDTELENT, (fSentryHealthPercent > 0.99f) && !m_bIsCarryingObj && !bHasFlag && ((m_pSentryGun.get() && (iSentryLevel > 1)) || (m_pSentryGun.get() == NULL)) && m_bEntranceVectorValid&&!m_pTeleEntrance && (iMetal >= 125), 0.7f); - ADD_UTILITY(BOT_UTIL_BUILDTELEXT, !bSentryHasEnemy && (fSentryHealthPercent > 0.99f) && !m_bIsCarryingObj && !bHasFlag&&m_pSentryGun && (iSentryLevel > 1) && !m_pTeleExit && (iMetal >= 125), randomFloat(0.7, 0.9)); + ADD_UTILITY(BOT_UTIL_BUILDTELENT, (fSentryHealthPercent > 0.99f) && !m_bIsCarryingObj && !bHasFlag && ((m_pSentryGun.get() && (iSentryLevel > 1)) || (m_pSentryGun.get() == NULL)) && m_bEntranceVectorValid&&!m_pTeleEntrance && (iMetal >= 125), 0.7f) + ADD_UTILITY(BOT_UTIL_BUILDTELEXT, !bSentryHasEnemy && (fSentryHealthPercent > 0.99f) && !m_bIsCarryingObj && !bHasFlag&&m_pSentryGun && (iSentryLevel > 1) && !m_pTeleExit && (iMetal >= 125), randomFloat(0.7f, 0.9f)) } @@ -4789,55 +4772,54 @@ void CBotTF2 :: getTasks ( unsigned int iIgnore ) if (CTeamFortress2Mod::isMapType(TF_MAP_MVM)) { - ADD_UTILITY(BOT_UTIL_BUILDTELENT, !m_bIsCarryingObj && !bHasFlag&&m_bEntranceVectorValid&&!m_pTeleEntrance && (iMetal >= 125), 0.95f); + ADD_UTILITY(BOT_UTIL_BUILDTELENT, !m_bIsCarryingObj && !bHasFlag&&m_bEntranceVectorValid&&!m_pTeleEntrance && (iMetal >= 125), 0.95f) } else { - dataUnconstArray *failed; - Vector vOrigin = getOrigin(); + vOrigin = getOrigin(); + WaypointList *failed; m_pNavigator->getFailedGoals(&failed); failedlist = CWaypointLocations::resetFailedWaypoints(failed); - pWaypointResupply = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(vOrigin, 1024.0f, -1, false, false, true, NULL, false, getTeam(), true, false, Vector(0, 0, 0), CWaypointTypes::W_FL_RESUPPLY));//CWaypoints::getWaypoint(CWaypoints::getClosestFlagged(CWaypointTypes::W_FL_RESUPPLY,vOrigin,iTeam,&fResupplyDist,failedlist)); + pWaypointResupply = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(vOrigin, 1024.0f, -1, false, false, true, nullptr, false, getTeam(), true, false, Vector(0, 0, 0), CWaypointTypes::W_FL_RESUPPLY));//CWaypoints::getWaypoint(CWaypoints::getClosestFlagged(CWaypointTypes::W_FL_RESUPPLY,vOrigin,iTeam,&fResupplyDist,failedlist)); - ADD_UTILITY_DATA(BOT_UTIL_BUILDTELENT_SPAWN, !m_bIsCarryingObj && (pWaypointResupply != NULL) && !bHasFlag&&!m_pTeleEntrance && (iMetal >= 125), 0.95f, CWaypoints::getWaypointIndex(pWaypointResupply)); + ADD_UTILITY_DATA(BOT_UTIL_BUILDTELENT_SPAWN, !m_bIsCarryingObj && (pWaypointResupply != NULL) && !bHasFlag&&!m_pTeleEntrance && (iMetal >= 125), 0.95f, CWaypoints::getWaypointIndex(pWaypointResupply)) } } } - // to do -- split into two - ADD_UTILITY(BOT_UTIL_UPGSENTRY,!m_bIsCarryingObj && (m_fRemoveSapTimeTime()) &&!bHasFlag &&( m_pSentryGun.get()!=NULL) && !CClassInterface::getTF2BuildingIsMini(m_pSentryGun) && (((iSentryLevel<3)&&(iMetal>=(200-CClassInterface::getTF2SentryUpgradeMetal(m_pSentryGun)))) || ((fSentryHealthPercent<1.0f)&&(iMetal>75)) || (CClassInterface::getSentryEnemy(m_pSentryGun)!=NULL) ),0.8+((1.0f-fSentryHealthPercent)*0.2)); + // TODO: -- split into two + ADD_UTILITY(BOT_UTIL_UPGSENTRY,!m_bIsCarryingObj && (m_fRemoveSapTimeTime()) &&!bHasFlag &&( m_pSentryGun.get()!=NULL) && !CClassInterface::getTF2BuildingIsMini(m_pSentryGun) && (((iSentryLevel<3)&&(iMetal>=(200-CClassInterface::getTF2SentryUpgradeMetal(m_pSentryGun)))) || ((fSentryHealthPercent<1.0f)&&(iMetal>75)) || (CClassInterface::getSentryEnemy(m_pSentryGun)!=NULL) ),0.8f+((1.0f-fSentryHealthPercent)*0.2f)) - ADD_UTILITY(BOT_UTIL_GETAMMODISP,!m_bIsCarryingObj && m_pDispenser && !CClassInterface::isObjectBeingBuilt(m_pDispenser) && isVisible(m_pDispenser) && (iMetal<200),fUseDispFactor); + ADD_UTILITY(BOT_UTIL_GETAMMODISP,!m_bIsCarryingObj && m_pDispenser && !CClassInterface::isObjectBeingBuilt(m_pDispenser) && isVisible(m_pDispenser) && (iMetal<200),fUseDispFactor) - ADD_UTILITY(BOT_UTIL_UPGTELENT,!m_bIsCarryingObj && (m_fRemoveSapTimeTime()) &&m_pTeleEntrance!=NULL && !CClassInterface::isObjectBeingBuilt(m_pTeleEntrance) && (iMetal>=(200-CClassInterface::getTF2SentryUpgradeMetal(m_pTeleEntrance))) && (fTeleporterEntranceHealthPercent<1.0f),((fEntranceDistTime()) &&m_pTeleExit!=NULL && !CClassInterface::isObjectBeingBuilt(m_pTeleExit) && (iMetal>=(200-CClassInterface::getTF2SentryUpgradeMetal(m_pTeleExit))) && (fTeleporterExitHealthPercent<1.0f),((fExitDistTime()) &&m_pDispenser!=NULL && !CClassInterface::isObjectBeingBuilt(m_pDispenser) && (iMetal>=(200-CClassInterface::getTF2SentryUpgradeMetal(m_pDispenser))) && ((iDispenserLevel<3)||(fDispenserHealthPercent<1.0f)),0.7+((1.0f-fDispenserHealthPercent)*0.3)); + ADD_UTILITY(BOT_UTIL_UPGTELENT,!m_bIsCarryingObj && (m_fRemoveSapTimeTime()) &&m_pTeleEntrance!=NULL && !CClassInterface::isObjectBeingBuilt(m_pTeleEntrance) && (iMetal>=(200-CClassInterface::getTF2SentryUpgradeMetal(m_pTeleEntrance))) && (fTeleporterEntranceHealthPercent<1.0f),((fEntranceDistTime()) &&m_pTeleExit!=NULL && !CClassInterface::isObjectBeingBuilt(m_pTeleExit) && (iMetal>=(200-CClassInterface::getTF2SentryUpgradeMetal(m_pTeleExit))) && (fTeleporterExitHealthPercent<1.0f),((fExitDistTime()) &&m_pDispenser!=NULL && !CClassInterface::isObjectBeingBuilt(m_pDispenser) && (iMetal>=(200-CClassInterface::getTF2SentryUpgradeMetal(m_pDispenser))) && ((iDispenserLevel<3)||(fDispenserHealthPercent<1.0f)),0.7f+((1.0f-fDispenserHealthPercent)*0.3f)) // remove sappers - ADD_UTILITY(BOT_UTIL_REMOVE_SENTRY_SAPPER,!m_bIsCarryingObj && (m_fRemoveSapTimeTime()) &&!bHasFlag&&(m_pSentryGun!=NULL) && CTeamFortress2Mod::isMySentrySapped(m_pEdict),1000.0f); - ADD_UTILITY(BOT_UTIL_REMOVE_DISP_SAPPER,!m_bIsCarryingObj && (m_fRemoveSapTimeTime()) &&!bHasFlag&&(m_pDispenser!=NULL) && CTeamFortress2Mod::isMyDispenserSapped(m_pEdict),1000.0f); + ADD_UTILITY(BOT_UTIL_REMOVE_SENTRY_SAPPER,!m_bIsCarryingObj && (m_fRemoveSapTimeTime()) &&!bHasFlag&&(m_pSentryGun!=NULL) && CTeamFortress2Mod::isMySentrySapped(m_pEdict),1000.0f) + ADD_UTILITY(BOT_UTIL_REMOVE_DISP_SAPPER,!m_bIsCarryingObj && (m_fRemoveSapTimeTime()) &&!bHasFlag&&(m_pDispenser!=NULL) && CTeamFortress2Mod::isMyDispenserSapped(m_pEdict),1000.0f) - ADD_UTILITY_DATA(BOT_UTIL_GOTORESUPPLY_FOR_AMMO, !bIsUbered && !m_bIsCarryingObj && !bHasFlag && pWaypointResupply && bNeedAmmo && !m_pAmmo, 1000.0f / fResupplyDist, CWaypoints::getWaypointIndex(pWaypointResupply)); + ADD_UTILITY_DATA(BOT_UTIL_GOTORESUPPLY_FOR_AMMO, !bIsUbered && !m_bIsCarryingObj && !bHasFlag && pWaypointResupply && bNeedAmmo && !m_pAmmo && !CTeamFortress2Mod::isSuddenDeath(), 1000.0f / fResupplyDist, CWaypoints::getWaypointIndex(pWaypointResupply)) - ADD_UTILITY_DATA(BOT_UTIL_FIND_NEAREST_AMMO,!m_bIsCarryingObj && !bHasFlag&&bNeedAmmo&&!m_pAmmo&&pWaypointAmmo,(400.0f/fAmmoDist) + ((!CTeamFortress2Mod::hasRoundStarted() && CTeamFortress2Mod::isMapType(TF_MAP_MVM))?0.5f:0.0f),CWaypoints::getWaypointIndex(pWaypointAmmo)); // only if close + ADD_UTILITY_DATA(BOT_UTIL_FIND_NEAREST_AMMO,!m_bIsCarryingObj && !bHasFlag&&bNeedAmmo&&!m_pAmmo&&pWaypointAmmo,(400.0f/fAmmoDist) + ((!CTeamFortress2Mod::hasRoundStarted() && CTeamFortress2Mod::isMapType(TF_MAP_MVM))?0.5f:0.0f),CWaypoints::getWaypointIndex(pWaypointAmmo)) + // only if close - ADD_UTILITY(BOT_UTIL_ENGI_LOOK_AFTER_SENTRY,!m_bIsCarryingObj && (m_pSentryGun.get()!=NULL) && (iSentryLevel>2) && (m_fLookAfterSentryTimeTime()),fGetFlagUtility+0.01f); + ADD_UTILITY(BOT_UTIL_ENGI_LOOK_AFTER_SENTRY,!m_bIsCarryingObj && (m_pSentryGun.get()!=NULL) && (iSentryLevel>2) && (m_fLookAfterSentryTimeTime()),fGetFlagUtility+0.01f) // remove sappers - ADD_UTILITY(BOT_UTIL_REMOVE_TMTELE_SAPPER,!m_bIsCarryingObj && (m_fRemoveSapTimeTime()) &&m_pNearestTeleEntrance && CTeamFortress2Mod::isTeleporterSapped(m_pNearestTeleEntrance),1.1f); - + ADD_UTILITY(BOT_UTIL_REMOVE_TMTELE_SAPPER,!m_bIsCarryingObj && (m_fRemoveSapTimeTime()) &&m_pNearestTeleEntrance && CTeamFortress2Mod::isTeleporterSapped(m_pNearestTeleEntrance),1.1f) - -// booooo + // booooo } else { pMedigun = CTeamFortress2Mod::getMediGun(m_pEdict); - if ( pMedigun != NULL ) + if ( pMedigun != nullptr) pBWMediGun = m_pWeapons->getWeapon(CWeapons::getWeapon(TF2_WEAPON_MEDIGUN)); if ( !m_pNearestDisp ) @@ -4848,18 +4830,18 @@ void CBotTF2 :: getTasks ( unsigned int iIgnore ) if ( ( m_iClass != TF_CLASS_SPY ) && ( m_iClass != TF_CLASS_MEDIC) && ( m_iClass != TF_CLASS_SNIPER) ) { //squads // follow leader // follow_leader - ADD_UTILITY(BOT_UTIL_FOLLOW_SQUAD_LEADER,!hasSomeConditions(CONDITION_DEFENSIVE) && hasSomeConditions(CONDITION_SQUAD_LEADER_INRANGE) && inSquad() && (m_pSquad->GetLeader()!=m_pEdict) && hasSomeConditions(CONDITION_SEE_SQUAD_LEADER),hasSomeConditions(CONDITION_SQUAD_IDLE)?0.1f:2.0f); - ADD_UTILITY(BOT_UTIL_FIND_SQUAD_LEADER,!hasSomeConditions(CONDITION_DEFENSIVE) && inSquad() && (m_pSquad->GetLeader()!=m_pEdict) && (!hasSomeConditions(CONDITION_SEE_SQUAD_LEADER) || !hasSomeConditions(CONDITION_SQUAD_LEADER_INRANGE)),hasSomeConditions(CONDITION_SQUAD_IDLE)?0.1f:2.0f); + ADD_UTILITY(BOT_UTIL_FOLLOW_SQUAD_LEADER,!hasSomeConditions(CONDITION_DEFENSIVE) && hasSomeConditions(CONDITION_SQUAD_LEADER_INRANGE) && inSquad() && (m_pSquad->GetLeader()!=m_pEdict) && hasSomeConditions(CONDITION_SEE_SQUAD_LEADER),hasSomeConditions(CONDITION_SQUAD_IDLE)?0.1f:2.0f) + ADD_UTILITY(BOT_UTIL_FIND_SQUAD_LEADER,!hasSomeConditions(CONDITION_DEFENSIVE) && inSquad() && (m_pSquad->GetLeader()!=m_pEdict) && (!hasSomeConditions(CONDITION_SEE_SQUAD_LEADER) || !hasSomeConditions(CONDITION_SQUAD_LEADER_INRANGE)),hasSomeConditions(CONDITION_SQUAD_IDLE)?0.1f:2.0f) } - ADD_UTILITY_DATA(BOT_UTIL_GOTORESUPPLY_FOR_AMMO, !bIsUbered && !m_bIsCarryingObj && !bHasFlag && pWaypointResupply && bNeedAmmo && !m_pAmmo, 1000.0f / fResupplyDist, CWaypoints::getWaypointIndex(pWaypointResupply)); - ADD_UTILITY_DATA(BOT_UTIL_FIND_NEAREST_AMMO, !bHasFlag&&bNeedAmmo&&!m_pAmmo&&pWaypointAmmo,(400.0f/fAmmoDist) + ((!CTeamFortress2Mod::hasRoundStarted() && CTeamFortress2Mod::isMapType(TF_MAP_MVM))?0.5f:0.0f),CWaypoints::getWaypointIndex(pWaypointAmmo)); + ADD_UTILITY_DATA(BOT_UTIL_GOTORESUPPLY_FOR_AMMO, !bIsUbered && !m_bIsCarryingObj && !bHasFlag && pWaypointResupply && bNeedAmmo && !m_pAmmo && !CTeamFortress2Mod::isSuddenDeath(), 1000.0f / fResupplyDist, CWaypoints::getWaypointIndex(pWaypointResupply)) + ADD_UTILITY_DATA(BOT_UTIL_FIND_NEAREST_AMMO, !bHasFlag&&bNeedAmmo&&!m_pAmmo&&pWaypointAmmo,(400.0f/fAmmoDist) + ((!CTeamFortress2Mod::hasRoundStarted() && CTeamFortress2Mod::isMapType(TF_MAP_MVM))?0.5f:0.0f),CWaypoints::getWaypointIndex(pWaypointAmmo)) if ( m_pNearestDisp ) - ADD_UTILITY(BOT_UTIL_GOTODISP,m_pNearestDisp && !CClassInterface::isObjectBeingBuilt(m_pNearestDisp) && !CTeamFortress2Mod::isDispenserSapped(m_pNearestDisp) && (bNeedAmmo || bNeedHealth),(1000.0f/distanceFrom(m_pNearestDisp)) + ((!CTeamFortress2Mod::hasRoundStarted() && CTeamFortress2Mod::isMapType(TF_MAP_MVM))?0.5f:0.0f)); + ADD_UTILITY(BOT_UTIL_GOTODISP,m_pNearestDisp && !CClassInterface::isObjectBeingBuilt(m_pNearestDisp) && !CTeamFortress2Mod::isDispenserSapped(m_pNearestDisp) && (bNeedAmmo || bNeedHealth),(1000.0f/distanceFrom(m_pNearestDisp)) + ((!CTeamFortress2Mod::hasRoundStarted() && CTeamFortress2Mod::isMapType(TF_MAP_MVM))?0.5f:0.0f)) } - fGetFlagUtility = 0.2+randomFloat(0.0f,0.2f); + fGetFlagUtility = 0.2f + randomFloat(0.0f,0.2f); if ( m_iClass == TF_CLASS_SCOUT ) fGetFlagUtility = 0.6f; @@ -4868,7 +4850,7 @@ void CBotTF2 :: getTasks ( unsigned int iIgnore ) else if ( m_iClass == TF_CLASS_MEDIC ) { if ( CTeamFortress2Mod::hasRoundStarted() ) - fGetFlagUtility = 0.85f - (((float)numplayersonteam)/(gpGlobals->maxClients/2)); + fGetFlagUtility = 0.85f - (static_cast(numplayersonteam) / (static_cast(gpGlobals->maxClients) / 2.0f)); else fGetFlagUtility = 0.1f; // not my priority } @@ -4896,7 +4878,7 @@ void CBotTF2 :: getTasks ( unsigned int iIgnore ) } // recently saw an enemy go near the point - if ( hasSomeConditions(CONDITION_DEFENSIVE) && (m_pLastEnemy.get() != NULL) && CBotGlobals::entityIsAlive(m_pLastEnemy.get()) && (m_fLastSeeEnemy > 0) ) + if ( hasSomeConditions(CONDITION_DEFENSIVE) && (m_pLastEnemy.get() != nullptr) && CBotGlobals::entityIsAlive(m_pLastEnemy.get()) && (m_fLastSeeEnemy > 0) ) fDefendFlagUtility = fGetFlagUtility+0.1f; if ( m_iClass == TF_CLASS_ENGINEER ) @@ -4904,72 +4886,106 @@ void CBotTF2 :: getTasks ( unsigned int iIgnore ) if ( m_bIsCarryingObj ) fDefendFlagUtility = 0.0f; } - ADD_UTILITY_DATA(BOT_UTIL_GOTORESUPPLY_FOR_HEALTH, !bIsUbered && !m_bIsCarryingObj && !bHasFlag && pWaypointResupply && bNeedHealth && !m_pHealthkit, 1000.0f / fResupplyDist, CWaypoints::getWaypointIndex(pWaypointResupply)); + ADD_UTILITY_DATA(BOT_UTIL_GOTORESUPPLY_FOR_HEALTH, + !bIsUbered && !m_bIsCarryingObj && !bHasFlag && pWaypointResupply && bNeedHealth && !m_pHealthkit && !CTeamFortress2Mod::isSuddenDeath(), + 1000.0f / fResupplyDist, CWaypoints::getWaypointIndex(pWaypointResupply)) + + ADD_UTILITY(BOT_UTIL_GETAMMOKIT, bNeedAmmo && m_pAmmo, + 1.0f + ((!CTeamFortress2Mod::hasRoundStarted() && CTeamFortress2Mod::isMapType(TF_MAP_MVM))?0.5f:0.0f)) - ADD_UTILITY(BOT_UTIL_GETAMMOKIT, bNeedAmmo && m_pAmmo,1.0 + ((!CTeamFortress2Mod::hasRoundStarted() && CTeamFortress2Mod::isMapType(TF_MAP_MVM))?0.5f:0.0f)); - ADD_UTILITY(BOT_UTIL_GETHEALTHKIT, bNeedHealth && m_pHealthkit,1.0 + ((!CTeamFortress2Mod::hasRoundStarted() && CTeamFortress2Mod::isMapType(TF_MAP_MVM))?0.5f:0.0f)); + ADD_UTILITY(BOT_UTIL_GETHEALTHKIT, bNeedHealth && m_pHealthkit && !CTeamFortress2Mod::isSuddenDeath(), + 1.0f + ((!CTeamFortress2Mod::hasRoundStarted() && CTeamFortress2Mod::isMapType(TF_MAP_MVM))?0.5f:0.0f)) - ADD_UTILITY(BOT_UTIL_GETFLAG, (CTeamFortress2Mod::isMapType(TF_MAP_CTF)||(CTeamFortress2Mod::isMapType(TF_MAP_SD)&&CTeamFortress2Mod::canTeamPickupFlag_SD(iTeam,false))) && !bHasFlag,fGetFlagUtility); - ADD_UTILITY(BOT_UTIL_GETFLAG_LASTKNOWN, (CTeamFortress2Mod::isMapType(TF_MAP_CTF)||CTeamFortress2Mod::isMapType(TF_MAP_MVM)||(CTeamFortress2Mod::isMapType(TF_MAP_SD)&&CTeamFortress2Mod::canTeamPickupFlag_SD(iTeam,true))) && !bHasFlag && (m_fLastKnownFlagTime && (m_fLastKnownFlagTime > engine->Time())), fGetFlagUtility+0.1); + ADD_UTILITY(BOT_UTIL_GETFLAG, + (CTeamFortress2Mod::isMapType(TF_MAP_CTF)||(CTeamFortress2Mod::isMapType(TF_MAP_RD)||(CTeamFortress2Mod + ::isMapType(TF_MAP_SD)&&CTeamFortress2Mod::canTeamPickupFlag_SD(iTeam,false)))) && !bHasFlag, + fGetFlagUtility) + + ADD_UTILITY(BOT_UTIL_GETFLAG_LASTKNOWN, + (CTeamFortress2Mod::isMapType(TF_MAP_CTF)||(CTeamFortress2Mod::isMapType(TF_MAP_RD)||CTeamFortress2Mod:: + isMapType(TF_MAP_MVM)||(CTeamFortress2Mod::isMapType(TF_MAP_SD)&&CTeamFortress2Mod:: + canTeamPickupFlag_SD(iTeam,true)))) && !bHasFlag && (m_fLastKnownFlagTime && ( + m_fLastKnownFlagTime > engine->Time())), fGetFlagUtility+0.1f) + + ADD_UTILITY(BOT_UTIL_DEFEND_FLAG, + CTeamFortress2Mod::isMapType(TF_MAP_MVM) || + (CTeamFortress2Mod::isMapType(TF_MAP_CTF) && !bHasFlag) || + (CTeamFortress2Mod::isMapType(TF_MAP_CP) && !bHasFlag) || + (CTeamFortress2Mod::isMapType(TF_MAP_TC) && !bHasFlag) || + (CTeamFortress2Mod::isMapType(TF_MAP_RD) && !bHasFlag && (iClass != TF_CLASS_ENGINEER)), + fDefendFlagUtility + 0.1f) - ADD_UTILITY(BOT_UTIL_DEFEND_FLAG, CTeamFortress2Mod::isMapType(TF_MAP_MVM)||(CTeamFortress2Mod::isMapType(TF_MAP_CTF) && !bHasFlag), fDefendFlagUtility+0.1); ADD_UTILITY(BOT_UTIL_DEFEND_FLAG_LASTKNOWN, !bHasFlag && - (CTeamFortress2Mod::isMapType(TF_MAP_CTF) || CTeamFortress2Mod::isMapType(TF_MAP_MVM) || + (CTeamFortress2Mod::isMapType(TF_MAP_CTF) || CTeamFortress2Mod::isMapType(TF_MAP_MVM) || CTeamFortress2Mod::isMapType(TF_MAP_TC) || CTeamFortress2Mod::isMapType(TF_MAP_CP) || CTeamFortress2Mod::isMapType(TF_MAP_RD) || (CTeamFortress2Mod::isMapType(TF_MAP_SD) && (CTeamFortress2Mod::getFlagCarrierTeam()==CTeamFortress2Mod::getEnemyTeam(iTeam)))) && (m_fLastKnownTeamFlagTime && (m_fLastKnownTeamFlagTime > engine->Time())), - fDefendFlagUtility+(randomFloat(0.0,0.2)-0.1)); - ADD_UTILITY(BOT_UTIL_SNIPE, (iClass == TF_CLASS_SNIPER) && m_pWeapons->hasWeapon(TF2_WEAPON_SNIPERRIFLE) && !m_pWeapons->getWeapon(CWeapons::getWeapon(TF2_WEAPON_SNIPERRIFLE))->outOfAmmo(this) && !hasSomeConditions(CONDITION_PARANOID) && !bHasFlag && (getHealthPercent()>0.2f), 0.95); - ADD_UTILITY(BOT_UTIL_SNIPE_CROSSBOW, (iClass == TF_CLASS_SNIPER) && m_pWeapons->hasWeapon(TF2_WEAPON_BOW) && !m_pWeapons->getWeapon(CWeapons::getWeapon(TF2_WEAPON_BOW))->outOfAmmo(this) && !hasSomeConditions(CONDITION_PARANOID) && !bHasFlag && (getHealthPercent()>0.2f), 0.95); + fDefendFlagUtility + (randomFloat (0.0f, 0.2f) - 0.1f)) - ADD_UTILITY(BOT_UTIL_ROAM,true,0.0001f); - ADD_UTILITY_DATA(BOT_UTIL_FIND_NEAREST_HEALTH,!bHasFlag&&bNeedHealth&&!m_pHealthkit&&pWaypointHealth,(1000.0f/fHealthDist) + ((!CTeamFortress2Mod::hasRoundStarted() && CTeamFortress2Mod::isMapType(TF_MAP_MVM))?0.5f:0.0f),CWaypoints::getWaypointIndex(pWaypointHealth)); - - ADD_UTILITY(BOT_UTIL_FIND_MEDIC_FOR_HEALTH,(m_iClass != TF_CLASS_MEDIC) && !bHasFlag && bNeedHealth && m_pLastSeeMedic.hasSeen(10.0f),1.0f); - - if ( (m_pNearestEnemySentry.get() != NULL) && !CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEdict) ) + ADD_UTILITY(BOT_UTIL_SNIPE, (iClass == TF_CLASS_SNIPER) && (m_pWeapons->getCurrentWeaponInSlot(0) && !m_pWeapons->hasWeapon(TF2_WEAPON_BOW)) + && !m_pWeapons->getCurrentWeaponInSlot(0)->isProjectile() + && !m_pWeapons->getCurrentWeaponInSlot(0)->outOfAmmo(this) && !hasSomeConditions(CONDITION_PARANOID) + && !bHasFlag && (getHealthPercent() > 0.2f), 0.95f) + //ADD_UTILITY(BOT_UTIL_SNIPE_CROSSBOW, (iClass == TF_CLASS_SNIPER) && m_pWeapons->hasWeapon(TF2_WEAPON_BOW) && !m_pWeapons->getWeapon(CWeapons::getWeapon(TF2_WEAPON_BOW))->outOfAmmo(this) && !hasSomeConditions(CONDITION_PARANOID) && !bHasFlag && (getHealthPercent()>0.2f), 0.95f) + + ADD_UTILITY(BOT_UTIL_ROAM,true,0.0001f) + ADD_UTILITY_DATA(BOT_UTIL_FIND_NEAREST_HEALTH, !bHasFlag&&bNeedHealth&&!m_pHealthkit&&pWaypointHealth, + (1000.0f/fHealthDist) + ((!CTeamFortress2Mod::hasRoundStarted() && CTeamFortress2Mod::isMapType( + TF_MAP_MVM))?0.5f:0.0f), CWaypoints::getWaypointIndex(pWaypointHealth)) + + ADD_UTILITY(BOT_UTIL_FIND_MEDIC_FOR_HEALTH,(m_iClass != TF_CLASS_MEDIC) && !bHasFlag && bNeedHealth && m_pLastSeeMedic.hasSeen(10.0f),1.0f) + + if ( (m_pNearestEnemySentry.get() != nullptr) && !CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEdict) && !((std::strncmp(szmapname, "koth_lakeside_event", 19) == 0 || std::strncmp(szmapname, "koth_viaduct_event", 18) == 0) && (CTeamFortress2Mod::isBossSummoned()))) { - CBotWeapon *pWeapon = m_pWeapons->getPrimaryWeapon(); + pWeapon = m_pWeapons->getPrimaryWeapon(); - ADD_UTILITY_DATA(BOT_UTIL_ATTACK_SENTRY,(distanceFrom(m_pNearestEnemySentry) >= CWaypointLocations::REACHABLE_RANGE) && (m_iClass!=TF_CLASS_SPY)&& pWeapon && !pWeapon->outOfAmmo(this) && pWeapon->primaryGreaterThanRange(TF2_MAX_SENTRYGUN_RANGE+32.0f),0.7f,ENTINDEX(m_pNearestEnemySentry.get())); + ADD_UTILITY_DATA(BOT_UTIL_ATTACK_SENTRY, + (distanceFrom(m_pNearestEnemySentry) >= CWaypointLocations::REACHABLE_RANGE) && (m_iClass!= + TF_CLASS_SPY)&& pWeapon && !pWeapon->outOfAmmo(this) && pWeapon->primaryGreaterThanRange( + static_cast(TF2_MAX_SENTRYGUN_RANGE)+32.0f), 0.7f, + ENTINDEX(m_pNearestEnemySentry.get())) } // only attack if attack area is > 0 - ADD_UTILITY(BOT_UTIL_ATTACK_POINT,!CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEdict) && (m_fAttackPointTimeTime()) && + ADD_UTILITY(BOT_UTIL_ATTACK_POINT,!CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEdict) && (m_fAttackPointTimeTime()) && !((std::strncmp(szmapname, "koth_lakeside_event", 19) == 0 || std::strncmp(szmapname, "koth_viaduct_event", 18) == 0) && (CTeamFortress2Mod::isBossSummoned())) && ((m_iClass!=TF_CLASS_SPY)||!isDisguised()) && (m_iCurrentAttackArea>0) && (CTeamFortress2Mod::isMapType(TF_MAP_SD)||CTeamFortress2Mod::isMapType(TF_MAP_CART)|| CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE)|| (CTeamFortress2Mod::isMapType(TF_MAP_ARENA)&&CTeamFortress2Mod::isArenaPointOpen())|| + (CTeamFortress2Mod::isMapType(TF_MAP_SAXTON)&&CTeamFortress2Mod::isArenaPointOpen()) || (CTeamFortress2Mod::isMapType(TF_MAP_KOTH)&&CTeamFortress2Mod::isArenaPointOpen())|| - CTeamFortress2Mod::isMapType(TF_MAP_CP)||CTeamFortress2Mod::isMapType(TF_MAP_TC)),fGetFlagUtility); + CTeamFortress2Mod::isMapType(TF_MAP_CP)||std::strncmp(szmapname, "ctf_chouhen", 11) == 0||std::strncmp( + szmapname, "ctf_haarp", 9) == 0||std::strncmp(szmapname, "ctf_vector", 10) == 0||std::strncmp(szmapname, + "ctf_snowdrift", 13) == 0||CTeamFortress2Mod::isMapType(TF_MAP_CPPL)||CTeamFortress2Mod::isMapType( + TF_MAP_TC)), fGetFlagUtility) // only defend if defend area is > 0 // (!CTeamFortress2Mod::isAttackDefendMap()||(m_iTeam==TF2_TEAM_RED)) - ADD_UTILITY(BOT_UTIL_DEFEND_POINT, (m_iCurrentDefendArea>0) && + ADD_UTILITY(BOT_UTIL_DEFEND_POINT, (m_iCurrentDefendArea>0) && (iClass != TF_CLASS_ENGINEER) && (CTeamFortress2Mod::isMapType(TF_MAP_MVM)||CTeamFortress2Mod::isMapType(TF_MAP_SD)||CTeamFortress2Mod::isMapType(TF_MAP_CART)|| - CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE)||CTeamFortress2Mod::isMapType(TF_MAP_ARENA)|| - CTeamFortress2Mod::isMapType(TF_MAP_KOTH)||CTeamFortress2Mod::isMapType(TF_MAP_CP)|| - CTeamFortress2Mod::isMapType(TF_MAP_TC))&&m_iClass!=TF_CLASS_SCOUT,fDefendFlagUtility); + CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE)||CTeamFortress2Mod::isMapType(TF_MAP_ARENA)||CTeamFortress2Mod::isMapType(TF_MAP_SAXTON) || + CTeamFortress2Mod::isMapType(TF_MAP_KOTH)||CTeamFortress2Mod::isMapType(TF_MAP_CP)|| CTeamFortress2Mod::isMapType(TF_MAP_CPPL)|| + CTeamFortress2Mod::isMapType(TF_MAP_TC))&&m_iClass!=TF_CLASS_SCOUT,fDefendFlagUtility) ADD_UTILITY(BOT_UTIL_MEDIC_HEAL,(m_iClass == TF_CLASS_MEDIC) && (pMedigun!= NULL) && pBWMediGun && pBWMediGun->hasWeapon() && !hasFlag() && m_pHeal && - CBotGlobals::entityIsAlive(m_pHeal) && (getHealFactor(m_pHeal)>0),0.98f); + CBotGlobals::entityIsAlive(m_pHeal) && (getHealFactor(m_pHeal)>0),0.98f) ADD_UTILITY(BOT_UTIL_MEDIC_HEAL_LAST,(m_iClass == TF_CLASS_MEDIC) && (pMedigun!= NULL) && pBWMediGun && pBWMediGun->hasWeapon() && !hasFlag() && m_pLastHeal && - CBotGlobals::entityIsAlive(m_pLastHeal) && (getHealFactor(m_pLastHeal)>0),0.99f); + CBotGlobals::entityIsAlive(m_pLastHeal) && (getHealFactor(m_pLastHeal)>0),0.99f) ADD_UTILITY(BOT_UTIL_HIDE_FROM_ENEMY,!CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEdict) && (m_pEnemy.get()!=NULL) && hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && !hasFlag() && !CTeamFortress2Mod::isFlagCarrier(m_pEnemy) && (((m_iClass == TF_CLASS_SPY)&&(!isDisguised()&&!isCloaked()))||(((m_iClass == TF_CLASS_MEDIC) && (pMedigun!= NULL) && !m_pHeal) || - CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEnemy))),1.0f); + CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEnemy))),1.0f) - ADD_UTILITY(BOT_UTIL_HIDE_FROM_ENEMY,(m_pEnemy.get()!=NULL) && hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && (CTeamFortress2Mod::isLosingTeam(m_iTeam)||((m_iClass == TF_CLASS_ENGINEER) && m_bIsCarryingObj)),1.0f); + ADD_UTILITY(BOT_UTIL_HIDE_FROM_ENEMY,(m_pEnemy.get()!=NULL) && hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && (CTeamFortress2Mod::isLosingTeam(m_iTeam)||((m_iClass == TF_CLASS_ENGINEER) && m_bIsCarryingObj)),1.0f) ADD_UTILITY(BOT_UTIL_MEDIC_FINDPLAYER,(m_iClass == TF_CLASS_MEDIC) && !m_pHeal && m_pLastCalledMedic && (pMedigun!= NULL) && pBWMediGun && pBWMediGun->hasWeapon() && ((m_fLastCalledMedicTime+30.0f)>engine->Time()) && ( (numplayersonteam>1) && - (numplayersonteam>CTeamFortress2Mod::numClassOnTeam(iTeam,getClass())) ),0.95f); + (numplayersonteam>CTeamFortress2Mod::numClassOnTeam(iTeam,getClass())) ),0.95f) ADD_UTILITY(BOT_UTIL_MEDIC_FINDPLAYER_AT_SPAWN,(m_iClass == TF_CLASS_MEDIC) && !m_pHeal && !m_pLastCalledMedic && (pMedigun!= NULL) && pBWMediGun && pBWMediGun->hasWeapon() && m_bEntranceVectorValid && (numplayersonteam>1) && - ((!CTeamFortress2Mod::isAttackDefendMap() && !CTeamFortress2Mod::hasRoundStarted()) || (numplayersonteam_alive < numplayersonteam)),0.94f); + ((!CTeamFortress2Mod::isAttackDefendMap() && !CTeamFortress2Mod::hasRoundStarted()) || (numplayersonteam_alive < numplayersonteam)),0.94f) if ( (m_iClass==TF_CLASS_DEMOMAN) && !hasEnemy() && !CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEdict) ) { @@ -4978,15 +4994,15 @@ void CBotTF2 :: getTasks ( unsigned int iIgnore ) if ( pPipe && pPipe->hasWeapon() && !pPipe->outOfAmmo(this) && ( m_iTrapType != TF_TRAP_TYPE_ENEMY ) ) { - ADD_UTILITY_WEAPON(BOT_UTIL_PIPE_LAST_ENEMY,(m_pLastEnemy!=NULL) && (distanceFrom(m_pLastEnemy) > (BLAST_RADIUS)),0.8f,pPipe); - ADD_UTILITY_WEAPON(BOT_UTIL_PIPE_NEAREST_SENTRY,(m_pNearestEnemySentry!=NULL) && (distanceFrom(m_pNearestEnemySentry) > (BLAST_RADIUS)),0.81f,pPipe); - ADD_UTILITY_WEAPON(BOT_UTIL_PIPE_LAST_ENEMY_SENTRY,(m_pLastEnemySentry!=NULL) && (distanceFrom(m_pLastEnemySentry) > (BLAST_RADIUS)),0.82f,pPipe); + ADD_UTILITY_WEAPON(BOT_UTIL_PIPE_LAST_ENEMY,(m_pLastEnemy!=NULL) && (distanceFrom(m_pLastEnemy) > (BLAST_RADIUS)),0.8f,pPipe) + ADD_UTILITY_WEAPON(BOT_UTIL_PIPE_NEAREST_SENTRY,(m_pNearestEnemySentry!=NULL) && (distanceFrom(m_pNearestEnemySentry) > (BLAST_RADIUS)),0.81f,pPipe) + ADD_UTILITY_WEAPON(BOT_UTIL_PIPE_LAST_ENEMY_SENTRY,(m_pLastEnemySentry!=NULL) && (distanceFrom(m_pLastEnemySentry) > (BLAST_RADIUS)),0.82f,pPipe) } else if ( pGren && pGren->hasWeapon() && !pGren->outOfAmmo(this) ) { - ADD_UTILITY_WEAPON(BOT_UTIL_SPAM_LAST_ENEMY,(m_pLastEnemy!=NULL) && (distanceFrom(m_pLastEnemy) > (BLAST_RADIUS)),0.78f,pGren); - ADD_UTILITY_WEAPON(BOT_UTIL_SPAM_NEAREST_SENTRY,(m_pNearestEnemySentry!=NULL) && (distanceFrom(m_pNearestEnemySentry) > (BLAST_RADIUS)),0.79f,pGren); - ADD_UTILITY_WEAPON(BOT_UTIL_SPAM_LAST_ENEMY_SENTRY,(m_pLastEnemySentry!=NULL) && (distanceFrom(m_pLastEnemySentry) > (BLAST_RADIUS)),0.80f,pGren); + ADD_UTILITY_WEAPON(BOT_UTIL_SPAM_LAST_ENEMY,(m_pLastEnemy!=NULL) && (distanceFrom(m_pLastEnemy) > (BLAST_RADIUS)),0.78f,pGren) + ADD_UTILITY_WEAPON(BOT_UTIL_SPAM_NEAREST_SENTRY,(m_pNearestEnemySentry!=NULL) && (distanceFrom(m_pNearestEnemySentry) > (BLAST_RADIUS)),0.79f,pGren) + ADD_UTILITY_WEAPON(BOT_UTIL_SPAM_LAST_ENEMY_SENTRY,(m_pLastEnemySentry!=NULL) && (distanceFrom(m_pLastEnemySentry) > (BLAST_RADIUS)),0.80f,pGren) } } @@ -4995,45 +5011,45 @@ void CBotTF2 :: getTasks ( unsigned int iIgnore ) ADD_UTILITY(BOT_UTIL_BACKSTAB,!hasFlag() && (!m_pNearestEnemySentry || (CTeamFortress2Mod::isSentrySapped(m_pNearestEnemySentry))) && (m_fBackstabTimeTime()) && (m_iClass==TF_CLASS_SPY) && ((m_pEnemy&& CBotGlobals::isAlivePlayer(m_pEnemy))|| (m_pLastEnemy&& CBotGlobals::isAlivePlayer(m_pLastEnemy))), - fGetFlagUtility+(getHealthPercent()/10)); + fGetFlagUtility+(getHealthPercent()/10)) ADD_UTILITY(BOT_UTIL_SAP_ENEMY_SENTRY, m_pEnemy && CTeamFortress2Mod::isSentry(m_pEnemy,CTeamFortress2Mod::getEnemyTeam(iTeam)) && !CTeamFortress2Mod::isSentrySapped(m_pEnemy), - fGetFlagUtility+(getHealthPercent()/5)); + fGetFlagUtility+(getHealthPercent()/5)) ADD_UTILITY(BOT_UTIL_SAP_NEAREST_SENTRY,m_pNearestEnemySentry && !CTeamFortress2Mod::isSentrySapped(m_pNearestEnemySentry), - fGetFlagUtility+(getHealthPercent()/5)); + fGetFlagUtility+(getHealthPercent()/5)) ADD_UTILITY(BOT_UTIL_SAP_LASTENEMY_SENTRY, - m_pLastEnemy && CTeamFortress2Mod::isSentry(m_pLastEnemy,CTeamFortress2Mod::getEnemyTeam(iTeam)) && !CTeamFortress2Mod::isSentrySapped(m_pLastEnemy),fGetFlagUtility+(getHealthPercent()/5)); + m_pLastEnemy && CTeamFortress2Mod::isSentry(m_pLastEnemy,CTeamFortress2Mod::getEnemyTeam(iTeam)) && !CTeamFortress2Mod::isSentrySapped(m_pLastEnemy),fGetFlagUtility+(getHealthPercent()/5)) ADD_UTILITY(BOT_UTIL_SAP_LASTENEMY_SENTRY, - m_pLastEnemySentry.get()!=NULL,fGetFlagUtility+(getHealthPercent()/5)); + m_pLastEnemySentry.get()!=NULL,fGetFlagUtility+(getHealthPercent()/5)) //////////////// // sap tele ADD_UTILITY(BOT_UTIL_SAP_ENEMY_TELE, m_pEnemy && CTeamFortress2Mod::isTeleporter(m_pEnemy,CTeamFortress2Mod::getEnemyTeam(iTeam)) && !CTeamFortress2Mod::isTeleporterSapped(m_pEnemy), - fGetFlagUtility+(getHealthPercent()/6)); + fGetFlagUtility+(getHealthPercent()/6)) ADD_UTILITY(BOT_UTIL_SAP_NEAREST_TELE,m_pNearestEnemyTeleporter && !CTeamFortress2Mod::isTeleporterSapped(m_pNearestEnemyTeleporter), - fGetFlagUtility+(getHealthPercent()/6)); + fGetFlagUtility+(getHealthPercent()/6)) ADD_UTILITY(BOT_UTIL_SAP_LASTENEMY_TELE, - m_pLastEnemy && CTeamFortress2Mod::isTeleporter(m_pLastEnemy,CTeamFortress2Mod::getEnemyTeam(iTeam)) && !CTeamFortress2Mod::isTeleporterSapped(m_pLastEnemy),fGetFlagUtility+(getHealthPercent()/6)); + m_pLastEnemy && CTeamFortress2Mod::isTeleporter(m_pLastEnemy,CTeamFortress2Mod::getEnemyTeam(iTeam)) && !CTeamFortress2Mod::isTeleporterSapped(m_pLastEnemy),fGetFlagUtility+(getHealthPercent()/6)) //////////////// // sap dispenser ADD_UTILITY(BOT_UTIL_SAP_ENEMY_DISP, m_pEnemy && CTeamFortress2Mod::isDispenser(m_pEnemy,CTeamFortress2Mod::getEnemyTeam(iTeam)) && !CTeamFortress2Mod::isDispenserSapped(m_pEnemy), - fGetFlagUtility+(getHealthPercent()/7)); + fGetFlagUtility+(getHealthPercent()/7)) ADD_UTILITY(BOT_UTIL_SAP_NEAREST_DISP,m_pNearestEnemyDisp && !CTeamFortress2Mod::isDispenserSapped(m_pNearestEnemyDisp), - fGetFlagUtility+(getHealthPercent()/7)); + fGetFlagUtility+(getHealthPercent()/7)) ADD_UTILITY(BOT_UTIL_SAP_LASTENEMY_DISP, - m_pLastEnemy && CTeamFortress2Mod::isDispenser(m_pLastEnemy,CTeamFortress2Mod::getEnemyTeam(iTeam)) && !CTeamFortress2Mod::isDispenserSapped(m_pLastEnemy),fGetFlagUtility+(getHealthPercent()/7)); + m_pLastEnemy && CTeamFortress2Mod::isDispenser(m_pLastEnemy,CTeamFortress2Mod::getEnemyTeam(iTeam)) && !CTeamFortress2Mod::isDispenserSapped(m_pLastEnemy),fGetFlagUtility+(getHealthPercent()/7)) } //fGetFlagUtility = 0.2+randomFloat(0.0f,0.2f); @@ -5042,60 +5058,125 @@ void CBotTF2 :: getTasks ( unsigned int iIgnore ) { if ( iTeam == TF2_TEAM_BLUE ) { - ADD_UTILITY(BOT_UTIL_DEFEND_PAYLOAD_BOMB,((m_iClass!=TF_CLASS_SPY)||!isDisguised()) && (m_pDefendPayloadBomb!=NULL),fDefendFlagUtility+randomFloat(-0.1,0.2)); - ADD_UTILITY(BOT_UTIL_PUSH_PAYLOAD_BOMB,((m_iClass!=TF_CLASS_SPY)||!isDisguised()) && (m_pPushPayloadBomb!=NULL),fGetFlagUtility+randomFloat(-0.1,0.2)); + ADD_UTILITY(BOT_UTIL_DEFEND_PAYLOAD_BOMB, + ((m_iClass!=TF_CLASS_SPY)||!isDisguised()) && (m_pDefendPayloadBomb!=NULL), + fDefendFlagUtility+randomFloat(-0.1f,0.2f)) + ADD_UTILITY(BOT_UTIL_PUSH_PAYLOAD_BOMB, + ((m_iClass!=TF_CLASS_SPY)||!isDisguised()) && (m_pPushPayloadBomb!=NULL), + fGetFlagUtility+randomFloat(-0.1f,0.2f)) } - else + else if (iTeam == TF2_TEAM_RED) { - ADD_UTILITY(BOT_UTIL_DEFEND_PAYLOAD_BOMB,((m_iClass!=TF_CLASS_SPY)||!isDisguised()) && (m_pDefendPayloadBomb!=NULL),fDefendFlagUtility+randomFloat(-0.1,0.2)); - ADD_UTILITY(BOT_UTIL_PUSH_PAYLOAD_BOMB,((m_iClass!=TF_CLASS_SPY)||!isDisguised()) && (m_pPushPayloadBomb!=NULL),fGetFlagUtility+randomFloat(-0.1,0.2)); + ADD_UTILITY(BOT_UTIL_DEFEND_PAYLOAD_BOMB, + ((m_iClass!=TF_CLASS_SPY)||!isDisguised()) && (m_pDefendPayloadBomb!=NULL), + fDefendFlagUtility+randomFloat(-0.1f,0.2f)) + ADD_UTILITY(BOT_UTIL_PUSH_PAYLOAD_BOMB, + ((m_iClass!=TF_CLASS_SPY)||!isDisguised()) && (m_pPushPayloadBomb!=NULL), + fGetFlagUtility+randomFloat(-0.1f,0.2f)) } } - else if ( CTeamFortress2Mod::isMapType(TF_MAP_CART) ) + else if ( CTeamFortress2Mod::isMapType(TF_MAP_CART) || CTeamFortress2Mod::isMapType(TF_MAP_CPPL) ) { if ( iTeam == TF2_TEAM_BLUE ) { ADD_UTILITY(BOT_UTIL_PUSH_PAYLOAD_BOMB,((m_iClass!=TF_CLASS_SPY)||!isDisguised()) && (m_pPushPayloadBomb!=NULL), - fGetFlagUtility+ (hasSomeConditions(CONDITION_PUSH)?0.25f:randomFloat(-0.1f,0.2f))); + fGetFlagUtility+ (hasSomeConditions(CONDITION_PUSH)?0.25f:randomFloat(-0.1f,0.2f))) // Goto Payload bomb } - else + else if (iTeam == TF2_TEAM_RED) { // Defend Payload bomb ADD_UTILITY(BOT_UTIL_DEFEND_PAYLOAD_BOMB, ((m_iClass!=TF_CLASS_SPY)||!isDisguised()) && (m_pDefendPayloadBomb!=NULL),fDefendFlagUtility+ - (hasSomeConditions(CONDITION_PUSH)?0.25f:randomFloat(-0.1f,0.2f))); + (hasSomeConditions(CONDITION_PUSH)?0.25f:randomFloat(-0.1f,0.2f))) } } - - + else if (std::strncmp(szmapname, "pl_embargo", 10) == 0) + { + if (iTeam == TF2_TEAM_BLUE) + { + ADD_UTILITY(BOT_UTIL_PUSH_PAYLOAD_BOMB, ((m_iClass != TF_CLASS_SPY) || !isDisguised()) && (m_pPushPayloadBomb != NULL), + fGetFlagUtility + (hasSomeConditions(CONDITION_PUSH))) + // Goto Payload bomb + } + else if (iTeam == TF2_TEAM_RED) + { + // Defend Payload bomb + ADD_UTILITY(BOT_UTIL_DEFEND_PAYLOAD_BOMB, + ((m_iClass != TF_CLASS_SPY) || !isDisguised()) && (m_pDefendPayloadBomb != NULL), fDefendFlagUtility + + (hasSomeConditions(CONDITION_PUSH) ? 0.25f : randomFloat(-0.1f, 0.2f))) + } + } + /*if (std::strncmp(szmapname, "tow_", 4) == 0) + { + if (iTeam == TF2_TEAM_BLUE) + { + ADD_UTILITY(BOT_UTIL_PUSH_PAYLOAD_BOMB, + ((m_iClass != TF_CLASS_SPY) || !isDisguised()) && (m_pPushPayloadBomb != NULL), + fGetFlagUtility + randomFloat(-0.1f, 0.2f)) + } + else if (iTeam == TF2_TEAM_RED) + { + ADD_UTILITY(BOT_UTIL_PUSH_PAYLOAD_BOMB, + ((m_iClass != TF_CLASS_SPY) || !isDisguised()) && (m_pPushPayloadBomb != NULL), + fGetFlagUtility + randomFloat(-0.1f, 0.2f)) + } + }*/ + else if ((std::strncmp(szmapname, "sd_offload", 10) == 0) || (std::strncmp(szmapname, "ctf_system", 10) == 0)) + { + if ((iTeam == TF2_TEAM_BLUE || iTeam == TF2_TEAM_RED) && m_bHasFlag) + { + ADD_UTILITY(BOT_UTIL_PUSH_PAYLOAD_BOMB, (m_pPushPayloadBomb != NULL), + fGetFlagUtility) + // Goto Payload bomb + } + } + else if ((std::strncmp(szmapname, "koth_namicott", 13) == 0)) + { + if ((iTeam == TF2_TEAM_BLUE || iTeam == TF2_TEAM_RED)) + { + ADD_UTILITY(BOT_UTIL_PUSH_PAYLOAD_BOMB, (m_pPushPayloadBomb != NULL), + fGetFlagUtility) + // Goto Payload bomb + } + } + else if (std::strncmp(szmapname, "kotc_", 5) == 0) + { + if ((iTeam == TF2_TEAM_BLUE || iTeam == TF2_TEAM_RED)) + { + ADD_UTILITY(BOT_UTIL_PUSH_PAYLOAD_BOMB, (m_pPushPayloadBomb != NULL), + fGetFlagUtility) + // Goto Payload bomb + } + } + if ((m_iClass == TF_CLASS_DEMOMAN) && (m_iTrapType == TF_TRAP_TYPE_NONE) && canDeployStickies()) { ADD_UTILITY(BOT_UTIL_DEMO_STICKYTRAP_LASTENEMY, m_pLastEnemy && (m_iTrapType == TF_TRAP_TYPE_NONE), - randomFloat(min(fDefendFlagUtility, fGetFlagUtility), max(fDefendFlagUtility, fGetFlagUtility))); + randomFloat(std::min(fDefendFlagUtility, fGetFlagUtility), std::max(fDefendFlagUtility, fGetFlagUtility))) ADD_UTILITY(BOT_UTIL_DEMO_STICKYTRAP_FLAG, CTeamFortress2Mod::isMapType(TF_MAP_CTF) && !bHasFlag && (!m_fLastKnownTeamFlagTime || (m_fLastKnownTeamFlagTime < engine->Time())), - fDefendFlagUtility + 0.3f); + fDefendFlagUtility + 0.3f) ADD_UTILITY(BOT_UTIL_DEMO_STICKYTRAP_FLAG_LASTKNOWN, - (CTeamFortress2Mod::isMapType(TF_MAP_MVM) || CTeamFortress2Mod::isMapType(TF_MAP_CTF) || (CTeamFortress2Mod::isMapType(TF_MAP_SD) && + (CTeamFortress2Mod::isMapType(TF_MAP_MVM) || CTeamFortress2Mod::isMapType(TF_MAP_CTF) || CTeamFortress2Mod::isMapType(TF_MAP_CP) || CTeamFortress2Mod::isMapType(TF_MAP_TC) || CTeamFortress2Mod::isMapType(TF_MAP_RD) || (CTeamFortress2Mod::isMapType(TF_MAP_SD) && (CTeamFortress2Mod::getFlagCarrierTeam() == CTeamFortress2Mod::getEnemyTeam(iTeam)))) && !bHasFlag && - (m_fLastKnownTeamFlagTime && (m_fLastKnownTeamFlagTime > engine->Time())), fDefendFlagUtility + 0.4f); + (m_fLastKnownTeamFlagTime && (m_fLastKnownTeamFlagTime > engine->Time())), fDefendFlagUtility + 0.4f) ADD_UTILITY(BOT_UTIL_DEMO_STICKYTRAP_POINT, (iTeam == TF2_TEAM_RED) && (m_iCurrentDefendArea>0) && (CTeamFortress2Mod::isMapType(TF_MAP_MVM) || CTeamFortress2Mod::isMapType(TF_MAP_SD) || CTeamFortress2Mod::isMapType(TF_MAP_CART) || - CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE) || CTeamFortress2Mod::isMapType(TF_MAP_ARENA) || - CTeamFortress2Mod::isMapType(TF_MAP_KOTH) || CTeamFortress2Mod::isMapType(TF_MAP_CP) || + CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE) || CTeamFortress2Mod::isMapType(TF_MAP_ARENA) || CTeamFortress2Mod::isMapType(TF_MAP_SAXTON) || + CTeamFortress2Mod::isMapType(TF_MAP_KOTH) || CTeamFortress2Mod::isMapType(TF_MAP_CP) || CTeamFortress2Mod::isMapType(TF_MAP_CPPL) || CTeamFortress2Mod::isMapType(TF_MAP_TC)), - fDefendFlagUtility + 0.4f); + fDefendFlagUtility + 0.4f) ADD_UTILITY(BOT_UTIL_DEMO_STICKYTRAP_PL, - (CTeamFortress2Mod::isMapType(TF_MAP_CART) || CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE)) && + (CTeamFortress2Mod::isMapType(TF_MAP_CART) || CTeamFortress2Mod::isMapType(TF_MAP_CPPL) || CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE)) && (m_pDefendPayloadBomb != NULL), - fDefendFlagUtility + 0.4f); + fDefendFlagUtility + 0.4f) } //if ( !CTeamFortress2Mod::hasRoundStarted() && (iTeam == TF_TEAM_BLUE) ) //{ @@ -5106,7 +5187,7 @@ void CBotTF2 :: getTasks ( unsigned int iIgnore ) if ( getClass() == TF_CLASS_MEDIC ) fMessUtil -= randomFloat(0.0f,0.3f); - ADD_UTILITY(BOT_UTIL_MESSAROUND,(getHealthPercent()>0.75f) && ((iTeam==TF2_TEAM_BLUE)||(!CTeamFortress2Mod::isAttackDefendMap())) && !CTeamFortress2Mod::hasRoundStarted(),fMessUtil); + ADD_UTILITY(BOT_UTIL_MESSAROUND,(getHealthPercent()>0.75f) && ((iTeam==TF2_TEAM_BLUE)||(!CTeamFortress2Mod::isAttackDefendMap())) && !CTeamFortress2Mod::hasRoundStarted() && !CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE),fMessUtil) } //} @@ -5115,7 +5196,7 @@ void CBotTF2 :: getTasks ( unsigned int iIgnore ) ////////////////////////////////////////////////////////// utils.execute(); - while ( (next = utils.nextBest()) != NULL ) + while ( (next = utils.nextBest()) != nullptr) { if ( !m_pSchedules->isEmpty() && bCheckCurrent ) { @@ -5141,8 +5222,10 @@ void CBotTF2 :: getTasks ( unsigned int iIgnore ) do { - CClients::clientDebugMsg(this,BOT_DEBUG_UTIL,"%s = %0.3f",g_szUtils[next->getId()],next->getUtility(),this); - }while ( (++i<10) && ((next = utils.nextBest()) != NULL) ); + CClients::clientDebugMsg(this, BOT_DEBUG_UTIL, "%s = %0.3f, this = %p", g_szUtils[next->getId()], next->getUtility(), this); + } + + while ( (++i<10) && ((next = utils.nextBest()) != nullptr) ); CClients::clientDebugMsg(this,BOT_DEBUG_UTIL,"----END---- getTasks(%s) ----END----",m_szBotName); } @@ -5158,7 +5241,7 @@ void CBotTF2 :: getTasks ( unsigned int iIgnore ) bool CBotTF2 :: canDeployStickies () { - if ( m_pEnemy.get() != NULL ) + if ( m_pEnemy.get() != nullptr) { if ( CBotGlobals::isAlivePlayer(m_pEnemy) ) { @@ -5168,9 +5251,7 @@ bool CBotTF2 :: canDeployStickies () } // enough ammo??? - CBotWeapon *pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(TF2_WEAPON_PIPEBOMBS)); - - if (pWeapon) + if (const CBotWeapon *pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(TF2_WEAPON_PIPEBOMBS))) { return (pWeapon->hasWeapon() && pWeapon->getAmmo(this) >= 6); } @@ -5178,14 +5259,15 @@ bool CBotTF2 :: canDeployStickies () return false; } -#define STICKY_INIT 0 -#define STICKY_SELECTWEAP 1 -#define STICKY_RELOAD 2 -#define STICKY_FACEVECTOR 3 -#define IN_RANGE(x,low,high) ((x>low)&&(x(low))&&((x)<(high))) // returns true when finished -bool CBotTF2::deployStickies(eDemoTrapType type, Vector vStand, Vector vLocation, Vector vSpread, Vector *vPoint, int *iState, int *iStickyNum, bool *bFail, float *fTime, int wptindex) +bool CBotTF2::deployStickies(const eDemoTrapType type, const Vector& vStand, const Vector& vLocation, const Vector& vSpread, Vector *vPoint, int *iState, int *iStickyNum, bool *bFail, float *fTime, const int wptindex) { CBotWeapon *pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(TF2_WEAPON_PIPEBOMBS)); int iPipesLeft = 0; @@ -5199,10 +5281,10 @@ bool CBotTF2::deployStickies(eDemoTrapType type, Vector vStand, Vector vLocation if (*iState == STICKY_INIT) { - if (iPipesLeft < 6) + if (iPipesLeft < 8) *iStickyNum = iPipesLeft; else - *iStickyNum = 6; + *iStickyNum = 8; *iState = 1; } @@ -5253,10 +5335,10 @@ bool CBotTF2::deployStickies(eDemoTrapType type, Vector vStand, Vector vLocation return false; } -void CBotTF2::detonateStickies(bool isJumping) +void CBotTF2::detonateStickies(const bool isJumping) { // don't try to blow myself up unless i'm jumping - if ( isJumping || (distanceFrom(m_vStickyLocation) > (BLAST_RADIUS/2)) ) + if ( isJumping || (distanceFrom(m_vStickyLocation) > (BLAST_RADIUS/2)) || CTeamFortress2Mod::isMapType(TF_MAP_GG)) { secondaryAttack(); m_iTrapType = TF_TRAP_TYPE_NONE; @@ -5266,7 +5348,7 @@ void CBotTF2::detonateStickies(bool isJumping) bool CBotTF2::lookAfterBuildings ( float *fTime ) { - CBotWeapon *pWeapon = getCurrentWeapon(); + const CBotWeapon *pWeapon = getCurrentWeapon(); wantToListen(false); @@ -5274,7 +5356,7 @@ bool CBotTF2::lookAfterBuildings ( float *fTime ) if ( !pWeapon ) return false; - else if ( pWeapon->getID() != TF2_WEAPON_WRENCH ) + if ( pWeapon->getID() != TF2_WEAPON_WRENCH ) { if ( !select_CWeapon(CWeapons::getWeapon(TF2_WEAPON_WRENCH)) ) return false; @@ -5294,7 +5376,6 @@ bool CBotTF2::lookAfterBuildings ( float *fTime ) stopMoving(); duck(true); // crouch too - } lookAtEdict(m_pSentryGun); @@ -5337,40 +5418,42 @@ bool CBotTF2::lookAfterBuildings ( float *fTime ) bool CBotTF2 :: select_CWeapon ( CWeapon *pWeapon ) { - char cmd[128]; - CBotWeapon *pBotWeapon; + const CBotWeapon* pBotWeapon = m_pWeapons->getWeapon(pWeapon); - pBotWeapon = m_pWeapons->getWeapon(pWeapon); + const string_t mapname = gpGlobals->mapname; + + const char* szmapname = mapname.ToCStr(); if ( pBotWeapon && !pBotWeapon->hasWeapon() ) return false; if ( pBotWeapon && !pBotWeapon->isMelee() && pBotWeapon->canAttack() && pBotWeapon->outOfAmmo(this) ) return false; - sprintf(cmd,"use %s",pWeapon->getWeaponName()); + if ( const edict_t* pDesiredWeapon = CWeapons::findWeapon(m_pEdict, pWeapon->getWeaponName()) ) + m_iSelectWeapon = ENTINDEX(pDesiredWeapon); - helpers->ClientCommand(m_pEdict,cmd); + /*else if (std::strncmp(szmapname, "dm_hydro_v20", 12) == 0 || std::strncmp(szmapname, "dm_powerdown_v20", 16) == 0 || std::strncmp(szmapname, "dm_forgecall_v20", 16) == 0 || std::strncmp(szmapname, "dm_poolparty_v20", 16) == 0 || std::strncmp(szmapname, "dm_badworks_v20", 15) == 0 || std::strncmp(szmapname, "dm_razorpoint_v20", 17) == 0 || std::strncmp(szmapname, "dm_deadlock_v20", 15) == 0) + { + if (pWeapon->getID() == TF2_SLOT_SCNDR || TF2_SLOT_MELEE || TF2_SLOT_PDA || TF2_SLOT_PDA2 || TF2_SLOT_HAT || TF2_SLOT_MISC || TF2_SLOT_ACTION || TF2_SLOT_MAX) + return true; + }*/ return true; } bool CBotTF2 :: selectBotWeapon ( CBotWeapon *pBotWeapon ) { - CWeapon *pSelect = pBotWeapon->getWeaponInfo(); - - if ( pSelect ) + if ( const CWeapon *pSelect = pBotWeapon->getWeaponInfo() ) { - //int id = pSelect->getWeaponIndex(); - char cmd[128]; + if ( const edict_t* pDesiredWeapon = CWeapons::findWeapon(m_pEdict, pSelect->getWeaponName()) ) + { + m_iSelectWeapon = ENTINDEX(pDesiredWeapon); + return true; + } - sprintf(cmd,"use %s",pSelect->getWeaponName()); - - helpers->ClientCommand(m_pEdict,cmd); - - return true; + return false; } - else - failWeaponSelect(); + failWeaponSelect(); return false; } @@ -5381,11 +5464,14 @@ bool CBotTF2 :: selectBotWeapon ( CBotWeapon *pBotWeapon ) bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *pWaypointResupply, CWaypoint *pWaypointHealth, CWaypoint *pWaypointAmmo ) { static CWaypoint *pWaypoint; - extern ConVar rcbot_move_dist; int id; id = util->getId(); - pWaypoint = NULL; + pWaypoint = nullptr; + + const string_t mapname = gpGlobals->mapname; + + const char* szmapname = mapname.ToCStr(); switch ( id ) { @@ -5422,7 +5508,7 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p return true; } - if ( m_pDefendPayloadBomb.get() != NULL ) + if ( m_pDefendPayloadBomb.get() != nullptr) { m_pSchedules->add(new CBotTF2DefendPayloadBombSched(m_pDefendPayloadBomb)); removeCondition(CONDITION_PUSH); @@ -5432,7 +5518,7 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p break; case BOT_UTIL_PUSH_PAYLOAD_BOMB: { - if ( m_pPushPayloadBomb.get() != NULL ) + if ( m_pPushPayloadBomb.get() != nullptr) { m_pSchedules->add(new CBotTF2PushPayloadBombSched(m_pPushPayloadBomb)); removeCondition(CONDITION_PUSH); @@ -5442,7 +5528,7 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p break; case BOT_UTIL_ENGI_LOOK_AFTER_SENTRY: { - if ( m_pSentryGun.get() != NULL ) + if ( m_pSentryGun.get() != nullptr) { m_pSchedules->add(new CBotTFEngiLookAfterSentry(m_pSentryGun)); return true; @@ -5452,7 +5538,7 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p case BOT_UTIL_DEFEND_FLAG: // use last known flag position { - CWaypoint *pWaypoint = NULL; + //CWaypoint *pWaypoint = nullptr; if ( CTeamFortress2Mod::isMapType(TF_MAP_MVM) ) { @@ -5466,7 +5552,7 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p }*/ } - if ( pWaypoint == NULL ) + if ( pWaypoint == nullptr) pWaypoint = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_DEFEND,getTeam(),0,false,this,true); //if ( pWaypoint && randomInt(0,1) ) @@ -5493,7 +5579,7 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p removeCondition(CONDITION_PUSH); return true; } - break; + //break; case BOT_UTIL_ATTACK_POINT: /*pWaypoint = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_DEFEND,getTeam(),m_iCurrentAttackArea,true); @@ -5508,19 +5594,19 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p if ( pWaypoint && pWaypoint->checkReachable() ) { - CWaypoint *pRoute = NULL; Vector vRoute = Vector(0,0,0); bool bUseRoute = false; - int iRouteWpt = -1; bool bNest = false; if ( (m_fUseRouteTime < engine->Time()) ) { - // find random route + CWaypoint *pRoute = nullptr; + // find random route pRoute = CWaypoints::randomRouteWaypoint(this,getOrigin(),pWaypoint->getOrigin(),getTeam(),m_iCurrentAttackArea); if ( pRoute ) { + int iRouteWpt = -1; bUseRoute = true; vRoute = pRoute->getOrigin(); m_fUseRouteTime = engine->Time() + randomFloat(30.0f,60.0f); @@ -5530,36 +5616,41 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p } } - m_pSchedules->add(new CBotAttackPointSched(pWaypoint->getOrigin(),pWaypoint->getRadius(),pWaypoint->getArea(),bUseRoute,vRoute, bNest, m_pLastEnemySentry.get())); + m_pSchedules->add(new CBotAttackPointSched(pWaypoint->getOrigin(), pWaypoint->getRadius(), + pWaypoint->getArea(), bUseRoute, vRoute, bNest, + m_pLastEnemySentry.get())); removeCondition(CONDITION_PUSH); return true; } + if ((std::strncmp(szmapname, "koth_lakeside_event", 19) == 0 || std::strncmp(szmapname, "koth_viaduct_event", 18) == 0) && (CTeamFortress2Mod::isBossSummoned())) + return false; break; case BOT_UTIL_DEFEND_POINT: { float fprob; - if ( (CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE) || CTeamFortress2Mod::isMapType(TF_MAP_CART)) ) + if ( (CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE) || CTeamFortress2Mod::isMapType(TF_MAP_CPPL) || CTeamFortress2Mod::isMapType(TF_MAP_CART) || (std::strncmp(szmapname, "sd_offload", 10) == 0) || (std::strncmp(szmapname, "koth_namicott", 13) == 0) || (std::strncmp(szmapname, "ctf_system", 10) == 0) || (std::strncmp(szmapname, "cp_helmsdeep_v2", 15) == 0)) ) { - if ( m_pDefendPayloadBomb !=NULL ) + if ( m_pDefendPayloadBomb != nullptr) { - static const float fSearchDist = 1500.0f; + static constexpr float fSearchDist = 1500.0f; Vector vPayloadBomb = CBotGlobals::entityOrigin(m_pDefendPayloadBomb); - CWaypoint *pCapturePoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(vPayloadBomb,fSearchDist,-1,false,false,true,NULL,false,0,true,false,Vector(0,0,0),CWaypointTypes::W_FL_CAPPOINT)); + CWaypoint* pCapturePoint = CWaypoints::getWaypoint( + CWaypointLocations::NearestWaypoint(vPayloadBomb, fSearchDist, -1, false, false, true, nullptr, + false, 0, true, false, Vector(0, 0, 0), + CWaypointTypes::W_FL_CAPPOINT)); if ( pCapturePoint ) { float fDistance = pCapturePoint->distanceFrom(vPayloadBomb); - if ( fDistance == 0 ) + if ( fDistance == 0.0f ) fprob = 1.0f; else fprob = 1.0f - (fDistance/fSearchDist); } else // no where near the capture point { - extern ConVar bot_defrate; - fprob = bot_defrate.GetFloat(); } } @@ -5586,12 +5677,10 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p // chance of going to point fprob = (fTime - (engine->Time() - CTeamFortress2Mod::m_ObjectiveResource.getLastCaptureTime(m_iCurrentDefendArea)))/fTime; - if ( fprob < rcbot_tf2_protect_cap_percent.GetFloat() ) - fprob = rcbot_tf2_protect_cap_percent.GetFloat(); + fprob = std::max(fprob, rcbot_tf2_protect_cap_percent.GetFloat()); } } - - + if ( CTeamFortress2Mod::isMapType(TF_MAP_MVM) && CTeamFortress2Mod::TF2_IsPlayerInvuln(m_pEdict) && hasEnemy() ) { // move towards enemy if invuln @@ -5601,7 +5690,7 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p else pWaypoint = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_CAPPOINT,0,m_iCurrentDefendArea,true,this); - if ( !pWaypoint->checkReachable() || (randomFloat(0.0,1.0f) > fprob) ) + if ( !pWaypoint->checkReachable() || (randomFloat(0.0f,1.0f) > fprob) ) { pWaypoint = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_DEFEND,getTeam(),m_iCurrentDefendArea,true,this,false); @@ -5625,10 +5714,12 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p newSched->addTask(path); newSched->addTask(spam); + + // Ensure newSched is deleted before function exits [APG]RoboCopCL] + delete newSched; return true; } - else - delete spam; + delete spam; } } @@ -5663,7 +5754,7 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p case BOT_UTIL_ENGI_DESTROY_ENTRANCE: // destroy and rebuild sentry elsewhere engineerBuild(ENGI_ENTRANCE,ENGI_DESTROY); case BOT_UTIL_BUILDTELENT: - pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(m_vTeleportEntrance,300,-1,true,false,true,NULL,false,getTeam(),true)); + pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(m_vTeleportEntrance,300.0f,-1,true,false,true, nullptr,false,getTeam(),true)); if ( pWaypoint ) { @@ -5712,22 +5803,22 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p if ( m_bTeleportExitVectorValid ) { - pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(m_vTeleportExit,150,-1,true,false,true,NULL,false,getTeam(),true,false,Vector(0,0,0),CWaypointTypes::W_FL_TELE_EXIT)); + pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(m_vTeleportExit,150.0f,-1,true,false,true, nullptr,false,getTeam(),true,false,Vector(0,0,0),CWaypointTypes::W_FL_TELE_EXIT)); if ( CWaypoints::getWaypointIndex(pWaypoint) == m_iLastFailTeleExitWpt ) { - pWaypoint = NULL; + pWaypoint = nullptr; m_bTeleportExitVectorValid = false; } // no use going back to this waypoint else if ( pWaypoint && (pWaypoint->getArea() > 0) && (pWaypoint->getArea() != m_iCurrentAttackArea) && (pWaypoint->getArea() != m_iCurrentDefendArea) ) { - pWaypoint = NULL; + pWaypoint = nullptr; m_bTeleportExitVectorValid = false; } } - if ( pWaypoint == NULL ) + if ( pWaypoint == nullptr) { if ( CTeamFortress2Mod::isAttackDefendMap() ) { @@ -5769,21 +5860,21 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p engineerBuild(ENGI_SENTRY,ENGI_DESTROY); case BOT_UTIL_BUILDSENTRY: - pWaypoint = NULL; + //pWaypoint = nullptr; // did someone destroy my sentry at the last sentry point? -- build it again if ( m_bSentryGunVectorValid ) { - pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(m_vSentryGun,150,m_iLastFailSentryWpt,true,false,true,NULL,false,getTeam(),true,false,Vector(0,0,0),CWaypointTypes::W_FL_SENTRY)); + pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(m_vSentryGun,150.0f,m_iLastFailSentryWpt,true,false,true, nullptr,false,getTeam(),true,false,Vector(0,0,0),CWaypointTypes::W_FL_SENTRY)); if ( pWaypoint && CTeamFortress2Mod::buildingNearby(m_iTeam,pWaypoint->getOrigin()) ) - pWaypoint = NULL; + pWaypoint = nullptr; // no use going back to this waypoint if ( pWaypoint && (pWaypoint->getArea() > 0) && (pWaypoint->getArea() != m_iCurrentAttackArea) && (pWaypoint->getArea() != m_iCurrentDefendArea) ) - pWaypoint = NULL; + pWaypoint = nullptr; } - if ( pWaypoint == NULL ) + if ( pWaypoint == nullptr) { if ( CTeamFortress2Mod::isMapType(TF_MAP_MVM) ) { @@ -5827,21 +5918,22 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p m_iSentryArea = pWaypoint->getArea(); return true; } - else - m_iLastFailSentryWpt = -1; + m_iLastFailSentryWpt = -1; break; case BOT_UTIL_BACKSTAB: - if ( m_pEnemy && CBotGlobals::isAlivePlayer(m_pEnemy) ) { - m_pSchedules->add(new CBotBackstabSched(m_pEnemy)); - return true; - } - else if ( m_pLastEnemy && CBotGlobals::isAlivePlayer(m_pLastEnemy) ) - { - m_pSchedules->add(new CBotBackstabSched(m_pLastEnemy)); - return true; + if ( m_pEnemy && CBotGlobals::isAlivePlayer(m_pEnemy) ) + { + m_pSchedules->add(new CBotBackstabSched(m_pEnemy)); + return true; + } + if ( m_pLastEnemy && CBotGlobals::isAlivePlayer(m_pLastEnemy) ) + { + m_pSchedules->add(new CBotBackstabSched(m_pLastEnemy)); + return true; + } } - + break; case BOT_UTIL_REMOVE_TMTELE_SAPPER: updateCondition(CONDITION_PARANOID); @@ -5863,34 +5955,33 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p m_pSchedules->add(new CBotRemoveSapperSched(m_pNearestAllySentry,ENGI_SENTRY)); return true; - break; + //break; case BOT_UTIL_REMOVE_TMDISP_SAPPER: updateCondition(CONDITION_PARANOID); m_pSchedules->add(new CBotRemoveSapperSched(m_pNearestDisp,ENGI_DISP)); return true; - break; + //break; case BOT_UTIL_ENGI_DESTROY_DISP: engineerBuild(ENGI_DISP,ENGI_DESTROY); case BOT_UTIL_BUILDDISP: - pWaypoint = NULL; + //pWaypoint = nullptr; if ( m_bDispenserVectorValid ) { - pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(m_vDispenser,150,-1,true,false,true,NULL,false,getTeam(),true,false,Vector(0,0,0),CWaypointTypes::W_FL_SENTRY)); + pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(m_vDispenser,150.0f,-1,true,false,true, nullptr,false,getTeam(),true,false,Vector(0,0,0),CWaypointTypes::W_FL_SENTRY)); - // no use going back to this waypoint if (pWaypoint && (pWaypoint->getArea() > 0) && (pWaypoint->getArea() != m_iCurrentAttackArea) && (pWaypoint->getArea() != m_iCurrentDefendArea)) { - pWaypoint = NULL; + pWaypoint = nullptr; m_bDispenserVectorValid = false; } - else if (pWaypoint == NULL) + else if (pWaypoint == nullptr) m_bDispenserVectorValid = false; } - if ((pWaypoint == NULL) && (m_pSentryGun.get() != NULL)) - pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(CBotGlobals::entityOrigin(m_pSentryGun), 150, -1, true, false, true, NULL, false, getTeam(), true)); + if ((pWaypoint == nullptr) && (m_pSentryGun.get() != nullptr)) + pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(CBotGlobals::entityOrigin(m_pSentryGun), 150.0f, -1, true, false, true, nullptr, false, getTeam(), true)); if ( pWaypoint ) { @@ -5911,12 +6002,10 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p // run at flank while shooting CFindPathTask *pHideGoalPoint = new CFindPathTask(); Vector vOrigin = CBotGlobals::entityOrigin(m_pEnemy); - pSchedule->addTask(new CFindGoodHideSpot(vOrigin)); pSchedule->addTask(pHideGoalPoint); pSchedule->addTask(new CBotNest()); - // no interrupts, should be a quick waypoint path anyway pHideGoalPoint->setNoInterruptions(); @@ -6024,7 +6113,7 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p { Vector vSentry = CBotGlobals::entityOrigin(m_pSentryGun); - CWaypoint *pWaypoint = NULL; + //CWaypoint *pWaypoint = nullptr; if ( CTeamFortress2Mod::isMapType(TF_MAP_MVM) ) { @@ -6072,7 +6161,6 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p } } - if ( pWaypoint && (pWaypoint->distanceFrom(vSentry) > rcbot_move_dist.GetFloat()) ) { updateCondition(CONDITION_COVERT); @@ -6119,10 +6207,10 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p if ( m_pSentryGun.get() && m_pDispenser.get() ) { Vector vDisp = CBotGlobals::entityOrigin(m_pDispenser); - CWaypoint *pWaypoint = NULL; + //CWaypoint *pWaypoint = nullptr; if ( m_pSentryGun ) - pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(CBotGlobals::entityOrigin(m_pSentryGun),150,-1,true,false,true,NULL,false,getTeam(),true)); + pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(CBotGlobals::entityOrigin(m_pSentryGun),150.0f,-1,true,false,true, nullptr,false,getTeam(),true)); else pWaypoint = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_SENTRY,getTeam(),0,false,this); @@ -6140,7 +6228,9 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p if ( m_pTeleEntrance.get() ) { Vector vTele = CBotGlobals::entityOrigin(m_pTeleEntrance); - CWaypoint *pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(m_vTeleportEntrance,512,-1,true,false,true,NULL,false,getTeam(),true)); + pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint( + m_vTeleportEntrance, 512.0f, -1, true, false, true, nullptr, false, + getTeam(), true)); if ( pWaypoint && ( pWaypoint->distanceFrom(vTele) > rcbot_move_dist.GetFloat() ) ) { @@ -6190,7 +6280,7 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p case BOT_UTIL_FIND_MEDIC_FOR_HEALTH: { Vector vLoc = m_pLastSeeMedic.getLocation(); - int iWpt = CWaypointLocations::NearestWaypoint(vLoc,400,-1,true,false,true,0,false,getTeam(),true); + int iWpt = CWaypointLocations::NearestWaypoint(vLoc,400.0f,-1,true,false,true,nullptr,false,getTeam(),true); if ( iWpt != -1 ) { CFindPathTask *findpath = new CFindPathTask(iWpt,LOOK_WAYPOINT); @@ -6224,17 +6314,14 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p case BOT_UTIL_DEMO_STICKYTRAP_FLAG_LASTKNOWN: case BOT_UTIL_DEMO_STICKYTRAP_POINT: case BOT_UTIL_DEMO_STICKYTRAP_PL: -// to do + //TODO: Add Demoman Stickybomb Skill? { - - Vector vStand; - Vector vPoint; - Vector vDemoStickyPoint; + //Vector vDemoStickyPoint; eDemoTrapType iDemoTrapType = TF_TRAP_TYPE_NONE; if ( id == BOT_UTIL_DEMO_STICKYTRAP_LASTENEMY ) { - pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(m_vLastSeeEnemy,400,-1,true,false,true,0,false,getTeam(),true)); + pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(m_vLastSeeEnemy,400.0f,-1,true,false,true,nullptr,false,getTeam(),true)); iDemoTrapType = TF_TRAP_TYPE_WPT; } else if ( id == BOT_UTIL_DEMO_STICKYTRAP_FLAG ) @@ -6244,7 +6331,7 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p } else if ( id == BOT_UTIL_DEMO_STICKYTRAP_FLAG_LASTKNOWN ) { - pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(m_vLastKnownTeamFlagPoint,400,-1,true,false,true,0,false,getTeam(),true)); + pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(m_vLastKnownTeamFlagPoint,400.0f,-1,true,false,true,nullptr,false,getTeam(),true)); iDemoTrapType = TF_TRAP_TYPE_FLAG; } else if ( id == BOT_UTIL_DEMO_STICKYTRAP_POINT ) @@ -6258,34 +6345,35 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p } else if ( id == BOT_UTIL_DEMO_STICKYTRAP_PL ) { - pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint( CBotGlobals::entityOrigin(m_pDefendPayloadBomb),400,-1,true,false,true,0,false,getTeam(),true)); + pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint( CBotGlobals::entityOrigin(m_pDefendPayloadBomb),400.0f,-1,true,false,true,nullptr,false,getTeam(),true)); iDemoTrapType = TF_TRAP_TYPE_PL; } if ( pWaypoint ) { - CWaypoint *pStand = NULL; + Vector vPoint; + CWaypoint *pStand = nullptr; CWaypoint *pTemp; float fDist = 9999.0f; float fClosest = 9999.0f; vPoint = pWaypoint->getOrigin(); - dataUnconstArray m_iVisibles; - dataUnconstArray m_iInvisibles; + WaypointList m_iVisibles; + WaypointList m_iInvisibles; - int iWptFrom = CWaypointLocations::NearestWaypoint(vPoint,2048.0,-1,true,true,true,NULL,false,0,false); + int iWptFrom = CWaypointLocations::NearestWaypoint(vPoint,2048.0f,-1,true,true,true, nullptr,false,0,false); //int m_iVisiblePoints[CWaypoints::MAX_WAYPOINTS]; // make searching quicker - CWaypointLocations::GetAllVisible(iWptFrom,iWptFrom,vPoint,vPoint,2048.0,&m_iVisibles,&m_iInvisibles); + CWaypointLocations::GetAllVisible(iWptFrom,iWptFrom,vPoint,vPoint,2048.0f,&m_iVisibles,&m_iInvisibles); - for ( int i = 0; i < m_iVisibles.Size(); i ++ ) + for (int m_iVisible : m_iVisibles) { - if ( m_iVisibles[i] == CWaypoints::getWaypointIndex(pWaypoint) ) + if (m_iVisible == CWaypoints::getWaypointIndex(pWaypoint)) continue; - pTemp = CWaypoints::getWaypoint(m_iVisibles[i]); + pTemp = CWaypoints::getWaypoint(m_iVisible); if ( pTemp->distanceFrom(pWaypoint) < 512 ) { @@ -6298,26 +6386,21 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p } } } - - m_iVisibles.Destroy(); - m_iInvisibles.Destroy(); if ( !pStand ) { - pStand = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(pWaypoint->getOrigin(),400,CWaypoints::getWaypointIndex(pWaypoint),true,false,true,0,false,getTeam(),true)); + pStand = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(pWaypoint->getOrigin(),400.0f,CWaypoints::getWaypointIndex(pWaypoint),true,false,true,nullptr,false,getTeam(),true)); } if ( pStand ) { + Vector vStand; vStand = pStand->getOrigin(); - if ( pWaypoint ) - { - m_pSchedules->add(new CBotTF2DemoPipeTrapSched(iDemoTrapType,vStand,vPoint,Vector(150,150,20),false,pWaypoint->getArea())); - return true; - } + // Proceed with the current logic [APG]RoboCop[CL] + m_pSchedules->add(new CBotTF2DemoPipeTrapSched(iDemoTrapType, vStand, vPoint, Vector(150, 150, 20), false, pWaypoint->getArea())); + return true; } - } } break; @@ -6386,9 +6469,8 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p CWaypoint *pWpt = CWaypoints::getWaypoint(CWaypointLocations::NearestBlastWaypoint(vLoc,pWptBlast->getOrigin(),4096.0,CWaypoints::getWaypointIndex(pWptBlast),true,false,true,false,getTeam(),true,1024.0f)); */ int iAiming; - CWaypoint *pWpt = CWaypoints::nearestPipeWaypoint(vEnemy,getOrigin(),&iAiming); - if ( pWpt ) + if ( CWaypoint *pWpt = CWaypoints::nearestPipeWaypoint(vEnemy,getOrigin(),&iAiming) ) { CFindPathTask *findpath = new CFindPathTask(pEnemy); CBotTask *pipetask = new CBotTF2Spam(pWpt->getOrigin(),vEnemy,util->getWeaponChoice()); @@ -6439,14 +6521,12 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p } int iAiming; - CWaypoint *pWpt = CWaypoints::nearestPipeWaypoint(vEnemy,getOrigin(),&iAiming); - if ( pWpt ) + if ( CWaypoint *pWpt = CWaypoints::nearestPipeWaypoint(vEnemy,getOrigin(),&iAiming) ) { - - CFindPathTask *findpath = new CFindPathTask(pEnemy); - CBotTask *pipetask = new CBotTF2DemomanPipeEnemy(getWeapons()->getWeapon(CWeapons::getWeapon(TF2_WEAPON_PIPEBOMBS)),vEnemy,pEnemy); + CBotTask* pipetask = new CBotTF2DemomanPipeEnemy( + getWeapons()->getWeapon(CWeapons::getWeapon(TF2_WEAPON_PIPEBOMBS)), vEnemy, pEnemy); CBotSchedule *pipesched = new CBotSchedule(); pipetask->setInterruptFunction(new CBotTF2HurtInterrupt(this)); @@ -6545,12 +6625,15 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p if ( pWaypoint ) { - m_pSchedules->add(new CBotTF2SnipeSched(pWaypoint->getOrigin(),CWaypoints::getWaypointIndex(pWaypoint))); - return true; + if ((m_pWeapons->hasWeapon(TF2_WEAPON_BOW)) || (m_pWeapons->getCurrentWeaponInSlot(0)->isProjectile())) + return false; + else + m_pSchedules->add(new CBotTF2SnipeSched(pWaypoint->getOrigin(),CWaypoints::getWaypointIndex(pWaypoint))); + return true; } break; case BOT_UTIL_GETFLAG_LASTKNOWN: - pWaypoint = CWaypoints::getWaypoint(CWaypoints::nearestWaypointGoal(-1,m_vLastKnownFlagPoint,512.0,getTeam())); + pWaypoint = CWaypoints::getWaypoint(CWaypoints::nearestWaypointGoal(-1,m_vLastKnownFlagPoint,512.0f,getTeam())); if ( pWaypoint ) { @@ -6559,10 +6642,8 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p } break; case BOT_UTIL_MEDIC_FINDPLAYER_AT_SPAWN: - { - CWaypoint *pWaypoint = NULL; - - pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(m_vTeleportEntrance,300,-1,true,false,true,NULL,false,getTeam(),true)); + { + pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(m_vTeleportEntrance,300.0f,-1,true,false,true, nullptr,false,getTeam(),true)); //if ( pWaypoint && randomInt(0,1) ) // pWaypoint = CWaypoints::getPinchPointFromWaypoint(getOrigin(),pWaypoint->getOrigin()); @@ -6594,8 +6675,8 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p // find a nearby friendly int i = 0; edict_t *pEdict; - edict_t *pNearby = NULL; - float fMaxDistance = 500; + edict_t *pNearby = nullptr; + float fMaxDistance = 500.0f; float fDistance; for ( i = 1; i <= CBotGlobals::maxClients(); i ++ ) @@ -6630,19 +6711,19 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p return false; } - break; + //break; case BOT_UTIL_GETFLAG: pWaypoint = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_FLAG,getTeam()); if ( pWaypoint ) { - CWaypoint *pRoute = NULL; Vector vRoute = Vector(0,0,0); bool bUseRoute = false; if ( (m_fUseRouteTime < engine->Time()) ) { - // find random route + CWaypoint *pRoute = nullptr; + // find random route pRoute = CWaypoints::randomRouteWaypoint(this,getOrigin(),pWaypoint->getOrigin(),getTeam(),m_iCurrentAttackArea); if ( pRoute ) @@ -6651,6 +6732,12 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p vRoute = pRoute->getOrigin(); m_fUseRouteTime = engine->Time() + randomFloat(30.0f,60.0f); } + /*if (std::strncmp(szmapname, "ctf_chouhen_b2", 14) == 0 || std::strncmp(szmapname, "ctf_haarp", 9) == 0) + { + bUseRoute = true; + vRoute = pRoute->getOrigin(); + m_fUseRouteTime = engine->Time() + randomFloat(1.0f, 3.0f); + }*/ } m_pSchedules->add(new CBotTF2GetFlagSched(pWaypoint->getOrigin(),bUseRoute,vRoute)); @@ -6671,16 +6758,16 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p return true; } - break; + //break; case BOT_UTIL_FOLLOW_SQUAD_LEADER: { - Vector pos = m_pSquad->GetFormationVector(m_pEdict); + Vector pos = m_pSquad->GetFormationVector(m_pEdict); //'pos' unused [APG]RoboCop[CL] m_pSchedules->add(new CBotSchedule(new CBotFollowSquadLeader(m_pSquad))); return true; } - break; + //break; case BOT_UTIL_ROAM: // roam pWaypoint = CWaypoints::randomWaypointGoal(-1,getTeam(),0,false,this); @@ -6698,11 +6785,9 @@ bool CBotTF2 :: executeAction ( CBotUtility *util )//eBotAction id, CWaypoint *p return false; } -void CBotTF2 :: touchedWpt ( CWaypoint *pWaypoint , int iNextWaypoint, int iPrevWaypoint ) +void CBotTF2 :: touchedWpt ( CWaypoint *pWaypoint , const int iNextWaypoint, const int iPrevWaypoint ) { - static int wptindex; - - CBot::touchedWpt(pWaypoint); + CBotFortress::touchedWpt(pWaypoint, iNextWaypoint, iPrevWaypoint); if ( canGotoWaypoint (getOrigin(), pWaypoint) ) { @@ -6710,7 +6795,7 @@ void CBotTF2 :: touchedWpt ( CWaypoint *pWaypoint , int iNextWaypoint, int iPrev { if ( getNavigator()->hasNextPoint() ) { - CBotWeapon *pWeapon = NULL; + CBotWeapon *pWeapon; if ( getClass() == TF_CLASS_SOLDIER ) { @@ -6737,7 +6822,6 @@ void CBotTF2 :: touchedWpt ( CWaypoint *pWaypoint , int iNextWaypoint, int iPrev } else if ( pWaypoint->hasFlag(CWaypointTypes::W_FL_DOUBLEJUMP) ) { - extern ConVar bot_scoutdj; m_pButtons->tap(IN_JUMP); m_fDoubleJumpTime = engine->Time() + bot_scoutdj.GetFloat(); //m_pSchedules->addFront(new CBotSchedule(new CBotTFDoubleJump())); @@ -6748,16 +6832,16 @@ void CBotTF2 :: touchedWpt ( CWaypoint *pWaypoint , int iNextWaypoint, int iPrev { if ( randomFloat(0.0f,100.0f) > (m_pProfile->m_fBraveness*10) ) { - float fVel = m_vVelocity.Length(); + const float fVel = m_vVelocity.Length(); if ( fVel > 0.0f ) { - Vector v_next = getNavigator()->getNextPoint(); - Vector v_org = getOrigin(); - Vector v_comp = v_next-v_org; - float fDist = v_comp.Length(); + const Vector v_next = getNavigator()->getNextPoint(); + const Vector v_org = getOrigin(); + const Vector v_comp = v_next-v_org; + const float fDist = v_comp.Length(); - Vector v_vel = (m_vVelocity/fVel) * fDist; + const Vector v_vel = (m_vVelocity/fVel) * fDist; if ( (v_next-(v_org + v_vel)).Length() <= 24.0f ) m_pButtons->tap(IN_JUMP); @@ -6768,7 +6852,7 @@ void CBotTF2 :: touchedWpt ( CWaypoint *pWaypoint , int iNextWaypoint, int iPrev else if ( pWaypoint->hasFlag(CWaypointTypes::W_FL_FALL) ) { // jump to avoid being hurt (scouts can jump in the air) - if ( fabs(m_vVelocity.z) > 1 ) + if ( std::fabs(m_vVelocity.z) > 1 ) jump(); } } @@ -6776,6 +6860,7 @@ void CBotTF2 :: touchedWpt ( CWaypoint *pWaypoint , int iNextWaypoint, int iPrev // only good for spies so they know when to cloak better if ( getClass() == TF_CLASS_SPY ) { + static int wptindex; wptindex = CWaypoints::getWaypointIndex(pWaypoint); if ( m_pEnemy && hasSomeConditions(CONDITION_SEE_CUR_ENEMY) ) @@ -6787,26 +6872,176 @@ void CBotTF2 :: touchedWpt ( CWaypoint *pWaypoint , int iNextWaypoint, int iPrev } } -void CBotTF2 :: modAim ( edict_t *pEntity, Vector &v_origin, Vector *v_desired_offset, Vector &v_size, float fDist, float fDist2D ) +void CBotTF2::modAim(edict_t* pEntity, Vector& v_origin, Vector* v_desired_offset, Vector& v_size, const float fDist, + const float fDist2D) { - static CBotWeapon *pWp; + static CBotWeapon* pWp; static float fTime; - extern ConVar rcbot_supermode; + pWp = getCurrentWeapon(); + + CBotFortress::modAim(pEntity, v_origin, v_desired_offset, v_size, fDist, fDist2D); + + if (pWp) + { + /*if (m_iClass == TF_CLASS_SNIPER) + { + if (pWp->getID() == TF2_WEAPON_BOW) + { + if (pWp->getProjectileSpeed() > 0) + { + CClient *pClient = CClients::get(pEntity); + Vector vVelocity; + + if (CClassInterface::getVelocity(pEntity, &vVelocity)) + { + if (pClient && (vVelocity == Vector(0, 0, 0))) + vVelocity = pClient->getVelocity(); + } + else if (pClient) + vVelocity = pClient->getVelocity(); + + // the arrow will arc + fTime = fDist2D / (pWp->getProjectileSpeed() * 0.707); + + if (rcbot_supermode.GetBool()) + *v_desired_offset = *v_desired_offset + ((vVelocity * fTime)); + else + *v_desired_offset = *v_desired_offset + ((vVelocity * fTime) * m_pProfile->m_fAimSkill); + + if (sv_gravity.IsValid()) + v_desired_offset->z += ((pow(2, fTime) - 1.0f) + * (sv_gravity.GetFloat() * 0.1f)); // - (getOrigin().z - v_origin.z); + + v_desired_offset->z *= 0.6f; + } + } + else if ((v_desired_offset->z < 64.0f) && !hasSomeConditions(CONDITION_SEE_ENEMY_GROUND)) + { + if (rcbot_supermode.GetBool()) + v_desired_offset->z += 15.0f; + else + v_desired_offset->z += randomFloat(0.0f, 16.0f); + } + }*/ + + const CWeapon* pWepInfo = pWp->getWeaponInfo(); + if (pWepInfo->isProjectile()) + { + // int iSpeed = 0; + + /*switch (pWp->getID()) + { + case TF2_WEAPON_ROCKETLAUNCHER: + // fall through + case TF2_WEAPON_COWMANGLER: + case TF2_WEAPON_FLAREGUN: + case TF2_WEAPON_GRENADELAUNCHER: + {*/ + CClient* pClient = CClients::get(pEntity); + Vector vVelocity; + + // if ( iSpeed == 0 ) + // iSpeed = TF2_GRENADESPEED; + + // if ( pClient ) + //{ + if (CClassInterface::getVelocity(pEntity, &vVelocity)) + { + assert(pClient != nullptr); + if (vVelocity == Vector(0, 0, 0)) + vVelocity = pClient->getVelocity(); + } + else if (pClient) + vVelocity = pClient->getVelocity(); + + // speed = distance/time + // .'. + // time = distance/speed + + const bool bIsGrenade = pWepInfo->isGrenade(); + float fProjectileSpeed = pWepInfo->getProjectileSpeed(); + + if (fProjectileSpeed > 0.0f) + { + if (bIsGrenade) + fTime = fDist2D / (fProjectileSpeed * 0.707f); + else + fTime = fDist / fProjectileSpeed; + + // if (rcbot_supermode.GetBool()) + *v_desired_offset = *v_desired_offset + ((vVelocity * fTime)); + /*else + *v_desired_offset = *v_desired_offset + ((vVelocity * fTime) * m_pProfile->m_fAimSkill);*/ + + if ((sv_gravity.IsValid()) && bIsGrenade) + v_desired_offset->z += + ((static_cast(std::pow(2, fTime)) - 1.0f) * (sv_gravity.GetFloat() * 0.1f)); // - (getOrigin().z - v_origin.z); + + /*if ((pWp->getID() == TF2_WEAPON_GRENADELAUNCHER) && hasSomeConditions(CONDITION_SEE_ENEMY_GROUND)) + v_desired_offset->z -= randomFloat(8.0f, 32.0f); // aim for ground - with grenade launcher + else if ((pWp->getID() == TF2_WEAPON_ROCKETLAUNCHER) || (pWp->getID() == TF2_WEAPON_COWMANGLER) + || (v_origin.z > (getOrigin().z + 16.0f)))*/ + v_desired_offset->z += randomFloat(8.0f, 32.0f); // aim for body, not ground + /*} + break; + }*/ + } + } + + if (m_iClass == TF_CLASS_HWGUY) + { + if (pWp->getID() == TF2_WEAPON_MINIGUN) + { + Vector vForward; + Vector vRight; + Vector vUp; + + const QAngle eyes = m_pController->GetLocalAngles(); + + // in fov? Check angle to edict + AngleVectors(eyes, &vForward, &vRight, &vUp); + + *v_desired_offset = + *v_desired_offset + (((vRight * 24) - Vector(0, 0, 24)) * bot_heavyaimoffset.GetFloat()); + } + } + + if (m_iClass == TF_CLASS_MEDIC) + { + if (pWp->getID() != TF2_WEAPON_CROSSBOW) + v_desired_offset->z += std::sqrt(fDist) * 2; + } + + if (m_iClass == TF_CLASS_SNIPER) + { + if (pWepInfo->getSlot() == 0) + { + Vector eye; + gameclients->ClientEarPosition(pEntity, &eye); + v_desired_offset->z = (eye - v_origin).z; + } + } + } +} + +/*void CBotTF2 :: modAim ( edict_t *pEntity, Vector &v_origin, Vector *v_desired_offset, Vector &v_size, const float fDist, const float fDist2D ) +{ + static CBotWeapon *pWp; pWp = getCurrentWeapon(); - CBot::modAim(pEntity,v_origin,v_desired_offset,v_size,fDist,fDist2D); + CBotFortress::modAim(pEntity,v_origin,v_desired_offset,v_size,fDist,fDist2D); if ( pWp ) { + static float fTime; if ( m_iClass == TF_CLASS_SNIPER ) { if (pWp->getID() == TF2_WEAPON_BOW) { if (pWp->getProjectileSpeed() > 0) { - extern ConVar *sv_gravity; CClient *pClient = CClients::get(pEntity); Vector vVelocity; @@ -6819,15 +7054,15 @@ void CBotTF2 :: modAim ( edict_t *pEntity, Vector &v_origin, Vector *v_desired_o vVelocity = pClient->getVelocity(); // the arrow will arc - fTime = fDist2D / (pWp->getProjectileSpeed()*0.707); + fTime = fDist2D / (pWp->getProjectileSpeed()*0.707f); if (rcbot_supermode.GetBool()) *v_desired_offset = *v_desired_offset + ((vVelocity*fTime)); else *v_desired_offset = *v_desired_offset + ((vVelocity*fTime)*m_pProfile->m_fAimSkill); - if (sv_gravity != NULL) - v_desired_offset->z += ((pow(2, fTime) - 1.0f)*(sv_gravity->GetFloat()*0.1f));// - (getOrigin().z - v_origin.z); + if (sv_gravity.IsValid()) + v_desired_offset->z += (static_cast(std::pow(2, fTime)) - 1.0f) * (sv_gravity.GetFloat() * 0.1f);// - (getOrigin().z - v_origin.z); v_desired_offset->z *= 0.6f; } @@ -6843,19 +7078,17 @@ void CBotTF2 :: modAim ( edict_t *pEntity, Vector &v_origin, Vector *v_desired_o else if ( m_iClass == TF_CLASS_MEDIC ) { if ( pWp->getID() == TF2_WEAPON_SYRINGEGUN ) - v_desired_offset->z += sqrt(fDist)*2; + v_desired_offset->z += std::sqrt(fDist)*2; } else if ( m_iClass == TF_CLASS_HWGUY ) { if ( pWp->getID() == TF2_WEAPON_MINIGUN ) { - extern ConVar bot_heavyaimoffset; - Vector vForward; Vector vRight; Vector vUp; - QAngle eyes = m_pController->GetLocalAngles(); + const QAngle eyes = m_pController->GetLocalAngles(); // in fov? Check angle to edict AngleVectors(eyes,&vForward,&vRight,&vUp); @@ -6875,7 +7108,6 @@ void CBotTF2 :: modAim ( edict_t *pEntity, Vector &v_origin, Vector *v_desired_o case TF2_WEAPON_FLAREGUN: case TF2_WEAPON_GRENADELAUNCHER: { - extern ConVar *sv_gravity; CClient *pClient = CClients::get(pEntity); Vector vVelocity; @@ -6899,7 +7131,7 @@ void CBotTF2 :: modAim ( edict_t *pEntity, Vector &v_origin, Vector *v_desired_o if ( pWp->getProjectileSpeed() > 0 ) { if ( (pWp->getID() == TF2_WEAPON_GRENADELAUNCHER) ) - fTime = fDist2D/(pWp->getProjectileSpeed()*0.707); + fTime = fDist2D/(pWp->getProjectileSpeed()*0.707f); else fTime = fDist/(pWp->getProjectileSpeed()); @@ -6908,8 +7140,8 @@ void CBotTF2 :: modAim ( edict_t *pEntity, Vector &v_origin, Vector *v_desired_o else *v_desired_offset = *v_desired_offset + ((vVelocity*fTime)*m_pProfile->m_fAimSkill ); - if ( (sv_gravity != NULL) && (pWp->getID() == TF2_WEAPON_GRENADELAUNCHER) ) - v_desired_offset->z += ((pow(2,fTime)-1.0f)*(sv_gravity->GetFloat()*0.1f));// - (getOrigin().z - v_origin.z); + if ((sv_gravity.IsValid()) && (pWp->getID() == TF2_WEAPON_GRENADELAUNCHER)) + v_desired_offset->z += (static_cast(std::pow(2, fTime)) - 1.0f) * (sv_gravity.GetFloat() * 0.1f);// - (getOrigin().z - v_origin.z); if ((pWp->getID() == TF2_WEAPON_GRENADELAUNCHER) && hasSomeConditions(CONDITION_SEE_ENEMY_GROUND)) v_desired_offset->z -= randomFloat(8.0f,32.0f); // aim for ground - with grenade launcher @@ -6921,12 +7153,11 @@ void CBotTF2 :: modAim ( edict_t *pEntity, Vector &v_origin, Vector *v_desired_o } } } -} +}*/ + /* Vector CBotTF2 :: getAimVector ( edict_t *pEntity ) { - extern ConVar bot_aimsmoothing; - static CBotWeapon *pWp; static float fDist; static float fTime; @@ -6956,7 +7187,6 @@ Vector CBotTF2 :: getAimVector ( edict_t *pEntity ) { if ( pWp->getID() == TF2_WEAPON_MINIGUN ) { - extern ConVar bot_heavyaimoffset; Vector vForward; Vector vRight; @@ -7034,8 +7264,6 @@ void CBotTF2 :: checkDependantEntities () eBotFuncState CBotTF2 :: rocketJump(int *iState,float *fTime) { - extern ConVar bot_rj; - setLookAtTask(LOOK_GROUND); m_bIncreaseSensitivity = true; @@ -7068,15 +7296,17 @@ eBotFuncState CBotTF2 :: rocketJump(int *iState,float *fTime) return BOT_FUNC_CONTINUE; } - // return true if the enemy is ok to shoot, return false if there is a problem (e.g. weapon problem) bool CBotTF2 :: handleAttack ( CBotWeapon *pWeapon, edict_t *pEnemy ) { - extern ConVar rcbot_enemyshootfov; static float fDistance; fDistance = distanceFrom(pEnemy); + const string_t mapname = gpGlobals->mapname; + + const char* szmapname = mapname.ToCStr(); + if ( (fDistance > 128) && (DotProductFromOrigin(m_vAimVector) < rcbot_enemyshootfov.GetFloat()) ) return true; // keep enemy / don't shoot : until angle between enemy is less than 45 degrees @@ -7089,16 +7319,16 @@ bool CBotTF2 :: handleAttack ( CBotWeapon *pWeapon, edict_t *pEnemy ) { if ( ((fDistance < rcbot_tf2_spy_kill_on_cap_dist.GetFloat()) && CTeamFortress2Mod::isCapping(pEnemy)) || ( (fDistance < 130) && CBotGlobals::isAlivePlayer(pEnemy) && - ( fabs(CBotGlobals::yawAngleFromEdict(pEnemy,getOrigin())) > bot_spyknifefov.GetFloat() ) ) ) + ( std::fabs(CBotGlobals::yawAngleFromEdict(pEnemy,getOrigin())) > bot_spyknifefov.GetFloat() ) ) ) { - ; // ok attack + // ok attack } else if ( m_fFrenzyTime < engine->Time() ) return true; // return but don't attack else if ( CBotGlobals::isPlayer(pEnemy)&&(CClassInterface::getTF2Class(pEnemy) == TF_CLASS_ENGINEER) && ( - CTeamFortress2Mod::isMySentrySapped(pEnemy) || - CTeamFortress2Mod::isMyTeleporterSapped(pEnemy) || + CTeamFortress2Mod::isMySentrySapped(pEnemy) || + CTeamFortress2Mod::isMyTeleporterSapped(pEnemy) || CTeamFortress2Mod::isMyDispenserSapped(pEnemy) ) ) @@ -7110,14 +7340,21 @@ bool CBotTF2 :: handleAttack ( CBotWeapon *pWeapon, edict_t *pEnemy ) if ( pWeapon ) { - Vector vEnemyOrigin; bool bSecAttack = false; - extern ConVar rcbot_tf2_pyro_airblast; bool bIsPlayer = false; clearFailedWeaponSelect(); - if ( pWeapon->isMelee() ) + if ( pWeapon->isMelee() && !(std::strncmp(szmapname, "dm_hydro_v20", 12) == 0 || std::strncmp(szmapname, "dm_powerdown_v20", 16) == 0 || std::strncmp(szmapname, "dm_forgecall_v20", 16) == 0 || std::strncmp(szmapname, "dm_poolparty_v20", 16) == 0 || std::strncmp(szmapname, "dm_badworks_v20", 15) == 0 || std::strncmp(szmapname, "dm_razorpoint_v20", 17) == 0 || std::strncmp(szmapname, "dm_deadlock_v20", 15) == 0)) + { + setMoveTo(CBotGlobals::entityOrigin(pEnemy)); + //setLookAt(m_vAimVector); + setLookAtTask(LOOK_ENEMY); + // dontAvoid my enemy + m_fAvoidTime = engine->Time() + 1.0f; + } + + if ((pWeapon->getID() == TF2_SLOT_PRMRY) && (std::strncmp(szmapname, "dm_hydro_v20", 12) == 0 || std::strncmp(szmapname, "dm_powerdown_v20", 16) == 0 || std::strncmp(szmapname, "dm_forgecall_v20", 16) == 0 || std::strncmp(szmapname, "dm_poolparty_v20", 16) == 0 || std::strncmp(szmapname, "dm_badworks_v20", 15) == 0 || std::strncmp(szmapname, "dm_razorpoint_v20", 17) == 0 || std::strncmp(szmapname, "dm_deadlock_v20", 15) == 0)) { setMoveTo(CBotGlobals::entityOrigin(pEnemy)); //setLookAt(m_vAimVector); @@ -7139,10 +7376,20 @@ bool CBotTF2 :: handleAttack ( CBotWeapon *pWeapon, edict_t *pEnemy ) else if (( pEnemy == m_NearestEnemyRocket.get() ) || ( pEnemy == m_pNearestPipeGren.get() )) return false; // don't attack the rocket anymore } + + if (CTeamFortress2Mod::isMapType(TF_MAP_ZI) && m_iTeam == TF2_TEAM_BLUE) + { + setMoveTo(CBotGlobals::entityOrigin(pEnemy)); + //setLookAt(m_vAimVector); + setLookAtTask(LOOK_ENEMY); + // dontAvoid my enemy + m_fAvoidTime = engine->Time() + 1.0f; + secondaryAttack(); + } - if ((m_iClass == TF_CLASS_SNIPER) && (pWeapon->getID() == TF2_WEAPON_BOW)) + if (m_iClass == TF_CLASS_SNIPER && pWeapon->isProjectile()) { - stopMoving(); + //stopMoving(); if (m_fSnipeAttackTime > engine->Time()) { @@ -7150,17 +7397,18 @@ bool CBotTF2 :: handleAttack ( CBotWeapon *pWeapon, edict_t *pEnemy ) } else { - float fDistFactor = distanceFrom(pEnemy) / pWeapon->getPrimaryMaxRange(); - float fRandom = randomFloat(m_pProfile->m_fAimSkill, 1.0f); - float fSkill = 1.0f - fRandom; + const float fDistFactor = distanceFrom(pEnemy) / pWeapon->getPrimaryMaxRange(); + const float fRandom = randomFloat(m_pProfile->m_fAimSkill, 1.0f); + const float fSkill = 1.0f - fRandom; - m_fSnipeAttackTime = engine->Time() + (fSkill*1.0f) + ((4.0f*fDistFactor)*fSkill); + //m_fSnipeAttackTime = engine->Time() + (fSkill*1.0f) + ((4.0f*fDistFactor)*fSkill); + m_fSnipeAttackTime = engine->Time() + ((2.0f * fDistFactor)); m_pButtons->letGo(IN_ATTACK); } } - else if ( (m_iClass == TF_CLASS_SNIPER) && (pWeapon->getID() == TF2_WEAPON_SNIPERRIFLE) ) + else if (m_iClass == TF_CLASS_SNIPER && pWeapon->getWeaponInfo() && pWeapon->getWeaponInfo()->getSlot() == 0 && ((!m_pWeapons->hasWeapon(TF2_WEAPON_BOW)) || !(m_pWeapons->getCurrentWeaponInSlot(0)->isProjectile()))) { - stopMoving(); + //stopMoving(); if ( m_fSnipeAttackTime < engine->Time() ) { @@ -7169,7 +7417,9 @@ bool CBotTF2 :: handleAttack ( CBotWeapon *pWeapon, edict_t *pEnemy ) else secondaryAttack(); // zoom - m_fSnipeAttackTime = engine->Time() + randomFloat(0.5f,3.0f); + //m_fSnipeAttackTime = engine->Time() + randomFloat(0.5f,3.0f); + //m_fSnipeAttackTime = engine->Time() + randomFloat(0.1f, 0.8f); + m_fSnipeAttackTime = engine->Time() + randomFloat(0.3f, 1.5f); } } else if ( !bSecAttack ) @@ -7184,7 +7434,7 @@ bool CBotTF2 :: handleAttack ( CBotWeapon *pWeapon, edict_t *pEnemy ) tapButton(IN_ATTACK2); } - vEnemyOrigin = CBotGlobals::entityOrigin(pEnemy); + const Vector vEnemyOrigin = CBotGlobals::entityOrigin(pEnemy); // enemy below me! if ( pWeapon->isMelee() && (distanceFrom2D(pEnemy)<64.0f) && (vEnemyOrigin.z < getOrigin().z) && (vEnemyOrigin.z > (getOrigin().z-128)) ) { @@ -7202,13 +7452,11 @@ bool CBotTF2 :: handleAttack ( CBotWeapon *pWeapon, edict_t *pEnemy ) return true; } -int CBotFortress :: getMetal () +int CBotFortress :: getMetal () const { if ( m_iClass == TF_CLASS_ENGINEER ) { - CBotWeapon *pWrench = m_pWeapons->getWeapon(CWeapons::getWeapon(TF2_WEAPON_WRENCH)); - - if ( pWrench ) + if ( const CBotWeapon *pWrench = m_pWeapons->getWeapon(CWeapons::getWeapon(TF2_WEAPON_WRENCH)) ) { return pWrench->getAmmo(this); } @@ -7217,19 +7465,18 @@ int CBotFortress :: getMetal () return 0; } -bool CBotTF2 :: upgradeBuilding ( edict_t *pBuilding, bool removesapper ) +bool CBotTF2 :: upgradeBuilding ( edict_t *pBuilding, const bool removesapper ) { - Vector vOrigin = CBotGlobals::entityOrigin(pBuilding); + const Vector vOrigin = CBotGlobals::entityOrigin(pBuilding); - CBotWeapon *pWeapon = getCurrentWeapon(); - int iMetal = 0; + const CBotWeapon *pWeapon = getCurrentWeapon(); wantToListen(false); if ( !pWeapon ) return false; - iMetal = pWeapon->getAmmo(this); + const int iMetal = pWeapon->getAmmo(this); if ( pWeapon->getID() != TF2_WEAPON_WRENCH ) { @@ -7256,18 +7503,18 @@ bool CBotTF2 :: upgradeBuilding ( edict_t *pBuilding, bool removesapper ) lookAtEdict(pBuilding); m_fLookSetTime = 0; setLookAtTask(LOOK_EDICT); - m_fLookSetTime = engine->Time() + randomFloat(3.0,8.0); + m_fLookSetTime = engine->Time() + randomFloat(3.0f,8.0f); return true; } -void CBotFortress::teamFlagPickup () +void CBotFortress::teamFlagPickup () const { if ( CTeamFortress2Mod::isMapType(TF_MAP_SD) && m_pSchedules->hasSchedule(SCHED_TF2_GET_FLAG) ) m_pSchedules->removeSchedule(SCHED_TF2_GET_FLAG); } -void CBotTF2::roundWon(int iTeam, bool bFullRound ) +void CBotTF2::roundWon(int iTeam, const bool bFullRound) { m_pSchedules->freeMemory(); @@ -7282,45 +7529,86 @@ void CBotTF2::roundWon(int iTeam, bool bFullRound ) removeCondition(CONDITION_COVERT); } +void CBotTF2::changeClass() +{ + // Clean up any class-specific schedules before changing + if (m_iClass == TF_CLASS_ENGINEER) + { + // Clear building schedules for engineers + if (m_pSchedules->hasSchedule(SCHED_TF_BUILD)) + m_pSchedules->freeMemory(); + } + else if (m_iClass == TF_CLASS_MEDIC) + { + // Clear healing schedules for medics + if (m_pSchedules->hasSchedule(SCHED_HEAL)) + m_pSchedules->freeMemory(); + } + else if (m_iClass == TF_CLASS_SPY) + { + // Clear spy-specific schedules + if (m_pSchedules->hasSchedule(SCHED_SPY_SAP_BUILDING)) + m_pSchedules->freeMemory(); + } + // Choose a new class (updates m_iDesiredClass) + chooseClass(); + + // Change to the new class + selectClass(); + + // If bot is alive, need to suicide to trigger class change + // TF2 requires respawn for class changes to take effect + if (isAlive()) + { + helpers->ClientCommand(m_pEdict, "kill"); + } + + // Reset the change class timer + m_fChangeClassTime = engine->Time() + randomFloat(bot_min_cc_time.GetFloat(), bot_max_cc_time.GetFloat()); +} + void CBotTF2::waitRemoveSap () { // this gives engi bot some time to attack spy that has been sapping a sentry m_fRemoveSapTime = engine->Time()+randomFloat(2.5f,4.0f); - // TO DO :: add spy check task + // TODO :: add spy check task } void CBotTF2::roundReset(bool bFullReset) { - m_pRedPayloadBomb = NULL; - m_pBluePayloadBomb = NULL; + m_pRedPayloadBomb = nullptr; + m_pBluePayloadBomb = nullptr; m_fLastKnownTeamFlagTime = 0.0f; - m_bEntranceVectorValid = false; + m_bEntranceVectorValid = false; m_bSentryGunVectorValid = false; m_bDispenserVectorValid = false; m_bTeleportExitVectorValid = false; - m_pPrevSpy = NULL; - m_pHeal = NULL; - m_pSentryGun = NULL; - m_pDispenser = NULL; - m_pTeleEntrance = NULL; - m_pTeleExit = NULL; - m_pAmmo = NULL; - m_pHealthkit = NULL; - m_pNearestDisp = NULL; - m_pNearestEnemySentry = NULL; - m_pNearestAllySentry = NULL; - m_pNearestEnemyTeleporter = NULL; - m_pNearestEnemyDisp = NULL; - m_pNearestPipeGren = NULL; - m_pFlag = NULL; - m_pPrevSpy = NULL; + + m_pPrevSpy = nullptr; + m_pHeal = nullptr; + m_pSentryGun = nullptr; + m_pDispenser = nullptr; + m_pTeleEntrance = nullptr; + m_pTeleExit = nullptr; + + m_pAmmo = nullptr; + m_pHealthkit = nullptr; + m_pNearestDisp = nullptr; + m_pNearestEnemySentry = nullptr; + m_pNearestAllySentry = nullptr; + m_pNearestEnemyTeleporter = nullptr; + m_pNearestEnemyDisp = nullptr; + m_pNearestPipeGren = nullptr; + + m_pFlag = nullptr; + //m_pBall = nullptr; m_iSentryKills = 0; - m_fSentryPlaceTime = 0.0; + m_fSentryPlaceTime = 0.0f; m_fDispenserPlaceTime = 0.0f; m_fDispenserHealAmount = 0.0f; - m_fTeleporterEntPlacedTime = 0.0f; - m_fTeleporterExtPlacedTime = 0.0f; - m_iTeleportedPlayers = 0; + m_fTeleporterEntPlacedTime = 0.0f; + m_fTeleporterExtPlacedTime = 0.0f; + m_iTeleportedPlayers = 0; flagReset(); teamFlagReset(); @@ -7358,15 +7646,11 @@ void CBotTF2 :: pointsUpdated() { if ( m_iClass == TF_CLASS_ENGINEER ) { - extern ConVar rcbot_move_sentry_time; - extern ConVar rcbot_move_disp_time; - extern ConVar rcbot_move_tele_time; - -//m_pPayloadBomb = NULL; - bool bMoveSentry = (m_iSentryArea!=m_iCurrentAttackArea)&&(m_iSentryArea!=m_iCurrentDefendArea)&&((m_iTeam==TF2_TEAM_BLUE)||!CTeamFortress2Mod::isAttackDefendMap()); - bool bMoveTeleEntrance = (m_iTeam==TF2_TEAM_BLUE)||!CTeamFortress2Mod::isAttackDefendMap(); - bool bMoveTeleExit = (m_iTeleExitArea!=m_iCurrentAttackArea)&&(m_iTeleExitArea!=m_iCurrentDefendArea)&&((m_iTeam==TF2_TEAM_BLUE)||!CTeamFortress2Mod::isAttackDefendMap()); - bool bMoveDisp = bMoveSentry; + //m_pPayloadBomb = NULL; + const bool bMoveSentry = (m_iSentryArea!=m_iCurrentAttackArea)&&(m_iSentryArea!=m_iCurrentDefendArea)&&((m_iTeam==TF2_TEAM_BLUE)||!CTeamFortress2Mod::isAttackDefendMap()); + const bool bMoveTeleEntrance = (m_iTeam==TF2_TEAM_BLUE)||!CTeamFortress2Mod::isAttackDefendMap(); + const bool bMoveTeleExit = (m_iTeleExitArea!=m_iCurrentAttackArea)&&(m_iTeleExitArea!=m_iCurrentDefendArea)&&((m_iTeam==TF2_TEAM_BLUE)||!CTeamFortress2Mod::isAttackDefendMap()); + const bool bMoveDisp = bMoveSentry; // think about moving stuff now if ( bMoveSentry && m_pSentryGun.get() && ((m_fSentryPlaceTime + rcbot_move_sentry_time.GetFloat())>engine->Time()) ) @@ -7385,7 +7669,7 @@ void CBotTF2 :: pointsUpdated() void CBotTF2::updateAttackPoints() { - int iPrev = m_iCurrentAttackArea; + const int iPrev = m_iCurrentAttackArea; m_iTeam = getTeam(); @@ -7399,7 +7683,7 @@ void CBotTF2::updateAttackPoints() void CBotTF2::updateDefendPoints() { - int iPrev = m_iCurrentDefendArea; + const int iPrev = m_iCurrentDefendArea; m_iTeam = getTeam(); @@ -7411,132 +7695,189 @@ void CBotTF2::updateDefendPoints() } } -/// TO DO : list of areas -void CBotTF2::getDefendArea ( vector *m_iAreas ) +// TODO: list of areas +// TODO: determine if the intent was to use WaypointList for these +void CBotTF2::getDefendArea ( std::vector *m_iAreas ) { m_iCurrentDefendArea = CTeamFortress2Mod::m_ObjectiveResource.getRandomValidPointForTeam(m_iTeam,TF2_POINT_DEFEND); } -void CBotTF2::getAttackArea ( vector *m_iAreas ) +void CBotTF2::getAttackArea ( std::vector *m_iAreas ) { m_iCurrentAttackArea = CTeamFortress2Mod::m_ObjectiveResource.getRandomValidPointForTeam(m_iTeam,TF2_POINT_ATTACK); } void CBotTF2::pointCaptured(int iPoint, int iTeam, const char *szPointName) { - m_pRedPayloadBomb = NULL; - m_pBluePayloadBomb = NULL; + m_pRedPayloadBomb = nullptr; + m_pBluePayloadBomb = nullptr; } // Is Enemy Function // take a pEdict entity to check if its an enemy // return TRUE to "OPEN FIRE" (Attack) // return FALSE to ignore -#define RCBOT_ISENEMY_UNDEF -1 -#define RCBOT_ISENEMY_TRUE 1 -#define RCBOT_ISENEMY_FALSE 0 +enum : std::int8_t +{ + RCBOT_ISENEMY_UNDEF = (-1), + RCBOT_ISENEMY_TRUE = 1, + RCBOT_ISENEMY_FALSE = 0 +}; -bool CBotTF2 :: isEnemy ( edict_t *pEdict,bool bCheckWeapons ) +bool CBotTF2::isEnemy(edict_t* pEdict, const bool bCheckWeapons) { - extern ConVar rcbot_notarget; + const string_t mapname = gpGlobals->mapname; - static short int iEnemyTeam; - static bool bIsPipeBomb; - static bool bIsRocket; - static int bValid; - static bool bIsBoss; - static bool bIsGrenade; + const char* szmapname = mapname.ToCStr(); - bIsPipeBomb = false; - bIsRocket = false; - bValid = false; - bIsBoss = false; - bIsGrenade = false; + bool bIsPipeBomb = false, bIsRocket = false, bValid = false, bIsBoss = false, + bIsGrenade = false; - if ( !pEdict || !pEdict->GetUnknown() ) + if (!pEdict || !pEdict->GetUnknown()) { return false; + } - if ( !CBotGlobals::entityIsAlive(pEdict) ) + if (!CBotGlobals::entityIsAlive(pEdict)) { return false; + } - if ( rcbot_notarget.GetBool() && (ENTINDEX(pEdict) == 1) ) + if (rcbot_notarget.GetBool() && (ENTINDEX(pEdict) == 1)) { return false; + } if ( CBotGlobals::isPlayer(pEdict) ) { if ( CBotGlobals::getTeam(pEdict) != getTeam() ) { + //TODO: Stable tests on TF2 conditions + assert(pEdict != nullptr); + + if (pEdict->IsFree()) + return false; + + const int edictIndex = engine->IndexOfEdict(pEdict); + + if (CBotGlobals::entityIsValid(pEdict)) { + if (CTF2Conditions::TF2_IsPlayerInCondition(edictIndex, TFCond_UberchargedHidden)) + return false; // Don't attack MvM bots who are inside spawn. + if (CTF2Conditions::TF2_IsPlayerInCondition(edictIndex, TFCond_HalloweenGhostMode)) + return false; // Don't attack Ghost Players + if (CTF2Conditions::TF2_IsPlayerInCondition(edictIndex, TFCond_Stealthed)) + return false; // Don't attack invisible players or bots who used magic spell - RussiaTails + if (CTF2Conditions::TF2_IsPlayerInCondition(edictIndex, TFCond_HalloweenKart)) + { + setMoveTo(CBotGlobals::entityOrigin(pEdict)); + //setLookAt(m_vAimVector); + setLookAtTask(LOOK_ENEMY); + // dontAvoid my enemy + secondaryAttack(); + m_fAvoidTime = engine->Time() + 1.0f; + } + } + if ( m_iClass == TF_CLASS_SPY ) { - edict_t *pSentry = NULL; - if ( !bCheckWeapons ) return true; if ( isDisguised() ) { - if ( (pSentry = m_pNearestEnemySentry.get()) != NULL ) + edict_t *pSentry; + if ( (pSentry = m_pNearestEnemySentry.get()) != nullptr) { // If I'm disguised don't attack any player until nearby sentry is disabled - if ( !CTeamFortress2Mod::isSentrySapped(pSentry) && isVisible(pSentry) && (distanceFrom(pSentry)(TF2_MAX_SENTRYGUN_RANGE)) ) return false; } - if ( (pSentry = m_pLastEnemySentry.get()) != NULL ) + if ( (pSentry = m_pLastEnemySentry.get()) != nullptr) { // If I'm disguised don't attack any player until nearby sentry is disabled - if ( !CTeamFortress2Mod::isSentrySapped(pSentry) && isVisible(pSentry) && (distanceFrom(pSentry)(TF2_MAX_SENTRYGUN_RANGE)) ) return false; } } } - if ( CClassInterface::getTF2Class(pEdict) == (int)TF_CLASS_SPY ) + if ( CClassInterface::getTF2Class(pEdict) == static_cast(TF_CLASS_SPY) ) { - static float fMinReaction; - static float fMaxReaction; - static int dteam, dclass, dhealth, dindex; - static bool bfoundspy; - static float fSpyAttackTime; - static edict_t *pDisguisedAs; + //static float fMinReaction = 0.0f; //Unused? [APG]RoboCop[CL] + //static float fMaxReaction = 0.0f; - bfoundspy = true; // shout found spy if true + static int dTeam, dClass, dHealth, dIndex; + static bool bFoundSpy; - fSpyAttackTime = engine->Time() - m_fSpyList[ENTINDEX(pEdict)-1]; + bFoundSpy = true; // shout found spy if true - if ( CClassInterface::getTF2SpyDisguised(pEdict,&dclass,&dteam,&dindex,&dhealth) ) + if (CClassInterface::getTF2SpyDisguised(pEdict, &dClass, &dTeam, &dIndex, &dHealth)) { - pDisguisedAs = (dindex>0)?(INDEXENT(dindex)):(NULL); + bool bIsInvisible = false; + const edict_t *pDisguisedAs = (dIndex > 0) ? (INDEXENT(dIndex)) : (nullptr); - if ( CTeamFortress2Mod::TF2_IsPlayerCloaked(pEdict) ) // if he is cloaked -- can't see him + const int entIndex = ENTINDEX(pEdict) - 1; + const float fSpyAttackTime = engine->Time() - m_fSpyAttackedList[entIndex]; + + if (CTeamFortress2Mod::TF2_IsPlayerCloaked(pEdict)) // if he is cloaked -- can't see him { - bValid = false; - // out of cloak charge or on fire -- i will see him move - if ( ( CClassInterface::getTF2SpyCloakMeter(pEdict) == 0.0f ) || CTeamFortress2Mod::TF2_IsPlayerOnFire(pEdict) ) // if he is on fire and cloaked I can see him + const int iConds = CClassInterface::getTF2Conditions(pEdict); + const bool bExposedCloaked = CClassInterface::getTF2SpyCloakMeter(pEdict) == 0.0f + || ((CTeamFortress2Mod::isMapType(TF_MAP_ZI) || CTeamFortress2Mod::isMapType(TF_MAP_SAXTON)) + && (CTF2Conditions::TF2_IsPlayerInCondition(edictIndex, TFCond_Kritzkrieged) || + CTF2Conditions::TF2_IsPlayerInCondition(edictIndex, TFCond_Buffed))) /*Buff exposes invisibility - RussiaTails*/ + || CTF2Conditions::TF2_IsPlayerInCondition(edictIndex, TFCond_Sapped) + || CTF2Conditions::TF2_IsPlayerInCondition(edictIndex, TFCond_MVMBotRadiowave) + || CTeamFortress2Mod::TF2_IsPlayerOnFire(pEdict) // if he is on fire and cloaked I can see him + || iConds & (1 << 9) /* Flicker */ + || iConds & (1 << 24) /* Jarated */ + || iConds & (1 << 25) /* Bleeding */ + || iConds & (1 << 27); /* Milked */ + //|| iConds & (1 << 123) /* Gassed */ + + constexpr float fSpyAttackAfterCloakTime = 0.5f; + const float fSpyLastUncloakedTime = engine->Time() - m_fSpyLastUncloakedList[entIndex]; + + // Don't update last uncloaked time if there isn't anything exposing the spy in his cloaked + // state + if (!bExposedCloaked) + bIsInvisible = true; + // Destroy the cloaked spy if he either: + // - Ran out of cloak, got damaged or touched an enemy (revealing him temporarily) + // - Is on fire, coating in something or bleeding + // - Just cloaked within fSpyAttackAfterCloakTime seconds & is not using dead ringer + bValid = bExposedCloaked + || (fSpyLastUncloakedTime < fSpyAttackAfterCloakTime && !(iConds & (1 << 13))); + + //TODO: Stable tests on TF2 conditions + if ((CTeamFortress2Mod::isMapType(TF_MAP_ZI) || CTeamFortress2Mod::isMapType(TF_MAP_SAXTON)) && + (CTF2Conditions::TF2_IsPlayerInCondition(entIndex, TFCond_Kritzkrieged) || + CTF2Conditions::TF2_IsPlayerInCondition(entIndex, TFCond_Buffed))) //Buff exposes invisibility - RussiaTails { - // if I saw my team mate shoot him within the last 5 seconds, he's a spy! - // or no spies on team that can do this! - bValid = (fSpyAttackTime < 5.0f) || !isClassOnTeam(TF_CLASS_SPY,getTeam()); + bIsInvisible = false; } + + } + else if ( dTeam == 0 ) // not disguised + { + bValid = true; } - else if ( dteam == 0 ) // not disguised + else if ( dTeam != getTeam() ) { bValid = true; + bFoundSpy = false; // disguised as enemy! } - else if ( dteam != getTeam() ) + else if ( dIndex == ENTINDEX(m_pEdict)) // if he is disguised as me -- he must be a spy! { bValid = true; - bfoundspy = false; // disguised as enemy! } - else if ( dindex == ENTINDEX(m_pEdict) ) // if he is disguised as me -- he must be a spy! + else if (CTeamFortress2Mod::isMapType(TF_MAP_ZI)) // in Zombie Infection, spy's diguise uses a normal player model (with weapons) instead of Voodoo-Cursed Soul - RussiaTails { bValid = true; } - else if ( !isClassOnTeam(dclass,getTeam()) ) + else if ( !isClassOnTeam(dClass,getTeam())) {// be smart - check if player disguised as a class that exists on my team bValid = true; } - else if ( dhealth <= 0 ) + else if ( dHealth <= 0 ) { // be smart - check if player's health is below 0 bValid = true; @@ -7554,20 +7895,22 @@ bool CBotTF2 :: isEnemy ( edict_t *pEdict,bool bCheckWeapons ) bValid = true; } else - bValid = thinkSpyIsEnemy(pEdict,(TF_Class)dclass); + bValid = thinkSpyIsEnemy(pEdict, static_cast(dClass)); + if (bValid && !bIsInvisible) + m_fSpyLastUncloakedList[entIndex] = engine->Time(); - if ( bValid && bCheckWeapons && bfoundspy ) - foundSpy(pEdict,(TF_Class)dclass); + if (bValid && bCheckWeapons && bFoundSpy) + foundSpy(pEdict, static_cast(dClass)); } //if ( CTeamFortress2Mod::TF2_IsPlayerDisguised(pEdict) || CTeamFortress2Mod::TF2_IsPlayerCloaked(pEdict) ) // bValid = false; } - else if ( ( m_iClass == TF_CLASS_ENGINEER ) && ( m_pSentryGun.get() != NULL ) ) + else if ( ( m_iClass == TF_CLASS_ENGINEER ) && ( m_pSentryGun.get() != nullptr) ) { edict_t *pSentryEnemy = CClassInterface::getSentryEnemy(m_pSentryGun); - if ( pSentryEnemy == NULL ) + if ( pSentryEnemy == nullptr ) bValid = true; // attack else if ( pSentryEnemy == pEdict ) { @@ -7582,27 +7925,135 @@ bool CBotTF2 :: isEnemy ( edict_t *pEdict,bool bCheckWeapons ) else bValid = true; } + if (CTeamFortress2Mod::isMapType(TF_MAP_GG)) + { + if (CBotGlobals::getTeam(pEdict) == getTeam()) + return true; + } + if (std::strncmp(szmapname, "koth_lakeside_event", 19) == 0 || std::strncmp(szmapname, "koth_viaduct_event", 18) == 0) + { + if (CTeamFortress2Mod::isBossSummoned()) + { + if (CBotGlobals::getTeam(pEdict) != getTeam()) + { + bValid = false; + } + } + /*else if (!CTeamFortress2Mod::isBossSummoned()) + { + if (CBotGlobals::getTeam(pEdict) != getTeam() || CTeamFortress2Mod::isSentry(pEdict, iEnemyTeam) || + CTeamFortress2Mod::isDispenser(pEdict, iEnemyTeam) || + CTeamFortress2Mod::isTeleporter(pEdict, iEnemyTeam)) + { + bValid = true; + } + }*/ + } + /*if (mp_friendlyfire.GetInt() == 1) + { + if (CBotGlobals::getTeam(pEdict) == getTeam()) + return true; + } + if (mp_friendlyfire.GetInt() == 0) + { + if (CBotGlobals::getTeam(pEdict) == getTeam()) + return false; + }*/ //Doesn't work } - else if ( CTeamFortress2Mod::isMapType(TF_MAP_RD) && !strcmp(pEdict->GetClassName(),"tf_robot_destruction_robot") && (CClassInterface::getTeam(pEdict) != m_iTeam) ) + // TODO: to allow bots to properly attack RD Robots [APG]RoboCop[CL] + else if ( (CTeamFortress2Mod::isMapType(TF_MAP_RD) || CTeamFortress2Mod::isMapType(TF_MAP_CTF)) && !std::strcmp(pEdict->GetClassName(),"tf_robot_destruction_robot") && (CClassInterface::getTeam(pEdict) != m_iTeam)) { bValid = true; } - else if ( CTeamFortress2Mod::isBoss(pEdict) ) + else if (!std::strcmp(pEdict->GetClassName(), "tf_zombie") && (CClassInterface::getTeam(pEdict) != m_iTeam)) + { + bValid = true; + } + else if ((std::strncmp(szmapname, "koth_bound_event_rc3a", 21) == 0) && !std::strcmp(pEdict->GetClassName(), "func_breakable") && (CClassInterface::getTeam(pEdict) != m_iTeam)) + { + bValid = true; + } + else if ((std::strncmp(szmapname, "cp_fnaf_rc1", 11) == 0) && !std::strcmp(pEdict->GetClassName(), "func_breakable") && (CClassInterface::getTeam(pEdict) != m_iTeam)) + { + bValid = true; + } + else if ((CTeamFortress2Mod::isMapType(TF_MAP_PIPEBALL)) && !std::strcmp(pEdict->GetClassName(), "func_physbox") && (CClassInterface::getTeam(pEdict) != m_iTeam)) + { + bValid = true; + if (bValid) + { + m_pSchedules->freeMemory(); + setMoveTo(CBotGlobals::entityOrigin(pEdict)); + setLookAtTask(LOOK_EDICT); + } + } + else if ((std::strncmp(szmapname, "ctf_pressure", 12) == 0) && !std::strcmp(pEdict->GetClassName(), "generic_actor") && (CClassInterface::getTeam(pEdict) != m_iTeam)) + { + bValid = true; + } + else if ((CTeamFortress2Mod::isMapType(TF_MAP_CTF) || CTeamFortress2Mod::isMapType(TF_MAP_RD)) && !std::strcmp(pEdict->GetClassName(), "item_bonuspack") && (CClassInterface::getTeam(pEdict) != m_iTeam)) + { + bValid = false; + if (!bValid) + { + m_pSchedules->freeMemory(); + setMoveTo(CBotGlobals::entityOrigin(pEdict)); + setLookAtTask(LOOK_EDICT); + } + } + else if ((std::strncmp(szmapname, "slendytubbies", 13) == 0) && !std::strcmp(pEdict->GetClassName(), "tf_bonus_duck_pickup") && (CClassInterface::getTeam(pEdict) != m_iTeam)) + { + bValid = true; + if (bValid) + { + m_pSchedules->freeMemory(); + setMoveTo(CBotGlobals::entityOrigin(pEdict)); + setLookAtTask(LOOK_EDICT); + } + } + else if ((std::strncmp(szmapname, "slendytubbies", 13) == 0) && !std::strcmp(pEdict->GetClassName(), "base_boss") && (CClassInterface::getTeam(pEdict) != m_iTeam)) + { + bValid = true; + if (bValid) + { + m_fAvoidTime = engine->Time() + 9999.0f; + } + } + else if (CTeamFortress2Mod::isBoss(pEdict)) { bIsBoss = bValid = true; + if (std::strcmp(pEdict->GetClassName(), "merasmus") == 0) + { + //TODO: Stable tests on TF2 conditions + const int edictIndex = engine->IndexOfEdict(getEdict()); + if ((CTF2Conditions::TF2_IsPlayerInCondition(edictIndex, TFCond_HalloweenBombHead))) + { + m_pSchedules->freeMemory(); + setMoveTo(CBotGlobals::entityOrigin(pEdict)); + setLookAtTask(LOOK_EDICT); + } + } } // "FrenzyTime" is the time it takes for the bot to check out where he got hurt else if ( (m_iClass != TF_CLASS_SPY) || (m_fFrenzyTime > engine->Time()) ) { - iEnemyTeam = CTeamFortress2Mod::getEnemyTeam(getTeam()); + const int iEnemyTeam = CTeamFortress2Mod::getEnemyTeam(getTeam()); // don't attack sentries if spy, just sap them - if ( ((m_iClass != TF_CLASS_SPY) && CTeamFortress2Mod::isSentry(pEdict,iEnemyTeam)) || + if ( (m_iClass != TF_CLASS_SPY) && (CTeamFortress2Mod::isSentry(pEdict,iEnemyTeam) || CTeamFortress2Mod::isDispenser(pEdict,iEnemyTeam) || - CTeamFortress2Mod::isTeleporter(pEdict,iEnemyTeam) - /*CTeamFortress2Mod::isTeleporterExit(pEdict,iEnemyTeam)*/ ) + CTeamFortress2Mod::isTeleporter(pEdict,iEnemyTeam)) + /*CTeamFortress2Mod::isTeleporterExit(pEdict,iEnemyTeam)*/ ) { - bValid = true; + if (std::strncmp(szmapname, "koth_lakeside_event", 19) == 0 || std::strncmp(szmapname, "koth_viaduct_event", 18) == 0) + { + if (CTeamFortress2Mod::isBossSummoned()) + { + bValid = false; + } + } + else + bValid = true; } else if ( CTeamFortress2Mod::isPipeBomb ( pEdict, iEnemyTeam ) ) bIsPipeBomb = bValid = true; @@ -7616,23 +8067,20 @@ bool CBotTF2 :: isEnemy ( edict_t *pEdict,bool bCheckWeapons ) { if ( bCheckWeapons ) { - CBotWeapon *pWeapon = m_pWeapons->getBestWeapon(pEdict); + const CBotWeapon *pWeapon = m_pWeapons->getBestWeapon(pEdict); - if ( pWeapon == NULL ) + if ( pWeapon == nullptr) { return false; } - else - { - if ( bIsPipeBomb && !pWeapon->canDestroyPipeBombs() ) - return false; - else if ( bIsRocket && !pWeapon->canDeflectRockets() ) - return false; - else if ( bIsGrenade && !pWeapon->canDeflectRockets() ) - return false; - else if ( bIsBoss && pWeapon->isMelee() ) - return false; - } + if ( bIsPipeBomb && !pWeapon->canDestroyPipeBombs() ) + return false; + if ( bIsRocket && !pWeapon->canDeflectRockets() ) + return false; + if ( bIsGrenade && !pWeapon->canDeflectRockets() ) + return false; + if ( bIsBoss && pWeapon->isMelee() ) + return false; } return true; @@ -7641,10 +8089,8 @@ bool CBotTF2 :: isEnemy ( edict_t *pEdict,bool bCheckWeapons ) return false; } - //////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////// // FORTRESS FOREVER @@ -7675,20 +8121,20 @@ void CBotTF2::MannVsMachineWaveComplete() m_pSchedules->freeMemory(); m_fLastKnownTeamFlagTime = 0.0f; - m_pPrevSpy = NULL; + m_pPrevSpy = nullptr; flagReset(); teamFlagReset(); m_pNavigator->clear(); - setLastEnemy(NULL); + setLastEnemy(nullptr); reload(); - if (m_pSentryGun.get() != NULL) + if (m_pSentryGun.get() != nullptr) { - CWaypoint *pBest = CTeamFortress2Mod::getBestWaypointMVM(this, CWaypointTypes::W_FL_SENTRY); + const CWaypoint *pBest = CTeamFortress2Mod::getBestWaypointMVM(this, CWaypointTypes::W_FL_SENTRY); if (!pBest || (pBest->distanceFrom(CBotGlobals::entityOrigin(m_pSentryGun)) > 768)) { @@ -7697,39 +8143,36 @@ void CBotTF2::MannVsMachineWaveComplete() m_fDispenserPlaceTime = 1.0f; m_fLastSentryEnemyTime = 0.0f; m_iSentryKills = 0; - m_fDispenserHealAmount = 0; + m_fDispenserHealAmount = 0.0f; } } } -void CBotTF2::MannVsMachineAlarmTriggered(Vector vLoc) +void CBotTF2::MannVsMachineAlarmTriggered(const Vector& vLoc) { if (m_iClass == TF_CLASS_ENGINEER) { edict_t *pSentry; - if ((pSentry = m_pSentryGun.get()) != NULL) + if ((pSentry = m_pSentryGun.get()) != nullptr) { if (CTeamFortress2Mod::getSentryLevel(pSentry) < 3) { return; } - else + if ((m_fLastSentryEnemyTime + 5.0f) > engine->Time()) { - if ((m_fLastSentryEnemyTime + 5.0f) > engine->Time()) - { - CWaypoint *pWaypoint = CTeamFortress2Mod::getBestWaypointMVM(this, CWaypointTypes::W_FL_SENTRY); + const CWaypoint *pWaypoint = CTeamFortress2Mod::getBestWaypointMVM(this, CWaypointTypes::W_FL_SENTRY); - Vector vSentry = CBotGlobals::entityOrigin(pSentry); + const Vector vSentry = CBotGlobals::entityOrigin(pSentry); - float fDist = pWaypoint->distanceFrom(vSentry); + const float fDist = pWaypoint->distanceFrom(vSentry); - if (fDist > 1024.0f) - { - // move sentry - m_iSentryKills = 0; - m_fSentryPlaceTime = 1.0f; - } + if (fDist > 1024.0f) + { + // move sentry + m_iSentryKills = 0; + m_fSentryPlaceTime = 1.0f; } } @@ -7740,7 +8183,7 @@ void CBotTF2::MannVsMachineAlarmTriggered(Vector vLoc) return; } - float fDefTime = randomFloat(10.0f, 20.0f); + const float fDefTime = randomFloat(10.0f, 20.0f); m_fDefendTime = engine->Time() + fDefTime + 1.0f; @@ -7752,9 +8195,13 @@ void CBotTF2::MannVsMachineAlarmTriggered(Vector vLoc) } // Go back to Cap/Flag to -void CBotTF2 :: enemyAtIntel ( Vector vPos, int type, int iArea ) +void CBotTF2 :: enemyAtIntel ( Vector vPos, const int type, const int iArea ) { + + const string_t mapname = gpGlobals->mapname; + const char* szmapname = mapname.ToCStr(); + if ( m_pSchedules->getCurrentSchedule() ) { if ( m_pSchedules->getCurrentSchedule()->isID(SCHED_RETURN_TO_INTEL) ) @@ -7764,7 +8211,7 @@ void CBotTF2 :: enemyAtIntel ( Vector vPos, int type, int iArea ) } } - if ( CBotGlobals::entityIsValid(m_pDefendPayloadBomb) && (CTeamFortress2Mod::isMapType(TF_MAP_CART)||CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE)) ) + if ( CBotGlobals::entityIsValid(m_pDefendPayloadBomb) && (CTeamFortress2Mod::isMapType(TF_MAP_CART)||CTeamFortress2Mod::isMapType(TF_MAP_CPPL)||CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE)||(std::strncmp(szmapname, "sd_offload", 10) == 0) || (std::strncmp(szmapname, "koth_namicott", 13) == 0) || (std::strncmp(szmapname, "ctf_system", 10) == 0) || (std::strncmp(szmapname, "cp_helmsdeep_v2", 15) == 0)) ) { vPos = CBotGlobals::entityOrigin(m_pDefendPayloadBomb); } @@ -7774,12 +8221,12 @@ void CBotTF2 :: enemyAtIntel ( Vector vPos, int type, int iArea ) if ( ( m_iTrapType != TF_TRAP_TYPE_POINT ) || (iArea == m_iTrapCPIndex) ) { // Stickies at PL Capture or bomb point - if ( (( m_iTrapType == TF_TRAP_TYPE_POINT ) || ( m_iTrapType == TF_TRAP_TYPE_PL )) && ( CTeamFortress2Mod::isMapType(TF_MAP_CART) || CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE)) ) + if ( (( m_iTrapType == TF_TRAP_TYPE_POINT ) || ( m_iTrapType == TF_TRAP_TYPE_PL )) && ( CTeamFortress2Mod::isMapType(TF_MAP_CART) || CTeamFortress2Mod::isMapType(TF_MAP_CPPL) || CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE)||(std::strncmp(szmapname, "sd_offload", 10) == 0) || (std::strncmp(szmapname, "koth_namicott", 13) == 0) || (std::strncmp(szmapname, "ctf_system", 10) == 0) || (std::strncmp(szmapname, "cp_helmsdeep_v2", 15) == 0)) ) { edict_t *pBomb; // get enemy pl bomb - if ( (pBomb=m_pDefendPayloadBomb.get()) != NULL ) + if ( (pBomb=m_pDefendPayloadBomb.get()) != nullptr) { if ( (m_vStickyLocation-CBotGlobals::entityOrigin(pBomb)).Length() < (BLAST_RADIUS*2) ) detonateStickies(); @@ -7807,7 +8254,7 @@ void CBotTF2 :: enemyAtIntel ( Vector vPos, int type, int iArea ) if ( m_iClass == TF_CLASS_ENGINEER ) return; // got work to do... - if ((distanceFrom(vPos) < 768.0f) && (CTeamFortress2Mod::isMapType(TF_MAP_CP) || CTeamFortress2Mod::isMapType(TF_MAP_KOTH))) + if ((distanceFrom(vPos) < 768.0f) && (CTeamFortress2Mod::isMapType(TF_MAP_CP) || std::strncmp(szmapname, "ctf_chouhen", 11) == 0 || std::strncmp(szmapname, "ctf_haarp", 9) == 0 || std::strncmp(szmapname, "ctf_vector", 10) == 0 || std::strncmp(szmapname, "ctf_snowdrift", 13) == 0 || CTeamFortress2Mod::isMapType(TF_MAP_CPPL) || CTeamFortress2Mod::isMapType(TF_MAP_KOTH))) { m_vListenPosition = vPos; m_bListenPositionValid = true; @@ -7815,17 +8262,21 @@ void CBotTF2 :: enemyAtIntel ( Vector vPos, int type, int iArea ) m_fLookSetTime = m_fListenTime; setLookAtTask(LOOK_NOISE); } - - + // bot is already capturing a point if ( m_pSchedules && m_pSchedules->isCurrentSchedule(SCHED_ATTACKPOINT) ) { // already attacking a point - int capindex = CTeamFortress2Mod::m_ObjectiveResource.m_WaypointAreaToIndexTranslation[m_iCurrentAttackArea]; + const int capindex = CTeamFortress2Mod::m_ObjectiveResource.m_WaypointAreaToIndexTranslation[m_iCurrentAttackArea]; if ( capindex >= 0 ) { - Vector vCapAttacking = CTeamFortress2Mod::m_ObjectiveResource.getControlPointWaypoint(capindex); + //caxanga334: SDK 2013 doesn't like to create a Vector from an int + //#if SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_BMS || SOURCE_ENGINE == SE_TF2 + const Vector vCapAttacking = Vector(static_cast(CTeamFortress2Mod::m_ObjectiveResource.getControlPointWaypoint(capindex))); + //#else + //const Vector vCapAttacking = Vector(static_cast(CTeamFortress2Mod::m_ObjectiveResource.getControlPointWaypoint(capindex))); + //#endif if ( distanceFrom(vPos) > distanceFrom(vCapAttacking) ) return; @@ -7852,15 +8303,15 @@ void CBotTF2 :: enemyAtIntel ( Vector vPos, int type, int iArea ) // everyone go back to cap point unless doing something important if ( (type == EVENT_CAPPOINT) || (!m_pNavigator->hasNextPoint() || ((m_pNavigator->getGoalOrigin()-getOrigin()).Length() > ((vPos-getOrigin()).Length()))) ) { - dataUnconstArray *failed; + WaypointList *failed; m_pNavigator->getFailedGoals(&failed); - CWaypoint *pWpt = NULL; + CWaypoint *pWpt = nullptr; int iIgnore = -1; if ( (iArea >=0 ) && (iArea < MAX_CONTROL_POINTS) ) { // get control point waypoint - int iWpt = CTeamFortress2Mod::m_ObjectiveResource.getControlPointWaypoint(iArea); + const int iWpt = CTeamFortress2Mod::m_ObjectiveResource.getControlPointWaypoint(iArea); pWpt = CWaypoints::getWaypoint(iWpt); if ( pWpt && !pWpt->checkReachable() ) @@ -7872,8 +8323,8 @@ void CBotTF2 :: enemyAtIntel ( Vector vPos, int type, int iArea ) } - if ( pWpt == NULL ) - pWpt = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(vPos,400,iIgnore,false,false,true,failed,false,getTeam(),true)); + if ( pWpt == nullptr) + pWpt = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(vPos,400.0f,iIgnore,false,false,true,failed,false,getTeam(),true)); if ( pWpt ) { @@ -7884,13 +8335,10 @@ void CBotTF2 :: enemyAtIntel ( Vector vPos, int type, int iArea ) m_fDefendTime = engine->Time() + randomFloat(10.0f,20.0f); } } - } -void CBotTF2 :: buildingSapped ( eEngiBuild building, edict_t *pSapper, edict_t *pSpy ) +void CBotTF2 :: buildingSapped (const eEngiBuild building, edict_t *pSapper, edict_t *pSpy) { - static edict_t *pBuilding; - m_pSchedules->freeMemory(); if ( isVisible(pSpy) ) @@ -7899,6 +8347,7 @@ void CBotTF2 :: buildingSapped ( eEngiBuild building, edict_t *pSapper, edict_t } else { + static edict_t *pBuilding; pBuilding = CTeamFortress2Mod::getBuilding(building,m_pEdict); if ( pBuilding ) @@ -7910,75 +8359,83 @@ void CBotTF2 :: buildingSapped ( eEngiBuild building, edict_t *pSapper, edict_t //m_pPrevSpy = pSpy; } - - } -void CBotTF2 :: sapperDestroyed ( edict_t *pSapper ) +void CBotTF2 :: sapperDestroyed ( edict_t *pSapper ) const { m_pSchedules->freeMemory(); } -CBotTF2::CBotTF2() -{ - CBotFortress(); - m_iDesiredResistType = 0; - m_pHat = NULL; - m_pMisc = NULL; - m_pSecondary = NULL; - m_pPrimary = NULL; - m_pMelee = NULL; - m_pVTable = m_pVTable_Attributes = NULL; - m_bHatEquipped = false; - m_fEquipHatTime = 0.0f; - m_fDispenserPlaceTime = 0.0f; - m_fDispenserHealAmount = 0.0f; - m_fTeleporterEntPlacedTime = 0; - m_fTeleporterExtPlacedTime = 0; - m_iTeleportedPlayers = 0; - m_fDoubleJumpTime = 0; - m_fSpySapTime = 0; - m_iCurrentDefendArea = 0; - m_iCurrentAttackArea = 0; - //m_bBlockPushing = false; - //m_fBlockPushTime = 0; - m_pDefendPayloadBomb = NULL; - m_pPushPayloadBomb = NULL; - m_pRedPayloadBomb = NULL; - m_pBluePayloadBomb = NULL; - - m_iTrapType = TF_TRAP_TYPE_NONE; - m_pLastEnemySentry = MyEHandle(NULL); - m_prevSentryHealth = 0; - m_prevDispHealth = 0; - m_prevTeleExtHealth = 0; - m_prevTeleEntHealth = 0; - m_fHealClickTime = 0; - m_fCheckHealTime = 0; - - m_fAttackPointTime = 0; // used in cart maps +CBotTF2::CBotTF2() : m_vStickyLocation(), m_nextVoicecmd() +{ + //CBotFortress(); + //m_nextVoicecmd(); + m_iMvMUpdateTime = 0; + m_iDesiredResistType = 0; + m_pVTable = nullptr; + m_fDispenserPlaceTime = 0.0f; + m_fDispenserHealAmount = 0.0f; + m_fTeleporterEntPlacedTime = 0.0f; + m_fTeleporterExtPlacedTime = 0.0f; + m_iTeleportedPlayers = 0; + + m_fDoubleJumpTime = 0.0f; + m_fSpySapTime = 0.0f; + m_iCurrentDefendArea = 0; + m_iCurrentAttackArea = 0; + + //m_bBlockPushing = false; + //m_fBlockPushTime = 0; + + m_pDefendPayloadBomb = nullptr; + m_pPushPayloadBomb = nullptr; + m_pRedPayloadBomb = nullptr; + m_pBluePayloadBomb = nullptr; + + m_iTrapType = TF_TRAP_TYPE_NONE; + m_pLastEnemySentry = MyEHandle(nullptr); + m_fHealClickTime = 0.0f; + m_fCheckHealTime = 0.0f; + + m_iTrapCPIndex = 0; + m_fRemoveSapTime = 0.0f; + m_fRevMiniGunTime = 0.0f; + m_fNextRevMiniGunTime = 0.0f; + m_fRevMiniGunBelief = 0.0f; + m_fCloakBelief = 0.0f; + + m_bIsCarryingTeleExit = false; + m_bIsCarryingSentry = false; + m_bIsCarryingDisp = false; + m_bIsCarryingTeleEnt = false; + m_bIsCarryingObj = false; + m_fCarryTime = 0.0f; + m_fCheckNextCarrying = 0.0f; + m_fUseBuffItemTime = 0.0f; + + m_fAttackPointTime = 0.0f; // used in cart maps - m_prevSentryHealth = 0; - m_prevDispHealth = 0; - m_prevTeleExtHealth = 0; - m_prevTeleEntHealth = 0; + m_prevSentryHealth = 0; + m_prevDispHealth = 0; + m_prevTeleExtHealth = 0; + m_prevTeleEntHealth = 0; - m_iSentryArea = 0; - m_iDispenserArea = 0; - m_iTeleEntranceArea = 0; - m_iTeleExitArea = 0; + m_iSentryArea = 0; + m_iDispenserArea = 0; + m_iTeleEntranceArea = 0; + m_iTeleExitArea = 0; - for ( unsigned int i = 0; i < 10; i ++ ) - m_fClassDisguiseFitness[i] = 1.0f; + for (float& m_fClassDisguiseFit : m_fClassDisguiseFitness) + m_fClassDisguiseFit = 1.0f; - memset(m_fClassDisguiseTime,0,sizeof(float)*10); + std::memset(m_fClassDisguiseTime, 0, sizeof(float) * 10); } -void CBotTF2 ::init(bool bVarInit) +void CBotTF2 ::init(const bool bVarInit) { if( bVarInit ) { - CBotTF2(); + //CBotTF2(); } CBotFortress::init(bVarInit); @@ -7990,7 +8447,7 @@ bool CBotFortress :: getIgnoreBox ( Vector *vLoc, float *fSize ) { edict_t *pSentry; - if ( (pSentry = m_pSentryGun.get()) != NULL ) + if ( (pSentry = m_pSentryGun.get()) != nullptr) { *vLoc = CBotGlobals::entityOrigin(pSentry); *fSize = pSentry->GetCollideable()->OBBMaxs().Length()/2; @@ -8001,7 +8458,7 @@ bool CBotFortress :: getIgnoreBox ( Vector *vLoc, float *fSize ) { edict_t *pSentry; - if ( (pSentry = m_pNearestEnemySentry.get()) != NULL ) + if ( (pSentry = m_pNearestEnemySentry.get()) != nullptr) { *vLoc = CBotGlobals::entityOrigin(pSentry); *fSize = pSentry->GetCollideable()->OBBMaxs().Length()/2; @@ -8012,12 +8469,6 @@ bool CBotFortress :: getIgnoreBox ( Vector *vLoc, float *fSize ) return false; } -CAttribute :: CAttribute ( const char *name, float fval ) -{ - m_name = CStrings::getString(name); - m_fval = fval; -} - CBotWeapon *CBotTF2::getCurrentWeapon() { edict_t *pWeapon = CClassInterface::TF2_getActiveWeapon(m_pEdict); @@ -8032,5 +8483,5 @@ CBotWeapon *CBotTF2::getCurrentWeapon() } } - return NULL; + return nullptr; } diff --git a/utils/RCBot2_meta/bot_fortress.h b/utils/RCBot2_meta/bot_fortress.h index 8336204e3..c79aa90c6 100644 --- a/utils/RCBot2_meta/bot_fortress.h +++ b/utils/RCBot2_meta/bot_fortress.h @@ -36,41 +36,58 @@ #include "bot_utility.h" //#include -//using namespace std; -#define TF2_ROCKETSPEED 1100 -#define TF2_GRENADESPEED 1065 // TF2 wiki -#define TF2_MAX_SENTRYGUN_RANGE 1024 -#define TF2_STICKYGRENADE_MAX_DISTANCE 1600 +enum : std::uint16_t +{ + TF2_ROCKETSPEED = 1100, + TF2_GRENADESPEED = 1065, + TF2_MAX_SENTRYGUN_RANGE = 1024, + TF2_STICKYGRENADE_MAX_DISTANCE = 1600 +}; class CBotWeapon; class CWaypoint; class CBotUtility; -#define TF2_SLOT_PRMRY 0 // primary -#define TF2_SLOT_SCNDR 1 // secondary -#define TF2_SLOT_MELEE 2 -#define TF2_SLOT_PDA 3 -#define TF2_SLOT_PDA2 4 -#define TF2_SLOT_HAT 5 -#define TF2_SLOT_MISC 6 -#define TF2_SLOT_ACTION 7 -#define TF2_SLOT_MAX 8 +enum : std::uint8_t +{ + TF2_SLOT_PRMRY = 0, // primary + TF2_SLOT_SCNDR = 1, // secondary + TF2_SLOT_MELEE = 2, + TF2_SLOT_PDA = 3, + TF2_SLOT_PDA2 = 4, + TF2_SLOT_HAT = 5, + TF2_SLOT_MISC = 6, + TF2_SLOT_ACTION = 7, + TF2_SLOT_MAX = 8 +}; -#define TF2_TEAM_BLUE 3 -#define TF2_TEAM_RED 2 +enum : std::uint8_t +{ + TF2_TEAM_BLUE = 3, + TF2_TEAM_RED = 2 +}; -#define RESIST_BULLETS 0 -#define RESIST_EXPLO 1 -#define RESIST_FIRE 2 +enum : std::uint8_t +{ + RESIST_BULLETS = 0, + RESIST_EXPLO = 1, + RESIST_FIRE = 2 +}; -#define TF2_SENTRY_LEVEL1_HEALTH 150 -#define TF2_SENTRY_LEVEL2_HEALTH 180 -#define TF2_SENTRY_LEVEL3_HEALTH 216 +enum : std::uint8_t +{ + TF2_SENTRY_LEVEL1_HEALTH = 150, + TF2_SENTRY_LEVEL2_HEALTH = 180, + TF2_SENTRY_LEVEL3_HEALTH = 216 +}; -#define TF2_DISPENSER_LEVEL1_HEALTH 150 -#define TF2_DISPENSER_LEVEL2_HEALTH 180 -#define TF2_DISPENSER_LEVEL3_HEALTH 216 +enum : std::uint8_t +{ + TF2_DISPENSER_LEVEL1_HEALTH = 150, + TF2_DISPENSER_LEVEL2_HEALTH = 180, + TF2_DISPENSER_LEVEL3_HEALTH = 216 +}; // Naris @ Alliedmodders.net /* @@ -178,53 +195,56 @@ enum TFCond TFCond_RuneAgility, };*/ -#define TF2_PLAYER_BONKED (1<<14) -#define TF2_PLAYER_SLOWED (1 << 0) // 1 -#define TF2_PLAYER_ZOOMED (1 << 1) // 2 -#define TF2_PLAYER_DISGUISING (1 << 2) // 4 -#define TF2_PLAYER_DISGUISED (1 << 3) // 8 -#define TF2_PLAYER_CLOAKED (1 << 4) // 16 -#define TF2_PLAYER_INVULN (1 << 5) // 32 -#define TF2_PLAYER_TELEGLOW (1 << 6) // 64 -#define TF2_PLAYER_KRITS 524288 -#define TF2_PLAYER_HEALING 2097152 -#define TF2_PLAYER_TAUNTING (1 << 7) // 128 -#define TF2_PLAYER_TELEPORTING (1<<10) // 1024 Player is teleporting -#define TF2_PLAYER_ONFIRE 4194304 // fix may 2013 +enum +{ + TF2_PLAYER_BONKED = 1<<14, + TF2_PLAYER_SLOWED = 1 << 0, // 1 + TF2_PLAYER_ZOOMED = 1 << 1, // 2 + TF2_PLAYER_DISGUISING = 1 << 2, // 4 + TF2_PLAYER_DISGUISED = 1 << 3, // 8 + TF2_PLAYER_CLOAKED = 1 << 4, // 16 + TF2_PLAYER_INVULN = 1 << 5, // 32 + TF2_PLAYER_TELEGLOW = 1 << 6, // 64 + TF2_PLAYER_KRITS = 524288, + TF2_PLAYER_HEALING = 2097152, + TF2_PLAYER_TAUNTING = 1 << 7, // 128 + TF2_PLAYER_TELEPORTING = 1<<10, // 1024 Player is teleporting + TF2_PLAYER_ONFIRE = 4194304 // fix may 2013 +}; //#define TF2_SPY_FOV_KNIFEATTACK 90.0f -typedef enum +typedef enum : std::uint8_t { - TF_VC_MEDIC = 0, + TF_VC_MEDIC = 0, TF_VC_INCOMING = 1, TF_VC_HELP = 2, - TF_VC_THANKS = 4, + TF_VC_THANKS = 4, TF_VC_SPY = 5, TF_VC_BATTLECRY = 6, - TF_VC_GOGOGO = 8, - TF_VC_SENTRYAHEAD = 9, + TF_VC_GOGOGO = 8, + TF_VC_SENTRYAHEAD = 9, TF_VC_CHEERS = 10, - TF_VC_MOVEUP = 12, - TF_VC_TELEPORTERHERE =13, - TF_VC_JEERS = 14, - TF_VC_GOLEFT = 16, - TF_VC_DISPENSERHERE = 17, + TF_VC_MOVEUP = 12, + TF_VC_TELEPORTERHERE = 13,//TODO: allow engineers to hearcommands [APG]RoboCop[CL] + TF_VC_JEERS = 14, + TF_VC_GOLEFT = 16, + TF_VC_DISPENSERHERE = 17,// TODO: allow engineers to hearcommands [APG]RoboCop[CL] TF_VC_POSITIVE = 18, - TF_VC_GORIGHT = 20, - TF_VC_SENTRYHERE = 21, - TF_VC_NEGATIVE = 22, - TF_VC_YES = 24, - TF_VC_ACTIVATEUBER = 25, - TF_VC_NICESHOT = 26, - TF_VC_NO = 28, - TF_VC_UBERREADY = 29, - TF_VC_GOODJOB = 30, + TF_VC_GORIGHT = 20, + TF_VC_SENTRYHERE = 21, + TF_VC_NEGATIVE = 22, + TF_VC_YES = 24, + TF_VC_ACTIVATEUBER = 25, + TF_VC_NICESHOT = 26, + TF_VC_NO = 28, + TF_VC_UBERREADY = 29, + TF_VC_GOODJOB = 30, TF_VC_INVALID = 31 }eTFVoiceCMD; -typedef enum +typedef enum : std::uint8_t { TF_TRAP_TYPE_NONE, TF_TRAP_TYPE_WPT, @@ -234,9 +254,27 @@ typedef enum TF_TRAP_TYPE_ENEMY }eDemoTrapType; -typedef enum +//TODO: To allow the proper slot# values to be used, +//the class names should be changed to the slot names [APG]RoboCop[CL] + +/*typedef enum +{ + TF_CLASS_UNDEFINED = 0, + TF_CLASS_SCOUT = 1, + TF_CLASS_SOLDIER = 2, + TF_CLASS_PYRO = 3, + TF_CLASS_DEMOMAN = 4, + TF_CLASS_HWGUY = 5, + TF_CLASS_MEDIC = 6, + TF_CLASS_ENGINEER = 7, + TF_CLASS_SNIPER = 8, + TF_CLASS_SPY = 9, + TF_CLASS_MAX = 10 +}TF_Class;*/ + +typedef enum : std::uint8_t { - TF_CLASS_CIVILIAN = 0, + TF_CLASS_UNDEFINED = 0, TF_CLASS_SCOUT, TF_CLASS_SNIPER, TF_CLASS_SOLDIER, @@ -266,7 +304,7 @@ typedef enum ENGI_SENTRY, ENGI_SAPPER }eEngiBuild;*/ -typedef enum +typedef enum : std::uint8_t { ENGI_DISP = 0, ENGI_TELE, @@ -276,7 +314,7 @@ typedef enum ENGI_ENTRANCE, }eEngiBuild; -typedef enum +typedef enum : std::uint8_t { ENGI_BUILD, ENGI_DESTROY @@ -285,9 +323,15 @@ typedef enum class CBotTF2FunctionEnemyAtIntel : public IBotFunction { public: - CBotTF2FunctionEnemyAtIntel( int iTeam, Vector vPos, int type, edict_t *pPlayer = NULL, int capindex = -1 ){m_iTeam = iTeam;m_vPos = vPos;m_iType = type; m_pPlayer = pPlayer; m_iCapIndex = capindex; } + CBotTF2FunctionEnemyAtIntel(const int iTeam, const Vector& vPos, const int type, edict_t* pPlayer = nullptr, const int capindex = -1) : m_vPos(vPos) + { + m_iTeam = iTeam; + m_iType = type; + m_pPlayer = pPlayer; + m_iCapIndex = capindex; + } - void execute (CBot *pBot); + void execute (CBot *pBot) override; private: int m_iTeam; Vector m_vPos; @@ -300,7 +344,7 @@ class CBroadcastSpySap : public IBotFunction { public: CBroadcastSpySap (edict_t *pSpy) { m_pSpy = pSpy; } - void execute ( CBot *pBot ); + void execute ( CBot *pBot ) override; private: edict_t *m_pSpy; @@ -309,15 +353,15 @@ class CBroadcastSpySap : public IBotFunction class CBroadcastOvertime : public IBotFunction { public: - CBroadcastOvertime () {}; - void execute (CBot *pBot); + CBroadcastOvertime () = default; + void execute (CBot *pBot) override; }; class CBroadcastFlagReturned : public IBotFunction { public: - CBroadcastFlagReturned (int iTeam) { m_iTeam = iTeam; } - void execute ( CBot *pBot ); + CBroadcastFlagReturned (const int iTeam) { m_iTeam = iTeam; } + void execute ( CBot *pBot ) override; private: int m_iTeam; @@ -326,8 +370,12 @@ class CBroadcastFlagReturned : public IBotFunction class CBroadcastFlagDropped : public IBotFunction { public: - CBroadcastFlagDropped (int iTeam, Vector origin) { m_iTeam = iTeam; m_vOrigin = origin; } - void execute ( CBot *pBot ); + CBroadcastFlagDropped(const int iTeam, const Vector& origin) + : m_vOrigin(origin), m_iTeam(iTeam) + { + } + + void execute ( CBot *pBot ) override; private: Vector m_vOrigin; @@ -337,9 +385,9 @@ class CBroadcastFlagDropped : public IBotFunction class CBroadcastFlagCaptured : public IBotFunction { public: - CBroadcastFlagCaptured(int iTeam) { m_iTeam = iTeam; } + CBroadcastFlagCaptured(const int iTeam) { m_iTeam = iTeam; } - void execute ( CBot *pBot ); + void execute ( CBot *pBot ) override; private: int m_iTeam; }; @@ -347,8 +395,8 @@ class CBroadcastFlagCaptured : public IBotFunction class CBroadcastRoundStart : public IBotFunction { public: - CBroadcastRoundStart ( bool bFullReset ) { m_bFullReset = bFullReset; } - void execute ( CBot *pBot ); + CBroadcastRoundStart (const bool bFullReset) { m_bFullReset = bFullReset; } + void execute ( CBot *pBot ) override; private: bool m_bFullReset; }; @@ -358,148 +406,19 @@ class CBroadcastCapturedPoint : public IBotFunction public: CBroadcastCapturedPoint ( int iPoint, int iTeam, const char *szName ); - void execute ( CBot *pBot ); + void execute ( CBot *pBot ) override; private: int m_iPoint; int m_iTeam; const char *m_szName; }; - -class CBasePlayer; - -template< class T, class I = int > -class CUtlMemoryTF2Items : public CUtlMemory< T, I > -{ -public: - CUtlMemoryTF2Items( int nGrowSize = 0, int nInitSize = 0 ) { CUtlMemory< T, I >( nGrowSize, nInitSize ); } - CUtlMemoryTF2Items( T* pMemory, int numElements ) { CUtlMemory< T, I >( pMemory, numElements ); } - CUtlMemoryTF2Items( const T* pMemory, int numElements ) { CUtlMemory< T, I >( pMemory, numElements ); } - //~CUtlMemoryTF2Items() { ~CUtlMemory< T, I >(); } - - void Purge() - { - if ( !CUtlMemory< T, I >::IsExternallyAllocated() ) - { - if (CUtlMemory< T, I >::m_pMemory) - { - UTLMEMORY_TRACK_FREE(); - //free( (void*)m_pMemory ); -#ifdef TF2ITEMS_DEBUG_ITEMS - META_CONPRINTF("CUtlMemory tried to be freed!\n"); -#endif - CUtlMemory< T, I >::m_pMemory = 0; - } - CUtlMemory< T, I >::m_nAllocationCount = 0; - } - } -}; - -// Taken from the TF2Items extension by Asher "asherkin" Baker -class CAttributeManager; - -class CEconItemAttribute -{ -public: - CEconItemAttribute() {}; - - CEconItemAttribute(uint16 iAttributeDefinitionIndex, float flValue/* = -1.0*/) - { - this->m_iAttributeDefinitionIndex = iAttributeDefinitionIndex; - this->m_flValue = flValue; - this->m_nRefundableCurrency = 0; - this->m_pVTable = NULL; - } - -public: - void *m_pVTable; - - uint16 m_iAttributeDefinitionIndex; - float m_flValue; - int32 m_nRefundableCurrency; -}; - -class CEconItem; - -class CEconItemHandle -{ -public: - void *m_pVTable; - - CEconItem *m_pItem; - - int64 m_ulItemID; - uint64 m_SteamID; -}; - -class CAttributeList -{ -public: - void *m_pVTable; - - CUtlVector > m_Attributes; - void *m_pAttributeManager; - - -public: - CAttributeList& operator=(const CAttributeList &other) - { - m_pVTable = other.m_pVTable; - - m_Attributes = other.m_Attributes; - m_pAttributeManager = other.m_pAttributeManager; - - - return *this; - } -}; - - -class ITexture; -class ITextureCompositor; -class CEconItemView +enum : std::uint8_t { -public: - void *m_pVTable; //0 - - uint16 m_iItemDefinitionIndex; //4 - - int32 m_iEntityQuality; //8 - uint32 m_iEntityLevel; //12 - - uint64 m_iItemID; //16 - uint32 m_iItemIDHigh; //24 - uint32 m_iItemIDLow; //28 - - uint32 m_iAccountID; //32 - - uint32 m_iInventoryPosition; //36 - - CEconItemHandle m_ItemHandle; //40 (44, 48, 52, 56, 60) - - bool m_bColorInit; //64 - bool m_bPaintOverrideInit; //65 - bool m_bHasPaintOverride; //66 - //67 - - float m_flOverrideIndex; //68 - uint32 m_unRGB; //72 - uint32 m_unAltRGB; //76 - - int32 m_iTeamNumber; //80 - - bool m_bInitialized; //84 - - CAttributeList m_AttributeList; //88 (92, 96, 100, 104, 108, 112) - CAttributeList m_NetworkedDynamicAttributesForDemos; //116 (120, 124, 128, 132, 136, 140) - - bool m_bDoNotIterateStaticAttributes; //144 + EVENT_FLAG_PICKUP = 0, + EVENT_CAPPOINT = 1 }; -#define EVENT_FLAG_PICKUP 0 -#define EVENT_CAPPOINT 1 - - class CBotFortress : public CBot { public: @@ -510,73 +429,73 @@ class CBotFortress : public CBot //virtual void wantToZoom ( bool bSet ) { m_bWantToZoom = bSet; } - virtual void enemyLost (edict_t *pEnemy); + void enemyLost (edict_t *pEnemy) override; - virtual void updateConditions(); + void updateConditions() override; - virtual void shot ( edict_t *pEnemy ); + void shot ( edict_t *pEnemy ) override; virtual int engiBuildObject ( int *iState, eEngiBuild iObject, float *fTime, int *iTries ); - virtual float getEnemyFactor ( edict_t *pEnemy ) { return CBot::getEnemyFactor(pEnemy); } + float getEnemyFactor ( edict_t *pEnemy ) override { return CBot::getEnemyFactor(pEnemy); } - virtual void checkDependantEntities(); + void checkDependantEntities() override; - int getMetal (); + int getMetal () const; //virtual Vector getAimVector ( edict_t *pEntity ) { return CBot::getAimVector(pEntity); } - virtual void modAim ( edict_t *pEntity, Vector &v_origin, Vector *v_desired_offset, Vector &v_size, float fDist, float fDist2D ) + void modAim ( edict_t *pEntity, Vector &v_origin, Vector *v_desired_offset, Vector &v_size, const float fDist, const float fDist2D ) override { CBot::modAim(pEntity,v_origin,v_desired_offset,v_size,fDist,fDist2D); } - virtual void touchedWpt ( CWaypoint *pWaypoint, int iNextWaypoint = -1, int iPrevWaypoint = -1 ) { CBot::touchedWpt(pWaypoint); } + void touchedWpt ( CWaypoint *pWaypoint, int iNextWaypoint = -1, int iPrevWaypoint = -1 ) override { CBot::touchedWpt(pWaypoint); } - inline edict_t *getHealingEntity () { return m_pHeal; } + edict_t *getHealingEntity () { return m_pHeal; } - inline void clearHealingEntity () { m_pHeal = NULL; } + void clearHealingEntity () { m_pHeal = nullptr; } - virtual unsigned int maxEntityIndex ( ) { return gpGlobals->maxEntities; } + unsigned maxEntityIndex () override { return gpGlobals->maxEntities; } - virtual void init (bool bVarInit=false); + void init (bool bVarInit=false) override; virtual void foundSpy (edict_t *pEdict, TF_Class iDisguise ); - virtual void getTasks ( unsigned int iIgnore = 0 ) { CBot :: getTasks(iIgnore); } + void getTasks (const unsigned iIgnore = 0) override { CBot :: getTasks(iIgnore); } - virtual void died ( edict_t *pKiller, const char *pszWeapon ); + void died ( edict_t *pKiller, const char *pszWeapon ) override; - virtual void killed ( edict_t *pVictim, char *weapon ); + void killed ( edict_t *pVictim, char *weapon ) override; - virtual void modThink (); + void modThink () override; - bool isBuilding ( edict_t *pBuilding ); + bool isBuilding (const edict_t *pBuilding ); float getHealFactor ( edict_t *pPlayer ); - virtual bool wantToFollowEnemy (); + bool wantToFollowEnemy () override; - virtual void checkBuildingsValid (bool bForce = false) {}; + virtual void checkBuildingsValid (bool bForce = false) {} virtual void checkHealingValid (); // linux fix 2 - virtual edict_t *findEngineerBuiltObject ( eEngiBuild iBuilding, int index ) { return NULL; } + virtual edict_t *findEngineerBuiltObject ( eEngiBuild iBuilding, int index ) { return nullptr; } - virtual void engineerBuild ( eEngiBuild iBuilding, eEngiCmd iEngiCmd ) {}; + virtual void engineerBuild ( eEngiBuild iBuilding, eEngiCmd iEngiCmd ) {} - virtual void spyDisguise ( int iTeam, int iClass ) {}; + virtual void spyDisguise (const int iTeam, const int iClass) {} virtual bool lookAfterBuildings (float *fTime) { return false; } - inline void nextLookAfterSentryTime ( float fTime ) { m_fLookAfterSentryTime = fTime; } + void nextLookAfterSentryTime (const float fTime) { m_fLookAfterSentryTime = fTime; } - inline edict_t *getSentry () { return m_pSentryGun; } + edict_t *getSentry () { return m_pSentryGun; } virtual bool hasEngineerBuilt ( eEngiBuild iBuilding ) {return false;} - virtual void engiBuildSuccess ( eEngiBuild iObject, int index ) {}; + virtual void engiBuildSuccess ( eEngiBuild iBuilding, int index ) {} virtual bool healPlayer ( edict_t *pPlayer, edict_t *pPrevPlayer ) { return false; } virtual bool upgradeBuilding ( edict_t *pBuilding, bool removesapper = false) {return false;} @@ -585,90 +504,90 @@ class CBotFortress : public CBot virtual bool isDisguised () { return false; } - virtual CBotWeapon *getCurrentWeapon() + CBotWeapon *getCurrentWeapon() override { return CBot::getCurrentWeapon(); } - virtual bool handleAttack(CBotWeapon *pWeapon, edict_t *pEnemy) { return CBot::handleAttack(pWeapon, pEnemy); } + bool handleAttack(CBotWeapon *pWeapon, edict_t *pEnemy) override { return CBot::handleAttack(pWeapon, pEnemy); } - void resetAttackingEnemy() { m_pAttackingEnemy = NULL; } + void resetAttackingEnemy() { m_pAttackingEnemy = nullptr; } - virtual bool setVisible ( edict_t *pEntity, bool bVisible ); + bool setVisible ( edict_t *pEntity, bool bVisible ) override; virtual void setClass ( TF_Class _class ); - inline edict_t *seeFlag ( bool reset = false ) { if ( reset ) { m_pFlag = NULL; } return m_pFlag; } + edict_t *seeFlag (const bool reset = false) { if ( reset ) { m_pFlag = nullptr; } return m_pFlag; } - virtual bool canAvoid ( edict_t *pEntity ); + bool canAvoid ( edict_t *pEntity ) override; - virtual bool isEnemy ( edict_t *pEdict,bool bCheckWeapons = true ); + bool isEnemy ( edict_t *pEdict,bool bCheckWeapons = true ) override; - virtual bool startGame (); + bool startGame () override; - virtual void spawnInit (); + void spawnInit () override; - bool isTF () { return true; } + bool isTF () override { return true; } - virtual bool isTF2 () { return false; } + bool isTF2 () override { return false; } - virtual bool hurt ( edict_t *pAttacker, int iHealthNow, bool bDontHide = false ) + bool hurt ( edict_t *pAttacker, const int iHealthNow, const bool bDontHide = false ) override { return CBot::hurt(pAttacker,iHealthNow,bDontHide); } void chooseClass (); - virtual TF_Class getClass () { return TF_CLASS_CIVILIAN; } + virtual TF_Class getClass () { return TF_CLASS_UNDEFINED; } - virtual void updateClass () { }; + virtual void updateClass () {} - virtual void currentlyDead (); + void currentlyDead () override; - virtual void onInventoryApplication (){} + void onInventoryApplication () override {} void pickedUpFlag (); - inline bool hasFlag () { return m_bHasFlag; } + bool hasFlag () const { return m_bHasFlag; } - inline void droppedFlag () { m_bHasFlag = false; } + void droppedFlag () { m_bHasFlag = false; } void medicCalled ( edict_t *pPlayer ); - bool isAlive (); + bool isAlive () override; - void enemyDown (edict_t *pEnemy) + void enemyDown (edict_t *pEnemy) override { CBot::enemyDown(pEnemy); if ( pEnemy == m_pPrevSpy ) { - m_pPrevSpy = NULL; + m_pPrevSpy = nullptr; m_fSeeSpyTime = 0.0f; } } - bool isTeleporterUseful ( edict_t *pTele ); + bool isTeleporterUseful ( edict_t *pTele ) const; bool waitForFlag ( Vector *vOrigin, float *fWait, bool bFindFlag ); - void flagDropped ( Vector vOrigin ); - void teamFlagDropped ( Vector vOrigin ); - void teamFlagPickup (); + void flagDropped (const Vector& vOrigin ); + void teamFlagDropped (const Vector& vOrigin ); + void teamFlagPickup () const; virtual bool wantToListenToPlayer ( edict_t *pPlayer, int iWeaponID = -1 ) { return true; } - virtual bool wantToListenToPlayerFootsteps ( edict_t *pPlayer ) { return true; } - virtual bool wantToInvestigateSound () { return true; } + bool wantToListenToPlayerFootsteps ( edict_t *pPlayer ) override { return true; } + bool wantToInvestigateSound () override { return true; } - inline void flagReset () { m_fLastKnownFlagTime = 0.0f; } - inline void teamFlagReset () { m_fLastKnownTeamFlagTime = 0.0f; } + void flagReset () { m_fLastKnownFlagTime = 0.0f; } + void teamFlagReset () { m_fLastKnownTeamFlagTime = 0.0f; } - virtual bool canGotoWaypoint ( Vector vPrevWaypoint, CWaypoint *pWaypoint, CWaypoint *pPrev = NULL ) + bool canGotoWaypoint (const Vector& vPrevWaypoint, CWaypoint* pWaypoint, CWaypoint* pPrev = nullptr) override { return CBot::canGotoWaypoint(vPrevWaypoint,pWaypoint,pPrev); } - virtual void setup (); + void setup () override; virtual bool needHealth(); @@ -678,17 +597,17 @@ class CBotFortress : public CBot void wantToDisguise ( bool bSet ); - virtual bool select_CWeapon ( CWeapon *pWeapon ) { return CBot::select_CWeapon(pWeapon); } - virtual bool selectBotWeapon ( CBotWeapon *pBotWeapon ) { return CBot::selectBotWeapon(pBotWeapon); } + bool select_CWeapon ( CWeapon *pWeapon ) override { return CBot::select_CWeapon(pWeapon); } + bool selectBotWeapon ( CBotWeapon *pBotWeapon ) override { return CBot::selectBotWeapon(pBotWeapon); } - virtual bool getIgnoreBox ( Vector *vLoc, float *fSize ); + bool getIgnoreBox ( Vector *vLoc, float *fSize ) override; // found a new enemy - virtual void enemyFound (edict_t *pEnemy){CBot::enemyFound(pEnemy); } + void enemyFound (edict_t *pEnemy) override {CBot::enemyFound(pEnemy); } bool wantToNest (); - bool overrideAmmoTypes () { return false; } + bool overrideAmmoTypes () override { return false; } bool wantToCloak(); @@ -701,22 +620,22 @@ class CBotFortress : public CBot void detectedAsSpy ( edict_t *pDetector, bool bDisguiseComprimised ); // return an enemy sentry gun / special visible (e.g.) for quick checking - virtual edict_t *getVisibleSpecial (); + edict_t *getVisibleSpecial () override; - inline bool isBeingHealed () { return m_bIsBeingHealed; } + bool isBeingHealed () const { return m_bIsBeingHealed; } - virtual void handleWeapons () { CBot::handleWeapons(); } + void handleWeapons () override { CBot::handleWeapons(); } - virtual void seeFriendlyDie ( edict_t *pDied, edict_t *pKiller, CWeapon *pWeapon ) { CBot::seeFriendlyDie(pDied,pKiller,pWeapon); } - virtual void seeFriendlyKill ( edict_t *pTeamMate, edict_t *pDied, CWeapon *pWeapon ) { CBot::seeFriendlyKill(pTeamMate,pDied,pWeapon); } + void seeFriendlyDie ( edict_t *pDied, edict_t *pKiller, CWeapon *pWeapon ) override { CBot::seeFriendlyDie(pDied,pKiller,pWeapon); } + void seeFriendlyKill ( edict_t *pTeamMate, edict_t *pDied, CWeapon *pWeapon ) override { CBot::seeFriendlyKill(pTeamMate,pDied,pWeapon); } - virtual void voiceCommand ( int cmd ) { }; + void voiceCommand (byte voiceCmd) override {} - virtual void seeFriendlyHurtEnemy ( edict_t *pTeammate, edict_t *pEnemy, CWeapon *pWeapon ); + void seeFriendlyHurtEnemy ( edict_t *pTeammate, edict_t *pEnemy, CWeapon *pWeapon ) override; bool incomingRocket ( float fRange ); - virtual void hearPlayerAttack( edict_t *pAttacker, int iWeaponID ) { CBot::hearPlayerAttack(pAttacker,iWeaponID); } + void hearPlayerAttack( edict_t *pAttacker, const int iWeaponID ) override { CBot::hearPlayerAttack(pAttacker,iWeaponID); } protected: virtual void selectTeam (); @@ -726,11 +645,11 @@ class CBotFortress : public CBot static bool isClassOnTeam ( int iClass, int iTeam ); - int getSpyDisguiseClass ( int iTeam ); + int getSpyDisguiseClass ( int iTeam ) const; virtual bool thinkSpyIsEnemy ( edict_t *pEdict, TF_Class iDisguise ); - virtual bool checkStuck ( void ) { return CBot::checkStuck(); } + bool checkStuck () override { return CBot::checkStuck(); } float m_fCallMedic; float m_fTauntTime; @@ -824,21 +743,23 @@ class CBotFortress : public CBot float m_fDisguiseTime; unsigned short m_iDisguiseClass; float m_fSentryPlaceTime; - unsigned int m_iSentryKills; + unsigned m_iSentryKills; float m_fTeleporterEntPlacedTime; float m_fTeleporterExtPlacedTime; unsigned m_iTeleportedPlayers; // list of spies who I saw were attacked by my team-mates recently // for use with spy checking - float m_fSpyList[MAX_PLAYERS]; + float m_fSpyAttackedList[RCBOT_MAXPLAYERS]; + // List of spies I saw cloak in front of me + float m_fSpyLastUncloakedList[RCBOT_MAXPLAYERS]; int m_iTeam; float m_fWaitTurnSentry; // amount of time to wait before engineer turns their sentry before building // currently unused - float m_fCallMedicTime[MAX_PLAYERS]; // for every player ID is kept the last time they called medic + float m_fCallMedicTime[RCBOT_MAXPLAYERS]; // for every player ID is kept the last time they called medic int m_iLastFailSentryWpt; int m_iLastFailTeleExitWpt; @@ -858,21 +779,6 @@ class CBotFortress : public CBot // // // -class CTF2Loadout; - -class CTF2LoadoutAdded -{ -public: - CTF2LoadoutAdded ( CBaseEntity *pEnt, CTF2Loadout *pLoadout ) - { - m_pEnt = pEnt; - m_loadout = pLoadout; - } - - CBaseEntity *m_pEnt; - CTF2Loadout *m_loadout; - -}; class CBotTF2 : public CBotFortress { @@ -881,21 +787,18 @@ class CBotTF2 : public CBotFortress // CBotTF2(); - virtual CBotWeapon *getCurrentWeapon(); + CBotWeapon *getCurrentWeapon() override; - void onInventoryApplication(); - - void giveWeapon ( int slot, int index ); - void PostGiveNamedItem ( CEconItemView *cscript ); + void onInventoryApplication() override; void MannVsMachineWaveComplete(); - void MannVsMachineAlarmTriggered (Vector vLoc); + void MannVsMachineAlarmTriggered (const Vector& vLoc); - bool sentryRecentlyHadEnemy (); + bool sentryRecentlyHadEnemy () const; - void highFivePlayer ( edict_t *pPlayer, float fYaw ); + void highFivePlayer ( edict_t *pPlayer, float fYaw ) const; - virtual bool hurt ( edict_t *pAttacker, int iHealthNow, bool bDontHide = false ); + bool hurt ( edict_t *pAttacker, int iHealthNow, bool bDontHide = false ) override; void updateAttackDefendPoints (); @@ -903,92 +806,92 @@ class CBotTF2 : public CBotFortress void updateDefendPoints (); // found a new enemy - void enemyFound (edict_t *pEnemy); + void enemyFound (edict_t *pEnemy) override; void enemyAtIntel ( Vector vPos, int type = EVENT_FLAG_PICKUP, int iArea = -1 ); - bool isTF2 () { return true; } + bool isTF2 () override { return true; } - void checkDependantEntities (); + void checkDependantEntities () override; - virtual bool wantToListenToPlayerAttack ( edict_t *pPlayer, int iWeaponID = -1 ); - virtual bool wantToListenToPlayerFootsteps ( edict_t *pPlayer ); + bool wantToListenToPlayerAttack ( edict_t *pPlayer, int iWeaponID = -1 ) override; + bool wantToListenToPlayerFootsteps ( edict_t *pPlayer ) override; - bool wantToInvestigateSound (); + bool wantToInvestigateSound () override; - void getDefendArea ( vector *m_iAreas ); + void getDefendArea ( std::vector *m_iAreas ); - void getAttackArea ( vector *m_iAreas ); + void getAttackArea ( std::vector *m_iAreas ); - int getCurrentAttackArea () { return m_iCurrentAttackArea; } - int getCurrentDefendArea () { return m_iCurrentDefendArea; } + int getCurrentAttackArea () const { return m_iCurrentAttackArea; } + int getCurrentDefendArea () const { return m_iCurrentDefendArea; } void pointsUpdated ( ); - eBotFuncState rocketJump(int *iState,float *fTime); + eBotFuncState rocketJump(int *iState,float *fTime); //TODO: not implemented? [APG]RoboCop[CL] - virtual bool wantToFollowEnemy (); + bool wantToFollowEnemy () override; void resetCloakTime () { m_fSpyCloakTime = 0.0f; } - float getEnemyFactor ( edict_t *pEnemy ); + float getEnemyFactor ( edict_t *pEnemy ) override; - void foundSpy (edict_t *pEdict, TF_Class iDisguise); + void foundSpy (edict_t *pEdict, TF_Class iDisguise) override; - void touchedWpt ( CWaypoint *pWaypoint, int iNextWaypoint = -1, int iPrevWaypoint = -1 ); + void touchedWpt ( CWaypoint *pWaypoint, int iNextWaypoint = -1, int iPrevWaypoint = -1 ) override; - bool handleAttack ( CBotWeapon *pWeapon, edict_t *pEnemy ); + bool handleAttack ( CBotWeapon *pWeapon, edict_t *pEnemy ) override; - void engiBuildSuccess ( eEngiBuild iObject, int index ); + void engiBuildSuccess ( eEngiBuild iBuilding, int index ) override; - bool lookAfterBuildings (float *fTime); + bool lookAfterBuildings (float *fTime) override; - void spawnInit (); + void spawnInit () override; - bool setVisible ( edict_t *pEntity, bool bVisible ); + bool setVisible ( edict_t *pEntity, bool bVisible ) override; //Vector getAimVector ( edict_t *pEntity ); - virtual void modAim ( edict_t *pEntity, Vector &v_origin, - Vector *v_desired_offset, Vector &v_size, - float fDist, float fDist2D); + void modAim ( edict_t *pEntity, Vector &v_origin, + Vector *v_desired_offset, Vector &v_size, + float fDist, float fDist2D) override; - void modThink (); + void modThink () override; - bool isCloaked (); + bool isCloaked () override; bool executeAction ( CBotUtility *util );//eBotAction id, CWaypoint *pWaypointResupply, CWaypoint *pWaypointHealth, CWaypoint *pWaypointAmmo ); - void setClass ( TF_Class _class ); + void setClass ( TF_Class _class ) override; - bool isDisguised (); + bool isDisguised () override; - void checkBuildingsValid (bool bForce = false); + void checkBuildingsValid (bool bForce = false) override; - edict_t *findEngineerBuiltObject ( eEngiBuild iBuilding, int index ); + edict_t *findEngineerBuiltObject ( eEngiBuild iBuilding, int index ) override; - bool isEnemy ( edict_t *pEdict,bool bCheckWeapons = true ); + bool isEnemy ( edict_t *pEdict,bool bCheckWeapons = true ) override; - bool isTF () { return true; } + bool isTF () override { return true; } void taunt ( bool bOverride = false ); - void callMedic (); + void callMedic () override; void roundReset (bool bFullReset); void pointCaptured ( int iPoint, int iTeam, const char *szPointName ); - void engineerBuild ( eEngiBuild iBuilding, eEngiCmd iEngiCmd ); + void engineerBuild ( eEngiBuild iBuilding, eEngiCmd iEngiCmd ) override; - void spyDisguise ( int iTeam, int iClass ); + void spyDisguise (int iTeam, int iClass) override; - bool hasEngineerBuilt ( eEngiBuild iBuilding ); + bool hasEngineerBuilt ( eEngiBuild iBuilding ) override; - void getTasks ( unsigned int iIgnore = 0 ); + void getTasks ( unsigned iIgnore = 0 ) override; - void died ( edict_t *pKiller, const char *pszWeapon ); + void died ( edict_t *pKiller, const char *pszWeapon ) override; - void killed ( edict_t *pVictim, char *weapon ); + void killed ( edict_t *pVictim, char *weapon ) override; void capturedFlag (); @@ -1000,57 +903,57 @@ class CBotTF2 : public CBotFortress void changeClass (); - virtual bool needAmmo(); + bool needAmmo() override; void buildingDestroyed ( int iType, edict_t *pAttacker, edict_t *pEdict ); - TF_Class getClass (); + TF_Class getClass () override; - void updateClass (); + void updateClass () override; - bool healPlayer ( ); + bool healPlayer ( edict_t* pPlayer, edict_t* pPrevPlayer ) override; - bool upgradeBuilding ( edict_t *pBuilding, bool removesapper = false ); + bool upgradeBuilding ( edict_t *pBuilding, bool removesapper = false ) override; - void setup (); + void setup () override; void buildingSapped ( eEngiBuild building, edict_t *pSapper, edict_t *pSpy ); - void sapperDestroyed ( edict_t *pSapper ); + void sapperDestroyed ( edict_t *pSapper ) const; - bool canGotoWaypoint ( Vector vPrevWaypoint, CWaypoint *pWaypoint, CWaypoint *pPrev = NULL ); + bool canGotoWaypoint (const Vector& vPrevWaypoint, CWaypoint* pWaypoint, CWaypoint* pPrev = nullptr) override; - bool deployStickies ( eDemoTrapType type, Vector vStand, Vector vLocation, Vector vSpread, Vector *vPoint, int *iState, int *iStickyNum, bool *bFail, float *fTime, int wptindex ); + bool deployStickies ( eDemoTrapType type, const Vector& vStand, const Vector& vLocation, const Vector& vSpread, Vector *vPoint, int *iState, int *iStickyNum, bool *bFail, float *fTime, int wptindex ); void detonateStickies (bool isJumping = false); - void setStickyTrapType ( Vector vLocation, eDemoTrapType iTrapType ) { m_vStickyLocation = vLocation; m_iTrapType = iTrapType; } + void setStickyTrapType (const Vector& vLocation, const eDemoTrapType iTrapType) { m_vStickyLocation = vLocation; m_iTrapType = iTrapType; } bool canDeployStickies (); - bool thinkSpyIsEnemy ( edict_t *pEdict, TF_Class iDisguise ); + bool thinkSpyIsEnemy ( edict_t *pEdict, TF_Class iDisguise ) override; - void seeFriendlyDie ( edict_t *pDied, edict_t *pKiller, CWeapon *pWeapon ); - void seeFriendlyKill ( edict_t *pTeamMate, edict_t *pDied, CWeapon *pWeapon ); + void seeFriendlyDie ( edict_t *pDied, edict_t *pKiller, CWeapon *pWeapon ) override; + void seeFriendlyKill ( edict_t *pTeamMate, edict_t *pDied, CWeapon *pWeapon ) override; - void voiceCommand ( int cmd ); + void voiceCommand (byte voiceCmd) override; - void handleWeapons ( void ) ; + void handleWeapons () override; - virtual bool select_CWeapon ( CWeapon *pWeapon ); - virtual bool selectBotWeapon ( CBotWeapon *pBotWeapon ); + bool select_CWeapon ( CWeapon *pWeapon ) override; + bool selectBotWeapon ( CBotWeapon *pBotWeapon ) override; - void checkStuckonSpy ( void ); + void checkStuckonSpy (); - bool checkStuck ( void ); + bool checkStuck () override; - void init (bool bVarInit=false); + void init (bool bVarInit=false) override; - bool checkAttackPoint ( void ); + bool checkAttackPoint (); - bool canAvoid ( edict_t *pEntity ); + bool canAvoid ( edict_t *pEntity ) override; - void hearVoiceCommand ( edict_t *pPlayer, byte cmd ); + void hearVoiceCommand ( edict_t *pPlayer, byte voiceCmd ) override; void checkBeingHealed ( ); @@ -1060,19 +963,20 @@ class CBotTF2 : public CBotFortress void healedPlayer ( edict_t *pPlayer, float fAmount ); - void teleportedPlayer ( void ); - - void upgradeWeapon(int iSlot); + void teleportedPlayer (); - inline bool isCarrying () { return m_bIsCarryingObj; } + bool isCarrying () const { return m_bIsCarryingObj; } void updateCarrying (); - inline void resetCarryTime () { m_fCarryTime = engine->Time(); } + void resetCarryTime () { m_fCarryTime = engine->Time(); } + + void MvM_Update(); // Mann vs Machine think function! - void MvM_Upgrade (); + bool MvM_IsReady() const; + + void MvM_Upgrade (); // TODO: To allow bots to menuselect in order to buy upgrades? [APG]RoboCop[CL] - //void addLoadoutWeapon ( CTF2Loadout *weap ); private: // time for next jump float m_fDoubleJumpTime; @@ -1133,38 +1037,26 @@ class CBotTF2 : public CBotFortress float m_fCarryTime; float m_fCheckNextCarrying; - float m_fEquipHatTime; - - bool m_bHatEquipped; - - //stack m_toApply; void *m_pVTable; - void *m_pVTable_Attributes; float m_fUseBuffItemTime; - CTF2Loadout *m_pHat; - CTF2Loadout *m_pMisc; - CTF2Loadout *m_pMelee; - CTF2Loadout *m_pPrimary; - CTF2Loadout *m_pSecondary; - int m_iDesiredResistType; - //dataStack m_LoadoutsApplyAttributes; + + int m_iMvMUpdateTime; // Tick based update time }; class CBotFF : public CBotFortress { public: + CBotFF() = default; - CBotFF() { CBotFortress(); } - - void modThink (); + void modThink() override; - bool isEnemy ( edict_t *pEdict,bool bCheckWeapons = true ); + bool isEnemy(edict_t* pEdict, bool bCheckWeapons = true) override; - bool isTF () { return true; } + bool isTF() override { return true; } }; diff --git a/utils/RCBot2_meta/bot_ga.cpp b/utils/RCBot2_meta/bot_ga.cpp index 591cd86a4..0f3fe4fdf 100644 --- a/utils/RCBot2_meta/bot_ga.cpp +++ b/utils/RCBot2_meta/bot_ga.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -35,132 +37,133 @@ #include "bot_ga.h" #include "bot_globals.h" +#include +#include -const int CGA :: g_iDefaultMaxPopSize = 16; -const float CGA :: g_fCrossOverRate = 0.7f; -const float CGA :: g_fMutateRate = 0.1f; -const float CGA :: g_fMaxPerturbation = 0.3f; +//caxanga334: SDK 2013 contains macros for std::min and std::max which causes errors when compiling +//#if SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_BMS +#include "valve_minmax_off.h" +//#endif + +#include "logging.h" + +const int CGA::g_iDefaultMaxPopSize = 16; +const float CGA::g_fCrossOverRate = 0.7f; +const float CGA::g_fMutateRate = 0.1f; +const float CGA::g_fMaxPerturbation = 0.3f; //////////////////// // POPULATION //////////////////// -IIndividual *CPopulation :: get ( int iIndex ) +IIndividual* CPopulation::get(const std::size_t iIndex) const { + if (iIndex >= m_theIndividuals.size()) + { + logger->Log(LogLevel::WARN, "GA Error: Index out of range"); + } return m_theIndividuals[iIndex]; } -void CPopulation :: add ( IIndividual *individual ) -{ - m_theIndividuals.push_back(individual); +void CPopulation::add(IIndividual* individual) +{ + m_theIndividuals.emplace_back(individual); } -void CPopulation :: freeMemory () +void CPopulation::freeMemory() { - for ( unsigned int i = 0; i < m_theIndividuals.size(); i ++ ) - delete m_theIndividuals[i]; - m_theIndividuals.clear(); } -void CPopulation :: clear () +void CPopulation::clear() { m_theIndividuals.clear(); } -ga_nn_value CPopulation :: totalFitness () +ga_nn_value CPopulation::totalFitness() const { float fTotalFitness = 0.0f; - for ( unsigned int i = 0; i < size(); i ++ ) + for (IIndividual* const& individual : m_theIndividuals) { - fTotalFitness += m_theIndividuals[i]->getFitness(); + fTotalFitness += individual->getFitness(); } return fTotalFitness; } -ga_nn_value CPopulation :: bestFitness () +ga_nn_value CPopulation::bestFitness() const { - float fFitness = 0.0f; - BOOL gotBestFitness = FALSE; - float fBestFitness = 0.0f; + float fBestFitness = std::numeric_limits::lowest(); - for ( unsigned int i = 0; i < size(); i ++ ) + for (IIndividual* const& individual : m_theIndividuals) { - fFitness = m_theIndividuals[i]->getFitness(); - - if ( !gotBestFitness || (fFitness > fBestFitness) ) - { - fBestFitness = fFitness; - gotBestFitness = TRUE; - } + fBestFitness = std::max(fBestFitness, individual->getFitness()); } return fBestFitness; } -ga_nn_value CPopulation :: averageFitness () +ga_nn_value CPopulation::averageFitness() const { - return totalFitness()/m_theIndividuals.size(); + return totalFitness() / static_cast(m_theIndividuals.size()); } -IIndividual *CPopulation :: pick () +std::unique_ptr CPopulation::pick() { - IIndividual *to_return = m_theIndividuals.back(); - + IIndividual* to_return = m_theIndividuals.back(); m_theIndividuals.pop_back(); - return to_return; + return std::unique_ptr(to_return); } //////////////////// // GENETIC ALGORITHM //////////////////// -CGA :: CGA (ISelection *selectFunction) : m_theSelectFunction (selectFunction) +CGA::CGA(ISelection* selectFunction) : m_theSelectFunction(selectFunction) { init(); m_thePopulation.clear(); m_theNewPopulation.clear(); } -void CGA :: addToPopulation ( IIndividual *individual ) +void CGA::addToPopulation(IIndividual* individual) { m_thePopulation.add(individual); - if ( m_thePopulation.size() >= m_iMaxPopSize ) + if (m_thePopulation.size() >= m_iMaxPopSize) { epoch(); m_thePopulation.freeMemory(); } } -void CGA :: epoch () +void CGA::epoch() { m_theNewPopulation.freeMemory(); - while ( m_theNewPopulation.size() < m_iMaxPopSize ) + while (m_theNewPopulation.size() < m_iMaxPopSize) { - IIndividual *mum = m_theSelectFunction->select(&m_thePopulation); - IIndividual *dad = m_theSelectFunction->select(&m_thePopulation); + IIndividual* mum = m_theSelectFunction->select(&m_thePopulation); + IIndividual* dad = m_theSelectFunction->select(&m_thePopulation); - IIndividual *baby1 = mum->copy(); - IIndividual *baby2 = dad->copy(); + IIndividual* baby1 = mum->copy(); + IIndividual* baby2 = dad->copy(); - if ( randomFloat(0,1) < g_fCrossOverRate ) + if (randomFloat(0, 1) < g_fCrossOverRate) baby1->crossOver(baby2); baby1->mutate(); baby2->mutate(); - + m_theNewPopulation.add(baby1); m_theNewPopulation.add(baby2); - } + } m_iNumGenerations++; - float fCurAvgFitness = m_thePopulation.averageFitness(); + const float fCurAvgFitness = m_thePopulation.averageFitness(); /*CBotGlobals::botMessage(NULL,0,"------Generation %d------",m_iNumGenerations); CBotGlobals::botMessage(NULL,0,"best fitness = %0.5f",m_thePopulation.bestFitness()); @@ -174,26 +177,26 @@ void CGA :: epoch () m_fPrevAvgFitness = fCurAvgFitness; } -void CGA :: freeLocalMemory () +void CGA::freeLocalMemory() { m_thePopulation.freeMemory(); m_theNewPopulation.freeMemory(); m_iNumGenerations = 0; } -void CGA :: freeGlobalMemory () +void CGA::freeGlobalMemory() { freeLocalMemory(); delete m_theSelectFunction; - m_theSelectFunction = NULL; + m_theSelectFunction = nullptr; } -bool CGA :: canPick () +bool CGA::canPick() const { - return (m_theNewPopulation.size() > 0); + return m_theNewPopulation.size() > 0; } -IIndividual *CGA :: pick () +std::unique_ptr CGA::pick() { return m_theNewPopulation.pick(); } @@ -202,20 +205,36 @@ IIndividual *CGA :: pick () // SELECTION /////////////// -IIndividual *CRouletteSelection :: select ( CPopulation *population ) +IIndividual* CRouletteSelection::select(CPopulation* population) { - ga_nn_value fFitnessSlice = randomFloat(0,population->totalFitness()); + if (population->size() == 0) + logger->Log(LogLevel::WARN, "GA Error: Population is empty. Selection cannot proceed."); + + const ga_nn_value totalFitness = population->totalFitness(); + + if (totalFitness <= 0.0f) + logger->Log(LogLevel::WARN, "GA Error: Total fitness is zero or negative. Selection cannot proceed."); + + const ga_nn_value fFitnessSlice = randomFloat(0, totalFitness); + ga_nn_value fFitnessSoFar = 0.0f; - for ( unsigned int i = 0; i < population->size(); i ++ ) + for (std::size_t i = 0; i < population->size(); i++) { - IIndividual *individual = population->get(i); + // Ensure the index is within the range of int [APG]RoboCop[CL] + if (i > static_cast(std::numeric_limits::max())) + { + logger->Log(LogLevel::ERROR, "GA Error: Index exceeds the range of int. Aborting operation."); + return nullptr; // Or handle the error appropriately + } + + IIndividual* individual = population->get(i); fFitnessSoFar += individual->getFitness(); - if ( fFitnessSoFar >= fFitnessSlice ) + if (fFitnessSoFar >= fFitnessSlice) return individual; } return population->get(0); -} +} \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_ga.h b/utils/RCBot2_meta/bot_ga.h index a291328cc..fb5c531e5 100644 --- a/utils/RCBot2_meta/bot_ga.h +++ b/utils/RCBot2_meta/bot_ga.h @@ -32,16 +32,17 @@ #define __BOT_GA_H__ #include "bot_ga_nn_const.h" +#include #include -using namespace std; - class IIndividual { public: + virtual ~IIndividual() = default; + // get fitness for this individual - inline ga_nn_value getFitness () { return m_fFitness; } - inline void setFitness ( float fVal ) { m_fFitness = fVal; } + ga_nn_value getFitness () const { return m_fFitness; } + void setFitness (const float fVal) { m_fFitness = fVal; } // crossover with other individual virtual void crossOver ( IIndividual *other ) = 0; @@ -53,7 +54,7 @@ class IIndividual // sub classes return their class with own values virtual IIndividual *copy () = 0; private: - ga_nn_value m_fFitness; + ga_nn_value m_fFitness = 0.0f; }; class CGA; @@ -64,54 +65,56 @@ class CPopulation void freeMemory (); - inline void setGA ( CGA *ga ) { m_ga = ga; } + void setGA ( CGA *ga ) { m_ga = ga; } + // size of population - inline unsigned int size () { return m_theIndividuals.size(); }; + std::size_t size() const { return m_theIndividuals.size(); } // get from population index - IIndividual *get ( int iIndex ); + IIndividual *get (std::size_t iIndex) const; // add individual to population void add ( IIndividual *individual ); void clear (); - ga_nn_value totalFitness (); + ga_nn_value totalFitness () const; - ga_nn_value bestFitness (); + ga_nn_value bestFitness () const; - ga_nn_value averageFitness (); + ga_nn_value averageFitness () const; // get back individual - IIndividual *pick (); + std::unique_ptr pick(); private: - vector m_theIndividuals; - CGA *m_ga; + std::vector m_theIndividuals; + CGA * m_ga = nullptr; }; // selection function interface class ISelection { public: + virtual ~ISelection() = default; virtual IIndividual *select ( CPopulation *population ) = 0; }; class CRouletteSelection : public ISelection { - IIndividual *select ( CPopulation *population ); + IIndividual *select ( CPopulation *population ) override; }; class CGA { public: - CGA (int iMaxPopSize=0) + CGA (const std::size_t iMaxPopSize=0) { init(iMaxPopSize); } - void init (int iMaxPopSize=0) + void init (const std::size_t iMaxPopSize=0) { m_theSelectFunction = new CRouletteSelection(); @@ -119,7 +122,7 @@ class CGA m_theNewPopulation.setGA(this); m_iNumGenerations = 0; - m_fPrevAvgFitness = 0; + m_fPrevAvgFitness = 0.0f; m_iMaxPopSize = iMaxPopSize; @@ -139,11 +142,11 @@ class CGA void addToPopulation ( IIndividual *individual ); // can get an individual off new population - bool canPick (); + bool canPick () const; - IIndividual *pick (); + std::unique_ptr pick(); - unsigned int m_iMaxPopSize; + std::size_t m_iMaxPopSize; static const int g_iDefaultMaxPopSize; static const float g_fCrossOverRate; static const float g_fMutateRate; @@ -154,7 +157,7 @@ class CGA CPopulation m_thePopulation; CPopulation m_theNewPopulation; - unsigned int m_iNumGenerations; + unsigned m_iNumGenerations; float m_fPrevAvgFitness; ISelection *m_theSelectFunction; diff --git a/utils/RCBot2_meta/bot_ga_ind.cpp b/utils/RCBot2_meta/bot_ga_ind.cpp index c85601138..b28329387 100644 --- a/utils/RCBot2_meta/bot_ga_ind.cpp +++ b/utils/RCBot2_meta/bot_ga_ind.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -28,109 +30,103 @@ * version. * */ +#include "bot_ga_ind.h" #include "bot.h" #include "bot_mtrand.h" #include "bot_ga.h" -#include "bot_ga_ind.h" -#include "bot_mtrand.h" -CBotGAValues :: CBotGAValues() +#include + +CBotGAValues::CBotGAValues() { - init(); + init(); } -void CBotGAValues :: init (void) +void CBotGAValues::init() { - clear(); - setFitness(0); + clear(); + setFitness(0); } -CBotGAValues :: CBotGAValues( vector values ) +CBotGAValues::CBotGAValues(const std::vector& values) { - clear(); - setFitness(0); + clear(); + setFitness(0); - setVector(values); + setVector(values); } -void CBotGAValues :: clear () +void CBotGAValues::clear() { - m_theValues.clear(); + m_theValues.clear(); } // crossover with other individual -void CBotGAValues :: crossOver ( IIndividual *other ) +void CBotGAValues::crossOver(IIndividual* other) { - unsigned int iPoint = randomInt(0,m_theValues.size()); - float fTemp; - - CBotGAValues *vother = (CBotGAValues*)other; - - unsigned int i; - - for ( i = 0; i < iPoint; i ++ ) - { - fTemp = get(i); - set(i,vother->get(i)); - vother->set(i,fTemp); - } - - for ( i = iPoint; i < m_theValues.size(); i ++ ) - { - fTemp = vother->get(i); - vother->set(i,get(i)); - set(i,fTemp); - } + const std::size_t iPoint = randomInt(0, static_cast(m_theValues.size())); + + CBotGAValues* vother = static_cast(other); + + for (std::size_t i = 0; i < iPoint; i++) + { + std::swap(m_theValues[i], vother->m_theValues[i]); + } + + for (std::size_t i = iPoint; i < m_theValues.size(); i++) + { + std::swap(m_theValues[i], vother->m_theValues[i]); + } } // mutate some values -void CBotGAValues :: mutate () +void CBotGAValues::mutate() { - for ( unsigned int i = 0; i < m_theValues.size(); i ++ ) - { - if ( randomFloat(0,1) < CGA::g_fMutateRate ) - { - float fCurrentVal = get(i); - - set(i,fCurrentVal + ((fCurrentVal * (-1+randomFloat(0,2))) * CGA::g_fMaxPerturbation)); - } - } + for (std::size_t i = 0; i < m_theValues.size(); i++) + { + if (randomFloat(0, 1) < CGA::g_fMutateRate) + { + const float fCurrentVal = get(i); + + set(i, fCurrentVal + fCurrentVal * (-1 + randomFloat(0, 2)) * CGA::g_fMaxPerturbation); + } + } } - -float CBotGAValues :: get ( int iIndex ) +float CBotGAValues::get(const std::size_t iIndex) const { - return m_theValues[iIndex]; + return m_theValues[iIndex]; } -void CBotGAValues :: set ( int iIndex, float fVal ) +void CBotGAValues::set(const std::size_t iIndex, const float fVal) { - m_theValues[iIndex] = fVal; + m_theValues[iIndex] = fVal; } -void CBotGAValues :: addRnd() +void CBotGAValues::addRnd() { - m_theValues.push_back(randomFloat(0,1)); + m_theValues.emplace_back(randomFloat(0, 1)); } // get new copy of this // sub classes return their class with own values -IIndividual *CBotGAValues :: copy () +IIndividual* CBotGAValues::copy() { - IIndividual *individual = new CBotGAValues (m_theValues); + IIndividual* individual = new CBotGAValues(m_theValues); - individual->setFitness(getFitness()); + individual->setFitness(getFitness()); - return individual; + return individual; } -void CBotGAValues :: setVector ( vector values ) +void CBotGAValues::setVector(const std::vector& values) { - for ( unsigned int i = 0; i < values.size(); i ++ ) - m_theValues.push_back(values[i]); + m_theValues.reserve(values.size()); + for (const float& value : values) + m_theValues.emplace_back(value); } -void CBotGAValues :: freeMemory () +void CBotGAValues::freeMemory() { - m_theValues.clear(); -} + m_theValues.clear(); +} \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_ga_ind.h b/utils/RCBot2_meta/bot_ga_ind.h index 00fef7734..8264263a2 100644 --- a/utils/RCBot2_meta/bot_ga_ind.h +++ b/utils/RCBot2_meta/bot_ga_ind.h @@ -38,33 +38,33 @@ class CBotGAValues : public IIndividual public: CBotGAValues(); - CBotGAValues( vector values ); + CBotGAValues( const std::vector& values ); - void init (void); + void init (); // crossover with other individual - void crossOver ( IIndividual *other ); + void crossOver(IIndividual* other) override; // mutate some values - void mutate (); + void mutate () override; // get new copy of this // sub classes return their class with own values - virtual IIndividual *copy (); + IIndividual *copy () override; - void setVector ( vector values ); + void setVector (const std::vector& values); - float get ( int iIndex ); + float get (std::size_t iIndex) const; - void set ( int iIndex, float fVal ); + void set (std::size_t iIndex, float fVal); void clear (); - inline void add ( float val ) { m_theValues.push_back(val); } + void add ( float val ) { m_theValues.emplace_back(val); } void addRnd (); - void setup ( int iValues ) + void setup (const int iValues) { for ( int i = 0; i < iValues; i ++ ) addRnd(); @@ -73,7 +73,7 @@ class CBotGAValues : public IIndividual void freeMemory (); protected: - vector m_theValues; + std::vector m_theValues; }; class CBotStuckValues : public CBotGAValues @@ -85,17 +85,17 @@ class CBotStuckValues : public CBotGAValues setup(5); } - float getJumpTime () + float getJumpTime () const { return m_theValues[0]; } - float getFailTime () + float getFailTime () const { return m_theValues[1]; } - virtual IIndividual *copy () + IIndividual *copy () override { CBotStuckValues *p = new CBotStuckValues(); p->setVector(m_theValues); @@ -103,12 +103,12 @@ class CBotStuckValues : public CBotGAValues return p; } - void getStuckWeights ( vector *weights ) + void getStuckWeights ( std::vector *weights ) { weights->clear(); - weights->push_back(m_theValues[2]); - weights->push_back(m_theValues[3]); - weights->push_back(m_theValues[4]); + weights->emplace_back(m_theValues[2]); + weights->emplace_back(m_theValues[3]); + weights->emplace_back(m_theValues[4]); } }; diff --git a/utils/RCBot2_meta/bot_genclass.cpp b/utils/RCBot2_meta/bot_genclass.cpp deleted file mode 100644 index 8fe3bef82..000000000 --- a/utils/RCBot2_meta/bot_genclass.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* EXCLUDED FROM BUILD */ - -#include "bot.h" -#include "bot_const.h" -#include "bot_genclass.h" - -#include "vstdlib/random.h" // for random functions - diff --git a/utils/RCBot2_meta/bot_genclass.h b/utils/RCBot2_meta/bot_genclass.h index 2e48858c7..2d6afa0b7 100644 --- a/utils/RCBot2_meta/bot_genclass.h +++ b/utils/RCBot2_meta/bot_genclass.h @@ -44,7 +44,6 @@ #define __RCBOT_GENERIC_CLASS_H__ #include -using namespace std; //#include "vstdlib/random.h" // for random functions @@ -84,7 +83,7 @@ class dataStack { public: - void Init ( void ) + void Init () { m_Head = NULL; } @@ -127,10 +126,9 @@ class dataStack bool RemoveByPointer ( const T *pObj ) { - dataNode *tempNode = m_Head; - dataNode *deleteNode; + dataNode *tempNode = m_Head; - if ( m_Head == NULL ) + if ( m_Head == nullptr) return false; if ( &m_Head->m_NodeData == pObj ) @@ -146,7 +144,7 @@ class dataStack { if ( &tempNode->m_Next->m_NodeData == pObj ) { - deleteNode = tempNode->m_Next; + dataNode* deleteNode = tempNode->m_Next; tempNode->m_Next = tempNode->m_Next->m_Next; @@ -167,10 +165,9 @@ class dataStack bool Remove ( const T pObj ) { - dataNode *tempNode = m_Head; - dataNode *deleteNode; + dataNode *tempNode = m_Head; - if ( m_Head == NULL ) + if ( m_Head == nullptr) return false; if ( m_Head->m_NodeData == pObj ) @@ -186,7 +183,7 @@ class dataStack { if ( tempNode->m_Next->m_NodeData == pObj ) { - deleteNode = tempNode->m_Next; + dataNode* deleteNode = tempNode->m_Next; tempNode->m_Next = tempNode->m_Next->m_Next; @@ -204,13 +201,11 @@ class dataStack return false; } - void Destroy ( void ) + void Destroy () { - dataNode *tempNode; - while ( m_Head ) { - tempNode = m_Head; + dataNode* tempNode = m_Head; m_Head = m_Head->m_Next; @@ -223,9 +218,9 @@ class dataStack m_Head = NULL; } - inline bool IsEmpty ( void ) + bool IsEmpty () { - return ( m_Head == NULL ); + return m_Head == nullptr; } void Push ( const T pObj ) @@ -239,7 +234,7 @@ class dataStack } - T Pop ( void ) + T Pop () { dataNode *tempNode = m_Head; @@ -251,7 +246,7 @@ class dataStack return returnData; } - T ChooseFromStack ( void ) + T ChooseFromStack () { T *l_pTemp; @@ -275,7 +270,7 @@ class dataStack return *l_pTemp; } - T *ChoosePointerFromStack ( void ) + T *ChoosePointerFromStack () { T *l_pTemp; @@ -293,7 +288,7 @@ class dataStack m_Head = NULL; // return default - return NULL; + return nullptr; } return l_pTemp; @@ -301,14 +296,14 @@ class dataStack // Returns a pointer to the DETAILS (m_NodeData) // in the HEAD. - T *GetHeadInfoPointer ( void ) + T *GetHeadInfoPointer () { if ( m_Head ) { return &m_Head->m_NodeData; } - return NULL; + return nullptr; } private: @@ -331,7 +326,7 @@ class dataUnconstArray this->Clear(); } - inline Size (void) + inline Size () { return m_iArrayMax; } @@ -374,31 +369,31 @@ class dataUnconstArray m_iArrayMax = iNewSize; } - inline void Destroy (void) + inline void Destroy () { delete m_pArray; } - inline void Init ( void ) + inline void Init () { m_pArray = NULL; m_iArrayMax = -1; } - inline bool IsEmpty ( void ) + inline bool IsEmpty () { return (m_pArray == NULL); } - inline void Clear ( void ) + inline void Clear () { this->Destroy(); this->Init(); } - T Random ( void ) + T Random () { return m_pArray[RANDOM_INT(0,m_iArrayMax-1)];//RandomInt(0,m_iArrayMax-1)]; } @@ -487,7 +482,7 @@ class dataUnconstArray this->Clear(); } - inline Size (void) + inline Size () { return m_iArrayMax; } @@ -530,31 +525,31 @@ class dataUnconstArray m_iArrayMax = iNewSize; } - inline void Destroy (void) + inline void Destroy () { delete m_pArray; m_pArray = NULL; m_iArrayMax = -1; } - inline void Init ( void ) + inline void Init () { m_pArray = NULL; m_iArrayMax = -1; } - inline bool IsEmpty ( void ) + inline bool IsEmpty () { return (m_pArray == NULL); } - inline void Clear ( void ) + inline void Clear () { this->Destroy(); this->Init(); } - T Random ( void ) + T Random () { return m_pArray[RANDOM_INT(0,m_iArrayMax-1)]; } @@ -634,7 +629,7 @@ class dataUnconstArray this->Clear(); } - inline int Size (void) + int Size () { return array.size(); } @@ -647,16 +642,16 @@ class dataUnconstArray //SAFE REMOVE - SLOW std::vector newVec; - for ( unsigned int i = 0; i < array.size(); i ++ ) + for ( unsigned i = 0; i < array.size(); i ++ ) { if ( array[i] != obj ) - newVec.push_back(array[i]); + newVec.emplace_back(array[i]); } array.clear(); array = newVec; #elif defined(__linux__) && !defined(_DEBUG) - typename std::vector ::iterator it; + typename std::vector ::iterator it; for ( it = array.begin(); it != array.end(); ) { if ( *it == obj ) @@ -669,18 +664,18 @@ class dataUnconstArray } #elif defined(_DEBUG) //SAFE REMOVE - SLOW - vector newVec; + std::vector newVec; - for ( unsigned int i = 0; i < array.size(); i ++ ) + for ( unsigned i = 0; i < array.size(); i ++ ) { if ( array[i] != obj ) - newVec.push_back(array[i]); + newVec.emplace_back(array[i]); } array.clear(); array = newVec; #else - typename vector ::iterator it; + typename std::vector ::iterator it; for ( it = array.begin(); it != array.end(); ) { @@ -689,28 +684,27 @@ class dataUnconstArray it = array.erase(it); return; } - else - ++ it; + ++ it; } #endif } - inline void Destroy (void) + void Destroy () { array.clear(); } - inline void Init ( void ) + void Init () { array.clear(); } - inline bool IsEmpty ( void ) + bool IsEmpty () { return array.empty(); } - inline void Clear ( void ) + void Clear () { this->Destroy(); this->Init(); @@ -718,7 +712,7 @@ class dataUnconstArray //static int RandomInteger ( int min, int max ); - T Random ( void ) + T Random () { //return array[RANDOM_INT(0,array.size()-1)]; //return array[RandomInteger(0,array.size()-1)]; @@ -727,7 +721,7 @@ class dataUnconstArray void Add ( const T pObj ) { - array.push_back(pObj); + array.emplace_back(pObj); } T ReturnValueFromIndex ( int iIndex ) @@ -737,12 +731,12 @@ class dataUnconstArray T *ReturnPointerFromIndex ( int iIndex ) { - return &(array[iIndex]); + return &array[iIndex]; } bool IsMember ( T Obj ) { - for ( unsigned int i = 0; i < array.size(); i ++ ) + for ( unsigned i = 0; i < array.size(); i ++ ) { if ( array[i] == Obj ) return true; @@ -751,12 +745,12 @@ class dataUnconstArray return false; } - T operator [] ( unsigned int iIndex ) + T operator [] ( unsigned iIndex ) { return array[iIndex]; } private: - vector array; + std::vector array; }; template @@ -774,15 +768,15 @@ class dataQueue this->Destroy(); } - inline void Init ( void ) + void Init () { m_Head = NULL; m_Tail = NULL; } - void Destroy ( void ) + void Destroy () { - dataNode *tempNode = NULL; + dataNode *tempNode = nullptr; while ( m_Head ) { @@ -800,9 +794,9 @@ class dataQueue m_Tail = NULL; } - inline bool IsEmpty ( void ) + bool IsEmpty () { - return (( m_Head == NULL )||(m_Tail == NULL)); + return m_Head == nullptr ||m_Tail == nullptr; } void AddFront ( const T &pObj ) @@ -811,7 +805,7 @@ class dataQueue newNode->m_NodeData = pObj; - if ( m_Head == NULL ) + if ( m_Head == nullptr) { m_Tail = newNode; m_Head = newNode; @@ -842,17 +836,17 @@ class dataQueue } } - inline T GetFrontInfo ( void ) + T GetFrontInfo () { return m_Head->m_NodeData; } - inline T *GetFrontPointer ( void ) + T *GetFrontPointer () { return &m_Head->m_NodeData; } - T ChooseFrom ( void ) + T ChooseFrom () { T *l_pTemp; @@ -877,7 +871,7 @@ class dataQueue return *l_pTemp; } - T *ChoosePointerFrom ( void ) + T *ChoosePointerFrom () { T *l_pTemp; @@ -896,17 +890,15 @@ class dataQueue m_Head = NULL; m_Tail = NULL; // return default - return NULL; + return nullptr; } return l_pTemp; } - void RemoveFront ( void ) + void RemoveFront () { - dataNode *tempNode = m_Head; - - if ( m_Head == NULL ) + if ( m_Head == nullptr) { // just set tail to null incase m_Tail = NULL; @@ -916,7 +908,7 @@ class dataQueue try { - tempNode = m_Head; + dataNode* tempNode = m_Head; if ( m_Tail == m_Head ) { @@ -962,10 +954,9 @@ class dataQueue bool Remove ( const T pObj ) { - dataNode *tempNode = m_Head; - dataNode *deleteNode = NULL; + dataNode *tempNode = m_Head; - if ( m_Head == NULL ) + if ( m_Head == nullptr) return false; if ( m_Head->m_NodeData == pObj ) @@ -992,7 +983,7 @@ class dataQueue { if ( tempNode->m_Next->m_NodeData == pObj ) { - deleteNode = tempNode->m_Next; + dataNode* deleteNode = tempNode->m_Next; if ( deleteNode == m_Tail ) { @@ -1018,10 +1009,9 @@ class dataQueue bool RemoveByPointer ( const T *pObj ) { - dataNode *tempNode = m_Head; - dataNode *deleteNode = NULL; + dataNode *tempNode = m_Head; - if ( m_Head == NULL ) + if ( m_Head == nullptr) return false; if ( &m_Head->m_NodeData == pObj ) @@ -1046,7 +1036,7 @@ class dataQueue { if ( &tempNode->m_Next->m_NodeData == pObj ) { - deleteNode = tempNode->m_Next; + dataNode* deleteNode = tempNode->m_Next; if ( deleteNode == m_Tail ) { diff --git a/utils/RCBot2_meta/bot_getprop.cpp b/utils/RCBot2_meta/bot_getprop.cpp index 076d33001..3e4ab1187 100644 --- a/utils/RCBot2_meta/bot_getprop.cpp +++ b/utils/RCBot2_meta/bot_getprop.cpp @@ -1,10 +1,20 @@ - +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com #include "engine_wrappers.h" #include "server_class.h" #include "bot_const.h" #include "bot.h" #include "bot_globals.h" #include "bot_getprop.h" +#include "bot_cvars.h" +#include "datamap.h" +#include "rcbot/rb-platform.h" + +#include + +#if defined(_WIN64) || defined(_WIN32) +#define strcmpi _strcmpi +#endif CClassInterfaceValue CClassInterface :: g_GetProps[GET_PROPDATA_MAX]; bool CClassInterfaceValue :: m_berror = false; @@ -13,19 +23,17 @@ extern IServerGameDLL *servergamedll; void UTIL_FindServerClassnamePrint(const char *name_cmd) { - edict_t *current; - for (int i = 0; i < gpGlobals->maxEntities; i++) { - current = engine->PEntityOfEntIndex(i); - if (current == NULL) + edict_t* current = engine->PEntityOfEntIndex(i); + if (current == nullptr) { continue; } IServerNetworkable *network = current->GetNetworkable(); - if (network == NULL) + if (network == nullptr) { continue; } @@ -34,39 +42,37 @@ void UTIL_FindServerClassnamePrint(const char *name_cmd) const char *name = sClass->GetName(); - if (strcmp(name, name_cmd) == 0) + if (std::strcmp(name, name_cmd) == 0) { - CBotGlobals::botMessage(NULL,0,"%s",current->GetClassName()); + CBotGlobals::botMessage(nullptr,0,"%s",current->GetClassName()); return; } } - CBotGlobals::botMessage(NULL,0,"Not found"); + CBotGlobals::botMessage(nullptr,0,"Not found"); } - - void UTIL_FindServerClassPrint(const char *name_cmd) { char temp[128]; char name[128]; - strncpy(name,name_cmd,127); + std::strncpy(name,name_cmd,127); name[127] = 0; - __strlow(name); + __strlow(name) - ServerClass *pClass = servergamedll->GetAllServerClasses(); + const ServerClass *pClass = servergamedll->GetAllServerClasses(); while (pClass) { - strncpy(temp,pClass->m_pNetworkName,127); + std::strncpy(temp,pClass->m_pNetworkName,127); temp[127] = 0; - __strlow(temp); + __strlow(temp) - if (strstr(temp,name) != NULL ) + if (std::strstr(temp,name) != nullptr) { - CBotGlobals::botMessage(NULL,0,"%s",pClass->m_pNetworkName); + CBotGlobals::botMessage(nullptr,0,"%s",pClass->m_pNetworkName); //break; } pClass = pClass->m_pNext; @@ -91,8 +97,7 @@ ServerClass *UTIL_FindServerClass(const char *name) pClass = pClass->m_pNext; } - return NULL; - + return nullptr; } /** @@ -106,30 +111,28 @@ bool g_PrintProps = false; SendProp *UTIL_FindSendProp(SendTable *pTable, const char *name) { - int count = pTable->GetNumProps(); - //SendTable *pTable; - SendProp *pProp; + const int count = pTable->GetNumProps(); for (int i=0; iGetProp(i); + SendProp* pProp = pTable->GetProp(i); if ( g_PrintProps ) Msg("%s\n",pProp->GetName()); - if (strcmp(pProp->GetName(), name) == 0) + if (std::strcmp(pProp->GetName(), name) == 0) { return pProp; } if (pProp->GetDataTable()) { - if ((pProp=UTIL_FindSendProp(pProp->GetDataTable(), name)) != NULL) + if ((pProp=UTIL_FindSendProp(pProp->GetDataTable(), name)) != nullptr) { return pProp; } } } - return NULL; + return nullptr; } /** * vim: set ts=4 : @@ -165,32 +168,30 @@ SendProp *UTIL_FindSendProp(SendTable *pTable, const char *name) struct sm_sendprop_info_t { SendProp *prop; /**< Property instance. */ - unsigned int actual_offset; /**< Actual computed offset. */ + unsigned actual_offset; /**< Actual computed offset. */ }; bool UTIL_FindInSendTable(SendTable *pTable, const char *name, sm_sendprop_info_t *info, - unsigned int offset) + const unsigned offset) { - const char *pname; - int props = pTable->GetNumProps(); - SendProp *prop; + const int props = pTable->GetNumProps(); - for (int i=0; iGetProp(i); - pname = prop->GetName(); + SendProp* prop = pTable->GetProp(i); + const char* pname = prop->GetName(); if ( g_PrintProps ) Msg("%d : %s\n",offset + prop->GetOffset(),pname); - if (pname && strcmp(name, pname) == 0) + if (pname && std::strcmp(name, pname) == 0) { info->prop = prop; // for some reason offset is sometimes negative when it shouldn't be // so take the absolute value - info->actual_offset = offset + abs(info->prop->GetOffset()); + info->actual_offset = offset + std::abs(info->prop->GetOffset()); return true; } if (prop->GetDataTable()) @@ -209,7 +210,7 @@ bool UTIL_FindInSendTable(SendTable *pTable, return false; } -bool UTIL_FindSendPropInfo(ServerClass *pInfo, const char *szType, unsigned int *offset) +bool UTIL_FindSendPropInfo(const ServerClass *pInfo, const char *szType, unsigned *offset) { if ( !pInfo ) { @@ -232,7 +233,7 @@ CBaseHandle *CClassInterfaceValue :: getEntityHandle ( edict_t *edict ) { getData(edict); - return (CBaseHandle *)m_data; + return static_cast(m_data); } edict_t *CClassInterfaceValue :: getEntity ( edict_t *edict ) @@ -243,36 +244,33 @@ edict_t *CClassInterfaceValue :: getEntity ( edict_t *edict ) getData(edict); - if (m_berror) - return NULL; + return nullptr; - hndl = (CBaseHandle *)m_data; + hndl = static_cast(m_data); if ( hndl ) return INDEXENT(hndl->GetEntryIndex()); - return NULL; + return nullptr; } -void CClassInterfaceValue :: init ( char *key, char *value, unsigned int preoffset ) +void CClassInterfaceValue :: init (const char* key, const char* value, const unsigned preoffset) { m_class = CStrings::getString(key); m_value = CStrings::getString(value); - m_data = NULL; + m_data = nullptr; m_preoffset = preoffset; m_offset = 0; } void UTIL_FindPropPrint(const char *prop_name) { - bool bInterfaceErr = false; - - unsigned int offset; + unsigned offset; try { - ServerClass *pClass = servergamedll->GetAllServerClasses(); + const ServerClass *pClass = servergamedll->GetAllServerClasses(); while (pClass) { @@ -282,7 +280,7 @@ void UTIL_FindPropPrint(const char *prop_name) if ( offset != 0 ) { - CBotGlobals::botMessage(NULL,0,"found in %s : offset %d",pClass->m_pNetworkName, offset); + CBotGlobals::botMessage(nullptr,0,"found in %s : offset %d",pClass->m_pNetworkName, offset); //break; } pClass = pClass->m_pNext; @@ -290,24 +288,23 @@ void UTIL_FindPropPrint(const char *prop_name) } catch (...) { - bInterfaceErr = true; + bool bInterfaceErr = true; //Unused? [APG]RoboCop[CL] } } -void CClassInterfaceValue :: findOffset ( ) +void CClassInterfaceValue :: findOffset () { //if (!m_offset) //{ - ServerClass *sc = UTIL_FindServerClass(m_class); - if ( sc ) + if (const ServerClass *sc = UTIL_FindServerClass(m_class)) { UTIL_FindSendPropInfo(sc,m_value,&m_offset); } #ifdef _DEBUG else { - CBotGlobals::botMessage(NULL,1,"Warning: Couldn't find CLASS %s",m_class); + CBotGlobals::botMessage(nullptr,1,"Warning: Couldn't find CLASS %s",m_class); return; } #endif @@ -317,16 +314,97 @@ void CClassInterfaceValue :: findOffset ( ) #ifdef _DEBUG else { - CBotGlobals::botMessage(NULL,1,"Warning: Couldn't find getprop %s for class %s",m_value,m_class); + CBotGlobals::botMessage(nullptr,1,"Warning: Couldn't find getprop %s for class %s",m_value,m_class); } #endif } + +/** + * Finds a named offset in a datamap. + * + * @param pMap Datamap to search. + * @param name Name of the property to find. + * @return Offset of a data map property, or 0 if not found. + */ +unsigned UTIL_FindInDataMap(const datamap_t* pMap, const char* name) +{ + while (pMap) + { + for (int i = 0; i < pMap->dataNumFields; i++) + { + if (pMap->dataDesc[i].fieldName == nullptr) + { + continue; + } + if (std::strcmp(name, pMap->dataDesc[i].fieldName) == 0) + { + return pMap->dataDesc[i].fieldOffset[TD_OFFSET_NORMAL]; + } + if (pMap->dataDesc[i].td) + { + unsigned offset; + if ((offset = UTIL_FindInDataMap(pMap->dataDesc[i].td, name)) != 0) + { + return offset; + } + } + } + pMap = pMap->baseMap; + } + + return 0; +} + +class VEmptyClass {}; +datamap_t* VGetDataDescMap(CBaseEntity* pThisPtr, const int offset) +{ + // Ensure pThisPtr is not null + if (!pThisPtr) + { + return nullptr; + } + // Get the vtable from the entity + void** vtable = *reinterpret_cast(pThisPtr); + void* vfunc = vtable[offset]; + + union + { + datamap_t* (VEmptyClass::* mfpnew)(); +#ifndef PLATFORM_POSIX + void* addr; + } u; + u.addr = vfunc; +#else + struct + { + void* addr; + std::intptr_t adjustor; + } s; +} u; + u.s.addr = vfunc; + u.s.adjustor = 0; +#endif + // Cast pThisPtr to VEmptyClass* and call the member function pointer + return (reinterpret_cast(pThisPtr)->*u.mfpnew)(); +} + +datamap_t* CBaseEntity_GetDataDescMap(CBaseEntity* pEntity) +{ + const int offset = rcbot_datamap_offset.GetInt(); + + if (offset == -1) + { + return nullptr; + } + + return VGetDataDescMap(pEntity, offset); +} + /* Find and save all offsets at load to save CPU */ void CClassInterface:: init () { // DEFINE_GETPROP ID Class Variable Offset DEFINE_GETPROP(GETPROP_TF2MINIBUILDING,"CObjectSentryGun","m_bMiniBuilding",0); - DEFINE_GETPROP(GETPROP_TF2SCORE,"CTFPlayerResource","m_iTotalScore",0); DEFINE_GETPROP(GETPROP_ENTITY_FLAGS,"CBaseEntity","m_iEffectFlags",0); DEFINE_GETPROP(GETPROP_TEAM,"CBaseEntity","m_iTeamNum",0); @@ -336,11 +414,22 @@ void CClassInterface:: init () DEFINE_GETPROP(GETPROP_TF2_NUMHEALERS,"CTFPlayer","m_nNumHealers",0); DEFINE_GETPROP(GETPROP_TF2_CONDITIONS,"CTFPlayer","m_nPlayerCond",0); DEFINE_GETPROP(GETPROP_VELOCITY,"CBasePlayer","m_vecVelocity[0]",0); - DEFINE_GETPROP(GETPROP_TF2CLASS,"CTFPlayer","m_PlayerClass",4); +#ifdef RCBOT_ARCH_X64 + /* + * The offset is 8 on x86-64 and 4 on x86 + * Table: m_PlayerClass (offset 10016) (type DT_TFPlayerClassShared) + * Member: m_iClass (offset 8) (type integer) (bits 4) (Unsigned) + */ + + DEFINE_GETPROP(GETPROP_TF2CLASS, "CTFPlayer", "m_PlayerClass", 8); +#else + DEFINE_GETPROP(GETPROP_TF2CLASS, "CTFPlayer", "m_PlayerClass", 4); +#endif // RCBOT_ARCH_X86 + DEFINE_GETPROP(GETPROP_TF2SPYMETER,"CTFPlayer","m_flCloakMeter",0); DEFINE_GETPROP(GETPROP_TF2SPYDISGUISED_TEAM,"CTFPlayer","m_nDisguiseTeam",0); DEFINE_GETPROP(GETPROP_TF2SPYDISGUISED_CLASS,"CTFPlayer","m_nDisguiseClass",0); - DEFINE_GETPROP(GETPROP_TF2SPYDISGUISED_TARGET_INDEX,"CTFPlayer","m_iDisguiseTargetIndex",0); + DEFINE_GETPROP(GETPROP_TF2SPYDISGUISED_TARGET,"CTFPlayer","m_hDisguiseTarget",0); //nosoop fix for VScript update DEFINE_GETPROP(GETPROP_TF2SPYDISGUISED_DIS_HEALTH,"CTFPlayer","m_iDisguiseHealth",0); DEFINE_GETPROP(GETPROP_TF2MEDIGUN_HEALING,"CWeaponMedigun","m_bHealing",0); DEFINE_GETPROP(GETPROP_TF2MEDIGUN_TARGETTING,"CWeaponMedigun","m_hHealingTarget",0); @@ -467,20 +556,14 @@ void CClassInterface:: init () //8484 : m_bCarryingObject DEFINE_GETPROP(GETPROP_TF2_ISCARRYINGOBJ,"CTFPlayer","m_bCarryingObject",0); DEFINE_GETPROP(GETPROP_TF2_GETCARRIEDOBJ,"CTFPlayer","m_hCarriedObject",0); - DEFINE_GETPROP(GETPROP_TF2_ATTRIBUTELIST,"CTFPlayer","m_AttributeList",0); // Addon stuff for TF2 DEFINE_GETPROP(GETPROP_TF2_ITEMDEFINITIONINDEX,"CTFWeaponBase","m_iItemDefinitionIndex",0); DEFINE_GETPROP(GETPROP_TF2_DISGUISEWEARABLE,"CTFWearable","m_bDisguiseWearable",0); - DEFINE_GETPROP(GETPROP_TF2_ENTITYLEVEL,"CBaseAttributableItem","m_iEntityLevel",0); DEFINE_GETPROP(GETPROP_TF2_RAGEMETER,"CTFPlayer","m_flRageMeter",0); DEFINE_GETPROP(GETPROP_TF2_RAGEDRAINING,"CTFPlayer","m_bRageDraining",0); - DEFINE_GETPROP(GETPROP_TF2_ENTITYQUALITY,"CBaseAttributableItem","m_iEntityQuality",0); - DEFINE_GETPROP(GETPROP_TF2_WEAPON_INITIALIZED,"CBaseAttributableItem","m_bInitialized",0); DEFINE_GETPROP(GETPROP_SIMULATIONTIME,"CBaseEntity","m_flSimulationTime",0); DEFINE_GETPROP(GETPROP_TF2_INUPGRADEZONE,"CTFPlayer","m_bInUpgradeZone",0); - DEFINE_GETPROP(GETPROP_TF2_EXTRAWEARABLE, "CTFWeaponBase", "m_hExtraWearable", 0); - DEFINE_GETPROP(GETPROP_TF2_EXTRAWEARABLEVIEWMODEL, "CTFWeaponBase", "m_hExtraWearableViewModel", 0); DEFINE_GETPROP(GETPROP_TF2_ENERGYDRINKMETER, "CTFPlayer", "m_flEnergyDrinkMeter", 0); DEFINE_GETPROP(GETPROP_TF2_MEDIEVALMODE, "CTFGameRulesProxy", "m_bPlayingMedieval", 0); DEFINE_GETPROP(GETPROP_TF2_ACTIVEWEAPON, "CTFPlayer", "m_hActiveWeapon", 0); @@ -488,12 +571,34 @@ void CClassInterface:: init () DEFINE_GETPROP(GETPROP_TF2_BUILDER_MODE, "CTFWeaponBuilder", "m_iObjectMode", 0); DEFINE_GETPROP(GETPROP_TF2_CHARGE_RESIST_TYPE, "CWeaponMedigun", "m_nChargeResistType", 0); DEFINE_GETPROP(GETPROP_TF2_ROUNDSTATE, "CTFGameRulesProxy", "m_iRoundState", 0); - DEFINE_GETPROP(GETPROP_TF2DESIREDCLASS, "CTFPlayer", "m_iDesiredClass", 0); - - for ( unsigned int i = 0; i < GET_PROPDATA_MAX; i ++ ) + DEFINE_GETPROP(GETPROP_TF2DESIREDCLASS, "CTFPlayer", "m_iDesiredPlayerClass", 0); + + // Synergy + DEFINE_GETPROP(GETPROP_SYN_PLAYER_VEHICLE, "CSynergyPlayer", "m_hVehicle", 0); + DEFINE_GETPROP(GETPROP_SYN_VEHICLE_DRIVER, "CPropVehicleDriveable", "m_hPlayer", 0); + DEFINE_GETPROP(GETPROP_SYN_SUITPOWER, "CSynergyPlayer", "m_flSuitPower", 0); + + // Counter-Strike: Source + DEFINE_GETPROP(GETPROP_CSS_MONEY, "CCSPlayer", "m_iAccount", 0); + DEFINE_GETPROP(GETPROP_CSS_INBUYZONE, "CCSPlayer", "m_bInBuyZone", 0); + DEFINE_GETPROP(GETPROP_CSS_INBOMBZONE, "CCSPlayer", "m_bInBombZone", 0); + DEFINE_GETPROP(GETPROP_CSS_INHOSTAGERESCUEZONE, "CCSPlayer", "m_bInHostageRescueZone", 0); + DEFINE_GETPROP(GETPROP_CSS_ARMOR, "CCSPlayer", "m_ArmorValue", 0); + DEFINE_GETPROP(GETPROP_CSS_HASDEFUSER, "CCSPlayer", "m_bHasDefuser", 0); + DEFINE_GETPROP(GETPROP_CSS_HASHELMET, "CCSPlayer", "m_bHasHelmet", 0); + DEFINE_GETPROP(GETPROP_CSS_BOMBTICKING, "CPlantedC4", "m_bBombTicking", 0); + DEFINE_GETPROP(GETPROP_CSS_HOSTAGE_HEALTH, "CHostage", "m_iHealth", 0); + DEFINE_GETPROP(GETPROP_CSS_HOSTAGE_RESCUED, "CHostage", "m_isRescued", 0); + DEFINE_GETPROP(GETPROP_CSS_HOSTAGE_LEADER, "CHostage", "m_leader", 0); + + // Generic + DEFINE_GETPROP(GETPROP_PLAYER_FOV, "CBasePlayer", "m_iFOV", 0); + DEFINE_GETPROP(GETPROP_PLAYER_LIFESTATE, "CBasePlayer", "m_lifeState", 0); + + for (CClassInterfaceValue& g_GetProp : g_GetProps) { //if ( g_GetProps[i] - g_GetProps[i].findOffset(); + g_GetProp.findOffset(); } } @@ -501,8 +606,8 @@ void CClassInterface :: setupCTeamRoundTimer ( CTeamRoundTimer *pTimer ) { /* GETPROP_TF2_RNDTM_m_flTimerEndTime, - GETPROP_TF2_RNDTM_m_nSetupTimeLength, - GETPROP_TF2_RNDTM_m_bInSetup, + GETPROP_TF2_RNDTM_m_nSetupTimeLength, + GETPROP_TF2_RNDTM_m_bInSetup, */ pTimer->m_flTimerEndTime = g_GetProps[GETPROP_TF2_RNDTM_m_flTimerEndTime].getFloatPointer(pTimer->m_Resource); pTimer->m_nSetupTimeLength = g_GetProps[GETPROP_TF2_RNDTM_m_nSetupTimeLength].getIntPointer(pTimer->m_Resource); @@ -544,77 +649,74 @@ bool CClassInterface :: getTF2ObjectiveResource ( CTFObjectiveResource *pResourc } -void CClassInterfaceValue :: getData ( void *edict, bool bIsEdict ) +void CClassInterfaceValue :: getData ( void *edict, const bool bIsEdict ) { - static IServerUnknown *pUnknown; - static CBaseEntity *pEntity; - - if (!m_offset || (edict==NULL)) + if (!m_offset || edict== nullptr) { - m_data = NULL; + m_data = nullptr; m_berror = true; return; } if (bIsEdict) { - edict_t *pEdict = reinterpret_cast(edict); + static CBaseEntity *pEntity; + static IServerUnknown *pUnknown; + edict_t *pEdict = static_cast(edict); - pUnknown = (IServerUnknown *)pEdict->GetUnknown(); + pUnknown = pEdict->GetUnknown(); if (!pUnknown) { - m_data = NULL; + m_data = nullptr; m_berror = true; return; } pEntity = pUnknown->GetBaseEntity(); - m_data = (void *)((char *)pEntity + m_offset); + m_data = static_cast(reinterpret_cast(pEntity) + static_cast(m_offset)); + } else { // raw - m_data = (void *)((char *)edict + m_offset); + m_data = static_cast(static_cast(edict) + static_cast(m_offset)); } } -edict_t *CClassInterface::FindEntityByClassnameNearest(Vector vstart, const char *classname, float fMindist, edict_t *pOwner) +edict_t *CClassInterface::FindEntityByClassnameNearest(const Vector& vstart, const char *classname, float fMinDist, const edict_t *pOwner) { - edict_t *current; - edict_t *pfound = NULL; - float fDist; - const char *pszClassname; + edict_t *pfound = nullptr; // speed up loop by by using smaller ints in register - register short int max = (short int)gpGlobals->maxEntities; + const short max = static_cast(gpGlobals->maxEntities); - for (register short int i = 0; i < max; i++) + for (short i = 0; i < max; i++) { - current = engine->PEntityOfEntIndex(i); + edict_t* current = engine->PEntityOfEntIndex(i); - if (current == NULL) + if (current == nullptr) continue; if ( current->IsFree() ) continue; - if ( pOwner != NULL ) + if ( pOwner != nullptr) { if ( getOwner(current) != pOwner ) continue; } - pszClassname = current->GetClassName(); // For Debugging purposes + const char* pszClassname = current->GetClassName(); // For Debugging purposes - if (strcmp(classname, pszClassname) == 0) + if (std::strcmp(classname, pszClassname) == 0) { - fDist = (vstart - CBotGlobals::entityOrigin(current)).Length(); + const float fDist = (vstart - CBotGlobals::entityOrigin(current)).Length(); - if ( !pfound || (fDist < fMindist)) + if ( !pfound || fDist < fMinDist) { - fMindist = fDist; + fMinDist = fDist; pfound = current; } } @@ -623,28 +725,26 @@ edict_t *CClassInterface::FindEntityByClassnameNearest(Vector vstart, const char return pfound; } -edict_t *CClassInterface::FindEntityByNetClassNearest(Vector vstart, const char *classname) +edict_t *CClassInterface::FindEntityByNetClassNearest(const Vector& vstart, const char *classname) { - edict_t *current; - edict_t *pfound = NULL; + edict_t *pfound = nullptr; float fMindist = 8192.0f; - float fDist; - for (short int i = 0; i < gpGlobals->maxEntities; i++) + for (int i = 0; i < gpGlobals->maxEntities; i++) { - current = engine->PEntityOfEntIndex(i); - if (current == NULL) + edict_t* current = engine->PEntityOfEntIndex(i); + if (current == nullptr) { continue; } if ( current->IsFree() ) continue; - if ( current->GetUnknown() == NULL ) + if ( current->GetUnknown() == nullptr) continue; IServerNetworkable *network = current->GetNetworkable(); - if (network == NULL) + if (network == nullptr) { continue; } @@ -652,11 +752,11 @@ edict_t *CClassInterface::FindEntityByNetClassNearest(Vector vstart, const char ServerClass *sClass = network->GetServerClass(); const char *name = sClass->GetName(); - if (strcmp(name, classname) == 0) + if (std::strcmp(name, classname) == 0) { - fDist = (vstart - CBotGlobals::entityOrigin(current)).Length(); + const float fDist = (vstart - CBotGlobals::entityOrigin(current)).Length(); - if ( !pfound || (fDist < fMindist)) + if ( !pfound || fDist < fMindist) { fMindist = fDist; pfound = current; @@ -667,26 +767,24 @@ edict_t *CClassInterface::FindEntityByNetClassNearest(Vector vstart, const char return pfound; } -const char *CClassInterface::FindEntityNetClass(int start, const char *classname) +const char *CClassInterface::FindEntityNetClass(const int start, const char *classname) { - edict_t *current; - - for (int i = ((start != -1) ? start : 0); i < gpGlobals->maxEntities; i++) + for (int i = start != -1 ? start : 0; i < gpGlobals->maxEntities; i++) { - current = engine->PEntityOfEntIndex(i); - if (current == NULL) + edict_t* current = engine->PEntityOfEntIndex(i); + if (current == nullptr) { continue; } IServerNetworkable *network = current->GetNetworkable(); - if (network == NULL) + if (network == nullptr) { continue; } - if (strcmp(current->GetClassName(), classname) == 0) + if (std::strcmp(current->GetClassName(), classname) == 0) { ServerClass *sClass = network->GetServerClass(); @@ -695,24 +793,22 @@ const char *CClassInterface::FindEntityNetClass(int start, const char *classname } } - return NULL; + return nullptr; } // http://svn.alliedmods.net/viewvc.cgi/trunk/extensions/tf2/extension.cpp?revision=2183&root=sourcemod&pathrev=2183 -edict_t *CClassInterface::FindEntityByNetClass(int start, const char *classname) +edict_t *CClassInterface::FindEntityByNetClass(const int start, const char *classname) { - edict_t *current; - - for (int i = ((start != -1) ? start : 0); i < gpGlobals->maxEntities; i++) + for (int i = start != -1 ? start : 0; i < gpGlobals->maxEntities; i++) { - current = engine->PEntityOfEntIndex(i); - if (current == NULL) + edict_t* current = engine->PEntityOfEntIndex(i); + if (current == nullptr) { continue; } IServerNetworkable *network = current->GetNetworkable(); - if (network == NULL) + if (network == nullptr) { continue; } @@ -721,28 +817,23 @@ edict_t *CClassInterface::FindEntityByNetClass(int start, const char *classname) const char *name = sClass->GetName(); - if (strcmp(name, classname) == 0) + if (std::strcmp(name, classname) == 0) { return current; } } - return NULL; + return nullptr; } - int CClassInterface::getTF2Score ( edict_t *edict ) - { - edict_t *res = CTeamFortress2Mod::findResourceEntity(); - int *score_array = NULL; - - if ( res ) - { - score_array = g_GetProps[GETPROP_TF2SCORE].getIntPointer(res); - - if ( score_array ) - return score_array[ENTINDEX(edict)-1]; - } - - return 0; +int CClassInterface::getTF2Score(const edict_t* edict) +{ + if (edict_t* res = CTeamFortress2Mod::findResourceEntity()) + { + if (const int* score_array = g_GetProps[GETPROP_TF2SCORE].getIntPointer(res)) + return score_array[static_cast(ENTINDEX(edict) - 1)]; } + + return 0; +} diff --git a/utils/RCBot2_meta/bot_getprop.h b/utils/RCBot2_meta/bot_getprop.h index 4f506bed1..2c0d15ec2 100644 --- a/utils/RCBot2_meta/bot_getprop.h +++ b/utils/RCBot2_meta/bot_getprop.h @@ -1,187 +1,205 @@ #ifndef __RCBOT_GETPROP_H__ #define __RCBOT_GETPROP_H__ -typedef enum +#include + +#include "bot_const.h" + +typedef enum : std::uint8_t { TELE_ENTRANCE = 0, TELE_EXIT }eTeleMode; -typedef enum +typedef enum : std::int16_t { - GETPROP_UNDEF = -1, + GETPROP_UNDEF = (-1), GETPROP_TF2SCORE = 0, - GETPROP_ENTITY_FLAGS, - GETPROP_TEAM, - GETPROP_PLAYERHEALTH, - GETPROP_EFFECTS, - GETPROP_AMMO, - GETPROP_TF2_NUMHEALERS, - GETPROP_TF2_CONDITIONS, - GETPROP_VELOCITY, - GETPROP_TF2CLASS, - GETPROP_TF2SPYMETER,// CTFPlayer:: - GETPROP_TF2SPYDISGUISED_TEAM,//CTFPlayer::m_nDisguiseTeam - GETPROP_TF2SPYDISGUISED_CLASS,//CTFPlayer::m_nDisguiseClass - GETPROP_TF2SPYDISGUISED_TARGET_INDEX,//CTFPlayer::m_iDisguiseTargetIndex - GETPROP_TF2SPYDISGUISED_DIS_HEALTH,//CTFPlayer::m_iDisguiseHealth - GETPROP_TF2MEDIGUN_HEALING, - GETPROP_TF2MEDIGUN_TARGETTING, + GETPROP_ENTITY_FLAGS = 1, + GETPROP_TEAM = 2, + GETPROP_PLAYERHEALTH = 3, + GETPROP_EFFECTS = 4, + GETPROP_AMMO = 5, + GETPROP_TF2_NUMHEALERS = 6, + GETPROP_TF2_CONDITIONS = 7, + GETPROP_VELOCITY = 8, + GETPROP_TF2CLASS = 9, + GETPROP_TF2SPYMETER = 10, // CTFPlayer:: + GETPROP_TF2SPYDISGUISED_TEAM = 11, //CTFPlayer::m_nDisguiseTeam + GETPROP_TF2SPYDISGUISED_CLASS = 12, //CTFPlayer::m_nDisguiseClass + GETPROP_TF2SPYDISGUISED_TARGET = 13, //CTFPlayer::m_iDisguiseTargetIndex - nosoop fix for VScript update + GETPROP_TF2SPYDISGUISED_DIS_HEALTH = 14, //CTFPlayer::m_iDisguiseHealth + GETPROP_TF2MEDIGUN_HEALING = 15, + GETPROP_TF2MEDIGUN_TARGETTING = 16, //SETPROP_SET_TICK_BASE, - GETPROP_TF2TELEPORTERMODE, - GETPROP_CURRENTWEAPON, - GETPROP_TF2UBERCHARGE_LEVEL, - GETPROP_TF2SENTRYHEALTH, - GETPROP_TF2DISPENSERHEALTH, - GETPROP_TF2TELEPORTERHEALTH, - GETPROP_TF2OBJECTCARRIED, - GETPROP_TF2OBJECTUPGRADELEVEL, - GETPROP_TF2OBJECTUPGRADEMETAL, - GETPROP_TF2OBJECTMAXHEALTH, - GETPROP_TF2DISPMETAL, - GETPROP_TF2MINIBUILDING, - GETPROP_MAXSPEED, - GETPROP_CONSTRAINT_SPEED, - GETPROP_TF2OBJECTBUILDING, - GETPROP_HL2DM_PHYSCANNON_ATTACHED, - GETPROP_HL2DM_PHYSCANNON_OPEN, - GETPROP_HL2DM_PLAYER_AUXPOWER, - GETPROP_HL2DM_LADDER_ENT, - GETPROP_WEAPONLIST, - GETPROP_WEAPONSTATE, - GETPROP_WEAPONCLIP1, - GETPROP_WEAPONCLIP2, - GETPROP_WEAPON_AMMOTYPE1, - GETPROP_WEAPON_AMMOTYPE2, - GETPROP_DOD_PLAYERCLASS, - GETPROP_DOD_DES_PLAYERCLASS, - GETPROP_DOD_STAMINA, - GETPROP_DOD_PRONE, - GETPROP_SEQUENCE, - GETPROP_CYCLE, - GETPROP_ENTITYFLAGS, - GETPROP_DOD_CP_NUMCAPS, - GETPROP_DOD_CP_POSITIONS, - GETPROP_DOD_CP_ALLIES_REQ_CAP, - GETPROP_DOD_CP_AXIS_REQ_CAP, - GETPROP_DOD_CP_NUM_AXIS, - GETPROP_DOD_CP_NUM_ALLIES, - GETPROP_DOD_CP_OWNER, - GETPROP_DOD_SNIPER_ZOOMED, - GETPROP_DOD_MACHINEGUN_DEPLOYED, - GETPROP_DOD_ROCKET_DEPLOYED, - GETPROP_DOD_SEMI_AUTO, - GETPROP_MOVETYPE, - GETPROP_DOD_GREN_THROWER, - GETPROP_DOD_SCORE, - GETPROP_DOD_OBJSCORE, - GETPROP_DOD_DEATHS, - GETPROP_DOD_SMOKESPAWN_TIME, - GETPROP_DOD_ROUNDTIME, - GETPROP_DOD_K98ZOOM, - GETPROP_DOD_GARANDZOOM, - GETPROP_DOD_ALLIESBOMBING, - GETPROP_DOD_AXISBOMBING, - GETPROP_DOD_BOMBSPLANTED, - GETPROP_DOD_BOMBSREQ, - GETPROP_DOD_BOMBSDEFUSED, - GETPROP_DOD_BOMBSREMAINING, - GETPROP_DOD_PLANTINGBOMB, - GETPROP_DOD_DEFUSINGBOMB, - GETPROP_ALL_ENTOWNER, - GETPROP_DOD_BOMB_STATE, - GETPROP_DOD_BOMB_TEAM, - GETPROP_DOD_CP_VISIBLE, - GETPROP_GROUND_ENTITY, - GETPROP_ORIGIN, - GETPROP_TAKEDAMAGE, - GETPROP_SENTRY_ENEMY, - GETPROP_WATERLEVEL, - GETPROP_TF2OBJECTSHELLS, - GETPROP_TF2OBJECTROCKETS, - GETPROP_TF2_TELEPORT_RECHARGETIME, - GETPROP_TF2_TELEPORT_RECHARGEDURATION, - GETPROP_TF2_OBJTR_m_vCPPositions, - GETPROP_TF2_OBJTR_m_bCPIsVisible, - GETPROP_TF2_OBJTR_m_iTeamIcons, - GETPROP_TF2_OBJTR_m_iTeamOverlays, - GETPROP_TF2_OBJTR_m_iTeamReqCappers, - GETPROP_TF2_OBJTR_m_flTeamCapTime, - GETPROP_TF2_OBJTR_m_iPreviousPoints, - GETPROP_TF2_OBJTR_m_bTeamCanCap, - GETPROP_TF2_OBJTR_m_iTeamBaseIcons, - GETPROP_TF2_OBJTR_m_iBaseControlPoints, - GETPROP_TF2_OBJTR_m_bInMiniRound, - GETPROP_TF2_OBJTR_m_iWarnOnCap, - GETPROP_TF2_OBJTR_m_iCPGroup, - GETPROP_TF2_OBJTR_m_bCPLocked, - GETPROP_TF2_OBJTR_m_bTrackAlarm, - GETPROP_TF2_OBJTR_m_flUnlockTimes, - GETPROP_TF2_OBJTR_m_flCPTimerTimes, - GETPROP_TF2_OBJTR_m_iNumTeamMembers, - GETPROP_TF2_OBJTR_m_iCappingTeam, - GETPROP_TF2_OBJTR_m_iTeamInZone, - GETPROP_TF2_OBJTR_m_bBlocked, - GETPROP_TF2_OBJTR_m_iOwner, - GETPROP_TF2_OBJTR_m_bCPCapRateScalesWithPlayers, - GETPROP_TF2_OBJTR_m_iNumControlPoints, - GETPROP_TF2_OBJTR_m_bPlayingMiniRounds, - GETPROP_TF2_RNDTM_m_flTimerEndTime, - GETPROP_TF2_RNDTM_m_nSetupTimeLength, - GETPROP_TF2_RNDTM_m_bInSetup, - GETPROP_PIPEBOMB_OWNER, - GETPROP_TF2_TAUNTYAW, - GETPROP_TF2_HIGHFIVE, - GETPROP_TF2_HIGHFIVE_PARTNER, - GETPROP_SENTRYGUN_PLACING, - GETPROP_TF2_ISCARRYINGOBJ, - GETPROP_TF2_GETCARRIEDOBJ, - GETPROP_TF2_ATTRIBUTELIST, - GETPROP_TF2_ITEMDEFINITIONINDEX, - GETPROP_TF2_DISGUISEWEARABLE, - GETPROP_TF2_ENTITYLEVEL, - GETPROP_TF2_RAGEMETER, - GETPROP_TF2_RAGEDRAINING, - GETPROP_TF2_ENTITYQUALITY, - GETPROP_SIMULATIONTIME, - GETPROP_TF2_WEAPON_INITIALIZED, - GETPROP_TF2_INUPGRADEZONE, - GETPROP_TF2_EXTRAWEARABLE, - GETPROP_TF2_EXTRAWEARABLEVIEWMODEL, - GETPROP_TF2_ENERGYDRINKMETER, - GETPROP_TF2_MEDIEVALMODE, - GETPROP_TF2_ACTIVEWEAPON, - GETPROP_TF2_BUILDER_TYPE, - GETPROP_TF2_BUILDER_MODE, - GETPROP_TF2_CHARGE_RESIST_TYPE, - GETPROP_TF2_ROUNDSTATE, - GETPROP_TF2DESIREDCLASS, //Jrob - GET_PROPDATA_MAX -}getpropdata_id; - -bool UTIL_FindSendPropInfo(ServerClass *pInfo, const char *szType, unsigned int *offset); + GETPROP_TF2TELEPORTERMODE = 17, + GETPROP_CURRENTWEAPON = 18, + GETPROP_TF2UBERCHARGE_LEVEL = 19, + GETPROP_TF2SENTRYHEALTH = 20, + GETPROP_TF2DISPENSERHEALTH = 21, + GETPROP_TF2TELEPORTERHEALTH = 22, + GETPROP_TF2OBJECTCARRIED = 23, + GETPROP_TF2OBJECTUPGRADELEVEL = 24, + GETPROP_TF2OBJECTUPGRADEMETAL = 25, + GETPROP_TF2OBJECTMAXHEALTH = 26, + GETPROP_TF2DISPMETAL = 27, + GETPROP_TF2MINIBUILDING = 28, + GETPROP_MAXSPEED = 29, + GETPROP_CONSTRAINT_SPEED = 30, + GETPROP_TF2OBJECTBUILDING = 31, + GETPROP_HL2DM_PHYSCANNON_ATTACHED = 32, + GETPROP_HL2DM_PHYSCANNON_OPEN = 33, + GETPROP_HL2DM_PLAYER_AUXPOWER = 34, + GETPROP_HL2DM_LADDER_ENT = 35, + GETPROP_WEAPONLIST = 36, + GETPROP_WEAPONSTATE = 37, + GETPROP_WEAPONCLIP1 = 38, + GETPROP_WEAPONCLIP2 = 39, + GETPROP_WEAPON_AMMOTYPE1 = 40, + GETPROP_WEAPON_AMMOTYPE2 = 41, + GETPROP_DOD_PLAYERCLASS = 42, + GETPROP_DOD_DES_PLAYERCLASS = 43, + GETPROP_DOD_STAMINA = 44, + GETPROP_DOD_PRONE = 45, + GETPROP_SEQUENCE = 46, + GETPROP_CYCLE = 47, + GETPROP_ENTITYFLAGS = 48, + GETPROP_DOD_CP_NUMCAPS = 49, + GETPROP_DOD_CP_POSITIONS = 50, + GETPROP_DOD_CP_ALLIES_REQ_CAP = 51, + GETPROP_DOD_CP_AXIS_REQ_CAP = 52, + GETPROP_DOD_CP_NUM_AXIS = 53, + GETPROP_DOD_CP_NUM_ALLIES = 54, + GETPROP_DOD_CP_OWNER = 55, + GETPROP_DOD_SNIPER_ZOOMED = 56, + GETPROP_DOD_MACHINEGUN_DEPLOYED = 57, + GETPROP_DOD_ROCKET_DEPLOYED = 58, + GETPROP_DOD_SEMI_AUTO = 59, + GETPROP_MOVETYPE = 60, + GETPROP_DOD_GREN_THROWER = 61, + GETPROP_DOD_SCORE = 62, + GETPROP_DOD_OBJSCORE = 63, + GETPROP_DOD_DEATHS = 64, + GETPROP_DOD_SMOKESPAWN_TIME = 65, + GETPROP_DOD_ROUNDTIME = 66, + GETPROP_DOD_K98ZOOM = 67, + GETPROP_DOD_GARANDZOOM = 68, + GETPROP_DOD_ALLIESBOMBING = 69, + GETPROP_DOD_AXISBOMBING = 70, + GETPROP_DOD_BOMBSPLANTED = 71, + GETPROP_DOD_BOMBSREQ = 72, + GETPROP_DOD_BOMBSDEFUSED = 73, + GETPROP_DOD_BOMBSREMAINING = 74, + GETPROP_DOD_PLANTINGBOMB = 75, + GETPROP_DOD_DEFUSINGBOMB = 76, + GETPROP_ALL_ENTOWNER = 77, + GETPROP_DOD_BOMB_STATE = 78, + GETPROP_DOD_BOMB_TEAM = 79, + GETPROP_DOD_CP_VISIBLE = 80, + GETPROP_GROUND_ENTITY = 81, + GETPROP_ORIGIN = 82, + GETPROP_TAKEDAMAGE = 83, + GETPROP_SENTRY_ENEMY = 84, + GETPROP_WATERLEVEL = 85, + GETPROP_TF2OBJECTSHELLS = 86, + GETPROP_TF2OBJECTROCKETS = 87, + GETPROP_TF2_TELEPORT_RECHARGETIME = 88, + GETPROP_TF2_TELEPORT_RECHARGEDURATION = 89, + GETPROP_TF2_OBJTR_m_vCPPositions = 90, + GETPROP_TF2_OBJTR_m_bCPIsVisible = 91, + GETPROP_TF2_OBJTR_m_iTeamIcons = 92, + GETPROP_TF2_OBJTR_m_iTeamOverlays = 93, + GETPROP_TF2_OBJTR_m_iTeamReqCappers = 94, + GETPROP_TF2_OBJTR_m_flTeamCapTime = 95, + GETPROP_TF2_OBJTR_m_iPreviousPoints = 96, + GETPROP_TF2_OBJTR_m_bTeamCanCap = 97, + GETPROP_TF2_OBJTR_m_iTeamBaseIcons = 98, + GETPROP_TF2_OBJTR_m_iBaseControlPoints = 99, + GETPROP_TF2_OBJTR_m_bInMiniRound = 100, + GETPROP_TF2_OBJTR_m_iWarnOnCap = 101, + GETPROP_TF2_OBJTR_m_iCPGroup = 102, + GETPROP_TF2_OBJTR_m_bCPLocked = 103, + GETPROP_TF2_OBJTR_m_bTrackAlarm = 104, + GETPROP_TF2_OBJTR_m_flUnlockTimes = 105, + GETPROP_TF2_OBJTR_m_flCPTimerTimes = 106, + GETPROP_TF2_OBJTR_m_iNumTeamMembers = 107, + GETPROP_TF2_OBJTR_m_iCappingTeam = 108, + GETPROP_TF2_OBJTR_m_iTeamInZone = 109, + GETPROP_TF2_OBJTR_m_bBlocked = 110, + GETPROP_TF2_OBJTR_m_iOwner = 111, + GETPROP_TF2_OBJTR_m_bCPCapRateScalesWithPlayers = 112, + GETPROP_TF2_OBJTR_m_iNumControlPoints = 113, + GETPROP_TF2_OBJTR_m_bPlayingMiniRounds = 114, + GETPROP_TF2_RNDTM_m_flTimerEndTime = 115, + GETPROP_TF2_RNDTM_m_nSetupTimeLength = 116, + GETPROP_TF2_RNDTM_m_bInSetup = 117, + GETPROP_PIPEBOMB_OWNER = 118, + GETPROP_TF2_TAUNTYAW = 119, + GETPROP_TF2_HIGHFIVE = 120, + GETPROP_TF2_HIGHFIVE_PARTNER = 121, + GETPROP_SENTRYGUN_PLACING = 122, + GETPROP_TF2_ISCARRYINGOBJ = 123, + GETPROP_TF2_GETCARRIEDOBJ = 124, + GETPROP_TF2_ITEMDEFINITIONINDEX = 125, + GETPROP_TF2_DISGUISEWEARABLE = 126, + GETPROP_TF2_RAGEMETER = 127, + GETPROP_TF2_RAGEDRAINING = 128, + GETPROP_SIMULATIONTIME = 129, + GETPROP_TF2_INUPGRADEZONE = 130, + GETPROP_TF2_ENERGYDRINKMETER = 131, + GETPROP_TF2_MEDIEVALMODE = 132, + GETPROP_TF2_ACTIVEWEAPON = 133, + GETPROP_TF2_BUILDER_TYPE = 134, + GETPROP_TF2_BUILDER_MODE = 135, + GETPROP_TF2_CHARGE_RESIST_TYPE = 136, + GETPROP_TF2_ROUNDSTATE = 137, + GETPROP_TF2DESIREDCLASS = 138, //Jrob + GETPROP_SYN_PLAYER_VEHICLE = 139, + GETPROP_SYN_VEHICLE_DRIVER = 140, + GETPROP_SYN_SUITPOWER = 141, + GETPROP_CSS_MONEY = 142, + GETPROP_CSS_INBUYZONE = 143, + GETPROP_CSS_INBOMBZONE = 144, + GETPROP_CSS_INHOSTAGERESCUEZONE = 145, + GETPROP_CSS_ARMOR = 146, + GETPROP_CSS_HASDEFUSER = 147, + GETPROP_CSS_HASHELMET = 148, + GETPROP_CSS_BOMBTICKING = 149, + GETPROP_PLAYER_FOV = 150, + GETPROP_PLAYER_LIFESTATE = 151, + GETPROP_CSS_HOSTAGE_HEALTH = 152, + GETPROP_CSS_HOSTAGE_RESCUED = 153, + GETPROP_CSS_HOSTAGE_LEADER = 154, + GET_PROPDATA_MAX = 155 +} getpropdata_id; + +bool UTIL_FindSendPropInfo(const ServerClass *pInfo, const char *szType, unsigned *offset); ServerClass *UTIL_FindServerClass(const char *name); void UTIL_FindServerClassPrint(const char*name_cmd); void UTIL_FindServerClassnamePrint(const char *name_cmd); void UTIL_FindPropPrint(const char *prop_name); +unsigned UTIL_FindInDataMap(const datamap_t* pMap, const char* name); +datamap_t* CBaseEntity_GetDataDescMap(CBaseEntity* pEntity); +datamap_t* VGetDataDescMap(CBaseEntity* pThisPtr, int offset); class CClassInterfaceValue { public: CClassInterfaceValue () { - m_data = NULL; - m_class = NULL; - m_value = NULL; + m_data = nullptr; + m_class = nullptr; + m_value = nullptr; m_offset = 0; + m_preoffset = 0; } - CClassInterfaceValue ( char *key, char *value, unsigned int preoffset ) + CClassInterfaceValue (const char *key, const char *value, const unsigned preoffset) { init(key,value,preoffset); } - void init ( char *key, char *value, unsigned int preoffset = 0 ); + void init (const char* key, const char* value, unsigned preoffset = 0); void findOffset ( ); @@ -191,7 +209,7 @@ class CClassInterfaceValue CBaseHandle *getEntityHandle ( edict_t *edict ); - inline bool getBool(void *edict, bool defaultvalue, bool bIsEdict = true) + bool getBool(void *edict, const bool defaultvalue, const bool bIsEdict = true) { getData(edict, bIsEdict); @@ -200,7 +218,7 @@ class CClassInterfaceValue try { - return *((bool*)m_data); + return *static_cast(m_data); } catch(...) @@ -209,75 +227,73 @@ class CClassInterfaceValue } } - inline bool *getBoolPointer ( edict_t *edict ) + bool *getBoolPointer ( edict_t *edict ) { getData(edict); if ( !m_data ) - return NULL; + return nullptr; - return ((bool*)m_data); + return static_cast(m_data); } - inline void *getVoidPointer ( edict_t *edict ) + void *getVoidPointer ( edict_t *edict ) { getData(edict); if ( !m_data ) - return NULL; + return nullptr; return m_data; } - inline float getFloat ( edict_t *edict, float defaultvalue ) + float getFloat ( edict_t *edict, const float defaultvalue ) { getData(edict); if ( !m_data ) return defaultvalue; - return *((float*)m_data); + return *static_cast(m_data); } - inline float *getFloatPointer ( edict_t *edict ) + float *getFloatPointer ( edict_t *edict ) { getData(edict); if ( !m_data ) - return NULL; + return nullptr; - return ((float*)m_data); + return static_cast(m_data); } - inline char *getString (edict_t *edict ) + char *getString (edict_t *edict ) { getData(edict); - return (char*)m_data; + return static_cast(m_data); } - inline Vector *getVectorPointer ( edict_t *edict ) + Vector *getVectorPointer ( edict_t *edict ) { getData(edict); if ( m_data ) { - return (Vector*)m_data; + return static_cast(m_data); } - return NULL; + return nullptr; } - inline bool getVector ( edict_t *edict, Vector *v ) + bool getVector ( edict_t *edict, Vector *v ) { - static float *x; - getData(edict); if ( m_data ) { - x = (float*)m_data; - *v = Vector(*x,*(x+1),*(x+2)); + float* x = static_cast(m_data); + *v = Vector(*x, *(x + 1), *(x + 2)); return true; } @@ -285,7 +301,7 @@ class CClassInterfaceValue return false; } - inline int getInt(void *edict, int defaultvalue, bool bIsEdict = true) + int getInt(void *edict, const int defaultvalue, const bool bIsEdict = true) { getData(edict, bIsEdict); @@ -294,7 +310,7 @@ class CClassInterfaceValue try { - return *((int*)m_data); + return *static_cast(m_data); } catch ( ... ) @@ -303,40 +319,40 @@ class CClassInterfaceValue } } - inline int *getIntPointer ( edict_t *edict ) + int *getIntPointer ( edict_t *edict ) { getData(edict); - return (int*)m_data; + return static_cast(m_data); } - inline byte *getBytePointer ( edict_t *edict ) + byte *getBytePointer ( edict_t *edict ) { getData(edict); - return (byte*)m_data; + return static_cast(m_data); } - inline float getFloatFromInt ( edict_t *edict, float defaultvalue ) + float getFloatFromInt ( edict_t *edict, const float defaultvalue ) { getData(edict); if ( !m_data ) return defaultvalue; - return (float)(*(int *)m_data); + return static_cast(*static_cast(m_data)); } static void resetError () { m_berror = false; } static bool isError () { return m_berror; } - int getOffset() + int getOffset() const { - return m_offset; + return static_cast(m_offset); } private: - unsigned int m_offset; - unsigned int m_preoffset; + unsigned m_offset; + unsigned m_preoffset; void *m_data; char *m_class; char *m_value; @@ -348,7 +364,6 @@ class CClassInterfaceValue extern CClassInterfaceValue g_GetProps[GET_PROPDATA_MAX]; class CTFObjectiveResource; class CTeamRoundTimer; -class CAttributeList; #define DEFINE_GETPROP(id,classname,value,preoffs)\ g_GetProps[id] = CClassInterfaceValue( CClassInterfaceValue ( classname, value, preoffs ) ) @@ -359,51 +374,46 @@ class CClassInterface static const char *FindEntityNetClass(int start, const char *classname); static edict_t *FindEntityByNetClass(int start, const char *classname); - static edict_t *FindEntityByNetClassNearest(Vector vstart, const char *classname); - static edict_t *FindEntityByClassnameNearest(Vector vstart, const char *classname, float fMinDist = 8192.0f, edict_t *pOwner = NULL ); + static edict_t *FindEntityByNetClassNearest(const Vector& vstart, const char *classname); + static edict_t *FindEntityByClassnameNearest(const Vector& vstart, const char *classname, float fMinDist = 8192.0f, const edict_t *pOwner = nullptr); // TF2 - static int getTF2Score ( edict_t *edict ); + static int getTF2Score (const edict_t* edict); static void setupCTeamRoundTimer ( CTeamRoundTimer *pTimer ); - inline static float getRageMeter ( edict_t *edict ) { return g_GetProps[GETPROP_TF2_RAGEMETER].getFloat(edict,0); } - inline static int getFlags ( edict_t *edict ) { return g_GetProps[GETPROP_ENTITY_FLAGS].getInt(edict,0); } - inline static int getTeam ( edict_t *edict ) { return g_GetProps[GETPROP_TEAM].getInt(edict,0); } - inline static float getPlayerHealth ( edict_t *edict ) { return g_GetProps[GETPROP_PLAYERHEALTH].getFloatFromInt(edict,0); } - inline static int getEffects ( edict_t *edict ) { return g_GetProps[GETPROP_EFFECTS].getInt(edict,0); } - inline static int *getAmmoList ( edict_t *edict ) { return g_GetProps[GETPROP_AMMO].getIntPointer(edict); } - //static unsigned int findOffset(const char *szType,const char *szClass); - inline static int getTF2NumHealers ( edict_t *edict ) { return g_GetProps[GETPROP_TF2_NUMHEALERS].getInt(edict,0); } - inline static int getTF2Conditions ( edict_t *edict ) { return g_GetProps[GETPROP_TF2_CONDITIONS].getInt(edict,0); } - inline static bool getVelocity ( edict_t *edict, Vector *v ) {return g_GetProps[GETPROP_VELOCITY].getVector(edict,v); } - inline static int getTF2Class ( edict_t *edict ) { return g_GetProps[GETPROP_TF2CLASS].getInt(edict,0); } - inline static edict_t *getExtraWearable(edict_t *edict) { return g_GetProps[GETPROP_TF2_EXTRAWEARABLE].getEntity(edict); } - inline static edict_t *getExtraWearableViewModel(edict_t *edict) { return g_GetProps[GETPROP_TF2_EXTRAWEARABLEVIEWMODEL].getEntity(edict); } - inline static float TF2_getEnergyDrinkMeter(edict_t * edict) { return g_GetProps[GETPROP_TF2_ENERGYDRINKMETER].getFloat(edict, 0); } - inline static void setInitialized ( edict_t *edict ) - { - bool *m_bInitialized = g_GetProps[GETPROP_TF2_WEAPON_INITIALIZED].getBoolPointer(edict); - - *m_bInitialized = true; - } - inline static edict_t *TF2_getActiveWeapon(edict_t *edict) { return g_GetProps[GETPROP_TF2_ACTIVEWEAPON].getEntity(edict); } + static float getRageMeter ( edict_t *edict ) { return g_GetProps[GETPROP_TF2_RAGEMETER].getFloat(edict,0); } + static int getFlags ( edict_t *edict ) { return g_GetProps[GETPROP_ENTITY_FLAGS].getInt(edict,0); } + static int getTeam ( edict_t *edict ) { return g_GetProps[GETPROP_TEAM].getInt(edict,0); } + static float getPlayerHealth ( edict_t *edict ) { return g_GetProps[GETPROP_PLAYERHEALTH].getFloatFromInt(edict,0); } + static int getEffects ( edict_t *edict ) { return g_GetProps[GETPROP_EFFECTS].getInt(edict,0); } + static int *getAmmoList ( edict_t *edict ) { return g_GetProps[GETPROP_AMMO].getIntPointer(edict); } + //static unsigned findOffset(const char *szType,const char *szClass); + static int getTF2NumHealers ( edict_t *edict ) { return g_GetProps[GETPROP_TF2_NUMHEALERS].getInt(edict,0); } + static int getTF2Conditions ( edict_t *edict ) { return g_GetProps[GETPROP_TF2_CONDITIONS].getInt(edict,0); } + static bool getVelocity ( edict_t *edict, Vector *v ) {return g_GetProps[GETPROP_VELOCITY].getVector(edict,v); } + static int getTF2Class ( edict_t *edict ) { return g_GetProps[GETPROP_TF2CLASS].getInt(edict,0); } + static float TF2_getEnergyDrinkMeter(edict_t * edict) { return g_GetProps[GETPROP_TF2_ENERGYDRINKMETER].getFloat(edict, 0); } + static edict_t *TF2_getActiveWeapon(edict_t *edict) { return g_GetProps[GETPROP_TF2_ACTIVEWEAPON].getEntity(edict); } // set weapon - static bool TF2_setActiveWeapon(edict_t *edict, edict_t *pWeapon) + static void TF2_setActiveWeapon(edict_t* edict, edict_t* pWeapon) //-caxanga334 { - CBaseHandle *pHandle = g_GetProps[GETPROP_TF2_ACTIVEWEAPON].getEntityHandle(edict); + CBaseHandle* pHandle = g_GetProps[GETPROP_TF2_ACTIVEWEAPON].getEntityHandle(edict); pHandle->Set(pWeapon->GetNetworkable()->GetEntityHandle()); } - inline static void TF2_SetBuilderType(edict_t *pBuilder, int itype) + + static void TF2_SetBuilderType(edict_t *pBuilder, const int itype) { int *pitype = g_GetProps[GETPROP_TF2_BUILDER_TYPE].getIntPointer(pBuilder); *pitype = itype; //, ] } - inline static int getChargeResistType(edict_t *pMedigun) + + static int getChargeResistType(edict_t *pMedigun) { return g_GetProps[GETPROP_TF2_CHARGE_RESIST_TYPE].getInt(pMedigun, 0); } - inline static void TF2_SetBuilderMode(edict_t *pBuilder, int imode) + + static void TF2_SetBuilderMode(edict_t *pBuilder, const int imode) { int *pitype = g_GetProps[GETPROP_TF2_BUILDER_MODE].getIntPointer(pBuilder); @@ -411,26 +421,26 @@ class CClassInterface //GETPROP_TF2_BUILDER_MODE, ] } //Jrob - inline static int getTF2DesiredClass(edict_t *edict) { return g_GetProps[GETPROP_TF2DESIREDCLASS].getInt(edict, 0); } - inline static void setTF2Class(edict_t *edict, int _class) + static int getTF2DesiredClass(edict_t *edict) { return g_GetProps[GETPROP_TF2DESIREDCLASS].getInt(edict, 0); } + + static void setTF2Class(edict_t *edict, const int _class) { int* p = g_GetProps[GETPROP_TF2DESIREDCLASS].getIntPointer(edict); - if (p != NULL) *p = _class; + if (p != nullptr) *p = _class; } //end Jrob - inline static bool TF2_IsMedievalMode(void*gamerules) { return g_GetProps[GETPROP_TF2_MEDIEVALMODE].getBool(gamerules, false, false);} - inline static int TF2_getRoundState(void *gamerules) { return g_GetProps[GETPROP_TF2_ROUNDSTATE].getInt(gamerules, 0, 0); } - inline static float getTF2SpyCloakMeter ( edict_t *edict ) { return g_GetProps[GETPROP_TF2SPYMETER].getFloat(edict,0); } - inline static int getWaterLevel ( edict_t *edict ) { return g_GetProps[GETPROP_WATERLEVEL].getInt(edict,0); } - inline static void updateSimulationTime ( edict_t *edict ) - { - float *m_flSimulationTime = g_GetProps[GETPROP_SIMULATIONTIME].getFloatPointer(edict); + static bool TF2_IsMedievalMode(void*gamerules) { return g_GetProps[GETPROP_TF2_MEDIEVALMODE].getBool(gamerules, false, false);} + static int TF2_getRoundState(void *gamerules) { return g_GetProps[GETPROP_TF2_ROUNDSTATE].getInt(gamerules, 0, false); } + static float getTF2SpyCloakMeter ( edict_t *edict ) { return g_GetProps[GETPROP_TF2SPYMETER].getFloat(edict,0); } + static int getWaterLevel ( edict_t *edict ) { return g_GetProps[GETPROP_WATERLEVEL].getInt(edict,0); } - if ( m_flSimulationTime ) + static void updateSimulationTime ( edict_t *edict ) + { + if ( float *m_flSimulationTime = g_GetProps[GETPROP_SIMULATIONTIME].getFloatPointer(edict) ) *m_flSimulationTime = gpGlobals->curtime; } - inline static bool *getDODCPVisible ( edict_t *pResource ) { return g_GetProps[GETPROP_DOD_CP_VISIBLE].getBoolPointer(pResource); } + static bool *getDODCPVisible ( edict_t *pResource ) { return g_GetProps[GETPROP_DOD_CP_VISIBLE].getBoolPointer(pResource); } static bool getTF2SpyDisguised( edict_t *edict, int *_class, int *_team, int *_index, int *_health ) { CClassInterfaceValue::resetError(); @@ -440,8 +450,11 @@ class CClassInterface if ( _class ) *_class = g_GetProps[GETPROP_TF2SPYDISGUISED_CLASS].getInt(edict,0); - if ( _index ) - *_index = g_GetProps[GETPROP_TF2SPYDISGUISED_TARGET_INDEX].getInt(edict,0); + if ( _index )//nosoop fix for VScript update + { + const edict_t* hTarget = g_GetProps[GETPROP_TF2SPYDISGUISED_TARGET].getEntity(edict); + *_index = IndexOfEdict(hTarget); + } if ( _health ) *_health = g_GetProps[GETPROP_TF2SPYDISGUISED_DIS_HEALTH].getInt(edict,0); @@ -449,128 +462,107 @@ class CClassInterface return !CClassInterfaceValue::isError(); } - inline static int TF2_getItemDefinitionIndex(edict_t *edict) + static int TF2_getItemDefinitionIndex(edict_t *edict) { return g_GetProps[GETPROP_TF2_ITEMDEFINITIONINDEX].getInt(edict, 0); } - inline static void setEntityIndex_Level_Quality( edict_t *edict, int iIndex, int iLevel = 0, int iQuality = 0 ) - { - int *pdata = g_GetProps[GETPROP_TF2_ITEMDEFINITIONINDEX].getIntPointer(edict); - - if ( pdata ) - *pdata = iIndex; - - if ( iLevel ) - { - int *pdata = g_GetProps[GETPROP_TF2_ENTITYLEVEL].getIntPointer(edict); - - if ( pdata ) - *pdata = iLevel; - } - if ( iQuality ) - { - int *pdata = g_GetProps[GETPROP_TF2_ENTITYQUALITY].getIntPointer(edict); - if ( pdata ) - *pdata = iQuality; - } - } - inline static bool isCarryingObj ( edict_t *edict ) { return g_GetProps[GETPROP_TF2_ISCARRYINGOBJ].getBool(edict,false); } - inline static edict_t *getCarriedObj ( edict_t *edict ) { return g_GetProps[GETPROP_TF2_GETCARRIEDOBJ].getEntity(edict); } - inline static bool getMedigunHealing ( edict_t *edict ) { return g_GetProps[GETPROP_TF2MEDIGUN_HEALING].getBool(edict,false); } - inline static edict_t *getMedigunTarget ( edict_t *edict ) { return g_GetProps[GETPROP_TF2MEDIGUN_TARGETTING].getEntity(edict); } - inline static edict_t *getSentryEnemy ( edict_t *edict ) { return g_GetProps[GETPROP_SENTRY_ENEMY].getEntity(edict); } - inline static edict_t *getOwner ( edict_t *edict ) { return g_GetProps[GETPROP_ALL_ENTOWNER].getEntity(edict); } - inline static bool isMedigunTargetting ( edict_t *pgun, edict_t *ptarget) { return (g_GetProps[GETPROP_TF2MEDIGUN_TARGETTING].getEntity(pgun) == ptarget); } + static bool isCarryingObj ( edict_t *edict ) { return g_GetProps[GETPROP_TF2_ISCARRYINGOBJ].getBool(edict,false); } + static edict_t *getCarriedObj ( edict_t *edict ) { return g_GetProps[GETPROP_TF2_GETCARRIEDOBJ].getEntity(edict); } + static bool getMedigunHealing ( edict_t *edict ) { return g_GetProps[GETPROP_TF2MEDIGUN_HEALING].getBool(edict,false); } + static edict_t *getMedigunTarget ( edict_t *edict ) { return g_GetProps[GETPROP_TF2MEDIGUN_TARGETTING].getEntity(edict); } + static edict_t *getSentryEnemy ( edict_t *edict ) { return g_GetProps[GETPROP_SENTRY_ENEMY].getEntity(edict); } + static edict_t *getOwner ( edict_t *edict ) { return g_GetProps[GETPROP_ALL_ENTOWNER].getEntity(edict); } + static bool isMedigunTargetting ( edict_t *pgun, const edict_t *ptarget) { return g_GetProps[GETPROP_TF2MEDIGUN_TARGETTING].getEntity(pgun) == ptarget; } //static void setTickBase ( edict_t *edict, int tickbase ) { return ; - inline static int isTeleporterMode (edict_t *edict, eTeleMode mode ) { return (g_GetProps[GETPROP_TF2TELEPORTERMODE].getInt(edict,-1) == (int)mode); } - inline static edict_t *getCurrentWeapon (edict_t *player) { return g_GetProps[GETPROP_CURRENTWEAPON].getEntity(player); } - inline static int getUberChargeLevel (edict_t *pWeapon) { return (int)(g_GetProps[GETPROP_TF2UBERCHARGE_LEVEL].getFloat(pWeapon,0)*100.0); } + static int isTeleporterMode (edict_t *edict, const eTeleMode mode ) { return g_GetProps[GETPROP_TF2TELEPORTERMODE].getInt(edict,-1) == static_cast(mode); } + static edict_t *getCurrentWeapon (edict_t *player) { return g_GetProps[GETPROP_CURRENTWEAPON].getEntity(player); } + static int getUberChargeLevel (edict_t *pWeapon) { return static_cast(g_GetProps[GETPROP_TF2UBERCHARGE_LEVEL].getFloat(pWeapon, 0) * 100.0f); } //static void test (); - inline static float getSentryHealth ( edict_t *edict ) { return g_GetProps[GETPROP_TF2SENTRYHEALTH].getFloatFromInt(edict,100); } - inline static float getDispenserHealth ( edict_t *edict ) { return g_GetProps[GETPROP_TF2DISPENSERHEALTH].getFloatFromInt(edict,100); } - inline static float getTeleporterHealth ( edict_t *edict ) { return g_GetProps[GETPROP_TF2TELEPORTERHEALTH].getFloatFromInt(edict,100); } - inline static bool isObjectCarried ( edict_t *edict ) { return g_GetProps[GETPROP_TF2OBJECTCARRIED].getBool(edict,false); } - inline static int getTF2UpgradeLevel ( edict_t *edict ) { return g_GetProps[GETPROP_TF2OBJECTUPGRADELEVEL].getInt(edict,0); } - inline static int getTF2SentryUpgradeMetal ( edict_t *edict ) { return g_GetProps[GETPROP_TF2OBJECTUPGRADEMETAL].getInt(edict,0); } - inline static int getTF2SentryShells ( edict_t *edict ) { return g_GetProps[GETPROP_TF2OBJECTSHELLS].getInt(edict,0); } - inline static int getTF2SentryRockets ( edict_t *edict ) { return g_GetProps[GETPROP_TF2OBJECTROCKETS].getInt(edict,0); } + static float getSentryHealth ( edict_t *edict ) { return g_GetProps[GETPROP_TF2SENTRYHEALTH].getFloatFromInt(edict,100); } + static float getDispenserHealth ( edict_t *edict ) { return g_GetProps[GETPROP_TF2DISPENSERHEALTH].getFloatFromInt(edict,100); } + static float getTeleporterHealth ( edict_t *edict ) { return g_GetProps[GETPROP_TF2TELEPORTERHEALTH].getFloatFromInt(edict,100); } + static bool isObjectCarried ( edict_t *edict ) { return g_GetProps[GETPROP_TF2OBJECTCARRIED].getBool(edict,false); } + static int getTF2UpgradeLevel ( edict_t *edict ) { return g_GetProps[GETPROP_TF2OBJECTUPGRADELEVEL].getInt(edict,0); } + static int getTF2SentryUpgradeMetal ( edict_t *edict ) { return g_GetProps[GETPROP_TF2OBJECTUPGRADEMETAL].getInt(edict,0); } + static int getTF2SentryShells ( edict_t *edict ) { return g_GetProps[GETPROP_TF2OBJECTSHELLS].getInt(edict,0); } + static int getTF2SentryRockets ( edict_t *edict ) { return g_GetProps[GETPROP_TF2OBJECTROCKETS].getInt(edict,0); } static bool getTF2ObjectiveResource ( CTFObjectiveResource *pResource ); - inline static float getTF2TeleRechargeTime(edict_t *edict) { return g_GetProps[GETPROP_TF2_TELEPORT_RECHARGETIME].getFloat(edict,0); } - inline static float getTF2TeleRechargeDuration(edict_t *edict) { return g_GetProps[GETPROP_TF2_TELEPORT_RECHARGEDURATION].getFloat(edict,0); } - - inline static int getTF2GetBuildingMaxHealth ( edict_t *edict ) { return g_GetProps[GETPROP_TF2OBJECTMAXHEALTH].getInt(edict,0); } - inline static int getTF2DispMetal ( edict_t *edict ) { return g_GetProps[GETPROP_TF2DISPMETAL].getInt(edict,0); } - inline static bool getTF2BuildingIsMini ( edict_t *edict ) { return g_GetProps[GETPROP_TF2MINIBUILDING].getBool(edict,false); } - inline static float getMaxSpeed(edict_t *edict) { return g_GetProps[GETPROP_MAXSPEED].getFloat(edict,0); } - inline static float getSpeedFactor(edict_t *edict) { return g_GetProps[GETPROP_CONSTRAINT_SPEED].getFloat(edict,0); } - inline static bool isObjectBeingBuilt(edict_t *edict) { return g_GetProps[GETPROP_TF2OBJECTBUILDING].getBool(edict,false); } - inline static edict_t *getGroundEntity(edict_t *edict) { return g_GetProps[GETPROP_GROUND_ENTITY].getEntity(edict); } - inline static edict_t *gravityGunObject(edict_t *pgun) { return g_GetProps[GETPROP_HL2DM_PHYSCANNON_ATTACHED].getEntity(pgun); } - inline static bool gravityGunOpen(edict_t *pgun) { return g_GetProps[GETPROP_HL2DM_PHYSCANNON_OPEN].getBool(pgun,false); } - inline static float auxPower (edict_t *player) { return g_GetProps[GETPROP_HL2DM_PLAYER_AUXPOWER].getFloat(player,0);} - inline static edict_t *onLadder ( edict_t *player ) { return g_GetProps[GETPROP_HL2DM_LADDER_ENT].getEntity(player);} - inline static CBaseHandle *getWeaponList ( edict_t *player ) { return g_GetProps[GETPROP_WEAPONLIST].getEntityHandle(player);} - inline static int getWeaponState ( edict_t *pgun ) { return g_GetProps[GETPROP_WEAPONSTATE].getInt(pgun,0); } - - inline static edict_t *getPipeBombOwner ( edict_t *pPipeBomb ) { return g_GetProps[GETPROP_PIPEBOMB_OWNER].getEntity(pPipeBomb); } - - inline static int getDODBombState ( edict_t *pBombTarget ) { return g_GetProps[GETPROP_DOD_BOMB_STATE].getInt(pBombTarget,0); } - inline static int getDODBombTeam ( edict_t *pBombTarget ) { return g_GetProps[GETPROP_DOD_BOMB_TEAM].getInt(pBombTarget,0); } - inline static int *getWeaponClip1Pointer ( edict_t *pgun ) { return g_GetProps[GETPROP_WEAPONCLIP1].getIntPointer(pgun); } - inline static int *getWeaponClip2Pointer ( edict_t *pgun ) { return g_GetProps[GETPROP_WEAPONCLIP2].getIntPointer(pgun); } - inline static CAttributeList *getAttributeList ( edict_t *player ) { return (CAttributeList*)g_GetProps[GETPROP_TF2_ATTRIBUTELIST].getVoidPointer(player); } - inline static int getOffset(int id) { return g_GetProps[id].getOffset(); } - inline static void getWeaponClip ( edict_t *pgun, int *iClip1, int *iClip2 ) { *iClip1 = g_GetProps[GETPROP_WEAPONCLIP1].getInt(pgun,0); *iClip2 = g_GetProps[GETPROP_WEAPONCLIP2].getInt(pgun,0); } - inline static void getAmmoTypes ( edict_t *pgun, int *iAmmoType1, int *iAmmoType2 ) { *iAmmoType1 = g_GetProps[GETPROP_WEAPON_AMMOTYPE1].getInt(pgun,-1); *iAmmoType2 = g_GetProps[GETPROP_WEAPON_AMMOTYPE2].getInt(pgun,-1);} - - inline static int getPlayerClassDOD(edict_t *player) { return g_GetProps[GETPROP_DOD_PLAYERCLASS].getInt(player,0); } - inline static void getPlayerInfoDOD(edict_t *player, bool *m_bProne, float *m_flStamina) + static float getTF2TeleRechargeTime(edict_t *edict) { return g_GetProps[GETPROP_TF2_TELEPORT_RECHARGETIME].getFloat(edict,0); } + static float getTF2TeleRechargeDuration(edict_t *edict) { return g_GetProps[GETPROP_TF2_TELEPORT_RECHARGEDURATION].getFloat(edict,0); } + + static int getTF2GetBuildingMaxHealth ( edict_t *edict ) { return g_GetProps[GETPROP_TF2OBJECTMAXHEALTH].getInt(edict,0); } + static int getTF2DispMetal ( edict_t *edict ) { return g_GetProps[GETPROP_TF2DISPMETAL].getInt(edict,0); } + static bool getTF2BuildingIsMini ( edict_t *edict ) { return g_GetProps[GETPROP_TF2MINIBUILDING].getBool(edict,false); } + static float getMaxSpeed(edict_t *edict) { return g_GetProps[GETPROP_MAXSPEED].getFloat(edict,0); } + static float getSpeedFactor(edict_t *edict) { return g_GetProps[GETPROP_CONSTRAINT_SPEED].getFloat(edict,0); } + static bool isObjectBeingBuilt(edict_t *edict) { return g_GetProps[GETPROP_TF2OBJECTBUILDING].getBool(edict,false); } + static edict_t *getGroundEntity(edict_t *edict) { return g_GetProps[GETPROP_GROUND_ENTITY].getEntity(edict); } + static edict_t *gravityGunObject(edict_t *pgun) { return g_GetProps[GETPROP_HL2DM_PHYSCANNON_ATTACHED].getEntity(pgun); } + static bool gravityGunOpen(edict_t *pgun) { return g_GetProps[GETPROP_HL2DM_PHYSCANNON_OPEN].getBool(pgun,false); } + static float auxPower (edict_t *player) { return g_GetProps[GETPROP_HL2DM_PLAYER_AUXPOWER].getFloat(player,0);} + static edict_t *onLadder ( edict_t *player ) { return g_GetProps[GETPROP_HL2DM_LADDER_ENT].getEntity(player);} + static CBaseHandle *getWeaponList ( edict_t *player ) { return g_GetProps[GETPROP_WEAPONLIST].getEntityHandle(player);} + static int getWeaponState ( edict_t *pgun ) { return g_GetProps[GETPROP_WEAPONSTATE].getInt(pgun,0); } + + static edict_t *getPipeBombOwner ( edict_t *pPipeBomb ) { return g_GetProps[GETPROP_PIPEBOMB_OWNER].getEntity(pPipeBomb); } + + static int getDODBombState ( edict_t *pBombTarget ) { return g_GetProps[GETPROP_DOD_BOMB_STATE].getInt(pBombTarget,0); } + static int getDODBombTeam ( edict_t *pBombTarget ) { return g_GetProps[GETPROP_DOD_BOMB_TEAM].getInt(pBombTarget,0); } + static int *getWeaponClip1Pointer ( edict_t *pgun ) { return g_GetProps[GETPROP_WEAPONCLIP1].getIntPointer(pgun); } + static int *getWeaponClip2Pointer ( edict_t *pgun ) { return g_GetProps[GETPROP_WEAPONCLIP2].getIntPointer(pgun); } + static int getOffset(const int id) { return g_GetProps[id].getOffset(); } + static void getWeaponClip ( edict_t *pgun, int *iClip1, int *iClip2 ) { *iClip1 = g_GetProps[GETPROP_WEAPONCLIP1].getInt(pgun,0); *iClip2 = g_GetProps[GETPROP_WEAPONCLIP2].getInt(pgun,0); } + static void getAmmoTypes ( edict_t *pgun, int *iAmmoType1, int *iAmmoType2 ) { *iAmmoType1 = g_GetProps[GETPROP_WEAPON_AMMOTYPE1].getInt(pgun,-1); *iAmmoType2 = g_GetProps[GETPROP_WEAPON_AMMOTYPE2].getInt(pgun,-1);} + + static int getPlayerClassDOD(edict_t *player) { return g_GetProps[GETPROP_DOD_PLAYERCLASS].getInt(player,0); } + + static void getPlayerInfoDOD(edict_t *player, bool *m_bProne, float *m_flStamina) { *m_bProne = g_GetProps[GETPROP_DOD_PRONE].getBool(player,false); if ( m_flStamina ) *m_flStamina = g_GetProps[GETPROP_DOD_STAMINA].getFloat(player,0); } - inline static float getAnimCycle ( edict_t *edict) + static float getAnimCycle ( edict_t *edict) { return g_GetProps[GETPROP_CYCLE].getFloat(edict,0); } - inline static void getAnimatingInfo ( edict_t *edict, float *flCycle, int *iSequence ) + static void getAnimatingInfo ( edict_t *edict, float *flCycle, int *iSequence ) { - *flCycle = g_GetProps[GETPROP_CYCLE].getFloat(edict,0); - *iSequence = g_GetProps[GETPROP_SEQUENCE].getInt(edict,false); + *flCycle = g_GetProps[GETPROP_CYCLE].getFloat(edict,0.0f); + *iSequence = g_GetProps[GETPROP_SEQUENCE].getInt(edict,0); } - inline static int getPlayerFlags (edict_t *player) { return g_GetProps[GETPROP_ENTITYFLAGS].getInt(player,0);} - inline static int *getPlayerFlagsPointer (edict_t *player) { return g_GetProps[GETPROP_ENTITYFLAGS].getIntPointer(player);} + static int getPlayerFlags (edict_t *player) { return g_GetProps[GETPROP_ENTITYFLAGS].getInt(player,0);} + static int *getPlayerFlagsPointer (edict_t *player) { return g_GetProps[GETPROP_ENTITYFLAGS].getIntPointer(player);} - inline static int getDODNumControlPoints ( edict_t *pResource ) + static int getDODNumControlPoints ( edict_t *pResource ) { return g_GetProps[GETPROP_DOD_CP_NUMCAPS].getInt(pResource,0); } - inline static Vector *getOrigin ( edict_t *pPlayer ) + static Vector *getOrigin ( edict_t *pPlayer ) { return g_GetProps[GETPROP_ORIGIN].getVectorPointer(pPlayer); } - inline static void setOrigin ( edict_t *pPlayer, Vector vOrigin ) + static void setOrigin ( edict_t *pPlayer, const Vector& vOrigin ) { Vector *vEntOrigin = g_GetProps[GETPROP_ORIGIN].getVectorPointer(pPlayer); *vEntOrigin = vOrigin; } - inline static Vector *getDODCP_Positions ( edict_t *pResource ) + static Vector *getDODCP_Positions ( edict_t *pResource ) { return g_GetProps[GETPROP_DOD_CP_POSITIONS].getVectorPointer(pResource); } - inline static void getDODFlagInfo (edict_t *pResource, int **m_iNumAxis, int **m_iNumAllies, int **m_iOwner, int **m_iNumAlliesReq, int **m_iNumAxisReq ) + static void getDODFlagInfo (edict_t *pResource, int **m_iNumAxis, int **m_iNumAllies, int **m_iOwner, int **m_iNumAlliesReq, int **m_iNumAxisReq ) { *m_iNumAxis = g_GetProps[GETPROP_DOD_CP_NUM_AXIS].getIntPointer(pResource); *m_iNumAllies = g_GetProps[GETPROP_DOD_CP_NUM_ALLIES].getIntPointer(pResource); @@ -579,7 +571,7 @@ class CClassInterface *m_iNumAxisReq = g_GetProps[GETPROP_DOD_CP_AXIS_REQ_CAP].getIntPointer(pResource); } - inline static void getDODBombInfo ( edict_t *pResource, bool **m_bBombPlanted, int **m_iBombsRequired, int **m_iBombsRemaining, bool **m_bBombBeingDefused) + static void getDODBombInfo ( edict_t *pResource, bool **m_bBombPlanted, int **m_iBombsRequired, int **m_iBombsRemaining, bool **m_bBombBeingDefused) { *m_bBombPlanted = g_GetProps[GETPROP_DOD_BOMBSPLANTED].getBoolPointer(pResource); *m_iBombsRequired = g_GetProps[GETPROP_DOD_BOMBSREQ].getIntPointer(pResource); @@ -587,132 +579,429 @@ class CClassInterface *m_bBombBeingDefused = g_GetProps[GETPROP_DOD_BOMBSDEFUSED].getBoolPointer(pResource); } - inline static float getTF2TauntYaw ( edict_t *edict ) { return g_GetProps[GETPROP_TF2_TAUNTYAW].getFloat(edict,0); } - inline static bool getTF2HighFiveReady ( edict_t *edict ) { return g_GetProps[GETPROP_TF2_HIGHFIVE].getBool(edict,false); } - inline static edict_t *getHighFivePartner ( edict_t *edict ) { return g_GetProps[GETPROP_TF2_HIGHFIVE_PARTNER].getEntity(edict); } + static float getTF2TauntYaw ( edict_t *edict ) { return g_GetProps[GETPROP_TF2_TAUNTYAW].getFloat(edict,0); } + static bool getTF2HighFiveReady ( edict_t *edict ) { return g_GetProps[GETPROP_TF2_HIGHFIVE].getBool(edict,false); } + static edict_t *getHighFivePartner ( edict_t *edict ) { return g_GetProps[GETPROP_TF2_HIGHFIVE_PARTNER].getEntity(edict); } - inline static int getDesPlayerClassDOD(edict_t *player) { return g_GetProps[GETPROP_DOD_DES_PLAYERCLASS].getInt(player,0); } + static int getDesPlayerClassDOD(edict_t *player) { return g_GetProps[GETPROP_DOD_DES_PLAYERCLASS].getInt(player,0); } - inline static bool isSniperWeaponZoomed (edict_t *weapon) { return g_GetProps[GETPROP_DOD_SNIPER_ZOOMED].getBool(weapon,false); } - inline static bool isMachineGunDeployed (edict_t *weapon) { return g_GetProps[GETPROP_DOD_MACHINEGUN_DEPLOYED].getBool(weapon,false); } - inline static bool isRocketDeployed ( edict_t *weapon ) { return g_GetProps[GETPROP_DOD_ROCKET_DEPLOYED].getBool(weapon,false); } + static bool isSniperWeaponZoomed (edict_t *weapon) { return g_GetProps[GETPROP_DOD_SNIPER_ZOOMED].getBool(weapon,false); } + static bool isMachineGunDeployed (edict_t *weapon) { return g_GetProps[GETPROP_DOD_MACHINEGUN_DEPLOYED].getBool(weapon,false); } + static bool isRocketDeployed ( edict_t *weapon ) { return g_GetProps[GETPROP_DOD_ROCKET_DEPLOYED].getBool(weapon,false); } - inline static bool isMoveType ( edict_t *pent, int movetype ) + static bool isMoveType ( edict_t *pent, const int movetype ) { - return ((g_GetProps[GETPROP_MOVETYPE].getInt(pent,0) & 15) == movetype); + return (g_GetProps[GETPROP_MOVETYPE].getInt(pent,0) & 15) == movetype; } - inline static byte getTakeDamage ( edict_t *pent ) + static byte getTakeDamage ( edict_t *pent ) { - return (byte)(g_GetProps[GETPROP_TAKEDAMAGE].getInt(pent,0)); + return static_cast(g_GetProps[GETPROP_TAKEDAMAGE].getInt(pent, 0)); } - inline static byte *getTakeDamagePointer ( edict_t *pent ) + static byte *getTakeDamagePointer ( edict_t *pent ) { - return (g_GetProps[GETPROP_TAKEDAMAGE].getBytePointer(pent)); + return g_GetProps[GETPROP_TAKEDAMAGE].getBytePointer(pent); } - inline static int getMoveType ( edict_t *pent ) + static int getMoveType ( edict_t *pent ) { - return (g_GetProps[GETPROP_MOVETYPE].getInt(pent,0) & 15); + return g_GetProps[GETPROP_MOVETYPE].getInt(pent,0) & 15; } - inline static byte *getMoveTypePointer ( edict_t *pent ) + static byte *getMoveTypePointer ( edict_t *pent ) { - return (g_GetProps[GETPROP_MOVETYPE].getBytePointer(pent)); + return g_GetProps[GETPROP_MOVETYPE].getBytePointer(pent); } - inline static edict_t *getGrenadeThrower ( edict_t *gren ) + static edict_t *getGrenadeThrower ( edict_t *gren ) { return g_GetProps[GETPROP_DOD_GREN_THROWER].getEntity(gren); } - inline static int getPlayerScoreDOD ( edict_t *resource, edict_t *pPlayer ) + static int getPlayerScoreDOD (edict_t* resource, const edict_t* pPlayer) { - int *score_array = g_GetProps[GETPROP_DOD_SCORE].getIntPointer(resource); + const int *score_array = g_GetProps[GETPROP_DOD_SCORE].getIntPointer(resource); - return (score_array!=NULL) ? score_array[ENTINDEX(pPlayer)] : 0; + return score_array != nullptr ? score_array[static_cast(ENTINDEX(pPlayer))] : 0; } - inline static int getPlayerObjectiveScoreDOD ( edict_t *resource, edict_t *pPlayer ) + static int getPlayerObjectiveScoreDOD (edict_t* resource, const edict_t* pPlayer) { - int *score_array = g_GetProps[GETPROP_DOD_OBJSCORE].getIntPointer(resource); + const int *score_array = g_GetProps[GETPROP_DOD_OBJSCORE].getIntPointer(resource); - return (score_array!=NULL) ? score_array[ENTINDEX(pPlayer)] : 0; + return score_array != nullptr ? score_array[static_cast(ENTINDEX(pPlayer))] : 0; } - inline static int getPlayerDeathsDOD ( edict_t *resource, edict_t *pPlayer ) + static int getPlayerDeathsDOD (edict_t* resource, const edict_t* pPlayer) { - int *score_array = g_GetProps[GETPROP_DOD_DEATHS].getIntPointer(resource); + const int *score_array = g_GetProps[GETPROP_DOD_DEATHS].getIntPointer(resource); - return (score_array!=NULL) ? score_array[ENTINDEX(pPlayer)] : 0; + return score_array != nullptr ? score_array[static_cast(ENTINDEX(pPlayer))] : 0; } - inline static float getSmokeSpawnTime ( edict_t *pSmoke ) + static float getSmokeSpawnTime ( edict_t *pSmoke ) { return g_GetProps[GETPROP_DOD_SMOKESPAWN_TIME].getFloat(pSmoke,0); } - - inline static float getRoundTime ( edict_t *pGamerules ) + + static float getRoundTime ( edict_t *pGamerules ) { return g_GetProps[GETPROP_DOD_ROUNDTIME].getFloat(pGamerules,0); } - inline static bool isGarandZoomed ( edict_t *pGarand ) + static bool isGarandZoomed ( edict_t *pGarand ) { return g_GetProps[GETPROP_DOD_GARANDZOOM].getBool(pGarand,false); } - inline static bool isK98Zoomed( edict_t *pK98 ) + static bool isK98Zoomed( edict_t *pK98 ) { return g_GetProps[GETPROP_DOD_K98ZOOM].getBool(pK98,false); } // HL2DM //static void - inline static bool areAlliesBombing (edict_t *pRes) + static bool areAlliesBombing (edict_t *pRes) { return g_GetProps[GETPROP_DOD_ALLIESBOMBING].getBool(pRes,false); } - inline static bool areAxisBombing (edict_t *pRes) + + static bool areAxisBombing (edict_t *pRes) { return g_GetProps[GETPROP_DOD_AXISBOMBING].getBool(pRes,false); } - inline static int *isBombPlantedList (edict_t *pRes) + + static int *isBombPlantedList (edict_t *pRes) { return g_GetProps[GETPROP_DOD_BOMBSPLANTED].getIntPointer(pRes); } - inline static int *getNumBombsRequiredList (edict_t *pRes) + + static int *getNumBombsRequiredList (edict_t *pRes) { return g_GetProps[GETPROP_DOD_BOMBSREQ].getIntPointer(pRes); } - inline static int *isBombDefusingList (edict_t *pRes) + + static int *isBombDefusingList (edict_t *pRes) { return g_GetProps[GETPROP_DOD_BOMBSDEFUSED].getIntPointer(pRes); } - inline static int *getNumBombsRemaining ( edict_t *pRes ) + + static int *getNumBombsRemaining ( edict_t *pRes ) { return g_GetProps[GETPROP_DOD_BOMBSREMAINING].getIntPointer(pRes); } - inline static bool isPlayerDefusingBomb_DOD(edict_t *pPlayer) + static bool isPlayerDefusingBomb_DOD(edict_t *pPlayer) { return g_GetProps[GETPROP_DOD_DEFUSINGBOMB].getBool(pPlayer,false); } - inline static bool isPlayerPlantingBomb_DOD(edict_t *pPlayer) + static bool isPlayerPlantingBomb_DOD(edict_t *pPlayer) { return g_GetProps[GETPROP_DOD_PLANTINGBOMB].getBool(pPlayer,false); } - inline static bool isSentryGunBeingPlaced (edict_t *pSentry ) + static bool isSentryGunBeingPlaced (edict_t *pSentry ) { return g_GetProps[GETPROP_SENTRYGUN_PLACING].getBool(pSentry,false); } + /** + * Gets the player FOV + * + * @param pPlayer The player to retreive FOV from + * @return The player's FOV + **/ + static int getPlayerFOV(edict_t *pPlayer) + { + return g_GetProps[GETPROP_PLAYER_FOV].getInt(pPlayer, 0); + } + + /** + * Gets the player life state + * + * @param pPlayer The player to retreive life state from + * @return The player's life state + **/ + static int getPlayerLifeState(edict_t *pPlayer) + { + return g_GetProps[GETPROP_PLAYER_LIFESTATE].getInt(pPlayer, 0); + } + + // Synergy + + /** + * Gets the player vehicle entity + * + * @param pPlayer The player to retreive the vehicle from + * @return The player's vehicle + **/ + static edict_t* getSynPlayerVehicle(edict_t* pPlayer) + { + return g_GetProps[GETPROP_SYN_PLAYER_VEHICLE].getEntity(pPlayer); + } + + /** + * Gets the vehicle current driver + * + * @param pVehicle The vehicle to get the driver from + * @return The vehicle current driver + **/ + static edict_t* getSynVehicleDriver(edict_t* pVehicle) + { + return g_GetProps[GETPROP_SYN_VEHICLE_DRIVER].getEntity(pVehicle); + } + + /** + * Gets the player HEV suit power level + * + * @param pPlayer The player to retreive the suit power from + * @return The player's current suit power level + **/ + static float getSynPlayerSuitPower(edict_t* pPlayer) + { + return g_GetProps[GETPROP_SYN_SUITPOWER].getFloat(pPlayer, 0.0f); + } + + // Counter-Strike: Source + + /** + * Gets the amount of money the player has + * + * @param pPlayer The player's pointer + * @return The player's current money value + **/ + static int getCSPlayerMoney(edict_t* pPlayer) + { + return g_GetProps[GETPROP_CSS_MONEY].getInt(pPlayer, 0); + } + + /** + * Checks if the player is inside a buy zone + * + * @param pPlayer The player's pointer + * @return TRUE if the player is inside a buy zone + **/ + static bool isCSPlayerInBuyZone(edict_t* pPlayer) + { + return g_GetProps[GETPROP_CSS_INBUYZONE].getBool(pPlayer, false); + } + + /** + * Checks if the player is inside a bomb zone + * + * @param pPlayer The player's pointer + * @return TRUE if the player is inside a bomb zone + **/ + static bool isCSPlayerInBombZone(edict_t* pPlayer) + { + return g_GetProps[GETPROP_CSS_INBOMBZONE].getBool(pPlayer, false); + } + + /** + * Checks if the player is inside a hostage rescue zone + * + * @param pPlayer The player's pointer + * @return TRUE if the player is inside a hostage rescue zone + **/ + static bool isCSPlayerInHostageRescueZone(edict_t* pPlayer) + { + return g_GetProps[GETPROP_CSS_INHOSTAGERESCUEZONE].getBool(pPlayer, false); + } + + /** + * Gets the amount of armor a player has + * + * @param pPlayer The player's pointer + * @return The player's current armor value + **/ + static int getCSPlayerArmor(edict_t* pPlayer) + { + return g_GetProps[GETPROP_CSS_ARMOR].getInt(pPlayer, 0); + } + + /** + * Checks if the player has a defuse kit + * + * @param pPlayer The player's pointer + * @return TRUE if the player has a defuse kit + **/ + static bool CSPlayerHasDefuser(edict_t* pPlayer) + { + return g_GetProps[GETPROP_CSS_HASDEFUSER].getBool(pPlayer, false); + } + + /** + * Checks if the player has helmet armor + * + * @param pPlayer The player's pointer + * @return TRUE if the player has helmet armor + **/ + static bool CSPlayerHasHelmet(edict_t* pPlayer) + { + return g_GetProps[GETPROP_CSS_HASHELMET].getBool(pPlayer, false); + } + + /** + * Checks if the bomb is ticking + * + * @param pBomb The planted bomb entity + * @return TRUE if the bomb is ticking (returns FALSE is the bomb was defused) + **/ + static bool isCSBombTicking(edict_t* pBomb) + { + return g_GetProps[GETPROP_CSS_BOMBTICKING].getBool(pBomb, false); + } + + /** + * Checks how much health a specific hostage has + * + * @param pHostage The hostage entity edict + * @return How much health the given hostage has + **/ + static int getCSHostageHealth(edict_t* pHostage) + { + return g_GetProps[GETPROP_CSS_HOSTAGE_HEALTH].getInt(pHostage, 0); + } + + /** + * Checks if the specified hostage has been rescued + * + * @param pHostage The hostage entity edict + * @return TRUE if the given hostage has been rescued + **/ + static bool isCSHostageRescued(edict_t* pHostage) + { + return g_GetProps[GETPROP_CSS_HOSTAGE_RESCUED].getBool(pHostage, false); + } + + /** + * Gets the edict of the player currently leading the hostage + * + * @param pHostage The hostage entity edict + * @return Edict pointer of the player leading the hostage + **/ + static edict_t* getCSHostageLeader(edict_t* pHostage) + { + return g_GetProps[GETPROP_CSS_HOSTAGE_LEADER].getEntity(pHostage); + } + private: static CClassInterfaceValue g_GetProps[GET_PROPDATA_MAX]; }; +// For reference: https://github.com/alliedmodders/sourcemod/blob/master/core/smn_entities.cpp +class CDataInterface +{ +public: + /** + * Gets the entity's given prop via datamaps + * + * @param pEntity The entity to read + * @param prop The property to read + * @return The property value + **/ + static int GetEntPropInt(CBaseEntity *pEntity, const char *prop) + { + const datamap_t* pDataMap = CBaseEntity_GetDataDescMap(pEntity); + const unsigned offset = UTIL_FindInDataMap(pDataMap, prop); + const int propvalue = *reinterpret_cast(reinterpret_cast(pEntity) + offset); // TODO: bit count? + return propvalue; + } + + /** + * Gets the entity's given prop via datamaps + * + * @param pEntity The entity to read + * @param prop The property to read + * @return The property value + **/ + static float GetEntPropFloat(CBaseEntity *pEntity, const char *prop) + { + const datamap_t* pDataMap = CBaseEntity_GetDataDescMap(pEntity); + const unsigned offset = UTIL_FindInDataMap(pDataMap, prop); + const float propvalue = *reinterpret_cast(reinterpret_cast(pEntity) + offset); + return propvalue; + } + + /** + * Gets the entity's given prop via datamaps + * + * @param pEntity The entity to read + * @param prop The property to read + * @return The property value or NULL if the edict is invalid + **/ + static edict_t *GetEntPropEdict(CBaseEntity *pEntity, const char *prop) + { + const datamap_t* pDataMap = CBaseEntity_GetDataDescMap(pEntity); + const unsigned offset = UTIL_FindInDataMap(pDataMap, prop); + edict_t *pEdict = *reinterpret_cast(reinterpret_cast(pEntity) + offset); + if(!pEdict || pEdict->IsFree()) + { + return nullptr; + } + + return pEdict; + } + + /** + * Gets the entity's given prop via datamaps + * + * @param pEntity The entity to read + * @param prop The property to read + * @return The property value + **/ + static Vector *GetEntPropVector(CBaseEntity *pEntity, const char *prop) + { + const datamap_t* pDataMap = CBaseEntity_GetDataDescMap(pEntity); + const unsigned offset = UTIL_FindInDataMap(pDataMap, prop); + Vector *propvalue = reinterpret_cast(reinterpret_cast(pEntity) + offset); + return propvalue; + } + + /** + * Gets the entity's health via datamaps + * + * @param pEntity The entity to get the health from + * @return The entity current health (m_iHealth) value + **/ + static int GetEntityHealth(CBaseEntity* pEntity) + { + const datamap_t* pDataMap = CBaseEntity_GetDataDescMap(pEntity); + const unsigned offset = UTIL_FindInDataMap(pDataMap, "m_iHealth"); + const int iHealth = *reinterpret_cast(reinterpret_cast(pEntity) + offset); + return iHealth; + } + /** + * Gets the entity's maxhealth via datamaps + * + * @param pEntity The entity to get the health from + * @return The entity current max health (m_iMaxHealth) value + **/ + static int GetEntityMaxHealth(CBaseEntity* pEntity) + { + const datamap_t* pDataMap = CBaseEntity_GetDataDescMap(pEntity); + const unsigned offset = UTIL_FindInDataMap(pDataMap, "m_iMaxHealth"); + const int iMaxHealth = *reinterpret_cast(reinterpret_cast(pEntity) + offset); + return iMaxHealth; + } + /** + * Gets the entity's health as percentage + * + * @param pEntity The entity to get the health from + * @return The entity health as percentage, range 1 to 0, where 1 is full health + **/ + static float GetEntityHealthPercent(CBaseEntity* pEntity) + { + const datamap_t* pDataMap = CBaseEntity_GetDataDescMap(pEntity); + const unsigned offset = UTIL_FindInDataMap(pDataMap, "m_iHealth"); + //int offset2 = UTIL_FindInDataMap(pDataMap, "m_iMaxHealth"); //unused? [APG]RoboCop[CL] + const int iHealth = *reinterpret_cast(reinterpret_cast(pEntity) + offset); + const int iMaxHealth = *reinterpret_cast(reinterpret_cast(pEntity) + offset); + return static_cast(iHealth) / static_cast(iMaxHealth); + } +}; + #endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_globals.cpp b/utils/RCBot2_meta/bot_globals.cpp index 84d88c78e..568dc3883 100644 --- a/utils/RCBot2_meta/bot_globals.cpp +++ b/utils/RCBot2_meta/bot_globals.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -29,16 +31,8 @@ * */ -#ifndef __linux__ -// for file stuff -#include -#define WIN32_LEAN_AND_MEAN - -#include - -#endif - #include "bot.h" +#include "bot_cvars.h" #include "bot_globals.h" #include "bot_strings.h" #include "bot_waypoint_locations.h" @@ -46,30 +40,43 @@ #include "bot_weapons.h" #include "ndebugoverlay.h" +//#include "filesystem.h" + +#include "rcbot/logging.h" #ifndef __linux__ #include // for mkdir -#include #else #include -#include #endif +#include + +#include +#include +#include +#include +#include + +//caxanga334: SDK 2013 contains macros for std::min and std::max which causes errors when compiling +//#if SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_BMS +#include "valve_minmax_off.h" +//#endif + extern IServerGameEnts *servergameents; /////////// trace_t CBotGlobals :: m_TraceResult; -char * CBotGlobals :: m_szGameFolder = NULL; -char * CBotGlobals :: m_szModFolder = NULL; +char * CBotGlobals :: m_szModFolder = nullptr; eModId CBotGlobals :: m_iCurrentMod = MOD_UNSUPPORTED; -CBotMod *CBotGlobals :: m_pCurrentMod = NULL; +CBotMod *CBotGlobals :: m_pCurrentMod = nullptr; bool CBotGlobals :: m_bMapRunning = false; int CBotGlobals :: m_iMaxClients = 0; int CBotGlobals :: m_iEventVersion = 1; int CBotGlobals :: m_iWaypointDisplayType = 0; char CBotGlobals :: m_szMapName[MAX_MAP_STRING_LEN]; bool CBotGlobals :: m_bTeamplay = false; -char *CBotGlobals :: m_szRCBotFolder = NULL; +char *CBotGlobals :: m_szRCBotFolder = nullptr; /////////// @@ -78,24 +85,26 @@ extern IVDebugOverlay *debugoverlay; class CTraceFilterVis : public CTraceFilter { public: - CTraceFilterVis(edict_t *pPlayer, edict_t *pHit = NULL ) + virtual ~CTraceFilterVis() = default; + + CTraceFilterVis(edict_t *pPlayer, edict_t *pHit = nullptr) { m_pPlayer = pPlayer; m_pHit = pHit; } - virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ) + bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ) override { - if ( m_pPlayer && (pServerEntity == (IHandleEntity*)m_pPlayer->GetIServerEntity()) ) + if ( m_pPlayer && pServerEntity == static_cast(m_pPlayer->GetIServerEntity()) ) return false; - if ( m_pHit && (pServerEntity == (IHandleEntity*)m_pHit->GetIServerEntity()) ) + if ( m_pHit && pServerEntity == static_cast(m_pHit->GetIServerEntity()) ) return false; return true; } - virtual TraceType_t GetTraceType() const + TraceType_t GetTraceType() const override { return TRACE_EVERYTHING; } @@ -113,18 +122,17 @@ void CBotGlobals :: init () { m_iCurrentMod = MOD_UNSUPPORTED; m_szModFolder[0] = 0; - m_szGameFolder[0] = 0; } bool CBotGlobals ::isAlivePlayer ( edict_t *pEntity ) { - return pEntity && ENTINDEX(pEntity) && (ENTINDEX(pEntity) <= gpGlobals->maxClients) && (entityIsAlive(pEntity)); + return pEntity && ENTINDEX(pEntity) && ENTINDEX(pEntity) <= gpGlobals->maxClients && entityIsAlive(pEntity); } //new map void CBotGlobals :: setMapName ( const char *szMapName ) { - strncpy(m_szMapName,szMapName,MAX_MAP_STRING_LEN-1); + std::strncpy(m_szMapName,szMapName,MAX_MAP_STRING_LEN-1); m_szMapName[MAX_MAP_STRING_LEN-1] = 0; } @@ -133,20 +141,48 @@ char *CBotGlobals :: getMapName () return m_szMapName; } -bool CBotGlobals :: isCurrentMod ( eModId modid ) +bool CBotGlobals :: isCurrentMod (const eModId modid) { return m_pCurrentMod->getModId() == modid; } -int CBotGlobals ::numPlayersOnTeam(int iTeam, bool bAliveOnly) +int CBotGlobals ::numPlayersPlaying() +{ + int num = CBotGlobals::numClients(); + + if (rcbot_ignore_spectators.GetBool()) + { + for ( int i = 1; i <= CBotGlobals::maxClients(); i ++ ) + { + edict_t* pEdict = INDEXENT(i); + + if ( !pEdict ) + continue; + + if ( CBotGlobals::entityIsValid(pEdict) ) + { + if ( CClassInterface::getTeam(pEdict) >= 2 ) + continue; + if ( CBots::getBotPointer(pEdict) != nullptr ) + continue; + num--; + } + } + } + + return num; +} + +int CBotGlobals ::numPlayersOnTeam(const int iTeam, const bool bAliveOnly) { - int i = 0; int num = 0; - edict_t *pEdict; - for ( i = 1; i <= CBotGlobals::numClients(); i ++ ) + for ( int i = 1; i <= CBotGlobals::maxClients(); i ++ ) { - pEdict = INDEXENT(i); + edict_t* pEdict = INDEXENT(i); + + if ( !pEdict ) + continue; if ( CBotGlobals::entityIsValid(pEdict) ) { @@ -165,20 +201,47 @@ int CBotGlobals ::numPlayersOnTeam(int iTeam, bool bAliveOnly) return num; } +int CBotGlobals ::numBotsOnTeam(const int iTeam, const bool bAliveOnly) +{ + int num = 0; + + for ( int i = 1; i <= CBotGlobals::maxClients(); i ++ ) + { + edict_t* pEdict = INDEXENT(i); + + if ( !pEdict ) + continue; + + if ( CBotGlobals::entityIsValid(pEdict) && CBots::getBotPointer(pEdict) != nullptr ) + { + if ( CClassInterface::getTeam(pEdict) == iTeam ) + { + if ( bAliveOnly ) + { + if ( CBotGlobals::entityIsAlive(pEdict) ) + num++; + } + else + num++; + } + } + } + return num; +} + bool CBotGlobals::dirExists(const char *path) { -#ifdef _WIN32 +#if defined(_WIN64) || defined(_WIN32) struct _stat info; if (_stat(path, &info) != 0) return false; - else if (info.st_mode & _S_IFDIR) + if (info.st_mode & _S_IFDIR) return true; - else - return false; + return false; -#else +#elif __linux__ struct stat info; @@ -194,121 +257,109 @@ bool CBotGlobals::dirExists(const char *path) void CBotGlobals::readRCBotFolder() { - KeyValues *mainkv = new KeyValues("Metamod Plugin"); + std::unique_ptr mainkv(new KeyValues("Metamod Plugin"), [](KeyValues* kv) { kv->deleteThis(); }); if (mainkv->LoadFromFile(filesystem, "addons/metamod/rcbot2.vdf", "MOD")) { char folder[256] = "\0"; - const char *szRCBotFolder = mainkv->GetString("rcbot2path"); + const char* szRCBotFolder = mainkv->GetString("rcbot2path"); if (szRCBotFolder && *szRCBotFolder) { - CBotGlobals::botMessage(NULL, 0, "RCBot Folder -> trying %s", szRCBotFolder); + logger->Log(LogLevel::INFO, "RCBot Folder -> trying %s", szRCBotFolder); if (!dirExists(szRCBotFolder)) { - snprintf(folder, sizeof(folder), "%s/%s", CBotGlobals::modFolder(), szRCBotFolder); + snprintf(folder, sizeof folder, "%s/%s", CBotGlobals::modFolder(), szRCBotFolder); szRCBotFolder = CStrings::getString(folder); - CBotGlobals::botMessage(NULL, 0, "RCBot Folder -> trying %s", szRCBotFolder); + logger->Log(LogLevel::INFO, "RCBot Folder -> trying %s", szRCBotFolder); if (!dirExists(szRCBotFolder)) { - CBotGlobals::botMessage(NULL, 0, "RCBot Folder -> not found ..."); + logger->Log(LogLevel::ERROR, "RCBot Folder -> not found ..."); } } m_szRCBotFolder = CStrings::getString(szRCBotFolder); } } - - mainkv->deleteThis(); } -float CBotGlobals :: grenadeWillLand ( Vector vOrigin, Vector vEnemy, float fProjSpeed, float fGrenadePrimeTime, float *fAngle ) +float CBotGlobals::grenadeWillLand(const Vector& vOrigin, const Vector& vEnemy, const float fProjSpeed, const float fGrenadePrimeTime, const float* fAngle) { static float g; - extern ConVar *sv_gravity; - Vector v_comp = vEnemy-vOrigin; - float fDistance = v_comp.Length(); - - v_comp = v_comp/fDistance; - - g = sv_gravity->GetFloat(); + Vector v_comp = vEnemy - vOrigin; + const float fDistance = v_comp.Length(); + + v_comp = v_comp / fDistance; + + g = sv_gravity.IsValid() ? sv_gravity.GetFloat() : 800.0f; - if ( fAngle == NULL ) + if (fAngle == nullptr) { - - return false; + return 0.0f; } - else - { - // use angle -- work out time - // work out angle - float vhorz; - float vvert; - - SinCos(DEG2RAD(*fAngle),&vvert,&vhorz); + // use angle -- work out time + // work out angle + float vhorz; + float vvert; - vhorz *= fProjSpeed; - vvert *= fProjSpeed; + SinCos(DEG2RAD(*fAngle), &vvert, &vhorz); - float t = fDistance/vhorz; + vhorz *= fProjSpeed; + vvert *= fProjSpeed; - // within one second of going off - if ( fabs(t-fGrenadePrimeTime) < 1.0f ) - { - float ffinaly = vOrigin.z + (vvert*t) - ((g*0.5)*(t*t)); + // within one second of going off + if (const float t = fDistance / vhorz; std::fabs(t - fGrenadePrimeTime) < 1.0f) + { + const float ffinaly = vOrigin.z + vvert * t - g * 0.5f * (t * t); - return ( fabs(ffinaly - vEnemy.z) < BLAST_RADIUS ); // ok why not - } + return (std::fabs(ffinaly - vEnemy.z) < BLAST_RADIUS) ? 1.0f : 0.0f; } - return false; + return 0.0f; } -// TO DO :: put in CClients ? +// TODO :: put in CClients ? edict_t *CBotGlobals :: findPlayerByTruncName ( const char *name ) // find a player by a truncated name "name". // e.g. name = "Jo" might find a player called "John" { - edict_t *pent = NULL; - IPlayerInfo *pInfo; - int i; - - for( i = 1; i <= maxClients(); i ++ ) + const std::size_t length = std::strlen(name); + for( int i = 1; i <= maxClients(); i ++ ) { - pent = INDEXENT(i); + edict_t* pent = INDEXENT(i); if( pent && CBotGlobals::isNetworkable(pent) ) { - int length = strlen(name); - char arg_lwr[128]; char pent_lwr[128]; - strcpy(arg_lwr,name); + std::strcpy(arg_lwr,name); - pInfo = playerinfomanager->GetPlayerInfo( pent ); + IPlayerInfo* pInfo = playerinfomanager->GetPlayerInfo(pent); - if ( pInfo == NULL ) + if ( pInfo == nullptr) continue; - strcpy(pent_lwr,pInfo->GetName()); + std::strcpy(pent_lwr,pInfo->GetName()); - __strlow(arg_lwr); - __strlow(pent_lwr); + __strlow(arg_lwr) + __strlow(pent_lwr) - if( strncmp( arg_lwr,pent_lwr,length) == 0 ) + if( std::strncmp( arg_lwr,pent_lwr,length) == 0 ) { return pent; } } } - return NULL; + return nullptr; } class CTraceFilterHitAllExceptPlayers : public CTraceFilter { public: - virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ) + virtual ~CTraceFilterHitAllExceptPlayers() = default; + + bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask ) override { return pServerEntity->GetRefEHandle().GetEntryIndex() <= gpGlobals->maxClients; } @@ -320,8 +371,9 @@ class CTraceFilterHitAllExceptPlayers : public CTraceFilter class CTraceFilterSimple : public CTraceFilter { public: - - CTraceFilterSimple( const IHandleEntity *passentity1, const IHandleEntity *passentity2, int collisionGroup ) + virtual ~CTraceFilterSimple() = default; + + CTraceFilterSimple( const IHandleEntity *passentity1, const IHandleEntity *passentity2, const int collisionGroup ) { m_pPassEnt1 = passentity1; @@ -330,7 +382,8 @@ class CTraceFilterSimple : public CTraceFilter m_collisionGroup = collisionGroup; } - virtual bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) + + bool ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) override { if ( m_pPassEnt1 == pHandleEntity ) return false; @@ -351,7 +404,7 @@ class CTraceFilterSimple : public CTraceFilter //virtual void SetPassEntity( const IHandleEntity *pPassEntity ) { m_pPassEnt = pPassEntity; } //virtual void SetCollisionGroup( int iCollisionGroup ) { m_collisionGroup = iCollisionGroup; } - //const IHandleEntity *GetPassEntity( void ){ return m_pPassEnt;} + //const IHandleEntity *GetPassEntity(){ return m_pPassEnt;} private: const IHandleEntity *m_pPassEnt1; @@ -359,48 +412,51 @@ class CTraceFilterSimple : public CTraceFilter int m_collisionGroup; }; -bool CBotGlobals :: checkOpensLater ( Vector vSrc, Vector vDest ) +bool CBotGlobals :: checkOpensLater (const Vector& vSrc, const Vector& vDest) { - CTraceFilterSimple traceFilter( NULL, NULL, MASK_PLAYERSOLID ); + CTraceFilterSimple traceFilter(nullptr, nullptr, MASK_PLAYERSOLID ); traceLine (vSrc,vDest,MASK_PLAYERSOLID,&traceFilter); - return (traceVisible(NULL)); + return traceVisible(nullptr); } -bool CBotGlobals :: isVisibleHitAllExceptPlayer ( edict_t *pPlayer, Vector vSrc, Vector vDest, edict_t *pDest ) +bool CBotGlobals :: isVisibleHitAllExceptPlayer ( edict_t *pPlayer, const Vector& vSrc, const Vector& vDest, edict_t *pDest ) { const IHandleEntity *ignore = pPlayer->GetIServerEntity(); - CTraceFilterSimple traceFilter( ignore, ((pDest==NULL)?NULL:pDest->GetIServerEntity()), MASK_ALL ); + CTraceFilterSimple traceFilter( ignore, (pDest== nullptr ? nullptr :pDest->GetIServerEntity()), MASK_ALL ); traceLine (vSrc,vDest,MASK_SHOT|MASK_VISIBLE,&traceFilter); - return (traceVisible(pDest)); + return traceVisible(pDest); } -bool CBotGlobals :: isVisible ( edict_t *pPlayer, Vector vSrc, Vector vDest) +bool CBotGlobals :: isVisible (edict_t *pPlayer, const Vector& vSrc, const Vector& vDest) { CTraceFilterWorldAndPropsOnly filter; traceLine (vSrc,vDest,MASK_SOLID_BRUSHONLY|CONTENTS_OPAQUE,&filter); - return (traceVisible(NULL)); + return traceVisible(nullptr); } -bool CBotGlobals :: isVisible ( edict_t *pPlayer, Vector vSrc, edict_t *pDest ) +bool CBotGlobals :: isVisible (edict_t *pPlayer, const Vector& vSrc, edict_t *pDest) { //CTraceFilterWorldAndPropsOnly filter;// CTraceFilterHitAll filter; CTraceFilterWorldAndPropsOnly filter; + if ( isBrushEntity(pDest) ) + traceLine (vSrc,worldCenter(pDest),MASK_SOLID_BRUSHONLY|CONTENTS_OPAQUE,&filter); + else traceLine (vSrc,entityOrigin(pDest),MASK_SOLID_BRUSHONLY|CONTENTS_OPAQUE,&filter); - return (traceVisible(pDest)); + return traceVisible(pDest); } -bool CBotGlobals :: isShotVisible ( edict_t *pPlayer, Vector vSrc, Vector vDest, edict_t *pDest ) +bool CBotGlobals :: isShotVisible (edict_t *pPlayer, const Vector& vSrc, const Vector& vDest, edict_t *pDest) { //CTraceFilterWorldAndPropsOnly filter;// CTraceFilterHitAll filter; @@ -408,52 +464,50 @@ bool CBotGlobals :: isShotVisible ( edict_t *pPlayer, Vector vSrc, Vector vDest, traceLine (vSrc,vDest,MASK_SHOT,&filter); - return (traceVisible(pDest)); + return traceVisible(pDest); } -bool CBotGlobals :: isVisible (Vector vSrc, Vector vDest) +bool CBotGlobals :: isVisible (const Vector& vSrc, const Vector& vDest) { CTraceFilterWorldAndPropsOnly filter; traceLine (vSrc,vDest,MASK_SOLID_BRUSHONLY|CONTENTS_OPAQUE,&filter); - return traceVisible(NULL); + return traceVisible(nullptr); } -void CBotGlobals :: traceLine (Vector vSrc, Vector vDest, unsigned int mask, ITraceFilter *pFilter) +void CBotGlobals :: traceLine (const Vector& vSrc, const Vector& vDest, const unsigned mask, ITraceFilter *pFilter) { Ray_t ray; - memset(&m_TraceResult,0,sizeof(trace_t)); + m_TraceResult = trace_t{}; ray.Init( vSrc, vDest ); enginetrace->TraceRay( ray, mask, pFilter, &m_TraceResult ); } -float CBotGlobals :: quickTraceline (edict_t *pIgnore,Vector vSrc, Vector vDest) +float CBotGlobals :: quickTraceline (edict_t *pIgnore, const Vector& vSrc, const Vector& vDest) { CTraceFilterVis filter = CTraceFilterVis(pIgnore); Ray_t ray; - memset(&m_TraceResult,0,sizeof(trace_t)); + m_TraceResult = trace_t{}; ray.Init( vSrc, vDest ); enginetrace->TraceRay( ray, MASK_NPCSOLID_BRUSHONLY, &filter, &m_TraceResult ); return m_TraceResult.fraction; } -float CBotGlobals :: DotProductFromOrigin ( edict_t *pEnemy, Vector pOrigin ) +float CBotGlobals :: DotProductFromOrigin ( edict_t *pEnemy, const Vector& pOrigin ) { static Vector vecLOS; static float flDot; - IPlayerInfo *p; - + Vector vForward; - QAngle eyes; - p = playerinfomanager->GetPlayerInfo(pEnemy); + IPlayerInfo* p = playerinfomanager->GetPlayerInfo(pEnemy); if (!p ) return 0; - eyes = p->GetAbsAngles(); + const QAngle eyes = p->GetAbsAngles(); // in fov? Check angle to edict AngleVectors(eyes,&vForward); @@ -467,7 +521,7 @@ float CBotGlobals :: DotProductFromOrigin ( edict_t *pEnemy, Vector pOrigin ) } -float CBotGlobals :: DotProductFromOrigin ( Vector vPlayer, Vector vFacing, QAngle eyes ) +float CBotGlobals :: DotProductFromOrigin (const Vector& vPlayer, const Vector& vFacing, const QAngle& eyes) { static Vector vecLOS; static float flDot; @@ -487,22 +541,17 @@ float CBotGlobals :: DotProductFromOrigin ( Vector vPlayer, Vector vFacing, QAng bool CBotGlobals :: traceVisible (edict_t *pEnt) { - return (m_TraceResult.fraction >= 1.0)||(m_TraceResult.m_pEnt && pEnt && (m_TraceResult.m_pEnt==pEnt->GetUnknown()->GetBaseEntity())); -} - -void CBotGlobals :: freeMemory () -{ - m_pCommands->freeMemory(); + return m_TraceResult.fraction >= 1.0f || (m_TraceResult.m_pEnt && pEnt && m_TraceResult.m_pEnt == pEnt->GetUnknown()->GetBaseEntity()); } bool CBotGlobals::initModFolder() { char szGameFolder[512]; engine->GetGameDir(szGameFolder, 512); - int iLength = strlen(CStrings::getString(szGameFolder)); - int pos = iLength - 1; + const std::size_t iLength = std::strlen(CStrings::getString(szGameFolder)); + std::size_t pos = iLength - 1; - while ((pos > 0) && (szGameFolder[pos] != '\\') && (szGameFolder[pos] != '/')) { + while (pos > 0 && szGameFolder[pos] != '\\' && szGameFolder[pos] != '/') { pos--; } pos++; @@ -514,33 +563,19 @@ bool CBotGlobals::initModFolder() { bool CBotGlobals :: gameStart () { char szGameFolder[512]; - engine->GetGameDir(szGameFolder,512); - char szSteamFolder[512]; + engine->GetGameDir(szGameFolder,512); /* CFileSystemPassThru a; a.InitPassThru(filesystem,true); a.GetCurrentDirectoryA(szSteamFolder,512); */ - V_GetCurrentDirectory(szSteamFolder,512); //filesystem->GetCurrentDirectory(szSteamFolder,512); - int iLength = strlen(szSteamFolder); - - int pos = iLength-1; - - while ( (pos > 0) && (szSteamFolder[pos] != '\\') && (szSteamFolder[pos] != '/') ) - { - pos--; - } - pos++; - - m_szGameFolder = CStrings::getString(&szSteamFolder[pos]); - - iLength = strlen(CStrings::getString(szGameFolder)); + const std::size_t iLength = std::strlen(CStrings::getString(szGameFolder)); - pos = iLength-1; + std::size_t pos = iLength - 1; - while ( (pos > 0) && (szGameFolder[pos] != '\\') && (szGameFolder[pos] != '/') ) + while ( pos > 0 && szGameFolder[pos] != '\\' && szGameFolder[pos] != '/' ) { pos--; } @@ -550,9 +585,9 @@ bool CBotGlobals :: gameStart () CBotMods::readMods(); - m_pCurrentMod = CBotMods::getMod(m_szModFolder,m_szGameFolder); + m_pCurrentMod = CBotMods::getMod(m_szModFolder); - if ( m_pCurrentMod != NULL ) + if ( m_pCurrentMod != nullptr) { m_iCurrentMod = m_pCurrentMod->getModId(); @@ -562,23 +597,18 @@ bool CBotGlobals :: gameStart () return true; } - else - { - Msg("[BOT ERROR] Mod not found. Please edit the bot_mods.ini in the bot config folder\nsteamdir = %s\ngamedir = %s\n",m_szGameFolder,m_szModFolder); + logger->Log(LogLevel::ERROR, "Mod not found. Please edit the bot_mods.ini in the bot config folder (gamedir = %s)",m_szModFolder); - return false; - } + return false; } void CBotGlobals :: levelInit () { - } -int CBotGlobals :: countTeamMatesNearOrigin ( Vector vOrigin, float fRange, int iTeam, edict_t *pIgnore ) +int CBotGlobals :: countTeamMatesNearOrigin (const Vector& vOrigin, const float fRange, const int iTeam, const edict_t *pIgnore) { int iCount = 0; - IPlayerInfo *p; for ( int i = 1; i <= CBotGlobals::maxClients(); i ++ ) { @@ -590,7 +620,7 @@ int CBotGlobals :: countTeamMatesNearOrigin ( Vector vOrigin, float fRange, int if ( pEdict == pIgnore ) continue; - p = playerinfomanager->GetPlayerInfo(pEdict); + IPlayerInfo* p = playerinfomanager->GetPlayerInfo(pEdict); if ( !p || !p->IsConnected() || p->IsDead() || p->IsObserver() || !p->IsPlayer() ) continue; @@ -610,15 +640,22 @@ int CBotGlobals :: countTeamMatesNearOrigin ( Vector vOrigin, float fRange, int int CBotGlobals :: numClients () { int iCount = 0; + int iIndex = 0; for ( int i = 1; i <= CBotGlobals::maxClients(); i ++ ) { edict_t *pEdict = INDEXENT(i); - if ( pEdict ) - { - if ( engine->GetPlayerUserId(pEdict) > 0 ) - iCount++; + if ( !pEdict ) + continue; + + IPlayerInfo *p = playerinfomanager->GetPlayerInfo(pEdict); + if (!p || p->IsHLTV()) + continue; + + if ( engine->GetPlayerUserId(pEdict) > 0 ) { + iIndex = i; + iCount++; } } @@ -631,35 +668,39 @@ bool CBotGlobals :: entityIsAlive ( edict_t *pEntity ) index = ENTINDEX(pEntity); - if ( index && (index <= gpGlobals->maxClients) ) + if ( index && index <= gpGlobals->maxClients ) { IPlayerInfo *p = playerinfomanager->GetPlayerInfo(pEntity); if ( !p ) return false; - return (!p->IsDead() && (p->GetHealth()>0)); + return !p->IsDead() && p->GetHealth()>0; } - return ( pEntity->GetIServerEntity() && pEntity->GetClassName() && *pEntity->GetClassName() ); + return pEntity->GetIServerEntity() && pEntity->GetClassName() && *pEntity->GetClassName(); //CBaseEntity *pBaseEntity = CBaseEntity::Instance(pEntity); //return pBaseEntity->IsAlive(); } -edict_t *CBotGlobals :: playerByUserId(int iUserId) +bool CBotGlobals :: isBrushEntity ( edict_t *pEntity ) +{ + const char* szModel = pEntity->GetIServerEntity()->GetModelName().ToCStr(); + return szModel[0] == '*'; +} + +edict_t *CBotGlobals :: playerByUserId(const int iUserId) { for ( int i = 1; i <= maxClients(); i ++ ) { - edict_t *pEdict = INDEXENT(i); - - if ( pEdict ) + if ( edict_t *pEdict = INDEXENT(i) ) { if ( engine->GetPlayerUserId(pEdict) == iUserId ) return pEdict; } } - return NULL; + return nullptr; } int CBotGlobals :: getTeam ( edict_t *pEntity ) @@ -674,7 +715,7 @@ bool CBotGlobals :: isNetworkable ( edict_t *pEntity ) pServerEnt = pEntity->GetIServerEntity(); - return (pServerEnt && (pServerEnt->GetNetworkable() != NULL)); + return pServerEnt && pServerEnt->GetNetworkable() != nullptr; } /* @@ -692,28 +733,31 @@ inline Vector CBotGlobals :: entityOrigin ( edict_t *pEntity ) return vOrigin; }*/ -void CBotGlobals :: serverSay ( char *fmt, ... ) +void CBotGlobals::serverSay(const char* fmt, ...) { - va_list argptr; + if (!fmt) return; + + va_list argptr; + static char string[1024]; - va_start (argptr, fmt); - - strcpy(string,"say \""); + va_start(argptr, fmt); - vsprintf (&string[5], fmt, argptr); + std::strcpy(string, "say \""); - va_end (argptr); + vsnprintf(&string[5], sizeof(string) - 6, fmt, argptr); + + va_end(argptr); - strcat(string,"\""); + std::strcat(string, "\""); engine->ServerCommand(string); } -// TO DO :: put into CClient -bool CBotGlobals :: setWaypointDisplayType ( int iType ) +// TODO :: put into CClient +bool CBotGlobals :: setWaypointDisplayType (const int iType) { - if ( (iType >= 0) && (iType <= 1) ) + if ( iType >= 0 && iType <= 1 ) { m_iWaypointDisplayType = iType; return true; @@ -721,23 +765,21 @@ bool CBotGlobals :: setWaypointDisplayType ( int iType ) return false; } + // work on this -bool CBotGlobals :: walkableFromTo (edict_t *pPlayer, Vector v_src, Vector v_dest) -{ - extern ConVar rcbot_wptplace_width; +bool CBotGlobals :: walkableFromTo (edict_t *pPlayer, const Vector& v_src, const Vector& v_dest) +{ CTraceFilterVis filter = CTraceFilterVis(pPlayer); - float fDistance = sqrt((v_dest - v_src).LengthSqr()); - CClient *pClient = CClients::get(pPlayer); + const float fDistance = std::sqrt((v_dest - v_src).LengthSqr()); + const CClient *pClient = CClients::get(pPlayer); Vector vcross = v_dest - v_src; - Vector vleftsrc,vleftdest, vrightsrc,vrightdest; float fWidth = rcbot_wptplace_width.GetFloat(); if ( v_dest == v_src ) return true; // minimum - if ( fWidth < 2.0f ) - fWidth = 2.0f; + fWidth = std::max(fWidth, 2.0f); if ( pClient->autoWaypointOn() ) fWidth = 4.0f; @@ -746,11 +788,11 @@ bool CBotGlobals :: walkableFromTo (edict_t *pPlayer, Vector v_src, Vector v_des vcross = vcross.Cross(Vector(0,0,1)); vcross = vcross * (fWidth*0.5f); - vleftsrc = v_src - vcross; - vrightsrc = v_src + vcross; + const Vector vleftsrc = v_src - vcross; + const Vector vrightsrc = v_src + vcross; - vleftdest = v_dest - vcross; - vrightdest = v_dest + vcross; + const Vector vleftdest = v_dest - vcross; + const Vector vrightdest = v_dest + vcross; if ( fDistance > CWaypointLocations::REACHABLE_RANGE ) return false; @@ -759,31 +801,31 @@ bool CBotGlobals :: walkableFromTo (edict_t *pPlayer, Vector v_src, Vector v_des // return false; // can swim there? - if ((enginetrace->GetPointContents( v_src ) == CONTENTS_WATER) && - (enginetrace->GetPointContents( v_dest ) == CONTENTS_WATER)) + if (enginetrace->GetPointContents( v_src ) == CONTENTS_WATER && + enginetrace->GetPointContents( v_dest ) == CONTENTS_WATER) { return true; } // find the ground - CBotGlobals::traceLine(v_src,v_src-Vector(0,0,256.0),MASK_NPCSOLID_BRUSHONLY,&filter); + CBotGlobals::traceLine(v_src,v_src-Vector(0,0,256.0f),MASK_NPCSOLID_BRUSHONLY,&filter); #ifndef __linux__ - debugoverlay->AddLineOverlay(v_src,v_src-Vector(0,0,256.0),255,0,255,false,3); + debugoverlay->AddLineOverlay(v_src,v_src-Vector(0,0,256.0f),255,0,255,false,3); #endif - Vector v_ground_src = CBotGlobals::getTraceResult()->endpos + Vector(0,0,1); + const Vector v_ground_src = CBotGlobals::getTraceResult()->endpos + Vector(0,0,1); - CBotGlobals::traceLine(v_dest,v_dest-Vector(0,0,256.0),MASK_NPCSOLID_BRUSHONLY,&filter); + CBotGlobals::traceLine(v_dest,v_dest-Vector(0,0,256.0f),MASK_NPCSOLID_BRUSHONLY,&filter); #ifndef __linux__ - debugoverlay->AddLineOverlay(v_dest,v_dest-Vector(0,0,256.0),255,255,0,false,3); + debugoverlay->AddLineOverlay(v_dest,v_dest-Vector(0,0,256.0f),255,255,0,false,3); #endif - Vector v_ground_dest = CBotGlobals::getTraceResult()->endpos + Vector(0,0,1); + const Vector v_ground_dest = CBotGlobals::getTraceResult()->endpos + Vector(0,0,1); if ( !CBotGlobals::isVisible(pPlayer,v_ground_src,v_ground_dest) ) { #ifndef __linux__ debugoverlay->AddLineOverlay(v_ground_src,v_ground_dest,0,255,255,false,3); #endif - trace_t *tr = CBotGlobals::getTraceResult(); + const trace_t *tr = CBotGlobals::getTraceResult(); // no slope there if ( tr->endpos.z > v_src.z ) @@ -794,13 +836,13 @@ bool CBotGlobals :: walkableFromTo (edict_t *pPlayer, Vector v_src, Vector v_des CBotGlobals::traceLine(tr->endpos,tr->endpos-Vector(0,0,45),MASK_NPCSOLID_BRUSHONLY,&filter); - Vector v_jsrc = tr->endpos; + const Vector v_jsrc = tr->endpos; #ifndef __linux__ debugoverlay->AddLineOverlay(v_jsrc,v_jsrc-Vector(0,0,45),255,255,255,false,3); #endif // can't jump there - if ( ((v_jsrc.z - tr->endpos.z) + (v_dest.z-v_jsrc.z)) > 45.0f ) + if ( v_jsrc.z - tr->endpos.z + (v_dest.z-v_jsrc.z) > 45.0f ) { //if ( (tr->endpos.z > (v_src.z+45)) && (fDistance > 64.0f) ) //{ @@ -809,16 +851,17 @@ bool CBotGlobals :: walkableFromTo (edict_t *pPlayer, Vector v_src, Vector v_des #endif // check for slope or stairs Vector v_norm = v_dest-v_src; - v_norm = v_norm/sqrt(v_norm.LengthSqr()); + v_norm = v_norm/std::sqrt(v_norm.LengthSqr()); - for ( float fDistCheck = 45.0f; fDistCheck < fDistance; fDistCheck += 45.0f ) - { - Vector v_checkpoint = v_src + (v_norm * fDistCheck); + for (int iDistCheck = 0; static_cast(iDistCheck) * 45 < fDistance; ++iDistCheck) { + float fDistCheck = static_cast(iDistCheck) * 45.0f; + + Vector v_checkpoint = v_src + v_norm * fDistCheck; // check jump height again CBotGlobals::traceLine(v_checkpoint,v_checkpoint-Vector(0,0,45.0f),MASK_NPCSOLID_BRUSHONLY,&filter); - if ( CBotGlobals::traceVisible(NULL) ) + if ( CBotGlobals::traceVisible(nullptr) ) { #ifndef __linux__ debugoverlay->AddTextOverlay(tr->endpos,0,3,"step/jump fail"); @@ -836,38 +879,36 @@ bool CBotGlobals :: walkableFromTo (edict_t *pPlayer, Vector v_src, Vector v_des //return true; } -bool CBotGlobals :: boundingBoxTouch2d ( - const Vector2D &a1, const Vector2D &a2, +bool CBotGlobals :: boundingBoxTouch2d ( const Vector2D &a1, const Vector2D &a2, const Vector2D &bmins, const Vector2D &bmaxs ) { - Vector2D amins = Vector2D(min(a1.x,a2.x),min(a1.y,a2.y)); - Vector2D amaxs = Vector2D(max(a1.x,a2.x),max(a1.y,a2.y)); + const Vector2D amins = Vector2D(std::min(a1.x, a2.x), std::min(a1.y, a2.y)); + const Vector2D amaxs = Vector2D(std::max(a1.x, a2.x), std::max(a1.y, a2.y)); - return (((bmins.x >= amins.x) && (bmins.y >= amins.y)) && ((bmins.x <= amaxs.x) && (bmins.y <= amaxs.y)) || - ((bmaxs.x >= amins.x) && (bmaxs.y >= amins.y)) && ((bmaxs.x <= amaxs.x) && (bmaxs.y <= amaxs.y))); + return (bmins.x >= amins.x && bmins.y >= amins.y && (bmins.x <= amaxs.x && bmins.y <= amaxs.y)) || + (bmaxs.x >= amins.x && bmaxs.y >= amins.y && (bmaxs.x <= amaxs.x && bmaxs.y <= amaxs.y)); } -bool CBotGlobals :: boundingBoxTouch3d ( - const Vector &a1, const Vector &a2, +bool CBotGlobals :: boundingBoxTouch3d ( const Vector &a1, const Vector &a2, const Vector &bmins, const Vector &bmaxs ) { - Vector amins = Vector(min(a1.x,a2.x),min(a1.y,a2.y),min(a1.z,a2.z)); - Vector amaxs = Vector(max(a1.x,a2.x),max(a1.y,a2.y),max(a1.z,a2.z)); + const Vector amins = Vector(std::min(a1.x, a2.x), std::min(a1.y, a2.y), std::min(a1.z, a2.z)); + const Vector amaxs = Vector(std::max(a1.x, a2.x), std::max(a1.y, a2.y), std::max(a1.z, a2.z)); - return (((bmins.x >= amins.x) && (bmins.y >= amins.y) && (bmins.z >= amins.z)) && ((bmins.x <= amaxs.x) && (bmins.y <= amaxs.y) && (bmins.z <= amaxs.z)) || - ((bmaxs.x >= amins.x) && (bmaxs.y >= amins.y) && (bmaxs.z >= amins.z)) && ((bmaxs.x <= amaxs.x) && (bmaxs.y <= amaxs.y) && (bmaxs.z <= amaxs.z))); + return (bmins.x >= amins.x && bmins.y >= amins.y && bmins.z >= amins.z && (bmins.x <= amaxs.x && bmins.y <= amaxs.y && bmins.z <= amaxs.z)) || + (bmaxs.x >= amins.x && bmaxs.y >= amins.y && bmaxs.z >= amins.z && (bmaxs.x <= amaxs.x && bmaxs.y <= amaxs.y && bmaxs.z <= amaxs.z)); } bool CBotGlobals :: onOppositeSides2d ( const Vector2D &amins, const Vector2D &amaxs, const Vector2D &bmins, const Vector2D &bmaxs ) { - float g = (amaxs.x - amins.x) * (bmins.y - amins.y) - - (amaxs.y - amins.y) * (bmins.x - amins.x); + const float g = (amaxs.x - amins.x) * (bmins.y - amins.y) - + (amaxs.y - amins.y) * (bmins.x - amins.x); - float h = (amaxs.x - amins.x) * (bmaxs.y - amins.y) - - (amaxs.y - amins.y) * (bmaxs.x - amins.x); + const float h = (amaxs.x - amins.x) * (bmaxs.y - amins.y) - + (amaxs.y - amins.y) * (bmaxs.x - amins.x); - return (g * h) <= 0.0f; + return g * h <= 0.0f; } bool CBotGlobals :: onOppositeSides3d ( @@ -877,51 +918,57 @@ bool CBotGlobals :: onOppositeSides3d ( amins.Cross(bmins); amaxs.Cross(bmaxs); - float g = (amaxs.x - amins.x) * (bmins.y - amins.y) * (bmins.z - amins.z) - - (amaxs.z - amins.z) * (amaxs.y - amins.y) * (bmins.x - amins.x); + const float g = (amaxs.x - amins.x) * (bmins.y - amins.y) * (bmins.z - amins.z) - + (amaxs.z - amins.z) * (amaxs.y - amins.y) * (bmins.x - amins.x); - float h = (amaxs.x - amins.x) * (bmaxs.y - amins.y) * (bmaxs.z - amins.z) - - (amaxs.z - amins.z) * (amaxs.y - amins.y) * (bmaxs.x - amins.x); + const float h = (amaxs.x - amins.x) * (bmaxs.y - amins.y) * (bmaxs.z - amins.z) - + (amaxs.z - amins.z) * (amaxs.y - amins.y) * (bmaxs.x - amins.x); - return (g * h) <= 0.0f; + return g * h <= 0.0f; } -bool CBotGlobals :: linesTouching2d ( - const Vector2D &amins, const Vector2D &amaxs, - const Vector2D &bmins, const Vector2D &bmaxs ) +bool CBotGlobals :: linesTouching2d (const Vector2D &amins, const Vector2D &amaxs, + const Vector2D &bmins, const Vector2D &bmaxs) { return onOppositeSides2d(amins,amaxs,bmins,bmaxs) && boundingBoxTouch2d(amins,amaxs,bmins,bmaxs); } -bool CBotGlobals :: linesTouching3d ( - const Vector &amins, const Vector &amaxs, - const Vector &bmins, const Vector &bmaxs ) +bool CBotGlobals :: linesTouching3d (const Vector &amins, const Vector &amaxs, + const Vector &bmins, const Vector &bmaxs) { return onOppositeSides3d(amins,amaxs,bmins,bmaxs) && boundingBoxTouch3d(amins,amaxs,bmins,bmaxs); } -void CBotGlobals :: botMessage ( edict_t *pEntity, int iErr, char *fmt, ... ) +void CBotGlobals :: botMessage ( edict_t *pEntity, const int iErr, const char *fmt, ... ) { va_list argptr; static char string[1024]; va_start (argptr, fmt); - vsprintf (string, fmt, argptr); + vsnprintf(string, sizeof(string), fmt, argptr); va_end (argptr); const char *bot_tag = BOT_TAG; - int len = strlen(string); - int taglen = strlen(BOT_TAG); + const std::size_t len = std::strlen(string); + const std::size_t taglen = std::strlen(BOT_TAG); + + // Ensure the total length does not exceed the buffer size - [APG]RoboCop[CL] + if (len + taglen + 1 >= sizeof(string)) + { + Warning("Message too long, truncating.\n"); + return; + } + // add tag -- push tag into string - for ( int i = len + taglen; i >= taglen; i -- ) + for ( std::size_t i = len + taglen; i >= taglen; i -- ) string[i] = string[i-taglen]; - string[len+taglen+1] = 0; + string[len + taglen] = '\0'; - for ( int i = 0; i < taglen; i ++ ) + for ( std::size_t i = 0; i < taglen; i ++ ) string[i] = bot_tag[i]; - strcat(string,"\n"); + std::strcat(string,"\n"); if ( pEntity ) { @@ -931,32 +978,33 @@ void CBotGlobals :: botMessage ( edict_t *pEntity, int iErr, char *fmt, ... ) { if ( iErr ) { - Warning(string); + Warning("%s", string); } else - Msg(string); + Msg("%s", string); } } -bool CBotGlobals :: makeFolders ( char *szFile ) +bool CBotGlobals :: makeFolders (const char* szFile) { + //Should be `const char*` to fix strings [APG]RoboCop[CL] #ifndef __linux__ - char *delimiter = "\\"; + const char* delimiter = "\\"; #else - char *delimiter = "/"; + const char* delimiter = "/"; #endif char szFolderName[1024]; - int folderNameSize = 0; + std::size_t folderNameSize = 0; szFolderName[0] = 0; - int iLen = strlen(szFile); + const std::size_t iLen = std::strlen(szFile); - int i = 0; + std::size_t i = 0; while ( i < iLen ) { - while ( (i < iLen) && (szFile[i] != *delimiter) ) + while ( i < iLen && szFile[i] != *delimiter ) { szFolderName[folderNameSize++]=szFile[i]; i++; @@ -966,19 +1014,19 @@ bool CBotGlobals :: makeFolders ( char *szFile ) return true; i++; - szFolderName[folderNameSize++]=*delimiter;//next - szFolderName[folderNameSize] = 0; - + szFolderName[folderNameSize++] =* delimiter; //next + szFolderName[folderNameSize] = 0; + #ifndef __linux__ - mkdir(szFolderName); + _mkdir(szFolderName); #else if ( mkdir(szFolderName, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0 ) { - botMessage(NULL,0,"Trying to create folder '%s' successful",szFolderName); + logger->Log(LogLevel::INFO, "Trying to create folder '%s' successful", szFolderName); } else { if (dirExists(szFolderName)) { - botMessage(NULL,0,"Folder '%s' already exists", szFolderName); + logger->Log(LogLevel::DEBUG, "Folder '%s' already exists", szFolderName); } else { - botMessage(NULL,0,"Trying to create folder '%s' failed",szFolderName); + logger->Log(LogLevel::ERROR, "Trying to create folder '%s' failed", szFolderName); } } #endif @@ -990,50 +1038,108 @@ bool CBotGlobals :: makeFolders ( char *szFile ) void CBotGlobals :: addDirectoryDelimiter ( char *szString ) { #ifndef __linux__ - strcat(szString,"\\"); + std::strcat(szString,"\\"); #else - strcat(szString,"/"); + std::strcat(szString,"/"); #endif } bool CBotGlobals :: isBreakableOpen ( edict_t *pBreakable ) { - return ((CClassInterface::getEffects(pBreakable) & EF_NODRAW) == EF_NODRAW); + return (CClassInterface::getEffects(pBreakable) & EF_NODRAW) == EF_NODRAW; } -Vector CBotGlobals:: getVelocity ( edict_t *pPlayer ) +Vector CBotGlobals:: getVelocity (const edict_t *pPlayer) { - CClient *pClient = CClients::get(pPlayer); - - if ( pClient ) + if ( CClient *pClient = CClients::get(pPlayer) ) return pClient->getVelocity(); - return Vector(0,0,0); + return {0,0,0}; +} + +/** + * Clone of CCollisionProperty::OBBCenter( ) --- see game/shared/collisionproperty.h + * + * @param pEntity Entity to get OBB center + **/ +Vector CBotGlobals::getOBBCenter( edict_t *pEntity ) +{ + Vector result = Vector(0,0,0); + VectorLerp(pEntity->GetCollideable()->OBBMins(), pEntity->GetCollideable()->OBBMaxs(), 0.5f, result); + return result; +} + +Vector CBotGlobals::collisionToWorldSpace( const Vector &in, edict_t *pEntity ) +{ + Vector result = Vector(0,0,0); + + if(!isBoundsDefinedInEntitySpace(pEntity) || pEntity->GetCollideable()->GetCollisionAngles() == vec3_angle) + { + VectorAdd(in, pEntity->GetCollideable()->GetCollisionOrigin(), result); + } + else + { + VectorTransform(in, pEntity->GetCollideable()->CollisionToWorldTransform(), result); + } + + return result; } -FILE *CBotGlobals :: openFile ( char *szFile, char *szMode ) +/** + * Gets the entity world center. Clone of WorldSpaceCenter() + * @param pEntity The entity to get the center from + * @return Center vector + **/ +Vector CBotGlobals::worldCenter( edict_t *pEntity ) { - FILE *fp = fopen(szFile,szMode); + Vector result = getOBBCenter(pEntity); + result = collisionToWorldSpace(result, pEntity); + return result; +} - if ( fp == NULL ) +/** + * Checks if a point is within a trigger + * + * @param pEntity The trigger entity + * @param vPoint The point to be tested + * @return True if the given point is within pEntity + **/ +bool CBotGlobals::pointIsWithin( edict_t *pEntity, const Vector &vPoint ) +{ + Ray_t ray; + trace_t tr; + ICollideable *pCollide = pEntity->GetCollideable(); + ray.Init(vPoint, vPoint); + enginetrace->ClipRayToCollideable(ray, MASK_ALL, pCollide, &tr); + return tr.startsolid; +} + +std::fstream CBotGlobals::openFile(const char* szFile, const std::ios_base::openmode mode) +{ + std::fstream fp; + fp.open(szFile, mode); + + if (!fp) { - botMessage ( NULL, 0, "file not found/opening error '%s' mode %s", szFile, szMode ); + logger->Log(LogLevel::INFO, "file not found/opening error '%s' mode %d", szFile, mode); makeFolders(szFile); // try again - fp = fopen(szFile,szMode); + fp.open(szFile, mode); - if ( fp == NULL ) - botMessage ( NULL, 0, "failed to make folders for %s",szFile); + if (!fp) + logger->Log(LogLevel::WARN, "failed to make folders for %s", szFile); + } else { + logger->Log(LogLevel::INFO, "Opened file '%s' mode %i", szFile, mode); // `mode %i` fix by caxanga334 } return fp; } -void CBotGlobals :: buildFileName ( char *szOutput, const char *szFile, const char *szFolder, const char *szExtension, bool bModDependent ) +void CBotGlobals :: buildFileName ( char *szOutput, const char *szFile, const char *szFolder, const char *szExtension, const bool bModDependent ) { - if (m_szRCBotFolder == NULL) + if (m_szRCBotFolder == nullptr) { #ifdef HOMEFOLDER char home[512]; @@ -1041,66 +1147,67 @@ void CBotGlobals :: buildFileName ( char *szOutput, const char *szFile, const ch #endif szOutput[0] = 0; -#if defined(HOMEFOLDER) && defined(__linux) +#if defined(HOMEFOLDER) && defined(__linux__) char *lhome = getenv ("HOME"); if (lhome != NULL) { - strncpy(home,lhome,511); + std::strncpy(home,lhome,511); home[511] = 0; } else - strcpy(home,"."); + std::strcpy(home,"."); #endif -#if defined(HOMEFOLDER) && defined(WIN32) +#if defined(HOMEFOLDER) && defined(_WIN64) ExpandEnvironmentStringsA("%userprofile%", home, 511); #endif #ifdef HOMEFOLDER - strcat(szOutput, home); + std::strcat(szOutput, home); addDirectoryDelimiter(szOutput); #endif /*#ifndef HOMEFOLDER - strcat(szOutput,".."); + std::strcat(szOutput,".."); #endif HOMEFOLDER*/ - strcat(szOutput, BOT_FOLDER); + std::strcat(szOutput, BOT_FOLDER); } else - strcpy(szOutput, m_szRCBotFolder); + std::strcpy(szOutput, m_szRCBotFolder); - if ( (szOutput[strlen(szOutput)-1] != '\\') && (szOutput[strlen(szOutput)-1] != '/') ) + if (const std::size_t len = std::strlen(szOutput); len > 0 && szOutput[len - 1] != '\\' && szOutput[len - 1] != '/') addDirectoryDelimiter(szOutput); if ( szFolder ) { - strcat(szOutput,szFolder); + std::strcat(szOutput,szFolder); addDirectoryDelimiter(szOutput); } if ( bModDependent ) { - strcat(szOutput,CBotGlobals::gameFolder()); - addDirectoryDelimiter(szOutput); - strcat(szOutput,CBotGlobals::modFolder()); + std::strcat(szOutput,CBotGlobals::modFolder()); addDirectoryDelimiter(szOutput); } - strcat(szOutput,szFile); + std::strcat(szOutput,szFile); if ( szExtension ) { - strcat(szOutput,"."); - strcat(szOutput,szExtension); + std::strcat(szOutput,"."); + std::strcat(szOutput,szExtension); } + + //if (m_szRCBotFolder != NULL) + // filesystem->RelativePathToFullPath(szOutput, NULL, szOutput, 512, FILTER_CULLPACK); } QAngle CBotGlobals::playerAngles ( edict_t *pPlayer ) { IPlayerInfo *pPlayerInfo = playerinfomanager->GetPlayerInfo(pPlayer); - CBotCmd lastCmd = pPlayerInfo->GetLastUserCommand(); + const CBotCmd lastCmd = pPlayerInfo->GetLastUserCommand(); return lastCmd.viewangles; } @@ -1132,7 +1239,7 @@ void CBotGlobals :: fixFloatDegrees360 ( float *pFloat ) *pFloat += 360; } -float CBotGlobals :: yawAngleFromEdict (edict_t *pEntity,Vector vOrigin) +float CBotGlobals :: yawAngleFromEdict (edict_t *pEntity, const Vector& vOrigin) { /* float fAngle; @@ -1153,14 +1260,13 @@ float CBotGlobals :: yawAngleFromEdict (edict_t *pEntity,Vector vOrigin) float fAngle; float fYaw; - QAngle qBotAngles = playerAngles(pEntity); + const QAngle qBotAngles = playerAngles(pEntity); QAngle qAngles; - Vector vAngles; Vector vPlayerOrigin; gameclients->ClientEarPosition(pEntity,&vPlayerOrigin); - vAngles = vOrigin - vPlayerOrigin; + const Vector vAngles = vOrigin - vPlayerOrigin; VectorAngles(vAngles/vAngles.Length(),qAngles); @@ -1175,12 +1281,13 @@ float CBotGlobals :: yawAngleFromEdict (edict_t *pEntity,Vector vOrigin) } -void CBotGlobals::teleportPlayer ( edict_t *pPlayer, Vector v_dest ) +void CBotGlobals::teleportPlayer(const edict_t* pPlayer, const Vector& v_dest) { - CClient *pClient = CClients::get(pPlayer); - - if ( pClient ) - pClient->teleportTo(v_dest); + CClient* pClient = CClients::get(pPlayer); + + assert(pClient && "CClients::get returned nullptr!"); + + pClient->teleportTo(v_dest); } /* diff --git a/utils/RCBot2_meta/bot_globals.h b/utils/RCBot2_meta/bot_globals.h index 7be1c4b23..f3296abf0 100644 --- a/utils/RCBot2_meta/bot_globals.h +++ b/utils/RCBot2_meta/bot_globals.h @@ -38,13 +38,18 @@ #include "bot_const.h" // for Mod id #include "bot_commands.h" // for main rcbot command -#ifdef _WIN32 -#include +#include + +#if defined(_WIN64) || defined(_WIN32) +#include #endif -#define MAX_MAP_STRING_LEN 64 -#define MAX_PATH_LEN 512 -#define MAX_ENTITIES 2048 +enum : std::uint16_t +{ + MAX_MAP_STRING_LEN = 64, + MAX_PATH_LEN = 512, + MAX_ENTITIES = 2048 +}; class CBotGlobals { @@ -60,55 +65,53 @@ class CBotGlobals static QAngle playerAngles ( edict_t *pPlayer ); - static void freeMemory (); - - static inline bool isPlayer ( edict_t *pEdict ) + static bool isPlayer(const edict_t* pEdict) { - static int index; + const int index = ENTINDEX(pEdict); - index = ENTINDEX(pEdict); - - return (index>0)&&(index<=gpGlobals->maxClients); + return index > 0 && index <= gpGlobals->maxClients; } - static bool walkableFromTo (edict_t *pPlayer,Vector v_src, Vector v_dest); + static bool walkableFromTo (edict_t *pPlayer, const Vector& v_src, const Vector& v_dest); - static void teleportPlayer ( edict_t *pPlayer, Vector v_dest ); + static void teleportPlayer (const edict_t *pPlayer, const Vector& v_dest); - static float yawAngleFromEdict(edict_t *pEntity,Vector vOrigin); + static float yawAngleFromEdict(edict_t *pEntity, const Vector& vOrigin); //static float getAvoidAngle(edict_t *pEdict,Vector origin); // make folders for a file if they don't exist - static bool makeFolders ( char *szFile ); + static bool makeFolders (const char* szFile); // just open file but also make folders if possible - static FILE *openFile ( char *szFile, char *szMode ); + static std::fstream openFile (const char *szFile, std::ios_base::openmode mode); // get the proper location - static void buildFileName ( char *szOutput, const char *szFile, const char *szFolder = NULL, const char *szExtension = NULL, bool bModDependent = false ); + static void buildFileName ( char *szOutput, const char *szFile, const char *szFolder = nullptr, const char *szExtension = nullptr, bool bModDependent = false ); // add a directory delimiter to the string like '/' (linux) or '\\' (windows) or static void addDirectoryDelimiter ( char *szString ); // print a message to client pEntity with bot formatting - static void botMessage ( edict_t *pEntity, int iErr, char *fmt, ... ); + static void botMessage ( edict_t *pEntity, int iErr, const char *fmt, ... ); static void fixFloatAngle ( float *fAngle ); - static float DotProductFromOrigin ( edict_t *pEnemy, Vector pOrigin ); - static float DotProductFromOrigin ( Vector vPlayer, Vector vFacing, QAngle eyes ); + static float DotProductFromOrigin ( edict_t *pEnemy, const Vector& pOrigin ); + static float DotProductFromOrigin (const Vector& vPlayer, const Vector& vFacing, const QAngle& eyes ); + static int numPlayersPlaying(); static int numPlayersOnTeam(int iTeam, bool bAliveOnly); + static int numBotsOnTeam(int iTeam, bool bAliveOnly); static void setMapName ( const char *szMapName ); static char *getMapName (); static bool IsMapRunning () { return m_bMapRunning; } - static void setMapRunning ( bool bSet ) { m_bMapRunning = bSet; } + static void setMapRunning (const bool bSet) { m_bMapRunning = bSet; } static bool isNetworkable ( edict_t *pEntity ); - static inline bool entityIsValid ( edict_t *pEntity ) + static bool entityIsValid ( edict_t *pEntity ) { - return pEntity && !pEntity->IsFree() && (pEntity->GetNetworkable() != NULL) && (pEntity->GetIServerEntity() != NULL) && (pEntity->m_NetworkSerialNumber != 0); + return pEntity && !pEntity->IsFree() && pEntity->GetNetworkable() != nullptr && pEntity->GetIServerEntity() != nullptr && pEntity->m_NetworkSerialNumber != 0; } - static void serverSay ( char *fmt, ... ); + static void serverSay (const char* fmt, ... ); static bool isAlivePlayer ( edict_t *pEntity ); @@ -119,7 +122,7 @@ class CBotGlobals static edict_t *findPlayerByTruncName ( const char *name ); // linux fix - inline static CBotMod *getCurrentMod () + static CBotMod *getCurrentMod () { return m_pCurrentMod; } @@ -150,7 +153,7 @@ class CBotGlobals const Vector &amins, const Vector &amaxs, const Vector &bmins, const Vector &bmaxs ); - static float grenadeWillLand ( Vector vOrigin, Vector vEnemy, float fProjSpeed = 400.0f, float fGrenadePrimeTime = 5.0f, float *fAngle = NULL ); + static float grenadeWillLand (const Vector& vOrigin, const Vector& vEnemy, float fProjSpeed = 400.0f, float fGrenadePrimeTime = 5.0f, const float *fAngle = nullptr); //////////////////////////////////////////////////////////////////////// /*static Vector forwardVec (); @@ -158,57 +161,72 @@ class CBotGlobals static Vector upVec ();*/ //////// static trace_t *getTraceResult () { return &m_TraceResult; } - static bool isVisibleHitAllExceptPlayer ( edict_t *pPlayer, Vector vSrc, Vector vDest, edict_t *pDest = NULL ); - static bool isVisible ( edict_t *pPlayer, Vector vSrc, Vector vDest); - static bool isVisible ( edict_t *pPlayer, Vector vSrc, edict_t *pDest); - static bool isShotVisible ( edict_t *pPlayer, Vector vSrc, Vector vDest, edict_t *pDest ); - static bool isVisible ( Vector vSrc, Vector vDest); - static void traceLine ( Vector vSrc, Vector vDest, unsigned int mask, ITraceFilter *pFilter); - static float quickTraceline ( edict_t *pIgnore, Vector vSrc, Vector vDest ); // return fFraction + static bool isVisibleHitAllExceptPlayer ( edict_t *pPlayer, const Vector& vSrc, const Vector& vDest, edict_t *pDest = nullptr); + static bool isVisible ( edict_t *pPlayer, const Vector& vSrc, const Vector& vDest); + static bool isVisible ( edict_t *pPlayer, const Vector& vSrc, edict_t *pDest); + static bool isShotVisible ( edict_t *pPlayer, const Vector& vSrc, const Vector& vDest, edict_t *pDest ); + static bool isVisible (const Vector& vSrc, const Vector& vDest); + static void traceLine (const Vector& vSrc, const Vector& vDest, unsigned mask, ITraceFilter *pFilter); + static float quickTraceline ( edict_t *pIgnore, const Vector& vSrc, const Vector& vDest ); // return fFraction static bool traceVisible (edict_t *pEnt); //////// - static inline Vector entityOrigin ( edict_t *pEntity ) + static Vector entityOrigin ( edict_t *pEntity ) { return pEntity->GetIServerEntity()->GetCollideable()->GetCollisionOrigin(); } static int getTeam ( edict_t *pEntity ); static bool entityIsAlive ( edict_t *pEntity ); - static int countTeamMatesNearOrigin ( Vector vOrigin, float fRange, int iTeam, edict_t *pIgnore = NULL ); + static bool isBrushEntity( edict_t *pEntity ); + static int countTeamMatesNearOrigin (const Vector& vOrigin, float fRange, int iTeam, const edict_t *pIgnore = nullptr); static int numClients (); static void levelInit(); - static inline void setClientMax ( int iMaxClients ) { m_iMaxClients = iMaxClients; } - - static inline void setEventVersion ( int iVersion ){m_iEventVersion = iVersion;} + static void setClientMax (const int iMaxClients) { m_iMaxClients = iMaxClients; } - static inline bool isEventVersion ( int iVersion ){return (m_iEventVersion == iVersion);} + static void setEventVersion (const int iVersion) { m_iEventVersion = iVersion; } - static inline bool getTeamplayOn (){return m_bTeamplay;} + static bool isEventVersion (const int iVersion) { return m_iEventVersion == iVersion; } - static inline void setTeamplay ( bool bOn ){m_bTeamplay = bOn;} + static bool getTeamplayOn () { return m_bTeamplay; } - static inline bool isMod ( eModId iMod ) { return m_iCurrentMod == iMod; } + static void setTeamplay (const bool bOn) { m_bTeamplay = bOn; } - static inline char *gameFolder (){return m_szGameFolder;} + static bool isMod (const eModId iMod) { return m_iCurrentMod == iMod; } - static inline char *modFolder (){return m_szModFolder;} + static char *modFolder (){return m_szModFolder;} - static inline int maxClients () {return m_iMaxClients;} + static int maxClients () {return m_iMaxClients;} static edict_t *playerByUserId(int iUserId); - static bool isCurrentMod ( eModId modid ); + static bool isCurrentMod ( eModId modid ); //TODO: not implemented? [APG]RoboCop[CL] - static bool checkOpensLater ( Vector vSrc, Vector vDest ); + static bool checkOpensLater (const Vector& vSrc, const Vector& vDest ); - inline static bool setupMapTime ( ) { return m_fMapStartTime == 0; } + static bool setupMapTime ( ) { return m_fMapStartTime == 0.0f; } static bool isBreakableOpen ( edict_t *pBreakable ); - static Vector getVelocity ( edict_t *pPlayer ); + static Vector getVelocity (const edict_t *pPlayer ); + + static bool isBoundsDefinedInEntitySpace(edict_t* pEntity) + { + const ICollideable* pCollideable = pEntity->GetCollideable(); // Store the result in a local pointer [APG]RoboCop[CL] + return (pCollideable->GetSolidFlags() & FSOLID_FORCE_WORLD_ALIGNED) == 0 && + pCollideable->GetSolid() != SOLID_BBOX && + pCollideable->GetSolid() != SOLID_NONE; + } + + static Vector getOBBCenter( edict_t *pEntity ); + + static Vector collisionToWorldSpace( const Vector &in, edict_t *pEntity ); + + static Vector worldCenter( edict_t *pEntity ); + + static bool pointIsWithin( edict_t *pEntity, const Vector &vPoint ); //////// - static CBotCommandContainer *m_pCommands; + static CBotSubcommands *m_pCommands; static void readRCBotFolder(); @@ -228,7 +246,6 @@ class CBotGlobals static eModId m_iCurrentMod; static CBotMod *m_pCurrentMod; static char *m_szModFolder; - static char *m_szGameFolder; static char m_szMapName[MAX_MAP_STRING_LEN]; static int m_iDebugLevels; static bool m_bMapRunning; diff --git a/utils/RCBot2_meta/bot_hl1dmsrc.cpp b/utils/RCBot2_meta/bot_hl1dmsrc.cpp index 4b1ea4535..1d7842016 100644 --- a/utils/RCBot2_meta/bot_hl1dmsrc.cpp +++ b/utils/RCBot2_meta/bot_hl1dmsrc.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -34,12 +36,13 @@ #include "bot_globals.h" #include "bot_profile.h" - #include "bot_mtrand.h" -void CHL1DMSrcBot :: init () +#include + +void CHL1DMSrcBot :: init (const bool bVarInit) { - CBot::init(); + CBot::init(bVarInit); } void CHL1DMSrcBot :: setup () @@ -47,7 +50,6 @@ void CHL1DMSrcBot :: setup () CBot::setup(); } - bool CHL1DMSrcBot :: startGame () { return true; @@ -58,7 +60,7 @@ void CHL1DMSrcBot :: killed ( edict_t *pVictim ) return; } -void CHL1DMSrcBot :: died ( edict_t *pKiller ) +void CHL1DMSrcBot :: died (edict_t* pKiller, const char* pszWeapon) { spawnInit(); @@ -84,17 +86,17 @@ bool CHL1DMSrcBot :: isEnemy ( edict_t *pEdict,bool bCheckWeapons ) if ( ENTINDEX(pEdict) > CBotGlobals::maxClients() ) // monster { - const char *cname = ((IServerNetworkable*)pEdict->GetNetworkable())->GetClassName(); + const char *cname = pEdict->GetNetworkable()->GetClassName(); - if ( strncmp("monster_",cname,8) == 0 ) + if ( std::strncmp("monster_",cname,8) == 0 ) { - if ( strcmp(cname,"monster_barney") == 0 ) + if ( std::strcmp(cname,"monster_barney") == 0 ) return false; - else if ( strcmp(cname,"monster_scientist") == 0 ) + if ( std::strcmp(cname,"monster_scientist") == 0 ) return false; - else if ( strcmp(cname,"monster_gman") == 0 ) + if ( std::strcmp(cname,"monster_gman") == 0 ) return false; - else if ( strcmp(cname,"monster_furniture") == 0 ) + if ( std::strcmp(cname,"monster_furniture") == 0 ) return false; return true; @@ -113,5 +115,4 @@ bool CHL1DMSrcBot :: isEnemy ( edict_t *pEdict,bool bCheckWeapons ) void CHL1DMSrcBot :: modThink () { // find weapons and neat stuff - } \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_hl1dmsrc_bot.h b/utils/RCBot2_meta/bot_hl1dmsrc_bot.h index cf17adce4..bb631f83f 100644 --- a/utils/RCBot2_meta/bot_hl1dmsrc_bot.h +++ b/utils/RCBot2_meta/bot_hl1dmsrc_bot.h @@ -35,22 +35,21 @@ class CHL1DMSrcBot : public CBot { public: + static bool isHL1DMSrc () { return true; } - bool isHL1DMSrc () { return true; } + void modThink () override; - void modThink (); + void init (bool bVarInit = false) override; + void setup () override; - void init (); - void setup (); + bool startGame () override; - bool startGame (); + void died (edict_t* pKiller, const char* pszWeapon) override; + static void killed ( edict_t *pVictim ); - void died ( edict_t *pKiller ); - void killed ( edict_t *pVictim ); + void spawnInit () override; - void spawnInit (); - - bool isEnemy ( edict_t *pEdict,bool bCheckWeapons = true ); + bool isEnemy ( edict_t *pEdict, bool bCheckWeapons = true ) override; private: // blah blah }; diff --git a/utils/RCBot2_meta/bot_hldm_bot.cpp b/utils/RCBot2_meta/bot_hldm_bot.cpp index e22300864..9a00ac5ed 100644 --- a/utils/RCBot2_meta/bot_hldm_bot.cpp +++ b/utils/RCBot2_meta/bot_hldm_bot.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -28,33 +30,33 @@ * version. * */ + #include "in_buttons.h" #include "bot.h" +#include "bot_cvars.h" #include "bot_hldm_bot.h" #include "bot_client.h" #include "bot_buttons.h" #include "bot_globals.h" -#include "bot_profile.h" +//#include "bot_profile.h" #include "bot_navigator.h" #include "bot_waypoint.h" #include "bot_utility.h" #include "bot_task.h" #include "bot_schedule.h" -#include "bot_waypoint.h" +//#include "bot_waypoint.h" #include "bot_weapons.h" #include "bot_mtrand.h" #include "bot_waypoint_locations.h" #include "bot_getprop.h" +#include "rcbot/logging.h" - -extern ConVar rcbot_jump_obst_dist; -extern ConVar rcbot_jump_obst_speed; -extern ConVar rcbot_melee_only; +#include // initialise , i.e. set everything to a default value -void CHLDMBot :: init () +void CHLDMBot :: init (const bool bVarInit) { - CBot::init(); + CBot::init(bVarInit); } // initialize structures and classes used be the bot @@ -73,20 +75,18 @@ bool CHLDMBot :: startGame () // the bot killed pVictim void CHLDMBot :: killed ( edict_t *pVictim, char *weapon ) { - extern ConVar bot_beliefmulti; - - CBot::killed(pVictim,weapon); + CBot::killed(pVictim, weapon); // update belief around this waypoint - if ( pVictim && CBotGlobals::entityIsValid(pVictim) ) - m_pNavigator->belief(CBotGlobals::entityOrigin(pVictim),getEyePosition(),bot_beliefmulti.GetFloat(),distanceFrom(pVictim),BELIEF_SAFETY); + if (pVictim && CBotGlobals::entityIsValid(pVictim)) + { + m_pNavigator->belief(CBotGlobals::entityOrigin(pVictim), getEyePosition(), bot_beliefmulti.GetFloat(), distanceFrom(pVictim), BELIEF_SAFETY); + } } // the bot was killed by pKiller void CHLDMBot :: died ( edict_t *pKiller, const char *pszWeapon ) { - extern ConVar bot_beliefmulti; - // re-initialize stuff per life CBot::died(pKiller, pszWeapon); @@ -102,17 +102,15 @@ void CHLDMBot :: died ( edict_t *pKiller, const char *pszWeapon ) } } -void CHLDMBot :: touchedWpt ( CWaypoint *pWaypoint ) +void CHLDMBot :: touchedWpt (CWaypoint* pWaypoint, const int iNextWaypoint, const int iPrevWaypoint) { - CBot::touchedWpt(pWaypoint); + CBot::touchedWpt(pWaypoint, iNextWaypoint, iPrevWaypoint); if ( pWaypoint->hasFlag(CWaypointTypes::W_FL_LIFT) ) { if ( m_fUseButtonTime < engine->Time() ) { - edict_t *pButton = CHalfLifeDeathmatchMod::getButtonAtWaypoint(pWaypoint); - - if ( pButton ) + if ( edict_t *pButton = CHalfLifeDeathmatchMod::getButtonAtWaypoint(pWaypoint) ) { m_fUseButtonTime = engine->Time() + randomFloat(5.0f,10.0f); @@ -122,6 +120,7 @@ void CHLDMBot :: touchedWpt ( CWaypoint *pWaypoint ) } } } + // new life void CHLDMBot :: spawnInit () { @@ -132,47 +131,60 @@ void CHLDMBot :: spawnInit () m_CurrentUtil = BOT_UTIL_MAX; // reset objects - m_pNearbyWeapon = NULL; - m_FailedPhysObj = NULL; - m_flSprintTime = 0; - m_NearestPhysObj = NULL; - m_pBattery = NULL; - m_pHealthKit = NULL; - m_pAmmoKit = NULL; - m_pCurrentWeapon = NULL; - m_pCharger = NULL; + m_pNearbyWeapon = nullptr; + m_FailedPhysObj = nullptr; + m_fSprintTime = 0.0f; + m_NearestPhysObj = nullptr; + + m_pBattery = nullptr; + m_pHealthKit = nullptr; + m_pAmmoKit = nullptr; + m_pCurrentWeapon = nullptr; + m_pCharger = nullptr; + m_fFixWeaponTime = 0.0f; m_fUseButtonTime = 0.0f; m_fUseCrateTime = 0.0f; + + ConVarRef hl2_normspeed("hl2_normspeed"); + + if (!hl2_normspeed.IsValid()) + { + logger->Log(LogLevel::ERROR, "Unable to find \"hl2_normspeed\" ConVar!"); + m_fCachedNormSpeed = 190.0f; // hl2_normspeed default value -caxanga334 + } + else + { + m_fCachedNormSpeed = hl2_normspeed.GetFloat(); + } } // Is pEdict an enemy? return true if enemy / false if not // if checkWeapons is true, check if current weapon can attack enemy // return false if not -bool CHLDMBot :: isEnemy ( edict_t *pEdict,bool bCheckWeapons ) +bool CHLDMBot::isEnemy(edict_t* pEdict, bool bCheckWeapons) { - extern ConVar rcbot_notarget; static int entity_index; entity_index = ENTINDEX(pEdict); // if no target on - listen sever player is a non target - if ( rcbot_notarget.GetBool() && (entity_index == 1) ) + if (rcbot_notarget.GetBool() && entity_index == 1) return false; // not myself - if ( pEdict == m_pEdict ) + if (pEdict == m_pEdict) return false; // not a player - false - if ( !entity_index || (entity_index > CBotGlobals::maxClients()) ) + if (!entity_index || entity_index > CBotGlobals::maxClients()) { - if ( !m_pCarryingObject && pEdict->GetUnknown() && (pEdict == m_NearestBreakable) && (CClassInterface::getPlayerHealth(pEdict)>0) ) + if (!m_pCarryingObject && pEdict->GetUnknown() && pEdict == m_NearestBreakable && CClassInterface::getPlayerHealth(pEdict) > 0) { - if ( distanceFrom(CBotGlobals::entityOrigin(pEdict)) < rcbot_jump_obst_dist.GetFloat() ) + if (distanceFrom(CBotGlobals::entityOrigin(pEdict)) < rcbot_jump_obst_dist.GetFloat()) { - if ( BotFunc_BreakableIsEnemy(m_NearestBreakable,m_pEdict) || ((CBotGlobals::entityOrigin(pEdict) - m_vMoveTo).Length()+48) < (getOrigin() - m_vMoveTo).Length() ) - return true; + if (BotFunc_BreakableIsEnemy(m_NearestBreakable, m_pEdict) || (CBotGlobals::entityOrigin(pEdict) - m_vMoveTo).Length() + 48 < (getOrigin() - m_vMoveTo).Length()) + return true; } } @@ -180,31 +192,29 @@ bool CHLDMBot :: isEnemy ( edict_t *pEdict,bool bCheckWeapons ) } // not alive -- false - if ( !CBotGlobals::entityIsAlive(pEdict) ) + if (!CBotGlobals::entityIsAlive(pEdict)) return false; // team game? - if ( CBotGlobals::getTeamplayOn() ) + if (CBotGlobals::getTeamplayOn()) { // same team ? false - if ( CBotGlobals::getTeam(pEdict) == getTeam() ) + if (CBotGlobals::getTeam(pEdict) == getTeam()) return false; } - return true; + return true; } // from the bots UTILITIES , execute the given action -bool CHLDMBot :: executeAction ( eBotAction iAction ) +bool CHLDMBot :: executeAction (const eBotAction iAction) { switch ( iAction ) { case BOT_UTIL_HL2DM_USE_CRATE: // check if it is worth it first { - const char *szModel; - char type; - CBotWeapon *pWeapon = NULL; + const CBotWeapon *pWeapon = nullptr; /* possible models @@ -216,8 +226,8 @@ bool CHLDMBot :: executeAction ( eBotAction iAction ) models/items/ammocrate_smg1.mdl */ - szModel = m_pAmmoCrate.get()->GetIServerEntity()->GetModelName().ToCStr(); - type = szModel[23]; + const char* szModel = m_pAmmoCrate.get()->GetIServerEntity()->GetModelName().ToCStr(); + const char type = szModel[23]; if ( type == 'a' ) // ar2 { @@ -236,7 +246,7 @@ bool CHLDMBot :: executeAction ( eBotAction iAction ) pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(HL2DM_WEAPON_SMG1)); } - if ( pWeapon && (pWeapon->getAmmo(this) < 1) ) + if ( pWeapon && pWeapon->getAmmo(this) < 1 ) { CBotSchedule *pSched = new CBotSchedule(); @@ -304,10 +314,10 @@ bool CHLDMBot :: executeAction ( eBotAction iAction ) pFindPath->setCompleteInterrupt(CONDITION_SEE_CUR_ENEMY); - if ( !CClassInterface::getVelocity(m_pLastEnemy,&vVelocity) ) + assert(pClient != nullptr); // Ensure pClient is not null - [APG]RoboCop[CL] + if (!CClassInterface::getVelocity(m_pLastEnemy, &vVelocity)) { - if ( pClient ) - vVelocity = pClient->getVelocity(); + vVelocity = pClient->getVelocity(); } pSchedule->addTask(pFindPath); @@ -325,31 +335,34 @@ bool CHLDMBot :: executeAction ( eBotAction iAction ) case BOT_UTIL_THROW_GRENADE: { // find hide waypoint - CWaypoint *pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::GetCoverWaypoint(getOrigin(),m_vLastSeeEnemy,NULL)); - if ( pWaypoint ) + if ( CWaypoint *pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::GetCoverWaypoint(getOrigin(),m_vLastSeeEnemy, nullptr)) ) { CBotSchedule *pSched = new CBotSchedule(); - pSched->addTask(new CThrowGrenadeTask(m_pWeapons->getWeapon(CWeapons::getWeapon(HL2DM_WEAPON_FRAG)),getAmmo(CWeapons::getWeapon(HL2DM_WEAPON_FRAG)->getAmmoIndex1()),m_vLastSeeEnemyBlastWaypoint)); // first - throw + pSched->addTask(new CThrowGrenadeTask( + m_pWeapons->getWeapon(CWeapons::getWeapon(HL2DM_WEAPON_FRAG)), + getAmmo(CWeapons::getWeapon(HL2DM_WEAPON_FRAG)->getAmmoIndex1()), + m_vLastSeeEnemyBlastWaypoint + )); + pSched->addTask(new CFindPathTask(pWaypoint->getOrigin())); // 2nd -- hide m_pSchedules->add(pSched); return true; } - } + break; case BOT_UTIL_SNIPE: { // roam - CWaypoint *pWaypoint = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_SNIPER); - if ( pWaypoint ) + if ( CWaypoint *pWaypoint = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_SNIPER) ) { - CBotSchedule *snipe = new CBotSchedule(); + CBotSchedule* snipe = new CBotSchedule(); CBotTask *findpath = new CFindPathTask(CWaypoints::getWaypointIndex(pWaypoint)); - CBotTask *snipetask; - // use DOD task - snipetask = new CBotHL2DMSnipe(m_pWeapons->getWeapon(CWeapons::getWeapon(HL2DM_WEAPON_CROSSBOW)),pWaypoint->getOrigin(),pWaypoint->getAimYaw(),false,0); + // use DOD task //Unstable? [APG]RoboCop[CL] + CBotTask* snipetask = new CBotHL2DMSnipe(m_pWeapons->getWeapon(CWeapons::getWeapon(HL2DM_WEAPON_CROSSBOW)), + pWaypoint->getOrigin(), pWaypoint->getAimYaw(), false, 0); findpath->setCompleteInterrupt(CONDITION_PUSH); snipetask->setCompleteInterrupt(CONDITION_PUSH); @@ -380,6 +393,7 @@ bool CHLDMBot :: executeAction ( eBotAction iAction ) return false; } + // deal with attacking code here // return false if it is impossible to shoot this enemy; i.e. change enemy // return true: if it is possible to shoot this enemy @@ -388,7 +402,6 @@ bool CHLDMBot :: handleAttack ( CBotWeapon *pWeapon, edict_t *pEnemy ) { if ( pWeapon ) { - extern ConVar rcbot_enemyshoot_gravgun_fov; static float fDistance; fDistance = distanceFrom(pEnemy); @@ -398,7 +411,7 @@ bool CHLDMBot :: handleAttack ( CBotWeapon *pWeapon, edict_t *pEnemy ) if ( pWeapon->isMelee() ) setMoveTo(CBotGlobals::entityOrigin(pEnemy)); - if ( (pWeapon->getID() == HL2DM_WEAPON_PHYSCANNON) && (DotProductFromOrigin(m_vAimVector) < rcbot_enemyshoot_gravgun_fov.GetFloat()) ) + if ( pWeapon->getID() == HL2DM_WEAPON_PHYSCANNON && DotProductFromOrigin(m_vAimVector) < rcbot_enemyshoot_gravgun_fov.GetFloat() ) return true; // keep enemy / don't shoot : until angle between enemy is less than 20 degrees if ( pWeapon->canUseSecondary() && pWeapon->getAmmo(this,2) && pWeapon->secondaryInRange(fDistance) ) @@ -430,13 +443,12 @@ bool CHLDMBot :: handleAttack ( CBotWeapon *pWeapon, edict_t *pEnemy ) return false; } // time to think about something new to do -void CHLDMBot :: getTasks (unsigned int iIgnore) +void CHLDMBot :: getTasks (unsigned iIgnore) { static CBotUtilities utils; static CBotUtility *next; static CBotWeapon *gravgun; static CBotWeapon *crossbow; - static CWeapon *pWeapon; static bool bCheckCurrent; if ( !hasSomeConditions(CONDITION_CHANGED) && !m_pSchedules->isEmpty() ) @@ -453,63 +465,74 @@ void CHLDMBot :: getTasks (unsigned int iIgnore) { edict_t *pent = INDEXENT(gravgun->getWeaponIndex()); - if ( CBotGlobals::entityIsValid(pent) ) + if (CBotGlobals::entityIsValid(pent)) { - ADD_UTILITY(BOT_UTIL_HL2DM_GRAVIGUN_PICKUP,(!m_pEnemy||(m_pCurrentWeapon&&(strcmp("weapon_physcannon",m_pCurrentWeapon->GetClassName())))) && gravgun && gravgun->hasWeapon() && (m_NearestPhysObj.get()!=NULL) && (gravgun->getWeaponIndex() > 0) && (CClassInterface::gravityGunObject(INDEXENT(gravgun->getWeaponIndex()))==NULL),0.9f); + ADD_UTILITY(BOT_UTIL_HL2DM_GRAVIGUN_PICKUP, + (!m_pEnemy || (m_pCurrentWeapon && std::strcmp("weapon_physcannon", m_pCurrentWeapon->GetClassName()) == 0)) && + gravgun && gravgun->hasWeapon() && (m_NearestPhysObj.get() != nullptr) && gravgun->getWeaponIndex() > 0 && + (CClassInterface::gravityGunObject(INDEXENT(gravgun->getWeaponIndex())) == nullptr), 0.9f) } } - if ( (crossbow = m_pWeapons->getWeapon(CWeapons::getWeapon(HL2DM_WEAPON_CROSSBOW))) != NULL ) + if ( (crossbow = m_pWeapons->getWeapon(CWeapons::getWeapon(HL2DM_WEAPON_CROSSBOW))) != nullptr) { if ( crossbow->hasWeapon() && !crossbow->outOfAmmo(this) ) - ADD_UTILITY(BOT_UTIL_SNIPE,true,0.91f); + ADD_UTILITY(BOT_UTIL_SNIPE,true,0.91f) } // low on health? Pick some up if there's any near by - ADD_UTILITY(BOT_UTIL_HL2DM_USE_HEALTH_CHARGER,(m_pHealthCharger.get() != NULL) && (CClassInterface::getAnimCycle(m_pHealthCharger)<1.0f) && (getHealthPercent()<1.0f),(1.0f-getHealthPercent())); - ADD_UTILITY(BOT_UTIL_FIND_NEAREST_HEALTH,(m_pHealthKit.get()!=NULL) && (getHealthPercent()<1.0f),1.0f-getHealthPercent()); + ADD_UTILITY(BOT_UTIL_HL2DM_USE_HEALTH_CHARGER, + (m_pHealthCharger.get() != nullptr) && CClassInterface::getAnimCycle(m_pHealthCharger)<1.0f && + getHealthPercent()<1.0f, 1.0f-getHealthPercent()) + ADD_UTILITY(BOT_UTIL_FIND_NEAREST_HEALTH,(m_pHealthKit.get()!=nullptr) && getHealthPercent()<1.0f,1.0f-getHealthPercent()) // low on armor? - ADD_UTILITY(BOT_UTIL_HL2DM_FIND_ARMOR,(m_pBattery.get() !=NULL) && (getArmorPercent()<1.0f),(1.0f-getArmorPercent())*0.75f); - ADD_UTILITY(BOT_UTIL_HL2DM_USE_CHARGER,(m_pCharger.get() !=NULL) && (CClassInterface::getAnimCycle(m_pCharger)<1.0f) && (getArmorPercent()<1.0f),(1.0f-getArmorPercent())*0.75f); - - ADD_UTILITY(BOT_UTIL_HL2DM_USE_CRATE,(m_pAmmoCrate.get()!=NULL) && (m_fUseCrateTime < engine->Time()),1.0f); + ADD_UTILITY(BOT_UTIL_HL2DM_FIND_ARMOR,(m_pBattery.get() !=nullptr) && getArmorPercent()<1.0f,(1.0f-getArmorPercent())*0.75f) + ADD_UTILITY(BOT_UTIL_HL2DM_USE_CHARGER, + (m_pCharger.get() !=nullptr) && CClassInterface::getAnimCycle(m_pCharger)<1.0f && getArmorPercent()<1.0f, + (1.0f-getArmorPercent())*0.75f) + + ADD_UTILITY(BOT_UTIL_HL2DM_USE_CRATE,(m_pAmmoCrate.get()!=nullptr) && m_fUseCrateTime < engine->Time(),1.0f) // low on ammo? ammo nearby? - ADD_UTILITY(BOT_UTIL_FIND_NEAREST_AMMO,(m_pAmmoKit.get() !=NULL) && (getAmmo(0)<5),0.01f*(100-getAmmo(0))); + ADD_UTILITY(BOT_UTIL_FIND_NEAREST_AMMO,(m_pAmmoKit.get() !=nullptr) && getAmmo(0)<5,0.01f*(100-getAmmo(0))) // always able to roam around - ADD_UTILITY(BOT_UTIL_ROAM,true,0.01f); + ADD_UTILITY(BOT_UTIL_ROAM,true,0.01f) // I have an enemy - ADD_UTILITY(BOT_UTIL_FIND_LAST_ENEMY,wantToFollowEnemy() && !m_bLookedForEnemyLast && m_pLastEnemy && CBotGlobals::entityIsValid(m_pLastEnemy) && CBotGlobals::entityIsAlive(m_pLastEnemy),getHealthPercent()*(getArmorPercent()+0.1)); + ADD_UTILITY(BOT_UTIL_FIND_LAST_ENEMY, + wantToFollowEnemy() && !m_bLookedForEnemyLast && m_pLastEnemy && CBotGlobals::entityIsValid(m_pLastEnemy + ) && CBotGlobals::entityIsAlive(m_pLastEnemy), getHealthPercent()*(getArmorPercent()+0.1f)) - if ( !hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && hasSomeConditions(CONDITION_SEE_LAST_ENEMY_POS) && m_pLastEnemy && m_fLastSeeEnemy && ((m_fLastSeeEnemy + 10.0) > engine->Time()) && m_pWeapons->hasWeapon(HL2DM_WEAPON_FRAG) ) + if (!hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && hasSomeConditions(CONDITION_SEE_LAST_ENEMY_POS) && m_pLastEnemy + && m_fLastSeeEnemy && m_fLastSeeEnemy + 10.0f > engine->Time() && m_pWeapons->hasWeapon(HL2DM_WEAPON_FRAG)) { - float fDistance = distanceFrom(m_vLastSeeEnemyBlastWaypoint); + const float fDistance = distanceFrom(m_vLastSeeEnemyBlastWaypoint); - if ( ( fDistance > BLAST_RADIUS ) && ( fDistance < 1500 ) ) + if ( fDistance > BLAST_RADIUS && fDistance < 1500 ) { - CWeapon *pWeapon = CWeapons::getWeapon(HL2DM_WEAPON_FRAG); - CBotWeapon *pBotWeapon = m_pWeapons->getWeapon(pWeapon); + const CWeapon *pWeapon = CWeapons::getWeapon(HL2DM_WEAPON_FRAG); + const CBotWeapon *pBotWeapon = m_pWeapons->getWeapon(pWeapon); - ADD_UTILITY(BOT_UTIL_THROW_GRENADE, pBotWeapon && (pBotWeapon->getAmmo(this) > 0) ,1.0f-(getHealthPercent()*0.2)); + ADD_UTILITY(BOT_UTIL_THROW_GRENADE, pBotWeapon && pBotWeapon->getAmmo(this) > 0,1.0f- getHealthPercent()*0.2f) } } if ( m_pNearbyWeapon.get() ) { + static CWeapon *pWeapon; pWeapon = CWeapons::getWeapon(m_pNearbyWeapon.get()->GetClassName()); if ( pWeapon && !m_pWeapons->hasWeapon(pWeapon->getID()) ) { - ADD_UTILITY(BOT_UTIL_PICKUP_WEAPON, true , 0.6f + pWeapon->getPreference()*0.1f); + ADD_UTILITY(BOT_UTIL_PICKUP_WEAPON, true , 0.6f + pWeapon->getPreference()*0.1f) } } utils.execute(); - while ( (next = utils.nextBest()) != NULL ) + while ( (next = utils.nextBest()) != nullptr) { if ( !m_pSchedules->isEmpty() && bCheckCurrent ) { @@ -541,16 +564,16 @@ void CHLDMBot :: getTasks (unsigned int iIgnore) void CHLDMBot :: modThink () { - m_fIdealMoveSpeed = CClassInterface::getMaxSpeed(m_pEdict); + m_fIdealMoveSpeed = m_fCachedNormSpeed; // update hitbox hull //m_pEdict->GetCollideable()->GetCollisionOrigin(); if ( !CBotGlobals::entityIsValid(m_NearestPhysObj) ) - m_NearestPhysObj = NULL; + m_NearestPhysObj = nullptr; if ( !CBotGlobals::entityIsValid(m_FailedPhysObj) ) - m_FailedPhysObj = NULL; + m_FailedPhysObj = nullptr; m_pCurrentWeapon = CClassInterface::getCurrentWeapon(m_pEdict); @@ -558,7 +581,7 @@ void CHLDMBot :: modThink () if ( m_pCurrentWeapon ) CClassInterface::getWeaponClip(m_pCurrentWeapon,&m_iClip1,&m_iClip2); - if ( CClassInterface::onLadder(m_pEdict) != NULL ) + if ( CClassInterface::onLadder(m_pEdict) != nullptr) { setMoveLookPriority(MOVELOOK_OVERRIDE); setLookAtTask(LOOK_WAYPOINT); @@ -566,22 +589,22 @@ void CHLDMBot :: modThink () setMoveLookPriority(MOVELOOK_MODTHINK); } - if ( (m_fCurrentDanger >= 20.0f) && (CClassInterface::auxPower(m_pEdict) > 90.f ) && (m_flSprintTime < engine->Time())) + if ( m_fCurrentDanger >= 20.0f && CClassInterface::auxPower(m_pEdict) > 90.0f && m_fSprintTime < engine->Time()) { m_pButtons->holdButton(IN_SPEED,0,1,0); } - else if (( m_fCurrentDanger < 1 ) || (CClassInterface::auxPower(m_pEdict) < 5.0f )) + else if (m_fCurrentDanger < 1 || CClassInterface::auxPower(m_pEdict) < 5.0f) { - m_flSprintTime = engine->Time() + randomFloat(5.0f,20.0f); + m_fSprintTime = engine->Time() + randomFloat(5.0f,20.0f); } - if ( m_fLastSeeEnemy && ((m_fLastSeeEnemy + 5.0)Time()) ) + if ( m_fLastSeeEnemy && m_fLastSeeEnemy + 5.0fTime() ) { - CBotWeapon *pWeapon = getCurrentWeapon(); + const CBotWeapon *pWeapon = getCurrentWeapon(); - if ( pWeapon && (pWeapon->getClip1(this)==0) && (pWeapon->getAmmo(this) > 0 ) ) + if ( pWeapon && pWeapon->getClip1(this)==0 && pWeapon->getAmmo(this) > 0 ) { - m_fLastSeeEnemy = 0; + m_fLastSeeEnemy = 0.0f; m_pButtons->tap(IN_RELOAD); } } @@ -591,20 +614,20 @@ void CHLDMBot :: modThink () bool bCarry = false; edict_t *pEntity = m_NearestPhysObj.get(); - if ( m_pCurrentWeapon && !strcmp("weapon_physcannon",m_pCurrentWeapon->GetClassName()) ) + if ( m_pCurrentWeapon && !std::strcmp("weapon_physcannon",m_pCurrentWeapon->GetClassName()) ) { m_pCarryingObject = CClassInterface::gravityGunObject(m_pCurrentWeapon); - bCarry = (CClassInterface::gravityGunObject(m_pCurrentWeapon) == m_NearestPhysObj.get()); + bCarry = CClassInterface::gravityGunObject(m_pCurrentWeapon) == m_NearestPhysObj.get(); } - if ( !bCarry && (distanceFrom(pEntity) < rcbot_jump_obst_dist.GetFloat()) ) + if ( !bCarry && distanceFrom(pEntity) < rcbot_jump_obst_dist.GetFloat() ) { bool bCanJump = false; float fTime = 0; if ( willCollide(pEntity,&bCanJump,&fTime) ) { - if ( bCanJump && (fTime < 1.5f) ) // one second to jump + if ( bCanJump && fTime < 1.5f ) // one second to jump { if ( randomInt(0,1) ) jump(); @@ -623,18 +646,19 @@ bool CHLDMBot::checkStuck() if ( m_pWeapons->hasWeapon(HL2DM_WEAPON_PHYSCANNON) ) {// check stuck on object - CBotWeapon *currentWeapon = getCurrentWeapon(); + /*const CBotWeapon* currentWeapon = getCurrentWeapon(); //Unstable? [APG]RoboCop[CL] - if ( ( currentWeapon->getID() == HL2DM_WEAPON_PHYSCANNON ) && ( m_pCarryingObject ) ) + if (currentWeapon->getID() == HL2DM_WEAPON_PHYSCANNON && m_pCarryingObject) { primaryAttack(); } - else if ( m_NearestPhysObj && (distanceFrom(m_NearestPhysObj)<100) ) + else */if ( m_NearestPhysObj && distanceFrom(m_NearestPhysObj)<100 ) { if ( !m_pSchedules->hasSchedule(SCHED_GRAVGUN_PICKUP) ) { m_pSchedules->freeMemory(); - CBotSchedule *pSched = new CBotSchedule(new CBotGravGunPickup(m_pCurrentWeapon,m_NearestPhysObj)); + CBotSchedule* const pSched = new CBotSchedule( + new CBotGravGunPickup(m_pCurrentWeapon, m_NearestPhysObj)); pSched->setID(SCHED_GRAVGUN_PICKUP); m_pSchedules->add(pSched); } @@ -645,18 +669,20 @@ bool CHLDMBot::checkStuck() return bStuck; } -bool CHLDMBot :: willCollide ( edict_t *pEntity, bool *bCanJump, float *fTime ) +bool CHLDMBot :: willCollide ( edict_t *pEntity, bool *bCanJump, float *fTime ) const { static Vector vel; - static Vector v_size; - static float fDistance; - static Vector vOrigin; - static float fSpeed; - static Vector v_dest; - static Vector v_min,v_max; if ( CClassInterface::getVelocity(m_pEdict,&vel) ) { + static Vector v_size; + static float fDistance; + static Vector vOrigin; + + static float fSpeed; + static Vector v_min; + static Vector v_max; + v_min = pEntity->GetCollideable()->OBBMins(); v_max = pEntity->GetCollideable()->OBBMaxs(); v_size = v_max - v_min; @@ -668,22 +694,22 @@ bool CHLDMBot :: willCollide ( edict_t *pEntity, bool *bCanJump, float *fTime ) // speed = dist/time --- time = dist/speed if ( fSpeed > 0 ) { + static Vector v_dest; *fTime = fDistance / fSpeed; vel = vel / fSpeed; // normalize - v_dest = getOrigin() + (vel*fDistance); + v_dest = getOrigin() + vel*fDistance; if ( v_size.z <= 48 ) // jump height *bCanJump = true; - return (vOrigin - v_dest).Length() < (v_size.Length()/2); + return (vOrigin - v_dest).Length() < v_size.Length()/2; } } return false; } - void CHLDMBot :: handleWeapons () { // @@ -693,92 +719,90 @@ void CHLDMBot :: handleWeapons () hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && wantToShoot() && isVisible(m_pEnemy) && isEnemy(m_pEnemy) ) { - CBotWeapon *pWeapon; - - pWeapon = getBestWeapon(m_pEnemy,true,true,(m_pEnemy==m_NearestBreakable)&&!rcbot_melee_only.GetBool()); + CBotWeapon* pWeapon = getBestWeapon(m_pEnemy, true, true, + m_pEnemy == m_NearestBreakable && !rcbot_melee_only.GetBool()); - if ( m_bWantToChangeWeapon && (pWeapon != NULL) && (pWeapon != getCurrentWeapon()) && pWeapon->getWeaponIndex() ) + if ( m_bWantToChangeWeapon && pWeapon != nullptr && pWeapon != getCurrentWeapon() && pWeapon->getWeaponIndex() ) { - //selectWeaponSlot(pWeapon->getWeaponInfo()->getSlot()); selectWeapon(pWeapon->getWeaponIndex()); } - setLookAtTask((LOOK_ENEMY)); + setLookAtTask(LOOK_ENEMY); ///battack = true; if ( !handleAttack ( pWeapon, m_pEnemy ) ) { - m_pEnemy = NULL; - m_pOldEnemy = NULL; + m_pEnemy = nullptr; + m_pOldEnemy = nullptr; wantToShoot(false); } } } + // update some edicts in my memory if I see them or not -bool CHLDMBot :: setVisible ( edict_t *pEntity, bool bVisible ) +bool CHLDMBot :: setVisible ( edict_t *pEntity, const bool bVisible ) { static float fDist; - const char *szClassname; - bool bValid = CBot::setVisible(pEntity,bVisible); + const bool bValid = CBot::setVisible(pEntity,bVisible); fDist = distanceFrom(pEntity); // if no draw effect it is invisible if ( bValid && bVisible && !(CClassInterface::getEffects(pEntity)&EF_NODRAW) ) { - szClassname = pEntity->GetClassName(); + const char* szClassname = pEntity->GetClassName(); - if ( ( strncmp(szClassname,"item_ammo",9)==0 ) && - ( !m_pAmmoKit.get() || (fDist0) && - ( !m_NearestBreakable.get() || (fDist0 && + ( !m_NearestBreakable.get() || fDistGetArmorValue()); } + float getArmorPercent() const { return (0.01f * m_pPlayerInfo->GetArmorValue()); } - bool setVisible ( edict_t *pEntity, bool bVisible ); + bool setVisible(edict_t* pEntity, bool bVisible) override; - virtual unsigned int maxEntityIndex ( ) { return gpGlobals->maxEntities; } + unsigned maxEntityIndex() override { return gpGlobals->maxEntities; } - void enemyLost (edict_t *pEnemy); + void enemyLost(edict_t* pEnemy) override; - inline void setFailedObject ( edict_t *pent ) - { - m_FailedPhysObj = pent; + void setFailedObject(edict_t* pent) + { + m_FailedPhysObj = pent; - if ( m_NearestPhysObj == pent ) - m_NearestPhysObj = NULL; + if (m_NearestPhysObj == pent) + m_NearestPhysObj = nullptr; } - bool checkStuck (); + bool checkStuck() override; - bool willCollide ( edict_t *pEntity, bool *bCanJump, float *fTime ); + bool willCollide(edict_t* pEntity, bool* bCanJump, float* fTime) const; - edict_t *getFailedObject () { return m_FailedPhysObj; } + edict_t* getFailedObject() const { return m_FailedPhysObj; } - virtual void touchedWpt ( CWaypoint *pWaypoint ); + void touchedWpt(CWaypoint* pWaypoint, int iNextWaypoint = -1, int iPrevWaypoint = -1) override; private: // blah blah MyEHandle m_NearestPhysObj; MyEHandle m_NearestBreakable; - edict_t *m_FailedPhysObj; - float m_flSprintTime; + edict_t* m_FailedPhysObj = nullptr; + float m_fSprintTime = 0.0f; MyEHandle m_pHealthCharger; MyEHandle m_pHealthKit; MyEHandle m_pAmmoKit; // nearest healthkit @@ -99,19 +99,20 @@ class CHLDMBot : public CBot MyEHandle m_pNearestButton; //MyEHandle m_pNearestBreakable; MyEHandle m_pAmmoCrate; - edict_t *m_pCurrentWeapon; + edict_t* m_pCurrentWeapon = nullptr; - float m_fUseButtonTime; - float m_fUseCrateTime; + float m_fUseButtonTime = 0.0f; + float m_fUseCrateTime = 0.0f; - CBaseHandle *m_Weapons; + CBaseHandle* m_Weapons = nullptr; - float m_fFixWeaponTime; + float m_fFixWeaponTime = 0.0f; - int m_iClip1; - int m_iClip2; + int m_iClip1 = 0; + int m_iClip2 = 0; - edict_t *m_pCarryingObject; // using grav gun + edict_t* m_pCarryingObject = nullptr; // using grav gun + float m_fCachedNormSpeed = 0.0f; // hl2_normspeed cvar value cache -caxanga334 }; #endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_hooks.cpp b/utils/RCBot2_meta/bot_hooks.cpp deleted file mode 100644 index b882e9dbb..000000000 --- a/utils/RCBot2_meta/bot_hooks.cpp +++ /dev/null @@ -1,353 +0,0 @@ - - -#include "filesystem.h" - -#ifdef __linux__ -#include "shake.h" //bir3yk -#endif -#include "enginecallback.h" - -#include "bot_const.h" -#include "bot.h" -#include "bot_fortress.h" -#include "bot_kv.h" -#include "bot_globals.h" -#include "bot_getprop.h" -#include "bot_weapons.h" -#include "bot_hooks.h" - -extern IServerGameEnts *servergameents; - -void *g_pVTable = NULL; -void *g_pVTable_Attributes = NULL; - -// needed to call the original playerruncommand function -void (CBaseEntity::*pPlayerRunCommand)(CUserCmd*, IMoveHelper*) = 0x0; -CBaseEntity* (CBaseEntity::*TF2GiveNamedItem)(char const*, int, CEconItemView*, bool) = 0x0; -CBaseEntity* (CBaseEntity::*TF2EquipWearable)(CBaseEntity*) = 0x0; - -//DWORD* pPlayerRunCommandHookedClass = 0; -DWORD* player_vtable = 0; - -// linux: Ted http://rcbot.bots-united.com/forums/index.php?showuser=2257 -// Needed to hook virtual tables and member functions -DWORD VirtualTableHook( DWORD* pdwNewInterface, int vtable, DWORD newInterface ) -{ - DWORD dwOld, dwStor = 0x0; -#ifndef __linux - VirtualProtect( &pdwNewInterface[vtable], 4, PAGE_EXECUTE_READWRITE, &dwOld ); -#else - // need page aligned address - char *addr = reinterpret_cast(reinterpret_cast(&pdwNewInterface[vtable]) - - reinterpret_cast(&pdwNewInterface[vtable]) - % sysconf(_SC_PAGE_SIZE)); - int len = sizeof(DWORD) + reinterpret_cast(&pdwNewInterface[vtable]) - % sysconf(_SC_PAGE_SIZE); - if (mprotect(addr, len, PROT_EXEC|PROT_READ|PROT_WRITE) == -1) { - Warning("In VirtualTableHook while calling mprotect for write access: %s.\n", - strerror(errno)); - } - else - { -#endif - dwStor = pdwNewInterface[vtable]; - *(DWORD*)&pdwNewInterface[vtable] = newInterface; -#ifndef __linux - VirtualProtect(&pdwNewInterface[vtable], 4, dwOld, &dwOld); -#else - if (mprotect(addr, len, PROT_EXEC|PROT_READ) == -1) - { - Warning("In VirtualTableHook while calling mprotect to remove write access: %s.\n", - strerror(errno)); - } - } -#endif - - return dwStor; -} - -// PlayerRunCommmand Hook -// Some Mods have their own puppet bots that run around and override RCBOT if this is not here -// this function overrides the puppet bots movements -#ifdef __linux__ -void FASTCALL nPlayerRunCommand( CBaseEntity *_this, CUserCmd* pCmd, IMoveHelper* pMoveHelper) -#else -void __fastcall nPlayerRunCommand( CBaseEntity *_this, void *unused, CUserCmd* pCmd, IMoveHelper* pMoveHelper) -#endif -{ - edict_t *pEdict = servergameents->BaseEntityToEdict(_this); - - static CBot *pBot; - - pBot = CBots::getBotPointer(pEdict); - - if ( pBot ) - { - static CBotCmd *cmd; - - cmd = pBot->getUserCMD(); - - // put the bot's commands into this move frame - pCmd->buttons = cmd->buttons; - pCmd->forwardmove = cmd->forwardmove; - pCmd->impulse = cmd->impulse; - pCmd->sidemove = cmd->sidemove; - pCmd->upmove = cmd->upmove; - pCmd->viewangles = cmd->viewangles; - pCmd->weaponselect = cmd->weaponselect; - pCmd->weaponsubtype = cmd->weaponsubtype; - pCmd->tick_count = cmd->tick_count; - pCmd->command_number = cmd->command_number; - } - //try - //{ - (*_this.*pPlayerRunCommand)(pCmd, pMoveHelper); - /*} - catch(...) - { - UnhookPlayerRunCommand(); - UnhookGiveNamedItem(); - Error("RCBOT: nPlayerRunCommand Failed. bad offset?"); - return; - }*/ -} - -#ifdef __linux__ -CBaseEntity * FASTCALL nTF2GiveNamedItem( CBaseEntity *_this, void *punused, const char *name, int subtype, CEconItemView *cscript, bool b ) -#else -CBaseEntity * __fastcall nTF2GiveNamedItem( CBaseEntity *_this, void *punused, const char *name, int subtype, CEconItemView *cscript, bool b ) -#endif -{ - const char *pszOverrideName = name; - edict_t *pEdict = servergameents->BaseEntityToEdict(_this); - CTF2Loadout *weap = NULL; - CBot *pBot = NULL; - CBaseEntity *pAdded = NULL; - extern ConVar rcbot_customloadouts; - extern ConVar rcbot_force_generation; - //CEconItemView newItem; - - if ( cscript && (g_pVTable == NULL) ) - { - g_pVTable = cscript->m_pVTable; - g_pVTable_Attributes = cscript->m_pVTable_Attributes; - } - - if ( rcbot_customloadouts.GetBool() && (cscript != NULL) && ((pBot=CBots::getBotPointer(pEdict)) != NULL) ) - { - int iclass = CClassInterface::getTF2Class(pEdict); - - // prevent any weird things from happening - // only change weapons if this class is the class I want to be and I just spawned - if ( pBot->isDesiredClass(iclass) && pBot->recentlySpawned(5.0f) ) - { - weap = CTeamFortress2Mod::findRandomWeaponLoadOut(iclass,name); - // this is an RC bot - if ( weap != NULL ) - { - weap->getScript(cscript); - - pszOverrideName = weap->m_pszClassname; - - if ( weap->m_Attributes.size() > 0 ) - { - if ( strcmp( pszOverrideName, "saxxy" ) ) - { - if ( b == false ) - b = rcbot_force_generation.GetBool(); - } - } - } - } - } - - //try - //{ - pAdded = (*_this.*TF2GiveNamedItem)(pszOverrideName,subtype,cscript,b); - //} - - /*catch ( ... ) - { - UnhookGiveNamedItem(); - UnhookPlayerRunCommand(); - Error("RCBOT: nTF2GiveNamedItem Failed. bad offset?"); - }*/ - - if ( pBot && cscript ) - ((CBotTF2*)pBot)->PostGiveNamedItem(pAdded,weap,cscript); - - return pAdded; - -} - -void UTIL_TF2EquipStockWeapon ( edict_t *pEdict, int islot, void *vTable, void *vTableAttributes ) -{ - int iClass = CClassInterface::getTF2Class(pEdict); - /* - switch ( iClass ) - { - - }*/ -} - -bool UTIL_TF2EquipHat ( edict_t *pEdict, CTF2Loadout *pHat, void *vTable, void *vTableAttributes ) -{ - extern ConVar rcbot_force_generation; - - CEconItemView script; - memset(&script,0,sizeof(CEconItemView)); - - if ( pHat && TF2GiveNamedItem && TF2EquipWearable ) - { - CBaseEntity *pEnt = servergameents->EdictToBaseEntity(pEdict); - - if ( pEnt ) - { - CBaseEntity *added = NULL; - - - script.m_pVTable = vTable; - script.m_pVTable_Attributes = vTableAttributes; - //pHat->applyAttributes(&script); - pHat->getScript(&script); - added = (*pEnt.*TF2GiveNamedItem)(pHat->m_pszClassname,0,&script,rcbot_force_generation.GetBool()); - - if ( added ) - { - (*pEnt.*TF2EquipWearable)(added); - - return true; - } - } - } - - return false; -} - -CTF2Loadout *UTIL_TF2EquipRandomHat ( edict_t *pEdict, void *vTable, void *vTableAttributes ) -{ - extern ConVar rcbot_force_generation; - CTF2Loadout *pHat = CTeamFortress2Mod::getRandomHat(); - - if ( UTIL_TF2EquipHat(pEdict,pHat,vTable,vTableAttributes) ) - { - return pHat; - } - - return NULL; -} - -void HookGiveNamedItem ( edict_t *edict ) -{ - extern ConVar rcbot_givenameditem_offset; - extern ConVar rcbot_equipwearable_offset; - CBaseEntity *BasePlayer = servergameents->EdictToBaseEntity(edict);//(CBaseEntity *)(edict->GetUnknown()->GetBaseEntity()); - - if((TF2GiveNamedItem == 0x0) && BasePlayer && CBotGlobals::isCurrentMod(MOD_TF2) ) - { - int vtable = rcbot_givenameditem_offset.GetInt(); - - DWORD *mem = ( DWORD* )*( DWORD* )BasePlayer; - int offset = rcbot_equipwearable_offset.GetInt(); - *(DWORD*)&TF2EquipWearable = mem[offset]; - - if ( vtable != 0 ) - { - // hook it - if ( player_vtable == NULL ) - player_vtable = ( DWORD* )*( DWORD* )BasePlayer; - - *(DWORD*)&TF2GiveNamedItem = VirtualTableHook( player_vtable, vtable, ( DWORD )nTF2GiveNamedItem ); - - } - } - -} - -void UnhookGiveNamedItem () -{ - extern ConVar rcbot_givenameditem_offset; - - if ( TF2GiveNamedItem && player_vtable ) - { - int vtable = rcbot_givenameditem_offset.GetInt(); - - if ( vtable != 0 ) - { - /* linux and windows offsets are now separate in hooksinfo.ini - #ifndef WIN32 - ++vtable; - #endif - */ - VirtualTableHook( player_vtable, vtable, *(DWORD*)&TF2GiveNamedItem ); - TF2GiveNamedItem = 0x0; - //GiveNamedItemHookedClass = 0x0; - } - } -} - -//---------------------------------- -// begin hook -void HookPlayerRunCommand ( edict_t *edict ) -{ - extern ConVar rcbot_runplayercmd_dods; - extern ConVar rcbot_runplayercmd_tf2; - - if ( CBots::controlBots() ) //rcbot_override.GetBool() ) - { - CBaseEntity *BasePlayer = (CBaseEntity *)(edict->GetUnknown()->GetBaseEntity()); - - if(BasePlayer) - { - int vtable = 0; - - if ( CBotGlobals::isCurrentMod(MOD_DOD) ) - vtable = rcbot_runplayercmd_dods.GetInt(); - else - vtable = rcbot_runplayercmd_tf2.GetInt(); - - if ( vtable != 0 ) - { - /* - #ifndef WIN32 - ++vtable; - #endif*/ - // hook it - if ( pPlayerRunCommand == 0x0 ) - { - player_vtable = ( DWORD* )*( DWORD* )BasePlayer; - *(DWORD*)&pPlayerRunCommand = VirtualTableHook( player_vtable, vtable, ( DWORD )nPlayerRunCommand ); - } - } - } - } -} - -// end hook -void UnhookPlayerRunCommand () -{ - extern ConVar rcbot_runplayercmd_dods; - extern ConVar rcbot_runplayercmd_tf2; - - if ( pPlayerRunCommand && player_vtable ) - { - int vtable = 0; - - if ( CBotGlobals::isCurrentMod(MOD_DOD) ) - vtable = rcbot_runplayercmd_dods.GetInt(); - else - vtable = rcbot_runplayercmd_tf2.GetInt(); - - if ( vtable != 0 ) - { - /* - #ifndef WIN32 - ++vtable; - #endif - */ - VirtualTableHook( player_vtable, vtable, *(DWORD*)&pPlayerRunCommand ); - //pPlayerRunCommandHookedClass = NULL; - pPlayerRunCommand = NULL; - } - } -} diff --git a/utils/RCBot2_meta/bot_hooks.h b/utils/RCBot2_meta/bot_hooks.h deleted file mode 100644 index 2816b215e..000000000 --- a/utils/RCBot2_meta/bot_hooks.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef __BOT_HOOKS_H__ -#define __BOT_HOOKS_H__ - -#ifdef WIN32 -#include -#else -#include -#include -#include -#endif - -#ifdef GetClassName -#undef GetClassName -#endif - -DWORD VirtualTableHook( DWORD* pdwNewInterface, int vtable, DWORD newInterface ); - -extern DWORD* player_vtable; -extern void (CBaseEntity::*pPlayerRunCommand)(CUserCmd*, IMoveHelper*); -extern CBaseEntity* (CBaseEntity::*TF2GiveNamedItem)(char const*, int, CEconItemView*, bool); -extern CBaseEntity* (CBaseEntity::*TF2EquipWearable)(CBaseEntity*); -// PlayerRunCommmand Hook -// Some Mods have their own puppet bots that run around and override RCBOT if this is not here -// this function overrides the puppet bots movements -#ifdef __linux__ -void FASTCALL nPlayerRunCommand( CBaseEntity *_this, CUserCmd* pCmd, IMoveHelper* pMoveHelper); -#else -void __fastcall nPlayerRunCommand( CBaseEntity *_this, void *unused, CUserCmd* pCmd, IMoveHelper* pMoveHelper); -#endif - -#ifdef __linux__ -CBaseEntity * FASTCALL nTF2GiveNamedItem( CBaseEntity *_this, void *punused, const char *name, int subtype, CEconItemView *cscript, bool b ); -#else -CBaseEntity * __fastcall nTF2GiveNamedItem( CBaseEntity *_this, void *punused, const char *name, int subtype, CEconItemView *cscript, bool b ); -#endif - -bool UTIL_TF2EquipHat ( edict_t *pEdict, CTF2Loadout *pHat, void *vTable, void *vTableAttributes ); -CTF2Loadout *UTIL_TF2EquipRandomHat ( edict_t *pEdict, void *vTable, void *vTableAttributes ); - -void HookGiveNamedItem ( edict_t *edict ); - -void UnhookGiveNamedItem (); - -//---------------------------------- -// begin hook -void HookPlayerRunCommand ( edict_t *edict ); -// end hook -void UnhookPlayerRunCommand (); - -#endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_kv.cpp b/utils/RCBot2_meta/bot_kv.cpp index edf91b06a..6e5860087 100644 --- a/utils/RCBot2_meta/bot_kv.cpp +++ b/utils/RCBot2_meta/bot_kv.cpp @@ -1,141 +1,113 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com #include "bot.h" #include "bot_kv.h" #include "bot_globals.h" -void CRCBotKeyValueList :: parseFile ( FILE *fp ) -{ - char buffer[2*(RCBOT_MAX_KV_LEN)]; - char szKey[RCBOT_MAX_KV_LEN]; - char szValue[RCBOT_MAX_KV_LEN]; +#include +#include +#include - int iKi; - int iVi; - int iLen; - int iCi; // current character index - bool bHaveKey; - int iLine; +#include "rcbot/logging.h" - iLine = 0; +void CRCBotKeyValueList::parseFile(std::fstream& fp) +{ + std::string line; + std::size_t iLine = 0; // parse profile ini - while ( fgets(buffer,255,fp) != NULL ) + while (std::getline(fp, line)) { iLine++; - if ( buffer[0] == '#' ) // skip comment - continue; - - iLen = strlen(buffer); + // remove carriage return if present + if (!line.empty() && line.back() == '\r') + { + line.pop_back(); + } - if ( iLen == 0 ) + if (line.empty() || line[0] == '#') // skip empty lines and comments continue; - if ( buffer[iLen-1] == '\n' ) - buffer[--iLen] = 0; - - if ( buffer[iLen-1] == '\r' ) - buffer[--iLen] = 0; - - bHaveKey = false; - - iKi = 0; - iVi = 0; + std::string key, value; + bool bHaveKey = false; - for ( iCi = 0; iCi < iLen; iCi ++ ) + for (const char c : line) { - // ignore spacing - if ( buffer[iCi] == ' ' ) + if (c == ' ') // ignore spacing continue; - if ( !bHaveKey ) + if (!bHaveKey) { - if ( buffer[iCi] == '=' ) + if (c == '=') { bHaveKey = true; - continue; } - - // parse key - - if ( iKi < RCBOT_MAX_KV_LEN ) - szKey[iKi++] = buffer[iCi]; + else + { + key += c; + } } - else if ( iVi < RCBOT_MAX_KV_LEN ) - szValue[iVi++] = buffer[iCi]; else - break; - } - - szKey[iKi] = 0; - szValue[iVi] = 0; - - CBotGlobals::botMessage(NULL,0,"m_KVs.push_back(%s,%s)",szKey, szValue); - - m_KVs.push_back(new CRCBotKeyValue(szKey,szValue)); + { + value += c; + } + } - } + if (key.length() >= RCBOT_MAX_KV_LEN || value.length() >= RCBOT_MAX_KV_LEN) + { + logger->Log(LogLevel::WARN, "Key or value too long on line %zu in KV file.", iLine); + continue; + } -} + logger->Log(LogLevel::TRACE, "m_KVs.emplace_back(%s,%s)", key.c_str(), value.c_str()); -CRCBotKeyValueList :: ~CRCBotKeyValueList() -{ - for ( unsigned int i = 0; i < m_KVs.size(); i ++ ) - { - delete m_KVs[i]; - m_KVs[i] = NULL; + m_KVs.emplace_back(std::make_unique(key.c_str(), value.c_str())); } - - m_KVs.clear(); } -CRCBotKeyValue *CRCBotKeyValueList :: getKV ( const char *key ) +CRCBotKeyValue* CRCBotKeyValueList::getKV(const char* key) const { - for ( unsigned int i = 0; i < m_KVs.size(); i ++ ) + for (const std::unique_ptr& m_KV : m_KVs) { - if ( FStrEq(m_KVs[i]->getKey(),key) ) - return m_KVs[i]; + if (FStrEq(m_KV->getKey(), key)) + return m_KV.get(); } - return NULL; + return nullptr; } -bool CRCBotKeyValueList :: getFloat ( const char *key, float *val ) +bool CRCBotKeyValueList::getFloat(const char* key, float* val) const { - CRCBotKeyValue *pKV; + const CRCBotKeyValue* pKV = getKV(key); - pKV = getKV(key); - - if ( !pKV ) + if (!pKV) return false; - - *val = atof(pKV->getValue()); + + *val = static_cast(std::atof(pKV->getValue())); return true; } - -bool CRCBotKeyValueList :: getInt ( const char *key, int *val ) -{ - CRCBotKeyValue *pKV; - pKV = getKV(key); +bool CRCBotKeyValueList::getInt(const char* key, int* val) const +{ + const CRCBotKeyValue* pKV = getKV(key); - if ( !pKV ) + if (!pKV) return false; - - *val = atoi(pKV->getValue()); + + *val = std::atoi(pKV->getValue()); return true; } -bool CRCBotKeyValueList :: getString ( const char *key, char **val ) +bool CRCBotKeyValueList::getString(const char* key, const char** val) const { - CRCBotKeyValue *pKV; - - pKV = getKV(key); + const CRCBotKeyValue* pKV = getKV(key); - if ( !pKV ) + if (!pKV) return false; *val = pKV->getValue(); @@ -143,10 +115,11 @@ bool CRCBotKeyValueList :: getString ( const char *key, char **val ) return true; } -CRCBotKeyValue :: CRCBotKeyValue (const char *szKey, char *szValue ) +CRCBotKeyValue::CRCBotKeyValue(const char* szKey, const char* szValue) { - strncpy(m_szKey,szKey,RCBOT_MAX_KV_LEN-1); - m_szKey[RCBOT_MAX_KV_LEN-1] = 0; - strncpy(m_szValue,szValue,RCBOT_MAX_KV_LEN-1); - m_szValue[RCBOT_MAX_KV_LEN-1] = 0; + std::strncpy(m_szKey, szKey, RCBOT_MAX_KV_LEN - 1); + m_szKey[RCBOT_MAX_KV_LEN - 1] = 0; + + std::strncpy(m_szValue, szValue, RCBOT_MAX_KV_LEN - 1); + m_szValue[RCBOT_MAX_KV_LEN - 1] = 0; } \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_kv.h b/utils/RCBot2_meta/bot_kv.h index 27492ff6c..567fc762c 100644 --- a/utils/RCBot2_meta/bot_kv.h +++ b/utils/RCBot2_meta/bot_kv.h @@ -1,26 +1,19 @@ #ifndef __RCBOT_KEY_VAL__ #define __RCBOT_KEY_VAL__ -#define RCBOT_MAX_KV_LEN 256 - #include -using namespace std; +#include +#include + +constexpr int RCBOT_MAX_KV_LEN = 128; //Was 256 [APG]RoboCop[CL] class CRCBotKeyValue { public: - CRCBotKeyValue(const char *szKey, char *szValue); - - char *getKey () - { - return m_szKey; - } - - char *getValue () - { - return m_szValue; - } + CRCBotKeyValue(const char* szKey, const char* szValue); + const char* getKey() const { return m_szKey; } + const char* getValue() const { return m_szValue; } private: char m_szKey[RCBOT_MAX_KV_LEN]; char m_szValue[RCBOT_MAX_KV_LEN]; @@ -29,25 +22,17 @@ class CRCBotKeyValue class CRCBotKeyValueList { public: - ~CRCBotKeyValueList(); - - void parseFile ( FILE *fp ); + ~CRCBotKeyValueList() = default; - //unsigned int size (); + void parseFile(std::fstream& fp); - //CRCBotKeyValue *getKV ( unsigned int iIndex ); - - bool getInt ( const char *key, int *val ); - - bool getString ( const char *key, char **val ); - - bool getFloat ( const char *key, float *val ); + CRCBotKeyValue* getKV(const char* key) const; + bool getFloat(const char* key, float* val) const; + bool getInt(const char* key, int* val) const; + bool getString(const char* key, const char** val) const; private: - - CRCBotKeyValue *getKV ( const char *key ); - - vector m_KVs; + std::vector> m_KVs; }; #endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_menu.cpp b/utils/RCBot2_meta/bot_menu.cpp index c3e9afb8e..db9879b31 100644 --- a/utils/RCBot2_meta/bot_menu.cpp +++ b/utils/RCBot2_meta/bot_menu.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * part of https://rcbot2.svn.sourceforge.net/svnroot/rcbot2 * @@ -31,74 +33,77 @@ * */ #include "engine_wrappers.h" - #include "ndebugoverlay.h" +#include "bot_cvars.h" #include "bot_waypoint.h" #include "bot_menu.h" #include "bot_wpt_color.h" #include "bot_globals.h" #include "bot_client.h" -extern IVDebugOverlay *debugoverlay; +#include +#include + +extern IVDebugOverlay* debugoverlay; -CBotMenu *CBotMenuList :: m_MenuList[BOT_MENU_MAX]; +CBotMenu* CBotMenuList::m_MenuList[BOT_MENU_MAX]; -void CWaypointFlagMenuItem :: activate ( CClient *pClient ) +void CWaypointFlagMenuItem::activate(CClient* pClient) { - int iWpt = pClient->currentWaypoint(); - CWaypoint *pWpt = CWaypoints::getWaypoint(iWpt); - CWaypointType *type = CWaypointTypes::getTypeByIndex(m_iFlag); + const int iWpt = pClient->currentWaypoint(); + CWaypoint* pWpt = CWaypoints::getWaypoint(iWpt); + const CWaypointType* type = CWaypointTypes::getTypeByIndex(m_iFlag); - if ( pWpt ) + if (pWpt) { - if ( pWpt->hasFlag(type->getBits()) ) + if (pWpt->hasFlag(type->getBits())) pWpt->removeFlag(type->getBits()); else pWpt->addFlag(type->getBits()); } } -const char *CWaypointFlagMenu :: getCaption(CClient *pClient,WptColor &color ) +const char* CWaypointFlagMenu::getCaption(CClient* pClient, WptColor& color) { pClient->updateCurrentWaypoint(); - int iWpt = pClient->currentWaypoint(); - CWaypoint *pWpt = CWaypoints::getWaypoint(iWpt); + const int iWpt = pClient->currentWaypoint(); - if ( pWpt ) + if (const CWaypoint* pWpt = CWaypoints::getWaypoint(iWpt)) { color = CWaypointTypes::getColour(pWpt->getFlags()); - sprintf(m_szCaption,"Waypoint Flags ID = [%d]",iWpt); + snprintf(m_szCaption, sizeof(m_szCaption), "Waypoint Flags ID = [%d]", iWpt); } else { color = WptColor::white; - sprintf(m_szCaption,"No Waypoint"); + snprintf(m_szCaption, sizeof(m_szCaption), "No Waypoint"); } return m_szCaption; } -const char *CWaypointFlagMenuItem :: getCaption ( CClient *pClient, WptColor &color ) +const char* CWaypointFlagMenuItem::getCaption(CClient* pClient, WptColor& color) { pClient->updateCurrentWaypoint(); - int iWpt = pClient->currentWaypoint(); - CWaypoint * pWpt = CWaypoints::getWaypoint(iWpt); + const int iWpt = pClient->currentWaypoint(); + const CWaypoint* pWpt = CWaypoints::getWaypoint(iWpt); - CWaypointType *type = CWaypointTypes::getTypeByIndex(m_iFlag); + const CWaypointType* type = CWaypointTypes::getTypeByIndex(m_iFlag); color = type->getColour(); - sprintf(m_szCaption,"[%s] %s",(pWpt!=NULL)?(pWpt->hasFlag(type->getBits())?"x":" "):"No Waypoint",type->getName()); + snprintf(m_szCaption, sizeof(m_szCaption), "[%s] %s", pWpt != nullptr ? + (pWpt->hasFlag(type->getBits()) ? "x" : " ") : "No Waypoint", type->getName()); return m_szCaption; } -CWaypointFlagMenu :: CWaypointFlagMenu ( CBotMenu *pPrev ) +CWaypointFlagMenu::CWaypointFlagMenu(CBotMenu* pPrev) { - int iMod = CBotGlobals::getCurrentMod()->getModId(); + const int iMod = CBotGlobals::getCurrentMod()->getModId(); // check the number of waypoint types available // caption // 1. @@ -111,281 +116,259 @@ CWaypointFlagMenu :: CWaypointFlagMenu ( CBotMenu *pPrev ) // 8. More... // 9. Go Back - int iNumTypes = CWaypointTypes::getNumTypes(); + const std::size_t iNumTypes = CWaypointTypes::getNumTypes(); - int iNumAdded = 0; - CBotMenu *pParent; - CBotMenu *pCurrent; + std::size_t iNumAdded = 0; - int i; + CBotMenu* pCurrent = this; + CBotMenu* pParent = pPrev; - pCurrent = this; - pParent = pPrev; - - for ( i = 0; i < iNumTypes; i ++ ) + for (std::size_t i = 0; i < iNumTypes; i++) { - if ( !CWaypointTypes::getTypeByIndex(i)->forMod(iMod) ) + if (!CWaypointTypes::getTypeByIndex(i)->forMod(iMod)) continue; - pCurrent->addMenuItem(new CWaypointFlagMenuItem(i)); + pCurrent->addMenuItem(new CWaypointFlagMenuItem(static_cast(i))); iNumAdded++; - if ( (iNumAdded > 7) || (i == (iNumTypes-1)) ) + if (iNumAdded > 7 || i == iNumTypes - 1) { - CBotMenuItem *back = new CBotGotoMenuItem("Back...",pParent); + CBotMenuItem* back = new CBotGotoMenuItem("Back...", pParent); pParent = pCurrent; - if ( (iNumAdded > 7) && (i < (iNumTypes-1)) ) + if (iNumAdded > 7 && i < iNumTypes - 1) { pCurrent = new CBotMenu(); pCurrent->setCaption("Waypoint Flags (More)"); - pParent->addMenuItem(new CBotGotoMenuItem("More...",pCurrent)); + pParent->addMenuItem(new CBotGotoMenuItem("More...", pCurrent)); } pParent->addMenuItem(back); - // make a new menu + //make a new menu iNumAdded = 0; // reset - } } - } -void CBotMenuList :: setupMenus () +void CBotMenuList::setupMenus() { - m_MenuList[BOT_MENU_WPT] = new CWaypointMenu(); //new CWaypointFlagMenu(NULL); + m_MenuList[BOT_MENU_WPT] = new CWaypointMenu(); } -const char *CWaypointRadiusMenu :: getCaption ( CClient *pClient, WptColor &color ) +const char* CWaypointRadiusMenu::getCaption(CClient* pClient, WptColor& color) { - int iWpt = pClient->currentWaypoint(); - CWaypoint *pWpt = CWaypoints::getWaypoint(iWpt); - float fRadius = 0; + const int iWpt = pClient->currentWaypoint(); + const CWaypoint* pWpt = CWaypoints::getWaypoint(iWpt); + float fRadius = 0.0f; - if ( pWpt ) + if (pWpt) { fRadius = pWpt->getRadius(); } - sprintf(m_szCaption,"Waypoint Radius (%0.1f)",fRadius); + snprintf(m_szCaption, sizeof(m_szCaption), "Waypoint Radius (%0.1f)", fRadius); color = WptColor::white; return m_szCaption; } -const char *CWaypointAreaMenu :: getCaption ( CClient *pClient, WptColor &color ) +const char* CWaypointAreaMenu::getCaption(CClient* pClient, WptColor& color) { - int iWpt = pClient->currentWaypoint(); - CWaypoint *pWpt = CWaypoints::getWaypoint(iWpt); + const int iWpt = pClient->currentWaypoint(); + const CWaypoint* pWpt = CWaypoints::getWaypoint(iWpt); int iArea = 0; - if ( pWpt ) + if (pWpt) { iArea = pWpt->getArea(); } - sprintf(m_szCaption,"Waypoint Area (%d)",iArea); + snprintf(m_szCaption, sizeof(m_szCaption), "Waypoint Area (%d)", iArea); color = WptColor::white; return m_szCaption; } -const char *CWaypointMenu::getCaption(CClient *pClient,WptColor &color ) +const char* CWaypointMenu::getCaption(CClient* pClient, WptColor& color) { - int iWpt = pClient->currentWaypoint(); - - if ( iWpt == -1 ) - sprintf(m_szCaption,"Waypoint Menu - No waypoint - Walk towards a waypoint"); + const int iWpt = pClient->currentWaypoint(); + + if (iWpt == -1) + snprintf(m_szCaption, sizeof(m_szCaption), "Waypoint Menu - No waypoint - Walk towards a waypoint"); else - sprintf(m_szCaption,"Waypoint Menu [%d]",iWpt); + snprintf(m_szCaption, sizeof(m_szCaption), "Waypoint Menu [%d]", iWpt); color = WptColor::white; return m_szCaption; } -const char *CWaypointYawMenuItem :: getCaption ( CClient *pClient, WptColor &color ) +const char* CWaypointYawMenuItem::getCaption(CClient* pClient, WptColor& color) { - CWaypoint *pWpt = CWaypoints::getWaypoint(pClient->currentWaypoint()); - - if ( pWpt ) - sprintf(m_szCaption,"Yaw = %d degrees (press to update)",(int)pWpt->getAimYaw()); + if (const CWaypoint* pWpt = CWaypoints::getWaypoint(pClient->currentWaypoint())) + snprintf(m_szCaption, sizeof(m_szCaption), "Yaw = %d degrees (press to update)", static_cast(pWpt->getAimYaw())); else - sprintf(m_szCaption,"No Waypoint"); + snprintf(m_szCaption, sizeof(m_szCaption), "No Waypoint"); return m_szCaption; } -void CWaypointYawMenuItem :: activate ( CClient *pClient ) +void CWaypointYawMenuItem::activate(CClient* pClient) { - CWaypoint *pWpt = CWaypoints::getWaypoint(pClient->currentWaypoint()); - - if ( pWpt ) + if (CWaypoint* pWpt = CWaypoints::getWaypoint(pClient->currentWaypoint())) pWpt->setAim(CBotGlobals::playerAngles(pClient->getPlayer()).y); } -void CWaypointAreaIncrease :: activate ( CClient *pClient ) +void CWaypointAreaIncrease::activate(CClient* pClient) { - int iWpt = pClient->currentWaypoint(); - CWaypoint *pWpt = CWaypoints::getWaypoint(iWpt); + const int iWpt = pClient->currentWaypoint(); - if ( pWpt ) + if (CWaypoint* pWpt = CWaypoints::getWaypoint(iWpt)) { - pWpt->setArea(pWpt->getArea()+1); + pWpt->setArea(pWpt->getArea() + 1); } } -void CWaypointAreaDecrease :: activate ( CClient *pClient ) +void CWaypointAreaDecrease::activate(CClient* pClient) { - int iWpt = pClient->currentWaypoint(); - CWaypoint *pWpt = CWaypoints::getWaypoint(iWpt); + const int iWpt = pClient->currentWaypoint(); - if ( pWpt ) + if (CWaypoint* pWpt = CWaypoints::getWaypoint(iWpt)) { - pWpt->setArea(pWpt->getArea()-1); + pWpt->setArea(pWpt->getArea() - 1); } } -void CWaypointRadiusIncrease :: activate ( CClient *pClient ) +void CWaypointRadiusIncrease::activate(CClient* pClient) { - int iWpt = pClient->currentWaypoint(); - CWaypoint *pWpt = CWaypoints::getWaypoint(iWpt); + const int iWpt = pClient->currentWaypoint(); - if ( pWpt ) + if (CWaypoint* pWpt = CWaypoints::getWaypoint(iWpt)) { - float fRadius = pWpt->getRadius(); + const float fRadius = pWpt->getRadius(); - if ( fRadius < 200.0f ) - pWpt->setRadius(fRadius+32.0f); + if (fRadius < 200.0f) + pWpt->setRadius(fRadius + 32.0f); else pWpt->setRadius(200.0f); } } -void CWaypointRadiusDecrease :: activate ( CClient *pClient ) +void CWaypointRadiusDecrease::activate(CClient* pClient) { - int iWpt = pClient->currentWaypoint(); - CWaypoint *pWpt = CWaypoints::getWaypoint(iWpt); + const int iWpt = pClient->currentWaypoint(); - if ( pWpt ) + if (CWaypoint* pWpt = CWaypoints::getWaypoint(iWpt)) { - float fRadius = pWpt->getRadius(); - - if ( fRadius > 32.0f ) - pWpt->setRadius(fRadius-32.0f); + if (const float fRadius = pWpt->getRadius(); fRadius > 32.0f) + pWpt->setRadius(fRadius - 32.0f); else pWpt->setRadius(0.0f); } } - -const char *CWaypointCutMenuItem :: getCaption ( CClient *pClient, WptColor &color ) +const char* CWaypointCutMenuItem::getCaption(CClient* pClient, WptColor& color) { - sprintf(m_szCaption,"Cut Waypoint"); + snprintf(m_szCaption, sizeof(m_szCaption), "Cut Waypoint"); color = WptColor::white; return m_szCaption; } -void CWaypointCutMenuItem :: activate ( CClient *pClient ) +void CWaypointCutMenuItem::activate(CClient* pClient) { pClient->updateCurrentWaypoint(); - CWaypoint *pwpt = CWaypoints::getWaypoint(pClient->currentWaypoint()); - - if ( pwpt ) + if (const CWaypoint* pWpt = CWaypoints::getWaypoint(pClient->currentWaypoint())) { - pClient->setWaypointCut(pwpt); + pClient->setWaypointCut(pWpt); CWaypoints::deleteWaypoint(pClient->currentWaypoint()); } } -const char *CWaypointCopyMenuItem :: getCaption ( CClient *pClient, WptColor &color ) +const char* CWaypointCopyMenuItem::getCaption(CClient* pClient, WptColor& color) { - sprintf(m_szCaption,"Copy Waypoint"); + snprintf(m_szCaption, sizeof(m_szCaption), "Copy Waypoint"); color = WptColor::white; return m_szCaption; } -void CWaypointCopyMenuItem :: activate ( CClient *pClient ) +void CWaypointCopyMenuItem::activate(CClient* pClient) { - pClient->updateCurrentWaypoint(); - - CWaypoint *pwpt = CWaypoints::getWaypoint(pClient->currentWaypoint()); + pClient->updateCurrentWaypoint(); - if ( pwpt ) - { - pClient->setWaypointCopy(pwpt); - } + if (const CWaypoint* pWpt = CWaypoints::getWaypoint(pClient->currentWaypoint())) + { + pClient->setWaypointCopy(pWpt); + } } -const char *CWaypointPasteMenuItem :: getCaption ( CClient *pClient, WptColor &color ) +const char* CWaypointPasteMenuItem::getCaption(CClient* pClient, WptColor& color) { - sprintf(m_szCaption,"Paste Waypoint"); + snprintf(m_szCaption, sizeof(m_szCaption), "Paste Waypoint"); color = WptColor::white; return m_szCaption; } -void CWaypointPasteMenuItem :: activate ( CClient *pClient ) +void CWaypointPasteMenuItem::activate(CClient* pClient) { - CWaypoints::addWaypoint(pClient,NULL,NULL,NULL,NULL,true); + CWaypoints::addWaypoint(pClient, nullptr, nullptr, nullptr, nullptr, true); } -void CBotMenu ::render (CClient *pClient) +void CBotMenu::render(CClient* pClient) { - CBotMenuItem *item; WptColor color; - unsigned int i; - Vector vOrigin; Vector vForward; - Vector vRight; - QAngle angles; - const char *pszCaption; - IPlayerInfo *pPlayerInfo = playerinfomanager->GetPlayerInfo(pClient->getPlayer()); - CBotCmd lastCmd = pPlayerInfo->GetLastUserCommand(); - extern ConVar rcbot_menu_update_time1; - float fUpdateTime = rcbot_menu_update_time1.GetFloat(); + IPlayerInfo* pPlayerInfo = playerinfomanager->GetPlayerInfo(pClient->getPlayer()); + const CBotCmd lastCmd = pPlayerInfo->GetLastUserCommand(); + const float fUpdateTime = rcbot_menu_update_time1.GetFloat(); - angles = lastCmd.viewangles; + const QAngle angles = lastCmd.viewangles; - vOrigin = pPlayerInfo->GetAbsOrigin(); + Vector vOrigin = pPlayerInfo->GetAbsOrigin(); - AngleVectors(angles,&vForward); + AngleVectors(angles, &vForward); vForward = vForward / vForward.Length(); - vRight = vForward.Cross(Vector(0,0,1)); + const Vector vRight = vForward.Cross(Vector(0, 0, 1)); - vOrigin = vOrigin + (vForward * 100) - (vRight * 100); + vOrigin = vOrigin + vForward * 100 - vRight * 100; vOrigin.z += 72.0f; - pszCaption = getCaption(pClient,color); + const char* pszCaption = getCaption(pClient, color); - debugoverlay->AddTextOverlayRGB(vOrigin,0,fUpdateTime,color.r,color.g,color.b,color.a,pszCaption); - debugoverlay->AddTextOverlayRGB(vOrigin,1,fUpdateTime,color.r,color.g,color.b,color.a,"----------------"); -/* - Vector screen; - Vector point = Vector(0,0,0); + //TODO: to allow waypoint menu work for the newer SDK2013 for CSS, DODS, HL2DM and TF2 [APG]RoboCop[CL] +//#if SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_HL2DM +// debugoverlay->AddScreenTextOverlay(0.135f, 0.4f, 0, fUpdateTime, color.r, color.g, color.b, color.a, pszCaption); +// debugoverlay->AddScreenTextOverlay(0.135f, 0.4f, 1, fUpdateTime, color.r, color.g, color.b, color.a, "----------------"); +//#else + debugoverlay->AddTextOverlayRGB(vOrigin, 0, fUpdateTime, color.r, color.g, color.b, color.a, pszCaption); + debugoverlay->AddTextOverlayRGB(vOrigin, 1, fUpdateTime, color.r, color.g, color.b, color.a, "----------------"); +//#endif + /* + Vector screen; + Vector point = Vector(0,0,0); - debugoverlay->ScreenPosition(0.5f, 0.5f, screen); - debugoverlay->ScreenPosition(point,screen);*/ + debugoverlay->ScreenPosition(0.5f, 0.5f, screen); + debugoverlay->ScreenPosition(point,screen);*/ - for ( i = 0; i < m_MenuItems.size(); i ++ ) + for (int i = 0; i < static_cast(m_MenuItems.size()); i++) { - item = m_MenuItems[i]; + CBotMenuItem* item = m_MenuItems[i]; - pszCaption = item->getCaption(pClient,color); + pszCaption = item->getCaption(pClient, color); - debugoverlay->AddTextOverlayRGB(vOrigin,i+2,fUpdateTime,color.r,color.g,color.b,color.a,"%d. %s",(i==9)?(0):(i+1),pszCaption); + debugoverlay->AddTextOverlayRGB(vOrigin, i + 2, fUpdateTime, color.r, color.g, color.b, color.a, "%d. %s", i == 9 ? 0 : i + 1, pszCaption); } } -const char *CBotMenuItem :: getCaption ( CClient *pClient, WptColor &color ) +const char* CBotMenuItem::getCaption(CClient* pClient, WptColor& color) { color.r = 255; color.g = 255; @@ -395,35 +378,41 @@ const char *CBotMenuItem :: getCaption ( CClient *pClient, WptColor &color ) return m_szCaption; } -void CBotMenuList :: render ( CClient *pClient ) // render +void CBotMenuList::render(CClient* pClient) // render { - CBotMenu *pMenu = pClient->getCurrentMenu(); + CBotMenu* pMenu = pClient->getCurrentMenu(); pMenu->render(pClient); //m_MenuList[iMenu]->render(pClient); } -void CBotMenuList :: selectedMenu ( CClient *pClient, unsigned int iMenu ) +void CBotMenuList::selectedMenu(CClient* pClient, const unsigned iMenu) { - CBotMenu *pMenu = pClient->getCurrentMenu(); + const CBotMenu* pMenu = pClient->getCurrentMenu(); pMenu->selectedMenu(pClient, iMenu); } -void CBotMenu :: activate ( CClient *pClient ) +void CBotMenu::activate(CClient* pClient) { pClient->setCurrentMenu(this); } -void CBotMenu :: selectedMenu ( CClient *pClient, unsigned int iMenu ) +//TODO: Experimental [APG]RoboCop[CL] +Color CBotMenu::getColor(CClient* pClient) +{ + return Color(); +} + +void CBotMenu::selectedMenu(CClient* pClient, const unsigned iMenu) const { - if ( iMenu < m_MenuItems.size() ) + if (iMenu < m_MenuItems.size()) m_MenuItems[iMenu]->activate(pClient); } -CWaypointFlagShowMenu :: CWaypointFlagShowMenu (CBotMenu *pParent) +CWaypointFlagShowMenu::CWaypointFlagShowMenu(CBotMenu* pParent) { - int iMod = CBotGlobals::getCurrentMod()->getModId(); + const int iMod = CBotGlobals::getCurrentMod()->getModId(); // check the number of waypoint types available // caption // 1. @@ -436,160 +425,147 @@ CWaypointFlagShowMenu :: CWaypointFlagShowMenu (CBotMenu *pParent) // 8. More... // 9. Go Back - int iNumTypes = CWaypointTypes::getNumTypes(); - int iNumAdded = 0; - CBotMenu *pCurrent; + const std::size_t iNumTypes = CWaypointTypes::getNumTypes(); - int i; + int iNumAdded = 0; - pCurrent = this; + CBotMenu* pCurrent = this; - for ( i = 0; i < iNumTypes; i ++ ) + for (unsigned i = 0; i < iNumTypes; i++) { - if ( !CWaypointTypes::getTypeByIndex(i)->forMod(iMod) ) + if (!CWaypointTypes::getTypeByIndex(i)->forMod(iMod)) continue; pCurrent->addMenuItem(new CWaypointFlagShowMenuItem(i)); iNumAdded++; - if ( (iNumAdded > 7) || (i == (iNumTypes-1)) ) + if (iNumAdded > 7 || i == iNumTypes - 1) { - CBotMenuItem *back = new CBotGotoMenuItem("Back...",pParent); - // make a new menu + CBotMenuItem* back = new CBotGotoMenuItem("Back...", pParent); + // make a new menu pParent = pCurrent; - if ( (iNumAdded > 7) && (i < (iNumTypes-1)) ) + if (iNumAdded > 7 && i < iNumTypes - 1) { pCurrent = new CBotMenu(); pCurrent->setCaption("Show Waypoint Flags (More)"); - pParent->addMenuItem(new CBotGotoMenuItem("More...",pCurrent)); - + pParent->addMenuItem(new CBotGotoMenuItem("More...", pCurrent)); } pParent->addMenuItem(back); iNumAdded = 0; // reset - } } } -const char *CWaypointFlagShowMenu::getCaption(CClient *pClient,WptColor &color ) +const char* CWaypointFlagShowMenu::getCaption(CClient* pClient, WptColor& color) { - if ( pClient->isShowingAllWaypoints() ) + if (pClient->isShowingAllWaypoints()) { - sprintf(m_szCaption,"Showing All Waypoints (change)"); + snprintf(m_szCaption, sizeof(m_szCaption), "Showing All Waypoints (change)"); color = WptColor::white; } else { - sprintf(m_szCaption,"Showing Only Some Waypoints (change)"); + snprintf(m_szCaption, sizeof(m_szCaption), "Showing Only Some Waypoints (change)"); color = CWaypointTypes::getColour(pClient->getShowWaypointFlags()); } return m_szCaption; } - -const char *CWaypointFlagShowMenuItem :: getCaption ( CClient *pClient, WptColor &color ) +const char* CWaypointFlagShowMenuItem::getCaption(CClient* pClient, WptColor& color) { - CWaypointType *type = CWaypointTypes::getTypeByIndex(m_iFlag); + const CWaypointType* type = CWaypointTypes::getTypeByIndex(m_iFlag); color = type->getColour(); - sprintf(m_szCaption,"[%s] %s",(pClient->isShowingAllWaypoints()||pClient->isShowingWaypoint(type->getBits()))?"showing":"hiding",type->getName()); + snprintf(m_szCaption, sizeof(m_szCaption), "[%s] %s", pClient->isShowingAllWaypoints() || pClient->isShowingWaypoint(type->getBits()) ? "showing" : "hiding", type->getName()); return m_szCaption; } -void CWaypointFlagShowMenuItem::activate ( CClient *pClient ) +void CWaypointFlagShowMenuItem::activate(CClient* pClient) { - CWaypointType *type = CWaypointTypes::getTypeByIndex(m_iFlag); + const CWaypointType* type = CWaypointTypes::getTypeByIndex(m_iFlag); // toggle - if ( pClient->isShowingWaypoint(type->getBits()) ) + if (pClient->isShowingWaypoint(type->getBits())) pClient->dontShowWaypoints(type->getBits()); else pClient->showWaypoints(type->getBits()); } -void CBotMenuItem :: freeMemory () +void CBotMenuItem::freeMemory() { // do nothing } -void CBotMenu :: freeMemory () +void CBotMenu::freeMemory() { - for ( unsigned int i = 0; i < m_MenuItems.size(); i ++ ) + for (CBotMenuItem* temp : m_MenuItems) { - CBotMenuItem *temp = m_MenuItems[i]; - temp->freeMemory(); - delete temp; } } -void CBotMenuList :: freeMemory () +void CBotMenuList::freeMemory() { - for ( unsigned int i = 0; i < BOT_MENU_MAX; i ++ ) + for (CBotMenu* temp : m_MenuList) { - CBotMenu *temp = m_MenuList[i]; - temp->freeMemory(); - delete temp; } } -const char *CPathWaypointDeleteToMenuItem :: getCaption ( CClient *pClient, WptColor &color ) +const char* CPathWaypointDeleteToMenuItem::getCaption(CClient* pClient, WptColor& color) { - int iWpt = pClient->currentWaypoint(); + const int iWpt = pClient->currentWaypoint(); color = WptColor::white; - if ( iWpt == -1 ) + if (iWpt == -1) { - strcpy(m_szCaption,"No Waypoint"); + std::strcpy(m_szCaption, "No Waypoint"); return m_szCaption; } - CWaypoint *pWaypoint = CWaypoints::getWaypoint(iWpt); + const CWaypoint* pWaypoint = CWaypoints::getWaypoint(iWpt); - sprintf(m_szCaption,"Delete Paths To This Waypoint (%d)", pWaypoint->numPathsToThisWaypoint()); + snprintf(m_szCaption, sizeof(m_szCaption), "Delete Paths To This Waypoint (%d)", pWaypoint->numPathsToThisWaypoint()); return m_szCaption; } -void CPathWaypointDeleteToMenuItem :: activate ( CClient *pClient ) +void CPathWaypointDeleteToMenuItem::activate(CClient* pClient) { - if ( pClient->currentWaypoint() != -1 ) + if (pClient->currentWaypoint() != -1) CWaypoints::deletePathsTo(pClient->currentWaypoint()); } - -const char *CPathWaypointDeleteFromMenuItem :: getCaption ( CClient *pClient, WptColor &color ) +const char* CPathWaypointDeleteFromMenuItem::getCaption(CClient* pClient, WptColor& color) { - int iWpt = pClient->currentWaypoint(); + const int iWpt = pClient->currentWaypoint(); color = WptColor::white; - if ( iWpt == -1 ) + if (iWpt == -1) { - strcpy(m_szCaption,"No Waypoint"); + std::strcpy(m_szCaption, "No Waypoint"); return m_szCaption; } - CWaypoint *pWaypoint = CWaypoints::getWaypoint(iWpt); + const CWaypoint* pWaypoint = CWaypoints::getWaypoint(iWpt); - sprintf(m_szCaption,"Delete Paths From This Waypoint (%d)", pWaypoint->numPaths()); + snprintf(m_szCaption, sizeof(m_szCaption), "Delete Paths From This Waypoint (%d)", pWaypoint->numPaths()); return m_szCaption; } -void CPathWaypointDeleteFromMenuItem :: activate ( CClient *pClient ) +void CPathWaypointDeleteFromMenuItem::activate(CClient* pClient) { - if ( pClient->currentWaypoint() != -1 ) + if (pClient->currentWaypoint() != -1) CWaypoints::deletePathsFrom(pClient->currentWaypoint()); -} - +} \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_menu.h b/utils/RCBot2_meta/bot_menu.h index db917d996..a1f7c03e7 100644 --- a/utils/RCBot2_meta/bot_menu.h +++ b/utils/RCBot2_meta/bot_menu.h @@ -48,7 +48,6 @@ #define __BOT_MENU_H__ #include -using namespace std; class CClient; class CBotMenu; @@ -56,7 +55,7 @@ class CBotMenuItem; class WptColor; // menu types -typedef enum +typedef enum : std::uint8_t { BOT_MENU_NONE = 0, BOT_MENU_WAYPOINT_MAIN, @@ -83,7 +82,10 @@ typedef enum BOT_MENU_MAX_ITEMS }eBotMenus; -#define MAX_MENU_CAPTION_LENGTH 64 +enum : std::uint8_t +{ + MAX_MENU_CAPTION_LENGTH = 64 +}; class CBotMenuItem { @@ -93,6 +95,8 @@ class CBotMenuItem m_szCaption[0] = 0; } + virtual ~CBotMenuItem() = default; + virtual const char *getCaption ( CClient *pClient, WptColor &color ); virtual void activate ( CClient *pClient ) = 0; @@ -112,17 +116,17 @@ class CBotMenuItem class CWaypointFlagMenuItem : public CBotMenuItem { public: - CWaypointFlagMenuItem ( int iFlag ) + CWaypointFlagMenuItem (const int iFlag) { m_iFlag = iFlag; } - const char *getCaption ( CClient *pClient, WptColor &color ); + const char *getCaption ( CClient *pClient, WptColor &color ) override; - void activate ( CClient *pClient ); + void activate ( CClient *pClient ) override; private: - int m_iFlag; + std::size_t m_iFlag; }; class CBotGotoMenuItem : public CBotMenuItem @@ -135,7 +139,7 @@ class CBotGotoMenuItem : public CBotMenuItem m_pPrevMenu = pPrevMenu; } - void activate ( CClient *pClient ) + void activate ( CClient *pClient ) override { pClient->setCurrentMenu(m_pPrevMenu); } @@ -145,59 +149,59 @@ class CBotGotoMenuItem : public CBotMenuItem class CBotExitMenuItem : public CBotMenuItem { - const char *getCaption ( CClient *pClient, WptColor &color ) + const char *getCaption ( CClient *pClient, WptColor &color ) override { return "Exit"; } - void activate ( CClient *pClient ) + void activate ( CClient *pClient ) override { - pClient->setCurrentMenu(NULL); + pClient->setCurrentMenu(nullptr); } }; class CWaypointAreaMenuItem : public CBotMenuItem { public: - const char *getCaption ( CClient *pClient, WptColor &color ); + const char *getCaption ( CClient *pClient, WptColor &color ) override; - void activate ( CClient *pClient ); + void activate ( CClient *pClient ) override; }; class CBotMenu : public CBotMenuItem { public: - void freeMemory (); + void freeMemory () override; - virtual const char *getCaption ( CClient *pClient, WptColor &color ) + const char *getCaption ( CClient *pClient, WptColor &color ) override { return CBotMenuItem::getCaption(pClient,color); }// returns the caption (may be dynamic) - void activate ( CClient *pClient ); + void activate ( CClient *pClient ) override; - Color getColor ( CClient *pClient ); // gets the colour of the caption + static Color getColor ( CClient *pClient ); // gets the colour of the caption - TODO: not implemented yet? [APG]RoboCop[CL] virtual void addMenuItem ( CBotMenuItem *item ) { - m_MenuItems.push_back(item); + m_MenuItems.emplace_back(item); } void render ( CClient *pClient ); - void selectedMenu ( CClient *pClient, unsigned int iMenu ); + void selectedMenu ( CClient *pClient, unsigned iMenu ) const; private: - vector m_MenuItems; + std::vector m_MenuItems; }; class CWaypointFlagMenu : public CBotMenu { public: - CWaypointFlagMenu (CBotMenu *pParent); + CWaypointFlagMenu (CBotMenu *pPrev); //CWaypointFlagMenu ( int iShow ); - const char *getCaption(CClient *pClient,WptColor &color ); + const char *getCaption(CClient *pClient,WptColor &color ) override; }; class CWaypointFlagShowMenu : public CBotMenu @@ -205,23 +209,23 @@ class CWaypointFlagShowMenu : public CBotMenu public: CWaypointFlagShowMenu (CBotMenu *pParent); //CWaypointFlagMenu ( int iShow ); - const char *getCaption(CClient *pClient,WptColor &color ); + const char *getCaption(CClient *pClient,WptColor &color ) override; }; class CWaypointFlagShowMenuItem : public CBotMenuItem { public: - CWaypointFlagShowMenuItem ( int iFlag ) + CWaypointFlagShowMenuItem (const int iFlag) { m_iFlag = iFlag; } - const char *getCaption ( CClient *pClient, WptColor &color ); + const char *getCaption ( CClient *pClient, WptColor &color ) override; - void activate ( CClient *pClient ); + void activate ( CClient *pClient ) override; private: - int m_iFlag; + std::size_t m_iFlag; }; class CWaypointRadiusIncrease : public CBotMenuItem @@ -229,7 +233,7 @@ class CWaypointRadiusIncrease : public CBotMenuItem public: CWaypointRadiusIncrease() { setCaption("Increase Radius (+)"); } - void activate ( CClient *pClient ); + void activate ( CClient *pClient ) override; //const char *getCaption(CClient *pClient, WptColor &color); }; @@ -238,7 +242,7 @@ class CWaypointRadiusDecrease : public CBotMenuItem public: CWaypointRadiusDecrease() { setCaption("Decrease Radius (-)"); } - void activate ( CClient *pClient ); + void activate ( CClient *pClient ) override; //const char *getCaption(CClient *pClient, WptColor &color); }; @@ -247,12 +251,12 @@ class CWaypointRadiusMenu : public CBotMenu public: CWaypointRadiusMenu( CBotMenu *pParent ) { - addMenuItem(new CWaypointRadiusIncrease()); - addMenuItem(new CWaypointRadiusDecrease()); - addMenuItem(new CBotGotoMenuItem("Back",pParent)); + CBotMenu::addMenuItem(new CWaypointRadiusIncrease()); + CBotMenu::addMenuItem(new CWaypointRadiusDecrease()); + CBotMenu::addMenuItem(new CBotGotoMenuItem("Back",pParent)); } - const char *getCaption ( CClient *pClient, WptColor &color ); + const char *getCaption ( CClient *pClient, WptColor &color ) override; }; class CWaypointAreaIncrease : public CBotMenuItem @@ -260,7 +264,7 @@ class CWaypointAreaIncrease : public CBotMenuItem public: CWaypointAreaIncrease() { setCaption("Increase Area (+)"); } - void activate ( CClient *pClient ); + void activate ( CClient *pClient ) override; //const char *getCaption(CClient *pClient, WptColor &color); }; @@ -269,7 +273,7 @@ class CWaypointAreaDecrease : public CBotMenuItem public: CWaypointAreaDecrease() { setCaption("Decrease Area (-)"); } - void activate ( CClient *pClient ); + void activate ( CClient *pClient ) override; //const char *getCaption(CClient *pClient, WptColor &color); }; @@ -278,54 +282,54 @@ class CWaypointAreaMenu : public CBotMenu public: CWaypointAreaMenu( CBotMenu *pParent ) { - addMenuItem(new CWaypointAreaIncrease()); - addMenuItem(new CWaypointAreaDecrease()); - addMenuItem(new CBotGotoMenuItem("Back",pParent)); + CBotMenu::addMenuItem(new CWaypointAreaIncrease()); + CBotMenu::addMenuItem(new CWaypointAreaDecrease()); + CBotMenu::addMenuItem(new CBotGotoMenuItem("Back",pParent)); } - const char *getCaption ( CClient *pClient, WptColor &color ); + const char *getCaption ( CClient *pClient, WptColor &color ) override; }; class CWaypointYawMenuItem : public CBotMenuItem { - const char *getCaption ( CClient *pClient, WptColor &color ); + const char *getCaption ( CClient *pClient, WptColor &color ) override; - void activate ( CClient *pClient ); + void activate ( CClient *pClient ) override; }; class CWaypointCutMenuItem : public CBotMenuItem { - const char *getCaption ( CClient *pClient, WptColor &color ); + const char *getCaption ( CClient *pClient, WptColor &color ) override; - void activate ( CClient *pClient ); + void activate ( CClient *pClient ) override; }; class CWaypointCopyMenuItem : public CBotMenuItem { - const char *getCaption ( CClient *pClient, WptColor &color ); + const char *getCaption ( CClient *pClient, WptColor &color ) override; - void activate ( CClient *pClient ); + void activate ( CClient *pClient ) override; }; class CWaypointPasteMenuItem : public CBotMenuItem { - const char *getCaption ( CClient *pClient, WptColor &color ); + const char *getCaption ( CClient *pClient, WptColor &color ) override; - void activate ( CClient *pClient ); + void activate ( CClient *pClient ) override; }; class CPathWaypointDeleteToMenuItem : public CBotMenuItem { - const char *getCaption ( CClient *pClient, WptColor &color ); + const char *getCaption ( CClient *pClient, WptColor &color ) override; - void activate ( CClient *pClient ); + void activate ( CClient *pClient ) override; }; class CPathWaypointDeleteFromMenuItem : public CBotMenuItem { - const char *getCaption ( CClient *pClient, WptColor &color ); + const char *getCaption ( CClient *pClient, WptColor &color ) override; - void activate ( CClient *pClient ); + void activate ( CClient *pClient ) override; }; class CPathWaypointMenu : public CBotMenu @@ -333,9 +337,9 @@ class CPathWaypointMenu : public CBotMenu public: CPathWaypointMenu (CBotMenu *pParent) { - addMenuItem(new CPathWaypointDeleteFromMenuItem()); - addMenuItem(new CPathWaypointDeleteToMenuItem()); - addMenuItem(new CBotGotoMenuItem("Back",pParent)); + CBotMenu::addMenuItem(new CPathWaypointDeleteFromMenuItem()); + CBotMenu::addMenuItem(new CPathWaypointDeleteToMenuItem()); + CBotMenu::addMenuItem(new CBotGotoMenuItem("Back",pParent)); setCaption("Edit Path Options"); } }; @@ -345,10 +349,10 @@ class CWaypointEditMenu : public CBotMenu public: CWaypointEditMenu (CBotMenu *pParent) { - addMenuItem(new CWaypointCutMenuItem()); - addMenuItem(new CWaypointCopyMenuItem()); - addMenuItem(new CWaypointPasteMenuItem()); - addMenuItem(new CBotGotoMenuItem("Back",pParent)); + CBotMenu::addMenuItem(new CWaypointCutMenuItem()); + CBotMenu::addMenuItem(new CWaypointCopyMenuItem()); + CBotMenu::addMenuItem(new CWaypointPasteMenuItem()); + CBotMenu::addMenuItem(new CBotGotoMenuItem("Back",pParent)); setCaption("Edit Waypoint Options"); } }; @@ -370,18 +374,18 @@ class CWaypointMenu : public CBotMenu // 9 Exit CWaypointMenu () { - addMenuItem(new CWaypointFlagMenu(this)); - addMenuItem(new CWaypointAreaMenu(this)); - addMenuItem(new CWaypointRadiusMenu(this)); - addMenuItem(new CWaypointYawMenuItem()); - addMenuItem(new CWaypointEditMenu(this)); - addMenuItem(new CPathWaypointMenu(this)); - addMenuItem(new CWaypointFlagShowMenu(this)); - addMenuItem(new CBotGotoMenuItem("Exit",NULL)); + CBotMenu::addMenuItem(new CWaypointFlagMenu(this)); + CBotMenu::addMenuItem(new CWaypointAreaMenu(this)); + CBotMenu::addMenuItem(new CWaypointRadiusMenu(this)); + CBotMenu::addMenuItem(new CWaypointYawMenuItem()); + CBotMenu::addMenuItem(new CWaypointEditMenu(this)); + CBotMenu::addMenuItem(new CPathWaypointMenu(this)); + CBotMenu::addMenuItem(new CWaypointFlagShowMenu(this)); + CBotMenu::addMenuItem(new CBotGotoMenuItem("Exit", nullptr)); } //CWaypointFlagMenu ( int iShow ); - const char *getCaption(CClient *pClient,WptColor &color ); + const char *getCaption(CClient *pClient,WptColor &color ) override; }; //////////////////////////////////////// @@ -455,7 +459,7 @@ class CBotMenu_Bot : public CBotMenu const char *getCaption(CClient *pClient,WptColor &color ); };*/ -typedef enum +enum : std::uint8_t { BOT_MENU_WPT = 0, //BOT_MENU_BOT = 1, @@ -467,7 +471,7 @@ class CBotMenuList public: CBotMenuList () { - memset(m_MenuList,0,sizeof(CBotMenu*)*BOT_MENU_MAX); + std::memset(m_MenuList,0,sizeof(CBotMenu*)*BOT_MENU_MAX); } static void setupMenus (); @@ -476,9 +480,9 @@ class CBotMenuList static void render ( CClient *pClient ); // render - static void selectedMenu ( CClient *pClient, unsigned int iMenu ); + static void selectedMenu ( CClient *pClient, unsigned iMenu ); - static CBotMenu *getMenu ( int id ) { return m_MenuList[id]; } + static CBotMenu *getMenu (const int id) { return m_MenuList[id]; } private: static CBotMenu *m_MenuList[BOT_MENU_MAX]; diff --git a/utils/RCBot2_meta/bot_mods.cpp b/utils/RCBot2_meta/bot_mods.cpp index d128edc5a..220b1888b 100644 --- a/utils/RCBot2_meta/bot_mods.cpp +++ b/utils/RCBot2_meta/bot_mods.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -46,59 +48,59 @@ #include "bot_waypoint_locations.h" #include "bot_perceptron.h" -vector CHalfLifeDeathmatchMod::m_LiftWaypoints; +#include -void CBotMods :: parseFile () +#include "rcbot/logging.h" + +#if defined(_WIN64) || defined(_WIN32) +#define strcmpi _strcmpi +#endif + +std::vector CHalfLifeDeathmatchMod::m_LiftWaypoints; + +void CBotMods::parseFile() { char buffer[1024]; - unsigned int len; char key[64]; - unsigned int i,j; char val[256]; - eModId modtype; - eBotType bottype; - char steamfolder[256]; + eModId modtype = MOD_CUSTOM; + eBotType bottype = BOTTYPE_GENERIC; + char gamefolder[256]; char weaponlist[64]; - CBotGlobals::buildFileName(buffer,BOT_MOD_FILE,BOT_CONFIG_FOLDER,BOT_CONFIG_EXTENSION); + CBotGlobals::buildFileName(buffer, BOT_MOD_FILE, BOT_CONFIG_FOLDER, BOT_CONFIG_EXTENSION); - FILE *fp = CBotGlobals::openFile(buffer,"r"); + std::fstream fp = CBotGlobals::openFile(buffer, std::fstream::in); - CBotMod *curmod = NULL; + CBotMod* curmod = nullptr; - if ( !fp ) + if (!fp) { - createFile(); - fp = CBotGlobals::openFile(buffer,"r"); - } - - if ( !fp ) - { - // ERROR! + logger->Log(LogLevel::ERROR, "Failed to open file '%s' for reading", buffer); return; } - while ( fgets(buffer,1023,fp) != NULL ) + while (fp.getline(buffer, 1023)) { - if ( buffer[0] == '#' ) + if (buffer[0] == '#') continue; - len = strlen(buffer); + std::size_t len = std::strlen(buffer); - if ( len == 0 ) + if (len == 0) continue; - if ( buffer[len-1] == '\n' ) + if (buffer[len - 1] == '\n') buffer[--len] = 0; - i = 0; - j = 0; + std::size_t i = 0; + std::size_t j = 0; - while ( (i < len) && (buffer[i] != '=') ) + while (i < len && buffer[i] != '=') { - if ( buffer[i] != ' ' ) + if (buffer[i] != ' ') key[j++] = buffer[i]; i++; } @@ -109,81 +111,82 @@ void CBotMods :: parseFile () j = 0; - while ( (i < len) && (buffer[i] != '\n') && (buffer[i] != '\r') ) + while (i < len && buffer[i] != '\n' && buffer[i] != '\r') { - if ( j || (buffer[i] != ' ') ) + if (j || buffer[i] != ' ') val[j++] = buffer[i]; i++; } val[j] = 0; - if ( !strcmp(key,"mod") ) + if (!std::strcmp(key, "mod")) { - if ( curmod ) + if (curmod) { - curmod->setup(gamefolder, steamfolder, modtype, bottype, weaponlist); - m_Mods.push_back(curmod); + curmod->setup(gamefolder, modtype, bottype, weaponlist); + m_Mods.emplace_back(curmod); } - - curmod = NULL; + + curmod = nullptr; weaponlist[0] = 0; bottype = BOTTYPE_GENERIC; - modtype = MOD_CUSTOM; + //modtype = MOD_CUSTOM; + //TODO: Add Black Mesa Source support [APG]RoboCop[CL] - if ( !strcmpi("CUSTOM",val) ) + if (!strcmpi("CUSTOM", val)) { modtype = MOD_CUSTOM; curmod = new CBotMod(); } - else if ( !strcmpi("CSS",val) ) + else if (!strcmpi("CSS", val)) { modtype = MOD_CSS; curmod = new CCounterStrikeSourceMod(); } - else if ( !strcmpi("HL1DM",val) ) + else if (!strcmpi("HL1DM", val)) { modtype = MOD_HL1DMSRC; curmod = new CHLDMSourceMod(); } - else if ( !strcmpi("HL2DM",val) ) + else if (!strcmpi("HL2DM", val)) { modtype = MOD_HLDM2; curmod = new CHalfLifeDeathmatchMod(); } - else if ( !strcmpi("FF",val) ) + else if (!strcmpi("FF", val)) { modtype = MOD_FF; curmod = new CFortressForeverMod(); } - else if ( !strcmpi("TF2",val) ) + else if (!strcmpi("TF2", val)) { modtype = MOD_TF2; curmod = new CTeamFortress2Mod(); } - else if ( !strcmpi("SVENCOOP2",val) ) + else if (!strcmpi("SVENCOOP2", val)) { modtype = MOD_SVENCOOP2; curmod = new CBotMod(); } - else if ( !strcmpi("TIMCOOP",val) ) + else if (!strcmpi("TIMCOOP", val)) { modtype = MOD_TIMCOOP; curmod = new CBotMod(); } - else if ( !strcmpi("NS2",val) ) + else if (!strcmpi("NS2", val)) { modtype = MOD_NS2; curmod = new CBotMod(); } - else if ( !strcmpi("SYNERGY",val) ) + else if (!strcmpi("SYNERGY", val)) { modtype = MOD_SYNERGY; curmod = new CSynergyMod(); } - else if ( !strcmpi("DOD",val) ) + else if (!strcmpi("DOD", val)) { modtype = MOD_DOD; curmod = new CDODMod(); @@ -191,160 +194,83 @@ void CBotMods :: parseFile () else curmod = new CBotMod(); } - else if ( curmod && !strcmp(key,"bot") ) + else if (curmod && !std::strcmp(key, "bot")) { - if ( !strcmpi("GENERIC",val) ) + if (!strcmpi("GENERIC", val)) bottype = BOTTYPE_GENERIC; - else if ( !strcmpi("CSS",val) ) + else if (!strcmpi("CSS", val)) bottype = BOTTYPE_CSS; - else if ( !strcmpi("HL1DM",val) ) + else if (!strcmpi("HL1DM", val)) bottype = BOTTYPE_HL1DM; - else if ( !strcmpi("HL2DM",val) ) + else if (!strcmpi("HL2DM", val)) bottype = BOTTYPE_HL2DM; - else if ( !strcmpi("FF",val) ) + else if (!strcmpi("FF", val)) bottype = BOTTYPE_FF; - else if ( !strcmpi("TF2",val) ) + else if (!strcmpi("TF2", val)) bottype = BOTTYPE_TF2; - else if ( !strcmpi("COOP",val) ) + else if (!strcmpi("COOP", val)) bottype = BOTTYPE_COOP; - else if ( !strcmpi("ZOMBIE",val) ) + else if (!strcmpi("ZOMBIE", val)) bottype = BOTTYPE_ZOMBIE; - else if ( !strcmpi("DOD",val) ) + else if (!strcmpi("DOD", val)) bottype = BOTTYPE_DOD; + else if (!strcmpi("SYNERGY", val)) + bottype = BOTTYPE_SYN; } - else if ( curmod && !strcmpi(key,"steamdir") ) + else if (curmod && !strcmpi(key, "gamedir")) { - strncpy(steamfolder,val,255); - } - else if ( curmod && !strcmpi(key,"gamedir") ) - { - strncpy(gamefolder,val,255); + std::strncpy(gamefolder, val, 255); + gamefolder[255] = '\0'; } else if (curmod && !strcmpi(key, "weaponlist")) { - strncpy(weaponlist, val, 63); + std::strncpy(weaponlist, val, 63); + weaponlist[63] = '\0'; } } - if ( curmod ) - { - curmod->setup(gamefolder, steamfolder, modtype, bottype, weaponlist); - m_Mods.push_back(curmod); - } - - fclose(fp); -} - -void CBotMods :: createFile () -{ - char filename[1024]; - - CBotGlobals::buildFileName(filename,BOT_MOD_FILE,BOT_CONFIG_FOLDER,BOT_CONFIG_EXTENSION); - - FILE *fp = CBotGlobals::openFile(filename,"w"); - - CBotGlobals::botMessage(NULL,0,"Making a %s.%s file for you... Edit it in '%s'",BOT_MOD_FILE,BOT_CONFIG_EXTENSION,filename); - - if ( fp ) + if (curmod) { - fprintf(fp,"# EXAMPLE MOD FILE"); - fprintf(fp,"# valid mod types\n"); - fprintf(fp,"# ---------------\n"); - fprintf(fp,"# CSS\n"); - fprintf(fp,"# TF2\n"); - fprintf(fp,"# HL2DM\n"); - fprintf(fp,"# HL1DM\n"); - fprintf(fp,"# FF\n"); - fprintf(fp,"# SVENCOOP2\n"); - fprintf(fp,"# TIMCOOP\n"); - fprintf(fp,"# NS2\n"); - fprintf(fp,"# DOD (day of defeat source)\n"); - fprintf(fp,"#\n"); - fprintf(fp,"# valid bot types\n"); - fprintf(fp,"# ---------------\n"); - fprintf(fp,"# CSS\n"); - fprintf(fp,"# TF2\n"); - fprintf(fp,"# HL2DM\n"); - fprintf(fp,"# HL1DM\n"); - fprintf(fp,"# FF\n"); - fprintf(fp,"# COOP\n"); - fprintf(fp,"# ZOMBIE\n"); - fprintf(fp,"# DOD\n"); - fprintf(fp,"#\n"); - fprintf(fp, "# weaponlists are changeable in config / weapons.ini\n"); - fprintf(fp,"#\n"); - fprintf(fp,"#mod = CSS\n"); - fprintf(fp,"#steamdir = counter-strike source\n"); - fprintf(fp,"#gamedir = cstrike\n"); - fprintf(fp,"#bot = CSS\n"); - fprintf(fp,"#\n"); - fprintf(fp,"#mod = TF2\n"); - fprintf(fp,"#steamdir = teamfortress 2\n"); - fprintf(fp,"#gamedir = tf\n"); - fprintf(fp,"#bot = TF2\n"); - fprintf(fp,"#\n"); - fprintf(fp,"#mod = FF\n"); - fprintf(fp,"#steamdir = sourcemods\n"); - fprintf(fp,"#gamedir = ff\n"); - fprintf(fp,"#bot = FF\n"); - fprintf(fp,"#\n"); - fprintf(fp,"#mod = HL2DM\n"); - fprintf(fp,"#steamdir = half-life 2 deathmatch\n"); - fprintf(fp,"#gamedir = hl2mp\n"); - fprintf(fp,"#bot = HL2DM\n"); - fprintf(fp,"#\n"); - fprintf(fp,"#mod = HL1DM\n"); - fprintf(fp,"#steamdir = half-life 1 deathmatch\n"); - fprintf(fp,"#gamedir = hl1dm\n"); - fprintf(fp,"#bot = HL1DM\n"); - fprintf(fp,"#\n"); - fprintf(fp,"mod = DOD\n"); - fprintf(fp,"steamdir = orangebox\n"); - fprintf(fp,"gamedir = dod\n"); - fprintf(fp,"bot = DOD\n"); - fprintf(fp, "weaponlist = DOD\n"); - fprintf(fp,"#\n"); - - fclose(fp); + curmod->setup(gamefolder, modtype, bottype, weaponlist); + m_Mods.emplace_back(curmod); } - else - CBotGlobals::botMessage(NULL,0,"Error! Couldn't create config file %s",filename); } -void CBotMods :: readMods() +void CBotMods::readMods() { - m_Mods.push_back(new CDODMod()); - m_Mods.push_back(new CDODModDedicated()); - - m_Mods.push_back(new CCounterStrikeSourceMod()); - m_Mods.push_back(new CHalfLifeDeathmatchMod()); - - m_Mods.push_back(new CCounterStrikeSourceModDedicated()); - m_Mods.push_back(new CHalfLifeDeathmatchModDedicated()); - - m_Mods.push_back(new CFortressForeverMod()); - m_Mods.push_back(new CFortressForeverModDedicated()); - - m_Mods.push_back(new CTeamFortress2Mod()); - m_Mods.push_back(new CTeamFortress2ModDedicated()); - - m_Mods.push_back(new CHLDMSourceMod()); + // TODO improve game detection + // caxanga334: Better game detection required if we want to support multiple mods on the same engine (IE: SDK 2013) +#if SOURCE_ENGINE == SE_TF2 + m_Mods.emplace_back(new CTeamFortress2Mod()); +#elif SOURCE_ENGINE == SE_DODS + m_Mods.emplace_back(new CDODMod()); +#elif SOURCE_ENGINE == SE_CSS + m_Mods.emplace_back(new CCounterStrikeSourceMod()); +#elif SOURCE_ENGINE == SE_HL2DM + m_Mods.emplace_back(new CHalfLifeDeathmatchMod()); +#elif SOURCE_ENGINE == SE_SDK2013 + m_Mods.emplace_back(new CSynergyMod()); +#else + //TODO: Add Black Mesa Source support [APG]RoboCop[CL] + m_Mods.emplace_back(new CFortressForeverMod()); + + m_Mods.emplace_back(new CHLDMSourceMod()); // Look for extra MODs parseFile(); +#endif } ////////////////////////////////////////////////////////////////////////////// -void CBotMod :: setup ( const char *szModFolder, const char *szSteamFolder, eModId iModId, eBotType iBotType, const char *szWeaponListName ) +void CBotMod::setup(const char* szModFolder, const eModId iModId, const eBotType iBotType, const char* szWeaponListName) { m_szModFolder = CStrings::getString(szModFolder); - m_szSteamFolder = CStrings::getString(szSteamFolder); m_iModId = iModId; m_iBotType = iBotType; - if (szWeaponListName && *szWeaponListName ) + if (szWeaponListName && *szWeaponListName) m_szWeaponListName = CStrings::getString(szWeaponListName); } @@ -353,27 +279,17 @@ void CBotMod :: setup ( const char *szModFolder, const char *szSteamFolder, eMod return NULL; }*/ -bool CBotMod :: isSteamFolder ( char *szSteamFolder ) -{ - return FStrEq(m_szSteamFolder,szSteamFolder); -} - -bool CBotMod :: isModFolder ( char *szModFolder ) -{ - return FStrEq(m_szModFolder,szModFolder); -} - -char *CBotMod :: getSteamFolder () +bool CBotMod::isModFolder(const char* szModFolder) const { - return m_szSteamFolder; + return FStrEq(m_szModFolder, szModFolder); } -char *CBotMod :: getModFolder () +char* CBotMod::getModFolder() const { return m_szModFolder; } -eModId CBotMod :: getModId () +eModId CBotMod::getModId() const { return m_iModId; } @@ -381,52 +297,52 @@ eModId CBotMod :: getModId () // // MOD LIST -vector CBotMods::m_Mods; +std::vector CBotMods::m_Mods; -void CBotMods :: freeMemory () +void CBotMods::freeMemory() { - for ( unsigned int i = 0; i < m_Mods.size(); i ++ ) + for (CBotMod*& m_Mod : m_Mods) { - m_Mods[i]->freeMemory(); - delete m_Mods[i]; - m_Mods[i] = NULL; + m_Mod->freeMemory(); + delete m_Mod; + m_Mod = nullptr; } m_Mods.clear(); } -CBotMod *CBotMods :: getMod ( char *szModFolder, char *szSteamFolder ) +CBotMod* CBotMods::getMod(char* szModFolder) { - for ( unsigned int i = 0; i < m_Mods.size(); i ++ ) + for (CBotMod* const& m_Mod : m_Mods) { - if ( m_Mods[i]->isModFolder(szModFolder) && m_Mods[i]->isSteamFolder(szSteamFolder) ) + if (m_Mod->isModFolder(szModFolder)) { - CBotGlobals::botMessage(NULL,1,"HL2 MOD ID %d (Steam Folder = %s) (Game Folder = %s) FOUND",m_Mods[i]->getModId(),szSteamFolder,szModFolder); + logger->Log(LogLevel::INFO, "HL2 MOD ID %d (Game Folder = %s) FOUND", m_Mod->getModId(), szModFolder); - return m_Mods[i]; + return m_Mod; } } - CBotGlobals::botMessage(NULL,1,"HL2 MODIFICATION \"%s/%s\" NOT FOUND, EXITING... see bot_mods.ini in bot config folder",szSteamFolder,szModFolder); + logger->Log(LogLevel::FATAL, "HL2 MODIFICATION \"%s\" NOT FOUND, EXITING... see bot_mods.ini in bot config folder", szModFolder); - return NULL; + return nullptr; } -void CBotMod :: initMod () +void CBotMod::initMod() { m_bPlayerHasSpawned = false; - CWeapons::loadWeapons(m_szWeaponListName, NULL); + CWeapons::loadWeapons(m_szWeaponListName, nullptr); } -void CBotMod :: mapInit () +void CBotMod::mapInit() { m_bPlayerHasSpawned = false; } -bool CBotMod :: playerSpawned ( edict_t *pEntity ) +bool CBotMod::playerSpawned(edict_t* pPlayer) { - if ( m_bPlayerHasSpawned ) + if (m_bPlayerHasSpawned) return false; m_bPlayerHasSpawned = true; @@ -434,32 +350,29 @@ bool CBotMod :: playerSpawned ( edict_t *pEntity ) return true; } -bool CHalfLifeDeathmatchMod :: playerSpawned ( edict_t *pPlayer ) +bool CHalfLifeDeathmatchMod::playerSpawned(edict_t* pPlayer) { - if ( CBotMod::playerSpawned(pPlayer) ) + if (CBotMod::playerSpawned(pPlayer)) { m_LiftWaypoints.clear(); - CWaypoints::updateWaypointPairs(&m_LiftWaypoints,CWaypointTypes::W_FL_LIFT,"func_button"); + CWaypoints::updateWaypointPairs(&m_LiftWaypoints, CWaypointTypes::W_FL_LIFT, "func_button"); } return true; } -void CHalfLifeDeathmatchMod :: initMod () +void CHalfLifeDeathmatchMod::initMod() { - CBots::controlBotSetup(false); + CWeapons::loadWeapons(m_szWeaponListName == nullptr ? "HL2DM" : m_szWeaponListName, HL2DMWeaps.data()); - CWeapons::loadWeapons((m_szWeaponListName==NULL)?"HL2DM":m_szWeaponListName, HL2DMWeaps); - -// for ( i = 0; i < HL2DM_WEAPON_MAX; i ++ ) + // for ( i = 0; i < HL2DM_WEAPON_MAX; i ++ ) // CWeapons::addWeapon(new CWeapon(HL2DMWeaps[i]));//.iSlot,HL2DMWeaps[i].szWeaponName,HL2DMWeaps[i].iId,HL2DMWeaps[i].m_iFlags,HL2DMWeaps[i].m_iAmmoIndex,HL2DMWeaps[i].minPrimDist,HL2DMWeaps[i].maxPrimDist,HL2DMWeaps[i].m_iPreference,HL2DMWeaps[i].m_fProjSpeed)); } -void CHalfLifeDeathmatchMod :: mapInit () +void CHalfLifeDeathmatchMod::mapInit() { CBotMod::mapInit(); m_LiftWaypoints.clear(); -} - +} \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_mods.h b/utils/RCBot2_meta/bot_mods.h index 50f1daaee..62d823eb4 100644 --- a/utils/RCBot2_meta/bot_mods.h +++ b/utils/RCBot2_meta/bot_mods.h @@ -39,21 +39,33 @@ #include "bot_dod_bot.h" #include "bot_waypoint.h" #include "bot_tf2_points.h" +#include "bot_cvars.h" -#define MAX_CAP_POINTS 32 +#include -#define DOD_MAPTYPE_UNKNOWN 0 -#define DOD_MAPTYPE_FLAG 1 -#define DOD_MAPTYPE_BOMB 2 +enum : std::uint8_t +{ + MAX_CAP_POINTS = 32 +}; + +enum : std::uint8_t +{ + DOD_MAPTYPE_UNKNOWN = 0, + DOD_MAPTYPE_FLAG = 1, + DOD_MAPTYPE_BOMB = 2 +}; -#define BOT_ADD_METHOD_DEFAULT 0 -#define BOT_ADD_METHOD_PUPPET 1 -#define BOT_ADD_PUPPET_COMMAND "bot" +enum : std::uint8_t +{ + BOT_ADD_METHOD_DEFAULT = 0, + BOT_ADD_METHOD_PUPPET = 1 +}; + +constexpr const char* BOT_ADD_PUPPET_COMMAND = "bot"; class CBotNeuralNet; #include -using namespace std; /* @@ -65,7 +77,7 @@ using namespace std; COOP ZOMBIE */ -typedef enum +typedef enum : std::uint8_t { BOTTYPE_GENERIC = 0, BOTTYPE_CSS, @@ -77,77 +89,52 @@ typedef enum BOTTYPE_ZOMBIE, BOTTYPE_DOD, BOTTYPE_NS2, + BOTTYPE_SYN, + BOTTYPE_BMS, BOTTYPE_MAX }eBotType; - -// tf2 -class CAttributeID -{ -public: - CAttributeID(int id, const char *attrib) - { - m_id = id; - m_attribute = attrib; - } - - int m_id; - const char *m_attribute; -}; - -class CAttributeLookup -{ -public: - static void addAttribute(const char *szAttrib, int id); - static int findAttributeID(const char *szAttrib); - static void freeMemory(); -private: - static vector attributes; -}; - - class CBotMod { public: CBotMod() { - m_szModFolder = NULL; - m_szSteamFolder = NULL; - m_szWeaponListName = NULL; + m_szModFolder = nullptr; + m_szSteamFolder = nullptr; + m_szWeaponListName = nullptr; m_iModId = MOD_UNSUPPORTED; m_iBotType = BOTTYPE_GENERIC; m_bPlayerHasSpawned = false; m_bBotCommand_ResetCheatFlag = false; - m_bBotCommand_NeedCheatsHack = false; } + virtual ~CBotMod() = default; + virtual bool checkWaypointForTeam(CWaypoint *pWpt, int iTeam) { return true; // okay -- no teams!! } -// linux fix - void setup ( const char *szModFolder, const char *szSteamFolder, eModId iModId, eBotType iBotType, const char *szWeaponListName ); + // linux fix + void setup ( const char *szModFolder, eModId iModId, eBotType iBotType, const char *szWeaponListName ); - bool isSteamFolder ( char *szSteamFolder ); + bool isModFolder (const char* szModFolder) const; - bool isModFolder ( char *szModFolder ); - - char *getSteamFolder (); - - char *getModFolder (); + char *getModFolder () const; virtual const char *getPlayerClass () { return "CBasePlayer"; } - eModId getModId (); + eModId getModId () const; //TODO: not implemented? [APG]RoboCop[CL] - virtual bool isAreaOwnedByTeam (int iArea, int iTeam) { return (iArea == 0); } + virtual bool isAreaOwnedByTeam (const int iArea, int iTeam) { return iArea == 0; } - eBotType getBotType () { return m_iBotType; } + eBotType getBotType () const { return m_iBotType; } - virtual void addWaypointFlags (edict_t *pPlayer, edict_t *pEdict, int *iFlags, int *iArea, float *fMaxDistance ){ return; } + virtual void addWaypointFlags (edict_t *pPlayer, edict_t *pEdict, int *iFlags, int *iArea, float *fMaxDistance) + { + } //////////////////////////////// virtual void initMod (); @@ -156,11 +143,11 @@ class CBotMod virtual bool playerSpawned ( edict_t *pPlayer ); - virtual void clientCommand ( edict_t *pEntity, int argc,const char *pcmd, const char *arg1, const char *arg2 ) {}; + virtual void clientCommand ( edict_t *pEntity, int argc,const char *pcmd, const char *arg1, const char *arg2 ) {} - virtual void modFrame () { }; + virtual void modFrame () { } - virtual void freeMemory() {}; + virtual void freeMemory() {} virtual bool isWaypointAreaValid ( int iWptArea, int iWptFlags ) { return true; } @@ -170,12 +157,7 @@ class CBotMod *iOff = 0; } - inline bool needCheatsHack () - { - return m_bBotCommand_NeedCheatsHack; - } - - inline bool needResetCheatFlag () + bool needResetCheatFlag () const { return m_bBotCommand_ResetCheatFlag; } @@ -188,9 +170,10 @@ class CBotMod char *m_szWeaponListName; bool m_bPlayerHasSpawned; bool m_bBotCommand_ResetCheatFlag; - bool m_bBotCommand_NeedCheatsHack; }; +//TODO: Add Black Mesa Source support [APG]RoboCop[CL] + /////////////////// /* class CDODFlag @@ -217,7 +200,10 @@ class CDODFlag int m_iId; }; */ -#define MAX_DOD_FLAGS 8 +enum : std::uint8_t +{ + MAX_DOD_FLAGS = 8 +}; class CDODFlags { @@ -230,35 +216,35 @@ class CDODFlags void init () { m_iNumControlPoints = 0; - m_vCPPositions = NULL; - - m_iAlliesReqCappers = NULL; - m_iAxisReqCappers = NULL; - m_iNumAllies = NULL; - m_iNumAxis = NULL; - m_iOwner = NULL; - m_bBombPlanted_Unreliable = NULL; - m_iBombsRequired = NULL; - m_iBombsRemaining = NULL; - m_bBombBeingDefused = NULL; + m_vCPPositions = nullptr; + + m_iAlliesReqCappers = nullptr; + m_iAxisReqCappers = nullptr; + m_iNumAllies = nullptr; + m_iNumAxis = nullptr; + m_iOwner = nullptr; + m_bBombPlanted_Unreliable = nullptr; + m_iBombsRequired = nullptr; + m_iBombsRemaining = nullptr; + m_bBombBeingDefused = nullptr; m_iNumAxisBombsOnMap = 0; m_iNumAlliesBombsOnMap = 0; - memset(m_bBombPlanted,0,sizeof(bool)*MAX_DOD_FLAGS); - memset(m_pFlags,0,sizeof(edict_t*)*MAX_DOD_FLAGS); - memset(m_pBombs,0,sizeof(edict_t*)*MAX_DOD_FLAGS*2); + std::memset(m_bBombPlanted,0,sizeof(bool)*MAX_DOD_FLAGS); + std::memset(m_pFlags,0,sizeof(edict_t*)*MAX_DOD_FLAGS); + std::memset(m_pBombs,0,sizeof(edict_t*)*MAX_DOD_FLAGS*8); - for ( short int i = 0; i < MAX_DOD_FLAGS; i ++ ) + for (int& i : m_iWaypoint) { - m_iWaypoint[i] = -1; + i = -1; } } - int getNumFlags () { return m_iNumControlPoints; } - int getNumFlagsOwned (int iTeam) + int getNumFlags () const { return m_iNumControlPoints; } + int getNumFlagsOwned (const int iTeam) const { int count = 0; - for ( short int i = 0; i < m_iNumControlPoints; i ++ ) + for (int i = 0; i < m_iNumControlPoints; i++) { if ( m_iOwner[i] == iTeam ) count++; @@ -269,25 +255,25 @@ class CDODFlags int setup (edict_t *pResourceEntity); - bool getRandomEnemyControlledFlag ( CBot *pBot, Vector *position, int iTeam, int *id = NULL ); - bool getRandomTeamControlledFlag ( CBot *pBot, Vector *position, int iTeam, int *id = NULL ); + bool getRandomEnemyControlledFlag (const CBot *pBot, Vector *position, int iTeam, int *id = nullptr) const; + bool getRandomTeamControlledFlag (const CBot *pBot, Vector *position, int iTeam, int *id = nullptr) const; - bool getRandomBombToDefuse ( Vector *position, int iTeam, edict_t **pBombTarget, int *id = NULL ); - bool getRandomBombToPlant ( CBot *pBot, Vector *position, int iTeam, edict_t **pBombTarget, int *id = NULL ); - bool getRandomBombToDefend ( CBot *pBot, Vector *position, int iTeam, edict_t **pBombTarget, int *id = NULL ); + bool getRandomBombToDefuse (Vector& position, int iTeam, edict_t*& pBombTarget, int* id = nullptr) const; + bool getRandomBombToPlant (CBot* pBot, Vector& position, int iTeam, edict_t*& pBombTarget, int* id = nullptr) const; + bool getRandomBombToDefend (CBot* pBot, Vector* position, int iTeam, edict_t** pBombTarget, int* id = nullptr) const; - int findNearestObjective ( Vector vOrigin ); + int findNearestObjective (const Vector& vOrigin) const; - inline int getWaypointAtFlag ( int iFlagId ) + int getWaypointAtFlag (const int iFlagId) const { return m_iWaypoint[iFlagId]; } - inline int getNumBombsToDefend ( int iTeam ) + int getNumBombsToDefend (const int iTeam) const { int count = 0; - for ( short int i = 0; i < m_iNumControlPoints; i ++ ) + for (int i = 0; i < m_iNumControlPoints; i++) { if ( canDefendBomb(iTeam,i) ) count++; @@ -296,11 +282,11 @@ class CDODFlags return count; } - inline int getNumBombsToDefuse ( int iTeam ) + int getNumBombsToDefuse (const int iTeam) const { int count = 0; - for ( short int i = 0; i < m_iNumControlPoints; i ++ ) + for (int i = 0; i < m_iNumControlPoints; i++) { if ( canDefuseBomb(iTeam,i) ) count++; @@ -309,11 +295,11 @@ class CDODFlags return count; } - inline int getNumPlantableBombs (int iTeam) + int getNumPlantableBombs (const int iTeam) const { int count = 0; - for ( short int i = 0; i < m_iNumControlPoints; i ++ ) + for (int i = 0; i < m_iNumControlPoints; i++) { if ( canPlantBomb(iTeam,i) ) count += getNumBombsRequired(i); @@ -322,12 +308,12 @@ class CDODFlags return count; } - inline float isBombExplodeImminent ( int id ) + bool isBombExplodeImminent(const int id) const { - return (engine->Time() - m_fBombPlantedTime[id]) > DOD_BOMB_EXPLODE_IMMINENT_TIME; + return engine->Time() - m_fBombPlantedTime[id] > DOD_BOMB_EXPLODE_IMMINENT_TIME; } - inline void setBombPlanted ( int id, bool val ) + void setBombPlanted (const int id, const bool val) { m_bBombPlanted[id] = val; @@ -337,11 +323,11 @@ class CDODFlags m_fBombPlantedTime[id] = 0; } - inline int getNumBombsToPlant ( int iTeam) + int getNumBombsToPlant (const int iTeam) const { int count = 0; - for ( short int i = 0; i < m_iNumControlPoints; i ++ ) + for (int i = 0; i < m_iNumControlPoints; i++) { if ( canPlantBomb(iTeam,i) ) count += getNumBombsRemaining(i); @@ -350,8 +336,9 @@ class CDODFlags return count; } - inline bool ownsFlag ( edict_t *pFlag, int iTeam ) { return ownsFlag(getFlagID(pFlag),iTeam); } - inline bool ownsFlag ( int iFlag, int iTeam ) + bool ownsFlag (const edict_t *pFlag, const int iTeam) const { return ownsFlag(getFlagID(pFlag),iTeam); } + + bool ownsFlag (const int iFlag, const int iTeam) const { if ( iFlag == -1 ) return false; @@ -359,11 +346,11 @@ class CDODFlags return m_iOwner[iFlag] == iTeam; } - inline int numFlagsOwned (int iTeam) + int numFlagsOwned (const int iTeam) const { int count = 0; - for ( short int i = 0; i < m_iNumControlPoints; i ++ ) + for (int i = 0; i < m_iNumControlPoints; i++) { if ( m_iOwner[i] == iTeam ) count++; @@ -372,16 +359,17 @@ class CDODFlags return count; } - inline int numCappersRequired ( edict_t *pFlag, int iTeam ) { return numCappersRequired(getFlagID(pFlag),iTeam); } - inline int numCappersRequired ( int iFlag, int iTeam ) + int numCappersRequired (const edict_t *pFlag, const int iTeam) const { return numCappersRequired(getFlagID(pFlag),iTeam); } + + int numCappersRequired (const int iFlag, const int iTeam) const { if ( iFlag == -1 ) return 0; - return (iTeam == TEAM_ALLIES) ? (m_iAlliesReqCappers[iFlag]) : (m_iAxisReqCappers[iFlag]); + return iTeam == TEAM_ALLIES ? m_iAlliesReqCappers[iFlag] : m_iAxisReqCappers[iFlag]; } - inline bool isBombPlanted ( int iId ) + bool isBombPlanted (const int iId) const { if ( iId == -1 ) return false; @@ -389,59 +377,59 @@ class CDODFlags return m_bBombPlanted[iId]; } - inline bool isBombPlanted ( edict_t *pBomb ) + bool isBombPlanted (const edict_t *pBomb) const { return isBombPlanted(getBombID(pBomb)); } - inline bool canDefendBomb ( int iTeam, int iId ) + bool canDefendBomb (const int iTeam, const int iId) const { - return ((m_pBombs[iId][0]!=NULL)&&(m_iOwner[iId]!=iTeam) && isBombPlanted(iId)); + return m_pBombs[iId][0]!= nullptr &&m_iOwner[iId]!=iTeam && isBombPlanted(iId); } - inline bool canDefuseBomb ( int iTeam, int iId ) + bool canDefuseBomb (const int iTeam, const int iId) const { - return ((m_pBombs[iId][0]!=NULL)&&(m_iOwner[iId]==iTeam) && isBombPlanted(iId)); + return m_pBombs[iId][0]!= nullptr &&m_iOwner[iId]==iTeam && isBombPlanted(iId); } - inline bool canPlantBomb ( int iTeam, int iId ) + bool canPlantBomb (const int iTeam, const int iId) const { - return ((m_pBombs[iId][0]!=NULL)&&(m_iOwner[iId]!=iTeam) && !isBombPlanted(iId)); + return m_pBombs[iId][0]!= nullptr &&m_iOwner[iId]!=iTeam && !isBombPlanted(iId); } - bool isTeamMateDefusing ( edict_t *pIgnore, int iTeam, int id ); - bool isTeamMatePlanting ( edict_t *pIgnore, int iTeam, int id ); + bool isTeamMateDefusing (const edict_t *pIgnore, int iTeam, int id ) const; + bool isTeamMatePlanting (const edict_t *pIgnore, int iTeam, int id ) const; - bool isTeamMateDefusing ( edict_t *pIgnore, int iTeam, Vector vOrigin ); - bool isTeamMatePlanting ( edict_t *pIgnore, int iTeam, Vector vOrigin ); + static bool isTeamMateDefusing (const edict_t *pIgnore, int iTeam, const Vector& vOrigin ); + static bool isTeamMatePlanting (const edict_t *pIgnore, int iTeam, const Vector& vOrigin ); - inline int getNumBombsRequired ( int iId ) + int getNumBombsRequired (const int iId) const { if ( iId == -1 ) - return false; + return 0; return m_iBombsRequired[iId]; } - inline int getNumBombsRequired ( edict_t *pBomb ) + int getNumBombsRequired (const edict_t *pBomb) const { return getNumBombsRequired(getBombID(pBomb)); } - inline int getNumBombsRemaining ( int iId ) + int getNumBombsRemaining (const int iId) const { if ( iId == -1 ) - return false; + return 0; return m_iBombsRemaining[iId]; } - inline int getNumBombsRemaining ( edict_t *pBomb ) + int getNumBombsRemaining (const edict_t *pBomb) const { return getNumBombsRemaining(getBombID(pBomb)); } - inline bool isBombBeingDefused ( int iId ) + bool isBombBeingDefused (const int iId) const { if ( iId == -1 ) return false; @@ -449,42 +437,42 @@ class CDODFlags return m_bBombBeingDefused[iId]; } - inline bool isBombBeingDefused ( edict_t *pBomb ) + bool isBombBeingDefused (const edict_t *pBomb) const { return isBombBeingDefused(getBombID(pBomb)); } - inline int numEnemiesAtCap ( edict_t *pFlag, int iTeam ) { return numEnemiesAtCap(getFlagID(pFlag),iTeam); } + int numEnemiesAtCap (const edict_t *pFlag, const int iTeam) const { return numEnemiesAtCap(getFlagID(pFlag),iTeam); } - inline int numFriendliesAtCap ( edict_t *pFlag, int iTeam ) { return numFriendliesAtCap(getFlagID(pFlag),iTeam); } + int numFriendliesAtCap (const edict_t *pFlag, const int iTeam) const { return numFriendliesAtCap(getFlagID(pFlag),iTeam); } - inline int numFriendliesAtCap ( int iFlag, int iTeam ) + int numFriendliesAtCap (const int iFlag, const int iTeam) const { if ( iFlag == -1 ) return 0; - return (iTeam == TEAM_ALLIES) ? (m_iNumAllies[iFlag]) : (m_iNumAxis[iFlag]); + return iTeam == TEAM_ALLIES ? m_iNumAllies[iFlag] : m_iNumAxis[iFlag]; } - inline int numEnemiesAtCap ( int iFlag, int iTeam ) + int numEnemiesAtCap (const int iFlag, const int iTeam) const { if ( iFlag == -1 ) return 0; - return (iTeam == TEAM_ALLIES) ? (m_iNumAxis[iFlag]) : (m_iNumAllies[iFlag]); + return iTeam == TEAM_ALLIES ? m_iNumAxis[iFlag] : m_iNumAllies[iFlag]; } - inline edict_t *getFlagByID ( int id ) + edict_t *getFlagByID (const int id) const { - if ( (id >= 0) && (id < m_iNumControlPoints) ) + if ( id >= 0 && id < m_iNumControlPoints ) return m_pFlags[id]; - return NULL; + return nullptr; } - inline int getFlagID ( edict_t *pent ) + int getFlagID (const edict_t *pent) const { - for ( short int i = 0; i < m_iNumControlPoints; i ++ ) + for (int i = 0; i < m_iNumControlPoints; i++) { if ( m_pFlags[i] == pent ) return i; @@ -493,38 +481,38 @@ class CDODFlags return -1; } - inline int getBombID ( edict_t *pent ) + int getBombID (const edict_t *pent) const { - if ( pent == NULL ) + if ( pent == nullptr) return -1; - for ( short int i = 0; i < m_iNumControlPoints; i ++ ) + for (int i = 0; i < m_iNumControlPoints; i++) { - if ( (m_pBombs[i][0] == pent) || (m_pBombs[i][1] == pent) ) + if ( m_pBombs[i][0] == pent || m_pBombs[i][1] == pent ) return i; } return -1; } - inline bool isFlag ( edict_t *pent ) + bool isFlag (const edict_t *pent) const { return getFlagID(pent) != -1; } - inline bool isBomb ( edict_t *pent ) + bool isBomb (const edict_t *pent) const { return getBombID(pent) != -1; } - inline int getNumBombsOnMap ( int iTeam ) + int getNumBombsOnMap (const int iTeam) const { if ( iTeam == TEAM_ALLIES ) return m_iNumAlliesBombsOnMap; return m_iNumAxisBombsOnMap; } - inline void reset () + void reset () { // time up m_iNumControlPoints = 0; @@ -532,7 +520,7 @@ class CDODFlags private: edict_t *m_pFlags[MAX_DOD_FLAGS]; - edict_t *m_pBombs[MAX_DOD_FLAGS][2]; // maximum of 2 bombs per capture point + edict_t* m_pBombs[MAX_DOD_FLAGS][8]; // maximum of 8 bombs per capture point increased for stability [APG]RoboCop[CL] int m_iWaypoint[MAX_DOD_FLAGS]; int m_iNumControlPoints; @@ -546,7 +534,7 @@ class CDODFlags // reply on this one bool *m_bBombPlanted_Unreliable; - bool m_bBombPlanted[MAX_DOD_FLAGS]; + bool m_bBombPlanted[MAX_DOD_FLAGS]; float m_fBombPlantedTime[MAX_DOD_FLAGS]; int *m_iBombsRequired; int *m_iBombsRemaining; @@ -560,14 +548,12 @@ class CDODMod : public CBotMod public: CDODMod() { - setup("dod","day of defeat source",MOD_DOD,BOTTYPE_DOD,"DOD"); - - m_bBotCommand_NeedCheatsHack = false; + setup("dod",MOD_DOD,BOTTYPE_DOD,"DOD"); } static void roundStart (); - bool checkWaypointForTeam(CWaypoint *pWpt, int iTeam); + bool checkWaypointForTeam(CWaypoint *pWpt, int iTeam) override; static int numClassOnTeam( int iTeam, int iClass ); @@ -575,46 +561,46 @@ class CDODMod : public CBotMod static int getHighestScore (); - void clientCommand ( edict_t *pEntity, int argc, const char *pcmd, const char *arg1, const char *arg2 ); + void clientCommand ( edict_t *pEntity, int argc, const char *pcmd, const char *arg1, const char *arg2 ) override; static float getMapStartTime (); - inline static bool isBombMap () { return (m_iMapType & DOD_MAPTYPE_BOMB) == DOD_MAPTYPE_BOMB; } - inline static bool isFlagMap () { return (m_iMapType & DOD_MAPTYPE_FLAG) == DOD_MAPTYPE_FLAG; } - inline static bool mapHasBombs () { return (m_iMapType & DOD_MAPTYPE_BOMB) == DOD_MAPTYPE_BOMB; } + static bool isBombMap () { return (m_iMapType & DOD_MAPTYPE_BOMB) == DOD_MAPTYPE_BOMB; } //TODO: both `maphasBombs` and `isBombMap` do the same thing but conflict? [APG]RoboCop[CL] + static bool isFlagMap () { return (m_iMapType & DOD_MAPTYPE_FLAG) == DOD_MAPTYPE_FLAG; } + static bool mapHasBombs () { return (m_iMapType & DOD_MAPTYPE_BOMB) == DOD_MAPTYPE_BOMB; } - inline static bool isCommunalBombPoint () { return m_bCommunalBombPoint; } - inline static int getBombPointArea (int iTeam) { if ( iTeam == TEAM_ALLIES ) return m_iBombAreaAllies; return m_iBombAreaAxis; } + static bool isCommunalBombPoint () { return m_bCommunalBombPoint; } + static int getBombPointArea (const int iTeam) { if ( iTeam == TEAM_ALLIES ) return m_iBombAreaAllies; return m_iBombAreaAxis; } - void addWaypointFlags (edict_t *pPlayer, edict_t *pEdict, int *iFlags, int *iArea, float *fMaxDistance ); + void addWaypointFlags (edict_t *pPlayer, edict_t *pEdict, int *iFlags, int *iArea, float *fMaxDistance ) override; static CDODFlags m_Flags; static bool shouldAttack ( int iTeam ); // uses the neural net to return probability of attack - static edict_t *getBombTarget ( CWaypoint *pWpt ); - static edict_t *getBreakable ( CWaypoint *pWpt ); + static edict_t *getBombTarget (const CWaypoint *pWpt ); + static edict_t *getBreakable (const CWaypoint *pWpt ); - void getTeamOnlyWaypointFlags ( int iTeam, int *iOn, int *iOff ); + void getTeamOnlyWaypointFlags ( int iTeam, int *iOn, int *iOff ) override; static bool isBreakableRegistered ( edict_t *pBreakable, int iTeam ); - static inline CWaypoint *getBombWaypoint ( edict_t *pBomb ) + static CWaypoint *getBombWaypoint ( edict_t *pBomb ) { - for ( unsigned int i = 0; i < m_BombWaypoints.size(); i ++ ) + for (edict_wpt_pair_t& m_BombWaypoint : m_BombWaypoints) { - if ( m_BombWaypoints[i].pEdict == pBomb ) - return m_BombWaypoints[i].pWaypoint; + if (m_BombWaypoint.pEdict == pBomb ) + return m_BombWaypoint.pWaypoint; } - return NULL; + return nullptr; } - static inline bool isPathBomb ( edict_t *pBomb ) + static bool isPathBomb ( edict_t *pBomb ) { - for ( unsigned int i = 0; i < m_BombWaypoints.size(); i ++ ) + for (edict_wpt_pair_t& m_BombWaypoint : m_BombWaypoints) { - if ( m_BombWaypoints[i].pEdict == pBomb ) + if (m_BombWaypoint.pEdict == pBomb ) return true; } @@ -631,13 +617,13 @@ class CDODMod : public CBotMod protected: - void initMod (); + void initMod () override; - void mapInit (); + void mapInit () override; - void modFrame (); + void modFrame () override; - void freeMemory (); + void freeMemory () override; static edict_t *m_pResourceEntity; static edict_t *m_pPlayerResourceEntity; @@ -648,58 +634,93 @@ class CDODMod : public CBotMod static int m_iBombAreaAllies; static int m_iBombAreaAxis; - static vector m_BombWaypoints; - static vector m_BreakableWaypoints; + static std::vector m_BombWaypoints; + static std::vector m_BreakableWaypoints; // enemy // team static float fAttackProbLookUp[MAX_DOD_FLAGS+1][MAX_DOD_FLAGS+1]; }; -class CDODModDedicated : public CDODMod +typedef enum : std::uint8_t { -public: - CDODModDedicated() - { - setup("dod", "source dedicated server", MOD_DOD, BOTTYPE_DOD, "DOD"); - } -protected: - -}; + CS_MAP_DEATHMATCH = 0, // Generic Maps + CS_MAP_BOMBDEFUSAL, // Bomb Defusal maps + CS_MAP_HOSTAGERESCUE, // Hostage Rescue maps + CS_MAP_MAX +}eCSSMapType; class CCounterStrikeSourceMod : public CBotMod { public: CCounterStrikeSourceMod() { - setup("cstrike", "counter-strike source", MOD_CSS, BOTTYPE_CSS, "CSS"); + setup("cstrike", MOD_CSS, BOTTYPE_CSS, "CSS"); } - //void initMod (); + const char *getPlayerClass () override + { + return "CCSPlayer"; + } - //void mapInit (); + void initMod() override; + void mapInit() override; + bool checkWaypointForTeam(CWaypoint *pWpt, int iTeam) override; + static void onRoundStart(); + static void onFreezeTimeEnd(); + static void onBombPlanted(); + static bool isMapType(const eCSSMapType MapType) { return MapType == m_MapType; } + static bool isBombCarrier(const CBot *pBot); - //void entitySpawn ( edict_t *pEntity ); -protected: - // storing mod specific info - vector m_pHostages; - vector m_pBombPoints; - vector m_pRescuePoints; -}; + static float getRemainingRoundTime() + { + return m_fRoundStartTime + mp_roundtime.GetFloat() * 60.0f - engine->Time(); + } + static float getRemainingBombTime() + { + return m_fBombPlantedTime + mp_c4timer.GetFloat() - engine->Time(); + } -class CCounterStrikeSourceModDedicated : public CCounterStrikeSourceMod -{ -public: - CCounterStrikeSourceModDedicated() + static bool isBombPlanted() { - setup("cstrike","source dedicated server",MOD_CSS,BOTTYPE_CSS,"CSS"); + return m_bIsBombPlanted; } - //void initMod (); + static edict_t *getBomb() + { + return engine->PEntityOfEntIndex(m_hBomb.GetEntryIndex()); + } + static bool isBombDropped(); + static bool isBombDefused(); - //void mapInit (); + static bool wasBombFound() + { + return m_bBombWasFound; + } + + static void setBombFound(const bool set) + { + m_bBombWasFound = set; + } + static bool canHearPlantedBomb(const CBot *pBot); + static bool isScoped(const CBot *pBot); + static void updateHostages(); + static edict_t *getRandomHostage(); + static bool canRescueHostages(); + static std::vector getHostageVector() + { + return m_hHostages; + } //void entitySpawn ( edict_t *pEntity ); +private: + static eCSSMapType m_MapType; // Map Type + static float m_fRoundStartTime; // The time when the round started + static float m_fBombPlantedTime; // The time when the bomb was planted + static bool m_bIsBombPlanted; // Is the bomb planted? + static bool m_bBombWasFound; // Did the CTs locate the bomb? + static CBaseHandle m_hBomb; // The bomb. Experimental CBaseHandle instead of MyEHandle + static std::vector m_hHostages; // Vector with hostage handles }; class CTimCoopMod : public CBotMod @@ -707,7 +728,7 @@ class CTimCoopMod : public CBotMod public: CTimCoopMod() { - setup("SourceMods","timcoop",MOD_TIMCOOP,BOTTYPE_COOP,"HL2DM"); + setup("SourceMods",MOD_TIMCOOP,BOTTYPE_COOP,"HL2DM"); } //void initMod (); @@ -722,7 +743,7 @@ class CSvenCoop2Mod : public CBotMod public: CSvenCoop2Mod() { - setup("SourceMods","svencoop2",MOD_SVENCOOP2,BOTTYPE_COOP,"SVENCOOP2"); + setup("SourceMods",MOD_SVENCOOP2,BOTTYPE_COOP,"SVENCOOP2"); } //void initMod (); @@ -737,21 +758,8 @@ class CFortressForeverMod : public CBotMod public: CFortressForeverMod() { - setup("FortressForever", "SourceMods", MOD_FF, BOTTYPE_FF, "FF"); + setup("FortressForever", MOD_FF, BOTTYPE_FF, "FF"); } -private: - -}; - -class CFortressForeverModDedicated : public CBotMod -{ -public: - CFortressForeverModDedicated() - { - setup("FortressForever","source dedicated server",MOD_FF,BOTTYPE_FF,"FF"); - } -private: - }; class CHLDMSourceMod : public CBotMod @@ -759,7 +767,7 @@ class CHLDMSourceMod : public CBotMod public: CHLDMSourceMod() { - setup("hl1mp","half-life deathmatch source",MOD_HL1DMSRC,BOTTYPE_HL1DM,"HLDMSRC"); + setup("hl1mp",MOD_HL1DMSRC,BOTTYPE_HL1DM,"HLDMSRC"); } }; @@ -768,19 +776,29 @@ class CSynergyMod : public CBotMod public: CSynergyMod() { - setup("synergy","synergy",MOD_SYNERGY,BOTTYPE_COOP,"SYNERGY"); + setup("synergy",MOD_SYNERGY,BOTTYPE_SYN,"SYNERGY"); } - //void initMod (); + void initMod () override; + void mapInit () override; - //void mapInit (); + const char *getPlayerClass () override + { + return "CSynergyPlayer"; + } //void entitySpawn ( edict_t *pEntity ); + + static bool IsEntityLocked(edict_t *pEntity); + static bool IsCombineMinePlayerPlaced(edict_t *pMine); + static bool IsCombineMineDisarmed(edict_t *pMine); + static bool IsCombineMineArmed(edict_t *pMine); + static bool IsCombineMineHeldByPhysgun(edict_t *pMine); }; #define NEWENUM typedef enum { -typedef enum +typedef enum : std::uint8_t { TF_MAP_DM = 0, TF_MAP_CTF, @@ -789,12 +807,19 @@ typedef enum TF_MAP_CART, TF_MAP_CARTRACE, TF_MAP_ARENA, + TF_MAP_SAXTON, + TF_MAP_PIPEBALL, TF_MAP_KOTH, TF_MAP_SD, // special delivery : added 15 jul 12 TF_MAP_TR, TF_MAP_MVM, TF_MAP_RD, TF_MAP_BUMPERCARS, + TF_MAP_PD, // Player Destruction + TF_MAP_ZI, // Scream Fortress XV (Oct 9th, 2023) update for Zombie Infection maps - [APG]RoboCop[CL] + TF_MAP_PASS, //TODO: add support for those gamemodes [APG]RoboCop[CL] + TF_MAP_CPPL, // CP+PL Hybrid maps - RussiaTails + TF_MAP_GG, // GunGame maps - RussiaTails TF_MAP_MAX }eTFMapType; @@ -829,84 +854,38 @@ class CTeamControlPointMaster; class CTeamControlPoint; class CTeamRoundTimer; -class CAttribute -{ -public: - CAttribute ( const char *name, float fval ); - - void applyAttribute ( edict_t *pEdict ); - - const char *m_name; - float m_fval; -}; - -class CTF2Loadout -{ -public: - CTF2Loadout ( const char *pszClassname, int iIndex, int iQuality, int iMinLevel, int iMaxLevel ); - - //const char *getScript ( CEconItemView *script ); - //CEconItemView *getScript ( CEconItemView *other ); - void getScript ( CEconItemView *cscript ); - - void addAttribute ( int id, float fval ); - - unsigned int copyAttributesIntoArray ( CEconItemAttribute *pArray, void *pVTable = NULL ); - //void addAttribute ( CAttribute *attrib ); - - //void applyAttributes ( edict_t *pEdict ); - void applyAttributes ( CEconItemView *cscript ); - void applyAttributes ( CBaseEntity *pEnt ); - - void freeMemory (); - - int m_iIndex; -// int m_iSlot; - int m_iQuality; - bool m_bCanBeUsedInMedieval; - int m_iMinLevel; - int m_iMaxLevel; - const char *m_pszClassname; - //vector m_Attributes; - vector m_Attributes; - //CEconItemView m_ItemView; -}; - class CTeamFortress2Mod : public CBotMod { public: CTeamFortress2Mod() { - setup("tf","team fortress 2",MOD_TF2,BOTTYPE_TF2,"TF2"); + setup("tf",MOD_TF2,BOTTYPE_TF2,"TF2"); - m_pResourceEntity = NULL; - m_bBotCommand_NeedCheatsHack = true; + m_pResourceEntity = nullptr; } - void mapInit (); + void mapInit () override; - void modFrame (); + void modFrame () override; - bool isAreaOwnedByTeam (int iArea, int iTeam); + bool isAreaOwnedByTeam (int iArea, int iTeam) override; static void updatePointMaster (); - void clientCommand ( edict_t *pEntity, int argc, const char *pcmd, const char *arg1, const char *arg2 ); + void clientCommand ( edict_t *pEntity, int argc, const char *pcmd, const char *arg1, const char *arg2 ) override; - virtual const char *getPlayerClass () + const char *getPlayerClass () override { return "CTFPlayer"; } - void initMod (); - - static void roundStart (); + void initMod () override; - void freeMemory (); + static void roundStart (); // TODO: Needs implemented properly [APG]RoboCop[CL] static int getTeam ( edict_t *pEntity ); - static TF_Class getSpyDisguise ( edict_t *pPlayer ); + static TF_Class getSpyDisguise ( edict_t *pPlayer ); //TODO: not implemented? [APG]RoboCop[CL] static int getSentryLevel ( edict_t *pSentry ); static int getDispenserLevel ( edict_t *pDispenser ); @@ -915,33 +894,33 @@ class CTeamFortress2Mod : public CBotMod static bool isPayloadBomb ( edict_t *pEntity, int iTeam ); - static int getTeleporterWaypoint ( edict_t *pTele ); + static int getTeleporterWaypoint (const edict_t *pTele ); - bool isWaypointAreaValid ( int iWptArea, int iWptFlags ); + bool isWaypointAreaValid ( int iWptArea, int iWptFlags ) override; - static bool isSuddenDeath(void); + static bool isSuddenDeath(); - static bool isHealthKit ( edict_t *pEntity ); + static bool isHealthKit (const edict_t* pEntity); - static bool isAmmo ( edict_t *pEntity ); + static bool isAmmo (const edict_t* pEntity); - static int getArea (); // get current area of map + static int getArea (); // get current area of map // TODO: Needs implemented properly? [APG]RoboCop[CL] - static void setArea ( int area ) { m_iArea = area; } + static void setArea (const int area) { m_iArea = area; } static bool isSentry ( edict_t *pEntity, int iTeam, bool checkcarrying = false ); - static bool isTankBoss(edict_t *pEntity); + static bool isTankBoss(const edict_t* pEntity); static void checkMVMTankBoss(edict_t *pEntity); static bool isTeleporter ( edict_t *pEntity, int iTeam, bool checkcarrying = false ); - static void updateTeleportTime ( edict_t *pOwner ); - static float getTeleportTime ( edict_t *pOwner ); + static void updateTeleportTime (const edict_t* pOwner); + static float getTeleportTime (const edict_t* pOwner); static bool isTeleporterEntrance ( edict_t *pEntity, int iTeam, bool checkcarrying = false ); static bool isTeleporterExit ( edict_t *pEntity, int iTeam, bool checkcarrying = false ); - static inline bool isMapType ( eTFMapType iMapType ) { return iMapType == m_MapType; } + static bool isMapType (const eTFMapType iMapType) { return iMapType == m_MapType; } static bool isFlag ( edict_t *pEntity, int iTeam ); @@ -955,7 +934,7 @@ class CTeamFortress2Mod : public CBotMod static int getEnemyTeam ( int iTeam ); - static bool buildingNearby ( int iTeam, Vector vOrigin ); + static bool buildingNearby ( int iTeam, const Vector& vOrigin ); // Naris @ AlliedModders .net @@ -975,11 +954,11 @@ class CTeamFortress2Mod : public CBotMod static bool TF2_IsPlayerTaunting(edict_t *pPlayer); - static float TF2_GetPlayerSpeed(edict_t *pPlayer, TF_Class iClass ); + static float TF2_GetPlayerSpeed(edict_t *pPlayer, TF_Class iClass ); //TODO: not implemented? [APG]RoboCop[CL] - static void teleporterBuilt ( edict_t *pOwner, eEngiBuild type, edict_t *pBuilding ); + static void teleporterBuilt ( edict_t *pOwner, eEngiBuild type, edict_t *pBuilding ); //TODO: not implemented? [APG]RoboCop[CL] - static edict_t *getTeleporterExit ( edict_t *pTele ); + static edict_t *getTeleporterExit (const edict_t *pTele ); static void setPointOpenTime ( int time ); @@ -993,28 +972,28 @@ class CTeamFortress2Mod : public CBotMod static int getHighestScore (); - static edict_t *nearestDispenser ( Vector vOrigin, int team ); + static edict_t *nearestDispenser (const Vector& vOrigin, int team ); static void flagPickedUp (int iTeam, edict_t *pPlayer); static void flagReturned (int iTeam); - static void setAttackDefendMap ( bool bSet ) { m_bAttackDefendMap = bSet; } + static void setAttackDefendMap (const bool bSet) { m_bAttackDefendMap = bSet; } static bool isAttackDefendMap () { return m_bAttackDefendMap; } - void addWaypointFlags (edict_t *pPlayer, edict_t *pEdict, int *iFlags, int *iArea, float *fMaxDistance ); + void addWaypointFlags (edict_t *pPlayer, edict_t *pEdict, int *iFlags, int *iArea, float *fMaxDistance ) override; - void getTeamOnlyWaypointFlags ( int iTeam, int *iOn, int *iOff ); + void getTeamOnlyWaypointFlags ( int iTeam, int *iOn, int *iOff ) override; static bool getFlagLocation ( int iTeam, Vector *vec ); - static bool getDroppedFlagLocation ( int iTeam, Vector *vec ) + static bool getDroppedFlagLocation (const int iTeam, Vector *vec) { if ( iTeam == TF2_TEAM_BLUE ) { *vec = m_vFlagLocationBlue; return m_bFlagLocationValidBlue; } - else if ( iTeam == TF2_TEAM_RED ) + if ( iTeam == TF2_TEAM_RED ) { *vec = m_vFlagLocationRed; return m_bFlagLocationValidRed; @@ -1023,17 +1002,17 @@ class CTeamFortress2Mod : public CBotMod return false; } - static void flagDropped (int iTeam, Vector vLoc) + static void flagDropped (const int iTeam, const Vector& vLoc) { if ( iTeam == TF2_TEAM_BLUE ) { - m_pFlagCarrierBlue = NULL; + m_pFlagCarrierBlue = nullptr; m_vFlagLocationBlue = vLoc; m_bFlagLocationValidBlue = true; } else if ( iTeam == TF2_TEAM_RED ) { - m_pFlagCarrierRed = NULL; + m_pFlagCarrierRed = nullptr; m_vFlagLocationRed = vLoc; m_bFlagLocationValidRed = true; } @@ -1044,11 +1023,11 @@ class CTeamFortress2Mod : public CBotMod static void roundStarted () { m_bHasRoundStarted = true; - m_bRoundOver = false; + m_bRoundOver = false; m_iWinningTeam = 0; } - static void roundWon ( int iWinningTeam ) + static void roundWon (const int iWinningTeam) { m_bHasRoundStarted = false; m_bRoundOver = true; @@ -1056,154 +1035,148 @@ class CTeamFortress2Mod : public CBotMod m_iLastWinningTeam = m_iWinningTeam; } - static inline bool wonLastRound(int iTeam) + static bool wonLastRound(const int iTeam) { return m_iLastWinningTeam == iTeam; } - static inline bool isLosingTeam ( int iTeam ) + static bool isLosingTeam (const int iTeam) { - return !m_bHasRoundStarted && m_bRoundOver && m_iWinningTeam && (m_iWinningTeam != iTeam); + return !m_bHasRoundStarted && m_bRoundOver && m_iWinningTeam && m_iWinningTeam != iTeam; } static void roundReset (); - static inline bool isFlagCarrier (edict_t *pPlayer) + static bool isFlagCarrier (edict_t *pPlayer) { - return (m_pFlagCarrierBlue==pPlayer)||(m_pFlagCarrierRed==pPlayer); + return m_pFlagCarrierBlue==pPlayer||m_pFlagCarrierRed==pPlayer; } - static inline edict_t *getFlagCarrier (int iTeam) + static edict_t *getFlagCarrier (const int iTeam) { if ( iTeam == TF2_TEAM_BLUE ) return m_pFlagCarrierBlue; - else if ( iTeam == TF2_TEAM_RED ) + if ( iTeam == TF2_TEAM_RED ) return m_pFlagCarrierRed; - return NULL; + return nullptr; } - static bool isFlagCarried (int iTeam) + static bool isFlagCarried (const int iTeam) { if ( iTeam == TF2_TEAM_BLUE ) - return (m_pFlagCarrierBlue != NULL); - else if ( iTeam == TF2_TEAM_RED ) - return (m_pFlagCarrierRed != NULL); + return m_pFlagCarrierBlue != nullptr; + if ( iTeam == TF2_TEAM_RED ) + return m_pFlagCarrierRed != nullptr; return false; } - static void sapperPlaced(edict_t *pOwner,eEngiBuild type,edict_t *pSapper); - static void sapperDestroyed(edict_t *pOwner,eEngiBuild type,edict_t *pSapper); - static void sentryBuilt(edict_t *pOwner, eEngiBuild type, edict_t *pBuilding); - static void dispenserBuilt(edict_t *pOwner, eEngiBuild type, edict_t *pBuilding); + static void sapperPlaced(const edict_t* pOwner, eEngiBuild type, edict_t* pSapper); //TODO: all 4 lines not implemented? [APG]RoboCop[CL] + static void sapperDestroyed(edict_t *pOwner,eEngiBuild type, const edict_t *pSapper); + static void sentryBuilt(const edict_t* pOwner, eEngiBuild type, edict_t* pBuilding); + static void dispenserBuilt(const edict_t* pOwner, eEngiBuild type, edict_t* pBuilding); - static CWaypoint *getBestWaypointMVM ( CBot *pBot, int iFlags ); + static CWaypoint *getBestWaypointMVM (const CBot *pBot, int iFlags ); - static edict_t *getMySentryGun ( edict_t *pOwner ) + static edict_t *getMySentryGun (const edict_t* pOwner) { - int id = ENTINDEX(pOwner)-1; + const int id = ENTINDEX(pOwner)-1; if ( id>=0 ) { return m_SentryGuns[id].sentry.get(); } - return NULL; + return nullptr; } - static edict_t *getSentryOwner ( edict_t *pSentry ) + static edict_t *getSentryOwner (const edict_t *pSentry) { //for ( short int i = 1; i <= gpGlobals->maxClients; i ++ ) - for ( short int i = 0; i < MAX_PLAYERS; i ++ ) + for ( short int i = 0; i < RCBOT_MAXPLAYERS; i ++ ) { if ( m_SentryGuns[i].sentry.get() == pSentry ) return INDEXENT(i+1); } - return NULL; + return nullptr; } - static bool isMySentrySapped ( edict_t *pOwner ) + static bool isMySentrySapped (const edict_t* pOwner) { - int id = ENTINDEX(pOwner)-1; + const int id = ENTINDEX(pOwner)-1; if ( id>=0 ) { - return (m_SentryGuns[id].sentry.get()!=NULL)&&(m_SentryGuns[id].sapper.get()!=NULL); + return m_SentryGuns[id].sentry.get()!= nullptr &&m_SentryGuns[id].sapper.get()!= nullptr; } return false; } - static edict_t *getSentryGun ( int id ) + static edict_t *getSentryGun (const int id) { return m_SentryGuns[id].sentry.get(); } - static edict_t *getTeleEntrance ( int id ) + static edict_t *getTeleEntrance (const int id) { return m_Teleporters[id].entrance.get(); } - static bool isMyTeleporterSapped ( edict_t *pOwner ) + static bool isMyTeleporterSapped (const edict_t* pOwner) { - int id = ENTINDEX(pOwner)-1; + const int id = ENTINDEX(pOwner)-1; if ( id>=0 ) { - return ((m_Teleporters[id].exit.get()!=NULL)||(m_Teleporters[id].entrance.get()!=NULL))&&(m_Teleporters[id].sapper.get()!=NULL); + return (m_Teleporters[id].exit.get()!= nullptr ||m_Teleporters[id].entrance.get()!= nullptr)&&m_Teleporters[id].sapper.get()!= nullptr; } return false; } - static bool isMyDispenserSapped ( edict_t *pOwner ) + static bool isMyDispenserSapped (const edict_t* pOwner) { - int id = ENTINDEX(pOwner)-1; + const int id = ENTINDEX(pOwner)-1; if ( id>=0 ) { - return (m_Dispensers[id].disp.get()!=NULL)&&(m_Dispensers[id].sapper.get()!=NULL); + return m_Dispensers[id].disp.get()!= nullptr &&m_Dispensers[id].sapper.get()!= nullptr; } return false; } - static bool isSentrySapped ( edict_t *pSentry ) + static bool isSentrySapped (const edict_t *pSentry) { - unsigned int i; - - for ( i = 0; i < MAX_PLAYERS; i ++ ) + for (tf_sentry_t& m_SentryGun : m_SentryGuns) { - if ( m_SentryGuns[i].sentry.get() == pSentry ) - return m_SentryGuns[i].sapper.get()!=NULL; + if (m_SentryGun.sentry.get() == pSentry ) + return m_SentryGun.sapper.get()!= nullptr; } return false; } - static bool isTeleporterSapped ( edict_t *pTele ) + static bool isTeleporterSapped (const edict_t *pTele) { - unsigned int i; - - for ( i = 0; i < MAX_PLAYERS; i ++ ) + for (tf_tele_t& m_Teleporter : m_Teleporters) { - if ( (m_Teleporters[i].entrance.get() == pTele) || (m_Teleporters[i].exit.get() == pTele) ) - return m_Teleporters[i].sapper.get()!=NULL; + if (m_Teleporter.entrance.get() == pTele || m_Teleporter.exit.get() == pTele ) + return m_Teleporter.sapper.get()!= nullptr; } return false; } - static bool isDispenserSapped ( edict_t *pDisp ) + static bool isDispenserSapped (const edict_t *pDisp) { - unsigned int i; - - for ( i = 0; i < MAX_PLAYERS; i ++ ) + for (tf_disp_t& m_Dispenser : m_Dispensers) { - if ( m_Dispensers[i].disp.get() == pDisp ) - return m_Dispensers[i].sapper.get()!=NULL; + if (m_Dispenser.disp.get() == pDisp ) + return m_Dispenser.sapper.get()!= nullptr; } return false; @@ -1211,53 +1184,57 @@ class CTeamFortress2Mod : public CBotMod static edict_t *findResourceEntity (); - static void addCapDefender ( edict_t *pPlayer, int iCapIndex ) + static void addCapDefender (const edict_t* pPlayer, const int iCapIndex) { - m_iCapDefenders[iCapIndex] |= (1<<(ENTINDEX(pPlayer)-1)); + m_iCapDefenders[iCapIndex] |= 1 << (ENTINDEX(pPlayer) - 1); } - static void removeCapDefender ( edict_t *pPlayer, int iCapIndex ) + static void removeCapDefender (const edict_t* pPlayer, const int iCapIndex) { - m_iCapDefenders[iCapIndex] &= ~(1<<(ENTINDEX(pPlayer)-1)); + m_iCapDefenders[iCapIndex] &= ~(1 << (ENTINDEX(pPlayer) - 1)); } static void resetDefenders () { - memset(m_iCapDefenders,0,sizeof(int)*MAX_CONTROL_POINTS); + std::memset(m_iCapDefenders,0,sizeof(int)*MAX_CONTROL_POINTS); } static bool isDefending ( edict_t *pPlayer );//, int iCapIndex = -1 ); static bool isCapping ( edict_t *pPlayer );//, int iCapIndex = -1 ); - static void addCapper ( int cp, int capper ) + static void addCapper(const int cp, const int capper) { - if ( capper && (cp < MAX_CAP_POINTS) ) - m_Cappers[cp] |= (1<<(capper-1)); + assert(cp >= 0 && cp < MAX_CAP_POINTS); // Debug assertion [APG]RoboCop[CL] + + if (capper > 0 && cp >= 0 && cp < MAX_CAP_POINTS) + { + m_Cappers[cp] |= 1 << (capper - 1); + } } - static void removeCappers ( int cp ) + static void removeCappers (const int cp) { m_Cappers[cp] = 0; } static void resetCappers () { - memset(m_Cappers,0,sizeof(int)*MAX_CONTROL_POINTS); + std::memset(m_Cappers,0,sizeof(int)*MAX_CONTROL_POINTS); } - static int numPlayersOnTeam ( int iTeam, bool bAliveOnly = false ); + static int numPlayersOnTeam ( int iTeam, bool bAliveOnly = false ); //TODO: Experimental [APG]RoboCop[CL] static int numClassOnTeam ( int iTeam, int iClass ); static int getFlagCarrierTeam () { return m_iFlagCarrierTeam; } static bool canTeamPickupFlag_SD(int iTeam,bool bGetUnknown); - static edict_t *getBuildingOwner (eEngiBuild object, short index); - static edict_t *getBuilding (eEngiBuild object, edict_t *pOwner); + static edict_t *getBuildingOwner (eEngiBuild object, short index); //TODO: not implemented? [APG]RoboCop[CL] + static edict_t *getBuilding (eEngiBuild object, const edict_t* pOwner); //TODO: not implemented? [APG]RoboCop[CL] - static bool isBoss ( edict_t *pEntity, float *fFactor = NULL ); + static bool isBoss ( edict_t *pEntity, float *fFactor = nullptr); - static void initBoss ( bool bSummoned ) { m_bBossSummoned = bSummoned; m_pBoss = NULL; } + static void initBoss (const bool bSummoned) { m_bBossSummoned = bSummoned; m_pBoss = nullptr; } static bool isBossSummoned () { return m_bBossSummoned; } @@ -1268,12 +1245,12 @@ class CTeamFortress2Mod : public CBotMod static void findMediGun ( edict_t *pPlayer ); - bool checkWaypointForTeam(CWaypoint *pWpt, int iTeam); + bool checkWaypointForTeam(CWaypoint *pWpt, int iTeam) override; static bool isFlagAtDefaultState () { return bFlagStateDefault; } static void resetFlagStateToDefault() { bFlagStateDefault = true; } - static void setDontClearPoints ( bool bClear ) { m_bDontClearPoints = bClear; } + static void setDontClearPoints (const bool bClear) { m_bDontClearPoints = bClear; } static bool dontClearPoints () { return m_bDontClearPoints; } static CTFObjectiveResource m_ObjectiveResource; @@ -1300,15 +1277,11 @@ class CTeamFortress2Mod : public CBotMod return true; } - return ( getFlagLocation(TF2_TEAM_BLUE,vec) ); + return getFlagLocation(TF2_TEAM_BLUE,vec); } static bool isMedievalMode(); - static CTF2Loadout *findRandomWeaponLoadOutInSlot(int iclass, int islot ); - static CTF2Loadout *findRandomWeaponLoadOut ( int iclass, const char *classname ); - static CTF2Loadout *getRandomHat ( int iClass ); - private: @@ -1324,9 +1297,9 @@ class CTeamFortress2Mod : public CBotMod static MyEHandle m_pPayLoadBombRed; static MyEHandle m_pPayLoadBombBlue; - static tf_tele_t m_Teleporters[MAX_PLAYERS]; // used to let bots know who made a teleport ans where it goes - static tf_sentry_t m_SentryGuns[MAX_PLAYERS]; // used to let bots know if sentries have been sapped or not - static tf_disp_t m_Dispensers[MAX_PLAYERS]; // used to let bots know where friendly/enemy dispensers are + static tf_tele_t m_Teleporters[RCBOT_MAXPLAYERS]; // used to let bots know who made a teleport ans where it goes + static tf_sentry_t m_SentryGuns[RCBOT_MAXPLAYERS]; // used to let bots know if sentries have been sapped or not + static tf_disp_t m_Dispensers[RCBOT_MAXPLAYERS]; // used to let bots know where friendly/enemy dispensers are static int m_iArea; @@ -1354,7 +1327,7 @@ class CTeamFortress2Mod : public CBotMod static bool m_bBossSummoned; static bool bFlagStateDefault; - static MyEHandle pMediGuns[MAX_PLAYERS]; + static MyEHandle pMediGuns[RCBOT_MAXPLAYERS]; static bool m_bDontClearPoints; static bool m_bRoundOver; @@ -1375,31 +1348,9 @@ class CTeamFortress2Mod : public CBotMod static int m_iCapturePointWptID; static int m_iFlagPointWptID; - static void setupLoadOutWeapons ( void ); - static MyEHandle m_pNearestTankBoss; static float m_fNearestTankDistance; static Vector m_vNearestTankLocation; - // slots X nine classes - static vector m_pLoadoutWeapons[TF2_SLOT_MAX][9]; - //static vector m_pHats; - //static CTF2Loadout *m_StockWeapons[3][9]; //stock weapons - -}; - -class CTeamFortress2ModDedicated : public CTeamFortress2Mod -{ -public: - CTeamFortress2ModDedicated() - { -#ifdef __linux__ - setup("tf","orangebox",MOD_TF2,BOTTYPE_TF2,"TF2"); //bir3yk -#else - setup("tf", "source dedicated server", MOD_TF2, BOTTYPE_TF2, "TF2"); -#endif - } - -private: }; @@ -1408,54 +1359,38 @@ class CHalfLifeDeathmatchMod : public CBotMod public: CHalfLifeDeathmatchMod() { - setup("hl2mp", "half-life 2 deathmatch", MOD_HLDM2, BOTTYPE_HL2DM, "HL2DM"); + setup("hl2mp", MOD_HLDM2, BOTTYPE_HL2DM, "HL2DM"); } - void initMod (); + void initMod () override; - void mapInit (); + void mapInit () override; - bool playerSpawned ( edict_t *pPlayer ); + bool playerSpawned ( edict_t *pPlayer ) override; - static inline edict_t *getButtonAtWaypoint ( CWaypoint *pWaypoint ) + static edict_t *getButtonAtWaypoint (const CWaypoint *pWaypoint) { - for ( unsigned int i = 0; i < m_LiftWaypoints.size(); i ++ ) + for (edict_wpt_pair_t& m_LiftWaypoint : m_LiftWaypoints) { - if ( m_LiftWaypoints[i].pWaypoint == pWaypoint ) - return m_LiftWaypoints[i].pEdict; + if (m_LiftWaypoint.pWaypoint == pWaypoint ) + return m_LiftWaypoint.pEdict; } - return NULL; + return nullptr; } //void entitySpawn ( edict_t *pEntity ); private: - static vector m_LiftWaypoints; + static std::vector m_LiftWaypoints; }; -class CHalfLifeDeathmatchModDedicated : public CHalfLifeDeathmatchMod -{ -public: - CHalfLifeDeathmatchModDedicated() - { - setup("hl2mp", "source dedicated server", MOD_HLDM2, BOTTYPE_HL2DM, "HL2DM"); - } - - //void initMod (); - - //void mapInit (); - - //void entitySpawn ( edict_t *pEntity ); -protected: - -}; /* class CNaturalSelection2Mod : public CBotMod { public: CNaturalSelection2Mod() { - setup("ns2","natural selection 2",MOD_NS2,BOTTYPE_NS2); + setup("ns2",MOD_NS2,BOTTYPE_NS2); } // linux fix @@ -1497,16 +1432,14 @@ class CBotMods static void parseFile (); - static void createFile (); - static void readMods(); static void freeMemory (); - static CBotMod *getMod ( char *szModFolder, char *szSteamFolder ); + static CBotMod *getMod ( char *szModFolder ); private: - static vector m_Mods; + static std::vector m_Mods; }; #endif diff --git a/utils/RCBot2_meta/bot_mtrand.cpp b/utils/RCBot2_meta/bot_mtrand.cpp index 5fc6ce354..9d753d254 100644 --- a/utils/RCBot2_meta/bot_mtrand.cpp +++ b/utils/RCBot2_meta/bot_mtrand.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com // mtrand.h // C++ include file for MT19937, with initialization improved 2002/1/26. // Coded by Takuji Nishimura and Makoto Matsumoto. @@ -73,7 +75,10 @@ * version. * */ + #include "bot_mtrand.h" +#include + // non-inline function definitions and static member definitions cannot // reside in header file because of the risk of multiple declarations @@ -82,68 +87,93 @@ unsigned long MTRand_int32::state[n] = {0x0UL}; int MTRand_int32::p = 0; bool MTRand_int32::init = false; -static unsigned long init[4] = {0x123, 0x234, 0x345, 0x456}, length = 4; -MTRand_int32 irand(init,length); +static unsigned long init[] = { 0x123, 0x234, 0x345, 0x456 }; +static constexpr std::size_t length = sizeof(init) / sizeof(init[0]); // Manual array size calculation + +MTRand_int32 irand(init, length); static MTRand drand; double randomOne() { //irand is seeded - return static_cast(irand()) * (1. / 4294967296.); + return static_cast(irand()) * (1.0 / 4294967296.0); } -int randomInt ( int imin, int imax ) +int randomInt (const int imin, const int imax) { // quicker if (imin == imax) return imin; - return static_cast(imin + (int)(randomOne()*((float)(imax - imin) + 0.99f))); + return imin + static_cast(randomOne() * (static_cast(imax - imin) + 0.99f)); //return (int)(imin + (int)(drand()*((float)(imax-imin)+0.99f))); } -float randomFloat ( float fmin, float fmax ) +float randomFloat (const float fmin, const float fmax) { - return static_cast(fmin + ((randomOne())*(fmax - fmin))); + return static_cast(fmin + randomOne()*(fmax - fmin)); } void MTRand_int32::gen_state() { // generate new state vector - for (int i = 0; i < (n - m); ++i) - state[i] = state[i + m] ^ twiddle(state[i], state[i + 1]); - for (int i = n - m; i < (n - 1); ++i) - state[i] = state[i + m - n] ^ twiddle(state[i], state[i + 1]); + for (int i = 0; i < n - m; ++i) + state[i] = state[i + m] ^ twiddle(state[i], state[i + 1]); + for (int i = n - m; i < n - 1; ++i) + state[i] = state[i + m - n] ^ twiddle(state[i], state[i + 1]); state[n - 1] = state[m - 1] ^ twiddle(state[n - 1], state[0]); p = 0; // reset position } -void MTRand_int32::seed(unsigned long s) +void MTRand_int32::seed(const unsigned long s) { // init by 32 bit seed - state[0] = s & 0xFFFFFFFFUL; // for > 32 bit machines + state[0] = s & BIT_MASK_32; // for > 32 bit machines for (int i = 1; i < n; ++i) { - state[i] = 1812433253UL * (state[i - 1] ^ (state[i - 1] >> 30)) + i; + state[i] = 1812433253UL * (state[i - 1] ^ state[i - 1] >> 30) + i; // see Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier // in the previous versions, MSBs of the seed affect only MSBs of the array state // 2002/01/09 modified by Makoto Matsumoto - state[i] &= 0xFFFFFFFFUL; // for > 32 bit machines + state[i] &= BIT_MASK_32; // for > 32 bit machines } p = n; // force gen_state() to be called for next random number } -void MTRand_int32::seed(const unsigned long* array, int size) { // init by array - seed(19650218UL); - int i = 1, j = 0; - for (int k = ((n > size) ? n : size); k; --k) { - state[i] = (state[i] ^ ((state[i - 1] ^ (state[i - 1] >> 30)) * 1664525UL)) - + array[j] + j; // non linear - state[i] &= 0xFFFFFFFFUL; // for > 32 bit machines - ++j; j %= size; - if ((++i) == n) { state[0] = state[n - 1]; i = 1; } - } - for (int k = n - 1; k; --k) { - state[i] = (state[i] ^ ((state[i - 1] ^ (state[i - 1] >> 30)) * 1566083941UL)) - i; - state[i] &= 0xFFFFFFFFUL; // for > 32 bit machines - if ((++i) == n) { state[0] = state[n - 1]; i = 1; } - } - state[0] = 0x80000000UL; // MSB is 1; assuring non-zero initial array - p = n; // force gen_state() to be called for next random number +void MTRand_int32::seed(const unsigned long* array, const int size) const +{ // init by array + seed(19650218UL); + int i = 1, j = 0; + for (int k = n > size ? n : size; k; --k) { + state[i] = (state[i] ^ (state[i - 1] ^ (state[i - 1] >> 30)) * 1664525UL) + + array[j] + j; // non linear + state[i] &= BIT_MASK_32; // for > 32 bit machines + ++j; j %= size; + if (++i == n) { state[0] = state[n - 1]; i = 1; } + } + for (int k = n - 1; k; --k) { + state[i] = (state[i] ^ (state[i - 1] ^ (state[i - 1] >> 30)) * 1566083941UL) - i; + state[i] &= BIT_MASK_32; // for > 32 bit machines + if (++i == n) { state[0] = state[n - 1]; i = 1; } + } + state[0] = MSB_MASK; // MSB is 1; assuring non-zero initial array + p = n; // force gen_state() to be called for next random number +} + +//TODO: 64-bit generator? [APG]RoboCop[CL] +/*void MTRand_int64::seed(const unsigned long long* array, const int size) const +{ // init by array for 64-bit generator + seed(19650218ULL); + size_t i = 1, j = 0; + for (size_t k = n > size ? n : size; k; --k) { + state[i] = (state[i] ^ (state[i - 1] ^ (state[i - 1] >> 30)) * 6364136223846793005ULL) + + array[j] + j; // non linear + state[i] &= BIT_MASK_64; // for > 64 bit machines + ++j; j %= size; + if (++i == n) { state[0] = state[n - 1]; i = 1; } + } + for (size_t k = n - 1; k; --k) { + state[i] = (state[i] ^ (state[i - 1] ^ (state[i - 1] >> 30)) * 3935559000370003845ULL) - i; + state[i] &= BIT_MASK_64; // for > 64 bit machines + if (++i == n) { state[0] = state[n - 1]; i = 1; } + } + state[0] = MSB_MASK_64; // MSB is 1; assuring non-zero initial array + p = n; // force gen_state() to be called for next random number } +*/ \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_mtrand.h b/utils/RCBot2_meta/bot_mtrand.h index 651e40c77..5755bd5d0 100644 --- a/utils/RCBot2_meta/bot_mtrand.h +++ b/utils/RCBot2_meta/bot_mtrand.h @@ -74,6 +74,8 @@ #ifndef MTRAND_H #define MTRAND_H +#include + int randomInt ( int imin, int imax ); float randomFloat ( float fmin, float fmax ); @@ -82,36 +84,45 @@ class MTRand_int32 { // Mersenne Twister random number generator // default constructor: uses default seed only if this is the first instance MTRand_int32() { if (!init) seed(5489UL); init = true; } // constructor with 32 bit int as seed - MTRand_int32(unsigned long s) { seed(s); init = true; } + MTRand_int32(const unsigned long s) { seed(s); init = true; } // constructor with array of size 32 bit ints as seed - MTRand_int32(const unsigned long* array, int size) { seed(array, size); init = true; } + MTRand_int32(const unsigned long* array, const int size) { seed(array, size); init = true; } +// make copy constructor and assignment operator unavailable, they don't make sense + MTRand_int32(const MTRand_int32&) = delete; // copy constructor not defined + void operator=(const MTRand_int32&) = delete; // assignment operator not defined // the two seed functions - void seed(unsigned long); // seed with 32 bit integer - void seed(const unsigned long*, int size); // seed with array +static void seed(unsigned long); // seed with 32 bit integer + void seed(const unsigned long*, int size) const; // seed with array // overload operator() to make this a generator (functor) unsigned long operator()() { return rand_int32(); } // 2007-02-11: made the destructor virtual; thanks "double more" for pointing this out - virtual ~MTRand_int32() {} // destructor + virtual ~MTRand_int32() = default; // destructor protected: // used by derived classes, otherwise not accessible; use the ()-operator unsigned long rand_int32(); // generate 32 bit random integer private: - static const int n = 624, m = 397; // compile time constants + static constexpr int n = 624, m = 397; // compile time constants // the variables below are static (no duplicates can exist) static unsigned long state[n]; // state vector array static int p; // position in state array static bool init; // true if init function is called // private functions used to generate the pseudo random numbers - unsigned long twiddle(unsigned long, unsigned long); // used by gen_state() +static unsigned long twiddle(unsigned long, unsigned long); // used by gen_state() void gen_state(); // generate new state -// make copy constructor and assignment operator unavailable, they don't make sense - MTRand_int32(const MTRand_int32&); // copy constructor not defined - void operator=(const MTRand_int32&); // assignment operator not defined }; +// Mask to isolate the most significant bit (MSB) in a 32-bit unsigned integer +constexpr std::uint32_t MSB_MASK = 0x80000000UL; +// Mask to represent all bits set in a 32-bit unsigned integer +constexpr std::uint32_t BIT_MASK_32 = 0xFFFFFFFFUL; +// Mask for all bits except the MSB +constexpr std::uint32_t LSB_MASK = 0x7FFFFFFFUL; +// Mersenne Twister constant +constexpr std::uint32_t TEMPERING_CONSTANT = 0x9908B0DFUL; + // inline for speed, must therefore reside in header file -inline unsigned long MTRand_int32::twiddle(unsigned long u, unsigned long v) { - return (((u & 0x80000000UL) | (v & 0x7FFFFFFFUL)) >> 1) - ^ ((v & 1UL) ? 0x9908B0DFUL : 0x0UL); +inline unsigned long MTRand_int32::twiddle(const unsigned long u, const unsigned long v) { + return ((u & MSB_MASK) | (v & LSB_MASK)) >> 1 + ^ (v & 1UL ? TEMPERING_CONSTANT : 0x0UL); } inline unsigned long MTRand_int32::rand_int32() { // generate 32 bit random int @@ -119,67 +130,76 @@ inline unsigned long MTRand_int32::rand_int32() { // generate 32 bit random int // gen_state() is split off to be non-inline, because it is only called once // in every 624 calls and otherwise irand() would become too big to get inlined unsigned long x = state[p++]; - x ^= (x >> 11); - x ^= (x << 7) & 0x9D2C5680UL; - x ^= (x << 15) & 0xEFC60000UL; - return x ^ (x >> 18); + x ^= x >> 11; + x ^= x << 7 & 0x9D2C5680UL; + x ^= x << 15 & 0xEFC60000UL; + return x ^ x >> 18; } // generates double floating point numbers in the half-open interval [0, 1) class MTRand : public MTRand_int32 { public: - MTRand() : MTRand_int32() {} - MTRand(unsigned long seed) : MTRand_int32(seed) {} - MTRand(const unsigned long* seed, int size) : MTRand_int32(seed, size) {} - ~MTRand() {} + MTRand() = default; + MTRand(const unsigned long seed) : MTRand_int32(seed) {} + MTRand(const unsigned long* seed, const int size) : MTRand_int32(seed, size) {} + ~MTRand() override = default; + + MTRand(const MTRand&) = delete; // copy constructor not defined + void operator=(const MTRand&) = delete; // assignment operator not defined + double operator()() { - return static_cast(rand_int32()) * (1. / 4294967296.); } // divided by 2^32 + return static_cast(rand_int32()) * (1.0 / 4294967296.0); } // divided by 2^32 private: - MTRand(const MTRand&); // copy constructor not defined - void operator=(const MTRand&); // assignment operator not defined }; // generates double floating point numbers in the closed interval [0, 1] class MTRand_closed : public MTRand_int32 { public: - MTRand_closed() : MTRand_int32() {} - MTRand_closed(unsigned long seed) : MTRand_int32(seed) {} - MTRand_closed(const unsigned long* seed, int size) : MTRand_int32(seed, size) {} - ~MTRand_closed() {} + MTRand_closed() = default; + MTRand_closed(const unsigned long seed) : MTRand_int32(seed) {} + MTRand_closed(const unsigned long* seed, const int size) : MTRand_int32(seed, size) {} + ~MTRand_closed() override = default; + + MTRand_closed(const MTRand_closed&) = delete; // copy constructor not defined + void operator=(const MTRand_closed&) = delete; // assignment operator not defined + double operator()() { - return static_cast(rand_int32()) * (1. / 4294967295.); } // divided by 2^32 - 1 + return static_cast(rand_int32()) * (1.0 / 4294967295.0); } // divided by 2^32 - 1 private: - MTRand_closed(const MTRand_closed&); // copy constructor not defined - void operator=(const MTRand_closed&); // assignment operator not defined + }; // generates double floating point numbers in the open interval (0, 1) class MTRand_open : public MTRand_int32 { public: - MTRand_open() : MTRand_int32() {} - MTRand_open(unsigned long seed) : MTRand_int32(seed) {} - MTRand_open(const unsigned long* seed, int size) : MTRand_int32(seed, size) {} - ~MTRand_open() {} + MTRand_open() = default; + MTRand_open(const unsigned long seed) : MTRand_int32(seed) {} + MTRand_open(const unsigned long* seed, const int size) : MTRand_int32(seed, size) {} + ~MTRand_open() override = default; + + MTRand_open(const MTRand_open&) = delete; // copy constructor not defined + void operator=(const MTRand_open&) = delete; // assignment operator not defined + double operator()() { - return (static_cast(rand_int32()) + .5) * (1. / 4294967296.); } // divided by 2^32 + return (static_cast(rand_int32()) + 0.5) * (1.0 / 4294967296.0); } // divided by 2^32 private: - MTRand_open(const MTRand_open&); // copy constructor not defined - void operator=(const MTRand_open&); // assignment operator not defined }; // generates 53 bit resolution doubles in the half-open interval [0, 1) class MTRand53 : public MTRand_int32 { public: - MTRand53() : MTRand_int32() {} - MTRand53(unsigned long seed) : MTRand_int32(seed) {} - MTRand53(const unsigned long* seed, int size) : MTRand_int32(seed, size) {} - ~MTRand53() {} + MTRand53() = default; + MTRand53(const unsigned long seed) : MTRand_int32(seed) {} + MTRand53(const unsigned long* seed, const int size) : MTRand_int32(seed, size) {} + ~MTRand53() override = default; + + MTRand53(const MTRand53&) = delete; // copy constructor not defined + void operator=(const MTRand53&); // assignment operator not defined + double operator()() { - return (static_cast(rand_int32() >> 5) * 67108864. + - static_cast(rand_int32() >> 6)) * (1. / 9007199254740992.); } + return (static_cast(rand_int32() >> 5) * 67108864.0 + + static_cast(rand_int32() >> 6)) * (1.0 / 9007199254740992.0); } private: - MTRand53(const MTRand53&); // copy constructor not defined - void operator=(const MTRand53&); // assignment operator not defined }; #endif // MTRAND_H diff --git a/utils/RCBot2_meta/bot_navigator.h b/utils/RCBot2_meta/bot_navigator.h index c8a472c58..fb2fd1484 100644 --- a/utils/RCBot2_meta/bot_navigator.h +++ b/utils/RCBot2_meta/bot_navigator.h @@ -31,27 +31,31 @@ #ifndef __RCBOT_NAVIGATOR_H__ #define __RCBOT_NAVIGATOR_H__ -#include "bot_genclass.h" - #include #include -using namespace std; +#include #include "bot.h" #include "bot_waypoint.h" #include "bot_belief.h" -#include "bot_genclass.h" -class CNavMesh; +class CNavMesh { +public: + // other methods... + static void freeMemory() + { + // implementation of freeing memory + } +}; class CWaypointVisibilityTable; -#define MAX_BELIEF 200.0f +constexpr float MAX_BELIEF = 200.0f; class INavigatorNode { public: - inline Vector getOrigin () { return m_vOrigin; } + Vector getOrigin () { return m_vOrigin; } protected: Vector m_vOrigin; }; @@ -59,10 +63,12 @@ class INavigatorNode class IBotNavigator { public: + virtual ~IBotNavigator() = default; virtual void init () = 0; // returns true when working out route finishes, not if successful - virtual bool workRoute ( Vector vFrom, Vector vTo, bool *bFail, bool bRestart = true, bool bNoInterruptions = false, int iGoalId = -1, int iConditions = 0, int iDangerId = -1 ) = 0; + virtual bool workRoute (const Vector& vFrom, const Vector& vTo, bool* bFail, bool bRestart = true, bool bNoInterruptions = false, int iGoalId = + -1, int iConditions = 0, int iDangerId = -1) = 0; virtual void rollBackPosition () = 0; @@ -72,7 +78,7 @@ class IBotNavigator virtual bool getNextRoutePoint ( Vector *vPoint ) = 0; - inline Vector getPreviousPoint () { return m_vPreviousPoint; } + Vector getPreviousPoint () { return m_vPreviousPoint; } virtual bool hasNextPoint () = 0; @@ -84,12 +90,12 @@ class IBotNavigator virtual void updatePosition () = 0; - virtual bool canGetTo ( Vector vOrigin ) = 0; + virtual bool canGetTo (const Vector& vOrigin) = 0; virtual int getCurrentFlags () { return 0; } virtual int getPathFlags ( int iPath ) { return 0; } - virtual float distanceTo ( Vector vOrigin ) = 0; + virtual float distanceTo (const Vector& vOrigin) = 0; virtual float distanceTo ( CWaypoint *pWaypoint ) = 0; @@ -103,82 +109,92 @@ class IBotNavigator virtual void clear () = 0; - virtual void getFailedGoals (dataUnconstArray **goals) = 0; + virtual void getFailedGoals (WaypointList **goals) = 0; - inline Vector getGoalOrigin () { return m_vGoal; } + Vector getGoalOrigin () { return m_vGoal; } virtual bool nextPointIsOnLadder () { return false; } - virtual bool beliefLoad ( ) { return false; }; + virtual bool beliefLoad ( ) { return false; } - virtual bool beliefSave ( bool bOverride = false ) { return false; }; + virtual bool beliefSave ( bool bOverride = false ) { return false; } - virtual void belief ( Vector origin, Vector vOther, float fBelief, float fStrength, BotBelief iType ) = 0; + virtual void belief (const Vector& origin, const Vector& vOther, float fBelief, float fStrength, BotBelief iType) = 0; // nearest cover position to vOrigin only - virtual bool getCoverPosition ( Vector vCoverOrigin, Vector *vCover ) = 0; + virtual bool getCoverPosition (const Vector& vCoverOrigin, Vector* vCover) = 0; // nearest cover postion to both vectors - virtual bool getHideSpotPosition ( Vector vCoverOrigin, Vector *vCover ) = 0; + virtual bool getHideSpotPosition (const Vector& vCoverOrigin, Vector* vCover) = 0; virtual float getCurrentBelief ( ) { return 0; } virtual float getBelief ( int index ) { return 0; } - virtual void beliefOne ( int iWptIndex, BotBelief iBeliefType, float fDist ) { return; } + virtual void beliefOne ( int iWptIndex, BotBelief iBeliefType, float fDist ) { + } virtual int numPaths ( ) { return 0; } - virtual Vector getPath ( int pathid ) { return Vector(0,0,0); } + virtual Vector getPath ( int pathid ) { return {0,0,0}; } virtual bool randomDangerPath (Vector *vec) { return false; } - bool getDangerPoint ( Vector *vec ) { *vec = m_bDangerPoint ? m_vDangerPoint : Vector(0,0,0); return m_bDangerPoint; } + bool getDangerPoint ( Vector *vec ) const + { *vec = m_bDangerPoint ? m_vDangerPoint : Vector(0,0,0); return m_bDangerPoint; } - bool wantToLoadBelief () { return m_bLoadBelief; } + bool wantToLoadBelief () const { return m_bLoadBelief; } virtual bool wantToSaveBelief () { return false; } - float getGoalDistance () { return m_fGoalDistance; } + float getGoalDistance () const { return m_fGoalDistance; } - static const int MAX_PATH_TICKS = 200; + static constexpr int MAX_PATH_TICKS = 200; protected: Vector m_vGoal; - float m_fGoalDistance; + float m_fGoalDistance = 0.0f; Vector m_vPreviousPoint; Vector m_vDangerPoint; - bool m_bDangerPoint; - short int m_iBeliefTeam; - bool m_bBeliefChanged; - bool m_bLoadBelief; + bool m_bDangerPoint = false; + int m_iBeliefTeam = 0; + bool m_bBeliefChanged = false; + bool m_bLoadBelief = false; }; -#define FL_ASTAR_CLOSED 1 -#define FL_ASTAR_PARENT 2 -#define FL_ASTAR_OPEN 4 -#define FL_HEURISTIC_SET 8 +enum : std::uint8_t +{ + FL_ASTAR_CLOSED = 1, + FL_ASTAR_PARENT = 2, + FL_ASTAR_OPEN = 4, + FL_HEURISTIC_SET = 8 +}; class AStarNode { public: - AStarNode() { memset(this,0,sizeof(AStarNode)); } + AStarNode() { std::memset(this,0,sizeof(AStarNode)); } /////////////////////////////////////////////////////// - inline void close () { setFlag(FL_ASTAR_CLOSED); } - inline void unClose () { removeFlag(FL_ASTAR_CLOSED); } - inline bool isOpen () { return hasFlag(FL_ASTAR_OPEN); } - inline void unOpen () { removeFlag(FL_ASTAR_OPEN); } - inline bool isClosed () { return hasFlag(FL_ASTAR_CLOSED); } - inline void open () { setFlag(FL_ASTAR_OPEN); } + void close () { setFlag(FL_ASTAR_CLOSED); } + void unClose () { removeFlag(FL_ASTAR_CLOSED); } + bool isOpen () const { return hasFlag(FL_ASTAR_OPEN); } + void unOpen () { removeFlag(FL_ASTAR_OPEN); } + bool isClosed () const { return hasFlag(FL_ASTAR_CLOSED); } + void open () { setFlag(FL_ASTAR_OPEN); } ////////////////////////////////////////////////////// - inline void setHeuristic ( float fHeuristic ) { m_fHeuristic = fHeuristic; setFlag(FL_HEURISTIC_SET); } - inline bool heuristicSet () { return hasFlag(FL_HEURISTIC_SET); } - inline const float getHeuristic () { return m_fHeuristic; } const - + void setHeuristic (const float fHeuristic) { m_fHeuristic = fHeuristic; setFlag(FL_HEURISTIC_SET); } + bool heuristicSet () const { return hasFlag(FL_HEURISTIC_SET); } + float getHeuristic() const { return m_fHeuristic; } + //////////////////////////////////////////////////////// - inline void setFlag ( int iFlag ) { m_iFlags |= iFlag; } - inline bool hasFlag ( int iFlag ) { return ((m_iFlags & iFlag) == iFlag); } - inline void removeFlag ( int iFlag ) { m_iFlags &= ~iFlag; } + void setFlag(const int iFlag) { m_iFlags |= iFlag; } + bool hasFlag (const int iFlag) const { return (m_iFlags & iFlag) == iFlag; } + void removeFlag (const int iFlag) { m_iFlags &= ~iFlag; } ///////////////////////////////////////////////////////// - inline int getParent () { if ( hasFlag(FL_ASTAR_PARENT) ) return m_iParent; else return -1; } - inline void setParent ( short int iParent ) + int getParent () const + { + if ( hasFlag(FL_ASTAR_PARENT) ) return m_iParent; + return -1; + } + + void setParent (const int iParent) { m_iParent = iParent; @@ -188,21 +204,21 @@ class AStarNode setFlag(FL_ASTAR_PARENT); } //////////////////////////////////////////////////////// - inline const float getCost () { return m_fCost; } const - inline void setCost ( float fCost ) { m_fCost = fCost; } + float getCost () const { return m_fCost; } + void setCost(const float fCost) { m_fCost = fCost; } //////////////////////////////////////////////////////// // for comparison - bool precedes ( AStarNode *other ) const + bool precedes (const AStarNode *other) const { - return (m_fCost+m_fHeuristic) < (other->getCost() + other->getHeuristic()); + return m_fCost+m_fHeuristic < other->getCost() + other->getHeuristic(); } - void setWaypoint ( int iWpt ) { m_iWaypoint = iWpt; } - inline int getWaypoint () { return m_iWaypoint; } + void setWaypoint (const int iWpt) { m_iWaypoint = iWpt; } + int getWaypoint () const { return m_iWaypoint; } private: float m_fCost; float m_fHeuristic; unsigned char m_iFlags; - short int m_iParent; + int m_iParent; int m_iWaypoint; }; // Insertion sorted list @@ -212,7 +228,7 @@ class AStarListNode AStarListNode ( AStarNode *data ) { m_Data = data; - m_Next = NULL; + m_Next = nullptr; } AStarNode *m_Data; AStarListNode *m_Next; @@ -223,27 +239,27 @@ class AStarOpenList public: AStarOpenList() { - m_Head = NULL; + m_Head = nullptr; } - bool empty () + bool empty () const { - return (m_Head==NULL); + return m_Head== nullptr; } - AStarNode *top () + AStarNode *top () const { - if ( m_Head == NULL ) - return NULL; + if ( m_Head == nullptr) + return nullptr; return m_Head->m_Data; } void pop () { - if ( m_Head != NULL ) + if ( m_Head != nullptr) { - AStarListNode *t = m_Head; + const AStarListNode *t = m_Head; m_Head = m_Head->m_Next; @@ -255,10 +271,8 @@ class AStarOpenList void add ( AStarNode *data ) { AStarListNode *newNode = new AStarListNode(data); - AStarListNode *t; - AStarListNode *p; - if ( m_Head == NULL ) + if ( m_Head == nullptr) m_Head = newNode; else { @@ -269,10 +283,10 @@ class AStarOpenList } else { - p = m_Head; - t = m_Head->m_Next; + AStarListNode* p = m_Head; + AStarListNode* t = m_Head->m_Next; - while ( t != NULL ) + while ( t != nullptr) { if ( data->precedes(t->m_Data) ) { @@ -285,26 +299,24 @@ class AStarOpenList t = t->m_Next; } - if ( t == NULL ) + if ( t == nullptr) p->m_Next = newNode; } } } - void destroy () + void destroy() { - AStarListNode *t; - - while ( m_Head != NULL ) + while (m_Head != nullptr) { - t = m_Head; + const AStarListNode* t = m_Head; m_Head = m_Head->m_Next; delete t; - t = NULL; + t = nullptr; } - m_Head = NULL; + //m_Head = nullptr; } private: @@ -317,7 +329,7 @@ struct AstarNodeCompare : binary_function // Other stuff... bool operator()(AStarNode* x, AStarNode* y) const { - return y->betterCost(x); + return y->betterCost(x); } }; @@ -326,16 +338,16 @@ class AStarOpenList : public vector AstarNodeCompare comp; public: AStarOpenList(AstarNodeCompare cmp = AstarNodeCompare()) : comp(cmp) { - make_heap(begin(), end(), comp); + make_heap(begin(), end(), comp); } AStarNode* top() { return front(); } void push(AStarNode* x) { - push_back(x); - push_heap(begin(), end(), comp); + emplace_back(x); + push_heap(begin(), end(), comp); } void pop() { - pop_heap(begin(), end(), comp); - pop_back(); + pop_heap(begin(), end(), comp); + pop_back(); } };*/ @@ -343,22 +355,25 @@ class AStarOpenList : public vector /* bool operator<( const AStarNode & A, const AStarNode & B ) { - return A.betterCost(&B); + return A.betterCost(&B); } bool operator<( const AStarNode * A, const AStarNode * B ) { - return A->betterCost(B); + return A->betterCost(B); }*/ -#define WPT_SEARCH_AVOID_SENTRIES 1 -#define WPT_SEARCH_AVOID_SNIPERS 2 -#define WPT_SEARCH_AVOID_TEAMMATE 4 +enum : std::uint8_t +{ + WPT_SEARCH_AVOID_SENTRIES = 1, + WPT_SEARCH_AVOID_SNIPERS = 2, + WPT_SEARCH_AVOID_TEAMMATE = 4 +}; typedef struct { - short int iFrom; - short int iTo; + int iFrom; + int iTo; bool bValid; bool bSkipped; }failedpath_t; @@ -366,104 +381,107 @@ typedef struct class CWaypointNavigator : public IBotNavigator { public: - CWaypointNavigator ( CBot *pBot ) - { - init(); - m_pBot = pBot; - m_fNextClearFailedGoals = 0; + CWaypointNavigator(CBot* pBot) + : curr(nullptr), succ(nullptr) // Initialize pointers to nullptr + { + CWaypointNavigator::init(); + m_pBot = pBot; + m_fNextClearFailedGoals = 0.0f; m_bDangerPoint = false; m_iBeliefTeam = -1; m_bLoadBelief = true; m_bBeliefChanged = false; - memset(&m_lastFailedPath,0,sizeof(failedpath_t)); + std::memset(&m_lastFailedPath, 0, sizeof(failedpath_t)); } - void init (); + void init () override; - CWaypoint *chooseBestFromBelief ( dataUnconstArray *goals, bool bHighDanger = false, int iSearchFlags = 0, int iTeam = 0); - CWaypoint *chooseBestFromBeliefBetweenAreas ( dataUnconstArray *goals, bool bHighDanger = false, bool bIgnoreBelief = false ); + CWaypoint *chooseBestFromBelief (const std::vector& goals, bool bHighDanger = false, int iSearchFlags = 0, int iTeam = 0) const; + CWaypoint *chooseBestFromBeliefBetweenAreas (const std::vector& goals, bool bHighDanger = false, bool bIgnoreBelief = false) const; - float getNextYaw (); + float getNextYaw () override; - bool workRoute ( Vector vFrom, Vector vTo, bool *bFail, bool bRestart = true, bool bNoInterruptions = false, int iGoalId = -1, int iConditions = 0, int iDangerId = -1 ); + bool workRoute (const Vector& vFrom, const Vector& vTo, bool* bFail, bool bRestart = true, bool bNoInterruptions = false, int iGoalId = + -1, int iConditions = 0, int iDangerId = -1) override; - bool getNextRoutePoint ( Vector *vPoint ); + bool getNextRoutePoint ( Vector *vPoint ) override; - void clear (); + void clear () override; - Vector getNextPoint (); + Vector getNextPoint () override; - void updatePosition (); + void updatePosition () override; - float getBelief ( int index ) { if ( index >= 0 ) return m_fBelief[index]; return 0; } + float getBelief (const int index) override + { if ( index >= 0 ) return m_fBelief[index]; return 0; } - void failMove (); + void failMove () override; - bool hasNextPoint (); + bool hasNextPoint () override; - void freeMapMemory (); + void freeMapMemory () override; - void freeAllMemory (); + void freeAllMemory () override; - bool canGetTo ( Vector vOrigin ); + bool canGetTo (const Vector& vOrigin) override; - bool routeFound (); + bool routeFound () override; - void rollBackPosition (); + void rollBackPosition () override; - bool nextPointIsOnLadder (); + bool nextPointIsOnLadder () override; void open ( AStarNode *pNode ); AStarNode *nextNode (); - float distanceTo ( Vector vOrigin ); + float distanceTo (const Vector& vOrigin) override; - float distanceTo ( CWaypoint *pWaypoint ); + float distanceTo ( CWaypoint *pWaypoint ) override; - Vector getCoverOrigin ( Vector vCover ); + Vector getCoverOrigin ( Vector vCover ); // TODO: Needs implemented properly [APG]RoboCop[CL] void clearOpenList (); - float getCurrentBelief ( ); + float getCurrentBelief ( ) override; //virtual void goBack(); - void belief ( Vector origin, Vector vOther, float fBelief, float fStrength, BotBelief iType ); + void belief (const Vector& vOrigin, const Vector& vOther, float fBelief, float fStrength, BotBelief iType) override; //TODO: not implemented? [APG]RoboCop[CL] - void beliefOne ( int iWptIndex, BotBelief iBeliefType, float fDist ); + void beliefOne ( int iWptIndex, BotBelief iBeliefType, float fDist ) override; //TODO: not implemented? [APG]RoboCop[CL] // nearest cover position to vOrigin only - bool getCoverPosition ( Vector vCoverOrigin, Vector *vCover ); + bool getCoverPosition (const Vector& vCoverOrigin, Vector* vCover) override; // nearest cover postion to both vectors - bool getHideSpotPosition ( Vector vCoverOrigin, Vector *vCover ); + bool getHideSpotPosition (const Vector& vCoverOrigin, Vector* vCover) override; - void getFailedGoals ( dataUnconstArray **goals) { *goals = &m_iFailedGoals; } + void getFailedGoals (WaypointList **goals) override { *goals = &m_iFailedGoals; } - int numPaths ( ); + int numPaths ( ) override; - Vector getPath ( int pathid ); + Vector getPath ( int pathid ) override; - bool randomDangerPath (Vector *vec); + bool randomDangerPath (Vector *vec) override; - bool beliefLoad ( ); + bool beliefLoad ( ) override; - bool beliefSave ( bool bOverride = false ); + bool beliefSave ( bool bOverride = false ) override; - bool wantToSaveBelief (); + bool wantToSaveBelief () override; - inline int getCurrentWaypointID () + int getCurrentWaypointID () override { return m_iCurrentWaypoint; } - inline int getCurrentGoalID () + int getCurrentGoalID () override { return m_iGoalWaypoint; } - int getCurrentFlags (); - int getPathFlags ( int iPath ); + int getCurrentFlags () override; + int getPathFlags ( int iPath ) override; private: CBot *m_pBot; @@ -479,16 +497,16 @@ class CWaypointNavigator : public IBotNavigator failedpath_t m_lastFailedPath; - dataStack m_currentRoute; - queue m_oldRoute; + std::stack m_currentRoute; + std::queue m_oldRoute; int m_iLastFailedWpt; AStarNode paths[CWaypoints::MAX_WAYPOINTS]; - AStarNode *curr; - AStarNode *succ; + AStarNode* curr = nullptr; + AStarNode* succ = nullptr; - dataUnconstArray m_iFailedGoals; + WaypointList m_iFailedGoals; float m_fNextClearFailedGoals; float m_fBelief [CWaypoints::MAX_WAYPOINTS]; @@ -502,31 +520,40 @@ class CWaypointNavigator : public IBotNavigator class CNavMeshNavigator : public IBotNavigator { public: - virtual bool workRoute ( Vector vFrom, Vector vTo, bool *bFail, bool bRestart = true, bool bNoInterruptions = false, int iGoalId = -1, int iConditions = 0, int iDangerId = -1 ); + //TODO: Add Nav Mesh support [APG]RoboCop[CL] + CNavMesh* m_theNavMesh; // Add a member variable for the NavMesh instance + + CNavMeshNavigator(); + ~CNavMeshNavigator() override; + + void CalculateRoute(Vector startNodeID, Vector goalNodeID); + + bool workRoute (const Vector& vFrom, const Vector& vTo, bool* bFail, bool bRestart = true, bool bNoInterruptions = false, int iGoalId = + -1, int iConditions = 0, int iDangerId = -1) override; - virtual Vector getNextPoint (); + Vector getNextPoint () override; - virtual void updatePosition (); + void updatePosition () override; - void freeMapMemory (); + void freeMapMemory () override; - void freeAllMemory (); + void freeAllMemory () override; - bool routeFound (); + bool routeFound () override; - bool hasNextPoint (); + bool hasNextPoint () override; - void rollBackPosition () {}; + void rollBackPosition () override {} - void init (); + void init () override; - void belief ( Vector origin, Vector facing, float fBelief, float fStrength, BotBelief iType ){}; //bir3yk + void belief (const Vector& origin, const Vector& facing, const float fBelief, const float fStrength, const BotBelief iType) override {} //bir3yk //void rememberEnemyPosition ( Vector vOrigin ); //Vector getEnemyPositionPinchPoint ( Vector vOrigin ); private: - CNavMesh *m_pNavMesh; + CNavMesh * m_pNavMesh; }; #endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_navmesh.cpp b/utils/RCBot2_meta/bot_navmesh.cpp index 4fa59c400..1ed817643 100644 --- a/utils/RCBot2_meta/bot_navmesh.cpp +++ b/utils/RCBot2_meta/bot_navmesh.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -28,45 +30,112 @@ * version. * */ -#include -#include +#include +#include + #include "bot_navigator.h" +#include "bot_waypoint.h" //#include "nav_mesh.h" -bool CNavMeshNavigator :: workRoute ( Vector vFrom, Vector vTo, bool *bFail, bool bRestart, bool bNoInterruptions, int iGoalId, int iConditions, int iDangerId ) +CNavMeshNavigator::CNavMeshNavigator() +{ + // Create a new instance of the NavMesh class + //m_theNavMesh = new CNavMesh(); +} + +CNavMeshNavigator::~CNavMeshNavigator() { - return true; + // Clean up the NavMesh instance + //delete m_theNavMesh; +} + +void CNavMeshNavigator::CalculateRoute(Vector startNodeID, Vector goalNodeID) +{ + // Call the CalculateRoute function from the NavMesh class + //m_theNavMesh->CalculateRoute(vFrom, vTo); + + // Since we can't determine success, we assume the route was successfully calculated + //*bFail = false; + + // Calculate the route + //m_theNavMesh->CalculateRoute(startNodeID, goalNodeID); +} + +bool CNavMeshNavigator::workRoute(const Vector& vFrom, const Vector& vTo, bool* bFail, const bool bRestart, const bool bNoInterruptions, const int + iGoalId, const int iConditions, const int iDangerId) +{ + // Try to find a route using the primary waypoint system + /*bool routeFound = false; // logic to find a route using the primary waypoint system + + // If a route was not found using the primary waypoint system + if (!routeFound) + { + // Use the NavMesh as a backup + CalculateRoute(vFrom, vTo); + routeFound = true; // Assume the route was successfully calculated + + // Now, you can check if the NavMesh has a valid route + //if (routeFound && m_theNavMesh->routeFound()) + //{ + // // Perform additional logic or use the calculated route from the NavMesh + // while (hasNextPoint()) + // { + // getNextPoint(); + // // Use navMeshWaypoint as needed + // // ... + // } + //} + } + + // Continue with the rest of your navigation logic + return routeFound;*/ + return false; } -Vector CNavMeshNavigator :: getNextPoint () +Vector CNavMeshNavigator::getNextPoint() { - return Vector(0,0,0); + // Get the next point from the calculated route using Nav Mesh + //return m_theNavMesh->GetNextRoutePoint(); + return { 0,0,0 }; } -void CNavMeshNavigator :: updatePosition () +void CNavMeshNavigator::updatePosition() { + // Update the bot's position during navigation using Nav Mesh + //m_theNavMesh->botPosition(currentPosition); // Use the botPosition function to update the bot's position + + // Update the bot's position + //m_theNavMesh->UpdatePosition(m_pBot->pEdict->v.origin); } -void CNavMeshNavigator :: freeMapMemory () +void CNavMeshNavigator::freeMapMemory() { + // Free the memory used by the NavMesh + //m_theNavMesh->freeMemory(); } -void CNavMeshNavigator :: freeAllMemory () +void CNavMeshNavigator::freeAllMemory() { + // Free the memory used by the NavMesh + //m_theNavMesh->freeMemory(); } -bool CNavMeshNavigator :: routeFound () +bool CNavMeshNavigator::routeFound() { + // Check if a route has been successfully calculated by the NavMesh + //return m_theNavMesh->routeFound(); return false; } -bool CNavMeshNavigator :: hasNextPoint () +bool CNavMeshNavigator::hasNextPoint() { + // Check if there are more points in the calculated route + //return m_theNavMesh->HasNextRoutePoint(); return false; } -void CNavMeshNavigator :: init () +void CNavMeshNavigator::init() { //m_theNavMesh->Reset(); } diff --git a/utils/RCBot2_meta/bot_perceptron.cpp b/utils/RCBot2_meta/bot_perceptron.cpp index 689ff672a..ffd161260 100644 --- a/utils/RCBot2_meta/bot_perceptron.cpp +++ b/utils/RCBot2_meta/bot_perceptron.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -28,22 +30,31 @@ * version. * */ -#include + +#include #include +#include //#include "vstdlib/random.h" // for random functions #include "bot_mtrand.h" #include "bot_perceptron.h" +#include "logging.h" + ga_nn_value CPerceptron::m_fDefaultLearnRate = 0.5f; ga_nn_value CPerceptron::m_fDefaultBias = 1.0f; CNeuron :: CNeuron () { - m_weights = NULL; - m_inputs = NULL; + m_iInputs = 0; + m_LearnRate = 0; + m_output = 0; + m_Bias = 0; + + m_weights = nullptr; + m_inputs = nullptr; } -CPerceptron :: CPerceptron (unsigned short int iInputs) +CPerceptron::CPerceptron(const unsigned short iInputs) { m_inputs = new ga_nn_value [iInputs];//.clear(); m_weights = new ga_nn_value[iInputs]; @@ -53,23 +64,37 @@ CPerceptron :: CPerceptron (unsigned short int iInputs) // bias weight m_Bias = -0.5; - for ( unsigned short int i = 0; i < m_iInputs; i++ ) - m_weights[i] = -0.3f+randomFloat(0.0f,0.6f); + for (unsigned short int i = 0; i < m_iInputs; i++) + m_weights[i] = -0.3f + randomFloat(0.0f, 0.6f); } -void CPerceptron :: setWeights ( ga_nn_value *weights ) -{ - memcpy(m_weights,weights,sizeof(ga_nn_value)*m_iInputs); +void CPerceptron::setWeights(const ga_nn_value* weights) const { + if (!weights) { + logger->Log(LogLevel::WARN, "Weights pointer is null"); + return; // Exit the function to prevent unsafe usage + } + + std::memcpy(m_weights, weights, sizeof(ga_nn_value) * m_iInputs); } void CNeuron :: input ( ga_nn_value *inputs ) { - memcpy(m_inputs,inputs,sizeof(ga_nn_value)*m_iInputs); + std::memcpy(m_inputs,inputs,sizeof(ga_nn_value)*m_iInputs); +} + +ga_nn_value CNeuron::execute() +{ + return ga_nn_value(); +} + +bool CNeuron::fired() //TODO: experimental [APG]RoboCop[CL] +{ + return false; } ga_nn_value CPerceptron :: execute () { - static unsigned short int i; + static unsigned short i; static ga_nn_value *w; static ga_nn_value *x; // bias weight @@ -80,30 +105,30 @@ ga_nn_value CPerceptron :: execute () for ( i = 0; i < m_iInputs; i ++ ) { - m_output += (*w) * (*x); + m_output += *w * *x; w++; x++; } // sigmoid function - m_output = 1.0f/(1.0f+exp(-m_output)); //m_transferFunction->transfer(fNetInput); + m_output = 1.0f / (1.0f + std::exp(-m_output)); //m_transferFunction->transfer(fNetInput); return m_output; } -bool CPerceptron :: fired () +bool CPerceptron :: fired () const { return m_output >= 0.5f; } -ga_nn_value CPerceptron :: getOutput () +ga_nn_value CPerceptron :: getOutput () const { return m_output; } -void CPerceptron :: train ( ga_nn_value expectedOutput ) +void CPerceptron::train(const ga_nn_value expectedOutput) { - static unsigned short int i; + static unsigned short i; static ga_nn_value *w; static ga_nn_value *x; @@ -115,7 +140,7 @@ void CPerceptron :: train ( ga_nn_value expectedOutput ) for ( i = 0; i < m_iInputs; i ++ ) { - *w = *w + m_LearnRate*(expectedOutput-m_output)* (*x); + *w = *w + m_LearnRate*(expectedOutput-m_output)* *x; w++; x++; } @@ -123,7 +148,7 @@ void CPerceptron :: train ( ga_nn_value expectedOutput ) void CLogisticalNeuron :: train ()// ITransfer *transferFunction, bool usebias ) { - static unsigned short int i; + static unsigned short i; static ga_nn_value *w; static ga_nn_value *x; static ga_nn_value delta; @@ -133,7 +158,7 @@ void CLogisticalNeuron :: train ()// ITransfer *transferFunction, bool usebias ) for ( i = 0; i < m_iInputs; i ++ ) { - delta = (m_LearnRate * (*x) * m_error); + delta = m_LearnRate * *x * m_error; delta += m_momentum * 0.9f; *w = *w + delta; m_momentum = delta; @@ -144,32 +169,32 @@ void CLogisticalNeuron :: train ()// ITransfer *transferFunction, bool usebias ) m_Bias += m_LearnRate * m_error; } -ga_nn_value CLogisticalNeuron :: execute ( )//, bool usebias ) +ga_nn_value CLogisticalNeuron :: execute ( )//, bool usebias ) { static unsigned short int i; static ga_nn_value *w; static ga_nn_value *x; - m_netinput = 0; + //m_netinput = 0; w = m_weights; x = m_inputs; // bias weight - m_netinput = m_Bias; + m_netinput = m_Bias;//m_netinput assigned twice? [APG]RoboCop[CL] for ( i = 0; i < m_iInputs; i ++ ) { - m_netinput += (*w) * (*x); + m_netinput += *w * *x; w++; x++; } - m_output = 1/(1+exp(-m_netinput));//transferFunction->transfer(m_netinput); + m_output = 1/(1+std::exp(-m_netinput));//transferFunction->transfer(m_netinput); return m_output; } -void CLogisticalNeuron::init(unsigned short int iInputs, ga_nn_value learnrate) +void CLogisticalNeuron::init(const unsigned short iInputs, const ga_nn_value learnrate) { m_weights = new ga_nn_value[iInputs]; m_inputs = new ga_nn_value[iInputs]; @@ -188,12 +213,11 @@ void CLogisticalNeuron::init(unsigned short int iInputs, ga_nn_value learnrate) m_LearnRate = learnrate; } -CBotNeuralNet :: CBotNeuralNet ( unsigned short int numinputs, unsigned short int numhiddenlayers, - unsigned short int neuronsperhiddenlayer, unsigned short int numoutputs, - ga_nn_value learnrate) +CBotNeuralNet :: CBotNeuralNet (const unsigned short numinputs, const unsigned short numhiddenlayers, + const unsigned short neuronsperhiddenlayer, const unsigned short numoutputs, + const ga_nn_value learnrate) { - register unsigned short int i; - register unsigned short int j; + unsigned short i; m_pOutputs = new CLogisticalNeuron[numoutputs]; m_pHidden = new CLogisticalNeuron*[numhiddenlayers]; @@ -201,7 +225,7 @@ CBotNeuralNet :: CBotNeuralNet ( unsigned short int numinputs, unsigned short in m_layerinput = new ga_nn_value[_MAX(numinputs,neuronsperhiddenlayer)]; m_layeroutput = new ga_nn_value[_MAX(numoutputs,_MAX(numinputs,neuronsperhiddenlayer))]; - for ( j = 0; j < numhiddenlayers; j ++ ) + for ( unsigned short j = 0; j < numhiddenlayers; j ++ ) { m_pHidden[j] = new CLogisticalNeuron[neuronsperhiddenlayer]; @@ -223,32 +247,23 @@ CBotNeuralNet :: CBotNeuralNet ( unsigned short int numinputs, unsigned short in m_numOutputs = numoutputs; m_numHidden = neuronsperhiddenlayer; m_numHiddenLayers = numhiddenlayers; - - } -#define RCPP_VERB_EPOCHS 1000 +constexpr int RCPP_VERB_EPOCHS = 1000; -void CBotNeuralNet :: batch_train ( CTrainingSet *tset, unsigned short int epochs ) +void CBotNeuralNet :: batch_train (const CTrainingSet *tset, const unsigned short epochs) const { - ga_nn_value *outs; - ga_nn_value exp_out; // expected - ga_nn_value act_out; // actual - ga_nn_value out_error; - unsigned short int e; // epoch - register unsigned short int bi; // batch iterator - register unsigned short int i; // ith node - register unsigned short int j; //jth output - register signed short int l; // layer - CLogisticalNeuron *pNode, *pOutputNode; - unsigned short int numbatches = tset->getNumBatches(); - training_batch_t *batches = tset->getBatches(); - ga_nn_value min_value = tset->getMinScale(); - ga_nn_value max_value = tset->getMaxScale(); - - outs = new ga_nn_value [m_numOutputs]; - - for ( e = 0; e < epochs; e ++ ) + unsigned short i; // ith node + unsigned short j; //jth output + CLogisticalNeuron*pOutputNode; + const unsigned short numbatches = tset->getNumBatches(); + const training_batch_t *batches = tset->getBatches(); + const ga_nn_value min_value = tset->getMinScale(); + const ga_nn_value max_value = tset->getMaxScale(); + + ga_nn_value* outs = new ga_nn_value [m_numOutputs]; + + for ( unsigned short e = 0; e < epochs; e ++ ) { /*if ( !(e%RCPP_VERB_EPOCHS) ) { @@ -258,20 +273,20 @@ void CBotNeuralNet :: batch_train ( CTrainingSet *tset, unsigned short int epoch printf("in1\tin2\texp\tact\terr\n"); }*/ - for ( bi = 0; bi < numbatches; bi ++ ) + for ( unsigned short bi = 0; bi < numbatches; bi ++ ) { - memset(outs,0,sizeof(ga_nn_value)*m_numOutputs); + std::memset(outs,0,sizeof(ga_nn_value)*m_numOutputs); execute(batches[bi].in,outs,min_value,max_value); - pNode = m_pOutputs; + CLogisticalNeuron* pNode = m_pOutputs; // work out error for output layer for ( j = 0; j < m_numOutputs; j ++ ) { - act_out = pNode->getOutput(); - exp_out = batches[bi].out[j]; - out_error = act_out * (1.0f-act_out) * (exp_out - act_out); + const ga_nn_value act_out = pNode->getOutput(); + const ga_nn_value exp_out = batches[bi].out[j]; + const ga_nn_value out_error = act_out * (1.0f - act_out) * (exp_out - act_out); pNode->setError(out_error); pNode++; } @@ -301,7 +316,7 @@ void CBotNeuralNet :: batch_train ( CTrainingSet *tset, unsigned short int epoch pNode++; } - for ( l = (m_numHiddenLayers-2); l >= 0; l -- ) + for ( signed short l = m_numHiddenLayers - 2; l >= 0; l -- ) //l should be int only? [APG]RoboCop[CL] { pOutputNode = m_pHidden[l]; //Send Error back to Input Layer @@ -318,7 +333,7 @@ void CBotNeuralNet :: batch_train ( CTrainingSet *tset, unsigned short int epoch pNode++; } - pOutputNode->setError((pOutputNode->getOutput() * (1.0f-pOutputNode->getOutput())) * err); + pOutputNode->setError(pOutputNode->getOutput() * (1.0f-pOutputNode->getOutput()) * err); pOutputNode ++; } } @@ -345,20 +360,21 @@ void CBotNeuralNet :: batch_train ( CTrainingSet *tset, unsigned short int epoch delete[] outs; } -void CBotNeuralNet :: execute ( ga_nn_value *inputs, ga_nn_value *outputs, ga_nn_value fMin, ga_nn_value fMax ) +void CBotNeuralNet :: execute (const ga_nn_value* inputs, ga_nn_value* outputs, const ga_nn_value fMin, const ga_nn_value fMax) const { - static CLogisticalNeuron *pNode; - static CLogisticalNeuron *pLayer; - static unsigned short int i; // i-th node + static CLogisticalNeuron *pLayer; //Unused? [APG]RoboCop[CL] + static unsigned short i; // i-th node static unsigned short l; // layer static ga_nn_value *output_it; - memset(outputs,0,sizeof(ga_nn_value)*m_numOutputs); - memset(m_layeroutput,0,sizeof(ga_nn_value)*m_numInputs); - memcpy(m_layerinput,inputs,sizeof(ga_nn_value)*m_numInputs); + std::memset(outputs,0,sizeof(ga_nn_value)*m_numOutputs); + std::memset(m_layeroutput,0,sizeof(ga_nn_value)*m_numInputs); + std::memcpy(m_layerinput,inputs,sizeof(ga_nn_value)*m_numInputs); - //pLayer = m_pHidden; + // Missing inputs!!! + for (i = 0; i < m_numInputs; i++) + m_layerinput[i] = inputs[i]; for ( l = 0; l < m_numHiddenLayers; l ++ ) { @@ -378,10 +394,10 @@ void CBotNeuralNet :: execute ( ga_nn_value *inputs, ga_nn_value *outputs, ga_nn output_it ++; pNode++; // next - //layeroutput.push_back(pNode->getOutput()); + //layeroutput.emplace_back(pNode->getOutput()); } - memcpy(m_layerinput,m_layeroutput,sizeof(ga_nn_value) * m_numHidden); + std::memcpy(m_layerinput,m_layeroutput,sizeof(ga_nn_value) * m_numHidden); //pLayer++; } @@ -394,5 +410,4 @@ void CBotNeuralNet :: execute ( ga_nn_value *inputs, ga_nn_value *outputs, ga_nn pNode->execute();//m_transferFunction); outputs[i] = gdescale(pNode->getOutput(),fMin,fMax); } -} - +} \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_perceptron.h b/utils/RCBot2_meta/bot_perceptron.h index d3f0c5e51..dc42e0106 100644 --- a/utils/RCBot2_meta/bot_perceptron.h +++ b/utils/RCBot2_meta/bot_perceptron.h @@ -8,27 +8,27 @@ typedef float ga_nn_value; //#define scale (x,min,max) (((x)-(min))/((max)-(min))) //#define descale (x,min,max) ((min)+((x)*((max)-(min)))) -inline unsigned short int _MAX ( unsigned short int a, unsigned short int b ) +inline unsigned short int _MAX (const unsigned short int a, const unsigned short int b) { if ( a > b ) return a; return b; } -inline ga_nn_value zeroscale ( ga_nn_value x, ga_nn_value fMin, ga_nn_value fMax ) +inline ga_nn_value zeroscale (const ga_nn_value x, const ga_nn_value fMin, const ga_nn_value fMax) { - return ((x-fMin)/(fMax-fMin)); + return (x-fMin)/(fMax-fMin); } // scales into -1 and +1 (medium at zero) -inline ga_nn_value gscale ( ga_nn_value x, ga_nn_value fMin, ga_nn_value fMax ) +inline ga_nn_value gscale (const ga_nn_value x, const ga_nn_value fMin, const ga_nn_value fMax) { - return (zeroscale(x,fMin,fMax)*2)-1.0f; + return zeroscale(x,fMin,fMax)*2-1.0f; } // descales between 0 and 1 to min and max range -inline ga_nn_value gdescale ( ga_nn_value x, ga_nn_value fMin, ga_nn_value fMax ) +inline ga_nn_value gdescale (const ga_nn_value x, const ga_nn_value fMin, const ga_nn_value fMax) { - return (fMin+(x*(fMax-fMin))); + return fMin+x*(fMax-fMin); } /* @@ -67,21 +67,21 @@ class CNeuron public: CNeuron (); - CNeuron (unsigned short int iInputs); + CNeuron (unsigned short int iInputs); //TODO: not implemented? [APG]RoboCop[CL] - ~CNeuron() { if ( m_inputs ) delete[] m_inputs; if ( m_weights ) delete[] m_weights; } + virtual ~CNeuron() { /*if ( m_inputs )*/ delete[] m_inputs; /*if ( m_weights )*/ delete[] m_weights; } - void setWeights ( ga_nn_value *weights ); + void setWeights ( ga_nn_value *weights ); //TODO: not implemented? [APG]RoboCop[CL] virtual void input ( ga_nn_value *inputs ); - inline ga_nn_value getWeight ( unsigned short int i ) { return m_weights[i]; } + ga_nn_value getWeight (const unsigned short int i) const { return m_weights[i]; } - ga_nn_value execute (); + virtual ga_nn_value execute (); //TODO: not implemented? [APG]RoboCop[CL] - bool fired (); + static bool fired (); //TODO: experimental [APG]RoboCop[CL] - inline ga_nn_value getOutput () { return m_output; } + virtual ga_nn_value getOutput () const { return m_output; } protected: @@ -103,13 +103,13 @@ class CPerceptron : public CNeuron CPerceptron (unsigned short int iInputs); - void setWeights ( ga_nn_value *weights ); + void setWeights (const ga_nn_value* weights) const; - ga_nn_value execute (); + ga_nn_value execute () override; - bool fired (); + bool fired () const; - ga_nn_value getOutput (); + ga_nn_value getOutput () const override; void train ( ga_nn_value expectedOutput ); @@ -133,14 +133,14 @@ class CLogisticalNeuron : public CNeuron void train ();/// ITransfer *transferFunction, bool usebias = true ); - ga_nn_value execute ();//, bool usebias = true ); + ga_nn_value execute () override;//, bool usebias = true ); - inline void setError ( ga_nn_value err ) { m_error = err; } - inline void addError ( ga_nn_value err ) { m_error += err; } - inline void divError ( unsigned short int samples ) { m_error /= samples; } + void setError (const ga_nn_value err) { m_error = err; } + void addError (const ga_nn_value err) { m_error += err; } + void divError (const ga_nn_value samples) { m_error /= samples; } - inline ga_nn_value getError ( unsigned short int w ) { return m_error * m_weights[w]; } - inline ga_nn_value getMSE () { return m_error; } + ga_nn_value getError (const unsigned short int w) const { return m_error * m_weights[w]; } + ga_nn_value getMSE () const { return m_error; } private: ga_nn_value m_error; ga_nn_value m_netinput; @@ -157,7 +157,7 @@ typedef struct class CTrainingSet { public: - CTrainingSet( unsigned short int numInputs, unsigned short int numOutputs, unsigned short int numBatches ) + CTrainingSet(const unsigned short int numInputs, const unsigned short int numOutputs, const unsigned short int numBatches) { m_numInputs = numInputs; m_numOutputs = numOutputs; @@ -190,7 +190,7 @@ class CTrainingSet delete[] batches; } - batches = NULL; + batches = nullptr; } void init () @@ -205,34 +205,34 @@ class CTrainingSet { batches[i].in = new ga_nn_value[m_numInputs]; batches[i].out = new ga_nn_value[m_numOutputs]; - memset(batches[i].in,0,sizeof(ga_nn_value)*m_numInputs); - memset(batches[i].out,0,sizeof(ga_nn_value)*m_numOutputs); + std::memset(batches[i].in,0,sizeof(ga_nn_value)*m_numInputs); + std::memset(batches[i].out,0,sizeof(ga_nn_value)*m_numOutputs); } } - inline void setScale ( ga_nn_value min, ga_nn_value max ) + void setScale (const ga_nn_value min, const ga_nn_value max) { m_fMin = min; m_fMax = max; } // input and scale between -1 and 1 - inline void in ( ga_nn_value input ) + void in (const ga_nn_value input) { //assert(m_batchNum>=0); - if ( (m_batchNum >= 0) && (m_batchNum < m_numBatches) && (m_inputNum < m_numInputs) ) + if ( m_batchNum >= 0 && m_batchNum < m_numBatches && m_inputNum < m_numInputs ) batches[m_batchNum].in[m_inputNum++] = scale(input); } // output and scale between 0 and 1 - inline void out ( ga_nn_value output ) + void out (const ga_nn_value output) { //assert(m_batchNum>=0); - if ( (m_batchNum >= 0) && (m_batchNum < m_numBatches) && (m_outputNum < m_numOutputs) ) + if ( m_batchNum >= 0 && m_batchNum < m_numBatches && m_outputNum < m_numOutputs ) batches[m_batchNum].out[m_outputNum++] = zeroscale(output,m_fMin,m_fMax); } - inline void addSet ( void ) + void addSet () { if ( m_batchNum >= m_numBatches ) return; // error -- too many @@ -242,25 +242,25 @@ class CTrainingSet m_outputNum = 0; } - inline unsigned short int getNumBatches () + unsigned short int getNumBatches () const { return m_numBatches; } - inline ga_nn_value scale ( ga_nn_value x ) + ga_nn_value scale (const ga_nn_value x) const { return gscale(x,m_fMin,m_fMax); } - inline ga_nn_value descale ( ga_nn_value x ) + ga_nn_value descale (const ga_nn_value x) const { return gdescale(x,m_fMin,m_fMax); } - inline ga_nn_value getMinScale () { return m_fMin; } - inline ga_nn_value getMaxScale () { return m_fMax; } + ga_nn_value getMinScale () const { return m_fMin; } + ga_nn_value getMaxScale () const { return m_fMax; } - inline training_batch_t *getBatches () { return batches; } + training_batch_t *getBatches () const { return batches; } private: // simple format (ins / outs) training_batch_t *batches; @@ -279,28 +279,29 @@ class CBotNeuralNet { public: - CBotNeuralNet ( unsigned short int numinputs, unsigned short int hiddenlayers, unsigned short int hiddenlayer, unsigned short int outputlayer, ga_nn_value learnrate ); + CBotNeuralNet(unsigned short int numinputs, unsigned short int numhiddenlayers, unsigned short int neuronsperhiddenlayer, unsigned short int numoutputs, ga_nn_value learnrate); CBotNeuralNet () { - m_pOutputs = NULL; + m_pHidden = nullptr; + m_pOutputs = nullptr; //m_transferFunction = NULL; m_numInputs = 0; // number of inputs m_numOutputs = 0; // number of outputs m_numHidden = 0; // neurons per hidden layer m_numHiddenLayers = 0; - m_layeroutput = NULL; - m_layerinput = NULL; + m_layeroutput = nullptr; + m_layerinput = nullptr; } - void execute ( ga_nn_value *inputs, ga_nn_value *outputs, ga_nn_value fMin, ga_nn_value fMax ); + void execute (const ga_nn_value* inputs, ga_nn_value* outputs, ga_nn_value fMin, ga_nn_value fMax) const; - void batch_train ( CTrainingSet *tset, unsigned short int epochs ); + void batch_train (const CTrainingSet *tset, unsigned short int epochs) const; ~CBotNeuralNet () { - if ( m_pOutputs ) + //if ( m_pOutputs ) delete [] m_pOutputs; //if ( m_transferFunction ) // delete m_transferFunction; diff --git a/utils/RCBot2_meta/bot_plugin_meta.cpp b/utils/RCBot2_meta/bot_plugin_meta.cpp index ac29eee72..7ed62c231 100644 --- a/utils/RCBot2_meta/bot_plugin_meta.cpp +++ b/utils/RCBot2_meta/bot_plugin_meta.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /** * vim: set ts=4 sw=4 tw=99 noet : * ====================================================== @@ -12,39 +14,39 @@ * This sample plugin is public domain. */ -#include +#include + +#pragma push_macro("clamp") //Fix for C++17 [APG]RoboCop[CL] +#undef clamp +#include +#pragma pop_macro("clamp") #include "bot_plugin_meta.h" #include "filesystem.h" #include "interface.h" +#include "IStaticPropMgr.h" #ifdef __linux__ #include "shake.h" //bir3yk #endif -#include "IEffects.h" -#include "igameevents.h" -#include "IEngineTrace.h" -#include "Color.h" #include "ndebugoverlay.h" -#include "server_class.h" -#include "time.h" #include "irecipientfilter.h" -#include "KeyValues.h" - #include "bot_cvars.h" +#if defined(_WIN64) || defined(_WIN32) + #include +#endif + // for IServerTools #include "bot.h" #include "bot_configfile.h" #include "bot_globals.h" #include "bot_profile.h" -#include "bot_waypoint.h" #include "bot_menu.h" #include "bot_getprop.h" -#include "bot_fortress.h" #include "bot_event.h" #include "bot_profiling.h" #include "bot_wpt_dist.h" @@ -54,10 +56,20 @@ #include "bot_waypoint_visibility.h" #include "bot_kv.h" #include "bot_sigscan.h" +//#include "bot_mods.h" + +#include "tier0/icommandline.h" -//#include "ndebugoverlay.h" -CBotTF2 *g_pLastBot; +#include "rcbot/logging.h" +#include + +#include +#include + +#ifdef SM_EXT +#include "rcbot/entprops.h" +#endif SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, 0, bool, char const *, char const *, char const *, char const *, bool, bool); SH_DECL_HOOK3_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0, edict_t *, int, int); SH_DECL_HOOK1_void(IServerGameDLL, GameFrame, SH_NOATTRIB, 0, bool); @@ -66,7 +78,6 @@ SH_DECL_HOOK2_void(IServerGameClients, ClientActive, SH_NOATTRIB, 0, edict_t *, SH_DECL_HOOK1_void(IServerGameClients, ClientDisconnect, SH_NOATTRIB, 0, edict_t *); SH_DECL_HOOK2_void(IServerGameClients, ClientPutInServer, SH_NOATTRIB, 0, edict_t *, char const *); SH_DECL_HOOK1_void(IServerGameClients, SetCommandClient, SH_NOATTRIB, 0, int); -SH_DECL_HOOK1_void(IServerGameClients, ClientSettingsChanged, SH_NOATTRIB, 0, edict_t *); SH_DECL_HOOK5(IServerGameClients, ClientConnect, SH_NOATTRIB, 0, bool, edict_t *, const char*, const char *, char *, int); SH_DECL_HOOK2(IGameEventManager2, FireEvent, SH_NOATTRIB, 0, bool, IGameEvent *, bool); @@ -78,160 +89,48 @@ SH_DECL_HOOK1_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *) #endif SH_DECL_MANUALHOOK2_void(MHook_PlayerRunCmd, 0, 0, 0, CUserCmd*, IMoveHelper*); -SH_DECL_MANUALHOOK4(MHook_GiveNamedItem, 0, 0, 0,CBaseEntity*, const char *,int,CEconItemView*,bool); - -SH_DECL_MANUALHOOK1_void(MHook_EquipWearable, 0, 0, 0, CEconWearable*); -SH_DECL_MANUALHOOK1_void(MHook_EquipWeapon, 0, 0, 0, CBaseEntity*); - -SH_DECL_MANUALHOOK1_void(MHook_RemovePlayerItem, 0, 0, 0, CBaseEntity*); - -SH_DECL_MANUALHOOK1(MHook_GetPlayerWeaponSlot, 0, 0, 0, CBaseEntity*, int); -SH_DECL_MANUALHOOK1_void(MHook_RemoveWearable, 0, 0, 0, CBaseEntity*); - -/* -SH_DECL_HOOK1_void(bf_write, WriteChar, SH_NOATTRIB, 0, int); -SH_DECL_HOOK1_void(bf_write, WriteShort, SH_NOATTRIB, 0, int); -SH_DECL_HOOK1_void(bf_write, WriteByte, SH_NOATTRIB, 0, int); -SH_DECL_HOOK1_void(bf_write, WriteFloat, SH_NOATTRIB, 0, float); -SH_DECL_HOOK1(bf_write, WriteString, SH_NOATTRIB, 0, bool, const char *); - -SH_DECL_HOOK2(IVEngineServer, UserMessageBegin, SH_NOATTRIB, 0, bf_write*, IRecipientFilter*, int); -SH_DECL_HOOK0_void(IVEngineServer, MessageEnd, SH_NOATTRIB, 0); - -bf_write *current_msg = NULL; - -#define BUF_SIZ 1024 -char current_msg_buffer[BUF_SIZ]; -*/ - -CBaseEntity* (CBaseEntity::*TF2EquipWearable)(CBaseEntity*) = 0x0; -CBaseEntity* (CBaseEntity::*TF2PlayerWeaponSlot)(int) = 0x0; -void (CAttributeManager::*OnAttributeValuesChanged)(void) = 0x0; -void (CBaseEntity::*TF2RemoveWearable)(CBaseEntity*) = 0x0; -void (CBaseEntity::*TF2RemovePlayerItem)(CBaseEntity*) = 0x0; -//void (CBaseEntity::*TF2WeaponEquip)(CBaseEntity*) = 0x0; - -IServerGameDLL *server = NULL; -IGameEventManager2 *gameevents = NULL; -IServerPluginCallbacks *vsp_callbacks = NULL; -ICvar *icvar = NULL; -IVEngineServer *engine = NULL; // helper functions (messaging clients, loading content, making entities, running commands, etc) -IFileSystem *filesystem = NULL; // file I/O -IGameEventManager2 *gameeventmanager = NULL; -IGameEventManager *gameeventmanager1 = NULL; // game events interface -IPlayerInfoManager *playerinfomanager = NULL; // game dll interface to interact with players -IServerPluginHelpers *helpers = NULL; // special 3rd party plugin helpers from the engine -IServerGameClients* gameclients = NULL; -IEngineTrace *enginetrace = NULL; -IEffects *g_pEffects = NULL; -IBotManager *g_pBotManager = NULL; -CGlobalVars *gpGlobals = NULL; -IVDebugOverlay *debugoverlay = NULL; -IServerGameEnts *servergameents = NULL; // for accessing the server game entities -IServerGameDLL *servergamedll = NULL; -IServerTools *servertools = NULL; + +IServerGameDLL *server = nullptr; +IGameEventManager2 *gameevents = nullptr; +IServerPluginCallbacks *vsp_callbacks = nullptr; +ICvar *icvar = nullptr; +IVEngineServer *engine = nullptr; // helper functions (messaging clients, loading content, making entities, running commands, etc) +IFileSystem *filesystem = nullptr; // file I/O +IGameEventManager2 *gameeventmanager = nullptr; +IGameEventManager *gameeventmanager1 = nullptr; // game events interface +IPlayerInfoManager *playerinfomanager = nullptr; // game dll interface to interact with players +IServerPluginHelpers *helpers = nullptr; // special 3rd party plugin helpers from the engine +IServerGameClients* gameclients = nullptr; +IEngineTrace *enginetrace = nullptr; +IEffects *g_pEffects = nullptr; +IBotManager *g_pBotManager = nullptr; +CGlobalVars *gpGlobals = nullptr; +IVDebugOverlay *debugoverlay = nullptr; +IServerGameEnts *servergameents = nullptr; // for accessing the server game entities +IServerGameDLL *servergamedll = nullptr; +IServerTools *servertools = nullptr; +IStaticPropMgrServer* staticpropmgr = nullptr; RCBotPluginMeta g_RCBotPluginMeta; PLUGIN_EXPOSE(RCBotPluginMeta, g_RCBotPluginMeta); -static ConVar rcbot2_ver_cvar(BOT_VER_CVAR, BOT_VER, FCVAR_REPLICATED, BOT_NAME_VER); - - -int UTIL_ListAttributesOnEntity(edict_t *pEdict) -{ - CAttributeList *pAttributeList = CClassInterface::getAttributeList(pEdict); - int offset = CClassInterface::getOffset(GETPROP_TF2_ATTRIBUTELIST); - CBaseEntity *pEntity = servergameents->EdictToBaseEntity(pEdict); - - if (!pAttributeList) - return 0; - - //local variable is initialized but not referenced - [APG]RoboCop[CL] - int *pAttribList1 = (int*)((unsigned int)pAttributeList + 4); - - int *pAttribList = (int*)((unsigned int)pEntity + offset + 4); - - if ((unsigned int)pAttribList < 0x10000) - return 0; - - int iNumAttribs = *(int*)((unsigned int)pAttributeList + 16); - short int iAttribIndices[16]; - - CBotGlobals::botMessage(NULL, 0, "There are %d attributes on %s entity", iNumAttribs, pEdict->GetClassName()); - - for (int i = 0; i < iNumAttribs; i++) //THIS IS HOW YOU GET THE ATTRIBUTES ON AN ITEM! - { - iAttribIndices[i] = *(short int*)((unsigned int)pAttribList + (i * 16) + 4); - - CBotGlobals::botMessage(NULL, 0, "%d) %d", i, iAttribIndices[i]); - } - - return iNumAttribs; -} - -CON_COMMAND(rcbot_printattribs, "print attributes") -{ - if (args.ArgC() > 1) - { - int slot = atoi(args.Arg(1)); - - edict_t *pEdict = INDEXENT(1); - - if (slot >= 0) - { - - CBaseEntity *pEntity = RCBotPluginMeta::TF2_getPlayerWeaponSlot(pEdict, slot); - - if (pEntity) - pEdict = servergameents->BaseEntityToEdict(pEntity); - } - - if (pEdict) - UTIL_ListAttributesOnEntity(pEdict); - } -} - -CON_COMMAND(rcbot_setattrib, "set an attribute") -{ - if (args.ArgC() > 2) - { - edict_t *pPlayer = CClients::getListenServerClient(); - - CBaseEntity *pEntity = RCBotPluginMeta::TF2_getPlayerWeaponSlot(pPlayer, TF2_SLOT_PRMRY); - - if (pEntity != NULL) - { - edict_t *pEdict = servergameents->BaseEntityToEdict(pEntity); - - if (pEdict && !pEdict->IsFree()) - { - const char *strAttrib = args.Arg(1); - float flVal = atof(args.Arg(2)); - //void (edict_t *pEdict, const char *szName, float flVal) - if (TF2_setAttribute(pEdict, strAttrib, flVal)) - CBotGlobals::botMessage(NULL, 0, "OK"); - else - CBotGlobals::botMessage(NULL, 0, "FAIL"); - - RCBotPluginMeta::TF2_ClearAttributeCache(pPlayer); - } - } - } -} +static ConVar rcbot2_ver_cvar("rcbot_ver", build_info::long_version, FCVAR_REPLICATED, "RCBot version"); CON_COMMAND(rcbotd, "access the bot commands on a server") { - eBotCommandResult iResult; - if (!engine->IsDedicatedServer() || !CBotGlobals::IsMapRunning()) { - CBotGlobals::botMessage(NULL, 0, "Error, no map running or not dedicated server"); + logger->Log(LogLevel::ERROR, "Error, no map running or not dedicated server"); return; } - //iResult = CBotGlobals::m_pCommands->execute(NULL,engine->Cmd_Argv(1),engine->Cmd_Argv(2),engine->Cmd_Argv(3),engine->Cmd_Argv(4),engine->Cmd_Argv(5),engine->Cmd_Argv(6)); - iResult = CBotGlobals::m_pCommands->execute(NULL, args.Arg(1), args.Arg(2), args.Arg(3), args.Arg(4), args.Arg(5), args.Arg(6)); + // shift args and call subcommand + BotCommandArgs argList; + for (unsigned i = 1; i <= static_cast(args.ArgC()); i++) { + argList.emplace_back(args.Arg(static_cast(i))); + } + const eBotCommandResult iResult = CBotGlobals::m_pCommands->execute(nullptr, argList); if (iResult == COMMAND_ACCESSED) { @@ -239,117 +138,31 @@ CON_COMMAND(rcbotd, "access the bot commands on a server") } else if (iResult == COMMAND_REQUIRE_ACCESS) { - CBotGlobals::botMessage(NULL, 0, "You do not have access to this command"); + logger->Log(LogLevel::ERROR, "You do not have access to this command"); } else if (iResult == COMMAND_NOT_FOUND) { - CBotGlobals::botMessage(NULL, 0, "bot command not found"); + logger->Log(LogLevel::ERROR, "bot command not found"); } else if (iResult == COMMAND_ERROR) { - CBotGlobals::botMessage(NULL, 0, "bot command returned an error"); + logger->Log(LogLevel::ERROR, "bot command returned an error"); } } -/* -bool RCBotPluginMeta :: ClearAttributeCache(edict_t *pedict) -{ - if (hSDKOnAttribValuesChanged == INVALID_HANDLE) return false; - - if (pedict == NULL || pedict->IsFree() ) - return false; - - new offs = GetEntSendPropOffs(entity, "m_AttributeList", true); - if (offs <= 0) return false; - new Address:pAttribs = GetEntityAddress(entity); - if (pAttribs < Address_MinimumValid) return false; - pAttribs = Address:LoadFromAddress(pAttribs + Address:(offs + 24), NumberType_Int32); - if (pAttribs < Address_MinimumValid) return false; - SDKCall(hSDKOnAttribValuesChanged, pAttribs); - return true; -}*/ - - -CBaseEntity *RCBotPluginMeta::TF2_getPlayerWeaponSlot(edict_t *pPlayer, int iSlot) -{ - CBaseEntity *pEnt = servergameents->EdictToBaseEntity(pPlayer); - - return SH_MCALL(pEnt, MHook_GetPlayerWeaponSlot)(iSlot); -} - -void RCBotPluginMeta::TF2_removeWearable(edict_t *pPlayer, CBaseEntity *pWearable) -{ - CBaseEntity *pEnt = servergameents->EdictToBaseEntity(pPlayer); - - SH_MCALL(pEnt, MHook_RemoveWearable)(pWearable); -} - - -void RCBotPluginMeta::TF2_equipWearable(edict_t *pPlayer, CBaseEntity *pWearable) -{ - CBaseEntity *pEnt = servergameents->EdictToBaseEntity(pPlayer); - - SH_MCALL(pEnt, MHook_EquipWearable)((CEconWearable*)pWearable); -} -/* -"CAttributeManager::OnAttributeValuesChanged" //use instead of ClearCache/NotifyManagerOfAttributeValueChanges -{ - "windows" "12" - "linux" "13" - "mac" "13" -} -*/ -bool RCBotPluginMeta::TF2_ClearAttributeCache(edict_t *pEdict) -{ - CAttributeList *pList = CClassInterface::getAttributeList(pEdict); - - CAttributeManager *pManager = (CAttributeManager*)(((unsigned int)pList) + 24); - - if (!pManager) - return false; - - unsigned int *mem = (unsigned int*)*(unsigned int*)pManager; - - if (!mem) - return false; - - int offset = 12; - - *(unsigned int*)&OnAttributeValuesChanged = mem[offset]; - - if (!OnAttributeValuesChanged) - return false; - - (*pManager.*OnAttributeValuesChanged)(); - - return true; -} -void RCBotPluginMeta::TF2_equipWeapon(edict_t *pPlayer, CBaseEntity *pWeapon) -{ - CBaseEntity *pEnt = servergameents->EdictToBaseEntity(pPlayer); - - SH_MCALL(pEnt, MHook_EquipWeapon)(pWeapon); -} - -void RCBotPluginMeta::TF2_removePlayerItem(edict_t *pPlayer, CBaseEntity *pItem) -{ - CBaseEntity *pEnt = servergameents->EdictToBaseEntity(pPlayer); - - SH_MCALL(pEnt, MHook_RemovePlayerItem)(pItem); -} class CBotRecipientFilter : public IRecipientFilter { public: - CBotRecipientFilter(edict_t *pPlayer) + CBotRecipientFilter(const edict_t *pPlayer) { m_iPlayerSlot = ENTINDEX(pPlayer); } - bool IsReliable(void) const { return false; } - bool IsInitMessage(void) const { return false; } + bool IsReliable() const override { return false; } + bool IsInitMessage() const override { return false; } - int GetRecipientCount(void) const { return 1; } - int GetRecipientIndex(int slot) const { return m_iPlayerSlot; } + int GetRecipientCount() const override { return 1; } + int GetRecipientIndex(int slot) const override { return m_iPlayerSlot; } private: int m_iPlayerSlot; @@ -359,14 +172,16 @@ class CClientBroadcastRecipientFilter : public IRecipientFilter { public: - CClientBroadcastRecipientFilter() { - m_iMaxCount = 0; + CClientBroadcastRecipientFilter() : m_iMaxCount(0) { - for (int i = 0; i < MAX_PLAYERS; ++i) { + // Initialize m_iPlayerSlot with a default value, e.g., -1 + std::fill(std::begin(m_iPlayerSlot), std::end(m_iPlayerSlot), -1); + + for (int i = 0; i < RCBOT_MAXPLAYERS; ++i) { CClient* client = CClients::get(i); if (client->isUsed()) { - IPlayerInfo *p = playerinfomanager->GetPlayerInfo(client->getPlayer()); + IPlayerInfo* p = playerinfomanager->GetPlayerInfo(client->getPlayer()); if (p->IsConnected() && !p->IsFakeClient()) { m_iPlayerSlot[m_iMaxCount] = i; @@ -376,36 +191,36 @@ class CClientBroadcastRecipientFilter : public IRecipientFilter } } - bool IsReliable(void) const { return false; } - bool IsInitMessage(void) const { return false; } + bool IsReliable() const override { return false; } + bool IsInitMessage() const override { return false; } - int GetRecipientCount(void) const { return m_iMaxCount; } - int GetRecipientIndex(int slot) const { return m_iPlayerSlot[slot] + 1; } + int GetRecipientCount() const override { return m_iMaxCount; } + int GetRecipientIndex(const int slot) const override { return m_iPlayerSlot[slot] + 1; } private: int m_iMaxCount; - int m_iPlayerSlot[MAX_PLAYERS]; + int m_iPlayerSlot[RCBOT_MAXPLAYERS]; }; /////////////// // hud message /////////////// -void RCBotPluginMeta::HudTextMessage(edict_t *pEntity, const char *szMessage) +void RCBotPluginMeta::HudTextMessage(const edict_t* pEntity, const char* szMessage) { int msgid = 0; int imsgsize = 0; char msgbuf[64]; - bool bOK; + bool bOK; //Unused? [APG]RoboCop[CL] int hint = -1; int say = -1; while ((bOK = servergamedll->GetUserMessageInfo(msgid, msgbuf, 63, imsgsize)) == true) { - if (strcmp(msgbuf, "HintText") == 0) + if (std::strcmp(msgbuf, "HintText") == 0) hint = msgid; - else if (strcmp(msgbuf, "SayText") == 0) + else if (std::strcmp(msgbuf, "SayText") == 0) say = msgid; msgid++; @@ -417,12 +232,12 @@ void RCBotPluginMeta::HudTextMessage(edict_t *pEntity, const char *szMessage) // if (!bOK) // return; - CBotRecipientFilter *filter = new CBotRecipientFilter(pEntity); + CBotRecipientFilter filter(pEntity); - bf_write *buf = nullptr; + bf_write* buf; if (hint > 0) { - buf = engine->UserMessageBegin(filter, hint); + buf = engine->UserMessageBegin(&filter, hint); buf->WriteString(szMessage); engine->MessageEnd(); } @@ -431,32 +246,30 @@ void RCBotPluginMeta::HudTextMessage(edict_t *pEntity, const char *szMessage) char chatline[128]; snprintf(chatline, sizeof(chatline), "\x01\x04[RCBot2]\x01 %s\n", szMessage); - buf = engine->UserMessageBegin(filter, say); + buf = engine->UserMessageBegin(&filter, say); buf->WriteString(chatline); engine->MessageEnd(); } - - delete filter; } ////////////////////////// // chat broadcast message ////////////////////////// -void RCBotPluginMeta::BroadcastTextMessage(const char *szMessage) +void RCBotPluginMeta::BroadcastTextMessage(const char* szMessage) { int msgid = 0; int imsgsize = 0; char msgbuf[64]; - bool bOK; + bool bOK; //Unused? [APG]RoboCop[CL] - int hint = -1; + int hint = -1; //Unused? [APG]RoboCop[CL] int say = -1; while ((bOK = servergamedll->GetUserMessageInfo(msgid, msgbuf, 63, imsgsize)) == true) { - if (strcmp(msgbuf, "HintText") == 0) + if (std::strcmp(msgbuf, "HintText") == 0) hint = msgid; - else if (strcmp(msgbuf, "SayText") == 0) + else if (std::strcmp(msgbuf, "SayText") == 0) say = msgid; msgid++; @@ -465,106 +278,15 @@ void RCBotPluginMeta::BroadcastTextMessage(const char *szMessage) if (msgid == 0) return; - CClientBroadcastRecipientFilter *filter = new CClientBroadcastRecipientFilter(); - - bf_write *buf = nullptr; - + CClientBroadcastRecipientFilter filter; // Allocate on stack if (say > 0) { char chatline[128]; snprintf(chatline, sizeof(chatline), "\x01\x04[RCBot2]\x01 %s\n", szMessage); - buf = engine->UserMessageBegin(filter, say); + bf_write* buf = engine->UserMessageBegin(&filter, say); buf->WriteString(chatline); engine->MessageEnd(); } - - delete filter; -} - -void RCBotPluginMeta::TF2_RemoveWeaponSlot(edict_t *pPlayer, int iSlot) -{ - CBaseEntity *pWeaponInSlot = RCBotPluginMeta::TF2_getPlayerWeaponSlot(pPlayer, iSlot); - - if (pWeaponInSlot) - { - // bug #6206 - // papering over a valve bug where a weapon's extra wearables aren't properly removed from the weapon's owner - edict_t *extraWearable = CClassInterface::getExtraWearable(pPlayer); - - if (extraWearable != NULL) - { - CBaseEntity *pEnt = servergameents->EdictToBaseEntity(extraWearable); - RCBotPluginMeta::TF2_removeWearable(pPlayer, pEnt); - engine->RemoveEdict(extraWearable); - } - - extraWearable = CClassInterface::getExtraWearableViewModel(pPlayer); - - if (extraWearable != NULL) - { - CBaseEntity *pEnt = servergameents->EdictToBaseEntity(extraWearable); - RCBotPluginMeta::TF2_removeWearable(pPlayer, pEnt); - engine->RemoveEdict(extraWearable); - } - - RCBotPluginMeta::TF2_removePlayerItem(pPlayer, pWeaponInSlot); - - edict_t *pWeaponInSlotEdict = servergameents->BaseEntityToEdict(pWeaponInSlot); - //AcceptEntityInput(weaponIndex, "Kill"); - engine->RemoveEdict(pWeaponInSlotEdict); - } -} - -void RCBotPluginMeta::giveRandomLoadout(edict_t *pPlayer, int iClass, int iSlot, void *pVTable, void *pVTable_Attributes) -{ - CTF2Loadout *p = CTeamFortress2Mod::findRandomWeaponLoadOutInSlot(iClass, iSlot); - - if (p) - { - RCBotPluginMeta::givePlayerLoadOut(pPlayer, p, iSlot, pVTable, pVTable_Attributes); - } -} - -// TF2 Items -bool RCBotPluginMeta::givePlayerLoadOut(edict_t *pPlayer, CTF2Loadout *pLoadout, int iSlot, void *pVTable, void *pVTable_Attributes) -{ - CBaseEntity *pEnt = servergameents->EdictToBaseEntity(pPlayer); - // first remove any thing from the slot - RCBotPluginMeta::TF2_RemoveWeaponSlot(pPlayer, iSlot); - - CEconItemView hScriptCreatedItem; - memset(&hScriptCreatedItem, 0, sizeof(CEconItemView)); - - hScriptCreatedItem.m_pVTable = pVTable; - hScriptCreatedItem.m_AttributeList.m_pVTable = pVTable_Attributes; - hScriptCreatedItem.m_NetworkedDynamicAttributesForDemos.m_pVTable = pVTable_Attributes; - - const char *strWeaponClassname = pLoadout->m_pszClassname; - hScriptCreatedItem.m_iItemDefinitionIndex = pLoadout->m_iIndex; - hScriptCreatedItem.m_iEntityLevel = randomInt(pLoadout->m_iMinLevel, pLoadout->m_iMaxLevel); - hScriptCreatedItem.m_iEntityQuality = pLoadout->m_iQuality; - CEconItemAttribute attribs[16]; - int iSize = pLoadout->copyAttributesIntoArray(attribs, pVTable); - hScriptCreatedItem.m_AttributeList.m_Attributes.CopyArray(attribs, iSize);// pLoadout->m_Attributes, pLoadout->m_Attributes.size()); - hScriptCreatedItem.m_bInitialized = true; - hScriptCreatedItem.m_bDoNotIterateStaticAttributes = false; // true breaks pyro bot flamethrowers - - if (hScriptCreatedItem.m_iEntityQuality == 0 && iSize > 0) - { - hScriptCreatedItem.m_iEntityQuality = 6; - } - - CBaseEntity *added = SH_MCALL(pEnt, MHook_GiveNamedItem)(strWeaponClassname, 0, &hScriptCreatedItem, rcbot_force_generation.GetBool()); - - if (added) - { - if ((iSlot == TF2_SLOT_MELEE) || (iSlot == TF2_SLOT_PRMRY) || (iSlot == TF2_SLOT_SCNDR)) - RCBotPluginMeta::TF2_equipWeapon(pPlayer, added); - else - RCBotPluginMeta::TF2_equipWearable(pPlayer, added); - } - - return added != NULL; } void RCBotPluginMeta::Hook_PlayerRunCmd(CUserCmd *ucmd, IMoveHelper *moveHelper) @@ -573,7 +295,7 @@ void RCBotPluginMeta::Hook_PlayerRunCmd(CUserCmd *ucmd, IMoveHelper *moveHelper) CBaseEntity *pPlayer = META_IFACEPTR(CBaseEntity); - edict_t *pEdict = servergameents->BaseEntityToEdict(pPlayer); + const edict_t *pEdict = servergameents->BaseEntityToEdict(pPlayer); pBot = CBots::getBotPointer(pEdict); @@ -594,223 +316,66 @@ void RCBotPluginMeta::Hook_PlayerRunCmd(CUserCmd *ucmd, IMoveHelper *moveHelper) ucmd->weaponsubtype = cmd->weaponsubtype; ucmd->tick_count = cmd->tick_count; ucmd->command_number = cmd->command_number; - - g_pLastBot = (CBotTF2*)pBot; } - -//g_pSM->LogMessage(NULL, "H %i %i %f %f %f %f %i", ucmd->command_number, ucmd->tick_count, ucmd->viewangles.x, ucmd->viewangles.y, ucmd->viewangles.z, ucmd->forwardmove, ucmd->buttons); - -RETURN_META(MRES_IGNORED); -} - - -void RCBotPluginMeta::Hook_EquipWeapon(CBaseEntity *pWeapon) -{ - RETURN_META(MRES_IGNORED); -} - - -CBaseEntity *RCBotPluginMeta::Hook_GetPlayerWeaponSlot(int iSlot) -{ - RETURN_META_VALUE(MRES_IGNORED, NULL); -} -void RCBotPluginMeta::Hook_RemoveWearable(CBaseEntity *pWearable) -{ RETURN_META(MRES_IGNORED); } - -void RCBotPluginMeta::Hook_RemovePlayerItem(CBaseEntity *pWeapon) -{ - RETURN_META(MRES_IGNORED); -} - -void RCBotPluginMeta::Hook_EquipWearable(CEconWearable *pItem) -{ - RETURN_META(MRES_IGNORED); -} - - -CBaseEntity *RCBotPluginMeta::Hook_GiveNamedItem( const char *name, int subtype, CEconItemView *cscript, bool b ) -{ - CBaseEntity *pPlayer = META_IFACEPTR(CBaseEntity); - edict_t *pEdict = servergameents->BaseEntityToEdict(pPlayer); - CBot *pBot = NULL; - - if (rcbot_customloadouts.GetBool() && ((pBot = CBots::getBotPointer(pEdict)) != NULL) && cscript) - { - ((CBotTF2*)pBot)->PostGiveNamedItem(cscript); - } - - RETURN_META_VALUE(MRES_IGNORED, NULL); -} /** * Something like this is needed to register cvars/CON_COMMANDs. */ class BaseAccessor : public IConCommandBaseAccessor { public: - bool RegisterConCommandBase(ConCommandBase *pCommandBase) + virtual ~BaseAccessor() = default; + + bool RegisterConCommandBase(ConCommandBase *pCommandBase) override { /* Always call META_REGCVAR instead of going through the engine. */ return META_REGCVAR(pCommandBase); } } s_BaseAccessor; -// --- you're going to take over message begin -bf_write *RCBotPluginMeta::Hook_MessageBegin(IRecipientFilter *filter, int msg_type) -{ - /* - bool bfound = false; - - for (int i = 0; i < filter->GetRecipientCount(); i++) - { - if (filter->GetRecipientIndex(i) == 1) - { - bfound = true; - break; - } - } - - if (bfound) - { - - int msgid = 0; - int imsgsize = 0; - char msgbuf[64]; - bool bOK; - - if (servergamedll->GetUserMessageInfo(msg_type, msgbuf, 63, imsgsize)) - { - sprintf(current_msg_buffer, "MessageBegin() msg_type = %d name = %s\n", msg_type,msgbuf); - } - - } - else - current_msg_buffer[0] = 0; - - current_msg = SH_CALL(engine, &IVEngineServer::UserMessageBegin)(filter, msg_type); - - if (current_msg) - { - SH_ADD_HOOK_MEMFUNC(bf_write, WriteString, current_msg, this, &RCBotPluginMeta::Hook_WriteString, true); - SH_ADD_HOOK_MEMFUNC(bf_write, WriteByte, current_msg, this, &RCBotPluginMeta::Hook_WriteByte, true); - SH_ADD_HOOK_MEMFUNC(bf_write, WriteChar, current_msg, this, &RCBotPluginMeta::Hook_WriteChar, true); - SH_ADD_HOOK_MEMFUNC(bf_write, WriteShort, current_msg, this, &RCBotPluginMeta::Hook_WriteShort, true); - SH_ADD_HOOK_MEMFUNC(bf_write, WriteFloat, current_msg, this, &RCBotPluginMeta::Hook_WriteFloat, true); - } - - // - RETURN_META_VALUE(MRES_SUPERCEDE, current_msg);*/ - - RETURN_META_VALUE(MRES_IGNORED, NULL); -} - -void RCBotPluginMeta::Hook_WriteChar(int val) -{ - /*char tocat[64]; - - sprintf(tocat, "\nWriteChar(%c)", (char)val); - strcat(current_msg_buffer, tocat);*/ -} -void RCBotPluginMeta::Hook_WriteShort(int val) -{ - /*char tocat[64]; - - sprintf(tocat, "\nWriteShort(%d)", val); - strcat(current_msg_buffer, tocat);*/ -} -void RCBotPluginMeta::Hook_WriteByte(int val) -{ - /*char tocat[64]; - - sprintf(tocat, "\nWriteByte(%d)", val); - strcat(current_msg_buffer, tocat);*/ -} -void RCBotPluginMeta::Hook_WriteFloat(float val) -{ - /*char tocat[64]; - - sprintf(tocat, "\nWriteFloat(%0.1f)", val); - strcat(current_msg_buffer, tocat);*/ -} - -bool RCBotPluginMeta::Hook_WriteString(const char *pStr) -{ - /*char *tocat = new char[strlen(pStr) + 16]; - - sprintf(tocat, "\nWriteString(%s)", pStr); - strcat(current_msg_buffer, tocat); - - delete tocat;*/ - - RETURN_META_VALUE(MRES_IGNORED, false); -} - -void RCBotPluginMeta::Hook_MessageEnd() -{ - // probe the current_msg m_pData - // deep copy the data because it might free itself later - //strncpy(current_msg_buffer, (char*)current_msg->m_pData, BUF_SIZ - 1); - //current_msg_buffer[BUF_SIZ - 1] = 0; - /*if (current_msg) - { - SH_REMOVE_HOOK_MEMFUNC(bf_write, WriteString, current_msg, this, &RCBotPluginMeta::Hook_WriteString, true); - SH_REMOVE_HOOK_MEMFUNC(bf_write, WriteByte, current_msg, this, &RCBotPluginMeta::Hook_WriteByte, true); - SH_REMOVE_HOOK_MEMFUNC(bf_write, WriteChar, current_msg, this, &RCBotPluginMeta::Hook_WriteChar, true); - SH_REMOVE_HOOK_MEMFUNC(bf_write, WriteShort, current_msg, this, &RCBotPluginMeta::Hook_WriteShort, true); - SH_REMOVE_HOOK_MEMFUNC(bf_write, WriteFloat, current_msg, this, &RCBotPluginMeta::Hook_WriteFloat, true); - } - - current_msg_buffer[0] = 0;*/ - - RETURN_META(MRES_IGNORED); -} - -bool RCBotPluginMeta::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late) +bool RCBotPluginMeta::Load(PluginId id, ISmmAPI *ismm, char *error, std::size_t maxlen, bool late) { extern MTRand_int32 irand; - PLUGIN_SAVEVARS(); + PLUGIN_SAVEVARS() - GET_V_IFACE_CURRENT(GetEngineFactory, enginetrace, IEngineTrace, INTERFACEVERSION_ENGINETRACE_SERVER); - GET_V_IFACE_CURRENT(GetEngineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER); - GET_V_IFACE_CURRENT(GetEngineFactory, gameevents, IGameEventManager2, INTERFACEVERSION_GAMEEVENTSMANAGER2); - GET_V_IFACE_CURRENT(GetEngineFactory, helpers, IServerPluginHelpers, INTERFACEVERSION_ISERVERPLUGINHELPERS); - GET_V_IFACE_CURRENT(GetEngineFactory, icvar, ICvar, CVAR_INTERFACE_VERSION); + GET_V_IFACE_CURRENT(GetEngineFactory, enginetrace, IEngineTrace, INTERFACEVERSION_ENGINETRACE_SERVER) + GET_V_IFACE_CURRENT(GetEngineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER) + GET_V_IFACE_CURRENT(GetEngineFactory, gameevents, IGameEventManager2, INTERFACEVERSION_GAMEEVENTSMANAGER2) + GET_V_IFACE_CURRENT(GetEngineFactory, helpers, IServerPluginHelpers, INTERFACEVERSION_ISERVERPLUGINHELPERS) + GET_V_IFACE_CURRENT(GetEngineFactory, icvar, ICvar, CVAR_INTERFACE_VERSION) + GET_V_IFACE_CURRENT(GetEngineFactory, staticpropmgr, IStaticPropMgrServer, INTERFACEVERSION_STATICPROPMGR_SERVER) GET_V_IFACE_ANY(GetEngineFactory, filesystem, IFileSystem, FILESYSTEM_INTERFACE_VERSION) - GET_V_IFACE_ANY(GetServerFactory, servergameents, IServerGameEnts, INTERFACEVERSION_SERVERGAMEENTS); - GET_V_IFACE_ANY(GetServerFactory, server, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL); - GET_V_IFACE_ANY(GetServerFactory, gameclients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS); - GET_V_IFACE_ANY(GetServerFactory, playerinfomanager, IPlayerInfoManager, INTERFACEVERSION_PLAYERINFOMANAGER); + GET_V_IFACE_ANY(GetServerFactory, servergameents, IServerGameEnts, INTERFACEVERSION_SERVERGAMEENTS) + GET_V_IFACE_ANY(GetServerFactory, server, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL) + GET_V_IFACE_ANY(GetServerFactory, gameclients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS) + GET_V_IFACE_ANY(GetServerFactory, playerinfomanager, IPlayerInfoManager, INTERFACEVERSION_PLAYERINFOMANAGER) - GET_V_IFACE_ANY(GetServerFactory, g_pEffects, IEffects, IEFFECTS_INTERFACE_VERSION); - GET_V_IFACE_ANY(GetServerFactory, g_pBotManager, IBotManager, INTERFACEVERSION_PLAYERBOTMANAGER); - GET_V_IFACE_ANY(GetServerFactory, servertools, IServerTools, VSERVERTOOLS_INTERFACE_VERSION); + GET_V_IFACE_ANY(GetServerFactory, g_pEffects, IEffects, IEFFECTS_INTERFACE_VERSION) + GET_V_IFACE_ANY(GetServerFactory, g_pBotManager, IBotManager, INTERFACEVERSION_PLAYERBOTMANAGER) + GET_V_IFACE_ANY(GetServerFactory, servertools, IServerTools, VSERVERTOOLS_INTERFACE_VERSION) #ifndef __linux__ - GET_V_IFACE_CURRENT(GetEngineFactory,debugoverlay, IVDebugOverlay, VDEBUG_OVERLAY_INTERFACE_VERSION); + GET_V_IFACE_CURRENT(GetEngineFactory,debugoverlay, IVDebugOverlay, VDEBUG_OVERLAY_INTERFACE_VERSION) #endif - GET_V_IFACE_ANY(GetServerFactory, servergamedll, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL); - GET_V_IFACE_ANY(GetServerFactory, gameclients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS); + GET_V_IFACE_ANY(GetServerFactory, servergamedll, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL) + GET_V_IFACE_ANY(GetServerFactory, gameclients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS) gpGlobals = ismm->GetCGlobals(); META_LOG(g_PLAPI, "Starting plugin."); /* Load the VSP listener. This is usually needed for IServerPluginHelpers. */ - if ((vsp_callbacks = ismm->GetVSPInfo(NULL)) == NULL) + ismm->AddListener(this, this); + if ((vsp_callbacks = ismm->GetVSPInfo(nullptr)) == nullptr) { - ismm->AddListener(this, this); ismm->EnableVSPListener(); } - - /*SH_ADD_HOOK_MEMFUNC(IVEngineServer, UserMessageBegin, engine, this, &RCBotPluginMeta::Hook_MessageBegin, false); - SH_ADD_HOOK_MEMFUNC(IVEngineServer, MessageEnd, engine, this, &RCBotPluginMeta::Hook_MessageEnd, false);*/ - SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelInit, server, this, &RCBotPluginMeta::Hook_LevelInit, true); SH_ADD_HOOK_MEMFUNC(IServerGameDLL, ServerActivate, server, this, &RCBotPluginMeta::Hook_ServerActivate, true); SH_ADD_HOOK_MEMFUNC(IServerGameDLL, GameFrame, server, this, &RCBotPluginMeta::Hook_GameFrame, true); @@ -818,14 +383,11 @@ bool RCBotPluginMeta::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxle SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientActive, gameclients, this, &RCBotPluginMeta::Hook_ClientActive, true); SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, gameclients, this, &RCBotPluginMeta::Hook_ClientDisconnect, true); SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientPutInServer, gameclients, this, &RCBotPluginMeta::Hook_ClientPutInServer, true); - SH_ADD_HOOK_MEMFUNC(IServerGameClients, SetCommandClient, gameclients, this, &RCBotPluginMeta::Hook_SetCommandClient, true); - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientSettingsChanged, gameclients, this, &RCBotPluginMeta::Hook_ClientSettingsChanged, false); SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientConnect, gameclients, this, &RCBotPluginMeta::Hook_ClientConnect, false); SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientCommand, gameclients, this, &RCBotPluginMeta::Hook_ClientCommand, false); //Hook FireEvent to our function - unstable for TF2? [APG]RoboCop[CL] SH_ADD_HOOK_MEMFUNC(IGameEventManager2, FireEvent, gameevents, this, &RCBotPluginMeta::FireGameEvent, false); - #if SOURCE_ENGINE >= SE_ORANGEBOX g_pCVar = icvar; ConVar_Register(0, &s_BaseAccessor); @@ -833,6 +395,11 @@ bool RCBotPluginMeta::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxle ConCommandBaseMgr::OneTimeInit(&s_BaseAccessor); #endif +#if SOURCE_ENGINE!=SE_DARKMESSIAH + // read loglevel from startup param for early logging + ConVarRef rcbot_loglevel("rcbot_loglevel"); + rcbot_loglevel.SetValue(CommandLine()->ParmValue("+rcbot_loglevel", rcbot_loglevel.GetInt())); +#endif // Read Signatures and Offsets CBotGlobals::initModFolder(); @@ -842,136 +409,84 @@ bool RCBotPluginMeta::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxle // Load RCBOT2 hook data CBotGlobals::buildFileName(filename, "hookinfo", BOT_CONFIG_FOLDER, "ini"); - FILE *fp = fopen(filename, "r"); + std::fstream fp(filename, std::fstream::in); - CRCBotKeyValueList *pKVL = new CRCBotKeyValueList(); + CRCBotKeyValueList kvl; if (fp) - pKVL->parseFile(fp); + kvl.parseFile(fp); void *gameServerFactory = reinterpret_cast(ismm->GetServerFactory(false)); int val; -#ifdef _WIN32 - - if (pKVL->getInt("givenameditem_win", &val)) - rcbot_givenameditem_offset.SetValue(val); - if (pKVL->getInt("equipwearable_win", &val)) - rcbot_equipwearable_offset.SetValue(val); - if (pKVL->getInt("runplayermove_tf2_win", &val)) - rcbot_runplayercmd_tf2.SetValue(val); - if (pKVL->getInt("runplayermove_dods_win", &val)) +#if defined(_WIN64) || defined(_WIN32) + if (kvl.getInt("runplayermove_dods_win", &val)) rcbot_runplayercmd_dods.SetValue(val); - if (pKVL->getInt("getweaponslot_win", &val)) - rcbot_getweaponslot_offset.SetValue(val); - if (pKVL->getInt("removewearable_win", &val)) - rcbot_removewearable_offset.SetValue(val); - if (pKVL->getInt("removeplayeritem_win", &val)) - rcbot_rmplayeritem_offset.SetValue(val); - if (pKVL->getInt("weaponequip_win", &val)) - rcbot_weaponequip_offset.SetValue(val); - if (pKVL->getInt("gamerules_win", &val)) + if (kvl.getInt("gamerules_win", &val)) rcbot_gamerules_offset.SetValue(val); - if (pKVL->getInt("mstr_offset_win", &val)) { - rcbot_const_point_master_offset.SetValue(val); - //rcbot_const_round_offset.SetValue(val); - } + if (kvl.getInt("runplayermove_synergy_win", &val)) + rcbot_runplayercmd_syn.SetValue(val); + if (kvl.getInt("getdatadescmap_win", &val)) + rcbot_datamap_offset.SetValue(val); #else - - if (pKVL->getInt("givenameditem_linux", &val)) - rcbot_givenameditem_offset.SetValue(val); - if (pKVL->getInt("equipwearable_linux", &val)) - rcbot_equipwearable_offset.SetValue(val); - if (pKVL->getInt("runplayermove_tf2_linux", &val)) - rcbot_runplayercmd_tf2.SetValue(val); - if (pKVL->getInt("runplayermove_dods_linux", &val)) + if (kvl.getInt("runplayermove_dods_linux", &val)) rcbot_runplayercmd_dods.SetValue(val); - if (pKVL->getInt("getweaponslot_linux", &val)) - rcbot_getweaponslot_offset.SetValue(val); - if (pKVL->getInt("removewearable_linux", &val)) - rcbot_removewearable_offset.SetValue(val); - if (pKVL->getInt("removeplayeritem_linux", &val)) - rcbot_rmplayeritem_offset.SetValue(val); - if (pKVL->getInt("weaponequip_linux", &val)) - rcbot_weaponequip_offset.SetValue(val); - if (pKVL->getInt("mstr_offset_linux", &val)) { - rcbot_const_point_master_offset.SetValue(val); - //rcbot_const_round_offset.SetValue(val); - } + if (kvl.getInt("runplayermove_synergy_linux", &val)) + rcbot_runplayercmd_syn.SetValue(val); + if (kvl.getInt("getdatadescmap_linux", &val)) + rcbot_datamap_offset.SetValue(val); #endif - g_pGetEconItemSchema = new CGetEconItemSchema(pKVL, gameServerFactory); - g_pSetRuntimeAttributeValue = new CSetRuntimeAttributeValue(pKVL, gameServerFactory); - g_pGetAttributeDefinitionByName = new CGetAttributeDefinitionByName(pKVL, gameServerFactory); - g_pAttribList_GetAttributeByID = new CAttributeList_GetAttributeByID(pKVL, gameServerFactory); - g_pGameRules_Obj = new CGameRulesObject(pKVL, gameServerFactory); - g_pGameRules_Create_Obj = new CCreateGameRulesObject(pKVL, gameServerFactory); - g_pGetAttributeDefinitionByID = new CGetAttributeDefinitionByID(pKVL, gameServerFactory); - - delete pKVL; + g_pGameRules_Obj = new CGameRulesObject(kvl, gameServerFactory); + g_pGameRules_Create_Obj = new CCreateGameRulesObject(kvl, gameServerFactory); if (fp) - fclose(fp); + fp.close(); if (!CBotGlobals::gameStart()) return false; - CBotMod *pMod = CBotGlobals::getCurrentMod(); + CBotMod *pMod = CBotGlobals::getCurrentMod(); // `*pMod` Unused? [APG]RoboCop[CL] - if (CBots::controlBots()) +#ifdef OVERRIDE_RUNCMD + // TODO figure out a more robust gamedata fix instead of vtable + #if SOURCE_ENGINE == SE_DODS + SH_MANUALHOOK_RECONFIGURE(MHook_PlayerRunCmd, rcbot_runplayercmd_dods.GetInt(), 0, 0); + #elif SOURCE_ENGINE == SE_SDK2013 + if(pMod->getModId() == MOD_SYNERGY) { - if (pMod->getModId() == MOD_TF2) - SH_MANUALHOOK_RECONFIGURE(MHook_PlayerRunCmd, rcbot_runplayercmd_tf2.GetInt(), 0, 0); - else if (pMod->getModId() == MOD_DOD) - SH_MANUALHOOK_RECONFIGURE(MHook_PlayerRunCmd, rcbot_runplayercmd_dods.GetInt(), 0, 0); + SH_MANUALHOOK_RECONFIGURE(MHook_PlayerRunCmd, rcbot_runplayercmd_syn.GetInt(), 0, 0); } - if (pMod->getModId() == MOD_TF2) - { - if (rcbot_givenameditem_offset.GetInt() > 0) - SH_MANUALHOOK_RECONFIGURE(MHook_GiveNamedItem, rcbot_givenameditem_offset.GetInt(), 0, 0); - - if (rcbot_equipwearable_offset.GetInt() > 0) - SH_MANUALHOOK_RECONFIGURE(MHook_EquipWearable, rcbot_equipwearable_offset.GetInt(), 0, 0); - - if (rcbot_weaponequip_offset.GetInt() > 0) - SH_MANUALHOOK_RECONFIGURE(MHook_EquipWeapon, rcbot_weaponequip_offset.GetInt(), 0, 0); - - if (rcbot_rmplayeritem_offset.GetInt() > 0) - SH_MANUALHOOK_RECONFIGURE(MHook_RemovePlayerItem, rcbot_rmplayeritem_offset.GetInt(), 0, 0); +#endif - if (rcbot_getweaponslot_offset.GetInt() > 0) - SH_MANUALHOOK_RECONFIGURE(MHook_GetPlayerWeaponSlot, rcbot_getweaponslot_offset.GetInt(), 0, 0); +#endif - if (rcbot_removewearable_offset.GetInt() > 0) - SH_MANUALHOOK_RECONFIGURE(MHook_RemoveWearable, rcbot_removewearable_offset.GetInt(), 0, 0); - } ENGINE_CALL(LogPrint)("All hooks started!\n"); - - //MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f ); //ConVar_Register( 0 ); //InitCVars( interfaceFactory ); // register any cvars we have defined - srand( (unsigned)time(NULL) ); // initialize the random seed - irand.seed( (unsigned)time(NULL) ); + std::srand( static_cast(time(nullptr)) ); // initialize the random seed + MTRand_int32::seed( static_cast(time(nullptr)) ); // Find the RCBOT2 Path from metamod VDF - extern IFileSystem *filesystem; - KeyValues *mainkv = new KeyValues("metamodplugin"); - - const char *rcbot2path; - CBotGlobals::botMessage(NULL, 0, "Reading rcbot2 path from VDF..."); - + extern IFileSystem* filesystem; + KeyValues* mainkv = new KeyValues("metamodplugin"); + + const char* rcbot2path; //Unused? [APG]RoboCop[CL] + logger->Log(LogLevel::INFO, "Reading rcbot2 path from VDF..."); + mainkv->LoadFromFile(filesystem, "addons/metamod/rcbot2.vdf", "MOD"); - - mainkv = mainkv->FindKey("Metamod Plugin"); + KeyValues* temp = mainkv->FindKey("Metamod Plugin"); + + if (temp) + rcbot2path = temp->GetString("rcbot2path", "\0"); - if (mainkv) - rcbot2path = mainkv->GetString("rcbot2path", "\0"); + mainkv->deleteThis(); //mainkv possible redundant? [APG]RoboCop[CL] + mainkv = temp; // Memory leak fix [APG]RoboCop[CL] - mainkv->deleteThis(); //eventListener2 = new CRCBotEventListener(); // Initialize bot variables @@ -989,7 +504,7 @@ bool RCBotPluginMeta::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxle //CRCBotPlugin::ShowLicense(); - //RandomSeed((unsigned int)time(NULL)); + //RandomSeed((unsigned)time(NULL)); CClassInterface::init(); @@ -1001,64 +516,77 @@ bool RCBotPluginMeta::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxle int bot_count = 0; int human_count = 0; - for (int i = 0; i < MAX_PLAYERS; ++i) { - m_iTargetBots[i] = 0; + for (int& m_iTargetBot : m_iTargetBots) + { + m_iTargetBot = 0; } CBotGlobals::buildFileName(filename, "bot_quota", BOT_CONFIG_FOLDER, "ini"); - fp = fopen(filename, "r"); + fp = std::fstream(filename, std::fstream::in); - memset(bq_line, 0, sizeof(bq_line)); + std::memset(bq_line, 0, sizeof(bq_line)); - if (fp != NULL) { - while (fgets(bq_line, sizeof(bq_line), fp) != NULL) { + if (fp) { + while (fp.getline(bq_line, sizeof(bq_line))) { if (bq_line[0] == '#') continue; - for (int i = 0; i < sizeof(bq_line); ++i) { - if (bq_line[i] == '\0') + for (char& i : bq_line) + { + if (i == '\0') break; - if (!isdigit(bq_line[i])) - bq_line[i] = ' '; + if (!isdigit(i)) + i = ' '; } - if (sscanf(bq_line, "%d %d", &human_count, &bot_count) == 2) { - if (human_count < 0 || human_count > 32) { - CBotGlobals::botMessage(NULL, 0, "Bot Quota - Invalid Human Count %d", human_count); + if (std::sscanf(bq_line, "%d %d", &human_count, &bot_count) == 2) { + if (human_count < 0 || human_count > RCBOT_MAXPLAYERS) { + logger->Log(LogLevel::WARN, "Bot Quota - Invalid Human Count %d", human_count); continue; } - if (bot_count < 0 || bot_count > 32) { - CBotGlobals::botMessage(NULL, 0, "Bot Quota - Invalid Bot Count %d", bot_count); + if (bot_count < 0 || bot_count > RCBOT_MAXPLAYERS) { + logger->Log(LogLevel::WARN, "Bot Quota - Invalid Bot Count %d", bot_count); continue; } - m_iTargetBots[human_count] = bot_count; - CBotGlobals::botMessage(NULL, 0, "Bot Quota - Humans: %d, Bots: %d", human_count, bot_count); + if (human_count < RCBOT_MAXPLAYERS) { // Ensure human_count is within bounds + m_iTargetBots[human_count] = bot_count; + logger->Log(LogLevel::INFO, "Bot Quota - Humans: %d, Bots: %d", human_count, bot_count); + } } } } - if (fp) { - fclose(fp); - } - return true; } -bool RCBotPluginMeta::FireGameEvent(IGameEvent * pevent, bool bDontBroadcast) +bool RCBotPluginMeta::FireGameEvent(IGameEvent* pevent, bool bDontBroadcast) { - static char szKey[128]; - static char szValue[128]; + // Skip processing if another plugin already handled/blocked this event - [APG]RoboCop[CL] + if (META_RESULT_STATUS >= MRES_OVERRIDE) + { + RETURN_META_VALUE(MRES_IGNORED, true); + } - CBotEvents::executeEvent((void*)pevent,TYPE_IGAMEEVENT); + // Sanity check: ensure event pointer is valid before processing - [APG]RoboCop[CL] + if (pevent != nullptr) + { + CBotEvents::executeEvent(pevent, TYPE_IGAMEEVENT); + } -RETURN_META_VALUE(MRES_IGNORED, true); + RETURN_META_VALUE(MRES_IGNORED, true); } -bool RCBotPluginMeta::Unload(char *error, size_t maxlen) +bool RCBotPluginMeta::Unload(char *error, std::size_t maxlen) { +#ifdef SM_EXT + SM_UnloadExtension(); +#endif + + //CBots::kickRandomBot(RCBOT_MAXPLAYERS); //breaks the bot quota system? [APG]RoboCop[CL] + SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, LevelInit, server, this, &RCBotPluginMeta::Hook_LevelInit, true); SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, ServerActivate, server, this, &RCBotPluginMeta::Hook_ServerActivate, true); SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, GameFrame, server, this, &RCBotPluginMeta::Hook_GameFrame, true); @@ -1066,8 +594,6 @@ bool RCBotPluginMeta::Unload(char *error, size_t maxlen) SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientActive, gameclients, this, &RCBotPluginMeta::Hook_ClientActive, true); SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, gameclients, this, &RCBotPluginMeta::Hook_ClientDisconnect, true); SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientPutInServer, gameclients, this, &RCBotPluginMeta::Hook_ClientPutInServer, true); - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, SetCommandClient, gameclients, this, &RCBotPluginMeta::Hook_SetCommandClient, true); - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientSettingsChanged, gameclients, this, &RCBotPluginMeta::Hook_ClientSettingsChanged, false); SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientConnect, gameclients, this, &RCBotPluginMeta::Hook_ClientConnect, false); SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientCommand, gameclients, this, &RCBotPluginMeta::Hook_ClientCommand, false); @@ -1079,7 +605,6 @@ bool RCBotPluginMeta::Unload(char *error, size_t maxlen) CBots::freeAllMemory(); CStrings::freeAllMemory(); - CBotGlobals::freeMemory(); CBotMods::freeMemory(); CAccessClients::freeMemory(); CBotEvents::freeMemory(); @@ -1088,7 +613,6 @@ bool RCBotPluginMeta::Unload(char *error, size_t maxlen) CBotProfiles::deleteProfiles(); CWeapons::freeMemory(); CBotMenuList::freeMemory(); - CAttributeLookup::freeMemory(); //unloadSignatures(); //UnhookPlayerRunCommand(); @@ -1099,17 +623,6 @@ bool RCBotPluginMeta::Unload(char *error, size_t maxlen) //if ( gameevents ) // gameevents->RemoveListener(this); - // Reset Cheat Flag - if ( puppet_bot_cmd != NULL ) - { - if ( !puppet_bot_cmd->IsFlagSet(FCVAR_CHEAT) ) - { - int *m_nFlags = (int*)((unsigned long)puppet_bot_cmd + BOT_CONVAR_FLAGS_OFFSET); // 20 is offset to flags - - *m_nFlags |= FCVAR_CHEAT; - } - } - ConVar_Unregister( ); return true; @@ -1120,7 +633,7 @@ void RCBotPluginMeta::OnVSPListening(IServerPluginCallbacks *iface) vsp_callbacks = iface; } -void RCBotPluginMeta::Hook_ServerActivate(edict_t *pEdictList, int edictCount, int clientMax) +void RCBotPluginMeta::Hook_ServerActivate(edict_t *pEdictList, const int edictCount, const int clientMax) { META_LOG(g_PLAPI, "ServerActivate() called: edictCount = %d, clientMax = %d", edictCount, clientMax); @@ -1134,9 +647,26 @@ void RCBotPluginMeta::AllPluginsLoaded() /* This is where we'd do stuff that relies on the mod or other plugins * being initialized (for example, cvars added and events registered). */ +#ifdef SM_EXT + BindToSourcemod(); +#endif +} + +#ifdef SM_EXT +void* RCBotPluginMeta::OnMetamodQuery(const char* iface, int *ret) { + if (std::strcmp(iface, SOURCEMOD_NOTICE_EXTENSIONS) == 0) { + BindToSourcemod(); + } + + if (ret != NULL) { + *ret = IFACE_OK; + } + + return NULL; } +#endif -void RCBotPluginMeta::Hook_ClientActive(edict_t *pEntity, bool bLoadGame) +void RCBotPluginMeta::Hook_ClientActive(edict_t *pEntity, const bool bLoadGame) { META_LOG(g_PLAPI, "Hook_ClientActive(%d, %d)", IndexOfEdict(pEntity), bLoadGame); @@ -1149,7 +679,7 @@ void RCBotPluginMeta::Hook_ClientCommand(edict_t *pEntity, const CCommand &args) void RCBotPluginMeta::Hook_ClientCommand(edict_t *pEntity) #endif { - static CBotMod *pMod = NULL; + static CBotMod *pMod = nullptr; #if SOURCE_ENGINE <= SE_DARKMESSIAH CCommand args; @@ -1167,8 +697,12 @@ void RCBotPluginMeta::Hook_ClientCommand(edict_t *pEntity) // is bot command? if ( CBotGlobals::m_pCommands->isCommand(pcmd) ) { - //eBotCommandResult iResult = CBotGlobals::m_pCommands->execute(pClient,engine->Cmd_Argv(1),engine->Cmd_Argv(2),engine->Cmd_Argv(3),engine->Cmd_Argv(4),engine->Cmd_Argv(5),engine->Cmd_Argv(6)); - eBotCommandResult iResult = CBotGlobals::m_pCommands->execute(pClient,args.Arg(1),args.Arg(2),args.Arg(3),args.Arg(4),args.Arg(5),args.Arg(6)); + // create shifted command list + BotCommandArgs argList; + for (unsigned i = 1; i <= static_cast(args.ArgC()); i++) { + argList.emplace_back(args.Arg(static_cast(i))); + } + const eBotCommandResult iResult = CBotGlobals::m_pCommands->execute(pClient, argList); if ( iResult == COMMAND_ACCESSED ) { @@ -1189,11 +723,11 @@ void RCBotPluginMeta::Hook_ClientCommand(edict_t *pEntity) RETURN_META(MRES_SUPERCEDE); } - else if ( strncmp(pcmd,"menuselect",10) == 0 ) // menu command + if ( std::strncmp(pcmd,"menuselect",10) == 0 ) // menu command { if ( pClient->isUsingMenu() ) { - int iCommand = atoi(args.Arg(1)); + int iCommand = std::atoi(args.Arg(1)); // format is 1.2.3.4.5.6.7.8.9.0 if ( iCommand == 0 ) @@ -1214,42 +748,32 @@ void RCBotPluginMeta::Hook_ClientCommand(edict_t *pEntity) RETURN_META(MRES_IGNORED); } -void RCBotPluginMeta::Hook_ClientSettingsChanged(edict_t *pEdict) -{ - -} - bool RCBotPluginMeta::Hook_ClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen) { - META_LOG(g_PLAPI, "Hook_ClientConnect(%d, \"%s\", \"%s\")", IndexOfEdict(pEntity), pszName, pszAddress); + META_LOG(g_PLAPI, R"(Hook_ClientConnect(%d, "%s", "%s"))", IndexOfEdict(pEntity), pszName, pszAddress); CClients::init(pEntity); return true; } -void RCBotPluginMeta::Hook_ClientPutInServer(edict_t *pEntity, char const *playername) +void RCBotPluginMeta::Hook_ClientPutInServer(edict_t *pEntity, char const* playername) { - CBaseEntity *pEnt = servergameents->EdictToBaseEntity(pEntity); - bool is_Rcbot = false; - - CClient *pClient = CClients::clientConnected(pEntity); + CBaseEntity *pEnt = servergameents->EdictToBaseEntity(pEntity); //`*pEnt` Unused? [APG]RoboCop[CL] + constexpr bool is_Rcbot = false; - if ( CBots::controlBots() ) - is_Rcbot = CBots::handlePlayerJoin(pEntity,playername); - - if ( !is_Rcbot && pClient ) - { + if ( CClient *pClient = CClients::clientConnected(pEntity) ) + { if ( !engine->IsDedicatedServer() ) { if ( CClients::noListenServerClient() ) { // give listenserver client all access to bot commands - CClients::setListenServerClient(pClient); + CClients::setListenServerClient(pClient); pClient->setAccessLevel(CMD_ACCESS_ALL); pClient->resetMenuCommands(); } @@ -1260,59 +784,31 @@ void RCBotPluginMeta::Hook_ClientPutInServer(edict_t *pEntity, char const *playe pMod->playerSpawned(pEntity); +#ifdef OVERRIDE_RUNCMD if ( pEnt ) { - if (CBots::controlBots()) - SH_ADD_MANUALHOOK_MEMFUNC(MHook_PlayerRunCmd, pEnt, this, &RCBotPluginMeta::Hook_PlayerRunCmd, false); - - if (pMod->getModId() == MOD_TF2) - { - SH_ADD_MANUALHOOK_MEMFUNC(MHook_GiveNamedItem, pEnt, this, &RCBotPluginMeta::Hook_GiveNamedItem, false); - - SH_ADD_MANUALHOOK_MEMFUNC(MHook_EquipWearable, pEnt, this, &RCBotPluginMeta::Hook_EquipWearable, false); - - SH_ADD_MANUALHOOK_MEMFUNC(MHook_EquipWeapon, pEnt, this, &RCBotPluginMeta::Hook_EquipWeapon, false); - - SH_ADD_MANUALHOOK_MEMFUNC(MHook_RemovePlayerItem, pEnt, this, &RCBotPluginMeta::Hook_RemovePlayerItem, false); - - SH_ADD_MANUALHOOK_MEMFUNC(MHook_GetPlayerWeaponSlot, pEnt, this, &RCBotPluginMeta::Hook_GetPlayerWeaponSlot, false); - SH_ADD_MANUALHOOK_MEMFUNC(MHook_RemoveWearable, pEnt, this, &RCBotPluginMeta::Hook_RemoveWearable, false); - } + SH_ADD_MANUALHOOK_MEMFUNC(MHook_PlayerRunCmd, pEnt, this, &RCBotPluginMeta::Hook_PlayerRunCmd, false); } +#endif } void RCBotPluginMeta::Hook_ClientDisconnect(edict_t *pEntity) { - CBaseEntity *pEnt = servergameents->EdictToBaseEntity(pEntity); + CBaseEntity *pEnt = servergameents->EdictToBaseEntity(pEntity); //`*pEnt` Unused? [APG]RoboCop[CL] +#ifdef OVERRIDE_RUNCMD if ( pEnt ) { - CBotMod *pMod = CBotGlobals::getCurrentMod(); - - if (CBots::controlBots()) - SH_REMOVE_MANUALHOOK_MEMFUNC(MHook_PlayerRunCmd, pEnt, this, &RCBotPluginMeta::Hook_PlayerRunCmd, false); - - if (pMod->getModId() == MOD_TF2) - { - SH_REMOVE_MANUALHOOK_MEMFUNC(MHook_GiveNamedItem, pEnt, this, &RCBotPluginMeta::Hook_GiveNamedItem, false); - - SH_REMOVE_MANUALHOOK_MEMFUNC(MHook_EquipWearable, pEnt, this, &RCBotPluginMeta::Hook_EquipWearable, false); - - SH_REMOVE_MANUALHOOK_MEMFUNC(MHook_EquipWeapon, pEnt, this, &RCBotPluginMeta::Hook_EquipWeapon, false); - - SH_REMOVE_MANUALHOOK_MEMFUNC(MHook_RemovePlayerItem, pEnt, this, &RCBotPluginMeta::Hook_RemovePlayerItem, false); - - SH_REMOVE_MANUALHOOK_MEMFUNC(MHook_GetPlayerWeaponSlot, pEnt, this, &RCBotPluginMeta::Hook_GetPlayerWeaponSlot, false); - SH_REMOVE_MANUALHOOK_MEMFUNC(MHook_RemoveWearable, pEnt, this, &RCBotPluginMeta::Hook_RemoveWearable, false); - } + SH_REMOVE_MANUALHOOK_MEMFUNC(MHook_PlayerRunCmd, pEnt, this, &RCBotPluginMeta::Hook_PlayerRunCmd, false); } +#endif CClients::clientDisconnected(pEntity); META_LOG(g_PLAPI, "Hook_ClientDisconnect(%d)", IndexOfEdict(pEntity)); } -void RCBotPluginMeta::Hook_GameFrame(bool simulating) +void RCBotPluginMeta::Hook_GameFrame(const bool simulating) { /** * simulating: @@ -1321,14 +817,11 @@ void RCBotPluginMeta::Hook_GameFrame(bool simulating) * false | game is not ticking */ - static CBotMod *currentmod; - if ( simulating && CBotGlobals::IsMapRunning() ) { + static CBotMod *currentmod; + CBots::botThink(); - //if ( !CBots::controlBots() ) - //gameclients->PostClientMessagesSent(); - CBots::handleAutomaticControl(); CClients::clientThink(); if ( CWaypoints::getVisiblity()->needToWorkVisibility() ) @@ -1351,14 +844,15 @@ void RCBotPluginMeta::Hook_GameFrame(bool simulating) currentmod->modFrame(); // Bot Quota - if (rcbot_bot_quota_interval.GetInt() > 0) { + if (rcbot_bot_quota_interval.GetFloat() > 0.0) { BotQuotaCheck(); } } } void RCBotPluginMeta::BotQuotaCheck() { - if (rcbot_bot_quota_interval.GetInt() < 0) { + // this is configured with config/bot_quota.ini + if (rcbot_bot_quota_interval.GetFloat() <= 0.0) { return; } @@ -1366,13 +860,9 @@ void RCBotPluginMeta::BotQuotaCheck() { m_fBotQuotaTimer = engine->Time() + 10.0f; // Sleep 10 seconds } - if (m_fBotQuotaTimer < engine->Time() - rcbot_bot_quota_interval.GetInt()) { + if (m_fBotQuotaTimer < engine->Time() - rcbot_bot_quota_interval.GetFloat()) { m_fBotQuotaTimer = engine->Time(); - // Target Bot Count - int bot_target = 0; - int bot_diff = 0; - // Change Notification bool notify = false; @@ -1381,49 +871,63 @@ void RCBotPluginMeta::BotQuotaCheck() { int human_count = 0; // Count Players - for (int i = 0; i < MAX_PLAYERS; ++i) { - CClient* client = CClients::get(i); - CBot* bot = CBots::get(i); + for (int i = 0; i < RCBOT_MAXPLAYERS; ++i) { + const CClient* client = CClients::get(i); + const CBot* bot = CBots::get(i); - if (bot != NULL && bot->getEdict() != NULL && bot->inUse()) { + if (bot != nullptr && bot->getEdict() != nullptr && bot->inUse()) { IPlayerInfo *p = playerinfomanager->GetPlayerInfo(bot->getEdict()); - if (p->IsConnected() && p->IsFakeClient()) { + if (p->IsConnected() && p->IsFakeClient() && !p->IsHLTV()) { bot_count++; } } - if (client != NULL && client->getPlayer() != NULL && client->isUsed()) { - IPlayerInfo *p = playerinfomanager->GetPlayerInfo(client->getPlayer()); + if (client->getPlayer() != nullptr && client->isUsed()) { + IPlayerInfo* p = playerinfomanager->GetPlayerInfo(client->getPlayer()); - if (p->IsConnected() && !p->IsFakeClient()) { - human_count++; + if (p->IsConnected() && !p->IsFakeClient() && !p->IsHLTV()) { + if (rcbot_ignore_spectators.GetBool()) { + if ( CClassInterface::getTeam(client->getPlayer()) >= 2 ) + human_count++; + } else + human_count++; } } } - if (human_count >= MAX_PLAYERS) { + if (human_count >= RCBOT_MAXPLAYERS) { human_count = 0; } // Get Bot Quota - bot_target = m_iTargetBots[human_count]; + int bot_target = m_iTargetBots[human_count]; + const int max_bots = CBots::getMaxBots(); + const int min_bots = CBots::getMinBots(); + + // Use min and max as ceiling and floor + if ((max_bots > -1) && (bot_target > max_bots)) { + bot_target = max_bots; + } else if ((min_bots > -1) && (bot_target < min_bots)) { + bot_target = min_bots; + } // Change Bot Quota - if (bot_target < bot_count) { - bot_diff = bot_count - bot_target; - - for (int i = 0; i < bot_diff; ++i) { - CBots::kickRandomBot(); + if (bot_count > bot_target) { + if (rcbot_nonrandom_kicking.GetBool()) { + CBots::kickChosenBot(static_cast(bot_count - bot_target)); + } else { + CBots::kickRandomBot(static_cast(bot_count - bot_target)); } - notify = true; - } else if (bot_target > bot_count) { - bot_diff = bot_target - bot_count; + } + else if ((bot_target > bot_count) && ( CBots::getAddKickBotTime() < engine->Time() )) { + const int bot_diff = bot_target - bot_count; for (int i = 0; i < bot_diff; ++i) { - CBots::addBot("", "", ""); - break; // Bug-Fix, only add one bot at a time + CBots::createBot("", "", ""); + if (rcbot_addbottime.GetFloat() > 0.0) + break; } notify = true; @@ -1432,11 +936,7 @@ void RCBotPluginMeta::BotQuotaCheck() { if (notify) { char chatmsg[128]; snprintf(chatmsg, sizeof(chatmsg), "[Bot Quota] Humans: %d, Bots: %d", human_count, bot_target); - - CBotGlobals::botMessage(NULL, 0, "======================================="); - CBotGlobals::botMessage(NULL, 0, chatmsg); - CBotGlobals::botMessage(NULL, 0, "======================================="); - + logger->Log(LogLevel::INFO, chatmsg); // RCBotPluginMeta::BroadcastTextMessage(chatmsg); } } @@ -1455,7 +955,7 @@ bool RCBotPluginMeta::Hook_LevelInit(const char *pMapName, // Must set this CBotGlobals::setMapName(pMapName); - Msg( "Level \"%s\" has been loaded\n", pMapName ); + logger->Log(LogLevel::INFO, "Level \"%s\" has been loaded", pMapName); CWaypoints::precacheWaypointTexture(); @@ -1469,8 +969,8 @@ bool RCBotPluginMeta::Hook_LevelInit(const char *pMapName, CBotGlobals::setMapRunning(true); CBotConfigFile::reset(); - if ( mp_teamplay ) - CBotGlobals::setTeamplay(mp_teamplay->GetBool()); + if ( mp_teamplay.IsValid() ) + CBotGlobals::setTeamplay(mp_teamplay.GetBool()); else CBotGlobals::setTeamplay(false); @@ -1478,17 +978,15 @@ bool RCBotPluginMeta::Hook_LevelInit(const char *pMapName, CBots::mapInit(); - CBotMod *pMod = CBotGlobals::getCurrentMod(); - - if ( pMod ) + if ( CBotMod *pMod = CBotGlobals::getCurrentMod() ) pMod->mapInit(); CBotSquads::FreeMemory(); - CClients::setListenServerClient(NULL); + CClients::setListenServerClient(nullptr); // Setup game rules - extern void **g_pGameRules; + extern void **g_pGameRules; //Unused? [APG]RoboCop[CL] if (g_pGameRules_Obj && g_pGameRules_Obj->found()) { @@ -1516,17 +1014,12 @@ void RCBotPluginMeta::Hook_LevelShutdown() CBotEvents::freeMemory(); } -void RCBotPluginMeta::Hook_SetCommandClient(int index) -{ - META_LOG(g_PLAPI, "Hook_SetCommandClient(%d)", index); -} - -bool RCBotPluginMeta::Pause(char *error, size_t maxlen) +bool RCBotPluginMeta::Pause(char *error, std::size_t maxlen) { return true; } -bool RCBotPluginMeta::Unpause(char *error, size_t maxlen) +bool RCBotPluginMeta::Unpause(char *error, std::size_t maxlen) { return true; } @@ -1538,12 +1031,12 @@ const char *RCBotPluginMeta::GetLicense() const char *RCBotPluginMeta::GetVersion() { - return "1.01 (r487-apg-ch)"; + return build_info::short_version; } const char *RCBotPluginMeta::GetDate() { - return __DATE__; + return build_info::date; } const char *RCBotPluginMeta::GetLogTag() @@ -1553,7 +1046,7 @@ const char *RCBotPluginMeta::GetLogTag() const char *RCBotPluginMeta::GetAuthor() { - return "Cheeseh, RoboCop"; + return build_info::authors; } const char *RCBotPluginMeta::GetDescription() @@ -1568,5 +1061,17 @@ const char *RCBotPluginMeta::GetName() const char *RCBotPluginMeta::GetURL() { - return "http://rcbot.bots-united.com/"; + return build_info::url; } + +#ifdef SM_EXT +void RCBotPluginMeta::BindToSourcemod() +{ + char error[256]; + if (!SM_LoadExtension(error, sizeof(error))) { + char message[512]; + snprintf(message, sizeof(message), "Could not load as a SourceMod extension: %s\n", error); + engine->LogPrint(message); + } +} +#endif diff --git a/utils/RCBot2_meta/bot_plugin_meta.h b/utils/RCBot2_meta/bot_plugin_meta.h index 7358c3b33..222e6242f 100644 --- a/utils/RCBot2_meta/bot_plugin_meta.h +++ b/utils/RCBot2_meta/bot_plugin_meta.h @@ -51,27 +51,28 @@ #include "engine_wrappers.h" #include +#ifdef SM_EXT +#include +#endif + class CUserCmd; class IMoveHelper; -class CEconItemView; -class CTF2Loadout; -class CEconWearable; -#if defined WIN32 && !defined snprintf +#if defined(_WIN64) || defined(_WIN32) && !defined snprintf #define snprintf _snprintf #endif class RCBotPluginMeta : public ISmmPlugin, public IMetamodListener { public: - bool Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late); - bool Unload(char *error, size_t maxlen); - bool Pause(char *error, size_t maxlen); - bool Unpause(char *error, size_t maxlen); - void AllPluginsLoaded(); -public: //IMetamodListener stuff - void OnVSPListening(IServerPluginCallbacks *iface); -public: //hooks + bool Load(PluginId id, ISmmAPI *ismm, char *error, std::size_t maxlen, bool late) override; + bool Unload(char *error, std::size_t maxlen) override; + bool Pause(char *error, std::size_t maxlen) override; + bool Unpause(char *error, std::size_t maxlen) override; + void AllPluginsLoaded() override; +//public: //IMetamodListener stuff + void OnVSPListening(IServerPluginCallbacks *iface) override; +//public: //hooks void Hook_ServerActivate(edict_t *pEdictList, int edictCount, int clientMax); bool Hook_LevelInit(const char *pMapName, @@ -81,47 +82,22 @@ class RCBotPluginMeta : public ISmmPlugin, public IMetamodListener bool loadGame, bool background); void Hook_GameFrame(bool simulating); - void Hook_LevelShutdown(void); + void Hook_LevelShutdown(); void Hook_ClientActive(edict_t *pEntity, bool bLoadGame); void Hook_ClientDisconnect(edict_t *pEntity); void Hook_ClientPutInServer(edict_t *pEntity, char const *playername); - void Hook_SetCommandClient(int index); - void Hook_ClientSettingsChanged(edict_t *pEdict); + //Called for a game event. Same definition as server plugins??? bool FireGameEvent( IGameEvent *pevent, bool bDontBroadcast ); void Hook_PlayerRunCmd(CUserCmd *ucmd, IMoveHelper *moveHelper); - CBaseEntity *Hook_GiveNamedItem(const char *name, int subtype, CEconItemView *cscript, bool b); - void Hook_EquipWearable(CEconWearable *pItem); - void Hook_EquipWeapon(CBaseEntity *pWeapon); - void Hook_RemovePlayerItem(CBaseEntity *pWeapon); - - CBaseEntity *Hook_GetPlayerWeaponSlot(int iSlot); - void Hook_RemoveWearable(CBaseEntity *pWearable); + bool Hook_ClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen); - bf_write *Hook_MessageBegin(IRecipientFilter *filter, int msg_type); - void Hook_MessageEnd(); - - void Hook_WriteChar(int val); - void Hook_WriteShort(int val); - void Hook_WriteByte(int val); - void Hook_WriteFloat(float val); - bool Hook_WriteString(const char *pStr); - - static CBaseEntity *TF2_getPlayerWeaponSlot(edict_t *pPlayer, int iSlot); - static void TF2_removeWearable(edict_t *pPlayer, CBaseEntity *pWearable); - static void TF2_removePlayerItem(edict_t *pPlayer, CBaseEntity *pItem); - static void TF2_RemoveWeaponSlot(edict_t *pPlayer, int iSlot); - static void TF2_equipWeapon(edict_t *pPlayer, CBaseEntity *pWeapon); - static bool givePlayerLoadOut(edict_t *pPlayer, CTF2Loadout *pLoadout, int iSlot, void *pVTable, void *pVTable_Attributes); - static void giveRandomLoadout(edict_t *pPlayer, int iClass, int iSlot, void *pVTable, void *pVTable_Attributes); - static void TF2_equipWearable(edict_t *pPlayer, CBaseEntity *pWearable); - static bool TF2_ClearAttributeCache(edict_t *pEdict); - - static void HudTextMessage(edict_t *pEntity, const char *szMessage); + + static void HudTextMessage(const edict_t *pEntity, const char *szMessage); static void BroadcastTextMessage(const char *szMessage); #if SOURCE_ENGINE >= SE_ORANGEBOX @@ -130,28 +106,34 @@ class RCBotPluginMeta : public ISmmPlugin, public IMetamodListener void Hook_ClientCommand(edict_t *pEntity); #endif -public: +//public: // SourceMod +#ifdef SM_EXT + void *OnMetamodQuery(const char* iface, int *ret) override; +#endif - const char *GetAuthor(); - const char *GetName(); - const char *GetDescription(); - const char *GetURL(); - const char *GetLicense(); - const char *GetVersion(); - const char *GetDate(); - const char *GetLogTag(); +//public: - static bool UTIL_TF2EquipHat(edict_t *pEdict, CTF2Loadout *pHat, void *vTable, void *vTableAttributes); - static CTF2Loadout *UTIL_TF2EquipRandomHat(edict_t *pEdict, void *vTable, void *vTableAttributes); + const char *GetAuthor() override; + const char *GetName() override; + const char *GetDescription() override; + const char *GetURL() override; + const char *GetLicense() override; + const char *GetVersion() override; + const char *GetDate() override; + const char *GetLogTag() override; private: - int m_iClientCommandIndex; +#ifdef SM_EXT + void BindToSourcemod(); +#endif + + int m_iClientCommandIndex = 0; // Bot Quota - float m_fBotQuotaTimer; - int m_iTargetBots[MAX_PLAYERS]; + float m_fBotQuotaTimer = 0.0f; + int m_iTargetBots[RCBOT_MAXPLAYERS] = {}; - void BotQuotaCheck( void ); + void BotQuotaCheck(); }; extern RCBotPluginMeta g_RCBotPluginMeta; diff --git a/utils/RCBot2_meta/bot_plugin_valve.cpp b/utils/RCBot2_meta/bot_plugin_valve.cpp deleted file mode 100644 index e127c6ad6..000000000 --- a/utils/RCBot2_meta/bot_plugin_valve.cpp +++ /dev/null @@ -1,1201 +0,0 @@ -/* - * This file is part of RCBot. - * - * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. - * - * RCBot is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * RCBot is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with RCBot; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * In addition, as a special exception, the author gives permission to - * link the code of this program with the Half-Life Game Engine ("HL - * Engine") and Modified Game Libraries ("MODs") developed by Valve, - * L.L.C ("Valve"). You must obey the GNU General Public License in all - * respects for all of the code used other than the HL Engine and MODs - * from Valve. If you modify this file, you may extend this exception - * to your version of the file, but you are not obligated to do so. If - * you do not wish to do so, delete this exception statement from your - * version. - * - *///=================================================================================// -// -// HPB_bot2_main.cpp - bot source code file (Copyright 2004, Jeffrey "botman" Broome) -// -//=================================================================================// - -#include -#include - -#ifdef WIN32 -#include -#else -#include -#include -#include -#endif - -//#include "cbase.h" -//#include "baseentity.h" -#include "filesystem.h" -#include "interface.h" -#include "engine/iserverplugin.h" -#include "iplayerinfo.h" -#include "IEngineTrace.h" -#include "tier2/tier2.h" -#ifdef __linux__ -#include "shake.h" //bir3yk -#endif -#include "IEffects.h" -#include "vplane.h" -#include "eiface.h" -#include "igameevents.h" - -#include "Color.h" -#include "ndebugoverlay.h" -#include "server_class.h" -#include "time.h" -#include "irecipientfilter.h" -#include "bot.h" -#include "bot_commands.h" -#include "bot_client.h" -#include "bot_globals.h" -#include "bot_accessclient.h" -#include "bot_waypoint_visibility.h" // for initializing table -#include "bot_event.h" -#include "bot_profile.h" -#include "bot_weapons.h" -#include "bot_mods.h" -#include "bot_profiling.h" -#include "bot_menu.h" -#include "bot_squads.h" -#include "bot_kv.h" -#include "bot_fortress.h" -#include "vstdlib/random.h" // for random seed - -#include "bot_wpt_dist.h" - -#include "bot_configfile.h" - -#include "bot_getprop.h" - -#include "bot_sigscan.h" - -#include "bot_hooks.h" - -#include "bot_cvars.h" -// memdbgon must be the last include file in a .cpp file!!! -#include "bot_valve_plguin.h" - -bool bInitialised = false; - -// Interfaces from the engine*/ -IVEngineServer *engine = NULL; // helper functions (messaging clients, loading content, making entities, running commands, etc) -IFileSystem *filesystem = NULL; // file I/O -IGameEventManager2 *gameeventmanager = NULL; -IGameEventManager *gameeventmanager1 = NULL; // game events interface -IPlayerInfoManager *playerinfomanager = NULL; // game dll interface to interact with players -IServerPluginHelpers *helpers = NULL; // special 3rd party plugin helpers from the engine -IServerGameClients* gameclients = NULL; -IEngineTrace *enginetrace = NULL; -IEffects *g_pEffects = NULL; -IBotManager *g_pBotManager = NULL; -CGlobalVars *gpGlobals = NULL; -IVDebugOverlay *debugoverlay = NULL; -IServerGameEnts *servergameents = NULL; // for accessing the server game entities -IServerGameDLL *servergamedll = NULL; -IServerTools *servertools = NULL; - -void (CBaseEntity::*RemovePlayerItem)(CBaseEntity*) = 0x0; -void (CBaseEntity::*Touch)(CBaseEntity*) = 0x0; -//GCC takes the this pointer on the stack as the first parameter - -void UTIL_ApplyAttribute ( edict_t *pEdict, const char *name, float fVal ) -{ - CAttributeList *address = CClassInterface::getAttributeList(pEdict); - - if ( address == NULL ) - { - CBotGlobals::botMessage(NULL,1,"getAttributeList not found"); - return; - } - - CEconItemAttributeDefinition *def = g_pGetAttributeDefinitionByName->callme(g_pGetEconItemSchema->callme(),name); - - if ( def ) - { - g_pSetRuntimeAttributeValue->callme(pEdict,address,def,fVal); - } - else - CBotGlobals::botMessage(NULL,1,"CEconItemAttributeDefinition for %s not found",name); -} - - -CON_COMMAND( rcbot_ragemeter, "get rage meter value" ) -{ - // get listen server edict - edict_t *pplayer = CClients::getListenServerClient(); - - if ( pplayer ) - { - CBotGlobals::botMessage(NULL,0,"ragemeter = %0.2f",CClassInterface::getRageMeter(pplayer)); - } -} -/* -CON_COMMAND( rcbot_attribtest, "attributes for tf2 test" ) -{ - // get listen server edict - edict_t *pplayer = CClients::getListenServerClient(); - - if ( pplayer && (args.ArgC() > 3)) - { - edict_t *pEnt; - - if ( strcmp(args.Arg(1),"player") == 0 ) - pEnt = pplayer; - else - pEnt = CClassInterface::FindEntityByClassnameNearest(CBotGlobals::entityOrigin(pplayer),args.Arg(1),200.0f); - - const char *attrib = args.Arg(2); - float fValue = atof(args.Arg(3)); - - UTIL_ApplyAttribute(pEnt,attrib,fValue); - - // Call AttributeChanged - - //DWORD *mem = ( DWORD* )*( DWORD* )address; - //*(DWORD*)&OnAttributesChanged = mem[12];CAttributeListSetValue - //CAttributeManager *pAttributeManager = (CAttributeManager *)((unsigned long)address + 24); - - //if ( pAttributeManager && OnAttributesChanged ) - //{ - // (*pAttributeManager.*OnAttributesChanged)(); - //} - - - } -}*/ - -CON_COMMAND( rcbot_enginetime, "get engine time" ) -{ - Msg("%f\n",engine->Time()); -} - -CON_COMMAND( rcbot_maptime, "get map time" ) -{ - Msg("CDODMod::getMapStartTime() = %f\n",CDODMod::getMapStartTime()); - Msg("engine->Time() = %f\n",engine->Time()); - Msg("diff = %f\n",engine->Time() - CDODMod::getMapStartTime()); - Msg("gpGlobals->realtime = %f\n",gpGlobals->realtime); - Msg("gpGlobals->curtime = %f\n",gpGlobals->curtime); -} - -//CBaseEntityList * g_pEntityList; -// -// The plugin is a static singleton that is exported as an interface -// -CRCBotPlugin g_RCBOTServerPlugin; -EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CRCBotPlugin, IServerPluginCallbacks, INTERFACEVERSION_ISERVERPLUGINCALLBACKS, g_RCBOTServerPlugin ); - -//--------------------------------------------------------------------------------- -// Purpose: constructor/destructor -//--------------------------------------------------------------------------------- -CRCBotPlugin::CRCBotPlugin() -{ - m_iClientCommandIndex = 0; -} - -CRCBotPlugin::~CRCBotPlugin() -{ -} - -//------------ -//--------------------------------------------------------------------------------- -// Purpose: an example of how to implement a new command -//--------------------------------------------------------------------------------- -static ConVar empty_cvar(BOT_VER_CVAR, BOT_VER, FCVAR_REPLICATED, BOT_NAME_VER); - -CON_COMMAND( rcbotd, "access the bot commands on a server" ) -{ - eBotCommandResult iResult; - - if ( !engine->IsDedicatedServer() || !CBotGlobals::IsMapRunning() ) - { - CBotGlobals::botMessage(NULL,0,"Error, no map running or not dedicated server"); - return; - } - - //iResult = CBotGlobals::m_pCommands->execute(NULL,engine->Cmd_Argv(1),engine->Cmd_Argv(2),engine->Cmd_Argv(3),engine->Cmd_Argv(4),engine->Cmd_Argv(5),engine->Cmd_Argv(6)); - iResult = CBotGlobals::m_pCommands->execute(NULL,args.Arg(1),args.Arg(2),args.Arg(3),args.Arg(4),args.Arg(5),args.Arg(6)); - - if ( iResult == COMMAND_ACCESSED ) - { - // ok - } - else if ( iResult == COMMAND_REQUIRE_ACCESS ) - { - CBotGlobals::botMessage(NULL,0,"You do not have access to this command"); - } - else if ( iResult == COMMAND_NOT_FOUND ) - { - CBotGlobals::botMessage(NULL,0,"bot command not found"); - } - else if ( iResult == COMMAND_ERROR ) - { - CBotGlobals::botMessage(NULL,0,"bot command returned an error"); - } -} - -void CRCBotPlugin::OnEdictAllocated( edict_t *edict ) -{ - -} - -void CRCBotPlugin::OnEdictFreed( const edict_t *edict ) -{ - -} - -class CBotRecipientFilter : public IRecipientFilter -{ -public: - CBotRecipientFilter ( edict_t *pPlayer ) - { - m_iPlayerSlot = ENTINDEX(pPlayer); - } - - bool IsReliable( void ) const { return false; } - bool IsInitMessage( void ) const { return false; } - - int GetRecipientCount( void ) const { return 1; } - int GetRecipientIndex( int slot ) const { return m_iPlayerSlot; } - -private: - int m_iPlayerSlot; -};/////////////// -// hud message - - -void CRCBotPlugin :: HudTextMessage ( edict_t *pEntity, const char *szMessage ) -{ - int msgid = 0; - int imsgsize = 0; - char msgbuf[64]; - bool bOK; - - while ( (bOK=servergamedll->GetUserMessageInfo(msgid,msgbuf,63,imsgsize))==true ) - { - if ( strcmp(msgbuf,"HintText") == 0 ) - break; - else - msgid++; - } - - if ( msgid == 0 ) - return; - if ( !bOK ) - return; - - CBotRecipientFilter *filter = new CBotRecipientFilter(pEntity); - - bf_write *buf = engine->UserMessageBegin(filter,msgid); - - buf->WriteString(szMessage); - - engine->MessageEnd(); - - delete filter; - - /* - KeyValues *kv = new KeyValues( "msg" ); - kv->SetString( "title", szMessage ); - kv->SetString( "msg", "This is the msg" ); - - kv->SetColor( "color", colour); - kv->SetInt( "level", level); - kv->SetInt( "time", time); -//DIALOG_TEXT - helpers->CreateMessage( pEntity, DIALOG_MSG, kv, &g_RCBOTServerPlugin ); - - kv->deleteThis();*/ -} - -#ifdef __linux__ -#define LOAD_INTERFACE(var,type,version) if ( (var = (type*)interfaceFactory(version,NULL)) == NULL ) { Warning("[RCBOT] Cannot open interface "#version " "#type " "#var "\n"); return false; } else { Msg("[RCBOT] Found interface "#version " "#type " "#var "\n"); } -#define LOAD_GAME_SERVER_INTERFACE(var,type,version) if ( (var = (type*)gameServerFactory(version,NULL)) == NULL ) { Warning("[RCBOT] Cannot open game server interface "#version " "#type " "#var "\n"); return false; } else { Msg("[RCBOT] Found interface "#version " "#type " "#var "\n"); } -#else -#define LOAD_INTERFACE(var,type,version) if ( (var = (type*)interfaceFactory(version,NULL)) == NULL ) { Warning("[RCBOT] Cannot open interface "## #version ##" "## #type ##" "## #var ##"\n"); return false; } else { Msg("[RCBOT] Found interface "## #version ##" "## #type ##" "## #var ## "\n"); } -#define LOAD_GAME_SERVER_INTERFACE(var,type,version) if ( (var = (type*)gameServerFactory(version,NULL)) == NULL ) { Warning("[RCBOT] Cannot open game server interface "## #version ##" "## #type ##" "## #var ##"\n"); return false; } else { Msg("[RCBOT] Found interface "## #version ##" "## #type ##" "## #var ## "\n"); } -#endif - -//#define FILESYSTEM_INT FILESYSTEM_INTERFACE_VERSION -//#define FILESYSTEM_MAXVER 19 - -#ifndef __linux__ - -#define RCBot_LoadUndefinedInterface(var,type,vername,maxver,minver) { \ - int ver = maxver; \ - char str [256]; \ - char tempver[8]; \ - do{ \ - strcpy(str,vername); \ - sprintf(tempver,"%03d",ver); \ - strcat(str,tempver); \ - ver--; \ - var = (type*)interfaceFactory(str,NULL); \ - Msg("Trying... %s\n",str); \ - }while((var==NULL)&&(ver>minver)); \ - if ( var == NULL ) \ - { \ - Warning("[RCBOT] Cannot open interface "## #vername ##" "## #type ##" "## #var ##" (Max ver: "## #maxver ##") Min ver: ("## #minver ##") \n"); \ - return false; \ - } else { \ - Msg("[RCBOT] Found interface "## #vername ##" "## #type ##" "## #var ##", ver = %03d\n",ver+1); \ - }\ -} - -#define RCBot_LoadUndefinedGameInterface(var,type,vername,maxver,minver) { \ - int ver = maxver; \ - char str [256]; \ - char tempver[8]; \ - do{ \ - strcpy(str,vername); \ - sprintf(tempver,"%03d",ver); \ - strcat(str,tempver); \ - ver--; \ - var = (type*)gameServerFactory(str,NULL); \ - Msg("Trying... %s\n",str); \ - }while((var==NULL)&&(ver>minver)); \ - if ( var == NULL ) \ - { \ - Warning("[RCBOT] Cannot open interface "## #vername ##" "## #type ##" "## #var ##" (Max ver: "## #maxver ##") Min ver: ("## #minver ##") \n"); \ - return false; \ - } else { \ - Msg("[RCBOT] Found interface "## #vername ##" "## #type ##" "## #var ##", ver = %03d\n",ver+1); \ - }\ -} -#else - -// we need to change preprocessor concatonations for this - -#define RCBot_LoadUndefinedInterface(var,type,vername,maxver,minver) { \ - int ver = maxver; \ - char str [256]; \ - char tempver[8]; \ - do{ \ - strcpy(str,vername); \ - sprintf(tempver,"%03d",ver); \ - strcat(str,tempver); \ - ver--; \ - var = (type*)interfaceFactory(str,NULL); \ - Msg("Trying... %s\n",str); \ - }while((var==NULL)&&(ver>minver)); \ - if ( var == NULL ) \ - { \ - Warning("[RCBOT] Cannot open interface " #vername " " #type " " #var " (Max ver: " #maxver ") Min ver: (" #minver ") \n"); \ - return false; \ - } else { \ - Msg("[RCBOT] Found interface " #vername " " #type " " #var ", ver = %03d\n",ver+1); \ - }\ -} - -// -#define RCBot_LoadUndefinedGameInterface(var,type,vername,maxver,minver) { \ - int ver = maxver; \ - char str [256]; \ - char tempver[8]; \ - do{ \ - strcpy(str,vername); \ - sprintf(tempver,"%03d",ver); \ - strcat(str,tempver); \ - ver--; \ - var = (type*)gameServerFactory(str,NULL); \ - Msg("Trying... %s\n",str); \ - }while((var==NULL)&&(ver>minver)); \ - if ( var == NULL ) \ - { \ - Warning("[RCBOT] Cannot open interface " #vername " " #type " " #var " (Max ver: " #maxver ") Min ver: (" #minver ") \n"); \ - return false; \ - } else { \ - Msg("[RCBOT] Found interface " #vername " " #type " " #var ", ver = %03d\n",ver+1); \ - }\ -} - -#endif - -void unloadSignatures () -{ - if ( g_pGetEconItemSchema ) - delete g_pGetEconItemSchema; - - if ( g_pSetRuntimeAttributeValue ) - delete g_pSetRuntimeAttributeValue; - - if ( g_pGetAttributeDefinitionByName ) - delete g_pGetAttributeDefinitionByName; - - if ( g_pAttribList_GetAttributeByID ) - delete g_pAttribList_GetAttributeByID; -} - -void findSignaturesAndOffsets(void *gameServerFactory) -{ - char filename[512]; - // Load RCBOT2 hook data - CBotGlobals::buildFileName(filename,"hookinfo",BOT_CONFIG_FOLDER,"ini"); - - FILE *fp = fopen(filename,"r"); - - CRCBotKeyValueList *pKVL = new CRCBotKeyValueList(); - - if ( fp ) - pKVL->parseFile(fp); - - g_pGetEconItemSchema = new CGetEconItemSchema(pKVL,gameServerFactory); - g_pSetRuntimeAttributeValue = new CSetRuntimeAttributeValue(pKVL,gameServerFactory); - g_pGetAttributeDefinitionByName = new CGetAttributeDefinitionByName(pKVL,gameServerFactory); - g_pAttribList_GetAttributeByID = new CAttributeList_GetAttributeByID(pKVL,gameServerFactory); - /* -#ifdef _WIN32 - if ( pKVL->getString("set_attribute_value_win",&sig) && sig ) -#else - if ( pKVL->getString("set_attribute_value_linux",&sig) && sig ) -#endif - SetRuntimeAttributeValue = findSignature((void*)gameServerFactory,sig); - else - SetRuntimeAttributeValue = findSignature((void*)gameServerFactory,"\\x55\\x8B\\xEC\\x83\\xEC\\x14\\x33\\xD2\\x53\\x8B\\xD9\\x56\\x57\\x8B\\x73\\x10\\x85\\xF6"); - -#ifdef _WIN32 - if ( pKVL->getString("get_item_schema_win",&sig) && sig ) -#else - if ( pKVL->getString("get_item_schema_linux",&sig) && sig ) -#endif - GEconItemSchemaFunc = findSignature((void*)gameServerFactory,sig); - else - GEconItemSchemaFunc = findSignature((void*)gameServerFactory,"\\xE8\\x2A\\x2A\\x2A\\x2A\\x83\\xC0\\x04\\xC3"); - -#ifdef _WIN32 - if ( pKVL->getString("get_attrib_definition_win",&sig) && sig ) -#else - if ( pKVL->getString("get_attrib_definition_linux",&sig) && sig ) -#endif - GetAttributeDefinitionByName = findSignature((void*)gameServerFactory,sig); - else - GetAttributeDefinitionByName = findSignature((void*)gameServerFactory,"\\x55\\x8B\\xEC\\x83\\xEC\\x1C\\x53\\x8B\\xD9\\x8B\\x0D\\x2A\\x2A\\x2A\\x2A\\x56\\x33\\xF6\\x89\\x5D\\xF8\\x89\\x75\\xE4\\x89\\x75\\xE8"); - -#ifdef _WIN32 - if ( pKVL->getString("attributelist_get_attrib_by_id_win",&sig) && sig ) -#else - if ( pKVL->getString("attributelist_get_attrib_by_id_linux",&sig) && sig ) -#endif - AttributeList_GetAttributeByID = findSignature((void*)gameServerFactory,sig); - else - AttributeList_GetAttributeByID = findSignature((void*)gameServerFactory,"\\x55\\x8B\\xEC\\x51\\x8B\\xC1\\x53\\x56\\x33\\xF6\\x89\\x45\\xFC\\x8B\\x58\\x10"); - */ - int val; - -#ifdef _WIN32 - - if ( pKVL->getInt("givenameditem_win",&val) ) - rcbot_givenameditem_offset.SetValue(val); - if ( pKVL->getInt("equipwearable_win",&val) ) - rcbot_equipwearable_offset.SetValue(val); - if ( pKVL->getInt("runplayermove_tf2_win",&val) ) - rcbot_runplayercmd_tf2.SetValue(val); - if ( pKVL->getInt("runplayermove_dods_win",&val) ) - rcbot_runplayercmd_dods.SetValue(val); - -#else - - if ( pKVL->getInt("givenameditem_linux",&val) ) - rcbot_givenameditem_offset.SetValue(val); - if ( pKVL->getInt("equipwearable_linux",&val) ) - rcbot_equipwearable_offset.SetValue(val); - if ( pKVL->getInt("runplayermove_tf2_linux",&val) ) - rcbot_runplayercmd_tf2.SetValue(val); - if ( pKVL->getInt("runplayermove_dods_linux",&val) ) - rcbot_runplayercmd_dods.SetValue(val); - -#endif - - delete pKVL; - fclose(fp); -} - -//--------------------------------------------------------------------------------- -// Purpose: called when the plugin is loaded, load the interface we need from the engine -//--------------------------------------------------------------------------------- -bool CRCBotPlugin::Load( CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory ) -{ - extern MTRand_int32 irand; - // TODO: check rcbot isn't already loaded already - - ConVar *rcbot_instance; - - ConnectTier1Libraries( &interfaceFactory, 1 ); - ConnectTier2Libraries( &interfaceFactory, 1 ); - - rcbot_instance = cvar->FindVar("rcbot_ver"); - - if ( rcbot_instance != NULL ) - { - Msg("An instance of RCBOT is already running. Can't load!"); - DisconnectTier2Libraries( ); - DisconnectTier1Libraries( ); - return false; - } - - findSignaturesAndOffsets((void*)gameServerFactory); - - LOAD_GAME_SERVER_INTERFACE(playerinfomanager,IPlayerInfoManager,INTERFACEVERSION_PLAYERINFOMANAGER); - - gpGlobals = playerinfomanager->GetGlobalVars(); - - LOAD_INTERFACE(engine,IVEngineServer,INTERFACEVERSION_VENGINESERVER); - RCBot_LoadUndefinedInterface(filesystem,IFileSystem,"VFileSystem",22,1); - - if ( !CBotGlobals::gameStart() ) - return false; - - LOAD_INTERFACE(helpers,IServerPluginHelpers,INTERFACEVERSION_ISERVERPLUGINHELPERS); - LOAD_INTERFACE(enginetrace,IEngineTrace,INTERFACEVERSION_ENGINETRACE_SERVER); - LOAD_GAME_SERVER_INTERFACE(servergameents,IServerGameEnts,INTERFACEVERSION_SERVERGAMEENTS); - LOAD_GAME_SERVER_INTERFACE(g_pEffects,IEffects,IEFFECTS_INTERFACE_VERSION); - LOAD_GAME_SERVER_INTERFACE(g_pBotManager,IBotManager,INTERFACEVERSION_PLAYERBOTMANAGER); - LOAD_GAME_SERVER_INTERFACE(servertools,IServerTools,VSERVERTOOLS_INTERFACE_VERSION); - -#ifndef __linux__ - LOAD_INTERFACE(debugoverlay,IVDebugOverlay,VDEBUG_OVERLAY_INTERFACE_VERSION); -#endif - LOAD_INTERFACE(gameeventmanager,IGameEventManager2,INTERFACEVERSION_GAMEEVENTSMANAGER2) - LOAD_INTERFACE(gameeventmanager1,IGameEventManager,INTERFACEVERSION_GAMEEVENTSMANAGER) - - RCBot_LoadUndefinedGameInterface(servergamedll,IServerGameDLL,"ServerGameDLL",8,2); - RCBot_LoadUndefinedGameInterface(gameclients,IServerGameClients,"ServerGameClients",4,1); - - MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f ); - ConVar_Register( 0 ); - //InitCVars( interfaceFactory ); // register any cvars we have defined - - srand( (unsigned)time(NULL) ); // initialize the random seed - irand.seed( (unsigned)time(NULL) ); - - eventListener2 = new CRCBotEventListener(); - - // Initialize bot variables - CBotProfiles::setupProfiles(); - - - //CBotEvents::setupEvents(); - CWaypointTypes::setup(); - CWaypoints::setupVisibility(); - - CBotConfigFile::reset(); - CBotConfigFile::load(); - - CBotMenuList::setupMenus(); - - CRCBotPlugin::ShowLicense(); - - RandomSeed((unsigned int)time(NULL)); - - CClassInterface::init(); - - RCBOT2_Cvar_setup(); - bInitialised = true; - - return true; -} - -void CRCBotPlugin::ShowLicense ( void ) -{ - - Msg ("-----------------------------------------------------------------\n"); - Msg (" RCBOT LICENSE\n"); - Msg ("-----------------------------------------------------------------\n"); - Msg ("RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template.\n\n"); - - Msg ("RCBot is free software; you can redistribute it and/or modify it\n"); - Msg ("under the terms of the GNU General Public License as published by the\n"); - Msg ("Free Software Foundation; either version 2 of the License, or (at\n"); - Msg ("your option) any later version.\n\n"); - - Msg ("RCBot is distributed in the hope that it will be useful, but\n"); - Msg ("WITHOUT ANY WARRANTY; without even the implied warranty of\n"); - Msg ("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"); - Msg ("General Public License for more details.\n\n"); - - Msg ("You should have received a copy of the GNU General Public License\n"); - Msg ("along with RCBot; if not, write to the Free Software Foundation,\n"); - Msg ("Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n\n"); - - Msg ("In addition, as a special exception, the author gives permission to\n"); - Msg ("link the code of this program with the Half-Life Game Engine (\"HL\"\n"); - Msg ("Engine\") and Modified Game Libraries (\"MODs\") developed by Valve,\n"); - Msg ("L.L.C (\"Valve\"). You must obey the GNU General Public License in all\n"); - Msg ("respects for all of the code used other than the HL Engine and MODs\n"); - Msg ("from Valve. If you modify this file, you may extend this exception\n"); - Msg ("to your version of the file, but you are not obligated to do so. If\n"); - Msg ("you do not wish to do so, delete this exception statement from your\n"); - Msg ("version.\n"); - Msg ("-----------------------------------------------------------------\n"); -} - -//--------------------------------------------------------------------------------- -// Purpose: called when the plugin is unloaded (turned off) -//--------------------------------------------------------------------------------- -void CRCBotPlugin::Unload( void ) -{ - // if another instance is running dont run through this - if ( !bInitialised ) - return; - - CBots::freeAllMemory(); - CStrings::freeAllMemory(); - CBotGlobals::freeMemory(); - CBotMods::freeMemory(); - CAccessClients::freeMemory(); - CBotEvents::freeMemory(); - CWaypoints::freeMemory(); - CWaypointTypes::freeMemory(); - CBotProfiles::deleteProfiles(); - CWeapons::freeMemory(); - CBotMenuList::freeMemory(); - - unloadSignatures(); - - UnhookPlayerRunCommand(); - UnhookGiveNamedItem(); - - //ConVar_Unregister(); - - if ( gameeventmanager1 ) - gameeventmanager1->RemoveListener( this ); // make sure we are unloaded from the event system - if ( gameeventmanager ) - { - if ( eventListener2 ) - { - gameeventmanager->RemoveListener( eventListener2 ); - delete eventListener2; - } - } - - // Reset Cheat Flag - if ( puppet_bot_cmd != NULL ) - { - if ( !puppet_bot_cmd->IsFlagSet(FCVAR_CHEAT) ) - { - int *m_nFlags = (int*)((unsigned long)puppet_bot_cmd + BOT_CONVAR_FLAGS_OFFSET); // 20 is offset to flags - - *m_nFlags |= FCVAR_CHEAT; - } - } - - ConVar_Unregister( ); - - DisconnectTier2Libraries( ); - DisconnectTier1Libraries( ); - -} - -//--------------------------------------------------------------------------------- -// Purpose: called when the plugin is paused (i.e should stop running but isn't unloaded) -//--------------------------------------------------------------------------------- -void CRCBotPlugin::Pause( void ) -{ -} - -//--------------------------------------------------------------------------------- -// Purpose: called when the plugin is unpaused (i.e should start executing again) -//--------------------------------------------------------------------------------- -void CRCBotPlugin::UnPause( void ) -{ -} - -//--------------------------------------------------------------------------------- -// Purpose: the name of this plugin, returned in "plugin_print" command -//--------------------------------------------------------------------------------- -const char *CRCBotPlugin::GetPluginDescription( void ) -{ - return "RCBot2 Plugin, by Cheeseh"; -} - -//--------------------------------------------------------------------------------- -// Purpose: called on level start -//--------------------------------------------------------------------------------- -void CRCBotPlugin::LevelInit( char const *pMapName ) -{ - //CClients::initall(); - // Must set this - CBotGlobals::setMapName(pMapName); - - Msg( "Level \"%s\" has been loaded\n", pMapName ); - - CWaypoints::precacheWaypointTexture(); - - CWaypointDistances::reset(); - - CProfileTimers::reset(); - - CWaypoints::init(); - CWaypoints::load(); - - CBotGlobals::setMapRunning(true); - CBotConfigFile::reset(); - - if ( mp_teamplay ) - CBotGlobals::setTeamplay(mp_teamplay->GetBool()); - else - CBotGlobals::setTeamplay(false); - - gameeventmanager1->AddListener( this, true ); - - CBotEvents::setupEvents(); - - CBots::mapInit(); - - CBotMod *pMod = CBotGlobals::getCurrentMod(); - - if ( pMod ) - pMod->mapInit(); - - CBotSquads::FreeMemory(); - - CClients::setListenServerClient(NULL); -} - -//--------------------------------------------------------------------------------- -// Purpose: called on level start, when the server is ready to accept client connections -// edictCount is the number of entities in the level, clientMax is the max client count -//--------------------------------------------------------------------------------- -void CRCBotPlugin::ServerActivate( edict_t *pEdictList, int edictCount, int clientMax ) -{ - Msg( "clientMax is %d\n", clientMax ); - - CAccessClients::load(); - - CBotGlobals::setClientMax(clientMax); -} - -void CRCBotPlugin::PreClientUpdate(bool simulating) -{ - //if ( simulating && CBotGlobals::IsMapRunning() ) - //{ - // CBots::runPlayerMoveAll(); - //} -} - -//--------------------------------------------------------------------------------- -// Purpose: called once per server frame, do recurring work here (like checking for timeouts) -//--------------------------------------------------------------------------------- -void CRCBotPlugin::GameFrame( bool simulating ) -{ - static CBotMod *currentmod; - - if ( simulating && CBotGlobals::IsMapRunning() ) - { - CBots::botThink(); - if ( !CBots::controlBots() ) - gameclients->PostClientMessagesSent(); - CBots::handleAutomaticControl(); - CClients::clientThink(); - - if ( CWaypoints::getVisiblity()->needToWorkVisibility() ) - { - CWaypoints::getVisiblity()->workVisibility(); - } - - // Profiling -#ifdef _DEBUG - if ( CClients::clientsDebugging(BOT_DEBUG_PROFILE) ) - { - CProfileTimers::updateAndDisplay(); - } -#endif - - // Config Commands - CBotConfigFile::doNextCommand(); - currentmod = CBotGlobals::getCurrentMod(); - - currentmod->modFrame(); - } -} - -//--------------------------------------------------------------------------------- -// Purpose: called on level end (as the server is shutting down or going to a new map) -//--------------------------------------------------------------------------------- -void CRCBotPlugin::LevelShutdown( void ) // !!!!this can get called multiple times per map change -{ - CClients::initall(); - CWaypointDistances::save(); - - //if ( !rcbot_runplayercmd_hookonce.GetBool() ) - //{ - UnhookPlayerRunCommand(); - UnhookGiveNamedItem(); - //} - - CBots::freeMapMemory(); - CWaypoints::init(); - - CBotGlobals::setMapRunning(false); - CBotEvents::freeMemory(); - - gameeventmanager1->RemoveListener( this ); - - if ( gameeventmanager ) - gameeventmanager->RemoveListener( eventListener2 ); -} - -//--------------------------------------------------------------------------------- -// Purpose: called when a client spawns into a server (i.e as they begin to play) -//--------------------------------------------------------------------------------- -void CRCBotPlugin::ClientActive( edict_t *pEntity ) -{ - CClients::clientActive(pEntity); -} - -//--------------------------------------------------------------------------------- -// Purpose: called when a client leaves a server (or is timed out) -//--------------------------------------------------------------------------------- -void CRCBotPlugin::ClientDisconnect( edict_t *pEntity ) -{ - // this is sorted in CClients::clientDisconnected() - //CBot *pBot = CBots::getBotPointer(pEntity); - //pBot->freeMapMemory(); - - CClients::clientDisconnected(pEntity); -} - -//--------------------------------------------------------------------------------- -// Purpose: called on client being added to this server -//--------------------------------------------------------------------------------- -void CRCBotPlugin::ClientPutInServer( edict_t *pEntity, char const *playername ) -{ - bool is_Rcbot = false; - - CClient *pClient = CClients::clientConnected(pEntity); - - if ( CBots::controlBots() ) - is_Rcbot = CBots::handlePlayerJoin(pEntity,playername); - - if ( !is_Rcbot && pClient ) - { - if ( !engine->IsDedicatedServer() ) - { - if ( CClients::noListenServerClient() ) - { - // give listenserver client all access to bot commands - CClients::setListenServerClient(pClient); - pClient->setAccessLevel(CMD_ACCESS_ALL); - pClient->resetMenuCommands(); - } - } - } - - CBotMod *pMod = CBotGlobals::getCurrentMod(); - - pMod->playerSpawned(pEntity); - -} - -CRCBotEventListener *CRCBotPlugin:: getEventListener ( void ) -{ - return eventListener2; -} - -//--------------------------------------------------------------------------------- -// Purpose: called on level start -//--------------------------------------------------------------------------------- -void CRCBotPlugin::SetCommandClient( int index ) -{ - m_iClientCommandIndex = index; -} - -//--------------------------------------------------------------------------------- -// Purpose: called on level start -//--------------------------------------------------------------------------------- -void CRCBotPlugin::ClientSettingsChanged( edict_t *pEdict ) -{ - /* - if ( playerinfomanager ) - { - IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEdict ); - - const char *name = engine->GetClientConVarValue( engine->IndexOfEdict(pEdict), "name" ); - - if ( playerinfo && name && playerinfo->GetName() && - Q_stricmp( name, playerinfo->GetName()) ) // playerinfo may be NULL if the MOD doesn't support access to player data - // OR if you are accessing the player before they are fully connected - { - char msg[128]; - Q_snprintf( msg, sizeof(msg), "Your name changed to \"%s\" (from \"%s\"\n", name, playerinfo->GetName() ); - engine->ClientPrintf( pEdict, msg ); // this is the bad way to check this, the better option it to listen for the "player_changename" event in FireGameEvent() - // this is here to give a real example of how to use the playerinfo interface - } - }*/ -} - -//--------------------------------------------------------------------------------- -// Purpose: called when a client joins a server -//--------------------------------------------------------------------------------- -PLUGIN_RESULT CRCBotPlugin::ClientConnect( bool *bAllowConnect, edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen ) -{ - CClients::init(pEntity); - - return PLUGIN_CONTINUE; -} - -//--------------------------------------------------------------------------------- -// Purpose: called when a client types in a command (only a subset of commands however, not CON_COMMAND's) -//--------------------------------------------------------------------------------- -PLUGIN_RESULT CRCBotPlugin::ClientCommand( edict_t *pEntity, const CCommand &args ) -{ - const char *pcmd = args.Arg(0); - CBotMod *pMod; - //const char *pcmd = engine->Cmd_Argv(0); - - if ( !pEntity || pEntity->IsFree() ) - { - return PLUGIN_CONTINUE; - } - - CClient *pClient = CClients::get(pEntity); - - // is bot command? - if ( CBotGlobals::m_pCommands->isCommand(pcmd) ) - { - //eBotCommandResult iResult = CBotGlobals::m_pCommands->execute(pClient,engine->Cmd_Argv(1),engine->Cmd_Argv(2),engine->Cmd_Argv(3),engine->Cmd_Argv(4),engine->Cmd_Argv(5),engine->Cmd_Argv(6)); - eBotCommandResult iResult = CBotGlobals::m_pCommands->execute(pClient,args.Arg(1),args.Arg(2),args.Arg(3),args.Arg(4),args.Arg(5),args.Arg(6)); - - if ( iResult == COMMAND_ACCESSED ) - { - // ok - } - else if ( iResult == COMMAND_REQUIRE_ACCESS ) - { - CBotGlobals::botMessage(pEntity,0,"You do not have access to this command"); - } - else if ( iResult == COMMAND_NOT_FOUND ) - { - CBotGlobals::botMessage(pEntity,0,"bot command not found"); - } - else if ( iResult == COMMAND_ERROR ) - { - CBotGlobals::botMessage(pEntity,0,"bot command returned an error"); - } - - return PLUGIN_STOP; // we handled this function - } - else if ( strncmp(pcmd,"menuselect",10) == 0 ) // menu command - { - if ( pClient->isUsingMenu() ) - { - int iCommand = atoi(args.Arg(1)); - - // format is 1.2.3.4.5.6.7.8.9.0 - if ( iCommand == 0 ) - iCommand = 9; - else - iCommand --; - - pClient->getCurrentMenu()->selectedMenu(pClient,iCommand); - } - } - - // command capturing - pMod = CBotGlobals::getCurrentMod(); - - // capture some client commands e.g. voice commands - pMod->clientCommand(pEntity,args.ArgC(),pcmd,args.Arg(1),args.Arg(2)); - - return PLUGIN_CONTINUE; -} - -//--------------------------------------------------------------------------------- -// Purpose: called when a client is authenticated -//--------------------------------------------------------------------------------- -PLUGIN_RESULT CRCBotPlugin::NetworkIDValidated( const char *pszUserName, const char *pszNetworkID ) -{ - return PLUGIN_CONTINUE; -} - -void CRCBotPlugin::OnQueryCvarValueFinished( QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue ) -{ - return; -} - -// Data types from Keyvalues.h -enum types_t -{ - TYPE_NONE = 0, - TYPE_STRING, - TYPE_INT, - TYPE_FLOAT, - TYPE_PTR, - TYPE_WSTRING, - TYPE_COLOR, - TYPE_UINT64, - TYPE_NUMTYPES, -}; - -//--------------------------------------------------------------------------------- -// Purpose: called when an event is fired -//--------------------------------------------------------------------------------- -void CRCBotPlugin::FireGameEvent( KeyValues * pevent ) -{ - static char szKey[128]; - static char szValue[128]; - - if ( CBotGlobals :: isEventVersion (1) ) - { - const char *type = pevent->GetName(); - - CBotEvents::executeEvent((void*)pevent,TYPE_KEYVALUES); - - if ( CClients::clientsDebugging(BOT_DEBUG_GAME_EVENT) ) - { - KeyValues *pk = pevent->GetFirstTrueSubKey(); - - CClients::clientDebugMsg(NULL,BOT_DEBUG_GAME_EVENT,"[BEGIN \"%s\"]",type); - - /*while ( pk != NULL ) - { - CClients::clientDebugMsg(NULL,BOT_DEBUG_GAME_EVENT,"BEGIN %s",pk->GetName()); - pk = pk->GetNextTrueSubKey(); - }*/ - - pk = pevent->GetFirstValue(); - -//For some reason KeyValues CRASHES when receiving the GetString of a non string -//so we have to be careful below: - - while ( pk != NULL ) - { - strncpy(szKey,pk->GetName(),127); - szKey[127] = 0; - - switch ( pk->GetDataType() ) - { - case TYPE_FLOAT: - sprintf(szValue,"%0.2f",pk->GetFloat()); - break; - case TYPE_INT: - sprintf(szValue,"%d",pk->GetInt()); - break; - case TYPE_PTR: - sprintf(szValue,"%x",(int)pk->GetPtr()); - break; - case TYPE_UINT64: - sprintf(szValue,"%d",pk->GetUint64()); - break; - case TYPE_WSTRING: - strcpy(szValue,"WSTRING"); - break; - case TYPE_STRING: - strncpy(szValue,pk->GetString(),127); - break; - default: - strcpy(szValue,"NULL"); - break; - } - - szValue[127] = 0; - - CClients::clientDebugMsg(NULL,BOT_DEBUG_GAME_EVENT,"\t%s = %s",szKey,szValue); - pk = pk->GetNextValue(); - } - - CClients::clientDebugMsg(NULL,BOT_DEBUG_GAME_EVENT,"[END \"%s\"]",type); - -/* - for ( KeyValues *pk = pevent->GetFirstTrueSubKey(); pk; pk = pk->GetNextTrueSubKey()) - { - CClients::clientDebugMsg(BOT_DEBUG_GAME_EVENT,pk->GetName()); - } - for ( KeyValues *pk = pevent->GetFirstValue(); pk; pk = pk->GetNextValue() ) - { - char szMsg[512]; - - sprintf(szMsg,"%s = %s",pk->GetName(),pk->GetString()); - CClients::clientDebugMsg(BOT_DEBUG_GAME_EVENT,szMsg); - }*/ - } - } -} - -void CRCBotEventListener::FireGameEvent( IGameEvent * pevent ) -{ - if ( CBotGlobals :: isEventVersion (2) ) - { - CBotEvents::executeEvent((void*)pevent,TYPE_IGAMEEVENT); - } -} - - - -/////////////////// -//useful functions -// defined in const more efficiently -/*int round ( float f ) -{ - f = f-(float)((int)f); - - if ( f >= 0.5 ) - return (int)f+1; - - return (int)f; -}*/ -//defined in const more efficiently -/*int RANDOM_INT(int min, int max) -{ - return min + round(((float)rand()/RAND_MAX)*(float)(max-min)); -}*/ - -////////////////////// - - -/*edict_t* INDEXENT( int iEdictNum ) -{ - return engine->PEntityOfEntIndex(iEdictNum); -} - -#ifndef GAME_DLL -// get entity index -int ENTINDEX( edict_t *pEdict ) -{ - return engine->IndexOfEdict(pEdict); -} -#endif*/ - -int Ceiling ( float fVal ) -{ - int loVal = (int)fVal; - - fVal -= (float)loVal; - - if ( fVal == 0.0 ) - return loVal; - - return loVal+1; -} - -float VectorDistance(Vector &vec) -{ - return (float)sqrt(((vec.x*vec.x) + (vec.y*vec.y) + (vec.z*vec.z))); -} - -// Testing the three types of "entity" for nullity -bool FNullEnt(const edict_t* pent) -{ - return pent == NULL || ENTINDEX((edict_t*)pent) == 0; -} diff --git a/utils/RCBot2_meta/bot_profile.cpp b/utils/RCBot2_meta/bot_profile.cpp index f9fad0932..2c70b2fdf 100644 --- a/utils/RCBot2_meta/bot_profile.cpp +++ b/utils/RCBot2_meta/bot_profile.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -32,15 +34,16 @@ #include "bot_strings.h" #include "bot_globals.h" #include "bot_profile.h" -#include "bot_genclass.h" #include "bot_visibles.h" #include "bot_navigator.h" #include "bot_kv.h" -vector CBotProfiles :: m_Profiles; -CBotProfile *CBotProfiles :: m_pDefaultProfile = NULL; +#include "rcbot/logging.h" -CBotProfile :: CBotProfile ( CBotProfile &other ) +std::vector CBotProfiles :: m_Profiles; +CBotProfile *CBotProfiles :: m_pDefaultProfile = nullptr; + +CBotProfile :: CBotProfile (const CBotProfile &other) { *this = other; @@ -49,16 +52,16 @@ CBotProfile :: CBotProfile ( CBotProfile &other ) } CBotProfile :: CBotProfile ( - const char *szName, - const char *szModel, - int iTeam, - int iVisionTicks, - int iPathTicks, - int iVisionTicksClients, - int iSensitivity, - float fBraveness, - float fAimSkill, - int iClass ) + const char* szName, + const char* szModel, + const int iTeam, + const int iVisionTicks, + const int iPathTicks, + const int iVisionTicksClients, + const int iSensitivity, + const float fBraveness, + const float fAimSkill, + const int iClass ) { m_iVisionTicksClients = iVisionTicksClients; m_iSensitivity = iSensitivity; @@ -74,95 +77,91 @@ CBotProfile :: CBotProfile ( void CBotProfiles :: deleteProfiles () { - for ( unsigned int i = 0; i < m_Profiles.size(); i ++ ) + for (CBotProfile*& m_Profile : m_Profiles) { - delete m_Profiles[i]; - m_Profiles[i] = NULL; + delete m_Profile; + m_Profile = nullptr; } m_Profiles.clear(); delete m_pDefaultProfile; - m_pDefaultProfile = NULL; + m_pDefaultProfile = nullptr; } -// requires CBotProfile 'read' declared -#ifndef __linux__ -#define READ_PROFILE_STRING(kvname,varname) if ( !pKVL->getString(##kvname##,&read.varname) ) { read.varname = m_pDefaultProfile->varname; } -#define READ_PROFILE_INT(kvname,varname) if ( !pKVL->getInt(##kvname##,&read.varname) ) { read.varname = m_pDefaultProfile->varname; } -// reads integers between 0 and 100 and converts to between 0.0 and 1.0 -#define READ_PROFILE_FLOAT(kvname,varname) { float fval; if ( !pKVL->getFloat(##kvname##,&fval) ) { read.varname = m_pDefaultProfile->varname; } else { read.varname = fval * 0.01f; } } -#else -#define READ_PROFILE_STRING(kvname,varname) if ( !pKVL->getString(kvname,&read.varname) ) { read.varname = m_pDefaultProfile->varname; } -#define READ_PROFILE_INT(kvname,varname) if ( !pKVL->getInt(kvname,&read.varname) ) { read.varname = m_pDefaultProfile->varname; } -// reads integers between 0 and 100 and converts to between 0.0 and 1.0 -#define READ_PROFILE_FLOAT(kvname,varname) { float fval; if ( !pKVL->getFloat(kvname,&fval) ) { read.varname = m_pDefaultProfile->varname; } else { read.varname = fval * 0.01f; } } -#endif // find profiles and setup list void CBotProfiles :: setupProfiles () { - unsigned int iId; - bool bDone; - char szId[4]; - char filename[512]; - - extern ConVar bot_anglespeed; - // Setup Default profile + // TODO: to maybe balance the aim skill and reaction times from being too high [APG]RoboCop[CL] m_pDefaultProfile = new CBotProfile( DEFAULT_BOT_NAME, // name "default", // model (team in HL2DM) -1, // iTeam CBotVisibles::DEFAULT_MAX_TICKS, // vis ticks IBotNavigator::MAX_PATH_TICKS, // path ticks - 2, // visrevs clients - 8.0f, // sensitivity - 0.5f, // braveness - 0.5f, // aim skill + 10, // visrevs clients + 8, // sensitivity + 0.7f, // braveness + 0.85f, // aim skill -1 // class ); // read profiles - iId = 1; - bDone = false; + unsigned iId = 1; + bool bDone = false; - while ( (iId < 999) && (!bDone) ) + while ( iId < 999 && !bDone ) { - sprintf(szId,"%d",iId); + char szId[4]; + char filename[512]; + snprintf(szId, sizeof(szId), "%d", iId); CBotGlobals::buildFileName(filename,szId,BOT_PROFILE_FOLDER,BOT_CONFIG_EXTENSION); - FILE *fp = CBotGlobals::openFile(filename,"r"); - - if ( fp ) + if ( std::fstream fp = CBotGlobals::openFile(filename, std::fstream::in) ) { - CBotProfile read; - CRCBotKeyValueList *pKVL = new CRCBotKeyValueList(); - - CBotGlobals::botMessage(NULL,0,"Reading bot profile \"%s\"",filename); - - pKVL->parseFile(fp); - - READ_PROFILE_INT("team",m_iTeam); - READ_PROFILE_STRING("model",m_szModel); - READ_PROFILE_STRING("name",m_szName); - READ_PROFILE_INT("visionticks",m_iVisionTicks); - READ_PROFILE_INT("pathticks",m_iPathTicks); - READ_PROFILE_INT("visionticks_clients",m_iVisionTicksClients); - READ_PROFILE_INT("sensitivity",m_iSensitivity); - READ_PROFILE_FLOAT("aim_skill",m_fAimSkill); - READ_PROFILE_FLOAT("braveness",m_fBraveness); - READ_PROFILE_INT("class",m_iClass); - - m_Profiles.push_back(new CBotProfile(read)); - - delete pKVL; - - fclose(fp); + // copy defaults + CBotProfile read = *m_pDefaultProfile; + CRCBotKeyValueList kvl; + + logger->Log(LogLevel::INFO, "Reading bot profile \"%s\"", filename); + + kvl.parseFile(fp); + + kvl.getInt("team", &read.m_iTeam); + kvl.getString("model", &read.m_szModel); + kvl.getString("name", &read.m_szName); + kvl.getInt("visionticks", &read.m_iVisionTicks); + kvl.getInt("pathticks", &read.m_iPathTicks); + kvl.getInt("visionticks_clients", &read.m_iVisionTicksClients); + kvl.getInt("sensitivity", &read.m_iSensitivity); + + // config maps [ 0.0, 100.0 ] to [ 0.0, 1.0 ] + float flWholeValuePercent; + if (kvl.getFloat("aim_skill", &flWholeValuePercent)) { + read.m_fAimSkill = flWholeValuePercent / 100.0f; + } else if (kvl.getFloat("aimskill", &flWholeValuePercent)) { + // *someone* wrote a broken bot profile generator. + // most of the profiles did not actually have working aim skill values + // we'll go ahead and allow it, but I have to express my displeasure about the matter in some way + logger->Log(LogLevel::WARN, + "Incorrect option 'aimskill' on bot profile \"%s\". " + "Did you mean 'aim_skill'?", filename); + read.m_fAimSkill = flWholeValuePercent / 100.0f; + } + + if (kvl.getFloat("braveness", &flWholeValuePercent)) { + read.m_fBraveness = flWholeValuePercent / 100.0f; + } + + kvl.getInt("class", &read.m_iClass); + + m_Profiles.emplace_back(new CBotProfile(read)); } else { bDone = true; - CBotGlobals::botMessage(NULL,0,"Bot profile \"%s\" not found",filename); + logger->Log(LogLevel::DEBUG, "Bot profile \"%s\" not found", filename); } iId ++; @@ -172,33 +171,51 @@ void CBotProfiles :: setupProfiles () CBotProfile *CBotProfiles :: getDefaultProfile () { - if ( m_pDefaultProfile == NULL ) - CBotGlobals::botMessage(NULL,1,"Error, default profile is NULL (Caused by memory problem, bad initialisation or overwrite) Exiting.."); + if ( m_pDefaultProfile == nullptr) + logger->Log(LogLevel::FATAL, "Default profile is NULL (Caused by memory problem, bad initialisation or overwrite) Exiting.."); return m_pDefaultProfile; } // return a profile unused by a bot -CBotProfile *CBotProfiles :: getRandomFreeProfile () +CBotProfile* CBotProfiles::getRandomFreeProfile() { - unsigned int i; - dataUnconstArray iList; - CBotProfile *found = NULL; + std::vector freeProfiles; - for ( i = 0; i < m_Profiles.size(); i ++ ) + for (CBotProfile*& m_Profile : m_Profiles) { - if ( !CBots::findBotByProfile(m_Profiles[i]) ) - iList.Add(i); + if (!CBots::findBotByProfile(m_Profile)) + freeProfiles.emplace_back(m_Profile); } - if ( iList.IsEmpty() ) - return NULL; - - found = m_Profiles[iList.Random()]; - iList.Clear(); + if (freeProfiles.empty()) + return nullptr; - return found; + return freeProfiles[static_cast(randomInt(0, static_cast(freeProfiles.size()) - 1))]; } - +// return first unused bot, concidering teams if they're unequal +CBotProfile* CBotProfiles::getChosenFreeProfile() +{ + int team = 0; + int teamA = CBotGlobals::numPlayersOnTeam(2,false); + int teamB = CBotGlobals::numPlayersOnTeam(3,false); + + if (teamA < teamB) { + team = 2; + } else if (teamA > teamB) { + team = 3; + } else { + team = 0; + } + + for (CBotProfile*& m_Profile : m_Profiles) + { + if ((!CBots::findBotByProfile(m_Profile)) && ((team < 2) || (m_Profile->m_iTeam < 2) || (m_Profile->m_iTeam == team))) { + return(m_Profile); + } + } + // fall back to random if matching fails + return CBotProfiles::getRandomFreeProfile(); +} diff --git a/utils/RCBot2_meta/bot_profile.h b/utils/RCBot2_meta/bot_profile.h index 719e40d5b..8ddece010 100644 --- a/utils/RCBot2_meta/bot_profile.h +++ b/utils/RCBot2_meta/bot_profile.h @@ -1,17 +1,18 @@ #ifndef __RCBOT_PROFILE_H__ #define __RCBOT_PROFILE_H__ +#include +#include #include -using namespace std; class CBotProfile { public: CBotProfile () - { - memset(this,0,sizeof(CBotProfile)); - } - CBotProfile ( CBotProfile &other ); + { + std::memset(this,0,sizeof(CBotProfile)); + } + CBotProfile (const CBotProfile &other); // setup profile CBotProfile ( const char *szName, @@ -25,16 +26,16 @@ class CBotProfile float fAimSkill, int iClass = 0 ); - // bot's name - char *m_szName; - char *m_szModel; - // bot's team + // bot's name + const char* m_szName; + const char* m_szModel; + // bot's team int m_iTeam; // preferred player team int m_iVisionTicks; // speed of finding non players (npcs/teleporters etc) int m_iPathTicks; // speed of finding a path int m_iClass; // preferred player class int m_iVisionTicksClients; // speed of finding other players and enemy players - int m_iSensitivity; // 1 to 20 sensitivity of bot's "mouse" (angle speed) + int m_iSensitivity; // 1 to 20 sensitivity of bot's "mouse" (angle speed) float m_fBraveness; // 0.0 to 1.0 sensitivity to danger (brave = less sensitive) float m_fAimSkill; // 0.0 to 1.0 ability to predict players movements (aim skill) }; @@ -49,12 +50,13 @@ class CBotProfiles // return a profile unused by a bot static CBotProfile *getRandomFreeProfile (); + static CBotProfile *getChosenFreeProfile (); static CBotProfile *getDefaultProfile (); private: - static vector m_Profiles; + static std::vector m_Profiles; static CBotProfile *m_pDefaultProfile; }; -#endif \ No newline at end of file +#endif diff --git a/utils/RCBot2_meta/bot_profiling.cpp b/utils/RCBot2_meta/bot_profiling.cpp index 48b0afcca..570bc4277 100644 --- a/utils/RCBot2_meta/bot_profiling.cpp +++ b/utils/RCBot2_meta/bot_profiling.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -34,153 +36,148 @@ #include "bot_strings.h" #include "bot_client.h" -// List of all timers -CProfileTimer CProfileTimers :: m_Timers[PROFILING_TIMERS] = +#include +#include +#include + +//caxanga334: SDK 2013 contains macros for std::min and std::max which causes errors when compiling +//#if SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_BMS +#include "valve_minmax_off.h" +//#endif + + // List of all timers +CProfileTimer CProfileTimers::m_Timers[PROFILING_TIMERS] = { -CProfileTimer("CBots::botThink()"), // BOTS_THINK_TIMER -CProfileTimer("CBot::think()"), // BOT_THINK_TIMER -CProfileTimer("Nav::findRoute()"), // BOT_ROUTE_TIMER -CProfileTimer("updateVisibles()") // BOT_VISION_TIMER + CProfileTimer("CBots::botThink()"), // BOTS_THINK_TIMER + CProfileTimer("CBot::think()"), // BOT_THINK_TIMER + CProfileTimer("Nav::findRoute()"), // BOT_ROUTE_TIMER + CProfileTimer("updateVisibles()") // BOT_VISION_TIMER }; -// initialise update time +// Initialise update time float CProfileTimers::m_fNextUpdate = 0; +// Nuke this on x64 +/*#if !defined(PLATFORM_64BITS) + // if windows USE THE QUERYPERFORMANCECOUNTER #ifdef _WIN32 -inline unsigned __int64 RDTSC(void) - { - _asm _emit 0x0F - _asm _emit 0x31 - } +inline unsigned __int64 RDTSC() +{ + _asm _emit 0x0F + _asm _emit 0x31 +} #define WIN32_LEAN_AND_MEAN -#include +#include #else // #define rdtsc _emit 0x0f _asm _emit 0x31 -// inline unsigned long long rdtsc(void) -// __asm__ volatile (".byte 0x0f, 0x31" : "=A" (void)); +// inline unsigned long long rdtsc() +// __asm__ volatile (".byte 0x0f, 0x31" : "=A" ()); // { // } - extern __inline__ unsigned long long int rdtsc() - { - unsigned long long int x; - __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x)); - return x; - } +extern __inline__ unsigned long long int rdtsc() +{ + unsigned long long int x; + __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x)); + return x; +} #endif -CProfileTimer :: CProfileTimer (const char *szFunction) +#endif*/ + +CProfileTimer::CProfileTimer(const char* szFunction) + : start_cycle(0), + end_cycle(0), + m_average(0), + m_min(std::numeric_limits::max()), + m_max(0), + m_last(0), + m_overall(0), + m_szFunction(CStrings::getString(szFunction)), + m_iInvoked(0) { - m_szFunction = CStrings::getString(szFunction); - m_min = 9999999999; - m_max = 0; - m_average = 2; - m_iInvoked = 0; - m_overall = 0; } // "Begin" Timer i.e. update time -void CProfileTimer :: Start() +void CProfileTimer::Start() { -#ifdef _WIN32 - QueryPerformanceCounter(reinterpret_cast(&start_cycle)); -#else - start_cycle = rdtsc(); -#endif - + start_cycle = std::chrono::high_resolution_clock::now().time_since_epoch().count(); } + // Stop Timer, work out min/max values and set invoked -void CProfileTimer :: Stop() +void CProfileTimer::Stop() { -#ifdef _WIN32 - unsigned __int64 end_cycle; - QueryPerformanceCounter(reinterpret_cast(&end_cycle)); -#else - unsigned long long end_cycle; - end_cycle = rdtsc(); -#endif - - m_last = end_cycle - start_cycle; - - if ( m_last > m_max ) - m_max = m_last; - if ( (m_iInvoked==0) || (m_last < m_min) ) - m_min = m_last; + end_cycle = std::chrono::high_resolution_clock::now().time_since_epoch().count(); + m_last = end_cycle - start_cycle; - m_overall = m_overall + m_last; + if (m_last > m_max) + m_max = m_last; + if (m_iInvoked == 0 || m_last < m_min) + m_min = m_last; - m_iInvoked ++; + m_overall += m_last; + m_iInvoked++; } - - -// print the values, first work out average (use max/min/previous values), -// and work out percentage of power -void CProfileTimer :: print (double *high) +// Print the values, first work out average (use max/min/previous values), and work out percentage of power +void CProfileTimer::print(const double* high) { - if ((m_iInvoked>0) && m_szFunction ) - { - char str[256]; - float percent = 1; - - m_average = m_overall/m_iInvoked; - - percent = (((double)m_overall)/(*high))*100.0f; - - sprintf(str,"%17s|%13lld|%10lld|%10lld|%10lld|%6.1f",m_szFunction,m_overall,m_min,m_max,m_average,percent); + if (m_iInvoked > 0 && m_szFunction) + { + char str[256]; - CClients::clientDebugMsg(BOT_DEBUG_PROFILE,str); + m_average = m_overall / m_iInvoked; + const double percent = static_cast(m_overall) / *high * 100.0; - // uninvoke now - m_iInvoked = 0; - - // reset max - m_max = 0; + snprintf(str, 256, "%17s|%13llu|%10llu|%10llu|%10llu|%6.1f", m_szFunction, m_overall, m_min, m_max, m_average, percent); + CClients::clientDebugMsg(BOT_DEBUG_PROFILE, str); - m_overall = 0; - } + // Reset values + m_iInvoked = 0; + m_max = 0; + m_overall = 0; + } } -// get the required timer -CProfileTimer *CProfileTimers::getTimer (int id) +// Get the required timer +CProfileTimer* CProfileTimers::getTimer(const int id) { - if ( id >= 0 && id < PROFILING_TIMERS ) - return &m_Timers[id]; + if (id >= 0 && id < PROFILING_TIMERS) + return &m_Timers[id]; - return NULL; + return nullptr; } -// do this every map start -void CProfileTimers :: reset () + +// Do this every map start +void CProfileTimers::reset() { - m_fNextUpdate = 0; + m_fNextUpdate = 0; } -// update and show every x seconds + +// Update and show every x seconds void CProfileTimers::updateAndDisplay() { - if ( CClients::clientsDebugging(BOT_DEBUG_PROFILE) ) - { - if ( m_fNextUpdate < engine->Time() ) - { - int i = 0; - - double highest = 1.0; - - for ( i = 0; i < PROFILING_TIMERS; i ++ ) - { - if (m_Timers[i].getOverall() > highest) - highest = m_Timers[i].getOverall(); - } - - // next update in 1 second - m_fNextUpdate = engine->Time() + 1.0f; - - CClients::clientDebugMsg(BOT_DEBUG_PROFILE,"|----------------PROFILING---UPDATE---------------------------------|"); - CClients::clientDebugMsg(BOT_DEBUG_PROFILE,"|------name------|---overall---|---min----|---max----|----avg---|-prct-|"); - - for ( i = 0; i < PROFILING_TIMERS; i ++ ) - { - m_Timers[i].print(&highest); - } - } - } + if (CClients::clientsDebugging(BOT_DEBUG_PROFILE)) + { + if (m_fNextUpdate < engine->Time()) + { + double highest = 1.0; + + for (const CProfileTimer& m_Timer : m_Timers) + { + highest = std::max(static_cast(m_Timer.getOverall()), highest); + } + + // Next update in 1 second + m_fNextUpdate = engine->Time() + 1.0f; + + CClients::clientDebugMsg(BOT_DEBUG_PROFILE, "|----------------PROFILING---UPDATE---------------------------------|"); + CClients::clientDebugMsg(BOT_DEBUG_PROFILE, "|------name------|---overall---|---min----|---max----|----avg---|-prct-|"); + + for (CProfileTimer& m_Timer : m_Timers) + { + m_Timer.print(&highest); + } + } + } } \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_profiling.h b/utils/RCBot2_meta/bot_profiling.h index 5f7004f0e..6ff7fff42 100644 --- a/utils/RCBot2_meta/bot_profiling.h +++ b/utils/RCBot2_meta/bot_profiling.h @@ -38,56 +38,54 @@ #ifndef __BOT_PROFILING_H__ #define __BOT_PROFILING_H__ -using namespace std; - class CBot; class CProfileTimer { public: - CProfileTimer (const char *szFunction); + CProfileTimer(const char* szFunction); - inline const char *getFunction () + const char* getFunction() const { return m_szFunction; } - void Start(); + void Start(); - void Stop(); + void Stop(); - void print(double *high); + void print(const double* high); #ifndef __linux__ - inline __int64 getOverall () + __int64 getOverall() const #else - inline long long getOverall () + inline long long getOverall() const #endif - { - return m_overall; - } - + { + return m_overall; + } + private: #ifndef __linux__ - unsigned __int64 start_cycle; - unsigned __int64 end_cycle; - unsigned __int64 m_average; - unsigned __int64 m_min; - unsigned __int64 m_max; - unsigned __int64 m_last; - unsigned __int64 m_overall; + unsigned __int64 start_cycle; + unsigned __int64 end_cycle; + unsigned __int64 m_average; + unsigned __int64 m_min; + unsigned __int64 m_max; + unsigned __int64 m_last; + unsigned __int64 m_overall; #else - unsigned long long start_cycle; - unsigned long long end_cycle; - unsigned long long m_average; - unsigned long long m_min; - unsigned long long m_max; - unsigned long long m_last; - unsigned long long m_overall; + unsigned long long start_cycle; + unsigned long long end_cycle; + unsigned long long m_average; + unsigned long long m_min; + unsigned long long m_max; + unsigned long long m_last; + unsigned long long m_overall; #endif - const char *m_szFunction; + const char* m_szFunction; // helps us to know if the timer has been used recently // is also used to reset the minimum value @@ -96,13 +94,13 @@ class CProfileTimer int m_iInvoked; }; -enum +enum : std::uint8_t { -BOTS_THINK_TIMER = 0, -BOT_THINK_TIMER, -BOT_ROUTE_TIMER, -BOT_VISION_TIMER, -PROFILING_TIMERS + BOTS_THINK_TIMER = 0, + BOT_THINK_TIMER = 1, + BOT_ROUTE_TIMER = 2, + BOT_VISION_TIMER = 3, + PROFILING_TIMERS = 4 }; class CProfileTimers @@ -111,9 +109,9 @@ class CProfileTimers static void reset(); - static void updateAndDisplay (); + static void updateAndDisplay(); - static CProfileTimer *getTimer (int id); + static CProfileTimer* getTimer(int id); private: static CProfileTimer m_Timers[PROFILING_TIMERS]; diff --git a/utils/RCBot2_meta/bot_rb.h b/utils/RCBot2_meta/bot_rb.h index 08ff14e22..efb14f634 100644 --- a/utils/RCBot2_meta/bot_rb.h +++ b/utils/RCBot2_meta/bot_rb.h @@ -1,24 +1,42 @@ #ifndef __RCBOT_RB_H__ #define __RCBOT_RB_H__ +#include +#include // Include for std::uint8_t + +class CBotOperator; + +typedef enum : std::uint8_t +{ + OP_NONE = 0, + OP_PRE_NORM, + OP_PRE_NOT, + OP_AND, + OP_OR, + OP_AND_NOT, + OP_OR_NOT +} CBotFactOperator; // Corrected the typo in the typedef name class CBotRule { public: - CBotRule () - { - } + CBotRule() = default; + private: - vector m_Rules; + std::vector m_Rules; }; class CBotOperator { public: - CBotOperator ( CBotFactOpertor op ) : m_op(op) - { + virtual ~CBotOperator() = default; + + CBotOperator(const CBotFactOperator& op) : m_op(op) // Corrected the typo in the parameter type + { } - virtual bool operate ( bool bVal, CBotOperator *pNext ) + CBotOperator(); + + virtual bool operate(const bool bVal, CBotOperator* pNext) { switch (m_op) { @@ -26,52 +44,46 @@ class CBotOperator return bVal; case OP_PRE_NORM: return pNext->value(); - case OP_PRE_NOT: - case OP_AND: - case OP_OR: - case OP_AND_NOT: - case OP_OR_NOT: + // Uncomment and implement these cases as needed + // case OP_PRE_NOT: + // case OP_AND: + // case OP_OR: + // case OP_AND_NOT: + // case OP_OR_NOT: + default: + // Handle unexpected values of m_op + return false; // or some other default behavior } } virtual bool value() { - return -1; + return true; } private: - CBotFactOperator m_op; + CBotFactOperator m_op; // Corrected the typo in the member variable type }; + // for use with rule list class CBotFact : public CBotOperator { public: - CBotFact ( unsigned int iFactId ) : m_fid(iFactId) + CBotFact(const unsigned iFactId) : m_fid(iFactId) { } - bool operate ( bVal, CBotOperator *pNext ) + bool operate(const bool bVal, CBotOperator* pNext) override // Added missing parameter type { return m_bVal; } - bool value() + bool value() override { return m_bVal; } private: - unsigned int m_fid; + unsigned m_fid; bool m_bVal; }; -typedef enum -{ - OP_NONE = 0, - OP_PRE_NORM, - OP_PRE_NOT, - OP_AND, - OP_OR, - OP_AND_NOT, - OP_OR_NOT -}CBotFactOperator; - #endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_recipients.h b/utils/RCBot2_meta/bot_recipients.h index e55acfdb4..56900d3b8 100644 --- a/utils/RCBot2_meta/bot_recipients.h +++ b/utils/RCBot2_meta/bot_recipients.h @@ -31,30 +31,35 @@ #ifndef __BOT_RECIPIENTS_H__ #define __BOT_RECIPIENTS_H__ +#include +#include + +#include "bot_const.h" +#include "engine_wrappers.h" #include "irecipientfilter.h" class CEdictRecipient : public IRecipientFilter { public: - CEdictRecipient ( edict_t *pEdict, bool bReliable ) + CEdictRecipient (edict_t *pEdict, const bool bReliable) { m_pEdict = pEdict; m_bReliable = bReliable; } // require destructor - ~CEdictRecipient () + ~CEdictRecipient () override { - m_pEdict = NULL; + m_pEdict = nullptr; m_bReliable = false; } - bool IsReliable( void ) const { return m_bReliable; } + bool IsReliable() const override { return m_bReliable; } - bool IsInitMessage( void ) const { return false; } + bool IsInitMessage() const override { return false; } - int GetRecipientCount( void ) const { return 1; } - int GetRecipientIndex( int slot ) const { return ENTINDEX(m_pEdict); } // only 1 stored + int GetRecipientCount() const override { return 1; } + int GetRecipientIndex( int slot ) const override { return ENTINDEX(m_pEdict); } // only 1 stored private: edict_t *m_pEdict; bool m_bReliable; diff --git a/utils/RCBot2_meta/bot_schedule.cpp b/utils/RCBot2_meta/bot_schedule.cpp index 25a19e2a0..85edac9e6 100644 --- a/utils/RCBot2_meta/bot_schedule.cpp +++ b/utils/RCBot2_meta/bot_schedule.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * part of https://rcbot2.svn.sourceforge.net/svnroot/rcbot2 * @@ -31,14 +33,14 @@ * */ -#include "bot.h" #include "bot_schedule.h" -#include "bot_task.h" +#include "bot.h" #include "bot_client.h" -#include "bot_weapons.h" -#include "bot_globals.h" #include "bot_getprop.h" +#include "bot_globals.h" +#include "bot_task.h" #include "bot_waypoint_locations.h" +#include "bot_weapons.h" //////////////////////////////////// // these must match the SCHED IDs const char *szSchedules[SCHED_MAX+1] = @@ -89,6 +91,14 @@ const char *szSchedules[SCHED_MAX+1] = "SCHED_RETURN_TO_INTEL", "SCHED_INVESTIGATE_HIDE", "SCHED_TAUNT", + "SCHED_SYN_OPEN_DOOR", + "SCHED_SYN_DISARM_MINE", + "SCHED_SYN_PLANT_MINE", + "SCHED_SYN_BREAK_ICRATE", + "SCHED_BUY", + "SCHED_PLANT_BOMB", + "SCHED_WAIT", + "SCHED_WAIT_FOR_ENEMY", "SCHED_MAX" }; ////////////////////// unused @@ -103,7 +113,8 @@ void CBotTF2DemoPipeEnemySched :: init() setID(SCHED_TF2_DEMO_PIPEENEMY); } /////////////////// -CBotTF2DemoPipeTrapSched :: CBotTF2DemoPipeTrapSched ( eDemoTrapType type, Vector vStand, Vector vLoc, Vector vSpread, bool bAutoDetonate, int wptarea ) + +CBotTF2DemoPipeTrapSched :: CBotTF2DemoPipeTrapSched (const eDemoTrapType type, const Vector& vStand, const Vector& vLoc, const Vector& vSpread, const bool bAutoDetonate, const int wptarea) { addTask(new CFindPathTask(vStand)); addTask(new CBotTF2DemomanPipeTrap(type,vStand,vLoc,vSpread,bAutoDetonate,wptarea)); @@ -114,8 +125,8 @@ void CBotTF2DemoPipeTrapSched :: init() setID(SCHED_TF2_DEMO_PIPETRAP); } - ////////////////////////////////////// + CBotTF2HealSched::CBotTF2HealSched(edict_t *pHeal) { CFindPathTask *findpath = new CFindPathTask(pHeal); @@ -131,7 +142,7 @@ void CBotTF2HealSched::init() ///////////////////////////////////////////// -CBotTFEngiBuild :: CBotTFEngiBuild ( CBot *pBot, eEngiBuild iObject, CWaypoint *pWaypoint ) +CBotTFEngiBuild :: CBotTFEngiBuild (const CBot *pBot, const eEngiBuild iObject, CWaypoint *pWaypoint) { CFindPathTask *pathtask = new CFindPathTask(CWaypoints::getWaypointIndex(pWaypoint)); addTask(pathtask); // first @@ -145,9 +156,10 @@ void CBotTFEngiBuild :: init () { setID(SCHED_TF_BUILD); } + ////////////////////////////////////////////// -CBotGetMetalSched :: CBotGetMetalSched ( Vector vOrigin ) +CBotGetMetalSched :: CBotGetMetalSched (const Vector& vOrigin) { CFindPathTask *task1 = new CFindPathTask(vOrigin); @@ -164,8 +176,10 @@ void CBotGetMetalSched :: init () { setID(SCHED_GET_METAL); } + ////////////////////////////////////////////// -CBotEngiMoveBuilding :: CBotEngiMoveBuilding ( edict_t *pBotEdict, edict_t *pBuilding, eEngiBuild iObject, Vector vNewLocation, bool bCarrying ) + +CBotEngiMoveBuilding::CBotEngiMoveBuilding(edict_t *pBotEdict, edict_t *pBuilding, const eEngiBuild iObject, const Vector& vNewLocation, const bool bCarrying) { // not carrying if ( !bCarrying ) @@ -184,7 +198,6 @@ void CBotEngiMoveBuilding :: init () setID(SCHED_TF2_ENGI_MOVE_BUILDING); } - /////////////////////////////////////////// CBotTF2PushPayloadBombSched :: CBotTF2PushPayloadBombSched (edict_t * ePayloadBomb) @@ -197,6 +210,7 @@ void CBotTF2PushPayloadBombSched :: init () { setID(SCHED_TF2_PUSH_PAYLOADBOMB); } + /////////////////////////////////// CBotTF2DefendPayloadBombSched :: CBotTF2DefendPayloadBombSched (edict_t * ePayloadBomb) @@ -210,10 +224,9 @@ void CBotTF2DefendPayloadBombSched :: init () setID(SCHED_TF2_DEFEND_PAYLOADBOMB); } - ////////////////////////////////////////////// -CBotTFEngiUpgrade :: CBotTFEngiUpgrade ( CBot *pBot, edict_t *pBuilding ) +CBotTFEngiUpgrade :: CBotTFEngiUpgrade (const CBot *pBot, edict_t *pBuilding) { CFindPathTask *pathtask = new CFindPathTask(pBuilding); @@ -246,11 +259,10 @@ void CBotTFEngiUpgrade :: init () ////////////////////////////////////////////////// CBotBackstabSched :: CBotBackstabSched ( edict_t *pEnemy ) { - Vector vrear; Vector vangles; AngleVectors(CBotGlobals::entityEyeAngles(pEnemy),&vangles); - vrear = CBotGlobals::entityOrigin(pEnemy) - (vangles * 45) + Vector(0,0,32); + const Vector vrear = CBotGlobals::entityOrigin(pEnemy) - vangles * 45 + Vector(0, 0, 32); addTask(new CFindPathTask(vrear)); addTask(new CBotBackstab(pEnemy)); @@ -264,7 +276,7 @@ void CBotBackstabSched :: init () /////////// -CBotTF2SnipeCrossBowSched::CBotTF2SnipeCrossBowSched(Vector vOrigin, int iWpt) +CBotTF2SnipeCrossBowSched::CBotTF2SnipeCrossBowSched(const Vector& vOrigin, const int iWpt) { CBotTask *pFindPath = new CFindPathTask(iWpt); CBotTask *pSnipeTask = new CBotTF2SnipeCrossBow(vOrigin, iWpt); @@ -274,16 +286,14 @@ CBotTF2SnipeCrossBowSched::CBotTF2SnipeCrossBowSched(Vector vOrigin, int iWpt) pFindPath->setFailInterrupt(CONDITION_PARANOID); pSnipeTask->setFailInterrupt(CONDITION_PARANOID); - } - void CBotTF2SnipeCrossBowSched::init() { setID(SCHED_SNIPE); } -CBotTF2SnipeSched :: CBotTF2SnipeSched ( Vector vOrigin, int iWpt ) +CBotTF2SnipeSched :: CBotTF2SnipeSched (const Vector& vOrigin, const int iWpt) { CBotTask *pFindPath = new CFindPathTask(iWpt); CBotTask *pSnipeTask = new CBotTF2Snipe(vOrigin,iWpt); @@ -293,10 +303,8 @@ CBotTF2SnipeSched :: CBotTF2SnipeSched ( Vector vOrigin, int iWpt ) pFindPath->setFailInterrupt(CONDITION_PARANOID); pSnipeTask->setFailInterrupt(CONDITION_PARANOID); - } - void CBotTF2SnipeSched :: init () { setID(SCHED_SNIPE); @@ -315,7 +323,7 @@ void CBotTFEngiLookAfterSentry :: init () } //////////// -CBotTF2GetHealthSched :: CBotTF2GetHealthSched ( Vector vOrigin ) +CBotTF2GetHealthSched :: CBotTF2GetHealthSched (const Vector& vOrigin) { CFindPathTask *task1 = new CFindPathTask(vOrigin); CBotTF2WaitHealthTask *task2 = new CBotTF2WaitHealthTask(vOrigin); @@ -333,9 +341,10 @@ void CBotTF2GetHealthSched :: init () { setID(SCHED_TF2_GET_HEALTH); } + /////////////////////////////////////// -CBotTF2GetAmmoSched :: CBotTF2GetAmmoSched ( Vector vOrigin ) +CBotTF2GetAmmoSched :: CBotTF2GetAmmoSched (const Vector& vOrigin) { CFindPathTask *task1 = new CFindPathTask(vOrigin); CBotTF2WaitAmmoTask *task2 = new CBotTF2WaitAmmoTask(vOrigin); @@ -355,7 +364,7 @@ void CBotTF2GetAmmoSched :: init () } ////////////////////////////////////////////// -CBotTF2GetFlagSched :: CBotTF2GetFlagSched ( Vector vOrigin, bool bUseRoute, Vector vRoute ) +CBotTF2GetFlagSched :: CBotTF2GetFlagSched (const Vector& vOrigin, const bool bUseRoute, const Vector& vRoute) { if ( bUseRoute ) addTask(new CFindPathTask(vRoute)); @@ -368,6 +377,7 @@ void CBotTF2GetFlagSched :: init () { setID(SCHED_TF2_GET_FLAG); } + /////////////////////////////////////////// CBotUseTeleSched :: CBotUseTeleSched ( edict_t *pTele ) { @@ -379,9 +389,10 @@ void CBotUseTeleSched :: init () { setID(SCHED_USE_TELE); } + ////////////////////////////////////////// -CBotUseDispSched :: CBotUseDispSched ( CBot *pBot, edict_t *pDisp )//, bool bNest ) +CBotUseDispSched :: CBotUseDispSched (const CBot *pBot, edict_t *pDisp)//, bool bNest ) { CFindPathTask *pathtask = new CFindPathTask(pDisp); CBotTF2WaitHealthTask *gethealth = new CBotTF2WaitHealthTask(CBotGlobals::entityOrigin(pDisp)); @@ -400,14 +411,13 @@ void CBotUseDispSched :: init () setID(SCHED_USE_DISPENSER); } - //////////////////////////////////////////// void CBotSpySapBuildingSched :: init () { setID(SCHED_SPY_SAP_BUILDING); } -CBotSpySapBuildingSched :: CBotSpySapBuildingSched ( edict_t *pBuilding, eEngiBuild id ) +CBotSpySapBuildingSched :: CBotSpySapBuildingSched ( edict_t *pBuilding, const eEngiBuild id ) { CFindPathTask *findpath = new CFindPathTask(pBuilding); @@ -417,29 +427,26 @@ CBotSpySapBuildingSched :: CBotSpySapBuildingSched ( edict_t *pBuilding, eEngiBu findpath->setDangerPoint(CWaypointLocations::NearestWaypoint(CBotGlobals::entityOrigin(pBuilding),200.0f,-1)); } ////////////////////////////////////// -CBotTauntSchedule :: CBotTauntSchedule ( edict_t *pPlayer, float fYaw ) +CBotTauntSchedule :: CBotTauntSchedule ( edict_t *pPlayer, const float fYaw ) : m_pPlayer(pPlayer) { - QAngle angles = QAngle(0,fYaw,0); + const QAngle angles = QAngle(0,fYaw,0); Vector forward; - Vector vOrigin; - Vector vGoto; - const float fTauntDist = 40.0f; + constexpr float fTauntDist = 40.0f; - m_pPlayer = pPlayer; m_fYaw = 180 - fYaw; AngleVectors(angles,&forward); - forward = forward/forward.Length(); - vOrigin = CBotGlobals::entityOrigin(pPlayer); + //forward = forward/forward.Length(); + const Vector vOrigin = CBotGlobals::entityOrigin(pPlayer); - vGoto = vOrigin + (forward*fTauntDist); + const Vector vGoto = vOrigin + forward * fTauntDist; CBotGlobals::fixFloatAngle(&m_fYaw); - addTask(new CFindPathTask(vOrigin)); - addTask(new CMoveToTask(vOrigin)); - addTask(new CTF2_TauntTask(vOrigin,vGoto,fTauntDist)); + addTask(new CFindPathTask(vGoto)); + addTask(new CMoveToTask(vGoto)); + addTask(new CTF2_TauntTask(pPlayer, vGoto, 5.0f)); } void CBotTauntSchedule :: init () @@ -449,7 +456,7 @@ void CBotTauntSchedule :: init () /////////////////////////////////////////// -CBotTF2FindFlagSched :: CBotTF2FindFlagSched ( Vector vOrigin ) +CBotTF2FindFlagSched :: CBotTF2FindFlagSched (const Vector& vOrigin) { addTask(new CFindPathTask(vOrigin)); // first addTask(new CBotTF2WaitFlagTask(vOrigin,true)); // second @@ -484,7 +491,7 @@ void CBotPickupSchedUse :: init () } ///////////////////////////////////////////// -CBotInvestigateNoiseSched::CBotInvestigateNoiseSched ( Vector vSource, Vector vAttackPoint ) +CBotInvestigateNoiseSched::CBotInvestigateNoiseSched (const Vector& vSource, const Vector& vAttackPoint) { addTask(new CFindPathTask(vSource,LOOK_NOISE)); addTask(new CBotInvestigateTask(vSource,200.0f,vAttackPoint,true,3.0f)); @@ -496,7 +503,7 @@ void CBotInvestigateNoiseSched::init () } //////////////////////////////////////////////// -CBotGotoOriginSched :: CBotGotoOriginSched ( Vector vOrigin ) +CBotGotoOriginSched :: CBotGotoOriginSched (const Vector& vOrigin) { addTask(new CFindPathTask(vOrigin)); // first addTask(new CMoveToTask(vOrigin)); // second @@ -512,18 +519,17 @@ void CBotGotoOriginSched :: init () { setID(SCHED_GOTO_ORIGIN); } + /////////////////////////////////////// -CBotDefendSched ::CBotDefendSched ( Vector vOrigin, float fMaxTime ) +CBotDefendSched ::CBotDefendSched (const Vector& vOrigin, const float fMaxTime) { addTask(new CFindPathTask(vOrigin)); addTask(new CBotDefendTask(vOrigin,fMaxTime)); } -CBotDefendSched::CBotDefendSched ( int iWaypointID, float fMaxTime ) +CBotDefendSched::CBotDefendSched (const int iWaypointID, const float fMaxTime) { - CWaypoint *pWaypoint; - - pWaypoint = CWaypoints::getWaypoint(iWaypointID); + CWaypoint* pWaypoint = CWaypoints::getWaypoint(iWaypointID); addTask(new CFindPathTask(iWaypointID)); addTask(new CBotDefendTask(pWaypoint->getOrigin(),fMaxTime,8,false,Vector(0,0,0),LOOK_SNIPE,pWaypoint->getFlags())); @@ -536,7 +542,7 @@ void CBotDefendSched :: init () ////// -CBotRemoveSapperSched :: CBotRemoveSapperSched ( edict_t *pBuilding, eEngiBuild id ) +CBotRemoveSapperSched :: CBotRemoveSapperSched ( edict_t *pBuilding, const eEngiBuild id ) { CFindPathTask *pathtask = new CFindPathTask(pBuilding); addTask(pathtask); @@ -550,7 +556,7 @@ void CBotRemoveSapperSched :: init () setID(SCHED_REMOVESAPPER); } /////////// -CGotoHideSpotSched :: CGotoHideSpotSched ( CBot *pBot, edict_t *pEdict, bool bIsGrenade ) +CGotoHideSpotSched :: CGotoHideSpotSched ( CBot *pBot, edict_t *pEdict, const bool bIsGrenade ) { // run at flank while shooting CFindPathTask *pHideGoalPoint = new CFindPathTask(pEdict); @@ -576,12 +582,12 @@ CGotoHideSpotSched :: CGotoHideSpotSched ( CBot *pBot, edict_t *pEdict, bool bIs } } -CGotoHideSpotSched :: CGotoHideSpotSched (CBot *pBot, Vector vOrigin, IBotTaskInterrupt *interrupt ) +CGotoHideSpotSched :: CGotoHideSpotSched (CBot *pBot, const Vector& vOrigin, IBotTaskInterrupt *interrupt) { // run at flank while shooting CFindPathTask *pHideGoalPoint = new CFindPathTask(); - pBot->setCoverFrom(NULL); + pBot->setCoverFrom(nullptr); addTask(new CFindGoodHideSpot(vOrigin)); addTask(pHideGoalPoint); @@ -597,7 +603,7 @@ void CGotoHideSpotSched :: init () setID(SCHED_GOOD_HIDE_SPOT); } /////////////// -CGotoNestSched :: CGotoNestSched (int iWaypoint ) +CGotoNestSched :: CGotoNestSched (int iWaypoint) { //addTask(new CFindGoodHideSpot(1)); //addTask(new CNestTask()); @@ -629,7 +635,7 @@ CBotTF2AttackSentryGun::CBotTF2AttackSentryGun( edict_t *pSentry, CBotWeapon *pW path->completeInRangeFromEdict(); path->completeIfSeeTaskEdict(); - path->setRange(pWeapon->primaryMaxRange()-100); + path->setRange(pWeapon->primaryMaxRange() - 100); } ///////////// @@ -644,11 +650,11 @@ void CBotAttackSched :: init () setID(SCHED_ATTACK); } /////////////////////////////////////////// -CBotAttackPointSched :: CBotAttackPointSched ( Vector vPoint, int iRadius, int iArea, bool bHasRoute, Vector vRoute, bool bNest, edict_t *pLastEnemySentry ) +CBotAttackPointSched :: CBotAttackPointSched (const Vector& vPoint, const float fRadius, const int iArea, const bool bHasRoute, const Vector& vRoute, const bool bNest, edict_t *pLastEnemySentry) { int iDangerWpt = -1; - if ( pLastEnemySentry != NULL ) + if ( pLastEnemySentry != nullptr) iDangerWpt = CWaypointLocations::NearestWaypoint(CBotGlobals::entityOrigin(pLastEnemySentry),200.0f,-1,true,true); // First find random route @@ -665,7 +671,7 @@ CBotAttackPointSched :: CBotAttackPointSched ( Vector vPoint, int iRadius, int i CFindPathTask *toPoint = new CFindPathTask(vPoint); addTask(toPoint); // second / first toPoint->setDangerPoint(iDangerWpt); - addTask(new CBotTF2AttackPoint(iArea,vPoint,iRadius)); // third / second + addTask(new CBotTF2AttackPoint(iArea,vPoint,fRadius)); // third / second } void CBotAttackPointSched ::init () @@ -673,7 +679,7 @@ void CBotAttackPointSched ::init () setID(SCHED_ATTACKPOINT); } /////////////// -CBotTF2MessAroundSched :: CBotTF2MessAroundSched ( edict_t *pFriendly, int iMaxVoiceCmd ) +CBotTF2MessAroundSched :: CBotTF2MessAroundSched ( edict_t *pFriendly, const int iMaxVoiceCmd ) { addTask(new CMessAround(pFriendly,iMaxVoiceCmd)); } @@ -684,21 +690,23 @@ void CBotTF2MessAroundSched :: init() } //////////////////////////////////////////////// -CBotFollowLastEnemy :: CBotFollowLastEnemy ( CBot *pBot, edict_t *pEnemy, Vector vLastSee ) +CBotFollowLastEnemy::CBotFollowLastEnemy(CBot* pBot, edict_t* pEnemy, const Vector& vLastSee) { - Vector vVelocity = Vector(0,0,0); - CClient *pClient = CClients::get(pEnemy); + Vector vVelocity = Vector(0, 0, 0); + CClient* pClient = CClients::get(pEnemy); - CFindPathTask *pFindPath = new CFindPathTask(vLastSee,LOOK_LAST_ENEMY); + CFindPathTask* pFindPath = new CFindPathTask(vLastSee, LOOK_LAST_ENEMY); - if ( CClassInterface :: getVelocity(pEnemy,&vVelocity) ) + if (CClassInterface::getVelocity(pEnemy, &vVelocity)) { - if ( pClient && (vVelocity == Vector(0,0,0)) ) + if (pClient && vVelocity == Vector(0, 0, 0)) + vVelocity = pClient->getVelocity(); + } + else + { + if (pClient) vVelocity = pClient->getVelocity(); } - else if ( pClient ) - vVelocity = pClient->getVelocity(); - pFindPath->setCompleteInterrupt(CONDITION_SEE_CUR_ENEMY); addTask(pFindPath); @@ -706,12 +714,12 @@ CBotFollowLastEnemy :: CBotFollowLastEnemy ( CBot *pBot, edict_t *pEnemy, Vector /*if ( pBot->isTF2() ) { int playerclass = ((CBotTF2*)pBot)->getClass(); - + if ( ( playerclass == TF_CLASS_SOLDIER ) || (playerclass == TF_CLASS_DEMOMAN) ) addTask(new CBotTF2ShootLastEnemyPosition(vLastSee,pEnemy,vVelocity)); }*/ - addTask(new CFindLastEnemy(vLastSee,vVelocity)); + addTask(new CFindLastEnemy(vLastSee, vVelocity)); ////////////// pFindPath->setNoInterruptions(); @@ -723,7 +731,7 @@ void CBotFollowLastEnemy :: init () } -CBotTF2ShootLastEnemyPos::CBotTF2ShootLastEnemyPos ( Vector vLastSeeEnemyPos, Vector vVelocity, edict_t *pLastEnemy ) +CBotTF2ShootLastEnemyPos::CBotTF2ShootLastEnemyPos (const Vector& vLastSeeEnemyPos, const Vector& vVelocity, edict_t *pLastEnemy) { addTask(new CBotTF2ShootLastEnemyPosition(vLastSeeEnemyPos,pLastEnemy,vVelocity)); } @@ -734,16 +742,16 @@ void CBotTF2ShootLastEnemyPos::init() } /////////////////////////////// -CDeployMachineGunSched :: CDeployMachineGunSched ( CBotWeapon *pWeapon, CWaypoint *pWaypoint, Vector vEnemy ) +CDeployMachineGunSched :: CDeployMachineGunSched (CBotWeapon *pWeapon, CWaypoint *pWaypoint, const Vector& vEnemy) { addTask(new CFindPathTask(CWaypoints::getWaypointIndex(pWaypoint),LOOK_LAST_ENEMY)); addTask(new CBotDODSnipe(pWeapon,pWaypoint->getOrigin(),pWaypoint->getAimYaw(),true,vEnemy.z,pWaypoint->getFlags())); } ////////////////////////////////////////////////// -CBotDefendPointSched :: CBotDefendPointSched ( Vector vPoint, int iRadius, int iArea ) +CBotDefendPointSched :: CBotDefendPointSched (const Vector& vPoint, const float fRadius, const int iArea) { addTask(new CFindPathTask(vPoint)); // first - addTask(new CBotTF2DefendPoint(iArea,vPoint,iRadius)); // second + addTask(new CBotTF2DefendPoint(iArea,vPoint,fRadius)); // second } void CBotDefendPointSched ::init () @@ -751,6 +759,44 @@ void CBotDefendPointSched ::init () setID(SCHED_DEFENDPOINT); } +CSynOpenDoorSched::CSynOpenDoorSched(edict_t *pDoor) +{ + addTask(new CBotHL2DMUseButton(pDoor)); // The bot will already move to range with this task + addTask(new CBotWaitTask(3.0f)); +} + +CSynDisarmMineSched::CSynDisarmMineSched(edict_t *pMine) +{ + addTask(new CBotSynDisarmMineTask(pMine)); +} + +CSynBreakICrateSched::CSynBreakICrateSched(edict_t* pCrate, CBotWeapon* pWeapon) +{ + CFindPathTask *pPathTask = new CFindPathTask(pCrate); + pPathTask->setRange(96.0f); + addTask(pPathTask); + addTask(new CMoveToTask(pCrate)); + addTask(new CBotSynBreakICrateTask(pCrate, pWeapon)); +} + +/******************************** + * Counter-Strike: Source * + ********************************/ +CCSSPlantBombSched::CCSSPlantBombSched(CWaypoint *pWaypoint, CWaypoint *pRoute) +{ + if(pRoute) + { + CBotTask *pRouteTask = new CFindPathTask(CWaypoints::getWaypointIndex(pRoute)); + pRouteTask->setFailInterrupt(CONDITION_SEE_CUR_ENEMY); + addTask(pRouteTask); + } + + CBotTask *pTask = new CFindPathTask(CWaypoints::getWaypointIndex(pWaypoint)); + pTask->setFailInterrupt(CONDITION_SEE_CUR_ENEMY); + addTask(pTask); + addTask(new CMoveToTask(pWaypoint->getOrigin())); + addTask(new CCSSPlantTheBombTask()); +} ///////////////////////////////////////////// void CBotSchedule :: execute ( CBot *pBot ) @@ -759,15 +805,16 @@ void CBotSchedule :: execute ( CBot *pBot ) static CBotTask *pTask; static eTaskState iState; - if ( m_Tasks.IsEmpty() ) + if ( m_Tasks.empty() ) { m_bFailed = true; return; } - pTask = m_Tasks.GetFrontInfo(); + // why would task ever be null?? + pTask = m_Tasks.front(); - if ( pTask == NULL ) + if ( pTask == nullptr) { m_bFailed = true; return; @@ -790,7 +837,7 @@ void CBotSchedule :: execute ( CBot *pBot ) { char dbg[512]; - pTask->debugString(dbg); + pTask->debugString(dbg, {}); CClients::clientDebugMsg(BOT_DEBUG_TASK,dbg,pBot); } @@ -813,20 +860,18 @@ void CBotSchedule :: addTask ( CBotTask *pTask ) { // initialize pTask->init(); - // add - m_Tasks.Add(pTask); + // add + m_Tasks.emplace_back(pTask); } void CBotSchedule :: removeTop () { - CBotTask *pTask = m_Tasks.GetFrontInfo(); - - m_Tasks.RemoveFront(); - + const CBotTask *pTask = m_Tasks.front(); + m_Tasks.pop_front(); delete pTask; } -const char *CBotSchedule :: getIDString () +const char *CBotSchedule :: getIDString () const { return szSchedules[m_iSchedId]; } @@ -848,22 +893,22 @@ void CBotSchedule :: _init () iPass = 0; fPass = 0; vPass = Vector(0,0,0); - pPass = 0; + pPass = nullptr; - init(); + //init(); // may cause an unexpected result at runtime - [APG]RoboCop[CL] } -void CBotSchedule :: passInt(int i) +void CBotSchedule :: passInt(const int i) { iPass = i; m_bitsPass |= BITS_SCHED_PASS_INT; } -void CBotSchedule :: passFloat(float f) +void CBotSchedule :: passFloat(const float f) { fPass = f; m_bitsPass |= BITS_SCHED_PASS_FLOAT; } -void CBotSchedule :: passVector(Vector v) +void CBotSchedule :: passVector(const Vector& v) { vPass = v; m_bitsPass |= BITS_SCHED_PASS_VECTOR; diff --git a/utils/RCBot2_meta/bot_schedule.h b/utils/RCBot2_meta/bot_schedule.h index f5a31ab60..63327df2f 100644 --- a/utils/RCBot2_meta/bot_schedule.h +++ b/utils/RCBot2_meta/bot_schedule.h @@ -33,19 +33,24 @@ #include "bot.h" #include "bot_task.h" -#include "bot_genclass.h" //#include "bot_fortress.h" +#include +#include + class CBotTask; class CAttackEntityTask; class IBotTaskInterrupt; -#define BITS_SCHED_PASS_INT (1<<0) -#define BITS_SCHED_PASS_FLOAT (1<<1) -#define BITS_SCHED_PASS_VECTOR (1<<2) -#define BITS_SCHED_PASS_EDICT (1<<3) +enum : std::uint8_t +{ + BITS_SCHED_PASS_INT = 1<<0, + BITS_SCHED_PASS_FLOAT = 1<<1, + BITS_SCHED_PASS_VECTOR = 1<<2, + BITS_SCHED_PASS_EDICT = 1<<3 +}; -typedef enum +typedef enum : std::uint8_t { SCHED_NONE = 0, SCHED_ATTACK, @@ -93,6 +98,14 @@ typedef enum SCHED_RETURN_TO_INTEL, SCHED_INVESTIGATE_HIDE, SCHED_TAUNT, + SCHED_SYN_OPEN_DOOR, + SCHED_SYN_DISARM_MINE, + SCHED_SYN_PLANT_MINE, + SCHED_SYN_BREAK_ICRATE, + SCHED_BUY, + SCHED_PLANT_BOMB, + SCHED_WAIT, + SCHED_WAIT_FOR_ENEMY, SCHED_MAX //SCHED_HIDE_FROM_ENEMY }eBotSchedule; @@ -110,36 +123,40 @@ class CBotSchedule CBotSchedule(); void _init (); - virtual void init () { return; } // nothing, used by sub classes + + virtual void init () { + } // nothing, used by sub classes + + virtual ~CBotSchedule() = default; //TODO: experimental [APG]RoboCop[CL] void addTask( CBotTask *pTask ); void execute ( CBot *pBot ); - const char *getIDString (); + const char *getIDString () const; - CBotTask *currentTask () + CBotTask *currentTask () const { - if ( m_Tasks.IsEmpty() ) - return NULL; - - return m_Tasks.GetFrontInfo(); + return m_Tasks.empty() ? nullptr : m_Tasks.front(); } - bool hasFailed () + bool hasFailed () const { return m_bFailed; } - bool isComplete () + bool isComplete () const { - return m_Tasks.IsEmpty(); + return m_Tasks.empty(); } void freeMemory () { - m_Tasks.Destroy(); - } + for (const CBotTask* task : m_Tasks) { + delete task; + } + m_Tasks.clear(); + } void removeTop (); @@ -149,28 +166,27 @@ class CBotSchedule void passInt(int i); void passFloat(float f); - void passVector(Vector v); + void passVector(const Vector& v); void passEdict(edict_t *p); ////////////////////////// - bool hasPassInfo () { return (m_bitsPass!=0); } - - inline int passedInt () { return iPass; } - inline float passedFloat() { return fPass; } - inline Vector passedVector() { return vPass; } - inline edict_t *passedEdict() { return pPass; } - inline bool isID ( eBotSchedule iId ) { return m_iSchedId == iId; } + bool hasPassInfo () const { return m_bitsPass!=0; } - inline bool hasPassInt () { return ((m_bitsPass&BITS_SCHED_PASS_INT)>0); } - inline bool hasPassFloat () { return ((m_bitsPass&BITS_SCHED_PASS_FLOAT)>0); } - inline bool hasPassVector () { return ((m_bitsPass&BITS_SCHED_PASS_VECTOR)>0); } - inline bool hasPassEdict () { return ((m_bitsPass&BITS_SCHED_PASS_EDICT)>0); } + int passedInt () const { return iPass; } + float passedFloat() const { return fPass; } + Vector passedVector() { return vPass; } + edict_t *passedEdict() const { return pPass; } + bool isID (const eBotSchedule iId) const { return m_iSchedId == iId; } - inline void setID ( eBotSchedule iId ) { m_iSchedId = iId; } + bool hasPassInt () const { return (m_bitsPass&BITS_SCHED_PASS_INT)>0; } + bool hasPassFloat () const { return (m_bitsPass&BITS_SCHED_PASS_FLOAT)>0; } + bool hasPassVector () const { return (m_bitsPass&BITS_SCHED_PASS_VECTOR)>0; } + bool hasPassEdict () const { return (m_bitsPass&BITS_SCHED_PASS_EDICT)>0; } + void setID (const eBotSchedule iId) { m_iSchedId = iId; } private: - dataQueue m_Tasks; + std::deque m_Tasks; bool m_bFailed; eBotSchedule m_iSchedId; @@ -186,54 +202,31 @@ class CBotSchedule class CBotSchedules { public: - bool hasSchedule ( eBotSchedule iSchedule ) + bool hasSchedule(eBotSchedule iSchedule) const { - dataQueue tempQueue = m_Schedules; - - while ( !tempQueue.IsEmpty() ) - { - CBotSchedule *sched = tempQueue.ChooseFrom(); - - if ( sched->isID(iSchedule) ) - { - tempQueue.Init(); - return true; - } - } - - return false; + return std::any_of(m_Schedules.begin(), m_Schedules.end(), + [iSchedule](const CBotSchedule* sched) { + return sched->isID(iSchedule); + }); } - bool isCurrentSchedule ( eBotSchedule iSchedule ) + bool isCurrentSchedule (const eBotSchedule iSchedule) const { - if ( m_Schedules.IsEmpty() ) + if ( m_Schedules.empty() ) return false; - - return m_Schedules.GetFrontInfo()->isID(iSchedule); + return m_Schedules.front()->isID(iSchedule); } - void removeSchedule ( eBotSchedule iSchedule ) + // remove the first schedule in the queue matching this schedule identifier + void removeSchedule (const eBotSchedule iSchedule) { - dataQueue tempQueue = m_Schedules; - - CBotSchedule *toRemove = NULL; - - while ( !tempQueue.IsEmpty() ) - { - CBotSchedule *sched = tempQueue.ChooseFrom(); - - if ( sched->isID(iSchedule) ) - { - toRemove = sched; - tempQueue.Init(); - break; + for (std::deque::iterator it = m_Schedules.begin(); it != m_Schedules.end(); ) { + if ((*it)->isID(iSchedule)) { + m_Schedules.erase(it); + return; } + ++it; } - - if ( toRemove ) - m_Schedules.Remove(toRemove); - - return; } void execute ( CBot *pBot ) @@ -241,8 +234,7 @@ class CBotSchedules if ( isEmpty() ) return; - CBotSchedule *pSched = m_Schedules.GetFrontInfo(); - + CBotSchedule *pSched = m_Schedules.front(); pSched->execute(pBot); if ( pSched->isComplete() || pSched->hasFailed() ) @@ -251,10 +243,10 @@ class CBotSchedules void removeTop () { - CBotSchedule *pSched = m_Schedules.GetFrontInfo(); - - m_Schedules.RemoveFront(); + CBotSchedule *pSched = m_Schedules.front(); + m_Schedules.pop_front(); + // TODO: eradicate freeMemory from the codebase pSched->freeMemory(); delete pSched; @@ -262,7 +254,10 @@ class CBotSchedules void freeMemory () { - m_Schedules.Destroy(); + for (const CBotSchedule *sched : m_Schedules) { + delete sched; + } + m_Schedules.clear(); } void add ( CBotSchedule *pSchedule ) @@ -270,73 +265,70 @@ class CBotSchedules // initialize pSchedule->init(); // add - m_Schedules.Add(pSchedule); + m_Schedules.emplace_back(pSchedule); } void addFront ( CBotSchedule *pSchedule ) { pSchedule->init(); - m_Schedules.AddFront(pSchedule); + m_Schedules.push_front(pSchedule); } - inline bool isEmpty () + bool isEmpty () const { - return m_Schedules.IsEmpty(); + return m_Schedules.empty(); } - CBotTask *getCurrentTask () + CBotTask *getCurrentTask () const { - if ( !m_Schedules.IsEmpty() ) + if ( !m_Schedules.empty() ) { - CBotSchedule *sched = m_Schedules.GetFrontInfo(); + const CBotSchedule *sched = m_Schedules.front(); - if ( sched != NULL ) + if ( sched != nullptr) { return sched->currentTask(); } } - return NULL; + return nullptr; } - CBotSchedule *getCurrentSchedule () + CBotSchedule *getCurrentSchedule () const { if ( isEmpty() ) - return NULL; + return nullptr; - return m_Schedules.GetFrontInfo(); + return m_Schedules.front(); } private: - dataQueue m_Schedules; + std::deque m_Schedules; }; /////////////////////////////////////////// class CBotTF2DemoPipeTrapSched : public CBotSchedule { public: - CBotTF2DemoPipeTrapSched ( eDemoTrapType type, Vector vStand, Vector vLoc, Vector vSpread, bool bAutoDetonate = false, int wptarea = -1 ); + CBotTF2DemoPipeTrapSched ( eDemoTrapType type, const Vector& vStand, const Vector& vLoc, const Vector& vSpread, bool bAutoDetonate = false, int wptarea = -1 ); - void init(); + void init() override; }; class CBotTF2DemoPipeEnemySched : public CBotSchedule { public: - CBotTF2DemoPipeEnemySched ( - CBotWeapon *pLauncher, - Vector vStand, - edict_t *pEnemy ); + CBotTF2DemoPipeEnemySched ( CBotWeapon *pLauncher, Vector vStand, edict_t *pEnemy ); - void init(); + void init() override; }; /////////////////////////////////////////////// class CBotTF2ShootLastEnemyPos : public CBotSchedule { public: - CBotTF2ShootLastEnemyPos ( Vector vLastSeeEnemyPos, Vector vVelocity, edict_t *pLastEnemy ); + CBotTF2ShootLastEnemyPos (const Vector& vLastSeeEnemyPos, const Vector& vVelocity, edict_t *pLastEnemy ); - void init(); + void init() override; }; /////////////////////////////////////////////// @@ -345,7 +337,7 @@ class CBotTF2MessAroundSched : public CBotSchedule public: CBotTF2MessAroundSched ( edict_t *pFriendly, int iMaxVoiceCmd ); - void init(); + void init() override; }; /////////////////////////////////////////////////// @@ -354,7 +346,7 @@ class CBotTauntSchedule : public CBotSchedule public: CBotTauntSchedule ( edict_t *pPlayer, float fYaw ); - void init (); + void init () override; private: MyEHandle m_pPlayer; float m_fYaw; @@ -365,32 +357,32 @@ class CBotUseTeleSched : public CBotSchedule public: CBotUseTeleSched ( edict_t *pTele ); - void init (); + void init () override; }; /////////////////////////////////////////////////// class CBotEngiMoveBuilding : public CBotSchedule { public: - CBotEngiMoveBuilding ( edict_t *pBotEdict, edict_t *pBuilding, eEngiBuild iObject, Vector vNewLocation, bool bCarrying ); + CBotEngiMoveBuilding ( edict_t *pBotEdict, edict_t *pBuilding, eEngiBuild iObject, const Vector& vNewLocation, bool bCarrying ); - void init (); + void init () override; }; ///////////////////////////////////////////////// class CBotAttackPointSched : public CBotSchedule { public: - CBotAttackPointSched ( Vector vPoint, int iRadius, int iArea, bool bHasRoute = false, Vector vRoute = Vector(0,0,0), bool bNest = false, edict_t *pLastEnemySentry = NULL ); + CBotAttackPointSched (const Vector& vPoint, float fRadius, int iArea, bool bHasRoute = false, const Vector& vRoute = Vector(0,0,0), bool bNest = false, edict_t *pLastEnemySentry = nullptr); - void init (); + void init () override; }; ////////////////////////////////////////////////// class CBotDefendPointSched : public CBotSchedule { public: - CBotDefendPointSched ( Vector vPoint, int iRadius, int iArea ); + CBotDefendPointSched (const Vector& vPoint, float fRadius, int iArea); - void init (); + void init () override; }; /////////////////////////////////////////////// class CBotTF2PushPayloadBombSched : public CBotSchedule @@ -398,7 +390,7 @@ class CBotTF2PushPayloadBombSched : public CBotSchedule public: CBotTF2PushPayloadBombSched (edict_t * ePayloadBomb); - void init (); + void init () override; }; /////////////////////////////////////////////// class CBotTF2DefendPayloadBombSched : public CBotSchedule @@ -406,7 +398,7 @@ class CBotTF2DefendPayloadBombSched : public CBotSchedule public: CBotTF2DefendPayloadBombSched (edict_t * ePayloadBomb); - void init (); + void init () override; }; /////////////////////////////////////////////////// class CBotSpySapBuildingSched : public CBotSchedule @@ -414,24 +406,24 @@ class CBotSpySapBuildingSched : public CBotSchedule public: CBotSpySapBuildingSched ( edict_t *pBuilding, eEngiBuild id ); - void init (); + void init () override; }; //////////////////////////////////////////////// class CBotUseDispSched : public CBotSchedule { public: - CBotUseDispSched ( CBot *pBot, edict_t *pDisp ); + CBotUseDispSched (const CBot *pBot, edict_t *pDisp ); - void init (); + void init () override; }; /////////////////////////////////////////////////// class CBotTFEngiUpgrade : public CBotSchedule { public: - CBotTFEngiUpgrade ( CBot *pBot, edict_t *pBuilding ); + CBotTFEngiUpgrade (const CBot *pBot, edict_t *pBuilding ); - void init (); + void init () override; }; ////////////////////////////////////////////////////// class CBotTFEngiMoveBuilding : public CBotSchedule @@ -439,15 +431,15 @@ class CBotTFEngiMoveBuilding : public CBotSchedule public: CBotTFEngiMoveBuilding ( edict_t *pBuilding, Vector vNewOrigin ); - void init (); + void init () override; }; /////////////////////////////////////////////////// class CBotTFEngiBuild : public CBotSchedule { public: - CBotTFEngiBuild ( CBot *pBot, eEngiBuild iObject, CWaypoint *pWaypoint ); + CBotTFEngiBuild (const CBot *pBot, eEngiBuild iObject, CWaypoint *pWaypoint ); - void init (); + void init () override; }; class CBotRemoveSapperSched : public CBotSchedule @@ -455,32 +447,32 @@ class CBotRemoveSapperSched : public CBotSchedule public: CBotRemoveSapperSched ( edict_t *pBuilding, eEngiBuild id ); - void init(); + void init() override; }; class CBotTF2HealSched : public CBotSchedule { public: CBotTF2HealSched(edict_t *pHeal); - void init (); + void init () override; }; class CBotDefendSched : public CBotSchedule { public: - CBotDefendSched ( Vector vOrigin, float fMaxTime = 0 ); + CBotDefendSched (const Vector& vOrigin, float fMaxTime = 0 ); CBotDefendSched ( int iWaypointID, float fMaxTime = 0 ); - void init (); + void init () override; }; class CBotGetMetalSched : public CBotSchedule { public: - CBotGetMetalSched ( Vector vOrigin ); + CBotGetMetalSched (const Vector& vOrigin ); - void init (); + void init () override; }; class CBotBackstabSched : public CBotSchedule @@ -488,7 +480,7 @@ class CBotBackstabSched : public CBotSchedule public: CBotBackstabSched ( edict_t *pEnemy ); - void init(); + void init() override; }; class CBotTFEngiLookAfterSentry : public CBotSchedule @@ -496,31 +488,31 @@ class CBotTFEngiLookAfterSentry : public CBotSchedule public: CBotTFEngiLookAfterSentry ( edict_t *pSentry ); - void init (); + void init () override; }; class CBotFollowLastEnemy : public CBotSchedule { public: - CBotFollowLastEnemy ( CBot *pBot, edict_t *pEnemy, Vector vLastSee ); + CBotFollowLastEnemy ( CBot *pBot, edict_t *pEnemy, const Vector& vLastSee ); - void init (); + void init () override; }; class CBotTF2SnipeSched : public CBotSchedule { public: - CBotTF2SnipeSched ( Vector vOrigin, int iWpt ); + CBotTF2SnipeSched (const Vector& vOrigin, int iWpt ); - void init (); + void init () override; }; class CBotTF2SnipeCrossBowSched : public CBotSchedule { public: - CBotTF2SnipeCrossBowSched(Vector vOrigin, int iWpt); + CBotTF2SnipeCrossBowSched(const Vector& vOrigin, int iWpt); - void init(); + void init() override; }; class CBotTF2AttackSentryGun : public CBotSchedule @@ -528,7 +520,7 @@ class CBotTF2AttackSentryGun : public CBotSchedule public: CBotTF2AttackSentryGun( edict_t *pSentry, CBotWeapon *pWeapon ); - void init () + void init () override { setID(SCHED_ATTACK_SENTRY_GUN); } @@ -537,33 +529,33 @@ class CBotTF2AttackSentryGun : public CBotSchedule class CBotTF2GetAmmoSched : public CBotSchedule { public: - CBotTF2GetAmmoSched ( Vector vOrigin ); + CBotTF2GetAmmoSched (const Vector& vOrigin ); - void init (); + void init () override; }; class CBotTF2GetHealthSched : public CBotSchedule { public: - CBotTF2GetHealthSched ( Vector vOrigin ); + CBotTF2GetHealthSched (const Vector& vOrigin ); - void init (); + void init () override; }; class CBotTF2GetFlagSched : public CBotSchedule { public: - CBotTF2GetFlagSched ( Vector vOrigin, bool bUseRoute = false, Vector vRoute = Vector(0,0,0) ); + CBotTF2GetFlagSched (const Vector& vOrigin, bool bUseRoute = false, const Vector& vRoute = Vector(0,0,0) ); - void init (); + void init () override; }; class CBotTF2FindFlagSched : public CBotSchedule { public: - CBotTF2FindFlagSched ( Vector vOrigin ); + CBotTF2FindFlagSched (const Vector& vOrigin ); - void init (); + void init () override; }; class CBotPickupSched : public CBotSchedule @@ -571,7 +563,7 @@ class CBotPickupSched : public CBotSchedule public: CBotPickupSched ( edict_t *pEdict ); - void init (); + void init () override; }; class CBotPickupSchedUse : public CBotSchedule @@ -579,17 +571,17 @@ class CBotPickupSchedUse : public CBotSchedule public: CBotPickupSchedUse ( edict_t *pEdict ); - void init (); + void init () override; }; class CBotGotoOriginSched : public CBotSchedule { public: - CBotGotoOriginSched ( Vector vOrigin ); + CBotGotoOriginSched (const Vector& vOrigin ); CBotGotoOriginSched ( edict_t *pEdict ); - void init (); + void init () override; }; class CBotAttackSched : public CBotSchedule @@ -597,7 +589,7 @@ class CBotAttackSched : public CBotSchedule public: CBotAttackSched ( edict_t *pEdict ); - void init (); + void init () override; }; class CRunForCover : public CBotSchedule @@ -606,7 +598,7 @@ class CRunForCover : public CBotSchedule // run for cover to this spot CRunForCover ( Vector vOrigin ); - void init () + void init () override { setID(SCHED_RUN_FOR_COVER); } @@ -615,9 +607,9 @@ class CRunForCover : public CBotSchedule class CBotInvestigateNoiseSched : public CBotSchedule { public: - CBotInvestigateNoiseSched ( Vector vSource, Vector vAttackPoint ); + CBotInvestigateNoiseSched (const Vector& vSource, const Vector& vAttackPoint ); - void init (); + void init () override; }; class CGotoHideSpotSched : public CBotSchedule @@ -627,9 +619,9 @@ class CGotoHideSpotSched : public CBotSchedule // hide from an enemy (pEdict) CGotoHideSpotSched ( CBot *pBot, edict_t *pEdict, bool bIsGrenade = false ); // hide from a Vector - CGotoHideSpotSched ( CBot *pBot, Vector vOrigin, IBotTaskInterrupt *interrupt = NULL ); + CGotoHideSpotSched ( CBot *pBot, const Vector& vOrigin, IBotTaskInterrupt *interrupt = nullptr); - void init (); + void init () override; }; class CGotoNestSched : public CBotSchedule @@ -639,7 +631,7 @@ class CGotoNestSched : public CBotSchedule // if iWaypoint is -1 it will find a random, suitable nest CGotoNestSched ( int iWaypoint ); - void init (); + void init () override; }; class CCrouchHideSched : public CBotSchedule @@ -649,7 +641,7 @@ class CCrouchHideSched : public CBotSchedule // if iWaypoint is -1 it will find a random, suitable nest CCrouchHideSched ( edict_t *pCoverFrom ); - void init (); + void init () override; }; class CDeployMachineGunSched : public CBotSchedule @@ -657,13 +649,74 @@ class CDeployMachineGunSched : public CBotSchedule public: // iWaypoint = the waypoint number the bot will go to (to nest) // if iWaypoint is -1 it will find a random, suitable nest - CDeployMachineGunSched ( CBotWeapon *pWeapon, CWaypoint *pWaypoint, Vector vEnemy ); + CDeployMachineGunSched ( CBotWeapon *pWeapon, CWaypoint *pWaypoint, const Vector& vEnemy ); - void init () + void init () override { setID(SCHED_DEPLOY_MACHINE_GUN); } }; +class CSynOpenDoorSched : public CBotSchedule +{ +public: + // pDoor - The door the bot will try to open + CSynOpenDoorSched( edict_t *pDoor ); + + void init() override + { + setID(SCHED_SYN_OPEN_DOOR); + } +}; + +class CSynDisarmMineSched : public CBotSchedule +{ +public: + // @param pMine The mine the bot will try to disarm + CSynDisarmMineSched( edict_t *pMine ); + + void init() override + { + setID(SCHED_SYN_DISARM_MINE); + } +}; + +class CSynBreakICrateSched : public CBotSchedule +{ +public: + /** + * Schedule to break an item_item_crate entity + * + * @param pCrate The crate to break + * @param pWeapon The weapon to use + **/ + CSynBreakICrateSched(edict_t* pCrate, CBotWeapon* pWeapon); + + void init() override + { + setID(SCHED_SYN_BREAK_ICRATE); + } +}; + +/******************************** + * Counter-Strike: Source * + ********************************/ + +class CCSSPlantBombSched : public CBotSchedule +{ +public: + /** + * Schedule for the bot to plant the C4 in CSS + * + * @param pWaypoint The waypoint where the c4 will be planted + * @param pRoute Route waypoint to use + **/ + CCSSPlantBombSched(CWaypoint *pWaypoint, CWaypoint *pRoute = nullptr); + + void init() override + { + setID(SCHED_PLANT_BOMB); + } +}; #endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_sigscan.cpp b/utils/RCBot2_meta/bot_sigscan.cpp index 229aec219..7b850af5c 100644 --- a/utils/RCBot2_meta/bot_sigscan.cpp +++ b/utils/RCBot2_meta/bot_sigscan.cpp @@ -1,12 +1,17 @@ -#ifdef WIN32 +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +#if defined(_WIN64) || defined(_WIN32) #include #else -#include "shake.h" //bir3yk +#include +//#define byte uint8_t + +//#include "shake.h" //bir3yk #include "elf.h" #define PAGE_SIZE 4096 -#define PAGE_ALIGN_UP(x) ((x + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) +#define PAGE_ALIGN_UP(x) (((x) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) #include #include @@ -20,44 +25,39 @@ #include "engine/iserverplugin.h" #include "tier2/tier2.h" #ifdef __linux__ -#include "shake.h" //bir3yk -#ifndef sscanf_s -#define sscanf_s sscanf -#endif +//#include "shake.h" //bir3yk #endif #include "eiface.h" #include "bot_const.h" #include "bot.h" +#include "bot_cvars.h" #include "bot_fortress.h" #include "bot_kv.h" #include "bot_getprop.h" #include "bot_sigscan.h" #include "bot_mods.h" -CGetEconItemSchema *g_pGetEconItemSchema = NULL; -CSetRuntimeAttributeValue *g_pSetRuntimeAttributeValue = NULL; -CGetAttributeDefinitionByName *g_pGetAttributeDefinitionByName = NULL; -CAttributeList_GetAttributeByID *g_pAttribList_GetAttributeByID = NULL; -CGameRulesObject *g_pGameRules_Obj = NULL; -CCreateGameRulesObject *g_pGameRules_Create_Obj = NULL; -CGetAttributeDefinitionByID *g_pGetAttributeDefinitionByID = NULL; +#include + +CGameRulesObject *g_pGameRules_Obj = nullptr; +CCreateGameRulesObject *g_pGameRules_Create_Obj = nullptr; -void **g_pGameRules = NULL; +void **g_pGameRules = nullptr; void *GetGameRules() { if (!g_pGameRules) - return NULL; + return nullptr; return *g_pGameRules; } -size_t CSignatureFunction::decodeHexString(unsigned char *buffer, size_t maxlength, const char *hexstr) +std::size_t CSignatureFunction::decodeHexString(unsigned char* buffer, const std::size_t maxlength, const char* hexstr) { - size_t written = 0; - size_t length = strlen(hexstr); + std::size_t written = 0; + const std::size_t length = std::strlen(hexstr); - for (size_t i = 0; i < length; i++) + for (std::size_t i = 0; i < length; i++) { if (written >= maxlength) break; @@ -68,15 +68,23 @@ size_t CSignatureFunction::decodeHexString(unsigned char *buffer, size_t maxleng continue; // Get the hex part. char s_byte[3]; - int r_byte; + unsigned r_byte; // Use unsigned here s_byte[0] = hexstr[i + 2]; s_byte[1] = hexstr[i + 3]; s_byte[2] = '\0'; // Read it as an integer - sscanf_s(s_byte, "%x", &r_byte); + std::sscanf(s_byte, "%x", &r_byte); + // Check if the value fits into a char + if (r_byte <= UCHAR_MAX) + { // Save the value - buffer[written - 1] = r_byte; + buffer[written - 1] = static_cast(r_byte); + } + else + { + // Handle the error + } // Adjust index i += 3; } @@ -87,34 +95,29 @@ size_t CSignatureFunction::decodeHexString(unsigned char *buffer, size_t maxleng bool CSignatureFunction::getLibraryInfo(const void *libPtr, DynLibInfo &lib) { - uintptr_t baseAddr; + std::uintptr_t baseAddr; - if (libPtr == NULL) + if (libPtr == nullptr) { return false; } -#ifdef _WIN32 - +#if defined(_WIN64) || defined(_WIN32) MEMORY_BASIC_INFORMATION info; - IMAGE_DOS_HEADER *dos; - IMAGE_NT_HEADERS *pe; - IMAGE_FILE_HEADER *file; - IMAGE_OPTIONAL_HEADER *opt; if (!VirtualQuery(libPtr, &info, sizeof(MEMORY_BASIC_INFORMATION))) { return false; } - baseAddr = reinterpret_cast(info.AllocationBase); + baseAddr = reinterpret_cast(info.AllocationBase); // All this is for our insane sanity checks :o - dos = reinterpret_cast(baseAddr); - pe = reinterpret_cast(baseAddr + dos->e_lfanew); - file = &pe->FileHeader; - opt = &pe->OptionalHeader; + const IMAGE_DOS_HEADER* dos = reinterpret_cast(baseAddr); + IMAGE_NT_HEADERS* pe = reinterpret_cast(baseAddr + static_cast(dos->e_lfanew)); + IMAGE_FILE_HEADER* file = &pe->FileHeader; + const IMAGE_OPTIONAL_HEADER* opt = &pe->OptionalHeader; // Check PE magic and signature if (dos->e_magic != IMAGE_DOS_SIGNATURE || pe->Signature != IMAGE_NT_SIGNATURE || opt->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) @@ -137,7 +140,7 @@ bool CSignatureFunction::getLibraryInfo(const void *libPtr, DynLibInfo &lib) } //Finally, we can do this - lib.memorySize = opt->SizeOfImage; + lib.memorySize = static_cast(opt->SizeOfImage); #else Dl_info info; @@ -156,7 +159,7 @@ bool CSignatureFunction::getLibraryInfo(const void *libPtr, DynLibInfo &lib) } // This is for our insane sanity checks :o - baseAddr = reinterpret_cast(info.dli_fbase); + baseAddr = reinterpret_cast(info.dli_fbase); file = reinterpret_cast(baseAddr); // Check ELF magic @@ -213,26 +216,24 @@ bool CSignatureFunction::getLibraryInfo(const void *libPtr, DynLibInfo &lib) return true; } -void *CSignatureFunction::findPattern(const void *libPtr, const char *pattern, size_t len) +void *CSignatureFunction::findPattern(const void *libPtr, const char *pattern, const std::size_t len) { DynLibInfo lib; - bool found; - char *ptr, *end; - memset(&lib, 0, sizeof(DynLibInfo)); + std::memset(&lib, 0, sizeof(DynLibInfo)); if (!getLibraryInfo(libPtr, lib)) { - return NULL; + return nullptr; } - ptr = reinterpret_cast(lib.baseAddress); - end = ptr + lib.memorySize - len; + char* ptr = static_cast(lib.baseAddress); + const char* end = ptr + lib.memorySize - len; while (ptr < end) { - found = true; - for (register size_t i = 0; i < len; i++) + bool found = true; + for (std::size_t i = 0; i < len; i++) { if (pattern[i] != '\x2A' && pattern[i] != ptr[i]) { @@ -247,379 +248,55 @@ void *CSignatureFunction::findPattern(const void *libPtr, const char *pattern, s ptr++; } - return NULL; + return nullptr; } // Sourcemod - Metamod - Allied Modders.net -void *CSignatureFunction::findSignature(void *addrInBase, const char *signature) +void *CSignatureFunction::findSignature(const void* addrInBase, const char* signature) { // First, preprocess the signature unsigned char real_sig[511]; - size_t real_bytes; - - real_bytes = decodeHexString(real_sig, sizeof(real_sig), signature); + const std::size_t real_bytes = decodeHexString(real_sig, sizeof real_sig, signature); if (real_bytes >= 1) { - return findPattern(addrInBase, (char*)real_sig, real_bytes); + return findPattern(addrInBase, reinterpret_cast(real_sig), real_bytes); } - return NULL; + return nullptr; } -void CSignatureFunction::findFunc(CRCBotKeyValueList *kv, const char*pKey, void *pAddrBase, const char *defaultsig) +void CSignatureFunction::findFunc(const CRCBotKeyValueList& kv, const char* pKey, const void* pAddrBase, const char* defaultsig) { - char *sig = NULL; + const char* sig = nullptr; - if (kv->getString(pKey, &sig) && sig) + if (kv.getString(pKey, &sig) && sig) m_func = findSignature(pAddrBase, sig); else m_func = findSignature(pAddrBase, defaultsig); } -CGameRulesObject::CGameRulesObject(CRCBotKeyValueList *list, void *pAddrBase) +CGameRulesObject::CGameRulesObject(CRCBotKeyValueList &list, void *pAddrBase) { -#ifdef _WIN32 - m_func = NULL; +#if defined(_WIN64) || defined(_WIN32) + m_func = nullptr; #else findFunc(list, "g_pGameRules", pAddrBase, "@g_pGameRules"); #endif } -CCreateGameRulesObject::CCreateGameRulesObject(CRCBotKeyValueList *list, void *pAddrBase) -{ -#ifdef _WIN32 - findFunc(list, "create_gamerules_object_win", pAddrBase, "\\x55\\x8B\\xEC\\x8B\\x0D\\x2A\\x2A\\x2A\\x2A\\x85\\xC9\\x74\\x07"); -#else - m_func = NULL; -#endif -} - -void **CCreateGameRulesObject::getGameRules() -{ - char *addr = reinterpret_cast(m_func); - extern ConVar rcbot_gamerules_offset; - - return *reinterpret_cast(addr + rcbot_gamerules_offset.GetInt()); -} - -CGetEconItemSchema::CGetEconItemSchema(CRCBotKeyValueList *list, void *pAddrBase) -{ -#ifdef _WIN32 - findFunc(list, "get_item_schema_win", pAddrBase, "\\xE8\\x2A\\x2A\\x2A\\x2A\\x83\\xC0\\x04\\xC3"); -#else - findFunc(list, "get_item_schema_linux", pAddrBase, "@_Z15GEconItemSchemav"); -#endif -} - -CEconItemSchema *CGetEconItemSchema::callme() -{ - void *thefunc = m_func; - CEconItemSchema *pret = NULL; - - if (thefunc == NULL) - return NULL; -#ifdef _WIN32 - __asm - { - call thefunc; - mov pret, eax; - }; -#else - FUNC_GET_ECON_ITEM_SCHEMA func = (FUNC_GET_ECON_ITEM_SCHEMA)thefunc; - - pret = func(); -#endif - return pret; -} - - - -CSetRuntimeAttributeValue::CSetRuntimeAttributeValue(CRCBotKeyValueList *list, void *pAddrBase) -{ -#ifdef _WIN32 - findFunc(list, "set_attribute_value_win", pAddrBase, "\\x55\\x8B\\xEC\\x83\\xEC\\x14\\x33\\xD2\\x53\\x8B\\xD9\\x56\\x57\\x8B\\x73\\x10\\x85\\xF6"); -#else - findFunc(list, "set_attribute_value_linux", pAddrBase, "@_ZN14CAttributeList24SetRuntimeAttributeValueEPK28CEconItemAttributeDefinitionf"); -#endif -} - -bool CSetRuntimeAttributeValue::callme(edict_t *pEnt, CAttributeList *list, CEconItemAttributeDefinition *attrib, float value) -{ - union { - int (CAttributeList::*SetRunTimeAttributeValue)(CEconItemAttributeDefinition*, float); - void* addr; - } u; - - int bret = 0; - void *thefunc = m_func; - - int iEntityIndex = ENTINDEX(pEnt); - - if (list && attrib && thefunc) - { - u.addr = m_func; - - bret = (reinterpret_cast(list)->*u.SetRunTimeAttributeValue)(attrib, value); - /* - #ifdef _WIN32 - __asm - { - mov ecx, list; - push attrib; - push value; - call thefunc; - mov bret, eax; - }; - #else - FUNC_SET_ATTRIB_VALUE func = (FUNC_SET_ATTRIB_VALUE)thefunc; - - bret = func(list,attrib,value); - #endif*/ - } - - return (bret == 1) || ((bret & 0x1FFF) == ((iEntityIndex + 4) * 4)); -} - - -CGetAttributeDefinitionByID::CGetAttributeDefinitionByID(CRCBotKeyValueList *list, void *pAddrBase) -{ -#ifdef _WIN32 - findFunc(list, "get_attrib_def_id_win", pAddrBase, "\\x55\\x8B\\xEC\\x83\\xEC\\x2A\\x53\\x56\\x8B\\xD9\\x8D\\x2A\\x2A\\x57"); -#else - findFunc(list, "get_attrib_def_id_linux", pAddrBase, "@_ZN15CEconItemSchema22GetAttributeDefinitionEi"); -#endif -} - -CEconItemAttributeDefinition *CGetAttributeDefinitionByID::callme(CEconItemSchema *schema, int id) +CCreateGameRulesObject::CCreateGameRulesObject(const CRCBotKeyValueList &list, const void *pAddrBase) { - void *pret = NULL; - - if (schema && m_func) - { - void *thefunc = m_func; -#ifdef _WIN32 - __asm - { - mov ecx, schema; - push id; - call thefunc; - mov pret, eax; - }; +#if defined(_WIN64) || defined(_WIN32) + findFunc(list, "create_gamerules_object_win", pAddrBase, R"(\x55\x8B\xEC\x8B\x0D\x2A\x2A\x2A\x2A\x85\xC9\x74\x07)"); #else - FUNC_GET_ATTRIB_BY_NAME func = (FUNC_GET_ATTRIB_BY_NAME)thefunc; - - pret = (void*)func(schema, id); -#endif - } - - return (CEconItemAttributeDefinition*)pret; -} - - -CGetAttributeDefinitionByName::CGetAttributeDefinitionByName(CRCBotKeyValueList *list, void *pAddrBase) -{ -#ifdef _WIN32 - findFunc(list, "get_attrib_definition_win", pAddrBase, "\\x55\\x8B\\xEC\\x83\\xEC\\x18\\x83\\x7D\\x08\\x00\\x53\\x56\\x57\\x8B\\xD9\\x75\\x2A\\x33\\xC0\\x5F"); -#else - findFunc(list, "get_attrib_definition_linux", pAddrBase, "@_ZN15CEconItemSchema28GetAttributeDefinitionByNameEPKc"); + m_func = nullptr; #endif } -CEconItemAttributeDefinition *CGetAttributeDefinitionByName::callme(CEconItemSchema *schema, const char *attrib) +void** CCreateGameRulesObject::getGameRules() const { - void *pret = NULL; - - if (schema && m_func) - { - void *thefunc = m_func; -#ifdef _WIN32 - __asm - { - mov ecx, schema; - push attrib; - call thefunc; - mov pret, eax; - }; -#else - FUNC_GET_ATTRIB_BY_NAME func = (FUNC_GET_ATTRIB_BY_NAME)thefunc; - - pret = (void*)func(schema, attrib); -#endif - } - - return (CEconItemAttributeDefinition*)pret; -} - - -CAttributeList_GetAttributeByID::CAttributeList_GetAttributeByID(CRCBotKeyValueList *list, void *pAddrBase) -{ -#ifdef _WIN32 - findFunc(list, "attributelist_get_attrib_by_id_win", pAddrBase, "\\x55\\x8B\\xEC\\x51\\x8B\\xC1\\x53\\x56\\x33\\xF6\\x89\\x45\\xFC\\x8B\\x58\\x10"); -#else - findFunc(list, "attributelist_get_attrib_by_id_linux", pAddrBase, "@_ZNK14CAttributeList16GetAttributeByIDEi"); -#endif -} - -CEconItemAttribute *CAttributeList_GetAttributeByID::callme(CAttributeList *list, int id) -{ - void *pret = NULL; - - if (list && m_func) - { - void *thefunc = m_func; -#ifdef _WIN32 - __asm - { - mov ecx, list; - push id; - call thefunc; - mov pret, eax; - }; -#else - FUNC_ATTRIBLIST_GET_ATTRIB_BY_ID func = (FUNC_ATTRIBLIST_GET_ATTRIB_BY_ID)thefunc; - - pret = (void*)func(list, id); -#endif - } - - return (CEconItemAttribute*)pret; -} - -// TF2 Attributes - Flamin Sarge -bool TF2_SetAttrib(edict_t *pedict, const char *strAttrib, float flVal) -{ - //CBaseEntity *pEntity; - - if (!pedict || pedict->IsFree()) - return false; - - CAttributeList *pList = CClassInterface::getAttributeList(pedict); - - CEconItemSchema *pSchema = g_pGetEconItemSchema->callme(); - - if (pSchema == NULL) - return false; - - int id = CAttributeLookup::findAttributeID(strAttrib); - - if (id == -1) - return false; - - CEconItemAttributeDefinition *pAttribDef = g_pGetAttributeDefinitionByID->callme(pSchema, id); - - if ((unsigned int)pAttribDef < 0x10000) - { - return false; - } - - bool bSuccess = g_pSetRuntimeAttributeValue->callme(pedict, pList, pAttribDef, flVal); - - //Just a note, the above SDKCall returns ((entindex + 4) * 4) | 0xA000), and you can AND it with 0x1FFF to get back the entindex if you want, though it's pointless) - //I don't know any other specifics, such as if the highest 3 bits actually matter - //And I don't know what happens when you hit ent index 2047 - // ClearAttributeCache(GetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity")); - // decl String:strClassname[64]; - // GetEntityClassname(entity, strClassname, sizeof(strClassname)); - // if (strncmp(strClassname, "tf_wea", 6, false) == 0 || StrEqual(strClassname, "tf_powerup_bottle", false)) - // { - // new client = GetEntPropEnt(entity, Prop_Send, "m_hOwnerEntity"); - // if (client > 0 && client <= MaxClients && IsClientInGame(client)) ClearAttributeCache(client); - // } - - return bSuccess; -} - -CEconItemAttribute *TF2Attrib_GetByName(edict_t *entity, const char *strAttrib) -{ - if (entity->IsFree()) - { - return NULL; - } - - CAttributeList *pList = CClassInterface::getAttributeList(entity); - - if (pList == NULL) - return NULL; - - if (*(int*)((unsigned long)pList + 4) == 0x0) - { - throw "Invalid Attribute List?"; - - return NULL; - } - - if (!g_pGetEconItemSchema) - return NULL; - - CEconItemSchema *pSchema = g_pGetEconItemSchema->callme(); - - if (pSchema == NULL) - return NULL; - CEconItemAttributeDefinition *pAttribDef = g_pGetAttributeDefinitionByName->callme(pSchema, strAttrib); - - if ((unsigned int)pAttribDef < 0x10000) - return NULL; - - unsigned short int iDefIndex = *(unsigned short int*)(((unsigned long)pAttribDef) + 4); - - CEconItemAttribute *pAttrib = g_pAttribList_GetAttributeByID->callme(pList, iDefIndex); - - if ((unsigned int)pAttrib < 0x10000) - pAttrib = NULL; - - return pAttrib; -} - -bool TF2_setAttribute(edict_t *pEdict, const char *szName, float flVal) -{ - // Creates the new Attribute - CEconItemAttribute *pAttrib = NULL; - - try - { - pAttrib = TF2Attrib_GetByName(pEdict, szName); - } - - catch (const char *str) - { - if (str && *str) - return false; - } - - if (((unsigned int)pAttrib) < 0x10000) - { - return TF2_SetAttrib(pEdict, szName, flVal); - } - else - pAttrib->m_flValue = flVal; - - return true; -} - -/* -CEconItemAttribute *UTIL_AttributeList_GetAttributeByID ( CAttributeList *list, int id ) -{ -void *pret = NULL; - -if ( list && AttributeList_GetAttributeByID ) -{ -#ifdef _WIN32 -__asm -{ -mov ecx, list; -push id; -call AttributeList_GetAttributeByID; -mov pret, eax; -}; -#else -FUNC_ATTRIBLIST_GET_ATTRIB_BY_ID func = (FUNC_ATTRIBLIST_GET_ATTRIB_BY_ID)AttributeList_GetAttributeByID; - -pret = (void*)func(list,id); -#endif -} - -return (CEconItemAttribute*)pret; + char* addr = static_cast(m_func); + return *reinterpret_cast(addr + static_cast(rcbot_gamerules_offset.GetInt())); } -*/ diff --git a/utils/RCBot2_meta/bot_sigscan.h b/utils/RCBot2_meta/bot_sigscan.h index 696b6406f..867e4ae4f 100644 --- a/utils/RCBot2_meta/bot_sigscan.h +++ b/utils/RCBot2_meta/bot_sigscan.h @@ -3,24 +3,10 @@ #include "bot_const.h" -/* From SOURCEMOD */ -class CAttributeList; -class CEconItemAttribute; -class CEconItemAttributeDefinition; -class CEconItemSchema; -class CEconWearable; - -typedef CEconItemAttribute* (*FUNC_ATTRIBLIST_GET_ATTRIB_BY_ID)(CAttributeList*,int); -typedef CEconItemSchema* (*FUNC_GET_ECON_ITEM_SCHEMA)(void); -typedef CEconItemAttributeDefinition* (*FUNC_GET_ATTRIB_BY_NAME)(CEconItemSchema*,const char*); -typedef int (*FUNC_SET_ATTRIB_VALUE)(CAttributeList*,const CEconItemAttributeDefinition*, float); - -void UTIL_ApplyAttribute ( edict_t *pEdict, const char *name, float fVal ); - struct DynLibInfo { void *baseAddress; - size_t memorySize; + std::size_t memorySize; }; class CRCBotKeyValueList; @@ -28,17 +14,17 @@ class CRCBotKeyValueList; class CSignatureFunction { public: - CSignatureFunction() { m_func = 0x0; } + CSignatureFunction() { m_func = nullptr; } private: - size_t decodeHexString(unsigned char *buffer, size_t maxlength, const char *hexstr); + static std::size_t decodeHexString(unsigned char *buffer, std::size_t maxlength, const char *hexstr); - bool getLibraryInfo(const void *libPtr, DynLibInfo &lib); + static bool getLibraryInfo(const void *libPtr, DynLibInfo &lib); - void *findPattern(const void *libPtr, const char *pattern, size_t len); + void *findPattern(const void *libPtr, const char *pattern, std::size_t len); - void *findSignature ( void *addrInBase, const char *signature ); + void *findSignature (const void* addrInBase, const char* signature); protected: - void findFunc ( CRCBotKeyValueList *kv, const char *pKey, void *pAddrBase, const char *defaultsig ); + void findFunc (const CRCBotKeyValueList& kv, const char* pKey, const void* pAddrBase, const char* defaultsig); void *m_func; }; @@ -46,99 +32,25 @@ class CSignatureFunction class CGameRulesObject : public CSignatureFunction { public: - CGameRulesObject(CRCBotKeyValueList *list, void *pAddrBase); + CGameRulesObject(CRCBotKeyValueList &list, void *pAddrBase); - bool found() { return m_func != NULL; } + bool found() const { return m_func != nullptr; } - void **getGameRules() { return reinterpret_cast(m_func); } + void **getGameRules() const { return static_cast(m_func); } }; class CCreateGameRulesObject : public CSignatureFunction { public: - CCreateGameRulesObject(CRCBotKeyValueList *list, void *pAddrBase); - - bool found() { return m_func != NULL; } - - void **getGameRules(); -}; - -class CGetEconItemSchema : public CSignatureFunction -{ -public: - CGetEconItemSchema ( CRCBotKeyValueList *list, void *pAddrBase ); - - CEconItemSchema *callme(); -}; - -class CSetRuntimeAttributeValue : public CSignatureFunction -{ -public: - CSetRuntimeAttributeValue ( CRCBotKeyValueList *list, void *pAddrBase ); - - bool callme(edict_t *pEnt, CAttributeList *list, CEconItemAttributeDefinition *attrib,float value); -}; - -class CGetAttributeDefinitionByID : public CSignatureFunction -{ -public: - CGetAttributeDefinitionByID(CRCBotKeyValueList *list, void *pAddrBase); + CCreateGameRulesObject(const CRCBotKeyValueList &list, const void *pAddrBase); - CEconItemAttributeDefinition *callme(CEconItemSchema *schema, int id); -}; - -class CGetAttributeDefinitionByName : public CSignatureFunction -{ -public: - CGetAttributeDefinitionByName ( CRCBotKeyValueList *list, void *pAddrBase ); + bool found() const { return m_func != nullptr; } - CEconItemAttributeDefinition *callme(CEconItemSchema *schema, const char *attrib); + void **getGameRules() const; }; -class CAttributeList_GetAttributeByID : public CSignatureFunction -{ -public: - CAttributeList_GetAttributeByID ( CRCBotKeyValueList *list, void *pAddrBase ); - - CEconItemAttribute *callme(CAttributeList *list, int id); -}; - -/* -CEconItemAttribute *UTIL_AttributeList_GetAttributeByID ( CAttributeList *list, int id ) -{ - void *pret = NULL; - - if ( list && AttributeList_GetAttributeByID ) - { -#ifdef _WIN32 - __asm - { - mov ecx, list; - push id; - call AttributeList_GetAttributeByID; - mov pret, eax; - }; -#else - FUNC_ATTRIBLIST_GET_ATTRIB_BY_ID func = (FUNC_ATTRIBLIST_GET_ATTRIB_BY_ID)AttributeList_GetAttributeByID; - - pret = (void*)func(list,id); -#endif - } - - return (CEconItemAttribute*)pret; -} -*/ - - -extern CGetEconItemSchema *g_pGetEconItemSchema; -extern CSetRuntimeAttributeValue *g_pSetRuntimeAttributeValue; -extern CGetAttributeDefinitionByName *g_pGetAttributeDefinitionByName; -extern CAttributeList_GetAttributeByID *g_pAttribList_GetAttributeByID; extern CGameRulesObject *g_pGameRules_Obj; extern CCreateGameRulesObject *g_pGameRules_Create_Obj; -extern CGetAttributeDefinitionByID *g_pGetAttributeDefinitionByID; void *GetGameRules(); - -bool TF2_setAttribute(edict_t *pEdict, const char *szName, float flVal); #endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_som.cpp b/utils/RCBot2_meta/bot_som.cpp index 8a18f6214..97702a510 100644 --- a/utils/RCBot2_meta/bot_som.cpp +++ b/utils/RCBot2_meta/bot_som.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -30,15 +32,15 @@ */ #ifdef __linux__ -#include -#include +#include +#include #endif #include "bot_som.h" #include "bot_mtrand.h" -float CSom :: m_fLearnRate = 1.0; +float CSom :: m_fLearnRate = 1.0f; -CSom :: CSom ( int iW, int iH, int iIn ) +CSom :: CSom (const int iW, const int iH, const int iIn) { unsigned short id = 0; @@ -46,12 +48,12 @@ CSom :: CSom ( int iW, int iH, int iIn ) m_iH = iH; // neighbourhood size - m_fNSize = (float)(int)((float)iW/2); + m_fNSize = static_cast(static_cast(static_cast(iW) / 2)); for ( int i = 0; i < iH; i ++ ) { for ( int j = 0; j < iW; j ++ ) - m_Neurons.push_back(new CSomNeuron(id++,iIn,j,i)); + m_Neurons.emplace_back(new CSomNeuron(id++,iIn,j,i)); } m_iEpochs = 0; @@ -62,19 +64,18 @@ CSom :: ~CSom () m_Neurons.clear(); } -CSomNeuron *CSom :: getBMU ( vector *inputs ) +CSomNeuron *CSom :: getBMU (const std::vector* inputs) const { - CSomNeuron *winner = NULL; + CSomNeuron *winner = nullptr; float bestdistance = 0; - float dist; - for ( unsigned int i = 0; i < m_Neurons.size(); i ++ ) - { - dist = m_Neurons[i]->distance(inputs); + for (CSomNeuron* const m_Neuron : m_Neurons) + { + const float dist = m_Neuron->distance(inputs); - if ( !winner || (dist < bestdistance) ) + if ( !winner || dist < bestdistance ) { - winner = m_Neurons[i]; + winner = m_Neuron; bestdistance = dist; } } @@ -82,63 +83,68 @@ CSomNeuron *CSom :: getBMU ( vector *inputs ) return winner; } - - -void CSom :: updateAround ( vector *inputs, CSomNeuron *bmu ) +void CSom :: updateAround (const std::vector* inputs, CSomNeuron* bmu) const { float dist; - float nsiz = (m_fNSize*m_fNSize); + const float nsiz = m_fNSize*m_fNSize; - for ( unsigned int i = 0; i < m_Neurons.size(); i ++ ) + for (const CSomNeuron* const current : m_Neurons) { - CSomNeuron *current = m_Neurons[i]; - if ( (dist = bmu->neighbourDistance(current)) <= nsiz ) { - bmu->update(inputs,exp(-(dist) / (2*nsiz))); + bmu->update(inputs,std::exp(-dist / (2*nsiz))); } } } -CSomNeuron *CSom :: inputOne ( vector *inputs ) +CSomNeuron *CSom :: inputOne (const std::vector *inputs) { CSomNeuron *winner = getBMU(inputs); updateAround(inputs,winner); - m_fNSize *= 0.75; - m_fLearnRate *= 0.75; + m_fNSize *= 0.75f; + m_fLearnRate *= 0.75f; m_iEpochs++; return winner; } -CSomNeuron *CSom :: input ( vector < vector > *inputs ) +void CSom::input(std::vector>* inputs, const int epochs)// Experimental [APG]RoboCop[CL] { - return inputOne(&((*inputs)[randomInt(0,(int)inputs->size()-1)])); + for (int i = 0; i < epochs; i++) + { + for (std::vector& input : *inputs) + { + inputOne(&input); + } + } +} + +CSomNeuron *CSom :: input (const std::vector < std::vector > *inputs) +{ + return inputOne(&(*inputs)[static_cast(randomInt(0, static_cast(inputs->size()) - 1))]); } -void CSom :: display () +void CSom :: display () const { //printf("\nDisplaying...\n"); - for ( unsigned int i = 0; i < m_Neurons.size(); i ++ ) + for (const CSomNeuron* m_Neuron : m_Neurons) { //printf("%d -- ",i); - m_Neurons[i]->displayWeights(); + m_Neuron->displayWeights(); //printf("\n"); } } -void CSomNeuron :: update ( vector *inputs, float inf ) +void CSomNeuron :: update (const std::vector* inputs, const float inf) { - float change; - - for ( unsigned int i = 0; i < inputs->size(); i ++ ) + for ( std::size_t i = 0; i < inputs->size(); i ++ ) { - change = ((*inputs)[i] - fWeights[i]); + const float change = (*inputs)[i] - fWeights[i]; - fWeights[i] += (change*CSom::m_fLearnRate*inf); + fWeights[i] += change*CSom::m_fLearnRate*inf; } } @@ -149,52 +155,53 @@ CSomNeuron :: ~CSomNeuron () CSomNeuron :: CSomNeuron () { + m_iX = 0; + m_iY = 0; m_iId = 0; return; } -CSomNeuron :: CSomNeuron ( unsigned short iId, int iInp, int iX, int iY ) +CSomNeuron :: CSomNeuron (const unsigned short iId, const int iInp, const int iX, const int iY) { - m_iX = (float)iX; - m_iY = (float)iY; + m_iX = static_cast(iX); + m_iY = static_cast(iY); m_iId = iId; - for ( int i = 0; i < iInp; i ++ ) - fWeights.push_back(randomFloat(0,1)); + for (int i = 0; i < iInp; i++) + fWeights.emplace_back(randomFloat(0,1)); } -float CSomNeuron :: distance ( vector *inputs ) +float CSomNeuron :: distance (const std::vector* inputs) const { float dist = 0; - float comp; - - for ( unsigned int i = 0; i < inputs->size(); i ++ ) + + for ( std::size_t i = 0; i < inputs->size(); i ++ ) { - comp = fWeights[i] - (*inputs)[i]; + const float comp = fWeights[i] - (*inputs)[i]; - dist += (comp*comp); + dist += comp*comp; } return dist; } -vector *CSomNeuron :: weights () +std::vector *CSomNeuron :: weights () { return &fWeights; } -void CSomNeuron :: displayWeights () +void CSomNeuron :: displayWeights () const { - for ( unsigned int i = 0; i < fWeights.size(); i ++ ) + for (const float fWeight : fWeights) { - printf("%0.4f,",fWeights[i]); + std::printf("%0.4f,", fWeight); } } -float CSomNeuron :: neighbourDistance ( CSomNeuron *other ) +float CSomNeuron :: neighbourDistance (const CSomNeuron *other) const { - float distx = getX()-other->getX(); - float disty = getY()-other->getY(); + const float distx = getX()-other->getX(); + const float disty = getY()-other->getY(); - return (distx*distx)+(disty*disty); + return distx*distx+disty*disty; } diff --git a/utils/RCBot2_meta/bot_som.h b/utils/RCBot2_meta/bot_som.h index ec41f6e3f..8dc16795f 100644 --- a/utils/RCBot2_meta/bot_som.h +++ b/utils/RCBot2_meta/bot_som.h @@ -31,10 +31,9 @@ #ifndef __RCBOT_SOM_H__ #define __RCBOT_SOM_H__ -#include +#include #include -using namespace std; class CSomNeuron { @@ -43,34 +42,34 @@ class CSomNeuron CSomNeuron (); - CSomNeuron ( unsigned short id, int iInp, int iX, int iY ); + CSomNeuron (unsigned short iId, int iInp, int iX, int iY); - inline float getX() + float getX() const { return m_iX; } - inline float getY() + float getY() const { return m_iY; } - void update ( vector *inputs, float inf ); + void update (const std::vector* inputs, float inf); - float distance ( vector *inputs ); + float distance (const std::vector* inputs) const; - vector *weights (); + std::vector *weights (); - void displayWeights (); + void displayWeights () const; - float neighbourDistance ( CSomNeuron *other ); + float neighbourDistance (const CSomNeuron *other) const; - inline void setClassID ( unsigned short iId ) { m_iId = iId; } + void setClassID (const unsigned short iId) { m_iId = iId; } - inline unsigned short getClassID () { return m_iId; } + unsigned short getClassID () const { return m_iId; } private: - vector fWeights; + std::vector fWeights; float m_iX; float m_iY; unsigned short m_iId; @@ -85,28 +84,28 @@ class CSom ~CSom (); - CSomNeuron *getBMU ( vector *inputs ); + CSomNeuron *getBMU (const std::vector* inputs) const; - void updateAround ( vector *inputs, CSomNeuron *bmu ); + void updateAround (const std::vector* inputs, CSomNeuron* bmu) const; - CSomNeuron *input ( vector < vector > *inputs ); + CSomNeuron *input (const std::vector < std::vector > *inputs); - CSomNeuron *inputOne ( vector < float > *inputs ); + CSomNeuron *inputOne (const std::vector < float > *inputs); - void input ( vector < vector > *inputs, int epochs ); + void input (std::vector < std::vector > *inputs, int epochs); - void display (); + void display () const; - inline unsigned int epochs () + unsigned epochs () const { return m_iEpochs; } private: - vector m_Neurons; + std::vector m_Neurons; int m_iH; int m_iW; float m_fNSize; - unsigned int m_iEpochs; + unsigned m_iEpochs; }; #endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_squads.cpp b/utils/RCBot2_meta/bot_squads.cpp index 0b4a5bb1c..2ba717432 100644 --- a/utils/RCBot2_meta/bot_squads.cpp +++ b/utils/RCBot2_meta/bot_squads.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -32,13 +34,17 @@ #include "vector.h" -#include "bot_const.h" #include "bot.h" +#include "bot_const.h" +#include "bot_getprop.h" #include "bot_globals.h" #include "bot_squads.h" -#include "bot_getprop.h" +#include "rcbot/logging.h" + +#include +#include -dataStack CBotSquads::m_theSquads; +std::deque CBotSquads::m_theSquads; class CRemoveBotFromSquad : public IBotFunction { @@ -49,7 +55,7 @@ class CRemoveBotFromSquad : public IBotFunction m_pSquad = pSquad; } - virtual void execute ( CBot *pBot ) + void execute ( CBot *pBot ) override { if ( pBot->inSquad(m_pSquad) ) pBot->clearSquad(); @@ -61,24 +67,16 @@ class CRemoveBotFromSquad : public IBotFunction //------------- -void CBotSquads::FreeMemory ( void ) +void CBotSquads::FreeMemory () { - CBotSquad *pSquad; - dataStack tempStack = m_theSquads; - - while ( !tempStack.IsEmpty() ) - { - pSquad = tempStack.ChooseFromStack(); - - if ( pSquad ) - delete pSquad; - pSquad = NULL; + // TODO inline squad or use unique pointers or something so they're freed automatically + for (const CBotSquad *squad : m_theSquads) { + delete squad; } - - m_theSquads.Destroy(); + m_theSquads.clear(); } -void CBotSquads::removeSquadMember ( CBotSquad *pSquad, edict_t *pMember ) +void CBotSquads::removeSquadMember (CBotSquad* pSquad, const edict_t* pMember) { pSquad->removeMember(pMember); @@ -88,21 +86,14 @@ void CBotSquads::removeSquadMember ( CBotSquad *pSquad, edict_t *pMember ) } } -edict_t *CBotSquad::getMember ( int iMember ) +edict_t *CBotSquad::getMember (const std::size_t iMember) { - int i = 0; - dataStack tempStack = m_theSquad; - edict_t *pPlayer; - - while ( !tempStack.IsEmpty() ) - { - pPlayer = tempStack.ChooseFromStack(); - - if ( i == iMember ) - return pPlayer; + // TODO: this is only used in CBotSquads::SquadJoin() -- inline the logic + if (iMember < 0 || iMember >= m_SquadMembers.size()) { + return nullptr; } - - return NULL; + + return m_SquadMembers[iMember]; } // AddSquadMember can have many effects @@ -114,17 +105,13 @@ edict_t *CBotSquad::getMember ( int iMember ) // make a new squad CBotSquad *CBotSquads::AddSquadMember ( edict_t *pLeader, edict_t *pMember ) { - dataStack tempStack = m_theSquads; - CBotSquad *theSquad; - CBot *pBot; - //char msg[120]; if ( !pLeader ) - return NULL; + return nullptr; if ( CClassInterface::getTeam(pLeader) != CClassInterface::getTeam(pMember) ) - return NULL; + return nullptr; //CClient *pClient = gBotGlobals.m_Clients.GetClientByEdict(pLeader); @@ -136,34 +123,23 @@ CBotSquad *CBotSquads::AddSquadMember ( edict_t *pLeader, edict_t *pMember ) //sprintf(msg,"%s %s has joined your squad",BOT_DBG_MSG_TAG,STRING(pMember->v.netname)); //ClientPrint(pLeader,HUD_PRINTTALK,msg); - while ( !tempStack.IsEmpty() ) - { - theSquad = tempStack.ChooseFromStack(); - - if ( theSquad->IsLeader(pLeader) ) - { - theSquad->AddMember(pMember); - tempStack.Init(); - return theSquad; - } - else if ( theSquad->IsMember(pLeader) ) - { - theSquad->AddMember(pMember); - tempStack.Init(); - return theSquad; + // member joins whatever squad the leader is in + for (CBotSquad *squad : m_theSquads) { + if (squad->IsLeader(pLeader) || squad->IsMember(pLeader)) { + squad->AddMember(pMember); + return squad; } } // no squad with leader, make one + CBotSquad *theSquad = new CBotSquad(pLeader, pMember); - theSquad = new CBotSquad(pLeader,pMember); - - if ( theSquad != NULL ) + CBot* pBot; + m_theSquads.emplace_back(theSquad); + + if ((pBot = CBots::getBotPointer(pLeader)) != nullptr) { - m_theSquads.Push(theSquad); - - if ( (pBot = CBots::getBotPointer(pLeader)) != NULL ) - pBot->setSquad(theSquad); + pBot->setSquad(theSquad); } return theSquad; @@ -173,108 +149,76 @@ CBotSquad *CBotSquads::AddSquadMember ( edict_t *pLeader, edict_t *pMember ) // CBotSquad *CBotSquads::SquadJoin ( edict_t *pLeader, edict_t *pMember ) { - dataStack tempStack = m_theSquads; - CBotSquad *theSquad; - CBotSquad *joinSquad; - //char msg[120]; if ( !pLeader ) - return NULL; + return nullptr; if ( CClassInterface::getTeam(pLeader) != CClassInterface::getTeam(pMember) ) - return NULL; + return nullptr; // no squad with leader, make pMember join SquadLeader - theSquad = FindSquadByLeader(pMember); + CBotSquad* theSquad = FindSquadByLeader(pMember); - if ( theSquad != NULL ) + if ( theSquad != nullptr) { theSquad->AddMember(pMember); - joinSquad = FindSquadByLeader(pLeader); - - if ( joinSquad ) + if ( CBotSquad* joinSquad = FindSquadByLeader(pLeader) ) { - for ( int i = 0; i < joinSquad->numMembers(); i ++ ) + // TODO make this a friend class so we could just join the squads directly? + for ( unsigned i = 0; i < joinSquad->numMembers(); i ++ ) { - theSquad->AddMember(joinSquad->getMember(i)); + theSquad->AddMember(joinSquad->getMember(i)); } RemoveSquad(joinSquad); } else - return NULL; + return nullptr; } // no squad with leader, make pMember join SquadLeader theSquad = FindSquadByLeader(pLeader); - if ( theSquad != NULL ) + if ( theSquad != nullptr) theSquad->AddMember(pMember); return theSquad; } -CBotSquad *CBotSquads::FindSquadByLeader ( edict_t *pLeader ) +CBotSquad *CBotSquads::FindSquadByLeader (const edict_t *pLeader) { - CBotSquad *pSquad; - dataStack tempStack = m_theSquads; - - while ( !tempStack.IsEmpty() ) - { - pSquad = tempStack.ChooseFromStack(); - - if ( pSquad->IsLeader(pLeader) ) - { - tempStack.Init(); - return pSquad; + for (CBotSquad *squad : m_theSquads) { + if (squad->IsLeader(pLeader)) { + return squad; } } - - return NULL; + return nullptr; } void CBotSquads::RemoveSquad ( CBotSquad *pSquad ) { - CRemoveBotFromSquad *func = new CRemoveBotFromSquad(pSquad); - CBots::botFunction(func); - delete func; - - m_theSquads.Remove(pSquad); + // TODO see if we can modify this so the squad unregisters itself + // TODO call this logic in CBotSquad::~CBotSquad() instead + CRemoveBotFromSquad func(pSquad); + CBots::botFunction(&func); - if ( pSquad != NULL ) - delete pSquad; + m_theSquads.erase(std::remove(m_theSquads.begin(), m_theSquads.end(), pSquad), m_theSquads.end()); + + delete pSquad; } -void CBotSquads::UpdateAngles ( void ) +void CBotSquads::UpdateAngles () { - CBotSquad *pSquad; - dataStack tempStack = m_theSquads; - - pSquad = NULL; - - while ( !tempStack.IsEmpty() ) - { - try - { - pSquad = tempStack.ChooseFromStack(); - pSquad->UpdateAngles(); - } - - catch ( ... ) - { - // Arghhhhh - - m_theSquads.Remove(pSquad); - tempStack = m_theSquads; - } + for (CBotSquad *squad : m_theSquads) { + squad->UpdateAngles(); } } //------------- -void CBotSquad::UpdateAngles ( void ) +void CBotSquad::UpdateAngles () { edict_t *pLeader = GetLeader(); @@ -299,7 +243,7 @@ void CBotSquad::Init () bCanFire = true; - if ( (pLeader = GetLeader()) != NULL ) + if ( (pLeader = GetLeader()) != nullptr) { IPlayerInfo *p = playerinfomanager->GetPlayerInfo(pLeader); m_vLeaderAngle = p->GetLastUserCommand().viewangles; @@ -307,35 +251,39 @@ void CBotSquad::Init () } // Change a leader of a squad, this can cause lots of effects -void CBotSquads :: ChangeLeader ( CBotSquad *theSquad ) +void CBotSquads :: ChangeLeader ( CBotSquad *pSquad ) { // first change leader to next squad member - theSquad->ChangeLeader(); + pSquad->ChangeLeader(); // if no leader anymore/no members in group - if ( theSquad->IsLeader(NULL) ) + if ( pSquad->IsLeader(nullptr) ) { - CRemoveBotFromSquad *func = new CRemoveBotFromSquad(theSquad); - - CBots::botFunction(func); - - // must also remove from stack of available squads. - m_theSquads.Remove(theSquad); + CRemoveBotFromSquad func(pSquad); + CBots::botFunction(&func); + + // must also remove from available squads. + m_theSquads.erase(std::remove(m_theSquads.begin(), m_theSquads.end(), pSquad), m_theSquads.end()); } } -void CBotSquad::ChangeLeader ( void ) +/** + * Make the succeeding squad member the new leader if they have any subordinates, otherwise + * disband the squad. + */ +void CBotSquad::ChangeLeader () { - if ( m_theSquad.IsEmpty() ) + if ( m_SquadMembers.empty() ) { - SetLeader(NULL); + SetLeader(nullptr); } else { - m_pLeader = m_theSquad.Pop(); + m_pLeader = m_SquadMembers.front(); + m_SquadMembers.pop_front(); - if ( m_theSquad.IsEmpty() ) - SetLeader(NULL); + if ( m_SquadMembers.empty() ) + SetLeader(nullptr); else { Init(); // new squad init @@ -343,30 +291,32 @@ void CBotSquad::ChangeLeader ( void ) } } -Vector CBotSquad :: GetFormationVector ( edict_t *pEdict ) +Vector CBotSquad :: GetFormationVector (const edict_t* pEdict) { - Vector vLeaderOrigin; - Vector vBase; + Vector vBase; Vector v_forward; Vector v_right; - QAngle angle_right; - // vBase = first : offset from leader origin without taking into consideration spread and position - int iPosition; - trace_t *tr = CBotGlobals::getTraceResult(); + const trace_t *tr = CBotGlobals::getTraceResult(); edict_t *pLeader = GetLeader(); - - iPosition = GetFormationPosition(pEdict); - vLeaderOrigin = CBotGlobals::entityOrigin(pLeader); - int iMod = iPosition % 2; + if (!pLeader || pLeader->IsFree() || pLeader->GetIServerEntity() == nullptr) + { + logger->Log(LogLevel::DEBUG, "Trying to get squad formation vector with a NULL squad leader! Alert a programmer! edict_t *pLeader == %p", pLeader); + return vec3_origin; + } + + const int iPosition = GetFormationPosition(pEdict); + const Vector vLeaderOrigin = CBotGlobals::entityOrigin(pLeader); + + const int iMod = iPosition % 2; AngleVectors(m_vLeaderAngle,&v_forward); // leader body angles as base - angle_right = m_vLeaderAngle; + QAngle angle_right = m_vLeaderAngle; angle_right.y += 90.0f; - CBotGlobals::fixFloatAngle(&(angle_right.y)); + CBotGlobals::fixFloatAngle(&angle_right.y); AngleVectors(angle_right,&v_right); // leader body angles as base @@ -376,9 +326,9 @@ Vector CBotSquad :: GetFormationVector ( edict_t *pEdict ) case SQUAD_FORM_VEE: { if ( iMod ) - vBase = (v_forward-v_right); + vBase = v_forward-v_right; else - vBase = (v_forward+v_right); + vBase = v_forward+v_right; } break; case SQUAD_FORM_WEDGE: @@ -415,58 +365,36 @@ Vector CBotSquad :: GetFormationVector ( edict_t *pEdict ) vBase = -v_forward + v_right; } break; + //case SQUAD_FORM_NONE: + // break; } - vBase = (vBase * m_fDesiredSpread) * iPosition; + vBase = vBase * static_cast(m_fDesiredSpread) * iPosition; CBotGlobals::quickTraceline(pLeader,vLeaderOrigin,vLeaderOrigin+vBase); - if ( tr->fraction < 1.0 ) + if ( tr->fraction < 1.0f ) { - return vLeaderOrigin + (vBase*tr->fraction*0.5f); + return vLeaderOrigin + vBase * tr->fraction * 0.5f; } return vLeaderOrigin+vBase; } -int CBotSquad::GetFormationPosition ( edict_t *pEdict ) +/** + * Returns the edict's position in the squad. + */ +int CBotSquad::GetFormationPosition(const edict_t* pEdict) { - int iPosition = 0; - - dataStack tempStack = m_theSquad; - - while ( !tempStack.IsEmpty() ) - { - iPosition++; - - if ( pEdict == tempStack.ChooseFromStack().get() ) - { - /// !! musssst init - tempStack.Init(); - return iPosition; - } - } - - return 0; + const auto it = std::find(m_SquadMembers.begin(), m_SquadMembers.end(), pEdict); + return it != m_SquadMembers.end() ? std::distance(m_SquadMembers.begin(), it) : 0; } -void CBotSquad::removeMember ( edict_t *pMember ) +void CBotSquad::removeMember(const edict_t* pMember) { - dataStack tempStack; - MyEHandle *temp; - - tempStack = m_theSquad; - - while ( !tempStack.IsEmpty() ) - { - temp = tempStack.ChoosePointerFromStack(); - - if ( temp->get() == pMember ) - { - m_theSquad.RemoveByPointer(temp); - tempStack.Init(); - return; - } + const auto it = std::find(m_SquadMembers.begin(), m_SquadMembers.end(), pMember); + if (it != m_SquadMembers.end()) { + m_SquadMembers.erase(it); } } @@ -474,12 +402,11 @@ void CBotSquad::AddMember ( edict_t *pEdict ) { if ( !IsMember(pEdict) ) { - MyEHandle newh; //CBot *pBot; - newh = pEdict; + const MyEHandle newh = pEdict; - m_theSquad.Push(newh); + m_SquadMembers.emplace_back(newh); /*if ( (pBot=CBots::getBotPointer(pEdict))!=NULL ) { @@ -489,63 +416,25 @@ void CBotSquad::AddMember ( edict_t *pEdict ) } } -int CBotSquad::numMembers () +std::size_t CBotSquad::numMembers() const { - dataStack tempStack; - int num = 0; - - tempStack = m_theSquad; - - while ( !tempStack.IsEmpty() ) - { - tempStack.ChooseFromStack(); - - num++; - } - - return num; + return m_SquadMembers.size(); } -void CBotSquad :: ReturnAllToFormation ( void ) +void CBotSquad :: ReturnAllToFormation () { - dataStack tempStack = this->m_theSquad; - edict_t *pMember; - CBot *pBot; - - while ( !tempStack.IsEmpty() ) - { - pMember = tempStack.ChooseFromStack().get(); - - pBot = CBots::getBotPointer(pMember); - - if ( pBot ) - { + for (const edict_t *member : m_SquadMembers) { + if (CBot *pBot = CBots::getBotPointer(member)) { pBot->removeCondition(CONDITION_PUSH); pBot->removeCondition(CONDITION_COVERT); pBot->updateCondition(CONDITION_CHANGED); pBot->setSquadIdleTime(0.0f); } - } + } } -bool CBotSquad::IsMember ( edict_t *pEdict ) +bool CBotSquad::IsMember (const edict_t* pEdict) { - dataStack tempStack; - MyEHandle temp; - - tempStack = m_theSquad; - - while ( !tempStack.IsEmpty() ) - { - temp = tempStack.ChooseFromStack(); - - if ( temp.get() == pEdict ) - { - tempStack.Init(); - return true; - } - } - - return false; + return std::find(m_SquadMembers.begin(), m_SquadMembers.end(), pEdict) + != m_SquadMembers.end(); } - diff --git a/utils/RCBot2_meta/bot_squads.h b/utils/RCBot2_meta/bot_squads.h index aeda0737b..8d8b4633a 100644 --- a/utils/RCBot2_meta/bot_squads.h +++ b/utils/RCBot2_meta/bot_squads.h @@ -32,12 +32,11 @@ #define __RCBOT_SQUADS_H__ #include "vector.h" -#include "bot_genclass.h" #include "bot_ehandle.h" -#define SQUAD_DEFAULT_SPREAD 80.0// say 50 units between each member...? +constexpr float SQUAD_DEFAULT_SPREAD = 80.0f;// say 50 units between each member...?; -typedef enum eSquadForm +enum eSquadForm : std::uint8_t { SQUAD_FORM_NONE = 0, SQUAD_FORM_WEDGE, @@ -48,7 +47,7 @@ typedef enum eSquadForm SQUAD_FORM_VEE }; -typedef enum eCombatType +enum eCombatType : std::uint8_t { COMBAT_NONE = 0, COMBAT_STEALTH, @@ -57,7 +56,7 @@ typedef enum eCombatType COMBAT_PRONE }; -typedef enum eTacticType +enum eTacticType : std::uint8_t { TACTIC_FREE = 0, TACTIC_IDLE, @@ -69,7 +68,8 @@ class CBotSquad { public: - CBotSquad ( edict_t *pLeader, edict_t *pMember ) + CBotSquad(edict_t* pLeader, edict_t* pMember) + : m_fDesiredSpread(0.0f), bCanFire(false), m_CombatType(COMBAT_NONE), m_bIsWaitingForOther(false) // Initialize with a default value { SetLeader(pLeader); AddMember(pMember); @@ -77,23 +77,21 @@ class CBotSquad Init(); } - ~CBotSquad() - { - m_theSquad.Destroy(); - } + + ~CBotSquad() = default; void Init (); - void ReturnAllToFormation ( void ); + void ReturnAllToFormation (); - inline void SetLeader ( edict_t *pLeader ) + void SetLeader ( edict_t *pLeader ) { m_pLeader = pLeader; } - edict_t *getMember ( int iMember ); + edict_t *getMember (std::size_t iMember); - void ToggleFireMode ( void ) + void ToggleFireMode () { bCanFire = !bCanFire; @@ -103,34 +101,47 @@ class CBotSquad BotPrintTalkMessageOne(m_pLeader.Get(),"Squad is now HOLDING FIRE");*/ } - inline bool SquadCanShoot ( void ) + bool SquadCanShoot () const { return bCanFire; } - inline bool IsStealthMode ( void ) + bool IsStealthMode () const + { + return m_CombatType == COMBAT_STEALTH; + } + + bool IsProneMode () const { - return (m_CombatType == COMBAT_STEALTH); + return m_CombatType == COMBAT_PRONE; } - inline bool IsProneMode ( void ) + bool IsCrouchMode () const { - return (m_CombatType == COMBAT_PRONE); + return m_CombatType == COMBAT_CROUCH; } - inline bool IsCrouchMode ( void ) + // Returns true if the squad leader entity is valid. False if not. -caxanga334 + bool IsSquadLeaderValid() { - return (m_CombatType == COMBAT_CROUCH); + edict_t* pLeader = m_pLeader.get(); + + if (!pLeader || pLeader->IsFree() || pLeader->GetIServerEntity() == nullptr) + { + return false; + } + + return true; } - inline edict_t *GetLeader ( void ) + edict_t *GetLeader () { - return (edict_t*)m_pLeader.get(); + return m_pLeader.get(); } - void SetCombatType ( eCombatType iCombatType ) + void SetCombatType (const eCombatType iCombatType) { - edict_t *pLeader = GetLeader(); + const edict_t *pLeader = GetLeader(); m_CombatType = iCombatType; @@ -148,66 +159,66 @@ class CBotSquad break; case COMBAT_PRONE: strcpy(szCombatType,"PRONE"); - break; - case COMBAT_CROUCH: - strcpy(szCombatType,"CROUCH"); - break; + break; + case COMBAT_CROUCH: + strcpy(szCombatType,"CROUCH"); + break; case COMBAT_NONE: case COMBAT_COMBAT: strcpy(szCombatType,"NORMAL"); break; - } + } //BotPrintTalkMessageOne ( pLeader, "Combat mode is now %s\n", szCombatType ); } - void ChangeLeader ( void ); + void ChangeLeader (); - void removeMember ( edict_t *pMember ); + void removeMember (const edict_t* pMember); - inline bool IsLeader ( edict_t *pLeader ) + bool IsLeader (const edict_t *pLeader) { - return (GetLeader() == pLeader); + return GetLeader() == pLeader; } void AddMember ( edict_t *pEdict ); - int numMembers (); + std::size_t numMembers() const; - bool IsMember ( edict_t *pEdict ); + bool IsMember (const edict_t* pEdict); - inline bool isFormation (eSquadForm theFormation) + bool isFormation (const eSquadForm theFormation) const { return m_theDesiredFormation == theFormation; } - inline void ChangeFormation ( eSquadForm theNewFormation ) + void ChangeFormation (const eSquadForm theNewFormation) { m_theDesiredFormation = theNewFormation; } - inline float GetSpread ( void ) const + float GetSpread () const { return m_fDesiredSpread; } - inline void ChangeSpread ( float fNewSpread ) + void ChangeSpread (const float fNewSpread) { m_fDesiredSpread = fNewSpread; } - int GetFormationPosition ( edict_t *pEdict ); + int GetFormationPosition (const edict_t* pEdict); - Vector GetFormationVector ( edict_t *pEdict ); + Vector GetFormationVector (const edict_t* pEdict); - void UpdateAngles ( void ); + void UpdateAngles (); - bool isDefensive () { return m_Tactics == TACTIC_DEFEND; } + bool isDefensive () const { return m_Tactics == TACTIC_DEFEND; } - void setTactic ( eTacticType iTactics ) { m_Tactics = iTactics; } + void setTactic (const eTacticType iTactics) { m_Tactics = iTactics; } // Squad is waiting for another squad to Syncronize - bool isWaitingForOtherSquad () + bool isWaitingForOtherSquad () const { return m_bIsWaitingForOther; } @@ -222,7 +233,7 @@ class CBotSquad // use 'EHandles' for squads // as players might leave and stuff... MyEHandle m_pLeader; - dataStack m_theSquad; + std::deque m_SquadMembers; // followers? eSquadForm m_theDesiredFormation; float m_fDesiredSpread; @@ -241,9 +252,9 @@ class CBotSquads { public: - static void FreeMemory ( void ); + static void FreeMemory (); - static void removeSquadMember ( CBotSquad *pSquad, edict_t *pMember ); + static void removeSquadMember (CBotSquad* pSquad, const edict_t* pMember); // AddSquadMember can have many effects // 1. scenario: squad leader exists as squad leader @@ -256,16 +267,16 @@ class CBotSquads static CBotSquad *SquadJoin ( edict_t *pLeader, edict_t *pMember ); - static CBotSquad *FindSquadByLeader ( edict_t *pLeader ); + static CBotSquad *FindSquadByLeader (const edict_t *pLeader ); static void RemoveSquad ( CBotSquad *pSquad ); - static void UpdateAngles ( void ); + static void UpdateAngles (); - static void ChangeLeader ( CBotSquad *theSquad ); + static void ChangeLeader ( CBotSquad *pSquad ); private: - static dataStack m_theSquads; + static std::deque m_theSquads; }; /* class CBotSquadE diff --git a/utils/RCBot2_meta/bot_strings.cpp b/utils/RCBot2_meta/bot_strings.cpp index c251df7eb..af9e376ba 100644 --- a/utils/RCBot2_meta/bot_strings.cpp +++ b/utils/RCBot2_meta/bot_strings.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -28,71 +30,70 @@ * version. * */ -#include -#include +#include +#include #include "bot.h" #include "bot_strings.h" #include //bir3yk -vector CStrings::m_Strings[MAX_STRINGS_HASH]; +std::vector CStrings::m_Strings[MAX_STRINGS_HASH]; -CStrings :: CStrings () +CStrings::CStrings() { return; } -void CStrings :: freeAllMemory() +void CStrings::freeAllMemory() { - char *pszFree; - // clear strings - for ( int i = 0; i < MAX_STRINGS_HASH; i ++ ) + for (std::vector& m_String : m_Strings) { - for ( unsigned int j = 0; j < m_Strings[i].size(); j ++ ) + for (char*& j : m_String) { - pszFree = m_Strings[i][j]; - - if ( pszFree ) - delete pszFree; + delete[] j; - m_Strings[i][j] = NULL; + j = nullptr; } - m_Strings[i].clear(); + m_String.clear(); } } // Either : 1 . Return the existing string or 2 . make a new string and return it. -char *CStrings :: getString ( const char *szString ) +char* CStrings::getString(const char* szString) { - if ( szString == NULL ) - return NULL; + if (szString == nullptr) + return nullptr; + + // Ensure MAX_STRINGS_HASH is large enough or validate the index - [APG]RoboCop[CL] + const unsigned short iHash = szString[0] % MAX_STRINGS_HASH; - unsigned short int iHash = szString[0]%MAX_STRINGS_HASH; - - for ( register unsigned short int i = 0; i < m_Strings[iHash].size(); i ++ ) + // Validate that iHash is within bounds + if (iHash >= MAX_STRINGS_HASH) { - char *szCompString = m_Strings[iHash][i]; + // Handle error appropriately (e.g., log, throw exception, etc.) - [APG]RoboCop[CL] + return nullptr; + } + for (char* const szCompString : m_Strings[iHash]) + { // check if pointers match first - if ( szCompString == szString ) + if (szCompString == szString) return szCompString; // if not do a full string comparison - if ( FStrEq(szString,szCompString) ) + if (FStrEq(szString, szCompString)) return szCompString; } - unsigned int len = strlen(szString); - - char *szNew = new char[len+1]; + const std::size_t len = std::strlen(szString); - strcpy(szNew,szString); + char* szNew = new char[len + 1]; - szNew[len] = 0; + std::strcpy(szNew, szString); - m_Strings[iHash].push_back(szNew); + m_Strings[iHash].emplace_back(szNew); - return szNew; + return szNew; } \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_strings.h b/utils/RCBot2_meta/bot_strings.h index 811dc9811..2517ae4a6 100644 --- a/utils/RCBot2_meta/bot_strings.h +++ b/utils/RCBot2_meta/bot_strings.h @@ -32,9 +32,11 @@ #define __BOT_STRINGS_H__ #include -using namespace std; -#define MAX_STRINGS_HASH 26 +enum : std::uint8_t +{ + MAX_STRINGS_HASH = 26 +}; /* * CStrings @@ -53,14 +55,14 @@ using namespace std; class CStrings { public: - CStrings (); + CStrings(); static void freeAllMemory(); - static char *getString ( const char *szString ); + static char* getString(const char* szString); private: // dataStack is like a linked list, dont want // to use an array for lots of stuff like this - static vector m_Strings[MAX_STRINGS_HASH]; + static std::vector m_Strings[MAX_STRINGS_HASH]; }; #endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_synergy.cpp b/utils/RCBot2_meta/bot_synergy.cpp new file mode 100644 index 000000000..b2e6bebf3 --- /dev/null +++ b/utils/RCBot2_meta/bot_synergy.cpp @@ -0,0 +1,976 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +/* + * This file is part of RCBot. + * + * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. + * + * RCBot is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * RCBot is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RCBot; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + */ +#include "engine_wrappers.h" + +#include "bot.h" +#include "bot_cvars.h" +#include "ndebugoverlay.h" +#include "bot_squads.h" +#include "bot_synergy.h" +#include "in_buttons.h" +#include "bot_buttons.h" +#include "bot_globals.h" +#include "bot_profile.h" +#include "bot_getprop.h" +#include "bot_mtrand.h" +#include "bot_mods.h" +#include "bot_task.h" +#include "bot_schedule.h" +#include "bot_weapons.h" +#include "bot_waypoint.h" +#include "bot_waypoint_locations.h" +#include "bot_navigator.h" +#include "bot_perceptron.h" +#include "bot_plugin_meta.h" +#include "bot_waypoint_visibility.h" + +#include + +extern IVDebugOverlay* debugoverlay; +extern IServerGameEnts* servergameents; // for accessing the server game entities + +void CBotSynergy::init(const bool bVarInit) +{ + CBot::init(bVarInit); // call base first + m_fFov = 110.0f; // Coop mod, give bot larger FOV (default is 75) +} + +void CBotSynergy::spawnInit() +{ + CBot::spawnInit(); + + if (m_pWeapons) // reset weapons + m_pWeapons->clearWeapons(); + + m_CurrentUtil = BOT_UTIL_MAX; + m_pNearbyAmmo = nullptr; + m_pNearbyBattery = nullptr; + m_pNearbyCrate = nullptr; + m_pNearbyHealthKit = nullptr; + m_pNearbyWeapon = nullptr; + m_pNearbyMine = nullptr; + m_pNearbyGrenade = nullptr; + m_pNearbyItemCrate = nullptr; + m_pCurrentWeapon = nullptr; + m_flNextSprintTime = engine->Time(); + m_flSuitPower = 0.0f; + m_flUseCrateTime = engine->Time(); + m_flPickUpTime = engine->Time(); +} + +void CBotSynergy::died(edict_t* pKiller, const char* pszWeapon) +{ + CBot::died(pKiller, pszWeapon); + + if (pKiller) + { + if (CBotGlobals::entityIsValid(pKiller)) + { + m_pNavigator->belief(CBotGlobals::entityOrigin(pKiller), getEyePosition(), bot_beliefmulti.GetFloat(), distanceFrom(pKiller), BELIEF_DANGER); + } + } +} + +/** + * Determines if the bot needs health + * + * @return True if the bot needs health + **/ +bool CBotSynergy::needHealth() +{ + return getHealthPercent() <= 0.7f; +} + +/** + * Determines if the bot needs ammo + * + * @return True if the bot needs ammo + **/ +bool CBotSynergy::needAmmo() +{ + if (m_pCurrentWeapon == nullptr) + { + return false; + } + + if (const CBotWeapon* weapon = m_pWeapons->getWeapon(CWeapons::getWeapon(m_pCurrentWeapon->GetClassName()))) + { + const int iAmmo = weapon->getAmmo(this); // Current weapon reserve ammo + + switch (weapon->getID()) + { + case SYN_WEAPON_PISTOL: + { + return iAmmo < 30; + //break; + } + case SYN_WEAPON_SHOTGUN: + case SYN_WEAPON_DESERTEAGLE: + case SYN_WEAPON_357: + { + return iAmmo < 6; + //break; + } + case SYN_WEAPON_SMG1: + case SYN_WEAPON_MP5K: + { + return iAmmo < 75; + //break; + } + case SYN_WEAPON_AR2: + case SYN_WEAPON_MG1: + { + return iAmmo < 20; + //break; + } + case SYN_WEAPON_CROSSBOW: + { + return iAmmo < 2; + //break; + } + case SYN_WEAPON_RPG: + { + return iAmmo < 2; + //break; + } + + default: + { + return false; + //break; + } + } //Not required? [APG]RoboCop[CL] + } + + return false; +} + +void CBotSynergy::modThink() +{ + m_fIdealMoveSpeed = CClassInterface::getMaxSpeed(m_pEdict); + m_pCurrentWeapon = CClassInterface::getCurrentWeapon(m_pEdict); + m_flSuitPower = CClassInterface::getSynPlayerSuitPower(m_pEdict); + + if (needHealth()) + updateCondition(CONDITION_NEED_HEALTH); + else + removeCondition(CONDITION_NEED_HEALTH); + + if (needAmmo()) + updateCondition(CONDITION_NEED_AMMO); + else + removeCondition(CONDITION_NEED_AMMO); + + if (onLadder()) + { + setMoveLookPriority(MOVELOOK_OVERRIDE); + setLookAtTask(LOOK_WAYPOINT); + m_pButtons->holdButton(IN_FORWARD, 0, 1, 0); + setMoveLookPriority(MOVELOOK_MODTHINK); + } + + if (m_pNearbyGrenade && distanceFrom(m_pNearbyGrenade.get()) <= 200.0f) // Nearby grenade, RUN for cover! + { + updateCondition(CONDITION_RUN); + if (!m_pSchedules->isCurrentSchedule(SCHED_GOOD_HIDE_SPOT)) + { + m_pSchedules->removeSchedule(SCHED_GOOD_HIDE_SPOT); + m_pSchedules->addFront(new CGotoHideSpotSched(this, m_pNearbyGrenade, false)); // bIsGrenade is false because when true the bot will do a DoD specific task + debugMsg(BOT_DEBUG_THINK, "[MOD THINK] Taking cover from grenade"); + } + } + + if (m_pNearbyMine && distanceFrom(m_pNearbyMine.get()) <= 512.0f && !CSynergyMod::IsCombineMineDisarmed(m_pNearbyMine.get())) + { + if (CSynergyMod::IsCombineMinePlayerPlaced(m_pNearbyMine.get())) + { + m_pNearbyMine = nullptr; // The mine is friendly now. + } + else + { + if (m_pWeapons->hasWeapon(SYN_WEAPON_PHYSCANNON) && !CSynergyMod::IsCombineMineHeldByPhysgun(m_pNearbyMine.get())) + { + if (!m_pSchedules->isCurrentSchedule(SCHED_SYN_DISARM_MINE)) + { + m_pSchedules->removeSchedule(SCHED_SYN_DISARM_MINE); + m_pSchedules->addFront(new CSynDisarmMineSched(m_pNearbyMine.get())); + debugMsg(BOT_DEBUG_THINK, "[MOD THINK] Disarming combine mine"); + } + } + else + { + m_pNavigator->belief(CBotGlobals::entityOrigin(m_pNearbyMine.get()), getEyePosition(), MAX_BELIEF, distanceFrom(m_pNearbyMine.get()), BELIEF_DANGER); + } + } + } + + // Pick nearby weapons that the bot doesn't already have + if (m_pNearbyWeapon && distanceFrom(m_pNearbyWeapon.get()) <= 400.0f && m_flPickUpTime <= engine->Time()) + { + const edict_t* pOwner = CClassInterface::getOwner(m_pNearbyWeapon); + + if (pOwner != nullptr) // Someone already owns this weapon + { + m_pNearbyWeapon = nullptr; + } + else + { + if (!m_pSchedules->isCurrentSchedule(SCHED_PICKUP)) + { + m_pSchedules->removeSchedule(SCHED_PICKUP); + m_pSchedules->addFront(new CBotPickupSched(m_pNearbyWeapon.get())); + debugMsg(BOT_DEBUG_THINK, "[MOD THINK] Picking up weapon"); + m_flPickUpTime = engine->Time() + randomFloat(5.0f, 10.0f); + } + } + } + + // Checks for nearby item boxes and try to break them + if (m_pNearbyItemCrate && distanceFrom(m_pNearbyItemCrate.get()) <= 400.0f && m_flPickUpTime <= engine->Time()) + { + if (!m_pSchedules->isCurrentSchedule(SCHED_SYN_BREAK_ICRATE)) + { + CBotWeapon* pWeapon = nullptr; + + if (m_pWeapons->hasWeapon(SYN_WEAPON_PHYSCANNON)) + { + pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(SYN_WEAPON_PHYSCANNON)); + } + else if (m_pWeapons->hasWeapon(SYN_WEAPON_CROWBAR)) + { + pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(SYN_WEAPON_CROWBAR)); + } + else if (m_pWeapons->hasWeapon(SYN_WEAPON_STUNSTICK)) + { + pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(SYN_WEAPON_STUNSTICK)); + } + else if (m_pWeapons->hasWeapon(SYN_WEAPON_LEADPIPE)) + { + pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(SYN_WEAPON_LEADPIPE)); + } + else if (m_pWeapons->hasWeapon(SYN_WEAPON_SHOTGUN)) + { + pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(SYN_WEAPON_SHOTGUN)); + } + else if (m_pWeapons->hasWeapon(SYN_WEAPON_SMG1)) + { + pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(SYN_WEAPON_SMG1)); + } + else if (m_pWeapons->hasWeapon(SYN_WEAPON_PISTOL)) + { + pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(SYN_WEAPON_PISTOL)); + } + + m_pSchedules->removeSchedule(SCHED_SYN_BREAK_ICRATE); + m_pSchedules->addFront(new CSynBreakICrateSched(m_pNearbyItemCrate.get(), pWeapon)); + debugMsg(BOT_DEBUG_THINK, "[MOD THINK] Breaking item crate"); + m_flPickUpTime = engine->Time() + randomFloat(5.0f, 10.0f); + } + } + + /** + * Bot sprinting logic + **/ + if (hasSomeConditions(CONDITION_RUN) && m_flSuitPower > 1.0f && m_flNextSprintTime <= engine->Time()) // The bot wants to sprint + { + m_pButtons->holdButton(IN_SPEED, 0.0f, 1.0f, 0.0f); + } + else if (m_fCurrentDanger >= 75.0f && m_flSuitPower > 1.0f && !isUnderWater()) // dangerous area, sprint + { + m_pButtons->holdButton(IN_SPEED, 0.0f, 1.0f, 0.0f); + } + else if (m_flSuitPower < 1.0f) // Low on suit power, don't sprint for a while + { + m_flNextSprintTime = engine->Time() + randomFloat(8.0f, 10.0f); + removeCondition(CONDITION_RUN); + } + else if (isUnderWater()) // In Synergy/HL2 suit power is also used for oxygen + { + m_flNextSprintTime = engine->Time() + 0.5f; + } +} + +void CBotSynergy::updateConditions() +{ + CBot::updateConditions(); + + if (m_pEnemy.get() != nullptr) + { + if (CDataInterface::GetEntityHealth(m_pEnemy.get()->GetNetworkable()->GetBaseEntity()) <= 0) + { + updateCondition(CONDITION_ENEMY_DEAD); + m_pNavigator->belief(getOrigin(), CBotGlobals::entityOrigin(m_pEnemy), bot_belief_fade.GetFloat(), distanceFrom(m_pEnemy), BELIEF_SAFETY); + enemyDown(m_pEnemy); + m_pEnemy = nullptr; + } + } +} + +bool CBotSynergy::isEnemy(edict_t* pEdict, bool bCheckWeapons) +{ + if (m_pEdict == pEdict) // Not self + return false; + + if (ENTINDEX(pEdict) <= CBotGlobals::maxClients()) // Coop mod, don't attack players + return false; + + const char* szclassname = pEdict->GetClassName(); + + // BUGBUG!! Maps can override NPC relationship with the ai_relationship entity, making this classname filter useless + if (std::strncmp(szclassname, "npc_", 4) == 0) // Attack NPCs + { + if (std::strcmp(szclassname, "npc_metropolice") == 0 || std::strcmp(szclassname, "npc_combine_s") == 0 || std::strcmp(szclassname, "npc_manhack") == 0 || + std::strcmp(szclassname, "npc_zombie") == 0 || std::strcmp(szclassname, "npc_fastzombie") == 0 || std::strcmp(szclassname, "npc_poisonzombie") == 0 || std::strcmp(szclassname, "npc_zombine") == 0 || + std::strcmp(szclassname, "npc_antlionguard") == 0 || std::strcmp(szclassname, "npc_antlion") == 0 || std::strcmp(szclassname, "npc_headcrab") == 0 || std::strcmp(szclassname, "npc_headcrab_fast") == 0 || + std::strcmp(szclassname, "npc_headcrab_black") == 0 || std::strcmp(szclassname, "npc_hunter") == 0 || std::strcmp(szclassname, "npc_fastzombie_torso") == 0 || std::strcmp(szclassname, "npc_zombie_torso") == 0 || + std::strcmp(szclassname, "npc_barnacle") == 0 || (std::strcmp(szclassname, "npc_combinegunship") == 0) || (std::strcmp(szclassname, "npc_helicopter") == 0) + || (std::strcmp(szclassname, "npc_strider") == 0) || (std::strcmp(szclassname, "npc_combinedropship") == 0) || (std::strcmp(szclassname, "npc_clawscanner") == 0) + || (std::strcmp(szclassname, "npc_combine_camera") == 0) || (std::strcmp(szclassname, "npc_antlion_worker") == 0) || (std::strcmp(szclassname, "npc_cscanner") == 0)) + { + return true; + } + } + + return false; +} + +bool CBotSynergy::setVisible(edict_t* pEntity, const bool bVisible) +{ + const bool bValid = CBot::setVisible(pEntity, bVisible); + + static float fDist = distanceFrom(pEntity); + const Vector entityorigin = CBotGlobals::entityOrigin(pEntity); + const char* szclassname = pEntity->GetClassName(); + + // Is valid and NOT invisible + if (bValid && bVisible && !(CClassInterface::getEffects(pEntity) & EF_NODRAW)) + { + if (std::strcmp(szclassname, "item_ammo_crate") == 0 && (!m_pNearbyCrate.get() || fDist < distanceFrom(m_pNearbyCrate.get()))) + { + m_pNearbyCrate = pEntity; + } + else if (std::strncmp(szclassname, "item_ammo", 9) == 0 && (!m_pNearbyAmmo.get() || fDist < distanceFrom(m_pNearbyAmmo.get()))) + { + if (std::strncmp(szclassname, "item_ammo_crate", 15) == 0) + { + m_pNearbyAmmo = nullptr; // Invalidate if this entity is an ammo crate + } + else if (std::strncmp(szclassname, "item_ammo_pack", 14) == 0) // Ignore these + { + m_pNearbyAmmo = nullptr; + } + else if (filterAmmo(pEntity, szclassname)) + { + m_pNearbyAmmo = pEntity; + } + } + else if (std::strncmp(szclassname, "item_box_buckshot", 17) == 0 && (!m_pNearbyAmmo.get() || fDist < distanceFrom(m_pNearbyAmmo.get()))) + { + if (filterAmmo(pEntity, szclassname)) + { + m_pNearbyAmmo = pEntity; + } + } + else if (std::strncmp(szclassname, "item_rpg_round", 14) == 0 && (!m_pNearbyAmmo.get() || fDist < distanceFrom(m_pNearbyAmmo.get()))) + { + if (filterAmmo(pEntity, szclassname)) + { + m_pNearbyAmmo = pEntity; + } + } + else if (std::strncmp(szclassname, "item_healthkit", 14) == 0 && (!m_pNearbyHealthKit.get() || fDist < distanceFrom(m_pNearbyHealthKit.get()))) + { + m_pNearbyHealthKit = pEntity; + } + else if (std::strncmp(szclassname, "item_battery", 12) == 0 && (!m_pNearbyBattery.get() || fDist < distanceFrom(m_pNearbyBattery.get()))) + { + m_pNearbyBattery = pEntity; + } + else if (std::strncmp(szclassname, "weapon_", 7) == 0 && (!m_pNearbyWeapon.get() || fDist < distanceFrom(m_pNearbyWeapon.get()))) + { + const CBotWeapon* pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(szclassname)); + if (pWeapon && pWeapon->hasWeapon()) + { + m_pNearbyWeapon = nullptr; // bot already has this weapon + } + else + { + const edict_t* pOwner = CClassInterface::getOwner(pEntity); + if (pOwner == nullptr) // Don't pick weapons owned by someone + { + m_pNearbyWeapon = pEntity; + } + } + } + else if (std::strncmp(szclassname, "npc_grenade_frag", 16) == 0 && (!m_pNearbyGrenade.get() || fDist < distanceFrom(m_pNearbyGrenade.get()))) + { + const edict_t* pOwner = CClassInterface::getOwner(pEntity); + const IPlayerInfo* p = playerinfomanager->GetPlayerInfo(pEntity); + if (pOwner == nullptr || p == nullptr) // Only care about grenades that doesn't have an owner or isn't owned by a player + { + m_pNearbyGrenade = pEntity; + const int iWaypoint = CWaypointLocations::NearestWaypoint(entityorigin, 512.0f, -1); + if (iWaypoint != -1) + { + m_pNavigator->beliefOne(iWaypoint, BELIEF_DANGER, distanceFrom(pEntity)); + } + } + } + else if (std::strncmp(szclassname, "combine_mine", 12) == 0 && (!m_pNearbyMine.get() || fDist < distanceFrom(m_pNearbyMine.get()))) + { + if (!CSynergyMod::IsCombineMinePlayerPlaced(pEntity)) // Ignore player placed (friendly) mines + { + m_pNearbyMine = pEntity; + const int iWaypoint = CWaypointLocations::NearestWaypoint(entityorigin, 512.0f, -1); + if (iWaypoint != -1) + { + m_pNavigator->beliefOne(iWaypoint, BELIEF_DANGER, distanceFrom(pEntity)); + } + } + } + else if (std::strncmp(szclassname, "item_item_crate", 15) == 0 && (!m_pNearbyItemCrate.get() || fDist < distanceFrom(m_pNearbyItemCrate.get()))) + { + m_pNearbyItemCrate = pEntity; + } + else if (std::strncmp(szclassname, "item_healthcharger", 18) == 0 && (!m_pNearbyHealthCharger.get() || fDist < distanceFrom(m_pNearbyHealthCharger.get()))) + { + if (CClassInterface::getAnimCycle(pEntity) < 1.0f) + { + m_pNearbyHealthCharger = pEntity; + } + } + else if (std::strncmp(szclassname, "item_suitcharger", 16) == 0 && (!m_pNearbyArmorCharger.get() || fDist < distanceFrom(m_pNearbyArmorCharger.get()))) + { + if (CClassInterface::getAnimCycle(pEntity) < 1.0f) + { + m_pNearbyArmorCharger = pEntity; + } + } + } + else + { + if (pEntity == m_pNearbyAmmo.get_old()) + m_pNearbyAmmo = nullptr; + else if (pEntity == m_pNearbyCrate.get_old()) + m_pNearbyCrate = nullptr; + else if (pEntity == m_pNearbyHealthKit.get_old()) + m_pNearbyHealthKit = nullptr; + else if (pEntity == m_pNearbyBattery.get_old()) + m_pNearbyBattery = nullptr; + else if (pEntity == m_pNearbyWeapon.get_old()) + m_pNearbyWeapon = nullptr; + else if (pEntity == m_pNearbyMine.get_old()) + m_pNearbyMine = nullptr; + else if (pEntity == m_pNearbyGrenade.get_old()) + m_pNearbyGrenade = nullptr; + else if (pEntity == m_pNearbyItemCrate.get_old()) + m_pNearbyItemCrate = nullptr; + else if (pEntity == m_pNearbyHealthCharger.get_old()) + m_pNearbyHealthCharger = nullptr; + else if (pEntity == m_pNearbyArmorCharger.get_old()) + m_pNearbyArmorCharger = nullptr; + } + + return bValid; +} + +void CBotSynergy::getTasks(unsigned iIgnore) +{ + static CBotUtilities utils; + static CBotUtility* next; + static bool bCheckCurrent; + + if (!hasSomeConditions(CONDITION_CHANGED) && !m_pSchedules->isEmpty()) + return; + + removeCondition(CONDITION_CHANGED); + bCheckCurrent = true; // important for checking current schedule + + // Utilities + ADD_UTILITY(BOT_UTIL_PICKUP_WEAPON, m_pNearbyWeapon.get() != NULL, 0.75f) // New weapons are interesting, high priority + ADD_UTILITY(BOT_UTIL_GETHEALTHKIT, m_pNearbyHealthKit.get() != NULL, 1.0f - getHealthPercent()) // Pick up health kits + ADD_UTILITY(BOT_UTIL_HL2DM_FIND_ARMOR, m_pNearbyBattery.get() != NULL, 1.0f - getArmorPercent()) // Pick up armor batteries + ADD_UTILITY(BOT_UTIL_FIND_NEAREST_HEALTH, hasSomeConditions(CONDITION_NEED_HEALTH), 1.0f - getHealthPercent()) // Search for health kits + ADD_UTILITY(BOT_UTIL_FIND_NEAREST_AMMO, hasSomeConditions(CONDITION_NEED_AMMO), 0.15f) // Search for ammo + ADD_UTILITY(BOT_UTIL_ATTACK_POINT, true, 0.01f) // Go to waypoints with 'goal' flag + ADD_UTILITY(BOT_UTIL_ROAM, true, 0.0001f) // Roam around + + utils.execute(); + + while ((next = utils.nextBest()) != nullptr) + { + if (!m_pSchedules->isEmpty() && bCheckCurrent) + { + if (m_CurrentUtil != next->getId()) + m_pSchedules->freeMemory(); + else + break; + } + + bCheckCurrent = false; + + if (executeAction(next->getId())) + { + m_CurrentUtil = next->getId(); + m_flInterruptTime = engine->Time() + randomFloat(30.0f, 45.0f); + + if (m_fUtilTimes[next->getId()] < engine->Time()) + m_fUtilTimes[next->getId()] = engine->Time() + randomFloat(0.1f, 2.0f); // saves problems with consistent failing + + if (CClients::clientsDebugging(BOT_DEBUG_UTIL)) + { + CClients::clientDebugMsg(BOT_DEBUG_UTIL, g_szUtils[next->getId()], this); + } + break; + } + } + + utils.freeMemory(); +} + +bool CBotSynergy::executeAction(const eBotAction iAction) +{ + switch (iAction) + { + case BOT_UTIL_PICKUP_WEAPON: + m_pSchedules->add(new CBotPickupSched(m_pNearbyWeapon.get())); + m_fUtilTimes[BOT_UTIL_PICKUP_WEAPON] = engine->Time() + randomFloat(5.0f, 10.0f); + return true; + //break; + case BOT_UTIL_GETHEALTHKIT: + m_pSchedules->add(new CBotPickupSched(m_pNearbyHealthKit.get())); + m_fUtilTimes[BOT_UTIL_GETHEALTHKIT] = engine->Time() + randomFloat(5.0f, 10.0f); + return true; + //break; + case BOT_UTIL_HL2DM_FIND_ARMOR: + m_pSchedules->add(new CBotPickupSched(m_pNearbyBattery.get())); + m_fUtilTimes[BOT_UTIL_HL2DM_FIND_ARMOR] = engine->Time() + randomFloat(5.0f, 10.0f); + return true; + //break; + case BOT_UTIL_FIND_NEAREST_HEALTH: + { + const Vector vOrigin = getOrigin(); + CBotSchedule* pSched = new CBotSchedule(); + pSched->setID(SCHED_GOTO_ORIGIN); + updateCondition(CONDITION_COVERT); // Pay more attention to danger + CWaypoint* pWaypoint = CWaypoints::getWaypoint( + CWaypoints::nearestWaypointGoal(CWaypointTypes::W_FL_HEALTH, vOrigin, 2048.0f)); + m_fUtilTimes[BOT_UTIL_FIND_NEAREST_HEALTH] = engine->Time() + randomFloat(60.0f, 90.0f); + + if (pWaypoint) + { + pSched->addTask(new CFindPathTask(CWaypoints::getWaypointIndex(pWaypoint), LOOK_WAYPOINT)); + pSched->addTask(new CMoveToTask(pWaypoint->getOrigin())); + m_pSchedules->add(pSched); + return true; + } + } + case BOT_UTIL_FIND_NEAREST_AMMO: + { + const Vector vOrigin = getOrigin(); + CBotSchedule* pSched = new CBotSchedule(); + pSched->setID(SCHED_GOTO_ORIGIN); + CWaypoint* pWaypoint = CWaypoints::getWaypoint( + CWaypoints::nearestWaypointGoal(CWaypointTypes::W_FL_AMMO, vOrigin, 2048.0f)); + m_fUtilTimes[BOT_UTIL_FIND_NEAREST_AMMO] = engine->Time() + randomFloat(60.0f, 90.0f); + + if (pWaypoint) + { + pSched->addTask(new CFindPathTask(CWaypoints::getWaypointIndex(pWaypoint), LOOK_WAYPOINT)); + pSched->addTask(new CMoveToTask(pWaypoint->getOrigin())); + m_pSchedules->add(pSched); + return true; + } + } + case BOT_UTIL_ATTACK_POINT: + { + // roam + CBotSchedule* pSched = new CBotSchedule(); + m_fUtilTimes[BOT_UTIL_ATTACK_POINT] = engine->Time() + randomFloat(60.0f, 180.0f); + + pSched->setID(SCHED_ATTACKPOINT); + + // Make the bot more likely to use alternate paths based on their braveness and current health + if (getHealthPercent() + m_pProfile->m_fBraveness <= 1.0f) + updateCondition(CONDITION_COVERT); + else + removeCondition(CONDITION_COVERT); + + if (CWaypoint* pWaypoint = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_GOAL)) + { + CBotTask* pFindPath; + CWaypoint* pRoute = CWaypoints::randomRouteWaypoint(this, getOrigin(), pWaypoint->getOrigin(), 0, 0); + if ((m_fUseRouteTime <= engine->Time())) + { + if (pRoute) + { + const int iRoute = CWaypoints::getWaypointIndex(pRoute); // Route waypoint + pFindPath = new CFindPathTask(iRoute, LOOK_WAYPOINT); + pFindPath->setInterruptFunction(new CBotSYNRoamInterrupt()); + pSched->addTask(pFindPath); + pSched->addTask(new CMoveToTask(pRoute->getOrigin())); + m_pSchedules->add(pSched); + m_fUseRouteTime = engine->Time() + 30.0f; + } + } + + const int iWaypoint = CWaypoints::getWaypointIndex(pWaypoint); + pFindPath = new CFindPathTask(iWaypoint, LOOK_WAYPOINT); + pFindPath->setInterruptFunction(new CBotSYNRoamInterrupt()); + pSched->addTask(pFindPath); + pSched->addTask(new CMoveToTask(pWaypoint->getOrigin())); + m_pSchedules->add(pSched); + + return true; + } + + break; + } + case BOT_UTIL_ROAM: + { + // roam + CBotSchedule* pSched = new CBotSchedule(); + + pSched->setID(SCHED_GOTO_ORIGIN); + + // Make the bot more likely to use alternate paths based on their braveness and current health + if (getHealthPercent() + m_pProfile->m_fBraveness <= 1.0f) + updateCondition(CONDITION_COVERT); + else + removeCondition(CONDITION_COVERT); + + if (CWaypoint* pWaypoint = CWaypoints::randomWaypointGoal(-1)) + { + CBotTask* pFindPath; + CWaypoint* pRoute = CWaypoints::randomRouteWaypoint(this, getOrigin(), pWaypoint->getOrigin(), 0, 0); + if ((m_fUseRouteTime <= engine->Time())) + { + if (pRoute) + { + const int iRoute = CWaypoints::getWaypointIndex(pRoute); // Route waypoint + pFindPath = new CFindPathTask(iRoute, LOOK_WAYPOINT); + pFindPath->setInterruptFunction(new CBotSYNRoamInterrupt()); + pSched->addTask(pFindPath); + pSched->addTask(new CMoveToTask(pRoute->getOrigin())); + m_pSchedules->add(pSched); + m_fUseRouteTime = engine->Time() + 30.0f; + } + } + + const int iWaypoint = CWaypoints::getWaypointIndex(pWaypoint); + pFindPath = new CFindPathTask(iWaypoint, LOOK_WAYPOINT); + pFindPath->setInterruptFunction(new CBotSYNRoamInterrupt()); + pSched->addTask(pFindPath); + pSched->addTask(new CMoveToTask(pWaypoint->getOrigin())); + m_pSchedules->add(pSched); + + return true; + } + + break; + } + } //Not required? [APG]RoboCop[CL] + + return false; +} + +void CBotSynergy::touchedWpt(CWaypoint* pWaypoint, const int iNextWaypoint, const int iPrevWaypoint) +{ + if (iNextWaypoint != -1 && pWaypoint->hasFlag(CWaypointTypes::W_FL_USE)) // Use waypoint: Check for door + { + CWaypoint* pNext = CWaypoints::getWaypoint(iNextWaypoint); + if (pNext && pNext->hasFlag(CWaypointTypes::W_FL_USE)) + { + /** + * Perform a trace to check if there is something blocking the path between the current waypoint and the next waypoint. + * Originally I wanted to use tr->GetEntityIndex() and check if the hit entity is a door + * but that function causes link errors when compiling, so I had to fall back to manually searching for door entities. + **/ + CTraceFilterHitAll filter; + const trace_t* tr = CBotGlobals::getTraceResult(); + CBotGlobals::traceLine(pWaypoint->getOrigin() + Vector(0, 0, CWaypoint::WAYPOINT_HEIGHT / 2), pNext->getOrigin() + Vector(0, 0, CWaypoint::WAYPOINT_HEIGHT / 2), MASK_PLAYERSOLID, &filter); + if (tr->fraction < 1.0f) + { + if (tr->m_pEnt) + { + edict_t* pDoor = servergameents->BaseEntityToEdict(tr->m_pEnt); + const char* szclassname = pDoor->GetClassName(); + if (std::strncmp(szclassname, "prop_door_rotating", 18) == 0 || std::strncmp(szclassname, "func_door", 9) == 0 || std::strncmp(szclassname, "func_door_rotating", 18) == 0) + { + if (!CSynergyMod::IsEntityLocked(pDoor)) + { + m_pSchedules->addFront(new CSynOpenDoorSched(pDoor)); + } + } + } + /* pDoor = CClassInterface::FindEntityByClassnameNearest(getOrigin(), "prop_door_rotating", rcbot_syn_use_search_range.GetFloat()); + if(pDoor != NULL && !CSynergyMod::IsEntityLocked(pDoor)) + { + m_pSchedules->addFront(new CSynOpenDoorSched(pDoor)); + } + else + { + pDoor = CClassInterface::FindEntityByClassnameNearest(getOrigin(), "func_door", rcbot_syn_use_search_range.GetFloat()); + if(pDoor != NULL && !CSynergyMod::IsEntityLocked(pDoor)) + { + m_pSchedules->addFront(new CSynOpenDoorSched(pDoor)); + } + else + { + pDoor = CClassInterface::FindEntityByClassnameNearest(getOrigin(), "func_door_rotating", rcbot_syn_use_search_range.GetFloat()); + if(pDoor != NULL && !CSynergyMod::IsEntityLocked(pDoor)) + { + m_pSchedules->addFront(new CSynOpenDoorSched(pDoor)); + } + } + } */ + } + } + } + else // Check for button + { + edict_t* pEntity = CClassInterface::FindEntityByClassnameNearest(getOrigin(), "func_button", + rcbot_syn_use_search_range.GetFloat()); + if (pEntity != nullptr && !CSynergyMod::IsEntityLocked(pEntity)) + { + CBotSchedule* sched = new CBotSchedule(); + sched->setID(SCHED_GOTO_ORIGIN); + sched->addTask(new CMoveToTask(pEntity)); + sched->addTask(new CBotHL2DMUseButton(pEntity)); + sched->addTask(new CBotWaitTask(randomFloat(3.0f, 6.0f))); + m_pSchedules->addFront(sched); + } + } + + CBot::touchedWpt(pWaypoint, iNextWaypoint, iPrevWaypoint); +} + +bool CBotSynergy::walkingTowardsWaypoint(CWaypoint* pWaypoint, bool* bOffsetApplied, Vector& vOffset) +{ + return CBot::walkingTowardsWaypoint(pWaypoint, bOffsetApplied, vOffset); +} + +void CBotSynergy::reachedCoverSpot(int flags) +{ + removeCondition(CONDITION_RUN); // Remove when in cover +} + +void CBotSynergy::handleWeapons() +{ + if (m_pEnemy && !hasSomeConditions(CONDITION_ENEMY_DEAD) && + hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && wantToShoot() && + isVisible(m_pEnemy) && isEnemy(m_pEnemy)) + { + const char* szclassname = m_pEnemy.get()->GetClassName(); + CBotWeapon* pWeapon; + + if ((std::strncmp(szclassname, "npc_combinegunship", 18) == 0) || (std::strncmp(szclassname, "npc_combinedropship", 19) == 0) || (std::strncmp(szclassname, "npc_strider", 11) == 0) || + (std::strncmp(szclassname, "npc_helicopter", 14) == 0)) + { + pWeapon = m_pWeapons->getWeapon(CWeapons::getWeapon(SYN_WEAPON_RPG)); + } + else + { + pWeapon = getBestWeapon(m_pEnemy, true, true, false, false); + } + + if (m_bWantToChangeWeapon && (pWeapon != nullptr) && (pWeapon != getCurrentWeapon()) && pWeapon->getWeaponIndex()) + { + selectBotWeapon(pWeapon); + } + + setLookAtTask(LOOK_ENEMY); + + if (!handleAttack(pWeapon, m_pEnemy)) + { + m_pEnemy = nullptr; + m_pOldEnemy = nullptr; + wantToShoot(false); + } + } +} + +bool CBotSynergy::handleAttack(CBotWeapon* pWeapon, edict_t* pEnemy) +{ + const char* szclassname = pEnemy->GetClassName(); + + if ((std::strncmp(szclassname, "npc_combinegunship", 18) == 0) || (std::strncmp(szclassname, "npc_combinedropship", 19) == 0) || (std::strncmp(szclassname, "npc_strider", 11) == 0) || + (std::strncmp(szclassname, "npc_helicopter", 14) == 0)) + { + if (!m_pWeapons->hasWeapon(SYN_WEAPON_RPG)) + { + return false; + } + } + + if (pWeapon) + { + clearFailedWeaponSelect(); + + if (pWeapon->isMelee()) + setMoveTo(CBotGlobals::entityOrigin(pEnemy)); + + if (pWeapon->mustHoldAttack()) + primaryAttack(true); + else + primaryAttack(); + } + else + { + primaryAttack(); + } + + return true; +} + +/** + * Filters and validates ammo entities + * + * @param pAmmo The ammo entity to validate + * @param szclassname The ammo entity's classname + * @return True if the bot should pick up this ammo entity + **/ +bool CBotSynergy::filterAmmo(edict_t* pAmmo, const char* szclassname) +{ + if (std::strncmp(szclassname, "item_ammo_pistol", 16) == 0) + { + if (m_pWeapons->hasWeapon(SYN_WEAPON_PISTOL)) + { + if (m_pWeapons->getWeapon(CWeapons::getWeapon(SYN_WEAPON_PISTOL))->getAmmo(this, AMMO_PRIM) < 36) + { + return true; + } + } + } + else if (std::strncmp(szclassname, "item_ammo_357", 13) == 0) + { + if (m_pWeapons->hasWeapon(SYN_WEAPON_357) || m_pWeapons->hasWeapon(SYN_WEAPON_DESERTEAGLE)) + { + if (m_pWeapons->getWeapon(CWeapons::getWeapon(SYN_WEAPON_357))->getAmmo(this, AMMO_PRIM) < 6 || + m_pWeapons->getWeapon(CWeapons::getWeapon(SYN_WEAPON_DESERTEAGLE))->getAmmo(this, AMMO_PRIM) < 6) + { + return true; + } + } + } + else if (std::strncmp(szclassname, "item_ammo_smg1", 14) == 0) + { + if (std::strncmp(szclassname, "item_ammo_smg1_grenade", 22) == 0) + { + if (m_pWeapons->hasWeapon(SYN_WEAPON_SMG1)) + { + if (m_pWeapons->getWeapon(CWeapons::getWeapon(SYN_WEAPON_SMG1))->getAmmo(this, AMMO_SEC) < 1) + { + return true; + } + } + } + else + { + if (m_pWeapons->hasWeapon(SYN_WEAPON_SMG1) || m_pWeapons->hasWeapon(SYN_WEAPON_MP5K)) + { + if (m_pWeapons->getWeapon(CWeapons::getWeapon(SYN_WEAPON_SMG1))->getAmmo(this, AMMO_PRIM) < 75 || + m_pWeapons->getWeapon(CWeapons::getWeapon(SYN_WEAPON_MP5K))->getAmmo(this, AMMO_PRIM) < 75) + { + return true; + } + } + } + } + else if (std::strncmp(szclassname, "item_ammo_ar2", 13) == 0) + { + if (std::strncmp(szclassname, "item_ammo_ar2_altfire", 21) == 0) + { + if (m_pWeapons->hasWeapon(SYN_WEAPON_AR2)) + { + if (m_pWeapons->getWeapon(CWeapons::getWeapon(SYN_WEAPON_AR2))->getAmmo(this, AMMO_SEC) < 1) + { + return true; + } + } + } + else + { + if (m_pWeapons->hasWeapon(SYN_WEAPON_AR2) || m_pWeapons->hasWeapon(SYN_WEAPON_MG1)) + { + if (m_pWeapons->getWeapon(CWeapons::getWeapon(SYN_WEAPON_AR2))->getAmmo(this, AMMO_PRIM) < 30 || + m_pWeapons->getWeapon(CWeapons::getWeapon(SYN_WEAPON_MG1))->getAmmo(this, AMMO_PRIM) < 30) + { + return true; + } + } + } + } + else if (std::strncmp(szclassname, "item_ammo_crossbow", 18) == 0) + { + if (m_pWeapons->hasWeapon(SYN_WEAPON_CROSSBOW)) + { + if (m_pWeapons->getWeapon(CWeapons::getWeapon(SYN_WEAPON_CROSSBOW))->getAmmo(this, AMMO_PRIM) < 3) + { + return true; + } + } + } + else if (std::strncmp(szclassname, "item_box_buckshot", 17) == 0) + { + if (m_pWeapons->hasWeapon(SYN_WEAPON_SHOTGUN)) + { + if (m_pWeapons->getWeapon(CWeapons::getWeapon(SYN_WEAPON_SHOTGUN))->getAmmo(this, AMMO_PRIM) < 12) + { + return true; + } + } + } + else if (std::strncmp(szclassname, "item_rpg_round", 14) == 0) + { + if (m_pWeapons->hasWeapon(SYN_WEAPON_RPG)) + { + if (m_pWeapons->getWeapon(CWeapons::getWeapon(SYN_WEAPON_RPG))->getAmmo(this, AMMO_PRIM) < 2) + { + return true; + } + } + } + + return false; +} + +/** + * This functions is called by task interruptions check to see if the bot should change it's current task + * + * @return TRUE if the bot should interrupt it's current task + **/ +bool CBotSynergy::wantsToChangeCourseOfAction() +{ + return false; // TODO +} \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_synergy.h b/utils/RCBot2_meta/bot_synergy.h new file mode 100644 index 000000000..18d5f5e7e --- /dev/null +++ b/utils/RCBot2_meta/bot_synergy.h @@ -0,0 +1,78 @@ +/* + * This file is part of RCBot. + * + * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. + * + * RCBot is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * RCBot is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RCBot; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + */ +#ifndef _BOT_SYNERGY_H_ +#define _BOT_SYNERGY_H_ + +class CBotSynergy : public CBot +{ +public: + bool isSYN () override { return true; } + void init (bool bVarInit = false) override; + void spawnInit () override; + void died ( edict_t *pKiller, const char *pszWeapon ) override; + void modThink () override; + void getTasks (unsigned iIgnore=0) override; + virtual bool executeAction(eBotAction iAction); //TODO: not implemented yet? [APG]RoboCop[CL] + virtual float getArmorPercent() { return 0.01f * m_pPlayerInfo->GetArmorValue(); } + unsigned maxEntityIndex() override { return gpGlobals->maxEntities; } + bool isEnemy ( edict_t *pEdict, bool bCheckWeapons = true ) override; + bool setVisible ( edict_t *pEntity, bool bVisible ) override; + void touchedWpt ( CWaypoint *pWaypoint, int iNextWaypoint = -1, int iPrevWaypoint = -1 ) override; + bool walkingTowardsWaypoint ( CWaypoint *pWaypoint, bool *bOffsetApplied, Vector &vOffset ) override; + void reachedCoverSpot (int flags) override; + void updateConditions () override; // Overridden due to Synergy's quirks + void handleWeapons() override; + bool handleAttack(CBotWeapon *pWeapon, edict_t *pEnemy) override; + virtual bool needHealth(); + virtual bool needAmmo(); + virtual bool filterAmmo(edict_t *pAmmo, const char *szclassname); + virtual bool wantsToChangeCourseOfAction(); + float getInterruptionTimer() const { return m_flInterruptTime; } +protected: + MyEHandle m_pNearbyWeapon; // weapons + MyEHandle m_pNearbyHealthKit; // Healthkit + MyEHandle m_pNearbyBattery; // Armor battery + MyEHandle m_pNearbyAmmo; // ammo pickups + MyEHandle m_pNearbyCrate; // ammo crate + MyEHandle m_pNearbyGrenade; // grenades + MyEHandle m_pNearbyMine; // combine mine + MyEHandle m_pNearbyItemCrate; // breakable item crate + MyEHandle m_pNearbyHealthCharger; // Health charger + MyEHandle m_pNearbyArmorCharger; // Armor/Suit charger + edict_t * m_pCurrentWeapon = nullptr; // The bot current weapon + float m_flSuitPower = 0.0f; // HEV suit power level, range: 100-0 + float m_flNextSprintTime = 0.0f; // Used to control the bot's sprinting + float m_flUseCrateTime = 0.0f; // Use ammo crate time delay + float m_flPickUpTime = 0.0f; // Pick ammo delay + float m_flInterruptTime = 0.0f; // Time delay for general interruptions +}; + +#endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_synergy_mod.cpp b/utils/RCBot2_meta/bot_synergy_mod.cpp new file mode 100644 index 000000000..fd624d64f --- /dev/null +++ b/utils/RCBot2_meta/bot_synergy_mod.cpp @@ -0,0 +1,157 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +/* + * This file is part of RCBot. + * + * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. + * + * RCBot is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * RCBot is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RCBot; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of this program with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + * + */ +#include "server_class.h" + +#include "bot.h" + +#include "in_buttons.h" + +#include "bot_mods.h" +#include "bot_globals.h" +#include "bot_weapons.h" +#include "bot_configfile.h" +#include "bot_getprop.h" +#include "bot_synergy.h" +#include "bot_navigator.h" +#include "bot_waypoint.h" +#include "bot_waypoint_locations.h" +#include "bot_perceptron.h" + +#include "rcbot/logging.h" + +void CSynergyMod::initMod() +{ + //Load weapons + CWeapons::loadWeapons(m_szWeaponListName == nullptr ? "SYNERGY" : m_szWeaponListName, SYNERGYWeaps.data()); +} + +void CSynergyMod::mapInit() +{ + logger->Log(LogLevel::DEBUG, "[Synergy Mod] map Init."); +} + +/** + * Checks if the given entity is locked. (Door, buttons) + * + * @param pEntity The entity to check + * @return true if the entity is locked, false if unlocked or invalid + **/ +bool CSynergyMod::IsEntityLocked(edict_t *pEntity) +{ + CBaseEntity *pBaseEntity = pEntity->GetUnknown()->GetBaseEntity(); + const datamap_t* pDataMap = CBaseEntity_GetDataDescMap(pBaseEntity); + const int offset = UTIL_FindInDataMap(pDataMap, "m_bLocked"); + if(offset == 0) + { + const char *szclassname = pEntity->GetClassName(); + logger->Log(LogLevel::ERROR, "Offset 0 for entity \"%s\"", szclassname); + return false; + } + const int value = *reinterpret_cast(reinterpret_cast(pBaseEntity) + offset); + if(value == 1) + return true; // Locked + return false; + // Unlocked +} + +/** + * Checks if the given combine mine was placed by a player + * + * @param pMine The mine entity to check + * @return True if the given mine was placed by a player + **/ +bool CSynergyMod::IsCombineMinePlayerPlaced(edict_t *pMine) +{ + CBaseEntity *pBaseEntity = pMine->GetUnknown()->GetBaseEntity(); + const datamap_t* pDataMap = CBaseEntity_GetDataDescMap(pBaseEntity); + const int offset = UTIL_FindInDataMap(pDataMap, "m_bPlacedByPlayer"); + const int value = *reinterpret_cast(reinterpret_cast(pBaseEntity) + offset); + if(value == 1) + return true; + + return false; +} + +/** + * Checks if the given combine mine is disarmed + * + * @param pMine The mine entity to check + * @return True if the given mine is disarmed + **/ +bool CSynergyMod::IsCombineMineDisarmed(edict_t *pMine) +{ + CBaseEntity *pBaseEntity = pMine->GetUnknown()->GetBaseEntity(); + const datamap_t* pDataMap = CBaseEntity_GetDataDescMap(pBaseEntity); + const int offset = UTIL_FindInDataMap(pDataMap, "m_bDisarmed"); + const int value = *reinterpret_cast(reinterpret_cast(pBaseEntity) + offset); + if(value == 1) + return true; + + return false; +} + +/** + * Checks if the given combine mine is armed + * + * @param pMine The mine entity to check + * @return True if the given mine is armed + **/ +bool CSynergyMod::IsCombineMineArmed(edict_t *pMine) +{ + CBaseEntity *pBaseEntity = pMine->GetUnknown()->GetBaseEntity(); + const datamap_t* pDataMap = CBaseEntity_GetDataDescMap(pBaseEntity); + const int offset = UTIL_FindInDataMap(pDataMap, "m_iMineState"); + const int value = *reinterpret_cast(reinterpret_cast(pBaseEntity) + offset); + if(value > 0) + return true; + + return false; +} + +/** + * Checks if the given combine mine is held by a physcannon (gravity gun) + * + * @param pMine The mine entity to check + * @return True if the given mine is held by a physcannon (gravity gun) + **/ +bool CSynergyMod::IsCombineMineHeldByPhysgun(edict_t *pMine) +{ + CBaseEntity *pBaseEntity = pMine->GetUnknown()->GetBaseEntity(); + const datamap_t* pDataMap = CBaseEntity_GetDataDescMap(pBaseEntity); + const int offset = UTIL_FindInDataMap(pDataMap, "m_bHeldByPhysgun"); + const int value = *reinterpret_cast(reinterpret_cast(pBaseEntity) + offset); + if(value > 0) + return true; + + return false; +} \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_task.cpp b/utils/RCBot2_meta/bot_task.cpp index 8c53e8f48..f3bb3ef3b 100644 --- a/utils/RCBot2_meta/bot_task.cpp +++ b/utils/RCBot2_meta/bot_task.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * part of https://rcbot2.svn.sourceforge.net/svnroot/rcbot2 * @@ -34,8 +36,11 @@ #include "bot_mtrand.h" #include "bot.h" +#include "bot_cvars.h" #include "bot_schedule.h" #include "bot_task.h" + +#include #include "bot_navigator.h" #include "bot_waypoint_locations.h" #include "bot_globals.h" @@ -43,86 +48,87 @@ #include "bot_weapons.h" #include "bot_hldm_bot.h" #include "bot_fortress.h" +#include "bot_css_bot.h" #include "bot_profiling.h" #include "bot_getprop.h" #include "bot_dod_bot.h" #include "bot_squads.h" #include "bot_waypoint_visibility.h" +#include "bot_synergy.h" +#include "rcbot/utils.h" +//caxanga334: SDK 2013 contains macros for std::min and std::max which causes errors when compiling +//#if SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_BMS +#include "valve_minmax_off.h" +//#endif -extern ConVar *sv_gravity; // desx and desy must be normalized // desx = distance (should be 2d) // desy = height offset -void getGrenadeAngle ( float v, float g, float desx, float desy, float *fa1, float *fa2 ) +void getGrenadeAngle(double v, double g, double desx, double desy, float* fa1, float* fa2) { - //normalize - float fmax = MAX(v,MAX(g,MAX(desx,desy))); + // Normalize + const float fmax = static_cast(std::max({ v, g, desx, desy })); v /= fmax; g /= fmax; desx /= fmax; desy /= fmax; - double vsquared = v*v; - double vfourth = vsquared * vsquared; - double x2 = desx * desx; - double gx2 = g * x2; - double twoyv2 = 2*desy*vsquared; - double fourabplusa = vfourth - g*(gx2+twoyv2); - double topplus = vsquared + sqrt(fourabplusa); - double topminus = vsquared - sqrt(fourabplusa); - double bottom = g*desx; - - *fa1 = (float)atan(topplus / bottom); - *fa2 = (float)atan(topminus / bottom); + + const double vsquared = v * v; + const double vfourth = vsquared * vsquared; + const double x2 = desx * desx; + const double gx2 = g * x2; + const double twoyv2 = 2 * desy * vsquared; + const double fourabplusa = vfourth - g * (gx2 + twoyv2); + const double topplus = vsquared + std::sqrt(fourabplusa); + const double topminus = vsquared - std::sqrt(fourabplusa); + const double bottom = g * desx; + + *fa1 = static_cast(std::atan2(topplus, bottom)); + *fa2 = static_cast(std::atan2(topminus, bottom)); *fa1 = RAD2DEG(*fa1); *fa2 = RAD2DEG(*fa2); - - return; } -float getGrenadeZ ( edict_t *pShooter, edict_t *pTarget, Vector vOrigin, Vector vTarget, float fInitialSpeed ) +float getGrenadeZ ( edict_t *pShooter, edict_t *pTarget, const Vector& vOrigin, const Vector& vTarget, const float fInitialSpeed ) { float fAngle1,fAngle2; Vector vForward; - QAngle angles; - Vector v_comp = (vTarget-vOrigin); + const Vector v_comp = vTarget-vOrigin; - float fDist2D = v_comp.Length2D(); - float fDist3D = v_comp.Length(); + const float fDist2D = v_comp.Length2D(); + const float fDist3D = v_comp.Length(); - getGrenadeAngle(fInitialSpeed,sv_gravity->GetFloat(),fDist2D,vTarget.z-vOrigin.z,&fAngle1,&fAngle2); + getGrenadeAngle(fInitialSpeed,sv_gravity.GetFloat(),fDist2D,vTarget.z-vOrigin.z,&fAngle1,&fAngle2); - angles = QAngle(0,0,0); + QAngle angles = QAngle(0, 0, 0); // do a quick traceline to check which angle to choose (minimum angle = straight) if (CBotGlobals::isShotVisible(pShooter,vOrigin,vTarget,pTarget)) - angles.x = -MIN(fAngle1,fAngle2); + angles.x = -std::min(fAngle1,fAngle2); else - angles.x = -MAX(fAngle1,fAngle2); + angles.x = -std::max(fAngle1,fAngle2); AngleVectors(angles,&vForward); // add gravity height - return (vOrigin + (vForward*fDist3D)).z; + return (vOrigin + vForward*fDist3D).z; } //////////////////////////////////////////////////////////////////////////////////////////// // Tasks CBotTF2MedicHeal :: CBotTF2MedicHeal () { - m_pHeal = NULL; + m_pHeal = nullptr; m_bHealerJumped = false; } void CBotTF2MedicHeal::execute(CBot *pBot,CBotSchedule *pSchedule) -{ - edict_t *pHeal; - CBotTF2 *pBotTF2; - +{ pBot->wantToShoot(false); pBot->wantToListen(false); @@ -132,19 +138,17 @@ void CBotTF2MedicHeal::execute(CBot *pBot,CBotSchedule *pSchedule) return; } - pBotTF2 = (CBotTF2*)pBot; + CBotTF2* pBotTF2 = static_cast(pBot); - pHeal = pBotTF2->getHealingEntity(); + edict_t* pHeal = pBotTF2->getHealingEntity(); if ( pHeal && !m_bHealerJumped ) { Vector vVelocity; - if ( !CClassInterface::getVelocity(pHeal,&vVelocity) || (vVelocity.Length2D() > 1.0f) ) + if ( !CClassInterface::getVelocity(pHeal,&vVelocity) || vVelocity.Length2D() > 1.0f ) { - IPlayerInfo *p = playerinfomanager->GetPlayerInfo(pHeal); - - if ( p ) + if ( IPlayerInfo *p = playerinfomanager->GetPlayerInfo(pHeal) ) { if ( p->GetLastUserCommand().buttons & IN_JUMP ) { @@ -161,13 +165,13 @@ void CBotTF2MedicHeal::execute(CBot *pBot,CBotSchedule *pSchedule) pBot->getNavigator()->rollBackPosition(); fail(); } - else if ( pBot->getCurrentWeapon() == NULL ) + else if (pBot->getCurrentWeapon() == nullptr) //Revert fix by caxanga334 { pBotTF2->clearHealingEntity(); pBot->getNavigator()->rollBackPosition(); fail(); } - else if ( pBotTF2->getHealFactor(pHeal) == 0.0f ) + else if (pBotTF2->getHealFactor(pHeal) == 0.0f) { pBotTF2->clearHealingEntity(); pBot->getNavigator()->rollBackPosition(); @@ -197,13 +201,13 @@ void CBotTF2MedicHeal::execute(CBot *pBot,CBotSchedule *pSchedule) pBot->clearFailedWeaponSelect(); - if ( m_bHealerJumped && (pBot->distanceFrom(m_vJump) < 64.0f) && (vVelocity.Length()>1.0f) ) + if ( m_bHealerJumped && pBot->distanceFrom(m_vJump) < 64.0f && vVelocity.Length()>1.0f ) { pBot->jump(); m_bHealerJumped = false; } - if ( !pBotTF2->healPlayer() ) + if ( !pBotTF2->healPlayer(nullptr, nullptr) ) { pBot->getNavigator()->rollBackPosition(); pBotTF2->clearHealingEntity(); @@ -214,28 +218,23 @@ void CBotTF2MedicHeal::execute(CBot *pBot,CBotSchedule *pSchedule) /////////// - -CBotTF2ShootLastEnemyPosition :: CBotTF2ShootLastEnemyPosition ( Vector vPosition, edict_t *pEnemy, Vector m_vVelocity ) +CBotTF2ShootLastEnemyPosition::CBotTF2ShootLastEnemyPosition(const Vector& vPosition, edict_t* pEnemy, + const Vector& m_vVelocity) : m_pEnemy(pEnemy), m_vPosition(vPosition) { - float len = m_vVelocity.Length(); - - m_vPosition = vPosition; + const float len = m_vVelocity.Length(); if ( len > 0 ) - m_vPosition = m_vPosition - ((m_vVelocity/m_vVelocity.Length())*16); - - m_pEnemy = pEnemy; - m_fTime = 0; + m_vPosition = m_vPosition - m_vVelocity/m_vVelocity.Length()*16; + m_fTime = 0.0f; } void CBotTF2ShootLastEnemyPosition :: execute (CBot *pBot,CBotSchedule *pSchedule) { - CBotWeapon *pWeapon = pBot->getCurrentWeapon(); - CBotTF2 *pTF2Bot = (CBotTF2*)pBot; - CWeapon *pChange = NULL; - CBotWeapon *pChangeTo = NULL; + const CBotWeapon *pWeapon = pBot->getCurrentWeapon(); + CBotTF2 *pTF2Bot = static_cast(pBot); + const CWeapon *pChange = nullptr; - if ( m_fTime == 0 ) + if ( m_fTime == 0.0f ) m_fTime = engine->Time() + randomFloat(2.0f,4.5f); if ( m_fTime < engine->Time() ) @@ -275,7 +274,7 @@ void CBotTF2ShootLastEnemyPosition :: execute (CBot *pBot,CBotSchedule *pSchedu return; } - pChangeTo = pBot->getWeapons()->getWeapon(pChange); + CBotWeapon* pChangeTo = pBot->getWeapons()->getWeapon(pChange); if ( pChangeTo->getAmmo(pBot) < 1 ) { @@ -298,24 +297,22 @@ void CBotTF2ShootLastEnemyPosition :: execute (CBot *pBot,CBotSchedule *pSchedu } -void CBotTF2ShootLastEnemyPosition :: debugString ( char *string ) +void CBotTF2ShootLastEnemyPosition :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CBotTF2ShootLastEnemyPosition\nm_vPosition = (%0.4f,%0.4f,%0.4f)",m_vPosition.x,m_vPosition.y,m_vPosition.z); + std::sprintf(string,"CBotTF2ShootLastEnemyPosition\nm_vPosition = (%0.4f,%0.4f,%0.4f)",m_vPosition.x,m_vPosition.y,m_vPosition.z); } - ///////////// -CBotTF2WaitHealthTask :: CBotTF2WaitHealthTask ( Vector vOrigin ) +CBotTF2WaitHealthTask :: CBotTF2WaitHealthTask (const Vector& vOrigin) : m_vOrigin(vOrigin) { - m_vOrigin = vOrigin; - m_fWaitTime = 0; + m_fWaitTime = 0.0f; } void CBotTF2WaitHealthTask :: execute (CBot *pBot,CBotSchedule *pSchedule) { - if ( !m_fWaitTime ) - m_fWaitTime = engine->Time() + randomFloat(5.0f,10.0f); + if (m_fWaitTime == 0.0f) + m_fWaitTime = engine->Time() + randomFloat(5.0f, 10.0f); if ( !pBot->hasSomeConditions(CONDITION_NEED_HEALTH) ) complete(); @@ -323,7 +320,7 @@ void CBotTF2WaitHealthTask :: execute (CBot *pBot,CBotSchedule *pSchedule) fail(); else { - // TO DO + // TODO: /*edict_t *pOtherPlayer = CBotGlobals::findNearestPlayer(m_vOrigin,50.0,pBot->getEdict()); if ( pOtherPlayer ) @@ -335,36 +332,35 @@ void CBotTF2WaitHealthTask :: execute (CBot *pBot,CBotSchedule *pSchedule) pBot->setLookAtTask(LOOK_AROUND); if ( pBot->distanceFrom(m_vOrigin) > 50 ) - pBot->setMoveTo((m_vOrigin)); + pBot->setMoveTo(m_vOrigin); else pBot->stopMoving(); if ( pBot->isTF() ) { - ((CBotTF2*)pBot)->taunt(); + static_cast(pBot)->taunt(); - if ( ((CBotTF2*)pBot)->isBeingHealed() ) + if ( static_cast(pBot)->isBeingHealed() ) complete(); } } } -void CBotTF2WaitHealthTask :: debugString ( char *string ) +void CBotTF2WaitHealthTask :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CBotTF2WaitHealthTask\nm_vOrigin = (%0.4f,%0.4f,%0.4f)",m_vOrigin.x,m_vOrigin.y,m_vOrigin.z); + std::sprintf(string,"CBotTF2WaitHealthTask\nm_vOrigin = (%0.4f,%0.4f,%0.4f)",m_vOrigin.x,m_vOrigin.y,m_vOrigin.z); } -CBotTF2WaitFlagTask :: CBotTF2WaitFlagTask ( Vector vOrigin, bool bFind ) +CBotTF2WaitFlagTask :: CBotTF2WaitFlagTask (const Vector& vOrigin, const bool bFind) : m_vOrigin(vOrigin) { - m_vOrigin = vOrigin; - m_fWaitTime = 0; + m_fWaitTime = 0.0f; m_bFind = bFind; } void CBotTF2WaitFlagTask :: execute (CBot *pBot,CBotSchedule *pSchedule) { - if ( !m_fWaitTime ) + if (m_fWaitTime == 0.0f) { if ( m_bFind ) m_fWaitTime = engine->Time() + 5.0f; @@ -372,15 +368,15 @@ void CBotTF2WaitFlagTask :: execute (CBot *pBot,CBotSchedule *pSchedule) m_fWaitTime = engine->Time() + 10.0f; } - if ( ((CBotTF2*)pBot)->hasFlag() ) + if ( static_cast(pBot)->hasFlag() ) complete(); - else if ( pBot->getHealthPercent() < 0.2 ) + else if ( pBot->getHealthPercent() < 0.2f ) { fail(); } else if ( m_fWaitTime < engine->Time() ) { - ((CBotFortress*)pBot)->flagReset(); + static_cast(pBot)->flagReset(); fail(); } else if ( !pBot->isTF() ) @@ -389,29 +385,30 @@ void CBotTF2WaitFlagTask :: execute (CBot *pBot,CBotSchedule *pSchedule) } else { - if ( !((CBotFortress*)pBot)->waitForFlag(&m_vOrigin,&m_fWaitTime,m_bFind) ) + if ( !static_cast(pBot)->waitForFlag(&m_vOrigin,&m_fWaitTime,m_bFind) ) { fail(); } } } -void CBotTF2WaitFlagTask :: debugString ( char *string ) +void CBotTF2WaitFlagTask :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CBotTF2WaitFlagTask\nm_vOrigin = (%0.4f,%0.4f,%0.4f)",m_vOrigin.x,m_vOrigin.y,m_vOrigin.z); + std::sprintf(string,"CBotTF2WaitFlagTask\nm_vOrigin = (%0.4f,%0.4f,%0.4f)",m_vOrigin.x,m_vOrigin.y,m_vOrigin.z); } ////////// -CBotDODBomb :: CBotDODBomb ( int iBombType, int iBombID, edict_t *pBomb, Vector vPosition, int iPrevOwner ) +CBotDODBomb::CBotDODBomb(const int iBombType, const int iBombID, edict_t* m_pBomb, const Vector& vPosition, + const int iPrevOwner) : m_vOrigin(vPosition) { m_iType = iBombType; m_iBombID = iBombID; - m_fTime = 0; + m_fTime = 0.0f; if ( m_iBombID == -1 ) - m_iBombID = CDODMod::m_Flags.getBombID(pBomb); + m_iBombID = CDODMod::m_Flags.getBombID(m_pBomb); - m_pBombTarget = pBomb; - m_vOrigin = vPosition; + m_pBombTarget = m_pBomb; + m_iPrevTeam = iPrevOwner; } @@ -421,12 +418,12 @@ void CBotDODBomb :: execute (CBot *pBot,CBotSchedule *pSchedule) pBot->wantToShoot(false); - if ( m_fTime == 0 ) + if ( m_fTime == 0.0f ) { m_fTime = engine->Time() + randomFloat(8.0f,12.0f); - ((CDODBot*)pBot)->setNearestBomb(m_pBombTarget); + static_cast(pBot)->setNearestBomb(m_pBombTarget); - if ( (m_iType == DOD_BOMB_PLANT) || (m_iType == DOD_BOMB_PATH_PLANT) ) + if ( m_iType == DOD_BOMB_PLANT || m_iType == DOD_BOMB_PATH_PLANT ) { if ( CDODMod::m_Flags.isTeamMatePlanting(pBot->getEdict(),pBot->getTeam(),m_iBombID) ) fail(); @@ -480,7 +477,7 @@ void CBotDODBomb :: execute (CBot *pBot,CBotSchedule *pSchedule) complete(); } - else if ( CDODMod::m_Flags.isTeamMatePlanting(pBot->getEdict(),pBot->getTeam(),CBotGlobals::entityOrigin(m_pBombTarget)) ) + else if ( CDODFlags::isTeamMatePlanting(pBot->getEdict(),pBot->getTeam(),CBotGlobals::entityOrigin(m_pBombTarget)) ) complete(); // team mate doing my job } @@ -490,7 +487,7 @@ void CBotDODBomb :: execute (CBot *pBot,CBotSchedule *pSchedule) if ( CClassInterface::getDODBombState(m_pBombTarget) == DOD_BOMB_STATE_AVAILABLE ) complete(); - else if ( CDODMod::m_Flags.isTeamMateDefusing(pBot->getEdict(),pBot->getTeam(),CBotGlobals::entityOrigin(m_pBombTarget)) ) + else if ( CDODFlags::isTeamMateDefusing(pBot->getEdict(),pBot->getTeam(),CBotGlobals::entityOrigin(m_pBombTarget)) ) complete(); // team mate doing my job } @@ -510,24 +507,24 @@ void CBotDODBomb :: execute (CBot *pBot,CBotSchedule *pSchedule) } } -void CBotDODBomb :: debugString ( char *string ) +void CBotDODBomb :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CBotDODBomb\nm_iType = %d\nm_iBombID = %d\nm_fTime = %0.2f\nm_iPrevTeam = %d",m_iType, m_iBombID,m_fTime,m_iPrevTeam); + std::sprintf(string,"CBotDODBomb\nm_iType = %d\nm_iBombID = %d\nm_fTime = %0.2f\nm_iPrevTeam = %d",m_iType, m_iBombID,m_fTime,m_iPrevTeam); } ////// void CDODWaitForGrenadeTask :: execute (CBot *pBot,CBotSchedule *pSchedule) { - if ( m_pGrenade.get() == NULL ) + if ( m_pGrenade.get() == nullptr) { complete(); } else if ( !CBotGlobals::entityIsAlive(m_pGrenade) ) complete(); - else if ( m_fTime == 0 ) + else if ( m_fTime == 0.0f ) { - CDODBot *pDODBot = (CDODBot*)pBot; + CDODBot *pDODBot = static_cast(pBot); m_fTime = engine->Time() + randomFloat(3.0f,5.0f); @@ -535,7 +532,7 @@ void CDODWaitForGrenadeTask :: execute (CBot *pBot,CBotSchedule *pSchedule) } else if ( m_fTime < engine->Time() ) { - CDODBot *pDODBot = (CDODBot*)pBot; + CDODBot *pDODBot = static_cast(pBot); complete(); @@ -543,9 +540,9 @@ void CDODWaitForGrenadeTask :: execute (CBot *pBot,CBotSchedule *pSchedule) } } -void CDODWaitForGrenadeTask :: debugString ( char *string ) +void CDODWaitForGrenadeTask :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CDODWaitForGrenadeTask"); + std::sprintf(string,"CDODWaitForGrenadeTask"); } ////////// @@ -553,24 +550,24 @@ void CDODWaitForBombTask :: execute (CBot *pBot,CBotSchedule *pSchedule) { if ( m_fTime == 0.0f ) { - CWaypoint *pCurrent; pBot->updateCondition(CONDITION_RUN); - pCurrent = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(pBot->getOrigin(),400.0f,CWaypoints::getWaypointIndex(m_pBlocking),true,false,true)); + CWaypoint* pCurrent = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(pBot->getOrigin(), 400.0f, + CWaypoints::getWaypointIndex(m_pBlocking), true, false, true)); - if ( pCurrent == NULL ) + if ( pCurrent == nullptr) pCurrent = m_pBlocking; m_fTime = engine->Time() + randomFloat(2.0f,5.0f); m_pRunTo = CWaypoints::getNextCoverPoint(pBot,pCurrent,m_pBlocking) ; } - if ( m_pBombTarget.get() == NULL ) + if ( m_pBombTarget.get() == nullptr) { complete(); return; } - if ( m_pBombTarget.get()->GetUnknown() == NULL ) + if ( m_pBombTarget.get()->GetUnknown() == nullptr) { complete(); return; @@ -582,7 +579,7 @@ void CDODWaitForBombTask :: execute (CBot *pBot,CBotSchedule *pSchedule) { if (m_pRunTo->touched(pBot->getOrigin(),Vector(0,0,0),48.0f) ) { - if ( pBot->distanceFrom(m_pBombTarget) > (BLAST_RADIUS*2) ) + if ( pBot->distanceFrom(m_pBombTarget) > BLAST_RADIUS*2 ) pBot->stopMoving(); else m_pRunTo = CWaypoints::getNextCoverPoint(pBot,m_pRunTo,m_pBlocking) ; @@ -607,18 +604,18 @@ void CDODWaitForBombTask :: execute (CBot *pBot,CBotSchedule *pSchedule) pBot->setLookAtTask(LOOK_EDICT); } -void CDODWaitForBombTask :: debugString ( char *string ) +void CDODWaitForBombTask :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CDODWaitForBombTask"); + std::sprintf(string,"CDODWaitForBombTask"); } ////////// -CBotDODAttackPoint :: CBotDODAttackPoint ( int iFlagID, Vector vOrigin, float fRadius ) +CBotDODAttackPoint :: CBotDODAttackPoint (const int iFlagID, const Vector& vOrigin, const float fRadius) : m_vOrigin(vOrigin) { - m_vOrigin = vOrigin; - m_fAttackTime = 0; - m_fTime = 0; + m_bProne = false; + m_fAttackTime = 0.0f; + m_fTime = 0.0f; m_iFlagID = iFlagID; m_fRadius = fRadius; } @@ -637,10 +634,9 @@ void CBotDODAttackPoint :: execute (CBot *pBot,CBotSchedule *pSchedule) if ( pBot->inSquad() && pBot->isSquadLeader() ) { - float fDanger = MAX_BELIEF; IBotNavigator *pNav = pBot->getNavigator(); - fDanger = pNav->getBelief(CDODMod::m_Flags.getWaypointAtFlag(m_iFlagID)); + const float fDanger = pNav->getBelief(CDODMod::m_Flags.getWaypointAtFlag(m_iFlagID)); if ( randomFloat(0.0f,MAX_BELIEF) < fDanger ) { @@ -651,34 +647,33 @@ void CBotDODAttackPoint :: execute (CBot *pBot,CBotSchedule *pSchedule) return; } - else if ( m_fAttackTime == 0 ) + if ( m_fAttackTime == 0.0f ) { - m_fAttackTime = engine->Time() + randomFloat(30.0,60.0); + m_fAttackTime = engine->Time() + randomFloat(30.0f,60.0f); } else if ( m_fAttackTime < engine->Time() ) { complete(); - return; } else { - if ( m_fTime == 0 ) + if ( m_fTime == 0.0f ) { - m_fTime = engine->Time() + randomFloat(2.0,4.0); + m_fTime = engine->Time() + randomFloat(2.0f,4.0f); m_vMoveTo = m_vOrigin + Vector(randomFloat(-m_fRadius,m_fRadius),randomFloat(-m_fRadius,m_fRadius),0); - m_bProne = (randomFloat(0,1) * (1.0f-pBot->getHealthPercent())) > 0.75f; + m_bProne = randomFloat(0,1) * (1.0f-pBot->getHealthPercent()) > 0.75f; if ( CDODMod::m_Flags.numFriendliesAtCap(m_iFlagID,iTeam) < CDODMod::m_Flags.numCappersRequired(m_iFlagID,iTeam) ) { // count players I see - CDODBot *pDODBot = (CDODBot*)pBot; + CDODBot *pDODBot = static_cast(pBot); pDODBot->addVoiceCommand(DOD_VC_NEED_BACKUP); } } else if ( m_fTime < engine->Time() ) { - m_fTime = 0; + m_fTime = 0.0f; } else { @@ -694,7 +689,7 @@ void CBotDODAttackPoint :: execute (CBot *pBot,CBotSchedule *pSchedule) pBot->stopMoving(); pBot->setLookAtTask(LOOK_AROUND); } - else if ( fdist > 400 ) + else if ( fdist > 400.0f ) fail(); else { @@ -704,34 +699,34 @@ void CBotDODAttackPoint :: execute (CBot *pBot,CBotSchedule *pSchedule) } } -void CBotDODAttackPoint :: debugString ( char *string ) +void CBotDODAttackPoint :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CBotDODAttackPoint\nm_iFlagID = %d\n m_vOrigin = (%0.1f,%0.1f,%0.1f,radius = %0.1f)",m_iFlagID,m_vOrigin.x,m_vOrigin.y,m_vOrigin.z,m_fRadius); + std::sprintf(string, "CBotDODAttackPoint\nm_iFlagID = %d\n m_vOrigin = (%0.1f,%0.1f,%0.1f,radius = %0.1f)", m_iFlagID, + m_vOrigin.x, m_vOrigin.y, m_vOrigin.z, m_fRadius); } /////////// -CBotTF2AttackPoint :: CBotTF2AttackPoint ( int iArea, Vector vOrigin, int iRadius ) +CBotTF2AttackPoint :: CBotTF2AttackPoint (const int iArea, const Vector& vOrigin, const float fRadius) : m_vOrigin(vOrigin) { - m_vOrigin = vOrigin; - m_fAttackTime = 0; - m_fTime = 0; + m_fAttackTime = 0.0f; + m_fTime = 0.0f; m_iArea = iArea; - m_iRadius = iRadius; + m_fRadius = fRadius; } void CBotTF2AttackPoint :: execute (CBot *pBot,CBotSchedule *pSchedule) { - int iCpIndex = CTeamFortress2Mod::m_ObjectiveResource.m_WaypointAreaToIndexTranslation[m_iArea]; - int iTeam = pBot->getTeam(); - CBotTF2 *pTF2Bot = (CBotTF2*)pBot; + const int iCpIndex = CTeamFortress2Mod::m_ObjectiveResource.m_WaypointAreaToIndexTranslation[m_iArea]; + const int iTeam = pBot->getTeam(); + CBotTF2 *pTF2Bot = static_cast(pBot); if ( CTeamFortress2Mod::TF2_IsPlayerInvuln(pBot->getEdict()) ) fail(); pBot->wantToInvestigateSound(false); - if ( m_iArea && (CTeamFortress2Mod::m_ObjectiveResource.GetOwningTeam(iCpIndex) == iTeam) ) + if ( m_iArea && CTeamFortress2Mod::m_ObjectiveResource.GetOwningTeam(iCpIndex) == iTeam ) { complete(); // done pTF2Bot->updateAttackDefendPoints(); @@ -741,21 +736,21 @@ void CBotTF2AttackPoint :: execute (CBot *pBot,CBotSchedule *pSchedule) fail(); // too slow pTF2Bot->updateAttackDefendPoints(); } - else if ( m_fAttackTime == 0 ) - m_fAttackTime = engine->Time() + randomFloat(30.0,60.0); + else if ( m_fAttackTime == 0.0f ) + m_fAttackTime = engine->Time() + randomFloat(30.0f,60.0f); else if ( m_fAttackTime < engine->Time() ) complete(); else { - if ( m_fTime == 0 ) + if ( m_fTime == 0.0f ) { - m_fTime = engine->Time() + randomFloat(5.0,10.0); - m_vMoveTo = m_vOrigin + Vector(randomFloat(-m_iRadius,m_iRadius),randomFloat(-m_iRadius,m_iRadius),0); + m_fTime = engine->Time() + randomFloat(5.0f,10.0f); + m_vMoveTo = m_vOrigin + Vector(randomFloat(-m_fRadius,m_fRadius),randomFloat(-m_fRadius,m_fRadius),0); } else if ( m_fTime < engine->Time() ) { - m_fTime = 0; + m_fTime = 0.0f; } else { @@ -785,28 +780,28 @@ void CBotTF2AttackPoint :: execute (CBot *pBot,CBotSchedule *pSchedule) } - if ( fdist < 52 ) + if ( fdist < 52.0f ) { pBot->stopMoving(); } - else if ( fdist > 400 ) + else if ( fdist > 400.0f ) fail(); else { - pBot->setMoveTo((m_vMoveTo)); + pBot->setMoveTo(m_vMoveTo); } pBot->setLookAtTask(LOOK_AROUND); - if ( ((CBotTF2*)pBot)->checkAttackPoint() ) + if ( static_cast(pBot)->checkAttackPoint() ) complete(); } } } -void CBotTF2AttackPoint :: debugString ( char *string ) +void CBotTF2AttackPoint :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CBotTF2AttackPoint (%d,%0.1f,%0.1f,%0.1f,%d)",m_iArea,m_vOrigin.x,m_vOrigin.y,m_vOrigin.z,m_iRadius); + std::sprintf(string,"CBotTF2AttackPoint (%d,%0.1f,%0.1f,%0.1f,%f)",m_iArea,m_vOrigin.x,m_vOrigin.y,m_vOrigin.z,m_fRadius); } //////////////////////// @@ -816,13 +811,33 @@ void CPrimaryAttack:: execute ( CBot *pBot, CBotSchedule *pSchedule ) complete(); } +void CBotWaitTask::execute ( CBot *pBot, CBotSchedule *pSchedule ) +{ + pBot->stopMoving(); + + if(m_bAimSet) + { + pBot->setLookVector(m_vAim); + pBot->setLookAtTask(LOOK_VECTOR); + } + + if(engine->Time() >= m_fTime) + { + complete(); + } +} + +void CBotWaitTask::debugString(char* string, unsigned bufferSize) +{ + std::sprintf(string,"CBotWaitTask (%.1f)",m_fTime - engine->Time()); +} + //////////////////////////// -CBotTF2PushPayloadBombTask :: CBotTF2PushPayloadBombTask (edict_t * pPayloadBomb) +CBotTF2PushPayloadBombTask :: CBotTF2PushPayloadBombTask (edict_t * pPayloadBomb) : m_pPayloadBomb(pPayloadBomb) { - m_pPayloadBomb = pPayloadBomb; - m_fPushTime = 0; - m_fTime = 0; + m_fPushTime = 0.0f; + m_fTime = 0.0f; m_vRandomOffset = Vector(0,0,0); } @@ -830,19 +845,18 @@ void CBotTF2PushPayloadBombTask :: execute (CBot *pBot,CBotSchedule *pSchedule) { pBot->wantToInvestigateSound(false); - if ( m_fPushTime == 0 ) + if ( m_fPushTime == 0.0f ) { - m_fPushTime = engine->Time() + randomFloat(10.0,30.0); + m_fPushTime = engine->Time() + randomFloat(10.0f,30.0f); m_vRandomOffset = Vector(randomFloat(-50,50),randomFloat(-50,50),0); } else if ( m_fPushTime < engine->Time() ) { complete(); } - else if(m_pPayloadBomb.get() == NULL) + else if(m_pPayloadBomb.get() == nullptr) { complete(); - return; } else { @@ -853,10 +867,10 @@ void CBotTF2PushPayloadBombTask :: execute (CBot *pBot,CBotSchedule *pSchedule) if ( pBot->distanceFrom(m_vMoveTo) < 100 ) { - if ( (((CBotTF2*)pBot)->getClass() == TF_CLASS_SPY) && (((CBotTF2*)pBot)->isDisguised())) + if ( static_cast(pBot)->getClass() == TF_CLASS_SPY && static_cast(pBot)->isDisguised()) pBot->primaryAttack(); // remove disguise to capture - ((CBotFortress*)pBot)->wantToDisguise(false); + static_cast(pBot)->wantToDisguise(false); } else @@ -864,26 +878,24 @@ void CBotTF2PushPayloadBombTask :: execute (CBot *pBot,CBotSchedule *pSchedule) pBot->setLookAtTask(LOOK_AROUND); } - } -void CBotTF2PushPayloadBombTask :: debugString ( char *string ) +void CBotTF2PushPayloadBombTask :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CBotTF2PushPayloadBombTask (%0.1f,%0.1f,%0.1f)",m_vOrigin.x,m_vOrigin.y,m_vOrigin.z); + std::sprintf(string,"CBotTF2PushPayloadBombTask (%0.1f,%0.1f,%0.1f)",m_vOrigin.x,m_vOrigin.y,m_vOrigin.z); } //////////////////////////////////////////////////////////////////////// -CBotTF2DefendPayloadBombTask :: CBotTF2DefendPayloadBombTask (edict_t * pPayloadBomb) +CBotTF2DefendPayloadBombTask :: CBotTF2DefendPayloadBombTask (edict_t * pPayloadBomb) : m_pPayloadBomb(pPayloadBomb) { - m_pPayloadBomb = pPayloadBomb; - m_fDefendTime = 0; - m_fTime = 0; + m_fDefendTime = 0.0f; + m_fTime = 0.0f; m_vRandomOffset = Vector(0,0,0); } void CBotTF2DefendPayloadBombTask :: execute (CBot *pBot,CBotSchedule *pSchedule) { - if ( m_fDefendTime == 0 ) + if ( m_fDefendTime == 0.0f ) { m_fDefendTime = engine->Time() + randomFloat(10.0f,30.0f); m_vRandomOffset = Vector(randomFloat(-150.0f,150.0f),randomFloat(-150.0f,150.0f),0); @@ -892,10 +904,9 @@ void CBotTF2DefendPayloadBombTask :: execute (CBot *pBot,CBotSchedule *pSchedule { complete(); } - else if(m_pPayloadBomb.get() == NULL) + else if(m_pPayloadBomb.get() == nullptr) { complete(); - return; } else { @@ -913,52 +924,49 @@ void CBotTF2DefendPayloadBombTask :: execute (CBot *pBot,CBotSchedule *pSchedule } -void CBotTF2DefendPayloadBombTask :: debugString ( char *string ) +void CBotTF2DefendPayloadBombTask :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CBotTF2DefendPayloadBombTask (%0.1f,%0.1f,%0.1f)",m_vOrigin.x,m_vOrigin.y,m_vOrigin.z); + std::sprintf(string,"CBotTF2DefendPayloadBombTask (%0.1f,%0.1f,%0.1f)",m_vOrigin.x,m_vOrigin.y,m_vOrigin.z); } ////////////////////// -CBotTF2DefendPoint :: CBotTF2DefendPoint ( int iArea, Vector vOrigin, int iRadius ) +CBotTF2DefendPoint :: CBotTF2DefendPoint (const int iArea, const Vector& vOrigin, const float fRadius) : m_vOrigin(vOrigin) { - m_vOrigin = vOrigin; - m_fDefendTime = 0; - m_fTime = 0; + m_fDefendTime = 0.0f; + m_fTime = 0.0f; m_iArea = iArea; - m_iRadius = iRadius; + m_fRadius = fRadius; } -void CBotTF2DefendPoint :: execute (CBot *pBot,CBotSchedule *pSchedule) +void CBotTF2DefendPoint :: execute (CBot *pBot, CBotSchedule *pSchedule) { - int iCpIndex = CTeamFortress2Mod::m_ObjectiveResource.m_WaypointAreaToIndexTranslation[m_iArea]; - int iTeam = pBot->getTeam(); + const int iCpIndex = CTeamFortress2Mod::m_ObjectiveResource.m_WaypointAreaToIndexTranslation[m_iArea]; + const int iTeam = pBot->getTeam(); - if ( m_iArea && (CTeamFortress2Mod::m_ObjectiveResource.GetOwningTeam(iCpIndex) != iTeam) ) + if ( m_iArea && CTeamFortress2Mod::m_ObjectiveResource.GetOwningTeam(iCpIndex) != iTeam ) { // doesn't belong to us/can't defend anymore - ((CBotTF2*)pBot)->updateAttackDefendPoints(); + static_cast(pBot)->updateAttackDefendPoints(); complete(); // done } else if ( m_iArea && !CTeamFortress2Mod::m_ObjectiveResource.isCPValid(iCpIndex,iTeam,TF2_POINT_DEFEND) ) { - ((CBotTF2*)pBot)->updateAttackDefendPoints(); + static_cast(pBot)->updateAttackDefendPoints(); fail(); // too slow } - else if ( m_fDefendTime == 0 ) + else if ( m_fDefendTime == 0.0f ) { - m_fDefendTime = engine->Time() + randomFloat(30.0,60.0); + m_fDefendTime = engine->Time() + randomFloat(30.0f,60.0f); pBot->resetLookAroundTime(); } else if ( m_fDefendTime < engine->Time() ) complete(); else { - if ( m_fTime == 0 ) + if ( m_fTime == 0.0f ) { - float fdist; - - m_fTime = engine->Time() + randomFloat(5.0,10.0); - m_vMoveTo = m_vOrigin + Vector(randomFloat(-m_iRadius,m_iRadius),randomFloat(-m_iRadius,m_iRadius),0); - fdist = pBot->distanceFrom(m_vMoveTo); + m_fTime = engine->Time() + randomFloat(5.0f,10.0f); + m_vMoveTo = m_vOrigin + Vector(randomFloat(-m_fRadius,m_fRadius),randomFloat(-m_fRadius,m_fRadius),0); + const float fdist = pBot->distanceFrom(m_vMoveTo); if ( fdist < 32 ) pBot->stopMoving(); @@ -971,50 +979,48 @@ void CBotTF2DefendPoint :: execute (CBot *pBot,CBotSchedule *pSchedule) } else if ( m_fTime < engine->Time() ) { - m_fTime = 0; + m_fTime = 0.0f; } pBot->setLookAtTask(LOOK_SNIPE); } } -void CBotTF2DefendPoint :: debugString ( char *string ) +void CBotTF2DefendPoint :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CBotTF2DefendPoint\nm_iArea=%d\nm_vOrigin=(%0.1f,%0.1f,%0.1f,%d)",m_iArea,m_vOrigin.x,m_vOrigin.y,m_vOrigin.z,m_iRadius); + std::sprintf(string, "CBotTF2DefendPoint\nm_iArea=%d\nm_vOrigin=(%0.1f,%0.1f,%0.1f,%f)", m_iArea, + m_vOrigin.x, m_vOrigin.y, m_vOrigin.z, m_fRadius); } /////////// -CBotTF2UpgradeBuilding :: CBotTF2UpgradeBuilding ( edict_t *pBuilding ) +CBotTF2UpgradeBuilding :: CBotTF2UpgradeBuilding ( edict_t *pBuilding ) : m_pBuilding(pBuilding) { - m_pBuilding = pBuilding; m_fTime = 0.0f; } -void CBotTF2UpgradeBuilding :: execute (CBot *pBot,CBotSchedule *pSchedule) +void CBotTF2UpgradeBuilding :: execute (CBot *pBot, CBotSchedule *pSchedule) { edict_t *pBuilding = m_pBuilding.get(); - edict_t *pOwner = NULL; + edict_t *pOwner; pBot->wantToShoot(false); pBot->wantToInvestigateSound(false); pBot->wantToListen(false); - if (!m_fTime ) + if (m_fTime == 0.0f) m_fTime = engine->Time() + randomFloat(9.0f,11.0f); if ( m_fTimeTime() ) { complete(); }// Fix 16/07/09 - else if ( pBuilding == NULL ) + else if ( pBuilding == nullptr) { fail(); - return; } - else if ( ((pOwner = CTeamFortress2Mod::getSentryOwner(pBuilding)) != NULL) && - CClassInterface::isCarryingObj(pOwner) && (CClassInterface::getCarriedObj(pOwner)==pBuilding)) + else if ( (pOwner = CTeamFortress2Mod::getSentryOwner(pBuilding)) != nullptr && + CClassInterface::isCarryingObj(pOwner) && CClassInterface::getCarriedObj(pOwner)==pBuilding) { // Owner is carrying it fail(); - return; } else if ( !pBot->isVisible(pBuilding) ) { @@ -1028,23 +1034,23 @@ void CBotTF2UpgradeBuilding :: execute (CBot *pBot,CBotSchedule *pSchedule) } else if ( CBotGlobals::entityIsValid(pBuilding) && CBotGlobals::entityIsAlive(pBuilding) ) { - if ( !((CBotFortress*)pBot)->upgradeBuilding(pBuilding) ) + if ( !static_cast(pBot)->upgradeBuilding(pBuilding) ) fail(); } else fail(); } -void CBotTF2UpgradeBuilding:: debugString ( char *string ) +void CBotTF2UpgradeBuilding:: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CBotTF2UpgradeBuilding"); + std::sprintf(string,"CBotTF2UpgradeBuilding"); } -void CBotHL2DMUseButton :: execute (CBot *pBot,CBotSchedule *pSchedule) +void CBotHL2DMUseButton :: execute (CBot *pBot, CBotSchedule *pSchedule) { static Vector vOrigin; - if ( m_pButton.get() == NULL ) + if ( m_pButton.get() == nullptr) { fail(); return; @@ -1063,8 +1069,19 @@ void CBotHL2DMUseButton :: execute (CBot *pBot,CBotSchedule *pSchedule) //if ( CClassInterface::getAnimCycle(m_pCharger) == 1.0f ) // complete(); - pBot->setLookVector(vOrigin); - pBot->setLookAtTask(LOOK_VECTOR); + if(m_bOverrideLook) + { + pBot->setMoveLookPriority(MOVELOOK_OVERRIDE); + pBot->setLookVector(vOrigin); + pBot->setLookAtTask(LOOK_VECTOR); + pBot->setMoveLookPriority(MOVELOOK_TASK); + } + else + { + pBot->setLookVector(vOrigin); + pBot->setLookAtTask(LOOK_VECTOR); + } + if ( pBot->distanceFrom(m_pButton) > 96 ) { @@ -1077,11 +1094,11 @@ void CBotHL2DMUseButton :: execute (CBot *pBot,CBotSchedule *pSchedule) } } -void CBotHL2DMUseCharger :: execute (CBot *pBot,CBotSchedule *pSchedule) +void CBotHL2DMUseCharger :: execute (CBot *pBot, CBotSchedule *pSchedule) { static Vector vOrigin; - if ( m_pCharger.get() == NULL ) + if ( m_pCharger.get() == nullptr) { fail(); return; @@ -1100,9 +1117,9 @@ void CBotHL2DMUseCharger :: execute (CBot *pBot,CBotSchedule *pSchedule) if ( CClassInterface::getAnimCycle(m_pCharger) == 1.0f ) complete(); - if ( ( m_iType == CHARGER_HEALTH ) && ( pBot->getHealthPercent() >= 0.99f ) ) + if ( m_iType == CHARGER_HEALTH && pBot->getHealthPercent() >= 0.99f ) complete(); - else if ( ( m_iType == CHARGER_ARMOR ) && ( ((CHLDMBot*)pBot)->getArmorPercent() >= 0.99f ) ) + else if ( m_iType == CHARGER_ARMOR && static_cast(pBot)->getArmorPercent() >= 0.99f ) complete(); pBot->setLookVector(vOrigin); @@ -1118,22 +1135,22 @@ void CBotHL2DMUseCharger :: execute (CBot *pBot,CBotSchedule *pSchedule) } } -void CBotGravGunPickup :: execute(CBot *pBot,CBotSchedule *pSchedule) +void CBotGravGunPickup :: execute(CBot *pBot, CBotSchedule *pSchedule) { static Vector vOrigin; static Vector vBotOrigin; if ( m_fTime == 0.0f ) { - m_fSecAttTime = 0; + m_fSecAttTime = 0.0f; m_fTime = engine->Time() + randomFloat(2.0f,4.0f); } if ( m_fTime < engine->Time() ) { - CHLDMBot *HL2DMBot = ((CHLDMBot*)pBot); + CHLDMBot* const HL2DMBot = static_cast(pBot); - if (HL2DMBot->getFailedObject() && (HL2DMBot->distanceFrom(HL2DMBot->getFailedObject())<=(pBot->distanceFrom(m_Prop)+48)) ) + if (HL2DMBot->getFailedObject() && HL2DMBot->distanceFrom(HL2DMBot->getFailedObject())<=pBot->distanceFrom(m_Prop)+48 ) pBot->primaryAttack(); HL2DMBot->setFailedObject(m_Prop); @@ -1144,7 +1161,7 @@ void CBotGravGunPickup :: execute(CBot *pBot,CBotSchedule *pSchedule) if ( !CBotGlobals::entityIsValid(m_Prop) || !pBot->isVisible(m_Prop) ) { - ((CHLDMBot*)pBot)->setFailedObject(m_Prop); + static_cast(pBot)->setFailedObject(m_Prop); fail(); return; } @@ -1154,9 +1171,9 @@ void CBotGravGunPickup :: execute(CBot *pBot,CBotSchedule *pSchedule) vBotOrigin = pBot->getOrigin(); vOrigin = CBotGlobals::entityOrigin(m_Prop); - CBotWeapon *pWeapon = pBot->getCurrentWeapon(); + const CBotWeapon *pWeapon = pBot->getCurrentWeapon(); - if ( !pWeapon || ( pWeapon->getID() != HL2DM_WEAPON_PHYSCANNON) ) + if ( !pWeapon || pWeapon->getID() != HL2DM_WEAPON_PHYSCANNON ) { if ( !pBot->select_CWeapon(CWeapons::getWeapon(HL2DM_WEAPON_PHYSCANNON)) ) { @@ -1166,7 +1183,7 @@ void CBotGravGunPickup :: execute(CBot *pBot,CBotSchedule *pSchedule) } else if ( pBot->distanceFrom(vOrigin) > 100 ) pBot->setMoveTo(vOrigin); - else if ( ((vOrigin-vBotOrigin).Length2D() < 16) && (vOrigin.z < vBotOrigin.z) ) + else if ( (vOrigin-vBotOrigin).Length2D() < 16 && vOrigin.z < vBotOrigin.z ) pBot->setMoveTo(vBotOrigin + (vBotOrigin-vOrigin)*100); else pBot->stopMoving(); @@ -1186,7 +1203,7 @@ void CBotGravGunPickup :: execute(CBot *pBot,CBotSchedule *pSchedule) if ( pBot->isFacing(vOrigin) ) { - edict_t *pPhys = CClassInterface::gravityGunObject(m_Weapon); + const edict_t *pPhys = CClassInterface::gravityGunObject(m_Weapon); if ( pPhys == m_Prop.get() ) complete(); @@ -1195,7 +1212,7 @@ void CBotGravGunPickup :: execute(CBot *pBot,CBotSchedule *pSchedule) if ( m_fSecAttTime < engine->Time() ) { pBot->secondaryAttack(); - m_fSecAttTime = engine->Time() + randomFloat(0.25,0.75); + m_fSecAttTime = engine->Time() + randomFloat(0.25f,0.75f); } } } @@ -1269,15 +1286,14 @@ void CBotTFEngiTankSentry :: execute (CBot *pBot,CBotSchedule *pSchedule) //////////////////////// -CBotTF2WaitAmmoTask :: CBotTF2WaitAmmoTask ( Vector vOrigin ) +CBotTF2WaitAmmoTask :: CBotTF2WaitAmmoTask (const Vector& vOrigin) : m_vOrigin(vOrigin) { - m_vOrigin = vOrigin; m_fWaitTime = 0.0f; } -void CBotTF2WaitAmmoTask :: execute (CBot *pBot,CBotSchedule *pSchedule) +void CBotTF2WaitAmmoTask :: execute (CBot *pBot, CBotSchedule *pSchedule) { - if ( !m_fWaitTime ) + if(m_fWaitTime == 0.0f) m_fWaitTime = engine->Time() + randomFloat(5.0f,10.0f); if ( !pBot->hasSomeConditions(CONDITION_NEED_AMMO) ) @@ -1296,20 +1312,19 @@ void CBotTF2WaitAmmoTask :: execute (CBot *pBot,CBotSchedule *pSchedule) } } -void CBotTF2WaitAmmoTask :: debugString ( char *string ) +void CBotTF2WaitAmmoTask :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CBotTF2WaitAmmoTask"); + std::sprintf(string,"CBotTF2WaitAmmoTask"); } /////////////////////////// -CBotTaskEngiPickupBuilding :: CBotTaskEngiPickupBuilding ( edict_t *pBuilding ) +CBotTaskEngiPickupBuilding::CBotTaskEngiPickupBuilding (edict_t *pBuilding) : m_pBuilding(pBuilding) { - m_pBuilding = pBuilding; m_fTime = 0.0f; } // move building / move sentry / move disp / move tele void CBotTaskEngiPickupBuilding :: execute (CBot *pBot,CBotSchedule *pSchedule) { - CBotWeapon *pWeapon = pBot->getCurrentWeapon(); + const CBotWeapon *pWeapon = pBot->getCurrentWeapon(); if ( m_fTime == 0.0f ) m_fTime = engine->Time() + 6.0f; @@ -1321,7 +1336,7 @@ void CBotTaskEngiPickupBuilding :: execute (CBot *pBot,CBotSchedule *pSchedule) } // don't pick up sentry now because my sentry is in good use!!! - if ( ((CBotTF2*)pBot)->sentryRecentlyHadEnemy() ) + if ( static_cast(pBot)->sentryRecentlyHadEnemy() ) { fail(); return; @@ -1331,9 +1346,9 @@ void CBotTaskEngiPickupBuilding :: execute (CBot *pBot,CBotSchedule *pSchedule) pBot->lookAtEdict(m_pBuilding.get()); pBot->setLookAtTask(LOOK_EDICT); - ((CBotTF2*)pBot)->updateCarrying(); + static_cast(pBot)->updateCarrying(); - if ( ((CBotTF2*)pBot)->isCarrying() ) //if ( CBotGlobals::entityOrigin(m_pBuilding) == CBotGlobals::entityOrigin(pBot->getEdict()) ) + if ( static_cast(pBot)->isCarrying() ) //if ( CBotGlobals::entityOrigin(m_pBuilding) == CBotGlobals::entityOrigin(pBot->getEdict()) ) complete(); else if ( m_fTime < engine->Time() ) fail(); @@ -1353,21 +1368,20 @@ void CBotTaskEngiPickupBuilding :: execute (CBot *pBot,CBotSchedule *pSchedule) else pBot->letGoOfButton(IN_ATTACK2); - ((CBotTF2*)pBot)->resetCarryTime(); + static_cast(pBot)->resetCarryTime(); } } else - pBot->setMoveTo((CBotGlobals::entityOrigin(m_pBuilding))); + pBot->setMoveTo(CBotGlobals::entityOrigin(m_pBuilding)); } -void CBotTaskEngiPickupBuilding :: debugString ( char *string ) +void CBotTaskEngiPickupBuilding :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CBotTaskEngiPickupBuilding"); + std::sprintf(string,"CBotTaskEngiPickupBuilding"); } ///////////////// -CBotTaskEngiPlaceBuilding :: CBotTaskEngiPlaceBuilding ( eEngiBuild iObject, Vector vOrigin ) +CBotTaskEngiPlaceBuilding :: CBotTaskEngiPlaceBuilding (const eEngiBuild iObject, const Vector& vOrigin) : m_vOrigin(vOrigin) { - m_vOrigin = vOrigin; m_fTime = 0.0f; m_iState = 1; // BEGIN HERE , otherwise bot will try to destroy the building m_iObject = iObject; @@ -1391,17 +1405,17 @@ void CBotTaskEngiPlaceBuilding :: execute (CBot *pBot,CBotSchedule *pSchedule) pBot->setLookVector(m_vOrigin); pBot->setLookAtTask(LOOK_VECTOR); - ((CBotTF2*)pBot)->updateCarrying(); + static_cast(pBot)->updateCarrying(); - if ( !(((CBotTF2*)pBot)->isCarrying()) ) + if ( !static_cast(pBot)->isCarrying() ) complete(); else if ( m_fTime < engine->Time() ) fail(); else if ( pBot->distanceFrom(m_vOrigin) < 100 ) { if ( CBotGlobals::yawAngleFromEdict(pBot->getEdict(),m_vOrigin) < 25 ) - { - int state = ((CBotTF2*)pBot)->engiBuildObject(&m_iState,m_iObject,&m_fTime,&m_iTries); + { + const int state = static_cast(pBot)->engiBuildObject(&m_iState,m_iObject,&m_fTime,&m_iTries); if ( state == 1 ) complete(); @@ -1420,9 +1434,9 @@ void CBotTaskEngiPlaceBuilding :: execute (CBot *pBot,CBotSchedule *pSchedule) pBot->primaryAttack(); } } -void CBotTaskEngiPlaceBuilding :: debugString ( char *string ) +void CBotTaskEngiPlaceBuilding :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CBotTaskEngiPlaceBuilding"); + std::sprintf(string,"CBotTaskEngiPlaceBuilding"); } ///////////////////////////// CBotUseLunchBoxDrink::CBotUseLunchBoxDrink() @@ -1431,17 +1445,15 @@ CBotUseLunchBoxDrink::CBotUseLunchBoxDrink() } void CBotUseBuffItem::execute(CBot *pBot, CBotSchedule *pSchedule) { - CBotWeapon *pWeapon; - pBot->wantToShoot(false); pBot->wantToChangeWeapon(false); - if (m_fTime == 0) + if (m_fTime == 0.0f) m_fTime = engine->Time() + 5.0f; else if (m_fTime < engine->Time()) fail(); - pWeapon = pBot->getCurrentWeapon(); + const CBotWeapon* pWeapon = pBot->getCurrentWeapon(); if (CClassInterface::getRageMeter(pBot->getEdict()) < 100.0f) { @@ -1449,7 +1461,7 @@ void CBotUseBuffItem::execute(CBot *pBot, CBotSchedule *pSchedule) return; } - if (!pWeapon || (pWeapon->getID() != TF2_WEAPON_BUFF_ITEM)) + if (!pWeapon || pWeapon->getID() != TF2_WEAPON_BUFF_ITEM) { if (!pBot->select_CWeapon(CWeapons::getWeapon(TF2_WEAPON_BUFF_ITEM))) fail(); @@ -1467,17 +1479,15 @@ CBotUseBuffItem :: CBotUseBuffItem () } void CBotUseLunchBoxDrink::execute(CBot *pBot, CBotSchedule *pSchedule) { - CBotWeapon *pWeapon; - pBot->wantToShoot(false); pBot->wantToChangeWeapon(false); - if ( m_fTime == 0 ) + if ( m_fTime == 0.0f ) m_fTime = engine->Time() + 5.0f; else if ( m_fTime < engine->Time() ) fail(); - pWeapon = pBot->getCurrentWeapon(); + const CBotWeapon* pWeapon = pBot->getCurrentWeapon(); if ( CClassInterface::TF2_getEnergyDrinkMeter(pBot->getEdict()) < 100.0f ) { @@ -1485,7 +1495,7 @@ void CBotUseLunchBoxDrink::execute(CBot *pBot, CBotSchedule *pSchedule) return; } - if ( !pWeapon || (pWeapon->getID() != TF2_WEAPON_LUNCHBOX_DRINK) ) + if ( !pWeapon || pWeapon->getID() != TF2_WEAPON_LUNCHBOX_DRINK ) { if (!pBot->select_CWeapon(CWeapons::getWeapon(TF2_WEAPON_LUNCHBOX_DRINK))) fail(); @@ -1497,25 +1507,21 @@ void CBotUseLunchBoxDrink::execute(CBot *pBot, CBotSchedule *pSchedule) } } ///////////////////////////// -CBotBackstab :: CBotBackstab (edict_t *_pEnemy) +CBotBackstab :: CBotBackstab (edict_t *_pEnemy) : pEnemy(_pEnemy) { m_fTime = 0.0f; - pEnemy = _pEnemy; } void CBotBackstab ::execute (CBot *pBot,CBotSchedule *pSchedule) { - Vector vrear; Vector vangles; - CBotWeapon *pBotWeapon; - CWeapon *pWeapon; - CBotTF2 *pTF2Bot = (CBotTF2*)pBot; + CBotTF2 *pTF2Bot = static_cast(pBot); pBot->wantToChangeWeapon(false); pBot->wantToShoot(false); pBot->wantToListen(false); - pBotWeapon = pBot->getCurrentWeapon(); + CBotWeapon* pBotWeapon = pBot->getCurrentWeapon(); if ( !pBotWeapon ) { @@ -1524,9 +1530,9 @@ void CBotBackstab ::execute (CBot *pBot,CBotSchedule *pSchedule) return; } - pWeapon = pBotWeapon->getWeaponInfo(); + const CWeapon* pWeapon = pBotWeapon->getWeaponInfo(); - if (pWeapon == NULL) + if (pWeapon == nullptr) { fail(); pTF2Bot->waitBackstab(); @@ -1536,7 +1542,7 @@ void CBotBackstab ::execute (CBot *pBot,CBotSchedule *pSchedule) if ( !CBotGlobals::isAlivePlayer(pEnemy) ) fail(); - if ( !m_fTime ) + if (m_fTime == 0.0f) m_fTime = engine->Time() + randomFloat(5.0f,10.0f); pBot->setLookAtTask(LOOK_EDICT); @@ -1548,9 +1554,9 @@ void CBotBackstab ::execute (CBot *pBot,CBotSchedule *pSchedule) pTF2Bot->waitBackstab(); return; } - else if ( !pEnemy || !CBotGlobals::entityIsValid(pEnemy) || !CBotGlobals::entityIsAlive(pEnemy) ) + if ( !pEnemy || !CBotGlobals::entityIsValid(pEnemy) || !CBotGlobals::entityIsAlive(pEnemy) ) { - if ( pBot->getEnemy() && (pEnemy != pBot->getEnemy()) && pBot->hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && CBotGlobals::isAlivePlayer(pBot->getEnemy()) ) + if ( pBot->getEnemy() && pEnemy != pBot->getEnemy() && pBot->hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && CBotGlobals::isAlivePlayer(pBot->getEnemy()) ) { pEnemy = pBot->getEnemy(); } @@ -1562,10 +1568,10 @@ void CBotBackstab ::execute (CBot *pBot,CBotSchedule *pSchedule) pTF2Bot->waitBackstab(); return; } - else if ( !pBot->isVisible(pEnemy) ) + if ( !pBot->isVisible(pEnemy) ) { // this guy will do - if ( pBot->getEnemy() && (pEnemy != pBot->getEnemy()) && pBot->hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && CBotGlobals::isAlivePlayer(pBot->getEnemy()) ) + if ( pBot->getEnemy() && pEnemy != pBot->getEnemy() && pBot->hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && CBotGlobals::isAlivePlayer(pBot->getEnemy()) ) { pEnemy = pBot->getEnemy(); } @@ -1577,7 +1583,7 @@ void CBotBackstab ::execute (CBot *pBot,CBotSchedule *pSchedule) pTF2Bot->waitBackstab(); return; } - else if (pWeapon->getID() != TF2_WEAPON_KNIFE) + if (pWeapon->getID() != TF2_WEAPON_KNIFE) { if ( !pBot->select_CWeapon(CWeapons::getWeapon(TF2_WEAPON_KNIFE)) ) { @@ -1586,9 +1592,10 @@ void CBotBackstab ::execute (CBot *pBot,CBotSchedule *pSchedule) return; } } - + AngleVectors(CBotGlobals::entityEyeAngles(pEnemy),&vangles); - vrear = CBotGlobals::entityOrigin(pEnemy) - (vangles * 45) + Vector(0,0,32); + constexpr int Z_OFFSET = 32; + const Vector vrear = CBotGlobals::entityOrigin(pEnemy) - vangles * 45 + Vector(0, 0, Z_OFFSET); pTF2Bot->resetAttackingEnemy(); @@ -1608,11 +1615,11 @@ void CBotBackstab ::execute (CBot *pBot,CBotSchedule *pSchedule) void CBotInvestigateTask :: execute (CBot *pBot,CBotSchedule *pSchedule) { - if ( m_fTime == 0 ) + if ( m_fTime == 0.0f ) { - CWaypoint *pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(m_vOrigin,m_fRadius,-1)); + const CWaypoint *pWaypoint = CWaypoints::getWaypoint(CWaypointLocations::NearestWaypoint(m_vOrigin,m_fRadius,-1)); - if ( pWaypoint == NULL ) + if ( pWaypoint == nullptr) { // can't investigate // but other tasks depend on this, so complete it @@ -1623,7 +1630,7 @@ void CBotInvestigateTask :: execute (CBot *pBot,CBotSchedule *pSchedule) if ( pWaypoint->numPaths() > 0 ) { for ( int i = 0; i < pWaypoint->numPaths(); i ++ ) - m_InvPoints.push_back(CWaypoints::getWaypoint(pWaypoint->getPath(i))->getOrigin()); + m_InvPoints.emplace_back(CWaypoints::getWaypoint(pWaypoint->getPath(i))->getOrigin()); m_iCurPath = randomInt(0,pWaypoint->numPaths()-1); } @@ -1632,9 +1639,12 @@ void CBotInvestigateTask :: execute (CBot *pBot,CBotSchedule *pSchedule) } if ( m_fTime < engine->Time() ) + { complete(); + return; + } - if ( m_InvPoints.size() > 0 ) + if (!m_InvPoints.empty()) { Vector vPoint; @@ -1643,12 +1653,12 @@ void CBotInvestigateTask :: execute (CBot *pBot,CBotSchedule *pSchedule) else if ( m_iState == 1 ) // goto origin vPoint = m_vOrigin; - if ( (pBot->distanceFrom(vPoint) < 80) || ((m_iState==0)&&(pBot->distanceFrom(m_vOrigin)>m_fRadius)) ) + if (pBot->distanceFrom(vPoint) < 80 || (m_iState == 0 && pBot->distanceFrom(m_vOrigin) > m_fRadius)) { - m_iState = (!m_iState) ? 1 : 0; + m_iState = !m_iState ? 1 : 0; if ( m_iState == 0 ) - m_iCurPath = randomInt(0,m_InvPoints.size()-1); + m_iCurPath = randomInt(0, static_cast(m_InvPoints.size()) - 1); } else pBot->setMoveTo(vPoint); @@ -1674,13 +1684,13 @@ void CBotDefendTask :: execute (CBot *pBot,CBotSchedule *pSchedule) { static float fDist; - if ( m_fTime == 0 ) + if ( m_fTime == 0.0f ) { if ( pBot->inSquad() && pBot->isSquadLeader() ) { m_fTime = engine->Time() + randomFloat(15.0f,45.0f); } - else if ( m_fMaxTime > 0 ) + else if ( m_fMaxTime > 0.0f ) m_fTime = engine->Time() + m_fMaxTime; else { @@ -1695,8 +1705,8 @@ void CBotDefendTask :: execute (CBot *pBot,CBotSchedule *pSchedule) if ( CTeamFortress2Mod::getFlagLocation(TF2_TEAM_BLUE,&vFlag) ) { // FOR DEBUGGING - float fDist = (vFlag - m_vOrigin).Length(); - float fWaitTime = (90.0f - (fDist/45)); // MAX Dist 4050 + fDist = (vFlag - m_vOrigin).Length(); + const float fWaitTime = 90.0f - fDist/45; // MAX Dist 4050 // m_fTime = engine->Time() + fWaitTime; } @@ -1707,9 +1717,9 @@ void CBotDefendTask :: execute (CBot *pBot,CBotSchedule *pSchedule) fDist = pBot->distanceFrom(m_vOrigin); - if ( fDist > 200 ) + if ( fDist > 200.0f ) fail(); // too far -- bug - else if ( fDist > 100 ) + else if ( fDist > 100.0f ) pBot->setMoveTo(m_vOrigin); else { @@ -1751,9 +1761,9 @@ void CBotDefendTask :: execute (CBot *pBot,CBotSchedule *pSchedule) ////////////////////// void CBotTF2EngiLookAfter :: execute (CBot *pBot,CBotSchedule *pSchedule) { - CBotFortress *tfBot = (CBotFortress*)pBot; + CBotFortress *tfBot = static_cast(pBot); - if ( !m_fTime ) + if (m_fTime == 0.0f) { m_fTime = engine->Time() + randomFloat(21.0f,60.0f); m_fHitSentry = engine->Time() + randomFloat(1.0f,3.0f); @@ -1765,7 +1775,7 @@ void CBotTF2EngiLookAfter :: execute (CBot *pBot,CBotSchedule *pSchedule) } else { - CBotWeapon *pWeapon = pBot->getCurrentWeapon(); + const CBotWeapon *pWeapon = pBot->getCurrentWeapon(); edict_t *pSentry = m_pSentry.get(); pBot->wantToListen(false); @@ -1777,7 +1787,7 @@ void CBotTF2EngiLookAfter :: execute (CBot *pBot,CBotSchedule *pSchedule) fail(); return; } - else if ( pWeapon->getID() != TF2_WEAPON_WRENCH ) + if ( pWeapon->getID() != TF2_WEAPON_WRENCH ) { if ( !pBot->select_CWeapon(CWeapons::getWeapon(TF2_WEAPON_WRENCH)) ) { @@ -1786,7 +1796,7 @@ void CBotTF2EngiLookAfter :: execute (CBot *pBot,CBotSchedule *pSchedule) } } - if ( pSentry != NULL ) + if ( pSentry != nullptr) { if ( pBot->distanceFrom(pSentry) > 100 ) pBot->setMoveTo(CBotGlobals::entityOrigin(pSentry)); @@ -1794,10 +1804,10 @@ void CBotTF2EngiLookAfter :: execute (CBot *pBot,CBotSchedule *pSchedule) { pBot->stopMoving(); - if ( (CClassInterface::getSentryEnemy(pSentry)!=NULL) || - (CClassInterface::getSentryHealth(pSentry) < CClassInterface::getTF2GetBuildingMaxHealth(pSentry) ) || - (CClassInterface::getTF2SentryRockets(pSentry)<20) || - (CClassInterface::getTF2SentryShells(pSentry)<150)) + if ( CClassInterface::getSentryEnemy(pSentry)!= nullptr || + CClassInterface::getSentryHealth(pSentry) < CClassInterface::getTF2GetBuildingMaxHealth(pSentry) || + CClassInterface::getTF2SentryRockets(pSentry)<20 || + CClassInterface::getTF2SentryShells(pSentry)<150) { pBot->primaryAttack(); } @@ -1817,18 +1827,18 @@ void CBotTF2EngiLookAfter :: execute (CBot *pBot,CBotSchedule *pSchedule) } //////////////////////// -CBotTFEngiBuildTask :: CBotTFEngiBuildTask ( eEngiBuild iObject, CWaypoint *pWaypoint ) +CBotTFEngiBuildTask :: CBotTFEngiBuildTask (const eEngiBuild iObject, CWaypoint *pWaypoint) { m_iObject = iObject; m_vOrigin = pWaypoint->getOrigin()+pWaypoint->applyRadius(); m_iState = 0; - m_fTime = 0; + m_fTime = 0.0f; m_iTries = 0; m_fNextUpdateAngle = 0.0f; - QAngle ang = QAngle(0,pWaypoint->getAimYaw(),0); + const QAngle ang = QAngle(0,pWaypoint->getAimYaw(),0); Vector vForward; AngleVectors(ang,&vForward); - m_vAimingVector = m_vOrigin + (vForward*100.0f); + m_vAimingVector = m_vOrigin + vForward*100.0f; m_iArea = pWaypoint->getArea(); m_vBaseOrigin = m_vOrigin; m_fRadius = pWaypoint->getRadius(); @@ -1836,10 +1846,6 @@ CBotTFEngiBuildTask :: CBotTFEngiBuildTask ( eEngiBuild iObject, CWaypoint *pWay void CBotTFEngiBuildTask :: execute (CBot *pBot,CBotSchedule *pSchedule) { - CBotFortress *tfBot; - - bool bAimingOk = true; - pBot->wantToInvestigateSound(false); //if ( !pBot->isTF() ) // shouldn't happen ever @@ -1852,7 +1858,7 @@ void CBotTFEngiBuildTask :: execute (CBot *pBot,CBotSchedule *pSchedule) pBot->wantToChangeWeapon(false); // if enemy just strike them with wrench pBot->wantToListen(false); // sometimes bots dont place sentries because they are looking the wrong way due to a noise - tfBot = (CBotFortress*)pBot; + CBotFortress* tfBot = static_cast(pBot); if ( tfBot->getClass() != TF_CLASS_ENGINEER ) { @@ -1894,9 +1900,9 @@ void CBotTFEngiBuildTask :: execute (CBot *pBot,CBotSchedule *pSchedule) if ( pSentry && CBotGlobals::entityIsValid(pSentry) ) { - Vector vSentry = CBotGlobals::entityOrigin(pSentry); - Vector vOrigin = pBot->getOrigin(); - Vector vLookAt = vOrigin - (vSentry - vOrigin); + const Vector vSentry = CBotGlobals::entityOrigin(pSentry); + const Vector vOrigin = pBot->getOrigin(); + const Vector vLookAt = vOrigin - (vSentry - vOrigin); m_vAimingVector = vLookAt; @@ -1908,9 +1914,9 @@ void CBotTFEngiBuildTask :: execute (CBot *pBot,CBotSchedule *pSchedule) } else { - Vector vSentry = pBot->getAiming(); - Vector vOrigin = pBot->getOrigin(); - Vector vLookAt = vOrigin - (vSentry - vOrigin); + const Vector vSentry = pBot->getAiming(); + const Vector vOrigin = pBot->getOrigin(); + const Vector vLookAt = vOrigin - (vSentry - vOrigin); m_vAimingVector = vLookAt; @@ -1920,7 +1926,7 @@ void CBotTFEngiBuildTask :: execute (CBot *pBot,CBotSchedule *pSchedule) } } - if ( (m_iTries > 1) && (m_fNextUpdateAngle < engine->Time()) ) + if ( m_iTries > 1 && m_fNextUpdateAngle < engine->Time() ) { QAngle angles; Vector vforward = m_vAimingVector - pBot->getOrigin(); @@ -1943,7 +1949,7 @@ void CBotTFEngiBuildTask :: execute (CBot *pBot,CBotSchedule *pSchedule) pBot->setLookAtTask(LOOK_VECTOR,0.2f); pBot->setLookVector(m_vAimingVector); - bAimingOk = pBot->isFacing(m_vAimingVector); // 15 degrees + const bool bAimingOk = pBot->isFacing(m_vAimingVector); // 15 degrees if ( pBot->distanceFrom(m_vOrigin) > 70.0f ) { @@ -1952,9 +1958,9 @@ void CBotTFEngiBuildTask :: execute (CBot *pBot,CBotSchedule *pSchedule) else pBot->setMoveTo(m_vOrigin); } - else if ( bAimingOk || (m_iTries > 1) ) + else if ( bAimingOk || m_iTries > 1 ) { - int state = tfBot->engiBuildObject(&m_iState,m_iObject,&m_fTime,&m_iTries); + const int state = tfBot->engiBuildObject(&m_iState,m_iObject,&m_fTime,&m_iTries); if ( state == 1 ) complete(); @@ -1968,15 +1974,14 @@ void CBotTFEngiBuildTask :: execute (CBot *pBot,CBotSchedule *pSchedule) { // can't build here fail(); - return; } } } } -void CBotTFEngiBuildTask :: debugString ( char *string ) +void CBotTFEngiBuildTask :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CBotTFEngiBuildTask (%d,%0.4f,%0.4f,%0.4f)",m_iObject,m_vOrigin.x,m_vOrigin.y,m_vOrigin.z); + std::sprintf(string,"CBotTFEngiBuildTask (%d,%0.4f,%0.4f,%0.4f)",m_iObject,m_vOrigin.x,m_vOrigin.y,m_vOrigin.z); } @@ -1987,9 +1992,8 @@ CFindGoodHideSpot :: CFindGoodHideSpot ( edict_t *pEntity ) m_vHideFrom = CBotGlobals::entityOrigin(pEntity); } -CFindGoodHideSpot :: CFindGoodHideSpot ( Vector vec ) +CFindGoodHideSpot :: CFindGoodHideSpot (const Vector& vec) : m_vHideFrom(vec) { - m_vHideFrom = vec; } void CFindGoodHideSpot :: init () @@ -2011,8 +2015,9 @@ void CFindGoodHideSpot :: execute ( CBot *pBot, CBotSchedule *pSchedule ) } } -CFindPathTask :: CFindPathTask ( int iWaypointId, eLookTask looktask ) +CFindPathTask :: CFindPathTask (const int iWaypointId, const eLookTask looktask) { + m_iInt = 0; m_iWaypointId = iWaypointId; m_LookTask = looktask; m_vVector = CWaypoints::getWaypoint(iWaypointId)->getOrigin(); @@ -2032,21 +2037,21 @@ void CFindPathTask :: init () //setFailInterrupt(CONDITION_SEE_CUR_ENEMY); } -CFindPathTask :: CFindPathTask ( edict_t *pEdict ) +CFindPathTask :: CFindPathTask ( edict_t *pEdict ) : m_pEdict(pEdict) { m_iWaypointId = -1; - m_pEdict = pEdict; m_vVector = CBotGlobals::entityOrigin(pEdict); m_LookTask = LOOK_WAYPOINT; m_flags.m_data = 0; m_fRange = 0.0f; + m_iInt = 0; m_iDangerPoint = -1; m_bGetPassedIntAsWaypointId = false; } -void CFindPathTask :: debugString ( char *string ) +void CFindPathTask :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CFindPathTask\n m_iInt = %d\n m_vVector = (%0.4f,%0.4f,%0.4f)",m_iInt,m_vVector.x,m_vVector.y,m_vVector.z); + std::sprintf(string,"CFindPathTask\n m_iInt = %d\n m_vVector = (%0.4f,%0.4f,%0.4f)",m_iInt,m_vVector.x,m_vVector.y,m_vVector.z); } void CFindPathTask :: execute ( CBot *pBot, CBotSchedule *pSchedule ) @@ -2074,7 +2079,7 @@ void CFindPathTask :: execute ( CBot *pBot, CBotSchedule *pSchedule ) pSchedule->clearPass(); } - if ( (m_iInt == 0) || (m_iInt == 1) ) + if ( m_iInt == 0 || m_iInt == 1 ) { IBotNavigator *pNav = pBot->getNavigator(); @@ -2090,12 +2095,12 @@ void CFindPathTask :: execute ( CBot *pBot, CBotSchedule *pSchedule ) #endif if ( pNav->workRoute( pBot->getOrigin(), - m_vVector, - &bFail, - (m_iInt==0), - m_flags.bits.m_bNoInterruptions, - m_iWaypointId, - pBot->getConditions(), m_iDangerPoint ) ) + m_vVector, + &bFail, + m_iInt==0, + m_flags.bits.m_bNoInterruptions, + m_iWaypointId, + pBot->getConditions(), m_iDangerPoint ) ) { pBot->m_fWaypointStuckTime = engine->Time() + randomFloat(10.0f,15.0f); pBot->moveFailed(); // reset @@ -2121,7 +2126,7 @@ void CFindPathTask :: execute ( CBot *pBot, CBotSchedule *pSchedule ) } else if ( m_iInt == 2 ) { - if ( pBot->m_fWaypointStuckTime == 0 ) + if ( pBot->m_fWaypointStuckTime == 0.0f ) pBot->m_fWaypointStuckTime = engine->Time() + randomFloat(5.0f,10.0f); //if ( m_bNoInterruptions ) @@ -2144,26 +2149,26 @@ void CFindPathTask :: execute ( CBot *pBot, CBotSchedule *pSchedule ) pBot->getNavigator()->failMove(); } - if ( m_pEdict ) + if (m_pEdict) { - if ( CBotGlobals::entityIsValid(m_pEdict) ) + if (CBotGlobals::entityIsValid(m_pEdict)) { pBot->lookAtEdict(m_pEdict); - if ( m_flags.bits.m_bCompleteInRangeOfEdict && m_flags.bits.m_bCompleteSeeTaskEdict ) + if (m_flags.bits.m_bCompleteInRangeOfEdict && m_flags.bits.m_bCompleteSeeTaskEdict) { // complete if inrange AND see edict - if ( ( m_flags.bits.m_bCompleteInRangeOfEdict && (pBot->distanceFrom(m_pEdict)isVisible(m_pEdict) ) + if (pBot->distanceFrom(m_pEdict) < m_fRange && pBot->isVisible(m_pEdict)) complete(); } - else if ( !m_flags.bits.m_bDontGoToEdict && pBot->isVisible(m_pEdict) ) + else if (!m_flags.bits.m_bDontGoToEdict && pBot->isVisible(m_pEdict)) { - if ( pBot->distanceFrom(m_pEdict) < pBot->distanceFrom(pBot->getNavigator()->getNextPoint()) ) + if (pBot->distanceFrom(m_pEdict) < pBot->distanceFrom(pBot->getNavigator()->getNextPoint())) complete(); - } - else if ( m_flags.bits.m_bCompleteOutOfRangeEdict && (pBot->distanceFrom(m_pEdict)>m_fRange) ) + } + else if (m_flags.bits.m_bCompleteOutOfRangeEdict && pBot->distanceFrom(m_pEdict) > m_fRange) complete(); - else if ( m_flags.bits.m_bCompleteInRangeOfEdict && (pBot->distanceFrom(m_pEdict)distanceFrom(m_pEdict) < m_fRange) complete(); } else @@ -2177,17 +2182,17 @@ void CFindPathTask :: execute ( CBot *pBot, CBotSchedule *pSchedule ) } } - if ( m_pEdict.get() != NULL ) // task edict + if ( m_pEdict.get() != nullptr) // task edict { if ( m_flags.bits.m_bCompleteSeeTaskEdict ) { - if ( pBot->isVisible(m_pEdict.get()) && (pBot->distanceFrom(CBotGlobals::entityOrigin(m_pEdict)) < CWaypointLocations::REACHABLE_RANGE) ) + if ( pBot->isVisible(m_pEdict.get()) && pBot->distanceFrom(CBotGlobals::entityOrigin(m_pEdict)) < CWaypointLocations::REACHABLE_RANGE ) complete(); } if ( m_flags.bits.m_bFailTaskEdictDied ) { - if ( (m_pEdict == NULL) || !CBotGlobals::entityIsAlive(m_pEdict) ) + if ( m_pEdict == nullptr || !CBotGlobals::entityIsAlive(m_pEdict) ) { fail(); } @@ -2197,39 +2202,33 @@ void CFindPathTask :: execute ( CBot *pBot, CBotSchedule *pSchedule ) fail(); } -CBotTF2FindPipeWaypoint:: CBotTF2FindPipeWaypoint ( Vector vOrigin, Vector vTarget ) +CBotTF2FindPipeWaypoint::CBotTF2FindPipeWaypoint(const Vector& vOrigin, const Vector& vTarget) + : m_iters(0), + m_i(0), + m_j(0), // Initialize m_pTarget to nullptr + m_vOrigin(vOrigin), + m_vTarget(vTarget), + m_iTargetWaypoint(static_cast(CWaypointLocations::NearestWaypoint(m_vTarget, BLAST_RADIUS, -1, true, true))), + m_fNearesti(2048.0f), + m_fNearestj(4096.0f), + m_iNearesti(-1), + m_iNearestj(-1), + m_pTable(CWaypoints::getVisiblity()), + m_pTarget(nullptr) { - m_vOrigin = vOrigin; - m_vTarget = vTarget; - - m_i = 0; - m_j = 0; - m_iters = 0; - m_iNearesti = -1; - m_iNearestj = -1; - m_fNearesti = 2048.0f; - m_fNearestj = 4096.0f; - m_iTargetWaypoint = (short int)CWaypointLocations::NearestWaypoint(m_vTarget,BLAST_RADIUS,-1,true,true); - - m_pTable = CWaypoints::getVisiblity(); - - if ( m_iTargetWaypoint != -1 ) + if (m_iTargetWaypoint != -1) { // first find the waypoint nearest the target - Vector vComp = (vOrigin - vTarget); - vComp = vComp/vComp.Length(); - vComp = vTarget + vComp*256; // get into a better area + Vector vComp = vOrigin - vTarget; + vComp = vComp / vComp.Length(); + vComp = vTarget + vComp * 256; // get into a better area m_pTarget = CWaypoints::getWaypoint(m_iTargetWaypoint); - CWaypointLocations::GetAllInArea(vComp,&m_WaypointsI,m_iTargetWaypoint); + CWaypointLocations::GetAllInArea(vComp, &m_WaypointsI, m_iTargetWaypoint); } - - } // a concurrentish pipe waypoint search void CBotTF2FindPipeWaypoint :: execute (CBot *pBot,CBotSchedule *pSchedule) { - CWaypoint *pTempi,*pTempj; - float fidist,fjdist; int maxiters = 128; // push! @@ -2242,7 +2241,7 @@ void CBotTF2FindPipeWaypoint :: execute (CBot *pBot,CBotSchedule *pSchedule) pBot->setLookAtTask(LOOK_AROUND); pBot->stopMoving(); - if ( m_pTarget == NULL ) + if ( m_pTarget == nullptr) { fail(); return; @@ -2251,11 +2250,11 @@ void CBotTF2FindPipeWaypoint :: execute (CBot *pBot,CBotSchedule *pSchedule) m_iters = 0; // loop through every visible waypoint to target (can be unreachable) - while ((m_i < m_WaypointsI.size())&&(m_itersdistanceFrom(pTempi->getOrigin()); + CWaypoint* pTempi = CWaypoints::getWaypoint(m_WaypointsI[m_i]); + const float fidist = m_pTarget->distanceFrom(pTempi->getOrigin()); if ( fidist > m_fNearesti ) { @@ -2269,7 +2268,7 @@ void CBotTF2FindPipeWaypoint :: execute (CBot *pBot,CBotSchedule *pSchedule) CWaypointLocations::GetAllInArea(vTempi,&m_WaypointsJ,m_WaypointsI[m_i]); // loop through every visible waypoint to intermediatery waypoint (cannot be unreachable) - while ((m_j < m_WaypointsJ.size())&&(m_iterscanGotoWaypoint(pTempj->getOrigin(),pTempj) ) @@ -2287,7 +2286,7 @@ void CBotTF2FindPipeWaypoint :: execute (CBot *pBot,CBotSchedule *pSchedule) } // only remember the nearest waypoints - the nearest is updated when both I and J are found - fjdist = pTempj->distanceFrom(m_vOrigin) + pTempj->distanceFrom(pTempi->getOrigin()); + const float fjdist = pTempj->distanceFrom(m_vOrigin) + pTempj->distanceFrom(pTempi->getOrigin()); if ( fjdist > m_fNearestj ) { @@ -2297,12 +2296,12 @@ void CBotTF2FindPipeWaypoint :: execute (CBot *pBot,CBotSchedule *pSchedule) } // If this waypoint is NOT visible to target it is good - if ( !m_pTable->GetVisibilityFromTo((int)m_iTargetWaypoint,(int)m_WaypointsJ[m_j]) ) + if ( !m_pTable->GetVisibilityFromTo(m_iTargetWaypoint,m_WaypointsJ[m_j]) ) { m_fNearesti = fidist; m_fNearestj = fjdist; - m_iNearesti = m_WaypointsI[m_i]; - m_iNearestj = m_WaypointsJ[m_j]; + m_iNearesti = static_cast(m_WaypointsI[m_i]); + m_iNearestj = static_cast(m_WaypointsJ[m_j]); } m_iters++; @@ -2333,55 +2332,137 @@ void CBotTF2FindPipeWaypoint :: execute (CBot *pBot,CBotSchedule *pSchedule) void CTF2_TauntTask :: init () { - m_fTime = 0; + m_fTime = 0.0f; + m_fTauntUntil = 0.0f; + m_fActionTime = 0.0f; } -void CTF2_TauntTask :: execute ( CBot *pBot, CBotSchedule *pSchedule ) +void CTF2_TauntTask::execute(CBot* pBot, CBotSchedule* pSchedule) { - if ( m_fTime == 0 ) - m_fTime = engine->Time() + randomFloat(2.5f,5.0f); - else if ( m_fTime < engine->Time() ) + if (!m_pPlayer) { + // Stop taunting + /*CClassInterface::g_GetProps[GETPROP_TF2_CONDITIONS].getData(pBot->getEdict()); + *static_cast(CClassInterface::g_GetProps[GETPROP_TF2_CONDITIONS].m_data) &= ~(1 << 7);*/ + fail(); return; } - pBot->setLookVector(m_vPlayer); - pBot->setLookAtTask(LOOK_VECTOR); + const float fTime = engine->Time(); - if ( pBot->distanceFrom(m_vOrigin) > m_fDist ) - pBot->setMoveTo(m_vOrigin); - else + if (m_fTauntUntil == 0.0f) { - if ( pBot->DotProductFromOrigin(m_vPlayer) > 0.95 ) + if (m_fTime == 0.0f) + m_fTime = engine->Time() + randomFloat(2.5f, 5.0f); + else if (m_fTime < engine->Time()) { - ((CBotTF2*)pBot)->taunt(true); - complete(); + fail(); + return; + } + + pBot->lookAtEdict(m_pPlayer.get()); + pBot->setLookAtTask(LOOK_EDICT, 10.0f); + + if (pBot->distanceFrom(m_vOrigin) > m_fDist) + pBot->setMoveTo(m_vOrigin); + else + { + CBotTF2* pTF2Bot = static_cast(pBot); + + if (pTF2Bot->getClass() == TF_CLASS_SPY) + { + if (pTF2Bot->isCloaked()) + { + pTF2Bot->spyUnCloak(); + return; + } + + if (pTF2Bot->isDisguised()) + { + pTF2Bot->spyDisguise(pTF2Bot->getTeam(), 8); + return; + } + } + + pTF2Bot->taunt(true); + + m_fTauntUntil = fTime + randomFloat(15.0f, 30.0f); } + + return; + } + + const bool bIsTaunting = CClassInterface::getTF2Conditions(pBot->getEdict()) & (1 << 7); + Vector vPlayerOrigin = m_pPlayer.get()->GetCollideable()->GetCollisionOrigin(); + + // Don't do anything but follow target player as long as they are still taunting and bot isn't wandering off + if (bIsTaunting && (CClassInterface::getTF2Conditions(m_pPlayer.get()) & (1 << 7)) && vPlayerOrigin.IsValid() + && pBot->distanceFrom(vPlayerOrigin) < m_fDist * 4.0f) + { + // In case taunt time has expired, extend it a bit as long as target player is still taunting + if (fTime > m_fTauntUntil) + m_fTauntUntil = fTime + randomFloat(2.0f, 10.0f); + + // Do random actions in case the taunt permits it + /*if (fTime > m_fActionTime) + { + m_fActionTime = fTime + randomFloat(0.5f, 2.0f); + + int iRand = randomInt(0, 20); + if (iRand == 0) + pBot->primaryAttack(true); + else if (iRand == 1) + pBot->secondaryAttack(true); + }*/ + + // Chase player if the taunt allows movement + if (pBot->distanceFrom(vPlayerOrigin) > m_fDist * 2.0f) + { + vPlayerOrigin.x += randomFloat(-m_fDist * 2.0f, m_fDist * 2.0f); + vPlayerOrigin.y += randomFloat(-m_fDist * 2.0f, m_fDist * 2.0f); + pBot->setMoveTo(vPlayerOrigin); + } + + return; } + + if (bIsTaunting) + { + if (fTime > m_fTauntUntil) + { + // Stop taunting + /*CClassInterface::g_GetProps[GETPROP_TF2_CONDITIONS].getData(pBot->getEdict()); + *static_cast(CClassInterface::g_GetProps[GETPROP_TF2_CONDITIONS].m_data) &= ~(1 << 7);*/ + } + + // return; + } + + complete(); } -void CTF2_TauntTask :: debugString ( char *string ) +void CTF2_TauntTask :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CTF2_TauntTask"); + std::sprintf(string,"CTF2_TauntTask"); } ////////////////////////////////////// void CMoveToTask :: init () { - fPrevDist = 0; + fPrevDist = 0.0f; //m_vVector = Vector(0,0,0); //m_pEdict = NULL; } -void CMoveToTask :: debugString ( char *string ) +void CMoveToTask :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CMoveToTask\nm_vVector =(%0.4f,%0.4f,%0.4f)",m_vVector.x,m_vVector.y,m_vVector.z); + std::sprintf(string,"CMoveToTask\nm_vVector =(%0.4f,%0.4f,%0.4f)",m_vVector.x,m_vVector.y,m_vVector.z); } -CMoveToTask :: CMoveToTask ( edict_t *pEdict ) +CMoveToTask :: CMoveToTask ( edict_t *pEdict ) : m_pEdict(pEdict) { - m_pEdict = pEdict; + fPrevDist = 0.0f; m_vVector = CBotGlobals::entityOrigin(m_pEdict); //setFailInterrupt(CONDITION_SEE_CUR_ENEMY); @@ -2389,24 +2470,18 @@ CMoveToTask :: CMoveToTask ( edict_t *pEdict ) void CMoveToTask :: execute ( CBot *pBot, CBotSchedule *pSchedule ) { - - float fDistance; - - fDistance = pBot->distanceFrom(m_vVector); + const float fDistance = pBot->distanceFrom(m_vVector); // sort out looping move to origins by using previous distance check - if ( (fDistance < 64) || (fPrevDist&&(fPrevDist < fDistance)) ) + if (fDistance < 64 || (fPrevDist != 0.0f && fPrevDist < fDistance)) { complete(); return; } - else - { - pBot->setMoveTo(m_vVector); + pBot->setMoveTo(m_vVector); - if ( pBot->moveFailed() ) - fail(); - } + if ( pBot->moveFailed() ) + fail(); fPrevDist = fDistance; } @@ -2423,14 +2498,11 @@ CBotTFRocketJump :: CBotTFRocketJump () m_iState = 0; } -void CBotTFRocketJump :: execute (CBot *pBot,CBotSchedule *pSchedule) +void CBotTFRocketJump :: execute (CBot *pBot, CBotSchedule *pSchedule) { - CBotWeapon *pBotWeapon; - CWeapon *pWeapon; - pBot->wantToListen(false); - pBotWeapon = pBot->getCurrentWeapon(); + const CBotWeapon* pBotWeapon = pBot->getCurrentWeapon(); if ( !pBotWeapon ) { @@ -2438,15 +2510,15 @@ void CBotTFRocketJump :: execute (CBot *pBot,CBotSchedule *pSchedule) return; } - pWeapon = pBotWeapon->getWeaponInfo(); + const CWeapon* pWeapon = pBotWeapon->getWeaponInfo(); - if (pWeapon == NULL) + if (pWeapon == nullptr) { fail(); return; } - if ( !pBot->isTF() || (((CBotFortress*)pBot)->getClass() != TF_CLASS_SOLDIER) || (pBot->getHealthPercent() < 0.3) ) + if ( !pBot->isTF() || static_cast(pBot)->getClass() != TF_CLASS_SOLDIER || pBot->getHealthPercent() < 0.3f ) { fail(); } @@ -2459,9 +2531,9 @@ void CBotTFRocketJump :: execute (CBot *pBot,CBotSchedule *pSchedule) } else { - CBotTF2 *tf2Bot = ((CBotTF2*)pBot); + CBotTF2 *tf2Bot = static_cast(pBot); - if ( !m_fTime ) + if (m_fTime == 0.0f) { m_fTime = engine->Time()+randomFloat(4.0f,5.0f); } @@ -2475,9 +2547,9 @@ void CBotTFRocketJump :: execute (CBot *pBot,CBotSchedule *pSchedule) } } -void CBotTFRocketJump :: debugString ( char *string ) +void CBotTFRocketJump :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CBotTFRocketJump"); + std::sprintf(string,"CBotTFRocketJump"); } @@ -2488,7 +2560,7 @@ CBotTFDoubleJump :: CBotTFDoubleJump () m_fTime = 0.0f; } -void CBotTFDoubleJump ::execute (CBot *pBot,CBotSchedule *pSchedule) +void CBotTFDoubleJump ::execute (CBot *pBot, CBotSchedule *pSchedule) { pBot->wantToListen(false); @@ -2496,7 +2568,7 @@ void CBotTFDoubleJump ::execute (CBot *pBot,CBotSchedule *pSchedule) { pBot->tapButton(IN_JUMP); - m_fTime = engine->Time() + 0.4; + m_fTime = engine->Time() + 0.4f; } else if ( m_fTime < engine->Time() ) { @@ -2505,15 +2577,14 @@ void CBotTFDoubleJump ::execute (CBot *pBot,CBotSchedule *pSchedule) } } -void CBotTFDoubleJump :: debugString ( char *string ) +void CBotTFDoubleJump :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CbotTFDoublejump"); + std::sprintf(string,"CbotTFDoublejump"); } /////////////////////////////////////////////// void CSpyCheckAir :: execute ( CBot *pBot, CBotSchedule *pSchedule ) { - CBotTF2 *pBotTF2 = (CBotTF2*)pBot; - CBotWeapon *pWeapon; + CBotTF2 *pBotTF2 = static_cast(pBot); CBotWeapon *pChooseWeapon; CBotWeapons *pWeaponList; static int iAttackProb; @@ -2523,23 +2594,19 @@ void CSpyCheckAir :: execute ( CBot *pBot, CBotSchedule *pSchedule ) if ( m_fTime == 0.0f ) { - // record the number of people I see now - int i; - edict_t *pPlayer; - IPlayerInfo *p; -/* edict_t *pDisguised; + /* edict_t *pDisguised; int iClass; int iTeam; int iIndex; int iHealth; -*/ + */ seenlist = 0; m_bHitPlayer = false; - for ( i = 1; i <= gpGlobals->maxClients; i ++ ) + for ( int i = 1; i <= gpGlobals->maxClients; i ++ ) { - pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(i); if ( pPlayer == pBot->getEdict() ) continue; @@ -2547,7 +2614,7 @@ void CSpyCheckAir :: execute ( CBot *pBot, CBotSchedule *pSchedule ) if ( !CBotGlobals::entityIsValid(pPlayer) ) continue; - p = playerinfomanager->GetPlayerInfo(pPlayer); + IPlayerInfo* p = playerinfomanager->GetPlayerInfo(pPlayer); if ( p->IsDead() || p->IsObserver() ) continue; @@ -2560,7 +2627,7 @@ void CSpyCheckAir :: execute ( CBot *pBot, CBotSchedule *pSchedule ) } if ( pBot->isVisible(pPlayer) ) - seenlist |= (1<<(i-1)); + seenlist |= (1 << (i - 1)); } m_fTime = engine->Time() + randomFloat(2.0f,5.0f); @@ -2573,17 +2640,13 @@ void CSpyCheckAir :: execute ( CBot *pBot, CBotSchedule *pSchedule ) if ( pBot->hasEnemy() ) complete(); - if ( (m_pUnseenBefore==NULL) && (m_fNextCheckUnseen < engine->Time()) ) + if ( m_pUnseenBefore== nullptr && m_fNextCheckUnseen < engine->Time() ) { - int i; - edict_t *pPlayer; - IPlayerInfo *p; - seenlist = 0; - for ( i = 1; i <= gpGlobals->maxClients; i ++ ) + for ( int i = 1; i <= gpGlobals->maxClients; i ++ ) { - pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(i); if ( pPlayer == pBot->getEdict() ) continue; @@ -2591,7 +2654,7 @@ void CSpyCheckAir :: execute ( CBot *pBot, CBotSchedule *pSchedule ) if ( !CBotGlobals::entityIsValid(pPlayer) ) continue; - p = playerinfomanager->GetPlayerInfo(pPlayer); + IPlayerInfo* p = playerinfomanager->GetPlayerInfo(pPlayer); if ( p->IsDead() || p->IsObserver() ) continue; @@ -2611,17 +2674,16 @@ void CSpyCheckAir :: execute ( CBot *pBot, CBotSchedule *pSchedule ) if ( CTeamFortress2Mod::isFlagCarrier(pPlayer) ) continue; // spies can't hold flag unless not disguised - if ( !(seenlist & (1<<(i-1))) ) + if (!(seenlist & (1 << (i - 1)))) { m_pUnseenBefore = pPlayer; - seenlist |= (1<<(i-1)); //add to list + seenlist |= (1 << (i - 1)); //add to list break; } } - } - if ( m_pUnseenBefore != NULL ) + if ( m_pUnseenBefore != nullptr) { // add more time m_fTime = engine->Time() + randomFloat(2.0f,5.0f); @@ -2631,11 +2693,11 @@ void CSpyCheckAir :: execute ( CBot *pBot, CBotSchedule *pSchedule ) } else if ( m_pUnseenBefore && (!CBotGlobals::entityIsAlive(m_pUnseenBefore) || !CBotGlobals::entityIsValid(m_pUnseenBefore) || !pBot->isVisible(m_pUnseenBefore) ) ) { - m_pUnseenBefore = NULL; + m_pUnseenBefore = nullptr; m_fNextCheckUnseen = 0.0f; } - if ( m_pUnseenBefore == NULL ) + if ( m_pUnseenBefore == nullptr) { // automatically look at danger points pBot->updateDanger(50.0f); @@ -2649,8 +2711,9 @@ void CSpyCheckAir :: execute ( CBot *pBot, CBotSchedule *pSchedule ) pBot->setLookAtTask(LOOK_EDICT); pBot->setMoveTo(CBotGlobals::entityOrigin(m_pUnseenBefore)); } -/* - TF_CLASS_CIVILIAN = 0, + + /* + TF_CLASS_UNDEFINED = 0, TF_CLASS_SCOUT, TF_CLASS_SNIPER, TF_CLASS_SOLDIER, @@ -2660,9 +2723,10 @@ void CSpyCheckAir :: execute ( CBot *pBot, CBotSchedule *pSchedule ) TF_CLASS_PYRO, TF_CLASS_SPY, TF_CLASS_ENGINEER, - TF_CLASS_MAX*/ + TF_CLASS_MAX + */ - pWeapon = pBot->getCurrentWeapon(); + const CBotWeapon* pWeapon = pBot->getCurrentWeapon(); switch ( pBotTF2->getClass() ) { @@ -2671,7 +2735,6 @@ void CSpyCheckAir :: execute ( CBot *pBot, CBotSchedule *pSchedule ) pWeaponList = pBot->getWeapons(); pChooseWeapon = pWeaponList->getWeapon(CWeapons::getWeapon(TF2_WEAPON_FLAMETHROWER)); - if (pChooseWeapon && pChooseWeapon->hasWeapon() && !pChooseWeapon->outOfAmmo(pBot)) { @@ -2682,7 +2745,7 @@ void CSpyCheckAir :: execute ( CBot *pBot, CBotSchedule *pSchedule ) // move down to melee if out of ammo default: iAttackProb = 75; - pChooseWeapon = pBot->getBestWeapon(NULL,true,true,true); + pChooseWeapon = pBot->getBestWeapon(nullptr,true,true,true); break; } @@ -2691,7 +2754,7 @@ void CSpyCheckAir :: execute ( CBot *pBot, CBotSchedule *pSchedule ) pBot->setMoveTo(CBotGlobals::entityOrigin(m_pUnseenBefore)); } - if ( pChooseWeapon && (pWeapon != pChooseWeapon) ) + if ( pChooseWeapon && pWeapon != pChooseWeapon ) { if ( !pBot->selectBotWeapon(pChooseWeapon) ) { @@ -2704,9 +2767,9 @@ void CSpyCheckAir :: execute ( CBot *pBot, CBotSchedule *pSchedule ) { pBot->primaryAttack(); - if ( m_pUnseenBefore != NULL ) + if ( m_pUnseenBefore != nullptr) { - if ( !m_bHitPlayer && (pBot->distanceFrom(CBotGlobals::entityOrigin(m_pUnseenBefore)) < 80.0f) ) + if ( !m_bHitPlayer && pBot->distanceFrom(CBotGlobals::entityOrigin(m_pUnseenBefore)) < 80.0f ) { m_bHitPlayer = true; m_fTime = engine->Time()+randomFloat(0.5f,1.5f); @@ -2723,20 +2786,18 @@ void CSpyCheckAir :: execute ( CBot *pBot, CBotSchedule *pSchedule ) if ( p->GetLastUserCommand().buttons & IN_ATTACK ) { complete(); - return; } } } - } -void CSpyCheckAir :: debugString (char *string) +void CSpyCheckAir :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CSpyCheckAir: checking for spies"); + std::sprintf(string,"CSpyCheckAir: checking for spies"); } ///////////////////////////////////////////// -CBotRemoveSapper :: CBotRemoveSapper ( edict_t *pBuilding, eEngiBuild id ) +CBotRemoveSapper :: CBotRemoveSapper ( edict_t *pBuilding, const eEngiBuild id ) { m_fTime = 0.0f; m_pBuilding = MyEHandle(pBuilding); @@ -2746,9 +2807,7 @@ CBotRemoveSapper :: CBotRemoveSapper ( edict_t *pBuilding, eEngiBuild id ) void CBotRemoveSapper :: execute (CBot *pBot,CBotSchedule *pSchedule) { - //int i = 0; - edict_t *pBuilding; - CBotTF2 *pTF2Bot = (CBotTF2*)pBot; + CBotTF2 *pTF2Bot = static_cast(pBot); pBot->wantToShoot(false); pBot->wantToChangeWeapon(false); @@ -2759,7 +2818,7 @@ void CBotRemoveSapper :: execute (CBot *pBot,CBotSchedule *pSchedule) pBot->removeCondition(CONDITION_COVERT); } - pBuilding = m_pBuilding.get(); + edict_t* pBuilding = m_pBuilding.get(); if ( !pBuilding ) { @@ -2841,24 +2900,29 @@ void CBotRemoveSapper :: execute (CBot *pBot,CBotSchedule *pSchedule) } else { - if ( !((CBotFortress*)pBot)->upgradeBuilding(pBuilding,true) ) + if ( !static_cast(pBot)->upgradeBuilding(pBuilding,true) ) fail(); } } //////////////////////////////////////////////////// -CBotTF2SnipeCrossBow::CBotTF2SnipeCrossBow(Vector vOrigin, int iWpt) +CBotTF2SnipeCrossBow::CBotTF2SnipeCrossBow(const Vector& vOrigin, const int iWpt) : m_vOrigin(vOrigin) { - CWaypoint *pWaypoint = CWaypoints::getWaypoint(iWpt); + const CWaypoint *pWaypoint = CWaypoints::getWaypoint(iWpt); + m_iHideWaypoint = 0; + m_fHideTime = 0.0f; + m_iPrevClip = 0; + m_fCheckTime = 0.0f; + m_fOriginDistance = 0.0f; + m_iSnipeWaypoint = iWpt; - QAngle angle; m_fAimTime = 0.0f; m_fTime = 0.0f; - angle = QAngle(0, pWaypoint->getAimYaw(), 0); + const QAngle angle = QAngle(0, pWaypoint->getAimYaw(), 0); AngleVectors(angle, &m_vAim); - m_vAim = vOrigin + (m_vAim * 4096); - m_vOrigin = vOrigin; + + m_vAim = vOrigin + m_vAim * 4096; m_fEnemyTime = 0.0f; m_vEnemy = m_vAim; m_iArea = pWaypoint->getArea(); @@ -2866,14 +2930,12 @@ CBotTF2SnipeCrossBow::CBotTF2SnipeCrossBow(Vector vOrigin, int iWpt) void CBotTF2SnipeCrossBow::execute(CBot *pBot, CBotSchedule *pSchedule) { - CBotWeapon *pBotWeapon; - CWeapon *pWeapon; - CBotTF2 *pBotTF2; + CBotTF2* pBotTF2 = static_cast(pBot); - pBotTF2 = (CBotTF2*)pBot; // Sniper should move if the point has changed, so he's not wasting time if (!CTeamFortress2Mod::m_ObjectiveResource.isWaypointAreaValid(m_iArea)) fail(); // move up + else if (m_iArea > 0) { if (CTeamFortress2Mod::isAttackDefendMap()) @@ -2886,11 +2948,10 @@ void CBotTF2SnipeCrossBow::execute(CBot *pBot, CBotSchedule *pSchedule) else if (m_iArea != pBotTF2->getCurrentDefendArea()) complete(); } - else if ((m_iArea != pBotTF2->getCurrentAttackArea()) && (m_iArea != pBotTF2->getCurrentDefendArea())) + else if (m_iArea != pBotTF2->getCurrentAttackArea() && m_iArea != pBotTF2->getCurrentDefendArea()) { complete(); // move up } - } // disable normal attack functions @@ -2901,7 +2962,7 @@ void CBotTF2SnipeCrossBow::execute(CBot *pBot, CBotSchedule *pSchedule) pBot->wantToInvestigateSound(false); // change weapon to sniper if not already - pBotWeapon = pBot->getCurrentWeapon(); + CBotWeapon* pBotWeapon = pBot->getCurrentWeapon(); if (!pBotWeapon) { @@ -2909,9 +2970,9 @@ void CBotTF2SnipeCrossBow::execute(CBot *pBot, CBotSchedule *pSchedule) return; } - pWeapon = pBotWeapon->getWeaponInfo(); + const CWeapon* pWeapon = pBotWeapon->getWeaponInfo(); - if (pWeapon == NULL) + if (pWeapon == nullptr) { fail(); return; @@ -2941,18 +3002,16 @@ void CBotTF2SnipeCrossBow::execute(CBot *pBot, CBotSchedule *pSchedule) CBotGlobals::quickTraceline(pBot->getEdict(), m_vOrigin, m_vAim); - int iAimWpt = CWaypointLocations::NearestWaypoint(CBotGlobals::getTraceResult()->endpos, 400.0f, -1, true, true); + const int iAimWpt = CWaypointLocations::NearestWaypoint(CBotGlobals::getTraceResult()->endpos, 400.0f, -1, true, true); if (iAimWpt != -1) { - CWaypoint *pWaypoint = CWaypoints::getWaypoint(m_iSnipeWaypoint); - CWaypointVisibilityTable *pTable = CWaypoints::getVisiblity(); - - int iPathId; + const CWaypoint *pWaypoint = CWaypoints::getWaypoint(m_iSnipeWaypoint); + const CWaypointVisibilityTable *pTable = CWaypoints::getVisiblity(); for (int i = 0; i < pWaypoint->numPaths(); i++) { - iPathId = pWaypoint->getPath(i); + const int iPathId = pWaypoint->getPath(i); // isn't visible to the target if (!pTable->GetVisibilityFromTo(iAimWpt, iPathId)) @@ -2972,7 +3031,7 @@ void CBotTF2SnipeCrossBow::execute(CBot *pBot, CBotSchedule *pSchedule) { CWaypoint *pHideWaypoint = CWaypoints::getWaypoint(m_iHideWaypoint); - if (pHideWaypoint != NULL) + if (pHideWaypoint != nullptr) { m_vHideOrigin = pHideWaypoint->getOrigin(); } @@ -2998,12 +3057,12 @@ void CBotTF2SnipeCrossBow::execute(CBot *pBot, CBotSchedule *pSchedule) pBot->setLookAtTask(LOOK_SNIPE); // saw an enemy less than 5 secs ago - if ((m_fEnemyTime + 5.0f) > engine->Time()) + if (m_fEnemyTime + 5.0f > engine->Time()) pBot->setAiming(m_vEnemy); else pBot->setAiming(m_vAim); - if (!pBot->isTF() || (((CBotFortress*)pBot)->getClass() != TF_CLASS_SNIPER) || (pBot->getHealthPercent() < 0.2)) + if (!pBot->isTF() || static_cast(pBot)->getClass() != TF_CLASS_SNIPER || pBot->getHealthPercent() < 0.2f) { // out of health -- finish //if (CTeamFortress2Mod::TF2_IsPlayerZoomed(pBot->getEdict())) @@ -3012,12 +3071,11 @@ void CBotTF2SnipeCrossBow::execute(CBot *pBot, CBotSchedule *pSchedule) fail(); return; } - else if (pBotWeapon->getAmmo(pBot) < 1) + if (pBotWeapon->getAmmo(pBot) < 1) { // out of ammo -- finish //if (CTeamFortress2Mod::TF2_IsPlayerZoomed(pBot->getEdict())) // pBot->secondaryAttack(); - complete(); } else if (pBot->distanceFrom(m_vOrigin) > 400) @@ -3027,7 +3085,7 @@ void CBotTF2SnipeCrossBow::execute(CBot *pBot, CBotSchedule *pSchedule) // too far away fail(); } - else if ((m_iHideWaypoint != -1) && (((CBotFortress*)pBot)->incomingRocket(512.0f) || (m_fHideTime > engine->Time()))) + else if (m_iHideWaypoint != -1 && (static_cast(pBot)->incomingRocket(512.0f) || m_fHideTime > engine->Time())) { // hide time -- move to hide origin pBot->setMoveTo(m_vHideOrigin); @@ -3057,8 +3115,9 @@ void CBotTF2SnipeCrossBow::execute(CBot *pBot, CBotSchedule *pSchedule) m_vEnemy = CBotGlobals::entityOrigin(pBot->getEnemy()); m_fEnemyTime = engine->Time(); - if (m_fAimTime == 0.0f) - m_fAimTime = engine->Time() + randomFloat(0.1f, 0.3f); + // Check m_fEnemyTime instead of m_fAimTime if that was the intention - [APG]RoboCop[CL] + if (m_fEnemyTime == 0.0f) + m_fEnemyTime = engine->Time() + randomFloat(0.1f, 0.3f); // too close for sniper rifle if (pBot->distanceFrom(pBot->getEnemy()) < 200.0f) @@ -3075,7 +3134,7 @@ void CBotTF2SnipeCrossBow::execute(CBot *pBot, CBotSchedule *pSchedule) pBot->setLookAtTask(LOOK_ENEMY); - float angle = pBot->DotProductFromOrigin(CBotGlobals::entityOrigin(pBot->getEnemy())); + const float angle = pBot->DotProductFromOrigin(CBotGlobals::entityOrigin(pBot->getEnemy())); if (angle > 0.96f) // 16 degrees { @@ -3090,7 +3149,7 @@ void CBotTF2SnipeCrossBow::execute(CBot *pBot, CBotSchedule *pSchedule) if (CBotGlobals::isPlayer(pBot->getEnemy())) bhide = CBotGlobals::DotProductFromOrigin(pBot->getEnemy(), pBot->getOrigin()) > 0.96f; else - bhide = randomFloat(0.0f, 2.0f) <= (angle + (1.0f - pBot->getHealthPercent())); + bhide = randomFloat(0.0f, 2.0f) <= angle + (1.0f - pBot->getHealthPercent()); if (bhide) m_fHideTime = engine->Time() + randomFloat(1.5f, 2.5f); @@ -3136,34 +3195,35 @@ void CBotTF2SnipeCrossBow::execute(CBot *pBot, CBotSchedule *pSchedule) } } /////////////////////////////////////////// -CBotTF2Snipe :: CBotTF2Snipe ( Vector vOrigin, int iWpt ) +CBotTF2Snipe :: CBotTF2Snipe (const Vector& vOrigin, const int iWpt) : m_vOrigin(vOrigin) { - CWaypoint *pWaypoint = CWaypoints::getWaypoint(iWpt); + m_iHideWaypoint = 0; + m_fHideTime = 0.0f; + m_iPrevClip = 0; + m_fCheckTime = 0.0f; + m_fOriginDistance = 0.0f; + + const CWaypoint *pWaypoint = CWaypoints::getWaypoint(iWpt); m_iSnipeWaypoint = iWpt; - QAngle angle; m_fAimTime = 0.0f; m_fTime = 0.0f; - angle = QAngle(0,pWaypoint->getAimYaw(),0); + const QAngle angle = QAngle(0, pWaypoint->getAimYaw(), 0); + AngleVectors(angle,&m_vAim); - m_vAim = vOrigin + (m_vAim*4096); - m_vOrigin = vOrigin; + m_vAim = vOrigin + m_vAim*4096; m_fEnemyTime = 0.0f; m_vEnemy = m_vAim; m_iArea = pWaypoint->getArea(); } -void CBotTF2Snipe :: execute (CBot *pBot,CBotSchedule *pSchedule) +void CBotTF2Snipe :: execute (CBot *pBot, CBotSchedule *pSchedule) { - - CBotWeapon *pBotWeapon; - CWeapon *pWeapon; - // Sniper should move if the point has changed, so he's not wasting time if ( !CTeamFortress2Mod::m_ObjectiveResource.isWaypointAreaValid(m_iArea) ) fail(); // move up else if ( m_iArea > 0 ) { - CBotTF2 *pBotTF2 = (CBotTF2*)pBot; + CBotTF2 *pBotTF2 = static_cast(pBot); if ( CTeamFortress2Mod::isAttackDefendMap() ) { @@ -3175,7 +3235,7 @@ void CBotTF2Snipe :: execute (CBot *pBot,CBotSchedule *pSchedule) else if ( m_iArea != pBotTF2->getCurrentDefendArea() ) complete(); } - else if (( m_iArea != pBotTF2->getCurrentAttackArea() ) && ( m_iArea != pBotTF2->getCurrentDefendArea() )) + else if (m_iArea != pBotTF2->getCurrentAttackArea() && m_iArea != pBotTF2->getCurrentDefendArea()) { complete(); // move up } @@ -3190,7 +3250,7 @@ void CBotTF2Snipe :: execute (CBot *pBot,CBotSchedule *pSchedule) pBot->wantToInvestigateSound(false); // change weapon to sniper if not already - pBotWeapon = pBot->getCurrentWeapon(); + CBotWeapon* pBotWeapon = pBot->getCurrentWeapon(); if ( !pBotWeapon ) { @@ -3198,17 +3258,20 @@ void CBotTF2Snipe :: execute (CBot *pBot,CBotSchedule *pSchedule) return; } - pWeapon = pBotWeapon->getWeaponInfo(); + const CWeapon* pWeapon = pBotWeapon->getWeaponInfo(); - if (pWeapon == NULL) + if (pWeapon == nullptr) { fail(); return; } - if (pWeapon->getID() != TF2_WEAPON_SNIPERRIFLE ) + if (pWeapon->getSlot() != 0) { - if ( !pBot->select_CWeapon(CWeapons::getWeapon(TF2_WEAPON_SNIPERRIFLE)) ) + CBotWeapons* pWeapons = pBot->getWeapons(); + const CBotWeapon* bot_weapon = pWeapons->getCurrentWeaponInSlot(0); + + if (bot_weapon && !pBot->select_CWeapon(bot_weapon->getWeaponInfo())) { fail(); return; @@ -3230,18 +3293,16 @@ void CBotTF2Snipe :: execute (CBot *pBot,CBotSchedule *pSchedule) CBotGlobals::quickTraceline(pBot->getEdict(),m_vOrigin,m_vAim); - int iAimWpt = CWaypointLocations::NearestWaypoint(CBotGlobals::getTraceResult()->endpos,400.0f,-1,true,true); + const int iAimWpt = CWaypointLocations::NearestWaypoint(CBotGlobals::getTraceResult()->endpos,400.0f,-1,true,true); if ( iAimWpt != -1 ) { - CWaypoint *pWaypoint = CWaypoints::getWaypoint(m_iSnipeWaypoint); - CWaypointVisibilityTable *pTable = CWaypoints::getVisiblity(); - - int iPathId; + const CWaypoint *pWaypoint = CWaypoints::getWaypoint(m_iSnipeWaypoint); + const CWaypointVisibilityTable *pTable = CWaypoints::getVisiblity(); for ( int i = 0; i < pWaypoint->numPaths(); i ++ ) { - iPathId = pWaypoint->getPath(i); + const int iPathId = pWaypoint->getPath(i); // isn't visible to the target if ( !pTable->GetVisibilityFromTo(iAimWpt,iPathId) ) @@ -3255,14 +3316,14 @@ void CBotTF2Snipe :: execute (CBot *pBot,CBotSchedule *pSchedule) if (m_iHideWaypoint == -1) { // can't find a useful hide waypoint -- choose a random one - int pathid = randomInt(0, pWaypoint->numPaths()); + const int pathid = randomInt(0, pWaypoint->numPaths()); m_iHideWaypoint = pWaypoint->getPath(pathid); if (m_iHideWaypoint != -1) { CWaypoint *pHideWaypoint = CWaypoints::getWaypoint(m_iHideWaypoint); - if (pHideWaypoint != NULL) + if (pHideWaypoint != nullptr) { m_vHideOrigin = pHideWaypoint->getOrigin(); } @@ -3292,12 +3353,12 @@ void CBotTF2Snipe :: execute (CBot *pBot,CBotSchedule *pSchedule) pBot->setLookAtTask(LOOK_SNIPE); // saw an enemy less than 5 secs ago - if ( (m_fEnemyTime + 5.0f) > engine->Time() ) + if ( m_fEnemyTime + 5.0f > engine->Time() ) pBot->setAiming(m_vEnemy); else pBot->setAiming(m_vAim); - if ( !pBot->isTF() || (((CBotFortress*)pBot)->getClass() != TF_CLASS_SNIPER) || (pBot->getHealthPercent() < 0.2) ) + if ( !pBot->isTF() || static_cast(pBot)->getClass() != TF_CLASS_SNIPER || pBot->getHealthPercent() < 0.2f ) { // out of health -- finish if ( CTeamFortress2Mod::TF2_IsPlayerZoomed(pBot->getEdict()) ) @@ -3306,7 +3367,7 @@ void CBotTF2Snipe :: execute (CBot *pBot,CBotSchedule *pSchedule) fail(); return; } - else if ( pBotWeapon->getAmmo(pBot) < 1 ) + if ( pBotWeapon->getAmmo(pBot) < 1 ) { // out of ammo -- finish if ( CTeamFortress2Mod::TF2_IsPlayerZoomed(pBot->getEdict()) ) @@ -3321,7 +3382,7 @@ void CBotTF2Snipe :: execute (CBot *pBot,CBotSchedule *pSchedule) // too far away fail(); } - else if ( (m_iHideWaypoint != -1) && (((CBotFortress*)pBot)->incomingRocket(512.0f) || (m_fHideTime > engine->Time())) ) + else if ( m_iHideWaypoint != -1 && (static_cast(pBot)->incomingRocket(512.0f) || m_fHideTime > engine->Time()) ) { // hide time -- move to hide origin pBot->setMoveTo(m_vHideOrigin); @@ -3346,16 +3407,17 @@ void CBotTF2Snipe :: execute (CBot *pBot,CBotSchedule *pSchedule) if ( CTeamFortress2Mod::TF2_IsPlayerZoomed(pBot->getEdict()) && pBot->hasEnemy() ) { - if ( pBot->hasSomeConditions(CONDITION_SEE_CUR_ENEMY) ) + if (pBot->hasSomeConditions(CONDITION_SEE_CUR_ENEMY)) { m_vEnemy = CBotGlobals::entityOrigin(pBot->getEnemy()); m_fEnemyTime = engine->Time(); - if ( m_fAimTime == 0.0f ) - m_fAimTime = engine->Time() + randomFloat(0.1f,0.3f); + // Check m_fEnemyTime instead of m_fAimTime if that was the intention - [APG]RoboCop[CL] + if (m_fEnemyTime == 0.0f) + m_fEnemyTime = engine->Time() + randomFloat(0.1f, 0.3f); // too close for sniper rifle - if ( pBot->distanceFrom(pBot->getEnemy()) < 200.0f ) + if (pBot->distanceFrom(pBot->getEnemy()) < 200.0f) { complete(); return; @@ -3369,7 +3431,7 @@ void CBotTF2Snipe :: execute (CBot *pBot,CBotSchedule *pSchedule) pBot->setLookAtTask(LOOK_ENEMY); - float angle = pBot->DotProductFromOrigin(CBotGlobals::entityOrigin(pBot->getEnemy())); + const float angle = pBot->DotProductFromOrigin(CBotGlobals::entityOrigin(pBot->getEnemy())); if ( angle > 0.96f ) // 16 degrees { @@ -3384,7 +3446,7 @@ void CBotTF2Snipe :: execute (CBot *pBot,CBotSchedule *pSchedule) if ( CBotGlobals::isPlayer(pBot->getEnemy()) ) bhide = CBotGlobals::DotProductFromOrigin(pBot->getEnemy(),pBot->getOrigin()) > 0.96f; else - bhide = randomFloat(0.0f,2.0f) <= (angle+(1.0f-pBot->getHealthPercent())); + bhide = randomFloat(0.0f,2.0f) <= angle+(1.0f-pBot->getHealthPercent()); if ( bhide ) m_fHideTime = engine->Time() + randomFloat(1.5f,2.5f); @@ -3428,7 +3490,7 @@ void CBotTF2Snipe :: execute (CBot *pBot,CBotSchedule *pSchedule) ///////////////////////////////////////////////////// -CBotTF2SpySap :: CBotTF2SpySap ( edict_t *pBuilding, eEngiBuild id ) +CBotTF2SpySap :: CBotTF2SpySap ( edict_t *pBuilding, const eEngiBuild id ) { m_pBuilding = MyEHandle(pBuilding); m_fTime = 0.0f; @@ -3437,8 +3499,7 @@ CBotTF2SpySap :: CBotTF2SpySap ( edict_t *pBuilding, eEngiBuild id ) void CBotTF2SpySap :: execute (CBot *pBot,CBotSchedule *pSchedule) { - edict_t *pBuilding; - CBotTF2 *tf2Bot = (CBotTF2*)pBot; + CBotTF2 *tf2Bot = static_cast(pBot); if ( !pBot->isTF() ) { @@ -3453,10 +3514,9 @@ void CBotTF2SpySap :: execute (CBot *pBot,CBotSchedule *pSchedule) } - CBotWeapon *weapon; pBot->wantToShoot(false); - pBuilding = m_pBuilding.get(); + edict_t* pBuilding = m_pBuilding.get(); if ( !pBuilding ) { @@ -3480,7 +3540,7 @@ void CBotTF2SpySap :: execute (CBot *pBot,CBotSchedule *pSchedule) return; } } - else if ( m_id == ENGI_TELE) + else if ( m_id == ENGI_TELE ) { if ( CTeamFortress2Mod::isTeleporterSapped(pBuilding) ) { @@ -3491,12 +3551,12 @@ void CBotTF2SpySap :: execute (CBot *pBot,CBotSchedule *pSchedule) pBot->lookAtEdict(pBuilding); pBot->setLookAtTask(LOOK_EDICT,0.2f); - weapon = tf2Bot->getCurrentWeapon(); + const CBotWeapon* weapon = tf2Bot->getCurrentWeapon(); // time out if ( m_fTime < engine->Time() ) fail(); - else if ( !weapon || (weapon->getID() != TF2_WEAPON_BUILDER) ) + else if ( !weapon || weapon->getID() != TF2_WEAPON_BUILDER ) { helpers->ClientCommand(pBot->getEdict(),"build 3 0"); } @@ -3504,7 +3564,7 @@ void CBotTF2SpySap :: execute (CBot *pBot,CBotSchedule *pSchedule) { if ( pBot->distanceFrom(pBuilding) > 100 ) { - pBot->setMoveTo((CBotGlobals::entityOrigin(pBuilding))); + pBot->setMoveTo(CBotGlobals::entityOrigin(pBuilding)); } else { @@ -3520,18 +3580,18 @@ void CBotTF2SpySap :: execute (CBot *pBot,CBotSchedule *pSchedule) } -void CBotTF2SpySap :: debugString ( char *string ) +void CBotTF2SpySap :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CBotTF2SpySap"); + std::sprintf(string,"CBotTF2SpySap"); } ///////////////////////////////////////////////////// -CBotTFUseTeleporter :: CBotTFUseTeleporter ( edict_t *pTele ) +CBotTFUseTeleporter :: CBotTFUseTeleporter (edict_t *pTele) : m_pTele(pTele) {// going to use this - m_pTele = pTele; - m_fTime = 0.0; + + m_fTime = 0.0f; } void CBotTFUseTeleporter :: execute (CBot *pBot,CBotSchedule *pSchedule) @@ -3544,14 +3604,14 @@ void CBotTFUseTeleporter :: execute (CBot *pBot,CBotSchedule *pSchedule) if ( !pBot->isTF() ) { - if ( ((CBotFortress*)pBot)->hasFlag() ) + if ( static_cast(pBot)->hasFlag() ) { fail(); return; } } - if ( !m_fTime ) + if (m_fTime == 0.0f) { // initialize m_fTime = engine->Time() + 13.0f; @@ -3574,11 +3634,11 @@ void CBotTFUseTeleporter :: execute (CBot *pBot,CBotSchedule *pSchedule) { if ( CTeamFortress2Mod::getTeleporterExit(m_pTele) ) // exit is still alive? { - Vector vTele = CBotGlobals::entityOrigin(m_pTele); + const Vector vTele = CBotGlobals::entityOrigin(m_pTele); - if ( (pBot->distanceFrom(vTele) > 48) || (CClassInterface::getGroundEntity(pBot->getEdict())!=m_pTele.get()) ) + if ( pBot->distanceFrom(vTele) > 48 || CClassInterface::getGroundEntity(pBot->getEdict())!=m_pTele.get() ) { - pBot->setMoveTo((vTele)); + pBot->setMoveTo(vTele); if ( (m_vLastOrigin - pBot->getOrigin()).Length() > 50 ) { @@ -3600,26 +3660,25 @@ void CBotTFUseTeleporter :: execute (CBot *pBot,CBotSchedule *pSchedule) } } -void CBotTFUseTeleporter :: debugString ( char *string ) +void CBotTFUseTeleporter::debugString(char* string, const unsigned bufferSize) { - sprintf(string,"CBotTFUseTeleporter\nm_pTele = %x",(int)m_pTele.get()); + snprintf(string, bufferSize, "CBotTFUseTeleporter\nm_pTele = %p", m_pTele.get()); } /////////////////////////////////////////////////// -CAttackEntityTask :: CAttackEntityTask ( edict_t *pEdict ) +CAttackEntityTask :: CAttackEntityTask (edict_t *pEdict) : m_pEdict(pEdict) { - m_pEdict = pEdict; } -void CAttackEntityTask :: debugString ( char *string ) +void CAttackEntityTask :: debugString (char* string, unsigned bufferSize) { int id = -1; if ( m_pEdict ) - id = ENTINDEX(m_pEdict); + id = ENTINDEX(m_pEdict); - sprintf(string,"CAttackEntityTask (%d)",id); + std::sprintf(string,"CAttackEntityTask (%d)",id); } void CAttackEntityTask :: init () @@ -3628,11 +3687,9 @@ void CAttackEntityTask :: init () //setCompleteInterrupt ( CONDITION_ENEMY_DEAD ); } -void CAttackEntityTask :: execute (CBot *pBot,CBotSchedule *pSchedule) +void CAttackEntityTask :: execute (CBot *pBot, CBotSchedule *pSchedule) { - CBotWeapon *pWeapon; - - if ( m_pEdict.get() == NULL ) + if ( m_pEdict.get() == nullptr) { fail(); return; @@ -3656,11 +3713,10 @@ void CAttackEntityTask :: execute (CBot *pBot,CBotSchedule *pSchedule) return; } - pWeapon = pBot->getBestWeapon(m_pEdict); + CBotWeapon* pWeapon = pBot->getBestWeapon(m_pEdict); - if ( (pWeapon != NULL) && (pWeapon != pBot->getCurrentWeapon()) && pWeapon->getWeaponIndex() ) + if ( pWeapon != nullptr && pWeapon != pBot->getCurrentWeapon() && pWeapon->getWeaponIndex() ) { - //pBot->selectWeaponSlot(pWeapon->getWeaponInfo()->getSlot()); pBot->selectWeapon(pWeapon->getWeaponIndex()); } @@ -3673,38 +3729,36 @@ void CAttackEntityTask :: execute (CBot *pBot,CBotSchedule *pSchedule) } /// -CThrowGrenadeTask :: CThrowGrenadeTask (CBotWeapon *pWeapon, int ammo, Vector vLoc ) +CThrowGrenadeTask :: CThrowGrenadeTask (CBotWeapon *pWeapon, const int ammo, const Vector& vLoc) : m_vLoc(vLoc) { m_pWeapon = pWeapon; - m_fTime = 0; - m_vLoc = vLoc; + m_fTime = 0.0f; - m_fHoldAttackTime = 0; + m_fHoldAttackTime = 0.0f; m_iAmmo = ammo; } void CThrowGrenadeTask ::init() { - m_fTime = 0; + m_fTime = 0.0f; } - -void CThrowGrenadeTask::debugString(char *string) +void CThrowGrenadeTask::debugString(char* string, unsigned bufferSize) { - sprintf(string,"CThrowGrenadeTask\nm_vLoc =(%0.4f,%0.4f,%0.4f)\nfTime = %0.4f",m_vLoc.x,m_vLoc.y,m_vLoc.z,m_fTime); + std::sprintf(string,"CThrowGrenadeTask\nm_vLoc =(%0.4f,%0.4f,%0.4f)\nfTime = %0.4f",m_vLoc.x,m_vLoc.y,m_vLoc.z,m_fTime); } void CThrowGrenadeTask ::execute (CBot *pBot,CBotSchedule *pSchedule) { - if ( m_fTime == 0 ) + if ( m_fTime == 0.0f ) { m_fTime = engine->Time() + 2.5f; - if ( sv_gravity ) + if ( sv_gravity.IsValid() ) { - float fFraction = pBot->distanceFrom(m_vLoc)/MAX_GREN_THROW_DIST; + const float fFraction = pBot->distanceFrom(m_vLoc)/MAX_GREN_THROW_DIST; //m_vLoc.z = m_vLoc.z + getGrenadeZ(pBot->getOrigin(),m_vLoc,m_pWeapon->getProjectileSpeed()); - m_vLoc.z = m_vLoc.z + (sv_gravity->GetFloat() * randomFloat(1.5f,2.5f) * fFraction); + m_vLoc.z = m_vLoc.z + (sv_gravity.GetFloat() * randomFloat(1.5f,2.5f) * fFraction); } } @@ -3728,15 +3782,13 @@ void CThrowGrenadeTask ::execute (CBot *pBot,CBotSchedule *pSchedule) return; } - if ( !m_pWeapon ) + /*if ( !m_pWeapon ) { fail(); return; - } - - CBotWeapon *pWeapon; + }*/ - pWeapon = pBot->getCurrentWeapon(); + const CBotWeapon* pWeapon = pBot->getCurrentWeapon(); pBot->wantToChangeWeapon(false); if ( pWeapon && pWeapon->isGravGun() && CClassInterface::gravityGunObject(INDEXENT(pWeapon->getWeaponIndex())) ) @@ -3769,14 +3821,14 @@ void CThrowGrenadeTask ::execute (CBot *pBot,CBotSchedule *pSchedule) } } /// -CBotInvestigateHidePoint :: CBotInvestigateHidePoint ( int iWaypointIndexToInvestigate, int iOriginalWaypointIndex ) +CBotInvestigateHidePoint :: CBotInvestigateHidePoint (const int iWaypointIndexToInvestigate, const int iOriginalWaypointIndex) { CWaypoint *pWaypoint = CWaypoints::getWaypoint(iWaypointIndexToInvestigate); CWaypoint *pOriginalWpt = CWaypoints::getWaypoint(iOriginalWaypointIndex); m_vOrigin = pOriginalWpt->getOrigin(); m_vMoveTo = pWaypoint->getOrigin(); - m_fTime = 0; - m_fInvestigateTime = 0; + m_fTime = 0.0f; + m_fInvestigateTime = 0.0f; m_iState = 0; for ( int i = 0; i < pWaypoint->numPaths(); i ++ ) @@ -3788,7 +3840,7 @@ CBotInvestigateHidePoint :: CBotInvestigateHidePoint ( int iWaypointIndexToInves if ( pWaypointOther == pOriginalWpt ) continue; - m_CheckPoints.push_back(pWaypointOther->getOrigin()); + m_CheckPoints.emplace_back(pWaypointOther->getOrigin()); } m_iCurrentCheckPoint = 0; @@ -3796,7 +3848,7 @@ CBotInvestigateHidePoint :: CBotInvestigateHidePoint ( int iWaypointIndexToInves void CBotInvestigateHidePoint:: execute (CBot *pBot,CBotSchedule *pSchedule) { - if ( m_fTime == 0 ) + if ( m_fTime == 0.0f ) { m_fTime = engine->Time() + randomFloat(6.0f, 8.0f); m_fInvestigateTime = randomFloat(0.3f,1.0f); @@ -3812,7 +3864,7 @@ void CBotInvestigateHidePoint:: execute (CBot *pBot,CBotSchedule *pSchedule) } } - if ( m_CheckPoints.size() == 0 ) + if (m_CheckPoints.empty()) { // don't move, just look pBot->setLookVector(m_vMoveTo); @@ -3873,9 +3925,9 @@ void CBotInvestigateHidePoint:: execute (CBot *pBot,CBotSchedule *pSchedule) } } -void CBotInvestigateHidePoint::debugString ( char *string ) +void CBotInvestigateHidePoint::debugString (char* string, unsigned bufferSize) { - sprintf(string,"CBotInvestigateHidePoint"); + std::sprintf(string,"CBotInvestigateHidePoint"); } ////// @@ -3884,12 +3936,12 @@ void CAutoBuy :: init () m_bTimeset = false; } -void CAutoBuy :: execute (CBot *pBot,CBotSchedule *pSchedule) +void CAutoBuy :: execute (CBot *pBot, CBotSchedule *pSchedule) { if ( !m_bTimeset ) { m_bTimeset = true; - m_fTime = engine->Time() + randomFloat(2.0,4.0); + m_fTime = engine->Time() + randomFloat(2.0f,4.0f); } else if ( m_fTime < engine->Time() ) { @@ -3900,47 +3952,296 @@ void CAutoBuy :: execute (CBot *pBot,CBotSchedule *pSchedule) } } -CFindLastEnemy::CFindLastEnemy (Vector vLast,Vector vVelocity) +void CCSSPerformBuyTask::init() { - setCompleteInterrupt(CONDITION_SEE_CUR_ENEMY); - m_vLast = vLast+(vVelocity*10); - m_fTime = 0; + m_fDelay = engine->Time() + randomFloat(2.0f, 5.0f); } -void CFindLastEnemy::execute ( CBot *pBot, CBotSchedule *pSchedule ) +void CCSSPerformBuyTask::execute(CBot *pBot, CBotSchedule *pSchedule) { - if ( m_fTime == 0 ) - m_fTime = engine->Time() + randomFloat(2.0,4.0); - - if ( !pBot->moveToIsValid() || pBot->moveFailed() ) - fail(); - if ( pBot->distanceFrom(m_vLast) > 80 ) - pBot->setMoveTo(m_vLast); + if(m_fDelay <= engine->Time()) + { + if(!CClassInterface::isCSPlayerInBuyZone(pBot->getEdict())) + { + fail(); // outside buy zone + return; + } + CCSSBot *pCSSBot = static_cast(pBot); + pCSSBot->runBuy(); + complete(); + } else + { pBot->stopMoving(); + pBot->wantToShoot(false); + pBot->setMoveLookPriority(MOVELOOK_OVERRIDE); + pBot->setLookAtTask(LOOK_AROUND); + pBot->setMoveLookPriority(MOVELOOK_TASK); + } +} +void CCSSPlantTheBombTask::execute(CBot *pBot, CBotSchedule *pSchedule) +{ + pBot->stopMoving(); + pBot->wantToShoot(false); + pBot->wantToChangeWeapon(false); + pBot->setMoveLookPriority(MOVELOOK_OVERRIDE); pBot->setLookAtTask(LOOK_AROUND); + pBot->setMoveLookPriority(MOVELOOK_TASK); - if ( m_fTime < engine->Time() ) + if(!CCounterStrikeSourceMod::isBombCarrier(pBot)) + { complete(); -} -//////////////////////// -CFollowTask :: CFollowTask ( edict_t *pFollow ) -{ - m_pFollow = pFollow; - m_fFollowTime = 0; - m_vLastSeeVector = CBotGlobals::entityOrigin(pFollow); - CClassInterface::getVelocity(pFollow,&m_vLastSeeVelocity); -} - -void CFollowTask :: init () -{ + pBot->letGoOfButton(IN_ATTACK); + return; + } + if(CClassInterface::isCSPlayerInBombZone(pBot->getEdict())) + { + if(pBot->getCurrentWeapon() != pBot->getWeapons()->getWeapon(CWeapons::getWeapon(CS_WEAPON_C4))) + { + pBot->selectBotWeapon(pBot->getWeapons()->getWeapon(CWeapons::getWeapon(CS_WEAPON_C4))); + } + else + { + pBot->primaryAttack(true); + } + } + else + { + if(CClassInterface::getGroundEntity(pBot->getEdict()) != nullptr) + { // Must be on ground to fail since you can't plant while in the air and the bot might have to jump to reach some plant spots + fail(); + } + } } -void CFollowTask::execute ( CBot *pBot, CBotSchedule *pSchedule ) +void CCSSEngageEnemyTask::execute(CBot *pBot, CBotSchedule *pSchedule) { - if ( m_pFollow.get() == NULL ) + edict_t *pEnemy = engine->PEntityOfEntIndex(m_hEnemy.GetEntryIndex()); + const edict_t *pWeapon = CClassInterface::getCurrentWeapon(pBot->getEdict()); + isBrush = CBotGlobals::isBrushEntity(pEnemy); + + if(pBot->hasSomeConditions(CONDITION_OUT_OF_AMMO)) + { + fail(); + return; + } + + if(pBot->getEnemy() == nullptr || pBot->getEnemy() != pEnemy) + { + fail(); + return; + } + + if(pEnemy) + { + if(pWeapon) + { + if(const CBotWeapon *weapon = pBot->getWeapons()->getWeapon(CWeapons::getWeaponByShortName(pWeapon->GetClassName()))) + { + if(weapon->isMelee()) + { + if(isBrush) + pBot->setMoveTo(CBotGlobals::worldCenter(pEnemy)); + else + pBot->setMoveTo(CBotGlobals::entityOrigin(pEnemy)); + } + else + { + pBot->stopMoving(); + } + } + } + else + { + pBot->stopMoving(); + } + + if(!CBotGlobals::entityIsAlive(pEnemy)) + { + complete(); + } + + pBot->setLookAtTask(LOOK_ENEMY); + //pBot->handleAttack(pBot->getCurrentWeapon(), pBot->getEnemy()); + } + else + { + complete(); + } +} + +void CCSSEngageEnemyTask::debugString(char* string, unsigned bufferSize) +{ + const edict_t *pEnemy = engine->PEntityOfEntIndex(m_hEnemy.GetEntryIndex()); + std::sprintf(string,"CSS Engage Enemy\n%s", pEnemy ? pEnemy->GetClassName() : "null"); +} + +void CCSSDefuseTheBombTask::execute(CBot *pBot, CBotSchedule *pSchedule) +{ + pBot->stopMoving(); + pBot->setMoveLookPriority(MOVELOOK_OVERRIDE); + pBot->setLookVector(m_vBomb); + pBot->setLookAtTask(LOOK_VECTOR); + pBot->setMoveLookPriority(MOVELOOK_TASK); + + if(pBot->distanceFrom(m_vBomb) >= 75.0f) + { + fail(); + } + + pBot->use(); + + if(CCounterStrikeSourceMod::isBombDefused()) + { + complete(); + } +} + +void CCSSGuardTask::execute(CBot *pBot, CBotSchedule *pSchedule) +{ + static CBotWeapon *pCurrentWeapon; + static CWeapon *pWeapon; + + static float fDist; + + pBot->wantToShoot(false); + pBot->wantToListen(false); + + if ( m_fTime == 0.0f ) + { + m_fEnemyTime = engine->Time(); + m_fTime = randomFloat(15.0f,30.0f); + pBot->resetLookAroundTime(); + } + + pCurrentWeapon = pBot->getCurrentWeapon(); + + if ( !pCurrentWeapon ) + { + fail(); + return; + } + + pWeapon = pCurrentWeapon->getWeaponInfo(); + + if (pWeapon == nullptr) + { + fail(); + return; + } + + if ( m_pWeaponToUse && pCurrentWeapon != m_pWeaponToUse ) + { + if ( !pBot->selectBotWeapon(m_pWeaponToUse) ) + { + fail(); + } + + return; + } + + if ( pCurrentWeapon->getAmmo(pBot) < 1 ) + { + complete(); + } + else if ( pBot->distanceFrom(m_vOrigin) > 200 ) // too far from sniper point + { + // too far away + fail(); + } + + if ( m_bUseZ ) + { + const Vector vAim = Vector(m_vAim.x,m_vAim.y,m_z); + pBot->setLookAtTask(LOOK_VECTOR); + pBot->setLookVector(pBot->snipe(vAim)); + } + else + { + pBot->setLookAtTask(LOOK_SNIPE); + pBot->setLookVector(pBot->snipe(m_vAim)); + } + + fDist = (m_vOrigin - pBot->getOrigin()).Length2D(); + + if ( fDist > 32 ) + { + pBot->setMoveTo(m_vOrigin); + pBot->setMoveSpeed(CClassInterface::getMaxSpeed(pBot->getEdict())/2); + } + else + { + pBot->stopMoving(); + + if ( m_iWaypointType & CWaypointTypes::W_FL_CROUCH ) + pBot->duck(); + + // no enemy for a while + if ( m_fEnemyTime + m_fTime < engine->Time() ) + { + complete(); + } + + if( pCurrentWeapon->isZoomable() && !CCounterStrikeSourceMod::isScoped(pBot) ) + { + pBot->secondaryAttack(false); + } + } + + if ( pBot->hasEnemy() ) + { + pBot->setMoveLookPriority(MOVELOOK_ATTACK); + pBot->setLookAtTask(LOOK_ENEMY); + pBot->handleAttack(pCurrentWeapon,pBot->getEnemy()); + pBot->setMoveLookPriority(MOVELOOK_TASK); + + // havin' fun + m_fEnemyTime = engine->Time(); + } +} + +CFindLastEnemy::CFindLastEnemy (const Vector& vLast, const Vector& vVelocity) +{ + setCompleteInterrupt(CONDITION_SEE_CUR_ENEMY); + m_vLast = vLast+vVelocity*10; + m_fTime = 0.0f; +} + +void CFindLastEnemy::execute ( CBot *pBot, CBotSchedule *pSchedule ) +{ + if ( m_fTime == 0.0f ) + m_fTime = engine->Time() + randomFloat(2.0f,4.0f); + + if ( !pBot->moveToIsValid() || pBot->moveFailed() ) + fail(); + if ( pBot->distanceFrom(m_vLast) > 80 ) + pBot->setMoveTo(m_vLast); + else + pBot->stopMoving(); + + pBot->setLookAtTask(LOOK_AROUND); + + if ( m_fTime < engine->Time() ) + complete(); +} +//////////////////////// +CFollowTask :: CFollowTask (edict_t *pFollow) : m_pFollow(pFollow) +{ + m_fFollowTime = 0; + m_vLastSeeVector = CBotGlobals::entityOrigin(pFollow); + CClassInterface::getVelocity(pFollow,&m_vLastSeeVelocity); +} + +void CFollowTask :: init () +{ + +} + +void CFollowTask::execute ( CBot *pBot, CBotSchedule *pSchedule ) +{ + if ( m_pFollow.get() == nullptr) { fail(); return; @@ -3975,28 +4276,30 @@ void CFollowTask::execute ( CBot *pBot, CBotSchedule *pSchedule ) complete(); } -void CFollowTask::debugString ( char *string ) +void CFollowTask::debugString (char* string, unsigned bufferSize) { - sprintf(string,"CFollowTask\nm_pFollow =(%s)",engine->GetPlayerNetworkIDString(m_pFollow)); + std::sprintf(string,"CFollowTask\nm_pFollow =(%s)",engine->GetPlayerNetworkIDString(m_pFollow)); } //////////////////////////////////////////////// -void CDODDropAmmoTask :: debugString ( char *string ) +void CDODDropAmmoTask :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CDODDropAmmoTask"); + std::sprintf(string,"CDODDropAmmoTask"); } -void CDODDropAmmoTask :: execute (CBot *pBot,CBotSchedule *pSchedule) +void CDODDropAmmoTask :: execute (CBot *pBot, CBotSchedule *pSchedule) { - Vector vOrigin = CBotGlobals::entityOrigin(m_pPlayer.get()); + edict_t* pPlayer = m_pPlayer.get(); - if ( m_pPlayer.get() == NULL ) + if (!pPlayer) { fail(); return; } - if ( !CBotGlobals::entityIsAlive(m_pPlayer) ) + const Vector vOrigin = CBotGlobals::entityOrigin(pPlayer); + + if (!CBotGlobals::entityIsAlive(pPlayer)) { fail(); return; @@ -4008,27 +4311,25 @@ void CDODDropAmmoTask :: execute (CBot *pBot,CBotSchedule *pSchedule) if ( pBot->isFacing(vOrigin) ) { - if ( !pBot->isVisible(m_pPlayer) ) + if (!pBot->isVisible(m_pPlayer)) { fail(); return; } } - if ( (pBot->distanceFrom(m_pPlayer) < 200.0f) && pBot->isFacing(vOrigin) ) + if (pBot->distanceFrom(pPlayer) < 200.0f && pBot->isFacing(vOrigin)) { - CDODBot *pDODBot = ((CDODBot*)pBot); + CDODBot *pDODBot = static_cast(pBot); pDODBot->dropAmmo(); complete(); - return; } } //////////////////////////////////////////// -CCrouchHideTask :: CCrouchHideTask( edict_t *pHideFrom ) +CCrouchHideTask::CCrouchHideTask(edict_t *pHideFrom) : m_pHideFrom(pHideFrom) { - m_pHideFrom = pHideFrom; m_vLastSeeVector = CBotGlobals::entityOrigin(pHideFrom); m_bCrouching = true; // duck m_fChangeTime = 0.0f; @@ -4042,16 +4343,16 @@ void CCrouchHideTask :: init () m_fHideTime = 0.0f; } -void CCrouchHideTask :: debugString ( char *string ) +void CCrouchHideTask :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CCrouchHideTask\nm_pHideFrom =(%s)",engine->GetPlayerNetworkIDString(m_pHideFrom)); + std::sprintf(string,"CCrouchHideTask\nm_pHideFrom =(%s)",engine->GetPlayerNetworkIDString(m_pHideFrom)); } void CCrouchHideTask :: execute ( CBot *pBot, CBotSchedule *pSchedule ) { pBot->wantToListen(false); - if ( m_pHideFrom.get() == NULL ) + if ( m_pHideFrom.get() == nullptr) { complete(); return; @@ -4062,7 +4363,7 @@ void CCrouchHideTask :: execute ( CBot *pBot, CBotSchedule *pSchedule ) return; } - if ( m_fHideTime == 0 ) + if ( m_fHideTime == 0.0f ) m_fHideTime = engine->Time() + randomFloat(7.0f,14.0f); if ( m_fChangeTime == 0.0f ) @@ -4101,21 +4402,21 @@ void CCrouchHideTask :: execute ( CBot *pBot, CBotSchedule *pSchedule ) complete(); } + //////////////////////////////////////////////////////// -CHideTask :: CHideTask( Vector vHideFrom ) +CHideTask :: CHideTask(const Vector& vHideFrom) : m_vHideFrom(vHideFrom) { - m_vHideFrom = vHideFrom; + m_fHideTime = 0.0f; } - -void CHideTask :: debugString ( char *string ) +void CHideTask :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CHideTask\nm_vHideFrom =(%0.4f,%0.4f,%0.4f)",m_vHideFrom.x,m_vHideFrom.y,m_vHideFrom.z); + std::sprintf(string,"CHideTask\nm_vHideFrom =(%0.4f,%0.4f,%0.4f)",m_vHideFrom.x,m_vHideFrom.y,m_vHideFrom.z); } void CHideTask :: init () { - m_fHideTime = 0; + m_fHideTime = 0.0f; } void CHideTask :: execute ( CBot *pBot, CBotSchedule *pSchedule ) @@ -4125,32 +4426,30 @@ void CHideTask :: execute ( CBot *pBot, CBotSchedule *pSchedule ) pBot->setLookAtTask(LOOK_VECTOR); pBot->duck(true); - if ( m_fHideTime == 0 ) - m_fHideTime = engine->Time() + randomFloat(5.0,10.0); + if ( m_fHideTime == 0.0f ) + m_fHideTime = engine->Time() + randomFloat(5.0f,10.0f); if ( m_fHideTime < engine->Time() ) complete(); } /////////////////////////////////////////// -CBotTF2DemomanPipeJump :: CBotTF2DemomanPipeJump ( CBot *pBot, Vector vWaypointGround, - Vector vWaypointNext, - CBotWeapon *pWeapon ) +CBotTF2DemomanPipeJump::CBotTF2DemomanPipeJump (CBot *pBot, const Vector& vWaypointGround, + const Vector& vWaypointNext, CBotWeapon *pWeapon) : m_vEnd(vWaypointNext) { m_iStartingAmmo = pWeapon->getClip1(pBot); - m_vStart = vWaypointGround - Vector(0,0,48.0); - m_vEnd = vWaypointNext; - m_pPipeBomb = NULL; - m_fTime = 0; + m_vStart = vWaypointGround - Vector(0,0,48.0f); + m_pPipeBomb = nullptr; + m_fTime = 0.0f; m_iState = 0; m_pWeapon = pWeapon; m_bFired = false; } -void CBotTF2DemomanPipeJump :: execute (CBot *pBot,CBotSchedule *pSchedule) +void CBotTF2DemomanPipeJump :: execute (CBot *pBot, CBotSchedule *pSchedule) { pBot->wantToListen(false); - if ( m_fTime == 0 ) + if ( m_fTime == 0.0f ) { // init m_fTime = engine->Time() + randomFloat(5.0f,10.0f); @@ -4165,9 +4464,12 @@ void CBotTF2DemomanPipeJump :: execute (CBot *pBot,CBotSchedule *pSchedule) return; } - if ( m_pPipeBomb ) + edict_t* pPipeBomb = m_pPipeBomb.get(); + + // pipe bomb entity is set on state 0 + if (m_iState > 0) { - if ( !CBotGlobals::entityIsValid(m_pPipeBomb) ) + if (!rcbot2utils::IsValidEdict(pPipeBomb)) { fail(); return; @@ -4188,16 +4490,17 @@ void CBotTF2DemomanPipeJump :: execute (CBot *pBot,CBotSchedule *pSchedule) { if ( !m_bFired && !m_iStartingAmmo ) m_iStartingAmmo = m_pWeapon->getClip1(pBot); - else if ( m_bFired && (m_iStartingAmmo > m_pWeapon->getClip1(pBot)) ) + else if ( m_bFired && m_iStartingAmmo > m_pWeapon->getClip1(pBot) ) { // find pipe bomb - m_pPipeBomb = CClassInterface::FindEntityByClassnameNearest(pBot->getOrigin(),"tf_projectile_pipe_remote",150.0f,NULL); + edict_t* pipe = CClassInterface::FindEntityByClassnameNearest(pBot->getOrigin(), "tf_projectile_pipe_remote", 150.0f, nullptr); - if ( m_pPipeBomb ) + if (rcbot2utils::IsValidEdict(pipe)) { // set this up incase of fail, the bot knows he has a sticky there - ((CBotTF2*)pBot)->setStickyTrapType(m_vStart,TF_TRAP_TYPE_ENEMY); + static_cast(pBot)->setStickyTrapType(m_vStart,TF_TRAP_TYPE_ENEMY); m_iState++; + m_pPipeBomb = pipe; } else fail(); @@ -4209,7 +4512,7 @@ void CBotTF2DemomanPipeJump :: execute (CBot *pBot,CBotSchedule *pSchedule) if ( pBot->distanceFrom(m_vStart) < 150 ) { - if ( pBot->DotProductFromOrigin(m_vStart) > 0.99 ) + if ( pBot->DotProductFromOrigin(m_vStart) > 0.99f ) { if ( randomInt(0,1) ) { @@ -4227,26 +4530,23 @@ void CBotTF2DemomanPipeJump :: execute (CBot *pBot,CBotSchedule *pSchedule) break; case 1: { - Vector v_comp; - Vector v_startrunup; - Vector v_pipe; Vector vel; - extern ConVar rcbot_demo_runup_dist; - if ( CClassInterface::getVelocity(m_pPipeBomb,&vel) ) + if ( CClassInterface::getVelocity(pPipeBomb, &vel) ) { - if ( vel.Length() > 1.0 ) + if ( vel.Length() > 1.0f ) break; // wait until the pipe bomb has rested } - v_comp = m_vEnd - m_vStart; + Vector v_comp = m_vEnd - m_vStart; v_comp = v_comp / v_comp.Length(); - v_pipe = CBotGlobals::entityOrigin(m_pPipeBomb); - v_startrunup = v_pipe - (v_comp * rcbot_demo_runup_dist.GetFloat()); + const Vector v_pipe = CBotGlobals::entityOrigin(pPipeBomb); + + Vector v_startrunup = v_pipe - v_comp * rcbot_demo_runup_dist.GetFloat(); v_startrunup.z = v_pipe.z; - pBot->lookAtEdict(m_pPipeBomb); + pBot->lookAtEdict(pPipeBomb); pBot->setLookAtTask(LOOK_EDICT); // m_pPipeBomb != NULL @@ -4261,16 +4561,12 @@ void CBotTF2DemomanPipeJump :: execute (CBot *pBot,CBotSchedule *pSchedule) break; case 2: { - Vector v_comp; - extern ConVar rcbot_demo_runup_dist; - Vector v_endrunup; - Vector v_pipe; - - v_comp = m_vEnd - m_vStart; + Vector v_comp = m_vEnd - m_vStart; v_comp = v_comp / v_comp.Length(); - v_pipe = CBotGlobals::entityOrigin(m_pPipeBomb); - v_endrunup = v_pipe + (v_comp * rcbot_demo_runup_dist.GetFloat()); + const Vector v_pipe = CBotGlobals::entityOrigin(pPipeBomb); + + Vector v_endrunup = v_pipe + v_comp * rcbot_demo_runup_dist.GetFloat(); v_endrunup.z = v_pipe.z; pBot->setLookVector(m_vEnd); @@ -4300,13 +4596,13 @@ void CBotTF2DemomanPipeJump :: execute (CBot *pBot,CBotSchedule *pSchedule) { if ( vel.z > 10 ) { - ((CBotTF2*)pBot)->detonateStickies(true); + static_cast(pBot)->detonateStickies(true); complete(); } } else { - ((CBotTF2*)pBot)->detonateStickies(true); + static_cast(pBot)->detonateStickies(true); complete(); } } @@ -4317,20 +4613,19 @@ void CBotTF2DemomanPipeJump :: execute (CBot *pBot,CBotSchedule *pSchedule) } ////////////////////////////////////////// -CBotTF2DemomanPipeEnemy :: CBotTF2DemomanPipeEnemy ( CBotWeapon *pPipeLauncher, Vector vEnemy, edict_t *pEnemy ) +CBotTF2DemomanPipeEnemy::CBotTF2DemomanPipeEnemy(CBotWeapon* pPipeLauncher, const Vector& vEnemy, + edict_t* pEnemy) : m_vStand(vEnemy), m_vEnemy(vEnemy), m_vAim(vEnemy) { - m_vEnemy = vEnemy; m_pEnemy = MyEHandle(pEnemy); m_fTime = 0.0f; - m_vAim = vEnemy; m_pPipeLauncher = pPipeLauncher; m_fHoldAttackTime = 0.0f; m_fHeldAttackTime = 0.0f; } -void CBotTF2DemomanPipeEnemy :: execute (CBot *pBot,CBotSchedule *pSchedule) +void CBotTF2DemomanPipeEnemy :: execute (CBot *pBot, CBotSchedule *pSchedule) { - if ( m_pEnemy.get() == NULL ) + if ( m_pEnemy.get() == nullptr) { fail(); return; @@ -4350,15 +4645,15 @@ void CBotTF2DemomanPipeEnemy :: execute (CBot *pBot,CBotSchedule *pSchedule) pBot->wantToListen(false); pBot->wantToInvestigateSound(false); - if ( m_fTime == 0 ) + if ( m_fTime == 0.0f ) { m_vStand = CWaypoints::getWaypoint(pSchedule->passedInt())->getOrigin(); - Vector vOtherWaypoint = pSchedule->passedVector(); - ((CBotTF2*)pBot)->setStickyTrapType(m_vEnemy,TF_TRAP_TYPE_ENEMY); + const Vector vOtherWaypoint = pSchedule->passedVector(); + static_cast(pBot)->setStickyTrapType(m_vEnemy,TF_TRAP_TYPE_ENEMY); // Need to Lob my pipes - if ( vOtherWaypoint.z > (m_vEnemy.z+32.0f) ) + if ( vOtherWaypoint.z > m_vEnemy.z+32.0f ) { m_vAim = m_vEnemy; //(m_vEnemy - pBot->getOrigin())/2; m_vAim.z = m_vEnemy.z + getGrenadeZ(pBot->getEdict(),m_pEnemy,pBot->getOrigin(),m_vEnemy,TF2_GRENADESPEED);//();//(sv_gravity->GetFloat() * randomFloat(0.9f,1.1f) * fFraction); @@ -4369,10 +4664,9 @@ void CBotTF2DemomanPipeEnemy :: execute (CBot *pBot,CBotSchedule *pSchedule) m_vAim = (vOtherWaypoint+m_vEnemy)/2; } - m_fHoldAttackTime = (pBot->distanceFrom(m_vEnemy)/512.0f) - 1.0f; + m_fHoldAttackTime = pBot->distanceFrom(m_vEnemy)/512.0f - 1.0f; - if ( m_fHoldAttackTime < 0.0f ) - m_fHoldAttackTime = 0.0f; + m_fHoldAttackTime = std::max(m_fHoldAttackTime, 0.0f); /* if ( sv_gravity ) @@ -4388,37 +4682,37 @@ void CBotTF2DemomanPipeEnemy :: execute (CBot *pBot,CBotSchedule *pSchedule) if ( pBot->distanceFrom(m_vStand) > 200 ) { fail(); - pBot->setLastEnemy(NULL); + pBot->setLastEnemy(nullptr); } - if ( !CBotGlobals::entityIsValid(m_pEnemy) || !CBotGlobals::entityIsAlive(m_pEnemy) || (m_fTime < engine->Time()) ) + if ( !CBotGlobals::entityIsValid(m_pEnemy) || !CBotGlobals::entityIsAlive(m_pEnemy) || m_fTime < engine->Time() ) { // blow up any grens before we finish //if ( m_pEnemy.get() && pBot->isVisible(m_pEnemy.get()) ) - ((CBotTF2*)pBot)->detonateStickies(true); + static_cast(pBot)->detonateStickies(true); complete(); - pBot->setLastEnemy(NULL); + pBot->setLastEnemy(nullptr); return; } pBot->wantToShoot(false); - if ( (m_pPipeLauncher->getAmmo(pBot) + m_pPipeLauncher->getClip1(pBot)) == 0 ) + if ( m_pPipeLauncher->getAmmo(pBot) + m_pPipeLauncher->getClip1(pBot) == 0 ) { if ( pBot->isVisible(m_pEnemy.get()) ) - ((CBotTF2*)pBot)->detonateStickies(true); + static_cast(pBot)->detonateStickies(true); complete(); - pBot->setLastEnemy(NULL); + pBot->setLastEnemy(nullptr); return; } if ( pBot->getCurrentWeapon() != m_pPipeLauncher ) { pBot->selectBotWeapon(m_pPipeLauncher); - pBot->setLastEnemy(NULL); + pBot->setLastEnemy(nullptr); return; } @@ -4437,39 +4731,37 @@ void CBotTF2DemomanPipeEnemy :: execute (CBot *pBot,CBotSchedule *pSchedule) pBot->setLookVector(m_vAim); pBot->stopMoving(); - if ( pBot->DotProductFromOrigin(m_vAim) > 0.99 ) + if ( pBot->DotProductFromOrigin(m_vAim) > 0.99f ) { - float fTime = engine->Time(); + const float fTime = engine->Time(); - if ( m_fHeldAttackTime == 0 ) - m_fHeldAttackTime = fTime + m_fHoldAttackTime + randomFloat(0.0,0.15); + if ( m_fHeldAttackTime == 0.0f ) + m_fHeldAttackTime = fTime + m_fHoldAttackTime + randomFloat(0.0f,0.15f); if ( m_fHeldAttackTime > fTime) pBot->primaryAttack(true); else { - if ( m_fHeldAttackTime < (fTime - 0.1f) ) - m_fHeldAttackTime = 0; + if ( m_fHeldAttackTime < fTime - 0.1f ) + m_fHeldAttackTime = 0.0f; pBot->letGoOfButton(IN_ATTACK); } - ((CBotTF2*)pBot)->setStickyTrapType(m_vEnemy,TF_TRAP_TYPE_ENEMY); + static_cast(pBot)->setStickyTrapType(m_vEnemy,TF_TRAP_TYPE_ENEMY); } } } ////////////////////////////////////////// -CBotTF2DemomanPipeTrap :: CBotTF2DemomanPipeTrap ( eDemoTrapType type, Vector vStand, Vector vLoc, Vector vSpread, bool bAutoDetonate, int wptarea ) +CBotTF2DemomanPipeTrap::CBotTF2DemomanPipeTrap(const eDemoTrapType type, const Vector& vStand, const Vector& vLoc, + const Vector& vSpread, const bool bAutoDetonate, const int wptarea) + : m_vPoint(vLoc), m_vStand(vStand), m_vLocation(vLoc), m_vSpread(vSpread) { - m_vPoint = vLoc; - m_vLocation = vLoc; - m_vSpread = vSpread; m_iState = 0; m_iStickies = 6; m_iTrapType = type; - m_vStand = vStand; m_fTime = 0.0f; m_bAutoDetonate = bAutoDetonate; m_iWptArea = wptarea; @@ -4478,8 +4770,8 @@ CBotTF2DemomanPipeTrap :: CBotTF2DemomanPipeTrap ( eDemoTrapType type, Vector vS void CBotTF2DemomanPipeTrap :: execute (CBot *pBot,CBotSchedule *pSchedule) { bool bFail = false; - CBotTF2 *pTF2Bot = (CBotTF2*)pBot; - if (pBot->getWeapons()->getWeapon(CWeapons::getWeapon(TF2_WEAPON_PIPEBOMBS)) == NULL) + CBotTF2 *pTF2Bot = static_cast(pBot); + if (pBot->getWeapons()->getWeapon(CWeapons::getWeapon(TF2_WEAPON_PIPEBOMBS)) == nullptr) { // don't have the weapon fail(); @@ -4509,10 +4801,9 @@ void CBotTF2DemomanPipeTrap :: execute (CBot *pBot,CBotSchedule *pSchedule) } ///////// -CMessAround::CMessAround ( edict_t *pFriendly, int iMaxVoiceCmd ) +CMessAround::CMessAround (edict_t *pFriendly, const int iMaxVoiceCmd) : m_pFriendly(pFriendly) { m_fTime = 0.0f; - m_pFriendly = pFriendly; m_iType = randomInt(0,3); m_iMaxVoiceCmd = iMaxVoiceCmd; } @@ -4530,7 +4821,7 @@ void CMessAround::execute ( CBot *pBot, CBotSchedule *pSchedule ) { case 0: { - Vector origin = CBotGlobals::entityOrigin(m_pFriendly); + const Vector origin = CBotGlobals::entityOrigin(m_pFriendly); pBot->setLookVector(origin); pBot->setLookAtTask(LOOK_VECTOR); @@ -4538,13 +4829,11 @@ void CMessAround::execute ( CBot *pBot, CBotSchedule *pSchedule ) if ( pBot->distanceFrom(m_pFriendly) > 100 ) { - pBot->setMoveTo((origin)); + pBot->setMoveTo(origin); } else if ( pBot->FInViewCone(m_pFriendly) ) { - CBotWeapon *pWeapon = pBot->getBestWeapon(NULL,true,true); - - if ( pWeapon ) + if ( CBotWeapon *pWeapon = pBot->getBestWeapon(nullptr,true,true) ) { pBot->selectBotWeapon(pWeapon); @@ -4553,13 +4842,13 @@ void CMessAround::execute ( CBot *pBot, CBotSchedule *pSchedule ) } } - if ( !m_fTime ) + if (m_fTime == 0.0f) m_fTime = engine->Time() + randomFloat(3.5f,8.0f); } break;// taunt at my friendly player case 1: { - Vector origin = CBotGlobals::entityOrigin(m_pFriendly); + const Vector origin = CBotGlobals::entityOrigin(m_pFriendly); bool ok = true; pBot->setLookVector(origin); @@ -4572,19 +4861,19 @@ void CMessAround::execute ( CBot *pBot, CBotSchedule *pSchedule ) if ( pBot->distanceFrom(m_pFriendly) > 100 ) { - pBot->setMoveTo((origin)); + pBot->setMoveTo(origin); ok = false; } if ( ok ) { if ( pBot->isTF2() ) - ((CBotTF2*)pBot)->taunt(true); + static_cast(pBot)->taunt(true); //else if ( pBot->isDOD() ) // ((CDODBot*)pBot)->taunt(); pBot->impulse(100); } - if ( !m_fTime ) + if (m_fTime == 0.0f) m_fTime = engine->Time() + randomFloat(3.5f,6.5f); } @@ -4592,10 +4881,10 @@ void CMessAround::execute ( CBot *pBot, CBotSchedule *pSchedule ) break; case 2: { - if ( !m_fTime ) + if (m_fTime == 0.0f) pBot->addVoiceCommand(randomInt(0,m_iMaxVoiceCmd-1)); - if ( !m_fTime ) + if (m_fTime == 0.0f) m_fTime = engine->Time() + randomFloat(1.5f,3.0f); } // press some random buttons, such as attack2, jump @@ -4608,12 +4897,12 @@ void CMessAround::execute ( CBot *pBot, CBotSchedule *pSchedule ) { if ( pBot->isTF2() ) { - if ( ((CBotTF2*)pBot)->getClass() == TF_CLASS_HWGUY ) + if ( static_cast(pBot)->getClass() == TF_CLASS_HWGUY ) pBot->secondaryAttack(true); } } - if ( !m_fTime ) + if (m_fTime == 0.0f) m_fTime = engine->Time() + randomFloat(1.5f,3.0f); } default: @@ -4639,36 +4928,34 @@ void CMessAround::execute ( CBot *pBot, CBotSchedule *pSchedule ) /////////// //defensive technique -CBotTF2Spam :: CBotTF2Spam ( CBot *pBot, Vector vStart, int iYaw, CBotWeapon *pWeapon ) +CBotTF2Spam :: CBotTF2Spam (const CBot *pBot, const Vector& vStart, const float fYaw, CBotWeapon *pWeapon) : m_vStart(vStart) { Vector forward; - QAngle angle = QAngle(0,iYaw,0); + const QAngle angle = QAngle(0,fYaw,0); AngleVectors(angle,&forward); m_vTarget = vStart + forward*2000.0f; CBotGlobals::quickTraceline(pBot->getEdict(),vStart,m_vTarget); m_vTarget = CBotGlobals::getTraceResult()->endpos-forward; m_pWeapon = pWeapon; - m_vStart = vStart; - + m_fNextAttack = 0.0f; m_fTime = 0.0f; } -CBotTF2Spam :: CBotTF2Spam ( Vector vStart, Vector vTarget, CBotWeapon *pWeapon ) +CBotTF2Spam::CBotTF2Spam(const Vector& vStart, const Vector& vTarget, CBotWeapon* pWeapon) : m_vTarget(vTarget), + m_vStart(vStart) { - m_vTarget = vTarget; m_pWeapon = pWeapon; - m_vStart = vStart; - + m_fNextAttack = 0.0f; m_fTime = 0.0f; } -float CBotTF2Spam :: getDistance () +float CBotTF2Spam :: getDistance () const { return (m_vStart - m_vTarget).Length(); } -void CBotTF2Spam :: execute (CBot *pBot,CBotSchedule *pSchedule) +void CBotTF2Spam :: execute (CBot *pBot, CBotSchedule *pSchedule) { pBot->wantToShoot(false); pBot->wantToListen(false); @@ -4688,15 +4975,19 @@ void CBotTF2Spam :: execute (CBot *pBot,CBotSchedule *pSchedule) return; } - if ( m_fTime == 0.0f ) { - if ( m_pWeapon->getID() == TF2_WEAPON_GRENADELAUNCHER ) + if ( m_pWeapon->getID() == TF2_WEAPON_GRENADELAUNCHER ) // Triggers crash [APG]RoboCop[CL] { - Vector vVisibleWaypoint = pSchedule->passedVector(); + //Stability fix? [APG]RoboCop[CL] + if (pSchedule == nullptr) { + // Handle the error + return; + } + const Vector vVisibleWaypoint = pSchedule->passedVector(); - if ( vVisibleWaypoint.z > (m_vTarget.z + 32.0f) ) // need to lob grenade - m_vTarget.z += getGrenadeZ(pBot->getEdict(),NULL,pBot->getOrigin(),m_vTarget,m_pWeapon->getProjectileSpeed()); + if ( vVisibleWaypoint.z > m_vTarget.z + 32.0f ) // need to lob grenade + m_vTarget.z += getGrenadeZ(pBot->getEdict(), nullptr,pBot->getOrigin(),m_vTarget,m_pWeapon->getProjectileSpeed()); else // mid point between waypoint and target as I won't see target m_vTarget = (m_vTarget + vVisibleWaypoint) / 2; } @@ -4708,7 +4999,7 @@ void CBotTF2Spam :: execute (CBot *pBot,CBotSchedule *pSchedule) { complete(); - pBot->setLastEnemy(NULL); + pBot->setLastEnemy(nullptr); // prevent bot from keeping doing this pBot->updateUtilTime(BOT_UTIL_SPAM_NEAREST_SENTRY); @@ -4732,7 +5023,7 @@ void CBotTF2Spam :: execute (CBot *pBot,CBotSchedule *pSchedule) if ( m_pWeapon->outOfAmmo(pBot) ) { - pBot->setLastEnemy(NULL); + pBot->setLastEnemy(nullptr); complete(); } else if ( m_pWeapon->needToReload(pBot) ) @@ -4745,18 +5036,22 @@ void CBotTF2Spam :: execute (CBot *pBot,CBotSchedule *pSchedule) pBot->primaryAttack(); m_fNextAttack = engine->Time() + randomFloat(0.2f,1.0f); } - } /////////// -CBotTF2AttackSentryGunTask::CBotTF2AttackSentryGunTask ( edict_t *pSentryGun, CBotWeapon *pWeapon ) +CBotTF2AttackSentryGunTask::CBotTF2AttackSentryGunTask(edict_t* pSentryGun, CBotWeapon* pWeapon) + : m_pSentryGun(pSentryGun), m_vStart(0, 0, 0), m_vHide(0, 0, 0) // Required for SGs to face the direction correctly? [APG]RoboCop[CL] { + m_iStartingWaypoint = 0; + m_iSentryWaypoint = 0; + m_fDist = 0.0f; + m_fTime = 0.0f; m_pSentryGun = pSentryGun; m_pWeapon = pWeapon; } -void CBotTF2AttackSentryGunTask::execute (CBot *pBot,CBotSchedule *pSchedule) +void CBotTF2AttackSentryGunTask::execute (CBot *pBot, CBotSchedule *pSchedule) { pBot->wantToListen(false); pBot->wantToInvestigateSound(false); @@ -4764,7 +5059,7 @@ void CBotTF2AttackSentryGunTask::execute (CBot *pBot,CBotSchedule *pSchedule) if ( CTeamFortress2Mod::TF2_IsPlayerInvuln(pBot->getEdict()) ) fail(); - if ( m_pSentryGun.get() == NULL ) + if ( m_pSentryGun.get() == nullptr) { fail(); return; @@ -4772,24 +5067,23 @@ void CBotTF2AttackSentryGunTask::execute (CBot *pBot,CBotSchedule *pSchedule) if ( m_fTime == 0.0f ) { - float fMinDist = 9999; - float fDist; - - CWaypointVisibilityTable *table = CWaypoints::getVisiblity(); + const CWaypointVisibilityTable *table = CWaypoints::getVisiblity(); m_fTime = engine->Time() + randomFloat(8.0f,14.0f); m_iSentryWaypoint = CWaypointLocations::NearestWaypoint(CBotGlobals::entityOrigin(m_pSentryGun),200.0f,-1); - m_iStartingWaypoint = CWaypointLocations::NearestWaypoint(pBot->getOrigin(),200.0f,-1,true,true,true,NULL); + m_iStartingWaypoint = CWaypointLocations::NearestWaypoint(pBot->getOrigin(),200.0f,-1,true,true,true, nullptr); m_vStart = pBot->getOrigin(); m_vHide = m_vStart; - CWaypoint *pWpt = CWaypoints::getWaypoint(m_iStartingWaypoint); + const CWaypoint *pWpt = CWaypoints::getWaypoint(m_iStartingWaypoint); - if ( pWpt != NULL ) + if ( pWpt != nullptr) { + float fMinDist = 9999; + float fDist; for ( int i = 0; i < pWpt->numPaths(); i ++ ) { if ( table->GetVisibilityFromTo(pWpt->getPath(i),m_iSentryWaypoint) == false ) @@ -4829,7 +5123,7 @@ void CBotTF2AttackSentryGunTask::execute (CBot *pBot,CBotSchedule *pSchedule) pBot->lookAtEdict(m_pSentryGun); pBot->setLookAtTask(LOOK_EDICT); - if ( m_pWeapon->needToReload(pBot) || (CClassInterface::getSentryEnemy(m_pSentryGun) == pBot->getEdict()) ) + if ( m_pWeapon->needToReload(pBot) || CClassInterface::getSentryEnemy(m_pSentryGun) == pBot->getEdict() ) { if ( pBot->distanceFrom(m_vHide) > 80.0f ) pBot->setMoveTo(m_vHide); @@ -4853,25 +5147,25 @@ void CBotTF2AttackSentryGunTask::execute (CBot *pBot,CBotSchedule *pSchedule) // use this shooting method below pBot->wantToShoot(false); - CBotTF2 *pTF2Bot = (CBotTF2*)pBot; + CBotTF2 *pTF2Bot = static_cast(pBot); pTF2Bot->resetAttackingEnemy(); // attack pBot->handleAttack(m_pWeapon,m_pSentryGun); } } -void CBotTF2AttackSentryGunTask::debugString ( char *string ) +void CBotTF2AttackSentryGunTask::debugString (char* string, unsigned bufferSize) { - sprintf(string,"CBotTF2AttackSentryGunTask"); + std::sprintf(string,"CBotTF2AttackSentryGunTask"); } ///////////// void CBotNest :: execute (CBot *pBot, CBotSchedule *pSchedule) { - CBotTF2 *pBotTF2 = (CBotTF2*)pBot; + CBotTF2 *pBotTF2 = static_cast(pBot); - if ( ( pBotTF2->getClass() == TF_CLASS_MEDIC ) && pBotTF2->someoneCalledMedic() ) + if ( pBotTF2->getClass() == TF_CLASS_MEDIC && pBotTF2->someoneCalledMedic() ) fail(); // Follow player if ( !pBotTF2->wantToNest() ) @@ -4880,7 +5174,7 @@ void CBotNest :: execute (CBot *pBot, CBotSchedule *pSchedule) pBotTF2->addVoiceCommand(TF_VC_GOGOGO); return; } - else if ( pBot->hasSomeConditions(CONDITION_PUSH) ) + if ( pBot->hasSomeConditions(CONDITION_PUSH) ) { complete(); pBot->removeCondition(CONDITION_PUSH); @@ -4888,7 +5182,7 @@ void CBotNest :: execute (CBot *pBot, CBotSchedule *pSchedule) return; } - if ( m_fTime == 0 ) + if ( m_fTime == 0.0f ) { m_fTime = engine->Time() + randomFloat(6.0f,12.0f); @@ -4914,7 +5208,7 @@ void CBotNest :: execute (CBot *pBot, CBotSchedule *pSchedule) CBotNest::CBotNest() { m_fTime = 0.0f; - m_pEnemy = NULL; + m_pEnemy = nullptr; } //////////////////////////////////////////////// @@ -4922,7 +5216,7 @@ CBotNest::CBotNest() ///////////////////////////////////////////// -void CBotJoinSquad:: execute (CBot *pBot,CBotSchedule *pSchedule) +void CBotJoinSquad:: execute (CBot *pBot, CBotSchedule *pSchedule) { if ( !pBot->inSquad() ) { @@ -4932,18 +5226,15 @@ void CBotJoinSquad:: execute (CBot *pBot,CBotSchedule *pSchedule) //CBotSquads::SquadJoin(pBot->getEdict(),m_pPlayer); } -void CBotFollowSquadLeader :: execute (CBot *pBot,CBotSchedule *pSchedule) +void CBotFollowSquadLeader :: execute (CBot *pBot, CBotSchedule *pSchedule) { - edict_t *pSquadLeader; - float fDist; - if ( !pBot->inSquad(m_pSquad) ) { fail(); return; } - pSquadLeader = m_pSquad->GetLeader(); + edict_t* pSquadLeader = m_pSquad->GetLeader(); if ( pSquadLeader == pBot->getEdict() ) { @@ -4957,10 +5248,10 @@ void CBotFollowSquadLeader :: execute (CBot *pBot,CBotSchedule *pSchedule) return; } - if ( (m_fVisibleTime > 0.0f) && !pBot->hasEnemy() && !pBot->isVisible(pSquadLeader) ) + if ( m_fVisibleTime > 0.0f && !pBot->hasEnemy() && !pBot->isVisible(pSquadLeader) ) { // haven't seen leader for five seconds - if ( (engine->Time() - m_fVisibleTime) > 0.2f ) + if ( engine->Time() - m_fVisibleTime > 0.2f ) { complete(); return; @@ -4978,29 +5269,28 @@ void CBotFollowSquadLeader :: execute (CBot *pBot,CBotSchedule *pSchedule) if ( m_fUpdateMovePosTime < engine->Time() ) { - float fRand; Vector vVelocity; - fRand = randomFloat(1.0f,2.0f); + const float fRand = randomFloat(1.0f, 2.0f); CClassInterface::getVelocity(pSquadLeader,&vVelocity); - m_fLeaderSpeed = (MIN(m_fLeaderSpeed,100.0f)*0.5f) + (vVelocity.Length()*0.5f); + m_fLeaderSpeed = MIN(m_fLeaderSpeed,100.0f)*0.5f + vVelocity.Length()*0.5f; - m_fUpdateMovePosTime = engine->Time() + (fRand * (1.0f-(vVelocity.Length()/320))); + m_fUpdateMovePosTime = engine->Time() + fRand * (1.0f-vVelocity.Length()/320); m_vPos = m_pSquad->GetFormationVector(pBot->getEdict()); m_vForward = m_vPos+vVelocity; } - fDist = pBot->distanceFrom(m_vPos); // More than reachable range + const float fDist = pBot->distanceFrom(m_vPos); // More than reachable range if ( fDist > 400.0f ) { fail(); // find a path instead return; } - else if ( fDist > m_pSquad->GetSpread() ) + if ( fDist > m_pSquad->GetSpread() ) { pBot->setMoveTo(m_vPos); pBot->setSquadIdleTime(engine->Time()); @@ -5020,26 +5310,26 @@ void CBotFollowSquadLeader :: execute (CBot *pBot,CBotSchedule *pSchedule) } //////////////////////////////////////////////////// -CBotDODSnipe :: CBotDODSnipe ( CBotWeapon *pWeaponToUse, Vector vOrigin, float fYaw, bool bUseZ, float z, int iWaypointType ) +CBotDODSnipe::CBotDODSnipe(CBotWeapon* pWeaponToUse, const Vector& vOrigin, const float fYaw, const bool bUseZ, const float z, + const int iWaypointType) : m_vOrigin(vOrigin), m_vLastEnemy() { - QAngle angle; m_fEnemyTime = 0.0f; m_fTime = 0.0f; - angle = QAngle(0,fYaw,0); - AngleVectors(angle,&m_vAim); - m_vAim = vOrigin + (m_vAim*1024); - m_vOrigin = vOrigin; + const QAngle angle = QAngle(0, fYaw, 0); + AngleVectors(angle, &m_vAim); + m_vAim = vOrigin + m_vAim * 1024; m_pWeaponToUse = pWeaponToUse; - m_fScopeTime = 0; + m_fScopeTime = 0.0f; m_bUseZ = bUseZ; m_z = z; // z = ground level m_iWaypointType = iWaypointType; m_fTimeout = 0.0f; } -void CBotDODSnipe :: debugString ( char *string ) +void CBotDODSnipe :: debugString (char* string, unsigned bufferSize) { - sprintf(string,"CBotDODSnipe\nm_fTime = %0.2f\npWeaponToUse = %s\nm_bUseZ = %s\nm_z = %0.2f",m_fTime,m_pWeaponToUse->getWeaponInfo()->getWeaponName(),m_bUseZ ? "true":"false",m_z); + std::sprintf(string, "CBotDODSnipe\nm_fTime = %0.2f\npWeaponToUse = %s\nm_bUseZ = %s\nm_z = %0.2f", m_fTime, + m_pWeaponToUse->getWeaponInfo()->getWeaponName(), m_bUseZ ? "true" : "false", m_z); } void CBotDODSnipe :: execute (CBot *pBot,CBotSchedule *pSchedule) @@ -5072,7 +5362,7 @@ void CBotDODSnipe :: execute (CBot *pBot,CBotSchedule *pSchedule) pWeapon = pCurrentWeapon->getWeaponInfo(); - if (pWeapon == NULL) + if (pWeapon == nullptr) { fail(); return; @@ -5080,36 +5370,33 @@ void CBotDODSnipe :: execute (CBot *pBot,CBotSchedule *pSchedule) if ( pCurrentWeapon != m_pWeaponToUse ) { - if ( !pBot->select_CWeapon(CWeapons::getWeapon(m_pWeaponToUse->getID())) ) + if ( !pBot->select_CWeapon(CWeapons::getWeapon(m_pWeaponToUse->getID())) )//TODO: Needs stability fixes? [APG]RoboCop[CL] { fail(); } return; } - else - { - if ( pCurrentWeapon->isZoomable() ) - bDeployedOrZoomed = CClassInterface::isSniperWeaponZoomed(pCurrentWeapon->getWeaponEntity()); - else if ( pCurrentWeapon->isDeployable() ) - bDeployedOrZoomed = CClassInterface::isMachineGunDeployed(pCurrentWeapon->getWeaponEntity()); + if ( pCurrentWeapon->isZoomable() ) + bDeployedOrZoomed = CClassInterface::isSniperWeaponZoomed(pCurrentWeapon->getWeaponEntity()); + else if ( pCurrentWeapon->isDeployable() ) + bDeployedOrZoomed = CClassInterface::isMachineGunDeployed(pCurrentWeapon->getWeaponEntity()); - if ( m_fScopeTime < engine->Time() ) + if ( m_fScopeTime < engine->Time() ) + { + if ( !bDeployedOrZoomed ) { - if ( !bDeployedOrZoomed ) - { - pBot->secondaryAttack(); + pBot->secondaryAttack(); - if ( m_fTimeout == 0.0f ) - m_fTimeout = engine->Time(); - else if ( (m_fTimeout + 3.0f) < engine->Time() ) - fail(); - } - else - m_fTimeout = 0.0f; - - m_fScopeTime = engine->Time() + randomFloat(0.5f,1.0f); + if ( m_fTimeout == 0.0f ) + m_fTimeout = engine->Time(); + else if ( m_fTimeout + 3.0f < engine->Time() ) + fail(); } + else + m_fTimeout = 0.0f; + + m_fScopeTime = engine->Time() + randomFloat(0.5f,1.0f); } if ( pCurrentWeapon->getAmmo(pBot) < 1 ) @@ -5127,14 +5414,14 @@ void CBotDODSnipe :: execute (CBot *pBot,CBotSchedule *pSchedule) fail(); } - if ( (m_fEnemyTime + 5.0f) > engine->Time() ) + if ( m_fEnemyTime + 5.0f > engine->Time() ) { pBot->setLookAtTask(LOOK_VECTOR); pBot->setLookVector(m_vLastEnemy); } else if ( m_bUseZ ) { - Vector vAim = Vector(m_vAim.x,m_vAim.y,m_z); + const Vector vAim = Vector(m_vAim.x,m_vAim.y,m_z); pBot->setLookAtTask(LOOK_VECTOR); pBot->setLookVector(pBot->snipe(vAim)); } @@ -5146,12 +5433,12 @@ void CBotDODSnipe :: execute (CBot *pBot,CBotSchedule *pSchedule) fDist = (m_vOrigin - pBot->getOrigin()).Length2D(); - if ( (fDist > 16) || !bDeployedOrZoomed ) + if ( fDist > 16 || !bDeployedOrZoomed ) { pBot->setMoveTo(m_vOrigin); pBot->setMoveSpeed(CClassInterface::getMaxSpeed(pBot->getEdict())/8); - if ( ( fDist < 48 ) && ((CDODBot*)pBot)->withinTeammate() ) + if ( fDist < 48 && static_cast(pBot)->withinTeammate() ) fail(); } else @@ -5181,20 +5468,18 @@ void CBotDODSnipe :: execute (CBot *pBot,CBotSchedule *pSchedule) if ( unprone ) { - CClassInterface::getPlayerInfoDOD(pBot->getEdict(),&unprone,NULL); + CClassInterface::getPlayerInfoDOD(pBot->getEdict(),&unprone, nullptr); if ( unprone ) { - CDODBot *pDODBot = (CDODBot *)pBot; + CDODBot *pDODBot = static_cast(pBot); pDODBot->unProne(); } } // no enemy for a while - if ( (m_fEnemyTime + m_fTime) < engine->Time() ) + if (m_fEnemyTime + m_fTime < engine->Time()) { - if ( bDeployedOrZoomed ) - pBot->secondaryAttack(); - + pBot->secondaryAttack(); complete(); } } @@ -5218,15 +5503,14 @@ void CBotDODSnipe :: execute (CBot *pBot,CBotSchedule *pSchedule) ////////////////////////// -CBotHL2DMSnipe :: CBotHL2DMSnipe ( CBotWeapon *pWeaponToUse, Vector vOrigin, float fYaw, bool bUseZ, float z, int iWaypointType ) +CBotHL2DMSnipe::CBotHL2DMSnipe(CBotWeapon* pWeaponToUse, const Vector& vOrigin, const float fYaw, const bool bUseZ, const float z, + const int iWaypointType) : m_vOrigin(vOrigin) { - QAngle angle; m_fEnemyTime = 0.0f; m_fTime = 0.0f; - angle = QAngle(0,fYaw,0); + const QAngle angle = QAngle(0, fYaw, 0); AngleVectors(angle,&m_vAim); - m_vAim = vOrigin + (m_vAim*1024); - m_vOrigin = vOrigin; + m_vAim = vOrigin + m_vAim*1024; m_pWeaponToUse = pWeaponToUse; m_fScopeTime = 0; m_bUseZ = bUseZ; @@ -5234,9 +5518,10 @@ CBotHL2DMSnipe :: CBotHL2DMSnipe ( CBotWeapon *pWeaponToUse, Vector vOrigin, flo m_iWaypointType = iWaypointType; } -void CBotHL2DMSnipe :: debugString ( char *string ) +void CBotHL2DMSnipe::debugString(char* string, unsigned bufferSize) //Unstable? [APG]RoboCop[CL] { - sprintf(string,"CBotHL2DMSnipe\nm_fTime = %0.2f\npWeaponToUse = %s\nm_bUseZ = %s\nm_z = %0.2f",m_fTime,m_pWeaponToUse->getWeaponInfo()->getWeaponName(),m_bUseZ ? "true":"false",m_z); + std::sprintf(string, "CBotHL2DMSnipe\nm_fTime = %0.2f\npWeaponToUse = %s\nm_bUseZ = %s\nm_z = %0.2f", m_fTime, + m_pWeaponToUse->getWeaponInfo()->getWeaponName(), m_bUseZ ? "true" : "false", m_z); } void CBotHL2DMSnipe :: execute (CBot *pBot,CBotSchedule *pSchedule) @@ -5244,7 +5529,7 @@ void CBotHL2DMSnipe :: execute (CBot *pBot,CBotSchedule *pSchedule) static CBotWeapon *pCurrentWeapon; static CWeapon *pWeapon; - static bool bDeployedOrZoomed; + static bool bDeployedOrZoomed; //Unused? [APG]RoboCop[CL] static float fDist; bDeployedOrZoomed = false; @@ -5269,7 +5554,7 @@ void CBotHL2DMSnipe :: execute (CBot *pBot,CBotSchedule *pSchedule) pWeapon = pCurrentWeapon->getWeaponInfo(); - if (pWeapon == NULL) + if (pWeapon == nullptr) { fail(); return; @@ -5278,15 +5563,15 @@ void CBotHL2DMSnipe :: execute (CBot *pBot,CBotSchedule *pSchedule) // refrain from proning pBot->updateCondition(CONDITION_RUN); - if ( pCurrentWeapon != m_pWeaponToUse ) + /*if (pCurrentWeapon != m_pWeaponToUse) { - if ( !pBot->select_CWeapon(CWeapons::getWeapon(m_pWeaponToUse->getID())) ) + if ( !pBot->select_CWeapon(CWeapons::getWeapon(m_pWeaponToUse->getID())) ) //Unstable? [APG]RoboCop[CL] { fail(); } return; - } + }*/ if ( pCurrentWeapon->getAmmo(pBot) < 1 ) { @@ -5300,7 +5585,7 @@ void CBotHL2DMSnipe :: execute (CBot *pBot,CBotSchedule *pSchedule) if ( m_bUseZ ) { - Vector vAim = Vector(m_vAim.x,m_vAim.y,m_z); + const Vector vAim = Vector(m_vAim.x,m_vAim.y,m_z); pBot->setLookAtTask(LOOK_VECTOR); pBot->setLookVector(pBot->snipe(vAim)); } @@ -5328,7 +5613,7 @@ void CBotHL2DMSnipe :: execute (CBot *pBot,CBotSchedule *pSchedule) pBot->duck(); // no enemy for a while - if ( (m_fEnemyTime + m_fTime) < engine->Time() ) + if ( m_fEnemyTime + m_fTime < engine->Time() ) { //if ( bDeployedOrZoomed ) // pBot->secondaryAttack(); @@ -5348,19 +5633,203 @@ void CBotHL2DMSnipe :: execute (CBot *pBot,CBotSchedule *pSchedule) m_fEnemyTime = engine->Time(); } } + +void CBotSynDisarmMineTask::execute(CBot *pBot, CBotSchedule *pSchedule) +{ + if(m_pMine.get() == nullptr) + { + fail(); + return; + } + + //if(CSynergyMod::IsCombineMinePlayerPlaced(m_pMine.get())) + //{ + // fail(); + //} + + m_vMinePos = CBotGlobals::entityOrigin(m_pMine.get()); + m_fDist = pBot->distanceFrom(m_pMine.get()); + + pBot->wantToChangeWeapon(false); + pBot->wantToShoot(false); + pBot->wantToListen(false); + pBot->setMoveLookPriority(MOVELOOK_OVERRIDE); + pBot->setLookAtTask(LOOK_VECTOR); + pBot->setLookVector(m_vMinePos); + pBot->setMoveLookPriority(MOVELOOK_TASK); + + if(pBot->getCurrentWeapon() != pBot->getWeapons()->getWeapon(CWeapons::getWeapon(SYN_WEAPON_PHYSCANNON))) + { + pBot->selectBotWeapon(pBot->getWeapons()->getWeapon(CWeapons::getWeapon(SYN_WEAPON_PHYSCANNON))); + } + + if(m_fDist <= 400.0f) + { + pBot->duck(true); + } + + if(m_fDist <= 250.0f) + { + pBot->stopMoving(); + + if(!m_bTimeSet && CSynergyMod::IsCombineMineHeldByPhysgun(m_pMine.get())) + { + m_fTime = engine->Time() + 2.0f; + m_bTimeSet = true; + } + + if(m_bTimeSet && m_fTime < engine->Time()) + { + pBot->letGoOfButton(IN_ATTACK2); + pBot->tapButton(IN_ATTACK2); // Press M2 again to release + pBot->letGoOfButton(IN_DUCK); + + if(CClassInterface::gravityGunObject(CClassInterface::getCurrentWeapon(pBot->getEdict())) == nullptr) + { + pBot->jump(); // Sometimes the mine blocks the bot's path + complete(); + } + } + else + { + pBot->secondaryAttack(true); + } + } + else + { + pBot->setMoveTo(m_vMinePos); + } +} + +void CBotSynDisarmMineTask::debugString(char* string, unsigned bufferSize) +{ + std::sprintf(string, "CBotSynDisarmMineTask\nPos: (%0.4f,%0.4f,%0.4f)\nDistance: %.2f\nTime Set: %s", m_vMinePos.x, + m_vMinePos.y, m_vMinePos.z, m_fDist, m_bTimeSet ? "true" : "false"); +} + +void CBotSynBreakICrateTask::execute(CBot *pBot, CBotSchedule *pSchedule) +{ + if(m_pCrate.get() == nullptr) + { + complete(); + return; + } + + m_vPos = CBotGlobals::entityOrigin(m_pCrate.get()); + + if(pBot->distanceFrom(m_vPos) >= 256.0f) + { + fail(); + return; + } + + if(m_pWeapon) + { + if(pBot->getCurrentWeapon() != m_pWeapon) + { + pBot->selectBotWeapon(m_pWeapon); + } + } + + pBot->wantToChangeWeapon(false); + pBot->wantToListen(false); + pBot->wantToShoot(false); + pBot->setMoveLookPriority(MOVELOOK_OVERRIDE); + pBot->setLookAtTask(LOOK_VECTOR); + pBot->setLookVector(m_vPos); + pBot->setMoveLookPriority(MOVELOOK_TASK); + + // Attack + const CBotWeapon* currentWeapon = pBot->getCurrentWeapon(); + + if (currentWeapon && currentWeapon->isGravGun()) + { + if (CClassInterface::gravityGunObject(CClassInterface::getCurrentWeapon(pBot->getEdict())) != nullptr) + { + pBot->primaryAttack(); + } + else + { + pBot->secondaryAttack(true); + } + } + else + { + pBot->setMoveTo(m_vPos); + pBot->primaryAttack(); + + if (!currentWeapon->isMelee()) + { + if (currentWeapon->getClip1(pBot) < 1) + { + if (currentWeapon->getAmmo(pBot) < 1) + { + m_pWeapon = pBot->getBestWeapon(m_pCrate.get()); + } + else + { + pBot->tapButton(IN_RELOAD); + } + } + } + } +} + +void CBotSynUseCharger::execute(CBot *pBot, CBotSchedule *pSchedule) +{ + if(m_pCharger == nullptr) + { + fail(); + return; + } + + m_vPos = CBotGlobals::entityOrigin(m_pCharger); + + if(m_flTime <= engine->Time()) + complete(); + + if(CClassInterface::getAnimCycle(m_pCharger) == 1.0f) + complete(); + + if(m_iType == CHARGER_HEALTH && pBot->getHealthPercent() >= 0.99f) + complete(); + else if(m_iType == CHARGER_ARMOR && static_cast(pBot)->getArmorPercent() >= 0.99f) + complete(); + + pBot->setMoveLookPriority(MOVELOOK_OVERRIDE); + pBot->setLookVector(m_vPos); + pBot->setLookAtTask(LOOK_VECTOR); + pBot->setMoveLookPriority(MOVELOOK_TASK); + + if(pBot->distanceFrom(m_pCharger) > 96.0f) + { + pBot->setMoveTo(m_vPos); + } + else + { + pBot->stopMoving(); + } + + if(pBot->isFacing(m_vPos)) + { + pBot->use(); + } +} + /////////////////////////////////////////// // interrupts -CBotTF2EngineerInterrupt :: CBotTF2EngineerInterrupt( CBot *pBot ) +CBotTF2EngineerInterrupt :: CBotTF2EngineerInterrupt(const CBot *pBot) { + pWrench = nullptr; m_pSentryGun = CTeamFortress2Mod::getMySentryGun(pBot->getEdict()); - if ( m_pSentryGun.get() != NULL ) + if ( m_pSentryGun.get() != nullptr) { m_fPrevSentryHealth = CClassInterface::getSentryHealth(m_pSentryGun); } else - m_fPrevSentryHealth = 0; + m_fPrevSentryHealth = 0.0f; } bool CBotTF2CoverInterrupt::isInterrupted ( CBot *pBot, bool *bFailed, bool *bCompleted ) @@ -5374,7 +5843,7 @@ bool CBotTF2CoverInterrupt::isInterrupted ( CBot *pBot, bool *bFailed, bool *bCo return false; } -CBotTF2HurtInterrupt :: CBotTF2HurtInterrupt ( CBot *pBot ) +CBotTF2HurtInterrupt :: CBotTF2HurtInterrupt (const CBot *pBot) { m_iHealth = pBot->getHealthPercent(); } @@ -5393,13 +5862,13 @@ bool CBotTF2HurtInterrupt::isInterrupted ( CBot *pBot, bool *bFailed, bool *bCom bool CBotTF2EngineerInterrupt :: isInterrupted ( CBot *pBot, bool *bFailed, bool *bCompleted ) { - if ( m_pSentryGun.get() != NULL ) + if ( m_pSentryGun.get() != nullptr) { if ( !CClassInterface::getTF2BuildingIsMini(m_pSentryGun) ) { - float m_fCurrentHealth = CClassInterface::getSentryHealth(m_pSentryGun); + const float m_fCurrentHealth = CClassInterface::getSentryHealth(m_pSentryGun); - if ( (((CBotFortress*)pBot)->getMetal()>75) && (m_fCurrentHealth < m_fPrevSentryHealth) ) + if ( static_cast(pBot)->getMetal()>75 && m_fCurrentHealth < m_fPrevSentryHealth ) { *bFailed = true; return true; @@ -5412,6 +5881,47 @@ bool CBotTF2EngineerInterrupt :: isInterrupted ( CBot *pBot, bool *bFailed, bool return false; } +/** + * CSS: Task interruption for when the bot is walking around + **/ +bool CBotCSSRoamInterrupt::isInterrupted(CBot *pBot, bool *bFailed, bool *bCompleted) +{ + if(pBot->hasEnemy()) + return true; + + if(CCounterStrikeSourceMod::isMapType(CS_MAP_BOMBDEFUSAL)) + { + if(pBot->getTeam() == CS_TEAM_TERRORIST && CCounterStrikeSourceMod::isBombDropped()) + { + return true; + } + if(pBot->getTeam() == CS_TEAM_COUNTERTERRORIST && CCounterStrikeSourceMod::isBombPlanted()) + { + return true; + } + } + + return false; +} + +// Task interruption for synergy's roaming tasks +bool CBotSYNRoamInterrupt::isInterrupted(CBot *pBot, bool *bFailed, bool *bCompleted) +{ + CBotSynergy *pBotSyn = static_cast(pBot); + + // Can be interrupted? + if(pBotSyn->getInterruptionTimer() <= engine->Time()) + { + if(pBotSyn->needHealth()) + return true; + + if(pBotSyn->needAmmo()) + return true; + } + + return false; +} + //////////////////////////////////////////////////////////////////////////////////////////// // Base Task CBotTask :: CBotTask () @@ -5419,14 +5929,14 @@ CBotTask :: CBotTask () _init(); } -bool CBotTask :: timedOut () +bool CBotTask :: timedOut () const { - return (this->m_fTimeOut != 0) && (engine->Time() < this->m_fTimeOut); + return this->m_fTimeOut != 0.0f && engine->Time() < this->m_fTimeOut; } eTaskState CBotTask :: isInterrupted (CBot *pBot) { - if ( m_pInterruptFunc != NULL ) + if ( m_pInterruptFunc != nullptr) { bool bFailed = false; bool bCompleted = false; @@ -5469,7 +5979,7 @@ eTaskState CBotTask :: isInterrupted (CBot *pBot) void CBotTask :: _init() { - m_pInterruptFunc = NULL; + m_pInterruptFunc = nullptr; m_iFlags = 0; m_iState = STATE_IDLE; m_fTimeOut = 0; @@ -5481,25 +5991,23 @@ void CBotTask :: _init() m_iFailInterruptConditionsDontHave = 0; m_iCompleteInterruptConditionsHave = 0; m_iCompleteInterruptConditionsDontHave = 0; - init(); + //init(); // may cause an unexpected result at runtime - [APG]RoboCop[CL] } void CBotTask :: init () { - return; } void CBotTask :: execute ( CBot *pBot, CBotSchedule *pSchedule ) { - return; } -bool CBotTask :: hasFailed () +bool CBotTask :: hasFailed () const { return m_iState == STATE_FAIL; } -bool CBotTask :: isComplete () +bool CBotTask :: isComplete () const { return m_iState == STATE_COMPLETE; } @@ -5520,13 +6028,13 @@ void CBotTask :: setEdict ( edict_t *pEdict ) } */ // if this condition is true it will complete, if bUnset is true, the condition must be false to be complete -void CBotTask :: setCompleteInterrupt ( int iInterruptHave, int iInterruptDontHave ) +void CBotTask :: setCompleteInterrupt (const int iInterruptHave, const int iInterruptDontHave) { m_iCompleteInterruptConditionsHave = iInterruptHave; m_iCompleteInterruptConditionsDontHave = iInterruptDontHave; } -void CBotTask :: setFailInterrupt ( int iInterruptHave, int iInterruptDontHave ) +void CBotTask :: setFailInterrupt (const int iInterruptHave, const int iInterruptDontHave) { m_iFailInterruptConditionsHave = iInterruptHave; m_iFailInterruptConditionsDontHave = iInterruptDontHave; diff --git a/utils/RCBot2_meta/bot_task.h b/utils/RCBot2_meta/bot_task.h index 96a88b8b3..d8ea07f85 100644 --- a/utils/RCBot2_meta/bot_task.h +++ b/utils/RCBot2_meta/bot_task.h @@ -39,83 +39,98 @@ struct edict_t; #include "bot.h" #include "bot_const.h" #include "bot_fortress.h" +#include "bot_waypoint.h" class CWaypointVisibilityTable; class IBotTaskInterrupt { public: - virtual bool isInterrupted ( CBot *pBot, bool *bFailed, bool *bCompleted ) = 0; + virtual ~IBotTaskInterrupt() = default; + virtual bool isInterrupted(CBot* pBot, bool* bFailed, bool* bCompleted) = 0; }; class CBotTF2EngineerInterrupt : public IBotTaskInterrupt { public: - CBotTF2EngineerInterrupt( CBot *pBot ); + CBotTF2EngineerInterrupt(const CBot* pBot); - bool isInterrupted ( CBot *pBot, bool *bFailed, bool *bCompleted ); + bool isInterrupted(CBot* pBot, bool* bFailed, bool* bCompleted) override; private: float m_fPrevSentryHealth; MyEHandle m_pSentryGun; - CBotWeapon *pWrench; + CBotWeapon* pWrench; }; class CBotTF2CoverInterrupt : public IBotTaskInterrupt { public: - bool isInterrupted ( CBot *pBot, bool *bFailed, bool *bCompleted ); + bool isInterrupted(CBot* pBot, bool* bFailed, bool* bCompleted) override; }; class CBotTF2HurtInterrupt : public IBotTaskInterrupt { public: - CBotTF2HurtInterrupt ( CBot *pBot ); + CBotTF2HurtInterrupt(const CBot* pBot); - bool isInterrupted ( CBot *pBot, bool *bFailed, bool *bCompleted ); + bool isInterrupted(CBot* pBot, bool* bFailed, bool* bCompleted) override; private: float m_iHealth; }; +class CBotCSSRoamInterrupt : public IBotTaskInterrupt +{ +public: + bool isInterrupted(CBot* pBot, bool* bFailed, bool* bCompleted) override; +}; + +class CBotSYNRoamInterrupt : public IBotTaskInterrupt +{ +public: + bool isInterrupted(CBot* pBot, bool* bFailed, bool* bCompleted) override; +}; + class CBotTask { -public: - CBotTask(); - ~CBotTask() +public: + CBotTask(); + + virtual ~CBotTask() { - if ( m_pInterruptFunc!=NULL ) + if (m_pInterruptFunc != nullptr) { delete m_pInterruptFunc; - m_pInterruptFunc = NULL; + m_pInterruptFunc = nullptr; } } void _init(); - virtual void init (); - virtual void execute ( CBot *pBot, CBotSchedule *pSchedule ); + virtual void init(); + virtual void execute(CBot* pBot, CBotSchedule* pSchedule); //void setTimeout (); - bool hasFailed (); - bool isComplete (); + bool hasFailed() const; + bool isComplete() const; //void setVector ( Vector vOrigin ); //void setFloat ( float fFloat ); - bool timedOut (); + bool timedOut() const; //void setEdict ( edict_t *pEdict ); - void setFailInterrupt ( int iInterruptHave, int iInterruptDontHave = 0 ); - void setCompleteInterrupt ( int iInterruptHave, int iInterruptDontHave = 0 ); - void setInterruptFunction ( IBotTaskInterrupt *func ) { m_pInterruptFunc = func; } - virtual eTaskState isInterrupted (CBot *pBot); - void fail (); - void complete (); - inline bool hasFlag ( int iFlag ) { return (m_iFlags & iFlag) == iFlag; } - inline void setFlag ( int iFlag ) { m_iFlags |= iFlag; } - void clearFailInterrupts () { m_iFailInterruptConditionsHave = m_iFailInterruptConditionsDontHave = 0; } - virtual void debugString ( char *string ) { string[0] = 0; return; } + void setFailInterrupt(int iInterruptHave, int iInterruptDontHave = 0); + void setCompleteInterrupt(int iInterruptHave, int iInterruptDontHave = 0); + void setInterruptFunction(IBotTaskInterrupt* func) { m_pInterruptFunc = func; } + virtual eTaskState isInterrupted(CBot* pBot); + void fail(); + void complete(); + bool hasFlag(const int iFlag) const { return (m_iFlags & iFlag) == iFlag; } + void setFlag(const int iFlag) { m_iFlags |= iFlag; } + void clearFailInterrupts() { m_iFailInterruptConditionsHave = m_iFailInterruptConditionsDontHave = 0; } + virtual void debugString(char* string, unsigned bufferSize) { string[0] = 0; } //bool isID ( eTaskID eTaskId ) { }; protected: - IBotTaskInterrupt *m_pInterruptFunc; + IBotTaskInterrupt* m_pInterruptFunc; //void setID(); // flags int m_iFlags; @@ -125,7 +140,7 @@ class CBotTask int m_iFailInterruptConditionsDontHave; int m_iCompleteInterruptConditionsDontHave; // current state - eTaskState m_iState; + int m_iState; //Mistake? [APG]RoboCop[CL] // time out float m_fTimeOut; // vars @@ -139,64 +154,65 @@ class CBotTask class CFindPathTask : public CBotTask { public: - CFindPathTask () + CFindPathTask() { - m_pEdict = NULL; + m_pEdict = nullptr; m_LookTask = LOOK_WAYPOINT; m_iWaypointId = -1; m_flags.m_data = 0; - m_fRange = 0; + m_fRange = 0.0f; + m_iInt = 0; m_iDangerPoint = -1; m_bGetPassedIntAsWaypointId = false; } - CFindPathTask ( Vector vOrigin, eLookTask looktask = LOOK_WAYPOINT ) + CFindPathTask(const Vector& vOrigin, const eLookTask looktask = LOOK_WAYPOINT) + : m_vVector(vOrigin), m_LookTask(looktask) { - m_vVector = vOrigin; - m_pEdict = NULL; // no edict - m_LookTask = looktask; + m_pEdict = nullptr; m_iWaypointId = -1; m_flags.m_data = 0; - m_fRange = 0; + m_fRange = 0.0f; + m_iInt = 0; m_iDangerPoint = -1; m_bGetPassedIntAsWaypointId = false; } // having this constructor saves us trying to find the goal waypoint again if we // already know it - CFindPathTask ( int iWaypointId, eLookTask looktask = LOOK_WAYPOINT ); + CFindPathTask(int iWaypointId, eLookTask looktask = LOOK_WAYPOINT); - CFindPathTask ( edict_t *pEdict ); + CFindPathTask(edict_t* pEdict); - void setRange ( float fRange ) { m_fRange = fRange; } + void setRange(const float fRange) { m_fRange = fRange; } - void setEdict ( edict_t *pEdict ) { m_pEdict = pEdict; } + void setEdict(edict_t* pEdict) { m_pEdict = pEdict; } - void setDangerPoint ( int iWpt ) { m_iDangerPoint = iWpt; } + void setDangerPoint(const int iWpt) { m_iDangerPoint = iWpt; } - void getPassedVector () { m_flags.bits.m_bGetPassedVector = true; } + void getPassedVector() { m_flags.bits.m_bGetPassedVector = true; } - void getPassedIntAsWaypointId () { m_bGetPassedIntAsWaypointId = true; } + void getPassedIntAsWaypointId() { m_bGetPassedIntAsWaypointId = true; } - void dontGoToEdict () { m_flags.bits.m_bDontGoToEdict = true; } + void dontGoToEdict() { m_flags.bits.m_bDontGoToEdict = true; } - void setNoInterruptions () { clearFailInterrupts(); m_flags.bits.m_bNoInterruptions = true; } + void setNoInterruptions() { clearFailInterrupts(); m_flags.bits.m_bNoInterruptions = true; } - void execute ( CBot *pBot, CBotSchedule *pSchedule ); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - void completeOutOfRangeFromEdict () { m_flags.bits.m_bCompleteOutOfRangeEdict = true; } + void completeOutOfRangeFromEdict() { m_flags.bits.m_bCompleteOutOfRangeEdict = true; } - void completeInRangeFromEdict () { m_flags.bits.m_bCompleteInRangeOfEdict = true; } + void completeInRangeFromEdict() { m_flags.bits.m_bCompleteInRangeOfEdict = true; } - void completeIfSeeTaskEdict () { m_flags.bits.m_bCompleteSeeTaskEdict = true; } + void completeIfSeeTaskEdict() { m_flags.bits.m_bCompleteSeeTaskEdict = true; } - void failIfTaskEdictDead () { m_flags.bits.m_bFailTaskEdictDied = true; } + void failIfTaskEdictDead() { m_flags.bits.m_bFailTaskEdictDied = true; } - void init (); + void init() override; - void setLookTask ( eLookTask task ) { m_LookTask = task; } + void setLookTask(const eLookTask task) { m_LookTask = task; } - virtual void debugString ( char *string ); + void debugString(char* string, unsigned bufferSize) override; private: @@ -214,17 +230,17 @@ class CFindPathTask : public CBotTask struct { - bool m_bNoInterruptions:1; // quick path finding - non concurrent - bool m_bGetPassedVector:1; // receive vector from previous task - bool m_bDontLookAtWaypoints:1; - bool m_bCompleteSeeTaskEdict:1; // complete when see the edict - bool m_bFailTaskEdictDied:1; // fail if the edict no longer exists or dead - bool m_bDontGoToEdict:1; // don't complete if nearby edict - bool m_bCompleteOutOfRangeEdict:1; // complete if outside of m_fRange from edict (grenades) - bool m_bCompleteInRangeOfEdict:1; + bool m_bNoInterruptions : 1; // quick path finding - non concurrent + bool m_bGetPassedVector : 1; // receive vector from previous task + bool m_bDontLookAtWaypoints : 1; + bool m_bCompleteSeeTaskEdict : 1; // complete when see the edict + bool m_bFailTaskEdictDied : 1; // fail if the edict no longer exists or dead + bool m_bDontGoToEdict : 1; // don't complete if nearby edict + bool m_bCompleteOutOfRangeEdict : 1; // complete if outside of m_fRange from edict (grenades) + bool m_bCompleteInRangeOfEdict : 1; }bits; }m_flags; - + bool m_bGetPassedIntAsWaypointId; //bool m_bWaitUntilReached; }; @@ -232,20 +248,20 @@ class CFindPathTask : public CBotTask class CBotTF2AttackSentryGunTask : public CBotTask { public: - CBotTF2AttackSentryGunTask ( edict_t *pSentryGun, CBotWeapon *pWeapon ); + CBotTF2AttackSentryGunTask(edict_t* pSentryGun, CBotWeapon* pWeapon); - void execute (CBot *pBot,CBotSchedule *pSchedule); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - void init () + void init() override { m_fTime = 0.0f; } - void debugString ( char *string ); + void debugString(char* string, unsigned bufferSize) override; private: - + MyEHandle m_pSentryGun; - CBotWeapon *m_pWeapon; + CBotWeapon* m_pWeapon; int m_iStartingWaypoint; int m_iSentryWaypoint; Vector m_vStart; @@ -258,70 +274,73 @@ class CBotTF2AttackSentryGunTask : public CBotTask class CBotTF2Spam : public CBotTask { public: - CBotTF2Spam ( Vector vStart, Vector vTarget, CBotWeapon *pWeapon ); + CBotTF2Spam(const Vector& vStart, const Vector& vTarget, CBotWeapon* pWeapon); - CBotTF2Spam ( CBot *pBot, Vector vStart, int iYaw, CBotWeapon *pWeapon ); + CBotTF2Spam(const CBot* pBot, const Vector& vStart, float fYaw, CBotWeapon* pWeapon); - void execute (CBot *pBot,CBotSchedule *pSchedule); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - Vector getTarget () { return m_vTarget; } + Vector getTarget() { return m_vTarget; } - void debugString ( char *string ) + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string,"CBotTF2Spam"); + snprintf(string, bufferSize, "CBotTF2Spam"); } - float getDistance (); + float getDistance() const; private: - + Vector m_vTarget; Vector m_vStart; - CBotWeapon *m_pWeapon; + CBotWeapon* m_pWeapon; float m_fTime; float m_fNextAttack; }; -#define TASK_TF2_DEMO_STATE_LAY_BOMB 0 -#define TASK_TF2_DEMO_STATE_RUN_UP 1 +enum : std::uint8_t +{ + TASK_TF2_DEMO_STATE_LAY_BOMB = 0, + TASK_TF2_DEMO_STATE_RUN_UP = 1 +}; class CBotTF2DemomanPipeJump : public CBotTask { public: - CBotTF2DemomanPipeJump ( CBot *pBot, Vector vWaypointGround, Vector vWaypointNext, CBotWeapon *pWeapon ); + CBotTF2DemomanPipeJump(CBot* pBot, const Vector& vWaypointGround, const Vector& vWaypointNext, CBotWeapon* pWeapon); - void execute (CBot *pBot,CBotSchedule *pSchedule); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - void debugString ( char *string ) + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string,"CBotTF2DemomanPipeJump"); + snprintf(string, bufferSize, "CBotTF2DemomanPipeJump"); } private: - + Vector m_vStart; - Vector m_vPipe; + Vector m_vPipe; //TODO: required for proper pipe jumping? [APG]RoboCop[CL] Vector m_vEnd; - edict_t *m_pPipeBomb; + MyEHandle m_pPipeBomb; bool m_bFired; float m_fTime; - int m_iState; + //int m_iState; int m_iStartingAmmo; - CBotWeapon *m_pWeapon; + CBotWeapon* m_pWeapon; }; // automatically detonate pipes from a standing location, make sure // the bot is not standing in a location visible to the enemy // in vStand -class CBotTF2DemomanPipeEnemy : public CBotTask +class CBotTF2DemomanPipeEnemy : public CBotTask { public: //CBotTF2DemomanPipeEnemy ( Vector vStand, Vector vBlastPoint, CBotWeapon *pPipeLauncher, Vector vEnemy, edict_t *pEnemy ); - CBotTF2DemomanPipeEnemy ( CBotWeapon *pPipeLauncher, Vector vEnemy, edict_t *pEnemy ); - void execute (CBot *pBot,CBotSchedule *pSchedule); + CBotTF2DemomanPipeEnemy(CBotWeapon* pPipeLauncher, const Vector& vEnemy, edict_t* pEnemy); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - void debugString ( char *string ) + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string,"CBotTF2DemomanPipeEnemy"); + snprintf(string, bufferSize, "CBotTF2DemomanPipeEnemy"); } private: Vector m_vStand; @@ -331,7 +350,7 @@ class CBotTF2DemomanPipeEnemy : public CBotTask float m_fTime; float m_fHoldAttackTime; float m_fHeldAttackTime; - CBotWeapon *m_pPipeLauncher; + CBotWeapon* m_pPipeLauncher; }; class CBotTF2DemomanPipeTrap : public CBotTask @@ -340,13 +359,13 @@ class CBotTF2DemomanPipeTrap : public CBotTask // Set up a pipe trap or fire pipe bombs -- // if autodetonate, detonate them when I've shot them rather than wait for an enemy // such as when attacking a sentry - CBotTF2DemomanPipeTrap ( eDemoTrapType type, Vector vStand, Vector vLoc, Vector vSpread, bool bAutoDetonate = false, int m_iWptArea = -1 ); - - void execute (CBot *pBot,CBotSchedule *pSchedule); + CBotTF2DemomanPipeTrap(eDemoTrapType type, const Vector& vStand, const Vector& vLoc, const Vector& vSpread, bool bAutoDetonate = false, int m_iWptArea = -1); - void debugString ( char *string ) + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string,"CBotTF2DemomanPipeTrap"); + snprintf(string, bufferSize, "CBotTF2DemomanPipeTrap"); } private: Vector m_vPoint; @@ -355,24 +374,23 @@ class CBotTF2DemomanPipeTrap : public CBotTask Vector m_vSpread; float m_fTime; eDemoTrapType m_iTrapType; - int m_iState; + //int m_iState; int m_iStickies; bool m_bAutoDetonate; int m_iWptArea; }; - class CBotTF2FindPipeWaypoint : public CBotTask { public: - CBotTF2FindPipeWaypoint ( Vector vOrigin, Vector vTarget ); - - void execute (CBot *pBot,CBotSchedule *pSchedule); + CBotTF2FindPipeWaypoint(const Vector& vOrigin, const Vector& vTarget); + + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - void debugString ( char *string ) + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string,"Finding Pipe Waypoint"); + snprintf(string, bufferSize, "Finding Pipe Waypoint"); } private: int m_iters; @@ -386,28 +404,28 @@ class CBotTF2FindPipeWaypoint : public CBotTask short int m_iNearesti; short int m_iNearestj; - CWaypointVisibilityTable *m_pTable; - CWaypoint *m_pTarget; - vector m_WaypointsI; - vector m_WaypointsJ; + CWaypointVisibilityTable* m_pTable; + CWaypoint* m_pTarget; + WaypointList m_WaypointsI; + WaypointList m_WaypointsJ; }; class CBotGravGunPickup : public CBotTask { public: - CBotGravGunPickup ( edict_t *pWeapon, edict_t *pProp ) + CBotGravGunPickup(edict_t* pWeapon, edict_t* pProp) + : m_Weapon(pWeapon), m_Prop(pProp) { - m_Weapon = pWeapon; - m_Prop = pProp; - m_fTime = 0; + m_fTime = 0.0f; + m_fSecAttTime = 0.0f; } - - void execute (CBot *pBot,CBotSchedule *pSchedule); - void debugString ( char *string ) + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string,"Grav Gun Pickup"); + snprintf(string, bufferSize, "Grav Gun Pickup"); } private: MyEHandle m_Weapon; @@ -417,24 +435,26 @@ class CBotGravGunPickup : public CBotTask }; -#define CHARGER_HEALTH 0 -#define CHARGER_ARMOR 1 +enum : std::uint8_t +{ + CHARGER_HEALTH = 0, + CHARGER_ARMOR = 1 +}; class CBotHL2DMUseCharger : public CBotTask { public: - CBotHL2DMUseCharger ( edict_t *pCharger, int type ) + CBotHL2DMUseCharger(edict_t* pCharger, const int type) : m_pCharger(pCharger) { - m_pCharger = pCharger; m_fTime = 0; m_iType = type; } - - void execute (CBot *pBot,CBotSchedule *pSchedule); - void debugString ( char *string ) + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string,"Use Charger"); + snprintf(string, bufferSize, "Use Charger"); } private: MyEHandle m_pCharger; @@ -446,33 +466,40 @@ class CBotHL2DMUseCharger : public CBotTask class CBotHL2DMUseButton : public CBotTask { public: - CBotHL2DMUseButton ( edict_t *pButton ) + CBotHL2DMUseButton(edict_t* pButton) : m_pButton(pButton) { - m_pButton = pButton; m_fTime = 0.0f; + m_bOverrideLook = false; } - - void execute (CBot *pBot,CBotSchedule *pSchedule); - void debugString ( char *string ) + CBotHL2DMUseButton(edict_t* pButton, const bool bOverrideLook) : m_pButton(pButton) { - sprintf(string,"Use Button"); + m_fTime = 0.0f; + m_bOverrideLook = bOverrideLook; + } + + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + + void debugString(char* string, const unsigned bufferSize) override + { + snprintf(string, bufferSize, "Use Button"); } private: MyEHandle m_pButton; float m_fTime; + bool m_bOverrideLook; }; class CBotTF2MedicHeal : public CBotTask { public: - CBotTF2MedicHeal ( ); - - void execute (CBot *pBot,CBotSchedule *pSchedule); + CBotTF2MedicHeal(); - void debugString ( char *string ) + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string,"CBotTF2MedicHeal"); + snprintf(string, bufferSize, "CBotTF2MedicHeal"); } private: MyEHandle m_pHeal; @@ -484,13 +511,13 @@ class CBotTF2MedicHeal : public CBotTask class CBotRemoveSapper : public CBotTask { public: - CBotRemoveSapper ( edict_t *pBuilding, eEngiBuild id ); - - void execute (CBot *pBot,CBotSchedule *pSchedule); + CBotRemoveSapper(edict_t* pBuilding, eEngiBuild id); + + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - void debugString ( char *string ) + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string,"CBotRemoveSapper"); + snprintf(string, bufferSize, "CBotRemoveSapper"); } private: float m_fTime; @@ -504,11 +531,11 @@ class CBotUseLunchBoxDrink : public CBotTask public: CBotUseLunchBoxDrink(); - void execute(CBot *pBot, CBotSchedule *pSchedule); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - void debugString(char *string) + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string, "CBotUseLunchBoxDrink"); + snprintf(string, bufferSize, "CBotUseLunchBoxDrink"); } private: float m_fTime; @@ -517,13 +544,13 @@ class CBotUseLunchBoxDrink : public CBotTask class CBotUseBuffItem : public CBotTask { public: - CBotUseBuffItem ( ); - - void execute (CBot *pBot,CBotSchedule *pSchedule); + CBotUseBuffItem(); - void debugString ( char *string ) + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string,"CBotUseBuffITem"); + snprintf(string, bufferSize, "CBotUseBuffITem"); } private: float m_fTime; @@ -532,13 +559,13 @@ class CBotUseBuffItem : public CBotTask class CBotBackstab : public CBotTask { public: - CBotBackstab ( edict_t *_pEnemy ); - - void execute (CBot *pBot,CBotSchedule *pSchedule); + CBotBackstab(edict_t* _pEnemy); + + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - void debugString ( char *string ) + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string,"CBotBackstab"); + snprintf(string, bufferSize, "CBotBackstab"); } private: float m_fTime; @@ -549,43 +576,43 @@ class CBotJoinSquad : public CBotTask { public: - CBotJoinSquad ( edict_t *pPlayerToJoin ) + CBotJoinSquad(edict_t* pPlayerToJoin) { m_pPlayer = pPlayerToJoin; } - void execute (CBot *pBot,CBotSchedule *pSchedule); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - void debugString ( char *string ) + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string,"CBotFollowSquadLeader"); + snprintf(string, bufferSize, "CBotFollowSquadLeader"); } private: - edict_t *m_pPlayer; + edict_t* m_pPlayer; }; class CBotFollowSquadLeader : public CBotTask { public: - CBotFollowSquadLeader ( CBotSquad *pSquad ) + CBotFollowSquadLeader(CBotSquad* pSquad) { m_fLeaderSpeed = 0.0f; m_pSquad = pSquad; m_fVisibleTime = 0.0f; m_fUpdateMovePosTime = 0.0f; - m_vPos = Vector(0,0,0); - m_vForward = Vector(0,0,0); + m_vPos = Vector(0, 0, 0); + m_vForward = Vector(0, 0, 0); } - void execute (CBot *pBot,CBotSchedule *pSchedule); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - void debugString ( char *string ) + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string,"CBotFollowSquadLeader"); + snprintf(string, bufferSize, "CBotFollowSquadLeader"); } private: - CBotSquad *m_pSquad; + CBotSquad* m_pSquad; float m_fVisibleTime; float m_fUpdateMovePosTime; float m_fLeaderSpeed; @@ -593,17 +620,16 @@ class CBotFollowSquadLeader : public CBotTask Vector m_vForward; }; - class CBotNest : public CBotTask { public: - CBotNest (); - - void execute (CBot *pBot,CBotSchedule *pSchedule); + CBotNest(); - void debugString ( char *string ) + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string,"CBotNest"); + snprintf(string, bufferSize, "CBotNest"); } private: float m_fTime; @@ -613,23 +639,23 @@ class CBotNest : public CBotTask class CBotDefendTask : public CBotTask { public: - CBotDefendTask ( Vector vOrigin, float fMaxTime = 0, int iInterrupt = CONDITION_SEE_CUR_ENEMY, bool bDefendOrigin = false, Vector vDefendOrigin = Vector(0,0,0), eLookTask looktask = LOOK_SNIPE, int iWaypointType = 0 ) - { - m_fMaxTime = fMaxTime; - m_vOrigin = vOrigin; - m_fTime = 0; - setCompleteInterrupt(iInterrupt); + CBotDefendTask(const Vector& vOrigin, const float fMaxTime = 0.0f, const int iInterrupt = CONDITION_SEE_CUR_ENEMY, + const bool bDefendOrigin = false, const Vector& vDefendOrigin = Vector(0, 0, 0), + const eLookTask looktask = LOOK_SNIPE, const int iWaypointType = 0) : m_vOrigin(vOrigin), m_vDefendOrigin(vDefendOrigin) + { + m_fMaxTime = fMaxTime; + m_fTime = 0.0f; + setCompleteInterrupt(iInterrupt); m_bDefendOrigin = bDefendOrigin; - m_vDefendOrigin = vDefendOrigin; m_LookTask = looktask; m_iWaypointType = iWaypointType; } - - void execute (CBot *pBot,CBotSchedule *pSchedule); - void debugString ( char *string ) + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string,"CBotDefendTask"); + snprintf(string, bufferSize, "CBotDefendTask"); } private: float m_fTime; @@ -644,26 +670,26 @@ class CBotDefendTask : public CBotTask class CBotInvestigateTask : public CBotTask { public: - CBotInvestigateTask ( Vector vOrigin, float fRadius, Vector vPOV, bool bHasPOV, float fMaxTime = 0, int iInterrupt = CONDITION_SEE_CUR_ENEMY ) - { - m_fMaxTime = fMaxTime; - m_vOrigin = vOrigin; + CBotInvestigateTask(const Vector& vOrigin, const float fRadius, const Vector& vPOV, const bool bHasPOV, const float fMaxTime = 0, + const int iInterrupt = CONDITION_SEE_CUR_ENEMY) : m_vOrigin(vOrigin), m_vPOV(vPOV) + { + m_fMaxTime = fMaxTime; m_fRadius = fRadius; - m_fTime = 0; - setCompleteInterrupt(iInterrupt); + m_fTime = 0.0f; + setCompleteInterrupt(iInterrupt); + m_iCurPath = 0; m_iState = 0; - m_vPOV = vPOV; m_bHasPOV = bHasPOV; } - - void execute (CBot *pBot,CBotSchedule *pSchedule); - void debugString ( char *string ) + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string,"CBotInvestigateTask"); + snprintf(string, bufferSize, "CBotInvestigateTask"); } private: - int m_iState; + //int m_iState; float m_fTime; float m_fMaxTime; Vector m_vOrigin; @@ -671,19 +697,21 @@ class CBotInvestigateTask : public CBotTask int m_iCurPath; bool m_bHasPOV; Vector m_vPOV; - vector m_InvPoints; // investigation points (waypoint paths) + std::vector m_InvPoints; // investigation points (waypoint paths) }; class CBotTF2EngiLookAfter : public CBotTask { public: - CBotTF2EngiLookAfter ( edict_t *pSentry ) { m_pSentry = pSentry; m_fTime = 0; m_fHitSentry = 0; } - - void execute (CBot *pBot,CBotSchedule *pSchedule); + CBotTF2EngiLookAfter(edict_t* pSentry) + : m_fTime(0.0f), m_fHitSentry(0.0f), m_pSentry(pSentry) { + } - void debugString ( char *string ) + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string,"CBotTF2EngiLookAfter"); + snprintf(string, bufferSize, "CBotTF2EngiLookAfter"); } private: float m_fTime; @@ -694,13 +722,13 @@ class CBotTF2EngiLookAfter : public CBotTask class CBotTF2SnipeCrossBow : public CBotTask { public: - CBotTF2SnipeCrossBow(Vector vOrigin, int iWpt); + CBotTF2SnipeCrossBow(const Vector& vOrigin, int iWpt); - void execute(CBot *pBot, CBotSchedule *pSchedule); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - void debugString(char *string) + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string, "CBotSnipe"); + snprintf(string, bufferSize, "CBotSnipe"); } private: float m_fTime; // time of task @@ -723,13 +751,13 @@ class CBotTF2SnipeCrossBow : public CBotTask class CBotTF2Snipe : public CBotTask { public: - CBotTF2Snipe ( Vector vOrigin, int iWpt ); - - void execute (CBot *pBot,CBotSchedule *pSchedule); + CBotTF2Snipe(const Vector& vOrigin, int iWpt); + + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - void debugString ( char *string ) + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string,"CBotSnipe"); + snprintf(string, bufferSize, "CBotSnipe"); } private: float m_fTime; // time of task @@ -753,11 +781,11 @@ class CBotTF2Snipe : public CBotTask class CBotDODSnipe : public CBotTask { public: - CBotDODSnipe ( CBotWeapon *pWeaponToUse, Vector vOrigin, float fYaw, bool bUseZ = false, float z = 0, int iWaypointType = 0 ); - - void execute (CBot *pBot,CBotSchedule *pSchedule); + CBotDODSnipe(CBotWeapon* pWeaponToUse, const Vector& vOrigin, float fYaw, bool bUseZ = false, float z = 0, int iWaypointType = 0); + + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - void debugString ( char *string ); + void debugString(char* string, unsigned bufferSize) override; private: float m_fTime; @@ -765,7 +793,7 @@ class CBotDODSnipe : public CBotTask float m_fScopeTime; Vector m_vAim; Vector m_vOrigin; - CBotWeapon *m_pWeaponToUse; + CBotWeapon* m_pWeaponToUse; Vector m_vLastEnemy; bool m_bUseZ; float m_z; // z = ground level @@ -776,11 +804,11 @@ class CBotDODSnipe : public CBotTask class CBotHL2DMSnipe : public CBotTask { public: - CBotHL2DMSnipe ( CBotWeapon *pWeaponToUse, Vector vOrigin, float fYaw, bool bUseZ = false, float z = 0, int iWaypointType = 0 ); - - void execute (CBot *pBot,CBotSchedule *pSchedule); + CBotHL2DMSnipe(CBotWeapon* pWeaponToUse, const Vector& vOrigin, float fYaw, bool bUseZ = false, float z = 0, int iWaypointType = 0); - void debugString ( char *string ); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + + void debugString(char* string, unsigned bufferSize) override; private: float m_fTime; @@ -788,7 +816,7 @@ class CBotHL2DMSnipe : public CBotTask float m_fScopeTime; Vector m_vAim; Vector m_vOrigin; - CBotWeapon *m_pWeaponToUse; + CBotWeapon* m_pWeaponToUse; bool m_bUseZ; float m_z; // z = ground level int m_iWaypointType; @@ -797,31 +825,31 @@ class CBotHL2DMSnipe : public CBotTask class CBotTF2SpyDisguise : public CBotTask { public: - CBotTF2SpyDisguise ( ); - - void execute (CBot *pBot,CBotSchedule *pSchedule); + CBotTF2SpyDisguise(); + + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - void debugString ( char *string ) + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string,"CBotTF2SpyDisguise"); + snprintf(string, bufferSize, "CBotTF2SpyDisguise"); } }; class CBotTFEngiBuildTask : public CBotTask { public: - CBotTFEngiBuildTask ( eEngiBuild iObject, CWaypoint *pWaypoint ); - - void execute (CBot *pBot,CBotSchedule *pSchedule); + CBotTFEngiBuildTask(eEngiBuild iObject, CWaypoint* pWaypoint); + + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - virtual void debugString ( char *string ); + void debugString(char* string, unsigned bufferSize) override; - void oneTryOnly () { m_iTries = 2; } + void oneTryOnly() { m_iTries = 2; } private: Vector m_vOrigin; eEngiBuild m_iObject; - int m_iState; + //int m_iState; float m_fTime; int m_iTries; float m_fNextUpdateAngle; @@ -835,14 +863,13 @@ class CBotTFEngiBuildTask : public CBotTask class CDODDropAmmoTask : public CBotTask { public: - CDODDropAmmoTask ( edict_t *pPlayer ) + CDODDropAmmoTask(edict_t* pPlayer) : m_pPlayer(pPlayer) { m_fTime = 0.0f; - m_pPlayer = pPlayer; } - virtual void debugString ( char *string ); - void execute (CBot *pBot,CBotSchedule *pSchedule); + void debugString(char* string, unsigned bufferSize) override; + void execute(CBot* pBot, CBotSchedule* pSchedule) override; private: MyEHandle m_pPlayer; @@ -852,14 +879,13 @@ class CDODDropAmmoTask : public CBotTask class CDODWaitForGrenadeTask : public CBotTask { public: - CDODWaitForGrenadeTask ( edict_t *pGrenade ) + CDODWaitForGrenadeTask(edict_t* pGrenade) : m_pGrenade(pGrenade) { - m_pGrenade = pGrenade; m_fTime = 0.0f; } - virtual void debugString ( char *string ); - void execute (CBot *pBot,CBotSchedule *pSchedule); + void debugString(char* string, unsigned bufferSize) override; + void execute(CBot* pBot, CBotSchedule* pSchedule) override; private: MyEHandle m_pGrenade; @@ -869,45 +895,46 @@ class CDODWaitForGrenadeTask : public CBotTask class CDODWaitForBombTask : public CBotTask { public: - CDODWaitForBombTask ( edict_t *pBombTarget, CWaypoint *pBlocking ) + CDODWaitForBombTask(edict_t* pBombTarget, CWaypoint* pBlocking) : m_pBombTarget(pBombTarget) { - m_pBombTarget = pBombTarget; m_fTime = 0.0f; + m_pRunTo = nullptr; m_pBlocking = pBlocking; } - virtual void debugString ( char *string ); - void execute (CBot *pBot,CBotSchedule *pSchedule); + + void debugString(char* string, unsigned bufferSize) override; + void execute(CBot* pBot, CBotSchedule* pSchedule) override; private: MyEHandle m_pBombTarget; float m_fTime; - CWaypoint *m_pRunTo; - CWaypoint *m_pBlocking; + CWaypoint* m_pRunTo; + CWaypoint* m_pBlocking; }; class CBotDODBomb : public CBotTask { public: - CBotDODBomb ( int iBombType, int iBombID, edict_t *m_pBombTarget, Vector vPosition, int iPrevOwner ); - void execute (CBot *pBot,CBotSchedule *pSchedule); + CBotDODBomb(int iBombType, int iBombID, edict_t* m_pBomb, const Vector& vPosition, int iPrevOwner); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - virtual void debugString ( char *string ); + void debugString(char* string, unsigned bufferSize) override; private: Vector m_vOrigin; float m_fTime; int m_iBombID; int m_iPrevTeam; // prev owner - edict_t *m_pBombTarget; + edict_t* m_pBombTarget; int m_iType; }; class CBotDODAttackPoint : public CBotTask { public: - CBotDODAttackPoint ( int iFlagID, Vector vOrigin, float fRadius ); - void execute (CBot *pBot,CBotSchedule *pSchedule); + CBotDODAttackPoint(int iFlagID, const Vector& vOrigin, float fRadius); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - virtual void debugString ( char *string ); + void debugString(char* string, unsigned bufferSize) override; private: Vector m_vOrigin; Vector m_vMoveTo; @@ -918,52 +945,49 @@ class CBotDODAttackPoint : public CBotTask bool m_bProne; }; - class CBotTF2AttackPoint : public CBotTask { public: - CBotTF2AttackPoint ( int iArea, Vector vOrigin, int iRadius ); - void execute (CBot *pBot,CBotSchedule *pSchedule); + CBotTF2AttackPoint(int iArea, const Vector& vOrigin, float fRadius); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - virtual void debugString ( char *string ); + void debugString(char* string, unsigned bufferSize) override; private: Vector m_vOrigin; Vector m_vMoveTo; float m_fAttackTime; float m_fTime; int m_iArea; - int m_iRadius; + float m_fRadius; }; - class CBotTF2ShootLastEnemyPosition : public CBotTask { public: - CBotTF2ShootLastEnemyPosition ( Vector vPosition, edict_t *pEnemy, Vector velocity ); - void execute (CBot *pBot,CBotSchedule *pSchedule); + CBotTF2ShootLastEnemyPosition(const Vector& vPosition, edict_t* pEnemy, const Vector& m_vVelocity); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - virtual void debugString ( char *string ); + void debugString(char* string, unsigned bufferSize) override; private: - MyEHandle m_pEnemy; + MyEHandle m_pEnemy; Vector m_vPosition; float m_fTime; }; - class CBotTF2DefendPoint : public CBotTask { public: - CBotTF2DefendPoint ( int iArea, Vector vOrigin, int iRadius ); - void execute (CBot *pBot,CBotSchedule *pSchedule); + CBotTF2DefendPoint(int iArea, const Vector& vOrigin, float fRadius); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - virtual void debugString ( char *string ); + void debugString(char* string, unsigned bufferSize) override; private: Vector m_vOrigin; Vector m_vMoveTo; float m_fDefendTime; float m_fTime; int m_iArea; - int m_iRadius; + float m_fRadius; }; class CBotInvestigateHidePoint : public CBotTask @@ -971,28 +995,28 @@ class CBotInvestigateHidePoint : public CBotTask // investigate a possible enemy hiding point public: - CBotInvestigateHidePoint ( int iWaypointIndexToInvestigate, int iOriginalWaypointIndex ); + CBotInvestigateHidePoint(int iWaypointIndexToInvestigate, int iOriginalWaypointIndex); - void execute (CBot *pBot,CBotSchedule *pSchedule); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - virtual void debugString ( char *string ); + void debugString(char* string, unsigned bufferSize) override; private: Vector m_vOrigin; Vector m_vMoveTo; - vector m_CheckPoints; - unsigned int m_iCurrentCheckPoint; + std::vector m_CheckPoints; + unsigned m_iCurrentCheckPoint; float m_fInvestigateTime; float m_fTime; - int m_iState; + //int m_iState; }; class CBotTF2PushPayloadBombTask : public CBotTask { public: - CBotTF2PushPayloadBombTask (edict_t * pPayloadBomb); - - void execute (CBot *pBot,CBotSchedule *pSchedule); - virtual void debugString ( char *string ); + CBotTF2PushPayloadBombTask(edict_t* pPayloadBomb); + + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + void debugString(char* string, unsigned bufferSize) override; private: MyEHandle m_pPayloadBomb; Vector m_vMoveTo; @@ -1005,10 +1029,10 @@ class CBotTF2PushPayloadBombTask : public CBotTask class CBotTF2DefendPayloadBombTask : public CBotTask { public: - CBotTF2DefendPayloadBombTask (edict_t * pPayloadBomb); - - void execute (CBot *pBot,CBotSchedule *pSchedule); - virtual void debugString ( char *string ); + CBotTF2DefendPayloadBombTask(edict_t* pPayloadBomb); + + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + void debugString(char* string, unsigned bufferSize) override; private: MyEHandle m_pPayloadBomb; Vector m_vMoveTo; @@ -1021,10 +1045,10 @@ class CBotTF2DefendPayloadBombTask : public CBotTask class CBotTF2UpgradeBuilding : public CBotTask { public: - CBotTF2UpgradeBuilding ( edict_t *pBuilding ); - void execute (CBot *pBot,CBotSchedule *pSchedule); + CBotTF2UpgradeBuilding(edict_t* pBuilding); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - virtual void debugString ( char *string ); + void debugString(char* string, unsigned bufferSize) override; private: MyEHandle m_pBuilding; float m_fTime; @@ -1033,10 +1057,10 @@ class CBotTF2UpgradeBuilding : public CBotTask class CBotTF2WaitAmmoTask : public CBotTask { public: - CBotTF2WaitAmmoTask ( Vector vOrigin ); - - void execute (CBot *pBot,CBotSchedule *pSchedule); - virtual void debugString ( char *string ); + CBotTF2WaitAmmoTask(const Vector& vOrigin); + + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + void debugString(char* string, unsigned bufferSize) override; private: Vector m_vOrigin; float m_fWaitTime; @@ -1045,10 +1069,10 @@ class CBotTF2WaitAmmoTask : public CBotTask class CBotTF2WaitHealthTask : public CBotTask { public: - CBotTF2WaitHealthTask ( Vector vOrigin ); - - void execute (CBot *pBot,CBotSchedule *pSchedule); - virtual void debugString ( char *string ); + CBotTF2WaitHealthTask(const Vector& vOrigin); + + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + void debugString(char* string, unsigned bufferSize) override; private: Vector m_vOrigin; float m_fWaitTime; @@ -1057,10 +1081,10 @@ class CBotTF2WaitHealthTask : public CBotTask class CBotTFDoubleJump : public CBotTask { public: - CBotTFDoubleJump (); // going here - - void execute (CBot *pBot,CBotSchedule *pSchedule); - virtual void debugString ( char *string ); + CBotTFDoubleJump(); // going here + + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + void debugString(char* string, unsigned bufferSize) override; private: float m_fTime; }; @@ -1069,24 +1093,24 @@ class CBotTFDoubleJump : public CBotTask class CBotTFRocketJump : public CBotTask { public: - CBotTFRocketJump (); // going here - - void execute (CBot *pBot,CBotSchedule *pSchedule); - virtual void debugString ( char *string ); + CBotTFRocketJump(); // going here + + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + void debugString(char* string, unsigned bufferSize) override; private: float m_fTime; float m_fJumpTime; - int m_iState; + //int m_iState; }; class CBotTF2SpySap : public CBotTask { public: - CBotTF2SpySap ( edict_t *pBuilding, eEngiBuild id ); // going to use this - - void execute (CBot *pBot,CBotSchedule *pSchedule); + CBotTF2SpySap(edict_t* pBuilding, eEngiBuild id); // going to use this + + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - virtual void debugString ( char *string ); + void debugString(char* string, unsigned bufferSize) override; private: MyEHandle m_pBuilding; float m_fTime; @@ -1096,10 +1120,10 @@ class CBotTF2SpySap : public CBotTask class CBotTFUseTeleporter : public CBotTask { public: - CBotTFUseTeleporter ( edict_t *pTele ); // going to use this - - void execute (CBot *pBot,CBotSchedule *pSchedule); - virtual void debugString ( char *string ); + CBotTFUseTeleporter(edict_t* pTele); // going to use this + + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + void debugString(char* string, unsigned bufferSize) override; private: MyEHandle m_pTele; float m_fTime; @@ -1109,9 +1133,9 @@ class CBotTFUseTeleporter : public CBotTask class CBotTaskEngiPickupBuilding : public CBotTask { public: - CBotTaskEngiPickupBuilding ( edict_t *pBuilding ); // going to use this - void execute (CBot *pBot,CBotSchedule *pSchedule); - virtual void debugString ( char *string ); + CBotTaskEngiPickupBuilding(edict_t* pBuilding); // going to use this + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + void debugString(char* string, unsigned bufferSize) override; private: MyEHandle m_pBuilding; float m_fTime; @@ -1120,24 +1144,24 @@ class CBotTaskEngiPickupBuilding : public CBotTask class CBotTaskEngiPlaceBuilding : public CBotTask { public: - CBotTaskEngiPlaceBuilding ( eEngiBuild iObject, Vector vOrigin ); // going to use this - void execute (CBot *pBot,CBotSchedule *pSchedule); - virtual void debugString ( char *string ); + CBotTaskEngiPlaceBuilding(eEngiBuild iObject, const Vector& vOrigin); // going to use this + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + void debugString(char* string, unsigned bufferSize) override; private: Vector m_vOrigin; float m_fTime; eEngiBuild m_iObject; - int m_iState; + //int m_iState; int m_iTries; }; class CBotTF2WaitFlagTask : public CBotTask { public: - CBotTF2WaitFlagTask ( Vector vOrigin, bool bFind = false ); - - void execute (CBot *pBot,CBotSchedule *pSchedule); - virtual void debugString ( char *string ); + CBotTF2WaitFlagTask(const Vector& vOrigin, bool bFind = false); + + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + void debugString(char* string, unsigned bufferSize) override; private: Vector m_vOrigin; float m_fWaitTime; @@ -1147,13 +1171,13 @@ class CBotTF2WaitFlagTask : public CBotTask class CThrowGrenadeTask : public CBotTask { public: - CThrowGrenadeTask ( CBotWeapon *pWeapon, int ammo, Vector vLoc ); - void init (); - void execute (CBot *pBot,CBotSchedule *pSchedule); - virtual void debugString ( char *string ); + CThrowGrenadeTask(CBotWeapon* pWeapon, int ammo, const Vector& vLoc); + void init() override; + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + void debugString(char* string, unsigned bufferSize) override; private: Vector m_vLoc; - CBotWeapon *m_pWeapon; + CBotWeapon* m_pWeapon; float m_fTime; float m_fHoldAttackTime; int m_iAmmo; @@ -1162,10 +1186,10 @@ class CThrowGrenadeTask : public CBotTask class CAttackEntityTask : public CBotTask { public: - CAttackEntityTask ( edict_t *pEdict ); - void init (); - void execute (CBot *pBot,CBotSchedule *pSchedule); - virtual void debugString ( char *string ); + CAttackEntityTask(edict_t* pEdict); + void init() override; + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + void debugString(char* string, unsigned bufferSize) override; private: MyEHandle m_pEdict; }; @@ -1174,56 +1198,157 @@ class CAttackEntityTask : public CBotTask class CAutoBuy : public CBotTask { public: - void init (); + void init() override; + + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + +private: + float m_fTime = 0.0f; + bool m_bTimeset = false; +}; + +class CCSSPerformBuyTask : public CBotTask +{ +public: + void init() override; + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + void debugString(char* string, const unsigned bufferSize) override + { + snprintf(string, bufferSize, "CSS Perform Buy"); + } +private: + float m_fDelay = 0.0f; +}; + +class CCSSPlantTheBombTask : public CBotTask +{ +public: + void init() override + { + setFailInterrupt(CONDITION_SEE_CUR_ENEMY); + } + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + void debugString(char* string, const unsigned bufferSize) override + { + snprintf(string, bufferSize, "CSS Plant C4"); + } +}; + +class CCSSEngageEnemyTask : public CBotTask +{ +public: + CCSSEngageEnemyTask(const edict_t* pEnemy) + { + isBrush = false; + m_hEnemy.Init(engine->IndexOfEdict(pEnemy), pEnemy->m_NetworkSerialNumber); + } + void init() override + { + setFailInterrupt(CONDITION_ENEMY_OBSCURED); + setCompleteInterrupt(CONDITION_ENEMY_DEAD); + } + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + void debugString(char* string, unsigned bufferSize) override; +private: + CBaseHandle m_hEnemy; + bool isBrush; // Is my enemy a brush entity? +}; - void execute (CBot *pBot,CBotSchedule *pSchedule); +class CCSSDefuseTheBombTask : public CBotTask +{ +public: + CCSSDefuseTheBombTask(const Vector& vBomb) : m_vBomb(vBomb) + { + } + void init() override + { + setFailInterrupt(CONDITION_SEE_CUR_ENEMY); + } + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + void debugString(char* string, const unsigned bufferSize) override + { + snprintf(string, bufferSize, "CSS Defuse C4\nBomb Vector (%0.4f,%0.4f,%0.4f)", m_vBomb.x, m_vBomb.y, m_vBomb.z); + } +private: + Vector m_vBomb; +}; +class CCSSGuardTask : public CBotTask +{ +public: + CCSSGuardTask(CBotWeapon* pWeaponToUse, const Vector& vOrigin, const float fYaw, const bool bUseZ, const float z, const int iWaypointType) : m_vOrigin(vOrigin) + { + m_fEnemyTime = 0.0f; + m_fTime = 0.0f; + const QAngle angle = QAngle(0, fYaw, 0); + AngleVectors(angle, &m_vAim); + m_vAim = vOrigin + m_vAim * 1024; + m_pWeaponToUse = pWeaponToUse; + m_fScopeTime = 0.0f; + m_bUseZ = bUseZ; + m_z = z; // z = ground level + m_iWaypointType = iWaypointType; + } + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + void debugString(char* string, const unsigned bufferSize) override + { + snprintf(string, bufferSize, "CSS Guard Task\nm_fEnemyTime = %.1f\nm_fTime = %.1f", m_fEnemyTime, m_fTime); + } private: float m_fTime; - bool m_bTimeset; + float m_fEnemyTime; + float m_fScopeTime; + Vector m_vAim; + Vector m_vOrigin; + CBotWeapon* m_pWeaponToUse; + bool m_bUseZ; + float m_z; // z = ground level + int m_iWaypointType; }; + ////////////////////// class CTF2_TauntTask : public CBotTask { public: - CTF2_TauntTask ( Vector vPlayer, Vector vOrigin, float fDist ) + CTF2_TauntTask(edict_t* pPlayer, const Vector& vOrigin, const float fDist) + : m_pPlayer(pPlayer), m_vOrigin(vOrigin), m_fDist(fDist) { - m_vPlayer = vPlayer; - m_vOrigin = vOrigin; - m_fDist = fDist; + m_fTime = 0.0f; + m_fTauntUntil = 0.0f; + m_fActionTime = 0.0f; } - void init (); - - void execute ( CBot *pBot, CBotSchedule *pSchedule ); + void init() override; + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + void debugString(char* string, unsigned bufferSize) override; - virtual void debugString ( char *string ); private: - Vector m_vPlayer; + MyEHandle m_pPlayer; Vector m_vOrigin; float m_fDist; float m_fTime; + float m_fTauntUntil; + float m_fActionTime; }; ///////////////////// class CMoveToTask : public CBotTask { public: - CMoveToTask ( Vector vOrigin ) + CMoveToTask(const Vector& vOrigin) : m_vVector(vOrigin) { - m_vVector = vOrigin; - m_pEdict = NULL; + m_pEdict = nullptr; + fPrevDist = 0.0f; setFailInterrupt(CONDITION_SEE_CUR_ENEMY); } - CMoveToTask ( edict_t *pEdict ); + CMoveToTask(edict_t* pEdict); - void init (); + void init() override; + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + void debugString(char* string, unsigned bufferSize) override; - void execute ( CBot *pBot, CBotSchedule *pSchedule ); - - virtual void debugString ( char *string ); private: float fPrevDist; Vector m_vVector; @@ -1233,13 +1358,13 @@ class CMoveToTask : public CBotTask class CMessAround : public CBotTask { public: - CMessAround ( edict_t *pFriendly, int iMaxVoiceCmd ); + CMessAround(edict_t* pFriendly, int iMaxVoiceCmd); - void execute ( CBot *pBot, CBotSchedule *pSchedule ); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - void debugString ( char *string ) + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string,"CMessAround"); + snprintf(string, bufferSize, "CMessAround"); } private: float m_fTime; @@ -1248,17 +1373,16 @@ class CMessAround : public CBotTask int m_iType; // 0 = attack friendly , 1 = taunt, 2 = random voice command }; - class CFindLastEnemy : public CBotTask { public: - CFindLastEnemy (Vector vLast,Vector vVelocity); + CFindLastEnemy(const Vector& vLast, const Vector& vVelocity); - void execute ( CBot *pBot, CBotSchedule *pSchedule ); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - void debugString ( char *string ) + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string,"CFindLastEnemy"); + snprintf(string, bufferSize, "CFindLastEnemy"); } private: Vector m_vLast; @@ -1268,18 +1392,17 @@ class CFindLastEnemy : public CBotTask class CFindGoodHideSpot : public CBotTask { public: - CFindGoodHideSpot ( edict_t *pEntity ); - - CFindGoodHideSpot ( Vector vec ); + CFindGoodHideSpot(edict_t* pEntity); - void init (); + CFindGoodHideSpot(const Vector& vec); - void execute ( CBot *pBot, CBotSchedule *pSchedule ); + void init() override; + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - void debugString ( char *string ) + void debugString(char* string, const unsigned bufferSize) override { - sprintf(string,"CFindGoodHideSpot"); + snprintf(string, bufferSize, "CFindGoodHideSpot"); } private: Vector m_vHideFrom; @@ -1288,13 +1411,13 @@ class CFindGoodHideSpot : public CBotTask class CHideTask : public CBotTask { public: - CHideTask ( Vector vHideFrom ); + CHideTask(const Vector& vHideFrom); - void init (); + void init() override; - void execute ( CBot *pBot, CBotSchedule *pSchedule ); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - virtual void debugString ( char *string ); + void debugString(char* string, unsigned bufferSize) override; private: Vector m_vHideFrom; float m_fHideTime; @@ -1303,13 +1426,13 @@ class CHideTask : public CBotTask class CFollowTask : public CBotTask { public: - CFollowTask ( edict_t *pFollow ); + CFollowTask(edict_t* pFollow); - void init (); + void init() override; - void execute ( CBot *pBot, CBotSchedule *pSchedule ); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - virtual void debugString ( char *string ); + void debugString(char* string, unsigned bufferSize) override; private: MyEHandle m_pFollow; float m_fFollowTime; @@ -1317,17 +1440,16 @@ class CFollowTask : public CBotTask Vector m_vLastSeeVelocity; }; - class CCrouchHideTask : public CBotTask { public: - CCrouchHideTask ( edict_t *pHideFrom ); + CCrouchHideTask(edict_t* pHideFrom); - void init (); + void init() override; - void execute ( CBot *pBot, CBotSchedule *pSchedule ); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - virtual void debugString ( char *string ); + void debugString(char* string, unsigned bufferSize) override; private: MyEHandle m_pHideFrom; float m_fHideTime; @@ -1339,13 +1461,20 @@ class CCrouchHideTask : public CBotTask class CSpyCheckAir : public CBotTask { public: - CSpyCheckAir () { m_fTime = 0.0f; m_pUnseenBefore = NULL; m_bHitPlayer = false; } + CSpyCheckAir() + { + seenlist = 0; + m_fNextCheckUnseen = 0.0f; + m_fTime = 0.0f; + m_pUnseenBefore = nullptr; + m_bHitPlayer = false; + } - void execute ( CBot *pBot, CBotSchedule *pSchedule ); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; - void debugString (char *string); + void debugString(char* string, unsigned bufferSize) override; private: - edict_t *m_pUnseenBefore; + edict_t* m_pUnseenBefore; int seenlist; float m_fNextCheckUnseen; float m_fTime; @@ -1355,12 +1484,12 @@ class CSpyCheckAir : public CBotTask class CTaskVoiceCommand : public CBotTask { public: - CTaskVoiceCommand(int iVoiceCmd) + CTaskVoiceCommand(const byte iVoiceCmd) { m_iVoiceCmd = iVoiceCmd; } - void execute ( CBot *pBot, CBotSchedule *pSchedule ) + void execute(CBot* pBot, CBotSchedule* pSchedule) override { pBot->addVoiceCommand(m_iVoiceCmd); @@ -1368,15 +1497,96 @@ class CTaskVoiceCommand : public CBotTask } private: - int m_iVoiceCmd; + byte m_iVoiceCmd; }; class CPrimaryAttack : public CBotTask { public: - void execute ( CBot *pBot, CBotSchedule *pSchedule ); + void execute(CBot* pBot, CBotSchedule* pSchedule) override; }; + +class CBotWaitTask : public CBotTask +{ +public: + CBotWaitTask(const float waittime) + { + m_fTime = engine->Time() + waittime; + m_bAimSet = false; + } + CBotWaitTask(const float waittime, const Vector& vAim) : m_vAim(vAim) + { + m_fTime = engine->Time() + waittime; + m_bAimSet = true; + } + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + void debugString(char* string, unsigned bufferSize) override; +private: + float m_fTime; + bool m_bAimSet; + Vector m_vAim; +}; + +class CBotSynDisarmMineTask : public CBotTask +{ +public: + CBotSynDisarmMineTask(edict_t* pMine) : m_pMine(pMine) + { + m_fDist = 0.0f; + m_fTime = 0.0f; + m_bTimeSet = false; + } + void execute(CBot* pBot, CBotSchedule* pSchedule) override; + void debugString(char* string, unsigned bufferSize) override; +private: + Vector m_vMinePos; + float m_fDist; + float m_fTime; + bool m_bTimeSet; + MyEHandle m_pMine; +}; + +class CBotSynBreakICrateTask : public CBotTask +{ +public: + CBotSynBreakICrateTask(edict_t* pCrate, CBotWeapon* pWeapon) : m_pCrate(pCrate) + { + m_pWeapon = pWeapon; + m_vPos = Vector(0, 0, 0); + } + void debugString(char* string, const unsigned bufferSize) override + { + snprintf(string, bufferSize, "Break Item Crate"); + } + void execute(CBot* pBot, CBotSchedule* pSchedule) override; +private: + CBotWeapon* m_pWeapon; + MyEHandle m_pCrate; + Vector m_vPos; +}; + +class CBotSynUseCharger : public CBotTask +{ +public: + CBotSynUseCharger(edict_t* pCharger, const int type) : m_pCharger(pCharger) + { + m_vPos = Vector(0, 0, 0); + m_iType = type; + m_flTime = engine->Time() + randomFloat(8.0f, 10.0f); + } + void debugString(char* string, const unsigned bufferSize) override + { + snprintf(string, bufferSize, "Use Charger"); + } + void execute(CBot* pBot, CBotSchedule* pSchedule) override; +private: + MyEHandle m_pCharger; + Vector m_vPos; + int m_iType; + float m_flTime; +}; + /* class CAttackTask : public CBotTask { diff --git a/utils/RCBot2_meta/bot_tf2_mod.cpp b/utils/RCBot2_meta/bot_tf2_mod.cpp index 0ba770aaf..963db8147 100644 --- a/utils/RCBot2_meta/bot_tf2_mod.cpp +++ b/utils/RCBot2_meta/bot_tf2_mod.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -30,280 +32,109 @@ */ #include "engine_wrappers.h" -//#include "server_class.h" + // #include "server_class.h" #include "bot.h" +#include "bot_cvars.h" #include "in_buttons.h" -#include "bot_mods.h" -#include "bot_globals.h" -#include "bot_fortress.h" -#include "bot_weapons.h" #include "bot_configfile.h" +#include "bot_fortress.h" #include "bot_getprop.h" +#include "bot_globals.h" +#include "bot_mods.h" #include "bot_navigator.h" -#include "bot_waypoint.h" -#include "bot_waypoint_locations.h" #include "bot_perceptron.h" -#include "bot_tf2_points.h" #include "bot_sigscan.h" +#include "bot_tf2_points.h" +#include "bot_waypoint.h" +#include "bot_waypoint_locations.h" +#include "bot_weapons.h" + +#include +#include + +#include "rcbot/logging.h" + +//#if SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_BMS +#include "valve_minmax_off.h" +//#endif eTFMapType CTeamFortress2Mod :: m_MapType = TF_MAP_CTF; -tf_tele_t CTeamFortress2Mod :: m_Teleporters[MAX_PLAYERS]; +tf_tele_t CTeamFortress2Mod :: m_Teleporters[RCBOT_MAXPLAYERS]; + int CTeamFortress2Mod :: m_iArea = 0; + float CTeamFortress2Mod::m_fSetupTime = 0.0f; float CTeamFortress2Mod::m_fRoundTime = 0.0f; -MyEHandle CTeamFortress2Mod::m_pFlagCarrierRed = MyEHandle(NULL); -MyEHandle CTeamFortress2Mod::m_pFlagCarrierBlue = MyEHandle(NULL); + +MyEHandle CTeamFortress2Mod::m_pFlagCarrierRed = MyEHandle(nullptr); +MyEHandle CTeamFortress2Mod::m_pFlagCarrierBlue = MyEHandle(nullptr); + float CTeamFortress2Mod::m_fArenaPointOpenTime = 0.0f; float CTeamFortress2Mod::m_fPointTime = 0.0f; -tf_sentry_t CTeamFortress2Mod::m_SentryGuns[MAX_PLAYERS]; // used to let bots know if sentries have been sapped or not -tf_disp_t CTeamFortress2Mod::m_Dispensers[MAX_PLAYERS]; // used to let bots know where friendly/enemy dispensers are -MyEHandle CTeamFortress2Mod::m_pResourceEntity = MyEHandle(NULL); -MyEHandle CTeamFortress2Mod::m_pGameRules = MyEHandle(NULL); + +tf_sentry_t CTeamFortress2Mod::m_SentryGuns[RCBOT_MAXPLAYERS]; // used to let bots know if sentries have been sapped or not +tf_disp_t CTeamFortress2Mod::m_Dispensers[RCBOT_MAXPLAYERS]; // used to let bots know where friendly/enemy dispensers are + +MyEHandle CTeamFortress2Mod::m_pResourceEntity = MyEHandle(nullptr); +MyEHandle CTeamFortress2Mod::m_pGameRules = MyEHandle(nullptr); + bool CTeamFortress2Mod::m_bAttackDefendMap = false; int CTeamFortress2Mod::m_Cappers[MAX_CONTROL_POINTS]; int CTeamFortress2Mod::m_iCapDefenders[MAX_CONTROL_POINTS]; bool CTeamFortress2Mod::m_bHasRoundStarted = true; bool CTeamFortress2Mod::m_bDontClearPoints = false; int CTeamFortress2Mod::m_iFlagCarrierTeam = 0; -MyEHandle CTeamFortress2Mod::m_pBoss = MyEHandle(NULL); +MyEHandle CTeamFortress2Mod::m_pBoss = MyEHandle(nullptr); bool CTeamFortress2Mod::m_bBossSummoned = false; -MyEHandle CTeamFortress2Mod::pMediGuns[MAX_PLAYERS]; +MyEHandle CTeamFortress2Mod::pMediGuns[RCBOT_MAXPLAYERS]; CTFObjectiveResource CTeamFortress2Mod::m_ObjectiveResource = CTFObjectiveResource(); -CTeamControlPointMaster *CTeamFortress2Mod::m_PointMaster = NULL; +CTeamControlPointMaster *CTeamFortress2Mod::m_PointMaster = nullptr; CTeamRoundTimer CTeamFortress2Mod::m_Timer; -MyEHandle CTeamFortress2Mod::m_PointMasterResource = MyEHandle(NULL); -CTeamControlPointRound *CTeamFortress2Mod::m_pCurrentRound = NULL; +MyEHandle CTeamFortress2Mod::m_PointMasterResource = MyEHandle(nullptr); +CTeamControlPointRound *CTeamFortress2Mod::m_pCurrentRound = nullptr; + bool CTeamFortress2Mod::bFlagStateDefault = true; -MyEHandle CTeamFortress2Mod::m_pPayLoadBombBlue = MyEHandle(NULL); -MyEHandle CTeamFortress2Mod::m_pPayLoadBombRed = MyEHandle(NULL); + +MyEHandle CTeamFortress2Mod::m_pPayLoadBombBlue = MyEHandle(nullptr); +MyEHandle CTeamFortress2Mod::m_pPayLoadBombRed = MyEHandle(nullptr); + bool CTeamFortress2Mod::m_bRoundOver = false; int CTeamFortress2Mod::m_iWinningTeam = 0; int CTeamFortress2Mod::m_iLastWinningTeam = 0; + Vector CTeamFortress2Mod::m_vFlagLocationBlue = Vector(0,0,0); Vector CTeamFortress2Mod::m_vFlagLocationRed = Vector(0,0,0); + bool CTeamFortress2Mod::m_bFlagLocationValidBlue = false; bool CTeamFortress2Mod::m_bFlagLocationValidRed = false; + bool CTeamFortress2Mod::m_bMVMFlagStartValid = false; Vector CTeamFortress2Mod::m_vMVMFlagStart = Vector(0,0,0); bool CTeamFortress2Mod::m_bMVMCapturePointValid = false; Vector CTeamFortress2Mod::m_vMVMCapturePoint = Vector(0,0,0); bool CTeamFortress2Mod::m_bMVMAlarmSounded = false; float CTeamFortress2Mod::m_fMVMCapturePointRadius = 0.0f; + int CTeamFortress2Mod::m_iCapturePointWptID = -1; int CTeamFortress2Mod::m_iFlagPointWptID = -1; -vector CTeamFortress2Mod::m_pLoadoutWeapons[TF2_SLOT_MAX][9]; -MyEHandle CTeamFortress2Mod::m_pNearestTankBoss = NULL; -float CTeamFortress2Mod::m_fNearestTankDistance = 0.0f; -Vector CTeamFortress2Mod::m_vNearestTankLocation = Vector(0, 0, 0); -vector CAttributeLookup::attributes; -extern ConVar bot_use_disp_dist; - -int UTIL_FindAttributeID ( vector *list, const char *name ) -{ - unsigned int i; - - for ( i = 0; i < list->size(); i ++ ) - { - CAttributeID *attrib = list->at(i); - - if ( attrib && (strcmp(attrib->m_attribute,name) == 0) ) - { - return attrib->m_id; - } - } - - return -1; -} - -CTF2Loadout :: CTF2Loadout ( const char *pszClassname, int iIndex, int iQuality, int iMinLevel, int iMaxLevel ) -{ - m_pszClassname = CStrings::getString(pszClassname); - m_iIndex = iIndex; - m_iQuality = iQuality; - m_iMinLevel = iMinLevel; - m_iMaxLevel = iMaxLevel; - m_bCanBeUsedInMedieval = false; - -} -void CSCICopy(CEconItemView *olditem, CEconItemView *newitem) -{ - memset(newitem, 0, sizeof(CEconItemView)); - - //#define copymember(a) newitem->a = olditem->a -#define copymember(a) memcpy(&newitem->a, &olditem->a, sizeof(newitem->a)); - - copymember(m_pVTable); - - copymember(m_iItemDefinitionIndex); - - copymember(m_iEntityQuality); - copymember(m_iEntityLevel); - - copymember(m_iItemID); - copymember(m_iItemIDHigh); - copymember(m_iItemIDLow); - copymember(m_iAccountID); - copymember(m_iInventoryPosition); - - copymember(m_ItemHandle); - - copymember(m_bColorInit); - copymember(m_bPaintOverrideInit); - copymember(m_bHasPaintOverride); - - copymember(m_flOverrideIndex); - copymember(m_unRGB); - copymember(m_unAltRGB); - - copymember(m_iTeamNumber); - - copymember(m_bInitialized); - // copy ctor so the CUtlVector is copied correctly - newitem->m_AttributeList = olditem->m_AttributeList; - newitem->m_NetworkedDynamicAttributesForDemos = olditem->m_NetworkedDynamicAttributesForDemos; +MyEHandle CTeamFortress2Mod::m_pNearestTankBoss = nullptr; - copymember(m_bDoNotIterateStaticAttributes); - - /* - META_CONPRINTF("Copying attributes...\n"); - int nCount = olditem->m_Attributes.Count(); - META_CONPRINTF("Count: %d\n", nCount); - newitem->m_Attributes.SetSize( nCount ); - for ( int i = 0; i < nCount; i++ ) - { - META_CONPRINTF("Copying %d...\n", i+1); - newitem->m_Attributes[ i ] = olditem->m_Attributes[ i ]; - } - */ -} - - -void CAttributeLookup::addAttribute(const char *pszAttrib, int id) -{ - attributes.push_back(new CAttributeID(id, pszAttrib)); -} - -void CAttributeLookup::freeMemory() -{ - for (unsigned int i = 0; i < attributes.size(); i++) - { - CAttributeID *attrib = attributes[i]; - - delete attrib; - - attributes[i] = NULL; - } -} - -int CAttributeLookup::findAttributeID(const char *name) -{ - unsigned int i; - - for (i = 0; i < attributes.size(); i++) - { - CAttributeID *attrib = attributes.at(i); - - if (attrib && (strcmp(attrib->m_attribute, name) == 0)) - { - return attrib->m_id; - } - } - - return -1; -} - -/* -int TF2II_GetItemLevelByID(int iItemDefinitionIndex) -{ - int iLevel = 1; - //new iSlot = TF2II_GetItemSlotByID(iItemDefinitionIndex); - //if (iSlot >= TF2ItemSlot_Hat && iSlot <= TF2ItemSlot_Misc) - // iLevel = GetRandomInt(1, 100); - switch (iItemDefinitionIndex) - { - case 125; 262; 335, 336, 360, 434, 435: iLevel = 1; - case 164, 343: iLevel = 5; - case 115, 116, 126, 165, 240, 261, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 263, 279, 346, 347, 486, 408, 409, 410, 470, 473, 490, 491, 492, 514, 515, 516, 517, 518, 519, 520, 537: iLevel = 10; - case 422: iLevel = 13; - case 166, 333, 392, 443, 483, 484: iLevel = 15; - case 170, 189, 295, 299, 296, 345, 420, 432, 454, 1899: iLevel = 20; - case 334: iLevel = 28; - case 332: iLevel = 30; - case 278, 287, 289, 290, 291: iLevel = 31; - case 292, 471: iLevel = 50; - } - return iLevel; -} - - -*/ -/* -void CTF2Loadout::getScript ( CEconItemView *cscript ) -{ - static CEconItemAttribute m_Attributes[16]; - extern ConVar rcbot_enable_attributes; - - cscript->m_iEntityLevel = m_iLevel; - cscript->m_iEntityQuality = m_iQuality; - cscript->m_iItemDefinitionIndex = m_iIndex; - cscript->m_bInitialized = true; - - if ( rcbot_enable_attributes.GetBool() ) - { - unsigned int size = copyAttributesIntoArray(m_Attributes,cscript->m_pVTable_Attributes); - - if ( size > 0 ) - { - cscript->m_Attributes.CopyArray(m_Attributes,size); - - cscript->m_bDoNotIterateStaticAttributes = true; - - if ( cscript->m_iEntityQuality == 0 ) - cscript->m_iEntityQuality = 6; - } - } - -}*/ -/* -const char *CTF2Loadout :: getScript ( CEconItemView *script ) -{ - script->m_iEntityLevel = m_iLevel; - script->m_iItemDefinitionIndex = m_iIndex; - script->m_iEntityQuality = m_iQuality; - script->m_bInitialized = true; - - return m_pszClassname; -}*/ - -CTF2Loadout *CTeamFortress2Mod :: getRandomHat ( int iClass ) -{ - int iSize; - - if ( (iSize = m_pLoadoutWeapons[TF2_SLOT_HAT][iClass].size()) > 0) - { - return m_pLoadoutWeapons[TF2_SLOT_HAT][iClass].at(randomInt(0, iSize - 1)); - } - - return NULL; -} +float CTeamFortress2Mod::m_fNearestTankDistance = 0.0f; +Vector CTeamFortress2Mod::m_vNearestTankLocation = Vector(0, 0, 0); bool CTeamFortress2Mod::isSuddenDeath() { - extern ConVar *mp_stalemate_enable; - // Bot weapon Randomizer -- leonardo - if (!mp_stalemate_enable || !mp_stalemate_enable->GetBool() || isMapType(TF_MAP_ARENA)) + if (!mp_stalemate_enable.IsValid() || !mp_stalemate_enable.GetBool() || isMapType(TF_MAP_ARENA) || isMapType(TF_MAP_SAXTON)) return false; - void *pGameRules = GetGameRules(); - - if (pGameRules) + if (void *pGameRules = GetGameRules()) { - int iRoundState = CClassInterface::TF2_getRoundState(pGameRules); + const int iRoundState = CClassInterface::TF2_getRoundState(pGameRules); return iRoundState == RoundState_Stalemate; } @@ -311,411 +142,33 @@ bool CTeamFortress2Mod::isSuddenDeath() return false; } -#define CHECK_PREFAB_INT(val) ((prefab==NULL)||(prefab->GetInt(val,-1)==-1))?kv->GetInt(val):prefab->GetInt(val) -#define CHECK_PREFAB_STRING(val) ((prefab==NULL)||(prefab->GetString(val,NULL)==NULL))?kv->GetString(val):prefab->GetString(val) -#define CHECK_PREFAB_FINDKEY(keyname) ((prefab==NULL)||(prefab->FindKey(keyname)==NULL))?kv->FindKey(keyname):prefab->FindKey(keyname) - -void CTeamFortress2Mod::setupLoadOutWeapons() -{ - extern IFileSystem *filesystem; - KeyValues *mainkv = new KeyValues("tfweapons"); - - KeyValues *kv; - KeyValues *usedbyclass; - KeyValues *attribs; - KeyValues *prefabs; - KeyValues *prefab; - - CBotGlobals::botMessage(NULL, 0, "Reading Weapon Loadout details from TF MOD..."); - mainkv->LoadFromFile(filesystem, "scripts/items/items_game.txt", "MOD"); - - kv = mainkv->FindKey("items"); - prefabs = mainkv->FindKey("prefabs"); - - attribs = mainkv->FindKey("attributes"); - - if (attribs) - { - attribs = attribs->FindKey("1"); - - if (attribs) - { - do - { - int id; - - const char *keyname = attribs->GetName(); - - const char *attrib_name; - - if (keyname && *keyname) - { - id = atoi(keyname); - - attrib_name = attribs->GetString("name"); - - CAttributeLookup::addAttribute(CStrings::getString(attrib_name), id); - } - } while ((attribs = attribs->GetNextTrueSubKey()) != NULL); - } - - } - - if (kv) - { - kv = kv->FindKey("default"); - - if (kv) - { - while ((kv = kv->GetNextTrueSubKey()) != NULL) - { - int iclass = 0; - - CTF2Loadout *added = NULL; - - const char *szPrefab = kv->GetString("prefab"); - prefab = NULL; - - if ((strncmp(szPrefab, "valve", 5) == 0) && (strlen(szPrefab) > 6)) - { - prefab = prefabs->FindKey(&szPrefab[6]); - - if (prefab == NULL) - { - // search prefabs for "valve" - } - } - else if ((szPrefab != NULL) && (*szPrefab != NULL)) - { - prefab = prefabs->FindKey(szPrefab); - } - - const char *szKeyName = kv->GetName(); - - int iindex; - - if (szKeyName && *szKeyName) - { - if ((*szKeyName >= '0') && (*szKeyName <= '9')) - iindex = atoi(szKeyName); - else - continue; // not a number - } - else - continue; - - const char *pszquality; - int iquality = 0; - int iminlevel = 1; - int imaxlevel = 1; - bool bIsWeapon = false; - int islot = 0; - - // These two demoman weapons seem to cause problems - // skip them - if (iindex == 1151) - continue; - if (iindex == 1150) - continue; - - KeyValues *loadout; - - if (prefab != NULL) - loadout = prefab; - else - loadout = kv; - - const char *classname = CHECK_PREFAB_STRING("item_class");//loadout->GetString("item_class"); - - if ((classname == NULL) || (*classname == 0)) - continue; - - const char *slot = CHECK_PREFAB_STRING("item_slot"); //loadout->GetString("item_slot"); - - if ((slot == NULL) || (*slot == 0)) - continue; - - usedbyclass = CHECK_PREFAB_FINDKEY("used_by_classes");// loadout->FindKey("used_by_classes"); - - if (usedbyclass) - { - if (usedbyclass->FindKey("scout") && ((usedbyclass->GetInt("scout", 0) == 1) || (strcmp(usedbyclass->GetString("scout"), loadout->GetString("item_slot")) == 0))) - iclass |= (1 << TF_CLASS_SCOUT); - if (usedbyclass->FindKey("sniper") && ((usedbyclass->GetInt("sniper", 0) == 1) || (strcmp(usedbyclass->GetString("sniper"), loadout->GetString("item_slot")) == 0))) - iclass |= (1 << TF_CLASS_SNIPER); - if (usedbyclass->FindKey("soldier") && ((usedbyclass->GetInt("soldier", 0) == 1) || (strcmp(usedbyclass->GetString("soldier"), loadout->GetString("item_slot")) == 0))) - iclass |= (1 << TF_CLASS_SOLDIER); - if (usedbyclass->FindKey("demoman") && ((usedbyclass->GetInt("demoman", 0) == 1) || (strcmp(usedbyclass->GetString("demoman"), loadout->GetString("item_slot")) == 0))) - iclass |= (1 << TF_CLASS_DEMOMAN); - if (usedbyclass->FindKey("medic") && ((usedbyclass->GetInt("medic", 0) == 1) || (strcmp(usedbyclass->GetString("medic"), loadout->GetString("item_slot")) == 0))) - iclass |= (1 << TF_CLASS_MEDIC);; - if (usedbyclass->FindKey("heavy") && ((usedbyclass->GetInt("heavy", 0) == 1) || (strcmp(usedbyclass->GetString("heavy"), loadout->GetString("item_slot")) == 0))) - iclass |= (1 << TF_CLASS_HWGUY); - if (usedbyclass->FindKey("pyro") && ((usedbyclass->GetInt("pyro", 0) == 1) || (strcmp(usedbyclass->GetString("pyro"), loadout->GetString("item_slot")) == 0))) - iclass |= (1 << TF_CLASS_PYRO); - if (usedbyclass->FindKey("spy") && ((usedbyclass->GetInt("spy", 0) == 1) || (strcmp(usedbyclass->GetString("spy"), loadout->GetString("item_slot")) == 0))) - iclass |= (1 << TF_CLASS_SPY); - if (usedbyclass->FindKey("engineer") && ((usedbyclass->GetInt("engineer", 0) == 1) || (strcmp(usedbyclass->GetString("engineer"), loadout->GetString("item_slot")) == 0))) - iclass |= (1 << TF_CLASS_ENGINEER); - } - - if (iclass == 0) - continue; - - pszquality = CHECK_PREFAB_STRING("item_quality"); - - if (pszquality && *pszquality) - iquality = (strcmp(pszquality, "unique") == 0) ? 6 : 0; - - iminlevel = CHECK_PREFAB_INT("min_ilevel"); - imaxlevel = CHECK_PREFAB_INT("max_ilevel"); - - if (strcmp(classname, "tf_wearable") == 0) - { - islot = 0; - - // hat - if (strcmp(slot, "misc") == 0) - { - islot = TF2_SLOT_MISC; - } - else if (strcmp(slot, "head") == 0) - { - islot = TF2_SLOT_HAT; - } - if (islot != 0) - { - added = new CTF2Loadout(classname, iindex, iquality, iminlevel, imaxlevel); - - // find which hats are available for which class and add them - for (int i = 1; i <= 9; i++) - { - if ((iclass & (1 << i)) > 0) - m_pLoadoutWeapons[islot][i - 1].push_back(added); - } - - CBotGlobals::botMessage(NULL, 0, "FOUND hat : %s", loadout->GetString("name")); - } - } - - if (added == NULL) - { - - CWeapon *pWeapon = CWeapons::getWeapon(classname); - const char *craft_class; - - craft_class = CHECK_PREFAB_STRING("craft_class"); - - // check if bots can use this weapon - if (pWeapon == NULL) - { - - if (!strcmp(craft_class, "weapon")) - { - CBotGlobals::botMessage(NULL, 1, "Weapon not in weapons ini \"%s\"", classname); - } - - continue; - } - - if (strcmp(slot, "primary") == 0) - islot = TF2_SLOT_PRMRY; - else if (strcmp(slot, "melee") == 0) - islot = TF2_SLOT_MELEE; - else if (strcmp(slot, "secondary") == 0) - islot = TF2_SLOT_SCNDR; - else - continue; - - - - if (!craft_class || !*craft_class) - continue; - - if (strcmp(craft_class, "weapon")) - continue; - - if (pWeapon->getSlot() != islot) - { - CBotGlobals::botMessage(NULL, 1, "Weapon Slot mismatch for %s - set as %d -- should be %d", pWeapon->getWeaponName(), pWeapon->getSlot(), islot); - continue; - } - - /*if ( ((iclass == TF_CLASS_ENGINEER) && (islot == TF2_SLOT_MELEE)) || (strcmp(classname,"tf_weapon_wrench")==0) ) - { - // don't add any wrenches -- may cause bots unable to build sentries - continue; - }*/ - - CBotGlobals::botMessage(NULL, 0, "FOUND loadout : %s", loadout->GetString("name")); - - //attributes - added = new CTF2Loadout(classname, iindex, iquality, iminlevel, imaxlevel); - - for (int i = 1; i <= 9; i++) - { - if ((iclass & (1 << i)) > 0) - m_pLoadoutWeapons[islot][i - 1].push_back(added); - } - - //m_pLoadoutWeapons[islot][iclass-1].push_back(added); - bIsWeapon = true; - } - - if (added) - { - //if ( prefab != NULL ) - // loadout = kv; - - attribs = CHECK_PREFAB_FINDKEY("attributes"); - - if (attribs) - { - attribs = attribs->GetFirstSubKey(); - - if (attribs) - { - do - { - const char *attribname = attribs->GetName(); - float fval = attribs->GetFloat("value"); - - if (attribname && *attribname) - { - int iId = CAttributeLookup::findAttributeID(attribname); - - if (bIsWeapon && (strcmp(attribname, "damage penalty") == 0)) - { - // don't add any weapons that don't cause damage e.g. rocket jumper - if (fval == 0) - { - // delete - for (int i = 1; i <= 9; i++) - { - if ((iclass & (1 << i)) > 0) - m_pLoadoutWeapons[islot][i - 1].pop_back(); - } - - // m_pLoadoutWeapons[islot][iclass-1].pop_back(); - - delete added; // free - - attribs = NULL; // break loop - - iId = -1; // don't add - } - } - else if (strcmp(attribname, "allowed in medieval mode") == 0) - { - added->m_bCanBeUsedInMedieval = true; - } - - if (iId != -1) - added->addAttribute(iId, fval); - } - } while (attribs && ((attribs = attribs->GetNextTrueSubKey()) != NULL)); - } - } - } - } - } - } - - mainkv->deleteThis(); - /* - m_pLoadoutWeapons[TF2_SLOT_PRMRY][TF_CLASS_PYRO].push_back(new CTF2LoadoutWeapon("tf_weapon_flamethrower",40,6,10,"170 ; 2.5 ; 24 ; 1.0 ; 28 ; 0.0",200)); - m_pLoadoutWeapons[TF2_SLOT_SCNDR][TF_CLASS_PYRO].push_back(new CTF2LoadoutWeapon("tf_weapon_flaregun",39,6,10,"25 ; 0.5",16)); - m_pLoadoutWeapons[TF2_SLOT_PRMRY][TF_CLASS_SOLDIER].push_back(new CTF2LoadoutWeapon("tf_weapon_rocketlauncher_directhit",127,6,1,"100 ; 0.3 ; 103 ; 1.8 ; 2 ; 1.25 ; 114 ; 1.0 ; 328 ; 1.0",20)); - */ - -} - -CTF2Loadout *CTeamFortress2Mod::findRandomWeaponLoadOutInSlot(int iclass, int islot) -{ - vector *list = &(m_pLoadoutWeapons[islot][iclass - 1]); - CTF2Loadout *weap = NULL; - - if (list->size() == 0) - return NULL; - - if (((islot == TF2_SLOT_PRMRY) || (islot == TF2_SLOT_SCNDR)) && CTeamFortress2Mod::isMedievalMode()) - { - vector newlist; - unsigned int _size = list->size(); - - // add all medieval weapons - for (unsigned i = 0; i < _size; i++) - { - CTF2Loadout *temp = list->at(i); - - if (temp->m_bCanBeUsedInMedieval) - { - newlist.push_back(temp); - } - } - - if (newlist.size() > 0) - { - weap = newlist.at(randomInt(0, newlist.size() - 1)); - } - } - else - weap = list->at(randomInt(0, list->size() - 1)); - - return weap; -} - bool CTeamFortress2Mod::isMedievalMode() { return CClassInterface::TF2_IsMedievalMode(GetGameRules()); } -/* -CTF2Loadout *CTeamFortress2Mod::findRandomWeaponLoadOut ( int iclass, const char *classname ) -{ - // find weapon slot - int islot; - // this is only used to find the slot - CWeapon *pWeapon = CWeapons::getWeapon(classname);//::getWeapon(classname); - - if ( pWeapon == NULL ) - return NULL; - islot = pWeapon->getSlot(); - - if ( islot == TF2_SLOT_SHOTGUN ) - { - // find the slot for this shotgun - if ( iclass == TF_CLASS_ENGINEER ) - islot = TF2_SLOT_PRMRY; - else - islot = TF2_SLOT_SCNDR; - } - - return findRandomWeaponLoadOutInSlot(iclass, islot); -} -*/ -bool CTeamFortress2Mod :: checkWaypointForTeam(CWaypoint *pWpt, int iTeam) +bool CTeamFortress2Mod::checkWaypointForTeam(CWaypoint* pWpt, const int iTeam) { -// Returns true if team can go to waypoint - return m_bRoundOver || ((!pWpt->hasFlag(CWaypointTypes::W_FL_NOBLU)||(iTeam!=TF2_TEAM_BLUE))&&(!pWpt->hasFlag(CWaypointTypes::W_FL_NORED)||(iTeam!=TF2_TEAM_RED))); + // Returns true if team can go to waypoint + return m_bRoundOver || ((!pWpt->hasFlag(CWaypointTypes::W_FL_NOBLU) || iTeam != TF2_TEAM_BLUE) && (!pWpt->hasFlag(CWaypointTypes::W_FL_NORED) || iTeam != TF2_TEAM_RED)); } - -bool CTeamFortress2Mod :: isWaypointAreaValid ( int iWptArea, int iWptFlags ) + +bool CTeamFortress2Mod :: isWaypointAreaValid (const int iWptArea, const int iWptFlags) { return CTeamFortress2Mod::m_ObjectiveResource.isWaypointAreaValid(iWptArea,iWptFlags); } /////////////////////////// -bool CTeamFortress2Mod :: withinEndOfRound ( float fTime ) +bool CTeamFortress2Mod :: withinEndOfRound (const float fTime) { if ( m_Timer.m_flTimerEndTime ) - return (gpGlobals->curtime > (*m_Timer.m_flTimerEndTime - fTime)); + return gpGlobals->curtime > *m_Timer.m_flTimerEndTime - fTime; return false; } -void CTeamFortress2Mod :: getTeamOnlyWaypointFlags ( int iTeam, int *iOn, int *iOff ) +void CTeamFortress2Mod :: getTeamOnlyWaypointFlags (const int iTeam, int *iOn, int *iOff) { if ( iTeam == TF2_TEAM_BLUE ) { @@ -727,18 +180,17 @@ void CTeamFortress2Mod :: getTeamOnlyWaypointFlags ( int iTeam, int *iOn, int *i *iOn = CWaypointTypes::W_FL_NOBLU; *iOff = CWaypointTypes::W_FL_NORED; } - } void CTeamFortress2Mod ::modFrame () { if( m_bPlayerHasSpawned ) { - if ( m_ObjectiveResource.m_ObjectiveResource == NULL ) + if ( m_ObjectiveResource.m_ObjectiveResource == nullptr ) { m_ObjectiveResource.m_ObjectiveResource = CClassInterface::FindEntityByNetClass(gpGlobals->maxClients+1, "CTFObjectiveResource"); - if ( m_ObjectiveResource.m_ObjectiveResource.get() != NULL ) + if ( m_ObjectiveResource.m_ObjectiveResource.get() != nullptr) m_ObjectiveResource.setup(); } else @@ -753,7 +205,7 @@ void CTeamFortress2Mod ::modFrame () { const char *classname = m_pGameRules.get()->GetClassName(); - CBotGlobals::botMessage(NULL, 0, "Found gamerules %s", classname); + logger->Log(LogLevel::DEBUG, "Found gamerules %s", classname); } }*/ } @@ -761,12 +213,10 @@ void CTeamFortress2Mod ::modFrame () void CTeamFortress2Mod :: initMod () { -// unsigned int i; +// unsigned i; // Setup Weapons - CBots::controlBotSetup(true); - - CWeapons::loadWeapons((m_szWeaponListName == NULL) ? "TF2" : m_szWeaponListName, TF2Weaps); + CWeapons::loadWeapons(m_szWeaponListName == nullptr ? "TF2" : m_szWeaponListName, TF2Weaps.data()); //CWeapons::loadWeapons("TF2", TF2Weaps); /* i = 0; @@ -775,7 +225,6 @@ void CTeamFortress2Mod :: initMod () */ CRCBotTF2UtilFile::loadConfig(); - setupLoadOutWeapons(); //memset(g_fBotUtilityPerturb,0,sizeof(float)*TF_CLASS_MAX*BOT_UTIL_MAX); } @@ -786,56 +235,119 @@ void CTeamFortress2Mod :: mapInit () m_vNearestTankLocation = Vector(0, 0, 0); - unsigned int i = 0; - string_t mapname = gpGlobals->mapname; + const string_t mapname = gpGlobals->mapname; const char *szmapname = mapname.ToCStr(); m_iLastWinningTeam = 0; m_iWinningTeam = 0; - m_pResourceEntity = NULL; - m_ObjectiveResource.m_ObjectiveResource = NULL; + m_pResourceEntity = nullptr; + + m_ObjectiveResource.m_ObjectiveResource = nullptr; m_ObjectiveResource.reset(); - m_PointMaster = NULL; - m_PointMasterResource = NULL; - m_pCurrentRound = NULL; + + m_PointMaster = nullptr; + m_PointMasterResource = nullptr; + m_pCurrentRound = nullptr; m_Timer = CTeamRoundTimer(); + bFlagStateDefault = true; m_bFlagLocationValidBlue = false; m_bFlagLocationValidRed = false; m_bMVMAlarmSounded = false; m_bMVMFlagStartValid = false; m_bMVMCapturePointValid = false; + m_fMVMCapturePointRadius = 0.0f; m_iCapturePointWptID = -1; m_iFlagPointWptID = -1; - if ( strncmp(szmapname,"ctf_",4) == 0 ) - m_MapType = TF_MAP_CTF; // capture the flag - else if ( strncmp(szmapname,"cp_",3) == 0 ) + if (std::strncmp(szmapname, "ctf_", 4) == 0 || std::strncmp(szmapname, "quake_turbine", 13) == 0 || + std::strncmp(szmapname, "pass_", 5) == 0 || std::strncmp(szmapname, "pd_", 3) == 0 || + std::strncmp(szmapname, "od_", 3) == 0 || + std::strncmp(szmapname, "workshop/ctf_", 13) == 0 || + std::strncmp(szmapname, "workshop/pass_", 14) == 0 || + std::strncmp(szmapname, "workshop/pd_", 12) == 0 || + std::strncmp(szmapname, "slendytubbies", 13) == 0) + // Quake Turbine is CTF. - RussiaTails + m_MapType = TF_MAP_CTF; // capture the flag + pass time + player destruction + else if (std::strncmp(szmapname, "cp_", 3) == 0 || + std::strncmp(szmapname, "cqt_", 4) == 0 || + std::strncmp(szmapname, "conquest_", 9) == 0 || + std::strncmp(szmapname, "dom_", 4) == 0 || + std::strncmp(szmapname, "2koth_", 6) == 0 || + std::strncmp(szmapname, "falling_cp", 10) == 0 || + std::strncmp(szmapname, "stt_", 4) == 0 || + std::strncmp(szmapname, "koth_lifesnatcher", 17) == 0 || + std::strncmp(szmapname, "vip_", 4) == 0 || + std::strncmp(szmapname, "vipr_", 5) == 0 || + std::strncmp(szmapname, "szf_", 4) == 0 || + std::strncmp(szmapname, "rush_", 5) == 0 || + std::strncmp(szmapname, "workshop/cp_", 12) == 0 || + std::strncmp(szmapname, "workshop/vip_", 13) == 0 || + std::strncmp(szmapname, "workshop/rush_", 14) == 0 || + std::strncmp(szmapname, "zf_", 3) == 0) + // Conquest, 2koth and DOM works fine as CP_. Moved stt to cp to make bots attack a tank - RussiaTails m_MapType = TF_MAP_CP; // control point - else if ( strncmp(szmapname,"tc_",3) == 0 ) + else if (std::strncmp(szmapname, "tc_", 3) == 0) m_MapType = TF_MAP_TC; // territory control - else if ( strncmp(szmapname,"pl_",3) == 0 ) + else if (std::strncmp(szmapname, "pl_", 3) == 0 || + std::strncmp(szmapname, "workshop/pl_", 12) == 0 || + std::strncmp(szmapname, "kotc_", 5) == 0) + // Tug of War works fine as Payload - RussiaTails m_MapType = TF_MAP_CART; // pipeline - else if ( strncmp(szmapname,"plr_",4) == 0 ) + else if (std::strncmp(szmapname, "plr_", 4) == 0 || std::strncmp(szmapname, "tow_", 4) == 0 || + std::strncmp(szmapname, "workshop/plr_", 13) == 0 || + std::strncmp(szmapname, "workshop/tow_", 13) == 0 || + std::strncmp(szmapname, "arena_tinyrock", 14) == 0 || std::strncmp(szmapname, "tow_impasse", 11) == 0 || + std::strncmp(szmapname, "arena_hailstone", 15) == 0) // to make bots push payloads on these maps. - RussiaTails m_MapType = TF_MAP_CARTRACE; // pipeline racing - else if ( strncmp(szmapname,"arena_",6) == 0 || strncmp(szmapname,"vsh_",4) == 0 ) // pongo1321 - m_MapType = TF_MAP_ARENA; // arena mode (also fallback for VS Saxton Hale gamemode) - else if ( strncmp(szmapname,"arena_",6) == 0 ) + else if (std::strncmp(szmapname, "arena_", 6) == 0 || + std::strncmp(szmapname, "workshop/arena_", 15) == 0 || + std::strncmp(szmapname, "ft_", 3) == 0) // pongo1321 m_MapType = TF_MAP_ARENA; // arena mode - else if ( strncmp(szmapname,"koth_",5) == 0 ) + else if (std::strncmp(szmapname, "vsh_", 4) == 0 || + std::strncmp(szmapname, "ff2_", 4) == 0 || + std::strncmp(szmapname, "bvb_", 4) == 0 || + std::strncmp(szmapname, "workshop/vsh_", 13) == 0 || + std::strncmp(szmapname, "dr_", 3) == 0) + m_MapType = TF_MAP_SAXTON; // arena mode + else if (std::strncmp(szmapname, "pipeball_", 9) == 0) + m_MapType = TF_MAP_PIPEBALL; // arena mode + else if (std::strncmp(szmapname, "koth_", 5) == 0 || + std::strncmp(szmapname, "workshop/koth_", 14) == 0 || + std::strncmp(szmapname, "ctk_", 4) == 0) + // Control the Keep works almost the same as KOTH. - RussiaTails m_MapType = TF_MAP_KOTH; // king of the hill - else if ( strncmp(szmapname,"sd_",3) == 0 ) + else if (std::strncmp(szmapname, "sd_", 3) == 0 || + std::strncmp(szmapname, "workshop/sd_", 12) == 0 || + std::strncmp(szmapname, "sdr_", 4) == 0) + // Object Destruction and Special Delivery Race (I dunno why it's named like this when it works as a usual sd_) works the same as SD_. - RussiaTails m_MapType = TF_MAP_SD; // special delivery - else if ( strncmp(szmapname,"tr_",3) == 0 ) + else if (std::strncmp(szmapname, "tr_", 3) == 0) m_MapType = TF_MAP_TR; // training mode - else if ( strncmp(szmapname,"mvm_",4) == 0 ) + else if (std::strncmp(szmapname, "cppl_", 5) == 0 || + std::strncmp(szmapname, "workshop/cppl_", 14) == 0 || + std::strncmp(szmapname, "cw_", 3) == 0) // Hybrid - RussiaTails + m_MapType = TF_MAP_CPPL; // CP+PL maps + else if (std::strncmp(szmapname, "gg_", 3) == 0 || std::strncmp(szmapname, "dm_hydro", 8) == 0 || + std::strncmp(szmapname, "dm_powerdown", 12) == 0 || std::strncmp(szmapname, "dm_forgecall", 12) == 0 || + std::strncmp(szmapname, "dm_poolparty", 12) == 0 || std::strncmp(szmapname, "dm_badworks", 11) == 0 || + std::strncmp(szmapname, "dm_razorpoint", 13) == 0 || std::strncmp(szmapname, "dm_deadlock", 11) == 0) + // GunGame (and non-team deathmatch) - RussiaTails + m_MapType = TF_MAP_GG; // GunGame maps + else if (std::strncmp(szmapname, "mvm_", 4) == 0 || std::strncmp(szmapname, "gd_", 3) == 0) + // gd is MvM Guardian, for now there are only two maps exist with this prefix. - RussiaTails m_MapType = TF_MAP_MVM; // mann vs machine - else if ( strncmp(szmapname,"rd_",3) == 0 ) + else if (std::strncmp(szmapname, "rd_", 3) == 0 || + std::strncmp(szmapname, "workshop/rd_", 12) == 0 || + std::strncmp(szmapname, "rda_", 4) == 0) m_MapType = TF_MAP_RD; // robot destruction + else if (std::strncmp(szmapname, "zi_", 3) == 0 || + std::strncmp(szmapname, "workshop/zi_", 12) == 0) + m_MapType = TF_MAP_ZI; // Zombie Infection //TODO: add support for those gamemodes [APG]RoboCop[CL] else - m_MapType = TF_MAP_DM; + m_MapType = TF_MAP_DM; // deathmatch //TODO: to prevent bots from idling in their spawns by giving them basic tasks [APG]RoboCop[CL] m_iArea = 0; @@ -843,27 +355,27 @@ void CTeamFortress2Mod :: mapInit () m_fRoundTime = 0.0f; - m_pFlagCarrierRed = NULL; - m_pFlagCarrierBlue = NULL; + m_pFlagCarrierRed = nullptr; + m_pFlagCarrierBlue = nullptr; m_iFlagCarrierTeam = 0; m_bDontClearPoints = false; - for ( i = 0; i < MAX_PLAYERS; i ++ ) + for ( unsigned i = 0; i < RCBOT_MAXPLAYERS; i ++ ) { m_Teleporters[i].m_iWaypoint = -1; m_Teleporters[i].m_fLastTeleported = 0.0f; - m_Teleporters[i].entrance = MyEHandle(NULL); - m_Teleporters[i].exit = MyEHandle(NULL); - m_Teleporters[i].sapper = MyEHandle(NULL); - m_SentryGuns[i].sapper = MyEHandle(NULL); - m_SentryGuns[i].sentry = MyEHandle(NULL); - m_Dispensers[i].sapper = MyEHandle(NULL); - m_Dispensers[i].disp = MyEHandle(NULL); - pMediGuns[i] = NULL; + m_Teleporters[i].entrance = MyEHandle(nullptr); + m_Teleporters[i].exit = MyEHandle(nullptr); + m_Teleporters[i].sapper = MyEHandle(nullptr); + m_SentryGuns[i].sapper = MyEHandle(nullptr); + m_SentryGuns[i].sentry = MyEHandle(nullptr); + m_Dispensers[i].sapper = MyEHandle(nullptr); + m_Dispensers[i].disp = MyEHandle(nullptr); + pMediGuns[i] = nullptr; } m_bAttackDefendMap = false; - m_pBoss = NULL; + m_pBoss = nullptr; m_bBossSummoned = false; resetCappers(); @@ -871,14 +383,12 @@ void CTeamFortress2Mod :: mapInit () //CPoints::loadMapScript(); } -int CTeamFortress2Mod :: getTeleporterWaypoint ( edict_t *pTele ) +int CTeamFortress2Mod :: getTeleporterWaypoint (const edict_t *pTele) { - int i; - - for ( i = 0; i < MAX_PLAYERS; i ++ ) + for (tf_tele_t& m_Teleporter : m_Teleporters) { - if ( m_Teleporters[i].exit.get() == pTele ) - return m_Teleporters[i].m_iWaypoint; + if (m_Teleporter.exit.get() == pTele ) + return m_Teleporter.m_iWaypoint; } return -1; @@ -888,48 +398,48 @@ int CTeamFortress2Mod :: getTeleporterWaypoint ( edict_t *pTele ) bool CTeamFortress2Mod :: TF2_IsPlayerZoomed(edict_t *pPlayer) { - int pcond = CClassInterface :: getTF2Conditions(pPlayer); - return ((pcond & TF2_PLAYER_ZOOMED) == TF2_PLAYER_ZOOMED); + const int pcond = CClassInterface :: getTF2Conditions(pPlayer); + return (pcond & TF2_PLAYER_ZOOMED) == TF2_PLAYER_ZOOMED; } bool CTeamFortress2Mod :: TF2_IsPlayerSlowed(edict_t *pPlayer) { - int pcond = CClassInterface :: getTF2Conditions(pPlayer); - return ((pcond & TF2_PLAYER_SLOWED) == TF2_PLAYER_SLOWED); + const int pcond = CClassInterface :: getTF2Conditions(pPlayer); + return (pcond & TF2_PLAYER_SLOWED) == TF2_PLAYER_SLOWED; } bool CTeamFortress2Mod :: TF2_IsPlayerDisguised(edict_t *pPlayer) { - int pcond = CClassInterface :: getTF2Conditions(pPlayer); - return ((pcond & TF2_PLAYER_DISGUISED) == TF2_PLAYER_DISGUISED); + const int pcond = CClassInterface :: getTF2Conditions(pPlayer); + return (pcond & TF2_PLAYER_DISGUISED) == TF2_PLAYER_DISGUISED; } bool CTeamFortress2Mod :: TF2_IsPlayerTaunting ( edict_t *pPlayer ) { - int pcond = CClassInterface :: getTF2Conditions(pPlayer); - return ((pcond & TF2_PLAYER_TAUNTING) == TF2_PLAYER_TAUNTING); + const int pcond = CClassInterface :: getTF2Conditions(pPlayer); + return (pcond & TF2_PLAYER_TAUNTING) == TF2_PLAYER_TAUNTING; } bool CTeamFortress2Mod :: TF2_IsPlayerCloaked(edict_t *pPlayer) { - int pcond = CClassInterface :: getTF2Conditions(pPlayer); - return ((pcond & TF2_PLAYER_CLOAKED) == TF2_PLAYER_CLOAKED); + const int pcond = CClassInterface :: getTF2Conditions(pPlayer); + return (pcond & TF2_PLAYER_CLOAKED) == TF2_PLAYER_CLOAKED; } bool CTeamFortress2Mod :: TF2_IsPlayerKrits(edict_t *pPlayer) { - int pcond = CClassInterface :: getTF2Conditions(pPlayer); - return ((pcond & TF2_PLAYER_KRITS) == TF2_PLAYER_KRITS); + const int pcond = CClassInterface :: getTF2Conditions(pPlayer); + return (pcond & TF2_PLAYER_KRITS) == TF2_PLAYER_KRITS; - return false; + //return false; //Unreachable? [APG]RoboCop[CL] } bool CTeamFortress2Mod :: TF2_IsPlayerInvuln(edict_t *pPlayer) { if ( CBotGlobals::isPlayer(pPlayer) ) { - int pcond = CClassInterface :: getTF2Conditions(pPlayer); - return ((pcond & TF2_PLAYER_INVULN) == TF2_PLAYER_INVULN); + const int pcond = CClassInterface :: getTF2Conditions(pPlayer); + return (pcond & TF2_PLAYER_INVULN) == TF2_PLAYER_INVULN; } return false; @@ -937,19 +447,26 @@ bool CTeamFortress2Mod :: TF2_IsPlayerInvuln(edict_t *pPlayer) bool CTeamFortress2Mod :: TF2_IsPlayerOnFire(edict_t *pPlayer) { - int pcond = CClassInterface :: getTF2Conditions(pPlayer); - return ((pcond & TF2_PLAYER_ONFIRE) == TF2_PLAYER_ONFIRE); + const int pcond = CClassInterface :: getTF2Conditions(pPlayer); + return (pcond & TF2_PLAYER_ONFIRE) == TF2_PLAYER_ONFIRE; } -int CTeamFortress2Mod ::numClassOnTeam( int iTeam, int iClass ) +//TODO: Experimental [APG]RoboCop[CL] +int CTeamFortress2Mod::numPlayersOnTeam(int iTeam, bool bAliveOnly) +{ + return 0; +} + +int CTeamFortress2Mod ::numClassOnTeam(const int iTeam, const int iClass) { - int i = 0; int num = 0; - edict_t *pEdict; - for ( i = 1; i <= CBotGlobals::numClients(); i ++ ) + for ( int i = 1; i <= CBotGlobals::maxClients(); i ++ ) { - pEdict = INDEXENT(i); + edict_t* pEdict = INDEXENT(i); + + if ( !pEdict ) + continue; if ( CBotGlobals::entityIsValid(pEdict) ) { @@ -982,47 +499,42 @@ TF_Class CTeamFortress2Mod :: getSpyDisguise ( edict_t *pPlayer ) CClassInterface::getTF2SpyDisguised(pPlayer,&iClass,&iTeam,&iIndex,&iHealth); - return (TF_Class)iClass; + return static_cast(iClass); } - -float CTeamFortress2Mod :: TF2_GetClassSpeed(int iClass) +float CTeamFortress2Mod :: TF2_GetClassSpeed(const int iClass) { switch (iClass) { -case TF_CLASS_SCOUT: return 133.0f; -case TF_CLASS_SOLDIER: return 80.0f; -case TF_CLASS_DEMOMAN: return 93.00; -case TF_CLASS_MEDIC: return 109.0f; -case TF_CLASS_PYRO: return 100.0f; -case TF_CLASS_SPY: return 109.0f; -case TF_CLASS_ENGINEER: return 100.0f; -case TF_CLASS_SNIPER: return 100.0f; -case TF_CLASS_HWGUY: return 77.0f; + case TF_CLASS_SCOUT: return 133.0f; + case TF_CLASS_SOLDIER: return 80.0f; + case TF_CLASS_DEMOMAN: return 93.0f; + case TF_CLASS_MEDIC: return 109.0f; + case TF_CLASS_PYRO: return 100.0f; + case TF_CLASS_SPY: return 109.0f; + case TF_CLASS_ENGINEER: return 100.0f; + case TF_CLASS_HWGUY: return 77.0f; + case TF_CLASS_SNIPER: return 100.0f; } -return 0.0; +return 0.0f; } -float CTeamFortress2Mod :: TF2_GetPlayerSpeed(edict_t *pPlayer, TF_Class iClass ) +float CTeamFortress2Mod :: TF2_GetPlayerSpeed(edict_t *pPlayer, const TF_Class iClass) { static float fSpeed; fSpeed = CClassInterface::getMaxSpeed(pPlayer);// * CClassInterface::getSpeedFactor(pPlayer); - if ( fSpeed == 0 ) + if ( fSpeed == 0.0f ) { if (TF2_IsPlayerSlowed(pPlayer)) - return 30.0; - else - return TF2_GetClassSpeed(iClass) * 1.58; + return 30.0f; + return TF2_GetClassSpeed(iClass) * 1.58f; } return fSpeed; } - - - int CTeamFortress2Mod :: getTeam ( edict_t *pEntity ) { return CClassInterface::getTeam (pEntity); @@ -1031,28 +543,28 @@ int CTeamFortress2Mod :: getTeam ( edict_t *pEntity ) int CTeamFortress2Mod :: getSentryLevel ( edict_t *pSentry ) { - string_t model = pSentry->GetIServerEntity()->GetModelName(); + const string_t model = pSentry->GetIServerEntity()->GetModelName(); const char *szmodel = model.ToCStr(); - return (szmodel[24] - '1')+1; + return szmodel[24] - '1'+1; //if ( pSentry && pSentry-> } int CTeamFortress2Mod :: getDispenserLevel ( edict_t *pDispenser ) { - string_t model = pDispenser->GetIServerEntity()->GetModelName(); + const string_t model = pDispenser->GetIServerEntity()->GetModelName(); const char *szmodel = model.ToCStr(); - if ( strcmp(szmodel,"models/buildables/dispenser_light.mdl") == 0 ) + if ( std::strcmp(szmodel,"models/buildables/dispenser_light.mdl") == 0 ) return 1; - return (szmodel[31] - '1')+1; + return szmodel[31] - '1'+1; //if ( pSentry && pSentry-> } -int CTeamFortress2Mod :: getEnemyTeam ( int iTeam ) +int CTeamFortress2Mod :: getEnemyTeam (const int iTeam) { - return (iTeam == TF2_TEAM_BLUE)?TF2_TEAM_RED:TF2_TEAM_BLUE; + return iTeam == TF2_TEAM_BLUE?TF2_TEAM_RED:TF2_TEAM_BLUE; } /* @@ -1063,109 +575,151 @@ int CTeamFortress2Mod :: getEnemyTeam ( int iTeam ) */ -bool CTeamFortress2Mod :: isDispenser ( edict_t *pEntity, int iTeam, bool checkcarrying ) +bool CTeamFortress2Mod :: isDispenser (edict_t *pEntity, const int iTeam, const bool checkcarrying) { - return (!iTeam || (iTeam == getTeam(pEntity))) && (strcmp(pEntity->GetClassName(),"obj_dispenser")==0) && (checkcarrying||!CClassInterface::isSentryGunBeingPlaced(pEntity)); + return (!iTeam || iTeam == getTeam(pEntity)) && std::strcmp(pEntity->GetClassName(),"obj_dispenser")==0 && (checkcarrying||!CClassInterface::isSentryGunBeingPlaced(pEntity)); } -bool CTeamFortress2Mod :: isFlag ( edict_t *pEntity, int iTeam ) +bool CTeamFortress2Mod :: isFlag (edict_t *pEntity, const int iTeam) { - return (!iTeam || (getEnemyTeam(iTeam) == getTeam(pEntity))) && (strcmp(pEntity->GetClassName(),"item_teamflag")==0); + return (!iTeam || getEnemyTeam(iTeam) == getTeam(pEntity)) && std::strcmp(pEntity->GetClassName(),"item_teamflag")==0; } -bool CTeamFortress2Mod ::isBoss ( edict_t *pEntity, float *fFactor ) +/*bool CTeamFortress2Mod::isBall(edict_t* pEntity, const int iTeam) +{ + return (!iTeam || getEnemyTeam(iTeam) == getTeam(pEntity)) && std::strcmp(pEntity->GetClassName(), "passtime_ball") == 0; +}*/ + +bool CTeamFortress2Mod::isBoss(edict_t* pEntity, float* fFactor) { - if ( m_bBossSummoned ) + const string_t mapname = gpGlobals->mapname; + + const char* szmapname = mapname.ToCStr(); + + if (m_bBossSummoned) { - if ( m_pBoss.get() && CBotGlobals::entityIsAlive(m_pBoss.get()) ) + if (m_pBoss.get() && CBotGlobals::entityIsAlive(m_pBoss.get())) return m_pBoss.get() == pEntity; - else if ( (strcmp(pEntity->GetClassName(),"merasmus")==0)|| - (strcmp(pEntity->GetClassName(),"headless_hatman")==0)|| - (strcmp(pEntity->GetClassName(),"eyeball_boss")==0)|| - (strcmp(pEntity->GetClassName(),"tf_zombie")==0) ) + if (std::strcmp(pEntity->GetClassName(), "merasmus") == 0 || + std::strcmp(pEntity->GetClassName(), "headless_hatman") == 0 || + std::strcmp(pEntity->GetClassName(), "eyeball_boss") == 0 || + std::strcmp(pEntity->GetClassName(), "tf_merasmus_trick_or_treat_prop") == 0 || + std::strcmp(pEntity->GetClassName(), "base_boss") == 0) // For Krampus and any other NPCs which uses base_boss entity - RussiaTails { m_pBoss = pEntity; return true; } + if (std::strcmp(pEntity->GetClassName(), "tf_merasmus_trick_or_treat_prop") == 0 && CBotGlobals::entityIsAlive(m_pBoss.get())) + return (std::strcmp(pEntity->GetClassName(), "merasmus") != 0); } - else if ( CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE) ) + else if (CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE) || isMapType(TF_MAP_CART) || isMapType(TF_MAP_CTF) || isMapType(TF_MAP_KOTH) || + isMapType(TF_MAP_CP) || isMapType(TF_MAP_PD) || isMapType(TF_MAP_ARENA) || isMapType(TF_MAP_SAXTON) || isMapType(TF_MAP_SD) || isMapType(TF_MAP_DM)) { - if ( m_pBoss.get() == pEntity ) + if (m_pBoss.get() == pEntity) + return true; + if (std::strcmp(pEntity->GetClassName(), "base_boss") == 0 || // For Krampus and any other NPCs which uses base_boss entity - RussiaTails + std::strcmp(pEntity->GetClassName(), "tf_robot_botler") == 0 || // Botler Robots from Embargo entity - RussiaTails + std::strcmp(pEntity->GetClassName(), "prop_soccer_ball") == 0) + { + m_pBoss = pEntity; return true; - // for plr_hightower_event summon event is not called! Boo tf2!!! - else if (strcmp(pEntity->GetClassName(),"tf_zombie")==0) + } + if (isTankBoss(pEntity)) { + /*if (fFactor != nullptr) + *fFactor = -200.0f;*/ m_pBoss = pEntity; return true; } + } - else if ( CTeamFortress2Mod::isMapType(TF_MAP_MVM) ) + else if (CTeamFortress2Mod::isMapType(TF_MAP_PIPEBALL)) { - if ( m_pBoss.get() == pEntity ) + if (m_pBoss.get() == pEntity) return true; - else if (isTankBoss(pEntity)) + if (std::strcmp(pEntity->GetClassName(), "func_physbox") == 0 || + std::strcmp(pEntity->GetClassName(), "base_boss") == 0) + { + m_pBoss = pEntity; + return true; + } + if (isTankBoss(pEntity)) { - if (fFactor != NULL) + if (fFactor != nullptr) *fFactor = 200.0f; m_pBoss = pEntity; return true; } + + } + else if (CTeamFortress2Mod::isMapType(TF_MAP_MVM)) + { + if (m_pBoss.get() == pEntity) + return true; + if (isTankBoss(pEntity)) /* && CClassInterface::getTeam(pEntity) != iTeam)*/ + { + /*if (fFactor != nullptr) + *fFactor = -200.0f;*/ + + m_pBoss = pEntity; + return true; + } } return false; } -void CTeamFortress2Mod :: updateTeleportTime ( edict_t *pOwner ) +void CTeamFortress2Mod :: updateTeleportTime (const edict_t* pOwner) { m_Teleporters[ENTINDEX(pOwner)-1].m_fLastTeleported = engine->Time(); } -float CTeamFortress2Mod :: getTeleportTime ( edict_t *pOwner ) +float CTeamFortress2Mod :: getTeleportTime (const edict_t* pOwner) { return m_Teleporters[ENTINDEX(pOwner)-1].m_fLastTeleported; } -bool CTeamFortress2Mod :: isSentry ( edict_t *pEntity, int iTeam, bool checkcarrying ) +bool CTeamFortress2Mod :: isSentry (edict_t *pEntity, const int iTeam, const bool checkcarrying) { - return (!iTeam || (iTeam == getTeam(pEntity))) && (strcmp(pEntity->GetClassName(),"obj_sentrygun")==0) && (checkcarrying||!CClassInterface::isSentryGunBeingPlaced(pEntity)); + return (!iTeam || iTeam == getTeam(pEntity)) && std::strcmp(pEntity->GetClassName(),"obj_sentrygun")==0 && (checkcarrying||!CClassInterface::isSentryGunBeingPlaced(pEntity)); } -bool CTeamFortress2Mod::isTankBoss(edict_t *pEntity) +bool CTeamFortress2Mod::isTankBoss(const edict_t* pEntity) { - return (strcmp(pEntity->GetClassName(), "tank_boss") == 0); + return std::strcmp(pEntity->GetClassName(), "tank_boss") == 0; } -bool CTeamFortress2Mod :: isTeleporter ( edict_t *pEntity, int iTeam, bool checkcarrying ) +bool CTeamFortress2Mod :: isTeleporter (edict_t *pEntity, const int iTeam, const bool checkcarrying) { - return (!iTeam || (iTeam == getTeam(pEntity))) && (strcmp(pEntity->GetClassName(),"obj_teleporter")==0) && (checkcarrying||!CClassInterface::isSentryGunBeingPlaced(pEntity)); + return (!iTeam || iTeam == getTeam(pEntity)) && std::strcmp(pEntity->GetClassName(),"obj_teleporter")==0 && (checkcarrying||!CClassInterface::isSentryGunBeingPlaced(pEntity)); } -bool CTeamFortress2Mod :: isTeleporterEntrance ( edict_t *pEntity, int iTeam, bool checkcarrying ) +bool CTeamFortress2Mod :: isTeleporterEntrance (edict_t *pEntity, const int iTeam, const bool checkcarrying) { return isTeleporter(pEntity,iTeam) && CClassInterface::isTeleporterMode(pEntity,TELE_ENTRANCE) && (checkcarrying||!CClassInterface::isSentryGunBeingPlaced(pEntity)); } -bool CTeamFortress2Mod :: isTeleporterExit ( edict_t *pEntity, int iTeam, bool checkcarrying ) +bool CTeamFortress2Mod :: isTeleporterExit (edict_t *pEntity, const int iTeam, const bool checkcarrying) { return isTeleporter(pEntity,iTeam) && CClassInterface::isTeleporterMode(pEntity,TELE_EXIT) && (checkcarrying||!CClassInterface::isSentryGunBeingPlaced(pEntity)); } -bool CTeamFortress2Mod :: isPipeBomb ( edict_t *pEntity, int iTeam) +bool CTeamFortress2Mod :: isPipeBomb (edict_t *pEntity, const int iTeam) { - return (!iTeam || (iTeam == getTeam(pEntity))) && (strcmp(pEntity->GetClassName(),"tf_projectile_pipe_remote")==0); + return (!iTeam || iTeam == getTeam(pEntity)) && std::strcmp(pEntity->GetClassName(),"tf_projectile_pipe_remote")==0; } -bool CTeamFortress2Mod :: isHurtfulPipeGrenade ( edict_t *pEntity, edict_t *pPlayer, bool bCheckOwner ) +bool CTeamFortress2Mod :: isHurtfulPipeGrenade (edict_t *pEntity, edict_t *pPlayer, const bool bCheckOwner) { - if ( strcmp(pEntity->GetClassName(),"tf_projectile_pipe")==0 ) + if ( std::strcmp(pEntity->GetClassName(),"tf_projectile_pipe")==0 ) { - if ( bCheckOwner && (CClassInterface::getPipeBombOwner(pEntity) == pPlayer) ) + if ( bCheckOwner && CClassInterface::getPipeBombOwner(pEntity) == pPlayer ) return true; - int iPlayerTeam = getTeam(pPlayer); - int iGrenTeam = getTeam(pEntity); + const int iPlayerTeam = getTeam(pPlayer); + const int iGrenTeam = getTeam(pEntity); return iPlayerTeam != iGrenTeam; } @@ -1173,16 +727,16 @@ bool CTeamFortress2Mod :: isHurtfulPipeGrenade ( edict_t *pEntity, edict_t *pPla return false; } -bool CTeamFortress2Mod :: isRocket ( edict_t *pEntity, int iTeam ) +bool CTeamFortress2Mod :: isRocket (edict_t *pEntity, const int iTeam) { - return (!iTeam || (iTeam == getTeam(pEntity))) && (strcmp(pEntity->GetClassName(),"tf_projectile_rocket")==0); + return (!iTeam || iTeam == getTeam(pEntity)) && std::strcmp(pEntity->GetClassName(),"tf_projectile_rocket")==0; } edict_t *CTeamFortress2Mod:: getMediGun ( edict_t *pPlayer ) { if ( CClassInterface::getTF2Class(pPlayer) == TF_CLASS_MEDIC ) return pMediGuns[ENTINDEX(pPlayer)-1]; - return NULL; + return nullptr; } void CTeamFortress2Mod :: findMediGun ( edict_t *pPlayer ) @@ -1193,13 +747,13 @@ void CTeamFortress2Mod :: findMediGun ( edict_t *pPlayer ) vOrigin = CBotGlobals::entityOrigin(pPlayer); - for ( i = (gpGlobals->maxClients+1); i < gpGlobals->maxEntities; i ++ ) + for ( i = gpGlobals->maxClients+1; i < gpGlobals->maxEntities; i ++ ) { pEnt = INDEXENT(i); if ( pEnt && CBotGlobals::entityIsValid(pEnt) ) { - if ( strcmp(pEnt->GetClassName(),"tf_weapon_medigun") == 0 ) + if ( std::strcmp(pEnt->GetClassName(),"tf_weapon_medigun") == 0 ) { if ( CBotGlobals::entityOrigin(pEnt) == vOrigin ) { @@ -1212,64 +766,66 @@ void CTeamFortress2Mod :: findMediGun ( edict_t *pPlayer ) } // get the teleporter exit of an entrance -edict_t *CTeamFortress2Mod :: getTeleporterExit ( edict_t *pTele ) +edict_t *CTeamFortress2Mod :: getTeleporterExit (const edict_t *pTele) { - int i; edict_t *pExit; - for ( i = 0; i < MAX_PLAYERS; i ++ ) + for (tf_tele_t& m_Teleporter : m_Teleporters) { - if ( m_Teleporters[i].entrance.get() == pTele ) + if (m_Teleporter.entrance.get() == pTele ) { - if ( (pExit = m_Teleporters[i].exit.get()) != NULL ) + if ( (pExit = m_Teleporter.exit.get()) != nullptr) { return pExit; } - return false; + return nullptr; } } - return false; + return nullptr; } // check if the entity is a health kit -bool CTeamFortress2Mod :: isHealthKit ( edict_t *pEntity ) +bool CTeamFortress2Mod :: isHealthKit (const edict_t* pEntity) { - return strncmp(pEntity->GetClassName(),"item_healthkit",14)==0; + if (CTeamFortress2Mod::isMapType(TF_MAP_SAXTON) || isMapType(TF_MAP_ZI)) + { + return false; + } + return std::strncmp(pEntity->GetClassName(),"item_healthkit",14)==0; } -bool CTeamFortress2Mod :: isAreaOwnedByTeam (int iArea, int iTeam) +bool CTeamFortress2Mod :: isAreaOwnedByTeam (const int iArea, const int iTeam) { if ( CTeamFortress2Mod::m_ObjectiveResource.isInitialised() ) { - return ((iArea==0) || (CTeamFortress2Mod::m_ObjectiveResource.GetOwningTeam(CTeamFortress2Mod::m_ObjectiveResource.m_WaypointAreaToIndexTranslation[iArea])==iTeam) ); + return iArea==0 || CTeamFortress2Mod::m_ObjectiveResource.GetOwningTeam(CTeamFortress2Mod::m_ObjectiveResource.m_WaypointAreaToIndexTranslation[iArea])==iTeam; } return false; } // cehc kif the team can pick up a flag in SD mode (special delivery) -bool CTeamFortress2Mod::canTeamPickupFlag_SD(int iTeam,bool bGetUnknown) +bool CTeamFortress2Mod::canTeamPickupFlag_SD(const int iTeam, const bool bGetUnknown) { if ( isArenaPointOpen() ) { if ( bGetUnknown ) - return (m_iFlagCarrierTeam==iTeam); - else - return (m_iFlagCarrierTeam==0); + return m_iFlagCarrierTeam==iTeam; + return m_iFlagCarrierTeam==0; } return false; } // For MVM only -bool CTeamFortress2Mod::getFlagLocation ( int iTeam, Vector *vec ) +bool CTeamFortress2Mod::getFlagLocation (const int iTeam, Vector *vec) { if ( getDroppedFlagLocation(iTeam,vec) ) { return true; } - else if ( hasRoundStarted() && isFlagCarried(iTeam) ) + if ( hasRoundStarted() && isFlagCarried(iTeam) ) { *vec = CBotGlobals::entityOrigin(getFlagCarrier(iTeam)); return true; @@ -1279,7 +835,7 @@ bool CTeamFortress2Mod::getFlagLocation ( int iTeam, Vector *vec ) } // for special delivery mod and MVM -void CTeamFortress2Mod::flagReturned(int iTeam) +void CTeamFortress2Mod::flagReturned(const int iTeam) { m_iFlagCarrierTeam = 0; bFlagStateDefault = true; @@ -1294,7 +850,7 @@ void CTeamFortress2Mod::flagReturned(int iTeam) } } -void CTeamFortress2Mod:: flagPickedUp (int iTeam, edict_t *pPlayer) +void CTeamFortress2Mod:: flagPickedUp (const int iTeam, edict_t *pPlayer) { bFlagStateDefault = false; if ( iTeam == TF2_TEAM_BLUE ) @@ -1310,11 +866,8 @@ void CTeamFortress2Mod:: flagPickedUp (int iTeam, edict_t *pPlayer) m_iFlagCarrierTeam = iTeam; - CBotTF2FunctionEnemyAtIntel *function = new CBotTF2FunctionEnemyAtIntel(iTeam,CBotGlobals::entityOrigin(pPlayer),EVENT_FLAG_PICKUP); - - CBots::botFunction(function); - - delete function; + CBotTF2FunctionEnemyAtIntel func(iTeam, CBotGlobals::entityOrigin(pPlayer), EVENT_FLAG_PICKUP); + CBots::botFunction(&func); } bool CTeamFortress2Mod :: isArenaPointOpen () @@ -1328,54 +881,141 @@ void CTeamFortress2Mod :: resetSetupTime () m_fArenaPointOpenTime = engine->Time() + m_fPointTime; } -bool CTeamFortress2Mod::hasRoundStarted () +bool CTeamFortress2Mod::hasRoundStarted() { - return m_bHasRoundStarted || (!isMapType(TF_MAP_MVM)&&(engine->Time() > m_fRoundTime)); + return m_bHasRoundStarted || (!isMapType(TF_MAP_MVM) && engine->Time() > m_fRoundTime); //return (engine->Time() > m_fRoundTime); } -void CTeamFortress2Mod :: setPointOpenTime ( int time ) +void CTeamFortress2Mod :: setPointOpenTime (const int time) { m_fArenaPointOpenTime = 0.0f; - m_fPointTime = (float)time; + m_fPointTime = static_cast(time); } -void CTeamFortress2Mod :: setSetupTime ( int time ) +void CTeamFortress2Mod :: setSetupTime (const int time) { m_fRoundTime = 0.0f; - m_fSetupTime = (float)time; + m_fSetupTime = static_cast(time); } -bool CTeamFortress2Mod :: isAmmo ( edict_t *pEntity ) +bool CTeamFortress2Mod :: isAmmo (const edict_t* pEntity) { static const char *szClassname; szClassname = pEntity->GetClassName(); - return (strcmp(szClassname,"tf_ammo_pack")==0) || (strncmp(szClassname,"item_ammopack",13)==0); + return std::strcmp(szClassname,"tf_ammo_pack") == 0 || std::strncmp(szClassname,"item_ammopack",13) == 0; } -bool CTeamFortress2Mod :: isPayloadBomb ( edict_t *pEntity, int iTeam ) +//TODO: Experimental [APG]RoboCop[CL] +int CTeamFortress2Mod::getArea() { - return ((strncmp(pEntity->GetClassName(),"mapobj_cart_dispenser",21)==0) && (CClassInterface::getTeam(pEntity)==iTeam)); + return 0; } +bool CTeamFortress2Mod::isPayloadBomb(edict_t* pEdict, int iTeam) +{ + const string_t mapname = gpGlobals->mapname; + + const char* szmapname = mapname.ToCStr(); + + const string_t model = pEdict->GetIServerEntity()->GetModelName(); + + if (std::strncmp(szmapname, "pl_embargo", 10) == 0 && engine->IndexOfEdict(pEdict) >= 400) // Make bots focus on payload only - RussiaTails + { + return std::strncmp(pEdict->GetClassName(), "mapobj_cart_dispenser", 21) == 0 && CClassInterface::getTeam(pEdict) == iTeam; + } + if (std::strncmp(szmapname, "pl_aquarius", 11) == 0 && engine->IndexOfEdict(pEdict) <= 100) // Make bots focus on payload only - RussiaTails + { + return std::strncmp(pEdict->GetClassName(), "mapobj_cart_dispenser", 21) == 0 && CClassInterface::getTeam(pEdict) == iTeam; + } + if (std::strncmp(szmapname, "plr_cutter", 10) == 0) + { + if ((engine->IndexOfEdict(pEdict) >= 400) && (CClassInterface::getTeam(pEdict) == TF2_TEAM_RED)) + { + return std::strncmp(pEdict->GetClassName(), "mapobj_cart_dispenser", 21) == 0; + } + if ((engine->IndexOfEdict(pEdict) >= 400) && (CClassInterface::getTeam(pEdict) == TF2_TEAM_BLUE)) + { + return std::strncmp(pEdict->GetClassName(), "mapobj_cart_dispenser", 21) == 0; + } + return false; + } + if (std::strncmp(szmapname, "plr_matterhorn", 14) == 0) + { + if (engine->IndexOfEdict(pEdict) >= 310) + { + return std::strncmp(pEdict->GetClassName(), "mapobj_cart_dispenser", 21) == 0 && CClassInterface::getTeam(pEdict) == iTeam; + } + return false; + } + if ((std::strncmp(szmapname, "tow_", 4) == 0 || std::strncmp(szmapname, "kotc_", 5) == 0) && std::strncmp(szmapname, "tow_impasse", 11) != 0) + { + return std::strncmp(pEdict->GetClassName(), "mapobj_cart_dispenser", 21) == 0; + } + if (std::strncmp(szmapname, "sd_offload", 10) == 0) + { + return (std::strncmp(pEdict->GetClassName(), "prop_dynamic", 12) == 0) && std::strcmp(model.ToCStr(), "models/props_doomsday/cap_point_small.mdl") == 0; + } + if (std::strncmp(szmapname, "ctf_system", sizeof("ctf_system") - 1) == 0) + { + return std::strncmp(pEdict->GetClassName(), "item_teamflag", sizeof("item_teamflag") - 1) == 0 + && CClassInterface::getTeam(pEdict) == iTeam; + } + if (CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE) || + CTeamFortress2Mod::isMapType(TF_MAP_CPPL) || + (CTeamFortress2Mod::isMapType(TF_MAP_CART) && + !(std::strncmp(szmapname, "plr_cutter", 10) == 0 || + std::strncmp(szmapname, "plr_matterhorn", 14) == 0 || + std::strncmp(szmapname, "pl_embargo", 10) == 0 || + std::strncmp(szmapname, "pl_aquarius", 11) == 0 || + std::strncmp(szmapname, "sd_offload", 10) == 0 || + std::strncmp(szmapname, "ctf_system", 10) == 0 || + std::strncmp(szmapname, "tow_", 4) == 0))) + { + return std::strncmp(pEdict->GetClassName(), "mapobj_cart_dispenser", 21) == 0 && CClassInterface::getTeam(pEdict) == iTeam; + } + if (std::strncmp(szmapname, "tow_impasse", 11) == 0) + { + return std::strncmp(pEdict->GetClassName(), "mapobj_cart_dispenser", 21) == 0 && CClassInterface::getTeam(pEdict) == iTeam; + } + /*else if (std::strncmp(szmapname, "tow_impasse", 11) == 0) + { + if ((engine->IndexOfEdict(pEdict) > 250) && (CClassInterface::getTeam(pEdict) == TF2_TEAM_RED)) + { + return std::strncmp(pEdict->GetClassName(), "trigger_capture_area", 21) == 0 && CBotGlobals::entityOrigin(pEdict);; + } + if ((engine->IndexOfEdict(pEdict) < 250) && (CClassInterface::getTeam(pEdict) == TF2_TEAM_BLUE)) + { + return std::strncmp(pEdict->GetClassName(), "trigger_capture_area", 21) == 0 && CBotGlobals::entityOrigin(pEdict);; + } + return false; + }*/ + /*else if (std::strncmp(szmapname, "tow_impasse", 4) == 0) + { + return std::strncmp(pEdict->GetClassName(), "trigger_capture_area", 20) == 0 && (CBaseEntityOutput::m_OnCapTeam1(pEdict) == iTeam || CBaseEntityOutput::m_OnCapTeam2(pEdict) == iTeam); + }*/ + return false; +} + + void CTeamFortress2Mod::checkMVMTankBoss(edict_t *pEntity) { - float fTankDistance = CBotGlobals::entityOrigin(pEntity).DistTo(m_vMVMCapturePoint); + const float fTankDistance = CBotGlobals::entityOrigin(pEntity).DistTo(m_vMVMCapturePoint); - if (m_pNearestTankBoss.get() != NULL) + if (m_pNearestTankBoss.get() != nullptr) { if (!CBotGlobals::entityIsAlive(m_pNearestTankBoss)) { - m_pNearestTankBoss = NULL; + m_pNearestTankBoss = nullptr; m_fNearestTankDistance = 0.0f; } } - if (CBotGlobals::entityIsAlive(pEntity) && ((m_pNearestTankBoss.get() == NULL) || ((m_fNearestTankDistance == 0.0f) || (fTankDistance < m_fNearestTankDistance)))) + if (CBotGlobals::entityIsAlive(pEntity) && (m_pNearestTankBoss.get() == nullptr || (m_fNearestTankDistance == 0.0f || fTankDistance < m_fNearestTankDistance))) { m_fNearestTankDistance = fTankDistance; m_pNearestTankBoss = pEntity; @@ -1383,57 +1023,53 @@ void CTeamFortress2Mod::checkMVMTankBoss(edict_t *pEntity) } } - -CWaypoint *CTeamFortress2Mod :: getBestWaypointMVM ( CBot *pBot, int iFlags ) +CWaypoint *CTeamFortress2Mod :: getBestWaypointMVM (const CBot *pBot, const int iFlags) { Vector vFlagLocation; - bool bFlagLocationValid = CTeamFortress2Mod::getFlagLocation(TF2_TEAM_BLUE,&vFlagLocation); - + const bool bFlagLocationValid = CTeamFortress2Mod::getFlagLocation(TF2_TEAM_BLUE,&vFlagLocation); - float fTankDistance = 0.0f; + float fTankDistance = 0.0f; //never used? [APG]RoboCop[CL] edict_t *pTank; // check tank boss is valid - if ((pTank = m_pNearestTankBoss.get()) != NULL) + if ((pTank = m_pNearestTankBoss.get()) != nullptr) { if (CBotGlobals::entityIsAlive(pTank) == false) - m_pNearestTankBoss = NULL; + m_pNearestTankBoss = nullptr; } - - + if ( hasRoundStarted() && m_bMVMFlagStartValid && m_bMVMCapturePointValid && bFlagLocationValid ) { if ( m_bMVMAlarmSounded ) return CWaypoints::randomWaypointGoalNearestArea(iFlags,TF2_TEAM_RED,0,false,pBot,true,&m_vMVMCapturePoint,-1,true,m_iCapturePointWptID); - else if ((m_pNearestTankBoss.get() != NULL) && (m_fNearestTankDistance < vFlagLocation.DistTo(m_vMVMCapturePoint))) + if (m_pNearestTankBoss.get() != nullptr && m_fNearestTankDistance < vFlagLocation.DistTo(m_vMVMCapturePoint)) return CWaypoints::randomWaypointGoalBetweenArea(iFlags, TF2_TEAM_RED, 0, false, pBot, true, &m_vNearestTankLocation, &m_vMVMCapturePoint, true, -1, m_iCapturePointWptID); - else if ( ((m_vMVMFlagStart-vFlagLocation).Length()<1024.0f) ) + if ( (m_vMVMFlagStart-vFlagLocation).Length()<1024.0f ) return CWaypoints::randomWaypointGoalNearestArea(iFlags,TF2_TEAM_RED,0,false,pBot,true,&vFlagLocation,-1,true); - else - return CWaypoints::randomWaypointGoalBetweenArea(iFlags,TF2_TEAM_RED,0,false,pBot,true,&vFlagLocation,&m_vMVMCapturePoint,true,-1,m_iCapturePointWptID); + return CWaypoints::randomWaypointGoalBetweenArea(iFlags,TF2_TEAM_RED,0,false,pBot,true,&vFlagLocation,&m_vMVMCapturePoint,true,-1,m_iCapturePointWptID); } - else if ( bFlagLocationValid ) + if ( bFlagLocationValid ) { return CWaypoints::randomWaypointGoalNearestArea(iFlags,TF2_TEAM_RED,0,false,pBot,true,&vFlagLocation,-1,true,m_iFlagPointWptID); } - return NULL; + return nullptr; } // check voice commands -void CTeamFortress2Mod:: clientCommand ( edict_t *pEntity, int argc, const char *pcmd, const char *arg1, const char *arg2 ) +void CTeamFortress2Mod:: clientCommand ( edict_t *pEntity, const int argc, const char *pcmd, const char *arg1, const char *arg2 ) { if ( argc > 2 ) { - if ( strcmp(pcmd,"voicemenu") == 0 ) + if ( std::strcmp(pcmd,"voicemenu") == 0 ) { // somebody said a voice command u_VOICECMD vcmd; vcmd.voicecmd = 0; - vcmd.b1.v1 = atoi(arg1); - vcmd.b1.v2 = atoi(arg2); + vcmd.b1.v1 = std::atoi(arg1); + vcmd.b1.v2 = std::atoi(arg2); CBroadcastVoiceCommand voicecmd = CBroadcastVoiceCommand(pEntity,vcmd.voicecmd); @@ -1442,7 +1078,7 @@ void CTeamFortress2Mod:: clientCommand ( edict_t *pEntity, int argc, const char } else { - /*if ( strcmp(pcmd,"+use_action_slot_item") == 0 ) + /*if ( std::strcmp(pcmd,"+use_action_slot_item") == 0 ) { CClient *pClient = CClients::get(pEntity); @@ -1455,19 +1091,17 @@ void CTeamFortress2Mod:: clientCommand ( edict_t *pEntity, int argc, const char } // to fixed -void CTeamFortress2Mod :: teleporterBuilt ( edict_t *pOwner, eEngiBuild type, edict_t *pBuilding ) +void CTeamFortress2Mod :: teleporterBuilt ( edict_t *pOwner, const eEngiBuild type, edict_t *pBuilding ) { - int team; - - if ( (type != ENGI_TELE ) ) //(type != ENGI_ENTRANCE) && (type != ENGI_EXIT) ) + if ( type != ENGI_TELE ) //(type != ENGI_ENTRANCE) && (type != ENGI_EXIT) ) return; - short int iIndex = ENTINDEX(pOwner)-1; + const int iIndex = ENTINDEX(pOwner) - 1; - if ( (iIndex < 0) || (iIndex > gpGlobals->maxClients) ) + if ( iIndex < 0 || iIndex > gpGlobals->maxClients ) return; - team = getTeam(pOwner); + const int team = getTeam(pOwner); if ( CTeamFortress2Mod::isTeleporterEntrance(pBuilding,team) ) m_Teleporters[iIndex].entrance = MyEHandle(pBuilding); @@ -1478,26 +1112,21 @@ void CTeamFortress2Mod :: teleporterBuilt ( edict_t *pOwner, eEngiBuild type, ed m_Teleporters[iIndex].m_fLastTeleported = 0.0f; m_Teleporters[iIndex].m_iWaypoint = CWaypointLocations::NearestWaypoint(CBotGlobals::entityOrigin(pBuilding),400.0f,-1,true); } + // used for changing class if I'm doing badly in my team int CTeamFortress2Mod ::getHighestScore () { short int highest = 0; - short int score; - short int i = 0; - edict_t *edict; - for ( i = 1; i <= gpGlobals->maxClients; i ++ ) + for ( int i = 1; i <= gpGlobals->maxClients; i ++ ) { - edict = INDEXENT(i); + edict_t* edict = INDEXENT(i); if ( edict && CBotGlobals::entityIsValid(edict) ) { - score = (short int)CClassInterface::getTF2Score(edict); - - if ( score > highest ) - { - highest = score; - } + const short score = static_cast(CClassInterface::getTF2Score(edict)); + + highest = std::max(score, highest); } } @@ -1506,26 +1135,26 @@ int CTeamFortress2Mod ::getHighestScore () // check if there is another building near where I want to build // check quickly by using the storage of sentryguns etc in the mod class -bool CTeamFortress2Mod::buildingNearby ( int iTeam, Vector vOrigin ) +bool CTeamFortress2Mod::buildingNearby(const int iTeam, const Vector& vOrigin) { - edict_t *pPlayer; - short int i; - short int sentryIndex; - - for ( i = 1; i <= gpGlobals->maxClients; i ++ ) + for (int i = 1; i <= gpGlobals->maxClients; i++) { - pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(i); // crash bug fix - if ( !pPlayer || pPlayer->IsFree() ) + if (!pPlayer || pPlayer->IsFree()) + continue; + + // check if the player is valid [APG]RoboCop[CL] + if (!playerinfomanager->GetPlayerInfo(pPlayer)) continue; - sentryIndex = i - 1; + const short sentryIndex = static_cast(i - 1); - if ( CClassInterface::getTF2Class(pPlayer) != TF_CLASS_ENGINEER ) + if (CClassInterface::getTF2Class(pPlayer) != TF_CLASS_ENGINEER) continue; - if ( CClassInterface::getTeam(pPlayer) != iTeam ) + if (CClassInterface::getTeam(pPlayer) != iTeam) continue; if (m_SentryGuns[sentryIndex].sentry.get()) @@ -1542,13 +1171,13 @@ bool CTeamFortress2Mod::buildingNearby ( int iTeam, Vector vOrigin ) if (m_Teleporters[sentryIndex].entrance.get()) { - if ( (vOrigin-CBotGlobals::entityOrigin(m_Teleporters[sentryIndex].entrance.get())).Length() < 100 ) + if ((vOrigin - CBotGlobals::entityOrigin(m_Teleporters[sentryIndex].entrance.get())).Length() < 100) return true; } if (m_Teleporters[sentryIndex].exit.get()) { - if ( (vOrigin-CBotGlobals::entityOrigin(m_Teleporters[sentryIndex].exit.get())).Length() < 100 ) + if ((vOrigin - CBotGlobals::entityOrigin(m_Teleporters[sentryIndex].exit.get())).Length() < 100) return true; } @@ -1558,17 +1187,17 @@ bool CTeamFortress2Mod::buildingNearby ( int iTeam, Vector vOrigin ) } //get the building -edict_t *CTeamFortress2Mod::getBuilding (eEngiBuild object, edict_t *pOwner) +edict_t *CTeamFortress2Mod::getBuilding (const eEngiBuild object, const edict_t* pOwner) { - static short int i; - static tf_tele_t *tele; + static int i; + static tf_tele_t *tele; //tele not used [APG]RoboCop[CL] //index = ENTINDEX(pOwner)-1; // i is 1 to 32 ( 0 == worldspawn) i = ENTINDEX(pOwner) - 1; if (i < 0) - return NULL; + return nullptr; //i = ENTINDEX(pOwner)+1; @@ -1579,74 +1208,84 @@ edict_t *CTeamFortress2Mod::getBuilding (eEngiBuild object, edict_t *pOwner) case ENGI_SENTRY: return m_SentryGuns[i].sentry.get(); case ENGI_TELE: - if ( m_Teleporters[i].entrance.get() != NULL ) + if ( m_Teleporters[i].entrance.get() != nullptr) return m_Teleporters[i].entrance.get(); return m_Teleporters[i].exit.get(); + //TODO: Added support for Sapper and Teleporter? [APG]RoboCop[CL] + /*case ENGI_SAPPER: + break; + case ENGI_EXIT: + break; + case ENGI_ENTRANCE: + break;*/ + default: ; } - return NULL; + return nullptr; } // get the owner of -edict_t *CTeamFortress2Mod ::getBuildingOwner (eEngiBuild object, short index) +edict_t *CTeamFortress2Mod ::getBuildingOwner (const eEngiBuild object, const short index) { - static short int i; - static tf_tele_t *tele; - switch ( object ) { + static short int i; + static tf_tele_t *tele; case ENGI_DISP: - for ( i = 0; i < MAX_PLAYERS; i ++ ) + for ( i = 0; i < RCBOT_MAXPLAYERS; i ++ ) { - if ( m_Dispensers[i].disp.get() && (ENTINDEX(m_Dispensers[i].disp.get())==index) ) + if ( m_Dispensers[i].disp.get() && ENTINDEX(m_Dispensers[i].disp.get())==index ) return INDEXENT(i+1); } //m_SentryGuns[i]. break; case ENGI_SENTRY: - for ( i = 0; i < MAX_PLAYERS; i ++ ) + for ( i = 0; i < RCBOT_MAXPLAYERS; i ++ ) { - if ( m_SentryGuns[i].sentry.get() && (ENTINDEX(m_SentryGuns[i].sentry.get())==index) ) + if ( m_SentryGuns[i].sentry.get() && ENTINDEX(m_SentryGuns[i].sentry.get())==index ) return INDEXENT(i+1); } break; case ENGI_TELE: tele = m_Teleporters; - for ( i = 0; i < MAX_PLAYERS; i ++ ) + for ( i = 0; i < RCBOT_MAXPLAYERS; i ++ ) { - if ( tele->entrance.get() && (ENTINDEX(tele->entrance.get())==index) ) + if ( tele->entrance.get() && ENTINDEX(tele->entrance.get())==index ) return INDEXENT(i+1); - if ( tele->exit.get() && (ENTINDEX(tele->exit.get())==index) ) + if ( tele->exit.get() && ENTINDEX(tele->exit.get())==index ) return INDEXENT(i+1); tele++; } break; + //TODO: Added support for Sapper and Teleporter? [APG]RoboCop[CL] + /*case ENGI_SAPPER: + break; + case ENGI_EXIT: + break; + case ENGI_ENTRANCE: + break;*/ + default: ; } - return NULL; + return nullptr; } -edict_t *CTeamFortress2Mod :: nearestDispenser ( Vector vOrigin, int team ) +edict_t *CTeamFortress2Mod :: nearestDispenser (const Vector& vOrigin, const int team) { - edict_t *pNearest = NULL; - edict_t *pDisp; - float fDist; + edict_t *pNearest = nullptr; float fNearest = bot_use_disp_dist.GetFloat(); - for ( unsigned int i = 0; i < MAX_PLAYERS; i ++ ) + for (tf_disp_t& m_Dispenser : m_Dispensers) { //m_Dispensers[i] - pDisp = m_Dispensers[i].disp.get(); - if ( pDisp ) + if ( edict_t* pDisp = m_Dispenser.disp.get() ) { - if ( CTeamFortress2Mod::getTeam(pDisp) == team ) + if ( getTeam(pDisp) == team ) { - fDist = (CBotGlobals::entityOrigin(pDisp) - vOrigin).Length(); - - if ( fDist < fNearest ) + if (const float fDist = (CBotGlobals::entityOrigin(pDisp) - vOrigin).Length(); fDist < fNearest ) { pNearest = pDisp; fNearest = fDist; @@ -1658,13 +1297,13 @@ edict_t *CTeamFortress2Mod :: nearestDispenser ( Vector vOrigin, int team ) return pNearest; } -void CTeamFortress2Mod::sapperPlaced(edict_t *pOwner,eEngiBuild type,edict_t *pSapper) +void CTeamFortress2Mod::sapperPlaced(const edict_t* pOwner, const eEngiBuild type, edict_t* pSapper) { - static short int index; + static int index; - index = ENTINDEX(pOwner)-1; + index = ENTINDEX(pOwner) - 1; - if ( (index>=0) && (index= 0 && index < RCBOT_MAXPLAYERS ) { if ( type == ENGI_TELE ) m_Teleporters[index].sapper = MyEHandle(pSapper); @@ -1675,17 +1314,17 @@ void CTeamFortress2Mod::sapperPlaced(edict_t *pOwner,eEngiBuild type,edict_t *pS } } -void CTeamFortress2Mod:: addWaypointFlags (edict_t *pPlayer, edict_t *pEdict, int *iFlags, int *iArea, float *fMaxDistance ) +void CTeamFortress2Mod:: addWaypointFlags (edict_t *pPlayer, edict_t *pEdict, int *iFlags, int *iArea, float *fMaxDistance) { - string_t model = pEdict->GetIServerEntity()->GetModelName(); + const string_t model = pEdict->GetIServerEntity()->GetModelName(); - if ( strncmp(pEdict->GetClassName(),"item_health",11) == 0 ) + if ( std::strncmp(pEdict->GetClassName(),"item_health",11) == 0 ) *iFlags |= CWaypointTypes::W_FL_HEALTH; - else if ( strncmp(pEdict->GetClassName(),"item_ammo",9) == 0 ) + else if ( std::strncmp(pEdict->GetClassName(),"item_ammo",9) == 0 ) *iFlags |= CWaypointTypes::W_FL_AMMO; - else if ( strcmp(pEdict->GetClassName(),"prop_dynamic") == 0 ) + else if ( std::strcmp(pEdict->GetClassName(),"prop_dynamic") == 0 ) { - if ( strcmp(model.ToCStr(),"models/props_gameplay/resupply_locker.mdl") == 0 ) + if ( std::strcmp(model.ToCStr(),"models/props_gameplay/resupply_locker.mdl") == 0 ) { *iFlags |= CWaypointTypes::W_FL_RESUPPLY; @@ -1695,25 +1334,34 @@ void CTeamFortress2Mod:: addWaypointFlags (edict_t *pPlayer, edict_t *pEdict, in *iFlags |= CWaypointTypes::W_FL_NOBLU; } } + else if (std::strcmp(pEdict->GetClassName(), "func_regenerate") == 0) // the actual resupply locker entity + { + *iFlags |= CWaypointTypes::W_FL_RESUPPLY; + + if (CTeamFortress2Mod::getTeam(pPlayer) == TF2_TEAM_BLUE) + *iFlags |= CWaypointTypes::W_FL_NORED; + else if (CTeamFortress2Mod::getTeam(pPlayer) == TF2_TEAM_RED) + *iFlags |= CWaypointTypes::W_FL_NOBLU; + } // do this in the event code - /*else if ( strcmp(pEdict->GetClassName(),"item_teamflag") == 0 ) + /*else if ( std::strcmp(pEdict->GetClassName(),"item_teamflag") == 0 ) { if ( !CTeamFortress2Mod::isFlagCarrier(pPlayer) ) *iFlags |= CWaypointTypes::W_FL_FLAG; }*/ - else if ( strcmp(pEdict->GetClassName(),"team_control_point") == 0 ) + else if ( std::strcmp(pEdict->GetClassName(),"team_control_point") == 0 ) { *iFlags |= CWaypointTypes::W_FL_CAPPOINT; *iArea = m_ObjectiveResource.getControlPointArea(pEdict); - *fMaxDistance = 100; + *fMaxDistance = 200; } } -void CTeamFortress2Mod::sapperDestroyed(edict_t *pOwner,eEngiBuild type, edict_t *pSapper) +void CTeamFortress2Mod::sapperDestroyed(edict_t *pOwner, const eEngiBuild type, const edict_t *pSapper) { static short int index; - for ( index = 0; index < MAX_PLAYERS; index ++ ) + for ( index = 0; index < RCBOT_MAXPLAYERS; index ++ ) { if ( type == ENGI_TELE ) { @@ -1736,64 +1384,50 @@ void CTeamFortress2Mod::sapperDestroyed(edict_t *pOwner,eEngiBuild type, edict_t void CTeamFortress2Mod::updatePointMaster() { - if ( m_PointMasterResource.get() == NULL ) + if ( m_PointMasterResource.get() == nullptr) { - edict_t *pMaster = CClassInterface::FindEntityByClassnameNearest(Vector(0,0,0),"team_control_point_master",65535); - - if ( pMaster ) + if ( edict_t *pMaster = CClassInterface::FindEntityByClassnameNearest(Vector(0,0,0),"team_control_point_master",65535) ) { -#ifdef _WIN32 - extern ConVar rcbot_const_point_master_offset; extern IServerGameEnts *servergameents; + extern IServerTools *servertools; + + // HACK: we use one of the known CBaseEntity-sized entities to compute the offset to the first subclass member for CTeamControlPointMaster / CTeamControlPointRound + const std::size_t baseEntityOffset = servertools->GetEntityFactoryDictionary()->FindFactory("simple_physics_brush")->GetEntitySize(); - CBaseEntity *pMasterEntity = servergameents->EdictToBaseEntity(pMaster); - - //local variable is initialized but not referenced - [APG]RoboCop[CL] - unsigned long full_size = sizeof(pMasterEntity); - unsigned long mempoint = ((unsigned long)pMasterEntity) + rcbot_const_point_master_offset.GetInt(); - - m_PointMaster = (CTeamControlPointMaster*)mempoint; - m_PointMasterResource = pMaster; -#else - extern ConVar rcbot_const_point_master_offset; - CBaseEntity *pent = pMaster->GetUnknown()->GetBaseEntity(); - unsigned long mempoint = ((unsigned long)pent)+rcbot_const_point_master_offset.GetInt(); - - m_PointMaster = (CTeamControlPointMaster*)mempoint; + const std::uintptr_t pMasterMembers = reinterpret_cast(servergameents->EdictToBaseEntity(pMaster)) + baseEntityOffset; + m_PointMaster = reinterpret_cast(pMasterMembers); m_PointMasterResource = pMaster; -#endif - - //extern ConVar rcbot_const_round_offset; + + logger->Log(LogLevel::INFO, "Computed point master offset %d", baseEntityOffset); - int idx = m_PointMaster->m_iCurrentRoundIndex; - int size = m_PointMaster->m_ControlPointRounds.Size(); + const int idx = m_PointMaster->m_iCurrentRoundIndex; + const int size = m_PointMaster->m_ControlPointRounds.Count(); if (idx >= 0 && size >= 0 && idx < 100 && size < 100) { int infoCount = 0; - for (int r = 0; r < m_PointMaster->m_ControlPointRounds.Size(); ++r) + for (int r = 0; r < m_PointMaster->m_ControlPointRounds.Count(); ++r) { try { CBaseEntity *pent = m_PointMaster->m_ControlPointRounds[r]; + CTeamControlPointRound* pointRound = reinterpret_cast(reinterpret_cast(pent) + baseEntityOffset); - CTeamControlPointRound* pointRound = (CTeamControlPointRound*)((unsigned long)pent + (unsigned long)rcbot_const_point_master_offset.GetInt()); - - CBotGlobals::botMessage(NULL, 0, "Control Points for Round %d", r); + logger->Log(LogLevel::DEBUG, "Control Points for Round %d", r); for (int i = 0; i < pointRound->m_ControlPoints.Count(); ++i) { - CBaseHandle* handle = &pointRound->m_ControlPoints.Element(i); + const CBaseHandle* handle = &pointRound->m_ControlPoints.Element(i); if (handle->IsValid()) { - edict_t* edict = INDEXENT(handle->GetEntryIndex()); + const edict_t* edict = INDEXENT(handle->GetEntryIndex()); if (!edict->IsFree()) { infoCount++; - CBotGlobals::botMessage(NULL, 0, "%d, %d, %d, %s", r, i, handle->GetSerialNumber(), edict->GetClassName()); + logger->Log(LogLevel::DEBUG, "%d, %d, %d, %s", r, i, handle->GetSerialNumber(), edict->GetClassName()); } } } @@ -1805,37 +1439,40 @@ void CTeamFortress2Mod::updatePointMaster() } } - if (infoCount == 0) - { - CBotGlobals::botMessage(NULL, 0, "If you are playing cp_* maps, and you get this message, something might be wrong with your mstr_offset!"); - } - } - else - { - CBotGlobals::botMessage(NULL, 0, "If you are playing cp_* maps, and you get this message, something might be wrong with your mstr_offset!"); + //if (infoCount == 0) + //{ + // logger->Log(LogLevel::WARN, "If you are playing cp_* maps, and you get this message, something might be wrong with your mstr_offset!"); + //} } + //else + //{ + // logger->Log(LogLevel::WARN, "If you are playing cp_* maps, and you get this message, something might be wrong with your mstr_offset!"); + //} } } - if ( m_PointMaster != NULL ) + if ( m_PointMaster != nullptr) { m_pCurrentRound = m_PointMaster->getCurrentRound(); } } -edict_t *CTeamFortress2Mod :: getPayloadBomb ( int team ) +edict_t *CTeamFortress2Mod :: getPayloadBomb (const int team) { if ( team == TF2_TEAM_BLUE ) return m_pPayLoadBombBlue; - else if ( team == TF2_TEAM_RED ) + if ( team == TF2_TEAM_RED ) return m_pPayLoadBombRed; - return NULL; + return nullptr; } void CTeamFortress2Mod :: roundReset () { - if ( m_ObjectiveResource.m_ObjectiveResource.get() == NULL ) + if (CTeamFortress2Mod::isMapType(TF_MAP_MVM) && g_pCVar->FindVar("tf_mvm_endless_force_on")->GetBool()) + return; + + if ( m_ObjectiveResource.m_ObjectiveResource.get() == nullptr) { m_ObjectiveResource.m_ObjectiveResource = CClassInterface::FindEntityByNetClass(gpGlobals->maxClients+1, "CTFObjectiveResource"); @@ -1846,7 +1483,7 @@ void CTeamFortress2Mod :: roundReset () } //always reset on new round - if ( m_ObjectiveResource.m_ObjectiveResource.get() != NULL ) //!m_ObjectiveResource.isInitialised() ) + if ( m_ObjectiveResource.m_ObjectiveResource.get() != nullptr) //!m_ObjectiveResource.isInitialised() ) m_ObjectiveResource.setup(); m_Timer.reset(); @@ -1855,8 +1492,7 @@ void CTeamFortress2Mod :: roundReset () if ( m_ObjectiveResource.isInitialised() ) { - extern ConVar rcbot_tf2_autoupdate_point_time; - int numpoints = m_ObjectiveResource.GetNumControlPoints(); + const int numpoints = m_ObjectiveResource.GetNumControlPoints(); int i; for ( i = 0; i < numpoints; i ++ ) @@ -1875,23 +1511,21 @@ void CTeamFortress2Mod :: roundReset () } - m_pNearestTankBoss = NULL; + m_pNearestTankBoss = nullptr; m_fNearestTankDistance = 0.0f; m_iWinningTeam = 0; m_bRoundOver = false; m_bHasRoundStarted = false; m_iFlagCarrierTeam = 0; - m_pPayLoadBombBlue = NULL; - m_pPayLoadBombRed = NULL; + m_pPayLoadBombBlue = nullptr; + m_pPayLoadBombRed = nullptr; if ( isMapType(TF_MAP_MVM) ) { if ( !m_bMVMFlagStartValid ) { - CWaypoint *pGoal = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_FLAG); - - if ( pGoal ) + if ( CWaypoint *pGoal = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_FLAG) ) { m_vNearestTankLocation = m_vMVMFlagStart = m_vFlagLocationBlue = pGoal->getOrigin(); m_bMVMFlagStartValid = m_bFlagLocationValidBlue = true; @@ -1907,9 +1541,7 @@ void CTeamFortress2Mod :: roundReset () if ( !m_bMVMCapturePointValid ) { - CWaypoint *pGoal = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_CAPPOINT); - - if ( pGoal ) + if ( CWaypoint *pGoal = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_CAPPOINT) ) { m_vMVMCapturePoint = pGoal->getOrigin(); m_bMVMCapturePointValid = true; @@ -1920,18 +1552,18 @@ void CTeamFortress2Mod :: roundReset () } } -void CTeamFortress2Mod::sentryBuilt(edict_t *pOwner, eEngiBuild type, edict_t *pBuilding ) +void CTeamFortress2Mod::sentryBuilt(const edict_t* pOwner, const eEngiBuild type, edict_t* pBuilding) { - static short int index; - static tf_sentry_t *temp; - - index = ENTINDEX(pOwner)-1; + static int index; + + index = ENTINDEX(pOwner) - 1; - if ( (index>=0) && (index=0 && indexsentry = MyEHandle(pBuilding); temp->sapper = MyEHandle(); //m_SentryGuns[index].builder @@ -1939,14 +1571,14 @@ void CTeamFortress2Mod::sentryBuilt(edict_t *pOwner, eEngiBuild type, edict_t *p } } -bool CTeamFortress2Mod::isSentryGun (edict_t *pEdict ) +bool CTeamFortress2Mod::isSentryGun (edict_t *pEdict) { static short int i; static tf_sentry_t *temp; temp = m_SentryGuns; - for ( i = 0; i < MAX_PLAYERS; i ++ ) + for ( i = 0; i < RCBOT_MAXPLAYERS; i ++ ) { if ( temp->sentry == pEdict ) return true; @@ -1957,18 +1589,18 @@ bool CTeamFortress2Mod::isSentryGun (edict_t *pEdict ) return false; } -void CTeamFortress2Mod::dispenserBuilt(edict_t *pOwner, eEngiBuild type, edict_t *pBuilding ) +void CTeamFortress2Mod::dispenserBuilt(const edict_t* pOwner, const eEngiBuild type, edict_t* pBuilding) { - static short int index; - static tf_disp_t *temp; - + static int index; + index = ENTINDEX(pOwner)-1; - if ( (index>=0) && (index=0 && indexdisp = MyEHandle(pBuilding); temp->sapper = MyEHandle(); //m_Dispensers[index].builder = userid; @@ -1978,7 +1610,7 @@ void CTeamFortress2Mod::dispenserBuilt(edict_t *pOwner, eEngiBuild type, edict_t void CTeamFortress2Mod::updateRedPayloadBomb ( edict_t *pent ) { - edict_t *cur = m_pPayLoadBombRed.get(); + const edict_t *cur = m_pPayLoadBombRed.get(); if ( cur != pent ) m_pPayLoadBombRed = pent; @@ -1986,7 +1618,7 @@ void CTeamFortress2Mod::updateRedPayloadBomb ( edict_t *pent ) void CTeamFortress2Mod::updateBluePayloadBomb ( edict_t *pent ) { - edict_t *cur = m_pPayLoadBombBlue.get(); + const edict_t *cur = m_pPayLoadBombBlue.get(); if ( cur != pent ) m_pPayLoadBombBlue = pent; @@ -1994,11 +1626,11 @@ void CTeamFortress2Mod::updateBluePayloadBomb ( edict_t *pent ) bool CTeamFortress2Mod::isDefending ( edict_t *pPlayer )//, int iCapIndex = -1 ) { - int iIndex = (1<<(ENTINDEX(pPlayer)-1)); + const int iIndex = (1 << (ENTINDEX(pPlayer) - 1)); if ( m_ObjectiveResource.GetNumControlPoints() > 0 ) { - int iTeam = CClassInterface::getTeam(pPlayer); + const int iTeam = CClassInterface::getTeam(pPlayer); //if ( iCapIndex == -1 ) //{ @@ -2020,19 +1652,17 @@ bool CTeamFortress2Mod::isDefending ( edict_t *pPlayer )//, int iCapIndex = -1 ) bool CTeamFortress2Mod::isCapping ( edict_t *pPlayer )//, int iCapIndex = -1 ) { - int index = (1<<(ENTINDEX(pPlayer)-1)); + const int index = (1 << (ENTINDEX(pPlayer) - 1)); if ( m_ObjectiveResource.GetNumControlPoints() > 0 ) { - int iTeam = CClassInterface::getTeam(pPlayer); - - int i = 0; + const int iTeam = CClassInterface::getTeam(pPlayer); - for ( i = 0; i < MAX_CAP_POINTS; i ++ ) + for ( int i = 0; i < MAX_CAP_POINTS; i ++ ) { if ( m_ObjectiveResource.isCPValid(i,iTeam,TF2_POINT_ATTACK) ) { - if ( (m_Cappers[i] & index) == index ) + if ( (m_Cappers[i] & index) == index ) return true; } } @@ -2040,109 +1670,3 @@ bool CTeamFortress2Mod::isCapping ( edict_t *pPlayer )//, int iCapIndex = -1 ) return false; } - - -/*void CTF2Loadout :: addAttribute ( CAttribute *attrib ) -{ - m_Attributes.push_back(attrib); -}*/ - -unsigned int CTF2Loadout::copyAttributesIntoArray ( CEconItemAttribute *pArray, void *pVTable ) -{ - for ( unsigned int i = 0; i < m_Attributes.size(); i ++ ) - { - pArray[i] = *(m_Attributes[i]); - pArray[i].m_pVTable = pVTable; - } - - return m_Attributes.size(); -} - -void CTF2Loadout :: addAttribute ( int id, float fval ) -{ - m_Attributes.push_back(new CEconItemAttribute(id,fval)); -} - -void CTF2Loadout :: applyAttributes ( CBaseEntity *pEnt ) -{/* - extern IServerGameEnts *servergameents; - - edict_t *pEdict = servergameents->BaseEntityToEdict(pEnt); - - for ( unsigned int i = 0; i < m_Attributes.size(); i ++ ) - { - int id = m_Attributes[i]->m_iAttributeDefinitionIndex; - float fval = m_Attributes[i]->m_flValue; - - UTIL_ApplyAttribute(pEdict,g_pszAttributeNames[id],fval); - }*/ -} - -void CTF2Loadout :: applyAttributes ( CEconItemView *cscript ) -{ - for ( unsigned int i = 0; i < m_Attributes.size(); i ++ ) - { - m_Attributes[i]->m_pVTable = cscript->m_AttributeList.m_pVTable; - - cscript->m_AttributeList.m_Attributes.AddToHead((*m_Attributes[i])); - } -} - -void CTF2Loadout :: freeMemory () -{ - for ( unsigned int i = 0; i < m_Attributes.size(); i ++ ) - { - CEconItemAttribute *pdel = m_Attributes[i]; - delete pdel; - m_Attributes[i] = NULL; - } -} - -void CTeamFortress2Mod::freeMemory() -{ - vector loadouts_to_free; - - for (unsigned int i = 0; i < TF2_SLOT_MAX; i++) - { - for (unsigned int j = 0; j < 9; j++) - { - for (unsigned int k = 0; k < m_pLoadoutWeapons[i][j].size(); k++) - { - CTF2Loadout *wep = (m_pLoadoutWeapons[i][j]).at(k); - - bool bfound = false; - - for (unsigned int l = 0; l < loadouts_to_free.size(); l++) - { - if (loadouts_to_free.at(l) == wep) - { - bfound = true; - break; - } - } - - if (bfound == false) - loadouts_to_free.push_back(wep); - - (m_pLoadoutWeapons[i][j])[k] = NULL; - } - - (m_pLoadoutWeapons[i][j]).clear(); - } - } - - for (unsigned int i = 0; i < loadouts_to_free.size(); i++) - { - CTF2Loadout *wep = loadouts_to_free.at(i); - - delete wep; - loadouts_to_free[i] = NULL; - } - - loadouts_to_free.clear(); -} - -void CAttribute :: applyAttribute ( edict_t *pEdict ) -{ - //UTIL_ApplyAttribute(pEdict,m_name,m_fval); -} diff --git a/utils/RCBot2_meta/bot_tf2_points.cpp b/utils/RCBot2_meta/bot_tf2_points.cpp index e8e75d588..1decae4a0 100644 --- a/utils/RCBot2_meta/bot_tf2_points.cpp +++ b/utils/RCBot2_meta/bot_tf2_points.cpp @@ -1,20 +1,25 @@ -#include "engine_wrappers.h" +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com +#include "bot_tf2_points.h" #include "bot.h" -#include "bot_getprop.h" +#include "bot_cvars.h" #include "bot_fortress.h" -#include "bot_tf2_points.h" -#include "bot_waypoint.h" +#include "bot_getprop.h" #include "bot_globals.h" +#include "bot_waypoint.h" #include "bot_waypoint_locations.h" +#include "engine_wrappers.h" + +#include class CBotFuncResetAttackPoint : public IBotFunction { public: - CBotFuncResetAttackPoint(int team) { iTeam = team; } - void execute ( CBot *pBot ) + CBotFuncResetAttackPoint(const int team) { iTeam = team; } + void execute ( CBot *pBot ) override { if ( pBot->getTeam() == iTeam ) - ((CBotTF2*)pBot)->updateAttackPoints(); + static_cast(pBot)->updateAttackPoints(); } private: int iTeam; @@ -23,11 +28,11 @@ class CBotFuncResetAttackPoint : public IBotFunction class CBotFuncResetDefendPoint : public IBotFunction { public: - CBotFuncResetDefendPoint(int team) { iTeam = team; } - void execute ( CBot *pBot ) + CBotFuncResetDefendPoint(const int team) { iTeam = team; } + void execute ( CBot *pBot ) override { if ( pBot->getTeam() == iTeam ) - ((CBotTF2*)pBot)->updateDefendPoints(); + static_cast(pBot)->updateDefendPoints(); } private: int iTeam; @@ -37,9 +42,9 @@ class CBotFuncResetDefendPoint : public IBotFunction class CBotFuncPointsUpdated : public IBotFunction { public: - void execute ( CBot *pBot ) + void execute ( CBot *pBot ) override { - ((CBotTF2*)pBot)->pointsUpdated(); + static_cast(pBot)->pointsUpdated(); } }; @@ -88,7 +93,7 @@ void CTFObjectiveResource::updatePoints() } // INPUT = Waypoint Area -bool CTFObjectiveResource :: isWaypointAreaValid ( int wptarea, int waypointflags ) +bool CTFObjectiveResource :: isWaypointAreaValid (const int wptarea, const int waypointflags) const { // CWaypoint *pWaypoint; @@ -96,10 +101,10 @@ bool CTFObjectiveResource :: isWaypointAreaValid ( int wptarea, int waypointflag return true; // Translate Waypoint Area to Index - if ( (wptarea < 0) || (wptarea > MAX_CONTROL_POINTS) ) + if ( wptarea < 0 || wptarea > MAX_CONTROL_POINTS ) return false; - int cpindex = m_WaypointAreaToIndexTranslation[wptarea]; +const int cpindex = m_WaypointAreaToIndexTranslation[wptarea]; if ( cpindex == -1 ) return false; @@ -128,85 +133,83 @@ bool CTFObjectiveResource :: isWaypointAreaValid ( int wptarea, int waypointflag return m_ValidAreas[wptarea-1];*/ } -bool CTFObjectiveResource::isCPValidWptArea ( int iWptArea, int iTeam, ePointAttackDefend_s type ) +bool CTFObjectiveResource::isCPValidWptArea (const int iWptArea, const int iTeam, const ePointAttackDefend_s type) const { if ( iWptArea == 0 ) return true; - if ( (iWptArea < 1) || (iWptArea > MAX_CONTROL_POINTS) ) + if ( iWptArea < 1 || iWptArea > MAX_CONTROL_POINTS ) return false; return isCPValid(m_WaypointAreaToIndexTranslation[iWptArea],iTeam,type); } // Returns TRUE if waypoint area is worth attacking or defending at this moment -bool CTFObjectiveResource::testProbWptArea ( int iWptArea, int iTeam ) +bool CTFObjectiveResource::testProbWptArea (const int iWptArea, const int iTeam) const { - int iCpIndex = m_WaypointAreaToIndexTranslation[iWptArea]; + const int iCpIndex = m_WaypointAreaToIndexTranslation[iWptArea]; - if ( (iTeam != TF2_TEAM_BLUE) && (iTeam != TF2_TEAM_RED) ) + if ( iTeam != TF2_TEAM_BLUE && iTeam != TF2_TEAM_RED ) return true; if ( iWptArea == 0 ) return true; - if ( (iWptArea < 1) || (iWptArea > MAX_CONTROL_POINTS) ) + if ( iWptArea < 1 || iWptArea > MAX_CONTROL_POINTS ) return true; - return isCPValid(iCpIndex,iTeam,TF2_POINT_ATTACK) ? (randomFloat(0.0f,1.0f) > m_ValidPoints[iTeam-2][TF2_POINT_ATTACK][iCpIndex].fProb) : ( isCPValid(iCpIndex,iTeam,TF2_POINT_DEFEND) ? (randomFloat(0.0f,1.0f) > m_ValidPoints[iTeam-2][TF2_POINT_DEFEND][iCpIndex].fProb) : true ); + return isCPValid(iCpIndex,iTeam,TF2_POINT_ATTACK) ? randomFloat(0.0f,1.0f) > m_ValidPoints[iTeam-2][TF2_POINT_ATTACK][iCpIndex].fProb : isCPValid(iCpIndex,iTeam,TF2_POINT_DEFEND) ? randomFloat(0.0f,1.0f) > m_ValidPoints[iTeam-2][TF2_POINT_DEFEND][iCpIndex].fProb : true; } -bool CTFObjectiveResource::isCPValid ( int iCPIndex, int iTeam, ePointAttackDefend_s type ) +bool CTFObjectiveResource::isCPValid (const int iCPIndex, const int iTeam, const ePointAttackDefend_s type) const { - if ( (iCPIndex < 0) || (iCPIndex >= MAX_CONTROL_POINTS) ) + if ( iCPIndex < 0 || iCPIndex >= MAX_CONTROL_POINTS ) return false; return m_ValidPoints[iTeam-2][type][iCPIndex].bValid; } -// TO DO - Base on waypoint danger +// TODO: - Base on waypoint danger // base on base point -- if already have attack point and base point -- less focus on base point -int CTFObjectiveResource::getRandomValidPointForTeam ( int team, ePointAttackDefend_s type) +int CTFObjectiveResource::getRandomValidPointForTeam (const int team, const ePointAttackDefend_s type) { - TF2PointProb_t *arr = NULL; - vector points; - int iotherteam; + std::vector points; // point indices float fTotal = 0.0f; - if (( team < 2 ) || ( team > 3 )) + if (team < 2 || team > 3) return 0; - if ( m_iNumControlPoints == NULL ) + if ( m_iNumControlPoints == nullptr) return 0; - iotherteam = (team==2)?3:2; + const int iotherteam = team == 2 ? 3 : 2; - arr = m_ValidPoints[team-2][type]; + TF2PointProb_t* arr = m_ValidPoints[team - 2][type]; for ( int i = 0; i < *m_iNumControlPoints; i ++ ) { if ( arr[i].bValid == true ) { - points.push_back(i); + points.emplace_back(i); if ( type == TF2_POINT_ATTACK ) { if (GetCappingTeam(i) == team) arr[i].fProbMultiplier = 3.0f; - else if ((getLastCaptureTime(i) + 10.0f) > gpGlobals->curtime ) + else if (getLastCaptureTime(i) + 10.0f > gpGlobals->curtime ) arr[i].fProbMultiplier = 2.0f; } else { if (GetCappingTeam(i) == iotherteam) { - int numplayers = GetNumPlayersInArea(i,iotherteam); + const int numplayers = GetNumPlayersInArea(i,iotherteam); // IF this is not base point and a lot of players are here, reduce probability of defending - if ( (i != GetBaseControlPointForTeam(team)) && (numplayers > 1) ) + if ( i != GetBaseControlPointForTeam(team) && numplayers > 1 ) { - arr[i].fProbMultiplier = 1.0f - ((float)numplayers/(gpGlobals->maxClients/4)); + arr[i].fProbMultiplier = 1.0f - static_cast(numplayers) / static_cast(gpGlobals->maxClients) / 4; if ( arr[i].fProbMultiplier <= 0.0f ) arr[i].fProbMultiplier = 0.1f; @@ -214,7 +217,7 @@ int CTFObjectiveResource::getRandomValidPointForTeam ( int team, ePointAttackDef else // Otherwise there aren't any playres on or is base and has been attacked recently arr[i].fProbMultiplier = 4.0f; } - else if ((getLastCaptureTime(i) + 10.0f) > gpGlobals->curtime ) + else if (getLastCaptureTime(i) + 10.0f > gpGlobals->curtime ) arr[i].fProbMultiplier = 2.0f; } @@ -222,14 +225,12 @@ int CTFObjectiveResource::getRandomValidPointForTeam ( int team, ePointAttackDef } } - float fRand = randomFloat(0.0f,fTotal); + const float fRand = randomFloat(0.0f,fTotal); fTotal = 0.0f; - for ( unsigned int i = 0; i < points.size(); i ++ ) + for (const int index : points) { - int index = points[i]; - fTotal += arr[index].fProb*arr[index].fProbMultiplier; if ( fTotal > fRand ) @@ -241,44 +242,30 @@ int CTFObjectiveResource::getRandomValidPointForTeam ( int team, ePointAttackDef // no points return 0; } + void CTeamRoundTimer::reset() { - CTeamRoundTimer(); + // Manually reset the object's state + std::memset(this, 0, sizeof(CTeamRoundTimer)); m_Resource = CClassInterface::FindEntityByNetClass(gpGlobals->maxClients + 1, "CTeamRoundTimer"); - if (m_Resource.get() != NULL) + if (m_Resource.get() != nullptr) { CClassInterface::setupCTeamRoundTimer(this); } } + bool CTeamControlPointRound :: isPointInRound ( edict_t *point_pent ) { - edict_t *pPoint; - //extern ConVar rcbot_const_point_master_offset; - - for ( int i = 0; i < m_ControlPoints.Size(); i ++ ) + for (int i = 0; i < m_ControlPoints.Count(); i++) { - CBaseHandle *hndl; - - hndl = (CBaseHandle *)&(m_ControlPoints[i]); - - if ( hndl ) + if ( const CBaseHandle* hndl = &m_ControlPoints[i] ) { - pPoint = INDEXENT(hndl->GetEntryIndex()); - - CBaseEntity *pent = pPoint->GetUnknown()->GetBaseEntity(); - + edict_t* pPoint = INDEXENT(hndl->GetEntryIndex()); + const CBaseEntity *pent = pPoint->GetUnknown()->GetBaseEntity(); if ( point_pent->GetUnknown()->GetBaseEntity() == pent ) return true; - - //CTeamControlPoint *point = (CTeamControlPoint*)((unsigned long)pent + rcbot_const_point_offset.GetInt() ); - - //if ( point ) - //{ - // if ( point->m_iIndex == iIndex ) - // return true; - //} } } @@ -288,7 +275,7 @@ bool CTeamControlPointRound :: isPointInRound ( edict_t *point_pent ) CTeamControlPointRound *CTeamControlPointMaster:: getCurrentRound ( ) { if ( m_iCurrentRoundIndex == -1 ) - return NULL; + return nullptr; CBaseEntity *pent = m_ControlPointRounds[m_iCurrentRoundIndex]; @@ -296,14 +283,13 @@ CTeamControlPointRound *CTeamControlPointMaster:: getCurrentRound ( ) //edict_t *p = servergameents->BaseEntityToEdict(pent); - extern ConVar rcbot_const_point_master_offset; - /* - CTeamControlPointRound *org = (CTeamControlPointRound*)((unsigned long)pent+(unsigned long)rcbot_const_round_offset.GetInt()); - CTeamControlPointRound *fromunk = (CTeamControlPointRound*)p->GetUnknown(); - CTeamControlPointRound *fromserverent = (CTeamControlPointRound*)p->GetIServerEntity();*/ + extern IServerGameEnts *servergameents; // servergameents not used? [APG]RoboCop[CL] + extern IServerTools *servertools; + + // HACK: we use one of the known CBaseEntity-sized entities to compute the offset to the first subclass member for CTeamControlPointMaster / CTeamControlPointRound + const std::size_t baseEntityOffset = servertools->GetEntityFactoryDictionary()->FindFactory("simple_physics_brush")->GetEntitySize(); - // Fix for later TF2 2016 Engine? [APG]RoboCop[CL] - return (CTeamControlPointRound*)((unsigned long)pent + (unsigned long)rcbot_const_point_master_offset.GetInt()); + return reinterpret_cast(reinterpret_cast(pent) + baseEntityOffset); } ////////////////// @@ -313,35 +299,34 @@ void CTFObjectiveResource::setup () { CClassInterface::getTF2ObjectiveResource(this); - memset(m_pControlPoints,0,sizeof(edict_t*)*MAX_CONTROL_POINTS); - memset(m_iControlPointWpt,0xFF,sizeof(int)*MAX_CONTROL_POINTS); - memset(m_fLastCaptureTime,0,sizeof(float)*MAX_CONTROL_POINTS); + //std::memset(m_pControlPoints,0,sizeof(edict_t*)*MAX_CONTROL_POINTS); + std::memset(m_pControlPoints, 0, sizeof(*m_pControlPoints) * MAX_CONTROL_POINTS); + std::memset(m_iControlPointWpt,0xFF,sizeof(int)*MAX_CONTROL_POINTS); + std::memset(m_fLastCaptureTime,0,sizeof(float)*MAX_CONTROL_POINTS); // Find control point entities - edict_t *pent; - Vector vOrigin; int i = gpGlobals->maxClients; - memset(m_IndexToWaypointAreaTranslation,0,sizeof(int)*MAX_CONTROL_POINTS); - memset(m_WaypointAreaToIndexTranslation,0xFF,sizeof(int)*(MAX_CONTROL_POINTS+1)); + std::memset(m_IndexToWaypointAreaTranslation,0,sizeof(int)*MAX_CONTROL_POINTS); + std::memset(m_WaypointAreaToIndexTranslation,0xFF,sizeof(int)*(MAX_CONTROL_POINTS+1)); // find visible flags -- with a model while ( ++i < gpGlobals->maxEntities ) { - pent = INDEXENT(i); + edict_t* pent = INDEXENT(i); if ( !pent || pent->IsFree() ) continue; - if ( strcmp(pent->GetClassName(),"team_control_point") == 0 ) + if ( std::strcmp(pent->GetClassName(),"team_control_point") == 0 ) { vOrigin = CBotGlobals::entityOrigin(pent); for ( int j = 0; j < *m_iNumControlPoints; j ++ ) { - if ( m_pControlPoints[j].get() != NULL ) + if ( m_pControlPoints[j].get() != nullptr) continue; if ( vOrigin == m_vCPPositions[j] ) @@ -353,27 +338,25 @@ void CTFObjectiveResource::setup () } } - CWaypoint *pWaypoint; - int iWpt; - - for ( int j = 0; j < *m_iNumControlPoints; j ++ ) + for (int j = 0; j < *m_iNumControlPoints; j++) { vOrigin = m_vCPPositions[j]; if ( m_iControlPointWpt[j] == -1 ) { - iWpt = CWaypointLocations::NearestWaypoint(vOrigin,1024.0f,-1,false,false,false,NULL,false,0,false,false,Vector(0,0,0),CWaypointTypes::W_FL_CAPPOINT); - pWaypoint = CWaypoints::getWaypoint(iWpt); + const int iWpt = CWaypointLocations::NearestWaypoint(vOrigin, 1024.0f, -1, false, false, false, nullptr, false, 0, false, + false, Vector(0, 0, 0), CWaypointTypes::W_FL_CAPPOINT); + const CWaypoint* pWaypoint = CWaypoints::getWaypoint(iWpt); m_iControlPointWpt[j] = iWpt; // For compatibility -- old waypoints are already set with an area, so take the area from the waypoint here // in the future waypoints will automatically be set to the waypoint area anyway if ( pWaypoint ) { - int iArea = pWaypoint->getArea(); + const int iArea = pWaypoint->getArea(); m_IndexToWaypointAreaTranslation[j] = iArea; - if ( ( iArea >= 1 ) && ( iArea < MAX_CONTROL_POINTS ) ) + if ( iArea >= 1 && iArea < MAX_CONTROL_POINTS ) m_WaypointAreaToIndexTranslation[iArea] = j; } else @@ -389,15 +372,15 @@ void CTFObjectiveResource::setup () int CTFObjectiveResource :: getControlPointArea ( edict_t *pPoint ) { - for ( int j = 0; j < *m_iNumControlPoints; j ++ ) + for (int j = 0; j < *m_iNumControlPoints; j++) { if ( m_pControlPoints[j] == pPoint ) - return (j+1); // return waypoint area (+1) + return j+1; // return waypoint area (+1) } return 0; } -void CTFObjectiveResource:: debugprint ( void ) +void CTFObjectiveResource:: debugprint () const { edict_t *pEdict = CClients::getListenServerClient(); @@ -406,14 +389,14 @@ void CTFObjectiveResource:: debugprint ( void ) CBotGlobals::botMessage(pEdict,0,"m_bCPLocked[byte]\t[%d]",*m_bCPLocked); CBotGlobals::botMessage(pEdict,0,"m_bCPLocked[8]\t[%s,%s,%s,%s,%s,%s,%s,%s]",m_bCPLocked[0]?"Y":"N",m_bCPLocked[1]?"Y":"N",m_bCPLocked[2]?"Y":"N",m_bCPLocked[3]?"Y":"N",m_bCPLocked[4]?"Y":"N",m_bCPLocked[5]?"Y":"N",m_bCPLocked[6]?"Y":"N",m_bCPLocked[7]?"Y":"N"); CBotGlobals::botMessage(pEdict,0,"m_bCPIsVisible[8]\t[%s,%s,%s,%s,%s,%s,%s,%s]",m_bCPIsVisible[0]?"Y":"N",m_bCPIsVisible[1]?"Y":"N",m_bCPIsVisible[2]?"Y":"N",m_bCPIsVisible[3]?"Y":"N",m_bCPIsVisible[4]?"Y":"N",m_bCPIsVisible[5]?"Y":"N",m_bCPIsVisible[6]?"Y":"N",m_bCPIsVisible[7]?"Y":"N"); - CBotGlobals::botMessage(pEdict,0,"m_iOwner[8]\t[%s,%s,%s,%s,%s,%s,%s,%s]",(m_iOwner[0]==2)?"red":((m_iOwner[0]==3)?"blue":"unassigned"),(m_iOwner[1]==2)?"red":((m_iOwner[1]==3)?"blue":"unassigned"),(m_iOwner[2]==2)?"red":((m_iOwner[2]==3)?"blue":"unassigned"),(m_iOwner[3]==2)?"red":((m_iOwner[3]==3)?"blue":"unassigned"),(m_iOwner[4]==2)?"red":((m_iOwner[4]==3)?"blue":"unassigned"),(m_iOwner[5]==2)?"red":((m_iOwner[5]==3)?"blue":"unassigned"),(m_iOwner[6]==2)?"red":((m_iOwner[6]==3)?"blue":"unassigned"),(m_iOwner[7]==2)?"red":((m_iOwner[7]==3)?"blue":"unassigned")); + CBotGlobals::botMessage(pEdict,0,"m_iOwner[8]\t[%s,%s,%s,%s,%s,%s,%s,%s]",m_iOwner[0]==2?"red":m_iOwner[0]==3?"blue":"unassigned",m_iOwner[1]==2?"red":m_iOwner[1]==3?"blue":"unassigned",m_iOwner[2]==2?"red":m_iOwner[2]==3?"blue":"unassigned",m_iOwner[3]==2?"red":m_iOwner[3]==3?"blue":"unassigned",m_iOwner[4]==2?"red":m_iOwner[4]==3?"blue":"unassigned",m_iOwner[5]==2?"red":m_iOwner[5]==3?"blue":"unassigned",m_iOwner[6]==2?"red":m_iOwner[6]==3?"blue":"unassigned",m_iOwner[7]==2?"red":m_iOwner[7]==3?"blue":"unassigned"); } -int CTFObjectiveResource::NearestArea ( Vector vOrigin ) +int CTFObjectiveResource::NearestArea (const Vector& vOrigin) const { int iNearest = -1; float fNearest = 2048.0f; - float fDist; + float fDist; //TODO: fDist could be reduced? [APG]RoboCop[CL] for ( int i = 0; i < *m_iNumControlPoints; i ++ ) { @@ -433,12 +416,11 @@ int CTFObjectiveResource::NearestArea ( Vector vOrigin ) /*CTeamControlPoint *CTeamControlPoint::getPoint ( edict_t *pent ) { - extern ConVar rcbot_const_point_offset; return (CTeamControlPoint*)((((unsigned long)pent) + rcbot_const_point_offset.GetInt())); //MAP_CLASS(CTeamControlPoint,(((unsigned long)pent) + offset),knownoffset); }*/ -bool CTFObjectiveResource :: updateDefendPoints ( int team ) +bool CTFObjectiveResource :: updateDefendPoints (const int team) { /*int other = (team==2)?3:2; @@ -447,28 +429,27 @@ bool CTFObjectiveResource :: updateDefendPoints ( int team ) int signature = 0; int other; int prev; - bool isPayLoadMap = CTeamFortress2Mod::isMapType(TF_MAP_CART)||CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE); - TF2PointProb_t *arr; + const bool isPayLoadMap = CTeamFortress2Mod::isMapType(TF_MAP_CART)||CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE); //CTeamControlPoint *pPoint; //CTeamControlPointMaster *pMaster = CTeamFortress2Mod::getPointMaster(); CTeamControlPointRound *pRound = CTeamFortress2Mod::getCurrentRound(); - if ( m_ObjectiveResource.get() == NULL ) // not set up yet + if ( m_ObjectiveResource.get() == nullptr) // not set up yet return false; if ( team == 0 ) // invalid team return false; - arr = m_ValidPoints[team-2][TF2_POINT_DEFEND]; + TF2PointProb_t* arr = m_ValidPoints[team - 2][TF2_POINT_DEFEND]; // reset array - memset(arr,0,sizeof(TF2PointProb_t)*MAX_CONTROL_POINTS); + std::memset(arr,0,sizeof(TF2PointProb_t)*MAX_CONTROL_POINTS); - for ( int i = 0; i < *m_iNumControlPoints; i ++ ) + for (int i = 0; i < *m_iNumControlPoints; i++) { arr[i].fProbMultiplier = 1.0f; arr[i].fProb = 1.0f; - memset(arr[i].iPrev,0xFF,sizeof(int)*MAX_PREVIOUS_POINTS); + std::memset(arr[i].iPrev,0xFF,sizeof(int)*MAX_PREVIOUS_POINTS); // not visible if ( m_bCPIsVisible[i] == 0 ) @@ -488,7 +469,7 @@ bool CTFObjectiveResource :: updateDefendPoints ( int team ) if ( GetOwningTeam(i) == team ) { // The other team can capture - other = (team==2)?3:2; + other = team==2?3:2; if ( TeamCanCapPoint(i,other) ) { @@ -500,36 +481,32 @@ bool CTFObjectiveResource :: updateDefendPoints ( int team ) arr[i].bValid = true; continue; } - else - { - // This point needs previous points to be captured first - int j; - bool bEnemyCanCap = true; + bool bEnemyCanCap = true; - for ( j = 0; j < MAX_PREVIOUS_POINTS; j ++ ) - { - // need to go through each previous point to update the array - // DONT BREAK!!! - prev = GetPreviousPointForPoint(i,other,j); - arr[i].iPrev[j] = prev; + for (int j = 0; j < MAX_PREVIOUS_POINTS; j++) + { + // need to go through each previous point to update the array + // DONT BREAK!!! + prev = GetPreviousPointForPoint(i,other,j); + arr[i].iPrev[j] = prev; - if ( prev == -1 ) - continue; - else if ( GetOwningTeam(prev) != other ) - bEnemyCanCap = false; - } + if ( prev == -1 ) + continue; + if ( GetOwningTeam(prev) != other ) + bEnemyCanCap = false; + } - if ( !bEnemyCanCap ) - { - arr[i].bPrev = true; - arr[i].bValid = false; - // Check later by checking prev points - } - else - { - arr[i].bValid = true; - } - /* + if ( !bEnemyCanCap ) + { + arr[i].bPrev = true; + arr[i].bValid = false; + // Check later by checking prev points + } + else + { + arr[i].bValid = true; + } + /* // other team has captured previous points if ( j == 3 ) { @@ -539,7 +516,6 @@ bool CTFObjectiveResource :: updateDefendPoints ( int team ) else { continue;*/ - } } else { @@ -547,7 +523,7 @@ bool CTFObjectiveResource :: updateDefendPoints ( int team ) arr[i].bValid = true; else { - int basepoint = GetBaseControlPointForTeam(team); + const int basepoint = GetBaseControlPointForTeam(team); arr[i].bValid = true; if ( i == basepoint ) @@ -574,14 +550,13 @@ bool CTFObjectiveResource :: updateDefendPoints ( int team ) iNumAvailable++; } - if ( iNumOwned == (iNumAvailable-1) ) + if ( iNumOwned == iNumAvailable-1 ) { // other team can capture arr[i].fProb = 1.0f; } - else if ( iNumOwned == (iNumAvailable-2) ) - { - extern ConVar bot_defrate; + else if ( iNumOwned == iNumAvailable-2 ) + { // other team can capture this as the next point arr[i].fProb = bot_defrate.GetFloat(); } @@ -589,8 +564,6 @@ bool CTFObjectiveResource :: updateDefendPoints ( int team ) arr[i].fProb = 0.001f; } } - - continue; } } else @@ -601,20 +574,19 @@ bool CTFObjectiveResource :: updateDefendPoints ( int team ) } } // do another search through the previous points - for ( int i = 0; i < *m_iNumControlPoints; i ++ ) + for (int i = 0; i < *m_iNumControlPoints; i++) { if ( arr[i].bPrev ) { int iNumPrevPointsAvail = 0; - int j; // Check this points prevous points - for ( j = 0; j < MAX_PREVIOUS_POINTS; j ++ ) + for (const int j : arr[i].iPrev) { - if ( arr[i].iPrev[j] != -1 ) + if (j != -1 ) { // the previous point is not valid - if ( arr[arr[i].iPrev[j]].bValid ) + if ( arr[j].bValid ) iNumPrevPointsAvail++; } } @@ -624,17 +596,15 @@ bool CTFObjectiveResource :: updateDefendPoints ( int team ) { // this point is next because the current valid points are required arr[i].bNextPoint = true; - - extern ConVar bot_defrate; // other team can capture this as the next point // lower chance of defending the next point before round has started!!! Get everyone up!! - arr[i].fProb = CTeamFortress2Mod::hasRoundStarted() ? bot_defrate.GetFloat() : (bot_defrate.GetFloat()*0.5f); + arr[i].fProb = CTeamFortress2Mod::hasRoundStarted() ? bot_defrate.GetFloat() : bot_defrate.GetFloat()*0.5f; } } } - for ( int i = 0; i < *m_iNumControlPoints; i ++ ) + for (int i = 0; i < *m_iNumControlPoints; i++) { if ( arr[i].bNextPoint ) arr[i].bValid = true; @@ -643,16 +613,16 @@ bool CTFObjectiveResource :: updateDefendPoints ( int team ) bool bfound = false; // find this point in one of the previous points - for ( int j = 0; j < *m_iNumControlPoints; j ++ ) + for (int j = 0; j < *m_iNumControlPoints; j++) { if ( i == j ) continue; if ( arr[j].bPrev ) { - for ( int k = 0; k < MAX_PREVIOUS_POINTS; k ++ ) + for (const int k : arr[j].iPrev) { - if ( arr[j].iPrev[k] == i ) + if (k == i ) { bfound = true; break; @@ -681,23 +651,21 @@ bool CTFObjectiveResource :: updateDefendPoints ( int team ) { float fMaxProb = 1.0f; bool bFirst = true; - extern ConVar bot_defrate; - extern ConVar rcbot_tf2_payload_dist_retreat; - other = (team==2)?3:2; + other = team==2?3:2; - for ( int i = 0; i < *m_iNumControlPoints; i ++ ) + for (int i = 0; i < *m_iNumControlPoints; i++) { if ( arr[i].bValid ) { edict_t *pPayloadBomb = CTeamFortress2Mod::getPayloadBomb(other); - if ( pPayloadBomb != NULL ) + if ( pPayloadBomb != nullptr) { if ( bFirst ) { - // TO DO update probability depending on distance to payload bomb - float fDist = (CBotGlobals::entityOrigin(pPayloadBomb) - m_vCPPositions[i]).Length(); + // TODO: update probability depending on distance to payload bomb + const float fDist = (CBotGlobals::entityOrigin(pPayloadBomb) - m_vCPPositions[i]).Length(); bFirst = false; @@ -714,13 +682,13 @@ bool CTFObjectiveResource :: updateDefendPoints ( int team ) { arr[i].fProb = bot_defrate.GetFloat(); - int j = i + 1; + const int j = i + 1; if ( j < *m_iNumControlPoints ) { if ( arr[j].bValid == false ) { - if ( !pRound || (m_pControlPoints[j]&&pRound->isPointInRound(m_pControlPoints[j])) ) + if (!pRound || (m_pControlPoints[j] && pRound->isPointInRound(m_pControlPoints[j]))) arr[j].bValid = true; // this is the next point - move back lads } } @@ -737,7 +705,6 @@ bool CTFObjectiveResource :: updateDefendPoints ( int team ) arr[i].fProb = fMaxProb; fMaxProb = fMaxProb/4; } - //arr[i].fProb *= arr[i].fProb; // square it } @@ -745,13 +712,12 @@ bool CTFObjectiveResource :: updateDefendPoints ( int team ) } // update signature - for ( int i = 0; i < *m_iNumControlPoints; i ++ ) + for (int i = 0; i < *m_iNumControlPoints; i++) { - byte j; - byte *barr = (byte*)&(arr[i]); + const byte *barr = reinterpret_cast(&arr[i]); - for ( j = 0; j < sizeof(TF2PointProb_t); j ++ ) - signature = signature + ((barr[j]*(i+1))+j); + for ( byte j = 0; j < sizeof(TF2PointProb_t); j ++ ) + signature = signature + (barr[j]*(i+1)+j); } if ( signature != m_PointSignature[team-2][TF2_POINT_DEFEND] ) @@ -765,9 +731,9 @@ bool CTFObjectiveResource :: updateDefendPoints ( int team ) void CTFObjectiveResource :: think () { - if ( m_bInitialised && ( m_fNextCheckMonitoredPoint < engine->Time() ) ) + if ( m_bInitialised && m_fNextCheckMonitoredPoint < engine->Time() ) { - bool bupdate = (m_fUpdatePointTime < engine->Time()); + bool bupdate = m_fUpdatePointTime < engine->Time(); int team = 0; @@ -775,11 +741,11 @@ void CTFObjectiveResource :: think () { if ( m_iMonitorPoint[team] != -1 ) { - for ( int j = 0; j < MAX_PREVIOUS_POINTS; j ++ ) + for (int j = 0; j < MAX_PREVIOUS_POINTS; j++) { - int prev = GetPreviousPointForPoint(m_iMonitorPoint[team],(team+2),j); + const int prev = GetPreviousPointForPoint(m_iMonitorPoint[team],team+2,j); - if ( (prev != -1) && (GetOwningTeam(prev)!=(team+2)) ) + if ( prev != -1 && GetOwningTeam(prev)!=team+2 ) { bupdate = true; break; @@ -787,12 +753,10 @@ void CTFObjectiveResource :: think () } } team++; - }while ((team < 2) && (bupdate==false)); + }while (team < 2 && bupdate==false); if ( bupdate ) { - extern ConVar rcbot_tf2_autoupdate_point_time; - updatePoints(); m_fNextCheckMonitoredPoint = engine->Time() + 5.0f; @@ -805,35 +769,34 @@ void CTFObjectiveResource :: think () } // return true if bots should change attack point -bool CTFObjectiveResource :: updateAttackPoints ( int team ) +bool CTFObjectiveResource :: updateAttackPoints (const int team) { int prev; int signature = 0; CTeamControlPointRound *pRound = CTeamFortress2Mod::getCurrentRound(); - TF2PointProb_t *arr; - if ( m_ObjectiveResource.get() == NULL ) // not set up yet + if ( m_ObjectiveResource.get() == nullptr) // not set up yet return false; if ( team == 0 ) return false; - arr = m_ValidPoints[team-2][TF2_POINT_ATTACK]; + TF2PointProb_t* arr = m_ValidPoints[team - 2][TF2_POINT_ATTACK]; // reset array - memset(arr,0,sizeof(TF2PointProb_t)*MAX_CONTROL_POINTS); - memset(arr->iPrev,0xFF,sizeof(int)*MAX_PREVIOUS_POINTS); + std::memset(arr,0,sizeof(TF2PointProb_t)*MAX_CONTROL_POINTS); + std::memset(arr->iPrev,0xFF,sizeof(int)*MAX_PREVIOUS_POINTS); - if ( (team == TF2_TEAM_RED) && (CTeamFortress2Mod::isAttackDefendMap()) ) + if ( team == TF2_TEAM_RED && CTeamFortress2Mod::isAttackDefendMap() ) { // no attacking for red on this map return false; } - for ( int i = 0; i < *m_iNumControlPoints; i ++ ) + for (int i = 0; i < *m_iNumControlPoints; i++) { arr[i].fProb = 1.0f; arr[i].fProbMultiplier = 1.0f; - memset(arr[i].iPrev,0xFF,sizeof(int)*MAX_PREVIOUS_POINTS); + std::memset(arr[i].iPrev,0xFF,sizeof(int)*MAX_PREVIOUS_POINTS); // not visible if ( m_bCPIsVisible[i] == 0 ) @@ -870,11 +833,9 @@ bool CTFObjectiveResource :: updateAttackPoints ( int team ) } else { - int j; - bool bCanCap = true; - for ( j = 0; j < MAX_PREVIOUS_POINTS; j ++ ) + for ( int j = 0; j < MAX_PREVIOUS_POINTS; j ++ ) { // need to go through each previous point to update the array // DONT BREAK!!! @@ -883,7 +844,7 @@ bool CTFObjectiveResource :: updateAttackPoints ( int team ) if ( prev == -1 ) continue; - else if ( GetOwningTeam(prev) != team ) + if ( GetOwningTeam(prev) != team ) bCanCap = false; } @@ -906,10 +867,10 @@ bool CTFObjectiveResource :: updateAttackPoints ( int team ) if ( !CTeamFortress2Mod::isAttackDefendMap() ) { // if its not an attack defend map check previous points are owned - int other = (team==2)?3:2; + const int other = team==2?3:2; // find the base point - int basepoint = GetBaseControlPointForTeam(other); + const int basepoint = GetBaseControlPointForTeam(other); /*if ( i == basepoint ) { @@ -937,7 +898,7 @@ bool CTFObjectiveResource :: updateAttackPoints ( int team ) continue; } - else if ( basepoint == ((*m_iNumControlPoints)-1) ) + if ( basepoint == *m_iNumControlPoints-1 ) { bool allowned = true; // make sure team owns all points below this point @@ -955,7 +916,6 @@ bool CTFObjectiveResource :: updateAttackPoints ( int team ) continue; } - } arr[i].bValid = true; @@ -965,23 +925,23 @@ bool CTFObjectiveResource :: updateAttackPoints ( int team ) } // Flush out less important cap points - for ( int i = 0; i < *m_iNumControlPoints; i ++ ) + for (int i = 0; i < *m_iNumControlPoints; i++) { if ( arr[i].bValid ) { bool bfound = false; // find this point in one of the previous points - for ( int j = 0; j < *m_iNumControlPoints; j ++ ) + for (int j = 0; j < *m_iNumControlPoints; j++) { if ( i == j ) continue; if ( arr[j].bPrev ) { - for ( int k = 0; k < MAX_PREVIOUS_POINTS; k ++ ) + for (const int k : arr[j].iPrev) { - if ( arr[j].iPrev[k] == i ) + if (k == i ) { bfound = true; break; @@ -1008,23 +968,22 @@ bool CTFObjectiveResource :: updateAttackPoints ( int team ) // In Payload give lower numbers higher priority if ( CTeamFortress2Mod::isMapType(TF_MAP_CART) || CTeamFortress2Mod::isMapType(TF_MAP_CARTRACE) ) { - for ( int i = 0; i < *m_iNumControlPoints; i ++ ) + for (int i = 0; i < *m_iNumControlPoints; i++) { if ( arr[i].bValid ) { - arr[i].fProb = (float)(*m_iNumControlPoints+1-i); + arr[i].fProb = static_cast(*m_iNumControlPoints + 1 - i); arr[i].fProb *= arr[i].fProb; // square it } } } - for ( int i = 0; i < *m_iNumControlPoints; i ++ ) + for (int i = 0; i < *m_iNumControlPoints; i++) { - byte j; - byte *barr = (byte*)&(arr[i]); + const byte *barr = reinterpret_cast(&arr[i]); - for ( j = 0; j < sizeof(TF2PointProb_t); j ++ ) - signature = signature + ((barr[j]*(i+1))+j); + for ( byte j = 0; j < sizeof(TF2PointProb_t); j ++ ) + signature = signature + (barr[j]*(i+1)+j); } if ( signature != m_PointSignature[team-2][TF2_POINT_ATTACK] ) @@ -1037,12 +996,12 @@ bool CTFObjectiveResource :: updateAttackPoints ( int team ) } -void CTFObjectiveResource :: updateCaptureTime(int index) +void CTFObjectiveResource :: updateCaptureTime(const int index) { m_fLastCaptureTime[index] = engine->Time(); } -float CTFObjectiveResource :: getLastCaptureTime(int index) +float CTFObjectiveResource :: getLastCaptureTime(const int index) const { return m_fLastCaptureTime[index]; -} \ No newline at end of file +} diff --git a/utils/RCBot2_meta/bot_tf2_points.h b/utils/RCBot2_meta/bot_tf2_points.h index ae95bc88c..88e582113 100644 --- a/utils/RCBot2_meta/bot_tf2_points.h +++ b/utils/RCBot2_meta/bot_tf2_points.h @@ -1,6 +1,13 @@ #ifndef __RCBOT_TF2_POINTS_H__ #define __RCBOT_TF2_POINTS_H__ +#include +#include + +#include "bot_ehandle.h" +#include "edict.h" +#include "ehandle.h" +#include "shareddefs.h" #include "utlmap.h" class CTeamControlPoint; @@ -26,13 +33,13 @@ class CTFGameRulesProxy { MyEHandle m_Resource; - float m_flCapturePointEnableTime; + float m_flCapturePointEnableTime = 0.0f; }; -#define TEAM_ARRAY( index, team ) (index + (team * MAX_CONTROL_POINTS)) +#define TEAM_ARRAY( index, team ) ((index) + ((team) * MAX_CONTROL_POINTS)) -typedef enum ePointAttackDefend_s +typedef enum ePointAttackDefend_s : std::uint8_t { TF2_POINT_DEFEND = 0, TF2_POINT_ATTACK @@ -65,26 +72,26 @@ class CTFObjectiveResource } - bool isWaypointAreaValid ( int wptarea, int waypointflags = 0 ); + bool isWaypointAreaValid ( int wptarea, int waypointflags = 0 ) const; - bool testProbWptArea ( int iWptArea, int iTeam ); + bool testProbWptArea ( int iWptArea, int iTeam ) const; - void debugprint ( void ); + void debugprint () const; void updatePoints(); - bool TeamCanCapPoint( int index, int team ) + bool TeamCanCapPoint(const int index, const int team) { AssertValidIndex(index); return m_bTeamCanCap[ TEAM_ARRAY( index, team ) ]; } // Is the point visible in the objective display - bool IsCPVisible( int index ) + bool IsCPVisible(const int index) const { - return (m_bCPIsVisible[index] == 1); + return m_bCPIsVisible[index] == 1; } - bool IsCPBlocked( int index ) + bool IsCPBlocked(const int index) const { return m_bBlocked[index]; } @@ -94,19 +101,19 @@ class CTFObjectiveResource int getControlPointArea ( edict_t *pPoint ); // Get the world location of this control point - Vector& GetCPPosition( int index ) + Vector& GetCPPosition(const int index) const { return m_vCPPositions[index]; } - int getControlPointWaypoint ( int index ) + int getControlPointWaypoint (const int index) const { return m_iControlPointWpt[index]; } - int NearestArea ( Vector vOrigin ); + int NearestArea (const Vector& vOrigin) const; - int GetCappingTeam( int index ) + int GetCappingTeam(const int index) const { if ( index >= *m_iNumControlPoints ) return TEAM_UNASSIGNED; @@ -114,7 +121,7 @@ class CTFObjectiveResource return m_iCappingTeam[index]; } - int GetTeamInZone( int index ) + int GetTeamInZone(const int index) const { if ( index >= *m_iNumControlPoints ) return TEAM_UNASSIGNED; @@ -123,94 +130,94 @@ class CTFObjectiveResource } // Icons - int GetCPCurrentOwnerIcon( int index, int iOwner ) + int GetCPCurrentOwnerIcon(const int index, const int iOwner) const { return GetIconForTeam( index, iOwner ); } - int GetCPCappingIcon( int index ) + int GetCPCappingIcon(const int index) const { - int iCapper = GetCappingTeam(index); + const int iCapper = GetCappingTeam(index); return GetIconForTeam( index, iCapper ); } // Icon for the specified team - int GetIconForTeam( int index, int team ) + int GetIconForTeam(const int index, const int team) const { return m_iTeamIcons[ TEAM_ARRAY(index,team) ]; } // Overlay for the specified team - int GetOverlayForTeam( int index, int team ) + int GetOverlayForTeam(const int index, const int team) const { return m_iTeamOverlays[ TEAM_ARRAY(index,team) ]; } // Number of players in the area - int GetNumPlayersInArea( int index, int team ) + int GetNumPlayersInArea(const int index, const int team) const { return m_iNumTeamMembers[ TEAM_ARRAY(index,team) ]; } // get the required cappers for the passed team - int GetRequiredCappers( int index, int team ) + int GetRequiredCappers(const int index, const int team) const { return m_iTeamReqCappers[ TEAM_ARRAY(index,team) ]; } // Base Icon for the specified team - int GetBaseIconForTeam( int team ) + int GetBaseIconForTeam(const int team) const { return m_iTeamBaseIcons[ team ]; } - int GetBaseControlPointForTeam( int iTeam ) + int GetBaseControlPointForTeam(const int iTeam) const { return m_iBaseControlPoints[iTeam]; } // Data functions, called to set up the state at the beginning of a round - inline int GetNumControlPoints( void ) + int GetNumControlPoints() const { - if ( m_iNumControlPoints==NULL ) + if ( m_iNumControlPoints== nullptr) return 0; return *m_iNumControlPoints; } - int GetPreviousPointForPoint( int index, int team, int iPrevIndex ) + int GetPreviousPointForPoint(const int index, const int team, const int iPrevIndex) { AssertValidIndex(index); Assert( iPrevIndex >= 0 && iPrevIndex < MAX_PREVIOUS_POINTS ); - int iIntIndex = iPrevIndex + (index * MAX_PREVIOUS_POINTS) + (team * MAX_CONTROL_POINTS * MAX_PREVIOUS_POINTS); + const int iIntIndex = iPrevIndex + index * MAX_PREVIOUS_POINTS + team * MAX_CONTROL_POINTS * MAX_PREVIOUS_POINTS; return m_iPreviousPoints[ iIntIndex ]; } - int GetOwningTeam( int index ) + int GetOwningTeam(const int index) const { if ( index >= *m_iNumControlPoints ) return TEAM_UNASSIGNED; return m_iOwner[index]; - } + } void AssertValidIndex( int index ) { Assert( (0 <= index) && (index <= MAX_CONTROL_POINTS) && (index < *m_iNumControlPoints) ); } - float getLastCaptureTime(int index); + float getLastCaptureTime(int index) const; - bool isCPValidWptArea ( int iWptArea, int iTeam, ePointAttackDefend_s type); - bool isCPValid ( int iCPIndex, int iTeam, ePointAttackDefend_s type); + bool isCPValidWptArea ( int iWptArea, int iTeam, ePointAttackDefend_s type) const; + bool isCPValid ( int iCPIndex, int iTeam, ePointAttackDefend_s type) const; // Mini-rounds data - bool PlayingMiniRounds( void ){ return *m_bPlayingMiniRounds; } - bool IsInMiniRound( int index ) { return m_bInMiniRound[index]; } + bool PlayingMiniRounds() const { return *m_bPlayingMiniRounds; } + bool IsInMiniRound(const int index) const { return m_bInMiniRound[index]; } void updateCaptureTime(int index); void setup (); - bool isInitialised() { return m_bInitialised == true; } + bool isInitialised() const { return m_bInitialised == true; } MyEHandle m_ObjectiveResource; int getRandomValidPointForTeam ( int team, ePointAttackDefend_s type ); @@ -271,22 +278,22 @@ class CTFObjectiveResource bool updateAttackPoints ( int team ); bool updateDefendPoints ( int team ); - inline void resetValidWaypointAreas() + void resetValidWaypointAreas() { memset(m_ValidAreas,0,sizeof(bool)*MAX_CONTROL_POINTS); } - void updateValidWaypointAreas ( void ) + void updateValidWaypointAreas () { resetValidWaypointAreas(); - for ( int i = 0; i < 2; i ++ ) + for (const TF2PointProb_t (&m_ValidPoint)[2][8] : m_ValidPoints) { - for ( int j = 0; j < 2; j ++ ) + for (const TF2PointProb_t (&j)[8] : m_ValidPoint) { for ( int k = 0; k < MAX_CONTROL_POINTS; k ++ ) { // OR - m_ValidAreas[k] = (m_ValidAreas[k] || m_ValidPoints[i][j][k].bValid); + m_ValidAreas[k] = m_ValidAreas[k] || j[k].bValid; } } } @@ -304,8 +311,8 @@ class CTeamRoundTimer float getSetupTime () { - if ((m_Resource.get() != NULL) && m_nSetupTimeLength) - return (float)*m_nSetupTimeLength; + if (m_Resource.get() != nullptr && m_nSetupTimeLength) + return static_cast(*m_nSetupTimeLength); return 0.0f; } @@ -322,7 +329,7 @@ class variant_t { union { - bool bVal; + bool bVal = false; string_t iszVal; int iVal; float flVal; @@ -339,7 +346,7 @@ class COutputEvent { variant_t m_Value; CEventAction *m_ActionList; - DECLARE_SIMPLE_DATADESC(); + DECLARE_SIMPLE_DATADESC() }; class CTeamControlPointMaster @@ -419,25 +426,27 @@ class CTeamControlPoint iszOverlay = NULL_STRING; iPlayersRequired = 0; iTimedPoints = 0; - for ( int i = 0; i < MAX_PREVIOUS_POINTS; i++ ) + // Initialize the raw array using a loop + for (string_t& i : iszPreviousPoint) { - iszPreviousPoint[i] = NULL_STRING; + i = NULL_STRING; } iTeamPoseParam = 0; } - string_t iszCapSound; string_t iszModel; + string_t iszIcon; + string_t iszOverlay; + string_t iszPreviousPoint[MAX_PREVIOUS_POINTS]; + int iModelBodygroup; int iTeamPoseParam; int iIcon; - string_t iszIcon; int iOverlay; - string_t iszOverlay; int iPlayersRequired; int iTimedPoints; - string_t iszPreviousPoint[MAX_PREVIOUS_POINTS]; }; + CUtlVector m_TeamData; CBaseEntityOutput m_OnCapReset; diff --git a/utils/RCBot2_meta/bot_usercmd.cpp b/utils/RCBot2_meta/bot_usercmd.cpp deleted file mode 100644 index 780952045..000000000 --- a/utils/RCBot2_meta/bot_usercmd.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * This file is part of RCBot. - * - * RCBot by Paul Murphy adapted from Botman's HPB Bot 2 template. - * - * RCBot is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * RCBot is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with RCBot; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * In addition, as a special exception, the author gives permission to - * link the code of this program with the Half-Life Game Engine ("HL - * Engine") and Modified Game Libraries ("MODs") developed by Valve, - * L.L.C ("Valve"). You must obey the GNU General Public License in all - * respects for all of the code used other than the HL Engine and MODs - * from Valve. If you modify this file, you may extend this exception - * to your version of the file, but you are not obligated to do so. If - * you do not wish to do so, delete this exception statement from your - * version. - * - */ -//====================================================================================// -// -// HPB_bot2_usercmd.cpp - bot source code file (Copyright 2004, Jeffrey "botman" Broome) -// -//====================================================================================// - -#include - -#include "interface.h" -#include "filesystem.h" -#include "engine/iserverplugin.h" -#include "iplayerinfo.h" -#include "vplane.h" -#include "eiface.h" -#include "igameevents.h" -#ifdef __linux__ -#include "shareddefs.h" //bir3yk -#endif -#include "usercmd.h" -#include "bitbuf.h" - -#include "bot.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include "tier0/memdbgon.h" - -void WriteUsercmd( bf_write *buf, CUserCmd *cmd ) -{ - buf->WriteOneBit( 0 ); // command_number - - buf->WriteOneBit( 0 ); // tick_count - - buf->WriteOneBit( 1 ); - buf->WriteBitAngle( cmd->viewangles.x, 16 ); // viewangles[0] - buf->WriteOneBit( 1 ); - buf->WriteBitAngle( cmd->viewangles.y, 16 ); // viewangles[1] - buf->WriteOneBit( 1 ); - buf->WriteBitAngle( cmd->viewangles.z, 8 ); // viewangles[2] - - buf->WriteOneBit( 1 ); - buf->WriteSBitLong( cmd->forwardmove, 16 ); - - buf->WriteOneBit( 1 ); - buf->WriteSBitLong( cmd->sidemove, 16 ); - - buf->WriteOneBit( 1 ); - buf->WriteSBitLong( cmd->upmove, 16 ); - - buf->WriteOneBit( 1 ); - buf->WriteUBitLong( cmd->buttons, 32 ); - - buf->WriteOneBit( 1 ); - buf->WriteUBitLong( cmd->impulse, 8 ); - - buf->WriteOneBit( 1 ); - buf->WriteUBitLong( cmd->weaponselect, MAX_EDICT_BITS ); - - buf->WriteOneBit( 0 ); // weaponsubtype - - buf->WriteOneBit( 0 ); // mousedx - buf->WriteOneBit( 0 ); // mousedy -} diff --git a/utils/RCBot2_meta/bot_utility.cpp b/utils/RCBot2_meta/bot_utility.cpp index c96782549..7241b488e 100644 --- a/utils/RCBot2_meta/bot_utility.cpp +++ b/utils/RCBot2_meta/bot_utility.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * part of https://rcbot2.svn.sourceforge.net/svnroot/rcbot2 * @@ -39,7 +41,7 @@ #include "bot_mods.h" #include "bot_fortress.h" -const char *g_szUtils[BOT_UTIL_MAX+1] = +const char* g_szUtils[BOT_UTIL_MAX + 1] = { "BOT_UTIL_BUILDSENTRY", "BOT_UTIL_BUILDDISP", @@ -70,16 +72,16 @@ const char *g_szUtils[BOT_UTIL_MAX+1] = "BOT_UTIL_ATTACK_POINT", "BOT_UTIL_DEFEND_POINT", "BOT_UTIL_DEFEND_FLAG", - "BOT_UTIL_ENGI_LOOK_AFTER_SENTRY", - "BOT_UTIL_DEFEND_FLAG_LASTKNOWN", - "BOT_UTIL_PUSH_PAYLOAD_BOMB", - "BOT_UTIL_DEFEND_PAYLOAD_BOMB", + "BOT_UTIL_ENGI_LOOK_AFTER_SENTRY", + "BOT_UTIL_DEFEND_FLAG_LASTKNOWN", + "BOT_UTIL_PUSH_PAYLOAD_BOMB", + "BOT_UTIL_DEFEND_PAYLOAD_BOMB", "BOT_UTIL_MEDIC_HEAL", "BOT_UTIL_MEDIC_HEAL_LAST", "BOT_UTIL_MEDIC_FINDPLAYER", "BOT_UTIL_SAP_NEAREST_SENTRY", - "BOT_UTIL_SAP_ENEMY_SENTRY", - "BOT_UTIL_SAP_LASTENEMY_SENTRY", + "BOT_UTIL_SAP_ENEMY_SENTRY", + "BOT_UTIL_SAP_LASTENEMY_SENTRY", "BOT_UTIL_SAP_DISP", "BOT_UTIL_BACKSTAB", "BOT_UTIL_REMOVE_SENTRY_SAPPER", @@ -92,64 +94,72 @@ const char *g_szUtils[BOT_UTIL_MAX+1] = "BOT_UTIL_DEMO_STICKYTRAP_FLAG_LASTKNOWN", "BOT_UTIL_DEMO_STICKYTRAP_PL", "BOT_UTIL_REMOVE_TMTELE_SAPPER", - "BOT_UTIL_SAP_NEAREST_TELE", - "BOT_UTIL_SAP_ENEMY_TELE", - "BOT_UTIL_SAP_LASTENEMY_TELE", + "BOT_UTIL_SAP_NEAREST_TELE", + "BOT_UTIL_SAP_ENEMY_TELE", + "BOT_UTIL_SAP_LASTENEMY_TELE", "BOT_UTIL_GOTO_NEST", "BOT_UTIL_MESSAROUND", - "BOT_UTIL_ENGI_MOVE_SENTRY", - "BOT_UTIL_ENGI_MOVE_DISP", - "BOT_UTIL_ENGI_MOVE_ENTRANCE", - "BOT_UTIL_ENGI_MOVE_EXIT", - "BOT_UTIL_ENGI_DESTROY_SENTRY", - "BOT_UTIL_ENGI_DESTROY_DISP", - "BOT_UTIL_ENGI_DESTROY_ENTRANCE", - "BOT_UTIL_ENGI_DESTROY_EXIT", - "BOT_UTIL_HIDE_FROM_ENEMY", - "BOT_UTIL_MEDIC_FINDPLAYER_AT_SPAWN", - "BOT_UTIL_HL2DM_GRAVIGUN_PICKUP", - "BOT_UTIL_HL2DM_FIND_ARMOR", - "BOT_UTIL_FIND_LAST_ENEMY", - "BOT_UTIL_HL2DM_USE_CHARGER", - "BOT_UTIL_HL2DM_USE_HEALTH_CHARGER", - "BOT_UTIL_THROW_GRENADE", - "BOT_UTIL_PICKUP_WEAPON", - "BOT_UTIL_ATTACK_NEAREST_POINT", - "BOT_UTIL_DEFEND_NEAREST_POINT", - "BOT_UTIL_DEFEND_BOMB", - "BOT_UTIL_DEFUSE_BOMB", - "BOT_UTIL_PLANT_BOMB", - "BOT_UTIL_PLANT_NEAREST_BOMB", - "BOT_UTIL_DEFUSE_NEAREST_BOMB", - "BOT_UTIL_DEFEND_NEAREST_BOMB", - "BOT_UTIL_PICKUP_BOMB", - "BOT_UTIL_PIPE_NEAREST_SENTRY", - "BOT_UTIL_PIPE_LAST_ENEMY", - "BOT_UTIL_PIPE_LAST_ENEMY_SENTRY", - "BOT_UTIL_DOD_PICKUP_OBJ", - "BOT_UTIL_HL2DM_USE_CRATE", - "BOT_UTIL_PLACE_BUILDING", - "BOT_UTIL_SPYCHECK_AIR", - "BOT_UTIL_FIND_MEDIC_FOR_HEALTH", - "BOT_UTIL_FIND_SQUAD_LEADER", - "BOT_UTIL_FOLLOW_SQUAD_LEADER", - "BOT_UTIL_ATTACK_SENTRY", - "BOT_UTIL_SPAM_LAST_ENEMY", - "BOT_UTIL_SPAM_NEAREST_SENTRY", - "BOT_UTIL_SPAM_LAST_ENEMY_SENTRY", - "BOT_UTIL_SAP_NEAREST_DISP", - "BOT_UTIL_SAP_ENEMY_DISP", - "BOT_UTIL_SAP_LASTENEMY_DISP", - "BOT_UTIL_BUILDTELENT_SPAWN", - "BOT_UTIL_INVESTIGATE_POINT", - "BOT_UTIL_COVER_POINT", - "BOT_UTIL_SNIPE_POINT", - "BOT_UTIL_MOVEUP_MG", - "BOT_UTIL_SNIPE_CROSSBOW", -"BOT_UTIL_MAX" + "BOT_UTIL_ENGI_MOVE_SENTRY", + "BOT_UTIL_ENGI_MOVE_DISP", + "BOT_UTIL_ENGI_MOVE_ENTRANCE", + "BOT_UTIL_ENGI_MOVE_EXIT", + "BOT_UTIL_ENGI_DESTROY_SENTRY", + "BOT_UTIL_ENGI_DESTROY_DISP", + "BOT_UTIL_ENGI_DESTROY_ENTRANCE", + "BOT_UTIL_ENGI_DESTROY_EXIT", + "BOT_UTIL_HIDE_FROM_ENEMY", + "BOT_UTIL_MEDIC_FINDPLAYER_AT_SPAWN", + "BOT_UTIL_HL2DM_GRAVIGUN_PICKUP", + "BOT_UTIL_HL2DM_FIND_ARMOR", + "BOT_UTIL_FIND_LAST_ENEMY", + "BOT_UTIL_HL2DM_USE_CHARGER", + "BOT_UTIL_HL2DM_USE_HEALTH_CHARGER", + "BOT_UTIL_THROW_GRENADE", + "BOT_UTIL_PICKUP_WEAPON", + "BOT_UTIL_ATTACK_NEAREST_POINT", + "BOT_UTIL_DEFEND_NEAREST_POINT", + "BOT_UTIL_DEFEND_BOMB", + "BOT_UTIL_DEFUSE_BOMB", + "BOT_UTIL_PLANT_BOMB", + "BOT_UTIL_PLANT_NEAREST_BOMB", + "BOT_UTIL_DEFUSE_NEAREST_BOMB", + "BOT_UTIL_DEFEND_NEAREST_BOMB", + "BOT_UTIL_PICKUP_BOMB", + "BOT_UTIL_PIPE_NEAREST_SENTRY", + "BOT_UTIL_PIPE_LAST_ENEMY", + "BOT_UTIL_PIPE_LAST_ENEMY_SENTRY", + "BOT_UTIL_DOD_PICKUP_OBJ", + "BOT_UTIL_HL2DM_USE_CRATE", + "BOT_UTIL_PLACE_BUILDING", + "BOT_UTIL_SPYCHECK_AIR", + "BOT_UTIL_FIND_MEDIC_FOR_HEALTH", + "BOT_UTIL_FIND_SQUAD_LEADER", + "BOT_UTIL_FOLLOW_SQUAD_LEADER", + "BOT_UTIL_ATTACK_SENTRY", + "BOT_UTIL_SPAM_LAST_ENEMY", + "BOT_UTIL_SPAM_NEAREST_SENTRY", + "BOT_UTIL_SPAM_LAST_ENEMY_SENTRY", + "BOT_UTIL_SAP_NEAREST_DISP", + "BOT_UTIL_SAP_ENEMY_DISP", + "BOT_UTIL_SAP_LASTENEMY_DISP", + "BOT_UTIL_BUILDTELENT_SPAWN", + "BOT_UTIL_INVESTIGATE_POINT", + "BOT_UTIL_COVER_POINT", + "BOT_UTIL_SNIPE_POINT", + "BOT_UTIL_MOVEUP_MG", + "BOT_UTIL_SNIPE_CROSSBOW", + "BOT_UTIL_BUY", + "BOT_UTIL_WAIT_LAST_ENEMY", + "BOT_UTIL_ENGAGE_ENEMY", + "BOT_UTIL_SEARCH_FOR_BOMB", + "BOT_UTIL_RESCUE", + "BOT_UTIL_GUARD_RESCUE_ZONE", + "BOT_UTIL_GET_HOSTAGE", + "BOT_UTIL_MAX" }; -CBotUtility :: CBotUtility ( CBot *pBot, eBotAction id, bool bCanDo, float fUtil, CBotWeapon *pWeapon, int iData, Vector vec ) +CBotUtility::CBotUtility(CBot* pBot, const eBotAction id, const bool bCanDo, const float fUtil, + CBotWeapon* pWeapon, const int iData, const Vector& vec) : m_vVector(vec) { m_iData = iData; m_fUtility = fUtil; @@ -157,78 +167,66 @@ CBotUtility :: CBotUtility ( CBot *pBot, eBotAction id, bool bCanDo, float fUtil m_bCanDo = bCanDo; m_pBot = pBot; m_pWeapon = pWeapon; - m_vVector = vec; - if ( m_pBot && m_pBot->isTF2() ) + if (m_pBot && m_pBot->isTF2()) { - int iClass = CClassInterface::getTF2Class(pBot->getEdict()); + const int iClass = CClassInterface::getTF2Class(pBot->getEdict()); - if ( CTeamFortress2Mod::isAttackDefendMap() && (m_pBot->getTeam() == TF2_TEAM_BLUE) ) - m_fUtility += randomFloat(CRCBotTF2UtilFile::m_fUtils[BOT_ATT_UTIL][id][iClass].min,CRCBotTF2UtilFile::m_fUtils[BOT_ATT_UTIL][id][iClass].max); + if (CTeamFortress2Mod::isAttackDefendMap() && m_pBot->getTeam() == TF2_TEAM_BLUE) + m_fUtility += randomFloat(CRCBotTF2UtilFile::m_fUtils[BOT_ATT_UTIL][id][iClass].min, CRCBotTF2UtilFile::m_fUtils[BOT_ATT_UTIL][id][iClass].max); else - m_fUtility += randomFloat(CRCBotTF2UtilFile::m_fUtils[BOT_NORM_UTIL][id][iClass].min,CRCBotTF2UtilFile::m_fUtils[BOT_NORM_UTIL][id][iClass].max); + m_fUtility += randomFloat(CRCBotTF2UtilFile::m_fUtils[BOT_NORM_UTIL][id][iClass].min, CRCBotTF2UtilFile::m_fUtils[BOT_NORM_UTIL][id][iClass].max); } } // Execute a list of possible actions and put them into order of available actions against utility -void CBotUtilities :: execute () +void CBotUtilities::execute() { - unsigned int i = 0; - CBotUtility *pUtil; - float fUtil; + m_pBest.head = nullptr; - util_node_t *temp; - util_node_t *pnew; - util_node_t *prev; - - m_pBest.head = NULL; - - for ( i = 0; i < m_Utilities.size(); i ++ ) + for (CBotUtility& m_Utility : m_Utilities) { - pUtil = &(m_Utilities[i]); - fUtil = pUtil->getUtility(); + CBotUtility* pUtil = &m_Utility; + const float fUtil = pUtil->getUtility(); // if bot can do this action - if ( pUtil->canDo() ) - { + if (pUtil->canDo()) + { // add to list - temp = m_pBest.head; + util_node_t* temp = m_pBest.head; // put in correct order by making a linked list - pnew = (util_node_t*)malloc(sizeof(util_node_t)); + util_node_t* pnew = static_cast(std::malloc(sizeof(util_node_t))); - if ( pnew != NULL ) + if (pnew != nullptr) { pnew->util = pUtil; - pnew->next = NULL; - prev = NULL; + pnew->next = nullptr; - if ( temp ) + if (temp) { - while ( temp ) + util_node_t* prev = nullptr; + while (temp) { // put into correct position - if ( fUtil > temp->util->getUtility() ) + if (fUtil > temp->util->getUtility()) { - if ( temp == m_pBest.head ) + if (temp == m_pBest.head) { pnew->next = temp; m_pBest.head = pnew; break; } - else - { - prev->next = pnew; - pnew->next = temp; - break; - } + prev->next = pnew; + pnew->next = temp; + break; } prev = temp; temp = temp->next; } - if ( pnew->next == NULL ) + if (pnew->next == nullptr) prev->next = pnew; } else @@ -240,36 +238,32 @@ void CBotUtilities :: execute () //return pBest; } -void CBotUtilities :: freeMemory () +void CBotUtilities::freeMemory() { - util_node_t *temp; + util_node_t* temp; m_Utilities.clear(); // FREE LIST - while ( (temp = m_pBest.head) != NULL ) + while ((temp = m_pBest.head) != nullptr) { - temp = m_pBest.head; + //temp = m_pBest.head; m_pBest.head = m_pBest.head->next; - free(temp); + std::free(temp); } } -CBotUtility *CBotUtilities :: nextBest () +CBotUtility* CBotUtilities::nextBest() { - CBotUtility *pBest; - util_node_t *temp; - - if ( m_pBest.head == NULL ) - return NULL; + if (m_pBest.head == nullptr) + return nullptr; - pBest = m_pBest.head->util; + CBotUtility* pBest = m_pBest.head->util; - temp = m_pBest.head; + util_node_t* temp = m_pBest.head; m_pBest.head = m_pBest.head->next; - free(temp); + std::free(temp); return pBest; - } \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_utility.h b/utils/RCBot2_meta/bot_utility.h index f2111f386..b879e841f 100644 --- a/utils/RCBot2_meta/bot_utility.h +++ b/utils/RCBot2_meta/bot_utility.h @@ -34,188 +34,193 @@ #ifndef __BOT_UTILITY_H__ #define __BOT_UTILITY_H__ -#include "bot_genclass.h" +#include "vector.h" #include -using namespace std; class CBot; class CBotWeapon; -typedef enum +typedef enum : std::uint8_t { - BOT_UTIL_BUILDSENTRY = 0, - BOT_UTIL_BUILDDISP, - BOT_UTIL_BUILDTELENT, - BOT_UTIL_BUILDTELEXT, - BOT_UTIL_UPGSENTRY, - BOT_UTIL_UPGDISP, - BOT_UTIL_UPGTELENT, - BOT_UTIL_UPGTELEXT, - BOT_UTIL_UPGTMSENTRY, - BOT_UTIL_UPGTMDISP, - BOT_UTIL_UPGTMTELENT, - BOT_UTIL_UPGTMTELEXT, - BOT_UTIL_GOTODISP, - BOT_UTIL_GOTORESUPPLY_FOR_HEALTH, - BOT_UTIL_GETAMMOKIT, - BOT_UTIL_GETAMMOTMDISP, - BOT_UTIL_GETAMMODISP, - BOT_UTIL_GETFLAG, - BOT_UTIL_GETHEALTHKIT, - BOT_UTIL_GETFLAG_LASTKNOWN, - BOT_UTIL_SNIPE, - BOT_UTIL_ROAM, - BOT_UTIL_CAPTURE_FLAG, - BOT_UTIL_GOTORESUPPLY_FOR_AMMO, - BOT_UTIL_FIND_NEAREST_HEALTH, - BOT_UTIL_FIND_NEAREST_AMMO, - BOT_UTIL_ATTACK_POINT, - BOT_UTIL_DEFEND_POINT, - BOT_UTIL_DEFEND_FLAG, - BOT_UTIL_ENGI_LOOK_AFTER_SENTRY, - BOT_UTIL_DEFEND_FLAG_LASTKNOWN, - BOT_UTIL_PUSH_PAYLOAD_BOMB, - BOT_UTIL_DEFEND_PAYLOAD_BOMB, - BOT_UTIL_MEDIC_HEAL, // heal someone - BOT_UTIL_MEDIC_HEAL_LAST, // find the player I was healing last - BOT_UTIL_MEDIC_FINDPLAYER, // find player who called medic - BOT_UTIL_SAP_NEAREST_SENTRY, - BOT_UTIL_SAP_ENEMY_SENTRY, - BOT_UTIL_SAP_LASTENEMY_SENTRY, - BOT_UTIL_SAP_DISP, - BOT_UTIL_BACKSTAB, - BOT_UTIL_REMOVE_SENTRY_SAPPER, - BOT_UTIL_REMOVE_DISP_SAPPER, - BOT_UTIL_REMOVE_TMSENTRY_SAPPER, - BOT_UTIL_REMOVE_TMDISP_SAPPER, - BOT_UTIL_DEMO_STICKYTRAP_LASTENEMY, - BOT_UTIL_DEMO_STICKYTRAP_POINT, - BOT_UTIL_DEMO_STICKYTRAP_FLAG, - BOT_UTIL_DEMO_STICKYTRAP_FLAG_LASTKNOWN, - BOT_UTIL_DEMO_STICKYTRAP_PL, - BOT_UTIL_REMOVE_TMTELE_SAPPER, - BOT_UTIL_SAP_NEAREST_TELE, - BOT_UTIL_SAP_ENEMY_TELE, - BOT_UTIL_SAP_LASTENEMY_TELE, - BOT_UTIL_GOTO_NEST, // camp , regain health or allies - BOT_UTIL_MESSAROUND, - BOT_UTIL_ENGI_MOVE_SENTRY, - BOT_UTIL_ENGI_MOVE_DISP, - BOT_UTIL_ENGI_MOVE_ENTRANCE, - BOT_UTIL_ENGI_MOVE_EXIT, - BOT_UTIL_ENGI_DESTROY_SENTRY, - BOT_UTIL_ENGI_DESTROY_DISP, - BOT_UTIL_ENGI_DESTROY_ENTRANCE, - BOT_UTIL_ENGI_DESTROY_EXIT, - BOT_UTIL_HIDE_FROM_ENEMY, - BOT_UTIL_MEDIC_FINDPLAYER_AT_SPAWN, // find team players around spawn area - BOT_UTIL_HL2DM_GRAVIGUN_PICKUP, - BOT_UTIL_HL2DM_FIND_ARMOR, - BOT_UTIL_FIND_LAST_ENEMY, - BOT_UTIL_HL2DM_USE_CHARGER, - BOT_UTIL_HL2DM_USE_HEALTH_CHARGER, - BOT_UTIL_THROW_GRENADE, - BOT_UTIL_PICKUP_WEAPON, - BOT_UTIL_ATTACK_NEAREST_POINT, - BOT_UTIL_DEFEND_NEAREST_POINT, - BOT_UTIL_DEFEND_BOMB, - BOT_UTIL_DEFUSE_BOMB, - BOT_UTIL_PLANT_BOMB, - BOT_UTIL_PLANT_NEAREST_BOMB, - BOT_UTIL_DEFUSE_NEAREST_BOMB, - BOT_UTIL_DEFEND_NEAREST_BOMB, - BOT_UTIL_PICKUP_BOMB, - BOT_UTIL_PIPE_NEAREST_SENTRY, - BOT_UTIL_PIPE_LAST_ENEMY, - BOT_UTIL_PIPE_LAST_ENEMY_SENTRY, - BOT_UTIL_DOD_PICKUP_OBJ, - BOT_UTIL_HL2DM_USE_CRATE, - BOT_UTIL_PLACE_BUILDING, - BOT_UTIL_SPYCHECK_AIR, - BOT_UTIL_FIND_MEDIC_FOR_HEALTH, - BOT_UTIL_FIND_SQUAD_LEADER, - BOT_UTIL_FOLLOW_SQUAD_LEADER, - BOT_UTIL_ATTACK_SENTRY, - BOT_UTIL_SPAM_LAST_ENEMY, - BOT_UTIL_SPAM_NEAREST_SENTRY, - BOT_UTIL_SPAM_LAST_ENEMY_SENTRY, - BOT_UTIL_SAP_NEAREST_DISP, - BOT_UTIL_SAP_ENEMY_DISP, - BOT_UTIL_SAP_LASTENEMY_DISP, - BOT_UTIL_BUILDTELENT_SPAWN, - BOT_UTIL_INVESTIGATE_POINT, - BOT_UTIL_COVER_POINT, - BOT_UTIL_SNIPE_POINT, - BOT_UTIL_MOVEUP_MG, - BOT_UTIL_SNIPE_CROSSBOW, - BOT_UTIL_MAX + BOT_UTIL_BUILDSENTRY = 0, + BOT_UTIL_BUILDDISP, + BOT_UTIL_BUILDTELENT, + BOT_UTIL_BUILDTELEXT, + BOT_UTIL_UPGSENTRY, + BOT_UTIL_UPGDISP, + BOT_UTIL_UPGTELENT, + BOT_UTIL_UPGTELEXT, + BOT_UTIL_UPGTMSENTRY, + BOT_UTIL_UPGTMDISP, + BOT_UTIL_UPGTMTELENT, + BOT_UTIL_UPGTMTELEXT, + BOT_UTIL_GOTODISP, + BOT_UTIL_GOTORESUPPLY_FOR_HEALTH, + BOT_UTIL_GETAMMOKIT, + BOT_UTIL_GETAMMOTMDISP, + BOT_UTIL_GETAMMODISP, + BOT_UTIL_GETFLAG, + BOT_UTIL_GETHEALTHKIT, + BOT_UTIL_GETFLAG_LASTKNOWN, + BOT_UTIL_SNIPE, + BOT_UTIL_ROAM, + BOT_UTIL_CAPTURE_FLAG, + BOT_UTIL_GOTORESUPPLY_FOR_AMMO, + BOT_UTIL_FIND_NEAREST_HEALTH, + BOT_UTIL_FIND_NEAREST_AMMO, + BOT_UTIL_ATTACK_POINT, + BOT_UTIL_DEFEND_POINT, + BOT_UTIL_DEFEND_FLAG, + BOT_UTIL_ENGI_LOOK_AFTER_SENTRY, + BOT_UTIL_DEFEND_FLAG_LASTKNOWN, + BOT_UTIL_PUSH_PAYLOAD_BOMB, + BOT_UTIL_DEFEND_PAYLOAD_BOMB, + BOT_UTIL_MEDIC_HEAL, // heal someone + BOT_UTIL_MEDIC_HEAL_LAST, // find the player I was healing last + BOT_UTIL_MEDIC_FINDPLAYER, // find player who called medic + BOT_UTIL_SAP_NEAREST_SENTRY, + BOT_UTIL_SAP_ENEMY_SENTRY, + BOT_UTIL_SAP_LASTENEMY_SENTRY, + BOT_UTIL_SAP_DISP, + BOT_UTIL_BACKSTAB, + BOT_UTIL_REMOVE_SENTRY_SAPPER, + BOT_UTIL_REMOVE_DISP_SAPPER, + BOT_UTIL_REMOVE_TMSENTRY_SAPPER, + BOT_UTIL_REMOVE_TMDISP_SAPPER, + BOT_UTIL_DEMO_STICKYTRAP_LASTENEMY, + BOT_UTIL_DEMO_STICKYTRAP_POINT, + BOT_UTIL_DEMO_STICKYTRAP_FLAG, + BOT_UTIL_DEMO_STICKYTRAP_FLAG_LASTKNOWN, + BOT_UTIL_DEMO_STICKYTRAP_PL, + BOT_UTIL_REMOVE_TMTELE_SAPPER, + BOT_UTIL_SAP_NEAREST_TELE, + BOT_UTIL_SAP_ENEMY_TELE, + BOT_UTIL_SAP_LASTENEMY_TELE, + BOT_UTIL_GOTO_NEST, // camp , regain health or allies + BOT_UTIL_MESSAROUND, + BOT_UTIL_ENGI_MOVE_SENTRY, + BOT_UTIL_ENGI_MOVE_DISP, + BOT_UTIL_ENGI_MOVE_ENTRANCE, + BOT_UTIL_ENGI_MOVE_EXIT, + BOT_UTIL_ENGI_DESTROY_SENTRY, + BOT_UTIL_ENGI_DESTROY_DISP, + BOT_UTIL_ENGI_DESTROY_ENTRANCE, + BOT_UTIL_ENGI_DESTROY_EXIT, + BOT_UTIL_HIDE_FROM_ENEMY, + BOT_UTIL_MEDIC_FINDPLAYER_AT_SPAWN, // find team players around spawn area + BOT_UTIL_HL2DM_GRAVIGUN_PICKUP, + BOT_UTIL_HL2DM_FIND_ARMOR, + BOT_UTIL_FIND_LAST_ENEMY, + BOT_UTIL_HL2DM_USE_CHARGER, + BOT_UTIL_HL2DM_USE_HEALTH_CHARGER, + BOT_UTIL_THROW_GRENADE, + BOT_UTIL_PICKUP_WEAPON, + BOT_UTIL_ATTACK_NEAREST_POINT, + BOT_UTIL_DEFEND_NEAREST_POINT, + BOT_UTIL_DEFEND_BOMB, + BOT_UTIL_DEFUSE_BOMB, + BOT_UTIL_PLANT_BOMB, + BOT_UTIL_PLANT_NEAREST_BOMB, + BOT_UTIL_DEFUSE_NEAREST_BOMB, + BOT_UTIL_DEFEND_NEAREST_BOMB, + BOT_UTIL_PICKUP_BOMB, + BOT_UTIL_PIPE_NEAREST_SENTRY, + BOT_UTIL_PIPE_LAST_ENEMY, + BOT_UTIL_PIPE_LAST_ENEMY_SENTRY, + BOT_UTIL_DOD_PICKUP_OBJ, + BOT_UTIL_HL2DM_USE_CRATE, + BOT_UTIL_PLACE_BUILDING, + BOT_UTIL_SPYCHECK_AIR, + BOT_UTIL_FIND_MEDIC_FOR_HEALTH, + BOT_UTIL_FIND_SQUAD_LEADER, + BOT_UTIL_FOLLOW_SQUAD_LEADER, + BOT_UTIL_ATTACK_SENTRY, + BOT_UTIL_SPAM_LAST_ENEMY, + BOT_UTIL_SPAM_NEAREST_SENTRY, + BOT_UTIL_SPAM_LAST_ENEMY_SENTRY, + BOT_UTIL_SAP_NEAREST_DISP, + BOT_UTIL_SAP_ENEMY_DISP, + BOT_UTIL_SAP_LASTENEMY_DISP, + BOT_UTIL_BUILDTELENT_SPAWN, + BOT_UTIL_INVESTIGATE_POINT, + BOT_UTIL_COVER_POINT, + BOT_UTIL_SNIPE_POINT, + BOT_UTIL_MOVEUP_MG, + BOT_UTIL_SNIPE_CROSSBOW, + BOT_UTIL_BUY, + BOT_UTIL_WAIT_LAST_ENEMY, + BOT_UTIL_ENGAGE_ENEMY, + BOT_UTIL_SEARCH_FOR_BOMB, + BOT_UTIL_RESCUE, + BOT_UTIL_GUARD_RESCUE_ZONE, + BOT_UTIL_GET_HOSTAGE, + BOT_UTIL_MAX }eBotAction; -extern const char *g_szUtils[BOT_UTIL_MAX+1]; +extern const char* g_szUtils[BOT_UTIL_MAX + 1]; class CBotUtility { public: - CBotUtility ( CBot *pBot, eBotAction id, bool bCanDo, float fUtil, CBotWeapon *pWeapon = NULL, int iData = 0, Vector vec = Vector(0,0,0) ); + CBotUtility(CBot* pBot, eBotAction id, bool bCanDo, float fUtil, CBotWeapon* pWeapon = nullptr, int iData = 0, const Vector& vec = Vector(0, 0, 0)); - inline float getUtility () { return m_fUtility; } + float getUtility() const { return m_fUtility; } - inline eBotAction getId () { return m_id; } + eBotAction getId() const { return m_id; } - inline bool canDo () { return m_bCanDo; } + bool canDo() const { return m_bCanDo; } - inline CBotWeapon *getWeaponChoice () { return m_pWeapon; } + CBotWeapon* getWeaponChoice() const { return m_pWeapon; } - inline int getIntData () { return m_iData; } + int getIntData() const { return m_iData; } - inline Vector getVectorData () { return m_vVector; } + Vector getVectorData() { return m_vVector; } private: - int m_iData; - float m_fUtility; - bool m_bCanDo; - eBotAction m_id; - CBot *m_pBot; - CBotWeapon *m_pWeapon; - Vector m_vVector; + CBot* m_pBot; // Bot pointer + CBotWeapon* m_pWeapon; // Weapon choice + Vector m_vVector; // Vector data + float m_fUtility; // Utility value + int m_iData; // Integer data + eBotAction m_id; // Bot action ID + bool m_bCanDo; // Can perform action }; - typedef struct util_node_s { - CBotUtility *util; - struct util_node_s *next; + CBotUtility* util; + util_node_s* next; }util_node_t; - typedef struct { - util_node_t *head; + util_node_t* head; }util_list; class CBotUtilities { public: - CBotUtilities () + CBotUtilities() { - m_pBest.head = NULL; + m_pBest.head = nullptr; } - void freeMemory (); + void freeMemory(); - inline void addUtility ( CBotUtility p ) { if ( p.canDo() ) { m_Utilities.push_back(p); } } + void addUtility(CBotUtility p) { if (p.canDo()) { m_Utilities.emplace_back(p); } } - void execute (); + void execute(); - CBotUtility *nextBest (); + CBotUtility* nextBest(); private: - vector m_Utilities; + std::vector m_Utilities; util_list m_pBest; }; + #define ADD_UTILITY_WEAPON_DATA_VECTOR(utilname,condition,utility,weapon,data,vector) if ( m_fUtilTimes[utilname] < engine->Time()) { if ( condition ) { utils.addUtility(CBotUtility(this,utilname,true,utility,weapon,data,vector)); } } #define ADD_UTILITY_DATA_VECTOR(utilname,condition,utility,data,vector) if ( m_fUtilTimes[utilname] < engine->Time()) { if ( condition ) { utils.addUtility(CBotUtility(this,utilname,true,utility,NULL,data,vector)); } } #define ADD_UTILITY_WEAPON_DATA(utilname,condition,utility,weapon,data) if ( m_fUtilTimes[utilname] < engine->Time()) { if ( condition ) { utils.addUtility(CBotUtility(this,utilname,true,utility,weapon,data)); } } @@ -223,5 +228,4 @@ class CBotUtilities #define ADD_UTILITY_WEAPON(utilname,condition,utility,weapon) if ( m_fUtilTimes[utilname] < engine->Time()) { if ( condition ) { utils.addUtility(CBotUtility(this,utilname,true,utility,weapon)); } } #define ADD_UTILITY(utilname,condition,utility) if ( m_fUtilTimes[utilname] < engine->Time()) { if ( condition ) { utils.addUtility(CBotUtility(this,utilname,true,utility)); } } - #endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_valve_plugin.h b/utils/RCBot2_meta/bot_valve_plugin.h deleted file mode 100644 index f34a49468..000000000 --- a/utils/RCBot2_meta/bot_valve_plugin.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef __BOT_VALVE_PLUGIN_H__ -#define __BOT_VALVE_PLUGIN_H__ - -#include "GameEventListener.h" -#include "iserverplugin.h" -//--------------------------------------------------------------------------------- -// Purpose: a sample 3rd party plugin class -//--------------------------------------------------------------------------------- -class CRCBotPlugin : public IServerPluginCallbacks, public IGameEventListener -{ -public: - CRCBotPlugin(); - ~CRCBotPlugin(); - - // IServerPluginCallbacks methods - virtual bool Load( CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory ); - virtual void Unload( void ); - virtual void Pause( void ); - virtual void UnPause( void ); - virtual const char *GetPluginDescription( void ); - virtual void LevelInit( char const *pMapName ); - virtual void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax ); - virtual void GameFrame( bool simulating ); - // Called once per simulation frame on the final tick - virtual void PreClientUpdate( bool simulating ); - virtual void LevelShutdown( void ); - virtual void ClientActive( edict_t *pEntity ); - virtual void ClientDisconnect( edict_t *pEntity ); - virtual void ClientPutInServer( edict_t *pEntity, char const *playername ); - virtual void SetCommandClient( int index ); - virtual void ClientSettingsChanged( edict_t *pEdict ); - virtual PLUGIN_RESULT ClientConnect( bool *bAllowConnect, edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen ); - virtual PLUGIN_RESULT ClientCommand( edict_t *pEntity, const CCommand &args ); - virtual PLUGIN_RESULT NetworkIDValidated( const char *pszUserName, const char *pszNetworkID ); - virtual void OnQueryCvarValueFinished( QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue ); - - // added with version 3 of the interface. - virtual void OnEdictAllocated( edict_t *edict ); - virtual void OnEdictFreed( const edict_t *edict ); - - // IGameEventListener Interface - virtual void FireGameEvent( KeyValues * pevent ); - //virtual void FireGameEvent( IGameEvent * event ); - - virtual int GetCommandIndex() { return m_iClientCommandIndex; } - - static void HudTextMessage ( edict_t *pEntity, const char *szMessage ); - - static void ShowLicense ( void ); - - CRCBotEventListener *getEventListener ( void ); -private: - int m_iClientCommandIndex; - CRCBotEventListener *eventListener2; -}; - - - -extern CRCBotPlugin g_RCBOTServerPlugin; - -#endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_visibles.cpp b/utils/RCBot2_meta/bot_visibles.cpp index 8a96c7e53..c868579d3 100644 --- a/utils/RCBot2_meta/bot_visibles.cpp +++ b/utils/RCBot2_meta/bot_visibles.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -31,8 +33,8 @@ #include "engine_wrappers.h" #include "bot.h" +#include "bot_cvars.h" #include "bot_visibles.h" -#include "bot_genclass.h" #include "bot_globals.h" #include "bot_profile.h" #include "bot_client.h" @@ -41,9 +43,15 @@ #include "ndebugoverlay.h" +#include +#include + +//caxanga334: SDK 2013 contains macros for std::min and std::max which causes errors when compiling +//#if SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_BMS +#include "valve_minmax_off.h" +//#endif + extern IVDebugOverlay *debugoverlay; -extern ConVar bot_visrevs; -extern ConVar bot_visrevs_clients; //////////////////////////////////////////// byte CBotVisibles :: m_bPvs[MAX_MAP_CLUSTERS/8]; @@ -54,7 +62,7 @@ byte CBotVisibles :: m_bPvs[MAX_MAP_CLUSTERS/8]; void CTF2FindFlagFunc :: execute ( edict_t *pEntity ) { if ( m_pBot-> - if ( strcmp(pEntity->GetClassName(),""); + if ( std::strcmp(pEntity->GetClassName(),""); } void CTF2FindFlagFunc :: init () @@ -70,9 +78,9 @@ void CFindEnemyFunc :: execute ( edict_t *pEntity ) { if ( m_pBot->isEnemy(pEntity) ) { - float fFactor = getFactor(pEntity); + const float fFactor = getFactor(pEntity); - if ( !m_pBest || (fFactor < m_fBestFactor) ) + if ( !m_pBest || fFactor < m_fBestFactor ) { m_pBest = pEntity; m_fBestFactor = fFactor; @@ -80,7 +88,7 @@ void CFindEnemyFunc :: execute ( edict_t *pEntity ) } } -float CFindEnemyFunc :: getFactor ( edict_t *pEntity ) +float CFindEnemyFunc :: getFactor ( edict_t *pEntity ) const { return m_pBot->getEnemyFactor(pEntity); } @@ -93,7 +101,7 @@ void CFindEnemyFunc :: setOldEnemy ( edict_t *pEntity ) void CFindEnemyFunc :: init () { - m_pBest = NULL; + m_pBest = nullptr; m_fBestFactor = 0; } @@ -103,59 +111,58 @@ CBotVisibles :: CBotVisibles ( CBot *pBot ) { m_pBot = pBot; m_iMaxIndex = m_pBot->maxEntityIndex(); - m_iMaxSize = (m_iMaxIndex/8)+1; - m_iIndicesVisible = new unsigned char [m_iMaxSize]; + m_iMaxSize = m_iMaxIndex/8+1; + m_iIndicesVisible = new unsigned char[m_iMaxSize]; reset(); } CBotVisibles :: ~CBotVisibles () { - m_pBot = NULL; + m_pBot = nullptr; delete[] m_iIndicesVisible; - m_iIndicesVisible = NULL; + m_iIndicesVisible = nullptr; } -void CBotVisibles :: eachVisible ( CVisibleFunc *pFunc ) +void CBotVisibles::eachVisible(CVisibleFunc* pFunc) const { - dataStack tempStack = m_VisibleList; - edict_t *pEnt; - - while ( !tempStack.IsEmpty() ) - { - pEnt = tempStack.ChooseFromStack(); - - if ( !pEnt->IsFree() ) - pFunc->execute(pEnt); - } + for (edict_t* pEnt : m_VisibleSet) + { + pFunc->execute(pEnt); + } } -void CBotVisibles :: reset () +void CBotVisibles::reset() { - memset(m_iIndicesVisible,0,sizeof(unsigned char)*m_iMaxSize); - m_VisibleList.Destroy(); - m_iCurrentIndex = CBotGlobals::maxClients()+1; - m_iCurPlayer = 1; + std::fill_n(m_iIndicesVisible, m_iMaxSize, 0); + m_VisibleSet.clear(); + m_iCurrentIndex = CBotGlobals::maxClients() + 1; + m_iCurPlayer = 1; } -void CBotVisibles :: debugString ( char *string ) +void CBotVisibles::debugString(char* string) { - //char szEntities[1024]; - char szNum[10]; + //char szEntities[1024]; + //char szNum[10]{}; - string[0] = 0; + string[0] = 0; - dataStack tempStack = m_VisibleList; + /** + * I don't trust this implementation, so I'll just comment it out for now. + * TODO: modify to use `std::set m_VisibleSet` instead of the now-removed + * `dataStack m_VisibleList` + */ + // dataStack tempStack = m_VisibleList; - while ( !tempStack.IsEmpty() ) - { - edict_t *pEnt = tempStack.ChooseFromStack(); + // while ( !tempStack.IsEmpty() ) + // { + // edict_t *pEnt = tempStack.ChooseFromStack(); - if ( !pEnt ) - continue; + // if ( !pEnt ) + // continue; - sprintf(szNum,"%d,",ENTINDEX(pEnt)); - strcat(string,szNum); - } + // sprintf(szNum,"%d,",ENTINDEX(pEnt)); + // std::strcat(string,szNum); + // } } /* @param pEntity entity to check @@ -163,258 +170,241 @@ void CBotVisibles :: debugString ( char *string ) @param bVisible returns if the entity is visible or not @param iIndex saves recalling INDEXENT */ -void CBotVisibles :: checkVisible ( edict_t *pEntity, int *iTicks, bool *bVisible, int &iIndex, bool bCheckHead ) -{ - // make these static, calling a function with data many times - //static Vector vectorSurroundMins, vectorSurroundMaxs; - static Vector vEntityOrigin; - static int clusterIndex; - static bool playerInPVS; +void CBotVisibles::checkVisible(edict_t* pEntity, int* iTicks, bool* bVisible, const int iIndex, const bool bCheckHead) const +{ // reset - *bVisible = false; - - // update - if ( CBotGlobals::entityIsValid(pEntity) ) - { - //if ( CClients::clientsDebugging() && CClients::get(0)->isDebuggingBot(m_pBot) && (ENTINDEX(pEntity)AddLineOverlay(m_pBot->getOrigin(),CBotGlobals::entityOrigin(pEntity),255,255,255,false,1); - - // if in view cone - if ( m_pBot->FInViewCone(pEntity) ) - { + *bVisible = false; + + // update + if (CBotGlobals::entityIsValid(pEntity)) + { + //if ( CClients::clientsDebugging() && CClients::get(0)->isDebuggingBot(m_pBot) && (ENTINDEX(pEntity)AddLineOverlay(m_pBot->getOrigin(),CBotGlobals::entityOrigin(pEntity),255,255,255,false,1); + + // if in view cone + if (m_pBot->FInViewCone(pEntity)) + { + static Vector vEntityOrigin; + static int clusterIndex; + static bool playerInPVS; // from Valve developer community wiki // http://developer.valvesoftware.com/wiki/Transforming_the_Multiplayer_SDK_into_Coop - // update tick -- counts the number of PVS done (cpu intensive) - *iTicks = *iTicks + 1; + // update tick -- counts the number of PVS done (cpu intensive) + *iTicks += 1; + + clusterIndex = engine->GetClusterForOrigin(m_pBot->getOrigin()); + engine->GetPVSForCluster(clusterIndex, sizeof m_bPvs, m_bPvs); - clusterIndex = engine->GetClusterForOrigin( m_pBot->getOrigin() ); - engine->GetPVSForCluster( clusterIndex, sizeof(m_bPvs), m_bPvs ); - - vEntityOrigin = CBotGlobals::entityOrigin(pEntity); + // caxanga334: entityOrigin returns v(0,0,0) for brush entities. + if (CBotGlobals::isBrushEntity(pEntity)) + vEntityOrigin = CBotGlobals::worldCenter(pEntity); + else + vEntityOrigin = CBotGlobals::entityOrigin(pEntity); - // for some reason the origin is their feet. add body height - if ( iIndex <= gpGlobals->maxClients ) - vEntityOrigin + Vector(0,0,32); + constexpr int Z_OFFSET = 32; - playerInPVS = engine->CheckOriginInPVS(vEntityOrigin,m_bPvs,sizeof(m_bPvs));//engine->CheckBoxInPVS( vectorSurroundMins, vectorSurroundMaxs, m_bPvs, sizeof( m_bPvs ) ); + // for some reason the origin is their feet. add body height + if (iIndex <= gpGlobals->maxClients) + vEntityOrigin += Vector(0, 0, Z_OFFSET); - if ( playerInPVS ) - { + playerInPVS = engine->CheckOriginInPVS(vEntityOrigin, m_bPvs, sizeof m_bPvs);//engine->CheckBoxInPVS( vectorSurroundMins, vectorSurroundMaxs, m_bPvs, sizeof( m_bPvs ) ); - *bVisible = m_pBot->FVisible(pEntity,bCheckHead); + if (playerInPVS) + { + *bVisible = m_pBot->FVisible(pEntity, bCheckHead); #ifndef __linux__ - if ( *bVisible ) - { - if ( CClients::clientsDebugging(BOT_DEBUG_VIS) && CClients::get(0)->isDebuggingBot(m_pBot->getEdict()) && (ENTINDEX(pEntity)<=CBotGlobals::maxClients())) - debugoverlay->AddTextOverlay(CBotGlobals::entityOrigin(pEntity),0,0.1,"VISIBLE"); - } - else - { - if ( CClients::clientsDebugging(BOT_DEBUG_VIS) && CClients::get(0)->isDebuggingBot(m_pBot->getEdict()) && (ENTINDEX(pEntity)<=CBotGlobals::maxClients())) - debugoverlay->AddTextOverlayRGB(CBotGlobals::entityOrigin(pEntity),0,0.1,255,0,0,200,"INVISIBLE"); - } + if (CClients::clientsDebugging(BOT_DEBUG_VIS) && CClients::get(0)->isDebuggingBot(m_pBot->getEdict()) && ENTINDEX(pEntity) <= CBotGlobals::maxClients()) + { + if (*bVisible) + debugoverlay->AddTextOverlay(CBotGlobals::entityOrigin(pEntity), 0, 0.1f, "VISIBLE"); + else + debugoverlay->AddTextOverlayRGB(CBotGlobals::entityOrigin(pEntity), 0, 0.1f, 255, 0, 0, 200, "INVISIBLE"); + } #endif - } + } //else if ( CClients::clientsDebugging() && CClients::get(0)->isDebuggingBot(m_pBot) && (ENTINDEX(pEntity)AddTextOverlay(CBotGlobals::entityOrigin(pEntity),0,0.1,"INVISIBLE: playerInPVS false"); - } + } //else if ( CClients::clientsDebugging() && CClients::get(0)->isDebuggingBot(m_pBot) && (ENTINDEX(pEntity)AddTextOverlay(CBotGlobals::entityOrigin(pEntity),0,0.1,"INVISIBLE: FInViewCone false"); - } + } } -void CBotVisibles :: updateVisibles () +void CBotVisibles::updateVisibles() { - static bool bVisible; - static edict_t *pEntity; - static edict_t *pGroundEntity; - extern ConVar rcbot_supermode; + static bool bVisible; + static edict_t* pEntity; + static edict_t* pGroundEntity; - static int iTicks; + static int iTicks; static int iMaxTicks; //m_pBot->getProfile()->getVisionTicks(); - static int iStartIndex; - static int iMaxClientTicks; - static int iStartPlayerIndex; - static int iSpecialIndex; + static int iStartIndex; + static int iMaxClientTicks; + static int iStartPlayerIndex; + static int iSpecialIndex; //update ground entity - pGroundEntity = CClassInterface::getGroundEntity(m_pBot->getEdict()); + pGroundEntity = CClassInterface::getGroundEntity(m_pBot->getEdict()); - if ( pGroundEntity && (ENTINDEX(pGroundEntity) > 0) ) - { - setVisible(pGroundEntity,true); - m_pBot->setVisible(pGroundEntity,true); - } + if (pGroundEntity && ENTINDEX(pGroundEntity) > 0) + { + setVisible(pGroundEntity, true); + m_pBot->setVisible(pGroundEntity, true); + } + + iTicks = 0; - iTicks = 0; - - if ( rcbot_supermode.GetBool() ) - iMaxTicks = 100; - else + if (rcbot_supermode.GetBool()) + iMaxTicks = 100; + else iMaxTicks = m_pBot->getProfile()->m_iVisionTicks;// bot_visrevs.GetInt(); - iStartIndex = m_iCurrentIndex; + iStartIndex = m_iCurrentIndex; - if ( rcbot_supermode.GetBool() ) - iMaxClientTicks = (gpGlobals->maxClients/2)+1; - else - iMaxClientTicks =m_pBot->getProfile()->m_iVisionTicksClients; // bot_visrevs_clients.GetInt(); + if (rcbot_supermode.GetBool()) + iMaxClientTicks = gpGlobals->maxClients / 2 + 1; + else + iMaxClientTicks = m_pBot->getProfile()->m_iVisionTicksClients; // bot_visrevs_clients.GetInt(); - if ( iMaxTicks <= 2 ) - iMaxTicks = 2; - if ( iMaxClientTicks < 1 ) - iMaxClientTicks = 1; + iMaxTicks = std::max(iMaxTicks, 2); + iMaxClientTicks = std::max(iMaxClientTicks, 1); #ifdef _DEBUG - CProfileTimer *timer = CProfileTimers::getTimer(BOT_VISION_TIMER); + CProfileTimer* timer = CProfileTimers::getTimer(BOT_VISION_TIMER); - if ( CClients::clientsDebugging(BOT_DEBUG_PROFILE) ) - { - timer->Start(); - } + if (CClients::clientsDebugging(BOT_DEBUG_PROFILE)) + { + timer->Start(); + } #endif - iStartPlayerIndex = m_iCurPlayer; + iStartPlayerIndex = m_iCurPlayer; - if ( m_pBot->moveToIsValid() ) - { - Vector vMoveTo = m_pBot->getMoveTo(); - if ( m_pBot->FVisible(vMoveTo) ) - m_pBot->updateCondition(CONDITION_SEE_WAYPOINT); - else - m_pBot->removeCondition(CONDITION_SEE_WAYPOINT); - } + if (m_pBot->moveToIsValid()) + { + const Vector vMoveTo = m_pBot->getMoveTo(); + if (m_pBot->FVisible(vMoveTo)) + m_pBot->updateCondition(CONDITION_SEE_WAYPOINT); + else + m_pBot->removeCondition(CONDITION_SEE_WAYPOINT); + } - // we'll start searching some players first for quick player checking - while ( iTicks < iMaxClientTicks ) - { - pEntity = INDEXENT(m_iCurPlayer); + // we'll start searching some players first for quick player checking + while (iTicks < iMaxClientTicks) + { + pEntity = INDEXENT(m_iCurPlayer); - if ( pEntity != pGroundEntity ) - { - if ( CBotGlobals::entityIsValid(pEntity) && (pEntity != m_pBot->getEdict()) ) - { - checkVisible(pEntity,&iTicks,&bVisible,m_iCurPlayer); - setVisible(pEntity,bVisible); - m_pBot->setVisible(pEntity,bVisible); - } - } + if (pEntity != pGroundEntity) + { + if (CBotGlobals::entityIsValid(pEntity) && pEntity != m_pBot->getEdict()) + { + checkVisible(pEntity, &iTicks, &bVisible, m_iCurPlayer); + setVisible(pEntity, bVisible); + m_pBot->setVisible(pEntity, bVisible); + } + } - m_iCurPlayer++; + m_iCurPlayer++; - if ( m_iCurPlayer > CBotGlobals::maxClients() ) - m_iCurPlayer = 1; + if (m_iCurPlayer > CBotGlobals::maxClients()) + m_iCurPlayer = 1; - if ( iStartPlayerIndex == m_iCurPlayer ) - break; - } + if (iStartPlayerIndex == m_iCurPlayer) + break; + } - if ( iMaxTicks > m_iMaxIndex ) - iMaxTicks = m_iMaxIndex; + iMaxTicks = std::min(iMaxTicks, m_iMaxIndex); - if ( m_iCurPlayer >= m_iCurrentIndex ) - return; + if (m_iCurPlayer >= m_iCurrentIndex) + return; // get entities belonging to players too // we've captured them elsewhere in another data structure which is quicker to find - pEntity = m_pBot->getVisibleSpecial(); - iSpecialIndex = 0; + pEntity = m_pBot->getVisibleSpecial(); + iSpecialIndex = 0; - if ( pEntity ) - { - if ( CBotGlobals::entityIsValid(pEntity) ) - { - iSpecialIndex = ENTINDEX(pEntity); - checkVisible(pEntity,&iTicks,&bVisible,iSpecialIndex,true); + if (pEntity) + { + if (CBotGlobals::entityIsValid(pEntity)) + { + iSpecialIndex = ENTINDEX(pEntity); + checkVisible(pEntity, &iTicks, &bVisible, iSpecialIndex, true); - setVisible(pEntity,bVisible); - m_pBot->setVisible(pEntity,bVisible); - } - } + setVisible(pEntity, bVisible); + m_pBot->setVisible(pEntity, bVisible); + } + } - while ( iTicks < iMaxTicks ) - { - bVisible = false; + while (iTicks < iMaxTicks) + { + bVisible = false; - pEntity = INDEXENT(m_iCurrentIndex); + pEntity = INDEXENT(m_iCurrentIndex); - if ( (pEntity != pGroundEntity) && (m_iCurrentIndex != iSpecialIndex) ) - { - if ( CBotGlobals::entityIsValid(pEntity) ) - { - checkVisible(pEntity,&iTicks,&bVisible,m_iCurrentIndex); + if (pEntity != pGroundEntity && m_iCurrentIndex != iSpecialIndex) + { + if (CBotGlobals::entityIsValid(pEntity)) + { + checkVisible(pEntity, &iTicks, &bVisible, m_iCurrentIndex); - setVisible(pEntity,bVisible); - m_pBot->setVisible(pEntity,bVisible); - } - } + setVisible(pEntity, bVisible); + m_pBot->setVisible(pEntity, bVisible); + } + } - m_iCurrentIndex ++; + m_iCurrentIndex++; - if ( m_iCurrentIndex >= m_iMaxIndex ) - m_iCurrentIndex = CBotGlobals::maxClients()+1; // back to start of non clients + if (m_iCurrentIndex >= m_iMaxIndex) + m_iCurrentIndex = CBotGlobals::maxClients() + 1; - if ( m_iCurrentIndex == iStartIndex ) + if (m_iCurrentIndex == iStartIndex) break; // back to where we started - } - + } #ifdef _DEBUG - if ( CClients::clientsDebugging(BOT_DEBUG_PROFILE) ) - { - timer->Stop(); - } + if (CClients::clientsDebugging(BOT_DEBUG_PROFILE)) + { + timer->Stop(); + } #endif } -bool CBotVisibles :: isVisible ( edict_t *pEdict ) -{ - static int iIndex; - static int iByte; - static int iBit; - - iIndex = ENTINDEX(pEdict)-1; - iByte = iIndex/8; - iBit = iIndex%8; - - if ( iIndex < 0 ) - return false; +bool CBotVisibles::isVisible(const edict_t* pEdict) const +{ + const int iIndex = ENTINDEX(pEdict) - 1; + const std::size_t iByte = static_cast(iIndex / 8); // Use size_t for indexing [APG]RoboCop[CL] + const int iBit = iIndex % 8; - if ( iByte > m_iMaxSize ) - return false; + if (iIndex < 0 || iByte > m_iMaxSize) + return false; - return ( (*(m_iIndicesVisible+iByte))&(1<(iIndex / 8); // Use size_t for indexing [APG]RoboCop[CL] + const int iBit = iIndex % 8; + const int iFlag = 1 << iBit; + + if (bVisible) + { + // visible now + if ((m_iIndicesVisible[iByte] & iFlag) != iFlag) + m_VisibleSet.insert(pEdict); + + m_iIndicesVisible[iByte] |= iFlag; + } + else + { + // not visible anymore + if (pEdict && (m_iIndicesVisible[iByte] & iFlag) == iFlag) + m_VisibleSet.erase(pEdict); + + m_iIndicesVisible[iByte] &= ~iFlag; + } } diff --git a/utils/RCBot2_meta/bot_visibles.h b/utils/RCBot2_meta/bot_visibles.h index aae861bcf..51a496fe6 100644 --- a/utils/RCBot2_meta/bot_visibles.h +++ b/utils/RCBot2_meta/bot_visibles.h @@ -33,12 +33,16 @@ #include "bot.h" #include "bot_globals.h" -#include "bot_genclass.h" + +#include class CVisibleFunc { public: - virtual void execute ( edict_t *pEntity ) { return; } + virtual ~CVisibleFunc() = default; + + virtual void execute ( edict_t *pEntity ) { + } }; class CTF2FindFlagFunc : public CVisibleFunc @@ -46,17 +50,18 @@ class CTF2FindFlagFunc : public CVisibleFunc public: CTF2FindFlagFunc ( CBot *pBot ) { - m_pFlag = NULL; + m_pBot = nullptr; + m_pFlag = nullptr; } - edict_t *getFlag ( Vector &vOrigin ) + edict_t *getFlag ( Vector &vOrigin ) const { return m_pFlag; } void init (); - void execute ( edict_t *pEntity ); + void execute ( edict_t *pEntity ) override; private: CBot *m_pBot; edict_t *m_pFlag; @@ -69,20 +74,20 @@ class CFindEnemyFunc : public CVisibleFunc CFindEnemyFunc ( CBot *pBot ) { m_pBot = pBot; - m_fBestFactor = 0; - m_pBest = NULL; + m_fBestFactor = 0.0f; + m_pBest = nullptr; } - edict_t *getBestEnemy () + edict_t *getBestEnemy () const { return m_pBest; } - float getFactor ( edict_t *pEntity ); + float getFactor ( edict_t *pEntity ) const; void setOldEnemy ( edict_t *pEntity ); void init (); - void execute ( edict_t *pEntity ); + void execute ( edict_t *pEntity ) override; private: CBot *m_pBot; float m_fBestFactor; @@ -98,16 +103,16 @@ class CBotVisibles void reset (); void updateVisibles (); - bool isVisible ( edict_t *pEdict ); + bool isVisible (const edict_t* pEdict) const; void setVisible ( edict_t *pEdict, bool bVisible ); - void eachVisible ( CVisibleFunc *pFunc ); + void eachVisible ( CVisibleFunc *pFunc ) const; - void checkVisible ( edict_t *pEntity, int *iTicks, bool *bVisible, int &iIndex, bool bCheckHead = false ); + void checkVisible (edict_t* pEntity, int* iTicks, bool* bVisible, int iIndex, bool bCheckHead = false) const; - void debugString ( char *string ); + static void debugString ( char *string ); - static const int DEFAULT_MAX_TICKS = 10; // max number of PVS checks fired every visible check + static constexpr int DEFAULT_MAX_TICKS = 10; // max number of PVS checks fired every visible check private: //static const int NUM_BYTES = 4; // 32 entities @@ -121,10 +126,10 @@ class CBotVisibles // current player index we are checking -- updated more often int m_iCurPlayer; unsigned char *m_iIndicesVisible;//[NUM_BYTES]; - int m_iMaxSize; + std::size_t m_iMaxSize; int m_iMaxIndex; - dataStack m_VisibleList; + std::set m_VisibleSet; }; #endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_waypoint.cpp b/utils/RCBot2_meta/bot_waypoint.cpp index 60d38ba11..bcba50552 100644 --- a/utils/RCBot2_meta/bot_waypoint.cpp +++ b/utils/RCBot2_meta/bot_waypoint.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -35,36 +37,45 @@ #include "iplayerinfo.h" -#include "convar.h" #include "ndebugoverlay.h" #include "bot.h" +#include "bot_cvars.h" #include "in_buttons.h" -#include "bot_globals.h" #include "bot_client.h" +#include "bot_fortress.h" +#include "bot_getprop.h" +#include "bot_globals.h" #include "bot_navigator.h" +#include "bot_profile.h" +#include "bot_schedule.h" #include "bot_waypoint.h" #include "bot_waypoint_locations.h" #include "bot_waypoint_visibility.h" #include "bot_wpt_color.h" -#include "bot_profile.h" -#include "bot_schedule.h" -#include "bot_getprop.h" -#include "bot_fortress.h" #include "bot_wpt_dist.h" +#include "rcbot/logging.h" +#include "rcbot/utils.h" +#include +#include +#include #include //bir3yk -using namespace std; //bir3yk + + //caxanga334: SDK 2013 contains macros for std::min and std::max which causes errors when compiling +//#if SOURCE_ENGINE == SE_SDK2013 || SOURCE_ENGINE == SE_BMS +#include "valve_minmax_off.h" +//#endif int CWaypoints::m_iNumWaypoints = 0; -CWaypoint CWaypoints::m_theWaypoints[CWaypoints::MAX_WAYPOINTS]; -float CWaypoints::m_fNextDrawWaypoints = 0; +CWaypoint CWaypoints::m_theWaypoints[MAX_WAYPOINTS]; +float CWaypoints::m_fNextDrawWaypoints = 0.0f; int CWaypoints::m_iWaypointTexture = 0; -CWaypointVisibilityTable * CWaypoints::m_pVisibilityTable = NULL; -vector CWaypointTypes::m_Types; +CWaypointVisibilityTable * CWaypoints::m_pVisibilityTable = nullptr; +std::vector CWaypointTypes::m_Types; char CWaypoints::m_szAuthor[32]; char CWaypoints::m_szModifiedBy[32]; char CWaypoints::m_szWelcomeMessage[128]; @@ -72,181 +83,161 @@ const WptColor WptColor::white = WptColor(255,255,255,255) ; extern IVDebugOverlay *debugoverlay; -extern ConVar bot_belief_fade; - /////////////////////////////////////////////////////////////// // initialise -void CWaypointNavigator :: init () +void CWaypointNavigator::init() { - m_pBot = NULL; + m_pBot = nullptr; - m_vOffset = Vector(0,0,0); + m_vOffset = Vector(0, 0, 0); m_bOffsetApplied = false; m_iCurrentWaypoint = -1; m_iNextWaypoint = -1; m_iGoalWaypoint = -1; - m_currentRoute.Destroy(); - while( !m_oldRoute.empty() ) - m_oldRoute.pop(); + std::stack().swap(m_currentRoute); + std::queue().swap(m_oldRoute); m_iLastFailedWpt = -1; m_iPrevWaypoint = -1; m_bWorkingRoute = false; - Q_memset(m_fBelief,0,sizeof(float)*CWaypoints::MAX_WAYPOINTS); + std::memset(m_fBelief, 0, sizeof(float) * CWaypoints::MAX_WAYPOINTS); - m_iFailedGoals.Destroy();//.clear();//Destroy(); + m_iFailedGoals.clear(); } -bool CWaypointNavigator :: beliefLoad ( ) +bool CWaypointNavigator::beliefLoad() { - int iSize; - int iDesiredSize; - register unsigned short int i; - register unsigned short int num; - unsigned short int filebelief [ CWaypoints::MAX_WAYPOINTS ]; + unsigned short int filebelief[CWaypoints::MAX_WAYPOINTS]; - char filename[1024]; + char filename[1024]; char mapname[512]; m_bLoadBelief = false; - m_iBeliefTeam = m_pBot->getTeam(); - - sprintf(mapname,"%s%d",CBotGlobals::getMapName(),m_iBeliefTeam); + m_iBeliefTeam = static_cast(m_pBot->getTeam()); - CBotGlobals::buildFileName(filename,mapname,BOT_WAYPOINT_FOLDER,"rcb",true); + snprintf(mapname, sizeof(mapname), "%s%d", CBotGlobals::getMapName(), m_iBeliefTeam); - FILE *bfp = CBotGlobals::openFile(filename,"rb"); + CBotGlobals::buildFileName(filename, mapname, BOT_AUXILERY_FOLDER, "rcb", true); - if ( bfp == NULL ) - { - Msg(" *** Can't open Waypoint belief array for reading!\n"); - return false; - } + std::fstream bfp(filename, std::ios::in | std::ios::binary); - fseek (bfp, 0, SEEK_END); // seek at end + if (!bfp) + { + logger->Log(LogLevel::ERROR, "Can't open Waypoint belief array for reading!"); + return false; + } - iSize = ftell(bfp); // get file size - iDesiredSize = CWaypoints::numWaypoints()*sizeof(unsigned short int); + bfp.seekg(0, std::ios::end); // seek at end - // size not right, return false to re workout table - if ( iSize != iDesiredSize ) - { - fclose(bfp); - return false; - } + const std::size_t iSize = bfp.tellg(); // get file size + const std::size_t iDesiredSize = static_cast(CWaypoints::numWaypoints()) * sizeof(unsigned short int); + + // size not right, return false to re workout table + if (iSize != iDesiredSize) + { + return false; + } - fseek (bfp, 0, SEEK_SET); // seek at start + bfp.seekg(0, std::ios::beg); // seek at start - memset(filebelief,0,sizeof(unsigned short int)*CWaypoints::MAX_WAYPOINTS); + std::memset(filebelief, 0, sizeof(unsigned short int) * CWaypoints::MAX_WAYPOINTS); - fread(filebelief,sizeof(unsigned short int),CWaypoints::numWaypoints(),bfp); + bfp.read(reinterpret_cast(filebelief), static_cast(sizeof(unsigned short)) * CWaypoints::numWaypoints()); - // convert from short int to float - - num = (unsigned short int)CWaypoints::numWaypoints(); + // convert from short int to float - // quick loop - for ( i = 0; i < num; i ++ ) - { - m_fBelief[i] = (((float)filebelief[i])/32767) * MAX_BELIEF; - } + const unsigned short int num = static_cast(CWaypoints::numWaypoints()); - fclose(bfp); + // quick loop + for (unsigned short int i = 0; i < num; i++) + { + m_fBelief[i] = static_cast(filebelief[i])/32767 * MAX_BELIEF; + } - return true; + return true; } + // update belief array with averaged belief for this team -bool CWaypointNavigator :: beliefSave ( bool bOverride ) +bool CWaypointNavigator::beliefSave(const bool bOverride) { - int iSize; - int iDesiredSize; - register unsigned short int i; - register unsigned short int num; - unsigned short int filebelief [ CWaypoints::MAX_WAYPOINTS ]; - char filename[1024]; - char mapname[512]; + unsigned short int filebelief[CWaypoints::MAX_WAYPOINTS]; + char filename[1024]; + char mapname[512]; - if ( (m_pBot->getTeam() == m_iBeliefTeam) && !bOverride ) - return false; + if (m_pBot->getTeam() == m_iBeliefTeam && !bOverride) + return false; - memset(filebelief,0,sizeof(unsigned short int)*CWaypoints::MAX_WAYPOINTS); + std::memset(filebelief, 0, sizeof(unsigned short int) * CWaypoints::MAX_WAYPOINTS); - // m_iBeliefTeam is the team we've been using -- we might have changed team now - // so would need to change files if a different team - // stick to the current team we've been using - sprintf(mapname,"%s%d",CBotGlobals::getMapName(),m_iBeliefTeam); - CBotGlobals::buildFileName(filename,mapname,BOT_WAYPOINT_FOLDER,"rcb",true); + // m_iBeliefTeam is the team we've been using -- we might have changed team now + // so would need to change files if a different team + // stick to the current team we've been using + snprintf(mapname, sizeof(mapname), "%s%d", CBotGlobals::getMapName(), m_iBeliefTeam); + CBotGlobals::buildFileName(filename, mapname, BOT_AUXILERY_FOLDER, "rcb", true); - FILE *bfp = CBotGlobals::openFile(filename,"rb"); + { + std::fstream bfp(filename, std::ios::in | std::ios::binary); - if ( bfp != NULL ) - { - fseek (bfp, 0, SEEK_END); // seek at end - - iSize = ftell(bfp); // get file size - iDesiredSize = CWaypoints::numWaypoints()*sizeof(unsigned short int); - - // size not right, return false to re workout table - if ( iSize != iDesiredSize ) - { - fclose(bfp); - } - else - { - fseek (bfp, 0, SEEK_SET); // seek at start - - if ( bfp ) - fread(filebelief,sizeof(unsigned short int),CWaypoints::numWaypoints(),bfp); - - fclose(bfp); - } - } + if (bfp) + { + bfp.seekg(0, std::ios::end); // seek at end - bfp = CBotGlobals::openFile(filename,"wb"); + const std::size_t iSize = bfp.tellg(); // get file size + const std::size_t iDesiredSize = static_cast(CWaypoints::numWaypoints()) * sizeof(unsigned short int); - if ( bfp == NULL ) - { - m_bLoadBelief = true; - m_iBeliefTeam = m_pBot->getTeam(); - Msg(" *** Can't open Waypoint Belief array for writing!\n"); - return false; - } + // size not right, return false to re workout table + if (iSize == iDesiredSize) + { + bfp.seekg(0, std::ios::beg); // seek at start + + bfp.read(reinterpret_cast(filebelief), static_cast(sizeof(unsigned short)) * CWaypoints::numWaypoints()); + } + } + } + + std::fstream bfp(filename, std::ios::out | std::ios::binary); + + if (!bfp) + { + m_bLoadBelief = true; + m_iBeliefTeam = m_pBot->getTeam(); + logger->Log(LogLevel::ERROR, "Can't open Waypoint Belief array for writing!"); + return false; + } - // convert from short int to float - - num = (unsigned short int)CWaypoints::numWaypoints(); + // convert from short int to float - // quick loop - for ( i = 0; i < num; i ++ ) + const unsigned short int num = static_cast(CWaypoints::numWaypoints()); + + // quick loop + for ( unsigned short int i = 0; i < num; i ++ ) { - filebelief[i] = (filebelief[i]/2) + ((unsigned short int)((m_fBelief[i]/MAX_BELIEF) * 16383)); + filebelief[i] = filebelief[i]/2 + static_cast(m_fBelief[i] / MAX_BELIEF * 16383); } - fseek (bfp, 0, SEEK_SET); // seek at start - - fwrite(filebelief,sizeof(unsigned short int),num,bfp); + bfp.seekg(0, std::ios::beg); // seek at start - fclose(bfp); + bfp.write(reinterpret_cast(filebelief), static_cast(sizeof(unsigned short)) * num); - // new team -- load belief - m_iBeliefTeam = m_pBot->getTeam(); + // new team -- load belief + m_iBeliefTeam = m_pBot->getTeam(); m_bLoadBelief = true; m_bBeliefChanged = false; // saved - return true; + return true; } -bool CWaypointNavigator :: wantToSaveBelief () -{ +bool CWaypointNavigator::wantToSaveBelief() +{ // playing on this map for more than a normal load time - return ( m_bBeliefChanged && (m_iBeliefTeam != m_pBot->getTeam()) ) ; + return m_bBeliefChanged && m_iBeliefTeam != m_pBot->getTeam(); } -int CWaypointNavigator :: numPaths ( ) +int CWaypointNavigator :: numPaths () { if ( m_iCurrentWaypoint != -1 ) return CWaypoints::getWaypoint(m_iCurrentWaypoint)->numPaths(); @@ -256,37 +247,32 @@ int CWaypointNavigator :: numPaths ( ) bool CWaypointNavigator :: randomDangerPath (Vector *vec) { - float fMaxDanger = 0; - float fTotal; + float fMaxDanger = 0.0f; float fBelief; - float fRand; - short int i; - CWaypoint *pWpt; + int i; CWaypoint *pNext; - CWaypoint *pOnRouteTo = NULL; + const CWaypoint *pOnRouteTo = nullptr; if ( m_iCurrentWaypoint == -1 ) return false; - if ( !m_currentRoute.IsEmpty() ) + if ( !m_currentRoute.empty() ) { - static int *head; - static CWaypoint *pW; - - head = m_currentRoute.GetHeadInfoPointer(); + const int head = m_currentRoute.top(); + static CWaypoint *pW; //Unused? [APG]RoboCop[CL] - if ( head && (*head!= -1)) + if (head != -1) { - pOnRouteTo = CWaypoints::getWaypoint(*head); + pOnRouteTo = CWaypoints::getWaypoint(head); } } - pWpt = CWaypoints::getWaypoint(m_iCurrentWaypoint); + const CWaypoint* pWpt = CWaypoints::getWaypoint(m_iCurrentWaypoint); - if ( pWpt == NULL ) + if ( pWpt == nullptr) return false; - fTotal = 0; + float fTotal = 0.0f; for ( i = 0; i < pWpt->numPaths(); i ++ ) { @@ -294,10 +280,9 @@ bool CWaypointNavigator :: randomDangerPath (Vector *vec) fBelief = getBelief(CWaypoints::getWaypointIndex(pNext)); if ( pNext == pOnRouteTo ) - fBelief *= pWpt->numPaths(); + fBelief *= static_cast(pWpt->numPaths()); - if ( fBelief > fMaxDanger ) - fMaxDanger = fBelief; + fMaxDanger = std::max(fBelief, fMaxDanger); fTotal += fBelief; } @@ -305,7 +290,7 @@ bool CWaypointNavigator :: randomDangerPath (Vector *vec) if ( fMaxDanger < 10 ) return false; // not useful enough - fRand = randomFloat(0,fTotal); + const float fRand = randomFloat(0, fTotal); for ( i = 0; i < pWpt->numPaths(); i ++ ) { @@ -313,7 +298,7 @@ bool CWaypointNavigator :: randomDangerPath (Vector *vec) fBelief = getBelief(CWaypoints::getWaypointIndex(pNext)); if ( pNext == pOnRouteTo ) - fBelief *= pWpt->numPaths(); + fBelief *= static_cast(pWpt->numPaths()); fTotal += fBelief; @@ -328,15 +313,15 @@ bool CWaypointNavigator :: randomDangerPath (Vector *vec) } -Vector CWaypointNavigator :: getPath ( int pathid ) +Vector CWaypointNavigator :: getPath (const int pathid) { return CWaypoints::getWaypoint(CWaypoints::getWaypoint(m_iCurrentWaypoint)->getPath(pathid))->getOrigin(); } -int CWaypointNavigator :: getPathFlags ( int iPath ) +int CWaypointNavigator :: getPathFlags (const int iPath) { - CWaypoint *pWpt = CWaypoints::getWaypoint(m_iCurrentWaypoint); + const CWaypoint *pWpt = CWaypoints::getWaypoint(m_iCurrentWaypoint); return CWaypoints::getWaypoint(pWpt->getPath(iPath))->getFlags(); } @@ -347,7 +332,7 @@ bool CWaypointNavigator::nextPointIsOnLadder() { CWaypoint *pWaypoint; - if ( (pWaypoint = CWaypoints::getWaypoint(m_iCurrentWaypoint)) != NULL ) + if ( (pWaypoint = CWaypoints::getWaypoint(m_iCurrentWaypoint)) != nullptr) { return pWaypoint->hasFlag(CWaypointTypes::W_FL_LADDER); } @@ -361,38 +346,35 @@ float CWaypointNavigator :: getNextYaw () if ( m_iCurrentWaypoint != -1 ) return CWaypoints::getWaypoint(m_iCurrentWaypoint)->getAimYaw(); - return false; + return 0.0f; } // best waypoints are those with lowest danger -CWaypoint *CWaypointNavigator :: chooseBestFromBeliefBetweenAreas ( dataUnconstArray *goals, bool bHighDanger, bool bIgnoreBelief ) +CWaypoint *CWaypointNavigator :: chooseBestFromBeliefBetweenAreas ( const std::vector &goals, const bool bHighDanger, const bool bIgnoreBelief ) const { - int i; - CWaypoint *pWpt = NULL; -// CWaypoint *pCheck; - - float fBelief = 0; - float fSelect; + CWaypoint *pWpt = nullptr; + //CWaypoint *pCheck; // simple checks - switch ( goals->Size() ) + switch ( goals.size() ) { - case 0:return NULL; - case 1:return CWaypoints::getWaypoint(goals->ReturnValueFromIndex(0)->getWaypoint()); + case 0:return nullptr; + case 1:return CWaypoints::getWaypoint(goals[0]->getWaypoint()); default: { + float fBelief = 0.0f; AStarNode *node; - for ( i = 0; i < goals->Size(); i ++ ) + for (AStarNode* const goal : goals) { - node = goals->ReturnValueFromIndex(i); + node = goal; if ( bIgnoreBelief ) { if ( bHighDanger ) fBelief += node->getHeuristic(); else - fBelief += (131072.0f - node->getHeuristic()); + fBelief += 131072.0f - node->getHeuristic(); } else if ( bHighDanger ) fBelief += m_fBelief[node->getWaypoint()] + node->getHeuristic(); @@ -400,20 +382,20 @@ CWaypoint *CWaypointNavigator :: chooseBestFromBeliefBetweenAreas ( dataUnconstA fBelief += MAX_BELIEF - m_fBelief[node->getWaypoint()] + (131072.0f - node->getHeuristic()); } - fSelect = randomFloat(0,fBelief); + const float fSelect = randomFloat(0, fBelief); - fBelief = 0; + fBelief = 0.0f; - for ( i = 0; i < goals->Size(); i ++ ) + for (AStarNode* const goal : goals) { - node = goals->ReturnValueFromIndex(i); + node = goal; if ( bIgnoreBelief ) { if ( bHighDanger ) fBelief += node->getHeuristic(); else - fBelief += (131072.0f - node->getHeuristic()); + fBelief += 131072.0f - node->getHeuristic(); } else if ( bHighDanger ) fBelief += m_fBelief[node->getWaypoint()] + node->getHeuristic(); @@ -427,8 +409,8 @@ CWaypoint *CWaypointNavigator :: chooseBestFromBeliefBetweenAreas ( dataUnconstA } } - if ( pWpt == NULL ) - pWpt = CWaypoints::getWaypoint(goals->Random()->getWaypoint()); + if (!goals.empty() && pWpt == nullptr) + pWpt = CWaypoints::getWaypoint(goals[static_cast(randomInt(0, static_cast(goals.size()) - 1))]->getWaypoint()); } } @@ -436,26 +418,22 @@ CWaypoint *CWaypointNavigator :: chooseBestFromBeliefBetweenAreas ( dataUnconstA } // best waypoints are those with lowest danger -CWaypoint *CWaypointNavigator :: chooseBestFromBelief ( dataUnconstArray *goals, bool bHighDanger, int iSearchFlags, int iTeam ) +CWaypoint *CWaypointNavigator :: chooseBestFromBelief ( const std::vector &goals, const bool bHighDanger, const int iSearchFlags, const int iTeam ) const { - int i; - CWaypoint *pWpt = NULL; - CWaypoint *pCheck; - - float fBelief = 0; - float fSelect; - float bBeliefFactor = 1.0f; + CWaypoint *pWpt = nullptr; // simple checks - switch ( goals->Size() ) + switch ( goals.size() ) { - case 0:return NULL; - case 1:return goals->ReturnValueFromIndex(0); + case 0:return nullptr; + case 1:return goals[0]; default: { - for ( i = 0; i < goals->Size(); i ++ ) + float fBelief = 0.0f; + float bBeliefFactor = 1.0f; + for (CWaypoint* goal : goals) { - bBeliefFactor = 1.0f; + //bBeliefFactor = 1.0f; if ( iSearchFlags & WPT_SEARCH_AVOID_SENTRIES ) { @@ -463,9 +441,9 @@ CWaypoint *CWaypointNavigator :: chooseBestFromBelief ( dataUnconstArrayReturnValueFromIndex(i)->distanceFrom(CBotGlobals::entityOrigin(pSentry)) < 200.0f ) + if (goal->distanceFrom(CBotGlobals::entityOrigin(pSentry)) < 200.0f ) { bBeliefFactor *= 0.1f; } @@ -477,13 +455,16 @@ CWaypoint *CWaypointNavigator :: chooseBestFromBelief ( dataUnconstArraymaxClients; j ++ ) { - edict_t *pPlayer = INDEXENT(i); + /** + * So this was using 'i' instead of 'j' and was basically broken since forever -caxanga334 + */ + edict_t* pPlayer = INDEXENT(j); - if ( (pPlayer != NULL) && !pPlayer->IsFree() && (CClassInterface::getTF2Class(pPlayer)==TF_CLASS_SNIPER) ) + if ( pPlayer != nullptr && !pPlayer->IsFree() && CClassInterface::getTF2Class(pPlayer)==TF_CLASS_SNIPER ) { - if ( ( iTeam == 0 ) || ( iTeam == CClassInterface::getTeam(pPlayer) ) ) + if ( iTeam == 0 || iTeam == CClassInterface::getTeam(pPlayer) ) { - if ( goals->ReturnValueFromIndex(i)->distanceFrom(CBotGlobals::entityOrigin(pPlayer)) < 200.0f ) + if (goal->distanceFrom(CBotGlobals::entityOrigin(pPlayer)) < 200.0f ) { bBeliefFactor *= 0.1f; } @@ -496,13 +477,13 @@ CWaypoint *CWaypointNavigator :: chooseBestFromBelief ( dataUnconstArraymaxClients; j ++ ) { - edict_t *pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(j); - if ( (pPlayer != NULL) && !pPlayer->IsFree() ) + if ( pPlayer != nullptr && !pPlayer->IsFree() ) { - if ( ( iTeam == 0 ) || ( iTeam == CClassInterface::getTeam(pPlayer) ) ) + if ( iTeam == 0 || iTeam == CClassInterface::getTeam(pPlayer) ) { - if ( goals->ReturnValueFromIndex(i)->distanceFrom(CBotGlobals::entityOrigin(pPlayer)) < 200.0f ) + if (goal->distanceFrom(CBotGlobals::entityOrigin(pPlayer)) < 200.0f ) { bBeliefFactor *= 0.1f; } @@ -513,33 +494,33 @@ CWaypoint *CWaypointNavigator :: chooseBestFromBelief ( dataUnconstArraySize(); i ++ ) + for (CWaypoint* goal : goals) { - pCheck = goals->ReturnValueFromIndex(i); + CWaypoint* pCheck = goal; bBeliefFactor = 1.0f; if ( iSearchFlags & WPT_SEARCH_AVOID_SENTRIES ) { - for ( int j = 0; j < MAX_PLAYERS; j ++ ) + for ( int j = 0; j < RCBOT_MAXPLAYERS; j ++ ) { edict_t *pSentry = CTeamFortress2Mod::getSentryGun(j); - if ( pSentry != NULL ) + if ( pSentry != nullptr) { - if ( goals->ReturnValueFromIndex(i)->distanceFrom(CBotGlobals::entityOrigin(pSentry)) < 200.0f ) + if (goal->distanceFrom(CBotGlobals::entityOrigin(pSentry)) < 200.0f ) { bBeliefFactor *= 0.1f; } @@ -551,11 +532,11 @@ CWaypoint *CWaypointNavigator :: chooseBestFromBelief ( dataUnconstArraymaxClients; j ++ ) { - edict_t *pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(j); - if ( (pPlayer != NULL) && !pPlayer->IsFree() && (CClassInterface::getTF2Class(pPlayer)==TF_CLASS_SNIPER) ) + if ( pPlayer != nullptr && !pPlayer->IsFree() && CClassInterface::getTF2Class(pPlayer)==TF_CLASS_SNIPER ) { - if ( goals->ReturnValueFromIndex(i)->distanceFrom(CBotGlobals::entityOrigin(pPlayer)) < 200.0f ) + if (goal->distanceFrom(CBotGlobals::entityOrigin(pPlayer)) < 200.0f ) { bBeliefFactor *= 0.1f; } @@ -567,11 +548,11 @@ CWaypoint *CWaypointNavigator :: chooseBestFromBelief ( dataUnconstArraymaxClients; j ++ ) { - edict_t *pPlayer = INDEXENT(i); + edict_t* pPlayer = INDEXENT(j); - if ( (pPlayer != NULL) && !pPlayer->IsFree() ) + if ( pPlayer != nullptr && !pPlayer->IsFree() ) { - if ( goals->ReturnValueFromIndex(i)->distanceFrom(CBotGlobals::entityOrigin(pPlayer)) < 200.0f ) + if (goal->distanceFrom(CBotGlobals::entityOrigin(pPlayer)) < 200.0f ) { bBeliefFactor *= 0.1f; } @@ -581,11 +562,11 @@ CWaypoint *CWaypointNavigator :: chooseBestFromBelief ( dataUnconstArrayRandom(); + if (!goals.empty() && pWpt == nullptr) + pWpt = goals[static_cast(randomInt(0, static_cast(goals.size()) - 1))]; } } @@ -604,122 +585,115 @@ CWaypoint *CWaypointNavigator :: chooseBestFromBelief ( dataUnconstArraygetOrigin(), vCoverOrigin, nullptr); - iWpt = CWaypointLocations::GetCoverWaypoint(m_pBot->getOrigin(),vCoverOrigin,NULL); + CWaypoint* pWaypoint = CWaypoints::getWaypoint(iWpt); - CWaypoint *pWaypoint = CWaypoints::getWaypoint(iWpt); - - if ( pWaypoint == NULL ) + if (pWaypoint == nullptr) return false; - + *vCover = pWaypoint->getOrigin(); return true; } -void CWaypointNavigator :: beliefOne ( int iWptIndex, BotBelief iBeliefType, float fDist ) +void CWaypointNavigator :: beliefOne (const int iWptIndex, const BotBelief iBeliefType, const float fDist) { if ( iBeliefType == BELIEF_SAFETY ) { if ( m_fBelief[iWptIndex] > 0) m_fBelief[iWptIndex] *= bot_belief_fade.GetFloat(); - if ( m_fBelief[iWptIndex] < 0 ) - m_fBelief[iWptIndex] = 0; + m_fBelief[iWptIndex] = std::max(m_fBelief[iWptIndex], 0); } else // danger { if ( m_fBelief[iWptIndex] < MAX_BELIEF ) - m_fBelief[iWptIndex] += (2048.0f / fDist); - if ( m_fBelief[iWptIndex] > MAX_BELIEF ) - m_fBelief[iWptIndex] = MAX_BELIEF; + m_fBelief[iWptIndex] += 2048.0f / fDist; + m_fBelief[iWptIndex] = std::min(m_fBelief[iWptIndex], MAX_BELIEF); } m_bBeliefChanged = true; } // get belief nearest to current origin using waypoints to store belief -void CWaypointNavigator :: belief ( Vector vOrigin, Vector vOther, float fBelief, - float fStrength, BotBelief iType ) +void CWaypointNavigator :: belief (const Vector& vOrigin, const Vector& vOther, const float fBelief, + const float fStrength, const BotBelief iType) { - static int i; - static float factor; + static float factor; //Unused? [APG]RoboCop[CL] static float fEDist; static int iWptIndex; CWaypoint *pWpt; - dataUnconstArray m_iVisibles; - dataUnconstArray m_iInvisibles; + WaypointList m_iVisibles; + WaypointList m_iInvisibles; static int iWptFrom; static int iWptTo; // get nearest waypoint visible to others - iWptFrom = CWaypointLocations::NearestWaypoint(vOrigin,2048.0,-1,true,true,false,NULL,false,0,false,true,vOther); - iWptTo = CWaypointLocations::NearestWaypoint(vOther,2048.0,-1,true,true,false,NULL,false,0,false,true,vOrigin); + iWptFrom = CWaypointLocations::NearestWaypoint(vOrigin,2048.0f,-1,true,true,false, nullptr,false,0,false,true,vOther); + iWptTo = CWaypointLocations::NearestWaypoint(vOther,2048.0f,-1,true,true,false, nullptr,false,0,false,true,vOrigin); // no waypoint information - if ( (iWptFrom == -1) || (iWptTo == -1) ) + if ( iWptFrom == -1 || iWptTo == -1 ) return; fEDist = (vOrigin-vOther).Length(); // range - m_iVisibles.Add(iWptFrom); - m_iVisibles.Add(iWptTo); + m_iVisibles.emplace_back(iWptFrom); + m_iVisibles.emplace_back(iWptTo); + //TODO: duplicates? [APG]RoboCop[CL] CWaypointLocations::GetAllVisible(iWptFrom,iWptTo,vOrigin,vOther,fEDist,&m_iVisibles,&m_iInvisibles); - CWaypointLocations::GetAllVisible(iWptFrom,iWptTo,vOther,vOrigin,fEDist,&m_iVisibles,&m_iInvisibles); + //CWaypointLocations::GetAllVisible(iWptFrom,iWptTo,vOther,vOrigin,fEDist,&m_iVisibles,&m_iInvisibles); - for ( i = 0; i < m_iVisibles.Size(); i ++ ) + for (const int m_iVisible : m_iVisibles) { - pWpt = CWaypoints::getWaypoint(m_iVisibles[i]); + pWpt = CWaypoints::getWaypoint(m_iVisible); iWptIndex = CWaypoints::getWaypointIndex(pWpt); if ( iType == BELIEF_SAFETY ) { if ( m_fBelief[iWptIndex] > 0) m_fBelief[iWptIndex] *= bot_belief_fade.GetFloat();//(fStrength / (vOrigin-pWpt->getOrigin()).Length())*fBelief; - if ( m_fBelief[iWptIndex] < 0 ) - m_fBelief[iWptIndex] = 0; + m_fBelief[iWptIndex] = std::max(m_fBelief[iWptIndex], 0); //debugoverlay->AddTextOverlayRGB(pWpt->getOrigin(),0,5.0f,0.0,150,0,200,"Safety"); } else if ( iType == BELIEF_DANGER ) { if ( m_fBelief[iWptIndex] < MAX_BELIEF ) - m_fBelief[iWptIndex] += (fStrength / (vOrigin-pWpt->getOrigin()).Length())*fBelief; - if ( m_fBelief[iWptIndex] > MAX_BELIEF ) - m_fBelief[iWptIndex] = MAX_BELIEF; + m_fBelief[iWptIndex] += fStrength / (vOrigin-pWpt->getOrigin()).Length()*fBelief; + m_fBelief[iWptIndex] = std::min(m_fBelief[iWptIndex], MAX_BELIEF); //debugoverlay->AddTextOverlayRGB(pWpt->getOrigin(),0,5.0f,255,0,0,200,"Danger %0.2f",m_fBelief[iWptIndex]); } } - for ( i = 0; i < m_iInvisibles.Size(); i ++ ) + for (const int m_iInvisible : m_iInvisibles) { - pWpt = CWaypoints::getWaypoint(m_iInvisibles[i]); + pWpt = CWaypoints::getWaypoint(m_iInvisible); iWptIndex = CWaypoints::getWaypointIndex(pWpt); // this waypoint is safer from this danger if ( iType == BELIEF_DANGER ) { if ( m_fBelief[iWptIndex] > 0) - m_fBelief[iWptIndex] *= 0.9;//(fStrength / (vOrigin-pWpt->getOrigin()).Length())*fBelief; + m_fBelief[iWptIndex] *= 0.9f;//(fStrength / (vOrigin-pWpt->getOrigin()).Length())*fBelief; //debugoverlay->AddTextOverlayRGB(pWpt->getOrigin(),1,5.0f,0.0,150,0,200,"Safety INV"); } else if ( iType == BELIEF_SAFETY ) { if ( m_fBelief[iWptIndex] < MAX_BELIEF ) - m_fBelief[iWptIndex] += (fStrength / (vOrigin-pWpt->getOrigin()).Length())*fBelief*0.5f; + m_fBelief[iWptIndex] += fStrength / (vOrigin-pWpt->getOrigin()).Length()*fBelief*0.5f; if ( m_fBelief[iWptIndex] > MAX_BELIEF ) m_fBelief[iWptIndex] = MAX_BELIEF; //debugoverlay->AddTextOverlayRGB(pWpt->getOrigin(),1,5.0f,255,0,0,200,"Danger INV %0.2f",m_fBelief[iWptIndex]); } } - - + /* i = m_oldRoute.size(); @@ -751,8 +725,8 @@ void CWaypointNavigator :: belief ( Vector vOrigin, Vector vOther, float fBelief m_oldRoute.pop(); }*/ - m_iVisibles.Destroy(); - m_iInvisibles.Destroy(); + m_iVisibles.clear(); + m_iInvisibles.clear(); m_bBeliefChanged = true; } @@ -781,18 +755,18 @@ bool CWaypointNavigator :: getCrouchHideSpot ( Vector vCoverOrigin, Vector *vCov } */ // get the hide spot position (vCover) from origin vCoverOrigin -bool CWaypointNavigator :: getHideSpotPosition ( Vector vCoverOrigin, Vector *vCover ) +bool CWaypointNavigator :: getHideSpotPosition (const Vector& vCoverOrigin, Vector *vCover) { int iWpt; if ( m_pBot->hasGoal() ) - iWpt = CWaypointLocations::GetCoverWaypoint(m_pBot->getOrigin(),vCoverOrigin,NULL,m_pBot->getGoalOrigin()); + iWpt = CWaypointLocations::GetCoverWaypoint(m_pBot->getOrigin(),vCoverOrigin, nullptr,m_pBot->getGoalOrigin()); else - iWpt = CWaypointLocations::GetCoverWaypoint(m_pBot->getOrigin(),vCoverOrigin,NULL); + iWpt = CWaypointLocations::GetCoverWaypoint(m_pBot->getOrigin(),vCoverOrigin, nullptr); CWaypoint *pWaypoint = CWaypoints::getWaypoint(iWpt); - if ( pWaypoint == NULL ) + if ( pWaypoint == nullptr) return false; *vCover = pWaypoint->getOrigin(); @@ -805,16 +779,14 @@ void CWaypointNavigator :: open ( AStarNode *pNode ) if ( !pNode->isOpen() ) { pNode->open(); - //m_theOpenList.push_back(pNode); + //m_theOpenList.emplace_back(pNode); m_theOpenList.add(pNode); } } // AStar Algorithm : get the waypoint with lowest cost AStarNode *CWaypointNavigator :: nextNode () { - AStarNode *pNode = NULL; - - pNode = m_theOpenList.top(); + AStarNode* pNode = m_theOpenList.top(); m_theOpenList.pop(); return pNode; @@ -824,9 +796,8 @@ AStarNode *CWaypointNavigator :: nextNode () void CWaypointNavigator :: clearOpenList () { m_theOpenList.destroy(); - - - //for ( unsigned int i = 0; i < m_theOpenList.size(); i ++ ) + + //for ( unsigned i = 0; i < m_theOpenList.size(); i ++ ) // m_theOpenList[i]->unOpen(); //m_theOpenList.clear(); @@ -841,23 +812,22 @@ void CWaypointNavigator :: failMove () m_lastFailedPath.iTo = m_iCurrentWaypoint; m_lastFailedPath.bSkipped = false; - if ( !m_iFailedGoals.IsMember(m_iGoalWaypoint) ) + if ( std::find(m_iFailedGoals.begin(), m_iFailedGoals.end(), m_iGoalWaypoint) == m_iFailedGoals.end() ) { - m_iFailedGoals.Add(m_iGoalWaypoint); + m_iFailedGoals.emplace_back(m_iGoalWaypoint); m_fNextClearFailedGoals = engine->Time() + randomFloat(8.0f,30.0f); } } -float CWaypointNavigator :: distanceTo ( Vector vOrigin ) +float CWaypointNavigator :: distanceTo (const Vector& vOrigin) { - int iGoal; - if ( m_iCurrentWaypoint == -1 ) - m_iCurrentWaypoint = CWaypointLocations::NearestWaypoint(m_pBot->getOrigin(),CWaypointLocations::REACHABLE_RANGE,-1,true,false,true,NULL,false,m_pBot->getTeam()); + m_iCurrentWaypoint = CWaypointLocations::NearestWaypoint(m_pBot->getOrigin(),CWaypointLocations::REACHABLE_RANGE,-1,true,false,true, nullptr,false,m_pBot->getTeam()); if ( m_iCurrentWaypoint != -1 ) { - iGoal = CWaypointLocations::NearestWaypoint(vOrigin,CWaypointLocations::REACHABLE_RANGE,-1,true,false,true,NULL,false,m_pBot->getTeam()); + const int iGoal = CWaypointLocations::NearestWaypoint(vOrigin, CWaypointLocations::REACHABLE_RANGE, -1, true, false, true, + nullptr, false, m_pBot->getTeam()); if ( iGoal != -1 ) return CWaypointDistances::getDistance(m_iCurrentWaypoint,iGoal); @@ -872,21 +842,16 @@ float CWaypointNavigator :: distanceTo ( CWaypoint *pWaypoint ) } // find route using A* algorithm -bool CWaypointNavigator :: workRoute ( Vector vFrom, - Vector vTo, - bool *bFail, - bool bRestart, - bool bNoInterruptions, - int iGoalId, - int iConditions, int iDangerId ) +bool CWaypointNavigator :: workRoute (const Vector& vFrom, + const Vector& vTo, + bool *bFail, + const bool bRestart, + const bool bNoInterruptions, + const int iGoalId, + const int iConditions, const int iDangerId) { - extern ConVar bot_pathrevs; - extern ConVar rcbot_debug_show_route; - if ( bRestart ) { - CWaypoint *pGoalWaypoint; - if ( wantToSaveBelief() ) beliefSave(); if ( wantToLoadBelief() ) @@ -901,13 +866,13 @@ bool CWaypointNavigator :: workRoute ( Vector vFrom, else m_iGoalWaypoint = iGoalId; - pGoalWaypoint = CWaypoints::getWaypoint(m_iGoalWaypoint); + const CWaypoint* pGoalWaypoint = CWaypoints::getWaypoint(m_iGoalWaypoint); if ( CClients::clientsDebugging(BOT_DEBUG_NAV) ) { char str[64]; - sprintf(str,"goal waypoint = %d",m_iGoalWaypoint); + snprintf(str, sizeof(str), "goal waypoint = %d", m_iGoalWaypoint); CClients::clientDebugMsg(BOT_DEBUG_NAV,str,m_pBot); @@ -925,16 +890,16 @@ bool CWaypointNavigator :: workRoute ( Vector vFrom, Vector vIgnore; float fIgnoreSize; - bool bIgnore = m_pBot->getIgnoreBox(&vIgnore,&fIgnoreSize) && (pGoalWaypoint->distanceFrom(vFrom) > (fIgnoreSize*2)); + const bool bIgnore = m_pBot->getIgnoreBox(&vIgnore,&fIgnoreSize) && pGoalWaypoint->distanceFrom(vFrom) > fIgnoreSize*2; m_iCurrentWaypoint = CWaypointLocations::NearestWaypoint(vFrom,CWaypointLocations::REACHABLE_RANGE,m_iLastFailedWpt, - true,false,true,NULL,false,m_pBot->getTeam(),true,false,vIgnore,0,NULL,bIgnore,fIgnoreSize); + true,false,true, nullptr,false,m_pBot->getTeam(),true,false,vIgnore,0, nullptr,bIgnore,fIgnoreSize); // no nearest waypoint -- find nearest waypoint if ( m_iCurrentWaypoint == -1 ) { // don't ignore this time - m_iCurrentWaypoint = CWaypointLocations::NearestWaypoint(vFrom,CWaypointLocations::REACHABLE_RANGE,-1,true,false,true,NULL,false,m_pBot->getTeam(),false,false,Vector(0,0,0),0,m_pBot->getEdict()); + m_iCurrentWaypoint = CWaypointLocations::NearestWaypoint(vFrom,CWaypointLocations::REACHABLE_RANGE,-1,true,false,true, nullptr,false,m_pBot->getTeam(),false,false,Vector(0,0,0),0,m_pBot->getEdict()); if ( m_iCurrentWaypoint == -1 ) { @@ -948,12 +913,12 @@ bool CWaypointNavigator :: workRoute ( Vector vFrom, m_iLastFailedWpt = -1; clearOpenList(); - Q_memset(paths,0,sizeof(AStarNode)*CWaypoints::MAX_WAYPOINTS); + Q_memset(paths, 0, sizeof(AStarNode) * CWaypoints::MAX_WAYPOINTS); - AStarNode *curr = &paths[m_iCurrentWaypoint]; - curr->setWaypoint(m_iCurrentWaypoint); - curr->setHeuristic(m_pBot->distanceFrom(vTo)); - open(curr); + AStarNode* currentNode = &paths[m_iCurrentWaypoint]; + currentNode->setWaypoint(m_iCurrentWaypoint); + currentNode->setHeuristic(m_pBot->distanceFrom(vTo)); + open(currentNode); } ///////////////////////////////// if ( m_iGoalWaypoint == -1 ) @@ -971,6 +936,7 @@ bool CWaypointNavigator :: workRoute ( Vector vFrom, /////////////////////////////// int iLoops = 0; + //int iMaxLoops = this->m_pBot->getProfile()->getPathTicks(); // bot_pathrevs.GetInt(); //IBotNavigator::MAX_PATH_TICKS; - DNA.styx int iMaxLoops = bot_pathrevs.GetInt(); //this->m_pBot->getProfile()->getPathTicks();//IBotNavigator::MAX_PATH_TICKS; if ( iMaxLoops <= 0 ) @@ -983,19 +949,11 @@ bool CWaypointNavigator :: workRoute ( Vector vFrom, bool bFoundGoal = false; - CWaypoint *currWpt; - CWaypoint *succWpt; - CWaypointVisibilityTable *pVisTable = CWaypoints::getVisiblity(); + const CWaypointVisibilityTable *pVisTable = CWaypoints::getVisiblity(); float fCost; float fOldCost; - Vector vOrigin; - - int iPath; - int iMaxPaths; - int iSucc; - int iLastNode = -1; float fBeliefSensitivity = 1.5f; @@ -1003,7 +961,7 @@ bool CWaypointNavigator :: workRoute ( Vector vFrom, if ( iConditions & CONDITION_COVERT ) fBeliefSensitivity = 2.0f; - while ( !bFoundGoal && !m_theOpenList.empty() && (iLoops < iMaxLoops) ) + while ( !bFoundGoal && !m_theOpenList.empty() && iLoops < iMaxLoops ) { iLoops ++; @@ -1014,25 +972,25 @@ bool CWaypointNavigator :: workRoute ( Vector vFrom, iCurrentNode = curr->getWaypoint(); - bFoundGoal = (iCurrentNode == m_iGoalWaypoint); + bFoundGoal = iCurrentNode == m_iGoalWaypoint; if ( bFoundGoal ) break; // can get here now - m_iFailedGoals.Remove(iCurrentNode);//.Remove(iCurrentNode); + m_iFailedGoals.erase(std::remove(m_iFailedGoals.begin(), m_iFailedGoals.end(), iCurrentNode), m_iFailedGoals.end()); - currWpt = CWaypoints::getWaypoint(iCurrentNode); + CWaypoint* currWpt = CWaypoints::getWaypoint(iCurrentNode); - vOrigin = currWpt->getOrigin(); + const Vector vOrigin = currWpt->getOrigin(); - iMaxPaths = currWpt->numPaths(); + const int iMaxPaths = currWpt->numPaths(); - succ = NULL; + succ = nullptr; - for ( iPath = 0; iPath < iMaxPaths; iPath ++ ) + for ( int iPath = 0; iPath < iMaxPaths; iPath ++ ) { - iSucc = currWpt->getPath(iPath); + const int iSucc = currWpt->getPath(iPath); if ( iSucc == iLastNode ) continue; @@ -1052,19 +1010,19 @@ bool CWaypointNavigator :: workRoute ( Vector vFrom, } succ = &paths[iSucc]; - succWpt = CWaypoints::getWaypoint(iSucc); + CWaypoint* succWpt = CWaypoints::getWaypoint(iSucc); #ifndef __linux__ if ( rcbot_debug_show_route.GetBool() ) { - edict_t *pListenEdict; + edict_t *pListenEdict; //Unused? [APG]RoboCop[CL] - if ( !engine->IsDedicatedServer() && ((pListenEdict = CClients::getListenServerClient())!=NULL) ) + if ( !engine->IsDedicatedServer() && (pListenEdict = CClients::getListenServerClient())!= nullptr) { debugoverlay->AddLineOverlayAlpha(succWpt->getOrigin(),currWpt->getOrigin(),255,0,0,255,false,5.0f); } } #endif - if ( (iSucc != m_iGoalWaypoint) && !m_pBot->canGotoWaypoint(vOrigin,succWpt,currWpt) ) + if ( iSucc != m_iGoalWaypoint && !m_pBot->canGotoWaypoint(vOrigin,succWpt,currWpt) ) continue; if ( currWpt->hasFlag(CWaypointTypes::W_FL_TELEPORT_CHEAT) ) @@ -1072,9 +1030,9 @@ bool CWaypointNavigator :: workRoute ( Vector vFrom, else if ( succWpt->hasFlag(CWaypointTypes::W_FL_TELEPORT_CHEAT) ) fCost = succWpt->distanceFrom(vOrigin); else - fCost = curr->getCost()+(succWpt->distanceFrom(vOrigin)); + fCost = curr->getCost()+succWpt->distanceFrom(vOrigin); - if ( !CWaypointDistances::isSet(m_iCurrentWaypoint,iSucc) || (CWaypointDistances::getDistance(m_iCurrentWaypoint,iSucc) > fCost) ) + if ( !CWaypointDistances::isSet(m_iCurrentWaypoint,iSucc) || CWaypointDistances::getDistance(m_iCurrentWaypoint,iSucc) > fCost ) CWaypointDistances::setDistance(m_iCurrentWaypoint,iSucc,fCost); if ( succ->isOpen() || succ->isClosed() ) @@ -1096,7 +1054,7 @@ bool CWaypointNavigator :: workRoute ( Vector vFrom, if ( fBeliefSensitivity > 1.6f ) { - if ( (m_pBot->getEnemy() != NULL) && CBotGlobals::isPlayer(m_pBot->getEnemy()) && (m_pBot->isVisible(m_pBot->getEnemy())) ) + if ( m_pBot->getEnemy() != nullptr && CBotGlobals::isPlayer(m_pBot->getEnemy()) && m_pBot->isVisible(m_pBot->getEnemy()) ) { if ( CBotGlobals::DotProductFromOrigin(m_pBot->getEnemy(),succWpt->getOrigin()) > 0.96f ) succ->setCost(fCost+CWaypointLocations::REACHABLE_RANGE); @@ -1106,7 +1064,7 @@ bool CWaypointNavigator :: workRoute ( Vector vFrom, if ( iDangerId != -1 ) { if ( pVisTable->GetVisibilityFromTo(iDangerId,iSucc) ) - succ->setCost(succ->getCost()+(m_fBelief[iSucc]*fBeliefSensitivity*2)); + succ->setCost(succ->getCost()+m_fBelief[iSucc]*fBeliefSensitivity*2); } } else if ( iDangerId != -1 ) @@ -1114,22 +1072,22 @@ bool CWaypointNavigator :: workRoute ( Vector vFrom, if ( !pVisTable->GetVisibilityFromTo(iDangerId,iSucc) ) succ->setCost(fCost); else - succ->setCost(fCost+(m_fBelief[iSucc]*fBeliefSensitivity*2)); + succ->setCost(fCost+m_fBelief[iSucc]*fBeliefSensitivity*2); } else - succ->setCost(fCost+(m_fBelief[iSucc]*fBeliefSensitivity)); + succ->setCost(fCost+m_fBelief[iSucc]*fBeliefSensitivity); //succ->setCost(fCost-(MAX_BELIEF-m_fBelief[iSucc])); //succ->setCost(fCost-((MAX_BELIEF*fBeliefSensitivity)-(m_fBelief[iSucc]*(fBeliefSensitivity-m_pBot->getProfile()->m_fBraveness)))); } else - succ->setCost(fCost+(m_fBelief[iSucc]*(fBeliefSensitivity-m_pBot->getProfile()->m_fBraveness))); + succ->setCost(fCost+m_fBelief[iSucc]*(fBeliefSensitivity-m_pBot->getProfile()->m_fBraveness)); succ->setWaypoint(iSucc); if ( !succ->heuristicSet() ) { if ( fBeliefSensitivity > 1.6f ) - succ->setHeuristic(m_pBot->distanceFrom(succWpt->getOrigin())+succWpt->distanceFrom(vTo)+(m_fBelief[iSucc]*2)); + succ->setHeuristic(m_pBot->distanceFrom(succWpt->getOrigin())+succWpt->distanceFrom(vTo)+m_fBelief[iSucc]*2); else succ->setHeuristic(m_pBot->distanceFrom(succWpt->getOrigin())+succWpt->distanceFrom(vTo)); } @@ -1166,9 +1124,9 @@ bool CWaypointNavigator :: workRoute ( Vector vFrom, if ( m_lastFailedPath.bSkipped ) m_lastFailedPath.bValid = false; - if ( !m_iFailedGoals.IsMember(m_iGoalWaypoint) ) + if (std::find(m_iFailedGoals.begin(), m_iFailedGoals.end(), m_iGoalWaypoint) == m_iFailedGoals.end()) { - m_iFailedGoals.Add(m_iGoalWaypoint); + m_iFailedGoals.emplace_back(m_iGoalWaypoint); m_fNextClearFailedGoals = engine->Time() + randomFloat(8.0f,30.0f); } @@ -1180,22 +1138,22 @@ bool CWaypointNavigator :: workRoute ( Vector vFrom, iCurrentNode = m_iGoalWaypoint; - m_currentRoute.Destroy(); + while ( !m_currentRoute.empty() ) + m_currentRoute.pop(); iLoops = 0; - int iNumWaypoints = CWaypoints::numWaypoints(); - float fDistance = 0.0; - int iParent; + const int iNumWaypoints = CWaypoints::numWaypoints(); + float fDistance = 0.0f; - while ( (iCurrentNode != -1) && (iCurrentNode != m_iCurrentWaypoint ) && (iLoops <= iNumWaypoints) ) + while ( iCurrentNode != -1 && iCurrentNode != m_iCurrentWaypoint && iLoops <= iNumWaypoints ) { iLoops++; - m_currentRoute.Push(iCurrentNode); + m_currentRoute.push(iCurrentNode); m_oldRoute.push(iCurrentNode); - iParent = paths[iCurrentNode].getParent(); + const int iParent = paths[iCurrentNode].getParent(); // crash bug fix if ( iParent != -1 ) @@ -1203,9 +1161,9 @@ bool CWaypointNavigator :: workRoute ( Vector vFrom, #ifndef __linux__ if ( rcbot_debug_show_route.GetBool() ) { - edict_t *pListenEdict; + edict_t *pListenEdict; //Unused? [APG]RoboCop[CL] - if ( !engine->IsDedicatedServer() && ((pListenEdict = CClients::getListenServerClient())!=NULL) ) + if ( !engine->IsDedicatedServer() && (pListenEdict = CClients::getListenServerClient())!= nullptr) { debugoverlay->AddLineOverlayAlpha(CWaypoints::getWaypoint(iCurrentNode)->getOrigin()+Vector(0,0,8.0f),CWaypoints::getWaypoint(iParent)->getOrigin()+Vector(0,0,8.0f),255,255,255,255,false,5.0f); } @@ -1223,7 +1181,9 @@ bool CWaypointNavigator :: workRoute ( Vector vFrom, while ( !m_oldRoute.empty () ) m_oldRoute.pop(); - m_currentRoute.Destroy(); + while ( !m_currentRoute.empty() ) + m_currentRoute.pop(); + *bFail = true; } else @@ -1231,7 +1191,7 @@ bool CWaypointNavigator :: workRoute ( Vector vFrom, m_vGoal = CWaypoints::getWaypoint(m_iGoalWaypoint)->getOrigin(); } - return true; + return true; } // if bot has a current position to walk to return the boolean bool CWaypointNavigator :: hasNextPoint () @@ -1244,19 +1204,15 @@ Vector CWaypointNavigator :: getNextPoint () return CWaypoints::getWaypoint(m_iCurrentWaypoint)->getOrigin(); } -bool CWaypointNavigator :: getNextRoutePoint ( Vector *point ) +bool CWaypointNavigator :: getNextRoutePoint ( Vector *vPoint ) { - if ( !m_currentRoute.IsEmpty() ) + if ( !m_currentRoute.empty() ) { - static int *head; - static CWaypoint *pW; - - head = m_currentRoute.GetHeadInfoPointer(); - - if ( head && (*head!= -1)) + if (const int head = m_currentRoute.top()) { - pW = CWaypoints::getWaypoint(*head); - *point = pW->getOrigin();// + pW->applyRadius(); + static CWaypoint *pW; + pW = CWaypoints::getWaypoint(head); + *vPoint = pW->getOrigin();// + pW->applyRadius(); return true; } @@ -1265,13 +1221,13 @@ bool CWaypointNavigator :: getNextRoutePoint ( Vector *point ) return false; } -bool CWaypointNavigator :: canGetTo ( Vector vOrigin ) +bool CWaypointNavigator :: canGetTo (const Vector& vOrigin) { - int iwpt = CWaypointLocations::NearestWaypoint(vOrigin,100,-1,true,false,true,NULL,false,m_pBot->getTeam()); + const int iwpt = CWaypointLocations::NearestWaypoint(vOrigin,100,-1,true,false,true, nullptr,false,m_pBot->getTeam()); if ( iwpt >= 0 ) { - if ( m_iFailedGoals.IsMember(iwpt) ) + if (std::find(m_iFailedGoals.begin(), m_iFailedGoals.end(), iwpt) != m_iFailedGoals.end()) return false; } else @@ -1283,35 +1239,37 @@ bool CWaypointNavigator :: canGetTo ( Vector vOrigin ) void CWaypointNavigator :: rollBackPosition () { m_vPreviousPoint = m_pBot->getOrigin(); - m_iCurrentWaypoint = CWaypointLocations::NearestWaypoint(m_vPreviousPoint,CWaypointLocations::REACHABLE_RANGE,m_iLastFailedWpt,true,false,true,NULL,false,m_pBot->getTeam()); + m_iCurrentWaypoint = CWaypointLocations::NearestWaypoint(m_vPreviousPoint,CWaypointLocations::REACHABLE_RANGE,m_iLastFailedWpt,true,false,true, nullptr,false,m_pBot->getTeam()); - while ( !m_currentRoute.IsEmpty() ) // reached goal!! - { - if ( m_iCurrentWaypoint == m_currentRoute.Pop() ) + // TODO: figure out what this is actually intended to do + while ( !m_currentRoute.empty() ) // reached goal!! + { + const int iRouteWaypoint = m_currentRoute.top(); + m_currentRoute.pop(); + if (m_iCurrentWaypoint == iRouteWaypoint && !m_currentRoute.empty()) { - if ( !m_currentRoute.IsEmpty() ) - m_iCurrentWaypoint = m_currentRoute.Pop(); + m_iCurrentWaypoint = m_currentRoute.top(); + m_currentRoute.pop(); } } if ( m_iCurrentWaypoint == -1 ) - m_iCurrentWaypoint = CWaypointLocations::NearestWaypoint(m_pBot->getOrigin(),CWaypointLocations::REACHABLE_RANGE,-1,true,false,true,NULL,false,m_pBot->getTeam()); + m_iCurrentWaypoint = CWaypointLocations::NearestWaypoint(m_pBot->getOrigin(),CWaypointLocations::REACHABLE_RANGE,-1,true,false,true, nullptr,false,m_pBot->getTeam()); // find waypoint in route } // update the bots current walk vector void CWaypointNavigator :: updatePosition () { static Vector vWptOrigin; - static float fRadius; - static float fPrevBelief,fBelief; + static float fRadius; //Unused? [APG]RoboCop[CL] + static float fPrevBelief; //Unused? [APG]RoboCop[CL] + static float fBelief; //Unused? [APG]RoboCop[CL] static QAngle aim; static Vector vaim; - static bool bTouched; - - fPrevBelief = 0; - fBelief = 0; + fPrevBelief = 0.0f; + fBelief = 0.0f; if ( m_iCurrentWaypoint == -1 ) // invalid { @@ -1322,7 +1280,7 @@ void CWaypointNavigator :: updatePosition () CWaypoint *pWaypoint = CWaypoints::getWaypoint(m_iCurrentWaypoint); - if ( pWaypoint == NULL ) + if ( pWaypoint == nullptr) { m_bOffsetApplied = false; return; @@ -1337,7 +1295,8 @@ void CWaypointNavigator :: updatePosition () if ( !m_bWorkingRoute ) { - bool movetype_ok = CClassInterface::isMoveType(m_pBot->getEdict(),MOVETYPE_LADDER)||CClassInterface::isMoveType(m_pBot->getEdict(),MOVETYPE_FLYGRAVITY); + static bool bTouched; + const bool movetype_ok = CClassInterface::isMoveType(m_pBot->getEdict(),MOVETYPE_LADDER)||CClassInterface::isMoveType(m_pBot->getEdict(),MOVETYPE_FLYGRAVITY); //bTouched = false; @@ -1348,34 +1307,28 @@ void CWaypointNavigator :: updatePosition () if ( bTouched ) { - int iWaypointID = CWaypoints::getWaypointIndex(pWaypoint); - int iWaypointFlagsPrev = 0; + const int iWaypointID = CWaypoints::getWaypointIndex(pWaypoint); fPrevBelief = getBelief(iWaypointID); // Bot passed into this waypoint safely, update belief - bot_statistics_t *stats = m_pBot->getStats(); - - if ( stats ) + if ( const bot_statistics_t *stats = m_pBot->getStats() ) { - if ( (stats->stats.m_iEnemiesVisible > stats->stats.m_iTeamMatesVisible) && (stats->stats.m_iEnemiesInRange>0) ) + if ( stats->stats.m_iEnemiesVisible > stats->stats.m_iTeamMatesVisible && stats->stats.m_iEnemiesInRange>0 ) beliefOne(iWaypointID,BELIEF_DANGER,100.0f); - else if ( (stats->stats.m_iTeamMatesVisible > 0) && (stats->stats.m_iTeamMatesInRange > 0) ) + else if ( stats->stats.m_iTeamMatesVisible > 0 && stats->stats.m_iTeamMatesInRange > 0 ) beliefOne(iWaypointID,BELIEF_SAFETY,100.0f); } m_bOffsetApplied = false; - m_bDangerPoint = false; - - - if ( m_currentRoute.IsEmpty() ) // reached goal!! + + if ( m_currentRoute.empty() ) // reached goal!! { // fix: bots jumping at wrong positions m_pBot->touchedWpt(pWaypoint,-1); - m_vPreviousPoint = m_pBot->getOrigin(); m_iPrevWaypoint = m_iCurrentWaypoint; m_iCurrentWaypoint = -1; @@ -1386,23 +1339,26 @@ void CWaypointNavigator :: updatePosition () } else { - iWaypointFlagsPrev = CWaypoints::getWaypoint(m_iCurrentWaypoint)->getFlags(); - int iPrevWpt = m_iPrevWaypoint; + const int iWaypointFlagsPrev = CWaypoints::getWaypoint(m_iCurrentWaypoint)->getFlags(); + const int iPrevWpt = m_iPrevWaypoint; m_vPreviousPoint = m_pBot->getOrigin(); m_iPrevWaypoint = m_iCurrentWaypoint; - m_iCurrentWaypoint = m_currentRoute.Pop(); + + m_iCurrentWaypoint = m_currentRoute.top(); + m_currentRoute.pop(); // fix: bots jumping at wrong positions m_pBot->touchedWpt(pWaypoint,m_iCurrentWaypoint,iPrevWpt); - // fix : update pWaypoint as Current Waypoint pWaypoint = CWaypoints::getWaypoint(m_iCurrentWaypoint); if ( pWaypoint ) { + //caxanga334: Original code subtracted an int from Vector, SDK 2013 doesn't like that + //The waypoint height is probably the Z axis, so I created a Vector with 0 for xy and waypoint height for z if ( iWaypointFlagsPrev & CWaypointTypes::W_FL_TELEPORT_CHEAT ) - CBotGlobals::teleportPlayer(m_pBot->getEdict(),pWaypoint->getOrigin()-(CWaypoint::WAYPOINT_HEIGHT/2)); + CBotGlobals::teleportPlayer(m_pBot->getEdict(), pWaypoint->getOrigin() - Vector(0, 0, CWaypoint::WAYPOINT_HEIGHT / 2)); } if ( m_iCurrentWaypoint != -1 ) { // random point, but more chance of choosing the most dangerous point @@ -1419,16 +1375,16 @@ void CWaypointNavigator :: updatePosition () m_pBot->walkingTowardsWaypoint(pWaypoint,&m_bOffsetApplied,m_vOffset); // fix for bots not finding goals - if ( m_fNextClearFailedGoals && ( m_fNextClearFailedGoals < engine->Time() ) ) + if (m_fNextClearFailedGoals > 0.0f && m_fNextClearFailedGoals < engine->Time()) { - m_iFailedGoals.Destroy(); - m_fNextClearFailedGoals = 0; + m_iFailedGoals.clear(); + m_fNextClearFailedGoals = 0.0f; } m_pBot->setMoveTo(vWptOrigin+m_vOffset); if ( pWaypoint && pWaypoint->isAiming() ) - m_pBot->setAiming(vWptOrigin+(vaim*1024)); + m_pBot->setAiming(vWptOrigin+vaim*1024); /*if ( !m_pBot->hasEnemy() && (fBelief >= (fPrevBelief+10.0f)) ) m_pBot->setLookAtTask(LOOK_LAST_ENEMY); @@ -1441,8 +1397,10 @@ void CWaypointNavigator :: updatePosition () void CWaypointNavigator :: clear() { - m_currentRoute.Destroy(); - m_iFailedGoals.Destroy();//.clear();//Destroy(); + while (!m_currentRoute.empty()) { + m_currentRoute.pop(); + } + m_iFailedGoals.clear(); } // free up memory void CWaypointNavigator :: freeMapMemory () @@ -1458,33 +1416,26 @@ void CWaypointNavigator :: freeAllMemory () bool CWaypointNavigator :: routeFound () { - return !m_currentRoute.IsEmpty(); + return !m_currentRoute.empty(); } ///////////////////////////////////////////////////////// // draw paths from this waypoint (if waypoint drawing is on) -void CWaypoint :: drawPaths ( edict_t *pEdict, unsigned short int iDrawType ) +void CWaypoint::drawPaths(edict_t* pEdict, const unsigned short int iDrawType) const { - int iPaths; - int iWpt; - CWaypoint *pWpt; - - iPaths = numPaths(); - - for ( int i = 0; i < iPaths; i ++ ) + for (const int iWpt : *this) { - iWpt = getPath(i); - - pWpt = CWaypoints::getWaypoint(iWpt); - - drawPathBeam(pWpt,iDrawType); + if (CWaypoint* pWpt = CWaypoints::getWaypoint(iWpt)) + { + drawPathBeam(pWpt, iDrawType); + } } } // draws one path beam -void CWaypoint :: drawPathBeam ( CWaypoint *to, unsigned short int iDrawType ) +void CWaypoint :: drawPathBeam (CWaypoint *to, const unsigned short int iDrawType) const { - static int r,g,b; + static unsigned char r,g,b; r = g = b = 200; @@ -1520,15 +1471,14 @@ bool CWaypoint :: touched ( edict_t *pEdict ) return touched(pEdict->m_pNetworkable->GetPVSInfo()-> }*/ // checks if a waypoint is touched -bool CWaypoint :: touched ( Vector vOrigin, Vector vOffset, float fTouchDist, bool onground ) +bool CWaypoint :: touched (const Vector& vOrigin, const Vector& vOffset, const float fTouchDist, const bool onground) { static Vector v_dynamic; - extern ConVar rcbot_ladder_offs; v_dynamic = m_vOrigin+vOffset; if ( hasFlag(CWaypointTypes::W_FL_TELEPORT_CHEAT) ) - return ((vOrigin - getOrigin()).Length()) < (MAX(fTouchDist,getRadius())); + return (vOrigin - getOrigin()).Length() < (MAX(fTouchDist,getRadius())); // on ground or ladder if ( onground ) @@ -1536,9 +1486,9 @@ bool CWaypoint :: touched ( Vector vOrigin, Vector vOffset, float fTouchDist, bo if ( (vOrigin-v_dynamic).Length2D() <= fTouchDist ) { if ( hasFlag(CWaypointTypes::W_FL_LADDER) ) - return ((vOrigin.z+rcbot_ladder_offs.GetFloat()) > v_dynamic.z); + return vOrigin.z+rcbot_ladder_offs.GetFloat() > v_dynamic.z; - return fabs(vOrigin.z-v_dynamic.z) <= WAYPOINT_HEIGHT; + return std::fabs(vOrigin.z-v_dynamic.z) <= WAYPOINT_HEIGHT; } } else // swimming @@ -1549,50 +1499,55 @@ bool CWaypoint :: touched ( Vector vOrigin, Vector vOffset, float fTouchDist, bo return false; } + +// TODO: Needs implemented properly [APG]RoboCop[CL] +void CWaypoint::botTouch(CBot* pBot) +{ +} + // get the colour of this waypoint in WptColor format -WptColor CWaypointTypes ::getColour ( int iFlags ) +WptColor CWaypointTypes ::getColour (const int iFlags) { WptColor colour = WptColor(0,0,255); // normal waypoint bool bNoColour = true; - for ( unsigned int i = 0; i < m_Types.size(); i ++ ) + for (CWaypointType* const& m_Type : m_Types) { - if ( m_Types[i]->isBitsInFlags(iFlags) ) + if (m_Type->isBitsInFlags(iFlags) ) { if ( bNoColour ) { - colour = m_Types[i]->getColour(); + colour = m_Type->getColour(); bNoColour = false; } else - colour.mix(m_Types[i]->getColour()); + colour.mix(m_Type->getColour()); } } return colour; } // draw this waypoint -void CWaypoint :: draw ( edict_t *pEdict, bool bDrawPaths, unsigned short int iDrawType ) +void CWaypoint :: draw ( edict_t *pEdict, const bool bDrawPaths, const unsigned short int iDrawType ) { float fHeight = WAYPOINT_HEIGHT; float fDistance = 250.0f; - QAngle qAim; Vector vAim; CBotMod *pCurrentMod = CBotGlobals::getCurrentMod(); - - WptColor colour = CWaypointTypes::getColour(m_iFlags); + + const WptColor colour = CWaypointTypes::getColour(m_iFlags); ////////////////////////////////////////// - unsigned char r = (unsigned char)colour.r; - unsigned char g = (unsigned char)colour.g; - unsigned char b = (unsigned char)colour.b; - unsigned char a = (unsigned char)colour.a; + unsigned char r = colour.r; + unsigned char g = colour.g; + unsigned char b = colour.b; + unsigned char a = colour.a; - qAim = QAngle(0,m_iAimYaw,0); + const QAngle qAim = QAngle(0, static_cast(m_iAimYaw), 0); AngleVectors(qAim,&vAim); @@ -1608,36 +1563,35 @@ void CWaypoint :: draw ( edict_t *pEdict, bool bDrawPaths, unsigned short int iD { if ( CClients::clientsDebugging(BOT_DEBUG_NAV) ) { - CClient *pClient = CClients::get(pEdict); - - if ( pClient ) + if ( CClient *pClient = CClients::get(pEdict) ) { - edict_t *pEdict = pClient->getDebugBot(); - CBot *pBot = CBots::getBotPointer(pEdict); + pEdict = pClient->getDebugBot(); - if ( pBot ) - { - char belief = (char)((int)pBot->getNavigator()->getBelief(CWaypoints::getWaypointIndex(this))); + if ( const CBot *pBot = CBots::getBotPointer(pEdict) ) + { + const char belief = static_cast(pBot->getNavigator()->getBelief( + CWaypoints::getWaypointIndex(this))); // show danger - red = dangerous / blue = safe r = belief; - b = MAX_BELIEF-belief; + b = MAX_BELIEF - static_cast(belief); g = 0; a = 255; } - } } } + [[fallthrough]]; case DRAWTYPE_DEBUGENGINE3: fDistance = 72.0f; + [[fallthrough]]; case DRAWTYPE_DEBUGENGINE2: // draw area if ( pEdict ) { if ( distanceFrom(CBotGlobals::entityOrigin(pEdict)) < fDistance ) { - CWaypointTypes::printInfo(this,pEdict,1.0); + CWaypointTypes::printInfo(this,pEdict,1.0f); #ifndef __linux__ if ( m_iFlags ) @@ -1650,16 +1604,15 @@ void CWaypoint :: draw ( edict_t *pEdict, bool bDrawPaths, unsigned short int iD if ( CClients::clientsDebugging() ) { - CClient *pClient = CClients::get(pEdict); - - if ( pClient ) + if ( CClient *pClient = CClients::get(pEdict) ) { - edict_t *pEdict = pClient->getDebugBot(); - CBot *pBot = CBots::getBotPointer(pEdict); + pEdict = pClient->getDebugBot(); - if ( pBot ) + if ( const CBot *pBot = CBots::getBotPointer(pEdict) ) { - debugoverlay->AddTextOverlayRGB(m_vOrigin + Vector(0,0,fHeight+8.0f),0,1,0,0,255,255,"%0.4f",pBot->getNavigator()->getBelief(CWaypoints::getWaypointIndex(this))); + debugoverlay->AddTextOverlayRGB(m_vOrigin + Vector(0, 0, fHeight + 8.0f), 0, 1, + 0, 0, 255, 255, "%0.4f", pBot->getNavigator()->getBelief( + CWaypoints::getWaypointIndex(this))); } } @@ -1670,6 +1623,7 @@ void CWaypoint :: draw ( edict_t *pEdict, bool bDrawPaths, unsigned short int iD } } // this will drop down -- don't break + [[fallthrough]]; case DRAWTYPE_DEBUGENGINE: #ifndef __linux__ @@ -1680,7 +1634,7 @@ void CWaypoint :: draw ( edict_t *pEdict, bool bDrawPaths, unsigned short int iD debugoverlay->AddLineOverlay (m_vOrigin + Vector(0,0,fHeight/2), m_vOrigin + Vector(0,0,fHeight/2) + vAim*48, r,g,b, false, 1); // draw radius - if ( m_fRadius ) + if (m_fRadius > 0.0f) { debugoverlay->AddBoxOverlay(m_vOrigin,Vector(-m_fRadius,-m_fRadius,-fHeight),Vector(m_fRadius,m_fRadius,fHeight),QAngle(0,0,0),r,g,b,40,1); } @@ -1714,44 +1668,40 @@ void CWaypoint :: draw ( edict_t *pEdict, bool bDrawPaths, unsigned short int iD // clear the waypoints possible paths void CWaypoint :: clearPaths () { - m_thePaths.Clear(); + m_thePaths.clear(); } // get the distance from this waypoint from vector position vOrigin -float CWaypoint :: distanceFrom ( Vector vOrigin ) +float CWaypoint :: distanceFrom (const Vector& vOrigin) const { return (m_vOrigin - vOrigin).Length(); } /////////////////////////////////////////////////// -void CWaypoints :: updateWaypointPairs ( vector *pPairs, int iWptFlag, const char *szClassname ) +void CWaypoints :: updateWaypointPairs (std::vector* pPairs, const int iWptFlag, const char* szClassname) { - register short int iSize = numWaypoints(); - CWaypoint *pWpt; + const int iSize = numWaypoints(); edict_wpt_pair_t pair; CTraceFilterWorldAndPropsOnly filter; - trace_t *trace_result; - - pWpt = m_theWaypoints; - trace_result = CBotGlobals::getTraceResult(); - Vector vOrigin; + CWaypoint* pWpt = m_theWaypoints; + const trace_t* trace_result = CBotGlobals::getTraceResult(); - for ( register short int i = 0; i < iSize; i ++ ) + for ( int i = 0; i < iSize; i ++ ) { if ( pWpt->isUsed() && pWpt->hasFlag(iWptFlag) ) { pair.pWaypoint = pWpt; pair.pEdict = CClassInterface::FindEntityByClassnameNearest(pWpt->getOrigin(),szClassname,300.0f); - if ( pair.pEdict != NULL ) + if ( pair.pEdict != nullptr) { - vOrigin = CBotGlobals::entityOrigin(pair.pEdict); + Vector vOrigin = CBotGlobals::entityOrigin(pair.pEdict); CBotGlobals::traceLine(vOrigin,vOrigin-Vector(0,0,CWaypointLocations::REACHABLE_RANGE),MASK_SOLID_BRUSHONLY,&filter); // updates trace_result pair.v_ground = trace_result->endpos + Vector(0,0,48.0f); - pPairs->push_back(pair); + pPairs->emplace_back(pair); } } @@ -1761,21 +1711,20 @@ void CWaypoints :: updateWaypointPairs ( vector *pPairs, int i ///////////////////////////////////////////////////////////////////////////////////// // save waypoints (visibilitymade saves having to work out visibility again) // pPlayer is the person who called the command to save, NULL if automatic -bool CWaypoints :: save ( bool bVisiblityMade, edict_t *pPlayer, const char *pszAuthor, const char *pszModifier ) +bool CWaypoints :: save (const bool bVisiblityMade, const edict_t* pPlayer, const char* pszAuthor, const char* pszModifier) { char filename[1024]; - char szAuthorName[32]; CBotGlobals::buildFileName(filename,CBotGlobals::getMapName(),BOT_WAYPOINT_FOLDER,BOT_WAYPOINT_EXTENSION,true); - FILE *bfp = CBotGlobals::openFile(filename,"wb"); + std::fstream bfp = CBotGlobals::openFile(filename, std::fstream::out | std::fstream::binary); - if ( bfp == NULL ) + if ( !bfp ) { return false; // give up } - int iSize = numWaypoints(); + const int iSize = numWaypoints(); // write header // ---- @@ -1792,53 +1741,53 @@ bool CWaypoints :: save ( bool bVisiblityMade, edict_t *pPlayer, const char *psz header.iNumWaypoints = iSize; header.iVersion = WAYPOINT_VERSION; - if ( pszAuthor != NULL ) - strncpy(authorinfo.szAuthor,pszAuthor,31); + if (pszAuthor != nullptr) + std::strncpy(authorinfo.szAuthor, pszAuthor, sizeof(authorinfo.szAuthor) - 1); else { - strncpy(authorinfo.szAuthor,CWaypoints::getAuthor(),31); + std::strncpy(authorinfo.szAuthor, CWaypoints::getAuthor(), sizeof(authorinfo.szAuthor) - 1); } + authorinfo.szAuthor[sizeof(authorinfo.szAuthor) - 1] = '\0'; - if ( pszModifier != NULL ) - strncpy(authorinfo.szModifiedBy,pszModifier,31); + if (pszModifier != nullptr) + std::strncpy(authorinfo.szModifiedBy, pszModifier, sizeof(authorinfo.szModifiedBy) - 1); else { - strncpy(authorinfo.szModifiedBy,CWaypoints::getModifier(),31); + std::strncpy(authorinfo.szModifiedBy, CWaypoints::getModifier(), sizeof(authorinfo.szModifiedBy) - 1); } + authorinfo.szModifiedBy[sizeof(authorinfo.szModifiedBy) - 1] = '\0'; - authorinfo.szAuthor[31] = 0; - authorinfo.szModifiedBy[31] = 0; - - if ( !bVisiblityMade && (pszAuthor==NULL) && (pszModifier==NULL) ) + if ( !bVisiblityMade && pszAuthor== nullptr && pszModifier== nullptr) { - strcpy(szAuthorName,"(unknown)"); + char szAuthorName[32]; + std::strcpy(szAuthorName,"(unknown)"); - if ( pPlayer != NULL ) + if ( pPlayer != nullptr) { - strcpy(szAuthorName,CClients::get(pPlayer)->getName()); + std::strcpy(szAuthorName,CClients::get(pPlayer)->getName()); } if ( authorinfo.szAuthor[0] == 0 ) // no author { - strncpy(authorinfo.szAuthor,szAuthorName,31); + std::strncpy(authorinfo.szAuthor,szAuthorName,31); authorinfo.szAuthor[31] = 0; - memset(authorinfo.szModifiedBy,0,32); + std::memset(authorinfo.szModifiedBy,0,32); } - else if ( strcmp(szAuthorName,authorinfo.szAuthor) ) + else if ( std::strcmp(szAuthorName,authorinfo.szAuthor) != 0 ) { // modified - strncpy(authorinfo.szModifiedBy,szAuthorName,31); + std::strncpy(authorinfo.szModifiedBy,szAuthorName,31); authorinfo.szModifiedBy[31] = 0; } } - strcpy(header.szFileType,BOT_WAYPOINT_FILE_TYPE); - strcpy(header.szMapName,CBotGlobals::getMapName()); + std::strcpy(header.szFileType,BOT_WAYPOINT_FILE_TYPE); + std::strcpy(header.szMapName,CBotGlobals::getMapName()); ////////////////////////////////////////////// - fwrite(&header,sizeof(CWaypointHeader),1,bfp); - fwrite(&authorinfo,sizeof(CWaypointAuthorInfo),1,bfp); + bfp.write(reinterpret_cast(&header), sizeof(CWaypointHeader)); + bfp.write(reinterpret_cast(&authorinfo), sizeof(CWaypointAuthorInfo)); for ( int i = 0; i < iSize; i ++ ) { @@ -1848,7 +1797,7 @@ bool CWaypoints :: save ( bool bVisiblityMade, edict_t *pPlayer, const char *psz pWpt->save(bfp); } - fclose(bfp); + bfp.close(); //CWaypointDistances::reset(); @@ -1862,17 +1811,17 @@ bool CWaypoints :: load (const char *szMapName) { char filename[1024]; - strcpy(m_szWelcomeMessage,"No waypoints for this map"); + std::strcpy(m_szWelcomeMessage,"No waypoints for this map"); // open explicit map name waypoints - if ( szMapName == NULL ) + if ( szMapName == nullptr) CBotGlobals::buildFileName(filename,CBotGlobals::getMapName(),BOT_WAYPOINT_FOLDER,BOT_WAYPOINT_EXTENSION,true); else CBotGlobals::buildFileName(filename,szMapName,BOT_WAYPOINT_FOLDER,BOT_WAYPOINT_EXTENSION,true); - FILE *bfp = CBotGlobals::openFile(filename,"rb"); + std::fstream bfp = CBotGlobals::openFile(filename, std::fstream::in | std::fstream::binary); - if ( bfp == NULL ) + if ( !bfp ) { return false; // give up } @@ -1880,24 +1829,22 @@ bool CWaypoints :: load (const char *szMapName) CWaypointHeader header; CWaypointAuthorInfo authorinfo; - memset(authorinfo.szAuthor,0,31); - memset(authorinfo.szModifiedBy,0,31); + std::memset(authorinfo.szAuthor,0, sizeof(authorinfo.szAuthor)); + std::memset(authorinfo.szModifiedBy, 0, sizeof(authorinfo.szModifiedBy)); // read header // ----------- - fread(&header,sizeof(CWaypointHeader),1,bfp); + bfp.read(reinterpret_cast(&header), sizeof(CWaypointHeader)); if ( !FStrEq(header.szFileType,BOT_WAYPOINT_FILE_TYPE) ) { - CBotGlobals::botMessage(NULL,0,"Error loading waypoints: File type mismatch"); - fclose(bfp); + logger->Log(LogLevel::ERROR, "Error loading waypoints: File type mismatch"); return false; } if ( header.iVersion > WAYPOINT_VERSION ) { - CBotGlobals::botMessage(NULL,0,"Error loading waypoints: Waypoint version too new"); - fclose(bfp); + logger->Log(LogLevel::ERROR, "Error loading waypoints: Waypoint version too new"); return false; } @@ -1905,35 +1852,33 @@ bool CWaypoints :: load (const char *szMapName) { if ( !FStrEq(header.szMapName,szMapName) ) { - CBotGlobals::botMessage(NULL,0,"Error loading waypoints: Map name mismatch"); - fclose(bfp); + logger->Log(LogLevel::ERROR, "Error loading waypoints: Map name mismatch"); return false; } } else if ( !FStrEq(header.szMapName,CBotGlobals::getMapName()) ) { - CBotGlobals::botMessage(NULL,0,"Error loading waypoints: Map name mismatch"); - fclose(bfp); + logger->Log(LogLevel::ERROR, "Error loading waypoints: Map name mismatch"); return false; } if ( header.iVersion > 3 ) { // load author information - fread(&authorinfo,sizeof(CWaypointAuthorInfo),1,bfp); + bfp.read(reinterpret_cast(&authorinfo), sizeof(CWaypointAuthorInfo)); - sprintf(m_szWelcomeMessage,"Waypoints by %s",authorinfo.szAuthor); + snprintf(m_szWelcomeMessage, sizeof(m_szWelcomeMessage), "Waypoints by %s", authorinfo.szAuthor); if ( authorinfo.szModifiedBy[0] != 0 ) { - strcat(m_szWelcomeMessage," modified by "); - strcat(m_szWelcomeMessage,authorinfo.szModifiedBy); + std::strcat(m_szWelcomeMessage," modified by "); + std::strcat(m_szWelcomeMessage,authorinfo.szModifiedBy); } } else - sprintf(m_szWelcomeMessage,"Waypoints Loaded"); + snprintf(m_szWelcomeMessage, sizeof(m_szWelcomeMessage), "Waypoints Loaded"); - int iSize = header.iNumWaypoints; + const int iSize = header.iNumWaypoints; // ok lets read the waypoints // initialize @@ -1945,14 +1890,14 @@ bool CWaypoints :: load (const char *szMapName) bool bWorkVisibility = true; // if we're loading from another map, just load visibility, save effort! - if ( (szMapName == NULL) && (header.iFlags & W_FILE_FL_VISIBILITY) ) - bWorkVisibility = ( !m_pVisibilityTable->ReadFromFile(iSize) ); + if ( szMapName == nullptr && header.iFlags & W_FILE_FL_VISIBILITY ) + bWorkVisibility = !m_pVisibilityTable->ReadFromFile(iSize); for ( int i = 0; i < iSize; i ++ ) { CWaypoint *pWpt = &m_theWaypoints[i]; - pWpt->load(bfp,header.iVersion); + pWpt->load(bfp, header.iVersion); if ( pWpt->isUsed() ) // not a deleted waypoint { @@ -1961,15 +1906,15 @@ bool CWaypoints :: load (const char *szMapName) } } - fclose(bfp); + bfp.close(); m_pVisibilityTable->setWorkVisiblity(bWorkVisibility); if ( bWorkVisibility ) // say a message - Msg(" *** No waypoint visibility file ***\n *** Working out waypoint visibility information... ***\n"); + logger->Log(LogLevel::INFO, "No waypoint visibility file -- working out waypoint visibility information..."); // if we're loading from another map just do this again! - if ( szMapName == NULL ) + if ( szMapName == nullptr) CWaypointDistances::load(); // script coupled to waypoints too @@ -1985,74 +1930,73 @@ void CWaypoint :: init () m_vOrigin = Vector(0,0,0); m_bUsed = false; // ( == "deleted" ) setAim(0); - m_thePaths.Clear(); + m_thePaths.clear(); m_iArea = 0; - m_fRadius = 0; + m_fRadius = 0.0f; m_bUsed = true; - m_fNextCheckGroundTime = 0; + m_fNextCheckGroundTime = 0.0f; m_bHasGround = false; - m_fRadius = 0; - m_OpensLaterInfo.Clear(); + m_OpensLaterInfo.clear(); m_bIsReachable = true; - m_fCheckReachableTime = 0; + m_fCheckReachableTime = 0.0f; } -void CWaypoint :: save ( FILE *bfp ) +void CWaypoint :: save (std::fstream &bfp ) { - fwrite(&m_vOrigin,sizeof(Vector),1,bfp); + bfp.write(reinterpret_cast(&m_vOrigin), sizeof(Vector)); // aim of vector (used with certain waypoint types) - fwrite(&m_iAimYaw,sizeof(int),1,bfp); - fwrite(&m_iFlags,sizeof(int),1,bfp); + bfp.write(reinterpret_cast(&m_iAimYaw), sizeof(int)); + bfp.write(reinterpret_cast(&m_iFlags), sizeof(int)); // not deleted - fwrite(&m_bUsed,sizeof(bool),1,bfp); + bfp.write(reinterpret_cast(&m_bUsed), sizeof(bool)); int iPaths = numPaths(); - fwrite(&iPaths,sizeof(int),1,bfp); + bfp.write(reinterpret_cast(&iPaths), sizeof(int)); for ( int n = 0; n < iPaths; n ++ ) { int iPath = getPath(n); - fwrite(&iPath,sizeof(int),1,bfp); + bfp.write(reinterpret_cast(&iPath), sizeof(int)); } if ( CWaypoints::WAYPOINT_VERSION >= 2 ) { - fwrite(&m_iArea,sizeof(int),1,bfp); + bfp.write(reinterpret_cast(&m_iArea), sizeof(int)); } if ( CWaypoints::WAYPOINT_VERSION >= 3 ) { - fwrite(&m_fRadius,sizeof(float),1,bfp); + bfp.write(reinterpret_cast(&m_fRadius), sizeof(float)); } } -void CWaypoint :: load ( FILE *bfp, int iVersion ) +void CWaypoint :: load (std::fstream &bfp, const int iVersion ) { int iPaths; - fread(&m_vOrigin,sizeof(Vector),1,bfp); + bfp.read(reinterpret_cast(&m_vOrigin), sizeof(Vector)); // aim of vector (used with certain waypoint types) - fread(&m_iAimYaw,sizeof(int),1,bfp); - fread(&m_iFlags,sizeof(int),1,bfp); + bfp.read(reinterpret_cast(&m_iAimYaw), sizeof(int)); + bfp.read(reinterpret_cast(&m_iFlags), sizeof(int)); // not deleted - fread(&m_bUsed,sizeof(bool),1,bfp); - fread(&iPaths,sizeof(int),1,bfp); + bfp.read(reinterpret_cast(&m_bUsed), sizeof(bool)); + bfp.read(reinterpret_cast(&iPaths), sizeof(int)); for ( int n = 0; n < iPaths; n ++ ) { int iPath; - fread(&iPath,sizeof(int),1,bfp); + bfp.read(reinterpret_cast(&iPath), sizeof(int)); addPathTo(iPath); } if ( iVersion >= 2 ) { - fread(&m_iArea,sizeof(int),1,bfp); + bfp.read(reinterpret_cast(&m_iArea), sizeof(int)); } if ( iVersion >= 3 ) { - fread(&m_fRadius,sizeof(float),1,bfp); + bfp.read(reinterpret_cast(&m_fRadius),sizeof(float)); } } @@ -2060,8 +2004,8 @@ bool CWaypoint :: checkGround () { if ( m_fNextCheckGroundTime < engine->Time() ) { - CBotGlobals::quickTraceline(NULL,m_vOrigin,m_vOrigin-Vector(0,0,80.0f)); - m_bHasGround = ( CBotGlobals::getTraceResult()->fraction < 1.0f ); + CBotGlobals::quickTraceline(nullptr,m_vOrigin,m_vOrigin-Vector(0,0,80.0f)); + m_bHasGround = CBotGlobals::getTraceResult()->fraction < 1.0f; m_fNextCheckGroundTime = engine->Time() + 1.0f; } @@ -2070,10 +2014,9 @@ bool CWaypoint :: checkGround () // draw waypoints to this client pClient void CWaypoints :: drawWaypoints( CClient *pClient ) { - float fTime = engine->Time(); - CWaypoint *pWpt; + const float fTime = engine->Time(); ////////////////////////////////////////// - // TODO + // TODO: // draw time currently part of CWaypoints // once we can send sprites to individual players // make draw waypoints time part of CClient @@ -2088,27 +2031,25 @@ void CWaypoints :: drawWaypoints( CClient *pClient ) if ( pClient->isPathWaypointOn() ) { - pWpt = CWaypoints::getWaypoint(pClient->currentWaypoint()); - // valid waypoint - if ( pWpt ) + if ( const CWaypoint* pWpt = getWaypoint(pClient->currentWaypoint()) ) pWpt->drawPaths(pClient->getPlayer(),pClient->getDrawType()); } } void CWaypoints :: init (const char *pszAuthor, const char *pszModifiedBy) { - if ( pszAuthor != NULL ) + if ( pszAuthor != nullptr) { - strncpy(m_szAuthor,pszAuthor,31); + std::strncpy(m_szAuthor,pszAuthor,31); m_szAuthor[31] = 0; } else m_szAuthor[0] = 0; - if ( pszModifiedBy != NULL ) + if ( pszModifiedBy != nullptr) { - strncpy(m_szModifiedBy,pszModifiedBy,31); + std::strncpy(m_szModifiedBy,pszModifiedBy,31); m_szModifiedBy[31] = 0; } else @@ -2117,10 +2058,10 @@ void CWaypoints :: init (const char *pszAuthor, const char *pszModifiedBy) m_iNumWaypoints = 0; m_fNextDrawWaypoints = 0; - for ( int i = 0; i < MAX_WAYPOINTS; i ++ ) - m_theWaypoints[i].init(); + for (CWaypoint& m_theWaypoint : m_theWaypoints) + m_theWaypoint.init(); - Q_memset(m_theWaypoints,0,sizeof(CWaypoint)*MAX_WAYPOINTS); + Q_memset(m_theWaypoints, 0, sizeof(CWaypoint) * MAX_WAYPOINTS); CWaypointLocations::Init(); CWaypointDistances::reset(); @@ -2141,7 +2082,7 @@ void CWaypoints :: freeMemory () delete m_pVisibilityTable; } - m_pVisibilityTable = NULL; + m_pVisibilityTable = nullptr; } void CWaypoints :: precacheWaypointTexture () @@ -2151,9 +2092,9 @@ void CWaypoints :: precacheWaypointTexture () /////////////////////////////////////////////////////// // return nearest waypoint not visible to pinch point -CWaypoint *CWaypoints :: getPinchPointFromWaypoint ( Vector vPlayerOrigin, Vector vPinchOrigin ) +CWaypoint *CWaypoints :: getPinchPointFromWaypoint (const Vector& vPlayerOrigin, const Vector& vPinchOrigin) { - int iWpt = CWaypointLocations::GetCoverWaypoint(vPlayerOrigin,vPinchOrigin,NULL,&vPinchOrigin); + const int iWpt = CWaypointLocations::GetCoverWaypoint(vPlayerOrigin,vPinchOrigin, nullptr,&vPinchOrigin); return getWaypoint(iWpt); } @@ -2161,29 +2102,29 @@ CWaypoint *CWaypoints :: getPinchPointFromWaypoint ( Vector vPlayerOrigin, Vecto CWaypoint *CWaypoints :: getNestWaypoint ( int iTeam, int iArea, bool bForceArea, CBot *pBot ) { //m_theWaypoints - return NULL; + return nullptr; } -void CWaypoints :: deleteWaypoint ( int iIndex ) +void CWaypoints :: deleteWaypoint (const int iIndex) { // mark as not used m_theWaypoints[iIndex].setUsed(false); m_theWaypoints[iIndex].clearPaths(); // remove from waypoint locations - Vector vOrigin = m_theWaypoints[iIndex].getOrigin(); - float fOrigin[3] = { vOrigin.x, vOrigin.y, vOrigin.z }; + const Vector vOrigin = m_theWaypoints[iIndex].getOrigin(); + const float fOrigin[3] = { vOrigin.x, vOrigin.y, vOrigin.z }; CWaypointLocations::DeleteWptLocation(iIndex,fOrigin); // delete any paths pointing to this waypoint deletePathsTo(iIndex); } -void CWaypoints :: shiftVisibleAreas ( edict_t *pPlayer, int from, int to ) +void CWaypoints :: shiftVisibleAreas ( edict_t *pPlayer, const int from, const int to ) { for ( int i = 0; i < m_iNumWaypoints; i ++ ) { - CWaypoint *pWpt = &(m_theWaypoints[i]); + CWaypoint *pWpt = &m_theWaypoints[i]; if ( !pWpt->isUsed() ) continue; @@ -2192,13 +2133,13 @@ void CWaypoints :: shiftVisibleAreas ( edict_t *pPlayer, int from, int to ) { CBotGlobals::quickTraceline(pPlayer,CBotGlobals::entityOrigin(pPlayer),pWpt->getOrigin()); - if ( (CBotGlobals::getTraceResult()->fraction >= 1.0f) ) + if ( CBotGlobals::getTraceResult()->fraction >= 1.0f ) pWpt->setArea(to); } } } -void CWaypoints :: shiftAreas (int val) +void CWaypoints :: shiftAreas (const int val) { for ( int i = 0; i < m_iNumWaypoints; i ++ ) { @@ -2211,43 +2152,37 @@ void CWaypoints :: shiftAreas (int val) } } -int CWaypoints :: getClosestFlagged ( int iFlags, Vector &vOrigin, int iTeam, float *fReturnDist, unsigned char *failedwpts ) +int CWaypoints::getClosestFlagged(const int iFlags, const Vector& vOrigin, const int iTeam, float* fReturnDist, const unsigned char* failedwpts) { - int i = 0; - int size = numWaypoints(); + const int iSize = numWaypoints(); - float fDist = 8192.0; + float fDist = 8192.0f; float distance; int iwpt = -1; - int iFrom = CWaypointLocations::NearestWaypoint(vOrigin,fDist,-1,true,false,true,NULL,false,iTeam); + const int iFrom = CWaypointLocations::NearestWaypoint(vOrigin, fDist, -1, true, false, true, nullptr, false, iTeam); - CWaypoint *pWpt; - CBotMod *pCurrentMod = CBotGlobals::getCurrentMod(); - - for ( i = 0; i < size; i ++ ) + CBotMod* pCurrentMod = CBotGlobals::getCurrentMod(); + for (int i = 0; i < static_cast(iSize); i++) { - pWpt = &m_theWaypoints[i]; - - if ( i == iFrom ) + CWaypoint* pWpt = &m_theWaypoints[i]; + if (i == static_cast(iFrom)) continue; - - if ( failedwpts[i] == 1 ) + if (failedwpts[i] == 1) continue; - - if ( pWpt->isUsed() && pWpt->forTeam(iTeam) ) + if (pWpt->isUsed() && pWpt->forTeam(iTeam)) { - if ( pWpt->hasFlag(iFlags) ) + if (pWpt->hasFlag(iFlags)) { // BUG FIX for DOD:S - if (!pCurrentMod->isWaypointAreaValid(pWpt->getArea(), iFlags)) // CTeamFortress2Mod::m_ObjectiveResource.isWaypointAreaValid(pWpt->getArea()) ) + if (!pCurrentMod->isWaypointAreaValid(pWpt->getArea(), iFlags)) continue; - if ( (iFrom == -1) ) - distance = (pWpt->getOrigin()-vOrigin).Length(); + if (iFrom == -1) + distance = (pWpt->getOrigin() - vOrigin).Length(); else - distance = CWaypointDistances::getDistance(iFrom,i); + distance = CWaypointDistances::getDistance(iFrom, i); - if ( distance < fDist) + if (distance < fDist) { fDist = distance; iwpt = i; @@ -2262,28 +2197,28 @@ int CWaypoints :: getClosestFlagged ( int iFlags, Vector &vOrigin, int iTeam, fl return iwpt; } -void CWaypoints :: deletePathsTo ( int iWpt ) +void CWaypoints :: deletePathsTo (const int iWpt) { - CWaypoint *pWaypoint = CWaypoints::getWaypoint(iWpt); + const CWaypoint *pWaypoint = CWaypoints::getWaypoint(iWpt); int iNumPathsTo = pWaypoint->numPathsToThisWaypoint(); - dataUnconstArray m_PathsTo; + WaypointList pathsTo; // this will go into an evil loop unless we do this first // and use a temporary copy as a side effect of performing // a remove will affect the original array - for ( int i = 0; i < iNumPathsTo; i ++ ) + for (std::size_t i = 0; i < static_cast(iNumPathsTo); i++) { - m_PathsTo.Add(pWaypoint->getPathToThisWaypoint(i)); + pathsTo.emplace_back(pWaypoint->getPathToThisWaypoint(static_cast(i))); } - iNumPathsTo = m_PathsTo.Size(); + iNumPathsTo = static_cast(pathsTo.size()); - for ( int i = 0; i < iNumPathsTo; i ++ ) + for (std::size_t i = 0; i < static_cast(iNumPathsTo); i++) { - int iOther = m_PathsTo.ReturnValueFromIndex(i); + const int iOther = pathsTo[i]; - CWaypoint *pOther = getWaypoint(iOther); + CWaypoint* pOther = getWaypoint(iOther); pOther->removePathTo(iWpt); } @@ -2291,27 +2226,24 @@ void CWaypoints :: deletePathsTo ( int iWpt ) short int iNumWaypoints = (short int)numWaypoints(); - for ( register short int i = 0; i < iNumWaypoints; i ++ ) + for ( short int i = 0; i < iNumWaypoints; i ++ ) m_theWaypoints[i].removePathTo(iWpt);*/ } // Fixed; 23/01 -void CWaypoints :: deletePathsFrom ( int iWpt ) +void CWaypoints :: deletePathsFrom (const int iWpt) { m_theWaypoints[iWpt].clearPaths(); } -int CWaypoints :: addWaypoint ( CClient *pClient, const char *type1, const char *type2,const char *type3,const char *type4, bool bUseTemplate ) +int CWaypoints :: addWaypoint ( CClient *pClient, const char *type1, const char *type2, const char *type3, const char *type4, const bool bUseTemplate ) { int iFlags = 0; - int iIndex = -1; // waypoint index - int iPrevFlags = 0; - int iArea = 0; - Vector vWptOrigin = pClient->getOrigin(); - QAngle playerAngles = CBotGlobals::playerAngles (pClient->getPlayer()); - float fMaxDistance = 0.0; // distance for auto type - - extern ConVar rcbot_wpt_autotype; + int iIndex; // waypoint index + int iArea; + const Vector vWptOrigin = pClient->getOrigin(); + const QAngle playerAngles = CBotGlobals::playerAngles (pClient->getPlayer()); + float fMaxDistance = 0.0f; // distance for auto type CBotMod *pCurrentMod = CBotGlobals::getCurrentMod(); @@ -2322,28 +2254,28 @@ int CWaypoints :: addWaypoint ( CClient *pClient, const char *type1, const char // override types and area here if ( type1 && *type1 ) { - CWaypointType *t = CWaypointTypes::getType(type1); + const CWaypointType *t = CWaypointTypes::getType(type1); if ( t ) iFlags |= t->getBits(); - else if ( atoi(type1) > 0 ) - iArea = atoi(type1); + else if ( std::atoi(type1) > 0 ) + iArea = std::atoi(type1); if ( type2 && *type2 ) { t = CWaypointTypes::getType(type2); if ( t ) iFlags |= t->getBits(); - else if ( atoi(type2) > 0 ) - iArea = atoi(type2); + else if ( std::atoi(type2) > 0 ) + iArea = std::atoi(type2); if ( type3 && *type3 ) { t = CWaypointTypes::getType(type3); if ( t ) iFlags |= t->getBits(); - else if ( atoi(type3) > 0 ) - iArea = atoi(type3); + else if ( std::atoi(type3) > 0 ) + iArea = std::atoi(type3); if ( type4 && *type4 ) { @@ -2351,17 +2283,15 @@ int CWaypoints :: addWaypoint ( CClient *pClient, const char *type1, const char if ( t ) iFlags |= t->getBits(); - else if ( atoi(type4) > 0 ) - iArea = atoi(type4); + else if ( std::atoi(type4) > 0 ) + iArea = std::atoi(type4); } } - } - } - iPrevFlags = iFlags; // to detect change + const int iPrevFlags = iFlags; // to detect change //IPlayerInfo *p = playerinfomanager->GetPlayerInfo(pClient->getPlayer()); @@ -2374,41 +2304,45 @@ int CWaypoints :: addWaypoint ( CClient *pClient, const char *type1, const char if ( pPlayer->GetFlags() & FL_DUCKING ) iFlags |= CWaypoint::W_FL_CROUCH; */ + float maxRange = rcbot_wpt_autotype_detection_range.GetFloat(); + maxRange = std::clamp(maxRange, 80.0f, 512.0f); // clamp the variable to sane values - if ( rcbot_wpt_autotype.GetInt() && (!bUseTemplate || (rcbot_wpt_autotype.GetInt()==2)) ) + if ( rcbot_wpt_autotype.GetInt() && (!bUseTemplate || rcbot_wpt_autotype.GetInt()==2) ) { - int i = 0; - - edict_t *pEdict; - float fDistance; - - IPlayerInfo *pPlayerInfo = playerinfomanager->GetPlayerInfo(pClient->getPlayer()); - - if ( pPlayerInfo ) + if ( IPlayerInfo *pPlayerInfo = playerinfomanager->GetPlayerInfo(pClient->getPlayer()) ) { if ( pPlayerInfo->GetLastUserCommand().buttons & IN_DUCK ) iFlags |= CWaypointTypes::W_FL_CROUCH; } - for ( i = 0; i < gpGlobals->maxEntities; i ++ ) + for (int i = 0; i < gpGlobals->maxEntities; i++) { - pEdict = INDEXENT(i); + edict_t* pEdict = rcbot2utils::EdictOfIndex(i); - if ( pEdict ) + if (rcbot2utils::IsValidEdict(pEdict)) { - if ( !pEdict->IsFree() ) + const float rangeToOrigin = (rcbot2utils::GetEntityOrigin(pEdict) - vWptOrigin).Length(); + const float rangeToCenter = (rcbot2utils::GetWorldSpaceCenter(pEdict) - vWptOrigin).Length(); // for brush entities + const float fDistance = std::min(rangeToOrigin, rangeToCenter); // select the smallest between the two distances + + if (fDistance <= maxRange) { - if ( pEdict->m_pNetworkable && pEdict->GetIServerEntity() ) - { - fDistance=(CBotGlobals::entityOrigin(pEdict) - vWptOrigin).Length(); + fMaxDistance = std::max(fDistance, fMaxDistance); - if ( fDistance <= 80.0f ) - { - if ( fDistance > fMaxDistance ) - fMaxDistance = fDistance; + pCurrentMod->addWaypointFlags(pClient->getPlayer(), pEdict, &iFlags, &iArea, &fMaxDistance); + } + else + { + // distances are unreliable for brush entities, also do a bounds check if the distance above failed + Vector vWptTop = vWptOrigin; + vWptTop.z += CWaypoint::WAYPOINT_HEIGHT; - pCurrentMod->addWaypointFlags(pClient->getPlayer(),pEdict,&iFlags,&iArea,&fMaxDistance); - } + if (rcbot2utils::PointIsWithinTrigger(pEdict, vWptOrigin) || rcbot2utils::PointIsWithinTrigger(pEdict, vWptTop)) + { + // Waypoint origin collides with a entity bound + fMaxDistance = std::max(fDistance, fMaxDistance); + + pCurrentMod->addWaypointFlags(pClient->getPlayer(), pEdict, &iFlags, &iArea, &fMaxDistance); } } } @@ -2418,11 +2352,13 @@ int CWaypoints :: addWaypoint ( CClient *pClient, const char *type1, const char if ( bUseTemplate ) { - iIndex = addWaypoint(pClient->getPlayer(),vWptOrigin,pClient->getWptCopyFlags(),pClient->isAutoPathOn(),(int)playerAngles.y,iArea,pClient->getWptCopyRadius()); // sort flags out + iIndex = addWaypoint(pClient->getPlayer(), vWptOrigin, pClient->getWptCopyFlags(), pClient->isAutoPathOn(), + playerAngles.y, iArea, pClient->getWptCopyRadius()); // sort flags out } else { - iIndex = addWaypoint(pClient->getPlayer(),vWptOrigin,iFlags,pClient->isAutoPathOn(),(int)playerAngles.y,iArea,(iFlags!=iPrevFlags) ? (fMaxDistance/2) : 0); // sort flags out + iIndex = addWaypoint(pClient->getPlayer(), vWptOrigin, iFlags, pClient->isAutoPathOn(), playerAngles.y, + iArea, iFlags != iPrevFlags ? fMaxDistance / 2 : 0); // sort flags out } pClient->playSound("weapons/crossbow/hit1"); @@ -2430,18 +2366,17 @@ int CWaypoints :: addWaypoint ( CClient *pClient, const char *type1, const char return iIndex; } -int CWaypoints :: addWaypoint ( edict_t *pPlayer, Vector vOrigin, int iFlags, bool bAutoPath, int iYaw, int iArea, float fRadius ) +int CWaypoints :: addWaypoint (edict_t *pPlayer, const Vector& vOrigin, const int iFlags, const bool bAutoPath, const int iYaw, const int iArea, float fRadius) { - int iIndex = freeWaypointIndex(); - extern ConVar rcbot_wpt_autoradius; + const int iIndex = freeWaypointIndex(); if ( iIndex == -1 ) { - Msg("Waypoints full!"); + logger->Log(LogLevel::ERROR, "Waypoints full!"); return -1; } - if ( (fRadius == 0) && (rcbot_wpt_autoradius.GetFloat() > 0) ) + if ( fRadius == 0.0f && rcbot_wpt_autoradius.GetFloat() > 0 ) fRadius = rcbot_wpt_autoradius.GetFloat(); /////////////////////////////////////////////////// @@ -2454,10 +2389,10 @@ int CWaypoints :: addWaypoint ( edict_t *pPlayer, Vector vOrigin, int iFlags, bo m_iNumWaypoints++; /////////////////////////////////////////////////// - float fOrigin[3] = {vOrigin.x,vOrigin.y,vOrigin.z}; + const float fOrigin[3] = {vOrigin.x,vOrigin.y,vOrigin.z}; CWaypointLocations::AddWptLocation(iIndex,fOrigin); - m_pVisibilityTable->workVisibilityForWaypoint(iIndex,true); + m_pVisibilityTable->workVisibilityForWaypoint(iIndex,1); if ( bAutoPath && !(iFlags & CWaypointTypes::W_FL_UNREACHABLE) ) { @@ -2467,40 +2402,43 @@ int CWaypoints :: addWaypoint ( edict_t *pPlayer, Vector vOrigin, int iFlags, bo return iIndex; } -void CWaypoints :: removeWaypoint ( int iIndex ) +void CWaypoints :: removeWaypoint (const int iIndex) { if ( iIndex >= 0 ) m_theWaypoints[iIndex].setUsed(false); } -int CWaypoints :: numWaypoints () +int CWaypoints::numWaypoints() { return m_iNumWaypoints; } +// TODO: Needs implemented properly [APG]RoboCop[CL] +bool CWaypoints::checkReachable(CWaypoint* pWaypoint, int iStart) +{ + return false; +} + /////////// -int CWaypoints :: nearestWaypointGoal ( int iFlags, Vector &origin, float fDist, int iTeam ) +int CWaypoints::nearestWaypointGoal(const int iFlags, const Vector& origin, float fDist, const int iTeam) { - register short int i; static int size; float distance; - int iwpt = -1; - - CWaypoint *pWpt; + int iWpt = -1; size = numWaypoints(); CBotMod *pCurrentMod = CBotGlobals::getCurrentMod(); - for ( i = 0; i < size; i ++ ) + for ( int i = 0; i < size; i ++ ) { - pWpt = &m_theWaypoints[i]; + CWaypoint* pWpt = &m_theWaypoints[i]; if ( pWpt->isUsed() && pWpt->forTeam(iTeam) ) { - if ( (iFlags == -1) || pWpt->hasFlag(iFlags) ) + if ( iFlags == -1 || pWpt->hasFlag(iFlags) ) { // FIX DODS bug if (pCurrentMod->isWaypointAreaValid(pWpt->getArea(), iFlags)) // CTeamFortress2Mod::m_ObjectiveResource.isWaypointAreaValid(pWpt->getArea())) @@ -2508,45 +2446,43 @@ int CWaypoints :: nearestWaypointGoal ( int iFlags, Vector &origin, float fDist, if ( (distance = pWpt->distanceFrom(origin)) < fDist) { fDist = distance; - iwpt = i; + iWpt = i; } } } } } - return iwpt; + return iWpt; } -CWaypoint *CWaypoints :: randomRouteWaypoint ( CBot *pBot, Vector vOrigin, Vector vGoal, int iTeam, int iArea ) +CWaypoint *CWaypoints :: randomRouteWaypoint (const CBot *pBot, const Vector& vOrigin, const Vector& vGoal, const int iTeam, const int iArea) { - register short int i; - static short int size; - static CWaypoint *pWpt; + static int size; static CWaypointNavigator *pNav; - pNav = (CWaypointNavigator*)pBot->getNavigator(); + pNav = static_cast(pBot->getNavigator()); size = numWaypoints(); - dataUnconstArray goals; + std::vector goals; - for ( i = 0; i < size; i ++ ) + for ( int i = 0; i < size; i ++ ) { - pWpt = &m_theWaypoints[i]; + CWaypoint *pWpt = &m_theWaypoints[i]; if ( pWpt->isUsed() && pWpt->forTeam(iTeam) )// && (pWpt->getArea() == iArea) ) { if ( pWpt->hasFlag(CWaypointTypes::W_FL_ROUTE) ) { - if ((pWpt->getArea() != iArea) ) + if (pWpt->getArea() != iArea ) continue; // CHECK THAT ROUTE WAYPOINT IS USEFUL... Vector vRoute = pWpt->getOrigin(); - if ( (vRoute - vOrigin).Length() < ((vGoal - vOrigin).Length()+128.0f) ) + if ( (vRoute - vOrigin).Length() < (vGoal - vOrigin).Length()+128.0f ) { //if ( CWaypointDistances::getDistance() ) /*Vector vecLOS; @@ -2562,25 +2498,20 @@ CWaypoint *CWaypoints :: randomRouteWaypoint ( CBot *pBot, Vector vOrigin, Vecto flDot = DotProduct (vecLOS , vForward ); if ( flDot > 0.17f ) // 80 degrees*/ - goals.Add(pWpt); + goals.emplace_back(pWpt); } } } } - pWpt = NULL; - - if ( !goals.IsEmpty() ) + if ( !goals.empty() ) { - pWpt = pNav->chooseBestFromBelief(&goals); + return pNav->chooseBestFromBelief(goals); } - - goals.Clear(); - - return pWpt; + return nullptr; } -#define MAX_DEPTH 10 +constexpr int MAX_DEPTH = 10; /* void CWaypointNavigator::runAwayFrom ( int iId ) { @@ -2599,15 +2530,13 @@ void CWaypointNavigator::runAwayFrom ( int iId ) CWaypoint *CWaypoints::getNextCoverPoint ( CBot *pBot, CWaypoint *pCurrent, CWaypoint *pBlocking ) { int iMaxDist = -1; - int iNext; float fMaxDist = 0.0f; float fDist = 0.0f; - CWaypoint *pNext; for ( int i = 0; i < pCurrent->numPaths(); i ++ ) { - iNext = pCurrent->getPath(i); - pNext = CWaypoints::getWaypoint(iNext); + const int iNext = pCurrent->getPath(i); + CWaypoint* pNext = CWaypoints::getWaypoint(iNext); if ( pNext == pBlocking ) continue; @@ -2615,7 +2544,7 @@ CWaypoint *CWaypoints::getNextCoverPoint ( CBot *pBot, CWaypoint *pCurrent, CWay if ( !pBot->canGotoWaypoint(pCurrent->getOrigin(),pNext,pCurrent) ) continue; - if ( (iMaxDist == -1) || ((fDist=pNext->distanceFrom(pBlocking->getOrigin())) > fMaxDist) ) + if ( iMaxDist == -1 || (fDist=pNext->distanceFrom(pBlocking->getOrigin())) > fMaxDist ) { fMaxDist = fDist; iMaxDist = iNext; @@ -2623,61 +2552,59 @@ CWaypoint *CWaypoints::getNextCoverPoint ( CBot *pBot, CWaypoint *pCurrent, CWay } if ( iMaxDist == -1 ) - return NULL; + return nullptr; return CWaypoints::getWaypoint(iMaxDist); } -CWaypoint *CWaypoints :: nearestPipeWaypoint ( Vector vTarget, Vector vOrigin, int *iAiming ) +CWaypoint *CWaypoints :: nearestPipeWaypoint (const Vector& vTarget, const Vector& vOrigin, int *iAiming) { // 1 : find nearest waypoint to vTarget // 2 : loop through waypoints find visible waypoints to vTarget // 3 : loop through visible waypoints find another waypoint invisible to vTarget but visible to waypoint 2 - short int iTarget = (short int)CWaypointLocations::NearestWaypoint(vTarget,BLAST_RADIUS,-1,true,true); - CWaypoint *pTarget = CWaypoints::getWaypoint(iTarget); + const short iTarget = static_cast(CWaypointLocations::NearestWaypoint(vTarget,BLAST_RADIUS, -1, true, true)); + const CWaypoint *pTarget = CWaypoints::getWaypoint(iTarget); //vector waypointlist; int inearest = -1; - if ( pTarget == NULL ) - return NULL; + if ( pTarget == nullptr) + return nullptr; - CWaypointVisibilityTable *pTable = CWaypoints::getVisiblity(); + const CWaypointVisibilityTable *pTable = CWaypoints::getVisiblity(); - register short int numwaypoints = (short int)numWaypoints(); + const short numwaypoints = static_cast(numWaypoints()); float finearestdist = 9999.0f; float fjnearestdist = 9999.0f; float fidist; float fjdist; - CWaypoint *pTempi,*pTempj; - - for ( register short int i = 0; i < numwaypoints; i ++ ) + for (short int i = 0; i < numwaypoints; i ++ ) { if ( iTarget == i ) continue; - pTempi = CWaypoints::getWaypoint(i); + CWaypoint* pTempi = CWaypoints::getWaypoint(i); if ( (fidist=pTarget->distanceFrom(pTempi->getOrigin())) > finearestdist ) continue; - if ( pTable->GetVisibilityFromTo((int)iTarget,(int)i) ) + if ( pTable->GetVisibilityFromTo(iTarget,i) ) { - for ( register short int j = 0; j < numwaypoints; j ++ ) + for (short int j = 0; j < numwaypoints; j ++ ) { if ( j == i ) continue; if ( j == iTarget ) continue; - pTempj = CWaypoints::getWaypoint(j); + const CWaypoint* pTempj = CWaypoints::getWaypoint(j); if ( (fjdist=pTempj->distanceFrom(vOrigin)) > fjnearestdist ) continue; - if ( pTable->GetVisibilityFromTo((int)i,(int)j) && !pTable->GetVisibilityFromTo((int)iTarget,(int)j) ) + if ( pTable->GetVisibilityFromTo(i,j) && !pTable->GetVisibilityFromTo(iTarget,j) ) { finearestdist = fidist; fjnearestdist = fjdist; @@ -2692,24 +2619,30 @@ CWaypoint *CWaypoints :: nearestPipeWaypoint ( Vector vTarget, Vector vOrigin, i } -void CWaypoints :: autoFix ( bool bAutoFixNonArea ) +void CWaypoints :: autoFix (const bool bAutoFixNonArea) { - int *iNumAreas = CTeamFortress2Mod::m_ObjectiveResource.m_iNumControlPoints; - int iNumCps; + const int *iNumAreas = CTeamFortress2Mod::m_ObjectiveResource.m_iNumControlPoints; - if ( iNumAreas == NULL ) + if ( iNumAreas == nullptr) return; - iNumCps = *iNumAreas + 1; + const int iNumCps = *iNumAreas + 1; for ( int i = 0; i < numWaypoints(); i ++ ) { - if ( m_theWaypoints[i].isUsed() && (m_theWaypoints[i].getFlags() > 0) ) + if ( m_theWaypoints[i].isUsed() && m_theWaypoints[i].getFlags() > 0 ) { - if ( ( m_theWaypoints[i].getArea() > iNumCps ) || ( bAutoFixNonArea && ( m_theWaypoints[i].getArea()==0) && m_theWaypoints[i].hasSomeFlags(CWaypointTypes::W_FL_SENTRY|CWaypointTypes::W_FL_DEFEND|CWaypointTypes::W_FL_SNIPER|CWaypointTypes::W_FL_CAPPOINT|CWaypointTypes::W_FL_TELE_EXIT) ) ) + if (m_theWaypoints[i].getArea() > iNumCps || + (bAutoFixNonArea && + m_theWaypoints[i].getArea() == 0 && + m_theWaypoints[i].hasSomeFlags(CWaypointTypes::W_FL_SENTRY | + CWaypointTypes::W_FL_DEFEND | + CWaypointTypes::W_FL_SNIPER | + CWaypointTypes::W_FL_CAPPOINT | + CWaypointTypes::W_FL_TELE_EXIT))) { m_theWaypoints[i].setArea(CTeamFortress2Mod::m_ObjectiveResource.NearestArea(m_theWaypoints[i].getOrigin())); - CBotGlobals::botMessage(NULL,0,"Changed Waypoint id %d area to (area = %d)",i,m_theWaypoints[i].getArea()); + CBotGlobals::botMessage(nullptr,0,"Changed Waypoint id %d area to (area = %d)",i,m_theWaypoints[i].getArea()); } } } @@ -2717,17 +2650,16 @@ void CWaypoints :: autoFix ( bool bAutoFixNonArea ) void CWaypoints :: checkAreas ( edict_t *pActivator ) { - int *iNumAreas = CTeamFortress2Mod::m_ObjectiveResource.m_iNumControlPoints; - int iNumCps; + const int *iNumAreas = CTeamFortress2Mod::m_ObjectiveResource.m_iNumControlPoints; - if ( iNumAreas == NULL ) + if ( iNumAreas == nullptr) return; - iNumCps = *iNumAreas + 1; + const int iNumCps = *iNumAreas + 1; for ( int i = 0; i < numWaypoints(); i ++ ) { - if ( m_theWaypoints[i].isUsed() && (m_theWaypoints[i].getFlags() > 0) ) + if ( m_theWaypoints[i].isUsed() && m_theWaypoints[i].getFlags() > 0 ) { if ( m_theWaypoints[i].getArea() > iNumCps ) { @@ -2737,24 +2669,26 @@ void CWaypoints :: checkAreas ( edict_t *pActivator ) } } -CWaypoint *CWaypoints :: randomWaypointGoalNearestArea ( int iFlags, int iTeam, int iArea, bool bForceArea, CBot *pBot, bool bHighDanger, Vector *origin, int iIgnore, bool bIgnoreBelief, int iWpt1 ) +CWaypoint* CWaypoints::randomWaypointGoalNearestArea(const int iFlags, const int iTeam, const int iArea, const bool bForceArea, + const CBot* pBot, const bool bHighDanger, const Vector* origin, + const int iIgnore, const bool bIgnoreBelief, int iWpt1) { - register short int i; - static short int size; + static int size; CWaypoint *pWpt; AStarNode *node; float fDist; size = numWaypoints(); - dataUnconstArray goals; + // TODO: inline AStarNode entries + std::vector goals; CBotMod *pCurrentMod = CBotGlobals::getCurrentMod(); if ( iWpt1 == -1 ) - iWpt1 = CWaypointLocations::NearestWaypoint(*origin,200,-1); + iWpt1 = CWaypointLocations::NearestWaypoint(*origin,200.0f,-1); - for ( i = 0; i < size; i ++ ) + for ( int i = 0; i < size; i ++ ) { if ( i == iIgnore ) continue; @@ -2763,12 +2697,12 @@ CWaypoint *CWaypoints :: randomWaypointGoalNearestArea ( int iFlags, int iTeam, if ( pWpt->isUsed() && pWpt->forTeam(iTeam) )// && (pWpt->getArea() == iArea) ) { - if ( (iFlags == -1) || pWpt->hasSomeFlags(iFlags) ) + if ( iFlags == -1 || pWpt->hasSomeFlags(iFlags) ) { //DOD:S Bug if (!bForceArea && !pCurrentMod->isWaypointAreaValid(pWpt->getArea(), iFlags)) continue; - else if ( bForceArea && (pWpt->getArea() != iArea) ) + if ( bForceArea && pWpt->getArea() != iArea ) continue; node = new AStarNode(); @@ -2788,73 +2722,71 @@ CWaypoint *CWaypoints :: randomWaypointGoalNearestArea ( int iFlags, int iTeam, node->setWaypoint(i); node->setHeuristic(131072.0f/(fDist*fDist)); - goals.Add(node); + goals.emplace_back(node); } } } - pWpt = NULL; + pWpt = nullptr; - if ( !goals.IsEmpty() ) + if ( !goals.empty() ) { if ( pBot ) { - CWaypointNavigator *pNav; - - pNav = (CWaypointNavigator*)pBot->getNavigator(); - - pWpt = pNav->chooseBestFromBeliefBetweenAreas(&goals,bHighDanger,bIgnoreBelief); + const CWaypointNavigator* pNav = static_cast(pBot->getNavigator()); + pWpt = pNav->chooseBestFromBeliefBetweenAreas(goals, bHighDanger, bIgnoreBelief); } else - pWpt = CWaypoints::getWaypoint(goals.Random()->getWaypoint()); - + { + // Ensure the index is of type std::size_t + std::size_t randomIndex = static_cast(randomInt(0, static_cast(goals.size()) - 1)); + pWpt = CWaypoints::getWaypoint(goals[randomIndex]->getWaypoint()); + } //pWpt = goals.Random(); } - for ( i = 0; i < goals.Size(); i ++ ) + for (AStarNode* const& goal : goals) { - node = goals.ReturnValueFromIndex(i); - + node = goal; delete node; } - goals.Clear(); - return pWpt; } -CWaypoint *CWaypoints :: randomWaypointGoalBetweenArea ( int iFlags, int iTeam, int iArea, bool bForceArea, CBot *pBot, bool bHighDanger, Vector *org1, Vector *org2, bool bIgnoreBelief, int iWpt1, int iWpt2 ) +CWaypoint* CWaypoints::randomWaypointGoalBetweenArea(const int iFlags, const int iTeam, const int iArea, const bool bForceArea, const CBot* pBot, + const bool bHighDanger, const Vector* org1, const Vector* org2, const bool + bIgnoreBelief, int iWpt1, int iWpt2) { - register short int i; - static short int size; + static int size; CWaypoint *pWpt; AStarNode *node; - float fCost = 0; if ( iWpt1 == -1 ) - iWpt1 = CWaypointLocations::NearestWaypoint(*org1,200,-1); + iWpt1 = CWaypointLocations::NearestWaypoint(*org1,200.0f,-1); if ( iWpt2 == -1 ) - iWpt2 = CWaypointLocations::NearestWaypoint(*org2,200,-1); + iWpt2 = CWaypointLocations::NearestWaypoint(*org2,200.0f,-1); size = numWaypoints(); - dataUnconstArray goals; + // TODO: inline AStarNode instead of doing manual `new`s + std::vector goals; - for ( i = 0; i < size; i ++ ) + for ( int i = 0; i < size; i ++ ) { pWpt = &m_theWaypoints[i]; if ( pWpt->isUsed() && pWpt->forTeam(iTeam) )// && (pWpt->getArea() == iArea) ) { - if ( (iFlags == -1) || pWpt->hasSomeFlags(iFlags) ) + if ( iFlags == -1 || pWpt->hasSomeFlags(iFlags) ) { if ( !bForceArea && !CTeamFortress2Mod::m_ObjectiveResource.isWaypointAreaValid(pWpt->getArea()) ) continue; - else if ( bForceArea && (pWpt->getArea() != iArea) ) + if ( bForceArea && pWpt->getArea() != iArea ) continue; - fCost = 0; + float fCost; node = new AStarNode(); @@ -2872,54 +2804,51 @@ CWaypoint *CWaypoints :: randomWaypointGoalBetweenArea ( int iFlags, int iTeam, node->setHeuristic(fCost); - goals.Add(node); + goals.emplace_back(node); } } } - pWpt = NULL; + pWpt = nullptr; - if ( !goals.IsEmpty() ) + if ( !goals.empty() ) { if ( pBot ) { - CWaypointNavigator *pNav; - - pNav = (CWaypointNavigator*)pBot->getNavigator(); + const CWaypointNavigator* pNav = static_cast(pBot->getNavigator()); - pWpt = pNav->chooseBestFromBeliefBetweenAreas(&goals,bHighDanger,bIgnoreBelief); + pWpt = pNav->chooseBestFromBeliefBetweenAreas(goals, bHighDanger, bIgnoreBelief); } else - pWpt = CWaypoints::getWaypoint(goals.Random()->getWaypoint()); + { + pWpt = CWaypoints::getWaypoint(goals[static_cast(randomInt(0, static_cast(goals.size())))]->getWaypoint()); + } //pWpt = goals.Random(); } - for ( i = 0; i < goals.Size(); i ++ ) + for (AStarNode* const& goal : goals) { - node = goals.ReturnValueFromIndex(i); - + node = goal; delete node; } - goals.Clear(); - return pWpt; } -CWaypoint *CWaypoints :: randomWaypointGoal ( int iFlags, int iTeam, int iArea, bool bForceArea, CBot *pBot, bool bHighDanger, int iSearchFlags, int iIgnore ) +CWaypoint* CWaypoints::randomWaypointGoal(const int iFlags, const int iTeam, const int iArea, const bool bForceArea, + const CBot* pBot, const bool bHighDanger, const int iSearchFlags, const int iIgnore) { - register short int i; - static short int size; + static int size; CWaypoint *pWpt; size = numWaypoints(); - dataUnconstArray goals; + std::vector goals; CBotMod *pCurrentMod = CBotGlobals::getCurrentMod(); - for ( i = 0; i < size; i ++ ) + for ( int i = 0; i < size; i ++ ) { if ( iIgnore == i ) continue; @@ -2928,42 +2857,38 @@ CWaypoint *CWaypoints :: randomWaypointGoal ( int iFlags, int iTeam, int iArea, if ( pWpt->isUsed() && pWpt->forTeam(iTeam) )// && (pWpt->getArea() == iArea) ) { - if ( (iFlags == -1) || pWpt->hasSomeFlags(iFlags) ) + if ( iFlags == -1 || pWpt->hasSomeFlags(iFlags) ) { if (!bForceArea && !pCurrentMod->isWaypointAreaValid(pWpt->getArea(), iFlags)) continue; - else if ( bForceArea && (pWpt->getArea() != iArea) ) + if ( bForceArea && pWpt->getArea() != iArea ) continue; - goals.Add(pWpt); + goals.emplace_back(pWpt); } } } - pWpt = NULL; + pWpt = nullptr; - if ( !goals.IsEmpty() ) + if ( !goals.empty() ) { if ( pBot ) { - CWaypointNavigator *pNav; + const CWaypointNavigator* pNav = static_cast(pBot->getNavigator()); - pNav = (CWaypointNavigator*)pBot->getNavigator(); - - pWpt = pNav->chooseBestFromBelief(&goals,bHighDanger,iSearchFlags); + pWpt = pNav->chooseBestFromBelief(goals, bHighDanger, iSearchFlags); } else - pWpt = goals.Random(); - - //pWpt = goals.Random(); + { + pWpt = goals[static_cast(randomInt(0, static_cast(goals.size()) - 1))]; + } } - goals.Clear(); - return pWpt; } -int CWaypoints :: randomFlaggedWaypoint (int iTeam) +int CWaypoints :: randomFlaggedWaypoint (const int iTeam) { return getWaypointIndex(randomWaypointGoal(-1,iTeam)); } @@ -2986,13 +2911,12 @@ bool CWaypoint :: checkReachable () { if ( m_fCheckReachableTime < engine->Time() ) { - CWaypoint *pOther; - int numPathsTo = numPathsToThisWaypoint(); + const int numPathsTo = numPathsToThisWaypoint(); int i; for ( i = 0; i < numPathsTo; i ++ ) { - pOther = CWaypoints::getWaypoint(getPathToThisWaypoint(i)); + CWaypoint* pOther = CWaypoints::getWaypoint(getPathToThisWaypoint(i)); if ( pOther->getFlags() == 0 ) break; @@ -3010,41 +2934,36 @@ bool CWaypoint :: checkReachable () } } - m_bIsReachable = !( i == numPathsTo ); + m_bIsReachable = i != numPathsTo; m_fCheckReachableTime = engine->Time() + 1.0f; } return m_bIsReachable; } -int CWaypoint :: numPaths () +int CWaypoint :: numPaths () const { - return m_thePaths.Size(); + return static_cast(m_thePaths.size()); } -int CWaypoint :: getPath ( int i ) +int CWaypoint :: getPath (const int i) const { - return m_thePaths.ReturnValueFromIndex(i); + return m_thePaths[static_cast(i)]; } -bool CWaypoint :: isPathOpened ( Vector vPath ) +bool CWaypoint :: isPathOpened (const Vector& vPath) { - wpt_opens_later_t *info; - - for ( int i = 0; i < m_OpensLaterInfo.Size(); i ++ ) + for (wpt_opens_later_t& info : m_OpensLaterInfo) { - info = m_OpensLaterInfo.ReturnPointerFromIndex(i); - - if ( info->vOrigin == vPath ) + if ( info.vOrigin == vPath ) { - if ( info->fNextCheck < engine->Time() ) + if ( info.fNextCheck < engine->Time() ) { - info->bVisibleLastCheck = CBotGlobals::checkOpensLater(m_vOrigin,vPath); - - info->fNextCheck = engine->Time() + 2.0f; + info.bVisibleLastCheck = CBotGlobals::checkOpensLater(m_vOrigin,vPath); + info.fNextCheck = engine->Time() + 2.0f; } - return info->bVisibleLastCheck; + return info.bVisibleLastCheck; } } @@ -3055,71 +2974,67 @@ bool CWaypoint :: isPathOpened ( Vector vPath ) newinfo.vOrigin = vPath; newinfo.bVisibleLastCheck = CBotGlobals::checkOpensLater(m_vOrigin,vPath); - m_OpensLaterInfo.Add(newinfo); + m_OpensLaterInfo.emplace_back(newinfo); return newinfo.bVisibleLastCheck; } void CWaypoint :: addPathFrom ( int iWaypointIndex ) { - m_PathsTo.Add(iWaypointIndex); + m_PathsTo.emplace_back(iWaypointIndex); } -void CWaypoint :: removePathFrom ( int iWaypointIndex ) +void CWaypoint :: removePathFrom (const int iWaypointIndex) { - m_PathsTo.Remove(iWaypointIndex); + m_PathsTo.erase(std::remove(m_PathsTo.begin(), m_PathsTo.end(), iWaypointIndex), m_PathsTo.end()); } -int CWaypoint :: numPathsToThisWaypoint () +int CWaypoint :: numPathsToThisWaypoint () const { - return m_PathsTo.Size(); + return static_cast(m_PathsTo.size()); } -int CWaypoint :: getPathToThisWaypoint ( int i ) +int CWaypoint :: getPathToThisWaypoint (const int i) const { - return m_PathsTo.ReturnValueFromIndex(i); + return m_PathsTo[static_cast(i)]; } bool CWaypoint :: addPathTo ( int iWaypointIndex ) { CWaypoint *pTo = CWaypoints::getWaypoint(iWaypointIndex); - if ( pTo == NULL ) + if ( pTo == nullptr) return false; // already in list - if ( m_thePaths.IsMember(iWaypointIndex) ) + if (std::find(m_thePaths.begin(), m_thePaths.end(), iWaypointIndex) != m_thePaths.end()) return false; // dont have a path loop if ( this == pTo ) return false; - m_thePaths.Add(iWaypointIndex); - + m_thePaths.emplace_back(iWaypointIndex); pTo->addPathFrom(CWaypoints::getWaypointIndex(this)); return true; } -Vector CWaypoint :: applyRadius () +Vector CWaypoint :: applyRadius () const { if ( m_fRadius > 0 ) - return Vector(randomFloat(-m_fRadius,m_fRadius),randomFloat(m_fRadius,m_fRadius),0); + return {randomFloat(-m_fRadius,m_fRadius),randomFloat(m_fRadius,m_fRadius),0}; - return Vector(0,0,0); + return {0,0,0}; } -void CWaypoint :: removePathTo ( int iWaypointIndex ) +void CWaypoint :: removePathTo (const int iWaypointIndex) { CWaypoint *pOther = CWaypoints::getWaypoint(iWaypointIndex); - if ( pOther != NULL ) + if ( pOther != nullptr) { - m_thePaths.Remove(iWaypointIndex); - + m_thePaths.erase(std::remove(m_thePaths.begin(), m_thePaths.end(), iWaypointIndex), m_thePaths.end()); pOther->removePathFrom(CWaypoints::getWaypointIndex(this)); } - - return; } void CWaypoint :: info ( edict_t *pEdict ) @@ -3127,7 +3042,7 @@ void CWaypoint :: info ( edict_t *pEdict ) CWaypointTypes::printInfo(this,pEdict); } -bool CWaypoint ::isAiming() +bool CWaypoint ::isAiming() const { return (m_iFlags & (CWaypointTypes::W_FL_DEFEND | CWaypointTypes::W_FL_ROCKET_JUMP | @@ -3142,65 +3057,65 @@ bool CWaypoint ::isAiming() // Waypoint Types ///////////////////////////////////// -CWaypointType *CWaypointTypes :: getType( const char *szType ) +CWaypointType *CWaypointTypes :: getType(const char *szType) { - for ( unsigned int i = 0; i < m_Types.size(); i ++ ) + for (CWaypointType* const& m_Type : m_Types) { - if ( FStrEq(m_Types[i]->getName(),szType) ) - return m_Types[i]; + if ( FStrEq(m_Type->getName(),szType) ) + return m_Type; } - return NULL; + return nullptr; } -void CWaypointTypes :: showTypesOnConsole ( edict_t *pPrintTo ) +void CWaypointTypes :: showTypesOnConsole(edict_t *pPrintTo) { - CBotMod *pMod = CBotGlobals::getCurrentMod(); + const CBotMod *pMod = CBotGlobals::getCurrentMod(); CBotGlobals::botMessage(pPrintTo,0,"Available waypoint types"); - for ( unsigned int i = 0; i < m_Types.size(); i ++ ) + for (CWaypointType* const& m_Type : m_Types) { - const char *name = m_Types[i]->getName(); - const char *description = m_Types[i]->getDescription(); + const char *name = m_Type->getName(); + const char *description = m_Type->getDescription(); - if ( m_Types[i]->forMod(pMod->getModId()) ) + if (m_Type->forMod(pMod->getModId()) ) CBotGlobals::botMessage(pPrintTo,0,"\"%s\" (%s)",name,description); } } void CWaypointTypes:: addType ( CWaypointType *type ) { - m_Types.push_back(type); + m_Types.emplace_back(type); } -CWaypointType *CWaypointTypes :: getTypeByIndex ( unsigned int iIndex ) +CWaypointType *CWaypointTypes :: getTypeByIndex (const std::size_t iIndex) { if ( iIndex < m_Types.size() ) { - return m_Types[iIndex]; + return m_Types[static_cast(iIndex)]; } - else - return NULL; + + return nullptr; } -CWaypointType *CWaypointTypes :: getTypeByFlags ( int iFlags ) +CWaypointType *CWaypointTypes :: getTypeByFlags (const int iFlags) { - CBotMod *pMod = CBotGlobals::getCurrentMod(); + const CBotMod *pMod = CBotGlobals::getCurrentMod(); - for ( unsigned int i = 0; i < m_Types.size(); i ++ ) + for (CWaypointType* const& m_Type : m_Types) { - if ( !m_Types[i]->forMod(pMod->getModId()) ) + if ( !m_Type->forMod(pMod->getModId()) ) continue; - if ( m_Types[i]->getBits() == iFlags ) - return m_Types[i]; + if (m_Type->getBits() == iFlags ) + return m_Type; } - return NULL; + return nullptr; } -unsigned int CWaypointTypes :: getNumTypes () +std::size_t CWaypointTypes::getNumTypes() { return m_Types.size(); } @@ -3208,28 +3123,28 @@ unsigned int CWaypointTypes :: getNumTypes () void CWaypointTypes :: setup () { addType(new CWaypointType(W_FL_NOBLU,"noblueteam","TF2 blue team can't use this waypoint",WptColor(255,0,0),(1<getArea(),pWpt->getRadius()); + Q_snprintf(szMessage, 1024, "Waypoint ID %d (Area = %d | Radius = %0.1f)[", CWaypoints::getWaypointIndex(pWpt), + pWpt->getArea(), static_cast(pWpt->getRadius())); if ( pWpt->getFlags() ) { bool bComma = false; - for ( unsigned int i = 0; i < m_Types.size(); i ++ ) + for (CWaypointType* const& m_Type : m_Types) { - if ( m_Types[i]->forMod(pCurrentMod->getModId()) && m_Types[i]->isBitsInFlags(pWpt->getFlags()) ) + if (m_Type->forMod(pCurrentMod->getModId()) && m_Type->isBitsInFlags(pWpt->getFlags()) ) { if ( bComma ) - strcat(szMessage,","); + std::strcat(szMessage,","); - strcat(szMessage,m_Types[i]->getName()); - //strcat(szMessage," ("); - //strcat(szMessage,m_Types[i]->getDescription()); - //strcat(szMessage,")"); + std::strcat(szMessage, m_Type->getName()); + //std::strcat(szMessage," ("); + //std::strcat(szMessage,m_Types[i]->getDescription()); + //std::strcat(szMessage,")"); bComma = true; } } } else { - strcat(szMessage,"No Waypoint Types"); + std::strcat(szMessage,"No Waypoint Types"); } - strcat(szMessage,"]"); + std::strcat(szMessage,"]"); #ifndef __linux__ debugoverlay->AddTextOverlay(pWpt->getOrigin()+Vector(0,0,24),duration,szMessage); @@ -3303,7 +3232,7 @@ void CWaypointTypes:: printInfo ( CWaypoint *pWpt, edict_t *pPrintTo, float dura /* CCrouchWaypointType :: CCrouchWaypointType() { - CWaypointType(W_FL_CROUCH,"crouch","bot will duck here",WptColor(200,100,0)); + CWaypointType(W_FL_CROUCH,"crouch","bot will duck here",WptColor(200,100,0)); } void CCrouchWaypointType :: giveTypeToWaypoint ( CWaypoint *pWaypoint ) @@ -3336,7 +3265,7 @@ void CWaypointType :: removeTypeFromWaypoint ( CWaypoint *pWaypoint ) }*/ -CWaypointType :: CWaypointType (int iBit, const char *szName, const char *szDescription, WptColor vColour, int iModBits, int iImportance ) +CWaypointType :: CWaypointType (const int iBit, const char *szName, const char *szDescription, const WptColor& vColour, const int iModBits, const int iImportance) { m_iBit = iBit; m_szName = CStrings::getString(szName); @@ -3346,7 +3275,7 @@ CWaypointType :: CWaypointType (int iBit, const char *szName, const char *szDesc m_iImportance = iImportance; } -bool CWaypoint :: forTeam ( int iTeam ) +bool CWaypoint :: forTeam (const int iTeam) { CBotMod *pMod = CBotGlobals::getCurrentMod(); @@ -3363,45 +3292,35 @@ bool CWaypoint :: forTeam ( int iTeam ) class CTestBot : public CBotTF2 { public: - CTestBot(edict_t *pEdict, int iTeam, int iClass) + CTestBot(edict_t *pEdict, const int iTeam, int iClass) { - init(); - strcpy(m_szBotName,"Test Bot"); - m_iClass = (TF_Class)iClass; + CBotTF2::init(); + std::strcpy(m_szBotName,"Test Bot"); + m_iClass = static_cast(iClass); m_iTeam = iTeam; m_pEdict = pEdict; - setup(); + CBotTF2::setup(); } }; void CWaypointTest :: go ( edict_t *pPlayer ) { - int i,j; - int iCheck = 0; - //int iCurrentArea = 0; - CWaypoint *pWpt1; - CWaypoint *pWpt2; - - IBotNavigator *pNav; CBot *pBots[2]; - CBot *pBot; pBots[0] = new CTestBot(pPlayer,2,9); pBots[1] = new CTestBot(pPlayer,3,9); - int iBot = 0; - - for ( iBot = 0; iBot < 2; iBot ++ ) + for ( int iBot = 0; iBot < 2; iBot ++ ) { - pBot = pBots[iBot]; + CBot* pBot = pBots[iBot]; - pNav = pBot->getNavigator(); + IBotNavigator* pNav = pBot->getNavigator(); - for ( i = 0; i < CWaypoints::MAX_WAYPOINTS; i ++ ) + for ( int i = 0; i < CWaypoints::MAX_WAYPOINTS; i ++ ) { - pWpt1 = CWaypoints::getWaypoint(i); + CWaypoint* pWpt1 = CWaypoints::getWaypoint(i); - iCheck = 0; + int iCheck = 0; if ( !pWpt1->forTeam(iBot+2) ) continue; @@ -3418,13 +3337,13 @@ void CWaypointTest :: go ( edict_t *pPlayer ) if ( iCheck != 0 ) { - for ( j = 0; j < CWaypoints::MAX_WAYPOINTS; j ++ ) + for ( int j = 0; j < CWaypoints::MAX_WAYPOINTS; j ++ ) { if ( i == j ) continue; - pWpt2 = CWaypoints::getWaypoint(j); + CWaypoint* pWpt2 = CWaypoints::getWaypoint(j); if ( !pWpt2->forTeam(iBot+2) ) continue; @@ -3434,24 +3353,24 @@ void CWaypointTest :: go ( edict_t *pPlayer ) if ( !pBot->canGotoWaypoint(Vector(0,0,0),pWpt2) ) continue; - if ( (pWpt2->getArea() != 0) && (pWpt2->getArea() != pWpt1->getArea()) ) + if ( pWpt2->getArea() != 0 && pWpt2->getArea() != pWpt1->getArea() ) continue; if ( pWpt2->hasSomeFlags(iCheck) ) { bool bfail = false; - bool brestart = true; - bool bnointerruptions = true; + constexpr bool brestart = true; + constexpr bool bnointerruptions = true; while ( pNav->workRoute( - pWpt1->getOrigin(), - pWpt2->getOrigin(), - &bfail, - brestart, - bnointerruptions,j) + pWpt1->getOrigin(), + pWpt2->getOrigin(), + &bfail, + brestart, + bnointerruptions,j) == false - ); + ) {} if ( bfail ) { @@ -3462,7 +3381,6 @@ void CWaypointTest :: go ( edict_t *pPlayer ) } } } - } delete pBots[0]; diff --git a/utils/RCBot2_meta/bot_waypoint.h b/utils/RCBot2_meta/bot_waypoint.h index dba429497..0795a04c7 100644 --- a/utils/RCBot2_meta/bot_waypoint.h +++ b/utils/RCBot2_meta/bot_waypoint.h @@ -31,14 +31,18 @@ #ifndef __RCBOT_WAYPOINT_H__ #define __RCBOT_WAYPOINT_H__ -#include +#include + +// this must be before bot_client.h to avoid unknown override / missing type warnings +#include +using WaypointList = std::vector; #include "bot.h" -#include "bot_genclass.h" #include "bot_client.h" +#include "bot_mtrand.h" #include "bot_wpt_color.h" -//#include "bot_navigator.h" +// #include "bot_navigator.h" class CWaypointVisibilityTable; class CClient; @@ -61,21 +65,21 @@ class CWaypointHeader int iFlags; }; -typedef struct +struct edict_wpt_pair_t { MyEHandle pEdict; // MyEHandle fixes problems with reused edict slots CWaypoint *pWaypoint; Vector v_ground; -}edict_wpt_pair_t; +}; -enum +enum : std::uint8_t { - DRAWTYPE_EFFECTS = 0, - DRAWTYPE_DEBUGENGINE, - DRAWTYPE_DEBUGENGINE2, - DRAWTYPE_DEBUGENGINE3, - DRAWTYPE_BELIEF, - DRAWTYPE_MAX + DRAWTYPE_EFFECTS = 0, + DRAWTYPE_DEBUGENGINE, + DRAWTYPE_DEBUGENGINE2, + DRAWTYPE_DEBUGENGINE3, + DRAWTYPE_BELIEF, + DRAWTYPE_MAX }; class CWaypoint; @@ -84,22 +88,21 @@ class CWaypoint; class CWaypointType { public: + CWaypointType ( int iBit, const char *szName, const char *szDescription, const WptColor& vColour, int iModBits = BITS_MOD_ALL, int iImportance = 0 ); - CWaypointType ( int iBit, const char *szName, const char *szDescription, WptColor vColour, int iModBits = BITS_MOD_ALL, int iImportance = 0 ); - - inline const char *getName () { return m_szName; } - inline const char *getDescription () { return m_szDescription; } + const char* getName() const { return m_szName; } + const char* getDescription() const { return m_szDescription; } - inline bool isBitsInFlags ( int iFlags ) { return (iFlags & m_iBit)==m_iBit; } - inline int getBits () { return m_iBit; } - inline void setMods ( int iMods ){ m_iMods = iMods; }// input bitmask of mods (32 max) - inline bool forMod ( int iMod ) { return ((1<getImportance(); + return m_iImportance < other.getImportance(); } //virtual void giveTypeToWaypoint ( CWaypoint *pWaypoint ); @@ -120,7 +123,7 @@ class CCrouchWaypointType : public CWaypointType { public: CCrouchWaypointType(); - + void giveTypeToWaypoint ( CWaypoint *pWaypoint ); void removeTypeFromWaypoint ( CWaypoint *pWaypoint ); };*/ @@ -129,248 +132,270 @@ class CWaypointTypes { public: - static const int W_FL_NONE = 0; - static const int W_FL_JUMP = 1; - static const int W_FL_CROUCH = 2; - static const int W_FL_UNREACHABLE = 4; - static const int W_FL_LADDER = 8; - static const int W_FL_FLAG = 16; - static const int W_FL_CAPPOINT = 32; - static const int W_FL_NOBLU = 64; - static const int W_FL_NOAXIS = 64; - static const int W_FL_NORED = 128; - static const int W_FL_NOALLIES = 128; - static const int W_FL_HEALTH = 256; - static const int W_FL_OPENS_LATER = 512; - static const int W_FL_ROCKET_JUMP = 1024; - static const int W_FL_BOMB_TO_OPEN = 1024; // DOD:S - static const int W_FL_SNIPER = 2048; - static const int W_FL_AMMO = 4096; - static const int W_FL_RESUPPLY = 8192; - static const int W_FL_BOMBS_HERE = 8192; - static const int W_FL_SENTRY = 16384; - static const int W_FL_MACHINEGUN = 16384; - static const int W_FL_DOUBLEJUMP = 32768; - static const int W_FL_PRONE = 32768; - static const int W_FL_TELE_ENTRANCE = 65536; - static const int W_FL_TELE_EXIT = 131072; - static const int W_FL_DEFEND = 262144; - static const int W_FL_AREAONLY = 524288; - static const int W_FL_ROUTE = 1048576; - static const int W_FL_WAIT_GROUND = 2097152; - static const int W_FL_NO_FLAG = 4194304; - static const int W_FL_COVER_RELOAD = 4194304; // DOD:S only - static const int W_FL_LIFT = 8388608; - static const int W_FL_FLAGONLY = 16777216; - static const int W_FL_FALL = 33554432; - static const int W_FL_BREAKABLE = 67108864; - static const int W_FL_SPRINT = 134217728; - static const int W_FL_TELEPORT_CHEAT = 268435456; // teleports bots to the next waypoint (cheat) - static const int W_FL_OWNER_ONLY = 536870912; // Only owners of this area can use the waypoint - //static const int W_FL_ATTACKPOINT = 1073741824; // Tactical waypoint -- each squad will go to different attack points and signal others to go - - static void setup (); - - static void addType ( CWaypointType *type ); - - static void printInfo ( CWaypoint *pWpt, edict_t *pPrintTo, float duration = 6.0f ); - - static void displayTypesMenu ( edict_t *pPrintTo ); +// if you're adding a new waypoint type, don't forget to update CWaypointTypes :: setup() + static constexpr int W_FL_NONE = 0; + static constexpr int W_FL_JUMP = 1 << 0; + static constexpr int W_FL_CROUCH = 1 << 1; + static constexpr int W_FL_UNREACHABLE = 1 << 2; + static constexpr int W_FL_LADDER = 1 << 3; + + static constexpr int W_FL_FLAG = 1 << 4; + static constexpr int W_FL_RESCUEZONE = 1 << 4; // Counter-Strike: Source --> Hostage rescue zone + + static constexpr int W_FL_CAPPOINT = 1 << 5; + static constexpr int W_FL_GOAL = 1 << 5; // Synergy & Counter-Strike: Source --> Map Goal + + static constexpr int W_FL_NOBLU = 1 << 6; + static constexpr int W_FL_NOAXIS = 1 << 6; + static constexpr int W_FL_NOTERRORIST = 1 << 6; // Counter-Strike: Source --> Terrorists cannot use this waypoint + + static constexpr int W_FL_NORED = 1 << 7; + static constexpr int W_FL_NOALLIES = 1 << 7; + static constexpr int W_FL_NOCOUNTERTR = 1 << 7; // Counter-Strike: Source --> Counter-Terrorists cannot use this waypoint + + static constexpr int W_FL_HEALTH = 1 << 8; + static constexpr int W_FL_OPENS_LATER = 1 << 9; - static CWaypointType *getType( const char *szType ); + static constexpr int W_FL_ROCKET_JUMP = 1 << 10; + static constexpr int W_FL_BOMB_TO_OPEN = 1 << 10; // DOD:S + static constexpr int W_FL_DOOR = 1 << 10; // Counter-Strike: Source --> Check for door + + static constexpr int W_FL_SNIPER = 1 << 11; + static constexpr int W_FL_AMMO = 1 << 12; + + static constexpr int W_FL_RESUPPLY = 1 << 13; + static constexpr int W_FL_BOMBS_HERE = 1 << 13; + + static constexpr int W_FL_SENTRY = 1 << 14; + static constexpr int W_FL_MACHINEGUN = 1 << 14; + + static constexpr int W_FL_DOUBLEJUMP = 1 << 15; + static constexpr int W_FL_PRONE = 1 << 15; + static constexpr int W_FL_TELE_ENTRANCE = 1 << 16; + static constexpr int W_FL_TELE_EXIT = 1 << 17; + static constexpr int W_FL_DEFEND = 1 << 18; + static constexpr int W_FL_AREAONLY = 1 << 19; + static constexpr int W_FL_ROUTE = 1 << 20; + static constexpr int W_FL_WAIT_GROUND = 1 << 21; + + static constexpr int W_FL_NO_FLAG = 1 << 22; + static constexpr int W_FL_COVER_RELOAD = 1 << 22; // DOD:S only + static constexpr int W_FL_NO_HOSTAGES = 1 << 22; // Counter-Strike: Source --> Bots escorting hostages cannot use this waypoint + + static constexpr int W_FL_LIFT = 1 << 23; + static constexpr int W_FL_FLAGONLY = 1 << 24; + static constexpr int W_FL_FALL = 1 << 25; + static constexpr int W_FL_BREAKABLE = 1 << 26; + static constexpr int W_FL_SPRINT = 1 << 27; + static constexpr int W_FL_TELEPORT_CHEAT = 1 << 28; // teleports bots to the next waypoint (cheat) + static constexpr int W_FL_OWNER_ONLY = 1 << 29; // Only owners of this area can use the waypoint + static constexpr int W_FL_USE = 1 << 30; // Synergy: Use Button/Door + //static const int W_FL_ATTACKPOINT = (1 << 30); // Tactical waypoint -- each squad will go to different attack points and signal others to go + + static void setup(); + + static void addType(CWaypointType *type); - static void showTypesOnConsole( edict_t *pPrintTo ); + static void printInfo(CWaypoint *pWpt, edict_t *pPrintTo, float duration = 6.0f); - static void selectedType ( CClient *pClient ); + static void displayTypesMenu(edict_t *pPrintTo); - static void freeMemory (); + static CWaypointType *getType(const char *szType); - static WptColor getColour ( int iFlags ); + static void showTypesOnConsole(edict_t *pPrintTo); - static CWaypointType *getTypeByIndex ( unsigned int iIndex ); + static void selectedType(CClient *pClient); - static unsigned int getNumTypes (); + static void freeMemory(); - static CWaypointType *getTypeByFlags ( int iFlags ); + static WptColor getColour(int iFlags); + + static CWaypointType *getTypeByIndex(std::size_t iIndex); + + static std::size_t getNumTypes(); + + static CWaypointType *getTypeByFlags(int iFlags); private: - static vector m_Types; + static std::vector m_Types; }; class CWaypointTest { public: - void go ( edict_t *pPlayer ); + void go(edict_t* pPlayer); }; -typedef struct +struct wpt_opens_later_t { float fNextCheck; Vector vOrigin; bool bVisibleLastCheck; -}wpt_opens_later_t; +}; class CWaypoint //: public INavigatorNode { public: //static const int MAX_PATHS = 8; // Waypoint flags (up to 32) - - - static const int WAYPOINT_HEIGHT = 72; - static const int WAYPOINT_WIDTH = 8; - static const int PATHWAYPOINT_WIDTH = 4; + + static constexpr float WAYPOINT_HEIGHT = 72.0f; + static constexpr int WAYPOINT_WIDTH = 8; + static constexpr int PATHWAYPOINT_WIDTH = 4; CWaypoint () { - m_thePaths.Init(); + m_thePaths.clear(); init(); -// m_iId = -1; + //m_iId = -1; } - CWaypoint ( Vector vOrigin, int iFlags = 0, int iYaw = 0, int m_fRadius = 0 ) + CWaypoint(const Vector& vOrigin, const int iFlags = 0, const int iYaw = 0) { - m_thePaths.Clear(); - init(); - m_iFlags = iFlags; - m_vOrigin = vOrigin; + m_thePaths.clear(); + init(); // this function resets a bunch of variables that are manually set again below - caxanga334 m_bUsed = true; setAim(iYaw); - m_fNextCheckGroundTime = 0; + m_fNextCheckGroundTime = 0.0f; m_bHasGround = false; - m_fRadius = 0; - m_OpensLaterInfo.Clear(); - m_bIsReachable = true; - m_fCheckReachableTime = 0; -// m_iId = iId; + m_fRadius = 0.0f; + m_OpensLaterInfo.clear(); + m_bIsReachable = true; + m_fCheckReachableTime = 0.0f; + m_vOrigin = vOrigin; + m_iFlags = iFlags; + //m_iId = iId; } - bool checkGround (); + bool checkGround(); - inline void setAim ( int iYaw ) + void setAim(const int fYaw) { - m_iAimYaw = iYaw; + m_iAimYaw = fYaw; } - inline float getAimYaw () + float getAimYaw() const { - return (float)m_iAimYaw; + return static_cast(m_iAimYaw); } - inline Vector getOrigin () + Vector getOrigin() { return m_vOrigin; } - void init (); + void init(); - inline void addFlag ( int iFlag ) + void addFlag(const int iFlag) { m_iFlags |= iFlag; } - inline void removeFlag ( int iFlag ) + void removeFlag(const int iFlag) { m_iFlags &= ~iFlag; } // removes all waypoint flags - inline void removeFlags () + void removeFlags() { m_iFlags = 0; } - inline bool hasFlag ( int iFlag ) + bool hasFlag(const int iFlag) const { return (m_iFlags & iFlag) == iFlag; } - inline bool hasSomeFlags ( int iFlag ) + bool hasSomeFlags(const int iFlag) const { return (m_iFlags & iFlag) > 0; } - inline void move ( Vector origin ) + void move(const Vector& origin) { // move to new origin m_vOrigin = origin; } - void checkAreas ( edict_t *pActivator ); + void checkAreas(edict_t *pActivator); // TODO: Needs implemented properly [APG]RoboCop[CL] // show info to player - void info ( edict_t *pEdict ); + void info(edict_t *pEdict); // methods - void touched (); + void touched(); // TODO: Needs implemented properly [APG]RoboCop[CL] - void draw ( edict_t *pEdict, bool bDrawPaths, unsigned short int iDrawType ); + void draw(edict_t* pEdict, bool bDrawPaths, unsigned short int iDrawType); - bool addPathTo ( int iWaypointIndex ); - void removePathTo ( int iWaypointIndex ); - - void addPathFrom ( int iWaypointIndex ); - void removePathFrom ( int iWaypointIndex ); + bool addPathTo(int iWaypointIndex); + void removePathTo(int iWaypointIndex); + + void addPathFrom(int iWaypointIndex); + void removePathFrom(int iWaypointIndex); - bool checkReachable (); + bool checkReachable(); - bool isPathOpened ( Vector vPath ); + bool isPathOpened(const Vector& vPath); - inline bool isUsed () + bool isUsed() const { return m_bUsed; } //bool touched ( edict_t *pEdict ); - bool touched ( Vector vOrigin, Vector vOffset, float fTouchDist, bool onground = true ); + bool touched(const Vector& vOrigin, const Vector& vOffset, float fTouchDist, bool onground = true); - void botTouch ( CBot *pBot ); + static void botTouch ( CBot *pBot ); // TODO: Needs implemented properly [APG]RoboCop[CL] - inline void freeMapMemory () + void freeMapMemory() { - m_thePaths.Clear();//Destroy(); + m_thePaths.clear(); } - inline int getArea () { return m_iArea; } - inline void setArea (int area) { m_iArea = area; } + int getArea() const { return m_iArea; } + void setArea(const int area) { m_iArea = area; } - void drawPaths ( edict_t *pEdict, unsigned short int iDrawType ); + void drawPaths(edict_t* pEdict, unsigned short int iDrawType) const; - void drawPathBeam ( CWaypoint *to, unsigned short int iDrawType ); + void drawPathBeam(CWaypoint* to, unsigned short int iDrawType) const; - inline void setUsed ( bool bUsed ){ m_bUsed = bUsed;} + void setUsed(const bool bUsed) { m_bUsed = bUsed; } - inline void clearPaths (); + inline void clearPaths(); - inline float distanceFrom ( CWaypoint *other ) + float distanceFrom(CWaypoint* other) const { return distanceFrom(other->getOrigin()); } - float distanceFrom ( Vector vOrigin ); + float distanceFrom(const Vector& vOrigin) const; - int numPaths (); + int numPaths() const; - int numPathsToThisWaypoint (); - int getPathToThisWaypoint ( int i ); + int numPathsToThisWaypoint() const; + int getPathToThisWaypoint(int i) const; - int getPath ( int i ); + int getPath(int i) const; - void load ( FILE *bfp, int iVersion ); + WaypointList::const_iterator begin() const { return m_thePaths.begin(); } + WaypointList::const_iterator end() const { return m_thePaths.end(); } - void save ( FILE *bfp ); + void load(std::fstream& bfp, int iVersion); - inline int getFlags (){return m_iFlags;} + void save(std::fstream& bfp); - bool forTeam ( int iTeam ); + int getFlags() const { return m_iFlags; } - inline float getRadius () { return m_fRadius; } + bool forTeam(int iTeam); - inline void setRadius ( float fRad ) { m_fRadius = fRad; } + float getRadius() const { return m_fRadius; } - Vector applyRadius (); + void setRadius(const float fRad) { m_fRadius = fRad; } - bool isAiming ( void ); + Vector applyRadius() const; + + bool isAiming() const; private: Vector m_vOrigin; @@ -382,121 +407,127 @@ class CWaypoint //: public INavigatorNode // not deleted bool m_bUsed; // paths to other waypoints - dataUnconstArray m_thePaths; + WaypointList m_thePaths; // for W_FL_WAIT_GROUND waypoints float m_fNextCheckGroundTime; bool m_bHasGround; // Update m_iNumPathsTo (For display) bool m_bIsReachable; float m_fCheckReachableTime; - dataUnconstArray m_PathsTo; // paths to this waypoint from other waypoints + WaypointList m_PathsTo; // paths to this waypoint from other waypoints - dataUnconstArray m_OpensLaterInfo; + std::vector m_OpensLaterInfo; }; class CWaypoints { public: - static const int MAX_WAYPOINTS = 1024; - static const int WAYPOINT_VERSION = 4; // waypoint version 4 add author information + static constexpr int MAX_WAYPOINTS = 2048; + static constexpr int WAYPOINT_VERSION = 5; // waypoint version 5 add author information - static const int W_FILE_FL_VISIBILITY = 1; + static constexpr int W_FILE_FL_VISIBILITY = 1; - static void init (const char *pszAuthor = NULL, const char *pszModifiedBy = NULL); + static void init (const char *pszAuthor = nullptr, const char *pszModifiedBy = nullptr); - static inline int getWaypointIndex ( CWaypoint *pWpt ) + static int getWaypointIndex(CWaypoint* pWpt) { - if ( pWpt == NULL ) + if (pWpt == nullptr) return -1; + /** + * This should be nuked. RCBot2 should be upgraded to store waypoints on an unordered_map, the index becomes the key. + * Also just store the waypoint index on the waypoint itself. Valve navmesh doesn't need to look up the area id, each area know it's own ID. + * Better than dealing with this pointer math crap + */ + + // return ((int)pWpt - (int)m_theWaypoints)/sizeof(CWaypoint); - return ((int)pWpt - (int)m_theWaypoints)/sizeof(CWaypoint); + // This will probably not work -caxanga334 + return static_cast((reinterpret_cast(pWpt) - reinterpret_cast(m_theWaypoints)) / sizeof(CWaypoint)); } - static void autoFix ( bool bAutoFixNonArea ); + static void autoFix(bool bAutoFixNonArea); - static void checkAreas ( edict_t *pActivator ); + static void checkAreas(edict_t* pActivator); - static void shiftVisibleAreas ( edict_t *pPlayer, int from, int to ); + static void shiftVisibleAreas(edict_t* pPlayer, int from, int to); - static void drawWaypoints ( CClient *pClient ); + static void drawWaypoints(CClient* pClient); - static int addWaypoint ( CClient *pClient, const char *type1, const char *type2,const char *type3,const char *type4, bool bUseTemplate = false ); + static int addWaypoint(CClient *pClient, const char *type1, const char *type2, const char *type3, const char *type4, bool bUseTemplate = false); - static int addWaypoint ( edict_t *pPlayer, Vector vOrigin, int iFlags = CWaypointTypes::W_FL_NONE, bool bAutoPath = false, int iYaw = 0, int iArea = 0, float fRadius = 0 ); + static int addWaypoint(edict_t* pPlayer, const Vector& vOrigin, int iFlags = CWaypointTypes::W_FL_NONE, bool bAutoPath = false, int iYaw = 0, int iArea = 0, float fRadius = 0.0f); - static void removeWaypoint ( int iIndex ); + static void removeWaypoint(int iIndex); - static int numWaypoints (); + static int numWaypoints(); - static bool checkReachable ( CWaypoint *pWaypoint, int iStart ); + static bool checkReachable(CWaypoint* pWaypoint, int iStart); // TODO: Needs implemented properly [APG]RoboCop[CL] - static CWaypoint *nearestPipeWaypoint ( Vector vTarget, Vector vOrigin, int *iAiming ); + static CWaypoint* nearestPipeWaypoint(const Vector& vTarget, const Vector& vOrigin, int* iAiming); - static int freeWaypointIndex (); + static int freeWaypointIndex(); - static void deletePathsTo ( int iWpt ); - static void deletePathsFrom ( int iWpt ); + static void deletePathsTo(int iWpt); + static void deletePathsFrom(int iWpt); - static void shiftAreas (int val); + static void shiftAreas(int val); - static inline CWaypoint *getWaypoint ( int iIndex ) + static CWaypoint *getWaypoint (const int iIndex) { - if ( !validWaypointIndex(iIndex) ) - return NULL; + if (!validWaypointIndex(iIndex)) + return nullptr; return &m_theWaypoints[iIndex]; } - static CWaypoint *getNextCoverPoint ( CBot *pBot, CWaypoint *pCurrent, CWaypoint *pBlocking ); + static CWaypoint* getNextCoverPoint(CBot* pBot, CWaypoint* pCurrent, CWaypoint* pBlocking); // save waypoints - static bool save ( bool bVisiblityMade, edict_t *pPlayer = NULL, const char *pszAuthor = NULL, const char *pszModifier = NULL ); + static bool save ( bool bVisiblityMade, const edict_t *pPlayer = nullptr, const char *pszAuthor = nullptr, const char *pszModifier = nullptr); // load waypoints - static bool load (const char *szMapName = NULL); + static bool load (const char *szMapName = nullptr); - static inline bool validWaypointIndex ( int iIndex ) + static bool validWaypointIndex (const int iIndex) { - return ((iIndex >= 0) && (iIndex < m_iNumWaypoints)); + return iIndex >= 0 && iIndex < m_iNumWaypoints; } - static void precacheWaypointTexture (); + static void precacheWaypointTexture(); - static int waypointTexture () { return m_iWaypointTexture; } + static int waypointTexture() { return m_iWaypointTexture; } - static void deleteWaypoint ( int iIndex ); + static void deleteWaypoint(int iIndex); - static void freeMemory (); + static void freeMemory(); - static int getClosestFlagged ( int iFlags, Vector &vOrigin, int iTeam,float *fReturnDist =NULL, unsigned char *failedwpts = NULL ); + static int getClosestFlagged(int iFlags, const Vector& vOrigin, int iTeam, float* fReturnDist = nullptr, const unsigned char* failedwpts = nullptr); - static int nearestWaypointGoal ( int iFlags, Vector &origin, float fDist, int iTeam = 0 ); - static CWaypoint *randomRouteWaypoint ( CBot *pBot, Vector vOrigin, Vector vGoal, int iTeam, int iArea ); - static CWaypoint *randomWaypointGoal ( int iFlags, int iTeam = 0, int iArea = 0, bool bForceArea = false, CBot *pBot = NULL, bool bHighDanger = false, int iSearchFlags = 0, int iIgnore = -1 ); - static CWaypoint *randomWaypointGoalBetweenArea ( int iFlags, int iTeam, int iArea, bool bForceArea, CBot *pBot, bool bHighDanger, Vector *org1, Vector *org2, bool bIgnoreBelief = false, int iWpt1 = -1, int iWpt2 = -1 ); - static CWaypoint *randomWaypointGoalNearestArea ( int iFlags, int iTeam, int iArea, bool bForceArea, CBot *pBot, bool bHighDanger, Vector *origin, int iIgnore = -1, bool bIgnoreBelief = false, int iWpt1 = -1 ); - static int randomFlaggedWaypoint (int iTeam = 0); + static int nearestWaypointGoal(int iFlags, const Vector& origin, float fDist, int iTeam = 0); + static CWaypoint* randomRouteWaypoint(const CBot* pBot, const Vector& vOrigin, const Vector& vGoal, int iTeam, int iArea); + static CWaypoint* randomWaypointGoal(int iFlags, int iTeam = 0, int iArea = 0, bool bForceArea = false, const CBot* pBot = nullptr, bool bHighDanger = false, int iSearchFlags = 0, int iIgnore = -1); + static CWaypoint* randomWaypointGoalBetweenArea(int iFlags, int iTeam, int iArea, bool bForceArea, const CBot* pBot, bool bHighDanger, const Vector* org1, const Vector* org2, bool bIgnoreBelief = false, int iWpt1 = -1, int iWpt2 = -1); + static CWaypoint* randomWaypointGoalNearestArea(int iFlags, int iTeam, int iArea, bool bForceArea, const CBot* pBot, bool bHighDanger, const Vector* origin, int iIgnore = -1, bool bIgnoreBelief = false, int iWpt1 = -1); + static int randomFlaggedWaypoint(int iTeam = 0); - static CWaypointVisibilityTable *getVisiblity () { return m_pVisibilityTable; } - static void setupVisibility (); - static CWaypoint *getPinchPointFromWaypoint ( Vector vPlayerOrigin, Vector vPinchOrigin ); - static CWaypoint *getNestWaypoint ( int iTeam, int iArea, bool bForceArea = false, CBot *pBot = NULL ); + static CWaypointVisibilityTable* getVisiblity() { return m_pVisibilityTable; } + static void setupVisibility(); + static CWaypoint* getPinchPointFromWaypoint(const Vector& vPlayerOrigin, const Vector& vPinchOrigin); + static CWaypoint* getNestWaypoint(int iTeam, int iArea, bool bForceArea = false, CBot* pBot = nullptr); + + static void updateWaypointPairs(std::vector* pPairs, int iWptFlag, const char* szClassname); + static const char* getAuthor() { return m_szAuthor; } + static const char* getModifier() { return m_szModifiedBy; } + static const char* getWelcomeMessage() { return m_szWelcomeMessage; } - static void updateWaypointPairs ( vector *pPairs, int iWptFlag, const char *szClassname ); - static bool hasAuthor () { return (m_szAuthor[0]!=0); } - static const char *getAuthor() { return m_szAuthor; } - static bool isModified () { return (m_szModifiedBy[0]!=0); } - static const char *getModifier() { return m_szModifiedBy; } - static const char *getWelcomeMessage () { return m_szWelcomeMessage; } private: - static CWaypoint m_theWaypoints[MAX_WAYPOINTS]; + static CWaypoint m_theWaypoints[MAX_WAYPOINTS]; static int m_iNumWaypoints; static float m_fNextDrawWaypoints; static int m_iWaypointTexture; - static CWaypointVisibilityTable *m_pVisibilityTable; + static CWaypointVisibilityTable* m_pVisibilityTable; static char m_szAuthor[32]; static char m_szModifiedBy[32]; static char m_szWelcomeMessage[128]; }; - #endif \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_waypoint_locations.cpp b/utils/RCBot2_meta/bot_waypoint_locations.cpp index 95912d9cd..aa5d9751c 100644 --- a/utils/RCBot2_meta/bot_waypoint_locations.cpp +++ b/utils/RCBot2_meta/bot_waypoint_locations.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -30,25 +32,26 @@ */ #include "bot.h" +#include "bot_cvars.h" +#include "bot_globals.h" #include "bot_waypoint.h" -#include "bot_waypoint_visibility.h" #include "bot_waypoint_locations.h" -#include "bot_genclass.h" -#include "bot_globals.h" +#include "bot_waypoint_visibility.h" +#include #include //bir3yk -using namespace std; //bir3yk +#include unsigned char CWaypointLocations :: g_iFailedWaypoints[CWaypoints::MAX_WAYPOINTS]; -dataUnconstArray CWaypointLocations :: m_iLocations[MAX_WPT_BUCKETS][MAX_WPT_BUCKETS][MAX_WPT_BUCKETS]; +WaypointList CWaypointLocations :: m_iLocations[MAX_WPT_BUCKETS][MAX_WPT_BUCKETS][MAX_WPT_BUCKETS]; float CWaypointLocations :: m_fIgnoreSize = 0; Vector CWaypointLocations :: m_vIgnoreLoc = Vector(0,0,0); bool CWaypointLocations :: m_bIgnoreBox = false; -#define READ_LOC(loc) abs((int)((int)(loc + HALF_MAX_MAP_SIZE) / BUCKET_SPACING)); +#define READ_LOC(loc) std::abs((int)((int)((loc) + HALF_MAX_MAP_SIZE) / BUCKET_SPACING)); -unsigned char *CWaypointLocations :: resetFailedWaypoints (dataUnconstArray *iIgnoreWpts) +unsigned char *CWaypointLocations :: resetFailedWaypoints (const WaypointList *iIgnoreWpts) { Q_memset(g_iFailedWaypoints,0,sizeof(unsigned char)*CWaypoints::MAX_WAYPOINTS); @@ -58,9 +61,9 @@ unsigned char *CWaypointLocations :: resetFailedWaypoints (dataUnconstArray int iWpt; //while ( !ignoreWptStack.IsEmpty() ) - for ( int l = 0; l < iIgnoreWpts->Size(); l ++ ) + for (const int iIgnoreWpt : *iIgnoreWpts) { - if ( (iWpt = (*iIgnoreWpts)[l]) != -1 )//(iWpt = ignoreWptStack.ChooseFromStack()) != -1 ) + if ( (iWpt = iIgnoreWpt) != -1 )//(iWpt = ignoreWptStack.ChooseFromStack()) != -1 ) g_iFailedWaypoints[iWpt] = 1; } } @@ -68,14 +71,14 @@ unsigned char *CWaypointLocations :: resetFailedWaypoints (dataUnconstArray return g_iFailedWaypoints; } -#define CLAMP_TO_ZERO(x) x=(x<0)?0:x -#define CLAMP_TO(x,clamp) x=(x>clamp)?clamp:x +#define CLAMP_TO_ZERO(x) x=((x)<0)?0:x +#define CLAMP_TO(x,clamp) x=((x)>(clamp))?(clamp):x -void CWaypointLocations :: getMinMaxs ( int iLoc, int jLoc, int kLoc, - int *iMinLoci, int *iMinLocj, int *iMinLock, - int *iMaxLoci, int *iMaxLocj, int *iMaxLock ) +void CWaypointLocations :: getMinMaxs (const int iLoc, const int jLoc, const int kLoc, + int *iMinLoci, int *iMinLocj, int *iMinLock, + int *iMaxLoci, int *iMaxLocj, int *iMaxLock ) { - static const int iMaxLoc = MAX_WPT_BUCKETS-1; + static constexpr int iMaxLoc = MAX_WPT_BUCKETS-1; // get current area *iMinLoci = iLoc-1; @@ -98,26 +101,24 @@ void CWaypointLocations :: getMinMaxs ( int iLoc, int jLoc, int kLoc, } /////////////// // return nearest waypoint that can be used to cover from vCoverFrom vector -void CWaypointLocations :: AutoPath ( edict_t *pPlayer, int iWpt ) +void CWaypointLocations :: AutoPath (edict_t *pPlayer, const int iWpt) { CWaypoint *pWpt = CWaypoints::getWaypoint(iWpt); - Vector vOrigin = pWpt->getOrigin(); + const Vector vOrigin = pWpt->getOrigin(); - int iLoc = READ_LOC(vOrigin.x); - int jLoc = READ_LOC(vOrigin.y); - int kLoc = READ_LOC(vOrigin.z); - - int i,j,k; + const int iLoc = READ_LOC(vOrigin.x) + const int jLoc = READ_LOC(vOrigin.y) + const int kLoc = READ_LOC(vOrigin.z) int iMinLoci,iMaxLoci,iMinLocj,iMaxLocj,iMinLock,iMaxLock; getMinMaxs(iLoc,jLoc,kLoc,&iMinLoci,&iMinLocj,&iMinLock,&iMaxLoci,&iMaxLocj,&iMaxLock); - for ( i = iMinLoci; i <= iMaxLoci; i++ ) + for ( int i = iMinLoci; i <= iMaxLoci; i++ ) { - for ( j = iMinLocj; j <= iMaxLocj; j++ ) + for ( int j = iMinLocj; j <= iMaxLocj; j++ ) { - for ( k = iMinLock; k <= iMaxLock; k++ ) + for ( int k = iMinLock; k <= iMaxLock; k++ ) { // check each area around the current area // for closer waypoints @@ -128,42 +129,32 @@ void CWaypointLocations :: AutoPath ( edict_t *pPlayer, int iWpt ) } // @param iFrom waypoint number from a and b within distance -void CWaypointLocations :: GetAllInArea ( Vector &vOrigin, vector *pWaypointList, int iVisibleTo ) +void CWaypointLocations :: GetAllInArea (const Vector& vOrigin, WaypointList* pWaypointList, const int iVisibleTo) { - int iLoc = READ_LOC(vOrigin.x); - int jLoc = READ_LOC(vOrigin.y); - int kLoc = READ_LOC(vOrigin.z); - - static dataUnconstArray *arr; - - int i,j,k; - int iWpt; + const int iLoc = READ_LOC(vOrigin.x) + const int jLoc = READ_LOC(vOrigin.y) + const int kLoc = READ_LOC(vOrigin.z) - CWaypointVisibilityTable *pTable = CWaypoints::getVisiblity(); + const CWaypointVisibilityTable *pTable = CWaypoints::getVisiblity(); int iMinLoci,iMaxLoci,iMinLocj,iMaxLocj,iMinLock,iMaxLock; getMinMaxs(iLoc,jLoc,kLoc,&iMinLoci,&iMinLocj,&iMinLock,&iMaxLoci,&iMaxLocj,&iMaxLock); - for ( i = iMinLoci; i <= iMaxLoci; i++ ) + for (int i = iMinLoci; i <= iMaxLoci; i++ ) { - for ( j = iMinLocj; j <= iMaxLocj; j++ ) - { - for ( k = iMinLock; k <= iMaxLock; k++ ) - { - //dataStack tempStack = m_iLocations[i][j][k]; - - arr = &(m_iLocations[i][j][k]); - //while ( !tempStack.IsEmpty() ) - for ( int l = 0; l < m_iLocations[i][j][k].Size(); l ++ ) + for (int j = iMinLocj; j <= iMaxLocj; j++ ) + { + for (int k = iMinLock; k <= iMaxLock; k++ ) + { + WaypointList loc = m_iLocations[i][j][k]; + for (int iWpt : loc) { - iWpt = arr->ReturnValueFromIndex(l); - if ( iWpt == iVisibleTo ) continue; - if ( (iVisibleTo==-1) || pTable->GetVisibilityFromTo(iWpt,iVisibleTo) ) - pWaypointList->push_back(iWpt); + if ( iVisibleTo==-1 || pTable->GetVisibilityFromTo(iWpt,iVisibleTo) ) + pWaypointList->emplace_back(iWpt); } } } @@ -172,56 +163,47 @@ void CWaypointLocations :: GetAllInArea ( Vector &vOrigin, vector *pWaypoi // @param iFrom waypoint number from a and b within distance -void CWaypointLocations :: GetAllVisible ( int iFrom, int iOther, Vector &vOrigin, - Vector &vOther, float fEDist, dataUnconstArray *iVisible, - dataUnconstArray *iInvisible ) +void CWaypointLocations :: GetAllVisible (const int iFrom, int iOther, const Vector& vOrigin, + const Vector& vOther, const float fEDist, WaypointList* iVisible, + WaypointList* iInvisible) { - CWaypoint *pWpt; - int iLoc = READ_LOC(vOrigin.x); - int jLoc = READ_LOC(vOrigin.y); - int kLoc = READ_LOC(vOrigin.z); - - static dataUnconstArray *arr; - - int i,j,k; - int iWpt; + const int iLoc = READ_LOC(vOrigin.x) + const int jLoc = READ_LOC(vOrigin.y) + const int kLoc = READ_LOC(vOrigin.z) int iMinLoci,iMaxLoci,iMinLocj,iMaxLocj,iMinLock,iMaxLock; - CWaypointVisibilityTable *pTable = CWaypoints::getVisiblity(); + const CWaypointVisibilityTable *pTable = CWaypoints::getVisiblity(); - if ( (iFrom == -1) || !pTable) + if ( iFrom == -1 || !pTable) return; getMinMaxs(iLoc,jLoc,kLoc,&iMinLoci,&iMinLocj,&iMinLock,&iMaxLoci,&iMaxLocj,&iMaxLock); - for ( i = iMinLoci; i <= iMaxLoci; i++ ) + for ( int i = iMinLoci; i <= iMaxLoci; i++ ) { - for ( j = iMinLocj; j <= iMaxLocj; j++ ) - { - for ( k = iMinLock; k <= iMaxLock; k++ ) - { - //dataStack tempStack = m_iLocations[i][j][k]; - - arr = &(m_iLocations[i][j][k]); - //while ( !tempStack.IsEmpty() ) - for ( int l = 0; l < m_iLocations[i][j][k].Size(); l ++ ) + for ( int j = iMinLocj; j <= iMaxLocj; j++ ) + { + for ( int k = iMinLock; k <= iMaxLock; k++ ) + { + WaypointList& arr = m_iLocations[i][j][k]; + for (std::size_t l = 0; l < m_iLocations[i][j][k].size(); l++) { - iWpt = arr->ReturnValueFromIndex(l); - pWpt = CWaypoints::getWaypoint(iWpt); + int iWpt = arr[l]; + const CWaypoint* pWpt = CWaypoints::getWaypoint(iWpt); //int iWpt = tempStack.ChooseFromStack(); // within range only deal with these waypoints - if ( (pWpt->distanceFrom(vOrigin) < fEDist) && (pWpt->distanceFrom(vOther) < fEDist) ) + if ( pWpt->distanceFrom(vOrigin) < fEDist && pWpt->distanceFrom(vOther) < fEDist ) { // iFrom should be the enemy waypoint if ( pTable->GetVisibilityFromTo(iFrom,iWpt) ) //|| pTable->GetVisibilityFromTo(iOther,iWpt) ) { //CBotGlobals::isVisible(vVisibleFrom,CWaypoints::getWaypoint(iWpt)->getOrigin()) ) - iVisible->Add(iWpt); + iVisible->emplace_back(iWpt); } - else if ( !iVisible->IsMember(iWpt) ) - iInvisible->Add(iWpt); + else if (std::find(iVisible->begin(), iVisible->end(), iWpt) == iVisible->end()) + iInvisible->emplace_back(iWpt); } } } @@ -229,40 +211,36 @@ void CWaypointLocations :: GetAllVisible ( int iFrom, int iOther, Vector &vOrigi } } -void CWaypointLocations :: AutoPathInBucket ( edict_t *pPlayer, int i, int j, int k, int iWptFrom ) +void CWaypointLocations :: AutoPathInBucket ( edict_t *pPlayer, const int i, const int j, const int k, const int iWptFrom ) { - //dataStack tempStack = m_iLocations[i][j][k]; - int iWpt; - CWaypoint *pOtherWpt; - extern ConVar bot_waypointpathdist; - CWaypoint *pWpt = CWaypoints::getWaypoint(iWptFrom); - Vector vWptOrigin = pWpt->getOrigin(); - Vector vOtherWptOrigin; + const Vector vWptOrigin = pWpt->getOrigin(); - trace_t tr; + //trace_t tr; //tr not used? [APG]RoboCop[CL] //CTraceFilterWorldOnly filter; - //while ( !tempStack.IsEmpty() ) - dataUnconstArray *arr = &(m_iLocations[i][j][k]); - short int size = (short int)arr->Size(); + const WaypointList& arr = m_iLocations[i][j][k]; + const std::size_t size = arr.size(); - for ( int l = 0; l < size; l ++ ) + for (std::size_t l = 0; l < size; l++) { - iWpt = arr->ReturnValueFromIndex(l); + const int iWpt = arr[l]; //iWpt = tempStack.ChooseFromStack(); - pOtherWpt = CWaypoints::getWaypoint(iWpt); + CWaypoint* pOtherWpt = CWaypoints::getWaypoint(iWpt); if ( !pOtherWpt->isUsed() ) continue; if ( pOtherWpt == pWpt ) continue; + + if( pOtherWpt->hasFlag(CWaypointTypes::W_FL_UNREACHABLE) ) // Stop auto adding paths to waypoints with unreachable flag + continue; - vOtherWptOrigin = pOtherWpt->getOrigin(); + Vector vOtherWptOrigin = pOtherWpt->getOrigin(); // if ( fabs(vOtherWptOrigin.z-vWptOrigin.z) > 128 ) // continue; @@ -289,35 +267,33 @@ void CWaypointLocations :: AddWptLocation ( int iIndex, const float *fOrigin ) { // Add a waypoint with index and at origin (for quick insertion in the list) // - int i = READ_LOC(fOrigin[0]); - int j = READ_LOC(fOrigin[1]); - int k = READ_LOC(fOrigin[2]); +const int i = READ_LOC(fOrigin[0]) +const int j = READ_LOC(fOrigin[1]) +const int k = READ_LOC(fOrigin[2]) - m_iLocations[i][j][k].Add(iIndex); - //m_iLocations[i][j][k].Push(iIndex); +m_iLocations[i][j][k].emplace_back(iIndex); } -void CWaypointLocations :: DeleteWptLocation ( int iIndex, const float *fOrigin ) +void CWaypointLocations :: DeleteWptLocation (const int iIndex, const float *fOrigin ) // Delete the waypoint index at the origin (for finding it quickly in the list) // { - int i = READ_LOC(fOrigin[0]); - int j = READ_LOC(fOrigin[1]); - int k = READ_LOC(fOrigin[2]); + const int i = READ_LOC(fOrigin[0]) + const int j = READ_LOC(fOrigin[1]) + const int k = READ_LOC(fOrigin[2]) - m_iLocations[i][j][k].Remove(iIndex); - //m_iLocations[i][j][k].Remove(iIndex); + WaypointList& vec = m_iLocations[i][j][k]; + vec.erase(std::remove(vec.begin(), vec.end(), iIndex), vec.end()); } /////////////// // return nearest waypoint that can be used to cover from vCoverFrom vector -int CWaypointLocations :: GetCoverWaypoint ( Vector vPlayerOrigin, Vector vCoverFrom, - dataUnconstArray *iIgnoreWpts, Vector *vGoalOrigin, - int iTeam, float fMinDist, float fMaxDist ) +int CWaypointLocations :: GetCoverWaypoint (const Vector& vPlayerOrigin, const Vector& vCoverFrom, + WaypointList *iIgnoreWpts, const Vector *vGoalOrigin, + const int iTeam, const float fMinDist, const float fMaxDist) { - int iWaypoint; - - iWaypoint = CWaypointLocations::NearestWaypoint(vCoverFrom,REACHABLE_RANGE,-1,true,true,false,NULL,false,0,false,true,vPlayerOrigin); + const int iWaypoint = NearestWaypoint(vCoverFrom, REACHABLE_RANGE, -1, true, true, false, nullptr, false, + 0, false, true, vPlayerOrigin); if ( iWaypoint == -1 ) return -1; @@ -326,11 +302,9 @@ int CWaypointLocations :: GetCoverWaypoint ( Vector vPlayerOrigin, Vector vCover int iNearestIndex = -1; - int iLoc = READ_LOC(vPlayerOrigin.x); - int jLoc = READ_LOC(vPlayerOrigin.y); - int kLoc = READ_LOC(vPlayerOrigin.z); - - int i,j,k; + const int iLoc = READ_LOC(vPlayerOrigin.x) + const int jLoc = READ_LOC(vPlayerOrigin.y) + const int kLoc = READ_LOC(vPlayerOrigin.z) int iMinLoci,iMaxLoci,iMinLocj,iMaxLocj,iMinLock,iMaxLock; @@ -344,22 +318,23 @@ int CWaypointLocations :: GetCoverWaypoint ( Vector vPlayerOrigin, Vector vCover int iWpt; //while ( !ignoreWptStack.IsEmpty() ) - for ( int l = 0; l < iIgnoreWpts->Size(); l ++ ) + for (const int iIgnoreWpt : *iIgnoreWpts) { - if ( (iWpt = (*iIgnoreWpts)[l]) != -1 )//(iWpt = ignoreWptStack.ChooseFromStack()) != -1 ) + if ( (iWpt = iIgnoreWpt) != -1 ) g_iFailedWaypoints[iWpt] = 1; } } - for ( i = iMinLoci; i <= iMaxLoci; i++ ) + for ( int i = iMinLoci; i <= iMaxLoci; i++ ) { - for ( j = iMinLocj; j <= iMaxLocj; j++ ) + for ( int j = iMinLocj; j <= iMaxLocj; j++ ) { - for ( k = iMinLock; k <= iMaxLock; k++ ) + for ( int k = iMinLock; k <= iMaxLock; k++ ) { // check each area around the current area // for closer waypoints - FindNearestCoverWaypointInBucket(i,j,k,vPlayerOrigin,&fNearestDist,&iNearestIndex,iIgnoreWpts,iWaypoint,vGoalOrigin,iTeam,fMinDist); + FindNearestCoverWaypointInBucket(i, j, k, vPlayerOrigin, &fNearestDist, &iNearestIndex, iIgnoreWpts, + iWaypoint, vGoalOrigin, iTeam, fMinDist); } } } @@ -367,57 +342,53 @@ int CWaypointLocations :: GetCoverWaypoint ( Vector vPlayerOrigin, Vector vCover return iNearestIndex; } -void CWaypointLocations :: FindNearestCoverWaypointInBucket ( int i, int j, int k, +void CWaypointLocations :: FindNearestCoverWaypointInBucket (const int i, const int j, const int k, const Vector &vOrigin, float *pfMinDist, int *piIndex, - dataUnconstArray *iIgnoreWpts, - int iCoverFromWpt, Vector *vGoalOrigin, - int iTeam, float fMinDist ) + WaypointList *iIgnoreWpts, + const int iCoverFromWpt, const Vector *vGoalOrigin, + const int iTeam, const float fMinDist) // Search for the nearest waypoint : I.e. // Find the waypoint that is closest to vOrigin from the distance pfMinDist // And set the piIndex to the waypoint index if closer. { //dataStack tempStack = m_iLocations[i][j][k]; - - CWaypoint *curr_wpt; - int iSelectedIndex; - float fDist; - dataUnconstArray *arr = &(m_iLocations[i][j][k]); - short int size = (short int)arr->Size(); + + const WaypointList &arr = m_iLocations[i][j][k]; + const std::size_t size = arr.size(); //CBotMod *curmod = CBotGlobals::getCurrentMod(); - for ( int l = 0; l < size; l ++ ) + for (std::size_t l = 0; l < size; l++) //while ( !tempStack.IsEmpty() ) { - iSelectedIndex = arr->ReturnValueFromIndex(l);//tempStack.ChooseFromStack(); + const int iSelectedIndex = arr[l];//tempStack.ChooseFromStack(); if ( iCoverFromWpt == iSelectedIndex ) continue; if ( g_iFailedWaypoints[iSelectedIndex] ) - continue; + continue; - curr_wpt = CWaypoints::getWaypoint(iSelectedIndex); + CWaypoint* curr_wpt = CWaypoints::getWaypoint(iSelectedIndex); if ( !curr_wpt->isUsed() ) continue; if ( curr_wpt->hasFlag(CWaypointTypes::W_FL_UNREACHABLE) ) continue; - if ( !curr_wpt->forTeam(iTeam) ) + if ( !curr_wpt->forTeam(iTeam) ) { continue; } if ( CWaypoints::getVisiblity()->GetVisibilityFromTo(iCoverFromWpt,iSelectedIndex) ) continue; + float fDist = curr_wpt->distanceFrom(vOrigin); - (fDist = curr_wpt->distanceFrom(vOrigin)); - - if ( vGoalOrigin != NULL ) + if ( vGoalOrigin != nullptr) { fDist += curr_wpt->distanceFrom(*vGoalOrigin); } - if ( (fDist > fMinDist) && (fDist < *pfMinDist) ) + if ( fDist > fMinDist && fDist < *pfMinDist ) { *piIndex = iSelectedIndex; *pfMinDist = fDist; @@ -430,36 +401,32 @@ void CWaypointLocations :: FindNearestCoverWaypointInBucket ( int i, int j, int ///////////////////////////// // get the nearest waypoint INDEX from an origin int CWaypointLocations :: NearestBlastWaypoint ( const Vector &vOrigin, const Vector &vSrc, - float fNearestDist, int iIgnoreWpt, - bool bGetVisible, bool bGetUnReachable, - bool bIsBot, bool bNearestAimingOnly, - int iTeam, bool bCheckArea, float fBlastRadius ) + float fNearestDist, const int iIgnoreWpt, + const bool bGetVisible, const bool bGetUnReachable, + const bool bIsBot, const bool bNearestAimingOnly, + const int iTeam, const bool bCheckArea, const float fBlastRadius ) { int iNearestIndex = -1; - int iLoc; - int jLoc; - int kLoc; - int i,j,k; - Vector vMid = (vSrc - vOrigin); + Vector vMid = vSrc - vOrigin; - vMid = (vMid / vMid.Length()); - vMid = (vMid*((vSrc-vOrigin).Length()/2)); + vMid = vMid / vMid.Length(); + vMid = vMid*((vSrc-vOrigin).Length()/2); vMid = vOrigin + vMid; - iLoc = READ_LOC(vMid.x); - jLoc = READ_LOC(vMid.y); - kLoc = READ_LOC(vMid.z); + const int iLoc = READ_LOC(vMid.x) + const int jLoc = READ_LOC(vMid.y) + const int kLoc = READ_LOC(vMid.z) int iMinLoci,iMaxLoci,iMinLocj,iMaxLocj,iMinLock,iMaxLock; getMinMaxs(iLoc,jLoc,kLoc,&iMinLoci,&iMinLocj,&iMinLock,&iMaxLoci,&iMaxLocj,&iMaxLock); - for ( i = iMinLoci; i <= iMaxLoci; i++ ) + for ( int i = iMinLoci; i <= iMaxLoci; i++ ) { - for ( j = iMinLocj; j <= iMaxLocj; j++ ) + for ( int j = iMinLocj; j <= iMaxLocj; j++ ) { - for ( k = iMinLock; k <= iMaxLock; k++ ) + for ( int k = iMinLock; k <= iMaxLock; k++ ) { FindNearestBlastInBucket(i,j,k,vOrigin,vSrc,&fNearestDist,&iNearestIndex,iIgnoreWpt,bGetVisible,bGetUnReachable,bIsBot,bNearestAimingOnly,iTeam,bCheckArea,fBlastRadius); } @@ -471,40 +438,35 @@ int CWaypointLocations :: NearestBlastWaypoint ( const Vector &vOrigin, const Ve /////////////////////////////////////////////// // find a waypoint I can fire a blast (e.g. rpg or grenade to) -void CWaypointLocations :: FindNearestBlastInBucket ( int i, int j, int k, const Vector &vOrigin, +void CWaypointLocations :: FindNearestBlastInBucket (const int i, const int j, const int k, const Vector &vOrigin, const Vector &vSrc, float *pfMinDist, - int *piIndex, int iIgnoreWpt, bool bGetVisible, - bool bGetUnReachable, bool bIsBot, - bool bNearestAimingOnly, int iTeam, - bool bCheckArea, float fBlastRadius ) + int *piIndex, const int iIgnoreWpt, const bool bGetVisible, + const bool bGetUnReachable, const bool bIsBot, + bool bNearestAimingOnly, const int iTeam, + const bool bCheckArea, const float fBlastRadius ) // Search for the nearest waypoint : I.e. // Find the waypoint that is closest to vOrigin from the distance pfMinDist // And set the piIndex to the waypoint index if closer. { //dataStack tempStack = m_iLocations[i][j][k]; - CWaypoint *curr_wpt; - int iSelectedIndex; float fDist; -// int iWptFlags; + //int iWptFlags; - trace_t tr; - - bool bAdd; - - dataUnconstArray *arr = &(m_iLocations[i][j][k]); - short int size = (short int)arr->Size(); + //trace_t tr; //tr not used? [APG]RoboCop[CL] + + const WaypointList &arr = m_iLocations[i][j][k]; + const std::size_t size = arr.size(); CBotMod *curmod = CBotGlobals::getCurrentMod(); - for ( register short int l = 0; l < size; l ++ ) - //while ( !tempStack.IsEmpty() ) + for (std::size_t l = 0; l < size; l ++ ) { - iSelectedIndex = arr->ReturnValueFromIndex(l);//tempStack.ChooseFromStack(); + const int iSelectedIndex = arr[l];//tempStack.ChooseFromStack(); if ( iSelectedIndex == iIgnoreWpt ) continue; - curr_wpt = CWaypoints::getWaypoint(iSelectedIndex); + CWaypoint* curr_wpt = CWaypoints::getWaypoint(iSelectedIndex); if ( !bGetUnReachable && curr_wpt->hasFlag(CWaypointTypes::W_FL_UNREACHABLE) ) continue; @@ -526,11 +488,11 @@ void CWaypointLocations :: FindNearestBlastInBucket ( int i, int j, int k, const continue; } - if ( curr_wpt->distanceFrom(vOrigin) < (fBlastRadius*2) ) + if ( curr_wpt->distanceFrom(vOrigin) < fBlastRadius*2 ) { - if ( (fDist = (curr_wpt->distanceFrom(vSrc)+curr_wpt->distanceFrom(vOrigin))) < *pfMinDist ) + if ( (fDist = curr_wpt->distanceFrom(vSrc)+curr_wpt->distanceFrom(vOrigin)) < *pfMinDist ) { - bAdd = false; + bool bAdd; if ( bGetVisible == false ) bAdd = true; @@ -549,38 +511,46 @@ void CWaypointLocations :: FindNearestBlastInBucket ( int i, int j, int k, const } } +// TODO: Needs implemented properly [APG]RoboCop[CL] +/*int CWaypointLocations::NearestGrenadeWaypoint(const Vector& vTarget, int iTeam, bool bCheckArea, float fBlastRadius) +{ + return 0; +} + +void CWaypointLocations::FindNearestGrenadeWptInBucket(int i, int j, int k, const Vector& vOrigin, const Vector& vSrc, float* pfMinDist, int* piIndex, int iIgnoreWpt, bool bGetVisible, bool bGetUnReachable, bool bIsBot, bool bNearestAimingOnly, int iTeam, bool bCheckArea, float fBlastRadius) +{ + +}*/ + /////////////////////////////////////////////// // -void CWaypointLocations :: FindNearestInBucket ( int i, int j, int k, const Vector &vOrigin, - float *pfMinDist, int *piIndex, int iIgnoreWpt, - bool bGetVisible, bool bGetUnReachable, bool bIsBot, - dataUnconstArray *iFailedWpts, bool bNearestAimingOnly, - int iTeam, bool bCheckArea, bool bGetVisibleFromOther, - Vector vOther, int iFlagsOnly, edict_t *pPlayer ) +void CWaypointLocations :: FindNearestInBucket (const int i, const int j, const int k, const Vector &vOrigin, + float *pfMinDist, int *piIndex, const int iIgnoreWpt, + const bool bGetVisible, const bool bGetUnreachable, const bool bIsBot, + WaypointList *iFailedWpts, bool bNearestAimingOnly, + const int iTeam, const bool bCheckArea, const bool bGetVisibleFromOther, + const Vector& vOther, const int iFlagsOnly, edict_t *pPlayer) // Search for the nearest waypoint : I.e. // Find the waypoint that is closest to vOrigin from the distance pfMinDist // And set the piIndex to the waypoint index if closer. { //dataStack tempStack = m_iLocations[i][j][k]; - CWaypoint *curr_wpt; - int iSelectedIndex; float fDist; -// int iWptFlags; - - trace_t tr; + //int iWptFlags; - bool bAdd; + //trace_t tr; //tr not used? [APG]RoboCop[CL] + CBotMod *curmod = CBotGlobals::getCurrentMod(); + + const WaypointList &arr = m_iLocations[i][j][k]; + const std::size_t size = arr.size(); - dataUnconstArray *arr = &(m_iLocations[i][j][k]); - short int size = (short int)arr->Size(); - - for ( int l = 0; l < size; l ++ ) + for (std::size_t l = 0; l < size; l++) //while ( !tempStack.IsEmpty() ) { - iSelectedIndex = arr->ReturnValueFromIndex(l);//tempStack.ChooseFromStack(); + const int iSelectedIndex = arr[l];//tempStack.ChooseFromStack(); if ( iSelectedIndex == iIgnoreWpt ) continue; @@ -590,9 +560,9 @@ void CWaypointLocations :: FindNearestInBucket ( int i, int j, int k, const Vect continue; } - curr_wpt = CWaypoints::getWaypoint(iSelectedIndex); + CWaypoint* curr_wpt = CWaypoints::getWaypoint(iSelectedIndex); - if ( !bGetUnReachable && curr_wpt->hasFlag(CWaypointTypes::W_FL_UNREACHABLE) ) + if ( !bGetUnreachable && curr_wpt->hasFlag(CWaypointTypes::W_FL_UNREACHABLE) ) continue; if ( !curr_wpt->isUsed() ) @@ -612,11 +582,11 @@ void CWaypointLocations :: FindNearestInBucket ( int i, int j, int k, const Vect } // DOD:S compatibility if (bCheckArea && !curmod->isWaypointAreaValid(curr_wpt->getArea(), curr_wpt->getFlags())) - continue;; + continue; if ( iFlagsOnly != 0 ) { - if ( !curr_wpt->getFlags() || (!curr_wpt->hasSomeFlags(iFlagsOnly)) ) + if ( !curr_wpt->getFlags() || !curr_wpt->hasSomeFlags(iFlagsOnly) ) continue; } @@ -634,13 +604,13 @@ void CWaypointLocations :: FindNearestInBucket ( int i, int j, int k, const Vect if ( curr_wpt->distanceFrom(m_vIgnoreLoc) < m_fIgnoreSize ) continue; - else if ( ((vOrigin + (vcomp*((vOther-vOrigin).Length()))) - vOther).Length() < m_fIgnoreSize ) + if ( (vOrigin + vcomp*(vOther-vOrigin).Length() - vOther).Length() < m_fIgnoreSize ) continue; } if ( (fDist = curr_wpt->distanceFrom(vOrigin)) < *pfMinDist ) { - bAdd = false; + bool bAdd; if ( bGetVisible == false ) bAdd = true; @@ -650,7 +620,7 @@ void CWaypointLocations :: FindNearestInBucket ( int i, int j, int k, const Vect bAdd = CBotGlobals::isVisible(vOther,curr_wpt->getOrigin()); else { - if ( pPlayer != NULL ) + if ( pPlayer != nullptr) { CBotGlobals::quickTraceline(pPlayer,vOrigin,curr_wpt->getOrigin()); bAdd = CBotGlobals::getTraceResult()->fraction>=1.0f; @@ -671,20 +641,18 @@ void CWaypointLocations :: FindNearestInBucket ( int i, int j, int k, const Vect ///////////////////////////// // get the nearest waypoint INDEX from an origin -int CWaypointLocations :: NearestWaypoint ( const Vector &vOrigin, float fNearestDist, - int iIgnoreWpt, bool bGetVisible, bool bGetUnReachable, - bool bIsBot, dataUnconstArray *iFailedWpts, - bool bNearestAimingOnly, int iTeam, bool bCheckArea, - bool bGetVisibleFromOther, Vector vOther, int iFlagsOnly, - edict_t *pPlayer, bool bIgnorevOther, float fIgnoreSize ) +int CWaypointLocations :: NearestWaypoint (const Vector &vOrigin, float fNearestDist, + const int iIgnoreWpt, const bool bGetVisible, const bool bGetUnreachable, + const bool bIsBot, WaypointList *iFailedWpts, + const bool bNearestAimingOnly, const int iTeam, const bool bCheckArea, + const bool bGetVisibleFromOther, const Vector& vOther, const int iFlagsOnly, + edict_t *pPlayer, const bool bIgnorevOther, const float fIgnoreSize) { int iNearestIndex = -1; - - int iLoc = READ_LOC(vOrigin.x); - int jLoc = READ_LOC(vOrigin.y); - int kLoc = READ_LOC(vOrigin.z); - int i,j,k; + const int iLoc = READ_LOC(vOrigin.x) + const int jLoc = READ_LOC(vOrigin.y) + const int kLoc = READ_LOC(vOrigin.z) int iMinLoci,iMaxLoci,iMinLocj,iMaxLocj,iMinLock,iMaxLock; @@ -702,36 +670,36 @@ int CWaypointLocations :: NearestWaypoint ( const Vector &vOrigin, float fNeares { int iWpt; - for ( int l = 0; l < iFailedWpts->Size(); l ++ ) + for (const int iFailedWpt : *iFailedWpts) { - if ( (iWpt=(*iFailedWpts)[l]) != -1 ) //( (iWpt = tempStack.ChooseFromStack()) != -1 ) + if ( (iWpt= iFailedWpt) != -1 ) g_iFailedWaypoints[iWpt] = 1; } } } - for ( i = iMinLoci; i <= iMaxLoci; i++ ) + for ( int i = iMinLoci; i <= iMaxLoci; i++ ) { - for ( j = iMinLocj; j <= iMaxLocj; j++ ) + for ( int j = iMinLocj; j <= iMaxLocj; j++ ) { - for ( k = iMinLock; k <= iMaxLock; k++ ) + for ( int k = iMinLock; k <= iMaxLock; k++ ) { - FindNearestInBucket(i,j,k,vOrigin,&fNearestDist,&iNearestIndex,iIgnoreWpt,bGetVisible,bGetUnReachable,bIsBot,iFailedWpts,bNearestAimingOnly,iTeam,bCheckArea,bGetVisibleFromOther,vOther,iFlagsOnly,pPlayer); + FindNearestInBucket(i,j,k,vOrigin,&fNearestDist,&iNearestIndex,iIgnoreWpt,bGetVisible,bGetUnreachable,bIsBot,iFailedWpts,bNearestAimingOnly,iTeam,bCheckArea,bGetVisibleFromOther,vOther,iFlagsOnly,pPlayer); } } } if ( iFailedWpts ) - { + { int iWpt; - for ( int l = 0; l < iFailedWpts->Size(); l ++ ) + for (std::size_t l = 0; l < iFailedWpts->size(); l++) { if ( (iWpt=(*iFailedWpts)[l]) != -1 ) //( (iWpt = tempStack.ChooseFromStack()) != -1 ) { if ( g_iFailedWaypoints[iWpt] == 2 ) { - iFailedWpts->Remove(iWpt); + iFailedWpts->erase(std::remove(iFailedWpts->begin(), iFailedWpts->end(), iWpt), iFailedWpts->end()); } } } @@ -744,47 +712,41 @@ int CWaypointLocations :: NearestWaypoint ( const Vector &vOrigin, float fNeares ////////////////////////////////// // Draw waypoints around a player -void CWaypointLocations :: DrawWaypoints ( CClient *pClient, float fDist ) +void CWaypointLocations :: DrawWaypoints (const CClient *pClient, float fDist) { - static byte m_bPvs[MAX_MAP_CLUSTERS/8]; static int clusterIndex; - static dataUnconstArray *arr; - static short int size; + static short int size; //size not used? [APG]RoboCop[CL] static int iWpt; static CWaypoint *pWpt; - static int i,j,k; static Vector vWpt; //static bool bDrawPaths; static unsigned short int iDrawType; static Vector vOrigin; static edict_t *pEntity; - static int iMinLoci,iMaxLoci,iMinLocj,iMaxLocj,iMinLock,iMaxLock; - int iLoc = READ_LOC(vOrigin.x); - int jLoc = READ_LOC(vOrigin.y); - int kLoc = READ_LOC(vOrigin.z); + const int iLoc = READ_LOC(vOrigin.x) + const int jLoc = READ_LOC(vOrigin.y) + const int kLoc = READ_LOC(vOrigin.z) pEntity = pClient->getPlayer(); vOrigin = pClient->getOrigin(); //bDrawPaths = false; iDrawType = pClient->getDrawType(); + int iMinLoci,iMaxLoci,iMinLocj,iMaxLocj,iMinLock,iMaxLock; getMinMaxs(iLoc,jLoc,kLoc,&iMinLoci,&iMinLocj,&iMinLock,&iMaxLoci,&iMaxLocj,&iMaxLock); - - for ( i = iMinLoci; i <= iMaxLoci; i++ ) + for (int i = iMinLoci; i <= iMaxLoci; i++) { - for ( j = iMinLocj; j <= iMaxLocj; j++ ) + for (int j = iMinLocj; j <= iMaxLocj; j++) { - for ( k = iMinLock; k <= iMaxLock; k++ ) + for (int k = iMinLock; k <= iMaxLock; k++) { - arr = &(m_iLocations[i][j][k]); - size = (short int)arr->Size(); - - for ( short int l = 0; l < size; l ++ ) - //while ( !tempStack.IsEmpty() ) + // TODO use a type alias for this + WaypointList &arr = m_iLocations[i][j][k]; + for (const int l : arr) { - iWpt = arr->ReturnValueFromIndex(l);//tempStack.ChooseFromStack(); + iWpt = l; pWpt = CWaypoints::getWaypoint(iWpt);//tempStack.ChooseFromStack()); @@ -795,24 +757,25 @@ void CWaypointLocations :: DrawWaypoints ( CClient *pClient, float fDist ) { if ( pWpt->getFlags() == 0 ) continue; // hidden - else if ( !pClient->isShowingWaypoint(pWpt->getFlags()) ) + if ( !pClient->isShowingWaypoint(pWpt->getFlags()) ) continue; } vWpt = pWpt->getOrigin(); - if ( fabs(vWpt.z - vOrigin.z) <= 256.0 ) // also in z range + if ( std::fabs(vWpt.z - vOrigin.z) <= 256.0f ) // also in z range { //if ( CBotGlobals::FInViewCone(pEntity) ) { + static byte m_bPvs[MAX_MAP_CLUSTERS/8]; // from Valve developer community wiki // http://developer.valvesoftware.com/wiki/Transforming_the_Multiplayer_SDK_into_Coop clusterIndex = engine->GetClusterForOrigin( vOrigin ); - engine->GetPVSForCluster( clusterIndex, sizeof(m_bPvs), m_bPvs ); + engine->GetPVSForCluster( clusterIndex, sizeof m_bPvs, m_bPvs ); - if ( engine->CheckOriginInPVS( vWpt, m_bPvs, sizeof( m_bPvs ) ) ) - pWpt->draw(pEntity,pClient->isPathWaypointOn()&&(pClient->currentWaypoint()==iWpt),iDrawType); + if ( engine->CheckOriginInPVS( vWpt, m_bPvs, sizeof m_bPvs ) ) + pWpt->draw(pEntity,pClient->isPathWaypointOn()&&pClient->currentWaypoint()==iWpt,iDrawType); } } } @@ -821,10 +784,10 @@ void CWaypointLocations :: DrawWaypoints ( CClient *pClient, float fDist ) } } -void CWaypointLocations ::AddWptLocation (CWaypoint *pWaypoint, int iIndex) +void CWaypointLocations ::AddWptLocation (CWaypoint *pWaypoint, const int iIndex) { - Vector vOrigin = pWaypoint->getOrigin(); - float flOrigin[3] = { vOrigin.x, vOrigin.y, vOrigin.z }; + const Vector vOrigin = pWaypoint->getOrigin(); + const float flOrigin[3] = { vOrigin.x, vOrigin.y, vOrigin.z }; AddWptLocation(iIndex,flOrigin); } diff --git a/utils/RCBot2_meta/bot_waypoint_locations.h b/utils/RCBot2_meta/bot_waypoint_locations.h index 679c3bb5c..cc8effe8a 100644 --- a/utils/RCBot2_meta/bot_waypoint_locations.h +++ b/utils/RCBot2_meta/bot_waypoint_locations.h @@ -31,10 +31,6 @@ #ifndef __RCBOT_WAYPOINT_LOC_H__ #define __RCBOT_WAYPOINT_LOC_H__ -//#include -//using namespace std; - -#include "bot_genclass.h" #include "bot_waypoint.h" /*#define WAYPOINT_LOC(x)\ @@ -67,18 +63,18 @@ class CWaypointLocations { public: - static const int REACHABLE_RANGE = 400; + static constexpr int REACHABLE_RANGE = 400; // max map size is 32768 - static const int HALF_MAX_MAP_SIZE = 16384; // need to know half (negative + positive halves = max) + static constexpr int HALF_MAX_MAP_SIZE = 16384; // need to know half (negative + positive halves = max) /* // want bucket spacing of 256 units - static const int MAX_WPT_BUCKETS = 128; + static constexpr int MAX_WPT_BUCKETS = 128; */ // want bucket spacing of 512 units - static const int MAX_WPT_BUCKETS = 64; + static constexpr int MAX_WPT_BUCKETS = 64; - static const int BUCKET_SPACING = (HALF_MAX_MAP_SIZE*2)/MAX_WPT_BUCKETS; + static constexpr int BUCKET_SPACING = HALF_MAX_MAP_SIZE*2/MAX_WPT_BUCKETS; static unsigned char g_iFailedWaypoints [ CWaypoints::MAX_WAYPOINTS ]; @@ -89,83 +85,71 @@ class CWaypointLocations Init(); } - static unsigned char *resetFailedWaypoints (dataUnconstArray *iIgnoreWpts); + static unsigned char *resetFailedWaypoints (const WaypointList *iIgnoreWpts); static void Init() { - int i,j,k; - - for ( i = 0; i < MAX_WPT_BUCKETS; i ++ ) - { - for ( j = 0; j < MAX_WPT_BUCKETS; j ++ ) - { - for ( k = 0; k < MAX_WPT_BUCKETS; k ++ ) - { - m_iLocations[i][j][k].Init();//.Init(); - } - } - } + Clear(); } static void Clear () { - int i,j,k; - - for ( i = 0; i < MAX_WPT_BUCKETS; i ++ ) + for (WaypointList (&m_iLocation)[64][64] : m_iLocations) { - for ( j = 0; j < MAX_WPT_BUCKETS; j ++ ) + for (WaypointList (&j)[64] : m_iLocation) { - for ( k = 0; k < MAX_WPT_BUCKETS; k ++ ) + for (WaypointList& k : j) { - m_iLocations[i][j][k].Destroy();//.Destroy(); + k.clear(); } } } } - static void GetAllInArea ( Vector &vOrigin, vector *pWaypointList, int iVisibleTo ); + static void GetAllInArea (const Vector& vOrigin, WaypointList* pWaypointList, int iVisibleTo); static void getMinMaxs ( int iLoc, int jLoc, int kLoc, - int *iMinLoc, int *jMinLoc, int *kMinLoc, - int *iMaxLoc, int *jMaxLoc, int *kMaxLoc ); + int *iMinLoci, int *iMinLocj, int *iMinLock, + int *iMaxLoci, int *iMaxLocj, int *iMaxLock ); - static int GetCoverWaypoint ( Vector vPlayerOrigin, Vector vCoverFrom, dataUnconstArray *iIgnoreWpts, Vector *vGoalOrigin = NULL, int iTeam = 0, float fMinDist = MIN_COVER_MOVE_DIST, float fMaxDist = HALF_MAX_MAP_SIZE ); + static int GetCoverWaypoint (const Vector& vPlayerOrigin, const Vector& vCoverFrom, WaypointList *iIgnoreWpts, const Vector *vGoalOrigin = nullptr, int iTeam = 0, float fMinDist = MIN_COVER_MOVE_DIST, float fMaxDist = HALF_MAX_MAP_SIZE); - static void FindNearestCoverWaypointInBucket ( int i, int j, int k, const Vector &vOrigin, float *pfMinDist, int *piIndex, dataUnconstArray *iIgnoreWpts, int iCoverFromWpt, Vector *vGoalOrigin = NULL, int iTeam = 0, float fMinDist = MIN_COVER_MOVE_DIST ); + static void FindNearestCoverWaypointInBucket (int i, int j, int k, const Vector &vOrigin, float *pfMinDist, int *piIndex, WaypointList *iIgnoreWpts, int iCoverFromWpt, const Vector *vGoalOrigin = nullptr, int iTeam = 0, float fMinDist = MIN_COVER_MOVE_DIST); static void AddWptLocation ( int iIndex, const float *fOrigin ); - static void FindNearestInBucket ( int i, int j, int k, const Vector &vOrigin, float *pfMinDist, int *piIndex,int iIgnoreWpt, bool bGetVisible = true, bool bGetUnreachable = false, bool bIsBot = false, dataUnconstArray *iFailedWpts = NULL, bool bNearestAimingOnly = false, int iTeam = 0, bool bCheckArea = false, bool bGetVisibleFromOther = false, Vector vOther = Vector(0,0,0), int iFlagsOnly = 0, edict_t *pPlayer = NULL ); - static void DrawWaypoints ( CClient *pClient, float fDist ); + static void FindNearestInBucket ( int i, int j, int k, const Vector &vOrigin, float *pfMinDist, int *piIndex,int iIgnoreWpt, bool bGetVisible = true, bool bGetUnreachable = false, bool bIsBot = false, WaypointList *iFailedWpts = nullptr, bool bNearestAimingOnly = false, int iTeam = 0, bool bCheckArea = false, bool bGetVisibleFromOther = false, const Vector& vOther = Vector(0,0,0), int iFlagsOnly = 0, edict_t *pPlayer = nullptr); + static void DrawWaypoints (const CClient *pClient, float fDist); static void DeleteWptLocation ( int iIndex, const float *fOrigin ); - static int NearestWaypoint ( const Vector &vOrigin, float fDist, int iIgnoreWpt, bool bGetVisible = true, - bool bGetUnreachable = false, bool bIsBot = false, dataUnconstArray *iFailedWpts = NULL, + static int NearestWaypoint ( const Vector &vOrigin, float fNearestDist, int iIgnoreWpt, bool bGetVisible = true, + bool bGetUnreachable = false, bool bIsBot = false, WaypointList *iFailedWpts = nullptr, bool bNearestAimingOnly = false, int iTeam = 0, bool bCheckArea = false, - bool bGetVisibleFromOther = false, Vector vOther = Vector(0,0,0), int FlagsOnly = 0, - edict_t *pPlayer = NULL, bool bIgnorevOther = false, float fIgnoreSize = 0.0f ); + bool bGetVisibleFromOther = false, const Vector& vOther = Vector(0,0,0), int iFlagsOnly = 0, + edict_t *pPlayer = nullptr, bool bIgnorevOther = false, float fIgnoreSize = 0.0f ); - static void GetAllVisible( int iFrom, int iOther, Vector &vOrigin, Vector &vOther, float fEDist, dataUnconstArray *iVisible, dataUnconstArray *iInvisible ); + static void GetAllVisible(int iFrom, int iOther, const Vector& vOrigin, const Vector& vOther, float fEDist, WaypointList* iVisible, WaypointList* + iInvisible); /////////// static void AutoPath ( edict_t *pPlayer, int iWpt ); - static void AutoPathInBucket ( edict_t *pPlayer, int i, int j, int k, int iWpt ); + static void AutoPathInBucket (edict_t *pPlayer, int i, int j, int k, int iWptFrom); static int NearestBlastWaypoint ( const Vector &vOrigin, const Vector &vSrc, float fNearestDist, int iIgnoreWpt, bool bGetVisible, bool bGetUnReachable, bool bIsBot, bool bNearestAimingOnly, int iTeam, bool bCheckArea, float fBlastRadius = BLAST_RADIUS ); static void FindNearestBlastInBucket ( int i, int j, int k, const Vector &vOrigin, const Vector &vSrc, float *pfMinDist, int *piIndex, int iIgnoreWpt, bool bGetVisible, bool bGetUnReachable, bool bIsBot, bool bNearestAimingOnly, int iTeam, bool bCheckArea, float fBlastRadius = BLAST_RADIUS ); - static int NearestGrenadeWaypoint ( const Vector &vTarget, int iTeam, bool bCheckArea, float fBlastRadius = BLAST_RADIUS ); + //static int NearestGrenadeWaypoint ( const Vector &vTarget, int iTeam, bool bCheckArea, float fBlastRadius = BLAST_RADIUS ); // TODO: Needs implemented properly [APG]RoboCop[CL] - static void FindNearestGrenadeWptInBucket ( int i, int j, int k, const Vector &vOrigin, const Vector &vSrc, float *pfMinDist, int *piIndex, int iIgnoreWpt, bool bGetVisible, bool bGetUnReachable, bool bIsBot, bool bNearestAimingOnly, int iTeam, bool bCheckArea, float fBlastRadius = BLAST_RADIUS ); + //static void FindNearestGrenadeWptInBucket ( int i, int j, int k, const Vector &vOrigin, const Vector &vSrc, float *pfMinDist, int *piIndex, int iIgnoreWpt, bool bGetVisible, bool bGetUnReachable, bool bIsBot, bool bNearestAimingOnly, int iTeam, bool bCheckArea, float fBlastRadius = BLAST_RADIUS ); // TODO: Needs implemented properly [APG]RoboCop[CL] private: //static dataStack m_iLocations[MAX_WPT_BUCKETS][MAX_WPT_BUCKETS][MAX_WPT_BUCKETS]; - static dataUnconstArray m_iLocations[MAX_WPT_BUCKETS][MAX_WPT_BUCKETS][MAX_WPT_BUCKETS]; + static WaypointList m_iLocations[MAX_WPT_BUCKETS][MAX_WPT_BUCKETS][MAX_WPT_BUCKETS]; static float m_fIgnoreSize; static Vector m_vIgnoreLoc; static bool m_bIgnoreBox; diff --git a/utils/RCBot2_meta/bot_waypoint_visibility.cpp b/utils/RCBot2_meta/bot_waypoint_visibility.cpp index 30ad77eb7..17aca7290 100644 --- a/utils/RCBot2_meta/bot_waypoint_visibility.cpp +++ b/utils/RCBot2_meta/bot_waypoint_visibility.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com /* * This file is part of RCBot. * @@ -34,39 +36,43 @@ #include "bot_waypoint.h" #include "bot_waypoint_visibility.h" #include "bot_globals.h" -#include -/*unsigned char *CWaypointVisibilityTable :: m_VisTable = NULL; -bool CWaypointVisibilityTable :: bWorkVisibility = false; -int CWaypointVisibilityTable :: iCurFrom = 0; -int CWaypointVisibilityTable :: iCurTo = 0;*/ +#include +#include -void CWaypointVisibilityTable :: workVisibility () -{ - int percent; +#include "rcbot/logging.h" + + /*unsigned char *CWaypointVisibilityTable :: m_VisTable = NULL; + bool CWaypointVisibilityTable :: bWorkVisibility = false; + int CWaypointVisibilityTable :: iCurFrom = 0; + int CWaypointVisibilityTable :: iCurTo = 0;*/ + +void CWaypointVisibilityTable::workVisibility() +{ int iTicks = 0; - register unsigned short int iSize = (unsigned short int) CWaypoints::numWaypoints(); + const unsigned short int iSize = static_cast(CWaypoints::numWaypoints()); - for ( iCurFrom = iCurFrom; iCurFrom < iSize; iCurFrom ++ ) + for (/*iCurFrom = iCurFrom*/; iCurFrom < iSize; iCurFrom++) { - for ( iCurTo = iCurTo; iCurTo < iSize; iCurTo ++ ) + for (/*iCurTo = iCurTo*/; iCurTo < iSize; iCurTo++) { - CWaypoint *pWaypoint1 = CWaypoints::getWaypoint(iCurFrom); - CWaypoint *pWaypoint2 = CWaypoints::getWaypoint(iCurTo); + CWaypoint* pWaypoint1 = CWaypoints::getWaypoint(iCurFrom); + CWaypoint* pWaypoint2 = CWaypoints::getWaypoint(iCurTo); - SetVisibilityFromTo(iCurFrom,iCurTo,CBotGlobals::isVisible(pWaypoint1->getOrigin(),pWaypoint2->getOrigin())); + SetVisibilityFromTo(iCurFrom, iCurTo, + CBotGlobals::isVisible(pWaypoint1->getOrigin(), pWaypoint2->getOrigin())); iTicks++; - if ( iTicks >= WAYPOINT_VIS_TICKS ) + if (iTicks >= WAYPOINT_VIS_TICKS) { - if ( m_fNextShowMessageTime < engine->Time() ) + if (m_fNextShowMessageTime < engine->Time()) { - percent = (int)(((float)iCurFrom / iSize) * 100); + const int percent = (iCurFrom / iSize) * 100; - if ( m_iPrevPercent != percent ) + if (m_iPrevPercent != percent) { - Msg(" *** working out visibility %d percent***\n",percent); + logger->Log(LogLevel::INFO, "Working out visibility... %d%%", percent); m_fNextShowMessageTime = engine->Time() + 2.5f; m_iPrevPercent = percent; } @@ -79,132 +85,126 @@ void CWaypointVisibilityTable :: workVisibility () iCurTo = 0; } - if ( iCurFrom == iSize ) + if (iCurFrom == iSize) { // finished - Msg(" *** finished working out visibility ***\n"); + logger->Log(LogLevel::INFO, "Finished working out visibility. Saving..."); ///////////////////////////// - // for "concurrent" reading of + // for "concurrent" reading of // visibility throughout frames bWorkVisibility = false; iCurFrom = 0; iCurTo = 0; // save waypoints with visibility flag now - if ( SaveToFile() ) + if (SaveToFile()) { CWaypoints::save(true); - Msg(" *** saving waypoints with visibility information ***\n"); + logger->Log(LogLevel::INFO, "Saved waypoints with visibility information"); } else - Msg(" *** error, couldn't save waypoints with visibility information ***\n"); + logger->Log(LogLevel::ERROR, "Couldn't save waypoints with visibility information"); //////////////////////////// } } -void CWaypointVisibilityTable :: workVisibilityForWaypoint ( int i, int iNumWaypoints, bool bTwoway ) +void CWaypointVisibilityTable::workVisibilityForWaypoint(const int i, const int iNumWaypoints, const bool bTwoway) const { - static CWaypoint *Waypoint1; - static CWaypoint *Waypoint2; + static CWaypoint* Waypoint1; + static CWaypoint* Waypoint2; static bool bVisible; Waypoint1 = CWaypoints::getWaypoint(i); - if ( !Waypoint1->isUsed() ) + if (!Waypoint1->isUsed()) return; - for ( register short int j = 0; j < iNumWaypoints; j ++ ) + for (int j = 0; j < iNumWaypoints; j++) { - if ( i == j ) + if (i == j) { - SetVisibilityFromTo(i,j,1); + SetVisibilityFromTo(i, j, true); continue; } Waypoint2 = CWaypoints::getWaypoint(j); - if ( !Waypoint2->isUsed() ) + if (!Waypoint2->isUsed()) continue; - bVisible = CBotGlobals::isVisible(Waypoint1->getOrigin(),Waypoint2->getOrigin()); + bVisible = CBotGlobals::isVisible(Waypoint1->getOrigin(), Waypoint2->getOrigin()); - SetVisibilityFromTo(i,j,bVisible); + SetVisibilityFromTo(i, j, bVisible); - if ( bTwoway ) - SetVisibilityFromTo(j,i,bVisible); + if (bTwoway) + SetVisibilityFromTo(j, i, bVisible); } } -void CWaypointVisibilityTable :: WorkOutVisibilityTable () +void CWaypointVisibilityTable::WorkOutVisibilityTable() { - register short int i; - - int iNumWaypoints = CWaypoints::numWaypoints(); + const int iNumWaypoints = CWaypoints::numWaypoints(); ClearVisibilityTable(); // loop through all waypoint possibilities. - for ( i = 0; i < iNumWaypoints; i ++ ) + for (int i = 0; i < iNumWaypoints; i++) { - workVisibilityForWaypoint(i,iNumWaypoints,false); + workVisibilityForWaypoint(i, iNumWaypoints, false); } } -bool CWaypointVisibilityTable :: SaveToFile ( void ) +bool CWaypointVisibilityTable::SaveToFile() const { - char filename[1024]; + char filename[1024]; wpt_vis_header_t header; - CBotGlobals::buildFileName(filename,CBotGlobals::getMapName(),BOT_WAYPOINT_FOLDER,"rcv",true); + CBotGlobals::buildFileName(filename, CBotGlobals::getMapName(), BOT_AUXILERY_FOLDER, BOT_VISIBILITY_EXTENSION, true); - FILE *bfp = CBotGlobals::openFile(filename,"wb"); + std::fstream bfp = CBotGlobals::openFile(filename, std::fstream::out | std::fstream::binary); - if ( bfp == NULL ) - { - CBotGlobals::botMessage(NULL,0,"Can't open Waypoint Visibility table for writing!"); - return false; - } + if (!bfp) + { + logger->Log(LogLevel::ERROR, "Can't open Waypoint Visibility table for writing!"); + return false; + } header.numwaypoints = CWaypoints::numWaypoints(); - strncpy(header.szMapName,CBotGlobals::getMapName(),63); + std::strncpy(header.szMapName, CBotGlobals::getMapName(), 63); header.waypoint_version = CWaypoints::WAYPOINT_VERSION; - fwrite(&header,sizeof(wpt_vis_header_t),1,bfp); - fwrite(m_VisTable,sizeof(byte),g_iMaxVisibilityByte,bfp); - - fclose(bfp); + bfp.write(reinterpret_cast(&header), sizeof(wpt_vis_header_t)); + bfp.write(reinterpret_cast(m_VisTable), sizeof(byte) * g_iMaxVisibilityByte); - return true; + return true; } -bool CWaypointVisibilityTable :: ReadFromFile ( int numwaypoints ) +bool CWaypointVisibilityTable::ReadFromFile(const int numwaypoints) const { - char filename[1024]; + char filename[1024]; wpt_vis_header_t header; - CBotGlobals::buildFileName(filename,CBotGlobals::getMapName(),BOT_WAYPOINT_FOLDER,"rcv",true); - - FILE *bfp = CBotGlobals::openFile(filename,"rb"); + CBotGlobals::buildFileName(filename, CBotGlobals::getMapName(), BOT_AUXILERY_FOLDER, BOT_VISIBILITY_EXTENSION, true); - if ( bfp == NULL ) - { - Msg(" *** Can't open Waypoint Visibility table for reading!\n"); - return false; - } + std::fstream bfp = CBotGlobals::openFile(filename, std::fstream::in | std::fstream::binary); - fread(&header,sizeof(wpt_vis_header_t),1,bfp); + if (!bfp) + { + logger->Log(LogLevel::ERROR, "Can't open Waypoint Visibility table for reading!"); + return false; + } - if ( header.numwaypoints != numwaypoints ) - return false; - if ( header.waypoint_version != CWaypoints::WAYPOINT_VERSION ) - return false; - if ( strncmp(header.szMapName,CBotGlobals::getMapName(),63) ) - return false; + bfp.read(reinterpret_cast(&header), sizeof(wpt_vis_header_t)); - fread(m_VisTable,sizeof(byte),g_iMaxVisibilityByte,bfp); + if (header.numwaypoints != numwaypoints) + return false; + if (header.waypoint_version != CWaypoints::WAYPOINT_VERSION) + return false; + if (std::strncmp(header.szMapName, CBotGlobals::getMapName(), 63) != 0) + return false; - fclose(bfp); + bfp.read(reinterpret_cast(m_VisTable), sizeof(byte) * g_iMaxVisibilityByte); - return true; + return true; } \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_waypoint_visibility.h b/utils/RCBot2_meta/bot_waypoint_visibility.h index a5bcf495a..8b0e2025e 100644 --- a/utils/RCBot2_meta/bot_waypoint_visibility.h +++ b/utils/RCBot2_meta/bot_waypoint_visibility.h @@ -33,7 +33,8 @@ #include "bot_waypoint.h" -const int g_iMaxVisibilityByte = (CWaypoints::MAX_WAYPOINTS*CWaypoints::MAX_WAYPOINTS)/8; // divide by 8 bits, need byte number +constexpr int g_iMaxVisibilityByte = +(CWaypoints::MAX_WAYPOINTS * CWaypoints::MAX_WAYPOINTS) / 8; // divide by 8 bits, need byte number typedef struct { @@ -47,7 +48,7 @@ class CWaypointVisibilityTable public: CWaypointVisibilityTable() { - m_VisTable = NULL; + m_VisTable = nullptr; bWorkVisibility = false; iCurFrom = 0; iCurTo = 0; @@ -55,14 +56,14 @@ class CWaypointVisibilityTable m_fNextShowMessageTime = 0; } - void workVisibility (); + void workVisibility(); - void init () + void init() { - int iSize = g_iMaxVisibilityByte; + constexpr int iSize = g_iMaxVisibilityByte; ///////////////////////////// - // for "concurrent" reading of + // for "concurrent" reading of // visibility throughout frames bWorkVisibility = false; m_fNextShowMessageTime = 0; @@ -74,40 +75,40 @@ class CWaypointVisibilityTable m_VisTable = new unsigned char[iSize]; m_iPrevPercent = 0; - memset(m_VisTable,0,iSize); + memset(m_VisTable, 0, iSize); } - bool SaveToFile ( void ); + bool SaveToFile() const; - bool ReadFromFile ( int numwaypoints ); + bool ReadFromFile(int numwaypoints) const; - void workVisibilityForWaypoint ( int i, int iNumWaypoints, bool bTwoway = false ); + void workVisibilityForWaypoint(int i, int iNumWaypoints, bool bTwoway = false) const; - bool GetVisibilityFromTo ( int iFrom, int iTo ) + bool GetVisibilityFromTo(const int iFrom, const int iTo) const { - // work out the position - int iPosition = (iFrom*CWaypoints::MAX_WAYPOINTS)+iTo; + // work out the position + const int iPosition = (iFrom * CWaypoints::MAX_WAYPOINTS) + iTo; - int iByte = (int)(iPosition/8); - int iBit = iPosition%8; + const int iByte = iPosition / 8; + const int iBit = iPosition % 8; - if ( iByte < g_iMaxVisibilityByte ) - { - unsigned char *ToReturn = (m_VisTable+iByte); - - return ( (*ToReturn & (1< 0 ); + if (iByte < g_iMaxVisibilityByte) + { + const unsigned char* ToReturn = (m_VisTable + iByte); + + return ((*ToReturn & (1 << iBit)) > 0); } return false; } - void ClearVisibilityTable ( void ) + void ClearVisibilityTable() { - if ( m_VisTable ) - memset(m_VisTable,0,g_iMaxVisibilityByte); + if (m_VisTable) + memset(m_VisTable, 0, g_iMaxVisibilityByte); ///////////////////////////// - // for "concurrent" reading of + // for "concurrent" reading of // visibility throughout frames bWorkVisibility = false; iCurFrom = 0; @@ -115,16 +116,16 @@ class CWaypointVisibilityTable //////////////////////////// } - void FreeVisibilityTable ( void ) + void FreeVisibilityTable() { - if ( m_VisTable != NULL ) + if (m_VisTable != nullptr) { - delete m_VisTable; - m_VisTable = NULL; + delete[] m_VisTable; + m_VisTable = nullptr; } ///////////////////////////// - // for "concurrent" reading of + // for "concurrent" reading of // visibility throughout frames bWorkVisibility = false; iCurFrom = 0; @@ -132,36 +133,43 @@ class CWaypointVisibilityTable //////////////////////////// } - void SetVisibilityFromTo ( int iFrom, int iTo, bool bVisible ) + void SetVisibilityFromTo(const int iFrom, const int iTo, const bool bVisible) const { - int iPosition = (iFrom*CWaypoints::MAX_WAYPOINTS)+iTo; + int iPosition = (iFrom * CWaypoints::MAX_WAYPOINTS) + iTo; - int iByte = (int)(iPosition/8); - int iBit = iPosition%8; + int iByte = iPosition / 8; + int iBit = iPosition % 8; - if ( iByte < g_iMaxVisibilityByte ) + if (iByte < g_iMaxVisibilityByte) { - unsigned char *ToChange = (m_VisTable+iByte); - - if ( bVisible ) - *ToChange |= (1< +#include +#include +#include +#include +#include +#include +#include + +#include "rcbot/logging.h" + +constexpr std::array g_szDODWeapons = { + "weapon_amerknife", + "weapon_spade", + "weapon_colt", + "weapon_p38", + "weapon_m1carbine", "weapon_c96", - "weapon_garand", - "weapon_k98", - "weapon_thompson", - "weapon_mp40", - "weapon_bar", + "weapon_garand", + "weapon_k98", + "weapon_thompson", + "weapon_mp40", + "weapon_bar", "weapon_mp44", - "weapon_spring", + "weapon_spring", "weapon_k98_scoped", - "weapon_30cal", - "weapon_mg42", - "weapon_bazooka", + "weapon_30cal", + "weapon_mg42", + "weapon_bazooka", "weapon_pschreck", - "weapon_riflegren_us", - "weapon_riflegren_ger", - "weapon_frag_us", - "weapon_frag_ger", - "weapon_smoke_us", + "weapon_riflegren_us", + "weapon_riflegren_ger", + "weapon_frag_us", + "weapon_frag_ger", + "weapon_smoke_us", "weapon_smoke_ger", "weapon_basebomb" }; -const char *g_szHL2DMWeapons[] = -{ +constexpr std::array g_szHL2DMWeapons = { "weapon_pistol", "weapon_crowbar", "weapon_357", @@ -80,190 +91,325 @@ const char *g_szHL2DMWeapons[] = "weapon_physcannon" }; - /* 0, 0, 1, 2, 6, 3, - 4, 5, 8, 8, 9, 8, - 7, 5, 10, 11, 12, 12, - 21, 22, 13, 14, 17, 18*/ +//TODO: Add Black Mesa weapons support [APG]RoboCop[CL] +/*constexpr std::array g_szBMSWeapons = { + "weapon_357", + "weapon_assassin_glock", + "weapon_crossbow", + "weapon_crowbar", + "weapon_frag", + "weapon_glock", + "weapon_gluon", + "weapon_hivehand", + "weapon_mp5", + "weapon_rpg", + "weapon_satchel", + "weapon_shotgun", + "weapon_snark", + "weapon_tau", + "weapon_tripmine" +};*/ -WeaponsData_t DODWeaps[] = -{ -/* - slot, id , weapon name, flags, min dist, max dist, ammo index, preference - */ - {1,DOD_WEAPON_AMERKNIFE, g_szDODWeapons[0], WEAP_FL_PRIM_ATTACK|WEAP_FL_MELEE|WEAP_FL_UNDERWATER,0,100,-1,1,0}, - {1,DOD_WEAPON_SPADE, g_szDODWeapons[1], WEAP_FL_PRIM_ATTACK|WEAP_FL_MELEE|WEAP_FL_UNDERWATER,0,100,-1,1,0}, - {2,DOD_WEAPON_COLT, g_szDODWeapons[2], WEAP_FL_PRIM_ATTACK|WEAP_FL_UNDERWATER,0,800,1,2,0}, - {2,DOD_WEAPON_P38, g_szDODWeapons[3], WEAP_FL_PRIM_ATTACK|WEAP_FL_UNDERWATER,0,800,2,2,0}, +constexpr std::array g_szSYNWeapons = { + "weapon_pistol", // 0 + "weapon_crowbar", + "weapon_pipe", + "weapon_357", + "weapon_deagle", + "weapon_smg1", // 5 + "weapon_mp5k", + "weapon_ar2", + "weapon_frag", + "weapon_stunstick", + "weapon_crossbow", // 10 + "weapon_rpg", + "weapon_slam", + "weapon_shotgun", + "weapon_physcannon", + "weapon_mg1", // 15 + "weapon_bugbait" +}; + +constexpr std::array g_szCSWeapons = { + "weapon_knife", // 0 + "weapon_usp", + "weapon_glock", + "weapon_p228", + "weapon_fiveseven", + "weapon_elite", // 5 + "weapon_deagle", + "weapon_m3", + "weapon_xm1014", + "weapon_tmp", + "weapon_mac10", // 10 + "weapon_mp5navy", + "weapon_ump45", + "weapon_p90", + "weapon_famas", + "weapon_galil", // 15 + "weapon_ak47", + "weapon_m4a1", + "weapon_aug", + "weapon_sg552", + "weapon_scout", // 20 + "weapon_awp", + "weapon_sg550", + "weapon_g3sg1", + "weapon_m249", + "weapon_hegrenade", // 25 + "weapon_flashbang", + "weapon_smokegrenade", + "weapon_c4" +}; + +/* 0, 0, 1, 2, 6, 3, + 4, 5, 8, 8, 9, 8, + 7, 5, 10, 11, 12, 12, + 21, 22, 13, 14, 17, 18*/ + +std::vector DODWeaps = { + + // slot, id , weapon name, flags, min dist, max dist, ammo index, preference + {1,DOD_WEAPON_AMERKNIFE, g_szDODWeapons[0], WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER,0,100,-1,1,0}, + {1,DOD_WEAPON_SPADE, g_szDODWeapons[1], WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER,0,100,-1,1,0}, + {2,DOD_WEAPON_COLT, g_szDODWeapons[2], WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER,0,800,1,2,0}, + {2,DOD_WEAPON_P38, g_szDODWeapons[3], WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER,0,800,2,2,0}, {3,DOD_WEAPON_M1, g_szDODWeapons[4], WEAP_FL_PRIM_ATTACK,0,1600,6,4,0}, {3,DOD_WEAPON_C96, g_szDODWeapons[5], WEAP_FL_PRIM_ATTACK,0,1600,-1,4,0}, - {3,DOD_WEAPON_GARAND, g_szDODWeapons[6], WEAP_FL_PRIM_ATTACK|WEAP_FL_ZOOMABLE,0,1600,-1,3,0}, - {3,DOD_WEAPON_K98, g_szDODWeapons[7], WEAP_FL_PRIM_ATTACK|WEAP_FL_ZOOMABLE,0,1600,-1,3,0}, - {3,DOD_WEAPON_THOMPSON, g_szDODWeapons[8], WEAP_FL_PRIM_ATTACK|WEAP_FL_MELEE_SEC_ATT,0,900,-1,3,0}, - {3,DOD_WEAPON_MP40, g_szDODWeapons[9], WEAP_FL_PRIM_ATTACK|WEAP_FL_MELEE_SEC_ATT,0,1600,-1,4,0}, + {3,DOD_WEAPON_GARAND, g_szDODWeapons[6], WEAP_FL_PRIM_ATTACK | WEAP_FL_ZOOMABLE,0,1600,-1,3,0}, + {3,DOD_WEAPON_K98, g_szDODWeapons[7], WEAP_FL_PRIM_ATTACK | WEAP_FL_ZOOMABLE,0,1600,-1,3,0}, + {3,DOD_WEAPON_THOMPSON, g_szDODWeapons[8], WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE_SEC_ATT,0,900,-1,3,0}, + {3,DOD_WEAPON_MP40, g_szDODWeapons[9], WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE_SEC_ATT,0,1600,-1,4,0}, {3,DOD_WEAPON_BAR, g_szDODWeapons[10], WEAP_FL_PRIM_ATTACK,0,1600,-1,3,0}, {3,DOD_WEAPON_MP44, g_szDODWeapons[11], WEAP_FL_PRIM_ATTACK,0,1600,-1,3,0}, - {3,DOD_WEAPON_SPRING, g_szDODWeapons[12], WEAP_FL_PRIM_ATTACK|WEAP_FL_SCOPE|WEAP_FL_CANTFIRE_NORM|WEAP_FL_ZOOMABLE,0,3200,-1,3,0}, - {3,DOD_WEAPON_K98_SCOPED, g_szDODWeapons[13], WEAP_FL_PRIM_ATTACK|WEAP_FL_SCOPE|WEAP_FL_CANTFIRE_NORM|WEAP_FL_ZOOMABLE,0,3200,-1,4,0}, - {3,DOD_WEAPON_20CAL, g_szDODWeapons[14], WEAP_FL_PRIM_ATTACK|WEAP_FL_DEPLOYABLE|WEAP_FL_HIGH_RECOIL,0,2000,-1,4,0}, - {3,DOD_WEAPON_MG42, g_szDODWeapons[15], WEAP_FL_PRIM_ATTACK|WEAP_FL_DEPLOYABLE|WEAP_FL_HIGH_RECOIL,0,2000,-1,4,0}, - {3,DOD_WEAPON_BAZOOKA, g_szDODWeapons[16], WEAP_FL_PROJECTILE|WEAP_FL_EXPLOSIVE|WEAP_FL_PRIM_ATTACK|WEAP_FL_CANTFIRE_NORM|WEAP_FL_DEPLOYABLE,500,3200,-1,5,1300}, - {3,DOD_WEAPON_PSCHRECK, g_szDODWeapons[17], WEAP_FL_PROJECTILE|WEAP_FL_EXPLOSIVE|WEAP_FL_PRIM_ATTACK|WEAP_FL_CANTFIRE_NORM|WEAP_FL_DEPLOYABLE,500,3200,-1,5,1300}, - {3,DOD_WEAPON_RIFLEGREN_US, g_szDODWeapons[18], WEAP_FL_EXPLOSIVE_SEC|WEAP_FL_PRIM_ATTACK,500,1800,-1,4,0}, - {3,DOD_WEAPON_RIFLEGREN_GER, g_szDODWeapons[19], WEAP_FL_EXPLOSIVE_SEC|WEAP_FL_PRIM_ATTACK,500,1800,-1,4,0}, - {3,DOD_WEAPON_FRAG_US, g_szDODWeapons[20], WEAP_FL_PROJECTILE|WEAP_FL_GRENADE|WEAP_FL_EXPLOSIVE|WEAP_FL_NONE,0,1200,-1,1,0}, - {3,DOD_WEAPON_FRAG_GER, g_szDODWeapons[21], WEAP_FL_PROJECTILE|WEAP_FL_GRENADE|WEAP_FL_EXPLOSIVE|WEAP_FL_NONE,0,1200,-1,1,0}, - {3,DOD_WEAPON_SMOKE_US, g_szDODWeapons[22], WEAP_FL_PROJECTILE|WEAP_FL_GRENADE,0,1200,-1,1,0}, - {3,DOD_WEAPON_SMOKE_GER, g_szDODWeapons[23], WEAP_FL_PROJECTILE|WEAP_FL_GRENADE,0,1200,-1,1,0}, + {3,DOD_WEAPON_SPRING, g_szDODWeapons[12], WEAP_FL_PRIM_ATTACK | WEAP_FL_SCOPE | WEAP_FL_CANTFIRE_NORM | WEAP_FL_ZOOMABLE,0,3200,-1,3,0}, + {3,DOD_WEAPON_K98_SCOPED, g_szDODWeapons[13], WEAP_FL_PRIM_ATTACK | WEAP_FL_SCOPE | WEAP_FL_CANTFIRE_NORM | WEAP_FL_ZOOMABLE,0,3200,-1,4,0}, + {3,DOD_WEAPON_20CAL, g_szDODWeapons[14], WEAP_FL_PRIM_ATTACK | WEAP_FL_DEPLOYABLE | WEAP_FL_HIGH_RECOIL,0,2000,-1,4,0}, + {3,DOD_WEAPON_MG42, g_szDODWeapons[15], WEAP_FL_PRIM_ATTACK | WEAP_FL_DEPLOYABLE | WEAP_FL_HIGH_RECOIL,0,2000,-1,4,0}, + {3,DOD_WEAPON_BAZOOKA, g_szDODWeapons[16], WEAP_FL_PROJECTILE | WEAP_FL_EXPLOSIVE | WEAP_FL_PRIM_ATTACK | WEAP_FL_CANTFIRE_NORM | WEAP_FL_DEPLOYABLE,500,3200,-1,5,1300}, + {3,DOD_WEAPON_PSCHRECK, g_szDODWeapons[17], WEAP_FL_PROJECTILE | WEAP_FL_EXPLOSIVE | WEAP_FL_PRIM_ATTACK | WEAP_FL_CANTFIRE_NORM | WEAP_FL_DEPLOYABLE,500,3200,-1,5,1300}, + {3,DOD_WEAPON_RIFLEGREN_US, g_szDODWeapons[18], WEAP_FL_EXPLOSIVE_SEC | WEAP_FL_PRIM_ATTACK,500,1800,-1,4,0}, + {3,DOD_WEAPON_RIFLEGREN_GER, g_szDODWeapons[19], WEAP_FL_EXPLOSIVE_SEC | WEAP_FL_PRIM_ATTACK,500,1800,-1,4,0}, + {3,DOD_WEAPON_FRAG_US, g_szDODWeapons[20], WEAP_FL_PROJECTILE | WEAP_FL_GRENADE | WEAP_FL_EXPLOSIVE | WEAP_FL_NONE,0,1200,-1,1,0}, + {3,DOD_WEAPON_FRAG_GER, g_szDODWeapons[21], WEAP_FL_PROJECTILE | WEAP_FL_GRENADE | WEAP_FL_EXPLOSIVE | WEAP_FL_NONE,0,1200,-1,1,0}, + {3,DOD_WEAPON_SMOKE_US, g_szDODWeapons[22], WEAP_FL_PROJECTILE | WEAP_FL_GRENADE,0,1200,-1,1,0}, + {3,DOD_WEAPON_SMOKE_GER, g_szDODWeapons[23], WEAP_FL_PROJECTILE | WEAP_FL_GRENADE,0,1200,-1,1,0}, {3,DOD_WEAPON_BOMB, g_szDODWeapons[24], WEAP_FL_NONE,0,0,-1,1,0}, { 0, 0, "\0", 0, 0, 0, 0, 0, 0 }//signal last weapon }; -WeaponsData_t HL2DMWeaps[] = -{ -/* - slot, id , weapon name, flags, min dist, max dist, ammo index, preference -*/ - {2,HL2DM_WEAPON_PISTOL, g_szHL2DMWeapons[0], WEAP_FL_PRIM_ATTACK|WEAP_FL_UNDERWATER,0,1000,-1,1,0}, - {1,HL2DM_WEAPON_CROWBAR, g_szHL2DMWeapons[1], WEAP_FL_PRIM_ATTACK|WEAP_FL_MELEE|WEAP_FL_UNDERWATER,0,128,-1,1,0}, +std::vector HL2DMWeaps = { + + // slot, id , weapon name, flags, min dist, max dist, ammo index, preference + {2,HL2DM_WEAPON_PISTOL, g_szHL2DMWeapons[0], WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER,0,1000,-1,1,0}, + {1,HL2DM_WEAPON_CROWBAR, g_szHL2DMWeapons[1], WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER,0,128,-1,1,0}, {2,HL2DM_WEAPON_357, g_szHL2DMWeapons[2], WEAP_FL_PRIM_ATTACK,0,768,-1,2,0}, - {3,HL2DM_WEAPON_SMG1, g_szHL2DMWeapons[3], WEAP_FL_PRIM_ATTACK|WEAP_FL_SEC_ATTACK,0,1400,-1,2,0}, - {2,HL2DM_WEAPON_AR2, g_szHL2DMWeapons[4], WEAP_FL_PRIM_ATTACK|WEAP_FL_SEC_ATTACK,0,1400,-1,3,0}, - {1,HL2DM_WEAPON_FRAG, g_szHL2DMWeapons[5], WEAP_FL_GRENADE|WEAP_FL_EXPLOSIVE,0,180,-1,1,0}, - {2,HL2DM_WEAPON_STUNSTICK, g_szHL2DMWeapons[6], WEAP_FL_PRIM_ATTACK|WEAP_FL_MELEE|WEAP_FL_UNDERWATER,0,128,-1,1,0}, - {3,HL2DM_WEAPON_CROSSBOW, g_szHL2DMWeapons[7], WEAP_FL_PRIM_ATTACK|WEAP_FL_SCOPE|WEAP_FL_UNDERWATER,0,2000,-1,2,0}, - {2,HL2DM_WEAPON_RPG, g_szHL2DMWeapons[8], WEAP_FL_PROJECTILE|WEAP_FL_EXPLOSIVE|WEAP_FL_PRIM_ATTACK|WEAP_FL_UNDERWATER,400,2000,-1,3,1000.0f}, + {3,HL2DM_WEAPON_SMG1, g_szHL2DMWeapons[3], WEAP_FL_PRIM_ATTACK | WEAP_FL_SEC_ATTACK,0,1400,-1,2,0}, + {2,HL2DM_WEAPON_AR2, g_szHL2DMWeapons[4], WEAP_FL_PRIM_ATTACK | WEAP_FL_SEC_ATTACK,0,1400,-1,3,0}, + {1,HL2DM_WEAPON_FRAG, g_szHL2DMWeapons[5], WEAP_FL_GRENADE | WEAP_FL_EXPLOSIVE,0,180,-1,1,0}, + {2,HL2DM_WEAPON_STUNSTICK, g_szHL2DMWeapons[6], WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER,0,128,-1,1,0}, + {3,HL2DM_WEAPON_CROSSBOW, g_szHL2DMWeapons[7], WEAP_FL_PRIM_ATTACK | WEAP_FL_SCOPE | WEAP_FL_UNDERWATER,0,2000,-1,2,0}, + {2,HL2DM_WEAPON_RPG, g_szHL2DMWeapons[8], WEAP_FL_PROJECTILE | WEAP_FL_EXPLOSIVE | WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER,400,2000,-1,3,1000.0f}, {1,HL2DM_WEAPON_SLAM, g_szHL2DMWeapons[9], WEAP_FL_EXPLOSIVE,0,180,-1,1,0}, {2,HL2DM_WEAPON_SHOTGUN, g_szHL2DMWeapons[10], WEAP_FL_PRIM_ATTACK,0,768,-1,2,0}, - {1,HL2DM_WEAPON_PHYSCANNON, g_szHL2DMWeapons[11], WEAP_FL_GRAVGUN|WEAP_FL_PRIM_ATTACK,0,768,-1,4,0}, + {1,HL2DM_WEAPON_PHYSCANNON, g_szHL2DMWeapons[11], WEAP_FL_GRAVGUN | WEAP_FL_PRIM_ATTACK,0,768,-1,4,0}, { 0, 0, "\0", 0, 0, 0, 0, 0, 0 }//signal last weapon }; //SENTRYGUN ID = 34 - -WeaponsData_t TF2Weaps[] = -{ - -//{"slot, id , weapon name, flags, min dist, max dist, ammo index, preference - - {TF2_SLOT_MELEE,TF2_WEAPON_BAT, "tf_weapon_bat", WEAP_FL_PRIM_ATTACK|WEAP_FL_MELEE|WEAP_FL_UNDERWATER,0,180,0,1,0}, - {TF2_SLOT_MELEE,TF2_WEAPON_BOTTLE, "tf_weapon_bottle", WEAP_FL_PRIM_ATTACK|WEAP_FL_MELEE|WEAP_FL_UNDERWATER,0,180,0,1,0}, - {TF2_SLOT_MELEE,TF2_WEAPON_FIREAXE, "tf_weapon_fireaxe", WEAP_FL_PRIM_ATTACK|WEAP_FL_MELEE|WEAP_FL_UNDERWATER,0,180,0,1,0}, - {TF2_SLOT_MELEE,TF2_WEAPON_CLUB, "tf_weapon_club", WEAP_FL_PRIM_ATTACK|WEAP_FL_MELEE|WEAP_FL_UNDERWATER,0,180,0,1,0}, - {TF2_SLOT_MELEE,TF2_WEAPON_KNIFE, "tf_weapon_knife", WEAP_FL_PRIM_ATTACK|WEAP_FL_MELEE|WEAP_FL_UNDERWATER,0,220,0,2,0}, - {TF2_SLOT_MELEE,TF2_WEAPON_FISTS, "tf_weapon_fists", WEAP_FL_PRIM_ATTACK|WEAP_FL_MELEE|WEAP_FL_UNDERWATER,0,180,0,1,0}, - {TF2_SLOT_MELEE,TF2_WEAPON_SHOVEL, "tf_weapon_shovel", WEAP_FL_PRIM_ATTACK|WEAP_FL_MELEE|WEAP_FL_UNDERWATER,0,180,0,1,0}, - {TF2_SLOT_MELEE,TF2_WEAPON_WRENCH, "tf_weapon_wrench", WEAP_FL_PRIM_ATTACK|WEAP_FL_MELEE|WEAP_FL_UNDERWATER,0,180,3,1,0}, - {TF2_SLOT_MELEE,TF2_WEAPON_BONESAW, "tf_weapon_bonesaw", WEAP_FL_PRIM_ATTACK|WEAP_FL_MELEE|WEAP_FL_UNDERWATER,0,180,0,1,0}, - {TF2_SLOT_PRMRY,TF2_WEAPON_SHOTGUN_PRIMARY, "tf_weapon_shotgun_primary", WEAP_FL_KILLPIPEBOMBS|WEAP_FL_PRIM_ATTACK|WEAP_FL_UNDERWATER,0,800,1,2,0}, - {TF2_SLOT_SCNDR,TF2_WEAPON_SHOTGUN_SOLDIER, "tf_weapon_shotgun_soldier", WEAP_FL_KILLPIPEBOMBS|WEAP_FL_PRIM_ATTACK|WEAP_FL_UNDERWATER,0,500,2,2,0}, - {TF2_SLOT_SCNDR,TF2_WEAPON_SHOTGUN_HWG, "tf_weapon_shotgun_hwg", WEAP_FL_KILLPIPEBOMBS|WEAP_FL_PRIM_ATTACK|WEAP_FL_UNDERWATER,0,800,2,2,0}, - {TF2_SLOT_SCNDR,TF2_WEAPON_SHOTGUN_PYRO, "tf_weapon_shotgun_pyro", WEAP_FL_KILLPIPEBOMBS|WEAP_FL_PRIM_ATTACK|WEAP_FL_UNDERWATER,0,800,2,2,0}, - {TF2_SLOT_PRMRY,TF2_WEAPON_SCATTERGUN, "tf_weapon_scattergun", WEAP_FL_KILLPIPEBOMBS|WEAP_FL_PRIM_ATTACK|WEAP_FL_UNDERWATER,0,800,1,3,0}, - {TF2_SLOT_PRMRY,TF2_WEAPON_SNIPERRIFLE, "tf_weapon_sniperrifle", WEAP_FL_SCOPE|WEAP_FL_PRIM_ATTACK,1000,4000,1,3,0}, - {TF2_SLOT_PRMRY,TF2_WEAPON_MINIGUN, "tf_weapon_minigun", WEAP_FL_PRIM_ATTACK|WEAP_FL_HOLDATTACK,120,1800,1,3,0}, - {TF2_SLOT_SCNDR,TF2_WEAPON_SMG, "tf_weapon_smg", WEAP_FL_KILLPIPEBOMBS|WEAP_FL_PRIM_ATTACK|WEAP_FL_UNDERWATER,0,1000,2,2,0}, - {TF2_SLOT_PRMRY,TF2_WEAPON_SYRINGEGUN, "tf_weapon_syringegun_medic", WEAP_FL_PRIM_ATTACK|WEAP_FL_UNDERWATER,0,1000,1,2,0}, - {TF2_SLOT_PRMRY,TF2_WEAPON_ROCKETLAUNCHER, "tf_weapon_rocketlauncher", WEAP_FL_PRIM_ATTACK|WEAP_FL_EXPLOSIVE|WEAP_FL_UNDERWATER,BLAST_RADIUS,4096,1,3,TF2_ROCKETSPEED}, - {TF2_SLOT_PRMRY,TF2_WEAPON_GRENADELAUNCHER, "tf_weapon_grenadelauncher", WEAP_FL_PROJECTILE|WEAP_FL_PRIM_ATTACK|WEAP_FL_EXPLOSIVE|WEAP_FL_UNDERWATER,100,1200,1,2,TF2_GRENADESPEED}, +//TODO: Add Black Mesa weapons support [APG]RoboCop[CL] +/*std::vector BMSWeaps = { + + // slot, id , weapon name, flags, min dist, max dist, ammo index, preference + {2,BMS_WEAPON_GLOCK, g_szBMSWeapons[0], WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER,0,1000,-1,1,0}, + {1,BMS_WEAPON_CROWBAR, g_szBMSWeapons[1], WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER,0,128,-1,1,0}, + {2,BMS_WEAPON_PYTHON, g_szBMSWeapons[2], WEAP_FL_PRIM_ATTACK,0,768,-1,2,0}, + {3,BMS_WEAPON_MP5, g_szBMSWeapons[3], WEAP_FL_PRIM_ATTACK | WEAP_FL_SEC_ATTACK,0,1400,-1,2,0}, + //Chaingun? + {3,BMS_WEAPON_CROSSBOW, g_szBMSWeapons[5], WEAP_FL_PRIM_ATTACK | WEAP_FL_SCOPE | WEAP_FL_UNDERWATER,0,2000,-1,2,0}, + {3,BMS_WEAPON_SHOTGUN, g_szBMSWeapons[6], WEAP_FL_PRIM_ATTACK,0,768,-1,2,0}, + {4,BMS_WEAPON_RPG, g_szBMSWeapons[7], WEAP_FL_PROJECTILE | WEAP_FL_EXPLOSIVE | WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER,400,2000,-1,3,1000.0f}, + {4,BMS_WEAPON_TAU, g_szBMSWeapons[8], WEAP_FL_PRIM_ATTACK | WEAP_FL_SEC_ATTACK,0,1400,-1,3,0}, + {4,BMS_WEAPON_GLUON, g_szBMSWeapons[9], WEAP_FL_PRIM_ATTACK | WEAP_FL_SEC_ATTACK,0,1400,-1,3,0}, + //Hornetgun? + {5,BMS_WEAPON_HANDGRENADE, g_szBMSWeapons[11], WEAP_FL_GRENADE | WEAP_FL_EXPLOSIVE,0,180,-1,1,0}, + //Tripmine? + {5,BMS_WEAPON_SATCHEL, g_szBMSWeapons[13], WEAP_FL_EXPLOSIVE,0,180,-1,1,0}, + //Snark? + { 0, 0, "\0", 0, 0, 0, 0, 0, 0 }//signal last weapon +};*/ + +std::vector TF2Weaps = { + + // slot, id , weapon name, flags, min dist, max dist, ammo index, preference + {TF2_SLOT_MELEE,TF2_WEAPON_BAT, "tf_weapon_bat", WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER,0,180,0,1,0}, + {TF2_SLOT_MELEE,TF2_WEAPON_BOTTLE, "tf_weapon_bottle", WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER,0,180,0,1,0}, + {TF2_SLOT_MELEE,TF2_WEAPON_FIREAXE, "tf_weapon_fireaxe", WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER,0,180,0,1,0}, + {TF2_SLOT_MELEE,TF2_WEAPON_CLUB, "tf_weapon_club", WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER,0,180,0,1,0}, + {TF2_SLOT_MELEE,TF2_WEAPON_KNIFE, "tf_weapon_knife", WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER,0,220,0,2,0}, + {TF2_SLOT_MELEE,TF2_WEAPON_FISTS, "tf_weapon_fists", WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER,0,180,0,1,0}, + {TF2_SLOT_MELEE,TF2_WEAPON_SHOVEL, "tf_weapon_shovel", WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER,0,180,0,1,0}, + {TF2_SLOT_MELEE,TF2_WEAPON_WRENCH, "tf_weapon_wrench", WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER,0,180,3,1,0}, + {TF2_SLOT_MELEE,TF2_WEAPON_BONESAW, "tf_weapon_bonesaw", WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER,0,180,0,1,0}, + {TF2_SLOT_PRMRY,TF2_WEAPON_SHOTGUN_PRIMARY, "tf_weapon_shotgun_primary", WEAP_FL_KILLPIPEBOMBS | WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER,0,800,1,2,0}, + {TF2_SLOT_SCNDR,TF2_WEAPON_SHOTGUN_SOLDIER, "tf_weapon_shotgun_soldier", WEAP_FL_KILLPIPEBOMBS | WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER,0,500,2,2,0}, + {TF2_SLOT_SCNDR,TF2_WEAPON_SHOTGUN_HWG, "tf_weapon_shotgun_hwg", WEAP_FL_KILLPIPEBOMBS | WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER,0,800,2,2,0}, + {TF2_SLOT_SCNDR,TF2_WEAPON_SHOTGUN_PYRO, "tf_weapon_shotgun_pyro", WEAP_FL_KILLPIPEBOMBS | WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER,0,800,2,2,0}, + {TF2_SLOT_PRMRY,TF2_WEAPON_SCATTERGUN, "tf_weapon_scattergun", WEAP_FL_KILLPIPEBOMBS | WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER,0,800,1,3,0}, + {TF2_SLOT_PRMRY,TF2_WEAPON_SNIPERRIFLE, "tf_weapon_sniperrifle", WEAP_FL_SCOPE | WEAP_FL_PRIM_ATTACK,1000,4000,1,3,0}, + {TF2_SLOT_PRMRY,TF2_WEAPON_SNIPERRIFLE_DECAP, "tf_weapon_sniperrifle_decap", WEAP_FL_SCOPE | WEAP_FL_PRIM_ATTACK, 1000, 4000, 1, 3, 0 }, + {TF2_SLOT_PRMRY,TF2_WEAPON_MINIGUN, "tf_weapon_minigun", WEAP_FL_PRIM_ATTACK | WEAP_FL_HOLDATTACK,120,1800,1,3,0}, + {TF2_SLOT_SCNDR,TF2_WEAPON_SMG, "tf_weapon_smg", WEAP_FL_KILLPIPEBOMBS | WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER,0,1000,2,2,0}, + {TF2_SLOT_PRMRY,TF2_WEAPON_SYRINGEGUN, "tf_weapon_syringegun_medic", WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER,0,1000,1,2,0}, + {TF2_SLOT_PRMRY,TF2_WEAPON_ROCKETLAUNCHER, "tf_weapon_rocketlauncher", WEAP_FL_PRIM_ATTACK | WEAP_FL_EXPLOSIVE | WEAP_FL_UNDERWATER,BLAST_RADIUS,4096,1,3,TF2_ROCKETSPEED}, + {TF2_SLOT_PRMRY,TF2_WEAPON_GRENADELAUNCHER, "tf_weapon_grenadelauncher", WEAP_FL_PROJECTILE | WEAP_FL_PRIM_ATTACK | WEAP_FL_EXPLOSIVE | WEAP_FL_UNDERWATER,100,1200,1,2,TF2_GRENADESPEED}, {TF2_SLOT_SCNDR,TF2_WEAPON_PIPEBOMBS, "tf_weapon_pipebomblauncher", WEAP_FL_NONE,0,1000,2,1,0}, - {TF2_SLOT_PRMRY,TF2_WEAPON_FLAMETHROWER, "tf_weapon_flamethrower", WEAP_FL_DEFLECTROCKETS|WEAP_FL_PRIM_ATTACK|WEAP_FL_MELEE|WEAP_FL_HOLDATTACK|WEAP_FL_SPECIAL,0,400,1,3,0}, - {TF2_SLOT_SCNDR,TF2_WEAPON_PISTOL, "tf_weapon_pistol", WEAP_FL_KILLPIPEBOMBS|WEAP_FL_PRIM_ATTACK|WEAP_FL_UNDERWATER,0,2000,2,1,0}, - {TF2_SLOT_SCNDR,TF2_WEAPON_PISTOL_SCOUT, "tf_weapon_pistol_scout", WEAP_FL_KILLPIPEBOMBS|WEAP_FL_PRIM_ATTACK|WEAP_FL_UNDERWATER,0,1800,2,2,0}, - {TF2_SLOT_SCNDR,TF2_WEAPON_REVOLVER, "tf_weapon_revolver", WEAP_FL_KILLPIPEBOMBS|WEAP_FL_PRIM_ATTACK|WEAP_FL_UNDERWATER,0,1400,2,1,0}, - { TF2_SLOT_PRMRY, TF2_WEAPON_POMSON6000, "tf_weapon_drg_pomson", WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER, 0, 800, 1, 2, 0 }, + {TF2_SLOT_PRMRY,TF2_WEAPON_FLAMETHROWER, "tf_weapon_flamethrower", WEAP_FL_DEFLECTROCKETS | WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_HOLDATTACK | WEAP_FL_SPECIAL,0,400,1,3,0}, + {TF2_SLOT_SCNDR,TF2_WEAPON_PISTOL, "tf_weapon_pistol", WEAP_FL_KILLPIPEBOMBS | WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER,0,2000,2,1,0}, + {TF2_SLOT_SCNDR,TF2_WEAPON_PISTOL_SCOUT, "tf_weapon_pistol_scout", WEAP_FL_KILLPIPEBOMBS | WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER,0,1800,2,2,0}, + {TF2_SLOT_SCNDR,TF2_WEAPON_REVOLVER, "tf_weapon_revolver", WEAP_FL_KILLPIPEBOMBS | WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER,0,1400,2,1,0}, + + // Custom Weapons + + {TF2_SLOT_PRMRY, TF2_WEAPON_POMSON6000, "tf_weapon_drg_pomson", WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER, 0, 800, 1, 2, 0 }, //{TF2_SLOT_PDA,TF2_WEAPON_PDA_ENGI_BUILD, "tf_weapon_pda_engineer_build", WEAP_FL_NONE,0,100,0,1,0}, // this class is used with all classes that can use shotgun but the slot might be different - { TF2_SLOT_SCNDR, TF2_WEAPON_SHOTGUN, "tf_weapon_shotgun", WEAP_FL_KILLPIPEBOMBS | WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER, 0, 500, 2, 2, 0 }, + {TF2_SLOT_SCNDR, TF2_WEAPON_SHOTGUN, "tf_weapon_shotgun", WEAP_FL_KILLPIPEBOMBS | WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER, 0, 500, 2, 2, 0 }, //{TF2_SLOT_OTHER,TF2_WEAPON_PDA_ENGI_DESTROY, "tf_weapon_pda_engineer_destroy", WEAP_FL_NONE,0,100,0,1,0}, //{TF2_SLOT_PDA, TF2_WEAPON_PDA_SPY, "tf_weapon_pda_spy", WEAP_FL_NONE, 0, 100, 0, 1, 0 }, - { TF2_SLOT_PRMRY, TF2_WEAPON_FRONTIERJUSTICE, "tf_weapon_sentry_revenge", WEAP_FL_KILLPIPEBOMBS | WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER, 0, 800, 1, 2, 0 }, + {TF2_SLOT_PRMRY, TF2_WEAPON_FRONTIERJUSTICE, "tf_weapon_sentry_revenge", WEAP_FL_KILLPIPEBOMBS | WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER, 0, 800, 1, 2, 0 }, {TF2_SLOT_PDA, TF2_WEAPON_BUILDER, "tf_weapon_builder", WEAP_FL_NONE, 0, 100, 0, 1, 0 }, {TF2_SLOT_SCNDR,TF2_WEAPON_MEDIGUN, "tf_weapon_medigun", WEAP_FL_NONE,0,100,0,1,0}, {TF2_SLOT_PDA, TF2_WEAPON_INVIS, "tf_weapon_invis", WEAP_FL_NONE, 0, 100, 0, 1, 0 }, {TF2_SLOT_SCNDR,TF2_WEAPON_BUFF_ITEM, "tf_weapon_buff_item", WEAP_FL_NONE,0,100,0,1,0}, - { TF2_SLOT_SCNDR, TF2_WEAPON_FLAREGUN, "tf_weapon_flaregun", WEAP_FL_PRIM_ATTACK, 0, 1600, 2, 2, TF2_GRENADESPEED }, + {TF2_SLOT_SCNDR, TF2_WEAPON_FLAREGUN, "tf_weapon_flaregun", WEAP_FL_PRIM_ATTACK, 0, 1600, 2, 2, TF2_GRENADESPEED }, {TF2_SLOT_PDA, TF2_WEAPON_SENTRYGUN, "obj_sentrygun", 0, 0, 0, 0, 0, 0 }, - {TF2_SLOT_MELEE,TF2_WEAPON_SAXXY, "saxxy", WEAP_FL_PRIM_ATTACK|WEAP_FL_MELEE|WEAP_FL_UNDERWATER,0,150,0,1,0}, - {TF2_SLOT_MELEE,TF2_WEAPON_BAT_WOOD, "tf_weapon_bat_wood", WEAP_FL_PRIM_ATTACK|WEAP_FL_MELEE|WEAP_FL_UNDERWATER,0,180,0,1,0}, + {TF2_SLOT_MELEE,TF2_WEAPON_SAXXY, "saxxy", WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER,0,150,0,1,0}, + //Bat Wood AKA The Sandman + {TF2_SLOT_MELEE,TF2_WEAPON_BAT_WOOD, "tf_weapon_bat_wood", WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER,0,180,0,1,0}, {TF2_SLOT_SCNDR,TF2_WEAPON_LUNCHBOX_DRINK, "tf_weapon_lunchbox_drink", WEAP_FL_NONE,0,180,0,1,0}, - { TF2_SLOT_PRMRY, TF2_WEAPON_BOW, "tf_weapon_compound_bow", WEAP_FL_SCOPE | WEAP_FL_PRIM_ATTACK | WEAP_FL_PROJECTILE, 400, 2500, 1, 3, 1875}, + {TF2_SLOT_PRMRY, TF2_WEAPON_BOW, "tf_weapon_compound_bow", WEAP_FL_SCOPE | WEAP_FL_PRIM_ATTACK | WEAP_FL_PROJECTILE, 400, 2500, 1, 3, 1875}, {TF2_SLOT_SCNDR,TF2_WEAPON_JAR, "tf_weapon_jar", WEAP_FL_NONE,0,180,0,1,0}, - {TF2_SLOT_MELEE,TF2_WEAPON_BAT_FISH, "tf_weapon_bat_fish", WEAP_FL_PRIM_ATTACK|WEAP_FL_MELEE|WEAP_FL_UNDERWATER,0,180,0,1,0}, - {TF2_SLOT_PRMRY,TF2_WEAPON_DIRECTHIT, "tf_weapon_rocketlauncher_directhit", WEAP_FL_PRIM_ATTACK|WEAP_FL_EXPLOSIVE|WEAP_FL_UNDERWATER,BLAST_RADIUS,4096,1,3,TF2_ROCKETSPEED*1.8}, - {TF2_SLOT_MELEE,TF2_WEAPON_SWORD, "tf_weapon_sword", WEAP_FL_PRIM_ATTACK|WEAP_FL_MELEE|WEAP_FL_UNDERWATER,0,190,0,1,0}, - {TF2_SLOT_MELEE,TF2_WEAPON_KATANA, "tf_weapon_katana", WEAP_FL_PRIM_ATTACK|WEAP_FL_MELEE|WEAP_FL_UNDERWATER,0,210,0,1,0}, - { TF2_SLOT_PRMRY, TF2_WEAPON_COWMANGLER, "tf_weapon_particle_cannon", WEAP_FL_KILLPIPEBOMBS | WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER, 0, 1500, 1, 2, TF2_ROCKETSPEED }, + {TF2_SLOT_MELEE,TF2_WEAPON_BAT_FISH, "tf_weapon_bat_fish", WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER,0,180,0,1,0}, + {TF2_SLOT_PRMRY,TF2_WEAPON_DIRECTHIT, "tf_weapon_rocketlauncher_directhit", WEAP_FL_PRIM_ATTACK | WEAP_FL_EXPLOSIVE | WEAP_FL_UNDERWATER,BLAST_RADIUS,4096,1,3,static_cast(TF2_ROCKETSPEED) * 1.8f}, + {TF2_SLOT_MELEE,TF2_WEAPON_SWORD, "tf_weapon_sword", WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER,0,190,0,1,0}, + {TF2_SLOT_MELEE,TF2_WEAPON_KATANA, "tf_weapon_katana", WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER,0,210,0,1,0}, + {TF2_SLOT_PRMRY, TF2_WEAPON_COWMANGLER, "tf_weapon_particle_cannon", WEAP_FL_KILLPIPEBOMBS | WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER, 0, 1500, 1, 2, TF2_ROCKETSPEED }, {TF2_SLOT_PRMRY,TF2_WEAPON_CROSSBOW, "tf_weapon_crossbow", WEAP_FL_PRIM_ATTACK,600,2500,1,3,0}, - {TF2_SLOT_MELEE,TF2_WEAPON_CLEAVER, "tf_weapon_cleaver", WEAP_FL_PRIM_ATTACK|WEAP_FL_MELEE|WEAP_FL_UNDERWATER,0,150,0,1,0}, - {TF2_SLOT_MELEE,TF2_WEAPON_BAT_GIFTWRAP, "tf_weapon_bat_giftwrap", WEAP_FL_PRIM_ATTACK|WEAP_FL_MELEE|WEAP_FL_UNDERWATER,0,150,0,1,0}, + {TF2_SLOT_MELEE,TF2_WEAPON_CLEAVER, "tf_weapon_cleaver", WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER,0,150,0,1,0}, + {TF2_SLOT_MELEE,TF2_WEAPON_BAT_GIFTWRAP, "tf_weapon_bat_giftwrap", WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER,0,150,0,1,0}, {TF2_SLOT_SCNDR,TF2_WEAPON_RAYGUN, "tf_weapon_raygun", WEAP_FL_PRIM_ATTACK,100,2000,2,2,0}, {0, 0, "\0", 0, 0, 0, 0, 0, 0}//signal last weapon -}; +}; + + +std::vector SYNERGYWeaps = { + + // slot, id , weapon name, flags, min dist, max dist, ammo index, preference + {2, SYN_WEAPON_PISTOL, g_szSYNWeapons[0], WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER, 0, 1000, -1, 1, 0}, + {1, SYN_WEAPON_CROWBAR, g_szSYNWeapons[1], WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER, 0, 128, -1, 1, 0}, + {1, SYN_WEAPON_LEADPIPE, g_szSYNWeapons[2], WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER, 0, 128, -1, 1, 0}, + {2, SYN_WEAPON_357, g_szSYNWeapons[3], WEAP_FL_PRIM_ATTACK, 0, 768, -1, 2, 0}, + {2, SYN_WEAPON_DESERTEAGLE, g_szSYNWeapons[4], WEAP_FL_PRIM_ATTACK, 0, 768, -1, 2, 0}, + {3, SYN_WEAPON_SMG1, g_szSYNWeapons[5], WEAP_FL_PRIM_ATTACK | WEAP_FL_SEC_ATTACK, 0, 1400, -1, 2, 0}, + {3, SYN_WEAPON_MP5K, g_szSYNWeapons[6], WEAP_FL_PRIM_ATTACK, 0, 1400, -1, 2, 0}, + {3, SYN_WEAPON_AR2, g_szSYNWeapons[7], WEAP_FL_PRIM_ATTACK | WEAP_FL_SEC_ATTACK, 0, 1400, -1, 3, 0}, + {5, SYN_WEAPON_FRAG, g_szSYNWeapons[8], WEAP_FL_GRENADE | WEAP_FL_EXPLOSIVE, 0, 180, -1, 1, 0}, + {1, SYN_WEAPON_STUNSTICK, g_szSYNWeapons[9], WEAP_FL_PRIM_ATTACK | WEAP_FL_MELEE | WEAP_FL_UNDERWATER, 0, 128, -1, 1, 0}, + {4, SYN_WEAPON_CROSSBOW, g_szSYNWeapons[10], WEAP_FL_PRIM_ATTACK | WEAP_FL_SCOPE | WEAP_FL_UNDERWATER, 0, 2000, -1, 2, 0}, + {5, SYN_WEAPON_RPG, g_szSYNWeapons[11], WEAP_FL_PROJECTILE | WEAP_FL_EXPLOSIVE | WEAP_FL_PRIM_ATTACK | WEAP_FL_UNDERWATER, 400, 2000, -1, 3, 1000.0f}, + {5, SYN_WEAPON_SLAM, g_szSYNWeapons[12], WEAP_FL_EXPLOSIVE, 0, 180, -1, 1, 0}, + {4, SYN_WEAPON_SHOTGUN, g_szSYNWeapons[13], WEAP_FL_PRIM_ATTACK, 0, 768, -1, 2, 0}, + {6, SYN_WEAPON_PHYSCANNON, g_szSYNWeapons[14], WEAP_FL_GRAVGUN | WEAP_FL_PRIM_ATTACK, 0, 768, -1, 4, 0}, + {4, SYN_WEAPON_MG1, g_szSYNWeapons[15], WEAP_FL_PRIM_ATTACK, 0, 1000, -1, 3, 0}, + {6, SYN_WEAPON_BUGBAIT, g_szSYNWeapons[16], WEAP_FL_PRIM_ATTACK | WEAP_FL_PROJECTILE, 0, 300, -1, 3, 1000.0f}, + {0, 0, "\0", 0, 0, 0, 0, 0, 0} // signal last weapon +}; + +std::vector CSSWeaps = { + + // slot, id , weapon name, flags, min dist, max dist, ammo index, preference, projectile speed + {2,CS_WEAPON_KNIFE, g_szCSWeapons[0], WEAP_FL_PRIM_ATTACK | WEAP_FL_SEC_ATTACK | WEAP_FL_UNDERWATER | WEAP_FL_MELEE | WEAP_FL_MELEE_SEC_ATT,0,128,-1,1,0}, + {1,CS_WEAPON_USP, g_szCSWeapons[1], WEAP_FL_PRIM_ATTACK,0,3072,-1,2,0}, + {1,CS_WEAPON_GLOCK, g_szCSWeapons[2], WEAP_FL_PRIM_ATTACK,0,3072,-1,2,0}, + {1,CS_WEAPON_228C, g_szCSWeapons[3], WEAP_FL_PRIM_ATTACK,0,3072,-1,2,0}, + {1,CS_WEAPON_FIVESEVEN, g_szCSWeapons[4], WEAP_FL_PRIM_ATTACK,0,3072,-1,2,0}, + {1,CS_WEAPON_ELITES, g_szCSWeapons[5], WEAP_FL_PRIM_ATTACK,0,3072,-1,2,0}, + {1,CS_WEAPON_DEAGLE, g_szCSWeapons[6], WEAP_FL_PRIM_ATTACK,0,3072,-1,2,0}, + {0,CS_WEAPON_SUPERSHOTGUN, g_szCSWeapons[7], WEAP_FL_PRIM_ATTACK,0,1024,-1,3,0}, + {0,CS_WEAPON_AUTOSHOTGUN, g_szCSWeapons[8], WEAP_FL_PRIM_ATTACK,0,1024,-1,3,0}, + {0,CS_WEAPON_TMP, g_szCSWeapons[9], WEAP_FL_PRIM_ATTACK,0,2048,-1,3,0}, + {0,CS_WEAPON_MAC10, g_szCSWeapons[10], WEAP_FL_PRIM_ATTACK,0,2048,-1,3,0}, + {0,CS_WEAPON_MP5, g_szCSWeapons[11], WEAP_FL_PRIM_ATTACK,0,2048,-1,3,0}, + {0,CS_WEAPON_UMP45, g_szCSWeapons[12], WEAP_FL_PRIM_ATTACK,0,2048,-1,3,0}, + {0,CS_WEAPON_P90, g_szCSWeapons[13], WEAP_FL_PRIM_ATTACK,0,2048,-1,3,0}, + {0,CS_WEAPON_FAMAS, g_szCSWeapons[14], WEAP_FL_PRIM_ATTACK,0,4096,-1,3,0}, + {0,CS_WEAPON_GALIL, g_szCSWeapons[15], WEAP_FL_PRIM_ATTACK,0,4096,-1,3,0}, + {0,CS_WEAPON_AK47, g_szCSWeapons[16], WEAP_FL_PRIM_ATTACK,0,4096,-1,3,0}, + {0,CS_WEAPON_M4A1, g_szCSWeapons[17], WEAP_FL_PRIM_ATTACK,0,4096,-1,3,0}, + {0,CS_WEAPON_AUG, g_szCSWeapons[18], WEAP_FL_PRIM_ATTACK | WEAP_FL_SCOPE | WEAP_FL_ZOOMABLE,0,4096,-1,3,0}, + {0,CS_WEAPON_SG552, g_szCSWeapons[19], WEAP_FL_PRIM_ATTACK | WEAP_FL_SCOPE | WEAP_FL_ZOOMABLE,0,4096,-1,3,0}, + {0,CS_WEAPON_SCOUT, g_szCSWeapons[20], WEAP_FL_PRIM_ATTACK | WEAP_FL_SCOPE | WEAP_FL_ZOOMABLE,512,4096,-1,3,0}, + {0,CS_WEAPON_AWP, g_szCSWeapons[21], WEAP_FL_PRIM_ATTACK | WEAP_FL_SCOPE | WEAP_FL_ZOOMABLE,512,4096,-1,3,0}, + {0,CS_WEAPON_SG550, g_szCSWeapons[22], WEAP_FL_PRIM_ATTACK | WEAP_FL_SCOPE | WEAP_FL_ZOOMABLE,512,4096,-1,3,0}, + {0,CS_WEAPON_G3SG1, g_szCSWeapons[23], WEAP_FL_PRIM_ATTACK | WEAP_FL_SCOPE | WEAP_FL_ZOOMABLE,512,4096,-1,3,0}, + {0,CS_WEAPON_M249, g_szCSWeapons[24], WEAP_FL_PRIM_ATTACK,0,2048,-1,3,0}, + {3,CS_WEAPON_HE_GRENADE, g_szCSWeapons[25], WEAP_FL_PRIM_ATTACK | WEAP_FL_PROJECTILE | WEAP_FL_EXPLOSIVE | WEAP_FL_GRENADE,0,2048,-1,1,0}, + {3,CS_WEAPON_FLASH_GRENADE, g_szCSWeapons[26], WEAP_FL_PRIM_ATTACK | WEAP_FL_PROJECTILE | WEAP_FL_GRENADE,0,2048,-1,1,0}, + {3,CS_WEAPON_SMOKE_GRENADE, g_szCSWeapons[27], WEAP_FL_PRIM_ATTACK | WEAP_FL_PROJECTILE | WEAP_FL_GRENADE,0,2048,-1,1,0}, + {4,CS_WEAPON_C4, g_szCSWeapons[28], WEAP_FL_PRIM_ATTACK | WEAP_FL_SPECIAL | WEAP_FL_HOLDATTACK,0,1024,-1,1,0}, + { 0, 0, "\0", 0, 0, 0, 0, 0, 0 }//signal last weapon +}; -bool CBotWeapon :: needToReload (CBot *pBot) -{ - if ( m_iClip1 ) +bool CBotWeapon::needToReload(const CBot* pBot) const +{ + if (m_iClip1) { - return (*m_iClip1 == 0) && (getAmmo(pBot)>0); + return *m_iClip1 == 0 && getAmmo(pBot) > 0; } return false; } // static init (all weapons in game) -vector CWeapons :: m_theWeapons; +std::vector CWeapons::m_theWeapons; -int CBotWeapon :: getAmmo (CBot *pBot, int type ) +int CBotWeapon::getAmmo(const CBot* pBot, const int type) const { - if ( type == AMMO_PRIM ) - return pBot->getAmmo(m_pWeaponInfo->getAmmoIndex1()); - - if ( type == AMMO_SEC ) - return pBot->getAmmo(m_pWeaponInfo->getAmmoIndex2()); + if (type == AMMO_PRIM) + return pBot->getAmmo(static_cast(m_pWeaponInfo->getAmmoIndex1())); + if (type == AMMO_SEC) + return pBot->getAmmo(static_cast(m_pWeaponInfo->getAmmoIndex2())); return 0; } - -bool CBotWeapons::hasExplosives( void ) +// Example of using range-based for loop and nullptr +bool CBotWeapons::hasExplosives() const { - CBotWeapon *pWeapon; - - for ( int i = 0; i < MAX_WEAPONS; i ++ ) + for (const CBotWeapon& weapon : m_theWeapons) { - pWeapon = &(m_theWeapons[i]); // find weapon info from weapon id - if ( pWeapon->hasWeapon() && pWeapon->isExplosive() ) + if (weapon.hasWeapon() && weapon.isExplosive() && weapon.getAmmo(m_pBot) > 1) { - if ( pWeapon->getAmmo(m_pBot) > 1 ) - return true; + return true; } } return false; } - -bool CBotWeapons::hasWeapon(int id) +bool CBotWeapons::hasWeapon(int id) const { - for (int i = 0; i < MAX_WEAPONS; i++) - { - if (m_theWeapons[i].getWeaponInfo() == NULL) - continue; - if (m_theWeapons[i].hasWeapon() == false) - continue; - if (m_theWeapons[i].getID() == id) - // find weapon info from weapon id - { - return true; - } - } - return false; + return std::any_of(std::begin(m_theWeapons), std::end(m_theWeapons), [id](const CBotWeapon& weapon) { + return weapon.getWeaponInfo() != nullptr && weapon.hasWeapon() && weapon.getID() == id; + }); } + // Bot Weapons -CBotWeapons::CBotWeapons(CBot *pBot) +CBotWeapons::CBotWeapons(CBot* pBot) { m_pBot = pBot; clearWeapons(); @@ -278,47 +424,44 @@ CBotWeapons::CBotWeapons(CBot *pBot) m_iWeaponsSignature = 0x0; } -edict_t *CWeapons :: findWeapon ( edict_t *pPlayer, const char *pszWeaponName ) +edict_t* CWeapons::findWeapon(edict_t* pPlayer, const char* szWeaponName) { - register unsigned short int j; - CBaseHandle *m_Weapons = CClassInterface::getWeaponList(pPlayer); - edict_t *pWeapon; - CBaseHandle *m_Weapon_iter = m_Weapons; + const CBaseHandle* m_Weapons = CClassInterface::getWeaponList(pPlayer); + const CBaseHandle* m_Weapon_iter = m_Weapons; // loop through the weapons array and see if it is in the CBaseCombatCharacter - pWeapon = NULL; - - for ( j = 0; j < MAX_WEAPONS; j ++ ) + for (unsigned short int j = 0; j < MAX_WEAPONS; j++) { - pWeapon = INDEXENT(m_Weapon_iter->GetEntryIndex()); + edict_t* pWeapon = INDEXENT(m_Weapon_iter->GetEntryIndex()); - if ( strcmp(pWeapon->GetClassName(),pszWeaponName) == 0 ) + // TODO get familiar with validity of handles / edicts + if (pWeapon && !pWeapon->IsFree() && std::strcmp(pWeapon->GetClassName(), szWeaponName) == 0) return pWeapon; m_Weapon_iter++; } - return NULL; + return nullptr; } - -bool CBotWeapons::update(bool bOverrideAllFromEngine) +bool CBotWeapons::update(const bool bOverrideAllFromEngine) { - // create mask of weapons data - short int i = 0; - unsigned short int iWeaponsSignature = 0x0; // check sum of weapons - edict_t *pWeapon; - CBaseHandle *m_Weapons = CClassInterface::getWeaponList(m_pBot->getEdict()); - CBaseHandle *m_Weapon_iter; + std::uintptr_t iWeaponsSignature = 0x0; // check sum of weapons + edict_t* pWeapon; - m_Weapon_iter = m_Weapons; + const CBaseHandle* m_Weapons = CClassInterface::getWeaponList(m_pBot->getEdict()); + const CBaseHandle* m_Weapon_iter = m_Weapons; - for (i = 0; i < MAX_WEAPONS; i++) + for (short int i = 0; i < MAX_WEAPONS; i++) { // create a 'hash' of current weapons - pWeapon = (m_Weapon_iter == NULL) ? NULL : INDEXENT(m_Weapon_iter->GetEntryIndex()); - iWeaponsSignature += ((unsigned int)pWeapon) + ((pWeapon == NULL) ? 0 : (unsigned int)CClassInterface::getWeaponState(pWeapon)); - m_Weapon_iter++; + pWeapon = m_Weapon_iter == nullptr ? nullptr : INDEXENT(m_Weapon_iter->GetEntryIndex()); + iWeaponsSignature += reinterpret_cast(pWeapon) + + static_cast(pWeapon == nullptr ? 0 : static_cast(CClassInterface::getWeaponState(pWeapon))); + + if (m_Weapon_iter != nullptr) { + m_Weapon_iter++; + } } // if weapons have changed this will be different @@ -326,21 +469,13 @@ bool CBotWeapons::update(bool bOverrideAllFromEngine) { this->clearWeapons(); - int iWeaponState; - register unsigned short int i; - bool bFound; - - const char *pszClassname; - - CBaseHandle *m_Weapons = CClassInterface::getWeaponList(m_pBot->getEdict()); - CBotWeapon *m_BotWeapon_iter = m_theWeapons; + CBotWeapon* m_BotWeapon_iter = m_theWeapons; //`m_BotWeapon_iter` not used? [APG]RoboCop[CL] // loop through the weapons array and see if it is in the CBaseCombatCharacter - for (i = 0; i < MAX_WEAPONS; i++) + for (unsigned short int i = 0; i < MAX_WEAPONS; i++) { m_Weapon_iter = &m_Weapons[i]; - iWeaponState = 0; - bFound = false; + bool bFound = false; //`bFound` not used? [APG]RoboCop[CL] pWeapon = INDEXENT(m_Weapon_iter->GetEntryIndex()); @@ -349,17 +484,17 @@ bool CBotWeapons::update(bool bOverrideAllFromEngine) continue; } - iWeaponState = CClassInterface::getWeaponState(pWeapon); + const int iWeaponState = CClassInterface::getWeaponState(pWeapon); - pszClassname = pWeapon->GetClassName(); + const char* pszClassname = pWeapon->GetClassName(); - CWeapon *pWeaponInfo = CWeapons::getWeapon(pszClassname); + CWeapon* pWeaponInfo = CWeapons::getWeapon(pszClassname); - if (pWeaponInfo != NULL) + if (pWeaponInfo != nullptr) { if (iWeaponState != WEAPON_NOT_CARRIED) { - CBotWeapon *pAdded = addWeapon(pWeaponInfo, i, pWeapon, bOverrideAllFromEngine); + CBotWeapon* pAdded = addWeapon(pWeaponInfo, i, pWeapon, bOverrideAllFromEngine); pAdded->setHasWeapon(true); } } @@ -391,7 +526,7 @@ bool CBotWeapons ::update ( bool bOverrideAllFromEngine ) { // create a 'hash' of current weapons pWeapon = (m_Weapon_iter==NULL) ? NULL : INDEXENT(m_Weapon_iter->GetEntryIndex()); - iWeaponsSignature += ((unsigned int)pWeapon) + ((pWeapon == NULL) ? 0 : (unsigned int)CClassInterface::getWeaponState(pWeapon)); + iWeaponsSignature += ((unsigned)pWeapon) + ((pWeapon == NULL) ? 0 : (unsigned)CClassInterface::getWeaponState(pWeapon)); m_Weapon_iter++; } @@ -399,7 +534,7 @@ bool CBotWeapons ::update ( bool bOverrideAllFromEngine ) if ( iWeaponsSignature != m_iWeaponsSignature ) // m_fUpdateWeaponsTime < engine->Time() ) { int iWeaponState; - register unsigned short int i,j; + unsigned short int i,j; bool bFound; CBaseHandle *m_Weapons = CClassInterface::getWeaponList(m_pBot->getEdict()); @@ -458,77 +593,77 @@ bool CBotWeapons ::update ( bool bOverrideAllFromEngine ) return false; }*/ -CBotWeapon *CBotWeapons :: getBestWeapon ( edict_t *pEnemy, bool bAllowMelee, bool bAllowMeleeFallback, bool bMeleeOnly, bool bExplosivesOnly, bool bIgnorePrimaryMinimum ) +CBotWeapon* CBotWeapons::getBestWeapon(edict_t* pEnemy, const bool bAllowMelee, const bool bAllowMeleeFallback, const bool bMeleeOnly, const bool bExplosivesOnly, const bool bIgnorePrimaryMinimum) { - CBotWeapon *m_theBestWeapon = NULL; - CBotWeapon *m_FallbackMelee = NULL; + CBotWeapon* m_theBestWeapon = nullptr; + CBotWeapon* m_FallbackMelee = nullptr; int iBestPreference = 0; Vector vEnemyOrigin; - if ( pEnemy ) + if (pEnemy) vEnemyOrigin = CBotGlobals::entityOrigin(pEnemy); else vEnemyOrigin = m_pBot->getOrigin(); float flDist = 0; - if ( pEnemy ) + if (pEnemy) flDist = m_pBot->distanceFrom(vEnemyOrigin); - for ( unsigned int i = 0; i < MAX_WEAPONS; i ++ ) + for (CBotWeapon& m_theWeapon : m_theWeapons) { - CBotWeapon *pWeapon = &(m_theWeapons[i]); - - if ( !pWeapon ) - continue; + CBotWeapon* pWeapon = &m_theWeapon; - if ( !pWeapon->hasWeapon() ) + if (!pWeapon->hasWeapon()) continue; - if ( bMeleeOnly && !pWeapon->isMelee() ) + if (bMeleeOnly && !pWeapon->isMelee()) continue; - if ( !bAllowMelee && pWeapon->isMelee() ) + if (!bAllowMelee && pWeapon->isMelee()) continue; - if ( bExplosivesOnly && !pWeapon->isExplosive() ) + if (bExplosivesOnly && !pWeapon->isExplosive()) continue; - if ( !pWeapon->isMelee() || pWeapon->isSpecial() ) + if (!pWeapon->isMelee() || pWeapon->isSpecial()) { - if ( pWeapon->outOfAmmo(m_pBot) ) + if (pWeapon->outOfAmmo(m_pBot)) continue; } - if ( !pWeapon->canAttack() ) + if (!pWeapon->canAttack()) continue; - if ( m_pBot->isUnderWater() && !pWeapon->canUseUnderWater() ) + if (m_pBot->isUnderWater() && !pWeapon->canUseUnderWater()) continue; - if ( !pWeapon->primaryInRange(flDist) ) + if (!pWeapon->primaryInRange(flDist)) { - if ( pWeapon->isMelee() && !pWeapon->isSpecial() ) + if (pWeapon->isMelee() && !pWeapon->isSpecial()) m_FallbackMelee = pWeapon; - if ( !pWeapon->isExplosive() || !bIgnorePrimaryMinimum ) + if (!pWeapon->isExplosive() || !bIgnorePrimaryMinimum) continue; // ignore explosive range if I'm invincible } - if ( pWeapon->getPreference() > iBestPreference ) + if (pWeapon->getPreference() > iBestPreference) { iBestPreference = pWeapon->getPreference(); m_theBestWeapon = pWeapon; } } - if ( bMeleeOnly || (bAllowMeleeFallback && ((m_theBestWeapon == NULL) && (flDist < 400.0f) && (fabs(vEnemyOrigin.z-m_pBot->getOrigin().z)getOrigin().z) < static_cast(BOT_JUMP_HEIGHT)))) + { m_theBestWeapon = m_FallbackMelee; + } return m_theBestWeapon; } -void CBotWeapon::setWeaponEntity(edict_t *pent, bool bOverrideAmmoTypes) +void CBotWeapon::setWeaponEntity(edict_t* pent, const bool bOverrideAmmoTypes) { m_pEnt = pent; m_iClip1 = CClassInterface::getWeaponClip1Pointer(pent); @@ -544,23 +679,17 @@ void CBotWeapon::setWeaponEntity(edict_t *pent, bool bOverrideAmmoTypes) setWeaponIndex(ENTINDEX(m_pEnt)); } - -CBotWeapon *CBotWeapons::addWeapon(CWeapon *pWeaponInfo, int iId, edict_t *pent, bool bOverrideAll) +CBotWeapon* CBotWeapons::addWeapon(CWeapon* pWeaponInfo, const int iId, edict_t* pent, const bool bOverrideAll) { - register int i = 0; - Vector origin; - const char *classname; - edict_t *pEnt = NULL; - m_theWeapons[iId].setHasWeapon(true); m_theWeapons[iId].setWeapon(pWeaponInfo); if (!m_theWeapons[iId].getWeaponInfo()) - return NULL; + return nullptr; - classname = pWeaponInfo->getWeaponName(); + const char* classname = pWeaponInfo->getWeaponName(); - origin = m_pBot->getOrigin(); + const Vector origin = m_pBot->getOrigin(); // if entity comes from the engine use the entity if (pent) @@ -569,15 +698,15 @@ CBotWeapon *CBotWeapons::addWeapon(CWeapon *pWeaponInfo, int iId, edict_t *pent, } else // find the weapon entity { - for (i = (gpGlobals->maxClients + 1); i <= gpGlobals->maxEntities; i++) + for (int i = gpGlobals->maxClients + 1; i <= gpGlobals->maxEntities; i++) { - pEnt = INDEXENT(i); + edict_t* pEnt = INDEXENT(i); if (pEnt && CBotGlobals::entityIsValid(pEnt)) { if (CBotGlobals::entityOrigin(pEnt) == origin) { - if (strcmp(pEnt->GetClassName(), classname) == 0) + if (std::strcmp(pEnt->GetClassName(), classname) == 0) { m_theWeapons[iId].setWeaponEntity(pEnt, bOverrideAll);// .setWeaponIndex(ENTINDEX(pEnt)); @@ -589,12 +718,11 @@ CBotWeapon *CBotWeapons::addWeapon(CWeapon *pWeaponInfo, int iId, edict_t *pent, } return &m_theWeapons[iId]; - } /* void CBotWeapons :: addWeapon ( int iId, edict_t *pent, bool bOverrideAll ) { -register int i = 0; +int i = 0; Vector origin; const char *classname; CWeapon *pWeapon; @@ -636,166 +764,151 @@ return; } } } - }*/ -CBotWeapon *CBotWeapons :: getWeapon ( CWeapon *pWeapon ) + +CBotWeapon* CBotWeapons::getWeapon(const CWeapon* pWeapon) { - for ( register unsigned int i = 0; i < MAX_WEAPONS; i ++ ) + for (CBotWeapon& m_theWeapon : m_theWeapons) { - if ( m_theWeapons[i].getWeaponInfo() == pWeapon ) - return &(m_theWeapons[i]); + if (m_theWeapon.getWeaponInfo() == pWeapon) + return &m_theWeapon; } - return NULL; + return nullptr; } -CBotWeapon *CBotWeapons :: getCurrentWeaponInSlot ( int iSlot ) +CBotWeapon* CBotWeapons::getCurrentWeaponInSlot(const int iSlot) { - for ( register unsigned int i = 0; i < MAX_WEAPONS; i ++ ) + for (CBotWeapon& m_theWeapon : m_theWeapons) { - if ( m_theWeapons[i].hasWeapon() && m_theWeapons[i].getWeaponInfo() && (m_theWeapons[i].getWeaponInfo()->getSlot()==iSlot) ) - return &(m_theWeapons[i]); + if (m_theWeapon.hasWeapon() && m_theWeapon.getWeaponInfo() && m_theWeapon.getWeaponInfo()->getSlot() == iSlot) + return &m_theWeapon; } - return NULL; + return nullptr; } -const char *szWeaponFlags[] = { - "primary_attack" , - "secondary_attack" , - "explosive" , - "melee" , - "underwater" , - "hold_attack" , - "special" , - "can_kill_pipes" , - "can_deflect_rockets" , - "is_grav_gun" , - "has_explosive_secondary" , - "is_zoomable" , - "is_deployable_dods" , - "has_melee_secondary" , - "has_fire_select_mode_dods" , - "cant_be_fired_unzoomed_undeployed_dods" , - "is_grenade" , - "has_high_recoil_dods" , - "has_scope" , - "weapon_fires_projectile" , - "\0" +constexpr std::array g_szWeaponFlags = { + "primary_attack", + "secondary_attack", + "explosive", + "melee", + "underwater", + "hold_attack", + "special", + "can_kill_pipes", + "can_deflect_rockets", + "is_grav_gun", + "has_explosive_secondary", + "is_zoomable", + "is_deployable_dods", + "has_melee_secondary", + "has_fire_select_mode_dods", + "cant_be_fired_unzoomed_undeployed_dods", + "is_grenade", + "has_high_recoil_dods", + "has_scope", + "weapon_fires_projectile", + "\0" }; -void CWeapons::loadWeapons(const char *szWeaponListName, WeaponsData_t *pDefault) -{ - if ((szWeaponListName != NULL) && (szWeaponListName[0] != 0)) - { - KeyValues *kv = new KeyValues("Weapons"); - char szFilename[1024]; - - CBotGlobals::buildFileName(szFilename, "weapons", BOT_CONFIG_FOLDER, "ini", false); - - if (kv) - { - if (kv->LoadFromFile(filesystem, szFilename, NULL)) - { - kv = kv->FindKey(szWeaponListName); - - if (kv) - { - kv = kv->GetFirstSubKey(); - - if (0) - kv = kv->GetFirstTrueSubKey(); - - while (kv != NULL) - { - WeaponsData_t newWeapon; - - memset(&newWeapon, 0, sizeof(WeaponsData_t)); - - const char *szKeyName = kv->GetName(); - - char lowered[64]; - - strncpy(lowered, szKeyName, 63); - lowered[63] = 0; - - __strlow(lowered); +std::unordered_map createWeaponFlagMap() { + std::unordered_map flagMap; + for (std::size_t i = 0; i < g_szWeaponFlags.size(); ++i) { + flagMap[g_szWeaponFlags[i]] = 1 << i; + } + return flagMap; +} - newWeapon.szWeaponName = CStrings::getString(lowered); - newWeapon.iId = kv->GetInt("id"); - newWeapon.iSlot = kv->GetInt("slot"); - newWeapon.minPrimDist = kv->GetFloat("minPrimDist"); - newWeapon.maxPrimDist = kv->GetFloat("maxPrimDist"); - newWeapon.m_fProjSpeed = kv->GetFloat("m_fProjSpeed"); - newWeapon.m_iAmmoIndex = kv->GetInt("m_iAmmoIndex"); - newWeapon.m_iPreference = kv->GetInt("m_iPreference"); +const std::unordered_map g_weaponFlagMap = createWeaponFlagMap(); - KeyValues *flags = kv->FindKey("flags"); +void CWeapons::loadWeapons(const char* szWeaponListName, const WeaponsData_t* pDefault) { + if (szWeaponListName && szWeaponListName[0] != '\0') { + auto keyValuesDeleter = [](KeyValues* kv) { + if (kv) { + kv->deleteThis(); + } + }; - if (flags) - { - int i = 0; + const std::unique_ptr kv(new KeyValues("Weapons"), keyValuesDeleter); + char szFilename[1024]; - while (szWeaponFlags[i][0] != '\0') - { - if (flags->FindKey(szWeaponFlags[i]) && (flags->GetInt(szWeaponFlags[i]) == 1)) - newWeapon.m_iFlags |= (1 << i); + CBotGlobals::buildFileName(szFilename, "weapons", BOT_CONFIG_FOLDER, "ini", false); - i++; + if (kv && kv->LoadFromFile(filesystem, szFilename, nullptr)) { + if (KeyValues* weaponListKey = kv->FindKey(szWeaponListName)) { + + for (KeyValues* subKey = weaponListKey->GetFirstSubKey(); subKey != nullptr; subKey = subKey->GetNextTrueSubKey()) { + WeaponsData_t newWeapon; + std::memset(&newWeapon, 0, sizeof(WeaponsData_t)); + + if (const char* szKeyName = subKey->GetName()) { + std::string lowered(szKeyName); + std::transform(lowered.begin(), lowered.end(), lowered.begin(), ::tolower); + + newWeapon.szWeaponName = CStrings::getString(lowered.c_str()); + newWeapon.iId = subKey->GetInt("id"); + newWeapon.iSlot = subKey->GetInt("slot"); + newWeapon.minPrimDist = subKey->GetFloat("minPrimDist"); + newWeapon.maxPrimDist = subKey->GetFloat("maxPrimDist"); + newWeapon.m_fProjSpeed = subKey->GetFloat("m_fProjSpeed"); + newWeapon.m_iAmmoIndex = subKey->GetInt("m_iAmmoIndex"); + newWeapon.m_iPreference = subKey->GetInt("m_iPreference"); + + if (KeyValues* flags = subKey->FindKey("flags")) { + for (const auto& flag : g_weaponFlagMap) { + if (flags->GetInt(flag.first.c_str(), 0) == 1) { + newWeapon.m_iFlags |= flag.second; + } } } addWeapon(new CWeapon(&newWeapon)); - - kv = kv->GetNextTrueSubKey(); + } + else { + logger->Log(LogLevel::ERROR, "Error: szKeyName is null.\n"); } } - } - - - kv->deleteThis(); - + } + else { + logger->Log(LogLevel::ERROR, "Error: Failed to allocate KeyValues.\n"); } } - if (pDefault!=NULL) - { - // No weapons from INI file then add default - if (m_theWeapons.size() == 0) - { - while (pDefault->szWeaponName[0] != '\0') - { + if (pDefault) { + if (m_theWeapons.empty()) { + while (pDefault->szWeaponName[0] != '\0') { addWeapon(new CWeapon(pDefault)); - pDefault++; + ++pDefault; } } } } - void CBotWeapons::clearWeapons() { - for (register unsigned short i = 0; i < MAX_WEAPONS; i++) + for (CBotWeapon& m_theWeapon : m_theWeapons) { - memset(&m_theWeapons[i], 0, sizeof(CBotWeapon)); - //m_theWeapons[i].setHasWeapon(false); + m_theWeapon = CBotWeapon(); // Assign a default-constructed instance [APG]RoboCop[CL] + // Alternatively, call a reset or clear method if available + // m_theWeapon.reset(); } } // returns weapon with highest priority even if no ammo -CBotWeapon *CBotWeapons :: getPrimaryWeapon () +CBotWeapon* CBotWeapons::getPrimaryWeapon() { - CBotWeapon *pBest = NULL; + CBotWeapon* pBest = nullptr; - for ( register unsigned short i = 0; i < MAX_WEAPONS; i ++ ) + for (CBotWeapon& m_theWeapon : m_theWeapons) { - CBotWeapon *pWeap = &(m_theWeapons[i]); + CBotWeapon* pWeap = &m_theWeapon; - if ( !pWeap->hasWeapon() ) + if (!pWeap->hasWeapon()) continue; - if ( (pBest == NULL) || (pBest->getPreference() < pWeap->getPreference() ) ) + if (pBest == nullptr || pBest->getPreference() < pWeap->getPreference()) { pBest = pWeap; } @@ -804,29 +917,24 @@ CBotWeapon *CBotWeapons :: getPrimaryWeapon () return pBest; } - -CBotWeapon *CBotWeapons::getActiveWeapon(const char *szWeaponName, edict_t *pWeaponUpdate, bool bOverrideAmmoTypes) +CBotWeapon* CBotWeapons::getActiveWeapon(const char* szWeaponName, edict_t* pWeaponUpdate, const bool bOverrideAmmoTypes) { - CBotWeapon *toReturn = NULL; + CBotWeapon* toReturn = nullptr; if (szWeaponName && *szWeaponName) { - CWeapon *pWeapon = CWeapons::getWeapon(szWeaponName); - - if (pWeapon) + if (const CWeapon* pWeapon = CWeapons::getWeapon(szWeaponName)) { - register unsigned short int i; - - for (i = 0; i < MAX_WEAPONS; i++) + for (CBotWeapon& m_theWeapon : m_theWeapons) { - CWeapon *p = m_theWeapons[i].getWeaponInfo(); + const CWeapon* p = m_theWeapon.getWeaponInfo(); if (!p) continue; - if (strcmp(p->getWeaponName(), szWeaponName) == 0) + if (std::strcmp(p->getWeaponName(), szWeaponName) == 0) { - toReturn = &m_theWeapons[i]; + toReturn = &m_theWeapon; break; } } @@ -849,17 +957,17 @@ bool CBotWeaponGravGun ::outOfAmmo (CBot *pBot) return true; } */ -bool CBotWeapon :: outOfAmmo(CBot *pBot) +bool CBotWeapon::outOfAmmo(const CBot* pBot) const { - if ( m_pWeaponInfo->isGravGun() && m_pEnt ) - return (CClassInterface::gravityGunObject(m_pEnt) == NULL); + if (m_pWeaponInfo && m_pWeaponInfo->isGravGun() && m_pEnt) + return CClassInterface::gravityGunObject(m_pEnt) == nullptr; // if I have something in my clip now // I am okay, otherwise return ammo in list - if ( m_iClip1 && (*m_iClip1 > 0) ) + if (m_iClip1 && *m_iClip1 > 0) return false; - return getAmmo(pBot)==0; + return getAmmo(pBot) == 0; } /* bool CBotWeapon :: needToReload(CBot *pBot) @@ -872,118 +980,119 @@ bool CBotWeapon :: needToReload(CBot *pBot) class IWeaponFunc { public: - virtual void execute ( CWeapon *pWeapon ) = 0; + virtual ~IWeaponFunc() = default; + virtual void execute(CWeapon* pWeapon) = 0; }; class CGetWeapID : public IWeaponFunc { public: - CGetWeapID ( int iId ) + CGetWeapID(const int iId) { m_iId = iId; - m_pFound = NULL; + m_pFound = nullptr; } - void execute ( CWeapon *pWeapon ) + void execute(CWeapon* pWeapon) override { - if ( m_iId == pWeapon->getID() ) + if (m_iId == pWeapon->getID()) m_pFound = pWeapon; } - CWeapon *get () + CWeapon* get() const { return m_pFound; } private: int m_iId; - CWeapon *m_pFound; + CWeapon* m_pFound; }; class CGetWeapCName : public IWeaponFunc { public: - CGetWeapCName ( const char *szWeapon ) + CGetWeapCName(const char* szWeapon) { - m_pFound = NULL; - m_szWeapon = szWeapon; + m_pFound = nullptr; + m_szWeapon = szWeapon; } - void execute ( CWeapon *pWeapon ) + void execute(CWeapon* pWeapon) override { - if ( pWeapon->isWeaponName(m_szWeapon) ) + if (pWeapon->isWeaponName(m_szWeapon)) m_pFound = pWeapon; } - CWeapon *get () + CWeapon* get() const { return m_pFound; } private: - const char *m_szWeapon; - CWeapon *m_pFound; + const char* m_szWeapon; + CWeapon* m_pFound; }; class CGetWeapShortName : public IWeaponFunc { public: - CGetWeapShortName ( const char *szWeapon ) + CGetWeapShortName(const char* szWeapon) { - m_pFound = NULL; - m_szWeapon = szWeapon; + m_pFound = nullptr; + m_szWeapon = szWeapon; } - void execute ( CWeapon *pWeapon ) + void execute(CWeapon* pWeapon) override { - if ( pWeapon->isShortWeaponName(m_szWeapon) ) + if (pWeapon->isShortWeaponName(m_szWeapon)) m_pFound = pWeapon; } - CWeapon *get () + CWeapon* get() const { return m_pFound; } private: - const char *m_szWeapon; - CWeapon *m_pFound; + const char* m_szWeapon; + CWeapon* m_pFound; }; -CWeapon *CWeapons :: getWeapon ( const int iId ) +CWeapon* CWeapons::getWeapon(const int iId) { CGetWeapID pFunc = CGetWeapID(iId); eachWeapon(&pFunc); return pFunc.get(); } -CWeapon *CWeapons :: getWeapon ( const char *szWeapon ) +CWeapon* CWeapons::getWeapon(const char* szWeapon) { CGetWeapCName pFunc = CGetWeapCName(szWeapon); eachWeapon(&pFunc); return pFunc.get(); } -CWeapon *CWeapons :: getWeaponByShortName ( const char *szWeapon ) +CWeapon* CWeapons::getWeaponByShortName(const char* szWeapon) { CGetWeapShortName pFunc = CGetWeapShortName(szWeapon); eachWeapon(&pFunc); return pFunc.get(); } -void CWeapons :: eachWeapon ( IWeaponFunc *pFunc ) +void CWeapons::eachWeapon(IWeaponFunc* pFunc) { - for ( unsigned int i = 0; i < m_theWeapons.size(); i ++ ) + for (CWeapon* const& m_theWeapon : m_theWeapons) { - pFunc->execute(m_theWeapons[i]); + pFunc->execute(m_theWeapon); } } -void CWeapons :: freeMemory () +void CWeapons::freeMemory() { - for ( unsigned int i = 0; i < m_theWeapons.size(); i ++ ) + for (CWeapon*& m_theWeapon : m_theWeapons) { - delete m_theWeapons[i]; - m_theWeapons[i] = NULL; + delete m_theWeapon; + m_theWeapon = nullptr; } m_theWeapons.clear(); -} +} \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_weapons.h b/utils/RCBot2_meta/bot_weapons.h index e88674420..849e325b2 100644 --- a/utils/RCBot2_meta/bot_weapons.h +++ b/utils/RCBot2_meta/bot_weapons.h @@ -32,24 +32,21 @@ #define __BOT_WEAPONS_H__ #include -using namespace std; +#include - - -extern const char *g_szTF2Weapons[]; +extern const char* g_szTF2Weapons[]; #include "shareddefs.h" class CBot; - extern int m_TF2AmmoIndices[]; typedef struct { int iSlot; int iId; - const char *szWeaponName; + const char* szWeaponName; int m_iFlags; float minPrimDist; float maxPrimDist; @@ -58,15 +55,15 @@ typedef struct float m_fProjSpeed; }WeaponsData_t; -enum +enum : std::uint8_t { TF2_WEAPON_BAT = 0, TF2_WEAPON_BOTTLE, //1 TF2_WEAPON_FIREAXE, //2 - TF2_WEAPON_CLUB, //3 - TF2_WEAPON_KNIFE, //4 - TF2_WEAPON_FISTS, //5 - TF2_WEAPON_SHOVEL, //6 + TF2_WEAPON_CLUB, //3 + TF2_WEAPON_KNIFE, //4 + TF2_WEAPON_FISTS, //5 + TF2_WEAPON_SHOVEL, //6 TF2_WEAPON_WRENCH,//7 TF2_WEAPON_BONESAW,//8 TF2_WEAPON_SHOTGUN_PRIMARY,//9 @@ -108,10 +105,11 @@ enum TF2_WEAPON_CLEAVER, TF2_WEAPON_BAT_GIFTWRAP, TF2_WEAPON_RAYGUN, + TF2_WEAPON_SNIPERRIFLE_DECAP, TF2_WEAPON_MAX }; /* -enum +enum { TF2_WEAPON_BAT = 0, TF2_WEAPON_BONESAW, @@ -151,7 +149,7 @@ enum TF2_WEAPON_MAX }; */ -enum +enum : std::uint8_t { HL2DM_WEAPON_PISTOL = 0, HL2DM_WEAPON_CROWBAR, @@ -162,13 +160,33 @@ enum HL2DM_WEAPON_STUNSTICK, HL2DM_WEAPON_CROSSBOW, HL2DM_WEAPON_RPG, - HL2DM_WEAPON_SLAM, + HL2DM_WEAPON_SLAM, HL2DM_WEAPON_SHOTGUN, HL2DM_WEAPON_PHYSCANNON, HL2DM_WEAPON_MAX }; -enum +//TODO: Add Black Mesa weapons support [APG]RoboCop[CL] +/*enum : std::uint8_t +{ + BMS_WEAPON_GLOCK = 0, + BMS_WEAPON_CROWBAR, + BMS_WEAPON_PYTHON, + BMS_WEAPON_MP5, + BMS_WEAPON_CHAINGUN, + BMS_WEAPON_CROSSBOW, + BMS_WEAPON_SHOTGUN, + BMS_WEAPON_RPG, + BMS_WEAPON_TAU, + BMS_WEAPON_GLUON, + BMS_WEAPON_HORNETGUN, + BMS_WEAPON_HANDGRENADE, + BMS_WEAPON_TRIPMINE, + BMS_WEAPON_SATCHEL, + BMS_WEAPON_SNARK +};*/ + +enum : std::uint8_t { DOD_WEAPON_AMERKNIFE = 0, DOD_WEAPON_SPADE, @@ -191,44 +209,105 @@ enum DOD_WEAPON_RIFLEGREN_US, DOD_WEAPON_RIFLEGREN_GER, DOD_WEAPON_FRAG_US, - DOD_WEAPON_FRAG_GER, + DOD_WEAPON_FRAG_GER, DOD_WEAPON_SMOKE_US, DOD_WEAPON_SMOKE_GER, DOD_WEAPON_BOMB, DOD_WEAPON_MAX }; +enum : std::uint8_t +{ + SYN_WEAPON_PISTOL = 0, + SYN_WEAPON_CROWBAR, + SYN_WEAPON_LEADPIPE, + SYN_WEAPON_357, + SYN_WEAPON_DESERTEAGLE, + SYN_WEAPON_SMG1, + SYN_WEAPON_MP5K, + SYN_WEAPON_AR2, + SYN_WEAPON_FRAG, + SYN_WEAPON_STUNSTICK, + SYN_WEAPON_CROSSBOW, + SYN_WEAPON_RPG, + SYN_WEAPON_SLAM, + SYN_WEAPON_SHOTGUN, + SYN_WEAPON_PHYSCANNON, + SYN_WEAPON_MG1, + SYN_WEAPON_BUGBAIT, + SYN_WEAPON_MAX +}; + +enum : std::uint8_t +{ + CS_WEAPON_KNIFE = 0, + CS_WEAPON_USP, + CS_WEAPON_GLOCK, + CS_WEAPON_228C, + CS_WEAPON_FIVESEVEN, + CS_WEAPON_ELITES, + CS_WEAPON_DEAGLE, + CS_WEAPON_SUPERSHOTGUN, // M3 pump action shotgun + CS_WEAPON_AUTOSHOTGUN, // XM1014 auto shotgun + CS_WEAPON_TMP, + CS_WEAPON_MAC10, + CS_WEAPON_MP5, + CS_WEAPON_UMP45, + CS_WEAPON_P90, + CS_WEAPON_FAMAS, + CS_WEAPON_GALIL, + CS_WEAPON_AK47, + CS_WEAPON_M4A1, + CS_WEAPON_AUG, + CS_WEAPON_SG552, // Krieg 552 (T Rifle) + CS_WEAPON_SCOUT, + CS_WEAPON_AWP, + CS_WEAPON_SG550, // CT Auto Sniper + CS_WEAPON_G3SG1, // T Auto Sniper + CS_WEAPON_M249, + CS_WEAPON_HE_GRENADE, + CS_WEAPON_FLASH_GRENADE, + CS_WEAPON_SMOKE_GRENADE, + CS_WEAPON_C4, + CS_WEAPON_MAX +}; + +enum +{ + WEAP_FL_NONE = 0, + WEAP_FL_PRIM_ATTACK = 1 << 0, + WEAP_FL_SEC_ATTACK = 1 << 1, + WEAP_FL_EXPLOSIVE = 1 << 2, // weapon is an explosive weapon eg. rpg + WEAP_FL_MELEE = 1 << 3, // + WEAP_FL_UNDERWATER = 1 << 4, // weapon can be used under water + WEAP_FL_HOLDATTACK = 1 << 5, // weapon must hold attack (e.g. minigun) + WEAP_FL_SPECIAL = 1 << 6, // + WEAP_FL_KILLPIPEBOMBS = 1 << 7, // weapon can destroy pipe bombs (tf2) + WEAP_FL_DEFLECTROCKETS = 1 << 8, // weapon can deflect rocekts (tf2) + WEAP_FL_GRAVGUN = 1 << 9, // weapon is a grav gun + WEAP_FL_EXPLOSIVE_SEC = 1 << 10, // weapon has an explosive secondary attack + WEAP_FL_ZOOMABLE = 1 << 11, // weapon can be zoomed + WEAP_FL_DEPLOYABLE = 1 << 12, // weapon can be deployed + WEAP_FL_MELEE_SEC_ATT = 1 << 13, // weapon has a melee secondary attack + WEAP_FL_FIRE_SELECT = 1 << 14, // weapon can choose fire mode + WEAP_FL_CANTFIRE_NORM = 1 << 15, // weapon can't be fired normally, needs to be zoomed/deployed + WEAP_FL_GRENADE = 1 << 16, + WEAP_FL_HIGH_RECOIL = 1 << 17, // can't be fired at long distance, but ok when deployed + WEAP_FL_SCOPE = 1 << 18, // has a scope . i.e. sniper rifle + WEAP_FL_PROJECTILE = 1 << 19 // affected by gravity +}; -#define WEAP_FL_NONE 0 -#define WEAP_FL_PRIM_ATTACK 1 -#define WEAP_FL_SEC_ATTACK 2 -#define WEAP_FL_EXPLOSIVE 4 // weapon is an explosive weapon eg. rpg -#define WEAP_FL_MELEE 8 // -#define WEAP_FL_UNDERWATER 16 // weapon can be used under water -#define WEAP_FL_HOLDATTACK 32 // weapon must hold attack (e.g. minigun) -#define WEAP_FL_SPECIAL 64 // -#define WEAP_FL_KILLPIPEBOMBS 128 // weapon can destroy pipe bombs (tf2) -#define WEAP_FL_DEFLECTROCKETS 256 // weapon can deflect rocekts (tf2) -#define WEAP_FL_GRAVGUN 512 // weapon is a grav gun -#define WEAP_FL_EXPLOSIVE_SEC 1024 // weapon has an explosive secondary attack -#define WEAP_FL_ZOOMABLE 2048 // weapon can be zoomed -#define WEAP_FL_DEPLOYABLE 4096 // weapon can be deployed -#define WEAP_FL_MELEE_SEC_ATT 8192 // weapon has a melee secondary attack -#define WEAP_FL_FIRE_SELECT 16384 // weapon can choose fire mode -#define WEAP_FL_CANTFIRE_NORM 32768 // weapon can't be fired normally, needs to be zoomed/deployed -#define WEAP_FL_GRENADE 65536 -#define WEAP_FL_HIGH_RECOIL 131072 // can't be fired at long distance, but ok when deployed -#define WEAP_FL_SCOPE 262144 // has a scope . i.e. sniper rifle -#define WEAP_FL_PROJECTILE 524288 // affected by gravity - -extern WeaponsData_t TF2Weaps[]; -extern WeaponsData_t HL2DMWeaps[]; -extern WeaponsData_t DODWeaps[]; +extern std::vector TF2Weaps; +extern std::vector HL2DMWeaps; +extern std::vector DODWeaps; +extern std::vector BMSWeaps; +extern std::vector SYNERGYWeaps; +extern std::vector CSSWeaps; class CWeapon { public: - CWeapon ( WeaponsData_t *data ) + CWeapon(const WeaponsData_t* data) { m_iSlot = data->iSlot; setID(data->iId); @@ -271,214 +350,211 @@ class CWeapon m_iPreference = iPref; }*/ - inline void setName ( const char *szWeaponName ) + void setName(const char* szWeaponName) { m_szWeaponName = szWeaponName; } - inline bool isWeaponName ( const char *szWeaponName ) + bool isWeaponName(const char* szWeaponName) const { - return !strcmp(szWeaponName,getWeaponName()); + return !strcmp(szWeaponName, getWeaponName()); } - inline bool isShortWeaponName ( const char *szWeaponName ) + bool isShortWeaponName(const char* szWeaponName) const { - static int start; - - start = strlen(m_szWeaponName) - strlen(szWeaponName); - - if ( start < 0 ) + if (std::strlen(szWeaponName) > std::strlen(m_szWeaponName)) return false; - return !strcmp(&m_szWeaponName[start],szWeaponName); + const std::size_t start = std::strlen(m_szWeaponName) - std::strlen(szWeaponName); + + return std::strcmp(&m_szWeaponName[start], szWeaponName) == 0; } - inline bool canDestroyPipeBombs() + bool canDestroyPipeBombs() const { return hasAllFlags(WEAP_FL_KILLPIPEBOMBS); } - inline bool isScoped () + bool isScoped() const { return hasAllFlags(WEAP_FL_SCOPE); } - - inline bool canDeflectRockets() + + bool canDeflectRockets() const { return hasAllFlags(WEAP_FL_DEFLECTROCKETS); } - inline void setID ( const int iId ) + void setID(const int iId) { m_iWeaponId = iId; } - inline void setFlags ( const int iFlags ) + void setFlags(const int iFlags) { m_iFlags = iFlags; } - inline bool primaryInRange ( float fDistance ) + bool primaryInRange(const float fDistance) const { - return (fDistance>m_fPrimMinWeaponShootDist)&&(fDistance m_fPrimMinWeaponShootDist && fDistance < m_fPrimMaxWeaponShootDist; } - inline bool primaryGreaterThanRange ( float fDistance ) + bool primaryGreaterThanRange(const float fDistance) const { - return (fDistancem_fSecMinWeaponShootDist)&&(fDistance m_fSecMinWeaponShootDist && fDistance < m_fSecMaxWeaponShootDist; } - inline int getPreference () + int getPreference() const { return m_iPreference; } - inline const char *getWeaponName () const + const char* getWeaponName() const { return m_szWeaponName; } - inline const int getID () const + int getID() const { return m_iWeaponId; } - inline void setPrimaryRange ( float fMinRange, float fMaxRange ) + void setPrimaryRange(const float fMinRange, const float fMaxRange) { - m_fPrimMinWeaponShootDist = fMinRange; + m_fPrimMinWeaponShootDist = fMinRange; m_fPrimMaxWeaponShootDist = fMaxRange; } - inline void setSecondaryRange ( float fMinRange, float fMaxRange ) + void setSecondaryRange(const float fMinRange, const float fMaxRange) { m_fSecMinWeaponShootDist = fMinRange; m_fSecMaxWeaponShootDist = fMaxRange; } - inline int getAmmoIndex1 () + int getAmmoIndex1() const { return m_iAmmoIndex1; } - inline int getAmmoIndex2 () + int getAmmoIndex2() const { return m_iAmmoIndex2; } - inline int getSlot () + int getSlot() const { return m_iSlot; } - void setAmmoIndex ( int iAmmoIndex1, int iAmmoIndex2 = -1) + void setAmmoIndex(const int iAmmoIndex1, const int iAmmoIndex2 = -1) { m_iAmmoIndex1 = iAmmoIndex1; m_iAmmoIndex2 = iAmmoIndex2; } - inline bool canUseSecondary () + bool canUseSecondary() const { return hasSomeFlags(WEAP_FL_SEC_ATTACK); } - inline float getProjectileSpeed () + float getProjectileSpeed() const { return m_fProjectileSpeed; } private: - - inline bool hasAllFlags ( int iFlags ) const + bool hasAllFlags(const int iFlags) const { - return (m_iFlags & iFlags)==iFlags; + return (m_iFlags & iFlags) == iFlags; } - inline bool hasSomeFlags ( int iFlags ) const + bool hasSomeFlags(const int iFlags) const { - return (m_iFlags & iFlags)>0; + return (m_iFlags & iFlags) > 0; } - const char *m_szWeaponName; // classname + const char* m_szWeaponName; // classname int m_iWeaponId; // identification int m_iFlags; // flags @@ -502,33 +578,37 @@ class IWeaponFunc; class CWeapons { public: - CWeapons () + CWeapons() { m_theWeapons.clear(); } - static inline void addWeapon ( CWeapon *pWeapon ) { m_theWeapons.push_back(pWeapon); } + static void addWeapon(CWeapon* pWeapon) { m_theWeapons.emplace_back(pWeapon); } - static CWeapon *getWeapon ( const int iId ); + static CWeapon* getWeapon(int iId); - static CWeapon *getWeapon ( const char *szWeapon ); + static CWeapon* getWeapon(const char* szWeapon); - static CWeapon *getWeaponByShortName ( const char *pszWeapon ); + static CWeapon* getWeaponByShortName(const char* szWeapon); - static void eachWeapon ( IWeaponFunc *pFunc ); + static void eachWeapon(IWeaponFunc* pFunc); - static void freeMemory (); + static void freeMemory(); - static edict_t *findWeapon ( edict_t *pPlayer, const char *szWeaponName ); + static edict_t* findWeapon(edict_t* pPlayer, const char* szWeaponName); - static void loadWeapons(const char *szWeaponListName, WeaponsData_t *pDefault); + static void loadWeapons(const char* szWeaponListName, const WeaponsData_t* pDefault); private: // available weapons in game - static vector m_theWeapons; + static std::vector m_theWeapons; +}; + +enum : std::uint8_t +{ + AMMO_PRIM = 1, + AMMO_SEC = 2 }; -#define AMMO_PRIM 1 -#define AMMO_SEC 2 //////////////////////////////////////////////////////////// // Weapon but with bot holding it and ammo information etc @@ -536,253 +616,251 @@ class CWeapons class CBotWeapon { public: - CBotWeapon () + CBotWeapon() { - m_pWeaponInfo = NULL; - m_bHasWeapon = false; + m_pWeaponInfo = nullptr; + m_bHasWeapon = false; m_iWeaponIndex = 0; - m_pEnt = NULL; - m_iClip1 = NULL; - m_iClip2 = NULL; + m_pEnt = nullptr; + m_iClip1 = nullptr; + m_iClip2 = nullptr; } - inline void setWeapon ( CWeapon *pWeapon ) + void setWeapon(CWeapon* pWeapon) { m_pWeaponInfo = pWeapon; } - inline float getPrimaryMaxRange() + float getPrimaryMaxRange() const { return m_pWeaponInfo->primaryMaxRange(); } - inline bool primaryInRange ( float fDistance ) + bool primaryInRange(const float fDistance) const { return m_pWeaponInfo->primaryInRange(fDistance); } - inline bool primaryGreaterThanRange ( float fDistance ) + bool primaryGreaterThanRange(const float fDistance) const { - return m_pWeaponInfo->primaryGreaterThanRange(fDistance); + return m_pWeaponInfo->primaryGreaterThanRange(fDistance); } - inline bool needsDeployedOrZoomed () + bool needsDeployedOrZoomed() const { return m_pWeaponInfo->needsDeployedOrZoomed(); } - inline bool isGravGun () + bool isGravGun() const { return m_pWeaponInfo->isGravGun(); } - - inline bool isExplosive () + bool isExplosive() const { return m_pWeaponInfo->isExplosive(); } - inline bool isZoomable () + bool isZoomable() const { return m_pWeaponInfo->isZoomable(); } - inline bool canUseUnderWater () + bool canUseUnderWater() const { return m_pWeaponInfo->canUseUnderWater(); } - inline bool hasHighRecoil () + bool hasHighRecoil() const { return m_pWeaponInfo->hasHighRecoil(); } - inline int getID () + int getID() const { return m_pWeaponInfo->getID(); } - inline bool isSpecial () + bool isSpecial() const { return m_pWeaponInfo->isSpecial(); } - inline float primaryMaxRange ( ) + float primaryMaxRange() const { - return (m_pWeaponInfo->primaryMaxRange()); + return m_pWeaponInfo->primaryMaxRange(); } - inline bool isDeployable () + bool isDeployable() const { return m_pWeaponInfo->isDeployable(); } - inline bool mustHoldAttack () + bool mustHoldAttack() const { return m_pWeaponInfo->mustHoldAttack(); } - inline bool canDestroyPipeBombs() + bool canDestroyPipeBombs() const { return m_pWeaponInfo->canDestroyPipeBombs(); } - inline bool isProjectile () + bool isProjectile() const { return m_pWeaponInfo->isProjectile(); } - inline float getProjectileSpeed () + float getProjectileSpeed() const { return m_pWeaponInfo->getProjectileSpeed(); } - - inline bool canDeflectRockets() + + bool canDeflectRockets() const { return m_pWeaponInfo->canDeflectRockets(); } - inline bool canUseSecondary () + bool canUseSecondary() const { return m_pWeaponInfo->canUseSecondary(); } - inline bool isMelee () + bool isMelee() const { return m_pWeaponInfo->isMelee(); } - inline bool isMeleeSecondary () + bool isMeleeSecondary() const { return m_pWeaponInfo->isMeleeSecondary(); } - inline bool secondaryInRange ( float fDistance ) + bool secondaryInRange(const float fDistance) const { return m_pWeaponInfo->secondaryInRange(fDistance); } - inline int getPreference () + int getPreference() const { return m_pWeaponInfo->getPreference(); } - bool outOfAmmo (CBot *pBot); + bool outOfAmmo(const CBot* pBot) const; - bool needToReload (CBot *pBot); + bool needToReload(const CBot* pBot) const; - inline void setHasWeapon ( bool bHas ) + void setHasWeapon(const bool bHas) { m_bHasWeapon = bHas; } - inline bool hasWeapon () + bool hasWeapon() const { return m_bHasWeapon; } - inline bool canAttack () + bool canAttack() const { return m_pWeaponInfo->canAttack(); } - int getAmmo ( CBot *pBot, int type = AMMO_PRIM ); + int getAmmo(const CBot* pBot, int type = AMMO_PRIM) const; - int getClip1 ( CBot *pBot ) - { - if ( m_iClip1 ) - return *m_iClip1; - - return 0; - } + int getClip1(CBot* pBot) const + { + if (m_iClip1) + return *m_iClip1; - int getClip2 ( CBot *pBot ) - { - if ( m_iClip2 ) - return *m_iClip2; - - return 0; + return 0; } - CWeapon *getWeaponInfo () { return m_pWeaponInfo; } + int getClip2(CBot* pBot) const + { + if (m_iClip2) + return *m_iClip2; + + return 0; + } - inline int getWeaponIndex () { return m_iWeaponIndex; } + CWeapon* getWeaponInfo() const { return m_pWeaponInfo; } - inline void setWeaponIndex (int iIndex) { m_iWeaponIndex = iIndex; } // Entity Index + int getWeaponIndex() const { return m_iWeaponIndex; } - void setWeaponEntity (edict_t *pent, bool bOverrideAmmoTypes = true ); + void setWeaponIndex(const int iIndex) { m_iWeaponIndex = iIndex; } // Entity Index - inline edict_t *getWeaponEntity () { return m_pEnt; } + void setWeaponEntity(edict_t* pent, bool bOverrideAmmoTypes = true); + edict_t* getWeaponEntity() const { return m_pEnt; } private: // link to weapon info - CWeapon *m_pWeaponInfo; + CWeapon* m_pWeaponInfo; int m_iWeaponIndex; bool m_bHasWeapon; - edict_t *m_pEnt; + edict_t* m_pEnt; - int *m_iClip1; - int *m_iClip2; + int* m_iClip1; + int* m_iClip2; }; // Weapons that -class CBotWeapons +class CBotWeapons { public: -///////////////////////////////////// - CBotWeapons ( CBot *pBot ); // // constructor -///////////////////////////////////// - CBotWeapon *getBestWeapon ( edict_t *pEnemy, bool bAllowMelee = true, bool bAllowMeleeFallback = true, bool bMeleeOnly = false, bool bExplosivesOnly = false, bool bIgnorePrimaryMinimum = false ); + ///////////////////////////////////// + CBotWeapons(CBot* pBot); // // constructor + ///////////////////////////////////// + CBotWeapon* getBestWeapon(edict_t* pEnemy, bool bAllowMelee = true, bool bAllowMeleeFallback = true, bool bMeleeOnly = false, bool bExplosivesOnly = false, bool bIgnorePrimaryMinimum = false); - CBotWeapon *addWeapon(CWeapon *pWeaponInfo, int iId, edict_t *pent, bool bOverrideAll = true); + CBotWeapon* addWeapon(CWeapon* pWeaponInfo, int iId, edict_t* pent, bool bOverrideAll = true); - CBotWeapon *getWeapon(CWeapon *pWeapon); + CBotWeapon* getWeapon(const CWeapon* pWeapon); - CBotWeapon *getActiveWeapon(const char *szWeaponName, edict_t *pWeaponUpdate = NULL, bool bOverrideAmmoTypes = true); + CBotWeapon* getActiveWeapon(const char* szWeaponName, edict_t* pWeaponUpdate = nullptr, bool bOverrideAmmoTypes = true); - CBotWeapon *getCurrentWeaponInSlot ( int iSlot ); + CBotWeapon* getCurrentWeaponInSlot(int iSlot); - CBotWeapon *getGrenade () + CBotWeapon* getGrenade() { - for ( int i = 0; i < MAX_WEAPONS; i ++ ) + for (CBotWeapon& m_theWeapon : m_theWeapons) { - if ( m_theWeapons[i].hasWeapon() ) + if (m_theWeapon.hasWeapon()) { - if ( m_theWeapons[i].getWeaponInfo() ) + if (m_theWeapon.getWeaponInfo()) { - if ( m_theWeapons[i].getWeaponInfo()->isGrenade() ) - return &(m_theWeapons[i]); + if (m_theWeapon.getWeaponInfo()->isGrenade()) + return &m_theWeapon; } } } - return NULL; + return nullptr; } - void clearWeapons (); + void clearWeapons(); - bool hasWeapon ( int id ); + bool hasWeapon(int id) const; - bool hasExplosives ( void ); + bool hasExplosives() const; // returns true if there is a change to the weapons - bool update ( bool bOverrideAllFromEngine = true ); // update from sendprop + bool update(bool bOverrideAllFromEngine = true); // update from sendprop - CBotWeapon *getPrimaryWeapon (); // return the most important weapon bot is holding if if out o ammo - inline void resetSignature() { m_iWeaponsSignature = 0; } + CBotWeapon* getPrimaryWeapon(); // return the most important weapon bot is holding if if out o ammo + void resetSignature() { m_iWeaponsSignature = 0; } private: // bot that has these weapons - CBot *m_pBot; + CBot* m_pBot; // checksum mask of weapons bot already has so we know if we need to update or not - unsigned int m_iWeaponsSignature; + std::uintptr_t m_iWeaponsSignature; - // weapons local to the bot only + // weapons local to the bot only // (holds ammo/preference etc and link to actual weapon) CBotWeapon m_theWeapons[MAX_WEAPONS];//[MAX_WEAPONS]; diff --git a/utils/RCBot2_meta/bot_wpt_color.h b/utils/RCBot2_meta/bot_wpt_color.h index 2c75b631b..353c9e72c 100644 --- a/utils/RCBot2_meta/bot_wpt_color.h +++ b/utils/RCBot2_meta/bot_wpt_color.h @@ -1,19 +1,31 @@ +#pragma once + #ifndef __BOT_WPT_COLOR_H__ #define __BOT_WPT_COLOR_H__ +#include + +#pragma push_macro("clamp") //Fix for C++17 [APG]RoboCop[CL] +#undef clamp +#include +#pragma pop_macro("clamp") + // gone for the american spelling of 'colour' :) -#define WAYPOINT_ALPHA 200 +enum : std::uint8_t +{ + WAYPOINT_ALPHA = 200 +}; class WptColor { public: WptColor () { - memset(this,0,sizeof(WptColor)); + std::memset(this,0,sizeof(WptColor)); } - WptColor ( int _r, int _g, int _b, int _a ) + WptColor (const unsigned char _r, const unsigned char _g, const unsigned char _b, const unsigned char _a) { r=_r; g=_g; @@ -21,7 +33,7 @@ class WptColor a=_a; } - WptColor ( int _r, int _g, int _b ) + WptColor (const unsigned char _r, const unsigned char _g, const unsigned char _b) { r=_r; g=_g; @@ -29,22 +41,19 @@ class WptColor a=WAYPOINT_ALPHA; } - void mix ( WptColor other ) + void mix (const WptColor& other) { - float fr = (r-other.r)*0.5; - float fg = (g-other.g)*0.5; - float fb = (b-other.b)*0.5; - - if ( fr < 0 ) - fr = 0; - if ( fg < 0 ) - fg = 0; - if ( fb < 0 ) - fb = 0; - - r = (unsigned char)((int)((float)other.r*0.5))+(unsigned char)((int)fr); - g = (unsigned char)((int)((float)other.g*0.5))+(unsigned char)((int)fg); - b = (unsigned char)((int)((float)other.b*0.5))+(unsigned char)((int)fb); + float fr = (r-other.r)*0.5f; + float fg = (g-other.g)*0.5f; + float fb = (b-other.b)*0.5f; + + fr = std::max(fr, 0); + fg = std::max(fg, 0); + fb = std::max(fb, 0); + + r = static_cast(static_cast(static_cast(other.r) * 0.5f))+static_cast(static_cast(fr)); + g = static_cast(static_cast(static_cast(other.g) * 0.5f))+static_cast(static_cast(fg)); + b = static_cast(static_cast(static_cast(other.b) * 0.5f))+static_cast(static_cast(fb)); //r = (r+other.r)/2; //g = (g+other.g)/2; diff --git a/utils/RCBot2_meta/bot_wpt_dist.cpp b/utils/RCBot2_meta/bot_wpt_dist.cpp index 975e64426..b980d9db8 100644 --- a/utils/RCBot2_meta/bot_wpt_dist.cpp +++ b/utils/RCBot2_meta/bot_wpt_dist.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com #include "engine_wrappers.h" #include "bot_wpt_dist.h" @@ -11,79 +13,73 @@ typedef struct int maxwaypoints; }wpt_dist_hdr_t; -int CWaypointDistances::m_Distances [CWaypoints::MAX_WAYPOINTS][CWaypoints::MAX_WAYPOINTS]; -float CWaypointDistances::m_fSaveTime = 0; +int CWaypointDistances::m_Distances[CWaypoints::MAX_WAYPOINTS][CWaypoints::MAX_WAYPOINTS]; +float CWaypointDistances::m_fSaveTime = 0.0f; -void CWaypointDistances :: load () +void CWaypointDistances::load() { - char filename[1024]; wpt_dist_hdr_t hdr; - char *szMapName = CBotGlobals::getMapName(); + const char* szMapName = CBotGlobals::getMapName(); - if ( szMapName && *szMapName ) + if (szMapName && *szMapName) { - CBotGlobals::buildFileName(filename,szMapName,BOT_WAYPOINT_FOLDER,BOT_WAYPOINT_DST_EXTENSION,true); + char filename[1024]; + CBotGlobals::buildFileName(filename, szMapName, BOT_AUXILERY_FOLDER, BOT_WAYPOINT_DST_EXTENSION, true); - FILE *bfp = CBotGlobals::openFile(filename,"rb"); + std::fstream bfp = CBotGlobals::openFile(filename, std::fstream::in | std::fstream::binary); - if ( bfp == NULL ) + if (!bfp) { return; // give up } - fread(&hdr,sizeof(wpt_dist_hdr_t),1,bfp); + bfp.read(reinterpret_cast(&hdr), sizeof(wpt_dist_hdr_t)); - if ( (hdr.maxwaypoints == CWaypoints::MAX_WAYPOINTS) && (hdr.numwaypoints == CWaypoints::numWaypoints()) && (hdr.version == WPT_DIST_VER) ) + if ((hdr.maxwaypoints == CWaypoints::MAX_WAYPOINTS) && (hdr.numwaypoints == CWaypoints::numWaypoints()) && (hdr.version == WPT_DIST_VER)) { - fread(m_Distances,sizeof(int),CWaypoints::MAX_WAYPOINTS * CWaypoints::MAX_WAYPOINTS,bfp); + bfp.read(reinterpret_cast(m_Distances), sizeof(m_Distances)); } m_fSaveTime = engine->Time() + 100.0f; - - fclose(bfp); } } -void CWaypointDistances :: save () +void CWaypointDistances::save() { - //if ( m_fSaveTime < engine->Time() ) - //{ - char filename[1024]; - char *szMapName = CBotGlobals::getMapName(); - - if ( szMapName && *szMapName ) - { - wpt_dist_hdr_t hdr; + const char* szMapName = CBotGlobals::getMapName(); - CBotGlobals::buildFileName(filename,szMapName,BOT_WAYPOINT_FOLDER,BOT_WAYPOINT_DST_EXTENSION,true); + if (szMapName && *szMapName) + { + char filename[1024]; + wpt_dist_hdr_t hdr; - FILE *bfp = CBotGlobals::openFile(filename,"wb"); + CBotGlobals::buildFileName(filename, szMapName, BOT_AUXILERY_FOLDER, BOT_WAYPOINT_DST_EXTENSION, true); - if ( bfp == NULL ) - { - m_fSaveTime = engine->Time() + 100.0f; - return; // give up - } + std::fstream bfp = CBotGlobals::openFile(filename, std::fstream::out | std::fstream::binary); - hdr.maxwaypoints = CWaypoints::MAX_WAYPOINTS; - hdr.numwaypoints = CWaypoints::numWaypoints(); - hdr.version = WPT_DIST_VER; + if (!bfp) + { + m_fSaveTime = engine->Time() + 100.0f; + return; // give up + } - fwrite(&hdr,sizeof(wpt_dist_hdr_t),1,bfp); + hdr.maxwaypoints = CWaypoints::MAX_WAYPOINTS; + hdr.numwaypoints = CWaypoints::numWaypoints(); + hdr.version = WPT_DIST_VER; - fwrite(m_Distances,sizeof(int),CWaypoints::MAX_WAYPOINTS * CWaypoints::MAX_WAYPOINTS,bfp); + bfp.write(reinterpret_cast(&hdr), sizeof(wpt_dist_hdr_t)); - m_fSaveTime = engine->Time() + 100.0f; + bfp.write(reinterpret_cast(m_Distances), sizeof(m_Distances)); - fclose(bfp); - } + m_fSaveTime = engine->Time() + 100.0f; + } //} } -float CWaypointDistances :: getDistance ( int iFrom, int iTo ) +float CWaypointDistances::getDistance(const int iFrom, const int iTo) { - if ( m_Distances[iFrom][iTo] == -1 ) - return (CWaypoints::getWaypoint(iFrom)->getOrigin()-CWaypoints::getWaypoint(iTo)->getOrigin()).Length(); + if (m_Distances[iFrom][iTo] == -1) + return (CWaypoints::getWaypoint(iFrom)->getOrigin() - CWaypoints::getWaypoint(iTo)->getOrigin()).Length(); - return (float)m_Distances[iFrom][iTo]; + return static_cast(m_Distances[iFrom][iTo]); } \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_wpt_dist.h b/utils/RCBot2_meta/bot_wpt_dist.h index 78f224d27..0c142327b 100644 --- a/utils/RCBot2_meta/bot_wpt_dist.h +++ b/utils/RCBot2_meta/bot_wpt_dist.h @@ -3,28 +3,31 @@ #include "bot_waypoint.h" -#define WPT_DIST_VER 0x03 +enum : std::uint8_t +{ + WPT_DIST_VER = 0x03 +}; -#define BOT_WAYPOINT_DST_EXTENSION "rcd" +constexpr const char* BOT_WAYPOINT_DST_EXTENSION = "rcd"; class CWaypointDistances { public: CWaypointDistances() { - m_fSaveTime = 0; + m_fSaveTime = 0.0f; } static float getDistance ( int iFrom, int iTo ); - static inline bool isSet ( int iFrom, int iTo ) + static bool isSet (const int iFrom, const int iTo) { return m_Distances[iFrom][iTo] >= 0; } - static inline void setDistance ( int iFrom, int iTo, float fDist ) + static void setDistance (const int iFrom, const int iTo, const float fDist) { - m_Distances[iFrom][iTo] = (int)fDist; + m_Distances[iFrom][iTo] = static_cast(fDist); } static void load (); @@ -33,7 +36,7 @@ class CWaypointDistances static void reset () { - memset(m_Distances,0xFF,sizeof(int)*CWaypoints::MAX_WAYPOINTS*CWaypoints::MAX_WAYPOINTS); + std::memset(m_Distances,0xFF,sizeof(int)*CWaypoints::MAX_WAYPOINTS*CWaypoints::MAX_WAYPOINTS); } private: static int m_Distances [CWaypoints::MAX_WAYPOINTS][CWaypoints::MAX_WAYPOINTS]; diff --git a/utils/RCBot2_meta/bot_zombie.cpp b/utils/RCBot2_meta/bot_zombie.cpp index 3aae251c6..ae100815f 100644 --- a/utils/RCBot2_meta/bot_zombie.cpp +++ b/utils/RCBot2_meta/bot_zombie.cpp @@ -1,3 +1,5 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++, C#, and Java: http://www.viva64.com #include "engine_wrappers.h" #include "bot.h" @@ -7,34 +9,37 @@ #include "bot_waypoint_locations.h" #include "bot_schedule.h" -bool CBotZombie :: isEnemy ( edict_t *pEdict,bool bCheckWeapons ) +bool CBotZombie::isEnemy(edict_t* pEdict, bool bCheckWeapons) { - if ( pEdict == m_pEdict ) + if (pEdict == nullptr || pEdict == m_pEdict) return false; - if ( !ENTINDEX(pEdict) || (ENTINDEX(pEdict) > CBotGlobals::maxClients()) ) + const int edictIndex = ENTINDEX(pEdict); + if (edictIndex == 0 || edictIndex > CBotGlobals::maxClients()) return false; - if ( CBotGlobals::getTeamplayOn() ) + if (CBotGlobals::getTeamplayOn()) { - if ( CBotGlobals::getTeam(pEdict) == getTeam() ) + if (CBotGlobals::getTeam(pEdict) == getTeam()) return false; } - return true; + return true; } -void CBotZombie :: modThink ( void ) +void CBotZombie::modThink() { - // + // Implement zombie-specific thinking logic here } -void CBotZombie :: getTasks ( unsigned int iIgnore ) +void CBotZombie::getTasks(unsigned iIgnore) { - if ( m_pEnemy ) + if (m_pEnemy) { m_pSchedules->add(new CBotGotoOriginSched(m_pEnemy)); } else + { CBot::getTasks(); + } } \ No newline at end of file diff --git a/utils/RCBot2_meta/bot_zombie.h b/utils/RCBot2_meta/bot_zombie.h index 68bc82ef5..ee8ff0c7e 100644 --- a/utils/RCBot2_meta/bot_zombie.h +++ b/utils/RCBot2_meta/bot_zombie.h @@ -3,11 +3,11 @@ class CBotZombie : public CBot { - bool isEnemy ( edict_t *pEdict,bool bCheckWeapons = true ); + bool isEnemy ( edict_t *pEdict,bool bCheckWeapons = true ) override; - void modThink ( void ); + void modThink () override; - void getTasks (unsigned int iIgnore); + void getTasks (unsigned iIgnore) override; }; -#endif \ No newline at end of file +#endif // _BOT_ZOMBIE_H_ \ No newline at end of file diff --git a/utils/RCBot2_meta/engine_wrappers.h b/utils/RCBot2_meta/engine_wrappers.h index 1f883e1c0..8ca447a5d 100644 --- a/utils/RCBot2_meta/engine_wrappers.h +++ b/utils/RCBot2_meta/engine_wrappers.h @@ -29,7 +29,7 @@ extern CGlobalVars *gpGlobals; /** * Wrap some API calls for legacy MM:S. */ -#if !defined METAMOD_PLAPI_VERSION +#ifndef METAMOD_PLAPI_VERSION #define GetEngineFactory engineFactory #define GetServerFactory serverFactory #define MM_Format snprintf @@ -68,26 +68,26 @@ class CCommand */ #if SOURCE_ENGINE >= SE_LEFT4DEAD -inline int IndexOfEdict(const edict_t *pEdict) +inline int IndexOfEdict(const edict_t* pEdict) { - return (int)(pEdict - gpGlobals->pEdicts); + return static_cast(pEdict - engine->PEntityOfEntIndex(0)); } -inline edict_t *PEntityOfEntIndex(int iEntIndex) +inline edict_t* PEntityOfEntIndex(const int iEntIndex) { if (iEntIndex >= 0 && iEntIndex < gpGlobals->maxEntities) { - return (edict_t *)(gpGlobals->pEdicts + iEntIndex); + return engine->PEntityOfEntIndex(iEntIndex); } - return NULL; + return nullptr; } #else -inline int IndexOfEdict(const edict_t *pEdict) +inline int IndexOfEdict(const edict_t* pEdict) { return engine->IndexOfEdict(pEdict); } -inline edict_t *PEntityOfEntIndex(int iEntIndex) +inline edict_t* PEntityOfEntIndex(const int iEntIndex) { return engine->PEntityOfEntIndex(iEntIndex); } diff --git a/utils/RCBot2_meta/logging.h b/utils/RCBot2_meta/logging.h new file mode 100644 index 000000000..3a4472640 --- /dev/null +++ b/utils/RCBot2_meta/logging.h @@ -0,0 +1,61 @@ +/** + * Copyright 2021 nosoop + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA + * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __RCBOT2_LOGGER_H__ +#define __RCBOT2_LOGGER_H__ + +#include + +// Undefine potential conflicting macros +#ifdef FATAL +#undef FATAL +#endif + +#ifdef ERROR +#undef ERROR +#endif + +#ifdef WARN +#undef WARN +#endif + +#ifdef INFO +#undef INFO +#endif + +#ifdef DEBUG +#undef DEBUG +#endif + +#ifdef TRACE +#undef TRACE +#endif + +/** + * Log levels in ascending order. + */ +enum LogLevel : std::uint8_t { + FATAL, ERROR, WARN, INFO, DEBUG, TRACE +}; + +class CBotLogger { + public: + void Log(LogLevel level, const char* fmt, ...); +}; + +extern CBotLogger *logger; + +#endif diff --git a/utils/mmsource/.gitignore b/utils/mmsource/.gitignore deleted file mode 100644 index c2f678d98..000000000 --- a/utils/mmsource/.gitignore +++ /dev/null @@ -1,28 +0,0 @@ -# Binaries -*.dll -*.dylib -*.exe -*.so - -# Files generated by Visual Studio -*.aps -*.ncb -*.sdf -*.suo -*.user - -# Build directories -Debug.*/ -Release.*/ - -# Files generated by Mac OS X Finder -.DS_Store - -# Files generated by Windows Explorer -[Dd]esktop.ini -[Tt]humbs.db - -# AMBuild build directories -build/ -obj-*/ -.gdb_history diff --git a/utils/mmsource/.travis.yml b/utils/mmsource/.travis.yml deleted file mode 100644 index ada0ce352..000000000 --- a/utils/mmsource/.travis.yml +++ /dev/null @@ -1,116 +0,0 @@ -git: - depth: 3 - -sudo: false -language: cpp -os: linux -dist: trusty -addons: - apt: - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-trusty-3.9 - - llvm-toolchain-trusty-4.0 - - llvm-toolchain-trusty-5.0 - packages: - - lib32stdc++6 - - lib32z1-dev - - libc6-dev-i386 - - linux-libc-dev - - g++-multilib -# - clang-3.6 -# - clang-3.8 -# - clang-4.0 -# - clang-5.0 -# - g++-6 -# - g++-6-multilib - - clang-3.9 - - g++-4.8-multilib - - g++-4.8 - - g++-4.9-multilib - - g++-4.9 - - g++-5-multilib - - g++-5 - - g++-7-multilib - - g++-7 - cache: - directories: - - ../mysql-5.0 -env: - - MATRIX_EVAL="CC=clang-3.9 && CXX=clang++-3.9" - - MATRIX_EVAL="CC=gcc-4.8 && CXX=g++-4.8" - - MATRIX_EVAL="CC=gcc-4.9 && CXX=g++-4.9" - - MATRIX_EVAL="CC=gcc-5 && CXX=g++-5" - - MATRIX_EVAL="CC=gcc-7 && CXX=g++-7" - -matrix: - fast_finish: true - include: - - os: linux - sudo: false - language: cpp - addons: - apt: - packages: ['clang-3.6', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib'] - env: ['MATRIX_EVAL="CC=clang-3.6 && CXX=clang++-3.6"'] - - - os: linux - sudo: false - language: cpp - addons: - apt: - packages: ['clang-3.8', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib'] - env: ['MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8"'] - - - os: linux - sudo: false - language: cpp - addons: - apt: - sources: ['llvm-toolchain-trusty-4.0'] - packages: ['clang-4.0', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib'] - env: ['MATRIX_EVAL="CC=clang-4.0 && CXX=clang++-4.0"'] - - - os: linux - sudo: false - language: cpp - addons: - apt: - sources: ['llvm-toolchain-trusty-5.0'] - packages: ['clang-5.0', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib'] - env: ['MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0"'] - - - os: linux - sudo: false - language: cpp - addons: - apt: - sources: ['ubuntu-toolchain-r-test'] - packages: ['g++-6', 'g++-6-multilib', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib'] - env: ['MATRIX_EVAL="CC=gcc-6 && CXX=g++-6"'] - - allow_failures: - - env: MATRIX_EVAL="CC=clang-3.7 && CXX=clang++-3.7" - - env: MATRIX_EVAL="CC=clang-3.9 && CXX=clang++-3.9" - - env: MATRIX_EVAL="CC=gcc-4.8 && CXX=g++-4.8" - - env: MATRIX_EVAL="CC=gcc-4.9 && CXX=g++-4.9" - - env: MATRIX_EVAL="CC=gcc-5 && CXX=g++-5" - - env: MATRIX_EVAL="CC=gcc-7 && CXX=g++-7" - - -before_script: - - CHECKOUT_DIR=$PWD && cd .. && $CHECKOUT_DIR/support/checkout-deps.sh && cd $CHECKOUT_DIR -script: - - mkdir build && cd build - - PATH="~/.local/bin:$PATH" - - eval "${MATRIX_EVAL}" - - python ../configure.py --enable-optimize --sdks=episode1,tf2,l4d2,csgo,dota - - ambuild - - cd .. && mkdir build-sh-opt && cd build-sh-opt - - python ../configure.py --enable-optimize --enable-tests --sdks= - - ambuild - - ./core/sourcehook/test/test_sourcehook/test_sourcehook -v - - cd .. && mkdir build-sh-debug && cd build-sh-debug - - python ../configure.py --enable-debug --enable-tests --sdks= - - ambuild - - ./core/sourcehook/test/test_sourcehook/test_sourcehook -v diff --git a/utils/mmsource/AMBuildScript b/utils/mmsource/AMBuildScript deleted file mode 100644 index 836534896..000000000 --- a/utils/mmsource/AMBuildScript +++ /dev/null @@ -1,528 +0,0 @@ -# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: -import os, sys - -class SDK(object): - def __init__(self, sdk, ext, aDef, name, platform, dir): - self.folder = 'hl2sdk-' + dir - self.envvar = sdk - self.ext = ext - self.code = aDef - self.define = name - self.name = dir - self.path = None # Actual path - self.platformSpec = platform - - # By default, nothing supports x64. - if type(platform) is list: - self.platformSpec = {p: ['x86'] for p in platform} - else: - self.platformSpec = platform - - def shouldBuild(self, target, archs): - if target.platform not in self.platformSpec: - return False - if not len([i for i in self.platformSpec[target.platform] if i in archs]): - return False - return True - -WinOnly = ['windows'] -WinLinux = ['windows', 'linux'] -WinLinuxMac = ['windows', 'linux', 'mac'] -CSGO = { - 'windows': ['x86'], - 'linux': ['x86', 'x64'], - 'mac': ['x64'] -} -Source2 = { - 'windows': ['x86', 'x64'], - 'linux': ['x64'], -} - -PossibleSDKs = { - 'episode1': SDK('HL2SDK', '2.ep1', '1', 'EPISODEONE', WinLinux, 'episode1'), - 'ep2': SDK('HL2SDKOB', '2.ep2', '3', 'ORANGEBOX', WinLinux, 'orangebox'), - 'css': SDK('HL2SDKCSS', '2.css', '6', 'CSS', WinLinuxMac, 'css'), - 'hl2dm': SDK('HL2SDKHL2DM', '2.hl2dm', '7', 'HL2DM', WinLinuxMac, 'hl2dm'), - 'dods': SDK('HL2SDKDODS', '2.dods', '8', 'DODS', WinLinuxMac, 'dods'), - 'sdk2013': SDK('HL2SDK2013', '2.sdk2013', '9', 'SDK2013', WinLinuxMac, 'sdk2013'), - 'tf2': SDK('HL2SDKTF2', '2.tf2', '11', 'TF2', WinLinuxMac, 'tf2'), - 'l4d': SDK('HL2SDKL4D', '2.l4d', '12', 'LEFT4DEAD', WinLinuxMac, 'l4d'), - 'nucleardawn': SDK('HL2SDKND', '2.nd', '13', 'NUCLEARDAWN', WinLinuxMac, 'nucleardawn'), - 'l4d2': SDK('HL2SDKL4D2', '2.l4d2', '15', 'LEFT4DEAD2', WinLinuxMac, 'l4d2'), - 'darkm': SDK('HL2SDK-DARKM', '2.darkm', '2', 'DARKMESSIAH', WinOnly, 'darkm'), - 'swarm': SDK('HL2SDK-SWARM', '2.swarm', '16', 'ALIENSWARM', WinOnly, 'swarm'), - 'bgt': SDK('HL2SDK-BGT', '2.bgt', '4', 'BLOODYGOODTIME', WinOnly, 'bgt'), - 'eye': SDK('HL2SDK-EYE', '2.eye', '5', 'EYE', WinOnly, 'eye'), - 'csgo': SDK('HL2SDKCSGO', '2.csgo', '21', 'CSGO', CSGO, 'csgo'), - 'dota': SDK('HL2SDKDOTA', '2.dota', '22', 'DOTA', Source2, 'dota'), - 'portal2': SDK('HL2SDKPORTAL2', '2.portal2', '17', 'PORTAL2', [], 'portal2'), - 'blade': SDK('HL2SDKBLADE', '2.blade', '18', 'BLADE', WinLinux, 'blade'), - 'insurgency': SDK('HL2SDKINSURGENCY', '2.insurgency', '19', 'INSURGENCY', WinLinuxMac, 'insurgency'), - 'doi': SDK('HL2SDKDOI', '2.doi', '20', 'DOI', WinLinuxMac, 'doi'), - 'contagion': SDK('HL2SDKCONTAGION', '2.contagion', '14', 'CONTAGION', WinOnly, 'contagion'), - 'bms': SDK('HL2SDKBMS', '2.bms', '10', 'BMS', WinLinux, 'bms'), -} - -def ResolveEnvPath(env, folder): - if env in os.environ: - path = os.environ[env] - if os.path.isdir(path): - return path - else: - head = os.getcwd() - oldhead = None - while head != None and head != oldhead: - path = os.path.join(head, folder) - if os.path.isdir(path): - return path - oldhead = head - head, tail = os.path.split(head) - return None - -def SetArchFlags(compiler, arch, platform): - if compiler.behavior == 'gcc': - if arch == 'x86': - compiler.cflags += ['-m32'] - compiler.linkflags += ['-m32'] - if platform == 'mac': - compiler.linkflags += ['-arch', 'i386'] - elif arch == 'x64': - compiler.cflags += ['-m64', '-fPIC'] - compiler.linkflags += ['-m64'] - if platform == 'mac': - compiler.linkflags += ['-arch', 'x86_64'] - elif compiler.like('msvc'): - if arch == 'x86': - compiler.linkflags += ['/MACHINE:X86'] - elif arch == 'x64': - compiler.linkflags += ['/MACHINE:X64'] - -def AppendArchSuffix(binary, name, arch): - if arch == 'x64': - binary.localFolder = name + '.x64' - -class MMSConfig(object): - def __init__(self): - self.sdks = {} - self.binaries = [] - self.generated_headers = None - self.versionlib = None - self.archs = builder.target.arch.replace('x86_64', 'x64').split(',') - - def use_auto_versioning(self): - if builder.backend != 'amb2': - return False - return not getattr(builder.options, 'disable_auto_versioning', False) - - def detectProductVersion(self): - builder.AddConfigureFile('product.version') - - # For OS X dylib versioning - import re - with open(os.path.join(builder.sourcePath, 'product.version'), 'r') as fp: - productContents = fp.read() - m = re.match('(\d+)\.(\d+)\.(\d+).*', productContents) - if m == None: - self.productVersion = '1.0.0' - else: - major, minor, release = m.groups() - self.productVersion = '{0}.{1}.{2}'.format(major, minor, release) - - def detectSDKs(self): - sdk_list = builder.options.sdks.split(',') - use_all = sdk_list[0] == 'all' - use_present = sdk_list[0] == 'present' - if sdk_list[0] == '': - sdk_list = [] - - for sdk_name in PossibleSDKs: - sdk = PossibleSDKs[sdk_name] - if sdk.shouldBuild(builder.target, self.archs): - if builder.options.hl2sdk_root: - sdk_path = os.path.join(builder.options.hl2sdk_root, sdk.folder) - else: - sdk_path = ResolveEnvPath(sdk.envvar, sdk.folder) - if sdk_path is None: - if use_all or sdk_name in sdk_list: - raise Exception('Could not find a valid path for {0}'.format(sdk.envvar)) - continue - if use_all or use_present or sdk_name in sdk_list: - sdk.path = sdk_path - self.sdks[sdk_name] = sdk - - if len(self.sdks) < 1 and len(sdk_list): - raise Exception('No SDKs were found that build on {0}-{1}, nothing to do.'.format( - builder.target.platform, builder.target.arch)) - - def configure(self): - builder.AddConfigureFile('pushbuild.txt') - - if not set(self.archs).issubset(['x86', 'x64']): - raise Exception('Unknown target architecture: {0}'.format(builder.target.arch)) - - cxx = builder.DetectCxx() - - if cxx.like('msvc') and len(self.archs) > 1: - raise Exception('Building multiple archs with MSVC is not currently supported') - - if cxx.behavior == 'gcc': - cxx.defines += [ - 'stricmp=strcasecmp', - '_stricmp=strcasecmp', - '_snprintf=snprintf', - '_vsnprintf=vsnprintf', - 'HAVE_STDINT_H', - 'GNUC', - ] - cxx.cflags += [ - '-pipe', - '-fno-strict-aliasing', - '-Wall', - '-Werror', - '-Wno-uninitialized', - '-Wno-unused', - '-Wno-switch', - '-msse', - ] - - cxx.cxxflags += [ '-std=c++11' ] - if (cxx.version >= 'gcc-4.0') or cxx.family == 'clang': - cxx.cflags += ['-fvisibility=hidden'] - cxx.cxxflags += ['-fvisibility-inlines-hidden'] - cxx.cxxflags += [ - '-fno-exceptions', - '-fno-rtti', - '-fno-threadsafe-statics', - '-Wno-non-virtual-dtor', - '-Wno-overloaded-virtual', - ] - if (cxx.version >= 'gcc-4.7' or cxx.family == 'clang'): - cxx.cxxflags += ['-Wno-delete-non-virtual-dtor'] - if cxx.family == 'gcc': - cxx.cflags += ['-mfpmath=sse'] - if cxx.family == 'clang': - cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch'] - if cxx.version >= 'clang-3.9': - cxx.cxxflags += ['-Wno-expansion-to-defined'] - if cxx.version >= 'clang-3.6' or cxx.version >= 'apple-clang-7.0': - cxx.cxxflags += ['-Wno-inconsistent-missing-override'] - if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4': - cxx.cxxflags += ['-Wno-deprecated-register'] - else: - cxx.cxxflags += ['-Wno-deprecated'] - - elif cxx.like('msvc'): - if builder.options.debug == '1': - cxx.cflags += ['/MTd'] - cxx.linkflags += ['/NODEFAULTLIB:libcmt'] - else: - cxx.cflags += ['/MT'] - cxx.defines += [ - '_CRT_SECURE_NO_DEPRECATE', - '_CRT_SECURE_NO_WARNINGS', - '_CRT_NONSTDC_NO_DEPRECATE', - ] - cxx.cflags += [ - '/W3', - '/Zi', - ] - cxx.cxxflags += ['/TP'] - - cxx.linkflags += [ - '/SUBSYSTEM:WINDOWS', - 'kernel32.lib', - 'user32.lib', - 'gdi32.lib', - 'winspool.lib', - 'comdlg32.lib', - 'advapi32.lib', - 'shell32.lib', - 'ole32.lib', - 'oleaut32.lib', - 'uuid.lib', - 'odbc32.lib', - 'odbccp32.lib', - ] - - # Optimization - if builder.options.opt == '1': - cxx.defines += ['NDEBUG'] - if cxx.behavior == 'gcc': - cxx.cflags += ['-O3'] - elif cxx.behavior == 'msvc': - cxx.cflags += ['/Ox', '/Zo'] - cxx.linkflags += ['/OPT:ICF', '/OPT:REF'] - - # Debugging - if builder.options.debug == '1': - cxx.defines += ['DEBUG', '_DEBUG'] - if cxx.behavior == 'gcc': - cxx.cflags += ['-g3'] - elif cxx.behavior == 'msvc': - cxx.cflags += ['/Od', '/RTC1'] - - # This needs to be after our optimization flags which could otherwise disable it. - if cxx.family == 'msvc': - # Don't omit the frame pointer. - cxx.cflags += ['/Oy-'] - - # Platform-specifics - if builder.target.platform == 'linux': - cxx.defines += ['_LINUX', 'POSIX', '_FILE_OFFSET_BITS=64'] - if cxx.family == 'gcc': - cxx.linkflags += ['-static-libgcc'] - elif cxx.family == 'clang': - cxx.linkflags += ['-lgcc_eh'] - elif builder.target.platform == 'mac': - cxx.defines += ['OSX', '_OSX', 'POSIX'] - cxx.cflags += ['-mmacosx-version-min=10.5'] - cxx.linkflags += [ - '-mmacosx-version-min=10.5', - '-lc++', - ] - elif builder.target.platform == 'windows': - cxx.defines += ['WIN32', '_WINDOWS'] - - # Finish up. - cxx.defines += [ 'MMS_USE_VERSIONLIB' ] - cxx.includes += [ - os.path.join(builder.sourcePath, 'public'), - ] - if self.use_auto_versioning(): - cxx.defines += ['MMS_GENERATED_BUILD'] - cxx.includes += [ - os.path.join(builder.buildPath, 'includes'), - os.path.join(builder.sourcePath, 'versionlib'), - ] - - def HL2Compiler(self, context, sdk, arch): - compiler = context.cxx.clone() - compiler.cxxincludes += [ - os.path.join(context.currentSourcePath), - os.path.join(context.currentSourcePath, 'sourcehook'), - os.path.join(context.sourcePath, 'loader'), - ] - - defines = ['SE_' + PossibleSDKs[i].define + '=' + PossibleSDKs[i].code for i in PossibleSDKs] - compiler.defines += defines - paths = [['public'], - ['public', 'engine'], - ['public', 'mathlib'], - ['public', 'vstdlib'], - ['public', 'tier0'], ['public', 'tier1']] - if sdk.name == 'episode1' or sdk.name == 'darkm': - paths.append(['public', 'dlls']) - paths.append(['game_shared']) - else: - paths.append(['public', 'game', 'server']) - paths.append(['game', 'shared']) - paths.append(['common']) - - compiler.defines += ['SOURCE_ENGINE=' + sdk.code] - - if sdk.name in ['sdk2013', 'bms'] and compiler.like('gcc'): - # The 2013 SDK already has these in public/tier0/basetypes.h - compiler.defines.remove('stricmp=strcasecmp') - compiler.defines.remove('_stricmp=strcasecmp') - compiler.defines.remove('_snprintf=snprintf') - compiler.defines.remove('_vsnprintf=vsnprintf') - - if compiler.family == 'msvc': - compiler.defines += ['COMPILER_MSVC'] - if arch == 'x86': - compiler.defines += ['COMPILER_MSVC32'] - elif arch == 'x64': - compiler.defines += ['COMPILER_MSVC64'] - - if compiler.version >= 1900: - compiler.linkflags += ['legacy_stdio_definitions.lib'] - else: - compiler.defines += ['COMPILER_GCC'] - - if arch == 'x64': - compiler.defines += ['X64BITS', 'PLATFORM_64BITS'] - - if sdk.name in ['css', 'hl2dm', 'dods', 'sdk2013', 'bms', 'tf2', 'l4d', 'nucleardawn', 'l4d2', 'dota']: - if builder.target.platform in ['linux', 'mac']: - compiler.defines += ['NO_HOOK_MALLOC', 'NO_MALLOC_OVERRIDE'] - - if sdk.name == 'csgo' and builder.target.platform == 'linux': - compiler.linkflags += ['-lstdc++'] - - - for path in paths: - compiler.cxxincludes += [os.path.join(sdk.path, *path)] - - return compiler - - def AddVersioning(self, binary, arch): - if builder.target.platform == 'windows': - binary.sources += ['version.rc'] - binary.compiler.rcdefines += [ - 'BINARY_NAME="{0}"'.format(binary.outputFile), - 'RC_COMPILE' - ] - elif builder.target.platform == 'mac' and binary.type == 'library': - binary.compiler.postlink += [ - '-compatibility_version', '1.0.0', - '-current_version', self.productVersion - ] - if self.use_auto_versioning(): - binary.compiler.linkflags += [self.versionlib[arch]] - binary.compiler.sourcedeps += MMS.generated_headers - if builder.options.breakpad_dump: - binary.compiler.symbol_files = 'separate' - return binary - - def LibraryBuilder(self, compiler, name, arch): - binary = compiler.Library(name) - AppendArchSuffix(binary, name, arch) - self.AddVersioning(binary, arch) - return binary - - def ProgramBuilder(self, compiler, name, arch): - binary = compiler.Program(name) - AppendArchSuffix(binary, name, arch) - self.AddVersioning(binary, arch) - if '-static-libgcc' in binary.compiler.linkflags: - binary.compiler.linkflags.remove('-static-libgcc') - if '-lgcc_eh' in binary.compiler.linkflags: - binary.compiler.linkflags.remove('-lgcc_eh') - if binary.compiler.like('gcc'): - binary.compiler.linkflags += ['-lstdc++'] - return binary - - def StaticLibraryBuilder(self, compiler, name, arch): - binary = compiler.StaticLibrary(name) - AppendArchSuffix(binary, name, arch) - return binary; - - def Library(self, context, name, arch): - compiler = context.cxx.clone() - SetArchFlags(compiler, arch, builder.target.platform) - return self.LibraryBuilder(compiler, name, arch) - - def Program(self, context, name, arch): - compiler = context.cxx.clone() - SetArchFlags(compiler, arch, builder.target.platform) - return self.ProgramBuilder(compiler, name, arch) - - def StaticLibrary(self, context, name, arch): - compiler = context.cxx.clone() - SetArchFlags(compiler, arch, builder.target.platform) - return self.StaticLibraryBuilder(compiler, name, arch) - - def HL2Library(self, context, name, sdk, arch): - compiler = self.HL2Compiler(context, sdk, arch) - - SetArchFlags(compiler, arch, builder.target.platform) - - if builder.target.platform == 'linux': - if sdk.name == 'episode1': - lib_folder = os.path.join(sdk.path, 'linux_sdk') - elif sdk.name in ['sdk2013', 'bms']: - lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux32') - elif arch == 'x64': - lib_folder = os.path.join(sdk.path, 'lib', 'linux64') - else: - lib_folder = os.path.join(sdk.path, 'lib', 'linux') - elif builder.target.platform == 'mac': - if sdk.name in ['sdk2013', 'bms']: - lib_folder = os.path.join(sdk.path, 'lib', 'public', 'osx32') - elif arch == 'x64': - lib_folder = os.path.join(sdk.path, 'lib', 'osx64') - else: - lib_folder = os.path.join(sdk.path, 'lib', 'mac') - - if builder.target.platform in ['linux', 'mac']: - if sdk.name in ['sdk2013', 'bms'] or arch == 'x64': - compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'tier1.a'))] - else: - compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'tier1_i486.a'))] - - if sdk.name in ['blade', 'insurgency', 'doi', 'csgo', 'dota']: - if arch == 'x64': - compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'interfaces.a'))] - else: - compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'interfaces_i486.a'))] - - if sdk.name == 'bms': - compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'mathlib.a'))] - - binary = self.LibraryBuilder(compiler, name, arch) - - dynamic_libs = [] - if builder.target.platform == 'linux': - compiler.linkflags[0:0] = ['-lm'] - if sdk.name in ['css', 'hl2dm', 'dods', 'tf2', 'sdk2013', 'bms', 'nucleardawn', 'l4d2', 'insurgency', 'doi']: - dynamic_libs = ['libtier0_srv.so', 'libvstdlib_srv.so'] - elif arch == 'x64' and sdk.name == 'csgo': - dynamic_libs = ['libtier0_client.so', 'libvstdlib_client.so'] - elif sdk.name in ['l4d', 'blade', 'insurgency', 'doi', 'csgo', 'dota']: - dynamic_libs = ['libtier0.so', 'libvstdlib.so'] - else: - dynamic_libs = ['tier0_i486.so', 'vstdlib_i486.so'] - elif builder.target.platform == 'mac': - binary.compiler.linkflags.append('-liconv') - dynamic_libs = ['libtier0.dylib', 'libvstdlib.dylib'] - elif builder.target.platform == 'windows': - libs = ['tier0', 'tier1', 'vstdlib'] - if sdk.name in ['swarm', 'blade', 'insurgency', 'doi', 'csgo', 'dota']: - libs.append('interfaces') - if sdk.name == 'bms': - libs.append('mathlib') - for lib in libs: - if arch == 'x86': - lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib' - elif arch == 'x64': - lib_path = os.path.join(sdk.path, 'lib', 'public', 'win64', lib) + '.lib' - binary.compiler.linkflags.append(binary.Dep(lib_path)) - - for library in dynamic_libs: - source_path = os.path.join(lib_folder, library) - output_path = os.path.join(binary.localFolder, library) - - def make_linker(source_path, output_path): - def link(context, binary): - cmd_node, (output,) = context.AddSymlink(source_path, output_path) - return output - return link - - linker = make_linker(source_path, output_path) - binary.compiler.linkflags[0:0] = [binary.Dep(library, linker)] - - return binary - -MMS = MMSConfig() -MMS.detectProductVersion() -MMS.detectSDKs() -MMS.configure() - -if MMS.use_auto_versioning(): - MMS.generated_headers = builder.Build( - 'support/buildbot/Versioning', - { 'MMS': MMS } - ) - MMS.versionlib = builder.Build( - 'versionlib/AMBuildScript', - { 'MMS': MMS } - ) - -BuildScripts = [ - 'loader/AMBuilder', - 'core/AMBuilder', -] -if getattr(builder.options, 'enable_tests', False): - BuildScripts += [ - 'core/sourcehook/test/AMBuilder', - ] - -if builder.backend == 'amb2': - BuildScripts += [ - 'support/buildbot/PackageScript', - ] - -builder.Build(BuildScripts, { 'MMS': MMS }) - -if builder.options.breakpad_dump: - builder.Build('support/buildbot/BreakpadSymbols', { 'MMS': MMS }) diff --git a/utils/mmsource/LICENSE.txt b/utils/mmsource/LICENSE.txt deleted file mode 100644 index 2618fa427..000000000 --- a/utils/mmsource/LICENSE.txt +++ /dev/null @@ -1,29 +0,0 @@ -The software is Copyright (C) 2004-2008, Metamod:Source Development Team. - -Metamod:Source is distributed under the "zLib/libpng" license, which is reproduced -below: - ------------------------------------------------------------------------------ - -This software is provided "as-is", without any express or implied warranty. -In no event will the authors be held liable for any damages arising from -the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software in - a product, an acknowledgment in the product documentation would be - appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and must not - be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source distribution. - ------------------------------------------------------------------------------ - -The zLib/libpng license has been approved by the "Open Source Initiative" -organization. diff --git a/utils/mmsource/README.md b/utils/mmsource/README.md deleted file mode 100644 index d0af309ef..000000000 --- a/utils/mmsource/README.md +++ /dev/null @@ -1,14 +0,0 @@ -Metamod:Source -============== - -Metamod:Source - A C++ Plugin Environment and Detour Library for the Source Engine. - -Build instructions: See - -Build snapshots: - -General documentation: - -Detouring with SourceHook: - -Development: diff --git a/utils/mmsource/configure.py b/utils/mmsource/configure.py deleted file mode 100644 index 68d3826a1..000000000 --- a/utils/mmsource/configure.py +++ /dev/null @@ -1,34 +0,0 @@ -# vim: set sts=2 ts=8 sw=2 tw=99 et: -import sys -try: - from ambuild2 import run, util -except: - try: - import ambuild - sys.stderr.write('It looks like you have AMBuild 1 installed, but this project uses AMBuild 2.\n') - sys.stderr.write('Upgrade to the latest version of AMBuild to continue.\n') - except: - sys.stderr.write('AMBuild must be installed to build this project.\n') - sys.stderr.write('http://www.alliedmods.net/ambuild\n') - sys.exit(1) - -def make_objdir_name(p): - return 'obj-' + util.Platform() + '-' + p.target_arch - -parser = run.BuildParser(sourcePath=sys.path[0], api='2.1') -parser.default_arch = 'x86' -parser.default_build_folder = make_objdir_name -parser.options.add_option('--hl2sdk-root', type=str, dest='hl2sdk_root', default=None, - help='Root search folder for HL2SDKs') -parser.options.add_option('--enable-debug', action='store_const', const='1', dest='debug', - help='Enable debugging symbols') -parser.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt', - help='Enable optimization') -parser.options.add_option('-s', '--sdks', default='all', dest='sdks', - help='Build against specified SDKs; valid args are "all", "present", or ' - 'comma-delimited list of engine names (default: %default)') -parser.options.add_option('--enable-tests', default=False, dest='enable_tests', action='store_true', - help='Build tests.') -parser.options.add_option('--breakpad-dump', action='store_true', dest='breakpad_dump', - default=False, help='Dump and upload breakpad symbols') -parser.Configure() diff --git a/utils/mmsource/core/AMBuilder b/utils/mmsource/core/AMBuilder deleted file mode 100644 index f583482c7..000000000 --- a/utils/mmsource/core/AMBuilder +++ /dev/null @@ -1,35 +0,0 @@ -# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: -import os - -for sdk_name in MMS.sdks: - for arch in MMS.archs: - sdk = MMS.sdks[sdk_name] - - if not arch in sdk.platformSpec[builder.target.platform]: - continue - - name = 'metamod.' + sdk.ext - binary = MMS.HL2Library(builder, name, sdk, arch) - - binary.sources += [ - 'metamod.cpp', - 'metamod_console.cpp', - 'metamod_oslink.cpp', - 'metamod_plugins.cpp', - 'metamod_util.cpp', - 'provider/console.cpp', - 'provider/provider_ep2.cpp', - 'sourcehook/sourcehook.cpp', - 'sourcehook/sourcehook_impl_chookidman.cpp', - 'sourcehook/sourcehook_impl_chookmaninfo.cpp', - 'sourcehook/sourcehook_impl_cproto.cpp', - 'sourcehook/sourcehook_impl_cvfnptr.cpp', - 'gamedll_bridge.cpp', - 'vsp_bridge.cpp' - ] - - # Source2 hack. TODO: check this more deterministically, "are we doing an x64 build?" - if arch == 'x86': - binary.sources += ['sourcehook/sourcehook_hookmangen.cpp'] - nodes = builder.Add(binary) - MMS.binaries += [nodes] diff --git a/utils/mmsource/core/IPluginManager.h b/utils/mmsource/core/IPluginManager.h deleted file mode 100644 index ac0b7c033..000000000 --- a/utils/mmsource/core/IPluginManager.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * vim: set ts=4 : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2008 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_METAMOD_IPLUGINMANAGER_H -#define _INCLUDE_METAMOD_IPLUGINMANAGER_H - -/** - * @brief Plugin Manager interface - * @file IPluginManager.h - */ - -#include - -namespace SourceMM -{ - /** - * @brief Load sources - */ - enum - { - Pl_BadLoad=0, - Pl_Console=-1, - Pl_File=-2, - Pl_MinId=1, - }; - - /** - * @brief Status of a plugin at runtime - */ - enum Pl_Status - { - Pl_NotFound=-4, - Pl_Error=-3, - Pl_Refused=-2, - Pl_Paused=-1, - Pl_Running=0, - }; - - /** - * @brief Programmatic management of the "loaded plugin" list. - */ - class ISmmPluginManager - { - public: - /** - * @brief Loads a plugin and returns its id. If this is called before DLLInit(), - * then the plugin is considered to be "hot" - it might refuse its own load later! - * Also, a hot plugin might not have an error message. - * - * @param file String containing file name. - * @param source Specifies who loaded the plugin. - * @param already Whether or not the plugin was already loaded. - * @param error String buffer for error messages. - * @param maxlen Maximum length of buffer. - * @return Id of plugin. - */ - virtual PluginId Load(const char *file, PluginId source, bool &already, char *error, size_t maxlen) =0; - - /** - * @brief Unloads a plugin. - * - * @param id Id of plugin - * @param force True to forcefully unload, false to let plugin opt-out. - * @param error String buffer for error messages - * @param maxlen Maximum length of buffer - * @return True on success, false otherwise - */ - virtual bool Unload(PluginId id, bool force, char *error, size_t maxlen) =0; - - /** - * @brief Pauses a plugin - * - * @param id Id of plugin - * @param error String buffer for error messages - * @param maxlen Maximum length of buffer - * @return True on success, false otherwise - */ - virtual bool Pause(PluginId id, char *error, size_t maxlen) =0; - - /** - * @brief Unpauses a plugin - * - * @param id Id of plugin - * @param error String buffer for error messages - * @param maxlen Maximum length of buffer - * @return True on success, false otherwise - */ - virtual bool Unpause(PluginId id, char *error, size_t maxlen) =0; - - /** - * @brief Unloads all plugins forcefully - * - * @return True on success, false otherwise - */ - virtual bool UnloadAll() =0; - - /** - * @brief Returns information about a plugin - * - * @param id Id of plugin - * @param file Pointer to store filename pointer, or NULL to ignore. - * @param status Pointer to store status, or NULL to ignore. - * @param source Pointer to store source, or NULL to ignore. - * @return True on success, false if not found - */ - virtual bool Query(PluginId id, const char **file, Pl_Status *status, PluginId *source) =0; - - /** - * @brief Checks another plugin's QueryRunning() status. - * - * @param id Id of plugin - * @param error Message buffer - * @param maxlength Size of error buffer - * @return Status value - */ - virtual bool QueryRunning(PluginId id, char *error, size_t maxlength) =0; - - /** - * @brief Returns the handle of a plugin (OS dependent meaning) - * - * @param id Id of plugin - * @param handle Pointer to store handle pointer, or NULL to ignore. - * @return True if plugin id is valid, false otherwise - */ - virtual bool QueryHandle(PluginId id, void **handle) =0; - }; -} - -#if !defined METAMOD_NO_AUTO_NAMESPACE -using namespace SourceMM; -#endif - -#endif //_INCLUDE_PLUGINMANAGER_H - diff --git a/utils/mmsource/core/ISmmAPI.h b/utils/mmsource/core/ISmmAPI.h deleted file mode 100644 index 0788e08fc..000000000 --- a/utils/mmsource/core/ISmmAPI.h +++ /dev/null @@ -1,415 +0,0 @@ -/* - * vim: set ts=4 : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2008 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_ISMM_API_H -#define _INCLUDE_ISMM_API_H - -/** - * @brief Core API calls that are provided to plugins. - * @file ISmmAPI.h - */ - -#include -#include -#include - -#if defined META_NO_HL2SDK -class CGlobalVars; -struct edict_t; -class ConCommandBase; -#else -#include -#endif - -#include -#include - -#define MMIFACE_SOURCEHOOK "ISourceHook" /**< ISourceHook Pointer */ -#define MMIFACE_PLMANAGER "IPluginManager" /**< SourceMM Plugin Functions */ -#define MMIFACE_SH_HOOKMANAUTOGEN "IHookManagerAutoGen" /**< SourceHook::IHookManagerAutoGen Pointer */ -#define IFACE_MAXNUM 999 /**< Maximum interface version */ - -typedef void* (*CreateInterfaceFn)(const char *pName, int *pReturnCode); - -class IServerPluginCallbacks; - -namespace SourceMM -{ - class ISmmPlugin; - class IMetamodListener; - - /** - * The core API that Metamod:Source provides to plugins. - */ - class ISmmAPI - { - public: - /** - * @brief Logs a message through the HL2 log system. - * Note: Newlines are appended automatically. - * - * @param pl Plugin API pointer (used for tagging message) - * @param msg Formatted string. - */ - virtual void LogMsg(ISmmPlugin *pl, const char *msg, ...) =0; - - /** - * @brief Returns an interface factory for the HL2 engine. - * - * @param syn If syn is true, the synthetic wrapper is returned. - * If syn is false, the true function is returned. - * @return CreateInterfaceFn function pointer. - */ - virtual CreateInterfaceFn GetEngineFactory(bool syn=true) =0; - - /** - * @brief Returns an interface factory for the HL2 physics engine. - * - * @param syn If syn is true, the synthetic wrapper is returned. - * If syn is false, the true function is returned. - * @return CreateInterfaceFn function pointer. - */ - virtual CreateInterfaceFn GetPhysicsFactory(bool syn=true) =0; - - /** - * @brief Returns an interface factory for the HL2 file system. - * - * @param syn If syn is true, the synthetic wrapper is returned. - * If syn is false, the true function is returned. - * @return CreateInterfaceFn function pointer. - */ - virtual CreateInterfaceFn GetFileSystemFactory(bool syn=true) =0; - - /** - * @brief Returns an interface factory for the GameDLL. - * - * If syn is false, the true function is returned. - * @return CreateInterfaceFn function pointer. - */ - virtual CreateInterfaceFn GetServerFactory(bool syn=true) =0; - - /** - * @brief Returns a CGlobalVars pointer from the HL2 Engine. - * - * @return CGlobalVars pointer. - */ - virtual CGlobalVars *GetCGlobals() =0; - - /** - * @brief Registers a ConCommandBase. - * - * @param plugin Parent plugin API pointer. - * @param pCommand ConCommandBase to register. - * @return True if successful, false otherwise. - */ - virtual bool RegisterConCommandBase(ISmmPlugin *plugin, ConCommandBase *pCommand) =0; - - /** - * @brief Unregisters a ConCommandBase. - * - * @param plugin Parent plugin API pointer. - * @param pCommand ConCommandBase to unlink. - */ - virtual void UnregisterConCommandBase(ISmmPlugin *plugin, ConCommandBase *pCommand) =0; - - /** - * @brief Prints an unformatted string to the remote server console. - * - * Note: Newlines are not added automatically. - * - * @param str Message string. - */ - virtual void ConPrint(const char *str) =0; - - /** - * @brief Prints a formatted message to the remote server console. - * - * Note: Newlines are not added automatically. - * - * @param fmt Formatted message. - */ - virtual void ConPrintf(const char *fmt, ...) =0; - - /** - * @brief Returns the Metamod Version numbers as major version and - * minor (API) version. Changes to minor version are guaranteed to be - * backwards compatible. Changes to major version are not. - * - * @param major Filled with the major API version number. - * @param minor Filled with the minor API version number. - * @param plvers Filled with the current plugin API version number. - * @param plmin Filled with the minimum plugin API version number - * supported. - */ - virtual void GetApiVersions(int &major, int &minor, int &plvers, int &plmin) =0; - - /** - * @brief Returns sourcehook API version and implementation version. - * - * @param shvers Filled with the SourceHook API version number. - * @param shimpl Filled with the SourceHook implementation number. - */ - virtual void GetShVersions(int &shvers, int &shimpl) =0; - - /** - * @brief Adds a Metamod listener. - * - * @param plugin Plugin interface pointer. - * @param pListener Listener interface pointer to add. - */ - virtual void AddListener(ISmmPlugin *plugin, IMetamodListener *pListener) =0; - - /** - * @brief Queries the metamod factory - * - * @param iface String containing interface name - * @param ret Optional pointer to store return status - * @param id Optional pointer to store id of plugin that - * overrode interface, 0 if none - * @return Returned pointer - */ - virtual void *MetaFactory(const char *iface, int *ret, PluginId *id) =0; - - /** - * @brief Given a base interface name, such as ServerGameDLL or - * ServerGameDLL003, reformats the string to increase the number, then - * returns the new number. This is the base function to InterfaceSearch() - * and VInterfaceMatch(). - * - * @param iface Input/output interface name. Must be writable. - * @param maxlength Maximum length of iface buffer. Must be at least - * strlen(iface)+4 chars. - * @return The newly incremented iface version number. - * @deprecated Use InterfaceSearch() or VInterfaceMatch instead. - */ - virtual int FormatIface(char iface[], unsigned int maxlength) =0; - - /** - * @brief Searches for an interface, eliminating the need to loop - * through FormatIface(). - * - * @param fn InterfaceFactory function. - * @param iface Interface string name. - * @param max Maximum version to look up. - * @param ret Last return code from interface factory function. - * @return Interface pointer, or NULL if not found. - */ - virtual void *InterfaceSearch(CreateInterfaceFn fn, - const char *iface, - int max, - int *ret) =0; - - /** - * @brief Returns the base directory of the game/server, equivalent to - * IVEngineServer::GetGameDir(), except the path is absolute. - * - * @return Static pointer to game's absolute basedir. - */ - virtual const char *GetBaseDir() =0; - - /** - * @brief Formats a file path to the local OS. - * - * Does not include any base directories. Note that all slashes and - * black slashes are reverted to the local OS's expectancy. - * - * @param buffer Destination buffer to store path. - * @param len Maximum length of buffer, including null - * terminator. - * @param fmt Formatted string. - * @param ... Arguments in the string. - * @return Number of bytes written, not including the null - * terminator. - */ - virtual size_t PathFormat(char *buffer, size_t len, const char *fmt, ...) =0; - - /** - * @brief Prints text in the specified client's console. Same as - * IVEngineServer::ClientPrintf except that it allows for string - * formatting. - * - * @param client Client edict pointer. - * @param fmt Formatted string to print to the client. - */ - virtual void ClientConPrintf(edict_t *client, const char *fmt, ...) =0; - - /** - * @brief Wrapper around InterfaceSearch(). Assumes no maximum. - * This is designed to replace the fact that searches only went upwards. - * The "V" is intended to convey that this is for Valve formatted - * interface strings. - * - * @param fn Interface factory function. - * @param iface Interface string. - * @param min Minimum value to search from. If zero, searching - * begins from the first available version regardless - * of the interface. Note that this can return - * interfaces EARLIER than the version specified. A - * value of -1 (default) specifies the string version - * as the minimum. Any other value specifices the - * minimum value to search from. - * @return Interface pointer, or NULL if not found. - */ - virtual void *VInterfaceMatch(CreateInterfaceFn fn, - const char *iface, - int min=-1) =0; - - /** - * @brief Tells SourceMM to add VSP hooking capability to plugins. - * - * Since this potentially uses more resources than it would otherwise, - * plugins have to explicitly enable the feature. Whether requested or - * not, if it is enabled, all plugins will get a pointer to the VSP - * listener through IMetamodListener. This will not be called more than - * once for a given plugin; if it is requested more than once, each - * successive call will only give the pointer to plugins which have not - * yet received it. - */ - virtual void EnableVSPListener() =0; - - /** - * @brief Returns the interface version of the GameDLL's IServerGameDLL - * implementation. - * - * @return Interface version of the loaded IServerGameDLL. - */ - virtual int GetGameDLLVersion() =0; - - /** - * @brief Returns the number of user messages in the GameDLL. - * - * @return Number of user messages, or -1 if SourceMM has - * failed to get user message list. - */ - virtual int GetUserMessageCount() =0; - - /** - * @brief Returns the index of the specified user message. - * - * @param name User message name. - * @param size Optional pointer to store size of user message. - * @return Message index, or -1 on failure. - */ - virtual int FindUserMessage(const char *name, int *size=NULL) =0; - - /** - * @brief Returns the name of the specified user message. - * - * @param index User message index. - * @param size Optional pointer to store size of user message. - * @return Message name, or NULL on failure. - */ - virtual const char *GetUserMessage(int index, int *size=NULL) =0; - - /** - * @brief Returns the highest interface version of IServerPluginCallbacks - * that the engine supports. This is useful for games that run on older - * versions of the Source engine, such as The Ship. - * - * @return Highest interface version of IServerPluginCallbacks. - * Returns 0 if SourceMM's VSP listener isn't - * currently enabled. - * @deprecated Use GetVSPInfo() instead. - */ - virtual int GetVSPVersion() =0; - - /** - * @brief Returns the engine interface that MM:S is using as a backend. - * - * The values will be one of the SOURCE_ENGINE_* constants from the top - * of this file. - * - * @return A SOURCE_ENGINE_* constant value. - */ - virtual int GetSourceEngineBuild() =0; - - /** - * @brief Returns the VSP listener loaded. - * - * This is useful for late-loading plugins which need to decide whether - * to add a listener or not (or need to get the pointer at all). - * - * @param pVersion Optional pointer to store the VSP version. - * @return IServerPluginCallbacks pointer, or NULL if an - * IMetamodListener event has yet to occur for - * EnableVSPListener(). - */ - virtual IServerPluginCallbacks *GetVSPInfo(int *pVersion) =0; - - /** - * @brief Formats a string. This is a platform safe wrapper around - * snprintf/_snprintf. - * - * @param buffer Buffer to write to. - * @param maxlength Maximum length of the buffer. - * @param format Format specifiers. - * @param ... Format arguments. - * @return Number of bytes actually written, not including - * the null terminator. - */ - virtual size_t Format(char *buffer, - size_t maxlength, - const char *format, - ...) =0; - - /** - * @brief Formats a string. This is a platform safe wrapper around - * vsnprintf/_vsnprintf. - * - * @param buffer Buffer to write to. - * @param maxlength Maximum length of the buffer. - * @param format Format specifiers. - * @param ap Format argument list. - * @return Number of bytes actually written, not including the - * null terminator. - */ - virtual size_t FormatArgs(char *buffer, - size_t maxlength, - const char *format, - va_list ap) =0; - }; -} - -#if !defined METAMOD_NO_AUTO_NAMESPACE -using namespace SourceMM; -#endif - -/** - * Version History - * - * 1.1.0 Bumped API to 1:0. The breaking changes occurred in SourceHook and the plugin API. - * 1.1.2 Added API call for generating iface names. - * 1.2 Added API more helper functions and new SourceHook version. - * 1.2.2 Added API for printing to client console (with string formatting). - * 1.3 Added new interface search API. - * 1.4 Added VSP listener and user message API. - * 1.5.0 Added API for getting highest supported version of IServerPluginCallbacks. - * 1.6.0 Added API for Orange Box. Broke backwards compatibility. - */ - -#endif //_INCLUDE_ISMM_API_H - diff --git a/utils/mmsource/core/ISmmPlugin.h b/utils/mmsource/core/ISmmPlugin.h deleted file mode 100644 index d15dfc548..000000000 --- a/utils/mmsource/core/ISmmPlugin.h +++ /dev/null @@ -1,552 +0,0 @@ -/* - * vim: set ts=4 : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2008 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_ISMM_PLUGIN_H -#define _INCLUDE_ISMM_PLUGIN_H - -/** - * @brief Plugin API interface. - * @file ISmmPlugin.h These are callbacks that plugins can implement without hooks. - * The pure-virtual ISmmPlugin callbacks must be implemented for the load to load. - */ - -#include -#include -#include -#include - -#ifndef META_NO_HL2SDK -#if SOURCE_ENGINE == SE_DOTA -#include -#else -#include -#endif -#endif - -class IServerPluginCallbacks; - -// Interface return status, binary-compatible with HL2SDK's IFACE_OK and IFACE_FAILED. -enum -{ - META_IFACE_OK = 0, - META_IFACE_FAILED -}; - -namespace SourceMM -{ - class ISmmAPI; - - /** - * @brief Callbacks that a plugin must expose. - */ - class ISmmPlugin - { - public: - /** - * @brief Called to request the plugin's API version. - * - * This is the first callback invoked, and always remains at the top - * of the virtual table. - * - * @return Plugin API version. - */ - virtual int GetApiVersion() - { - return METAMOD_PLAPI_VERSION; - } - - /** - * @brief Virtual destructor so GCC doesn't complain. - */ - virtual ~ISmmPlugin() - { - } - - public: - /** - * @brief Called on plugin load. - * - * This is called as DLLInit() executes - after the parameters are - * known, but before the original GameDLL function is called. - * Therefore, you cannot hook it, but you don't need to - Load() is - * basically your hook. You can override factories before the engine - * and gamedll exchange them. However, take care to note that if your - * plugin is unloaded, and the gamedll/engine have cached an interface - * you've passed, something will definitely crash. Be careful. - * - * @param id Internal id of plugin. Saved globally by PLUGIN_SAVEVARS() - * @param ismm External API for SourceMM. Saved globally by PLUGIN_SAVEVARS() - * @param error Error message buffer - * @param maxlength Size of error message buffer - * @param late Set to true if your plugin was loaded late (not at server load). - * @return True if successful, return false to reject the load. - */ - virtual bool Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlength, bool late) =0; - - /** - * @brief Called when all plugins have been loaded. - * - * This is called after DLLInit(), and thus the mod has been mostly initialized. - * It is also safe to assume that all other (automatically loaded) plugins are now - * ready to start interacting, because they are all loaded. - */ - virtual void AllPluginsLoaded() - { - } - - /** - * @brief Called when your plugin is "queried". - * - * This is useful for rejecting a loaded state. For example, if your - * plugin wants to stop operating, it can simply return false and copy - * an error message. This will notify other plugins or MM:S of - * something bad that happened. MM:S will not cache the return state, - * so if you return false, your plugin will not actually be paused or - * unloaded. This callback will be called when: - * - Another plugin requests it - * - Someone types "meta list", it will show up as "REFUSED" - * - When Metamod need to re-check the plugin's status - * - If the plugin does something like overload a factory, Metamod - * will make sure the Query() returns true before calling it. - * Also note that this query will only override Metamod when the - * plugin is running and not paused. - * - * @param error Buffer for error message, or NULL if none. - * @param maxlen Maximum length of error buffer. - * @return Status code - true for okay, false for badness. - */ - virtual bool QueryRunning(char *error, size_t maxlen) - { - return true; - } - - /** - * @brief Called on plugin unload. You can return false if you know - * your plugin is not capable of restoring critical states it modifies. - * - * @param error Error message buffer - * @param maxlen Size of error message buffer - * @return True on success, return false to request no unload. - */ - virtual bool Unload(char *error, size_t maxlen) - { - return true; - } - - /** - * @brief Called on plugin pause. - * - * @param error Error message buffer - * @param maxlen Size of error message buffer - * @return True on success, return false to request no pause. - */ - virtual bool Pause(char *error, size_t maxlen) - { - return true; - } - - /** - * @brief Called on plugin unpause. - * - * @param error Error message buffer - * @param maxlen Size of error message buffer - * @return True on success, return false to request no unpause. - */ - virtual bool Unpause(char *error, size_t maxlen) - { - return true; - } - public: - /** @brief Return author as string */ - virtual const char *GetAuthor() =0; - - /** @brief Return plugin name as string */ - virtual const char *GetName() =0; - - /** @brief Return a description as string */ - virtual const char *GetDescription() =0; - - /** @brief Return a URL as string */ - virtual const char *GetURL() =0; - - /** @brief Return quick license code as string */ - virtual const char *GetLicense() =0; - - /** @brief Return version as string */ - virtual const char *GetVersion() =0; - - /** @brief Return author as string */ - virtual const char *GetDate() =0; - - /** @brief Return author as string */ - virtual const char *GetLogTag() =0; - }; - - /** - * @brief Various events that Metamod can fire. - */ - class IMetamodListener - { - public: - /** - * @brief Called when a plugin is loaded. - * - * @param id Id of the plugin. - */ - virtual void OnPluginLoad(PluginId id) - { - } - - /** - * @brief Called when a plugin is unloaded. - * - * @param id Id of the plugin. - */ - virtual void OnPluginUnload(PluginId id) - { - } - - /** - * @brief Called when a plugin is paused. - * - * @param id Id of the plugin. - */ - virtual void OnPluginPause(PluginId id) - { - } - - /** - * @brief Called when a plugin is unpaused. - * - * @param id Id of the plugin. - */ - virtual void OnPluginUnpause(PluginId id) - { - } - - /** - * @brief Called when the level is loaded (after GameInit, before - * ServerActivate). - * - * To override this, hook IServerGameDLL::LevelInit(). - * - * @param pMapName Name of the map. - * @param pMapEntities Lump string of the map entities, in KeyValues - * format. - * @param pOldLevel Unknown. - * @param pLandmarkName Unknown. - * @param loadGame Unknown. - * @param background Unknown. - */ - virtual void OnLevelInit(char const *pMapName, - char const *pMapEntities, - char const *pOldLevel, - char const *pLandmarkName, - bool loadGame, - bool background) - { - } - - /** - * @brief Called when the level is shut down. May be called more than - * once. - */ - virtual void OnLevelShutdown() - { - } - - /** - * @brief Called when engineFactory() is used through Metamod:Source's - * wrapper. This can be used to provide interfaces to other plugins or - * the GameDLL. - * - * If ret is passed, you should fill it with META_IFACE_OK or META_IFACE_FAILED. - * - * @param iface Interface string. - * @param ret Optional pointer to store return code. - * @return Generic pointer to the interface, or NULL if - * not found. - */ - virtual void *OnEngineQuery(const char *iface, int *ret) - { - if (ret) - { - *ret = META_IFACE_FAILED; - } - - return NULL; - } - - /** - * @brief Called when the physics factory is used through - * Metamod:Source's wrapper. This can be used to provide interfaces to - * other plugins. - * - * If ret is passed, you should fill it with META_IFACE_OK or META_IFACE_FAILED. - * - * @param iface Interface string. - * @param ret Optional pointer to store return code. - * @return Generic pointer to the interface, or NULL if - * not found. - */ - virtual void *OnPhysicsQuery(const char *iface, int *ret) - { - if (ret) - { - *ret = META_IFACE_FAILED; - } - - return NULL; - } - - /** - * @brief Called when the filesystem factory is used through - * Metamod:Source's wrapper. This can be used to provide interfaces to - * other plugins. - * - * If ret is passed, you should fill it with META_IFACE_OK or META_IFACE_FAILED. - * - * @param iface Interface string. - * @param ret Optional pointer to store return code. - * @return Generic pointer to the interface, or NULL if not - * found. - */ - virtual void *OnFileSystemQuery(const char *iface, int *ret) - { - if (ret) - { - *ret = META_IFACE_FAILED; - } - - return NULL; - } - - /** - * @brief Called when the server DLL's factory is used through - * Metamod:Source's wrapper. This can be used to provide interfaces to - * other plugins. - * - * If ret is passed, you should fill it with META_IFACE_OK or META_IFACE_FAILED. - * - * @param iface Interface string. - * @param ret Optional pointer to store return code. - * @return Generic pointer to the interface, or NULL if not - * found. - */ - virtual void *OnGameDLLQuery(const char *iface, int *ret) - { - if (ret) - { - *ret = META_IFACE_FAILED; - } - - return NULL; - } - - /** - * @brief Called when Metamod's own factory is invoked. - * This can be used to provide interfaces to other plugins. - * - * If ret is passed, you should fill it with META_IFACE_OK or META_IFACE_FAILED. - * - * @param iface Interface string. - * @param ret Optional pointer to store return code. - * @return Generic pointer to the interface, or NULL if not - * found. - */ - virtual void *OnMetamodQuery(const char *iface, int *ret) - { - if (ret) - { - *ret = META_IFACE_FAILED; - } - - return NULL; - } - - /** - * @brief Called when Metamod:Source acquires a valid - * IServerPluginCallbacks pointer to be used for hooking by plugins. - * - * This will only be called after a call to ISmmAPI::EnableVSPListener(). - * If called before GameInit, this callback will occur before LevelInit. - * Otherwise, it will be called on the first call after that. - * - * This callback is provided to all plugins regardless of which (or how - * many) called EnableVSPListener(), but only if at least one did in - * fact enable it, and only once for all plugins. That is, a late - * loading plugin should use ISmmAPI::GetVSPInfo() before relying on - * this callback. - * - * This callback is never called if Metamod:Source is in VSP mode. - * If in VSP mode, a VSP instance is automatically and always available - * via ISmmAPI::GetVSPInfo(), which should be called anyway (to handle - * late loading cases). - * - * @param iface Interface pointer. If NULL, then the VSP - * listening construct failed to initialize and - * is not available. - */ - virtual void OnVSPListening(IServerPluginCallbacks *iface) - { - } - - /** - * @brief Called when Metamod:Source is about to remove a concommand or - * convar. This can also be called if ISmmAPI::UnregisterConCmdBase is - * used by a plugin. - * - * @param id Id of the plugin that created the concommand or - * convar. - * @param pCommand Pointer to concommand or convar that is being - * removed. - */ - virtual void OnUnlinkConCommandBase(PluginId id, ConCommandBase *pCommand) - { - } - }; -} - -#if !defined METAMOD_NO_AUTO_NAMESPACE -using namespace SourceMM; -#endif - -#define PL_EXPOSURE CreateInterface -#define PL_EXPOSURE_C "CreateInterface" - -/** - * @brief Exposes the plugin to the MM:S loader. - * - * @param name Deprecated - should be a variable name (like name). - * @param var Name of the variable that contains the singleton. - * This macro automatically takes the address of it, so - * you should not pass a pointer to your plugin's - * singleton. - */ -#ifdef META_NO_HL2SDK -#define PL_EXPOSURE_FUNC(name, var) \ - SMM_API void *PL_EXPOSURE(const char *name, int *code) { \ - if (name && !strcmp(name, METAMOD_PLAPI_NAME)) { \ - return static_cast(&var); \ - } \ - return NULL; \ - } - -#else -// First param should be actual classname, not iface name, but we don't have that and it doesn't matter here. -#define PL_EXPOSURE_FUNC(name, var) EXPOSE_SINGLE_INTERFACE_GLOBALVAR(ISmmPlugin, ISmmPlugin, METAMOD_PLAPI_NAME, var); -#endif - -#define PLUGIN_EXPOSE(name, var) \ - ISmmAPI *g_SMAPI = NULL; \ - ISmmPlugin *g_PLAPI = NULL; \ - PluginId g_PLID = (PluginId)0; \ - SourceHook::ISourceHook *g_SHPtr = NULL; \ - PL_EXPOSURE_FUNC(name, var) - - - - - -/** - * @brief This should be in one of your header files, if you wish - * to use values like g_SHPtr in other files. - */ -#define PLUGIN_GLOBALVARS() \ - extern SourceHook::ISourceHook *g_SHPtr; \ - extern ISmmAPI *g_SMAPI; \ - extern ISmmPlugin *g_PLAPI; \ - extern PluginId g_PLID; - -/** - * @brief This should be the first line in your Load callback. - */ -#define PLUGIN_SAVEVARS() \ - g_SMAPI = ismm; \ - g_SHPtr = static_cast(ismm->MetaFactory(MMIFACE_SOURCEHOOK, NULL, NULL)); \ - g_PLAPI = static_cast(this); \ - g_PLID = id; - -#define META_LOG g_SMAPI->LogMsg -#define META_REGCMD(name) g_SMAPI->RegisterConCommandBase(g_PLAPI, name##_command) -#define META_REGCVAR(var) g_SMAPI->RegisterConCommandBase(g_PLAPI, var) -#define META_UNREGCMD(name) g_SMAPI->UnregisterConCommandBase(g_PLAPI, name##_command) -#define META_UNREGCVAR(var) g_SMAPI->UnregisterConCommandBase(g_PLAPI, var) -#define META_CONPRINT g_SMAPI->ConPrint -#define META_CONPRINTF g_SMAPI->ConPrintf - -/* Probably should use this up above someday */ -#define CONCMD_VARNAME(name) name##_command - -#if !defined SMM_API -#if defined __WIN32__ || defined _WIN32 || defined WIN32 - #define SMM_API extern "C" __declspec(dllexport) -#elif defined __GNUC__ - #define SMM_API extern "C" __attribute__ ((visibility("default"))) -#endif -#endif //!defined SMM_API - -/** - * @brief Macro for automatically getting a current or newer Valve interface. - * - * @param v_factory Factory method to use from ISmmAPI (such as engineFactory). - * @param v_var Variable name to store into. - * @param v_type Interface type (do not include the pointer/asterisk). - * @param v_name Interface name. - */ -#define GET_V_IFACE_CURRENT(v_factory, v_var, v_type, v_name) \ - v_var = (v_type *)ismm->VInterfaceMatch(ismm->v_factory(), v_name); \ - if (!v_var) \ - { \ - if (error && maxlen) \ - { \ - ismm->Format(error, maxlen, "Could not find interface: %s", v_name); \ - } \ - return false; \ - } - - /** - * @brief Same as GET_V_IFACE, except searches for any. - * - * @param v_factory Factory method to use from ISmmAPI (such as engineFactory). - * @param v_var Variable name to store into. - * @param v_type Interface type (do not include the pointer/asterisk). - * @param v_name Interface name. - */ -#define GET_V_IFACE_ANY(v_factory, v_var, v_type, v_name) \ - v_var = (v_type *)ismm->VInterfaceMatch(ismm->v_factory(), v_name, 0); \ - if (!v_var) \ - { \ - if (error && maxlen) \ - { \ - ismm->Format(error, maxlen, "Could not find interface: %s", v_name); \ - } \ - return false; \ - } - -#endif //_INCLUDE_ISMM_PLUGIN_H - diff --git a/utils/mmsource/core/ISmmPluginExt.h b/utils/mmsource/core/ISmmPluginExt.h deleted file mode 100644 index 351b90656..000000000 --- a/utils/mmsource/core/ISmmPluginExt.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2009 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#ifndef _INCLUDE_METAMOD_SOURCE_PLUGIN_EXT_H_ -#define _INCLUDE_METAMOD_SOURCE_PLUGIN_EXT_H_ - -#include - -/** - * @file ISmmPluginExt.h Provides an alternate method for loading plugins, - * without needing to include the default headers and all their Half-Life baggage. - * - * @brief Definitions for extended plugin loading. - */ - -#define SOURCE_ENGINE_UNKNOWN 0 /**< Could not determine the engine version */ -#define SOURCE_ENGINE_ORIGINAL 1 /**< Original Source Engine (used by The Ship) */ -#define SOURCE_ENGINE_EPISODEONE 2 /**< Episode 1 Source Engine (second major SDK) */ -#define SOURCE_ENGINE_ORANGEBOX 3 /**< Orange Box Source Engine (third major SDK) */ -#define SOURCE_ENGINE_LEFT4DEAD 4 /**< Left 4 Dead */ -#define SOURCE_ENGINE_DARKMESSIAH 5 /**< Dark Messiah Multiplayer (based on original engine) */ -#define SOURCE_ENGINE_ORANGEBOXVALVE_DEPRECATED 6 /**< Orange Box Source Engine for Valve games (TF2/DOD:S/HL2DM) */ -#define SOURCE_ENGINE_LEFT4DEAD2 7 /**< Left 4 Dead 2 */ -#define SOURCE_ENGINE_ALIENSWARM 8 /**< Alien Swarm */ -#define SOURCE_ENGINE_BLOODYGOODTIME 9 /**< Bloody Good Time */ -#define SOURCE_ENGINE_EYE 10 /**< E.Y.E Divine Cybermancy */ -#define SOURCE_ENGINE_PORTAL2 11 /**< Portal 2 */ -#define SOURCE_ENGINE_CSGO 12 /**< Counter-Strike: Global Offensive */ -#define SOURCE_ENGINE_CSS 13 /**< Counter-Strike: Source (sometimes older version of Orange Box Valve) */ -#define SOURCE_ENGINE_DOTA 14 /**< Dota 2 */ -#define SOURCE_ENGINE_HL2DM 15 /**< Half-Life 2 Deathmatch */ -#define SOURCE_ENGINE_DODS 16 /**< Day of Defeat: Source */ -#define SOURCE_ENGINE_TF2 17 /**< Team Fortress 2 */ -#define SOURCE_ENGINE_NUCLEARDAWN 18 /**< Nuclear Dawn */ -#define SOURCE_ENGINE_SDK2013 19 /**< Source SDK 2013 */ -#define SOURCE_ENGINE_BLADE 20 /**< Blade Symphony */ -#define SOURCE_ENGINE_INSURGENCY 21 /**< Insurgency */ -#define SOURCE_ENGINE_CONTAGION 22 /**< Contagion */ -#define SOURCE_ENGINE_BMS 23 /**< Black Mesa Multiplayer */ -#define SOURCE_ENGINE_DOI 24 /**< Day of Infamy */ - -#define METAMOD_PLAPI_VERSION 16 /**< Version of this header file */ -#define METAMOD_PLAPI_NAME "ISmmPlugin" /**< Name of the plugin interface */ - -namespace SourceMM -{ - class ISmmPlugin; - class ISmmAPI; - - /** - * @brief Used to uniquely identify plugins. - */ - typedef int PluginId; - - #define METAMOD_FAIL_API_V1 7 /**< Minimum API version to detect for V1 */ - #define METAMOD_FAIL_API_V2 14 /**< Minimum API version to detect for V2 */ - - /** - * Use this to instantiate a plugin that will always fail. - * This class definition works against major API versions 1 and 2. - */ - class ISmmFailPlugin - { - public: - /** - * @brief You must return METAMOD_FAIL_API_V1 or METAMOD_FAIL_API_V2 here, - * depending on which Metamod:Source version you detected. - */ - virtual int GetApiVersion() = 0; - - /** - * @brief Do not change. - */ - virtual ~ISmmFailPlugin() - { - } - - /** - * @brief Return false here -- fill in the error buffer appropriately. - * - * Do not ever return true. If you do, MM:S will crash because the class layout is - * incomplete against ISmmPlugin. - * - * @param id Ignore. - * @param ismm Ignore. - * @param error Error buffer (must be filled). - * @param maxlength Maximum size of error buffer. - * @param late Ignore. - * @return Must return false. - */ - virtual bool Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlength, bool late) =0; - }; -} - -typedef SourceMM::ISmmPlugin METAMOD_PLUGIN; - -/** - * @brief Contains version information. - */ -struct MetamodVersionInfo -{ - int api_major; /**< ISmmAPI major version */ - int api_minor; /**< ISmmAPI minor version */ - int sh_iface; /**< SourceHook interface version */ - int sh_impl; /**< SourceHook implementation version */ - int pl_min; /**< Plugin API minimum version */ - int pl_max; /**< Plugin API maximum version */ - int source_engine; /**< Source Engine version (SOURCE_* constants) */ - const char *game_dir; /**< Game directory name */ - - /** - * @brief Returns the game folder. - * - * @return Game folder, or NULL if not available on this version - * of Metamod:Source. - */ - inline const char *GetGameDir() const - { - if (pl_max < 15) - return NULL; - return game_dir; - } -}; - -/** - * @brief Contains information about loading a plugin. - */ -struct MetamodLoaderInfo -{ - const char *pl_file; /**< File path to the plugin being loaded. */ - const char *pl_path; /**< Folder path containing the plugin. */ -}; - -/** - * @brief If a function of this type is exposed as "CreateInterface_MMS", then - * Metamod:Source will attempt to call this function before calling - * CreateInterface. If this function returns a valid ISmmPlugin pointer, then - * CreateInterface will not be called. - * - * This is useful for implementing a mini-loader plugin for multiple versions. - * - * @param mvi MetamodVersionInfo structure. - * @param mli MetamodLoaderInfo structure. - * @return ISmmAPI pointer, or NULL if none. - */ -typedef METAMOD_PLUGIN *(*METAMOD_FN_LOAD)(const MetamodVersionInfo *mvi, - const MetamodLoaderInfo *mli); - -/** - * @brief If a function of this type is exposed as "UnloadInterface_MMS", then - * Metamod:Source will attempt to call this function after calling - * ISmmAPI::Unload(), and before closing the library. This lets loader plugins - * clean up before exiting. - * - * Note: This function will be ignored unless CreateInterfce_MMS was exposed. - * It may be called even if ISmmAPI::Unload() could not be called. - */ -typedef void (*METAMOD_FN_UNLOAD)(); - -/** - * @brief Original type of load function. CreateInterfaceFn from Valve. - * - * Plugins will expose this as "CreateInterface". - */ -typedef void *(*METAMOD_FN_ORIG_LOAD)(const char *, int *); - -#endif //INCLUDE_METAMOD_SOURCE_PLUGIN_EXT_H_ - diff --git a/utils/mmsource/core/Makefile b/utils/mmsource/core/Makefile deleted file mode 100644 index 3c89eb1a9..000000000 --- a/utils/mmsource/core/Makefile +++ /dev/null @@ -1,183 +0,0 @@ -# (C)2004-2010 SourceMod Development Team -# Makefile written by David "BAILOPAN" Anderson - -HL2SDK_OB = ../../hl2sdk-ob -HL2SDK_CSS = ../../hl2sdk-css -HL2SDK_OB_VALVE = ../../hl2sdk-ob-valve -HL2SDK_L4D = ../../hl2sdk-l4d -HL2SDK_L4D2 = ../../hl2sdk-l4d2 -HL2SDK_CSGO = ../../hl2sdk-csgo - -##################################### -### EDIT BELOW FOR OTHER PROJECTS ### -##################################### - -OBJECTS = metamod.cpp \ - metamod_util.cpp \ - metamod_console.cpp \ - metamod_oslink.cpp \ - metamod_plugins.cpp \ - sourcehook/sourcehook.cpp \ - sourcehook/sourcehook_hookmangen.cpp \ - sourcehook/sourcehook_impl_chookidman.cpp \ - sourcehook/sourcehook_impl_chookmaninfo.cpp \ - sourcehook/sourcehook_impl_cproto.cpp \ - sourcehook/sourcehook_impl_cvfnptr.cpp \ - provider/console.cpp \ - provider/provider_ep2.cpp \ - vsp_bridge.cpp \ - gamedll_bridge.cpp - -############################################## -### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ### -############################################## - -C_OPT_FLAGS = -DNDEBUG -O3 -funroll-loops -pipe -fno-strict-aliasing -C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3 -C_GCC4_FLAGS = -fvisibility=hidden -CPP_GCC4_FLAGS = -fvisibility-inlines-hidden -CPP = gcc - -override ENGSET = false -ifeq "$(ENGINE)" "orangebox" - HL2SDK = $(HL2SDK_OB) - HL2PUB = $(HL2SDK)/public - HL2LIB = $(HL2SDK)/lib/linux - CFLAGS += -DSOURCE_ENGINE=3 - INCLUDE += -I$(HL2SDK)/public/game/server - BINARY = metamod.2.ep2.so - LIB_SUFFIX = _i486.so - override ENGSET = true -endif -ifeq "$(ENGINE)" "css" - HL2SDK = $(HL2SDK_CSS) - HL2PUB = $(HL2SDK)/public - HL2LIB = $(HL2SDK)/lib/linux - CFLAGS += -DSOURCE_ENGINE=6 - INCLUDE += -I$(HL2SDK)/public/game/server - BINARY = metamod.2.css.so - LIB_PREFIX = lib - LIB_SUFFIX = _srv.so - override ENGSET = true -endif -ifeq "$(ENGINE)" "orangeboxvalve" - HL2SDK = $(HL2SDK_OB_VALVE) - HL2PUB = $(HL2SDK)/public - HL2LIB = $(HL2SDK)/lib/linux - CFLAGS += -DSOURCE_ENGINE=7 - INCLUDE += -I$(HL2SDK)/public/game/server - BINARY = metamod.2.ep2v.so - LIB_PREFIX = lib - LIB_SUFFIX = _srv.so - override ENGSET = true -endif -ifeq "$(ENGINE)" "left4dead" - HL2SDK = $(HL2SDK_L4D) - HL2PUB = $(HL2SDK)/public - HL2LIB = $(HL2SDK)/lib/linux - CFLAGS += -DSOURCE_ENGINE=8 - INCLUDE += -I$(HL2SDK)/public/game/server - BINARY = metamod.2.l4d.so - LIB_PREFIX = lib - LIB_SUFFIX = .so - override ENGSET = true -endif -ifeq "$(ENGINE)" "left4dead2" - HL2SDK = $(HL2SDK_L4D2) - HL2PUB = $(HL2SDK)/public - HL2LIB = $(HL2SDK)/lib/linux - CFLAGS += -DSOURCE_ENGINE=9 - INCLUDE += -I$(HL2SDK)/public/game/server - BINARY = metamod.2.l4d2.so - LIB_PREFIX = lib - LIB_SUFFIX = _srv.so - override ENGSET = true -endif -ifeq "$(ENGINE)" "csgo" - HL2SDK = $(HL2SDK_CSGO) - HL2PUB = $(HL2SDK)/public - HL2LIB = $(HL2SDK)/lib/linux - CFLAGS += -DSOURCE_ENGINE=12 - INCLUDE += -I$(HL2SDK)/public/game/server - BINARY = metamod.2.csgo.so - LIB_PREFIX = lib - LIB_SUFFIX = .so - override ENGSET = true -endif - -CFLAGS += -DSE_EPISODEONE=1 -DSE_DARKMESSIAH=2 -DSE_ORANGEBOX=3 -DSE_BLOODYGOODTIME=4 -DSE_EYE=5 \ - -DSE_CSS=6 -DSE_ORANGEBOXVALVE=7 -DSE_LEFT4DEAD=8 -DSE_LEFT4DEAD2=9 -DSE_ALIENSWARM=10 \ - -DSE_PORTAL2=11 -DSE_CSGO=12 - -ifeq "$(ENGINE)" "csgo" - LINK += $(HL2LIB)/interfaces_i486.a -endif - -LINK += $(HL2LIB)/tier1_i486.a $(LIB_PREFIX)vstdlib$(LIB_SUFFIX) $(LIB_PREFIX)tier0$(LIB_SUFFIX) \ - -static-libgcc - -INCLUDE += -I. -I.. -I../public -I$(HL2PUB) -I$(HL2PUB)/engine -I$(HL2PUB)/mathlib -I$(HL2PUB)/vstdlib \ - -I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 -I. -Isourcehook -I../loader - -CFLAGS += -D_LINUX -DPOSIX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp \ - -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca \ - -Dstrcmpi=strcasecmp -Wall -Werror -Wno-uninitialized -mfpmath=sse -msse -DHAVE_STDINT_H -m32 \ - -DCOMPILER_GCC -CPPFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti - -################################################ -### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ### -################################################ - -ifeq "$(DEBUG)" "true" - BIN_DIR = Debug.$(ENGINE) - CFLAGS += $(C_DEBUG_FLAGS) -else - BIN_DIR = Release.$(ENGINE) - CFLAGS += $(C_OPT_FLAGS) -endif - -GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1) -ifeq "$(GCC_VERSION)" "4" - CFLAGS += $(C_GCC4_FLAGS) - CPPFLAGS += $(CPP_GCC4_FLAGS) -endif - -OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o) -OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o) - -$(BIN_DIR)/%.o: %.cpp - $(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $< - -$(BIN_DIR)/%.o: %.c - $(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $< - -all: check - mkdir -p $(BIN_DIR) - mkdir -p $(BIN_DIR)/provider - mkdir -p $(BIN_DIR)/sourcehook - ln -sf $(HL2LIB)/$(LIB_PREFIX)vstdlib$(LIB_SUFFIX) - ln -sf $(HL2LIB)/$(LIB_PREFIX)tier0$(LIB_SUFFIX) - $(MAKE) -f Makefile metamod - -check: - if [ "$(ENGSET)" = "false" ]; then \ - echo "You must supply one of the following values for ENGINE:"; \ - echo "csgo, left4dead2, left4dead, orangeboxvalve, css or orangebox"; \ - exit 1; \ - fi - -metamod: check $(OBJ_LINUX) - $(CPP) $(INCLUDE) $(OBJ_LINUX) $(LINK) -m32 -shared -ldl -lm -o$(BIN_DIR)/$(BINARY) - -debug: - $(MAKE) -f Makefile all DEBUG=true - -default: all - -clean: check - rm -rf $(BIN_DIR)/*.o - rm -rf $(BIN_DIR)/sourcehook/*.o - rm -rf $(BIN_DIR)/provider/*.o - rm -rf $(BIN_DIR)/$(BINARY) - diff --git a/utils/mmsource/core/gamedll_bridge.cpp b/utils/mmsource/core/gamedll_bridge.cpp deleted file mode 100644 index 9c8c34b1e..000000000 --- a/utils/mmsource/core/gamedll_bridge.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2009 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#include -#include "metamod.h" -#include "metamod_plugins.h" -#include "metamod_util.h" -#include -#include "provider/provider_ep2.h" - -using namespace SourceMM; - -class GameDllBridge : public IGameDllBridge -{ -public: - virtual bool DLLInit_Pre(const gamedll_bridge_info *info, char *buffer, size_t maxlength) - { - server = (IServerGameDLL *) info->isgd; - g_Metamod.SetGameDLLInfo((CreateInterfaceFn) info->gsFactory, - info->dllVersion, - true); - g_Metamod.SetVSPListener(info->vsp_listener_path); - mm_InitializeGlobals((CreateInterfaceFn) info->engineFactory, - (CreateInterfaceFn) info->physicsFactory, - (CreateInterfaceFn) info->fsFactory, - (CGlobalVars*) info->pGlobals); - - if (!mm_DetectGameInformation()) - { - UTIL_Format(buffer, maxlength, "Metamod:Source failed to detect game paths; cannot load."); - return false; - } - - mm_InitializeForLoad(); - mm_StartupMetamod(false); - - return true; - } - virtual void DLLInit_Post(int *isgdUnload) - { - SourceHook::MemFuncInfo mfi; - - mfi.isVirtual = false; -#if SOURCE_ENGINE == SE_DOTA - SourceHook::GetFuncInfo(&IServerGameDLL::Shutdown, mfi); -#else - SourceHook::GetFuncInfo(&IServerGameDLL::DLLShutdown, mfi); -#endif - assert(mfi.isVirtual); - assert(mfi.vtbloffs == 0); - assert(mfi.thisptroffs == 0); - *isgdUnload = mfi.vtblindex; - - g_PluginMngr.SetAllLoaded(); - } - virtual void *QueryInterface(const char *iface, int *ret) - { - return g_Metamod.GetServerFactory(true)(iface, ret); - } - virtual void Unload() - { - mm_UnloadMetamod(); - } -}; - -GameDllBridge mm16_gamedll_bridge; - -SMM_API IGameDllBridge * -GetGameDllBridge() -{ - return &mm16_gamedll_bridge; -} - diff --git a/utils/mmsource/core/metamod.cpp b/utils/mmsource/core/metamod.cpp deleted file mode 100644 index 4ef99889b..000000000 --- a/utils/mmsource/core/metamod.cpp +++ /dev/null @@ -1,1435 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2010 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#include -#include "metamod_oslink.h" -#include "metamod.h" -#include -#include -#include -#include "metamod_provider.h" -#include "metamod_plugins.h" -#include "metamod_util.h" -#include "metamod_console.h" -#include "provider/provider_ep2.h" -#include -#if SOURCE_ENGINE == SE_DOTA -#include -#endif - -#define X64_SUFFIX ".x64" -#if defined(WIN32) || defined(_WIN32) -#define BINARY_EXT ".dll" -#elif defined(__linux__) -#define BINARY_EXT ".so" -#elif defined(__APPLE__) -#define BINARY_EXT ".dylib" -#endif - -using namespace SourceMM; -using namespace SourceHook; -using namespace SourceHook::Impl; - -/** - * @brief Implementation of main SourceMM GameDLL functionality - * @file sourcemm.cpp - */ - -#if SOURCE_ENGINE == SE_DOTA -// Hack to make hook decl compile when only having forward decl in header. -// (we have class structure but it requires protobuf which we don't want to include here) -class GameSessionConfiguration_t { }; - -SH_DECL_MANUALHOOK3_void(SGD_StartupServer, 0, 0, 0, const GameSessionConfiguration_t &, ISource2WorldSession *, const char *); -SH_DECL_MANUALHOOK2_void(SGD_Init, 0, 0, 0, GameSessionConfiguration_t *, const char *); -SH_DECL_MANUALHOOK3(SGD_StartChangeLevel, 0, 0, 0, CUtlVector *, const char *, const char *, void *); -SH_DECL_MANUALHOOK5_void(SGD_SwitchToLoop, 0, 0, 0, const char *, KeyValues *, uint32, const char *, bool); - -static void -Handler_SwitchToLoop(const char *, KeyValues *, uint32, const char *, bool); - -static void -Handler_StartupServer_Post(const GameSessionConfiguration_t &, ISource2WorldSession *, const char *); - -static void -Handler_Init(GameSessionConfiguration_t *, const char *); - -static CUtlVector * -Handler_StartChangeLevel(const char *, const char *, void *); -#else -SH_DECL_MANUALHOOK0(SGD_GameInit, 0, 0, 0, bool); -SH_DECL_MANUALHOOK6(SGD_LevelInit, 0, 0, 0, bool, const char *, const char *, const char *, const char *, bool, bool); -SH_DECL_MANUALHOOK0_void(SGD_LevelShutdown, 0, 0, 0); - -static void -Handler_LevelShutdown(); - -static bool -Handler_LevelInit(char const *pMapName, - char const *pMapEntities, - char const *pOldLevel, - char const *pLandmarkName, - bool loadGame, - bool background); - -static bool -Handler_GameInit(); -#endif - -static void -InitializeVSP(); - -static int -LoadPluginsFromFile(const char *filepath, int &skipped); - -static int -LoadVDFPluginsFromDir(const char *dir, int &skipped); - -struct game_dll_t -{ - CreateInterfaceFn factory; -}; - -static String mod_path; -static String metamod_path; -static String full_bin_path; -static int vsp_version = 0; -static int gamedll_version = 0; -static int engine_build = SOURCE_ENGINE_UNKNOWN; -static List gamedll_list; -static bool is_gamedll_loaded = false; -static bool in_first_level = true; -static bool is_game_init = false; -static bool vsp_load_requested = false; -static bool vsp_loaded = false; -static game_dll_t gamedll_info; -static ConVar *metamod_version = NULL; -static ConVar *mm_pluginsfile = NULL; -static ConVar *mm_basedir = NULL; -static CreateInterfaceFn engine_factory = NULL; -static CreateInterfaceFn physics_factory = NULL; -static CreateInterfaceFn filesystem_factory = NULL; -#if !defined( _WIN64 ) && !defined( __amd64__ ) -static CHookManagerAutoGen g_SH_HookManagerAutoGen(&g_SourceHook); -#endif -static META_RES last_meta_res; -static IServerPluginCallbacks *vsp_callbacks = NULL; -static bool were_plugins_loaded = false; -static bool g_bIsVspBridged = false; - -MetamodSource g_Metamod; -PluginId g_PLID = Pl_Console; -CSourceHookImpl g_SourceHook; -ISourceHook *g_SHPtr = &g_SourceHook; -SourceMM::ISmmAPI *g_pMetamod = &g_Metamod; - -/* Helper Macro */ -#define IFACE_MACRO(orig,nam) \ - CPluginManager::CPlugin *pl; \ - SourceHook::List::iterator event; \ - IMetamodListener *api; \ - int mret = 0; \ - void *val = NULL; \ - for (PluginIter iter = g_PluginMngr._begin(); iter != g_PluginMngr._end(); iter++) { \ - pl = (*iter); \ - for (event=pl->m_Events.begin(); event!=pl->m_Events.end(); event++) { \ - api = (*event); \ - mret = META_IFACE_FAILED; \ - if ( (val=api->On##nam##Query(iface, &mret)) != NULL ) { \ - if (ret) *ret = mret; \ - return val; \ - } \ - } \ - } \ - return (orig)(iface, ret); - -#define ITER_EVENT(evn, args) \ - CPluginManager::CPlugin *pl; \ - SourceHook::List::iterator event; \ - IMetamodListener *api; \ - for (PluginIter iter = g_PluginMngr._begin(); iter != g_PluginMngr._end(); iter++) { \ - pl = (*iter); \ - for (event=pl->m_Events.begin(); event!=pl->m_Events.end(); event++) { \ - api = (*event); \ - api->evn args; \ - } \ - } - -/* Initialize everything here */ -void -mm_InitializeForLoad() -{ - char full_path[PATH_SIZE] = {0}; - GetFileOfAddress((void *)gamedll_info.factory, full_path, sizeof(full_path)); - full_bin_path.assign(full_path); - - /* Like Metamod, reload plugins at the end of the map. - * This is so plugins can hook everything on load, BUT, new plugins will be reloaded - * if the server is shut down (silly, but rare case). - */ - in_first_level = true; - -#if SOURCE_ENGINE == SE_DOTA - SourceHook::MemFuncInfo info; - - if (!provider->GetHookInfo(ProvidedHook_StartupServer, &info)) - { - provider->DisplayError("Metamod:Source could not find a valid hook for INetworkServerService::StartupServer"); - } - SH_MANUALHOOK_RECONFIGURE(SGD_StartupServer, info.vtblindex, info.vtbloffs, info.thisptroffs); - SH_ADD_MANUALHOOK(SGD_StartupServer, netservice, SH_STATIC(Handler_StartupServer_Post), true); - - if (!provider->GetHookInfo(ProvidedHook_SwitchToLoop, &info)) - { - provider->DisplayError("Metamod:Source could not find a valid hook for IEngineServiceMgr::SwitchToLoop"); - } - SH_MANUALHOOK_RECONFIGURE(SGD_SwitchToLoop, info.vtblindex, info.vtbloffs, info.thisptroffs); - SH_ADD_MANUALHOOK(SGD_SwitchToLoop, enginesvcmgr, SH_STATIC(Handler_SwitchToLoop), false); -#else - SourceHook::MemFuncInfo info; - - if (!provider->GetHookInfo(ProvidedHook_GameInit, &info)) - { - provider->DisplayError("Metamod:Source could not find a valid hook for IServerGameDLL::GameInit"); - } - SH_MANUALHOOK_RECONFIGURE(SGD_GameInit, info.vtblindex, info.vtbloffs, info.thisptroffs); - SH_ADD_MANUALHOOK_STATICFUNC(SGD_GameInit, server, Handler_GameInit, false); - - if (!provider->GetHookInfo(ProvidedHook_LevelInit, &info)) - { - provider->DisplayError("Metamod:Source could not find a valid hook for IServerGameDLL::LevelInit"); - } - SH_MANUALHOOK_RECONFIGURE(SGD_LevelInit, info.vtblindex, info.vtbloffs, info.thisptroffs); - SH_ADD_MANUALHOOK_STATICFUNC(SGD_LevelInit, server, Handler_LevelInit, true); - - if (!provider->GetHookInfo(ProvidedHook_LevelShutdown, &info)) - { - provider->DisplayError("Metamod:Source could not find a valid hook for IServerGameDLL::LevelShutdown"); - } - SH_MANUALHOOK_RECONFIGURE(SGD_LevelShutdown, info.vtblindex, info.vtbloffs, info.thisptroffs); - SH_ADD_MANUALHOOK_STATICFUNC(SGD_LevelShutdown, server, Handler_LevelShutdown, true); -#endif -} - -bool -mm_DetectGameInformation() -{ - char game_path[PATH_SIZE]; - - provider->GetGamePath(game_path, sizeof(game_path)); - - mod_path.assign(game_path); - - engine_build = provider->DetermineSourceEngine(); - - return true; -} - -void * -ServerFactory(const char *iface, int *ret) -{ - IFACE_MACRO(gamedll_info.factory, GameDLL); -} - -static int -LoadPluginsFromFile(const char *filepath, int &skipped) -{ - FILE *fp; - int total = 0; - PluginId id; - bool already; - - skipped = 0; - - fp = fopen(filepath, "rt"); - if (!fp) - { - return 0; - } - - char buffer[255], error[255], full_path[PATH_SIZE]; - const char *file; - size_t length; - while (!feof(fp) && fgets(buffer, sizeof(buffer), fp) != NULL) - { - UTIL_TrimLeft(buffer); - UTIL_TrimRight(buffer); - - length = strlen(buffer); - if (!length) - { - continue; - } - - if (buffer[0] == '\0' || buffer[0] == ';' || strncmp(buffer, "//", 2) == 0) - { - continue; - } - - file = buffer; - if (buffer[0] == '"') - { - char *cptr = buffer; - file = ++cptr; - - while (*cptr) - { - if (*cptr == '"') - { - *cptr = '\0'; - break; - } - cptr++; - } - } - else - { - char *cptr = buffer; - while (*cptr) - { - if (isspace(*cptr)) - { - char *optr = cptr; - while (*cptr && isspace(*cptr)) - { - cptr++; - } - *optr = '\0'; - UTIL_TrimRight(cptr); - if (*cptr && isalpha(*cptr)) - { - g_PluginMngr.SetAlias(buffer, cptr); - file = cptr; - } - break; - } - cptr++; - } - } - if (!file[0]) - { - continue; - } - - g_Metamod.GetFullPluginPath(file, full_path, sizeof(full_path)); - - id = g_PluginMngr.Load(full_path, Pl_File, already, error, sizeof(error)); - if (id < Pl_MinId || g_PluginMngr.FindById(id)->m_Status < Pl_Paused) - { - mm_LogMessage("[META] Failed to load plugin %s. %s", buffer, error); - } - else - { - if (already) - skipped++; - else - total++; - } - } - fclose(fp); - - return total; -} - -void InitializeVSP() -{ - if (g_bIsVspBridged) - return; - - size_t len; - char engine_file[PATH_SIZE]; - char engine_path[PATH_SIZE]; - char rel_path[PATH_SIZE * 2]; - - GetFileOfAddress((void *)engine_factory, engine_file, sizeof(engine_file)); - - /* Chop off the "engine" file part */ - len = strlen(engine_file); - for (size_t i = len - 1; i < len; i--) - { - if (engine_file[i] == '/' || engine_file[i] == '\\') - { - engine_file[i] = '\0'; - break; - } - } - - /* If this fails the file either does not exist or - * on Windows the buffer may be too small. */ - if (abspath(engine_path, engine_file) == NULL) - { - engine_path[0] = '\0'; - } - - const char *usepath = metamod_path.c_str(); - if (UTIL_Relatize(rel_path, sizeof(rel_path), engine_path, metamod_path.c_str())) - { - usepath = rel_path; - } - - char command[PATH_SIZE * 2]; - UTIL_Format(command, sizeof(command), "plugin_load \"%s\"\n", usepath); - provider->ServerCommand(command); -} - -/* Wrapper function. This is called when the GameDLL thinks it's using - * the engine's real engineFactory. - */ -static void * -EngineFactory(const char *iface, int *ret) -{ - IFACE_MACRO(engine_factory, Engine); -} - -/* Wrapper function. This is called when the GameDLL thinks it's using - * the engine's real physicsFactory. - */ -static void * -PhysicsFactory(const char *iface, int *ret) -{ - IFACE_MACRO(physics_factory, Physics); -} - -/* Wrapper function. This is called when the GameDLL thinks it's using - * the engine's real fileSystemFactory. - */ -static void * -FileSystemFactory(const char *iface, int *ret) -{ - IFACE_MACRO(filesystem_factory, FileSystem); -} - -void -mm_LogMessage(const char *msg, ...) -{ - va_list ap; - static char buffer[2048]; - - va_start(ap, msg); - size_t len = vsnprintf(buffer, sizeof(buffer) - 2, msg, ap); - va_end(ap); - - buffer[len++] = '\n'; - buffer[len] = '\0'; - - if (!provider->LogMessage(buffer)) - { - fprintf(stdout, "%s", buffer); - } -} - -static void -DoInitialPluginLoads() -{ - const char *pluginFile = provider->GetCommandLineValue("mm_pluginsfile", NULL); - const char *mmBaseDir = provider->GetCommandLineValue("mm_basedir", NULL); - if (!pluginFile) - { - pluginFile = provider->GetConVarString(mm_pluginsfile); - if (pluginFile == NULL) - { - pluginFile = "addons/metamod/metaplugins.ini"; - } - } - if (!mmBaseDir) - { - mmBaseDir = provider->GetConVarString(mm_basedir); - if (mmBaseDir == NULL) - { - mmBaseDir = "addons/metamod"; - } - } - - char filepath[PATH_SIZE], vdfpath[PATH_SIZE]; - - g_Metamod.PathFormat(filepath, sizeof(filepath), "%s/%s", mod_path.c_str(), pluginFile); - g_Metamod.PathFormat(vdfpath, sizeof(vdfpath), "%s/%s", mod_path.c_str(), mmBaseDir); - mm_LoadPlugins(filepath, vdfpath); -} - -void -mm_StartupMetamod(bool is_vsp_load) -{ - char buffer[255]; - - UTIL_Format(buffer, - sizeof(buffer), - "%s%s", - METAMOD_VERSION, - is_vsp_load ? "V" : ""); - - metamod_version = provider->CreateConVar("metamod_version", - METAMOD_VERSION, - "Metamod:Source Version", - ConVarFlag_Notify|ConVarFlag_SpOnly); - - provider->SetConVarString(metamod_version, buffer); - - mm_pluginsfile = provider->CreateConVar("mm_pluginsfile", -#if defined WIN32 || defined _WIN32 - "addons\\metamod\\metaplugins.ini", -#else - "addons/metamod/metaplugins.ini", -#endif - "Metamod:Source Plugins File", - ConVarFlag_SpOnly); - - mm_basedir = provider->CreateConVar("mm_basedir", -#if defined __linux__ || defined __APPLE__ - "addons/metamod", -#else - "addons\\metamod", -#endif - "Metamod:Source Base Folder", - ConVarFlag_SpOnly); - - g_bIsVspBridged = is_vsp_load; - - if (!is_vsp_load) - { - DoInitialPluginLoads(); - in_first_level = true; - } -} - -void -mm_InitializeGlobals(CreateInterfaceFn engineFactory, - CreateInterfaceFn physicsFactory, - CreateInterfaceFn filesystemFactory, - CGlobalVars *pGlobals) -{ - engine_factory = engineFactory; - physics_factory = physicsFactory; - filesystem_factory = filesystemFactory; - gpGlobals = pGlobals; - provider->Notify_DLLInit_Pre(engineFactory, gamedll_info.factory); -} - -void -mm_UnloadMetamod() -{ - /* Unload plugins */ - g_PluginMngr.UnloadAll(); - - provider->Notify_DLLShutdown_Pre(); - - g_SourceHook.CompleteShutdown(); -} - -static void -mm_HandleGameInit() -{ - if (is_game_init) - return; - -#if SOURCE_ENGINE == SE_DOTA - DevMsg("MMS: GameInit\n"); -#endif - - if (vsp_load_requested) - InitializeVSP(); - - if (g_bIsVspBridged && !were_plugins_loaded) - { - DoInitialPluginLoads(); - g_PluginMngr.SetAllLoaded(); - were_plugins_loaded = true; - } - - is_game_init = true; -} - -static void -mm_HandleLevelShutdown() -{ -#if SOURCE_ENGINE == SE_DOTA - DevMsg("MMS: LevelShutdown\n"); -#endif - - if (g_bIsVspBridged && !were_plugins_loaded) - { - DoInitialPluginLoads(); - g_PluginMngr.SetAllLoaded(); - were_plugins_loaded = true; - in_first_level = true; - } - - if (!in_first_level) - { - char filepath[PATH_SIZE], vdfpath[PATH_SIZE]; - - g_Metamod.PathFormat(filepath, - sizeof(filepath), - "%s/%s", - mod_path.c_str(), - provider->GetConVarString(mm_pluginsfile)); - g_Metamod.PathFormat(vdfpath, - sizeof(vdfpath), - "%s/%s", - mod_path.c_str(), - provider->GetConVarString(mm_basedir)); - mm_LoadPlugins(filepath, vdfpath); - } - else - { - in_first_level = false; - } - - ITER_EVENT(OnLevelShutdown, ()); -} - -static void -mm_HandleLevelInit(char const *pMapName, -char const *pMapEntities, -char const *pOldLevel, -char const *pLandmarkName, -bool loadGame, -bool background) -{ -#if SOURCE_ENGINE == SE_DOTA - DevMsg("MMS: LevelInit\n"); -#endif - - ITER_EVENT(OnLevelInit, (pMapName, pMapEntities, pOldLevel, pLandmarkName, loadGame, background)); -} -#include -#if SOURCE_ENGINE == SE_DOTA -static void -Handler_SwitchToLoop(const char *pszLoopName, KeyValues *pKV, uint32 nId, const char *pszUnk, bool bUnk) -{ - if (strcmp(pszLoopName, "levelload") == 0) - { - mm_HandleGameInit(); - } - - RETURN_META(MRES_IGNORED); -} - -static void -Handler_StartupServer_Post(const GameSessionConfiguration_t &config, ISource2WorldSession *, const char *) -{ - static bool bGameServerHooked = false; - if (!bGameServerHooked) - { - INetworkGameServer *netserver = (META_IFACEPTR(INetworkServerService))->GetIGameServer(); - - SourceHook::MemFuncInfo info; - if (!provider->GetHookInfo(ProvidedHook_Init, &info)) - { - provider->DisplayError("Metamod:Source could not find a valid hook for INetworkGameServer::Init"); - } - SH_MANUALHOOK_RECONFIGURE(SGD_Init, info.vtblindex, info.vtbloffs, info.thisptroffs); - SH_ADD_MANUALVPHOOK(SGD_Init, netserver, SH_STATIC(Handler_Init), false); - - if (!provider->GetHookInfo(ProvidedHook_StartChangeLevel, &info)) - { - provider->DisplayError("Metamod:Source could not find a valid hook for INetworkGameServer::StartChangeLevel"); - } - SH_MANUALHOOK_RECONFIGURE(SGD_StartChangeLevel, info.vtblindex, info.vtbloffs, info.thisptroffs); - SH_ADD_MANUALVPHOOK(SGD_StartChangeLevel, netserver, SH_STATIC(Handler_StartChangeLevel), false); - - bGameServerHooked = true; - } - - RETURN_META(MRES_IGNORED); -} - -static void -Handler_Init(GameSessionConfiguration_t *pConfig, const char *pszMapName) -{ - static char szLastMap[260] = ""; - mm_HandleLevelInit(pszMapName, "", szLastMap, "", false, false); - UTIL_Format(szLastMap, sizeof(szLastMap), "%s", pszMapName); - - RETURN_META(MRES_IGNORED); -} - -static CUtlVector * -Handler_StartChangeLevel(const char *, const char *, void *) -{ - mm_HandleLevelShutdown(); - - RETURN_META_VALUE(MRES_IGNORED, nullptr); -} - -#else - -static bool -Handler_GameInit() -{ - mm_HandleGameInit(); - - RETURN_META_VALUE(MRES_IGNORED, true); -} - -static void -Handler_LevelShutdown(void) -{ - mm_HandleLevelShutdown(); - - RETURN_META(MRES_IGNORED); -} - -static bool -Handler_LevelInit(char const *pMapName, - char const *pMapEntities, - char const *pOldLevel, - char const *pLandmarkName, - bool loadGame, - bool background) -{ - ITER_EVENT(OnLevelInit, (pMapName, pMapEntities, pOldLevel, pLandmarkName, loadGame, background)); - - RETURN_META_VALUE(MRES_IGNORED, false); -} -#endif - -void MetamodSource::LogMsg(ISmmPlugin *pl, const char *msg, ...) -{ - va_list ap; - char buffer[2048]; - - va_start(ap, msg); - UTIL_FormatArgs(buffer, sizeof(buffer), msg, ap); - va_end(ap); - - mm_LogMessage("[%s] %s", pl->GetLogTag(), buffer); -} - -CreateInterfaceFn MetamodSource::GetEngineFactory(bool syn/* =true */) -{ - if (syn) - return EngineFactory; - return engine_factory; -} - -CreateInterfaceFn MetamodSource::GetPhysicsFactory(bool syn/* =true */) -{ - if (syn) - return PhysicsFactory; - return physics_factory; -} - -CreateInterfaceFn MetamodSource::GetFileSystemFactory(bool syn/* =true */) -{ - if (syn) - return FileSystemFactory; - return filesystem_factory; -} - -CreateInterfaceFn MetamodSource::GetServerFactory(bool syn/* =true */) -{ - if (syn) - return ServerFactory; - return gamedll_info.factory; -} - -CGlobalVars *MetamodSource::GetCGlobals() -{ - return gpGlobals; -} - -void MetamodSource::SetLastMetaReturn(META_RES res) -{ - last_meta_res = res; -} - -META_RES MetamodSource::GetLastMetaReturn() -{ - return last_meta_res; -} - -void MetamodSource::ConPrint(const char *str) -{ - provider->ConsolePrint(str); -} - -void MetamodSource::ConPrintf(const char *fmt, ...) -{ - va_list ap; - char buffer[2048]; - - va_start(ap, fmt); - UTIL_FormatArgs(buffer, sizeof(buffer), fmt, ap); - va_end(ap); - - provider->ConsolePrint(buffer); -} - -void MetamodSource::GetApiVersions(int &major, int &minor, int &plvers, int &plmin) -{ - major = METAMOD_API_MAJOR; - minor = METAMOD_API_MINOR; - plvers = METAMOD_PLAPI_VERSION; - plmin = PLAPI_MIN_VERSION; -} - -void MetamodSource::GetShVersions(int &shvers, int &shimpl) -{ - shvers = SH_IFACE_VERSION; - shimpl = SH_IMPL_VERSION; -} - -int MetamodSource::FormatIface(char iface[], unsigned int maxlength) -{ - int length = (int)strlen(iface); - int i; - int num = 0; - - for (i = length - 1; i >= 0; i--) - { - if (!isdigit(iface[i])) - { - if (i != length - 1) - { - num = 1; - } - break; - } - } - - if ( (num && ((int)maxlength <= length)) || (!num && ((int)maxlength <= length + 3)) ) - { - return -1; - } - - if (i != length - 1) - { - num = atoi(&(iface[++i])); - } - - num++; - - snprintf(&(iface[i]), 4, "%03d", num); - - return num; -} - -void *MetamodSource::InterfaceSearch(CreateInterfaceFn fn, const char *iface, int max, int *ret) -{ - char _if[256]; /* assume no interface goes beyond this */ - size_t len = strlen(iface); - int num = 0; - void *pf = NULL; - - if (max > 999) - { - max = 999; - } - - if (len + 4 > sizeof(_if)) - { - if (ret) - { - *ret = META_IFACE_FAILED; - } - return NULL; - } - - strcpy(_if, iface); - - do - { - if ((pf = (fn)(_if, ret)) != NULL) - { - break; - } - if (num > max) - { - break; - } - } while ((num = FormatIface(_if, len+1))); - - return pf; -} - -void *MetamodSource::VInterfaceMatch(CreateInterfaceFn fn, const char *iface, int min) -{ - char buffer[256]; /* assume no interface will go beyond this */ - size_t len = strlen(iface); - int ret; /* just in case something doesn't handle NULL properly */ - - if (len > sizeof(buffer) - 4) - { - return NULL; - } - - strcpy(buffer, iface); - - if (min != -1) - { - char *ptr = &buffer[len - 1]; - int digits = 0; - while (isdigit(*ptr) && digits <=3) - { - *ptr = '\0'; - digits++; - ptr--; - } - if (digits != 3) - { - /* for now, assume this is an error */ - strcpy(buffer, iface); - } - else - { - char num[4]; - min = (min == 0) ? 1 : min; - snprintf(num, sizeof(num), "%03d", min); - strcat(buffer, num); - } - } - - return InterfaceSearch(fn, buffer, IFACE_MAXNUM, &ret); -} - -const char *MetamodSource::GetBaseDir() -{ - return mod_path.c_str(); -} - -size_t MetamodSource::PathFormat(char *buffer, size_t len, const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - size_t mylen = UTIL_FormatArgs(buffer, len, fmt, ap); - va_end(ap); - - for (size_t i = 0; i < mylen; i++) - { - if (buffer[i] == ALT_SEP_CHAR) - { - buffer[i] = PATH_SEP_CHAR; - } - } - - return mylen; -} - -#if SOURCE_ENGINE == SE_DOTA -void MetamodSource::ClientConPrintf(int clientIndex, const char *fmt, ...) -{ - va_list ap; - char buffer[2048]; - - va_start(ap, fmt); - UTIL_FormatArgs(buffer, sizeof(buffer), fmt, ap); - va_end(ap); - - ClientConPrintf((edict_t *)(gpGlobals->pEdicts + clientIndex), "%s", buffer); -} -#endif - -void MetamodSource::ClientConPrintf(edict_t *client, const char *fmt, ...) -{ - va_list ap; - char buffer[2048]; - - va_start(ap, fmt); - UTIL_FormatArgs(buffer, sizeof(buffer), fmt, ap); - va_end(ap); - - provider->ClientConsolePrint(client, buffer); -} - -void MetamodSource::EnableVSPListener() -{ - if (is_game_init && !vsp_load_requested && !vsp_loaded) - { - InitializeVSP(); - } - - vsp_load_requested = true; -} - -int MetamodSource::GetVSPVersion() -{ - return vsp_version; -} - -int MetamodSource::GetGameDLLVersion() -{ - return gamedll_version; -} - -bool MetamodSource::RemotePrintingAvailable() -{ - return provider->IsRemotePrintingAvailable(); -} - -void *MetamodSource::MetaFactory(const char *iface, int *ret, PluginId *id) -{ - if (id) - { - *id = 0; - } - - if (!iface) - { - return NULL; - } - - /* First check ours... we get first chance! */ - if (strcmp(iface, MMIFACE_SOURCEHOOK) == 0) - { - if (ret) - { - *ret = META_IFACE_OK; - } - return static_cast(static_cast(&g_SourceHook)); - } - else if (strcmp(iface, MMIFACE_PLMANAGER) == 0) - { - if (ret) - { - *ret = META_IFACE_OK; - } - return static_cast(static_cast(&g_PluginMngr)); - } - else if (strcmp(iface, MMIFACE_SH_HOOKMANAUTOGEN) == 0) - { -#if defined( _WIN64 ) || defined( __amd64__ ) - if (ret) - { - *ret = META_IFACE_FAILED; - } - return nullptr; -#else - if (ret) - { - *ret = META_IFACE_OK; - } - return static_cast(static_cast(&g_SH_HookManagerAutoGen)); -#endif - } - - CPluginManager::CPlugin *pl; - List::iterator event; - IMetamodListener *api; - void *value; - - int subret = 0; - for (PluginIter iter = g_PluginMngr._begin(); - iter != g_PluginMngr._end(); - iter++) - { - pl = (*iter); - for (event = pl->m_Events.begin(); event != pl->m_Events.end(); event++) - { - api = (*event); - subret = META_IFACE_FAILED; - if ((value = api->OnMetamodQuery(iface, &subret)) != NULL) - { - if (ret) - { - *ret = subret; - } - if (id) - { - *id = pl->m_Id; - } - return value; - } - } - } - - if (ret) - { - *ret = META_IFACE_FAILED; - } - - return NULL; -} - -void MetamodSource::AddListener(ISmmPlugin *plugin, IMetamodListener *pListener) -{ - CPluginManager::CPlugin *pl = g_PluginMngr.FindByAPI(plugin); - - pl->m_Events.push_back(pListener); -} - -const char *MetamodSource::GetGameBinaryPath() -{ - return full_bin_path.c_str(); -} - -const char *MetamodSource::GetPluginsFile() -{ - return provider->GetConVarString(mm_pluginsfile); -} - -const char *MetamodSource::GetVDFDir() -{ - return provider->GetConVarString(mm_basedir); -} - -IConCommandBaseAccessor *MetamodSource::GetCvarBaseAccessor() -{ - return provider->GetConCommandBaseAccessor(); -} - -bool MetamodSource::RegisterConCommandBase(ISmmPlugin *plugin, ConCommandBase *pCommand) -{ - if (provider->IsConCommandBaseACommand(pCommand)) - { - g_PluginMngr.AddPluginCmd(plugin, pCommand); - } - else - { - g_PluginMngr.AddPluginCvar(plugin, pCommand); - } - - return provider->RegisterConCommandBase(pCommand); -} - -void MetamodSource::UnregisterConCommandBase(ISmmPlugin *plugin, ConCommandBase *pCommand) -{ - if (provider->IsConCommandBaseACommand(pCommand)) - { - g_PluginMngr.RemovePluginCmd(plugin, pCommand); - } - else - { - g_PluginMngr.RemovePluginCvar(plugin, pCommand); - } - - CPluginManager::CPlugin *pOrig = g_PluginMngr.FindByAPI(plugin); - UnregisterConCommandBase(pOrig ? pOrig->m_Id : 0, pCommand); -} - -void MetamodSource::UnregisterConCommandBase(PluginId id, ConCommandBase *pCommand) -{ - PluginIter iter; - CPluginManager::CPlugin *pPlugin; - List::iterator event; - IMetamodListener *pML; - for (iter=g_PluginMngr._begin(); iter!=g_PluginMngr._end(); iter++) - { - pPlugin = (*iter); - if (pPlugin->m_Status < Pl_Paused) - { - continue; - } - /* Only valid for plugins >= 12 (v1:6, SourceMM 1.5) */ - if (pPlugin->m_API->GetApiVersion() < 12) - { - continue; - } - for (event=pPlugin->m_Events.begin(); - event!=pPlugin->m_Events.end(); - event++) - { - pML = (*event); - pML->OnUnlinkConCommandBase(id, pCommand); - } - } - - return provider->UnregisterConCommandBase(pCommand); -} - -int MetamodSource::GetUserMessageCount() -{ - return provider->GetUserMessageCount(); -} - -int MetamodSource::FindUserMessage(const char *name, int *size/* =NULL */) -{ - return provider->FindUserMessage(name, size); -} - -const char *MetamodSource::GetUserMessage(int index, int *size/* =NULL */) -{ - return provider->GetUserMessage(index, size); -} - -int MetamodSource::GetSourceEngineBuild() -{ - return engine_build; -} - -void MetamodSource::NotifyVSPListening(IServerPluginCallbacks *callbacks, int version) -{ - if (version != -1) - vsp_version = version; - - vsp_callbacks = callbacks; - ITER_EVENT(OnVSPListening, (callbacks)); - - if (is_gamedll_loaded) - { - /* - * MM:S is loaded as a game DLL so we need to set these for mm_IsVspBridged() and - * mm_IsVspLoadComplete() - */ - g_bIsVspBridged = true; - were_plugins_loaded = true; - } -} - -IServerPluginCallbacks *MetamodSource::GetVSPInfo(int *pVersion) -{ - if (pVersion) - { - *pVersion = vsp_version; - } - - return vsp_callbacks; -} - -size_t MetamodSource::Format(char *buffer, size_t maxlength, const char *format, ...) -{ - va_list ap; - size_t result; - - va_start(ap, format); - result = FormatArgs(buffer, maxlength, format, ap); - va_end(ap); - - return result; -} - -size_t MetamodSource::FormatArgs(char *buffer, size_t maxlength, const char *format, va_list ap) -{ - return UTIL_FormatArgs(buffer, maxlength, format, ap); -} - -bool MetamodSource::IsLoadedAsGameDLL() -{ - return is_gamedll_loaded; -} - -void MetamodSource::SetGameDLLInfo(CreateInterfaceFn serverFactory, int version, bool loaded) -{ - gamedll_info.factory = serverFactory; - gamedll_version = version; - is_gamedll_loaded = loaded; -} - -void MetamodSource::SetVSPListener(const char *path) -{ - metamod_path.assign(path); -} - -size_t MetamodSource::GetFullPluginPath(const char *plugin, char *buffer, size_t len) -{ - const char *pext, *ext; - size_t num; - - /* First find if it's an absolute path or not... */ - if (plugin[0] == '/' || strncmp(&(plugin[1]), ":\\", 2) == 0) - { - return UTIL_Format(buffer, len, plugin); - } - - /* Attempt to find a file extension */ - pext = UTIL_GetExtension(plugin); - /* Add an extension if there's none there */ - if (!pext) - { -#if defined(WIN32) || defined(_WIN32) -#if defined(WIN64) || defined(_WIN64) - ext = X64_SUFFIX BINARY_EXT; -#else - ext = BINARY_EXT; -#endif -#elif defined __APPLE__ -#if defined (__x86_64__) - ext = X64_SUFFIX BINARY_EXT; -#else - ext = BINARY_EXT; -#endif -#else -#if defined(__x86_64__) - ext = X64_SUFFIX BINARY_EXT; -#else - ext = "_i486" BINARY_EXT; -#endif -#endif - } - else - { - ext = ""; - } - - /* Format the new path */ - num = PathFormat(buffer, len, "%s/%s%s", mod_path.c_str(), plugin, ext); - - /* If path was passed without extension and it doesn't exist with "." try "." */ -#if defined(WIN64) || defined (_WIN64) || defined(__linux__) || defined(__x86_64__) - struct stat s; - if (!pext && stat(buffer, &s) != 0) - { - num = PathFormat(buffer, len, "%s/%s" BINARY_EXT, mod_path.c_str(), plugin); - } -#endif - - return num; -} - -static bool -ProcessVDF(const char *path, bool &skipped) -{ - PluginId id; - bool already; - char alias[24], file[255], full_path[255], error[255]; - - if (!provider->ProcessVDF(path, file, sizeof(file), alias, sizeof(alias))) - { - skipped = false; - return false; - } - - if (alias[0] != '\0') - g_PluginMngr.SetAlias(alias, file); - - g_Metamod.GetFullPluginPath(file, full_path, sizeof(full_path)); - - id = g_PluginMngr.Load(full_path, Pl_File, already, error, sizeof(error)); - skipped = already; - if (id < Pl_MinId || g_PluginMngr.FindById(id)->m_Status < Pl_Paused) - { - mm_LogMessage("[META] Failed to load plugin %s: %s", file, error); - return false; - } - - return true; -} - -static int -LoadVDFPluginsFromDir(const char *dir, int &skipped) -{ - bool success, skip; - int total = 0; - char path[MAX_PATH]; - char relpath[MAX_PATH * 2]; - - skipped = 0; - -#if defined _MSC_VER - HANDLE hFind; - WIN32_FIND_DATA fd; - char error[255]; - - g_Metamod.PathFormat(path, sizeof(path), "%s\\*.vdf", dir); - if ((hFind = FindFirstFile(path, &fd)) == INVALID_HANDLE_VALUE) - { - DWORD dw = GetLastError(); - if (dw == ERROR_FILE_NOT_FOUND) - return 0; - - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - dw, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - error, - sizeof(error), - NULL); - mm_LogMessage("[META] Could not open folder \"%s\" (%s)", dir, error); - return 0; - } - - do - { - g_Metamod.PathFormat(path, sizeof(path), "%s\\%s", dir, fd.cFileName); - UTIL_Relatize(relpath, sizeof(relpath), mod_path.c_str(), path); - success = ProcessVDF(relpath, skip); - if (skip) - skipped++; - else if (success) - total++; - } while (FindNextFile(hFind, &fd)); - - FindClose(hFind); -#else - DIR *pDir; - struct dirent *pEnt; - int extidx; - - if ((pDir = opendir(dir)) == NULL) - { - mm_LogMessage("[META] Could not open folder \"%s\" (%s)", dir, strerror(errno)); - return 0; - } - - while ((pEnt = readdir(pDir)) != NULL) - { - if (strcmp(pEnt->d_name, ".") == 0 - || strcmp(pEnt->d_name, "..") == 0) - { - continue; - } - extidx = strlen(pEnt->d_name) - 4; - if (extidx < 0 || stricmp(&pEnt->d_name[extidx], ".vdf")) - { - continue; - } - g_Metamod.PathFormat(path, sizeof(path), "%s/%s", dir, pEnt->d_name); - UTIL_Relatize(relpath, sizeof(relpath), mod_path.c_str(), path); - success = ProcessVDF(relpath, skip); - if (skip) - skipped++; - else if (success) - total++; - } - - closedir(pDir); -#endif - - return total; -} - -int -mm_LoadPlugins(const char *filepath, const char *vdfpath) -{ - int total, skipped, fskipped, vskipped; - const char *s = ""; - - total = LoadPluginsFromFile(filepath, fskipped); - total += LoadVDFPluginsFromDir(vdfpath, vskipped); - skipped = fskipped + vskipped; - - if (total == 0 || total > 1) - s = "s"; - - if (skipped) - mm_LogMessage("[META] Loaded %d plugin%s (%d already loaded)", total, s, skipped); - else - mm_LogMessage("[META] Loaded %d plugin%s.", total, s); - - return total; -} - -bool -mm_IsVspBridged() -{ - return g_bIsVspBridged; -} - -bool -mm_IsVspLoadComplete() -{ - return were_plugins_loaded; -} - diff --git a/utils/mmsource/core/metamod.h b/utils/mmsource/core/metamod.h deleted file mode 100644 index 07a2b3854..000000000 --- a/utils/mmsource/core/metamod.h +++ /dev/null @@ -1,140 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2010 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#ifndef _INCLUDE_SOURCEMM_H -#define _INCLUDE_SOURCEMM_H - -/** - * @brief SourceMM main functionality for GameDLL interception - * @file sourcemm.h - */ - -#include -#include -#include -#include -#include -#include -#include "metamod_provider.h" - -using namespace SourceMM; - -/** - * Versioning - * increase api_major when API breaks - * increase api_minor when new functions are added (non-breaking) - */ -#define SOURCEMM_VERSION SVN_FILE_VERSION_STRING -#define SOURCEMM_DATE __DATE__ -#define METAMOD_API_MAJOR 2 /* increase this on a breaking change */ -#define METAMOD_API_MINOR 0 /* increase this on a non-breaking API change */ - -class MetamodSource : public ISmmAPI -{ -public: - void LogMsg(ISmmPlugin *pl, const char *msg, ...); - CreateInterfaceFn GetEngineFactory(bool syn=true); - CreateInterfaceFn GetPhysicsFactory(bool syn=true); - CreateInterfaceFn GetFileSystemFactory(bool syn=true); - CreateInterfaceFn GetServerFactory(bool syn=true); - CGlobalVars *GetCGlobals(); - void SetLastMetaReturn(META_RES res); - META_RES GetLastMetaReturn(); - IConCommandBaseAccessor *GetCvarBaseAccessor(); - bool RegisterConCommandBase(ISmmPlugin *plugin, ConCommandBase *pCommand); - void UnregisterConCommandBase(ISmmPlugin *plugin, ConCommandBase *pCommand); - void ConPrint(const char *str); - void ConPrintf(const char *fmt, ...); - bool RemotePrintingAvailable(); - void GetApiVersions(int &major, int &minor, int &plvers, int &plmin); - void GetShVersions(int &shvers, int &shimpl); - void AddListener(ISmmPlugin *plugin, IMetamodListener *pListener); - void *MetaFactory(const char *iface, int *ret, PluginId *id); - int FormatIface(char iface[], unsigned int maxlength); - void *InterfaceSearch(CreateInterfaceFn fn, const char *iface, int max, int *ret); - const char *GetBaseDir(); - size_t PathFormat(char *buffer, size_t len, const char *fmt, ...); -#if SOURCE_ENGINE == SE_DOTA - // Shim - void ClientConPrintf(int clientIndex, const char *fmt, ...); -#endif - void ClientConPrintf(edict_t *client, const char *fmt, ...); - void *VInterfaceMatch(CreateInterfaceFn fn, const char *iface, int min=-1); - void EnableVSPListener(); - int GetGameDLLVersion(); - int GetUserMessageCount(); - int FindUserMessage(const char *name, int *size=NULL); - const char *GetUserMessage(int index, int *size=NULL); - int GetVSPVersion(); - int GetSourceEngineBuild(); - IServerPluginCallbacks *GetVSPInfo(int *pVersion); - size_t Format(char *buffer, size_t maxlength, const char *format, ...); - size_t FormatArgs(char *buffer, size_t maxlength, const char *format, va_list ap); -public: - bool IsLoadedAsGameDLL(); - const char *GetGameBinaryPath(); - const char *GetPluginsFile(); - const char *GetVDFDir(); - void UnregisterConCommandBase(PluginId id, ConCommandBase *pCommand); - void NotifyVSPListening(IServerPluginCallbacks *callbacks, int version); - void SetGameDLLInfo(CreateInterfaceFn serverFactory, int version, bool loaded); - void SetVSPListener(const char *path); - size_t GetFullPluginPath(const char *plugin, char *buffer, size_t len); -}; - -bool -mm_DetectGameInformation(); - -void -mm_LogMessage(const char *msg, ...); - -int -mm_LoadPlugins(const char *filepath, const char *vdfpath); - -void -mm_InitializeForLoad(); - -void -mm_InitializeGlobals(CreateInterfaceFn engineFactory, - CreateInterfaceFn physicsFactory, - CreateInterfaceFn filesystemFactory, - CGlobalVars *pGlobals); -void -mm_StartupMetamod(bool is_vsp_load); - -void -mm_UnloadMetamod(); - -bool -mm_IsVspBridged(); - -bool -mm_IsVspLoadComplete(); - -extern MetamodSource g_Metamod; -extern SourceHook::Impl::CSourceHookImpl g_SourceHook; - -#endif //_INCLUDE_SOURCEMM_H - diff --git a/utils/mmsource/core/metamod_console.cpp b/utils/mmsource/core/metamod_console.cpp deleted file mode 100644 index 7804b49f4..000000000 --- a/utils/mmsource/core/metamod_console.cpp +++ /dev/null @@ -1,743 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2010 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#include -#include "metamod_oslink.h" -#include -#include -#include "metamod.h" -#include "metamod_util.h" -#include "metamod_console.h" -#include "metamod_plugins.h" - -using namespace SourceMM; -using namespace SourceHook; - -/** - * @brief Console Command Implementations - * @file concommands.cpp - */ - -#define CONMSG g_Metamod.ConPrintf -#define CLIENT_CONMSG g_Metamod.ClientConPrintf -template - -#if SOURCE_ENGINE == SE_DOTA -void CMDMSG(int client, const char *pMsg, Ts ... ts) -#else -void CMDMSG(edict_t *client, const char *pMsg, Ts ... ts) -#endif -{ - if (client) - { - CLIENT_CONMSG(client, pMsg, ts...); - } - else - { - CONMSG(pMsg, ts...); - } -} - -#if SOURCE_ENGINE == SE_DOTA -static void ReplyCredits(int client = 0) -#else -static void ReplyCredits(edict_t *client = nullptr) -#endif -{ - CMDMSG(client, "Metamod:Source was developed by:\n"); - CMDMSG(client, " SourceHook: Pavol \"PM OnoTo\" Marko\n"); - CMDMSG(client, " GameDLL/Plugins: David \"BAILOPAN\" Anderson\n"); - CMDMSG(client, " GameDLL: Scott \"DS\" Ehlert\n"); - CMDMSG(client, "For more information, see the official website\n"); - CMDMSG(client, "http://www.metamodsource.net/\n"); -} - -#if SOURCE_ENGINE == SE_DOTA -static void ReplyVersion(int client = 0) -#else -static void ReplyVersion(edict_t *client = nullptr) -#endif -{ - CMDMSG(client, " Metamod:Source Version Information\n"); - CMDMSG(client, " Metamod:Source version %s\n", METAMOD_VERSION); - CMDMSG(client, " Plugin interface version: %d:%d\n", METAMOD_PLAPI_VERSION, PLAPI_MIN_VERSION); - CMDMSG(client, " SourceHook version: %d:%d\n", g_SHPtr->GetIfaceVersion(), g_SHPtr->GetImplVersion()); - if (g_Metamod.IsLoadedAsGameDLL()) - { - CMDMSG(client, " Loaded As: GameDLL (gameinfo.txt)\n"); - } - else - { - CMDMSG(client, " Loaded As: Valve Server Plugin\n"); - } - CMDMSG(client, " Compiled on: %s\n", MMS_BUILD_TIMESTAMP); -#if defined(MMS_GENERATED_BUILD) - CMDMSG(client, " Built from: https://github.com/alliedmodders/metamod-source/commit/%s\n", METAMOD_SHA); - CMDMSG(client, " Build ID: %s:%s\n", METAMOD_LOCAL_REV, METAMOD_SHA); -#endif - CMDMSG(client, " http://www.metamodsource.net/\n"); -} - -bool Command_Meta(IMetamodSourceCommandInfo *info) -{ - unsigned int args = info->GetArgCount(); - - if (mm_IsVspBridged() && !mm_IsVspLoadComplete()) - { - CONMSG("You must change the map to activate Metamod:Source.\n"); - return true; - } - - if (args >= 1) - { - const char *command = info->GetArg(1); - if (strcmp(command, "credits") == 0) - { - ReplyCredits(); - - return true; - } - else if (strcmp(command, "version") == 0) - { - ReplyVersion(); - - return true; - } - else if (strcmp(command, "game") == 0) - { - CONMSG("GameDLL Information\n"); - CONMSG(" Description: %s\n", provider->GetGameDescription()); - CONMSG(" Mod Path: %s\n", g_Metamod.GetBaseDir()); - CONMSG(" DLL Path: %s\n", g_Metamod.GetGameBinaryPath()); - CONMSG(" Interface: ServerGameDLL%03d\n", g_Metamod.GetGameDLLVersion()); - CONMSG(" Engine: %s\n", provider->GetEngineDescription()); - - // Display user messages - const char *msgname; - int msgsize; - int messages = g_Metamod.GetUserMessageCount(); - - if (messages > 0) - { - CONMSG(" User Messages: %-32.31s %-5s %-5s\n", "Name", "Index", "Size"); - - for (int i = 0; i < messages; i++) - { - msgname = g_Metamod.GetUserMessage(i, &msgsize); - - CONMSG(" %-32.31s %-5d %-5d\n", msgname, i, msgsize); - } - - CONMSG(" %d user message%s in total\n", messages, (messages > 1) ? "s" : ""); - } - else - { - CONMSG(" User Messages: None\n"); - } - - return true; - } - else if (strcmp(command, "refresh") == 0) - { - char filepath[PATH_SIZE], vdfpath[PATH_SIZE]; - g_Metamod.PathFormat(filepath, - sizeof(filepath), - "%s/%s", - g_Metamod.GetBaseDir(), - g_Metamod.GetPluginsFile()); - g_Metamod.PathFormat(vdfpath, - sizeof(vdfpath), - "%s/%s", - g_Metamod.GetBaseDir(), - g_Metamod.GetVDFDir()); - - mm_LoadPlugins(filepath, vdfpath); - - return true; - } - else if (strcmp(command, "list") == 0) - { - CPluginManager::CPlugin *pl; - ISmmPlugin *plapi; - const char *plname; - PluginIter i; - char buffer[256]; - int len; - int plnum = g_PluginMngr.GetPluginCount(); - - if (!plnum) - { - CONMSG("No plugins loaded.\n"); - return true; - } else { - CONMSG("Listing %d plugin%s:\n", plnum, (plnum > 1) ? "s" : ""); - } - - for (i = g_PluginMngr._begin(); i != g_PluginMngr._end(); i++) - { - pl = (*i); - if (!pl) - { - break; - } - - len = 0; - - if (pl->m_Status != Pl_Running) - { - len += UTIL_Format(buffer, sizeof(buffer), " [%02d] <%s>", pl->m_Id, g_PluginMngr.GetStatusText(pl)); - } else { - len += UTIL_Format(buffer, sizeof(buffer), " [%02d]", pl->m_Id); - } - - if ((plapi = pl->m_API)) - { - plname = IS_STR_FILLED(plapi->GetName()) ? plapi->GetName() : pl->m_File.c_str(); - len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " %s", plname); - - if (IS_STR_FILLED(plapi->GetVersion())) - { - len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " (%s)", plapi->GetVersion()); - } - if (IS_STR_FILLED(plapi->GetAuthor())) - { - UTIL_Format(&buffer[len], sizeof(buffer)-len, " by %s", plapi->GetAuthor()); - } - } - - CONMSG("%s\n", buffer); - } - - return true; - } - else if (strcmp(command, "cmds") == 0) - { - if (args >= 2) - { - int id = atoi(info->GetArg(2)); - CPluginManager::CPlugin *pl = g_PluginMngr.FindById(id); - - if (!pl) - { - CONMSG("Plugin %d not found.\n", id); - return true; - } - - if (!pl->m_API) - { - CONMSG("Plugin %d is not loaded.\n", id); - } - else - { - CONMSG("Console commands for %s:\n", pl->m_API->GetName()); - List::iterator ci; - size_t count = 0; - - for (ci=pl->m_Cmds.begin(); ci!=pl->m_Cmds.end(); ci++) - { - count++; - CONMSG(" [%5d] %-s\n", count, (*ci)->GetName()); - } - } - } - else - { - CONMSG("Usage: meta cmds \n"); - } - - return true; - } - else if (strcmp(command, "cvars") == 0) - { - if (args >= 2) - { - int id = atoi(info->GetArg(2)); - CPluginManager::CPlugin *pl = g_PluginMngr.FindById(id); - - if (!pl) - { - CONMSG("Plugin %d not found.\n", id); - return true; - } - - if (!pl->m_API) - { - CONMSG("Plugin %d is not loaded.\n", id); - } - else - { - CONMSG("Registered cvars for %s:\n", pl->m_API->GetName()); - List::iterator ci; - size_t count = 0; - - for (ci=pl->m_Cvars.begin(); ci!=pl->m_Cvars.end(); ci++) - { - count++; - CONMSG(" [%5d] %-s\n", count, (*ci)->GetName()); - } - } - } - else - { - CONMSG("Usage: meta cvars \n"); - } - - return true; - } - else if (strcmp(command, "info") == 0) - { - if (args >= 2) - { - int id = atoi(info->GetArg(2)); - CPluginManager::CPlugin *pl = g_PluginMngr.FindById(id); - if (!pl) - { - CONMSG("Plugin %d not found.\n", id); - return true; - } - - if (!pl->m_API) - { - CONMSG("Plugin %d is not loaded.\n", id); - } - else - { - if (pl->m_Status == Pl_Paused) - { - CONMSG("Plugin %d is paused.\n", id); - } - else if (pl->m_Status == Pl_Running) - { - char run_msg[255]; - bool run = false; - if (pl->m_API && pl->m_API->QueryRunning(run_msg, sizeof(run_msg)-1)) - { - run = true; - } - if (run) - { - CONMSG("Plugin %d is running.\n", id); - } - else - { - CONMSG("Plugin %d is stopped: %s\n", id, run_msg); - } - } - CONMSG(" Name: \"%s\" by %s\n", pl->m_API->GetName(), pl->m_API->GetAuthor()); - CONMSG(" Version: %s\n", pl->m_API->GetVersion()); - CONMSG(" Description: %s\n", pl->m_API->GetDescription()); - CONMSG(" License: %s\n", pl->m_API->GetLicense()); - CONMSG(" URL: %s\n", pl->m_API->GetURL()); - CONMSG(" Details: API %03d, Date: %s\n", pl->m_API->GetApiVersion(), pl->m_API->GetDate()); - } - CONMSG("File: %s\n\n", pl->m_File.c_str()); - - return true; - } - else - { - CONMSG("Usage: meta info \n"); - - return true; - } - } - else if (strcmp(command, "pause") == 0) - { - if (args >= 2) - { - int id = atoi(info->GetArg(2)); - - char error[255]; - - if (!g_PluginMngr.Pause(id, error, sizeof(error))) - { - CONMSG("Pause failed: %s\n", error); - return true; - } - - CONMSG("Plugin %d has been paused.\n", id); - - return true; - } - else - { - CONMSG("Usage: meta pause \n"); - - return true; - } - } - else if (strcmp(command, "unpause") == 0) - { - if (args >= 2) - { - int id = atoi(info->GetArg(2)); - char error[255]; - - if (!g_PluginMngr.Unpause(id, error, sizeof(error))) - { - CONMSG("Unpause failed: %s\n", error); - return true; - } - - CONMSG("Plugin %d has been unpaused.\n", id); - - return true; - } - else - { - CONMSG("Usage: meta unpause \n"); - - return true; - } - } - else if (strcmp(command, "load") == 0) - { - if (args >= 2) - { - const char *file = info->GetArg(2); - char full_path[255]; - - const char *alias = g_PluginMngr.LookupAlias(file); - if (alias) - { - file = alias; - } - - g_Metamod.GetFullPluginPath(file, full_path, sizeof(full_path)); - - char error[255]={0}; - bool already; - CPluginManager::CPlugin *pl; - - // If we've recently tried to unload plugins, they might still - // be in the unload queue. Force them out now. This is not - // lowered to CPluginManager because it's not strictly safe - // there. - g_SourceHook.ResolvePendingUnloads(true); - - PluginId id = g_PluginMngr.Load(full_path, Pl_Console, already, error, sizeof(error)); - pl = g_PluginMngr.FindById(id); - if (!pl || id < Pl_MinId || (pl->m_Status < Pl_Paused)) - { - CONMSG("Failed to load plugin %s (%s).\n", file, error); - return true; - } - - if (!already) - { - CONMSG("Plugin \"%s\" loaded with id %d.\n", pl->m_API->GetName(), pl->m_Id); - } else { - CONMSG("Plugin \"%s\" is already loaded as %d.\n", pl->m_API->GetName(), pl->m_Id); - } - - return true; - } - else - { - CONMSG("Usage: meta load \n"); - - return true; - } - } - else if ( (strcmp(command, "alias") == 0) || - (strcmp(command, "aliases") == 0) ) - { - if (args >= 3) - { - const char *alias = info->GetArg(2); - const char *value = info->GetArg(3); - - g_PluginMngr.SetAlias(alias, value); - if (value == NULL || value[0] == '\0') - { - CONMSG("Deleted alias: %s.\n", alias); - } else { - CONMSG("Set alias \"%s\" to: %s\n", alias, value); - } - } - else if (args >= 2) - { - const char *alias = info->GetArg(2); - const char *value = g_PluginMngr.LookupAlias(alias); - if (value) - { - CONMSG("Alias \"%s\" is set to: %s\n", alias, value); - } else { - CONMSG("Alias \"%s\" was not found.\n", alias); - } - } - else - { - List::iterator iter, end; - CNameAlias *p; - - iter = g_PluginMngr._alias_begin(); - end = g_PluginMngr._alias_end(); - size_t total = 0; - if (iter != end) - { - CONMSG("%-10.9s %s\n", "Alias", "File"); - CONMSG(" --- \n"); - for (; iter!=end; iter++) - { - p = (*iter); - CONMSG("%-10.9s %s\n", p->alias.c_str(), p->value.c_str()); - total++; - } - CONMSG(" --- \n"); - CONMSG("%d aliases total.\n", total); - } - else - { - CONMSG("No aliases found.\n"); - } - } - return true; - } - else if (strcmp(command, "unload") == 0) - { - if (args >= 2) - { - const char *file = info->GetArg(2); - int id = atoi(file); - char error[255]={0}; - - if (id == 0 && isalpha(file[0])) - { - char full_path[255]; - const char *alias = g_PluginMngr.LookupAlias(file); - - if (alias) - { - file = alias; - } - - g_Metamod.GetFullPluginPath(file, full_path, sizeof(full_path)); - - List::iterator iter, end; - CPluginManager::CPlugin *pl; - iter = g_PluginMngr._begin(); - end = g_PluginMngr._end(); - for (; iter!=end; iter++) - { - pl = (*iter); - if (strcmp(pl->m_File.c_str(), full_path) == 0) - { - id = pl->m_Id; - break; - } - } - if (id == 0) - { - CONMSG("Plugin \"%s\" not found.\n", full_path); - return true; - } - } - - if (!g_PluginMngr.Unload(id, false, error, sizeof(error))) - { - CONMSG("Unload failed: %s\n", error); - return true; - } - - CONMSG("Plugin %d unloaded.\n", id); - } - else - { - CONMSG("Usage: meta unload \n"); - } - return true; - } - else if (strcmp(command, "force_unload") == 0) - { - if (args >= 2) - { - int id = atoi(info->GetArg(2)); - char error[255]={0}; - - if (!g_PluginMngr.Unload(id, false, error, sizeof(error))) - { - CONMSG("Force unload failed: %s\n", error); - return true; - } - - CONMSG("Plugin %d force unloaded.\n", id); - - return true; - } - else - { - CONMSG("Usage: meta force_unload \n"); - - return true; - } - } - else if (strcmp(command, "clear") == 0) - { - if (!g_PluginMngr.UnloadAll()) - { - CONMSG("One or more plugins resisted removal (cleaned anyway).\n"); - return true; - } - - CONMSG("All plugins unloaded.\n"); - - return true; - } - else if (strcmp(command, "retry") == 0) - { - if (args >= 2) - { - int id = atoi(info->GetArg(2)); - char error[255]; - - if (!g_PluginMngr.Retry(id, error, sizeof(error))) - { - CONMSG("Error reloading plugin: %s\n", error); - return true; - } - - CONMSG("Plugin %d successfully reloaded.\n", id); - - return true; - } - else - { - CONMSG("Usage: meta retry \n"); - - return true; - } - } - } - - CONMSG("Metamod:Source Menu\n"); - CONMSG("usage: meta [arguments]\n"); - CONMSG(" alias - List or set an alias\n"); - CONMSG(" clear - Unload all plugins forcefully\n"); - CONMSG(" cmds - Show plugin commands\n"); - CONMSG(" cvars - Show plugin cvars\n"); - CONMSG(" credits - About Metamod:Source\n"); - CONMSG(" force_unload - Forcefully unload a plugin\n"); - CONMSG(" game - Information about GameDLL\n"); - CONMSG(" info - Information about a plugin\n"); - CONMSG(" list - List plugins\n"); - CONMSG(" load - Load a plugin\n"); - CONMSG(" pause - Pause a running plugin\n"); - CONMSG(" refresh - Reparse plugin files\n"); - CONMSG(" retry - Attempt to reload a plugin\n"); - CONMSG(" unload - Unload a loaded plugin\n"); - CONMSG(" unpause - Unpause a paused plugin\n"); - CONMSG(" version - Version information\n"); - - return true; -} - -#if SOURCE_ENGINE == SE_DOTA -bool Command_ClientMeta(int client, IMetamodSourceCommandInfo *info) -#else -bool Command_ClientMeta(edict_t *client, IMetamodSourceCommandInfo *info) -#endif -{ - const char *cmd = info->GetArg(0); - - if (strcmp(cmd, "meta") == 0) - { - unsigned int args = info->GetArgCount(); - if (args == 1) - { - const char *subcmd = info->GetArg(1); - - if (strcmp(subcmd, "credits") == 0) - { - ReplyCredits(client); - - return true; - } - else if(strcmp(subcmd, "version") == 0) - { - ReplyVersion(client); - - return true; - } - else if(strcmp(subcmd, "list") == 0) - { - CPluginManager::CPlugin *pl; - ISmmPlugin *plapi; - const char *plname; - PluginIter i; - char buffer[256]; - int len = 0; - int plnum = 0; - - for (i = g_PluginMngr._begin(); i != g_PluginMngr._end(); i++, len=0) - { - pl = (*i); - if (pl && pl->m_Status == Pl_Running) - { - plapi = pl->m_API; - if (!plapi || !plapi->QueryRunning(NULL, 0)) - { - continue; - } - plnum++; - - len += UTIL_Format(buffer, sizeof(buffer), " [%02d]", plnum); - - plname = IS_STR_FILLED(plapi->GetName()) ? plapi->GetName() : pl->m_File.c_str(); - len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " %s", plname); - - if (IS_STR_FILLED(plapi->GetVersion())) - { - len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " (%s)", plapi->GetVersion()); - } - if (IS_STR_FILLED(plapi->GetAuthor())) - { - UTIL_Format(&buffer[len], sizeof(buffer)-len, " by %s", plapi->GetAuthor()); - } - - CLIENT_CONMSG(client, "%s\n", buffer); - } - } - - if (!plnum) - { - CLIENT_CONMSG(client, "No active plugins loaded.\n"); - } - - return true; - } - } - - CLIENT_CONMSG(client, "Metamod:Source Menu\n"); - CLIENT_CONMSG(client, "usage: meta \n"); - CLIENT_CONMSG(client, " credits - About Metamod:Source\n"); - CLIENT_CONMSG(client, " list - List plugins\n"); - CLIENT_CONMSG(client, " version - Version information\n"); - - return true; - } - - return false; -} diff --git a/utils/mmsource/core/metamod_console.h b/utils/mmsource/core/metamod_console.h deleted file mode 100644 index ef3d52901..000000000 --- a/utils/mmsource/core/metamod_console.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - * vim: set ts=4 : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2008 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_CONCOMMANDS_H -#define _INCLUDE_CONCOMMANDS_H - -#include "metamod_provider.h" - -bool Command_Meta(IMetamodSourceCommandInfo *info); -#if SOURCE_ENGINE == SE_DOTA -bool Command_ClientMeta(int client, IMetamodSourceCommandInfo *info); -#else -bool Command_ClientMeta(edict_t *client, IMetamodSourceCommandInfo *info); -#endif - -#endif //_INCLUDE_CONCOMMANDS_H diff --git a/utils/mmsource/core/metamod_oslink.cpp b/utils/mmsource/core/metamod_oslink.cpp deleted file mode 100644 index a100ea720..000000000 --- a/utils/mmsource/core/metamod_oslink.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/** - * vim: set ts=4 : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2008 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - * Version: $Id$ - */ - -#include -#include "metamod_oslink.h" -#include -#include -#if defined __linux__ || defined __APPLE__ -#include -#endif - -#if defined __WIN32__ || defined _WIN32 || defined WIN32 -const char *dlerror() -{ - static char buf[1024]; - DWORD num; - - num = GetLastError(); - - if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - num, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - buf, - sizeof(buf), - NULL) - == 0) - { - _snprintf(buf, sizeof(buf), "unknown error %x", num); - } - - return buf; -} -#endif - -#if defined __linux_ || defined __APPLE___ -int GetLastError() -{ - return errno; -} - -extern "C" void __cxa_guard_acquire(void) -{ -} - -extern "C" void __cxa_guard_release(void) -{ -} -#endif - -bool GetFileOfAddress(void *pAddr, char *buffer, size_t maxlength) -{ -#if defined WIN32 || defined _WIN32 - MEMORY_BASIC_INFORMATION mem; - if (!VirtualQuery(pAddr, &mem, sizeof(mem))) - return false; - if (mem.AllocationBase == NULL) - return false; - HMODULE dll = (HMODULE)mem.AllocationBase; - GetModuleFileName(dll, (LPTSTR)buffer, maxlength); -#elif defined __linux__ || defined __APPLE__ - Dl_info info; - if (!dladdr(pAddr, &info)) - return false; - if (!info.dli_fbase || !info.dli_fname) - return false; - const char *dllpath = info.dli_fname; - snprintf(buffer, maxlength, "%s", dllpath); -#endif - return true; -} - -#if defined __GNUC__ -void * operator new(size_t size) { - return malloc(size); -} - -void * operator new[](size_t size) { - return malloc(size); -} - -void operator delete(void * ptr) { - free(ptr); -} - -void operator delete[](void * ptr) { - free(ptr); -} -#endif - diff --git a/utils/mmsource/core/metamod_oslink.h b/utils/mmsource/core/metamod_oslink.h deleted file mode 100644 index a2b579c27..000000000 --- a/utils/mmsource/core/metamod_oslink.h +++ /dev/null @@ -1,112 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2009 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#ifndef _INCLUDE_OSLINK_H -#define _INCLUDE_OSLINK_H - -/** - * @brief Defines OS-independent information - * @file oslink.h - */ - -#if defined __WIN32__ || defined _WIN32 || defined WIN32 - #define WIN32_LEAN_AND_MEAN - #define OS_WIN32 - #if defined _MSC_VER && _MSC_VER >= 1400 - #undef ARRAYSIZE - #else - #define mkdir(a) _mkdir(a) - #endif - #include - #include - #include - #define dlmount(x) LoadLibrary(x) - #define dlsym(x, s) GetProcAddress(x, s) - #define dlclose(x) FreeLibrary(x) - const char* dlerror(); - #define abspath(x, s) _fullpath(x, s, sizeof(x)) - #define PATH_SEP_STR "\\" - #define PATH_SEP_CHAR '\\' - #define ALT_SEP_CHAR '/' - #define PATH_SIZE MAX_PATH - #define strcasecmp stricmp - inline bool _IsPathSepChar(char c) { return (c == '/' || c == '\\'); } -#elif defined __linux__ || defined __APPLE__ - #if defined __linux__ - #define OS_LINUX - #elif defined __APPLE__ - #define OS_DARWIN - #include - #endif - #include - #include - #include - #include - typedef void* HINSTANCE; - #define dlmount(x) dlopen(x,RTLD_NOW) - #define abspath(x, s) realpath(s, x) - #define PATH_SEP_STR "/" - #define PATH_SEP_CHAR '/' - #define ALT_SEP_CHAR '\\' - #define PATH_SIZE PATH_MAX - #ifndef stricmp - #define stricmp strcasecmp - #endif - #ifndef strnicmp - #define strnicmp strncasecmp - #endif - inline bool _IsPathSepChar(char c) { return (c == '/'); } -#endif - -#if defined __linux__ || defined __APPLE__ - #include - int GetLastError(); -#endif - -bool GetFileOfAddress(void *pAddr, char *buffer, size_t maxlength); - -#if defined __WIN32__ || defined _WIN32 || defined WIN32 - #define SMM_API extern "C" __declspec(dllexport) -#elif defined __GNUC__ - #define SMM_API extern "C" __attribute__ ((visibility("default"))) -#endif - -#if defined __WIN32__ || defined _WIN32 || defined WIN32 - typedef __int64 int64_t; - typedef unsigned __int64 uint64_t; - typedef __int32 int32_t; - typedef unsigned __int32 uint32_t; -#elif defined __GNUC__ -#include -#endif - -#if !defined __linux__ && !defined __APPLE__ - #define snprintf _snprintf - #if defined _MSC_VER && _MSC_VER < 1500 - #define vsnprintf _vsnprintf - #endif -#endif - -#endif //_INCLUDE_OSLINK_H diff --git a/utils/mmsource/core/metamod_plugins.cpp b/utils/mmsource/core/metamod_plugins.cpp deleted file mode 100644 index e44cbf8a6..000000000 --- a/utils/mmsource/core/metamod_plugins.cpp +++ /dev/null @@ -1,855 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2009 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#include -#include "metamod_oslink.h" -#include "metamod.h" -#include "metamod_plugins.h" -#include "metamod_util.h" - -/** - * @brief Implements functions from CPlugin.h - * @file CPlugin.cpp - */ - -using namespace SourceMM; - -#define ITER_PLEVENT(evn, plid) \ - CPluginManager::CPlugin *_Xpl; \ - SourceHook::List::iterator event; \ - IMetamodListener *api; \ - for (PluginIter iter = g_PluginMngr._begin(); iter != g_PluginMngr._end(); iter++) { \ - _Xpl = (*iter); \ - if (_Xpl->m_Id == plid) \ - continue; \ - for (event=_Xpl->m_Events.begin(); event!=_Xpl->m_Events.end(); event++) { \ - api = (*event); \ - api->evn(plid); \ - } \ - } - -CPluginManager g_PluginMngr; - -MetamodVersionInfo GlobVersionInfo = -{ - METAMOD_API_MAJOR, - METAMOD_API_MINOR, - SH_IFACE_VERSION, - SH_IMPL_VERSION, - PLAPI_MIN_VERSION, - METAMOD_PLAPI_VERSION, - SOURCE_ENGINE_UNKNOWN, - NULL -}; - -CPluginManager::CPluginManager() -{ - m_LastId = Pl_MinId; - m_AllLoaded = false; -} - -CPluginManager::~CPluginManager() -{ - SourceHook::List::iterator iter; - - for (iter = m_Aliases.begin(); iter != m_Aliases.end(); iter++) - { - delete (*iter); - } - - m_Aliases.clear(); -} - -const char *CPluginManager::LookupAlias(const char *alias) -{ - SourceHook::List::iterator iter; - CNameAlias *p; - - for (iter = m_Aliases.begin(); iter != m_Aliases.end(); iter++) - { - p = (*iter); - if (p->alias.compare(alias) == 0) - { - return p->value.c_str(); - } - } - - return NULL; -} - -SourceHook::List::iterator CPluginManager::_alias_begin() -{ - return m_Aliases.begin(); -} - -SourceHook::List::iterator CPluginManager::_alias_end() -{ - return m_Aliases.end(); -} - -void CPluginManager::SetAlias(const char *alias, const char *value) -{ - SourceHook::List::iterator iter; - CNameAlias *p; - - for (iter = m_Aliases.begin(); iter != m_Aliases.end(); iter++) - { - p = (*iter); - if (p->alias.compare(alias) == 0) - { - if (value[0] == '\0') - { - iter = m_Aliases.erase(iter); - return; - } - else - { - p->value.assign(value); - return; - } - } - } - - if (value[0] != '\0') - { - p = new CNameAlias; - - p->alias.assign(alias); - p->value.assign(value); - - m_Aliases.push_back(p); - } -} - -CPluginManager::CPlugin::CPlugin() : m_Id(0), m_Source(0), m_API(NULL), m_Lib(NULL), m_UnloadFn(NULL) -{ - -} - -PluginId CPluginManager::Load(const char *file, PluginId source, bool &already, char *error, size_t maxlen) -{ - already = false; - //Check if we're about to reload an old plugin - PluginIter i = m_Plugins.begin(); - while (i != m_Plugins.end()) - { - if ((*i) && UTIL_PathCmp(file, (*i)->m_File.c_str())) - { - if ((*i)->m_Status < Pl_Paused) - { - //Attempt to load the plugin again - already = true; - i = m_Plugins.erase(i); - continue; - } - else - { - //No need to load it - already = true; - return (*i)->m_Id; - } - } - i++; - } - - CPlugin *pl = _Load(file, source, error, maxlen); - - if (!pl) - { - return Pl_BadLoad; - } - - ITER_PLEVENT(OnPluginLoad, pl->m_Id); - - return pl->m_Id; -} - -CPluginManager::CPlugin *CPluginManager::FindById(PluginId id) -{ - PluginIter i; - - for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++) - { - if ( (*i)->m_Id == id )\ - { - return (*i); - } - } - - return NULL; -} - -void CPluginManager::SetAllLoaded() -{ - if (m_AllLoaded) - { - return; - } - - m_AllLoaded = true; - PluginIter i; - - for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++) - { - if ( (*i) && (*i)->m_Status == Pl_Running && (*i)->m_API ) - { - //API 4 is when we added this callback - //Min version is now 5, so we ignore this check - //if ( (*i)->m_API->GetApiVersion() >= 004 ) - (*i)->m_API->AllPluginsLoaded(); - } - } -} - -bool CPluginManager::Pause(PluginId id, char *error, size_t maxlen) -{ - CPlugin *pl = FindById(id); - - if (!pl) - { - UTIL_Format(error, maxlen, "Plugin id not found"); - return false; - } - - bool ret; - - if ((ret=_Pause(pl, error, maxlen)) == true) - { - ITER_PLEVENT(OnPluginPause, pl->m_Id); - } - - return ret; -} - -bool CPluginManager::Unpause(PluginId id, char *error, size_t maxlen) -{ - CPlugin *pl = FindById(id); - - if (!pl) - { - UTIL_Format(error, maxlen, "Plugin id not found"); - return false; - } - - bool ret; - - if ( (ret=_Unpause(pl, error, maxlen)) == true ) - { - ITER_PLEVENT(OnPluginUnpause, pl->m_Id); - } - - return ret; -} - -bool CPluginManager::Unload(PluginId id, bool force, char *error, size_t maxlen) -{ - CPlugin *pl = FindById(id); - - if (!pl) - { - UTIL_Format(error, maxlen, "Plugin %d not found", id); - return false; - } - - bool ret; - PluginId old_id = pl->m_Id; - if ( (ret=_Unload(pl, force, error, maxlen)) == true ) - { - ITER_PLEVENT(OnPluginUnload, old_id); - } - - return ret; -} - -bool CPluginManager::Retry(PluginId id, char *error, size_t len) -{ - PluginIter i; - char buffer[64]; - for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++) - { - if ( (*i) && (*i)->m_Id == id ) - { - if ( (*i)->m_Status >= Pl_Paused) - { - UTIL_Format(error, len, "Plugin %d is already running.", id); - return false; - } - CPlugin *pl = _Load((*i)->m_File.c_str(), Pl_Console, error, len); - if (!pl) - { - return false; - } - if (pl->m_Status >= Pl_Paused) - { - //Now it gets crazy... unload the original copy. - _Unload( (*i), true, buffer, sizeof(buffer)-1 ); - - //Set the new copy's id - pl->m_Id = id; - - //We just wasted an id... reclaim it - m_LastId--; - - return true; - } - else - { - //don't really care about the buffer here - _Unload(pl, true, buffer, sizeof(buffer)-1); - - //We just wasted an id... reclaim it - m_LastId--; - return false; - } - } - } - - UTIL_Format(error, len, "Plugin %d not found,", id); - return false; -} - -CPluginManager::CPlugin *CPluginManager::FindByAPI(ISmmPlugin *api) -{ - PluginIter i; - - //don't find bad plugins! - if (!api) - { - return NULL; - } - - for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++) - { - if ((*i)->m_API == api) - { - return (*i); - } - } - - return NULL; -} - -int CPluginManager::GetPluginCount() -{ - return (int)m_Plugins.size(); -} - -const char *CPluginManager::GetStatusText(CPlugin *pl) -{ - switch (pl->m_Status) - { - case Pl_NotFound: - return "NOFILE"; - case Pl_Error: - return "ERROR"; - case Pl_Refused: - return "FAILED"; - case Pl_Paused: - return "PAUSED"; - case Pl_Running: - { - if (pl->m_API && pl->m_API->QueryRunning(NULL, 0)) - { - return "STOPPED"; - } else { - return "RUNNING"; - } - } - default: - return "-"; - } -} - -struct Unloader : public SourceHook::Impl::UnloadListener -{ - CPluginManager::CPlugin *plugin_; - bool destroy_; - - Unloader(CPluginManager::CPlugin *plugin, bool destroy) - : plugin_(plugin), destroy_(destroy) - { } - - void ReadyToUnload(SourceHook::Plugin plug) - { - if (plugin_->m_UnloadFn != NULL) - plugin_->m_UnloadFn(); - - dlclose(plugin_->m_Lib); - - if (destroy_) - { - delete plugin_; - } - else - { - plugin_->m_Lib = NULL; - plugin_->m_API = NULL; - } - - delete this; - } -}; - -CPluginManager::CPlugin *CPluginManager::_Load(const char *file, PluginId source, char *error, size_t maxlen) -{ - FILE *fp; - CPlugin *pl; - - pl = new CPlugin(); - *error = '\0'; - - //Add plugin to list - pl->m_Id = m_LastId; - pl->m_File.assign(file); - m_Plugins.push_back(pl); - m_LastId++; - - //Check if the file even exists - fp = fopen(file, "r"); - if (!fp) - { - if (error) - { - UTIL_Format(error, maxlen, "File not found: %s", file); - } - pl->m_Status = Pl_NotFound; - } - - if (fp) - { - fclose(fp); - fp = NULL; - - //Load the file - pl->m_Lib = dlmount(file); - if (!pl->m_Lib) - { - if (error) - { - UTIL_Format(error, maxlen, "%s", dlerror()); - } - pl->m_Status = Pl_Error; - } - else - { - pl->m_API = NULL; - - /** - * First, try the new "advanced" interface - */ - METAMOD_FN_LOAD fnLoad = (METAMOD_FN_LOAD)dlsym(pl->m_Lib, "CreateInterface_MMS"); - if (fnLoad != NULL) - { - if (GlobVersionInfo.source_engine == SOURCE_ENGINE_UNKNOWN) - { - GlobVersionInfo.source_engine = g_Metamod.GetSourceEngineBuild(); - } - if (GlobVersionInfo.game_dir == NULL) - { - GlobVersionInfo.game_dir = strrchr(g_Metamod.GetBaseDir(), PATH_SEP_CHAR) + 1; - } - - /* Build path information */ - char file_path[256]; - size_t len = g_Metamod.PathFormat(file_path, sizeof(file_path), "%s", file); - - for (size_t i = len - 1; i < len; i--) - { - if (_IsPathSepChar(file_path[i])) - { - file_path[i] = '\0'; - break; - } - } - - MetamodLoaderInfo info; - info.pl_file = file; - info.pl_path = file_path; - - pl->m_API = fnLoad(&GlobVersionInfo, &info); -#if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_TF2 - /* For plugin compat - try loading again using original OB if OB-Valve has failed */ - if (pl->m_API == NULL) - { - GlobVersionInfo.source_engine = SOURCE_ENGINE_ORANGEBOXVALVE_DEPRECATED; - pl->m_API = fnLoad(&GlobVersionInfo, &info); - if (pl->m_API == NULL) - { - GlobVersionInfo.source_engine = SOURCE_ENGINE_ORANGEBOX; - pl->m_API = fnLoad(&GlobVersionInfo, &info); - } - GlobVersionInfo.source_engine = g_Metamod.GetSourceEngineBuild(); - } -#endif - pl->m_UnloadFn = (METAMOD_FN_UNLOAD)dlsym(pl->m_Lib, "UnloadInterface_MMS"); - } - - /** - * If we didn't get anything, try the normal/simple interface. - */ - if (pl->m_API == NULL) - { - CreateInterfaceFn pfn = (CreateInterfaceFn)(dlsym(pl->m_Lib, PL_EXPOSURE_C)); - if (!pfn) - { - if (error) - { - UTIL_Format(error, maxlen, "Function %s not found", PL_EXPOSURE_C); - } - pl->m_Status = Pl_Error; - } - else - { - pl->m_API = static_cast((pfn)(METAMOD_PLAPI_NAME, NULL)); - - if (!pl->m_API) - { - if (error) - { - UTIL_Format(error, maxlen, "Failed to get API"); - } - pl->m_Status = Pl_Error; - } - } - } - - if (pl->m_API != NULL) - { - int api = pl->m_API->GetApiVersion(); - if (api < PLAPI_MIN_VERSION) - { - if (error) - { - if (api == 13) - { - UTIL_Format(error, maxlen, "Plugin uses experimental Metamod build, probably 1.6.x (%d < %d)", api, PLAPI_MIN_VERSION); - } - else if (api <= 12 && api >= 7) - { - UTIL_Format(error, maxlen, "Older Metamod version required, probably 1.4.x (%d < %d)", api, PLAPI_MIN_VERSION); - } - else - { - UTIL_Format(error, maxlen, "Older Metamod version required, probably 1.0 (%d < %d)", api, PLAPI_MIN_VERSION); - } - } - pl->m_Status = Pl_Error; - } - else if (api > METAMOD_PLAPI_VERSION) - { - if (error) - { - UTIL_Format(error, maxlen, "Plugin requires newer Metamod version (%d > %d)", api, METAMOD_PLAPI_VERSION); - } - pl->m_Status = Pl_Error; - } - else - { - if (pl->m_API->Load(pl->m_Id, &g_Metamod, error, maxlen, m_AllLoaded)) - { - pl->m_Status = Pl_Running; - if (m_AllLoaded) - { - pl->m_API->AllPluginsLoaded(); - } - } - else - { - pl->m_Status = Pl_Refused; - } - } - } - } - } - - if (pl->m_Lib && (pl->m_Status < Pl_Paused)) - { - pl->m_Events.clear(); - UnregAllConCmds(pl); - g_SourceHook.UnloadPlugin(pl->m_Id, new Unloader(pl, false)); - } - - return pl; -} - -bool CPluginManager::_Unload(CPluginManager::CPlugin *pl, bool force, char *error, size_t maxlen) -{ - if (error) - { - *error = '\0'; - } - - if (pl->m_API && pl->m_Lib) - { - //Note, we'll always tell the plugin it will be unloading... - if (pl->m_API->Unload(error, maxlen) || force) - { - pl->m_Events.clear(); - UnregAllConCmds(pl); - - //Remove the plugin from the list - PluginIter i; - for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++) - { - if ( (*i)->m_Id == pl->m_Id ) - { - i = m_Plugins.erase(i); - break; - } - } - - //Make sure to detach it from sourcehook! - g_SourceHook.UnloadPlugin(pl->m_Id, new Unloader(pl, true)); - return true; - } - } else { - //The plugin is not valid, and let's just remove it from the list anyway - PluginIter i; - for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++) - { - if ( (*i)->m_Id == pl->m_Id ) - { - i = m_Plugins.erase(i); - break; - } - } - delete pl; - - return true; - } - - return false; -} - -bool CPluginManager::_Pause(CPluginManager::CPlugin *pl, char *error, size_t maxlen) -{ - if (error) - { - *error = '\0'; - } - - if (pl->m_Status != Pl_Running || !pl->m_API) - { - if (error) - { - UTIL_Format(error, maxlen, "Plugin cannot be paused"); - } - } - else - { - if (pl->m_API->Pause(error, maxlen)) - { - g_SourceHook.PausePlugin(pl->m_Id); - pl->m_Status = Pl_Paused; - - return true; - } - } - - return false; -} - -bool CPluginManager::_Unpause(CPluginManager::CPlugin *pl, char *error, size_t maxlen) -{ - if (error) - { - *error = '\0'; - } - - if (pl->m_Status != Pl_Paused || !pl->m_API) - { - if (error) - { - UTIL_Format(error, maxlen, "Plugin cannot be unpaused"); - } - } - else - { - if (pl->m_API->Unpause(error, maxlen)) - { - g_SourceHook.UnpausePlugin(pl->m_Id); - pl->m_Status = Pl_Running; - - return true; - } - } - - return false; -} - -bool CPluginManager::UnloadAll() -{ - PluginIter i; - - char error[128]; - bool status = true; - - while ((i = m_Plugins.begin()) != m_Plugins.end()) - { - if ( !_Unload( (*i), true, error, sizeof(error)) ) - { - status = false; - } - } - - return status; -} - -bool CPluginManager::Query(PluginId id, const char **file, Pl_Status *status, PluginId *source) -{ - CPlugin *pl = FindById(id); - - if (!pl) - { - return false; - } - - if (file != NULL) - { - *file = pl->m_File.c_str(); - } - - if (status != NULL) - { - *status = pl->m_Status; - } - - if (source != NULL) - { - *source = pl->m_Source; - } - - return true; -} - -bool CPluginManager::QueryRunning(PluginId id, char *error, size_t maxlength) -{ - CPlugin *pl = FindById(id); - - if (!pl || !pl->m_API) - { - if (error) - { - UTIL_Format(error, maxlength, "Plugin not valid"); - } - return false; - } - - return pl->m_API->QueryRunning(error, maxlength); -} - -bool CPluginManager::QueryHandle(PluginId id, void **handle) -{ - CPlugin *pl = FindById(id); - - if (!pl) - { - return false; - } - - if (handle) - { - *handle = static_cast(pl->m_Lib); - } - - return true; -} - -PluginIter CPluginManager::_begin() -{ - return m_Plugins.begin(); -} - -PluginIter CPluginManager::_end() -{ - return m_Plugins.end(); -} - -void CPluginManager::AddPluginCvar(ISmmPlugin *api, ConCommandBase *pCvar) -{ - CPlugin *pl = FindByAPI(api); - - if (!pl) - { - return; - } - - pl->m_Cvars.push_back(pCvar); -} - -void CPluginManager::AddPluginCmd(ISmmPlugin *api, ConCommandBase *pCmd) -{ - CPlugin *pl = FindByAPI(api); - - if (!pl) - { - return; - } - - pl->m_Cmds.push_back(pCmd); -} - -void CPluginManager::RemovePluginCvar(ISmmPlugin *api, ConCommandBase *pCvar) -{ - CPlugin *pl = FindByAPI(api); - - if (!pl) - { - return; - } - - pl->m_Cvars.remove(pCvar); -} - -void CPluginManager::RemovePluginCmd(ISmmPlugin *api, ConCommandBase *pCmd) -{ - CPlugin *pl = FindByAPI(api); - - if (!pl) - { - return; - } - - pl->m_Cmds.remove(pCmd); -} - -void CPluginManager::UnregAllConCmds(CPlugin *pl) -{ - SourceHook::List::iterator i; - - /* :TODO: */ - for (i=pl->m_Cvars.begin(); i!=pl->m_Cvars.end(); i++) - { - g_Metamod.UnregisterConCommandBase(pl->m_Id, (*i) ); - } - pl->m_Cvars.clear(); - - for (i=pl->m_Cmds.begin(); i!=pl->m_Cmds.end(); i++) - { - g_Metamod.UnregisterConCommandBase(pl->m_Id, (*i) ); - } - pl->m_Cmds.clear(); -} - diff --git a/utils/mmsource/core/metamod_plugins.h b/utils/mmsource/core/metamod_plugins.h deleted file mode 100644 index 5bf4f9046..000000000 --- a/utils/mmsource/core/metamod_plugins.h +++ /dev/null @@ -1,170 +0,0 @@ -/** - * vim: set ts=4 : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2008 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_CPLUGIN_H -#define _INCLUDE_CPLUGIN_H - -/** - * @brief Implementation of Plugin API and Management routines - * @file CPlugin.cpp - */ - -#include -#include -#include -#include -#include -#include -#include -#include "metamod_oslink.h" - -/** - * History of plugin versions: (M=min, C=current) - * 1: Initial interface - * 2: Added GetLogTag() - * 3: Moved GetApiVersion() to top (2005-04-16) - * 4: Added AllPluginsLoaded() callback (2005-04-18) - * 5: Bumped version for SourceHook V4 (2005-05-01) - * 6: Added functions for console printing (2005-05-26) - * 7: Changed template libraries (2005-08-11) - * New loading structure mechanism - * New SourceHook version - * 8: New SourceHook version (2005-12-23) - * New ISmmAPI additions - * 9: New ISmmPluginManager additions - * 10: Added VSP listen functions to ISmmAPI and IMetamodListener (2007-02-09) - * 11: New SourceHook version v4.5 (May, 2007) - * 12: Orange Box API - * 13: Breaking of API for next SH version and other API changes - * MC 14: ABI stability reached for 1.6.0 changes - */ - -#define PLAPI_MIN_VERSION 14 - -struct CNameAlias -{ - SourceHook::String alias; - SourceHook::String value; -}; -/** - * @brief Implements Plugin Manager API - */ -class CPluginManager : public ISmmPluginManager -{ -public: - /** - * @brief Internal structure for holding plugin data - */ - class CPlugin - { - public: - CPlugin(); - public: - PluginId m_Id; - SourceHook::String m_File; - Pl_Status m_Status; - PluginId m_Source; - ISmmPlugin *m_API; - HINSTANCE m_Lib; - SourceHook::List m_Cvars; - SourceHook::List m_Cmds; - SourceHook::List m_Events; - METAMOD_FN_UNLOAD m_UnloadFn; - }; -public: - CPluginManager(); - ~CPluginManager(); - void SetAllLoaded(); -public: - PluginId Load(const char *file, PluginId source, bool &already, char *error, size_t maxlen); - bool Unload(PluginId id, bool force, char *error, size_t maxlen); - bool Pause(PluginId id, char *error, size_t maxlen); - bool Unpause(PluginId id, char *error, size_t maxlen); - bool UnloadAll(); - void SetAlias(const char *alias, const char *value); -public: - bool Query(PluginId id, const char **file, Pl_Status *status, PluginId *source); - bool QueryRunning(PluginId id, char *error, size_t maxlength); - bool QueryHandle(PluginId id, void **handle); - - void AddPluginCvar(ISmmPlugin *api, ConCommandBase *pCvar); - void AddPluginCmd(ISmmPlugin *api, ConCommandBase *pCmd); - void RemovePluginCvar(ISmmPlugin *api, ConCommandBase *pCvar); - void RemovePluginCmd(ISmmPlugin *api, ConCommandBase *pCmd); - - /** - * @brief Finds a plugin by Id - * - * @param id Id of plugin - * @return CPlugin on success, NULL otherwise - */ - CPlugin *FindById(PluginId id); - - CPlugin *FindByAPI(ISmmPlugin *api); - - /** - * @brief Attempts to reload a failed plugin - * - * @param id Id of plugin - * @param error Error message buffer - * @param len Maximum length of buffer - * @return True on success, false otherwise - */ - bool Retry(PluginId id, char *error, size_t len); - - int GetPluginCount(); - const char *GetStatusText(CPlugin *pl); - - //get alias info - const char *LookupAlias(const char *alias); - SourceHook::List::iterator _alias_begin(); - SourceHook::List::iterator _alias_end(); - - //Internal iterators - SourceHook::List::iterator _begin(); - SourceHook::List::iterator _end(); -private: - //These are identical internal functions for the wrappers above. - CPlugin *_Load(const char *file, PluginId source, char *error, size_t maxlen); - bool _Unload(CPlugin *pl, bool force, char *error, size_t maxlen); - bool _Pause(CPlugin *pl, char *error, size_t maxlen); - bool _Unpause(CPlugin *pl, char *error, size_t maxlen); - void UnregAllConCmds(CPlugin *pl); -private: - PluginId m_LastId; - SourceHook::List m_Plugins; - SourceHook::List m_Aliases; - bool m_AllLoaded; -}; - -typedef SourceHook::List::iterator PluginIter; - -/** @brief Singleton for plugin manager */ -extern CPluginManager g_PluginMngr; - -#endif //_INCLUDE_CPLUGIN_H - diff --git a/utils/mmsource/core/metamod_provider.h b/utils/mmsource/core/metamod_provider.h deleted file mode 100644 index eda81773e..000000000 --- a/utils/mmsource/core/metamod_provider.h +++ /dev/null @@ -1,322 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2009 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#ifndef _INCLUDE_METAMOD_SOURCE_SUPPORT_H_ -#define _INCLUDE_METAMOD_SOURCE_SUPPORT_H_ - -namespace SourceMM -{ - enum - { - ConVarFlag_None = 0, - ConVarFlag_Notify = 1, - ConVarFlag_SpOnly = 2, - }; - - enum ProvidedHooks - { -#if SOURCE_ENGINE == SE_DOTA - ProvidedHook_StartChangeLevel = 0, - ProvidedHook_Init = 1, - ProvidedHook_StartupServer = 2, - ProvidedHook_SwitchToLoop = 3, -#else - ProvidedHook_LevelInit = 0, /**< IServerGameDLL::LevelInit */ - ProvidedHook_LevelShutdown = 1, /**< IServerGameDLL::LevelShutdown */ - ProvidedHook_GameInit = 4, /**< IServerGameDLL::GameInit */ -#endif - }; - - /** - * @brief Abstracts command information, since the new engine fixes the - * re-entrancy problems in the tokenization system. - */ - class IMetamodSourceCommandInfo - { - public: - /** - * @brief Returns the argument count such that arguments - * 1 to N are valid arguments, and 0 is the command name. - * - * @return Argument count. - */ - virtual unsigned int GetArgCount() =0; - - /** - * @brief Returns the string of an argument number. - * - * @param num Argument number. - * @return Argument text. - */ - virtual const char *GetArg(unsigned int num) =0; - - /** - * @brief Returns the entire command argument string. - * - * @return Argument string. - */ - virtual const char *GetArgString() =0; - }; - - class IMetamodSourceProvider - { - public: - /** - * @brief Returns whether source engine build is compatible. - * - * @param build Source engine build. - * @return True if compatible, false otherwise. - */ - virtual bool IsSourceEngineBuildCompatible(int build) =0; - - /** - * @brief Retrieves hook information for each callback. Each hook - * must be implemented. - * - * @param hook Hook information to provide. - * @param pInfo Non-NULL pointer to fill with information - * about the hook's virtual location. - * @return True if supported, false to fail, which - * will cause Metamod:Source to fail. - */ - virtual bool GetHookInfo(ProvidedHooks hook, SourceHook::MemFuncInfo *pInfo) =0; - - /** - * @brief Logs a message via IVEngineServer::LogPrint. - * - * @param buffer Buffer to print. - * @return True on success, false if not supported, - * or IVEngineServer is not yet known. - */ - virtual bool LogMessage(const char *buffer) =0; - - /** - * @brief Returns the command line value of a parameter. If ICvar - * is not yet loaded, this uses an equivalent function. - * - * @param key Parameter to look up. - * @param val Default string to return if none found. - * @return Parameter value. - */ - virtual const char *GetCommandLineValue(const char *key, const char *defval=NULL) =0; - - /** - * @brief Prints a string to the remote server console. - * - * Note: new lines are not appended. - * - * @param msg Message string. - */ - virtual void ConsolePrint(const char *msg) =0; - - /** - * @brief Returns whether remote printing is available. - * - * @return True if remote printing is available, - * otherwise returns false. - */ - virtual bool IsRemotePrintingAvailable() =0; - - /** - * @brief Prints text in the specified client's console. - * - * @param client Client edict pointer. - * @param msg Message string. - */ - virtual void ClientConsolePrint(edict_t *client, const char *msg) =0; - - /** - * @brief Halts the server with a fatal error message. - * - * No newline is appended. - * - * @param fmt Formatted message string. - * @param ... Format parameters. - */ - virtual void DisplayError(const char *fmt, ...) =0; - - /** - * @brief Sends the server a warning message. - * - * No newline is appended. - * - * @param fmt Formatted message string. - * @param ... Format parameters. - */ - virtual void DisplayWarning(const char *fmt, ...) =0; - - /** - * @brief Attempts to notify the provider of the gamedll version being - * used. - * - * @param iface Interface string. - * @return Version number on success, 0 otherwise. - */ - virtual int TryServerGameDLL(const char *iface) =0; - - /** - * @brief Notifies the provider that the DLLInit pre-hook is almost done. - */ - virtual void Notify_DLLInit_Pre(CreateInterfaceFn engineFactory, CreateInterfaceFn serverFactory) =0; - - virtual void Notify_DLLShutdown_Pre() =0; - - /** - * @brief Wrapper around IVEngineServer::ServerCommand() - * - * @param cmd Command string. - */ - virtual void ServerCommand(const char *cmd) =0; - - /** - * @brief Creates a ConVar pointer. - * - * @param name ConVar name. - * @param defval Default value string. - * @param flags ConVar flags. - * @param help Help text. - * @return ConVar pointer. - */ - virtual ConVar *CreateConVar(const char *name, - const char *defval, - const char *help, - int flags) =0; - - /** - * @brief Returns the string value of a ConVar. - * - * @param convar ConVar pointer. - * @return String value. - */ - virtual const char *GetConVarString(ConVar *convar) =0; - - /** - * @brief Sets a ConVar string. - * - * @param convar ConVar pointer. - * @param str String pointer. - */ - virtual void SetConVarString(ConVar *convar, const char *str) =0; - - /** - * @brief Retrieves the absolute path to the game directory. - * - * @param buffer Buffer in which to store path. - * @param maxlen Maximum length of buffer. - */ - virtual void GetGamePath(char *buffer, int maxlen) = 0; - - /** - * @brief Retrieves the game description. - * - * @return Game description. - */ - virtual const char *GetGameDescription() =0; - - /** - * @brief Returns the ConCommandBase accessor. - * - * @return An IConCommandBaseAccessor pointer. - */ - virtual IConCommandBaseAccessor *GetConCommandBaseAccessor() =0; - - /** - * @brief Registers a ConCommandBase. - * - * @param pCommand ConCommandBase to register. - * @return True if successful, false otherwise. - */ - virtual bool RegisterConCommandBase(ConCommandBase *pCommand) =0; - - /** - * @brief Unregisters a ConCommandBase. - * - * @param pCommand ConCommandBase to unlink. - */ - virtual void UnregisterConCommandBase(ConCommandBase *pCommand) =0; - - /** - * @brief Returns whether a ConCommandBase is a command or not. - * - * @param pCommand ConCommandBase pointer. - * @return True if a command, false otherwise. - */ - virtual bool IsConCommandBaseACommand(ConCommandBase *pCommand) =0; - - /** - * @brief Returns the number of user messages in the GameDLL. - * - * @return Number of user messages, or -1 if SourceMM has - * failed to get user message list. - */ - virtual int GetUserMessageCount() =0; - - /** - * @brief Returns the index of the specified user message. - * - * @param name User message name. - * @param size Optional pointer to store size of user message. - * @return Message index, or -1 on failure. - */ - virtual int FindUserMessage(const char *name, int *size=NULL) =0; - - /** - * @brief Returns the name of the specified user message. - * - * @param index User message index. - * @param size Optional pointer to store size of user message. - * @return Message name, or NULL on failure. - */ - virtual const char *GetUserMessage(int index, int *size=NULL) =0; - - /** - * @brief Returns the Source Engine build. - * - * @return SOURCE_ENGINE constant. - */ - virtual int DetermineSourceEngine() =0; - - /** - * @brief Processes a VDF plugin file. - * - */ - virtual bool ProcessVDF(const char *file, char path[], size_t path_len, char alias[], size_t alias_len) =0; - - /** - * @brief Returns string that describes engine version. - * - * @return Description. - */ - virtual const char *GetEngineDescription() const =0; - }; -}; - -extern PluginId g_PLID; -extern SourceHook::ISourceHook *g_SHPtr; -extern SourceMM::IMetamodSourceProvider *provider; -extern SourceMM::ISmmAPI *g_pMetamod; - -#endif //_INCLUDE_METAMOD_SOURCE_SUPPORT_H_ - diff --git a/utils/mmsource/core/metamod_util.cpp b/utils/mmsource/core/metamod_util.cpp deleted file mode 100644 index 35e763964..000000000 --- a/utils/mmsource/core/metamod_util.cpp +++ /dev/null @@ -1,359 +0,0 @@ -/** - * vim: set ts=4 : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2008 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - * Version: $Id$ - */ - -#include -#include -#include -#include "metamod_util.h" -#include "metamod_oslink.h" - -/** - * @brief Utility functions - * @file util.cpp - */ - -const char *UTIL_GetExtension(const char *file) -{ - int len = strlen(file); - int i = 0; - - for (i = len - 1; i >= 0; i--) - { - if (file[i] == '/' || file[i] == '\\') - { - return NULL; - } - - if ((file[i] == '.') && (i != len - 1)) - { - return (const char *)&(file[i + 1]); - } - } - - return NULL; -} - -void UTIL_TrimLeft(char *buffer) -{ - /* Let's think of this as our iterator */ - char *i = buffer; - - /* Make sure the buffer isn't null */ - if (i && *i) - { - /* Add up number of whitespace characters */ - while(isspace((unsigned char) *i)) - { - i++; - } - - /* If whitespace chars in buffer then adjust string so first non-whitespace char is at start of buffer */ - if (i != buffer) - { - memmove(buffer, i, (strlen(i) + 1) * sizeof(char)); - } - } -} - -void UTIL_TrimRight(char *buffer) -{ - /* Make sure buffer isn't null */ - if (buffer) - { - size_t len = strlen(buffer); - - /* Loop through buffer backwards while replacing whitespace chars with null chars */ - for (size_t i = len - 1; i < len; i--) - { - if (isspace((unsigned char) buffer[i])) - { - buffer[i] = '\0'; - } else { - break; - } - } - } -} - -bool UTIL_PathCmp(const char *path1, const char *path2) -{ - size_t pos1 = 0, pos2 = 0; - - while (true) - { - if (path1[pos1] == '\0' || path2[pos2] == '\0') - { - return (path1[pos1] == path2[pos2]); - } - - if (path1[pos1] == PATH_SEP_CHAR) - { - if (path2[pos2] != PATH_SEP_CHAR) - { - return false; - } - - /* Look for extra path chars */ - while (path1[++pos1]) - { - if (path1[pos1] != PATH_SEP_CHAR) - { - break; - } - } - while (path2[++pos2]) - { - if (path2[pos2] != PATH_SEP_CHAR) - { - break; - } - } - continue; - } - - /* If we're at a different non-alphanumeric, the next character MUST match */ - if ((((unsigned)path1[pos1] & 0x80) && path1[pos1] != path2[pos2]) - || - (!isalpha(path1[pos1]) && (path1[pos1] != path2[pos2])) - ) - { - return false; - } - - #ifdef WIN32 - if (toupper(path1[pos1]) != toupper(path2[pos2])) - #else - if (path1[pos1] != path2[pos2]) - #endif - { - return false; - } - - pos1++; - pos2++; - } -} - -size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - size_t len = vsnprintf(buffer, maxlength, fmt, ap); - va_end(ap); - - if (len >= maxlength) - { - len = maxlength - 1; - buffer[len] = '\0'; - } - - return len; -} - -size_t UTIL_FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list params) -{ - size_t len = vsnprintf(buffer, maxlength, fmt, params); - - if (len >= maxlength) - { - len = maxlength - 1; - buffer[len] = '\0'; - } - - return len; -} - -inline bool pathchar_isalpha(char a) -{ - return (((a & 1<<7) == 0) && isalpha(a)); -} - -inline bool pathchar_sep(char a) -{ -#if defined WIN32 - return (a == '/' || a == '\\'); -#else - return (a == '/'); -#endif -} - -inline bool pathstr_isabsolute(const char *str) -{ -#if defined WIN32 - return (pathchar_isalpha(str[0]) - && str[1] == ':' - && pathchar_sep(str[2])); -#else - return (str[0] == '/'); -#endif -} - -inline bool pathchar_cmp(char a, char b) -{ -#if defined WIN32 - if (pathchar_isalpha(a) && pathchar_isalpha(b)) - { - return (tolower(a) == tolower(b)); - } - /* Either path separator is acceptable */ - if (pathchar_sep(a)) - { - return pathchar_sep(b); - } -#endif - return (a == b); -} - -/** - * @brief Forms a relative path given two absolute paths. - * - * @param buffer Buffer to store relative path in. - * @param maxlength Maximum length of the output buffer. - * @param relTo Destination folder to use as a working directory. - * Final folder name should not be pathchar-terminated. - * @param relFrom Source file or folder to use as a target. - * @return True on success, false on failure. - */ -bool UTIL_Relatize(char buffer[], - size_t maxlength, - const char *relTo, - const char *relFrom) -{ - /* We don't allow relative paths in here, force - * the user to resolve these himself! - */ - if (!pathstr_isabsolute(relTo) - || !pathstr_isabsolute(relFrom)) - { - return false; - } - -#if defined WIN32 - /* Relative paths across drives are not possible */ - if (!pathchar_cmp(relTo[0], relFrom[0])) - { - return false; - } - /* Get rid of the drive and semicolon part */ - relTo = &relTo[2]; - relFrom = &relFrom[2]; -#endif - - /* Eliminate the common root between the paths */ - const char *rootTo = NULL; - const char *rootFrom = NULL; - while (*relTo != '\0' && *relFrom != '\0') - { - /* If we get to a new path sequence, start over */ - if (pathchar_sep(*relTo) - && pathchar_sep(*relFrom)) - { - rootTo = relTo; - rootFrom = relFrom; - /* If the paths don't compare, stop looking for a common root */ - } else if (!pathchar_cmp(*relTo, *relFrom)) { - break; - } - relTo++; - relFrom++; - } - - /* NULLs shouldn't happen! */ - if (rootTo == NULL - || rootFrom == NULL) - { - return false; - } - - size_t numLevels = 0; - - /* The root case is special! - * Don't count anything from it. - */ - if (*(rootTo + 1) != '\0') - { - /* Search for how many levels we need to go up. - * Since the root pointer points to a '/', we increment - * the initial pointer by one. - */ - while (*rootTo != '\0') - { - if (pathchar_sep(*rootTo)) - { - /* Check for an improper trailing slash, - * just to be nice even though the user - * should NOT have done this! - */ - if (*(rootTo + 1) == '\0') - { - break; - } - numLevels++; - } - rootTo++; - } - } - - /* Now build the new relative path. */ - size_t len, total = 0; - while (numLevels--) - { - len = snprintf(&buffer[total], maxlength - total, ".." PATH_SEP_STR); - if (len >= maxlength - total) - { - /* Not enough space in the buffer */ - return false; - } - total += len; - } - - /* Add the absolute path. */ - len = snprintf(&buffer[total], maxlength - total, "%s", &rootFrom[1]); - if (len >= maxlength - total) - { - return false; - } - - return true; -} - -bool UTIL_VerifySignature(const void *addr, const char *sig, size_t len) -{ - unsigned char *addr1 = (unsigned char *) addr; - unsigned char *addr2 = (unsigned char *) sig; - - for (size_t i = 0; i < len; i++) - { - if (addr2[i] == '*') - continue; - if (addr1[i] != addr2[i]) - return false; - } - - return true; -} diff --git a/utils/mmsource/core/metamod_util.h b/utils/mmsource/core/metamod_util.h deleted file mode 100644 index fa20138b3..000000000 --- a/utils/mmsource/core/metamod_util.h +++ /dev/null @@ -1,99 +0,0 @@ -/** - * vim: set ts=4 : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2008 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_UTIL_H -#define _INCLUDE_UTIL_H - -#include - -/** - * @brief Utility functions - * @file util.h - */ - -/** - * @brief Returns true is string is not blank, false otherwise. - */ -#define IS_STR_FILLED(var) (var != NULL && var[0] != '\0') - -/** - * @brief Returns a pointer to the extension in a file name. - */ -const char *UTIL_GetExtension(const char *file); - -/** - * @brief Removes whitespace characters from left side of string. - */ -void UTIL_TrimLeft(char *buffer); - -/** - * @brief Removes whitespace characters from right side of string. - */ -void UTIL_TrimRight(char *buffer); - -/** - * @brief Compares two file paths. - */ -bool UTIL_PathCmp(const char *path1, const char *path2); - -/** - * @brief Same as snprintf except that it ensures the string buffer is null terminated. - */ -size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...); - -/** - * @brief Same as vsnprintf except that it ensures the string buffer is null terminated. - */ -size_t UTIL_FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list params); - -/** - * @brief Forms a relative path given two absolute paths. - * - * @param buffer Buffer to store relative path in. - * @param maxlength Maximum length of the output buffer. - * @param relTo Destination folder to use as a working directory. - * Final folder name should not be pathchar-terminated. - * @param relFrom Source file or folder to use as a target. - * @return True on success, false on failure. - */ -bool UTIL_Relatize(char buffer[], - size_t maxlength, - const char *relTo, - const char *relFrom); - -/** - * @brief Compares memory address against a signature. - * - * @param addr Memory address to check. - * @param sig Signature used to check against memory address. Accept 0x2A as wildcard. - * @param len Length of signature. - * @return True if signature was verified, false otherwise. - */ -bool UTIL_VerifySignature(const void *addr, const char *sig, size_t len); - -#endif //_INCLUDE_UTIL_H - diff --git a/utils/mmsource/core/msvc10/mm_core.sln b/utils/mmsource/core/msvc10/mm_core.sln deleted file mode 100644 index 7c5179a1e..000000000 --- a/utils/mmsource/core/msvc10/mm_core.sln +++ /dev/null @@ -1,50 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mm_core", "mm_core.vcxproj", "{F7D47743-73B3-49B5-9D76-2333C5DFD565}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug - CS GO|Win32 = Debug - CS GO|Win32 - Debug - Dark Messiah|Win32 = Debug - Dark Messiah|Win32 - Debug - Left 4 Dead 2|Win32 = Debug - Left 4 Dead 2|Win32 - Debug - Left 4 Dead|Win32 = Debug - Left 4 Dead|Win32 - Debug - Orange Box Valve|Win32 = Debug - Orange Box Valve|Win32 - Debug - Orange Box|Win32 = Debug - Orange Box|Win32 - Release - CS GO|Win32 = Release - CS GO|Win32 - Release - Dark Messiah|Win32 = Release - Dark Messiah|Win32 - Release - Left 4 Dead 2|Win32 = Release - Left 4 Dead 2|Win32 - Release - Left 4 Dead|Win32 = Release - Left 4 Dead|Win32 - Release - Orange Box Valve|Win32 = Release - Orange Box Valve|Win32 - Release - Orange Box|Win32 = Release - Orange Box|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - CS GO|Win32.ActiveCfg = Debug - CS GO|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - CS GO|Win32.Build.0 = Debug - CS GO|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Dark Messiah|Win32.ActiveCfg = Debug - Dark Messiah|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Dark Messiah|Win32.Build.0 = Debug - Dark Messiah|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Left 4 Dead 2|Win32.ActiveCfg = Debug - Left 4 Dead 2|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Left 4 Dead 2|Win32.Build.0 = Debug - Left 4 Dead 2|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Left 4 Dead|Win32.ActiveCfg = Debug - Left 4 Dead|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Left 4 Dead|Win32.Build.0 = Debug - Left 4 Dead|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Orange Box Valve|Win32.ActiveCfg = Debug - Orange Box Valve|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Orange Box Valve|Win32.Build.0 = Debug - Orange Box Valve|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Orange Box|Win32.ActiveCfg = Debug - Orange Box|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Orange Box|Win32.Build.0 = Debug - Orange Box|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - CS GO|Win32.ActiveCfg = Release - CS GO|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - CS GO|Win32.Build.0 = Release - CS GO|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Dark Messiah|Win32.ActiveCfg = Release - Dark Messiah|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Dark Messiah|Win32.Build.0 = Release - Dark Messiah|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Left 4 Dead 2|Win32.ActiveCfg = Release - Left 4 Dead 2|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Left 4 Dead 2|Win32.Build.0 = Release - Left 4 Dead 2|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Left 4 Dead|Win32.ActiveCfg = Release - Left 4 Dead|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Left 4 Dead|Win32.Build.0 = Release - Left 4 Dead|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Orange Box Valve|Win32.ActiveCfg = Release - Orange Box Valve|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Orange Box Valve|Win32.Build.0 = Release - Orange Box Valve|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Orange Box|Win32.ActiveCfg = Release - Orange Box|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Orange Box|Win32.Build.0 = Release - Orange Box|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/utils/mmsource/core/msvc10/mm_core.vcxproj b/utils/mmsource/core/msvc10/mm_core.vcxproj deleted file mode 100644 index b5ce047cb..000000000 --- a/utils/mmsource/core/msvc10/mm_core.vcxproj +++ /dev/null @@ -1,1296 +0,0 @@ - - - - - Debug - Alien Swarm - Win32 - - - Debug - Bloody Good Time - Win32 - - - Debug - CS GO - Win32 - - - Debug - CSS - Win32 - - - Debug - Dark Messiah - Win32 - - - Debug - EYE - Win32 - - - Debug - Left 4 Dead 2 - Win32 - - - Debug - Left 4 Dead - Win32 - - - Debug - Orange Box Valve - Win32 - - - Debug - Orange Box - Win32 - - - Debug - Portal 2 - Win32 - - - Release - Alien Swarm - Win32 - - - Release - Bloody Good Time - Win32 - - - Release - CS GO - Win32 - - - Release - CSS - Win32 - - - Release - Dark Messiah - Win32 - - - Release - EYE - Win32 - - - Release - Left 4 Dead 2 - Win32 - - - Release - Left 4 Dead - Win32 - - - Release - Orange Box Valve - Win32 - - - Release - Orange Box - Win32 - - - Release - Portal 2 - Win32 - - - - {F7D47743-73B3-49B5-9D76-2333C5DFD565} - mm_core - Win32Proj - - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.40219.1 - $(Configuration)\ - $(Configuration)\ - true - $(Configuration)\ - $(Configuration)\ - false - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - true - true - true - true - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - false - false - false - false - $(Configuration)\ - $(Configuration)\ - true - $(Configuration)\ - $(Configuration)\ - false - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - true - true - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - false - false - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - true - true - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - false - false - $(Configuration)\ - $(Configuration)\ - true - $(Configuration)\ - $(Configuration)\ - false - - - metamod.2.csgo - - - metamod.2.portal2 - - - metamod.2.darkm - - - metamod.2.l4d - - - metamod.2.l4d2 - - - metamod.2.swarm - - - metamod.2.ep2 - - - metamod.2.ep2v - - - metamod.2.css - - - metamod.2.eye - - - metamod.2.bgt - - - metamod.2.csgo - - - metamod.2.portal2 - - - metamod.2.darkm - - - metamod.2.l4d - - - metamod.2.l4d2 - - - metamod.2.swarm - - - metamod.2.ep2 - - - metamod.2.ep2v - - - metamod.2.css - - - metamod.2.eye - - - metamod.2.bgt - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 - Disabled - ..;..\..\public;..\..\loader;..\sourcehook;$(HL2SDKOB)\public;$(HL2SDKOB)\public\engine;$(HL2SDKOB)\public\game\server;$(HL2SDKOB)\public\tier0;$(HL2SDKOB)\public\tier1;$(HL2SDKOB)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCE_ENGINE=3;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - false - - - Level3 - EditAndContinue - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(HL2SDKOB)\lib\public\tier0.lib;$(HL2SDKOB)\lib\public\tier1.lib;$(HL2SDKOB)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)$(TargetFileName) - libc.lib;libcd.lib;libcmt.lib;%(IgnoreSpecificDefaultLibraries) - true - $(OutDir)sourcemm.pdb - Windows - false - false - - - $(OutDir)sourcemm.lib - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 - Full - Speed - true - ..;..\..\public;..\..\loader;..\sourcehook;$(HL2SDKOB)\public;$(HL2SDKOB)\public\engine;$(HL2SDKOB)\public\game\server;$(HL2SDKOB)\public\tier0;$(HL2SDKOB)\public\tier1;$(HL2SDKOB)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCE_ENGINE=3;%(PreprocessorDefinitions) - true - Sync - MultiThreaded - false - false - - - Level3 - ProgramDatabase - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(HL2SDKOB)\lib\public\tier0.lib;$(HL2SDKOB)\lib\public\tier1.lib;$(HL2SDKOB)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)$(TargetFileName) - libc.lib;libcd.lib;libcmtd.lib;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - $(OutDir)sourcemm.lib - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 - Disabled - ..;..\..\public;..\..\loader;..\sourcehook;$(HL2SDKOBVALVE)\public;$(HL2SDKOBVALVE)\public\engine;$(HL2SDKOBVALVE)\public\game\server;$(HL2SDKOBVALVE)\public\tier0;$(HL2SDKOBVALVE)\public\tier1;$(HL2SDKOBVALVE)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCE_ENGINE=7;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - false - - - Level3 - EditAndContinue - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(HL2SDKOBVALVE)\lib\public\tier0.lib;$(HL2SDKOBVALVE)\lib\public\tier1.lib;$(HL2SDKOBVALVE)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)$(TargetFileName) - libc.lib;libcd.lib;libcmt.lib;%(IgnoreSpecificDefaultLibraries) - true - $(OutDir)sourcemm.pdb - Windows - false - false - - - $(OutDir)sourcemm.lib - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 - Disabled - ..;..\..\public;..\..\loader;..\sourcehook;$(HL2SDKCSS)\public;$(HL2SDKCSS)\public\engine;$(HL2SDKCSS)\public\game\server;$(HL2SDKCSS)\public\tier0;$(HL2SDKCSS)\public\tier1;$(HL2SDKCSS)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCE_ENGINE=6;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - false - - - Level3 - EditAndContinue - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(HL2SDKCSS)\lib\public\tier0.lib;$(HL2SDKCSS)\lib\public\tier1.lib;$(HL2SDKCSS)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)$(TargetFileName) - libc.lib;libcd.lib;libcmt.lib;%(IgnoreSpecificDefaultLibraries) - true - $(OutDir)sourcemm.pdb - Windows - false - false - - - $(OutDir)sourcemm.lib - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 - Disabled - ..;..\..\public;..\..\loader;..\sourcehook;$(HL2SDK-EYE)\public;$(HL2SDK-EYE)\public\engine;$(HL2SDK-EYE)\public\game\server;$(HL2SDK-EYE)\public\tier0;$(HL2SDK-EYE)\public\tier1;$(HL2SDK-EYE)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCE_ENGINE=5;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - false - - - Level3 - EditAndContinue - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(HL2SDK-EYE)\lib\public\tier0.lib;$(HL2SDK-EYE)\lib\public\tier1.lib;$(HL2SDK-EYE)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)$(TargetFileName) - libc.lib;libcd.lib;libcmt.lib;%(IgnoreSpecificDefaultLibraries) - true - $(OutDir)sourcemm.pdb - Windows - false - false - - - $(OutDir)sourcemm.lib - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 - Disabled - ..;..\..\public;..\..\loader;..\sourcehook;$(HL2SDK-BGT)\public;$(HL2SDK-BGT)\public\engine;$(HL2SDK-BGT)\public\game\server;$(HL2SDK-BGT)\public\tier0;$(HL2SDK-BGT)\public\tier1;$(HL2SDK-BGT)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCE_ENGINE=4;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - false - - - Level3 - EditAndContinue - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(HL2SDK-BGT)\lib\public\tier0.lib;$(HL2SDK-BGT)\lib\public\tier1.lib;$(HL2SDK-BGT)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)$(TargetFileName) - libc.lib;libcd.lib;libcmt.lib;%(IgnoreSpecificDefaultLibraries) - true - $(OutDir)sourcemm.pdb - Windows - false - false - - - $(OutDir)sourcemm.lib - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 - Full - Speed - true - ..;..\..\public;..\..\loader;..\sourcehook;$(HL2SDKOBVALVE)\public;$(HL2SDKOBVALVE)\public\engine;$(HL2SDKOBVALVE)\public\game\server;$(HL2SDKOBVALVE)\public\tier0;$(HL2SDKOBVALVE)\public\tier1;$(HL2SDKOBVALVE)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCE_ENGINE=7;%(PreprocessorDefinitions) - true - Sync - MultiThreaded - false - false - - - Level3 - ProgramDatabase - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(HL2SDKOBVALVE)\lib\public\tier0.lib;$(HL2SDKOBVALVE)\lib\public\tier1.lib;$(HL2SDKOBVALVE)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)$(TargetFileName) - libc.lib;libcd.lib;libcmtd.lib;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - $(OutDir)sourcemm.lib - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 - Full - Speed - true - ..;..\..\public;..\..\loader;..\sourcehook;$(HL2SDKCSS)\public;$(HL2SDKCSS)\public\engine;$(HL2SDKCSS)\public\game\server;$(HL2SDKCSS)\public\tier0;$(HL2SDKCSS)\public\tier1;$(HL2SDKCSS)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCE_ENGINE=6;%(PreprocessorDefinitions) - true - Sync - MultiThreaded - false - false - - - Level3 - ProgramDatabase - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(HL2SDKCSS)\lib\public\tier0.lib;$(HL2SDKCSS)\lib\public\tier1.lib;$(HL2SDKCSS)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)$(TargetFileName) - libc.lib;libcd.lib;libcmtd.lib;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - $(OutDir)sourcemm.lib - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 - Full - Speed - true - ..;..\..\public;..\..\loader;..\sourcehook;$(HL2SDK-EYE)\public;$(HL2SDK-EYE)\public\engine;$(HL2SDK-EYE)\public\game\server;$(HL2SDK-EYE)\public\tier0;$(HL2SDK-EYE)\public\tier1;$(HL2SDK-EYE)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCE_ENGINE=5;%(PreprocessorDefinitions) - true - Sync - MultiThreaded - false - false - - - Level3 - ProgramDatabase - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(HL2SDK-EYE)\lib\public\tier0.lib;$(HL2SDK-EYE)\lib\public\tier1.lib;$(HL2SDK-EYE)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)$(TargetFileName) - libc.lib;libcd.lib;libcmtd.lib;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - $(OutDir)sourcemm.lib - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 - Full - Speed - true - ..;..\..\public;..\..\loader;..\sourcehook;$(HL2SDK-BGT)\public;$(HL2SDK-BGT)\public\engine;$(HL2SDK-BGT)\public\game\server;$(HL2SDK-BGT)\public\tier0;$(HL2SDK-BGT)\public\tier1;$(HL2SDK-BGT)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCE_ENGINE=4;%(PreprocessorDefinitions) - true - Sync - MultiThreaded - false - false - - - Level3 - ProgramDatabase - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(HL2SDK-BGT)\lib\public\tier0.lib;$(HL2SDK-BGT)\lib\public\tier1.lib;$(HL2SDK-BGT)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)$(TargetFileName) - libc.lib;libcd.lib;libcmtd.lib;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - $(OutDir)sourcemm.lib - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 - Disabled - ..;..\..\public;..\..\loader;..\sourcehook;$(HL2SDKL4D)\public;$(HL2SDKL4D)\public\engine;$(HL2SDKL4D)\public\game\server;$(HL2SDKL4D)\public\tier0;$(HL2SDKL4D)\public\tier1;$(HL2SDKL4D)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCE_ENGINE=8;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - false - - - Level3 - EditAndContinue - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(HL2SDKL4D)\lib\public\tier0.lib;$(HL2SDKL4D)\lib\public\tier1.lib;$(HL2SDKL4D)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)$(TargetFileName) - libc.lib;libcd.lib;libcmt.lib;%(IgnoreSpecificDefaultLibraries) - true - $(OutDir)sourcemm.pdb - Windows - false - false - - - $(OutDir)sourcemm.lib - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 - Full - Speed - true - ..;..\..\public;..\..\loader;..\sourcehook;$(HL2SDKL4D)\public;$(HL2SDKL4D)\public\engine;$(HL2SDKL4D)\public\game\server;$(HL2SDKL4D)\public\tier0;$(HL2SDKL4D)\public\tier1;$(HL2SDKL4D)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCE_ENGINE=8;%(PreprocessorDefinitions) - true - Sync - MultiThreaded - false - false - - - Level3 - ProgramDatabase - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(HL2SDKL4D)\lib\public\tier0.lib;$(HL2SDKL4D)\lib\public\tier1.lib;$(HL2SDKL4D)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)$(TargetFileName) - libc.lib;libcd.lib;libcmtd.lib;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - $(OutDir)sourcemm.lib - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 - Disabled - ..;..\..\public;..\..\loader;..\sourcehook;$(HL2SDKL4D2)\public;$(HL2SDKL4D2)\public\engine;$(HL2SDKL4D2)\public\game\server;$(HL2SDKL4D2)\public\tier0;$(HL2SDKL4D2)\public\tier1;$(HL2SDKL4D2)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCE_ENGINE=9;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - false - - - Level3 - EditAndContinue - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(HL2SDKL4D2)\lib\public\tier0.lib;$(HL2SDKL4D2)\lib\public\tier1.lib;$(HL2SDKL4D2)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)$(TargetFileName) - libc.lib;libcd.lib;libcmt.lib;%(IgnoreSpecificDefaultLibraries) - true - $(OutDir)sourcemm.pdb - Windows - false - false - - - $(OutDir)sourcemm.lib - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 - Disabled - ..;..\..\public;..\..\loader;..\sourcehook;$(HL2SDK-SWARM)\public;$(HL2SDK-SWARM)\public\engine;$(HL2SDK-SWARM)\public\game\server;$(HL2SDK-SWARM)\public\tier0;$(HL2SDK-SWARM)\public\tier1;$(HL2SDK-SWARM)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;COMPILER_MSVC;COMPILER_MSVC32;SOURCE_ENGINE=10;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - false - - - Level3 - EditAndContinue - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(HL2SDK-SWARM)\lib\public\interfaces.lib;$(HL2SDK-SWARM)\lib\public\tier0.lib;$(HL2SDK-SWARM)\lib\public\tier1.lib;$(HL2SDK-SWARM)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)$(TargetFileName) - libc.lib;libcd.lib;libcmt.lib;%(IgnoreSpecificDefaultLibraries) - true - $(OutDir)sourcemm.pdb - Windows - false - false - - - $(OutDir)sourcemm.lib - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 - Full - Speed - true - ..;..\..\public;..\..\loader;..\sourcehook;$(HL2SDKL4D2)\public;$(HL2SDKL4D2)\public\engine;$(HL2SDKL4D2)\public\game\server;$(HL2SDKL4D2)\public\tier0;$(HL2SDKL4D2)\public\tier1;$(HL2SDKL4D2)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCE_ENGINE=9;%(PreprocessorDefinitions) - true - Sync - MultiThreaded - false - false - - - Level3 - ProgramDatabase - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(HL2SDKL4D2)\lib\public\tier0.lib;$(HL2SDKL4D2)\lib\public\tier1.lib;$(HL2SDKL4D2)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)$(TargetFileName) - libc.lib;libcd.lib;libcmtd.lib;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - $(OutDir)sourcemm.lib - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 - Full - Speed - true - ..;..\..\public;..\..\loader;..\sourcehook;$(HL2SDK-SWARM)\public;$(HL2SDK-SWARM)\public\engine;$(HL2SDK-SWARM)\public\game\server;$(HL2SDK-SWARM)\public\tier0;$(HL2SDK-SWARM)\public\tier1;$(HL2SDK-SWARM)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;COMPILER_MSVC;COMPILER_MSVC32;SOURCE_ENGINE=10;%(PreprocessorDefinitions) - true - Sync - MultiThreaded - false - false - - - Level3 - ProgramDatabase - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(HL2SDK-SWARM)\lib\public\interfaces.lib;$(HL2SDK-SWARM)\lib\public\tier0.lib;$(HL2SDK-SWARM)\lib\public\tier1.lib;$(HL2SDK-SWARM)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)$(TargetFileName) - libc.lib;libcd.lib;libcmtd.lib;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - $(OutDir)sourcemm.lib - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 - Disabled - ..;..\..\public;..\..\loader;..\sourcehook;$(HL2SDKCSGO)\public;$(HL2SDKCSGO)\public\engine;$(HL2SDKCSGO)\public\game\server;$(HL2SDKCSGO)\public\tier0;$(HL2SDKCSGO)\public\tier1;$(HL2SDKCSGO)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;COMPILER_MSVC;COMPILER_MSVC32;SOURCE_ENGINE=12;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - false - - - Level3 - EditAndContinue - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(HL2SDKCSGO)\lib\public\tier0.lib;$(HL2SDKCSGO)\lib\public\tier1.lib;$(HL2SDKCSGO)\lib\public\vstdlib.lib;$(HL2SDKCSGO)\lib\public\interfaces.lib;%(AdditionalDependencies) - $(OutDir)$(TargetFileName) - libc.lib;libcd.lib;libcmt.lib;%(IgnoreSpecificDefaultLibraries) - true - $(OutDir)sourcemm.pdb - Windows - false - false - - - $(OutDir)sourcemm.lib - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 - Disabled - ..;..\..\public;..\..\loader;..\sourcehook;$(HL2SDKPORTAL2)\public;$(HL2SDKPORTAL2)\public\engine;$(HL2SDKPORTAL2)\public\game\server;$(HL2SDKPORTAL2)\public\tier0;$(HL2SDKPORTAL2)\public\tier1;$(HL2SDKPORTAL2)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;COMPILER_MSVC;COMPILER_MSVC32;SOURCE_ENGINE=11;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - false - - - Level3 - EditAndContinue - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(HL2SDKPORTAL2)\lib\public\tier0.lib;$(HL2SDKPORTAL2)\lib\public\tier1.lib;$(HL2SDKPORTAL2)\lib\public\vstdlib.lib;$(HL2SDKPORTAL2)\lib\public\interfaces.lib;%(AdditionalDependencies) - $(OutDir)$(TargetFileName) - libc.lib;libcd.lib;libcmt.lib;%(IgnoreSpecificDefaultLibraries) - true - $(OutDir)sourcemm.pdb - Windows - false - false - - - $(OutDir)sourcemm.lib - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 - Full - Speed - true - ..;..\..\public;..\..\loader;..\sourcehook;$(HL2SDKCSGO)\public;$(HL2SDKCSGO)\public\engine;$(HL2SDKCSGO)\public\game\server;$(HL2SDKCSGO)\public\tier0;$(HL2SDKCSGO)\public\tier1;$(HL2SDKCSGO)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;COMPILER_MSVC;COMPILER_MSVC32;SOURCE_ENGINE=12;%(PreprocessorDefinitions) - true - Sync - MultiThreaded - false - false - - - Level3 - ProgramDatabase - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(HL2SDKCSGO)\lib\public\tier0.lib;$(HL2SDKCSGO)\lib\public\tier1.lib;$(HL2SDKCSGO)\lib\public\vstdlib.lib;$(HL2SDKCSGO)\lib\public\interfaces.lib;%(AdditionalDependencies) - $(OutDir)$(TargetFileName) - libc.lib;libcd.lib;libcmtd.lib;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - $(OutDir)sourcemm.lib - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 - Full - Speed - true - ..;..\..\public;..\..\loader;..\sourcehook;$(HL2SDKPORTAL2)\public;$(HL2SDKPORTAL2)\public\engine;$(HL2SDKPORTAL2)\public\game\server;$(HL2SDKPORTAL2)\public\tier0;$(HL2SDKPORTAL2)\public\tier1;$(HL2SDKPORTAL2)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;COMPILER_MSVC;COMPILER_MSVC32;SOURCE_ENGINE=11;%(PreprocessorDefinitions) - true - Sync - MultiThreaded - false - false - - - Level3 - ProgramDatabase - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(HL2SDKPORTAL2)\lib\public\tier0.lib;$(HL2SDKPORTAL2)\lib\public\tier1.lib;$(HL2SDKPORTAL2)\lib\public\vstdlib.lib;$(HL2SDKPORTAL2)\lib\public\interfaces.lib;%(AdditionalDependencies) - $(OutDir)$(TargetFileName) - libc.lib;libcd.lib;libcmtd.lib;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - $(OutDir)sourcemm.lib - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 - Disabled - ..;..\..\public;..\..\loader;..\sourcehook;$(HL2SDK-DARKM)\public;$(HL2SDK-DARKM)\public\engine;$(HL2SDK-DARKM)\public\dlls;$(HL2SDK-DARKM)\public\tier0;$(HL2SDK-DARKM)\public\tier1;$(HL2SDK-DARKM)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCE_ENGINE=2;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - false - - - Level3 - EditAndContinue - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(HL2SDK-DARKM)\lib\public\tier0.lib;$(HL2SDK-DARKM)\lib\public\tier1.lib;$(HL2SDK-DARKM)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)$(TargetFileName) - libc.lib;libcd.lib;libcmt.lib;%(IgnoreSpecificDefaultLibraries) - true - $(OutDir)sourcemm.pdb - Windows - false - false - - - $(OutDir)sourcemm.lib - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 - Full - Speed - true - ..;..\..\public;..\..\loader;..\sourcehook;$(HL2SDK-DARKM)\public;$(HL2SDK-DARKM)\public\engine;$(HL2SDK-DARKM)\public\dlls;$(HL2SDK-DARKM)\public\tier0;$(HL2SDK-DARKM)\public\tier1;$(HL2SDK-DARKM)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SOURCE_ENGINE=2;%(PreprocessorDefinitions) - true - Sync - MultiThreaded - false - false - - - Level3 - ProgramDatabase - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(HL2SDK-DARKM)\lib\public\tier0.lib;$(HL2SDK-DARKM)\lib\public\tier1.lib;$(HL2SDK-DARKM)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)$(TargetFileName) - libc.lib;libcd.lib;libcmtd.lib;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - $(OutDir)sourcemm.lib - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/utils/mmsource/core/msvc10/mm_core.vcxproj.filters b/utils/mmsource/core/msvc10/mm_core.vcxproj.filters deleted file mode 100644 index 247806c3b..000000000 --- a/utils/mmsource/core/msvc10/mm_core.vcxproj.filters +++ /dev/null @@ -1,189 +0,0 @@ - - - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx - - - {164581e9-afc3-4834-9fb9-b75638df6014} - - - {c5bf4755-d61f-4ec8-a807-bdd63b58c01c} - - - {5692b9dd-f21e-452e-bacd-e7e31277755b} - - - {72668373-0466-495c-8b9e-683af0cccf47} - - - {e1e87a63-9709-4c3b-a5c3-ed636b36c6ce} - - - {8258f77b-cb2f-4d79-a05e-9930ff1cb44d} - - - {cf9ff2d7-b5eb-46f0-8d52-e797194bfefd} - - - {14df2031-ed46-4e12-8456-bdffada2d706} - - - {2f387549-7fe6-4d64-bc34-14a32bc70cf3} - - - {188ed842-cd55-4ce7-a33b-60d426730a63} - - - - - Resource Files - - - - - Interfaces - - - Interfaces - - - Interfaces - - - Interfaces - - - Metamod\Header Files - - - Metamod\Header Files - - - Metamod\Header Files - - - Metamod\Header Files - - - Metamod\Header Files - - - Metamod\Header Files - - - Provider\Header Files - - - Provider\Header Files - - - SourceHook\Header Files - - - SourceHook\Header Files - - - SourceHook\Header Files - - - SourceHook\Header Files - - - SourceHook\Header Files - - - SourceHook\Header Files - - - SourceHook\Header Files - - - SourceHook\Header Files - - - SourceHook\Header Files - - - SourceHook\Header Files - - - SourceHook\Header Files - - - SourceHook\Header Files - - - SourceHook\Header Files - - - SourceHook\Header Files - - - SourceHook\Header Files - - - SourceHook\Header Files - - - SourceHook\Header Files - - - SourceHook\Header Files - - - SourceHook\Header Files - - - SourceHook\Header Files - - - - - Metamod\Source Files - - - Metamod\Source Files - - - Metamod\Source Files - - - Metamod\Source Files - - - Metamod\Source Files - - - Metamod\Source Files - - - Metamod\Source Files - - - Provider\Source Files - - - Provider\Source Files - - - SourceHook\Source Files - - - SourceHook\Source Files - - - SourceHook\Source Files - - - SourceHook\Source Files - - - SourceHook\Source Files - - - SourceHook\Source Files - - - \ No newline at end of file diff --git a/utils/mmsource/core/msvc9/mm_core.sln b/utils/mmsource/core/msvc9/mm_core.sln deleted file mode 100644 index 0823a7c83..000000000 --- a/utils/mmsource/core/msvc9/mm_core.sln +++ /dev/null @@ -1,56 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mm_core", "mm_core.vcproj", "{F7D47743-73B3-49B5-9D76-2333C5DFD565}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug - CS GO|Win32 = Debug - CS GO|Win32 - Debug - CSS|Win32 = Debug - CSS|Win32 - Debug - Dark Messiah|Win32 = Debug - Dark Messiah|Win32 - Debug - Left 4 Dead 2|Win32 = Debug - Left 4 Dead 2|Win32 - Debug - Left 4 Dead|Win32 = Debug - Left 4 Dead|Win32 - Debug - Orange Box|Win32 = Debug - Orange Box|Win32 - Debug - Orange Box Valve|Win32 = Debug - Orange Box Valve|Win32 - Release - CS GO|Win32 = Release - CS GO|Win32 - Release - CSS|Win32 = Release - CSS|Win32 - Release - Dark Messiah|Win32 = Release - Dark Messiah|Win32 - Release - Left 4 Dead 2|Win32 = Release - Left 4 Dead 2|Win32 - Release - Left 4 Dead|Win32 = Release - Left 4 Dead|Win32 - Release - Orange Box|Win32 = Release - Orange Box|Win32 - Release - Orange Box Valve|Win32 = Release - Orange Box Valve|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - CS GO|Win32.ActiveCfg = Debug - CS GO|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - CS GO|Win32.Build.0 = Debug - CS GO|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - CSS|Win32.ActiveCfg = Debug - CSS|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - CSS|Win32.Build.0 = Debug - CSS|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Dark Messiah|Win32.ActiveCfg = Debug - Dark Messiah|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Dark Messiah|Win32.Build.0 = Debug - Dark Messiah|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Left 4 Dead 2|Win32.ActiveCfg = Debug - Left 4 Dead 2|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Left 4 Dead 2|Win32.Build.0 = Debug - Left 4 Dead 2|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Left 4 Dead|Win32.ActiveCfg = Debug - Left 4 Dead|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Left 4 Dead|Win32.Build.0 = Debug - Left 4 Dead|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Orange Box|Win32.ActiveCfg = Debug - Orange Box|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Orange Box|Win32.Build.0 = Debug - Orange Box|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Orange Box Valve|Win32.ActiveCfg = Debug - Orange Box Valve|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Orange Box Valve|Win32.Build.0 = Debug - Orange Box Valve|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - CS GO|Win32.ActiveCfg = Release - CS GO|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - CS GO|Win32.Build.0 = Release - CS GO|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - CSS|Win32.ActiveCfg = Release - CSS|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - CSS|Win32.Build.0 = Release - CSS|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Dark Messiah|Win32.ActiveCfg = Release - Dark Messiah|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Dark Messiah|Win32.Build.0 = Release - Dark Messiah|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Left 4 Dead 2|Win32.ActiveCfg = Release - Left 4 Dead 2|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Left 4 Dead 2|Win32.Build.0 = Release - Left 4 Dead 2|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Left 4 Dead|Win32.ActiveCfg = Release - Left 4 Dead|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Left 4 Dead|Win32.Build.0 = Release - Left 4 Dead|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Orange Box|Win32.ActiveCfg = Release - Orange Box|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Orange Box|Win32.Build.0 = Release - Orange Box|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Orange Box Valve|Win32.ActiveCfg = Release - Orange Box Valve|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Orange Box Valve|Win32.Build.0 = Release - Orange Box Valve|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/utils/mmsource/core/msvc9/mm_core.vcproj b/utils/mmsource/core/msvc9/mm_core.vcproj deleted file mode 100644 index d4d9ccdcf..000000000 --- a/utils/mmsource/core/msvc9/mm_core.vcproj +++ /dev/null @@ -1,1461 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/utils/mmsource/core/provider/console.cpp b/utils/mmsource/core/provider/console.cpp deleted file mode 100644 index a1362c68d..000000000 --- a/utils/mmsource/core/provider/console.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/** - * vim: set ts=4 : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2008 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - * Version: $Id$ - */ - -#include "console.h" -#include "provider_ep2.h" -#include "metamod_util.h" - -using namespace SourceHook; - -SMConVarAccessor g_SMConVarAccessor; - -#if SOURCE_ENGINE >= SE_ORANGEBOX -#else -#define RegisterConCommand RegisterConCommandBase -#endif - -bool SMConVarAccessor::RegisterConCommandBase(ConCommandBase *pCommand) -{ - m_RegisteredCommands.push_back(pCommand); -#if SOURCE_ENGINE < SE_ALIENSWARM - pCommand->SetNext(NULL); -#endif - icvar->RegisterConCommand(pCommand); - - return true; -} - -bool SMConVarAccessor::Register(ConCommandBase *pCommand) -{ -#if SOURCE_ENGINE < SE_ALIENSWARM - pCommand->SetNext(NULL); -#endif - icvar->RegisterConCommand(pCommand); - - return true; -} - -void SMConVarAccessor::RemoveMetamodCommands() -{ - List::iterator iter; - - for (iter = m_RegisteredCommands.begin(); iter != m_RegisteredCommands.end(); iter++) - { - Unregister(*iter); - } -} - -#if SOURCE_ENGINE < SE_ORANGEBOX -/* Signature for ICvar::GetCommands() in vstdlib for Win32 and Linux. - * - * 20226EE0 A1 50 5C 5A 20 mov eax,dword ptr ds:[205A5C50h] <-- What we want - * 20226EE5 C3 ret - */ -#define CMDLIST_SIG "\xA1\x2A\x2A\x2A\x2A\xC3" -#define CMDLIST_SIGLEN 6 - -/* Linux symbol name of ConCommandBase list in vstdlib */ -#define CMDLIST_SYMBOL "_ZN14ConCommandBase18s_pConCommandBasesE" - -/* This function retrieves the address of the var that holds the top of the ConCommandBase list. - * Having this allows us to change the beginning of this list with ease. - * - * This craziness eliminates the need for the eternal command/cvar used previously which - * could have caused a crash as a result of registering commands/cvars more than once. - */ -bool SMConVarAccessor::InitConCommandBaseList() -{ - char *vfunc = (char *)SH_GET_ORIG_VFNPTR_ENTRY(icvar, &ICvar::GetCommands); - - if (*vfunc == '\xE9') - { - /* Get address from displacement... - * - * Add 5 because it's relative to next instruction: - * Opcode <1 byte> + 32-bit displacement <4 bytes> - */ - vfunc += *reinterpret_cast(vfunc + 1) + 5; - } - - if (!vfunc) - { - return false; - } - -#ifdef OS_WIN32 - if (UTIL_VerifySignature(vfunc, CMDLIST_SIG, CMDLIST_SIGLEN)) - { - /* Skip past 0xA1 and get addr of ConCommandBase list var */ - m_TopConCommandBase = *reinterpret_cast(vfunc + 1); - return true; - } -#elif defined OS_LINUX - /* Try dlsym first */ - char path[PATH_SIZE]; - if (GetFileOfAddress((void *)icvar, path, sizeof(path))) - { - void *handle = dlopen(path, RTLD_NOW); - if (handle) - { - m_TopConCommandBase = reinterpret_cast(dlsym(handle, CMDLIST_SYMBOL)); - dlclose(handle); - return true; - } - } - - /* If dlsym failed, then verify signature of function */ - if (!m_TopConCommandBase && UTIL_VerifySignature(vfunc, CMDLIST_SIG, CMDLIST_SIGLEN)) - { - /* Skip past 0xA1 and get addr of ConCommandBase list var */ - m_TopConCommandBase = *reinterpret_cast(vfunc + 1); - return true; - } -#endif - - return false; -} -#endif - -void SMConVarAccessor::Unregister(ConCommandBase *pCommand) -{ -#if SOURCE_ENGINE >= SE_ORANGEBOX - icvar->UnregisterConCommand(pCommand); -#else - ConCommandBase *pCur = NULL; - ConCommandBase *pPrev = NULL; - - if (!pCommand) - { - return; - } - - pCur = icvar->GetCommands(); - - if (!m_TopConCommandBase || !pCur) - { - return; - } - - if (pCur == pCommand) - { - *m_TopConCommandBase = const_cast(pCommand->GetNext()); - pCommand->SetNext(NULL); - return; - } - - pPrev = pCur; - pCur = const_cast(pCur->GetNext()); - - while (pCur) - { - if (pCur == pCommand) - { - pPrev->SetNext(const_cast(pCommand->GetNext())); - pCommand->SetNext(NULL); - } - - pPrev = pCur; - pCur = const_cast(pCur->GetNext()); - } -#endif -} - diff --git a/utils/mmsource/core/provider/console.h b/utils/mmsource/core/provider/console.h deleted file mode 100644 index 20139b6c5..000000000 --- a/utils/mmsource/core/provider/console.h +++ /dev/null @@ -1,55 +0,0 @@ -/** - * vim: set ts=4 : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2008 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_CONSOLE_MMS_H_ -#define _INCLUDE_CONSOLE_MMS_H_ - -#include -#include "convar.h" -#include -#include - -class SMConVarAccessor : public IConCommandBaseAccessor -{ -public: - bool RegisterConCommandBase(ConCommandBase *pCommand); - bool Register(ConCommandBase *pCommand); - void Unregister(ConCommandBase *pCommand); - void RemoveMetamodCommands(); -#if SOURCE_ENGINE < SE_ORANGEBOX - bool InitConCommandBaseList(); -private: - ConCommandBase **m_TopConCommandBase; -#endif -private: - SourceHook::List m_RegisteredCommands; -}; - -extern SMConVarAccessor g_SMConVarAccessor; - -#endif //_INCLUDE_CONSOLE_MMS_H_ - diff --git a/utils/mmsource/core/provider/provider_ep2.cpp b/utils/mmsource/core/provider/provider_ep2.cpp deleted file mode 100644 index 445f5030a..000000000 --- a/utils/mmsource/core/provider/provider_ep2.cpp +++ /dev/null @@ -1,855 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2009 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#include -#include -#include "../metamod_oslink.h" -#include -#include -#include -#include -#include -#include -#include "../metamod_util.h" -#include "provider_ep2.h" -#include "console.h" -#include "metamod_console.h" -#include -#include "metamod.h" -#include -#if SOURCE_ENGINE == SE_DOTA -#include -#endif - -#if SOURCE_ENGINE == SE_DOTA && defined( _WIN32 ) -SH_DECL_HOOK1(ISource2ServerConfig, AllowDedicatedServers, const, 0, bool, EUniverse); -bool BaseProvider::AllowDedicatedServers(EUniverse universe) const -{ - RETURN_META_VALUE(MRES_SUPERCEDE, true); -} -#endif - -/* Types */ -typedef void (*CONPRINTF_FUNC)(const char *, ...); -struct UsrMsgInfo -{ - UsrMsgInfo() - { - } - UsrMsgInfo(int s, const char *t) : size(s), name(t) - { - } - int size; - String name; -}; - -/* Imports */ -#if SOURCE_ENGINE < SE_ORANGEBOX -#undef CommandLine -DLL_IMPORT ICommandLine *CommandLine(); -#endif - -/* Functions */ -void CacheUserMessages(); -bool KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL); -void Detour_Error(const tchar *pMsg, ...); - -#if SOURCE_ENGINE == SE_DOTA -void ClientCommand(CEntityIndex index, const CCommand &args); -#elif SOURCE_ENGINE >= SE_ORANGEBOX -void ClientCommand(edict_t *pEdict, const CCommand &args); -#else -void ClientCommand(edict_t *pEdict); -#endif - -#if SOURCE_ENGINE >= SE_ORANGEBOX -void LocalCommand_Meta(const CCommand &args); -#else -void LocalCommand_Meta(); -#endif - -void _ServerCommand(); -/* Variables */ -static BaseProvider g_Ep1Provider; -static List conbases_unreg; -static CVector usermsgs_list; -static jmp_buf usermsg_end; -static bool g_bOriginalEngine = false; - -ICvar *icvar = NULL; -IFileSystem *baseFs = NULL; -IServerGameDLL *server = NULL; -#if SOURCE_ENGINE == SE_DOTA -static ISource2ServerConfig *serverconfig = NULL; -INetworkServerService *netservice = NULL; -IEngineServiceMgr *enginesvcmgr = NULL; -#endif -IVEngineServer *engine = NULL; -IServerGameClients *gameclients = NULL; -CGlobalVars *gpGlobals = NULL; -IMetamodSourceProvider *provider = &g_Ep1Provider; -ConCommand meta_local_cmd("meta", LocalCommand_Meta, "Metamod:Source control options"); - -#if SOURCE_ENGINE == SE_DOTA -SH_DECL_HOOK2_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, CEntityIndex, const CCommand &); -#elif SOURCE_ENGINE >= SE_ORANGEBOX -SH_DECL_HOOK2_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *, const CCommand &); -#else -SH_DECL_HOOK1_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *); -#endif - -void BaseProvider::ConsolePrint(const char *str) -{ -#if SOURCE_ENGINE >= SE_ORANGEBOX - ConMsg("%s", str); -#else - Msg("%s", str); -#endif -} - -void BaseProvider::Notify_DLLInit_Pre(CreateInterfaceFn engineFactory, - CreateInterfaceFn serverFactory) -{ -#if SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_DODS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_SDK2013 - // Shim to avoid hooking shims - engine = (IVEngineServer *)((engineFactory)("VEngineServer023", NULL)); - if (!engine) - { - engine = (IVEngineServer *)((engineFactory)("VEngineServer022", NULL)); - if (!engine) - { - engine = (IVEngineServer *)((engineFactory)("VEngineServer021", NULL)); - } - } -#else - engine = (IVEngineServer *)((engineFactory)(INTERFACEVERSION_VENGINESERVER, NULL)); -#endif - if (!engine) - { - DisplayError("Could not find IVEngineServer! Metamod cannot load."); - return; - } -#if SOURCE_ENGINE == SE_DOTA - gpGlobals = engine->GetServerGlobals(); - serverconfig = (ISource2ServerConfig *) ((serverFactory) (INTERFACEVERSION_SERVERCONFIG, NULL)); - netservice = (INetworkServerService *) ((engineFactory) (NETWORKSERVERSERVICE_INTERFACE_VERSION, NULL)); - enginesvcmgr = (IEngineServiceMgr *) ((engineFactory) (ENGINESERVICEMGR_INTERFACE_VERSION, NULL)); -#endif -#if SOURCE_ENGINE >= SE_ORANGEBOX - icvar = (ICvar *)((engineFactory)(CVAR_INTERFACE_VERSION, NULL)); -#else - icvar = (ICvar *)((engineFactory)(VENGINE_CVAR_INTERFACE_VERSION, NULL)); -#endif - if (!icvar) - { - DisplayError("Could not find ICvar! Metamod cannot load."); - return; - } - -#if SOURCE_ENGINE == SE_DOTA - gameclients = (IServerGameClients *)(serverFactory(INTERFACEVERSION_SERVERGAMECLIENTS, NULL)); -#else - if ((gameclients = (IServerGameClients *)(serverFactory("ServerGameClients003", NULL))) - == NULL) - { - gameclients = (IServerGameClients *)(serverFactory("ServerGameClients004", NULL)); - } -#endif - - baseFs = (IFileSystem *)((engineFactory)(FILESYSTEM_INTERFACE_VERSION, NULL)); - if (baseFs == NULL) - { - mm_LogMessage("Unable to find \"%s\": .vdf files will not be parsed", FILESYSTEM_INTERFACE_VERSION); - } - -#if SOURCE_ENGINE == SE_DOTA - // Since we have to be added as a Game path (cannot add GameBin directly), we - // automatically get added to other paths as well, including having the MM:S - // dir become the default write path for logs and more. We can fix some of these. - - char searchPath[260]; - baseFs->GetSearchPath("GAME", (GetSearchPathTypes_t)0, searchPath, sizeof(searchPath)); - for (size_t i = 0; i < sizeof(searchPath); ++i) - { - if (searchPath[i] == ';') - { - searchPath[i] = '\0'; - break; - } - } - baseFs->RemoveSearchPath(searchPath, "GAME"); - - // TODO: figure out why these calls get ignored and path remains - //baseFs->RemoveSearchPath(searchPath, "CONTENT"); - //baseFs->RemoveSearchPath(searchPath, "SHADER_SOURCE"); - //baseFs->RemoveSearchPath(searchPath, "SHADER_SOURCE_MOD"); - - baseFs->RemoveSearchPaths("DEFAULT_WRITE_PATH"); - baseFs->GetSearchPath("GAME", (GetSearchPathTypes_t)0, searchPath, sizeof(searchPath)); - for (size_t i = 0; i < sizeof(searchPath); ++i) - { - if (searchPath[i] == ';') - { - searchPath[i] = '\0'; - break; - } - } - baseFs->AddSearchPath(searchPath, "DEFAULT_WRITE_PATH"); -#endif - -#if SOURCE_ENGINE >= SE_ORANGEBOX - g_pCVar = icvar; -#endif - - g_SMConVarAccessor.RegisterConCommandBase(&meta_local_cmd); - -#if SOURCE_ENGINE == SE_EPISODEONE - /* The Ship is the only game known at this time that uses the pre-Episode One engine */ - g_bOriginalEngine = strcmp(CommandLine()->ParmValue("-game", "hl2"), "ship") == 0; -#endif - - CacheUserMessages(); - -#if SOURCE_ENGINE < SE_ORANGEBOX - if (!g_SMConVarAccessor.InitConCommandBaseList()) - { - /* This is very unlikely considering it's old engine */ - mm_LogMessage("[META] Warning: Failed to find ConCommandBase list!"); - mm_LogMessage("[META] Warning: ConVars and ConCommands cannot be unregistered properly! Please file a bug report."); - } -#endif - - if (gameclients) - { - SH_ADD_HOOK_STATICFUNC(IServerGameClients, ClientCommand, gameclients, ClientCommand, false); - } - -#if SOURCE_ENGINE == SE_DOTA && defined( _WIN32 ) - SH_ADD_VPHOOK(ISource2ServerConfig, AllowDedicatedServers, serverconfig, SH_MEMBER(this, &BaseProvider::AllowDedicatedServers), false); -#endif -} - -void BaseProvider::Notify_DLLShutdown_Pre() -{ - g_SMConVarAccessor.RemoveMetamodCommands(); - -#if SOURCE_ENGINE < SE_ORANGEBOX - if (g_Metamod.IsLoadedAsGameDLL()) - { - icvar->UnlinkVariables(FCVAR_GAMEDLL); - } -#endif -} - -bool BaseProvider::IsRemotePrintingAvailable() -{ - return true; -} - -void BaseProvider::ClientConsolePrint(edict_t *pEdict, const char *message) -{ -#if SOURCE_ENGINE == SE_DOTA - int client = (int)(pEdict - gpGlobals->pEdicts); - engine->ClientPrintf(client, message); -#else - engine->ClientPrintf(pEdict, message); -#endif -} - -void BaseProvider::ServerCommand(const char *cmd) -{ - engine->ServerCommand(cmd); -} - -const char *BaseProvider::GetConVarString(ConVar *convar) -{ - if (convar == NULL) - { - return NULL; - } - - return convar->GetString(); -} - -void BaseProvider::SetConVarString(ConVar *convar, const char *str) -{ - convar->SetValue(str); -} - -bool BaseProvider::IsConCommandBaseACommand(ConCommandBase *pCommand) -{ - return pCommand->IsCommand(); -} - - -bool BaseProvider::IsSourceEngineBuildCompatible(int build) -{ - return (build == SOURCE_ENGINE_ORIGINAL - || build == SOURCE_ENGINE_EPISODEONE); -} - -const char *BaseProvider::GetCommandLineValue(const char *key, const char *defval) -{ - if (key[0] == '-' || key[0] == '+') - { - return CommandLine()->ParmValue(key, defval); - } - else if (icvar) - { - const char *val; - if ((val = icvar->GetCommandLineValue(key)) == NULL) - { - return defval; - } - - return val; - } - - return NULL; -} - -int BaseProvider::TryServerGameDLL(const char *iface) -{ - if (strncmp(iface, "ServerGameDLL", 13) != 0) - { - return 0; - } - - return atoi(&iface[13]); -} - -bool BaseProvider::LogMessage(const char *buffer) -{ - if (!engine) - { - return false; - } - - engine->LogPrint(buffer); - - return true; -} - -bool BaseProvider::GetHookInfo(ProvidedHooks hook, SourceHook::MemFuncInfo *pInfo) -{ -#if SOURCE_ENGINE == SE_DOTA - SourceHook::MemFuncInfo mfi = {true, -1, 0, 0}; - - switch (hook) - { - case ProvidedHook_StartupServer: - SourceHook::GetFuncInfo(&INetworkServerService::StartupServer, mfi); - break; - case ProvidedHook_StartChangeLevel: - SourceHook::GetFuncInfo(&INetworkGameServer::StartChangeLevel, mfi); - break; - case ProvidedHook_Init: - SourceHook::GetFuncInfo(&INetworkGameServer::Init, mfi); - break; - case ProvidedHook_SwitchToLoop: - SourceHook::GetFuncInfo(&IEngineServiceMgr::SwitchToLoop, mfi); - break; - default: - return false; - } - - *pInfo = mfi; - - return (mfi.thisptroffs >= 0); -#else - SourceHook::MemFuncInfo mfi = {true, -1, 0, 0}; - - if (hook == ProvidedHook_LevelInit) - { - SourceHook::GetFuncInfo(&IServerGameDLL::LevelInit, mfi); - } - else if (hook == ProvidedHook_LevelShutdown) - { - SourceHook::GetFuncInfo(&IServerGameDLL::LevelShutdown, mfi); - } - else if (hook == ProvidedHook_GameInit) - { - SourceHook::GetFuncInfo(&IServerGameDLL::GameInit, mfi); - } - - *pInfo = mfi; - - return (mfi.thisptroffs >= 0); -#endif -} - -void BaseProvider::DisplayError(const char *fmt, ...) -{ - va_list ap; - char buffer[2048]; - - va_start(ap, fmt); - UTIL_FormatArgs(buffer, sizeof(buffer), fmt, ap); - va_end(ap); - - Error("%s", buffer); -} - -void BaseProvider::DisplayWarning(const char *fmt, ...) -{ - va_list ap; - char buffer[2048]; - - va_start(ap, fmt); - UTIL_FormatArgs(buffer, sizeof(buffer), fmt, ap); - va_end(ap); - - Warning("%s", buffer); -} - -IConCommandBaseAccessor *BaseProvider::GetConCommandBaseAccessor() -{ - return &g_SMConVarAccessor; -} - -bool BaseProvider::RegisterConCommandBase(ConCommandBase *pCommand) -{ - return g_SMConVarAccessor.Register(pCommand); -} - -void BaseProvider::UnregisterConCommandBase(ConCommandBase *pCommand) -{ - return g_SMConVarAccessor.Unregister(pCommand); -} - -int BaseProvider::GetUserMessageCount() -{ -#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA - return -1; -#else - return (int)usermsgs_list.size(); -#endif -} - -int BaseProvider::FindUserMessage(const char *name, int *size) -{ - for (size_t i = 0; i < usermsgs_list.size(); i++) - { - if (usermsgs_list[i].name.compare(name) == 0) - { - if (size) - { - *size = usermsgs_list[i].size; - } - return (int)i; - } - } - - return -1; -} - -const char *BaseProvider::GetUserMessage(int index, int *size) -{ - if (index < 0 || index >= (int)usermsgs_list.size()) - { - return NULL; - } - - if (size) - { - *size = usermsgs_list[index].size; - } - - return usermsgs_list[index].name.c_str(); -} - -void BaseProvider::GetGamePath(char *pszBuffer, int len) -{ - engine->GetGameDir(pszBuffer, len); -} - -const char *BaseProvider::GetGameDescription() -{ -#if SOURCE_ENGINE == SE_DOTA - return serverconfig->GetGameDescription(); -#else - return server->GetGameDescription(); -#endif -} - -int BaseProvider::DetermineSourceEngine() -{ -#if SOURCE_ENGINE == SE_BLOODYGOODTIME - return SOURCE_ENGINE_BLOODYGOODTIME; -#elif SOURCE_ENGINE == SE_ALIENSWARM - return SOURCE_ENGINE_ALIENSWARM; -#elif SOURCE_ENGINE == SE_LEFT4DEAD2 - return SOURCE_ENGINE_LEFT4DEAD2; -#elif SOURCE_ENGINE == SE_NUCLEARDAWN - return SOURCE_ENGINE_NUCLEARDAWN; -#elif SOURCE_ENGINE == SE_CONTAGION - return SOURCE_ENGINE_CONTAGION; -#elif SOURCE_ENGINE == SE_LEFT4DEAD - return SOURCE_ENGINE_LEFT4DEAD; -#elif SOURCE_ENGINE == SE_ORANGEBOX - return SOURCE_ENGINE_ORANGEBOX; -#elif SOURCE_ENGINE == SE_CSS - return SOURCE_ENGINE_CSS; -#elif SOURCE_ENGINE == SE_HL2DM - return SOURCE_ENGINE_HL2DM; -#elif SOURCE_ENGINE == SE_DODS - return SOURCE_ENGINE_DODS; -#elif SOURCE_ENGINE == SE_SDK2013 - return SOURCE_ENGINE_SDK2013; -#elif SOURCE_ENGINE == SE_TF2 - return SOURCE_ENGINE_TF2; -#elif SOURCE_ENGINE == SE_DARKMESSIAH - return SOURCE_ENGINE_DARKMESSIAH; -#elif SOURCE_ENGINE == SE_EYE - return SOURCE_ENGINE_EYE; -#elif SOURCE_ENGINE == SE_PORTAL2 - return SOURCE_ENGINE_PORTAL2; -#elif SOURCE_ENGINE == SE_BLADE - return SOURCE_ENGINE_BLADE; -#elif SOURCE_ENGINE == SE_INSURGENCY - return SOURCE_ENGINE_INSURGENCY; -#elif SOURCE_ENGINE == SE_DOI - return SOURCE_ENGINE_DOI; -#elif SOURCE_ENGINE == SE_CSGO - return SOURCE_ENGINE_CSGO; -#elif SOURCE_ENGINE == SE_DOTA - return SOURCE_ENGINE_DOTA; -#elif SOURCE_ENGINE == SE_BMS - return SOURCE_ENGINE_BMS; -#elif SOURCE_ENGINE == SE_EPISODEONE - return g_bOriginalEngine ? SOURCE_ENGINE_ORIGINAL : SOURCE_ENGINE_EPISODEONE; -#else -#error "SOURCE_ENGINE not defined to a known value" -#endif -} - -ConVar *BaseProvider::CreateConVar(const char *name, - const char *defval, - const char *help, - int flags) -{ - int newflags = 0; - if (flags & ConVarFlag_Notify) - { - newflags |= FCVAR_NOTIFY; - } - if (flags & ConVarFlag_SpOnly) - { - newflags |= FCVAR_SPONLY; - } - - ConVar *pVar = new ConVar(name, defval, newflags, help); - - g_SMConVarAccessor.RegisterConCommandBase(pVar); - - return pVar; -} - -bool BaseProvider::ProcessVDF(const char *file, char path[], size_t path_len, char alias[], size_t alias_len) -{ - if (baseFs == NULL) - { - return false; - } - - KeyValues *pValues; - bool bKVLoaded = false; - const char *plugin_file, *p_alias; - - pValues = new KeyValues("Metamod Plugin"); - - if (g_bOriginalEngine) - { - /* The Ship must use a special version of this function */ - bKVLoaded = KVLoadFromFile(pValues, baseFs, file); - } - else - { - bKVLoaded = pValues->LoadFromFile(baseFs, file); - } - - if (!bKVLoaded) - { - pValues->deleteThis(); - return false; - } - - if ((plugin_file = pValues->GetString("file", NULL)) == NULL) - { - pValues->deleteThis(); - return false; - } - - UTIL_Format(path, path_len, "%s", plugin_file); - - if ((p_alias = pValues->GetString("alias", NULL)) != NULL) - { - UTIL_Format(alias, alias_len, "%s", p_alias); - } - else - { - UTIL_Format(alias, alias_len, ""); - } - - pValues->deleteThis(); - - return true; -} - -const char *BaseProvider::GetEngineDescription() const -{ -#if SOURCE_ENGINE == SE_BLOODYGOODTIME - return "Bloody Good Time (2010)"; -#elif SOURCE_ENGINE == SE_ALIENSWARM - return "Alien Swarm (2010)"; -#elif SOURCE_ENGINE == SE_LEFT4DEAD2 - return "Left 4 Dead 2 (2009)"; -#elif SOURCE_ENGINE == SE_NUCLEARDAWN - return "Nuclear Dawn (2011)"; -#elif SOURCE_ENGINE == SE_CONTAGION - return "Contagion (2013)"; -#elif SOURCE_ENGINE == SE_LEFT4DEAD - return "Left 4 Dead (2008)"; -#elif SOURCE_ENGINE == SE_ORANGEBOX - return "Episode 2 (Orange Box, 2007)"; -#elif SOURCE_ENGINE == SE_CSS - return "Counter-Strike: Source (Valve Orange Box)"; -#elif SOURCE_ENGINE == SE_HL2DM - return "Half-Life 2 Deathmatch (Valve Orange Box)"; -#elif SOURCE_ENGINE == SE_DODS - return "Day of Defeat: Source (Valve Orange Box)"; -#elif SOURCE_ENGINE == SE_SDK2013 - return "Source SDK 2013 (2013)"; -#elif SOURCE_ENGINE == SE_BMS - return "Black Mesa (2015)"; -#elif SOURCE_ENGINE == SE_TF2 - return "Team Fortress 2 (Valve Orange Box)"; -#elif SOURCE_ENGINE == SE_DARKMESSIAH - return "Dark Messiah (2006)"; -#elif SOURCE_ENGINE == SE_EYE - return "E.Y.E. Divine Cybermancy (2011)"; -#elif SOURCE_ENGINE == SE_PORTAL2 - return "Portal 2 (2011)"; -#elif SOURCE_ENGINE == SE_BLADE - return "Blade Symphony (2013)"; -#elif SOURCE_ENGINE == SE_INSURGENCY - return "Insurgency (2013)"; -#elif SOURCE_ENGINE == SE_DOI - return "Day of Infamy (2016)"; -#elif SOURCE_ENGINE == SE_CSGO - return "Counter-Strike: Global Offensive (2012)"; -#elif SOURCE_ENGINE == SE_DOTA - return "Dota 2 (2013)"; -#elif SOURCE_ENGINE == SE_EPISODEONE - if (g_bOriginalEngine) - { - return "Original (pre-Episode 1)"; - } - else - { - return "Episode 1 (2004)"; - } -#else -#error "SOURCE_ENGINE not defined to a known value" -#endif -} - -#if SOURCE_ENGINE >= SE_ORANGEBOX -class GlobCommand : public IMetamodSourceCommandInfo -{ -public: - GlobCommand(const CCommand *cmd) : m_cmd(cmd) - { - } -public: - unsigned int GetArgCount() - { - return m_cmd->ArgC() - 1; - } - - const char *GetArg(unsigned int num) - { - return m_cmd->Arg(num); - } - - const char *GetArgString() - { - return m_cmd->ArgS(); - } -private: - const CCommand *m_cmd; -}; -#else -class GlobCommand : public IMetamodSourceCommandInfo -{ -public: - unsigned int GetArgCount() - { - return engine->Cmd_Argc() - 1; - } - - const char *GetArg(unsigned int num) - { - return engine->Cmd_Argv(num); - } - - const char *GetArgString() - { - return engine->Cmd_Args(); - } -}; -#endif - -#if SOURCE_ENGINE >= SE_ORANGEBOX -void LocalCommand_Meta(const CCommand &args) -{ - GlobCommand cmd(&args); -#else -void LocalCommand_Meta() -{ - GlobCommand cmd; -#endif - Command_Meta(&cmd); -} - -#if SOURCE_ENGINE == SE_DOTA -void ClientCommand(CEntityIndex index, const CCommand &_cmd) -{ - int client = index.Get(); - GlobCommand cmd(&_cmd); -#elif SOURCE_ENGINE >= SE_ORANGEBOX -void ClientCommand(edict_t *client, const CCommand &_cmd) -{ - GlobCommand cmd(&_cmd); -#else -void ClientCommand(edict_t *client) -{ - GlobCommand cmd; -#endif - if (strcmp(cmd.GetArg(0), "meta") == 0) - { - Command_ClientMeta(client, &cmd); - RETURN_META(MRES_SUPERCEDE); - } - - RETURN_META(MRES_IGNORED); -} - -#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA - -void CacheUserMessages() -{ -} - -#else - -/* This only gets called if IServerGameDLL::GetUserMessageInfo() triggers it */ -void Detour_Error(const tchar *pMsg, ...) -{ - /* Jump back to setjmp() in CacheUserMessages() */ - longjmp(usermsg_end, 1); -} - -#define IA32_JMP_IMM32 0xE9 - -/* IServerGameDLL::GetUserMessageInfo() crashes on games based on the old engine and - * early Orange Box. This is because Error() from tier0 gets called when a bad index is - * passed. This is all due to a bug in CUtlRBTree::IsValidIndex(). - * - * So we detour Error() to fix this. Our detour then jumps back into CacheUserMessages() - * to a point before GetUserMessageInfo() is called. The detour is then removed and we - * exit. - */ -void CacheUserMessages() -{ - int q, size; - char buffer[256]; - unsigned char *target, *detour; - unsigned char orig_bytes[5]; - - target = (unsigned char *)&Error; - detour = (unsigned char *)&Detour_Error; - - /* Save bytes from target function */ - memcpy(orig_bytes, target, sizeof(orig_bytes)); - - /* Patch in relative jump to our Error() detour */ - SetMemAccess(target, sizeof(orig_bytes), SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC); - target[0] = IA32_JMP_IMM32; - *(int32_t *)&target[1] = (int32_t)(detour - (target + 5)); - - /* This is where longjmp() will end up */ - if (setjmp(usermsg_end)) - { - /* Restore bytes and memory protection */ - memcpy(target, orig_bytes, sizeof(orig_bytes)); - SetMemAccess(target, sizeof(orig_bytes), SH_MEM_READ|SH_MEM_EXEC); - return; - } - - q = 0; - - /* If GetUserMessageInfo() calls Error(), we should end up in our detour */ - while (server->GetUserMessageInfo(q, buffer, sizeof(buffer), size)) - { - usermsgs_list.push_back(UsrMsgInfo(size, buffer)); - q++; - } - - /* Jump back to setjmp() */ - longjmp(usermsg_end, 1); -} - -#endif - -bool KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID) -{ - Assert(filesystem); -#ifdef _MSC_VER - Assert(_heapchk() == _HEAPOK); -#endif - - FileHandle_t f = filesystem->Open(resourceName, "rb", pathID); - if (!f) - return false; - - // load file into a null-terminated buffer - int fileSize = filesystem->Size(f); - char *buffer = (char *)MemAllocScratch(fileSize + 1); - - Assert(buffer); - - filesystem->Read(buffer, fileSize, f); // read into local buffer - - buffer[fileSize] = 0; // null terminate file as EOF - - filesystem->Close( f ); // close file after reading - - bool retOK = kv->LoadFromBuffer( resourceName, buffer, filesystem ); - - MemFreeScratch(); - - return retOK; -} diff --git a/utils/mmsource/core/provider/provider_ep2.h b/utils/mmsource/core/provider/provider_ep2.h deleted file mode 100644 index 99c758681..000000000 --- a/utils/mmsource/core/provider/provider_ep2.h +++ /dev/null @@ -1,101 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2009 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#ifndef _INCLUDE_METAMOD_SOURCE_BASE_PROVIDER_H_ -#define _INCLUDE_METAMOD_SOURCE_BASE_PROVIDER_H_ - -#if defined _DEBUG -#define DEBUG2 -#undef _DEBUG -#endif -#include -#include -#if SOURCE_ENGINE != SE_DOTA -#include -#endif -#include "ISmmAPI.h" -#include "metamod_provider.h" -#include "metamod_oslink.h" -#if defined DEBUG2 -#undef DEBUG2 -#define _DEBUG -#endif - -using namespace SourceMM; -using namespace SourceHook; - -class INetworkGameServer; - -class BaseProvider : public IMetamodSourceProvider -{ -public: - virtual bool IsSourceEngineBuildCompatible(int build); - virtual bool GetHookInfo(ProvidedHooks hook, SourceHook::MemFuncInfo *pInfo); - virtual bool LogMessage(const char *buffer); - virtual const char *GetCommandLineValue(const char *key, const char *defval); - virtual void ConsolePrint(const char *msg); - virtual bool IsRemotePrintingAvailable(); - virtual void ClientConsolePrint(edict_t *client, const char *msg); - virtual void DisplayError(const char *fmt, ...); - virtual void DisplayWarning(const char *fmt, ...); - virtual int TryServerGameDLL(const char *iface); - virtual void Notify_DLLInit_Pre(CreateInterfaceFn engineFactory, CreateInterfaceFn serverFactory); - void Notify_DLLShutdown_Pre(); - virtual void ServerCommand(const char *cmd); - virtual ConVar *CreateConVar(const char *name, - const char *defval, - const char *help, - int flags); - virtual const char *GetConVarString(ConVar *convar); - virtual void SetConVarString(ConVar *convar, const char *str); - virtual void GetGamePath(char *pszBuffer, int len); - virtual const char *GetGameDescription(); - virtual IConCommandBaseAccessor *GetConCommandBaseAccessor(); - virtual bool RegisterConCommandBase(ConCommandBase *pCommand); - virtual void UnregisterConCommandBase(ConCommandBase *pCommand); - virtual bool IsConCommandBaseACommand(ConCommandBase *pCommand); - virtual int GetUserMessageCount(); - virtual int FindUserMessage(const char *name, int *size=NULL); - virtual const char *GetUserMessage(int index, int *size=NULL); - virtual int DetermineSourceEngine(); - virtual bool ProcessVDF(const char *file, char path[], size_t path_len, char alias[], size_t alias_len); - virtual const char *GetEngineDescription() const; -#if SOURCE_ENGINE == SE_DOTA && defined( _WIN32 ) - bool AllowDedicatedServers(EUniverse universe) const; -#endif -}; - -extern IVEngineServer *engine; -extern IServerGameDLL *server; -extern IServerGameClients *gameclients; -extern ICvar *icvar; -extern CGlobalVars *gpGlobals; -#if SOURCE_ENGINE == SE_DOTA -extern INetworkServerService *netservice; -extern IEngineServiceMgr *enginesvcmgr; -#endif - -#endif //_INCLUDE_METAMOD_SOURCE_BASE_PROVIDER_H_ - diff --git a/utils/mmsource/core/sourcehook/FastDelegate.h b/utils/mmsource/core/sourcehook/FastDelegate.h deleted file mode 100644 index 53a3964c7..000000000 --- a/utils/mmsource/core/sourcehook/FastDelegate.h +++ /dev/null @@ -1,1074 +0,0 @@ -// FastDelegate.h -// Efficient delegates in C++ that generate only two lines of asm code! -// Documentation is found at http://www.codeproject.com/cpp/FastDelegate.asp -// -// - Don Clugston, Mar 2004. -// Major contributions were made by Jody Hagins. -// History: -// 24-Apr-04 1.0 * Submitted to CodeProject. -// 28-Apr-04 1.1 * Prevent most unsafe uses of evil static function hack. -// * Improved syntax for horrible_cast (thanks Paul Bludov). -// * Tested on Metrowerks MWCC and Intel ICL (IA32) -// * Compiled, but not run, on Comeau C++ and Intel Itanium ICL. -// 27-Jun-04 1.2 * Now works on Borland C++ Builder 5.5 -// * Now works on /clr "managed C++" code on VC7, VC7.1 -// * Comeau C++ now compiles without warnings. -// * Prevent the virtual inheritance case from being used on -// VC6 and earlier, which generate incorrect code. -// * Improved warning and error messages. Non-standard hacks -// now have compile-time checks to make them safer. -// * implicit_cast used instead of static_cast in many cases. -// * If calling a const member function, a const class pointer can be used. -// * MakeDelegate() global helper function added to simplify pass-by-value. -// * Added fastdelegate.clear() -// 16-Jul-04 1.2.1* Workaround for gcc bug (const member function pointers in templates) -// 30-Oct-04 1.3 * Support for (non-void) return values. -// * No more workarounds in client code! -// MSVC and Intel now use a clever hack invented by John Dlugosz: -// - The FASTDELEGATEDECLARE workaround is no longer necessary. -// - No more warning messages for VC6 -// * Less use of macros. Error messages should be more comprehensible. -// * Added include guards -// * Added FastDelegate::empty() to test if invocation is safe (Thanks Neville Franks). -// * Now tested on VS 2005 Express Beta, PGI C++ -// 24-Dec-04 1.4 * Added DelegateMemento, to allow collections of disparate delegates. -// * <,>,<=,>= comparison operators to allow storage in ordered containers. -// * Substantial reduction of code size, especially the 'Closure' class. -// * Standardised all the compiler-specific workarounds. -// * MFP conversion now works for CodePlay (but not yet supported in the full code). -// * Now compiles without warnings on _any_ supported compiler, including BCC 5.5.1 -// * New syntax: FastDelegate< int (char *, double) >. -// 14-Feb-05 1.4.1* Now treats =0 as equivalent to .clear(), ==0 as equivalent to .empty(). (Thanks elfric). -// * Now tested on Intel ICL for AMD64, VS2005 Beta for AMD64 and Itanium. -// 30-Mar-05 1.5 * Safebool idiom: "if (dg)" is now equivalent to "if (!dg.empty())" -// * Fully supported by CodePlay VectorC -// * Bugfix for Metrowerks: empty() was buggy because a valid MFP can be 0 on MWCC! -// * More optimal assignment,== and != operators for static function pointers. -// -// AlliedModders LLC modifications. -// -// 24-Oct-15 1.6 * Use C++11 variadic templates. -// - -#ifndef FASTDELEGATE_H -#define FASTDELEGATE_H - -#ifdef _MSC_VER -# if _MSC_VER > 1000 -# pragma once -# endif // _MSC_VER > 1000 -#endif // #ifdef _MSC_VER - -#include // to allow <,> comparisons - -//////////////////////////////////////////////////////////////////////////////// -// Configuration options -// -//////////////////////////////////////////////////////////////////////////////// - -// Uncomment the following #define for optimally-sized delegates. -// In this case, the generated asm code is almost identical to the code you'd get -// if the compiler had native support for delegates. -// It will not work on systems where sizeof(dataptr) < sizeof(codeptr). -// Thus, it will not work for DOS compilers using the medium model. -// It will also probably fail on some DSP systems. -#define FASTDELEGATE_USESTATICFUNCTIONHACK - -// Uncomment the next line to allow function declarator syntax. -// It is automatically enabled for those compilers where it is known to work. -//#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX - -//////////////////////////////////////////////////////////////////////////////// -// Compiler identification for workarounds -// -//////////////////////////////////////////////////////////////////////////////// - -// Compiler identification. It's not easy to identify Visual C++ because -// many vendors fraudulently define Microsoft's identifiers. -#if defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__VECTOR_C) && !defined(__ICL) && !defined(__BORLANDC__) -#define FASTDLGT_ISMSVC - -#if (_MSC_VER <1300) // Many workarounds are required for VC6. -#define FASTDLGT_VC6 -#pragma warning(disable:4786) // disable this ridiculous warning -#endif - -#endif - -// Does the compiler uses Microsoft's member function pointer structure? -// If so, it needs special treatment. -// Metrowerks CodeWarrior, Intel, and CodePlay fraudulently define Microsoft's -// identifier, _MSC_VER. We need to filter Metrowerks out. -#if defined(_MSC_VER) && !defined(__MWERKS__) -#define FASTDLGT_MICROSOFT_MFP - -#if !defined(__VECTOR_C) -// CodePlay doesn't have the __single/multi/virtual_inheritance keywords -#define FASTDLGT_HASINHERITANCE_KEYWORDS -#endif -#endif - -// Does it allow function declarator syntax? The following compilers are known to work: -#if defined(FASTDLGT_ISMSVC) && (_MSC_VER >=1310) // VC 7.1 -#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX -#endif - -// Gcc(2.95+), and versions of Digital Mars, Intel and Comeau in common use. -#if defined (__DMC__) || defined(__GNUC__) || defined(__ICL) || defined(__COMO__) -#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX -#endif - -// It works on Metrowerks MWCC 3.2.2. From boost.Config it should work on earlier ones too. -#if defined (__MWERKS__) -#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX -#endif - -#ifdef __GNUC__ // Workaround GCC bug #8271 - // At present, GCC doesn't recognize constness of MFPs in templates -#define FASTDELEGATE_GCC_BUG_8271 -#endif - - - -//////////////////////////////////////////////////////////////////////////////// -// General tricks used in this code -// -// (a) Error messages are generated by typdefing an array of negative size to -// generate compile-time errors. -// (b) Warning messages on MSVC are generated by declaring unused variables, and -// enabling the "variable XXX is never used" warning. -// (c) Unions are used in a few compiler-specific cases to perform illegal casts. -// (d) For Microsoft and Intel, when adjusting the 'this' pointer, it's cast to -// (char *) first to ensure that the correct number of *bytes* are added. -// -//////////////////////////////////////////////////////////////////////////////// -// Helper templates -// -//////////////////////////////////////////////////////////////////////////////// - - -namespace fastdelegate { -namespace detail { // we'll hide the implementation details in a nested namespace. - -// implicit_cast< > -// I believe this was originally going to be in the C++ standard but -// was left out by accident. It's even milder than static_cast. -// I use it instead of static_cast<> to emphasize that I'm not doing -// anything nasty. -// Usage is identical to static_cast<> -template -inline OutputClass implicit_cast(InputClass input){ - return input; -} - -// horrible_cast< > -// This is truly evil. It completely subverts C++'s type system, allowing you -// to cast from any class to any other class. Technically, using a union -// to perform the cast is undefined behaviour (even in C). But we can see if -// it is OK by checking that the union is the same size as each of its members. -// horrible_cast<> should only be used for compiler-specific workarounds. -// Usage is identical to reinterpret_cast<>. - -// This union is declared outside the horrible_cast because BCC 5.5.1 -// can't inline a function with a nested class, and gives a warning. -template -union horrible_union{ - OutputClass out; - InputClass in; -}; - -template -inline OutputClass horrible_cast(const InputClass input){ - horrible_union u; - // Cause a compile-time error if in, out and u are not the same size. - // If the compile fails here, it means the compiler has peculiar - // unions which would prevent the cast from working. - static_assert(sizeof(InputClass)==sizeof(u) && sizeof(InputClass)==sizeof(OutputClass), - "Can't use horrible cast"); - u.in = input; - return u.out; -} - -//////////////////////////////////////////////////////////////////////////////// -// Workarounds -// -//////////////////////////////////////////////////////////////////////////////// - -// Backwards compatibility: This macro used to be necessary in the virtual inheritance -// case for Intel and Microsoft. Now it just forward-declares the class. -#define FASTDELEGATEDECLARE(CLASSNAME) class CLASSNAME; - -// Prevent use of the static function hack with the DOS medium model. -#ifdef __MEDIUM__ -#undef FASTDELEGATE_USESTATICFUNCTIONHACK -#endif - -// DefaultVoid - a workaround for 'void' templates in VC6. -// -// (1) VC6 and earlier do not allow 'void' as a default template argument. -// (2) They also doesn't allow you to return 'void' from a function. -// -// Workaround for (1): Declare a dummy type 'DefaultVoid' which we use -// when we'd like to use 'void'. We convert it into 'void' and back -// using the templates DefaultVoidToVoid<> and VoidToDefaultVoid<>. -// Workaround for (2): On VC6, the code for calling a void function is -// identical to the code for calling a non-void function in which the -// return value is never used, provided the return value is returned -// in the EAX register, rather than on the stack. -// This is true for most fundamental types such as int, enum, void *. -// Const void * is the safest option since it doesn't participate -// in any automatic conversions. But on a 16-bit compiler it might -// cause extra code to be generated, so we disable it for all compilers -// except for VC6 (and VC5). -#ifdef FASTDLGT_VC6 -// VC6 workaround -typedef const void * DefaultVoid; -#else -// On any other compiler, just use a normal void. -typedef void DefaultVoid; -#endif - -// Translate from 'DefaultVoid' to 'void'. -// Everything else is unchanged -template -struct DefaultVoidToVoid { typedef T type; }; - -template <> -struct DefaultVoidToVoid { typedef void type; }; - -// Translate from 'void' into 'DefaultVoid' -// Everything else is unchanged -template -struct VoidToDefaultVoid { typedef T type; }; - -template <> -struct VoidToDefaultVoid { typedef DefaultVoid type; }; - - - -//////////////////////////////////////////////////////////////////////////////// -// Fast Delegates, part 1: -// -// Conversion of member function pointer to a standard form -// -//////////////////////////////////////////////////////////////////////////////// - -// GenericClass is a fake class, ONLY used to provide a type. -// It is vitally important that it is never defined, so that the compiler doesn't -// think it can optimize the invocation. For example, Borland generates simpler -// code if it knows the class only uses single inheritance. - -// Compilers using Microsoft's structure need to be treated as a special case. -#ifdef FASTDLGT_MICROSOFT_MFP - -#ifdef FASTDLGT_HASINHERITANCE_KEYWORDS - // For Microsoft and Intel, we want to ensure that it's the most efficient type of MFP - // (4 bytes), even when the /vmg option is used. Declaring an empty class - // would give 16 byte pointers in this case.... - class __single_inheritance GenericClass; -#endif - // ...but for Codeplay, an empty class *always* gives 4 byte pointers. - // If compiled with the /clr option ("managed C++"), the JIT compiler thinks - // it needs to load GenericClass before it can call any of its functions, - // (compiles OK but crashes at runtime!), so we need to declare an - // empty class to make it happy. - // Codeplay and VC4 can't cope with the unknown_inheritance case either. - class GenericClass {}; -#else - class GenericClass; -#endif - -// The size of a single inheritance member function pointer. -const int SINGLE_MEMFUNCPTR_SIZE = sizeof(void (GenericClass::*)()); - -// SimplifyMemFunc< >::Convert() -// -// A template function that converts an arbitrary member function pointer into the -// simplest possible form of member function pointer, using a supplied 'this' pointer. -// According to the standard, this can be done legally with reinterpret_cast<>. -// For (non-standard) compilers which use member function pointers which vary in size -// depending on the class, we need to use knowledge of the internal structure of a -// member function pointer, as used by the compiler. Template specialization is used -// to distinguish between the sizes. Because some compilers don't support partial -// template specialisation, I use full specialisation of a wrapper struct. - -// general case -- don't know how to convert it. Force a compile failure -template -struct SimplifyMemFunc { - template - inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, - GenericMemFuncType &bound_func) { - // Unsupported member function type -- force a compile failure. - static_assert(N >= 100, "Unsupported memeber function pointer on this compiler"); - return 0; - } -}; - -// For compilers where all member func ptrs are the same size, everything goes here. -// For non-standard compilers, only single_inheritance classes go here. -template <> -struct SimplifyMemFunc { - template - inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, - GenericMemFuncType &bound_func) { -#if defined __DMC__ - // Digital Mars doesn't allow you to cast between abitrary PMF's, - // even though the standard says you can. The 32-bit compiler lets you - // static_cast through an int, but the DOS compiler doesn't. - bound_func = horrible_cast(function_to_bind); -#else - bound_func = reinterpret_cast(function_to_bind); -#endif - return reinterpret_cast(pthis); - } -}; - -//////////////////////////////////////////////////////////////////////////////// -// Fast Delegates, part 1b: -// -// Workarounds for Microsoft and Intel -// -//////////////////////////////////////////////////////////////////////////////// - - -// Compilers with member function pointers which violate the standard (MSVC, Intel, Codeplay), -// need to be treated as a special case. -#ifdef FASTDLGT_MICROSOFT_MFP - -// We use unions to perform horrible_casts. I would like to use #pragma pack(push, 1) -// at the start of each function for extra safety, but VC6 seems to ICE -// intermittently if you do this inside a template. - -// __multiple_inheritance classes go here -// Nasty hack for Microsoft and Intel (IA32 and Itanium) -template<> -struct SimplifyMemFunc< SINGLE_MEMFUNCPTR_SIZE + sizeof(int) > { - template - inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, - GenericMemFuncType &bound_func) { - // We need to use a horrible_cast to do this conversion. - // In MSVC, a multiple inheritance member pointer is internally defined as: - union { - XFuncType func; - struct { - GenericMemFuncType funcaddress; // points to the actual member function - int delta; // #BYTES to be added to the 'this' pointer - }s; - } u; - // Check that the horrible_cast will work - static_assert(sizeof(function_to_bind)==sizeof(u.s), "Can't use horrible cast"); - u.func = function_to_bind; - bound_func = u.s.funcaddress; - return reinterpret_cast(reinterpret_cast(pthis) + u.s.delta); - } -}; - -// virtual inheritance is a real nuisance. It's inefficient and complicated. -// On MSVC and Intel, there isn't enough information in the pointer itself to -// enable conversion to a closure pointer. Earlier versions of this code didn't -// work for all cases, and generated a compile-time error instead. -// But a very clever hack invented by John M. Dlugosz solves this problem. -// My code is somewhat different to his: I have no asm code, and I make no -// assumptions about the calling convention that is used. - -// In VC++ and ICL, a virtual_inheritance member pointer -// is internally defined as: -struct MicrosoftVirtualMFP { - void (GenericClass::*codeptr)(); // points to the actual member function - int delta; // #bytes to be added to the 'this' pointer - int vtable_index; // or 0 if no virtual inheritance -}; -// The CRUCIAL feature of Microsoft/Intel MFPs which we exploit is that the -// m_codeptr member is *always* called, regardless of the values of the other -// members. (This is *not* true for other compilers, eg GCC, which obtain the -// function address from the vtable if a virtual function is being called). -// Dlugosz's trick is to make the codeptr point to a probe function which -// returns the 'this' pointer that was used. - -// Define a generic class that uses virtual inheritance. -// It has a trival member function that returns the value of the 'this' pointer. -struct GenericVirtualClass : virtual public GenericClass -{ - typedef GenericVirtualClass * (GenericVirtualClass::*ProbePtrType)(); - GenericVirtualClass * GetThis() { return this; } -}; - -// __virtual_inheritance classes go here -template <> -struct SimplifyMemFunc -{ - - template - inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, - GenericMemFuncType &bound_func) { - union { - XFuncType func; - GenericClass* (X::*ProbeFunc)(); - MicrosoftVirtualMFP s; - } u; - u.func = function_to_bind; - bound_func = reinterpret_cast(u.s.codeptr); - union { - GenericVirtualClass::ProbePtrType virtfunc; - MicrosoftVirtualMFP s; - } u2; - // Check that the horrible_cast<>s will work - static_assert(sizeof(function_to_bind)==sizeof(u.s) - && sizeof(function_to_bind)==sizeof(u.ProbeFunc) - && sizeof(u2.virtfunc)==sizeof(u2.s), - "Can't use horrible cast."); - // Unfortunately, taking the address of a MF prevents it from being inlined, so - // this next line can't be completely optimised away by the compiler. - u2.virtfunc = &GenericVirtualClass::GetThis; - u.s.codeptr = u2.s.codeptr; - return (pthis->*u.ProbeFunc)(); - } -}; - -#if (_MSC_VER <1300) - -// Nasty hack for Microsoft Visual C++ 6.0 -// unknown_inheritance classes go here -// There is a compiler bug in MSVC6 which generates incorrect code in this case!! -template <> -struct SimplifyMemFunc -{ - template - inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, - GenericMemFuncType &bound_func) { - // There is an apalling but obscure compiler bug in MSVC6 and earlier: - // vtable_index and 'vtordisp' are always set to 0 in the - // unknown_inheritance case! - // This means that an incorrect function could be called!!! - // Compiling with the /vmg option leads to potentially incorrect code. - // This is probably the reason that the IDE has a user interface for specifying - // the /vmg option, but it is disabled - you can only specify /vmg on - // the command line. In VC1.5 and earlier, the compiler would ICE if it ever - // encountered this situation. - // It is OK to use the /vmg option if /vmm or /vms is specified. - - // Fortunately, the wrong function is only called in very obscure cases. - // It only occurs when a derived class overrides a virtual function declared - // in a virtual base class, and the member function - // points to the *Derived* version of that function. The problem can be - // completely averted in 100% of cases by using the *Base class* for the - // member fpointer. Ie, if you use the base class as an interface, you'll - // stay out of trouble. - // Occasionally, you might want to point directly to a derived class function - // that isn't an override of a base class. In this case, both vtable_index - // and 'vtordisp' are zero, but a virtual_inheritance pointer will be generated. - // We can generate correct code in this case. To prevent an incorrect call from - // ever being made, on MSVC6 we generate a warning, and call a function to - // make the program crash instantly. - static_assert(true, "VC6 Compiler Bug"); - return 0; - } -}; - - -#else - -// Nasty hack for Microsoft and Intel (IA32 and Itanium) -// unknown_inheritance classes go here -// This is probably the ugliest bit of code I've ever written. Look at the casts! -// There is a compiler bug in MSVC6 which prevents it from using this code. -template <> -struct SimplifyMemFunc -{ - template - inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, - GenericMemFuncType &bound_func) { - // The member function pointer is 16 bytes long. We can't use a normal cast, but - // we can use a union to do the conversion. - union { - XFuncType func; - // In VC++ and ICL, an unknown_inheritance member pointer - // is internally defined as: - struct { - GenericMemFuncType m_funcaddress; // points to the actual member function - int delta; // #bytes to be added to the 'this' pointer - int vtordisp; // #bytes to add to 'this' to find the vtable - int vtable_index; // or 0 if no virtual inheritance - } s; - } u; - // Check that the horrible_cast will work - static_assert(sizeof(XFuncType)==sizeof(u.s), "Can't use horrible cast."); - u.func = function_to_bind; - bound_func = u.s.funcaddress; - int virtual_delta = 0; - if (u.s.vtable_index) { // Virtual inheritance is used - // First, get to the vtable. - // It is 'vtordisp' bytes from the start of the class. - const int * vtable = *reinterpret_cast( - reinterpret_cast(pthis) + u.s.vtordisp ); - - // 'vtable_index' tells us where in the table we should be looking. - virtual_delta = u.s.vtordisp + *reinterpret_cast( - reinterpret_cast(vtable) + u.s.vtable_index); - } - // The int at 'virtual_delta' gives us the amount to add to 'this'. - // Finally we can add the three components together. Phew! - return reinterpret_cast( - reinterpret_cast(pthis) + u.s.delta + virtual_delta); - }; -}; -#endif // MSVC 7 and greater - -#endif // MS/Intel hacks - -} // namespace detail - -//////////////////////////////////////////////////////////////////////////////// -// Fast Delegates, part 2: -// -// Define the delegate storage, and cope with static functions -// -//////////////////////////////////////////////////////////////////////////////// - -// DelegateMemento -- an opaque structure which can hold an arbitary delegate. -// It knows nothing about the calling convention or number of arguments used by -// the function pointed to. -// It supplies comparison operators so that it can be stored in STL collections. -// It cannot be set to anything other than null, nor invoked directly: -// it must be converted to a specific delegate. - -// Implementation: -// There are two possible implementations: the Safe method and the Evil method. -// DelegateMemento - Safe version -// -// This implementation is standard-compliant, but a bit tricky. -// A static function pointer is stored inside the class. -// Here are the valid values: -// +-- Static pointer --+--pThis --+-- pMemFunc-+-- Meaning------+ -// | 0 | 0 | 0 | Empty | -// | !=0 |(dontcare)| Invoker | Static function| -// | 0 | !=0 | !=0* | Method call | -// +--------------------+----------+------------+----------------+ -// * For Metrowerks, this can be 0. (first virtual function in a -// single_inheritance class). -// When stored stored inside a specific delegate, the 'dontcare' entries are replaced -// with a reference to the delegate itself. This complicates the = and == operators -// for the delegate class. - -// DelegateMemento - Evil version -// -// For compilers where data pointers are at least as big as code pointers, it is -// possible to store the function pointer in the this pointer, using another -// horrible_cast. In this case the DelegateMemento implementation is simple: -// +--pThis --+-- pMemFunc-+-- Meaning---------------------+ -// | 0 | 0 | Empty | -// | !=0 | !=0* | Static function or method call| -// +----------+------------+-------------------------------+ -// * For Metrowerks, this can be 0. (first virtual function in a -// single_inheritance class). -// Note that the Sun C++ and MSVC documentation explicitly state that they -// support static_cast between void * and function pointers. - -class DelegateMemento { -protected: - // the data is protected, not private, because many - // compilers have problems with template friends. - typedef void (detail::GenericClass::*GenericMemFuncType)(); // arbitrary MFP. - detail::GenericClass *m_pthis; - GenericMemFuncType m_pFunction; - -#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) - typedef void (*GenericFuncPtr)(); // arbitrary code pointer - GenericFuncPtr m_pStaticFunction; -#endif - -public: -#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) - DelegateMemento() : m_pthis(0), m_pFunction(0), m_pStaticFunction(0) {}; - void clear() { - m_pthis=0; m_pFunction=0; m_pStaticFunction=0; - } -#else - DelegateMemento() : m_pthis(0), m_pFunction(0) {}; - void clear() { m_pthis=0; m_pFunction=0; } -#endif -public: -#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) - inline bool IsEqual (const DelegateMemento &x) const{ - // We have to cope with the static function pointers as a special case - if (m_pFunction!=x.m_pFunction) return false; - // the static function ptrs must either both be equal, or both be 0. - if (m_pStaticFunction!=x.m_pStaticFunction) return false; - if (m_pStaticFunction!=0) return m_pthis==x.m_pthis; - else return true; - } -#else // Evil Method - inline bool IsEqual (const DelegateMemento &x) const{ - return m_pthis==x.m_pthis && m_pFunction==x.m_pFunction; - } -#endif - // Provide a strict weak ordering for DelegateMementos. - inline bool IsLess(const DelegateMemento &right) const { - // deal with static function pointers first -#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) - if (m_pStaticFunction !=0 || right.m_pStaticFunction!=0) - return m_pStaticFunction < right.m_pStaticFunction; -#endif - if (m_pthis !=right.m_pthis) return m_pthis < right.m_pthis; - // There are no ordering operators for member function pointers, - // but we can fake one by comparing each byte. The resulting ordering is - // arbitrary (and compiler-dependent), but it permits storage in ordered STL containers. - return memcmp(&m_pFunction, &right.m_pFunction, sizeof(m_pFunction)) < 0; - - } - // BUGFIX (Mar 2005): - // We can't just compare m_pFunction because on Metrowerks, - // m_pFunction can be zero even if the delegate is not empty! - inline bool operator ! () const // Is it bound to anything? - { return m_pthis==0 && m_pFunction==0; } - inline bool empty() const // Is it bound to anything? - { return m_pthis==0 && m_pFunction==0; } -public: - DelegateMemento & operator = (const DelegateMemento &right) { - SetMementoFrom(right); - return *this; - } - inline bool operator <(const DelegateMemento &right) { - return IsLess(right); - } - inline bool operator >(const DelegateMemento &right) { - return right.IsLess(*this); - } - DelegateMemento (const DelegateMemento &right) : - m_pthis(right.m_pthis), m_pFunction(right.m_pFunction) -#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) - , m_pStaticFunction (right.m_pStaticFunction) -#endif - {} -protected: - void SetMementoFrom(const DelegateMemento &right) { - m_pFunction = right.m_pFunction; - m_pthis = right.m_pthis; -#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) - m_pStaticFunction = right.m_pStaticFunction; -#endif - } -}; - - -// ClosurePtr<> -// -// A private wrapper class that adds function signatures to DelegateMemento. -// It's the class that does most of the actual work. -// The signatures are specified by: -// GenericMemFunc: must be a type of GenericClass member function pointer. -// StaticFuncPtr: must be a type of function pointer with the same signature -// as GenericMemFunc. -// UnvoidStaticFuncPtr: is the same as StaticFuncPtr, except on VC6 -// where it never returns void (returns DefaultVoid instead). - -// An outer class, FastDelegateN<>, handles the invoking and creates the -// necessary typedefs. -// This class does everything else. - -namespace detail { - -template < class GenericMemFunc, class StaticFuncPtr, class UnvoidStaticFuncPtr> -class ClosurePtr : public DelegateMemento { -public: - // These functions are for setting the delegate to a member function. - - // Here's the clever bit: we convert an arbitrary member function into a - // standard form. XMemFunc should be a member function of class X, but I can't - // enforce that here. It needs to be enforced by the wrapper class. - template < class X, class XMemFunc > - inline void bindmemfunc(X *pthis, XMemFunc function_to_bind ) { - m_pthis = SimplifyMemFunc< sizeof(function_to_bind) > - ::Convert(pthis, function_to_bind, m_pFunction); -#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) - m_pStaticFunction = 0; -#endif - } - // For const member functions, we only need a const class pointer. - // Since we know that the member function is const, it's safe to - // remove the const qualifier from the 'this' pointer with a const_cast. - // VC6 has problems if we just overload 'bindmemfunc', so we give it a different name. - template < class X, class XMemFunc> - inline void bindconstmemfunc(const X *pthis, XMemFunc function_to_bind) { - m_pthis= SimplifyMemFunc< sizeof(function_to_bind) > - ::Convert(const_cast(pthis), function_to_bind, m_pFunction); -#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) - m_pStaticFunction = 0; -#endif - } -#ifdef FASTDELEGATE_GCC_BUG_8271 // At present, GCC doesn't recognize constness of MFPs in templates - template < class X, class XMemFunc> - inline void bindmemfunc(const X *pthis, XMemFunc function_to_bind) { - bindconstmemfunc(pthis, function_to_bind); -#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) - m_pStaticFunction = 0; -#endif - } -#endif - // These functions are required for invoking the stored function - inline GenericClass *GetClosureThis() const { return m_pthis; } - inline GenericMemFunc GetClosureMemPtr() const { return reinterpret_cast(m_pFunction); } - -// There are a few ways of dealing with static function pointers. -// There's a standard-compliant, but tricky method. -// There's also a straightforward hack, that won't work on DOS compilers using the -// medium memory model. It's so evil that I can't recommend it, but I've -// implemented it anyway because it produces very nice asm code. - -#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) - -// ClosurePtr<> - Safe version -// -// This implementation is standard-compliant, but a bit tricky. -// I store the function pointer inside the class, and the delegate then -// points to itself. Whenever the delegate is copied, these self-references -// must be transformed, and this complicates the = and == operators. -public: - // The next two functions are for operator ==, =, and the copy constructor. - // We may need to convert the m_pthis pointers, so that - // they remain as self-references. - template< class DerivedClass > - inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &x) { - SetMementoFrom(x); - if (m_pStaticFunction!=0) { - // transform self references... - m_pthis=reinterpret_cast(pParent); - } - } - // For static functions, the 'static_function_invoker' class in the parent - // will be called. The parent then needs to call GetStaticFunction() to find out - // the actual function to invoke. - template < class DerivedClass, class ParentInvokerSig > - inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, - StaticFuncPtr function_to_bind ) { - if (function_to_bind==0) { // cope with assignment to 0 - m_pFunction=0; - } else { - bindmemfunc(pParent, static_function_invoker); - } - m_pStaticFunction=reinterpret_cast(function_to_bind); - } - inline UnvoidStaticFuncPtr GetStaticFunction() const { - return reinterpret_cast(m_pStaticFunction); - } -#else - -// ClosurePtr<> - Evil version -// -// For compilers where data pointers are at least as big as code pointers, it is -// possible to store the function pointer in the this pointer, using another -// horrible_cast. Invocation isn't any faster, but it saves 4 bytes, and -// speeds up comparison and assignment. If C++ provided direct language support -// for delegates, they would produce asm code that was almost identical to this. -// Note that the Sun C++ and MSVC documentation explicitly state that they -// support static_cast between void * and function pointers. - - template< class DerivedClass > - inline void CopyFrom (DerivedClass *pParent, const DelegateMemento &right) { - SetMementoFrom(right); - } - // For static functions, the 'static_function_invoker' class in the parent - // will be called. The parent then needs to call GetStaticFunction() to find out - // the actual function to invoke. - // ******** EVIL, EVIL CODE! ******* - template < class DerivedClass, class ParentInvokerSig> - inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, - StaticFuncPtr function_to_bind) { - if (function_to_bind==0) { // cope with assignment to 0 - m_pFunction=0; - } else { - // We'll be ignoring the 'this' pointer, but we need to make sure we pass - // a valid value to bindmemfunc(). - bindmemfunc(pParent, static_function_invoker); - } - - // WARNING! Evil hack. We store the function in the 'this' pointer! - // Ensure that there's a compilation failure if function pointers - // and data pointers have different sizes. - // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK. - static_assert(sizeof(GenericClass *)==sizeof(function_to_bind), "Can't use evil method."); - m_pthis = horrible_cast(function_to_bind); - // MSVC, SunC++ and DMC accept the following (non-standard) code: -// m_pthis = static_cast(static_cast(function_to_bind)); - // BCC32, Comeau and DMC accept this method. MSVC7.1 needs __int64 instead of long -// m_pthis = reinterpret_cast(reinterpret_cast(function_to_bind)); - } - // ******** EVIL, EVIL CODE! ******* - // This function will be called with an invalid 'this' pointer!! - // We're just returning the 'this' pointer, converted into - // a function pointer! - inline UnvoidStaticFuncPtr GetStaticFunction() const { - // Ensure that there's a compilation failure if function pointers - // and data pointers have different sizes. - // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK. - static_assert(sizeof(UnvoidStaticFuncPtr)==sizeof(this), "Can't use evil method."); - return horrible_cast(this); - } -#endif // !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) - - // Does the closure contain this static function? - inline bool IsEqualToStaticFuncPtr(StaticFuncPtr funcptr){ - if (funcptr==0) return empty(); - // For the Evil method, if it doesn't actually contain a static function, this will return an arbitrary - // value that is not equal to any valid function pointer. - else return funcptr==reinterpret_cast(GetStaticFunction()); - } -}; - - -} // namespace detail - -//////////////////////////////////////////////////////////////////////////////// -// Fast Delegates, part 3: -// -// Wrapper classes to ensure type safety -// -//////////////////////////////////////////////////////////////////////////////// - - -// Once we have the member function conversion templates, it's easy to make the -// wrapper classes. So that they will work with as many compilers as possible, -// the classes are of the form -// FastDelegate3 -// They can cope with any combination of parameters. The max number of parameters -// allowed is 8, but it is trivial to increase this limit. -// Note that we need to treat const member functions seperately. -// All this class does is to enforce type safety, and invoke the delegate with -// the correct list of parameters. - -// Because of the weird rule about the class of derived member function pointers, -// you sometimes need to apply a downcast to the 'this' pointer. -// This is the reason for the use of "implicit_cast(pthis)" in the code below. -// If CDerivedClass is derived from CBaseClass, but doesn't override SimpleVirtualFunction, -// without this trick you'd need to write: -// MyDelegate(static_cast(&d), &CDerivedClass::SimpleVirtualFunction); -// but with the trick you can write -// MyDelegate(&d, &CDerivedClass::SimpleVirtualFunction); - -// RetType is the type the compiler uses in compiling the template. For VC6, -// it cannot be void. DesiredRetType is the real type which is returned from -// all of the functions. It can be void. - -// Implicit conversion to "bool" is achieved using the safe_bool idiom, -// using member data pointers (MDP). This allows "if (dg)..." syntax -// Because some compilers (eg codeplay) don't have a unique value for a zero -// MDP, an extra padding member is added to the SafeBool struct. -// Some compilers (eg VC6) won't implicitly convert from 0 to an MDP, so -// in that case the static function constructor is not made explicit; this -// allows "if (dg==0) ..." to compile. - -template -class FastDelegate { -private: - typedef typename detail::DefaultVoidToVoid::type DesiredRetType; - typedef DesiredRetType (*StaticFunctionPtr)(Params... params); - typedef RetType (*UnvoidStaticFunctionPtr)(Params... params); - typedef RetType (detail::GenericClass::*GenericMemFn)(Params... params); - typedef detail::ClosurePtr ClosureType; - ClosureType m_Closure; -public: - // Typedefs to aid generic programming - typedef FastDelegate type; - - // Construction and comparison functions - FastDelegate() { - clear(); - } - FastDelegate(const FastDelegate &x) { - m_Closure.CopyFrom(this, x.m_Closure); - } - void operator = (const FastDelegate &x) { - m_Closure.CopyFrom(this, x.m_Closure); - } - bool operator ==(const FastDelegate &x) const { - return m_Closure.IsEqual(x.m_Closure); - } - bool operator !=(const FastDelegate &x) const { - return !m_Closure.IsEqual(x.m_Closure); - } - bool operator <(const FastDelegate &x) const { - return m_Closure.IsLess(x.m_Closure); - } - bool operator >(const FastDelegate &x) const { - return x.m_Closure.IsLess(m_Closure); - } - // Binding to non-const member functions - template < class X, class Y > - FastDelegate(Y *pthis, DesiredRetType (X::* function_to_bind)(Params... params) ) { - m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); - } - template < class X, class Y > - inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Params... params)) { - m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); - } - // Binding to const member functions. - template < class X, class Y > - FastDelegate(const Y *pthis, DesiredRetType (X::* function_to_bind)(Params... params) const) { - m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); - } - template < class X, class Y > - inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Params... params) const) { - m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); - } - // Static functions. We convert them into a member function call. - // This constructor also provides implicit conversion - FastDelegate(DesiredRetType (*function_to_bind)(Params... params) ) { - bind(function_to_bind); - } - // for efficiency, prevent creation of a temporary - void operator = (DesiredRetType (*function_to_bind)(Params... params) ) { - bind(function_to_bind); - } - inline void bind(DesiredRetType (*function_to_bind)(Params... params)) { - m_Closure.bindstaticfunc(this, &FastDelegate::InvokeStaticFunction, function_to_bind); - } - // Invoke the delegate - RetType operator() (Params... params) const { - return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(params...); - } - // Implicit conversion to "bool" using the safe_bool idiom -private: - typedef struct SafeBoolStruct { - int a_data_pointer_to_this_is_0_on_buggy_compilers; - StaticFunctionPtr m_nonzero; - } UselessTypedef; - typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; -public: - operator unspecified_bool_type() const { - return empty() ? 0: &SafeBoolStruct::m_nonzero; - } - // necessary to allow ==0 to work despite the safe_bool idiom - inline bool operator==(StaticFunctionPtr funcptr) { - return m_Closure.IsEqualToStaticFuncPtr(funcptr); - } - inline bool operator!=(StaticFunctionPtr funcptr) { - return !m_Closure.IsEqualToStaticFuncPtr(funcptr); - } - inline bool operator ! () const { // Is it bound to anything? - return !m_Closure; - } - inline bool empty() const { - return !m_Closure; - } - void clear() { - m_Closure.clear(); - } - // Conversion to and from the DelegateMemento storage class - const DelegateMemento & GetMemento() { - return m_Closure; - } - void SetMemento(const DelegateMemento &any) { - m_Closure.CopyFrom(this, any); - } - -private: - // Invoker for static functions - RetType InvokeStaticFunction(Params... params) const { - return (*(m_Closure.GetStaticFunction()))(params...); - } -}; - -//////////////////////////////////////////////////////////////////////////////// -// Fast Delegates, part 4: -// -// FastDelegate<> class (Original author: Jody Hagins) -// Allows boost::function style syntax like: -// FastDelegate< double (int, long) > -// instead of: -// FastDelegate2< int, long, double > -// -//////////////////////////////////////////////////////////////////////////////// - -#ifdef FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX - -//N=0 -// Specialization to allow use of -// FastDelegate< R ( ) > -// instead of -// FastDelegate0 < R > -template -class FastDelegate< R (Params...) > - // Inherit from FastDelegate0 so that it can be treated just like a FastDelegate0 - : public FastDelegate < R, Params... > -{ -public: - // Make using the base type a bit easier via typedef. - typedef FastDelegate < R, Params... > BaseType; - - // Allow users access to the specific type of this delegate. - typedef FastDelegate SelfType; - - // Mimic the base class constructors. - FastDelegate() : BaseType() { } - - template < class X, class Y > - FastDelegate(Y * pthis, - R (X::* function_to_bind)(Params... params)) - : BaseType(pthis, function_to_bind) { } - - template < class X, class Y > - FastDelegate(const Y *pthis, - R (X::* function_to_bind)(Params... params) const) - : BaseType(pthis, function_to_bind) - { } - - FastDelegate(R (*function_to_bind)(Params... params)) - : BaseType(function_to_bind) { } - void operator = (const BaseType &x) { - *static_cast(this) = x; } -}; - -#endif //FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX - -//////////////////////////////////////////////////////////////////////////////// -// Fast Delegates, part 5: -// -// MakeDelegate() helper function -// -// MakeDelegate(&x, &X::func) returns a fastdelegate of the type -// necessary for calling x.func() with the correct number of arguments. -// This makes it possible to eliminate many typedefs from user code. -// -//////////////////////////////////////////////////////////////////////////////// - -// Also declare overloads of a MakeDelegate() global function to -// reduce the need for typedefs. -// We need seperate overloads for const and non-const member functions. -// Also, because of the weird rule about the class of derived member function pointers, -// implicit downcasts may need to be applied later to the 'this' pointer. -// That's why two classes (X and Y) appear in the definitions. Y must be implicitly -// castable to X. - -// Workaround for VC6. VC6 needs void return types converted into DefaultVoid. -// GCC 3.2 and later won't compile this unless it's preceded by 'typename', -// but VC6 doesn't allow 'typename' in this context. -// So, I have to use a macro. - -#ifdef FASTDLGT_VC6 -#define FASTDLGT_RETTYPE detail::VoidToDefaultVoid::type -#else -#define FASTDLGT_RETTYPE RetType -#endif - -//N=1 -template -FastDelegate MakeDelegate(Y* x, RetType (X::*func)(Params... params)) { - return FastDelegate(x, func); -} - -template -FastDelegate MakeDelegate(Y* x, RetType (X::*func)(Params... params) const) { - return FastDelegate(x, func); -} - -template -FastDelegate MakeDelegate(RetType (*func)(Params... params)) { - return FastDelegate(func); -} - - // clean up after ourselves... -#undef FASTDLGT_RETTYPE - -} // namespace fastdelegate - -#endif // !defined(FASTDELEGATE_H) diff --git a/utils/mmsource/core/sourcehook/generate/generate b/utils/mmsource/core/sourcehook/generate/generate deleted file mode 100644 index 399784ccf..000000000 --- a/utils/mmsource/core/sourcehook/generate/generate +++ /dev/null @@ -1,9 +0,0 @@ -#/bin/sh - -cd shworker -make -cd .. - -shworker/bin/shworker.bin iter sourcehook.hxx sourcehook.h $1 - -cp *.h .. diff --git a/utils/mmsource/core/sourcehook/generate/generate.bat b/utils/mmsource/core/sourcehook/generate/generate.bat deleted file mode 100644 index 82a8c51ed..000000000 --- a/utils/mmsource/core/sourcehook/generate/generate.bat +++ /dev/null @@ -1,8 +0,0 @@ -:: Generates everything -:: Usage: -:: generate.bat - - -shworker iter sourcehook.hxx sourcehook.h %1 - -copy *.h .. diff --git a/utils/mmsource/core/sourcehook/generate/shworker.bin b/utils/mmsource/core/sourcehook/generate/shworker.bin deleted file mode 100644 index 96105b3c7..000000000 Binary files a/utils/mmsource/core/sourcehook/generate/shworker.bin and /dev/null differ diff --git a/utils/mmsource/core/sourcehook/generate/shworker/Makefile b/utils/mmsource/core/sourcehook/generate/shworker/Makefile deleted file mode 100644 index 933fe55c3..000000000 --- a/utils/mmsource/core/sourcehook/generate/shworker/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -CPP = gcc - -default: shworker - -bin: - mkdir bin - -fd_hopter.o: fd_hopter.cpp bin - $(CPP) -fPIC -O2 -o bin/$@ -c $< - -main.o: shworker.cpp bin - $(CPP) -fPIC -O2 -o bin/$@ -c $< - -shworker: fd_hopter.o main.o bin - $(CPP) -ldl -lstdc++ bin/fd_hopter.o bin/main.o -o bin/shworker.bin diff --git a/utils/mmsource/core/sourcehook/generate/shworker/fd_hopter.cpp b/utils/mmsource/core/sourcehook/generate/shworker/fd_hopter.cpp deleted file mode 100644 index 7fc149d6e..000000000 --- a/utils/mmsource/core/sourcehook/generate/shworker/fd_hopter.cpp +++ /dev/null @@ -1,370 +0,0 @@ -// From fastdelegate -// http://www.codeproject.com/cpp/FastDelegate.asp - -// Modified to be run from shworker by PM - - -// HOPTER.EXE -- A simple header generator for vararg templates -/* MOTIVATION - C++ doesn't have a vararg feature for templates. This can be a - nuisance when writing class libraries. There are a few options: - (a) manually repeat code. This is tedious and error prone. - (b) Use macros. Messy, can't cope with template - arguments, and users get hard-to-interpret error messages. - (c) Use the boost preprocessor library. This slows compilation, - and introduces a dependency on boost. - (d) Write a program to automatically generate the code. - I've never seen a general program to do this job, so this is - a very simple command-line program to do it. - - Why is it called Hopter? - I wanted a word that started with h, to be reminiscent of header - files. At the time, my 2yo son kept talking about 'Hopter Copters' - (he couldn't pronounce 'helicopter'). - It also reflects the level of sophistication of this program -- - it was named by a two year old. - - IMPLEMENTATION - - When you analyze the problem, you find that the requirements - are very simple. - Varargs are needed in two places: templates and functions. - You want to use them in two ways: when declaring the template - or function, and when invoking the function / selecting the - template. - - It's a brain-dead implementation, which just does a search-and-replace - of specific strings. It could be done with a few lines using sed on - a *NIX platform. Because I use Windows, I've done a quick and dirty - implementation using CString. - -In a file, @VARARGS at the start of a line indicates the start of the code -to be expanded. @ENDVAR at the start of a line marks the end of the -expansion. - - declare template -- template <@CLASSARGS> class SomeClass - template - class SomeClass - - declare function -- somefunc(@FUNCARGS) - somefunc(Param1 p1, Param2 p2) - - select template -- SomeClass<@SELARGS> - SomeClass - - invoke function -- somefunc(@INVOKEARGS) - somefunc(p1, p2) - - I also provide @NUM which is the number of arguments. - The case where @NUM is zero is a special case: for template declarations, - the entire template<> bit needs to disappear. When other arguments are - involved, either at the beginning or end of the list, there a commas - which might need to be removed. - - I've used .hxx as the extension for these files. This enables C++ - I wanted to use an unusual file extension (.HOH) for these files, because they - aren't real header files. But I also like to use the C++ syntax highlighting - in Visual Studio. I chose .hxx because MSVC treats it as C++, but it - seems to very rarely used. - - Installation (for VC6, if you want to use .HOH as the extension instead): - Go into the registry and change - HKEY_CURRENT_USER\Software\Microsoft\DevStudio\6.0\Text Editor\Tabs/Language Settings\C/C++\FileExtensions from cpp;cxx;c;h;hxx;hpp;inl;tlh;tli;rc;rc2 - to cpp;cxx;c;h;hxx;hpp;inl;tlh;tli;rc;rc2;hoh by adding ;hoh to the end. - Then add this as a custom build step to the main file of your project: - hopter $(InputDir)\*.hoh $(InputDir)\*.h - -*/ - -#include -#include -#include - -// This is a quick-n-dirty implementation of a CString replacement. -// It promises nothing more than to provide enough functionality to get -// this program to run. -// Note that I have really never used CString, so the information to -// implement the members that are used in this program come from -// online documentation at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vcmfc98/html/_mfc_cstring.asp -// Also, I have only used VC++ a few times, a long time ago, so -// I really do not know what all their alphabet soup is suppoed to -// mean, so I just made a guess... - - -class CString -{ -public: - enum { MAX_FORMAT_STRING_SIZE = 8 * 1044 }; - CString() - : str_() - { - } - - CString( - CString const & rhs) - : str_(rhs.str_) - { - } - - CString( - char ch, - int repeat = 1) - : str_(repeat, ch) - { - } - - CString( - char const * s) - : str_(s) - { - } - - CString & operator=( - CString const & rhs) - { - str_ = rhs.str_; - return *this; - } - - CString & operator=( - char const * s) - { - str_ = s; - return *this; - } - - CString & operator=( - char ch) - { - str_ = ch; - return *this; - } - - void Format( - char const * fmt, - ...) - { - char buffer[ MAX_FORMAT_STRING_SIZE ]; - va_list ap; - va_start(ap, fmt); - vsprintf(buffer, fmt, ap); - va_end(ap); - str_ = buffer; - } - - char operator[]( - int x) const - { - return str_[x]; - } - - CString & operator+=( - CString const & x) - { - str_ += x.str_; return *this; - } - - int Replace( - CString const & lhs, - CString const & rhs) - { - int rval = 0; - std::string::size_type pos = 0; - while (pos < str_.length()) - { - pos = str_.find(lhs.str_, pos); - if (pos != std::string::npos) - { - str_.replace(pos, lhs.GetLength(), rhs.str_); - pos += rhs.GetLength(); - ++rval; - } - } - return rval; - } - - int GetLength() const - { - return str_.length(); - } - - operator char const * () const - { - return str_.c_str(); - } - -private: - std::string str_; -}; - - -CString operator+( - CString const & x, - CString const & y) -{ - CString result(x); - result += y; - return result; -} - - -/* Example: This is an excerpt from boost::function_template.hpp - -#define BOOST_FUNCTION_FUNCTION_INVOKER \ - BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS) -#define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \ - BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS) - - template< - typename FunctionPtr, - typename R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_PARMS - > - struct BOOST_FUNCTION_GET_FUNCTION_INVOKER - { - typedef typename ct_if<(is_void::value), - BOOST_FUNCTION_VOID_FUNCTION_INVOKER< - FunctionPtr, - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS - >, - BOOST_FUNCTION_FUNCTION_INVOKER< - FunctionPtr, - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS - > - >::type type; - }; - -Using HOPTER, this can be written as: - - template< typename FunctionPtr, typename R, @CLASSARGS> - struct get_function_invoker@NUM - { - typedef typename ct_if<(is_void::value), - void_function_invoker@NUM, - function_invoker@NUM - >::type type; - }; -*/ - -int MaxNumArgs; - -/// Makes the necessary subsititutions in 'bigblock', and writes to fout. -void PrintVarArgs(FILE *fout, CString bigblock, int num) { - CString numstr; - CString invokelist; - CString funclist; - CString selectlist; - CString classlist; - CString commastr; - numstr.Format("%d", num); - if (num==0) { - invokelist=""; - funclist=""; - selectlist=""; - commastr=""; - classlist=""; - }else { - invokelist="p1"; - funclist="Param1 p1"; - selectlist = "Param1"; - classlist = "class Param1"; - commastr=", "; - CString str; - for (int k=2; k<=num; k++) { - str.Format(", p%d", k); - invokelist+=str; - str.Format(", Param%d p%d", k, k); - funclist+=str; - str.Format(", Param%d", k); - selectlist += str; - str.Format(", class Param%d", k); - classlist += str; - } - } - - // Simple replacement of number of arguments - bigblock.Replace("@NUM", numstr); - - // Template declarations - if (num==0) bigblock.Replace("template<@CLASSARGS>", ""); - else bigblock.Replace("template<@CLASSARGS>", - (CString)"template<" + classlist+">"); - if (num==0) bigblock.Replace("template <@CLASSARGS>", ""); - else bigblock.Replace("template <@CLASSARGS>", - (CString)"template<" + classlist+">"); - bigblock.Replace(",@CLASSARGS", commastr + classlist); - bigblock.Replace(", @CLASSARGS", commastr + classlist); - bigblock.Replace("@CLASSARGS, ", classlist + commastr); - bigblock.Replace("@CLASSARGS,", classlist + commastr); - bigblock.Replace("@CLASSARGS", classlist); - - // Template selections - CString selargstr; - if (num==0) selargstr = ""; - else selargstr = (CString)"<"+selectlist+">"; - - bigblock.Replace("<@SELARGS>", selargstr); - bigblock.Replace("< @SELARGS >", selargstr); - bigblock.Replace(",@SELARGS", commastr + selectlist); - bigblock.Replace(", @SELARGS", commastr + selectlist); - bigblock.Replace("@SELARGS, ", selectlist + commastr); - bigblock.Replace("@SELARGS,", selectlist + commastr); - bigblock.Replace("@SELARGS", selectlist); - - // Function declarations - bigblock.Replace(",@FUNCARGS", commastr + funclist); - bigblock.Replace(", @FUNCARGS", commastr + funclist); - bigblock.Replace("@FUNCARGS, ", funclist + commastr); - bigblock.Replace("@FUNCARGS,", funclist + commastr); - bigblock.Replace("@FUNCARGS", funclist); - - // Function invocation - bigblock.Replace(",@INVOKEARGS", commastr + invokelist); - bigblock.Replace(", @INVOKEARGS", commastr + invokelist); - bigblock.Replace("@INVOKEARGS, ", invokelist + commastr); - bigblock.Replace("@INVOKEARGS,", invokelist + commastr); - bigblock.Replace("@INVOKEARGS", invokelist); - - fprintf(fout, bigblock); -} - -int action_hopter(int numargs, const char *filenamein, const char *filenameout) -{ - - MaxNumArgs = numargs; - - FILE * fin; - FILE *fout; - - fin =fopen(filenamein,"rt"); - if (!fin) { printf("Error, can't open %s\n", filenamein); return 1; }; - fout = fopen (filenameout, "wt"); - if (!fout) { printf("Error, can't open %s\n", filenameout); return 1; }; - char buf[5000]; - for (;;) { - if (!fgets(buf, 5000, fin)) break; - if (!strncmp(buf, "@VARARGS", 8)) { - // found a match... - CString bigblock; - for (;;) { - if (feof(fin)) { printf("No matching @ENDVAR !!??\n"); return 1; }; - fgets(buf, 5000, fin); - if (!strncmp(buf, "@ENDVAR", 7)) break; - bigblock+=buf; - } -// fprintf(fout, "// Auto-generated code [[[\n"); - for (int k=0; k<=MaxNumArgs; k++) { - fprintf(fout, "//N=%d\n", k); - PrintVarArgs(fout, bigblock, k); - } -// fprintf(fout, "// ]]] End auto-generated code\n"); - } else { - fprintf(fout, "%s", buf); - } - } - fclose(fin); - fclose(fout); - return 0; -} diff --git a/utils/mmsource/core/sourcehook/generate/shworker/msvc7/shworker.vcproj b/utils/mmsource/core/sourcehook/generate/shworker/msvc7/shworker.vcproj deleted file mode 100644 index 1218a8ef3..000000000 --- a/utils/mmsource/core/sourcehook/generate/shworker/msvc7/shworker.vcproj +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/utils/mmsource/core/sourcehook/generate/shworker/msvc8/shworker.vcproj b/utils/mmsource/core/sourcehook/generate/shworker/msvc8/shworker.vcproj deleted file mode 100644 index 6f0ca43b5..000000000 --- a/utils/mmsource/core/sourcehook/generate/shworker/msvc8/shworker.vcproj +++ /dev/null @@ -1,208 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/utils/mmsource/core/sourcehook/generate/shworker/msvc9/shworker.sln b/utils/mmsource/core/sourcehook/generate/shworker/msvc9/shworker.sln deleted file mode 100644 index 185d2559c..000000000 --- a/utils/mmsource/core/sourcehook/generate/shworker/msvc9/shworker.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shworker", "shworker.vcproj", "{7CD76E64-A9DF-47DB-8A68-36297C67E557}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7CD76E64-A9DF-47DB-8A68-36297C67E557}.Debug|Win32.ActiveCfg = Debug|Win32 - {7CD76E64-A9DF-47DB-8A68-36297C67E557}.Debug|Win32.Build.0 = Debug|Win32 - {7CD76E64-A9DF-47DB-8A68-36297C67E557}.Release|Win32.ActiveCfg = Release|Win32 - {7CD76E64-A9DF-47DB-8A68-36297C67E557}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/utils/mmsource/core/sourcehook/generate/shworker/msvc9/shworker.vcproj b/utils/mmsource/core/sourcehook/generate/shworker/msvc9/shworker.vcproj deleted file mode 100644 index 8878a27bc..000000000 --- a/utils/mmsource/core/sourcehook/generate/shworker/msvc9/shworker.vcproj +++ /dev/null @@ -1,207 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/utils/mmsource/core/sourcehook/generate/shworker/shworker.cpp b/utils/mmsource/core/sourcehook/generate/shworker/shworker.cpp deleted file mode 100644 index 5e0047cea..000000000 --- a/utils/mmsource/core/sourcehook/generate/shworker/shworker.cpp +++ /dev/null @@ -1,767 +0,0 @@ -// SHWorker -// Inspired by "Hopter" that comes with FastDelegate (http://www.codeproject.com/cpp/FastDelegate.asp) -// Much more powerful (and ugly) though - -/* - - INPUT FILE DIRECTIVES - - $a is the first additional argument, $b the second, ... - - --- - ITERATION - - @[variable,min,max:code|separator@] - - variable: this will be replaced in code by its current value. - vars are always $ and a number. - min: first value to be used for variable - max: last value to be used for variable - code: the code that will be inserted on each iteration. - separator: optional. this will be inserted between iterations. - If you don't use a separator, you may leave out the | - IMPORTANT: iterations will only be performed if max >= min - - --- ARITHMETIC EXPRESSION - - @(expr) - - expr may contain: - variables - constants - operators (currently only + and * are supported) - - --- CONDITION - - @[expr operator expr:code@] - - Example: @[$1!=0:hello@] - - Currently only != and == are supported operators. - - - Yes, error handling in here is weird, some stuff uses return values, other code uses exceptions. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include "stdio.h" - -#ifdef __linux__ -# define stricmp strcasecmp -#endif - -// Ensure that the template version is being used! -#ifdef min -#undef min -#endif - -using namespace std; - -extern int action_hopter(int numargs, const char *filenamein, const char *filenameout); - -typedef map varmap; - -struct MyError -{ - const char *m_desc; - - MyError(const char *desc) : m_desc(desc) - { - } - - void Print() - { - cout << m_desc << endl; - } -}; - -struct SyntaxError : MyError -{ - SyntaxError() : MyError("Syntax error in expression") - { - } -}; -struct OtherError : MyError -{ - OtherError() : MyError("WTF") - { - } -}; - -void trim_string(std::string &str) -{ - size_t first = str.find_first_not_of(" \t\v\n\r"); - if (first == std::string::npos) - { - str.clear(); - return; - } - - size_t last = str.length(); - for (std::string::reverse_iterator riter = str.rbegin(); riter != str.rend(); ++riter) - { - char ch = *riter; - if (ch != ' ' && - ch != '\t' && - ch != '\v' && - ch != '\n' && - ch != '\r') - break; - --last; - } - str = str.substr(first, last - first); -} - -// unused -bool ExtractToken(std::string &strin, std::string &strout) -{ - trim_string(strin); - if (strin.begin() == strin.end()) - { - strout.clear(); - return false; - } - size_t first = strin.find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFHIJKLMNOPQRSTUVWXYZ_0123456789"); - if (first == 0) - { - if (strin.size() > 1 && strin.at(0) == '/' && strin.at(1) == '/') - { - // One-line comment, find its end - first = strin.find('\n') + 1; - } - else if (strin.size() > 1 && strin.at(0) == '/' && strin.at(1) == '*') - { - // Multi-line comment, find its end - first = strin.find("*/") + 2; - } - strin = strin.substr(1); - strout.clear(); - return true; - } - strout = strin.substr(0, first); - strin = strin.substr(first); - return true; -} - -// Returns the number of occurencies replaced -int DoReplace(string &str, const string &what, const string &with) -{ - int cnt=0; - size_t where = str.find(what); - - while (where != string::npos) - { - str.replace(where, what.size(), with); - ++cnt; - where = str.find(what, where); - } - return cnt; -} - -int DoReplace(string &str, const char *what, const char *with) -{ - int cnt=0; - size_t where = str.find(what); - size_t whatsize = strlen(what); - while (where != string::npos) - { - str.replace(where, whatsize, with); - ++cnt; - where = str.find(what, where); - } - return cnt; -} - - -class ExprParser -{ - // grammar: - /* - expr -> expr + term { do_add } - | expr - term { do_sub } - | term - - term -> term * factor { do_mul } - | term / factor { do_div } - | term % factor { do_mod } - - factor -> (expr) - | numeric constant { push } - - - equivalent to: - - expr -> term moreterms - moreterms -> + term { do_add } moreterms - moreterms -> - term { do_sub } moreterms - moreterms -> epsilon - - term -> factor morefactors - morefactors -> * factor { do_mul } morefactors - morefactors -> / factor { do_div } morefactors - morefactors -> % factor { do_mod } morefactors - morefactors -> epsilon - - factor -> (expr) - factor -> numeric constant { push } - - */ - - string::const_iterator m_begin; - string::const_iterator m_end; - string::const_iterator m_iter; - - int m_lookahead; - int m_tokenval; - - stack m_stack; - static const int DONE = 256; - static const int NUM = 257; - - int lexan() - { - while (1) - { - if (m_iter == m_end) - return DONE; - - int t = *m_iter++; - - if (t == ' ' || t == '\t') - ; // Remove whitespace - else if (isdigit(t)) - { - --m_iter; - - m_tokenval = 0; - while (m_iter != m_end && isdigit(*m_iter)) - { - m_tokenval *= 10; - m_tokenval += *m_iter - '0'; - ++m_iter; - } - return NUM; - } - else - return t; - } - } - - void match(int t) - { - if (m_lookahead == t) - m_lookahead = lexan(); - else - throw SyntaxError(); - } - void factor() - { - switch (m_lookahead) - { - case '(': - match('('); expr(); match(')'); - break; - case NUM: - m_stack.push(m_tokenval); match(NUM); - break; - default: - throw SyntaxError(); - } - } - void term() - { - factor(); - while (1) - { - switch (m_lookahead) - { - case '*': - match('*'); factor(); do_mul(); - continue; - case '/': - match('/'); factor(); do_div(); - continue; - case '%': - match('%'); factor(); do_mod(); - continue; - default: - return; - } - - } - } - - void expr() - { - term(); - while (1) - { - switch (m_lookahead) - { - case '+': - match('+'); term(); do_add(); - continue; - case '-': - match('-'); term(); do_sub(); - continue; - default: - return; - } - } - } - - void do_add() - { - int a2 = m_stack.top(); m_stack.pop(); - int a1 = m_stack.top(); m_stack.pop(); - m_stack.push(a1 + a2); - } - - void do_sub() - { - int a2 = m_stack.top(); m_stack.pop(); - int a1 = m_stack.top(); m_stack.pop(); - m_stack.push(a1 - a2); - } - - void do_mul() - { - int a2 = m_stack.top(); m_stack.pop(); - int a1 = m_stack.top(); m_stack.pop(); - m_stack.push(a1 * a2); - } - - void do_div() - { - int a2 = m_stack.top(); m_stack.pop(); - int a1 = m_stack.top(); m_stack.pop(); - m_stack.push(a1 / a2); - } - - void do_mod() - { - int a2 = m_stack.top(); m_stack.pop(); - int a1 = m_stack.top(); m_stack.pop(); - m_stack.push(a1 % a2); - } - -public: - ExprParser(string::const_iterator begin, string::const_iterator end) : - m_begin(begin), m_end(end), m_iter(begin) - { - m_lookahead = lexan(); - expr(); - } - - operator int() - { - if (m_stack.size() != 1) - throw OtherError(); - - return m_stack.top(); - } -}; - -int parse_expr(string::const_iterator begin, string::const_iterator end) -{ - return ExprParser(begin, end); -} - -size_t find_first_directive(const string &buf, size_t begin=0) -{ - for (;;) - { - if (begin >= buf.size()) - return string::npos; - - size_t firstdirpos = buf.find('@', begin); - if (firstdirpos == string::npos) - return firstdirpos; - - if (buf.size() > firstdirpos+1) - { - if (buf[firstdirpos+1] == '[' || buf[firstdirpos+1] == '(') - return firstdirpos; - } - begin = firstdirpos+1; - } -} - -// buf begins with a section. Find its end! -size_t find_section_end(const string &buf) -{ - int starttype = buf[1]; - int endtype = (buf[1] == '(') ? ')' : ']'; - - int nestlevel = 0; - - if (starttype == '(') - { - for (string::const_iterator iter = buf.begin(); iter != buf.end(); ++iter) - { - if (*iter == starttype) - ++nestlevel; - if (*iter == endtype) - { - if (--nestlevel == 0) - return iter - buf.begin() + 1; - } - } - return string::npos; - } - else if (starttype == '[') - { - int lastchar = 0; - for (string::const_iterator iter = buf.begin(); iter != buf.end(); ++iter) - { - if (lastchar == '@' && *iter == starttype) - ++nestlevel; - if (lastchar == '@' && *iter == endtype) - { - if (--nestlevel == 0) - return iter - buf.begin() + 1; - } - lastchar = *iter; - } - return string::npos; - } - - return string::npos; -} - -// replaces variables and additional arguments -void replace_vars(string &buf, int argc, int *argv, const varmap &vars) -{ - char varname[] = "$ "; - char value[32]; - - for (int i = 0; i < argc; ++i) - { - varname[1] = 'a' + i; - sprintf(value, "%d", argv[i]); - DoReplace(buf, varname, value); - } - - for (varmap::const_iterator iter = vars.begin(); iter != vars.end(); ++iter) - { - varname[1] = '0' + iter->first; - sprintf(value, "%d", iter->second); - DoReplace(buf, varname, value); - } -} - -// do_input -// params: -// argc: number of additional arguments -// argv: additional arguments -// outfile: output file -// buf: string to be processed. IMPORTANT: buf is modified! -// curvars: variables buffer. -// retval: -// 0 on success, non-zero on error - -int do_input(int argc, int *argv, ofstream &outfile, string &buf, varmap &curvars) -{ - for (;;) - { - // Find the next directive. - size_t firstdirpos = find_first_directive(buf); - - // Output everything that came before, and remove it from buf - outfile << buf.substr(0, firstdirpos); - if (firstdirpos == string::npos) - return 0; - buf = buf.substr(firstdirpos); - - // Now find the matching end. - size_t sectionend = find_section_end(buf); - if (sectionend == string::npos) - { - cout << "ERROR: Section not closed!" << endl; - return 1; - } - - // Place the section in its own buffer and remove it from the input string. - string sect(buf.begin(), buf.begin() + sectionend); - buf = buf.substr(sectionend); - - // CASE1: Arithmetic expression - if (sect[1] == '(') - { - replace_vars(sect, argc, argv, curvars); - outfile << parse_expr(sect.begin()+1, sect.end()); - } - else if (sect[1] == '[') - { - int is_iter = 0; // 0 -> no; 1 -> maybe (only used in check); 2 -> yes - char lastchar = 0; - // This could be an iteration OR a conditional thing. - // Pretty braindead check: iterations begin with a variable, then a comma. - for (string::iterator iter = sect.begin() + 2; iter != sect.end(); ++iter) - { - if (*iter == ' ' || *iter == '\t') - ; - else if (is_iter == 0 && lastchar == '$' && isdigit(*iter)) - is_iter = 1; - else if (is_iter == 1 && *iter == ',') - { - is_iter = 2; - break; - } - else if (*iter == '$') - ; - else - break; - lastchar = *iter; - } - if (is_iter == 2) - { - // CASE2: iteration - // Looks like: @[var,min,max:code|sep@] - // Replace known variables / additional arguments - replace_vars(sect, argc, argv, curvars); - - // get the parts! - string varname; - int varnum; - int expr_min; - int expr_max; - - // varname - size_t comma = sect.find(','); - if (comma == string::npos) - { - cout << "Invalid iteration syntax" << endl; - return 1; - } - varname.assign(sect.begin() + 2, sect.begin() + comma); - trim_string(varname); - if (varname.size() != 2 || varname[0] != '$' || !isdigit(varname[1])) - { - cout << "Invalid variable name" << endl; - return 1; - } - varnum = varname[1] - '0'; - - // min - ++comma; - size_t nextcomma = sect.find(',', comma); - if (nextcomma == string::npos) - { - cout << "Invalid iteration syntax" << endl; - return 1; - } - expr_min = parse_expr(sect.begin() + comma, sect.begin() + nextcomma); - - // max - comma = nextcomma + 1; - nextcomma = sect.find(':', comma); - if (nextcomma == string::npos) - { - cout << "Invalid iteration syntax" << endl; - return 1; - } - - expr_max = parse_expr(sect.begin() + comma, sect.begin() + nextcomma); - - // separator - size_t sepbegin = sect.find('|'); - size_t sepend = string::npos; - if (sepbegin != string::npos && sepbegin < nextcomma) - { - // There's a separator! - ++sepbegin; - sepend = nextcomma; - } - else - sepbegin = string::npos; - - - ++nextcomma; // nextcomma is now where code begins! - - size_t codeend = sect.size() - 2; - - // Check whether the var is already taken - if (curvars.find(varnum) != curvars.end()) - { - cout << "Variable $" << varnum << "already taken!" << endl; - return 1; - } - - // Do iterations!! - for (int i = expr_min; i <= expr_max; ++i) - { - curvars[varnum] = i; - - string code(sect.begin() + nextcomma, sect.begin() + codeend); - replace_vars(code, argc, argv, curvars); - - // Feed it through the input routine (RECURSE!!!!!! YEAH!) - do_input(argc, argv, outfile, code, curvars); - - // Add separator if required - if (sepbegin != string::npos && i != expr_max) - { - string tmp(sect.begin() + sepbegin, sect.begin() + sepend); - do_input(argc, argv, outfile, tmp, curvars); - } - } - // Remove the var! - curvars.erase(varnum); - } - else - { - // CASE3: conditional thing. - // Looks like: @[expr1 operator expr2:code@] - - // Find the operator position - - enum OP_TYPE - { - OP_EQ, - OP_NEQ - }; - - OP_TYPE op; - size_t oppos = sect.find("=="); - if (oppos != string::npos) - op = OP_EQ; - else - { - oppos = sect.find("!="); - if (oppos != string::npos) - op = OP_NEQ; - else - { - cout << "Conditional expression without operator!?" << endl; - return 1; - } - } - size_t colon = sect.find(':'); - - // Now we've got everything. Parse first expr: - int expr1 = parse_expr(sect.begin() + 2, sect.begin() + oppos); - int expr2 = parse_expr(sect.begin() + oppos + 2, sect.begin() + colon); - if ((op == OP_EQ && expr1 == expr2) || - (op == OP_NEQ && expr1 != expr2)) - { - // Condition is true, process it! - // The text may still contain arithmetic exprs or other cond. exprs - // so send it through do_input - string tmp(sect.substr(colon+1, sect.size() - colon - 3)); - do_input(argc, argv, outfile, tmp, curvars); - } - } - } - else - { - cout << "WTF" << endl; - return 1; - } - } - - return 0; -} - - - -// action_iter -// params: -// filenamein: input file name -// filenameout: output file name -// argc: number of additional arguments -// argv: additional arguments -// retval: 0 on success, non-zero on error - -// Convert additional arguments -// Read whole input file to memory and open output file -// Pass to do_input() -int action_iter(const char *filenamein, const char *filenameout, int argc, const char *argv[]) -{ - // Convert additional arguments - const int MAX_ARGC = 10; - int converted_argv[MAX_ARGC]; - - int i; - for (i = 0; i < argc && i < MAX_ARGC; ++i) - converted_argv[i] = atoi(argv[i]); - - if (argc != i) - cout << "WARNING: Not all additional arguments processed!" << endl; - - - // Read whole input file to memory and open output file - ifstream fin(filenamein); - ofstream fout(filenameout); - - if (!fin) - { - cout << "Could not open file \"" << filenamein << "\"." << endl; - return 1; - } - if (!fout) - { - cout << "Could not open file \"" << filenameout << "\"." << endl; - return 1; - } - string input_str( - istreambuf_iterator (fin.rdbuf()), - istreambuf_iterator ()); - - - // Begin processing input - varmap vars; - try - { - return do_input(argc, converted_argv, fout, input_str, vars); - } - catch (MyError err) - { - err.Print(); - return 1; - } -} - -// MAIN -// Prints usage if required -// Calls action_hopter OR action_iter -int main(int argc, const char **argv) -{ - if (argc < 4) - { - cout << "Usage:" << endl << " shworker [iter/hopter] ..." << endl; - cout << " shworker iter filename.in filename.out [param1, param2, ...]" << endl; - cout << " shworker hopter filename.in filename.out [num-of-args]" << endl; - return 1; - } - - const char *action = argv[1]; - - if (stricmp(action, "hopter") == 0) - { - const char *filenamein = argv[2]; - const char *filenameout = argv[3]; - int argsnum = atoi(argv[4]); - - return action_hopter(argsnum, filenamein, filenameout); - } - else if (stricmp(action, "iter") == 0) - { - const char *filenamein = argv[2]; - const char *filenameout = argv[3]; - int additional_argc = argc - 4; - const char ** additional_argv = argv + 4; - return action_iter(filenamein, filenameout, additional_argc, additional_argv); - } - else - { - cout << "Unrecognized action: " << argv[1] << endl; - return 1; - } -} diff --git a/utils/mmsource/core/sourcehook/generate/sourcehook.hxx b/utils/mmsource/core/sourcehook/generate/sourcehook.hxx deleted file mode 100644 index e69dd4ea5..000000000 --- a/utils/mmsource/core/sourcehook/generate/sourcehook.hxx +++ /dev/null @@ -1,1566 +0,0 @@ -/* ======== SourceHook ======== -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko -* ============================ -*/ - -/** -* @file sourcehook.h -* @brief Contains the public SourceHook API -*/ - -#ifndef __SOURCEHOOK_H__ -#define __SOURCEHOOK_H__ - -// Interface revisions: -// 1 - Initial revision -// 2 - Changed to virtual functions for iterators and all queries -// 3 - Added "hook loop status variable" -// 4 - Reentrant -// 5 - New "V2" interface -#define SH_IFACE_VERSION 5 - -// Impl versions: -// ??? -// 4 - addition of hook ids and vp hooks (with them, AddHookNew and RemoveHookNew) -// This is not a SH_IFACE_VERSION change so that old plugins continue working! -// 5 - implementation of the new "V2" interface -#define SH_IMPL_VERSION 5 - -// Hookman version: -// 1 - standard -#define SH_HOOKMAN_VERSION 1 - -// Hookmanautogen versions -// 1 - initial -#define SH_HOOKMANAUTOGEN_IFACE_VERSION 1 -#define SH_HOOKMANAUTOGEN_IMPL_VERSION 1 - -// The value of SH_GLOB_SHPTR has to be a pointer to SourceHook::ISourceHook -// It's used in various macros -#ifndef SH_GLOB_SHPTR -#define SH_GLOB_SHPTR g_SHPtr -#endif - -// Used to identify the current plugin -#ifndef SH_GLOB_PLUGPTR -#define SH_GLOB_PLUGPTR g_PLID -#endif - -#ifdef SH_DEBUG -# include -# include - -# define SH_ASSERT(x, info) \ - do { \ - if (!(x)) \ - { \ - printf("SOURCEHOOK DEBUG ASSERTION FAILED: %s:%u(%s): %s: ", __FILE__, __LINE__, __FUNCTION__, #x); \ - printf info; \ - putchar('\n'); \ - abort(); \ - } \ - } while(0) - -#else -# define SH_ASSERT(x, info) -#endif - -// System -#define SH_SYS_WIN32 1 -#define SH_SYS_LINUX 2 -#define SH_SYS_APPLE 3 - -// Platform -#define SH_XP_POSIX 10 -#define SH_XP_WINAPI 20 - -#ifdef _WIN32 -# define SH_SYS SH_SYS_WIN32 -# define SH_XP SH_XP_WINAPI -#elif defined __linux__ -# define SH_SYS SH_SYS_LINUX -# define SH_XP SH_XP_POSIX -#elif defined __APPLE__ -# define SH_SYS SH_SYS_APPLE -# define SH_XP SH_XP_POSIX -#else -# error Unsupported system -#endif - -// Compiler -#define SH_COMP_GCC 1 -#define SH_COMP_MSVC 2 - -#ifdef _MSC_VER -# define SH_COMP SH_COMP_MSVC -#elif defined __GNUC__ -# define SH_COMP SH_COMP_GCC -#else -# error Unsupported compiler -#endif - -#if SH_COMP==SH_COMP_MSVC && _MSC_VER < 1500 -# define vsnprintf _vsnprintf -#endif - -#if SH_SYS != SH_SYS_WIN32 -# include -#endif - -#define SH_PTRSIZE sizeof(void*) - -#include "sh_memfuncinfo.h" -#include "FastDelegate.h" - -// Good old metamod! - -// Flags returned by a plugin's api function. -// NOTE: order is crucial, as greater/less comparisons are made. -enum META_RES -{ - MRES_IGNORED=0, // plugin didn't take any action - MRES_HANDLED, // plugin did something, but real function should still be called - MRES_OVERRIDE, // call real function, but use my return value - MRES_SUPERCEDE // skip real function; use my return value -}; - - -namespace SourceHook -{ - /** - * @brief Specifies the size (in bytes) for the internal buffer of vafmt(printf-like) function handlers - */ - const int STRBUF_LEN=4096; - - /** - * @brief An empty class. No inheritance used. Used for original-function-call hacks - */ - class EmptyClass - { - }; - - /** - * @brief Implicit cast. - */ - template - inline Out implicit_cast(In input) - { - return input; - } - - /** - * @brief A plugin typedef - * - * SourceHook doesn't really care what this is. As long as the ==, != and = operators work on it and every - * plugin has a unique identifier, everything is ok. - * It should also be possible to set it to 0. - */ - typedef int Plugin; - - - template class CallClass : public T - { - }; - typedef void ManualCallClass; - - /** - * @brief Describes the way a parameter/retval is passed. - */ - struct PassInfo - { - enum PassType - { - PassType_Unknown=0, /**< Unknown -- no extra info available */ - PassType_Basic, /**< Plain old register data (pointers, integers) */ - PassType_Float, /**< Floating point data */ - PassType_Object, /**< Object or structure */ - }; - - enum PassFlags - { - PassFlag_ByVal = (1<<0), /**< Passing by value */ - PassFlag_ByRef = (1<<1), /**< Passing by reference */ - PassFlag_ODtor = (1<<2), /**< Object has a destructor */ - PassFlag_OCtor = (1<<3), /**< Object has a normal non-trivial constructor */ - PassFlag_AssignOp = (1<<4), /**< Object has a non-trivial assignment operator */ - PassFlag_CCtor = (1<<5), /**< Object has a copy constructor (which takes const Object& as only parameter) */ - - // The following two flags are only relevant for byval return types. - // SH tries to auto-detect these - // If you want to override SH's auto-detection, pass them in yourself - PassFlag_RetMem = (1<<6), /**< Object is returned in memory (through hidden first param */ - PassFlag_RetReg = (1<<7) /**< Object is returned in EAX(:EDX) */ - }; - - size_t size; //!< Size of the data being passed - - // Extra info: - // (might be used in future versions for automatic hookfunc generation) - int type; //!< PassType value - unsigned int flags; //!< Pass/return flags - - struct V2Info - { - void *pNormalCtor; - void *pCopyCtor; - void *pDtor; - void *pAssignOperator; - }; - }; - - struct ProtoInfo - { - enum CallConvention - { - CallConv_Unknown, /**< Unknown -- no extra info available (0)*/ - CallConv_ThisCall, /**< This call (object pointer required) (1)*/ - CallConv_Cdecl, /**< C call (2)*/ - CallConv_StdCall, /**< Windows "stdcall" (3)*/ - - CallConv_HasVarArgs = (1<<16), /**< Has variable arguments */ - CallConv_HasVafmt = CallConv_HasVarArgs | (1<<17) /**< last params: const char*, ... */ - }; - - int numOfParams; //!< number of parameters - PassInfo retPassInfo; //!< PassInfo for the return value. size=0 -> no retval - const PassInfo *paramsPassInfo; //!< PassInfos for the parameters - - // paramsPassInfo[0] is basically a dummy parameter. - // However, paramsPassInfo[0].size stores the version of the ProtoInfo structure. - - // Extra info: - int convention; - - // Version2: - PassInfo::V2Info retPassInfo2; - const PassInfo::V2Info *paramsPassInfo2; - }; - - struct IHookManagerInfo; - - /** - * @brief Pointer to hook manager interface function - * - * The hook manager should store hi for later use if store==true. It should then call hi->SetInfo(...) if hi - * is non-null. The hook manager can return 0 for success or a non-zero value if it doesn't want to be used. - * - * @param hi A pointer to IHookManagerInfo - */ - typedef int (*HookManagerPubFunc)(bool store, IHookManagerInfo *hi); - - class ISHDelegate - { - public: - virtual bool IsEqual(ISHDelegate *pOtherDeleg) = 0; // pOtherDeleg is from the same plugin and hookman - virtual void DeleteThis() = 0; - }; - - struct IHookManagerInfo - { - virtual void SetInfo(int hookman_version, int vtbloffs, int vtblidx, - ProtoInfo *proto, void *hookfunc_vfnptr) = 0; - }; - - // I'm adding support for functions which return references. - - // How it works: - // SH_SETUPCALLS doesn't use plain rettype to store the temporary return values (plugin ret, orig ret, - // override ret) anymore; instead, it uses SourceHook::ReferenceCarrier::type - // this is typedefed to the original rettype normally, but if the rettype is a reference, it's a special class - // which stores the reference as a pointer, and implements constructors, operator= and a conversion operator. - // special cases were needed for getoverrideret / getorigret; these are implemented through the - // SourceHook::MacroRefHelpers structs. - // Furthermore, SetOverrideRet had to be changed a bit; see SourceHook::OverrideFunctor somewhere down in this file. - template struct ReferenceCarrier - { - typedef T type; - }; - - template struct ReferenceCarrier - { - class type - { - T *m_StoredRef; - public: - type() : m_StoredRef(NULL) - { - } - type(T& ref) : m_StoredRef(&ref) - { - } - - T& operator= (T& ref) - { - m_StoredRef = &ref; - return ref; - } - - operator T& () const - { - return *m_StoredRef; - } - }; - }; - - template struct ReferenceUtil - { - typedef T plain_type; - typedef T* pointer_type; - typedef T& reference_type; - }; - - template struct ReferenceUtil - { - typedef T plain_type; - typedef T* pointer_type; - typedef T& reference_type; - }; - - struct IHookContext - { - virtual ISHDelegate *GetNext() = 0; - virtual void *GetOverrideRetPtr() = 0; - virtual const void *GetOrigRetPtr() = 0; - virtual bool ShouldCallOrig() = 0; - }; - - /** - * @brief The main SourceHook interface - */ - class ISourceHook - { - public: - /** - * @brief Return interface version - */ - virtual int GetIfaceVersion() = 0; - - /** - * @brief Return implementation version - */ - virtual int GetImplVersion() = 0; - - /** - * @brief Modes for the new AddHook - */ - enum AddHookMode - { - Hook_Normal, - Hook_VP, - Hook_DVP - }; - - /** - * @brief Add a (VP) hook. - * - * @return non-zero hook id on success, 0 otherwise - * - * @param plug The unique identifier of the plugin that calls this function - * @param mode Can be either Hook_Normal or Hook_VP (vtable-wide hook) - * @param iface The interface pointer - * @param ifacesize The size of the class iface points to - * @param myHookMan A hook manager function that should be capable of handling the function - * @param handler A pointer to the hook handler something - * @param post Set to true if you want a post handler - */ - virtual int AddHook(Plugin plug, AddHookMode mode, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, - ISHDelegate *handler, bool post) = 0; - - // Source backwarts compat (only for normal hooks) - virtual bool RemoveHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, - ISHDelegate *handler, bool post) = 0; - - /** - * @brief Remove a hook by ID. - * - * @return true on success, false otherwise - * - * @param hookid The hook id (returned by AddHook) - */ - virtual bool RemoveHookByID(int hookid) = 0; - - /** - * @brief Pause a hook by ID. - * - * @return true on success, false otherwise - * - * @param hookid The hook id (returned by AddHook) - */ - virtual bool PauseHookByID(int hookid) = 0; - - /** - * @brief Unpause a hook by ID. - * - * @return true on success, false otherwise - * - * @param hookid The hook id (returned by AddHook) - */ - virtual bool UnpauseHookByID(int hookid) = 0; - - /** - * @brief Checks whether a plugin has (a) hook manager(s) that is/are currently used by other plugins - * - * @param plug The unique identifier of the plugin in question - */ - - virtual void SetRes(META_RES res) = 0; //!< Sets the meta result - virtual META_RES GetPrevRes() = 0; //!< Gets the meta result of the - //!< previously calledhandler - virtual META_RES GetStatus() = 0; //!< Gets the highest meta result - virtual const void *GetOrigRet() = 0; //!< Gets the original result. - //!< If not in post function, undefined - virtual const void *GetOverrideRet() = 0; //!< Gets the override result. - //!< If none is specified, NULL - virtual void *GetIfacePtr() = 0; //!< Gets the interface pointer - - virtual void *GetOverrideRetPtr() = 0; //!< Used for setting the override return value - - /** - * @brief Remove a hook manager. Auto-removes all hooks attached to it from plugin plug. - * - * @param plug The owner of the hook manager - * @param pubFunc The hook manager's info function - */ - virtual void RemoveHookManager(Plugin plug, HookManagerPubFunc pubFunc) = 0; - - // For SH_CALL: - - /** - * @brief Makes sure that hooks are going to be ignored on the next call of vfnptr - * - * @param plug The unique identifier of the plugin that calls this function - * @param vfnptr The virtual function pointer of the function in question - */ - virtual void SetIgnoreHooks(void *vfnptr) = 0; - - /** - * @brief Reverses SetIgnoreHooks' effect - * - * @param plug The unique identifier of the plugin that calls this function - * @param vfnptr The virtual function pointer of the function in question - */ - virtual void ResetIgnoreHooks(void *vfnptr) = 0; - - /** - * @brief Finds the original entry of a virtual function pointer - * - * @param vfnptr The virtual function pointer - * @return The original entry if the virtual function pointer has been patched; NULL otherwise. - */ - virtual void *GetOrigVfnPtrEntry(void *vfnptr) = 0; - - ////////////////////////////////////////////////////////////////////////// - - // For hook managers - - // Returns the current iface ptr - virtual void DoRecall() = 0; //!< Initiates a recall sequence - - /* - HOW RECALLS WORK: - - The problem: - Users want the ability to change parameters of the called function - from inside their handler. - The solution: - 1) Mark as "recall" - 2) Recall the function - 3) => SH's hook func gets called: - 4) The first iterator points at the first hook the last hookfunc didn't execute yet - 5) does all iteration and returns normally - 6) The user's handler returns immediately - 7) The hook func returns immediately as well - - Also note that the recalled hookfunc starts with the status the recalling hookfunc - ended with. The last handler (doing the recall) is also able to specify its own - META_RES. - */ - - /** - * @brief Set up the hook loop. - * - * @param statusPtr pointer to status variable - * @param prevResPtr pointer to previous result variable - * @param curResPtr pointer to current result variable - * @param ifacePtrPtr pointer to interface this pointer variable - * @param origRetPr pointer to original return value variable. NULL for void funcs - * @param overrideRetPtr pointer to override return value variable. NULL for void funcs - * - * @return Override Return Pointer the hookfunc should use (may differ from overrideRetPtr - * when the hook func is being called as part of a recall - */ - virtual IHookContext *SetupHookLoop(IHookManagerInfo *hi, void *vfnptr, void *thisptr, void **origCallAddr, - META_RES *statusPtr, META_RES *prevResPtr, META_RES *curResPtr, - const void *origRetPtr, void *overrideRetPtr) = 0; - - virtual void EndContext(IHookContext *pCtx) = 0; - }; - - - class IHookManagerAutoGen - { - public: - virtual int GetIfaceVersion() = 0; - virtual int GetImplVersion() = 0; - - virtual HookManagerPubFunc MakeHookMan(const ProtoInfo *proto, int vtbl_offs, int vtbl_idx) = 0; - virtual void ReleaseHookMan(HookManagerPubFunc pubFunc) = 0; - }; - - // For META_RESULT_ORIG_RET and META_RESULT_OVERRIDE_RET: - // These have to be able to return references. If T is a reference, the pointers returned - // from the SH_GLOB_SHPTR are pointers to instances of ReferenceCarrier::type. - template struct MacroRefHelpers - { - inline static const T* GetOrigRet(ISourceHook *shptr) - { - return reinterpret_cast(shptr->GetOrigRet()); - } - inline static const T* GetOverrideRet(ISourceHook *shptr) - { - return reinterpret_cast(shptr->GetOverrideRet()); - } - }; - - template struct MacroRefHelpers - { - inline static T* GetOrigRet(ISourceHook *shptr) - { - T &ref = *reinterpret_cast::type *>(shptr->GetOrigRet()); - return &ref; - } - inline static T* GetOverrideRet(ISourceHook *shptr) - { - T &ref = *reinterpret_cast::type *>(shptr->GetOverrideRet()); - return &ref; - } - }; - - template - void *GetOrigVfnPtrEntry(X *pInstance, MFP mfp, ISourceHook *pSH) - { - SourceHook::MemFuncInfo info = {true, -1, 0, 0}; - SourceHook::GetFuncInfo(pInstance, mfp, info); - - void *vfnptr = reinterpret_cast( - *reinterpret_cast(reinterpret_cast(pInstance) + info.thisptroffs + info.vtbloffs) + info.vtblindex); - - void *origentry = pSH->GetOrigVfnPtrEntry(vfnptr); - - return origentry ? origentry : *reinterpret_cast(vfnptr); - } - - template struct GetPassInfo - { - static const int type = 0; - static const unsigned int flags = PassInfo::PassFlag_ByVal; - }; - - template struct GetPassInfo - { - static const int type = 0; - static const unsigned int flags = PassInfo::PassFlag_ByRef; - }; -} - -/************************************************************************/ -/* High level interface */ -/************************************************************************/ -#define META_RESULT_STATUS SH_GLOB_SHPTR->GetStatus() -#define META_RESULT_PREVIOUS SH_GLOB_SHPTR->GetPrevRes() -#define META_RESULT_ORIG_RET(type) *SourceHook::MacroRefHelpers::GetOrigRet(SH_GLOB_SHPTR) -#define META_RESULT_OVERRIDE_RET(type) *SourceHook::MacroRefHelpers::GetOverrideRet(SH_GLOB_SHPTR) -#define META_IFACEPTR(type) reinterpret_cast(SH_GLOB_SHPTR->GetIfacePtr()) - -#define SET_META_RESULT(result) SH_GLOB_SHPTR->SetRes(result) -#define RETURN_META(result) do { SET_META_RESULT(result); return; } while(0) -#define RETURN_META_VALUE(result, value) do { SET_META_RESULT(result); return (value); } while(0) - - -template -SourceHook::CallClass *SH_GET_CALLCLASS(T *p) -{ - return static_cast< SourceHook::CallClass *>(p); -} -#define SH_RELEASE_CALLCLASS(p) - -#define SH_GET_MCALLCLASS(p, size) reinterpret_cast(p) - -// only call these from the hook handlers directly! - -#define MAKE_NOREF_VALUE(rettype) \ - *reinterpret_cast< ::SourceHook::ReferenceUtil::pointer_type >(0) - -// If a hook on a function which returns a reference does not want to specify a return value, -// it can use this macro. -// ONLY USE THIS WITH MRES_IGNORED AND MRES_HANDLED !!! -#define RETURN_META_NOREF(result, rettype) \ - RETURN_META_VALUE(result, MAKE_NOREF_VALUE(rettype)) - -// Why take a memfuncptr instead of iface and func when we have to deduce the iface anyway now? -// Well, without it, there'd be no way to specify which overloaded version we want in _VALUE - -// SourceHook::SetOverrideRet is defined later. -#define RETURN_META_NEWPARAMS(result, memfuncptr, newparams) \ - do { \ - SET_META_RESULT(result); \ - SH_GLOB_SHPTR->DoRecall(); \ - (SourceHook::RecallGetIface(SH_GLOB_SHPTR, memfuncptr)->*(memfuncptr)) newparams; \ - RETURN_META(MRES_SUPERCEDE); \ - } while (0) - -#define RETURN_META_VALUE_NEWPARAMS(result, value, memfuncptr, newparams) \ - do { \ - SET_META_RESULT(result); \ - SH_GLOB_SHPTR->DoRecall(); \ - if ((result) >= MRES_OVERRIDE) \ - { \ - /* meh, set the override result here because we don't get a chance to return */ \ - /* before continuing the hook loop through the recall */ \ - SourceHook::SetOverrideResult(memfuncptr)(SH_GLOB_SHPTR, value); \ - } \ - RETURN_META_VALUE(MRES_SUPERCEDE, \ - (SourceHook::RecallGetIface(SH_GLOB_SHPTR, memfuncptr)->*(memfuncptr)) newparams); \ - } while (0) - -// :TODO: thisptroffs in MNEWPARAMS ?? - -#if SH_COMP == SH_COMP_MSVC - -#define SOUREHOOK__MNEWPARAMS_PREPAREMFP(hookname) \ - union \ - { \ - SH_MFHCls(hookname)::ECMFP mfp; \ - void *addr; \ - } u; \ - u.addr = (*reinterpret_cast(reinterpret_cast(thisptr) + SH_MFHCls(hookname)::ms_MFI.vtbloffs))[ \ - SH_MFHCls(hookname)::ms_MFI.vtblindex]; - -#elif SH_COMP == SH_COMP_GCC - -#define SOUREHOOK__MNEWPARAMS_PREPAREMFP(hookname) \ - union \ - { \ - SH_MFHCls(hookname)::ECMFP mfp; \ - struct \ - { \ - void *addr; \ - intptr_t adjustor; \ - } s; \ - } u; \ - u.s.addr = (*reinterpret_cast(reinterpret_cast(thisptr) + SH_MFHCls(hookname)::ms_MFI.vtbloffs))[ \ - SH_MFHCls(hookname)::ms_MFI.vtblindex]; \ - u.s.adjustor = 0; - -#endif - -#define RETURN_META_MNEWPARAMS(result, hookname, newparams) \ - do { \ - SET_META_RESULT(result); \ - SH_GLOB_SHPTR->DoRecall(); \ - SourceHook::EmptyClass *thisptr = reinterpret_cast(SH_GLOB_SHPTR->GetIfacePtr()); \ - (thisptr->*(__SoureceHook_FHM_GetRecallMFP##hookname(thisptr))) newparams; \ - RETURN_META(MRES_SUPERCEDE); \ - } while (0) - -#define RETURN_META_VALUE_MNEWPARAMS(result, value, hookname, newparams) \ - do { \ - SET_META_RESULT(result); \ - SH_GLOB_SHPTR->DoRecall(); \ - if ((result) >= MRES_OVERRIDE) \ - { \ - /* see RETURN_META_VALUE_NEWPARAMS */ \ - __SoureceHook_FHM_SetOverrideResult##hookname(SH_GLOB_SHPTR, value); \ - } \ - SourceHook::EmptyClass *thisptr = reinterpret_cast(SH_GLOB_SHPTR->GetIfacePtr()); \ - RETURN_META_VALUE(MRES_SUPERCEDE, (thisptr->*(__SoureceHook_FHM_GetRecallMFP##hookname(thisptr))) newparams); \ - } while (0) - - -#define SH_MANUALHOOK_RECONFIGURE(hookname, pvtblindex, pvtbloffs, pthisptroffs) \ - __SourceHook_FHM_Reconfigure##hookname(pvtblindex, pvtbloffs, pthisptroffs) - -#define SH_GET_ORIG_VFNPTR_ENTRY(inst, mfp) (SourceHook::GetOrigVfnPtrEntry(inst, mfp, SH_GLOB_SHPTR)) - -// New ADD / REMOVE macros. -#define SH_STATIC(func) fastdelegate::MakeDelegate(func) -#define SH_MEMBER(inst, func) fastdelegate::MakeDelegate(inst, func) - -#define SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, handler, post) \ - __SourceHook_FHAdd##ifacetype##ifacefunc((void*)SourceHook::implicit_cast(ifaceptr), \ - SourceHook::ISourceHook::Hook_Normal, post, handler) - -#define SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, handler, post) \ - __SourceHook_FHRemove##ifacetype##ifacefunc((void*)SourceHook::implicit_cast(ifaceptr), \ - post, handler) - -#define SH_ADD_MANUALHOOK(hookname, ifaceptr, handler, post) \ - __SourceHook_FHMAdd##hookname(reinterpret_cast(ifaceptr), \ - SourceHook::ISourceHook::Hook_Normal, post, handler) - -#define SH_REMOVE_MANUALHOOK(hookname, ifaceptr, handler, post) \ - __SourceHook_FHMRemove##hookname(reinterpret_cast(ifaceptr), post, handler) - -#define SH_ADD_VPHOOK(ifacetype, ifacefunc, ifaceptr, handler, post) \ - __SourceHook_FHAdd##ifacetype##ifacefunc((void*)SourceHook::implicit_cast(ifaceptr), \ - SourceHook::ISourceHook::Hook_VP, post, handler) - -#define SH_ADD_DVPHOOK(ifacetype, ifacefunc, ifaceptr, handler, post) \ - __SourceHook_FHAdd##ifacetype##ifacefunc((void*)SourceHook::implicit_cast(ifaceptr), \ - SourceHook::ISourceHook::Hook_DVP, post, handler) - -#define SH_ADD_MANUALVPHOOK(hookname, ifaceptr, handler, post) \ - __SourceHook_FHMAdd##hookname(reinterpret_cast(ifaceptr), SourceHook::ISourceHook::Hook_VP, post, handler) - -#define SH_ADD_MANUALDVPHOOK(hookname, ifaceptr, handler, post) \ - __SourceHook_FHMAdd##hookname(reinterpret_cast(ifaceptr), SourceHook::ISourceHook::Hook_DVP, post, handler) - -#define SH_REMOVE_HOOK_ID(hookid) \ - (SH_GLOB_SHPTR->RemoveHookByID(hookid)) - -// Old macros -// !! These are now deprecated. Instead, use one of these: -// SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post) -// SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(inst, func), post) - -#define SH_ADD_HOOK_STATICFUNC(ifacetype, ifacefunc, ifaceptr, handler, post) \ - SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post) -#define SH_ADD_HOOK_MEMFUNC(ifacetype, ifacefunc, ifaceptr, handler_inst, handler_func, post) \ - SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(handler_inst, handler_func), post) - -// SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post) -// SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(inst, func), post) - -#define SH_REMOVE_HOOK_STATICFUNC(ifacetype, ifacefunc, ifaceptr, handler, post) \ - SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post) -#define SH_REMOVE_HOOK_MEMFUNC(ifacetype, ifacefunc, ifaceptr, handler_inst, handler_func, post) \ - SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(handler_inst, handler_func), post) - -// SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post) -// SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(inst, func), post) - -#define SH_ADD_MANUALHOOK_STATICFUNC(hookname, ifaceptr, handler, post) \ - SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post) -#define SH_ADD_MANUALHOOK_MEMFUNC(hookname, ifaceptr, handler_inst, handler_func, post) \ - SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(handler_inst, handler_func), post) - -// SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post) -// SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(inst, func), post) - -#define SH_REMOVE_MANUALHOOK_STATICFUNC(hookname, ifaceptr, handler, post) \ - SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post) -#define SH_REMOVE_MANUALHOOK_MEMFUNC(hookname, ifaceptr, handler_inst, handler_func, post) \ - SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(handler_inst, handler_func), post) - -#define SH_NOATTRIB - - - - -#if SH_COMP == SH_COMP_MSVC -# define SH_SETUP_MFP(mfp) \ - reinterpret_cast(&mfp)[0] = vfnptr_origentry; -#elif SH_COMP == SH_COMP_GCC -# define SH_SETUP_MFP(mfp) \ - reinterpret_cast(&mfp)[0] = vfnptr_origentry; \ - reinterpret_cast(&mfp)[1] = 0; -#else -# error Not supported yet. -#endif - -////////////////////////////////////////////////////////////////////////// -#define SH_FHCls(ift, iff, ov) __SourceHook_FHCls_##ift##iff##ov -#define SH_MFHCls(hookname) __SourceHook_MFHCls_##hookname - -#define SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr) \ - static int HookManPubFunc(bool store, ::SourceHook::IHookManagerInfo *hi) \ - { \ - using namespace ::SourceHook; \ - GetFuncInfo(funcptr, ms_MFI); \ - /* Verify interface version */ \ - if (SH_GLOB_SHPTR->GetIfaceVersion() != SH_IFACE_VERSION) \ - return 1; \ - if (SH_GLOB_SHPTR->GetImplVersion() < SH_IMPL_VERSION) \ - return 1; \ - if (store) \ - ms_HI = hi; \ - if (hi) \ - { \ - MemFuncInfo mfi = {true, -1, 0, 0}; \ - GetFuncInfo(&SH_FHCls(ifacetype,ifacefunc,overload)::Func, mfi); \ - hi->SetInfo(SH_HOOKMAN_VERSION, ms_MFI.vtbloffs, ms_MFI.vtblindex, &ms_Proto, \ - reinterpret_cast(reinterpret_cast(&ms_Inst) + mfi.vtbloffs)[mfi.vtblindex] ); \ - } \ - return 0; \ - } - -// It has to be possible to use the macros in namespaces -// -> So we need to access and extend the global SourceHook namespace -// We use a namespace alias for this -#define SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, funcptr) \ - struct SH_FHCls(ifacetype,ifacefunc,overload) \ - { \ - static SH_FHCls(ifacetype,ifacefunc,overload) ms_Inst; \ - static ::SourceHook::MemFuncInfo ms_MFI; \ - static ::SourceHook::IHookManagerInfo *ms_HI; \ - static ::SourceHook::ProtoInfo ms_Proto; \ - SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr) - -#define SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, funcptr) \ - }; \ - SH_FHCls(ifacetype,ifacefunc,overload) SH_FHCls(ifacetype,ifacefunc,overload)::ms_Inst; \ - ::SourceHook::MemFuncInfo SH_FHCls(ifacetype,ifacefunc,overload)::ms_MFI; \ - ::SourceHook::IHookManagerInfo *SH_FHCls(ifacetype,ifacefunc,overload)::ms_HI; \ - int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ - SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \ - { \ - using namespace ::SourceHook; \ - MemFuncInfo mfi = {true, -1, 0, 0}; \ - GetFuncInfo(funcptr, mfi); \ - if (mfi.thisptroffs < 0 || !mfi.isVirtual) \ - return false; /* No non-virtual functions / virtual inheritance supported */ \ - \ - return SH_GLOB_SHPTR->AddHook(SH_GLOB_PLUGPTR, mode, \ - iface, mfi.thisptroffs, SH_FHCls(ifacetype,ifacefunc,overload)::HookManPubFunc, \ - new SH_FHCls(ifacetype,ifacefunc,overload)::CMyDelegateImpl(handler), post); \ - } \ - bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ - SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \ - { \ - using namespace ::SourceHook; \ - MemFuncInfo mfi = {true, -1, 0, 0}; \ - GetFuncInfo(funcptr, mfi); \ - SH_FHCls(ifacetype,ifacefunc,overload)::CMyDelegateImpl tmp(handler); \ - return SH_GLOB_SHPTR->RemoveHook(SH_GLOB_PLUGPTR, iface, mfi.thisptroffs, \ - SH_FHCls(ifacetype,ifacefunc,overload)::HookManPubFunc, &tmp, post); \ - } \ - -#define SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, pvtbloffs, pvtblidx, pthisptroffs) \ - struct SH_MFHCls(hookname) \ - { \ - static SH_MFHCls(hookname) ms_Inst; \ - static ::SourceHook::MemFuncInfo ms_MFI; \ - static ::SourceHook::IHookManagerInfo *ms_HI; \ - static ::SourceHook::ProtoInfo ms_Proto; \ - \ - SH_MFHCls(hookname)() \ - { \ - ms_MFI.isVirtual = true; \ - ms_MFI.thisptroffs = pthisptroffs; \ - ms_MFI.vtblindex = pvtblidx; \ - ms_MFI.vtbloffs = pvtbloffs; \ - } \ - static int HookManPubFunc(bool store, ::SourceHook::IHookManagerInfo *hi) \ - { \ - using namespace ::SourceHook; \ - /* Verify interface version */ \ - if (SH_GLOB_SHPTR->GetIfaceVersion() != SH_IFACE_VERSION) \ - return 1; \ - if (SH_GLOB_SHPTR->GetImplVersion() < SH_IMPL_VERSION) \ - return 1; \ - if (store) \ - ms_HI = hi; \ - if (hi) \ - { \ - MemFuncInfo mfi = {true, -1, 0, 0}; \ - GetFuncInfo(&SH_MFHCls(hookname)::Func, mfi); \ - hi->SetInfo(SH_HOOKMAN_VERSION, ms_MFI.vtbloffs, ms_MFI.vtblindex, &ms_Proto, \ - reinterpret_cast(reinterpret_cast(&ms_Inst) + mfi.vtbloffs)[mfi.vtblindex] ); \ - } \ - return 0; \ - } - -#define SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, pvtbloffs, pvtblidx, pthisptroffs) \ - }; \ - SH_MFHCls(hookname) SH_MFHCls(hookname)::ms_Inst; \ - ::SourceHook::MemFuncInfo SH_MFHCls(hookname)::ms_MFI; \ - ::SourceHook::IHookManagerInfo *SH_MFHCls(hookname)::ms_HI; \ - int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ - SH_MFHCls(hookname)::FD handler) \ - { \ - return SH_GLOB_SHPTR->AddHook(SH_GLOB_PLUGPTR, mode, \ - iface, pthisptroffs, SH_MFHCls(hookname)::HookManPubFunc, \ - new SH_MFHCls(hookname)::CMyDelegateImpl(handler), post); \ - } \ - bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ - SH_MFHCls(hookname)::FD handler) \ - { \ - SH_MFHCls(hookname)::CMyDelegateImpl tmp(handler); \ - return SH_GLOB_SHPTR->RemoveHook(SH_GLOB_PLUGPTR, iface, pthisptroffs, \ - SH_MFHCls(hookname)::HookManPubFunc, &tmp, post); \ - } \ - SH_MFHCls(hookname)::ECMFP __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) \ - { \ - SOUREHOOK__MNEWPARAMS_PREPAREMFP(hookname); \ - return u.mfp; \ - } \ - SH_MFHCls(hookname)::CallEC __SoureceHook_FHM_SHCall##hookname(void *ptr) \ - { \ - SH_MFHCls(hookname)::ECMFP mfp; \ - void *vfnptr = reinterpret_cast( \ - *reinterpret_cast( (reinterpret_cast(ptr) + SH_MFHCls(hookname)::ms_MFI.thisptroffs + SH_MFHCls(hookname)::ms_MFI.vtbloffs) ) + SH_MFHCls(hookname)::ms_MFI.vtblindex); \ - /* patch mfp */ \ - *reinterpret_cast(&mfp) = *reinterpret_cast(vfnptr); \ - if (sizeof(mfp) == 2*sizeof(void*)) /* gcc */ \ - *(reinterpret_cast(&mfp) + 1) = 0; \ - return SH_MFHCls(hookname)::CallEC(reinterpret_cast< ::SourceHook::EmptyClass* >(ptr), mfp, vfnptr, SH_GLOB_SHPTR); \ - } \ - void __SourceHook_FHM_Reconfigure##hookname(int p_vtblindex, int p_vtbloffs, int p_thisptroffs) \ - { \ - SH_GLOB_SHPTR->RemoveHookManager(SH_GLOB_PLUGPTR, SH_MFHCls(hookname)::HookManPubFunc); \ - SH_MFHCls(hookname)::ms_MFI.thisptroffs = p_thisptroffs; \ - SH_MFHCls(hookname)::ms_MFI.vtblindex = p_vtblindex; \ - SH_MFHCls(hookname)::ms_MFI.vtbloffs = p_vtbloffs; \ - } - -#define SH_SETUPCALLS(rettype, paramtypes, params) \ - /* 1) Set up */ \ - using namespace ::SourceHook; \ - void *ourvfnptr = reinterpret_cast( \ - *reinterpret_cast(reinterpret_cast(this) + ms_MFI.vtbloffs) + ms_MFI.vtblindex); \ - void *vfnptr_origentry; \ - \ - META_RES status = MRES_IGNORED; \ - META_RES prev_res; \ - META_RES cur_res; \ - \ - typedef ReferenceCarrier< rettype >::type my_rettype; \ - my_rettype orig_ret; \ - my_rettype override_ret; \ - my_rettype plugin_ret; \ - IMyDelegate *iter; \ - IHookContext *pContext = SH_GLOB_SHPTR->SetupHookLoop(ms_HI, ourvfnptr, reinterpret_cast(this), \ - &vfnptr_origentry, &status, &prev_res, &cur_res, &orig_ret, &override_ret); - -#define SH_CALL_HOOKS(post, params) \ - prev_res = MRES_IGNORED; \ - while ( (iter = static_cast(pContext->GetNext())) ) \ - { \ - cur_res = MRES_IGNORED; \ - plugin_ret = iter->Call params; \ - prev_res = cur_res; \ - if (cur_res > status) \ - status = cur_res; \ - if (cur_res >= MRES_OVERRIDE) \ - *reinterpret_cast(pContext->GetOverrideRetPtr()) = plugin_ret; \ - } - -#define SH_CALL_ORIG(rettype, paramtypes, params) \ - if (status != MRES_SUPERCEDE && pContext->ShouldCallOrig()) \ - { \ - rettype (EmptyClass::*mfp)paramtypes; \ - SH_SETUP_MFP(mfp); \ - orig_ret = (reinterpret_cast(this)->*mfp)params; \ - } \ - else \ - orig_ret = override_ret; /* :TODO: ??? : use pContext->GetOverrideRetPtr() or not? */ - -#define SH_RETURN() \ - const my_rettype *retptr = reinterpret_cast( \ - (status >= MRES_OVERRIDE) ? pContext->GetOverrideRetPtr() : pContext->GetOrigRetPtr()); \ - SH_GLOB_SHPTR->EndContext(pContext); \ - return *retptr; - -#define SH_HANDLEFUNC(paramtypes, params, rettype) \ - SH_SETUPCALLS(rettype, paramtypes, params) \ - SH_CALL_HOOKS(pre, params) \ - SH_CALL_ORIG(rettype, paramtypes, params) \ - SH_CALL_HOOKS(post, params) \ - SH_RETURN() - -////////////////////////////////////////////////////////////////////////// -#define SH_SETUPCALLS_void(paramtypes, params) \ - /* 1) Set up */ \ - using namespace ::SourceHook; \ - void *ourvfnptr = reinterpret_cast( \ - *reinterpret_cast(reinterpret_cast(this) + ms_MFI.vtbloffs) + ms_MFI.vtblindex); \ - void *vfnptr_origentry; \ - \ - META_RES status = MRES_IGNORED; \ - META_RES prev_res; \ - META_RES cur_res; \ - \ - IMyDelegate *iter; \ - IHookContext *pContext = SH_GLOB_SHPTR->SetupHookLoop(ms_HI, ourvfnptr, reinterpret_cast(this), \ - &vfnptr_origentry, &status, &prev_res, &cur_res, NULL, NULL); - -#define SH_CALL_HOOKS_void(post, params) \ - prev_res = MRES_IGNORED; \ - while ( (iter = static_cast(pContext->GetNext())) ) \ - { \ - cur_res = MRES_IGNORED; \ - iter->Call params; \ - prev_res = cur_res; \ - if (cur_res > status) \ - status = cur_res; \ - } - -#define SH_CALL_ORIG_void(paramtypes, params) \ - if (status != MRES_SUPERCEDE && pContext->ShouldCallOrig()) \ - { \ - void (EmptyClass::*mfp)paramtypes; \ - SH_SETUP_MFP(mfp); \ - (reinterpret_cast(this)->*mfp)params; \ - } - -#define SH_RETURN_void() \ - SH_GLOB_SHPTR->EndContext(pContext); - -#define SH_HANDLEFUNC_void(paramtypes, params) \ - SH_SETUPCALLS_void(paramtypes, params) \ - SH_CALL_HOOKS_void(pre, params) \ - SH_CALL_ORIG_void(paramtypes, params) \ - SH_CALL_HOOKS_void(post, params) \ - SH_RETURN_void() - - -// Special vafmt handlers -// :TODO: what -#define SH_HANDLEFUNC_vafmt(paramtypes, params_orig, params_plug, rettype) \ - SH_SETUPCALLS(rettype, paramtypes, params_orig) \ - SH_CALL_HOOKS(pre, params_plug) \ - SH_CALL_ORIG(rettype, paramtypes, params_orig) \ - SH_CALL_HOOKS(post, params_plug) \ - SH_RETURN() - -#define SH_HANDLEFUNC_void_vafmt(paramtypes, params_orig, params_plug) \ - SH_SETUPCALLS_void(paramtypes, params_orig) \ - SH_CALL_HOOKS_void(pre, params_plug) \ - SH_CALL_ORIG_void(paramtypes, params_orig) \ - SH_CALL_HOOKS_void(post, params_plug) \ - SH_RETURN_void() - -////////////////////////////////////////////////////////////////////////// - -#define MAKE_DELEG(ret_type, params_decl, params_pass) \ - struct IMyDelegate : ::SourceHook::ISHDelegate { virtual ret_type Call params_decl = 0; }; \ - struct CMyDelegateImpl : IMyDelegate \ - { \ - FD m_Deleg; \ - CMyDelegateImpl(FD deleg) : m_Deleg(deleg) {} \ - ret_type Call params_decl { return m_Deleg params_pass; } \ - void DeleteThis() { delete this; } \ - bool IsEqual(ISHDelegate *pOtherDeleg) { return m_Deleg == static_cast(pOtherDeleg)->m_Deleg; } \ - }; - -#define MAKE_DELEG_void(params_decl, params_pass) \ - struct IMyDelegate : ::SourceHook::ISHDelegate { virtual void Call params_decl = 0; }; \ - struct CMyDelegateImpl : IMyDelegate \ - { \ - FD m_Deleg; \ - CMyDelegateImpl(FD deleg) : m_Deleg(deleg) {} \ - void Call params_decl { m_Deleg params_pass; } \ - void DeleteThis() { delete this; } \ - bool IsEqual(ISHDelegate *pOtherDeleg) { return m_Deleg == static_cast(pOtherDeleg)->m_Deleg; } \ - }; - -// GetPassInfo -> easier access. __SH_GPI generates a SourceHook::PassInfo instance. -#define __SH_GPI(tt) { sizeof(tt), ::SourceHook::GetPassInfo< tt >::type, ::SourceHook::GetPassInfo< tt >::flags } -// Extra pass info V2 -#define __SH_EPI { 0, 0, 0, 0 } - -#define __SH_VAFMT_SEQ(fmt, buf) \ - char buf[::SourceHook::STRBUF_LEN]; \ - va_list ap; \ - va_start(ap, fmt); \ - vsnprintf(buf, sizeof(buf), fmt, ap); \ - buf[sizeof(buf) - 1] = 0; \ - va_end(ap); - -// Helper for MANUALEXTERN. -# define SHINT_DECL_MANUALEXTERN_impl_value(hookname, rettype) \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); - -// Helpers for transforming X(__VA_ARGS__, Y) -> Y when __VA_ARGS__ is empty. -#define SHINT_COLLAPSE0(_T, ...) __VA_ARGS__ - -// -// MSVC will automatically remove a trailing comma if __VA_ARGS__ is empty. GCC requires using ## to do this. -// -#if defined(_MSC_VER) -# define SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, ...) \ - int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ - fastdelegate::FastDelegate handler); \ - bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ - fastdelegate::FastDelegate handler); - -# define SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, void, __VA_ARGS__) - -# define SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, __VA_ARGS__, const char *) - -# define SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, void, __VA_ARGS__, const char *) - -// Helpers for MANUALEXTERN. -# define SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, ...) \ - int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ - fastdelegate::FastDelegate handler); \ - bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ - fastdelegate::FastDelegate handler); \ - void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); - -# define SHINT_DECL_MANUALEXTERN_impl(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, __VA_ARGS__) \ - rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(__VA_ARGS__); \ - SourceHook::ExecutableClassN __SoureceHook_FHM_SHCall##hookname(void *ptr); - -# define SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, __VA_ARGS__, const char *) \ - rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(SHINT_COLLAPSE0(void, __VA_ARGS__, const char *, ...)); \ - SourceHook::ExecutableClassN __SoureceHook_FHM_SHCall##hookname(void *ptr); - -# define SH_DECL_MANUALEXTERN(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl(hookname, rettype, __VA_ARGS__) \ - SHINT_DECL_MANUALEXTERN_impl_value(hookname, rettype) - -# define SH_DECL_MANUALEXTERN_void(hookname, ...) \ - SHINT_DECL_MANUALEXTERN_impl(hookname, void, __VA_ARGS__) - -# define SH_DECL_MANUALEXTERN_void_vafmt(hookname, ...) \ - SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, void, __VA_ARGS__) - -# define SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, rettype, __VA_ARGS__) \ - SHINT_DECL_MANUALEXTERN_impl_value(hookname, rettype) - -// -// GCC Implementation. -// -#else -# define SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, ...) \ - int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ - fastdelegate::FastDelegate handler); \ - bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ - fastdelegate::FastDelegate handler); - -# define SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, void, ##__VA_ARGS__) - -# define SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, ##__VA_ARGS__, const char *) - -# define SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, void, ##__VA_ARGS__, const char *) - -// Helpers for MANUALEXTERN. -# define SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, ...) \ - int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ - fastdelegate::FastDelegate handler); \ - bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ - fastdelegate::FastDelegate handler); \ - void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); - -# define SHINT_DECL_MANUALEXTERN_impl(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, ##__VA_ARGS__) \ - rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(__VA_ARGS__); \ - SourceHook::ExecutableClassN __SoureceHook_FHM_SHCall##hookname(void *ptr); - -# define SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, ##__VA_ARGS__, const char *) \ - rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(SHINT_COLLAPSE0(void, ##__VA_ARGS__, const char *, ...)); \ - SourceHook::ExecutableClassN __SoureceHook_FHM_SHCall##hookname(void *ptr); - -# define SH_DECL_MANUALEXTERN(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl(hookname, rettype, ##__VA_ARGS__) \ - SHINT_DECL_MANUALEXTERN_impl_value(hookname, rettype) - -# define SH_DECL_MANUALEXTERN_void(hookname, ...) \ - SHINT_DECL_MANUALEXTERN_impl(hookname, void, ##__VA_ARGS__) - -# define SH_DECL_MANUALEXTERN_void_vafmt(hookname, ...) \ - SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, void, ##__VA_ARGS__) - -# define SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, rettype, ##__VA_ARGS__) \ - SHINT_DECL_MANUALEXTERN_impl_value(hookname, rettype) - -#endif - -// Compatibility wrappers around modern variadic macros. -@[$1,0,$a: -// ********* Support for $1 arguments ********* -#define SH_DECL_HOOK$1(ifacetype, ifacefunc, attr, overload, rettype@[$2,1,$1:, param$2@]) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (@[$2,1,$1|, :param$2 p$2@]), (@[$2,1,$1|, :p$2@])); \ - virtual rettype Func(@[$2,1,$1|, :param$2 p$2@]) \ - { SH_HANDLEFUNC((@[$2,1,$1|, :param$2@]), (@[$2,1,$1|, :p$2@]), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}@[$2,1,$1:, __SH_GPI(param$2)@] }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI@[$2,1,$1:, __SH_EPI@] }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { $1, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN$1(ifacetype, ifacefunc, attr, overload, rettype@[$2,1,$1:, param$2@]) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype@[$2,1,$1|:, param$2@]) - -#define SH_DECL_HOOK$1_void(ifacetype, ifacefunc, attr, overload@[$2,1,$1:, param$2@]) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((@[$2,1,$1|, :param$2 p$2@]), (@[$2,1,$1|, :p$2@])); \ - virtual void Func(@[$2,1,$1|, :param$2 p$2@]) \ - { SH_HANDLEFUNC_void((@[$2,1,$1|, :param$2@]), (@[$2,1,$1|, :p$2@])); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}@[$2,1,$1:,__SH_GPI(param$2)@] }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI@[$2,1,$1:, __SH_EPI@] }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { $1, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN$1_void(ifacetype, ifacefunc, attr, overload@[$2,1,$1:, param$2@]) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload@[$1!=0:, @]@[$2,1,$1|, :param$2@]) - -#define SH_DECL_HOOK$1_vafmt(ifacetype, ifacefunc, attr, overload, rettype@[$2,1,$1:, param$2@]) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (@[$2,1,$1|, :param$2 p$2@]@[$1!=0:, @]const char *px), (@[$2,1,$1|, :p$2@]@[$1!=0:, @]px)); \ - virtual rettype Func(@[$2,1,$1|, :param$2 p$2@] @[$1!=0:, @]const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((@[$2,1,$1:param$2, @]const char *, ...), (@[$2,1,$1|, :p$2@]@[$1!=0:, @]"%s", buf), (@[$2,1,$1|, :p$2@]@[$1!=0:, @]buf), rettype); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}@[$2,1,$1:, __SH_GPI(param$2)@] }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI@[$2,1,$1:, __SH_EPI@] }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { $1, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN$1_vafmt(ifacetype, ifacefunc, attr, overload, rettype@[$2,1,$1:, param$2@]) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype@[$1!=0:, @]@[$2,1,$1|, :param$2@]) - -#define SH_DECL_HOOK$1_void_vafmt(ifacetype, ifacefunc, attr, overload@[$2,1,$1:, param$2@]) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((@[$2,1,$1|, :param$2 p$2@]@[$1!=0:, @]const char *px), (@[$2,1,$1|, :p$2@]@[$1!=0:, @]px)); \ - virtual void Func(@[$2,1,$1|, :param$2 p$2@]@[$1!=0:, @]const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((@[$2,1,$1:param$2, @]const char *, ...), (@[$2,1,$1|, :p$2@]@[$1!=0:, @]"%s", buf), (@[$2,1,$1|, :p$2@]@[$1!=0:, @]buf)); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}@[$2,1,$1:, __SH_GPI(param$2)@] }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI@[$2,1,$1:, __SH_EPI@] }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { $1, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN$1_void_vafmt(ifacetype, ifacefunc, attr, overload@[$2,1,$1:, param$2@]) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload@[$1!=0:, @]@[$2,1,$1|, :param$2@]) - -#define SH_DECL_MANUALHOOK$1(hookname, vtblidx, vtbloffs, thisptroffs, rettype@[$2,1,$1:, param$2@]) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (@[$2,1,$1|, :param$2 p$2@]), (@[$2,1,$1|, :p$2@])); \ - virtual rettype Func(@[$2,1,$1|, :param$2 p$2@]) \ - { SH_HANDLEFUNC((@[$2,1,$1|, :param$2@]), (@[$2,1,$1|, :p$2@]), rettype); } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(@[$2,1,$1|, :param$2@]); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype@[$2,1,$1:, param$2@] > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}@[$2,1,$1:, __SH_GPI(param$2)@] }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI@[$2,1,$1:, __SH_EPI@] }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { $1, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN$1(hookname, rettype@[$2,1,$1:, param$2@]) \ - SH_DECL_MANUALEXTERN(hookname, rettype@[$2,1,$1|:, param$2@]) - -#define SH_DECL_MANUALHOOK$1_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype@[$2,1,$1:, param$2@]) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (@[$2,1,$1:param$2 p$2, @]const char *px), (@[$2,1,$1:p$2, @]px)); \ - virtual rettype Func(@[$2,1,$1:param$2 p$2, @]const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((@[$2,1,$1:param$2, @]const char *, ...), (@[$2,1,$1|, :p$2@]@[$1!=0:, @]"%s", buf), (@[$2,1,$1|, :p$2@]@[$1!=0:, @]buf), rettype); \ - } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(@[$2,1,$1:param$2, @]const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype@[$2,1,$1:, param$2@], const char * > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}@[$2,1,$1:, __SH_GPI(param$2)@] }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI@[$2,1,$1:, __SH_EPI@] }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { $1, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN$1_vafmt(hookname, rettype@[$2,1,$1:, param$2@]) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype@[$1!=0:, @]@[$2,1,$1|, :param$2@]) - -#define SH_DECL_MANUALHOOK$1_void(hookname, vtblidx, vtbloffs, thisptroffs@[$2,1,$1:, param$2@]) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((@[$2,1,$1|, :param$2 p$2@]), (@[$2,1,$1|, :p$2@])); \ - virtual void Func(@[$2,1,$1|, :param$2 p$2@]) \ - { SH_HANDLEFUNC_void((@[$2,1,$1|, :param$2@]), (@[$2,1,$1|, :p$2@])); } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(@[$2,1,$1|, :param$2@]); \ - typedef SourceHook::ExecutableClassN CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}@[$2,1,$1:, __SH_GPI(param$2)@] }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI@[$2,1,$1:, __SH_EPI@] }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { $1, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN$1_void(hookname@[$2,1,$1:, param$2@]) \ - SH_DECL_MANUALEXTERN_void(hookname@[$1!=0:, @]@[$2,1,$1|, :param$2@]) - -#define SH_DECL_MANUALHOOK$1_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs@[$2,1,$1:, param$2@]) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((@[$2,1,$1:param$2 p$2, @]const char *px), (@[$2,1,$1:p$2, @]px)); \ - virtual void Func(@[$2,1,$1:param$2 p$2, @]const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((@[$2,1,$1:param$2, @]const char *, ...), (@[$2,1,$1|, :p$2@]@[$1!=0:, @]"%s", buf), (@[$2,1,$1|, :p$2@]@[$1!=0:, @]buf)); \ - } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(@[$2,1,$1:param$2, @]const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void@[$2,1,$1:, param$2@], const char * > CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}@[$2,1,$1:, __SH_GPI(param$2)@] }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI@[$2,1,$1:, __SH_EPI@] }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { $1, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN$1_void_vafmt(hookname@[$2,1,$1:, param$2@]) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname@[$1!=0:, @]@[$2,1,$1|, :param$2@]) - -@] - - -////////////////////////////////////////////////////////////////////////// -// SH_CALL - -namespace SourceHook -{ - template - class ExecutableClassN - { - ObjType *m_ThisPtr; - void *m_VfnPtr; - MFPType m_MFP; - ISourceHook *m_pSH; - public: - ExecutableClassN(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) - : m_ThisPtr(tp), - m_VfnPtr(vp), - m_MFP(mfp), - m_pSH(pSH) - { } - - RetType operator()(Params... params) const { - using namespace ::SourceHook; - m_pSH->SetIgnoreHooks(m_VfnPtr); - RetType tmpret = (m_ThisPtr->*m_MFP)(params...); - m_pSH->ResetIgnoreHooks(m_VfnPtr); - return tmpret; - } - - template - RetType operator()(Params... params, MoreParams... more) const { - using namespace ::SourceHook; - m_pSH->SetIgnoreHooks(m_VfnPtr); - RetType tmpret = (m_ThisPtr->*m_MFP)(params..., more...); - m_pSH->ResetIgnoreHooks(m_VfnPtr); - return tmpret; - } - }; - - template - class ExecutableClassN - { - ObjType *m_ThisPtr; - void *m_VfnPtr; - MFPType m_MFP; - ISourceHook *m_pSH; - public: - ExecutableClassN(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) - : m_ThisPtr(tp), - m_VfnPtr(vp), - m_MFP(mfp), - m_pSH(pSH) - { } - - void operator()(Params... params) const { - using namespace ::SourceHook; - m_pSH->SetIgnoreHooks(m_VfnPtr); - (m_ThisPtr->*m_MFP)(params...); - m_pSH->ResetIgnoreHooks(m_VfnPtr); - } - - template - void operator()(Params... params, MoreParams... more) const { - using namespace ::SourceHook; - m_pSH->SetIgnoreHooks(m_VfnPtr); - (m_ThisPtr->*m_MFP)(params..., more...); - m_pSH->ResetIgnoreHooks(m_VfnPtr); - } - }; -} - -#define SH__CALL_GET_VFNPTR_NORMAL \ - using namespace ::SourceHook; \ - MemFuncInfo mfi = {true, -1, 0, 0}; \ - GetFuncInfo(ptr, mfp, mfi); \ - void *vfnptr = reinterpret_cast( \ - *reinterpret_cast(reinterpret_cast(ptr) + mfi.thisptroffs + mfi.vtbloffs) + mfi.vtblindex); - -#define SH__CALL_GET_VFNPTR_MANUAL \ - using namespace ::SourceHook; \ - void *vfnptr = reinterpret_cast( \ - *reinterpret_cast( (reinterpret_cast(ptr) + thisptroffs + vtbloffs) ) + vtblidx); \ - /* patch mfp */ \ - *reinterpret_cast(&mfp) = *reinterpret_cast(vfnptr); - -// SH_CALL needs to deduce the return type -> it uses templates and function overloading -// That's why SH_CALL takes two parameters: "mfp2" of type RetType(X::*mfp)(params), and "mfp" of type MFP -// The only purpose of the mfp2 parameter is to extract the return type - -template -SourceHook::ExecutableClassN -SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params...), SourceHook::ISourceHook *shptr) -{ - SH__CALL_GET_VFNPTR_NORMAL - return SourceHook::ExecutableClassN(ptr, mfp, vfnptr, shptr); -} - -template -SourceHook::ExecutableClassN -SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params..., ...), SourceHook::ISourceHook *shptr) -{ - SH__CALL_GET_VFNPTR_NORMAL - return SourceHook::ExecutableClassN(ptr, mfp, vfnptr, shptr); -} - -template -SourceHook::ExecutableClassN -SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params...)const, SourceHook::ISourceHook *shptr) -{ - SH__CALL_GET_VFNPTR_NORMAL - return SourceHook::ExecutableClassN(ptr, mfp, vfnptr, shptr); -} - -template -SourceHook::ExecutableClassN -SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params..., ...)const, SourceHook::ISourceHook *shptr) -{ - SH__CALL_GET_VFNPTR_NORMAL - return SourceHook::ExecutableClassN(ptr, mfp, vfnptr, shptr); -} - -template -SourceHook::ExecutableClassN -SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params...), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) -{ - SH__CALL_GET_VFNPTR_MANUAL - return SourceHook::ExecutableClassN( - reinterpret_cast(ptr), mfp, vfnptr, shptr); -} - -template -SourceHook::ExecutableClassN -SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params..., ...), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) -{ - SH__CALL_GET_VFNPTR_MANUAL - return SourceHook::ExecutableClassN( - reinterpret_cast(ptr), mfp, vfnptr, shptr); -} - -#define SH_CALL(ptr, mfp) SH_CALL2((ptr), (mfp), (mfp), SH_GLOB_SHPTR) -#define SH_MCALL2(ptr, mfp, vtblidx, vtbloffs, thisptroffs) SH_MCALL3((ptr), (mfp), (mfp), (vtblidx), (vtbloffs), (thisptroffs), SH_GLOB_SHPTR) -#define SH_MCALL(ptr, mhookname) __SoureceHook_FHM_SHCall##mhookname(ptr) - -////////////////////////////////////////////////////////////////////////// -// SetOverrideRet and RecallGetIface for recalls -// These take a ISourceHook pointer instead of using SH_GLOB_SHPTR directly -// The reason is that the user may want to redefine SH_GLOB_SHPTR - then the macros -// (META_RETURN_VALUE_NEWPARAMS) should obey the new pointer. - -namespace SourceHook -{ - // SetOverrideResult used to be implemented like this: - // SetOverrideResult(shptr, memfuncptr, return); - // normally the compiler can deduce the return type from memfuncptr, but (at least msvc8) failed when it was a reference - // (it thought it was ambigous - the ref and non-ref type) - // so now SetOverrideResult(memfuncptr) deduces the ret type, and returns a functor which does the work - // new syntax: SetOverrideResult(memfuncptr)(shptr, return) - // This also allows us to create a special version for references which respects ReferenceCarrier. - - template struct OverrideFunctor - { - void operator()(ISourceHook *shptr, T res) - { - *reinterpret_cast(shptr->GetOverrideRetPtr()) = res; - } - }; - template struct OverrideFunctor - { - void operator()(ISourceHook *shptr, T &res) - { - // overrideretptr points to ReferenceCarrier - *reinterpret_cast::type *>(shptr->GetOverrideRetPtr()) = res; - } - }; - - // For manual hooks: - // The rettype is passed in manually - template - OverrideFunctor SetOverrideResult() - { - return OverrideFunctor(); - } - - template - OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Params...)) - { - return OverrideFunctor(); - } - - template - OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Params..., ...)) - { - return OverrideFunctor(); - } - - template - Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Params...)) - { - return reinterpret_cast(shptr->GetIfacePtr()); - } - - template - Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Params..., ...)) - { - return reinterpret_cast(shptr->GetIfacePtr()); - } -} - -#endif - // The pope is dead. -> :( diff --git a/utils/mmsource/core/sourcehook/sh_list.h b/utils/mmsource/core/sourcehook/sh_list.h deleted file mode 100644 index 21d57c03a..000000000 --- a/utils/mmsource/core/sourcehook/sh_list.h +++ /dev/null @@ -1,321 +0,0 @@ -/* ======== SourceMM ======== -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): David "BAILOPAN" Anderson -* ============================ -*/ - -#ifndef _INCLUDE_SMM_LIST_H -#define _INCLUDE_SMM_LIST_H - -#include -#include - -namespace SourceHook -{ - - //This class is from CSDM for AMX Mod X - /* - A circular, doubly-linked list with one sentinel node - - Empty: - m_Head = sentinel - m_Head->next = m_Head; - m_Head->prev = m_Head; - One element: - m_Head = sentinel - m_Head->next = node1 - m_Head->prev = node1 - node1->next = m_Head - node1->prev = m_Head - Two elements: - m_Head = sentinel - m_Head->next = node1 - m_Head->prev = node2 - node1->next = node2 - node1->prev = m_Head - node2->next = m_Head - node2->prev = node1 - */ - template - class List - { - public: - class iterator; - friend class iterator; - class ListNode - { - public: - ListNode(const T & o) : obj(o) { }; - ListNode() { }; - T obj; - ListNode *next; - ListNode *prev; - }; - private: - // Initializes the sentinel node. - // BAIL used malloc instead of new in order to bypass the need for a constructor. - ListNode *_Initialize() - { - ListNode *n = (ListNode *)malloc(sizeof(ListNode)); - n->next = n; - n->prev = n; - return n; - } - public: - List() : m_Head(_Initialize()), m_Size(0) - { - } - List(const List &src) : m_Head(_Initialize()), m_Size(0) - { - iterator iter; - for (iter=src.begin(); iter!=src.end(); iter++) - push_back( (*iter) ); - } - ~List() - { - clear(); - - // Don't forget to free the sentinel - if (m_Head) - { - free(m_Head); - m_Head = NULL; - } - } - void push_back(const T &obj) - { - ListNode *node = new ListNode(obj); - - node->prev = m_Head->prev; - node->next = m_Head; - m_Head->prev->next = node; - m_Head->prev = node; - - m_Size++; - } - - void push_front(const T &obj) - { - insert(begin(), obj); - } - - void push_sorted(const T &obj) - { - iterator iter; - for (iter = begin(); iter != end(); ++iter) - { - if (obj < *iter) - { - insert(iter, obj); - return; - } - } - push_back(obj); - } - - size_t size() const - { - return m_Size; - } - - void clear() - { - ListNode *node = m_Head->next; - ListNode *temp; - m_Head->next = m_Head; - m_Head->prev = m_Head; - - // Iterate through the nodes until we find g_Head (the sentinel) again - while (node != m_Head) - { - temp = node->next; - delete node; - node = temp; - } - m_Size = 0; - } - bool empty() const - { - return (m_Size == 0); - } - T & front() - { - return m_Head->next->obj; - } - T & back() - { - return m_Head->prev->obj; - } - private: - ListNode *m_Head; - size_t m_Size; - public: - class iterator - { - friend class List; - public: - iterator() - { - m_This = NULL; - } - iterator(const List &src) - { - m_This = src.m_Head; - } - iterator(ListNode *n) : m_This(n) - { - } - iterator(const iterator &where) - { - m_This = where.m_This; - } - //pre decrement - iterator & operator--() - { - if (m_This) - m_This = m_This->prev; - return *this; - } - //post decrement - iterator operator--(int) - { - iterator old(*this); - if (m_This) - m_This = m_This->prev; - return old; - } - - //pre increment - iterator & operator++() - { - if (m_This) - m_This = m_This->next; - return *this; - } - //post increment - iterator operator++(int) - { - iterator old(*this); - if (m_This) - m_This = m_This->next; - return old; - } - - const T & operator * () const - { - return m_This->obj; - } - T & operator * () - { - return m_This->obj; - } - - T * operator -> () - { - return &(m_This->obj); - } - const T * operator -> () const - { - return &(m_This->obj); - } - - bool operator != (const iterator &where) const - { - return (m_This != where.m_This); - } - bool operator ==(const iterator &where) const - { - return (m_This == where.m_This); - } - - operator bool() - { - return m_This != NULL; - } - private: - ListNode *m_This; - }; - public: - iterator begin() const - { - return iterator(m_Head->next); - } - iterator end() const - { - return iterator(m_Head); - } - iterator erase(iterator &where) - { - ListNode *pNode = where.m_This; - iterator iter(where); - iter++; - - - // Works for all cases: empty list, erasing first element, erasing tail, erasing in the middle... - pNode->prev->next = pNode->next; - pNode->next->prev = pNode->prev; - - delete pNode; - m_Size--; - - return iter; - } - - iterator insert(iterator where, const T &obj) - { - // Insert obj right before where - - ListNode *node = new ListNode(obj); - ListNode *pWhereNode = where.m_This; - - pWhereNode->prev->next = node; - node->prev = pWhereNode->prev; - pWhereNode->prev = node; - node->next = pWhereNode; - - m_Size++; - - return iterator(node); - } - - public: - void remove(const T & obj) - { - iterator b; - for (b=begin(); b!=end(); b++) - { - if ( (*b) == obj ) - { - erase( b ); - break; - } - } - } - template - iterator find(const U & equ) const - { - iterator iter; - for (iter=begin(); iter!=end(); iter++) - { - if ( (*iter) == equ ) - return iter; - } - return end(); - } - List & operator =(const List &src) - { - clear(); - iterator iter; - for (iter=src.begin(); iter!=src.end(); iter++) - push_back( (*iter) ); - return *this; - } - }; - -}; //NAMESPACE - -#endif //_INCLUDE_CSDM_LIST_H diff --git a/utils/mmsource/core/sourcehook/sh_memfuncinfo.h b/utils/mmsource/core/sourcehook/sh_memfuncinfo.h deleted file mode 100644 index f83bf69b2..000000000 --- a/utils/mmsource/core/sourcehook/sh_memfuncinfo.h +++ /dev/null @@ -1,327 +0,0 @@ -/* ======== SourceHook ======== -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko -* ============================ -*/ - -/** - * @brief This file provides a way for getting information about a member function. - * @file sh_memfuncinfo.h - */ - -#ifndef __SHINT_MEMFUNC_INFO_H__ -#define __SHINT_MEMFUNC_INFO_H__ - -namespace SourceHook -{ - - // Don Clugston: - // implicit_cast< > - // I believe this was originally going to be in the C++ standard but - // was left out by accident. It's even milder than static_cast. - // I use it instead of static_cast<> to emphasize that I'm not doing - // anything nasty. - // Usage is identical to static_cast<> - template - inline OutputClass implicit_cast(InputClass input){ - return input; - } - - - struct MemFuncInfo - { - bool isVirtual; // Is the function virtual? - int thisptroffs; // The this pointer the function expects to be called with - // If -1, you need to call the GetFuncInfo_GetThisPtr function - int vtblindex; // The function's index in the vtable (0-based, 1=second entry, 2=third entry, ...) - int vtbloffs; // The vtable pointer - }; - - // Ideas by Don Clugston. - // Check out his excellent paper: http://www.codeproject.com/cpp/FastDelegate.asp - - template struct MFI_Impl - { - template static inline void GetFuncInfo(MFP *mfp, MemFuncInfo &out) - { - static char weird_memfunc_pointer_exclamation_mark_arrow_error[N-1000]; - } - }; - -# if SH_COMP == SH_COMP_GCC - - template<> struct MFI_Impl<2*SH_PTRSIZE> // All of these have size==8/16 - { - struct GCC_MemFunPtr - { - union - { - void *funcadr; // always even - intptr_t vtable_index_plus1; // = vindex+1, always odd - }; - intptr_t delta; - }; - template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) - { - GCC_MemFunPtr *mfp_detail = (GCC_MemFunPtr*)&mfp; - out.thisptroffs = mfp_detail->delta; - if (mfp_detail->vtable_index_plus1 & 1) - { - out.vtblindex = (mfp_detail->vtable_index_plus1 - 1) / SH_PTRSIZE; - out.vtbloffs = 0; - out.isVirtual = true; - } - else - out.isVirtual = false; - } - }; - -# elif SH_COMP == SH_COMP_MSVC - - namespace - { - int MFI_GetVtblOffset(void *mfp) - { - unsigned char *addr = (unsigned char*)mfp; - if (*addr == 0xE9) // Jmp - { - // May or may not be! - // Check where it'd jump - addr += 5 /*size of the instruction*/ + *(unsigned long*)(addr + 1); - } - - // Check whether it's a virtual function call - // They look like this: - // 004125A0 8B 01 mov eax,dword ptr [ecx] - // 004125A2 FF 60 04 jmp dword ptr [eax+4] - // ==OR== - // 00411B80 8B 01 mov eax,dword ptr [ecx] - // 00411B82 FF A0 18 03 00 00 jmp dword ptr [eax+318h] - - // However, for vararg functions, they look like this: - // 0048F0B0 8B 44 24 04 mov eax,dword ptr [esp+4] - // 0048F0B4 8B 00 mov eax,dword ptr [eax] - // 0048F0B6 FF 60 08 jmp dword ptr [eax+8] - // ==OR== - // 0048F0B0 8B 44 24 04 mov eax,dword ptr [esp+4] - // 0048F0B4 8B 00 mov eax,dword ptr [eax] - // 00411B82 FF A0 18 03 00 00 jmp dword ptr [eax+318h] - - // With varargs, the this pointer is passed as if it was the first argument - - bool ok = false; - if (addr[0] == 0x8B && addr[1] == 0x44 && addr[2] == 0x24 && addr[3] == 0x04 && - addr[4] == 0x8B && addr[5] == 0x00) - { - addr += 6; - ok = true; - } - else if (addr[0] == 0x8B && addr[1] == 0x01) - { - addr += 2; - ok = true; - } - else if (addr[0] == 0x48 && addr[1] == 0x8B && addr[2] == 0x01) - { - addr += 3; - ok = true; - } - if (!ok) - return -1; - - if (*addr++ == 0xFF) - { - if (*addr == 0x60) - { - return *++addr / SH_PTRSIZE; - } - else if (*addr == 0xA0) - { - return *((unsigned int*)++addr) / SH_PTRSIZE; - } - else if (*addr == 0x20) - return 0; - else - return -1; - } - return -1; - } - } - - template<> struct MFI_Impl<1*SH_PTRSIZE> // simple ones - { - template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) - { - out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); - out.isVirtual = out.vtblindex >= 0 ? true : false; - out.thisptroffs = 0; - out.vtbloffs = 0; - } - }; - - template<> struct MFI_Impl<2*SH_PTRSIZE> // more complicated ones! - { - struct MSVC_MemFunPtr2 - { - void *funcadr; - int delta; - }; - template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) - { - out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); - out.isVirtual = out.vtblindex >= 0 ? true : false; - out.thisptroffs = reinterpret_cast(&mfp)->delta; - out.vtbloffs = 0; - } - }; - - // By Don Clugston, adapted - template<> struct MFI_Impl<3*SH_PTRSIZE> // WOW IT"S GETTING BIGGER OMGOMOGMG - { - class __single_inheritance GenericClass; - class GenericClass {}; - - struct MicrosoftVirtualMFP { - void (GenericClass::*codeptr)(); // points to the actual member function - int delta; // #bytes to be added to the 'this' pointer - int vtable_index; // or 0 if no virtual inheritance - }; - - struct GenericVirtualClass : virtual public GenericClass - { - typedef GenericVirtualClass * (GenericVirtualClass::*ProbePtrType)(); - GenericVirtualClass * GetThis() { return this; } - }; - - template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) - { - out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); - out.isVirtual = out.vtblindex >= 0 ? true : false; - // This pointer - /* - union { - MFP func; - GenericClass* (T::*ProbeFunc)(); - MicrosoftVirtualMFP s; - } u; - u.func = mfp; - union { - GenericVirtualClass::ProbePtrType virtfunc; - MicrosoftVirtualMFP s; - } u2; - - // Check that the horrible_cast<>s will work - typedef int ERROR_CantUsehorrible_cast[sizeof(mfp)==sizeof(u.s) - && sizeof(mfp)==sizeof(u.ProbeFunc) - && sizeof(u2.virtfunc)==sizeof(u2.s) ? 1 : -1]; - // Unfortunately, taking the address of a MF prevents it from being inlined, so - // this next line can't be completely optimised away by the compiler. - u2.virtfunc = &GenericVirtualClass::GetThis; - u.s.codeptr = u2.s.codeptr; - out.thisptroffs = (reinterpret_cast(NULL)->*u.ProbeFunc)(); - */ - out.thisptroffs = -1; - out.vtbloffs = 0; - } - }; - - // Don: Nasty hack for Microsoft and Intel (IA32 and Itanium) - // unknown_inheritance classes go here - // This is probably the ugliest bit of code I've ever written. Look at the casts! - // There is a compiler bug in MSVC6 which prevents it from using this code. - template<> struct MFI_Impl<4*SH_PTRSIZE> // THE BIGGEST ONE!!!1GABEN - { - template static inline void GetFuncInfo(MFP mfp, MemFuncInfo &out) - { - out.vtblindex = MFI_GetVtblOffset(*(void**)&mfp); - out.isVirtual = out.vtblindex >= 0 ? true : false; - - // The member function pointer is 16 bytes long. We can't use a normal cast, but - // we can use a union to do the conversion. - union { - MFP func; - // In VC++ and ICL, an unknown_inheritance member pointer - // is internally defined as: - struct { - void *m_funcaddress; // points to the actual member function - int delta; // #bytes to be added to the 'this' pointer - int vtordisp; // #bytes to add to 'this' to find the vtable - int vtable_index; // or 0 if no virtual inheritance - } s; - } u; - // Check that the horrible_cast will work - typedef int ERROR_CantUsehorrible_cast[sizeof(u.func)==sizeof(u.s)? 1 : -1]; - u.func = mfp; - int virtual_delta = 0; - if (u.s.vtable_index) { // Virtual inheritance is used - /* - // First, get to the vtable. - // It is 'vtordisp' bytes from the start of the class. - int * vtable = *reinterpret_cast( - reinterpret_cast(thisptr) + u.s.vtordisp ); - - // 'vtable_index' tells us where in the table we should be looking. - virtual_delta = u.s.vtordisp + *reinterpret_cast( - reinterpret_cast(vtable) + u.s.vtable_index); - // The int at 'virtual_delta' gives us the amount to add to 'this'. - // Finally we can add the three components together. Phew! - out.thisptr = reinterpret_cast( - reinterpret_cast(thisptr) + u.s.delta + virtual_delta); - */ - out.vtbloffs = u.s.vtordisp; - out.thisptroffs = -1; - } - else - { - out.vtbloffs = out.vtblindex < 0 ? 0 : u.s.delta; - out.thisptroffs = u.s.delta; - } - }; - }; -# else -# error Unsupported compiler -# endif - - // This version does not take a this pointer - // Useful for hookdecls, as they ensure that mfp is correct through a static_cast - template inline void GetFuncInfo(X mfp, MemFuncInfo &out) - { - MFI_Impl::GetFuncInfo(mfp, out); - } - - // Versions which do take a this - // - template - inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Params...), MemFuncInfo &out) - { - RetType(Y::*mfp2)(Params...) = mfp; - MFI_Impl::GetFuncInfo(mfp2, out); - } - - template - inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Params...) const, MemFuncInfo &out) - { - RetType(Y::*mfp2)(Params...) const = mfp; - MFI_Impl::GetFuncInfo(mfp2, out); - } - - template - inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Params..., ...), MemFuncInfo &out) - { - RetType(Y::*mfp2)(Params..., ...) = mfp; - MFI_Impl::GetFuncInfo(mfp2, out); - } - - template - inline void GetFuncInfo(Y *ptr, RetType(X::*mfp)(Params..., ...) const, MemFuncInfo &out) - { - RetType(Y::*mfp2)(Params..., ...) const = mfp; - MFI_Impl::GetFuncInfo(mfp2, out); - } -} - -#endif diff --git a/utils/mmsource/core/sourcehook/sh_memory.h b/utils/mmsource/core/sourcehook/sh_memory.h deleted file mode 100644 index bd36e79d9..000000000 --- a/utils/mmsource/core/sourcehook/sh_memory.h +++ /dev/null @@ -1,379 +0,0 @@ -/* ======== SourceHook ======== -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko, Scott "Damaged Soul" Ehlert -* Contributors: lancevorgin, XAD, theqizmo -* ============================ -*/ - -#ifndef __SHINT_MEMORY_H__ -#define __SHINT_MEMORY_H__ - -// Feb 17 / 2005: -// Unprotect now sets to readwrite -// The vtable doesn't need to be executable anyway - -# if SH_XP == SH_XP_WINAPI -# include -# define SH_MEM_READ 1 -# define SH_MEM_WRITE 2 -# define SH_MEM_EXEC 4 -# elif SH_XP == SH_XP_POSIX -# include -# include -# include -# include -# include -// http://www.die.net/doc/linux/man/man2/mprotect.2.html -# include -# ifndef PAGESIZE -# define PAGESIZE 4096 -# endif -# define SH_MEM_READ PROT_READ -# define SH_MEM_WRITE PROT_WRITE -# define SH_MEM_EXEC PROT_EXEC - -// We need to align addr down to pagesize on linux -// We assume PAGESIZE is a power of two -# define SH_LALIGN(x) (void*)((uintptr_t)(x) & ~(PAGESIZE-1)) -# define SH_LALDIF(x) ((uintptr_t)(x) % PAGESIZE) -# else -# error Unsupported OS/Compiler -# endif -#if SH_SYS == SH_SYS_APPLE -# include -# include -# include -#endif - -#include "sh_list.h" - -namespace SourceHook -{ - static inline bool GetPageBits(void *addr, int *bits) - { -#if SH_SYS == SH_SYS_LINUX - // On linux, first check /proc/self/maps - unsigned long laddr = reinterpret_cast(addr); - - FILE *pF = fopen("/proc/self/maps", "r"); - if (pF) { - // Linux /proc/self/maps -> parse - // Format: - // lower upper prot stuff path - // 08048000-0804c000 r-xp 00000000 03:03 1010107 /bin/cat - unsigned long rlower, rupper; - char r, w, x; - while (fscanf(pF, "%lx-%lx %c%c%c", &rlower, &rupper, &r, &w, &x) != EOF) { - // Check whether we're IN THERE! - if (laddr >= rlower && laddr < rupper) { - fclose(pF); - *bits = 0; - if (r == 'r') - *bits |= SH_MEM_READ; - if (w == 'w') - *bits |= SH_MEM_WRITE; - if (x == 'x') - *bits |= SH_MEM_EXEC; - return true; - } - // Read to end of line - int c; - while ((c = fgetc(pF)) != '\n') { - if (c == EOF) - break; - } - if (c == EOF) - break; - } - fclose(pF); - return false; - } - pF = fopen("/proc/curproc/map", "r"); - if (pF) { - // FreeBSD /proc/curproc/map -> parse - // 0x804800 0x805500 13 15 0xc6e18960 r-x 21 0x0 COW NC vnode - unsigned long rlower, rupper, ignoreLong; - int ignoreInt; - char r, w, x; - while (fscanf(pF, "0x%lx 0x%lx %d %d 0x%lx %c%c%c", &rlower, &rupper, &ignoreInt, - &ignoreInt, &ignoreLong, &r, &w, &x) != EOF) { - // Check whether we're IN THERE! - if (laddr >= rlower && laddr < rupper) { - fclose(pF); - *bits = 0; - if (r == 'r') - *bits |= SH_MEM_READ; - if (r == 'w') - *bits |= SH_MEM_WRITE; - if (r == 'x') - *bits |= SH_MEM_EXEC; - return true; - } - // Read to end of line - int c; - while ((c = fgetc(pF)) != '\n') { - if (c == EOF) - break; - } - if (c == EOF) - break; - } - fclose(pF); - return false; - } - return false; -#elif SH_SYS == SH_SYS_APPLE - vm_size_t ignoreSize; - vm_address_t vmaddr = (vm_address_t)addr; - memory_object_name_t obj; -#if defined(__i386__) - vm_region_basic_info_data_t info; - vm_region_flavor_t flavor = VM_REGION_BASIC_INFO; - mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT; - kern_return_t kr = vm_region(mach_task_self(), &vmaddr, &ignoreSize, flavor, - (vm_region_info_t)&info, &count, &obj); -#elif defined(__x86_64__) - vm_region_basic_info_data_64_t info; - vm_region_flavor_t flavor = VM_REGION_BASIC_INFO_64; - mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT_64; - kern_return_t kr = vm_region_64(mach_task_self(), &vmaddr, &ignoreSize, flavor, - (vm_region_info_64_t)&info, &count, &obj); -#endif - if (kr != KERN_SUCCESS) - return false; - *bits = 0; - if (info.protection & VM_PROT_READ) - *bits |= SH_MEM_READ; - if (info.protection & VM_PROT_WRITE) - *bits |= SH_MEM_WRITE; - if (info.protection & VM_PROT_EXECUTE) - *bits |= SH_MEM_EXEC; - return true; -#elif SH_XP == SH_XP_WINAPI - SYSTEM_INFO info; - GetSystemInfo(&info); - - MEMORY_BASIC_INFORMATION mem; - size_t base = size_t(addr) & ~size_t(info.dwPageSize - 1); - if (!VirtualQuery((void *)base, &mem, sizeof(mem))) - return false; - switch (mem.Protect) { - case PAGE_EXECUTE: - *bits = SH_MEM_EXEC; - break; - case PAGE_EXECUTE_READ: - *bits = SH_MEM_EXEC | SH_MEM_READ; - break; - case PAGE_EXECUTE_READWRITE: - case PAGE_EXECUTE_WRITECOPY: - *bits = SH_MEM_EXEC | SH_MEM_READ | SH_MEM_WRITE; - break; - case PAGE_NOACCESS: - *bits = 0; - break; - case PAGE_READONLY: - *bits = SH_MEM_READ; - break; - case PAGE_READWRITE: - case PAGE_WRITECOPY: - *bits = SH_MEM_READ | SH_MEM_WRITE; - break; - default: - return false; - } - return true; -#endif - } - - inline bool SetMemAccess(void *addr, size_t len, int access) - { -# if SH_XP == SH_XP_POSIX - return mprotect(SH_LALIGN(addr), len + SH_LALDIF(addr), access)==0 ? true : false; -# elif SH_XP == SH_XP_WINAPI - DWORD tmp; - DWORD prot; - switch (access) - { - case SH_MEM_READ: - prot = PAGE_READONLY; break; - case SH_MEM_READ | SH_MEM_WRITE: - prot = PAGE_READWRITE; break; - case SH_MEM_READ | SH_MEM_EXEC: - prot = PAGE_EXECUTE_READ; break; - default: - case SH_MEM_READ | SH_MEM_WRITE | SH_MEM_EXEC: - prot = PAGE_EXECUTE_READWRITE; break; - } - return VirtualProtect(addr, len, prot, &tmp) ? true : false; -# endif - } - - inline bool MakePageWritable(void *addr) - { - int bits; - if (GetPageBits(addr, &bits)) { - if (bits & SH_MEM_WRITE) - return true; - bits |= SH_MEM_WRITE; - } else { - bits = SH_MEM_READ | SH_MEM_WRITE | SH_MEM_EXEC; - } - return SetMemAccess(addr, sizeof(void *), bits); - } - -#if SH_XP == SH_XP_POSIX - namespace - { - bool g_BadReadCalled; - jmp_buf g_BadReadJmpBuf; - -# if SH_SYS == SH_SYS_LINUX - static void BadReadHandler(int sig) - { - if (g_BadReadCalled) - longjmp(g_BadReadJmpBuf, 1); - } -# elif SH_SYS == SH_SYS_APPLE - static void BadReadHandler(int signal, siginfo_t* my_siginfo, void* my_context) - { - if (g_BadReadCalled) - longjmp(g_BadReadJmpBuf, 1); - } -# endif - } -#endif - - /** - * @brief Checks whether the specified memory region is (still) accessible - * - * @param addr The lower boundary - * @param len Length of the region to be checked - */ - namespace - { - static inline bool ModuleInMemory(char *addr, size_t len) - { -#if SH_SYS == SH_SYS_LINUX - // On linux, first check /proc/self/maps - long lower = reinterpret_cast(addr); - long upper = lower + len; - - FILE *pF = fopen("/proc/self/maps", "r"); - if (pF) - { - // Linux /proc/self/maps -> parse - // Format: - // lower upper prot stuff path - // 08048000-0804c000 r-xp 00000000 03:03 1010107 /bin/cat - long rlower, rupper; - while (fscanf(pF, "%lx-%lx", &rlower, &rupper) != EOF) - { - // Check whether we're IN THERE! - if (lower >= rlower && upper <= rupper) - { - fclose(pF); - return true; - } - // Read to end of line - int c; - while ((c = fgetc(pF)) != '\n') - { - if (c == EOF) - break; - } - if (c == EOF) - break; - } - fclose(pF); - return false; - } - pF = fopen("/proc/curproc/map", "r"); - if (pF) - { - // FreeBSD /proc/curproc/map -> parse - // 0x804800 0x805500 13 15 0xc6e18960 r-x 21 0x0 COW NC vnode - long rlower, rupper; - while (fscanf(pF, "0x%lx 0x%lx", &rlower, &rupper) != EOF) - { - // Check whether we're IN THERE! - if (lower >= rlower && upper <= rupper) - { - fclose(pF); - return true; - } - // Read to end of line - int c; - while ((c = fgetc(pF)) != '\n') - { - if (c == EOF) - break; - } - if (c == EOF) - break; - } - fclose(pF); - return false; - } - - // Both of the above failed, try to actually read and trap sigsegv (implemented by Damaged Soul) - void(*prevHandler)(int sig); - g_BadReadCalled = true; - - if (setjmp(g_BadReadJmpBuf)) - return true; - - prevHandler = signal(SIGSEGV, BadReadHandler); - - volatile const char *p = reinterpret_cast(addr); - char dummy; - - for (size_t i = 0; i < len; i++) - dummy = p[i]; - (void)dummy; // silence unused var, we must read from p - - g_BadReadCalled = false; - - signal(SIGSEGV, prevHandler); - - return false; -#elif SH_SYS == SH_SYS_APPLE - struct sigaction sa, osa, osa2; - sa.sa_sigaction = BadReadHandler; - sa.sa_flags = SA_SIGINFO | SA_RESTART; - - g_BadReadCalled = true; - - if (setjmp(g_BadReadJmpBuf)) - return false; - - if (sigaction(SIGBUS, &sa, &osa) == -1) - return false; - if (sigaction(SIGSEGV, &sa, &osa2) == -1) - return false; - - volatile const char *p = reinterpret_cast(addr); - char dummy; - - for (size_t i = 0; i < len; i++) - dummy = p[i]; - (void)dummy; // silence unused var, we must read from p - - g_BadReadCalled = false; - - sigaction(SIGBUS, &osa, NULL); - sigaction(SIGSEGV, &osa2, NULL); - - return true; -#elif SH_XP == SH_XP_WINAPI - // On Win32, simply use IsBadReadPtr - return !IsBadReadPtr(addr, len); -#endif - } - } -} - -#endif diff --git a/utils/mmsource/core/sourcehook/sh_pagealloc.h b/utils/mmsource/core/sourcehook/sh_pagealloc.h deleted file mode 100644 index 3a415593c..000000000 --- a/utils/mmsource/core/sourcehook/sh_pagealloc.h +++ /dev/null @@ -1,330 +0,0 @@ -#ifndef __SH_PAGEALLOC_H__ -#define __SH_PAGEALLOC_H__ - -#include "sh_list.h" -#include "sh_memory.h" - -# if SH_XP == SH_XP_WINAPI -# include -# elif SH_XP == SH_XP_POSIX -# include -# include -# else -# error Unsupported OS/Compiler -# endif - - -namespace SourceHook -{ - - /* - Class which lets us allocate memory regions in special pages only meant for on the fly code generation. - - If we alloc with malloc and then set the page access type to read/exec only, other regions returned by - malloc that are in the same page would lose their write access as well and the process could crash. - - Allocating one page per code generation session is usually a waste of memory and on some platforms also - a waste of virtual address space (Windows VirtualAlloc has a granularity of 64K). - - - IMPORTANT: the memory that Alloc() returns is not a in a defined state! - It could be in read+exec OR read+write mode. - -> call SetRE() or SetRW() before using allocated memory! - */ - class CPageAlloc - { - struct AllocationUnit - { - size_t begin_offset; - size_t size; - - AllocationUnit(size_t p_offs, size_t p_size) : begin_offset(p_offs), size(p_size) - { - } - - bool operator < (const AllocationUnit &other) const - { - return begin_offset < other.begin_offset; - } - }; - - typedef List AUList; - struct AllocatedRegion - { - void *startPtr; - size_t size; - bool isolated; // may contain only one AU - size_t minAlignment; - AUList allocUnits; - bool isRE; // true: RE, otherwise: RW - - void CheckGap(size_t gap_begin, size_t gap_end, size_t reqsize, - size_t &smallestgap_pos, size_t &smallestgap_size, size_t &outAlignBytes) - { - size_t gapsize = gap_end - gap_begin; - // How many bytes do we actually need here? - // = requested size + alignment bytes - size_t neededSize = reqsize; - size_t alignBytes = minAlignment - ((reinterpret_cast(startPtr) + gap_begin) % minAlignment); - - alignBytes %= minAlignment; - neededSize += alignBytes; - - if (gapsize >= neededSize) - { - if (gapsize < smallestgap_size) - { - smallestgap_size = gapsize; - smallestgap_pos = gap_begin; - outAlignBytes = alignBytes; - } - } - } - - bool TryAlloc(size_t reqsize, void * &outAddr) - { - // Check for isolated - if (isolated && !allocUnits.empty()) - return false; - - // Find the smallest gap where req fits - size_t lastend = 0; - size_t smallestgap_pos = size + 1; - size_t smallestgap_size = size + 1; - size_t alignmentbytes = 0; - - for (AUList::iterator iter = allocUnits.begin(); iter != allocUnits.end(); ++iter) - { - CheckGap(lastend, iter->begin_offset, reqsize, smallestgap_pos, smallestgap_size, alignmentbytes); - lastend = iter->begin_offset + iter->size; - } - - CheckGap(lastend, size, reqsize, smallestgap_pos, smallestgap_size, alignmentbytes); - - if (smallestgap_pos < size) - { - outAddr = reinterpret_cast(reinterpret_cast(startPtr) + smallestgap_pos + alignmentbytes); - allocUnits.push_sorted( AllocationUnit(smallestgap_pos, reqsize + alignmentbytes) ); - return true; - } - else - { - return false; - } - } - - bool TryFree(void *addr) - { - if (addr < startPtr || addr >= reinterpret_cast(reinterpret_cast(startPtr) + size)) - return false; - - intptr_t start = reinterpret_cast(startPtr); - - for (AUList::iterator iter = allocUnits.begin(); iter != allocUnits.end(); ++iter) - { - size_t AUBegin = start + iter->begin_offset; - void *alignedAUBegin = reinterpret_cast( - AUBegin + ((minAlignment - AUBegin % minAlignment) % minAlignment) - ); - - if (addr == alignedAUBegin) - { - DebugCleanMemory(reinterpret_cast(startPtr) + iter->begin_offset, - iter->size); - allocUnits.erase(iter); - return true; - } - } - - return false; - } - - void DebugCleanMemory(unsigned char* start, size_t size) - { - bool wasRE = isRE; - if (isRE) - { - SetRW(); - } - - unsigned char* end = start + size; - for (unsigned char* p = start; p != end; ++p) - { - *p = 0xCC; - } - - if (wasRE) - { - SetRE(); - } - } - - bool Contains(void *addr) - { - return addr >= startPtr && addr < reinterpret_cast(reinterpret_cast(startPtr) + size); - } - - void FreeRegion() - { -#if SH_XP == SH_XP_POSIX - munmap(startPtr, size); -#elif SH_XP == SH_XP_WINAPI - VirtualFree(startPtr, 0, MEM_RELEASE); -#endif - } - - void SetRE() - { - SetMemAccess(startPtr, size, SH_MEM_READ | SH_MEM_EXEC); - isRE = true; - } - - void SetRW() - { - SetMemAccess(startPtr, size, SH_MEM_READ | SH_MEM_WRITE); - isRE = false; - } - }; - - typedef List ARList; - - size_t m_MinAlignment; - size_t m_PageSize; - ARList m_Regions; - - bool AddRegion(size_t minSize, bool isolated) - { - AllocatedRegion newRegion; - newRegion.startPtr = 0; - newRegion.isolated = isolated; - newRegion.minAlignment = m_MinAlignment; - - // Compute real size -> align up to m_PageSize boundary - - newRegion.size = minSize - (minSize % m_PageSize); - if (newRegion.size < minSize) - newRegion.size += m_PageSize; - -#if SH_XP == SH_XP_POSIX -# if !defined MAP_ANONYMOUS -# define MAP_ANONYMOUS MAP_ANON -# endif - newRegion.startPtr = mmap(0, newRegion.size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); -#elif SH_XP == SH_XP_WINAPI - newRegion.startPtr = VirtualAlloc(NULL, newRegion.size, MEM_COMMIT, PAGE_READWRITE); -#endif - - if (newRegion.startPtr) - { - newRegion.SetRW(); - m_Regions.push_back(newRegion); - return true; - } - else - { - return false; - } - - } - - void *AllocPriv(size_t size, bool isolated) - { - void *addr; - - if (!isolated) - { - for (ARList::iterator iter = m_Regions.begin(); iter != m_Regions.end(); ++iter) - { - if (iter->TryAlloc(size, addr)) - return addr; - } - } - - if (!AddRegion(size, isolated)) - return NULL; - - bool tmp = m_Regions.back().TryAlloc(size, addr); - SH_ASSERT(tmp, ("TryAlloc fails after AddRegion")); - return tmp ? addr : NULL; - } - - public: - CPageAlloc(size_t minAlignment = 4 /* power of 2 */ ) : m_MinAlignment(minAlignment) - { -#if SH_XP == SH_XP_POSIX - m_PageSize = sysconf(_SC_PAGESIZE); -#elif SH_XP == SH_XP_WINAPI - SYSTEM_INFO sysInfo; - GetSystemInfo(&sysInfo); - m_PageSize = sysInfo.dwPageSize; -#endif - } - - ~CPageAlloc() - { - // Free all regions - for (ARList::iterator iter = m_Regions.begin(); iter != m_Regions.end(); ++iter) - { - iter->FreeRegion(); - } - } - - void *Alloc(size_t size) - { - return AllocPriv(size, false); - } - - void *AllocIsolated(size_t size) - { - return AllocPriv(size, true); - } - - void Free(void *ptr) - { - for (ARList::iterator iter = m_Regions.begin(); iter != m_Regions.end(); ++iter) - { - if (iter->TryFree(ptr)) - { - if (iter->allocUnits.empty()) - { - iter->FreeRegion(); - m_Regions.erase(iter); - } - break; - } - } - } - - void SetRE(void *ptr) - { - for (ARList::iterator iter = m_Regions.begin(); iter != m_Regions.end(); ++iter) - { - if (iter->Contains(ptr)) - { - iter->SetRE(); - break; - } - } - } - - void SetRW(void *ptr) - { - for (ARList::iterator iter = m_Regions.begin(); iter != m_Regions.end(); ++iter) - { - if (iter->Contains(ptr)) - { - iter->SetRW(); - break; - } - } - } - - size_t GetPageSize() - { - return m_PageSize; - } - }; -} - -#endif - diff --git a/utils/mmsource/core/sourcehook/sh_stack.h b/utils/mmsource/core/sourcehook/sh_stack.h deleted file mode 100644 index 5322db28b..000000000 --- a/utils/mmsource/core/sourcehook/sh_stack.h +++ /dev/null @@ -1,232 +0,0 @@ -/* ======== SourceMM ======== -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko -* ============================ -*/ - -#ifndef __SH_STACK_H__ -#define __SH_STACK_H__ - -#include -#include "sh_vector.h" - -namespace SourceHook -{ - // May _never_ reallocate used memory! - - template class CStack - { - static const size_t SECTOR_SIZE = 16; - - CVector m_Sectors; // Stores sectors - - size_t m_UsedSize; - - void clear() - { - typename CVector::iterator sect_iter; - for (sect_iter = m_Sectors.begin(); sect_iter != m_Sectors.end(); ++sect_iter) - { - delete [] *sect_iter; - } - m_Sectors.clear(); - } - public: - friend class iterator; - class iterator - { - CStack *m_pParent; - size_t m_Index; - public: - iterator(CStack *pParent, size_t id) : m_pParent(pParent), m_Index(id) - { - } - - iterator(CStack *pParent) : m_pParent(pParent), m_Index(0) - { - } - - iterator() : m_pParent(NULL), m_Index(0) - { - } - - T &operator *() - { - return m_pParent->at(m_Index); - } - const T &operator *() const - { - return m_pParent->at(m_Index); - } - - T * operator->() - { - return &(m_pParent->at(m_Index)); - } - - const T * operator->() const - { - return &(m_pParent->at(m_Index)); - } - - iterator & operator++() // preincrement - { - ++m_Index; - return (*this); - } - - iterator operator++(int) // postincrement - { - iterator tmp = *this; - ++m_Index; - return tmp; - } - - iterator & operator--() // predecrement - { - --m_Index; - return (*this); - } - - iterator operator--(int) // postdecrememnt - { - iterator tmp = *this; - --m_Index; - return tmp; - } - - bool operator==(const iterator & right) const - { - return (m_pParent == right.m_pParent && m_Index == right.m_Index); - } - - bool operator!=(const iterator & right) const - { - return !(*this == right); - } - }; - CStack() : m_UsedSize(0) - { - } - - CStack(const CStack &other) - { - for (typename CVector::iterator sect_iter = other.m_Sectors.begin(); - sect_iter != other.m_Sectors.end(); ++sect_iter) - { - m_Sectors.push_back(new T[SECTOR_SIZE]); - for (size_t i = 0; i < SECTOR_SIZE; ++i) - m_Sectors.back()[i] = (*sect_iter)[i]; - } - m_UsedSize = other.m_UsedSize; - } - - CStack & operator =(const CStack &other) - { - clear(); - for (typename CVector::iterator sect_iter = other.m_Sectors.begin(); - sect_iter != other.m_Sectors.end(); ++sect_iter) - { - m_Sectors.push_back(new T[SECTOR_SIZE]); - for (size_t i = 0; i < SECTOR_SIZE; ++i) - m_Sectors.back()[i] = (*sect_iter)[i]; - } - m_UsedSize = other.m_UsedSize; - return *this; - } - - ~CStack() - { - clear(); - } - - T &at(size_t x) - { - return m_Sectors[x / SECTOR_SIZE][x % SECTOR_SIZE]; - } - - const T &at(size_t x) const - { - return m_Sectors[x / SECTOR_SIZE][x % SECTOR_SIZE]; - } - - bool push(const T &val) - { - if ((m_UsedSize / SECTOR_SIZE) >= m_Sectors.size()) - { - // New sector - m_Sectors.push_back(new T[SECTOR_SIZE]); - } - - at(m_UsedSize) = val; - - ++m_UsedSize; - return true; - } - - T *make_next() - { - if ((m_UsedSize / SECTOR_SIZE) >= m_Sectors.size()) - { - // New sector - m_Sectors.push_back(new T[SECTOR_SIZE]); - } - - return &(at(m_UsedSize++)); - } - - void pop() - { - --m_UsedSize; - } - - void popall() - { - m_UsedSize = 0; - } - - T &front() - { - return at(m_UsedSize-1); - } - - const T &front() const - { - return at(m_UsedSize-1); - } - - T &second() - { - return at(m_UsedSize-2); - } - - const T &second() const - { - return at(m_UsedSize-2); - } - - iterator begin() - { - return iterator(this, 0); - } - iterator end() - { - return iterator(this, m_UsedSize); - } - - size_t size() - { - return m_UsedSize; - } - bool empty() - { - return m_UsedSize == 0 ? true : false; - } - }; -}; //namespace SourceHook - -#endif diff --git a/utils/mmsource/core/sourcehook/sh_string.h b/utils/mmsource/core/sourcehook/sh_string.h deleted file mode 100644 index 36e1fef7b..000000000 --- a/utils/mmsource/core/sourcehook/sh_string.h +++ /dev/null @@ -1,401 +0,0 @@ -/* ======== SourceMM ======== -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): David "BAILOPAN" Anderson -* ============================ -*/ - -/* AMX Mod X - * - * by the AMX Mod X Development Team - */ - -#ifndef _INCLUDE_CSTRING_H -#define _INCLUDE_CSTRING_H - -#include -#include - -namespace SourceHook -{ -class String -{ -public: - String() - { - v = NULL; - a_size = 0; - //assign(""); - } - - ~String() - { - if (v) - delete [] v; - } - - String(const char *src) - { - v = NULL; - a_size = 0; - assign(src); - } - - String(const String &src) - { - v = NULL; - a_size = 0; - assign(src.c_str()); - } - - bool operator ==(const String &other) - { - return (compare(other.c_str()) == 0); - } - - bool operator ==(const char *other) - { - return (compare(other) == 0); - } - - const char *c_str() { return v?v:""; } - - const char *c_str() const { return v?v:""; } - - void append(const char *t) - { - Grow(size() + strlen(t) + 1); - strcat(v, t); - } - - void append(const char c) - { - size_t len = size(); - Grow(len + 2); - v[len] = c; - v[len + 1] = '\0'; - } - - void append(String &d) - { - append(d.c_str()); - } - - void assign(const String &src) - { - assign(src.c_str()); - } - - void assign(const char *d) - { - if (!d) - { - clear(); - } else { - Grow(strlen(d) + 1, false); - strcpy(v, d); - } - } - - void clear() - { - if (v) - v[0] = '\0'; - } - - int compare (const char *d) const - { - if (!v) - return strcmp("", d); - else - return strcmp(v, d); - } - - //Added this for amxx inclusion - bool empty() const - { - if (!v) - return true; - - if (v[0] == '\0') - return true; - - return false; - } - - size_t size() const - { - if (v) - return strlen(v); - else - return 0; - } - - int find(const char c, int index = 0) const - { - int len = static_cast(size()); - if (len < 1) - return npos; - if (index >= len || index < 0) - return npos; - int i = 0; - for (i=index; i(size()); - if (len < 1) - return npos; - if (index >= len || index < npos) - return npos; - int i; - if (index == npos) - i = len - 1; - else - i = index; - - for (; i>=0; i--) - { - if (v[i] == c) - { - return i; - } - } - - return npos; - } - - bool is_space(int c) const - { - if (c == '\f' || c == '\n' || - c == '\t' || c == '\r' || - c == '\v' || c == ' ') - { - return true; - } - - return false; - } - - void trim() - { - if (!v) - return; - - unsigned int i = 0; - unsigned int j = 0; - size_t len = strlen(v); - - if (len == 1) - { - if (is_space(v[i])) - { - clear(); - return; - } - } - - unsigned char c0 = v[0]; - - if (is_space(c0)) - { - for (i=0; i len-start) - num = len - start; - //do the erasing - bool copyflag = false; - for (i=0; i=start && i= len || !v) - return ns; - - if (num == npos) - { - num = len - index; - } else if (index+num >= len) { - num = len - index; - } - - unsigned int i = 0; - unsigned int nslen = num + 2; - - ns.Grow(nslen); - - for (i=index; i= 65 && v[i] <= 90) - v[i] &= ~(1<<5); - } - } - - String & operator = (const String &src) - { - assign(src); - return *this; - } - - String & operator = (const char *src) - { - assign(src); - return *this; - - } - - char operator [] (unsigned int index) const - { - if (index > size() || !v) - { - return -1; - } else { - return v[index]; - } - } - - int at(int a) const - { - if (a < 0 || a >= (int)size() || !v) - return -1; - - return v[a]; - } - - bool at(int at, char c) - { - if (at < 0 || at >= (int)size() || !v) - return false; - - v[at] = c; - - return true; - } - -private: - void Grow(unsigned int d, bool copy=true) - { - if (d <= a_size) - return; - char *n = new char[d + 1]; - if (copy && v) - strcpy(n, v); - if (v) - delete [] v; - else - strcpy(n, ""); - v = n; - a_size = d + 1; - } - - char *v; - unsigned int a_size; -public: - static const int npos = -1; -}; - -}; //NAMESPACE - -#endif //_INCLUDE_CSTRING_H diff --git a/utils/mmsource/core/sourcehook/sh_tinyhash.h b/utils/mmsource/core/sourcehook/sh_tinyhash.h deleted file mode 100644 index 60b919c34..000000000 --- a/utils/mmsource/core/sourcehook/sh_tinyhash.h +++ /dev/null @@ -1,534 +0,0 @@ -/* ======== SourceMM ======== -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): David "BAILOPAN" Anderson -* ============================ -*/ - -#ifndef _INCLUDE_SH_TINYHASH_H_ -#define _INCLUDE_SH_TINYHASH_H_ - -#include "sh_list.h" - -#define _T_INIT_HASH_SIZE 32 - -namespace SourceHook -{ - template - int HashFunction(const K & k); - - template - int HashAlt(const U &u); - - template - int CompareAlt(const U &k1, const K &k2); - - template - int Compare(const K & k1, const K & k2); - - /** - * This is a tiny, growable hash class. - * Meant for quick and dirty dictionaries only! - */ - template - class THash - { - public: - struct THashNode - { - THashNode(const K & k, const V & v) : - key(k), val(v) - { - }; - THashNode & operator =(const THashNode &other) - { - key = other.key; - val = other.val; - } - K key; - V val; - }; - typedef List * NodePtr; - public: - class const_iterator; - THash() : m_Buckets(NULL), m_numBuckets(0), m_percentUsed(0.0f) - { - _Refactor(); - } - THash(const THash &other) : m_Buckets(new NodePtr[other.m_numBuckets]), - m_numBuckets(other.m_numBuckets), m_percentUsed(other.m_percentUsed) - { - for (size_t i=0; ikey)->val = iter->val; - } - void operator=(const THash &other) - { - clear(); - for (const_iterator iter = other.begin(); iter != other.end(); ++iter) - _FindOrInsert(iter->key)->val = iter->val; - } - - ~THash() - { - _Clear(); - } - void clear() - { - _Clear(); - _Refactor(); - } - size_t GetBuckets() - { - return m_numBuckets; - } - float PercentUsed() - { - return m_percentUsed; - } - V & operator [](const K & key) - { - THashNode *pNode = _FindOrInsert(key); - return pNode->val; - } - private: - void _Clear() - { - typename List::iterator iter, end; - for (size_t i=0; iend(); - iter = m_Buckets[i]->begin(); - while (iter != end) - { - delete (*iter); - iter++; - } - delete m_Buckets[i]; - m_Buckets[i] = NULL; - } - } - if (m_Buckets) - delete [] m_Buckets; - m_Buckets = NULL; - m_numBuckets = 0; - } - public: - template - V & AltFindOrInsert(const U & ukey) - { - size_t place = HashAlt(ukey) % m_numBuckets; - THashNode *pNode = NULL; - if (!m_Buckets[place]) - { - m_Buckets[place] = new List; - pNode = new THashNode(ukey, V()); - m_Buckets[place]->push_back(pNode); - m_percentUsed += (1.0f / (float)m_numBuckets); - } else { - typename List::iterator iter; - for (iter=m_Buckets[place]->begin(); iter!=m_Buckets[place]->end(); iter++) - { - if (CompareAlt(ukey, (*iter)->key) == 0) - { - return (*iter)->val; - } - } - //node does not exist - pNode = new THashNode(ukey, V()); - m_Buckets[place]->push_back(pNode); - } - if (PercentUsed() > 0.75f) - { - _Refactor(); - } - return pNode->val; - } - private: - THashNode *_FindOrInsert(const K & key) - { - size_t place = HashFunction(key) % m_numBuckets; - THashNode *pNode = NULL; - if (!m_Buckets[place]) - { - m_Buckets[place] = new List; - pNode = new THashNode(key, V()); - m_Buckets[place]->push_back(pNode); - m_percentUsed += (1.0f / (float)m_numBuckets); - } else { - typename List::iterator iter; - for (iter=m_Buckets[place]->begin(); iter!=m_Buckets[place]->end(); iter++) - { - if (Compare((*iter)->key, key) == 0) - return (*iter); - } - //node does not exist - pNode = new THashNode(key, V()); - m_Buckets[place]->push_back(pNode); - } - if (PercentUsed() > 0.75f) - { - _Refactor(); - } - return pNode; - } - void _Refactor() - { - m_percentUsed = 0.0f; - if (!m_numBuckets) - { - m_numBuckets = _T_INIT_HASH_SIZE; - m_Buckets = new NodePtr[m_numBuckets]; - for (size_t i=0; i::iterator iter; - size_t place; - THashNode *pHashNode; - NodePtr *temp = new NodePtr[m_numBuckets]; - for (size_t i=0; ibegin(); iter != m_Buckets[i]->end(); iter++) - { - pHashNode = (*iter); - //rehash it with the new bucket filter - place = HashFunction(pHashNode->key) % m_numBuckets; - //add it to the new hash table - if (!temp[place]) - { - temp[place] = new List; - m_percentUsed += (1.0f / (float)m_numBuckets); - } - temp[place]->push_back(pHashNode); - } - //delete that bucket! - delete m_Buckets[i]; - m_Buckets[i] = NULL; - } - } - //reassign bucket table - delete [] m_Buckets; - m_Buckets = temp; - } - } - public: - class iterator - { - friend class THash; - public: - iterator() : curbucket(-1), hash(NULL), end(true) - { - }; - iterator(THash *h) : curbucket(-1), hash(h), end(false) - { - if (!h->m_Buckets) - end = true; - else - _Inc(); - }; - //pre increment - iterator & operator++() - { - _Inc(); - return *this; - } - //post increment - iterator operator++(int) - { - iterator old(*this); - _Inc(); - return old; - } - const THashNode & operator * () const - { - return *(*iter); - } - THashNode & operator * () - { - return *(*iter); - } - const THashNode * operator ->() const - { - return (*iter); - } - THashNode * operator ->() - { - return (*iter); - } - bool operator ==(const iterator &where) const - { - if (where.hash == this->hash - && where.end == this->end - && - (this->end || - ((where.curbucket == this->curbucket) - && (where.iter == iter)) - )) - return true; - return false; - } - bool operator !=(const iterator &where) const - { - return !( (*this) == where ); - } - - void erase() - { - if (end || !hash || curbucket < 0 || curbucket >= static_cast(hash->m_numBuckets)) - return; - - // Remove this element and move to the next one - iterator tmp = *this; - ++tmp; - delete (*iter); - hash->m_Buckets[curbucket]->erase(iter); - *this = tmp; - - // :TODO: Maybe refactor to a lower size if required - } - private: - void _Inc() - { - if (end || !hash || curbucket >= static_cast(hash->m_numBuckets)) - return; - if (curbucket < 0) - { - for (int i=0; i<(int)hash->m_numBuckets; i++) - { - if (hash->m_Buckets[i]) - { - iter = hash->m_Buckets[i]->begin(); - if (iter == hash->m_Buckets[i]->end()) - continue; - curbucket = i; - break; - } - } - if (curbucket < 0) - end = true; - } else { - if (iter != hash->m_Buckets[curbucket]->end()) - iter++; - if (iter == hash->m_Buckets[curbucket]->end()) - { - int oldbucket = curbucket; - for (int i=curbucket+1; i<(int)hash->m_numBuckets; i++) - { - if (hash->m_Buckets[i]) - { - iter = hash->m_Buckets[i]->begin(); - if (iter == hash->m_Buckets[i]->end()) - continue; - curbucket = i; - break; - } - } - if (curbucket == oldbucket) - end = true; - } - } - } - private: - int curbucket; - typename SourceHook::List::iterator iter; - THash *hash; - bool end; - }; - class const_iterator - { - friend class THash; - public: - const_iterator() : curbucket(-1), hash(NULL), end(true) - { - }; - const_iterator(const THash *h) : curbucket(-1), hash(h), end(false) - { - if (!h->m_Buckets) - end = true; - else - _Inc(); - }; - //pre increment - const_iterator & operator++() - { - _Inc(); - return *this; - } - //post increment - const_iterator operator++(int) - { - iterator old(*this); - _Inc(); - return old; - } - const THashNode & operator * () const - { - return *(*iter); - } - const THashNode * operator ->() const - { - return (*iter); - } - bool operator ==(const const_iterator &where) const - { - if (where.hash == this->hash - && where.end == this->end - && - (this->end || - ((where.curbucket == this->curbucket) - && (where.iter == iter)) - )) - return true; - return false; - } - bool operator !=(const const_iterator &where) const - { - return !( (*this) == where ); - } - private: - void _Inc() - { - if (end || !hash || curbucket >= static_cast(hash->m_numBuckets)) - return; - if (curbucket < 0) - { - for (int i=0; i<(int)hash->m_numBuckets; i++) - { - if (hash->m_Buckets[i]) - { - iter = hash->m_Buckets[i]->begin(); - if (iter == hash->m_Buckets[i]->end()) - continue; - curbucket = i; - break; - } - } - if (curbucket < 0) - end = true; - } else { - if (iter != hash->m_Buckets[curbucket]->end()) - iter++; - if (iter == hash->m_Buckets[curbucket]->end()) - { - int oldbucket = curbucket; - for (int i=curbucket+1; i<(int)hash->m_numBuckets; i++) - { - if (hash->m_Buckets[i]) - { - iter = hash->m_Buckets[i]->begin(); - if (iter == hash->m_Buckets[i]->end()) - continue; - curbucket = i; - break; - } - } - if (curbucket == oldbucket) - end = true; - } - } - } - private: - int curbucket; - typename SourceHook::List::iterator iter; - const THash *hash; - bool end; - }; - public: - iterator begin() - { - return iterator(this); - } - iterator end() - { - iterator iter; - iter.hash = this; - return iter; - } - - const_iterator begin() const - { - return const_iterator(this); - } - const_iterator end() const - { - const_iterator iter; - iter.hash = this; - return iter; - } - - template - iterator find(const U & u) const - { - iterator b = begin(); - iterator e = end(); - for (iterator iter = b; iter != e; iter++) - { - if ( (*iter).key == u ) - return iter; - } - return end(); - } - template - iterator find(const U & u) - { - iterator b = begin(); - iterator e = end(); - for (iterator iter = b; iter != e; iter++) - { - if ( (*iter).key == u ) - return iter; - } - return end(); - } - template - iterator FindAlt(const U & u) - { - iterator b = begin(); - iterator e = end(); - for (iterator iter = b; iter != e; iter++) - { - if (CompareAlt(u, (*iter).key) == 0) - { - return iter; - } - } - return e; - } - iterator erase(iterator where) - { - where.erase(); - return where; - } - template - void erase(const U & u) - { - iterator iter = find(u); - if (iter == end()) - return; - iter.erase(); - } - friend class iterator; - friend class const_iterator; - private: - NodePtr *m_Buckets; - size_t m_numBuckets; - float m_percentUsed; - }; -}; - -#endif //_INCLUDE_SH_TINYHASH_H_ diff --git a/utils/mmsource/core/sourcehook/sh_vector.h b/utils/mmsource/core/sourcehook/sh_vector.h deleted file mode 100644 index 34383ae33..000000000 --- a/utils/mmsource/core/sourcehook/sh_vector.h +++ /dev/null @@ -1,519 +0,0 @@ -/* ======== SourceMM ======== -* Copyright (C) 2004-2008 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko -* ============================ -*/ - -#ifndef __CVECTOR_H__ -#define __CVECTOR_H__ - -#include - -//This file originally from AMX Mod X -namespace SourceHook -{ -// Vector -template class CVector -{ - bool Grow(size_t amount) - { - // automatic grow - size_t newSize = m_Size * 2; - - if (newSize == 0) - { - newSize = 8; - } - - while (m_CurrentUsedSize + amount > newSize) - { - newSize *= 2; - } - - T *newData = new T[newSize]; - - if (m_Data) - { - for (size_t i=0; i= m_Size) - { - return Grow(amount); - } - else - { - return true; - } - } - - bool ChangeSize(size_t size) - { - // change size - if (size == m_Size) - { - return true; - } - - if (!size) - { - if (m_Data) - { - delete [] m_Data; - m_Data = NULL; - m_Size = 0; - } - return true; - } - - T *newData = new T[size]; - - if (m_Data) - { - size_t end = (m_CurrentUsedSize < size) ? (m_CurrentUsedSize) : size; - for (size_t i=0; i m_Size) - { - m_CurrentUsedSize = m_Size; - } - - return true; - } - - void FreeMemIfPossible() - { - if (!m_Data) - { - return; - } - - if (!m_CurrentUsedSize) - { - ChangeSize(0); - return; - } - - size_t newSize = m_Size; - while (m_CurrentUsedSize <= newSize / 2) - { - newSize /= 2; - } - - if (newSize != m_Size) - { - ChangeSize(newSize); - } - } -protected: - T *m_Data; - size_t m_Size; - size_t m_CurrentUsedSize; -public: - class iterator - { - protected: - T *m_Ptr; - public: - // constructors / destructors - iterator() - { - m_Ptr = NULL; - } - - iterator(T * ptr) - { - m_Ptr = ptr; - } - - // member functions - T * base() - { - return m_Ptr; - } - - const T * base() const - { - return m_Ptr; - } - - // operators - T & operator*() - { - return *m_Ptr; - } - - T * operator->() - { - return m_Ptr; - } - - iterator & operator++() // preincrement - { - ++m_Ptr; - return (*this); - } - - iterator operator++(int) // postincrement - { - iterator tmp = *this; - ++m_Ptr; - return tmp; - } - - iterator & operator--() // predecrement - { - --m_Ptr; - return (*this); - } - - iterator operator--(int) // postdecrememnt - { - iterator tmp = *this; - --m_Ptr; - return tmp; - } - - bool operator==(T * right) const - { - return (m_Ptr == right); - } - - bool operator==(const iterator & right) const - { - return (m_Ptr == right.m_Ptr); - } - - bool operator!=(T * right) const - { - return (m_Ptr != right); - } - - bool operator!=(const iterator & right) const - { - return (m_Ptr != right.m_Ptr); - } - - iterator & operator+=(size_t offset) - { - m_Ptr += offset; - return (*this); - } - - iterator & operator-=(size_t offset) - { - m_Ptr -= offset; - return (*this); - } - - iterator operator+(size_t offset) const - { - iterator tmp(*this); - tmp.m_Ptr += offset; - return tmp; - } - - iterator operator-(size_t offset) const - { - iterator tmp(*this); - tmp.m_Ptr -= offset; - return tmp; - } - - T & operator[](size_t offset) - { - return (*(*this + offset)); - } - - const T & operator[](size_t offset) const - { - return (*(*this + offset)); - } - - bool operator<(const iterator & right) const - { - return m_Ptr < right.m_Ptr; - } - - bool operator>(const iterator & right) const - { - return m_Ptr > right.m_Ptr; - } - - bool operator<=(const iterator & right) const - { - return m_Ptr <= right.m_Ptr; - } - - bool operator>=(const iterator & right) const - { - return m_Ptr >= right.m_Ptr; - } - - size_t operator-(const iterator & right) const - { - return m_Ptr - right.m_Ptr; - } - }; - - // constructors / destructors - CVector() - { - m_Size = 0; - m_CurrentUsedSize = 0; - m_Data = NULL; - } - - CVector(const CVector & other) - { - // copy data - m_Data = new T [other.m_CurrentUsedSize]; - m_Size = other.m_CurrentUsedSize; - m_CurrentUsedSize = other.m_CurrentUsedSize; - for (size_t i=0; i() - { - clear(); - } - - CVector & operator =(const CVector & other) - { - clear(); - ChangeSize(other.size()); - m_CurrentUsedSize = other.size(); - for (size_t i=0; i m_CurrentUsedSize) - assert(0); - return iterator(m_Data + pos); - } - - bool reserve(size_t newSize) - { - if (newSize > m_Size) - return ChangeSize(newSize); - return true; - } - - bool push_back(const T & elem) - { - if (!GrowIfNeeded(1)) - { - return false; - } - - m_Data[m_CurrentUsedSize++] = elem; - - return true; - } - - void pop_back() - { - --m_CurrentUsedSize; - if (m_CurrentUsedSize < 0) - m_CurrentUsedSize = 0; - - FreeMemIfPossible(); - } - - bool resize(size_t newSize) - { - return resize(newSize, T()); - } - - bool resize(size_t newSize, T defval) - { - if (!ChangeSize(newSize)) - return false; - for (size_t i = m_CurrentUsedSize; i < newSize; ++i) - m_Data[i] = defval; - m_CurrentUsedSize = newSize; - return true; - } - - bool empty() const - { - return (m_CurrentUsedSize == 0); - } - - T & at(size_t pos) - { - if (pos > m_CurrentUsedSize) - { - assert(0); - } - return m_Data[pos]; - } - - const T & at(size_t pos) const - { - if (pos > m_CurrentUsedSize) - { - assert(0); - } - return m_Data[pos]; - } - - T & operator[](size_t pos) - { - return at(pos); - } - - const T & operator[](size_t pos) const - { - return at(pos); - } - - T & front() - { - if (m_CurrentUsedSize < 1) - { - assert(0); - } - return m_Data[0]; - } - - const T & front() const - { - if (m_CurrentUsedSize < 1) - { - assert(0); - } - return m_Data[0]; - } - - T & back() - { - if (m_CurrentUsedSize < 1) - { - assert(0); - } - return m_Data[m_CurrentUsedSize - 1]; - } - - const T & back() const - { - if (m_CurrentUsedSize < 1) - { - assert(0); - } - return m_Data[m_CurrentUsedSize - 1]; - } - - iterator insert(iterator where, const T & value) - { - // validate iter - if (where < m_Data || where > (m_Data + m_CurrentUsedSize)) - return iterator(0); - - size_t ofs = where - begin(); - - if (!GrowIfNeeded(1)) - { - return iterator(0); - } - - ++m_CurrentUsedSize; - - where = begin() + ofs; - - // Move subsequent entries - for (T *ptr = m_Data + m_CurrentUsedSize - 2; ptr >= where.base(); --ptr) - *(ptr + 1) = *ptr; - - *where.base() = value; - - return where; - } - - iterator erase(iterator where) - { - // validate iter - if (where < m_Data || where >= (m_Data + m_CurrentUsedSize)) - return iterator(0); - - size_t ofs = where - begin(); - - if (m_CurrentUsedSize > 1) - { - // move - T *theend = m_Data + m_CurrentUsedSize; - for (T *ptr = where.base() + 1; ptr < theend; ++ptr) - *(ptr - 1) = *ptr; - } - - --m_CurrentUsedSize; - - FreeMemIfPossible(); - - return begin() + ofs; - } - - void clear() - { - m_Size = 0; - m_CurrentUsedSize = 0; - if (m_Data) - { - delete [] m_Data; - m_Data = NULL; - } - } -}; -}; //namespace SourceHook - -#endif // __CVECTOR_H__ diff --git a/utils/mmsource/core/sourcehook/sourcehook.cpp b/utils/mmsource/core/sourcehook/sourcehook.cpp deleted file mode 100644 index 8b66b2c31..000000000 --- a/utils/mmsource/core/sourcehook/sourcehook.cpp +++ /dev/null @@ -1,871 +0,0 @@ -/* ======== SourceHook ======== -* vim: set ts=4 sw=4 tw=99 noet: -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko -* Contributors: Scott "Damaged Soul" Ehlert -* ============================ -*/ - -/** - * @file sourcehook.cpp - * @brief Contains the implementation of the SourceHook API -*/ - -#if defined __GNUC__ -#include -#endif - -#include "sourcehook_impl.h" - -namespace SourceHook -{ - template<> - int HashFunction(const int & k) - { - return k; - } - template<> - int Compare(const int & k1, const int & k2) - { - if (k1 == k2) - return 0; - if (k1 > k2) - return 1; - if (k1 < k2) - return -1; - return 0; - } - - namespace Impl - { - ////////////////////////////////////////////////////////////////////////// - // CVfnPtrList - ////////////////////////////////////////////////////////////////////////// - - CVfnPtr *CVfnPtrList::GetVfnPtr(void *vfnptr) - { - iterator iter = find(vfnptr); - if (iter == end()) - { - // No vfnptr info object found - // --> create a new one - CVfnPtr newVfnPtr(vfnptr); - if (newVfnPtr.Init()) - { - push_back(newVfnPtr); - - return &(back()); - } - else - { - // Initialization failed. - return NULL; - } - } - else - { - return &(*iter); - } - } - - ////////////////////////////////////////////////////////////////////////// - // CSourceHookImpl - ////////////////////////////////////////////////////////////////////////// - - - CSourceHookImpl::CSourceHookImpl() - { - } - CSourceHookImpl::~CSourceHookImpl() - { - CompleteShutdown(); - } - - int CSourceHookImpl::GetIfaceVersion() - { - return SH_IFACE_VERSION; - } - - int CSourceHookImpl::GetImplVersion() - { - return SH_IMPL_VERSION; - } - - int CSourceHookImpl::AddHook(Plugin plug, AddHookMode mode, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, - ISHDelegate *handler, bool post) - { - if (mode != Hook_Normal && mode != Hook_VP && mode != Hook_DVP) - return 0; - - // Get info about hook manager - CHookManager hookManager(plug, myHookMan); - if (!hookManager) - return 0; - - void *adjustediface = NULL; - void **cur_vtptr = NULL; - void *cur_vfnptr = NULL; - - // find vfnptr - switch (mode) - { - case Hook_Normal: - adjustediface = reinterpret_cast(reinterpret_cast(iface) + thisptr_offs); - - cur_vtptr = *reinterpret_cast( - reinterpret_cast(adjustediface) + hookManager.GetVtblOffs()); - cur_vfnptr = reinterpret_cast(cur_vtptr + hookManager.GetVtblIdx()); - break; - - case Hook_VP: - - adjustediface = reinterpret_cast(reinterpret_cast(iface) + thisptr_offs); - - cur_vtptr = *reinterpret_cast( - reinterpret_cast(adjustediface) + hookManager.GetVtblOffs()); - cur_vfnptr = reinterpret_cast(cur_vtptr + hookManager.GetVtblIdx()); - - adjustediface = NULL; - break; - - case Hook_DVP: - adjustediface = NULL; - - cur_vtptr = reinterpret_cast(iface); - cur_vfnptr = cur_vtptr + hookManager.GetVtblIdx(); - - break; - } - - CVfnPtr *vfnPtr = m_VfnPtrs.GetVfnPtr(cur_vfnptr); - if (!vfnPtr) - { - // Could not create the vfnptr info object. - // This could be because a thunk generation on GCC - // has failed. See sourcehook_impl_cvfnptr.cpp - // for details. - return false; - } - - vfnPtr->AddHookMan(m_HookManList.GetHookMan(hookManager)); - CIface &ifaceinst = vfnPtr->GetIface(adjustediface); - - // Add the hook - CHook hook(plug, thisptr_offs, handler, - - m_HookIDMan.New(hookManager.GetProto(), hookManager.GetVtblOffs(), hookManager.GetVtblIdx(), - cur_vfnptr, adjustediface, plug, thisptr_offs, handler, post) - - ); - - if (post) - ifaceinst.GetPostHookList().push_back(hook); - else - ifaceinst.GetPreHookList().push_back(hook); - - return hook.GetID(); - } - - bool CSourceHookImpl::RemoveHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, - ISHDelegate *handler, bool post) - { - // Get info about hook manager and compute adjustediface - CHookManager tmpHookMan(plug, myHookMan); - - void *adjustediface = reinterpret_cast(reinterpret_cast(iface)+thisptr_offs); - - // Loop through all hooks and remove those which match: - // hookman, vfnptr, iface, plug, adjusted iface, this ptr offs, handler, post - CVector removehooks; - m_HookIDMan.FindAllHooks(removehooks, tmpHookMan.GetProto(), tmpHookMan.GetVtblOffs(), tmpHookMan.GetVtblIdx(), - adjustediface, plug, thisptr_offs, handler, post); - - if (removehooks.empty()) - return false; - - bool status = false; - - for (CVector::iterator iter = removehooks.begin(); iter != removehooks.end(); ++iter) - { - if (RemoveHookByID(*iter)) - status = true; - } - return status; - } - - bool CSourceHookImpl::RemoveHookByID(int hookid) - { - const CHookIDManager::Entry *hentry; - - hentry = m_HookIDMan.QueryHook(hookid); - if (!hentry) - { - // hookid doesn't exist ! - return false; - } - - // find vfnptr - List::iterator vfnptr_iter = m_VfnPtrs.find(hentry->vfnptr); - if (vfnptr_iter == m_VfnPtrs.end()) - return false; - - // find iface - List::iterator iface_iter = vfnptr_iter->GetIfaceList().find(hentry->adjustediface); - if (iface_iter == vfnptr_iter->GetIfaceList().end()) - return false; - - // find hook - List &hooks = hentry->post ? iface_iter->GetPostHookList() : iface_iter->GetPreHookList(); - List::iterator hook_iter = hooks.find(hookid); - if (hook_iter == hooks.end()) - return false; - - hook_iter->GetHandler()->DeleteThis(); - - // Iterator movage! - List::iterator oldhookiter = hook_iter; - hook_iter = hooks.erase(hook_iter); - - for (CStack::iterator ctx_iter = m_ContextStack.begin(); - ctx_iter != m_ContextStack.end(); ++ctx_iter) - { - ctx_iter->HookRemoved(oldhookiter, hook_iter); - } - - if (iface_iter->GetPreHookList().empty() && iface_iter->GetPostHookList().empty()) - { - // -> Kill all contexts that use it! - for (CStack::iterator ctx_iter = m_ContextStack.begin(); - ctx_iter != m_ContextStack.end(); ++ctx_iter) - { - ctx_iter->IfaceRemoved(&(*iface_iter)); - } - - // There are no hooks on this iface anymore... - iface_iter = vfnptr_iter->GetIfaceList().erase(iface_iter); - - if (vfnptr_iter->GetIfaceList().empty()) - { - // No ifaces at all -> Deactivate the hook - - for (CStack::iterator ctx_iter = m_ContextStack.begin(); - ctx_iter != m_ContextStack.end(); ++ctx_iter) - { - ctx_iter->VfnPtrRemoved(&(*vfnptr_iter)); - } - - RevertAndRemoveVfnPtr(vfnptr_iter); - } - } - - m_HookIDMan.Remove(hookid); - return true; - } - - List::iterator CSourceHookImpl::RevertAndRemoveVfnPtr(List::iterator vfnptr_iter) - { - ICleanupTask *cleanupTask = vfnptr_iter->GetCleanupTask(); - - // Some vfnptrs require cleanup. - // Concrete case: on GCC, when the original vtable entry is not even - // we generate an even-aligned thunk to call the original function. - // If the vfnptr is being removed from a pre hook on the vfnptr - // we have to delay the cleanup of this thunk until the hook loop is done - // (because the orig function call mechanism is going to use the thunk). - - if (cleanupTask != NULL) - { - // If this vfnptr is in use in one of the hook loops running at the moment - // Schedule it for removal on the DEEPEST hook loop. - - size_t numOfContexts = m_ContextStack.size(); - // m_ContextStack.at(0) is the deepest hook context - // m_ContextStack.at(size-1) = m_ContextStack.front is the uppermost - - bool cleanupImmedieately = true; - - CVfnPtr *vfnPtrObjAddr = &(*vfnptr_iter); - for (size_t i = 0; i < numOfContexts; ++i) - { - CHookContext &context = m_ContextStack.at(i); - if (context.pVfnPtr == vfnPtrObjAddr) - { - // Found a hook context using this vfnptr at the moment. - context.m_CleanupTask = cleanupTask; - cleanupImmedieately = false; // Delay the cleanup - break; - } - } - - if (cleanupImmedieately) - { - cleanupTask->CleanupAndDeleteThis(); - } - } - - // Do the work - vfnptr_iter->Revert(); - return m_VfnPtrs.erase(vfnptr_iter); - } - - void CSourceHookImpl::SetRes(META_RES res) - { - *m_ContextStack.front().pCurRes = res; - } - - META_RES CSourceHookImpl::GetPrevRes() - { - return *m_ContextStack.front().pPrevRes; - } - - META_RES CSourceHookImpl::GetStatus() - { - return *m_ContextStack.front().pStatus; - - } - - const void *CSourceHookImpl::GetOrigRet() - { - return m_ContextStack.front().pOrigRet; - } - - const void *CSourceHookImpl::GetOverrideRet() - { - return (*m_ContextStack.front().pStatus < MRES_OVERRIDE) ? - NULL : m_ContextStack.front().pOverrideRet; - } - - void *CSourceHookImpl::GetIfacePtr() - { - // If in recall: return last one - if (m_ContextStack.front().m_State >= CHookContext::State_Recall_Pre && - m_ContextStack.front().m_State <= CHookContext::State_Recall_PostVP) - { - return m_ContextStack.second().pIfacePtr; - } - else - { - return m_ContextStack.front().pIfacePtr; - } - } - - void *CSourceHookImpl::GetOverrideRetPtr() - { - return m_ContextStack.front().pOverrideRet; - } - - void CSourceHookImpl::UnloadPlugin(Plugin plug, UnloadListener *listener) - { - // 1) Remove all hooks by this plugin - - CVector removehooks; - m_HookIDMan.FindAllHooks(removehooks, plug); - - for (CVector::iterator iter = removehooks.begin(); iter != removehooks.end(); ++iter) - RemoveHookByID(*iter); - - // 2) Remove all hook managers - for (CHookManList::iterator iter = m_HookManList.begin(); iter != m_HookManList.end(); ) - { - if (iter->GetOwnerPlugin() == plug) - iter = RemoveHookManager(iter); - else - ++iter; - } - - // Fix for bug 5034. It's pretty tricky to find whether hookmanagers owned by this - // plugin are active. We could change how hook managers are tracked in SH, and lazily - // free them as the context stack drops to 0, or we could change the pubfunc API to - // know whether it's active or not. Rather than deal with this extra complexity, we - // just conservatively wait until the context stack hits 0 before unloading. - if (m_ContextStack.size() == 0) - { - listener->ReadyToUnload(plug); - } - else - { - m_PendingUnloads.push_back(new PendingUnload(listener, plug)); - } - } - - CHookManList::iterator CSourceHookImpl::RemoveHookManager(CHookManList::iterator hookman_iter) - { - // 2) Remove it - for (CVfnPtrList::iterator vfnptr_iter = m_VfnPtrs.begin(); - vfnptr_iter != m_VfnPtrs.end();) - { - if (!vfnptr_iter->HookManRemoved(&(*hookman_iter))) - { - // This vfnptr has no more hook managers - // and asks to be removed. - - m_HookIDMan.RemoveAll(vfnptr_iter->GetPtr()); - - vfnptr_iter = RevertAndRemoveVfnPtr(vfnptr_iter); - } - else - { - ++vfnptr_iter; - } - } - - return m_HookManList.erase(hookman_iter); - } - - void CSourceHookImpl::RemoveHookManager(Plugin plug, HookManagerPubFunc pubFunc) - { - // Find the hook manager - CHookManList::iterator hookman_iter = m_HookManList.find(CHookManager::Descriptor(plug, pubFunc)); - - if (hookman_iter != m_HookManList.end()) - { - RemoveHookManager(hookman_iter); - } - } - - void CSourceHookImpl::SetIgnoreHooks(void *vfnptr) - { - CHookContext ctx; - ctx.m_State = CHookContext::State_Ignore; - m_ContextStack.push(ctx); - } - - void CSourceHookImpl::ResetIgnoreHooks(void *vfnptr) - { - if (!m_ContextStack.empty() && m_ContextStack.front().m_State == CHookContext::State_Ignore) - { - // Actually use EndContext - // instead of m_ContextStack.pop directly - // because it runs the cleanup task if neccesary - EndContext(&(m_ContextStack.front())); - } - } - - void *CSourceHookImpl::GetOrigVfnPtrEntry(void *vfnptr) - { - for (CVfnPtrList::iterator vfnptr_iter = m_VfnPtrs.begin(); vfnptr_iter != m_VfnPtrs.end(); ++vfnptr_iter) - { - if (vfnptr_iter->GetPtr() == vfnptr) - return vfnptr_iter->GetOrigEntry(); - } - return NULL; - } - - void CSourceHookImpl::DoRecall() - { - CHookContext newCtx; - CHookContext &curCtx = m_ContextStack.front(); - - - newCtx.m_State = curCtx.m_State + (CHookContext::State_Recall_Pre - CHookContext::State_Pre); - if (newCtx.m_State == CHookContext::State_Recall_Post || newCtx.m_State == CHookContext::State_Recall_PostVP) - { - // Also save orig ret - newCtx.pOrigRet = curCtx.pOrigRet; - } - - // The hookfunc usually does this, but it won't have a chance to see it, - // so for recalls, we update status here if it's required - if (*curCtx.pCurRes > *curCtx.pStatus) - *curCtx.pStatus = *curCtx.pCurRes; - - newCtx.pStatus = curCtx.pStatus; - newCtx.pOverrideRet = curCtx.pOverrideRet; - newCtx.pPrevRes = curCtx.pPrevRes; - newCtx.m_Iter = curCtx.m_Iter; - - // Take this with us! - newCtx.pCurRes = curCtx.pCurRes; - - m_ContextStack.push(newCtx); - curCtx.m_State = CHookContext::State_Dead; - } - - IHookContext *CSourceHookImpl::SetupHookLoop(IHookManagerInfo *hi, void *vfnptr, void *thisptr, void **origCallAddr, META_RES *statusPtr, - META_RES *prevResPtr, META_RES *curResPtr, const void *origRetPtr, void *overrideRetPtr) - { - CHookContext *pCtx = NULL; - CHookContext *oldctx = m_ContextStack.empty() ? NULL : &m_ContextStack.front(); - if (oldctx) - { - // SH_CALL - if (oldctx->m_State == CHookContext::State_Ignore) - { - *statusPtr = MRES_IGNORED; - oldctx->m_CallOrig = true; - oldctx->m_State = CHookContext::State_Dead; - - List &vfnptr_list = static_cast(hi)->GetVfnPtrList(); - List::iterator vfnptr_iter; - for (vfnptr_iter = vfnptr_list.begin(); - vfnptr_iter != vfnptr_list.end(); ++vfnptr_iter) - { - if (**vfnptr_iter == vfnptr) - break; - } - if (vfnptr_iter == vfnptr_list.end()) - { - SH_ASSERT(false, ("How can a hook exist on a vfnptr which we don't have in our db?!")); - } - else - { - *origCallAddr = (*vfnptr_iter)->GetOrigCallAddr(); - oldctx->pVfnPtr = *vfnptr_iter; - } - - oldctx->pOrigRet = origRetPtr; - return oldctx; - } - // Recall - else if (oldctx->m_State >= CHookContext::State_Recall_Pre && - oldctx->m_State <= CHookContext::State_Recall_PostVP) - { - pCtx = oldctx; - - *statusPtr = *(oldctx->pStatus); - *prevResPtr = *(oldctx->pPrevRes); - - pCtx->m_Iter = oldctx->m_Iter; - - // Only have possibility of calling the orig func in pre recall mode - pCtx->m_CallOrig = (oldctx->m_State == CHookContext::State_Recall_Pre || - oldctx->m_State == CHookContext::State_Recall_PreVP); - - overrideRetPtr = pCtx->pOverrideRet; - - // When the status is low so there's no override return value and we're in a post recall, - // give it the orig return value as override return value. - if (pCtx->m_State == CHookContext::State_Recall_Post || - pCtx->m_State == CHookContext::State_Recall_PostVP) - { - origRetPtr = oldctx->pOrigRet; - if (*statusPtr < MRES_OVERRIDE) - overrideRetPtr = const_cast(pCtx->pOrigRet); - } - } - } - if (!pCtx) - { - pCtx = m_ContextStack.make_next(); - pCtx->m_State = CHookContext::State_Born; - pCtx->m_CallOrig = true; - } - - pCtx->pIface = NULL; - - List &vfnptr_list = static_cast(hi)->GetVfnPtrList(); - List::iterator vfnptr_iter; - for (vfnptr_iter = vfnptr_list.begin(); - vfnptr_iter != vfnptr_list.end(); ++vfnptr_iter) - { - if (**vfnptr_iter == vfnptr) - break; - } - if (vfnptr_iter == vfnptr_list.end()) - { - pCtx->m_State = CHookContext::State_Dead; - } - else - { - pCtx->pVfnPtr = *vfnptr_iter; - *origCallAddr = pCtx->pVfnPtr->GetOrigCallAddr(); - pCtx->pIface = pCtx->pVfnPtr->FindIface(thisptr); - } - - pCtx->pStatus = statusPtr; - pCtx->pPrevRes = prevResPtr; - pCtx->pCurRes = curResPtr; - pCtx->pThisPtr = thisptr; - pCtx->pOverrideRet = overrideRetPtr; - pCtx->pOrigRet = origRetPtr; - - return pCtx; - } - - void CSourceHookImpl::ResolvePendingUnloads(bool force) - { - List::iterator iter = m_PendingUnloads.begin(); - while (iter != m_PendingUnloads.end()) - { - PendingUnload *unload = *iter; - - if (!force && !unload->deactivated()) - { - // Unless being forced, wait one drop of the context stack - // before actually unloading. Otherwise, we'll still return - // to unloaded memory. - unload->deactivate(); - iter++; - } - else - { - unload->listener()->ReadyToUnload(unload->plugin()); - delete unload; - iter = m_PendingUnloads.erase(iter); - } - } - } - - void CSourceHookImpl::EndContext(IHookContext *pCtx) - { - // Do clean up task, if any is associated with this context - m_ContextStack.front().DoCleanupTaskAndDeleteIt(); - // Then remove it - m_ContextStack.pop(); - - // If we've reached 0 contexts and there are pending unloads, - // resolve them now. - if (m_ContextStack.size() == 0 && m_PendingUnloads.size() != 0) - ResolvePendingUnloads(); - } - - void CSourceHookImpl::CompleteShutdown() - { - CVector removehooks; - m_HookIDMan.FindAllHooks(removehooks); - - for (CVector::iterator iter = removehooks.begin(); iter != removehooks.end(); ++iter) - RemoveHookByID(*iter); - } - - void CSourceHookImpl::PausePlugin(Plugin plug) - { - CVector pausehooks; - m_HookIDMan.FindAllHooks(pausehooks, plug); - - for (CVector::iterator iter = pausehooks.begin(); iter != pausehooks.end(); ++iter) - PauseHookByID(*iter); - } - - void CSourceHookImpl::UnpausePlugin(Plugin plug) - { - CVector unpausehooks; - m_HookIDMan.FindAllHooks(unpausehooks, plug); - - for (CVector::iterator iter = unpausehooks.begin(); iter != unpausehooks.end(); ++iter) - UnpauseHookByID(*iter); - } - - bool CSourceHookImpl::PauseHookByID(int hookid) - { - return SetHookPaused(hookid, true); - } - - bool CSourceHookImpl::UnpauseHookByID(int hookid) - { - return SetHookPaused(hookid, false); - } - - bool CSourceHookImpl::SetHookPaused(int hookid, bool paused) - { - const CHookIDManager::Entry *hentry; - - hentry = m_HookIDMan.QueryHook(hookid); - if (!hentry) - { - // hookid doesn't exist ! - return false; - } - - // find vfnptr - List::iterator vfnptr_iter = m_VfnPtrs.find(hentry->vfnptr); - if (vfnptr_iter == m_VfnPtrs.end()) - return false; - - // find iface - List::iterator iface_iter = vfnptr_iter->GetIfaceList().find(hentry->adjustediface); - if (iface_iter == vfnptr_iter->GetIfaceList().end()) - return false; - - // find hook - List &hooks = hentry->post ? iface_iter->GetPostHookList() : iface_iter->GetPreHookList(); - List::iterator hook_iter = hooks.find(hookid); - if (hook_iter == hooks.end()) - return false; - - hook_iter->SetPaused(paused); - return true; - } - - ////////////////////////////////////////////////////////////////////////// - // CHookContext - ////////////////////////////////////////////////////////////////////////// - ISHDelegate *CHookContext::GetNext() - { - CIface *pVPIface; - switch (m_State) - { - case State_Dead: - return NULL; - - case State_Born: - m_Iter = List::iterator(); - m_State = State_Pre; - - // fall-through - case State_Recall_Pre: - m_State = State_Pre; - case State_Pre: - if (pIface) - { - if (!m_Iter) - m_Iter = pIface->GetPreHookList().begin(); - else - ++m_Iter; - SkipPaused(m_Iter, pIface->GetPreHookList()); - - if (m_Iter != pIface->GetPreHookList().end()) - { - pIfacePtr = reinterpret_cast(reinterpret_cast(pThisPtr) - m_Iter->GetThisPointerOffset()); - return m_Iter->GetHandler(); - } - } - - // end of normal hooks -> VP - - m_State = State_PreVP; - m_Iter = List::iterator(); - - // fall-through - case State_Recall_PreVP: - m_State = State_PreVP; - case State_PreVP: - pVPIface = pVfnPtr->FindIface(NULL); - if (pVPIface) - { - if (!m_Iter) - m_Iter = pVPIface->GetPreHookList().begin(); - else - ++m_Iter; - SkipPaused(m_Iter, pVPIface->GetPreHookList()); - - if (m_Iter != pVPIface->GetPreHookList()) - { - pIfacePtr = reinterpret_cast(reinterpret_cast(pThisPtr) - m_Iter->GetThisPointerOffset()); - return m_Iter->GetHandler(); - } - } - - // end VP hooks -> orig call - - m_State = State_OrigCall; - return NULL; - - case State_OrigCall: - m_Iter = List::iterator(); - m_State = State_Post; - - // fall-through - case State_Post: - if (pIface) - { - if (!m_Iter) - m_Iter = pIface->GetPostHookList().begin(); - else - ++m_Iter; - SkipPaused(m_Iter, pIface->GetPostHookList()); - - if (m_Iter != pIface->GetPostHookList().end()) - { - pIfacePtr = reinterpret_cast(reinterpret_cast(pThisPtr) - m_Iter->GetThisPointerOffset()); - return m_Iter->GetHandler(); - } - } - // end of normal hooks -> VP - - m_State = State_PostVP; - m_Iter = List::iterator(); - - // fall-through - case State_PostVP: - pVPIface = pVfnPtr->FindIface(NULL); - if (pVPIface) - { - if (!m_Iter) - m_Iter = pVPIface->GetPostHookList().begin(); - else - ++m_Iter; - SkipPaused(m_Iter, pVPIface->GetPostHookList()); - - if (m_Iter != pVPIface->GetPostHookList()) - { - pIfacePtr = reinterpret_cast(reinterpret_cast(pThisPtr) - m_Iter->GetThisPointerOffset()); - return m_Iter->GetHandler(); - } - } - - // end VP hooks -> done - - m_State = State_Dead; - return NULL; - - case State_Recall_Post: - // Skip pre hooks _and_ orig call - m_State = State_Post; - return NULL; - - case State_Recall_PostVP: - // Skip pre hooks _and_ orig call - m_State = State_PostVP; - return NULL; - } - return NULL; - } - - void *CHookContext::GetOverrideRetPtr() - { - return pOverrideRet; - } - - const void *CHookContext::GetOrigRetPtr() - { - return pOrigRet; - } - - bool CHookContext::ShouldCallOrig() - { - return m_CallOrig; - } - - void CHookContext::HookRemoved(List::iterator oldhookiter, List::iterator nexthookiter) - { - if (m_Iter == oldhookiter) - { - m_Iter = nexthookiter; - --m_Iter; - } - } - - void CHookContext::IfaceRemoved(CIface *iface) - { - if (pIface == iface) - pIface = NULL; - } - - void CHookContext::VfnPtrRemoved(CVfnPtr *vfnptr) - { - if (pVfnPtr == vfnptr) - { - // Don't set pVfnPtr = NULL here! - // It may be used still. - // RevertAndRemoveVfnPtr uses it to find the hook context - // to which to attach the cleanup task of the vfnptr. - - //pVfnPtr = NULL; - m_State = State_Dead; - } - } - - void CHookContext::DoCleanupTaskAndDeleteIt() - { - if (m_CleanupTask != NULL) - { - m_CleanupTask->CleanupAndDeleteThis(); - } - } - } -} diff --git a/utils/mmsource/core/sourcehook/sourcehook.h b/utils/mmsource/core/sourcehook/sourcehook.h deleted file mode 100644 index 1c008ff1d..000000000 --- a/utils/mmsource/core/sourcehook/sourcehook.h +++ /dev/null @@ -1,4926 +0,0 @@ -/* ======== SourceHook ======== -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko -* ============================ -*/ - -/** -* @file sourcehook.h -* @brief Contains the public SourceHook API -*/ - -#ifndef __SOURCEHOOK_H__ -#define __SOURCEHOOK_H__ - -// Interface revisions: -// 1 - Initial revision -// 2 - Changed to virtual functions for iterators and all queries -// 3 - Added "hook loop status variable" -// 4 - Reentrant -// 5 - New "V2" interface -#define SH_IFACE_VERSION 5 - -// Impl versions: -// ??? -// 4 - addition of hook ids and vp hooks (with them, AddHookNew and RemoveHookNew) -// This is not a SH_IFACE_VERSION change so that old plugins continue working! -// 5 - implementation of the new "V2" interface -#define SH_IMPL_VERSION 5 - -// Hookman version: -// 1 - standard -#define SH_HOOKMAN_VERSION 1 - -// Hookmanautogen versions -// 1 - initial -#define SH_HOOKMANAUTOGEN_IFACE_VERSION 1 -#define SH_HOOKMANAUTOGEN_IMPL_VERSION 1 - -// The value of SH_GLOB_SHPTR has to be a pointer to SourceHook::ISourceHook -// It's used in various macros -#ifndef SH_GLOB_SHPTR -#define SH_GLOB_SHPTR g_SHPtr -#endif - -// Used to identify the current plugin -#ifndef SH_GLOB_PLUGPTR -#define SH_GLOB_PLUGPTR g_PLID -#endif - -#ifdef SH_DEBUG -# include -# include - -# define SH_ASSERT(x, info) \ - do { \ - if (!(x)) \ - { \ - printf("SOURCEHOOK DEBUG ASSERTION FAILED: %s:%u(%s): %s: ", __FILE__, __LINE__, __FUNCTION__, #x); \ - printf info; \ - putchar('\n'); \ - abort(); \ - } \ - } while(0) - -#else -# define SH_ASSERT(x, info) -#endif - -// System -#define SH_SYS_WIN32 1 -#define SH_SYS_LINUX 2 -#define SH_SYS_APPLE 3 - -// Platform -#define SH_XP_POSIX 10 -#define SH_XP_WINAPI 20 - -#ifdef _WIN32 -# define SH_SYS SH_SYS_WIN32 -# define SH_XP SH_XP_WINAPI -#elif defined __linux__ -# define SH_SYS SH_SYS_LINUX -# define SH_XP SH_XP_POSIX -#elif defined __APPLE__ -# define SH_SYS SH_SYS_APPLE -# define SH_XP SH_XP_POSIX -#else -# error Unsupported system -#endif - -// Compiler -#define SH_COMP_GCC 1 -#define SH_COMP_MSVC 2 - -#ifdef _MSC_VER -# define SH_COMP SH_COMP_MSVC -#elif defined __GNUC__ -# define SH_COMP SH_COMP_GCC -#else -# error Unsupported compiler -#endif - -#if SH_COMP==SH_COMP_MSVC && _MSC_VER < 1500 -# define vsnprintf _vsnprintf -#endif - -#if SH_SYS != SH_SYS_WIN32 -# include -#endif - -#define SH_PTRSIZE sizeof(void*) - -#include "sh_memfuncinfo.h" -#include "FastDelegate.h" - -// Good old metamod! - -// Flags returned by a plugin's api function. -// NOTE: order is crucial, as greater/less comparisons are made. -enum META_RES -{ - MRES_IGNORED=0, // plugin didn't take any action - MRES_HANDLED, // plugin did something, but real function should still be called - MRES_OVERRIDE, // call real function, but use my return value - MRES_SUPERCEDE // skip real function; use my return value -}; - - -namespace SourceHook -{ - /** - * @brief Specifies the size (in bytes) for the internal buffer of vafmt(printf-like) function handlers - */ - const int STRBUF_LEN=4096; - - /** - * @brief An empty class. No inheritance used. Used for original-function-call hacks - */ - class EmptyClass - { - }; - - /** - * @brief Implicit cast. - */ - template - inline Out implicit_cast(In input) - { - return input; - } - - /** - * @brief A plugin typedef - * - * SourceHook doesn't really care what this is. As long as the ==, != and = operators work on it and every - * plugin has a unique identifier, everything is ok. - * It should also be possible to set it to 0. - */ - typedef int Plugin; - - - template class CallClass : public T - { - }; - typedef void ManualCallClass; - - /** - * @brief Describes the way a parameter/retval is passed. - */ - struct PassInfo - { - enum PassType - { - PassType_Unknown=0, /**< Unknown -- no extra info available */ - PassType_Basic, /**< Plain old register data (pointers, integers) */ - PassType_Float, /**< Floating point data */ - PassType_Object, /**< Object or structure */ - }; - - enum PassFlags - { - PassFlag_ByVal = (1<<0), /**< Passing by value */ - PassFlag_ByRef = (1<<1), /**< Passing by reference */ - PassFlag_ODtor = (1<<2), /**< Object has a destructor */ - PassFlag_OCtor = (1<<3), /**< Object has a normal non-trivial constructor */ - PassFlag_AssignOp = (1<<4), /**< Object has a non-trivial assignment operator */ - PassFlag_CCtor = (1<<5), /**< Object has a copy constructor (which takes const Object& as only parameter) */ - - // The following two flags are only relevant for byval return types. - // SH tries to auto-detect these - // If you want to override SH's auto-detection, pass them in yourself - PassFlag_RetMem = (1<<6), /**< Object is returned in memory (through hidden first param */ - PassFlag_RetReg = (1<<7) /**< Object is returned in EAX(:EDX) */ - }; - - size_t size; //!< Size of the data being passed - - // Extra info: - // (might be used in future versions for automatic hookfunc generation) - int type; //!< PassType value - unsigned int flags; //!< Pass/return flags - - struct V2Info - { - void *pNormalCtor; - void *pCopyCtor; - void *pDtor; - void *pAssignOperator; - }; - }; - - struct ProtoInfo - { - enum CallConvention - { - CallConv_Unknown, /**< Unknown -- no extra info available (0)*/ - CallConv_ThisCall, /**< This call (object pointer required) (1)*/ - CallConv_Cdecl, /**< C call (2)*/ - CallConv_StdCall, /**< Windows "stdcall" (3)*/ - - CallConv_HasVarArgs = (1<<16), /**< Has variable arguments */ - CallConv_HasVafmt = CallConv_HasVarArgs | (1<<17) /**< last params: const char*, ... */ - }; - - int numOfParams; //!< number of parameters - PassInfo retPassInfo; //!< PassInfo for the return value. size=0 -> no retval - const PassInfo *paramsPassInfo; //!< PassInfos for the parameters - - // paramsPassInfo[0] is basically a dummy parameter. - // However, paramsPassInfo[0].size stores the version of the ProtoInfo structure. - - // Extra info: - int convention; - - // Version2: - PassInfo::V2Info retPassInfo2; - const PassInfo::V2Info *paramsPassInfo2; - }; - - struct IHookManagerInfo; - - /** - * @brief Pointer to hook manager interface function - * - * The hook manager should store hi for later use if store==true. It should then call hi->SetInfo(...) if hi - * is non-null. The hook manager can return 0 for success or a non-zero value if it doesn't want to be used. - * - * @param hi A pointer to IHookManagerInfo - */ - typedef int (*HookManagerPubFunc)(bool store, IHookManagerInfo *hi); - - class ISHDelegate - { - public: - virtual bool IsEqual(ISHDelegate *pOtherDeleg) = 0; // pOtherDeleg is from the same plugin and hookman - virtual void DeleteThis() = 0; - }; - - struct IHookManagerInfo - { - virtual void SetInfo(int hookman_version, int vtbloffs, int vtblidx, - ProtoInfo *proto, void *hookfunc_vfnptr) = 0; - }; - - // I'm adding support for functions which return references. - - // How it works: - // SH_SETUPCALLS doesn't use plain rettype to store the temporary return values (plugin ret, orig ret, - // override ret) anymore; instead, it uses SourceHook::ReferenceCarrier::type - // this is typedefed to the original rettype normally, but if the rettype is a reference, it's a special class - // which stores the reference as a pointer, and implements constructors, operator= and a conversion operator. - // special cases were needed for getoverrideret / getorigret; these are implemented through the - // SourceHook::MacroRefHelpers structs. - // Furthermore, SetOverrideRet had to be changed a bit; see SourceHook::OverrideFunctor somewhere down in this file. - template struct ReferenceCarrier - { - typedef T type; - }; - - template struct ReferenceCarrier - { - class type - { - T *m_StoredRef; - public: - type() : m_StoredRef(NULL) - { - } - type(T& ref) : m_StoredRef(&ref) - { - } - - T& operator= (T& ref) - { - m_StoredRef = &ref; - return ref; - } - - operator T& () const - { - return *m_StoredRef; - } - }; - }; - - template struct ReferenceUtil - { - typedef T plain_type; - typedef T* pointer_type; - typedef T& reference_type; - }; - - template struct ReferenceUtil - { - typedef T plain_type; - typedef T* pointer_type; - typedef T& reference_type; - }; - - struct IHookContext - { - virtual ISHDelegate *GetNext() = 0; - virtual void *GetOverrideRetPtr() = 0; - virtual const void *GetOrigRetPtr() = 0; - virtual bool ShouldCallOrig() = 0; - }; - - /** - * @brief The main SourceHook interface - */ - class ISourceHook - { - public: - /** - * @brief Return interface version - */ - virtual int GetIfaceVersion() = 0; - - /** - * @brief Return implementation version - */ - virtual int GetImplVersion() = 0; - - /** - * @brief Modes for the new AddHook - */ - enum AddHookMode - { - Hook_Normal, - Hook_VP, - Hook_DVP - }; - - /** - * @brief Add a (VP) hook. - * - * @return non-zero hook id on success, 0 otherwise - * - * @param plug The unique identifier of the plugin that calls this function - * @param mode Can be either Hook_Normal or Hook_VP (vtable-wide hook) - * @param iface The interface pointer - * @param ifacesize The size of the class iface points to - * @param myHookMan A hook manager function that should be capable of handling the function - * @param handler A pointer to the hook handler something - * @param post Set to true if you want a post handler - */ - virtual int AddHook(Plugin plug, AddHookMode mode, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, - ISHDelegate *handler, bool post) = 0; - - // Source backwarts compat (only for normal hooks) - virtual bool RemoveHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, - ISHDelegate *handler, bool post) = 0; - - /** - * @brief Remove a hook by ID. - * - * @return true on success, false otherwise - * - * @param hookid The hook id (returned by AddHook) - */ - virtual bool RemoveHookByID(int hookid) = 0; - - /** - * @brief Pause a hook by ID. - * - * @return true on success, false otherwise - * - * @param hookid The hook id (returned by AddHook) - */ - virtual bool PauseHookByID(int hookid) = 0; - - /** - * @brief Unpause a hook by ID. - * - * @return true on success, false otherwise - * - * @param hookid The hook id (returned by AddHook) - */ - virtual bool UnpauseHookByID(int hookid) = 0; - - /** - * @brief Checks whether a plugin has (a) hook manager(s) that is/are currently used by other plugins - * - * @param plug The unique identifier of the plugin in question - */ - - virtual void SetRes(META_RES res) = 0; //!< Sets the meta result - virtual META_RES GetPrevRes() = 0; //!< Gets the meta result of the - //!< previously calledhandler - virtual META_RES GetStatus() = 0; //!< Gets the highest meta result - virtual const void *GetOrigRet() = 0; //!< Gets the original result. - //!< If not in post function, undefined - virtual const void *GetOverrideRet() = 0; //!< Gets the override result. - //!< If none is specified, NULL - virtual void *GetIfacePtr() = 0; //!< Gets the interface pointer - - virtual void *GetOverrideRetPtr() = 0; //!< Used for setting the override return value - - /** - * @brief Remove a hook manager. Auto-removes all hooks attached to it from plugin plug. - * - * @param plug The owner of the hook manager - * @param pubFunc The hook manager's info function - */ - virtual void RemoveHookManager(Plugin plug, HookManagerPubFunc pubFunc) = 0; - - // For SH_CALL: - - /** - * @brief Makes sure that hooks are going to be ignored on the next call of vfnptr - * - * @param plug The unique identifier of the plugin that calls this function - * @param vfnptr The virtual function pointer of the function in question - */ - virtual void SetIgnoreHooks(void *vfnptr) = 0; - - /** - * @brief Reverses SetIgnoreHooks' effect - * - * @param plug The unique identifier of the plugin that calls this function - * @param vfnptr The virtual function pointer of the function in question - */ - virtual void ResetIgnoreHooks(void *vfnptr) = 0; - - /** - * @brief Finds the original entry of a virtual function pointer - * - * @param vfnptr The virtual function pointer - * @return The original entry if the virtual function pointer has been patched; NULL otherwise. - */ - virtual void *GetOrigVfnPtrEntry(void *vfnptr) = 0; - - ////////////////////////////////////////////////////////////////////////// - - // For hook managers - - // Returns the current iface ptr - virtual void DoRecall() = 0; //!< Initiates a recall sequence - - /* - HOW RECALLS WORK: - - The problem: - Users want the ability to change parameters of the called function - from inside their handler. - The solution: - 1) Mark as "recall" - 2) Recall the function - 3) => SH's hook func gets called: - 4) The first iterator points at the first hook the last hookfunc didn't execute yet - 5) does all iteration and returns normally - 6) The user's handler returns immediately - 7) The hook func returns immediately as well - - Also note that the recalled hookfunc starts with the status the recalling hookfunc - ended with. The last handler (doing the recall) is also able to specify its own - META_RES. - */ - - /** - * @brief Set up the hook loop. - * - * @param statusPtr pointer to status variable - * @param prevResPtr pointer to previous result variable - * @param curResPtr pointer to current result variable - * @param ifacePtrPtr pointer to interface this pointer variable - * @param origRetPr pointer to original return value variable. NULL for void funcs - * @param overrideRetPtr pointer to override return value variable. NULL for void funcs - * - * @return Override Return Pointer the hookfunc should use (may differ from overrideRetPtr - * when the hook func is being called as part of a recall - */ - virtual IHookContext *SetupHookLoop(IHookManagerInfo *hi, void *vfnptr, void *thisptr, void **origCallAddr, - META_RES *statusPtr, META_RES *prevResPtr, META_RES *curResPtr, - const void *origRetPtr, void *overrideRetPtr) = 0; - - virtual void EndContext(IHookContext *pCtx) = 0; - }; - - - class IHookManagerAutoGen - { - public: - virtual int GetIfaceVersion() = 0; - virtual int GetImplVersion() = 0; - - virtual HookManagerPubFunc MakeHookMan(const ProtoInfo *proto, int vtbl_offs, int vtbl_idx) = 0; - virtual void ReleaseHookMan(HookManagerPubFunc pubFunc) = 0; - }; - - // For META_RESULT_ORIG_RET and META_RESULT_OVERRIDE_RET: - // These have to be able to return references. If T is a reference, the pointers returned - // from the SH_GLOB_SHPTR are pointers to instances of ReferenceCarrier::type. - template struct MacroRefHelpers - { - inline static const T* GetOrigRet(ISourceHook *shptr) - { - return reinterpret_cast(shptr->GetOrigRet()); - } - inline static const T* GetOverrideRet(ISourceHook *shptr) - { - return reinterpret_cast(shptr->GetOverrideRet()); - } - }; - - template struct MacroRefHelpers - { - inline static T* GetOrigRet(ISourceHook *shptr) - { - T &ref = *reinterpret_cast::type *>(shptr->GetOrigRet()); - return &ref; - } - inline static T* GetOverrideRet(ISourceHook *shptr) - { - T &ref = *reinterpret_cast::type *>(shptr->GetOverrideRet()); - return &ref; - } - }; - - template - void *GetOrigVfnPtrEntry(X *pInstance, MFP mfp, ISourceHook *pSH) - { - SourceHook::MemFuncInfo info = {true, -1, 0, 0}; - SourceHook::GetFuncInfo(pInstance, mfp, info); - - void *vfnptr = reinterpret_cast( - *reinterpret_cast(reinterpret_cast(pInstance) + info.thisptroffs + info.vtbloffs) + info.vtblindex); - - void *origentry = pSH->GetOrigVfnPtrEntry(vfnptr); - - return origentry ? origentry : *reinterpret_cast(vfnptr); - } - - template struct GetPassInfo - { - static const int type = 0; - static const unsigned int flags = PassInfo::PassFlag_ByVal; - }; - - template struct GetPassInfo - { - static const int type = 0; - static const unsigned int flags = PassInfo::PassFlag_ByRef; - }; -} - -/************************************************************************/ -/* High level interface */ -/************************************************************************/ -#define META_RESULT_STATUS SH_GLOB_SHPTR->GetStatus() -#define META_RESULT_PREVIOUS SH_GLOB_SHPTR->GetPrevRes() -#define META_RESULT_ORIG_RET(type) *SourceHook::MacroRefHelpers::GetOrigRet(SH_GLOB_SHPTR) -#define META_RESULT_OVERRIDE_RET(type) *SourceHook::MacroRefHelpers::GetOverrideRet(SH_GLOB_SHPTR) -#define META_IFACEPTR(type) reinterpret_cast(SH_GLOB_SHPTR->GetIfacePtr()) - -#define SET_META_RESULT(result) SH_GLOB_SHPTR->SetRes(result) -#define RETURN_META(result) do { SET_META_RESULT(result); return; } while(0) -#define RETURN_META_VALUE(result, value) do { SET_META_RESULT(result); return (value); } while(0) - - -template -SourceHook::CallClass *SH_GET_CALLCLASS(T *p) -{ - return static_cast< SourceHook::CallClass *>(p); -} -#define SH_RELEASE_CALLCLASS(p) - -#define SH_GET_MCALLCLASS(p, size) reinterpret_cast(p) - -// only call these from the hook handlers directly! - -#define MAKE_NOREF_VALUE(rettype) \ - *reinterpret_cast< ::SourceHook::ReferenceUtil::pointer_type >(0) - -// If a hook on a function which returns a reference does not want to specify a return value, -// it can use this macro. -// ONLY USE THIS WITH MRES_IGNORED AND MRES_HANDLED !!! -#define RETURN_META_NOREF(result, rettype) \ - RETURN_META_VALUE(result, MAKE_NOREF_VALUE(rettype)) - -// Why take a memfuncptr instead of iface and func when we have to deduce the iface anyway now? -// Well, without it, there'd be no way to specify which overloaded version we want in _VALUE - -// SourceHook::SetOverrideRet is defined later. -#define RETURN_META_NEWPARAMS(result, memfuncptr, newparams) \ - do { \ - SET_META_RESULT(result); \ - SH_GLOB_SHPTR->DoRecall(); \ - (SourceHook::RecallGetIface(SH_GLOB_SHPTR, memfuncptr)->*(memfuncptr)) newparams; \ - RETURN_META(MRES_SUPERCEDE); \ - } while (0) - -#define RETURN_META_VALUE_NEWPARAMS(result, value, memfuncptr, newparams) \ - do { \ - SET_META_RESULT(result); \ - SH_GLOB_SHPTR->DoRecall(); \ - if ((result) >= MRES_OVERRIDE) \ - { \ - /* meh, set the override result here because we don't get a chance to return */ \ - /* before continuing the hook loop through the recall */ \ - SourceHook::SetOverrideResult(memfuncptr)(SH_GLOB_SHPTR, value); \ - } \ - RETURN_META_VALUE(MRES_SUPERCEDE, \ - (SourceHook::RecallGetIface(SH_GLOB_SHPTR, memfuncptr)->*(memfuncptr)) newparams); \ - } while (0) - -// :TODO: thisptroffs in MNEWPARAMS ?? - -#if SH_COMP == SH_COMP_MSVC - -#define SOUREHOOK__MNEWPARAMS_PREPAREMFP(hookname) \ - union \ - { \ - SH_MFHCls(hookname)::ECMFP mfp; \ - void *addr; \ - } u; \ - u.addr = (*reinterpret_cast(reinterpret_cast(thisptr) + SH_MFHCls(hookname)::ms_MFI.vtbloffs))[ \ - SH_MFHCls(hookname)::ms_MFI.vtblindex]; - -#elif SH_COMP == SH_COMP_GCC - -#define SOUREHOOK__MNEWPARAMS_PREPAREMFP(hookname) \ - union \ - { \ - SH_MFHCls(hookname)::ECMFP mfp; \ - struct \ - { \ - void *addr; \ - intptr_t adjustor; \ - } s; \ - } u; \ - u.s.addr = (*reinterpret_cast(reinterpret_cast(thisptr) + SH_MFHCls(hookname)::ms_MFI.vtbloffs))[ \ - SH_MFHCls(hookname)::ms_MFI.vtblindex]; \ - u.s.adjustor = 0; - -#endif - -#define RETURN_META_MNEWPARAMS(result, hookname, newparams) \ - do { \ - SET_META_RESULT(result); \ - SH_GLOB_SHPTR->DoRecall(); \ - SourceHook::EmptyClass *thisptr = reinterpret_cast(SH_GLOB_SHPTR->GetIfacePtr()); \ - (thisptr->*(__SoureceHook_FHM_GetRecallMFP##hookname(thisptr))) newparams; \ - RETURN_META(MRES_SUPERCEDE); \ - } while (0) - -#define RETURN_META_VALUE_MNEWPARAMS(result, value, hookname, newparams) \ - do { \ - SET_META_RESULT(result); \ - SH_GLOB_SHPTR->DoRecall(); \ - if ((result) >= MRES_OVERRIDE) \ - { \ - /* see RETURN_META_VALUE_NEWPARAMS */ \ - __SoureceHook_FHM_SetOverrideResult##hookname(SH_GLOB_SHPTR, value); \ - } \ - SourceHook::EmptyClass *thisptr = reinterpret_cast(SH_GLOB_SHPTR->GetIfacePtr()); \ - RETURN_META_VALUE(MRES_SUPERCEDE, (thisptr->*(__SoureceHook_FHM_GetRecallMFP##hookname(thisptr))) newparams); \ - } while (0) - - -#define SH_MANUALHOOK_RECONFIGURE(hookname, pvtblindex, pvtbloffs, pthisptroffs) \ - __SourceHook_FHM_Reconfigure##hookname(pvtblindex, pvtbloffs, pthisptroffs) - -#define SH_GET_ORIG_VFNPTR_ENTRY(inst, mfp) (SourceHook::GetOrigVfnPtrEntry(inst, mfp, SH_GLOB_SHPTR)) - -// New ADD / REMOVE macros. -#define SH_STATIC(func) fastdelegate::MakeDelegate(func) -#define SH_MEMBER(inst, func) fastdelegate::MakeDelegate(inst, func) - -#define SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, handler, post) \ - __SourceHook_FHAdd##ifacetype##ifacefunc((void*)SourceHook::implicit_cast(ifaceptr), \ - SourceHook::ISourceHook::Hook_Normal, post, handler) - -#define SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, handler, post) \ - __SourceHook_FHRemove##ifacetype##ifacefunc((void*)SourceHook::implicit_cast(ifaceptr), \ - post, handler) - -#define SH_ADD_MANUALHOOK(hookname, ifaceptr, handler, post) \ - __SourceHook_FHMAdd##hookname(reinterpret_cast(ifaceptr), \ - SourceHook::ISourceHook::Hook_Normal, post, handler) - -#define SH_REMOVE_MANUALHOOK(hookname, ifaceptr, handler, post) \ - __SourceHook_FHMRemove##hookname(reinterpret_cast(ifaceptr), post, handler) - -#define SH_ADD_VPHOOK(ifacetype, ifacefunc, ifaceptr, handler, post) \ - __SourceHook_FHAdd##ifacetype##ifacefunc((void*)SourceHook::implicit_cast(ifaceptr), \ - SourceHook::ISourceHook::Hook_VP, post, handler) - -#define SH_ADD_DVPHOOK(ifacetype, ifacefunc, ifaceptr, handler, post) \ - __SourceHook_FHAdd##ifacetype##ifacefunc((void*)SourceHook::implicit_cast(ifaceptr), \ - SourceHook::ISourceHook::Hook_DVP, post, handler) - -#define SH_ADD_MANUALVPHOOK(hookname, ifaceptr, handler, post) \ - __SourceHook_FHMAdd##hookname(reinterpret_cast(ifaceptr), SourceHook::ISourceHook::Hook_VP, post, handler) - -#define SH_ADD_MANUALDVPHOOK(hookname, ifaceptr, handler, post) \ - __SourceHook_FHMAdd##hookname(reinterpret_cast(ifaceptr), SourceHook::ISourceHook::Hook_DVP, post, handler) - -#define SH_REMOVE_HOOK_ID(hookid) \ - (SH_GLOB_SHPTR->RemoveHookByID(hookid)) - -// Old macros -// !! These are now deprecated. Instead, use one of these: -// SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post) -// SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(inst, func), post) - -#define SH_ADD_HOOK_STATICFUNC(ifacetype, ifacefunc, ifaceptr, handler, post) \ - SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post) -#define SH_ADD_HOOK_MEMFUNC(ifacetype, ifacefunc, ifaceptr, handler_inst, handler_func, post) \ - SH_ADD_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(handler_inst, handler_func), post) - -// SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post) -// SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(inst, func), post) - -#define SH_REMOVE_HOOK_STATICFUNC(ifacetype, ifacefunc, ifaceptr, handler, post) \ - SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_STATIC(handler), post) -#define SH_REMOVE_HOOK_MEMFUNC(ifacetype, ifacefunc, ifaceptr, handler_inst, handler_func, post) \ - SH_REMOVE_HOOK(ifacetype, ifacefunc, ifaceptr, SH_MEMBER(handler_inst, handler_func), post) - -// SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post) -// SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(inst, func), post) - -#define SH_ADD_MANUALHOOK_STATICFUNC(hookname, ifaceptr, handler, post) \ - SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post) -#define SH_ADD_MANUALHOOK_MEMFUNC(hookname, ifaceptr, handler_inst, handler_func, post) \ - SH_ADD_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(handler_inst, handler_func), post) - -// SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post) -// SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(inst, func), post) - -#define SH_REMOVE_MANUALHOOK_STATICFUNC(hookname, ifaceptr, handler, post) \ - SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_STATIC(handler), post) -#define SH_REMOVE_MANUALHOOK_MEMFUNC(hookname, ifaceptr, handler_inst, handler_func, post) \ - SH_REMOVE_MANUALHOOK(hookname, ifaceptr, SH_MEMBER(handler_inst, handler_func), post) - -#define SH_NOATTRIB - - - - -#if SH_COMP == SH_COMP_MSVC -# define SH_SETUP_MFP(mfp) \ - reinterpret_cast(&mfp)[0] = vfnptr_origentry; -#elif SH_COMP == SH_COMP_GCC -# define SH_SETUP_MFP(mfp) \ - reinterpret_cast(&mfp)[0] = vfnptr_origentry; \ - reinterpret_cast(&mfp)[1] = 0; -#else -# error Not supported yet. -#endif - -////////////////////////////////////////////////////////////////////////// -#define SH_FHCls(ift, iff, ov) __SourceHook_FHCls_##ift##iff##ov -#define SH_MFHCls(hookname) __SourceHook_MFHCls_##hookname - -#define SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr) \ - static int HookManPubFunc(bool store, ::SourceHook::IHookManagerInfo *hi) \ - { \ - using namespace ::SourceHook; \ - GetFuncInfo(funcptr, ms_MFI); \ - /* Verify interface version */ \ - if (SH_GLOB_SHPTR->GetIfaceVersion() != SH_IFACE_VERSION) \ - return 1; \ - if (SH_GLOB_SHPTR->GetImplVersion() < SH_IMPL_VERSION) \ - return 1; \ - if (store) \ - ms_HI = hi; \ - if (hi) \ - { \ - MemFuncInfo mfi = {true, -1, 0, 0}; \ - GetFuncInfo(&SH_FHCls(ifacetype,ifacefunc,overload)::Func, mfi); \ - hi->SetInfo(SH_HOOKMAN_VERSION, ms_MFI.vtbloffs, ms_MFI.vtblindex, &ms_Proto, \ - reinterpret_cast(reinterpret_cast(&ms_Inst) + mfi.vtbloffs)[mfi.vtblindex] ); \ - } \ - return 0; \ - } - -// It has to be possible to use the macros in namespaces -// -> So we need to access and extend the global SourceHook namespace -// We use a namespace alias for this -#define SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, funcptr) \ - struct SH_FHCls(ifacetype,ifacefunc,overload) \ - { \ - static SH_FHCls(ifacetype,ifacefunc,overload) ms_Inst; \ - static ::SourceHook::MemFuncInfo ms_MFI; \ - static ::SourceHook::IHookManagerInfo *ms_HI; \ - static ::SourceHook::ProtoInfo ms_Proto; \ - SHINT_MAKE_HOOKMANPUBFUNC(ifacetype, ifacefunc, overload, funcptr) - -#define SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, funcptr) \ - }; \ - SH_FHCls(ifacetype,ifacefunc,overload) SH_FHCls(ifacetype,ifacefunc,overload)::ms_Inst; \ - ::SourceHook::MemFuncInfo SH_FHCls(ifacetype,ifacefunc,overload)::ms_MFI; \ - ::SourceHook::IHookManagerInfo *SH_FHCls(ifacetype,ifacefunc,overload)::ms_HI; \ - int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ - SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \ - { \ - using namespace ::SourceHook; \ - MemFuncInfo mfi = {true, -1, 0, 0}; \ - GetFuncInfo(funcptr, mfi); \ - if (mfi.thisptroffs < 0 || !mfi.isVirtual) \ - return false; /* No non-virtual functions / virtual inheritance supported */ \ - \ - return SH_GLOB_SHPTR->AddHook(SH_GLOB_PLUGPTR, mode, \ - iface, mfi.thisptroffs, SH_FHCls(ifacetype,ifacefunc,overload)::HookManPubFunc, \ - new SH_FHCls(ifacetype,ifacefunc,overload)::CMyDelegateImpl(handler), post); \ - } \ - bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ - SH_FHCls(ifacetype,ifacefunc,overload)::FD handler) \ - { \ - using namespace ::SourceHook; \ - MemFuncInfo mfi = {true, -1, 0, 0}; \ - GetFuncInfo(funcptr, mfi); \ - SH_FHCls(ifacetype,ifacefunc,overload)::CMyDelegateImpl tmp(handler); \ - return SH_GLOB_SHPTR->RemoveHook(SH_GLOB_PLUGPTR, iface, mfi.thisptroffs, \ - SH_FHCls(ifacetype,ifacefunc,overload)::HookManPubFunc, &tmp, post); \ - } \ - -#define SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, pvtbloffs, pvtblidx, pthisptroffs) \ - struct SH_MFHCls(hookname) \ - { \ - static SH_MFHCls(hookname) ms_Inst; \ - static ::SourceHook::MemFuncInfo ms_MFI; \ - static ::SourceHook::IHookManagerInfo *ms_HI; \ - static ::SourceHook::ProtoInfo ms_Proto; \ - \ - SH_MFHCls(hookname)() \ - { \ - ms_MFI.isVirtual = true; \ - ms_MFI.thisptroffs = pthisptroffs; \ - ms_MFI.vtblindex = pvtblidx; \ - ms_MFI.vtbloffs = pvtbloffs; \ - } \ - static int HookManPubFunc(bool store, ::SourceHook::IHookManagerInfo *hi) \ - { \ - using namespace ::SourceHook; \ - /* Verify interface version */ \ - if (SH_GLOB_SHPTR->GetIfaceVersion() != SH_IFACE_VERSION) \ - return 1; \ - if (SH_GLOB_SHPTR->GetImplVersion() < SH_IMPL_VERSION) \ - return 1; \ - if (store) \ - ms_HI = hi; \ - if (hi) \ - { \ - MemFuncInfo mfi = {true, -1, 0, 0}; \ - GetFuncInfo(&SH_MFHCls(hookname)::Func, mfi); \ - hi->SetInfo(SH_HOOKMAN_VERSION, ms_MFI.vtbloffs, ms_MFI.vtblindex, &ms_Proto, \ - reinterpret_cast(reinterpret_cast(&ms_Inst) + mfi.vtbloffs)[mfi.vtblindex] ); \ - } \ - return 0; \ - } - -#define SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, pvtbloffs, pvtblidx, pthisptroffs) \ - }; \ - SH_MFHCls(hookname) SH_MFHCls(hookname)::ms_Inst; \ - ::SourceHook::MemFuncInfo SH_MFHCls(hookname)::ms_MFI; \ - ::SourceHook::IHookManagerInfo *SH_MFHCls(hookname)::ms_HI; \ - int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ - SH_MFHCls(hookname)::FD handler) \ - { \ - return SH_GLOB_SHPTR->AddHook(SH_GLOB_PLUGPTR, mode, \ - iface, pthisptroffs, SH_MFHCls(hookname)::HookManPubFunc, \ - new SH_MFHCls(hookname)::CMyDelegateImpl(handler), post); \ - } \ - bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ - SH_MFHCls(hookname)::FD handler) \ - { \ - SH_MFHCls(hookname)::CMyDelegateImpl tmp(handler); \ - return SH_GLOB_SHPTR->RemoveHook(SH_GLOB_PLUGPTR, iface, pthisptroffs, \ - SH_MFHCls(hookname)::HookManPubFunc, &tmp, post); \ - } \ - SH_MFHCls(hookname)::ECMFP __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) \ - { \ - SOUREHOOK__MNEWPARAMS_PREPAREMFP(hookname); \ - return u.mfp; \ - } \ - SH_MFHCls(hookname)::CallEC __SoureceHook_FHM_SHCall##hookname(void *ptr) \ - { \ - SH_MFHCls(hookname)::ECMFP mfp; \ - void *vfnptr = reinterpret_cast( \ - *reinterpret_cast( (reinterpret_cast(ptr) + SH_MFHCls(hookname)::ms_MFI.thisptroffs + SH_MFHCls(hookname)::ms_MFI.vtbloffs) ) + SH_MFHCls(hookname)::ms_MFI.vtblindex); \ - /* patch mfp */ \ - *reinterpret_cast(&mfp) = *reinterpret_cast(vfnptr); \ - if (sizeof(mfp) == 2*sizeof(void*)) /* gcc */ \ - *(reinterpret_cast(&mfp) + 1) = 0; \ - return SH_MFHCls(hookname)::CallEC(reinterpret_cast< ::SourceHook::EmptyClass* >(ptr), mfp, vfnptr, SH_GLOB_SHPTR); \ - } \ - void __SourceHook_FHM_Reconfigure##hookname(int p_vtblindex, int p_vtbloffs, int p_thisptroffs) \ - { \ - SH_GLOB_SHPTR->RemoveHookManager(SH_GLOB_PLUGPTR, SH_MFHCls(hookname)::HookManPubFunc); \ - SH_MFHCls(hookname)::ms_MFI.thisptroffs = p_thisptroffs; \ - SH_MFHCls(hookname)::ms_MFI.vtblindex = p_vtblindex; \ - SH_MFHCls(hookname)::ms_MFI.vtbloffs = p_vtbloffs; \ - } - -#define SH_SETUPCALLS(rettype, paramtypes, params) \ - /* 1) Set up */ \ - using namespace ::SourceHook; \ - void *ourvfnptr = reinterpret_cast( \ - *reinterpret_cast(reinterpret_cast(this) + ms_MFI.vtbloffs) + ms_MFI.vtblindex); \ - void *vfnptr_origentry; \ - \ - META_RES status = MRES_IGNORED; \ - META_RES prev_res; \ - META_RES cur_res; \ - \ - typedef ReferenceCarrier< rettype >::type my_rettype; \ - my_rettype orig_ret; \ - my_rettype override_ret; \ - my_rettype plugin_ret; \ - IMyDelegate *iter; \ - IHookContext *pContext = SH_GLOB_SHPTR->SetupHookLoop(ms_HI, ourvfnptr, reinterpret_cast(this), \ - &vfnptr_origentry, &status, &prev_res, &cur_res, &orig_ret, &override_ret); - -#define SH_CALL_HOOKS(post, params) \ - prev_res = MRES_IGNORED; \ - while ( (iter = static_cast(pContext->GetNext())) ) \ - { \ - cur_res = MRES_IGNORED; \ - plugin_ret = iter->Call params; \ - prev_res = cur_res; \ - if (cur_res > status) \ - status = cur_res; \ - if (cur_res >= MRES_OVERRIDE) \ - *reinterpret_cast(pContext->GetOverrideRetPtr()) = plugin_ret; \ - } - -#define SH_CALL_ORIG(rettype, paramtypes, params) \ - if (status != MRES_SUPERCEDE && pContext->ShouldCallOrig()) \ - { \ - rettype (EmptyClass::*mfp)paramtypes; \ - SH_SETUP_MFP(mfp); \ - orig_ret = (reinterpret_cast(this)->*mfp)params; \ - } \ - else \ - orig_ret = override_ret; /* :TODO: ??? : use pContext->GetOverrideRetPtr() or not? */ - -#define SH_RETURN() \ - const my_rettype *retptr = reinterpret_cast( \ - (status >= MRES_OVERRIDE) ? pContext->GetOverrideRetPtr() : pContext->GetOrigRetPtr()); \ - SH_GLOB_SHPTR->EndContext(pContext); \ - return *retptr; - -#define SH_HANDLEFUNC(paramtypes, params, rettype) \ - SH_SETUPCALLS(rettype, paramtypes, params) \ - SH_CALL_HOOKS(pre, params) \ - SH_CALL_ORIG(rettype, paramtypes, params) \ - SH_CALL_HOOKS(post, params) \ - SH_RETURN() - -////////////////////////////////////////////////////////////////////////// -#define SH_SETUPCALLS_void(paramtypes, params) \ - /* 1) Set up */ \ - using namespace ::SourceHook; \ - void *ourvfnptr = reinterpret_cast( \ - *reinterpret_cast(reinterpret_cast(this) + ms_MFI.vtbloffs) + ms_MFI.vtblindex); \ - void *vfnptr_origentry; \ - \ - META_RES status = MRES_IGNORED; \ - META_RES prev_res; \ - META_RES cur_res; \ - \ - IMyDelegate *iter; \ - IHookContext *pContext = SH_GLOB_SHPTR->SetupHookLoop(ms_HI, ourvfnptr, reinterpret_cast(this), \ - &vfnptr_origentry, &status, &prev_res, &cur_res, NULL, NULL); - -#define SH_CALL_HOOKS_void(post, params) \ - prev_res = MRES_IGNORED; \ - while ( (iter = static_cast(pContext->GetNext())) ) \ - { \ - cur_res = MRES_IGNORED; \ - iter->Call params; \ - prev_res = cur_res; \ - if (cur_res > status) \ - status = cur_res; \ - } - -#define SH_CALL_ORIG_void(paramtypes, params) \ - if (status != MRES_SUPERCEDE && pContext->ShouldCallOrig()) \ - { \ - void (EmptyClass::*mfp)paramtypes; \ - SH_SETUP_MFP(mfp); \ - (reinterpret_cast(this)->*mfp)params; \ - } - -#define SH_RETURN_void() \ - SH_GLOB_SHPTR->EndContext(pContext); - -#define SH_HANDLEFUNC_void(paramtypes, params) \ - SH_SETUPCALLS_void(paramtypes, params) \ - SH_CALL_HOOKS_void(pre, params) \ - SH_CALL_ORIG_void(paramtypes, params) \ - SH_CALL_HOOKS_void(post, params) \ - SH_RETURN_void() - - -// Special vafmt handlers -// :TODO: what -#define SH_HANDLEFUNC_vafmt(paramtypes, params_orig, params_plug, rettype) \ - SH_SETUPCALLS(rettype, paramtypes, params_orig) \ - SH_CALL_HOOKS(pre, params_plug) \ - SH_CALL_ORIG(rettype, paramtypes, params_orig) \ - SH_CALL_HOOKS(post, params_plug) \ - SH_RETURN() - -#define SH_HANDLEFUNC_void_vafmt(paramtypes, params_orig, params_plug) \ - SH_SETUPCALLS_void(paramtypes, params_orig) \ - SH_CALL_HOOKS_void(pre, params_plug) \ - SH_CALL_ORIG_void(paramtypes, params_orig) \ - SH_CALL_HOOKS_void(post, params_plug) \ - SH_RETURN_void() - -////////////////////////////////////////////////////////////////////////// - -#define MAKE_DELEG(ret_type, params_decl, params_pass) \ - struct IMyDelegate : ::SourceHook::ISHDelegate { virtual ret_type Call params_decl = 0; }; \ - struct CMyDelegateImpl : IMyDelegate \ - { \ - FD m_Deleg; \ - CMyDelegateImpl(FD deleg) : m_Deleg(deleg) {} \ - ret_type Call params_decl { return m_Deleg params_pass; } \ - void DeleteThis() { delete this; } \ - bool IsEqual(ISHDelegate *pOtherDeleg) { return m_Deleg == static_cast(pOtherDeleg)->m_Deleg; } \ - }; - -#define MAKE_DELEG_void(params_decl, params_pass) \ - struct IMyDelegate : ::SourceHook::ISHDelegate { virtual void Call params_decl = 0; }; \ - struct CMyDelegateImpl : IMyDelegate \ - { \ - FD m_Deleg; \ - CMyDelegateImpl(FD deleg) : m_Deleg(deleg) {} \ - void Call params_decl { m_Deleg params_pass; } \ - void DeleteThis() { delete this; } \ - bool IsEqual(ISHDelegate *pOtherDeleg) { return m_Deleg == static_cast(pOtherDeleg)->m_Deleg; } \ - }; - -// GetPassInfo -> easier access. __SH_GPI generates a SourceHook::PassInfo instance. -#define __SH_GPI(tt) { sizeof(tt), ::SourceHook::GetPassInfo< tt >::type, ::SourceHook::GetPassInfo< tt >::flags } -// Extra pass info V2 -#define __SH_EPI { 0, 0, 0, 0 } - -#define __SH_VAFMT_SEQ(fmt, buf) \ - char buf[::SourceHook::STRBUF_LEN]; \ - va_list ap; \ - va_start(ap, fmt); \ - vsnprintf(buf, sizeof(buf), fmt, ap); \ - buf[sizeof(buf) - 1] = 0; \ - va_end(ap); - -// Helper for MANUALEXTERN. -# define SHINT_DECL_MANUALEXTERN_impl_value(hookname, rettype) \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype res); - -// Helpers for transforming X(__VA_ARGS__, Y) -> Y when __VA_ARGS__ is empty. -#define SHINT_COLLAPSE0(_T, ...) __VA_ARGS__ - -// -// MSVC will automatically remove a trailing comma if __VA_ARGS__ is empty. GCC requires using ## to do this. -// -#if defined(_MSC_VER) -# define SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, ...) \ - int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ - fastdelegate::FastDelegate handler); \ - bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ - fastdelegate::FastDelegate handler); - -# define SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, void, __VA_ARGS__) - -# define SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, __VA_ARGS__, const char *) - -# define SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, void, __VA_ARGS__, const char *) - -// Helpers for MANUALEXTERN. -# define SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, ...) \ - int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ - fastdelegate::FastDelegate handler); \ - bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ - fastdelegate::FastDelegate handler); \ - void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); - -# define SHINT_DECL_MANUALEXTERN_impl(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, __VA_ARGS__) \ - rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(__VA_ARGS__); \ - SourceHook::ExecutableClassN __SoureceHook_FHM_SHCall##hookname(void *ptr); - -# define SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, __VA_ARGS__, const char *) \ - rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(SHINT_COLLAPSE0(void, __VA_ARGS__, const char *, ...)); \ - SourceHook::ExecutableClassN __SoureceHook_FHM_SHCall##hookname(void *ptr); - -# define SH_DECL_MANUALEXTERN(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl(hookname, rettype, __VA_ARGS__) \ - SHINT_DECL_MANUALEXTERN_impl_value(hookname, rettype) - -# define SH_DECL_MANUALEXTERN_void(hookname, ...) \ - SHINT_DECL_MANUALEXTERN_impl(hookname, void, __VA_ARGS__) - -# define SH_DECL_MANUALEXTERN_void_vafmt(hookname, ...) \ - SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, void, __VA_ARGS__) - -# define SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, rettype, __VA_ARGS__) \ - SHINT_DECL_MANUALEXTERN_impl_value(hookname, rettype) - -// -// GCC Implementation. -// -#else -# define SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, ...) \ - int __SourceHook_FHAdd##ifacetype##ifacefunc(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ - fastdelegate::FastDelegate handler); \ - bool __SourceHook_FHRemove##ifacetype##ifacefunc(void *iface, bool post, \ - fastdelegate::FastDelegate handler); - -# define SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, void, ##__VA_ARGS__) - -# define SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, ##__VA_ARGS__, const char *) - -# define SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, ...) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, void, ##__VA_ARGS__, const char *) - -// Helpers for MANUALEXTERN. -# define SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, ...) \ - int __SourceHook_FHMAdd##hookname(void *iface, ::SourceHook::ISourceHook::AddHookMode mode, bool post, \ - fastdelegate::FastDelegate handler); \ - bool __SourceHook_FHMRemove##hookname(void *iface, bool post, \ - fastdelegate::FastDelegate handler); \ - void __SourceHook_FHM_Reconfigure##hookname(int pvtblindex, int pvtbloffs, int pthisptroffs); - -# define SHINT_DECL_MANUALEXTERN_impl(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, ##__VA_ARGS__) \ - rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(__VA_ARGS__); \ - SourceHook::ExecutableClassN __SoureceHook_FHM_SHCall##hookname(void *ptr); - -# define SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_shared(hookname, rettype, ##__VA_ARGS__, const char *) \ - rettype(::SourceHook::EmptyClass::* __SoureceHook_FHM_GetRecallMFP##hookname(::SourceHook::EmptyClass *thisptr) )(SHINT_COLLAPSE0(void, ##__VA_ARGS__, const char *, ...)); \ - SourceHook::ExecutableClassN __SoureceHook_FHM_SHCall##hookname(void *ptr); - -# define SH_DECL_MANUALEXTERN(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl(hookname, rettype, ##__VA_ARGS__) \ - SHINT_DECL_MANUALEXTERN_impl_value(hookname, rettype) - -# define SH_DECL_MANUALEXTERN_void(hookname, ...) \ - SHINT_DECL_MANUALEXTERN_impl(hookname, void, ##__VA_ARGS__) - -# define SH_DECL_MANUALEXTERN_void_vafmt(hookname, ...) \ - SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, void, ##__VA_ARGS__) - -# define SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, ...) \ - SHINT_DECL_MANUALEXTERN_impl_vafmt(hookname, rettype, ##__VA_ARGS__) \ - SHINT_DECL_MANUALEXTERN_impl_value(hookname, rettype) - -#endif - -// Compatibility wrappers around modern variadic macros. - -// ********* Support for 0 arguments ********* -#define SH_DECL_HOOK0(ifacetype, ifacefunc, attr, overload, rettype) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (), ()); \ - virtual rettype Func() \ - { SH_HANDLEFUNC((), (), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0} }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 0, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN0(ifacetype, ifacefunc, attr, overload, rettype) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype) - -#define SH_DECL_HOOK0_void(ifacetype, ifacefunc, attr, overload) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((), ()); \ - virtual void Func() \ - { SH_HANDLEFUNC_void((), ()); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0} }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 0, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN0_void(ifacetype, ifacefunc, attr, overload) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload) - -#define SH_DECL_HOOK0_vafmt(ifacetype, ifacefunc, attr, overload, rettype) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (const char *px), (px)); \ - virtual rettype Func( const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((const char *, ...), ("%s", buf), (buf), rettype); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0} }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 0, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN0_vafmt(ifacetype, ifacefunc, attr, overload, rettype) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype) - -#define SH_DECL_HOOK0_void_vafmt(ifacetype, ifacefunc, attr, overload) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((const char *px), (px)); \ - virtual void Func(const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((const char *, ...), ("%s", buf), (buf)); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0} }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 0, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN0_void_vafmt(ifacetype, ifacefunc, attr, overload) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload) - -#define SH_DECL_MANUALHOOK0(hookname, vtblidx, vtbloffs, thisptroffs, rettype) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (), ()); \ - virtual rettype Func() \ - { SH_HANDLEFUNC((), (), rettype); } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0} }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 0, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN0(hookname, rettype) \ - SH_DECL_MANUALEXTERN(hookname, rettype) - -#define SH_DECL_MANUALHOOK0_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (const char *px), (px)); \ - virtual rettype Func(const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((const char *, ...), ("%s", buf), (buf), rettype); \ - } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, const char * > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0} }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 0, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN0_vafmt(hookname, rettype) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype) - -#define SH_DECL_MANUALHOOK0_void(hookname, vtblidx, vtbloffs, thisptroffs) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((), ()); \ - virtual void Func() \ - { SH_HANDLEFUNC_void((), ()); } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(); \ - typedef SourceHook::ExecutableClassN CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0} }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 0, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN0_void(hookname) \ - SH_DECL_MANUALEXTERN_void(hookname) - -#define SH_DECL_MANUALHOOK0_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((const char *px), (px)); \ - virtual void Func(const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((const char *, ...), ("%s", buf), (buf)); \ - } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, const char * > CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0} }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 0, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN0_void_vafmt(hookname) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname) - - -// ********* Support for 1 arguments ********* -#define SH_DECL_HOOK1(ifacetype, ifacefunc, attr, overload, rettype, param1) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1), (p1)); \ - virtual rettype Func(param1 p1) \ - { SH_HANDLEFUNC((param1), (p1), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 1, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN1(ifacetype, ifacefunc, attr, overload, rettype, param1) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1) - -#define SH_DECL_HOOK1_void(ifacetype, ifacefunc, attr, overload, param1) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1), (p1)); \ - virtual void Func(param1 p1) \ - { SH_HANDLEFUNC_void((param1), (p1)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0},__SH_GPI(param1) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 1, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN1_void(ifacetype, ifacefunc, attr, overload, param1) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1) - -#define SH_DECL_HOOK1_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, const char *px), (p1, px)); \ - virtual rettype Func(param1 p1 , const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, const char *, ...), (p1, "%s", buf), (p1, buf), rettype); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 1, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN1_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1) - -#define SH_DECL_HOOK1_void_vafmt(ifacetype, ifacefunc, attr, overload, param1) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, const char *px), (p1, px)); \ - virtual void Func(param1 p1, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, const char *, ...), (p1, "%s", buf), (p1, buf)); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 1, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN1_void_vafmt(ifacetype, ifacefunc, attr, overload, param1) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1) - -#define SH_DECL_MANUALHOOK1(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1), (p1)); \ - virtual rettype Func(param1 p1) \ - { SH_HANDLEFUNC((param1), (p1), rettype); } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1 > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 1, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN1(hookname, rettype, param1) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1) - -#define SH_DECL_MANUALHOOK1_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, const char *px), (p1, px)); \ - virtual rettype Func(param1 p1, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, const char *, ...), (p1, "%s", buf), (p1, buf), rettype); \ - } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, const char * > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 1, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN1_vafmt(hookname, rettype, param1) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1) - -#define SH_DECL_MANUALHOOK1_void(hookname, vtblidx, vtbloffs, thisptroffs, param1) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1), (p1)); \ - virtual void Func(param1 p1) \ - { SH_HANDLEFUNC_void((param1), (p1)); } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1); \ - typedef SourceHook::ExecutableClassN CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 1, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN1_void(hookname, param1) \ - SH_DECL_MANUALEXTERN_void(hookname, param1) - -#define SH_DECL_MANUALHOOK1_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, const char *px), (p1, px)); \ - virtual void Func(param1 p1, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, const char *, ...), (p1, "%s", buf), (p1, buf)); \ - } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, const char * > CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 1, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN1_void_vafmt(hookname, param1) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1) - - -// ********* Support for 2 arguments ********* -#define SH_DECL_HOOK2(ifacetype, ifacefunc, attr, overload, rettype, param1, param2) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2), (p1, p2)); \ - virtual rettype Func(param1 p1, param2 p2) \ - { SH_HANDLEFUNC((param1, param2), (p1, p2), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 2, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN2(ifacetype, ifacefunc, attr, overload, rettype, param1, param2) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2) - -#define SH_DECL_HOOK2_void(ifacetype, ifacefunc, attr, overload, param1, param2) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2), (p1, p2)); \ - virtual void Func(param1 p1, param2 p2) \ - { SH_HANDLEFUNC_void((param1, param2), (p1, p2)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0},__SH_GPI(param1),__SH_GPI(param2) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 2, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN2_void(ifacetype, ifacefunc, attr, overload, param1, param2) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2) - -#define SH_DECL_HOOK2_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, const char *px), (p1, p2, px)); \ - virtual rettype Func(param1 p1, param2 p2 , const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, const char *, ...), (p1, p2, "%s", buf), (p1, p2, buf), rettype); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 2, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN2_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2) - -#define SH_DECL_HOOK2_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, const char *px), (p1, p2, px)); \ - virtual void Func(param1 p1, param2 p2, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, const char *, ...), (p1, p2, "%s", buf), (p1, p2, buf)); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 2, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN2_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2) - -#define SH_DECL_MANUALHOOK2(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2), (p1, p2)); \ - virtual rettype Func(param1 p1, param2 p2) \ - { SH_HANDLEFUNC((param1, param2), (p1, p2), rettype); } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2 > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 2, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN2(hookname, rettype, param1, param2) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2) - -#define SH_DECL_MANUALHOOK2_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, const char *px), (p1, p2, px)); \ - virtual rettype Func(param1 p1, param2 p2, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, const char *, ...), (p1, p2, "%s", buf), (p1, p2, buf), rettype); \ - } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, const char * > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 2, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN2_vafmt(hookname, rettype, param1, param2) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2) - -#define SH_DECL_MANUALHOOK2_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2), (p1, p2)); \ - virtual void Func(param1 p1, param2 p2) \ - { SH_HANDLEFUNC_void((param1, param2), (p1, p2)); } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2); \ - typedef SourceHook::ExecutableClassN CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 2, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN2_void(hookname, param1, param2) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2) - -#define SH_DECL_MANUALHOOK2_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, const char *px), (p1, p2, px)); \ - virtual void Func(param1 p1, param2 p2, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, const char *, ...), (p1, p2, "%s", buf), (p1, p2, buf)); \ - } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, const char * > CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 2, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN2_void_vafmt(hookname, param1, param2) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2) - - -// ********* Support for 3 arguments ********* -#define SH_DECL_HOOK3(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3), (p1, p2, p3)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3) \ - { SH_HANDLEFUNC((param1, param2, param3), (p1, p2, p3), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 3, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN3(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3) - -#define SH_DECL_HOOK3_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3), (p1, p2, p3)); \ - virtual void Func(param1 p1, param2 p2, param3 p3) \ - { SH_HANDLEFUNC_void((param1, param2, param3), (p1, p2, p3)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0},__SH_GPI(param1),__SH_GPI(param2),__SH_GPI(param3) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 3, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN3_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3) - -#define SH_DECL_HOOK3_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, const char *px), (p1, p2, p3, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3 , const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, const char *, ...), (p1, p2, p3, "%s", buf), (p1, p2, p3, buf), rettype); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 3, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN3_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3) - -#define SH_DECL_HOOK3_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, const char *px), (p1, p2, p3, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, const char *, ...), (p1, p2, p3, "%s", buf), (p1, p2, p3, buf)); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 3, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN3_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3) - -#define SH_DECL_MANUALHOOK3(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3), (p1, p2, p3)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3) \ - { SH_HANDLEFUNC((param1, param2, param3), (p1, p2, p3), rettype); } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3 > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 3, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN3(hookname, rettype, param1, param2, param3) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3) - -#define SH_DECL_MANUALHOOK3_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, const char *px), (p1, p2, p3, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, const char *, ...), (p1, p2, p3, "%s", buf), (p1, p2, p3, buf), rettype); \ - } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, const char * > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 3, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN3_vafmt(hookname, rettype, param1, param2, param3) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3) - -#define SH_DECL_MANUALHOOK3_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3), (p1, p2, p3)); \ - virtual void Func(param1 p1, param2 p2, param3 p3) \ - { SH_HANDLEFUNC_void((param1, param2, param3), (p1, p2, p3)); } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3); \ - typedef SourceHook::ExecutableClassN CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 3, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN3_void(hookname, param1, param2, param3) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3) - -#define SH_DECL_MANUALHOOK3_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, const char *px), (p1, p2, p3, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, const char *, ...), (p1, p2, p3, "%s", buf), (p1, p2, p3, buf)); \ - } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, const char * > CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 3, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN3_void_vafmt(hookname, param1, param2, param3) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3) - - -// ********* Support for 4 arguments ********* -#define SH_DECL_HOOK4(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4), (p1, p2, p3, p4)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4) \ - { SH_HANDLEFUNC((param1, param2, param3, param4), (p1, p2, p3, p4), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 4, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN4(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4) - -#define SH_DECL_HOOK4_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4), (p1, p2, p3, p4)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4), (p1, p2, p3, p4)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0},__SH_GPI(param1),__SH_GPI(param2),__SH_GPI(param3),__SH_GPI(param4) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 4, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN4_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4) - -#define SH_DECL_HOOK4_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, const char *px), (p1, p2, p3, p4, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4 , const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, const char *, ...), (p1, p2, p3, p4, "%s", buf), (p1, p2, p3, p4, buf), rettype); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 4, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN4_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4) - -#define SH_DECL_HOOK4_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, const char *px), (p1, p2, p3, p4, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, const char *, ...), (p1, p2, p3, p4, "%s", buf), (p1, p2, p3, p4, buf)); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 4, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN4_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4) - -#define SH_DECL_MANUALHOOK4(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4), (p1, p2, p3, p4)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4) \ - { SH_HANDLEFUNC((param1, param2, param3, param4), (p1, p2, p3, p4), rettype); } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4 > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 4, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN4(hookname, rettype, param1, param2, param3, param4) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4) - -#define SH_DECL_MANUALHOOK4_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, const char *px), (p1, p2, p3, p4, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, const char *, ...), (p1, p2, p3, p4, "%s", buf), (p1, p2, p3, p4, buf), rettype); \ - } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, const char * > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 4, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN4_vafmt(hookname, rettype, param1, param2, param3, param4) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4) - -#define SH_DECL_MANUALHOOK4_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4), (p1, p2, p3, p4)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4), (p1, p2, p3, p4)); } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4); \ - typedef SourceHook::ExecutableClassN CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 4, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN4_void(hookname, param1, param2, param3, param4) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4) - -#define SH_DECL_MANUALHOOK4_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, const char *px), (p1, p2, p3, p4, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, const char *, ...), (p1, p2, p3, p4, "%s", buf), (p1, p2, p3, p4, buf)); \ - } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, const char * > CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 4, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN4_void_vafmt(hookname, param1, param2, param3, param4) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4) - - -// ********* Support for 5 arguments ********* -#define SH_DECL_HOOK5(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5), (p1, p2, p3, p4, p5)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5), (p1, p2, p3, p4, p5), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 5, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN5(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5) - -#define SH_DECL_HOOK5_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5), (p1, p2, p3, p4, p5)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5), (p1, p2, p3, p4, p5)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0},__SH_GPI(param1),__SH_GPI(param2),__SH_GPI(param3),__SH_GPI(param4),__SH_GPI(param5) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 5, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN5_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5) - -#define SH_DECL_HOOK5_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, const char *px), (p1, p2, p3, p4, p5, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5 , const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, const char *, ...), (p1, p2, p3, p4, p5, "%s", buf), (p1, p2, p3, p4, p5, buf), rettype); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 5, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN5_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5) - -#define SH_DECL_HOOK5_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, const char *px), (p1, p2, p3, p4, p5, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, const char *, ...), (p1, p2, p3, p4, p5, "%s", buf), (p1, p2, p3, p4, p5, buf)); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 5, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN5_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5) - -#define SH_DECL_MANUALHOOK5(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5), (p1, p2, p3, p4, p5)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5), (p1, p2, p3, p4, p5), rettype); } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5 > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 5, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN5(hookname, rettype, param1, param2, param3, param4, param5) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5) - -#define SH_DECL_MANUALHOOK5_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, const char *px), (p1, p2, p3, p4, p5, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, const char *, ...), (p1, p2, p3, p4, p5, "%s", buf), (p1, p2, p3, p4, p5, buf), rettype); \ - } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, const char * > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 5, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN5_vafmt(hookname, rettype, param1, param2, param3, param4, param5) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5) - -#define SH_DECL_MANUALHOOK5_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5), (p1, p2, p3, p4, p5)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5), (p1, p2, p3, p4, p5)); } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5); \ - typedef SourceHook::ExecutableClassN CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 5, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN5_void(hookname, param1, param2, param3, param4, param5) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5) - -#define SH_DECL_MANUALHOOK5_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, const char *px), (p1, p2, p3, p4, p5, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, const char *, ...), (p1, p2, p3, p4, p5, "%s", buf), (p1, p2, p3, p4, p5, buf)); \ - } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, const char * > CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 5, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN5_void_vafmt(hookname, param1, param2, param3, param4, param5) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5) - - -// ********* Support for 6 arguments ********* -#define SH_DECL_HOOK6(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6), (p1, p2, p3, p4, p5, p6)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6), (p1, p2, p3, p4, p5, p6), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 6, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN6(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6) - -#define SH_DECL_HOOK6_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6), (p1, p2, p3, p4, p5, p6)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6), (p1, p2, p3, p4, p5, p6)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0},__SH_GPI(param1),__SH_GPI(param2),__SH_GPI(param3),__SH_GPI(param4),__SH_GPI(param5),__SH_GPI(param6) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 6, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN6_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6) - -#define SH_DECL_HOOK6_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, const char *px), (p1, p2, p3, p4, p5, p6, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6 , const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, const char *, ...), (p1, p2, p3, p4, p5, p6, "%s", buf), (p1, p2, p3, p4, p5, p6, buf), rettype); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 6, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN6_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6) - -#define SH_DECL_HOOK6_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, const char *px), (p1, p2, p3, p4, p5, p6, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, const char *, ...), (p1, p2, p3, p4, p5, p6, "%s", buf), (p1, p2, p3, p4, p5, p6, buf)); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 6, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN6_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6) - -#define SH_DECL_MANUALHOOK6(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6), (p1, p2, p3, p4, p5, p6)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6), (p1, p2, p3, p4, p5, p6), rettype); } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6 > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 6, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN6(hookname, rettype, param1, param2, param3, param4, param5, param6) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6) - -#define SH_DECL_MANUALHOOK6_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, const char *px), (p1, p2, p3, p4, p5, p6, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, const char *, ...), (p1, p2, p3, p4, p5, p6, "%s", buf), (p1, p2, p3, p4, p5, p6, buf), rettype); \ - } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, const char * > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 6, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN6_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6) - -#define SH_DECL_MANUALHOOK6_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6), (p1, p2, p3, p4, p5, p6)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6), (p1, p2, p3, p4, p5, p6)); } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6); \ - typedef SourceHook::ExecutableClassN CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 6, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN6_void(hookname, param1, param2, param3, param4, param5, param6) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6) - -#define SH_DECL_MANUALHOOK6_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, const char *px), (p1, p2, p3, p4, p5, p6, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, const char *, ...), (p1, p2, p3, p4, p5, p6, "%s", buf), (p1, p2, p3, p4, p5, p6, buf)); \ - } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, const char * > CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 6, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN6_void_vafmt(hookname, param1, param2, param3, param4, param5, param6) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6) - - -// ********* Support for 7 arguments ********* -#define SH_DECL_HOOK7(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7), (p1, p2, p3, p4, p5, p6, p7)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7), (p1, p2, p3, p4, p5, p6, p7), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 7, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN7(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7) - -#define SH_DECL_HOOK7_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7), (p1, p2, p3, p4, p5, p6, p7)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7), (p1, p2, p3, p4, p5, p6, p7)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0},__SH_GPI(param1),__SH_GPI(param2),__SH_GPI(param3),__SH_GPI(param4),__SH_GPI(param5),__SH_GPI(param6),__SH_GPI(param7) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 7, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN7_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7) - -#define SH_DECL_HOOK7_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, const char *px), (p1, p2, p3, p4, p5, p6, p7, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7 , const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, buf), rettype); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 7, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN7_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7) - -#define SH_DECL_HOOK7_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, const char *px), (p1, p2, p3, p4, p5, p6, p7, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, buf)); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 7, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN7_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7) - -#define SH_DECL_MANUALHOOK7(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7), (p1, p2, p3, p4, p5, p6, p7)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7), (p1, p2, p3, p4, p5, p6, p7), rettype); } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7 > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 7, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN7(hookname, rettype, param1, param2, param3, param4, param5, param6, param7) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7) - -#define SH_DECL_MANUALHOOK7_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, const char *px), (p1, p2, p3, p4, p5, p6, p7, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, buf), rettype); \ - } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, const char * > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 7, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN7_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7) - -#define SH_DECL_MANUALHOOK7_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7), (p1, p2, p3, p4, p5, p6, p7)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7), (p1, p2, p3, p4, p5, p6, p7)); } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7); \ - typedef SourceHook::ExecutableClassN CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 7, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN7_void(hookname, param1, param2, param3, param4, param5, param6, param7) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7) - -#define SH_DECL_MANUALHOOK7_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, const char *px), (p1, p2, p3, p4, p5, p6, p7, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, buf)); \ - } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, const char * > CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 7, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN7_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7) - - -// ********* Support for 8 arguments ********* -#define SH_DECL_HOOK8(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8), (p1, p2, p3, p4, p5, p6, p7, p8)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8), (p1, p2, p3, p4, p5, p6, p7, p8), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 8, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN8(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8) - -#define SH_DECL_HOOK8_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8), (p1, p2, p3, p4, p5, p6, p7, p8)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8), (p1, p2, p3, p4, p5, p6, p7, p8)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0},__SH_GPI(param1),__SH_GPI(param2),__SH_GPI(param3),__SH_GPI(param4),__SH_GPI(param5),__SH_GPI(param6),__SH_GPI(param7),__SH_GPI(param8) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 8, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN8_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8) - -#define SH_DECL_HOOK8_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8 , const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, buf), rettype); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 8, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN8_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8) - -#define SH_DECL_HOOK8_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, buf)); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 8, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN8_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8) - -#define SH_DECL_MANUALHOOK8(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8), (p1, p2, p3, p4, p5, p6, p7, p8)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8), (p1, p2, p3, p4, p5, p6, p7, p8), rettype); } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8 > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 8, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN8(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8) - -#define SH_DECL_MANUALHOOK8_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, buf), rettype); \ - } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, const char * > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 8, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN8_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8) - -#define SH_DECL_MANUALHOOK8_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8), (p1, p2, p3, p4, p5, p6, p7, p8)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8), (p1, p2, p3, p4, p5, p6, p7, p8)); } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8); \ - typedef SourceHook::ExecutableClassN CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 8, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN8_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8) - -#define SH_DECL_MANUALHOOK8_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, buf)); \ - } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, const char * > CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 8, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN8_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8) - - -// ********* Support for 9 arguments ********* -#define SH_DECL_HOOK9(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9), (p1, p2, p3, p4, p5, p6, p7, p8, p9)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9), (p1, p2, p3, p4, p5, p6, p7, p8, p9), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 9, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN9(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) - -#define SH_DECL_HOOK9_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9), (p1, p2, p3, p4, p5, p6, p7, p8, p9)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9), (p1, p2, p3, p4, p5, p6, p7, p8, p9)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0},__SH_GPI(param1),__SH_GPI(param2),__SH_GPI(param3),__SH_GPI(param4),__SH_GPI(param5),__SH_GPI(param6),__SH_GPI(param7),__SH_GPI(param8),__SH_GPI(param9) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 9, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN9_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9) - -#define SH_DECL_HOOK9_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9 , const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, buf), rettype); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 9, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN9_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) - -#define SH_DECL_HOOK9_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, buf)); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 9, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN9_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9) - -#define SH_DECL_MANUALHOOK9(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9), (p1, p2, p3, p4, p5, p6, p7, p8, p9)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9), (p1, p2, p3, p4, p5, p6, p7, p8, p9), rettype); } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9 > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 9, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN9(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) - -#define SH_DECL_MANUALHOOK9_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, buf), rettype); \ - } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, const char * > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 9, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN9_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9) - -#define SH_DECL_MANUALHOOK9_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9), (p1, p2, p3, p4, p5, p6, p7, p8, p9)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9), (p1, p2, p3, p4, p5, p6, p7, p8, p9)); } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9); \ - typedef SourceHook::ExecutableClassN CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 9, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN9_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9) - -#define SH_DECL_MANUALHOOK9_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, buf)); \ - } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, const char * > CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 9, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN9_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9) - - -// ********* Support for 10 arguments ********* -#define SH_DECL_HOOK10(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 10, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN10(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) - -#define SH_DECL_HOOK10_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0},__SH_GPI(param1),__SH_GPI(param2),__SH_GPI(param3),__SH_GPI(param4),__SH_GPI(param5),__SH_GPI(param6),__SH_GPI(param7),__SH_GPI(param8),__SH_GPI(param9),__SH_GPI(param10) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 10, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN10_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) - -#define SH_DECL_HOOK10_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10 , const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, buf), rettype); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 10, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN10_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) - -#define SH_DECL_HOOK10_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, buf)); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 10, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN10_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) - -#define SH_DECL_MANUALHOOK10(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10), rettype); } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10 > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 10, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN10(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) - -#define SH_DECL_MANUALHOOK10_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, buf), rettype); \ - } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, const char * > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 10, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN10_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) - -#define SH_DECL_MANUALHOOK10_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)); } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10); \ - typedef SourceHook::ExecutableClassN CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 10, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN10_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) - -#define SH_DECL_MANUALHOOK10_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, buf)); \ - } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, const char * > CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 10, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN10_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) - - -// ********* Support for 11 arguments ********* -#define SH_DECL_HOOK11(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 11, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN11(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) - -#define SH_DECL_HOOK11_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0},__SH_GPI(param1),__SH_GPI(param2),__SH_GPI(param3),__SH_GPI(param4),__SH_GPI(param5),__SH_GPI(param6),__SH_GPI(param7),__SH_GPI(param8),__SH_GPI(param9),__SH_GPI(param10),__SH_GPI(param11) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 11, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN11_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) - -#define SH_DECL_HOOK11_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11 , const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, buf), rettype); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 11, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN11_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) - -#define SH_DECL_HOOK11_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, buf)); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 11, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN11_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) - -#define SH_DECL_MANUALHOOK11(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11), rettype); } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11 > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 11, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN11(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) - -#define SH_DECL_MANUALHOOK11_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, buf), rettype); \ - } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, const char * > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 11, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN11_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) - -#define SH_DECL_MANUALHOOK11_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11)); } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11); \ - typedef SourceHook::ExecutableClassN CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 11, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN11_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) - -#define SH_DECL_MANUALHOOK11_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, buf)); \ - } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, const char * > CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 11, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN11_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11) - - -// ********* Support for 12 arguments ********* -#define SH_DECL_HOOK12(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 12, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN12(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) - -#define SH_DECL_HOOK12_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0},__SH_GPI(param1),__SH_GPI(param2),__SH_GPI(param3),__SH_GPI(param4),__SH_GPI(param5),__SH_GPI(param6),__SH_GPI(param7),__SH_GPI(param8),__SH_GPI(param9),__SH_GPI(param10),__SH_GPI(param11),__SH_GPI(param12) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 12, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN12_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) - -#define SH_DECL_HOOK12_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12 , const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, buf), rettype); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 12, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN12_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) - -#define SH_DECL_HOOK12_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, buf)); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 12, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN12_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) - -#define SH_DECL_MANUALHOOK12(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12), rettype); } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12 > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 12, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN12(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) - -#define SH_DECL_MANUALHOOK12_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, buf), rettype); \ - } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, const char * > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 12, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN12_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) - -#define SH_DECL_MANUALHOOK12_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12)); } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12); \ - typedef SourceHook::ExecutableClassN CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 12, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN12_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) - -#define SH_DECL_MANUALHOOK12_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, buf)); \ - } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, const char * > CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 12, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN12_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12) - - -// ********* Support for 13 arguments ********* -#define SH_DECL_HOOK13(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 13, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN13(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) - -#define SH_DECL_HOOK13_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0},__SH_GPI(param1),__SH_GPI(param2),__SH_GPI(param3),__SH_GPI(param4),__SH_GPI(param5),__SH_GPI(param6),__SH_GPI(param7),__SH_GPI(param8),__SH_GPI(param9),__SH_GPI(param10),__SH_GPI(param11),__SH_GPI(param12),__SH_GPI(param13) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 13, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN13_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) - -#define SH_DECL_HOOK13_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13 , const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, buf), rettype); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 13, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN13_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) - -#define SH_DECL_HOOK13_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, buf)); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 13, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN13_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) - -#define SH_DECL_MANUALHOOK13(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13), rettype); } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13 > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 13, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN13(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) - -#define SH_DECL_MANUALHOOK13_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, buf), rettype); \ - } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, const char * > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 13, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN13_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) - -#define SH_DECL_MANUALHOOK13_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13)); } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13); \ - typedef SourceHook::ExecutableClassN CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 13, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN13_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) - -#define SH_DECL_MANUALHOOK13_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, buf)); \ - } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, const char * > CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 13, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN13_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13) - - -// ********* Support for 14 arguments ********* -#define SH_DECL_HOOK14(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 14, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN14(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) - -#define SH_DECL_HOOK14_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0},__SH_GPI(param1),__SH_GPI(param2),__SH_GPI(param3),__SH_GPI(param4),__SH_GPI(param5),__SH_GPI(param6),__SH_GPI(param7),__SH_GPI(param8),__SH_GPI(param9),__SH_GPI(param10),__SH_GPI(param11),__SH_GPI(param12),__SH_GPI(param13),__SH_GPI(param14) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 14, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN14_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) - -#define SH_DECL_HOOK14_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14 , const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, buf), rettype); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 14, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN14_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) - -#define SH_DECL_HOOK14_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, buf)); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 14, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN14_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) - -#define SH_DECL_MANUALHOOK14(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14), rettype); } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14 > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 14, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN14(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) - -#define SH_DECL_MANUALHOOK14_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, buf), rettype); \ - } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, const char * > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 14, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN14_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) - -#define SH_DECL_MANUALHOOK14_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14)); } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14); \ - typedef SourceHook::ExecutableClassN CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 14, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN14_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) - -#define SH_DECL_MANUALHOOK14_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, buf)); \ - } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, const char * > CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 14, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN14_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14) - - -// ********* Support for 15 arguments ********* -#define SH_DECL_HOOK15(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 15, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN15(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) - -#define SH_DECL_HOOK15_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0},__SH_GPI(param1),__SH_GPI(param2),__SH_GPI(param3),__SH_GPI(param4),__SH_GPI(param5),__SH_GPI(param6),__SH_GPI(param7),__SH_GPI(param8),__SH_GPI(param9),__SH_GPI(param10),__SH_GPI(param11),__SH_GPI(param12),__SH_GPI(param13),__SH_GPI(param14),__SH_GPI(param15) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 15, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN15_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) - -#define SH_DECL_HOOK15_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15 , const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, buf), rettype); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 15, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN15_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) - -#define SH_DECL_HOOK15_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, buf)); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 15, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN15_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) - -#define SH_DECL_MANUALHOOK15(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15), rettype); } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15 > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 15, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN15(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) - -#define SH_DECL_MANUALHOOK15_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, buf), rettype); \ - } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, const char * > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 15, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN15_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) - -#define SH_DECL_MANUALHOOK15_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15)); } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15); \ - typedef SourceHook::ExecutableClassN CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 15, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN15_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) - -#define SH_DECL_MANUALHOOK15_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, buf)); \ - } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, const char * > CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 15, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN15_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15) - - -// ********* Support for 16 arguments ********* -#define SH_DECL_HOOK16(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 16, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN16(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) - -#define SH_DECL_HOOK16_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0},__SH_GPI(param1),__SH_GPI(param2),__SH_GPI(param3),__SH_GPI(param4),__SH_GPI(param5),__SH_GPI(param6),__SH_GPI(param7),__SH_GPI(param8),__SH_GPI(param9),__SH_GPI(param10),__SH_GPI(param11),__SH_GPI(param12),__SH_GPI(param13),__SH_GPI(param14),__SH_GPI(param15),__SH_GPI(param16) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 16, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN16_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) - -#define SH_DECL_HOOK16_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16 , const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, buf), rettype); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 16, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN16_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) - -#define SH_DECL_HOOK16_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, buf)); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 16, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN16_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) - -#define SH_DECL_MANUALHOOK16(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16), rettype); } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16 > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 16, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN16(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) - -#define SH_DECL_MANUALHOOK16_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, buf), rettype); \ - } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, const char * > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 16, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN16_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) - -#define SH_DECL_MANUALHOOK16_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16)); } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16); \ - typedef SourceHook::ExecutableClassN CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 16, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN16_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) - -#define SH_DECL_MANUALHOOK16_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, buf)); \ - } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, const char * > CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 16, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN16_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16) - - -// ********* Support for 17 arguments ********* -#define SH_DECL_HOOK17(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 17, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN17(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) - -#define SH_DECL_HOOK17_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0},__SH_GPI(param1),__SH_GPI(param2),__SH_GPI(param3),__SH_GPI(param4),__SH_GPI(param5),__SH_GPI(param6),__SH_GPI(param7),__SH_GPI(param8),__SH_GPI(param9),__SH_GPI(param10),__SH_GPI(param11),__SH_GPI(param12),__SH_GPI(param13),__SH_GPI(param14),__SH_GPI(param15),__SH_GPI(param16),__SH_GPI(param17) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 17, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN17_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) - -#define SH_DECL_HOOK17_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17 , const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, buf), rettype); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 17, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN17_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) - -#define SH_DECL_HOOK17_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, buf)); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 17, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN17_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) - -#define SH_DECL_MANUALHOOK17(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17), rettype); } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17 > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 17, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN17(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) - -#define SH_DECL_MANUALHOOK17_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, buf), rettype); \ - } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char * > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 17, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN17_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) - -#define SH_DECL_MANUALHOOK17_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17)); } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17); \ - typedef SourceHook::ExecutableClassN CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 17, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN17_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) - -#define SH_DECL_MANUALHOOK17_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, buf)); \ - } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, const char * > CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 17, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN17_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17) - - -// ********* Support for 18 arguments ********* -#define SH_DECL_HOOK18(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 18, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN18(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) - -#define SH_DECL_HOOK18_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0},__SH_GPI(param1),__SH_GPI(param2),__SH_GPI(param3),__SH_GPI(param4),__SH_GPI(param5),__SH_GPI(param6),__SH_GPI(param7),__SH_GPI(param8),__SH_GPI(param9),__SH_GPI(param10),__SH_GPI(param11),__SH_GPI(param12),__SH_GPI(param13),__SH_GPI(param14),__SH_GPI(param15),__SH_GPI(param16),__SH_GPI(param17),__SH_GPI(param18) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 18, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN18_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) - -#define SH_DECL_HOOK18_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18 , const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, buf), rettype); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 18, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN18_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) - -#define SH_DECL_HOOK18_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, buf)); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 18, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN18_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) - -#define SH_DECL_MANUALHOOK18(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18), rettype); } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18 > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 18, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN18(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) - -#define SH_DECL_MANUALHOOK18_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, buf), rettype); \ - } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char * > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 18, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN18_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) - -#define SH_DECL_MANUALHOOK18_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18)); } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18); \ - typedef SourceHook::ExecutableClassN CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 18, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN18_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) - -#define SH_DECL_MANUALHOOK18_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, buf)); \ - } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, const char * > CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 18, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN18_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18) - - -// ********* Support for 19 arguments ********* -#define SH_DECL_HOOK19(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18), __SH_GPI(param19) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 19, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN19(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) - -#define SH_DECL_HOOK19_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0},__SH_GPI(param1),__SH_GPI(param2),__SH_GPI(param3),__SH_GPI(param4),__SH_GPI(param5),__SH_GPI(param6),__SH_GPI(param7),__SH_GPI(param8),__SH_GPI(param9),__SH_GPI(param10),__SH_GPI(param11),__SH_GPI(param12),__SH_GPI(param13),__SH_GPI(param14),__SH_GPI(param15),__SH_GPI(param16),__SH_GPI(param17),__SH_GPI(param18),__SH_GPI(param19) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 19, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN19_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) - -#define SH_DECL_HOOK19_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19 , const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, buf), rettype); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18), __SH_GPI(param19) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 19, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN19_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) - -#define SH_DECL_HOOK19_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, buf)); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18), __SH_GPI(param19) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 19, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN19_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) - -#define SH_DECL_MANUALHOOK19(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19), rettype); } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19 > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18), __SH_GPI(param19) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 19, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN19(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) - -#define SH_DECL_MANUALHOOK19_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, buf), rettype); \ - } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char * > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18), __SH_GPI(param19) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 19, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN19_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) - -#define SH_DECL_MANUALHOOK19_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19)); } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19); \ - typedef SourceHook::ExecutableClassN CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18), __SH_GPI(param19) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 19, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN19_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) - -#define SH_DECL_MANUALHOOK19_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, buf)); \ - } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, const char * > CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18), __SH_GPI(param19) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 19, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN19_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19) - - -// ********* Support for 20 arguments ********* -#define SH_DECL_HOOK20(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), rettype); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18), __SH_GPI(param19), __SH_GPI(param20) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 20, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN20(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SH_DECL_EXTERN(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) - -#define SH_DECL_HOOK20_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20)); } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0},__SH_GPI(param1),__SH_GPI(param2),__SH_GPI(param3),__SH_GPI(param4),__SH_GPI(param5),__SH_GPI(param6),__SH_GPI(param7),__SH_GPI(param8),__SH_GPI(param9),__SH_GPI(param10),__SH_GPI(param11),__SH_GPI(param12),__SH_GPI(param13),__SH_GPI(param14),__SH_GPI(param15),__SH_GPI(param16),__SH_GPI(param17),__SH_GPI(param18),__SH_GPI(param19),__SH_GPI(param20) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 20, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN20_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SH_DECL_EXTERN_void(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) - -#define SH_DECL_HOOK20_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20 , const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, buf), rettype); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18), __SH_GPI(param19), __SH_GPI(param20) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 20, __SH_GPI(rettype), \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN20_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SH_DECL_EXTERN_vafmt(ifacetype, ifacefunc, attr, overload, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) - -#define SH_DECL_HOOK20_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SHINT_MAKE_GENERICSTUFF_BEGIN(ifacetype, ifacefunc, overload, (static_cast \ - (&ifacetype::ifacefunc))) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, buf)); \ - } \ - SHINT_MAKE_GENERICSTUFF_END(ifacetype, ifacefunc, overload, \ - (static_cast(&ifacetype::ifacefunc))) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18), __SH_GPI(param19), __SH_GPI(param20) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_FHCls(ifacetype, ifacefunc, overload)::ms_Proto = { 20, { 0, 0, 0 }, \ - __SourceHook_ParamInfos_##ifacetype##ifacefunc##overload, 0, __SH_EPI, __SourceHook_ParamInfos2_##ifacetype##ifacefunc##overload }; - -#define SH_DECL_EXTERN20_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SH_DECL_EXTERN_void_vafmt(ifacetype, ifacefunc, attr, overload, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) - -#define SH_DECL_MANUALHOOK20(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20) \ - { SH_HANDLEFUNC((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20), rettype); } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20 > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18), __SH_GPI(param19), __SH_GPI(param20) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 20, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN20(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SH_DECL_MANUALEXTERN(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) - -#define SH_DECL_MANUALHOOK20_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG(rettype, (param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, px)); \ - virtual rettype Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, buf), rettype); \ - } \ - typedef rettype(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char * > CallEC; \ - typedef rettype RetType; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18), __SH_GPI(param19), __SH_GPI(param20) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 20, __SH_GPI(rettype), \ - __SourceHook_ParamInfosM_##hookname, 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; \ - void __SoureceHook_FHM_SetOverrideResult##hookname(::SourceHook::ISourceHook *shptr, rettype value) \ - { \ - ::SourceHook::SetOverrideResult()(shptr, value); \ - } - -#define SH_DECL_MANUALEXTERN20_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SH_DECL_MANUALEXTERN_vafmt(hookname, rettype, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) - -#define SH_DECL_MANUALHOOK20_void(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20) \ - { SH_HANDLEFUNC_void((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20)); } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20); \ - typedef SourceHook::ExecutableClassN CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18), __SH_GPI(param19), __SH_GPI(param20) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 20, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN20_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SH_DECL_MANUALEXTERN_void(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) - -#define SH_DECL_MANUALHOOK20_void_vafmt(hookname, vtblidx, vtbloffs, thisptroffs, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SHINT_MAKE_GENERICSTUFF_BEGIN_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - typedef fastdelegate::FastDelegate FD; \ - MAKE_DELEG_void((param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20, const char *px), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, px)); \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7, param8 p8, param9 p9, param10 p10, param11 p11, param12 p12, param13 p13, param14 p14, param15 p15, param16 p16, param17 p17, param18 p18, param19 p19, param20 p20, const char *fmt, ...) \ - { \ - __SH_VAFMT_SEQ(fmt, buf); \ - SH_HANDLEFUNC_void_vafmt((param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *, ...), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, "%s", buf), (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, buf)); \ - } \ - typedef void(::SourceHook::EmptyClass::*ECMFP)(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char *, ...); \ - typedef SourceHook::ExecutableClassN< ::SourceHook::EmptyClass, ECMFP, void, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20, const char * > CallEC; \ - SHINT_MAKE_GENERICSTUFF_END_MANUAL(hookname, vtbloffs, vtblidx, thisptroffs) \ - \ - const ::SourceHook::PassInfo __SourceHook_ParamInfosM_##hookname[] = { {1, 0, 0}, __SH_GPI(param1), __SH_GPI(param2), __SH_GPI(param3), __SH_GPI(param4), __SH_GPI(param5), __SH_GPI(param6), __SH_GPI(param7), __SH_GPI(param8), __SH_GPI(param9), __SH_GPI(param10), __SH_GPI(param11), __SH_GPI(param12), __SH_GPI(param13), __SH_GPI(param14), __SH_GPI(param15), __SH_GPI(param16), __SH_GPI(param17), __SH_GPI(param18), __SH_GPI(param19), __SH_GPI(param20) }; \ - const ::SourceHook::PassInfo::V2Info __SourceHook_ParamInfos2M_##hookname[] = { __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI, __SH_EPI }; \ - ::SourceHook::ProtoInfo SH_MFHCls(hookname)::ms_Proto = { 20, { 0, 0, 0 }, \ - __SourceHook_ParamInfosM_##hookname , 0, __SH_EPI, __SourceHook_ParamInfos2M_##hookname }; - -#define SH_DECL_MANUALEXTERN20_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) \ - SH_DECL_MANUALEXTERN_void_vafmt(hookname, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11, param12, param13, param14, param15, param16, param17, param18, param19, param20) - - - - -////////////////////////////////////////////////////////////////////////// -// SH_CALL - -namespace SourceHook -{ - template - class ExecutableClassN - { - ObjType *m_ThisPtr; - void *m_VfnPtr; - MFPType m_MFP; - ISourceHook *m_pSH; - public: - ExecutableClassN(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) - : m_ThisPtr(tp), - m_VfnPtr(vp), - m_MFP(mfp), - m_pSH(pSH) - { } - - RetType operator()(Params... params) const { - using namespace ::SourceHook; - m_pSH->SetIgnoreHooks(m_VfnPtr); - RetType tmpret = (m_ThisPtr->*m_MFP)(params...); - m_pSH->ResetIgnoreHooks(m_VfnPtr); - return tmpret; - } - - template - RetType operator()(Params... params, MoreParams... more) const { - using namespace ::SourceHook; - m_pSH->SetIgnoreHooks(m_VfnPtr); - RetType tmpret = (m_ThisPtr->*m_MFP)(params..., more...); - m_pSH->ResetIgnoreHooks(m_VfnPtr); - return tmpret; - } - }; - - template - class ExecutableClassN - { - ObjType *m_ThisPtr; - void *m_VfnPtr; - MFPType m_MFP; - ISourceHook *m_pSH; - public: - ExecutableClassN(ObjType *tp, MFPType mfp, void *vp, ISourceHook *pSH) - : m_ThisPtr(tp), - m_VfnPtr(vp), - m_MFP(mfp), - m_pSH(pSH) - { } - - void operator()(Params... params) const { - using namespace ::SourceHook; - m_pSH->SetIgnoreHooks(m_VfnPtr); - (m_ThisPtr->*m_MFP)(params...); - m_pSH->ResetIgnoreHooks(m_VfnPtr); - } - - template - void operator()(Params... params, MoreParams... more) const { - using namespace ::SourceHook; - m_pSH->SetIgnoreHooks(m_VfnPtr); - (m_ThisPtr->*m_MFP)(params..., more...); - m_pSH->ResetIgnoreHooks(m_VfnPtr); - } - }; -} - -#define SH__CALL_GET_VFNPTR_NORMAL \ - using namespace ::SourceHook; \ - MemFuncInfo mfi = {true, -1, 0, 0}; \ - GetFuncInfo(ptr, mfp, mfi); \ - void *vfnptr = reinterpret_cast( \ - *reinterpret_cast(reinterpret_cast(ptr) + mfi.thisptroffs + mfi.vtbloffs) + mfi.vtblindex); - -#define SH__CALL_GET_VFNPTR_MANUAL \ - using namespace ::SourceHook; \ - void *vfnptr = reinterpret_cast( \ - *reinterpret_cast( (reinterpret_cast(ptr) + thisptroffs + vtbloffs) ) + vtblidx); \ - /* patch mfp */ \ - *reinterpret_cast(&mfp) = *reinterpret_cast(vfnptr); - -// SH_CALL needs to deduce the return type -> it uses templates and function overloading -// That's why SH_CALL takes two parameters: "mfp2" of type RetType(X::*mfp)(params), and "mfp" of type MFP -// The only purpose of the mfp2 parameter is to extract the return type - -template -SourceHook::ExecutableClassN -SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params...), SourceHook::ISourceHook *shptr) -{ - SH__CALL_GET_VFNPTR_NORMAL - return SourceHook::ExecutableClassN(ptr, mfp, vfnptr, shptr); -} - -template -SourceHook::ExecutableClassN -SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params..., ...), SourceHook::ISourceHook *shptr) -{ - SH__CALL_GET_VFNPTR_NORMAL - return SourceHook::ExecutableClassN(ptr, mfp, vfnptr, shptr); -} - -template -SourceHook::ExecutableClassN -SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params...)const, SourceHook::ISourceHook *shptr) -{ - SH__CALL_GET_VFNPTR_NORMAL - return SourceHook::ExecutableClassN(ptr, mfp, vfnptr, shptr); -} - -template -SourceHook::ExecutableClassN -SH_CALL2(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params..., ...)const, SourceHook::ISourceHook *shptr) -{ - SH__CALL_GET_VFNPTR_NORMAL - return SourceHook::ExecutableClassN(ptr, mfp, vfnptr, shptr); -} - -template -SourceHook::ExecutableClassN -SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params...), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) -{ - SH__CALL_GET_VFNPTR_MANUAL - return SourceHook::ExecutableClassN( - reinterpret_cast(ptr), mfp, vfnptr, shptr); -} - -template -SourceHook::ExecutableClassN -SH_MCALL3(Y *ptr, MFP mfp, RetType(X::*mfp2)(Params..., ...), int vtblidx, int vtbloffs, int thisptroffs, SourceHook::ISourceHook *shptr) -{ - SH__CALL_GET_VFNPTR_MANUAL - return SourceHook::ExecutableClassN( - reinterpret_cast(ptr), mfp, vfnptr, shptr); -} - -#define SH_CALL(ptr, mfp) SH_CALL2((ptr), (mfp), (mfp), SH_GLOB_SHPTR) -#define SH_MCALL2(ptr, mfp, vtblidx, vtbloffs, thisptroffs) SH_MCALL3((ptr), (mfp), (mfp), (vtblidx), (vtbloffs), (thisptroffs), SH_GLOB_SHPTR) -#define SH_MCALL(ptr, mhookname) __SoureceHook_FHM_SHCall##mhookname(ptr) - -////////////////////////////////////////////////////////////////////////// -// SetOverrideRet and RecallGetIface for recalls -// These take a ISourceHook pointer instead of using SH_GLOB_SHPTR directly -// The reason is that the user may want to redefine SH_GLOB_SHPTR - then the macros -// (META_RETURN_VALUE_NEWPARAMS) should obey the new pointer. - -namespace SourceHook -{ - // SetOverrideResult used to be implemented like this: - // SetOverrideResult(shptr, memfuncptr, return); - // normally the compiler can deduce the return type from memfuncptr, but (at least msvc8) failed when it was a reference - // (it thought it was ambigous - the ref and non-ref type) - // so now SetOverrideResult(memfuncptr) deduces the ret type, and returns a functor which does the work - // new syntax: SetOverrideResult(memfuncptr)(shptr, return) - // This also allows us to create a special version for references which respects ReferenceCarrier. - - template struct OverrideFunctor - { - void operator()(ISourceHook *shptr, T res) - { - *reinterpret_cast(shptr->GetOverrideRetPtr()) = res; - } - }; - template struct OverrideFunctor - { - void operator()(ISourceHook *shptr, T &res) - { - // overrideretptr points to ReferenceCarrier - *reinterpret_cast::type *>(shptr->GetOverrideRetPtr()) = res; - } - }; - - // For manual hooks: - // The rettype is passed in manually - template - OverrideFunctor SetOverrideResult() - { - return OverrideFunctor(); - } - - template - OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Params...)) - { - return OverrideFunctor(); - } - - template - OverrideFunctor SetOverrideResult(RetType (Iface::*mfp)(Params..., ...)) - { - return OverrideFunctor(); - } - - template - Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Params...)) - { - return reinterpret_cast(shptr->GetIfacePtr()); - } - - template - Iface *RecallGetIface(ISourceHook *shptr, RetType (Iface::*mfp)(Params..., ...)) - { - return reinterpret_cast(shptr->GetIfacePtr()); - } -} - -#endif - // The pope is dead. -> :( diff --git a/utils/mmsource/core/sourcehook/sourcehook_hookmangen.cpp b/utils/mmsource/core/sourcehook/sourcehook_hookmangen.cpp deleted file mode 100644 index 0b6404b95..000000000 --- a/utils/mmsource/core/sourcehook/sourcehook_hookmangen.cpp +++ /dev/null @@ -1,2040 +0,0 @@ -/* ======== SourceHook ======== -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko -* Contributor(s): Borja "faluco" Ferav (many thanks for assitance!) -* David "BAILOPAN" Anderson -* ============================ -*/ - -// recommended literature: -// http://www.cs.umbc.edu/~chang/cs313.s02/stack.shtml -// http://www.angelcode.com/dev/callconv/callconv.html -// http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/Chapter_6/CH06-1.html - -#include -#include "sourcehook_impl.h" -#include "sourcehook_hookmangen.h" -#include "sourcehook_hookmangen_x86.h" -#include "sh_memory.h" -#include // we might need the address of vsnprintf - -#if SH_COMP == SH_COMP_MSVC -# define GCC_ONLY(x) -# define MSVC_ONLY(x) x -#elif SH_COMP == SH_COMP_GCC -# define GCC_ONLY(x) x -# define MSVC_ONLY(x) -#endif - -// :TODO: test BIG vtable indices - -namespace SourceHook -{ - namespace Impl - { - CPageAlloc GenBuffer::ms_Allocator(16); - - template - jit_int32_t DownCastPtr(T ptr) - { - return reinterpret_cast(ptr); - } - - jit_uint32_t DownCastSize(size_t size) - { - return static_cast(size); - } - - GenContext::GenContext(const ProtoInfo *proto, int vtbl_offs, int vtbl_idx, ISourceHook *pSHPtr) - : m_GeneratedPubFunc(NULL), m_OrigProto(proto), m_Proto(proto), m_VtblOffs(vtbl_offs), - m_VtblIdx(vtbl_idx), m_SHPtr(pSHPtr), m_pHI(NULL), m_HookfuncVfnptr(NULL), m_RegCounter(0) - { - m_pHI = new void*; - m_HookfuncVfnptr = new void*; - m_BuiltPI = new ProtoInfo; - m_BuiltPI_Params = NULL; - m_BuiltPI_Params2 = NULL; - } - - GenContext::~GenContext() - { - Clear(); - delete m_pHI; - delete m_HookfuncVfnptr; - delete m_BuiltPI; - } - - void GenContext::Clear() - { - m_HookFunc.clear(); - m_PubFunc.clear(); - if (m_BuiltPI_Params) - { - delete [] m_BuiltPI_Params; - m_BuiltPI_Params = NULL; - } - if (m_BuiltPI_Params2) - { - delete [] m_BuiltPI_Params2; - m_BuiltPI_Params2 = NULL; - } - } - - void GenContext::BuildProtoInfo() - { - m_BuiltPI->convention = m_Proto.GetConvention(); - m_BuiltPI->numOfParams = m_Proto.GetNumOfParams(); - - m_BuiltPI->retPassInfo.size = m_Proto.GetRet().size; - m_BuiltPI->retPassInfo.type = m_Proto.GetRet().type; - m_BuiltPI->retPassInfo.flags = m_Proto.GetRet().flags; - m_BuiltPI->retPassInfo2.pNormalCtor = m_Proto.GetRet().pNormalCtor; - m_BuiltPI->retPassInfo2.pCopyCtor = m_Proto.GetRet().pCopyCtor; - m_BuiltPI->retPassInfo2.pDtor = m_Proto.GetRet().pDtor; - m_BuiltPI->retPassInfo2.pAssignOperator = m_Proto.GetRet().pAssignOperator; - - if (m_BuiltPI_Params) - delete m_BuiltPI_Params; - m_BuiltPI_Params = new PassInfo[m_BuiltPI->numOfParams + 1]; - if (m_BuiltPI_Params2) - delete m_BuiltPI_Params2; - m_BuiltPI_Params2 = new PassInfo::V2Info[m_BuiltPI->numOfParams + 1]; - - m_BuiltPI_Params[0].size = 1; // Version 1 - m_BuiltPI_Params[0].type = 0; - m_BuiltPI_Params[0].flags = 0; - - for (int i = 0; i < m_Proto.GetNumOfParams(); ++i) - { - m_BuiltPI_Params[i+1].size = m_Proto.GetParam(i).size; - m_BuiltPI_Params[i+1].type = m_Proto.GetParam(i).type; - m_BuiltPI_Params[i+1].flags = m_Proto.GetParam(i).flags; - - m_BuiltPI_Params2[i+1].pNormalCtor = m_Proto.GetParam(i).pNormalCtor; - m_BuiltPI_Params2[i+1].pCopyCtor = m_Proto.GetParam(i).pCopyCtor; - m_BuiltPI_Params2[i+1].pDtor = m_Proto.GetParam(i).pDtor; - m_BuiltPI_Params2[i+1].pAssignOperator = m_Proto.GetParam(i).pAssignOperator; - } - - m_BuiltPI->paramsPassInfo = m_BuiltPI_Params; - m_BuiltPI->paramsPassInfo2 = m_BuiltPI_Params2; - } - - jit_int32_t GenContext::GetRealSize(const IntPassInfo &info) - { - if (info.flags & (PassInfo::PassFlag_ByRef | PassFlag_ForcedByRef)) - { - return SIZE_PTR; - } - return static_cast(info.size); - } - - jit_int32_t GenContext::AlignSize(jit_int32_t x, jit_int32_t boundary) - { - if (x % boundary != 0) - x = (x & ~(boundary-1)) + boundary; - return x; - } - - // Computes size on the stack - jit_int32_t GenContext::GetParamStackSize(const IntPassInfo &info) - { - // Align up to 4 byte boundaries - return AlignSize(GetRealSize(info), 4); - } - - jit_int8_t GenContext::NextRegEBX_ECX_EDX() - { - switch ((m_RegCounter++) % 3) - { - case 0: - return REG_EBX; - case 1: - return REG_ECX; - case 2: - default: - m_RegCounter = 0; - return REG_EDX; - } - } - - void GenContext::BitwiseCopy_Setup() - { - //cld - //push edi - //push esi - - IA32_Cld(&m_HookFunc); - IA32_Push_Reg(&m_HookFunc, REG_EDI); - IA32_Push_Reg(&m_HookFunc, REG_ESI); - } - - void GenContext::BitwiseCopy_Do(size_t size) - { - jit_uint32_t dwords = DownCastSize(size) / 4; - jit_uint32_t bytes = DownCastSize(size) % 4; - - //if dwords - // mov ecx, - // rep movsd - //if bytes - // mov ecx, - // rep movsb - //pop esi - //pop edi - - if (dwords) - { - IA32_Mov_Reg_Imm32(&m_HookFunc, REG_ECX, dwords); - IA32_Rep(&m_HookFunc); - IA32_Movsd(&m_HookFunc); - } - if (bytes) - { - IA32_Mov_Reg_Imm32(&m_HookFunc, REG_ECX, bytes); - IA32_Rep(&m_HookFunc); - IA32_Movsb(&m_HookFunc); - } - IA32_Pop_Reg(&m_HookFunc, REG_ESI); - IA32_Pop_Reg(&m_HookFunc, REG_EDI); - } - - jit_int32_t GenContext::AlignStackBeforeCall(int paramsize, int flags) - { - paramsize += - GCC_ONLY( ((flags & AlignStack_GCC_ThisOnStack)!=0 ? SIZE_PTR : 0) + ) - MSVC_ONLY( ((flags & AlignStack_MSVC_ThisOnStack)!=0 ? SIZE_PTR : 0) + ) - ((flags & AlignStack_MemRet)!=0 ? SIZE_PTR : 0); - - // At the beginning of the hookfunc, the stack is aligned to a 16 bytes boundary. - // Then, m_BytesPushedAfterInitialAlignment were pushed (can also be 0). - - // After this function is called, paramsize bytes will be pushed onto the stack - // After that, the alignment has to be a 16 bytes boundary again. - - - // How many bytes we would subtract if the alignment was alright now: - int subtractFromEsp = 16 - (paramsize % 16); - if (subtractFromEsp == 16) - subtractFromEsp = 0; - - // But: there might be bytes pushed alreay! - subtractFromEsp -= m_BytesPushedAfterInitialAlignment; - - // For example: paramsize was 0 and m_BytesPushedAfterInitialAlignment was 4. - // we then have to push another 12 bytes to reach 16 bytes alignment again. - - if (subtractFromEsp < 0) - subtractFromEsp = 16 - ((-subtractFromEsp) % 16); - - if (subtractFromEsp != 0) - IA32_Sub_Rm_ImmAuto(&m_HookFunc, REG_ESP, subtractFromEsp, MOD_REG); - - return subtractFromEsp; - } - - void GenContext::AlignStackAfterCall(jit_int32_t numofbytes) - { - if (numofbytes != 0) - IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, numofbytes, MOD_REG); - } - - void GenContext::CheckAlignmentBeforeCall() - { -#if 0 - IA32_Test_Rm_Imm32(&m_HookFunc, REG_ESP, 15, MOD_REG); - IA32_Jump_Cond_Imm8(&m_HookFunc, CC_Z, 1); - IA32_Int3(&m_HookFunc); -#endif - } - - short GenContext::GetParamsTotalStackSize() - { - short acc = 0; - for (int i = 0; i < m_Proto.GetNumOfParams(); ++i) - { - acc += GetParamStackSize(m_Proto.GetParam(i)); - } - - return acc; - } - - short GenContext::GetForcedByRefParamOffset(int p) - { - short off = 0; - for (int i = 0; i < p; ++i) - { - if (m_Proto.GetParam(i).flags & PassFlag_ForcedByRef) - off += AlignSize(static_cast(m_Proto.GetParam(i).size), 4); - } - return off; - } - - short GenContext::GetForcedByRefParamsSize() - { - return GetForcedByRefParamOffset(m_Proto.GetNumOfParams()); - } - - jit_int32_t GenContext::PushRef(jit_int32_t param_offset, const IntPassInfo &pi) - { - // push [ebp+] - IA32_Push_Rm_DispAuto(&m_HookFunc, REG_EBP, param_offset); - - return SIZE_PTR; - } - - jit_int32_t GenContext::PushBasic(jit_int32_t param_offset, const IntPassInfo &pi) - { - int reg; - int reg2; - - switch (pi.size) - { - default: - SH_ASSERT(0, ("Unsupported!")); - return 0; - case 1: - reg = NextRegEBX_ECX_EDX(); - //movzx reg, BYTE PTR [ebp+] - //push reg - IA32_Movzx_Reg32_Rm8_DispAuto(&m_HookFunc, reg, REG_EBP, param_offset); - IA32_Push_Reg(&m_HookFunc, reg); - - return 4; - case 2: - reg = NextRegEBX_ECX_EDX(); - //movzx reg, WORD PTR [ebp+] - //push reg - m_HookFunc.write_ubyte(IA32_16BIT_PREFIX); - IA32_Movzx_Reg32_Rm16_DispAuto(&m_HookFunc, reg, REG_EBP, param_offset); - IA32_Push_Reg(&m_HookFunc, reg); - - return 4; - case 4: - reg = NextRegEBX_ECX_EDX(); - //mov reg, DWORD PTR [ebp+] - //push reg - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, reg, REG_EBP, param_offset); - IA32_Push_Reg(&m_HookFunc, reg); - - return 4; - case 8: - reg = NextRegEBX_ECX_EDX(); - reg2 = NextRegEBX_ECX_EDX(); - //mov reg, DWORD PTR [ebp++4] - //mov reg2, DWORD PTR [ebp+] - //push reg - //push reg2 - - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, reg, REG_EBP, param_offset+4); - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, reg2, REG_EBP, param_offset); - IA32_Push_Reg(&m_HookFunc, reg); - IA32_Push_Reg(&m_HookFunc, reg2); - - return 8; - } - } - - jit_int32_t GenContext::PushFloat(jit_int32_t param_offset, const IntPassInfo &pi) - { - switch (pi.size) - { - default: - SH_ASSERT(0, ("Unsupported!")); - return 0; - case 4: - //fld DWORD PTR [ebp+] - //push reg - //fstp DWORD PTR [esp] - IA32_Fld_Mem32_DispAuto(&m_HookFunc, REG_EBP, param_offset); - IA32_Push_Reg(&m_HookFunc, NextRegEBX_ECX_EDX()); - IA32_Fstp_Mem32_ESP(&m_HookFunc); - return 4; - case 8: - //fld QWORD PTR [ebp+] - //sub esp, 8 - //fstp QWORD PTR [esp] - IA32_Fld_Mem64_DispAuto(&m_HookFunc, REG_EBP, param_offset); - IA32_Sub_Rm_Imm8(&m_HookFunc, REG_ESP, 8, MOD_REG); - IA32_Fstp_Mem64_ESP(&m_HookFunc); - return 8; - } - } - - jit_int32_t GenContext::PushObject(jit_int32_t param_offset, const IntPassInfo &pi, jit_int32_t place_fbrr) - { - if ((pi.flags & PassFlag_ForcedByRef) == 0) - { - // make room on the stack - // sub esp, - IA32_Sub_Rm_ImmAuto(&m_HookFunc, REG_ESP, GetParamStackSize(pi), MOD_REG); - } - - // if there is a copy constructor.. - if (pi.pCopyCtor) - { - // :TODO: alignment here? - // can't use normal alignment methods - // because an unknown number of bytes has been pushed already (the other params) - - // save eax - IA32_Push_Reg(&m_HookFunc, REG_EAX); - - // compute dest addr to ECX - // = forcedbyref ? ebp+place_fbrr : esp+12 - if (pi.flags & PassFlag_ForcedByRef) - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, place_fbrr); - else - IA32_Lea_Reg_DispRegMultImm8(&m_HookFunc, REG_ECX, REG_NOIDX, REG_ESP, NOSCALE, 4); - - // compute src addr to EAX - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_EAX, REG_EBP, param_offset); - - // push params (gcc: also this) - IA32_Push_Reg(&m_HookFunc, REG_EAX); - GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX)); - - // call - IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EDX, DownCastPtr(pi.pCopyCtor)); - IA32_Call_Reg(&m_HookFunc, REG_EDX); - - // gcc: clean up stack - GCC_ONLY(IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, 2 * SIZE_PTR, MOD_REG)); - - // restore eax - IA32_Pop_Reg(&m_HookFunc, REG_EAX); - } - else - { - // bitwise copy - - BitwiseCopy_Setup(); - - //if forcedbyref: - // lea edi, [ebp_place_fbrr] - //else - // lea edi, [esp+8] - bc_setup pushed two regs onto the stack! - //lea esi, [ebp+] - if (pi.flags & PassFlag_ForcedByRef) - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_EDI, REG_EBP, place_fbrr); - else - IA32_Lea_Reg_DispRegMultImm8(&m_HookFunc, REG_EDI, REG_NOIDX, REG_ESP, NOSCALE, 8); - - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ESI, REG_EBP, param_offset); - - BitwiseCopy_Do(pi.size); - } - - // forcedref: push reference to ebp+place_fbrr - if (pi.flags & PassFlag_ForcedByRef) - { - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, place_fbrr); - IA32_Push_Reg(&m_HookFunc, REG_ECX); - return SIZE_PTR; - } - - return GetParamStackSize(pi); - } - - void GenContext::DestroyParams(jit_int32_t fbrr_base) - { - for (int i = m_Proto.GetNumOfParams() - 1; i >= 0; --i) - { - const IntPassInfo &pi = m_Proto.GetParam(i); - if (pi.type == PassInfo::PassType_Object && (pi.flags & PassInfo::PassFlag_ODtor) && - (pi.flags & PassInfo::PassFlag_ByVal) && (pi.flags & PassFlag_ForcedByRef)) - { - // Actually, this is only for GCC (see line above: ForcedByRef) - jit_int32_t tmpAlign = AlignStackBeforeCall(0, AlignStack_GCC_ThisOnStack); - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, fbrr_base + GetForcedByRefParamOffset(i)); - IA32_Push_Reg(&m_HookFunc, REG_ECX); - IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(pi.pDtor)); - CheckAlignmentBeforeCall(); - IA32_Call_Reg(&m_HookFunc, REG_EAX); - IA32_Pop_Reg(&m_HookFunc, REG_ECX); - - AlignStackAfterCall(tmpAlign); - } - } - } - - // May not touch eax! - jit_int32_t GenContext::PushParams(jit_int32_t param_base_offset, jit_int32_t save_ret_to, int v_place_for_memret, - jit_int32_t v_place_fbrr_base) - { - jit_int32_t added_to_stack = 0; - jit_int32_t ret = 0; - - // compute the offset _after_ the last parameter - jit_int32_t cur_offset = param_base_offset; - for (int i = 0; i < m_Proto.GetNumOfParams(); ++i) - { - cur_offset += GetParamStackSize(m_Proto.GetParam(i)); - } - - // push parameters in reverse order - for (int i = m_Proto.GetNumOfParams() - 1; i >= 0; --i) - { - const IntPassInfo &pi = m_Proto.GetParam(i); - cur_offset -= GetParamStackSize(pi); - if (pi.flags & PassInfo::PassFlag_ByVal) - { - switch (pi.type) - { - case PassInfo::PassType_Basic: - ret = PushBasic(cur_offset, pi); - break; - case PassInfo::PassType_Float: - ret = PushFloat(cur_offset, pi); - break; - case PassInfo::PassType_Object: - ret = PushObject(cur_offset, pi, v_place_fbrr_base + GetForcedByRefParamOffset(i)); - break; - } - } - else if (pi.flags & PassInfo::PassFlag_ByRef) - { - ret = PushRef(cur_offset, pi); - } - else - { - SH_ASSERT(0, ("Unsupported!")); - } - added_to_stack += ret; - } - - return added_to_stack; - } - - // It is IMPORTANT that PushMemRetPtr doesn't touch ecx and eax - jit_int32_t GenContext::PushMemRetPtr(jit_int32_t save_ret_to, jit_int32_t v_place_for_memret) - { - // Memory return support - if (m_Proto.GetRet().flags & PassInfo::PassFlag_RetMem) - { - // push address where to save it! - int reg = REG_EDX; - IA32_Lea_DispRegImmAuto(&m_HookFunc, reg, REG_EBP, - MemRetWithTempObj() ? v_place_for_memret : save_ret_to); - IA32_Push_Reg(&m_HookFunc, reg); - - return (SH_COMP==SH_COMP_MSVC) ? 4 : 0; // varargs funcs on msvc might need this. - // gcc doesn't: callee cleans the memret ptr, caller the other params :s - } - return 0; - } - - void GenContext::SaveRetVal(int v_where, int v_place_for_memret) - { - size_t size = GetRealSize(m_Proto.GetRet()); - if (size == 0) - { - // No return value -> nothing - return; - } - - if (m_Proto.GetRet().flags & PassInfo::PassFlag_ByRef) - { - // mov [ebp + v_plugin_ret], eax - IA32_Mov_Rm_Reg_DispAuto(&m_HookFunc, REG_EBP, REG_EAX, v_where); - return; - } - // else: ByVal - - - // Memory return: - if (m_Proto.GetRet().flags & PassInfo::PassFlag_RetMem) - { - if (MemRetWithTempObj()) - { - // *v_where = *v_place_for_memret - - // if we have an assign operator, use that - if (m_Proto.GetRet().pAssignOperator) - { - // lea edx, [ebp + v_place_for_memret] <-- src addr - // lea ecx, [ebp + v_where] <-- dest addr - // push edx - // gcc: push ecx - // call it - // gcc: clean up - - jit_int32_t tmpAlign = AlignStackBeforeCall(SIZE_PTR, AlignStack_GCC_ThisOnStack); - - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_EDX, REG_EBP, v_place_for_memret); - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_where); - IA32_Push_Reg(&m_HookFunc, REG_EDX); - GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX)); - - IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pAssignOperator)); - CheckAlignmentBeforeCall(); - IA32_Call_Reg(&m_HookFunc, REG_EAX); - GCC_ONLY(IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, 2 * SIZE_PTR, MOD_REG)); - - AlignStackAfterCall(tmpAlign); - } - else - { - // bitwise copy - BitwiseCopy_Setup(); - - //lea edi, [evp+v_where] <-- destination - //lea esi, [ebp+v_place_for_memret] <-- src - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_EDI, REG_EBP, v_where); - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ESI, REG_EBP, v_place_for_memret); - - BitwiseCopy_Do(m_Proto.GetRet().size); - } - - // Then: destruct *v_place_for_memret if required - if (m_Proto.GetRet().pDtor) - { - //lea ecx, [ebp+v_place_for_memret] - //gcc: push ecx - //call it - //gcc: clean up - - jit_int32_t tmpAlign = AlignStackBeforeCall(0, AlignStack_GCC_ThisOnStack); - - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_place_for_memret); - GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX)); - IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pDtor)); - CheckAlignmentBeforeCall(); - IA32_Call_Reg(&m_HookFunc, REG_EAX); - GCC_ONLY(IA32_Pop_Reg(&m_HookFunc, REG_ECX)); - - AlignStackAfterCall(tmpAlign); - } - } - else - { - // Already copied to correct address -> we're done - return; - } - } - - if (m_Proto.GetRet().type == PassInfo::PassType_Float) - { - if (size == 4) - IA32_Fstp_Mem32_DispAuto(&m_HookFunc, REG_EBP, v_where); - else if (size == 8) - IA32_Fstp_Mem64_DispAuto(&m_HookFunc, REG_EBP, v_where); - } - else if (m_Proto.GetRet().type == PassInfo::PassType_Basic) - { - if (size <= 4) - { - // size <= 4: return in EAX - // We align <4 sizes up to 4 - - - // mov [ebp + v_plugin_ret], eax - IA32_Mov_Rm_Reg_DispAuto(&m_HookFunc, REG_EBP, REG_EAX, v_where); - } - else if (size <= 8) - { - // size <= 4: return in EAX:EDX - // We align 4 8 !")); - } - } - } - } - - bool GenContext::MemRetWithTempObj() - { - // Memory return AND (has destructor OR has assign operator) - return ((m_Proto.GetRet().flags & PassInfo::PassFlag_RetMem) - && (m_Proto.GetRet().flags & (PassInfo::PassFlag_ODtor | PassInfo::PassFlag_AssignOp))); - } - - void GenContext::ProcessPluginRetVal(int v_cur_res, int v_pContext, int v_plugin_ret) - { - // only for non-void functions! - if (m_Proto.GetRet().size == 0) - return; - - // if (cur_res >= MRES_OVERRIDE) - // *reinterpret_cast(pContext->GetOverrideRetPtr()) = plugin_ret; - - // eax = cur_res - // cmp eax,MRES_OVERRIDE - // jnge thelabel - // pContext->GetOverrideRetPtr() --> overrideretptr in eax - // *eax = plugin_ret - // thelabel: - // - - jitoffs_t tmppos, counter; - - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_EAX, REG_EBP, v_cur_res); - - IA32_Cmp_Rm_Imm32(&m_HookFunc, MOD_REG, REG_EAX, MRES_OVERRIDE); - tmppos = IA32_Jump_Cond_Imm8(&m_HookFunc, CC_NGE, 0); - m_HookFunc.start_count(counter); - - // eax = pContext->GetOverrideRetPtr() no alignment needs - // ECX = pContext - // gcc: push ecx - // eax = [ecx] - // eax = [eax + 4] - // call eax - // gcc: clean up - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_ECX, REG_EBP, v_pContext); - GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX)); - - // vtbloffs=0, vtblidx=1 - IA32_Mov_Reg_Rm(&m_HookFunc, REG_EAX, REG_ECX, MOD_MEM_REG); - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_EAX, REG_EAX, 4); - IA32_Call_Reg(&m_HookFunc, REG_EAX); - GCC_ONLY(IA32_Pop_Reg(&m_HookFunc, REG_ECX)); - - - // *eax = plugin_ret - if (m_Proto.GetRet().flags & PassInfo::PassFlag_ByRef) - { - // mov ecx, [ebp+v_plugin_ret] - // mov [eax], ecx - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_ECX, REG_EBP, v_plugin_ret); - IA32_Mov_Rm_Reg(&m_HookFunc, REG_EAX, REG_ECX, MOD_MEM_REG); - } - else - { - if (m_Proto.GetRet().pAssignOperator) - { - // lea edx, [ebp + v_plugin_ret] - // push edx <-- src addr - // msvc: ecx = eax <-- dest addr - // gcc: push eax <-- dest addr - // call it - // gcc: clean up - - jit_int32_t tmpAlign = AlignStackBeforeCall(SIZE_PTR, AlignStack_GCC_ThisOnStack); - - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_EDX, REG_EBP, v_plugin_ret); - IA32_Push_Reg(&m_HookFunc, REG_EDX); -#if SH_COMP == SH_COMP_MSVC - IA32_Mov_Reg_Rm(&m_HookFunc, REG_ECX, REG_EAX, MOD_REG); -#elif SH_COMP == SH_COMP_GCC - IA32_Push_Reg(&m_HookFunc, REG_EAX); -#endif - - IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pAssignOperator)); - CheckAlignmentBeforeCall(); - IA32_Call_Reg(&m_HookFunc, REG_EAX); - GCC_ONLY(IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, 2 * SIZE_PTR, MOD_REG)); - - AlignStackAfterCall(tmpAlign); - } - else - { - // bitwise copy - BitwiseCopy_Setup(); - - //mov edi, eax <-- destination - //lea esi, [ebp+v_plugin_ret] <-- src - IA32_Mov_Reg_Rm(&m_HookFunc, REG_EDI, REG_EAX, MOD_REG); - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ESI, REG_EBP, v_plugin_ret); - - BitwiseCopy_Do(m_Proto.GetRet().size); - } - } - - m_HookFunc.end_count(counter); - m_HookFunc.rewrite(tmppos, static_cast(counter)); - } - - void GenContext::PrepareReturn(int v_status, int v_pContext, int v_retptr) - { - // only for non-void functions! - if (m_Proto.GetRet().size == 0) - return; - - // retptr = status >= MRES_OVERRIDE ? pContext->GetOverrideRetPtr() : pContext->GetOrigRetPtr() - - // OverrideRetPtr: vtblidx = 1 - // OrigRetPtr: vtbldix = 2 - // vtblidx = (status >= MRES_OVERRIDE) ? 1 : 2 - - // - // eax = pContext->GetOverrideRetPtr() - // ECX = pContext - // gcc: push ecx - - // eax = (status < MRES_OVERRIDE) ? 1 : 0 - // xor eax, eax - // cmp [ebp + v_status], MRES_OVERRIDE - // setl al <-- setcc optimization for ternary operators, - - - // lea eax, [4*eax + 0x4] - - // edx = [ecx] - // add edx, eax - // mov edx, [edx] - - // call edx - // gcc: clean up - - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_ECX, REG_EBP, v_pContext); - GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX)); - IA32_Xor_Reg_Rm(&m_HookFunc, REG_EAX, REG_EAX, MOD_REG); - IA32_Cmp_Rm_Disp8_Imm8(&m_HookFunc, REG_EBP, v_status, MRES_OVERRIDE); - IA32_SetCC_Rm8(&m_HookFunc, REG_EAX, CC_L); - - IA32_Lea_Reg_RegMultImm32(&m_HookFunc, REG_EAX, REG_EAX, SCALE4, 4); - - IA32_Mov_Reg_Rm(&m_HookFunc, REG_EDX, REG_ECX, MOD_MEM_REG); - IA32_Add_Reg_Rm(&m_HookFunc, REG_EDX, REG_EAX, MOD_REG); - - IA32_Mov_Reg_Rm(&m_HookFunc, REG_EDX, REG_EDX, MOD_MEM_REG); - IA32_Call_Reg(&m_HookFunc, REG_EDX); - GCC_ONLY(IA32_Pop_Reg(&m_HookFunc, REG_ECX)); - - IA32_Mov_Rm_Reg_DispAuto(&m_HookFunc, REG_EBP, REG_EAX, v_retptr); - } - - void GenContext::DoReturn(int v_retptr, int v_memret_outaddr) - { - size_t size = m_Proto.GetRet().size; - if (!size) - return; - - // Get real ret pointer into ecx - // mov ecx, [ebp + v_ret_ptr] - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_ECX, REG_EBP, v_retptr); - - if (m_Proto.GetRet().flags & PassInfo::PassFlag_ByRef) - { - // mov eax, [ecx] - IA32_Mov_Reg_Rm(&m_HookFunc, REG_EAX, REG_ECX, MOD_MEM_REG); - return; - } - // else: byval - - if (m_Proto.GetRet().type == PassInfo::PassType_Float) - { - if (size == 4) - IA32_Fld_Mem32(&m_HookFunc, REG_ECX); - else if (size == 8) - IA32_Fld_Mem64(&m_HookFunc, REG_ECX); - } - else if (m_Proto.GetRet().type == PassInfo::PassType_Basic || - ((m_Proto.GetRet().type == PassInfo::PassType_Object) && (m_Proto.GetRet().flags & PassInfo::PassFlag_RetReg)) ) - { - if (size <= 4) - { - // size <= 4: return in EAX - // We align <4 sizes up to 4 - - // mov eax, [ecx] - IA32_Mov_Reg_Rm(&m_HookFunc, REG_EAX, REG_ECX, MOD_MEM_REG); - } - else if (size <= 8) - { - // size <= 4: return in EAX:EDX - // We align 48: return in memory - // handled later - } - } - - if (m_Proto.GetRet().flags & PassInfo::PassFlag_RetMem) - { - // *memret_outaddr = plugin_ret - if (m_Proto.GetRet().pCopyCtor) - { - // mov edx, ecx <-- src ( we set ecx to [ebp+v_retptr] before ) - // push edx <-- src addr - // msvc: ecx = [ebp + v_memret_outaddr] <-- dest addr - // gcc: push [ebp + v_memret_outaddr] <-- dest addr - // call it - // gcc: clean up - - jit_int32_t tmpAlign = AlignStackBeforeCall(SIZE_PTR, AlignStack_GCC_ThisOnStack); - - IA32_Mov_Reg_Rm(&m_HookFunc, REG_EDX, REG_ECX, MOD_REG); - IA32_Push_Reg(&m_HookFunc, REG_EDX); - -#if SH_COMP == SH_COMP_MSVC - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_ECX, REG_EBP, v_memret_outaddr); -#elif SH_COMP == SH_COMP_GCC - IA32_Push_Rm_DispAuto(&m_HookFunc, REG_EBP, v_memret_outaddr); -#endif - - IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pCopyCtor)); - CheckAlignmentBeforeCall(); - IA32_Call_Reg(&m_HookFunc, REG_EAX); - GCC_ONLY(IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, 2 * SIZE_PTR, MOD_REG)); - - AlignStackAfterCall(tmpAlign); - } - else - { - // bitwise copy - BitwiseCopy_Setup(); - - //mov edi, [ebp+v_memret_outaddr] <-- destination - //mov esi, ecx <-- src ( we set ecx to [ebp+v_retptr] before ) - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_EDI, REG_EBP, v_memret_outaddr); - IA32_Mov_Reg_Rm(&m_HookFunc, REG_ESI, REG_ECX, MOD_REG); - - BitwiseCopy_Do(m_Proto.GetRet().size); - } - - // In both cases: return the pointer in EAX - // mov eax, [ebp + v_memret_outaddr] - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_EAX, REG_EBP, v_memret_outaddr); - } - } - - void GenContext::GenerateCallHooks(int v_status, int v_prev_res, int v_cur_res, int v_iter, - int v_pContext, int base_param_offset, int v_plugin_ret, int v_place_for_memret, jit_int32_t v_place_fbrr_base, jit_int32_t v_va_buf) - { - jitoffs_t counter, tmppos; - jitoffs_t counter2, tmppos2; - - jitoffs_t loop_begin_counter; - - // prev_res = MRES_IGNORED - IA32_Mov_Rm_Imm32_Disp8(&m_HookFunc, REG_EBP, MRES_IGNORED, v_prev_res); - - m_HookFunc.start_count(loop_begin_counter); - - // eax = pContext->GetNext() - // ECX = pContext - // gcc: push ecx - // eax = [ecx] - // eax = [eax] - // call eax - // gcc: clean up - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_ECX, REG_EBP, v_pContext); - GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX)); - - // vtbloffs=0, vtblidx=0 - IA32_Mov_Reg_Rm(&m_HookFunc, REG_EAX, REG_ECX, MOD_MEM_REG); - IA32_Mov_Reg_Rm(&m_HookFunc, REG_EAX, REG_EAX, MOD_MEM_REG); - IA32_Call_Reg(&m_HookFunc, REG_EAX); - GCC_ONLY(IA32_Pop_Reg(&m_HookFunc, REG_ECX)); - - // quit on zero - // test eax, eax - // jz exit - IA32_Test_Rm_Reg(&m_HookFunc, REG_EAX, REG_EAX, MOD_REG); - tmppos = IA32_Jump_Cond_Imm32(&m_HookFunc, CC_Z, 0); - m_HookFunc.start_count(counter); - - // prev_res = MRES_IGNORED - IA32_Mov_Rm_Imm32_Disp8(&m_HookFunc, REG_EBP, MRES_IGNORED, v_cur_res); - - // iter->call() - // push params - // ecx = eax - // gcc: push ecx - // eax = [ecx] - // eax = [eax+2*SIZE_PTR] - // call eax - // gcc: clean up - - jit_int32_t caller_clean_bytes = 0; // gcc always, msvc never (hooks never have varargs!) - - jit_int32_t alignBytes = AlignStackBeforeCall( - GetParamsTotalStackSize() + ((m_Proto.GetConvention() & ProtoInfo::CallConv_HasVafmt)!=0 ? SIZE_PTR : 0), - AlignStack_GCC_ThisOnStack | ((m_Proto.GetRet().flags & PassInfo::PassFlag_RetMem) == 0 ? 0 : AlignStack_MemRet) - ); - - // vafmt: push va_buf - if (m_Proto.GetConvention() & ProtoInfo::CallConv_HasVafmt) - { - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_va_buf); - IA32_Push_Reg(&m_HookFunc, REG_ECX); - caller_clean_bytes += SIZE_PTR; - } - - caller_clean_bytes += PushParams(base_param_offset, v_plugin_ret, v_place_for_memret, v_place_fbrr_base); - - IA32_Mov_Reg_Rm(&m_HookFunc, REG_ECX, REG_EAX, MOD_REG); - if (SH_COMP == SH_COMP_GCC) - IA32_Push_Reg(&m_HookFunc, REG_ECX); - caller_clean_bytes += PushMemRetPtr(v_plugin_ret, v_place_for_memret); - IA32_Mov_Reg_Rm(&m_HookFunc, REG_EAX, REG_ECX, MOD_MEM_REG); - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_EAX, REG_EAX, 2*SIZE_PTR); - CheckAlignmentBeforeCall(); - IA32_Call_Reg(&m_HookFunc, REG_EAX); - - AlignStackAfterCall(alignBytes); - - // cleanup (gcc only) - // params + thisptr - if (SH_COMP == SH_COMP_GCC) - IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, caller_clean_bytes + SIZE_PTR, MOD_REG); - - DestroyParams(v_place_fbrr_base); - - SaveRetVal(v_plugin_ret, v_place_for_memret); - - // process meta return: - // prev_res = cur_res - // if (cur_res > status) status = cur_res; - // - // eax = cur_res - // edx = status - // prev_res = eax - // cmp eax,edx - // jng thelabel - // status = eax - // thelabel: - // - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_EAX, REG_EBP, v_cur_res); - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_EDX, REG_EBP, v_status); - IA32_Mov_Rm_Reg_Disp8(&m_HookFunc, REG_EBP, REG_EAX, v_prev_res); - - IA32_Cmp_Reg_Rm(&m_HookFunc, REG_EAX, REG_EDX, MOD_REG); - tmppos2 = IA32_Jump_Cond_Imm8(&m_HookFunc, CC_NG, 0); - m_HookFunc.start_count(counter2); - - IA32_Mov_Rm_Reg_Disp8(&m_HookFunc, REG_EBP, REG_EAX, v_status); - - m_HookFunc.end_count(counter2); - m_HookFunc.rewrite(tmppos2, static_cast(counter2)); - - // process retval for non-void functions - ProcessPluginRetVal(v_cur_res, v_pContext, v_plugin_ret); - - // jump back to loop begin - tmppos2 = IA32_Jump_Imm32(&m_HookFunc, 0); - m_HookFunc.end_count(loop_begin_counter); - m_HookFunc.rewrite(tmppos2, -static_cast(loop_begin_counter)); - - m_HookFunc.end_count(counter); - m_HookFunc.rewrite(tmppos, static_cast(counter)); - } - - void GenContext::GenerateCallOrig(int v_status, int v_pContext, int param_base_offs, int v_this, - int v_vfnptr_origentry, int v_orig_ret, int v_override_ret, int v_place_for_memret, jit_int32_t v_place_fbrr_base, jit_int32_t v_va_buf) - { - jitoffs_t counter, tmppos; - jitoffs_t counter2, tmppos2; - jitoffs_t counter3, tmppos3; - - // if (status != MRES_SUPERCEDE && pConteext->ShouldCallOrig()) - // *v_orig_ret = orig_call() - // else - // *v_orig_ret = *v_override_ret - - // mov eax, status - // cmp eax, MRES_SUPERCEDE - // je dont_call - // call pContext->ShouldCallOrig() - // test al, al !! important: al, not eax! bool is only stored in the LSbyte - // jz dont_call - // - // orig_call() - // SaveRet(v_orig_ret) - // jmp skip_dont_call: - // - // dont_call: - // *v_orig_ret = *v_override_ret - // skip_dont_call: - - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_EAX, REG_EBP, v_status); - IA32_Cmp_Rm_Imm32(&m_HookFunc, MOD_REG, REG_EAX, MRES_SUPERCEDE); - - tmppos = IA32_Jump_Cond_Imm32(&m_HookFunc, CC_E, 0); - m_HookFunc.start_count(counter); - - // eax = pContext->ShouldCallOrig() - // ECX = pContext - // gcc: push ecx - // eax = [ecx] - // eax = [eax + 3*SIZE_PTR] - // call eax - // gcc: clean up - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_ECX, REG_EBP, v_pContext); - GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX)); - - // vtbloffs=0, vtblidx=3 - IA32_Mov_Reg_Rm(&m_HookFunc, REG_EAX, REG_ECX, MOD_MEM_REG); - IA32_Mov_Reg_Rm_Disp8(&m_HookFunc, REG_EAX, REG_EAX, 3*SIZE_PTR); - IA32_Call_Reg(&m_HookFunc, REG_EAX); - GCC_ONLY(IA32_Pop_Reg(&m_HookFunc, REG_ECX)); - - IA32_Test_Rm_Reg8(&m_HookFunc, REG_EAX, REG_EAX, MOD_REG); - tmppos2 = IA32_Jump_Cond_Imm32(&m_HookFunc, CC_Z, 0); - m_HookFunc.start_count(counter2); - - jit_int32_t caller_clean_bytes = 0; // gcc always, msvc when cdecl-like (varargs) - - jit_int32_t alignBytes = AlignStackBeforeCall( - GetParamsTotalStackSize() + ((m_Proto.GetConvention() & ProtoInfo::CallConv_HasVafmt)!=0 ? 2*SIZE_PTR : 0), - AlignStack_GCC_ThisOnStack | - ((m_Proto.GetRet().flags & PassInfo::PassFlag_RetMem) == 0 ? 0 : AlignStack_MemRet) | - ((m_Proto.GetConvention() & ProtoInfo::CallConv_HasVarArgs) == 0 ? 0 : AlignStack_MSVC_ThisOnStack) - ); - - // vafmt: push va_buf, then "%s" - if (m_Proto.GetConvention() & ProtoInfo::CallConv_HasVafmt) - { - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_va_buf); - IA32_Push_Reg(&m_HookFunc, REG_ECX); - IA32_Push_Imm32(&m_HookFunc, DownCastPtr("%s")); - caller_clean_bytes += 2*SIZE_PTR; - } - - // push params - caller_clean_bytes += PushParams(param_base_offs, v_orig_ret, v_place_for_memret, v_place_fbrr_base); - - // thisptr - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_ECX, REG_EBP, v_this); - if (SH_COMP == SH_COMP_GCC) - { - // on gcc/mingw, this is the first parameter - IA32_Push_Reg(&m_HookFunc, REG_ECX); - // on msvc without varargs, simply leave it in ecx - - // actually, if we're returning in memory, this pointer is the second param - // and the memret pointer is the real first parameter - caller_clean_bytes += PushMemRetPtr(v_orig_ret, v_place_for_memret); - } - else - { - // On msvc, if we're returning in memory, the memret pointer is the first parameter - caller_clean_bytes += PushMemRetPtr(v_orig_ret, v_place_for_memret); - - // actually, with varargs, the this pointer is the first param and the memret ptr - // is the second one - if (m_Proto.GetConvention() & ProtoInfo::CallConv_HasVarArgs) - { - IA32_Push_Reg(&m_HookFunc, REG_ECX); - } - } - - // call - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_EAX, REG_EBP, v_vfnptr_origentry); - CheckAlignmentBeforeCall(); - IA32_Call_Reg(&m_HookFunc, REG_EAX); - - AlignStackAfterCall(alignBytes); - - // cleanup - if (SH_COMP == SH_COMP_GCC || (m_Proto.GetConvention() & ProtoInfo::CallConv_HasVarArgs)) - IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, caller_clean_bytes + SIZE_PTR, MOD_REG); - - DestroyParams(v_place_fbrr_base); - - // save retval - SaveRetVal(v_orig_ret, v_place_for_memret); - - // Skip don't call variant - tmppos3 = IA32_Jump_Imm32(&m_HookFunc, 0); - m_HookFunc.start_count(counter3); - - - // don't call: - m_HookFunc.end_count(counter); - m_HookFunc.rewrite(tmppos, static_cast(counter)); - - m_HookFunc.end_count(counter2); - m_HookFunc.rewrite(tmppos2, static_cast(counter2)); - - // *v_orig_ret = *v_override_ret - if (m_Proto.GetRet().flags & PassInfo::PassFlag_ByRef) - { - // mov ecx, [ebp + v_override_ret] - // mov [ebp + v_orig_ret], ecx - - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_ECX, REG_EBP, v_override_ret); - IA32_Mov_Rm_Reg_DispAuto(&m_HookFunc, REG_EBP, REG_ECX, v_orig_ret); - } - else - { - if (m_Proto.GetRet().pAssignOperator) - { - // lea edx, [ebp + v_override_ret] <-- src addr - // lea ecx, [ebp + v_orig_ret] <-- dest addr - // push edx <-- src addr - // gcc: push ecx - // call it - // gcc: clean up - - jit_int32_t tmpAlign = AlignStackBeforeCall(SIZE_PTR, AlignStack_GCC_ThisOnStack); - - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_EDX, REG_EBP, v_override_ret); - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_orig_ret); - IA32_Push_Reg(&m_HookFunc, REG_EDX); - GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX)); - - IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pAssignOperator)); - CheckAlignmentBeforeCall(); - IA32_Call_Reg(&m_HookFunc, REG_EAX); - GCC_ONLY(IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_ESP, 2*SIZE_PTR, MOD_REG)); - - AlignStackAfterCall(tmpAlign); - } - else - { - // bitwise copy - BitwiseCopy_Setup(); - - //lea edi, [ebp+v_orig_ret] <-- destination - //lea esi, [ebp+v_override_ret] <-- src - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_EDI, REG_EBP, v_orig_ret); - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ESI, REG_EBP, v_override_ret); - - BitwiseCopy_Do(m_Proto.GetRet().size); - } - } - - // skip don't call label target: - m_HookFunc.end_count(counter3); - m_HookFunc.rewrite(tmppos3, static_cast(counter3)); - } - - // Sets *v_pContext to return value - void GenContext::CallSetupHookLoop(int v_orig_ret, int v_override_ret, - int v_cur_res, int v_prev_res, int v_status, int v_vfnptr_origentry, - int v_this, int v_pContext) - { - // call shptr->SetupHookLoop(ms_HI, ourvfnptr, reinterpret_cast(this), - // &vfnptr_origentry, &status, &prev_res, &cur_res, &orig_ret, &override_ret); - // The last two params are null for void funcs. - - if (m_Proto.GetRet().size == 0) - { - // void - IA32_Push_Imm8(&m_HookFunc, 0); // orig_ret - IA32_Push_Imm8(&m_HookFunc, 0); // override_ret - } - else - { - // orig_ret and override_ret - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_EAX, REG_EBP, v_override_ret); - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_EDX, REG_EBP, v_orig_ret); - IA32_Push_Reg(&m_HookFunc, REG_EAX); - IA32_Push_Reg(&m_HookFunc, REG_EDX); - } - - // cur_res and prev_res - IA32_Lea_DispRegImm8(&m_HookFunc, REG_EAX, REG_EBP, v_cur_res); - IA32_Lea_DispRegImm8(&m_HookFunc, REG_EDX, REG_EBP, v_prev_res); - IA32_Push_Reg(&m_HookFunc, REG_EAX); - IA32_Push_Reg(&m_HookFunc, REG_EDX); - - // status and vfnptr_origentry - IA32_Lea_DispRegImm8(&m_HookFunc, REG_EAX, REG_EBP, v_status); - IA32_Lea_DispRegImm8(&m_HookFunc, REG_EDX, REG_EBP, v_vfnptr_origentry); - IA32_Push_Reg(&m_HookFunc, REG_EAX); - IA32_Push_Reg(&m_HookFunc, REG_EDX); - - // this - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_EAX, REG_EBP, v_this); - IA32_Push_Reg(&m_HookFunc, REG_EAX); - - // our vfn ptr - // *(this + vtbloffs) + SIZE_PTR*vtblidx - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_ECX, REG_EBP, v_this); // get this into ecx (gcc!) - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_EAX, REG_ECX, m_VtblOffs); - IA32_Add_Rm_ImmAuto(&m_HookFunc, REG_EAX, m_VtblIdx * SIZE_PTR, MOD_REG); - IA32_Push_Reg(&m_HookFunc, REG_EAX); - - // *m_pHI - IA32_Mov_Rm_Imm32(&m_HookFunc, REG_EDX, DownCastPtr(m_pHI), MOD_REG); - IA32_Mov_Reg_Rm(&m_HookFunc, REG_EAX, REG_EDX, MOD_MEM_REG); - IA32_Push_Reg(&m_HookFunc, REG_EAX); - - // set up thisptr -#if SH_COMP == SH_COMP_GCC - // on gcc/mingw, this is the first parameter - GCC_ONLY(IA32_Push_Imm32(&m_HookFunc, DownCastPtr(m_SHPtr))); -#elif SH_COMP == SH_COMP_MSVC - // on msvc, it's ecx - IA32_Mov_Reg_Imm32(&m_HookFunc, REG_ECX, DownCastPtr(m_SHPtr)); -#endif - - // call the function. vtbloffs = 0, vtblidx = 19 - // get vtptr into edx -- we know shptr on jit time -> dereference it here! - IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, - (*reinterpret_cast(m_SHPtr))[19]); - - IA32_Call_Reg(&m_HookFunc, REG_EAX); - - // on gcc/mingw, we have to clean up after the call - // 9 params + hidden thisptr param - GCC_ONLY(IA32_Add_Rm_Imm8(&m_HookFunc, REG_ESP, 10*SIZE_PTR, MOD_REG)); - - // store return value - IA32_Mov_Rm_Reg_Disp8(&m_HookFunc, REG_EBP, REG_EAX, v_pContext); - } - - void GenContext::CallEndContext(int v_pContext) - { - // call endcontext: - // shptr->EndContext(pContex) - IA32_Mov_Reg_Rm_DispAuto(&m_HookFunc, REG_EAX, REG_EBP, v_pContext); - IA32_Push_Reg(&m_HookFunc, REG_EAX); - - // thisptr -#if SH_COMP == SH_COMP_GCC - // on gcc/mingw, this is the first parameter - IA32_Push_Imm32(&m_HookFunc, DownCastPtr(m_SHPtr)); -#elif SH_COMP == SH_COMP_MSVC - // on msvc, it's ecx - IA32_Mov_Reg_Imm32(&m_HookFunc, REG_ECX, DownCastPtr(m_SHPtr)); -#endif - - // get vtptr into edx -- we know shptr on jit time -> dereference it here! - IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, - (*reinterpret_cast(m_SHPtr))[20]); - - IA32_Call_Reg(&m_HookFunc, REG_EAX); - - // on gcc/mingw, we have to clean up after the call - // 1 param + hidden thisptr param - GCC_ONLY(IA32_Add_Rm_Imm8(&m_HookFunc, REG_ESP, 2*SIZE_PTR, MOD_REG)); - } - - void GenContext::ResetFrame(jit_int32_t startOffset) - { - m_HookFunc_FrameOffset = startOffset; - m_HookFunc_FrameVarsSize = 0; - } - - jit_int32_t GenContext::AddVarToFrame(jit_int32_t size) - { - m_HookFunc_FrameOffset -= size; - m_HookFunc_FrameVarsSize += size; - return m_HookFunc_FrameOffset; - } - - jit_int32_t GenContext::ComputeVarsSize() - { - return m_HookFunc_FrameVarsSize; - } - - void * GenContext::GenerateHookFunc() - { - // prologue - IA32_Push_Reg(&m_HookFunc, REG_EBP); - IA32_Push_Reg(&m_HookFunc, REG_EBX); - IA32_Mov_Reg_Rm(&m_HookFunc, REG_EBP, REG_ESP, MOD_REG); - - jit_int32_t v_this = 0; - jit_int32_t param_base_offs = 0; - if (SH_COMP == SH_COMP_GCC || (m_Proto.GetConvention() & ProtoInfo::CallConv_HasVarArgs)) - { - // gcc or msvc with varargs: - v_this = 12; // first param - param_base_offs = 16; - ResetFrame(0); - } - else - { - // on msvc without varargs, save thisptr - v_this = -4; - param_base_offs = 12; - IA32_Push_Reg(&m_HookFunc, REG_ECX); - ResetFrame(-4); // start placing local vars on offset -4 - // because there already is the thisptr variable - } - - // ********************** stack frame ********************** - // MSVC without varargs - // second param (gcc: first real param) ebp + 16 - // first param (gcc: thisptr) ebp + 12 - // ret address: ebp + 8 - // caller's ebp ebp + 4 - // saved ebx ebp - // MSVC ONLY: current this ebp - 4 - // void *vfnptr_origentry ebp - 4 -4 - // META_RES status = MRES_IGNORED ebp - 8 -4 - // META_RES prev_res ebp - 12 -4 - // META_RES cur_res ebp - 16 -4 - // IMyDelegate *iter ebp - 20 -4 - // IHookContext *pContext ebp - 24 -4 - // == 3 ptrs + 3 enums = 24 bytes - // - // non-void: add: - // my_rettype *ret_ptr ebp - 28 -4 - // my_rettype orig_ret ebp - 28 - sizeof(my_rettype) -4 - // my_rettype override_ret ebp - 28 - sizeof(my_rettype)*2 -4 - // my_rettype plugin_ret ebp - 28 - sizeof(my_rettype)*3 -4 - // == + 3 * sizeof(my_rettype) bytes - - // if required: - // my_rettype place_for_memret ebp - 28 - sizeof(my_rettype)*4 -4 - - // gcc only: if required: - // place forced byref params ebp - 28 - sizeof(my_rettype)*{4 or 5} - // - // varargs: - // va_list argptr - // char va_buf[something]; - - - const jit_int8_t v_vfnptr_origentry = AddVarToFrame(SIZE_PTR); - const jit_int8_t v_status = AddVarToFrame(sizeof(META_RES)); - const jit_int8_t v_prev_res = AddVarToFrame(sizeof(META_RES)); - const jit_int8_t v_cur_res = AddVarToFrame(sizeof(META_RES)); - const jit_int8_t v_iter = AddVarToFrame(SIZE_PTR); - const jit_int8_t v_pContext = AddVarToFrame(SIZE_PTR); - - // Memory return: first param is the address - jit_int32_t v_memret_addr = 0; - if (m_Proto.GetRet().flags & PassInfo::PassFlag_RetMem) - { - if (SH_COMP == SH_COMP_GCC) - { - // gcc: now: first param = mem ret addr - // second param = this pointer - // third param = actual first param - v_memret_addr = 12; - v_this += 4; - param_base_offs += SIZE_PTR; - } - else // MSVC - { - if (m_Proto.GetConvention() & ProtoInfo::CallConv_HasVarArgs) - { - // varargs -> cdecl - // msvc: now: - // first param = this pointer - // second param = mem ret addr - // third param = actual first param - - // params_base_offs is already updated to point to after the this pointer - v_memret_addr = param_base_offs; - param_base_offs += SIZE_PTR; - } - else - { - v_memret_addr = param_base_offs; - param_base_offs += SIZE_PTR; - } - } - } - - jit_int32_t v_ret_ptr = 0; - jit_int32_t v_orig_ret = 0; - jit_int32_t v_override_ret = 0; - jit_int32_t v_plugin_ret = 0; - - if (m_Proto.GetRet().size != 0) - { - v_ret_ptr = AddVarToFrame(SIZE_PTR); - v_orig_ret = AddVarToFrame(GetParamStackSize(m_Proto.GetRet())); - v_override_ret = AddVarToFrame(GetParamStackSize(m_Proto.GetRet())); - v_plugin_ret = AddVarToFrame(GetParamStackSize(m_Proto.GetRet())); - } - - jit_int32_t v_place_for_memret = 0; - if (MemRetWithTempObj()) - { - v_place_for_memret = AddVarToFrame(GetParamStackSize(m_Proto.GetRet())); - } - - jit_int32_t v_place_fbrr_base = 0; - if (SH_COMP == SH_COMP_GCC && GetForcedByRefParamsSize()) - { - v_place_fbrr_base = AddVarToFrame(GetForcedByRefParamsSize()); - } - - // Only exists for varargs functions - jit_int32_t v_va_argptr = 0; - if (m_Proto.GetConvention() & ProtoInfo::CallConv_HasVarArgs) - { - v_va_argptr = AddVarToFrame(SIZE_PTR); - } - - jit_int32_t v_va_buf = 0; - if (m_Proto.GetConvention() & ProtoInfo::CallConv_HasVafmt) - { - v_va_buf = AddVarToFrame(SourceHook::STRBUF_LEN); - } - - IA32_Sub_Rm_Imm32(&m_HookFunc, REG_ESP, ComputeVarsSize(), MOD_REG); - - // Initial stack alignment - IA32_And_Rm_Imm32(&m_HookFunc, REG_ESP, MOD_REG, -16); - m_BytesPushedAfterInitialAlignment = 0; - - // init status localvar - IA32_Mov_Rm_Imm32_Disp8(&m_HookFunc, REG_EBP, MRES_IGNORED, v_status); - - // VarArgs: init argptr & format - if (m_Proto.GetConvention() & ProtoInfo::CallConv_HasVarArgs) - { - // argptr = first vararg param - // lea eax, [ebp + param_base_offs + paramssize] - // mov argptr, eax - - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_EAX, REG_EBP, param_base_offs + GetParamsTotalStackSize() + SIZE_PTR); // +SIZE_PTR: last const char * is not in protoinfo - IA32_Mov_Rm_Reg_DispAuto(&m_HookFunc, REG_EBP, REG_EAX, v_va_argptr); - } - if (m_Proto.GetConvention() & ProtoInfo::CallConv_HasVafmt) - { - // vsnprintf - - jit_int32_t tmpAlign = AlignStackBeforeCall(SIZE_PTR*3 + sizeof(size_t), 0); - - // push valist, fmt param, maxsize, buffer - IA32_Push_Reg(&m_HookFunc, REG_EAX); - IA32_Push_Rm_DispAuto(&m_HookFunc, REG_EBP, param_base_offs + GetParamsTotalStackSize()); // last given param (+4-4, see above) - IA32_Push_Imm32(&m_HookFunc, SourceHook::STRBUF_LEN - 1); - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_va_buf); - IA32_Push_Reg(&m_HookFunc, REG_ECX); - - // call - IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(&vsnprintf)); - CheckAlignmentBeforeCall(); - IA32_Call_Reg(&m_HookFunc, REG_EAX); - - // Clean up (cdecl) - IA32_Add_Rm_Imm32(&m_HookFunc, REG_ESP, 0x10, MOD_REG); - - AlignStackAfterCall(tmpAlign); - - // Set trailing zero - IA32_Xor_Reg_Rm(&m_HookFunc, REG_EDX, REG_EDX, MOD_REG); - IA32_Mov_Rm8_Reg8_DispAuto(&m_HookFunc, REG_EBP, REG_EDX, v_va_buf + SourceHook::STRBUF_LEN - 1); - } - - // Call constructors for ret vars if required - if((m_Proto.GetRet().flags & PassInfo::PassFlag_ByVal) && - m_Proto.GetRet().pNormalCtor) - { - jit_int32_t tmpAlign = AlignStackBeforeCall(0, AlignStack_GCC_ThisOnStack); - - // orig_reg - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_orig_ret); - GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX)); - IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pNormalCtor)); - CheckAlignmentBeforeCall(); - IA32_Call_Reg(&m_HookFunc, REG_EAX); - GCC_ONLY(IA32_Pop_Reg(&m_HookFunc, REG_ECX)); - - // override_reg - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_override_ret); - GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX)); - IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pNormalCtor)); - CheckAlignmentBeforeCall(); - IA32_Call_Reg(&m_HookFunc, REG_EAX); - GCC_ONLY(IA32_Pop_Reg(&m_HookFunc, REG_ECX)); - - // plugin_ret - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_plugin_ret); - GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX)); - IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pNormalCtor)); - CheckAlignmentBeforeCall(); - IA32_Call_Reg(&m_HookFunc, REG_EAX); - GCC_ONLY(IA32_Pop_Reg(&m_HookFunc, REG_ECX)); - - AlignStackAfterCall(tmpAlign); - - // _don't_ call a constructor for v_place_for_memret ! - } - - // ********************** SetupHookLoop ********************** - CallSetupHookLoop(v_orig_ret, v_override_ret, v_cur_res, v_prev_res, v_status, v_vfnptr_origentry, - v_this, v_pContext); - - // ********************** call pre hooks ********************** - GenerateCallHooks(v_status, v_prev_res, v_cur_res, v_iter, v_pContext, param_base_offs, - v_plugin_ret, v_place_for_memret, v_place_fbrr_base, v_va_buf); - - // ********************** call orig func ********************** - GenerateCallOrig(v_status, v_pContext, param_base_offs, v_this, v_vfnptr_origentry, v_orig_ret, - v_override_ret, v_place_for_memret, v_place_fbrr_base, v_va_buf); - - // ********************** call post hooks ********************** - GenerateCallHooks(v_status, v_prev_res, v_cur_res, v_iter, v_pContext, param_base_offs, - v_plugin_ret, v_place_for_memret, v_place_fbrr_base, v_va_buf); - - // ********************** end context and return ********************** - - PrepareReturn(v_status, v_pContext, v_ret_ptr); - - CallEndContext(v_pContext); - - // Call destructors of byval object params which have a destructor - - jit_int32_t tmpAlign = AlignStackBeforeCall(0, AlignStack_GCC_ThisOnStack); - - jit_int32_t cur_param_pos = param_base_offs; - for (int i = 0; i < m_Proto.GetNumOfParams(); ++i) - { - const IntPassInfo &pi = m_Proto.GetParam(i); - // GCC: NOT of forced byref params. the caller destructs those. - if (pi.type == PassInfo::PassType_Object && (pi.flags & PassInfo::PassFlag_ODtor) && - (pi.flags & PassInfo::PassFlag_ByVal) && !(pi.flags & PassFlag_ForcedByRef)) - { - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, cur_param_pos); - IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(pi.pDtor)); - GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX)); - CheckAlignmentBeforeCall(); - IA32_Call_Reg(&m_HookFunc, REG_EAX); - GCC_ONLY(IA32_Pop_Reg(&m_HookFunc, REG_ECX)); - } - cur_param_pos += GetParamStackSize(pi); - } - - AlignStackAfterCall(tmpAlign); - - DoReturn(v_ret_ptr, v_memret_addr); - - // Call destructors of orig_ret/ ... - if((m_Proto.GetRet().flags & PassInfo::PassFlag_ByVal) && - m_Proto.GetRet().pDtor) - { - // Preserve return value in EAX(:EDX) - IA32_Push_Reg(&m_HookFunc, REG_EAX); - IA32_Push_Reg(&m_HookFunc, REG_EDX); - - m_BytesPushedAfterInitialAlignment += 8; - - jit_int32_t tmpAlign = AlignStackBeforeCall(0, AlignStack_GCC_ThisOnStack); - - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_plugin_ret); - GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX)); - IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pDtor)); - CheckAlignmentBeforeCall(); - IA32_Call_Reg(&m_HookFunc, REG_EAX); - GCC_ONLY(IA32_Pop_Reg(&m_HookFunc, REG_ECX)); - - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_override_ret); - GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX)); - IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pDtor)); - CheckAlignmentBeforeCall(); - IA32_Call_Reg(&m_HookFunc, REG_EAX); - GCC_ONLY(IA32_Pop_Reg(&m_HookFunc, REG_ECX)); - - IA32_Lea_DispRegImmAuto(&m_HookFunc, REG_ECX, REG_EBP, v_orig_ret); - GCC_ONLY(IA32_Push_Reg(&m_HookFunc, REG_ECX)); - IA32_Mov_Reg_Imm32(&m_HookFunc, REG_EAX, DownCastPtr(m_Proto.GetRet().pDtor)); - CheckAlignmentBeforeCall(); - IA32_Call_Reg(&m_HookFunc, REG_EAX); - GCC_ONLY(IA32_Pop_Reg(&m_HookFunc, REG_ECX)); - - AlignStackAfterCall(tmpAlign); - - IA32_Pop_Reg(&m_HookFunc, REG_EDX); - IA32_Pop_Reg(&m_HookFunc, REG_EAX); - - m_BytesPushedAfterInitialAlignment -= 8; - } - - // epilogue - IA32_Mov_Reg_Rm(&m_HookFunc, REG_ESP, REG_EBP, MOD_REG); - IA32_Pop_Reg(&m_HookFunc, REG_EBX); - IA32_Pop_Reg(&m_HookFunc, REG_EBP); - - if (SH_COMP == SH_COMP_MSVC && !(m_Proto.GetConvention() & ProtoInfo::CallConv_HasVarArgs)) - { - // msvc without varargs: - // callee cleans the stack - - short cleansize = GetParamsTotalStackSize(); - // Memory return: address is first param - if (m_Proto.GetRet().flags & PassInfo::PassFlag_RetMem) - cleansize += SIZE_PTR; - - IA32_Return_Popstack(&m_HookFunc, cleansize); - } - else - { - // gcc or msvc with varargs: caller cleans the stack - // exception: gcc removes the memret addr on memret: - if (SH_COMP == SH_COMP_GCC && (m_Proto.GetRet().flags & PassInfo::PassFlag_RetMem)) - IA32_Return_Popstack(&m_HookFunc, SIZE_PTR); - else - IA32_Return(&m_HookFunc); - } - - - // Store pointer for later use - // m_HookfuncVfnPtr is a pointer to a void* because SH expects a pointer - // into the hookman's vtable - *m_HookfuncVfnptr = reinterpret_cast(m_HookFunc.GetData()); - - m_HookFunc.SetRE(); - - return m_HookFunc.GetData(); - } - - // Pre-condition: GenerateHookFunc() has been called! - void * GenContext::GeneratePubFunc() - { - jitoffs_t counter, tmppos; - - // The pubfunc is a static cdecl function. - // C Code: - // int HookManPubFunc( - // bool store, ebp + 8 - // IHookManagerInfo *hi ebp + 12 - // ) - // { - // if (store) - // *m_pHI = hi; - // if (hi) - // hi->SetInfo(HOOKMAN_VERSION, m_VtblOffs, m_VtblIdx, m_Proto.GetProto(), m_HookfuncVfnptr) - // } - - // prologue - IA32_Push_Reg(&m_PubFunc, REG_EBP); - IA32_Mov_Reg_Rm(&m_PubFunc, REG_EBP, REG_ESP, MOD_REG); - - - // save store in eax, hi in ecx - IA32_Movzx_Reg32_Rm8_Disp8(&m_PubFunc, REG_EAX, REG_EBP, 8); - IA32_Mov_Reg_Rm_DispAuto(&m_PubFunc, REG_ECX, REG_EBP, 12); - - // Check for store == 0 - IA32_Test_Rm_Reg8(&m_PubFunc, REG_EAX, REG_EAX, MOD_REG); - tmppos = IA32_Jump_Cond_Imm8(&m_PubFunc, CC_Z, 0); - m_PubFunc.start_count(counter); - - // nonzero -> store hi - IA32_Mov_Rm_Imm32(&m_PubFunc, REG_EDX, DownCastPtr(m_pHI), MOD_REG); - IA32_Mov_Rm_Reg(&m_PubFunc, REG_EDX, REG_ECX, MOD_MEM_REG); - - // zero - m_PubFunc.end_count(counter); - m_PubFunc.rewrite(tmppos, static_cast(counter)); - - // check for hi == 0 - IA32_Test_Rm_Reg(&m_PubFunc, REG_ECX, REG_ECX, MOD_REG); - tmppos = IA32_Jump_Cond_Imm8(&m_PubFunc, CC_Z, 0); - m_PubFunc.start_count(counter); - - // nonzero -> call vfunc - // push params in reverse order - IA32_Push_Imm32(&m_PubFunc, DownCastPtr(m_HookfuncVfnptr)); - IA32_Push_Imm32(&m_PubFunc, DownCastPtr(m_BuiltPI)); - IA32_Push_Imm32(&m_PubFunc, m_VtblIdx); - IA32_Push_Imm32(&m_PubFunc, m_VtblOffs); - IA32_Push_Imm32(&m_PubFunc, SH_HOOKMAN_VERSION); - - // hi == this is in ecx - // on gcc/mingw, ecx is the first parameter -#if SH_COMP == SH_COMP_GCC - IA32_Push_Reg(&m_PubFunc, REG_ECX); -#endif - - // call the function. vtbloffs = 0, vtblidx = 0 - // get vtptr into edx - IA32_Mov_Reg_Rm(&m_PubFunc, REG_EDX, REG_ECX, MOD_MEM_REG); - // get funcptr into eax - IA32_Mov_Reg_Rm(&m_PubFunc, REG_EAX, REG_EDX, MOD_MEM_REG); - - IA32_Call_Reg(&m_PubFunc, REG_EAX); - - // on gcc/mingw, we have to clean up after the call -#if SH_COMP == SH_COMP_GCC - // 5 params + hidden thisptr param - IA32_Add_Rm_Imm8(&m_PubFunc, REG_ESP, 6*SIZE_MWORD, MOD_REG); -#endif - - // zero - m_PubFunc.end_count(counter); - m_PubFunc.rewrite(tmppos, static_cast(counter)); - - // return value - IA32_Xor_Reg_Rm(&m_PubFunc, REG_EAX, REG_EAX, MOD_REG); - - // epilogue - IA32_Mov_Reg_Rm(&m_PubFunc, REG_ESP, REG_EBP, MOD_REG); - IA32_Pop_Reg(&m_PubFunc, REG_EBP); - IA32_Return(&m_PubFunc); - - m_PubFunc.SetRE(); - - return m_PubFunc; - } - - bool GenContext::PassInfoSupported(const IntPassInfo &pi, bool is_ret) - { - // :TODO: Error returns - if (pi.type != PassInfo::PassType_Basic && - pi.type != PassInfo::PassType_Float && - pi.type != PassInfo::PassType_Object) - { - return false; - } - - if (pi.type == PassInfo::PassType_Object && - (pi.flags & PassInfo::PassFlag_ByVal)) - { - if ((pi.flags & PassInfo::PassFlag_CCtor) && !pi.pCopyCtor) - { - return false; - } - - if ((pi.flags & PassInfo::PassFlag_ODtor) && !pi.pDtor) - { - return false; - } - - if ((pi.flags & PassInfo::PassFlag_AssignOp) && !pi.pAssignOperator) - { - return false; - } - - if ((pi.flags & PassInfo::PassFlag_OCtor) && !pi.pNormalCtor) - { - return false; - } - } - - if ((pi.flags & (PassInfo::PassFlag_ByVal | PassInfo::PassFlag_ByRef)) == 0) - { - return false; // Neither byval nor byref! - } - return true; - } - - void GenContext::AutoDetectRetType() - { - IntPassInfo &pi = m_Proto.GetRet(); - - // Only relevant for byval types - if (pi.flags & PassInfo::PassFlag_ByVal) - { - // Basic + float: - if (pi.type == PassInfo::PassType_Basic || - pi.type == PassInfo::PassType_Float) - { - // <= 8 bytes: - // _always_ in registers, no matter what the user says - if (pi.size <= 8) - { - pi.flags &= ~PassInfo::PassFlag_RetMem; - pi.flags |= PassInfo::PassFlag_RetReg; - } - else - { - // Does this even exist? No idea, if it does: in memory! - pi.flags &= ~PassInfo::PassFlag_RetReg; - pi.flags |= PassInfo::PassFlag_RetMem; - } - } - // Object: - else if (pi.type == PassInfo::PassType_Object) - { - // If the user says nothing, auto-detect - if ((pi.flags & (PassInfo::PassFlag_RetMem | PassInfo::PassFlag_RetReg)) == 0) - { -#if SH_COMP == SH_COMP_MSVC - // MSVC seems to return _all_ structs, classes, unions in memory - pi.flags |= PassInfo::PassFlag_RetMem; -#elif SH_COMP == SH_COMP_GCC -#if SH_SYS == SH_SYS_APPLE - // Apple GCC returns in memory if size isn't a power of 2 or > 8 - if ((pi.size & (pi.size - 1)) == 0 && pi.size <= 8) - { - pi.flags |= PassInfo::PassFlag_RetReg; - } - else -#endif - { - // GCC on Linux does same thing as MSVC - pi.flags |= PassInfo::PassFlag_RetMem; - } -#endif - } - } - } - else - { - // byref: make sure that the flag is _not_ set - pi.flags &= ~PassInfo::PassFlag_RetMem; - pi.flags |= PassInfo::PassFlag_RetReg; - } - } - - void GenContext::AutoDetectParamFlags() - { -#if SH_COMP == SH_COMP_GCC - // On GCC, all objects are passed by reference if they have a destructor - for (int i = 0; i < m_Proto.GetNumOfParams(); ++i) - { - IntPassInfo &pi = m_Proto.GetParam(i); - if (pi.type == PassInfo::PassType_Object && (pi.flags & PassInfo::PassFlag_ByVal) && - (pi.flags & PassInfo::PassFlag_ODtor)) - { - pi.flags |= PassFlag_ForcedByRef; - } - } -#endif - } - - HookManagerPubFunc GenContext::Generate() - { - Clear(); - - // Check conditions: - // -1) good proto version - // 0) we don't support unknown passtypes, convention, ... - // 1) we don't support functions which return objects by value or take parameters by value - // that have a constructor, a destructor or an overloaded assignment op - // (we wouldn't know how to call it!) - - if (m_Proto.GetVersion() < 1) - { - return NULL; - } - - AutoDetectRetType(); - AutoDetectParamFlags(); - - // Basically, we only support ThisCall/thiscall with varargs - if ((m_Proto.GetConvention() & (~ProtoInfo::CallConv_HasVafmt)) != ProtoInfo::CallConv_ThisCall) - { - return NULL; - } - - - if (m_Proto.GetRet().size != 0 && !PassInfoSupported(m_Proto.GetRet(), true)) - { - return NULL; - } - - for (int i = 0; i < m_Proto.GetNumOfParams(); ++i) - { - if (!PassInfoSupported(m_Proto.GetParam(i), false)) - return NULL; - } - - BuildProtoInfo(); - GenerateHookFunc(); - return fastdelegate::detail::horrible_cast(GeneratePubFunc()); - } - - HookManagerPubFunc GenContext::GetPubFunc() - { - if (m_GeneratedPubFunc == 0) - m_GeneratedPubFunc = Generate(); - - return m_GeneratedPubFunc; - } - - bool GenContext::Equal(const CProto &proto, int vtbl_offs, int vtbl_idx) - { - return (m_OrigProto.ExactlyEqual(proto) && m_VtblOffs == vtbl_offs && m_VtblIdx == vtbl_idx); - } - - bool GenContext::Equal(HookManagerPubFunc other) - { - return m_GeneratedPubFunc == other; - } - - // *********************************** class GenContextContainer - CHookManagerAutoGen::CHookManagerAutoGen(ISourceHook *pSHPtr) : m_pSHPtr(pSHPtr) - { - } - - CHookManagerAutoGen::~CHookManagerAutoGen() - { - for (List::iterator iter = m_Contexts.begin(); iter != m_Contexts.end(); ++iter) - { - delete iter->m_GenContext; - } - } - - int CHookManagerAutoGen::GetIfaceVersion() - { - return SH_HOOKMANAUTOGEN_IFACE_VERSION; - } - - int CHookManagerAutoGen::GetImplVersion() - { - return SH_HOOKMANAUTOGEN_IMPL_VERSION; - } - - HookManagerPubFunc CHookManagerAutoGen::MakeHookMan(const ProtoInfo *proto, int vtbl_offs, int vtbl_idx) - { - CProto mproto(proto); - for (List::iterator iter = m_Contexts.begin(); iter != m_Contexts.end(); ++iter) - { - if (iter->m_GenContext->Equal(mproto, vtbl_offs, vtbl_idx)) - { - iter->m_RefCnt++; - return iter->m_GenContext->GetPubFunc(); - } - } - - // Not found yet -> new one - StoredContext sctx; - sctx.m_RefCnt = 1; - sctx.m_GenContext = new GenContext(proto, vtbl_offs, vtbl_idx, m_pSHPtr); - - if (sctx.m_GenContext->GetPubFunc() == NULL) - { - return NULL; - } - else - { - m_Contexts.push_back(sctx); - return sctx.m_GenContext->GetPubFunc(); - } - } - - void CHookManagerAutoGen::ReleaseHookMan(HookManagerPubFunc pubFunc) - { - for (List::iterator iter = m_Contexts.begin(); iter != m_Contexts.end(); ++iter) - { - if (iter->m_GenContext->Equal(pubFunc)) - { - iter->m_RefCnt--; - if (iter->m_RefCnt == 0) - { - delete iter->m_GenContext; - m_Contexts.erase(iter); - } - break; - } - } - } - } -} diff --git a/utils/mmsource/core/sourcehook/sourcehook_hookmangen.h b/utils/mmsource/core/sourcehook/sourcehook_hookmangen.h deleted file mode 100644 index 392993418..000000000 --- a/utils/mmsource/core/sourcehook/sourcehook_hookmangen.h +++ /dev/null @@ -1,299 +0,0 @@ -/* ======== SourceHook ======== -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko -* ============================ -*/ - -#ifndef __SOURCEHOOK_HOOKMANGEN_H__ -#define __SOURCEHOOK_HOOKMANGEN_H__ - -#include "sh_pagealloc.h" - -namespace SourceHook -{ - namespace Impl - { - - // Code gen stuff -#if SH_COMP == SH_COMP_GCC -#include - typedef int8_t jit_int8_t; - typedef uint8_t jit_uint8_t; - typedef int32_t jit_int32_t; - typedef uint32_t jit_uint32_t; - typedef int64_t jit_int64_t; - typedef uint64_t jit_uint64_t; -#elif SH_COMP == SH_COMP_MSVC - typedef __int8 jit_int8_t; - typedef unsigned __int8 jit_uint8_t; - typedef __int32 jit_int32_t; - typedef unsigned __int32 jit_uint32_t; - typedef __int64 jit_int64_t; - typedef unsigned __int64 jit_uint64_t; -#endif - typedef unsigned int jitoffs_t; - typedef signed int jitrel_t; - - - class GenBuffer - { - static CPageAlloc ms_Allocator; - - unsigned char *m_pData; - jitoffs_t m_Size; - jitoffs_t m_AllocatedSize; - - public: - GenBuffer() : m_pData(NULL), m_Size(0), m_AllocatedSize(0) - { - } - ~GenBuffer() - { - clear(); - } - jitoffs_t GetSize() - { - return m_Size; - } - unsigned char *GetData() - { - return m_pData; - } - - template void push(PT what) - { - push((const unsigned char *)&what, sizeof(PT)); - } - - void push(const unsigned char *data, jitoffs_t size) - { - jitoffs_t newSize = m_Size + size; - if (newSize > m_AllocatedSize) - { - m_AllocatedSize = newSize > m_AllocatedSize*2 ? newSize : m_AllocatedSize*2; - if (m_AllocatedSize < 64) - m_AllocatedSize = 64; - - unsigned char *newBuf; - newBuf = reinterpret_cast(ms_Allocator.Alloc(m_AllocatedSize)); - ms_Allocator.SetRW(newBuf); - if (!newBuf) - { - SH_ASSERT(0, ("bad_alloc: couldn't allocate 0x%08X bytes of memory\n", m_AllocatedSize)); - return; - } - memset((void*)newBuf, 0xCC, m_AllocatedSize); // :TODO: remove this ! - memcpy((void*)newBuf, (const void*)m_pData, m_Size); - if (m_pData) - { - ms_Allocator.SetRE(reinterpret_cast(m_pData)); - ms_Allocator.SetRW(newBuf); - ms_Allocator.Free(reinterpret_cast(m_pData)); - } - m_pData = newBuf; - } - memcpy((void*)(m_pData + m_Size), (const void*)data, size); - m_Size = newSize; - } - - template void rewrite(jitoffs_t offset, PT what) - { - rewrite(offset, (const unsigned char *)&what, sizeof(PT)); - } - - void rewrite(jitoffs_t offset, const unsigned char *data, jitoffs_t size) - { - SH_ASSERT(offset + size <= m_AllocatedSize, ("rewrite too far")); - - memcpy((void*)(m_pData + offset), (const void*)data, size); - } - - void clear() - { - if (m_pData) - ms_Allocator.Free(reinterpret_cast(m_pData)); - m_pData = NULL; - m_Size = 0; - m_AllocatedSize = 0; - } - - void SetRE() - { - ms_Allocator.SetRE(reinterpret_cast(m_pData)); - } - - operator void *() - { - return reinterpret_cast(GetData()); - } - - void write_ubyte(jit_uint8_t x) { push(x); } - void write_byte(jit_uint8_t x) { push(x); } - - void write_ushort(unsigned short x) { push(x); } - void write_short(signed short x) { push(x); } - - void write_uint32(jit_uint32_t x) { push(x); } - void write_int32(jit_uint32_t x) { push(x); } - - jitoffs_t get_outputpos() - { - return m_Size; - } - - void start_count(jitoffs_t &offs) - { - offs = get_outputpos(); - } - void end_count(jitoffs_t &offs) - { - offs = get_outputpos() - offs; - } - }; - - class GenContext - { - const static int SIZE_MWORD = 4; - const static int SIZE_PTR = sizeof(void*); - const static int PassFlag_ForcedByRef = (1<<30); // ByVal in source, but actually passed by reference (GCC) -> private pass, destruct - - HookManagerPubFunc m_GeneratedPubFunc; - - CProto m_OrigProto; // original passed-in prototype - CProto m_Proto; - int m_VtblOffs; - int m_VtblIdx; - ISourceHook *m_SHPtr; - - GenBuffer m_HookFunc; - GenBuffer m_PubFunc; - - ProtoInfo *m_BuiltPI; - PassInfo *m_BuiltPI_Params; - PassInfo::V2Info *m_BuiltPI_Params2; - - // For hookfunc - void **m_pHI; - void **m_HookfuncVfnptr; - - // Level 3 - Helpers - int m_RegCounter; - jit_int8_t NextRegEBX_ECX_EDX(); - - int m_BytesPushedAfterInitialAlignment; - enum AlignStackFlags - { - AlignStack_GCC_ThisOnStack = 1, - AlignStack_MSVC_ThisOnStack = 2, - AlignStack_MemRet = 4 - }; - jit_int32_t AlignStackBeforeCall(int paramsize, int flags); - void AlignStackAfterCall(jit_int32_t numofbytes); - void CheckAlignmentBeforeCall(); - - // size info - jit_int32_t GetRealSize(const IntPassInfo &info); // checks for reference - jit_int32_t AlignSize(jit_int32_t x, jit_int32_t boundary); // align a size - jit_int32_t GetParamStackSize(const IntPassInfo &info); // get the size of a param in the param stack - short GetParamsTotalStackSize(); // sum(GetParamStackSize(param[i]), 0 <= i < numOfParams) - - // Helpers - void BitwiseCopy_Setup(); - void BitwiseCopy_Do(size_t size); - - - // HookFunc frame - jit_int32_t m_HookFunc_FrameOffset; - jit_int32_t m_HookFunc_FrameVarsSize; - - void ResetFrame(jit_int32_t startOffset); - jit_int32_t AddVarToFrame(jit_int32_t size); - jit_int32_t ComputeVarsSize(); - - // Param push - short GetForcedByRefParamsSize(); // sum(param[i] is forcedbyref ? GetStackSize(param[i]) : 0, 0 <= i < numOfParams) - short GetForcedByRefParamOffset(int p); // sum(param[i] is forcedbyref ? GetStackSize(param[i]) : 0, 0 <= i < p) - jit_int32_t PushParams(jit_int32_t param_base_offset, jit_int32_t save_ret_to, - jit_int32_t v_place_for_memret, jit_int32_t v_place_fbrr_base); // save_ret_to and v_place_for_memret only used for memory returns - jit_int32_t PushRef(jit_int32_t param_offset, const IntPassInfo &pi); - jit_int32_t PushBasic(jit_int32_t param_offset, const IntPassInfo &pi); - jit_int32_t PushFloat(jit_int32_t param_offset, const IntPassInfo &pi); - jit_int32_t PushObject(jit_int32_t param_offset, const IntPassInfo &pi, jit_int32_t v_place_fbrr); - jit_int32_t PushMemRetPtr(jit_int32_t save_ret_to, jit_int32_t v_place_for_memret); - void DestroyParams(jit_int32_t fbrr_base); - - // Ret val processing - void SaveRetVal(jit_int32_t v_where, jit_int32_t v_place_for_memret); - void ProcessPluginRetVal(jit_int32_t v_cur_res, jit_int32_t v_pContext, jit_int32_t v_plugin_ret); - - void PrepareReturn(jit_int32_t v_status, jit_int32_t v_pContext, jit_int32_t v_retptr); - void DoReturn(jit_int32_t v_retptr, jit_int32_t v_memret_outaddr); - - bool MemRetWithTempObj(); // do we do a memory return AND need a temporary place for it? - - // Call hooks - void GenerateCallHooks(int v_status, int v_prev_res, int v_cur_res, int v_iter, - int v_pContext, int base_param_offset, int v_plugin_ret, int v_place_for_memret, jit_int32_t v_place_fbrr_base, jit_int32_t v_va_buf); - - // Call orig - void GenerateCallOrig(int v_status, int v_pContext, int param_base_offs, int v_this, - int v_vfnptr_origentry, int v_orig_ret, int v_override_ret, int v_place_for_memret, jit_int32_t v_place_fbrr_base, jit_int32_t v_va_buf); - - // Hook loop - void CallSetupHookLoop(int v_orig_ret, int v_override_ret, - int v_cur_res, int v_prev_res, int v_status, int v_vnfptr_origentry, - int v_this, int v_pContext); - - void CallEndContext(int v_pContext); - - // Level 2 -> called from Generate() - void AutoDetectRetType(); - void AutoDetectParamFlags(); - bool PassInfoSupported(const IntPassInfo &pi, bool is_ret); - void Clear(); - void BuildProtoInfo(); - void *GenerateHookFunc(); - void *GeneratePubFunc(); - - HookManagerPubFunc Generate(); - public: - // Level 1 -> Public interface - GenContext(const ProtoInfo *proto, int vtbl_offs, int vtbl_idx, ISourceHook *pSHPtr); - ~GenContext(); - - bool Equal(const CProto &proto, int vtbl_offs, int vtbl_idx); - bool Equal(HookManagerPubFunc other); - - HookManagerPubFunc GetPubFunc(); - }; - - class CHookManagerAutoGen : public IHookManagerAutoGen - { - struct StoredContext - { - int m_RefCnt; - GenContext *m_GenContext; - }; - List m_Contexts; - ISourceHook *m_pSHPtr; - - public: - CHookManagerAutoGen(ISourceHook *pSHPtr); - ~CHookManagerAutoGen(); - - int GetIfaceVersion(); - int GetImplVersion(); - - HookManagerPubFunc MakeHookMan(const ProtoInfo *proto, int vtbl_offs, int vtbl_idx); - void ReleaseHookMan(HookManagerPubFunc pubFunc); - }; - - } -} - - -#endif diff --git a/utils/mmsource/core/sourcehook/sourcehook_hookmangen_x86.h b/utils/mmsource/core/sourcehook/sourcehook_hookmangen_x86.h deleted file mode 100644 index 3dd330670..000000000 --- a/utils/mmsource/core/sourcehook/sourcehook_hookmangen_x86.h +++ /dev/null @@ -1,1611 +0,0 @@ -/* ======== SourceHook ======== -* vim: set ts=4 : -* Copyright (C) 2004-2010 AlliedModders LLC. All rights reserved. -* No warranties of any kind -* -* License: zlib/libpng -* -* from the SourcePawn JIT SDK -* ============================ -*/ - -#ifndef __SOURCEHOOK_HOOKMANGEN_X86_H__ -#define __SOURCEHOOK_HOOKMANGEN_X86_H__ - -#include - -#undef REG_EAX -#undef REG_ECX -#undef REG_EDX -#undef REG_EBX -#undef REG_ESP -#undef REG_SIB -#undef REG_EBP -#undef REG_ESI -#undef REG_EDI - -//MOD R/M -#define MOD_MEM_REG 0 -#define MOD_DISP8 1 -#define MOD_DISP32 2 -#define MOD_REG 3 - -//SIB -#define NOSCALE 0 -#define SCALE2 1 -#define SCALE4 2 -#define SCALE8 3 - -//Register codes -#define REG_EAX 0 -#define REG_ECX 1 -#define REG_EDX 2 -#define REG_EBX 3 -#define REG_ESP 4 -#define REG_SIB 4 -#define REG_NOIDX 4 -#define REG_IMM_BASE 5 -#define REG_EBP 5 -#define REG_ESI 6 -#define REG_EDI 7 - -#define IA32_16BIT_PREFIX 0x66 - -//condition codes (for example, Jcc opcodes) -#define CC_B 0x2 -#define CC_NAE CC_B -#define CC_NB 0x3 -#define CC_AE CC_NB -#define CC_E 0x4 -#define CC_Z CC_E -#define CC_NE 0x5 -#define CC_NZ CC_NE -#define CC_NA 0x6 -#define CC_BE CC_NA -#define CC_A 0x7 -#define CC_NBE CC_A -#define CC_L 0xC -#define CC_NGE CC_L -#define CC_NL 0xD -#define CC_GE CC_NL -#define CC_NG 0xE -#define CC_LE CC_NG -#define CC_G 0xF -#define CC_NLE CC_G - -//Opcodes with encoding information -#define IA32_XOR_RM_REG 0x31 // encoding is /r -#define IA32_XOR_REG_RM 0x33 // encoding is /r -#define IA32_XOR_EAX_IMM32 0x35 // encoding is /r -#define IA32_XOR_RM_IMM32 0x81 // encoding is /6 -#define IA32_XOR_RM_IMM8 0x83 // encoding is /6 -#define IA32_ADD_RM_REG 0x01 // encoding is /r -#define IA32_ADD_REG_RM 0x03 // encoding is /r -#define IA32_ADD_RM_IMM32 0x81 // encoding is /0 -#define IA32_ADD_RM_IMM8 0x83 // encoding is /0 -#define IA32_ADD_EAX_IMM32 0x05 // no extra encoding -#define IA32_SUB_RM_REG 0x29 // encoding is /r -#define IA32_SUB_REG_RM 0x2B // encoding is /r -#define IA32_SUB_RM_IMM8 0x83 // encoding is /5 -#define IA32_SUB_RM_IMM32 0x81 // encoding is /5 -#define IA32_SBB_REG_RM 0x1B // encoding is /r -#define IA32_SBB_RM_IMM8 0x83 // encoding is -#define IA32_JMP_IMM32 0xE9 // encoding is imm32 -#define IA32_JMP_IMM8 0xEB // encoding is imm8 -#define IA32_JMP_RM 0xFF // encoding is /4 -#define IA32_CALL_IMM32 0xE8 // relative call, -#define IA32_CALL_RM 0xFF // encoding is /2 -#define IA32_MOV_REG_IMM 0xB8 // encoding is +r -#define IA32_MOV_RM8_REG 0x88 // encoding is /r -#define IA32_MOV_RM_REG 0x89 // encoding is /r -#define IA32_MOV_REG_RM 0x8B // encoding is /r -#define IA32_MOV_REG8_RM8 0x8A // encoding is /r -#define IA32_MOV_RM8_REG8 0x88 // encoding is /r -#define IA32_MOV_RM_IMM32 0xC7 // encoding is /0 -#define IA32_CMP_RM_IMM32 0x81 // encoding is /7 -#define IA32_CMP_RM_IMM8 0x83 // encoding is /7 -#define IA32_CMP_AL_IMM32 0x3C // no extra encoding -#define IA32_CMP_EAX_IMM32 0x3D // no extra encoding -#define IA32_CMP_RM_REG 0x39 // encoding is /r -#define IA32_CMP_REG_RM 0x3B // encoding is /r -#define IA32_CMPSB 0xA6 // no extra encoding -#define IA32_TEST_RM_REG8 0x84 // encoding is /r -#define IA32_TEST_RM_REG 0x85 // encoding is /r -#define IA32_TEST_RM_IMM32 0xF7 // encoding is /0 -#define IA32_JCC_IMM 0x70 // encoding is +cc -#define IA32_JCC_IMM32_1 0x0F // opcode part 1 -#define IA32_JCC_IMM32_2 0x80 // encoding is +cc -#define IA32_RET 0xC3 // no extra encoding -#define IA32_RETN 0xC2 // encoding is -#define IA32_NEG_RM 0xF7 // encoding is /3 -#define IA32_INC_REG 0x40 // encoding is +r -#define IA32_INC_RM 0xFF // encoding is /0 -#define IA32_DEC_REG 0x48 // encoding is +r -#define IA32_DEC_RM 0xFF // encoding is /1 -#define IA32_OR_REG_RM 0x0B // encoding is /r -#define IA32_AND_REG_RM 0x23 // encoding is /r -#define IA32_AND_EAX_IMM32 0x25 // encoding is -#define IA32_AND_RM_IMM32 0x81 // encoding is /4 -#define IA32_AND_RM_IMM8 0x83 // encoding is /4 -#define IA32_NOT_RM 0xF7 // encoding is /2 -#define IA32_DIV_RM 0xF7 // encoding is /6 -#define IA32_MUL_RM 0xF7 // encoding is /4 -#define IA32_IDIV_RM 0xF7 // encoding is /7 -#define IA32_IMUL_RM 0xF7 // encoding is /5 -#define IA32_IMUL_REG_IMM32 0x69 // encoding is /r -#define IA32_IMUL_REG_IMM8 0x6B // encoding is /r -#define IA32_IMUL_REG_RM_1 0x0F // encoding is _2 -#define IA32_IMUL_REG_RM_2 0xAF // encoding is /r -#define IA32_SHR_RM_IMM8 0xC1 // encoding is /5 -#define IA32_SHR_RM_1 0xD1 // encoding is /5 -#define IA32_SHL_RM_IMM8 0xC1 // encoding is /4 -#define IA32_SHL_RM_1 0xD1 // encoding is /4 -#define IA32_SAR_RM_CL 0xD3 // encoding is /7 -#define IA32_SAR_RM_1 0xD1 // encoding is /7 -#define IA32_SHR_RM_CL 0xD3 // encoding is /5 -#define IA32_SHL_RM_CL 0xD3 // encoding is /4 -#define IA32_SAR_RM_IMM8 0xC1 // encoding is /7 -#define IA32_SETCC_RM8_1 0x0F // opcode part 1 -#define IA32_SETCC_RM8_2 0x90 // encoding is +cc /0 (8bits) -#define IA32_CMOVCC_RM_1 0x0F // opcode part 1 -#define IA32_CMOVCC_RM_2 0x40 // encoding is +cc /r -#define IA32_XCHG_EAX_REG 0x90 // encoding is +r -#define IA32_LEA_REG_MEM 0x8D // encoding is /r -#define IA32_POP_REG 0x58 // encoding is +r -#define IA32_PUSH_REG 0x50 // encoding is +r -#define IA32_PUSH_RM 0xFF // encoding is /6 -#define IA32_PUSH_IMM32 0x68 // encoding is -#define IA32_PUSH_IMM8 0x6A // encoding is -#define IA32_REP 0xF3 // no extra encoding -#define IA32_MOVSD 0xA5 // no extra encoding -#define IA32_MOVSB 0xA4 // no extra encoding -#define IA32_STOSD 0xAB // no extra encoding -#define IA32_CLD 0xFC // no extra encoding -#define IA32_PUSHAD 0x60 // no extra encoding -#define IA32_POPAD 0x61 // no extra encoding -#define IA32_NOP 0x90 // no extra encoding -#define IA32_INT3 0xCC // no extra encoding -#define IA32_FSTP_MEM32 0xD9 // encoding is /3 -#define IA32_FSTP_MEM64 0xDD // encoding is /3 -#define IA32_FLD_MEM32 0xD9 // encoding is /0 -#define IA32_FLD_MEM64 0xDD // encoding is /0 -#define IA32_FILD_MEM32 0xDB // encoding is /0 -#define IA32_FADD_MEM32 0xD8 // encoding is /0 -#define IA32_FADD_FPREG_ST0_1 0xDC // opcode part 1 -#define IA32_FADD_FPREG_ST0_2 0xC0 // encoding is +r -#define IA32_FSUB_MEM32 0xD8 // encoding is /4 -#define IA32_FMUL_MEM32 0xD8 // encoding is /1 -#define IA32_FDIV_MEM32 0xD8 // encoding is /6 -#define IA32_FSTCW_MEM16_1 0x9B // opcode part 1 -#define IA32_FSTCW_MEM16_2 0xD9 // encoding is /7 -#define IA32_FLDCW_MEM16 0xD9 // encoding is /5 -#define IA32_FISTP_MEM32 0xDB // encoding is /3 -#define IA32_FUCOMIP_1 0xDF // opcode part 1 -#define IA32_FUCOMIP_2 0xE8 // encoding is +r -#define IA32_FSTP_FPREG_1 0xDD // opcode part 1 -#define IA32_FSTP_FPREG_2 0xD8 // encoding is +r -#define IA32_MOVZX_R32_RM8_1 0x0F // opcode part 1 -#define IA32_MOVZX_R32_RM8_2 0xB6 // encoding is /r -#define IA32_MOVZX_R32_RM16_1 0x0F // opcode part 1 -#define IA32_MOVZX_R32_RM16_2 0xB7 // encoding is /r - - -namespace SourceHook -{ - namespace Impl - { - typedef GenBuffer JitWriter; - - inline jit_uint8_t ia32_modrm(jit_uint8_t mode, jit_uint8_t reg, jit_uint8_t rm) - { - jit_uint8_t modrm = (mode << 6); - - modrm |= (reg << 3); - modrm |= (rm); - - return modrm; - } - - //mode is the scaling method - NOSCALE ... SCALE8 - //index is the register that is scaled - //base is the base register - inline jit_uint8_t ia32_sib(jit_uint8_t mode, jit_uint8_t index, jit_uint8_t base) - { - jit_uint8_t sib = (mode << 6); - - sib |= (index << 3); - sib |= (base); - - return sib; - } - - inline void IA32_Int3(JitWriter *jit) - { - jit->write_ubyte(IA32_INT3); - } - - /*********************** - * INCREMENT/DECREMENT * - ***********************/ - - inline void IA32_Inc_Reg(JitWriter *jit, jit_uint8_t reg) - { - jit->write_ubyte(IA32_INC_REG+reg); - } - - inline void IA32_Inc_Rm_Disp8(JitWriter *jit, jit_uint8_t reg, jit_int8_t disp) - { - jit->write_ubyte(IA32_INC_RM); - jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, reg)); - jit->write_byte(disp); - } - - inline void IA32_Inc_Rm_Disp32(JitWriter *jit, jit_uint8_t reg, jit_int32_t disp) - { - jit->write_ubyte(IA32_INC_RM); - jit->write_ubyte(ia32_modrm(MOD_DISP32, 0, reg)); - jit->write_int32(disp); - } - - inline void IA32_Inc_Rm_Disp_Reg(JitWriter *jit, jit_uint8_t base, jit_uint8_t reg, jit_uint8_t scale) - { - jit->write_ubyte(IA32_INC_RM); - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 0, REG_SIB)); - jit->write_ubyte(ia32_sib(scale, reg, base)); - } - - inline void IA32_Dec_Reg(JitWriter *jit, jit_uint8_t reg) - { - jit->write_ubyte(IA32_DEC_REG+reg); - } - - inline void IA32_Dec_Rm_Disp8(JitWriter *jit, jit_uint8_t reg, jit_int8_t disp) - { - jit->write_ubyte(IA32_DEC_RM); - jit->write_ubyte(ia32_modrm(MOD_DISP8, 1, reg)); - jit->write_byte(disp); - } - - inline void IA32_Dec_Rm_Disp32(JitWriter *jit, jit_uint8_t reg, jit_int32_t disp) - { - jit->write_ubyte(IA32_DEC_RM); - jit->write_ubyte(ia32_modrm(MOD_DISP32, 1, reg)); - jit->write_int32(disp); - } - - inline void IA32_Dec_Rm_Disp_Reg(JitWriter *jit, jit_uint8_t base, jit_uint8_t reg, jit_uint8_t scale) - { - jit->write_ubyte(IA32_DEC_RM); - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 1, REG_SIB)); - jit->write_ubyte(ia32_sib(scale, reg, base)); - } - - /**************** - * BINARY LOGIC * - ****************/ - - inline void IA32_Xor_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t dest_mode) - { - jit->write_ubyte(IA32_XOR_RM_REG); - jit->write_ubyte(ia32_modrm(dest_mode, src, dest)); - } - - inline void IA32_Xor_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t dest_mode) - { - jit->write_ubyte(IA32_XOR_REG_RM); - jit->write_ubyte(ia32_modrm(dest_mode, dest, src)); - } - - inline void IA32_Xor_Rm_Imm8(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode, jit_int8_t value) - { - jit->write_ubyte(IA32_XOR_RM_IMM8); - jit->write_ubyte(ia32_modrm(mode, 6, reg)); - jit->write_byte(value); - } - - inline void IA32_Xor_Rm_Imm32(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode, jit_int32_t value) - { - jit->write_ubyte(IA32_XOR_RM_IMM32); - jit->write_ubyte(ia32_modrm(mode, 6, reg)); - jit->write_int32(value); - } - - inline void IA32_Xor_Eax_Imm32(JitWriter *jit, jit_int32_t value) - { - jit->write_ubyte(IA32_XOR_EAX_IMM32); - jit->write_int32(value); - } - - inline void IA32_Neg_Rm(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode) - { - jit->write_ubyte(IA32_NEG_RM); - jit->write_ubyte(ia32_modrm(mode, 3, reg)); - } - - inline void IA32_Or_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode) - { - jit->write_ubyte(IA32_OR_REG_RM); - jit->write_ubyte(ia32_modrm(mode, dest, src)); - } - - inline void IA32_And_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode) - { - jit->write_ubyte(IA32_AND_REG_RM); - jit->write_ubyte(ia32_modrm(mode, dest, src)); - } - - inline void IA32_And_Rm_Imm32(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode, jit_int32_t value) - { - jit->write_ubyte(IA32_AND_RM_IMM32); - jit->write_ubyte(ia32_modrm(mode, 4, reg)); - jit->write_int32(value); - } - - inline void IA32_And_Rm_Imm8(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode, jit_int8_t value) - { - jit->write_ubyte(IA32_AND_RM_IMM8); - jit->write_ubyte(ia32_modrm(mode, 4, reg)); - jit->write_byte(value); - } - - inline void IA32_And_Eax_Imm32(JitWriter *jit, jit_int32_t value) - { - jit->write_ubyte(IA32_AND_EAX_IMM32); - jit->write_int32(value); - } - - inline void IA32_Not_Rm(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode) - { - jit->write_ubyte(IA32_NOT_RM); - jit->write_ubyte(ia32_modrm(mode, 2, reg)); - } - - inline void IA32_Shr_Rm_Imm8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t value, jit_uint8_t mode) - { - jit->write_ubyte(IA32_SHR_RM_IMM8); - jit->write_ubyte(ia32_modrm(mode, 5, dest)); - jit->write_ubyte(value); - } - - inline void IA32_Shr_Rm_1(JitWriter *jit, jit_uint8_t dest, jit_uint8_t mode) - { - jit->write_ubyte(IA32_SHR_RM_1); - jit->write_ubyte(ia32_modrm(mode, 5, dest)); - } - - inline void IA32_Shl_Rm_Imm8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t value, jit_uint8_t mode) - { - jit->write_ubyte(IA32_SHL_RM_IMM8); - jit->write_ubyte(ia32_modrm(mode, 4, dest)); - jit->write_ubyte(value); - } - - inline void IA32_Shl_Rm_1(JitWriter *jit, jit_uint8_t dest, jit_uint8_t mode) - { - jit->write_ubyte(IA32_SHL_RM_1); - jit->write_ubyte(ia32_modrm(mode, 4, dest)); - } - - inline void IA32_Sar_Rm_Imm8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t value, jit_uint8_t mode) - { - jit->write_ubyte(IA32_SAR_RM_IMM8); - jit->write_ubyte(ia32_modrm(mode, 7, dest)); - jit->write_ubyte(value); - } - - inline void IA32_Sar_Rm_CL(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode) - { - jit->write_ubyte(IA32_SAR_RM_CL); - jit->write_ubyte(ia32_modrm(mode, 7, reg)); - } - - inline void IA32_Sar_Rm_1(JitWriter *jit, jit_uint8_t dest, jit_uint8_t mode) - { - jit->write_ubyte(IA32_SAR_RM_1); - jit->write_ubyte(ia32_modrm(mode, 7, dest)); - } - - inline void IA32_Shr_Rm_CL(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode) - { - jit->write_ubyte(IA32_SHR_RM_CL); - jit->write_ubyte(ia32_modrm(mode, 5, reg)); - } - - inline void IA32_Shl_Rm_CL(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode) - { - jit->write_ubyte(IA32_SHL_RM_CL); - jit->write_ubyte(ia32_modrm(mode, 4, reg)); - } - - inline void IA32_Xchg_Eax_Reg(JitWriter *jit, jit_uint8_t reg) - { - jit->write_ubyte(IA32_XCHG_EAX_REG+reg); - } - - /********************** - * ARITHMETIC (BASIC) * - **********************/ - - inline void IA32_Add_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode) - { - jit->write_ubyte(IA32_ADD_RM_REG); - jit->write_ubyte(ia32_modrm(mode, src, dest)); - } - - inline void IA32_Add_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode) - { - jit->write_ubyte(IA32_ADD_REG_RM); - jit->write_ubyte(ia32_modrm(mode, dest, src)); - } - - inline void IA32_Add_Rm_Imm8(JitWriter *jit, jit_uint8_t reg, jit_int8_t value, jit_uint8_t mode) - { - jit->write_ubyte(IA32_ADD_RM_IMM8); - jit->write_ubyte(ia32_modrm(mode, 0, reg)); - jit->write_byte(value); - } - - inline void IA32_Add_Rm_Imm32(JitWriter *jit, jit_uint8_t reg, jit_int32_t value, jit_uint8_t mode) - { - jit->write_ubyte(IA32_ADD_RM_IMM32); - jit->write_ubyte(ia32_modrm(mode, 0, reg)); - jit->write_int32(value); - } - - inline void IA32_Add_Rm_ImmAuto(JitWriter *jit, jit_uint8_t reg, jit_int32_t value, jit_uint8_t mode) - { - if (value >= SCHAR_MIN && value <= SCHAR_MAX) - IA32_Add_Rm_Imm8(jit, reg, static_cast(value), mode); - else - IA32_Add_Rm_Imm32(jit, reg, value, mode); - } - - inline void IA32_Add_Eax_Imm32(JitWriter *jit, jit_int32_t value) - { - jit->write_ubyte(IA32_ADD_EAX_IMM32); - jit->write_int32(value); - } - - inline void IA32_Sub_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode) - { - jit->write_ubyte(IA32_SUB_RM_REG); - jit->write_ubyte(ia32_modrm(mode, src, dest)); - } - - inline void IA32_Sub_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode) - { - jit->write_ubyte(IA32_SUB_REG_RM); - jit->write_ubyte(ia32_modrm(mode, dest, src)); - } - - inline void IA32_Sub_Reg_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp8) - { - jit->write_ubyte(IA32_SUB_REG_RM); - jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, src)); - jit->write_byte(disp8); - } - - inline void IA32_Sub_Rm_Reg_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp8) - { - jit->write_ubyte(IA32_SUB_RM_REG); - jit->write_ubyte(ia32_modrm(MOD_DISP8, src, dest)); - jit->write_byte(disp8); - } - - inline void IA32_Sub_Rm_Imm8(JitWriter *jit, jit_uint8_t reg, jit_int8_t val, jit_uint8_t mode) - { - jit->write_ubyte(IA32_SUB_RM_IMM8); - jit->write_ubyte(ia32_modrm(mode, 5, reg)); - jit->write_byte(val); - } - - inline void IA32_Sub_Rm_Imm32(JitWriter *jit, jit_uint8_t reg, jit_int32_t val, jit_uint8_t mode) - { - jit->write_ubyte(IA32_SUB_RM_IMM32); - jit->write_ubyte(ia32_modrm(mode, 5, reg)); - jit->write_int32(val); - } - - inline void IA32_Sub_Rm_ImmAuto(JitWriter *jit, jit_uint8_t reg, jit_int32_t val, jit_uint8_t mode) - { - if (val >= SCHAR_MIN && val <= SCHAR_MAX) - IA32_Sub_Rm_Imm8(jit, reg, static_cast(val), mode); - else - IA32_Sub_Rm_Imm32(jit, reg, val, mode); - } - - inline void IA32_Sbb_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode) - { - jit->write_ubyte(IA32_SBB_REG_RM); - jit->write_ubyte(ia32_modrm(mode, dest, src)); - } - - inline void IA32_Sbb_Rm_Imm8(JitWriter *jit, jit_uint8_t dest, jit_int8_t value, jit_uint8_t mode) - { - jit->write_ubyte(IA32_SBB_RM_IMM8); - jit->write_ubyte(ia32_modrm(mode, 3, dest)); - jit->write_byte(value); - } - - inline void IA32_Div_Rm(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode) - { - jit->write_ubyte(IA32_DIV_RM); - jit->write_ubyte(ia32_modrm(mode, 6, reg)); - } - - inline void IA32_IDiv_Rm(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode) - { - jit->write_ubyte(IA32_IDIV_RM); - jit->write_ubyte(ia32_modrm(mode, 7, reg)); - } - - inline void IA32_Mul_Rm(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode) - { - jit->write_ubyte(IA32_MUL_RM); - jit->write_ubyte(ia32_modrm(mode, 4, reg)); - } - - inline void IA32_IMul_Rm(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode) - { - jit->write_ubyte(IA32_IMUL_RM); - jit->write_ubyte(ia32_modrm(mode, 5, reg)); - } - - inline void IA32_IMul_Reg_Imm8(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode, jit_int8_t value) - { - jit->write_ubyte(IA32_IMUL_REG_IMM8); - jit->write_ubyte(ia32_modrm(mode, 0, reg)); - jit->write_byte(value); - } - - inline void IA32_IMul_Reg_Imm32(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode, jit_int32_t value) - { - jit->write_ubyte(IA32_IMUL_REG_IMM32); - jit->write_ubyte(ia32_modrm(mode, 0, reg)); - jit->write_int32(value); - } - - inline void IA32_IMul_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode) - { - jit->write_ubyte(IA32_IMUL_REG_RM_1); - jit->write_ubyte(IA32_IMUL_REG_RM_2); - jit->write_ubyte(ia32_modrm(mode, dest, src)); - } - - inline void IA32_Add_Rm_Reg_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp) - { - jit->write_ubyte(IA32_ADD_RM_REG); - jit->write_ubyte(ia32_modrm(MOD_DISP8, src, dest)); - jit->write_byte(disp); - } - - inline void IA32_Add_Reg_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp) - { - jit->write_ubyte(IA32_ADD_REG_RM); - jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, src)); - jit->write_byte(disp); - } - - inline void IA32_Add_Rm_Imm8_Disp8(JitWriter *jit, - jit_uint8_t dest, - jit_int8_t val, - jit_int8_t disp8) - { - jit->write_ubyte(IA32_ADD_RM_IMM8); - jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, dest)); - jit->write_byte(disp8); - jit->write_byte(val); - } - - inline void IA32_Add_Rm_Imm32_Disp8(JitWriter *jit, - jit_uint8_t dest, - jit_int32_t val, - jit_int8_t disp8) - { - jit->write_ubyte(IA32_ADD_RM_IMM32); - jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, dest)); - jit->write_byte(disp8); - jit->write_int32(val); - } - - inline jitoffs_t IA32_Add_Rm_Imm32_Later(JitWriter *jit, - jit_uint8_t dest, - jit_uint8_t mode) - { - jit->write_ubyte(IA32_ADD_RM_IMM32); - jit->write_ubyte(ia32_modrm(mode, 0, dest)); - jitoffs_t ptr = jit->get_outputpos(); - jit->write_int32(0); - return ptr; - } - - inline void IA32_Add_Rm_Imm8_Disp32(JitWriter *jit, - jit_uint8_t dest, - jit_int8_t val, - jit_int32_t disp32) - { - jit->write_ubyte(IA32_ADD_RM_IMM8); - jit->write_ubyte(ia32_modrm(MOD_DISP32, 0, dest)); - jit->write_int32(disp32); - jit->write_byte(val); - } - - inline void IA32_Add_RmEBP_Imm8_Disp_Reg(JitWriter *jit, - jit_uint8_t dest_base, - jit_uint8_t dest_index, - jit_uint8_t dest_scale, - jit_int8_t val) - { - jit->write_ubyte(IA32_ADD_RM_IMM8); - jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, REG_SIB)); - jit->write_ubyte(ia32_sib(dest_scale, dest_index, dest_base)); - jit->write_byte(0); - jit->write_byte(val); - } - - inline void IA32_Sub_Rm_Imm8_Disp8(JitWriter *jit, - jit_uint8_t dest, - jit_int8_t val, - jit_int8_t disp8) - { - jit->write_ubyte(IA32_SUB_RM_IMM8); - jit->write_ubyte(ia32_modrm(MOD_DISP8, 5, dest)); - jit->write_byte(disp8); - jit->write_byte(val); - } - - inline void IA32_Sub_Rm_Imm8_Disp32(JitWriter *jit, - jit_uint8_t dest, - jit_int8_t val, - jit_int32_t disp32) - { - jit->write_ubyte(IA32_SUB_RM_IMM8); - jit->write_ubyte(ia32_modrm(MOD_DISP32, 5, dest)); - jit->write_int32(disp32); - jit->write_byte(val); - } - - inline void IA32_Sub_RmEBP_Imm8_Disp_Reg(JitWriter *jit, - jit_uint8_t dest_base, - jit_uint8_t dest_index, - jit_uint8_t dest_scale, - jit_int8_t val) - { - jit->write_ubyte(IA32_SUB_RM_IMM8); - jit->write_ubyte(ia32_modrm(MOD_DISP8, 5, REG_SIB)); - jit->write_ubyte(ia32_sib(dest_scale, dest_index, dest_base)); - jit->write_byte(0); - jit->write_byte(val); - } - - /** - * Memory Instructions - */ - - inline void IA32_Lea_Reg_DispRegMult(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src_base, jit_uint8_t src_index, jit_uint8_t scale) - { - jit->write_ubyte(IA32_LEA_REG_MEM); - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, dest, REG_SIB)); - jit->write_ubyte(ia32_sib(scale, src_index, src_base)); - } - - inline void IA32_Lea_Reg_DispEBPRegMult(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src_base, jit_uint8_t src_index, jit_uint8_t scale) - { - jit->write_ubyte(IA32_LEA_REG_MEM); - jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, REG_SIB)); - jit->write_ubyte(ia32_sib(scale, src_index, src_base)); - jit->write_byte(0); - } - - inline void IA32_Lea_Reg_DispRegMultImm8(JitWriter *jit, - jit_uint8_t dest, - jit_uint8_t src_base, - jit_uint8_t src_index, - jit_uint8_t scale, - jit_int8_t val) - { - jit->write_ubyte(IA32_LEA_REG_MEM); - jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, REG_SIB)); - jit->write_ubyte(ia32_sib(scale, src_index, src_base)); - jit->write_byte(val); - } - - inline void IA32_Lea_Reg_DispRegMultImm32(JitWriter *jit, - jit_uint8_t dest, - jit_uint8_t src_base, - jit_uint8_t src_index, - jit_uint8_t scale, - jit_int32_t val) - { - jit->write_ubyte(IA32_LEA_REG_MEM); - jit->write_ubyte(ia32_modrm(MOD_DISP32, dest, REG_SIB)); - jit->write_ubyte(ia32_sib(scale, src_index, src_base)); - jit->write_int32(val); - } - - inline void IA32_Lea_Reg_RegMultImm32(JitWriter *jit, - jit_uint8_t dest, - jit_uint8_t src_index, - jit_uint8_t scale, - jit_int32_t val) - { - jit->write_ubyte(IA32_LEA_REG_MEM); - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, dest, REG_SIB)); - jit->write_ubyte(ia32_sib(scale, src_index, REG_IMM_BASE)); - jit->write_int32(val); - } - - inline void IA32_Lea_DispRegImm8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src_base, jit_int8_t val) - { - jit->write_ubyte(IA32_LEA_REG_MEM); - jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, src_base)); - jit->write_byte(val); - } - - inline void IA32_Lea_DispRegImm32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src_base, jit_int32_t val) - { - jit->write_ubyte(IA32_LEA_REG_MEM); - jit->write_ubyte(ia32_modrm(MOD_DISP32, dest, src_base)); - jit->write_int32(val); - } - - inline void IA32_Lea_DispRegImmAuto(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src_base, jit_int32_t val) - { - if (val >= SCHAR_MIN && val <= SCHAR_MAX) - IA32_Lea_DispRegImm8(jit, dest, src_base, static_cast(val)); - else - IA32_Lea_DispRegImm32(jit, dest, src_base, val); - } - - /** - * Stack Instructions - */ - - inline void IA32_Pop_Reg(JitWriter *jit, jit_uint8_t reg) - { - jit->write_ubyte(IA32_POP_REG+reg); - } - - inline void IA32_Push_Reg(JitWriter *jit, jit_uint8_t reg) - { - jit->write_ubyte(IA32_PUSH_REG+reg); - } - - inline void IA32_Push_Imm8(JitWriter *jit, jit_int8_t val) - { - jit->write_ubyte(IA32_PUSH_IMM8); - jit->write_byte(val); - } - - inline void IA32_Push_Imm32(JitWriter *jit, jit_int32_t val) - { - jit->write_ubyte(IA32_PUSH_IMM32); - jit->write_int32(val); - } - - inline void IA32_Pushad(JitWriter *jit) - { - jit->write_ubyte(IA32_PUSHAD); - } - - inline void IA32_Popad(JitWriter *jit) - { - jit->write_ubyte(IA32_POPAD); - } - - inline void IA32_Push_Rm_Disp8(JitWriter *jit, jit_uint8_t reg, jit_int8_t disp8) - { - jit->write_ubyte(IA32_PUSH_RM); - jit->write_ubyte(ia32_modrm(MOD_DISP8, 6, reg)); - jit->write_byte(disp8); - } - - inline void IA32_Push_Rm_Disp32(JitWriter *jit, jit_uint8_t reg, jit_int32_t disp32) - { - jit->write_ubyte(IA32_PUSH_RM); - jit->write_ubyte(ia32_modrm(MOD_DISP32, 6, reg)); - jit->write_int32(disp32); - } - - inline void IA32_Push_Rm_DispAuto(JitWriter *jit, jit_uint8_t reg, jit_int32_t disp) - { - if (disp >= SCHAR_MIN && disp <= SCHAR_MAX) - IA32_Push_Rm_Disp8(jit, reg, static_cast(disp)); - else - IA32_Push_Rm_Disp32(jit, reg, disp); - } - - inline void IA32_Push_Rm_Disp8_ESP(JitWriter *jit, jit_int8_t disp8) - { - jit->write_ubyte(IA32_PUSH_RM); - jit->write_ubyte(ia32_modrm(MOD_DISP8, 6, REG_SIB)); - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP)); - jit->write_byte(disp8); - } - - /** - * Moving from REGISTER/MEMORY to REGISTER - */ - - inline void IA32_Mov_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode) - { - jit->write_ubyte(IA32_MOV_REG_RM); - jit->write_ubyte(ia32_modrm(mode, dest, src)); - } - - inline void IA32_Mov_Reg8_Rm8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode) - { - jit->write_ubyte(IA32_MOV_REG8_RM8); - jit->write_ubyte(ia32_modrm(mode, dest, src)); - } - - inline void IA32_Mov_Reg_RmESP(JitWriter *jit, jit_uint8_t dest) - { - jit->write_ubyte(IA32_MOV_REG_RM); - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, dest, REG_ESP)); - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP)); - } - - inline void IA32_Mov_Reg_Rm_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp) - { - jit->write_ubyte(IA32_MOV_REG_RM); - jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, src)); - jit->write_byte(disp); - } - - inline void IA32_Mov_Reg8_Rm8_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp) - { - jit->write_ubyte(IA32_MOV_REG8_RM8); - jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, src)); - jit->write_byte(disp); - } - - inline void IA32_Mov_Reg_Esp_Disp8(JitWriter *jit, jit_uint8_t dest, jit_int8_t disp) - { - jit->write_ubyte(IA32_MOV_REG_RM); - jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, REG_SIB)); - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP)); - jit->write_byte(disp); - } - - inline void IA32_Mov_Reg_Rm_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp) - { - jit->write_ubyte(IA32_MOV_REG_RM); - jit->write_ubyte(ia32_modrm(MOD_DISP32, dest, src)); - jit->write_int32(disp); - } - - inline void IA32_Mov_Reg8_Rm8_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp) - { - jit->write_ubyte(IA32_MOV_REG8_RM8); - jit->write_ubyte(ia32_modrm(MOD_DISP32, dest, src)); - jit->write_int32(disp); - } - - inline void IA32_Mov_Reg_Rm_Disp_Reg(JitWriter *jit, - jit_uint8_t dest, - jit_uint8_t src_base, - jit_uint8_t src_index, - jit_uint8_t src_scale) - { - jit->write_ubyte(IA32_MOV_REG_RM); - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, dest, REG_SIB)); - jit->write_ubyte(ia32_sib(src_scale, src_index, src_base)); - } - - inline void IA32_Mov_Reg_Rm_Disp_Reg_Disp8(JitWriter *jit, - jit_uint8_t dest, - jit_uint8_t src_base, - jit_uint8_t src_index, - jit_uint8_t src_scale, - jit_int8_t disp8) - { - jit->write_ubyte(IA32_MOV_REG_RM); - jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, REG_SIB)); - jit->write_ubyte(ia32_sib(src_scale, src_index, src_base)); - jit->write_byte(disp8); - } - - inline void IA32_Mov_Reg_RmEBP_Disp_Reg(JitWriter *jit, - jit_uint8_t dest, - jit_uint8_t src_base, - jit_uint8_t src_index, - jit_uint8_t src_scale) - { - jit->write_ubyte(IA32_MOV_REG_RM); - jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, REG_SIB)); - jit->write_ubyte(ia32_sib(src_scale, src_index, src_base)); - jit->write_byte(0); - } - - inline void IA32_Mov_Reg_Rm_DispAuto(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp) - { - if (disp == 0) - IA32_Mov_Reg_Rm(jit, dest, src, MOD_MEM_REG); - else if (disp <= SCHAR_MAX) - IA32_Mov_Reg_Rm_Disp8(jit, dest, src, static_cast(disp)); - else - IA32_Mov_Reg_Rm_Disp32(jit, dest, src, disp); - } - - /** - * Moving from REGISTER to REGISTER/MEMORY - */ - - inline void IA32_Mov_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode) - { - jit->write_ubyte(IA32_MOV_RM_REG); - jit->write_ubyte(ia32_modrm(mode, src, dest)); - } - - inline void IA32_Mov_Rm8_Reg8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode) - { - jit->write_ubyte(IA32_MOV_RM8_REG8); - jit->write_ubyte(ia32_modrm(mode, src, dest)); - } - - inline void IA32_Mov_Rm8_Reg8_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp) - { - jit->write_ubyte(IA32_MOV_RM8_REG8); - jit->write_ubyte(ia32_modrm(MOD_DISP8, src, dest)); - jit->write_byte(disp); - } - - inline void IA32_Mov_Rm8_Reg8_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp) - { - jit->write_ubyte(IA32_MOV_RM8_REG8); - jit->write_ubyte(ia32_modrm(MOD_DISP32, src, dest)); - jit->write_int32(disp); - } - - inline void IA32_Mov_Rm8_Reg8_DispAuto(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp) - { - if (disp >= SCHAR_MIN && disp <= SCHAR_MAX) - IA32_Mov_Rm8_Reg8_Disp8(jit, dest, src, static_cast(disp)); - else - IA32_Mov_Rm8_Reg8_Disp32(jit, dest, src, disp); - } - - inline void IA32_Mov_RmESP_Reg(JitWriter *jit, jit_uint8_t src) - { - jit->write_ubyte(IA32_MOV_RM_REG); - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, src, REG_ESP)); - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP)); - } - - inline void IA32_Mov_Rm_Reg_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp) - { - jit->write_ubyte(IA32_MOV_RM_REG); - jit->write_ubyte(ia32_modrm(MOD_DISP8, src, dest)); - jit->write_byte(disp); - } - - inline void IA32_Mov_Rm_Reg_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp) - { - jit->write_ubyte(IA32_MOV_RM_REG); - jit->write_ubyte(ia32_modrm(MOD_DISP32, src, dest)); - jit->write_int32(disp); - } - - inline void IA32_Mov_Rm_Reg_DispAuto(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp) - { - if (disp >= SCHAR_MIN && disp <= SCHAR_MAX) - IA32_Mov_Rm_Reg_Disp8(jit, dest, src, static_cast(disp)); - else - IA32_Mov_Rm_Reg_Disp32(jit, dest, src, disp); - } - - inline void IA32_Mov_RmEBP_Reg_Disp_Reg(JitWriter *jit, - jit_uint8_t dest_base, - jit_uint8_t dest_index, - jit_uint8_t dest_scale, - jit_uint8_t src) - { - jit->write_ubyte(IA32_MOV_RM_REG); - jit->write_ubyte(ia32_modrm(MOD_DISP8, src, REG_SIB)); - jit->write_ubyte(ia32_sib(dest_scale, dest_index, dest_base)); - jit->write_byte(0); - } - - inline void IA32_Mov_Rm8EBP_Reg_Disp_Reg(JitWriter *jit, - jit_uint8_t dest_base, - jit_uint8_t dest_index, - jit_uint8_t dest_scale, - jit_uint8_t src) - { - jit->write_ubyte(IA32_MOV_RM8_REG); - jit->write_ubyte(ia32_modrm(MOD_DISP8, src, REG_SIB)); - jit->write_ubyte(ia32_sib(dest_scale, dest_index, dest_base)); - jit->write_byte(0); - } - - inline void IA32_Mov_Rm16EBP_Reg_Disp_Reg(JitWriter *jit, - jit_uint8_t dest_base, - jit_uint8_t dest_index, - jit_uint8_t dest_scale, - jit_uint8_t src) - { - jit->write_ubyte(IA32_16BIT_PREFIX); - jit->write_ubyte(IA32_MOV_RM_REG); - jit->write_ubyte(ia32_modrm(MOD_DISP8, src, REG_SIB)); - jit->write_ubyte(ia32_sib(dest_scale, dest_index, dest_base)); - jit->write_byte(0); - } - - /** - * Moving from IMMEDIATE to REGISTER - */ - - inline jitoffs_t IA32_Mov_Reg_Imm32(JitWriter *jit, jit_uint8_t dest, jit_int32_t num) - { - jitoffs_t offs; - jit->write_ubyte(IA32_MOV_REG_IMM+dest); - offs = jit->get_outputpos(); - jit->write_int32(num); - return offs; - } - - inline void IA32_Mov_Rm_Imm32(JitWriter *jit, jit_uint8_t dest, jit_int32_t val, jit_uint8_t mode) - { - jit->write_ubyte(IA32_MOV_RM_IMM32); - jit->write_ubyte(ia32_modrm(mode, 0, dest)); - jit->write_int32(val); - } - - inline void IA32_Mov_Rm_Imm32_Disp8(JitWriter *jit, - jit_uint8_t dest, - jit_int32_t val, - jit_int8_t disp8) - { - jit->write_ubyte(IA32_MOV_RM_IMM32); - jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, dest)); - jit->write_byte(disp8); - jit->write_int32(val); - } - - inline void IA32_Mov_Rm_Imm32_Disp32(JitWriter *jit, - jit_uint8_t dest, - jit_int32_t val, - jit_int32_t disp32) - { - jit->write_ubyte(IA32_MOV_RM_IMM32); - jit->write_ubyte(ia32_modrm(MOD_DISP32, 0, dest)); - jit->write_int32(disp32); - jit->write_int32(val); - } - - inline void IA32_Mov_RmEBP_Imm32_Disp_Reg(JitWriter *jit, - jit_uint8_t dest_base, - jit_uint8_t dest_index, - jit_uint8_t dest_scale, - jit_int32_t val) - { - jit->write_ubyte(IA32_MOV_RM_IMM32); - jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, REG_SIB)); - jit->write_ubyte(ia32_sib(dest_scale, dest_index, dest_base)); - jit->write_byte(0); - jit->write_int32(val); - } - - inline void IA32_Mov_ESP_Disp8_Imm32(JitWriter *jit, jit_int8_t disp8, jit_int32_t val) - { - jit->write_ubyte(IA32_MOV_RM_IMM32); - jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, REG_SIB)); - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP)); - jit->write_byte(disp8); - jit->write_int32(val); - } - - /** - * Floating Point Instructions - */ - - inline void IA32_Fstcw_Mem16_ESP(JitWriter *jit) - { - jit->write_ubyte(IA32_FSTCW_MEM16_1); - jit->write_ubyte(IA32_FSTCW_MEM16_2); - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 7, REG_SIB)); - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP)); - } - - inline void IA32_Fldcw_Mem16_ESP(JitWriter *jit) - { - jit->write_ubyte(IA32_FLDCW_MEM16); - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 5, REG_SIB)); - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP)); - } - - inline void IA32_Fldcw_Mem16_Disp8_ESP(JitWriter *jit, jit_int8_t disp8) - { - jit->write_ubyte(IA32_FLDCW_MEM16); - jit->write_ubyte(ia32_modrm(MOD_DISP8, 5, REG_SIB)); - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP)); - jit->write_byte(disp8); - } - - inline void IA32_Fistp_Mem32_ESP(JitWriter *jit) - { - jit->write_ubyte(IA32_FISTP_MEM32); - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 3, REG_SIB)); - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP)); - } - - inline void IA32_Fistp_Mem32_Disp8_Esp(JitWriter *jit, jit_int8_t disp8) - { - jit->write_ubyte(IA32_FISTP_MEM32); - jit->write_ubyte(ia32_modrm(MOD_DISP8, 3, REG_SIB)); - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP)); - jit->write_byte(disp8); - } - - inline void IA32_Fucomip_ST0_FPUreg(JitWriter *jit, jit_uint8_t reg) - { - jit->write_ubyte(IA32_FUCOMIP_1); - jit->write_ubyte(IA32_FUCOMIP_2+reg); - } - - inline void IA32_Fadd_FPUreg_ST0(JitWriter *jit, jit_uint8_t reg) - { - jit->write_ubyte(IA32_FADD_FPREG_ST0_1); - jit->write_ubyte(IA32_FADD_FPREG_ST0_2+reg); - } - - inline void IA32_Fadd_Mem32_Disp8(JitWriter *jit, jit_uint8_t src, jit_int8_t val) - { - jit->write_ubyte(IA32_FADD_MEM32); - jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, src)); - jit->write_byte(val); - } - - inline void IA32_Fadd_Mem32_ESP(JitWriter *jit) - { - jit->write_ubyte(IA32_FADD_MEM32); - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 0, REG_SIB)); - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP)); - } - - inline void IA32_Fsub_Mem32_Disp8(JitWriter *jit, jit_uint8_t src, jit_int8_t val) - { - jit->write_ubyte(IA32_FSUB_MEM32); - jit->write_ubyte(ia32_modrm(MOD_DISP8, 4, src)); - jit->write_byte(val); - } - - inline void IA32_Fmul_Mem32_Disp8(JitWriter *jit, jit_uint8_t src, jit_int8_t val) - { - jit->write_ubyte(IA32_FMUL_MEM32); - jit->write_ubyte(ia32_modrm(MOD_DISP8, 1, src)); - jit->write_byte(val); - } - - inline void IA32_Fdiv_Mem32_Disp8(JitWriter *jit, jit_uint8_t src, jit_int8_t val) - { - jit->write_ubyte(IA32_FDIV_MEM32); - jit->write_ubyte(ia32_modrm(MOD_DISP8, 6, src)); - jit->write_byte(val); - } - - inline void IA32_Fild_Mem32(JitWriter *jit, jit_uint8_t src) - { - jit->write_ubyte(IA32_FILD_MEM32); - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 0, src)); - } - - inline void IA32_Fstp_Mem32(JitWriter *jit, jit_uint8_t dest) - { - jit->write_ubyte(IA32_FSTP_MEM32); - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 3, dest)); - } - - inline void IA32_Fstp_Mem32_DispAuto(JitWriter *jit, jit_uint8_t dest, jit_int32_t disp) - { - jit->write_ubyte(IA32_FSTP_MEM32); - - if (disp > SCHAR_MIN && disp < SCHAR_MAX) - { - jit->write_ubyte(ia32_modrm(MOD_DISP8, 3, dest)); - jit->write_byte(static_cast(disp)); - } - else - { - jit->write_ubyte(ia32_modrm(MOD_DISP32, 3, dest)); - jit->write_byte(disp); - } - } - - inline void IA32_Fstp_Mem64(JitWriter *jit, jit_uint8_t dest) - { - jit->write_ubyte(IA32_FSTP_MEM64); - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 3, dest)); - } - - inline void IA32_Fstp_Mem64_DispAuto(JitWriter *jit, jit_uint8_t dest, jit_int32_t disp) - { - jit->write_ubyte(IA32_FSTP_MEM64); - - if (disp > SCHAR_MIN && disp < SCHAR_MAX) - { - jit->write_ubyte(ia32_modrm(MOD_DISP8, 3, dest)); - jit->write_byte(static_cast(disp)); - } - else - { - jit->write_ubyte(ia32_modrm(MOD_DISP32, 3, dest)); - jit->write_byte(disp); - } - } - - inline void IA32_Fstp_Mem32_ESP(JitWriter *jit) - { - jit->write_ubyte(IA32_FSTP_MEM32); - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 3, REG_SIB)); - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP)); - } - - inline void IA32_Fstp_Mem64_ESP(JitWriter *jit) - { - jit->write_ubyte(IA32_FSTP_MEM64); - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 3, REG_SIB)); - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP)); - } - - inline void IA32_Fstp_FPUreg(JitWriter *jit, jit_uint8_t reg) - { - jit->write_ubyte(IA32_FSTP_FPREG_1); - jit->write_ubyte(IA32_FSTP_FPREG_2+reg); - } - - inline void IA32_Fld_Mem32(JitWriter *jit, jit_uint8_t src) - { - jit->write_ubyte(IA32_FLD_MEM32); - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 0, src)); - } - - inline void IA32_Fld_Mem64(JitWriter *jit, jit_uint8_t src) - { - jit->write_ubyte(IA32_FLD_MEM64); - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 0, src)); - } - - inline void IA32_Fld_Mem32_Disp8(JitWriter *jit, jit_uint8_t src, jit_int8_t val) - { - jit->write_ubyte(IA32_FLD_MEM32); - jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, src)); - jit->write_byte(val); - } - - inline void IA32_Fld_Mem64_Disp8(JitWriter *jit, jit_uint8_t src, jit_int8_t val) - { - jit->write_ubyte(IA32_FLD_MEM64); - jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, src)); - jit->write_byte(val); - } - - inline void IA32_Fld_Mem32_Disp32(JitWriter *jit, jit_uint8_t src, jit_int32_t val) - { - jit->write_ubyte(IA32_FLD_MEM32); - jit->write_ubyte(ia32_modrm(MOD_DISP32, 0, src)); - jit->write_int32(val); - } - - inline void IA32_Fld_Mem64_Disp32(JitWriter *jit, jit_uint8_t src, jit_int32_t val) - { - jit->write_ubyte(IA32_FLD_MEM64); - jit->write_ubyte(ia32_modrm(MOD_DISP32, 0, src)); - jit->write_int32(val); - } - - inline void IA32_Fld_Mem32_DispAuto(JitWriter *jit, jit_uint8_t src, jit_int32_t disp) - { - if (disp == 0) - IA32_Fld_Mem32(jit, src); - else if (disp <= SCHAR_MAX) - IA32_Fld_Mem32_Disp8(jit, src, static_cast(disp)); - else - IA32_Fld_Mem32_Disp32(jit, src, disp); - } - - inline void IA32_Fld_Mem64_DispAuto(JitWriter *jit, jit_uint8_t src, jit_int32_t disp) - { - if (disp == 0) - IA32_Fld_Mem64(jit, src); - else if (disp <= SCHAR_MAX) - IA32_Fld_Mem64_Disp8(jit, src, static_cast(disp)); - else - IA32_Fld_Mem64_Disp32(jit, src, disp); - } - - /** - * Move data with zero extend - */ - - inline void IA32_Movzx_Reg32_Rm8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode) - { - jit->write_ubyte(IA32_MOVZX_R32_RM8_1); - jit->write_ubyte(IA32_MOVZX_R32_RM8_2); - jit->write_ubyte(ia32_modrm(mode, dest, src)); - } - - inline void IA32_Movzx_Reg32_Rm8_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp) - { - jit->write_ubyte(IA32_MOVZX_R32_RM8_1); - jit->write_ubyte(IA32_MOVZX_R32_RM8_2); - jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, src)); - jit->write_byte(disp); - } - - inline void IA32_Movzx_Reg32_Rm8_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp) - { - jit->write_ubyte(IA32_MOVZX_R32_RM8_1); - jit->write_ubyte(IA32_MOVZX_R32_RM8_2); - jit->write_ubyte(ia32_modrm(MOD_DISP32, dest, src)); - jit->write_int32(disp); - } - - inline void IA32_Movzx_Reg32_Rm8_DispAuto(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp) - { - if (disp >= SCHAR_MIN && disp <= SCHAR_MAX) - IA32_Movzx_Reg32_Rm8_Disp8(jit, dest, src, static_cast(disp)); - else - IA32_Movzx_Reg32_Rm8_Disp32(jit, dest, src, disp); - } - - inline void IA32_Movzx_Reg32_Rm16(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode) - { - jit->write_ubyte(IA32_MOVZX_R32_RM16_1); - jit->write_ubyte(IA32_MOVZX_R32_RM16_2); - jit->write_ubyte(ia32_modrm(mode, dest, src)); - } - - inline void IA32_Movzx_Reg32_Rm16_Disp8(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int8_t disp) - { - jit->write_ubyte(IA32_MOVZX_R32_RM16_1); - jit->write_ubyte(IA32_MOVZX_R32_RM16_2); - jit->write_ubyte(ia32_modrm(MOD_DISP8, dest, src)); - jit->write_byte(disp); - } - - inline void IA32_Movzx_Reg32_Rm16_Disp32(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp) - { - jit->write_ubyte(IA32_MOVZX_R32_RM16_1); - jit->write_ubyte(IA32_MOVZX_R32_RM16_2); - jit->write_ubyte(ia32_modrm(MOD_DISP32, dest, src)); - jit->write_int32(disp); - } - - inline void IA32_Movzx_Reg32_Rm16_DispAuto(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_int32_t disp) - { - if (disp >= SCHAR_MIN && disp <= SCHAR_MAX) - IA32_Movzx_Reg32_Rm16_Disp8(jit, dest, src, static_cast(disp)); - else - IA32_Movzx_Reg32_Rm16_Disp32(jit, dest, src, disp); - } - - /** - * Branching/Jumping - */ - - inline jitoffs_t IA32_Jump_Cond_Imm8(JitWriter *jit, jit_uint8_t cond, jit_int8_t disp) - { - jitoffs_t ptr; - jit->write_ubyte(IA32_JCC_IMM+cond); - ptr = jit->get_outputpos(); - jit->write_byte(disp); - return ptr; - } - - inline jitoffs_t IA32_Jump_Imm32(JitWriter *jit, jit_int32_t disp) - { - jitoffs_t ptr; - jit->write_ubyte(IA32_JMP_IMM32); - ptr = jit->get_outputpos(); - jit->write_int32(disp); - return ptr; - } - - inline jitoffs_t IA32_Jump_Imm8(JitWriter *jit, jit_int8_t disp) - { - jitoffs_t ptr; - jit->write_ubyte(IA32_JMP_IMM8); - ptr = jit->get_outputpos(); - jit->write_byte(disp); - return ptr; - } - - inline jitoffs_t IA32_Jump_Cond_Imm32(JitWriter *jit, jit_uint8_t cond, jit_int32_t disp) - { - jitoffs_t ptr; - jit->write_ubyte(IA32_JCC_IMM32_1); - jit->write_ubyte(IA32_JCC_IMM32_2+cond); - ptr = jit->get_outputpos(); - jit->write_int32(disp); - return ptr; - } - - inline void IA32_Jump_Reg(JitWriter *jit, jit_uint8_t reg) - { - jit->write_ubyte(IA32_JMP_RM); - jit->write_ubyte(ia32_modrm(MOD_REG, 4, reg)); - } - - inline void IA32_Jump_Rm(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode) - { - jit->write_ubyte(IA32_JMP_RM); - jit->write_ubyte(ia32_modrm(mode, 4, reg)); - } - - inline jitoffs_t IA32_Call_Imm32(JitWriter *jit, jit_int32_t disp) - { - jitoffs_t ptr; - jit->write_ubyte(IA32_CALL_IMM32); - ptr = jit->get_outputpos(); - jit->write_int32(disp); - return ptr; - } - - inline void IA32_Call_Reg(JitWriter *jit, jit_uint8_t reg) - { - jit->write_ubyte(IA32_CALL_RM); - jit->write_ubyte(ia32_modrm(MOD_REG, 2, reg)); - } - - inline void IA32_Call_Rm(JitWriter *jit, jit_uint8_t reg, jit_uint8_t mode) - { - jit->write_ubyte(IA32_CALL_RM); - jit->write_ubyte(ia32_modrm(mode, 4, reg)); - } - - inline void IA32_Return(JitWriter *jit) - { - jit->write_ubyte(IA32_RET); - } - - inline void IA32_Return_Popstack(JitWriter *jit, unsigned short bytes) - { - jit->write_ubyte(IA32_RETN); - jit->write_ushort(bytes); - } - - inline void IA32_Test_Rm_Reg(JitWriter *jit, jit_uint8_t reg1, jit_uint8_t reg2, jit_uint8_t mode) - { - jit->write_ubyte(IA32_TEST_RM_REG); - jit->write_ubyte(ia32_modrm(mode, reg2, reg1)); - } - - inline void IA32_Test_Rm_Reg8(JitWriter *jit, jit_uint8_t reg1, jit_uint8_t reg2, jit_uint8_t mode) - { - jit->write_ubyte(IA32_TEST_RM_REG8); - jit->write_ubyte(ia32_modrm(mode, reg2, reg1)); - } - - inline void IA32_Test_Rm_Imm32(JitWriter *jit, jit_uint8_t operand1, jit_int32_t imm_operand, jit_uint8_t mode) - { - jit->write_ubyte(IA32_TEST_RM_IMM32); - jit->write_ubyte(ia32_modrm(mode, 0, operand1)); - jit->write_int32(imm_operand); - } - - inline void IA32_Cmp_Rm_Reg(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode) - { - jit->write_ubyte(IA32_CMP_RM_REG); - jit->write_ubyte(ia32_modrm(mode, src, dest)); - } - - inline void IA32_Cmp_Reg_Rm(JitWriter *jit, jit_uint8_t dest, jit_uint8_t src, jit_uint8_t mode) - { - jit->write_ubyte(IA32_CMP_REG_RM); - jit->write_ubyte(ia32_modrm(mode, dest, src)); - } - - inline void IA32_Cmp_Reg_Rm_ESP(JitWriter *jit, jit_uint8_t cmpreg) - { - jit->write_ubyte(IA32_CMP_REG_RM); - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, cmpreg, REG_SIB)); - jit->write_ubyte(ia32_sib(NOSCALE, REG_NOIDX, REG_ESP)); - } - - inline void IA32_Cmp_Reg_Rm_Disp8(JitWriter *jit, jit_uint8_t reg1, jit_uint8_t reg2, jit_int8_t disp8) - { - jit->write_ubyte(IA32_CMP_REG_RM); - jit->write_ubyte(ia32_modrm(MOD_DISP8, reg1, reg2)); - jit->write_byte(disp8); - } - - inline void IA32_Cmp_Rm_Imm8(JitWriter *jit, jit_uint8_t mode, jit_uint8_t rm, jit_int8_t imm8) - { - jit->write_ubyte(IA32_CMP_RM_IMM8); - jit->write_ubyte(ia32_modrm(mode, 7, rm)); - jit->write_byte(imm8); - } - - inline void IA32_Cmp_Rm_Imm32(JitWriter *jit, jit_uint8_t mode, jit_uint8_t rm, jit_int32_t imm32) - { - jit->write_ubyte(IA32_CMP_RM_IMM32); - jit->write_ubyte(ia32_modrm(mode, 7, rm)); - jit->write_int32(imm32); - } - - inline void IA32_Cmp_Rm_Imm32_Disp8(JitWriter *jit, jit_uint8_t reg, jit_int8_t disp8, jit_int32_t imm32) - { - jit->write_ubyte(IA32_CMP_RM_IMM32); - jit->write_ubyte(ia32_modrm(MOD_DISP8, 7, reg)); - jit->write_byte(disp8); - jit->write_int32(imm32); - } - - inline void IA32_Cmp_Rm_Disp8_Imm8(JitWriter *jit, jit_uint8_t reg, jit_int8_t disp, jit_int8_t imm8) - { - jit->write_ubyte(IA32_CMP_RM_IMM8); - jit->write_ubyte(ia32_modrm(MOD_DISP8, 7, reg)); - jit->write_byte(disp); - jit->write_byte(imm8); - } - - inline void IA32_Cmp_Al_Imm8(JitWriter *jit, jit_int8_t value) - { - jit->write_ubyte(IA32_CMP_AL_IMM32); - jit->write_byte(value); - } - - inline void IA32_Cmp_Eax_Imm32(JitWriter *jit, jit_int32_t value) - { - jit->write_ubyte(IA32_CMP_EAX_IMM32); - jit->write_int32(value); - } - - inline void IA32_SetCC_Rm8(JitWriter *jit, jit_uint8_t reg, jit_uint8_t cond) - { - jit->write_ubyte(IA32_SETCC_RM8_1); - jit->write_ubyte(IA32_SETCC_RM8_2+cond); - jit->write_ubyte(ia32_modrm(MOD_REG, 0, reg)); - } - - inline void IA32_CmovCC_Rm(JitWriter *jit, jit_uint8_t src, jit_uint8_t cond) - { - jit->write_ubyte(IA32_CMOVCC_RM_1); - jit->write_ubyte(IA32_CMOVCC_RM_2+cond); - jit->write_ubyte(ia32_modrm(MOD_MEM_REG, 0, src)); - } - - inline void IA32_CmovCC_Rm_Disp8(JitWriter *jit, jit_uint8_t src, jit_uint8_t cond, jit_int8_t disp) - { - jit->write_ubyte(IA32_CMOVCC_RM_1); - jit->write_ubyte(IA32_CMOVCC_RM_2+cond); - jit->write_ubyte(ia32_modrm(MOD_DISP8, 0, src)); - jit->write_byte(disp); - } - - inline void IA32_Cmpsb(JitWriter *jit) - { - jit->write_ubyte(IA32_CMPSB); - } - - inline void IA32_Rep(JitWriter *jit) - { - jit->write_ubyte(IA32_REP); - } - - inline void IA32_Movsd(JitWriter *jit) - { - jit->write_ubyte(IA32_MOVSD); - } - - inline void IA32_Movsb(JitWriter *jit) - { - jit->write_ubyte(IA32_MOVSB); - } - - inline void IA32_Stosd(JitWriter *jit) - { - jit->write_ubyte(IA32_STOSD); - } - - inline void IA32_Cld(JitWriter *jit) - { - jit->write_ubyte(IA32_CLD); - } - - } -} - -#endif //_INCLUDE_JIT_X86_MACROS_H diff --git a/utils/mmsource/core/sourcehook/sourcehook_impl.h b/utils/mmsource/core/sourcehook/sourcehook_impl.h deleted file mode 100644 index f9ef068f3..000000000 --- a/utils/mmsource/core/sourcehook/sourcehook_impl.h +++ /dev/null @@ -1,392 +0,0 @@ -/* ======== SourceHook ======== -* vim: set ts=4 sw=4 tw=99 noet: -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko -* ============================ -*/ - -#ifndef __SOURCEHOOK_IMPL_H__ -#define __SOURCEHOOK_IMPL_H__ - -#include "sourcehook.h" -#include "sh_memory.h" -#include "sh_list.h" -#include "sh_vector.h" -#include "sh_tinyhash.h" -#include "sh_stack.h" - -/* - -IMPLEMENTATION INFO - ---------------------------------------- - :TODO: update ??? - -Protos ("Prototypes") - The purpose of protos is to provide the amount of type information about a function - which is required to be able to execute a function call without corrupting the stack. - Our protos do not fully do this, but they provide the size of the return value, the number of - parameters, and the size of each parameter, which is enough for most situations. - - There are two version of protos: - OLD: - C-Style strings. - - 0_void: - "attrib" - 1_void: - "attrib|param1_type" - 2_void: - "attrib|param1_type|param2_type - 0: - "attrib|ret_type" - 1: - "attrib|ret_type|param1_type" - 2: - "attrib|ret_type|param2_type" - - Old protos are deprecated. - - NEW: - New protos are in fact pointers to the ProtoInfo structure (see sourcehook.h) - - Old protos begin with a non-zero byte, new protos begin with a zero byte. - - Protos are usually stored in a CProto instance. - ---------------------------------------- -Hook managers and hook manager containers - Each hookman container is tied to _one_ proto/vtable index/vtable offset info. - Hookman containers then contain a list of hook managers provided by plugins, sorted by version. - (higher versions come first) - - Duplicate hook managers are ignored (ie. hook managers where proto, vtable index, vtable offset, - plugin, version are the same as in an already exisiting hook manager) - - A new hook manager is always added to the end of the version group in the corresponding - hook container. - - If the new hook manager was added to the beginning of the container (which only happens if - it is the first one or if it has a higher version than the previously first hook manager), - the now second hook manager is shut down and the new hook manager takes its job. - - A "hook manager container id" (HMCI) consits of three values: proto, vtbl index, vtbl offset. ---------------------------------------- -Hooks - When adding a hook, first the proposed hook manager is added to the corresponding - hook manager container as described above. - - Then the first hook manager in the the manhook container is chosen to handle the function. - - Removing a hook does not neccessarily unreigster the plugin's hook manager. In order to do this, - use RemoveHookManager or UnloadPlugin/ - - Hooks can be paused - they remain in memory but they are not called. In SH, the hook iterator - classes handle pausing transparently. - - The hook loop is supposed to call ShouldContinue before each iteration. This makes hook handlers - able to remove themselves. - ---------------------------------------- -Call classes - - !! deprecated !! - see below (new SH_CALL) - - Call classes are identified by a this pointer and an instance size - - We use the instance size because a derived class instance and a base class instance could - have the same this pointers, and we want to avoid that the derived class - (which could be bigger) gets the same callclass as the base class (mainly if the - base class' callclass was requested first). - - Call classes are reference counted. - - The original function pointers are stored in a vector (in order to allow fast random access). - These vectors are stored as the value type of a hash. The key type is int and represents the - vtable offset. - - If the hash key doesn't exist or the vtblidx is out of range or the corresponding element in the - vector is NULL, there is no hook on that function. - ---------------------------------------- -Recalls - Recalls are used for the META_RETURN_(VALUE_)NEWPARAMS macros, ie. to change the parameters - in the hook loop on the fly. - - First, the macro calls DoRecall(), then it calls the function the hook is attached to -> it - calls the hookfunc. SourceHook makes sure that the newly invoked hook loop starts where the last - one left off and that status variables like status, previous result, override return are kept. - When this recurisvely called hookfunc returns, the macro returns what it returned - (using MRES_SUPERCEDE). CSourceHookImpl returns false from ShouldContinue so the original hook loop - is abandonned. - -Post Recalls - People wanted to be able to use META_RETURN_(VALUE_)NEWPARAMS from post hooks as well. Crazy people! - Anyway, for this, we have to know where a hook handler is. Is it executing pre or post hooks at the moment? - The only way we can know this is watching when it calls CHookList::GetIter(). So CHookList gets a new variable: - m_RequestedFlag. It also gets two new functions: RQFlagReset() and RQFlagGet(). - HookLoopBegin() calls RQFlagReset on both hooklists of the iface; then DoRecall() checks whether the postlist's - RQ flag is set. if yes, the hook loop is in post mode. - - So, what a about a recall in post mode? The first ShouldContinue returns false and sets Status to supercede. - This way the pre hooks and the function call will be skipped. Then, then next ShouldContinue returns true, so we get - into the post hooks. HA! - -Return Values in Post Recalls - The easy case is when we already have an override return value. In this case, the status register gets transferred, - and so does the override return pointer. So, basically, everything is ok. - - However, what happens if we don't? ie. the status register is on MRES_IGNORED? In this case we'd have to transfer the - orig ret value. But we can't: There's no way to tell the hookfunc: "Use this as orig ret pointer". It uses its own. - So, we emulate it. GetOrigRet will return the orig ret pointer from the old hook loop. If still no one overrides it, - we'd have to return it. BUT! HOW TO DO THIS? Check out SH_RETURN(). First calls HookLoopEnd(), then decides whether - to return the override retval or the orig retval. But it doesn't ask for a new override return. So we give the function - the last orig return value as its new override return value; but leave status where it is so everything works, and in - HookLoopEnd we make sure that status is high enough so that the override return will be returned. crazy. - - All this stuff could be much less complicated if I didn't try to preserve binary compatibility :) - -VP Hooks - VP hooks are hooks which are called on a vfnptr, regardless of the this pointer with which it was called. They are - implemented as a special CIface instance with m_Ptr = NULL. All Hook Lists have a new "ListCatIterator" which - virtually concatenates the NULL-interface-hook-list with their normal hook list. - - - I'm afraid that with the addition of Recalls and VP Hooks, SourceHook is now a pretty complex and hacked-together - binary compatible beast which is pretty hard to maintain unless you've written it :) - -New SH_CALL - The addition of VP hooks messed up the Call Classes concept (see above) - call classes are bound to an - instance pointer; they only work on one of the hooked instances. But VP hooks are called on all instances. - - That's why now, SH_CALL takes an instance pointer instead of a callclass pointer. It basically does this: - 1) call SH_GLOB_PTR->SetIgnoreHooks(vfnptr) - 2) call this->*mfp - 3) call SH_GLOB_PTR->ResetIgnoreHooks(vfnptr) - - SourceHook stroes the "ignored vfnptr" and makes CVfnPtr::FindIface return NULL if the CVfnPtr instance - corresponds to the ignored vfnptr. This way the hook manager thinks that the instance isn't hooked, and calls - the original function. Everything works fine. This works even for VP hooks. -*/ - -#include "sourcehook_impl_cproto.h" -#include "sourcehook_impl_chookmaninfo.h" -#include "sourcehook_impl_chook.h" -#include "sourcehook_impl_ciface.h" -#include "sourcehook_impl_cvfnptr.h" -#include "sourcehook_impl_chookidman.h" - -namespace SourceHook -{ - /** - * @brief The SourceHook implementation - */ - - namespace Impl - { - struct CHookContext : IHookContext - { - CHookContext() : m_CleanupTask(NULL) - { - } - - enum State - { - State_Born, - State_Pre, - State_PreVP, - State_Post, - State_PostVP, - State_OrigCall, - State_Dead, - - // Special - State_Ignore, - State_Recall_Pre, - State_Recall_PreVP, - State_Recall_Post, - State_Recall_PostVP - }; - - int m_State; - List::iterator m_Iter; - - CVfnPtr *pVfnPtr; - CIface *pIface; - - META_RES *pStatus; - META_RES *pPrevRes; - META_RES *pCurRes; - - void *pThisPtr; - const void *pOrigRet; - void *pOverrideRet; - void *pIfacePtr; - - bool m_CallOrig; - - ICleanupTask *m_CleanupTask; - - void SkipPaused(List::iterator &iter, List &list) - { - while (iter != list.end() && iter->IsPaused()) - ++iter; - } - public: - void HookRemoved(List::iterator oldhookiter, List::iterator nexthookiter); - void IfaceRemoved(CIface *iface); - void VfnPtrRemoved(CVfnPtr *vfnptr); - - ISHDelegate *GetNext(); - void *GetOverrideRetPtr(); - const void *GetOrigRetPtr(); - bool ShouldCallOrig(); - void DoCleanupTaskAndDeleteIt(); - }; - - class CVfnPtrList : public List - { - public: - CVfnPtr *GetVfnPtr(void *p); - }; - - typedef CStack HookContextStack; - - class UnloadListener - { - public: - virtual void ReadyToUnload(Plugin plug) = 0; - }; - - class PendingUnload - { - UnloadListener *listener_; - Plugin plug_; - bool deactivated_; - - public: - PendingUnload(UnloadListener *listener, Plugin plug) - : listener_(listener), plug_(plug), deactivated_(false) - { } - - Plugin plugin() const - { - return plug_; - } - - UnloadListener *listener() const - { - return listener_; - } - - void deactivate() - { - deactivated_ = true; - } - bool deactivated() const - { - return deactivated_; - } - }; - - class CSourceHookImpl : public ISourceHook - { - private: - CHookManList m_HookManList; - CVfnPtrList m_VfnPtrs; - CHookIDManager m_HookIDMan; - HookContextStack m_ContextStack; - List m_PendingUnloads; - - bool SetHookPaused(int hookid, bool paused); - CHookManList::iterator RemoveHookManager(CHookManList::iterator iter); - List::iterator RevertAndRemoveVfnPtr(List::iterator vfnptr_iter); - public: - CSourceHookImpl(); - virtual ~CSourceHookImpl(); - - /** - * @brief Returns the interface version - */ - int GetIfaceVersion(); - - /** - * @brief Returns the implemnetation version - */ - int GetImplVersion(); - - int AddHook(Plugin plug, AddHookMode mode, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, - ISHDelegate *handler, bool post); - - bool RemoveHook(Plugin plug, void *iface, int thisptr_offs, HookManagerPubFunc myHookMan, - ISHDelegate *handler, bool post); - - bool RemoveHookByID(int hookid); - - bool PauseHookByID(int hookid); - bool UnpauseHookByID(int hookid); - - void SetRes(META_RES res); //!< Sets the meta result - META_RES GetPrevRes(); //!< Gets the meta result of the - //!< previously calledhandler - META_RES GetStatus(); //!< Gets the highest meta result - const void *GetOrigRet(); //!< Gets the original result. - //!< If not in post function, undefined - const void *GetOverrideRet(); //!< Gets the override result. - //!< If none is specified, NULL - void *GetIfacePtr(); //!< Gets the interface pointer - - void *GetOverrideRetPtr(); //!< Used for setting the override return value - - /* - * @brief Make sure that a plugin is not used by any - * other plugins anymore, and unregister all its hook - * managers. If any hooks owned by this plugin are - * still on the callstack, defers notifying the listener - * until the count has dropped to 0. - */ - void UnloadPlugin(Plugin plug, UnloadListener *listener); - - void ResolvePendingUnloads(bool force = false); - - void RemoveHookManager(Plugin plug, HookManagerPubFunc pubFunc); - - void SetIgnoreHooks(void *vfnptr); - void ResetIgnoreHooks(void *vfnptr); - - void DoRecall(); - - IHookContext *SetupHookLoop(IHookManagerInfo *hi, void *vfnptr, void *thisptr, void **origCallAddr, META_RES *statusPtr, - META_RES *prevResPtr, META_RES *curResPtr, const void *origRetPtr, void *overrideRetPtr); - - void EndContext(IHookContext *pCtx); - - void *GetOrigVfnPtrEntry(void *vfnptr); - - /** - * @brief Shut down the whole system, unregister all hook managers - */ - void CompleteShutdown(); - - /** - * @brief Pauses all hooks of a plugin - * - * @param plug The unique identifier of the plugin - */ - void PausePlugin(Plugin plug); - - /** - * @brief Unpauses all hooks of a plugin - * - * @param plug The unique identifier of the plugin - */ - void UnpausePlugin(Plugin plug); - }; - } -} - -#endif diff --git a/utils/mmsource/core/sourcehook/sourcehook_impl_chook.h b/utils/mmsource/core/sourcehook/sourcehook_impl_chook.h deleted file mode 100644 index 86b8cf075..000000000 --- a/utils/mmsource/core/sourcehook/sourcehook_impl_chook.h +++ /dev/null @@ -1,106 +0,0 @@ -/* ======== SourceHook ======== -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko -* ============================ -*/ - -#ifndef __SOURCEHOOK_IMPL_CHOOK_H__ -#define __SOURCEHOOK_IMPL_CHOOK_H__ - -namespace SourceHook -{ - namespace Impl - { - class CHook - { - // *** Data *** - Plugin m_OwnerPlugin; - int m_ThisPointerOffset; - ISHDelegate *m_pHandler; - int m_HookID; - bool m_Paused; - public: - - // *** Descriptor *** - struct Descriptor - { - Plugin m_OwnerPlugin; - int m_ThisPointerOffset; - ISHDelegate *m_pHandler; - - Descriptor(Plugin ownerPlugin, int thisPtrOffset, ISHDelegate *pHandler) - : m_OwnerPlugin(ownerPlugin), m_ThisPointerOffset(thisPtrOffset), - m_pHandler(pHandler) - { - } - }; - - // *** Interface *** - inline CHook(Plugin ownerPlugin, int thisPtrOffset, ISHDelegate *pHandler, int hookid, bool paused=false); - inline bool operator==(const Descriptor &other) const; - inline bool operator==(int hookid) const; - inline Plugin GetOwnerPlugin() const; - inline int GetThisPointerOffset() const; - inline ISHDelegate *GetHandler() const; - inline void SetPaused(bool value); - inline bool IsPaused() const; - inline int GetID() const; - }; - - // *** Implementation *** - inline CHook::CHook(Plugin ownerPlugin, int thisPtrOffset, ISHDelegate *pHandler, int hookid, bool paused) - : m_OwnerPlugin(ownerPlugin), m_ThisPointerOffset(thisPtrOffset), - m_pHandler(pHandler), m_HookID(hookid), m_Paused(paused) - { - } - - inline bool CHook::operator==(const Descriptor &other) const - { - return m_OwnerPlugin == other.m_OwnerPlugin - && m_ThisPointerOffset == other.m_ThisPointerOffset - && m_pHandler == other.m_pHandler; - } - - inline bool CHook::operator==(int hookid) const - { - return m_HookID == hookid; - } - - inline Plugin CHook::GetOwnerPlugin() const - { - return m_OwnerPlugin; - } - - inline int CHook::GetThisPointerOffset() const - { - return m_ThisPointerOffset; - } - - inline ISHDelegate *CHook::GetHandler() const - { - return m_pHandler; - } - - inline void CHook::SetPaused(bool value) - { - m_Paused = value; - } - - inline bool CHook::IsPaused() const - { - return m_Paused; - } - - inline int CHook::GetID() const - { - return m_HookID; - } - } -} - -#endif - diff --git a/utils/mmsource/core/sourcehook/sourcehook_impl_chookidman.cpp b/utils/mmsource/core/sourcehook/sourcehook_impl_chookidman.cpp deleted file mode 100644 index 29a3d09a7..000000000 --- a/utils/mmsource/core/sourcehook/sourcehook_impl_chookidman.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* ======== SourceHook ======== -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko -* Contributors: Scott "Damaged Soul" Ehlert -* ============================ -*/ - -#include "sourcehook_impl.h" - -namespace SourceHook -{ - namespace Impl - { - CHookIDManager::CHookIDManager() - { - } - - int CHookIDManager::New(const CProto &proto, int vtbl_offs, int vtbl_idx, void *vfnptr, - void *adjustediface, Plugin plug, int thisptr_offs, ISHDelegate *handler, bool post) - { - Entry tmp(proto, vtbl_offs, vtbl_idx, vfnptr, adjustediface, plug, thisptr_offs, handler, post); - - size_t cursize = m_Entries.size(); - for (size_t i = 0; i < cursize; ++i) - { - if (m_Entries[i].isfree) - { - m_Entries[i] = tmp; - return static_cast(i) + 1; - } - } - - m_Entries.push_back(tmp); - return static_cast(m_Entries.size()); // return size() because hookid = id+1 anyway - } - - bool CHookIDManager::Remove(int hookid) - { - int realid = hookid - 1; - if (realid < 0 || realid >= static_cast(m_Entries.size()) || m_Entries[realid].isfree) - return false; - - m_Entries[realid].isfree = true; - - // :TODO: remove free ids from back sometimes ?? - - return true; - } - - const CHookIDManager::Entry * CHookIDManager::QueryHook(int hookid) - { - int realid = hookid - 1; - if (realid < 0 || realid >= static_cast(m_Entries.size()) || m_Entries[realid].isfree) - return NULL; - - return &m_Entries[realid]; - } - - void CHookIDManager::FindAllHooks(CVector &output, const CProto &proto, int vtbl_offs, - int vtbl_idx, void *adjustediface, Plugin plug, int thisptr_offs, ISHDelegate *handler, bool post) - { - // oh my god, a lot of parameters... - size_t cursize = m_Entries.size(); - for (size_t i = 0; i < cursize; ++i) - { - if (!m_Entries[i].isfree && m_Entries[i].proto == proto && m_Entries[i].vtbl_offs == vtbl_offs && - m_Entries[i].vtbl_idx == vtbl_idx && m_Entries[i].adjustediface == adjustediface && m_Entries[i].plug == plug && - m_Entries[i].thisptr_offs == thisptr_offs && m_Entries[i].handler->IsEqual(handler) && m_Entries[i].post == post) - { - output.push_back(static_cast(i) + 1); - } - } - } - - void CHookIDManager::FindAllHooks(CVector &output) - { - size_t cursize = m_Entries.size(); - for (size_t i = 0; i < cursize; ++i) - { - if (!m_Entries[i].isfree) - output.push_back(static_cast(i) + 1); - } - } - - void CHookIDManager::FindAllHooks(CVector &output, Plugin plug) - { - size_t cursize = m_Entries.size(); - for (size_t i = 0; i < cursize; ++i) - { - if (!m_Entries[i].isfree && m_Entries[i].plug == plug) - output.push_back(static_cast(i) + 1); - } - } - - - void CHookIDManager::RemoveAll(void *vfnptr) - { - size_t cursize = m_Entries.size(); - for (size_t i = 0; i < cursize; ++i) - { - if (!m_Entries[i].isfree && m_Entries[i].vfnptr == vfnptr) - m_Entries[i].isfree = true; - } - } - - } -} diff --git a/utils/mmsource/core/sourcehook/sourcehook_impl_chookidman.h b/utils/mmsource/core/sourcehook/sourcehook_impl_chookidman.h deleted file mode 100644 index 19f8d08e4..000000000 --- a/utils/mmsource/core/sourcehook/sourcehook_impl_chookidman.h +++ /dev/null @@ -1,81 +0,0 @@ -/* ======== SourceHook ======== -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko -* ============================ -*/ - -#ifndef __SOURCEHOOK_IMPL_CHOOKIDMAN_H__ -#define __SOURCEHOOK_IMPL_CHOOKIDMAN_H__ - -#include "sh_vector.h" - -namespace SourceHook -{ - namespace Impl - { - // Associates hook ids with info about the hooks - // Also used to keep track of used hook ids - class CHookIDManager - { - public: - struct Entry - { - bool isfree; - - // hookman info - CProto proto; - int vtbl_offs; - int vtbl_idx; - - // vfnptr - void *vfnptr; - - // iface - void* adjustediface; - - // hook - Plugin plug; - int thisptr_offs; - ISHDelegate *handler; - bool post; - - Entry(const CProto &pprt, int pvo, int pvi, void *pvp, void *pai, Plugin pplug, int pto, - ISHDelegate *ph, bool ppost) - : isfree(false), proto(pprt), vtbl_offs(pvo), vtbl_idx(pvi), vfnptr(pvp), - adjustediface(pai), plug(pplug), thisptr_offs(pto), handler(ph), post(ppost) - { - } - Entry() - { - } - }; - private: - // Internally, hookid 1 is stored as m_Entries[0] - - CVector m_Entries; - public: - CHookIDManager(); - int New(const CProto &proto, int vtbl_offs, int vtbl_idx, void *vfnptr, void *adjustediface, - Plugin plug, int thisptr_offs, ISHDelegate *handler, bool post); - bool Remove(int hookid); - const Entry * QueryHook(int hookid); - - // Finds all hooks with the given info, and fills the hookids into output. - void FindAllHooks(CVector &output, const CProto &proto, int vtbl_offs, int vtbl_idx, - void *adjustediface, Plugin plug, int thisptr_offs, ISHDelegate *handler, bool post); - - // Removes all hooks with a specified vfnptr - void RemoveAll(void *vfnptr); - - void FindAllHooks(CVector &output); - void FindAllHooks(CVector &output, Plugin plug); - }; - } -} - -#endif - diff --git a/utils/mmsource/core/sourcehook/sourcehook_impl_chookmaninfo.cpp b/utils/mmsource/core/sourcehook/sourcehook_impl_chookmaninfo.cpp deleted file mode 100644 index 639b7a2a9..000000000 --- a/utils/mmsource/core/sourcehook/sourcehook_impl_chookmaninfo.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* ======== SourceHook ======== -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko -* Contributors: Scott "Damaged Soul" Ehlert -* ============================ -*/ - -#include "sourcehook_impl.h" - -namespace SourceHook -{ - namespace Impl - { - CHookManager::CHookManager(Plugin ownerPlugin, HookManagerPubFunc pubFunc) - : m_OwnerPlugin(ownerPlugin), m_PubFunc(pubFunc), m_Version(-1) - { - // Query pubfunc - // -> Should call SetInfo and set all the other variables! - if (m_PubFunc(false, this) != 0) - { - // Error! - m_Version = -1; - } - } - - void CHookManager::SetInfo(int hookman_version, int vtbloffs, int vtblidx, - ProtoInfo *proto, void *hookfunc_vfnptr) - { - m_Version = hookman_version; - m_VtblOffs = vtbloffs; - m_VtblIdx = vtblidx; - m_Proto = proto; - m_HookfuncVfnptr = hookfunc_vfnptr; - } - - void CHookManager::Register() - { - m_PubFunc(true, this); - } - - void CHookManager::Unregister() - { - m_PubFunc(true, NULL); - } - - void CHookManager::IncrRef(CVfnPtr *pVfnPtr) - { - m_VfnPtrs.push_back(pVfnPtr); - if (m_VfnPtrs.size() == 1) - Register(); - } - - void CHookManager::DecrRef(CVfnPtr *pVfnPtr) - { - m_VfnPtrs.remove(pVfnPtr); - if (m_VfnPtrs.empty()) - Unregister(); - } - - CHookManager *CHookManList::GetHookMan(Plugin plug, HookManagerPubFunc pubFunc) - { - CHookManager hm(plug, pubFunc); - return GetHookMan(hm); - } - - CHookManager *CHookManList::GetHookMan(CHookManager &hm) - { - iterator iter = find(hm); - if (iter == end()) - { - push_back(hm); - return &(back()); - } - else - { - return &(*iter); - } - } - } -} diff --git a/utils/mmsource/core/sourcehook/sourcehook_impl_chookmaninfo.h b/utils/mmsource/core/sourcehook/sourcehook_impl_chookmaninfo.h deleted file mode 100644 index 6a805ea9c..000000000 --- a/utils/mmsource/core/sourcehook/sourcehook_impl_chookmaninfo.h +++ /dev/null @@ -1,143 +0,0 @@ -/* ======== SourceHook ======== -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko -* ============================ -*/ - -#ifndef __SOURCEHOOK_IMPL_CHOOKMANINFO_H__ -#define __SOURCEHOOK_IMPL_CHOOKMANINFO_H__ - -#include "sh_list.h" -#include "sourcehook_impl_cproto.h" - -namespace SourceHook -{ - namespace Impl - { - class CVfnPtr; - - class CHookManager : public IHookManagerInfo - { - // *** Data *** - Plugin m_OwnerPlugin; - HookManagerPubFunc m_PubFunc; - int m_VtblOffs; - int m_VtblIdx; - CProto m_Proto; - int m_Version; - - void *m_HookfuncVfnptr; - - List m_VfnPtrs; - public: - // *** Descriptor *** - struct Descriptor - { - Plugin m_OwnerPlugin; - HookManagerPubFunc m_PubFunc; - Descriptor(Plugin ownerPlugin, HookManagerPubFunc pubFunc) - : m_OwnerPlugin(ownerPlugin), m_PubFunc(pubFunc) - { - } - }; - - // *** Interface *** - CHookManager(Plugin ownerPlugin, HookManagerPubFunc pubFunc); - - inline bool operator==(const Descriptor &other) const; - inline bool operator==(const CHookManager &other) const; - - inline operator bool() const; - inline Plugin GetOwnerPlugin() const; - inline int GetVtblOffs() const; - inline int GetVtblIdx() const; - inline const CProto &GetProto() const; - inline int GetVersion() const; - inline void *GetHookFunc() const; - inline HookManagerPubFunc GetPubFunc() const; - - void Register(); - void Unregister(); - - void IncrRef(CVfnPtr *pVfnPtr); - void DecrRef(CVfnPtr *pVfnPtr); - - List &GetVfnPtrList() - { - return m_VfnPtrs; - } - - // *** IHookManagerInfo interface *** - void SetInfo(int hookman_version, int vtbloffs, int vtblidx, - ProtoInfo *proto, void *hookfunc_vfnptr); - }; - - class CHookManList : public List - { - public: - CHookManager *GetHookMan(Plugin plug, HookManagerPubFunc pubFunc); - CHookManager *GetHookMan(CHookManager &hm); - }; - - // *** Implementation **/ - - inline CHookManager::operator bool() const - { - return m_Version != -1; - } - - inline bool CHookManager::operator==(const Descriptor &other) const - { - return m_OwnerPlugin == other.m_OwnerPlugin - && m_PubFunc == other.m_PubFunc; - } - - inline bool CHookManager::operator==(const CHookManager &other) const - { - return m_OwnerPlugin == other.m_OwnerPlugin - && m_PubFunc == other.m_PubFunc; - } - - inline Plugin CHookManager::GetOwnerPlugin() const - { - return m_OwnerPlugin; - } - - inline int CHookManager::GetVtblOffs() const - { - return m_VtblOffs; - } - - inline int CHookManager::GetVtblIdx() const - { - return m_VtblIdx; - } - - inline const CProto &CHookManager::GetProto() const - { - return m_Proto; - } - - inline int CHookManager::GetVersion() const - { - return m_Version; - } - - inline void *CHookManager::GetHookFunc() const - { - return *reinterpret_cast(m_HookfuncVfnptr); - } - - inline HookManagerPubFunc CHookManager::GetPubFunc() const - { - return m_PubFunc; - } - } -} - -#endif - diff --git a/utils/mmsource/core/sourcehook/sourcehook_impl_ciface.h b/utils/mmsource/core/sourcehook/sourcehook_impl_ciface.h deleted file mode 100644 index 690a4fca7..000000000 --- a/utils/mmsource/core/sourcehook/sourcehook_impl_ciface.h +++ /dev/null @@ -1,96 +0,0 @@ -/* ======== SourceHook ======== -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko -* ============================ -*/ - -#ifndef __SOURCEHOOK_IMPL_CIFACE_H__ -#define __SOURCEHOOK_IMPL_CIFACE_H__ - -#include "sh_list.h" - -namespace SourceHook -{ - namespace Impl - { - class CIface - { - // *** Data *** - void *m_Ptr; - - List m_PreHooks; - List m_PostHooks; - public: - - // *** Descriptor *** - typedef void* Descriptor; - - // *** Interface *** - inline CIface(void *ptr); - inline ~CIface(); - inline bool operator==(const Descriptor &other); - inline void *GetPtr() const; - inline List &GetPreHookList(); - inline List &GetPostHookList(); - inline const List &GetPreHookList() const; - inline const List &GetPostHookList() const; - }; - - // *** Implementation *** - inline CIface::CIface(void *ptr) - : m_Ptr(ptr) - { - } - - inline CIface::~CIface() - { - // Before getting deleted, delete all remaining hook handlers - for (List::iterator iter = m_PreHooks.begin(); iter != m_PreHooks.end(); ++iter) - { - iter->GetHandler()->DeleteThis(); - } - - for (List::iterator iter = m_PostHooks.begin(); iter != m_PostHooks.end(); ++iter) - { - iter->GetHandler()->DeleteThis(); - } - } - - inline bool CIface::operator==(const Descriptor &other) - { - return m_Ptr == other; - } - - inline void *CIface::GetPtr() const - { - return m_Ptr; - } - - inline List &CIface::GetPreHookList() - { - return m_PreHooks; - } - - inline List &CIface::GetPostHookList() - { - return m_PostHooks; - } - - inline const List &CIface::GetPreHookList() const - { - return m_PreHooks; - } - - inline const List &CIface::GetPostHookList() const - { - return m_PostHooks; - } - } -} - -#endif - diff --git a/utils/mmsource/core/sourcehook/sourcehook_impl_cleanuptask.h b/utils/mmsource/core/sourcehook/sourcehook_impl_cleanuptask.h deleted file mode 100644 index e8aa725a1..000000000 --- a/utils/mmsource/core/sourcehook/sourcehook_impl_cleanuptask.h +++ /dev/null @@ -1,29 +0,0 @@ -/* ======== SourceHook ======== -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko -* ============================ -*/ - -#ifndef __SOURCEHOOK_IMPL_CLEANUPTASK_H__ -#define __SOURCEHOOK_IMPL_CLEANUPTASK_H__ - - -namespace SourceHook -{ - namespace Impl - { - class ICleanupTask - { - public: - virtual void CleanupAndDeleteThis() = 0; - }; - } -} - -// __SOURCEHOOK_IMPL_CLEANUPTASK_H__ -#endif - diff --git a/utils/mmsource/core/sourcehook/sourcehook_impl_cproto.cpp b/utils/mmsource/core/sourcehook/sourcehook_impl_cproto.cpp deleted file mode 100644 index ff8af2886..000000000 --- a/utils/mmsource/core/sourcehook/sourcehook_impl_cproto.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* ======== SourceHook ======== -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko -* ============================ -*/ - -#include "sourcehook_impl.h" - -namespace SourceHook -{ - namespace Impl - { - void CProto::Fill(const ProtoInfo *pProto) - { - if (pProto == NULL) - m_Version = -1; - - m_ParamsPassInfo.clear(); - - if (pProto->paramsPassInfo[0].size == 0) - { - // Version 1 - m_Version = 0; - m_Convention = pProto->convention; - m_NumOfParams = pProto->numOfParams; - - m_RetPassInfo.size = pProto->retPassInfo.size; - m_RetPassInfo.type = pProto->retPassInfo.type; - m_RetPassInfo.flags = GetRealFlags(pProto->retPassInfo); - - m_RetPassInfo.pNormalCtor = NULL; - m_RetPassInfo.pCopyCtor = NULL; - m_RetPassInfo.pDtor = NULL; - m_RetPassInfo.pAssignOperator = NULL; - - - m_ParamsPassInfo.resize(pProto->numOfParams); - - for (int i = 1; i <= pProto->numOfParams; ++i) - { - m_ParamsPassInfo[i-1].size = pProto->paramsPassInfo[i].size; - m_ParamsPassInfo[i-1].type = pProto->paramsPassInfo[i].type; - m_ParamsPassInfo[i-1].flags = GetRealFlags(pProto->paramsPassInfo[i]); - - m_ParamsPassInfo[i-1].pNormalCtor = NULL; - m_ParamsPassInfo[i-1].pCopyCtor = NULL; - m_ParamsPassInfo[i-1].pDtor = NULL; - m_ParamsPassInfo[i-1].pAssignOperator = NULL; - } - } - else if (pProto->paramsPassInfo[0].size == 1) - { - // Version 2 - m_Version = 1; - m_Convention = pProto->convention; - m_NumOfParams = pProto->numOfParams; - - m_RetPassInfo.size = pProto->retPassInfo.size; - m_RetPassInfo.type = pProto->retPassInfo.type; - m_RetPassInfo.flags = pProto->retPassInfo.flags; - - m_RetPassInfo.pNormalCtor = pProto->retPassInfo2.pNormalCtor; - m_RetPassInfo.pCopyCtor = pProto->retPassInfo2.pCopyCtor; - m_RetPassInfo.pDtor = pProto->retPassInfo2.pDtor; - m_RetPassInfo.pAssignOperator = pProto->retPassInfo2.pAssignOperator; - - m_ParamsPassInfo.resize(pProto->numOfParams); - - for (int i = 1; i <= pProto->numOfParams; ++i) - { - m_ParamsPassInfo[i-1].size = pProto->paramsPassInfo[i].size; - m_ParamsPassInfo[i-1].type = pProto->paramsPassInfo[i].type; - m_ParamsPassInfo[i-1].flags = pProto->paramsPassInfo[i].flags; - - m_ParamsPassInfo[i-1].pNormalCtor = pProto->paramsPassInfo2[i].pNormalCtor; - m_ParamsPassInfo[i-1].pCopyCtor = pProto->paramsPassInfo2[i].pCopyCtor; - m_ParamsPassInfo[i-1].pDtor = pProto->paramsPassInfo2[i].pDtor; - m_ParamsPassInfo[i-1].pAssignOperator = pProto->paramsPassInfo2[i].pAssignOperator; - } - } - else - { - // Unknown - m_Version = -1; - } - } - - // Basic compat test - // Other than this, we assume that the plugins know what they're doing - bool CProto::operator == (const CProto &other) const - { - if (m_Version < 0 || other.GetVersion() < 0) - return false; - - if (m_NumOfParams != other.GetNumOfParams()) - return false; - - if (m_Convention != ProtoInfo::CallConv_Unknown && other.GetConvention() != ProtoInfo::CallConv_Unknown && - m_Convention != other.GetConvention()) - return false; - - if (GetRealSize(GetRet()) != GetRealSize(other.GetRet())) - return false; - - for (int i = 0; i < m_NumOfParams; ++i) - { - if (GetRealSize(GetParam(i)) != GetRealSize(other.GetParam(i))) - return false; - if (GetParam(i).type != PassInfo::PassType_Unknown && other.GetParam(i).type != PassInfo::PassType_Unknown) - { - if (GetParam(i).type != other.GetParam(i).type) - return false; - if (GetParam(i).flags != other.GetParam(i).flags) - return false; - } - } - - return true; - } - - bool CProto::ExactlyEqual(const CProto &other) const - { - if (m_Version != other.m_Version || - m_NumOfParams != other.m_NumOfParams || - m_Convention != other.m_Convention || - GetRet() != other.GetRet()) - { - return false; - } - - for (int i = 0; i < m_NumOfParams; ++i) - { - if(GetParam(i) != other.GetParam(i)) - return false; - } - - return true; - } - - } -} diff --git a/utils/mmsource/core/sourcehook/sourcehook_impl_cproto.h b/utils/mmsource/core/sourcehook/sourcehook_impl_cproto.h deleted file mode 100644 index 583fd7a65..000000000 --- a/utils/mmsource/core/sourcehook/sourcehook_impl_cproto.h +++ /dev/null @@ -1,141 +0,0 @@ -/* ======== SourceHook ======== -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko -* ============================ -*/ - -#ifndef __SOURCEHOOK_IMPL_CPROTO_H__ -#define __SOURCEHOOK_IMPL_CPROTO_H__ - -namespace SourceHook -{ - namespace Impl - { - // Internal representation - struct IntPassInfo - { - size_t size; - int type; - unsigned int flags; - - void *pNormalCtor; - void *pCopyCtor; - void *pDtor; - void *pAssignOperator; - - bool operator == (const IntPassInfo &other) const - { - return size == other.size - && type == other.type - && flags == other.flags - && pNormalCtor == other.pNormalCtor - && pDtor == other.pDtor - && pAssignOperator == other.pAssignOperator; - } - - bool operator != (const IntPassInfo &other) const - { - return !(*this == other); - } - }; - - class CProto - { - int m_Version; // -1 = invalid - int m_NumOfParams; - IntPassInfo m_RetPassInfo; - CVector m_ParamsPassInfo; - int m_Convention; - - void Fill(const ProtoInfo *pProto); - - // For old sourcehook.h: flags 0 -> assume ByVal - static unsigned int GetRealFlags(const PassInfo &info) - { - return (info.flags == 0) ? PassInfo::PassFlag_ByVal : info.flags; - } - - public: - CProto() : m_Version(-1) - { - } - - CProto(const ProtoInfo *pProto) - { - Fill(pProto); - } - - CProto(const CProto &other) : m_Version(other.m_Version), m_NumOfParams(other.m_NumOfParams), - m_RetPassInfo(other.m_RetPassInfo), m_ParamsPassInfo(other.m_ParamsPassInfo), - m_Convention(other.m_Convention) - { - - } - - ~CProto() - { - } - - void operator = (const ProtoInfo *pProto) - { - Fill (pProto); - } - - bool operator == (const CProto &other) const; - - bool ExactlyEqual(const CProto &other) const; - - int GetVersion() const - { - return m_Version; - } - - int GetNumOfParams() const - { - return m_NumOfParams; - } - - const IntPassInfo & GetParam(int i) const - { - return m_ParamsPassInfo[i]; - } - - IntPassInfo & GetParam(int i) - { - return m_ParamsPassInfo[i]; - } - - const IntPassInfo & GetRet() const - { - return m_RetPassInfo; - } - - IntPassInfo & GetRet() - { - return m_RetPassInfo; - } - - int GetConvention() const - { - return m_Convention; - } - - static size_t GetRealSize(const IntPassInfo &info) - { - if (info.flags & PassInfo::PassFlag_ByRef) - { - return sizeof(void*); - } - - return info.size; - } - }; - } -} - -#endif - diff --git a/utils/mmsource/core/sourcehook/sourcehook_impl_cvfnptr.cpp b/utils/mmsource/core/sourcehook/sourcehook_impl_cvfnptr.cpp deleted file mode 100644 index 82cdd5cd1..000000000 --- a/utils/mmsource/core/sourcehook/sourcehook_impl_cvfnptr.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* ======== SourceHook ======== -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko -* ============================ -*/ - -#include "sourcehook_impl.h" - -namespace SourceHook -{ - namespace Impl - { - CPageAlloc CVfnPtr::ms_AlignedPageAllocator(8); - - CVfnPtr::CVfnPtr(void *ptr) - : m_Ptr(ptr), m_OrigEntry(*reinterpret_cast(m_Ptr)), - m_OrigCallThunk(NULL) - { - } - - CVfnPtr::~CVfnPtr() - { - if (!m_HookMans.empty()) - m_HookMans.front()->DecrRef(this); - } - - bool CVfnPtr::Init() - { - // Initalize the vfn ptr info object. - - // If we're running on GCC and the original vtable entry is odd - // we have a problem. - // The hook functions use non-virtual member function pointers to - // call the original function (see sourcehook.hxx, SH_SETUP_MFP and SH_CALL_ORIG) - // GCC has the same format for virtual and non-virtual MFPs: - // virtual ones have an odd value as "funcptr" where the offset into the vtable is encoded - // non-virtual ones have the direct function pointer as "funcptr", assuming that it is even - - // When m_OrigEntry is odd, GCC's runtime MFP calling code interpretes it as a virtual - // function call though we want to call the function in a non-virtual way - // (the original function call mechanism between the pre and post hook loop has to bypass - // the virtual calling mechanism in order to call the original function). - -#if SH_COMP==SH_COMP_GCC - if ((((ptrdiff_t)m_OrigEntry) & 1) != 0) - { - // Generate a new thunk - m_OrigCallThunk = ms_AlignedPageAllocator.Alloc(12); - ms_AlignedPageAllocator.SetRW(m_OrigCallThunk); - - unsigned char* thunkBase = reinterpret_cast(m_OrigCallThunk); - ptrdiff_t offset = reinterpret_cast(m_OrigEntry) - thunkBase - 5; - - if (offset >= INT_MIN && offset <= INT_MAX) - { - *(thunkBase + 0) = 0xE9; // offset jump, immediate operand - ptrdiff_t *offsetAddr = reinterpret_cast(thunkBase + 1); - - // destination = src + offset + 5 - // <=> offset = destination - src - 5 - *offsetAddr = offset; - } - else - { - // mov rax, m_origEntry - *(thunkBase + 0) = 0x48; - *(thunkBase + 1) = 0xB8; - void **offsetAddr = reinterpret_cast(thunkBase + 2); - - *offsetAddr = m_OrigEntry; - - // jmp rax - *(thunkBase + 10) = 0xFF; - *(thunkBase + 11) = 0xE0; - } - - ms_AlignedPageAllocator.SetRE(m_OrigCallThunk); - } -#endif - return true; - } - - class CVfnPtrOrigThunkCleanup : public ICleanupTask - { - CPageAlloc *m_Allocator; - void *m_AddrToFree; - - public: - CVfnPtrOrigThunkCleanup(CPageAlloc *allocator, void *addrToFree) : - m_Allocator(allocator), m_AddrToFree(addrToFree) - { - } - - virtual void CleanupAndDeleteThis() - { - m_Allocator->Free(m_AddrToFree); - delete this; - } - }; - - ICleanupTask* CVfnPtr::GetCleanupTask() - { - if (m_OrigCallThunk != NULL) - { - return new CVfnPtrOrigThunkCleanup(&ms_AlignedPageAllocator, m_OrigCallThunk); - } - else - { - return NULL; - } - } - - void* CVfnPtr::GetOrigCallAddr() const - { - if (m_OrigCallThunk) - { - return m_OrigCallThunk; - } - else - { - return m_OrigEntry; - } - } - - bool CVfnPtr::Revert() - { - // Only patch the vfnptr back if the module is still in memory - // If it's not, do not remove stuff like we did before - // First off we did it wrong (shutdown the whole hookman, uh..) and secondly applications may be - // confused by RemoveHook returning false then (yeah, I know, I made this one up, no one checks for RemoveHook error) - if (ModuleInMemory(reinterpret_cast(m_Ptr), SH_PTRSIZE)) - { - return Patch(m_OrigEntry); - } - else - { - return true; - } - } - - CIface *CVfnPtr::FindIface(void *iface) - { - List::iterator iter = m_IfaceList.find(iface); - if (iter == m_IfaceList.end()) - return NULL; - else - return &(*iter); - } - - void CVfnPtr::AddHookMan(CHookManager *pHookMan) - { - List::iterator iter; - - // Don't accept invalid hook managers - if (!*pHookMan) - return; - - // Check whether this hook manager already exists; if yes, ignore. - iter = m_HookMans.find(pHookMan); - if (iter != m_HookMans.end()) - return; - - // It doesn't -> add it. Add it to the end of its version group. - for (iter = m_HookMans.begin(); iter != m_HookMans.end(); ++iter) - { - if ((*iter)->GetVersion() < pHookMan->GetVersion()) - break; - } - - bool isBeginning = iter == m_HookMans.begin(); - - m_HookMans.insert(iter, pHookMan); - - if (isBeginning) - { - pHookMan->IncrRef(this); - if (m_HookMans.size() > 1) - { - // If another hookman was used until now but this one is better - // (which it is because it's the first -> it has a higher version) - // -> switch! - - List::iterator second = m_HookMans.begin(); - ++second; - - (*second)->DecrRef(this); - } - - // Make sure that this vfnptr points at it - Patch(pHookMan->GetHookFunc()); - } - } - - bool CVfnPtr::HookManRemoved(CHookManager *pHookMan) - { - // Don't accept invalid hook managers - if (!*pHookMan) - return true; - - List::iterator iter = m_HookMans.find(pHookMan); - if (iter == m_HookMans.end()) - return true; // Didn't exist here anyway - - if (iter == m_HookMans.begin()) - { - // It is the first one! - pHookMan->DecrRef(this); - m_HookMans.erase(iter); - - if (m_HookMans.empty()) - return false; // No more hookmans -> let SH delete us - - // Activate second -> now first hookman - m_HookMans.front()->IncrRef(this); - Patch(m_HookMans.front()->GetHookFunc()); - } - else - { - m_HookMans.erase(iter); - } - return true; - } - - bool CVfnPtr::Patch(void *newValue) - { - if (!MakePageWritable(m_Ptr)) - { - return false; - } - - *reinterpret_cast(m_Ptr) = newValue; - - return true; - } - - CIface &CVfnPtr::GetIface(void *iface) - { - List::iterator iter = m_IfaceList.find(iface); - if (iter == m_IfaceList.end()) - { - CIface newIface(iface); - if (iface == NULL) - { - m_IfaceList.push_front(newIface); - return m_IfaceList.front(); - } - else - { - m_IfaceList.push_back(newIface); - return m_IfaceList.back(); - } - } - else - { - return *iter; - } - } - } -} diff --git a/utils/mmsource/core/sourcehook/sourcehook_impl_cvfnptr.h b/utils/mmsource/core/sourcehook/sourcehook_impl_cvfnptr.h deleted file mode 100644 index 6ed526042..000000000 --- a/utils/mmsource/core/sourcehook/sourcehook_impl_cvfnptr.h +++ /dev/null @@ -1,91 +0,0 @@ -/* ======== SourceHook ======== -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko -* ============================ -*/ - -#ifndef __SOURCEHOOK_IMPL_CVFNPTR_H__ -#define __SOURCEHOOK_IMPL_CVFNPTR_H__ - -#include "sh_list.h" -#include "sh_memory.h" -#include "sh_pagealloc.h" -#include "sourcehook_impl_cleanuptask.h" - -namespace SourceHook -{ - namespace Impl - { - class CVfnPtr - { - static CPageAlloc ms_AlignedPageAllocator; - - // *** Data *** - void *m_Ptr; - void *m_OrigEntry; - void *m_OrigCallThunk; // See Init() method - - List m_HookMans; - List m_IfaceList; - public: - // *** Descriptor *** - typedef void* Descriptor; - - // *** Interface *** - CVfnPtr(void *ptr); - ~CVfnPtr(); - bool Init(); - inline bool operator==(const Descriptor &other); - inline void *GetPtr() const; - inline void *GetOrigEntry() const; - void *GetOrigCallAddr() const; - inline List &GetIfaceList(); - inline const List &GetIfaceList() const; - CIface *FindIface(void *iface); - CIface &GetIface(void *iface); - bool Patch(void *newValue); - bool Revert(); - - ICleanupTask *GetCleanupTask(); - - void AddHookMan(CHookManager *pHookMan); - // If this returns false, it means that there is no hook manager left - // to use and that this vfnptr should be removed. - bool HookManRemoved(CHookManager *pHookMan); - }; - - // *** Implementation *** - - inline bool CVfnPtr::operator==(const Descriptor &other) - { - return m_Ptr == other; - } - - inline void *CVfnPtr::GetPtr() const - { - return m_Ptr; - } - - inline void *CVfnPtr::GetOrigEntry() const - { - return m_OrigEntry; - } - - inline List &CVfnPtr::GetIfaceList() - { - return m_IfaceList; - } - - inline const List &CVfnPtr::GetIfaceList() const - { - return m_IfaceList; - } - } -} - -#endif - diff --git a/utils/mmsource/core/sourcehook/sourcehook_pibuilder.h b/utils/mmsource/core/sourcehook/sourcehook_pibuilder.h deleted file mode 100644 index bcbb3f074..000000000 --- a/utils/mmsource/core/sourcehook/sourcehook_pibuilder.h +++ /dev/null @@ -1,109 +0,0 @@ -/* ======== SourceHook ======== -* Copyright (C) 2004-2010 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko -* ============================ -*/ - -#ifndef __SOURCEHOOK_PIBUILDER_H__ -#define __SOURCEHOOK_PIBUILDER_H__ - -#include "sourcehook.h" -#include "sh_vector.h" - -namespace SourceHook -{ - // Helper class: protocol information builder - class CProtoInfoBuilder - { - ProtoInfo m_PI; - CVector m_Params; - CVector m_Params2; - public: - CProtoInfoBuilder(int cc) - { - memset(reinterpret_cast(&m_PI), 0, sizeof(ProtoInfo)); - m_PI.convention = cc; - - // dummy 0 params - PassInfo dummy; - PassInfo::V2Info dummy2; - memset(reinterpret_cast(&dummy), 0, sizeof(PassInfo)); - memset(reinterpret_cast(&dummy2), 0, sizeof(PassInfo::V2Info)); - - dummy.size = 1; // Version1 - - m_Params.push_back(dummy); - m_Params2.push_back(dummy2); - } - - void SetReturnType(size_t size, PassInfo::PassType type, int flags, - void *pNormalCtor, void *pCopyCtor, void *pDtor, void *pAssignOperator) - { - if (pNormalCtor) - flags |= PassInfo::PassFlag_OCtor; - - if (pCopyCtor) - flags |= PassInfo::PassFlag_CCtor; - - if (pDtor) - flags |= PassInfo::PassFlag_ODtor; - - if (pAssignOperator) - flags |= PassInfo::PassFlag_AssignOp; - - m_PI.retPassInfo.size = size; - m_PI.retPassInfo.type = type; - m_PI.retPassInfo.flags = flags; - m_PI.retPassInfo2.pNormalCtor = pNormalCtor; - m_PI.retPassInfo2.pCopyCtor = pCopyCtor; - m_PI.retPassInfo2.pDtor = pDtor; - m_PI.retPassInfo2.pAssignOperator = pAssignOperator; - } - - void AddParam(size_t size, PassInfo::PassType type, int flags, - void *pNormalCtor, void *pCopyCtor, void *pDtor, void *pAssignOperator) - { - PassInfo pi; - PassInfo::V2Info pi2; - - if (pNormalCtor) - flags |= PassInfo::PassFlag_OCtor; - - if (pCopyCtor) - flags |= PassInfo::PassFlag_CCtor; - - if (pDtor) - flags |= PassInfo::PassFlag_ODtor; - - if (pAssignOperator) - flags |= PassInfo::PassFlag_AssignOp; - - - pi.size = size; - pi.type = type; - pi.flags = flags; - pi2.pNormalCtor = pNormalCtor; - pi2.pCopyCtor = pCopyCtor; - pi2.pDtor = pDtor; - pi2.pAssignOperator = pAssignOperator; - - m_Params.push_back(pi); - m_Params2.push_back(pi2); - ++m_PI.numOfParams; - } - - operator ProtoInfo*() - { - m_PI.paramsPassInfo = &(m_Params[0]); - m_PI.paramsPassInfo2 = &(m_Params2[0]); - return &m_PI; - } - }; -} - -#endif - diff --git a/utils/mmsource/core/sourcehook/test/AMBuilder b/utils/mmsource/core/sourcehook/test/AMBuilder deleted file mode 100644 index 205daf26d..000000000 --- a/utils/mmsource/core/sourcehook/test/AMBuilder +++ /dev/null @@ -1,42 +0,0 @@ -# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: -import os - -for arch in MMS.archs: - name = 'test_sourcehook' - binary = MMS.Program(builder, name, arch) - binary.compiler.cxxincludes += [ - os.path.join(builder.sourcePath, 'core', 'sourcehook'), - ] - if binary.compiler.version >= 'gcc-4.9': - binary.compiler.cxxflags += ['-fno-devirtualize'] - if binary.compiler.version >= 'clang-2.9' or binary.compiler.version >= 'apple-clang-3.0': - binary.compiler.cxxflags += ['-Wno-null-dereference'] - - binary.sources += [ - 'main.cpp', - '../sourcehook.cpp', - '../sourcehook_impl_chookmaninfo.cpp', - '../sourcehook_impl_chookidman.cpp', - '../sourcehook_impl_cproto.cpp', - '../sourcehook_impl_cvfnptr.cpp', - 'test1.cpp', - 'test2.cpp', - 'test3.cpp', - 'test4.cpp', - 'testbail.cpp', - 'testbail2.cpp', - 'testhookmangen.cpp', - 'testlist.cpp', - 'testmanual.cpp', - 'testmulti.cpp', - 'testoddthunks.cpp', - 'testrecall.cpp', - 'testreentr.cpp', - 'testref.cpp', - 'testrefret.cpp', - 'testvphooks.cpp', - ] - if arch == 'x86': - binary.sources += ['../sourcehook_hookmangen.cpp'] - - builder.Add(binary) diff --git a/utils/mmsource/core/sourcehook/test/Makefile b/utils/mmsource/core/sourcehook/test/Makefile deleted file mode 100644 index d5d4c3979..000000000 --- a/utils/mmsource/core/sourcehook/test/Makefile +++ /dev/null @@ -1,73 +0,0 @@ -# (C)2004-2009 Metamod:Source Development Team -# Makefile written by David "BAILOPAN" Anderson and Pavol Marko - -OPT_FLAGS = -O3 -funroll-loops -s -pipe -DEBUG_FLAGS = -g -ggdb3 -CPP = gcc -LINK = -lstdc++ -INCLUDE = -I. -I.. -MAX_PARAMS=20 - -BINARY = sourcehook_test -OBJECTS = main.cpp sourcehook.cpp sourcehook_hookmangen.cpp sourcehook_impl_chookmaninfo.cpp sourcehook_impl_chookidman.cpp sourcehook_impl_cproto.cpp sourcehook_impl_cvfnptr.cpp $(shell ls -t test*.cpp) -HEADERS = ../sh_list.h ../sh_tinyhash.h ../sh_memory.h ../sh_string.h ../sh_vector.h ../sourcehook_impl.h ../FastDelegate.h ../sourcehook.h ../sh_memfuncinfo.h ../sh_pagealloc.h - -ifeq "$(DEBUG)" "true" - BIN_DIR = Debug - CFLAGS = $(DEBUG_FLAGS) -else - BIN_DIR = Release - CFLAGS = $(OPT_FLAGS) -endif - -CFLAGS += -Wall -Wno-non-virtual-dtor -# Also, enable SH_ASSERT -CFLAGS += -DSH_DEBUG - -OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o) - - -default: all - -$(BIN_DIR)/%.o: %.cpp $(HEADERS) - $(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $< - -../sourcehook.h: ../generate/sourcehook.hxx - (cd ../generate; ./shworker.bin iter sourcehook.hxx sourcehook.h $(MAX_PARAMS); cp sourcehook.h ..) - -../sourcehook.hxx: ../generate/sh_memfuncinfo.hxx - (cd ../generate; ./shworker.bin iter sh_memfuncinfo.hxx sh_memfuncinfo.h $(MAX_PARAMS); cp sh_memfuncino.h ..) - -../FastDelegate.hxx: ../generate/FastDelegate.hxx - (cd ../generate; ./shworker.bin iter FastDelegate.hxx FastDelegate.h $(MAX_PARAMS); cp FastDelegate.h ..) - -debug: - $(MAKE) all DEBUG=true - -all: - mkdir -p $(BIN_DIR) - ln -sf ../sourcehook.cpp - ln -sf ../sourcehook_hookmangen.cpp - ln -sf ../sourcehook_impl_chookidman.cpp - ln -sf ../sourcehook_impl_chookmaninfo.cpp - ln -sf ../sourcehook_impl_cproto.cpp - ln -sf ../sourcehook_impl_cvfnptr.cpp - $(MAKE) $(BINARY) - rm -f $(BINARY) - rm -f sourcehook.cpp - rm -f sourcehook_hookmangen.cpp - rm -f sourcehook_impl_chookidman.cpp - rm -f sourcehook_impl_chookmaninfo.cpp - rm -f sourcehook_impl_cproto.cpp - rm -f sourcehook_impl_cvfnptr.cpp - ln -sf $(BIN_DIR)/$(BINARY) $(BINARY) - - -$(BINARY): $(OBJ_LINUX) - $(CPP) $(INCLUDE) $(CFLAGS) $(OBJ_LINUX) $(LINK) -o $(BIN_DIR)/$(BINARY) - -clean: - rm -rf Release/*.o - rm -rf Release/$(BINARY) - rm -rf Debug/*.o - rm -rf Debug/$(BINARY) diff --git a/utils/mmsource/core/sourcehook/test/generate.bat b/utils/mmsource/core/sourcehook/test/generate.bat deleted file mode 100644 index 3fd08a7df..000000000 --- a/utils/mmsource/core/sourcehook/test/generate.bat +++ /dev/null @@ -1,6 +0,0 @@ -:: Generates everything -:: Usage: -:: generate.bat - - -..\generate\shworker iter testhookmangen.hxx testhookmangen.h %1 \ No newline at end of file diff --git a/utils/mmsource/core/sourcehook/test/main.cpp b/utils/mmsource/core/sourcehook/test/main.cpp deleted file mode 100644 index a04f39c25..000000000 --- a/utils/mmsource/core/sourcehook/test/main.cpp +++ /dev/null @@ -1,142 +0,0 @@ -// Hello BAIL! -// hello pm how are you -// I'm fine, what about you? -// not bad, just looking for mem leaks -// mem leaks in my code!? never! I have to preserve binary compatibility :( -// This is a test file - -#include -#include -#include -#include -#include - -#include "sourcehook_impl.h" -#include "sourcehook.h" -#include "sourcehook_hookmangen.h" - -using namespace std; -bool g_Verbose; - -struct Unloader : public SourceHook::Impl::UnloadListener -{ - void ReadyToUnload(SourceHook::Plugin) { } -} g_UnloadListener; - -#define DECL_TEST(x) bool Test##x(std::string &error); - -#define DO_TEST(x) \ - error.clear(); \ - if (Test##x(error)) \ - { \ - ++passed; \ - cout << "Test" << #x << " passed" << endl; \ - } \ - else \ - { \ - ++failed; \ - cout << "Test" << #x << " FAILED: " << error << endl; \ - } \ - - -DECL_TEST(List); -DECL_TEST(Basic); -DECL_TEST(VafmtAndOverload); -DECL_TEST(ThisPtrOffs); -DECL_TEST(PlugSys); -DECL_TEST(Bail); -DECL_TEST(Reentr); -DECL_TEST(Manual); -DECL_TEST(Recall); -DECL_TEST(Multi); -DECL_TEST(Ref); -DECL_TEST(RefRet); -DECL_TEST(VPHooks); -DECL_TEST(CPageAlloc); // in testhookmangen.cpp -DECL_TEST(HookManGen); -DECL_TEST(OddThunks); - -int main(int argc, char *argv[]) -{ - std::string error; - - g_Verbose = argc > 1 && strcmp(argv[1], "-v") == 0; - - int passed = 0, failed = 0; - - DO_TEST(List); - DO_TEST(Basic); - DO_TEST(VafmtAndOverload); - DO_TEST(ThisPtrOffs); - DO_TEST(PlugSys); - DO_TEST(Bail); - DO_TEST(Reentr); - DO_TEST(Manual); - DO_TEST(Recall); - DO_TEST(Multi); - DO_TEST(Ref); - DO_TEST(RefRet); - DO_TEST(VPHooks); - DO_TEST(CPageAlloc); -#if !defined( _M_AMD64 ) && !defined( __amd64__ ) && !defined(__x86_64__) // TODO: Fix for 64-bit - DO_TEST(HookManGen); -#endif - DO_TEST(OddThunks); - - cout << endl << "----" << endl << "Passed: " << passed << endl << "Failed: " << failed << endl; - cout << "Total: " << passed + failed << endl; - - if (failed) - return 1; - return 0; -} - -SourceHook::ISourceHook *Test_Factory() -{ - return new SourceHook::Impl::CSourceHookImpl(); -} - -void Test_Delete(SourceHook::ISourceHook *shptr) -{ - delete static_cast(shptr); -} - -void Test_CompleteShutdown(SourceHook::ISourceHook *shptr) -{ - static_cast(shptr)->CompleteShutdown(); -} - -class Listener : public SourceHook::Impl::UnloadListener -{ -public: - void ReadyToUnload(SourceHook::Plugin plug) override { - } -} sListener; - -void Test_UnloadPlugin(SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) -{ - static_cast(shptr)->UnloadPlugin(plug, &sListener); -} - -void Test_PausePlugin(SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) -{ - static_cast(shptr)->PausePlugin(plug); -} - -void Test_UnpausePlugin(SourceHook::ISourceHook *shptr, SourceHook::Plugin plug) -{ - static_cast(shptr)->UnpausePlugin(plug); -} - -#if !defined( _M_AMD64 ) && !defined( __amd64__ ) && !defined(__x86_64__) -SourceHook::IHookManagerAutoGen *Test_HMAG_Factory(SourceHook::ISourceHook *shptr) -{ - return new SourceHook::Impl::CHookManagerAutoGen(shptr); -} - -void Test_HMAG_Delete(SourceHook::IHookManagerAutoGen *ptr) -{ - delete static_cast(ptr); -} -#endif - diff --git a/utils/mmsource/core/sourcehook/test/msvc12/test.sln b/utils/mmsource/core/sourcehook/test/msvc12/test.sln deleted file mode 100644 index e3e32039c..000000000 --- a/utils/mmsource/core/sourcehook/test/msvc12/test.sln +++ /dev/null @@ -1,40 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test.vcxproj", "{456BBA64-FF14-4292-8443-3BA79E4D84CC}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug_NoDebugRuntimeLib|Win32 = Debug_NoDebugRuntimeLib|Win32 - Debug_NoDebugRuntimeLib|x64 = Debug_NoDebugRuntimeLib|x64 - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - DebugOpt|Win32 = DebugOpt|Win32 - DebugOpt|x64 = DebugOpt|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug_NoDebugRuntimeLib|Win32.ActiveCfg = Debug_NoDebugRuntimeLib|Win32 - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug_NoDebugRuntimeLib|Win32.Build.0 = Debug_NoDebugRuntimeLib|Win32 - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug_NoDebugRuntimeLib|x64.ActiveCfg = Debug_NoDebugRuntimeLib|x64 - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug_NoDebugRuntimeLib|x64.Build.0 = Debug_NoDebugRuntimeLib|x64 - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug|Win32.ActiveCfg = Debug|Win32 - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug|Win32.Build.0 = Debug|Win32 - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug|x64.ActiveCfg = Debug|x64 - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug|x64.Build.0 = Debug|x64 - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.DebugOpt|Win32.ActiveCfg = DebugOpt|Win32 - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.DebugOpt|Win32.Build.0 = DebugOpt|Win32 - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.DebugOpt|x64.ActiveCfg = DebugOpt|x64 - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.DebugOpt|x64.Build.0 = DebugOpt|x64 - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Release|Win32.ActiveCfg = Release|Win32 - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Release|Win32.Build.0 = Release|Win32 - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Release|x64.ActiveCfg = Release|x64 - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/utils/mmsource/core/sourcehook/test/msvc12/test.vcxproj b/utils/mmsource/core/sourcehook/test/msvc12/test.vcxproj deleted file mode 100644 index d7d068b99..000000000 --- a/utils/mmsource/core/sourcehook/test/msvc12/test.vcxproj +++ /dev/null @@ -1,461 +0,0 @@ - - - - - DebugOpt - Win32 - - - DebugOpt - x64 - - - Debug_NoDebugRuntimeLib - Win32 - - - Debug_NoDebugRuntimeLib - x64 - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {456BBA64-FF14-4292-8443-3BA79E4D84CC} - test - Win32Proj - - - - Application - v120 - MultiByte - - - Application - v120 - MultiByte - - - Application - v120 - MultiByte - - - Application - v120 - MultiByte - - - Application - v120 - MultiByte - - - Application - v120 - MultiByte - - - Application - v120 - MultiByte - - - Application - v120 - MultiByte - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>12.0.30501.0 - - - Debug\ - Debug\ - true - - - true - - - Release\ - Release\ - false - - - false - - - DebugOpt\ - DebugOpt\ - true - - - true - - - Debug_NoDebugRuntimeLib\ - Debug_NoDebugRuntimeLib\ - true - - - true - - - - Disabled - Neither - ../..;..;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;SH_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true - true - EnableFastChecks - MultiThreadedDebug - true - true - - Level3 - EditAndContinue - - - $(OutDir)test.exe - true - $(OutDir)test.pdb - Console - false - - MachineX86 - - - - - Disabled - Neither - ../..;..;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;SH_DEBUG;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - true - true - - - Level3 - ProgramDatabase - - - $(OutDir)test.exe - true - $(OutDir)test.pdb - Console - false - - - - - - - Full - OnlyExplicitInline - Size - true - ../..;..;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true - MultiThreaded - true - true - - - Level3 - true - ProgramDatabase - - - $(OutDir)test.exe - true - true - true - Console - true - true - false - - MachineX86 - - - - - Full - OnlyExplicitInline - Size - true - ../..;..;%(AdditionalIncludeDirectories) - NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true - MultiThreaded - true - true - - - - - Level3 - true - ProgramDatabase - - - $(OutDir)test.exe - true - true - true - Console - true - true - false - - - - - - - Full - OnlyExplicitInline - false - Size - true - ..;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true - false - Default - MultiThreaded - true - true - - Level3 - ProgramDatabase - - - $(OutDir)test.exe - true - $(OutDir)test.pdb - Console - false - - MachineX86 - - - - - Full - OnlyExplicitInline - false - Size - true - ..;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true - false - Default - MultiThreaded - true - true - - - Level3 - ProgramDatabase - - - $(OutDir)test.exe - true - $(OutDir)test.pdb - Console - false - - - - - - - Disabled - Neither - ../..;..;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true - true - Sync - EnableFastChecks - MultiThreaded - true - true - - Level3 - EditAndContinue - - - $(OutDir)test.exe - true - $(OutDir)test.pdb - Console - false - - MachineX86 - - - - - Disabled - Neither - ../..;..;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) - true - Sync - EnableFastChecks - MultiThreaded - true - true - - - Level3 - ProgramDatabase - - - $(OutDir)test.exe - true - $(OutDir)test.pdb - Console - false - - - - - - - - - - - - - - - - - - - - - - false - false - false - false - - - - - - - - - - - - - - echo on -pushd ..\..\generate -shworker.exe iter sourcehook.hxx sourcehook.h 16 -copy sourcehook.h ..\sourcehook.h -popd - - echo on -pushd ..\..\generate -shworker.exe iter sourcehook.hxx sourcehook.h 16 -copy sourcehook.h ..\sourcehook.h -popd - - ..\..\sourcehook.h;%(Outputs) - ..\..\sourcehook.h;%(Outputs) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/utils/mmsource/core/sourcehook/test/msvc12/test.vcxproj.filters b/utils/mmsource/core/sourcehook/test/msvc12/test.vcxproj.filters deleted file mode 100644 index fddea24d7..000000000 --- a/utils/mmsource/core/sourcehook/test/msvc12/test.vcxproj.filters +++ /dev/null @@ -1,191 +0,0 @@ - - - - - {097d3bc9-e1f2-4054-93f3-b12d28409a01} - cpp;c;cxx;def;odl;idl;hpj;bat;asm - - - {c1c8bd55-c7ae-46fc-a115-e490b5068b5c} - - - {17326c78-c7e4-456b-b9df-019e07ca478f} - - - {c15408a4-1aa9-485e-916b-c4eeaddeeee2} - h;hpp;hxx;hm;inl;inc - - - {be31706d-65c6-4945-b7be-84dcbbcde2e7} - - - {75eb6b5b-331a-4eba-b0b2-687c273e2746} - - - {1efd71b2-ab96-4217-ab65-dbc369ec623f} - - - {d4f35fc6-e668-474b-82af-0771f32cde7f} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe - - - - - Source Files\SourceHook - - - Source Files\SourceHook - - - Source Files\SourceHook - - - Source Files\SourceHook - - - Source Files\SourceHook - - - Source Files\SourceHook - - - Source Files\TestTools - - - Source Files\TestTools - - - Source Files\TestTools - - - Source Files\TestTools - - - Source Files\TestTools - - - Source Files\TestTools - - - Source Files\TestTools - - - Source Files\TestTools - - - Source Files\TestTools - - - Source Files\TestTools - - - Source Files\TestTools - - - Source Files\TestTools - - - Source Files\TestTools - - - Source Files\TestTools - - - Source Files\TestTools - - - Source Files\TestTools - - - Source Files\TestTools - - - - - Header Files\TestTools - - - Header Files\TestTools - - - Header Files\TestTools - - - Header Files\SourceHook - - - Header Files\SourceHook - - - Header Files\SourceHook - - - Header Files\SourceHook - - - Header Files\SourceHook - - - Header Files\SourceHook - - - Header Files\SourceHook - - - Header Files\SourceHook - - - Header Files\SourceHook - - - Header Files\SourceHook - - - Header Files\SourceHook - - - Header Files\SourceHook - - - Header Files\SourceHook - - - Header Files\SourceHook - - - Header Files\SourceHook - - - Header Files\SourceHook - - - Header Files\SourceHook - - - Header Files\SourceHook - - - Header Files\SourceHook - - - Header Files\SourceHook - - - Header Files\SourceHook - - - Header Files\SourceHook\generate - - - Header Files\SourceHook\generate - - - Header Files\SourceHook\generate - - - - - Header Files\SourceHook\generate - - - \ No newline at end of file diff --git a/utils/mmsource/core/sourcehook/test/msvc7/test.vcproj b/utils/mmsource/core/sourcehook/test/msvc7/test.vcproj deleted file mode 100644 index 1d5f3978b..000000000 --- a/utils/mmsource/core/sourcehook/test/msvc7/test.vcproj +++ /dev/null @@ -1,417 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/utils/mmsource/core/sourcehook/test/msvc8/test.vcproj b/utils/mmsource/core/sourcehook/test/msvc8/test.vcproj deleted file mode 100644 index 0b49dd3d0..000000000 --- a/utils/mmsource/core/sourcehook/test/msvc8/test.vcproj +++ /dev/null @@ -1,578 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/utils/mmsource/core/sourcehook/test/sourcehook_test.h b/utils/mmsource/core/sourcehook/test/sourcehook_test.h deleted file mode 100644 index 065b543e0..000000000 --- a/utils/mmsource/core/sourcehook/test/sourcehook_test.h +++ /dev/null @@ -1,49 +0,0 @@ -// This file is used for backwards compatibility testing -// It allows us to test binary backwards compatibility by using an older include file HERE: -#include "sourcehook.h" // <-- here -// There. main.cpp which implements all of the following function is always usign sourcehook.h -// and the up-to-date sourcehook_impl.h/sourcehook.cpp. The tests use this file however. -// If the test needs an up-to-date version (like the recall test), it can simply -// #include "sourcehook.h" before including this, thus overriding our decision. - - -SourceHook::ISourceHook *Test_Factory(); -void Test_Delete(SourceHook::ISourceHook *shptr); - -template -struct CAutoPtrDestruction -{ - T *m_Ptr; - CAutoPtrDestruction(T *p) : m_Ptr(p) { } - ~CAutoPtrDestruction() { if (m_Ptr) delete m_Ptr; } - void clear() { m_Ptr = NULL; } - void set(T *ptr) { m_Ptr = ptr; } -}; - -struct CSHPtrAutoDestruction -{ - SourceHook::ISourceHook *m_SHPtr; - CSHPtrAutoDestruction(SourceHook::ISourceHook *shptr) : m_SHPtr(shptr) {} - ~CSHPtrAutoDestruction() { Test_Delete(m_SHPtr); } -}; - -#define GET_SHPTR(var) var = Test_Factory(); CSHPtrAutoDestruction ___autodestruction(var); - -// Access to CSourceHookImpl functions -void Test_CompleteShutdown(SourceHook::ISourceHook *shptr); -void Test_UnloadPlugin(SourceHook::ISourceHook *shptr, SourceHook::Plugin plug); -void Test_PausePlugin(SourceHook::ISourceHook *shptr, SourceHook::Plugin plug); -void Test_UnpausePlugin(SourceHook::ISourceHook *shptr, SourceHook::Plugin plug); - -SourceHook::IHookManagerAutoGen *Test_HMAG_Factory(SourceHook::ISourceHook *pSHPtr); -void Test_HMAG_Delete(SourceHook::IHookManagerAutoGen *ptr); - -struct CHMAGAutoDestruction -{ - SourceHook::IHookManagerAutoGen *m_Ptr; - CHMAGAutoDestruction(SourceHook::IHookManagerAutoGen *ptr) : m_Ptr(ptr) {} - ~CHMAGAutoDestruction() { Test_HMAG_Delete(m_Ptr); } -}; - - -#define GET_HMAG(var, shptr) var = Test_HMAG_Factory(shptr); CHMAGAutoDestruction __hmagautodestruction(var); diff --git a/utils/mmsource/core/sourcehook/test/test.sln b/utils/mmsource/core/sourcehook/test/test.sln deleted file mode 100644 index 75fafaee8..000000000 --- a/utils/mmsource/core/sourcehook/test/test.sln +++ /dev/null @@ -1,26 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test.vcproj", "{456BBA64-FF14-4292-8443-3BA79E4D84CC}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug_NoDebugRuntimeLib|Win32 = Debug_NoDebugRuntimeLib|Win32 - Debug|Win32 = Debug|Win32 - DebugOpt|Win32 = DebugOpt|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug_NoDebugRuntimeLib|Win32.ActiveCfg = Debug_NoDebugRuntimeLib|Win32 - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug_NoDebugRuntimeLib|Win32.Build.0 = Debug_NoDebugRuntimeLib|Win32 - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug|Win32.ActiveCfg = Debug|Win32 - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Debug|Win32.Build.0 = Debug|Win32 - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.DebugOpt|Win32.ActiveCfg = DebugOpt|Win32 - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.DebugOpt|Win32.Build.0 = DebugOpt|Win32 - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Release|Win32.ActiveCfg = Release|Win32 - {456BBA64-FF14-4292-8443-3BA79E4D84CC}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/utils/mmsource/core/sourcehook/test/test.vcproj b/utils/mmsource/core/sourcehook/test/test.vcproj deleted file mode 100644 index 6d6bbc47c..000000000 --- a/utils/mmsource/core/sourcehook/test/test.vcproj +++ /dev/null @@ -1,619 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/utils/mmsource/core/sourcehook/test/test1.cpp b/utils/mmsource/core/sourcehook/test/test1.cpp deleted file mode 100644 index 08bdbd78f..000000000 --- a/utils/mmsource/core/sourcehook/test/test1.cpp +++ /dev/null @@ -1,750 +0,0 @@ -#include -#include "sourcehook_test.h" -#include "testevents.h" - -#include "sh_memory.h" - -namespace -{ - StateList g_States; - SourceHook::ISourceHook *g_SHPtr; - SourceHook::Plugin g_PLID; - - // TEST1 - // Basic tests - // Hooking and callclass - - MAKE_STATE_1(State_ModuleInMemory, bool); - MAKE_STATE(State_F1_Called); - MAKE_STATE_1(State_F1_PreHandler_Called, void*); - MAKE_STATE_1(State_F1_PostHandler_Called, void*); - MAKE_STATE_1(State_F1_HookAdded, bool); - MAKE_STATE(State_F1_HookRemoved); - MAKE_STATE(State_F1_CallClassGenerated); - MAKE_STATE(State_F1_CallClassReleased); - MAKE_STATE_1(State_F299_Called, std::string); - MAKE_STATE_1(State_F299_PreHandlerCalled, std::string); - MAKE_STATE_1(State_F299_PostHandlerCalled, std::string); - MAKE_STATE_1(State_F299Ret, bool); - - class Test - { - public: - virtual void F1() - { - ADD_STATE(State_F1_Called); - } - virtual void F2(){} - virtual void F3(){} - virtual void F4(){} - virtual void F5(){} - virtual void F6(){} - virtual void F7(){} - virtual void F8(){} - virtual void F9(){} - virtual void F10(){} - virtual void F11(){} - virtual void F12(){} - virtual void F13(){} - virtual void F14(){} - virtual void F15(){} - virtual void F16(){} - virtual void F17(){} - virtual void F18(){} - virtual void F19(){} - virtual float F20() const { return 1.0f; } // Look! F20 is const-ed and returns a float - virtual void F21(){} - virtual void F22(){} - virtual void F23(){} - virtual void F24(){} - virtual void F25(){} - virtual void F26(){} - virtual void F27(){} - virtual void F28(){} - virtual void F29(){} - virtual void F30(){} - virtual void F31(){} - virtual void F32(){} - virtual void F33(){} - virtual void F34(){} - virtual void F35(){} - virtual void F36(){} - virtual void F37(){} - virtual void F38(){} - virtual void F39(){} - virtual void F40(){} - virtual void F41(){} - virtual void F42(){} - virtual void F43(){} - virtual void F44(){} - virtual void F45(){} - virtual void F46(){} - virtual void F47(){} - virtual void F48(){} - virtual void F49(){} - virtual void F50(){} - virtual void F51(){} - virtual void F52(){} - virtual void F53(){} - virtual void F54(){} - virtual void F55(){} - virtual void F56(){} - virtual void F57(){} - virtual void F58(){} - virtual void F59(){} - virtual void F60(int &hello){} - virtual void F61(){} - virtual void F62(){} - virtual void F63(){} - virtual void F64(){} - virtual void F65(){} - virtual void F66(){} - virtual void F67(){} - virtual void F68(){} - virtual void F69(){} - virtual void F70(){} - virtual void F71(){} - virtual void F72(){} - virtual void F73(){} - virtual void F74(){} - virtual void F75(){} - virtual void F76(){} - virtual void F77(){} - virtual void F78(){} - virtual void F79(){} - virtual void F80(){} - virtual void F81(){} - virtual void F82(){} - virtual void F83(){} - virtual void F84(){} - virtual void F85(){} - virtual void F86(){} - virtual void F87(){} - virtual void F88(){} - virtual void F89(){} - virtual void F90(){} - virtual void F91(){} - virtual void F92(){} - virtual void F93(){} - virtual void F94(){} - virtual void F95(){} - virtual void F96(){} - virtual void F97(){} - virtual void F98(){} - virtual void F99(){} - virtual void F100(){} - virtual void F101(){} - virtual void F102(){} - virtual void F103(){} - virtual void F104(){} - virtual void F105(){} - virtual void F106(){} - virtual void F107(){} - virtual void F108(){} - virtual void F109(){} - virtual void F110(){} - virtual void F111(){} - virtual void F112(){} - virtual void F113(){} - virtual void F114(){} - virtual void F115(){} - virtual void F116(){} - virtual void F117(){} - virtual void F118(){} - virtual void F119(){} - virtual void F120(){} - virtual void F121(){} - virtual void F122(){} - virtual void F123(){} - virtual void F124(){} - virtual void F125(){} - virtual void F126(){} - virtual void F127(){} - virtual void F128(){} - virtual void F129(){} - virtual void F130(){} - virtual void F131(){} - virtual void F132(){} - virtual void F133(){} - virtual void F134(){} - virtual void F135(){} - virtual void F136(){} - virtual void F137(){} - virtual void F138(){} - virtual void F139(){} - virtual void F140(){} - virtual void F141(){} - virtual void F142(){} - virtual void F143(){} - virtual void F144(){} - virtual void F145(){} - virtual void F146(){} - virtual void F147(){} - virtual void F148(){} - virtual void F149(){} - virtual void F150(){} - virtual void F151(){} - virtual void F152(){} - virtual void F153(){} - virtual void F154(){} - virtual void F155(){} - virtual void F156(){} - virtual void F157(){} - virtual void F158(){} - virtual void F159(){} - virtual void F160(){} - virtual void F161(){} - virtual void F162(){} - virtual void F163(){} - virtual void F164(){} - virtual void F165(){} - virtual void F166(){} - virtual void F167(){} - virtual void F168(){} - virtual void F169(){} - virtual void F170(){} - virtual void F171(){} - virtual void F172(){} - virtual void F173(){} - virtual void F174(){} - virtual void F175(){} - virtual void F176(){} - virtual void F177(){} - virtual void F178(){} - virtual void F179(){} - virtual void F180(){} - virtual void F181(){} - virtual void F182(){} - virtual void F183(){} - virtual void F184(){} - virtual void F185(){} - virtual void F186(){} - virtual void F187(){} - virtual void F188(){} - virtual void F189(){} - virtual void F190(){} - virtual void F191(){} - virtual void F192(){} - virtual void F193(){} - virtual void F194(){} - virtual void F195(){} - virtual void F196(){} - virtual void F197(){} - virtual void F198(){} - virtual void F199(){} - virtual void F200(){} - virtual void F201(){} - virtual void F202(){} - virtual void F203(){} - virtual void F204(){} - virtual void F205(){} - virtual void F206(){} - virtual void F207(){} - virtual void F208(){} - virtual void F209(){} - virtual void F210(){} - virtual void F211(){} - virtual void F212(){} - virtual void F213(){} - virtual void F214(){} - virtual void F215(){} - virtual void F216(){} - virtual void F217(){} - virtual void F218(){} - virtual void F219(){} - virtual void F220(){} - virtual void F221(){} - virtual void F222(){} - virtual void F223(){} - virtual void F224(){} - virtual void F225(){} - virtual void F226(){} - virtual void F227(){} - virtual void F228(){} - virtual void F229(){} - virtual void F230(){} - virtual void F231(){} - virtual void F232(){} - virtual void F233(){} - virtual void F234(){} - virtual void F235(){} - virtual void F236(){} - virtual void F237(){} - virtual void F238(){} - virtual void F239(){} - virtual void F240(){} - virtual void F241(){} - virtual void F242(){} - virtual void F243(){} - virtual void F244(){} - virtual void F245(){} - virtual void F246(){} - virtual void F247(){} - virtual void F248(){} - virtual void F249(){} - virtual void F250(){} - virtual void F251(){} - virtual void F252(){} - virtual void F253(){} - virtual void F254(){} - virtual void F255(){} - virtual void F256(){} - virtual void F257(){} - virtual void F258(){} - virtual void F259(){} - virtual void F260(){} - virtual void F261(){} - virtual void F262(){} - virtual void F263(){} - virtual void F264(){} - virtual void F265(){} - virtual void F266(){} - virtual void F267(){} - virtual void F268(){} - virtual void F269(){} - virtual void F270(){} - virtual void F271(){} - virtual void F272(){} - virtual void F273(){} - virtual void F274(){} - virtual void F275(){} - virtual void F276(){} - virtual void F277(){} - virtual void F278(){} - virtual void F279(){} - virtual void F280(){} - virtual void F281(){} - virtual void F282(){} - virtual void F283(){} - virtual void F284(){} - virtual void F285(){} - virtual void F286(){} - virtual void F287(){} - virtual void F288(){} - virtual void F289(){} - virtual void F290(){} - virtual void F291(){} - virtual void F292(){} - virtual void F293(){} - virtual void F294(){} - virtual void F295(){} - virtual void F296(){} - virtual void F297(){} - virtual void F298(){} - virtual bool F299(const char *mwah) - { - ADD_STATE(State_F299_Called(mwah)); - return true; - } - }; - - SH_DECL_HOOK1(Test, F299, SH_NOATTRIB, 0, bool, const char *); - SH_DECL_HOOK0_void(Test, F1, SH_NOATTRIB, 0); - SH_DECL_HOOK0_void(Test, F2, SH_NOATTRIB, 0); - SH_DECL_HOOK0_void(Test, F3, SH_NOATTRIB, 0); - SH_DECL_HOOK0_void(Test, F4, SH_NOATTRIB, 0); - SH_DECL_HOOK0_void(Test, F5, SH_NOATTRIB, 0); - SH_DECL_HOOK0_void(Test, F6, SH_NOATTRIB, 0); - SH_DECL_HOOK0_void(Test, F7, SH_NOATTRIB, 0); - SH_DECL_HOOK0_void(Test, F8, SH_NOATTRIB, 0); - SH_DECL_HOOK0_void(Test, F9, SH_NOATTRIB, 0); - SH_DECL_HOOK0_void(Test, F10, SH_NOATTRIB, 0); - - SH_DECL_HOOK0(Test, F20, const, 0, float); - SH_DECL_HOOK1_void(Test, F60, SH_NOATTRIB, 0, int&); - - SH_DECL_EXTERN1(Test, F299, SH_NOATTRIB, 0, bool, const char *); - SH_DECL_EXTERN0_void(Test, F1, SH_NOATTRIB, 0); - - META_RES g_F1Pre_WhatToDo; - META_RES g_F1Post_WhatToDo; - - struct HandlersF1 - { - void Pre() - { - ADD_STATE(State_F1_PreHandler_Called(reinterpret_cast(this))); - RETURN_META(g_F1Pre_WhatToDo); - } - - void Post() - { - ADD_STATE(State_F1_PostHandler_Called(reinterpret_cast(this))); - RETURN_META(g_F1Post_WhatToDo); - } - }; - - META_RES g_F299Pre_WhatToDo; - bool g_F299Pre_WhatToRet; - - bool F299_Pre(const char *mwah) - { - ADD_STATE(State_F299_PreHandlerCalled(mwah)); - RETURN_META_VALUE(g_F299Pre_WhatToDo, g_F299Pre_WhatToRet); - } - - bool F299_Post(const char *mwah) - { - ADD_STATE(State_F299_PostHandlerCalled(mwah)); - RETURN_META_VALUE(MRES_OVERRIDE, META_RESULT_STATUS >= MRES_OVERRIDE ? !META_RESULT_OVERRIDE_RET(bool) : - !META_RESULT_ORIG_RET(bool)); - } - - void F60_Pre(int &hello) - { - hello = 10; - } - - Test *MyTestFactory() - { - return new Test; - } -} - -template T func(T a) -{ - return a; -} - -bool TestBasic(std::string &error) -{ - // Simple test for ModuleInMemory - // 1) &error should on the stack - // 2) 0 should not be mapped - ADD_STATE(State_ModuleInMemory(SourceHook::ModuleInMemory(reinterpret_cast(&error), sizeof(error)))); - ADD_STATE(State_ModuleInMemory(SourceHook::ModuleInMemory(0, 1))); - - CHECK_STATES((&g_States, - new State_ModuleInMemory(true), - new State_ModuleInMemory(false), - NULL), "ModuleInMemory"); - - GET_SHPTR(g_SHPtr); - g_PLID = 1337; - - HandlersF1 f1_handlers; - Test *pTest = MyTestFactory(); - CAutoPtrDestruction apd(pTest); - - void *pOrigVfnPtrF1 = (*reinterpret_cast(pTest))[0]; - - // 1) Get a call class and call the member through it and normally - SourceHook::CallClass *cc = SH_GET_CALLCLASS(pTest); - - ADD_STATE(State_F1_CallClassGenerated); - - SH_CALL(cc, &Test::F1)(); - pTest->F1(); - - CHECK_STATES((&g_States, - new State_F1_CallClassGenerated, - new State_F1_Called, - new State_F1_Called, - NULL), "Part 1"); - - CHECK_COND(SH_GET_ORIG_VFNPTR_ENTRY(pTest, &Test::F1) == pOrigVfnPtrF1, "Part S1"); - - // 2) Request a call class again - SourceHook::CallClass *cc2 = SH_GET_CALLCLASS(pTest); - ADD_STATE(State_F1_CallClassGenerated); - - SH_CALL(cc, &Test::F1)(); - SH_CALL(cc2, &Test::F1)(); - pTest->F1(); - - SH_RELEASE_CALLCLASS(cc2); - ADD_STATE(State_F1_CallClassReleased); - - SH_CALL(cc, &Test::F1)(); - pTest->F1(); - - CHECK_STATES((&g_States, - new State_F1_CallClassGenerated, - new State_F1_Called, - new State_F1_Called, - new State_F1_Called, - new State_F1_CallClassReleased, - new State_F1_Called, - new State_F1_Called, - NULL), "Part 2"); - - // 3) Add a pre hook - // (one add memfunc in old format) - g_F1Pre_WhatToDo = MRES_SUPERCEDE; - ADD_STATE(State_F1_HookAdded(SH_ADD_HOOK_MEMFUNC(Test, F1, pTest, &f1_handlers, &HandlersF1::Pre, false) ? true : false)); - - SH_CALL(cc, &Test::F1)(); - pTest->F1(); - - CHECK_STATES((&g_States, - new State_F1_HookAdded(true), - new State_F1_Called, - new State_F1_PreHandler_Called(&f1_handlers), - NULL), "Part 3"); - - CHECK_COND(SH_GET_ORIG_VFNPTR_ENTRY(pTest, &Test::F1) == pOrigVfnPtrF1, "Part S3"); - - // 4) Rerequest the callclass - SH_RELEASE_CALLCLASS(cc); - - ADD_STATE(State_F1_CallClassReleased); - cc2 = SH_GET_CALLCLASS(pTest); - ADD_STATE(State_F1_CallClassGenerated); - - SH_CALL(cc, &Test::F1)(); - pTest->F1(); - - CHECK_STATES((&g_States, - new State_F1_CallClassReleased, - new State_F1_CallClassGenerated, - new State_F1_Called, - new State_F1_PreHandler_Called(&f1_handlers), - NULL), "Part 4"); - - // 5) Check ignore / supercede - g_F1Pre_WhatToDo = MRES_SUPERCEDE; - SH_CALL(cc, &Test::F1)(); - pTest->F1(); - - g_F1Pre_WhatToDo = MRES_IGNORED; - SH_CALL(cc, &Test::F1)(); - pTest->F1(); - - CHECK_STATES((&g_States, - new State_F1_Called, - new State_F1_PreHandler_Called(&f1_handlers), - new State_F1_Called, - new State_F1_PreHandler_Called(&f1_handlers), - new State_F1_Called, - NULL), "Part 5"); - - // 6) remove the hook again - // (one remove memfunc in old format) - SH_REMOVE_HOOK_MEMFUNC(Test, F1, pTest, &f1_handlers, &HandlersF1::Pre, false); - ADD_STATE(State_F1_HookRemoved); - - SH_CALL(cc, &Test::F1)(); - pTest->F1(); - - CHECK_STATES((&g_States, - new State_F1_HookRemoved, - new State_F1_Called, - new State_F1_Called, - NULL), "Part 6"); - - // 7) add a post hook now - g_F1Post_WhatToDo = MRES_IGNORED; - ADD_STATE(State_F1_HookAdded(SH_ADD_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Post), true) ? true : false)); - - SH_CALL(cc, &Test::F1)(); - pTest->F1(); - - CHECK_STATES((&g_States, - new State_F1_HookAdded(true), - new State_F1_Called, - new State_F1_Called, - new State_F1_PostHandler_Called(&f1_handlers), - NULL), "Part 7"); - - // 8) And a pre hook again - g_F1Pre_WhatToDo = MRES_IGNORED; - ADD_STATE(State_F1_HookAdded(SH_ADD_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false) ? true : false)); - - SH_CALL(cc, &Test::F1)(); - pTest->F1(); - - g_F1Pre_WhatToDo = MRES_SUPERCEDE; - SH_CALL(cc, &Test::F1)(); - pTest->F1(); - - CHECK_STATES((&g_States, - new State_F1_HookAdded(true), - new State_F1_Called, - new State_F1_PreHandler_Called(&f1_handlers), - new State_F1_Called, - new State_F1_PostHandler_Called(&f1_handlers), - new State_F1_Called, - new State_F1_PreHandler_Called(&f1_handlers), - new State_F1_PostHandler_Called(&f1_handlers), - NULL), "Part 8"); - - // 9) Remove all hooks - SH_REMOVE_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); - ADD_STATE(State_F1_HookRemoved); - SH_REMOVE_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Post), true); - ADD_STATE(State_F1_HookRemoved); - - SH_CALL(cc, &Test::F1)(); - pTest->F1(); - - CHECK_STATES((&g_States, - new State_F1_HookRemoved, - new State_F1_HookRemoved, - new State_F1_Called, - new State_F1_Called, - NULL), "Part 9"); - - // 10) Some checks on F299 - g_F299Pre_WhatToDo = MRES_IGNORED; - g_F299Pre_WhatToRet = false; - - ADD_STATE(State_F299Ret(pTest->F299("hi"))); - ADD_STATE(State_F299Ret(SH_CALL(cc, &Test::F299)("hi"))); - - CHECK_STATES((&g_States, - new State_F299_Called("hi"), - new State_F299Ret(true), - new State_F299_Called("hi"), - new State_F299Ret(true), - NULL), "Part 10.1"); - - // (one add staticfunc in old format) - SH_ADD_HOOK_STATICFUNC(Test, F299, pTest, F299_Pre, false); - ADD_STATE(State_F299Ret(pTest->F299("hi"))); - ADD_STATE(State_F299Ret(SH_CALL(cc, &Test::F299)("hi"))); - - CHECK_STATES((&g_States, - new State_F299_PreHandlerCalled("hi"), - new State_F299_Called("hi"), - new State_F299Ret(true), - new State_F299_Called("hi"), - new State_F299Ret(true), - NULL), "Part 10.2"); - - SH_ADD_HOOK(Test, F299, pTest, SH_STATIC(F299_Post), true); - ADD_STATE(State_F299Ret(pTest->F299("hi"))); - ADD_STATE(State_F299Ret(SH_CALL(cc, &Test::F299)("hi"))); - - CHECK_STATES((&g_States, - new State_F299_PreHandlerCalled("hi"), - new State_F299_Called("hi"), - new State_F299_PostHandlerCalled("hi"), - new State_F299Ret(false), - new State_F299_Called("hi"), - new State_F299Ret(true), - NULL), "Part 10.3"); - - g_F299Pre_WhatToDo = MRES_OVERRIDE; - ADD_STATE(State_F299Ret(pTest->F299("hi"))); - ADD_STATE(State_F299Ret(SH_CALL(cc, &Test::F299)("hi"))); - - CHECK_STATES((&g_States, - new State_F299_PreHandlerCalled("hi"), - new State_F299_Called("hi"), - new State_F299_PostHandlerCalled("hi"), - new State_F299Ret(true), - new State_F299_Called("hi"), - new State_F299Ret(true), - NULL), "Part 10.4"); - - g_F299Pre_WhatToDo = MRES_SUPERCEDE; - ADD_STATE(State_F299Ret(pTest->F299("hi"))); - ADD_STATE(State_F299Ret(SH_CALL(cc, &Test::F299)("hi"))); - - CHECK_STATES((&g_States, - new State_F299_PreHandlerCalled("hi"), - new State_F299_PostHandlerCalled("hi"), - new State_F299Ret(true), - new State_F299_Called("hi"), - new State_F299Ret(true), - NULL), "Part 10.5"); - - // (one remove staticfunc in old format) - SH_REMOVE_HOOK_STATICFUNC(Test, F299, pTest, F299_Pre, false); - ADD_STATE(State_F299Ret(pTest->F299("hi"))); - ADD_STATE(State_F299Ret(SH_CALL(cc, &Test::F299)("hi"))); - - CHECK_STATES((&g_States, - new State_F299_Called("hi"), - new State_F299_PostHandlerCalled("hi"), - new State_F299Ret(false), - new State_F299_Called("hi"), - new State_F299Ret(true), - NULL), "Part 10.6"); - - SH_REMOVE_HOOK(Test, F299, pTest, SH_STATIC(F299_Post), true); - ADD_STATE(State_F299Ret(pTest->F299("hi"))); - ADD_STATE(State_F299Ret(SH_CALL(cc, &Test::F299)("hi"))); - - CHECK_STATES((&g_States, - new State_F299_Called("hi"), - new State_F299Ret(true), - new State_F299_Called("hi"), - new State_F299Ret(true), - NULL), "Part 10.7"); - - // 11) Release callclass - SH_RELEASE_CALLCLASS(cc); - ADD_STATE(State_F1_CallClassReleased); - - - CHECK_STATES((&g_States, - new State_F1_CallClassReleased, - NULL), "Part 11"); - - // 11 1/2) Test removing hook by id - - g_F1Pre_WhatToDo = MRES_IGNORED; - - pTest->F1(); - int hookPre = SH_ADD_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); - int hookPost = SH_ADD_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Post), true); - - pTest->F1(); - SH_REMOVE_HOOK_ID(hookPost); - pTest->F1(); - SH_REMOVE_HOOK_ID(hookPre); - pTest->F1(); - - CHECK_STATES((&g_States, - new State_F1_Called, - - new State_F1_PreHandler_Called(&f1_handlers), - new State_F1_Called, - new State_F1_PostHandler_Called(&f1_handlers), - - new State_F1_PreHandler_Called(&f1_handlers), - new State_F1_Called, - - new State_F1_Called, - - NULL), "Part 11 1/2"); - - // 12) Try out one ref param - SH_ADD_HOOK(Test, F60, pTest, SH_STATIC(F60_Pre), false); - int a = 0; - pTest->F60(a); - CHECK_COND(a == 10, "Part12"); - SH_REMOVE_HOOK(Test, F60, pTest, SH_STATIC(F60_Pre), false); - - // 13) Remove hooks after the instance has been removed - SH_ADD_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true); - SH_ADD_HOOK(Test, F2, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true); - SH_ADD_HOOK(Test, F3, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); - SH_ADD_HOOK(Test, F4, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true); - SH_ADD_HOOK(Test, F5, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); - SH_ADD_HOOK(Test, F6, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true); - SH_ADD_HOOK(Test, F7, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); - SH_ADD_HOOK(Test, F8, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); - SH_ADD_HOOK(Test, F9, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); - SH_ADD_HOOK(Test, F10, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); - - delete pTest; - apd.clear(); - - SH_REMOVE_HOOK(Test, F1, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true); - SH_REMOVE_HOOK(Test, F2, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true); - SH_REMOVE_HOOK(Test, F3, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); - SH_REMOVE_HOOK(Test, F4, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true); - SH_REMOVE_HOOK(Test, F5, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); - SH_REMOVE_HOOK(Test, F6, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), true); - SH_REMOVE_HOOK(Test, F7, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); - SH_REMOVE_HOOK(Test, F8, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); - SH_REMOVE_HOOK(Test, F9, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); - SH_REMOVE_HOOK(Test, F10, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false); - CHECK_COND(SH_REMOVE_HOOK(Test, F10, pTest, SH_MEMBER(&f1_handlers, &HandlersF1::Pre), false) == false, "Part 12.1"); - - Test_CompleteShutdown(g_SHPtr); - - return true; -} diff --git a/utils/mmsource/core/sourcehook/test/test2.cpp b/utils/mmsource/core/sourcehook/test/test2.cpp deleted file mode 100644 index 78da423ef..000000000 --- a/utils/mmsource/core/sourcehook/test/test2.cpp +++ /dev/null @@ -1,242 +0,0 @@ -#include -#include "sourcehook_test.h" -#include "testevents.h" -#include - -// TEST2 -// Vafmt and Overloaded functions -namespace -{ - StateList g_States; - SourceHook::ISourceHook *g_SHPtr; - SourceHook::Plugin g_PLID; - - MAKE_STATE_1(State_EatYams_Called, int); - MAKE_STATE_1(State_EatYams_Handler_Called, int); - MAKE_STATE_2(State_Vafmt_Called, int, std::string); - MAKE_STATE_2(State_Vafmt_PreHandler_Called, int, std::string); - MAKE_STATE_2(State_Vafmt_PostHandler_Called, int, std::string); - - class IGaben - { - public: - virtual void EatYams() - { - ADD_STATE(State_EatYams_Called(0)); - } - virtual bool EatYams(const char *location) const - { - ADD_STATE(State_EatYams_Called(1)); - return true; - } - virtual void Vafmt1(bool param1, int x, const char *fmt, ...) - { - va_list ap; - va_start(ap, fmt); - char buffer[9999]; - vsnprintf(buffer, 9998, fmt, ap); - buffer[9998] = 0; - va_end(ap); - ADD_STATE(State_Vafmt_Called(1, std::string(buffer))); - } - virtual float Vafmt2(const char *fmt, ...) - { - va_list ap; - va_start(ap, fmt); - char buffer[9999]; - vsnprintf(buffer, 9998, fmt, ap); - buffer[9998] = 0; - va_end(ap); - ADD_STATE(State_Vafmt_Called(2, std::string(buffer))); - return 0.0f; - } - }; - - SH_DECL_HOOK0_void(IGaben, EatYams, SH_NOATTRIB, 0); - SH_DECL_HOOK1(IGaben, EatYams, const, 1, bool, const char *); - SH_DECL_HOOK2_void_vafmt(IGaben, Vafmt1, SH_NOATTRIB, 0, bool, int); - SH_DECL_HOOK0_vafmt(IGaben, Vafmt2, SH_NOATTRIB, 0, float); - - SH_DECL_EXTERN2_void_vafmt(IGaben, Vafmt1, SH_NOATTRIB, 0, bool, int); - SH_DECL_EXTERN0_vafmt(IGaben, Vafmt2, SH_NOATTRIB, 0, float); - - // Hook also using manual hooks! - SH_DECL_MANUALHOOK0_vafmt(IGaben_Vafmt2, 3, 0, 0, float); - SH_DECL_MANUALEXTERN0_vafmt(IGaben_Vafmt2, float); - - SH_DECL_MANUALHOOK2_void_vafmt(IGaben_Vafmt1, 2, 0, 0, bool, int); - SH_DECL_MANUALEXTERN2_void_vafmt(IGaben_Vafmt1, bool, int); - - void EatYams0_Handler() - { - ADD_STATE(State_EatYams_Handler_Called(0)); - } - - bool EatYams1_Handler(const char *loc) - { - ADD_STATE(State_EatYams_Handler_Called(1)); - return true; - } - - void Vafmt1_PreHandler(bool param1, int x, const char *in) - { - ADD_STATE(State_Vafmt_PreHandler_Called(1, std::string(in))); - } - void Vafmt1_PostHandler(bool param1, int x, const char *in) - { - ADD_STATE(State_Vafmt_PostHandler_Called(1, std::string(in))); - } - float Vafmt2_PreHandler(const char *in) - { - ADD_STATE(State_Vafmt_PreHandler_Called(2, std::string(in))); - return 0.0f; - } - float Vafmt2_PostHandler(const char *in) - { - ADD_STATE(State_Vafmt_PostHandler_Called(2, std::string(in))); - return 0.0f; - } - - IGaben *MyInstanceFactory() - { - return new IGaben; - } -} - - -bool TestVafmtAndOverload(std::string &error) -{ - int h1, h2, h3, h4; - GET_SHPTR(g_SHPtr); - g_PLID = 1337; - - IGaben *pGab = MyInstanceFactory(); - CAutoPtrDestruction apd(pGab); - - // Part 1 - SH_CALL(pGab, static_cast(&IGaben::EatYams))(); - SH_CALL(pGab, static_cast(&IGaben::EatYams))("Here!"); - - h1 = SH_ADD_HOOK(IGaben, EatYams, pGab, EatYams0_Handler, false); - h2 = SH_ADD_HOOK(IGaben, EatYams, pGab, EatYams1_Handler, false); - - pGab->EatYams(); - pGab->EatYams("Here!"); - - SH_REMOVE_HOOK_ID(h1); - SH_REMOVE_HOOK_ID(h2); - - CHECK_STATES((&g_States, - new State_EatYams_Called(0), - new State_EatYams_Called(1), - new State_EatYams_Handler_Called(0), - new State_EatYams_Called(0), - new State_EatYams_Handler_Called(1), - new State_EatYams_Called(1), - NULL),"Part 1"); - - // Part 2 - pGab->Vafmt1(true, 55, "Hello %s%d%s", "BA", 1, "L"); - SH_CALL(pGab, &IGaben::Vafmt1)(true, 55, "Hello %s%d%s", "BA", 1, "L"); - pGab->Vafmt2("Hello %s%d%s", "BA", 1, "LOPAN"); - SH_CALL(pGab, &IGaben::Vafmt2)("Hello %s%d%s", "BA", 1, "LOPAN"); - - CHECK_STATES((&g_States, - new State_Vafmt_Called(1, "Hello BA1L"), - new State_Vafmt_Called(1, "Hello BA1L"), - new State_Vafmt_Called(2, "Hello BA1LOPAN"), - new State_Vafmt_Called(2, "Hello BA1LOPAN"), - NULL), "Part 2"); - - // Part 3 - h1 = SH_ADD_HOOK(IGaben, Vafmt1, pGab, Vafmt1_PreHandler, false); - h2 = SH_ADD_HOOK(IGaben, Vafmt1, pGab, Vafmt1_PostHandler, true); - h3 = SH_ADD_HOOK(IGaben, Vafmt2, pGab, Vafmt2_PreHandler, false); - h4 = SH_ADD_HOOK(IGaben, Vafmt2, pGab, Vafmt2_PostHandler, true); - - pGab->Vafmt1(true, 55, "Hello %s%d%s", "BA", 1, "L"); - pGab->Vafmt2("Hello %s%d%s", "BA", 1, "LOPAN"); - - CHECK_STATES((&g_States, - new State_Vafmt_PreHandler_Called(1, std::string("Hello BA1L")), - new State_Vafmt_Called(1, std::string("Hello BA1L")), - new State_Vafmt_PostHandler_Called(1, std::string("Hello BA1L")), - - new State_Vafmt_PreHandler_Called(2, std::string("Hello BA1LOPAN")), - new State_Vafmt_Called(2, std::string("Hello BA1LOPAN")), - new State_Vafmt_PostHandler_Called(2, std::string("Hello BA1LOPAN")), - NULL), "Part 3"); - - - // Check LARGE stuff - char tmpbuf[501]; - for (int i = 0; i < 500; ++i) - tmpbuf[i] = (i % 10) + '0'; - tmpbuf[500] = 0; - - pGab->Vafmt2("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", - tmpbuf, tmpbuf, tmpbuf, tmpbuf, tmpbuf, tmpbuf, tmpbuf, tmpbuf, tmpbuf, tmpbuf, - tmpbuf, tmpbuf, tmpbuf, tmpbuf, tmpbuf, tmpbuf, tmpbuf, tmpbuf, tmpbuf, tmpbuf); - - char refbuf[SourceHook::STRBUF_LEN]; - for (int i = 0; i < (SourceHook::STRBUF_LEN - 1); ++i) - refbuf[i] = (i % 10) + '0'; - refbuf[SourceHook::STRBUF_LEN - 1] = 0; - - CHECK_STATES((&g_States, - new State_Vafmt_PreHandler_Called(2, std::string(refbuf)), - new State_Vafmt_Called(2, std::string(refbuf)), - new State_Vafmt_PostHandler_Called(2, std::string(refbuf)), - NULL - ), "Part 3.1"); - - // Part 4 - SH_REMOVE_HOOK_ID(h1); - SH_REMOVE_HOOK_ID(h2); - SH_REMOVE_HOOK_ID(h3); - SH_REMOVE_HOOK_ID(h4); - - pGab->Vafmt1(true, 55, "Hello %s%d%s", "BA", 1, "L"); - pGab->Vafmt2("Hello %s%d%s", "BA", 1, "LOPAN"); - - CHECK_STATES((&g_States, - new State_Vafmt_Called(1, "Hello BA1L"), - new State_Vafmt_Called(2, "Hello BA1LOPAN"), - NULL), "Part 4"); - - // Part5: Part3 but with manualhooks - h1 = SH_ADD_MANUALHOOK(IGaben_Vafmt1, pGab, SH_STATIC(Vafmt1_PreHandler), false); - h2 = SH_ADD_MANUALHOOK(IGaben_Vafmt1, pGab, SH_STATIC(Vafmt1_PostHandler), true); - h3 = SH_ADD_MANUALHOOK(IGaben_Vafmt2, pGab, SH_STATIC(Vafmt2_PreHandler), false); - h4 = SH_ADD_MANUALHOOK(IGaben_Vafmt2, pGab, SH_STATIC(Vafmt2_PostHandler), true); - - pGab->Vafmt1(true, 55, "Hello %s%d%s", "BA", 1, "L"); - SH_CALL(pGab, &IGaben::Vafmt1)(true, 55, "Hello %s%d%s", "BA", 1, "L"); - SH_MCALL(pGab, IGaben_Vafmt1)(true, 55, "Hello %s%d%s", "BA", 1, "L"); - - CHECK_STATES((&g_States, - new State_Vafmt_PreHandler_Called(1, std::string("Hello BA1L")), - new State_Vafmt_Called(1, std::string("Hello BA1L")), - new State_Vafmt_PostHandler_Called(1, std::string("Hello BA1L")), - - // SH_CALL and SH_MCALL - new State_Vafmt_Called(1, std::string("Hello BA1L")), - new State_Vafmt_Called(1, std::string("Hello BA1L")), - NULL), "Part 5.1"); - - pGab->Vafmt2("Hello %s%d%s", "BA", 1, "LOPAN"); - SH_CALL(pGab, &IGaben::Vafmt2)("Hello %s%d%s", "BA", 1, "LOPAN"); - SH_MCALL(pGab, IGaben_Vafmt2)("Hello %s%d%s", "BA", 1, "LOPAN"); - - CHECK_STATES((&g_States, - new State_Vafmt_PreHandler_Called(2, std::string("Hello BA1LOPAN")), - new State_Vafmt_Called(2, std::string("Hello BA1LOPAN")), - new State_Vafmt_PostHandler_Called(2, std::string("Hello BA1LOPAN")), - - // SH_CALL and SH_MCALL - new State_Vafmt_Called(2, "Hello BA1LOPAN"), - new State_Vafmt_Called(2, "Hello BA1LOPAN"), - NULL), "Part 5.2"); - - return true; -} diff --git a/utils/mmsource/core/sourcehook/test/test3.cpp b/utils/mmsource/core/sourcehook/test/test3.cpp deleted file mode 100644 index c4e88da3f..000000000 --- a/utils/mmsource/core/sourcehook/test/test3.cpp +++ /dev/null @@ -1,245 +0,0 @@ -#include -#include "sourcehook_test.h" -#include "testevents.h" - -// TEST3 -// Tests with inheritance / thisptroffsets - -namespace -{ - StateList g_States; - SourceHook::ISourceHook *g_SHPtr; - SourceHook::Plugin g_PLID; - - MAKE_STATE_1(State_Func1_Called, void*); // param1: This pointer - MAKE_STATE_1(State_Func2_Called, void*); // param1: This pointer - MAKE_STATE_1(State_Func3_Called, void*); // param1: This pointer - - MAKE_STATE_1(State_Func1H_Called, void*); - MAKE_STATE_1(State_Func2H_Called, void*); - MAKE_STATE_1(State_Func3H_Called, void*); - - class Base1 - { - int a; - public: - virtual void Func1() - { - ADD_STATE(State_Func1_Called(reinterpret_cast(this))); - } - }; - class Base2 - { - int b; - public: - virtual void Func2() - { - ADD_STATE(State_Func2_Called(reinterpret_cast(this))); - } - }; - class Derived : public Base1, public Base2 - { - int c; - public: - virtual void Func3() - { - ADD_STATE(State_Func3_Called(reinterpret_cast(this))); - } - }; - - SH_DECL_HOOK0_void(Derived, Func1, SH_NOATTRIB, 0); - SH_DECL_HOOK0_void(Derived, Func2, SH_NOATTRIB, 0); - SH_DECL_HOOK0_void(Derived, Func3, SH_NOATTRIB, 0); - SH_DECL_HOOK0_void(Base1, Func1, SH_NOATTRIB, 0); - SH_DECL_HOOK0_void(Base2, Func2, SH_NOATTRIB, 0); - - void Handler_Func1() - { - ADD_STATE(State_Func1H_Called(META_IFACEPTR(void))); - } - void Handler_Func2() - { - ADD_STATE(State_Func2H_Called(META_IFACEPTR(void))); - } - void Handler_Func3() - { - ADD_STATE(State_Func3H_Called(META_IFACEPTR(void))); - } - - Derived *MyInstanceFactory() - { - return new Derived; - } -} - -bool TestThisPtrOffs(std::string &error) -{ - GET_SHPTR(g_SHPtr); - g_PLID = 1337; - - Derived *pD = MyInstanceFactory(); - Base1 *pB1 = pD; - Base2 *pB2 = pD; - - CAutoPtrDestruction apd(pD); - - - // It should be: - // pB1 = pD - // pB2 > pB1 - - // 1) - // Get a callclass for pD - // Verify whether the this pointers are correct - // Also call them normally to make sure that we aren't messing it up ;) - SourceHook::CallClass *pD_CC = SH_GET_CALLCLASS(pD); - - SH_CALL(pD_CC, &Derived::Func1)(); - SH_CALL(pD_CC, &Derived::Func2)(); - SH_CALL(pD_CC, &Derived::Func3)(); - pD->Func1(); - pD->Func2(); - pD->Func3(); - - CHECK_STATES((&g_States, - new State_Func1_Called(pB1), - new State_Func2_Called(pB2), - new State_Func3_Called(pD), - new State_Func1_Called(pB1), - new State_Func2_Called(pB2), - new State_Func3_Called(pD), - NULL), "Part 1"); - - SH_CALL(pD_CC, &Base1::Func1)(); - SH_CALL(pD_CC, &Base2::Func2)(); - - CHECK_STATES((&g_States, - new State_Func1_Called(pB1), - new State_Func2_Called(pB2), - NULL), "Part 1.1"); - - // 2) - // Get callclasses for the other ones and verify it as well - - SourceHook::CallClass *pB1_CC = SH_GET_CALLCLASS(pB1); - SourceHook::CallClass *pB2_CC = SH_GET_CALLCLASS(pB2); - - SH_CALL(pB1_CC, &Base1::Func1)(); - SH_CALL(pB2_CC, &Base2::Func2)(); - - CHECK_STATES((&g_States, - new State_Func1_Called(pB1), - new State_Func2_Called(pB2), - NULL), "Part 2"); - - - // 3) Add hooks on them (referring to them through pD1 / Derived) - // Check whether the hooks are called with the correct this pointer - - SH_ADD_HOOK(Derived, Func1, pD, SH_STATIC(Handler_Func1), false); - SH_ADD_HOOK(Derived, Func2, pD, SH_STATIC(Handler_Func2), false); - SH_ADD_HOOK(Derived, Func3, pD, SH_STATIC(Handler_Func3), false); - - pD->Func1(); - pD->Func2(); - pD->Func3(); - pB1->Func1(); - pB2->Func2(); - - // The handlers should always be called with the pointer to Derived - CHECK_STATES((&g_States, - new State_Func1H_Called(pD), - new State_Func1_Called(pB1), - new State_Func2H_Called(pD), - new State_Func2_Called(pB2), - new State_Func3H_Called(pD), - new State_Func3_Called(pD), - new State_Func1H_Called(pD), - new State_Func1_Called(pB1), - new State_Func2H_Called(pD), - new State_Func2_Called(pB2), - NULL), "Part 3"); - - SH_REMOVE_HOOK(Derived, Func1, pD, SH_STATIC(Handler_Func1), false); - SH_REMOVE_HOOK(Derived, Func2, pD, SH_STATIC(Handler_Func2), false); - SH_REMOVE_HOOK(Derived, Func3, pD, SH_STATIC(Handler_Func3), false); - - // 4) - // Now add the hooks on Base1 and Base2 and check again - - // Note that the new implicit_cast should convert the pD to Base1*/Base2* :) - SH_ADD_HOOK(Base1, Func1, pD, SH_STATIC(Handler_Func1), false); - SH_ADD_HOOK(Base2, Func2, pD, SH_STATIC(Handler_Func2), false); - SH_ADD_HOOK(Derived, Func3, pD, SH_STATIC(Handler_Func3), false); - - pD->Func1(); - pD->Func2(); - pD->Func3(); - pB1->Func1(); - pB2->Func2(); - - // This time, the handlers for Func1 should be called with pB1 and the handlers - // for Func2 should be called with pB2 - CHECK_STATES((&g_States, - new State_Func1H_Called(pB1), - new State_Func1_Called(pB1), - new State_Func2H_Called(pB2), - new State_Func2_Called(pB2), - new State_Func3H_Called(pD), - new State_Func3_Called(pD), - new State_Func1H_Called(pB1), - new State_Func1_Called(pB1), - new State_Func2H_Called(pB2), - new State_Func2_Called(pB2), - NULL), "Part 4"); - - SH_REMOVE_HOOK(Base1, Func1, pD, SH_STATIC(Handler_Func1), false); - SH_REMOVE_HOOK(Base2, Func2, pD, SH_STATIC(Handler_Func2), false); - SH_REMOVE_HOOK(Derived, Func3, pD, SH_STATIC(Handler_Func3), false); - - - // 5) - // Add some hooks, and use callclasses - - // 5.1) First off, add all of them on pD - SH_ADD_HOOK(Derived, Func1, pD, SH_STATIC(Handler_Func1), false); - SH_ADD_HOOK(Derived, Func2, pD, SH_STATIC(Handler_Func2), false); - SH_ADD_HOOK(Derived, Func3, pD, SH_STATIC(Handler_Func3), false); - - pD->Func1(); - pD->Func2(); - pD->Func3(); - - CHECK_STATES((&g_States, - new State_Func1H_Called(pD), - new State_Func1_Called(pB1), - new State_Func2H_Called(pD), - new State_Func2_Called(pB2), - new State_Func3H_Called(pD), - new State_Func3_Called(pD), - NULL), "Part 5.1"); - - SH_CALL(pD_CC, &Derived::Func1)(); - SH_CALL(pD_CC, &Derived::Func2)(); - SH_CALL(pD_CC, &Derived::Func3)(); - SH_CALL(pB1_CC, &Base1::Func1)(); - SH_CALL(pB2_CC, &Base2::Func2)(); - - CHECK_STATES((&g_States, - new State_Func1_Called(pB1), - new State_Func2_Called(pB2), - new State_Func3_Called(pD), - new State_Func1_Called(pB1), - new State_Func2_Called(pB2), - NULL), "Part 5.2"); - - SH_REMOVE_HOOK(Derived, Func1, pD, SH_STATIC(Handler_Func1), false); - SH_REMOVE_HOOK(Derived, Func2, pD, SH_STATIC(Handler_Func2), false); - SH_REMOVE_HOOK(Derived, Func3, pD, SH_STATIC(Handler_Func3), false); - - SH_RELEASE_CALLCLASS(pB1_CC); - SH_RELEASE_CALLCLASS(pB2_CC); - SH_RELEASE_CALLCLASS(pD_CC); - - return true; -} diff --git a/utils/mmsource/core/sourcehook/test/test4.cpp b/utils/mmsource/core/sourcehook/test/test4.cpp deleted file mode 100644 index 8776204c7..000000000 --- a/utils/mmsource/core/sourcehook/test/test4.cpp +++ /dev/null @@ -1,315 +0,0 @@ -#include -#include "sourcehook_test.h" -#include "testevents.h" - -// TEST4 -// Tests of plugin management system - -namespace -{ - StateList g_States; - SourceHook::ISourceHook *g_SHPtr; - SourceHook::Plugin g_PLID; - - MAKE_STATE(State_Func1_Called); - MAKE_STATE(State_Func2_Called); - MAKE_STATE(State_Func3_Called); - - MAKE_STATE(State_Func1H_Called); - MAKE_STATE(State_Func2H_Called); - MAKE_STATE(State_Func3H_Called); - - class Test - { - public: - virtual void Func1() - { - ADD_STATE(State_Func1_Called); - } - - virtual void Func2() - { - ADD_STATE(State_Func2_Called); - } - - virtual void Func3() - { - ADD_STATE(State_Func3_Called); - } - }; - - SH_DECL_HOOK0_void(Test, Func1, SH_NOATTRIB, 1); - SH_DECL_HOOK0_void(Test, Func2, SH_NOATTRIB, 1); - SH_DECL_HOOK0_void(Test, Func3, SH_NOATTRIB, 1); - - void Handler_Func1() - { - ADD_STATE(State_Func1H_Called); - } - void Handler_Func2() - { - ADD_STATE(State_Func2H_Called); - } - void Handler_Func3() - { - ADD_STATE(State_Func3H_Called); - } - - Test *MyTestFactory() - { - return new Test; - } -} - -bool TestPlugSys(std::string &error) -{ - GET_SHPTR(g_SHPtr); - g_PLID = 1; - - Test *pInst = MyTestFactory(); - CAutoPtrDestruction apd(pInst); - - // 1) - // Add hooks, then issue a complete shutdown - SH_ADD_HOOK(Test, Func1, pInst, SH_STATIC(Handler_Func1), false); - SH_ADD_HOOK(Test, Func2, pInst, SH_STATIC(Handler_Func2), true); - SH_ADD_HOOK(Test, Func3, pInst, SH_STATIC(Handler_Func3), false); - - pInst->Func1(); - pInst->Func2(); - pInst->Func3(); - - CHECK_STATES((&g_States, - new State_Func1H_Called, - new State_Func1_Called, - new State_Func2_Called, - new State_Func2H_Called, - new State_Func3H_Called, - new State_Func3_Called, - NULL), "Part 1.1"); - - Test_CompleteShutdown(g_SHPtr); - - pInst->Func1(); - pInst->Func2(); - pInst->Func3(); - - CHECK_STATES((&g_States, - new State_Func1_Called, - new State_Func2_Called, - new State_Func3_Called, - NULL), "Part 1.2"); - - // 2) - // Add hooks from "different plugins", then shutdown the plugins - - g_PLID = 1; - SH_ADD_HOOK(Test, Func1, pInst, SH_STATIC(Handler_Func1), false); - g_PLID = 2; - SH_ADD_HOOK(Test, Func2, pInst, SH_STATIC(Handler_Func2), true); - g_PLID = 3; - SH_ADD_HOOK(Test, Func3, pInst, SH_STATIC(Handler_Func3), false); - - g_PLID = 1; - SH_ADD_HOOK(Test, Func2, pInst, SH_STATIC(Handler_Func2), true); - SH_ADD_HOOK(Test, Func3, pInst, SH_STATIC(Handler_Func3), false); - - g_PLID = 2; - SH_ADD_HOOK(Test, Func1, pInst, SH_STATIC(Handler_Func1), false); - SH_ADD_HOOK(Test, Func3, pInst, SH_STATIC(Handler_Func3), false); - - g_PLID = 3; - SH_ADD_HOOK(Test, Func1, pInst, SH_STATIC(Handler_Func1), false); - SH_ADD_HOOK(Test, Func2, pInst, SH_STATIC(Handler_Func2), true); - - pInst->Func1(); - pInst->Func2(); - pInst->Func3(); - - CHECK_STATES((&g_States, - new State_Func1H_Called, - new State_Func1H_Called, - new State_Func1H_Called, - new State_Func1_Called, - new State_Func2_Called, - new State_Func2H_Called, - new State_Func2H_Called, - new State_Func2H_Called, - new State_Func3H_Called, - new State_Func3H_Called, - new State_Func3H_Called, - new State_Func3_Called, - NULL), "Part 2.1"); - - // Unload plugins one by one - Test_UnloadPlugin(g_SHPtr, 3); - - pInst->Func1(); - pInst->Func2(); - pInst->Func3(); - - CHECK_STATES((&g_States, - new State_Func1H_Called, - new State_Func1H_Called, - new State_Func1_Called, - new State_Func2_Called, - new State_Func2H_Called, - new State_Func2H_Called, - new State_Func3H_Called, - new State_Func3H_Called, - new State_Func3_Called, - NULL), "Part 2.3.1"); - - Test_UnloadPlugin(g_SHPtr, 2); - - pInst->Func1(); - pInst->Func2(); - pInst->Func3(); - - CHECK_STATES((&g_States, - new State_Func1H_Called, - new State_Func1_Called, - new State_Func2_Called, - new State_Func2H_Called, - new State_Func3H_Called, - new State_Func3_Called, - NULL), "Part 2.4.1"); - - Test_UnloadPlugin(g_SHPtr, 1); - - pInst->Func1(); - pInst->Func2(); - pInst->Func3(); - - CHECK_STATES((&g_States, - new State_Func1_Called, - new State_Func2_Called, - new State_Func3_Called, - NULL), "Part 2.5.1"); - - - // 3) - // Add hooks from "different plugins", then pause the plugins - - g_PLID = 1; - SH_ADD_HOOK(Test, Func1, pInst, SH_STATIC(Handler_Func1), false); - g_PLID = 2; - SH_ADD_HOOK(Test, Func2, pInst, SH_STATIC(Handler_Func2), true); - g_PLID = 3; - SH_ADD_HOOK(Test, Func3, pInst, SH_STATIC(Handler_Func3), false); - - g_PLID = 1; - SH_ADD_HOOK(Test, Func2, pInst, SH_STATIC(Handler_Func2), true); - SH_ADD_HOOK(Test, Func3, pInst, SH_STATIC(Handler_Func3), false); - - g_PLID = 2; - SH_ADD_HOOK(Test, Func1, pInst, SH_STATIC(Handler_Func1), false); - SH_ADD_HOOK(Test, Func3, pInst, SH_STATIC(Handler_Func3), false); - - g_PLID = 3; - SH_ADD_HOOK(Test, Func1, pInst, SH_STATIC(Handler_Func1), false); - SH_ADD_HOOK(Test, Func2, pInst, SH_STATIC(Handler_Func2), true); - - pInst->Func1(); - pInst->Func2(); - pInst->Func3(); - - CHECK_STATES((&g_States, - new State_Func1H_Called, - new State_Func1H_Called, - new State_Func1H_Called, - new State_Func1_Called, - new State_Func2_Called, - new State_Func2H_Called, - new State_Func2H_Called, - new State_Func2H_Called, - new State_Func3H_Called, - new State_Func3H_Called, - new State_Func3H_Called, - new State_Func3_Called, - NULL), "Part 3.1"); - - // Unload plugins one by one - Test_PausePlugin(g_SHPtr, 3); - - pInst->Func1(); - pInst->Func2(); - pInst->Func3(); - - CHECK_STATES((&g_States, - new State_Func1H_Called, - new State_Func1H_Called, - new State_Func1_Called, - new State_Func2_Called, - new State_Func2H_Called, - new State_Func2H_Called, - new State_Func3H_Called, - new State_Func3H_Called, - new State_Func3_Called, - NULL), "Part 3.3.1"); - - Test_PausePlugin(g_SHPtr, 2); - - pInst->Func1(); - pInst->Func2(); - pInst->Func3(); - - CHECK_STATES((&g_States, - new State_Func1H_Called, - new State_Func1_Called, - new State_Func2_Called, - new State_Func2H_Called, - new State_Func3H_Called, - new State_Func3_Called, - NULL), "Part 3.4.1"); - - Test_PausePlugin(g_SHPtr, 1); - - pInst->Func1(); - pInst->Func2(); - pInst->Func3(); - - CHECK_STATES((&g_States, - new State_Func1_Called, - new State_Func2_Called, - new State_Func3_Called, - NULL), "Part 3.5.1"); - - Test_UnpausePlugin(g_SHPtr, 1); - Test_UnpausePlugin(g_SHPtr, 2); - Test_UnpausePlugin(g_SHPtr, 3); - - pInst->Func1(); - pInst->Func2(); - pInst->Func3(); - - CHECK_STATES((&g_States, - new State_Func1H_Called, - new State_Func1H_Called, - new State_Func1H_Called, - new State_Func1_Called, - new State_Func2_Called, - new State_Func2H_Called, - new State_Func2H_Called, - new State_Func2H_Called, - new State_Func3H_Called, - new State_Func3H_Called, - new State_Func3H_Called, - new State_Func3_Called, - NULL), "Part 3.7"); - - // 4) Shutdown :) - Test_CompleteShutdown(g_SHPtr); - - pInst->Func1(); - pInst->Func2(); - pInst->Func3(); - - CHECK_STATES((&g_States, - new State_Func1_Called, - new State_Func2_Called, - new State_Func3_Called, - NULL), "Part 4"); - - return true; -} diff --git a/utils/mmsource/core/sourcehook/test/testbail.cpp b/utils/mmsource/core/sourcehook/test/testbail.cpp deleted file mode 100644 index 46f7b9d33..000000000 --- a/utils/mmsource/core/sourcehook/test/testbail.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// TESTBAIL -// This test used to be a test for a bug BAIL found. -// That bug is now fixed so I've granted BAIL the pleasure of being a test for -// the correct priority ordering of hook managers based on their version. - -/* - THE PROBLEM: - Old hook funcs don't work right when you combine override returns and recalls. - THE SOLUTION: - Always use a new hook func when possible. For this, hook funcs have to be able to say - " HELLO I'M NEW! " - - This file tests that functionality. - - How it works: - testbail.cpp compiles with old version of sourcehook.h. - It sets everything up, adds a hook on a function - Then testbail2.cpp which has the new version adds a hook on the same function and - does a recall and overrides the value in it. -*/ -#include "sourcehook_test.h" -#include "testbail.h" - -namespace N_TestBail -{ - StateList g_States; - SourceHook::ISourceHook *g_SHPtr; - IGaben *g_Gabgab; -} - -namespace -{ - int EatYams_Handler1(int a) - { - ADD_STATE(State_EatYams_Handler1_Called(a)); - RETURN_META_VALUE(MRES_IGNORED, 0); - } -} - -bool TestBail(std::string &error) -{ - GET_SHPTR(g_SHPtr); - g_PLID = 1; - - g_Gabgab = new IGaben; - - SH_ADD_HOOK(IGaben, EatYams, g_Gabgab, SH_STATIC(EatYams_Handler1), false); - - ADD_STATE(State_EatYams_Return(g_Gabgab->EatYams(0xDEAD))); - - CHECK_STATES((&g_States, - new State_EatYams_Handler1_Called(0xDEAD), - new State_EatYams_Called(0xDEAD), - new State_EatYams_Return(5), - NULL), "Part 1"); - - if (!TestBail2(error)) - return false; - - CHECK_STATES((&g_States, - new State_EatYams_Handler1_Called(0xDEAD), - new State_EatYams_Handler2_Called(0xDEAD), - new State_EatYams_Handler3_Called(0xBEEF), - new State_EatYams_Called(0xBEEF), - NULL), "Part 2.1"); - - // WHAT IF NOW SOMEONE UNLOADS PLUGIN 2 !?!?!?!? - Test_UnloadPlugin(g_SHPtr, 2); - - ADD_STATE(State_EatYams_Return(g_Gabgab->EatYams(0xDEAD))); - - CHECK_STATES((&g_States, - new State_EatYams_Handler1_Called(0xDEAD), - new State_EatYams_Called(0xDEAD), - new State_EatYams_Return(5), - NULL), "Part 3"); - - SH_REMOVE_HOOK(IGaben, EatYams, g_Gabgab, SH_STATIC(EatYams_Handler1), false); - - ADD_STATE(State_EatYams_Return(g_Gabgab->EatYams(0xDEAD))); - - CHECK_STATES((&g_States, - new State_EatYams_Called(0xDEAD), - new State_EatYams_Return(5), - NULL), "Part 4"); - - // Now, heh, try it the other way round. - - Test_CompleteShutdown(g_SHPtr); - - if (!TestBail2(error)) - return false; - - CHECK_STATES((&g_States, - new State_EatYams_Handler2_Called(0xDEAD), - new State_EatYams_Handler3_Called(0xBEEF), - new State_EatYams_Called(0xBEEF), - NULL), "Part 5"); - - SH_ADD_HOOK(IGaben, EatYams, g_Gabgab, SH_STATIC(EatYams_Handler1), false); - - ADD_STATE(State_EatYams_Return(g_Gabgab->EatYams(0xDEAD))); - - CHECK_STATES((&g_States, - new State_EatYams_Handler2_Called(0xDEAD), - new State_EatYams_Handler3_Called(0xBEEF), - new State_EatYams_Handler1_Called(0xBEEF), - new State_EatYams_Called(0xBEEF), - new State_EatYams_Return(6), - NULL), "Part 6"); - - delete g_Gabgab; - - return true; -} diff --git a/utils/mmsource/core/sourcehook/test/testbail.h b/utils/mmsource/core/sourcehook/test/testbail.h deleted file mode 100644 index 258a49c39..000000000 --- a/utils/mmsource/core/sourcehook/test/testbail.h +++ /dev/null @@ -1,39 +0,0 @@ -////////////////////////////////////////////////////////////////////////// -// Shared data for testbail - -#include -#include "testevents.h" - -namespace N_TestBail -{ - extern StateList g_States; - extern SourceHook::ISourceHook *g_SHPtr; - - MAKE_STATE_1(State_EatYams_Called, int); - MAKE_STATE_1(State_EatYams_Handler1_Called, int); - MAKE_STATE_1(State_EatYams_Handler2_Called, int); - MAKE_STATE_1(State_EatYams_Handler3_Called, int); - MAKE_STATE_1(State_EatYams_Return, int); - - class IGaben - { - public: - virtual int EatYams(int a) - { - ADD_STATE(State_EatYams_Called(a)); - return 5; - } - }; - - extern IGaben *g_Gabgab; - - bool TestBail2(std::string &error); -} - -using namespace N_TestBail; - -namespace -{ - SourceHook::Plugin g_PLID; - SH_DECL_HOOK1(IGaben, EatYams, SH_NOATTRIB, 0, int, int); -} diff --git a/utils/mmsource/core/sourcehook/test/testbail2.cpp b/utils/mmsource/core/sourcehook/test/testbail2.cpp deleted file mode 100644 index d3f7f28ab..000000000 --- a/utils/mmsource/core/sourcehook/test/testbail2.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// TESTBAIL -// Different compilation unit - -#include "sourcehook.h" -#include "sourcehook_test.h" -#include "testbail.h" - - -int EatYams_Handler2(int a) -{ - ADD_STATE(State_EatYams_Handler2_Called(a)); - RETURN_META_VALUE_NEWPARAMS(MRES_OVERRIDE, 6, &IGaben::EatYams, (0xBEEF)); -} - -int EatYams_Handler3(int a) -{ - ADD_STATE(State_EatYams_Handler3_Called(a)); - RETURN_META_VALUE(MRES_IGNORED, 0); -} - -namespace N_TestBail -{ - bool TestBail2(std::string &error) - { - g_PLID = 2; - - SH_ADD_HOOK(IGaben, EatYams, g_Gabgab, SH_STATIC(EatYams_Handler2), false); - SH_ADD_HOOK(IGaben, EatYams, g_Gabgab, SH_STATIC(EatYams_Handler3), false); - - int ret = g_Gabgab->EatYams(0xDEAD); - - CHECK_COND(ret == 6, "Part 2.1"); - - return true; - } -} diff --git a/utils/mmsource/core/sourcehook/test/testevents.h b/utils/mmsource/core/sourcehook/test/testevents.h deleted file mode 100644 index 0a3116ec5..000000000 --- a/utils/mmsource/core/sourcehook/test/testevents.h +++ /dev/null @@ -1,214 +0,0 @@ -/* ======== SourceHook ======== -* Copyright (C) 2004-2008 Metamod:Source Development Team -* No warranties of any kind -* -* License: zlib/libpng -* -* Author(s): Pavol "PM OnoTo" Marko -* ============================ -*/ - -#ifndef __TESTEVENTS_H__ -#define __TESTEVENTS_H__ - -#include -#include -#include -#include -#include - -extern bool g_Verbose; - -static unsigned int MakeHash(const char *name) -{ - int a = 0; - unsigned int res = 0xFFFFFFFF; - - while (*name) - { - res ^= ((unsigned int)*name << ((a++ % 4)*8)); - ++name; - } - return res; -} - -struct State -{ - virtual ~State() - { - - } - - virtual bool IsEqual(State *other) - { - return (MakeHash(GetName()) == MakeHash(other->GetName())) ? true : false; - } - - virtual bool Ignore() - { - return false; - } - - virtual void Dump() = 0; - virtual const char *GetName() = 0; -}; - -struct IgnoreState : public State -{ - virtual bool Ignore() - { - return true; - } - virtual void Dump() - { - } -}; - -typedef std::list StateList; -namespace -{ - void DumpStates(StateList *sl) - { - for (StateList::iterator iter = sl->begin(); iter != sl->end(); ++iter) - (*iter)->Dump(); - } - - bool StatesOk(StateList *sl, ...) - { - StateList requiredstates; - va_list argptr; - va_start(argptr, sl); - while (true) - { - State *cs = va_arg(argptr, State*); - if (!cs) - break; - if (cs->Ignore()) - continue; - requiredstates.push_back(cs); - } - va_end(argptr); - - if (requiredstates.size() != sl->size()) - { - if (g_Verbose) - { - std::cout << std::endl << "FAIL: Should be:" << std::endl; - DumpStates(&requiredstates); - std::cout << std::endl << "FAIL: Is:" << std::endl; - DumpStates(sl); - } - - for (StateList::iterator iter = requiredstates.begin(); iter != requiredstates.end(); ++iter) - delete *iter; - for (StateList::iterator iter = sl->begin(); iter != sl->end(); ++iter) - delete *iter; - sl->clear(); - return false; - } - - bool ok = true; - StateList::iterator req_iter = requiredstates.begin(); - for (StateList::iterator o_iter = sl->begin(); o_iter != sl->end(); ++o_iter, ++req_iter) - { - if (!(*o_iter)->IsEqual(*req_iter)) - { - ok = false; - break; - } - } - - if (!ok && g_Verbose) - { - std::cout << std::endl << "FAIL: Should be:" << std::endl; - DumpStates(&requiredstates); - std::cout << std::endl << "FAIL: Is:" << std::endl; - DumpStates(sl); - } - - for (StateList::iterator iter = requiredstates.begin(); iter != requiredstates.end(); ++iter) - delete *iter; - for (StateList::iterator iter = sl->begin(); iter != sl->end(); ++iter) - delete *iter; - sl->clear(); - - return ok; - } -} - -#define ADD_STATE(name) g_States.push_back(new name) -#define ADD_STATE_PTR(statesptr, name) statesptr->push_back(new name) - -#define CHECK_STATES(mwah, myerr) if (!StatesOk mwah) { error=myerr; return false; } else if (g_Verbose) { std::cout << "No error: " << myerr << std::endl; } - -#define MAKE_STATE(name) struct name : State { \ - virtual void Dump() { \ - std::cout << " " << #name << std::endl; } \ - const char *GetName() { return #name; } \ - }; - -#define MAKE_STATE_1(name, p1_type) struct name : State { \ - p1_type m_Param1; \ - name(p1_type param1) : m_Param1(param1) {} \ - virtual bool IsEqual(State *other) { \ - if (MakeHash(GetName()) != MakeHash(other->GetName())) \ - return false; \ - name *other2 = static_cast(other); \ - return other2->m_Param1 == m_Param1;\ - } \ - virtual void Dump() { \ - std::cout << " " << #name << "; Param1=" << m_Param1 << std::endl; } \ - const char *GetName() { return #name; } \ - } - -#define MAKE_STATE_2(name, p1_type, p2_type) struct name : State { \ - p1_type m_Param1; \ - p2_type m_Param2; \ - name(p1_type param1, p2_type param2) : m_Param1(param1), m_Param2(param2) {} \ - virtual bool IsEqual(State *other) { \ - if (MakeHash(GetName()) != MakeHash(other->GetName())) \ - return false; \ - name *other2 = static_cast(other); \ - return other2->m_Param1 == m_Param1 && other2->m_Param2 == m_Param2;\ - } \ - virtual void Dump() { \ - std::cout << " " << #name << "; Param1=" << m_Param1 << "; Param2=" << m_Param2 << std::endl; } \ - const char *GetName() { return #name; } \ - } - -#define MAKE_STATE_3(name, p1_type, p2_type, p3_type) struct name : State { \ - p1_type m_Param1; \ - p2_type m_Param2; \ - p3_type m_Param3; \ - name(p1_type param1, p2_type param2, p3_type param3) : m_Param1(param1), m_Param2(param2), m_Param3(param3) {} \ - virtual bool IsEqual(State *other) { \ - if (MakeHash(GetName()) != MakeHash(other->GetName())) \ - return false; \ - name *other2 = static_cast(other); \ - return other2->m_Param1 == m_Param1 && other2->m_Param2 == m_Param2 && other2->m_Param3 == m_Param3;\ - } \ - virtual void Dump() { \ - std::cout << " " << #name << "; Param1=" << m_Param1 << "; Param2=" << m_Param2 << "; Param3=" << m_Param3 << std::endl; } \ - const char *GetName() { return #name; } \ - } - -#define MAKE_STATE_4(name, p1_type, p2_type, p3_type, p4_type) struct name : State { \ - p1_type m_Param1; \ - p2_type m_Param2; \ - p3_type m_Param3; \ - p4_type m_Param4; \ - name(p1_type param1, p2_type param2, p3_type param3, p4_type param4) : m_Param1(param1), m_Param2(param2), m_Param3(param3), m_Param4(param4) {} \ - virtual bool IsEqual(State *other) { \ - if (MakeHash(GetName()) != MakeHash(other->GetName())) \ - return false; \ - name *other2 = static_cast(other); \ - return other2->m_Param1 == m_Param1 && other2->m_Param2 == m_Param2 && other2->m_Param3 == m_Param3 && other2->m_Param4 == m_Param4;\ - } \ - virtual void Dump() { \ - std::cout << " " << #name << "; Param1=" << m_Param1 << "; Param2=" << m_Param2 << "; Param3=" << m_Param3 << "; Param4=" << m_Param4 << std::endl; } \ - const char *GetName() { return #name; } \ - } - -#define CHECK_COND(c, err) if (!(c)) { error = err; return false; } - -#endif diff --git a/utils/mmsource/core/sourcehook/test/testhookmangen.cpp b/utils/mmsource/core/sourcehook/test/testhookmangen.cpp deleted file mode 100644 index 9c0307e47..000000000 --- a/utils/mmsource/core/sourcehook/test/testhookmangen.cpp +++ /dev/null @@ -1,1232 +0,0 @@ -#include -#include -#include "sourcehook.h" -#include "sourcehook_test.h" -#include "testevents.h" -#include "sh_memory.h" -#include "sh_pagealloc.h" -#include "sourcehook_pibuilder.h" - -// TESTHOOKMANGEN -// Test automatic hookman generation -// Tests void and non-void functions -// 0 to 6 params: -// integer-type, float-type, plain-old-data struct and objects with ctors/dtors -// both byval and byref -// also tests ignore/supercede -// also tests recalls - -// :TODO: test override as well - -namespace -{ - StateList g_States; - SourceHook::ISourceHook *g_SHPtr; - SourceHook::Plugin g_PLID; - - SourceHook::IHookManagerAutoGen *g_HMAGPtr; - - // PtrBuf(ptr) gives ptrs unique numbers - // in the order they appear - SourceHook::List g_PtrHash; - - bool g_Inside_LeafFunc = false; // inside a hook or a func - bool g_Silent_CtorDtor = false; // inside a hook or a func - - - // POD / Object types - template - struct POD - { - char x[MYSIZE]; - - bool operator==(const POD &other) - { - return memcmp(reinterpret_cast(x), reinterpret_cast(other.x), MYSIZE) == 0; - } - - bool operator==(char other) - { - for (int i = 0; i < MYSIZE; ++i) - { - if (x[i] != other) - return false; - } - return true; - } - }; - - template - std::ostream& operator <<(std::ostream &os, const POD &obj) - { - os << "Some POD!"; - return os; - } - - MAKE_STATE_1(State_ObjOCtor_Called, int /*MYSIZE*/); - MAKE_STATE_1(State_ObjCCtor_Called, int /*MYSIZE*/); - MAKE_STATE_1(State_ObjODtor_Called, int /*MYSIZE*/); - MAKE_STATE_1(State_ObjAssignOp_Called, int /*MYSIZE*/); - - template - struct Object - { - char x[MYSIZE]; - - Object(char initch) - { - memset(reinterpret_cast(x), initch, MYSIZE); - if (!g_Inside_LeafFunc && !g_Silent_CtorDtor) - ADD_STATE(State_ObjOCtor_Called(MYSIZE)); - } - - Object() - { - if (!g_Inside_LeafFunc && !g_Silent_CtorDtor) - ADD_STATE(State_ObjOCtor_Called(MYSIZE)); - } - - Object(const Object & other) - { - memcpy(reinterpret_cast(x), reinterpret_cast(other.x), MYSIZE); - if (!g_Inside_LeafFunc && !g_Silent_CtorDtor) - ADD_STATE(State_ObjCCtor_Called(MYSIZE)); - } - - ~Object() - { - if (!g_Inside_LeafFunc && !g_Silent_CtorDtor) - ADD_STATE(State_ObjODtor_Called(MYSIZE)); - } - - Object & operator = (const Object &other) - { - if (!g_Inside_LeafFunc && !g_Silent_CtorDtor) - ADD_STATE(State_ObjAssignOp_Called(MYSIZE)); - - memcpy(reinterpret_cast(x), reinterpret_cast(other.x), MYSIZE); - - return *this; - } - - bool operator==(const Object &other) - { - return memcmp(reinterpret_cast(x), reinterpret_cast(other.x), MYSIZE) == 0; - } - }; - - template - std::ostream& operator <<(std::ostream &os, const Object &obj) - { - os << "Some Obj" << static_cast(obj.x[0]); - return os; - } - - // Because of some weird bug in MSVC < 1400 -#define MAKE_PODRET(size) \ - struct PodRet##size \ - { \ - POD actPod; \ - bool operator==(const PodRet##size &other) { return actPod == other.actPod; } \ - bool operator==(char other) { return actPod == other; } \ - }; \ - std::ostream& operator <<(std::ostream &os, const PodRet##size &obj) \ - { \ - os << obj.actPod; \ - return os; \ - } \ - template <> struct MakeRet< PodRet##size > \ - { \ - static PodRet##size Do(int a) \ - { \ - PodRet##size x; \ - memset(reinterpret_cast(x.actPod.x), a, size); \ - return x; \ - } \ - }; - -#define MAKE_OBJRET(size) \ - struct ObjRet##size \ - { \ - Object actObj; \ - bool operator==(const ObjRet##size &other) { return actObj == other.actObj; } \ - bool operator==(char other) { return actObj == other; } \ - }; \ - std::ostream& operator <<(std::ostream &os, const ObjRet##size &obj) \ - { \ - os << obj.actObj; \ - return os; \ - } \ - template <> struct MakeRet< ObjRet##size > \ - { \ - static ObjRet##size Do(int a) NO_OPTIMIZE \ - { \ - ObjRet##size *x = new ObjRet##size; /* ptr: otherwise gcc optimizes away the temp obj */ \ - CAutoPtrDestruction< ObjRet##size > apd(x); \ - memset(reinterpret_cast(x->actObj.x), a, size); \ - return *x; \ - } \ - }; - - - - // "Increment" something: (reproducible change for recall tests) - // integer: ++ - // float: += 1.3 - // pod/object: x[i]++, 0 <= i < MYSIZE - template - struct Increment - { - static void Incr(T &what) - { - ++what; - } - }; - - template<> - struct Increment - { - static void Incr(float &what) - { - what += 1.3f; - } - }; - - template<> - struct Increment - { - static void Incr(double &what) - { - what += 1.3; - } - }; - - template - struct Increment< POD > - { - static void Incr(POD &what) - { - for (int i = 0; i < MYSIZE; ++i) - ++ what.x[i]; - } - }; - - template - struct Increment< Object > - { - static void Incr(Object &what) - { - for (int i = 0; i < MYSIZE; ++i) - ++ what.x[i]; - } - }; - - template<> - struct Increment - { - static void Incr(std::string &what) - { - what += "!"; - } - }; - - #include "testhookmangen.h" - - template - int PtrBuf(T ptr) - { - int a = 0; - - const void *vptr = reinterpret_cast(ptr); - for (SourceHook::List::iterator iter = g_PtrHash.begin(); iter != g_PtrHash.end(); ++iter) - { - if (*iter == vptr) - return a; - else - ++a; - } - g_PtrHash.push_back(vptr); - return static_cast(g_PtrHash.size()) - 1; - } - - template - T PtrBufPtr(T ptr) - { - PtrBuf(ptr); - return ptr; - } - - void PtrBuf_Clear(int leave_in = 0) - { - for (SourceHook::List::iterator iter = g_PtrHash.begin(); iter != g_PtrHash.end();) - { - if (--leave_in < 0) - iter = g_PtrHash.erase(iter); - else - ++iter; - } - } - - // MyDelegate base class for other delegates - class MyDelegate : public SourceHook::ISHDelegate - { - // Unneeded - // because we don't use old SH_REMOVE_HOOK syntax - virtual bool IsEqual(SourceHook::ISHDelegate *pOtherDeleg) - { - return false; - } - - virtual void DeleteThis() - { - delete this; - } - }; - - THGM_MAKE_TEST0_void(0); - THGM_SETUP_PI0(0); - - THGM_MAKE_TEST1_void(1, char); - THGM_SETUP_PI1(1, char, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal); - - THGM_MAKE_TEST1_void(2, short); - THGM_SETUP_PI1(2, short, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal); - - THGM_MAKE_TEST1_void(3, int); - THGM_SETUP_PI1(3, int, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal); - - THGM_MAKE_TEST1_void(4, float); - THGM_SETUP_PI1(4, float, SourceHook::PassInfo::PassType_Float, SourceHook::PassInfo::PassFlag_ByVal); - - THGM_MAKE_TEST1_void(5, double); - THGM_SETUP_PI1(5, double, SourceHook::PassInfo::PassType_Float, SourceHook::PassInfo::PassFlag_ByVal); - - THGM_MAKE_TEST5_void(6, char, short, int, float, double); - THGM_SETUP_PI5(6, - char, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal, - short, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal, - int, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal, - float, SourceHook::PassInfo::PassType_Float, SourceHook::PassInfo::PassFlag_ByVal, - double, SourceHook::PassInfo::PassType_Float, SourceHook::PassInfo::PassFlag_ByVal - ); - - THGM_MAKE_TEST2_void(7, char&, double&); - THGM_SETUP_PI2(7, - char&, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByRef, - double&, SourceHook::PassInfo::PassType_Float, SourceHook::PassInfo::PassFlag_ByRef - ); - - THGM_MAKE_TEST1_void(8, POD<7>); - THGM_SETUP_PI1(8, POD<7>, SourceHook::PassInfo::PassType_Object, SourceHook::PassInfo::PassFlag_ByVal); - - THGM_MAKE_TEST1_void(9, POD<600>); - THGM_SETUP_PI1(9, POD<600>, SourceHook::PassInfo::PassType_Object, SourceHook::PassInfo::PassFlag_ByVal); - - THGM_MAKE_TEST1_void(10, POD<600> &); - THGM_SETUP_PI1(10, POD<600> &, SourceHook::PassInfo::PassType_Object, SourceHook::PassInfo::PassFlag_ByRef); - - THGM_MAKE_TEST2_void(11, Object<3>, Object<600>&); - THGM_SETUP_PI2(11, - Object<3>, SourceHook::PassInfo::PassType_Object, (SourceHook::PassInfo::PassFlag_ByVal | SourceHook::PassInfo::PassFlag_OCtor | SourceHook::PassInfo::PassFlag_ODtor | SourceHook::PassInfo::PassFlag_CCtor), - Object<600> &, SourceHook::PassInfo::PassType_Object, (SourceHook::PassInfo::PassFlag_ByRef | SourceHook::PassInfo::PassFlag_OCtor | SourceHook::PassInfo::PassFlag_ODtor | SourceHook::PassInfo::PassFlag_CCtor) - ); - - THGM_MAKE_TEST0(101, char); - THGM_SETUP_PI0(101); - THGM_SETUP_RI(101, char, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal); - - THGM_MAKE_TEST0(102, short); - THGM_SETUP_PI0(102); - THGM_SETUP_RI(102, short, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal); - - THGM_MAKE_TEST0(103, int); - THGM_SETUP_PI0(103); - THGM_SETUP_RI(103, int, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal); - - THGM_MAKE_TEST0(104, float); - THGM_SETUP_PI0(104); - THGM_SETUP_RI(104, float, SourceHook::PassInfo::PassType_Float, SourceHook::PassInfo::PassFlag_ByVal); - - THGM_MAKE_TEST0(105, double); - THGM_SETUP_PI0(105); - THGM_SETUP_RI(105, double, SourceHook::PassInfo::PassType_Float, SourceHook::PassInfo::PassFlag_ByVal); - - // pod 1-13 - MAKE_PODRET(1); - THGM_MAKE_TEST1(106, PodRet1, int); - THGM_SETUP_PI1(106, - int, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal - ); - THGM_SETUP_RI(106, PodRet1, SourceHook::PassInfo::PassType_Object, SourceHook::PassInfo::PassFlag_ByVal); - - MAKE_PODRET(4); - THGM_MAKE_TEST1(107, PodRet4, int); - THGM_SETUP_PI1(107, - int, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal - ); - THGM_SETUP_RI(107, PodRet4, SourceHook::PassInfo::PassType_Object, SourceHook::PassInfo::PassFlag_ByVal); - - MAKE_PODRET(8); - THGM_MAKE_TEST1(108, PodRet8, int); - THGM_SETUP_PI1(108, - int, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal - ); - THGM_SETUP_RI(108, PodRet8, SourceHook::PassInfo::PassType_Object, SourceHook::PassInfo::PassFlag_ByVal); - - MAKE_PODRET(13); - THGM_MAKE_TEST1(109, PodRet13, int); - THGM_SETUP_PI1(109, - int, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal - ); - THGM_SETUP_RI(109, PodRet13, SourceHook::PassInfo::PassType_Object, SourceHook::PassInfo::PassFlag_ByVal); - - MAKE_OBJRET(13); - THGM_MAKE_TEST1(110, ObjRet13, int); - THGM_SETUP_PI1(110, - int, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal - ); - THGM_SETUP_RI(110, ObjRet13, SourceHook::PassInfo::PassType_Object, - (SourceHook::PassInfo::PassFlag_ByVal | SourceHook::PassInfo::PassFlag_OCtor | SourceHook::PassInfo::PassFlag_ODtor | - SourceHook::PassInfo::PassFlag_CCtor | SourceHook::PassInfo::PassFlag_AssignOp)); - - MAKE_OBJRET(111); - ObjRet111 g_O111_0; - ObjRet111 g_O111_1; - ObjRet111 g_O111_2; - ObjRet111 g_O111_3; - ObjRet111 g_O111_4; - - template <> - struct MakeRet< ObjRet111& > - { - static ObjRet111 &Do(int a) - { - switch (a) - { - case 0: - return g_O111_0; - case 1: - return g_O111_1; - case 2: - return g_O111_2; - case 3: - return g_O111_3; - default: - return g_O111_4; - } - } - }; - - THGM_MAKE_TEST0(111, ObjRet111& ); - THGM_SETUP_PI0(111); - THGM_SETUP_RI(111, ObjRet111& , SourceHook::PassInfo::PassType_Object, - (SourceHook::PassInfo::PassFlag_ByRef | SourceHook::PassInfo::PassFlag_OCtor | SourceHook::PassInfo::PassFlag_ODtor | - SourceHook::PassInfo::PassFlag_CCtor | SourceHook::PassInfo::PassFlag_AssignOp)); - - - THGM_MAKE_TEST3_void(150, int, double, int); - THGM_SETUP_PI3(150, - int, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal, - double, SourceHook::PassInfo::PassType_Float, SourceHook::PassInfo::PassFlag_ByVal, - int, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal); - - // vafmt tests - THGM_MAKE_TEST0_vafmt_void(200); - THGM_SETUP_PI0(200); - - THGM_MAKE_TEST1_vafmt_void(201, char); - THGM_SETUP_PI1(201, char, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal); - - THGM_MAKE_TEST1_vafmt_void(203, int); - THGM_SETUP_PI1(203, int, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal); - - THGM_MAKE_TEST5_vafmt_void(206, char, short, int, float, double); - THGM_SETUP_PI5(206, - char, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal, - short, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal, - int, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal, - float, SourceHook::PassInfo::PassType_Float, SourceHook::PassInfo::PassFlag_ByVal, - double, SourceHook::PassInfo::PassType_Float, SourceHook::PassInfo::PassFlag_ByVal - ); - - THGM_MAKE_TEST2_vafmt_void(207, char&, double&); - THGM_SETUP_PI2(207, - char&, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByRef, - double&, SourceHook::PassInfo::PassType_Float, SourceHook::PassInfo::PassFlag_ByRef - ); - - THGM_MAKE_TEST1_vafmt_void(208, POD<7>); - THGM_SETUP_PI1(208, POD<7>, SourceHook::PassInfo::PassType_Object, SourceHook::PassInfo::PassFlag_ByVal); - - THGM_MAKE_TEST1_vafmt_void(210, POD<600> &); - THGM_SETUP_PI1(210, POD<600> &, SourceHook::PassInfo::PassType_Object, SourceHook::PassInfo::PassFlag_ByRef) - - THGM_MAKE_TEST1_vafmt(211, int, int); - THGM_SETUP_PI1(211, - int, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal - ); - THGM_SETUP_RI(211, int, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal); - - THGM_MAKE_TEST1_vafmt(212, double, int); - THGM_SETUP_PI1(212, - int, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal - ); - THGM_SETUP_RI(212, double, SourceHook::PassInfo::PassType_Float, SourceHook::PassInfo::PassFlag_ByVal); - - THGM_MAKE_TEST1_vafmt(213, PodRet8, int); - THGM_SETUP_PI1(213, - int, SourceHook::PassInfo::PassType_Basic, SourceHook::PassInfo::PassFlag_ByVal - ); - THGM_SETUP_RI(213, PodRet8, SourceHook::PassInfo::PassType_Object, SourceHook::PassInfo::PassFlag_ByVal); - - THGM_MAKE_TEST1_vafmt_void(214, Object<133>); - THGM_SETUP_PI1(214, Object<133>, SourceHook::PassInfo::PassType_Object, - (SourceHook::PassInfo::PassFlag_ByVal | SourceHook::PassInfo::PassFlag_OCtor | SourceHook::PassInfo::PassFlag_ODtor | - SourceHook::PassInfo::PassFlag_CCtor | SourceHook::PassInfo::PassFlag_AssignOp)); - - - MAKE_STATE(State_Hello_Func4_Called); - MAKE_STATE(State_Hello_Func79_Called); - - MAKE_STATE(State_Hello_Func4_PreHook); - MAKE_STATE(State_Hello_Func79_PreHook); - - // Test for larger vtable indices - class Hello - { - public: - virtual void Func0() {} - virtual void Func1() {} - virtual void Func2() {} - virtual void Func3() {} - virtual void Func4() - { - ADD_STATE(State_Hello_Func4_Called); - } - virtual void Func5() {} - virtual void Func6() {} - virtual void Func7() {} - virtual void Func8() {} - virtual void Func9() {} - virtual void Func10() {} - virtual void Func11() {} - virtual void Func12() {} - virtual void Func13() {} - virtual void Func14() {} - virtual void Func15() {} - virtual void Func16() {} - virtual void Func17() {} - virtual void Func18() {} - virtual void Func19() {} - virtual void Func20() {} - virtual void Func21() {} - virtual void Func22() {} - virtual void Func23() {} - virtual void Func24() {} - virtual void Func25() {} - virtual void Func26() {} - virtual void Func27() {} - virtual void Func28() {} - virtual void Func29() {} - virtual void Func30() {} - virtual void Func31() {} - virtual void Func32() {} - virtual void Func33() {} - virtual void Func34() {} - virtual void Func35() {} - virtual void Func36() {} - virtual void Func37() {} - virtual void Func38() {} - virtual void Func39() {} - virtual void Func40() {} - virtual void Func41() {} - virtual void Func42() {} - virtual void Func43() {} - virtual void Func44() {} - virtual void Func45() {} - virtual void Func46() {} - virtual void Func47() {} - virtual void Func48() {} - virtual void Func49() {} - virtual void Func50() {} - virtual void Func51() {} - virtual void Func52() {} - virtual void Func53() {} - virtual void Func54() {} - virtual void Func55() {} - virtual void Func56() {} - virtual void Func57() {} - virtual void Func58() {} - virtual void Func59() {} - virtual void Func60() {} - virtual void Func61() {} - virtual void Func62() {} - virtual void Func63() {} - virtual void Func64() {} - virtual void Func65() {} - virtual void Func66() {} - virtual void Func67() {} - virtual void Func68() {} - virtual void Func69() {} - virtual void Func70() {} - virtual void Func71() {} - virtual void Func72() {} - virtual void Func73() {} - virtual void Func74() {} - virtual void Func75() {} - virtual void Func76() {} - virtual void Func77() {} - virtual void Func78() {} - virtual void Func79() - { - ADD_STATE(State_Hello_Func79_Called); - } - }; - class Hello_Func4_Deleg : public MyDelegate - { - virtual void Func() - { - ADD_STATE(State_Hello_Func4_PreHook); - } - }; - class Hello_Func79_Deleg : public MyDelegate - { - int a; - virtual void Func() - { - ADD_STATE(State_Hello_Func79_PreHook); - } - }; - - bool Tests1(std::string &error) - { - THGM_DO_TEST_void(0, ()); - - THGM_DO_TEST_void(1, (100)); - - THGM_DO_TEST_void(2, (0x1F00)); - - THGM_DO_TEST_void(3, (0x1F000000)); - - THGM_DO_TEST_void(4, (0.5f)); - - THGM_DO_TEST_void(5, (5.5)); - - THGM_DO_TEST_void(6, (100, 0x1f00, 0x1f000000, 0.5f, 5.5)); - - return true; - } - - bool Tests2(std::string &error) - { - char a = 5; - double b = 233.33; - THGM_DO_TEST_void(7, (a, b)); - - POD<7> pod7 = MakeRet< POD<7> >::Do(78); - THGM_DO_TEST_void(8, (pod7)); - - POD<600> pod600 = MakeRet< POD<600> >::Do(34); - THGM_DO_TEST_void(9, (pod600)); - - THGM_DO_TEST_void(10, (pod600)); - - // Test11: Special: constructors/destructors - PtrBuf_Clear(); - Object<3> *obj3_real = new Object<3>(33); - Object<600> *obj600_real = new Object<600>(21); - - Object<3> & obj3 = *obj3_real; - Object<600> & obj600 = *obj600_real; - - CHECK_STATES((&g_States, - new State_ObjOCtor_Called(3), - new State_ObjOCtor_Called(600), - NULL), "Test11 Part0"); - - setuppi_11(); - SourceHook::HookManagerPubFunc myhookman11 = g_HMAGPtr->MakeHookMan(protoinfo_11, 0, 0); \ - CAutoReleaseHookMan arhm_11(myhookman11); \ - int hook1_11, hook2_11, hook3_11, hook4_11; - - TestClass11 *pTest11 = new TestClass11; - CAutoPtrDestruction apd11(pTest11); - - /* no hooks - no hooks */ - PtrBuf_Clear(); - pTest11->Func(obj3, obj600); - - g_Inside_LeafFunc = true; - CHECK_STATES((&g_States, - new State_ObjCCtor_Called(3), - new State_Func11(pTest11, ParamState_m11 (obj3, obj600)), - new State_ObjODtor_Called(3), - NULL), "Test" "11" " Part1"); - g_Inside_LeafFunc = false; - - /* hook1 - no hooks */ - THGM_ADD_HOOK(11, 1); - - PtrBuf_Clear(); - pTest11->Func(obj3, obj600); - g_Inside_LeafFunc = true; - CHECK_STATES((&g_States, - new State_ObjCCtor_Called(3), - - new State_ObjCCtor_Called(3), - new State_Deleg_11(1, pTest11, 0, ParamState_m11 (obj3, obj600)), - new State_ObjODtor_Called(3), - - new State_ObjCCtor_Called(3), - new State_Func11(pTest11, ParamState_m11 (obj3, obj600)), - new State_ObjODtor_Called(3), - - new State_ObjODtor_Called(3), - NULL), "Test" "11" " Part2"); - g_Inside_LeafFunc = false; - - THGM_REMOVE_HOOK(11, 1); - - /* hook1, hook2 - hook3, hook4 */ - THGM_ADD_HOOK(11, 1); - THGM_ADD_HOOK(11, 2); - THGM_ADD_HOOK(11, 3); - THGM_ADD_HOOK(11, 4); - PtrBuf_Clear(); - pTest11->Func(obj3, obj600); - g_Inside_LeafFunc = true; - CHECK_STATES((&g_States, - new State_ObjCCtor_Called(3), - - new State_ObjCCtor_Called(3), - new State_Deleg_11(1, pTest11, 0, ParamState_m11 (obj3, obj600)), - new State_ObjODtor_Called(3), - - new State_ObjCCtor_Called(3), - new State_Deleg_11(2, pTest11, 1, ParamState_m11 (obj3, obj600)), - new State_ObjODtor_Called(3), - - new State_ObjCCtor_Called(3), - new State_Deleg_11(3, pTest11, 2, ParamState_m11 (obj3, obj600)), - new State_ObjODtor_Called(3), - - new State_ObjCCtor_Called(3), - new State_Deleg_11(4, pTest11, 3, ParamState_m11 (obj3, obj600)), - new State_ObjODtor_Called(3), - - new State_ObjODtor_Called(3), - NULL), "Test" "11" " Part3"); - g_Inside_LeafFunc = false; - - /* hook1 - hook3, hook4 WITH RECALLS */ - THGM_REMOVE_HOOK(11, 2); - PtrBuf_Clear(); - TestClass11::ms_DoRecall = true; - pTest11->Func(obj3, obj600); - g_Inside_LeafFunc = true; - CHECK_STATES((&g_States, - new State_ObjCCtor_Called(3), - - new State_ObjCCtor_Called(3), - new State_Deleg_11(1, pTest11, 0 /* first deleg ptr */, ParamState_m11 (obj3, obj600)), - - // recall ! - // second hookfunc -> new copy - new State_ObjCCtor_Called(3), - - // in second hookfunc now - // -> calls orig func - - new State_ObjCCtor_Called(3), - new State_Func11(pTest11, ParamState_m11 (obj3, obj600)(1)), - new State_ObjODtor_Called(3), - - // calls first posthook - new State_ObjCCtor_Called(3), - new State_Deleg_11(3, pTest11, 1 /* second deleg ptr */, ParamState_m11 (obj3, obj600)(1)), - - // recall! - // third hookfunc -> new copy - new State_ObjCCtor_Called(3), - - // calls second posthook - - new State_ObjCCtor_Called(3), - new State_Deleg_11(4, pTest11, 2 /* third deleg ptr */, ParamState_m11 (obj3, obj600)(2)), - - // recall! - // fourth hookfunc -> new copy - new State_ObjCCtor_Called(3), - - // has nothing to do though! - - // fourth hookfunc done -> ret - new State_ObjODtor_Called(3), - - // third hookfunc done -> ret - new State_ObjODtor_Called(3), - // ret from hookhandler which did the recall - new State_ObjODtor_Called(3), - - // second hookfunc done -> ret - new State_ObjODtor_Called(3), - // ret from hookhandler which did the recall - new State_ObjODtor_Called(3), - - // deleg1's instance - new State_ObjODtor_Called(3), - // first hookfunc done -> ret - new State_ObjODtor_Called(3), - NULL), "Test" "11" " Part4"); - g_Inside_LeafFunc = false; - - THGM_REMOVE_HOOK(11, 1); - THGM_REMOVE_HOOK(11, 3); - THGM_REMOVE_HOOK(11, 4); - - delete obj3_real; - delete obj600_real; - - CHECK_STATES((&g_States, - new State_ObjODtor_Called(3), - new State_ObjODtor_Called(600), - NULL), "Test11 Part100"); - - return true; - } - - bool Tests3(std::string &error) - { - THGM_DO_TEST(101, ()); - - THGM_DO_TEST(102, ()); - - THGM_DO_TEST(103, ()); - - THGM_DO_TEST(104, ()); - - THGM_DO_TEST(105, ()); - - // pod returns - THGM_DO_TEST(106, (5)); - THGM_DO_TEST(107, (5)); - THGM_DO_TEST(108, (5)); - THGM_DO_TEST(109, (5)); - - return true; - } - - bool Tests4(std::string &error) - { - // Test110: Special: constructors/destructors on return - PtrBuf_Clear(); - ObjRet13 *obj13_real = new ObjRet13; - ObjRet13 &obj13 = *obj13_real; - - CHECK_STATES((&g_States, - new State_ObjOCtor_Called(13), - NULL), "Test110 Part0"); - - setuppi_110(); - setupri_110(); - - SourceHook::HookManagerPubFunc myhookman110 = g_HMAGPtr->MakeHookMan(protoinfo_110, 0, 0); \ - CAutoReleaseHookMan arhm_110(myhookman110); \ - int hook1_110, hook2_110, hook3_110, hook4_110; - - TestClass110 *pTest110 = new TestClass110; - CAutoPtrDestruction apd110(pTest110); - - /* no hooks - no hooks */ - PtrBuf_Clear(); - obj13 = pTest110->Func(5); - - g_Inside_LeafFunc = true; - CHECK_STATES((&g_States, - new State_Func110(pTest110, ParamState_m110 (5)), - new State_ObjOCtor_Called(13), // MakeRet: Construction of x - new State_ObjCCtor_Called(13), // Return from MakeRet -> construct temporary object in our stack - new State_ObjODtor_Called(13), // MakeRet: Destruction of x - - new State_ObjAssignOp_Called(13), // assign: obj13 = temporary object in our stack - new State_ObjODtor_Called(13), // Func110: destruction of temporary object - NULL), "Test" "110" " Part1"); - g_Inside_LeafFunc = false; - - /* hook1 - no hooks */ - THGM_ADD_HOOK(110, 1); - - PtrBuf_Clear(); - obj13 = pTest110->Func(5); - g_Inside_LeafFunc = true; - CHECK_STATES((&g_States, - // HookFunc: construct orig_ret/override_ret/plugin_ret objects - new State_ObjOCtor_Called(13), - new State_ObjOCtor_Called(13), - new State_ObjOCtor_Called(13), - - // Calling delegate - new State_Deleg_110(1, pTest110, 0, ParamState_m110 (5)), - - new State_ObjOCtor_Called(13), // MakeRet: Construction of x - new State_ObjCCtor_Called(13), // Return from MakeRet -> construct temporary object in HookFunc's stack - new State_ObjODtor_Called(13), // MakeRet: Destruction of x - - // back in hookfunc - new State_ObjAssignOp_Called(13), // assign: plugin_ret = temporary object in HookFunc's stack - new State_ObjODtor_Called(13), // destruction of temporary object in HookFunc's stack - - // Calling orig function Func110 - new State_Func110(pTest110, ParamState_m110 (5)), - new State_ObjOCtor_Called(13), // MakeRet: Construction of x - new State_ObjCCtor_Called(13), // Return from MakeRet -> construct temporary object in HookFunc's stack - new State_ObjODtor_Called(13), // MakeRet: Destruction of x - - // back in hookfunc - new State_ObjAssignOp_Called(13), // assign: orig_ret = temporary object in HookFunc's stack - new State_ObjODtor_Called(13), // destruction of temporary object in HookFunc's stack - - // hookfunc is returning: - new State_ObjCCtor_Called(13), // copy to temp object in our stack - - // hookfunc cleans up its stack -> destroys plugin_ret/override_ret/orig_ret - new State_ObjODtor_Called(13), - new State_ObjODtor_Called(13), - new State_ObjODtor_Called(13), - - // we are in our function: assign - new State_ObjAssignOp_Called(13), // assign: obj13 = temporary object in our stack - new State_ObjODtor_Called(13), // Func110: destruction of temporary object - - NULL), "Test" "11" " Part2"); - - CHECK_COND(obj13 == 0, "Test" "11" " Part 2.1"); - g_Inside_LeafFunc = false; - - THGM_REMOVE_HOOK(110, 1); - - /* hook1, hook2 - hook3, hook4 */ - THGM_ADD_HOOK(110, 1); - THGM_ADD_HOOK(110, 2); - THGM_ADD_HOOK(110, 3); - THGM_ADD_HOOK(110, 4); - - PtrBuf_Clear(); - obj13 = pTest110->Func(5); - g_Inside_LeafFunc = true; - CHECK_STATES((&g_States, - // HookFunc: construct orig_ret/override_ret/plugin_ret objects - new State_ObjOCtor_Called(13), - new State_ObjOCtor_Called(13), - new State_ObjOCtor_Called(13), - - // Calling delegate1 - new State_Deleg_110(1, pTest110, 0, ParamState_m110 (5)), - - new State_ObjOCtor_Called(13), // MakeRet: Construction of x - new State_ObjCCtor_Called(13), // Return from MakeRet -> construct temporary object in HookFunc's stack - new State_ObjODtor_Called(13), // MakeRet: Destruction of x - - // back in hookfunc - new State_ObjAssignOp_Called(13), // assign: plugin_ret = temporary object in HookFunc's stack - new State_ObjODtor_Called(13), // destruction of temporary object in HookFunc's stack - - - // Calling delegate2 - new State_Deleg_110(2, pTest110, 1, ParamState_m110 (5)), - - new State_ObjOCtor_Called(13), // MakeRet: Construction of x - new State_ObjCCtor_Called(13), // Return from MakeRet -> construct temporary object in HookFunc's stack - new State_ObjODtor_Called(13), // MakeRet: Destruction of x - - // back in hookfunc - new State_ObjAssignOp_Called(13), // assign: plugin_ret = temporary object in HookFunc's stack - new State_ObjODtor_Called(13), // destruction of temporary object in HookFunc's stack - - // hookfunc finds out that the hook wanted to SUPERCEDE --> copy to override_Ret - new State_ObjAssignOp_Called(13), - - // SUPERCEDE -> orig function is not called - // instead: orig_ret = override_ret - new State_ObjAssignOp_Called(13), - - // Calling delegate3 - new State_Deleg_110(3, pTest110, 2, ParamState_m110 (5)), - - new State_ObjOCtor_Called(13), // MakeRet: Construction of x - new State_ObjCCtor_Called(13), // Return from MakeRet -> construct temporary object in HookFunc's stack - new State_ObjODtor_Called(13), // MakeRet: Destruction of x - - // back in hookfunc - new State_ObjAssignOp_Called(13), // assign: plugin_ret = temporary object in HookFunc's stack - new State_ObjODtor_Called(13), // destruction of temporary object in HookFunc's stack - - // Calling delegate4 - new State_Deleg_110(4, pTest110, 3, ParamState_m110 (5)), - - new State_ObjOCtor_Called(13), // MakeRet: Construction of x - new State_ObjCCtor_Called(13), // Return from MakeRet -> construct temporary object in HookFunc's stack - new State_ObjODtor_Called(13), // MakeRet: Destruction of x - - // back in hookfunc - new State_ObjAssignOp_Called(13), // assign: plugin_ret = temporary object in HookFunc's stack - new State_ObjODtor_Called(13), // destruction of temporary object in HookFunc's stack - - // hookfunc finds out that the hook wanted to SUPERCEDE --> copy to override_Ret (yes really, we overwrite the old value!) - new State_ObjAssignOp_Called(13), - - // hookfunc is returning: - new State_ObjCCtor_Called(13), // copy to temp object in our stack - - // hookfunc cleans up its stack -> destroys plugin_ret/override_ret/orig_ret - new State_ObjODtor_Called(13), - new State_ObjODtor_Called(13), - new State_ObjODtor_Called(13), - - // we are in our function: assign - new State_ObjAssignOp_Called(13), // assign: obj13 = temporary object in our stack - new State_ObjODtor_Called(13), // Func110: destruction of temporary object - - NULL), "Test" "11" " Part3"); - - CHECK_COND(obj13 == 4, "Test" "11" " Part 3.1"); - g_Inside_LeafFunc = false; - - THGM_REMOVE_HOOK(110, 1); - THGM_REMOVE_HOOK(110, 2); - THGM_REMOVE_HOOK(110, 3); - THGM_REMOVE_HOOK(110, 4); - - delete obj13_real; - - CHECK_STATES((&g_States, - new State_ObjODtor_Called(13), - NULL), "Test110 Part100"); - - - THGM_DO_TEST_void(150, (5, 5.5, 6)); - - return true; - } - - bool Tests5(std::string &error) - { - // RefRet - THGM_DO_TEST(111, ()); - - // Vafmt - - THGM_DO_TEST_void(200, ("Hello %s%d%s", "BA", 1, "L!")); - - THGM_DO_TEST_void(201, (100, "Hello %s%d%s", "BA", 1, "L!")); - - THGM_DO_TEST_void(203, (0x1F000000, "Hello %s%d%s", "BA", 1, "L!")); - - THGM_DO_TEST_void(206, (100, 0x1f00, 0x1f000000, 0.5f, 5.5, "Hello %s%d%s", "BA", 1, "L!")); - - char a = 5; - double b = 233.33; - THGM_DO_TEST_void(207, (a, b, "Hello %s%d%s", "BA", 1, "L!")); - - POD<7> pod7 = MakeRet< POD<7> >::Do(78); - THGM_DO_TEST_void(208, (pod7, "Hello %s%d%s", "BA", 1, "L!")); - - POD<600> pod600 = MakeRet< POD<600> >::Do(34); - THGM_DO_TEST_void(210, (pod600, "Hello %s%d%s", "BA", 1, "L!")); - - - THGM_DO_TEST(211, (5, "Hello %s%d%s", "BA", 1, "L!")); - THGM_DO_TEST(212, (5, "Hello %s%d%s", "BA", 1, "L!")); - THGM_DO_TEST(213, (5, "Hello %s%d%s", "BA", 1, "L!")); - - // Silence Object's ctors/dtors: we only want a forced byref param - g_Silent_CtorDtor = true; - Object<133> *myobj133 = new Object<133>; - THGM_DO_TEST_void(214, (*myobj133, "Hello %s%d%s", "BA", 1, "L!")); - delete myobj133; - g_Silent_CtorDtor = false; - - // Test for high vtable indices - Hello *pHello = new Hello; - CAutoPtrDestruction apdHello(pHello); - SourceHook::CProtoInfoBuilder helloPi(SourceHook::ProtoInfo::CallConv_ThisCall); - SourceHook::HookManagerPubFunc helloHM_4 = g_HMAGPtr->MakeHookMan(helloPi, 0, 4); - SourceHook::HookManagerPubFunc helloHM_79 = g_HMAGPtr->MakeHookMan(helloPi, 0, 79); - - pHello->Func4(); - pHello->Func79(); - SH_CALL(pHello, &Hello::Func4)(); - SH_CALL(pHello, &Hello::Func79)(); - CHECK_STATES((&g_States, - new State_Hello_Func4_Called, - new State_Hello_Func79_Called, - new State_Hello_Func4_Called, - new State_Hello_Func79_Called, - NULL), "Test" "Hello" " Part1"); - - int helloHook4 = g_SHPtr->AddHook(g_PLID, SourceHook::ISourceHook::Hook_Normal, reinterpret_cast(pHello), - 0, helloHM_4, new Hello_Func4_Deleg, false); - - int helloHook79 = g_SHPtr->AddHook(g_PLID, SourceHook::ISourceHook::Hook_Normal, reinterpret_cast(pHello), - 0, helloHM_79, new Hello_Func79_Deleg, false); - - pHello->Func4(); - pHello->Func79(); - SH_CALL(pHello, &Hello::Func4)(); - SH_CALL(pHello, &Hello::Func79)(); - - CHECK_STATES((&g_States, - new State_Hello_Func4_PreHook, - new State_Hello_Func4_Called, - new State_Hello_Func79_PreHook, - new State_Hello_Func79_Called, - new State_Hello_Func4_Called, - new State_Hello_Func79_Called, - NULL), "Test" "Hello" " Part2"); - - g_SHPtr->RemoveHookByID(helloHook4); - g_SHPtr->RemoveHookByID(helloHook79); - - g_HMAGPtr->ReleaseHookMan(helloHM_4); - g_HMAGPtr->ReleaseHookMan(helloHM_79); - - return true; - } -} - -#if !defined( _M_AMD64 ) && !defined( __amd64__ ) && !defined(__x86_64__) -bool TestHookManGen(std::string &error) -{ - GET_SHPTR(g_SHPtr); - GET_HMAG(g_HMAGPtr, g_SHPtr); - g_PLID = 1337; - - // 5 Global constructors (g_O111_*) - CHECK_STATES((&g_States, - new State_ObjOCtor_Called(111), - new State_ObjOCtor_Called(111), - new State_ObjOCtor_Called(111), - new State_ObjOCtor_Called(111), - new State_ObjOCtor_Called(111), - NULL), "GlobCtors"); - - if (!Tests1(error)) - return false; - if (!Tests2(error)) - return false; - if (!Tests3(error)) - return false; - if (!Tests4(error)) - return false; - if (!Tests5(error)) - return false; - - // Shutdown now! - // If we don't SH will auto-shutdown _after_ genc's destructor is called - // -> crash - - Test_CompleteShutdown(g_SHPtr); - - CHECK_COND(sizeof(PodRet1) == 1, "WTF!"); - CHECK_COND(sizeof(PodRet4) == 4, "WTF!"); - CHECK_COND(sizeof(PodRet8) == 8, "WTF!"); - CHECK_COND(sizeof(PodRet13) == 13, "WTF!"); - - return true; -} -#endif - -bool TestCPageAlloc(std::string &error) -{ - using namespace SourceHook; - - CPageAlloc alloc; - int i; - size_t ps = alloc.GetPageSize(); - - char *test1[8]; - - for (i = 0; i < 8; ++i) - test1[i] = (char*) alloc.Alloc(ps / 4); - - CHECK_COND(test1[1] == test1[0] + ps/4, "Part 1.1"); - CHECK_COND(test1[2] == test1[1] + ps/4, "Part 1.2"); - CHECK_COND(test1[3] == test1[2] + ps/4, "Part 1.3"); - - CHECK_COND(test1[5] == test1[4] + ps/4, "Part 1.4"); - CHECK_COND(test1[6] == test1[5] + ps/4, "Part 1.5"); - CHECK_COND(test1[7] == test1[6] + ps/4, "Part 1.6"); - - void *test2 = alloc.Alloc(ps * 3); - - alloc.SetRW(test2); - memset(test2, 0, ps * 3); // should not crash :) - alloc.SetRE(test2); - - alloc.Free(test2); - - // Dealloc a ps/4 block and place two ps/8 blocks into it - alloc.Free(test1[2]); - - char *test3[2]; - test3[0] = (char*) alloc.Alloc(ps / 8); - test3[1] = (char*) alloc.Alloc(ps / 8); - - CHECK_COND(test3[0] == test1[2], "Part 2.1"); - CHECK_COND(test3[1] == test1[2] + ps/8, "Part 2.2"); - - // Isolated - char *test4[8]; - for (i = 0; i < 8; ++i) - test4[i] = (char*) alloc.AllocIsolated(ps / 4); - - // -> The difference is at least one page - CHECK_COND(static_cast(std::abs(test4[1] - test4[0])) >= ps, "Part 3.1"); - CHECK_COND(static_cast(std::abs(test4[2] - test4[1])) >= ps, "Part 3.2"); - CHECK_COND(static_cast(std::abs(test4[3] - test4[2])) >= ps, "Part 3.3"); - - CHECK_COND(static_cast(std::abs(test4[5] - test4[4])) >= ps, "Part 3.4"); - CHECK_COND(static_cast(std::abs(test4[6] - test4[5])) >= ps, "Part 3.5"); - CHECK_COND(static_cast(std::abs(test4[7] - test4[6])) >= ps, "Part 3.6"); - - // Thus i can set everything except for test4[2] to RE and still write to test4[2] - - alloc.SetRW(test4[2]); - - alloc.SetRE(test4[0]); - alloc.SetRE(test4[1]); - alloc.SetRE(test4[3]); - alloc.SetRE(test4[4]); - alloc.SetRE(test4[5]); - alloc.SetRE(test4[6]); - alloc.SetRE(test4[7]); - - memset((void*)test4[2], 0, ps / 4); - - // alignement tests - CPageAlloc alloc1(1); - CPageAlloc alloc4(4); - CPageAlloc alloc16(16); - - void *last1 = alloc1.Alloc(1); - void *last4 = alloc4.Alloc(4); - void *last16 = alloc16.Alloc(16); - void *cur; - for (int i = 0; i < 20; ++i) - { - cur = alloc1.Alloc(1); - CHECK_COND(reinterpret_cast(cur) == reinterpret_cast(last1) + 1, "Part 4.1"); - last1 = cur; - - cur = alloc4.Alloc(1); - CHECK_COND(reinterpret_cast(cur) == reinterpret_cast(last4) + 4, "Part 4.2"); - last4 = cur; - - cur = alloc16.Alloc(1); - CHECK_COND(reinterpret_cast(cur) == reinterpret_cast(last16) + 16, "Part 4.3"); - last16 = cur; - } - - alloc16.Free(alloc16.Alloc(1)); - return true; -} diff --git a/utils/mmsource/core/sourcehook/test/testhookmangen.h b/utils/mmsource/core/sourcehook/test/testhookmangen.h deleted file mode 100644 index 984a69c8a..000000000 --- a/utils/mmsource/core/sourcehook/test/testhookmangen.h +++ /dev/null @@ -1,2192 +0,0 @@ -struct CAutoReleaseHookMan -{ - SourceHook::HookManagerPubFunc m_Ptr; - CAutoReleaseHookMan(SourceHook::HookManagerPubFunc ptr) : m_Ptr(ptr) - { - } - ~CAutoReleaseHookMan() - { - g_HMAGPtr->ReleaseHookMan(m_Ptr); - } -}; - -// Strip & -template struct StripRef -{ - typedef T type; -}; - -template struct StripRef -{ - typedef T type; -}; - -// Address of constructor/destructor -// (using wrappers) -template -class Ctor_Thunk -{ -public: - void NormalConstructor() - { - new(this) T; - } - - void CopyConstructor(const T &other) - { - new(this) T(other); - } - - void Destructor() - { - reinterpret_cast(this)->~T(); - } - - const T& AssignOp(const T &other) - { - return (*reinterpret_cast(this) = other); - } -}; - - -template -void *FindFuncAddr(T mfp) -{ - union - { - T a; - void *b; - } u; - u.a = mfp; - return u.b; -} - -// Reference carrier -template struct MyRefCarrier -{ - typedef T type; -}; - -template struct MyRefCarrier -{ - class type - { - T *m_StoredRef; - public: - type() : m_StoredRef(NULL) - { - } - type(T& ref) : m_StoredRef(&ref) - { - } - - T& operator= (T& ref) - { - m_StoredRef = &ref; - return ref; - } - - operator T& () const - { - return *m_StoredRef; - } - - bool operator== (const typename MyRefCarrier::type &other) - { - return m_StoredRef == other.m_StoredRef; - } - - friend std::ostream& operator <<(std::ostream &os,const typename MyRefCarrier::type &obj) - { - os << *obj.m_StoredRef; - return os; - } - }; -}; - -#if SH_COMP==SH_COMP_GCC -#define NO_OPTIMIZE __attribute__((noinline)) -#else -#define NO_OPTIMIZE -#endif - -// Return value maker -template -struct MakeRet -{ - static T Do(int a) - { - return a; - } -}; - -template -struct MakeRet< POD > -{ - static POD Do(int a) - { - POD x; - memset(reinterpret_cast(x.x), a, SIZE); - return x; - } -}; - -// Stores parameter status -template -bool EqualToMyFmtString(T sth) -{ - return false; -} - -bool EqualToMyFmtString(std::string &sth) -{ - if (sth == "Hello %s%d%s") - sth = "Hello BA1L!"; - return true; -} - - - - -template -struct ParamState0 -{ - - - bool operator==(const ParamState0 &other) - { - return true - - ; - } - ParamState0(...) - { - - } - - ParamState0 & operator() (int incrsteps) - { - - - - return *this; - } -}; - - -std::ostream& operator <<(std::ostream &os,const ParamState0<0> &obj) -{ - ; - return os; -} - - - -template -struct ParamState1 -{ - typename MyRefCarrier::type m_1; - - bool operator==(const ParamState1 &other) - { - return true - && m_1 == other.m_1 - ; - } - ParamState1(p1 a1, ...) : m_1(a1) - { - - EqualToMyFmtString(m_1); - - } - - ParamState1 & operator() (int incrsteps) - { - int i; - - for (i = 0; i < incrsteps; ++i) - Increment::type >::Incr(m_1); - - - return *this; - } -}; - -template -std::ostream& operator <<(std::ostream &os,const ParamState1<0, p1> &obj) -{ - os << obj.m_1; - return os; -} - - - -template -struct ParamState2 -{ - typename MyRefCarrier::type m_1; typename MyRefCarrier::type m_2; - - bool operator==(const ParamState2 &other) - { - return true - && m_2 == other.m_2 && m_2 == other.m_2 - ; - } - ParamState2(p1 a1, p2 a2, ...) : m_1(a1), m_2(a2) - { - - EqualToMyFmtString(m_1); - - EqualToMyFmtString(m_2); - - } - - ParamState2 & operator() (int incrsteps) - { - int i; - - for (i = 0; i < incrsteps; ++i) - Increment::type >::Incr(m_1); - - for (i = 0; i < incrsteps; ++i) - Increment::type >::Incr(m_2); - - - return *this; - } -}; - -template -std::ostream& operator <<(std::ostream &os,const ParamState2<0, p1, p2> &obj) -{ - os << obj.m_1<< obj.m_2; - return os; -} - - - -template -struct ParamState3 -{ - typename MyRefCarrier::type m_1; typename MyRefCarrier::type m_2; typename MyRefCarrier::type m_3; - - bool operator==(const ParamState3 &other) - { - return true - && m_3 == other.m_3 && m_3 == other.m_3 && m_3 == other.m_3 - ; - } - ParamState3(p1 a1, p2 a2, p3 a3, ...) : m_1(a1), m_2(a2), m_3(a3) - { - - EqualToMyFmtString(m_1); - - EqualToMyFmtString(m_2); - - EqualToMyFmtString(m_3); - - } - - ParamState3 & operator() (int incrsteps) - { - int i; - - for (i = 0; i < incrsteps; ++i) - Increment::type >::Incr(m_1); - - for (i = 0; i < incrsteps; ++i) - Increment::type >::Incr(m_2); - - for (i = 0; i < incrsteps; ++i) - Increment::type >::Incr(m_3); - - - return *this; - } -}; - -template -std::ostream& operator <<(std::ostream &os,const ParamState3<0, p1, p2, p3> &obj) -{ - os << obj.m_1<< obj.m_2<< obj.m_3; - return os; -} - - - -template -struct ParamState4 -{ - typename MyRefCarrier::type m_1; typename MyRefCarrier::type m_2; typename MyRefCarrier::type m_3; typename MyRefCarrier::type m_4; - - bool operator==(const ParamState4 &other) - { - return true - && m_4 == other.m_4 && m_4 == other.m_4 && m_4 == other.m_4 && m_4 == other.m_4 - ; - } - ParamState4(p1 a1, p2 a2, p3 a3, p4 a4, ...) : m_1(a1), m_2(a2), m_3(a3), m_4(a4) - { - - EqualToMyFmtString(m_1); - - EqualToMyFmtString(m_2); - - EqualToMyFmtString(m_3); - - EqualToMyFmtString(m_4); - - } - - ParamState4 & operator() (int incrsteps) - { - int i; - - for (i = 0; i < incrsteps; ++i) - Increment::type >::Incr(m_1); - - for (i = 0; i < incrsteps; ++i) - Increment::type >::Incr(m_2); - - for (i = 0; i < incrsteps; ++i) - Increment::type >::Incr(m_3); - - for (i = 0; i < incrsteps; ++i) - Increment::type >::Incr(m_4); - - - return *this; - } -}; - -template -std::ostream& operator <<(std::ostream &os,const ParamState4<0, p1, p2, p3, p4> &obj) -{ - os << obj.m_1<< obj.m_2<< obj.m_3<< obj.m_4; - return os; -} - - - -template -struct ParamState5 -{ - typename MyRefCarrier::type m_1; typename MyRefCarrier::type m_2; typename MyRefCarrier::type m_3; typename MyRefCarrier::type m_4; typename MyRefCarrier::type m_5; - - bool operator==(const ParamState5 &other) - { - return true - && m_5 == other.m_5 && m_5 == other.m_5 && m_5 == other.m_5 && m_5 == other.m_5 && m_5 == other.m_5 - ; - } - ParamState5(p1 a1, p2 a2, p3 a3, p4 a4, p5 a5, ...) : m_1(a1), m_2(a2), m_3(a3), m_4(a4), m_5(a5) - { - - EqualToMyFmtString(m_1); - - EqualToMyFmtString(m_2); - - EqualToMyFmtString(m_3); - - EqualToMyFmtString(m_4); - - EqualToMyFmtString(m_5); - - } - - ParamState5 & operator() (int incrsteps) - { - int i; - - for (i = 0; i < incrsteps; ++i) - Increment::type >::Incr(m_1); - - for (i = 0; i < incrsteps; ++i) - Increment::type >::Incr(m_2); - - for (i = 0; i < incrsteps; ++i) - Increment::type >::Incr(m_3); - - for (i = 0; i < incrsteps; ++i) - Increment::type >::Incr(m_4); - - for (i = 0; i < incrsteps; ++i) - Increment::type >::Incr(m_5); - - - return *this; - } -}; - -template -std::ostream& operator <<(std::ostream &os,const ParamState5<0, p1, p2, p3, p4, p5> &obj) -{ - os << obj.m_1<< obj.m_2<< obj.m_3<< obj.m_4<< obj.m_5; - return os; -} - - - -template -struct ParamState6 -{ - typename MyRefCarrier::type m_1; typename MyRefCarrier::type m_2; typename MyRefCarrier::type m_3; typename MyRefCarrier::type m_4; typename MyRefCarrier::type m_5; typename MyRefCarrier::type m_6; - - bool operator==(const ParamState6 &other) - { - return true - && m_6 == other.m_6 && m_6 == other.m_6 && m_6 == other.m_6 && m_6 == other.m_6 && m_6 == other.m_6 && m_6 == other.m_6 - ; - } - ParamState6(p1 a1, p2 a2, p3 a3, p4 a4, p5 a5, p6 a6, ...) : m_1(a1), m_2(a2), m_3(a3), m_4(a4), m_5(a5), m_6(a6) - { - - EqualToMyFmtString(m_1); - - EqualToMyFmtString(m_2); - - EqualToMyFmtString(m_3); - - EqualToMyFmtString(m_4); - - EqualToMyFmtString(m_5); - - EqualToMyFmtString(m_6); - - } - - ParamState6 & operator() (int incrsteps) - { - int i; - - for (i = 0; i < incrsteps; ++i) - Increment::type >::Incr(m_1); - - for (i = 0; i < incrsteps; ++i) - Increment::type >::Incr(m_2); - - for (i = 0; i < incrsteps; ++i) - Increment::type >::Incr(m_3); - - for (i = 0; i < incrsteps; ++i) - Increment::type >::Incr(m_4); - - for (i = 0; i < incrsteps; ++i) - Increment::type >::Incr(m_5); - - for (i = 0; i < incrsteps; ++i) - Increment::type >::Incr(m_6); - - - return *this; - } -}; - -template -std::ostream& operator <<(std::ostream &os,const ParamState6<0, p1, p2, p3, p4, p5, p6> &obj) -{ - os << obj.m_1<< obj.m_2<< obj.m_3<< obj.m_4<< obj.m_5<< obj.m_6; - return os; -} - - - -#define CAT2(a, b) a##b -#define CAT3(a, b, c) a##b##c -#define CAT4(a, b, c, d) a##b##c##d - -// hook1: pre ignore -// hook2: pre supercede -// hook3: post ignore -// hook4: post supercede - - - - -#define THGM_MAKE_TEST0_void(id) \ - struct TestClass##id; \ - typedef ParamState0<0 > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual void Func() \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Func##id(this, ParamState_m##id())); \ - g_Inside_LeafFunc = false; \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual void Call() \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id())); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - \ - RETURN_META_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, &TestClass##id::Func, ()); \ - } \ - else \ - RETURN_META((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall); - - -#define THGM_MAKE_TEST0(id, ret_type) \ - struct TestClass##id; \ - typedef ret_type RetType##id; \ - typedef ParamState0<0 > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual ret_type Func() \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Func##id(this, ParamState_m##id())); \ - g_Inside_LeafFunc = false; \ - \ - return MakeRet< ret_type >::Do(0); \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual ret_type Call() \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id())); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - \ - RETURN_META_VALUE_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber), &TestClass##id::Func, ()); \ - } \ - else \ - RETURN_META_VALUE((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber)); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall); - -#define THGM_MAKE_TEST0_vafmt_void(id) \ - struct TestClass##id; \ - typedef ParamState1<0, std::string > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual void Func(const char *fmt, ...) \ - { \ - g_Inside_LeafFunc = true; \ - \ - char buf[9999]; \ - va_list ap; \ - va_start(ap, fmt); \ - vsnprintf(buf, 9998, fmt, ap); \ - buf[9998] = 0; \ - va_end(ap); \ - \ - ADD_STATE(State_Func##id(this, ParamState_m##id(std::string(buf)))); \ - g_Inside_LeafFunc = false; \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual void Call(const char *buf) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(buf))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - \ - RETURN_META_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, &TestClass##id::Func, ("%s!", buf)); \ - } \ - else \ - RETURN_META((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall | SourceHook::ProtoInfo::CallConv_HasVafmt); - -#define THGM_MAKE_TEST0_vafmt(id, ret_type) \ - struct TestClass##id; \ - typedef ret_type RetType##id; \ - typedef ParamState1<0, std::string > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual ret_type Func(const char *fmt, ...) \ - { \ - g_Inside_LeafFunc = true; \ - \ - char buf[9999]; \ - va_list ap; \ - va_start(ap, fmt); \ - vsnprintf(buf, 9998, fmt, ap); \ - buf[9998] = 0; \ - va_end(ap); \ - \ - ADD_STATE(State_Func##id(this, ParamState_m##id(std::string(buf)))); \ - \ - return MakeRet< ret_type >::Do(0); \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual ret_type Call(const char *buf) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(buf))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - \ - RETURN_META_VALUE_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber), &TestClass##id::Func, ("%s!", buf)); \ - } \ - else \ - RETURN_META_VALUE((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber)); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall | SourceHook::ProtoInfo::CallConv_HasVafmt); - -#define THGM_SETUP_PI0(id) \ - void setuppi_##id() \ - { \ - \ - } - - - -#define THGM_MAKE_TEST1_void(id, param1) \ - struct TestClass##id; \ - typedef ParamState1<0, param1 > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual void Func(param1 p1) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1))); \ - g_Inside_LeafFunc = false; \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual void Call(param1 p1) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1); \ - RETURN_META_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, &TestClass##id::Func, (p1)); \ - } \ - else \ - RETURN_META((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall); - - -#define THGM_MAKE_TEST1(id, ret_type, param1) \ - struct TestClass##id; \ - typedef ret_type RetType##id; \ - typedef ParamState1<0, param1 > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual ret_type Func(param1 p1) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1))); \ - g_Inside_LeafFunc = false; \ - \ - return MakeRet< ret_type >::Do(0); \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual ret_type Call(param1 p1) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1); \ - RETURN_META_VALUE_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber), &TestClass##id::Func, (p1)); \ - } \ - else \ - RETURN_META_VALUE((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber)); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall); - -#define THGM_MAKE_TEST1_vafmt_void(id, param1) \ - struct TestClass##id; \ - typedef ParamState2<0, param1, std::string > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual void Func(param1 p1, const char *fmt, ...) \ - { \ - g_Inside_LeafFunc = true; \ - \ - char buf[9999]; \ - va_list ap; \ - va_start(ap, fmt); \ - vsnprintf(buf, 9998, fmt, ap); \ - buf[9998] = 0; \ - va_end(ap); \ - \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1, std::string(buf)))); \ - g_Inside_LeafFunc = false; \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual void Call(param1 p1, const char *buf) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1, buf))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1); \ - RETURN_META_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, &TestClass##id::Func, (p1, "%s!", buf)); \ - } \ - else \ - RETURN_META((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall | SourceHook::ProtoInfo::CallConv_HasVafmt); - -#define THGM_MAKE_TEST1_vafmt(id, ret_type, param1) \ - struct TestClass##id; \ - typedef ret_type RetType##id; \ - typedef ParamState2<0, param1, std::string > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual ret_type Func(param1 p1, const char *fmt, ...) \ - { \ - g_Inside_LeafFunc = true; \ - \ - char buf[9999]; \ - va_list ap; \ - va_start(ap, fmt); \ - vsnprintf(buf, 9998, fmt, ap); \ - buf[9998] = 0; \ - va_end(ap); \ - \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1, std::string(buf)))); \ - \ - return MakeRet< ret_type >::Do(0); \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual ret_type Call(param1 p1, const char *buf) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1, buf))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1); \ - RETURN_META_VALUE_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber), &TestClass##id::Func, (p1, "%s!", buf)); \ - } \ - else \ - RETURN_META_VALUE((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber)); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall | SourceHook::ProtoInfo::CallConv_HasVafmt); - -#define THGM_SETUP_PI1(id, p1_type, p1_passtype, p1_flags) \ - void setuppi_##id() \ - { \ - \ - protoinfo_##id.AddParam(sizeof(p1_type), p1_passtype, p1_flags, \ - (p1_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (p1_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (p1_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (p1_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - \ - } - - - -#define THGM_MAKE_TEST2_void(id, param1, param2) \ - struct TestClass##id; \ - typedef ParamState2<0, param1, param2 > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual void Func(param1 p1, param2 p2) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1, p2))); \ - g_Inside_LeafFunc = false; \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual void Call(param1 p1, param2 p2) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1, p2))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1);Increment::type>::Incr(p2); \ - RETURN_META_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, &TestClass##id::Func, (p1, p2)); \ - } \ - else \ - RETURN_META((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall); - - -#define THGM_MAKE_TEST2(id, ret_type, param1, param2) \ - struct TestClass##id; \ - typedef ret_type RetType##id; \ - typedef ParamState2<0, param1, param2 > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual ret_type Func(param1 p1, param2 p2) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1, p2))); \ - g_Inside_LeafFunc = false; \ - \ - return MakeRet< ret_type >::Do(0); \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual ret_type Call(param1 p1, param2 p2) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1, p2))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1);Increment::type>::Incr(p2); \ - RETURN_META_VALUE_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber), &TestClass##id::Func, (p1, p2)); \ - } \ - else \ - RETURN_META_VALUE((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber)); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall); - -#define THGM_MAKE_TEST2_vafmt_void(id, param1, param2) \ - struct TestClass##id; \ - typedef ParamState3<0, param1, param2, std::string > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual void Func(param1 p1, param2 p2, const char *fmt, ...) \ - { \ - g_Inside_LeafFunc = true; \ - \ - char buf[9999]; \ - va_list ap; \ - va_start(ap, fmt); \ - vsnprintf(buf, 9998, fmt, ap); \ - buf[9998] = 0; \ - va_end(ap); \ - \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1, p2, std::string(buf)))); \ - g_Inside_LeafFunc = false; \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual void Call(param1 p1, param2 p2, const char *buf) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1, p2, buf))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1);Increment::type>::Incr(p2); \ - RETURN_META_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, &TestClass##id::Func, (p1, p2, "%s!", buf)); \ - } \ - else \ - RETURN_META((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall | SourceHook::ProtoInfo::CallConv_HasVafmt); - -#define THGM_MAKE_TEST2_vafmt(id, ret_type, param1, param2) \ - struct TestClass##id; \ - typedef ret_type RetType##id; \ - typedef ParamState3<0, param1, param2, std::string > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual ret_type Func(param1 p1, param2 p2, const char *fmt, ...) \ - { \ - g_Inside_LeafFunc = true; \ - \ - char buf[9999]; \ - va_list ap; \ - va_start(ap, fmt); \ - vsnprintf(buf, 9998, fmt, ap); \ - buf[9998] = 0; \ - va_end(ap); \ - \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1, p2, std::string(buf)))); \ - \ - return MakeRet< ret_type >::Do(0); \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual ret_type Call(param1 p1, param2 p2, const char *buf) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1, p2, buf))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1);Increment::type>::Incr(p2); \ - RETURN_META_VALUE_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber), &TestClass##id::Func, (p1, p2, "%s!", buf)); \ - } \ - else \ - RETURN_META_VALUE((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber)); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall | SourceHook::ProtoInfo::CallConv_HasVafmt); - -#define THGM_SETUP_PI2(id, p1_type, p1_passtype, p1_flags, p2_type, p2_passtype, p2_flags) \ - void setuppi_##id() \ - { \ - \ - protoinfo_##id.AddParam(sizeof(p1_type), p1_passtype, p1_flags, \ - (p1_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (p1_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (p1_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (p1_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - \ - protoinfo_##id.AddParam(sizeof(p2_type), p2_passtype, p2_flags, \ - (p2_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (p2_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (p2_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (p2_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - \ - } - - - -#define THGM_MAKE_TEST3_void(id, param1, param2, param3) \ - struct TestClass##id; \ - typedef ParamState3<0, param1, param2, param3 > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual void Func(param1 p1, param2 p2, param3 p3) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1, p2, p3))); \ - g_Inside_LeafFunc = false; \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual void Call(param1 p1, param2 p2, param3 p3) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1, p2, p3))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1);Increment::type>::Incr(p2);Increment::type>::Incr(p3); \ - RETURN_META_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, &TestClass##id::Func, (p1, p2, p3)); \ - } \ - else \ - RETURN_META((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall); - - -#define THGM_MAKE_TEST3(id, ret_type, param1, param2, param3) \ - struct TestClass##id; \ - typedef ret_type RetType##id; \ - typedef ParamState3<0, param1, param2, param3 > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual ret_type Func(param1 p1, param2 p2, param3 p3) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1, p2, p3))); \ - g_Inside_LeafFunc = false; \ - \ - return MakeRet< ret_type >::Do(0); \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual ret_type Call(param1 p1, param2 p2, param3 p3) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1, p2, p3))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1);Increment::type>::Incr(p2);Increment::type>::Incr(p3); \ - RETURN_META_VALUE_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber), &TestClass##id::Func, (p1, p2, p3)); \ - } \ - else \ - RETURN_META_VALUE((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber)); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall); - -#define THGM_MAKE_TEST3_vafmt_void(id, param1, param2, param3) \ - struct TestClass##id; \ - typedef ParamState4<0, param1, param2, param3, std::string > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual void Func(param1 p1, param2 p2, param3 p3, const char *fmt, ...) \ - { \ - g_Inside_LeafFunc = true; \ - \ - char buf[9999]; \ - va_list ap; \ - va_start(ap, fmt); \ - vsnprintf(buf, 9998, fmt, ap); \ - buf[9998] = 0; \ - va_end(ap); \ - \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1, p2, p3, std::string(buf)))); \ - g_Inside_LeafFunc = false; \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual void Call(param1 p1, param2 p2, param3 p3, const char *buf) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1, p2, p3, buf))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1);Increment::type>::Incr(p2);Increment::type>::Incr(p3); \ - RETURN_META_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, &TestClass##id::Func, (p1, p2, p3, "%s!", buf)); \ - } \ - else \ - RETURN_META((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall | SourceHook::ProtoInfo::CallConv_HasVafmt); - -#define THGM_MAKE_TEST3_vafmt(id, ret_type, param1, param2, param3) \ - struct TestClass##id; \ - typedef ret_type RetType##id; \ - typedef ParamState4<0, param1, param2, param3, std::string > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual ret_type Func(param1 p1, param2 p2, param3 p3, const char *fmt, ...) \ - { \ - g_Inside_LeafFunc = true; \ - \ - char buf[9999]; \ - va_list ap; \ - va_start(ap, fmt); \ - vsnprintf(buf, 9998, fmt, ap); \ - buf[9998] = 0; \ - va_end(ap); \ - \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1, p2, p3, std::string(buf)))); \ - \ - return MakeRet< ret_type >::Do(0); \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual ret_type Call(param1 p1, param2 p2, param3 p3, const char *buf) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1, p2, p3, buf))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1);Increment::type>::Incr(p2);Increment::type>::Incr(p3); \ - RETURN_META_VALUE_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber), &TestClass##id::Func, (p1, p2, p3, "%s!", buf)); \ - } \ - else \ - RETURN_META_VALUE((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber)); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall | SourceHook::ProtoInfo::CallConv_HasVafmt); - -#define THGM_SETUP_PI3(id, p1_type, p1_passtype, p1_flags, p2_type, p2_passtype, p2_flags, p3_type, p3_passtype, p3_flags) \ - void setuppi_##id() \ - { \ - \ - protoinfo_##id.AddParam(sizeof(p1_type), p1_passtype, p1_flags, \ - (p1_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (p1_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (p1_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (p1_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - \ - protoinfo_##id.AddParam(sizeof(p2_type), p2_passtype, p2_flags, \ - (p2_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (p2_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (p2_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (p2_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - \ - protoinfo_##id.AddParam(sizeof(p3_type), p3_passtype, p3_flags, \ - (p3_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (p3_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (p3_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (p3_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - \ - } - - - -#define THGM_MAKE_TEST4_void(id, param1, param2, param3, param4) \ - struct TestClass##id; \ - typedef ParamState4<0, param1, param2, param3, param4 > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1, p2, p3, p4))); \ - g_Inside_LeafFunc = false; \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual void Call(param1 p1, param2 p2, param3 p3, param4 p4) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1, p2, p3, p4))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1);Increment::type>::Incr(p2);Increment::type>::Incr(p3);Increment::type>::Incr(p4); \ - RETURN_META_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, &TestClass##id::Func, (p1, p2, p3, p4)); \ - } \ - else \ - RETURN_META((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall); - - -#define THGM_MAKE_TEST4(id, ret_type, param1, param2, param3, param4) \ - struct TestClass##id; \ - typedef ret_type RetType##id; \ - typedef ParamState4<0, param1, param2, param3, param4 > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual ret_type Func(param1 p1, param2 p2, param3 p3, param4 p4) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1, p2, p3, p4))); \ - g_Inside_LeafFunc = false; \ - \ - return MakeRet< ret_type >::Do(0); \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual ret_type Call(param1 p1, param2 p2, param3 p3, param4 p4) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1, p2, p3, p4))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1);Increment::type>::Incr(p2);Increment::type>::Incr(p3);Increment::type>::Incr(p4); \ - RETURN_META_VALUE_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber), &TestClass##id::Func, (p1, p2, p3, p4)); \ - } \ - else \ - RETURN_META_VALUE((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber)); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall); - -#define THGM_MAKE_TEST4_vafmt_void(id, param1, param2, param3, param4) \ - struct TestClass##id; \ - typedef ParamState5<0, param1, param2, param3, param4, std::string > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, const char *fmt, ...) \ - { \ - g_Inside_LeafFunc = true; \ - \ - char buf[9999]; \ - va_list ap; \ - va_start(ap, fmt); \ - vsnprintf(buf, 9998, fmt, ap); \ - buf[9998] = 0; \ - va_end(ap); \ - \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1, p2, p3, p4, std::string(buf)))); \ - g_Inside_LeafFunc = false; \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual void Call(param1 p1, param2 p2, param3 p3, param4 p4, const char *buf) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1, p2, p3, p4, buf))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1);Increment::type>::Incr(p2);Increment::type>::Incr(p3);Increment::type>::Incr(p4); \ - RETURN_META_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, &TestClass##id::Func, (p1, p2, p3, p4, "%s!", buf)); \ - } \ - else \ - RETURN_META((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall | SourceHook::ProtoInfo::CallConv_HasVafmt); - -#define THGM_MAKE_TEST4_vafmt(id, ret_type, param1, param2, param3, param4) \ - struct TestClass##id; \ - typedef ret_type RetType##id; \ - typedef ParamState5<0, param1, param2, param3, param4, std::string > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual ret_type Func(param1 p1, param2 p2, param3 p3, param4 p4, const char *fmt, ...) \ - { \ - g_Inside_LeafFunc = true; \ - \ - char buf[9999]; \ - va_list ap; \ - va_start(ap, fmt); \ - vsnprintf(buf, 9998, fmt, ap); \ - buf[9998] = 0; \ - va_end(ap); \ - \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1, p2, p3, p4, std::string(buf)))); \ - \ - return MakeRet< ret_type >::Do(0); \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual ret_type Call(param1 p1, param2 p2, param3 p3, param4 p4, const char *buf) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1, p2, p3, p4, buf))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1);Increment::type>::Incr(p2);Increment::type>::Incr(p3);Increment::type>::Incr(p4); \ - RETURN_META_VALUE_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber), &TestClass##id::Func, (p1, p2, p3, p4, "%s!", buf)); \ - } \ - else \ - RETURN_META_VALUE((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber)); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall | SourceHook::ProtoInfo::CallConv_HasVafmt); - -#define THGM_SETUP_PI4(id, p1_type, p1_passtype, p1_flags, p2_type, p2_passtype, p2_flags, p3_type, p3_passtype, p3_flags, p4_type, p4_passtype, p4_flags) \ - void setuppi_##id() \ - { \ - \ - protoinfo_##id.AddParam(sizeof(p1_type), p1_passtype, p1_flags, \ - (p1_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (p1_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (p1_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (p1_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - \ - protoinfo_##id.AddParam(sizeof(p2_type), p2_passtype, p2_flags, \ - (p2_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (p2_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (p2_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (p2_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - \ - protoinfo_##id.AddParam(sizeof(p3_type), p3_passtype, p3_flags, \ - (p3_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (p3_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (p3_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (p3_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - \ - protoinfo_##id.AddParam(sizeof(p4_type), p4_passtype, p4_flags, \ - (p4_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (p4_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (p4_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (p4_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - \ - } - - - -#define THGM_MAKE_TEST5_void(id, param1, param2, param3, param4, param5) \ - struct TestClass##id; \ - typedef ParamState5<0, param1, param2, param3, param4, param5 > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1, p2, p3, p4, p5))); \ - g_Inside_LeafFunc = false; \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual void Call(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1, p2, p3, p4, p5))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1);Increment::type>::Incr(p2);Increment::type>::Incr(p3);Increment::type>::Incr(p4);Increment::type>::Incr(p5); \ - RETURN_META_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, &TestClass##id::Func, (p1, p2, p3, p4, p5)); \ - } \ - else \ - RETURN_META((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall); - - -#define THGM_MAKE_TEST5(id, ret_type, param1, param2, param3, param4, param5) \ - struct TestClass##id; \ - typedef ret_type RetType##id; \ - typedef ParamState5<0, param1, param2, param3, param4, param5 > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual ret_type Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1, p2, p3, p4, p5))); \ - g_Inside_LeafFunc = false; \ - \ - return MakeRet< ret_type >::Do(0); \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual ret_type Call(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1, p2, p3, p4, p5))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1);Increment::type>::Incr(p2);Increment::type>::Incr(p3);Increment::type>::Incr(p4);Increment::type>::Incr(p5); \ - RETURN_META_VALUE_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber), &TestClass##id::Func, (p1, p2, p3, p4, p5)); \ - } \ - else \ - RETURN_META_VALUE((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber)); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall); - -#define THGM_MAKE_TEST5_vafmt_void(id, param1, param2, param3, param4, param5) \ - struct TestClass##id; \ - typedef ParamState6<0, param1, param2, param3, param4, param5, std::string > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, const char *fmt, ...) \ - { \ - g_Inside_LeafFunc = true; \ - \ - char buf[9999]; \ - va_list ap; \ - va_start(ap, fmt); \ - vsnprintf(buf, 9998, fmt, ap); \ - buf[9998] = 0; \ - va_end(ap); \ - \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1, p2, p3, p4, p5, std::string(buf)))); \ - g_Inside_LeafFunc = false; \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual void Call(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, const char *buf) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1, p2, p3, p4, p5, buf))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1);Increment::type>::Incr(p2);Increment::type>::Incr(p3);Increment::type>::Incr(p4);Increment::type>::Incr(p5); \ - RETURN_META_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, &TestClass##id::Func, (p1, p2, p3, p4, p5, "%s!", buf)); \ - } \ - else \ - RETURN_META((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall | SourceHook::ProtoInfo::CallConv_HasVafmt); - -#define THGM_MAKE_TEST5_vafmt(id, ret_type, param1, param2, param3, param4, param5) \ - struct TestClass##id; \ - typedef ret_type RetType##id; \ - typedef ParamState6<0, param1, param2, param3, param4, param5, std::string > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual ret_type Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, const char *fmt, ...) \ - { \ - g_Inside_LeafFunc = true; \ - \ - char buf[9999]; \ - va_list ap; \ - va_start(ap, fmt); \ - vsnprintf(buf, 9998, fmt, ap); \ - buf[9998] = 0; \ - va_end(ap); \ - \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1, p2, p3, p4, p5, std::string(buf)))); \ - \ - return MakeRet< ret_type >::Do(0); \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual ret_type Call(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, const char *buf) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1, p2, p3, p4, p5, buf))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1);Increment::type>::Incr(p2);Increment::type>::Incr(p3);Increment::type>::Incr(p4);Increment::type>::Incr(p5); \ - RETURN_META_VALUE_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber), &TestClass##id::Func, (p1, p2, p3, p4, p5, "%s!", buf)); \ - } \ - else \ - RETURN_META_VALUE((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber)); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall | SourceHook::ProtoInfo::CallConv_HasVafmt); - -#define THGM_SETUP_PI5(id, p1_type, p1_passtype, p1_flags, p2_type, p2_passtype, p2_flags, p3_type, p3_passtype, p3_flags, p4_type, p4_passtype, p4_flags, p5_type, p5_passtype, p5_flags) \ - void setuppi_##id() \ - { \ - \ - protoinfo_##id.AddParam(sizeof(p1_type), p1_passtype, p1_flags, \ - (p1_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (p1_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (p1_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (p1_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - \ - protoinfo_##id.AddParam(sizeof(p2_type), p2_passtype, p2_flags, \ - (p2_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (p2_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (p2_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (p2_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - \ - protoinfo_##id.AddParam(sizeof(p3_type), p3_passtype, p3_flags, \ - (p3_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (p3_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (p3_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (p3_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - \ - protoinfo_##id.AddParam(sizeof(p4_type), p4_passtype, p4_flags, \ - (p4_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (p4_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (p4_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (p4_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - \ - protoinfo_##id.AddParam(sizeof(p5_type), p5_passtype, p5_flags, \ - (p5_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (p5_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (p5_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (p5_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - \ - } - - - -#define THGM_MAKE_TEST6_void(id, param1, param2, param3, param4, param5, param6) \ - struct TestClass##id; \ - typedef ParamState6<0, param1, param2, param3, param4, param5, param6 > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1, p2, p3, p4, p5, p6))); \ - g_Inside_LeafFunc = false; \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual void Call(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1, p2, p3, p4, p5, p6))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1);Increment::type>::Incr(p2);Increment::type>::Incr(p3);Increment::type>::Incr(p4);Increment::type>::Incr(p5);Increment::type>::Incr(p6); \ - RETURN_META_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, &TestClass##id::Func, (p1, p2, p3, p4, p5, p6)); \ - } \ - else \ - RETURN_META((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall); - - -#define THGM_MAKE_TEST6(id, ret_type, param1, param2, param3, param4, param5, param6) \ - struct TestClass##id; \ - typedef ret_type RetType##id; \ - typedef ParamState6<0, param1, param2, param3, param4, param5, param6 > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual ret_type Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1, p2, p3, p4, p5, p6))); \ - g_Inside_LeafFunc = false; \ - \ - return MakeRet< ret_type >::Do(0); \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual ret_type Call(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1, p2, p3, p4, p5, p6))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1);Increment::type>::Incr(p2);Increment::type>::Incr(p3);Increment::type>::Incr(p4);Increment::type>::Incr(p5);Increment::type>::Incr(p6); \ - RETURN_META_VALUE_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber), &TestClass##id::Func, (p1, p2, p3, p4, p5, p6)); \ - } \ - else \ - RETURN_META_VALUE((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber)); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall); - -#define THGM_MAKE_TEST6_vafmt_void(id, param1, param2, param3, param4, param5, param6) \ - struct TestClass##id; \ - typedef ParamState7<0, param1, param2, param3, param4, param5, param6, std::string > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual void Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, const char *fmt, ...) \ - { \ - g_Inside_LeafFunc = true; \ - \ - char buf[9999]; \ - va_list ap; \ - va_start(ap, fmt); \ - vsnprintf(buf, 9998, fmt, ap); \ - buf[9998] = 0; \ - va_end(ap); \ - \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1, p2, p3, p4, p5, p6, std::string(buf)))); \ - g_Inside_LeafFunc = false; \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual void Call(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, const char *buf) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1, p2, p3, p4, p5, p6, buf))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1);Increment::type>::Incr(p2);Increment::type>::Incr(p3);Increment::type>::Incr(p4);Increment::type>::Incr(p5);Increment::type>::Incr(p6); \ - RETURN_META_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, &TestClass##id::Func, (p1, p2, p3, p4, p5, p6, "%s!", buf)); \ - } \ - else \ - RETURN_META((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall | SourceHook::ProtoInfo::CallConv_HasVafmt); - -#define THGM_MAKE_TEST6_vafmt(id, ret_type, param1, param2, param3, param4, param5, param6) \ - struct TestClass##id; \ - typedef ret_type RetType##id; \ - typedef ParamState7<0, param1, param2, param3, param4, param5, param6, std::string > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual ret_type Func(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, const char *fmt, ...) \ - { \ - g_Inside_LeafFunc = true; \ - \ - char buf[9999]; \ - va_list ap; \ - va_start(ap, fmt); \ - vsnprintf(buf, 9998, fmt, ap); \ - buf[9998] = 0; \ - va_end(ap); \ - \ - ADD_STATE(State_Func##id(this, ParamState_m##id(p1, p2, p3, p4, p5, p6, std::string(buf)))); \ - \ - return MakeRet< ret_type >::Do(0); \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual ret_type Call(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, const char *buf) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(p1, p2, p3, p4, p5, p6, buf))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - Increment::type>::Incr(p1);Increment::type>::Incr(p2);Increment::type>::Incr(p3);Increment::type>::Incr(p4);Increment::type>::Incr(p5);Increment::type>::Incr(p6); \ - RETURN_META_VALUE_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber), &TestClass##id::Func, (p1, p2, p3, p4, p5, p6, "%s!", buf)); \ - } \ - else \ - RETURN_META_VALUE((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber)); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall | SourceHook::ProtoInfo::CallConv_HasVafmt); - -#define THGM_SETUP_PI6(id, p1_type, p1_passtype, p1_flags, p2_type, p2_passtype, p2_flags, p3_type, p3_passtype, p3_flags, p4_type, p4_passtype, p4_flags, p5_type, p5_passtype, p5_flags, p6_type, p6_passtype, p6_flags) \ - void setuppi_##id() \ - { \ - \ - protoinfo_##id.AddParam(sizeof(p1_type), p1_passtype, p1_flags, \ - (p1_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (p1_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (p1_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (p1_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - \ - protoinfo_##id.AddParam(sizeof(p2_type), p2_passtype, p2_flags, \ - (p2_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (p2_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (p2_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (p2_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - \ - protoinfo_##id.AddParam(sizeof(p3_type), p3_passtype, p3_flags, \ - (p3_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (p3_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (p3_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (p3_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - \ - protoinfo_##id.AddParam(sizeof(p4_type), p4_passtype, p4_flags, \ - (p4_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (p4_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (p4_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (p4_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - \ - protoinfo_##id.AddParam(sizeof(p5_type), p5_passtype, p5_flags, \ - (p5_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (p5_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (p5_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (p5_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - \ - protoinfo_##id.AddParam(sizeof(p6_type), p6_passtype, p6_flags, \ - (p6_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (p6_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (p6_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (p6_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - \ - } - - - -#define THGM_SETUP_RI(id, ret_type, ret_passtype, ret_flags) \ - void setupri_##id() \ - { \ - protoinfo_##id.SetReturnType(sizeof(ret_type), ret_passtype, ret_flags, \ - (ret_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (ret_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (ret_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (ret_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - } - -#define THGM_ADD_HOOK(id, num) \ - CAT4(hook, num, _, id) = g_SHPtr->AddHook(g_PLID, SourceHook::ISourceHook::Hook_Normal, reinterpret_cast(pTest##id), \ - 0, myhookman##id, PtrBufPtr(new TestClass##id::Delegate(num)), num >= 3); - -#define THGM_REMOVE_HOOK(id, num) \ - g_SHPtr->RemoveHookByID(CAT4(hook, num, _, id)); - -#define THGM_CALLS_void(id, call_params) \ - pTest##id->Func call_params; \ - SH_CALL(pTest##id, &TestClass##id::Func) call_params; - -#define THGM_DO_TEST_void(id, call_params) \ - setuppi_##id(); \ - SourceHook::HookManagerPubFunc myhookman##id = g_HMAGPtr->MakeHookMan(protoinfo_##id, 0, 0); \ - CAutoReleaseHookMan arhm_##id(myhookman##id); \ - int hook1_##id, hook2_##id, hook3_##id, hook4_##id; \ - \ - TestClass##id::ms_DoRecall = false; \ - TestClass##id *pTest##id = new TestClass##id; \ - CAutoPtrDestruction apd##id(pTest##id); \ - \ - /* no hooks - no hooks */ \ - PtrBuf_Clear(); \ - THGM_CALLS_void(id, call_params); \ - CHECK_STATES((&g_States, \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - NULL), "Test" #id " Part1"); \ - \ - /* hook1 - hook3 */ \ - PtrBuf_Clear(); \ - THGM_ADD_HOOK(id, 1); \ - THGM_ADD_HOOK(id, 3); \ - THGM_CALLS_void(id, call_params); \ - CHECK_STATES((&g_States, \ - new State_Deleg_##id(1, pTest##id, 0, ParamState_m##id call_params), \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - new State_Deleg_##id(3, pTest##id, 1, ParamState_m##id call_params), \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - NULL), "Test" #id " Part4"); \ - THGM_REMOVE_HOOK(id, 1); \ - THGM_REMOVE_HOOK(id, 3); \ - \ - /* hook1, hook2 - hook3 */ \ - PtrBuf_Clear(); \ - THGM_ADD_HOOK(id, 1); \ - THGM_ADD_HOOK(id, 2); \ - THGM_ADD_HOOK(id, 3); \ - THGM_CALLS_void(id, call_params); \ - CHECK_STATES((&g_States, \ - new State_Deleg_##id(1, pTest##id, 0, ParamState_m##id call_params), \ - new State_Deleg_##id(2, pTest##id, 1, ParamState_m##id call_params), \ - new State_Deleg_##id(3, pTest##id, 2, ParamState_m##id call_params), \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - NULL), "Test" #id " Part5"); \ - /* hook1, hook2 - hook3, hook4 */ \ - THGM_ADD_HOOK(id, 4); \ - THGM_CALLS_void(id, call_params); \ - CHECK_STATES((&g_States, \ - new State_Deleg_##id(1, pTest##id, 0, ParamState_m##id call_params), \ - new State_Deleg_##id(2, pTest##id, 1, ParamState_m##id call_params), \ - new State_Deleg_##id(3, pTest##id, 2, ParamState_m##id call_params), \ - new State_Deleg_##id(4, pTest##id, 3, ParamState_m##id call_params), \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - NULL), "Test" #id " Part6"); \ - \ - /* hook1 - hook3, hook4, with recalls! */ \ - \ - TestClass##id::ms_DoRecall = true; \ - THGM_REMOVE_HOOK(id, 2); \ - THGM_CALLS_void(id, call_params); \ - CHECK_STATES((&g_States, \ - new State_Deleg_##id(1, pTest##id, 0, ParamState_m##id call_params(0)), \ - new State_Func##id(pTest##id, ParamState_m##id call_params(1)), \ - new State_Deleg_##id(3, pTest##id, 2, ParamState_m##id call_params(1)), \ - new State_Deleg_##id(4, pTest##id, 3, ParamState_m##id call_params(2)), \ - /* sh_call one */ \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - NULL), "Test" #id " Part7"); \ - THGM_REMOVE_HOOK(id, 1); \ - THGM_REMOVE_HOOK(id, 3); \ - THGM_REMOVE_HOOK(id, 4); - -template -T ComparableRef(T x) -{ - return x; -} - -template -T* ComparableRef(T& x) -{ - return &x; -} - -#define THGM_CALLS(id, call_params, exp_ret_norm, exp_ret_shcall, err) \ - CHECK_COND(ComparableRef(pTest##id->Func call_params) == ComparableRef(MakeRet< RetType##id >::Do(exp_ret_norm)), err " /retcallnorm"); \ - CHECK_COND(ComparableRef(SH_CALL(pTest##id, &TestClass##id::Func) call_params) == ComparableRef(MakeRet< RetType##id >::Do(exp_ret_shcall)), err " /retcallshcall"); - -#define THGM_DO_TEST(id, call_params) \ - setuppi_##id(); \ - setupri_##id(); \ - SourceHook::HookManagerPubFunc myhookman##id = g_HMAGPtr->MakeHookMan(protoinfo_##id, 0, 0); \ - CAutoReleaseHookMan arhm_##id(myhookman##id); \ - int hook1_##id, hook2_##id, hook3_##id, hook4_##id; \ - \ - TestClass##id::ms_DoRecall = false; \ - TestClass##id *pTest##id = new TestClass##id; \ - CAutoPtrDestruction apd##id(pTest##id); \ - \ - /* no hooks - no hooks */ \ - PtrBuf_Clear(); \ - THGM_CALLS(id, call_params, 0, 0, "Part1"); \ - CHECK_STATES((&g_States, \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - NULL), "Test" #id " Part1"); \ - \ - /* hook1 - hook3 */ \ - PtrBuf_Clear(); \ - THGM_ADD_HOOK(id, 1); \ - THGM_ADD_HOOK(id, 3); \ - THGM_CALLS(id, call_params, 0, 0, "Part4"); \ - CHECK_STATES((&g_States, \ - new State_Deleg_##id(1, pTest##id, 0, ParamState_m##id call_params), \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - new State_Deleg_##id(3, pTest##id, 1, ParamState_m##id call_params), \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - NULL), "Test" #id " Part4"); \ - THGM_REMOVE_HOOK(id, 1); \ - THGM_REMOVE_HOOK(id, 3); \ - \ - /* hook1, hook2 - hook3 */ \ - PtrBuf_Clear(); \ - THGM_ADD_HOOK(id, 1); \ - THGM_ADD_HOOK(id, 2); \ - THGM_ADD_HOOK(id, 3); \ - THGM_CALLS(id, call_params, 2, 0, "Part5"); \ - CHECK_STATES((&g_States, \ - new State_Deleg_##id(1, pTest##id, 0, ParamState_m##id call_params), \ - new State_Deleg_##id(2, pTest##id, 1, ParamState_m##id call_params), \ - new State_Deleg_##id(3, pTest##id, 2, ParamState_m##id call_params), \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - NULL), "Test" #id " Part5"); \ - /* hook1, hook2 - hook3, hook4 */ \ - THGM_ADD_HOOK(id, 4); \ - THGM_CALLS(id, call_params, 4, 0, "Part6"); \ - CHECK_STATES((&g_States, \ - new State_Deleg_##id(1, pTest##id, 0, ParamState_m##id call_params), \ - new State_Deleg_##id(2, pTest##id, 1, ParamState_m##id call_params), \ - new State_Deleg_##id(3, pTest##id, 2, ParamState_m##id call_params), \ - new State_Deleg_##id(4, pTest##id, 3, ParamState_m##id call_params), \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - NULL), "Test" #id " Part6"); \ - \ - /* hook1 - hook3, hook4, with recalls! */ \ - \ - TestClass##id::ms_DoRecall = true; \ - THGM_REMOVE_HOOK(id, 2); \ - THGM_CALLS(id, call_params, 4, 0, "Part7"); \ - CHECK_STATES((&g_States, \ - new State_Deleg_##id(1, pTest##id, 0, ParamState_m##id call_params(0)), \ - new State_Func##id(pTest##id, ParamState_m##id call_params(1)), \ - new State_Deleg_##id(3, pTest##id, 2, ParamState_m##id call_params(1)), \ - new State_Deleg_##id(4, pTest##id, 3, ParamState_m##id call_params(2)), \ - /* sh_call one */ \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - NULL), "Test" #id " Part7"); \ - THGM_REMOVE_HOOK(id, 1); \ - THGM_REMOVE_HOOK(id, 3); \ - THGM_REMOVE_HOOK(id, 4); diff --git a/utils/mmsource/core/sourcehook/test/testhookmangen.hxx b/utils/mmsource/core/sourcehook/test/testhookmangen.hxx deleted file mode 100644 index 81b21cc45..000000000 --- a/utils/mmsource/core/sourcehook/test/testhookmangen.hxx +++ /dev/null @@ -1,584 +0,0 @@ -struct CAutoReleaseHookMan -{ - SourceHook::HookManagerPubFunc m_Ptr; - CAutoReleaseHookMan(SourceHook::HookManagerPubFunc ptr) : m_Ptr(ptr) - { - } - ~CAutoReleaseHookMan() - { - g_HMAGPtr->ReleaseHookMan(m_Ptr); - } -}; - -// Strip & -template struct StripRef -{ - typedef T type; -}; - -template struct StripRef -{ - typedef T type; -}; - -// Address of constructor/destructor -// (using wrappers) -template -class Ctor_Thunk -{ -public: - void NormalConstructor() - { - new(this) T; - } - - void CopyConstructor(const T &other) - { - new(this) T(other); - } - - void Destructor() - { - reinterpret_cast(this)->~T(); - } - - const T& AssignOp(const T &other) - { - return (*reinterpret_cast(this) = other); - } -}; - - -template -void *FindFuncAddr(T mfp) -{ - union - { - T a; - void *b; - } u; - u.a = mfp; - return u.b; -} - -// Reference carrier -template struct MyRefCarrier -{ - typedef T type; -}; - -template struct MyRefCarrier -{ - class type - { - T *m_StoredRef; - public: - type() : m_StoredRef(NULL) - { - } - type(T& ref) : m_StoredRef(&ref) - { - } - - T& operator= (T& ref) - { - m_StoredRef = &ref; - return ref; - } - - operator T& () const - { - return *m_StoredRef; - } - - bool operator== (const typename MyRefCarrier::type &other) - { - return m_StoredRef == other.m_StoredRef; - } - - friend std::ostream& operator <<(std::ostream &os,const typename MyRefCarrier::type &obj) - { - os << *obj.m_StoredRef; - return os; - } - }; -}; - -#if SH_COMP==SH_COMP_GCC -#define NO_OPTIMIZE __attribute__((noinline)) -#else -#define NO_OPTIMIZE -#endif - -// Return value maker -template -struct MakeRet -{ - static T Do(int a) - { - return a; - } -}; - -template -struct MakeRet< POD > -{ - static POD Do(int a) - { - POD x; - memset(reinterpret_cast(x.x), a, SIZE); - return x; - } -}; - -// Stores parameter status -template -bool EqualToMyFmtString(T sth) -{ - return false; -} - -bool EqualToMyFmtString(std::string &sth) -{ - if (sth == "Hello %s%d%s") - sth = "Hello BA1L!"; - return true; -} - - -@[$1,0,$a: - -template -struct ParamState$1 -{ - @[$2,1,$1:typename MyRefCarrier::type m_$2; @] - - bool operator==(const ParamState$1 &other) - { - return true - @[$2,1,$1: && m_$1 == other.m_$1@] - ; - } - ParamState$1(@[$2,1,$1:p$2 a$2, @]...) @[$1!=0::@] @[$2,1,$1|, :m_$2(a$2)@] - { - @[$2,1,$1: - EqualToMyFmtString(m_$2); - @] - } - - ParamState$1 & operator() (int incrsteps) - { - @[$1!=0:int i;@] - @[$2,1,$1: - for (i = 0; i < incrsteps; ++i) - Increment::type >::Incr(m_$2); - @] - - return *this; - } -}; - -@[$1!=0:template<@[$2,1,$1|, :class p$2@]>@] -std::ostream& operator <<(std::ostream &os,const ParamState$1<0@[$2,1,$1:, p$2@]> &obj) -{ - @[$1!=0:os@] @[$2,1,$1:<< obj.m_$2@]; - return os; -} - -@] - -#define CAT2(a, b) a##b -#define CAT3(a, b, c) a##b##c -#define CAT4(a, b, c, d) a##b##c##d - -// hook1: pre ignore -// hook2: pre supercede -// hook3: post ignore -// hook4: post supercede - - -@[$1,0,$a: - -#define THGM_MAKE_TEST$1_void(id@[$2,1,$1:, param$2@]) \ - struct TestClass##id; \ - typedef ParamState$1<0@[$2,1,$1:, param$2@] > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual void Func(@[$2,1,$1|, :param$2 p$2@]) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Func##id(this, ParamState_m##id(@[$2,1,$1|, :p$2@]))); \ - g_Inside_LeafFunc = false; \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual void Call(@[$2,1,$1|, :param$2 p$2@]) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(@[$2,1,$1|, :p$2@]))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - @[$2,1,$1:Increment::type>::Incr(p$2);@] \ - RETURN_META_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, &TestClass##id::Func, (@[$2,1,$1|, :p$2@])); \ - } \ - else \ - RETURN_META((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall); - - -#define THGM_MAKE_TEST$1(id, ret_type@[$2,1,$1:, param$2@]) \ - struct TestClass##id; \ - typedef ret_type RetType##id; \ - typedef ParamState$1<0@[$2,1,$1:, param$2@] > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual ret_type Func(@[$2,1,$1|, :param$2 p$2@]) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Func##id(this, ParamState_m##id(@[$2,1,$1|, :p$2@]))); \ - g_Inside_LeafFunc = false; \ - \ - return MakeRet< ret_type >::Do(0); \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual ret_type Call(@[$2,1,$1|, :param$2 p$2@]) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(@[$2,1,$1|, :p$2@]))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - @[$2,1,$1:Increment::type>::Incr(p$2);@] \ - RETURN_META_VALUE_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber), &TestClass##id::Func, (@[$2,1,$1|, :p$2@])); \ - } \ - else \ - RETURN_META_VALUE((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber)); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall); - -#define THGM_MAKE_TEST$1_vafmt_void(id@[$2,1,$1:, param$2@]) \ - struct TestClass##id; \ - typedef ParamState@($1+1)<0@[$2,1,$1:, param$2@], std::string > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual void Func(@[$2,1,$1:param$2 p$2, @]const char *fmt, ...) \ - { \ - g_Inside_LeafFunc = true; \ - \ - char buf[9999]; \ - va_list ap; \ - va_start(ap, fmt); \ - vsnprintf(buf, 9998, fmt, ap); \ - buf[9998] = 0; \ - va_end(ap); \ - \ - ADD_STATE(State_Func##id(this, ParamState_m##id(@[$2,1,$1:p$2, @]std::string(buf)))); \ - g_Inside_LeafFunc = false; \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual void Call(@[$2,1,$1:param$2 p$2, @]const char *buf) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(@[$2,1,$1:p$2, @]buf))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - @[$2,1,$1:Increment::type>::Incr(p$2);@] \ - RETURN_META_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, &TestClass##id::Func, (@[$2,1,$1:p$2, @]"%s!", buf)); \ - } \ - else \ - RETURN_META((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall | SourceHook::ProtoInfo::CallConv_HasVafmt); - -#define THGM_MAKE_TEST$1_vafmt(id, ret_type@[$2,1,$1:, param$2@]) \ - struct TestClass##id; \ - typedef ret_type RetType##id; \ - typedef ParamState@($1+1)<0@[$2,1,$1:, param$2@], std::string > ParamState_m##id; \ - MAKE_STATE_2(State_Func##id, TestClass##id* /*thisptr*/, ParamState_m##id ); \ - MAKE_STATE_4(State_Deleg_##id, int /*delegnumber*/, TestClass##id* /*ifptr*/, int /*deleg thisptr*/, ParamState_m##id ); \ - \ - struct TestClass##id \ - { \ - static bool ms_DoRecall; \ - \ - virtual ret_type Func(@[$2,1,$1:param$2 p$2, @]const char *fmt, ...) \ - { \ - g_Inside_LeafFunc = true; \ - \ - char buf[9999]; \ - va_list ap; \ - va_start(ap, fmt); \ - vsnprintf(buf, 9998, fmt, ap); \ - buf[9998] = 0; \ - va_end(ap); \ - \ - ADD_STATE(State_Func##id(this, ParamState_m##id(@[$2,1,$1:p$2, @]std::string(buf)))); \ - \ - return MakeRet< ret_type >::Do(0); \ - } \ - \ - struct Delegate : public MyDelegate \ - { \ - int m_DelegNumber; \ - Delegate(int num) : m_DelegNumber(num) { } \ - \ - virtual ret_type Call(@[$2,1,$1:param$2 p$2, @]const char *buf) \ - { \ - g_Inside_LeafFunc = true; \ - ADD_STATE(State_Deleg_##id(m_DelegNumber, META_IFACEPTR(TestClass##id), PtrBuf(this), ParamState_m##id(@[$2,1,$1:p$2, @]buf))); \ - g_Inside_LeafFunc = false; \ - if (ms_DoRecall) \ - { \ - @[$2,1,$1:Increment::type>::Incr(p$2);@] \ - RETURN_META_VALUE_NEWPARAMS((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber), &TestClass##id::Func, (@[$2,1,$1:p$2, @]"%s!", buf)); \ - } \ - else \ - RETURN_META_VALUE((m_DelegNumber & 1) ? MRES_IGNORED : MRES_SUPERCEDE, MakeRet< ret_type >::Do(m_DelegNumber)); \ - } \ - }; \ - }; \ - \ - bool TestClass##id::ms_DoRecall = false; \ - SourceHook::CProtoInfoBuilder protoinfo_##id(SourceHook::ProtoInfo::CallConv_ThisCall | SourceHook::ProtoInfo::CallConv_HasVafmt); - -#define THGM_SETUP_PI$1(id@[$2,1,$1:, p$2_type, p$2_passtype, p$2_flags@]) \ - void setuppi_##id() \ - { \ - @[$2,1,$1: \ - protoinfo_##id.AddParam(sizeof(p$2_type), p$2_passtype, p$2_flags, \ - (p$2_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (p$2_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (p$2_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (p$2_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - @] \ - } - -@] - -#define THGM_SETUP_RI(id, ret_type, ret_passtype, ret_flags) \ - void setupri_##id() \ - { \ - protoinfo_##id.SetReturnType(sizeof(ret_type), ret_passtype, ret_flags, \ - (ret_flags & SourceHook::PassInfo::PassFlag_OCtor) ? FindFuncAddr(&Ctor_Thunk::type>::NormalConstructor) : NULL, \ - (ret_flags & SourceHook::PassInfo::PassFlag_CCtor) ? FindFuncAddr(&Ctor_Thunk::type>::CopyConstructor) : NULL, \ - (ret_flags & SourceHook::PassInfo::PassFlag_ODtor) ? FindFuncAddr(&Ctor_Thunk::type>::Destructor) : NULL, \ - (ret_flags & SourceHook::PassInfo::PassFlag_AssignOp) ? FindFuncAddr(&Ctor_Thunk::type>::AssignOp) : NULL \ - ); \ - } - -#define THGM_ADD_HOOK(id, num) \ - CAT4(hook, num, _, id) = g_SHPtr->AddHook(g_PLID, SourceHook::ISourceHook::Hook_Normal, reinterpret_cast(pTest##id), \ - 0, myhookman##id, PtrBufPtr(new TestClass##id::Delegate(num)), num >= 3); - -#define THGM_REMOVE_HOOK(id, num) \ - g_SHPtr->RemoveHookByID(CAT4(hook, num, _, id)); - -#define THGM_CALLS_void(id, call_params) \ - pTest##id->Func call_params; \ - SH_CALL(pTest##id, &TestClass##id::Func) call_params; - -#define THGM_DO_TEST_void(id, call_params) \ - setuppi_##id(); \ - SourceHook::HookManagerPubFunc myhookman##id = g_HMAGPtr->MakeHookMan(protoinfo_##id, 0, 0); \ - CAutoReleaseHookMan arhm_##id(myhookman##id); \ - int hook1_##id, hook2_##id, hook3_##id, hook4_##id; \ - \ - TestClass##id::ms_DoRecall = false; \ - TestClass##id *pTest##id = new TestClass##id; \ - CAutoPtrDestruction apd##id(pTest##id); \ - \ - /* no hooks - no hooks */ \ - PtrBuf_Clear(); \ - THGM_CALLS_void(id, call_params); \ - CHECK_STATES((&g_States, \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - NULL), "Test" #id " Part1"); \ - \ - /* hook1 - hook3 */ \ - PtrBuf_Clear(); \ - THGM_ADD_HOOK(id, 1); \ - THGM_ADD_HOOK(id, 3); \ - THGM_CALLS_void(id, call_params); \ - CHECK_STATES((&g_States, \ - new State_Deleg_##id(1, pTest##id, 0, ParamState_m##id call_params), \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - new State_Deleg_##id(3, pTest##id, 1, ParamState_m##id call_params), \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - NULL), "Test" #id " Part4"); \ - THGM_REMOVE_HOOK(id, 1); \ - THGM_REMOVE_HOOK(id, 3); \ - \ - /* hook1, hook2 - hook3 */ \ - PtrBuf_Clear(); \ - THGM_ADD_HOOK(id, 1); \ - THGM_ADD_HOOK(id, 2); \ - THGM_ADD_HOOK(id, 3); \ - THGM_CALLS_void(id, call_params); \ - CHECK_STATES((&g_States, \ - new State_Deleg_##id(1, pTest##id, 0, ParamState_m##id call_params), \ - new State_Deleg_##id(2, pTest##id, 1, ParamState_m##id call_params), \ - new State_Deleg_##id(3, pTest##id, 2, ParamState_m##id call_params), \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - NULL), "Test" #id " Part5"); \ - /* hook1, hook2 - hook3, hook4 */ \ - THGM_ADD_HOOK(id, 4); \ - THGM_CALLS_void(id, call_params); \ - CHECK_STATES((&g_States, \ - new State_Deleg_##id(1, pTest##id, 0, ParamState_m##id call_params), \ - new State_Deleg_##id(2, pTest##id, 1, ParamState_m##id call_params), \ - new State_Deleg_##id(3, pTest##id, 2, ParamState_m##id call_params), \ - new State_Deleg_##id(4, pTest##id, 3, ParamState_m##id call_params), \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - NULL), "Test" #id " Part6"); \ - \ - /* hook1 - hook3, hook4, with recalls! */ \ - \ - TestClass##id::ms_DoRecall = true; \ - THGM_REMOVE_HOOK(id, 2); \ - THGM_CALLS_void(id, call_params); \ - CHECK_STATES((&g_States, \ - new State_Deleg_##id(1, pTest##id, 0, ParamState_m##id call_params(0)), \ - new State_Func##id(pTest##id, ParamState_m##id call_params(1)), \ - new State_Deleg_##id(3, pTest##id, 2, ParamState_m##id call_params(1)), \ - new State_Deleg_##id(4, pTest##id, 3, ParamState_m##id call_params(2)), \ - /* sh_call one */ \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - NULL), "Test" #id " Part7"); \ - THGM_REMOVE_HOOK(id, 1); \ - THGM_REMOVE_HOOK(id, 3); \ - THGM_REMOVE_HOOK(id, 4); - -template -T ComparableRef(T x) -{ - return x; -} - -template -T* ComparableRef(T& x) -{ - return &x; -} - -#define THGM_CALLS(id, call_params, exp_ret_norm, exp_ret_shcall, err) \ - CHECK_COND(ComparableRef(pTest##id->Func call_params) == ComparableRef(MakeRet< RetType##id >::Do(exp_ret_norm)), err " /retcallnorm"); \ - CHECK_COND(ComparableRef(SH_CALL(pTest##id, &TestClass##id::Func) call_params) == ComparableRef(MakeRet< RetType##id >::Do(exp_ret_shcall)), err " /retcallshcall"); - -#define THGM_DO_TEST(id, call_params) \ - setuppi_##id(); \ - setupri_##id(); \ - SourceHook::HookManagerPubFunc myhookman##id = g_HMAGPtr->MakeHookMan(protoinfo_##id, 0, 0); \ - CAutoReleaseHookMan arhm_##id(myhookman##id); \ - int hook1_##id, hook2_##id, hook3_##id, hook4_##id; \ - \ - TestClass##id::ms_DoRecall = false; \ - TestClass##id *pTest##id = new TestClass##id; \ - CAutoPtrDestruction apd##id(pTest##id); \ - \ - /* no hooks - no hooks */ \ - PtrBuf_Clear(); \ - THGM_CALLS(id, call_params, 0, 0, "Part1"); \ - CHECK_STATES((&g_States, \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - NULL), "Test" #id " Part1"); \ - \ - /* hook1 - hook3 */ \ - PtrBuf_Clear(); \ - THGM_ADD_HOOK(id, 1); \ - THGM_ADD_HOOK(id, 3); \ - THGM_CALLS(id, call_params, 0, 0, "Part4"); \ - CHECK_STATES((&g_States, \ - new State_Deleg_##id(1, pTest##id, 0, ParamState_m##id call_params), \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - new State_Deleg_##id(3, pTest##id, 1, ParamState_m##id call_params), \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - NULL), "Test" #id " Part4"); \ - THGM_REMOVE_HOOK(id, 1); \ - THGM_REMOVE_HOOK(id, 3); \ - \ - /* hook1, hook2 - hook3 */ \ - PtrBuf_Clear(); \ - THGM_ADD_HOOK(id, 1); \ - THGM_ADD_HOOK(id, 2); \ - THGM_ADD_HOOK(id, 3); \ - THGM_CALLS(id, call_params, 2, 0, "Part5"); \ - CHECK_STATES((&g_States, \ - new State_Deleg_##id(1, pTest##id, 0, ParamState_m##id call_params), \ - new State_Deleg_##id(2, pTest##id, 1, ParamState_m##id call_params), \ - new State_Deleg_##id(3, pTest##id, 2, ParamState_m##id call_params), \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - NULL), "Test" #id " Part5"); \ - /* hook1, hook2 - hook3, hook4 */ \ - THGM_ADD_HOOK(id, 4); \ - THGM_CALLS(id, call_params, 4, 0, "Part6"); \ - CHECK_STATES((&g_States, \ - new State_Deleg_##id(1, pTest##id, 0, ParamState_m##id call_params), \ - new State_Deleg_##id(2, pTest##id, 1, ParamState_m##id call_params), \ - new State_Deleg_##id(3, pTest##id, 2, ParamState_m##id call_params), \ - new State_Deleg_##id(4, pTest##id, 3, ParamState_m##id call_params), \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - NULL), "Test" #id " Part6"); \ - \ - /* hook1 - hook3, hook4, with recalls! */ \ - \ - TestClass##id::ms_DoRecall = true; \ - THGM_REMOVE_HOOK(id, 2); \ - THGM_CALLS(id, call_params, 4, 0, "Part7"); \ - CHECK_STATES((&g_States, \ - new State_Deleg_##id(1, pTest##id, 0, ParamState_m##id call_params(0)), \ - new State_Func##id(pTest##id, ParamState_m##id call_params(1)), \ - new State_Deleg_##id(3, pTest##id, 2, ParamState_m##id call_params(1)), \ - new State_Deleg_##id(4, pTest##id, 3, ParamState_m##id call_params(2)), \ - /* sh_call one */ \ - new State_Func##id(pTest##id, ParamState_m##id call_params), \ - NULL), "Test" #id " Part7"); \ - THGM_REMOVE_HOOK(id, 1); \ - THGM_REMOVE_HOOK(id, 3); \ - THGM_REMOVE_HOOK(id, 4); diff --git a/utils/mmsource/core/sourcehook/test/testlist.cpp b/utils/mmsource/core/sourcehook/test/testlist.cpp deleted file mode 100644 index bbaa4d315..000000000 --- a/utils/mmsource/core/sourcehook/test/testlist.cpp +++ /dev/null @@ -1,282 +0,0 @@ -#include -#include "sh_list.h" -#include "sh_stack.h" -#include "sh_tinyhash.h" -#include "sh_vector.h" -#include "testevents.h" - -// TEST LIST -// Tests sh_list, sh_tinyhash, sh_vector - -// :TODO: vector test, list insert test - -namespace -{ - struct Hmm - { - Hmm *m_This; - int m_Int; - Hmm(const Hmm &other) : m_Int(other.m_Int) - { - m_This = this; - } - Hmm(int i) : m_Int(i) - { - m_This = this; - } - Hmm() : m_Int(0) - { - m_This = this; - } - void operator = (const Hmm &other) - { - m_Int = other.m_Int; - } - operator int () const - { - return m_Int; - } - }; - - #define LIST_THIS_CHECK(lst, err) \ - for (ListType::iterator iter = lst.begin(); iter != lst.end(); ++iter) \ - CHECK_COND(&(*iter) == iter->m_This, err); - - bool DoTestList(std::string &error) - { - typedef SourceHook::List ListType; - ListType lst; - - CHECK_COND(lst.empty(), "Part1"); - - for (int i = 1; i <= 100; ++i) - lst.push_back(i); - - LIST_THIS_CHECK(lst, "PartA1"); - - CHECK_COND(!lst.empty(), "Part2"); - - lst.clear(); - - CHECK_COND(lst.empty(), "Part3"); - - for (int i = 1; i <= 100; ++i) - lst.push_back(i); - - CHECK_COND(lst.back() == 100, "Part4"); - LIST_THIS_CHECK(lst, "PartA2"); - - int ver = 1; - for (ListType::iterator iter = lst.begin(); iter != lst.end(); ++iter) - CHECK_COND(*iter == ver++, "Part5"); - - CHECK_COND(ver == 101, "Part 6"); - - ListType::iterator iter50 = lst.find(50); - CHECK_COND(*iter50 == 50, "Part7"); - - iter50 = lst.erase(iter50); - CHECK_COND(*iter50 == 51, "Part8"); - CHECK_COND(*--iter50 == 49, "Part8.2"); - - lst.remove(80); - - ver = 1; - for (ListType::iterator iter = lst.begin(); iter != lst.end(); ++iter) - { - CHECK_COND(*iter == ver++, "Part9"); - if (ver == 50 || ver == 80) - ++ver; - } - CHECK_COND(ver == 101, "Part10"); - LIST_THIS_CHECK(lst, "PartA3"); - - ListType lst2; - lst = lst2; - CHECK_COND(lst.empty(), "Part11"); - - for (int i = 1; i <= 100; ++i) - lst.push_back(i); - lst2 = lst; - CHECK_COND(lst2.size() == 100, "Part11.2"); - - LIST_THIS_CHECK(lst, "PartA4"); - LIST_THIS_CHECK(lst2, "PartA5"); - - ver = 1; - for (ListType::iterator iter = lst2.begin(); iter != lst2.end(); ++iter) - CHECK_COND(*iter == ver++, "Part12"); - - lst.clear(); - for (int i = 401; i <= 500; ++i) - lst.push_back(i); - lst = lst2; - CHECK_COND(lst2.size() == 100, "Part13"); - - ver = 1; - for (ListType::iterator iter = lst.begin(); iter != lst.end(); ++iter) - CHECK_COND(*iter == ver++, "Part14"); - - LIST_THIS_CHECK(lst, "PartA6"); - LIST_THIS_CHECK(lst2, "PartA7"); - - return true; - } - - bool DoTestTinyHash(std::string &error) - { - const int mymax = 5000; - - typedef SourceHook::THash HashType; - HashType hash; - - for (int i = 1; i <= mymax; ++i) - hash[i] = i + 5000; - - for (int i = 1; i <= mymax; ++i) - CHECK_COND(hash[i] == i + 5000, "Part1"); - - // Find - int ver = 1; - HashType::iterator iter; - for (iter = hash.begin(); iter != hash.end(); ++iter) - CHECK_COND(iter->key == ver && iter->val == (ver++) + 5000, "Part2"); - - CHECK_COND(ver == mymax+1, "Part2.1"); - - iter = hash.find(300); - CHECK_COND(iter != hash.end() && iter->val == 300+5000, "Part3.1"); - iter = hash.find(mymax+200); - CHECK_COND(iter == hash.end(), "Part3.2"); - - HashType hash2; - for (int i = 1; i <= mymax; ++i) - hash2[i] = i + 5000; - - hash2.erase(mymax - 100); - CHECK_COND(hash2.find(mymax - 101) != hash2.end(), "Part 4.1"); - CHECK_COND(hash2.find(mymax - 99) != hash2.end(), "Part 4.2"); - CHECK_COND(hash2.find(mymax - 100) == hash2.end(), "Part 4.3"); - hash2.erase(mymax - 99); - CHECK_COND(hash2.find(mymax - 101) != hash2.end(), "Part 4.4"); - CHECK_COND(hash2.find(mymax - 99) == hash2.end(), "Part 4.5"); - CHECK_COND(hash2.find(mymax - 100) == hash2.end(), "Part 4.6"); - - return true; - } - - bool DoTestStack(std::string &error) - { - typedef SourceHook::CStack IntStack; - IntStack stk; - int i; - - CHECK_COND(stk.size() == 0 && stk.empty(), "A0"); - - for (i = 0; i < 5000; ++i) - stk.push(i); - - CHECK_COND(stk.front() == 4999, "1"); - CHECK_COND(stk.size() == 5000 && !stk.empty(), "A1"); - - IntStack::iterator iter; - i = 0; - for (iter = stk.begin(); iter != stk.end(); ++iter, ++i) - CHECK_COND(*iter == i, "2"); - - i = 0; - for (iter = stk.begin(); iter != stk.end(); iter++, ++i) - CHECK_COND(*iter == i, "3"); - - --iter; - iter--; - *iter = 'g'+'a'+'b'+'e'+'n'; - stk.pop(); - - CHECK_COND(stk.size() == 4999 && !stk.empty(), "A2"); - CHECK_COND(stk.front() == 'g'+'a'+'b'+'e'+'n', "4"); - - IntStack stk2(stk); - CHECK_COND(stk2.size() == 4999 && !stk2.empty(), "A3"); - - IntStack::iterator iter2 = stk2.begin(); - for (iter = stk.begin(); iter != stk.end(); ++iter, iter2++) - CHECK_COND(*iter == *iter2, "5"); - - while (!stk2.empty()) - stk2.pop(); - CHECK_COND(stk2.size() == 0 && stk2.empty(), "A4"); - stk = stk2; - CHECK_COND(stk.size() == 0 && stk.empty(), "A5"); - - return true; - } - - bool DoTestVec(std::string &error) - { - typedef SourceHook::CVector IntVector; - IntVector vec1; - IntVector::iterator iter; - int i; - - CHECK_COND(vec1.size() == 0 && vec1.empty(), "V1"); - for (i = 0; i < 500; ++i) - vec1.push_back(i); - - CHECK_COND(vec1.size() == 500 && !vec1.empty(), "V2"); - - for (i = 0; i < 500; ++i) - CHECK_COND(vec1[i] == i, "V3"); - - for (i = 0, iter = vec1.begin(); iter != vec1.end(); ++iter, ++i) - CHECK_COND(*iter == i, "V4"); - - vec1.resize(1000); - for (i = 0; i < 500; ++i) - CHECK_COND(vec1[i] == i, "V5.1"); - for (i = 500; i < 1000; ++i) - CHECK_COND(vec1[i] == 0, "V5.2"); - - vec1.resize(200); - for (i = 0; i < 200; ++i) - CHECK_COND(vec1[i] == i, "V6"); - - vec1.resize(500, 0x12345678); - for (i = 0; i < 200; ++i) - CHECK_COND(vec1[i] == i, "V7.1"); - for (i = 200; i < 500; ++i) - CHECK_COND(vec1[i] == 0x12345678, "V7.2"); - - IntVector vec2(vec1); - CHECK_COND(vec2.size() == vec1.size() && vec2.empty() == vec1.empty(), "V8.0"); - for (i = 0; i < 200; ++i) - CHECK_COND(vec2[i] == i, "V8.1"); - for (i = 200; i < 500; ++i) - CHECK_COND(vec2[i] == 0x12345678, "V8.2"); - - - vec1.clear(); - CHECK_COND(vec1.size() == 0 && vec1.empty() && vec1.begin() == vec1.end(), "V9"); - vec2 = vec1; - CHECK_COND(vec2.size() == 0 && vec2.empty() && vec2.begin() == vec2.end(), "V9"); - - return true; - } -} - -bool TestList(std::string &error) -{ - if (!DoTestList(error)) - return false; - - if (!DoTestTinyHash(error)) - return false; - - if (!DoTestStack(error)) - return false; - - if (!DoTestVec(error)) - return false; - - return true; -} diff --git a/utils/mmsource/core/sourcehook/test/testmanual.cpp b/utils/mmsource/core/sourcehook/test/testmanual.cpp deleted file mode 100644 index 41d2c0c7f..000000000 --- a/utils/mmsource/core/sourcehook/test/testmanual.cpp +++ /dev/null @@ -1,382 +0,0 @@ -#include -#include "sourcehook.h" -#include "sourcehook_test.h" -#include "testevents.h" - -// TESTMANUAL -// Test manual hooks -// :TODO: test more extensively - -namespace -{ - StateList g_States; - SourceHook::ISourceHook *g_SHPtr; - SourceHook::Plugin g_PLID; - - MAKE_STATE_1(State_Func1_Called, void*); // param1: This pointer - MAKE_STATE_2(State_Func2_Called, void*, int); // param1: This pointer; param2: parameter - MAKE_STATE_1(State_Func3_Called, void*); // param1: This pointer - MAKE_STATE_2(State_Func4_Called, void*, int); // param1: This pointer; param2: parameter - MAKE_STATE_1(State_Func5_Called, void*); // param1: This pointer - - MAKE_STATE_1(State_Func1H_Called, void*); - MAKE_STATE_2(State_Func2H_Called, void*, int); - MAKE_STATE_1(State_Func3H_Called, void*); - MAKE_STATE_2(State_Func4H_Called, void*, int); - - MAKE_STATE_1(State_Return, short); - - class TheWall - { - public: - virtual void Func1() - { - ADD_STATE(State_Func1_Called(reinterpret_cast(this))); - } - virtual void Func2(int x) - { - ADD_STATE(State_Func2_Called(reinterpret_cast(this), x)); - } - - virtual short Func3() - { - ADD_STATE(State_Func3_Called(reinterpret_cast(this))); - return 3; - } - virtual short Func4(int x) - { - ADD_STATE(State_Func4_Called(reinterpret_cast(this), x)); - return 4; - } - virtual void Func5() - { - ADD_STATE(State_Func5_Called(reinterpret_cast(this))); - } - - virtual const char *Func6() - { - return 0; - } - virtual char *Func7() - { - return 0; - } - }; - - SH_DECL_HOOK0_void(TheWall, Func1, SH_NOATTRIB, 0); - SH_DECL_HOOK1_void(TheWall, Func2, SH_NOATTRIB, 0, int); - SH_DECL_HOOK0(TheWall, Func3, SH_NOATTRIB, 0, short); - SH_DECL_HOOK1(TheWall, Func4, SH_NOATTRIB, 0, short, int); - - SH_DECL_MANUALHOOK0_void(TheWall_Func1, 0, 0, 0); - SH_DECL_MANUALHOOK1_void(TheWall_Func2, 1, 0, 0, int); - SH_DECL_MANUALHOOK0(TheWall_Func3, 2, 0, 0, short); - SH_DECL_MANUALHOOK1(TheWall_Func4, 3, 0, 0, short, int); - - SH_DECL_MANUALHOOK0(TheWall_Func6, 5, 0, 0, const char *); - SH_DECL_MANUALEXTERN0(TheWall_Func6, const char *); - - SH_DECL_MANUALHOOK0(TheWall_Func7, 6, 0, 0, char *); - SH_DECL_MANUALEXTERN0(TheWall_Func7, char *); - - SH_DECL_MANUALEXTERN0_void(TheWall_Func1); - SH_DECL_MANUALEXTERN1(TheWall_Func4, short, int); - - typedef void (SourceHook::EmptyClass::*MFP_Func1)(); - typedef void (SourceHook::EmptyClass::*MFP_Func2)(int); - typedef short (SourceHook::EmptyClass::*MFP_Func3)(); - typedef short (SourceHook::EmptyClass::*MFP_Func4)(int); - - void Handler_Func1() - { - ADD_STATE(State_Func1H_Called(META_IFACEPTR(void))); - } - void Handler_Func2(int x) - { - ADD_STATE(State_Func2H_Called(META_IFACEPTR(void), x)); - RETURN_META_MNEWPARAMS(MRES_IGNORED, TheWall_Func2, (0x87654321)); - } - short Handler_Func3() - { - ADD_STATE(State_Func3H_Called(META_IFACEPTR(void))); - return 0; - } - short Handler_Func4(int x) - { - ADD_STATE(State_Func4H_Called(META_IFACEPTR(void), x)); - - // newparams (recall) using the manual hook declaration! - RETURN_META_VALUE_MNEWPARAMS(MRES_IGNORED, 0, TheWall_Func4, (0x12345678)); - } - - struct AnotherBrick - { - void Handler_Func1() - { - ADD_STATE(State_Func1H_Called(META_IFACEPTR(void))); - RETURN_META(MRES_SUPERCEDE); - } - }; - - TheWall *MyInstanceFactory() - { - return new TheWall; - } -} - -bool TestManual(std::string &error) -{ - GET_SHPTR(g_SHPtr); - g_PLID = 1337; - - TheWall *p = MyInstanceFactory(); - CAutoPtrDestruction apd(p); - - SourceHook::ManualCallClass *cc = SH_GET_MCALLCLASS(p, sizeof(void*)); - - // 1) - // Call each function - p->Func1(); - p->Func2(200); - ADD_STATE(State_Return(p->Func3())); - ADD_STATE(State_Return(p->Func4(400))); - - CHECK_STATES((&g_States, - new State_Func1_Called(p), - new State_Func2_Called(p, 200), - new State_Func3_Called(p), - new State_Return(3), - new State_Func4_Called(p, 400), - new State_Return(4), - NULL), "Part 1"); - - // 1.1) - // Now call each function through the manual call class, using the hook decl and manually - SH_MCALL(cc, TheWall_Func1)(); - SH_MCALL2(cc, MFP_Func1(), 0, 0, 0)(); - SH_MCALL(cc, TheWall_Func2)(200); - SH_MCALL2(cc, MFP_Func2(), 1, 0, 0)(200); - ADD_STATE(State_Return(SH_MCALL(cc, TheWall_Func3)())); - ADD_STATE(State_Return(SH_MCALL2(cc, MFP_Func3(), 2, 0, 0)())); - ADD_STATE(State_Return(SH_MCALL(cc, TheWall_Func4)(400))); - ADD_STATE(State_Return(SH_MCALL2(cc, MFP_Func4(), 3, 0, 0)(400))); - - CHECK_STATES((&g_States, - new State_Func1_Called(p), - new State_Func1_Called(p), - new State_Func2_Called(p, 200), - new State_Func2_Called(p, 200), - new State_Func3_Called(p), - new State_Return(3), - new State_Func3_Called(p), - new State_Return(3), - new State_Func4_Called(p, 400), - new State_Return(4), - new State_Func4_Called(p, 400), - new State_Return(4), - NULL), "Part 1.1"); - - // 2) - // Hook each function normally, call them - SH_ADD_HOOK(TheWall, Func1, p, SH_STATIC(Handler_Func1), false); - SH_ADD_HOOK(TheWall, Func2, p, SH_STATIC(Handler_Func2), false); - SH_ADD_HOOK(TheWall, Func3, p, SH_STATIC(Handler_Func3), false); - SH_ADD_HOOK(TheWall, Func4, p, SH_STATIC(Handler_Func4), false); - - p->Func1(); - p->Func2(200); - ADD_STATE(State_Return(p->Func3())); - ADD_STATE(State_Return(p->Func4(400))); - - CHECK_STATES((&g_States, - new State_Func1H_Called(p), - new State_Func1_Called(p), - new State_Func2H_Called(p, 200), - new State_Func2_Called(p, 0x87654321), - new State_Func3H_Called(p), - new State_Func3_Called(p), - new State_Return(3), - new State_Func4H_Called(p, 400), - new State_Func4_Called(p, 0x12345678), - new State_Return(4), - NULL), "Part 2"); - - // Call them through the mcallclass - // 2.1) - // Now call each function through the manual call class, using the hook decl and manually - SH_MCALL(cc, TheWall_Func1)(); - SH_MCALL2(cc, MFP_Func1(), 0, 0, 0)(); - SH_MCALL(cc, TheWall_Func2)(200); - SH_MCALL2(cc, MFP_Func2(), 1, 0, 0)(200); - ADD_STATE(State_Return(SH_MCALL(cc, TheWall_Func3)())); - ADD_STATE(State_Return(SH_MCALL2(cc, MFP_Func3(), 2, 0, 0)())); - ADD_STATE(State_Return(SH_MCALL(cc, TheWall_Func4)(400))); - ADD_STATE(State_Return(SH_MCALL2(cc, MFP_Func4(), 3, 0, 0)(400))); - - CHECK_STATES((&g_States, - new State_Func1_Called(p), - new State_Func1_Called(p), - new State_Func2_Called(p, 200), - new State_Func2_Called(p, 200), - new State_Func3_Called(p), - new State_Return(3), - new State_Func3_Called(p), - new State_Return(3), - new State_Func4_Called(p, 400), - new State_Return(4), - new State_Func4_Called(p, 400), - new State_Return(4), - NULL), "Part 2.1"); - - // Unhook them - SH_REMOVE_HOOK(TheWall, Func1, p, SH_STATIC(Handler_Func1), false); - SH_REMOVE_HOOK(TheWall, Func2, p, SH_STATIC(Handler_Func2), false); - SH_REMOVE_HOOK(TheWall, Func3, p, SH_STATIC(Handler_Func3), false); - SH_REMOVE_HOOK(TheWall, Func4, p, SH_STATIC(Handler_Func4), false); - - // 3) - // Hook each function manually, call them - - SH_ADD_MANUALHOOK(TheWall_Func1, p, SH_STATIC(Handler_Func1), false); - SH_ADD_MANUALHOOK(TheWall_Func2, p, SH_STATIC(Handler_Func2), false); - SH_ADD_MANUALHOOK(TheWall_Func3, p, SH_STATIC(Handler_Func3), false); - SH_ADD_MANUALHOOK(TheWall_Func4, p, SH_STATIC(Handler_Func4), false); - - p->Func1(); - p->Func2(200); - ADD_STATE(State_Return(p->Func3())); - ADD_STATE(State_Return(p->Func4(400))); - - CHECK_STATES((&g_States, - new State_Func1H_Called(p), - new State_Func1_Called(p), - new State_Func2H_Called(p, 200), - new State_Func2_Called(p, 0x87654321), - new State_Func3H_Called(p), - new State_Func3_Called(p), - new State_Return(3), - new State_Func4H_Called(p, 400), - new State_Func4_Called(p, 0x12345678), - new State_Return(4), - NULL), "Part 3"); - - // Now through the mcallclass - - // Call them through the mcallclass - // 3.1) - // Now call each function through the manual call class, using the hook decl and manually - SH_MCALL(cc, TheWall_Func1)(); - SH_MCALL2(cc, MFP_Func1(), 0, 0, 0)(); - SH_MCALL(cc, TheWall_Func2)(200); - SH_MCALL2(cc, MFP_Func2(), 1, 0, 0)(200); - ADD_STATE(State_Return(SH_MCALL(cc, TheWall_Func3)())); - ADD_STATE(State_Return(SH_MCALL2(cc, MFP_Func3(), 2, 0, 0)())); - ADD_STATE(State_Return(SH_MCALL(cc, TheWall_Func4)(400))); - ADD_STATE(State_Return(SH_MCALL2(cc, MFP_Func4(), 3, 0, 0)(400))); - - CHECK_STATES((&g_States, - new State_Func1_Called(p), - new State_Func1_Called(p), - new State_Func2_Called(p, 200), - new State_Func2_Called(p, 200), - new State_Func3_Called(p), - new State_Return(3), - new State_Func3_Called(p), - new State_Return(3), - new State_Func4_Called(p, 400), - new State_Return(4), - new State_Func4_Called(p, 400), - new State_Return(4), - NULL), "Part 3.1"); - - // Unhook them - SH_REMOVE_MANUALHOOK(TheWall_Func1, p, SH_STATIC(Handler_Func1), false); - SH_REMOVE_MANUALHOOK(TheWall_Func2, p, SH_STATIC(Handler_Func2), false); - SH_REMOVE_MANUALHOOK(TheWall_Func3, p, SH_STATIC(Handler_Func3), false); - SH_REMOVE_MANUALHOOK(TheWall_Func4, p, SH_STATIC(Handler_Func4), false); - - // 4) - // Hook each function manually, then normally, call, unhook - - AnotherBrick handler_inst; - - // Why this? - // 1) tests sh_add_manualhook - // 2) in my tests, the proto of the manual hook was not equal to the proto of the auto hook - // (because there are no attribs for manual hooks). - // sourcehook.cpp did a !strcmp(..), so it assigned a new hook manager even though there - // already was one for this vfnptr. This hook manager stored the pointer of the original - // hook manager's hookfunc as the orig pointer - everything seemingly worked. - // The problem with this is that returning MRES_SUPERCEDE (as AnotherBrick::Handler_Func1 - // does) will supercede the second hook func from being called - thus bypassing the call - // of the auto hook here. - SH_ADD_MANUALHOOK(TheWall_Func1, p, SH_MEMBER(&handler_inst, &AnotherBrick::Handler_Func1), false); - SH_ADD_MANUALHOOK(TheWall_Func2, p, SH_STATIC(Handler_Func2), false); - SH_ADD_MANUALHOOK(TheWall_Func3, p, SH_STATIC(Handler_Func3), false); - SH_ADD_MANUALHOOK(TheWall_Func4, p, SH_STATIC(Handler_Func4), false); - - SH_ADD_HOOK(TheWall, Func1, p, SH_STATIC(Handler_Func1), false); - SH_ADD_HOOK(TheWall, Func2, p, SH_STATIC(Handler_Func2), false); - SH_ADD_HOOK(TheWall, Func3, p, SH_STATIC(Handler_Func3), false); - SH_ADD_HOOK(TheWall, Func4, p, SH_STATIC(Handler_Func4), false); - - p->Func1(); - p->Func2(200); - ADD_STATE(State_Return(p->Func3())); - ADD_STATE(State_Return(p->Func4(400))); - - CHECK_STATES((&g_States, - new State_Func1H_Called(p), - new State_Func1H_Called(p), - //new State_Func1_Called(p), - new State_Func2H_Called(p, 200), - new State_Func2H_Called(p, 0x87654321), - new State_Func2_Called(p, 0x87654321), - new State_Func3H_Called(p), - new State_Func3H_Called(p), - new State_Func3_Called(p), - new State_Return(3), - new State_Func4H_Called(p, 400), - new State_Func4H_Called(p, 0x12345678), - new State_Func4_Called(p, 0x12345678), - new State_Return(4), - NULL), "Part 4"); - - SH_REMOVE_MANUALHOOK(TheWall_Func1, p, SH_MEMBER(&handler_inst, &AnotherBrick::Handler_Func1), false); - SH_REMOVE_MANUALHOOK(TheWall_Func2, p, SH_STATIC(Handler_Func2), false); - SH_REMOVE_MANUALHOOK(TheWall_Func3, p, SH_STATIC(Handler_Func3), false); - SH_REMOVE_MANUALHOOK(TheWall_Func4, p, SH_STATIC(Handler_Func4), false); - - SH_REMOVE_HOOK(TheWall, Func1, p, SH_STATIC(Handler_Func1), false); - SH_REMOVE_HOOK(TheWall, Func2, p, SH_STATIC(Handler_Func2), false); - SH_REMOVE_HOOK(TheWall, Func3, p, SH_STATIC(Handler_Func3), false); - SH_REMOVE_HOOK(TheWall, Func4, p, SH_STATIC(Handler_Func4), false); - - // 5) Reconfigure TheWall_Func1 to actually hook Func5: - SH_MANUALHOOK_RECONFIGURE(TheWall_Func1, 4, 0, 0); - SH_MANUALHOOK_RECONFIGURE(TheWall_Func1, 4, 0, 0); - SH_ADD_MANUALHOOK(TheWall_Func1, p, SH_STATIC(Handler_Func1), false); - - p->Func5(); - - SH_MCALL(p, TheWall_Func1)(); - - CHECK_STATES((&g_States, - new State_Func1H_Called(p), - new State_Func5_Called(p), - new State_Func5_Called(p), - NULL), "Part 5"); - - // 6) Test auto-remove on reconfig - SH_MANUALHOOK_RECONFIGURE(TheWall_Func1, 0, 0, 0); - - p->Func1(); - p->Func5(); - - CHECK_STATES((&g_States, - new State_Func1_Called(p), - new State_Func5_Called(p), - NULL), "Part 6"); - - return true; -} diff --git a/utils/mmsource/core/sourcehook/test/testmulti.cpp b/utils/mmsource/core/sourcehook/test/testmulti.cpp deleted file mode 100644 index 8e2092391..000000000 --- a/utils/mmsource/core/sourcehook/test/testmulti.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include "sourcehook.h" -#include "sourcehook_test.h" -#include "testevents.h" - -// This should probably be done the other way round! -#if SH_XP == SH_XP_POSIX -#define _snprintf snprintf -#endif - -namespace -{ - SourceHook::ISourceHook *g_SHPtr; - SourceHook::Plugin g_PLID; - - unsigned int g_callcount[10]; - - class VMultiTest - { - public: - VMultiTest(unsigned int index) : m_idx(index) - { - } - public: - virtual void HookTarget() - { - } - virtual void Notify() - { - g_callcount[this->m_idx]++; - } - private: - unsigned int m_idx; - }; - - void HookFunction() - { - VMultiTest *pv = META_IFACEPTR(VMultiTest); - pv->Notify(); - } - - SH_DECL_HOOK0_void(VMultiTest, HookTarget, SH_NOATTRIB, false); -}; - -bool TestMulti(std::string &error) -{ - GET_SHPTR(g_SHPtr); - g_PLID = 1337; - - VMultiTest **pv = new VMultiTest *[10]; - for (unsigned int i=0; i<10; i++) - pv[i] = new VMultiTest(i); - - - for (unsigned int i=0; i<10; i++) - SH_ADD_HOOK(VMultiTest, HookTarget, pv[i], SH_STATIC(HookFunction), false); - - pv[0]->HookTarget(); - - if (g_callcount[0] != 1) - { - error.assign("g_callcount[0] != 0"); - return false; - } - - for (unsigned int i=1; i<10; i++) - { - if (g_callcount[i]) - { - error.assign("g_callcount[n] != 0"); - return false; - } - } - - SH_REMOVE_HOOK(VMultiTest, HookTarget, pv[0], SH_STATIC(HookFunction), false); - - for (unsigned int i=1; i<10; i++) - pv[i]->HookTarget(); - - if (g_callcount[0] != 1) - { - error.assign("g_callcount[0] != 0"); - return false; - } - - for (unsigned int i=1; i<10; i++) - { - if (g_callcount[i] != 1) - { - char err[256]; - _snprintf(err, sizeof(err)-1, "g_callcount[%d] != 1", i); - error.assign(err); - return false; - } - } - - for (unsigned int i=0; i<10; i++) - { - SH_REMOVE_HOOK(VMultiTest, HookTarget, pv[1], SH_STATIC(HookFunction), false); - delete pv[i]; - } - - delete [] pv; - - return true; -} diff --git a/utils/mmsource/core/sourcehook/test/testoddthunks.cpp b/utils/mmsource/core/sourcehook/test/testoddthunks.cpp deleted file mode 100644 index 7d625834a..000000000 --- a/utils/mmsource/core/sourcehook/test/testoddthunks.cpp +++ /dev/null @@ -1,182 +0,0 @@ -#include -#include -#include -#include "sourcehook_test.h" -#include "sh_pagealloc.h" -#include "testevents.h" - -namespace -{ - StateList g_States; - SourceHook::ISourceHook *g_SHPtr; - SourceHook::Plugin g_PLID; - - MAKE_STATE(State_Func_Called); - MAKE_STATE(State_Pre1_Called); - MAKE_STATE(State_Pre2_Called); - - int g_CallNumber; - - class Test - { - public: - virtual void Func() - { - ADD_STATE(State_Func_Called); - } - }; - - Test *g_pInst; - - void Handler_Func_Pre1() - { - ADD_STATE(State_Pre1_Called); - } - - SH_DECL_HOOK0_void(Test, Func, SH_NOATTRIB, 0); - - void Handler_Func_Pre2() - { - ADD_STATE(State_Pre2_Called); - - ++g_CallNumber; - if (g_CallNumber == 2) - { - // REMOVE ourselves - SH_REMOVE_HOOK(Test, Func, g_pInst, SH_STATIC(Handler_Func_Pre1), false); - SH_REMOVE_HOOK(Test, Func, g_pInst, SH_STATIC(Handler_Func_Pre2), false); - } - - // Call again. - g_pInst->Func(); - } - - Test *MyInstanceFactory() - { - return new Test; - } - - SourceHook::CPageAlloc g_ThunkAllocator(2); - void *g_OddThunkMemory = NULL; - void *g_OddThunk = NULL; - - // Guarantees that Func() - // has a vtable entry showing to an ODD address - void PatchFuncWithOddThunk() - { - g_OddThunkMemory = g_ThunkAllocator.Alloc(10); - unsigned char* base = reinterpret_cast(g_OddThunkMemory); - - if (((ptrdiff_t)base) & 1) - { - // ODD, ok. - } - else - { - // EVEN. make odd. - base += 1; - } - - // Get vtable entry pointer - SourceHook::MemFuncInfo info = {true, -1, 0, 0}; - SourceHook::GetFuncInfo(g_pInst, &Test::Func, info); - - void *adjustediface = NULL; - void **cur_vtptr = NULL; - void **cur_vfnptr = NULL; - - adjustediface = reinterpret_cast(reinterpret_cast(g_pInst) + info.thisptroffs); - - cur_vtptr = *reinterpret_cast( - reinterpret_cast(adjustediface) + info.vtbloffs); - cur_vfnptr = reinterpret_cast(cur_vtptr + info.vtblindex); - - - // Original function - void *origEntry = *cur_vfnptr; - - // Now generate the jump code - g_ThunkAllocator.SetRW(g_OddThunkMemory); - - // destination = src + offset + 5 - // <=> offset = destination - src - 5 - ptrdiff_t offset = reinterpret_cast(origEntry) - base - 5; - - if (offset >= INT_MIN && offset <= INT_MAX) - { - *(base + 0) = 0xE9; // offset jump, immediate operand - ptrdiff_t *offsetAddr = reinterpret_cast(base + 1); - - *offsetAddr = offset; - } - else - { - // mov rax, origEntry - *(base + 0) = 0x48; - *(base + 1) = 0xB8; - void **offsetAddr = reinterpret_cast(reinterpret_cast(base) + 2); - - *offsetAddr = origEntry; - - // jmp rax - *(base + 10) = 0xFF; - *(base + 11) = 0xE0; - } - - g_ThunkAllocator.SetRE(g_OddThunkMemory); - - g_OddThunk = reinterpret_cast(base); - - // Now set the odd thunk as new vtable entry - SourceHook::SetMemAccess((void*)cur_vfnptr, sizeof(void*), SH_MEM_READ | SH_MEM_WRITE); - *cur_vfnptr = g_OddThunk; - } - - void FreeOddThunk() - { - g_ThunkAllocator.Free(g_OddThunkMemory); - g_OddThunk = NULL; - } -} - -bool TestOddThunks(std::string &error) -{ - GET_SHPTR(g_SHPtr); - g_PLID = 1337; - - g_CallNumber = 0; - - g_pInst = MyInstanceFactory(); - - PatchFuncWithOddThunk(); - - SH_ADD_HOOK(Test, Func, g_pInst, SH_STATIC(Handler_Func_Pre1), false); - SH_ADD_HOOK(Test, Func, g_pInst, SH_STATIC(Handler_Func_Pre2), false); - - g_pInst->Func(); - - CHECK_STATES((&g_States, - // FIRST func() call - new State_Pre1_Called(), - new State_Pre2_Called(), // calls Func() again - - // SECOND func() call - new State_Pre1_Called(), - new State_Pre2_Called(), // removes hooks and calls Func() again - - // THIRD func() call - new State_Func_Called(), - - // SECOND func() call - new State_Func_Called(), - - // FIRST func() call - new State_Func_Called(), - NULL), "Part 1"); - - delete g_pInst; - FreeOddThunk(); - - return true; -} - diff --git a/utils/mmsource/core/sourcehook/test/testrecall.cpp b/utils/mmsource/core/sourcehook/test/testrecall.cpp deleted file mode 100644 index 67ddc6967..000000000 --- a/utils/mmsource/core/sourcehook/test/testrecall.cpp +++ /dev/null @@ -1,231 +0,0 @@ -#include -#include "sourcehook.h" -#include "sourcehook_test.h" -#include "testevents.h" - -// TESTRECALL -// Test modifying parameters from hook handlers - -namespace -{ - StateList g_States; - SourceHook::ISourceHook *g_SHPtr; - SourceHook::Plugin g_PLID; - - MAKE_STATE_1(State_Func1, int); - MAKE_STATE_1(State_H1_Func1, int); - MAKE_STATE_1(State_H2_Func1, int); - MAKE_STATE_2(State_HP_Func1, int, void*); - - MAKE_STATE_1(State_Func2, int); - MAKE_STATE_1(State_H1_Func2, int); - MAKE_STATE_1(State_H2_Func2, int); - MAKE_STATE_2(State_HP_Func2, int, int); - - MAKE_STATE_2(State_Func22, int, int); - MAKE_STATE_2(State_H1_Func22, int, int); - MAKE_STATE_2(State_HP1_Func22, int, int); - MAKE_STATE_2(State_HP2_Func22, int, int); - - struct Test - { - virtual void Func1(int a) - { - ADD_STATE(State_Func1(a)); - } - - virtual int Func2(int a) - { - ADD_STATE(State_Func2(a)); - return 1000; - } - - // Overloaded version - virtual int Func2(int a, int b) - { - ADD_STATE(State_Func22(a, b)); - return 0xDEADFC; - } - }; - - void Handler1_Func1(int a) - { - ADD_STATE(State_H1_Func1(a)); - RETURN_META_NEWPARAMS(MRES_IGNORED, &Test::Func1, (5)); - } - void Handler2_Func1(int a) - { - ADD_STATE(State_H2_Func1(a)); - RETURN_META_NEWPARAMS(MRES_IGNORED, &Test::Func1, (a - 5)); - } - void HandlerPost_Func1(int a) - { - ADD_STATE(State_HP_Func1(a, META_IFACEPTR(void))); - } - - - int Handler1_Func2(int a) - { - ADD_STATE(State_H1_Func2(a)); - // Pfeeehhh, ugly, I know, but I had to test it :) - RETURN_META_VALUE_NEWPARAMS(MRES_OVERRIDE, 500, - static_cast(&Test::Func2), (a - 10)); - } - - int Handler2_Func2(int a) - { - ADD_STATE(State_H2_Func2(a)); - RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, 0, - static_cast(&Test::Func2), (a - 10)); - } - - int HandlerPost_Func2(int a) - { - ADD_STATE(State_HP_Func2(a, META_RESULT_ORIG_RET(int))); - RETURN_META_VALUE(MRES_IGNORED, 0); - } - - int Handler1_Func22(int a, int b) - { - ADD_STATE(State_H1_Func22(a, b)); - RETURN_META_VALUE(MRES_IGNORED, 0); - } - - int HandlerPost1_Func22(int a, int b) - { - ADD_STATE(State_HP1_Func22(a, b)); - RETURN_META_VALUE_NEWPARAMS(MRES_IGNORED, 0, static_cast(&Test::Func2), (1, 2)); - } - - int HandlerPost1A_Func22(int a, int b) - { - ADD_STATE(State_HP1_Func22(a, b)); - RETURN_META_VALUE_NEWPARAMS(MRES_OVERRIDE, 0, static_cast(&Test::Func2), (1, 2)); - } - - int HandlerPost2_Func22(int a, int b) - { - ADD_STATE(State_HP2_Func22(a, b)); - RETURN_META_VALUE(MRES_IGNORED, 0); - } - - SH_DECL_HOOK1_void(Test, Func1, SH_NOATTRIB, 0, int); - SH_DECL_HOOK1(Test, Func2, SH_NOATTRIB, 0, int, int); - SH_DECL_HOOK2(Test, Func2, SH_NOATTRIB, 1, int, int, int); - - Test *MyTestFactory() - { - return new Test; - } -} - -bool TestRecall(std::string &error) -{ - GET_SHPTR(g_SHPtr); - g_PLID = 1337; - - Test *ptr = MyTestFactory(); - CAutoPtrDestruction apd(ptr); - - SH_ADD_HOOK(Test, Func1, ptr, SH_STATIC(Handler1_Func1), false); - SH_ADD_HOOK(Test, Func1, ptr, SH_STATIC(Handler2_Func1), false); - SH_ADD_HOOK(Test, Func1, ptr, SH_STATIC(HandlerPost_Func1), true); - - ptr->Func1(77); - - CHECK_STATES((&g_States, - new State_H1_Func1(77), - new State_H2_Func1(5), - new State_Func1(0), - new State_HP_Func1(0, ptr), - NULL), "Part 1"); - - SH_REMOVE_HOOK(Test, Func1, ptr, SH_STATIC(Handler1_Func1), false); - SH_ADD_HOOK(Test, Func1, ptr, SH_STATIC(Handler2_Func1), false); - SH_ADD_HOOK(Test, Func1, ptr, SH_STATIC(Handler2_Func1), false); - SH_ADD_HOOK(Test, Func1, ptr, SH_STATIC(Handler2_Func1), false); - - ptr->Func1(77); - - CHECK_STATES((&g_States, - new State_H2_Func1(77), - new State_H2_Func1(72), - new State_H2_Func1(67), - new State_H2_Func1(62), - new State_Func1(57), - new State_HP_Func1(57, ptr), - NULL), "Part 2"); - - SH_REMOVE_HOOK(Test, Func1, ptr, SH_STATIC(Handler2_Func1), false); - SH_REMOVE_HOOK(Test, Func1, ptr, SH_STATIC(HandlerPost_Func1), true); - - ptr->Func1(77); - - CHECK_STATES((&g_States, - new State_Func1(77), - NULL), "Part 3"); - - // Func2 - - SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(Handler1_Func2), false); - SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(HandlerPost_Func2), true); - - int a = ptr->Func2(77); - CHECK_STATES((&g_States, - new State_H1_Func2(77), - new State_Func2(67), - new State_HP_Func2(67, 1000), // 1000 because it's the ORIG_RET - NULL), "Part 4"); - - CHECK_COND(a == 500, "Part 4.1"); - - // Func2, with other handler - SH_REMOVE_HOOK(Test, Func2, ptr, SH_STATIC(Handler1_Func2), false); - SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(Handler2_Func2), false); - - a = ptr->Func2(77); - CHECK_STATES((&g_States, - new State_H2_Func2(77), - new State_Func2(67), - new State_HP_Func2(67, 1000), // 1000 because it's the ORIG_RET - NULL), "Part 4.2"); - - CHECK_COND(a == 1000, "Part 4.2.1"); // Should return 1000 as well. - - // Func22 -> post recalls - - // 1) WITH OVERRIDE - - SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(Handler1_Func22), false); - SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(HandlerPost1A_Func22), true); - SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(HandlerPost2_Func22), true); - - a = ptr->Func2(10, 11); - CHECK_STATES((&g_States, - new State_H1_Func22(10, 11), - new State_Func22(10, 11), - new State_HP1_Func22(10, 11), - new State_HP2_Func22(1, 2), - NULL), "Part 5"); - - CHECK_COND(a == 0, "Part 5.1"); - - // 2) WITH IGNORE - SH_REMOVE_HOOK(Test, Func2, ptr, SH_STATIC(HandlerPost1A_Func22), true); - SH_REMOVE_HOOK(Test, Func2, ptr, SH_STATIC(HandlerPost2_Func22), true); - - SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(HandlerPost1_Func22), true); - SH_ADD_HOOK(Test, Func2, ptr, SH_STATIC(HandlerPost2_Func22), true); - - a = ptr->Func2(10, 11); - CHECK_STATES((&g_States, - new State_H1_Func22(10, 11), - new State_Func22(10, 11), - new State_HP1_Func22(10, 11), - new State_HP2_Func22(1, 2), - NULL), "Part 5"); - - CHECK_COND(a == 0xDEADFC, "Part 5.1"); - - return true; -} diff --git a/utils/mmsource/core/sourcehook/test/testreentr.cpp b/utils/mmsource/core/sourcehook/test/testreentr.cpp deleted file mode 100644 index f96f74a25..000000000 --- a/utils/mmsource/core/sourcehook/test/testreentr.cpp +++ /dev/null @@ -1,599 +0,0 @@ -// Reentrancy test -// = calling hooks from hook handlers, etc - -#include -#include "sourcehook_test.h" -#include "testevents.h" - -namespace -{ - StateList g_States; - SourceHook::ISourceHook *g_SHPtr; - SourceHook::Plugin g_PLID; - - struct C1; - struct C2; - struct C3; - struct C4; - struct C5; - struct C6; - struct C7; - struct C8; - - C1 *g_pC1; - C2 *g_pC2; - C3 *g_pC3; - C4 *g_pC4; - C5 *g_pC5; - C6 *g_pC6; - C7 *g_pC7; - C8 *g_pC8; - - // param1: This pointer - MAKE_STATE_1(State_C1_F, C1*); - MAKE_STATE_1(State_C2_F, C2*); - MAKE_STATE_1(State_C3_F, C3*); - MAKE_STATE_1(State_C4_F, C4*); - MAKE_STATE_1(State_C5_F, C5*); - MAKE_STATE_1(State_C6_F, C6*); - MAKE_STATE_1(State_C7_F, C7*); - MAKE_STATE_1(State_C8_F, C8*); - - MAKE_STATE_1(State_C1_G, C1*); - MAKE_STATE_1(State_C2_G, C2*); - MAKE_STATE_1(State_C3_G, C3*); - MAKE_STATE_1(State_C4_G, C4*); - MAKE_STATE_1(State_C5_G, C5*); - MAKE_STATE_1(State_C6_G, C6*); - MAKE_STATE_1(State_C7_G, C7*); - MAKE_STATE_1(State_C8_G, C8*); - - MAKE_STATE_1(State_H_C1_F, C1*); - MAKE_STATE_1(State_H_C2_F, C2*); - MAKE_STATE_1(State_H_C3_F, C3*); - MAKE_STATE_1(State_H_C4_F, C4*); - MAKE_STATE_1(State_H_C5_F, C5*); - MAKE_STATE_1(State_H_C6_F, C6*); - MAKE_STATE_1(State_H_C7_F, C7*); - MAKE_STATE_1(State_H_C8_F, C8*); - - MAKE_STATE_1(State_H_C1_G, C1*); - MAKE_STATE_1(State_H_C2_G, C2*); - MAKE_STATE_1(State_H_C3_G, C3*); - MAKE_STATE_1(State_H_C4_G, C4*); - MAKE_STATE_1(State_H_C5_G, C5*); - MAKE_STATE_1(State_H_C6_G, C6*); - MAKE_STATE_1(State_H_C7_G, C7*); - MAKE_STATE_1(State_H_C8_G, C8*); - - MAKE_STATE_1(State_H2_C4_G, C4*); - - int g_TestID; - - struct C1 - { - virtual void F() - { - ADD_STATE(State_C1_F(this)); - } - virtual int G() - { - ADD_STATE(State_C1_G(this)); - return 1; - } - }; - struct C2 - { - virtual void F() - { - ADD_STATE(State_C2_F(this)); - } - virtual int G() - { - ADD_STATE(State_C2_G(this)); - return 2; - } - }; - struct C3 - { - virtual void F() - { - ADD_STATE(State_C3_F(this)); - } - virtual int G() - { - ADD_STATE(State_C3_G(this)); - return 3; - } - }; - struct C4 - { - virtual void F() - { - ADD_STATE(State_C4_F(this)); - } - virtual int G() - { - ADD_STATE(State_C4_G(this)); - return 4; - } - }; - struct C5 - { - virtual void F() - { - ADD_STATE(State_C5_F(this)); - } - virtual int G() - { - ADD_STATE(State_C5_G(this)); - return 5; - } - }; - struct C6 - { - virtual void F() - { - ADD_STATE(State_C6_F(this)); - } - virtual int G() - { - ADD_STATE(State_C6_G(this)); - return 6; - } - }; - struct C7 - { - virtual void F() - { - ADD_STATE(State_C7_F(this)); - } - virtual int G() - { - ADD_STATE(State_C7_G(this)); - return 7; - } - }; - struct C8 - { - virtual void F() - { - ADD_STATE(State_C8_F(this)); - } - virtual int G() - { - ADD_STATE(State_C8_G(this)); - return 8; - } - }; - - SH_DECL_HOOK0_void(C1, F, SH_NOATTRIB, 0); - SH_DECL_HOOK0(C1, G, SH_NOATTRIB, 0, int); - SH_DECL_HOOK0_void(C2, F, SH_NOATTRIB, 0); - SH_DECL_HOOK0(C2, G, SH_NOATTRIB, 0, int); - SH_DECL_HOOK0_void(C3, F, SH_NOATTRIB, 0); - SH_DECL_HOOK0(C3, G, SH_NOATTRIB, 0, int); - SH_DECL_HOOK0_void(C4, F, SH_NOATTRIB, 0); - SH_DECL_HOOK0(C4, G, SH_NOATTRIB, 0, int); - SH_DECL_HOOK0_void(C5, F, SH_NOATTRIB, 0); - SH_DECL_HOOK0(C5, G, SH_NOATTRIB, 0, int); - SH_DECL_HOOK0_void(C6, F, SH_NOATTRIB, 0); - SH_DECL_HOOK0(C6, G, SH_NOATTRIB, 0, int); - SH_DECL_HOOK0_void(C7, F, SH_NOATTRIB, 0); - SH_DECL_HOOK0(C7, G, SH_NOATTRIB, 0, int); - SH_DECL_HOOK0_void(C8, F, SH_NOATTRIB, 0); - SH_DECL_HOOK0(C8, G, SH_NOATTRIB, 0, int); - - void Handler_C1_F() - { - ADD_STATE(State_H_C1_F(META_IFACEPTR(C1))); - g_pC1->G(); - } - int Handler_C1_G() - { - ADD_STATE(State_H_C1_G(META_IFACEPTR(C1))); - g_pC2->F(); - return 1; - } - void Handler_C2_F() - { - ADD_STATE(State_H_C2_F(META_IFACEPTR(C2))); - g_pC2->G(); - } - int Handler_C2_G() - { - ADD_STATE(State_H_C2_G(META_IFACEPTR(C2))); - g_pC3->F(); - return 2; - } - void Handler_C3_F() - { - ADD_STATE(State_H_C3_F(META_IFACEPTR(C3))); - g_pC3->G(); - } - int Handler_C3_G() - { - ADD_STATE(State_H_C3_G(META_IFACEPTR(C3))); - g_pC4->F(); - return 3; - } - void Handler_C4_F() - { - ADD_STATE(State_H_C4_F(META_IFACEPTR(C4))); - g_pC4->G(); - } - int Handler_C4_G() - { - ADD_STATE(State_H_C4_G(META_IFACEPTR(C4))); - g_pC5->F(); - return 4; - } - int Handler2_C4_G() - { - ADD_STATE(State_H2_C4_G(META_IFACEPTR(C4))); - return 4; - } - void Handler_C5_F() - { - ADD_STATE(State_H_C5_F(META_IFACEPTR(C5))); - g_pC5->G(); - } - int Handler_C5_G() - { - ADD_STATE(State_H_C5_G(META_IFACEPTR(C5))); - g_pC6->F(); - return 5; - } - void Handler_C6_F() - { - ADD_STATE(State_H_C6_F(META_IFACEPTR(C6))); - g_pC6->G(); - } - int Handler_C6_G() - { - ADD_STATE(State_H_C6_G(META_IFACEPTR(C6))); - g_pC7->F(); - return 6; - } - void Handler_C7_F() - { - if (g_TestID == 1 || g_TestID == 2) - SH_REMOVE_HOOK(C4, G, g_pC4, SH_STATIC(Handler2_C4_G), false); - if (g_TestID == 2) - SH_REMOVE_HOOK(C4, G, g_pC4, SH_STATIC(Handler_C4_G), false); - - ADD_STATE(State_H_C7_F(META_IFACEPTR(C7))); - g_pC7->G(); - } - int Handler_C7_G() - { - ADD_STATE(State_H_C7_G(META_IFACEPTR(C7))); - g_pC8->F(); - return 7; - } - void Handler_C8_F() - { - ADD_STATE(State_H_C8_F(META_IFACEPTR(C8))); - g_pC8->G(); - } - int Handler_C8_G() - { - ADD_STATE(State_H_C8_G(META_IFACEPTR(C8))); - return 8; - } - - C1 g_C1; - C2 g_C2; - C3 g_C3; - C4 g_C4; - C5 g_C5; - C6 g_C6; - C7 g_C7; - C8 g_C8; -} - -bool TestReentr(std::string &error) -{ - GET_SHPTR(g_SHPtr); - g_PLID = 1337; - - g_pC1 = &g_C1; - g_pC2 = &g_C2; - g_pC3 = &g_C3; - g_pC4 = &g_C4; - g_pC5 = &g_C5; - g_pC6 = &g_C6; - g_pC7 = &g_C7; - g_pC8 = &g_C8; - - SH_ADD_HOOK(C1, F, g_pC1, SH_STATIC(Handler_C1_F), false); - SH_ADD_HOOK(C1, G, g_pC1, SH_STATIC(Handler_C1_G), false); - SH_ADD_HOOK(C2, F, g_pC2, SH_STATIC(Handler_C2_F), false); - SH_ADD_HOOK(C2, G, g_pC2, SH_STATIC(Handler_C2_G), false); - SH_ADD_HOOK(C3, F, g_pC3, SH_STATIC(Handler_C3_F), false); - SH_ADD_HOOK(C3, G, g_pC3, SH_STATIC(Handler_C3_G), false); - SH_ADD_HOOK(C4, F, g_pC4, SH_STATIC(Handler_C4_F), false); - SH_ADD_HOOK(C4, G, g_pC4, SH_STATIC(Handler_C4_G), false); - SH_ADD_HOOK(C5, F, g_pC5, SH_STATIC(Handler_C5_F), false); - SH_ADD_HOOK(C5, G, g_pC5, SH_STATIC(Handler_C5_G), false); - SH_ADD_HOOK(C6, F, g_pC6, SH_STATIC(Handler_C6_F), false); - SH_ADD_HOOK(C6, G, g_pC6, SH_STATIC(Handler_C6_G), false); - SH_ADD_HOOK(C7, F, g_pC7, SH_STATIC(Handler_C7_F), false); - SH_ADD_HOOK(C7, G, g_pC7, SH_STATIC(Handler_C7_G), false); - SH_ADD_HOOK(C8, F, g_pC8, SH_STATIC(Handler_C8_F), false); - SH_ADD_HOOK(C8, G, g_pC8, SH_STATIC(Handler_C8_G), false); - - g_pC1->F(); - - CHECK_STATES((&g_States, - new State_H_C1_F(g_pC1), - new State_H_C1_G(g_pC1), - new State_H_C2_F(g_pC2), - new State_H_C2_G(g_pC2), - new State_H_C3_F(g_pC3), - new State_H_C3_G(g_pC3), - new State_H_C4_F(g_pC4), - new State_H_C4_G(g_pC4), - new State_H_C5_F(g_pC5), - new State_H_C5_G(g_pC5), - new State_H_C6_F(g_pC6), - new State_H_C6_G(g_pC6), - new State_H_C7_F(g_pC7), - new State_H_C7_G(g_pC7), - new State_H_C8_F(g_pC8), - new State_H_C8_G(g_pC8), - new State_C8_G(g_pC8), - new State_C8_F(g_pC8), - new State_C7_G(g_pC7), - new State_C7_F(g_pC7), - new State_C6_G(g_pC6), - new State_C6_F(g_pC6), - new State_C5_G(g_pC5), - new State_C5_F(g_pC5), - new State_C4_G(g_pC4), - new State_C4_F(g_pC4), - new State_C3_G(g_pC3), - new State_C3_F(g_pC3), - new State_C2_G(g_pC2), - new State_C2_F(g_pC2), - new State_C1_G(g_pC1), - new State_C1_F(g_pC1), - NULL), "1"); - - - SH_ADD_HOOK(C4, G, g_pC4, SH_STATIC(Handler2_C4_G), false); - - g_pC1->F(); - - CHECK_STATES((&g_States, - new State_H_C1_F(g_pC1), - new State_H_C1_G(g_pC1), - new State_H_C2_F(g_pC2), - new State_H_C2_G(g_pC2), - new State_H_C3_F(g_pC3), - new State_H_C3_G(g_pC3), - new State_H_C4_F(g_pC4), - new State_H_C4_G(g_pC4), - new State_H_C5_F(g_pC5), - new State_H_C5_G(g_pC5), - new State_H_C6_F(g_pC6), - new State_H_C6_G(g_pC6), - new State_H_C7_F(g_pC7), - new State_H_C7_G(g_pC7), - new State_H_C8_F(g_pC8), - new State_H_C8_G(g_pC8), - new State_C8_G(g_pC8), - new State_C8_F(g_pC8), - new State_C7_G(g_pC7), - new State_C7_F(g_pC7), - new State_C6_G(g_pC6), - new State_C6_F(g_pC6), - new State_C5_G(g_pC5), - new State_C5_F(g_pC5), - new State_H2_C4_G(g_pC4), - new State_C4_G(g_pC4), - new State_C4_F(g_pC4), - new State_C3_G(g_pC3), - new State_C3_F(g_pC3), - new State_C2_G(g_pC2), - new State_C2_F(g_pC2), - new State_C1_G(g_pC1), - new State_C1_F(g_pC1), - NULL), "2"); - - g_pC1->F(); - - CHECK_STATES((&g_States, - new State_H_C1_F(g_pC1), - new State_H_C1_G(g_pC1), - new State_H_C2_F(g_pC2), - new State_H_C2_G(g_pC2), - new State_H_C3_F(g_pC3), - new State_H_C3_G(g_pC3), - new State_H_C4_F(g_pC4), - new State_H_C4_G(g_pC4), - new State_H_C5_F(g_pC5), - new State_H_C5_G(g_pC5), - new State_H_C6_F(g_pC6), - new State_H_C6_G(g_pC6), - new State_H_C7_F(g_pC7), - new State_H_C7_G(g_pC7), - new State_H_C8_F(g_pC8), - new State_H_C8_G(g_pC8), - new State_C8_G(g_pC8), - new State_C8_F(g_pC8), - new State_C7_G(g_pC7), - new State_C7_F(g_pC7), - new State_C6_G(g_pC6), - new State_C6_F(g_pC6), - new State_C5_G(g_pC5), - new State_C5_F(g_pC5), - new State_H2_C4_G(g_pC4), - new State_C4_G(g_pC4), - new State_C4_F(g_pC4), - new State_C3_G(g_pC3), - new State_C3_F(g_pC3), - new State_C2_G(g_pC2), - new State_C2_F(g_pC2), - new State_C1_G(g_pC1), - new State_C1_F(g_pC1), - NULL), "3"); - - g_TestID = 1; - - g_pC1->F(); - - CHECK_STATES((&g_States, - new State_H_C1_F(g_pC1), - new State_H_C1_G(g_pC1), - new State_H_C2_F(g_pC2), - new State_H_C2_G(g_pC2), - new State_H_C3_F(g_pC3), - new State_H_C3_G(g_pC3), - new State_H_C4_F(g_pC4), - new State_H_C4_G(g_pC4), - new State_H_C5_F(g_pC5), - new State_H_C5_G(g_pC5), - new State_H_C6_F(g_pC6), - new State_H_C6_G(g_pC6), - new State_H_C7_F(g_pC7), - new State_H_C7_G(g_pC7), - new State_H_C8_F(g_pC8), - new State_H_C8_G(g_pC8), - new State_C8_G(g_pC8), - new State_C8_F(g_pC8), - new State_C7_G(g_pC7), - new State_C7_F(g_pC7), - new State_C6_G(g_pC6), - new State_C6_F(g_pC6), - new State_C5_G(g_pC5), - new State_C5_F(g_pC5), - new State_C4_G(g_pC4), - new State_C4_F(g_pC4), - new State_C3_G(g_pC3), - new State_C3_F(g_pC3), - new State_C2_G(g_pC2), - new State_C2_F(g_pC2), - new State_C1_G(g_pC1), - new State_C1_F(g_pC1), - NULL), "4"); - - g_pC1->F(); - - CHECK_STATES((&g_States, - new State_H_C1_F(g_pC1), - new State_H_C1_G(g_pC1), - new State_H_C2_F(g_pC2), - new State_H_C2_G(g_pC2), - new State_H_C3_F(g_pC3), - new State_H_C3_G(g_pC3), - new State_H_C4_F(g_pC4), - new State_H_C4_G(g_pC4), - new State_H_C5_F(g_pC5), - new State_H_C5_G(g_pC5), - new State_H_C6_F(g_pC6), - new State_H_C6_G(g_pC6), - new State_H_C7_F(g_pC7), - new State_H_C7_G(g_pC7), - new State_H_C8_F(g_pC8), - new State_H_C8_G(g_pC8), - new State_C8_G(g_pC8), - new State_C8_F(g_pC8), - new State_C7_G(g_pC7), - new State_C7_F(g_pC7), - new State_C6_G(g_pC6), - new State_C6_F(g_pC6), - new State_C5_G(g_pC5), - new State_C5_F(g_pC5), - new State_C4_G(g_pC4), - new State_C4_F(g_pC4), - new State_C3_G(g_pC3), - new State_C3_F(g_pC3), - new State_C2_G(g_pC2), - new State_C2_F(g_pC2), - new State_C1_G(g_pC1), - new State_C1_F(g_pC1), - NULL), "5"); - - - - SH_ADD_HOOK(C4, G, g_pC4, SH_STATIC(Handler2_C4_G), false); - - g_TestID = 2; - - g_pC1->F(); - - CHECK_STATES((&g_States, - new State_H_C1_F(g_pC1), - new State_H_C1_G(g_pC1), - new State_H_C2_F(g_pC2), - new State_H_C2_G(g_pC2), - new State_H_C3_F(g_pC3), - new State_H_C3_G(g_pC3), - new State_H_C4_F(g_pC4), - new State_H_C4_G(g_pC4), - new State_H_C5_F(g_pC5), - new State_H_C5_G(g_pC5), - new State_H_C6_F(g_pC6), - new State_H_C6_G(g_pC6), - new State_H_C7_F(g_pC7), - new State_H_C7_G(g_pC7), - new State_H_C8_F(g_pC8), - new State_H_C8_G(g_pC8), - new State_C8_G(g_pC8), - new State_C8_F(g_pC8), - new State_C7_G(g_pC7), - new State_C7_F(g_pC7), - new State_C6_G(g_pC6), - new State_C6_F(g_pC6), - new State_C5_G(g_pC5), - new State_C5_F(g_pC5), - new State_C4_G(g_pC4), - new State_C4_F(g_pC4), - new State_C3_G(g_pC3), - new State_C3_F(g_pC3), - new State_C2_G(g_pC2), - new State_C2_F(g_pC2), - new State_C1_G(g_pC1), - new State_C1_F(g_pC1), - NULL), "6"); - - g_pC1->F(); - - CHECK_STATES((&g_States, - new State_H_C1_F(g_pC1), - new State_H_C1_G(g_pC1), - new State_H_C2_F(g_pC2), - new State_H_C2_G(g_pC2), - new State_H_C3_F(g_pC3), - new State_H_C3_G(g_pC3), - new State_H_C4_F(g_pC4), - new State_C4_G(g_pC4), - new State_C4_F(g_pC4), - new State_C3_G(g_pC3), - new State_C3_F(g_pC3), - new State_C2_G(g_pC2), - new State_C2_F(g_pC2), - new State_C1_G(g_pC1), - new State_C1_F(g_pC1), - NULL), "7"); - - SH_REMOVE_HOOK(C1, F, g_pC1, SH_STATIC(Handler_C1_F), false); - SH_REMOVE_HOOK(C1, G, g_pC1, SH_STATIC(Handler_C1_G), false); - SH_REMOVE_HOOK(C2, F, g_pC2, SH_STATIC(Handler_C2_F), false); - SH_REMOVE_HOOK(C2, G, g_pC2, SH_STATIC(Handler_C2_G), false); - SH_REMOVE_HOOK(C3, F, g_pC3, SH_STATIC(Handler_C3_F), false); - SH_REMOVE_HOOK(C3, G, g_pC3, SH_STATIC(Handler_C3_G), false); - SH_REMOVE_HOOK(C4, F, g_pC4, SH_STATIC(Handler_C4_F), false); - SH_REMOVE_HOOK(C4, G, g_pC4, SH_STATIC(Handler_C4_G), false); - SH_REMOVE_HOOK(C5, F, g_pC5, SH_STATIC(Handler_C5_F), false); - SH_REMOVE_HOOK(C5, G, g_pC5, SH_STATIC(Handler_C5_G), false); - SH_REMOVE_HOOK(C6, F, g_pC6, SH_STATIC(Handler_C6_F), false); - SH_REMOVE_HOOK(C6, G, g_pC6, SH_STATIC(Handler_C6_G), false); - SH_REMOVE_HOOK(C7, F, g_pC7, SH_STATIC(Handler_C7_F), false); - SH_REMOVE_HOOK(C7, G, g_pC7, SH_STATIC(Handler_C7_G), false); - SH_REMOVE_HOOK(C8, F, g_pC8, SH_STATIC(Handler_C8_F), false); - SH_REMOVE_HOOK(C8, G, g_pC8, SH_STATIC(Handler_C8_G), false); - - return true; -} diff --git a/utils/mmsource/core/sourcehook/test/testref.cpp b/utils/mmsource/core/sourcehook/test/testref.cpp deleted file mode 100644 index 97d5789de..000000000 --- a/utils/mmsource/core/sourcehook/test/testref.cpp +++ /dev/null @@ -1,227 +0,0 @@ -#include "testevents.h" -#include "sourcehook_test.h" - -// References and private copy constructors and stuff like that! - -/* -BAILOPAN, 29.04.2006 21:51 : -onoto-san, interesting error from VS -we have this function: -void GabHaben(ISomething &sth); - -SomethingDerived sth; -and SH_CALL(cc, &WHAT::GabHaben)(sth); -"No copy constructor available for class 'SomethingDerived'" -*/ - - -namespace -{ - StateList g_States; - SourceHook::ISourceHook *g_SHPtr; - SourceHook::Plugin g_PLID; - - MAKE_STATE_1(State_Result, int); - MAKE_STATE_1(State_Result_InHook, int); - - MAKE_STATE_2(State_F2_Called, int, int); - MAKE_STATE_2(State_F2_Handler_Called, int, int); - - struct POD - { - int a; - int b; - int c; - int d; - int e; - int f; - }; - - class CBase - { - // Private copy constructor! - CBase(CBase &other) - { - } - public: - CBase() - { - } - - virtual int Func() - { - return 0; - } - }; - - class CDerived : public CBase - { - virtual int Func() - { - return 10; - } - }; - - // Complicated derived shit ! - class COtherWeirdBase - { - int member; - }; - class CDerived2 : private COtherWeirdBase, public CBase - { - int m_Return; - public: - CDerived2(int a) : m_Return(a) - { - } - - virtual int Func() - { - return m_Return; - } - }; - - class CHello - { - public: - virtual int Func(CBase &sth) - { - return sth.Func(); - } - - virtual void F2(POD a) - { - } - }; - - - class Test2 - { - public: - virtual void F1(){} - virtual void F2(POD &a) - { - ADD_STATE(State_F2_Called(a.a, a.b)); - } - }; - - class CHook - { - public: - virtual int Func(CBase &sth) - { - ADD_STATE(State_Result_InHook(sth.Func())); - RETURN_META_VALUE(MRES_SUPERCEDE, 20); - } - - virtual void F2(POD &a) - { - ADD_STATE(State_F2_Handler_Called(a.a, a.b)); - } - - virtual void F21(POD a) - { - } - }; - - SH_DECL_HOOK1(CHello, Func, SH_NOATTRIB, 0, int, CBase&); - SH_DECL_HOOK1_void(CHello, F2, SH_NOATTRIB, 0, POD); - SH_DECL_HOOK1_void(Test2, F2, SH_NOATTRIB, 0, POD&); - - CHello *MyInstanceFactory() - { - return new CHello; - } -} - - -bool TestRef(std::string &error) -{ - GET_SHPTR(g_SHPtr); - g_PLID = 1; - - CBase base; - CDerived der; - CDerived2 der2(11); - CDerived2 der3(12); - CHello *pHello = MyInstanceFactory(); - Test2 *pTest2 = new Test2; - CAutoPtrDestruction apd(pHello); - CAutoPtrDestruction apd2(pTest2); - CHook hook; - - SourceHook::CallClass *cc = SH_GET_CALLCLASS(pHello); - - ADD_STATE(State_Result(pHello->Func(base))); - ADD_STATE(State_Result(pHello->Func(der))); - ADD_STATE(State_Result(pHello->Func(der2))); - ADD_STATE(State_Result(pHello->Func(der3))); - - CHECK_STATES((&g_States, - new State_Result(0), - new State_Result(10), - new State_Result(11), - new State_Result(12), - NULL), "Part 1"); - - ADD_STATE(State_Result(SH_CALL(cc, &CHello::Func)(base))); - ADD_STATE(State_Result(SH_CALL(cc, &CHello::Func)(der))); - ADD_STATE(State_Result(SH_CALL(cc, &CHello::Func)(der2))); - ADD_STATE(State_Result(SH_CALL(cc, &CHello::Func)(der3))); - - CHECK_STATES((&g_States, - new State_Result(0), - new State_Result(10), - new State_Result(11), - new State_Result(12), - NULL), "Part 2"); - - SH_ADD_HOOK(CHello, Func, pHello, SH_MEMBER(&hook, &CHook::Func), false); - - ADD_STATE(State_Result(pHello->Func(base))); - ADD_STATE(State_Result(pHello->Func(der))); - ADD_STATE(State_Result(pHello->Func(der2))); - ADD_STATE(State_Result(pHello->Func(der3))); - - CHECK_STATES((&g_States, - new State_Result_InHook(0), - new State_Result(20), - new State_Result_InHook(10), - new State_Result(20), - new State_Result_InHook(11), - new State_Result(20), - new State_Result_InHook(12), - new State_Result(20), - NULL), "Part 3"); - - ADD_STATE(State_Result(SH_CALL(cc, &CHello::Func)(base))); - ADD_STATE(State_Result(SH_CALL(cc, &CHello::Func)(der))); - ADD_STATE(State_Result(SH_CALL(cc, &CHello::Func)(der2))); - ADD_STATE(State_Result(SH_CALL(cc, &CHello::Func)(der3))); - - CHECK_STATES((&g_States, - new State_Result(0), - new State_Result(10), - new State_Result(11), - new State_Result(12), - NULL), "Part 4"); - - // Check for correct ref proto handling - - SH_ADD_HOOK(CHello, F2, pHello, SH_MEMBER(&hook, &CHook::F21), false); - SH_ADD_HOOK(Test2, F2, pTest2, SH_MEMBER(&hook, &CHook::F2), false); - - POD pod = { 1, 2 }; - pTest2->F2(pod); - - int a = 5; - - pHello->F2(pod); - - CHECK_STATES((&g_States, - new State_F2_Handler_Called(1, 2), - new State_F2_Called(1, 2), - NULL), "Part 5"); - - return true; -} diff --git a/utils/mmsource/core/sourcehook/test/testrefret.cpp b/utils/mmsource/core/sourcehook/test/testrefret.cpp deleted file mode 100644 index 4fad5b32b..000000000 --- a/utils/mmsource/core/sourcehook/test/testrefret.cpp +++ /dev/null @@ -1,319 +0,0 @@ -#include "testevents.h" -#include "sourcehook_test.h" - -// Tests support for functions which return references - -namespace -{ - StateList g_States; - SourceHook::ISourceHook *g_SHPtr; - SourceHook::Plugin g_PLID; - - MAKE_STATE_1(State_Func1_Pre1, int*); // p1: the ref Func1_Pre1 is going to return - MAKE_STATE_3(State_Func1_Pre2, META_RES, int*, int*); // p1: current status - // p2: override ret - // p3: what this handler is going to supercede with - MAKE_STATE_1(State_Func1, int*); // p1: the ref Func1 is going to return - MAKE_STATE_2(State_Func1_Post1, int*, int*); // p1: orig_ret; p2: override_ret - MAKE_STATE_1(State_Func1_Post2, int*); // p1: what it's going to return - MAKE_STATE_1(State_Func1_Ret, int*); // p1: the ref it returned - - - MAKE_STATE_2(State_Func2_Pre1, int, const int*); // p1: func's p1; p2: what it's going to ret - MAKE_STATE_2(State_Func2, int, const int*); // p1: func's p1; p2: what it's going to ret - MAKE_STATE_3(State_Func2_Post1, int, const int*, const int*); // p1: func's p1; p2: orig ret; p3: override ret - MAKE_STATE_1(State_Func2_Ret, const int*); // p1: ret - - int g_Var; - - class Test - { - public: - int m_Var1; - int m_Var2; - - Test() : m_Var1(87) - { - } - - virtual int& Func1() - { - ADD_STATE(State_Func1(&m_Var1)); - return m_Var1; - } - virtual const int& Func2(int p1) - { - ADD_STATE(State_Func2(p1, &m_Var2)); - m_Var2 = p1; - return m_Var2; - } - }; - - SH_DECL_HOOK0(Test, Func1, SH_NOATTRIB, 0, int&); - SH_DECL_MANUALHOOK0(Manual_Test_Func1, 0, 0, 0, int&); - SH_DECL_HOOK1(Test, Func2, SH_NOATTRIB, 0, const int&, int); - SH_DECL_MANUALHOOK1(Manual_Test_Func2, 1, 0, 0, const int&, int); - - class CHook - { - public: - int m_Var; - virtual int& Func1_Pre1() - { - ADD_STATE(State_Func1_Pre1(&m_Var)); - RETURN_META_VALUE(MRES_OVERRIDE, m_Var); - } - virtual int &Func1_Pre2() - { - int &overrideret = META_RESULT_OVERRIDE_RET(int&); - overrideret = 1337; - ADD_STATE(State_Func1_Pre2(META_RESULT_STATUS, &overrideret, &g_Var)); - RETURN_META_VALUE(MRES_SUPERCEDE, g_Var); - } - virtual int& Func1_Post1() - { - ADD_STATE(State_Func1_Post1(&META_RESULT_ORIG_RET(int&), &META_RESULT_OVERRIDE_RET(int&))); - RETURN_META_NOREF(MRES_IGNORED, int&); - } - virtual int& Func1_Post2() - { - ADD_STATE(State_Func1_Post2(&m_Var)); - RETURN_META_VALUE(MRES_OVERRIDE, m_Var); - } - - virtual const int& Func2_PreRecall_OverrideRet_Normal(int p1) - { - ADD_STATE(State_Func2_Pre1(p1, &m_Var)); - RETURN_META_VALUE_NEWPARAMS(MRES_OVERRIDE, m_Var, static_cast(&Test::Func2), (1337)); - } - - virtual const int& Func2_PreRecall_OverrideRet_Manual(int p1) - { - ADD_STATE(State_Func2_Pre1(p1, &m_Var)); - RETURN_META_VALUE_MNEWPARAMS(MRES_OVERRIDE, m_Var, Manual_Test_Func2, (1337)); - } - - virtual const int& Func2_Post1(int p1) - { - ADD_STATE(State_Func2_Post1(p1, &META_RESULT_ORIG_RET(int&), &META_RESULT_OVERRIDE_RET(int&))); - RETURN_META_NOREF(MRES_IGNORED, const int&); - } - }; - - Test *MyTestFactory() - { - return new Test; - } -} - -class TesterRefRet -{ -public: - Test *pTest; - CHook hook; - - TesterRefRet() - { - pTest = NULL; - } - - bool doTests(std::string &error) - { - GET_SHPTR(g_SHPtr); - g_PLID = 1; - - pTest = MyTestFactory(); - CAutoPtrDestruction apd(pTest); - - int &ret1 = pTest->Func1(); - ADD_STATE(State_Func1_Ret(&ret1)); - - CHECK_STATES((&g_States, - new State_Func1(&pTest->m_Var1), - new State_Func1_Ret(&pTest->m_Var1), - NULL), "Part 1"); - - // Now add Func1_Pre1, which supercedes and returns hook.m_Var - AddHook__Test_Func1__Func1_Pre(); - - int &ret2 = pTest->Func1(); - ADD_STATE(State_Func1_Ret(&ret2)); - - CHECK_STATES((&g_States, - new State_Func1_Pre1(&hook.m_Var), // Pre1 says that it's going to override with hook.m_Var - new State_Func1(&pTest->m_Var1), // Function says that it's going to return pTest->m_Var1 - new State_Func1_Ret(&hook.m_Var), // hook.m_Var is returned - NULL), "Part 2"); - - // Now add Func1_Post1, which only reports orig ret and override ret - AddHook__Test_Func1__Func1_Post(); - - int &ret3 = pTest->Func1(); - ADD_STATE(State_Func1_Ret(&ret3)); - - CHECK_STATES((&g_States, - new State_Func1_Pre1(&hook.m_Var), // Pre1 says that it's going to override with hook.m_Var - new State_Func1(&pTest->m_Var1), // Function says that it's going to return pTest->m_Var1 - new State_Func1_Post1(&pTest->m_Var1, &hook.m_Var), // origret(=p1) is what it wanted to - // return, overrideret(=p2) is pre1's var - new State_Func1_Ret(&hook.m_Var), // hook.m_Var is returned - NULL), "Part 3"); - - // Now add Func1_Pre2, which supercedes and returns g_Var (it also sets the override ret from pre1 to 1337) - // and add Func1_Post2, which overrides and returns hook.m_Var again. - - AddHook__Test_Func1__Func1_Pre2(); - AddHook__Test_Func1__Func1_Post2(); - - int &ret4 = pTest->Func1(); - ADD_STATE(State_Func1_Ret(&ret4)); - - CHECK_STATES((&g_States, - new State_Func1_Pre1(&hook.m_Var), // Pre1 says that it's going to override with hook.m_Var - new State_Func1_Pre2(MRES_OVERRIDE, // current status - &hook.m_Var, // override ret (which it set to 1337) - &g_Var), // what it's going to ret, AND supercede with - - new State_Func1_Post1(&g_Var, &g_Var), // origret(=p1) is what pre2 superceded with, - // so overrideret(=p2) has to be the same - new State_Func1_Post2(&hook.m_Var), // post2 is going to override with hook.m_Var again - new State_Func1_Ret(&hook.m_Var), // ==>>> hook.m_Var is returned - NULL), "Part 4"); - - CHECK_COND(hook.m_Var == 1337, "Part 4.1"); - - // Through a callclass - SourceHook::CallClass *cc1 = SH_GET_CALLCLASS(pTest); - int &ret5 = SH_CALL(cc1, &Test::Func1)(); - ADD_STATE(State_Func1_Ret(&ret5)); - - CHECK_STATES((&g_States, - new State_Func1(&pTest->m_Var1), - new State_Func1_Ret(&pTest->m_Var1), - NULL), "Part 5"); - - SH_RELEASE_CALLCLASS(cc1); - - //////////////////////////////////////////////////////////////////////////////////////// - // Func2 tests - const int &ret21 = pTest->Func2(500); - ADD_STATE(State_Func2_Ret(&ret21)); - - CHECK_STATES((&g_States, - new State_Func2(500, &pTest->m_Var2), - new State_Func2_Ret(&pTest->m_Var2), - NULL), "Part 6"); - - AddHook__Test_Func2__Func2_Pre1(); - AddHook__Test_Func2__Func2_Post1(); - - const int &ret22 = pTest->Func2(500); - ADD_STATE(State_Func2_Ret(&ret22)); - - CHECK_STATES((&g_States, - new State_Func2_Pre1(500, &hook.m_Var), // p1 was 500; it's going to override with hook.m_Var; and also change p1 to 1337 - new State_Func2(1337, &pTest->m_Var2), // p1 was 1337; it's going to ret pTest->m_Var2 - new State_Func2_Post1(1337, // p1 was 1337 - &pTest->m_Var2, // orig ret was pTest->m_Var2 - &hook.m_Var), // override ret was hook.m_Var - new State_Func2_Ret(&hook.m_Var), // really returned hook.m_Var - NULL), "Part 7"); - - return true; - } - - virtual void AddHook__Test_Func1__Func1_Pre() = 0; - virtual void AddHook__Test_Func1__Func1_Post() = 0; - - virtual void AddHook__Test_Func1__Func1_Pre2() = 0; - virtual void AddHook__Test_Func1__Func1_Post2() = 0; - - virtual void AddHook__Test_Func2__Func2_Pre1() = 0; - virtual void AddHook__Test_Func2__Func2_Post1() = 0; -}; - -class TesterRefRetNonManual : public TesterRefRet -{ -public: - void AddHook__Test_Func1__Func1_Pre() - { - SH_ADD_HOOK(Test, Func1, pTest, SH_MEMBER(&hook, &CHook::Func1_Pre1), false); - } - - void AddHook__Test_Func1__Func1_Post() - { - SH_ADD_HOOK(Test, Func1, pTest, SH_MEMBER(&hook, &CHook::Func1_Post1), true); - } - - void AddHook__Test_Func1__Func1_Pre2() - { - SH_ADD_HOOK(Test, Func1, pTest, SH_MEMBER(&hook, &CHook::Func1_Pre2), false); - } - - void AddHook__Test_Func1__Func1_Post2() - { - SH_ADD_HOOK(Test, Func1, pTest, SH_MEMBER(&hook, &CHook::Func1_Post2), true); - } - - void AddHook__Test_Func2__Func2_Pre1() - { - SH_ADD_HOOK(Test, Func2, pTest, SH_MEMBER(&hook, &CHook::Func2_PreRecall_OverrideRet_Normal), false); - } - - void AddHook__Test_Func2__Func2_Post1() - { - SH_ADD_HOOK(Test, Func2, pTest, SH_MEMBER(&hook, &CHook::Func2_Post1), true); - } -}; - -class TesterRefRetManual : public TesterRefRet -{ -public: - void AddHook__Test_Func1__Func1_Pre() - { - SH_ADD_MANUALHOOK(Manual_Test_Func1, pTest, SH_MEMBER(&hook, &CHook::Func1_Pre1), false); - } - - void AddHook__Test_Func1__Func1_Post() - { - SH_ADD_MANUALHOOK(Manual_Test_Func1, pTest, SH_MEMBER(&hook, &CHook::Func1_Post1), true); - } - - void AddHook__Test_Func1__Func1_Pre2() - { - SH_ADD_MANUALHOOK(Manual_Test_Func1, pTest, SH_MEMBER(&hook, &CHook::Func1_Pre2), false); - } - - void AddHook__Test_Func1__Func1_Post2() - { - SH_ADD_MANUALHOOK(Manual_Test_Func1, pTest, SH_MEMBER(&hook, &CHook::Func1_Post2), true); - } - - void AddHook__Test_Func2__Func2_Pre1() - { - SH_ADD_MANUALHOOK(Manual_Test_Func2, pTest, SH_MEMBER(&hook, &CHook::Func2_PreRecall_OverrideRet_Manual), false); - } - - void AddHook__Test_Func2__Func2_Post1() - { - SH_ADD_MANUALHOOK(Manual_Test_Func2, pTest, SH_MEMBER(&hook, &CHook::Func2_Post1), true); - } -}; - -bool TestRefRet(std::string &error) -{ - TesterRefRet *testerNonManual = new TesterRefRetNonManual; - bool resNonManual = testerNonManual->doTests(error); - if (!resNonManual) - { - return false; - } - - TesterRefRet *testerManual = new TesterRefRetManual; - bool resManual = testerManual->doTests(error); - if (!resManual) - { - return false; - } - return true; -} diff --git a/utils/mmsource/core/sourcehook/test/testvphooks.cpp b/utils/mmsource/core/sourcehook/test/testvphooks.cpp deleted file mode 100644 index 3aaf51fed..000000000 --- a/utils/mmsource/core/sourcehook/test/testvphooks.cpp +++ /dev/null @@ -1,273 +0,0 @@ -#include -#include "sourcehook.h" -#include "sourcehook_test.h" -#include "testevents.h" - -// TEST VP HOOKS -// Test vfnptr-wide hooks - -namespace -{ - StateList g_States; - SourceHook::ISourceHook *g_SHPtr; - SourceHook::Plugin g_PLID; - - class IBase; - - MAKE_STATE_1(State_D1_Func1, IBase *); - MAKE_STATE_1(State_D2_Func1, IBase *); - MAKE_STATE_1(State_Func1_Pre, IBase *); - MAKE_STATE_1(State_Func1_Post, IBase *); - - MAKE_STATE_1(State_D1_Func2, IBase *); - MAKE_STATE_1(State_D2_Func2, IBase *); - MAKE_STATE_1(State_Func2_Pre, IBase *); - MAKE_STATE_1(State_Func2_Post, IBase *); - - MAKE_STATE_2(State_D1_Func3, IBase *, int); - MAKE_STATE_2(State_D2_Func3, IBase *, int); - MAKE_STATE_2(State_Func3_Pre, IBase *, int); - MAKE_STATE_2(State_Func3_Post, IBase *, int); - - class IBase - { - public: - virtual void Func1() = 0; - virtual void Func2() = 0; - virtual void Func3(int x) = 0; - }; - - class CDerived1 : public IBase - { - public: - virtual void Func1() - { - ADD_STATE(State_D1_Func1(this)); - } - virtual void Func2() - { - ADD_STATE(State_D1_Func2(this)); - } - virtual void Func3(int x) - { - ADD_STATE(State_D1_Func3(this, x)); - } - }; - - class CDerived2 : public IBase - { - public: - virtual void Func1() - { - ADD_STATE(State_D2_Func1(this)); - } - virtual void Func2() - { - ADD_STATE(State_D2_Func2(this)); - } - virtual void Func3(int x) - { - ADD_STATE(State_D2_Func3(this, x)); - } - }; - - void Handler_Func1_Pre() - { - ADD_STATE(State_Func1_Pre(META_IFACEPTR(IBase))); - } - void Handler_Func1_Post() - { - ADD_STATE(State_Func1_Post(META_IFACEPTR(IBase))); - } - int g_F2_Pre_HookToRemove = 0; - void Handler_Func2_Pre() - { - ADD_STATE(State_Func2_Pre(META_IFACEPTR(IBase))); - SH_REMOVE_HOOK_ID(g_F2_Pre_HookToRemove); - } - void Handler_Func2_Post() - { - ADD_STATE(State_Func2_Post(META_IFACEPTR(IBase))); - } - - - void Handler_Func3_Pre(int x) - { - ADD_STATE(State_Func3_Pre(META_IFACEPTR(IBase), x)); - - RETURN_META_NEWPARAMS(MRES_IGNORED, &IBase::Func3, (x+1)); - } - void Handler_Func3_Post(int x) - { - ADD_STATE(State_Func3_Post(META_IFACEPTR(IBase), x)); - } - - SH_DECL_HOOK0_void(IBase, Func1, SH_NOATTRIB, 0); - SH_DECL_HOOK0_void(IBase, Func2, SH_NOATTRIB, 0); - SH_DECL_HOOK1_void(IBase, Func3, SH_NOATTRIB, 0, int); - - SH_DECL_MANUALHOOK1_void(IBase_Func3_Manual, 2, 0, 0, int); -} - -// Clang is smart enough to see: -// CDerived1 a; -// IBase *p = &a; -// p->Func1() -// -// May bypass the vtable, since p_d1i2 has exactly one assignment. We try to -// defeat the analysis that produces this result here. -template -T defeat_ssa(const T& t) -{ - return time(NULL) ? t : nullptr; -} - -bool TestVPHooks(std::string &error) -{ - GET_SHPTR(g_SHPtr); - g_PLID = 1337; - - CDerived1 d1i1; - CDerived1 d1i2; - CDerived2 d2i1; - - IBase *p_d1i1 = defeat_ssa(&d1i1); - IBase *p_d1i2 = defeat_ssa(&d1i2); - IBase *p_d2i1 = defeat_ssa(&d2i1); - - int hook1 = SH_ADD_VPHOOK(IBase, Func1, p_d1i1, SH_STATIC(Handler_Func1_Pre), false); - - p_d1i1->Func1(); - p_d1i2->Func1(); - p_d2i1->Func1(); - - CHECK_STATES((&g_States, - new State_Func1_Pre(p_d1i1), - new State_D1_Func1(p_d1i1), - - new State_Func1_Pre(p_d1i2), - new State_D1_Func1(p_d1i2), - - new State_D2_Func1(p_d2i1), - NULL), "Part 1"); - - SH_REMOVE_HOOK_ID(hook1); - - p_d1i1->Func1(); - p_d1i2->Func1(); - p_d2i1->Func1(); - - CHECK_STATES((&g_States, - new State_D1_Func1(p_d1i1), - - new State_D1_Func1(p_d1i2), - - new State_D2_Func1(p_d2i1), - NULL), "Part 2"); - - - // Normal hook, then vp hook - - int hook2 = SH_ADD_HOOK(IBase, Func1, p_d1i1, SH_STATIC(Handler_Func1_Pre), false); - hook1 = SH_ADD_VPHOOK(IBase, Func1, p_d1i1, SH_STATIC(Handler_Func1_Pre), false); - - p_d1i1->Func1(); - p_d1i2->Func1(); - p_d2i1->Func1(); - - CHECK_STATES((&g_States, - new State_Func1_Pre(p_d1i1), - new State_Func1_Pre(p_d1i1), - new State_D1_Func1(p_d1i1), - - new State_Func1_Pre(p_d1i2), - new State_D1_Func1(p_d1i2), - - new State_D2_Func1(p_d2i1), - NULL), "Part 3"); - - SH_REMOVE_HOOK_ID(hook1); - - p_d1i1->Func1(); - p_d1i2->Func1(); - p_d2i1->Func1(); - - CHECK_STATES((&g_States, - new State_Func1_Pre(p_d1i1), - new State_D1_Func1(p_d1i1), - - new State_D1_Func1(p_d1i2), - - new State_D2_Func1(p_d2i1), - NULL), "Part 4"); - - SH_REMOVE_HOOK_ID(hook2); - - p_d1i1->Func1(); - p_d1i2->Func1(); - p_d2i1->Func1(); - - CHECK_STATES((&g_States, - new State_D1_Func1(p_d1i1), - - new State_D1_Func1(p_d1i2), - - new State_D2_Func1(p_d2i1), - NULL), "Part 5"); - - // Test this: - // Normal hook AND vp hook on Func2 - // Func2's pre handler removes the VP hook. - - hook1 = SH_ADD_VPHOOK(IBase, Func2, p_d1i1, SH_STATIC(Handler_Func2_Pre), false); - hook2 = SH_ADD_HOOK(IBase, Func2, p_d1i1, SH_STATIC(Handler_Func2_Pre), false); - - g_F2_Pre_HookToRemove = hook1; - p_d1i1->Func2(); - p_d1i1->Func2(); - - CHECK_STATES((&g_States, - new State_Func2_Pre(p_d1i1), - new State_D1_Func2(p_d1i1), - - new State_Func2_Pre(p_d1i1), - new State_D1_Func2(p_d1i1), - - NULL), "Part 6"); - - SH_REMOVE_HOOK_ID(hook1); - - // Hook function 3: - // Using manualhook, VP - hook1 = SH_ADD_MANUALVPHOOK(IBase_Func3_Manual, p_d1i1, SH_STATIC(Handler_Func3_Pre), false); - - // Normally, VP - hook2 = SH_ADD_VPHOOK(IBase, Func3, p_d1i1, SH_STATIC(Handler_Func3_Pre), false); - - // Normally, no VP - int hook3 = SH_ADD_HOOK(IBase, Func3, p_d1i1, SH_STATIC(Handler_Func3_Pre), false); - - p_d1i1->Func3(1); - - CHECK_STATES((&g_States, - new State_Func3_Pre(p_d1i1, 1), // manual vp hook - new State_Func3_Pre(p_d1i1, 2), // normal vp hook - new State_Func3_Pre(p_d1i1, 3), // normal non-vp hook - - new State_D1_Func3(p_d1i1, 4), // function - - NULL), "Part 7.1"); - - p_d1i2->Func3(1); - - CHECK_STATES((&g_States, - new State_Func3_Pre(p_d1i2, 1), // manual vp hook - new State_Func3_Pre(p_d1i2, 2), // normal vp hook - - new State_D1_Func3(p_d1i2, 3), // function - - NULL), "Part 7.2"); - - return true; -} - diff --git a/utils/mmsource/core/version.rc b/utils/mmsource/core/version.rc deleted file mode 100644 index 63bde2b5d..000000000 --- a/utils/mmsource/core/version.rc +++ /dev/null @@ -1,101 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" -#include - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION MMS_VERSION_FILE - PRODUCTVERSION MMS_VERSION_FILE - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000004b0" - BEGIN - VALUE "Comments", "Metamod: Source" - VALUE "FileDescription", "Metamod: Source" - VALUE "FileVersion", MMS_VERSION_STRING - VALUE "InternalName", "mmsource" - VALUE "LegalCopyright", "Copyright (c) 2004-2010, Metamod: Source Development Team" - VALUE "OriginalFilename", BINARY_NAME - VALUE "ProductName", "Metamod:Source" - VALUE "ProductVersion", MMS_VERSION_STRING - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0, 1200 - END -END - - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED diff --git a/utils/mmsource/core/vsp_bridge.cpp b/utils/mmsource/core/vsp_bridge.cpp deleted file mode 100644 index ba813fa62..000000000 --- a/utils/mmsource/core/vsp_bridge.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2009 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#include "metamod.h" -#include "metamod_util.h" -#include -#include -#include -#include -#include -#include -#include -#include "provider/provider_ep2.h" - -#if SOURCE_ENGINE == SE_DOTA -SH_DECL_HOOK2_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommandContext &, const CCommand &); -#elif SOURCE_ENGINE >= SE_ORANGEBOX -SH_DECL_HOOK1_void(ConCommand, Dispatch, SH_NOATTRIB, false, const CCommand &); -#else -SH_DECL_HOOK0_void(ConCommand, Dispatch, SH_NOATTRIB, false); -#endif - -ConCommand *g_plugin_unload = NULL; -bool g_bIsTryingToUnload; -SourceHook::String vsp_desc("Metamod:Source"); - -#if SOURCE_ENGINE == SE_DOTA -void InterceptPluginUnloads(const CCommandContext &context, const CCommand &args) -#elif SOURCE_ENGINE >= SE_ORANGEBOX -void InterceptPluginUnloads(const CCommand &args) -#else -void InterceptPluginUnloads() -#endif -{ - g_bIsTryingToUnload = true; -} - -#if SOURCE_ENGINE == SE_DOTA -void InterceptPluginUnloads_Post(const CCommandContext &context, const CCommand &args) -#elif SOURCE_ENGINE >= SE_ORANGEBOX -void InterceptPluginUnloads_Post(const CCommand &args) -#else -void InterceptPluginUnloads_Post() -#endif -{ - g_bIsTryingToUnload = false; -} - -class VspBridge : public IVspBridge -{ -public: - virtual bool Load(const vsp_bridge_info *info, char *error, size_t maxlength) - { - if (!g_Metamod.IsLoadedAsGameDLL()) - { - vsp_desc.append(" "); - vsp_desc.append(METAMOD_VERSION); - - CGlobalVars *pGlobals; - IPlayerInfoManager *playerInfoManager; - - playerInfoManager = (IPlayerInfoManager *)info->gsFactory("PlayerInfoManager002", NULL); - if (playerInfoManager == NULL) - { - UTIL_Format(error, maxlength, "Metamod:Source requires gameinfo.txt modification to load on this game"); - return false; - } - - pGlobals = playerInfoManager->GetGlobalVars(); - - char gamedll_iface[24]; - for (unsigned int i = 3; i <= 50; i++) - { - UTIL_Format(gamedll_iface, sizeof(gamedll_iface), "ServerGameDLL%03d", i); - if ((server = (IServerGameDLL *)info->gsFactory(gamedll_iface, NULL)) != NULL) - { - g_Metamod.SetGameDLLInfo((CreateInterfaceFn)info->gsFactory, i, false); - break; - } - } - - if (server == NULL) - { - UTIL_Format(error, maxlength, "Metamod:Source could not load (GameDLL version not compatible)."); - return false; - } - - char gameclients_iface[] = "ServerGameClients000"; - for (unsigned int i = 3; i <= 4; i++) - { - gameclients_iface[19] = '0' + i; - if ((gameclients = (IServerGameClients *)info->gsFactory(gameclients_iface, NULL)) == NULL) - break; - } - - mm_InitializeGlobals((CreateInterfaceFn) info->engineFactory, - (CreateInterfaceFn) info->engineFactory, - (CreateInterfaceFn) info->engineFactory, - pGlobals); - - if (!mm_DetectGameInformation()) - { - UTIL_Format(error, maxlength, "Metamod:Source failed to detect game paths; cannot load."); - return false; - } - - mm_InitializeForLoad(); - g_Metamod.NotifyVSPListening(info->vsp_callbacks, info->vsp_version); - mm_StartupMetamod(true); - } - else - { - vsp_desc.append(" Interface "); - vsp_desc.append(METAMOD_VERSION); - - g_Metamod.NotifyVSPListening(info->vsp_callbacks, info->vsp_version); - } - -#if SOURCE_ENGINE >= SE_ORANGEBOX - g_plugin_unload = icvar->FindCommand("plugin_unload"); -#else - const ConCommandBase *pBase = icvar->GetCommands(); - while (pBase != NULL) - { - if (pBase->IsCommand() && strcmp(pBase->GetName(), "plugin_unload") == 0) - { - g_plugin_unload = (ConCommand *)pBase; - break; - } - pBase = pBase->GetNext(); - } -#endif - - if (g_plugin_unload != NULL) - { - SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, g_plugin_unload, InterceptPluginUnloads, false); - SH_ADD_HOOK_STATICFUNC(ConCommand, Dispatch, g_plugin_unload, InterceptPluginUnloads_Post, true); - } - - return true; - } - - virtual void Unload() - { - // Source2 doesn't have the Error function (nor VSP support). -#if SOURCE_ENGINE != SE_DOTA - if (g_bIsTryingToUnload) - { - Error("Metamod:Source cannot be unloaded from VSP mode. Use \"meta unload\" to unload specific plugins.\n"); - return; - } -#endif - if (g_plugin_unload != NULL) - { - SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, g_plugin_unload, InterceptPluginUnloads, false); - SH_REMOVE_HOOK_STATICFUNC(ConCommand, Dispatch, g_plugin_unload, InterceptPluginUnloads_Post, true); - g_plugin_unload = NULL; - } - if (!g_Metamod.IsLoadedAsGameDLL()) - { - mm_UnloadMetamod(); - } - } - - virtual const char *GetDescription() - { - return vsp_desc.c_str(); - } -}; - -VspBridge mm16_vsp_bridge; - -SMM_API IVspBridge * -GetVspBridge() -{ - return &mm16_vsp_bridge; -} - diff --git a/utils/mmsource/cruft/installer/Attach.cfg b/utils/mmsource/cruft/installer/Attach.cfg deleted file mode 100644 index 6c5763513..000000000 --- a/utils/mmsource/cruft/installer/Attach.cfg +++ /dev/null @@ -1,38 +0,0 @@ --$A8 --$B- --$C+ --$D+ --$E- --$F- --$G+ --$H+ --$I+ --$J- --$K- --$L+ --$M- --$N+ --$O+ --$P+ --$Q- --$R- --$S- --$T- --$U- --$V+ --$W- --$X+ --$YD --$Z1 --cg --AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; --H+ --W+ --M --$M16384,1048576 --K$00400000 --LE"c:\program files\borland\delphi7\Projects\Bpl" --LN"c:\program files\borland\delphi7\Projects\Bpl" --w-UNSAFE_TYPE --w-UNSAFE_CODE --w-UNSAFE_CAST diff --git a/utils/mmsource/cruft/installer/Attach.dpr b/utils/mmsource/cruft/installer/Attach.dpr deleted file mode 100644 index eb258b427..000000000 --- a/utils/mmsource/cruft/installer/Attach.dpr +++ /dev/null @@ -1,85 +0,0 @@ -program Attach; - -{$APPTYPE CONSOLE} - -uses - SysUtils, Classes, UnitPackSystem; - -var eStream: TMemoryStream; - eFiles: TStringList; - Version: String; -begin - WriteLn('// File attacher for the MM:S installer'); - WriteLn('// by Basic-Master'); - WriteLn(''); - WriteLn('// Looking up files...'); - { Check files } - if FileExists(ExtractFilePath(ParamStr(0)) + 'files\hl2launch.exe') then - WriteLn('// Found files\hl2launch.exe') - else begin - WriteLn('// Error: Couldn''t find files\hl2launch.exe!'); - ReadLn; - exit; - end; - if FileExists(ExtractFilePath(ParamStr(0)) + 'files\server.dll.source') then - WriteLn('// Found files\server.dll.source') - else begin - WriteLn('// Error: Couldn''t find files\server.dll.source!'); - ReadLn; - exit; - end; - if FileExists(ExtractFilePath(ParamStr(0)) + 'files\server_i486.so.source') then - WriteLn('// Found files\server_i486.so.source') - else begin - WriteLn('// Error: Couldn''t find files\server_i486.so.source!'); - ReadLn; - exit; - end; - if FileExists(ExtractFilePath(ParamStr(0)) + 'files\server.dll.orangebox') then - WriteLn('// Found files\server.dll.orangebox') - else begin - WriteLn('// Error: Couldn''t find files\server.dll.orangebox!'); - ReadLn; - exit; - end; - if FileExists(ExtractFilePath(ParamStr(0)) + 'files\server_i486.so.orangebox') then - WriteLn('// Found files\server_i486.so.orangebox') - else begin - WriteLn('// Error: Couldn''t find files\server_i486.so.orangebox!'); - ReadLn; - exit; - end; - if FileExists(ExtractFilePath(ParamStr(0)) + 'MMS_Installer.exe') then - WriteLn('// Found MMS_Installer.exe') - else begin - WriteLn('// Error: Couldn''t find MMS_Installer.exe!'); - ReadLn; - exit; - end; - { Get version number } - WriteLn('// Please enter the version number:'); - ReadLn(Version); - if (Trim(Version) = '') then begin - WriteLn('// Error: Invalid version number!'); - ReadLn; - exit; - end; - { Compress files } - WriteLn('// Compressing files...'); - eFiles := TStringList.Create; - eFiles.Add(ExtractFilePath(ParamStr(0)) + 'files\hl2launch.exe'); - eFiles.Add(ExtractFilePath(ParamStr(0)) + 'files\server.dll.source'); - eFiles.Add(ExtractFilePath(ParamStr(0)) + 'files\server_i486.so.source'); - eFiles.Add(ExtractFilePath(ParamStr(0)) + 'files\server.dll.orangebox'); - eFiles.Add(ExtractFilePath(ParamStr(0)) + 'files\server_i486.so.orangebox'); - eStream := TMemoryStream.Create; - CompressFiles(eFiles, ExtractFilePath(ParamStr(0)) + 'temp.zip'); - eStream.LoadFromFile(ExtractFilePath(ParamStr(0)) + 'temp.zip'); - WriteLn('// Attaching output to MMS_Installer.exe...'); - AttachToFile(ExtractFilePath(ParamStr(0)) + 'MMS_Installer.exe', eStream, Version); - DeleteFile(ExtractFilePath(ParamStr(0)) + 'temp.zip'); - eStream.Free; - eFiles.Free; - WriteLn('// Done.'); - ReadLn; -end. diff --git a/utils/mmsource/cruft/installer/HL2Launch.cfg b/utils/mmsource/cruft/installer/HL2Launch.cfg deleted file mode 100644 index 662b86fe5..000000000 --- a/utils/mmsource/cruft/installer/HL2Launch.cfg +++ /dev/null @@ -1,38 +0,0 @@ --$A8 --$B- --$C+ --$D+ --$E- --$F- --$G+ --$H+ --$I+ --$J- --$K- --$L+ --$M- --$N+ --$O+ --$P+ --$Q- --$R- --$S- --$T- --$U- --$V+ --$W- --$X+ --$YD --$Z1 --cg --AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; --H+ --W+ --M --$M16384,1048576 --K$00400000 --LE"c:\programme\borland\delphi7\Projects\Bpl" --LN"c:\programme\borland\delphi7\Projects\Bpl" --w-UNSAFE_TYPE --w-UNSAFE_CODE --w-UNSAFE_CAST diff --git a/utils/mmsource/cruft/installer/HL2Launch.dpr b/utils/mmsource/cruft/installer/HL2Launch.dpr deleted file mode 100644 index 7eacc19a9..000000000 --- a/utils/mmsource/cruft/installer/HL2Launch.dpr +++ /dev/null @@ -1,189 +0,0 @@ -program HL2Launch; - -{$APPTYPE CONSOLE} - -uses - SysUtils, - ShellApi, - Windows, - Classes; - -procedure LaunchFile(eFile, eStartDir, eParams: String); -var eStartInfo: TStartupInfo; - eProcInfo: TProcessInformation; -begin - FillChar(eStartInfo, SizeOf(TStartupInfo), 0); - with eStartInfo do begin - cb := SizeOf(eStartInfo); - dwFlags := STARTF_USESHOWWINDOW; - end; - - if (CreateProcess(nil, PChar(eFile + #32 + eParams), nil, nil, False, NORMAL_PRIORITY_CLASS, nil, PChar(eStartDir), eStartInfo, eProcInfo)) then begin - try - WaitForSingleObject(eProcInfo.hProcess, INFINITE); - finally - CloseHandle(eProcInfo.hProcess); - CloseHandle(eProcInfo.hThread); - end; - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 2); - Write(' Done.' + #13#10); - end - else begin - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12); - Write(' Couldn''t start hl2.exe!' + #13#10); - end; -end; - -function GetFileSize(eFile: String): Int64; -var eFindHandle: THandle; - eFindData: TWIN32FINDDATA; -begin - Result := 0; - if not FileExists(eFile) then exit; - eFindHandle := FindFirstFile(PChar(eFile), eFindData); - if eFindHandle = INVALID_HANDLE_VALUE then exit; - Result := (eFindData.nFileSizeHigh * (Int64(MAXDWORD) + 1)) + eFindData.nFileSizeLow; - FindClose(eFindHandle); -end; - -var eStream: TFileStream; - ePath, eParams: String; - eModDir: String; - eSearchRec: TSearchRec; - eStr: TStringList; - i: integer; - CheckSuccessful: Boolean; - StartTime: Cardinal; -begin - ePath := ExtractFilePath(ParamStr(0)); - for i := 1 to ParamCount do - eParams := eParams + #32 + ParamStr(i); - Delete(eParams, 1, 1); - if Pos('console', LowerCase(eParams)) = 0 then - eParams := eParams + ' -console'; - eStream := nil; - eModDir := ''; - - SetConsoleTitle('HL2 Launcher'); - Sleep(200); // wait a few ms until the launch program is closed - - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 2); - WriteLn(' _ _ _ ____ _ _ '); - WriteLn('| | | | | |___ \ | | __ _ _ _ _ __ ___| |__ ___ _ __ '); - WriteLn('| |_| | | __) | | | / _` | | | | ''_ \ / __| ''_ \ / _ \ ''__|'); - WriteLn('| _ | |___ / __/ | |__| (_| | |_| | | | | (__| | | | __/ | '); - WriteLn('|_| |_|_____|_____| |_____\__,_|\__,_|_| |_|\___|_| |_|\___|_| '); - WriteLn(' for listen servers using Metamod:Source'); - WriteLn(''); - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7); - { Check files } - WriteLn('Checking files...'); - if not FileExists(ePath + 'hl2.exe') then begin - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12); - WriteLn('Error: hl2.exe is missing! Maybe wrong directory? If not, start your HL2 Mod again via Steam and try again.'); - ReadLn; - exit; - end; - if not FileExists(Copy(ePath, 1, Pos('\steamapps\', LowerCase(ePath))) + 'steam.exe') then begin - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12); - WriteLn('Error: Cannot find steam.exe! Make sure this application is located in your listen server''s directory.'); - ReadLn; - exit; - end; - { Verify GameInfo.txt ... } - Write('Verifying GameInfo.txt...'); - if (FindFirst(ePath + '*.*', faDirectory, eSearchRec) = 0) then begin - repeat - if (FileExists(ePath + eSearchRec.Name + '\GameInfo.txt')) then begin - eModDir := eSearchRec.Name; - break; - end; - until (FindNext(eSearchRec) <> 0); - end; - FindClose(eSearchRec.FindHandle); - if eModDir = '' then begin - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12); - WriteLn(''); - WriteLn('Error: Couldn''t find GameInfo.txt!'); - ReadLn; - exit; - end - else begin - if Pos('game', LowerCase(eParams)) = 0 then // a small test which isn't worth a notice - eParams := '-game ' + eSearchRec.Name + #32 + eParams; - - eStr := TStringList.Create; - eStr.LoadFromFile(ePath + eModDir + '\GameInfo.txt'); - if Pos('|gameinfo_path|addons/metamod/bin', LowerCase(eStr.Text)) = 0 then begin - CheckSuccessful := False; - for i := 0 to eStr.Count -1 do begin - if Pos('searchpaths', LowerCase(Trim(eStr[i]))) = 1 then begin - if i+3 >= eStr.Count then - break; - eStr.Insert(i+2, ' GameBin |gameinfo_path|addons/metamod/bin'); - CheckSuccessful := True; - break; - end; - end; - - if CheckSuccessful then begin - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 2); - SetFileAttributes(PChar(ePath + eModDir + '\GameInfo.txt'), 0); - eStr.SaveToFile(ePath + eModDir + '\GameInfo.txt'); - SetFileAttributes(PChar(ePath + eModDir + '\GameInfo.txt'), faReadOnly); - Write(' Registered MM:S sucessfully' + #13#10); - end - else begin - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4); - Write(' Unexpected EOF, your GameInfo.txt seems to be corrupt' + #13#10); - end; - end - else begin - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 2); - Write(' Done' + #13#10); - end; - eStr.Free; - end; - { ... and set it to write-protected } - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7); - Write('Setting GameInfo.txt to write-protected...'); - try - eStream := TFileStream.Create(ePath + eModDir + '\GameInfo.txt', fmShareDenyWrite); - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 2); - Write(' Done.' + #13#10); - except - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14); - WriteLn(''); - WriteLn('Warning: Couldn''t set GameInfo.txt to write-protected!'); - eStream := nil; - end; - { Launch Steam if not opened } - ShellExecute(0, 'open', PChar(Copy(ePath, 1, Pos('\steamapps\', LowerCase(ePath))) + 'steam.exe'), nil, PChar(Copy(ePath, 1, Pos('\steamapps\', LowerCase(ePath)))), SW_SHOW); - { Launch game } - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7); - Write('Starting HL2...'); - StartTime := GetTickCount; - LaunchFile(ePath + 'hl2.exe', Copy(ePath, 1, Pos('Steam', ePath)+5), eParams); - if (GetTickCount - StartTime < 10000) then begin - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14); - WriteLn('Important: If you experience any problems starting HL2 using this program, please start it once via Steam and try again.'); - ReadLn; - end; - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7); - { Free GameInfo.txt } - Write('Removing read-only again from GameInfo.txt...'); - if Assigned(eStream) then begin - eStream.Free; - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 2); - Write(' Done' + #13#10); - end - else begin - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4); - Write(' Skipped' + #13#10); - end; - { End message } - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7); - WriteLn(''); - WriteLn('Thanks for using Metamod:Source! Visit http://www.sourcemm.net/'); - Sleep(2500); -end. diff --git a/utils/mmsource/cruft/installer/MMS_Installer.cfg b/utils/mmsource/cruft/installer/MMS_Installer.cfg deleted file mode 100644 index 6c5763513..000000000 --- a/utils/mmsource/cruft/installer/MMS_Installer.cfg +++ /dev/null @@ -1,38 +0,0 @@ --$A8 --$B- --$C+ --$D+ --$E- --$F- --$G+ --$H+ --$I+ --$J- --$K- --$L+ --$M- --$N+ --$O+ --$P+ --$Q- --$R- --$S- --$T- --$U- --$V+ --$W- --$X+ --$YD --$Z1 --cg --AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; --H+ --W+ --M --$M16384,1048576 --K$00400000 --LE"c:\program files\borland\delphi7\Projects\Bpl" --LN"c:\program files\borland\delphi7\Projects\Bpl" --w-UNSAFE_TYPE --w-UNSAFE_CODE --w-UNSAFE_CAST diff --git a/utils/mmsource/cruft/installer/MMS_Installer.dpr b/utils/mmsource/cruft/installer/MMS_Installer.dpr deleted file mode 100644 index 09273aca7..000000000 --- a/utils/mmsource/cruft/installer/MMS_Installer.dpr +++ /dev/null @@ -1,72 +0,0 @@ -program MMS_Installer; - -{ - - Metamod:Source installer is published under the zlib/libpng license, as well - as Metamod:Source itself. You can find a copy of it below. - - --------- - - zLib/libpng License - - Copyright (c) 2007, Metamod:Source Development Team - - This software is provided 'as-is', without any express or implied warranty. - In no event will the authors be held liable for any damages arising from the - use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it freely, - subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software in a - product, an acknowledgment in the product documentation would be appreciated - but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source distribution. - - --------- - - Used components: - - - Indy 9 (www.indyproject.org) - - FlatStyle Components (www.torry.net) - - FlatPack Component Pack (www.torry.net) - - JVCL Lib Pack 3.0 (jvcl.sourceforge.net) - - Half-Life 2 Icons by Vasili "vaksa" Vorotnikov, Thanks! - Visit www.vaksa.net for further information - -} - -uses - Forms, - UnitfrmMain in 'UnitfrmMain.pas' {frmMain}, - UnitFunctions in 'UnitFunctions.pas', - UnitfrmProxy in 'UnitfrmProxy.pas' {frmProxy}, - UnitInstall in 'UnitInstall.pas', - UnitSelectModPath in 'UnitSelectModPath.pas' {frmSelectModPath}, - UnitPackSystem in 'UnitPackSystem.pas'; - -{$R *.res} - -begin - Application.Initialize; - Application.Title := 'Metamod:Source Installer'; - Application.CreateForm(TfrmMain, frmMain); - UnitfrmMain.VERSION := GetVersion; - frmMain.lblWelcome.Caption := 'Welcome to the Metamod:Source ' + VERSION + ' Setup Wizard'; - frmMain.lblInfo1.Caption := 'This wizard will guide you through the installation of Metamod:Source ' + VERSION + '.'; - frmMain.lblSubTitle1.Caption := 'Please review the following license terms before installing Metamod:Source ' + VERSION + '.'; - frmMain.lblSelectModInfo.Caption := 'Please select the mod Metamod:Source ' + VERSION + ' shall be installed to.'; - frmMain.lblTitle3.Caption := 'Installing Metamod:Source ' + VERSION + ' via FTP'; - frmMain.lblTitle5.Caption := 'Installing Metamod:Source ' + VERSION; - frmMain.lblSubTitle5.Caption := 'Please wait while Metamod:Source ' + VERSION + ' is being installed.'; - Application.CreateForm(TfrmProxy, frmProxy); - Application.CreateForm(TfrmSelectModPath, frmSelectModPath); - Application.Run; -end. diff --git a/utils/mmsource/cruft/installer/MMS_Installer.res b/utils/mmsource/cruft/installer/MMS_Installer.res deleted file mode 100644 index ace331738..000000000 Binary files a/utils/mmsource/cruft/installer/MMS_Installer.res and /dev/null differ diff --git a/utils/mmsource/cruft/installer/UnitFunctions.pas b/utils/mmsource/cruft/installer/UnitFunctions.pas deleted file mode 100644 index a6f024dea..000000000 --- a/utils/mmsource/cruft/installer/UnitFunctions.pas +++ /dev/null @@ -1,126 +0,0 @@ -unit UnitFunctions; - -interface - -uses SysUtils, Classes, Windows, IdFTPList, Math; - -function CalcSpeed(eOld, eNew: Integer): String; -// local -function GetAllFiles(Mask: String; Attr: Integer; Recursive: Boolean; ShowDirs: Boolean; ShowPath: Boolean = True): TStringList; -// ftp -function GetAllDirs: TStringList; - -implementation - -uses UnitfrmMain; - -function CalcSpeed(eOld, eNew: Integer): String; -begin - Result := frmMain.Caption; - if (eOld < eNew) and (eOld <> 0) then begin - eOld := eNew - eOld; - //eOld := eOld *2; // this is only used for faster updates... - Result := 'Metamod:Source - Uploading with ' + FloatToStr(RoundTo(eOld / 1024, -2)) + ' kb/s'; - end; -end; - -function GetAllFiles(Mask: String; Attr: Integer; Recursive: Boolean; ShowDirs: Boolean; ShowPath: Boolean = True): TStringList; -var eSearch: TSearchRec; -begin - Result := TStringList.Create; - - // Find all files - if FindFirst(Mask, Attr, eSearch) = 0 then - begin - repeat - if eSearch.Name[1] <> '.' then begin - if ShowPath then begin - if ((eSearch.Attr and Attr) = eSearch.Attr) and ((eSearch.Attr and faDirectory) <> eSearch.Attr) then - Result.Add(ExtractFilePath(Mask) + eSearch.Name) - else if (ShowDirs) and ((eSearch.Attr and faDirectory) = eSearch.Attr) then - Result.Add(ExtractFilePath(Mask) + eSearch.Name); - end - else begin - if ((eSearch.Attr and Attr) = eSearch.Attr) and ((eSearch.Attr and faDirectory) <> eSearch.Attr) then - Result.Add(eSearch.Name) - else if (ShowDirs) and ((eSearch.Attr and faDirectory) = eSearch.Attr) then - Result.Add(eSearch.Name); - end; - - if ((eSearch.Attr and faDirectory) = eSearch.Attr) and (Recursive) then begin - with GetAllFiles(ExtractFilePath(Mask) + eSearch.Name + '\' + ExtractFileName(Mask), Attr, True, ShowDirs, ShowPath) do begin - Result.Text := Result.Text + Text; - Free; - end; - end; - end; - until FindNext(eSearch) <> 0; - end; -end; - -function GetAllDirs: TStringList; -var eList: TStringList; - i: integer; -begin - eList := TStringList.Create; - frmMain.IdFTP.List(eList); - frmMain.IdFTP.DirectoryListing.LoadList(eList); - eList.Clear; - for i := 0 to frmMain.IdFTP.DirectoryListing.Count -1 do begin - if frmMain.IdFTP.DirectoryListing.Items[i].ItemType = ditDirectory then - eList.Add(frmMain.IdFTP.DirectoryListing.Items[i].FileName); - end; - Result := eList; -end; - -{ This is another possibility I coded because I couldn't find another bug... - -function GetAllDirs: TStringList; -var eList: TStringList; - i, eStart: integer; -begin - eList := TStringList.Create; - frmMain.IdFTP.List(eList, '', True); - eStart := 0; - - - // +----------------------------------------------------------------+ - // | drwxr-xr-x 5 web3 ftponly 2048 Jun 25 19:43 files | - // | drwxr-xr-x 2 web3 ftponly 2048 Jun 25 19:57 html | - // | drwxr-xr-x 3 root root 2048 Jun 20 05:03 log | - // | drwxrwxrwx 2 web3 ftponly 2048 Jun 19 2004 phptmp | - // +----------------------------------------------------------------+ - - - // at first remove all non-directories from the list - for i := eList.Count -1 downto 0 do begin - if Pos('d', eList[i]) <> 1 then - eList.Delete(i); - end; - // then we have to find the position where ALL filenames start... - for i := 0 to eList.Count -1 do begin - if (eStart = 0) and (Pos(':', eList[i]) <> 0) then - eStart := Pos(':', eList[i]); - end; - - if eStart = 0 then - eList.Clear - else begin - // find the position - for i := 0 to eList.Count -1 do begin - if Pos(':', eList[i]) <> 0 then begin - while (eStart <> Length(eList[i])) and (eList[i][eStart] <> #32) do - Inc(eStart, 1); - end; - end; - // remove the detail stuff... - for i := 0 to eList.Count -1 do - eList[i] := Copy(eList[i], eStart +1, Length(eList[i])); - end; - - Result := eList; -end; } - -end. - - diff --git a/utils/mmsource/cruft/installer/UnitInstall.pas b/utils/mmsource/cruft/installer/UnitInstall.pas deleted file mode 100644 index 95622ba9c..000000000 --- a/utils/mmsource/cruft/installer/UnitInstall.pas +++ /dev/null @@ -1,560 +0,0 @@ -unit UnitInstall; - -interface - -uses SysUtils, Classes, Windows, Graphics, Forms, ShellAPI, Controls, Messages, - TlHelp32, IdFTPCommon, ComCtrls; - -type TOS = (osWindows, osLinux); - -procedure AddStatus(Text: String; Color: TColor; ShowTime: Boolean = True); -procedure AddDone(Additional: String = ''); -procedure AddSkipped; -procedure AddNotFound; -procedure DownloadFile(eFile: String; eDestination: String); - -procedure BasicInstallation(ePath: String; SteamInstall, ListenInstall: Boolean; OS: TOS; const Source: Boolean); -procedure InstallDedicated(eModPath: String; const UseSteam, Source: Boolean); -procedure InstallListen(ePath: String; const Source: Boolean); -procedure InstallCustom(ePath: String; eOS: TOS; const Source: Boolean); -procedure InstallFTP(OS: TOS; const Source: Boolean); - -var StartTime: TDateTime; - SteamPath: String; - StandaloneServer: String; - Cancel: Boolean = False; - -implementation - -uses UnitfrmMain, UnitfrmProxy, UnitFunctions, UnitPackSystem; - -// useful stuff - -function InstallTime: String; -begin - Result := Copy(FormatDateTime('HH:MM:SS', Now - StartTime), 4, 5); -end; - -procedure AddStatus(Text: String; Color: TColor; ShowTime: Boolean = True); -begin - frmMain.rtfDetails.SelStart := Length(frmMain.rtfDetails.Text); - if ShowTime then begin - frmMain.rtfDetails.SelAttributes.Color := clBlack; - if frmMain.rtfDetails.Text = '' then - frmMain.rtfDetails.SelText := '[' + InstallTime + '] ' - else - frmMain.rtfDetails.SelText := #13#10 + '[' + InstallTime + '] '; - frmMain.rtfDetails.SelStart := Length(frmMain.rtfDetails.Text); - end - else - frmMain.rtfDetails.SelText := #13#10; - - frmMain.rtfDetails.SelStart := Length(frmMain.rtfDetails.Text); - frmMain.rtfDetails.SelAttributes.Color := Color; - frmMain.rtfDetails.SelText := Text; - frmMain.rtfDetails.Perform(WM_VSCROLL, SB_BOTTOM, 0); - - frmMain.Repaint; - Application.ProcessMessages; -end; - -procedure AddDone(Additional: String = ''); -begin - frmMain.rtfDetails.SelStart := Length(frmMain.rtfDetails.Text); - frmMain.rtfDetails.SelAttributes.Color := clGreen; - if Additional = '' then - frmMain.rtfDetails.SelText := ' Done.' - else - frmMain.rtfDetails.SelText := ' Done, ' + Additional + '.'; - frmMain.rtfDetails.Perform(WM_VSCROLL, SB_BOTTOM, 0); - - frmMain.Repaint; - Application.ProcessMessages; -end; - -procedure AddSkipped; -begin - frmMain.rtfDetails.SelStart := Length(frmMain.rtfDetails.Text); - frmMain.rtfDetails.SelAttributes.Color := $004080FF; // orange - frmMain.rtfDetails.SelText := ' Skipped.'; - frmMain.rtfDetails.Perform(WM_VSCROLL, SB_BOTTOM, 0); - - frmMain.Repaint; - Application.ProcessMessages; -end; - -procedure AddNotFound; -begin - frmMain.rtfDetails.SelStart := Length(frmMain.rtfDetails.Text); - frmMain.rtfDetails.SelAttributes.Color := clRed; - frmMain.rtfDetails.SelText := ' Not found.'; - frmMain.rtfDetails.Perform(WM_VSCROLL, SB_BOTTOM, 0); - - frmMain.Repaint; - Application.ProcessMessages; -end; - -procedure FileCopy(Source, Destination: String; CopyConfig: Boolean; AddStatus: Boolean = True); -begin - if (not CopyConfig) and (Pos('config', Source) <> 0) then begin - if AddStatus then - AddSkipped; - exit; - end; - - if not FileExists(Source) then begin - if AddStatus then - AddNotFound; - exit; - end; - - try - if FileExists(Destination) then - DeleteFile(PChar(Destination)); - CopyFile(PChar(Source), PChar(Destination), False); - except - Application.ProcessMessages; - end; - - if AddStatus then - AddDone; -end; - -procedure DownloadFile(eFile: String; eDestination: String); -var TransferType: TIdFTPTransferType; -begin - // There's only one file to download and it's ASCII :] - TransferType := ftASCII; - if frmMain.IdFTP.TransferType <> TransferType then - frmMain.IdFTP.TransferType := TransferType; - // download the file - frmMain.IdFTP.Get(eFile, eDestination, True); -end; - -procedure UploadFile(eFile: String; eDestination: String; CopyConfig: Boolean = True); -var TransferType: TIdFTPTransferType; -begin - if (Pos('config', eFile) > 0) and (not CopyConfig) then begin - AddSkipped; - exit; - end; - - eDestination := StringReplace(eDestination, '\', '/', [rfReplaceAll]); - - // the same as in DownloadFile() - TransferType := ftBinary; - if ExtractFileExt(LowerCase(eFile)) = '.txt' then TransferType := ftASCII; - if frmMain.IdFTP.TransferType <> TransferType then - frmMain.IdFTP.TransferType := TransferType; - // upload the file - frmMain.IdFTP.Put(eFile, eDestination); - AddDone; -end; - -procedure FTPMakeDir(eDir: String); -begin - eDir := StringReplace(eDir, '\', '/', [rfReplaceAll]); - try - frmMain.IdFTP.MakeDir(eDir); - except - Application.ProcessMessages; - end; -end; - -function FSize(eFile: String): Cardinal; -var eRec: TSearchRec; -begin - if FindFirst(eFile, faAnyFile, eRec) = 0 then - Result := eRec.Size - else - Result := 0; -end; - -// stuff for killing processes - -function GetProcessID(sProcName: String): Integer; -var - hProcSnap: THandle; - pe32: TProcessEntry32; -begin - result := -1; - hProcSnap := CreateToolHelp32SnapShot(TH32CS_SNAPPROCESS, 0); - if hProcSnap = INVALID_HANDLE_VALUE then - exit; - - pe32.dwSize := SizeOf(ProcessEntry32); - if Process32First(hProcSnap, pe32) = true then begin - while Process32Next(hProcSnap, pe32) = true do begin - if pos(sProcName, pe32.szExeFile) <> 0then - result := pe32.th32ProcessID; - end; - end; - CloseHandle(hProcSnap); -end; - -procedure KillProcess(dwProcID: DWORD); -var - hProcess : Cardinal; - dw : DWORD; -begin - hProcess := OpenProcess(SYNCHRONIZE or PROCESS_TERMINATE, False, dwProcID); - TerminateProcess(hProcess, 0); - dw := WaitForSingleObject(hProcess, 5000); - case dw of - WAIT_TIMEOUT: begin - CloseHandle(hProcess); - exit; - end; - WAIT_FAILED: begin - RaiseLastOSError; - CloseHandle(hProcess); - exit; - end; - end; - CloseHandle(hProcess); -end; - -// Installation here - -{ Basic Installation } - -procedure BasicInstallation(ePath: String; SteamInstall, ListenInstall: Boolean; OS: TOS; const Source: Boolean); -var eStr: TStringList; - i: integer; - CopyConfig: Boolean; - eFound: Boolean; -begin - frmMain.ggeAll.MaxValue := 8; - frmMain.ggeAll.Progress := 0; - frmMain.ggeItem.MaxValue := 1; - frmMain.ggeItem.Progress := 0; - - {if (GetProcessID('Steam.exe') <> -1) and (SteamInstall) then begin - if MessageBox(frmMain.Handle, 'Steam is still running. It is necersarry to shut it down before you install Metamod:Source. Shut it down now?', PChar(frmMain.Caption), MB_ICONQUESTION + MB_YESNO) = mrYes then begin - AddStatus('Shutting down Steam...', clBlack, False); - if GetProcessID('Steam.exe') = -1 then - AddDone - else - KillProcess(GetProcessID('Steam.exe')); - - while GetProcessID('Steam.exe') <> -1 do begin // sure is sure... - Sleep(50); - Application.ProcessMessages; - end; - AddDone; - end - else begin - Application.Terminate; - exit; - end; - end;} - frmMain.ggeAll.Progress := 1; - frmMain.ggeItem.Progress := 1; - { Unpack } - frmMain.ggeItem.Progress := 0; - AddStatus('Unpacking files...', clBlack); - if not Unpack(Source) then begin - AddStatus('No files attached!', clRed); - Screen.Cursor := crDefault; - exit; - end; - AddDone; - frmMain.ggeAll.Progress := 2; - frmMain.ggeItem.Progress := 1; - { Check for installation / Create directories } - CopyConfig := True; - AddStatus('Creating directories...', clBlack); - if DirectoryExists(ePath + 'addons\metamod\bin') then begin - case MessageBox(frmMain.Handle, 'A Metamod:Source installation was already detected. If you choose to reinstall, your configuration files will be erased. Click Yes to continue, No to Upgrade, or Cancel to abort the install.', PChar(frmMain.Caption), MB_ICONQUESTION + MB_YESNOCANCEL) of - mrNo: CopyConfig := False; - mrCancel: begin - Application.Terminate; - exit; - end; - end; - AddSkipped; - end - else begin - frmMain.ggeItem.Progress := 0; - ForceDirectories(ePath + 'addons\metamod\bin'); - AddDone; - end; - frmMain.ggeItem.Progress := 1; - frmMain.ggeAll.Progress := 3; - - { gameinfo.txt } - if not FileExists(ePath + 'gameinfo.txt') then begin - if MessageBox(frmMain.Handle, 'The file "gameinfo.txt" couldn''t be found. Continue installation?', PChar(frmMain.Caption), MB_ICONQUESTION + MB_YESNO) = mrNo then begin - AddStatus('Installation canceled by user!', clRed, False); - Screen.Cursor := crDefault; - Cancel := True; - exit; - end; - end - else begin - eStr := TStringList.Create; - { Metaplugins.ini } - frmMain.ggeItem.Progress := 0; - AddStatus('Creating metaplugins.ini...', clBlack); - if CopyConfig then begin - eStr.SaveToFile(ePath + 'addons\metamod\metaplugins.ini'); - AddDone; - end - else - AddSkipped; - frmMain.ggeItem.Progress := 1; - frmMain.ggeAll.Progress := 4; - { Gameinfo.txt } - frmMain.ggeItem.Progress := 0; - eFound := False; - AddStatus('Editing gameinfo.txt...', clBlack); - eStr.LoadFromFile(ePath + 'gameinfo.txt'); - for i := 0 to eStr.Count -1 do begin - if Trim(LowerCase(eStr[i])) = 'gamebin |gameinfo_path|addons/metamod/bin' then begin - eFound := True; - break; - end; - end; - - if not eFound then begin - for i := 0 to eStr.Count -1 do begin - if Trim(eStr[i]) = 'SearchPaths' then begin - eStr.Insert(i +2, ' GameBin |gameinfo_path|addons/metamod/bin'); - break; - end; - end; - SetFileAttributes(PChar(ePath + 'gameinfo.txt'), 0); - eStr.SaveToFile(ePath + 'gameinfo.txt'); - SetFileAttributes(PChar(ePath + 'gameinfo.txt'), faReadOnly); // important for listen servers - AddDone; - end - else - AddSkipped; - eStr.Free; - frmMain.ggeItem.Progress := 1; - frmMain.ggeAll.Progress := 5; - end; - { Copy files } - frmMain.ggeItem.Progress := 0; - AddStatus('Copying server.dll...', clBlack); - CopyFile(PChar(ExtractFilePath(ParamStr(0)) + 'server.dll'), PChar(ePath + 'addons\metamod\bin\server.dll'), False); - AddDone; - frmMain.ggeItem.Progress := 1; - frmMain.ggeAll.Progress := 6; - if ListenInstall then begin - ePath := ExtractFilePath(Copy(ePath, 1, Length(ePath)-1)); - AddStatus('Copying hl2launch.exe...', clBlack); - CopyFile(PChar(ExtractFilePath(ParamStr(0)) + 'hl2launch.exe'), PChar(ePath + 'hl2launch.exe'), False); - AddDone; - end; - { Remove files } - frmMain.ggeItem.Progress := 0; - AddStatus('Removing temporary files...', clBlack); - DeleteFile(PChar(ExtractFilePath(ParamStr(0)) + 'hl2launch.exe')); - DeleteFile(PChar(ExtractFilePath(ParamStr(0)) + 'server.dll')); - DeleteFile(PChar(ExtractFilePath(ParamStr(0)) + 'server_i486.so')); - AddDone; - frmMain.ggeItem.Progress := 1; - frmMain.ggeAll.Progress := 8; - { Finish } - AddStatus('', clBlack, False); - AddStatus('Finished installation!', clBlack, False); - frmMain.cmdNext.Enabled := True; - frmMain.cmdCancel.Hide; - Screen.Cursor := crDefault; - - if ListenInstall then - MessageBox(frmMain.Handle, PChar('The Source launcher "hl2launch.exe" has been copied to ' + ePath + '. You can use it to start your game with Metamod:Source enabled.'), PChar(Application.Title), MB_ICONINFORMATION); -end; - -{ Dedicated Server } - -procedure InstallDedicated(eModPath: String; const UseSteam, Source: Boolean); -begin - StartTime := Now; - Screen.Cursor := crHourGlass; - AddStatus('Starting Metamod:Source installation on dedicated server...', clBlack, False); - BasicInstallation(eModPath, UseSteam, False, osWindows, Source); -end; - -{ Listen Server } - -procedure InstallListen(ePath: String; const Source: Boolean); -begin - StartTime := Now; - Screen.Cursor := crHourGlass; - AddStatus('Starting Metamod:Source installation on the listen server...', clBlack); - BasicInstallation(ePath, True, True, osWindows, Source); -end; - -{ Custom mod } - -procedure InstallCustom(ePath: String; eOS: TOS; const Source: Boolean); -begin - StartTime := Now; - Screen.Cursor := crHourGlass; - AddStatus('Starting Metamod:Source installation...', clBlack); - BasicInstallation(ePath, False, False, eOS, Source); -end; - -{ FTP } - -procedure InstallFTP(OS: TOS; const Source: Boolean); -function DoReconnect: Boolean; -begin - Result := False; - if MessageBox(frmMain.Handle, 'You have been disconnected due to an error. Try to reconnect?', PChar(Application.Title), MB_ICONQUESTION + MB_YESNO) = mrYes then begin - try - frmMain.IdFTP.Connect; - Result := True; - except - MessageBox(frmMain.Handle, 'Failed to reconnect. Installation aborted.', PChar(Application.Title), MB_ICONSTOP); - end; - end; -end; - -label CreateAgain; -label UploadAgain; -var eStr: TStringList; - i: integer; - CopyConfig, eFound: Boolean; -begin - frmMain.cmdCancel.Show; - frmMain.cmdNext.Hide; - Screen.Cursor := crHourGlass; - - frmMain.ggeAll.MaxValue := 6; - frmMain.ggeAll.Progress := 0; - frmMain.ggeItem.MaxValue := 1; - frmMain.ggeItem.Progress := 0; - - { Unpack } - frmMain.ggeItem.Progress := 0; - AddStatus('Unpacking files...', clBlack); - if not Unpack(Source) then begin - AddStatus('No files attached!', clRed); - Screen.Cursor := crDefault; - exit; - end; - AddDone; - frmMain.ggeAll.Progress := 2; - frmMain.ggeItem.Progress := 1; - { Check for installation } - AddStatus('Editing gameinfo.txt...', clBlack); - eStr := TStringList.Create; - DownloadFile('gameinfo.txt', ExtractFilePath(ParamStr(0)) + 'gameinfo.txt'); - eStr.LoadFromFile(ExtractFilePath(ParamStr(0)) + 'gameinfo.txt'); - - CopyConfig := True; - eFound := False; - for i := 0 to eStr.Count -1 do begin - if Trim(LowerCase(eStr[i])) = 'gamebin |gameinfo_path|addons/metamod/bin' then begin - eFound := True; - case MessageBox(frmMain.Handle, 'A Metamod:Source installation was already detected. If you choose to reinstall, your configuration files will be erased. Click Yes to continue, No to Upgrade, or Cancel to abort the install.', PChar(frmMain.Caption), MB_ICONQUESTION + MB_YESNOCANCEL) of - mrNo: CopyConfig := False; - mrCancel: begin - Application.Terminate; - eStr.Free; - exit; - end; - end; - break; - end; - end; - - if not eFound then begin - for i := 0 to eStr.Count -1 do begin - if Trim(eStr[i]) = 'SearchPaths' then begin - eStr.Insert(i +2, ' GameBin |gameinfo_path|addons/metamod/bin'); - AddDone; - break; - end; - end; - eStr.SaveToFile(ExtractFilePath(ParamStr(0)) + 'gameinfo.txt'); - UploadFile(ExtractFilePath(ParamStr(0)) + 'gameinfo.txt', 'gameinfo.txt'); - try - AddStatus('Trying to set gameinfo.txt to read-only...', clBlack); - frmMain.IdFTP.Site('CHMOD 744 gameinfo.txt'); - AddDone; - except - AddStatus('Warning: CHMOD not supported.', clMaroon); - end; - DeleteFile(PChar(ExtractFilePath(ParamStr(0)) + 'gameinfo.txt')); - end - else - AddSkipped; - frmMain.ggeAll.Progress := 3; - frmMain.ggeItem.Progress := 1; - - { Create directories } - frmMain.ggeItem.Progress := 0; - frmMain.ggeItem.MaxValue := 3; - AddStatus('Creating directories...', clBlack); - if not eFound then begin - FTPMakeDir('addons'); - frmMain.IdFTP.ChangeDir('addons'); - frmMain.ggeItem.Progress := 1; - FTPMakeDir('metamod'); - frmMain.IdFTP.ChangeDir('metamod'); - frmMain.ggeItem.Progress := 2; - FTPMakeDir('bin'); - frmMain.ggeItem.Progress := 3; - AddDone; - end - else - AddSkipped; - frmMain.ggeAll.Progress := 4; - frmMain.ggeItem.Progress := 3; - { Upload metaplugins.ini } - frmMain.ggeAll.Progress := 4; - frmMain.ggeItem.MaxValue := 1; - frmMain.ggeItem.Progress := 0; - AddStatus('Uploading metaplugins.ini...', clBlack); - if CopyConfig then begin - eStr.Clear; - eStr.SaveToFile(ExtractFilePath(ParamStr(0)) + 'metaplugins.ini'); - UploadFile(ExtractFilePath(ParamStr(0)) + 'metaplugins.ini', 'metaplugins.ini'); - DeleteFile(PChar(ExtractFilePath(ParamStr(0)) + 'metaplugins.ini')); - end - else - AddSkipped; - frmMain.ggeAll.Progress := 5; - frmMain.ggeItem.Progress := 1; - { Upload server.dll / server_i486.so } - frmMain.tmrSpeed.Enabled := True; - frmMain.ggeItem.Progress := 0; - frmMain.IdFTP.ChangeDir('bin'); - if OS = osWindows then begin - AddStatus('Uploading server.dll...', clBlack); - frmMain.ggeItem.MaxValue := FSize(ExtractFilePath(ParamStr(0)) + 'server.dll'); - UploadFile(ExtractFilePath(ParamStr(0)) + 'server.dll', 'server.dll'); - end - else begin - AddStatus('Uploading server_i486.so...', clBlack); - frmMain.ggeItem.MaxValue := FSize(ExtractFilePath(ParamStr(0)) + 'server_i486.so'); - UploadFile(ExtractFilePath(ParamStr(0)) + 'server_i486.so', 'server_i486.so'); - end; - { Remove created files } - AddStatus('Removing temporary files...', clBlack); - DeleteFile(PChar(ExtractFilePath(ParamStr(0)) + 'hl2launch.exe')); - DeleteFile(PChar(ExtractFilePath(ParamStr(0)) + 'server.dll')); - DeleteFile(PChar(ExtractFilePath(ParamStr(0)) + 'server_i486.so')); - AddDone; - { End } - frmMain.IdFTP.Disconnect; - frmMain.ggeAll.Progress := frmMain.ggeAll.MaxValue; - frmMain.ggeItem.Progress := frmMain.ggeItem.MaxValue; - AddStatus('', clBlack, False); - AddStatus('Finished installation!', clBlack, False); - frmMain.tmrSpeed.Enabled := False; - eStr.Free; - - Screen.Cursor := crDefault; - frmMain.cmdNext.Enabled := True; - frmMain.cmdCancel.Hide; - frmMain.cmdNext.Show; - frmMain.tmrSpeed.Enabled := False; - frmMain.Caption := Application.Title; -end; - -end. diff --git a/utils/mmsource/cruft/installer/UnitPackSystem.pas b/utils/mmsource/cruft/installer/UnitPackSystem.pas deleted file mode 100644 index db98ca950..000000000 --- a/utils/mmsource/cruft/installer/UnitPackSystem.pas +++ /dev/null @@ -1,222 +0,0 @@ -unit UnitPackSystem; - -interface - -uses SysUtils, Classes, Zlib; - -procedure CompressFiles(Files: TStrings; const Filename: String); -function DecompressStream(Stream: TMemoryStream; DestDirectory: String; const Source: Boolean): Boolean; -function AttachToFile(const AFileName: string; MemoryStream: TMemoryStream; Version: String): Boolean; -function LoadFromFile(const AFileName: string; MemoryStream: TMemoryStream): Boolean; -function Unpack(const Source: Boolean): Boolean; -function GetVersion: String; - -implementation - -uses UnitfrmMain; - -procedure CompressFiles(Files : TStrings; const Filename : String); -var - infile, outfile, tmpFile : TFileStream; - compr : TCompressionStream; - i,l : Integer; - s : String; - -begin - if Files.Count > 0 then - begin - outFile := TFileStream.Create(Filename,fmCreate); - try - { the number of files } - l := Files.Count; - outfile.Write(l,SizeOf(l)); - for i := 0 to Files.Count-1 do - begin - infile := TFileStream.Create(Files[i],fmOpenRead); - try - { the original filename } - s := ExtractFilename(Files[i]); - l := Length(s); - outfile.Write(l,SizeOf(l)); - outfile.Write(s[1],l); - { the original filesize } - l := infile.Size; - outfile.Write(l,SizeOf(l)); - { compress and store the file temporary} - tmpFile := TFileStream.Create('tmp',fmCreate); - compr := TCompressionStream.Create(clMax,tmpfile); - try - compr.CopyFrom(infile,l); - finally - compr.Free; - tmpFile.Free; - end; - { append the compressed file to the destination file } - tmpFile := TFileStream.Create('tmp',fmOpenRead); - try - l := tmpFile.Size; - outfile.WriteBuffer(l, SizeOf(l)); - outfile.CopyFrom(tmpFile,0); - finally - tmpFile.Free; - end; - finally - infile.Free; - end; - end; - finally - outfile.Free; - end; - DeleteFile('tmp'); - end; -end; - -function DecompressStream(Stream : TMemoryStream; DestDirectory : String; const Source: Boolean): Boolean; -var - dest,s : String; - decompr : TDecompressionStream; - outfile : TFilestream; - i,l,lr,c : Integer; -begin - // IncludeTrailingPathDelimiter (D6/D7 only) - dest := IncludeTrailingPathDelimiter(DestDirectory); - - Result := False; - try - { number of files } - Stream.Read(c,SizeOf(c)); - for i := 1 to c do begin - { read filename } - Stream.Read(l,SizeOf(l)); - SetLength(s,l); - Stream.Read(s[1],l); - Stream.Read(l,SizeOf(l)); - Stream.Read(lr,SizeOf(lr)); - { check if this is the right file } - if (s = 'hl2launch.exe') or ((Pos('.source', s) <> 0) and (Source)) or ((Pos('.orangebox', s) <> 0) and (not Source)) then begin - { remove extension and read filesize } - if (s <> 'hl2launch.exe') then - s := ChangeFileExt(s, ''); - { decompress the files and store it } - s := dest+s; //include the path - outfile := TFileStream.Create(s,fmCreate); - decompr := TDecompressionStream.Create(Stream); - try - outfile.CopyFrom(decompr,l); - finally - outfile.Free; - decompr.Free; - end; - end - else - Stream.Position := Stream.Position + lr; - end; - finally - Result := True; - end; -end; - -function AttachToFile(const AFileName: string; MemoryStream: TMemoryStream; Version: String): Boolean; -var - aStream: TFileStream; - iSize: Integer; -begin - Result := False; - if not FileExists(AFileName) then - Exit; - - try - aStream := TFileStream.Create(AFileName, fmOpenWrite or fmShareDenyWrite); - MemoryStream.Seek(0, soFromBeginning); - // seek to end of File - // ans Ende der Datei Seeken - aStream.Seek(0, soFromEnd); - // copy data from MemoryStream - // Daten vom MemoryStream kopieren - aStream.CopyFrom(MemoryStream, 0); - // save Stream-Size - // die Streamgre speichern - iSize := MemoryStream.Size + SizeOf(Integer); - aStream.Write(iSize, SizeOf(iSize)); - // save version number+length - iSize := aStream.Position; - aStream.Write(Version[1], Length(Version)); - aStream.Write(iSize, SizeOf(iSize)); - finally - aStream.Free; - end; - Result := True; -end; - -function LoadFromFile(const AFileName: string; MemoryStream: TMemoryStream): Boolean; -var - aStream: TMemoryStream; - iSize: Integer; - EndPos: Integer; -begin - Result := False; - if not FileExists(AFileName) then - Exit; - - try - aStream := TMemoryStream.Create; - aStream.LoadFromFile(AFileName); - // drop version part - aStream.Seek(-SizeOf(Integer), soFromEnd); - aStream.Read(EndPos, SizeOf(Integer)); - aStream.SetSize(EndPos); - // seek to position where Stream-Size is saved - // zur Position seeken wo Streamgre gespeichert - aStream.Seek(-SizeOf(Integer), soFromEnd); - aStream.Read(iSize, SizeOf(iSize)); - if iSize > aStream.Size then - begin - aStream.Free; - Exit; - end; - // seek to position where data is saved - // zur Position seeken an der die Daten abgelegt sind - aStream.Seek(-iSize, soFromEnd); - MemoryStream.SetSize(iSize - SizeOf(Integer)); - MemoryStream.CopyFrom(aStream, iSize - SizeOf(iSize)); - MemoryStream.Seek(0, soFromBeginning); - finally - aStream.Free; - end; - Result := True; -end; - -{ Unpack function } - -function Unpack(const Source: Boolean): Boolean; -var eStream: TMemoryStream; -begin - eStream := TMemoryStream.Create; - try - // Get ZIP - LoadFromFile(ParamStr(0), eStream); - DecompressStream(eStream, ExtractFilePath(ParamStr(0)), Source); // Unpack files - - Result := True; - except - Result := False; - end; - eStream.Free; -end; - -function GetVersion: String; -var FileStream: TFileStream; - EndPos, Size: Integer; - Version: String; -begin - FileStream := TFileStream.Create(ParamStr(0), fmOpenRead or fmShareDenyWrite); - FileStream.Seek(-SizeOf(Integer), soFromEnd); - FileStream.Read(EndPos, SizeOf(EndPos)); - FileStream.Position := EndPos; - Size := FileStream.Size - EndPos - SizeOf(Integer); - SetString(Result, nil, Size); - FileStream.Read(Pointer(Result)^, Size); // YAMS - FileStream.Free; -end; - -end. diff --git a/utils/mmsource/cruft/installer/UnitSelectModPath.dfm b/utils/mmsource/cruft/installer/UnitSelectModPath.dfm deleted file mode 100644 index 436262ce6..000000000 Binary files a/utils/mmsource/cruft/installer/UnitSelectModPath.dfm and /dev/null differ diff --git a/utils/mmsource/cruft/installer/UnitSelectModPath.pas b/utils/mmsource/cruft/installer/UnitSelectModPath.pas deleted file mode 100644 index 368d478ea..000000000 --- a/utils/mmsource/cruft/installer/UnitSelectModPath.pas +++ /dev/null @@ -1,26 +0,0 @@ -unit UnitSelectModPath; - -interface - -uses - SysUtils, Windows, Messages, Classes, Graphics, Controls, - StdCtrls, ExtCtrls, Forms, FileCtrl, ComCtrls, ShellCtrls, - TFlatComboBoxUnit, TFlatButtonUnit; - -type - TfrmSelectModPath = class(TForm) - pnlDesign: TPanel; - lblInfo: TLabel; - trvDirectory: TShellTreeView; - cmdOK: TFlatButton; - cmdCancel: TFlatButton; - end; - -var - frmSelectModPath: TfrmSelectModPath; - -implementation - -{$R *.DFM} - -end. diff --git a/utils/mmsource/cruft/installer/UnitfrmMain.dfm b/utils/mmsource/cruft/installer/UnitfrmMain.dfm deleted file mode 100644 index 14b183cb9..000000000 --- a/utils/mmsource/cruft/installer/UnitfrmMain.dfm +++ /dev/null @@ -1,11577 +0,0 @@ -object frmMain: TfrmMain - Left = 333 - Top = 271 - BorderIcons = [biSystemMenu, biMinimize] - BorderStyle = bsSingle - Caption = 'Metamod:Source Installer' - ClientHeight = 355 - ClientWidth = 527 - Color = clBtnFace - Font.Charset = DEFAULT_CHARSET - Font.Color = clWindowText - Font.Height = -11 - Font.Name = 'Tahoma' - Font.Style = [] - Icon.Data = { - 000001000C003030000001000800A80E0000C60000002020000001000800A808 - 00006E0F00001818000001000800C80600001618000010100000010008006805 - 0000DE1E0000808000000100200028080100462400006060000001002000A894 - 00006E2C010048480000010020008854000016C1010040400000010020002842 - 00009E1502003030000001002000A8250000C65702002020000001002000A810 - 00006E7D0200181800000100200088090000168E020010100000010020006804 - 00009E9702002800000030000000600000000100080000000000000900000000 - 0000000000000001000000010000000000003535360031393E003B3B3B00403E - 3E001D3642001E3C4C002A3B4400323B4100264150002C465400274C5F003E52 - 5D00214C62003A5A6B00205A7700205D7C00365E73002B627F00454343004846 - 46004647490048474800464A4D004A4848004C4A4A004D4D4D00504E4E004F4F - 50004F5050004351590053535300585656005457590055585800595858005C5B - 5B00595D5D005E5D5D00605F5F00595F600045616F005C6364005E696B004364 - 7500496A7B00596B72005B737B00636363006463630060656500666464006167 - 6B00636B6C006C6B6B00706E6E00606C70006370720068747600627479006979 - 7C007170700074737300767575007877770070777900797979007C7B7B007D7C - 7C0019668E0015699300336680002D6F91002C72970029729800337699003D7D - 9D001674A400327CA200476E820042728A005A79850051778B00567D8D005B7E - 8B00637D8500697D8200717C82001380B7002182B3002A82B000398CB7003E95 - BD005F8493006D8287006681890071808500788284007C888E00638C9B00688E - 9A0069919E0079959F00438CAE00488DAB00548CA300588FA600518FA9004B90 - AE005B91A6005594AF005993AA00408EB2004C93B2004C97B9004699BE004D99 - BA005496B100559AB7005E99B000539EBD00599DB800648FA6006397AA007098 - A8006A9CB300729EB50075A6BC007EA9BA001287C3001A8BC500118CCA00188E - CA000D95DB000D98DF001495D6001995D3001E98D5001195D800159ADD001C9B - DB00298EC2002596CD002A95CA003395C3003895C0003D9AC500329ACB00399B - CB002196D000239AD6002B9BD200239BD900319DD00024A0DF002CA1DC0032A0 - D70030A2DD000D9BE3000D9EE800119CE2001A9DE0000DA2EE001EA2E50013A4 - ED0019A5ED001DA8EF001AA7F0001CA8F00022A2E4002BA6E50021A7EB0028A7 - E80023A9ED002BABED0031A6E10034A9E50039ABE50033ACEA0039AEEA0037B0 - EE003CB2EE0024ABF0002BAEF00031AFF00033B1F1003CB4F100429AC3004C9E - C200529FC70070BADD0040B0E9004CB6EC0041B6F10047B8F2004CBAF30053BD - F3005BBEF10062BEED005BC0F40068C1EE007AC0E4007ACAEF0067C4F50069C5 - F50074C7F20078C7F00077CBF60078CBF5008281810086868600888787008B8A - 8A0086979D0090909100979B9F0099989800959DA2008FA0A60093A4AC0080AB - BE009AAEB500A5A4A400A3ADAD00AEBABA0084AFC60093B5C7009EB7C2009DBB - CA00A7BBC500AABCC30093C1D50099C2D700B1C3CA00A6C9DA00B1CAD40084CD - F1008ACFF20087D1F7008AD0F30094D5F6009ED7F5009ED8F60095D6F800A7D2 - E600B4DBED00A3DAF600ABDDF700A4DCF800AFE0F800BFE5F600B2E1F900BBE4 - F900CBE6F300CCE8F500C0E6FA00000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - D13F3F3F42D10000000000000000000000000000000000000000000000000000 - 00000000000000000000000042231814141413141418181B3100000000000000 - 0000000000000000000000000000000000000000000000000000311814141414 - 141414141414141414141F420000000000000000000000000000000000000000 - 00000000000000003F14141414181F2A2F5154542F2B2218181414141F000000 - 00000000000000000000000000000000000000000000001F1314141F3969BB9C - 9CB0AFAFAF9D9471511F181414143F0000000000000000000000000000000000 - 000000000000181814183B729DAFB2B5B5B5B5C1B5B5B3B09D94531F18141331 - 000000000000000000000000000000000000000000181814236F9BAFAEB4B5B5 - B5B5B5B5B5B5B5B5B4B2AF912B18161323000000000000000000000000000000 - 000000001818182BBB9AAAAEB4B9B9B9B9B9B9B9B5B9BAB9B5B9B2AF96511818 - 183100000000000000000000000000000000002018182B929AACB7B7B7B7B7B7 - B8B8B8B8B7B9B7B9B9B8B7B7AF9A531818183F00000000000000000000000000 - 00003F14142ABBA1ABB6B6B6B6B6B6B6B6B6B7B7B7B7B7AFAFB7B7B7B69A962F - 18161800000000000000000000000000000018141F6E8BA3A84A2C2D2D8FB6B6 - B6B6A8A8B6B6B650214F5BACB6ACA38F2A161423000000000000000000000000 - 00311814558CA0A7A38804181F29A3A8A7A8A8A8B6A7A11F1F201F21508DA3A3 - 671818180000000000000000000000000014142292A0A4A7A2A710131B185AA7 - A7A7A7A7A2A74B1F1B1B1B1B1812A8A4872F1814230000000000000000000000 - 4218145F8A9FA4A2A7A28B0218180CA4A2A2A2A2A7A20C19160301130484A7A4 - A07018181800000000000000000000001F141F7286A2A2A2A2A2A24504181449 - A2A4A2A2A25916191410460506A4A2A486882A18183F00000000000000000000 - 14142A9B86A2A2A2A2A2A286071314178AA2A2A2A21116140383A2A285A2A2A2 - A28553181418000000000000000000001414568A9FA2A2A2A2A2A2A24D041314 - 47A2A2A28B1616140BA2A2A2A2A2A2A2A28670181818D10000000000000000D1 - 18186385A2A2A2A2A2A2A2A2A20913141684A7A24A1614044DA2A2A2A2A2A2A2 - A286901F14182300000000000000003F14186E86A2A2A2A2A2A2A2A2A2580114 - 160EA2A20C14140886A2A2A2A2A2A2A2A29F8F2216141800000000000000003F - 13187586A2A2A2A2A2A2A2A2A2A20D131414598413141310A2A2A2A2A2A2A2A2 - A29F952318141431000000000000003718187586A2A2A2A2A2A2A2A2A2A28401 - 13181E4814140481A2A2A2A2A2A2A2A2A29F952816141418000000000000003F - 13187785A2A2A2A2A2A2A2A2A2A2A21013181F181B180AA2A2A2A2A2A2A2A2A2 - A29F8F22141414143F000000000000D418186385A2A2A2A2A2A2A2A2A7A8B79A - 1723232723204EB6A8A2A2A2A2A2A2A2A286911F141414141B00000000000000 - 1418568786A2A2A2A2A2A7B7B8B9B9B94C2731313122B0B9B9B8A8A2A2A2A2A2 - A28667181614141414D300000000000014182A999FA2A2A2A2A7B8BABAC1C1C1 - B52B37373752C1B5C1B5BAB6A2A2A2A2A2855416141414141423000000000000 - 1F141D7586A2A2A2A2C1C3C3C3C3C3C3C37A403F37BDC3C3C3C4C3C3A8A2A2A2 - 9F952A14141414141414000000000000D118185E8B86A2A2B8C7C7C7C7C7C7C7 - C762D1D157C5C7C7C7C7C7C7C3A2A2A2866C1818141414141414330000000000 - 00141422BC86A2A2C1CCCCCCCCCCCCCCBED4D4D47ECCCCCCCCCCCCCCCCA7A286 - 893B141818181B18181418000000000000401414568986A2C7CFCFCFCFE1DBD9 - D9D8D8D6C9CFCFCFCFCFCFCFCFA7A2866B181D7D7F7F7F7F5616184000000000 - 000018141F7B869FC1EEEEEEEEE2DEDEDEDEDEDBEEEEEEEEEEEEEEEECFA28690 - 2A1618BEEE807C7C3B16141F000000000000DF1314237886A3EEF3F3F3E4DEDE - DEDEDEE8F3F3F3F3F3F3F3F3C286963B1318182ECA7F23141414141400000000 - 00000037131832BC86B4F8F8F8EAE6E6E6E6E5F6F8F8F8F8F8F8F8CDA0965518 - 181618185DEE661B1414141433000000000000001F16182A798AB0F2FBFBFBFB - FBFBFBFBFBFBFBFBFBF9CC8B8F3B181414141414187DED60181414141F000000 - 000000000018181822659B8BC6F9FFFFFFFFFFFFFFFFFFFCECB0877135181814 - 14141414181FE7F4311814141B0000000000000000001F141418397B9B8AB0CC - EDF2F6F6F3CAC08C8973551F141414141414181F1F1735FBD518141420000000 - 0000000000000034141814183564789389878B87879B736D3C1D181414141414 - 14141DF5DD182AFADA181414420000000000000000000000E018181814181C23 - 3A3C56563A2A1F181818131414141414141418E3FEDDEBFE4114141B00000000 - 00000000000000000000D1181814181818181414141414181418181414141414 - 1416181FDBE9E661181814000000000000000000000000000000000000371814 - 1414141414141414141414141414141414141418181818181823000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000FFFFFFFFFFFF0000FFFFFFFFFFFF0000FFFF - FFFFFFFF0000FFFFFFFFFFFF0000FFFFC0FFFFFF0000FFFC001FFFFF0000FFF0 - 0003FFFF0000FFC00001FFFF0000FF8000007FFF0000FF0000003FFF0000FE00 - 00001FFF0000FC0000000FFF0000F800000007FF0000F000000007FF0000F000 - 000003FF0000E000000003FF0000E000000001FF0000C000000001FF0000C000 - 000000FF0000C000000000FF0000C0000000007F000080000000007F00008000 - 0000007F000080000000003F000080000000003F000080000000001F00008000 - 0000001F0000C0000000000F0000C0000000000F0000C0000000000F0000C000 - 000000070000E000000000070000E000000000030000F000000000030000F000 - 000000030000F800000000010000FC00000000010000FE00000000010000FF00 - 000000010000FF80000000010000FFC0000000030000FFF0000000070000FFFE - 0000000F0000FFFFFFFFFFFF0000FFFFFFFFFFFF0000FFFFFFFFFFFF0000FFFF - FFFFFFFF0000FFFFFFFFFFFF0000280000002000000040000000010008000000 - 00000004000000000000000000000001000000010000000000003E3D3D003042 - 4C0034444D003D464B002A495A00384B55002C51650024536C003C5968003B5B - 6D0034637B004240400045434300474545004846460046484900454B4F004A48 - 48004C4A4A004C4B4C004D4D4D00504E4E004D4E50004F50500041515B004555 - 5E005050500054525200535455005654540055595900555B5D00565C5E005A59 - 59005D5B5B00595C5D005F5E5E00605F5F00505B6000565F6100585F62005C61 - 61005A6064005261680056676D005C65690057696F005B686B005C6A6E004068 - 7D004E6A790052687100586B71005C6D7100596F7700526D780051717E006261 - 610064636300666464006B6A6A006C6B6B006E6D6D006C75780069767C007170 - 70007473730075747400787777007E7E7E00176288001F678D001D6E98001670 - 9E003B6E890029769E00397D9F001874A3001678AA00247AA700357DA2003C7F - A1004D758700497588005B7B8600507B8E00457A9500647E8900757F82001385 - BF001F88BE002981AE003E82A2003989AF003D88AE002183B500358CB6003C8D - B3003A95BF004D839A004D849C005F82910056879B0051879E005A879E006788 - 9700688997004083A1004583A0004C87A0004D88A3004888A5004488A800468C - AC00498DAB00508EA9004892B5004093B9007699A60071A1B6001E91CB001192 - D4001297DB001698D900199ADA001A9BDD001E9EDE002491C8002999CF002E99 - CE003D97C1003798C6003A98C4003399C900369AC900379BCC003A9AC8002498 - D400239CD700269CD6002E9DD2002B9DD500239EDD0026A1DF0033A2DA000D9A - E2000D9BE4000D9DE6000D9EE900129AE000179DE200149FE600189EE1000EA2 - EE001FA2E50014A1E90010A2EE0012A4EF0015A5EE001CA4EA0019A6EE0019A7 - F0001BA8F00027A6E60029A3E1002BA4E2002BA8E70025A8EB0026ABEF002EAE - EF0033A6E00031A8E40034ABE7003CACE60037AEEB0032AFEF0035AFED003AAF - EA0039B0ED003DB3EE0022AAF00024ABF00027ACF0002AADF0002DAEF10030B0 - F10035B1F10038B2F1003DB4F000439AC300429FCB0040A2D10040A3D40069AD - D00062B0D8007EBAD5004DB0E30049B1E60045B8F20049B9F3004FBAF10058BF - F30059BFF4005EC1F4006DC2ED007DCAEE0074CAF5007FCAF0007CCDF5008281 - 810085848400879396008B94940088969E0096959500989797008F9FA80087AB - BA0088ABBE0099ACB4009EAFB6009BB0BC00A5A4A400A6B3BA00A6B4BA0080B3 - CD0091B9CD00A4BFCC00ADCBD800B1CCD800B9CFD80081CCF2008AD1F60097D4 - F4009FD9F800A3CDE100A1D6F100A1D9F500ADDEF700A0DAF800B5E2F9000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 3F1E161616162244000000000000000000000000000000000000000000001E12 - 12161216160F121212220000000000000000000000000000000000003A12161F - 5675BFC1C1BE7038161612440000000000000000000000000000001E121E7091 - ADB1B4B4B4B4B2AD8439160F3A000000000000000000000000001E123488A7B1 - BBBBBBBBBBBCBBBCB1A57116163A00000000000000000000003A162D8EA8B7B7 - B7B7B7B7BBB9B9BBB7B1A461160F4600000000000000000000121F82A0804D52 - A5B6B6B6B6B6A5395FA5A89B6D16120000000000000000001E1672989F990416 - 4BA2A2A2A2A3511E1B1E327F7E34123F0000000000000000122E7C9F9D9F490F - 16799F9F9F9F1A16010F069F9F61121600000000000000440F70939D9D9D9502 - 0F0A9D9D9D5B120F4A474A9F957B280FD20000000000001E1684959D9D9D9D4F - 0C0F609D9D0B0F039D9D9D9D9D93540F1E000000000000121E8B9D9D9D9D9A9D - 050F199593100F489D9D9D9D9D935D120F0000000000000F2A7C9D9D9A9A9A9D - 5A010F4C5012017A9D9D9A9A9A9A5E0F122200000000000F2A7C9D9D9D9A9A9A - 9A080F11090F079D9D9A9A9A9A955E0F161600000000000F1F8B9D9D9A9A9A9D - 9F8B161F221E5C9F9D9A9A9A9A945D0F0F0F3F000000001E1684959D9A9AA3BB - BBBB573A3D29B1BBB99D9A9A9A94540F0F0F1600000000441268939D9AA3C8C8 - C8C8C5444469C8C8C8C89D9D9A7A28100F0F12D200000000122A7E9A9DCACCCC - CCCCC2D2D2C3CCCCCCCCBD9A9561160F12120F1E00000000221674939FCFCFCF - E2DBD9D7D6CFCFCFCFCFCA9D7B2D276A6A6A2A1000000000000F1F8893D1E9E9 - DEDFDFDFE3E9E9E9E9E9C89264102CCE77581F0F3A00000000D50F318EB4EEF0 - E4E1E1E1EDF0F0F0F0E99871150F1066C41E11121200000000002E102A84AEEE - F1F1F1F1F1F1F1F1E88F6E150F0F0F0F78DA160F120000000000002E161D688E - C5D0EEEFEFEACDAB633716120F0F16151DEC40121200000000000000D40F121F - 5574638884766537160F0F0F0F0F41E61FE55912160000000000000000003A0F - 0F0F1616160F12121212120F0F0F16DCE7DC1B12000000000000000000000000 - D83F1E0F0F1212120F120F0F0F0F0F0F16163D00000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFF - FFFFFFC03FFFFF000FFFFC0003FFF80001FFF00000FFE000007FE000007FC000 - 003FC000003F8000001F8000001F8000001F8000000F8000000F800000078000 - 000780000003C0000003C0000003E0000001E0000001F0000001F8000001FC00 - 0001FF000003FFC00007FFFFFFFFFFFFFFFFFFFFFFFF28000000180000003000 - 0000010008000000000040020000000000000000000000010000000100000000 - 00003E41430039424800384851002C5B73002B5C7600345E7300464444004846 - 460045494C004A4848004C4A4A004E4D4D00454B50004D51530041525C004656 - 5F004F595D005151510054535300535455005554540058565600525859005559 - 5A00525B5E00545A5C00525C5F005B5A5A005C5B5B00595E5F005E5D5D00605F - 5F0043576200455862004F5F6800535B6000525D6100585F62004D616A005061 - 67005461670059606300596264005262690056676D00516872004F707E006065 - 670061676A006A6969006E6D6D00706F6F006972760064747D00727171007473 - 73001D6F9A002164860033658000226A900029779F003E7894001478AC00436B - 8100466F82004A7183004C74850048758A004D7A8E005D7C8B0042779300497A - 90004F7F9400467F9900497F9800607C8B001682B9003882A8002686B800348B - B500398EB5003D8EB400318CB9006E8089004583A0004A87A2004789A800428B - AD00438EB0004590B5005499BC00729FB20075A3BB001386C1001D8AC1001192 - D4001694D5001E95D1001799DB00129ADF001D9AD9001F9FDF002D95CA003296 - C6002FA0DA0037A1D6003CA1D30031A2DB0039A6DC000F9AE0000D9CE6000D9E - E900109AE0000DA0EB000DA2EE0018A1E70010A0E90011A3EE0011A4EF0014A4 - EE001CA8EF001EA9F00022A1E10027A5E5002DA7E50023A7EA002EABEB002EAC - EC0036AAE50035AFEE0039ADE80022AAF00026ACF00029ADF0002CAEF00036B2 - F10038B3F1003FB5F20042A0CC0049A9D7006AA7C70076B2CD007AB1C80046AE - E30054B3E30056B5E5005BB8E70045B7F10046B8F2004DBAF30062C2F40066C4 - F4007FCEF60081818100868686008A8989009897970099989800989C9E009E9D - 9E009CA0A3008BA5B000A2AEAE00A7B1B600B2B1B1008DB9CC00A9BDC500A2BF - CD0085C0DE009FCDE50080CBF20086CEF20091D4F6009CD7F6009CD8F800B8E3 - F900B9E4FA000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000331F1F1F370000000000 - 00000000000000000000009C0C08122528190C08120000000000000000000000 - 0000200C2E5A6D8183816B55190833000000000000000000001F0C557D828889 - 898989826C420C320000000000000000370C5284858686868686827F867C4408 - 9B000000000000000C4B74621040797A85794E25476766270C00000000000033 - 19657676050C4F767676220A080676500A9B00000000000C4470737360011070 - 765F08053F5E7671190C00000000000851737373733A083D733B084D73737370 - 400C00000000000C68737373736E020D60090373737373733E081F0000000008 - 6873737373733908220C3C73737373703E080800000000085173737376867F23 - 201F69847673736E410A08340000000C456E737A9595955B374C949589767371 - 2508080C00000037196673969797975D9B8D9797978873500C080C089B000000 - 08496E9799A9A1A0A0ABAB99999463284C8F5C2512000000A30C5983AFAAA4A4 - A8AFAFAFAD7B420C0E8E26080800000000360C5690AEB1B1B1B1B1996B2F0808 - 0828A612089C00000000540C28598C9293928B4B190808083530A23508000000 - 0000000016080C262B190C080808080831A7A71220000000000000000000A5A0 - 9D9D9D9D9D9D9D9D9DA0A0A50000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000000000000000000000FFFF - FF00FFFFFF00FF07FF00F801FF00F0007F00E0003F00C0001F00C0001F008000 - 0F0080000F0080000F008000070080000700800003008000030080000100C000 - 0100C0000100E0000000F0000100FC000100FF000300FFFFFF00FFFFFF002800 - 0000100000002000000001000800000000000001000000000000000000000001 - 000000010000000000003D525D00315467002E5F79004345470048464600434A - 4E004A4949004D4D4E00514F4F004F5050004D5357004A585E004C585E005152 - 52005253540053545500555758005E5D5D00475C67004A5A6200525D62004F60 - 67004B606B0058686F00436677004D6671004A6774004B68760042667800466C - 7E00496A7900486D7D0069686800647077007171710031698600306B8A003B7C - 9B003C7C9A00187FB4002F7CA3002B7DA700437085004372880047758B004777 - 8E005E7D8C001E87BC002D8AB8002D8CBB005B8094006B899600718793007A9A - A80078A4BB001386C2001C8CC6001196DA003B97C5003295C800359BCF002199 - D500249EDC002E9FD8002AA0DB0037A0D40031A2DC000F9DE600139BE0000DA0 - EA000EA2EE0014A3EB0015A5EF0027AAEC003CADE60036AFEC0027ACF00029AD - F0002CAEF00035B1F1003AB3F0003DB5F1004E9BC10058AAD20071B8DD0040B5 - F10069C5F500818080008B8A8A008D8D8D00808E95008599A40097A9B100A6AC - AF00A9AEAF00AEB5B500A3B2BA00B4B4B40097CFEB0083CBF0008DD0F20090D4 - F70095D6F70095D6F800ABDEF800AFDFF8000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000058580000 - 000000000000000000580A1B2E2E17085900000000000000211C424C51514C3B - 14230000000000591F3F3C4A4D4E3D43410C00000000000F3E48012948491708 - 293209000000001E46462806453904383A440C00000062264647470225240346 - 47461D1200006226464747390A0B304747461D050000001F4649525233225650 - 47460B08210000113E5257555C3757574F3215180F0000601F4B68615E636868 - 410C2F3408590000351B54656A6A64530C0508360F230000005F0F1B2E2B1408 - 05055B5D11000000000000000000000000000000000000000000000000000000 - 000000000000FFFF0000FCFF0000E01F0000C00F0000800F0000800700008007 - 00000003000000030000800100008001000080000000C0000000E0010000FFFF - 0000FFFF00002800000080000000000100000100200000000000000801000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000007F7F - 7F017F7F7F017F7F7F017F7F7F017F7F7F017F7F7F017F7F7F017F7F7F017F7F - 7F01000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000100000002000000040000000500000007000000080000000A0000 - 000C0000000D0000000D0000000E0000000E0000000E0000000D0000000D0000 - 000C0000000A0000000800000007000000050000000300000002000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000100000003000000050000 - 00090000000C0000001000000014000000180000001C0000001F000000230000 - 0025000000270000002800000028000000280000002800000028000000270000 - 0025000000220000001F0000001C00000017000000130000000F0000000B0000 - 0007000000040000000200000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000100000003000000070000000C00000012000000180000 - 001F000000250000002C00000032000000370000003B0000003E000000410000 - 0043000000450000004500000046000000460000004600000045000000450000 - 0043000000410000003E0000003B00000036000000310000002B000000240000 - 001D00000016000000100000000A000000060000000300000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0003000000070000000C000000130000001B000000250000002E000000360000 - 003D00000043000000480000004B0000004E0000005100000052000000540000 - 0055000000550000005500000056000000560000005600000055000000550000 - 00540000005400000052000000500000004E0000004B00000047000000420000 - 003B000000340000002B0000002200000019000000110000000A000000050000 - 0001000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000001211110100000004000000090000 - 00100000001A00000025000000300000003A00000042000000490000004E0000 - 005203030357161616761F1E1E91242323A9343333BE3D3C3CD0403E3ED84543 - 43EA454343EA454343EA454343EA454343EA454343EA454343EA403E3ED83C3A - 3ACD323131BB232222A71E1D1D8C141414720000005700000056000000540000 - 00510000004C0000004700000040000000370000002C00000020000000160000 - 000E000000070000000300000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000012111101000000040000000A000000130000001F0000 - 002B00000037000000410000004A000000500908085E1F1E1E902D2C2CB54240 - 40E0484646FC494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF474545F73F3D3DD5292828AC1A1A - 1A820505055D00000056000000530000004E000000470000003E000000330000 - 00260000001A0000001000000008000000030000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000012111101000000040000000A00000014000000210000002F0000003B0000 - 00460000004E0F0F0F69262525A5403E3ED7494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF474545F7393737C8201F1F940707076000000055000000510000004B0000 - 0043000000370000002A0000001B000000100000000700000002000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00030000000800000012000000200000002F0000003D0000004805050555201F - 1F94403E3ED7494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF474545F7343232C01817177D000000570000 - 00540000004E0000004400000038000000290000001A0000000E000000061211 - 1101000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000012111101000000050000 - 000F0000001C0000002C0000003B000000480B0B0B612E2D2DB2474545F44947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF413F3FE02221 - 21970302025A000000540000004E000000440000003600000026000000160000 - 000B000000031211110100000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000300000009000000160000 - 002600000037000000460D0D0D65353333BF484646FA494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF454444EF262525A10505055C000000540000004C00000041000000310000 - 001F000000100000000712111101000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000002F3F3F01000000050000000E0000001D0000002F0000 - 0040090909572F2E2EB3484646FA494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF4A4848FF4A48 - 48FF4A4949FF4A4949FF4A4949FF4A4949FF4A4848FF4A4848FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF444242E7212020940000005700000052000000490000 - 003A00000028000000170000000A000000030000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000002F3F3F0100000007000000130000002400000037000000472524 - 2497474545F4494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF4A4949FF4C4B4BFF4F4F4FFF515353FF555757FF585C5CFF5B6060FF5D63 - 63FF5F6565FF606767FF606767FF5F6565FF5E6363FF5C6060FF585C5CFF5558 - 58FF525353FF4F4F4FFF4C4C4CFF4B4949FF494848FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF3F3D3DDB12121277000000550000 - 004E00000042000000300000001D0000000E000000052F3F3F01000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000020000000A000000170000002A0000003E111111673F3D3DD94947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF4A4949FF4D4C4CFF515252FF585B - 5BFF5F6565FF677070FF707B7BFF778787FF7D9293FF7D999EFF7B9EA7FF76A1 - ADFF72A2B1FF70A2B3FF70A2B3FF70A1B2FF73A0AEFF779EA9FF7B9AA0FF7B92 - 95FF78898AFF717E7EFF697272FF616767FF595C5CFF525353FF4D4D4DFF4B49 - 49FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF484646FC2F2E2EB30505 - 055C0000005200000048000000370000002300000011000000062F3F3F010000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00030000000C0000001B0000002F000000422928289B484646F9494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF4A4848FF4D4D4DFF535555FF5C6060FF687070FF768484FF7F97 - 9AFF74A1AEFF5DA1BCFF479FC6FF379DCDFF2899D1FF1F97D2FF1E96D4FF2098 - D5FF229AD6FF249BD7FF259BD7FF229AD6FF2199D6FF1E96D4FF1D96D3FF2197 - D1FF2D9ACFFF3C9CC8FF4F9DBEFF669EB2FF78989FFF778788FF6A7474FF5D63 - 63FF545656FF4E4E4EFF4A4949FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4341 - 41E512121277000000550000004B0000003C0000002800000014000000073F3F - 3F01000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000030000 - 000D0000001E000000330B0A0A543B3939CD494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4B4A - 4AFF505151FF595D5DFF677070FF798889FF7E9EA5FF65A4BCFF409FCAFF2498 - D1FF1E97D5FF269CD8FF2CA0DBFF2EA2DDFF30A3DEFF31A4DFFF32A5E0FF33A6 - E1FF33A6E1FF34A6E1FF34A6E1FF34A6E1FF33A6E1FF33A5E0FF32A5E0FF31A4 - DFFF30A2DDFF2DA1DCFF279DD9FF1F98D6FF1B94D2FF2C99CDFF4E9DBFFF709D - ABFF798C8EFF6A7474FF5C6060FF515252FF4C4B4BFF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF484646FC2726269F000000560000004E000000400000002B000000170000 - 0008000000020000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000030000000D0000 - 001F0000003513121269444242E9494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF4C4B4BFF525353FF5E63 - 63FF707C7CFF80999CFF6BA5BAFF3A9ECCFF2097D3FF239AD7FF2BA0DBFF2EA2 - DDFF30A4DFFF32A6E1FF34A7E2FF35A9E4FF37AAE5FF37ABE6FF38ACE6FF39AC - E7FF39ADE8FF3AADE8FF3AADE8FF3AADE8FF3AACE7FF39ACE7FF38ACE6FF38AB - E6FF37AAE5FF35A9E3FF33A7E2FF32A5E0FF30A4DFFF2DA1DCFF269CD8FF1B95 - D4FF2697CFFF4D9DBFFF7599A3FF738181FF606767FF535555FF4C4C4CFF4948 - 48FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF363434C30707075E00000050000000420000002D0000 - 0018000000090000000200000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000030000000D0000001F0000 - 0036201F1F80474545F7494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF4B4A4AFF515252FF5F6464FF738080FF80A0 - A6FF57A4C3FF2899D1FF2198D6FF2A9FDBFF2DA2DEFF30A5E0FF32A7E3FF34A9 - E5FF36ABE7FF37ACE8FF39AEE9FF3AAEEAFF3BAFEBFF3CB1ECFF3DB1ECFF3DB1 - ECFF3DB1EDFF3EB2EDFF3EB2EDFF3EB2EDFF3EB1ECFF3EB1ECFF3DB1ECFF3DB0 - ECFF3CB0EBFF3BAEEAFF3AAEE9FF38ACE8FF37ABE6FF34A8E4FF32A6E1FF30A4 - DFFF2CA1DCFF239BD8FF1994D2FF389AC8FF6C9DADFF758587FF616868FF5355 - 55FF4C4B4BFF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF3F3D3DDD0B0B0B6700000051000000440000 - 002F000000190000000903223202000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000030000000C0000001F000000362928 - 2894484646FC494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF4A4848FF4F4F4FFF5B6060FF717C7CFF82A0A5FF51A3C5FF2398 - D2FF249BD8FF2AA0DCFF2DA3E0FF30A6E3FF32A8E5FF35ABE7FF36ACE9FF38AE - EAFF39B0EBFF3BB0ECFF3CB1EDFF3DB2EEFF3DB3EEFF3EB3EFFF3EB3EFFF3FB4 - F0FF3FB4F0FF3FB4F0FF40B4F0FF40B4F0FF40B4F0FF40B4EFFF3FB4EFFF3FB3 - EFFF3EB2EEFF3EB2EEFF3DB2EDFF3CB1ECFF3BB0EBFF39AEEAFF37ADE9FF35AA - E6FF33A8E4FF30A5E1FF2DA2DEFF279DDAFF1A95D3FF3099CAFF6A9CAEFF7483 - 83FF5E6464FF505151FF4A4949FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF444242EA0F0E0E71000000520000 - 00440000002F00000018000000082F3F3F010000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000020000000B0000001D000000352A2929974947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF4C4B4BFF555858FF687171FF81989AFF5EA6C2FF2498D1FF249BD8FF29A0 - DCFF2CA4E0FF2FA6E3FF31A9E6FF34ABE9FF36AEEAFF38AFECFF39B0EDFF3AB1 - EEFF3BB2EFFF3CB3EFFF3DB3F0FF3DB4F0FF3DB4F1FF3EB5F1FF3EB5F1FF3EB5 - F1FF3EB5F1FF3FB5F1FF3FB5F2FF3FB5F1FF3FB5F2FF3FB5F2FF3FB5F1FF3FB5 - F1FF3FB5F1FF3FB4F0FF3EB4F0FF3EB3EFFF3DB3EFFF3CB2EDFF3BB1ECFF39AF - EBFF37ADEAFF35ABE8FF32A9E5FF2FA6E2FF2CA2DFFF269DDAFF1894D3FF3699 - C7FF7399A4FF6C7777FF585B5BFF4D4C4CFF494848FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF454444EF121111740000 - 0052000000430000002D00000017000000072F3F3F0100000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000002F3F3F01000000090000001A000000322B292996494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF4A4848FF4F4F - 4FFF5D6262FF778686FF79A8B5FF319CCEFF2098D6FF279EDBFF2AA2DFFF2DA6 - E3FF30A9E7FF32ABEAFF35ADEBFF37AFEDFF38B0EEFF39B1EFFF39B2F0FF39B3 - F0FF3AB3F0FF3BB4F1FF3BB4F1FF3CB5F2FF3CB5F2FF3CB5F2FF3CB5F2FF3CB5 - F2FF3DB5F2FF3DB5F2FF3DB5F2FF3DB5F2FF3DB5F2FF3DB5F2FF3DB5F2FF3EB5 - F2FF3EB5F2FF3EB5F1FF3EB5F1FF3DB4F1FF3DB4F1FF3DB3F0FF3CB3EFFF3BB2 - EFFF3AB1EDFF39AFECFF37AEEAFF34ABE8FF31A8E5FF2DA5E2FF2AA1DEFF239B - D9FF1893D1FF519DBDFF768C8FFF616767FF515252FF4A4949FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF474545F71413 - 137C00000051000000420000002B00000014000000062F3F3F01000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00002F3F3F0100000007000000160000002F2B2A2A94494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF4B4949FF535454FF666E - 6EFF829A9CFF55A5C6FF1F96D3FF249CDAFF27A0DEFF2AA4E3FF2DA8E6FF30AA - E9FF32ADEBFF34AEEDFF36B0EEFF37B1EFFF38B2F0FF38B2F0FF39B2F1FF39B3 - F1FF39B3F2FF39B4F2FF39B4F2FF39B4F2FF39B4F2FF3AB4F2FF3AB4F2FF3AB4 - F2FF3AB4F2FF3BB4F2FF3BB4F2FF3BB4F2FF3BB4F2FF3BB4F2FF3BB4F2FF3BB4 - F2FF3CB4F2FF3CB5F2FF3CB5F2FF3CB5F2FF3CB5F2FF3CB4F1FF3BB4F1FF3BB4 - F0FF3AB3F0FF39B2EFFF39B1EEFF38AFECFF35ADEBFF32AAE8FF2FA7E4FF2BA3 - E0FF289FDCFF1C97D6FF2B98CBFF6F99A7FF6A7575FF555757FF4C4B4BFF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4544 - 44EF0F0E0E71000000500000003F000000270000001100000004000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000500000012000000292322227E494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF4C4B4BFF565858FF6E7979FF81A5 - ADFF369DCEFF1E97D6FF249EDCFF28A2E1FF2AA5E5FF2DA9E8FF2FACEAFF31AD - ECFF33AFEEFF34B0EFFF35B1F0FF35B1F1FF36B2F1FF36B2F2FF37B2F2FF37B3 - F2FF37B3F2FF37B3F2FF37B3F2FF38B3F2FF38B3F2FF38B3F2FF38B3F2FF38B3 - F2FF38B3F2FF39B3F2FF39B3F2FF39B3F2FF39B3F2FF39B3F2FF39B3F2FF39B3 - F2FF39B4F2FF39B4F2FF39B4F2FF39B4F2FF39B4F2FF39B4F2FF39B4F2FF39B3 - F1FF39B3F1FF39B3F0FF39B2F0FF38B1EFFF37B0EEFF35AEECFF32ACEAFF2FA9 - E7FF2CA5E3FF29A1DEFF229BD9FF1A93D1FF599DB8FF728081FF595D5DFF4C4C - 4CFF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF454444EF0C0C0C680000004E0000003B000000220000000D000000030000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00030000000D0000002315141465484646F9494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF4C4C4CFF595D5DFF758383FF79AAB9FF2598 - D1FF209AD8FF249FDDFF27A3E2FF29A7E6FF2CAAEAFF2EACECFF30ADEEFF31AF - EFFF32AFF0FF32B0F1FF33B0F1FF33B1F1FF33B1F1FF34B1F1FF34B1F2FF34B1 - F2FF34B1F2FF35B1F2FF35B1F2FF35B1F2FF35B2F2FF35B2F2FF36B2F2FF36B2 - F2FF36B2F2FF36B2F2FF36B2F2FF36B2F2FF37B2F2FF37B2F2FF37B3F2FF37B3 - F2FF37B3F2FF37B3F2FF37B3F2FF38B3F2FF38B3F2FF38B3F2FF38B3F2FF38B3 - F2FF38B3F2FF38B3F2FF38B2F1FF37B2F0FF37B1F0FF36B0EFFF34AEEDFF32AD - EBFF2FAAE9FF2BA6E5FF28A2E0FF249DDCFF1694D3FF469CC2FF778A8DFF5C61 - 61FF4E4E4EFF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF424040E50707075D0000004B000000360000001D0000000A2F3F - 3F01000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000002F3F3F010000 - 00090000001C0D0D0D4B464444ED494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF4D4C4CFF5B6060FF7A8A8AFF6BAAC1FF1D95D2FF209A - D9FF239FDEFF26A3E4FF29A7E8FF2BAAEBFF2CABEDFF2EADEEFF2FAFEFFF2FAF - F0FF30AFF0FF30B0F1FF30B0F1FF31B0F1FF31B0F1FF31B0F1FF31B0F1FF32B0 - F1FF32B0F1FF32B1F1FF32B1F1FF32B1F1FF32B1F1FF33B1F1FF33B1F1FF33B1 - F1FF33B1F1FF33B1F1FF33B1F1FF34B1F1FF34B1F1FF34B1F2FF34B1F2FF35B1 - F2FF35B1F2FF35B1F2FF35B1F2FF35B2F2FF35B2F2FF35B2F2FF36B2F2FF36B2 - F2FF36B2F2FF36B2F2FF36B2F2FF36B2F2FF36B1F1FF35B1F0FF34B0F0FF33AF - EEFF31ADECFF2FABEAFF2BA7E7FF28A3E2FF249EDDFF1995D5FF3298C8FF7891 - 95FF5F6565FF4E4E4EFF4A4848FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF3A3939D003030357000000470000002F000000160000 - 0006000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000050000 - 0015040404313F3D3DD2494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF4D4C4CFF5C6161FF7D8D8EFF61A8C5FF1A95D3FF1E9ADAFF22A0 - E0FF24A4E5FF27A7E9FF29AAEBFF2AABEDFF2BADEFFF2CAEEFFF2DAEF0FF2DAF - F1FF2EAFF1FF2EAFF1FF2EAFF1FF2EAFF1FF2EAFF1FF2EAFF1FF2FAFF1FF2FB0 - F1FF2FB0F1FF2FB0F1FF2FB0F1FF2FB0F1FF30B0F1FF30B0F1FF30B0F1FF30B0 - F1FF30B0F1FF30B0F1FF31B0F1FF31B0F1FF31B0F1FF31B0F1FF31B0F1FF31B0 - F1FF32B0F1FF32B0F1FF32B1F1FF32B1F1FF32B1F1FF32B1F1FF33B1F1FF33B1 - F1FF33B1F1FF33B1F1FF33B1F1FF33B1F1FF33B1F1FF33B1F1FF33B0F1FF32B0 - F0FF31AFEFFF30ADEDFF2DABEAFF2AA7E7FF27A4E3FF249FDDFF1A96D7FF2996 - CBFF75939AFF606767FF4E4E4EFF4A4848FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF2E2C2CAE0000005200000041000000270000 - 0010000000030000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000030000000E0000 - 0025302F2FA2494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF4C4B4BFF5B5F5FFF7C8D8EFF62AAC6FF1894D3FF1D9ADBFF209FE1FF23A4 - E6FF26A7E9FF28A9EBFF28ABEEFF29ACEFFF29ADF0FF2AADF0FF2AAEF1FF2BAE - F1FF2BAEF1FF2BAEF1FF2BAEF1FF2BAEF1FF2BAEF1FF2CAEF1FF2CAFF1FF2CAF - F1FF2CAFF1FF2DAFF1FF2DAFF1FF2DAFF1FF2DAFF1FF2DAFF1FF2DAFF1FF2EAF - F1FF2EAFF1FF2EAFF1FF2EAFF1FF2EAFF1FF2EAFF1FF2FAFF1FF2FB0F1FF2FB0 - F1FF2FB0F1FF2FB0F1FF2FB0F1FF2FB0F1FF30B0F1FF30B0F1FF30B0F1FF30B0 - F1FF30B0F1FF30B0F1FF31B0F1FF31B0F1FF31B0F1FF31B0F1FF31B0F1FF31AF - F0FF30AFF0FF2FAEEFFF2EADEDFF2CAAEBFF29A8E8FF26A3E3FF229EDEFF1A97 - D7FF2895CBFF75939AFF5F6565FF4E4E4EFF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF1B1B1B860000004E000000390000 - 001F0000000A1211110100000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000012111101000000080000001B1A19 - 1966494747FF494747FF494747FF494747FF494747FF494747FF494747FF4C4B - 4BFF585C5CFF798989FF67ABC4FF1894D3FF1B9ADAFF1E9EE0FF21A3E5FF24A7 - E9FF25A8ECFF27AAEEFF27ABEFFF28ACF0FF28ADF1FF28ADF1FF28ADF1FF28AD - F1FF28ADF1FF28ADF1FF29ADF1FF29ADF1FF29ADF1FF29ADF1FF29ADF1FF29AD - F1FF29ADF1FF2AADF1FF2AAEF1FF2AAEF1FF2AAEF1FF2AAEF1FF2AAEF1FF2BAE - F1FF2BAEF1FF2BAEF1FF2BAEF1FF2BAEF1FF2BAEF1FF2BAEF1FF2CAEF1FF2CAF - F1FF2DAFF1FF2DAFF1FF2DAFF1FF2DAFF1FF2DAFF1FF2DAFF1FF2DAFF1FF2DAF - F1FF2EAFF1FF2EAFF1FF2EAFF1FF2EAFF1FF2EAFF1FF2FAFF1FF2FAFF1FF2EAF - F1FF2EAFF0FF2EAEF0FF2DAEEFFF2CACEDFF2AAAECFF28A7E9FF24A2E4FF219E - DEFF1997D7FF2896CBFF789195FF5C6161FF4C4C4CFF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF464444F20A0A0A62000000480000 - 0030000000150000000500000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000400000012090909344543 - 43E6494747FF494747FF494747FF494747FF494747FF494747FF4B4949FF5558 - 58FF748181FF73ADC0FF1793D2FF1A99DAFF1C9EE0FF1FA2E5FF22A6E9FF23A8 - ECFF24A9EEFF25ABEFFF25ABF0FF25ACF1FF26ACF1FF26ACF1FF26ACF1FF27AC - F1FF27ACF1FF27ACF1FF27ACF1FF27ACF1FF27ACF1FF27ACF1FF27ACF1FF28AD - F1FF28ADF1FF28ADF1FF28ADF1FF28ADF1FF28ADF1FF28ADF1FF28ADF1FF28AD - F1FF28ADF1FF28ADF1FF29ADF1FF29ADF1FF29ADF1FF29ADF1FF29ADF1FF29AD - F1FF2AADF1FF2AADF1FF2AAEF1FF2AAEF1FF2AAEF1FF2AAEF1FF2AAEF1FF2BAE - F1FF2BAEF1FF2BAEF1FF2BAEF1FF2BAEF1FF2BAEF1FF2CAEF1FF2CAEF1FF2CAF - F1FF2CAFF1FF2CAEF0FF2BADF0FF2BADEFFF2AABEDFF28AAEBFF26A6E8FF23A2 - E4FF1F9DDEFF1796D6FF3298C8FF768A8DFF595D5DFF4C4B4BFF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF373535C8000000510000 - 0040000000240000000D00000002000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000121111010000000A0000001F313030A64947 - 47FF494747FF494747FF494747FF494747FF494747FF4A4848FF525353FF6D78 - 78FF80ACB7FF1F96D1FF1897D9FF1A9DDFFF1CA1E5FF1FA5E9FF21A7ECFF22A9 - EEFF22AAEFFF23AAF0FF23ABF0FF23ABF0FF23ABF0FF24ABF0FF24ABF0FF24AB - F0FF24ABF0FF24ABF0FF24ABF0FF25ABF0FF25ABF0FF25ACF1FF25ACF1FF25AC - F1FF25ACF1FF25ACF1FF26ACF1FF26ACF1FF26ACF1FF26ACF1FF27ACF1FF27AC - F1FF27ACF1FF27ACF1FF27ACF1FF27ACF1FF27ACF1FF27ACF1FF27ACF1FF28AD - F1FF28ADF1FF28ADF1FF28ADF1FF28ADF1FF28ADF1FF28ADF1FF28ADF1FF3F83 - A5FF3B8FBAFF2BA9E9FF29ADF1FF29ADF1FF29ADF1FF29ADF1FF29ADF1FF29AD - F1FF2AADF1FF29ADF1FF29ADF0FF29ADF0FF29ACEFFF28ABEDFF27A8EBFF24A6 - E8FF21A1E3FF1D9CDDFF1594D5FF469CC2FF728081FF555757FF4A4949FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF1F1E1E8D0000 - 004C000000350000001900000007000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000040000001417171754484646FC4947 - 47FF494747FF494747FF494747FF494747FF494747FF4F4F4FFF656C6CFF85A5 - AAFF299AD0FF1696D7FF189BDEFF1AA0E4FF1DA4E9FF1EA6EBFF1FA8EDFF20A9 - EEFF20A9EFFF21AAF0FF21AAF0FF21AAF0FF21AAF0FF21AAF0FF21AAF0FF21AA - F0FF22AAF0FF22ABF0FF22ABF0FF22ABF0FF22ABF0FF22ABF0FF23ABF0FF23AB - F0FF23ABF0FF23ABF0FF23ABF0FF23ABF0FF23ABF0FF24ABF0FF24ABF0FF24AB - F0FF24ABF0FF24ABF0FF24ABF0FF24ABF0FF25ABF0FF25ACF1FF25ACF1FF25AC - F1FF25ACF1FF25ACF1FF26ACF1FF26ACF1FF26ACF1FF26ACF1FF2AA3E1FF5658 - 5AFF5B5959FF595D60FF497790FF3596C8FF28ABEEFF27ACF1FF27ACF1FF28AD - F1FF28ADF1FF28ADF1FF28ADF1FF28ADF1FF28ACF0FF27ABEFFF26A9EDFF24A8 - EBFF21A4E7FF1FA0E2FF1B9ADBFF1292D2FF599CB8FF6A7575FF515252FF4948 - 48FF494747FF494747FF494747FF494747FF494747FF494747FF454343EC0707 - 075B00000043000000270000000F000000030000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000010000000B00000021413F3FCC494747FF4947 - 47FF494747FF494747FF494747FF494747FF4C4B4BFF5C6161FF839798FF46A3 - CCFF1494D5FF169ADCFF189EE2FF1BA2E7FF1CA5EAFF1DA7EDFF1DA8EEFF1DA8 - EFFF1FA5E9FF2E3B42FF3E3D3DFF4C4A4AFF535252FF565454FF565454FF5654 - 54FF565454FF565454FF555454FF3B7898FF20A9F0FF20AAF0FF20AAF0FF20AA - F0FF21AAF0FF21AAF0FF21AAF0FF21AAF0FF21AAF0FF21AAF0FF21AAF0FF22AA - F0FF22AAF0FF22ABF0FF22ABF0FF22ABF0FF22ABF0FF22ABF0FF23ABF0FF23AB - F0FF23ABF0FF23ABF0FF23ABF0FF23ABF0FF23ABF0FF24ABF0FF3A81A5FF5856 - 56FF595858FF595858FF595858FF5A5858FF546169FF427E9DFF2F9CD4FF25AC - F1FF25ACF1FF25ACF1FF26ACF1FF26ACF1FF25ACF1FF25ABF0FF25AAEFFF24A9 - EDFF22A6EAFF1FA3E6FF1C9EE0FF1999DAFF1892D0FF6F99A7FF616767FF4D4C - 4CFF494747FF494747FF494747FF494747FF494747FF494747FF494747FF2E2D - 2DB00000004D000000360000001A000000070000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000004000000141F1E1E6D494747FF494747FF4947 - 47FF494747FF494747FF494747FF4A4848FF545656FF758282FF6CADC4FF1292 - D2FF1597DAFF169DE1FF18A1E7FF1AA4EAFF1AA6EDFF1BA7EEFF1BA7EFFF1CA8 - F0FF1CA8F0FF2277A2FF343333FF434242FF4F4D4DFF535151FF545353FF5453 - 53FF545353FF545353FF545353FF515253FF249CD9FF1EA9F0FF1EA9F0FF1EA9 - F0FF1EA9F0FF1EA9F0FF1EA9F0FF1EA9F0FF1FA9F0FF1FA9F0FF1FA9F0FF1FA9 - F0FF1FA9F0FF20A9F0FF20A9F0FF20A9F0FF20AAF0FF20AAF0FF20AAF0FF20AA - F0FF21AAF0FF21AAF0FF21AAF0FF21AAF0FF21AAF0FF22A9EDFF4D5A61FF5755 - 55FF585656FF585656FF585656FF585656FF585656FF585656FF585757FF4F67 - 73FF3B86ACFF28A3E1FF23ABF0FF23ABF0FF23ABF0FF23AAF0FF23AAEFFF22A9 - EEFF22A7ECFF1FA5E9FF1CA1E5FF1A9CDEFF1696D7FF2A97CBFF768C8FFF585B - 5BFF4A4949FF494747FF494747FF494747FF494747FF494747FF494747FF4846 - 46FA0C0C0C6600000043000000270000000E0000000200000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000A05050523454343DF494747FF494747FF4947 - 47FF494747FF494747FF494747FF4E4E4EFF666E6EFF87ABB1FF2097D1FF1395 - D8FF159BDFFF169FE5FF17A3E9FF18A4ECFF19A6EEFF19A6EFFF19A7F0FF1AA7 - F0FF1AA8F0FF1AA6EDFF29414DFF393838FF474646FF504E4EFF525050FF5351 - 51FF535151FF535151FF535151FF535151FF3E6B82FF1BA8F0FF1CA8F0FF1CA8 - F0FF1CA8F0FF1CA8F0FF1CA8F0FF1CA8F0FF1CA8F0FF1CA8F0FF1DA8F0FF1DA9 - F0FF1DA9F0FF1DA9F0FF1DA9F0FF1DA9F0FF1DA9F0FF1EA9F0FF1EA9F0FF1EA9 - F0FF1EA9F0FF1EA9F0FF1EA9F0FF1EA9F0FF1EA9F0FF2D8DBFFF535151FF5654 - 54FF565454FF565454FF565454FF565454FF575555FF575555FF575555FF5755 - 55FF575555FF565657FF486D81FF358CB8FF23A7EBFF21AAF0FF21AAEFFF21A9 - EFFF20A8EDFF1FA6EBFF1DA3E9FF1A9FE3FF189ADCFF1292D4FF519DBDFF6C77 - 77FF505151FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF353333BF0000004C00000034000000170000000500000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000030000001127252578494747FF494747FF494747FF4947 - 47FF494747FF494747FF4B4949FF595D5DFF819494FF48A4CDFF1192D5FF1398 - DCFF149DE3FF16A1E8FF17A3EBFF17A5EEFF17A6EFFF17A7F0FF17A7F0FF17A7 - F0FF18A7F0FF18A7F0FF1C82B7FF2F2E2EFF3F3D3DFF4B4949FF504E4EFF514F - 4FFF525050FF525050FF525050FF525050FF504E4EFF2690C6FF19A7F0FF19A7 - F0FF1AA8F0FF1AA8F0FF1AA8F0FF1AA8F0FF1AA8F0FF1AA8F0FF1AA8F0FF1BA8 - F0FF1BA8F0FF1BA8F0FF1BA8F0FF1BA8F0FF1BA8F0FF1BA8F0FF1BA8F0FF1CA8 - F0FF1CA8F0FF1CA8F0FF1CA8F0FF1CA8F0FF1CA8F0FF40667AFF535151FF5452 - 52FF545353FF545353FF545353FF545353FF545353FF555353FF555353FF5553 - 53FF555353FF555353FF555353FF555353FF53575AFF3F728CFF2A8FC2FF1EA9 - EFFF1EA8EEFF1EA7EDFF1DA5EAFF1AA2E6FF189DE1FF1597D9FF1391D0FF7399 - A4FF5E6464FF4C4B4BFF494747FF494747FF494747FF494747FF494747FF4947 - 47FF484646FC0E0E0E6500000040000000230000000B12111101000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000070000001B444242D8494747FF494747FF494747FF4947 - 47FF494747FF494747FF505151FF6D7878FF7CAFBEFF1090D1FF1196DAFF129B - E1FF149FE7FF15A2EAFF15A4EDFF16A5EFFF16A5EFFF16A6F0FF16A6F0FF17A6 - F0FF17A6F0FF17A6F0FF17A6F0FF23495CFF343333FF434141FF4C4A4AFF4F4D - 4DFF504E4EFF504E4EFF504E4EFF504E4EFF504E4EFF435C6AFF18A5EDFF18A7 - F0FF18A7F0FF18A7F0FF18A7F0FF18A7F0FF18A7F0FF18A7F0FF19A7F0FF19A7 - F0FF19A7F0FF19A7F0FF19A7F0FF19A7F0FF19A7F0FF19A7F0FF1AA7F0FF1AA8 - F0FF1AA8F0FF1AA8F0FF1AA8F0FF1AA8F0FF209BDAFF4E4C4CFF535151FF5351 - 51FF535151FF535151FF535151FF535151FF535151FF535151FF535252FF5452 - 52FF545252FF545252FF545252FF545252FF535252FF4F4D4DFF434141FF2E4E - 5EFF1CA7EFFF1CA7EEFF1BA6ECFF1AA3E9FF179FE4FF169ADDFF1294D6FF3699 - C8FF748383FF535555FF494848FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF2F2E2EB5000000490000002F0000001300000003000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000010000000D1F1E1E64494747FF494747FF494747FF494747FF4947 - 47FF494747FF4B4A4AFF5C6161FF879D9EFF359ECFFF0F92D6FF1098DDFF119D - E4FF13A0E9FF13A2EBFF14A4EDFF14A5EEFF14A5EFFF14A5EFFF15A6EFFF15A6 - EFFF15A6EFFF15A6EFFF15A6EFFF188DC9FF2A2B2CFF3A3838FF474545FF4D4B - 4BFF4F4D4DFF4F4D4DFF4F4D4DFF4F4D4DFF4F4D4DFF4E4C4CFF2A81AEFF16A6 - F0FF17A6F0FF17A6F0FF17A6F0FF17A6F0FF17A6F0FF17A6F0FF17A6F0FF17A6 - F0FF17A6F0FF17A6F0FF17A7F0FF17A7F0FF17A7F0FF17A7F0FF17A7F0FF18A7 - F0FF18A7F0FF18A7F0FF18A7F0FF18A7F0FF337496FF504E4EFF514F4FFF5250 - 50FF525050FF525050FF525050FF525050FF525050FF525050FF525050FF5250 - 50FF525050FF525050FF525050FF525050FF504E4EFF494747FF3A3939FF246C - 91FF1AA8F0FF1AA7EFFF1AA6EEFF19A4EBFF17A1E7FF159DE1FF1397DAFF0E90 - D2FF699CAEFF616868FF4C4C4CFF494747FF494747FF494747FF494747FF4947 - 47FF494747FF474545F4070707580000003A0000001D00000008000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000400000015413F3FC3494747FF494747FF494747FF494747FF4947 - 47FF494747FF505151FF6F7A7AFF76AFC2FF0E8FD1FF0F95DAFF0F9AE1FF119E - E7FF12A1EAFF12A3EDFF13A4EEFF13A5EFFF13A5EFFF13A5EFFF13A5EFFF13A5 - EFFF13A5EFFF13A5EFFF13A5EFFF14A5EFFF1E5470FF302E2EFF3F3E3EFF4947 - 47FF4D4B4BFF4D4B4BFF4D4B4BFF4D4B4BFF4D4B4BFF4D4B4BFF465258FF189F - E4FF15A6EFFF15A6EFFF15A6EFFF15A6EFFF15A6EFFF15A6EFFF16A6F0FF16A6 - F0FF16A6F0FF16A6F0FF16A6F0FF16A6F0FF16A6F0FF16A6F0FF16A6F0FF17A6 - F0FF17A6F0FF17A6F0FF17A6F0FF18A3EAFF465158FF4F4D4DFF4F4D4DFF4F4D - 4DFF504E4EFF504E4EFF504E4EFF4F4D4DFF4E4C4CFF4E4C4CFF4E4C4CFF504E - 4EFF514F4FFF514F4FFF514F4FFF514F4FFF4D4B4BFF414040FF323334FF1A9B - DDFF19A7F0FF18A6EFFF18A6EEFF17A5EDFF17A2E9FF159EE5FF1399DFFF1093 - D6FF2F98CAFF758587FF535555FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF2423239900000044000000280000000E000000020000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000815141439494747FF494747FF494747FF494747FF494747FF4947 - 47FF4B4949FF5B5F5FFF869D9DFF389FCFFF0D92D6FF0E98DEFF0F9CE4FF10A0 - E8FF10A2ECFF11A3EDFF11A3EEFF11A4EFFF11A4EFFF11A4EFFF11A4EFFF12A4 - EFFF12A4EFFF12A4EFFF12A4EFFF12A4EFFF1398DBFF26292BFF353434FF4342 - 42FF4B4949FF4D4B4BFF4D4B4BFF4D4B4BFF4D4B4BFF4D4B4BFF4C4A4AFF3073 - 95FF13A5EFFF13A5EFFF13A5EFFF13A5EFFF14A5EFFF14A5EFFF14A5EFFF14A5 - EFFF14A5EFFF14A5EFFF14A5EFFF14A5EFFF14A5EFFF14A5EFFF15A6EFFF15A6 - EFFF15A6EFFF15A6EFFF15A6EFFF2684B4FF4B4A4AFF4E4C4CFF4E4C4CFF4F4D - 4DFF4F4D4DFF4F4D4DFF4E4C4CFF4B4A4AFF474545FF444242FF454343FF4948 - 48FF4D4B4BFF4E4C4CFF4F4D4DFF4E4C4CFF484646FF393838FF25536BFF17A6 - F0FF17A6F0FF17A6F0FF17A5EFFF16A4EEFF16A3EBFF14A0E8FF129BE2FF1096 - DAFF0E90D1FF6C9DADFF606767FF4C4B4BFF494747FF494747FF494747FF4947 - 47FF494747FF494747FF413F3FDD0000004C0000003400000017000000050000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00010000000D2F2E2E93494747FF494747FF494747FF494747FF494747FF4947 - 47FF4F4F4FFF6B7676FF7FB1BFFF0D8FD1FF0E94D9FF0E99E1FF0F9DE7FF0FA0 - EAFF10A2EDFF10A3EEFF10A4EFFF10A4EFFF10A4EFFF10A4EFFF10A4EFFF11A4 - EFFF11A4EFFF11A4EFFF11A4EFFF11A4EFFF11A4EFFF196187FF2C2B2BFF3B3A - 3AFF464444FF4B4949FF4B4949FF4B4949FF4B4949FF4B4949FF4B4949FF474A - 4CFF1998D9FF12A4EFFF12A4EFFF12A4EFFF12A4EFFF12A4EFFF12A4EFFF13A5 - EFFF13A5EFFF13A5EFFF13A5EFFF13A5EFFF13A5EFFF13A5EFFF13A5EFFF13A5 - EFFF13A5EFFF13A5EFFF13A5EFFF3A5D6FFF4C4A4AFF4D4B4BFF4D4B4BFF4D4B - 4BFF4D4B4BFF4D4B4BFF4C4A4AFF454343FF3B3939FF343232FF353434FF3B3A - 3AFF413F3FFF464444FF4A4848FF494747FF403F3FFF313030FF1A81B6FF15A6 - EFFF15A6EFFF15A6EFFF15A6EFFF15A5EEFF14A3ECFF13A1E9FF119DE4FF0F98 - DDFF0E92D6FF379AC8FF738081FF515252FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF1211116A00000040000000230000000B1211 - 1101000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000300000014464444E1494747FF494747FF494747FF494747FF494747FF4A48 - 48FF575A5AFF819393FF46A4CEFF0C91D5FF0D96DDFF0D9BE4FF0F9FE8FF0FA1 - ECFF0FA2EDFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF10A4EFFF10A4 - EFFF10A4EFFF10A4EFFF10A4EFFF10A4EFFF10A4EFFF109DE5FF222F36FF3231 - 31FF403F3FFF484646FF4A4848FF4A4848FF4A4848FF4A4848FF4A4848FF4A48 - 48FF34667FFF11A4EFFF11A4EFFF11A4EFFF11A4EFFF11A4EFFF11A4EFFF11A4 - EFFF11A4EFFF11A4EFFF11A4EFFF11A4EFFF11A4EFFF11A4EFFF11A4EFFF12A4 - EFFF12A4EFFF12A4EFFF1A94D3FF484646FF4C4A4AFF4C4A4AFF4C4A4AFF4C4A - 4AFF4C4A4AFF4C4A4AFF484747FF3E3D3DFF2F2E2EFF252424FF242323FF2928 - 28FF302E2EFF363535FF3D3B3BFF3E3C3CFF363535FF273841FF14A5EFFF14A5 - EFFF14A5EFFF14A5EFFF13A5EFFF13A4EEFF12A3EDFF12A1EAFF109EE6FF0F9A - E0FF0E94D9FF0E8FD0FF7499A3FF5C6161FF4A4949FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF2E2D2DB20000004900000030000000140000 - 0004000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00061C1B1B44494747FF494747FF494747FF494747FF494747FF494747FF4C4B - 4BFF636B6BFF8AADB4FF1692D0FF0D93D8FF0D98E0FF0D9DE6FF0E9FEAFF0EA1 - EDFF0FA2EEFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3 - EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF156D99FF2827 - 27FF393737FF444242FF494747FF4A4848FF4A4848FF4A4848FF4A4848FF4A48 - 48FF484646FF1C8DC6FF10A4EFFF10A4EFFF10A4EFFF10A4EFFF10A4EFFF10A4 - EFFF10A4EFFF10A4EFFF10A4EFFF10A4EFFF10A4EFFF10A4EFFF10A4EFFF10A4 - EFFF10A4EFFF11A4EFFF2C6E90FF494747FF4B4949FF4B4949FF4B4949FF4B49 - 49FF4B4949FF4A4848FF444242FF363434FF224558FF185A7BFF1A252AFF1D1D - 1DFF212020FF252525FF2B2A2AFF2D2B2BFF282828FF1A678EFF12A4EFFF12A4 - EFFF12A4EFFF12A4EFFF12A4EFFF12A4EFFF11A3EDFF10A1EBFF109FE8FF0E9B - E3FF0E96DCFF0C91D4FF4D9DBFFF6A7474FF4E4E4EFF494747FF494747FF4947 - 47FF494747FF494747FF494747FF474545F4050505550000003C0000001F0000 - 0009000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000A302F2F91494747FF494747FF494747FF494747FF494747FF494747FF5152 - 52FF738080FF69ADC7FF0C90D3FF0D95DBFF0D9AE3FF0E9EE8FF0EA0EBFF0EA2 - EDFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0FA3EFFF0FA3EFFF0FA0EBFF1E35 - 40FF2F2E2EFF3F3D3DFF474545FF4A4848FF4A4848FF4A4848FF4A4848FF4A48 - 48FF494747FF3B5767FF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3 - EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3 - EFFF10A4EFFF11A0E9FF404A50FF494747FF4A4848FF4A4848FF4A4848FF4A48 - 48FF4A4848FF474646FF3F3D3DFF2F2E2EFF167BAFFF10A4EFFF109FE8FF1374 - A4FF17394AFF1B1A1AFF1D1D1DFF1F1E1EFF1E2123FF1299DEFF11A4EFFF11A4 - EFFF11A4EFFF11A4EFFF10A4EFFF10A4EFFF10A3EEFF0FA2EDFF0F9FE9FF0E9C - E6FF0D98DFFF0C93D7FF2195CEFF788C8EFF545656FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF24232399000000460000002B0000 - 0011000000030000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000010000 - 000E454343CE494747FF494747FF494747FF494747FF494747FF4A4848FF585C - 5CFF85999AFF3BA1D0FF0C92D6FF0D97DEFF0D9CE5FF0E9FE9FF0EA1ECFF0EA2 - EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF127A - B0FF262424FF363434FF434141FF484646FF494747FF494747FF494747FF4947 - 47FF494747FF484646FF237FAEFF0EA3EFFF0EA3EFFF0FA3EFFF0FA3EFFF0FA3 - EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3 - EFFF0FA3EFFF2080B2FF474545FF4A4848FF4A4848FF4A4848FF4A4848FF4A48 - 48FF494747FF454343FF393737FF26333AFF0FA1EBFF0FA3EFFF0FA3EFFF0FA3 - EFFF0FA3EFFF118BC9FF155272FF182025FF154761FF10A4EFFF10A4EFFF10A4 - EFFF10A4EFFF10A4EFFF10A4EFFF0FA3EFFF0FA3EEFF0FA2EDFF0EA0EBFF0E9E - E7FF0D99E1FF0D95DAFF0C8FD1FF709DABFF5E6363FF4B4949FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF424141E20000004E000000370000 - 001B000000070000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000030E0D - 0D21494747FF494747FF494747FF494747FF494747FF494747FF4C4A4AFF636A - 6AFF8DAFB4FF1592D0FF0D94D8FF0D99E0FF0D9DE6FF0EA0EAFF0EA2EDFF0EA2 - EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF1B4053FF2D2C2CFF3C3A3AFF454343FF484646FF494747FF494747FF4947 - 47FF494747FF484646FF404D54FF109EE6FF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0FA3EFFF345D72FF494747FF4A4848FF4A4848FF4A4848FF4A4848FF4A48 - 48FF484646FF413F3FFF323030FF1A5D7FFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3 - EFFF0FA3EFFF0FA3EFFF0FA3EFFF0F9EE8FF0F96DAFF0FA3EFFF0FA3EFFF0FA3 - EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF0EA2EEFF0EA1ECFF0E9F - E8FF0D9BE4FF0D96DCFF0C91D4FF4E9DBFFF6A7474FF4D4D4DFF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF1A19197E000000430000 - 00270000000E1211110200000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000042120 - 205A494747FF494747FF494747FF494747FF494747FF494747FF4F4F4FFF6F7B - 7BFF72B0C4FF0C8FD2FF0D95DBFF0D9AE3FF0E9EE8FF0EA0EBFF0EA2EEFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF1089C7FF242323FF343333FF413F3FFF474545FF494747FF494747FF4947 - 47FF494747FF494747FF484646FF297298FF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF1496D8FF444242FF484646FF494747FF494747FF494747FF494747FF4947 - 47FF454343FF3B3939FF2A2828FF118ECEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF0FA3 - EFFF0FA3EFFF0FA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF0EA1EDFF0E9F - E9FF0D9CE6FF0D98DFFF0C92D7FF2897CDFF778788FF525353FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF383636C70000004C0000 - 0033000000170000000500000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000072F2E - 2E8E494747FF494747FF494747FF494747FF494747FF494747FF545656FF7D8E - 8EFF4FA8CEFF0C91D5FF0D97DDFF0D9BE4FF0E9FE9FF0EA1ECFF0EA2EEFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF19506CFF2B2A2AFF3B3939FF454343FF484646FF494747FF4947 - 47FF494747FF494747FF494747FF444749FF1398DCFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF286F94FF474545FF494747FF494747FF494747FF494747FF494747FF4846 - 46FF424040FF343333FF1F3F50FF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EDFF0EA0 - EBFF0D9DE7FF0D99E1FF0D94D9FF0F8FD0FF78989FFF595C5CFF494848FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF484646FC0E0E0E650000 - 003F000000220000000B12111101000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000094442 - 42BA494747FF494747FF494747FF494747FF494747FF4A4848FF5B5F5FFF8BA1 - A2FF2D9CD0FF0C92D7FF0D98DFFF0D9CE6FF0E9FEAFF0EA1EDFF0EA2EEFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0F94D7FF222628FF323131FF403E3EFF474545FF494747FF4947 - 47FF494747FF494747FF494747FF484646FF316580FF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA1 - ECFF3D4C54FF484646FF494747FF494747FF494747FF494747FF494747FF4644 - 44FF3D3C3CFF2E2D2DFF16709EFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF0EA0 - EBFF0E9EE8FF0D9AE3FF0D95DBFF0C90D3FF679EB2FF616767FF4B4949FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF2D2B2BAF0000 - 00490000002F0000001300000004000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000000000000B4745 - 45E2494747FF494747FF494747FF494747FF494747FF4B4A4AFF626969FF8FAF - B3FF1491D0FF0D94D9FF0D99E0FF0D9DE7FF0EA0EBFF0EA2EDFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF165E83FF292828FF393838FF444242FF484646FF4947 - 47FF494747FF494747FF494747FF494747FF474545FF198DC9FF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF1C86 - BDFF454343FF494747FF494747FF494747FF494747FF494747FF484646FF4442 - 42FF383737FF262C30FF0E9CE5FF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF0EA1 - ECFF0E9FE9FF0D9BE4FF0D96DCFF0C91D5FF4E9DBFFF697272FF4C4C4CFF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF464444F20505 - 05550000003B0000001E00000009000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000007F7F7F010E0D0D184947 - 47FF494747FF494747FF494747FF494747FF494747FF4C4C4CFF697272FF85B3 - BEFF0C8ED1FF0D95DAFF0D9AE2FF0E9EE7FF0EA0EBFF0EA2EEFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0E9AE1FF202B31FF302F2FFF3F3D3DFF474545FF4947 - 47FF494747FF494747FF494747FF494747FF484646FF395869FF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF3160 - 79FF474545FF494747FF494747FF494747FF494747FF494747FF474545FF403F - 3FFF323131FF1B536FFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF0EA1 - EDFF0E9FE9FF0D9CE5FF0D97DEFF0C92D6FF3B9BC8FF717E7EFF4F4F4FFF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF2322 - 2297000000460000002A00000010000000030000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000007F7F7F011F1E1E374947 - 47FF494747FF494747FF494747FF494747FF494747FF4F4F4FFF707D7DFF71B0 - C6FF0C90D3FF0D95DBFF0D9AE3FF0E9EE8FF0EA1ECFF0EA2EEFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF146A96FF282626FF383636FF434242FF4846 - 46FF494747FF494747FF494747FF494747FF494747FF474545FF2180B0FF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF119AE1FF4245 - 47FF484646FF494747FF494747FF494747FF494747FF494747FF464444FF3C3A - 3AFF2B2A2AFF1284BEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2 - EDFF0E9FEAFF0D9DE6FF0D98DFFF0D93D7FF2898CEFF78898AFF525353FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF413F - 3FDD0000004E000000370000001A000000070000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000007F7F7F01222121514947 - 47FF494747FF494747FF494747FF494747FF494747FF515252FF788686FF5FAD - CCFF0C90D4FF0D97DDFF0D9BE4FF0E9FE9FF0EA1ECFF0EA2EEFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA0EBFF1E323DFF2F2E2EFF3E3C3CFF4644 - 44FF494747FF494747FF494747FF494747FF494747FF484646FF404E56FF0F9F - E9FF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF2378A4FF4644 - 44FF494747FF494747FF494747FF494747FF494747FF484646FF434141FF3634 - 34FF223844FF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2 - EDFF0EA0EBFF0D9DE7FF0D99E0FF0D94D9FF1792CFFF7B9295FF555858FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF1817177800000043000000260000000D1211110100000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000007F7F7F01232222674947 - 47FF494747FF494747FF494747FF494747FF494747FF545656FF7E8F8FFF4FA9 - CFFF0C91D6FF0D97DEFF0D9CE4FF0E9FE9FF0EA1EDFF0EA2EEFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF1278ADFF262525FF363434FF4240 - 40FF484646FF494747FF494747FF494747FF494747FF494747FF484646FF2874 - 9BFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF375463FF4846 - 46FF494747FF494747FF494747FF494747FF494747FF474545FF3E3D3DFF2F2E - 2EFF17668EFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2 - EEFF0EA0EBFF0D9EE7FF0D9AE1FF0D94DAFF0E8FD0FF7A99A0FF585C5CFF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF373636C40000004C00000033000000170000000500000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000007F7F7F012423237E4947 - 47FF494747FF494747FF494747FF494747FF494747FF565959FF849696FF43A5 - D1FF0C92D6FF0D97DEFF0D9CE5FF0E9FEAFF0EA1EDFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF1B4053FF2D2C2CFF3C3B - 3BFF464444FF484646FF494747FF494747FF494747FF494747FF494747FF4349 - 4CFF1399DEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF1592D2FF444242FF4846 - 46FF494747FF494747FF494747FF494747FF484646FF444343FF393838FF2829 - 2AFF0F96DBFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2 - EEFF0EA0EBFF0E9EE8FF0D9AE2FF0D95DAFF0C8ED1FF769DA8FF5C6060FF4A48 - 48FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF484646FC0B0B0B620000003F000000220000000B12111101000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000007F7F7F01242323854947 - 47FF494747FF494747FF494747FF494747FF494747FF585B5BFF889C9CFF38A0 - D0FF0C92D7FF0D98DFFF0D9CE6FF0E9FEAFF0EA2EDFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF1187C3FF242323FF3433 - 33FF413F3FFF484646FF494747FF494747FF494747FF494747FF494747FF4846 - 46FF306783FF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF276E93FF464444FF4947 - 47FF494747FF494747FF494747FF494747FF484646FF413F3FFF333232FF1E49 - 5FFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2 - EEFF0EA1ECFF0E9EE8FF0D9AE2FF0D95DBFF0C8FD2FF6F9EADFF5E6363FF4A48 - 48FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF2C2B2BAC000000480000002E0000001300000003000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000007F7F7F01242323854947 - 47FF494747FF494747FF494747FF494747FF494747FF5A5D5DFF8BA0A0FF329E - D1FF0C92D7FF0D98DFFF0D9DE6FF0E9FEAFF0EA2EDFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF194E69FF2B2A - 2AFF3B3939FF454343FF484646FF494747FF494747FF494747FF494747FF4947 - 47FF474545FF188FCBFF0EA3EFFF0EA3EFFF0EA3EFFF3A4D58FF484646FF4947 - 47FF494747FF494747FF494747FF494747FF464444FF3D3B3BFF2D2B2BFF137A - AEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2 - EEFF0EA1ECFF0E9EE8FF0D9AE3FF0D95DBFF0C8FD2FF6B9FB1FF5F6565FF4A49 - 49FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF464444EF050505550000003A0000001D00000008000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000007F7F7F01242323844947 - 47FF494747FF494747FF494747FF494747FF4A4848FF5A5E5EFF8CA2A2FF309D - D0FF0C92D7FF0D98DFFF0D9DE6FF0E9FEAFF0EA2EDFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0F92D4FF2226 - 28FF323131FF403F3FFF474545FF494747FF494747FF494747FF494747FF4947 - 47FF484646FF385A6BFF0EA3EFFF0EA3EFFF1594D6FF444242FF484646FF4947 - 47FF494747FF494747FF494747FF484646FF444242FF373535FF243138FF0EA1 - EBFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2 - EEFF0EA1ECFF0E9EE8FF0D9AE3FF0D95DBFF0C8FD2FF6B9FB2FF606767FF4A49 - 49FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF1F1E1E91000000450000002A00000010000000020000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000007F7F7F01242323844947 - 47FF494747FF494747FF494747FF494747FF4A4848FF5A5E5EFF8CA1A1FF319D - D0FF0C92D7FF0D98DFFF0D9DE6FF0E9FEAFF0EA2EDFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF165C - 7FFF2A2828FF393838FF444242FF484646FF494747FF494747FF494747FF4947 - 47FF494747FF474545FF2182B3FF0EA3EFFF2677A0FF464444FF494747FF4947 - 47FF494747FF494747FF494747FF474545FF403E3EFF312F2FFF195C7EFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2 - EEFF0EA1ECFF0E9EE8FF0D9AE3FF0D95DBFF0C8FD2FF6B9FB2FF606767FF4A49 - 49FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF403E3EDA0000004E000000360000001A000000070000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000007F7F7F01242323844947 - 47FF494747FF494747FF494747FF494747FF494747FF5A5D5DFF8B9F9FFF349F - D1FF0C92D7FF0D98DFFF0D9DE6FF0E9FEAFF0EA2EDFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0E9A - E1FF20292DFF312F2FFF3F3D3DFF474545FF494747FF494747FF494747FF4947 - 47FF494747FF484646FF40535DFF0FA0E9FF395D6FFF484646FF494747FF4947 - 47FF494747FF494747FF494747FF454343FF3B3939FF2A2828FF108ECEFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2 - EEFF0EA1ECFF0E9EE8FF0D9AE3FF0D95DBFF0C8FD2FF6E9FB0FF5F6565FF4A49 - 49FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF1616167600000042000000260000000D1211 - 1101000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000007F7F7F01242323834947 - 47FF494747FF494747FF494747FF494747FF494747FF585B5BFF879B9BFF3EA3 - D1FF0C92D6FF0D98DFFF0D9CE5FF0E9FEAFF0EA2EDFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF156893FF282626FF383636FF434242FF484646FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF2C7398FF484849FF494747FF494747FF4947 - 47FF494747FF494747FF484646FF424040FF343333FF1F3F50FF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2 - EEFF0EA1ECFF0E9EE8FF0D9AE2FF0D95DBFF0C8ED1FF739FACFF5D6363FF4A48 - 48FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF353333C20000004B00000032000000160000 - 0005000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000002423237B4947 - 47FF494747FF494747FF494747FF494747FF494747FF565858FF839595FF49A7 - D0FF0C92D6FF0D97DEFF0D9CE5FF0E9FE9FF0EA1EDFF0EA2EEFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA0EBFF1E323DFF2F2E2EFF3E3C3CFF464444FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF464444FF3D3C3CFF2E2D2DFF16709EFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2 - EEFF0EA0EBFF0E9EE7FF0D9AE1FF0D95DAFF0D8ED1FF7A9EA6FF5B6060FF4A48 - 48FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF484646FA0B0B0B620000003E000000210000 - 000A121111010000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000242323644947 - 47FF494747FF494747FF494747FF494747FF494747FF535555FF7D8E8EFF57AC - CFFF0C91D5FF0D97DDFF0D9CE4FF0E9FE9FF0EA1ECFF0EA2EEFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF1577AAFF2B2A2AFF3D3C3CFF4C4A4AFF525050FF545252FF5553 - 53FF565454FF565454FF575555FF565454FF555454FF555353FF545252FF5250 - 50FF514F4FFF4D4C4CFF474545FF393737FF262C30FF0E9CE5FF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2 - EDFF0EA0EBFF0D9EE7FF0D99E1FF0D94D9FF1291D0FF7D999EFF585C5CFF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF2A2929A7000000480000002E0000 - 0012000000030000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000002322224C4947 - 47FF494747FF494747FF494747FF494747FF494747FF515252FF778585FF69B0 - CBFF0C90D4FF0D96DCFF0D9BE3FF0E9EE8FF0EA1ECFF0EA2EEFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0FA3EFFF15A5EFFF1CA8 - F0FF20AAF0FF23ABF0FF304F5FFF403F3FFF4E4C4CFF575555FF595757FF5957 - 57FF595757FF595757FF595757FF595757FF595757FF595757FF595757FF5957 - 57FF595757FF585656FF525050FF434242FF2B5E79FF18A6EFFF12A4EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2 - EDFF0EA0EAFF0D9DE6FF0D98E0FF0D93D8FF1F95CFFF7D9293FF555757FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF464444EF030303520000003A0000 - 001D000000080000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000222121334947 - 47FF494747FF494747FF494747FF494747FF494747FF4F4E4EFF6F7B7BFF7DB5 - C5FF0C8FD2FF0D95DBFF0D9AE2FF0E9EE8FF0EA0EBFF0EA2EEFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF15A5EFFF1FA9F0FF26ACF0FF28ACF1FF28AC - F1FF28ACF1FF28ACF1FF2A92C7FF3C3B3BFF4A4949FF565454FF5C5A5AFF5D5B - 5BFF5D5B5BFF5D5B5BFF5D5B5BFF5D5B5BFF5D5B5BFF5D5B5BFF5D5B5BFF5D5B - 5BFF5D5B5BFF5A5858FF514F4FFF424141FF2B91C5FF28ACF1FF28ACF1FF23AB - F0FF1AA7EFFF11A4EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA1 - EDFF0E9FEAFF0D9CE6FF0D98DFFF0C92D7FF339BCDFF778787FF515353FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF1E1D1D8C000000450000 - 00290000000F0000000200000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000001010100F4947 - 47FF494747FF494747FF494747FF494747FF494747FF4C4B4BFF677171FF8EB6 - BEFF0E8FD1FF0D94DAFF0D99E1FF0D9EE7FF0EA0EBFF0EA2EDFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0FA3EFFF1AA7EFFF27ACF0FF2CAEF1FF2CAEF1FF2CAEF1FF2CAEF1FF2CAE - F1FF2CAEF1FF2CAEF1FF2CAEF1FF366279FF464545FF545252FF5C5B5BFF5F5D - 5DFF605E5EFF605E5EFF605E5EFF605E5EFF605E5EFF605E5EFF605E5EFF605E - 5EFF5F5D5DFF5A5959FF4F4E4EFF3E515BFF2CAEF1FF2CAEF1FF2CAEF1FF2CAE - F1FF2CAEF1FF2AAEF1FF21AAF0FF14A5EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF0EA1 - ECFF0E9FE9FF0D9CE5FF0D97DDFF0C91D6FF459FC6FF707C7CFF4F4F4FFF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF3F3D3DD70000004D0000 - 0036000000190000000600000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000014846 - 46E8494747FF494747FF494747FF494747FF494747FF4B4949FF606767FF93AF - B1FF1F95D0FF0D93D8FF0D98E0FF0D9DE6FF0EA0EAFF0EA2EDFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF19A7 - EFFF2AADF0FF30B0F1FF30B0F1FF30B0F1FF30B0F1FF30B0F1FF30B0F1FF30B0 - F1FF30B0F1FF30B0F1FF30B0F1FF319FD7FF414547FF4F4E4EFF5B5A5AFF615F - 5FFF626161FF626161FF626161FF626161FF626161FF626161FF626161FF6261 - 61FF615F5FFF5A5858FF4D4B4BFF387B9EFF30B0F1FF30B0F1FF30B0F1FF30B0 - F1FF30B0F1FF30B0F1FF30B0F1FF2EAFF1FF23AAF0FF12A4EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF0EA1 - ECFF0E9EE8FF0D9BE3FF0D96DCFF0C90D4FF5DA1BCFF677070FF4C4B4BFF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF141414720000 - 0041000000250000000D12111101000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000004745 - 45B9494747FF494747FF494747FF494747FF494747FF494848FF595D5DFF899E - 9EFF3EA3D0FF0C92D6FF0D97DEFF0D9CE5FF0E9FE9FF0EA1ECFF0EA2EEFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF13A5EFFF29ADF1FF35B1 - F2FF35B1F2FF35B1F2FF35B1F2FF35B1F2FF35B1F2FF35B1F2FF35B1F2FF35B1 - F2FF35B1F2FF35B1F2FF35B1F2FF35B1F2FF3C7491FF4C4B4BFF595858FF6261 - 61FF666464FF666464FF666464FF666464FF666464FF666464FF666464FF6664 - 64FF626161FF595858FF4B4C4CFF36A7E1FF35B1F2FF35B1F2FF35B1F2FF35B1 - F2FF35B1F2FF35B1F2FF35B1F2FF35B1F2FF35B1F2FF31B0F1FF1DA9F0FF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EDFF0EA0 - EBFF0D9EE7FF0D9AE2FF0D95DAFF0C8FD1FF75A1AEFF5F6565FF4A4949FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF343232BD0000 - 004B000000320000001600000005000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000003534 - 348D494747FF494747FF494747FF494747FF494747FF494747FF535555FF7B8B - 8BFF63B0CDFF0C90D4FF0D96DCFF0D9BE3FF0E9EE8FF0EA1ECFF0EA2EEFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF1BA8F0FF35B2F1FF39B3F2FF39B3 - F2FF39B3F2FF39B3F2FF39B3F2FF39B3F2FF39B3F2FF39B3F2FF39B3F2FF39B3 - F2FF39B3F2FF39B3F2FF39B3F2FF39B3F2FF39ACE7FF484F53FF565555FF6261 - 61FF686666FF696868FF696868FF696868FF696868FF696868FF696868FF6967 - 67FF636161FF585656FF46697BFF39B3F2FF39B3F2FF39B3F2FF39B3F2FF39B3 - F2FF39B3F2FF39B3F2FF39B3F2FF39B3F2FF39B3F2FF39B3F2FF39B3F2FF29AD - F1FF11A4EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF0EA2EDFF0EA0 - EAFF0D9DE6FF0D98E0FF0D93D8FF1A93CFFF7F9799FF585B5BFF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF484646FA0A0A - 0A5F0000003D000000210000000A000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000002322 - 2252494747FF494747FF494747FF494747FF494747FF494747FF4E4E4EFF6D78 - 78FF88B8C3FF0C8FD1FF0D95DAFF0D99E1FF0D9EE7FF0EA0EBFF0EA2EDFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF22ABF0FF3CB4F2FF3DB5F2FF3DB5F2FF3DB5 - F2FF3DB5F2FF3DB5F2FF3DB5F2FF3DB5F2FF3DB5F2FF3DB5F2FF3DB5F2FF3DB5 - F2FF3DB5F2FF3DB5F2FF3DB5F2FF3DB5F2FF3DB5F2FF4485A6FF565555FF6462 - 62FF6B6969FF6D6B6BFF6D6B6BFF6D6B6BFF6D6B6BFF6D6B6BFF6D6B6BFF6B69 - 69FF636262FF565555FF4294BEFF3DB5F2FF3DB5F2FF3DB5F2FF3DB5F2FF3DB5 - F2FF3DB5F2FF3DB5F2FF3DB5F2FF3DB5F2FF3DB5F2FF3DB5F2FF3DB5F2FF3DB5 - F2FF33B1F1FF13A5EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF0EA1ECFF0E9F - E9FF0D9CE5FF0D97DEFF0C92D6FF3D9ECAFF768484FF515252FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF2827 - 27A4000000470000002D00000012000000030000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000001111 - 1111494747FF494747FF494747FF494747FF494747FF494747FF4B4A4AFF6167 - 67FF92AEB0FF2799D0FF0C93D7FF0D98DFFF0D9CE6FF0E9FEAFF0EA1EDFF0EA2 - EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF25ACF0FF41B6F2FF42B7F2FF42B7F2FF42B7F2FF42B7 - F2FF42B7F2FF42B7F2FF42B7F2FF42B7F2FF42B7F2FF42B7F2FF42B7F2FF42B7 - F2FF42B7F2FF42B7F2FF42B7F2FF42B7F2FF42B7F2FF43B3EDFF58676FFF6866 - 66FF6E6D6DFF716F6FFF716F6FFF716F6FFF716F6FFF716F6FFF706E6EFF6C6B - 6BFF636161FF545E64FF42B5F0FF42B7F2FF42B7F2FF42B7F2FF42B7F2FF42B7 - F2FF42B7F2FF42B7F2FF42B7F2FF42B7F2FF42B7F2FF42B7F2FF42B7F2FF42B7 - F2FF42B7F2FF39B3F2FF13A5EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EDFF0EA0EBFF0E9E - E8FF0D9AE3FF0D95DBFF0C90D3FF65A4BCFF687070FF4D4C4CFF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4543 - 43EC03030352000000390000001C000000080000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000484646D0494747FF494747FF494747FF494747FF494747FF494848FF575A - 5AFF829595FF54ABD0FF0C91D4FF0D96DCFF0D9BE4FF0E9FE8FF0EA1ECFF0EA2 - EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF22AAF0FF45B8F2FF47B8F3FF47B8F3FF47B8F3FF47B8F3FF47B8 - F3FF47B8F3FF47B8F3FF47B8F3FF47B8F3FF47B8F3FF47B8F3FF47B8F3FF47B8 - F3FF47B8F3FF47B8F3FF47B8F3FF47B8F3FF47B8F3FF47B8F3FF519BC1FF6D6C - 6CFF737272FF747373FF747373FF747373FF747373FF747373FF737171FF6D6C - 6CFF616161FF50839DFF47B8F3FF47B8F3FF47B8F3FF47B8F3FF47B8F3FF47B8 - F3FF47B8F3FF47B8F3FF47B8F3FF47B8F3FF47B8F3FF47B8F3FF47B8F3FF47B8 - F3FF47B8F3FF47B8F3FF39B3F1FF11A4EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF0EA2EDFF0EA0EAFF0D9D - E6FF0D99E0FF0D94D9FF1291D0FF7E9EA5FF5C6161FF4A4949FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF1D1C1C8900000044000000290000000F0000000200000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000036343488494747FF494747FF494747FF494747FF494747FF494747FF5050 - 50FF707C7CFF82B7C5FF0C8FD1FF0D95DAFF0D99E1FF0D9DE7FF0EA0EAFF0EA2 - EDFF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF17A6EFFF47B8F2FF4CBAF3FF4CBAF3FF4CBAF3FF4CBAF3FF4CBAF3FF4CBA - F3FF4CBAF3FF4CBAF3FF4CBAF3FF4CBAF3FF4CBAF3FF4CBAF3FF4CBAF3FF4CBA - F3FF4CBAF3FF4CBAF3FF4CBAF3FF4CBAF3FF4CBAF3FF4CBAF3FF50B2E4FF7472 - 72FF777676FF787676FF787676FF787676FF787676FF787676FF757474FF6E6C - 6CFF616060FF4EA9D8FF4CBAF3FF4CBAF3FF4CBAF3FF4CBAF3FF4CBAF3FF4CBA - F3FF4CBAF3FF4CBAF3FF4CBAF3FF4CBAF3FF4CBAF3FF4CBAF3FF4CBAF3FF4CBA - F3FF4CBAF3FF4CBAF3FF4CBAF3FF31B0F1FF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF0EA1ECFF0E9FE9FF0D9C - E5FF0D97DEFF0C92D6FF379DCCFF798889FF535555FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF3D3C3CD20000004D00000035000000190000000600000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00002322223D494747FF494747FF494747FF494747FF494747FF494747FF4C4A - 4AFF616767FF92ADAEFF2D9CD0FF0C92D7FF0D97DEFF0D9CE5FF0E9FE9FF0EA1 - ECFF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF3DB5F2FF51BCF3FF51BCF3FF51BCF3FF51BCF3FF51BCF3FF51BCF3FF51BC - F3FF51BCF3FF51BCF3FF51BCF3FF51BCF3FF51BCF3FF51BCF3FF51BCF3FF51BC - F3FF51BCF3FF51BCF3FF51BCF3FF51BCF3FF51BCF3FF51BCF3FF619CBBFF7978 - 78FF7C7B7BFF7C7B7BFF7C7B7BFF7C7B7BFF7C7B7BFF7B7A7AFF777676FF6D6C - 6CFF5E7581FF51BCF3FF51BCF3FF51BCF3FF51BCF3FF51BCF3FF51BCF3FF51BC - F3FF51BCF3FF51BCF3FF51BCF3FF51BCF3FF51BCF3FF51BCF3FF51BCF3FF51BC - F3FF51BCF3FF51BCF3FF51BCF3FF50BCF3FF1DA9F0FF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF0EA2EDFF0EA0EBFF0D9EE7FF0D9A - E2FF0D95DBFF0C8FD2FF6AA5BAFF677171FF4D4D4DFF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF1413137000000041000000240000000C00000001000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000484646E3494747FF494747FF494747FF494747FF494747FF4948 - 48FF555858FF7D8D8DFF68B2CDFF0C90D3FF0D95DBFF0D9AE2FF0E9EE8FF0EA0 - EBFF0EA2EDFF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF20AA - F0FF57BEF4FF57BEF4FF57BEF4FF57BEF4FF57BEF4FF57BEF4FF57BEF4FF57BE - F4FF57BEF4FF57BEF4FF57BEF4FF57BEF4FF57BEF4FF57BEF4FF57BEF4FF57BE - F4FF57BEF4FF57BEF4FF57BEF4FF57BEF4FF57BEF4FF57BEF4FF728995FF7F7D - 7DFF807E7EFF807E7EFF807E7EFF807E7EFF807E7EFF7E7D7DFF787777FF6D6C - 6CFF5C9AB9FF57BEF4FF57BEF4FF57BEF4FF57BEF4FF57BEF4FF57BEF4FF57BE - F4FF57BEF4FF57BEF4FF57BEF4FF57BEF4FF57BEF4FF57BEF4FF57BEF4FF57BE - F4FF57BEF4FF57BEF4FF57BEF4FF57BEF4FF45B7F2FF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF0EA1ECFF0E9FE9FF0D9CE6FF0D98 - DFFF0C93D7FF1F95CFFF80999CFF595D5DFF4A4848FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF333131BA0000004A000000310000001500000004000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000003635358C494747FF494747FF494747FF494747FF494747FF4947 - 47FF4E4E4EFF687171FF93B6BBFF1B94D0FF0C93D8FF0D98DFFF0D9CE6FF0E9F - E9FF0EA1ECFF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF44B8 - F2FF5CC0F4FF5CC0F4FF5CC0F4FF5CC0F4FF5CC0F4FF5CC0F4FF5CC0F4FF5CC0 - F4FF5CC0F4FF5CC0F4FF5CC0F4FF5CC0F4FF5CC0F4FF5CC0F4FF5CC0F4FF5CC0 - F4FF5CC0F4FF5CC0F4FF5CC0F4FF5CC0F4FF5CC0F4FF5FB8E7FF807F7FFF8382 - 82FF848282FF848282FF848282FF848282FF838282FF807F7FFF787878FF6C6F - 71FF5CBCEDFF5CC0F4FF5CC0F4FF5CC0F4FF5CC0F4FF5CC0F4FF5CC0F4FF5CC0 - F4FF5CC0F4FF5CC0F4FF5CC0F4FF5CC0F4FF5CC0F4FF5CC0F4FF5CC0F4FF5CC0 - F4FF5CC0F4FF5CC0F4FF5CC0F4FF5CC0F4FF5BC0F4FF1EA9F0FF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA2EEFF0EA2EDFF0EA0EBFF0E9EE8FF0D9AE3FF0D96 - DCFF0C90D3FF57A4C3FF707C7CFF505151FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF484646FA0909095C0000003D000000200000000A000000000000 - 0000000000000000000000000001000000000000000000000000000000000000 - 00000000000023222228494747FF494747FF494747FF494747FF494747FF4947 - 47FF4A4848FF595C5CFF839696FF5BAECFFF0C90D4FF0D96DCFF0D9AE3FF0E9E - E8FF0EA0EBFF0EA2EDFF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF14A5EFFF5DC1 - F4FF61C2F4FF61C2F4FF61C2F4FF61C2F4FF61C2F4FF61C2F4FF61C2F4FF61C2 - F4FF61C2F4FF61C2F4FF61C2F4FF61C2F4FF61C2F4FF61C2F4FF61C2F4FF61C2 - F4FF61C2F4FF61C2F4FF61C2F4FF61C2F4FF61C2F4FF6FA8C5FF868484FF8887 - 87FF888787FF888787FF888787FF888787FF878686FF828181FF797878FF6A8E - A1FF61C2F4FF61C2F4FF61C2F4FF61C2F4FF61C2F4FF61C2F4FF61C2F4FF61C2 - F4FF61C2F4FF61C2F4FF61C2F4FF61C2F4FF61C2F4FF61C2F4FF61C2F4FF61C2 - F4FF61C2F4FF61C2F4FF61C2F4FF61C2F4FF61C2F4FF3AB3F2FF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA2EEFF0EA1ECFF0E9FE9FF0D9CE6FF0D98DFFF0C93 - D8FF1893D0FF809FA6FF5E6363FF4B4A4AFF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF272626A1000000470000002C00000012000000030000 - 0000000000000000000000000002000000000000000000000000000000000000 - 00000000000000000000484646C0494747FF494747FF494747FF494747FF4947 - 47FF494747FF4F4F4FFF6B7676FF90B8BEFF1692D0FF0C93D8FF0D98DFFF0D9C - E5FF0E9FE9FF0EA1ECFF0EA2EEFF0EA2EEFF0EA3EFFF0EA3EFFF25ACF0FF66C4 - F5FF66C4F5FF66C4F5FF66C4F5FF66C4F5FF66C4F5FF66C4F5FF66C4F5FF66C4 - F5FF66C4F5FF66C4F5FF66C4F5FF66C4F5FF66C4F5FF66C4F5FF66C4F5FF66C4 - F5FF66C4F5FF66C4F5FF66C4F5FF66C4F5FF66C4F5FF7F98A5FF8B8A8AFF8C8A - 8AFF8C8A8AFF8C8A8AFF8C8A8AFF8C8A8AFF8A8888FF838282FF797878FF69AF - D3FF66C4F5FF66C4F5FF66C4F5FF66C4F5FF66C4F5FF66C4F5FF66C4F5FF66C4 - F5FF66C4F5FF66C4F5FF66C4F5FF66C4F5FF66C4F5FF66C4F5FF66C4F5FF66C4 - F5FF66C4F5FF66C4F5FF66C4F5FF66C4F5FF66C4F5FF52BCF3FF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA2EEFF0EA2EDFF0EA0EBFF0D9EE7FF0D9AE2FF0D96DBFF0C90 - D3FF50A2C5FF738080FF525353FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF444242E70000004F000000390000001C000000070000 - 0000000000000000000000000003000000000000000000000000000000000000 - 0000000000000000000024232350494747FF494747FF494747FF494747FF4947 - 47FF494747FF4B4949FF595D5DFF849797FF60B0CFFF0C90D3FF0D95DBFF0D9A - E2FF0D9DE7FF0EA0EAFF0EA1EDFF0EA2EEFF0EA3EFFF0EA3EFFF34B1F1FF6CC6 - F5FF6CC6F5FF6CC6F5FF6CC6F5FF6CC6F5FF6CC6F5FF6CC6F5FF6CC6F5FF6CC6 - F5FF6CC6F5FF6CC6F5FF6CC6F5FF6CC6F5FF6CC6F5FF6CC6F5FF6CC6F5FF6CC6 - F5FF6CC6F5FF6CC6F5FF6CC6F5FF6CC6F5FF6EC2EDFF8E8F8FFF8F8E8EFF908F - 8FFF908F8FFF908F8FFF908F8FFF8F8E8EFF8C8B8BFF848383FF78848BFF6CC6 - F5FF6CC6F5FF6CC6F5FF6CC6F5FF6CC6F5FF6CC6F5FF6CC6F5FF6CC6F5FF6CC6 - F5FF6CC6F5FF6CC6F5FF6CC6F5FF6CC6F5FF6CC6F5FF6CC6F5FF6CC6F5FF6CC6 - F5FF6CC6F5FF6CC6F5FF6CC6F5FF6CC6F5FF6CC6F5FF63C3F4FF0EA3EFFF0EA3 - EFFF0EA2EEFF0EA2EDFF0EA1ECFF0E9FE9FF0D9CE5FF0D98DFFF0C93D7FF1A94 - CFFF82A0A5FF5F6464FF4C4B4BFF494747FF494747FF494747FF4A4848FF4B49 - 49FF4B4A4AFF4B4A4AFF4B4A4AFF4B4A4AFF4B4A4AFF4B4A4AFF4B4A4AFF4B4A - 4AFF4B4A4AFF4B4A4AFF4B4A4AFF4A4949FF4A4848FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF1C1B1B8600000044000000280000000E0000 - 0002000000000000000000000002000000000000000000000000000000000000 - 0000000000000000000011101004484646DB494747FF494747FF494747FF4947 - 47FF494747FF494747FF4F4F4FFF697272FF92B5B9FF2297D0FF0C92D6FF0D97 - DEFF0D9BE4FF0E9FE8FF0EA0EBFF0EA2EDFF0EA2EEFF0EA3EFFF3EB5F2FF71C9 - F6FF71C9F6FF71C9F6FF71C9F6FF71C9F6FF71C9F6FF71C9F6FF71C9F6FF71C9 - F6FF71C9F6FF71C9F6FF71C9F6FF71C9F6FF78B7D7FF7DB3CFFF7EB5D1FF7EB5 - D1FF7EB5D1FF7EB5D1FF7EB5D1FF7EB5D1FF85AABDFF949393FF949393FF9493 - 93FF949393FF949393FF949393FF939292FF8E8D8DFF858484FF77A5BDFF71C9 - F6FF71C9F6FF71C9F6FF71C9F6FF71C9F6FF71C9F6FF71C9F6FF71C9F6FF71C9 - F6FF71C9F6FF71C9F6FF71C9F6FF71C9F6FF71C9F6FF71C9F6FF71C9F6FF71C9 - F6FF71C9F6FF71C9F6FF71C9F6FF71C9F6FF71C9F6FF70C9F5FF0EA3EFFF0EA3 - EFFF0EA2EEFF0EA1EDFF0E9FEAFF0D9DE7FF0D99E1FF0D95DAFF0C8FD2FF5FA6 - C2FF717C7CFF515252FF494747FF494747FF4A4848FF4E4D4DFF545656FF5A5D - 5DFF5C6161FF5C6161FF5C6161FF5C6161FF5C6161FF5C6161FF5C6161FF5C61 - 61FF5C6161FF5C6161FF5B6060FF585C5CFF525353FF4C4B4BFF494747FF4947 - 47FF494747FF494747FF494747FF3D3B3BCF0000004D00000035000000180000 - 0005000000000000000000000002000000000000000000000000000000000000 - 000000000000000000000000000047454560494747FF494747FF494747FF4947 - 47FF494747FF494747FF4A4848FF575A5AFF7D8D8DFF75B6CCFF0C8FD1FF0D94 - D9FF0D99E0FF0D9CE6FF0E9FE9FF0EA1ECFF0EA2EDFF0EA2EEFF3EB5F2FF77CB - F6FF77CBF6FF77CBF6FF77CBF6FF77CBF6FF77CBF6FF77CBF6FF77CBF6FF77CB - F6FF77CBF6FF77CBF6FF77CBF6FF77CBF6FF889CA7FF949393FF989797FF9997 - 97FF999797FF999797FF999797FF999797FF999797FF999797FF999797FF9997 - 97FF999797FF999797FF989797FF969595FF908F8FFF868787FF78C3E9FF77CB - F6FF77CBF6FF77CBF6FF77CBF6FF77CBF6FF77CBF6FF77CBF6FF77CBF6FF77CB - F6FF77CBF6FF77CBF6FF77CBF6FF77CBF6FF77CBF6FF77CBF6FF77CBF6FF77CB - F6FF77CBF6FF77CBF6FF77CBF6FF77CBF6FF77CBF6FF73C9F5FF0EA3EFFF0EA2 - EEFF0EA1EDFF0EA0EBFF0E9EE8FF0D9BE3FF0D96DDFF0C91D6FF2C9ACDFF8098 - 9AFF5B6060FF4B4A4AFF494747FF494747FF4C4B4BFF50626AFF6699AFFF75A4 - B8FF79A8BBFF79A9BCFF79A9BCFF79A9BCFF79A9BCFF79A9BCFF79A9BCFF79A9 - BCFF79A9BCFF79A9BCFF78A7BAFF759EAFFF6A6F6FFF515252FF4A4848FF4947 - 47FF494747FF494747FF494747FF494747FF1312126D00000040000000240000 - 000C000000010000000000000002000000000000000000000000000000000000 - 000000000000000000000000000048464604494747DB494747FF494747FF4947 - 47FF494747FF494747FF494747FF4D4C4CFF626969FF90A8A9FF46A6D0FF0C90 - D4FF0D96DBFF0D9AE2FF0D9EE7FF0EA0EAFF0EA1EDFF0EA2EEFF34B1F1FF7DCD - F6FF7DCDF6FF7DCDF6FF7DCDF6FF7DCDF6FF7DCDF6FF7DCDF6FF7DCDF6FF7DCD - F6FF7DCDF6FF7DCDF6FF7DCDF6FF7DCDF6FF8DA0AAFF999898FF9C9B9BFF9D9C - 9CFF9D9C9CFF9D9C9CFF9D9C9CFF9D9C9CFF9D9C9CFF9D9C9CFF9D9C9CFF9D9C - 9CFF9D9C9CFF9D9C9CFF9C9B9BFF999898FF919090FF859DA9FF7DCDF6FF7DCD - F6FF7DCDF6FF7DCDF6FF7DCDF6FF7DCDF6FF7DCDF6FF7DCDF6FF7DCDF6FF7DCD - F6FF7DCDF6FF7DCDF6FF7DCDF6FF7DCDF6FF7DCDF6FF7DCDF6FF7DCDF6FF7DCD - F6FF7DCDF6FF7DCDF6FF7DCDF6FF7DCDF6FF7DCDF6FF6BC7F5FF0EA2EEFF0EA2 - EDFF0EA1ECFF0E9FE9FF0D9CE5FF0D98DFFF0C93D8FF1391D1FF79A8B5FF6871 - 71FF4F4F4FFF494747FF494747FF494747FF4D4D4DFF537684FF70CCF6FF80D1 - F7FF80D1F7FF80D1F7FF80D1F7FF80D1F7FF80D1F7FF80D1F7FF80D1F7FF80D1 - F7FF80D1F7FF80D1F7FF80D1F7FF83CAEBFF7D8383FF565858FF4A4848FF4947 - 47FF494747FF494747FF494747FF494747FF302E2EB70000004A000000300000 - 0014000000040000000000000002000000000000000000000000000000000000 - 00000000000000000000000000000000000048464660494747FF494747FF4947 - 47FF494747FF494747FF494747FF4A4848FF525353FF6F7B7BFF90B8BFFF1C94 - CFFF0C92D7FF0D97DDFF0D9BE3FF0E9EE8FF0EA0EBFF0EA1EDFF22AAEFFF82CF - F7FF82CFF7FF82CFF7FF82CFF7FF82CFF7FF82CFF7FF82CFF7FF82CFF7FF82CF - F7FF82CFF7FF82CFF7FF82CFF7FF82CFF7FF92A4AEFF9D9C9CFFA1A0A0FFA1A0 - A0FFA1A0A0FFA1A0A0FFA1A0A0FFA1A0A0FFA1A0A0FFA1A0A0FFA1A0A0FFA1A0 - A0FFA1A0A0FFA1A0A0FFA09F9FFF9B9A9AFF929191FF86B9D3FF82CFF7FF82CF - F7FF82CFF7FF82CFF7FF82CFF7FF82CFF7FF82CFF7FF82CFF7FF82CFF7FF82CF - F7FF82CFF7FF82CFF7FF82CFF7FF82CFF7FF82CFF7FF82CFF7FF82CFF7FF82CF - F7FF82CFF7FF82CFF7FF82CFF7FF82CFF7FF82CFF7FF5DC0F4FF0EA2EDFF0EA1 - ECFF0E9FE9FF0D9DE6FF0D99E1FF0D95DAFF0C8FD3FF54A4C6FF778686FF5558 - 58FF4A4848FF494747FF494747FF494747FF4D4D4DFF557785FF73CDF6FF80D1 - F7FF80D1F7FF80D1F7FF80D1F7FF80D1F7FF80D1F7FF80D1F7FF80D1F7FF80D1 - F7FF80D1F7FF80D1F7FF80D1F7FF82C9EBFF7B8181FF555757FF4A4848FF4947 - 47FF494747FF494747FF494747FF494747FF474545F70909095B0000003C0000 - 001F000000090000000000000001000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000484646CB494747FF4947 - 47FF494747FF494747FF494747FF494747FF4B4A4AFF595C5CFF7E8F8FFF7AB8 - CBFF0E8FD1FF0D94D8FF0D98DFFF0D9CE5FF0E9FE8FF0EA0EBFF0FA2EDFF74C9 - F5FF88D1F7FF88D1F7FF88D1F7FF88D1F7FF88D1F7FF88D1F7FF88D1F7FF88D1 - F7FF88D1F7FF88D1F7FF88D1F7FF88D1F7FF96A8B1FFA1A0A0FFA4A3A3FFA5A4 - A4FFA5A4A4FFA5A4A4FFA5A4A4FFA5A4A4FFA5A4A4FFA5A4A4FFA5A4A4FFA5A4 - A4FFA5A4A4FFA4A3A3FFA2A1A1FF9C9B9BFF93989BFF88D0F5FF88D1F7FF88D1 - F7FF88D1F7FF88D1F7FF88D1F7FF88D1F7FF88D1F7FF88D1F7FF88D1F7FF88D1 - F7FF88D1F7FF88D1F7FF88D1F7FF88D1F7FF88D1F7FF88D1F7FF88D1F7FF88D1 - F7FF88D1F7FF88D1F7FF88D1F7FF88D1F7FF88D1F7FF38B2F0FF0EA1ECFF0E9F - EAFF0D9DE7FF0D9AE2FF0D96DBFF0C91D5FF339BCDFF829A9CFF5D6262FF4C4B - 4BFF494747FF494747FF494747FF494747FF4C4B4BFF566469FF65BEE6FF80D1 - F7FF80D1F7FF80D1F7FF8EB8CAFF8AA7ACFF7C969CFF738B91FF71888EFF7188 - 8EFF71888EFF71888EFF70878DFF6B7E84FF5F6363FF4F5050FF494848FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF2423239C000000460000 - 002B000000100000000300000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000083A2A238494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF4D4D4DFF606767FF8BA1 - A1FF5CAECFFF0C8FD2FF0D94D9FF0D99E0FF0D9CE5FF0E9FE9FF0EA0EBFF4BB9 - F1FF8DD3F7FF8DD3F7FF8DD3F7FF8DD3F7FF8DD3F7FF8DD3F7FF8DD3F7FF8DD3 - F7FF8DD3F7FF8DD3F7FF8DD3F7FF8DD3F7FF9BACB5FFA5A4A4FFA8A7A7FFA8A7 - A7FFA8A7A7FFA8A7A7FFA8A7A7FFA8A7A7FFA8A7A7FFA8A7A7FFA8A7A7FFA8A7 - A7FFA8A7A7FFA8A7A7FFA4A3A3FF9D9D9DFF92B2C2FF8DD3F7FF8DD3F7FF8DD3 - F7FF8DD3F7FF8DD3F7FF8DD3F7FF8DD3F7FF8DD3F7FF8DD3F7FF8DD3F7FF8DD3 - F7FF8DD3F7FF8DD3F7FF8DD3F7FF8DD3F7FF8DD3F7FF8DD3F7FF8DD3F7FF8DD3 - F7FF8DD3F7FF8DD3F7FF8DD3F7FF8DD3F7FF82CFF6FF16A4EDFF0EA0EAFF0D9E - E7FF0D9BE3FF0D97DDFF0C92D6FF1E95CFFF81A6ADFF666E6EFF4F4F4FFF4947 - 47FF494747FF494747FF494747FF494747FF4A4848FF525353FF5D7B86FF71CB - F4FF80D1F7FF80D1F7FF81CEF2FF91A7AEFF717E7EFF5E6464FF565959FF5557 - 57FF555757FF555757FF545757FF525454FF4E4F4FFF4B4949FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF434141E50000004E0000 - 0036000000190000000600000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000004947479B4947 - 47FF494747FF494747FF494747FF494747FF494747FF4A4848FF505151FF6770 - 70FF92ADAFFF44A5D0FF0C90D4FF0D95DAFF0D99E1FF0D9CE6FF0E9FE9FF19A5 - ECFF86D0F6FF92D5F7FF92D5F7FF92D5F8FF92D5F8FF92D5F8FF92D5F8FF92D5 - F8FF92D5F8FF92D5F8FF92D5F8FF92D5F8FF9FAEB7FFA7A6A6FFA9A8A8FFA9A8 - A8FFA9A8A8FFA9A8A8FFA9A8A8FFA9A8A8FFA9A8A8FFA9A8A8FFA9A8A8FFA9A8 - A8FFA9A8A8FFA8A7A7FFA4A4A4FF9F9E9EFF94CBE7FF92D5F8FF92D5F8FF92D5 - F8FF92D5F8FF92D5F8FF92D5F8FF92D5F8FF92D5F8FF92D5F8FF92D5F8FF92D5 - F8FF92D5F8FF92D5F8FF92D5F8FF92D5F8FF92D5F8FF92D5F8FF92D5F8FF92D5 - F8FF92D5F8FF92D5F8FF92D5F7FF92D5F7FF50BBF1FF0EA0EAFF0D9EE7FF0D9B - E3FF0D97DEFF0C92D7FF1391D0FF79AAB9FF6E7979FF535454FF4A4848FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF4C4A4AFF565959FF5E91 - A5FF79CFF6FF80D1F7FF80D1F7FF84CBEBFF879496FF616767FF505151FF4A49 - 49FF4A4848FF4A4848FF4A4848FF494848FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF1C1B1B820000 - 003F000000220000000A00000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000A0D0D0104947 - 47E3494747FF494747FF494747FF494747FF494747FF494747FF4A4848FF5354 - 54FF6E7979FF93B5B9FF319ED0FF0C91D4FF0D95DBFF0D99E1FF0D9CE6FF0E9F - E9FF47B7EFFF98D7F7FF98D7F8FF98D7F8FF98D7F8FF98D7F8FF98D7F8FF98D7 - F8FF98D7F8FF98D7F8FF98D7F8FF98D7F8FFA0B0B8FFA5A5A5FFA6A6A6FFA6A6 - A6FFA6A6A6FFA6A6A6FFA6A6A6FFA6A6A6FFA6A6A6FFA6A6A6FFA6A6A6FFA6A6 - A6FFA6A6A6FFA6A5A5FFA3A3A3FF9EACB3FF98D7F8FF98D7F8FF98D7F8FF98D7 - F8FF98D7F8FF98D7F8FF98D7F8FF98D7F8FF98D7F8FF98D7F8FF98D7F8FF98D7 - F8FF98D7F8FF98D7F8FF98D7F8FF98D7F8FF98D7F8FF98D7F8FF98D7F8FF98D7 - F8FF98D7F8FF98D7F8FF98D7F7FF83CFF5FF17A3EAFF0D9EE7FF0D9BE3FF0D97 - DEFF0C93D8FF0E90D1FF6BAAC1FF758383FF565858FF4B4949FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF4D4C4CFF5A5E - 5EFF5FA5C2FF7ED0F7FF80D1F7FF80D1F7FF89C2DCFF7C8686FF5B6060FF4E4D - 4DFF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF383737C70000 - 00470000002B0000001000000002000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000006674 - 744C494747FF494747FF494747FF494747FF494747FF494747FF494747FF4B49 - 49FF555858FF738080FF91B8BEFF2899CFFF0C91D5FF0D95DBFF0D99E1FF0D9C - E5FF11A0E9FF6FC6F3FF9ED9F7FF9ED9F8FF9ED9F8FF9EDAF8FF9EDAF8FF9EDA - F8FF9EDAF8FF9EDAF8FF9EDAF8FF9EDAF8FFA3ABAFFFA4A4A4FFA5A4A4FFA5A4 - A4FFA5A4A4FFA5A4A4FFA5A4A4FFA5A4A4FFA5A4A4FFA5A4A4FFA5A4A4FFA5A4 - A4FFA5A4A4FFA4A4A4FFA3A3A3FFA0C3D5FF9EDAF8FF9EDAF8FF9EDAF8FF9EDA - F8FF9EDAF8FF9EDAF8FF9EDAF8FF9EDAF8FF9EDAF8FF9EDAF8FF9EDAF8FF9EDA - F8FF9EDAF8FF9EDAF8FF9EDAF8FF9EDAF8FF9EDAF8FF9EDAF8FF9EDAF8FF9ED9 - F8FF9ED9F8FF9ED9F8FF97D6F6FF32AEECFF0D9EE7FF0D9BE3FF0D97DEFF0C93 - D8FF0D8FD1FF61A8C4FF7A8A8AFF595D5DFF4C4B4BFF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF4A4848FF4F4E - 4EFF5D6668FF65B9DCFF80D1F7FF80D1F7FF80D1F7FF8DB7C9FF737D7DFF575B - 5BFF4C4B4BFF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF484646F90707 - 0755000000330000001600000004000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000066757597494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF4C4B4BFF575B5BFF768484FF93BAC0FF2899CFFF0C91D4FF0D95DAFF0D99 - E0FF0D9CE5FF1BA3E9FF86CFF4FFA3DBF8FFA3DBF8FFA3DBF8FFA3DCF9FFA3DC - F9FFA3DCF9FFA3DCF9FFA3DCF9FFA3DCF9FFA6ADB1FFA7A7A7FFA7A7A7FFA7A7 - A7FFA7A7A7FFA7A7A7FFA7A7A7FFA7A7A7FFA7A7A7FFA7A7A7FFA7A7A7FFA7A7 - A7FFA7A7A7FFA7A7A7FFA7A8A9FFA3D9F5FFA3DCF9FFA3DCF9FFA3DCF9FFA3DC - F9FFA3DCF9FFA3DCF9FFA3DCF9FFA3DCF9FFA3DCF9FFA3DCF9FFA3DCF9FFA3DC - F9FFA3DCF9FFA3DCF9FFA3DCF9FFA3DCF9FFA3DCF9FFA3DCF9FFA3DCF9FFA3DB - F8FFA3DBF8FFA1DAF7FF4BB7EEFF0D9DE6FF0D9AE2FF0D97DDFF0C93D8FF0E8F - D1FF61A9C5FF7D8D8EFF5B6060FF4C4B4BFF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4A48 - 48FF515252FF5E7379FF6DC5ECFF80D1F7FF80D1F7FF81D0F5FF8EA9B3FF6A74 - 74FF545656FF4B4A4AFF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF1E1D - 1D860000003A0000001B00000006000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000A0D1D108484646CF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF4C4B4BFF585B5BFF768484FF92B8BEFF329ED0FF0C90D4FF0D94 - D9FF0D98DFFF0D9BE3FF1EA4E9FF8DD1F4FFA9DDF8FFA9DDF8FFA9DDF9FFA9DE - F9FFA9DEF9FFA9DEF9FFA9DEF9FFA9DEF9FFA9DEF9FFA9DEF9FFA9DEF9FFA9DE - F9FFA9DEF9FFA9DEF9FFA9DEF9FFA9DEF9FFA9DEF9FFA9DEF9FFA9DEF9FFA9DE - F9FFA9DEF9FFA9DEF9FFA9DEF9FFA9DEF9FFA9DEF9FFA9DEF9FFA9DEF9FFA9DE - F9FFA9DEF9FFA9DEF9FFA9DEF9FFA9DEF9FFA9DEF9FFA9DEF9FFA9DEF9FFA9DE - F9FFA9DEF9FFA9DEF9FFA9DEF9FFA9DEF9FFA9DEF9FFA9DDF9FFA9DDF9FFA9DD - F8FFA5DBF7FF54BAEFFF0D9CE6FF0D99E1FF0D96DCFF0C92D7FF0F8FD0FF67AB - C4FF7C8D8EFF5C6161FF4D4C4CFF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF4B4A4AFF545656FF5E8492FF75CDF5FF81D1F7FF81D1F7FF83CDF0FF8B9C - A0FF646B6BFF515252FF4A4848FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF3635 - 35BD0000003E0000001F00000008000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000A0D1D124494747EF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF4C4B4BFF575B5BFF738080FF93B5B9FF44A5D0FF0C8F - D2FF0D94D8FF0D97DDFF0D9AE2FF1CA2E7FF81CCF3FFAEDFF8FFAEDFF8FFAEDF - F9FFAEDFF9FFAEE0F9FFAEE0FAFFAEE0FAFFAEE0FAFFAEE0FAFFAEE0FAFFAEE0 - FAFFAEE0FAFFAEE0FAFFAEE0FAFFAEE0FAFFAEE0FAFFAEE0FAFFAEE0FAFFAEE0 - FAFFAEE0FAFFAEE0FAFFAEE0FAFFAEE0FAFFAEE0FAFFAEE0FAFFAEE0FAFFAEE0 - FAFFAEE0FAFFAEE0FAFFAEE0FAFFAEE0FAFFAEE0FAFFAEE0FAFFAEE0FAFFAEE0 - FAFFAEE0FAFFAEE0FAFFAEE0FAFFAEE0F9FFAEDFF9FFAEDFF9FFAEDFF8FFA4DB - F7FF4AB6EDFF0D9BE4FF0D99E0FF0D95DBFF0C91D5FF1993D0FF73ADC0FF7989 - 89FF5B5F5FFF4D4C4CFF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF4C4B4BFF575B5BFF5F99AFFF7CD0F6FF81D1F7FF81D1F7FF87C8 - E6FF838F91FF5F6565FF4F4F4FFF4A4848FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4543 - 43E900000041000000220000000A000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000066757544494747FB494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF4C4B4BFF555858FF6E7979FF92ADAFFF5CAE - CFFF0E8FD1FF0C92D7FF0D96DBFF0D99E0FF159EE5FF65C1F0FFAEDFF7FFB3E1 - F9FFB3E1F9FFB3E2F9FFB3E2FAFFB3E2FAFFB3E2FAFFB3E2FAFFB3E2FAFFB3E2 - FAFFB3E2FAFFB3E2FAFFB3E2FAFFB3E2FAFFB3E2FAFFB3E2FAFFB3E2FAFFB3E2 - FAFFB3E2FAFFB3E2FAFFB3E2FAFFB3E2FAFFB3E2FAFFB3E2FAFFB3E2FAFFB3E2 - FAFFB3E2FAFFB3E2FAFFB3E2FAFFB3E2FAFFB3E2FAFFB3E2FAFFB3E2FAFFB3E2 - FAFFB3E2FAFFB3E2FAFFB3E2F9FFB3E1F9FFB3E1F9FFB3E1F8FF97D5F5FF30AB - E9FF0D9AE2FF0D97DEFF0D94D9FF0C90D4FF2598CFFF80ACB7FF748181FF585C - 5CFF4C4B4BFF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF4E4D4DFF5B6060FF61ACCBFF80D0F7FF81D1F7FF81D1 - F7FF8BBFD6FF7A8484FF5A5F5FFF4D4D4DFF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF0A09094D000000230000000A000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000039586867494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF4B4949FF535454FF677070FF8BA1 - A1FF7AB8CBFF1B94CFFF0C90D4FF0D94D9FF0D97DEFF0D9AE2FF36ADE9FF96D4 - F4FFB8E3F8FFB8E3F9FFB8E3FAFFB8E3FAFFB8E3FAFFB8E4FAFFB8E4FAFFB8E4 - FAFFB8E4FAFFB8E4FAFFB8E4FAFFB8E4FAFFB8E4FAFFB8E4FAFFB8E4FAFFB8E4 - FAFFB8E4FAFFB8E4FAFFB8E4FAFFB8E4FAFFB8E4FAFFB8E4FAFFB8E4FAFFB8E4 - FAFFB8E4FAFFB8E4FAFFB8E4FAFFB8E4FAFFB8E4FAFFB8E4FAFFB8E4FAFFB8E3 - FAFFB8E3FAFFB8E3FAFFB8E3F9FFB8E3F9FFAFDFF7FF68C1EFFF18A0E5FF0D99 - E0FF0D96DBFF0C92D7FF0D8FD1FF45A3CCFF85A5AAFF6D7777FF555858FF4C4B - 4BFF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF4A4848FF504F4FFF606B6EFF8DCCE8FFA4DEF9FFA2DD - F9FF9DDBF9FF9AB8C4FF707A7AFF565959FF4B4A4AFF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF1616165D000000210000000A000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000003958687F494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF4A4848FF505151FF6067 - 67FF7E8F8FFF90B8BFFF46A6D0FF0C8FD1FF0C92D6FF0D95DBFF0D98DFFF149D - E3FF52B8ECFFA3DAF6FFBEE5F9FFBEE5F9FFBEE5FAFFBEE5FAFFBEE6FAFFBEE6 - FAFFBEE6FBFFBEE6FBFFBEE6FBFFBEE6FBFFBEE6FBFFBEE6FBFFBEE6FBFFBEE6 - FBFFBEE6FBFFBEE6FBFFBEE6FBFFBEE6FBFFBEE6FBFFBEE6FBFFBEE6FBFFBEE6 - FBFFBEE6FBFFBEE6FBFFBEE6FBFFBEE6FBFFBEE6FBFFBEE6FAFFBEE6FAFFBEE5 - FAFFBEE5F9FFBEE5F9FFB8E3F8FF80CBF2FF2AA7E7FF0D99E1FF0D96DDFF0D94 - D9FF0C90D4FF1D95D0FF6DADC4FF839798FF656C6CFF525353FF4B4949FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF4A4949FF525353FF677C82FF9CD9F5FFAAE0 - FAFFAAE0FAFFA9DFF9FF96A8AEFF666F6FFF515252FF4A4848FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF1D1C1C6B0000001E00000008000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000003958688F494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF4A4848FF4D4D - 4DFF595C5CFF6F7B7BFF8FA8A9FF77B7CCFF2297D0FF0C90D3FF0C93D8FF0D96 - DCFF0D98DFFF159EE3FF4DB6EBFF99D6F5FFC2E7F9FFC3E7FAFFC3E7FAFFC3E7 - FAFFC3E7FAFFC3E7FBFFC3E7FBFFC3E8FBFFC3E8FBFFC3E8FBFFC3E8FBFFC3E8 - FBFFC3E8FBFFC3E8FBFFC3E8FBFFC3E8FBFFC3E8FBFFC3E8FBFFC3E8FBFFC3E8 - FBFFC3E8FBFFC3E7FBFFC3E7FBFFC3E7FAFFC3E7FAFFC3E7FAFFC3E7FAFFC3E7 - F9FFB4E1F7FF76C7F0FF2CA8E7FF0D99E1FF0D97DEFF0D94DAFF0C91D5FF0E8F - D1FF48A4CDFF88ABB1FF748282FF5C6161FF4F4F4FFF4A4848FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF4B4A4AFF555757FF71939FFFA9E0 - FAFFAFE1FAFFAFE1FAFFACD9EFFF848F8FFF5C6060FF4C4C4CFF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF1B1A1A620000001900000005000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000003958688F4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF4B4A4AFF525353FF626868FF7C8D8DFF93B5B9FF60B0CFFF1792D0FF0C90 - D4FF0C93D8FF0D95DBFF0D97DEFF0D99E1FF30A9E7FF6DC3EFFFA4DAF6FFC6E8 - F9FFC8E9FAFFC8E9FAFFC8E9FAFFC8E9FBFFC8E9FBFFC8E9FBFFC8E9FBFFC8E9 - FBFFC8E9FBFFC8E9FBFFC8E9FBFFC8E9FBFFC8E9FBFFC8E9FBFFC8E9FBFFC8E9 - FBFFC8E9FBFFC8E9FBFFC8E9FAFFC8E9FAFFC8E9FAFFBAE3F8FF8ED1F3FF4AB4 - EBFF189FE4FF0D98E0FF0D96DDFF0D94D9FF0C91D6FF0C8FD1FF349ECFFF7CAF - BEFF819393FF666E6EFF545656FF4C4B4BFF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF4C4C4CFF5A5D5DFF84B2 - C4FFB3E3FAFFB4E3FAFFB4E3FAFFA1B8C1FF687171FF515252FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF1515154A0000001400000004000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000003958 - 687B494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF4A4848FF4D4C4CFF575959FF697272FF849797FF90B7BEFF5CAE - CFFF1B94D0FF0C90D3FF0C92D7FF0D95DAFF0D96DCFF0D98DFFF0D99E1FF28A6 - E6FF4EB6EBFF82CCF2FFA3DAF5FFC0E6F8FFCDEBFAFFCDEBFAFFCDEBFAFFCDEB - FBFFCDEBFBFFCDEBFBFFCDEBFBFFCDEBFBFFCDEBFBFFCDEBFBFFCDEBFAFFCDEB - FAFFCAEAF9FFB2E0F7FF94D3F4FF68C1EFFF3BAEE9FF159EE4FF0D99E0FF0D97 - DEFF0D95DBFF0D93D8FF0C91D5FF0C8FD1FF379FCFFF76AFC2FF879D9EFF6D78 - 78FF595D5DFF4E4E4EFF4A4848FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF4B4949FF4D4D4DFF4F50 - 50FF4F5050FF4D4D4DFF4B4949FF494747FF494747FF4A4848FF4F4F4FFF6472 - 75FFA8DDF5FFB8E5FBFFB8E5FBFFAFD4E4FF7B8484FF565858FF4A4848FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4846 - 46FC0404042B0000000E00000002000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000039586860494747FB494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF4A4848FF4F4F4FFF595D5DFF6B7575FF8396 - 96FF93B6BBFF67B1CDFF2D9CD0FF0C8FD1FF0C91D4FF0C93D7FF0D95DAFF0D96 - DCFF0D97DEFF0D98E0FF0D99E1FF109BE3FF26A5E6FF3BAFE9FF4DB6EBFF5BBB - EDFF66C0EFFF6CC3EFFF6EC4EFFF69C2EFFF61BEEEFF55B9ECFF44B2EAFF31AA - E8FF1AA0E4FF0D9AE2FF0D99E0FF0D98DFFF0D97DDFF0D95DBFF0D94D8FF0C92 - D6FF0C90D3FF1692D0FF47A4CEFF7FB1BFFF869C9DFF6F7A7AFF5C6161FF5051 - 51FF4B4949FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF4B4949FF515252FF5D6161FF656D - 6DFF656D6DFF5D6262FF525252FF4B4949FF494747FF494747FF4A4949FF585C - 5CFF93C0D2FFBDE7FBFFBDE7FBFFB7E0F3FF848D8DFF595D5DFF4A4949FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4543 - 43D80000001D0000000800000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000039586840494747E7494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF4B4949FF4F4F4FFF595C - 5CFF687171FF7D8D8DFF91ADAEFF83B7C5FF54ABCFFF2799D0FF0C8FD1FF0C90 - D4FF0C92D6FF0D93D8FF0D94DAFF0D95DBFF0D96DCFF0D97DDFF0D97DEFF0D98 - DFFF0D98DFFF0D98DFFF0D98DFFF0D98DFFF0D98DFFF0D97DEFF0D97DEFF0D97 - DDFF0D95DBFF0D95DAFF0D94D9FF0C92D7FF0C91D5FF0C8FD2FF1592D0FF3BA2 - D0FF69ADC7FF8BAEB4FF819393FF6B7676FF5B5F5FFF505151FF4B4A4AFF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF4C4C4CFF637C87FFAEDCF0FFB8E0 - F2FFB8E0F2FF95A8AFFF5E6464FF4E4E4EFF494747FF494747FF4A4848FF5658 - 58FF8BACB7FFC2E8FBFFC2E8FBFFBCE1F3FF868F8FFF5A5E5EFF4A4949FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF302F - 2F9C000000120000000300000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000001B7AAA1C494747C3494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4A48 - 48FF4E4E4EFF555858FF616767FF707C7CFF829595FF92AEAFFF88B7C3FF63B0 - CDFF3EA2D0FF1F96D0FF0E8FD1FF0C8FD2FF0C90D4FF0C91D5FF0C92D6FF0C92 - D6FF0C92D7FF0C92D7FF0C92D7FF0C92D7FF0C92D7FF0C92D6FF0C91D6FF0C90 - D4FF0C90D3FF0C8ED1FF1491D0FF2C9CD0FF4FA8CEFF72B0C4FF8EAFB4FF8599 - 9AFF738080FF636B6BFF575A5AFF4F4F4FFF4B4949FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF4D4C4CFF677E86FFBEE8FBFFC6EA - FCFFC6EAFCFFADC1CAFF6E7979FF545656FF4A4848FF494747FF4C4A4AFF5B5F - 5FFF9DC9D9FFC6EAFCFFC6EAFCFFBFE2F3FF848D8DFF595D5DFF4A4949FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF1C1B - 1B4A000000090000000100000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000001B7AAA0439586887494747FB494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494848FF4C4A4AFF505050FF575A5AFF616767FF6D7878FF7B8B - 8BFF899E9EFF93AFB1FF8EB6BEFF7DB5C5FF69B1CBFF57ACCFFF49A7D0FF3DA2 - D1FF369FD1FF319DD0FF309DD0FF329ED1FF38A0D0FF43A5D1FF4FA9CFFF5FAD - CCFF71B0C6FF85B3BEFF8FAFB3FF8BA1A2FF7D8E8EFF6F7B7BFF626A6AFF585C - 5CFF515252FF4C4B4BFF4A4848FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF4C4A4AFF5D6465FFBAE5F8FFCBEC - FCFFCBECFCFFC2E1F0FF899697FF646B6BFF545555FF505151FF565959FF7083 - 87FFC1E8FAFFCBECFCFFCBECFCFFBBD8E5FF7A8484FF565858FF4A4848FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF454343D10000 - 0010000000030000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000083A3A338494747D74947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494848FF4B4A4AFF4E4E4EFF5355 - 55FF595D5DFF606767FF677171FF6F7B7BFF778585FF7D8E8EFF839595FF879B - 9BFF8A9F9FFF8CA1A1FF8CA2A2FF8BA0A0FF889C9CFF849696FF7E8F8FFF7886 - 86FF707D7DFF697272FF626969FF5B5F5FFF545656FF4F4F4FFF4C4A4AFF4A48 - 48FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF4A4848FF555858FF9ABECDFFCFED - FCFFCFEDFCFFCFEDFCFFB8D1DCFF869596FF6E7979FF697373FF788B8FFFB8DA - E7FFCFEDFCFFCFEDFCFFCFEDFCFFA9BBC2FF687171FF505151FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF212020590000 - 0007000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000A0D1D1046675 - 757B494747F7494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494848FF4B4949FF4C4B4BFF4F4E4EFF515252FF535555FF565858FF575B - 5BFF595D5DFF5A5E5EFF5A5E5EFF5A5D5DFF585B5BFF565959FF545656FF5152 - 52FF4F4F4FFF4C4C4CFF4B4A4AFF4A4848FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF4F4F4FFF68777CFFC2E5 - F4FFD4EFFCFFD4EFFCFFD4EFFCFFCEEAF8FFBCD9E4FFBCDCE8FFD0EDFBFFD4EF - FCFFD4EFFCFFD4EFFCFFC5DEEAFF7F8888FF5A5E5EFF4C4B4BFF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF424040B9000000090000 - 0001000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00006675751C4947479F494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF4A4848FF4A4848FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF4B4949FF535555FF7688 - 8EFFC6E5F3FFD8F1FDFFD8F1FDFFD8F1FDFFD8F1FDFFD8F1FDFFD8F1FDFFD8F1 - FDFFD8F1FDFFC8DFEBFF869394FF606767FF505050FF4A4848FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF484646EC10101025000000020000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000049474730494747AF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF4C4A4AFF5456 - 56FF687578FF9DB5BDFFC4E1EEFFD9F0FBFFDDF2FDFFDDF2FDFFD6EEF9FFC5DE - E9FFA3B6BBFF778283FF5F6565FF515252FF4B4949FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FB2C2B2B4600000002000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000004947472C4947479B494747F74947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4B4A - 4AFF505050FF585C5CFF626969FF697373FF6D7878FF6E7979FF6C7777FF6770 - 70FF606565FF565959FF4E4E4EFF4A4949FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FB323131580000000200000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000494747144947 - 4773494747D7494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF4B4A4AFF4E4D4DFF505050FF525353FF525353FF525252FF4F50 - 50FF4D4C4CFF4A4949FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF484646E732303042000000010000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000004947473049474787494747DB494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF464444A82322221500000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000004947472449474768494747A74947 - 47DF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FB484646B04846 - 4634000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000049474714494747444947476C4947478F494747AF494747C7494747DF4947 - 47EB494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747F3494747D3494747A34947476448464618000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFF007FFFFFFFFFFFFFFFFFFFFFFFFFFF800001FFFFFFFFFFFFFFFFFFF - FFFFFF80000001FFFFFFFFFFFFFFFFFFFFFFFC000000003FFFFFFFFFFFFFFFFF - FFFFF00000000007FFFFFFFFFFFFFFFFFFFF800000000001FFFFFFFFFFFFFFFF - FFFE0000000000007FFFFFFFFFFFFFFFFFF80000000000001FFFFFFFFFFFFFFF - FFF000000000000007FFFFFFFFFFFFFFFFC000000000000001FFFFFFFFFFFFFF - FF8000000000000000FFFFFFFFFFFFFFFE00000000000000007FFFFFFFFFFFFF - FC00000000000000001FFFFFFFFFFFFFF800000000000000000FFFFFFFFFFFFF - F0000000000000000007FFFFFFFFFFFFE0000000000000000003FFFFFFFFFFFF - C0000000000000000001FFFFFFFFFFFF80000000000000000000FFFFFFFFFFFF - 000000000000000000007FFFFFFFFFFE000000000000000000003FFFFFFFFFFC - 000000000000000000001FFFFFFFFFF8000000000000000000001FFFFFFFFFF8 - 000000000000000000000FFFFFFFFFF00000000000000000000007FFFFFFFFE0 - 0000000000000000000007FFFFFFFFE00000000000000000000003FFFFFFFFC0 - 0000000000000000000001FFFFFFFF800000000000000000000001FFFFFFFF80 - 0000000000000000000000FFFFFFFF000000000000000000000000FFFFFFFF00 - 00000000000000000000007FFFFFFE0000000000000000000000007FFFFFFE00 - 00000000000000000000003FFFFFFE0000000000000000000000003FFFFFFC00 - 00000000000000000000001FFFFFFC0000000000000000000000001FFFFFF800 - 00000000000000000000001FFFFFF80000000000000000000000000FFFFFF800 - 00000000000000000000000FFFFFF000000000000000000000000007FFFFF000 - 000000000000000000000007FFFFF000000000000000000000000007FFFFF000 - 000000000000000000000003FFFFE000000000000000000000000003FFFFE000 - 000000000000000000000001FFFFE000000000000000000000000001FFFFE000 - 000000000000000000000000FFFFE000000000000000000000000000FFFFE000 - 000000000000000000000000FFFFC0000000000000000000000000007FFFC000 - 0000000000000000000000007FFFC0000000000000000000000000003FFFC000 - 0000000000000000000000003FFFC0000000000000000000000000001FFFC000 - 0000000000000000000000001FFFC0000000000000000000000000001FFFC000 - 0000000000000000000000000FFFC0000000000000000000000000000FFFC000 - 00000000000000000000000007FFC00000000000000000000000000007FFE000 - 00000000000000000000000003FFE00000000000000000000000000003FFE000 - 00000000000000000000000003FFE00000000000000000000000000001FFE000 - 00000000000000000000000001FFE00000000000000000000000000000FFF000 - 00000000000000000000000000FFF00000000000000000000000000000FFF000 - 000000000000000000000000007FF000000000000000000000000000007FF800 - 000000000000000000000000003FF800000000000000000000000000003FF800 - 000000000000000000000000001FFC00000000000000000000000000001FFC00 - 000000000000000000000000001EFC00000000000000000000000000000EFE00 - 000000000000000000000000000EFE000000000000000000000000000006FE00 - 0000000000000000000000000006FF000000000000000000000000000002FF00 - 0000000000000000000000000002FF800000000000000000000000000002FFC0 - 0000000000000000000000000001FFC00000000000000000000000000001FFE0 - 0000000000000000000000000001FFE00000000000000000000000000000FFF0 - 0000000000000000000000000000FFF80000000000000000000000000000FFF8 - 0000000000000000000000000000FFFC0000000000000000000000000000FFFE - 0000000000000000000000000000FFFF0000000000000000000000000000FFFF - 8000000000000000000000000000FFFFC000000000000000000000000000FFFF - E000000000000000000000000000FFFFF000000000000000000000000000FFFF - F800000000000000000000000001FFFFFC00000000000000000000000001FFFF - FE00000000000000000000000001FFFFFF00000000000000000000000003FFFF - FFC0000000000000000000000007FFFFFFE0000000000000000000000007FFFF - FFF800000000000000000000000FFFFFFFFE00000000000000000000001FFFFF - FFFF80000000000000000000003FFFFFFFFFE0000000000000000000007FFFFF - FFFFFC00000000000000000001FFFFFFFFFFFF80000000000000000007FFFFFF - FFFFFFF800000000000000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFFFFFFFFFFFFFFFFFF2800000060000000C0000000010020000000 - 0000809400000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000009F9F9F019F9F - 9F019F9F9F010000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000010000 - 000300000006000000080000000B0000000E0000001000000011000000120000 - 00120000001200000011000000100000000D0000000A00000007000000050000 - 0002000000010000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000100000003000000070000000D000000140000 - 001B00000021000000280000002D000000320000003500000037000000370000 - 0037000000370000003700000034000000300000002C000000250000001F0000 - 0018000000100000000A00000005000000020000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000002000000070000000F00000019000000240000002F000000390000 - 0040000000460000004B0000004E000000500000005200000052000000530000 - 0053000000530000005200000051000000500000004D00000049000000440000 - 003D000000340000002A0000001E000000130000000A00000004000000010000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000025242401030303040000 - 000B0000001700000025000000330000004000000049030303530F0F0F711B1A - 1A8B292828A9302E2EC13D3B3BD4424040E1464444EF464444EF464444EF4644 - 44EF464444EF434141E53E3C3CD7323030C4292828AD1D1C1C900F0F0F750404 - 045B000000520000004C00000045000000390000002C0000001D000000100000 - 0007141313020000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000050505040000000D0000001A0000 - 002B0000003B01010149090909621F1E1E92343333C4413F3FE9474545F84947 - 47FE494747FF484646FE494747FF494747FF484646FE494747FF494747FF4846 - 46FE494747FF494747FF484646FE494747FF494747FF484646FE474545F94140 - 40EA353434C5201F1F960B0A0A6A010101540000004C00000041000000320000 - 0022000000130202020716161602000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000D0D0D020000000A000000190000002C0000003E0302 - 024E1D1C1C8C363535CB474545F6494747FF494747FF494747FF484646FE4947 - 47FF494747FF484646FE494747FF494747FF484646FE494747FF494747FF4846 - 46FE494747FF494747FF484646FE494747FF494747FF484646FE494747FF4947 - 47FF484646FE494747FF474545F6363535CB1B1B1B8C030303590000004F0000 - 0045000000350000002100000011000000062322220100000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00001B1A1A010000000700000015000000290000003D0A0A0A5F282626A64543 - 43EE484646FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE444242ED262525A60A0A - 0A680000005100000045000000330000001E0000000C03030303000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000606 - 06030000000D0000001F0000003608080857292828A6454343F1484646FE4846 - 46FE494747FF494747FF484646FE494747FF494747FF494747FF484646FE4947 - 47FF494747FF494747FE494747FF494747FF494747FE494747FF494747FF4947 - 47FE494747FF494747FF494747FE494747FF494747FF484646FE494747FF4947 - 47FF484646FE494747FF494747FF484646FE494747FF484646FE494747FF4442 - 42EF2A2929AB070707620000004E000000400000002A00000014030303062C31 - 3101000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000000B0F0F050000 - 0013000000290000004022212192424040E9484646FE484646FE484646FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE494747FE494747FE4A49 - 49FE4D4C4CFE505050FE535555FE565959FE595D5DFE5B5F5FFE5B5F5FFE5A5E - 5EFE585B5BFE555757FE515353FE4E4F4FFE4C4B4BFE4A4848FE494747FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE414040E91F1E1E940101015500000048000000340000001D0000 - 0009324343020000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000596B6B0100000008000000190000 - 0033101010663B3939D1494747FF494747FF484646FE494747FF494747FF4846 - 46FE494747FF494747FF494747FE4A4949FF4E4E4EFF565858FF616767FE6C78 - 78FF728689FF6F909AFE6796A6FF619AB0FF5D9DB7FE5B9EBAFF5A9FBBFF5A9D - B9FE5D9BB5FF6098ADFF6692A2FE6D8C95FF6F8184FF687171FE5C6161FF5354 - 54FF4C4C4CFE4A4848FF494747FF484646FE494747FF484646FE494747FF4947 - 47FF484646FE494747FF484646FE3A3838D30E0E0E6F0000004F0000003E0000 - 00240000000E1A23230300000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000073737301000000090000001D0201013A2121 - 2190454343F1484646FE494747FF494747FF484646FE494747FF494747FF4947 - 47FE4A4848FF4E4D4DFF575A5AFE666F6FFF71868AFF6B98A7FF529CBCFE3B9D - CAFF2D9BD1FF299CD6FE299DD9FF2A9FDBFF2CA0DCFE2DA1DCFF2EA1DCFF2DA1 - DCFE2BA0DBFF2A9EDAFF289DD8FE289BD5FF2B99CFFF3B9AC7FE5198B6FF6890 - 9EFF6B7D80FE606666FF535555FF4C4A4AFE494747FF494747FE494747FF4947 - 47FF484646FE494747FF494747FF484646FE444242F0201F1F95010101540000 - 00430000002A000000112B2B2B03000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000073737301000000090000001F04040442302F2FB44846 - 46FE484646FE484646FE484646FE484646FE484646FE494747FE4A4848FE4F4E - 4EFE5C6161FE717F80FE7099A6FE499DC3FE309CD1FE269BD7FE2BA0DBFE30A4 - DFFE32A6E1FE34A8E3FE36A9E4FE37AAE5FE38ABE6FE39ABE6FE39ABE6FE39AB - E6FE38ABE6FE37AAE5FE36A9E4FE34A8E2FE32A6E1FE30A3DEFE299FDBFE249A - D6FE2F99CDFE4998BAFE6C8F9AFE687272FE565959FE4C4B4BFE494747FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE484646FC2F2D2DB80404 - 0458000000460000002D00000012070707040000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000006B6B6B010000000A000000200B0B0B503B3A3AD2484646FE4947 - 47FF494747FF484646FE494747FF494747FF494848FE4F4F4FFF5E6363FF7386 - 89FE649FB5FF389ECEFF239AD7FE2CA1DDFF2FA4E0FF32A7E3FF35AAE6FE37AC - E8FF39AEEAFF3BAFEBFE3CB1ECFF3DB1EDFF3DB1EDFE3EB2EDFF3EB2EDFF3EB2 - EDFE3EB2EDFF3EB1ECFF3DB1ECFE3CB0EBFF3BAFEAFF39ADE8FE36AAE6FF33A8 - E3FF30A5E0FE2AA0DCFF1F98D6FF399AC8FE6294A6FF6A797BFE565959FF4C4B - 4BFF494747FE494747FF494747FF484646FE494747FF494747FF484646FE3A38 - 38D209090965000000490000002F0000001301131C0400000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000090000001F0C0C0C51403F3FE0494747FE484646FE4947 - 47FF494747FF484646FE494747FF4C4B4BFF575B5BFE708081FF679DB1FF359C - CDFE259CD9FF2BA1DEFF2FA6E2FE32A9E6FF35ACE9FF38AEEBFF39B0ECFE3BB1 - EEFF3CB2EFFF3DB3EFFE3DB4F0FF3EB4F0FF3EB4F0FE3FB4F0FF3FB5F1FF3FB4 - F1FE3FB5F1FF3FB4F0FF3FB4F0FE3EB3EFFF3EB3EFFF3DB2EDFE3BB1ECFF39AF - EBFF37ACE8FE34A9E6FF30A6E2FF2AA1DDFE239AD7FF3398C8FE6591A1FF6570 - 71FF525353FE4A4848FF494747FF484646FE494747FF494747FF484646FE4947 - 47FF3D3C3CDD0B0B0B6A000000480000002E00000012202B2B03000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000060000001B0C0C0C4F3F3E3EDD484646FE484646FE484646FE4846 - 46FE484646FE494747FE4F5050FE646B6BFE77979FFE409EC9FE239AD7FE28A0 - DDFE2CA5E3FE30A9E7FE33ACEAFE36AEECFE38B0EEFE39B1EFFE39B2F0FE3BB3 - F0FE3BB3F1FE3CB4F1FE3CB4F1FE3CB4F1FE3DB4F1FE3DB5F1FE3DB5F1FE3DB5 - F1FE3DB5F1FE3DB5F1FE3EB5F1FE3EB5F1FE3EB4F1FE3DB4F0FE3DB3F0FE3CB2 - EFFE3AB1EEFE38AFECFE36ADEAFE32A9E6FE2EA5E2FE29A0DDFE2098D4FE4297 - BEFE6E878CFE595D5DFE4C4B4BFE494747FE484646FE484646FE484646FE4846 - 46FE484646FE413F3FE60B0A0A6A000000470000002B0000000F202B2B020000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000000000000000000000080B - 0B04000000160C0C0C4B413F3FE0484646FE494747FF494747FF484646FE4947 - 47FF4A4949FF545757FE718182FF61A1BAFF2699D3FE259EDCFF29A3E1FF2DA8 - E6FE31ABEAFF33AEECFF35AFEEFE37B1EFFF37B2F0FF38B2F1FF38B3F1FE38B3 - F2FF39B3F2FF39B3F1FE39B3F2FF3AB3F2FF3AB3F1FE3AB4F2FF3AB4F2FF3AB4 - F1FE3AB4F2FF3BB4F2FF3BB4F1FE3BB4F2FF3BB4F2FF3BB4F1FE3BB4F1FF3BB4 - F1FF3AB3F0FE39B2F0FF39B1EEFF37AFECFE34ACEAFF30A9E6FE2BA4E1FF249D - DAFF2497D0FE6094A8FF646E6EFF4F4F4FFE494747FF494747FF484646FE4947 - 47FF494747FF484646FE3F3D3DE00A0A0A6900000045000000260000000C506B - 6B01000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000002C3B3B020000 - 0011050505373D3B3BD4494747FF484646FE494747FF494747FF494747FE4B4A - 4AFF5A5E5EFF778C8FFE49A0C6FF219AD7FF259FDEFE29A5E4FF2CA9E9FF2FAC - ECFE31AEEEFF33AFEFFF33B0F0FE34B1F1FF35B1F1FF35B2F2FF35B2F1FE36B2 - F2FF36B2F2FF36B2F1FE37B2F2FF37B2F2FF37B2F1FE37B3F2FF37B3F2FF37B2 - F1FE38B3F2FF38B3F2FF38B3F1FE38B3F2FF38B3F2FF38B3F1FE38B3F2FF39B3 - F2FF38B3F1FE38B3F1FF38B2F0FF38B1EFFE36B0EEFF34AEECFE30AAE9FF2CA6 - E4FF27A0DEFE1E97D4FF4C97B8FF6A797BFE515252FF4A4848FF494747FE4947 - 47FF494747FF484646FE494747FF3C3A3AD7070707600000003F000000200000 - 0008000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000000000000B0202 - 022A333131B6484646FE484646FE484646FE484646FE494747FE4B4A4AFE5D61 - 61FE79959BFE3B9DCBFE1F9AD8FE24A0E0FE28A6E6FE2AAAEAFE2DACEDFE2FAE - EFFE30AFF0FE30AFF0FE31B0F0FE31B0F0FE31B0F0FE32B0F1FE32B0F1FE32B0 - F1FE32B0F1FE33B1F1FE33B1F1FE33B1F1FE33B1F1FE34B1F1FE34B1F1FE34B1 - F1FE34B1F1FE35B1F1FE35B1F1FE35B1F1FE35B1F1FE35B2F1FE36B2F1FE36B2 - F1FE36B2F1FE36B2F1FE36B2F1FE36B2F1FE35B1F0FE34B0EFFE32AEEDFE2FAB - EAFE2BA7E6FE27A1E0FE1E98D7FE3B97C2FE6E7F81FE535555FE4A4848FE4846 - 46FE484646FE484646FE484646FE484646FE353434C801010152000000380000 - 0018040404040000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000050000001C2726 - 268E494747FF484646FE494747FF484646FE494747FF4B4A4AFF5D6363FE789B - A4FF2F9BCFFF1E9ADAFE22A1E2FF26A6E8FF28A9EBFE2AACEDFF2BADEFFF2CAE - F0FE2DAFF1FF2DAFF1FF2DAFF0FE2DAFF1FF2EAFF1FF2EAFF1FF2EAFF0FE2FAF - F1FF2FAFF1FF2FAFF0FE2FAFF1FF2FAFF1FF30AFF0FE30B0F1FF30B0F1FF30B0 - F0FE31B0F1FF31B0F1FF31B0F0FE31B0F1FF31B0F1FF32B0F0FE32B0F1FF32B0 - F1FF32B0F1FE32B0F1FF33B1F1FF33B0F1FE33B1F1FF32B0F0FE32AFF0FF30AE - EEFF2EABEBFE2AA7E7FF26A2E1FF1E99D9FE3197C7FF6C8489FF545656FE4A48 - 48FF494747FF484646FE494747FF494747FF484646FE292828A90000004D0000 - 00300000000F1312120200000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000002B373702000000111616165E4644 - 44F4494747FF484646FE494747FF494747FE4B4A4AFF5C6161FF78989FFE2D9B - CFFF1C9ADAFF20A0E2FE24A6E8FF26A9EBFF27ABEEFE28ACEFFF29ADF0FF29AD - F0FE29ADF1FF2AADF1FF2AADF0FE2AAEF1FF2AAEF1FF2BAEF1FF2AAEF0FE2BAE - F1FF2BAEF1FF2BAEF0FE2CAEF1FF2CAEF1FF2CAEF0FE2CAFF1FF2DAFF1FF2DAE - F0FE2DAFF1FF2DAFF1FF2EAFF0FE2EAFF1FF2EAFF1FF2EAFF0FE2EAFF1FF2FAF - F1FF2FAFF0FE2FAFF1FF2FB0F1FF2FAFF0FE30B0F1FF30AFF0FE2FAFF0FF2FAE - F0FF2EADEEFE2BABECFF28A7E8FF24A1E2FE1C99D9FF3296C6FF6B8287FE5253 - 53FF494747FF484646FE494747FF494747FF484646FE474545F8181717830000 - 0044000000220101010800000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000008050505283F3E3EDB4846 - 46FE484646FE484646FE484646FE4A4848FE575A5AFE799397FE359CCDFE1A99 - D9FE1D9FE1FE21A4E8FE23A8ECFE25AAEEFE25ABEFFE26ACF0FE26ACF0FE26AC - F0FE27ACF0FE27ACF0FE27ACF0FE27ACF0FE27ACF0FE28ACF0FE28ACF0FE28AC - F0FE28ADF0FE28ADF0FE28ADF0FE28ADF0FE28ADF0FE29ADF0FE29ADF0FE29AD - F0FE29ADF0FE29ADF0FE2AADF0FE2AADF0FE2AAEF0FE2AAEF0FE2BAEF0FE2BAE - F0FE2BAEF0FE2BAEF0FE2CAEF0FE2CAEF0FE2CAEF0FE2CAEF0FE2CAEF0FE2CAE - F0FE2CADEFFE2BACEEFE29AAECFE26A6E8FE22A0E1FE1B98D9FE3897C4FE6C79 - 7BFE505050FE494747FE484646FE484646FE484646FE484646FE403E3EE30706 - 065D000000370000001606060603000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000A090903000000172B2A2A98494747FF4947 - 47FF494747FF484646FE494747FF525454FE778B8DFF43A0CAFF1797D8FE1A9E - E1FF1DA3E8FF20A7EBFE21A9EEFF22AAEFFF23AAEFFE23ABF0FF23ABF0FF23AB - F0FE24ABF0FF24ABF0FF24ABF0FE24ABF0FF24ABF0FF25ABF0FF25ABF0FE25AB - F0FF25ABF0FF25ABF0FE26ACF1FF26ACF1FF26ACF0FE26ACF1FF26ACF1FF27AC - F0FE27ACF1FF27ACF1FF27ACF0FE27ACF1FF27ACF1FF28ACF0FE28ACF1FF28AC - F1FF457995FE3C8CB5FF2EA4E1FF28ADF0FE29ADF1FF29ADF0FE29ADF1FF29AD - F1FF29ADF0FE29ACF0FF28ABEEFF27A9EBFE23A5E7FF1F9FE1FF1896D7FE4798 - BBFF667172FF4D4D4DFE494747FF494747FF484646FE494747FF494747FF302E - 2EB800000049000000290000000B000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000A11111148464444F2494747FF4947 - 47FF494747FF494747FE4E4E4EFF6D7878FE59A4C3FF1696D6FF189CDFFE1BA2 - E7FF1DA5EBFF1EA7EDFE1FA8EFFF238BBFFF2F7295FE377B9EFF3B7FA1FF3C7F - A2FE3C7FA2FF3C7FA2FF3C7FA2FE2A9AD3FF21AAF0FF21AAF0FF22AAEFFE22AA - F0FF22AAF0FF22AAEFFE22ABF0FF22ABF0FF23AAF0FE23ABF0FF23ABF0FF23AB - F0FE23ABF0FF24ABF0FF24ABF0FE24ABF0FF24ABF0FF24ABF0FE25ABF0FF2F98 - CEFF585757FE5A5859FF565F63FF48768DFE3692C2FF29A6E7FE26ACF1FF26AC - F1FF27ACF0FE27ACF1FF26ABF0FF25AAEEFE24A8EBFF20A3E6FF1C9DDEFE1795 - D4FF5A94ACFF5D6363FE4A4949FF494747FF484646FE494747FF494747FF4846 - 46FB121212740000003C00000019090808030000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000200000016353434B6484646FE484646FE4846 - 46FE484646FE4B4949FE5F6565FE75A2AFFE1794D3FE1599DCFE179FE4FE1AA4 - EAFE1BA6EDFE1CA7EEFE1CA8EFFE1F92CDFE33393DFE474646FE525050FE5453 - 53FE545353FE545353FE545353FE44677AFE1FA6EBFE1EA9EFFE1EA9EFFE1EA9 - EFFE1FA9EFFE1FA9EFFE1FA9EFFE1FA9EFFE1FA9EFFE20A9EFFE20A9EFFE20A9 - EFFE20AAEFFE20AAEFFE21AAEFFE21AAEFFE21AAEFFE21AAEFFE22AAEFFE3F73 - 8EFE575656FE585656FE585656FE585656FE585757FE52616AFE417C9BFE2E9A - D1FE23ABF0FE23ABF0FE23ABF0FE23AAEFFE22A9EDFE21A6EAFE1DA1E5FE199A - DCFE1E94CFFE6B8B94FE535454FE494747FE484646FE484646FE484646FE4846 - 46FE383636CE0202024E0000002A0000000A0000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000819181859484646F9484646FE494747FF4947 - 47FF494747FF545656FE799295FF309CCFFE1397DAFF159DE3FF17A2E9FE18A5 - EDFF19A6EFFF19A7EFFE19A7F0FF1AA7EFFF236282FE3A3939FF4B4949FF514F - 4FFE535151FF535151FF535151FE515051FF2D88B7FF1BA8F0FF1CA8EFFE1CA8 - F0FF1CA8F0FF1CA8EFFE1CA8F0FF1CA8F0FF1DA8EFFE1DA8F0FF1DA8F0FF1DA8 - EFFE1DA8F0FF1DA8F0FF1EA8EFFE1EA9F0FF1EA9F0FF1EA8EFFE239EDDFF4E57 - 5CFF565454FE565454FF565454FF565454FE565454FF565454FE565454FF5755 - 55FF4E626EFE3A82A7FF299CD7FF21A9EFFE20A9EEFF1FA7ECFF1DA4E9FE1A9F - E2FF1697D9FF3698C6FE697576FF4D4D4DFF494747FE494747FF494747FF4846 - 46FE484646FE1A1919840000003B000000151312120200000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000002000000123B3939BE494747FF484646FE494747FF4947 - 47FF4C4B4BFF6B7575FE5BA4C1FF1193D6FE139AE0FF15A0E7FF16A3ECFE16A5 - EEFF16A6EFFF16A6EFFE17A6F0FF17A6F0FF189CE0FE2C363BFF413F3FFF4D4B - 4BFE504E4EFF514F4FFF514F4FFE514F4FFF465B67FF1CA1E5FF19A7EFFE19A7 - F0FF19A7F0FF19A7EFFE19A7F0FF19A7F0FF1AA7EFFE1AA7F0FF1AA7F0FF1AA7 - EFFE1AA7F0FF1AA8F0FF1BA8EFFE1BA8F0FF1BA8F0FF1BA8EFFE317FA7FF5250 - 50FF535252FE545252FF545252FF535252FE545252FF545252FE545353FF5453 - 53FF545252FE545353FF505559FF3D5F71FE2488BBFF1DA7EEFF1CA6EBFE1AA1 - E7FF169BDFFF1293D4FE5D94AAFF5A5E5EFF4A4848FE494747FF494747FF4846 - 46FE494747FF393737D00101014A000000240101010800000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000611111142484646FC494747FF484646FE494747FF4947 - 47FF565959FF7C9CA3FE1F96D1FF1096DBFE129DE4FF13A1EAFF14A4EDFE14A5 - EEFF14A5EFFF15A5EFFE15A6EFFF15A6EFFF15A5EFFE1D6B92FF343333FF4644 - 44FE4E4C4CFF4F4D4DFF4F4D4DFE4F4D4DFF4E4D4DFF2F7BA2FF16A6EFFE17A6 - F0FF17A6F0FF17A6EFFE17A6F0FF17A6F0FF17A6EFFE17A6F0FF17A7F0FF17A6 - EFFE17A7F0FF18A7F0FF18A7EFFE18A7F0FF18A7F0FF19A4EBFE435C69FF514F - 4FFF525050FE525050FF525050FF525050FE525050FF525050FE525050FF5250 - 50FF525050FE525050FF4E4C4CFF3E3D3DFE23749DFF1AA7EFFF1AA6EDFE19A3 - EAFF169FE4FF1497DBFE2795CBFF6B7E82FF4E4E4EFE494747FF494747FF4846 - 46FE494747FF474545F914131375000000320000001022212101000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000D343232A5484646FE484646FE484646FE494747FE4D4C - 4CFE6C7777FE53A5C7FE0E93D6FE0F9AE0FE119FE7FE12A2ECFE12A3EEFE12A4 - EEFE13A4EEFE13A4EEFE13A4EEFE13A4EEFE13A4EEFE149DE4FE253C49FE3B39 - 39FE494747FE4D4B4BFE4D4B4BFE4D4B4BFE4D4B4BFE494E52FE1A9BDDFE15A5 - EFFE15A5EFFE15A5EFFE15A5EFFE15A5EFFE15A5EFFE16A5EFFE16A5EFFE16A5 - EFFE16A5EFFE16A5EFFE16A5EFFE16A6EFFE16A6EFFE248BC0FE4C4D4EFE4F4D - 4DFE4F4D4DFE4F4D4DFE4F4D4DFE4E4C4CFE4C4A4AFE4D4B4BFE4F4D4DFE504E - 4EFE514F4FFE504E4EFE464545FE32383CFE19A0E5FE18A6EFFE18A6EEFE17A4 - ECFE16A0E8FE139AE0FE0F92D5FE5696B1FE5C6161FE494747FE484646FE4846 - 46FE484646FE484646FE313030BB000000410000001C00000005000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000209090928464444EA494747FF494747FF484646FE494747FF5658 - 58FF809CA1FF1A94D1FE0E96DBFF0E9CE4FE10A0EAFF10A2EDFF10A3EEFE11A4 - EFFF11A4EFFF11A4EEFE11A4EFFF11A4EFFF11A4EEFE11A4EFFF1777A8FF2D2D - 2EFE413F3FFF4B4949FF4C4A4AFE4C4A4AFF4C4A4AFF4C4A4AFF336C89FE13A4 - EDFF13A4EFFF13A4EEFE13A5EFFF13A5EFFF13A5EEFE13A5EFFF13A5EFFF13A5 - EEFE14A5EFFF14A5EFFF14A5EFFE14A5EFFF14A5EFFF36667FFE4D4B4BFF4E4C - 4CFF4E4C4CFE4E4C4CFF4D4B4BFF474545FE3E3C3CFF3D3B3BFE434242FF4947 - 47FF4C4A4AFE4B4949FF3D3C3CFF235C79FE16A6EFFF16A6EFFF16A5EFFE15A4 - EDFF14A1EAFF129DE4FE0F96DAFF2695CBFF6C7E81FE4D4C4CFF494747FF4846 - 46FE494747FF494747FF474545F5050505520000002B0000000C000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000005201F1F68484646FE494747FF494747FF484646FE4B4A4AFF676F - 6FFF60A6C1FF0C91D6FE0D98E0FF0E9EE7FE0FA1ECFF0FA2EEFF0FA3EEFE0FA3 - EFFF0FA3EFFF0FA3EEFE10A4EFFF10A4EFFF10A3EEFE10A4EFFF109FE8FF1F42 - 54FE373535FF454343FF4A4848FE4A4848FF4A4848FF4A4848FF474A4DFE1C90 - CCFF11A4EFFF11A3EEFE11A4EFFF11A4EFFF11A4EEFE11A4EFFF11A4EFFF11A4 - EEFE11A4EFFF12A4EFFF12A4EEFE12A4EFFF169BDFFF474A4CFE4C4A4AFF4C4A - 4AFF4C4A4AFE4C4A4AFF4A4848FF3D3B3BFE2C2A2AFF272626FE2D2C2CFF3635 - 35FF3E3C3CFE3F3D3DFF313335FF1887BFFE14A5EFFF14A5EFFF14A5EEFE13A4 - EEFF12A2EBFF109EE7FE0E98DEFF0F91D4FF6094A9FE565959FF494747FF4846 - 46FE494747FF494747FF484646FE1E1D1D8E0000003B00000017121111020000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000A3B3939B8484646FE484646FE484646FE494747FE515151FE7A8F - 91FE2D9BCFFE0C95DAFE0D9BE3FE0D9FE9FE0EA1EDFE0EA2EEFE0EA2EEFE0EA2 - EEFE0EA2EEFE0EA2EEFE0EA2EEFE0EA2EEFE0EA2EEFE0EA2EEFE0EA2EEFE1283 - BDFE2A292AFE3D3C3CFE484646FE494747FE494747FE494747FE494747FE385E - 72FE10A1EBFE0FA3EEFE0FA3EEFE0FA3EEFE0FA3EEFE0FA3EEFE0FA3EEFE10A3 - EEFE10A3EEFE10A3EEFE10A3EEFE10A3EEFE28769EFE494747FE4A4848FE4A48 - 48FE4A4848FE4A4848FE444242FE313132FE186A93FE174A64FE1C2428FE2120 - 20FE272626FE292828FE203F50FE12A2ECFE12A4EEFE12A4EEFE12A4EEFE11A3 - EEFE10A2EDFE0F9FE9FE0E9AE2FE0D94D9FE3698C6FE666F6FFE4B4A4AFE4846 - 46FE484646FE484646FE484646FE3B3939D70202024C00000026000000080000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000C0C0C22464444EA484646FE494747FF494747FF494747FE5B5F5FFF77A4 - B1FF1092D3FF0C97DEFE0D9DE6FF0DA0EBFE0EA2EEFF0EA3EFFF0EA2EEFE0EA3 - EFFF0EA3EFFF0EA2EEFE0EA3EFFF0EA3EFFF0EA2EEFE0EA3EFFF0EA3EFFF0EA2 - EEFE1B4A62FF323131FF434141FE494747FF494747FF494747FF494747FE4748 - 49FF2183B5FF0EA2EEFE0FA3EFFF0FA3EFFF0FA3EEFE0FA3EFFF0FA3EFFF0FA3 - EEFE0FA3EFFF0FA3EFFF0FA3EEFE119FE7FF3B5461FF494747FE4A4848FF4A48 - 48FF4A4848FE484646FF3E3C3CFF254150FE109FE7FF10A3EDFE1192D4FF1461 - 88FF192F3BFE1B1C1DFF146E9CFF10A3EEFE10A4EFFF10A4EFFF10A3EEFE10A3 - EFFF0FA2EEFF0FA0EBFE0D9CE5FF0D96DCFF1291D1FE70898FFF505050FF4947 - 47FE494747FF494747FF484646FE484646FC1514147700000036000000121616 - 1602000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000219191951484646FC484646FE494747FF494747FF4A4949FE6A7373FF5AA6 - C5FF0C92D6FF0C99E1FE0D9EE8FF0DA1ECFE0EA2EEFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2 - EEFE108AC8FF262C30FF3A3939FE464444FF484646FF494747FF484646FE4846 - 46FF3E525DFF0FA0EAFE0EA3EFFF0EA3EFFF0EA2EEFE0EA3EFFF0EA3EFFF0EA2 - EEFE0EA3EFFF0EA3EFFF0EA2EEFE1B8AC4FF474647FF494747FE4A4848FF4A48 - 48FF494747FE454343FF363434FF196891FE0FA3EFFF0EA2EEFE0FA3EFFF0FA3 - EFFF0F9EE7FE117BB2FF0F9AE1FF0FA3EEFE0FA3EFFF0FA3EFFF0FA3EEFE0FA3 - EFFF0EA2EEFF0EA1ECFE0D9EE7FF0D98E0FF0C91D5FE5C96ACFF585C5CFF4947 - 47FE494747FF494747FF484646FE494747FF323131BF000000440000001F0505 - 0506000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00032B2A2A8B484646FE484646FE484646FE494747FE4E4E4EFE7B8D8EFE309B - CEFE0C94DAFE0D9BE4FE0D9FEAFE0DA1EDFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE18597BFE2F2E2EFE424040FE484646FE484646FE484646FE4846 - 46FE484646FE2777A0FE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA2EEFE0DA2EEFE30637DFE484646FE484646FE484646FE4846 - 46FE484646FE3F3E3EFE2B2D2FFE0F97DCFE0EA2EEFE0EA2EEFE0EA2EEFE0EA2 - EEFE0EA2EEFE0EA2EEFE0EA2EEFE0EA2EEFE0EA2EEFE0EA2EEFE0EA2EEFE0EA2 - EEFE0DA2EEFE0DA1EDFE0D9FE9FE0D9AE3FE0C94D9FE3B97C2FE646D6DFE4A48 - 48FE484646FE484646FE484646FE484646FE454343F40D0C0C65000000300000 - 000F252424010000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00063F3E3EBB494747FF484646FE494747FF494747FF545656FE7E9FA6FF1994 - D2FF0D96DDFF0D9CE5FE0EA0EBFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2 - EEFE0EA3EFFF0F93D7FF233037FE393737FF454444FF484646FF484646FE4947 - 47FF494747FF414E55FE1497DBFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2 - EEFE0EA3EFFF0EA3EFFF1397DBFE414B50FF484646FF484646FE494747FF4947 - 47FF464444FE393737FF1F4D65FF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0EA3 - EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA0EAFF0D9CE4FF0C95DBFE2295CDFF6C7E82FF4C4C - 4CFE494747FF494747FF484646FE494747FF494747FE282727A60000003F0000 - 001B030303040000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0008474545E4494747FF484646FE494747FF494747FF5B6060FE74A7B7FF0F92 - D4FF0D98DFFF0D9EE7FE0EA1ECFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2 - EEFE0EA3EFFF0EA3EFFF16658DFE2E2D2DFF403E3EFF484646FF484646FE4947 - 47FF494747FF484646FE2E6B8BFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2 - EEFE0EA3EFFF0EA3EFFF237AA7FE474545FF494747FF484646FE494747FF4846 - 46FF434141FE313131FF147AAEFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0EA3 - EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA1EBFF0D9DE6FF0C97DDFE1292D2FF6C8C96FF5051 - 51FE494747FF494747FF484646FE494747FF494747FF444242EB0302024E0000 - 002A0000000B0000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000D0D - 0D16484646FE484646FE484646FE484646FE4A4848FE646B6BFE64A9C3FE0C92 - D6FE0C99E1FE0D9EE8FE0DA1EDFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA2EEFE0E9EE7FE21333CFE363535FE454343FE484646FE4846 - 46FE484646FE484646FE45494CFE198ECAFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0EA2EEFE395463FE484646FE484646FE484646FE484646FE4745 - 45FE3D3B3BFE263944FE0E9CE5FE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA2EEFE0DA1ECFE0D9DE7FE0C98E0FE0C91D4FE6395A8FE5557 - 57FE484646FE484646FE484646FE484646FE484646FE484646FE1F1E1E8E0000 - 003A000000160D0D0D0200000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000001818 - 1834494747FF494747FF484646FE494747FF4B4A4AFF6C7777FE51A7CBFF0C93 - D8FF0D9AE2FF0D9FE9FE0EA1EDFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2 - EEFE0EA3EFFF0EA3EFFF0DA2EEFE1472A2FF2B2B2CFF3E3D3DFF474545FE4947 - 47FF494747FF484646FE484646FF365E73FF0EA2EDFE0EA3EFFF0EA3EFFF0DA2 - EEFE0EA3EFFF1790CEFF454445FE484646FF494747FF484646FE484646FF4543 - 43FF363434FE1A5F83FF0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0EA3 - EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA1EDFF0D9EE8FF0C99E1FE0C92D6FF5497B4FF5A5F - 5FFE494747FF494747FF484646FE494747FF494747FF484646FE3A3838D20202 - 024B000000250000000800000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000001A19 - 194B494747FF494747FF484646FE494747FF4D4C4CFF748181FE40A3CFFF0C94 - D9FF0D9BE3FF0D9FE9FE0EA2EDFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2 - EEFE0EA3EFFF0EA3EFFF0DA2EEFE0E9EE8FF1E3D4EFF343333FF444242FE4846 - 46FF494747FF484646FE494747FF474546FF1D87BDFE0EA3EFFF0EA3EFFF0DA2 - EEFE0EA3EFFF2A6C8FFF484646FE494747FF494747FF484646FE484646FF413F - 3FFF2D2F30FE118BCAFF0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0EA3 - EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA1EDFF0D9FE9FF0D9AE2FE0C93D8FF4798BCFF5F66 - 66FE494747FF494747FF484646FE494747FF494747FF484646FE484646FB1312 - 127300000035000000111A191901000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000001B1A - 1A60484646FE484646FE484646FE484646FE4E4E4EFE7A8A8AFE349FD1FE0C95 - DAFE0D9BE4FE0D9FEAFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE1280B9FE282A2BFE3D3B3BFE4745 - 45FE484646FE484646FE484646FE484646FE3C5563FE109DE5FE0DA2EEFE0DA2 - EEFE109DE4FE3C4F59FE484646FE484646FE484646FE484646FE464444FE3A39 - 39FE21465AFE0EA0EBFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA2EEFE0DA2EEFE0D9FE9FE0D9AE3FE0C94D9FE3E99C3FE646C - 6CFE494747FE484646FE484646FE484646FE484646FE484646FE484646FE312F - 2FBD000000440000001F03030306000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000001B1A - 1A64494747FF494747FF484646FE494747FF4F4F4FFF7F9090FE2A9BD2FF0C95 - DBFF0D9BE5FF0DA0EAFE0EA2EEFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2 - EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA0EBFF1B4B63FF323131FE4341 - 41FF484646FF484646FE494747FF494747FF484646FE2679A4FF0EA3EFFF0DA2 - EEFE1B87BFFF454444FF484646FE494747FF494747FF484646FE434242FF3331 - 31FF1672A1FE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0EA3 - EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA2EEFF0E9FEAFF0D9BE4FE0C94D9FF3799C6FF6771 - 71FE4A4848FF494747FF484646FE494747FF494747FF484646FE494747FF4543 - 43F20C0C0C630000002F0000000E292727010000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000001B1A - 1A64494747FF494747FF484646FE494747FF505050FF819393FE279AD1FF0C95 - DBFF0D9CE5FF0DA0EAFE0EA2EEFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2 - EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF108CCCFF27282AFE3B39 - 39FF464444FF484646FE494747FF494747FF484646FE414E56FF1399DDFF0DA2 - EEFE2B6A8BFF474545FF484646FE494747FF494747FF484646FE3E3D3DFF2930 - 34FF0E9CE4FE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0EA3 - EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA2EEFF0E9FEAFF0D9BE4FE0C94D9FF3498C7FF6973 - 73FE4A4848FF494747FF484646FE494747FF494747FF484646FE494747FF4947 - 47FF262525A20000003E0000001A060606040000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000001B1A - 1A64484646FE484646FE484646FE484646FE505050FE819393FE289AD1FE0C95 - DBFE0D9BE5FE0DA0EAFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE185878FE302E - 2EFE414040FE484646FE484646FE484646FE484646FE484646FE2F6B8BFE0FA0 - E9FE3E515CFE484646FE484646FE484646FE484646FE454343FE373636FE1C56 - 74FE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA2EEFE0DA2EEFE0D9FEAFE0D9BE4FE0C94D9FE3599C7FE6973 - 73FE4A4848FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE444242EA0202024E0000002A0000000B0000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000001B1A - 1A63494747FF494747FF484646FE494747FF4F4F4FFF7F9090FE2D9DD2FF0C95 - DBFF0D9BE4FF0DA0EAFE0EA2EEFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2 - EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0EA3EFFF0F92D4FE242F - 36FF393737FF464444FE484646FF494747FF484646FE494747FF46494CFF2381 - B1FE46494BFF494747FF484646FE494747FF484646FF424040FE2F3032FF1382 - BCFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0EA3 - EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA2EEFF0E9FEAFF0D9BE3FE0C94D9FF3999C6FF6770 - 70FE4A4848FF494747FF484646FE494747FF494747FF484646FE494747FF4947 - 47FF484646FE1B1B1B880000003A000000161312120200000000000000000000 - 0000000000000000000000000000000000000000000000000000000000001B1A - 1A5E494747FF494747FF484646FE494747FF4E4E4EFF7A8989FE38A0D1FF0C95 - DAFF0D9BE4FF0D9FEAFE0EA2EEFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2 - EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0EA3EFFF0DA2EEFE1662 - 89FF2E2C2CFF413F3FFE484646FF494747FF484646FE494747FF494747FF454B - 4FFE494747FF494747FF484646FE494747FF474545FF3B3A3AFE243D4AFF0E9F - EAFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0EA3 - EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA2EDFF0E9FE9FF0D9AE3FE0C93D9FF419AC2FF646C - 6CFE494747FF494747FF484646FE494747FF494747FF484646FE494747FF4947 - 47FF484646FE393737CF0202024A000000240000000700000000000000000000 - 0000000000000000000000000000000000000000000000000000000000001A1A - 1A48484646FE484646FE484646FE484646FE4C4C4CFE738080FE47A5CFFE0C94 - D9FE0C9AE3FE0D9FE9FE0DA1EDFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0FA3EFFE149B - E1FE293D48FE414040FE504E4EFE555353FE565454FE575555FE575555FE5654 - 54FE565454FE555353FE535151FE514F4FFE4B4949FE373636FE196B94FE0DA2 - EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA2EEFE0DA1EDFE0D9FE8FE0C9AE2FE0C93D7FE4D9ABBFE5F65 - 65FE494747FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE484646FB1212127200000035000000111D1C1C01000000000000 - 0000000000000000000000000000000000000000000000000000000000001A19 - 1931494747FF494747FF484646FE494747FF4B4A4AFF6B7575FE59A9CAFF0C93 - D7FF0D99E2FF0D9EE9FE0EA1EDFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2 - EEFE0EA3EFFF0EA3EFFF0EA3EEFE10A4EFFF17A6EFFF1FA9F0FF24ABF0FE25AB - F0FF2B7FAAFF413F3FFE515050FF595858FF5B5959FE5B5959FF5B5959FF5B59 - 59FE5B5959FF5B5959FF5B5959FE5A5858FF535151FF3F4549FE269BD8FF1EA9 - F0FF16A6EFFE10A3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0EA3 - EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA1ECFF0D9EE8FF0C99E1FE0C92D6FF5C9AB2FF5A5E - 5EFE494747FF494747FF484646FE494747FF494747FF484646FE494747FF4947 - 47FF484646FE494747FF302E2EB9000000430000001E04040405000000000000 - 0000000000000000000000000000000000000000000000000000000000000F0F - 0F0F494747FF494747FF484646FE494747FF4A4848FF626A6AFE6CACC3FF0C92 - D6FF0D98E0FF0D9EE8FE0EA1ECFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2 - EEFE0EA3EFFF12A4EFFF1FA9F0FE28ADF0FF2BAEF1FF2BAEF1FF2BAEF0FE2BAE - F1FF2BACEEFF3A525FFE4E4C4CFF5B5959FF5F5D5DFE5F5D5DFF5F5D5DFF5F5D - 5DFE5F5D5DFF5F5D5DFF5F5D5DFE5D5B5BFF525050FF3A6378FE2BADEFFF2BAE - F1FF2BAEF0FE27ACF0FF1EA9F0FF11A4EFFE0EA3EFFF0DA2EEFE0EA3EFFF0EA3 - EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA1ECFF0D9DE7FF0C98DFFE0D91D4FF6A96A5FF5456 - 56FE494747FF494747FF484646FE494747FF494747FF484646FE494747FF4947 - 47FF484646FE494747FF444242F00A09095F0000002E0000000D222121010000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0001484646E6484646FE484646FE484646FE494747FE5A5E5EFE7CA9B6FE1292 - D3FE0C97DEFE0D9DE7FE0DA0EBFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE11A4 - EFFE22AAF0FE2FAFF1FE30B0F1FE30B0F1FE30B0F1FE30B0F1FE30B0F1FE30B0 - F1FE30B0F1FE3490BFFE484A4CFE585757FE626060FE636161FE636161FE6361 - 61FE636161FE636161FE636161FE5E5C5CFE4F4E4EFE368EBCFE30B0F1FE30B0 - F1FE30B0F1FE30B0F1FE30B0F1FE2EAFF1FE20A9F0FE10A3EFFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA2EEFE0DA0EBFE0D9CE6FE0C96DDFE1793D1FE708C92FE4F50 - 50FE484646FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE484646FE484646FE252424A00000003E0000001A0A0909040000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000444242BA494747FF484646FE494747FF494747FF535454FE84A0A3FF2097 - D1FF0D96DCFF0D9CE5FE0EA0EAFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF1AA7EFFF30B0 - F1FE37B2F2FF37B2F2FF36B2F1FE37B2F2FF37B2F2FF37B2F2FF36B2F1FE37B2 - F2FF37B2F2FF37B1EFFE42687BFF555454FF636161FE676565FF676666FF6766 - 66FE676666FF676666FF666464FE5E5C5CFF4B575DFF37B0EEFE37B2F2FF37B2 - F2FF36B2F1FE37B2F2FF37B2F2FF36B2F1FE36B2F2FF2FAFF1FE17A6EFFF0EA3 - EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EDFE0E9FEAFF0D9BE4FF0C95DAFE2B97CBFF6E7D7FFF4C4B - 4BFE494747FF494747FF484646FE494747FF494747FF484646FE494747FF4947 - 47FF484646FE494747FF494747FF424040E70101014D000000290000000A0000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00002D2B2B86484646FE484646FE484646FE494747FE4D4D4DFE7A8B8BFE40A2 - CEFE0C94D9FE0D9AE3FE0D9FE9FE0DA1EDFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE22AAF0FE3AB4F1FE3CB5 - F1FE3CB5F1FE3CB5F1FE3CB5F1FE3CB5F1FE3CB5F1FE3CB5F1FE3CB5F1FE3CB5 - F1FE3CB5F1FE3CB5F1FE3F9FCFFE535759FE656363FE6B6A6AFE6C6A6AFE6C6A - 6AFE6C6A6AFE6C6A6AFE696868FE5D5C5CFE477E9AFE3CB5F1FE3CB5F1FE3CB5 - F1FE3CB5F1FE3CB5F1FE3CB5F1FE3CB5F1FE3CB5F1FE3CB5F1FE39B3F1FE1EA9 - EFFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA1EDFE0D9EE8FE0D9AE2FE0C93D7FE4A9BBFFE636B6BFE4A48 - 48FE484646FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE484646FE484646FE484646FE1A19198300000038000000150000 - 0002000000000000000000000000000000000000000000000000000000000000 - 00001C1B1B46494747FD484646FE494747FF494747FF4A4949FE677070FF6BAC - C3FF0C91D5FF0C98E0FE0D9EE7FF0DA1ECFE0EA2EEFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF26ACF0FE42B7F2FF43B7F2FF43B7 - F2FE43B7F2FF43B7F2FF43B7F2FE43B7F2FF43B7F2FF43B7F2FF43B7F2FE43B7 - F2FF43B7F2FF43B7F2FE43B6F1FF528099FF6A6868FE706F6FFF716F6FFF716F - 6FFE716F6FFF716F6FFF6B6969FE5B5F61FF46A5D5FF43B7F2FE43B7F2FF43B7 - F2FF43B7F2FE43B7F2FF43B7F2FF43B7F2FE43B7F2FF43B7F2FE43B7F2FF41B6 - F2FF21AAF0FE0EA3EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA2EEFF0DA0EBFE0D9DE7FF0D97DEFF0C90D4FE6C99A9FF575959FF4947 - 47FE494747FF494747FF484646FE494747FF494747FF484646FE494747FF4947 - 47FF484646FE494747FF494747FF484646FE383737CE02010149000000240000 - 0007000000000000000000000000000000000000000000000000000000000000 - 00000F0F0F17474545E9484646FE494747FF494747FF494747FE595D5DFF81A6 - ADFF1894D2FF0C96DCFE0D9CE5FF0DA0EAFE0EA2EEFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA3EFFF21AAF0FF47B8F2FE49B9F3FF49B9F3FF49B9 - F2FE49B9F3FF49B9F3FF49B9F2FE49B9F3FF49B9F3FF49B9F3FF49B9F2FE49B9 - F3FF49B9F3FF49B9F2FE49B9F3FF4DAFE1FF717070FE757474FF767474FF7574 - 74FE767474FF747373FF6B6A6AFE597380FF4AB8F1FF49B9F2FE49B9F3FF49B9 - F3FF49B9F2FE49B9F3FF49B9F3FF49B9F2FE49B9F3FF49B9F2FE49B9F3FF49B9 - F3FF46B8F2FE1BA7EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0EA2EDFF0D9FEAFE0D9BE4FF0C95DBFF1D95D0FE75888AFF4F4F4FFF4947 - 47FE494747FF494747FF484646FE494747FF494747FF484646FE494747FF4947 - 47FF484646FE494747FF494747FF484646FE474545F91010106E000000340000 - 0010000000010000000000000000000000000000000000000000000000000000 - 0000000000003F3D3DB8484646FE484646FE484646FE484646FE505050FE7A8C - 8DFE41A2CEFE0C93D8FE0D9AE2FE0D9EE8FE0DA1EDFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA2EEFE0DA2EEFE13A5EFFE47B8F2FE50BCF3FE50BCF3FE50BCF3FE50BC - F3FE50BCF3FE50BCF3FE50BCF3FE50BCF3FE50BCF3FE50BCF3FE50BCF3FE50BC - F3FE50BCF3FE50BCF3FE50BCF3FE5AA7CFFE797777FE7B7979FE7B7979FE7B79 - 79FE7B7979FE777676FE6B6A6AFE5698B9FE50BCF3FE50BCF3FE50BCF3FE50BC - F3FE50BCF3FE50BCF3FE50BCF3FE50BCF3FE50BCF3FE50BCF3FE50BCF3FE50BC - F3FE50BCF3FE41B6F2FE11A4EFFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0DA1ECFE0D9EE8FE0C99E1FE0C92D7FE4B9EC2FE646C6CFE4A4949FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE2E2D2DB4000000430000 - 001D000000050000000000000000000000000000000000000000000000000000 - 00000000000024232360484646FE494747FF494747FF484646FE4A4949FF646C - 6CFF77ADBEFF0C90D4FE0D97DEFF0D9DE6FE0EA0EBFF0EA2EEFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE34B1F1FF58BEF4FF57BEF3FE58BEF4FF58BEF4FF57BE - F3FE58BEF4FF58BEF4FF57BEF3FE58BEF4FF58BEF4FF58BEF4FF57BEF3FE58BE - F4FF58BEF4FF57BEF3FE58BEF3FF6E94A8FF807E7EFE807F7FFF807F7FFF807F - 7FFE807E7EFF797878FF6A7277FE59B7E7FF58BEF4FF57BEF3FE58BEF4FF58BE - F4FF57BEF3FE58BEF4FF58BEF4FF57BEF3FE58BEF4FF57BEF3FE58BEF4FF58BE - F4FF57BEF3FE58BEF4FF2AADF0FF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA2 - EDFF0EA0EAFF0D9CE6FE0D96DDFF1392D2FF6F97A3FE545656FF494747FF4846 - 46FE494747FF494747FF484646FE494747FF494747FF484646FE494747FF4947 - 47FF484646FE494747FF494747FF484646FE494747FF444242F00909095E0000 - 002D0000000D0000000100000000000000000000000000000000000000000000 - 0000000000000C0C0C19484646E9494747FF494747FF484646FE494747FF5456 - 56FF849A9BFF2E9CD1FE0C94DAFF0D9AE3FE0E9FE9FF0EA1EDFF0DA2EEFE0EA3 - EFFF0EA3EFFF0FA3EFFE54BDF3FF5EC1F4FF5EC1F4FE5EC1F4FF5EC1F4FF5EC1 - F4FE5EC1F4FF5EC1F4FF5EC1F4FE5EC1F4FF5EC1F4FF5EC1F4FF5EC1F4FE5EC1 - F4FF5EC1F4FF5EC1F4FE60BDECFF7E888FFF858484FE868484FF868484FF8584 - 84FE848282FF7A7A7AFF688EA1FE5EC1F3FF5EC1F4FF5EC1F4FE5EC1F4FF5EC1 - F4FF5EC1F4FE5EC1F4FF5EC1F4FF5EC1F4FE5EC1F4FF5EC1F4FE5EC1F4FF5EC1 - F4FF5EC1F4FE5EC1F4FF4BBAF2FF0FA3EFFE0EA3EFFF0EA3EFFF0DA2EEFE0EA1 - ECFF0D9EE8FF0D9AE2FE0C93D8FF3B9BC7FF6E7B7CFE4C4B4BFF494747FF4846 - 46FE494747FF494747FF484646FE494747FF494747FF484646FE494747FF4947 - 47FF484646FE494747FF494747FF484646FE494747FF484646FE2423239C0000 - 003D000000190000000300000000000000000000000100000000000000000000 - 000000000000020202013B39399D484646FE484646FE484646FE484646FE4C4B - 4BFE697272FE6DAEC5FE0E91D4FE0C97DEFE0D9DE6FE0DA0EBFE0DA2EDFE0DA2 - EEFE0DA2EEFE1DA8F0FE65C4F4FE65C4F4FE65C4F4FE65C4F4FE65C4F4FE65C4 - F4FE65C4F4FE65C4F4FE65C4F4FE65C4F4FE65C4F4FE65C4F4FE65C4F4FE65C4 - F4FE65C4F4FE65C4F4FE6EB4D8FE898889FE8B8989FE8B8989FE8B8989FE8A89 - 89FE868585FE7B7A7AFE68B0D5FE65C4F4FE65C4F4FE65C4F4FE65C4F4FE65C4 - F4FE65C4F4FE65C4F4FE65C4F4FE65C4F4FE65C4F4FE65C4F4FE65C4F4FE65C4 - F4FE65C4F4FE65C4F4FE5FC1F4FE18A6EFFE0DA2EEFE0DA2EEFE0DA1EDFE0DA0 - EAFE0D9CE5FE0C97DDFE1091D3FE6B9AAAFE595D5DFE494747FE484646FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE484646FE413F3FE30000 - 0049000000280000000A00000000000000000000000200000000000000000000 - 000000000000000000001A1A1A2E494747FD494747FF484646FE494747FF4947 - 47FF545656FF849C9DFE329DCFFF0C93D8FE0D9AE2FF0D9EE8FF0DA1ECFE0EA2 - EEFF0EA3EFFF2CAEF1FE6DC7F5FF6DC7F5FF6CC7F5FE6DC7F5FF6DC7F5FF6CC7 - F5FE6DC7F5FF6DC7F5FF6CC7F5FE6DC7F5FF6DC7F5FF6DC7F5FF6CC7F5FE6DC7 - F5FF6DC7F5FF6CC7F5FE81A5B8FF908F8FFF908F8FFE908F8FFF908F8FFF8F8E - 8EFE898787FF7A8890FF6CC7F5FE6DC7F5FF6DC7F5FF6CC7F5FE6DC7F5FF6DC7 - F5FF6CC7F5FE6DC7F5FF6DC7F5FF6CC7F5FE6DC7F5FF6CC7F5FE6DC7F5FF6DC7 - F5FF6CC7F5FE6DC7F5FF6BC6F5FF22AAF0FE0EA2EFFF0EA2EEFF0DA1ECFE0D9E - E7FF0D99E1FF0C93D8FE3E9CC6FF6E7B7CFF4D4D4DFE494747FF494848FF4B4A - 4AFE4D4D4DFF4E4D4DFF4E4D4DFE4E4D4DFF4E4D4DFF4E4D4DFE4E4D4DFF4E4D - 4DFF4D4D4DFE4C4B4BFF4A4949FF494747FE494747FF494747FF484646FE1A19 - 1982000000390000001500000002000000000000000100000000000000000000 - 0000000000000000000000000000484646B7494747FF484646FE494747FF4947 - 47FF4B4A4AFF677070FE77ADBEFF1192D3FE0D96DDFF0D9CE5FF0D9FEAFE0EA1 - EDFF0EA2EEFF32B1F1FE74CAF6FF74CAF6FF74CAF5FE74CAF6FF74CAF6FF74CA - F5FE74CAF6FF74CAF6FF74CAF5FE76C3EBFF889EAAFF8EA0AAFF8FA1AAFE8FA1 - ABFF8FA1ABFF8FA1AAFE94989AFF969595FF969595FE969595FF969595FF9492 - 92FE8A898AFF7AA8BFFF74CAF5FE74CAF6FF74CAF6FF74CAF5FE74CAF6FF74CA - F6FF74CAF5FE74CAF6FF74CAF6FF74CAF5FE74CAF6FF74CAF5FE74CAF6FF74CA - F6FF74CAF5FE74CAF6FF74CAF6FF26ACF0FE0EA2EEFF0EA1ECFF0D9FE9FE0D9B - E4FF0C95DBFF1492D1FE7498A2FF585B5BFF494747FE494747FF4D4E4FFF5A68 - 6DFE68797EFF6B7D82FF6B7D82FE6B7D82FF6B7D82FF6B7D82FE6B7D82FF6B7D - 82FF6A7C81FE647073FF545656FF4A4848FE494747FF494747FF484646FE3735 - 35CA010101480000002300000006000000000000000100000000000000000000 - 000000000000000000000000000048464640484646F8484646FE484646FE4846 - 46FE494747FE525353FE7B8E8EFE4FA7CDFE0C92D6FE0D98DFFE0D9DE7FE0DA0 - EBFE0DA1EDFE2CAEF0FE7BCDF5FE7BCDF5FE7BCDF5FE7BCDF5FE7BCDF5FE7BCD - F5FE7BCDF5FE7BCDF5FE7BCDF5FE7EC5E8FE93979AFE9B9A9AFE9C9B9BFE9C9B - 9BFE9C9B9BFE9C9B9BFE9C9B9BFE9C9B9BFE9C9B9BFE9C9B9BFE9B9A9AFE9796 - 96FE8C8F92FE7DC3E6FE7BCDF5FE7BCDF5FE7BCDF5FE7BCDF5FE7BCDF5FE7BCD - F5FE7BCDF5FE7BCDF5FE7BCDF5FE7BCDF5FE7BCDF5FE7BCDF5FE7BCDF5FE7BCD - F5FE7BCDF5FE7BCDF5FE78CBF5FE22AAEFFE0DA1EDFE0DA0EAFE0D9DE6FE0C97 - DEFE0D92D5FE56A1C0FE677070FE4C4B4BFE494747FE494747FE515B5EFE66BB - E3FE7FD0F6FE7FD0F6FE7FD0F6FE7FD0F6FE7FD0F6FE7FD0F6FE7FD0F6FE7FD0 - F6FE7FD0F6FE86BCD6FE646969FE4C4A4AFE484646FE484646FE484646FE4745 - 45F80F0E0E6A000000330000000F000000010000000100000000000000000000 - 000000000000000000000000000048464601535858B1484646FE494747FF4947 - 47FF494747FF4A4848FE5C6161FF87A5A9FE2699D1FF0C94D9FF0C99E1FE0D9E - E8FF0EA0EBFF1AA6EEFE81CFF6FF83CFF7FF83CFF6FE83CFF7FF83CFF7FF83CF - F6FE83CFF7FF83CFF7FF83CFF6FE85C8EAFF9A9EA0FFA1A0A0FFA1A0A0FEA1A0 - A0FFA1A0A0FFA1A0A0FEA1A0A0FFA1A0A0FFA1A0A0FEA1A0A0FFA09F9FFF9998 - 98FE8CA3AFFF83CFF7FF83CFF6FE83CFF7FF83CFF7FF83CFF6FE83CFF7FF83CF - F7FF83CFF6FE83CFF7FF83CFF7FF83CFF6FE83CFF7FF83CFF6FE83CFF7FF83CF - F7FF83CFF6FE83CFF7FF76CAF6FF16A5EEFE0EA0EBFF0D9DE7FF0C99E1FE0C93 - D8FF329ACAFF75898CFE515252FF494747FF484646FE494747FF535B5FFF68BC - E2FE80D1F7FF80D1F7FF82CBEDFE82C8E7FF7FC5E5FF7EC4E4FE7EC4E4FF7EC4 - E4FF7EC4E4FE81B0C6FF616565FF4B4A4AFE494747FF494747FF484646FE4947 - 47FF2E2D2DB4000000420000001D000000050000000000000000000000000000 - 0000000000000000000000000000000000008AAEAE2F484646F2494747FF4947 - 47FF494747FF494747FE4D4D4DFF687171FE79AEBEFF1794D2FF0C95DBFE0D9B - E3FF0D9EE8FF0EA1EBFE6CC6F4FF8AD2F7FF8AD2F7FE8AD2F7FF8AD2F7FF8AD2 - F7FE8AD2F7FF8AD2F7FF8AD2F7FE8CCBEBFF9FA3A5FFA6A5A5FFA6A5A5FEA6A5 - A5FFA6A5A5FFA6A5A5FEA6A5A5FFA6A5A5FFA6A5A5FEA6A5A5FFA4A3A3FF9B9B - 9BFE8DBED8FF8AD2F7FF8AD2F7FE8AD2F7FF8AD2F7FF8AD2F7FE8AD2F7FF8AD2 - F7FF8AD2F7FE8AD2F7FF8AD2F7FF8AD2F7FE8AD2F7FF8AD2F7FE8AD2F7FF8AD2 - F7FF8AD2F7FE8AD2F7FF5DC0F3FF0EA0EBFE0D9EE8FF0D9AE2FF0C94DAFE1D95 - D0FF7298A3FF5A5F5FFE4A4848FF494747FF484646FE494747FF4F5050FF5D8E - A3FE7CCFF6FF80D1F7FF86C7E4FE899DA0FF6E7B7DFF636D6FFE626B6DFF626B - 6DFF616B6CFE5C6263FF515151FF4A4848FE494747FF494747FF484646FE4947 - 47FF434141ED0808085A0000002B0000000B0000000000000000000000000000 - 000000000000000000000000000000000000ABE2E2015E696989484646FE4846 - 46FE484646FE484646FE494747FE515252FE768484FE68ADC7FE0F91D3FE0C96 - DCFE0D9BE4FE0D9EE8FE39B1EFFE8FD4F6FE91D5F7FE91D5F7FE91D5F7FE91D5 - F7FE91D5F7FE91D5F7FE91D5F7FE93CEECFEA3A6A9FEA8A7A7FEA8A8A8FEA8A8 - A8FEA8A8A8FEA8A8A8FEA8A8A8FEA8A8A8FEA8A8A8FEA8A8A8FEA5A4A4FE9CA4 - A8FE92D1F2FE91D5F7FE91D5F7FE91D5F7FE91D5F7FE91D5F7FE91D5F7FE91D5 - F7FE91D5F7FE91D5F7FE91D5F7FE91D5F7FE91D5F7FE91D5F7FE91D5F7FE91D5 - F7FE91D5F7FE8DD3F6FE2AACEDFE0D9EE8FE0D9AE3FE0C95DBFE1091D2FE6CA1 - B3FE636B6BFE4C4B4BFE494747FE484646FE484646FE484646FE4A4949FE5659 - 59FE65AAC8FE7ED0F6FE7FD0F6FE89BACFFE6F7879FE535454FE4B4A4AFE4B4A - 4AFE4B4A4AFE4A4949FE494848FE494747FE484646FE484646FE484646FE4846 - 46FE484646FE2121219600000038000000140000000100000000000000000000 - 00000000000000000000000000000000000000000000ADE4E409494747D64947 - 47FF494747FF484646FE494747FF494747FE555757FF7C8E8FFF5BAACAFE0D91 - D4FF0C96DDFF0D9BE4FE11A0E9FF6DC6F3FF99D7F7FE99D7F8FF99D7F8FF99D7 - F7FE99D7F8FF99D7F8FF99D7F7FE9AD0ECFFA3A6A8FFA6A5A5FFA6A5A5FEA6A5 - A5FFA6A5A5FFA6A5A5FEA6A5A5FFA6A5A5FFA6A5A5FEA5A5A5FFA4A3A3FF9DBA - C9FE99D7F8FF99D7F8FF99D7F7FE99D7F8FF99D7F8FF99D7F7FE99D7F8FF99D7 - F8FF99D7F7FE99D7F8FF99D7F8FF99D7F7FE99D7F8FF99D7F7FE99D7F8FF99D7 - F8FF99D7F7FE5DBFF1FF0F9FE8FF0D9AE3FE0C96DBFF1092D3FF5FA2BCFE6973 - 73FF4E4E4EFF494747FE494747FF494747FF484646FE494747FF494747FF4B4A - 4AFE596467FF6BB8DAFF7FD0F6FE80D0F6FF88ABBAFF656C6CFE4E4D4DFF4947 - 47FF484646FE494747FF494747FF484646FE494747FF494747FF484646FE4947 - 47FF494747FF3F3D3DDD000000430000001E0000000500000000000000000000 - 000000000000000000000000000000000000000000000000000088ABAB414A49 - 49F3494747FF484646FE494747FF484646FE4A4949FF595C5CFF819597FE50A7 - CCFF0E92D4FF0C96DCFE0D9BE3FF22A6EAFF89D0F5FEA1DAF8FFA1DAF8FFA0DB - F8FEA1DBF8FFA1DBF8FFA0DBF8FEA1D1E9FFA5A6A7FFA5A5A5FFA5A5A5FEA5A5 - A5FFA5A5A5FFA5A5A5FEA5A5A5FFA5A5A5FFA5A5A5FEA5A5A5FFA5A5A5FFA1D2 - EAFEA1DBF8FFA1DBF8FFA0DBF8FEA1DBF8FFA1DBF8FFA0DBF8FEA1DBF8FFA1DB - F8FFA0DBF8FEA1DBF8FFA1DBF8FFA0DBF8FEA1DBF8FFA0DBF8FEA1DAF8FFA0DA - F8FF81CDF4FE17A2E8FF0D9AE3FF0C96DCFE1092D3FF58A1BEFF6F7C7DFE5051 - 51FF494747FF484646FE494747FF494747FF484646FE494747FF494747FF4947 - 47FE4E4D4DFF5C747CFF72C5EAFE80D1F7FF82CDF1FF849DA6FE5C6161FF4C4B - 4BFF494747FE494747FF494747FF484646FE494747FF494747FF484646FE4947 - 47FF494747FF484646FD0E0E0E60000000270000000800000000000000000000 - 0000000000000000000000000000000000000000000000000000000000006777 - 777C484646FE484646FE484646FE484646FE494747FE4B4A4AFE5A5E5EFE8299 - 9AFE55A9CCFE0D90D4FE0C96DBFE0D9AE2FE2AA9E9FE98D6F6FEA7DCF8FEA7DD - F8FEA7DDF8FEA7DEF8FEA7DEF8FEA8DBF5FEA8D1E5FEA8D0E4FEA8D0E4FEA8D0 - E4FEA8D0E4FEA8D0E4FEA8D0E4FEA8D0E4FEA8D0E4FEA8D0E4FEA8D1E5FEA7DE - F8FEA7DEF8FEA7DEF8FEA7DEF8FEA7DEF8FEA7DEF8FEA7DEF8FEA7DEF8FEA7DE - F8FEA7DEF8FEA7DEF8FEA7DEF8FEA7DEF8FEA7DDF8FEA7DDF8FEA7DCF8FE8CD1 - F4FE22A5E8FE0D99E1FE0C95DAFE0E90D3FE5DA3BFFE707E7FFE525353FE4947 - 47FE484646FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE494747FE505151FE5E8594FE7ACEF5FE80D0F6FE85C9E9FE7D8A8DFE575A - 5AFE4A4949FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE484646FE242323970000002E0000000C00000000000000000000 - 000000000000000000000000000000000000000000000000000000000000B8F6 - F6065B6363A9484646FE494747FF484646FE494747FF494747FF4B4949FE595D - 5DFF7E9091FF68ADC8FE1392D2FF0C94DAFF0C99E0FE26A6E8FF8BD0F4FFAFDF - F8FEAFDFF9FFAFE0F9FFAFE0F9FEAFE0FAFFAFE0FAFFAFE0FAFFAFE0F9FEAFE0 - FAFFAFE0FAFFAFE0F9FEAFE0FAFFAFE0FAFFAFE0F9FEAFE0FAFFAFE0FAFFAFE0 - F9FEAFE0FAFFAFE0FAFFAFE0F9FEAFE0FAFFAFE0FAFFAFE0F9FEAFE0FAFFAFE0 - FAFFAFE0F9FEAFE0FAFFAFE0FAFFAFE0F9FEAFDFF9FFAFDFF8FE7FCCF3FF1EA2 - E6FF0C98DFFE0C94D9FF1994D1FF69A4B9FE6D7878FF515252FF494747FE4947 - 47FF494747FF484646FE494747FF494747FF484646FE494747FF494747FF4846 - 46FE494747FF4A4848FF535555FE639AB1FF7DCFF5FF80D0F6FE87C1DCFF7480 - 81FF545555FE4A4848FF494747FF484646FE494747FF494747FF484646FE4947 - 47FF494747FF484646FE343333C5000000320000000E00000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000A2D3D311464A4DCE494747FF484646FE494747FF494747FF494747FE4B49 - 49FF565959FF768585FE74AEC1FF2398D1FF0C92D7FE0D97DDFF1AA0E4FF6BC3 - F0FEAFDFF8FFB6E2F9FFB5E2F9FEB6E3FAFFB6E3FAFFB6E3FAFFB5E3F9FEB6E3 - FAFFB6E3FAFFB5E3F9FEB6E3FAFFB6E3FAFFB5E3F9FEB6E3FAFFB6E3FAFFB5E3 - F9FEB6E3FAFFB6E3FAFFB5E3F9FEB6E3FAFFB6E3FAFFB5E3F9FEB6E3FAFFB6E3 - FAFFB5E3F9FEB6E3FAFFB6E2F9FFB5E2F8FEAADDF7FF61BFEEFE149DE3FF0C96 - DDFF0C92D6FE2998CEFF729FADFF687272FE4F5050FF494747FF484646FE4947 - 47FF494747FF484646FE494747FF494747FF484646FE494747FF494747FF4846 - 46FE494747FF494747FF4B4949FE575E5FFF73B2CDFF91D7F8FE8FD6F7FF91B8 - C9FF6B7474FE4F5050FF494747FF484646FE494747FF494747FF484646FE4947 - 47FF494747FF484646FE3F3E3EDB040404370000000E00000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000001B79A921464A4DDE484646FE484646FE484646FE484646FE4947 - 47FE4A4848FE525353FE6D7878FE83A9B1FE44A4CFFE0C90D4FE0C94DAFE0D98 - DFFE37ACE8FE8CD0F3FEBBE4F9FEBDE5F9FEBDE5F9FEBDE5FAFEBDE5FAFEBDE6 - FAFEBDE6FAFEBDE6FAFEBDE6FAFEBDE6FAFEBDE6FAFEBDE6FAFEBDE6FAFEBDE6 - FAFEBDE6FAFEBDE6FAFEBDE6FAFEBDE6FAFEBDE6FAFEBDE6FAFEBDE5FAFEBDE5 - FAFEBDE5F9FEBDE5F9FEB9E3F8FE81CCF2FE2EA8E7FE0D98DFFE0C94D9FE0F91 - D3FE49A2C9FE7A969BFE606767FE4D4D4DFE494747FE484646FE484646FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE484646FE494747FE4C4C4CFE5F6C70FE95CDE6FEA9E0F9FEA8DE - F7FE94ABB4FE5F6565FE4C4B4BFE494747FE484646FE484646FE484646FE4846 - 46FE484646FE484646FE444242E6060606390000000C00000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000001A7BAC29454B4FDD494747FF494747FF484646FE4947 - 47FF494747FF494747FE4E4D4DFF5E6464FF809393FE71AEC4FF2799D1FF0C91 - D5FE0C95DBFF0E99E0FF34ABE7FE80CBF1FFB3E0F7FFC4E7FAFFC3E7F9FEC4E7 - FAFFC4E7FBFFC3E8FAFEC4E8FBFFC4E8FBFFC3E8FAFEC4E8FBFFC4E8FBFFC3E8 - FAFEC4E8FBFFC4E8FBFFC3E8FAFEC4E8FBFFC4E7FBFFC3E7FAFEC4E7FAFFC4E7 - FAFFAEDEF7FE76C7F0FF2EA8E6FF0C98DFFE0C95DAFF0C91D4FE2E9ACEFF71A4 - B4FF728080FE565858FF4B4A4AFF494747FE494747FF494747FF484646FE4947 - 47FF494747FF484646FE494747FF494747FF484646FE494747FF494747FF4846 - 46FE494747FF494747FF484646FE494747FF4E4E4EFF677B82FEA6DCF4FFB0E1 - FAFFAEDDF3FE808C8EFF555757FF494747FE494747FF494747FF484646FE4947 - 47FF494747FF484646FE434141E1060606310000000800000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000001A7BAC29464A4DDC494747FF484646FE4947 - 47FF494747FF484646FE494747FF4B4949FF545656FE6C7777FF83A2A6FF60AB - C8FE2197D1FF0D92D5FF0C94DAFE0E98DEFF1EA1E3FF49B4EAFF83CCF2FEAADD - F6FFBEE5F9FFC8E9FAFECAEAFAFFCAEAFAFFCAEAFAFECAEAFBFFCAEAFBFFCAEA - FAFECAEAFBFFCAEAFAFFCAEAFAFEC7E9FAFFBDE5F8FFA5DBF6FE7CC9F1FF45B2 - E9FF1A9EE2FE0D97DEFF0C94D9FF0E92D5FE2798CFFF61A5BFFE7A9093FF6168 - 68FF4F5050FE4A4848FF494747FF484646FE494747FF494747FF484646FE4947 - 47FF494747FF484646FE494747FF494747FF484646FE494747FF494747FF4A49 - 49FE4B4A4AFF4B4949FF494848FE494747FF494848FF525252FE80A3B1FFB4E3 - FAFFB5E4FAFE9EB8C2FF606666FF4B4949FE494747FF494747FF484646FE4947 - 47FF494747FF484646FE3D3C3CD3030303220000000500000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000001B79A921464A4DCA484646FE4846 - 46FE484646FE484646FE484646FE494747FE494747FE4D4C4CFE595D5DFE717D - 7DFE85A5AAFE65ADC7FE2C9CD1FE0C90D3FE0C93D7FE0C95DBFE0C97DDFE119B - E1FE25A4E5FE3EAEE8FE58BAECFE6BC2EFFE79C8F0FE82CCF2FE86CDF2FE81CB - F2FE78C7F0FE69C1EEFE55B9EBFE3AADE8FE23A3E4FE0F99E0FE0C97DDFE0C95 - DAFE0C92D7FE0E91D3FE309CD0FE68A7BEFE7C9699FE677070FE535454FE4B4A - 4AFE494747FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE494747FE4D4C4CFE575A - 5AFE616767FE5D6363FE525353FE4A4848FE494747FE4A4949FE637175FEAFDE - F2FEBBE6FAFEAECDDBFE6A7171FE4C4B4BFE484646FE484646FE484646FE4846 - 46FE484646FE484646FE343333B2000000130000000200000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000001A7BAC0F3F515BA14947 - 47FF494747FF484646FE494747FF494747FF484646FE494747FF494848FF4D4C - 4CFE585B5BFF6B7575FF84999AFE7CACBAFF54A7CAFF2C9CD1FF1192D2FE0C91 - D5FF0C93D8FF0C94D9FE0D95DBFF0D96DCFF0C96DDFE0D97DDFF0D97DDFF0C96 - DDFE0D96DDFF0D96DCFF0C95DBFE0C94D9FF0C93D7FF0C91D5FE1492D2FF2F9C - CFFF57A5C5FE7AA4B0FF7B8C8CFF626969FE525454FF4B4A4AFE494747FF4947 - 47FF484646FE494747FF494747FF484646FE494747FF494747FF484646FE4947 - 47FF494747FF484646FE494747FF494747FF484646FE494747FF555C5FFFA2D0 - E4FEBBE2F5FFAECEDDFF6B7272FE4D4D4DFF494747FF494848FE5C6263FFB0D9 - EBFFC2E8FBFEB4D1DEFF6C7474FF4C4C4CFE494747FF494747FF484646FE4947 - 47FF494747FF484646FE21202070000000090000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000000E87C4053859 - 6A70484849EF484646FE494747FF494747FF484646FE494747FF494747FF4947 - 47FE494747FF4C4B4BFF535555FE606666FF717E7EFF80979AFF7FA9B3FE6AAA - C2FF51A6CBFF3AA0CEFE2799D0FF1C96D2FF1894D2FE1594D3FF1593D3FF1694 - D3FE1894D2FF1D96D2FF2999CFFE3CA0CDFF52A5C8FF6BA7BDFE7CA1AAFF7A8E - 90FF6A7474FE5B5F5FFF505151FF4A4949FE494747FF494747FE494747FF4947 - 47FF484646FE494747FF494747FF484646FE494747FF494747FF484646FE4947 - 47FF494747FF484646FE494747FF494747FF484646FE494747FF55595AFFA9CF - DFFEC8EBFCFFC3E3F3FF869395FE585C5CFF4C4C4CFF4F4F4FFE718389FFC1E6 - F7FFC8EBFBFEB3CDD8FF686F6FFF4C4B4BFE494747FF494747FF484646FE4947 - 47FF494747FF484646F20909091F000000020000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000088B0B236535858CA484646FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE484646FE494747FE4A4848FE4C4C4CFE525353FE5A5F5FFE656E - 6EFE707C7CFE7B8C8CFE829899FE839FA3FE81A2A9FE7FA4ADFE7EA4ADFE7EA3 - ACFE80A1A7FE829DA0FE7F9495FE778686FE6D7777FE616868FE575A5AFE5050 - 50FE4B4A4AFE494747FE494747FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE494747FE4F5050FE8FAD - B9FECEEDFBFECEECFBFEB6CED8FE7A8787FE656D6DFE6E7B7DFEB2D2DFFECEED - FBFECEEDFBFE9FB1B7FE5D6262FE4A4949FE484646FE484646FE484646FE4846 - 46FE484646FE3130309400000006000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000ADE5E502768E8E724C4C4CE6484646FE494747FF494747FF4846 - 46FE494747FF494747FF484646FE494747FF494747FF494747FF494747FE4A48 - 48FF4B4A4AFF4D4D4DFE505050FF525454FF545656FE565858FF565959FF5558 - 58FE535555FF525252FF4F4F4FFE4C4B4BFF4B4949FF494747FE494747FF4947 - 47FF484646FE494747FF494747FF484646FE494747FF484646FE494747FF4947 - 47FF484646FE494747FF494747FF484646FE494747FF494747FF484646FE4947 - 47FF494747FF484646FE494747FF494747FF484646FE494747FF4B4949FF5F68 - 6AFEBCDCEAFFD4EFFCFFD4EFFCFECEE9F6FFC2DEEAFFCEECF9FED4EFFCFFD4EF - FCFFBFD7E2FE717A7AFF515252FF494747FE494747FF494747FF484646FE4947 - 47FF444242DC0B0A0A1D00000001000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000004A49491C4846468E494747F0494747FF4846 - 46FE494747FF494747FF484646FE494747FF494747FF494747FF484646FE4947 - 47FF494747FF484646FE494747FF494747FF494747FE494747FF494747FF4947 - 47FE494747FF494747FF494747FE494747FF494747FF484646FE494747FF4947 - 47FF484646FE494747FF494747FF484646FE494747FF484646FE494747FF4947 - 47FF484646FE494747FF494747FF484646FE494747FF494747FF484646FE4947 - 47FF494747FF484646FE494747FF494747FF484646FE494747FF494747FF4E4D - 4DFE697578FFB0CBD5FFD2EBF7FED9F1FCFFDAF1FDFFD9F0FCFED2EAF6FFB4CA - D2FF798385FE565858FF4A4949FF494747FE494747FF494747FF484646FE4846 - 46F31F1F1F4C0000000100000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000484646244846468A4846 - 46ED484646FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE484646FE484646FE4947 - 47FE4D4D4DFE595C5CFE707D80FE859395FE8A979AFE869497FE768284FE6167 - 67FE525454FE4B4949FE494747FE484646FE484646FE484646FE484646FC2D2C - 2C63010101020000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000004846 - 460B49474765494747BD484646F6494747FF494747FF494747FF484646FE4947 - 47FF494747FF484646FE494747FF494747FF484646FE494747FF494747FF4846 - 46FE494747FF494747FF484646FE494747FF494747FF484646FE494747FF4947 - 47FF484646FE494747FF494747FF484646FE494747FF484646FE494747FF4947 - 47FF484646FE494747FF494747FF484646FE494747FF494747FF484646FE4947 - 47FF494747FF484646FE494747FF494747FF484646FE494747FF494747FF4846 - 46FE494747FF4A4848FF4C4B4BFE4E4E4EFF505050FF4F4F4FFE4D4D4DFF4B49 - 49FF494747FE494747FF494747FF484646FE494747FF464444E1302F2F4C0000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000049474704484646224947476E494747B4494747E5484646F94947 - 47FF494747FF484646FE494747FF494747FF484646FE494747FF494747FF4846 - 46FE494747FF494747FF484646FE494747FF494747FF484646FE494747FF4947 - 47FF484646FE494747FF494747FF484646FE494747FF484646FE494747FF4947 - 47FF484646FE494747FF494747FF484646FE494747FF494747FF484646FE4947 - 47FF494747FF484646FE494747FF494747FF484646FE494747FF494747FF4846 - 46FE494747FF494747FF484646FE494747FF494747FF484646FE494747FF4947 - 47FF484646FE494747FF494747FE484646EF413F3F943837371D000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000004846460F484646354846 - 46604846468B484646AE484646CD484646E4484646F3484646FE484646FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FE484646FE484646FE484646FE484646FE484646FE484646FE484646FE4846 - 46FC484646E2484646B24846466E484646210000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8FFFFFFFFFFFFFFFFF - FFFF80000FFFFFFFFFFFFFFFFFF8000001FFFFFFFFFFFFFFFFE00000003FFFFF - FFFFFFFFFF000000000FFFFFFFFFFFFFFE0000000003FFFFFFFFFFFFF8000000 - 0000FFFFFFFFFFFFE000000000007FFFFFFFFFFFC000000000001FFFFFFFFFFF - 8000000000000FFFFFFFFFFE00000000000007FFFFFFFFFC00000000000003FF - FFFFFFF800000000000001FFFFFFFFF000000000000000FFFFFFFFF000000000 - 0000007FFFFFFFE0000000000000003FFFFFFFC0000000000000001FFFFFFF80 - 000000000000001FFFFFFF80000000000000000FFFFFFF000000000000000007 - FFFFFE000000000000000007FFFFFE000000000000000003FFFFFC0000000000 - 00000003FFFFFC000000000000000001FFFFF8000000000000000001FFFFF800 - 0000000000000000FFFFF0000000000000000000FFFFF0000000000000000000 - 7FFFF00000000000000000007FFFE00000000000000000007FFFE00000000000 - 000000003FFFE00000000000000000003FFFE00000000000000000001FFFC000 - 00000000000000001FFFC00000000000000000000FFFC0000000000000000000 - 0FFFC00000000000000000000FFFC000000000000000000007FFC00000000000 - 0000000007FFC000000000000000000003FFC000000000000000000003FFC000 - 000000000000000001FFC000000000000000000001FFC0000000000000000000 - 01FFC000000000000000000000FFC000000000000000000000FFC00000000000 - 00000000007FC0000000000000000000007FC0000000000000000000003FC000 - 0000000000000000003FE0000000000000000000003FE0000000000000000000 - 001FE0000000000000000000001FE0000000000000000000000FF00000000000 - 00000000000FF00000000000000000000007F00000000000000000000006F000 - 00000000000000000006F80000000000000000000002FC000000000000000000 - 0002FC0000000000000000000000FC0000000000000000000001FE0000000000 - 000000000001FE0000000000000000000000FF0000000000000000000000FF80 - 00000000000000000000FFC000000000000000000000FFC00000000000000000 - 0000FFE000000000000000000000FFF000000000000000000000FFF800000000 - 000000000000FFFC00000000000000000000FFFE00000000000000000000FFFF - 00000000000000000001FFFF80000000000000000001FFFFE000000000000000 - 0003FFFFF0000000000000000003FFFFFC000000000000000007FFFFFF000000 - 00000000000FFFFFFFC0000000000000003FFFFFFFF0000000000000007FFFFF - FFFF00000000000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF28000000480000009000 - 0000010020000000000060540000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000003737370137373702373737043737370637373707373737073737 - 3707373737063737370537373703373737010000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000001000000050000 - 000B000000130000001B00000023000000290000002E00000030000000310000 - 00310000002F0000002C000000260000001E000000160000000E000000070000 - 0002000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000040000000D0000001A000000290000 - 00370000004200000049030303520C0C0C64100F0F7110101073101010741010 - 10740E0D0D6B0707075B000000500000004C000000460000003B0000002F0000 - 0020000000110000000600000001000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000028272701070707060000001300000026000000390303034E121111742423 - 23A1333232C7424040E5474545F9484646FC484646FD484646FD484646FD4846 - 46FD484646FC474545FA444242EE383636D12A2929AF171616840606065F0000 - 004C0000003F0000002D000000190101010A1F1E1E0200000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000D0C - 0C04000000120000002900000040121111702D2C2CB6424040E9484646FE4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF454343F23332 - 32C7181717860101015400000046000000320000001A03030308242323010000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000001A1A1A020000000D0000 - 0024020202421B1A1A873C3A3AD9484646FE494747FF484646FE494747FF4846 - 46FE494747FF494747FF484646FE494747FF484646FE494747FF484646FE4947 - 47FF484646FE494747FF494747FF484646FE494747FF484646FE494747FF4846 - 46FE494747FF424040E92322229F0606065E000000460000002E000000140808 - 0804000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000001014140500000017000000341716 - 16783C3A3AD9484646FE494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF4A4949FF4C4B4BFF4D4D4DFF4E4E4EFF4E4E4EFF4D4D - 4DFF4C4B4BFF4A4949FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF424040EA1F1E1E97020202540000003D0000 - 0020010101090000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000040505080000002009090950323131BE4846 - 46FE494747FF484646FE494747FF484646FE494747FF494747FE4C4C4CFF5456 - 56FE606666FF697879FF68848CFE638C9AFF6091A4FE5E94A9FF5E93A9FE5E90 - A4FF618A9AFE66838CFF687779FF5F6565FE545656FF4C4B4BFE494747FF4947 - 47FE494747FF484646FE494747FF484646FE494747FF3B3A3AD9100F0F740000 - 00480000002B0000000F546B6B01000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000505050A0000002718171776424141EA494747FF4947 - 47FF494747FF494747FF494747FF4B4A4AFF545656FF657071FF6A8B95FF5598 - B4FF3F9DC9FF2F9DD4FF2B9FD9FF2CA0DCFF2EA2DDFF30A3DEFF30A3DEFF2EA2 - DDFF2CA0DCFF2B9ED9FF2C9CD4FF399BCAFF4C95B5FF638895FF636E70FF5355 - 55FF4B4949FF494747FF494747FF494747FF494747FF494747FF464444F62322 - 229E010101500000003300000012515151020000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000606060A0101012B25242498484646FA494747FF484646FE4947 - 47FF494747FF4B4A4AFE575A5AFF6C7F82FE5A98B1FF399ECEFE289DD9FF2EA3 - DFFE33A7E3FF35AAE5FF38ACE7FE3AAEE9FF3BAEEAFE3CAFEAFF3CAFEAFE3CAF - EAFF3BAEE9FE39ADE8FF37ABE6FF34A8E3FE30A4DFFF279DD9FE319BCFFF4F93 - B0FE667C81FF565959FE4B4949FF494747FE494747FF494747FF484646FE4846 - 46FE323030C00404045800000037000000140327390200000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000404040A0101012C2E2D2DAD484646FD494747FF494747FF494747FF4948 - 48FF525454FF6A7B7EFF599AB5FF2E9DD3FF2AA0DDFF2FA6E3FF34AAE7FF37AD - EAFF39B0ECFF3BB1EEFF3DB3EFFF3EB4EFFF3EB4F0FF3FB4F0FF3FB4F0FF3FB4 - F0FF3FB4EFFF3EB3EFFF3EB2EEFF3CB1ECFF3AAFEBFF36ACE8FF32A7E4FF2BA1 - DEFF289AD4FF4B95B5FF65787CFF525454FF494848FF494747FF494747FF4947 - 47FF494747FF393737D30606065D0000003700000013526E6E01000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000D12 - 1206010101282E2D2DAC484646FE494747FF484646FE494747FF4B4A4AFE5F65 - 65FF6994A3FF349DCFFE269FDCFF2DA6E3FE31AAE8FF35AEECFE38B0EEFF39B2 - EFFE3AB3F0FF3BB4F1FF3BB4F1FE3CB4F1FF3CB4F1FE3DB5F2FF3DB5F1FE3DB5 - F2FF3DB4F1FE3EB5F1FF3DB5F1FF3DB4F1FE3CB3F0FF3BB2EEFE38B0ECFF35AC - E9FE30A7E4FF28A0DDFE2A99CFFF5A8EA3FE5D6363FF4B4A4AFF494747FE4947 - 47FF484646FE494747FF3C3B3BDB0505055B000000350000000F5E7E7E010000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000263333040000 - 001E2D2C2CA6484646FE494747FF494747FF494747FF4E4E4EFF6A7778FF539D - BDFF239BD8FF28A2E1FF2DA8E7FF31ADECFF33AFEEFF35B1F0FF36B2F1FF37B2 - F1FF37B2F2FF37B3F2FF38B3F2FF38B3F2FF38B3F2FF39B3F2FF39B3F2FF39B3 - F2FF39B3F2FF39B3F2FF3AB4F2FF3AB4F2FF3AB4F2FF39B3F1FF39B3F0FF38B1 - EFFF36AFEDFF31ABE9FF2BA5E2FF229BD9FF4196BDFF647478FF4E4D4DFF4947 - 47FF494747FF494747FF494747FF393838D4050505580000002E0304040B0000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000526E6E0100000014201F - 1F82484646FE494747FF494747FF494747FF505050FF6F8285FF419DC7FF219C - DBFF27A4E4FF2BA9EAFF2EADEDFF30AEEFFF31B0F0FF32B0F1FF32B0F1FF32B0 - F1FF33B1F1FF33B1F1FF33B1F1FF34B1F1FF34B1F1FF34B1F1FF34B1F1FF35B1 - F1FF35B2F2FF36B2F2FF36B2F2FF36B2F2FF36B2F2FF37B2F2FF37B2F2FF37B2 - F1FF36B1F0FF34AFEEFF31ACEBFF2BA7E6FF239EDDFF3197C8FF657D83FF4F50 - 50FF494747FF494747FF494747FF494747FF333232C40000004B000000240E11 - 1105000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000000000000B131313584745 - 45F7484646FE494747FF494747FE505151FF70878CFE359CCDFF1F9CDDFE24A4 - E6FF28A9EBFF2AACEEFE2BADF0FF2CAEF0FE2DAFF1FF2DAFF0FE2DAFF1FF2EAF - F0FE2EAFF1FF2EAFF1FF2EAFF0FE2FAFF1FF2FAFF0FE2FB0F1FF30B0F0FE30B0 - F1FF30B0F0FE30B0F1FF31B0F1FF31B0F0FE31B0F1FF32B0F1FE32B0F1FF32B0 - F1FE32B0F1FF32B0F0FE31AFEFFF2EACECFE29A7E7FF239FDFFF2797CEFE6481 - 8AFF505050FE494747FF484646FE494747FF484646FE262525A4000000420000 - 00181B1A1A020000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000001315150405040428413F3FDF4947 - 47FF494747FF494747FF4E4E4EFF6F8285FF379CCCFF1C9CDDFF21A3E6FF25A8 - ECFF27ABEFFF27ACF0FF28ACF1FF28ADF1FF28ADF1FF28ADF1FF29ADF1FF29AD - F1FF29ADF1FF29ADF1FF2AADF1FF2AADF1FF2AAEF1FF2BAEF1FF2BAEF1FF2BAE - F1FF2BAEF1FF2CAEF1FF2CAEF1FF2CAEF1FF2DAEF1FF2DAFF1FF2DAFF1FF2DAF - F1FF2EAFF1FF2EAFF1FF2EAFF0FF2DAEEFFF2BABEDFF27A7E8FF219EDFFF2796 - CDFF647D83FF4D4D4DFF494747FF494747FF494747FF474545F9121212770000 - 00330000000B0000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000102D2C2CA0494747FF4947 - 47FF494747FE4B4A4AFF6B7778FE439EC7FF199ADBFE1DA2E6FF21A7EBFE22A9 - EEFF23AAF0FF23ABF0FE24ABF0FF24ABF0FE24ABF0FF24ABF0FE25ABF0FF25AB - F0FE25ACF0FF26ACF0FF26ACF0FE26ACF1FF26ACF0FE26ACF1FF27ACF0FE27AC - F1FF27ACF0FE27ACF1FF28ADF1FF28ADF0FE28ADF1FF3990BDFE3698CAFF2AAB - EDFE29ADF1FF29ADF0FE2AADF1FF29ADF0FE29ACEFFF28AAECFF24A5E7FE1E9D - DEFF2F96C8FE647376FF4B4A4AFE494747FF484646FE494747FF3E3D3DE00303 - 034F000000201211110300000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000511111148474545F7494747FF4947 - 47FF494848FF5E6465FF589FBBFF1697D9FF199FE4FF1CA5EAFF1EA8EEFF1FA0 - E2FF2F6581FF3D708AFF42748EFF42748EFF42748EFF3B7D9FFF21A9EEFF21AA - F0FF21AAF0FF22AAF0FF22AAF0FF22AAF0FF22AAF0FF23ABF0FF23ABF0FF23AB - F0FF23ABF0FF24ABF0FF24ABF0FF24ABF0FF26A7EAFF535D63FF595959FF5264 - 6EFF4180A1FF2F9ED7FF26ABEFFF26ACF0FF26ACF0FF26ABEFFF24A8ECFF20A3 - E6FF199ADBFF4194BBFF5D6363FF494747FF494747FF494747FF484646FE2524 - 24A1000000390000000E00000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000001010110373636BF484646FE494747FF4947 - 47FF525454FE7096A2FF1996D5FE169CE1FF18A3E9FE1AA6EEFF1AA7EFFE1BA7 - EFFF285C77FF434242FE515050FF535252FE545252FF535152FE2B8EC1FF1DA8 - EFFE1DA8F0FF1DA8F0FF1DA8EFFE1EA9F0FF1EA9EFFE1EA9F0FF1EA9EFFE1FA9 - F0FF1FA9EFFE1FA9F0FF20A9F0FF20A9EFFE3288B4FF565454FE575555FF5755 - 55FE575555FF575657FE4B6979FF3986AEFE27A2E1FF22AAEFFF22A9EEFE20A6 - EBFF1BA0E4FE1796D7FF5B8DA1FE515252FF494747FE494747FF494747FF4442 - 42F10908085A0000002016161603000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000031615154F484646FC494747FF494747FF4B49 - 49FF6D7B7DFF359BCCFF1298DDFF15A0E7FF16A4EDFF17A6EFFF17A6F0FF17A6 - F0FF1998D9FF32373AFF494747FF504E4EFF514F4FFF514F4FFF465D6AFF1BA3 - E9FF19A7F0FF19A7F0FF19A7F0FF1AA7F0FF1AA7F0FF1AA8F0FF1AA7F0FF1AA8 - F0FF1BA8F0FF1BA8F0FF1BA8F0FF1CA7EEFF446272FF545252FF545252FF5452 - 52FF545252FF545353FF555353FF555353FF525659FF40697FFF2689BCFF1DA7 - EDFF1BA3E9FF179CDFFF2295CEFF65767AFF4B4949FF494747FF494747FF4947 - 47FF282727A8000000340202020A000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000B363434B6494747FF484646FE494747FF5658 - 58FF659EB3FE1094D7FF119CE3FE13A2EAFF14A4EEFE14A5EFFF15A5EFFE15A5 - EFFF15A5EFFF1F6487FE3B3A3AFF4C4A4AFE4E4C4CFF4E4C4CFE4E4C4DFF2D7E - A9FE16A6F0FF16A6F0FF16A6EFFE16A6F0FF17A6EFFE17A6F0FF17A6EFFE17A6 - F0FF17A6EFFE18A6F0FF18A7F0FF2294CEFE4E4F50FF514F4FFE514F4FFF514F - 4FFE514F4FFF514F4FFE525050FF525050FE514F4FFF454444FF266A8DFE1AA7 - EFFF19A5ECFE16A0E6FF1396DAFE4B92B1FF555858FE494747FF494747FF4846 - 46FE434242ED0505054D00000017252424010000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000010D0D0D31484646F9494747FF494747FF4B4A4AFF707F - 7FFF2B9AD0FF0E98DEFF109FE8FF11A2EDFF11A4EEFF11A4EFFF12A4EFFF12A4 - EFFF12A4EFFF139BE0FF293841FF434141FF4C4A4AFF4C4A4AFF4D4B4BFF4751 - 57FF189DE1FF13A5EFFF14A5EFFF14A5EFFF14A5EFFF14A5EFFF14A5EFFF14A5 - EFFF15A5EFFF15A5EFFF15A5EFFF356D8BFF4E4C4CFF4F4D4DFF4F4D4DFF4D4B - 4BFF474545FF464545FF4C4A4AFF4F4D4DFF4C4A4AFF383A3CFF1996D7FF17A6 - F0FF16A5EEFF15A2EAFF129AE1FF1C94D0FF657A7FFF4A4949FF494747FF4947 - 47FF484646FE1D1C1C8C0000002A0A0A0A060000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000327262684494747FF494747FF494747FF535555FF6B9D - AEFF0C92D7FF0E9BE3FF0FA0EBFF0FA2EEFF0FA3EFFF0FA3EFFF10A3EFFF10A4 - EFFF10A4EFFF10A4EFFF186E9AFF353434FF474545FF4A4848FF4A4848FF4A48 - 48FF307091FF11A4EFFF11A4EFFF11A4EFFF12A4EFFF12A4EFFF12A4EFFF12A4 - EFFF12A4EFFF12A4EFFF159FE6FF464D51FF4C4A4AFF4C4A4AFF4C4A4AFF4544 - 44FF313030FF2C2A2AFF363434FF403E3EFF3F3E3EFF265065FF14A5EFFF14A5 - EFFF14A5EEFF13A2ECFF109DE5FF0E94D9FF5192ADFF525353FF494747FF4947 - 47FF494747FF373535CD0000003E000000110000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000101010A403E3ED2484646FE494747FF494747FE666F70FF3E9E - CAFF0C96DCFE0D9DE7FF0EA1EDFE0EA2EEFF0EA2EEFE0EA3EFFF0EA2EEFE0EA3 - EFFF0EA3EFFF0EA2EEFE0F9FE9FF233B48FE3E3C3CFF494747FE4A4848FF4947 - 47FE464A4DFF1993D1FF0FA3EEFE0FA3EFFF0FA3EEFE0FA3EFFF0FA3EEFE10A3 - EFFF10A3EEFE10A3EFFF257CA9FF494747FE4A4848FF4A4848FE494747FF3A39 - 39FE1B658CFF16587AFE1C2B33FF232323FE262525FF167DB2FF12A4EEFE12A4 - EFFF11A4EEFE10A2EDFF0F9FE8FE0D97DEFF2696CCFE636B6BFF494747FF4846 - 46FE494747FF484646FC0E0E0E68000000231414140300000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000C0C0C2B484646F7494747FF494747FF4C4B4BFF758E93FF1995 - D3FF0D99E1FF0D9FEAFF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF1379ADFF303030FF454343FF494747FF4947 - 47FF494747FF356178FF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0FA1EDFF395969FF494747FF4A4848FF494747FF454343FF2E37 - 3DFF109BE2FF0FA3EFFF0F9BE2FF1371A2FF154964FF109EE7FF0FA3EFFF0FA3 - EFFF0FA3EFFF0FA2EEFF0EA0EBFF0D9AE3FF0D92D5FF668690FF4C4B4BFF4947 - 47FF494747FF494747FF2D2C2CB4000000370101010C00000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000201F1F63494747FF484646FE494747FF535454FE689EB2FF0C93 - D7FF0D9BE4FE0EA1EBFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA3EFFF0EA1ECFE1E455AFF3B3939FE474545FF4846 - 46FE494747FF484646FF1C88C0FE0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3 - EFFF0DA2EEFE188FCCFF464647FF494747FE494747FF484646FE3E3C3CFF1E59 - 77FE0EA3EFFF0EA2EEFE0EA3EFFF0EA2EEFE0EA3EFFF0EA3EFFF0EA2EEFE0EA3 - EFFF0EA2EEFE0EA2EEFF0DA1ECFE0D9DE6FF0C94DAFE4D92B0FF525454FF4846 - 46FE494747FF484646FE444242F1070707550000001C1F1E1E02000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000067676701312F2F94494747FF494747FF494747FF5E6363FF4EA2C5FF0C95 - DBFF0D9DE7FF0EA1EDFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF1186C2FF2C2E2FFF434141FF4846 - 46FF494747FF494747FF3B5766FF0F9FE9FF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF2C6B8CFF484646FF494747FF494747FF464444FF343435FF1285 - BFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA2EDFF0D9EE8FF0D97DDFF3396C4FF5D6262FF4947 - 47FF494747FF494747FF494747FE222121980000003001010108000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000067676703393737BE494747FF484646FE494747FF6B7575FE349ECFFF0D97 - DEFF0D9EE8FE0EA2EDFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA2EEFF1B516CFE383737FF4745 - 45FE494747FF494747FF484646FE247CA9FF0DA2EEFE0EA3EFFF0DA2EEFE0EA3 - EFFF0F9EE7FE414B52FF494747FF484646FE484646FF424040FE26404DFF0EA1 - EDFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0DA2EEFE0EA3EFFF0DA2EEFE0D9FE9FF0D99E0FE1E94CFFF657274FF4947 - 47FE494747FF484646FE494747FF3F3D3DE201010145000000162A2929010000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000069696907464444DC494747FF494747FF4A4949FF778787FF1E97D2FF0D99 - E0FF0E9FEAFF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF1090D2FF292F33FF413F - 3FFF484646FF494747FF494747FF424E55FF119CE2FF0EA3EFFF0EA3EFFF0EA3 - EFFF1F81B4FF474646FF494747FF494747FF484646FF3A3838FF186B95FF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA2EEFF0EA0EAFF0D9AE2FF1393D4FF677F85FF4A48 - 48FF494747FF494747FF494747FF484646FE1717177D000000290B0B0B050000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000069696909484646F0494747FF484646FE4C4B4BFF7B9396FE1293D4FF0D9A - E2FF0DA0EAFE0EA2EEFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE185D80FF3534 - 34FE464444FF494747FF484646FE484646FF2C7093FE0EA3EFFF0DA2EEFE0EA2 - EEFF345E75FE484646FF494747FF484646FE454343FF2F3437FE1094D8FF0DA2 - EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA0EBFF0D9BE3FE0D92D6FF648793FF4B4A - 4AFE494747FF484646FE494747FF484646FE353434C90000003D000000100000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00006969690B484646FE494747FF494747FF4D4D4DFF78979FFF0F92D5FF0D9A - E3FF0EA0EBFF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0F98DEFF2534 - 3BFF3F3E3EFF484646FF494747FF494747FF45494DFF1693D4FF0EA3EFFF1397 - DBFF43474AFF494747FF494747FF484646FF3F3D3DFF205069FF0EA2EEFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA1ECFF0D9BE5FF0C92D7FF608C9DFF4C4B - 4BFF494747FF494747FF494747FF494747FF474545F90E0E0E67000000211414 - 1403000000000000000000000000000000000000000000000000000000000000 - 00006969690B494747FF494747FF494747FF4E4E4EFF769AA3FF0E92D5FF0D9A - E3FF0EA0EBFF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF166A - 96FF333232FF454444FF494747FF494747FF484646FF34637BFF0EA3EFFF227C - AAFF474545FF494747FF494747FF474545FF363536FF147CB2FF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA1ECFF0D9CE5FF0C93D7FF5E8EA1FF4D4C - 4CFF494747FF494747FF494747FF494747FF494747FF2B2929B0000000350100 - 000B000000000000000000000000000000000000000000000000000000000000 - 00006969690B484646FE494747FF484646FE4E4E4EFF7799A2FE0E92D5FF0D9A - E3FF0DA0EBFE0EA2EEFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0E9F - E9FE223A46FF3D3C3CFF484646FE494747FF484646FE474748FF1D89C1FE3561 - 77FF484646FE494747FF494747FF434141FE293942FF0EA0EAFE0EA3EFFF0DA2 - EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA1ECFF0D9CE5FE0C93D7FF5E8EA0FF4D4C - 4CFE494747FF484646FE494747FF484646FE494747FF464444F30504044F0000 - 001B1F1E1E010000000000000000000000000000000000000000000000000000 - 00006969690A484646FE494747FF494747FF4D4C4CFF7A989EFF0F92D5FF0D9A - E2FF0EA0EBFF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF1478ABFF302F2FFF454343FF484646FF494747FF494747FF3E5866FF454B - 4FFF494747FF494747FF484646FF3C3A3AFF1B6185FF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA2EFFF0EA1ECFF0D9BE4FF0C92D7FF628D9CFF4C4B - 4BFF494747FF494747FF494747FF494747FF494747FF494747FF201F1F940000 - 002F050505070000000000000000000000000000000000000000000000000000 - 000069696907484646F0494747FF484646FE4C4B4BFF7C9295FE1493D4FF0D9A - E1FF0DA0EAFE0EA2EEFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0EA3 - EEFE10A1EBFF25485BFF434141FE504F4FFF525151FE535151FF535151FE5351 - 51FF525050FE504E4EFF4B4949FF333638FE118ECDFF0DA2EEFE0EA3EFFF0DA2 - EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA0EBFF0D9BE3FE0E92D6FF678892FF4B4A - 4AFE494747FF484646FE494747FF484646FE494747FF484646FE3E3C3CDE0202 - 0246000000152928280100000000000000000000000000000000000000000000 - 000069696904484646DB494747FF494747FF4A4949FF768586FF2499D2FF0D98 - E0FF0E9FE9FF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF11A4EFFF1BA7EFFF22AA - F0FF26ACF0FF2992C7FF434243FF565555FF5B5959FF5B5959FF5B5959FF5B59 - 59FF5B5959FF5B5959FF545353FF395A6BFF23A9EFFF1CA8EFFF13A4EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA2EEFF0EA0EAFF0D9AE2FF1694D3FF697E84FF4A48 - 48FF494747FF494747FF494747FF494747FF494747FF494747FF484646FE1514 - 147A000000270B0B0B0500000000000000000000000000000000000000000000 - 0000000000003A3838BC494747FF484646FE494747FF697373FE3CA1CFFF0D97 - DDFF0D9EE8FE0EA2EDFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3 - EFFF0EA3EFFF0DA2EEFE0EA3EFFF13A5EFFE23ABF0FF2DAEF0FE2EAFF1FF2DAF - F0FE2EAFF1FF2EAFF1FF3A667DFE535151FF605E5EFE615F5FFF615F5FFE615F - 5FFF615F5FFE605E5EFF535151FF3586AFFE2EAFF1FF2DAFF0FE2DAFF0FF25AB - F0FE15A5EFFF0EA3EEFE0EA3EFFF0DA2EEFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0DA2EEFE0EA3EFFF0DA2EEFE0D9FE9FF0D98DFFE2496CDFF667172FF4947 - 47FE494747FF484646FE494747FF484646FE494747FF484646FE494747FF3533 - 33C60000003C0000001000000000000000000000000000000000000000000000 - 00000000000034323291494747FF494747FF494747FF5C6161FF58A5C4FF0C95 - DAFF0D9DE6FF0EA1ECFF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0FA3EFFF21AAF0FF34B1F1FF36B2F2FF36B2F1FF36B2F2FF36B2 - F1FF36B2F2FF36B2F2FF38A1D8FF4D5255FF616060FF676565FF676565FF6765 - 65FF676565FF636161FF4F5559FF36ADEAFF36B2F2FF36B2F1FF36B2F2FF36B2 - F1FF35B1F1FF25ABF0FF10A3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA1EDFF0D9EE7FF0D96DDFF3C98C2FF5C6060FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4745 - 45FA0C0B0B610000002100000003000000000000000000000000000000000000 - 0000000000002120205C494747FF484646FE494747FF525353FE73A1B0FF0D92 - D6FF0D9BE3FE0EA0EBFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0EA3 - EFFF0FA3EFFF2DAFF0FE3DB5F1FF3DB5F1FE3DB5F2FF3DB5F1FE3DB5F2FF3DB5 - F1FE3DB5F2FF3DB5F2FF3DB5F1FE487D98FF636161FE6C6B6BFF6D6B6BFE6D6B - 6BFF6D6B6BFE646363FF4A7991FF3DB5F1FE3DB5F2FF3DB5F1FE3DB5F2FF3DB5 - F1FE3DB5F2FF3DB5F1FE32B0F1FF12A4EFFE0EA3EFFF0EA3EFFF0DA2EEFE0EA3 - EFFF0DA2EEFE0EA2EEFF0DA1ECFE0D9CE5FF0C94D9FE5894ACFF515252FF4846 - 46FE494747FF484646FE494747FF484646FE494747FF484646FE494747FF4947 - 47FF2A2929AD000000350000000B000000000000000000000000000000000000 - 0000000000000E0D0D22484646F7494747FF494747FF4B4A4AFF788D8FFF2298 - D2FF0D98E0FF0D9FE9FF0EA2EDFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0FA3 - EFFF32B0F1FF46B8F2FF46B8F3FF46B8F2FF46B8F3FF46B8F2FF46B8F3FF46B8 - F2FF46B8F3FF46B8F3FF46B8F2FF48B1E7FF697075FF737272FF737272FF7372 - 72FF727070FF636464FF4AA2CFFF46B8F2FF46B8F3FF46B8F2FF46B8F3FF46B8 - F2FF46B8F3FF46B8F2FF46B8F3FF3AB3F1FF10A4EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA2EEFF0EA0EAFF0D99E1FF1092D4FF6E868BFF4B4A4AFF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF434141ED050505500000001A000000010000000000000000000000000000 - 00000000000002010101424141D1484646FE494747FF494747FE646C6CFF4EA3 - C8FF0C95DBFE0D9DE6FF0DA1ECFE0EA2EEFF0DA2EEFE0EA3EFFF0DA2EEFE27AC - F0FF4EBBF3FF4FBBF3FE4FBBF3FF4FBBF3FE4FBBF3FF4FBBF3FE4FBBF3FF4FBB - F3FE4FBBF3FF4FBBF3FF4FBBF3FE50B9F0FF737D82FE7A7979FF7A7979FE7A79 - 79FF757474FE61737DFF4FB9F0FF4FBBF3FE4FBBF3FF4FBBF3FE4FBBF3FF4FBB - F3FE4FBBF3FF4FBBF3FE4FBBF3FF4FBBF3FE31B0F1FF0EA3EFFF0DA2EEFE0EA3 - EFFF0DA2EEFE0EA1EDFF0D9EE7FE0C96DDFF359AC9FE616868FF494747FF4846 - 46FE494747FF484646FE494747FF484646FE494747FF484646FE494747FF4947 - 47FF484646FE1F1E1E900000002E000000070000000000000000000000000000 - 000000000000000000002A29297C494747FF494747FF494747FF525353FF79A0 - AAFF0F92D5FF0D9AE2FF0E9FEAFF0EA2EEFF0EA3EFFF0EA3EFFF11A4EFFF51BC - F3FF59BFF4FF59BFF4FF59BFF4FF59BFF4FF59BFF4FF59BFF4FF59BFF4FF59BF - F4FF59BFF4FF59BFF4FF59BFF4FF61ADD4FF807E7EFF818080FF818080FF807F - 7FFF777676FF6098B5FF59BFF4FF59BFF4FF59BFF4FF59BFF4FF59BFF4FF59BF - F4FF59BFF4FF59BFF4FF59BFF4FF59BFF4FF55BEF3FF18A7EFFF0EA3EFFF0EA3 - EFFF0EA2EEFF0EA0EBFF0D9BE4FF0D93D7FF6094A8FF505151FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF3D3B3BDD01010143000000140000000000000000000000000000 - 0000000000000000000012111123484646F9494747FF494747FF4A4949FF6F7A - 7BFF3EA1CFFF0C96DCFF0D9DE7FF0EA1ECFF0EA2EEFF0EA3EFFF26ACF0FF61C2 - F4FF62C2F4FF62C2F4FF62C2F4FF62C2F4FF62C2F4FF62C2F4FF62C2F4FF62C2 - F4FF62C2F4FF62C2F4FF62C2F4FF769EB4FF888787FF888787FF888787FF8685 - 85FF787A7BFF63BAE7FF62C2F4FF62C2F4FF62C2F4FF62C2F4FF62C2F4FF62C2 - F4FF62C2F4FF62C2F4FF62C2F4FF62C2F4FF62C2F4FF33B1F1FF0EA3EFFF0EA2 - EEFF0EA1EDFF0D9EE8FF0D97DEFF2797CDFF697779FF4A4848FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF484646FD15141477000000260000000500000000000000010000 - 00000000000000000000010101013C3A3AAF494747FF484646FE494747FF5456 - 56FF76A2AFFE1293D5FF0D99E1FE0D9FE9FF0DA1EDFE0EA2EEFF3AB3F1FE6BC6 - F5FF6BC6F5FF6BC6F5FE6BC6F5FF6BC6F5FE6BC6F5FF6BC6F5FE6BC6F5FF6BC6 - F5FE6BC6F5FF6BC6F5FF6CC4F1FE8A959BFF8F8E8EFE8F8E8EFF8F8E8EFE8A88 - 88FF7793A2FE6BC6F4FF6BC6F5FF6BC6F5FE6BC6F5FF6BC6F5FE6BC6F5FF6BC6 - F5FE6BC6F5FF6BC6F5FE6BC6F5FF6BC6F5FE6BC6F5FF49B9F2FF0DA2EEFE0EA2 - EEFF0DA0EAFE0D9BE3FF0D92D7FE5F96ABFF545656FE494747FF4A4848FF4C4B - 4BFE4C4C4CFF4C4C4CFE4C4C4CFF4C4C4CFE4C4C4CFF4C4B4BFE4B4A4AFF4947 - 47FF484646FE494747FF323131C30000003B0000000F00000000000000010000 - 00000000000000000000000000002524243E484646FB494747FF494747FF4A49 - 49FF6C7777FF4AA3CAFF0C94DAFF0D9CE5FF0EA0EBFF0EA2EEFF43B7F2FF75CB - F6FF75CBF6FF75CAF6FF75CBF6FF75CAF6FF75CBF6FF75CAF6FF86A2B1FF919E - A6FF929FA6FF929FA6FF929EA4FF979696FF979696FF979696FF969595FF8D8C - 8CFF79B4D2FF75CBF6FF75CBF6FF75CAF6FF75CBF6FF75CAF6FF75CBF6FF75CA - F6FF75CBF6FF75CAF6FF75CBF6FF75CAF6FF75CBF6FF53BDF3FF0EA2EEFF0EA1 - ECFF0D9DE6FF0C96DCFF3299CAFF677274FF4A4949FF4A4848FF53656DFF6C8D - 9BFF70929FFF70929FFF70929FFF70929FFF70929FFF6F919EFF697B82FF4F4F - 4FFF494747FF494747FF474545F80B0B0B5F0000002000000002000000010000 - 000000000000000000000000000000000000484646B8484646FE494747FF4947 - 47FF515151FE7C979CFF2198D2FE0C97DEFF0D9DE7FE0EA1ECFF3BB3F1FE7FCE - F6FF7FCEF6FF7FCEF6FE7FCEF6FF7FCEF6FE7FCEF6FF7FCEF6FE92A1AAFF9E9D - 9DFE9F9E9EFF9F9E9EFF9E9D9DFE9F9E9EFF9E9D9DFE9F9E9EFF9C9B9BFE8E97 - 9BFF80CBF2FE7FCEF6FF7FCEF6FF7FCEF6FE7FCEF6FF7FCEF6FE7FCEF6FF7FCE - F6FE7FCEF6FF7FCEF6FE7FCEF6FF7FCEF6FE7FCEF6FF4CBAF2FF0DA1ECFE0D9E - E8FF0D98E0FE1693D3FF6C8F99FE505050FF494747FE4A4949FF5A8CA1FF7FD0 - F6FE80D1F7FF7FD0F6FE80D1F7FF7FD0F6FE80D1F7FF7FD0F6FE82ADC0FF5456 - 56FF484646FE494747FF484646FE282727A9000000340000000A000000010000 - 000000000000000000000000000000000000748A8A33484646F7494747FF4947 - 47FF494747FF5C6060FF71A5B7FF1294D5FF0D99E0FF0D9EE8FF1EA7EDFF86D0 - F6FF89D2F7FF89D2F7FF89D2F7FF89D2F7FF89D2F7FF89D2F7FF9AA9B0FFA5A4 - A4FFA6A5A5FFA6A5A5FFA6A5A5FFA6A5A5FFA6A5A5FFA5A4A4FF9F9F9FFF90B1 - C3FF89D2F7FF89D2F7FF89D2F7FF89D2F7FF89D2F7FF89D2F7FF89D2F7FF89D2 - F7FF89D2F7FF89D2F7FF89D2F7FF89D2F7FF88D1F7FF2FAEEFFF0D9FE9FF0D9A - E2FF0E93D6FF5A9AB4FF5B5F5FFF494747FF494747FF4A4848FF566F79FF78CB - F1FF80D0F6FF8BB5C4FF758C92FF697C82FF687B81FF687B81FF606B6EFF4D4D - 4DFF494747FF494747FF494747FF424141EB0404044D00000018000000010000 - 00000000000000000000000000000000000000000000626F6F91494747FF4947 - 47FF484646FE4B4A4AFF687272FE5FA7C3FF0D92D7FE0D99E1FF0D9EE8FE65C3 - F3FF92D5F7FF92D5F7FE92D5F8FF92D5F7FE92D5F8FF92D5F7FEA0ADB4FFA8A7 - A7FEA8A8A8FFA8A8A8FFA8A7A7FEA8A8A8FFA8A7A7FEA8A7A7FFA1A1A2FE94CC - E9FF92D5F7FE92D5F8FF92D5F8FF92D5F7FE92D5F8FF92D5F7FE92D5F8FF92D5 - F7FE92D5F8FF92D5F7FE92D5F8FF92D5F7FE77CAF4FF11A0E9FF0D9AE3FE0C93 - D8FF479CC1FE656F6FFF4B4949FE494747FF484646FE494747FF4E4D4DFF618D - 9FFE7DCFF5FF82CCEEFE7A8C91FF535454FE4B4949FF4A4949FE4A4848FF4947 - 47FF484646FE494747FF484646FE484646FE1D1C1C8B00000027000000040000 - 00000000000000000000000000000000000000000000ABE2E20D4E4F4FDA4947 - 47FF494747FF494747FF4D4C4CFF707D7EFF52A5C8FF0D93D7FF0D99E1FF1FA5 - EAFF8DD2F6FF9DD9F8FF9DD9F8FF9DD9F8FF9DD9F8FF9DD9F8FFA3ACB1FFA5A4 - A4FFA5A4A4FFA5A4A4FFA5A4A4FFA5A4A4FFA5A4A4FFA5A4A4FFA2B0B8FF9DD9 - F7FF9DD9F8FF9DD9F8FF9DD9F8FF9DD9F8FF9DD9F8FF9DD9F8FF9DD9F8FF9DD9 - F8FF9DD9F8FF9DD9F8FF9DD9F8FF97D6F7FF2CABEBFF0D9AE3FF0C94D9FF3B9A - C6FF6C7A7BFF4C4C4CFF494747FF494747FF494747FF494747FF494747FF5152 - 52FF66A3BDFF7FD0F6FF84C4E2FF6F7A7CFF4E4D4DFF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF383737CF000000360000000A0000 - 000000000000000000000000000000000000000000000000000092BABA3D4846 - 46F6484646FE494747FF494747FE4F4F4FFF748384FE52A5C9FF0D92D6FE0D99 - E0FF31ACEAFF9DD8F7FEA6DCF8FFA6DDF8FEA6DDF9FFA6DDF8FEA8C9D9FFA8C6 - D5FEA8C6D5FFA8C6D5FFA8C6D5FEA8C6D5FFA8C6D5FEA8C6D5FFA7D1E7FEA6DD - F9FFA6DDF8FEA6DDF9FFA6DDF9FFA6DDF8FEA6DDF9FFA6DDF8FEA6DDF9FFA6DD - F8FEA6DDF9FFA6DCF8FEA2DAF7FF45B4EDFE0D99E1FF0C93D8FF3C9BC7FE6D7F - 81FF4E4E4EFE494747FF484646FE494747FF484646FE494747FF494747FF4948 - 48FE555C5EFF6EB8D8FE80D0F6FF86B8CEFE636A6AFF4B4A4AFE494747FF4947 - 47FF484646FE494747FF484646FE494747FF474545F90707074B000000100000 - 0000000000000000000000000000000000000000000000000000000000007891 - 916A494747FE494747FF494747FF494747FF4E4E4EFF707D7DFF62A7C2FF1293 - D5FF0C97DDFF2EA9E8FF96D5F5FFB0E0F8FFB0E0F9FFB0E1FAFFB0E1FAFFB0E1 - FAFFB0E1FAFFB0E1FAFFB0E1FAFFB0E1FAFFB0E1FAFFB0E1FAFFB0E1FAFFB0E1 - FAFFB0E1FAFFB0E1FAFFB0E1FAFFB0E1FAFFB0E1FAFFB0E1FAFFB0E1FAFFB0E0 - F9FFB0E0F9FFA0D9F6FF3DAFEAFF0D98DFFF0F93D6FF4C9DC1FF6C797AFF4E4D - 4DFF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF4A4949FF596A70FF75C5E9FF81D1F7FF84A9B8FF5C6060FF4A4848FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF17161674000000140000 - 000000000000000000000000000000000000000000000000000000000000B9F8 - F80138586992494747FE494747FF494747FF494747FF4D4C4CFF677171FF72A5 - B6FF2398D2FF0C94DAFF1A9FE2FF6FC4EFFFB2E1F8FFB9E3F9FFB9E4FAFFB9E4 - FAFFB9E4FAFFB9E4FAFFB9E4FAFFB9E4FAFFB9E4FAFFB9E4FAFFB9E4FAFFB9E4 - FAFFB9E4FAFFB9E4FAFFB9E4FAFFB9E4FAFFB9E4FAFFB9E4FAFFB9E4FAFFB6E2 - F8FF7DCAF1FF22A3E4FF0C95DBFF1995D2FF629DB3FF656F6FFF4D4C4CFF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF4C4B4BFF67828DFF9CD9F6FF9FD9F5FF879AA1FF545555FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF2423238B000000120000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000E88C50638596BA1484646FE494747FF484646FE494747FF4B4949FE5B5F - 5FFF7C9599FF4EA4C9FE1293D4FF0C95DBFE28A5E4FF73C5EFFEB1DFF7FFC2E7 - FAFEC3E7FAFFC3E7FAFFC2E7FAFEC3E7FBFFC2E8FAFEC3E8FBFFC2E8FAFEC3E8 - FBFFC2E7FAFEC3E7FBFFC3E7FBFFC2E7FAFEC3E7FAFFB6E2F8FE7FCAF1FF32A9 - E6FE0D96DDFF0F93D5FE3F9DC8FF739198FE595E5EFF4A4949FF494747FE4947 - 47FF484646FE494747FF484646FE494747FF484646FE494747FF494747FF4846 - 46FE494747FF494747FE4F4F4FFF7B9EACFEADE1F9FFACD9EEFE727B7CFF4C4C - 4CFF484646FE494747FF484646FE494747FF484646FE252424890000000D0000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000E88C60638596A9C494747FD494747FF494747FF494747FF4947 - 47FF505050FF6A7475FF77A1ACFF42A2CDFF1293D5FF0C95DAFF179CE0FF42B0 - E8FF75C6F0FFA0D9F5FFBCE4F8FFC5E8FAFFC9E9FAFFCBEAFAFFCBEAFAFFC9E9 - FAFFC6E8FAFFBFE5F9FFA6DBF6FF7CC9F0FF4BB4EAFF1C9FE1FF0D95DBFF0F93 - D5FF379CCCFF6B9BABFF687272FF505050FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF4A4949FF4D4D - 4DFF4D4C4CFF494848FF494747FF545758FF9CC9DDFFB6E4FAFF95ACB4FF5355 - 55FF494747FF494747FF494747FF494747FF494747FF1C1B1B6E000000070000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000E88C50338596B7D484646FA494747FF484646FE4947 - 47FF494747FF4A4949FE535555FF6D7878FE789EA7FF54A4C6FE279AD2FF0E92 - D5FE0C94DAFF0D96DDFF129ADFFE22A2E3FF2EA7E5FE35AAE6FF36ABE6FE30A8 - E5FF24A3E3FE149BE0FF0D97DDFF0C94DAFE0C92D6FF2198D2FE4AA0C6FF7099 - A6FE6B7677FF535555FE4A4949FF494747FE494747FF494747FF484646FE4947 - 47FF484646FE494747FF484646FE494747FF484646FE4A4848FF64747AFF8DA5 - AFFE7F8F94FF525353FE494747FF4B4A4AFE84A1ACFFBFE7FAFEA5BEC9FF585B - 5BFF484646FE494747FF484646FE494747FF484646FE0F0E0E38000000020000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000296A8B4D47494BE7494747FF4947 - 47FF494747FF494747FF494747FF4A4848FF515252FF616868FF76888AFF769F - ABFF5CA4C0FF43A1CCFF2C9BD0FF1C96D3FF1594D4FF1394D4FF1394D4FF1594 - D4FF1A96D3FF299AD1FF3E9FCCFF56A1BFFF6F9CAAFF748689FF616767FF5151 - 51FF4A4848FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF4A4848FF7B939DFFC7EA - FBFFB7D2DFFF676E6EFF4C4C4CFF505151FF98B7C3FFC7EAFBFFA5BCC5FF5759 - 59FF494747FF494747FF494747FF494747FF3F3D3DCF0101010D000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000097CDD11E5C6666AE4947 - 47FE494747FF484646FE494747FF484646FE494747FF494747FE4B4A4AFF5151 - 51FE5A5F5FFF666F6FFF728080FE798D8FFF799397FE77959CFF77959CFE7792 - 97FF788C8EFE717F80FF666F6FFF5A5E5EFE515151FF4B4A4AFE494747FF4947 - 47FE494747FF484646FE494747FF484646FE494747FF494747FF484646FE4947 - 47FF484646FE494747FF484646FE494747FF484646FE494747FF606B6FFFC7E9 - F8FECEECFAFFA4B9BFFE778588FF8CA0A6FEC9E9F8FFCFEDFBFE8B989CFF5050 - 50FF484646FE494747FF484646FE484646FD1F1E1E6100000002000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000008CB1B1015D67 - 674D494747D0494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF4A4848FF4B4949FF4B4B4BFF4C4C4CFF4C4C4CFF4C4B - 4BFF4B4949FF4A4848FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF4D4D4DFF8498 - 9FFFCFEAF7FFD7F0FCFFD6EFFBFFD7F0FCFFD4EEFAFFA7BAC1FF5D6262FF4A48 - 48FF494747FF494747FF494747FF393838B20302020600000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000494747084846465F494747D0484646FE494747FF484646FE494747FF4846 - 46FE494747FF494747FF484646FE494747FF484646FE494747FF484646FE4947 - 47FF484646FE494747FF494747FF484646FE494747FF484646FE494747FF4846 - 46FE494747FF484646FE494747FF484646FE494747FF494747FF484646FE4947 - 47FF484646FE494747FF484646FE494747FF484646FE494747FF494747FF4E4E - 4EFE6A7477FF92A2A8FE9EADB2FF98A9AEFE7C888AFF5A5E5EFE4B4A4AFF4947 - 47FF484646FE494747FF434141D00C0C0C160000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000004947473E4947479D494747E6494747FE4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF4A4848FF4C4B4BFF4E4D4DFF4D4D4DFF4B4A4AFF494747FF494747FF4947 - 47FF484646FC3D3C3CA618181811000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000004947470C4947473F4947 - 477E494747B6494747E3494747F8494747FB494747FD494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FD494747F24846 - 46B2444242424442420200000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000D1D0D00DD1D1D127D1D0D036D1D1D13FD1D0D03FD1D1 - D13FD1D0D03FD1D1D13FD1D1D13FD1D0D03FD1D1D13FD1D0D03FD1D1D13FD1D0 - D03FD1D1D13FD1D0D03FD1D1D13FD1D0D03FD1D1D13FD1D1D13FD1D0D03FD1D1 - D13FD1D0D03FD1D1D13FD1D0D03FD1D1D13FD1D0D03FD1D1D13FD1D1D13FD1D0 - D03FD1D1D13FD1D0D03FD1D1D13FD1D0D03FD1D1D13FD1D0D030D1D1D10A0000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000000000000000000000FFFF - FFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF00 - 0000FFFFFFFFFFFFFFFFFF000000FFFFFFC007FFFFFFFF000000FFFFFC00007F - FFFFFF000000FFFFF000000FFFFFFF000000FFFF80000003FFFFFF000000FFFF - 00000000FFFFFF000000FFFC000000007FFFFF000000FFF8000000003FFFFF00 - 0000FFF0000000000FFFFF000000FFE00000000007FFFF000000FFC000000000 - 03FFFF000000FF800000000001FFFF000000FF000000000000FFFF000000FE00 - 0000000000FFFF000000FC0000000000007FFF000000FC0000000000003FFF00 - 0000F80000000000003FFF000000F80000000000001FFF000000F00000000000 - 001FFF000000F00000000000000FFF000000E00000000000000FFF000000E000 - 000000000007FF000000C000000000000007FF000000C000000000000007FF00 - 0000C000000000000003FF000000C000000000000003FF000000C00000000000 - 0001FF0000008000000000000001FF0000008000000000000000FF0000008000 - 000000000000FF0000008000000000000000FF00000080000000000000007F00 - 000080000000000000007F00000080000000000000003F000000800000000000 - 00003F00000080000000000000001F00000080000000000000001F000000C000 - 0000000000001F000000C0000000000000000F000000C0000000000000000F00 - 0000C00000000000000007000000C00000000000000007000000E00000000000 - 000007000000E00000000000000002000000E00000000000000002000000F000 - 00000000000000000000F80000000000000000000000F8000000000000000000 - 0000FC0000000000000000000000FC0000000000000000000000FE0000000000 - 000000000000FF0000000000000000000000FF0000000000000000000000FF80 - 00000000000000000000FFC000000000000000000000FFE00000000000000000 - 0000FFF800000000000001000000FFFC00000000000001000000FFFE00000000 - 000003000000FFFF80000000000007000000FFFFF000000000000F000000FFFF - FC00000000001F000000FFFFFFE000000000FF000000FFFFFFFFFFFFFFFFFF00 - 0000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFF - FFFFFF000000FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFF0000002800 - 0000400000008000000001002000000000000042000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000020000 - 00050000000A0000001000000015000000190000001B0000001B0000001A0000 - 0017000000120000000C00000007000000030000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000020000000900000015000000230000 - 00310000003C00000044000000490000004C0000004D0000004E0000004D0000 - 004B000000470000004000000036000000280000001A0000000C000000040000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000121111040000001000000023000000380202024A131212772322 - 22A1323030C13A3939D9444242E9474545F4474545F4474545F4464444F0403E - 3EE1343333CC292828B01A19198B0707075F0000004C0000003E0000002A0000 - 0015090808072D2C2C0100000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000001616 - 160300000010000000280101014218171780323030C3464444F5494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF484646FD3A3939D6201F1F9B0605055C0000 - 0047000000300000001709080806000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000040404090000 - 00220303034422212198414040E9494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF474545F72D2B - 2BB70A0A0A68000000460000002B0000000F1B1A1A0200000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000475F5F0200000012000000331D1C - 1C88424040EA494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF4B4A4AFF4E4E4EFF515252FF545656FF555858FF545656FF525353FF4E4E - 4EFF4B4A4AFF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF474545F92A2929B10404045A0000003D0000001C232F2F05000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000272F2F040000001B0A0A0A51383737CE4947 - 47FF494747FF494747FF494747FF494747FF4A4848FF505151FF5F6565FF6A7E - 82FF5F8B9BFF5594AEFF4D99BBFF4B9DC2FF4A9EC5FF499DC3FF4B99BCFF5093 - B0FF598A9EFF667E85FF606767FF515252FF4A4949FF494747FF494747FF4947 - 47FF494747FF494747FF424040EB1616168200000048000000260B0F0F090000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000002F2F2F050000002018181876454343F2494747FF4947 - 47FF494747FF494747FF4C4B4BFF5A5E5EFF6B8389FF5497B3FF3D9FCEFF289D - D8FF2EA2DEFF32A6E1FF35A8E3FF36A9E4FF37A9E4FF37A9E4FF35A8E3FF34A7 - E2FF2FA3DFFF279DDAFF339DD0FF4A95B7FF62838EFF5C6161FF4C4C4CFF4947 - 47FF494747FF494747FF494747FF484646FE292828AD0101014F0000002C0000 - 000B000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000002F2F2F040000002024232392484646FD494747FF494747FF4947 - 47FF4A4949FF5A5E5EFF698A94FF479EC5FF289DD9FF2EA4E0FF33A9E5FF37AC - E8FF3AAFEBFF3CB1ECFF3DB2EDFF3EB2EEFF3FB3EEFF3FB3EEFF3EB2EDFF3DB1 - EDFF3CB0EBFF39AEE9FF36AAE6FF31A6E1FF269DDAFF399AC9FF5C899AFF5C61 - 62FF4B4A4AFF494747FF494747FF494747FF494747FF363434CB030303560000 - 002E00080C0B0000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00002F3F3F030000001D27262698494747FF494747FF494747FF494747FF5051 - 51FF6B7E81FF4C9CC0FF269DD9FF2CA4E2FF32AAE7FF36AEEBFF39B1EEFF3AB2 - EFFF3BB3F0FF3CB4F1FF3DB5F1FF3DB5F1FF3EB5F1FF3EB5F1FF3EB5F1FF3EB5 - F1FF3EB4F1FF3DB4F0FF3CB2EEFF39B0ECFF36ACE9FF30A7E4FF259EDBFF3998 - C5FF637F87FF525353FF494747FF494747FF494747FF494747FF3A3838D60504 - 04580000002C0B0F0F0800000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000005F7F - 7F010000001625242490494747FF494747FF494747FF494848FF585B5BFF6892 - A1FF2D9CD3FF27A1DFFF2DA8E7FF31ADECFF34B0EEFF36B1F0FF37B2F1FF38B3 - F1FF38B3F2FF38B3F2FF39B3F2FF39B3F2FF3AB4F2FF3AB4F2FF3AB4F2FF3AB4 - F2FF3BB4F2FF3BB4F2FF3AB4F1FF3AB3F1FF39B2EFFF37AFEDFF32ABE9FF2BA4 - E1FF249BD6FF538FA9FF5B6060FF4A4848FF494747FF494747FF494747FF3837 - 37D30303035100000025232F2F05000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000D1A191970484646FD494747FF494747FF4A4848FF5F6464FF5E9BB3FF229B - D8FF26A3E3FF2BA9EAFF2FADEEFF30AFF0FF31B0F1FF32B0F1FF32B1F1FF33B1 - F1FF33B1F1FF33B1F1FF34B1F1FF34B1F1FF35B1F1FF35B2F1FF35B2F2FF36B2 - F2FF36B2F2FF36B2F2FF37B2F2FF37B2F2FF37B2F1FF36B1F1FF35B0EFFF31AC - EBFF2BA7E5FF229CDBFF4295BBFF60696AFF4A4949FF494747FF494747FF4947 - 47FF333131C4000000480000001B272A2A020000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000171F1F050D0C - 0C43464444F3494747FF494747FF4A4848FF606666FF569DBBFF1D9ADAFF24A3 - E5FF28A9EBFF2AACEEFF2BAEF0FF2CAEF1FF2CAFF1FF2DAFF1FF2DAFF1FF2EAF - F1FF2EAFF1FF2EAFF1FF2EAFF1FF2FAFF1FF2FAFF1FF2FB0F1FF30B0F1FF30B0 - F1FF30B0F1FF31B0F1FF31B0F1FF31B0F1FF32B0F1FF32B0F1FF32B0F1FF31AF - EFFF2FADEDFF29A7E7FF219EDDFF3895C2FF616B6DFF4A4949FF494747FF4947 - 47FF494747FF242323A10000003C0000000F0000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000242323010202021A3C3A - 3AD2494747FF494747FF494747FF5B6060FF5B9DB8FF1A99D9FF20A2E5FF24A8 - ECFF26ABEFFF27ACF0FF27ACF1FF27ACF1FF28ACF1FF28ADF1FF28ADF1FF28AD - F1FF29ADF1FF29ADF1FF29ADF1FF29ADF1FF2AADF1FF2AAEF1FF2AAEF1FF2BAE - F1FF2BAEF1FF2BAEF1FF2CAEF1FF2CAEF1FF2DAFF1FF2DAFF1FF2DAFF1FF2DAF - F0FF2DAEF0FF2BABEDFF26A6E8FF1F9DDDFF3A95BFFF5E6565FF494848FF4947 - 47FF494747FF484646FB101010710000002A0908080500000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000004040409242323854947 - 47FF494747FF494747FF545555FF6799AAFF1998D8FF1BA0E4FF1FA6EBFF21A9 - EEFF22AAF0FF22AAF0FF22ABF0FF23ABF0FF23ABF0FF23ABF0FF24ABF0FF24AB - F0FF24ABF0FF25ABF0FF25ABF0FF25ACF0FF25ACF0FF26ACF0FF26ACF1FF26AC - F1FF26ACF1FF27ACF1FF28AAEDFF4B7185FF3D8BB2FF2CA7E6FF28ADF1FF28AD - F1FF28ADF0FF28ACF0FF27AAEDFF22A5E7FF1B9ADBFF4993B3FF565A5AFF4947 - 47FF494747FF494747FF3D3C3CDE010101470000001500000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000010707072B474545F24947 - 47FF494747FF4C4C4CFF708A8FFF2098D3FF179DE1FF1BA4EAFF1CA7EEFF1DA7 - EEFF314855FF4C4A4AFF555353FF555353FF555353FF3484ADFF1FA9F0FF1FA9 - F0FF20A9F0FF20A9F0FF20AAF0FF20AAF0FF21AAF0FF21AAF0FF21AAF0FF22AA - F0FF22AAF0FF22AAF0FF338CB9FF585656FF595757FF57595BFF487287FF3591 - C0FF25A9ECFF24ABF0FF24AAEFFF22A8ECFF1EA2E5FF1897D8FF5C899AFF4E4E - 4EFF494747FF494747FF494747FF201F1F970000002E09080806000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000072E2D2D9E494747FF4947 - 47FF494747FF646B6BFF409EC9FF1499DDFF16A1E8FF18A5EEFF18A7EFFF19A7 - F0FF1E84B8FF3C3A3AFF4F4D4DFF525050FF525050FF4D565CFF1DA2E5FF1BA8 - F0FF1BA8F0FF1BA8F0FF1BA8F0FF1CA8F0FF1CA8F0FF1CA8F0FF1CA8F0FF1DA8 - F0FF1DA8F0FF1DA8F0FF456577FF555353FF555353FF555353FF565454FF5654 - 54FF525A5FFF407794FF2B95CBFF1FA8EEFF1DA5EAFF199EE2FF2396CEFF6371 - 74FF4A4848FF494747FF494747FF434242EE0303034900000013000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000007070725474545F5494747FF4947 - 47FF505151FF6998A9FF1094D7FF129EE5FF14A3ECFF15A5EFFF15A5EFFF16A6 - EFFF16A6EFFF264D61FF444242FF4E4D4DFF4F4D4DFF4F4D4DFF357394FF17A6 - F0FF17A6F0FF17A6F0FF18A6F0FF18A7F0FF18A7F0FF18A7F0FF18A7F0FF19A7 - F0FF19A7F0FF2197D4FF504E4EFF525050FF525050FF525050FF525151FF5351 - 51FF535151FF525050FF454343FF2282B3FF1BA6EDFF18A2E8FF1498DCFF4892 - B3FF525454FF494747FF494747FF494747FF1F1E1E92000000261B1A1A030000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000327262684494747FF494747FF4947 - 47FF687272FF329CCEFF0F99DFFF11A0E9FF12A3EDFF12A4EFFF12A4EFFF12A4 - EFFF13A4EFFF168DCAFF323233FF494747FF4D4B4BFF4D4B4BFF4B4C4EFF1C97 - D6FF14A5EFFF14A5EFFF15A5EFFF15A5EFFF15A5EFFF15A5EFFF15A5EFFF16A6 - EFFF16A6EFFF347090FF4E4D4DFF4F4D4DFF4F4D4DFF4C4A4AFF494747FF4E4C - 4CFF504E4EFF4D4B4BFF343F46FF18A3EBFF17A6EFFF16A3ECFF139CE3FF1794 - D3FF65787CFF4A4848FF494747FF494747FF3D3C3CDD0000003B0000000B0000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000009424040DC494747FF494747FF4E4E - 4EFF6C97A5FF0D92D7FF0E9CE5FF0FA1ECFF0FA3EEFF10A3EFFF10A3EFFF10A4 - EFFF10A4EFFF10A4EFFF1D5673FF3D3B3BFF4A4848FF4B4949FF4B4949FF3764 - 7BFF11A4EFFF11A4EFFF11A4EFFF12A4EFFF12A4EFFF12A4EFFF12A4EFFF12A4 - EFFF14A0E8FF464E52FF4C4A4AFF4D4B4BFF4B4949FF3B3939FF2C2B2BFF3534 - 34FF413F3FFF3F3E3EFF216385FF15A5EFFF14A5EFFF14A4EDFF119FE7FF0E96 - DBFF4B90AFFF505151FF494747FF494747FF494747FF100F0F690000001C2927 - 2701000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000013121239494747FF494747FF494747FF5D62 - 62FF459FC7FF0D97DDFF0D9EE9FF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF1094D8FF2C3033FF454343FF4A4848FF4A4848FF4947 - 47FF1D8AC2FF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EFFF10A3EFFF10A3EFFF10A3 - EFFF247FAEFF4A4848FF4A4848FF4A4848FF454343FF27485AFF14709FFF1A3A - 4BFF222121FF242425FF1492D2FF12A4EFFF11A4EFFF11A3EEFF0FA0EAFF0E99 - E1FF2195CEFF616969FF494747FF494747FF494747FF2E2D2DB8000000330908 - 0807000000000000000000000000000000000000000000000000000000000000 - 000000000000000000003F3F3F012726267F494747FF494747FF4A4848FF7383 - 85FF1A96D3FF0D9AE2FF0EA0EBFF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF186085FF383737FF484646FF494747FF4947 - 47FF3D5663FF0EA1ECFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF395A6CFF4A4848FF4A4848FF494747FF3C3A3AFF1775A5FF0FA3EFFF0FA3 - EFFF1189C6FF136792FF0FA3EFFF0FA3EFFF0FA3EFFF0FA3EEFF0EA1ECFF0D9C - E5FF0C92D7FF618490FF4A4949FF494747FF494747FF474545F7060606510000 - 0015000000000000000000000000000000000000000000000000000000000000 - 000000000000000000003F3F3F02383737B9494747FF494747FF4D4D4DFF6B98 - A7FF0C93D8FF0D9CE6FF0EA1EDFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0E9CE5FF27343BFF424040FF484646FF4947 - 47FF484646FF247DABFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF1692 - D2FF474545FF494747FF494747FF464444FF2E3539FF0E9DE6FF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF0D9E - E8FF0C96DCFF4A91B1FF4F4F4FFF494747FF494747FF494747FF2422229D0000 - 002B121111040000000000000000000000000000000000000000000000000000 - 000000000000000000003F3F3F05474545E6494747FF494747FF545656FF569F - BDFF0C96DCFF0D9EE8FF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF156E9CFF353434FF474545FF4947 - 47FF494747FF424E54FF109DE5FF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF2B6D - 90FF484646FF494747FF484646FF403E3EFF1E5978FF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF0E9F - EAFF0D98DFFF3397C6FF585B5BFF494747FF494747FF494747FF413F3FE70101 - 01420000000F0000000000000000000000000000000000000000000000000000 - 000000000000000000004B4A4A14494747FF494747FF494747FF5D6262FF43A0 - CAFF0D97DFFF0E9FE9FF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA0EBFF233B47FF403E3EFF4846 - 46FF494747FF484646FF2C7093FF0EA3EFFF0EA3EFFF0EA3EFFF0EA0EBFF404C - 53FF494747FF494747FF474545FF363535FF1287C2FF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF0EA0 - EBFF0D9AE2FF1F96D1FF626A6AFF494747FF494747FF494747FF494747FF1918 - 1882000000231B1A1A0200000000000000000000000000000000000000000000 - 000000000000000000005150502F494747FF494747FF494747FF676F6FFF319E - D1FF0D99E1FF0EA0EAFF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF137BB1FF323131FF4644 - 44FF494747FF494747FF46484AFF1596D8FF0EA3EFFF0EA3EFFF1D84B9FF4846 - 46FF494747FF494747FF444242FF27404DFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA1 - ECFF0D9BE4FF1092D5FF68787AFF494747FF494747FF494747FF494747FF3836 - 36CE0000003A0404040A00000000000000000000000000000000000000000000 - 0000000000000000000051515141494747FF494747FF494747FF6E7A7AFF259A - D3FF0D9AE2FF0EA0EBFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF1F4559FF3E3C - 3CFF484646FF494747FF494747FF33647DFF0EA3EFFF0EA3EFFF31627BFF4846 - 46FF494747FF484646FF3C3B3BFF196B95FF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA1 - EDFF0D9CE5FF0C92D6FF678086FF494747FF494747FF494747FF494747FF4846 - 46FE0E0D0D650000001B29272701000000000000000000000000000000000000 - 0000000000000000000052515143494747FF494747FF494747FF737F7FFF1F98 - D3FF0D9AE2FF0EA0EBFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF1189C6FF2F2E - 2FFF454343FF494747FF494747FF484646FF1B8BC5FF0F9FE8FF434649FF4947 - 47FF494747FF464545FF313335FF0F98DEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA1 - EDFF0D9CE5FF0C92D6FF65828BFF494848FF494747FF494747FF494747FF4947 - 47FF2D2B2BB50000003209080807000000000000000000000000000000000000 - 0000000000000000000052515142494747FF494747FF494747FF727F7FFF1F98 - D3FF0D9AE2FF0EA0EBFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF1C52 - 6EFF3B3A3AFF484646FF494747FF494747FF3C5867FF1F85BAFF484646FF4947 - 47FF494747FF424040FF215069FF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA1 - EDFF0D9CE5FF0C92D6FF66838BFF494848FF494747FF494747FF494747FF4947 - 47FF464444F50505054F00000015000000000000000000000000000000000000 - 0000000000000000000051515140494747FF494747FF494747FF6E7979FF289B - D3FF0D99E1FF0EA0EBFF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0F93 - D7FF2B2F32FF444242FF494747FF494747FF494747FF41525BFF494747FF4947 - 47FF484646FF383737FF147DB3FF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA1 - EDFF0D9CE5FF0C92D6FF698085FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF2221219A0000002A121111040000000000000000000000000000 - 000000000000000000005151512C494747FF494747FF494747FF666E6EFF369F - D0FF0D99E0FF0EA0EAFF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF10A3EFFF16A6 - EFFF256789FF464444FF555353FF575555FF585656FF575555FF575555FF5553 - 53FF4F4E4EFF334148FF11A2ECFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA1 - ECFF0D9BE3FF1293D4FF6A7779FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF403E3EE5000000400000000F0000000000000000000000000000 - 000000000000000000004C4C4C10494747FF494747FF494747FF5C6161FF49A2 - C9FF0D97DEFF0D9FE9FF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF17A6EFFF23ABF0FF29ADF0FF2AAD - F1FF2AA6E6FF404B50FF585757FF5E5C5CFF5E5C5CFF5E5C5CFF5E5C5CFF5E5C - 5CFF555353FF367494FF2AADF1FF25ABF0FF1BA7EFFF0FA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF0EA0 - EBFF0D99E1FF2497D0FF626969FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF1716167D000000221B1A1A0200000000000000000000 - 0000000000000000000000000000484646E7494747FF494747FF535555FF5EA1 - BCFF0C95DBFF0D9EE7FF0EA2EDFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF16A6EFFF2BAEF1FF32B0F1FF32B0F1FF32B0F1FF32B0 - F1FF32B0F1FF3982A8FF545353FF636161FF646262FF646262FF646262FF6361 - 61FF525252FF34A1D8FF32B0F1FF32B0F1FF32B0F1FF2EAFF1FF1BA8F0FF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF0D9F - E9FF0D98DFFF3A98C4FF575A5AFF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF363535CB000000390404040A00000000000000000000 - 00000000000000000000000000003A3939B7494747FF494747FF4D4C4CFF759A - A5FF0C92D6FF0D9CE5FF0EA1ECFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF22AAF0FF3AB4F1FF3BB4F2FF3BB4F2FF3BB4F2FF3BB4F2FF3BB4 - F2FF3BB4F2FF3BB2EFFF4E6069FF666565FF6B6969FF6B6969FF6B6969FF6665 - 65FF4D6A79FF3BB4F2FF3BB4F2FF3BB4F2FF3BB4F2FF3BB4F2FF3BB4F2FF2BAE - F0FF0FA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EDFF0D9E - E7FF0C95DBFF5393AEFF4F4F4FFF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF484646FD0C0C0C620000001A00000001000000000000 - 000000000000000000000000000028272778494747FF494747FF494848FF7381 - 81FF259AD3FF0D99E1FF0EA0EBFF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF26ACF0FF44B7F2FF45B7F2FF45B7F2FF45B7F2FF45B7F2FF45B7F2FF45B7 - F2FF45B7F2FF45B7F2FF4C9BC4FF6D6C6CFF727171FF727171FF727070FF6766 - 66FF4B93B9FF45B7F2FF45B7F2FF45B7F2FF45B7F2FF45B7F2FF45B7F2FF45B7 - F2FF33B1F1FF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF0EA1ECFF0D9B - E4FF0E92D6FF6A858CFF4A4848FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF2B2A2AB10000003000000006000000000000 - 000000000000000000000000000016151531494747FF494747FF494747FF5B5F - 5FFF53A3C5FF0C96DCFF0D9EE8FF0EA2EDFF0EA3EFFF0EA3EFFF0EA3EFFF1CA8 - EFFF4DBBF3FF4EBBF3FF4EBBF3FF4EBBF3FF4EBBF3FF4EBBF3FF4EBBF3FF4EBB - F3FF4EBBF3FF4EBBF3FF53B1E1FF787777FF7A7878FF7A7878FF787676FF666B - 6EFF4FB7ECFF4EBBF3FF4EBBF3FF4EBBF3FF4EBBF3FF4EBBF3FF4EBBF3FF4EBB - F3FF4EBBF3FF2BAEF0FF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF0D9FEAFF0D98 - E0FF2E99CBFF606667FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF464444F30504044D00000014000000000000 - 000000000000000000000000000000000000444242DB494747FF494747FF4D4D - 4DFF7899A1FF1093D5FF0D9BE4FF0EA0EBFF0EA2EEFF0EA3EFFF0EA3EFFF46B8 - F2FF59BFF4FF59BFF4FF59BFF4FF59BFF4FF59BFF4FF59BFF4FF59BFF4FF59BF - F4FF59BFF4FF59BFF4FF6A9FBBFF818080FF828080FF818080FF7C7B7BFF648C - A1FF59BFF4FF59BFF4FF59BFF4FF59BFF4FF59BFF4FF59BFF4FF59BFF4FF59BF - F4FF59BFF4FF54BDF3FF12A4EFFF0EA3EFFF0EA2EEFF0EA1ECFF0D9DE6FF0C94 - D9FF5993AAFF4F4F4FFF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF2120209600000029000000030000 - 0000000000000000000000000000000000002D2C2C79494747FF494747FF4947 - 47FF656E6EFF43A2CCFF0C97DDFF0D9EE8FF0EA1EDFF0EA2EEFF15A5EFFF63C3 - F4FF64C3F4FF64C3F4FF64C3F4FF64C3F4FF64C3F4FF64C3F4FF64C3F4FF64C3 - F4FF64C3F4FF64C3F4FF80939EFF8A8888FF8A8888FF898888FF7E7D7DFF67B1 - D7FF64C3F4FF64C3F4FF64C3F4FF64C3F4FF64C3F4FF64C3F4FF64C3F4FF64C3 - F4FF64C3F4FF64C3F4FF2AADF0FF0EA3EFFF0EA2EEFF0D9FEAFF0D99E1FF2096 - D0FF697577FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF3F3D3DE10000003F0000000E0000 - 0000000000010000000000000000000000000D0D0D15484646F6494747FF4947 - 47FF4F4F4FFF789BA4FF1293D5FF0D9AE3FF0EA0EBFF0EA2EEFF23ABF0FF6EC8 - F5FF6EC8F5FF6EC8F5FF6EC8F5FF6EC8F5FF6EC8F5FF70C3EDFF74BDE2FF75BE - E3FF75BEE3FF77BADCFF919091FF929191FF929191FF8F8E8EFF7E8C94FF6EC8 - F5FF6EC8F5FF6EC8F5FF6EC8F5FF6EC8F5FF6EC8F5FF6EC8F5FF6EC8F5FF6EC8 - F5FF6EC8F5FF6EC8F5FF3CB4F2FF0EA2EEFF0EA1ECFF0D9CE5FF0C93D8FF5B95 - ACFF515252FF494747FF4D4D4DFF535454FF545555FF545555FF545555FF5455 - 55FF535555FF4F5050FF4A4848FF494747FF494747FF16151579000000210000 - 000200000001000000000000000000000000000000004846468F494747FF4947 - 47FF494747FF616767FF56A5C6FF0C95DAFF0D9DE6FF0EA1ECFF23AAF0FF7ACC - F6FF7ACCF6FF7ACCF6FF7ACCF6FF7ACCF6FF7ACCF6FF82B5CFFF989797FF9B99 - 99FF9B9999FF9B9999FF9B9999FF9B9999FF9A9999FF949393FF80ADC3FF7ACC - F6FF7ACCF6FF7ACCF6FF7ACCF6FF7ACCF6FF7ACCF6FF7ACCF6FF7ACCF6FF7ACC - F6FF7ACCF6FF7ACCF6FF3EB5F2FF0EA1EDFF0D9EE8FF0C97DEFF3199CAFF656E - 6EFF494747FF4B4949FF5E8FA5FF7BBBD8FF7CBDD9FF7CBDD9FF7CBDD9FF7CBD - D9FF7CBCD9FF7896A3FF4F4F4FFF494747FF494747FF353333C8000000370000 - 00090000000100000000000000000000000000000000575D5D18484646F24947 - 47FF494747FF4C4B4BFF758889FF2C9BD0FF0D97DEFF0D9EE8FF13A3EDFF80CE - F6FF85D0F7FF85D0F7FF85D0F7FF85D0F7FF85D0F7FF8CBBD3FFA1A0A0FFA3A2 - A2FFA3A2A2FFA3A2A2FFA3A2A2FFA3A2A2FFA2A1A1FF979898FF86CAEDFF85D0 - F7FF85D0F7FF85D0F7FF85D0F7FF85D0F7FF85D0F7FF85D0F7FF85D0F7FF85D0 - F7FF85D0F7FF85D0F7FF2CADEFFF0D9FE9FF0D99E1FF1694D4FF6B8992FF4D4C - 4CFF494747FF4B4949FF609AB3FF80D1F7FF83CAEBFF81B8CDFF79ADC3FF78AC - C2FF78ACC2FF718B95FF4E4E4EFF494747FF494747FF484646FD0B0B0B5E0000 - 0019000000010000000000000000000000000000000000000000748B8B744947 - 47FF494747FF494747FF525353FF789BA4FF1A96D4FF0D99E0FF0D9EE8FF5EC0 - F2FF90D4F7FF90D4F7FF90D4F7FF90D4F7FF90D4F7FF96C1D7FFA7A6A6FFA8A8 - A8FFA8A8A8FFA8A8A8FFA8A8A8FFA8A8A8FFA6A5A5FF98AEB9FF90D4F7FF90D4 - F7FF90D4F7FF90D4F7FF90D4F7FF90D4F7FF90D4F7FF90D4F7FF90D4F7FF90D4 - F7FF90D4F7FF7CCCF5FF10A0EAFF0D9AE3FF0E93D6FF6197ABFF545656FF4947 - 47FF494747FF494747FF545C5FFF72BFE2FF80D0F5FF83A1ABFF595D5DFF4F50 - 50FF4F4F4FFF4D4C4CFF494747FF494747FF494747FF494747FF2A2929AD0000 - 002C000000040000000000000000000000000000000000000000B6F3F3045052 - 52CB494747FF494747FF494747FF585B5BFF72A3B2FF1394D5FF0D99E0FF1DA4 - E9FF8FD3F6FF9BD8F8FF9BD8F8FF9BD8F8FF9BD8F8FF9EC3D6FFA5A4A4FFA5A5 - A5FFA5A5A5FFA5A5A5FFA5A5A5FFA5A5A5FFA4A4A4FF9DC8DEFF9BD8F8FF9BD8 - F8FF9BD8F8FF9BD8F8FF9BD8F8FF9BD8F8FF9BD8F8FF9BD8F8FF9BD8F8FF9BD8 - F8FF99D7F7FF36AFEDFF0D9AE3FF0C93D7FF559BB8FF5C6161FF494747FF4947 - 47FF494747FF494747FF4A4848FF596E75FF78CAF0FF82CDF0FF76878BFF4E4E - 4EFF494747FF494747FF494747FF494747FF494747FF494747FF444242EF0101 - 013E0000000B000000000000000000000000000000000000000000000000A0D1 - D127484646F3494747FF494747FF494848FF5C6161FF71A4B4FF1595D5FF0D98 - DFFF33ACEAFF9FD9F7FFA6DCF8FFA6DDF9FFA6DDF9FFA7D1E7FFA8C2D0FFA8C2 - D0FFA8C2D0FFA8C2D0FFA8C2D0FFA8C2D0FFA8C3D0FFA6DCF8FFA6DDF9FFA6DD - F9FFA6DDF9FFA6DDF9FFA6DDF9FFA6DDF9FFA6DDF9FFA6DDF9FFA6DCF9FFA5DB - F8FF53BAEEFF0D9AE1FF0D93D7FF559CBAFF606667FF4A4848FF494747FF4947 - 47FF494747FF494747FF494747FF4C4B4BFF5F8493FF7DD0F6FF85C6E4FF6B74 - 75FF4C4B4BFF494747FF494747FF494747FF494747FF494747FF494747FF1514 - 146F000000120000000000000000000000000000000000000000000000000000 - 000083A3A355494747FE494747FF494747FF4A4848FF5B5F5FFF76A0ACFF2198 - D2FF0C96DCFF30A9E8FF9CD7F6FFB1E0F9FFB1E1F9FFB1E1FAFFB1E1FAFFB1E1 - FAFFB1E1FAFFB1E1FAFFB1E1FAFFB1E1FAFFB1E1FAFFB1E1FAFFB1E1FAFFB1E1 - FAFFB1E1FAFFB1E1FAFFB1E1FAFFB1E1FAFFB1E1F9FFB1E0F9FFAADDF7FF4BB5 - ECFF0D98DFFF1294D5FF609BB2FF5E6464FF4A4848FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF4E4E4EFF669DB4FF80D0F7FF85B9 - D1FF606666FF4A4949FF494747FF494747FF494747FF494747FF494747FF2625 - 259D000000160000000000000000000000000000000000000000000000000000 - 00000000000032607879494747FF494747FF494747FF494747FF555757FF7993 - 98FF3FA0CDFF0C93D7FF179DE1FF6DC3EFFFB4E1F8FFBBE4F9FFBBE5FAFFBBE5 - FAFFBBE5FAFFBBE5FAFFBBE5FAFFBBE5FAFFBBE5FAFFBBE5FAFFBBE5FAFFBBE5 - FAFFBBE5FAFFBBE5FAFFBBE5FAFFBBE4F9FFBAE3F9FF84CDF2FF26A4E4FF0C94 - DAFF2999CFFF6C939EFF575B5BFF494848FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF535656FF8DC0D6FFA4DE - F9FF92AEB9FF565959FF494747FF494747FF494747FF494747FF494747FF3130 - 30B1000000140000000000000000000000000000000000000000000000000000 - 0000000000000000000032607887494747FF494747FF494747FF494747FF4E4E - 4EFF6C7778FF6AA4B8FF2499D2FF0C94D9FF1FA0E2FF66C0EDFFA5DBF6FFC5E8 - FAFFC5E8FAFFC5E8FBFFC5E8FBFFC5E9FBFFC5E9FBFFC5E9FBFFC5E8FBFFC5E8 - FBFFC5E8FAFFC5E8FAFFB3E1F8FF76C7F0FF2FA7E5FF0C95DBFF1695D4FF549D - BCFF6D7C7DFF505050FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF5B6568FFA4D5 - ECFFB0E0F7FF7A8688FF4C4B4BFF494747FF494747FF494747FF494747FF302F - 2FAA0000000D0000000000000000000000000000000000000000000000000000 - 000000000000000000000000000032607876494747FE494747FF494747FF4947 - 47FF4A4848FF565959FF76888AFF63A3BCFF2B9CD2FF0C92D7FF0C96DCFF24A2 - E3FF50B6EAFF71C4EFFF88CEF2FF96D4F4FF9DD7F5FF99D5F4FF8CD0F3FF78C7 - F0FF58B9EBFF2FA7E5FF0F98DEFF0C93D8FF1D97D3FF529FBFFF728A8FFF585C - 5CFF4A4949FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF515252FF5A5E5EFF525353FF494747FF4B4949FF7E9B - A6FFBAE6FBFF99B1BAFF515151FF494747FF494747FF494747FF494747FF2423 - 2387000000060000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000002A698950494747F0494747FF4947 - 47FF494747FF494747FF4B4949FF565959FF717E7FFF729DA9FF53A3C5FF2E9D - D2FF1193D4FF0C92D7FF0C94D9FF0C95DAFF0C95DBFF0C95DBFF0C94DAFF0C93 - D8FF0E92D5FF2599D2FF48A0C7FF679AACFF718183FF585B5BFF4B4A4AFF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF4A4949FF8EAFBEFFBFE5F7FF839195FF4D4D4DFF4A4848FF768B - 92FFC4E9FBFFA1B8C0FF525353FF494747FF494747FF494747FF494747FF1312 - 1240000000010000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000074B4C422575E5EC24947 - 47FF494747FF494747FF494747FF494747FF494848FF4E4E4EFF5A5E5EFF6C77 - 77FF7A8F91FF7399A4FF689DB0FF619FB7FF5E9FB9FF5F9FB7FF659DB1FF6E98 - A5FF788F93FF6E7979FF5B5F5FFF4F4F4FFF4A4848FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF4A4848FF8198A0FFCDECFCFFB5CDD7FF6B7474FF626A6BFFAECC - D9FFCDECFCFF91A2A7FF4E4E4EFF494747FF494747FF494747FF3E3C3CCA0000 - 0006000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000000000000099C5C5016675 - 7563494747E7494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF4A4848FF4C4B4BFF4F4F4FFF515151FF525353FF515252FF4F4F4FFF4C4C - 4CFF4A4949FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF55595AFFB4D0DCFFD6F0FCFFCEE9F5FFCFEAF7FFD6F0 - FCFFB9D0D9FF626767FF4A4848FF494747FF494747FF484646FA1414143A0000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00004947470C49474776494747E4494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494848FF56595AFF87979CFFA3B3B9FFA3B4B9FF8C9A - 9EFF5E6364FF4C4A4AFF494747FF494747FF494747FE2A282867000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000004947470549474752494747AD494747F6494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF4A4949FF4D4C4CFF4D4D4DFF4B4A - 4AFF494747FF494747FF494747FF484646E93533335000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000049474709494747434947 - 477C494747AB494747CF494747E9494747FA494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747F1494747C1484646704442420D0000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFFFFFFF8001FFFFFFFFFFFC00003FFFFFFFFFF0000007FFFFFFFFC - 0000003FFFFFFFF80000000FFFFFFFE000000007FFFFFFC000000003FFFFFF80 - 00000001FFFFFF0000000000FFFFFE00000000007FFFFC00000000003FFFFC00 - 000000001FFFF800000000001FFFF000000000000FFFF000000000000FFFE000 - 0000000007FFE0000000000007FFE0000000000003FFC0000000000003FFC000 - 0000000001FFC0000000000001FF80000000000001FF80000000000000FF8000 - 0000000000FF800000000000007F800000000000007F800000000000003F8000 - 00000000003F800000000000003F800000000000001F800000000000001F8000 - 00000000000FC00000000000000FC000000000000007C000000000000007C000 - 000000000007E000000000000003E000000000000002E000000000000000F000 - 000000000000F000000000000000F800000000000000F800000000000000FC00 - 000000000000FE00000000000000FF00000000000000FF80000000000000FFC0 - 000000000000FFE0000000000000FFF0000000000001FFF8000000000003FFFE - 000000000007FFFF80000000000FFFFFF0000000001FFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - FFFFFFFFFFFF2800000030000000600000000100200000000000802500000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000200000008000000110000001A000000210000 - 002400000025000000230000001D000000140000000B00000004000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000A09 - 0901000000090000001B000000310404044B1110106F1B1A1A8C2221219D2322 - 22A1232222A1201F1F98161616830B0B0B640101014700000036000000210000 - 000C050404020000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000000A0A0A0A0000 - 0024080707502221219B393838D5464444F7484646FE494747FF484646FE4846 - 46FE494747FF484646FE484646FE484646FD424040EB2E2D2DBD1414147E0000 - 00470000002C0606060F29282801000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000191818040000001C0C0C0C59302E - 2EBD484646FA494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF3F3D - 3DE41E1D1D950101014A000000250F0E0E070000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000202B2B0904040435292828A9474545F94846 - 46FE484646FE494747FE4A4949FF525353FE5D6566FE5E7379FF5B7B87FE5B7F - 8DFE5A7D8AFF5B757EFE5E6A6CFE565858FF4C4B4BFE494747FE494747FF4846 - 46FE484646FE3C3B3BDE12111178000000380C10100F00000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000001C1C1C0D0D0D0D533E3C3CDF484646FE494747FF4947 - 47FE4F5050FE617073FE548CA3FF439CC5FE32A0D7FE2FA3DDFF31A5E0FE33A6 - E1FE32A6E1FF30A4DFFE2FA0DAFE399DCEFF4990B0FE5A7884FE555757FF4948 - 48FE484646FE494747FF474545FB262525A7010101430A0A0A15467287010000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000001A1A1A0D16151568454343F3494747FF494747FF4D4D4DFF6174 - 79FF4C97B9FF2DA0D9FF31A7E3FF36ACE8FF3AAFEBFF3CB2EDFF3EB3EEFF3FB3 - EFFF3FB3EFFF3EB3EEFF3DB1EDFF3AAEEAFF35AAE6FF2BA2DEFF3A9AC9FF567F - 8FFF535555FF494747FF494747FF494747FF323131C50202024A000407160000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00002531310816161665464444F6484646FE494747FF585C5CFE588FA6FF2C9E - D7FE2DA6E4FE33ADEBFE37B0EEFF39B2F0FE3AB3F1FE3BB4F1FF3BB4F1FE3CB4 - F1FE3CB4F2FF3CB4F1FE3DB4F1FE3CB4F1FF3BB3EFFE38B0EDFE33ABE8FF29A1 - DEFE3E95BDFE5A6A70FF4A4949FE494747FF484646FE353333CB02020248080A - 0A11000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000004F6A - 6A030E0E0E4A464444F4494747FF494747FF5E6869FF4699BEFF24A0DFFF2BA9 - E9FF30AEEEFF32B0F0FF33B1F1FF34B1F1FF34B1F1FF35B1F1FF35B2F1FF35B2 - F1FF36B2F1FF36B2F2FF37B2F2FF37B2F2FF37B3F1FF37B2F1FF36B1F0FF33AD - ECFF2BA6E4FF2C9AD1FF597884FF4C4B4BFF494747FF494747FF302F2FBF0000 - 003A171D1D090000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000505 - 0524403E3EE0494747FF494747FE5F6A6BFE3C9AC7FF21A0E1FE27A9EBFF2AAC - EFFE2BAEF0FE2BAEF0FE2CAEF1FF2CAEF0FE2DAFF0FE2DAFF1FF2EAFF0FE2EAF - F0FE2EAFF1FF2FAFF0FE30B0F0FE30B0F1FF30B0F1FE31B0F1FE31B0F1FF31AF - F0FE2FADEEFE29A7E7FF249BD7FE577C8BFF4B4A4AFE484646FE494747FF2221 - 219C000000292221210200000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000000D0D0D092E2D - 2DA6484646FE494747FF5B6061FE4299C2FE1C9EE1FF21A7EBFE24AAEFFF24AB - F0FE25ABF0FE25ABF0FE26ACF0FF26ACF0FE26ACF0FE27ACF0FF27ACF0FE27AC - F0FE28ADF1FF28ADF0FE29ADF0FE29ADF1FF31A0DAFE30A3DEFE2AAEF1FF2AAE - F0FE2AADF0FE29ACEEFF24A5E7FE2299D5FF5A747EFE4A4848FE494747FF4644 - 44F80D0D0D650101011300000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000111111474846 - 46FB484646FE505151FF5594AFFE179BDDFE1BA4EAFF1DA8EFFE297298FF4364 - 75FE48697AFE48697AFE2C94CAFF20A9EFFE20AAEFFE21AAF0FF21AAF0FE21AA - F0FE22AAF0FF22AAF0FE23ABF0FE23ABF0FF476E82FE58595AFE4C6D7FFF398C - B7FE28A7E8FE25ABF0FF24A9EDFE1EA2E5FF2A96CBFE596365FE494747FF4846 - 46FE373535CF000000331E1D1D03000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000007393737C34947 - 47FF4A4848FF658088FF1A98D8FF16A0E8FF17A5EEFF18A7EFFF1B93D0FF3C3E - 3FFF504E4EFF525050FF45616FFF1BA6EDFF1AA7F0FF1AA7F0FF1BA8F0FF1BA8 - F0FF1BA8F0FF1CA8F0FF1CA8F0FF239BD9FF525354FF555353FF555353FF5553 - 53FF53575AFF42728AFF298EC2FF1DA6ECFF189DE0FF448DAEFF4E4E4EFF4947 - 47FF484646FE1514147605040411000000000000000000000000000000000000 - 000000000000000000000000000000000000000000001111113E484646FE4947 - 47FE565959FE3F9AC4FF109BE2FE13A3ECFE13A5EFFF14A5EFFE14A5EFFF225E - 7CFE464444FE4E4C4CFE4E4C4CFF2A82B0FE16A6EFFE16A6EFFF16A6EFFE16A6 - EFFE17A6EFFF17A6EFFE17A6EFFE337699FF504E4EFE514F4FFE504E4EFF504E - 4EFE514F4FFE4D4C4CFF2B627FFE19A6EFFF17A1E8FE1796D7FE5B7179FF4947 - 47FE484646FE353434CA000000282D2B2B010000000000000000000000000000 - 000000000000000000000000000000000000000000022E2D2D9E494747FF4947 - 47FE67828AFE1095D8FF0F9FE8FE10A3EEFE10A3EFFF10A4EEFE10A4EFFF1297 - DBFE31393EFE494747FE4B4949FF44525AFE149FE5FE12A4EFFF12A4EEFE12A4 - EEFE12A4EFFF13A4EFFE14A2EBFE465158FF4D4B4BFE4C4A4AFE3B3A3AFF3534 - 34FE424141FE3E3D3EFF198BC5FE15A5EFFF14A3ECFE109AE1FE408EB2FF4D4D - 4DFE484646FE484646FC090808510F0F0F090000000000000000000000000000 - 0000000000000000000000000000000000000303030B444242E8494747FF4F50 - 50FF4C98B9FF0D99E0FF0EA1ECFF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF19668EFF3F3D3DFF494747FF494747FF2C7297FF0FA3EFFF0FA3EFFF0FA3 - EFFF0FA3EFFF0FA3EFFF2183B5FF4A4848FF4A4848FF454343FF205F7FFF1569 - 93FF1D3642FF1E3C4CFF11A3EEFF11A4EFFF10A3EEFF0E9DE7FF1895D3FF5C65 - 66FF494747FF494747FF272525A50000001E0000000000000000000000000000 - 00000000000000000000000000000000000011101038484646FE494747FF5F66 - 66FE299AD1FE0D9CE6FF0DA2EEFE0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2 - EEFE0E9CE5FE2A3B44FE464444FF484646FE46494CFE1497DAFF0EA2EEFE0EA2 - EEFE0EA3EFFF0EA2EEFE365E73FE494747FF494747FE393939FE1191D3FF0EA2 - EEFE0EA1EDFE0F97DCFF0FA3EEFE0EA3EFFF0EA2EEFE0EA0EAFE0C96DCFF557D - 8EFE494747FE494747FF424040EC0303033E1B1A1A0500000000000000000000 - 0000000000000000000000000000000000002120206B484646FE494747FF687F - 85FE1095D8FE0D9FE9FF0DA2EEFE0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2 - EEFE0DA2EEFE1573A3FE3B3939FF484646FE484646FE336680FF0DA2EEFE0DA2 - EEFE0EA3EFFF1496D8FE464749FE494747FF464444FE274C5FFE0EA3EFFF0DA2 - EEFE0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0DA1ECFE0D99E1FF438C - AEFE4B4A4AFE494747FF484646FE1B1B1B880000001500000000000000000000 - 0000000000000000000000000000000000002E2C2C92494747FF4A4848FF618C - 9CFF0C96DCFF0EA0EBFF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA1EDFF264150FF454343FF494747FF484748FF1B8CC6FF0EA3 - EFFF0EA3EFFF297399FF484646FF494747FF403E3EFF1776A6FF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EDFF0D9BE4FF3494 - C2FF505151FF494747FF494747FF3A3939D70000003024232302000000000000 - 000000000000000000000000000000000000313030AA484646FE4B4A4AFF5893 - ABFE0D98DFFE0EA1ECFF0DA2EEFE0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2 - EEFE0DA2EEFE0DA2EEFE1380B7FF373737FE484646FE494747FF3A5A6BFE0EA1 - ECFE0EA1ECFF3E525DFE484646FE484646FF323B41FE0E9CE4FE0EA3EFFF0DA2 - EEFE0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0DA2EEFE0D9DE6FF2796 - CCFE555858FE494747FF484646FE484646FD1110106A0707070E000000000000 - 000000000000000000000000000000000000323030B1484646FE4C4B4BFF5496 - B2FE0D98E0FE0EA1ECFF0DA2EEFE0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2 - EEFE0DA2EEFE0DA2EEFE0EA2EEFF214C62FE434141FE494747FF484646FE2281 - B1FE188ECAFF474546FE484646FE444343FF205C7BFE0DA2EEFE0EA3EFFF0DA2 - EEFE0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0DA2EEFE0D9DE7FF2196 - D0FE595D5DFE494747FF484646FE484646FE302E2EBD00000025302F2F010000 - 000000000000000000000000000000000000323030B1494747FF4C4B4BFF5596 - B1FF0D98E0FF0EA1ECFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF118CCAFF333537FF484646FF494747FF4150 - 59FF2D6F91FF484646FF484646FF3B3A3BFF1287C3FF0EA3EFFF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF0D9DE7FF2296 - D0FF595D5DFF494747FF494747FF494747FF474545F90707074E100F0F090000 - 000000000000000000000000000000000000323030A9484646FE4B4A4AFF5B94 - AAFE0D97DEFE0EA1ECFF0DA2EEFE0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2 - EEFE0DA2EEFE0DA2EEFE0EA3EFFF0EA3EFFE205A77FE464545FF4F4D4DFE504E - 4EFE4F4F50FF4E4C4CFE4B4949FE2C4654FF0EA2EDFE0DA2EEFE0EA3EFFF0DA2 - EEFE0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0DA2EEFE0D9CE6FF2A96 - CBFE555858FE494747FF484646FE484646FE494747FF252424A10000001C0000 - 0000000000000000000000000000000000002F2D2D8F484646FE494848FF658D - 9BFE0C95DBFE0DA0EAFF0DA2EEFE0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2 - EEFE0DA2EEFE13A5EFFE1FA9F0FF26ACF0FE29A1DEFE464B4FFF5B5A5AFE5D5B - 5BFE5D5B5BFF5D5B5BFE575555FE327CA2FF22AAF0FE19A7EFFE0EA3EFFF0DA2 - EEFE0DA2EEFE0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0DA2EDFE0D9BE4FF3895 - C0FE505050FE494747FF484646FE484646FE494747FF413F3FE90202023B1918 - 18050000000000000000000000000000000023222268494747FF494747FF6B7F - 83FF1395D7FF0D9EE8FF0EA2EEFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF11A4 - EFFF27ACF0FF33B1F1FF34B1F1FF34B1F1FF34B1F1FF3D7D9DFF5C5B5BFF6563 - 63FF656363FF656363FF555759FF35A8E3FF34B1F1FF34B1F1FF2FAFF1FF19A7 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA1ECFF0D99E0FF488D - ABFF4B4A4AFF494747FF494747FF494747FF494747FF494747FF1A1919840202 - 02140000000000000000000000000000000012111133484646FE494747FF5E64 - 64FE319DD0FE0D9CE5FF0DA2EDFE0DA2EEFE0EA3EFFF0DA2EEFE14A5EFFF38B3 - F1FE3FB6F2FE3FB6F2FE40B6F2FF3FB6F2FE3FB6F2FE40B0E9FF5D696FFE6E6D - 6DFE6F6D6DFF6C6A6AFE51778BFE40B6F2FF3FB6F2FE3FB6F2FE40B6F2FF3FB5 - F2FE23ABF0FE0EA3EFFF0DA2EEFE0EA3EFFF0DA2EEFE0D9FEAFE0C95DBFF5C7E - 8BFE494747FE494747FF484646FE484646FE494747FF484646FE393737D40000 - 002F0000000200000000000000000000000003030305464444E8494747FF4F4F - 4FFE559AB7FE0D98DFFF0DA0EBFE0DA2EEFE0EA3EFFF0FA3EFFE40B5F2FF4DBA - F3FE4DBAF3FE4DBAF3FE4DBAF3FF4DBAF3FE4DBAF3FE4DBAF3FF648FA6FE7877 - 77FE787777FF706F6FFE529FC7FE4DBAF3FF4DBAF3FE4DBAF3FE4DBAF3FF4DBA - F3FE4CBAF3FE1EA9F0FF0DA2EEFE0EA3EFFF0DA2EDFE0D9DE6FE2097D1FF5D63 - 63FE484747FE494747FF484646FE484646FE494747FF484646FE484646FD0F0F - 0F660000000D00000000000000000000000000000000302F2F98494747FF4947 - 47FF6D8287FF1596D7FF0D9DE7FF0EA2EEFF0EA3EFFF29ADF0FF5BC0F4FF5BC0 - F4FF5BC0F4FF5BC0F4FF5BC0F4FF5BC0F4FF5BC0F4FF5BBFF2FF7C888EFF8382 - 82FF828181FF717C82FF5BBEF0FF5BC0F4FF5BC0F4FF5BC0F4FF5BC0F4FF5BC0 - F4FF5BC0F4FF4BBAF3FF0EA3EFFF0EA2EEFF0DA0EBFF0D98DFFF4B90AEFF4C4C - 4CFF494747FF494747FF494747FF494747FF494747FF494747FF494747FF2F2D - 2DBA000000240000000100000000000000000000000016151533494747FE4846 - 46FE545757FE4C9EC2FF0D98E0FE0DA0EBFE0EA2EEFF47B8F2FE69C5F5FF69C5 - F5FE69C5F5FE69C5F5FE69C5F5FF69C5F5FE69C5F5FE70B9DEFF8D8C8CFE8D8C - 8CFE8A8989FF729EB5FE69C5F5FE69C5F5FF69C5F5FE69C5F5FE69C5F5FF69C5 - F5FE69C5F5FE67C4F5FF15A5EFFE0EA2EDFF0D9DE6FE1A96D3FE607074FF4947 - 47FE4A4949FE4B4A4AFF4B4A4AFE4B4A4AFE4B4A4AFF4A4848FE494747FE4745 - 45F80606064B0000000800000000000000000000000000000000484646BB4947 - 47FF494747FF6B7F84FF1E98D5FF0D9CE5FF0EA1EDFF53BDF3FF78CBF6FF78CB - F6FF78CBF6FF78CBF6FF84AFC6FF959DA2FF959EA3FF979B9FFF999898FF9998 - 98FF909091FF7AC0E4FF78CBF6FF78CBF6FF78CBF6FF78CBF6FF78CBF6FF78CB - F6FF78CBF6FF77CBF6FF19A6EFFF0D9FEAFF0D96DDFF518FA9FF4D4D4DFF4C4E - 4FFF699BB1FF75A7BCFF75A7BCFF75A7BCFF75A6BCFF687B82FF4A4848FF4947 - 47FF2322229D0000001B000000010000000000000000000000005C6565384846 - 46FB484646FE4F4F4FFF6397AAFE0F95DAFE0D9EE8FF45B7F1FE87D1F7FF87D1 - F7FE87D1F7FE87D1F7FE93B5C7FFA3A2A2FEA4A3A3FEA4A3A3FFA4A3A3FEA3A2 - A2FE93A5AEFF87D1F7FE87D1F7FE87D1F7FF87D1F7FE87D1F7FE87D1F7FF87D1 - F7FE87D1F7FE78CBF5FF10A1EBFE0D99E1FF3396C5FE5A6061FE494747FF4D4E - 4FFE70BBDCFE82CDF0FF7EA9BAFE7098A9FE7098A8FF647278FE494848FE4947 - 47FF413F3FE80202023900000004000000000000000000000000000000006777 - 7799484646FE494747FF595D5DFE539EBDFE0D96DCFF19A3E9FE8AD1F6FF95D6 - F7FE95D6F7FE95D6F7FE9DBBCAFFA7A6A6FEA7A6A6FEA7A6A6FFA7A6A6FEA6A5 - A5FE99C2D7FF95D6F7FE95D6F7FE95D6F8FF95D6F7FE95D6F7FE95D6F8FF95D6 - F7FE95D6F7FE49B7EFFF0D9AE2FE2397CFFF627378FE494848FE494747FF4947 - 47FE586C74FE7ACAEFFF80ABBEFE545656FE4A4848FF494747FE494747FE4947 - 47FF484646FE1817177C0000000E00000000000000000000000000000000B0EA - EA10515353DB494747FF494747FF5F6667FF4D9FC2FF0D96DCFF38AEEBFFA0DA - F7FFA4DCF8FFA4DCF8FFA6C9DAFFA7BBC5FFA7BBC5FFA7BBC5FFA7BBC5FFA7BB - C5FFA4DAF5FFA4DCF8FFA4DCF8FFA4DCF9FFA4DCF8FFA4DCF8FFA4DCF9FFA4DC - F8FF74C7F2FF0F9BE2FF2297D0FF627C84FF4B4949FF494747FF494747FF4947 - 47FF4A4848FF5F8493FF7FCFF5FF79959FFF4E4D4DFF494747FF494747FF4947 - 47FF494747FF313030BD0000001A000000000000000000000000000000000000 - 00009DCBCB30484748F2484646FE494747FE5E6464FF599DB8FE1296D8FF36AB - E7FE9ED8F6FEB2E1F9FEB2E2FAFFB2E2F9FEB2E2F9FEB2E2FAFFB2E2F9FEB2E2 - F9FEB2E2FAFFB2E2F9FEB2E2F9FEB2E2FAFFB2E2F9FEB2E1F9FEAFE0F8FF69C2 - EFFE1199DEFE3098C9FF63777DFE4B4A4AFF484646FE484646FE494747FF4846 - 46FE484646FE4C4B4BFF6B9EB5FE8AD0F0FE718085FF4B4949FE484646FE4947 - 47FF484646FE413F3FE701010121000000000000000000000000000000000000 - 00000000000021729B4A484849F6484646FE494747FF555858FE69919EFF2C9B - D0FE179BDEFE62BEEDFEABDDF7FFC0E6FAFEC0E6FAFEC0E7FAFFC0E7FAFEC0E7 - FAFEC0E7FAFFC0E7FAFEC0E7FAFEC0E6FAFFBBE4F9FE86CEF2FE32A8E4FF1596 - D7FE4F96B4FE5F6869FF4A4848FE494747FF484646FE484646FE494747FF4846 - 46FE484646FE494747FF515354FE93C1D5FEA7D2E6FF606565FE494747FE4947 - 47FF484646FE464444F10303031F000000000000000000000000000000000000 - 0000000000000000000021729B49484748F1494747FF494747FF4C4B4BFF6570 - 72FF5E99B0FF2B9CD2FF1197DBFF39ABE5FF68C0EDFF8ACFF2FF9ED7F5FFA7DB - F6FFA3DAF6FF94D3F4FF78C7F0FF4FB5E9FF1E9EDFFF1696D6FF469ABFFF657E - 86FF515252FF494747FF494747FF494747FF494747FF494747FF494747FF4A48 - 48FF535555FF515252FF494747FF606C70FFB5E3F8FF86979DFF4A4848FF4947 - 47FF494747FF413F3FE00000000F000000000000000000000000000000000000 - 00000000000000000000000000001D77A52D444B50D7484646FE494747FF4947 - 47FE4D4D4DFE636B6CFE688E9AFF4F9BBCFE359DCEFE1E98D5FF1396D7FE1195 - D8FE1295D8FF1897D6FE2A9BD1FE429BC3FF5B91A6FE68787BFE525353FF4947 - 47FE484646FE494747FF484646FE494747FF484646FE484646FE494747FF4F51 - 52FEB4DBEDFE99AEB6FF4F4F4FFE595F60FEBFE5F6FF8FA0A6FE4A4949FE4947 - 47FF484646FE2F2D2DA000000003000000000000000000000000000000000000 - 000000000000000000000000000000000000A5E4E80D7084848F494848F84846 - 46FE484646FE494747FE4A4848FF4F5050FE5A5F5FFE677071FF6B7B7EFE6A7E - 83FE6A7C80FF687476FE5F6565FE535454FF4B4A4AFE494747FE494747FF4846 - 46FE484646FE494747FF484646FE494747FF484646FE484646FE494747FF4B4A - 4AFE9EB7C2FECBE6F3FF9CAFB5FEB1CAD4FECCE8F5FF707779FE494747FE4947 - 47FF474545F60F0E0E2E00000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000004947472A4947 - 47A7494747FA494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4947 - 47FF535656FF93A4AAFFB1C3CAFFAABCC3FF788284FF4D4C4CFF494747FF4947 - 47FE262424690000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00004846461C48464676494747C8484646F7484646FE494747FF484646FE4846 - 46FE494747FF484646FE484646FE494747FF484646FE484646FE494747FF4846 - 46FE484646FE494747FF484646FE494747FF484646FE484646FE494747FF4846 - 46FE494747FE4A4848FF4C4B4BFE4B4A4AFE494747FF484646FE474545E03C3B - 3B52000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000A3A2A211A3A2A23BA4A3A35FA3A2A276A3A2 - A27FA4A3A37FA3A2A27FA3A2A27FA4A3A37FA3A2A27FA3A2A27FA4A3A37FA3A2 - A27FA3A2A27FA4A3A37FA3A2A27FA4A3A37FA3A2A27FA3A2A27FA4A3A37FA3A2 - A27FA3A2A27FA4A3A37FA3A2A27FA3A2A27FA4A3A377A3A2A248A3A2A2080000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000FFFFFFFFFFFF0000FFFFFFFFFFFF0000FFFF - FFFFFFFF0000FFFE001FFFFF0000FFF00003FFFF0000FFE00000FFFF0000FF80 - 00007FFF0000FF0000003FFF0000FE0000000FFF0000FC0000000FFF0000F800 - 000007FF0000F000000003FF0000F000000001FF0000E000000001FF0000E000 - 000000FF0000C000000000FF0000C0000000007F000080000000007F00008000 - 0000007F000080000000003F000080000000003F000080000000001F00008000 - 0000001F000080000000000F000080000000000F000080000000000F00008000 - 000000070000800000000007000080000000000300008000000000030000C000 - 000000010000C000000000010000E000000000000000E000000000000000F000 - 000000000000F000000000000000F800000000000000FC00000000000000FE00 - 000000000000FF00000000000000FF80000000010000FFE0000000030000FFF8 - 000000070000FFFF0000000F0000FFFFFFFFFFFF0000FFFFFFFFFFFF0000FFFF - FFFFFFFF0000FFFFFFFFFFFF0000280000002000000040000000010020000000 - 0000801000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000030000 - 000E0000001F0000002D00000033000000340000002F00000022000000110000 - 0004000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000252424040404041F121212672928 - 28AD393838D8444242F0484646F9474545F8414040EB353333CE2221219F0909 - 0958020202251F1F1F0700000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000B0B0B14181818763D3B3BDF494747FF4947 - 47FF494747FF4C4B4BFF4F4F4FFF4E4D4DFF4B4949FF494747FF494747FF4846 - 46FD323030C60B0B0B5F0606061A526262010000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000BBC3C3011011112D343232C4494747FF494848FF565C5EFF507B - 8EFF4892B5FF429FCBFF40A3D4FF40A2D1FF439AC3FF4888A5FF526D78FF4E4E - 4EFF494747FF474545FA2221219D0304042A6183900300000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000151515363F3E3EE3494747FF545858FF4D88A3FF33A2DAFF34AB - E7FF39B0EDFF3DB3EFFF3EB4F0FF3EB4F0FF3DB3EEFF3AAFEBFF31A8E4FF3A9A - C8FF51717EFF4B4A4AFF494747FF2F2D2DBD0103042F7FABAB02000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00001E262625403E3EE2494747FF57696FFF379BCCFF2BA8E7FF32AFEFFF35B1 - F1FF35B2F1FF36B2F1FF37B2F1FF37B3F1FF38B3F2FF38B3F1FF38B2F1FF35AF - EDFF2BA4E2FF4488A8FF4F5050FF494747FF2E2C2CBA090C0C23000000000000 - 000000000000000000000000000000000000000000000000000000000000292E - 2E08363434C2494747FF586B71FF2B9DD5FF25A8EBFF29ACF0FF2AADF1FF2AAE - F1FF2BAEF1FF2CAEF1FF2CAEF1FF2DAFF1FF2EAFF1FF2EAFF1FF2FAFF1FF2FAF - F1FF2EAEEFFF27A6E6FF3C8DB3FF4E4F4FFF494747FF1F1E1E920F0F0F0F0000 - 0000000000000000000000000000000000000000000000000000000000001E1D - 1D6B494747FF565C5EFF2E99CEFF1CA4EAFF2491C8FF397D9FFF3C7FA1FF26A1 - DFFF22AAF0FF22AAF0FF23ABF0FF23ABF0FF24ABF0FF29A3E1FF4E6A79FF3D88 - AEFF2BA5E3FF26ABEFFF1FA2E5FF4583A0FF4A4848FF464444F6080808493230 - 30010000000000000000000000000000000000000000000000000101010B4240 - 40E44B4949FF478DADFF149FE6FF16A5EFFF189EE1FF3D464BFF514F4FFF3B6E - 89FF19A7F0FF19A7F0FF1AA7F0FF1AA7F0FF1BA8F0FF357DA2FF545252FF5452 - 52FF535455FF40687DFF1E9EDEFF1A9BDDFF526871FF494747FF2C2A2AB21413 - 130F0000000000000000000000000000000000000000000000001A19195B4947 - 47FF5B686BFF1799DAFF10A2ECFF11A4EFFF11A4EFFF1D6E98FF474545FF4B4A - 4AFF1E91CBFF13A4EFFF13A5EFFF14A5EFFF15A4EDFF45555EFF4D4B4BFF3F3D - 3DFF454343FF384B55FF16A5EEFF14A1E9FF358CB6FF4B4949FF464444F60403 - 0333000000000000000000000000000000000000000000000000333131AD4947 - 47FF4C87A0FF0D9CE5FF0EA2EEFF0EA3EFFF0EA3EFFF0E9FE9FF30424CFF4947 - 47FF3B5B6DFF0FA3EEFF0FA3EFFF0FA3EFFF1F88BEFF4A4848FF454343FF1874 - A3FF176288FF16709EFF10A3EFFF0FA2EDFF1297DBFF555F62FF494747FF1F1E - 1E8D21202007000000000000000000000000000000009F9F9F02444242E74D4C - 4CFF3798C6FF0D9FEAFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF1678AAFF4240 - 40FF484646FF2183B5FF0EA3EFFF0EA3EFFF34637BFF484646FF34444DFF0EA1 - ECFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF0D9BE3FF497588FF494747FF3D3C - 3CE00404042000000000000000000000000000000000A6A6A610494747FF5558 - 58FF239CD7FF0EA1ECFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF2A49 - 5AFF484646FF41515BFF0F9FE9FF129AE0FF464849FF474545FF1F678DFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF0D9DE7FF3E82A2FF494747FF4947 - 47FF1413136B2B2A2A03000000000000000000000000A8A8A821494747FF5D62 - 62FF1799DBFF0EA1EDFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF1385 - BFFF3E3D3DFF494747FF29769EFF247AA7FF484646FF3F3E3FFF1192D4FF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0D9FE9FF3989AFFF494747FF4947 - 47FF333131C60C0C0C15000000000000000000000000A8A8A820494747FF5C61 - 61FF189ADBFF0EA1EDFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3 - EFFF24536CFF474545FF454B4FFF3C5968FF484646FF2C5165FF0EA3EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF0D9EE9FF3A89AFFF494747FF4947 - 47FF484646FC0A09094A353434010000000000000000A7A6A60F494747FF5557 - 57FF269CD6FF0DA1ECFF0EA3EFFF0EA3EFFF0EA3EFFF0EA3EFFF10A3EFFF1AA7 - EFFF2498D4FF4D4E50FF5B5959FF5A5858FF565454FF2981AEFF17A6EFFF0EA3 - EFFF0EA3EFFF0EA3EFFF0EA3EFFF0EA2EEFF0D9DE7FF4083A1FF494747FF4947 - 47FF494747FF282727A81616160D000000000000000000000000454343E74C4C - 4CFF3B99C4FF0D9FEAFF0EA3EFFF0EA3EFFF0EA3EFFF20AAF0FF35B1F1FF36B2 - F1FF36B2F1FF457A95FF666464FF676666FF5A6064FF37AEEBFF36B2F1FF30B0 - F1FF15A5EFFF0EA3EFFF0EA3EFFF0EA2EEFF0D9AE3FF4D7587FF494747FF4947 - 47FF494747FF444242F104040430000000000000000000000000343232A94947 - 47FF51879EFF0D9BE4FF0EA2EEFF0EA3EFFF27ACF0FF49B9F3FF49B9F3FF49B9 - F3FF49B9F3FF4DB0E3FF747373FF757474FF5A879EFF49B9F3FF49B9F3FF49B9 - F3FF45B8F2FF15A5EFFF0EA3EFFF0DA1ECFF1598D9FF575F60FF494747FF4947 - 47FF494747FF494747FF1D1C1C880000000600000000000000001C1B1B554947 - 47FF5D6769FF1B9AD9FF0DA1ECFF0FA3EFFF59BFF4FF5EC1F4FF5EC1F4FF5EC1 - F4FF5EC1F4FF69ADD0FF858484FF818080FF62B0D8FF5EC1F4FF5EC1F4FF5EC1 - F4FF5EC1F4FF3DB4F2FF0EA2EEFF0D9EE7FF3C8DB3FF4A4949FF494747FF4947 - 47FF494747FF494747FF3C3A3ADD0000001E0000000000000000030303054846 - 46E14A4949FF508EA9FF0D9BE3FF18A6EEFF74CAF5FF74CAF5FF74CAF5FF80B3 - CDFF88ABBEFF8F9FA8FF969595FF88969EFF74CAF5FF74CAF5FF74CAF5FF74CA - F5FF74CAF5FF58BFF3FF0DA1ECFF1698D9FF56676DFF505B60FF678897FF6889 - 97FF688997FF585F62FF494747FF121212660000000300000000000000005E69 - 695F494747FF575B5BFF3399C9FF0F9EE7FF7CCDF5FF8AD2F7FF8AD2F7FF9BB0 - BCFFA5A5A5FFA5A5A5FFA5A4A4FF91B9CDFF8AD2F7FF8AD2F7FF8AD2F7FF8AD2 - F7FF8AD2F7FF4FBAF1FF0D99E1FF4D839AFF4A4848FF526168FF7DCAEEFF7699 - A6FF647E89FF555B5DFF494747FF313030C200000012000000000000000090B7 - B701606C6CB9494747FF5C6A6EFF2999CFFF3BAFEAFF9FD9F8FFA0DBF8FFA4BF - CCFFA6B4BAFFA6B4BAFFA6B3BAFFA1D6F1FFA0DBF8FFA0DBF8FFA0DBF8FFA0DA - F8FF8BD1F5FF179DE2FF458CACFF4E4E4EFF494747FF494747FF5F8291FF7EBA - D5FF535555FF494747FF494747FF474545FB0505053200000000000000000000 - 0000AFE8E815434D53DD494747FF5C676AFF3998C5FF3CACE6FFA1D9F6FFB6E3 - F9FFB6E3FAFFB6E3FAFFB6E3FAFFB6E3FAFFB6E3FAFFB6E3FAFFB5E2F9FF81CC - F2FF239EDDFF4D87A0FF4E4E4EFF494747FF494747FF494747FF4A4949FF71A1 - B6FF87ABBAFF4C4C4CFF494747FF494747FF1515155E00000000000000000000 - 0000000000001580B621434D53DC494747FF535555FF56879BFF2E9DD2FF49B1 - E6FF7FCAF0FFA1D9F5FFAFDFF7FFACDEF7FF97D4F4FF6DC2EDFF33A6E0FF3A95 - BFFF596F77FF4A4949FF494747FF494747FF494747FF4B4A4AFF4F4F4FFF4E4F - 50FFA3CDE1FF6C7578FF494747FF494747FF1514145100000000000000000000 - 00000000000000000000409FC71457686CB5494747FF494747FF565959FF5B7B - 86FF498DABFF3D97C1FF369AC9FF3799C7FF4093B9FF4D849CFF5C6D71FF4D4D - 4DFF494747FF494747FF494747FF494747FF494747FF69767CFFB1CCD8FF595C - 5DFFADCBD8FF757F82FF494747FF464444F10404041200000000000000000000 - 00000000000000000000000000000000000050525255494747D6494747FF4947 - 47FF494747FF4B4A4AFF4D4C4CFF4C4B4BFF4A4848FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF4C4B4CFF99ACB4FFB9CF - D8FF9EAFB6FF505050FF494747FE212020670000000000000000000000000000 - 0000000000000000000000000000000000000000000049474701494747404947 - 4790494747C9494747ED494747FD494747FF494747FF494747FF494747FF4947 - 47FF494747FF494747FF494747FF494747FF494747FF494747FF494747FF4B49 - 49FF494848FB484646CC42404051000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFF80 - 1FFFFE0007FFFC0001FFF00000FFF000007FE000007FC000003FC000001F8000 - 001F8000001F8000000F0000000F000000070000000700000003000000038000 - 0003800000018000000180000000C0000000C0000000E0000000F0000000F800 - 0000FE000001FF000003FFFFFFFFFFFFFFFFFFFFFFFF28000000180000003000 - 0000010020000000000060090000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000006767 - 67066767670F6767671267676710676767076767670100000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000021202002040404201616166F2928 - 28AC333232C9363434D0323030C6252424A510101064010101201D1C1C040000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000262B2B101F1E1E86424040ED494747FF5051 - 51FE535F63FF526269FF525B5EFF4D4C4CFE494747FF3B3A3ADD141313711A1D - 1D14000000000000000000000000000000000000000000000000000000000000 - 000000000000000000004A4A4A20363535C94A4848FE516872FF4590B5FF39A6 - DCFE37ABE6FF39ADE8FF36AAE5FF3CA1D3FE4583A0FF4F595DFE484646FE2827 - 27AB1521271D0000000000000000000000000000000000000000000000000000 - 0000000000004E6767153B3939D34E4F4FFE4789A8FE2DA7E5FE34AFEFFE37B2 - F1FE38B3F1FE39B3F1FE39B3F1FE39B3F1FE36AFEDFE31A2DBFE4A7183FE4948 - 48FE2C2B2BB42B39391500000000000000000000000000000000000000000000 - 0000171A1A022F2D2DAA4D4D4DFF3E8FB5FF23A7EAFE27ACF0FF29ADF0FF29AD - F0FE2AADF0FF2BAEF1FF2CAEF1FF2EABEBFE2FACECFF2DAEF0FE27A5E5FF4875 - 8AFF494747FE1D1C1C892B2A2A05000000000000000000000000000000000000 - 000012121245494747FE497F98FF18A1E7FF1E95D1FE46565FFF436B81FF1DA8 - EFFE1EA9F0FF1EA9F0FF1FA9F0FF3882A8FE535B60FF427793FE2D95CAFF1F9F - DFFF4D616AFE444242F30E0D0D2F000000000000000000000000000000000000 - 0000343333B6545A5CFE1C9ADAFE11A3EEFE12A4EFFE2B5C76FE4C4A4AFE2686 - B8FE14A5EFFE14A5EFFE15A5EEFE455862FE4A4848FE464444FE345E73FE16A4 - ECFE318CB9FE4A4848FE21202090333232020000000000000000000000007C7C - 7C11474545F9497A90FE0D9EE8FF0EA3EFFF0EA2EEFE1192D4FF3E4143FF4152 - 5CFE10A0E9FF0EA3EFFF1D8AC1FF494747FE2C5B73FF1478ACFE1386C1FF0FA3 - EEFF109AE0FE515C60FF3E3D3DE4151515180000000000000000000000008B8A - 8A3F494747FF398EB5FE0DA1ECFF0EA3EFFF0DA2EEFE0EA3EFFF216486FF4746 - 46FE29779FFF0EA3EFFF336580FF464444FE1682B9FF0DA2EEFE0EA3EFFF0EA3 - EFFF0D9EE8FE456F83FF494747FF16151569000000000000000000000000908F - 8F574A4848FF3296C7FE0EA2EDFF0EA3EFFF0DA2EEFE0EA3EFFF0F9AE0FF3942 - 48FE454B50FF1694D5FF45494CFF384851FE0EA1ECFF0DA2EEFE0EA3EFFF0EA3 - EFFF0D9FEAFE3E7894FF494747FF343333C91F1E1E0D0000000000000000908F - 8F564A4848FE3296C6FE0DA2EDFE0DA2EEFE0DA2EEFE0DA2EEFE0DA2EEFE1D6F - 9AFE494747FE435762FE4B4949FE226A90FE0DA2EEFE0DA2EEFE0DA2EEFE0DA2 - EEFE0D9FEAFE3E7894FE484646FE484646FD0F0E0E4500000000000000008C8B - 8B3E494747FF3C8EB4FE0DA1ECFF0EA3EFFF0DA2EEFE15A5EFFF26ACF0FF2EAC - ECFE4F5F68FF615F5FFF5B5B5BFF2FA0DAFE22AAF0FF10A4EFFE0EA3EFFF0EA3 - EFFF0D9DE7FE476F82FF494747FF484646FE292828AA07060606000000007D7C - 7C0E484646F94D7A8EFE0D9DE7FE0DA2EEFE1CA8EFFE44B7F2FE46B8F2FE46B8 - F2FE5499BCFE737272FE607C8BFE46B8F2FE46B8F2FE3FB5F2FE12A4EFFE0DA2 - EEFE129ADFFE525C5FFE484646FE484646FE454343F304030329000000000000 - 0000363434B2555A5BFE1F9BD8FF0DA2EDFF4DBAF3FE62C2F4FF62C2F4FF62C2 - F4FE75A3BBFF878686FF6AA7C7FF62C2F4FE62C2F4FF62C2F4FE35B2F1FF0DA0 - EBFF348BB5FE4A4949FF4A4848FF4A4848FE494747FF1F1E1E88000000020000 - 0000292B2B3D494747FE4F7F94FF0E9CE5FF66C4F4FE7FCEF6FF85C0DEFF9CA0 - A3FE9E9E9FFF989C9EFF80CBF2FF7FCEF6FE7FCEF6FF7FCEF6FE46B7F1FF1799 - DBFF506167FE5D7C8BFF7AB1C8FF729FB2FE585F62FF3D3C3CE0000000160000 - 0000000000006C7F7FA14D4C4CFE438EB0FE3AAEE9FE9CD8F8FE9FCDE5FEA7B1 - B6FEA7B1B6FEA2BFCDFE9DD9F8FE9DD9F8FE9DD9F8FE91D4F6FE22A1E1FE4C74 - 85FE494747FE4D5153FE76B2CDFE596063FE494747FE484646FE121111580000 - 000000000000B5F2F20C3E525DCC4E4E4EFF4A87A2FE46AEE3FF9CD7F6FFB9E4 - FAFEB9E4FAFFB9E4FAFFB9E4FAFFB8E3F9FE86CEF2FF37A1D6FE4F707EFF4947 - 47FF484646FE494747FF546167FF8DB9CCFE4F4F4FFF494747FF232222860000 - 000000000000000000001184BF123C5461BD494848FE56676DFF428BADFF49A9 - D7FE56B5E5FF5BB8E7FF54B3E3FF42A0CCFE467F99FF525859FE494747FF4947 - 47FF484646FE687277FF606567FF8BA5B0FE6A7275FF494747FF1C1B1B640000 - 00000000000000000000000000007B9EA1035459596C484646E8494747FE4F4F - 4FFE595E5FFE596264FE56595AFE4C4B4BFE494747FE484646FE484646FE4846 - 46FE484646FE61676AFEAABFC7FEA8BCC4FE535455FE3F3E3ED70303030B0000 - 00000000000000000000000000000000000000000000767575077675754F7675 - 7590767575B4767575BF767575BF767575BF767575BF767575BF767575BF7675 - 75BF767575BF767575BF777676BF777676BD7674748C58575714000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000000000000000000000000000FFFF - FF00FF03FF00F800FF00F0007F00E0003F00C0001F0080000F0080000F008000 - 0700000007000000070000000300000003000000010000000100800000008000 - 0000C0000000C0000000E0000000F0000000FC000100FFFFFF00FFFFFF002800 - 0000100000002000000001002000000000004004000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000001B1A1A01050505221818186D2322 - 2292222121911615156802020220191818010000000000000000000000000000 - 00000000000000000000000000006C7B7B0B2827279349494AF74A6774FF4777 - 8EFF47758BFF4B606BFF444343F01F1E1E844E63660B00000000000000000000 - 0000000000000000000073959509373636BF4B6876FF37A0D4FF36AFEDFF3AB3 - F0FF3BB3F0FF37AFECFF3B97C5FF4A5A62FF292929A94E5F5F09000000000000 - 000000000000000000003131318D496A79FF249EDCFF3295C8FF27AAECFF27AC - F0FF29ADF0FF359BCFFF31A2DCFF2AA0DBFF49585FFF1F1E1E78000000000000 - 000000000000565656194C4E4FF8219AD6FF14A3EBFF3D525DFF2F7CA3FF16A6 - EFFF17A6EFFF475C67FF4B4A4AFF2B7DA7FF2D8CBBFF413F3FE9282727100000 - 0000000000006D6C6C65466C7EFF0DA0EBFF0EA3EFFF187FB4FF434A4EFF139B - E0FF1C8CC5FF434547FF1386C2FF1196DAFF0F9EE6FF4C585EFF201F1F650000 - 0000000000007877778C3B7C9BFF0EA2EDFF0EA3EFFF0EA2EEFF315467FF306B - 8AFF316986FF2E5F79FF0EA3EFFF0EA3EFFF0DA0EBFF426678FF363434CB3231 - 3106000000007877778B3C7C9AFF0DA2EDFF0EA3EFFF0EA3EFFF1C8DC7FF4D4E - 4FFF4D5357FF1E87BCFF0EA3EFFF0EA3EFFF0DA0EBFF436677FF484646FE1F1E - 1E40000000006E6D6D64486D7DFF0DA0EAFF14A5EFFF3AB3F1FF40B6F2FF5B80 - 94FF647077FF40B5F0FF35B1F1FF0FA3EFFF0F9DE6FF4D585DFF494747FF2B2A - 2AAA00000001575757164E4F50F72199D4FF3DB5F1FF69C5F5FF71B8DDFF8599 - A4FF78A4BBFF69C5F5FF69C5F5FF2CAEF0FF2D8AB8FF525D62FF58686FFF494A - 4AF60404042200000000667474864B6976FF3CADE6FF95D6F7FFA3B2BAFFA6AC - AFFF97CFEBFF95D6F8FF90D4F7FF2E9FD8FF4B585DFF5E7D8CFF6B8996FF4C4C - 4CFF1F1F1F8000000000A4D6D605395869B64C6773FF58AAD2FF8DD0F2FFAFDF - F8FFABDEF8FF83CBF0FF4E9BC1FF4C595FFF494747FF4B4A4AFF7A9AA8FF5253 - 54FF2F2E2EAB00000000000000005897AD05586263824C4B4BF44E6570FF4372 - 88FF437085FF4F6067FF4A4848FF494747FF494747FF808E95FF97A9B1FF5557 - 58FE1B1A1A5A00000000000000000000000000000000A4A3A310A4A3A356A4A3 - A37AA4A3A37FA4A3A37FA4A3A37FA4A3A37FA4A3A37FA4A3A37FA4A3A37EA2A1 - A147000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000FFFF0000E01F0000C00F00008007000080070000000300000003 - 0000000100000001000000000000000000008000000080000000C0000000F001 - 0000FFFF0000} - OldCreateOrder = False - Position = poScreenCenter - OnClose = FormClose - OnCreate = FormCreate - PixelsPerInch = 96 - TextHeight = 13 - object bvlSpace: TBevel - Left = 0 - Top = 314 - Width = 527 - Height = 3 - Align = alBottom - Shape = bsBottomLine - end - object jplWizard: TJvPageList - Left = 0 - Top = 0 - Width = 527 - Height = 314 - ActivePage = jspWelcome - PropagateEnable = False - Align = alClient - OnChange = jplWizardChange - object jspWelcome: TJvStandardPage - Left = 0 - Top = 0 - Width = 527 - Height = 314 - Color = clWhite - object imgInstall: TImage - Left = 0 - Top = 0 - Width = 164 - Height = 314 - Align = alLeft - AutoSize = True - Picture.Data = { - 07544269746D6170AE5B0200424DAE5B0200000000003600000028000000A400 - 00003A0100000100180000000000785B0200C40E0000C40E0000000000000000 - 00008C00018900028400047800036E02085F06094B02043500003404022F0401 - 3100004303024D00006200007300008304068000018200008600008700008700 - 018400018000047800046700016508094D00004D01024300004400014804053E - 00004300033C00003E00004302043D00004201034403053E00004201033C0000 - 3E00004302043D00004201034403053E00004201033C00003E00004302043D00 - 004201034403053E00004201033C00003E00004302043D00004201034403053E - 00004201033C00003E00004302043D00004201034403053E00004201033C0000 - 3E00004302043D00004201034403053E00004501023F00004100004603024000 - 004502014504033F00004302013C00003E00004104023900003E030140050338 - 00003B03023300003800003F04023B00004302014D03014C00005D0302570000 - 7002027A03047C00008702058700008A00028400018200018000018000018000 - 018000018400018400018300008000017B00027101016705055D08064E03013F - 00004003003F02004100004D02005200005E00006A00007A05087B00027F0002 - 8200018200018200018000018001008001008601008700008900008700008400 - 017D01017201046604045300014300003E00003F03043D00014300064B000845 - 00014C06063C00004F0A074000008A00018700028000047500046A03085D0609 - 4903043500003303013606043000004908074C00006701027000008405078000 - 018200008600008700008700018400017D0004760104640000680B0C49000051 - 07073E00004804054501024100003F0000420103390000500F113900004E0D0F - 3E00004201033E0000420103390000500F113900004E0D0F3E00004201033E00 - 00420103390000500F113900004E0D0F3E00004201033E000042010339000050 - 0F113900004E0D0F3E00004201033E0000420103390000500F113900004E0D0F - 3E00004201033E0000420103390000500F113900004E0D0F3E00004202024100 - 004502013C000053100F3C0000510E0D3F00004302013F00004202013900004E - 110F3700004C0F0D3C00003E03013800003C03013500004E110F3A0000530E0B - 4800005300005F03025A00007002027B03047C00008702058700008A00028600 - 018200018000017F00017F00017F00017F00017F00017E00017B00027601026A - 03016206055809064904013D0000420200490401430000580704520000670102 - 6800007D06077D00028000028200018400018200018200018001008001008200 - 008401008400008200007F00017801026D02046205044E00004901013900004E - 0F11390000510B124500024B00034D01024300005609074A0000880006820004 - 7D01076D00026403074F00004301023800003403013401003A00004A00005D03 - 036E03057B02068000028301028301018600008500008500007F000079000470 - 02046200015600004F01024500004701024100004600014300004100013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100024000014000013F00004201033E00004201033E000041000240 - 00014000013F00004201033E00004201033E00004100024000014000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100024000004300004200004502014100004302013F000042010041 - 00004000003E00004303023F00004404034000004303024101003E01003E0100 - 4101004300004700004C00005100005900006804046D02047402027B00028000 - 028600028700028900018700018400007F00007C000078000176000076000074 - 00007502056B00006400005600005001004200003C05003C0200480000520000 - 5A03016104036A04057103037801027C00018300038500028700028600018400 - 018100008100007F00007E03017C03017E06067903027606066900005F000051 - 00004C00014500004300033D00004300054000004700034B00005400005B0000 - 6101016303037D00047D04086B00006D06095100005006063D00003A02013802 - 013900004200004F00006202027103037E010382000183010183010184000084 - 00008100007E00007500036D02045C00005704034500004C06063C0000490506 - 3F00004501024000004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004100023F00004403053A000047 - 06083900004605073C00004100023F00004403053A0000470608390000460507 - 3C00004100023F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004101014000004704033D000048 - 07063A00004706053D00004101003E00004404033B00004908073B0000480706 - 4000004502014300004300004800004C00005201005601005E01006400006D02 - 047201047801027D00028200028600028700028700018600008300007E000078 - 00007301016F01016E01036A0203680203670505550000570402400000440802 - 3500003F03005300005F00006602026D03027303037902037F00028100018500 - 028700028700028600018400018200018000017D01017501007708066B000073 - 0C0A6000006407065100004F00004A00004A04043C00004702054000004F0307 - 4800005801056200006A00006E00027002027602076900006E070C5200005908 - 0B3E00004405073800003D01014100004A000058000069010277020380010382 - 00018301018301018200008200007F00007A00007100036602025A0202480000 - 4F09093A00004B090A3A00004905064200004300033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004201033A000049080A3900004A090B3900004605073E00004201033A0000 - 49080A3900004A090B3900004605073E00004201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004301023B00004A09083A00004B0A093900004606053E00004202013B0000 - 4A09083C00004F09093E00004C04044600004900004E00005300005700005D02 - 006403006904027004037402027801027D000280000282000284000286000286 - 00018500008100007A00007302006C02016703036302046104055F0505530000 - 5A0706470000520B083A00004309034400006102006E01007202027703027D03 - 038001028200018300008600018600018600018500028101028001027E020279 - 03026F05046200006B0C09540000630C0A4A00005106044700004C0404420000 - 5006064300005605084900005D080C6102066F00017900007D00027E02026500 - 016906085000005B080A4000004A08093700004203054100004A000055000162 - 00006E00027901028000018400018102018102018001008001007C0000740000 - 6D00026101015100005107053A00004A0D0B3700004B0B0B3B00004503043E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004201033E00004706083900004C0B0D3900004A090B - 3900004201033E00004706083900004C0B0D3900004A090B3900004201033E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004202023E00004707063A00004C0C0B390000480B09 - 3700004003013F00004807063C0000500A0A4000005208084300005000005500 - 005B00005E00006400006902006F03027404047A03047B00027D000280000282 - 00028400028400028400028400028301017E03017602016E03006402025D0302 - 5603025503025000005704064A00005C0A09470000590E0C4700005806016F04 - 017A02027D03037F03038202038301028400018600018600018400018200017F - 00017C02027903027703027103036200006309094C00005E0C0B430000540A08 - 3F00004904014700005105064900005F0909500000690A0E5E000172070A7B00 - 028301028402038402035C03064D00005608094000004B090A37000045060840 - 00004900005300016000036B00027500037C00018200018400008001007F0100 - 8002017D02007800007001006700005C00005202013F00004B0B0A350000480C - 0C3700004808084100004201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000420103390000 - 4A090B3900004C0B0D3900004706083E00004201033900004A090B3900004C0B - 0D3900004706083E00004201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000420202370000 - 4A0A093700004A0D0B3500004308063C00004404033B00004F09094000005509 - 0A4500005505065200006302006A01006D02006F02007302007802017C010380 - 01038200028200028400028400028400028400028400048000028204037A0502 - 6F04016504005A03015102004A00004900004D00014900005E05085200006B0D - 0E5A00006A0D0C6702007B030382030282030284020286020285010184000184 - 00018100007E00007B01017802017203017003016D04016804025E04044E0000 - 57090A420000500A0A3C00004B08074600004B00004A0000630909570000760D - 106500007A090C7700018102038602028602028602024A00004E06063C000047 - 0A083500004408083900004601044D00005900016700057300037A00017F0000 - 8300008400008001007F01008002017C03017802016D00006300005700004900 - 00470703350000430C09330000460A0A3C00004604053E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004201033E00004605073900004A090B39000049080A3A00004201033E00 - 004605073900004A090B39000049080A3A00004201033E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004202023C0000440705370000460B09350000450A083600004003014000 - 004807063E00005208084500005808094D00005D03036D030274030176020179 - 01017D0101800001820002860002870002870002860002860002840002820002 - 8200047F00027A03017305006804005C03004F02004500004200004300004800 - 005702065300006F080D6500007F0C0F7300017F050584020285010187010187 - 01018701018701018500028101027E00007800007501006F0200690200660300 - 6302005E02015200005405084200004C08093A00004808073E00004B03034C00 - 005F05045D0000790C0E6D0000830B0C77000080010282030283010183010183 - 01014302013D00004206063300003E08083400004304064700015000005F0002 - 6E00067901057E00018200008500008400007F00007D02007E03017A03017602 - 016C01005E00005400004B01003C000040070530000040080736000044060642 - 02024100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004100023C00004605073900004706 - 083A00004403053F00004100023C00004605073900004706083A00004403053F - 00004100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00003F01013800004207053300004108 - 063400004005033D00004303024000004D05054300005606074D00005D060960 - 02037203017B02007D01018000018200018600018700018900018B0002890002 - 8700028600028400028200028000047B00027100006702005E02005301004801 - 004001003D00004000005104085400016A030A6A000085070D8000008E02098A - 0000870000860100870000860000860000840000830101800201790101750100 - 6D02006602006002005A02005700005300005000024700004D03093A00004706 - 083B00004805044900005A04045F000075070972000087080A7F00008B030584 - 00008001007F01007F01007F01003F00003F02003900003D05043701003E0504 - 4000004A00015400006300027201057C01058000018200008500008400007F00 - 007D01017A02027504026F03026302005700004C00004500003F02003800003B - 03023800003F03033F01014404044000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000014000 - 014100023E00004201033E00004201033F00004000014000014100023E000042 - 01033E00004201033F00004000013E00013D01023C00004201033E0000430003 - 4000004100014100014200023F00004201033E00004001033D00003C00013901 - 003A03003700003B04013800003E03013D00004100004600004C01004C000055 - 00005600006103046401036D05067501007A01007F0100800001840001880002 - 8A00028C00038B00028900048600048000047D00047900047800057002046100 - 005A00005600005100004B00004A00004A00014D00015C05096605096D00057B - 03087F00038A01058B00008B0000890000860000860000860000860000860001 - 8301027F03037801026F01016602025E02015302004B01004500004500004C00 - 004E00024900004C01034600004D03034E000057000068060672060576000080 - 01038000008700028700008701018001007C01007E00007C0100430000400000 - 4002023A00003C03023C00004401004A00005E04046802037301017B01018000 - 018301018501018301018301027D00027806066800015F02034F00004A000142 - 00004000013D00004001033C00004002023E00003F02003E00004000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100024000014000013F00004201033E00004201033E000041000240 - 00014000013F00004201033E00004201033E00004100023E0001390100360000 - 3C03023C00004301024100004600024700014700014400004500053F00014000 - 053800013A01043501013202013000003403013200003D04023C00004502004A - 00005000005800006301016A0203730205770205790102780000770500770500 - 7A04007D020080010083000086000086000187000484000582040A7901067303 - 0A6600026000025400004C00004A00004E00005200005800005F00016700066F - 03096F01057201047402027802017B01017D0200820100840100820000850000 - 8700008800018800028800038500057F00047A04096900055A00034800004201 - 033400002F03043100004600005100005500005900005F02016703016E040374 - 04047801027B01017F00018000018200018200018200018200018000017F0001 - 8000017F00014400004703043A00004507073500004606054100004F00006004 - 036A03017301017B01018001008301018301018301018100018205076E00006C - 0A0A4E00004F05053D00003F00023B00024003073A00004706083A0000460606 - 3C00003F02003F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004100023F00004403053A000047 - 06083900004605073C00004100023F00004403053A0000470608390000460507 - 3C00003D01023600003B05043300004307073900004905064100004800024600 - 004902053D000047050A3500003F06093300003402023101003606042D00003E - 09063500004906034600005200005B00006300006D01007601027E0103810003 - 8400018100007A04007705007A04007B03008001008200018400028400028000 - 0580040A6E000172060C5C00005F03084E00004C00034300034400044E000558 - 00026200026D00037600057C00067B00047B00027901017902007902007B0300 - 7F02008002008401008600008701018500028500038000027C00047600036D00 - 056402084C00004C040A34000039070B2800003200004A00005700005E000064 - 01006B02007203017A02027F0303800001820001820001820001800001800001 - 7F00017F00018000018000018000018000014701023D0000490909370000480B - 093900004D06034E00006104036A03017402027B010180010082000083010183 - 0101820104760000790B0D5A00005E0A0C4000004605073B00003E0105360000 - 49080A3900004B090A3900004606053C00004201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004201033A000049080A3900004A090B3900004605073E00004201033A0000 - 49080A3900004A090B3900004605073C00003B0302330000430A093500004A0A - 0A3A00004904074100004500033D00004A070A390000460A0B3300003F060735 - 0000390302340000430A083700004D0A09420000560403530000610101690200 - 7202027A02038102038301028600018300007F02007D02007F01008002018101 - 028101028100037E01037D03096C000070060C5500005F050A47000051040846 - 00024200024801045200055E00056700047100047A00047E00057D00027D0002 - 7D01017D02007F01007F02008201008401008802028801038402038001027901 - 027200006A00026200015E00044D00005506094000004F0A0D3A000045050A40 - 00005601006002006502006902006F02007602017C0202800102800001820001 - 8200018200018000018000017F00017F00018000018000018000018000014300 - 004A06073900004A0C0C3700004B0A094200005200006404046D03027601027D - 01018001008200008200008001007D00007F08096500006D0D0D490000510909 - 3A00004004053A000145050A3900004C0B0D3A00004A0A0A3900004003013E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004201033E00004706083900004C0B0D3900004A090B - 3900004201033E00004706083900004C0B0D3900004A090B3900004001033A00 - 00410807350000480C0C370000480A0A3900004201033E00004706083900004A - 0B0D370000460A0B3500003E02023C00004707033C0000540D0A4500005C0B08 - 5300006203006904027103037803047D03038202038500028700018600008400 - 008201008200008001008001027E02027A02037702056C00026C07095200005C - 080A4300004E08093B00004503044502014D03035804066403076F0105770004 - 7D00048100038000028000027F00018000018001008200008600008600008902 - 048502057F02047702036C02016000005700004F000049000050060642000055 - 080B4500005D090D4E00005C03066303036804006C0300700301740301790101 - 7E02028101028200018200018200018200018000017F00017D01017D01018000 - 018000018000018000014501023C00004A0A0A3900004C0C0B3C00005106044F - 00006604046F03027801027D01018001008200008001007F01007F02046F0000 - 760B0D5300005B0B0C3E00004807093C00013E01053700004A090B3A00004D0B - 0C3900004707063C00004201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000420103390000 - 4A090B3900004C0B0D3900004706083E00004201033900004A090B3900004C0B - 0D3900004706083E0000400202370000480A0A350000480C0C35000041080738 - 00003C0302350000460A0A3700004A0C0C390000470707410000490000450000 - 5809064A0000650E0C5500006C0B086801007205037804037D03038103028402 - 028701018700008700008600008500008400018000017D00027801027002046B - 030460000150000059090A4000004D0B0C3700004007063B00004A0300560502 - 6206056B05067502057B00028000028301028200018200018000018000018200 - 018400018700018600018400067C01057502056A02035C02015101004401003F - 00004205013B000050090647000062070A59000074060C6F0004700403700502 - 7304027703027A02027E02028000018200018200018400018200018200018000 - 017F00017D01017D01018000018000018000018000014100004705063900004A - 0A0A3900004E08084600005700006905057103037901027F0001800100820000 - 7F00007C01007600007707075E0000640A094500004D07073B00004105063A00 - 014404093900004B080B3A00004909093A00004003013E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004201033E00004605073900004A090B39000049080A3A00004201033E00 - 004605073900004A090B39000049080A3A00004201033F000046060639000048 - 0A0A330000420A093300003B03023700003F0706350000480A0A3A00004C0809 - 3F00004C00015000005D04005300006A0C075C0000740D0A6B00007708067804 - 037A02028002018102018501018701018800018800018600008300008100007C - 00007400006D01006501015E02014C00004F04023E00004C0C0B350000420A09 - 3000003E01005204006105006B07037205037A02028000018400018500028400 - 018200017F00017F00018000018200018400028000027700037000036600025E - 01024F02004502003A02003602003901004809054200006009075A0000780508 - 79000085050A7902037504027903027A02027E02028101028200018400018400 - 018400018200018000018000017F00017D01017D01017F000180000180000180 - 00014200013D00004606063900004807064100005402015800006C0405750303 - 7C01038000018200008100007F00007A01007601026A00006907075100005004 - 053C00004304063E02033F00043A00004605073A00004806073A00004404033D - 00004100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004100023C00004605073900004706 - 083A00004403053F00004100023C00004605073900004706083A000044030540 - 00004400023F00004605073700004108073300003B0504360000380300350000 - 4207053900004C06064300004E02035000006102006200007007046700007609 - 076F00007B08057A03017D02007F010080010082000084000084000087010185 - 01018200017E00017700007100006700005F00005500004E01004700003C0000 - 4407053400004209083400003C04034100005E03006C04007504017A03018001 - 008600008700008802028200017F00017B00027901027901027901027B000478 - 00046600005D00005700015000014701013F02003902003801003C0200410000 - 5B0A075C00007606067500008B02068800037F00017B01017D01017F00018000 - 018200018500028700028600018400018200018000018000017F00017D01017D - 01017F00018000018000018000014100004200013E00004301024100004B0101 - 5000005C00007003057902038001038200018200008100007E00007A01007000 - 006B04025D00005502004600004201003E00014004053E00034100043F000043 - 00033F00004202023D00003E01004000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000014000 - 014100023E00004201033E00004201033F00004000014000014100023E000042 - 01033E00004201033F00004100014300014400023F00004001033800003B0302 - 3600003701003902003B02003E00004502014700005000005000005900006D03 - 027605037401007B06037700007D04027C01008002018001007F00007F00007F - 00007F00008001008102017F03037801027301016D00026600015C0000520000 - 4A00004500003F00003D03003700003C03013700003E02023E00004C01006703 - 007804007C04008103008500008800008700008602027F000179010174020270 - 02027002047002047002046B02055500004E00004900004700004201003F0200 - 3E01004001004000005103005F0400710A077802018402038700008900018100 - 007F00007F000082000184000186000187000287000286000184000182000180 - 00018000017F00017D01017D01017F0001800001800001800001420202410101 - 4404044000004701014A00005901016300027002047901028000028400018400 - 008200007F01007902007103036400005B01004E00004A02023F00003D01023A - 00003E00033F00024300034100004301023E00003F02003E01004000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100024000014000013F00004201033E00004201033E000041000240 - 00014000013F00004201033E00004201033E0000410002410001440002420000 - 4300033E00003E02023800003B02003900004005034202014400004700004E00 - 005600005E01026804047403017B02007D02007D02007F010080010080010082 - 00008001007F00007E00007C01007B02007A03017A02027605036D0506640202 - 6103045400005000004500004502003F02003C01003900003C03013A00004202 - 013F00004400015100006F03007D010080000084000087000088000088000281 - 01027901027101016F07086503036706085F00005F00005600004C0103430102 - 4400014300004200004500004700004D00005D06046405026D03027403017B01 - 0182000086000087000084000184000184000186000186000186000186000186 - 00018400018400018200018000018000017F00017D01017D01017F0001800001 - 8000018000014000004606063C00004907084000005404055600006801047401 - 047D00028200028400018400008200007F01007803006C02016506034F000053 - 06033F00004707063800003B01023D00024402073B00004A05083A0000460606 - 3A00003D02003F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004100023F00004403053A000047 - 06083900004605073C00004100023F00004403053A0000470608390000460507 - 3C00004200024200004702053B00004805083900004305053900004000004502 - 014801004C00005000005A00006000006703037004037B010180010080010082 - 00008200008200008400008200007E00007C01007C03017A0502750402720301 - 6E01006601005F02035B08074B00005207053E00004607033B00003D05003900 - 003E05033600004707063C00004D050545000056000074060281040085020087 - 01018700008600008100007A00017202026E08095C0000620A0A5100005A0608 - 5100004E00014100003C00004000004600004B00005200005900006000006B04 - 027002027602017B01017F010080010082010084000086000186000186000186 - 00018700018600018600018400018400018200018200018000017F00017F0001 - 7D01017F00018000018000018000018000014103033A00004B0B0B3C00005309 - 094900006305066900017800047F00028400028600018400008200007D020076 - 03006B06045800005B08064300004E0B0A3700004206073800004000053A0000 - 4A070A3C00004B090A3900004407053A00004201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004201033A000049080A3900004A090B3900004605073E00004201033A0000 - 49080A3900004A090B3900004605073E00004401063C00004A070A3A00004C08 - 093C00004903034500004D00005200005800005F00006600016C020171030379 - 05047F01008200008200008400008400008400008200018000017D0000790101 - 7804037205036E04036702006000005700005404034400004F09093A00004909 - 083500004108063A01003C0301360000470A083A000051090943000052040553 - 00006F04017A03018103028303048402038201047B00027300036F07085C0000 - 610B0B47000057090A4300005104074700003E00003C00004300004C00015700 - 036201036D02057502057901027D00027F00018000017F01007F01007D02007F - 0100840001870001870001870001860001860001860001840001840001820001 - 8200018000017F00017F00017F00017F00018000018000018000018000013C00 - 00460808390000500C0D4300005C080A5900007002067B000482000286000287 - 00018600008200007D0200740300650100600905470000550C083A0000480D0B - 3400003C02033C000147050A3A00004F0A0D3A00004A0A0A3700003E03013E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004201033E00004706083900004C0B0D3900004A090B - 3900004201033E00004706083900004C0B0D3900004A090B3900004201033E00 - 0147050A3A00004F0A0D3E00005207094500005200005900005D00006501016B - 01007202027703027903027D0303800100840000840000840000840000820001 - 8000017F00017B01017702036F03026903046101015A00005300004C00004400 - 00480706390000490C0A350000460B093400003E05033A00004508063900004F - 0C0B4000005309094300005300006100006A00007000007702037B0307790407 - 7204066D04075F0102600A0A450000560C0C42000051080A4200004A01034400 - 004700004E000159010165020470030579040781030880000284000284000182 - 00018001007F01007B02007D0200840001870001870001860001860001840001 - 8400018200018200018200018000018000017F00017F00017F00017F00018000 - 018000018000018000013E02023800004C0C0C3C0000560A0B4C00006906086D - 00027D00048400028700028900018600008200007D0200720400670603500000 - 570A074000004D0D0C3500004208093800004000053900004B080B3C00004D0B - 0C3900004508063A00004201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000420103390000 - 4A090B3900004C0B0D3900004706083E00004201033900004A090B3900004C0B - 0D3900004706083C00004101063700004A090B3C0000550A0C4700005C030658 - 00006601036C01037201047702037A02037E02027F00017F0000820001820001 - 8200018200018200018000027F00027B00027803046F02046501015C00005300 - 004E0000480000450000430201390000470909370000490B0B3700004507073D - 00004202013900004B0A093C0000510B0B3E00004C06064800004F0000570000 - 5D00006402026803056803056502046002065801044A0000560B0D400000560B - 0D4200005104074B00005600005B01006100026701027002047702037F020483 - 02058400028600028600018400018200017F00017D01017F0001840001860001 - 8600018400018400018400018400018200018200018000018000018000018000 - 018000018000018000018000018000018000018000013A000044060639000050 - 0A0B4300005D06095F00007403077D0004860002890002890001860000800100 - 7D02007204006001005A08034300004F0B06370000450C0A3500003D03043C00 - 014604093C00004D080B3A00004909093800003E03013E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004201033E00004605073900004A090B39000049080A3A00004201033E00 - 004605073900004A090B39000049080A3A000040010338000140050939000050 - 090C4500005F080C5A00006900037001057702057C0103800102810102820001 - 8100008100008200018200018200018200018000027F00027B00027801027002 - 046701025C00005000004800004300004000004002023D00004505053900004A - 0A0A3A00004A08093C00004301023F00004706053C00004B0A093A00004A0908 - 3A00004302014401004800004D01025101025600025500015400015100004A00 - 004F0406400000530A0C42000057080B4C00005A00026802036E020171000374 - 02027801027C0103800103830003840002840002840001840001820001800001 - 8000018000018400018400018400018400018400018200018200018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00013D01013A00004707073F00005305065100006A03067300047F0004870002 - 8B00028B00018600008001007D02007204006104014F00004F06023C00004609 - 073600003F06073A00013F00043C00004904073C00004806073A00004205033B - 00004100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004100023C00004605073900004706 - 083A00004403053F00004100023C00004605073900004706083A00004403053D - 000039000335000045060841000059080B5700006C050A6E00037800057D0004 - 8200028400018600018600008701018501018200018000018000028000027F00 - 027D00027900047401046800006000005500004B00004300003D00003A02013C - 02034201033E00004A05083D00004D07084000004B02044300004600013F0000 - 4706053900004508063600003E05033601003704023903023E02024200014800 - 014900004900004900004A00024300004C03054200005405084D00005C050963 - 00047800047F00017F00027F00017F00017F00017F0002800002800002800002 - 8200028200028400028400028400028400028400018400018400018200018200 - 018000018000017F00017F00017F00017F00017F000180000180000180000180 - 00018000018000018000018000013E00003F01013F0000460203480000590003 - 6700017901068400048900028900028700018400008001007D02007203015C03 - 004E04004500004303003D00004005033B02013E02034000014200023F000043 - 01023F00004202023D00003E01004000004101013E00004202023E0000420202 - 3F00004000004000014101013E00004202023E00004202023F00004000004100 - 014200013E00004202023E00004001033D00003C00013E00013F00023C000042 - 01033F00004300034200004100013E00004200014600005404055A0002690406 - 7201057B02067E00028200008500008800008900008800018901028703037F00 - 017B00027B00047900047601047201046F02046902055800005200004D000047 - 00004200013D01013A02013900013F0002430204410001470205420000480203 - 4500004700004700004600014100004202023C00003E02023800003502003002 - 013002013301013900014000014400024900024D00034B00014D00014B000052 - 00005300006100026702047406087E0001850000840001820001800001800001 - 8001038001037F00027F00028000028200028400028400028600028600028400 - 018200018200018200018000018000017F00017F00017F00017F00017F00017F - 00018000018000018000018000017F00017F00017F00017F0001460001400000 - 3F03033B00004701015200006E00047F00058900048D00028700028200017F01 - 007D02008001007403015100004200004303003F00004202013E000041010040 - 00004100004000004301023E00004202013C00003F02003E01004000003F0000 - 4301023F00004301023F00004200014100004100004000004301023F00004202 - 023E00003F01014000004300004200004301023E00004002023800003A020137 - 01003C03043A01023F03043E00004500034500004B00054A00004D0000540000 - 5E02016703017004037902037F00028500008900018D00008C00008A00008800 - 008700008502008203027800047100047304086C01046805075B00005400004B - 00004A00004400004502013E00004003013C00003D02003A0100390100380000 - 3C03023A00004202023F00004600024700014700014600004700034100004300 - 033E00004100023A00013503053001033604043800004103034200004C000150 - 00005600005D00006600016E02017503037903027B01017E0000800001820001 - 8200018000018000018000018000018000018000018000018000018000018200 - 0182000182000182000182000180000180000180000180000180000180000180 - 00018000018000018000018000018000018000018000017F00017D00027B0002 - 7B00027B00024600004703043500004108073C00005804066C00008400078D00 - 048F00028600028000017B02007B02008200007602014F00004404033A000047 - 07063A00004706053D00004201004000004504033A0000470706370000440705 - 3A00003F02003F00004404033B00004807063A00004706053F00004201004000 - 004504033B00004707063900004407053A00004101004200004903033B000047 - 07063500004007053300003802013701013E0405380000480508400000530308 - 4C00005700045B00006100006902007203017A02028101028600008A00008D00 - 008F00008D00008900008600008302008102017C020272010571050B62000067 - 060A510000570406460000470101400000420503360000430806370000440705 - 3C00003F02003900003D05043400004307073700004606063F00004400024400 - 004902053F00004A040A3A00004704093C00003D00043700033B060933000042 - 08093A00004D05054A00005600005E0000660000700000790101800201830101 - 8601008500008200018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000017F00027D00027F00027D00024900023E0000430A093300004D0A - 094A00007504088100048D00048F00028600028000017B02007B020082000076 - 02015200003B00004A09083A00004B0A093A00004706053F00004302013B0000 - 490908390000480B093700004407053C00004202013B00004A09083A00004B0A - 093A00004706053F00004302013A0000490908370000480B093500004207053C - 00004301023D00004A0809390000460A0A3300004007063800003D0101390000 - 4B070842000059080B4B00005F050A5D00006501006B03007004007704017F04 - 028301018700008800008B00018900018901038602028102037C030179010173 - 01017305096300016A060B5200005B0407450000500606440100420201380000 - 450A08350000480B093900004706053F00004301023A00004A08093900004B09 - 0A3A00004704073F00004201033A000049080A37000048090B3500004206073A - 00003D030437000048090B3A000052090B4500005805045900006501016B0100 - 7402027A02028103028301018401008300008200018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018200018600028600028700028600024500 - 004A0607330000460D0C3C00005D090B6700008501088D00048D000286000280 - 00017B02007D02008200007602014F00004807063A00004D0C0B3A00004B0A09 - 3A00004302013F00004807063900004C0C0B370000480B093700004202013F00 - 004807063A00004D0C0B3A00004B0A093A00004202013E000045080637000048 - 0D0B350000460B093500004003013F00004806073900004C0C0C370000480A0A - 3700004202023C00004C04044300005C090B4E0000690B0C5E00006B05066F04 - 017504017A05027D040282030285010186000087000087000185000284020380 - 03057B04057303036E00006A000165000268070B5200005F0609490000520607 - 3F00004605043E0000450806350000480D0B3900004A0A093A00004502014500 - 004E05073E00004F0B0C3C00004B090A3900004001033A000043070833000046 - 0C0D330000440A0B3300004001033D00004B0407420000570A0D470000610A0D - 5700006604046B03047103037804037B03038103028102018401008400008200 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018200018900 - 018B00018B00028B00014A01033D0000450C0B3300004C0B0A4A00007305097E - 00038B00048D00028600027F00017B02007D02008200007802015500003C0000 - 4D0A093C00004F0C0B3C00004807063F00004202013900004A0A093900004C0C - 0B3900004707063E00004302013C00004D0A093C00004D0C0B3A00004707063C - 0000400301350000460B09350000480D0B3300004108063A0000420103390000 - 4A090B3900004C0C0C3A00004A07064300004C00014700005E0808520000700B - 0D5F000076090B7301017B04027F040081040082040086020285010186000184 - 00018200028001037B03047704076F04066802036000005D00005E0004500000 - 5E070A49000055090A4000004906053E0000400301350000460B093500004C0C - 0B3900004807064300004C000245000054070A4000004F0B0C39000045070738 - 00003B0302300000410B0A300000450D0C3300004108073F00004B00004A0000 - 5D060A4E00006A0C10590000700B0D6B03047204067604047A04037D03037F04 - 0281020182000082000080000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018200018900018B00008B00018B000045000049050633000044 - 0B0A3A00005A07096700008201088900048B00028400027F00017B02007D0200 - 8200007802015100004B05053E00004D0A093C00004C09083B00004302013E00 - 004606053900004A0A093900004909083A00004302014100004906053C00004D - 0A093A00004909083800003E03013A0000420705350000460B09330000430A08 - 3400003E02023C00004604093900004B080B3C00004E08094300004E00015200 - 00600605570000700B096400007C0A0A73000081050582040085020085020085 - 02008701018501018301028101027D00027901057103056A03066302045C0104 - 5500015100004E0000560305450000560A0B4000004C09083A00003F02003A00 - 00420705350000480B093900004909083B00004701014A000054030643000051 - 080A3C00004709093400003B03023500003B0806300000430B0A350000470909 - 3A00004B00025200006400055800006F090E5E0000750C0F6D000278070A7604 - 047902037A02027C02027E030180020181020181020180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000182000186000086000087000086 - 00004B00024000004007063200004606054A00006E03067C0004870004890002 - 8200027D01017B02007D02008200007802015600004300004D05053E00004A07 - 063D00004504034000004101003C00004407053700004707063A000044040340 - 00004401004100004906053C00004807063A00004205033B00003D0200360000 - 4007053300004308063600004005033B00003F00023C00004704093C00004E05 - 074400005401035400006305066400007408076C00007E080777000085060584 - 01008700008701008700008700008600008200008001027C0103770205700305 - 6702045F01055700034E00024A00014700004A00004500004D05053F00004B08 - 073B00004306043B00003D02003800004407053700004707063A000045040344 - 00004B00014800004F03073C00004707073600003D0504360000380300330000 - 4007053700004A07064100004D03035000006801066A00007405096B00007908 - 0C7000007C070A7901057901027901027B01017D01017F00017F000180020181 - 0201800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00017F01007D02007F01007D02004900004501023900003B03023D0000510102 - 6700017C00068700048900028200027D01017B02007D02008200007901015700 - 004A00004700004901014300004502014000004000004000004101003C000040 - 03013E00004202013F00004100004300004600004100004302013F0000400301 - 3D00003C01003A01003B02003800003E03013A00004003013D00004000004100 - 014400044300014B00034A00005300015600005C00006C06077406067602017E - 05037D00008403008500008902008901008800008800008500008100007F0001 - 7A02037603067104066803055D02055400044C00024600024100014000014400 - 014701014100004302013E00004104023D02004005033C01003D02003C000040 - 03013E00004202014000004300004700014800024100004201033A00003C0302 - 3600003701003902003D02003F00004901014A00005300005400005E00007403 - 077D03097900057D04087800037D02067A00037B00027D00027C00017C00007C - 00007E00007F0001800201810302800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000017F00017B0200790200790200790200490000430000 - 3E05043800004205034D00006902057A00068600048700028000027D01017B02 - 007D02008400007B01015F02034E00014C00014600004701014100004302013F - 00004000003D00004003013C00004202013E0000420100410000430000440000 - 4502013F00004302013C00003F02003C01003D02003B00003F04023D00004404 - 034000004403024400014801044900034900004C00005300005C00026502046D - 05066F01037500017A00008001008400008702008A01008A0200890000860000 - 8500008100007F00017A02027503036F04065E00005600005200014700004500 - 033E00013D00043C00014000004000004202013C00004003013A00003D02003C - 01003C01003B00004003013C00004202013E00004201004100004100023D0000 - 3F03043900003D05043800003C05023B02004303024701014B00005100005900 - 006100006A01047403067B000480000480000480000480000480000280000280 - 00027F00027F00017F00017F00017F00017F00017F00017F0001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000018000018000018000017F00017F04027D0402 - 7C03017B02004800004804053600004109083800005406076300007A02078400 - 048600027F00027B01017902007D02008400007B010161000255050646000050 - 04054000004906053D00004101003D0000420503380000450806390000460605 - 3D00004401004400004903033D00004807063900004407053800003D02003B00 - 004205033B00004807063D00004C06064400004B01014B00004E000052000158 - 00025F00046601036D02047303037700017A00007E0000820000860100880100 - 8A02008801008400008100008101027F03037903027202026901026300025600 - 005401034400004A06073900004205093500003A01023B000042050338000045 - 08063500004207053800003D02003B0000400503380000450806390000460605 - 3D00004101013900003B05053400004007083300004108073B00004302014600 - 004E00005800006100006A00017000027601047C010382000484000284000484 - 00028400028200028200028200028200018000018000017F00017F00017F0001 - 7F00017F00018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000017D00007E00007F00018002014C0002400000440B0A320000490C - 0A4400006B06087400038200048400027F00027B01017902007D02008400007D - 01016603054F00005707084500005309093E00004706053E0000400301360000 - 450A083700004A0A093900004706054100004701013F00004C09083A00004A0A - 093700004207053A00004104023B00004A09083E00005309094300005404054E - 00004F00005400005C00026302046B04077104067502057901027C00017E0000 - 8200008400008401008601008702008502007D00007901017A03047404047004 - 036701025C00005500005200014400004E0809390000460A0B3300003F060937 - 00003E0202360000450A08350000460B093500004407053C0000400301380000 - 4909083900004A0A093900004706053C00003A04042E00003E0A0A300000440B - 0A3900004B05054800004D00005800006400006F01037803067D020480010382 - 0001860002860001860002860001860001840001840001820001820001800001 - 8000018000018000018000017F00017F00018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018200018300008500008500018500004800 - 004D0708330000440E0D350000550B0B5C00007802078000048200027D000279 - 01017902007D02008400007D01016400015E070A490000580A0B420000500A0A - 3B00004104023C0000430806350000480D0B3900004A0A093C00004502014300 - 004A07063A00004C0C0B390000480B093500004003013E00004807063E000055 - 0B0B4500005B080A4D00005A00025A00006000006701026E0305750407780304 - 7C01037F00018000018200018400008200008201008201008002007D02007601 - 027103056D02046902056100025A00005100004A00004700004A07063A00004A - 0C0C350000440A0B3200003C02033A0000430806350000480D0B370000480B09 - 3700004003013C00004508063900004C0C0B3900004A0A093A00004002023300 - 003A080A300000460C0D39000052090B4800005800025C000065000070000279 - 0203800305820203830102840001860001860001860001840001860001840001 - 8400018400018200018200018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018200018400 - 028400028500038300014D00033F0000460D0C300000480D0B42000068050770 - 00017F00048200027D00027901017902007B02008400007D0101690406530000 - 5D090B470000560C0C3E00004908073C0000400301350000460B093500004C0C - 0B3900004A07064100004502013C00004B0A093900004C0C0B3700004508063C - 00004403023F0000540A0A4700005F0B0D4E00006204085E00006802036C0201 - 7002027402027901027D01018000018400018400018400008400008001007F01 - 007D02007B02007602016D05066403055F01025A00025100004E000048000045 - 0000430102390000480A0A350000480C0C3500004307073A0000400301370000 - 480B093700004C0C0B3900004707063E00004202013900004A0A093900004C0C - 0B3900004707063C00003C0304310000470B0C3A0000570C0E4A000062040861 - 00006E00047300037900047D00027F0002800001800001820000820000840000 - 8400008200008400008200008200018200018200018200018200018200018200 - 0182000182000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000017F00027A00017900027C00047C01054900004C060733000041 - 0B0A3500005008085900007300047F00048000027B00027901017803007B0200 - 8400007D010166000260070A4A000059090A430000500A0A3D00004104023A00 - 00420705350000460B093900004909083D00004502014100004906053A00004A - 0A09390000470A083800004202014100004D05054500005D090B50000067080C - 5E00006B02057305057605027802017900007D00008000008500008700018701 - 018701018200008001007B02007902007502006E02016204055902065300024D - 00004700004300004100004202023C0000420606350000460A0A350000470909 - 3A00004202023C00004407053900004A0A093900004909083A00004202013E00 - 004606053900004A0A093900004909083A00004002023A00004205093A000055 - 090D4A000067070D6300007201057B03087D02067F00027D00007D00007D0000 - 7C01007F01008001008001008001008001008200008200008200018200018200 - 0182000182000182000182000182000182000182000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000017B00027100046C01046D00056A - 00024C00024200004108073000004007054100006201036D00007D0004800002 - 7B00027901017803007B02008400007F00016C03065800005B04074800005206 - 074400004706053E01003D02003600004207053500004707063A000047040342 - 00004401003F0000470605390000470706380000440403400000450000450000 - 5505064F000065070B5F000070060C6F01057703027903007C01007E00008200 - 008400008800008900008800018701018301027F000179010175010071020068 - 03015600034E00034A00014600004100003F00003D01023C02033B0201360000 - 4207053500004508063A00004504034000004101003C00004706053A00004807 - 063B00004504034000004201003D00004706053A00004707063A00004205033D - 00004000013F00005004084C000065070C62000177050C7900057E0006800004 - 7F00017E00007B00007700007702007902007D02007F02007F01007F01008001 - 0080010080010080010080000180000182000182000182000182000182000282 - 0002800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000178 - 01026201035602045600035200004A00004802033B00003B0401380000460100 - 5A00006C00017900047F00027D01017B01017B02007D02008200007D01016F01 - 036502045900005400024800004805043F02003C03013A01003B02003A000040 - 02023E00004301024000004100004000004101013E00004202013F0000430201 - 4400004900004C00005200005600006201036500017204087302067A05087800 - 007B00007F01008100008601008700008900008700018700028101027C010376 - 01026F03026802036503035C04044800004400004200004100004100023F0101 - 3D01023C00003C00003D01013C00004202013F00004502014400004300003E01 - 003D02003C00004202013F000043020142000045000045000044010043000045 - 02014100004303003F00004300004A000052000156000062010567000375030A - 7901068103097C00017E00007F00007F00007D02007902007803007902007D02 - 007F01007F01007F01007F01007F010080010080010080000180000182000182 - 0001820001820001820002820002820001800001800001800001800001800001 - 8000018000018000017F00018000018000018000018000018000018001007F01 - 007F01007F01008001008001008001008000018000017F00017F00017D01017D - 00027B00027901027901026F02044F00004600004800014A01034B0002450000 - 4303023C00004104024400005401005F00007302057D02048202038301027E00 - 007C01007C03017C04047800037502056B04075100004600003A000039060333 - 03003701003900004201033F00004300033F00004100043C0003380000360000 - 3E04054000004802024600005000005500006605026B04027002027402027900 - 047B00047F00047F000481020382030284020285010186000086000085000081 - 000183030879010672040A6200035902054B00004800013F00004100003F0000 - 4202023E00004202023F00004200014100004300004200004502014300004701 - 014300004800004100003901003500003C04033B00004404044300004802024A - 00004900004A00004B00004A00004700004400004200004A0000680404720104 - 7401047402027801027901027B00027B00027D00027F00017F00017F00017F00 - 017F00017D01017F00017F000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001820001820002820002 - 8200018200018000018000017F00017F00017F01007D02007F01007F01007F01 - 007F01007F01007F02007E04007C04007D03007F03008002007F01007F00007E - 00007D01017B00027D06077502057305076800006300005600004D0003430003 - 4100013E00004700004A04053C00004707063900004906034B00005C00006F03 - 027B03048202038500028200007C01007904017A04037C000081060A6700005E - 04033E00004008033101003405013401003E05043A00004A040A3C0000470409 - 3C00003D00053600023C06063800004806074300005603015600006502006F04 - 017602017901017F000180000282000284000484000282020381020182000081 - 000083000083000182000480000578000774060C5F00015F080C460000480508 - 3600003900013B00004205033800004707063A00004706053F00004600004400 - 004903033F00004C06063E00004B05054100004201003A00003D050435000044 - 08083800004707073E00004701014902004A00004900004A00004D0000500000 - 5201005D00007601027F00017F00017D01017D01017D01017D01017D01017D01 - 017D01017F00017F000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018200028400028200018200018000018000017F00017F00017F01 - 007F01007F01007F01007F01007F01008002007F02008004008004007F030080 - 02008002008002007F01007D01017901027B06076A00007008095C0000620405 - 5400005200024000003D00003F00004302044903043F0000490909370000480B - 093C00005306045700006C02017902038102038301028001007E00007A03017B - 0303800103760000770A0C5000005208063500003C0906320200390302340000 - 49080A3A00004D070D3A000046030A3C00024003073B00004E0A0B4200005A08 - 075000006908056B02007403017902007D010180000182000284000286000284 - 00028101027F01007E00007D00007E00017F00027F01067B0307720007610000 - 66080D4A000055090D3A00004005093800004002023A00004909083900004B0A - 093A00004706054100004502013D00004C09083C00004D0A093C000047060541 - 00004701024000004C0809390000460B093300003E0704370000400300410100 - 4700004E00005600006000006901027202027B00028000018000017F00017F00 - 017F00017F00017F00017F00017F00017F00017F000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018200018200018200018200018000 - 0180000180000180000180000180000180010080010080010080010082000082 - 01008402008601008702008502008302008102017E03017A0202780606690000 - 6E070A5500006106094A00005703074B00014702054201034000013D00004000 - 004907083700004A0C0C3700004C0B0A4500005901016701027402027E010381 - 01028000017E00007B02007D04027D00008207096400006A0D0C4300004A0B07 - 3300003B06033700004307073900004D0A0D3C00004B080D3900004200054100 - 00500709450000610E0D5200006D0C096600007807047902007D020080000182 - 00018400028400028600028200027F00017B02007B0101790101790102760102 - 7300036E00046100006304084C00005A0B0E4000004B0A0C3600003F03043C00 - 004707063900004C0C0B3A00004B0A093A00004202013E00004707063900004C - 0C0B3900004A0A093700004302014900005304074200004E0A0B370000430A08 - 3200003B04013C02004200004C00005700006400006F00017900047F02048000 - 018000018000018000018000017F00018000017F00018000017F00017F00017F - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0182000182000182000180000180000180000180000182000182000182000082 - 00008400008400008400008600008900008900008800018701018301017E0202 - 7903027303036A00016A07095200005E070A4700005306094100004903043E00 - 003E0000400001430204440404390000470B0B3500004A0D0B3A000051070552 - 00006400006E00007A02038001028000018000017F0100800201830205760000 - 7A0C0C5600005F0E0B3E00004508063A01003C03023500004A090B3A00004D0A - 0F3A000047050A4100014C00004C0000650C0F56000075100E6400007B0A0877 - 00007F01008201008400008400008600018600018400028200027A0000780201 - 7803047604047103056B00026200005C00005A00024B000057080B4200004F0A - 0D39000045050A3C00004202023A00004B0A093A00004C0C0B3900004707063C - 0000400301370000460B09350000480D0B3500004308063E00004E0104480000 - 5408093E00004C0B0A3900004508043F00004300004C00005A00006501017201 - 047B000483000384000282000182000182000182000182000180000182000180 - 00018200018000018000018000018000018000017F00017F0001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000182000182000182000182 - 00018400018400018400018400018600018600018600018700018C00018C0001 - 8700018400017F00017700016F01036801045E00014E000059090A420000510B - 0C3A00004605073B00004302044201034000013D00003C000043070733000044 - 0B0A3500004A09084500005502015F00006A00017601027F0204810102820001 - 8001008101028100008205076A0000720E0C4D00005208043D00004306043C00 - 004406063900004B080B3A00004A070C3A00004900034E00006204055D000078 - 10116800007F0C09740000810201840100860100860000860000840001840001 - 8200027F00027700017402027103036E04036703035D00005400004D00004A00 - 004F05053E00004D090A3A000049080A3B00004302043F00004706053A00004B - 0A09390000470A083800003E03013A0000400705330000440B09330000430A08 - 3400004003014500005005074200005008084200005309094900005604035500 - 005E00006901027302057B020681010684000282000084000182000182000182 - 0001820001820001820001820001820001820001820001800001800001800001 - 7F00017F00018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018000017F00017F000180000180 - 0001820001820001840001840001840001840001860001860001860001860001 - 8600028700028800038700038200027C00037400026C00016400015A00004C00 - 004E04043E00004C0C0C37000045090A3300003A00013A00003E000040000143 - 02043D03043700003F06073300004307073B00004C04044E00005B0000660001 - 7202027B03048001028200018400018400018503047800007B0607650000660A - 094A00004C02004502004101003C00004606063900004706083A000045020748 - 00005A00006200007407096C00007F0908770000830403820000870000870000 - 8600008400008200018000017F00027B00027301016B00026600015F00005900 - 005200004C00004600004502013D00004707073800004706083B000044030540 - 00004200013F00004706053A00004707063800004005033900003B0200350000 - 3F08053200004009063300003E05033900003F04023D00004906054200005906 - 055600006A05076D00037100017600027B00047E00058102048001037E00017D - 0000820001820001820001820001840001840001840001840001840001820001 - 8200018200018000018000017F00017F00018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00017F00017D01017F0001800001820001820001840001840001860002860002 - 8600028600028400028400028400048200048101067A01057601046E00036500 - 015C00005300004C00004500003B000042060734000041080B3400003C030638 - 00014304064302044100023D00003A01023C03043800003D03043A0000430303 - 4500004E00015400006000006D02047604047C01038000018400018600018301 - 027D01017500007307066400005800004B00004B04014300004101003E000042 - 02023E00004201034000024A00015E00006D00026E0000790302760000800100 - 8200008702008700008700008400008200017F00017D00027901027601046C01 - 036501015D00005300004E00004900004502014404033D02003D040239000040 - 04043D00004302044000004200014300004401003F00004202013E00003E0301 - 3B00003A01003902003A03003800003C03013800003E03013B00003C01003B02 - 004003014300005000015800006A01047400037F010784000687000587000584 - 00027F00017E00017C00017D00027F0001800001800001820001820001840001 - 8600018600018400018400018400018200018200018000017F00017F00018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000017F00017F00017D01017F00017F0001800001820001 - 8400018400018400028400028400028200028200048000047F00047900047203 - 076A03066502045E00045500014E00004500003E00003B00003A020136000039 - 03033400003B02053900033C01053B00003E0000400001430204370003380002 - 3B02033800003E02023E00004401004900005100005A00006301016F03027902 - 038001038500008400008200017F00017A02027403016B010061000054000049 - 00004901014100004303033C00004302043F00004401044B00016502046F0103 - 7200007600007B00007F00008401008601008802028300008202037B00007C04 - 057601047605087005086000005800005700014E00004C00014100003F02003A - 01003901003600003B03023800003E02033E0000420002430000430000420000 - 4302013E00004202013A00003D02003A01003B02003A01004005033E01004205 - 033F00004201004000004101004300004B00005800006500027200037C000384 - 00048A00058C00058C00038700028400027F00007C00007A00008004047F0303 - 8001028000018200018400018700028700028600018400018400018200018200 - 018000017F00017F000180000180000180000180000180000180000180000180 - 00018000018000018000018000018000018000018000017F00017E00007C0100 - 7E00007F00018000018101028300038300038300057E00028100057B00007C00 - 067700037B03087203075A00004F00004E00014700004701023F00003F010139 - 00003C03043802023B05053500003B02033700003B0002390000430204420103 - 4000013D00003600023D04073400004307083700004606063F00004800004B00 - 005300005E02016802037503037D00028500008600008200017F00017E020279 - 03027101016700005B00005000004A00004805043B0000450707390000460507 - 3E00004D00036201036D00027000027500017B01017F01008200008200008200 - 008505067500007C07086A000072070A6500016504085800005700034A000051 - 05063E00004606053600003A03003600003B0504310000400807350000460507 - 3D00004400014200004504033B00004707063700004407053800003D02003C01 - 004306043B00004908073F00004D05054600004C00015101005401005B010163 - 00026D00037600057D0004850005870004890002880001860001830000810000 - 7F00007C00007B03037A02027C02027D01018000018200018500028700028600 - 018600018600018400018400018200018000017F000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000017E00007C01007E00007F00018000018101028100038100037D00 - 0281030876000080080D6E000075060A6A00006302064900004504033A000045 - 07073500003F06053400003901003700003D0405340000410708350000440507 - 3C00004100023B00003D00003F00004302043B020533000045080C3700004A09 - 0B3A00004705064100004800004E01005702006303037002027B000284000286 - 00008100008001008001027E02027801027000006500005A0000500301410000 - 490908350000480A0A3900004806074A00005C00006500006B00027202027702 - 037A02027E02027D01017F05057400007C0A0A6300006F0A0C57000060040954 - 00015200024600005207093E00004B090A370000400706370000390302310000 - 420A09330000480A0A3900004705064100004302013B00004A0908390000480B - 093700004407053C00004303023E00004E08084200005608094900005A030659 - 00006702046C01046E00047001057201047502057901057A01057B00007D0000 - 8100018100008300008500008500008100007802017203017602017901017D01 - 0180000183010287000286000186000186000184000184000182000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000017E00007E00008001008001008000 - 018000018001037E01037C01057200007E0A0F660000730C115B00006203074F - 0000430303320000400A09320000420A093300004004043800003F0000390000 - 4806073A00004D090A3E00004D07084500014502054201034000013D00003700 - 0141060A3700004C0A0F3A00004B080B3A00004301024300004800005202015D - 03026C01037901028400028600018100008001008200018101027E0103780102 - 6E01036303034F00004F0805390000480D0B3700004B0B0B3C00004D02045400 - 005D00006601036C040571040674040477020376010273010177090B5F00006E - 0B0D5000005C070B4500004C00034700004E05073E00004D0B0C390000460A0A - 3300003C0302370000410807330000480C0C3900004B090A3A00004301023F00 - 004707063900004C0C0B370000480B093700004202014200004E06064500005C - 090B4E000066070B5800006900057701067C00067A00067A0006790105780004 - 7601047800047800017800017C00007E00008000018400018600018000016F00 - 006B02006F02007403017901017D010180000184000186000187000186000186 - 0001860001840001820001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018001 - 008001008001008001008000017F00017D00027901027500037A090D61000071 - 0D125200005F080C4900004800013800003A0907300000450D0C350000490909 - 3C0000460001460000500306430000560A0B430000540A0A4500004B02043E00 - 003E00004000014302043C00063500004A080D3A00004F0A0D3C00004806073E - 00004000004201004B01005702006701027601048200028700028100007F0000 - 8400008501018301027E02027303036905055502014200004B0B0A350000480C - 0C3700004B07084600004D00005200005B01016104036905056C04056F02046E - 01036F0406610000690A0E4C000058080D4000004603083B00004300033A0000 - 4A090B3900004A0B0D3700004307083A0000400103370000480A0A3900004C0C - 0C3A00004806073F0000420201370000480B093700004A0D0B37000047070641 - 00004A02024600005C080A5200006C080D5D000074040B7100027F0005820004 - 8000048000047E00037C00037A00017A00017901027901027901017A02027C03 - 017C03017E03017904016800006401006902006F02007602017A02027F000182 - 0001860001860001870001860001860001840001820001820001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018001008002008001008001007F00017D01017B000276 - 010475060A6500006B0A0E4E00005A090C4200004A05083C00003C0403320000 - 460B09390000530B0B4300005704065100005D020554000062090C4C00005D0A - 0C4700005204054600004602034201034000013D00003A000242040A3A00004D - 070D3E00004E070A3B00004002023C01003E0100470200510100630101730003 - 8100038700037F00007F00008300008600008600018101027902036C05035300 - 00500604390000460B093500004709093F00004B02044800004B000051010258 - 02025F02036202026501016501016100006305094D000057070C3E000046060C - 3200003A000538000142060735000048090B37000047080A3A00004201033F00 - 004704073A00004B090A3A00004A08093B00004202023C000044070537000048 - 0B093700004909083B00004701014800005703055300006F090E6300007B070E - 7200007E00067E00048100038100038300038300038300038400008200008300 - 038001037C02027802017403006F03006E03006804005C00005E00006401006C - 03007203017903027D0101800001840001860001870001870001860001860001 - 8400018200018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180010083010183020082000080 - 01007F00017D01017800037300036C01046A07094E00005405083E0000450608 - 3400003E05063A00004606053C000055090A4A000063080B5A00006600056700 - 056E070A5C0000690B0C4E00005A07064700004900003F00003E000040000143 - 02043F00053A00004903093E00004E040A3F00004503043D00003900003A0100 - 4202004F02006101017100038000058601047F00007F00008500008600008600 - 008200017901026E040358010046000046070333000043080639000048040545 - 00004300004600004A00005000005500005A00005D00005D00005B0003510000 - 5504073E000045050B31000036030A3200063801043500004005093500004505 - 0A3A00004502054200004600024100004905063C00004806073B00004404043F - 00003F02003800004207053500004508063A00004704034600004E0000520000 - 67060A6600007D091077000385020C7D00037800047800037E00038300038A00 - 018E00019400029400029100028900018200017600006802005E030056030054 - 03005200005800006002006804006F04017504027B0101800001840001860001 - 8700018700018600018600018400018200018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 01008301018302008301018001007F00017C00007700036F0103660002570000 - 5603054000004203053000003706083602024000004500005505065100006706 - 0863000073040872000378040970000373080B5F00006408074F000052030047 - 00004804054302044100023D0000400003410004410000470003430000470003 - 4000003E00003900003C01004101004C01005901016802037501067D02067C00 - 007F00008200008500008700008500007C00017202025F000054010048000044 - 04003E00004303024100004301023F01014101014300004700004C0000510000 - 5500015500015100005000024700004300033A00013802073300073503073900 - 033D01023A00014001033E000143000344000045000147000146000243000045 - 01024100004301024000003E00003C00003B02003A00004003013F0000470101 - 49000050000055000061000069000177060A7A020783050B8000058100067C00 - 037C00017F00018600028900028E00039000038E000389000281000176000068 - 01005C01004F01004501004501004A00005100005D00006902007403017C0202 - 8000018300008400018400018400018400018400018400018600018400017F00 - 027B00027D00027D00027F00027F000180000180000182000182000182000180 - 00018000018001008000018001008301018301018001027B01017601026F0101 - 6802036104035200004C00004400004301023900003B02033501013C02034700 - 005400005900006700036B00007702057800047B02067E03077D040877000374 - 03066400005F03025100004B01014000003E0000400001430204410000400000 - 4301023F00004301023F00004101004000004101004000004603024500005000 - 015000005D02056803057801027F00008300008400008500008500008300017C - 00017705056C05035F03025201004900004000003C00003900003B0203390001 - 3F03043C00004601044400004C01034B00014900004600004701023F00003E02 - 0337000038020239000140000142000045000341000047000343000046000245 - 00014600024400004700034100004500054100004400043D00003D0504390302 - 3B00004000004800005200005F01026902057001057401047800047900047B00 - 027B00027B00027F00028600018800008600008500008200018001037A020374 - 03066D04076201035C03064D00004901013F00004002023F01014502014E0100 - 5D00006D00018000028B00038E00028D00008700008200007F01007D02007F00 - 018200018700028400027800047201057401047800047B00047D000280000282 - 00028702048601038501018200007F00007E00007D00007E00008202037F0002 - 7901056A00006202025000004A00003E00003A01003A03003A03003B02003E00 - 003F00004200004800005C04046802037101017901027F00018001027C02027C - 02027D01017E00008300018000047901056A0104540002460000440104420103 - 4000013D00004200004504033B00004707063900004606053C00004101004000 - 004605043E00004C06064200005105064B000060060675030380000182000183 - 00008600008600008500018100017F02047601026901025D0100520100470000 - 3F01003800003900013E050834000043060A3700004704094000004601044200 - 004702053B00004707073700004206063600003D01014200004B02043F00004C - 06073E00004B05063F00004400024200004702053D00004A040A3C0000480208 - 3E00004100013C03023D01014100004900005400006000016C01047702057B00 - 047D00027F00027F00027D01017B01017901017F00018700008C000088000184 - 02027C02027402026901026101015B02055808094600004B0708370000420607 - 3700003D03043E02034901015B00016D00018400049100039300028F00008700 - 008001007902007803007D010180000187000286000478000572010574000578 - 00057B00047F00048200028400028500028500028400018200007F01007D0200 - 7D02007B02007700027703086500006507084C00004C07043800003503003405 - 013404003601003A00004200004A00005200025A00026503036F01017A000082 - 00018600008301017E03017C03017D02008100008800018700028000066E0004 - 5600034600003C00003D00003F00004302044302013B00004A09083900004A0A - 093700004407053C00004202013C00004D0A093E000051090942000053070859 - 01017103037E02028001028200018600028500018500018300017F0002780102 - 6E02016403005902004E010047000040000042040438000045090A3700004A09 - 0B3900004805084100014300033A0000490909370000480A0A3500004206063A - 00004202023B00004A08093A00004A0A0A3900004605073E00004401043C0000 - 4A070A3A00004C070A3C00004902054100004600014A00004F00005800026300 - 046C01047701067E03078000048200028200028200018000017F00017B02007D - 02008200008400008202037D03037702036D0100620000590000570305490000 - 51080A3C000049080A35000043060A3A00013C02034201005500016800017F00 - 048B00038E00028B00008400007D02007803007603007B01017F000186000286 - 00027F00047B00047D00047F0004800004820004840002840002830001810000 - 8000018001027C02027A03017903027203016B00035C000065070B4A00005509 - 0A3C00004407053800003C04003C02003F00004700004F000057000060010568 - 03056A02037101017D01018400018600008400007E03017C03017D0200810000 - 8600018600027E00066C01045400034400004502054201034000013D00003F00 - 004707063900004A0D0B370000480B093700004003013B00004808073A000050 - 0D0C3E00005109094500005805046E04037903027C0202800102830003840002 - 8500018300017F00017B00027402026B04026202025902005201004A00004400 - 004906093A00004C0B0D3900004B0A0C3900004203053C000045060835000048 - 0C0C370000480A0A3700004002023C00004507073700004A0C0C350000460A0A - 3500004001033C00004706083A00004F0A0D3E00004E070A4000004B00015300 - 015A00006100046700037001057901057E000584010484000286000286000184 - 00018200017F00017D02007B02007D02007C03017802017403016C0000640000 - 5A00005300004F00005105064000004E0A0B39000048090B3800003E04053802 - 023F02005000016200007800048500028800028600008200007B020078030076 - 03007901017D0101840002860002840002840002840004840004860004860004 - 8600028400027F00017F00027C01037A02027702037203016F01016702005500 - 00570406450000550B0B3E00004B0A093900004303024300004600004E000055 - 00005F00006600016F02047204066F03027402027F0001860001870000840000 - 7D02007B02007D02007F00008600018600027E00066C01045400034400003E00 - 003E00004000014302044202013900004A0A093700004A0D0B3500004308063A - 00003E03013800004C0C0B3A00004F0C0B3E00004D07074F0000670303710101 - 7601027A02037E01038000028400028300018100017F00027A02037303036D03 - 026602005E010057000052020344000052090B3E00004D0B0C37000044080839 - 00003B0302320000440B0A330000480C0C3700004707073E00003E0202350000 - 440B0A330000460D0C3300004108073A00004103033900004D090A3E0000530A - 0C4300005304075100006601036E01037201057702057E000581000386000286 - 00018900028900018700018600018200007F01007D02007902007605036F0401 - 6A00006400005E00005900005200005000004C00014000004E08093C00004B0A - 0C39000047050A3B00003602023B02004A00005D01007100037E020284000183 - 00008001007B02007803007603007901017D01018200028600028B00028B0001 - 8B00028B00028900028700028400028000027F02047902037503037002026B00 - 026601006100005900004A00013900004909093900004C0C0C3A00004C060647 - 00004C00005300005D00006601007002047801027C01037B0002760102780102 - 8200018700018700008600007D02007B02007D02007F00008600018400027C00 - 066A01045300034200004401044201034000013D00003E000046060537000048 - 0B09350000450A083600003E03013900004207053700004B0B0A3A00004B0807 - 3E00005003015D00006700006D01007202027902037E01038000028100018500 - 038100038001037A02037601026F01016B010066020257000058030747000053 - 080A3C00004909093600003D05043500003D0706300000440B0A350000490909 - 3B00004202023C0000400706330000430B0A320000420A093400003E02023C00 - 004705063E000054090B4700005C080C5100006201057401047C010380000581 - 00038500038700028800018A00018900018700018600018200017F01007B0200 - 7902007403006905016203005C00005600005100004E00004C00004B01004400 - 004A04043C00004B090A3A000049080A3B00003E02033802013902004800005B - 01006E01037901018000018100008001007D02007902007902007B01017D0101 - 8200028700028D00019000018F00018D00018900028400028000027B00027904 - 057103036A02036301015D00005800005600004D00003A00003B050533000045 - 09093900004E08094500005401005900006200006D01007503037D0204820203 - 8400017E00007A02037A02038400018900018900008600007C01007801007B02 - 007E00008500018400027C00066A01045300034200003D00003E000040000143 - 02044101003C00004407053700004308063600003E05033900003A0100380000 - 4409073900004707063A00004403024800005200005B00006400006C01037302 - 057A01057F00028200028601048601048301028000017D010179010178020171 - 03036300005600005B02054700004E06063C0000410604370200360301310000 - 3D07063200004506083A00004702054000004100023800004206073300004108 - 073400004004043D00004000004100005105064C000060070A59000067060A6B - 00037D00028600018600028700018900018900018A00028A0002870001840001 - 8000017D01017902007603007403006B04015C01005300005000004D00004800 - 004800004600004502014302013E00004806073B00004906093C00004502053C - 00003901003A01004800005801006C0103790101800001820000820000800100 - 7D02007D02007F00018000018200028700028F00019000008D00008900008600 - 017F00017901027202026E03056503035D00015400004F00004A00004A000043 - 01023900013000003E05063700004A06074400005501035900006600016E0002 - 7801027E02028202038501018600008200007E02027E01038800028B00018B00 - 008500007C01007801007B02007E00008500018200027A00066A010453000342 - 00004603064302044100023D00004000004101003E00004003013A00003E0301 - 3900003A01003800003C03013C01004005033B00004101003F00004500004B00 - 005200005C00006402026D02047502057B000280000287020586010487000283 - 00008100008000018102037C04056900006300005900005600024A0000480202 - 3E01003B04013701003603013500003B03023C00004300034200004300014100 - 014100023E00004001033A00003E02023D00004000004100004A00004F00005D - 02056100026C03066F01077A0207820000870000870000880000890001880002 - 8801038702048000017D01017901017602017003016D05006B04016406014E00 - 0048000048000047000044010042020041010040000041010043030240000045 - 03044000004401044100004000013A01003E01004A00005A00006B0002780201 - 7F00008200008400008400008200008200008200018200018400028600018B00 - 018B00008700008400007D01017802017002026904026205045803014F000047 - 00004200004000004202024004043800003A01043C0000450003480000530001 - 5900006200007403067902037E02028001008300008500008500008400007E02 - 028001038A00028D00018D00008600007E00007801007B02007E000083000182 - 00027A00066A01045300034400003E00003E0000400001430204430201400000 - 4303023C00003F04023B00003D04023B02003A01003900003E03013A00004003 - 013C00004101004300004A00004B00005300005500006501016B00007A050681 - 04068100038500038700028600018600008500008300007F00007B0307700305 - 6700035C00005100004900004100003D00003B04013702003C04033800004102 - 044000004601044600024500014400004500033F00004202023E000042010043 - 00004900004F00005800006300026B00037401047900057F0004870002890001 - 8900018700018500008100007D00007800007C05067303037206056500006403 - 005900005A00004F00004900004000004302013E00004202013C00003D02003C - 01003C00003D00004202023F00004300034100004600024100014002023F0000 - 4C00005500006C01037500008000018300008800018800018800018600008600 - 018300008300018300008500028301018405067A02027606066700005F000053 - 00005200004A00004701013E00004002023900003B02013B00003D0000410000 - 4900015000035A00056302066C03067403077800047B00027F00018001008200 - 008201008201008002007D01018000028900018D00018D00008700007F010079 - 02007C03017F0100830001820002790005690003540003450000440104420103 - 4000013D00004300004605043C00004707063700004207053900003D04023900 - 003E05033600004308063700004407053C00004201004200004B040144000058 - 05045500006D07086D00017D06077E0103830102870002870000870000860000 - 8600008300007D02047601046D00026400005B00005000004800004100003E01 - 004106043500004307073700004704074000004801044800004D01054100004C - 05083C00004705063F00004600004A00005200005D00016701027201047B0004 - 8000048400028700028600008400008200007E00007A00007802017303036D03 - 026E09075D0000630A064F00005805034A00004A000042000042050338000043 - 08063500004207053600003B02003B00004004043A00004707073C0000490407 - 4100004400024100004603024500005E04036100007C08077C00008701018900 - 008B00008800008800008500008300008100017F00017C00007D070670000077 - 0B0A6000006308044F00004D00004500004603003B0000440907340000400706 - 3500004000004900005000005500035D00046600056D02057501067A02067D00 - 027F00027F00018001007F01007F02007D02007D02007D01018000028B00018F - 00018D00008700007F01007902007C03017F01008500018400027B00056B0003 - 5600034700003C00003D00003F00004302044903033F00004C09083A00004A0A - 093700004308063C01003E0301360000450A08350000480B093700004606053E - 00004202013B00004D0707450000600A0A59000071090A7202027A0203800102 - 8200018600008600008601008600008300007F00017901027500016D01006400 - 005B00005000004900004903033D00004909093700004A090B39000048050A43 - 00034C000546000052060A4000004D090A3C0000490605430000490000530000 - 6100026D02047702058001038700038700028600028300017E00007B00007700 - 007402026F05046B07076205045700005E0B09470000560B094000004D060341 - 0000420201380000470909350000460A0A3300004007063800003E0202360000 - 4909093900004D090A3C00004B05064300004501023F0000560607500000700A - 0B6A00008408088300008700008900008A00008800008500008100007E000178 - 00017404046500006F0B09550000630C0A480000500604410000410100370000 - 470A083500004A0D0B3700004505044300005A00026200036600056B00057100 - 067600057A00067E00057F00027F00027F00017F01007D02007B030079030079 - 02007D01018000028B00018F00018D00008600007D02007803007A03017F0100 - 8500018600027F00056F00045B00044A00014702054201034000013D00004600 - 004D07073E00004F0C0B3A00004B0B0A3900004005033A000043080635000048 - 0D0B370000480B093900004003013900004308063A0000540C0C490000650B0B - 5F00007105047601027B01018001008200008401008401008601008401007F00 - 007D01017901027402026D00026400005B00005100004B00004F07073C00004D - 0B0C3900004B0A0C39000045020747000153030A420000510A0D3C00004B090A - 3A00004502014800005201005F02016D03027803048102038700028700018200 - 027F00027D00027801027202026D020465030360030453000057070643000055 - 0D0D3C00004C0B0A3A00004303033E0000450707370000480C0C350000440B0A - 3300003C03023A00004307073700004C0C0C3A00004D090A3E00004501024000 - 004B0505450000610C0A570000790E0B74000085060585000088000088000085 - 00008000017D01017801027002026400006508094E00005E0D0A430000520B08 - 3B00004405013B00004407033900004D0C0B3C0000520B084400005502016801 - 047100047300047600057900057D00048000058000058000028000027F00017F - 00017D01017B02007902007902007B01018000028900018D00018B0000860000 - 7B02007803007A03017F01008600018700028100067100045D00044E00024000 - 003E00004000014302044D0303440000520A0A3E00004F0C0B3A00004808073D - 0000400301370000480B093700004C0C0B3900004807063C00003B0302320000 - 460B093A0000580D0B4A00006508076300007002027602017B02007F01008002 - 008201008402008201008100008001007E02027A02027402026D01006400005C - 000057000349000054090B3E00004C0B0D37000044070B3D0002490005430000 - 51070B3C00004A0C0C3500004308063C00004300004B01005902006703017503 - 037E02028500028600018000027C01057A02067704076E03056601035B000051 - 00004F0102430000500A0B3A00004C0C0C3700004506083C00004300033A0000 - 4B080B3900004A0B0D3500004307083A00003E0203350000480A0A3900004D0B - 0C3A00004A06074100004200013C0000540A0A490000670D0C5C00007A0B097B - 02008001008400008400008102017C02027504027004036905055E04044D0000 - 57090A4000004E0B0A3900004609073B00004205013B00004E09064200005909 - 084C00006309096501017502057C01057C01057E000580000580010380000280 - 00028000028000028000027F00027F00027D01017D01017D01017B0002800002 - 8700018B00018900008400007B02007803007A03017F01008700028900028300 - 067600056100055100034801044201034000013D00004A000051050642000051 - 09093E00004C09083D00004404033E0000440705370000480B09390000490908 - 3B00004003013400003A07053300004B0B0A4000005808075300006201006C02 - 017102007803007B02007D02007F02008103008103008301018301018001027E - 02027901027500016D00026701025A00005C030647000051080A3A000045090A - 3500004003074300014D03093C00004A090B330000400A093100003B04003E01 - 004801005402006103006E01007800008200008200017D000279010578030672 - 04066801045D00005200004A00004700004B05063A000048090B35000045080C - 3700004101064100014904073C00004B080B39000047080A3800003E02033A00 - 004206073700004A0A0A3A00004A08093D00004301023D00004606053E000056 - 0C084A0000660A056600007706037E03018002018002017B02007403016C0300 - 6703015E04034F00005106083E00004A09083700004409073700004005034102 - 004C07044300005B08065200006B09096500007606067C010381010281000381 - 0003810003810003800002800002800002800002800002800002800002800002 - 8000028000027D00027F00028700018900018700008200007902007803007902 - 008001008900028A00038400077901066400065400044100003E000040000143 - 02044F01024700005004054200004C06063E00004605044000004101003C0000 - 4606053900004807063B00004704033D00003701002F00003F07063800004D08 - 054700005902005B00006803016E03007302007803007903007C04007E040080 - 04008402028402028301018001007D0101790102760104700305630002560000 - 5702064200004805083700003E05083A00034200044100004605073500003E08 - 072D00003707033402003B03004202004D01005901006600007401007F010081 - 01027C01057600057200036C00026300025A00005100004B0000490003400000 - 47050A38000043060A3700004002083F00024600044300004B03093C00004805 - 0A3A00004403053D00003F00023A00004606063900004806073B000047030440 - 00003E00003B00004808074000005306035000006704006C0100790401790200 - 7902007401006C01006401005C01005401004B00024000004704073700004307 - 073700004106043E01004502004600005906045700007008096C00007D06077D - 0002820001840000840001820001800001800001810102810102800002800002 - 8200028400028400048600048600048400027D00027D00028600018900018700 - 008200007902007603007902008001008900028C00038600077A000667000755 - 00044A03064302044100023D00005600005600005000005101004800004A0300 - 4300004202013E01003F02003C00004202023F00004301024200004000003700 - 003603013500003D04033E00004702004A00005100006005016504016A030070 - 03017603007A04007C0400800300830403840202830101810000810000800001 - 7F02047B03076B00006600005900005400024800004602033E00014001034300 - 014400023E00003E02033500003704023202003502003A030040020048000050 - 00005B00006501007101017303037103076A01046300005C00005300004F0000 - 4C00024A01034200024302043D00024003073D00024101073D00034200044900 - 014D00024A00004E00034A00005000024D00005000005000005100004C00004E - 00014800004901014400004100003E0000400301410000490401460000520000 - 5700006103006904026804006702006302005D00005800005100004A00004100 - 004001033D00004103033D00004404034300004901014900005500005D00006E - 06077302057D06077D0004800002830000830000830000820000800001800001 - 8101028101028000028000028200028400028600028600028700048400027F00 - 027F00028400018600018400008001007902007902007D02008200018900018A - 00038400067A02076801045801044400003E00004000014302047207046E0502 - 6602005B00005100004900004100003D00003E03013A01003F03033C00004302 - 044200004800064400043C00033800003902053700003B02033800003F010141 - 00004B01005000005E02016200007002027600007F02048001028001007F0000 - 8100008200008500008500008500008300017F00027900047302056903045F03 - 025401004B00004600004A01034400014703043F00004103033A00003B020139 - 00003E03014000004603024700004F01024F00005800025400005000004B0000 - 4C00014700004701013F00003F01013C00003C02033A00013D03043B00004102 - 043F00024200054500014D00005600005C02026103046905056E040374020277 - 00017B03047901027301016B00025F02015300004700003E0000430000440000 - 4901014700004E01004A00004D00004C00004A00004700004C02024600004D03 - 034A00004F00034800013D04023904013B02003E01004400004800004E000054 - 00006603056B02057001057400057800057900047B00057D0004800001820001 - 8200018000018000018000018000018000018000018000018000018200018200 - 018200018200028200018000018000018000017F00017F00017D01017D01017F - 00018100008700028700028300007D00027503036902005800004A0103420103 - 4000013D00007B04027603006E01006501005B00005000004600003E00003C01 - 003F06053500004307083900004903094200014800073F000240030734000040 - 070A3000003D07073500003B02014100004D05054D00006306075F0000740608 - 7300007A02037C02027D02008000018300008600008800008800008800008600 - 028000027C01037303036A03016001005800005000004900004B02044000004A - 06073B00004707073B00004103033E00004305053B00004806073E00004B0506 - 4400004A01034200004404033A00004508063500004007053500003A02013900 - 014006073800004607093B00004904074100004B00015700015F00006602026B - 04027503037C02028200008600008C00018900008100007800006A02035C0201 - 4C01004400004400004903034100005006064300004F05054100004200013C00 - 003E05043500004408083A00004A05084400004701023C01003902003E010044 - 01004D00005700005E00006500007201057600057900057B00057D00057D0005 - 7D00057D00047F00028000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018000018200018000017F00017D - 01017B01017D01017F00018200018500008700028700027F0000790101730402 - 6B02005A00004400003D00003F00004302047F00017B01017501006B02006001 - 005501004A000042000044040338000045090A3500004A080D3A00004A040A43 - 00034300053A000047080A350000440A0B3300004206063C0000450403430000 - 570A084A0000660A095900006B05066900007504027A02027E02027F00018400 - 018500008600018600018500018200027E01037702036F03026702006200005A - 00005100004300005106084000004E0A0B3A00004808083F0101400404380000 - 4709093700004B090A3A00004A06074300004301023A0000490909370000460A - 0A3500004206063A00004103033B00004D090A3E000054090B43000053040751 - 00006300026900036D02047103037803047C0202820000850000890000860000 - 8100007901016E03056105045303024902004502013B00004C09083C00004F09 - 093C00004706053C00003C0302340000420A09330000480A0A3A00004A040544 - 00004100004100004900005001005902006202026B03047302057800047B0004 - 7D00047F00048000048000047F00047F00048000028000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018200018000017F00017D01017B01017D01017F0001820001850000870002 - 8700027F00007901017304026B02005A00004D02044201034000013D00008300 - 008000017B01017203016902005D02005300004900004200004808073700004A - 0B0D3900004B090E3C00004701074100014A040A3A00004C0B0D39000048090B - 3900004202024000004D0707400000570C0A4700005C09074D00005D00006E04 - 037504027703027C02028001028200018500018500018500018400027F00027C - 01037702037002026E0103670303530000580408470000570A0D420000510B0C - 3C00004404043D0000460808350000480C0C370000490B0B3B00004404043E00 - 004707073700004A0C0C370000480A0A3900004301023F00004D050543000059 - 0B0C490000610B0B5300006204056F01057501067603067803047B03047E0202 - 8001008400008700008500007F00007901016F02046303035701014B00003F00 - 004508063900004C0C0B3A00004A0A093700003E030139000041080733000047 - 0B0B3900004C08093E00004B01014B00005000005700005E0100670303700305 - 7704077D04087D00048000048200048200048200048200048200048000028000 - 0280000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000018200018000017F00017D01017B01017D0101 - 7F00018200018500008700028700027F00007901017304026B02005A00004600 - 003E00004000014302048800008600018101027A02027202026602005D010052 - 00004E02034000004E0A0B3A00004C0B0D3900004807094000004500033E0000 - 4D080B3C00004F0B0C3C00004806073F00004504033B00004E0B0A3C00004F0C - 093E00004C07044900006304016C02017002027503037A02037F000282000283 - 00018500018300018200028100037E01037A0203790203710305650106550000 - 630A0D4A00005C0C0D4300004E06064300004504033B0000490C0A350000480D - 0B3500004209073B00004001033700004A090B3900004C0C0C3A00004C060645 - 00004900004700005B08075000006B0D0E5B0000700C0C6F02047B01077F0107 - 7F01067D02047D02047E02028001008200008501018400007E00007800006F01 - 036501015B00004D0000430201350000460B09350000480D0B35000043080638 - 0000400503360000480B093900004C0B0A3E00004E06064D00005C0000640000 - 6600016D00027401047901057F01068302078400048600048600048600048600 - 0484000484000482000280000280000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001820001800001 - 7F00017D01017B01017D01017F00018200018500008700028700027F00007901 - 017304026B02005A00004C01034201034000013D00008E00028C000287000281 - 01027801026E02016602025D03025100005305064000004F090A3A00004A070A - 3C00004502053F00004904073C00004D080B3E00004E08093D00004501024200 - 00470605390000490C0A350000450B063600004502005601006201006701026D - 03027303037902037D00027F0001830001830001830001840002820002810003 - 8001037A01056D00036D070C5C0000690A0E5000005E070A4B00004E00014700 - 004A07063A0000480B09370000450A083600004004043C00004604093900004B - 080B3C00005007094400005000014E00005D03025400006F0B09600000790D0C - 7000007E07088400068700068300058100038001038001028002018102018301 - 018200007E00007800007100036800015D00004F000041000042070533000044 - 0B09330000430A083400003E03013E01004707063C00004E0808420000540809 - 4700005903036802037100037300037800047B00048000058300058500058600 - 0487000487000486000486000484000484000482000280000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018200018000017F00017D01017B01017D01017F00018200018500 - 008700028700027F00007901017304026B02005A00004500003E000040000143 - 02049200039100038A00038400027D00027601026F02046905055C00004E0000 - 5204054200004C06063E00004604054000003F01013A00004606063A00004A06 - 073D00004903034200004502013D00004606053600004209073400003C07043E - 01004D00005800005D00016503036C04057302057800047D00047F0003810003 - 8300018500018500018600028400028100057A02076F000275060A6700006D06 - 095D00006104055700005301004900004D06033E00004808043B00004306023E - 01004100023D00004903093E0000500507460000540103540000610304620000 - 7107066900007B0A087400008108068101028900048B00058700048400028000 - 027F00018002018002018102018001007E00007B01017702056E010365000159 - 00004800003A00004207053300004108063400004005033F0000460300440000 - 5205034900005906054E00005B08076002037201047B00027D00027F00028200 - 0284000286000286000287000287000286000286000284000282000282000280 - 0002800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018200018000017F00017D01017B01 - 017D01017F00018200018500008700028700027F00007901017304026B02005A - 00004E03054302044100023D00009300049100038C00038500018100017B0002 - 7803067205076100005C00005200005101024800004A02024500004301023C00 - 003A02013A00004002023E00004501024200004500004200004401003E000041 - 04023900003B06033803003F04024600004F00005600005D03036403056C0405 - 7002047601047A00037E00038000008200008400008600018600018600027F00 - 037E00067900037A02077100027102066800026702045B00005800005000004F - 02004800004A03004700004701014500014600044500014C00034C0000530001 - 5600005C00006B05067307067403017C07047C01008104008100008600008D00 - 048C00048800038300017F00017D01017E03017F04027E00007F00007E00007E - 02027B03077403066D02055F01024A00004200013C00003E03013800003E0301 - 3F00004300004B00005300005500005C00005B00006303036002036B05067700 - 017F000180000282000284000286000287000387000386000286000284000282 - 00028200028000027F00027F0002800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018200 - 018000017F00017D01017B01017D01017F00018200018500008700028700027F - 00007901017304026B02005A00004600003E00004000014302048D00028A0001 - 8A00018500008200007E00007A00037300037003056804046104035A02025301 - 004D00004900004100003D04023603003D06033900004104023E000044010042 - 00004500004200004501023E00004002023800003B02013C0000460001490000 - 5202035200005E03066100026A03066F01057502057B02068102048401048601 - 048800038700018600018800058700058500058200047F00047A000375000371 - 00036C01036602026101015D01005700005100005000004D00004D00014E0003 - 5000035300035900045E00046401036901026F01037500017800007D02008200 - 008502008702008A00018F00068C00068600038000007B00007A00007C03017D - 04027F01007F01008000018001027B02067601046C0001610000500000440000 - 4301023E00004003013E00004401004A00005200005D00006800016E01037003 - 057004036D02046F01017B000282000282000282000284000284000284000284 - 00028200028200028000027F00027F00027D00027B00027B00027F0001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018200018000017F00017D01017B01017D01017F000182 - 00018500008700028700027F00007901017304026B02005A00004C0103420103 - 4000013D00008800038700028700028500018300018100017E00037800037702 - 056F02046802036202025D01005500005100004A00003C02003C070434000042 - 09073600004606053D00004502014400004903033D00004A06073A0000460606 - 3A00004101014100004B02044400005406074C00005F06095B00006601036D02 - 047201047902037E01038100038500038600018700018A00038A00038A000587 - 00028600048100017E00037A00017601047101016E01036902006400005F0000 - 5F00005B00005700015600035800035D00036100046700036C01037101017500 - 017800007C010080010084010087020088020088000188000587000683000580 - 01037901027802017801007A01007F01008001008000018001027F0106780004 - 7100026300005200004D02043D00004707073700004606054300005100005E00 - 006800007400027901027A02037A02037601027700017F000282000282000282 - 00028200028200028200028200028000027F00027F00027D00027B0002790102 - 7801027901027F00018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018000018200018000017F00017D - 01017B01017D01017F00018200018500008700028700027F0000790101730402 - 6B02005A00004400003D00003F00004302048001038100038100038200028200 - 028100017F00017E00017B00027801027101016C02016602006102005E020154 - 0300430300360000450B06350000490C0A3900004706054000004501023D0000 - 4E08093E00004D080B3C00004904074100004400023C00004D06094200005607 - 0A4900005A03065800006301016901026E00007301017901017D010180010283 - 01028800028A00028900028900018700028600018300017F00008001037C0202 - 7801027403017101016E03006D01006902006200016100046300046700036C01 - 046F01037401047801027A00017C000080010082000084010086010087020085 - 01018000047E00067B02067A0304780304760201760100780000800201820000 - 8200018101028101067900047300026600005700024400004E0809390000480B - 093900004D06035100006600017400027F00048300038401048101027D01017C - 00007F00018000018000018000018000018000017F00017F00017F00017D0101 - 7D01017B01017B01017901017802017901017F00018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018200018000017F00017D01017B01017D01017F0001820001850000870002 - 8700027F00007901017304026B02005A00004D02044201034000013D00007702 - 037902037A02037E01038001038000028100018100018000027D000279010276 - 01027002026B04026804026106024900004C07043E00004F0C093C00004E0B0A - 3B00004504033F00004806073C00004F0B0C3C00004D080B3E00004500033E00 - 004704073C000050090C4000005306094500005300015800005D00006400006A - 00006E01007403017903027D0303820001860001860001860001870001860001 - 8600018400018200018000017F00017D01017901017903027703027304026D00 - 026C01036E01036F01037401047801027C01037E02027F000180000182000082 - 00008201008201008201007F01007901057302067002046F03026F0302710200 - 7502007A01008102018400008400018400018000057C01057400036900035300 - 005104073C00004A0C0C350000480B094000005500006D02047A02038601048B - 00038B00038701018200007F01008000018000018000018000017F00017F0001 - 7D01017D01017D01017D01017D01017D01017B01017B01017B01017B01017F00 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000018200018000017F00017D01017B01017D0101 - 7F00018200018500008700028700027F00007901017304026B02005A00004600 - 003E00004000014302046A02036C01037002027702037C01037F000282000283 - 00018500018400028000017D01017903027504027205036B06045C00004D0000 - 5C0907470000570C0A4000004D070740000042020239000048090B3900004C0B - 0D3A00004A040A4100014502073B00004C090E3C00004F0A0D3E00004D050547 - 00004F00005200005800005E00006401006902006F04017304027902007F0100 - 7F01008001008200008200008400008400008300008300008100008001007F01 - 007D02007E03017A02027602017601027801027901027C010380010281010283 - 01028200018200008200008001008001007F01007F01007802016D0506660305 - 6301016100006400006A01007403007D04028402028600008600008600018100 - 057C01057600056900055500024200004A0A0A330000430E0B3300004C070451 - 00006F04067D02048900048F00038D00038A0001820000800100800001800001 - 7F00017F00017F00017F00017F00017F00017F00017F00017F00017F00017F00 - 017F00017F000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001820001800001 - 7F00017D01017B01017D01017F00018200018500008700028700027F00007901 - 017304026B02005A00004C01034201034000013D00005D000062000067020070 - 02027902037E01038400028600018800018700028600018200018001027A0202 - 7A04037405036700006B0506590000660A094A0000570A084300004504033C00 - 00420606330000440A0B35000047080A3A000043000541000348050A3A00004C - 090E3A00004B080B3C00004603024801004A00005000005300005B0000600200 - 6403006B04017103007502007803007B02007D02007F01008301018501018300 - 008300008300008300008200008001008001007F01007D02007D020080010281 - 02018301028500028500028700028501018501018001007F01007D02007B0200 - 7A01007102006205045802025600005600005C00006501007305017F06048402 - 028800018800008700018300057D02067701066A00064F00004B040735000041 - 0B0A2C0000400B083B00005201006D05067C01038800028E00018E00018A0100 - 8302008103008001008000018000017F00018000017F00018000018000018000 - 0180000182000182000182000182000184000184000182000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018200018000017F00017D01017B01017D01017F00018200018500 - 008700028700027F00007901017304026B02005A00004500003E000040000143 - 02045400005800006201006C02017503037E01038400028900028B00018B0001 - 8900018700018400018001027E03017A02027A02037100007605085F00006306 - 074D00004D05054000003D01013500003D070730000040070A3400004003073D - 00024300063E00014704093A0000480709390000430505400000420200450100 - 4800004D00005100005701005E04006204006A04006E03006F03007403007803 - 007C030180020181020183010184000084000084000084000082000082000082 - 0000820000840100840000860100860000870000870000870000870101850101 - 8101027D01017B01017701007701006C02015500004B00004B00005000005700 - 006401007004007E05038602028A00018800008700018300057D020678020769 - 02074F00013D00003F07062B0000350B062C00004205014D0000690304790102 - 8700018D00008D00008700008103008003008001008200008200008001008200 - 0080010082000082000082000084000086000086000087000087000089000087 - 0000820001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018200018000017F00017D01017B01 - 017D01017F00018200018500008700028700027F00007901017304026B02005A - 00004E03054302044100023D00004700004D00005600006003026D0204750205 - 7D00048400028900028B00018B00018900018600018400018001008000018100 - 038102047700027401046500006100025300004E00014700004200013E000040 - 01033A00003E02033B00023C00033C00013E00033B00003E02033A00003F0304 - 3C00003E02023F02004001004200004500004900004F01005302005804005E05 - 016105006504016B04017003017703027A02027C02027F030381020382020383 - 0101850101840000840000860000870000870000870000890000890000870000 - 8700008600018301028001027C01037601027202026E01036C01036104034700 - 004100004500004C00005501006001006E03007901018503048800028A000086 - 00008300037F02047A02066C03065000004200013700003505012E0100350501 - 3D00004E00006903047800018500008A00008A00008700008103008104008001 - 0082000082000082000082000082000082000082000082000084000086000086 - 0000870000870000870000860000820001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018200 - 018000017F00017D01017B01017D01017F00018200018500008700028700027F - 00007901017304026B02005A00004600003E00004000014302043E02033F0000 - 4701024A00005B00036200017102067A00067D00018200008600008600008700 - 008800018802028602028200018000017F00027D00027B00027800047201046D - 02056200005B00015500015000024B00024400014200023F00023B0203370101 - 3A04043500003B03023600003901003800003B02013B00004202013E00004401 - 004100004600004400004A00004A000055010357000067020469000171030575 - 02057400007600007B00027B00008402038400008B00038B00008A00008A0000 - 8A00008900008900008700028300038101067D02067600057002086400026001 - 055600005400014A00004400013F000046030244000050000056000068020374 - 01047F00028600028900018900018400018000017B01016F0302530000450000 - 4102003700003D06033A01004701014F00006A03067A02078600068A00038800 - 0085000083010183040380010080000180000180000180000180000180000180 - 0001800001820001820001820001820001820001820001820001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018200018000017F00017D01017B01017D01017F000182 - 00018500008700028700027F00007901017304026B02005A00004C0103420103 - 4000013D00003700033E05083800004B04074800006004096300017102067800 - 057D000482000284000186000186000087010187010182000182000182000182 - 00018200028200027F00047B00047400036C00026500035D00025300024D0001 - 4A00014300003B00003E05043400004108073500004206063800003D01013B00 - 004004043800004507073700004505053C00004101013D000045030443000058 - 04085200006504086200006A01046F01057507096F00007F0809760000850506 - 8100008700018600008600008500008500008300008000027D00047800047000 - 0570040A5E000062060B4C00005104084500004300013D00004204043B00004C - 06074300005A03066200007403077D0004840002890002890001860000820000 - 7D02007203015600004D03003C00004508043700004808074300005300006B01 - 077A020784000788000387000285000083010182030280000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018000018200018000017F00017D - 01017B01017D01017F00018200018500008700028700027F0000790101730402 - 6B02005A00004400003D00003F00004302043D04073500004807093E00005607 - 0A4C00006504086500007102067702057C01037F000180000182000181000081 - 00008200008001008200018200018400018200018000027D00027A0105740104 - 6E00046601035E00035700015200004D00004B00024100005007094000005108 - 0A3E00004905064200004301023A0000490909370000490B0B3500004307073B - 00003E02033700004B07084200005A060A4E00006002065C0000680507620000 - 730B0C6400007C0B0E6F00007E06077800007E03017D02007D01017B01017901 - 027801027300036E01036700055A000063070C49000055080C3E00004903093E - 00004001033900004909093E00005408094C00006906086F00047B0004820002 - 8700028700018600008200007D02007203015D02004700004D0805390000490C - 0A3900004D05054E000068010677010682000787000387000285000083010182 - 0302800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018200018000017F00017D01017B01017D01017F0001820001850000870002 - 8700027F00007901017304026B02005A00004D02044201034000013D00003B00 - 0246060B3900004E090C42000058070A4F00005D00026702046C010371000376 - 01027901027D01017F00017F01007F0100800100800001820001840001840001 - 8200028000028000057A01057601046F00046900036300026000035D00035700 - 005E04094E000060090D4A00005A060A4500004C00024600004B05063C00004D - 0B0C370000470B0B3600003D04033800004307083900004E0A0B420000570609 - 4900005500015400005F05055200006D0D0D5A0000750D0E6A00007406067205 - 037206027205037104026F03026D03026802036502045700005A030647000055 - 0A0C3E00004A090B3700003F03043A00004507073900004F0B0C4300005F080B - 5D00007304087B00048200028700028700018600008200007D02007203015B00 - 005607044000004D0D093700004C0C0B41000053000166000576000581000687 - 0003870002850000820000820302800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000018200018000017F00017D01017B01017D0101 - 7F00018200018500008700028700027F00007901017304026B02005A00004600 - 003E00004000014302044301063A00004B080B3C0000500A0B4200005204054E - 00005A00005D00006400006B01007101017703027A04037B03037D02007F0100 - 8001008200008400018400018400018400018300017F00017C00017900047601 - 047201047001056F010570020864000072080E5A00006C080D5300005D02054F - 00005200014500005309093E00004D0C0B3900004508063900003E0405350000 - 490A0C3900004C090C3E00004E05074700004A00004500005808094A0000640B - 0E52000066090A5F02016304016305006304016003005F02015E02015B010157 - 01015100004300005007093A00004A0B0D33000040070A3700003F0304380000 - 4B0B0B3C000055090A4A00006807096D00037900048200028700028700018600 - 008200007D02007403016304014C00005309073A00004B0E0C3900004D07074D - 0000620003720003800006850003860002840001820000810201800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001820001800001 - 7F00017D01017B01017D01017F00018200018500008700028700027F00007901 - 017304026B02005A00004C01034201034000013D00004100014704093A00004B - 080B3C00004B07083F00004A00004C00005100005900006000006701026D0302 - 7103037605037902007B02007D02007F01008200018400018600018600018400 - 008500018300018200028001037E01037D02067B02067800047E050D6C00007C - 080F62000070040A5D00005F00025900005A030649000057090A4200004D0707 - 3F000042000140000146060B370000490A0C37000049080A3B00004503044200 - 004B0506400000540A0A43000055070848000052000052000054000052000052 - 00005100004E00004E00004A0000430000470403390000450909330000400A0A - 3200003A04043A00004406063900004D090A4200005B07095C00007204087900 - 048000028600028700018600008200007D02007403016201005C07054300004D - 0A073700004A0A094000005000016100026F00027D0005860104870003840001 - 8200008102018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018200018000017F00017D01017B01017D01017F00018200018500 - 008700028700027F00007901017304026B02005A00004500003E000040000143 - 02044600023F00004704073B00004808083900004306043F0000420000470000 - 4D00005300005D01006101016602026C02017403017803007902007B02007F00 - 0182000184000186000187000187000189000187000187000187000287000383 - 00038100067B000182040A7300007F050B6D00007203076A00026801045E0000 - 6306075200005C06064C00005402014B00004A00044000004704093900004306 - 0A3700004105063D01024302043F00004A05083D00004C05083F000048010444 - 00004800004900004900004900004900004700004700004300004100003B0000 - 4105053300004007083100003B05053600003E02023B00004606063C00004F05 - 054C00006305066C01047800048000028600028700018600008200007F010076 - 02016A05035800005505043E00004707063900004805044B00005E00016D0002 - 7B00058401048500038400018200008001008000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018200018000017F00017D01017B01 - 017D01017F00018200018500008700028700027F00007901017304026B02005A - 00004E03054302044100023D00004400004400024000004403053C00003E0504 - 3A01003C03013C01004000004601004B00005200005801005C00006100006D04 - 017004007403017602017901017D01018000018400018800028A00028A00028B - 00018B00018A00008A00008600018100018000057D00028100077B00037D0309 - 7701067504087102066F04076900036803056000006100025C00005900015000 - 004D00044400004400043B00003C01053900013D03043B00004100023F000044 - 0104400000450205410002440203450000470000480100470200470200460300 - 4403024403023F00003F02003A00003E02023800003C02033800003A01023C00 - 004002023F00004301024400005101025D00016C03067601047F000284000286 - 00018400008200007F01007802016B04026003024F00004B01003E0000410402 - 4100004B00005A00006900017900058201048500038400018200008001008000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018200 - 018000017F00017D01017B01017D01017F00018200018500008700028700027F - 00007901017304026B02005A00004600003E0000400001430204450001420000 - 4300033C00003C03023700003802013701003902003900004202014100004B01 - 014C00005200005700006605026703006E04036B00007402027400007A00017D - 00008300008500008800008A00008A00008C00008C00008700008200047F0004 - 7F00047D00047D00047B00047900047800047800047601047401047401047201 - 047201047201046D02056400065800025000014500004302043A00013B020339 - 00003E00013F00004500054100014300053E00013F0004400001430000440000 - 4701014300004701014100004201004100004000003F00004002023C00004001 - 033C00003F00023E00013F01014000004303033F00004901014D00005F020369 - 02057401047D00028200028400018400008200007F01007802016C00005E0000 - 5400004500004201003C00004201004700005C01046A01047A02078102048300 - 0384000182000080010080000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018200018000017F00017D01017B01017D01017F000182 - 00018500008700028700027F00007901017304026B02005A00004C0103420103 - 4000013D00004200004702053A00004506083300003F07063300003802013601 - 003D06033600004707063E00004F05054600005100005600005F02015900006B - 07056200007408077100007C04057D00028000018400018600018900018B0001 - 8B00018700028000027B00027B00047D00027D00047D00027D00047D00027D00 - 047D00027D00047D00027D00047D00027D00047900046E000668010851000052 - 03063D00004307083700003B01023D00004502053F00004C040A3C0000470409 - 3A00003F00024200004903033F00004C06063C00004906053D00004201003F00 - 004404043A00004806073A00004704073D00004200023F00004505053B000048 - 06074000005305065800006904067401047B0002800002840001840000820000 - 7F01007901016F00006802035200005205033A00004508063D00004800005900 - 036801047501067F020481000382000182000080010080000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018000018200018000017F00017D - 01017B01017D01017F00018200018500008700028700027F0000790101730402 - 6B02005A00004400003D00003F00004302044301023A0000490909370000440B - 0A3200003F07063700003B03023300004509093700004B090A3C00004B050647 - 00004D00004A00005E0606500000690B0C5C000071090A6E0103750205790203 - 7C01038001038300038500038700038500037D00027901017901027B01017B00 - 027D01017D00027F000180000280000182000282000184000284000186000282 - 00027F020B6B00006A060C4A0000500A0B3700004007063700004202023F0000 - 52060A42000051070B3C00004404093E00004701024100005007093E00004D09 - 0A3C00004705063F00004301023B00004A08093C00004D090A3C00004B050641 - 00004301023B00004A0A0A3A00004F09094500005E0606620001720104790102 - 8000028200018400008200008001007B01017803046400006306074500004D0C - 0B3500004508064400005501036401037302067D020481000382000182000082 - 0000800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018200018000017F00017D01017B01017D01017F0001820001850000870002 - 8700027F00007901017304026B02005A00004D02044201034000013D00003C00 - 00450707370000480C0C350000460A0A3300003C03023800004307073500004A - 0C0C3700004A0A0A3900004501024500005206074500005B0B0C4A0000610909 - 5400006300026B02056F02047201047702037A02037C01038102047F02047B01 - 017901017901017B01017B01017D01017F00017F000180000182000184000186 - 000186000186000187000186000283000580080D5D0000620C0C400000470C0A - 3300003C03023E00004C060743000056090D4200004D080B3700004001034300 - 00500507400000510B0C3C00004B090A3A00004202023F00004806073A00004F - 0B0C3C00004F090A4000004701023E00004808083900004E0C0D3E0000540809 - 4F00006502047002047901027F00028200018400008200008001007D01017600 - 007306085300005B0B0A3A0000480D0B3800004502015300026100027001057A - 02037F0002820001820000830101800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000018200018000017F00017D01017B01017D0101 - 7F00018200018500008700028700027F00007901017304026B02005A00004600 - 003E00004000014302043C0302330000460A0A3500004A0C0C3700004706083E - 00004201033900004A090B3700004A0B0D3500004307083A00004504063C0000 - 4F0A0D3E0000550A0C4500005501054E00005F01056302046801046C01036F02 - 047002047502057702037901017B02007B02007D02007D02007F01007F01007F - 01008001008200008200008400008400008400008600008400018A0508760000 - 770C0E4E0000520D0A3300004009043700004202013E000054070A450000550A - 0C3C00004307083C000047000342000051070B3E00004F0A0D3A00004706083C - 00004201033900004A0A0A3A00004F0B0C3C00004C06074300004301023B0000 - 4C0C0C3A00004F0C0B4300005B05055D00006F02047801027F00028200018200 - 008200008001007D01017B03046800006807094900004F0C0B3500004207053F - 00005000015E00016F00047A02037F0002810000820000830101800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001820001800001 - 7F00017D01017B01017D01017F00018200018500008700028700027F00007901 - 017304026B02005A00004C01034201034000013D00003500003F070633000046 - 0A0A3900004A08093D00004500034100004904073A00004A090B35000043090A - 3300003B020338000142050935000048090B3A00004B06094100004C00025300 - 035700035D00036100026401036602026A02036F01017901017F01007F01007F - 01007F01007F01007F01007F01007F0100800100800100800100800100800100 - 80010082000084000185080A640000630C0A3C0000400A032F00003A06003C00 - 004B050543000056070A4200004C08093600003E02034100004D03073E00004D - 080B3A000049080A3800003E02033A00004206073700004A0A0A3A00004C0809 - 3D00004501023E00004705063900004C0A0B3C00005107074C00006000016F02 - 047801027F00028200018200008001008001007D01017900007704075700005A - 08073C00004409073500004100004F00005D00016E00047801027F0002810000 - 8200008301018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018200018000017F00017D01017B01017D01017F00018200018500 - 008700028700027F00007901017304026B02005A00004500003E000040000143 - 02043603013300003F07063500004707073D0000490205460000480002410000 - 49030939000043060A3300003B04073400023500043200003C04093200004306 - 0A3900004603064500004900004C00005100005500005A00005D000160000168 - 00017B01018400008400008200008200008001008001007F01007F01007D0200 - 7D02007D02007B02007B02007B02007D02008301027A00007009065000004708 - 003000003608003405003D03003F00005004054300004E05073B00003E050439 - 00004200024100004B03093C000047050A3800004004053900003B0102360000 - 4206063500004507073A00004503044000004100003D00004808083C00004A07 - 064200005401005900006D02047601027D00028000018200008001008001007F - 00018003057100006904064B00004D07073700004005033D00004C00005C0000 - 6D00037801027F00027F00008200008301018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018200018000017F00017D01017B01 - 017D01017F00018200018500008700028700027F00007901017304026B02005A - 00004E03054302044100023D00003701003802013800004002023F0000450102 - 4400004700014700014600024100014300053C00013C01053800023700033900 - 043B01063700023D02063800013E01053C00004100014300004700004B000051 - 00005600005B00005F00006800007D0101860000860001840000820001820000 - 8000018001007F00017D02007D01017B02007901017803007901017802017600 - 007103035F02005206003D00003703003102003606003A020041020041000047 - 01013F00003E02023600003901004000014600044100014300053F0001420005 - 3D00003C00013C00013D01023A00004002023E00004202024000004100003F00 - 004202023E00004205033D00004600004C00005700006903047201047B00027F - 00018200018200008000017F0001800305780306630000560302450000420503 - 3A01003E01004A00005800026900037601047D00028100008400018501018200 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018200 - 018000017F00017D01017B01017D01017F00018200018500008700028700027F - 00007901017304026B02005A00004600003E00004000014302043C00013B0000 - 4001033E00004201033F00004200024100014100014000004300033E00004201 - 033C00003F00023E00014100034200024300053E00014000053C00003F000240 - 00014501024900025000015400005A00006200016800047302067F0002840001 - 8400028400018200028200018000028000017F00027D01017D00027B01017B00 - 027901017B00027202025D01005202014C02004502003F02003A020039020036 - 01003B04013B04013A03003A03003803003303003203003502003F0000420000 - 4200004200004200004200004200004000004300034100014401044200004601 - 044100004400024200004000003B00003C03013600003C03013C00004601004F - 00006205046D02047601047D00028000028200018200028000017C0001720000 - 6804025400004A03003B00003B02003C01004400005300026502047302057D00 - 028500008A000089000184000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018200018000017F00017D01017B01017D01017F000182 - 00018500008700028700027F00007901017304026B02005A00004C0103420103 - 4000013D00003F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004200024400024B01073F00004A - 05083900004405073A00004101014501024C02025300025A0002600001680002 - 6E00057800058000048400028400028200028200028200028000028000027F00 - 027F00027D00027D00027B00027B00027B00027002045700004C00014B000049 - 00004800004500004300004000004302014202013F02003D02003B02003A0100 - 3A01003C01004101014200014200024200014400024400014400024400014500 - 034A06074000004C08093E00004A060740000043010240000043060437000042 - 09073400004508044200005000006205046D02047601047D0004800002820002 - 8400028000027B00007706046200006009054100004306023600003C03014200 - 005101026302047103057D00048500018C00008D000184000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018000018200018000017F00017D - 01017B01017D01017F00018200018500008700028700027F0000790101730402 - 6B02005A00004400003D00003F00004302044201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073F - 00004700033F00004C070A3A00004A0A0A390000460606410000480000500203 - 5B02056201036900036F00027700047B00058000048200028200028200028200 - 028000028000028000027F00027F00027D00027D00027B00027B00027B000276 - 01046600006000006000005D00005C00005A0000580000560000580000560000 - 5300005200005200004F00004F00004B00004200003F00003F00003F00003F00 - 003F00003F00003F00004204043A0000480A0A370000490B0B3700004406063F - 00004701014100004C09083A00004B0B073E00005005035100006604046F0204 - 7801027F0002820002840002820002800002800102720000740A09510000540A - 083900004007053B00004200005101026103047103057D00048500018C00008B - 0001840001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018200018000017F00017D01017B01017D01017F0001820001850000870002 - 8700027F00007901017304026B02005A00004D02044201034000013D00003E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004300034100004A06073A00004D0B0C3900004A0A09 - 3A00004701014B00005502016104056A03067302067700037E00048000048200 - 028200018200028200018200028000018000028000018000027F00017F00027D - 01017D00027B01017D00027901027500037300037300047200026F00026F0001 - 6D00026B00006B00036901026600026501016400016400006400015E00015100 - 004B00004B00004A00004B00004A00004A00004A00004600004F080540000053 - 0C09400000510A074000004B01014D000056030545000055090A430000550806 - 4A00005B00006B03047401047B00028000028200028400028200028200027D00 - 008208086400006B0E0B4500004B0B0736000040050342000051010261030470 - 03057B00048300018A00008B0001840001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000018200018000017F00017D01017B01017D0101 - 7F00018200018500008700028700027F00007901017304026B02005A00004600 - 003E00004000014302044201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E00004301023A0000 - 4A0A093900004C0C0B3A00004A07044700005100005C02016905057305077B02 - 0680010386000486000284000184000084000182000082000182000082000180 - 01008000017F01007F00017F01007F00017D02007F00017F0001810204810003 - 8000058001038000057D00027B00047901027A01057902037800047601027500 - 037301017300037100036D020469030469020568040469020568040468030566 - 0404630204590000680A0B530000690B0C5300006305065A0000610002570000 - 6508094E0000630B0B5000006306056100007002047800047F00028200028400 - 028400028200018200018601037900007C0C0C5500005C0C0B3E00004609073E - 01004400005101026103047003057B0004830001880000890001840001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001820001800001 - 7F00017D01017B01017D01017F00018200018500008700028700027F00007901 - 017304026B02005A00004C01034201034000013D00003E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004202023C00004407053700004A0B073900004A0A063F00004E01005500 - 005F02016C04057604048102048400028B00028C000287000084000086000084 - 0000840000840000840000820000820000820000800100800100800100800100 - 8001008001008400018400028200028200028200028200028000027F00028102 - 047F02047F02047E01037C01037B00027B00027B00027E01037E01037E00057C - 01037C01057C01037C01057A02037700037D08096E00007F0D0D6A00007C0A0A - 6C00007302056D000274060A620000710C0E5B0000700B0D6400007103057800 - 047D00028200028600028400028400028000018200018400008707086B000070 - 0C0A4A00005009063B0000440403440000510102610304700305790004810001 - 8600008700018200018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018200018000017F00017D01017B01017D01017F00018200018500 - 008700028700027F00007901017304026B02005A00004500003E000040000143 - 02044100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053D00003D02003800004208033700004708 - 043D00004B04004D00005801006302006F03027903028200018700018F000190 - 0002890000860000870000860000860000860000860000840000840000840000 - 8400008400008400008400008400008200008100007F00007F00007F00007E00 - 007E00007E00007C00007E02027C02027C02027B01017B01017B01017A00007F - 00008800008C00008C00018A00008A00018800008800018600008A0206820000 - 8C070A7F00008A070A7D00008603067F00017D02067500027A060B6C00007609 - 0B6A00007605087700037D000282000286000287000186000184000180000182 - 00018901038100007E07086000005C0606440000460504410100440000510102 - 6103046E03057800047F00018500008600018200018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018200018000017F00017D01017B01 - 017D01017F00018200018500008700028700027F00007901017304026B02005A - 00004E03054302044100023D00004000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00003E00003C01 - 003B03003A00004003003E00004503004800004E00005A01006302006F020079 - 01018100008600008D00018E0002890000870000870000870000870000870000 - 8600008600008600008600008600008600008600008600008600008400008000 - 017F00017F00017F00017D01017D01017D01017E02027D01017D01017D01017C - 00007C00007B00007B00008000008C00029100029000029000028E00028E0002 - 8C00028C00028900018800028500008801038300008500028300008300018000 - 027F00057900017A00067200007601047600017C000182000286000289000189 - 00018700018400018000018200018900018902047700006B04025300004C0200 - 4100004303024400005101026103046E03057800047E00018300008600018200 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018200 - 018000017F00017D01017B01017D01017F00018200018500008700028700027F - 00007901017304026B02005A00004600003E00004000014302044000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100023E00003A01003901003E04003C00004204004100004A01004E - 00005A0300620100710603770100830405830000890001860000870000850000 - 8500008400008400008500008500008600008600008600008600008600008700 - 008700008700008400008000017D01017D01017D01017D01017D01017F00017F - 00017F00017F00017F00017F00017F00017F00017F0001800001860103870002 - 8400018300008100008100008100007F00008000017F00017F00017D01017D01 - 017B01017D01017F00028200028200028000027E00037A00037A00037D000280 - 00028600028900018B00018B00018700008400007F0100800100890001850000 - 7C04056700005802024700004100003E00004701014E00015C00006800017601 - 047F020483010284000182000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018200018000017F00017D01017B01017D01017F000182 - 00018500008700028700027F00007901017304026B02005A00004C0103420103 - 4000013D00003F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00003F01013900003E060136000045 - 08043900004907024300004D00005400006205026400007A0B09730000840808 - 7F00008301028301028001008100008100008100008100008200018301018100 - 008100008100008100008300008300008300008100007E00007E00007E00007E - 00007D00007D00007E00007E00007F00007F0000810000810000810000810000 - 8300008100008101028001027F00017E00007B00007B00007C00007C00007C02 - 027C02027C02027A02027A02027A02027A02027E020284000486000482000480 - 00047D00047E01038001038300038700018B00018D00018B0001870000820000 - 7F01008001008600008B0406740000710A084F00004D06033C00004101004502 - 014E00015900006600017401047D020481010282000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018000018200018000017F00017D - 01017B01017D01017F00018200018500008700028700027F0000790101730402 - 6B02005A00004400003D00003F00004302044201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073C - 00003E0301340000450A083700004A0B073A00004B0603470000520100510000 - 6909095E00007A0E0D6A00007D08097600007801027802017800017800007800 - 017800007901027901017B00027B01017B00027B01017D00027D01017D00027D - 00027E00017F00017F00017F0001810001810001830001830001860002860002 - 8700028700028700028700028900028600028101027E02027D01017C00007C00 - 007C00007C00007C00007E02027E02027E02027C02027C02027C02027C020280 - 01028200048400048000027F00027D00027D00027F00028200018700018B0001 - 8D00008B00008600008200007F01007F0100890204800000800B0C5D00005F0C - 0B3E00004606053D00004502014B00005700006501017201047D020481010282 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018200018000017F00017D01017B01017D01017F0001820001850000870002 - 8700027F00007901017304026B02005A00004D02044201034000013D00003E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004001033A00004308063500004A0D0B3700004A0B07 - 3C00004702004700005607044C0000670D0C5300006D0C095F00006A03016B00 - 026B01006A00016A00006C00016C00006D00026D010071030571030371030573 - 03037302057303037302057702037A01057C01037C01057E01037E0005810204 - 8201068201048200048200028400048400028600048600028600048400028001 - 037E02027D00027C00007C00017D01017D00027E02027E00017E00007E00017E - 00007E00017E00007E00017F00017F00017F00037C00017A0001790000790000 - 7D00008000008700018B00018B00008900008600008001007D02007F01008300 - 008808096B000071100D4900004E0B083700004106044201004B000057000064 - 00007201047A0203810102810000800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000018200018000017F00017D01017B01017D0101 - 7F00018200018500008700028700027F00007901017304026B02005A00004600 - 003E00004000014302044201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000400103370000 - 480A0A3700004A0C0C3900004707063F0000480202410000550A084500005D0B - 0A4A00005A04045200005A00005A00005B00005B00005B00005B00005D00005D - 00006201036202026201036402026401036402026401036701026B00036D0002 - 6E00046F01037201057201047501067702057800057800047900057B00047D00 - 057D00047D00057D00047C01057B00027B00047A00017D00047D000280000580 - 01037F00037F00018100038100018300038300018300038100017F00027B0002 - 7901027801027700017800017C00007F00008600008900008B00008900008601 - 008002007D02007D02008503047700007A0C0C5300005A0D0B3A0000430A083B - 02004101004A00005400006200007100037A0203800001810000800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001820001800001 - 7F00017D01017B01017D01017F00018200018500008700028700027F00007901 - 017304026B02005A00004C01034201034000013D00003E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004201033E0000440507370000480A0A3700004709093800004202013F00 - 004706053C00004E09063E00004D06034200004800004B00004B00004C00004C - 00004C00004C00004F00004F0000510000510000520000520000520000520000 - 5400005600005800005A00005A00005B00005D00006000016000016200016601 - 036700036900036B00036D00036D00036E00036E00036E00036E00026E00026F - 00017000027300037300037601047901057A01057C01057C01057E00057E0005 - 7E00057E00057901027601027503037503037503037803047B03038102038400 - 008700008900008900008401008002007B03007B03007D000080060665000067 - 0C08430000490A063500003E07043F0200470000540000620000710003790102 - 7F00018100008000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018200018000017F00017D01017B01017D01017F00018200018500 - 008700028700027F00007901017304026B02005A00004500003E000040000143 - 02044100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004100043C00004604093700004506 - 083600004004053B00003E02023900004407053700004407053700004303023E - 00004101004101004000003F0000400000410000440001440100450000450000 - 4700004700004900004900004900004700004200004200004300004600004700 - 004A00004B00004E000151010253000254000256000258000258000258000258 - 00005700005700005700005900005900005C00005E0001610002640103660103 - 6700036900036B00036B00036B00036D00026E00006F00006D00006E00007003 - 017304027903027F03038400008700008900008700008401008002007B03007B - 03007D01017200006E07055200004F05033700003C07043904013E0100470000 - 5400006100006F01037901027F00018000008000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018200018000017F00017D01017B01 - 017D01017F00018200018500008700028700027F00007901017304026B02005A - 00004E03054302044100023D00004000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000014000 - 034100043F00014300033E00004201033D00003E00003C00003B02003800003B - 04013800003E05033B02003E05033E03013D02003B02003A01003A01003D0101 - 3D01014002024202024301024500034501024501024501024301024202023900 - 003800003A00003B00003E01003F020042020143020143000045000045000047 - 00004900004900004A00004900004800004800004700004700004900004A0000 - 4D00005000005200015300005500015700005700015900005900015B00005B00 - 005D00005C00005E00005F00006302006901026E020174020278010278010278 - 01027602017203016F04016F04016D00006C01035E00005401004300003E0100 - 3801003C05023E01004700005200006100007000007B01018300008400008200 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018200 - 018000017F00017D01017B01017D01017F00018200018500008700028700027F - 00007901017304026B02005A00004600003E00004000014302044000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100024000013E00013F000043000343000049000345000046000143 - 00004000003B00003B04013501003B04003700003B03003C02004004003E0200 - 3F05003800003B03023600003A00013A00004100014200004700054300004701 - 023F00004101003E01003D01013C00003F03033B00004204043D000041030341 - 0101410101400000430102410000460203410000470102430000460203440100 - 4703044200004602034200004701024500004700004600004B00024700004B00 - 024800004B00014A00004900004600004900024500004B00024700004B00014C - 00004E00004F00005200014E00005200014C00004F0000500000510000500000 - 5200024800004900033F00003F00023E00004301024600005300005D00007302 - 007D00008C00018C000084000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018200018000017F00017D01017B01017D01017F000182 - 00018500008700028700027F00007901017304026B02005A00004C0103420103 - 4000013D00003F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00003F00023D00004203053D00004E - 04084300005003064500004600013F00004005033300003E0A043000003F0803 - 3800003F0300410100450700370000420A053300003F07063600003E02033F00 - 024701073F00004C05083C00004705063A00003F02003E00004305053A000046 - 08083900004507073C00004103033D00004303033900004606063A0000460405 - 3C00004000003F00004204043800004507073700004305053B00004101013F00 - 004404043B00004806073A00004705063D00004101013D000040040536000043 - 07083500004206073A00003F00023D0000420305380000450608370000440507 - 3C00004200024400004B01054100004C05083C00004704093C00003F00024000 - 004903034A00006405026800008506058900008E000086000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018000018200018000017F00017D - 01017B01017D01017F00018200018500008700028700027F0000790101730402 - 6B02005A00004400003D00003F00004302044201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073C - 00004001033800004A070A3E000053080A4300004F0406430000420201360000 - 420B06300000430C073300004407033F00004404003C0000480C06350000450E - 0B3200004108093A00014000053A00004A070A3A00004A0A0A3700004207053A - 00004303033C00004A0A0A3900004B0B0B3900004707073F00004101013A0000 - 4808083900004A0A0A3900004505053D00003E0202360000440808350000460A - 0A3500004206063A00003E0202360000450909350000460A0A3500004206063A - 00003C020334000043090A330000440A0B3300004206073A00003E0203360000 - 45090A350000460A0B3500004206073C00004202023B00004A070A3A00004A09 - 0B3700004206073800004004043C0000530806500000740B087000008C070485 - 0000840001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018200018000017F00017D01017B01017D01017F0001820001850000870002 - 8700027F00007901017304026B02005A00004D02044201034000013D00003E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004001033C00004506083A0000510A0D42000053080A - 4000004501023E0000430806320000450E09330000480B073A00004503004300 - 004C08013A00004D0F09350000460D0B3500003E04053A000145050A3700004A - 0B0D370000460A0A3500004003013F00004C06073E0000510B0C3E00004D090A - 3C00004301024000004907083A00004E0C0D3A00004C0A0B3B00004404043C00 - 00440808350000490D0D350000460D0C3500003F060538000041080733000045 - 0D0C320000430B0A3200003B0302380000430708350000480C0D350000440A0B - 3300003C0203380000410708330000460C0D330000430A0B3300003C03023A00 - 004507073700004A0B0D370000460A0B3200003B02033800004508063E00005F - 0D085700007C0E0A780000840300820001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000018200018000017F00017D01017B01017D0101 - 7F00018200018500008700028700027F00007901017304026B02005A00004600 - 003E00004000014302044201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083C0000400103370000 - 4B080B3E0000530A0C4200004E0507410000420201350000440C073300004A0D - 093A00004C07044700004D0300440000520B073E00004E0D0C3700004607093A - 00003E0203350000460A0B350000480C0C3500004308063E00004A0202440000 - 54080943000055090A4200004E04044300004A0202410000500A0A3E0000500D - 0C3C00004B08073F0000430302370000490C0A3700004B0E0C3500004409073A - 00003C0301330000430C09320000450E0B3000003E09063700003E0202370000 - 480A0A3700004A0C0C3500004307073A00003C0302330000430B0A320000450D - 0C3000004008073700003C0302330000460A0A330000460C0D3200003E080835 - 00003B05043400004B0B074500006A0F0A6200007F0A057A0000800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001820001800001 - 7F00017D01017B01017D01017F00018200018500008700028700027F00007901 - 017304026B02005A00004C01034201034000013D00003E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004001033C00004405073A00004F080B4000005007093F00004301023C00 - 00420705350000480B073A00004E09064400005001005200005907024A000058 - 0B084200004E08083E00004201033C0000420607350000460A0A370000470A08 - 3A00004701015100005B04074C00005F080B4A00005A06084A00004F00004B00 - 005103044500005408094300005107074300004A00004500004B05053E00004E - 08083E00004A07063A00004100003E0000460605370000460B09350000450A08 - 3600004003013F00004905063E00004D090A3C00004A08093B00004202023C00 - 00440606350000440B0A330000430A093400003C030138000040070535000046 - 0A0A35000043090A3300003903023702004008033A0000560C06520000710D08 - 6E00007D05007F00018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018200018000017F00017D01017B01017D01017F00018200018500 - 008700028700027F00007901017304026B02005A00004500003E000040000143 - 02044100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053D00003F00023A00004704073E00004E05 - 074100004703044000003F02003800004208033900004C070444000054020154 - 00006205025F01006508055500005D07074D00004F02054500004200023A0000 - 4406063700004707073D00004B03034D00006204056300006A07095C00006706 - 085900006002035A00005C00005500005D05054E00005C06064D000057040352 - 00005603025100005906054B00005705044800004E01004900004B0000460000 - 4F05034000004E07043F00004904014600004B00004800005404054500005105 - 064300004D03034600004600004100004906053A00004807063A00004404033F - 00004101003C00004707033A00004807063A00004204043B00003F04023B0000 - 4B0603470000650A066300007608047701007F00018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018200018000017F00017D01017B01 - 017D01017F00018200018500008700028700027F00007901017304026B02005A - 00004E03054302044100023D00004000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000013E00 - 013F00023F00004500034300004701024000004000003E01003D02003C000043 - 03004700005000005400005C00006D06047007046C02016A05036100005F0203 - 5200014F00034500014200023E00004301024300004C00014F00005700006E03 - 067504086F00047203076C00026F010569000168000267000368030564000167 - 04066000016403055F01026302046904066A0507660103670406600000610002 - 5B00005B00005900005800005300005500005100005300005000005100005500 - 005800005500005900015300005500015000005100005000004F00004A00004C - 00014800004B01014800004700004700004801004700004B01004700004B0101 - 4600004500004401004702004800005503005E00006E05027302007902007F00 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018200 - 018000017F00017D01017B01017D01017F00018200018500008700028700027F - 00007901017304026B02005A00004600003E00004000014302044000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100024000013E00013D00004300034100004501024100004200013E - 00003D02003B0000420300430000510402560000630506690304730200790302 - 7902037500017201056C03066200065400014B00014400004501024500005103 - 045600006205066902057800047D00047B00047B000479000479000478000476 - 01047401047201047201047002046F02046F02046D0204700204760104780004 - 7800047601047601047401047201047002046F02046D02046D02046B03046903 - 046903046903046903046C05086D04076902056700036400015F00005C00005B - 00005C00005B0000590000570000570000550000550000530000550200550200 - 5601005500005600005300005000004F00004F00005100005400005B00006500 - 007001007902007E03017F000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018200018000017F00017D01017B01017D01017F000182 - 00018500008700028700027F00007901017304026B02005A00004C0103420103 - 4000013D00003F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004100023D00004203053B000048 - 05083C00004705063C00003F01013B00004005033A00004E07044B0000610707 - 6300007204067800008002018101027E00017B00047501066900055A00014D00 - 004D02044100005006064C00006406076400007603067F000484000284000482 - 00028200048000028000047F00027D00047B0002790004790102780004780102 - 7601047901028000048400028200048200028000048000027F00047D00027B00 - 0479010279000478010276010476010276010476010475020575020574000571 - 00037000036D00016C00026900006B0003690102670003670102660103660202 - 6401036202026104016003006203006301016400006300006100025E00015D00 - 025D00005F00006400006D00007600007F010080010080000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018000018200018000017F00017D - 01017B01017D01017F00018200018500008700028700027F0000790101730402 - 6B02005A00004400003D00003F00004302044201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004001033800004A070A3A00004B090A3A00004406063A00003C0301360000 - 4A0A064200005F090958000072070A7500037E00008501018700028300018200 - 047C00066E00055D00005300024400005008084300006109095C00007706097A - 0003840002870001870002870001870002860001860002840001820002800001 - 8000027F00017F00027F00017D00028000018700028B00018900028900018900 - 028700018700028600018400028200018200028000018000028000017F00027F - 00027D00027B00027C01057C01037C01057B03047B02067A0304770205750303 - 7502057303037302057303037103057004036F06036F06037005027002027201 - 047100036E00036D00036B00036900036A00016D00007600007C000084000086 - 0000820001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018200018000017F00017D01017B01017D01017F0001820001850000870002 - 8700027F00007901017304026B02005A00004D02044201034000013D00003E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004201033C00004706083900004D0A0D3A00004A0A0A - 3700003E02023800004508063C0000570C0A5000006F0A0C6800007C03077F00 - 008701018800028600008600047E00057000055F00004E000050050740000057 - 0B0C50000070090C6E0000830205860001890001870001870001870001870001 - 8700018600018400018400018200018200018200018200018000018400018900 - 018D00018B00018B00018B00018B000189000189000187000186000186000186 - 0001860001860001840001840001820002800002810003800103820104810204 - 8203058003057C00017A00017A00017800017A00017800017800017701007706 - 037706037A04037B03037C01037C01057B000578000577010674000574010477 - 00037A00017F0000870001870000820001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000018200018000017F00017D01017B01017D0101 - 7F00018200018500008700028700027F00007901017304026B02005A00004600 - 003E00004000014302044201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000420103390000 - 4A090B3900004C0C0C3700004307073800003D04023700004D0A07450000670A - 0B5E00007A060B7900027F00008501018700028500008400047E00056E00055B - 00004F01023E00004D0A09420000630B0B5E00007E060A7E0000840001860000 - 8600008600008600008600008600008400008400008400008400008400008200 - 0082000082000084000086000087000087000087000087000087000086000086 - 0000860000840000840000840000840000840000840000840001830003830003 - 8300038100038300038000028000028000027F00017F00017F00017E00017F00 - 017E00017E00017C00007B04027B05007E03018101028300038300058200057F - 00057D01077B01077A01057B00047F0002840001870001880002820001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001820001800001 - 7F00017D01017B01017D01017F00018200018500008700028700027F00007901 - 017304026B02005A00004C01034201034000013D00003E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004201033E00004605073900004A090B3900004709093600003C03023800 - 004407053C000059090853000072070A7100008002077E000081030085000283 - 00008200047C01056D00035A0000470000460605390000520B084C00006E0809 - 7200008302058200018200008200008200008200008200008200008200008200 - 0082000082000082000082000080010082000082000082000082000082000082 - 0000820000820000800100800100800100800100820000820000820000820000 - 8200008200008402038300038300038200028100018100018000008000008300 - 038300038300038300038300038300038300038101027D02007D020082000084 - 00008700028700028600048200058200077E00067E00057D0004800002840002 - 8A00028800028200018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018200018000017F00017D01017B01017D01017F00018200018500 - 008700028700027F00007901017304026B02005A00004500003E000040000143 - 02044100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004100023C00004605073900004507 - 073600003E05043800003B04013800004B06034800006504066600007C02087E - 00037C01007E03008101027F00007F0004790105690003560000470101380000 - 4208033B00005A07055F00007B04057E00017F00017D02007D02007D02007D02 - 007D02007F01007F01007F01007F01008001008001008001007F01008001007F - 01007B02007902007902007902007B02007B02007B02007B02007B02007B0200 - 7D02007D02007D02007D02007D02007F01008001028101028101028000018000 - 0180000181000081000083010283010285000285000285000285000285000283 - 01027E00007E01008300008600008900028900028700048400048300067F0005 - 7D00047E00038000028400028800028901038200018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018200018000017F00017D01017B01 - 017D01017F00018200018500008700028700027F00007901017304026B02005A - 00004E03054302044100023D00004000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000014000 - 014100023E00004201033E00004002023900003A01003A01003F020043000053 - 01005C00006E00047700037E01037A01007C03018001027F00007F0004790105 - 6700035400004300003B02003800004404005000006703037600028001037D01 - 017D02007D02007D02007D02007D02007D02007D02007F01007F01007F01007F - 01007F01007F01007F01007D0200790200780300790200790200790200790200 - 7902007902007B02007B02007B02007B02007D02007D02007D02007D02007F00 - 017F000181010281010281010281010283010284020382000182000182000182 - 00018400018200018400018200017F00007F0000840000860001870001870002 - 8600028400048200047F00037E00037E00017F00018200028700028801038200 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018200 - 018000017F00017D01017B01017D01017F00018200018500008700028700027F - 00007901017304026B02005A00004600003E00004000014302044000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100024000014000003F00004301023F00004300033E00003F00023C - 00013B00003E00004802024B00005D00006900007A02067A00017A01007E0301 - 8101028100008000047A01056900035600004400003C01003F04024000005600 - 006700007D02068100018000017F00017F00017F00017F00017F00017F00017F - 00018000018000018000018000018000018000018000017F00017F00017D0101 - 7F00017F00017F00017F00017F00017F00017F00017F00017F00017F00017F00 - 017F00017F00017F000180000180000180000180000180000180000180000180 - 0001800001800001800001800001820001800001820001800001800001800001 - 8200018200018200018200018200018200028000028000028000028000018000 - 0180000182000182000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018200018000017F00017D01017B01017D01017F000182 - 00018500008700028700027F00007901017304026B02005A00004C0103420103 - 4000013D00003F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004101013F00004404033B000048 - 06073A00004605073C00003F00043A0000460606410000540403540000710608 - 7300007C02027A00007E03018301028100008200047A01056B00055600004500 - 004407053800004906054F00006F06097A000183000382000280000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018000018200018000017F00017D - 01017B01017D01017F00018200018500008700028700027F0000790101730402 - 6B02005A00004400003D00003F00004302044201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004202023A00004A08093A00004B080B3900004604093C00013D01023C0000 - 4F090A4700006507086300007C07087800007A00007E03018301028100008200 - 047A01056B00055600004800003A0000460B093C000060080861000083050A7F - 0000820002800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018200018000017F00017D01017B01017D01017F0001820001850000870002 - 8700027F00007901017304026B02005A00004D02044201034000013D00003E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004202023E00004707063A00004D0B0C3A00004A090B - 3900004000053900004808083E0000590908530000750A0C7000007D03037A00 - 007E03018301028100008200047A01056B00055600004400004609073500004E - 0B0A4E0000730A0D770000840104820002800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000018200018000017F00017D01017B01017D0101 - 7F00018200018500008700028700027F00007901017304026B02005A00004600 - 003E00004000014302044201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000420202390000 - 4B090A3A00004D0A0D39000047050A3C00013D01023B0000510B0C4700006709 - 0A6100007E090A7800007A00007E03018301028100008200047A01056B000556 - 0000480000390000480D0B3C0000620A0A5F000085070C7F0000820002800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001820001800001 - 7F00017D01017B01017D01017F00018200018500008700028700027F00007901 - 017304026B02005A00004C01034201034000013D00003E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004202023E00004606053A00004B090A3A000049080A3A00004000053900 - 004707073E000057070653000074090B7100007C02027A00007E030183010281 - 00008200047A01056B00055600004400004508063500004C09084E000072090C - 7800008300038200028000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018200018000017F00017D01017B01017D01017F00018200018500 - 008700028700027F00007901017304026B02005A00004500003E000040000143 - 02044100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004101013C00004705063A00004805 - 083A00004402073D00023C00013E00004C06074700006103046500007B060779 - 00007A00007E03018301028100008200047A01056B00055600004700003C0000 - 4308063C00005C04046300008204098000008200028000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018200018000017F00017D01017B01 - 017D01017F00018200018500008700028700027F00007901017304026B02005A - 00004E03054302044100023D00004000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000004000 - 004101003F00004301023F00004201033F00023E00033A00004303034400004F - 00005800006D02047500017B01017A00007E03018301028100008200047A0105 - 6B00055600004500004104023B00004401005300006B02057C00038200028200 - 0280000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018200 - 018000017F00017D01017B01017D01017F00018200018500008700028700027F - 00007901017304026B02005A00004600003E00004000014302044000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100024000004000003F00004301023F00004300033E00004100043E - 00033B00004000004802034B00005D00006900007803047A00007A00007E0301 - 8301028100008200047A01056B00055600004600003E01003F04024000005800 - 006700017F010681000182000280000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018200018000017F00017D01017B01017D01017F000182 - 00018500008700028700027F00007901017304026B02005A00004C0103420103 - 4000013D00003F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004101013F00004404033B000048 - 06073A00004605073C00003F00043A0000460606410000540403540000710608 - 7300007C02027A00007E03018301028100008200047A01056B00055600004500 - 004407053800004906054F00006F06097A000183000382000280000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018000018200018000017F00017D - 01017B01017D01017F00018200018500008700028700027F0000790101730402 - 6B02005A00004400003D00003F00004302044201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004202023A00004A08093A00004B080B3900004604093C00013D01023C0000 - 4F090A4700006507086300007C07087800007A00007E03018301028100008200 - 047A01056B00055600004800003A0000460B093C000060080861000083050A7F - 0000820002800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018200018000017F00017D01017B01017D01017F0001820001850000870002 - 8700027F00007901017304026B02005A00004D02044201034000013D00003E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004202023E00004707063A00004D0B0C3A00004A090B - 3900004000053900004808083E0000590908530000750A0C7000007D03037A00 - 007E03018301028100008200047A01056B00055600004400004609073500004E - 0B0A4E0000730A0D770000840104820002800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000018200018000017F00017D01017B01017D0101 - 7F00018200018500008700028700027F00007901017304026B02005A00004600 - 003E00004000014302044201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000420202390000 - 4B090A3A00004D0A0D39000047050A3C00013D01023B0000510B0C4700006709 - 0A6100007E090A7800007A00007E03018301028100008200047A01056B000556 - 0000480000390000480D0B3C0000620A0A5F000085070C7F0000820002800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001820001800001 - 7F00017D01017B01017D01017F00018200018500008700028700027F00007901 - 017304026B02005A00004C01034201034000013D00003E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004202023E00004606053A00004B090A3A000049080A3A00004000053900 - 004707073E000057070653000074090B7100007C02027A00007E030183010281 - 00008200047A01056B00055600004400004508063500004C09084E000072090C - 7800008300038200028000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018200018000017F00017D01017B01017D01017F00018200018500 - 008700028700027F00007901017304026B02005A00004500003E000040000143 - 02044100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004101013C00004705063A00004805 - 083A00004402073D00023C00013E00004C06074700006103046500007B060779 - 00007A00007E03018301028100008200047A01056B00055600004700003C0000 - 4308063C00005C04046300008204098000008200028000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018200018000017F00017D01017B01 - 017D01017F00018200018500008700028700027F00007901017304026B02005A - 00004E03054302044100023D00004000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000004000 - 004101003F00004301023F00004201033F00023E00033A00004303034400004F - 00005800006D02047500017B01017A00007E03018301028100008200047A0105 - 6B00055800004500004104023B00004401005100006B02057A00038200028000 - 0280000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018200 - 018000017F00017D01017D01017D01017F00018000018300008500028301027E - 00007B01017703026E01005D00004700003E00004000014302044000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100024000004000003F00004301023F00004300033E00004100043E - 00033B00004000004802034B00005D00006900007803047A00007800007C0100 - 8100008200018300057800036800025700004600003E01003F04024000005600 - 006700017D020681000180000280000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000017F00017F00017D01017F00017F - 00017F00017F00017F00017D01017D01017B01017901016D03024F0003420103 - 4000013D00003F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004101013F00004404033B000048 - 06073A00004605073C00003F00043A0000460606410000540403540000710608 - 7300007C02027800007A01008100008400018300057A00036B00035A00004700 - 004606053A00004906054D00006D060976000183000380000280000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00017F00017F00017D01017D01017D01017D01017D01017D01017D01017F0001 - 7F00017002024900003D00003F00004302044201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004202023A00004A08093A00004B080B3900004604093C00013D01023C0000 - 4F090A4700006507086300007C07087800007901017A01008100008400018300 - 057A00036B00035B00014A00003C0000480B093C00005C09085F00007F060A7D - 0000800002800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000017F00017F00017F00017F00017F00017F0001 - 7F00017F00017F00018000018000017202025201044201034000013D00003E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004202023E00004707063A00004D0B0C3A00004A090B - 3900004000053900004808083E0000590908530000750A0C7000007D03037901 - 017A01008100008300008200047B00046C00045C00024600004808073700004E - 0B0A4A0000700B0D720000820104800002800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000018000018000018000018000017F00017F0001 - 7F00017F00018000017F00018000018000018000018000018000017202024B00 - 003E00004000014302044201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000420202390000 - 4B090A3A00004D0A0D39000047050A3C00013D01023B0000510B0C4700006709 - 0A6100007E090A7800007A02027A01008000008300008400047D00046F00065E - 00044A00003B00004A0D0B3C00005D0B0A5C00007E090C7C0000800002800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000018000018000018000018000017F00017F0001 - 8000018000018000018000018000018000018200018000018200018200018200 - 018200018200017402025100034201034000013D00003E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004202023E00004606053A00004B090A3A000049080A3A00004000053900 - 004707073E000057070653000074090B7100007C02027A02027D020080000083 - 00008400047E00057000076001054700004707063700004C09084900006D0A0C - 6F00007E01037F00028000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000017F00017F00018000018000018000018000018200018200018200 - 018200018200018200018200018200018200017402024A00003E000040000143 - 02044100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004101013C00004705063A00004805 - 083A00004402073D00023C00013E00004C06074700006103046500007B060779 - 00007A02027D02008000008500008600048000057301086102064A00003F0000 - 4508063C00005705045C00007706097900007F00028000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000017F00017F00018000018000018200 - 0182000184000184000184000184000184000184000182000182000182000174 - 02025302054302044100023D00004000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000004000 - 004101003F00004301023F00004201033F00023E00033A00004303034400004F - 00005800006D02047500017B01017B03037D0200800000840000860004810005 - 7301086403074A00004403023D00004201004C00006403057100037B00027F00 - 0280000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000017F00 - 017F000180000180000182000182000184000184000186000186000184000182 - 00018200018000018000017202024B00003E00004000014302044000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100024000004000003F00004301023F00004300033E00004100043E - 00033B00004000004802034B00005D00006900007803047A00007901017D0200 - 8200018600018700048000047400076602074D00004200004104023E00005000 - 005900006F01037901027F000280000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000017F00017F000180000182000184000184000186000186 - 00018500008600018500028402038202038102037E0202700403510003420103 - 4000013D00003F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004101013F00004404033B000048 - 06073A00004605073C00003F00043A0000460606410000540403540000710608 - 7300007C02027901017D02008200018600018700048200047600076602074D00 - 004704033900004807064500006003046900007A03047D000280000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018000017F000180000182000182 - 00018400018400018600018600018700028500028200018000017D01017C0202 - 7A02026C05034700003D00003F00004302044201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004202023A00004A08093A00004B080B3900004604093C00013D01023C0000 - 4F090A4700006507086300007C07087800007901017D02008200018600018700 - 048200047600076802075200013E0000470A083A000056090750000070050775 - 00017D0002800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001820001840001860001860001870001860001880103830102 - 8000017C00007800007602017203016905034E01044201034000013D00003E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004202023E00004707063A00004D0B0C3A00004A090B - 3900004000053900004808083E0000590908530000750A0C7000007D03037901 - 017D02008200018700018900048400047800076802074E00004C06063900004D - 0C0B4300006109096200007904057D0002800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001820001840001840001860001860001 - 8700018600018400018000017E02027A02027403016F02006B02005F02004600 - 003E00004000014302044201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000420202390000 - 4B090A3A00004D0A0D39000047050A3C00013D01023B0000510B0C4700006709 - 0A6100007E090A7800007901017D020084000187000189000484000478000769 - 02075400023F00004B0B0A3A0000550A084E00006F07087200007D0002800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001820001820001 - 8400018600018700018700018600018600017F00007E00007B03037905047205 - 036A03006300005700004A01034201034000013D00003E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004202023E00004606053A00004B090A3A000049080A3A00004000053900 - 004707073E000057070653000074090B7100007C02027901017D020084000187 - 00018900048400047900076902074F00004B05053900004A0A094300005F0707 - 6100007705057D00028000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018200018400018600018600018700018700018600018400017E00 - 007C00007A04037506046E05026502005D00005100004300003E000040000143 - 02044100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004101013C00004705063A00004805 - 083A00004402073D00023C00013E00004C06074700006103046500007B060779 - 00007901017D02008400018700018900048400047900076B0107530001420000 - 4606053900005005035100006A04057301017D00028000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018200018400018600018600018700 - 018700018600018400018101027C02027403016E03006602005F010058000050 - 00004A04054302044100023D00004000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000004000 - 004101003F00004301023F00004201033F00023E00033A00004303034600004F - 00005800006D02047700017B00027B01017F0001840001860001860002820004 - 7D00056F01075100004701023F00004202014400005401006700007702037D01 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001820001820001820001820001800001800001 - 7F00017F00017F00017F00017F00017F00017F00017F00017F00018000018200 - 018200018400018400018600018600018400018000018006067803046D010063 - 00005A00005200004E02004C03004000003F00004100014401044000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100024000003E00003F00004301023F00004300033E00004100043E - 00033D00004000004A01034D00005F00006900007A03047C00017F0002800002 - 8400018200007B02007B01018200027800055400014200004301063B00004202 - 014D00006E03007D02007F000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001820001860002870002 - 8600018400018200017F00017D01017B01017B02007902007902007B02007B02 - 007D02007D02007F01007D00007F00008200008301018301028101028001037B - 00027604046B00026303035200004B01003F00003E04003D0200440203450102 - 4300004000003F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004101013D00004205033B000048 - 06073A00004605073C00003F00043C0000470506430000560403560000730608 - 7500007E01037F00048000028400017F01007604007803008400017B00045200 - 004502073B000045050A3500005107036C000082040080000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018200018600028600028400018200018000017F00017D01017B01017B02 - 007B02007B02007B02007D02007F01007F020080020082000082000081020180 - 01027E02027802017301016D01006602026307064D00005107053A0000420705 - 3600003C05023B00003E00004000004402034201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004002023800004A08093A00004B080B3900004604093C00013F00023D0000 - 51080A4900006706086500007E07087A00007F00048000028400017F01007604 - 007803008400017B00045500033C000049060D370000460B094300007507037F - 0100800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000017F00017F00017F00 - 017F00017F00017F00017F000180000180010082000082000084000084000086 - 00008B00038901038402037E01037402026902005F0201570200520503440000 - 4F09093C00004A09083A00004806074100004204043E02023C00003900003E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004202023C00004508063A00004D0B0C3A00004A090B - 3700004000053B00004808084000005B0908550000750A0C7000007F02047F00 - 048000028400017F01007604007803008400017B000451000048050A3900004A - 0A0F350000560C08690000830501800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000017F00017B01 - 017B01017B01017D01017F000180000182000184000184000186000186000086 - 00008600008600008600008700018C01048901058102047702036A02035D0100 - 5001004601003F0000430904350000490C0A3A00004D0A094100004703043900 - 003500003701003A04034201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000400202370000 - 4B090A3A00004D0A0D39000045050A3A00013D01023B0000530A0C4700006709 - 0A6100007E090A7800007F00048000028400017F01007604007803008400017B - 00045600043B00004B080F370000470C0A4300007608047E0000800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000017D01017802017602017802017B01017F000182000186000187 - 00018900018B00018B00018900018900018700018700018600018400067E0005 - 7702056C01035F01025301004601003D00003B0401300000420A09330000490B - 0B3A00004C05084200003C04033704013502003200003E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004202023C00004606053A00004B090A3A000049080A3800003E01053900 - 004507073E0000570706520000720A0B6F00007C01037F00048000028400017F - 01007604007803008400017B000451000047040939000048080D350000540A06 - 6A00008305018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000017D01017802017602017802017B - 01018000018400018700018B00018D00018D00018B0001890001870001860001 - 8400027D00027200036B00036500045E01025400024C00014300003D00003700 - 003E0704320000440B0A3500004709093B00004002023600003500003702003A - 05024100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004101013C00004705063A00004805 - 083A00004202073B00023A00013C00004C06074500005E040461000079070777 - 00007F00048000028400017F01007604007803008400017B00045500033E0000 - 46030A3700004207054600007305017F01008000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018000018000018000018000017F - 00017901017802017B01017F00018400018700018B00018D00018D00028B0002 - 8900028600028000027D00027B00047002045800004F00005000024E00014E00 - 024B00014900004600004701023E00004706083600004208093400003B050537 - 00004106044304004102003D00004000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000004000 - 004101003F00004301023F00004201033D00023C00033800003F03034200004D - 00005500006804047101017901027F00048000028400017F0100760400780300 - 8400017B00045300014300053F00034000053900004D03006E00008103008000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000017F00017D01017D0101800001840001870001890001 - 8B00018B00018900028600028200027D00027800047201046F02046204054700 - 003E00004000004300004800014A00014A00004A00004A00014A010343000144 - 03053B00003C03043300003901004200004800004C00004F02004000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100024000004000003F00004301023F00004300033E00003F00043C - 00033C02033C00004503044800005800006000007002027902037D0004800002 - 8400017F01007604007803008400017B00045400024000024300073B00003E03 - 0149000071030080020080000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001820001840000860000 - 8700018900018800008800008700008400008200047C00037B03076F01036B04 - 075E00005800004B00004000003900003E02033C000043000343000048000149 - 00004900024700004701024000004202023B00003C00004000005000005B0000 - 6101016303033F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004101013F00004404033B000048 - 06073A00004605073A00003B00043900013F06053C00005107054D0000660404 - 6A00007904057D00048000028400017F01007604007803008400017B00045200 - 004502073B000045050A3500005107036C000082040080000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018200018900008A00008900008900008700008600008400028100037900 - 047605086600006706085100005705044700004901013F000040040538000045 - 06083700004406063C00004101014200014804053E00004B03034200004F0505 - 4800005602046200006A00006E00027002024201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004301023B00004C08093C00004B080B3900004205093800013C0304360000 - 4A0A0A4000005C09085600007107067601027D00048000028400017F01007604 - 007803008400017B00045500033C000049060D370000460B094300007507037F - 0100800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018400018B00008C00008B00008700008400 - 008000017D02047904057306086000006508094A00005206073E000048070642 - 00014900034100004E0809390000440B0A3000003B08063101003A0704350000 - 4A07064300005B04075300006C060B6E00047500007900007D00027E02023E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004202023F00004807063C00004F0B0C3A00004A090B - 3500003C0105380000420908390000540D0A4A0000670A096300007806067D00 - 048000028400017F01007604007803008400017B000451000048050A3900004A - 0A0F350000560C08690000830501800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018400018B00 - 008D00008900008400007F00017802016F01016803015F02015F090947000051 - 09093C00004608083600004505054800005504074200004D0B0C3300003D0D09 - 2900003205013101004109043E00005D0A0857000077090B7300008404098000 - 018301028402038402034201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E00004301023A0000 - 4D090A3C00004D0A0D39000043060A3800013D04053400004A0C0C3E00005C0A - 095300007009077301017D00048000028400017F01007604007803008400017B - 00045600043B00004B080F370000470C0A4300007608047E0000800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018200018600008702008402027E05037504026B02005E000055 - 0000530302440000500A0A3A0000490B0B3500004206073F00004E0002490000 - 53080A3C0000480D0B3000003A0A063101003A0300390000580B085200007A0D - 0F6F00008A070A8500008601038602028602028602023E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004202023F00004706053C00004D090A3A000049080A3600003B02053800 - 00400807370000500B084900006408076400007606067D00048000028400017F - 01007604007803008400017B000451000047040939000048080D350000540A06 - 6A00008305018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018001008200008003007B040274 - 06026A03005D0100500000460000430000460703370000480C0C35000047080A - 3800004200024700005003064000004D0A09390000450B063600004004004300 - 00540802520000720E0C6B0000870B0B80000088000286020283010183010183 - 01014100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004200013D00004905063C00004805 - 083A00004003073800023C03043700004507073F00005705045600006D060472 - 02027D00048000028400017F01007604007803008400017B00045500033E0000 - 46030A3700004207054600007305017F01008000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018000018000018000018000017F - 01007C03017803006E02006602005C01005101004700004000003D0300360000 - 4007053400004607093B00004603084000004200013D00004706053C00004C07 - 044300005003014F00005E04035F00007009076A0000800A097800008305047E - 00007F01007F01007F01007F01004000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000004000 - 004101004100004501023F00004001033B00023C00033D01023F03033C000044 - 04004800005902006A00007A03047D00048000028400017F0100760400780300 - 8400017B00045300014300053F00034000053900004D03006E00008103008000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000017F00017F00017F00017F00017F00017F00017F00017F00018000018200 - 018200018200018000018000017F00017F00017F00017F00017F000180000180 - 00018200018200018400017F00017405036A03006100005700004E0000480000 - 4303003F05003A03003904013700003C03023C00004302044200044702054100 - 004202004300004B01004E00005700005900006000006F05047505057400007A - 02027700007E03017B00007E03017D02007C01007E00007C01004000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100023E00003C00003D00004501024100004001033A00003F000441 - 00034800024400003D04033600004003004D0000710101800002800004800002 - 8400017F01007604007803008400017B00045400024000024300073B00003E03 - 0149000071030080020080000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001820001820001 - 8200018200018000018000017F00017D01017D01017D01017D01017D01017D01 - 017D01017D01017F00018602028701018400008100007E00007C01007A000079 - 01017C02027B00008001037C00008500038500008C0105810106600000520000 - 5200004A00004902004100003F02003C01003B03023901003C02033700003E02 - 033B00004100044200004700004E00005300005900006302006A030171030378 - 04037901017D01017F00017F00017F00017F00017F00017F00017F00017F0001 - 8000017F00013F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00003F01013900004005033D00004A - 06073700004206073A00004400044B00004D02043500003C0A04300000510703 - 7000008800048200048000028400017F01007604007803008400017B00045200 - 004502073B000045050A3500005107036C000082040080000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018200018400018200018200018000018000017F00017D01017D01 - 017D01017D01017D01017D01017D01017D01017F000183010185010184000082 - 00008001008001007F00017D01017B000081050578000085080A770000840507 - 7A00007100045400004D03034100004C06063A00004606053A00003D01013800 - 003D03043700004607093800004605073B00004700005000005700005E000064 - 01006B02007203017A02027F0303800001820001820001820001800001800001 - 7F00017F00018000018000018000018000014201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073C - 00003C03023600004C08093C000048090B3500004404094100014E0003440000 - 430A092E0000410D074300007904058500018200048000028400017F01007604 - 007803008400017B00045500033C000049060D370000460B094300007507037F - 0100800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018200018200018200018200018000 - 018000018000017F00017F00017F00017F00017F00017F00017F00017F00017F - 00017E03018002018102018501018700028800028A00028B00038700037A0000 - 850A0C6B0000770C0E5D00006404045100004C00013F00004C08093A00004A0A - 0A3700004406063C00003C00003700004909093A00004F0B0C3E00004C030548 - 00005801006002006502006902006F02007602017C0202800102800001820001 - 8200018200018000018000017F00017F00018000018000018000018000013E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004002023800004308063C00004F0B0C370000460A0B - 3700004500054A0000500507330000410F09300000560C086D00008901058200 - 048000028400017F01007604007803008400017B000451000048050A3900004A - 0A0F350000560C08690000830501800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018200 - 0182000182000182000180000180000180000182000182000182000182000182 - 00018200018200018200018000017D02007D02008102018802028B00038D0003 - 8F00038D000385000187080A6A0000740F0D5000005A0B084000004202003F00 - 004707073900004C0C0C370000480A0A3700004202023D00004706053E000055 - 0B0B430000570A084900005702006104016804006C0300700301740301790101 - 7E02028101028200018200018200018200018000017F00017D01017D01018000 - 018000018000018000014201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083C00003C0302350000 - 4D090A3C00004A0B0D35000045050A4100014F0004430000450C0B2E0000420E - 084300007A05068400008200048000028400017F01007604007803008400017B - 00045600043B00004B080F370000470C0A4300007608047E0000800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000182000182000182000184 - 0001840001840001860001860001860001860001860001840001820001800001 - 8500028801038B00048B00048800038400028204096E0000700A0B4E0000550B - 093700003E0A043300003B0203350000460A0B350000480C0C3700004707063F - 00004903034300005508064900005E08084E00006309085F02006A0602700502 - 7304027703027A02027E02028000018200018200018400018200018200018000 - 017F00017D01017D01018000018000018000018000013E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004002023800004207053C00004D090A37000045090A3800004500054A00 - 004F04063300003F0D07300000540A066E00008901058200048000028400017F - 01007604007803008400017B000451000047040939000048080D350000540A06 - 6A00008305018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001820001840001840001860001860001870001870001870001870001870001 - 8700018700018500008600018700028601038300038000027900007300006E01 - 036A08084C00005107053900003E0A042D00003708043300003F060932000044 - 0A0B3500004909093B00004701014B00005506034C00006108045300006B0A07 - 6200006F08057104027504027903027A02027E02028101028200018400018400 - 018400018200018000018000017F00017D01017D01017F000180000180000180 - 00014100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053D00003B02013800004905063C00004506 - 083600004202074200024E00034600004007062E00003D090346000077020385 - 00018200048000028400017F01007604007803008400017B00045500033E0000 - 46030A3700004207054600007305017F01008000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00017F00017F0001800001800001820001840001860001870001870001890001 - 8900018900018700018700018700018900018A00018B00028700038001037800 - 046E00026300005900005503024700004906033900004005033300003E07043A - 02013802023300003F06093300004507073B00004B0303490000520000520000 - 6205025E00007009066900007709057403007802017B01017D01017F00018000 - 018200018500028700028600018400018200018000018000017F00017D01017D - 01017F00018000018000018000014000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00003E00003A01 - 003D02004100004501023C00003E02033D00024300034C00014B000239000037 - 05003400004D03007200008700038200048000028400017F0100760400780300 - 8400017B00045300014300053F00034000053900004D03006E00008103008000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000017F00017F0001800001800001840001840001 - 8600018700018700018700018700018700018600018600018600018600018600 - 018600028001037702056A02035F02015100004800004000003C02003700003C - 03013900004003014000004002023A00013A01043800014001033F0000490101 - 4B00005100005400005E00006600007207037504017B09037903007B03007E00 - 007F00007F000082000184000186000187000287000286000184000182000180 - 00018000017F00017D01017D01017F00018000018000018000014000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100023E00003A01003B00004501024100004001033A00003F000443 - 00034D00024800003D0403320000390500490000750001860002820004800002 - 8400017F01007604007803008400017B00045400024000024300073B00003E03 - 0149000071030080020080000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000018000018000018000018000017F00017F0001 - 8000018000018400018400018600018600018801038700028600018300008100 - 007F00007F00007F00017E03057601047204066300005C02024D00004801003E - 00003C01003700003D04033B00004404044300004802034600014102043E0203 - 4100024300004600004A00004E00005600006604046B04027203017603007902 - 007D02007F020080020082000084000184000186000186000186000186000186 - 00018400018400018200018000018000017F00017D01017D01017F0001800001 - 8000018000013F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00003F01013900004005033D00004A - 06073700004206073A00004400044B00004D02043500003C0A04300000510703 - 7000008800048200048000028400017F01007604007803008400017B00045200 - 004502073B000045050A3500005107036C000082040080000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000017F00017F00018000018200018400018400018600018600018400 - 018400018200017F00017D01017A02027903027303036400006205045500005C - 06064900004F05034100004201003C00004205033900004808083B00004C0607 - 4400004900024300004300004700004B00004F00005500005C00006200006D03 - 027203017803007B02007F020080020082020084010086000086000186000186 - 00018700018600018600018400018400018200018200018000017F00017F0001 - 7D01017F00018000018000018000018000014201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073C - 00003C03023600004C08093C000048090B3500004404094100014E0003440000 - 430A092E0000410D074300007904058500018200048000028400017F01007604 - 007803008400017B00045500033C000049060D370000460B094300007507037F - 0100800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018200018200018400 - 018400018400018400018000007D00007D01017A020275040272050370050265 - 06034B01003C00004B08073E00005109094200005003064900004C0002450000 - 52060A4000004F080B3C00004603064000004800004C00005000005500005D00 - 016402026903047004037402027802017D02007F010082010084010084010086 - 0100860000870001870001870001860001860001860001840001840001820001 - 8200018000017F00017F00017F00017F00018000018000018000018000013E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004002023800004308063C00004F0B0C370000460A0B - 3700004500054A0000500507330000410F09300000560C086D00008901058200 - 048000028400017F01007604007803008400017B000451000048050A3900004A - 0A0F350000560C08690000830501800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018200018200018200018400018400018200018000017E000078000076020171 - 04026E05026805016305005605003A00003A0802320000490C0A3C0000510909 - 4600005300034F000057030747000055080C4000004C070A3900004700035000 - 005700005C00006000006802037004037505057A06057901017D010180010082 - 0000840100840100860100860000870001870001870001860001860001840001 - 8400018200018200018200018000018000017F00017F00017F00017F00018000 - 018000018000018000014201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083C00003C0302350000 - 4D090A3C00004A0B0D35000045050A4100014F0004430000450C0B2E0000420E - 084300007A05068400008200048000028400017F01007604007803008400017B - 00045600043B00004B080F370000470C0A4300007608047E0000800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018200018400018400018400018400018200018000017F - 00017B03037605037005026905016004005C04005403004903003C05002C0000 - 400D0B3300004C0C0C3E00005104084A000052000548000056060D4300005208 - 0E3E000048050A4800005C00006500006A00006D01007202027903027D030380 - 0404800001820000840000840000860000860000860000860000860001860001 - 8600018400018400018400018400018200018200018000018000018000018000 - 018000018000018000018000018000018000018000013E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004002023800004207053C00004D090A37000045090A3800004500054A00 - 004F04063300003F0D07300000540A066E00008901058200048000028400017F - 01007604007803008400017B000451000047040939000048080D350000540A06 - 6A00008305018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000182000184000184000184000184 - 00018400018200018000017B01017A06057205036905015F03005602004F0100 - 4901004302003B03003F0A07330000460D0C3700004909093B00004400024500 - 014E040842000052050C42000053060D46000057020668030171030075010078 - 03007B0101800102810102850002860000860000860000860000860000860000 - 8600008600008600018400018400018400018400018200018200018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00014100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053D00003B02013800004905063C00004506 - 083600004202074200024E00034600004007062E00003D090346000077020385 - 00018200048000028400017F01007604007803008400017B00045500033E0000 - 46030A3700004207054600007305017F01008000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000182 - 00018400018600018600018600018400018200017F00017901017706046D0401 - 6002005600004D00004601004103004203004802024300004A06073A00004307 - 073400003905053400003A03063700004604093E000052030C4D00015D040E62 - 00067202027903007D02007F0200800100840000860000870000890000890000 - 8900018700018600018600018400018400018400018400018400018200018200 - 018000018000017F00017F00017F00017F00017F000180000180000180000180 - 00018000018000018000018000014000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00003E00003A01 - 003D02004100004501023C00003E02033D00024300034C00014B000239000037 - 05003400004D03007200008700038200048000028400017F0100760400780300 - 8400017B00045300014300053F00034000053900004D03006E00008103008000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018001 - 0080010080010080010082000182000182000182000182000182000182000180 - 00018000018000018000018000018400018400018200018000017D0101790101 - 7403016F03026905035F04005501004C00004600004100004103004305004400 - 004800014100004202023800003B03023600003802013B010242010345000050 - 00025600006300086700077202097800007E0100800100820100840000860000 - 8701018800018700008700008700018600018600018400018200018200018200 - 018200018200018200018000018000017F00017F00017F00017F00017F00017F - 00018000018000018000018000018000018000018000018000014000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100023E00003A01003B00004501024100004001033A00003F000443 - 00034D00024800003D0403320000390500490000750001860002820004800002 - 8400017F01007604007803008400017B00045400024000024300073B00003E03 - 0149000071030080020080000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018001007F020080020080020082010084000084000086000086 - 00008701018701018500028200018000017F00007E00017E0001830102810102 - 8205077702037307066400005A01004F00004A00004600004702004100004302 - 013F00004201004000003C02033900013C03043900003F03033F00004701014A - 00004F00005800006301016C01037503037902037D00027E00007F0001800100 - 8000018001008200018200018200018200018200018200018200018200018200 - 0182000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000013F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00003F01013900004005033D00004A - 06073700004206073A00004400044B00004D02043500003C0A04300000510703 - 7000008800048200048000028400017F01007604007803008400017B00045200 - 004502073B000045050A3500005107036C000082040080000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018001007F02007F030080020082 - 0100840100860100860000870000880001870101850002840001820001800001 - 7F00027F00027E0000800606720000770B0A5C00005D09044A00004602003F00 - 004006013600004308063700004606063D00004100023701013B060933000042 - 08093A00004D05054A00005600005E0000660000700000790101800201830101 - 8601008500008200018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000014201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073C - 00003C03023600004C08093C000048090B3500004404094100014E0003440000 - 430A092E0000410D074300007904058500018200048000028400017F01007604 - 007803008400017B00045500033C000049060D370000460B094300007507037F - 0100800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018000018000018000018000017F - 01007D02007B03007D02007F0200800100820000840000860000860001860001 - 8400018500028300038100038100037E01037B03046E000076090B5B0000670B - 0A4A00005006043F0000400301340000430A0935000048090B3900004704073F - 00003F030437000048090B3A000052090B4500005805045900006501016B0100 - 7402027A02028103028301018401008300008200018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000013E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004002023800004308063C00004F0B0C370000460A0B - 3700004500054A0000500507330000410F09300000560C086D00008901058200 - 048000028400017F01007604007803008400017B000451000048050A3900004A - 0A0F350000560C08690000830501800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000017F00017B02007903007B03007D02007F0100800100 - 8200008200008400018400018200018200018100038001038001037A02036E00 - 006F0708590000670B0A4A0000550A083F00004404033A000041080633000048 - 0C0C3700004A090B3C00004500033F00004B0407420000570A0D470000610A0D - 5700006604046B03047103037804037B03038103028102018401008400008200 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000014201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083C00003C0302350000 - 4D090A3C00004A0B0D35000045050A4100014F0004430000450C0B2E0000420E - 084300007A05068400008200048000028400017F01007604007803008400017B - 00045600043B00004B080F370000470C0A4300007608047E0000800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000018000018000018000017F00017B0200790200 - 7B02007D02007D02007F01007F00018000017F00017F00017F00027F00027D00 - 047B00047B000474010468020356000060080849000055090A3E00004808073B - 00003C0302320000440A0B3500004A0B0D3900004A05084500004D00004A0000 - 5D060A4E00006A0C10590000700B0D6B03047204067604047A04037D03037F04 - 0281020182000082000080000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018000013E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004002023800004207053C00004D090A37000045090A3800004500054A00 - 004F04063300003F0D07300000540A066E00008901058200048000028400017F - 01007604007803008400017B000451000047040939000048080D350000540A06 - 6A00008305018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000017F00017D02007D02007D02007D02007D02007D01017D01017D01017A00 - 017A00017800017700017200027000026F000168000258000056060745000050 - 08083C00004808073700003E050438000040070635000048090B3900004C070A - 3F00004E00035400006400055800006F090E5E0000750C0F6D000278070A7604 - 047902037A02027C02027E030180020181020181020180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00014100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053D00003B02013800004905063C00004506 - 083600004202074200024E00034600004007062E00003D090346000077020385 - 00018200048000028400017F01007604007803008400017B00045500033E0000 - 46030A3700004207054600007305017F01008000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018200018200018200018000017F00 - 017D00027B00027901027601047100036E00026A000165000163000060000059 - 00004C00014200004905063900004507073700003F06053A01003B0102380000 - 4405073A00004A05084100004D01055000006701066A00007405096B00007908 - 0C7000007C070A7901057901027901027B01017D01017F00017F000180020181 - 0201800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000014000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00003E00003A01 - 003D02004100004501023C00003E02033D00024300034C00014B000239000037 - 05003400004D03007200008700038200048000028400017F0100760400780300 - 8400017B00045300014300053F00034000053900004D03006E00008103008000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018200018600 - 018700018600018400018000027D00027901027402026F02046802036402025F - 01025800005400005100004A00004100004002023B00003F03033B00003E0504 - 3A01003E02023E00014100024100004700034700004C00024B00005700007203 - 077D03097900057D04087800037D02067A00037B00027D00027C00017C00007C - 00007E00007F0001800201810302800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000018000018000018000018000014000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100023E00003A01003B00004501024100004001033A00003F000443 - 00034D00024800003D0403320000390500490000750001860002820004800002 - 8400017F01007604007803008400017B00045400024000024300073B00003E03 - 0149000071030080020080000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018400018B00028C00018A00018500018200047C010575020571 - 04066500025B00005802024D00004C02024200004300003D00003B0201380000 - 3D04033900004004043B00004103034101014703044701024800004A00004E00 - 0052000058010563020678000580000480000480000480000480000280000280 - 00027F00027F00017F00017F00017F00017F00017F00017F0001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000013F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00003F01013900004005033D00004A - 06073700004206073A00004400044B00004D02043500003C0A04300000510703 - 7000008800048200048000028400017F01007604007803008400017B00045200 - 004502073B000045050A3500005107036C000082040080000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018400018900008C00018A000386 - 00068000057800046E00026500025900005704034600004D07073A0000420705 - 3500003904013600003D05043400004108073800004707074000004901014900 - 004E00005200005500015A00025E01026001056A01047D000484000284000484 - 00028400028200028200028200028200018000018000017F00017F00017F0001 - 7F00017F00018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000014201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073C - 00003C03023600004C08093C000048090B3500004404094100014E0003440000 - 430A092E0000410D074300007904058500018200048000028400017F01007604 - 007803008400017B00045500033C000049060D370000460B094300007507037F - 0100800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000182 - 00018500008700048600068100077A00066E00036300005A0000530001440000 - 4C0809370000440C0B2E00003B0A083302003A0403340000450A083700004B0A - 094000005004054E00004F00005600005D00006502046A03066C04056B020571 - 0003800002860001860002860001860001840001840001820001820001800001 - 8000018000018000018000017F00017F00018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000013E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004002023800004308063C00004F0B0C370000460A0B - 3700004500054A0000500507330000410F09300000560C086D00008901058200 - 048000028400017F01007604007803008400017B000451000048050A3900004A - 0A0F350000560C08690000830501800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000028000047E00057900057400056C0002630000 - 5A00005100004A00004C0606390000470E0D300000410E0C2E00003906043700 - 004308063900004F0C0B4200005909084D00005C00005C00006300006B000270 - 0403740404740404740202780001820001860001860001840001860001840001 - 8400018400018200018200018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000014201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083C00003C0302350000 - 4D090A3C00004A0B0D35000045050A4100014F0004430000450C0B2E0000420E - 084300007A05068400008200048000028400017F01007604007803008400017B - 00045600043B00004B080F370000470C0A4300007608047E0000800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000018000018000018000017D00027603066F0105 - 6800026300005A00005500004F00004A00004B02043C00004C0B0D350000470D - 0E3300004007083800004104023B0000500B084200005C0C0B4E000063060560 - 00006E01037101017601027802017901017B01017D01017F0001820000840000 - 8400008200008400008200008200018200018200018200018200018200018200 - 0182000182000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018000013E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004002023800004207053C00004D090A37000045090A3800004500054A00 - 004F04063300003F0D07300000540A066E00008901058200048000028400017F - 01007604007803008400017B000451000047040939000048080D350000540A06 - 6A00008305018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000017901026903045F02035700005000004E00004800004900004701014100 - 004808083900004B0A0C39000049080A3A00004301024100004B06034200005A - 0B084E0000670A096100006F03027904057B03037D01017E00007E0000810000 - 8200008301018200008001008001008001008200008200008200018200018200 - 0182000182000182000182000182000182000182000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00014100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053D00003B02013800004905063C00004506 - 083600004202074200024E00034600004007062E00003D090346000077020385 - 00018200048000028400017F01007604007803008400017B00045500033E0000 - 46030A3700004207054600007305017F01008000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000017601025A00004C00014900004600004300 - 004200004200014202024201033C00004704073D00004D050B4300004F020949 - 00014700004500005506034F00006609086100007408077602017C02027F0100 - 8100008500008500008701008801008603008002007F02007F01007F01008001 - 0080010080010080010080000180000182000182000182000182000182000282 - 0002800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000014000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00003E00003A01 - 003D02004100004501023C00003E02033D00024300034C00014B000239000037 - 05003400004D0300720000870003840004820002840001800100760300780300 - 8600027B00045300004300033F00024001033900004D03006E00008102018000 - 0180010080000182000182000182000182000182000182000182000182000182 - 0001820001820001800001800001820001820000820000820000820000820001 - 8000018000017F00017D01017B01017901017802017602017601026B03044F00 - 004600004200004100004101013D01013D01013A01003900003C00013D000046 - 01044600004F0206500003550105510000580000590000640300670000730505 - 7703027F05057C00008000008300008601008801008902008902008603008002 - 007F01007F01007F01007F01007F010080010080010080000180000182000182 - 0001820001820001820002820002800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000018000018000018000018000014000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100023E00003A01003B00004501024100004001033A00003F000443 - 00034D00024800003D0403320000390500490000750001870002860002860002 - 8700028200017802017901028600027D00045400004000004303023B00003E04 - 0049000071000480000282000182010082000084000086000086000087000087 - 0000870001870001860001860001840002840002820002820001880202890200 - 8902008801008601008300008000007C00007F05057703027305056700006403 - 005900005800005100005000004800004A000442000042030539000138040434 - 02023302003603013B02014101014500004900004D00005500006D0204760201 - 7601027802017901017B01017D01017F00018000018000018200018200008200 - 0082000082000082000080010080000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000013F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00003F01013900004005033D00004A - 06073700004206073A00004400044B00004D02043500003C0A04300000510703 - 7000008900048700028700028700028400027901027901028700047D00045200 - 004505003B00004508043700005306046C000182010680000180020082010084 - 0100860000860000870000870000870001870001870001860001860002840002 - 8200028200018803008802008700008500008500008100007F01007C02027602 - 017408076100006609064F00005506034500004900004800004D000740000049 - 060B3600003E08083200003504023704023802013B0000410000480000500000 - 5500016300007801028000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000014201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073C - 00003C03023600004C08093C000048090B3500004404094100014E0003440000 - 430A092E0000410D074300007904058600018600028600028700028200027901 - 027901028700047D00045700003E00004A0A06370000480B0745000075030A7F - 00037F00017F0200800200800200820000840000860000860000860001860001 - 8600028400028200028000028000028000018301018201008100007E00007E00 - 007D01017B03037904056F0302610000670A094E00005A0A094200004B060341 - 00004301023B000047080A350000440A0B3200003E0605370000400202410000 - 4500004C00005400005C00006401036F02047B00028000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000013E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004002023800004308063C00004F0B0C370000460A0B - 3700004500054A0000500507330000410F09300000560C086D00008901058400 - 028400028600028200027801027901028600047D00045300004A08033A00004C - 0D093900005A0A096B00008301087D01017D02007D02007F0200800100820000 - 8200008400008400018400018400028200028000027F00027F00027D00027D01 - 017B01017B01017901017802017601027101016E01036000006306054E00005C - 0C0B420000500B083B0000410402390000400708320000440B0C330000450909 - 3900004501024900004D00005300005A00006300006A00027001057803067D00 - 0280000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000014201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083C00003C0302350000 - 4D090A3C00004A0B0D35000045050A4100014F0004430000450C0B2E0000420E - 084300007A05068400008200028000028400028000027801027901028600047D - 00045801003D00004C0C083900004B0C0847000078040B7E00037D01017B0200 - 7B02007D02007F01008001008200018200018200018200018200028000028000 - 027F00027F00047B00047700017402027604047404047004036B00026300005C - 00005C00004D00005909084200004F0C0B3900004308063700003906042D0000 - 3F0C0A320000490B0B3A00005005074D00005300005C00006400006C00027400 - 057900057C01057D000480000280000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018000013E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004002023800004207053C00004D090A37000045090A3800004500054A00 - 004F04063300003F0D07300000540A066E00008901058000027F00028200027F - 00027601027901028600047D00045300004B07023C00004B0B07390000580807 - 6C00008301087D01017B02007B02007D02007F01008001008200018200018200 - 018200018200028000027F00027F00027D00047900046F01036B03046C030669 - 04066502045D00005600004F00004E00005004054000004B0A09370000450A08 - 3400003A04033302003A09073000004509093C00005408094E00005F01056100 - 006A00007400037A00067F010782010682000480000080000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00014100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053D00003B02013800004905063C00004506 - 083600004202074200024E00034600004007062E00003D090346000077020383 - 00017F00027D00028000027D00027601027801028700047F0004590000420000 - 4906033A00004607034A00007501087F00047D01017D02007F01008001008000 - 018200018200018400018400028200028200048000047F00047F00047D000476 - 01046801046002035E00045A00025700015200004E0000490000490002400000 - 4707073800004108073400003D05043600003A05023600004407053C00005406 - 075200006605096B00037100027700027F000481000584000685000383000180 - 0000800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000014000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00003E00003A01 - 003D02004100004501023C00003E02033D00024300034C00014B000239000037 - 05003400004D03007200008500037F00027D00027F00027D0002740202780102 - 8700047F00045700004703004200004203003B00004F02006E00038100067F00 - 017F010080010082000082000184000184000184000184000284000282000480 - 00047F00047D00047D00047400056302065801045200014C00004A0000480000 - 4701024703044101014103033B00003E05043900003D04033800003B02013F02 - 004302014500005000015600006702046D00037803067F010681000583000584 - 0002830001830001810001800002800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000018000018000018000018000014000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100023E00003A01003B00004501024100004001033A00003F000443 - 00034D00024800003D04033200003905004900007500018400027D00027B0002 - 7F00027D00027601027901028700047F00045A00004501004404003F00004006 - 014C01006E00067E00047F000181000083000083000083000085000085000185 - 00018400048300038400067F00038103097B00057D03097203075700004B0000 - 4C00034700004900034100004100023E00013E02023A01003E05043900003F03 - 033B00004002024100004A00005000005600005D00006800027000027800037F - 00048200048400028400028200028200027F00017D01017D01017F0001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000013F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00003F01013900004005033D00004A - 06073700004206073A00004400044B00004D02043500003C0A04300000510703 - 7000008601047D00027B00027F00027D00027601027901028700047F00045700 - 004A06013C0000450804350000510A076700017E000683000385000285000285 - 000285000285000285000383000383000586050A79000082070B7100007A0409 - 6E00006A00065000004D01054100004A05083A00004405073800003B01023A01 - 003F06053700004507073A00004905064200004C00015A00006100006500016C - 00017200027900047F00048300038400028400028400028200017F00017B0101 - 7901017901017F00018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000014201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073C - 00003C03023600004C08093C000048090B3500004404094100014E0003440000 - 430A092E0000410D074300007904058300017F00027D00028000027F00027801 - 027B00028900048000045A0000400000490A06350000450E094000006C060B77 - 000381000383010283000383000383000381000381000580000581060A770002 - 800A0F67000076080C5F00006900035900005000023F00004C070A3900004809 - 0B3500004007063800003E05043700004808073C000052080845000056060758 - 00006A01047100037300037800047B0004800103830003850003840002840001 - 8200018001007D02007902007803007803007D01018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000013E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004002023800004308063C00004F0B0C370000460A0B - 3700004500054A0000500507330000410F09300000560C086D00008702057F00 - 027D00028200027F00027901027B00028900048000045500004A080337000046 - 0E092E00004F0F0B5B00007701067B00027F00017F00027F00027D00027B0002 - 790004780004740104780A0C620000710C0E5500006406075200005000004700 - 004A05083A00004A0B0D350000440B0A3200003C03023B00004808073E000055 - 0A084900006008085600006703037502057C01057C01057E0103800103800002 - 8200028200018200018200018001007F01007D02007902007803007902007F00 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000014201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083C00003C0302350000 - 4D090A3C00004A0B0D35000045050A4100014F0004430000450C0B2E0000420E - 084300007A05068400008000027F00028400028000027B00027D00028B000480 - 00045B01003D0000480B0732000040100A37000064060A6B0000760104790102 - 7901027801027601027402027002046D02046902055C0000670A0B4C00005D0A - 0C4500005004054300004701023A00004A090B370000480C0C3300004108073A - 00004404033F0000550A084A0000670A0B5900006F07086E00007B00027F0002 - 7F00027F00027F00017F00007F00007F00008000018001007F01007F01007F02 - 007D02007D02007D02007F000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018000013E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004002023800004207053C00004D090A37000045090A3800004500054A00 - 004F04063300003F0D07300000540A066E000089010582000280000284000282 - 00027B00027F00028D00048200045A00004B0904350000410D072B0000450B06 - 5300006A00027103057303037303037303037103036E04036A04056505055900 - 005A0404470000540A083C00004A0A093900004104023F000047040739000048 - 0A0A350000430A083400004003003F00005007034A0000670B0A5B0000760A09 - 6E00007B03047E00017F00017F00017E00017E00007E00007D00007D00007F01 - 007F01007F01007F010080020080020082010082010080010080000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00014100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053D00003B02013800004905063C00004506 - 083600004202074200024E00034600004007062E00003D090346000077020385 - 00018200028200028600028400027D00027F00028D00048200045F0302430100 - 4309042E0000340A033300005700036000006B00026B01006B01006902006701 - 026402025F03025B0402510000460000490603380000410A0731000039090535 - 02004101013D00004606063700004307073600004005033F00004601004A0000 - 5D08065C0000770B0A7200008005077E00007E00017E00017E00007C00007A00 - 007A00007B02007B02007B02007D02007F020080020084010086010087010086 - 0100820000800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000014000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00003E00003A01 - 003D02004100004501023C00003E02033D00024300034C00014B000239000037 - 05003400004D03007200008700038200028200018400028400027F0002800002 - 8900047F00046003024D06024001003B04002E00003902004900005900005A00 - 005A00005A00005900005500005100004E00004A00004700004502013D00003D - 04023601003805023303003704013E01004101003E00004202013F0000450200 - 4400004A00004E00005801006001007107067503037E06078001028101027F00 - 007E00007C01007F01008600018301027A02027703027901017B010180000182 - 0000860001870000870000860000820001800001820001820001820001820001 - 8400018400018400018400018200018200018200018200018000018000018200 - 0182000182000182000182000182000182000182000182000182000182000182 - 0001820001820001820001820001820001800001820001800001820001800001 - 8200018000018200018000018200018000018200018000018200017F00027901 - 027900048000048400028600028600028200018000017F00017F00017F000180 - 00018000018000017F00017F00018000018000018000018000014000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100023E00003A01003B00004501024100004001033A00003F000443 - 00034D00024800003D04033200003905004900007500018400028000017F0100 - 8200018200018200018000028000047800046603055100004800003E00004005 - 033900004100004700004A00014900004B00034500004700034100004100023E - 00013F01013B00003E02023A00004002023C00003F01013D00004006003E0500 - 3F01004000004700005100005A03006405026904026F04017203017602017901 - 017B01017D01017F0100810300780000860A047C00009F00049E040970000071 - 060878050874000085030A8100018500068B050B7F0001820004820002820002 - 8400028600028600028700028900028900028900028900028700028600028600 - 0284000282000282000284000284000284000284000286000286000287000287 - 0002870002870002860002860002840002840002840002840002840002820002 - 8400028200028400028200028400028200028904077700008F0A0D7B00008300 - 017E00008400027A000374080E62000074000090030E8D000296020A84000088 - 070A7901017901017D01018000018200018000017D00027B00027F0001800001 - 8000018000013F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00003F01013900004005033D00004A - 06073700004206073A00004400044B00004D02043500003C0A04300000510703 - 7000008601037F00017D02008001008200008400018000017D00047401046601 - 035B03034500004C06063A00004305053700004001034200024701083B000047 - 040B3700004205093600003A01043900003E0405360000450707390000460405 - 3E00004300004204004104004502004900005201005E02006804007104027602 - 017901017D01017D01017F00017F00017F00017F01007F03008007007B060080 - 0000A00105830000720E0E4D0000530000640307690308740D12620001620003 - 66050966070B6103046104036303036503036703036802036A02036A02036C01 - 036A020368020367030365030363030361040361040363030365030365030365 - 0303670303670303670303670303680203670303670303650303650303650303 - 6503036503036703036703036703036703036703036703036703036703036400 - 006300006D09095D00006A06066000006B07077113145300045F020B921C2777 - 00008A00019000048400017900007802017802017D0101800001840001820001 - 7D00027B00027F00018000018000018000014201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073C - 00003C03023600004C08093C000048090B3500004404094100014E0003440000 - 430A092E0000410D074300007904058300007F00017D02008001008200008400 - 018000017D00047401046904065100005305063E00004B0B0B3700004004043F - 00004700054100004E060C3C00004B080D3900004206073800003F0304370000 - 4509093700004909093A00004504033F00004802004B02005101005802006103 - 006804007104027905047B01017F00018000018200018200018200018000017F - 01007C04008211076300006600008A04048C1615FFEDE7FFFDF5FFFCF7FFFBF8 - FFEBE8FFFBF8FFF4F0FFFDF8FFFDF8FFFDF7FFFFF8FFFFF8FFFFF8FFFEF8FFFE - F8FFFEF8FFFDF8FFFDF8FFFDF8FFFDF8FFFEF8FFFEF8FFFEF8FFFFF8FFFFF8FF - FFF8FFFEF8FFFEF8FFFEF8FFFEF8FFFEF8FFFEF8FFFEF8FFFEF8FFFEF8FFFEF8 - FFFEF8FFFEF8FFFEF8FFFEF8FFFEF8FFFEF8FFFDF8FFFCF8FFFCF8FFFCF8FFFC - F8FFFCF8FFFCF8FFFCF8FFFCF8FFFCF8FFF8F4FFF8F4FFFCF8FFFCF8FFF6F2FF - E8E5FFF9F9FFECF2FFDDE5850E178B040E8600038504097D0204760201780201 - 7F00018400018700018400017F00027D00027F00018000018000018000013E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004002023800004308063C00004F0B0C370000460A0B - 3700004500054A0000500507330000410F09300000560C086D00008702047F00 - 017D02008001008200008400018000017D00047401046500025D050545000052 - 0C0C3900004709093500004303034300014E040A40000051090F3C00004B080B - 3900004001033C00004507073700004C0C0C3A00004A09083C00004A00005301 - 005A02005F03006603006D04017504027A02027F030380000184000184000186 - 00018600018400018400018001007100007D0902740D04740A037F0303610000 - FFF5EEFFFFF7FFFFF6FFFDF6FBF5EEFFFFF9FFFFF9FBFFF8F8FFF9E7F5EAF3FF - FAF2FFFAF3FFFBF5FFFAF7FFFBF7FFFAF9FFFBFAFFFAFAFFFBF9FFFAF7FFFBF7 - FFFAF5FFFBF3FFFAF3FFFBF3FFFAF5FFFBF5FFFAF5FFFBF5FFFAF7FFFBF7FFFA - F7FFFBF7FFFAF7FFFBF7FFFAF7FFFBF7FFFAF5FFFBF5FFFAF5FFFBF7FFFAFCFF - FBFEFFFAFEFFFBFEFFFAFEFFFBFEFFFAFEFFFBFEFFFAFCFDF9FFFFFBFFFFFCFF - FFFBF8F9F5F7F9F3FFFFFCFFFFFBFFFDFBFFF9FBFFF5F9600000770005810106 - 7F01067E06077602017901018200018700018900018700018000027F00028000 - 018000018000018000014201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083C00003C0302350000 - 4D090A3C00004A0B0D35000045050A4100014F0004430000450C0B2E0000420E - 084300007A05068200007F00017D02008001008200008400018000017D000474 - 01046A05075000005507083E00004D0D0D3700004105053E0000470005400000 - 51070B3E00004F0A0D3C00004805083F00004402033A00004D090A3C0000510B - 0B3E00004E06064E00006203006C03007003017504027A02027E020282000183 - 000087000187000187000187000187000186000186000186000097100E7E0000 - 7502006B00007D00006D0909FFFDF7FFFFF8FCFFF8FBFFFBFAFFFBF1FCF4F0FF - F7E5F9EDEDFFF9F1FFFBF3FFFEF7FFFEF9FEFFF9FFFEFAFEFFFAFFFEFCFEFFFC - FEFEFCFEFFFCFEFEFAFEFFFAFFFEF9FEFFF7FFFEF7FFFFF7FFFEF9FEFFFAFFFE - FAFEFFFAFFFEF9FEFFF9FFFEF9FEFFF9FFFEF9FEFFF9FFFEF9FEFFF9FFFEFAFE - FFFAFFFEFAFEFFF9FFFEF3FFFFF2FFFEF2FFFFF2FFFEF2FFFFF2FFFEF2FFFFF2 - FFFEF3FFFFEBF9F7EFFDFCF3FFFFECFAF9F3FFFFF3FFFFDFE7E6F5F4F0FFFCFA - FFF8F95500046F01077F070B6A00006F00007802017D01018600018900018B00 - 018900018200027F00028000018000018000018000013E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004002023800004207053C00004D090A37000045090A3800004500054A00 - 004F04063300003F0D07300000540A066E00008702047F00017D020080010082 - 00008400018000017D00047401046500025C0404450000500A0A390000460808 - 3500004103033F00004904073E00004D080B3C00004C08093F00004701024500 - 004D050542000055090A4500005A0A094E00005F03026F03027903027A02027E - 02028101028400018600008800008B00018B0001890001870001870001860001 - 8600018700019102047C00008408087A0203850107730E10FFF6F2F8F9F0F6FA - F4FBFFFCF0F6F1F1F7F2FBFFFCFBFFFBF3FAF5F9FEFCFFFEFFFFFDFFFFFDFFFF - FDFFFFFDFFFFFCFFFFFCFFFFFCFFFFFCFFFFFCFFFFFCFFFFFDFFFFFDFFFFFDFF - FFFDFFFFFDFFFFFDFFFFFCFFFFFCFFFFFDFFFFFDFFFFFDFFFFFDFFFFFDFFFFFD - FFFFFDFFFFFDFFFFFDFFFFFDFFFFFCFFFFFCFFFFFDFFFDFEFFFAFFFFFBFEFFFA - FFFFFBFEFFFAFFFFFBFEFFFAFFFFFBFEFFEEF3F6F4F7FBFAFFFFFBFEFFFAFFFF - F8FBFFFAFFFFF8FFFCFFFFFBFFF7F54B00026300027D080B740000850D0E7B01 - 017F00018700018D00018D00018900018000027F000280000180000180000180 - 00014100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053D00003B02013800004905063C00004506 - 083600004202074200024E00034600004007062E00003D090346000077020383 - 00007F00017D02008001008200008400018000017D0004740104690406530000 - 5002033F00004808083700003F03033C00003F01013A00004606063900004806 - 073D00004B02044800004C00004C00005804065100006407085A000067060869 - 01027901028000018200018400018600018700018A00028C00028B00018B0001 - 8900018700018400018200018200018600018B00008B00008405067F04067B00 - 00690005FFFAF8FFFFFBFFFFFCFCF0F03020211400011C04061B00001E000221 - 02051B01071901091B00091B00091B00091D00091D00091D00091D00091D0009 - 1D00091B00091B00091B00091B00091B00091D00091D00091D00091B00091B00 - 091901091901091901091901091901091901091B00091B00091D00091D00091D - 00091D00091B00091D00091B00091D00091B00091D00091B00091B0007220710 - 2A0D161B00091700031500033C1F28F8E9EDF4FBF6FDFDF7FFF9F74F090A6D07 - 0C7200007600017700007F00018200018900018D00018D00018700017F00027D - 00027F00018000018000018000014000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00003E00003A01 - 003D02004100004501023C00003E02033D00024300034C00014B000239000037 - 05003400004D03007200008500027F00017D0200800100820000840001800001 - 7D00047401046702045800004900004802023F00003F01013900003B02013901 - 003A02013800004002023E00004502014800004E00005100005800005B000066 - 01036800007003057002047A03047E00008200008400008500008700018A0002 - 8B00038C01048900018700018600018400018000017F00017F00018200018A00 - 009106097000007E060A7F00066A030AFFFBFBFFFDFAFFF7F7FFFDFE13000020 - 01042400012700003000042900002200011E00011E00011E00011E00011E0001 - 1E00011E00011E00011E00011E00011E00011E00011E00011E00011E00012000 - 012000012000011E00011C00011C00011B00011B00011B00011B00011C00011C - 00011E0001200001200001220001230001230001250001230001250001230001 - 250001230001250001270005250001230001390C15230001250001FFFBFFFAFE - F9FEFEF8FFFBF94C030570060C6B0000890B107E00008000018600018B00018F - 00018D00018600017D00027901027F00018000018000018000014000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100023E00003A01003B00004501024100004001033A00003F000443 - 00034D00024800003D04033200003905004900007500018400017F00017D0200 - 8001008200008400018000017D00047401046803055500004D00004300004404 - 043B00003C00003A01003704013303003904013700004202014200004C000052 - 00006103046703036E01037401047900047E0103800103830003840001860001 - 8600018600018600018700018700018600018600018400018000017F00017D01 - 017B01017B01017D01018100007D01016F03026A02037501085D0308FFFDFBFB - FFFCFFFFFEFFFEFF1E0B0E1C01052F060D2900023D09102E00022E050A1E0000 - 39161A2200032A070B1F00002D0A0E2200033C191D1E00002D0A0E2704082C09 - 0D1E000027040823000231090E2A0207310C101E00002D0C101E00013112151B - 00002B0C0F1B00002B0A0E1F00022F0C102400032D050A25000132060C250000 - 43151B25000035070D2500003F111725000032040A2C000634060C2700013608 - 0E27000135070DFFFBFCFFFEFBFFFFFBFFFAF957060971000680000483000385 - 00038400018700018D00018D00018B00018400017801027601027D0101800001 - 8000018000013F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00003F01013900004005033D00004A - 06073700004206073A00004400044B00004D02043500003C0A04300000510703 - 7000008601037F00017D02008001008200008400018000017D00047401046601 - 035B03034500004C06063A00004305053700003C030236030038080432000040 - 05033C00005005034F00005E02016802036F01037700037D0002820002870003 - 8A00038A00038600018600018600018400018400018400018400018400018200 - 018000017D01017B01017901017802017802017901017F00007B01016D030268 - 0203710108590408FFFEFBF8FFFCF6FBF9FCFAFA100305130000200004230000 - 2F01072700002300002501012000001F00002604042200002402021E00001E00 - 002A08083715151E00001E00002301012000002200002300002300002200002F - 0B0B1E00001C00001B00002C0E0D1C00002608071C00001E0000200000220000 - 2300002B0304280001230000230000391112240000320A0B2300002300002400 - 00230000270000230000290102230000270000FFF8F7FFFEFAFFFEFBFFF8F95E - 04097700068400048600038800038600018700018B00018D0001890001820001 - 7601027402027D01018000018000018000014201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073C - 00003C03023600004C08093C000048090B3500004404094100014E0003440000 - 430A092E0000410D074300007904058300007F00017D02008001008200008400 - 018000017D00047401046904065100005305063E00004B0B0B37000040040439 - 00003E07043400004508043A00005107054900006509086703036F0103770001 - 7D00028400028700028B00019000028E00028700018400018400018200018200 - 018200018000018000017F00017D01017B01017901017901017802017802017B - 01018500008400017402026F01037900085D0308FFFDFBFAFFFCFAFFFEFDFFFE - 140E0F110305210B0D1B00012E0D112100002B070729060334110E200000300F - 0C2403001D00002809063314112203002706031E000045221F20000039131122 - 00003A13112400003812102805022E0D0A1C0000270A061900002005011B0000 - 341512270603401D1A22000038110F220000300F0C1B00002E110D1B00002A0D - 091C000030130F1B0000270A06230602290C081D00002B0E0A1D0000290C08FF - FDF9FFFDFAFFFCFBFFF7F96303097A0006870004860003880003860001860001 - 8900018B00018700018000017601027402027D01018000018000018000013E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004002023800004308063C00004F0B0C370000460A0B - 3700004500054A0000500507330000410F09300000560C086D00008702047F00 - 017D02008001008200008400018000017D00047401046500025D050545000052 - 0C0C3900004709093500004104023E00004A0704400000580B084A0000680C0B - 6200007408077601027D00028200028600018900018D00018F00018D00018600 - 018400018200018200018000018000017F00017F00017D01017D01017B01017B - 01017901017901017802017F00018A00008B00007B0101770001800006660207 - FFFCF9FFFFFBFAFBF7FCFAF90C04040C00001601031500001F04071900001B00 - 002A0D081B00001900001E05011A02001500001500001500009A847E8A716DD9 - C1BBD9BEBAFFFDF8FFFDF91C00001E00002D0D081C0000190000170000150000 - 1D09049E8C85FFFEF998857E1903001700001B000032140F2B0A071E00002003 - 001900002106021E04001C01001900001E03002B110B1A00001900001D020019 - 00001F04001900001D0200FFFAF5FFFDFAFFFCFBFFF6F9650309780006860004 - 8500038500038200018400018700018900018700018000017801027601027D01 - 018000018000018000014201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083C00003C0302350000 - 4D090A3C00004A0B0D35000045050A4100014F0004430000450C0B2E0000420E - 084300007A05068200007F00017D02008001008200008400018000017D000474 - 01046A05075000005507083E00004D0D0D3700004105053F00004D00004C0000 - 610A08520000710F0F610000780A0A7500017B00028000018200018400018700 - 018700008900008700008400018200018200018200018000018000017F00017F - 00017F00017F00017D01017D01017D01017D01017D0101840001910000920000 - 8400017F00018800066F0107FFFAF9FFFFFBFFFFFCFFFEFC1F0D0C180302250B - 0B1B00002D0E0F1C00002613100E00000C0000110700180F0B090100A39D98CE - C8C1FFFFFBFFFBF4FFFFFBCBC3BCB8ADA9FFFFF9BFB0AD1F0F09271411120000 - 251613100400180D099A948DFFFDF8F3F1E9FFFEF9FFFFF9FFFAF58B837C1F13 - 0F0E00001502001E0803280C0B1B00002D0F0E1B0000381A191B00002A0C0B1B - 0000260807230602290B0A1D00002B0D0C1D0000290B0AFFFDFBFFFDFAFFFCFB - FFF7F96204097500067F00047E00038001037D01017F00018600018700018700 - 018200017901027801027F00018000018000018000013E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004002023800004207053C00004D090A37000045090A3800004500054A00 - 004F04063300003F0D07300000540A066E00008702047F00017D020080010082 - 00008400018000017D00047401046500025C0404450000500A0A390000460808 - 350000480202550000690304600000790C0E690000800B0C7300007E01038001 - 0281010282000182000182000082000081000081000082000182000182000182 - 00018200018000018000017F0001800001800001800001800001800001800001 - 8000018600008E00008D00007F01007C00008700056F0105FFFBF8FFFFF9FFF9 - F6FFF7F61803021700001E00001C00002604051B00001200000F0200160A0809 - 0000918A87FAF5F2FFFFFCAFACA87A7773787571787370FFFFFCD9D0CD8B7F7D - 1306040E00001000001001001B0E0C090000D6CFCCBAB7B3878682848581F7F8 - F40C0B0784817DC4BDBAFFFFFCC1B4B2A492911300001A00001C00001E00001E - 00001C00001C00002000012303041D00001C00002000011C00002202031C0000 - 200001FFF7F7FFFDFAFFFDFBFFF8F95C05096E00067900047700037902037802 - 017B01018200018700018700018600017D00027B00027F000180000180000180 - 00014100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053D00003B02013800004905063C00004506 - 083600004202074200024E00034600004007062E00003D090346000077020383 - 00007F00017D02008001008200008400018000017D0004740104690406530000 - 5002033F00004808083700003F03034900006801047100007D06077300008508 - 0A7A00008404057E00008301028101028002017D02007D02007A01007801007A - 0100800001840001840001820001820001820001820001800001820001820001 - 8200018200018400018400018600018400008100007B03006F04006E03007C01 - 05660305FFFCF8FFFFF9FFFFFBFFFEFB240D0B1E02012A0B0A220000340E0E21 - 0000290C0F291216715C5FFFFCFFFFF7FAFFFDFF8C7F81180B0D180B0D241719 - 1507091302051C090C1200001600031B02062E1317170000967D81FFFBFE8F7E - 81140709090000867E7FFFFEFF090000180B0D120104180306957E82FFF9FDFF - F4F991717629090E1B00001B000046262B1B000023030823030826060B230308 - 29090E1D00022B0B101D000229090EFFFCFEFFFEFBFFFEFBFFF9F95506096701 - 067201047100037303037203017602018000018600018900018700018200027F - 00028000018000018000018000014000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00003E00003A01 - 003D02003F00004501023C00004001033D00004100014700014701023900003B - 04013900004F02006C00007E01037F00017F01008001008200008000017F0001 - 7901027201046802035D00005000005101004B00004B00004700005600007403 - 068203057D00008100037C00008300038000008301028301028101028002017D - 02007B0200780100770200780100800001820001840001820001820001820001 - 8200018200018200018200018200018400018400018400018600018200007C01 - 007404006B05006C03007A0105640305FFFDF8FFFFF9FFFBF6FFFAF61A03011B - 00002400012000002804041C0000190002FFEDF19D868A917A7EFFF6F9190407 - 120000120000190407120000160003170004150000150000250A0E1700009C80 - 86FFEEF4D6BCC2998287847075FFF1F59E8F93897B7DFFFCFF1406080E000012 - 000020090D1500001A00039C7E83DFBFC4FFF7FCE3C2C99A7C8119000125070C - 1900011900001B00031900001F00051B00002100071B0000210006FFF7FBFFFE - FBFFFEFBFFF9F95506096801067201047100037103037003017403017F000186 - 00018900018900018400018000017F00017F00017F00017F00014000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100023E00003C00003B00004202013F00004302013E00004101013E - 00004002023F02004106043D00004802024E00006302046F01037D0002820001 - 8200017F00017D01017901017403017002026B01006500006100006300006A03 - 016D06046F03026E00007B000280000180000180000180000180000180000180 - 00018000018000018000017F00017F00017F00017D01017F0001800001800001 - 8200018000018000018000018000018000018000018000018000018200018200 - 018200018200018000017C0100790200760201770001850006690207FFFCF9FD - FFFBFEFFFAFFFFFC260E0E1C00002E060B300B0D1C0000170201FFFBFC938384 - 180607D6C4C598838513000021090B1F04072B101317000024090C22070A2409 - 0C150000331B1D887274FFF2F59C8B8E958487C0AFB2FFFCFF7D6F712413168D - 7D7EFFFCFF857576322021100000210F101402031F0B0A19040323080B1B0001 - 927479FFFAFDFFFBFF8D727523080C190001290E1217000034161B1B00002C0C - 111C00003E1A20FFF2F5FFFEFBFFFEFBFFF8F95C05096F000679000477000377 - 02037203017403007D02008200008700008700008600008000017A0000790101 - 7901017A02023F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00003F01013B000040050338000047 - 07063C00004706053C00003D02003A0100400705390000490807430000580507 - 5600006A03067D00028400018200017F00017B01017602017203017003016E01 - 006B00006B00006F00007802017B03037D01017C000080000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000017F00017E00007B02007B00027E - 00038800066B0108FFFCF9FAFFFBF3F9F4FFFFFC1500001E0000340C111E0000 - 170000D7C5C49285830B00009A8B89FFFCFB1300001F07071900001900001F00 - 011900001A00001700002A10109D8585FFF2F1D1BFBE180B0D73686AFFF7F992 - 87890B0000887B7DFFFDFEFFFDFEFFF1F2FFFDFEF1E2E09182800C00000D0000 - 271B171000001800022005081500001D0507957D7FA48E90FFFCFEC5AFB1907A - 7C2810121700001900001F00032605091F0000FFFAFDFFFEFBFFFEFBFFF7FB5E - 04097300067F00047C00037A02027403017603007D0200820100870000870000 - 8400008001007B00007A00007D01017E02024201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073C - 00003E0202360000470A083900004D0A093A00004606053A00003D0402360000 - 470C0A3A0000540A0A49000060070A6600027D00028600018400017F00017B01 - 017802017403017203017102006F00006F00007300007A02027E04047E02027D - 0000800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018000018000018000018000017F - 00017E00007B02007B00027E00038800066B0108FFFCF9FAFFFBFBFFFCFFFEFA - 1C0406300D112800052300043A2020FFEEED0F00001D0E0CC2B3B19D8B8A220D - 0C1500002A1010200606280C0C2004042206062B1111C2AAAAFFFBFA9B86850E - 0000877F80C3BEBF251F20827C7DD5CDCEFFFEFFFFF7F7FBF1F1FFFEFEFFFEFE - FFFEFCFFF6F4FFFEFCBFB3B1877C780C00001702041B05071500011200001B06 - 081200002D181A988385CCB7B9FFFCFED0B5B81C00023011141C0000351216FF - F5F8FFFEFBFFFEFBFFF8FB5E04097500068000047E00037E0202780201790200 - 7F01008400008700018700018400018200018800048900048800038700023E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004002023A00004308063700004C0C0B3C00004B0A09 - 3900003E03013800004209073500004E0D0C4200005C090B5300006A03067F00 - 028600018400018000017D010179010176020174030174030172010073000077 - 01007C0202800404800102800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000017F00017E00007B02007B00027E00038800066B0108 - FFFCF9FAFFFBF9FFFAF7F4F01C04062000012200002200038A70709B87861A08 - 07190706FFF5F4998584150000190101210707170000190000170000907676FF - F2F2A89392120000200C0B0C00000500000202027D7B7BF6F4F4FDF8F9F2EDEE - FFFFFEFFFFFEFFFCFBF2EDECFFF9F6FFFBF8FFFFFCFFF9F6FFFFFBFFFFFB9484 - 851000002210110E000019090A1404050E00000F0000160405150002D0B8BAD5 - BABD1B00001C00001C0000FFFCFEFFFEFBFFFEFBFFF9F95E0409750006840004 - 8300038100037D01017D02008001008400008700018600018000018000018A01 - 058D00048C00038B00024201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083C00003E0202350000 - 480B093900004F0C0B3A00004707063A00003D0402340000470C0A3A0000550B - 0B49000060070A6500017F00028600018400018200017F00017B010179010178 - 02017802017802017800007B01017E0202810203810102800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000018000018000018000017F00017E00007B0200 - 7B00027E00038800066B0108FFFCF9FAFFFBF9FFFAFFFFFC20080A1E0000370F - 14240105FEE4E49D8988180403120000FFFDFC8A7272371F1F170000290F0F17 - 00002E1414D8BEBEFFFCFC8B76751803021200001F0D0C1C100E9A9898EFF1F1 - FDFFFFFDFFFFFFFFFFFFFFFFEFEDECFDFBFAFFFCFB888483DCD7D4FFFFFCFFFC - F9FFFFFCFFFFFBFDF4F0F9EDEDFFFEFEB9ADAD867C7C180E0E1107071C10100C - 0000100001100000978183C7AFB133161927080B27060AFFFCFEFFFFFBFFFFFB - FFF9F95C05097700068700048600038700038000018000018400018600018600 - 028200027B00027B00028200028500018600028700033E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004002023A00004207053700004A0A093C00004A09083A00003E03013800 - 004007053500004B0A094200005906085300006902057F000286000186000182 - 00017F00017D01017B01017901017901017901017B01017D01017F0001800001 - 8200018200018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000017F00017E00007B02007B00027E00038800066B0108FFFCF9FAFFFBF6FC - F7FFFFFB1500001E00002A02071E0000FFFCFC897574200B0A1C0404D7BFBF99 - 7F7F170000240A0A170000967C7CFFFCFC856D6D130000210D0C170302100000 - 948583BCB0AEF7F5F5FBFFFFFBFFFFFBFFFFF7F9F9F1F3F39C9D9B7F7D7CFFFF - FE110D0C040100050000CCC5C2FFFFFCFFF8F4FFFFFBFFFEFEFFF7F7FFFFFEFF - FFFEF5F0EF7F77779189890900001D0F100E0000120000FFFCFE170000190000 - 240508F7E2E1FEFFFBFFFFFBFFF9F95C05097800068900048A00038A00038400 - 018200018400018400018200027F00027601027402027A02067A020378000375 - 00004100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053D00003D01013800004407053900004A07 - 063B00004404033B00003B02003600004207053A00004F05054A00005C030666 - 00027F00028600018600018200018000017F00017D01017B01017A00007D0101 - 7D01017F00017F00008100008300008400018200018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000017F00017E00007B02007B00027E00038800 - 066B0108FFFCF9FAFFFBFBFFFCFFFFFC1F07092C090D220000280509FFF1F190 - 7B7A240C0C170000907676FFFCFC2F1515170000FFF6F6DFC7C7200808130000 - 220D0C120000210D0C9C8A89FFFEFCFFF6F4FEFCFCFDFFFFFDFFFFFBFDFDC5C7 - C70000000D0E0C807E7DFAF6F5070201140D0A1B120F160A08998C8AFFF3F0FF - FCF8FEF6F6FFFFFEFBF7F6FFFBFAFFFFFEFFFEFDFFFEFDFFFEFE7C70701D0F10 - 8A7879FFFCFE1700001F02053A1B1EFFFDFCFCFFFBFFFFFBFFFAF95C05097800 - 068900048C00038C00038400028200028200028200027F00047900047002046B - 03046C07096806066300025F00004000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00003E00003C00 - 003D02003C00004202014100004302013F00003C01003900003C03013A000043 - 02014600005200015700016700037D0002860001840001820001800001800001 - 7F00017D01017D00007E00007F00018000018000008200008400008300008200 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000017F00017E00 - 007B02007B00027E00038800066B0108FFFCF9FAFFFBF0F6F1FFFFFC1500001E - 00002700041E00009A8080D0BBBA170000220606200404FFEDEDA187871E0404 - 977F7F1300001300001C0807120000968281FFFDFC837170796A68FFFEFCFFFE - FFF8F8F8FEFEFE8A8A8A0000008E8E8E020000040000FFFFFE0D03030C00000C - 00001200001200009D8684FFFEFBFFFAFAFFFFFEFEFCFBFCFAF9FFFFFEFFFFFE - F3EEEDFFFEFEFFFEFEFEF0F1FFFDFED0BABC1800021900001B0000FFFCFBFAFF - FBFFFFFBFFFAF95A05097800068900058A00038A00038400028000028000027D - 00027900047201046902056204055805045404035202015101004000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100023E00003C00003B00004003013E00004502013F00004101003C - 01003B02003700003D02004000004C02024D00005800026801047B0002840001 - 8400018200018000018000018000017F00018000018000018000018200018200 - 0184000186000184000182000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000017F00017E00007B02007B00027E00038800066B0108FFFCF9FA - FFFBF9FFFAFFFFFC250D0F1E0000340C111E00002D1313FFFDFC2105051B0000 - 270B0B1F0303FFF6F69B8181240C0C130000230E0D120000FFF1F0FFF9F8A795 - 94100000251312FFF7F5FFFEFF8D8788040000140F10B6B1B2FFFEFF807B7A07 - 0000FFFCFC0F0102210F0E1300002F15151900002F100FFFFDFB918787777574 - C5C3C2FCFAF9FFFFFEFFFFFEFFFEFDFFFEFEFFFEFEFFF3F4FFFDFE8973753119 - 1B19000026070AFFFCFBFAFFFCFFFFFBFFFAF95A050977000686000487000286 - 00048001037C01038005097901057605096700015D00024F00004C0202450201 - 4300004000003F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00003F01013B000040050338000047 - 07063C00004706053C00003D02003A01003D0402350000490807430000540103 - 5300006A03067901028200018200018200018000018000018000018000018000 - 0180000182000182000184000184000186000184000182000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000017F00017E00007B02007B00027E - 00038800066B0108FFFCF9FAFFFBFBFFFCFDFAF61800021E00002E060B1E0000 - 1B0101907B7AE2C6C61C0000190000170000907676FFFCFC846F6E220E0D1200 - 009A86859E8C8B100000100000120000170302998A880B00000700008D8586FF - FEFFFFFEFFFFFAFB948C8C0B0101FFFDFE1000001803021700002E0E0F200000 - 240000997B7ABEB2B21915140400000E0A097F7B7AF0ECEBFFFFFEFEF6F6FFF5 - F5A89A9B816F701701031700001900002C0D10FFF9F8FBFFFBFFFFF9FFFBF859 - 060875000684000583000381000577000179070770000078090D630000660509 - 5100004B00003E00003D00003F00004303024201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073C - 00003E0202360000470A083900004D0A093A00004606053A00003D0402330000 - 4409073A0000540A0A4900005C03066500027801028000018000018000018000 - 0180000180000180000182000182000182000182000184000184000184000184 - 0001820001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018000018000018000018000017F - 00017E00007B02007B00027E00038800066B0108FFFCF9FAFFFBFBFFFCFEFBF7 - 1800022100022800052502061B01011E0908D2B8B8DBBFBF270B0B170000331B - 1B897473FFFDFCD2BEBD210D0C1000001804038F7B7AFFFCFB8D7877200B0A12 - 00009B8E90CCC4C5FFFAFBFFFEFFF3EBECFFFAFB9187870B0000FFFDFE120000 - 1901011B00002D080A2800022800002C0808FFFDFE847C7C1914130500001813 - 12CDC5C5FFFEFE8B81811608090E000029141617010323080B1B0001250609FF - FDFCFDFFFBFFFFF9FFFBF85906087200078000067D00047A0206710406630000 - 70090C5B000068090D4F00005304074500004B02044701024500004200003E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004002023A00004308063700004C0C0B3C00004B0A09 - 3900003E03013800003F06043500004E0D0C4200005906085000006A05077601 - 027F00017F00017F00017F000180000180000180000182000182000182000182 - 0001840001840001840001820001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000017F00017E00007B02007B00027E00038800066B0108 - FFFCF9FAFFFBFAFFFBFFFFFC1E0608250206230000230004280E0E1300001900 - 00DAC0C0FFFAFA937B7B1300002E1A19120000907C7BFFFDFCCEBCBBD5C1C0FF - FDFC927D7CFFF8F8230B0B8F7A79F3E6E8FFFEFFFFFEFFFBF5F6FFFEFFFFFEFF - 756D6D160C0CFFFCFD1604051F07071E000027020428000037080A2200009781 - 83C4B8B8140808090000110707FFFCFC7F73730C00001F0F101000001B050715 - 00001C00021B00001C0000FFFAF9FEFFFAFFFFF9FFFAF85707086F01077A0006 - 760104710406620000650908500000630A0D4C000057080B3F00004502054400 - 004700004700004A01034201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083C00003E0202350000 - 480B093900004F0C0B3A00004707063A00003D0402330000450A083A0000560C - 0C4900005D04076500027601027D01017D01017D01017D01017F000180000180 - 0001800001800001820001820001820001820001820001820001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000018000018000018000017F00017E00007B0200 - 7B00027E00038800066B0108FFFCF9FAFFFBF0F6F1FFFFFC1A02041F00002200 - 001E0000260C0C1500001F07071B0101917979FFFDFCDEC9C88B777628141312 - 00001C0A098B79788B7776170201281010FFEDED2C1010917C7BFFFDFFFFFEFF - FFFEFFFFFEFFFAF8F8F2F0F07D79780B0605FDF3F31B0B0C1A05041900002702 - 04230000330708260000190103FFFDFE1000000E0000958586FFFDFE16060718 - 08091B090A1200001901031700002D0E112D0C102C0B0FFFFCFCFFFFFAFFFFF9 - FFF9F75406076A00067400056C01036705055A04044B000057090A4500005508 - 0B3E000046060B3D00004801044B00034900014600003E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004002023A00004207053700004A0A093C00004A09083A00003E03013900 - 003E05033500004C0B0A4200005704065100006904067402027B01017B01017B - 01017D01017D01017F0001800001800001800001820001820001820001820001 - 8200018200018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000017F00017E00007B02007B00027E00038800066B0108FFFCF9FAFFFBF5FB - F6FFFFFC1600001E00002A02071E00001C02021601001500001B030313000012 - 0000988483D2C0BFFFEEEDD1BFBE1000001200002C1716150000170000FFFCFC - 1E0000897171FFFEFFF8F8F8FFFFFFFDFFFFF3F5F5FDFFFF979896020000FFFA - F9160A0A1200001700002A0A0B2200002700002600001A00008F797B97818312 - 00008F7A7C8671732D181A1200001601031F090B250A0D1900001B00001C0000 - 200001FFFCFCFFFFFAFFFFF9FFF9F75305066500046D00036400005B04024B00 - 004D08053C00004C08093C00004807093400003D04073D000043000045000148 - 01044100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053D00003D01013800004407053900004A07 - 063B00004404033B00003C03013500004106043B00005006064900005B020564 - 01037202027901017901017B01017D01017D01017F00017F0001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000017F00017E00007B02007B00027E00038800 - 066B0108FFFCF9FAFFFBFBFFFCFFFFFC1B03052603072800052100021D030312 - 000025100F130000341F1E150100100000DCCDCBFFFEFCD7C8C6877574A69291 - 130000150000391D1DFFFBFC240405A89090FFFEFFFAFFFEF6FBFAFAFFFFFAFF - FFECF4F36C7370050A08FFFFFE0700001306041702012509091F000026000022 - 00002D0E111B0003FFFCFE150000DAC2C48973751600022C1618130000190103 - 1800002104072F101328070B260307FFFAFAFFFEFAFFFFF9FFF8F65204056100 - 026600005B00005301004502003B00004407053700004506083500003A040935 - 00033F05063F03043D01023900004000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00003E00013C00 - 003D02003C00004202013F00004302013F00003E01003C00003C01003B000045 - 04034500004D00005000006104056F02047602017801027901017B01017D0101 - 7D01017F00018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000017E00 - 007D02007B00027E00038800066B0108FFFDF9FAFFFBFBFFFCF5F2EE21090B2A - 070B220000210000230909130000170000260C0C1500001702011D0908837170 - FFFEFCFFF1EFFFFEFCFFEEEDFFFDFCFFFDFCFFF0F3FFFCFC230407846E70FAF6 - F5FAFFFFFAFFFFF2FAF9F7FFFEF8FFFF818885000100FFFFFE070000190C0A1A - 06051700001C00002904062000001B0000170000D2BABCA08A8CC8B2B4250F11 - 1300001500001700011F04071900001C00001E00011C00001C0000FFFCFCFFFE - FAFFFFF9FFF8F74604055300015900015000004B00004101003E04003B00003F - 03033B00003E03073700033702053600003800003A00013D03044000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100024000013E00013D00004201033E00004201033E000041000240 - 00003E00013D00004201033E0000430003410000460002500000670003700000 - 7300037601027A02037C01037E01038001038000018000018000018000018001 - 008001007F01007F010080000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000017F00008001007D00027F00038A00066B0108FFFDF9FA - FFFBFBFFFCFFFFFC230B0D23000430070C2400012C0D0E1C00002E0F0E1E0000 - 200001270B0B2208081300001F0D0E1202031D0D0E1303041303041F0D0E1B06 - 091300003922267D6D6EFFFFFEFBFFFEF8FDFBF9FEFCFBFFFEF9FCFA7A7B790B - 0706FFFEFE11050519090A18020426090C2000032C070B240203270B0B150000 - 857170FFFDFCFFFEFC0E00002C1A1913000022080822030429090A2000002B0B - 0C1D0000270B0BFFFDFCFFFDFBFFFEFCFFFBFC2F00023C000143000049010144 - 00004300003F00004003013C00004002023A00003D01023C0001410204400103 - 3E00013B00003F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004100023F00004403053A000047 - 06083900004605073C00004100023F00004403053A0000470608390000460507 - 3C00004A00015F00006B00006E00027401047801027901027D00027E00018000 - 018200018200018200018001008001008001007F010080000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018000018100008001007F00027F - 00038A00066B0108FFFDF9F8FFFBF6FCF7FEFBF71A02041E0000290003230000 - 2304051B00002000002F09092803051C00001E0202947F7E7967680F0102897B - 7C867A7A86787A8E8082938285857477867376978A8CFFFDFCF9FEFCF3F8F6F4 - F9F7FDFFFEFFFFFE888483050000FFF9F90C00001100001300001C00021C0000 - 2000011C0000190000200B0A210F0EFBECEAC7BAB81205030E00001804031A00 - 001C00002200011E00002202031900001B0101FFF9F8FFFBFBFFFEFEFFF4F42D - 0B0B2B00004108073D00004401004200004505013A0000450806370000440606 - 3C00004100023B00003D00003F00004302044201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004201033A000049080A3900004A090B3900004605073E00004201033A0000 - 49080A3900004A090B3900004605074500005700006300006800016F01037401 - 047800037B00007C000082000284000284000184000182000080010080010080 - 0100800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018100008001007F00027F00038A00066B0108FFFDF9F8FFFBFBFFFCFFFFFC - 240C0E23000433070D2500012D0E0F1E00002500002B03042000001C00001C02 - 02DFCAC99A88890E0001FFFEFEFFFEFEFFFDFFFFFBFDFFFDFFFFFDFFFFF9FCFF - F4F6FFFDFCFDFFFEFDFFFEFDFFFEF4F5F3F5F6F48682810E0606FFFEFE120405 - 1D080A1B0305270A0D2000032A070B230206280C0C190101120000E3D4D2C3B6 - B41508061C0D0B1804032509092404052C0A0B2000002C0C0D1D0000250B0BFF - FDFCFFFEFEFFFAFAFFFCFC1E00003A090B3300004707074100004502003B0000 - 490908370000480A0A3700004605073E00004403054201034000013D00003E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004201033E00004706083900004C0B0D3900004A090B - 3900004201033E00004706083900004C0B0D3900004A090B3900004701025000 - 005A00006200006A02037002047700037B00007D000084000286000286000186 - 0001840000820000800100800100800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000018100008001007F00027F00038A00066B0108 - FFFDF9F8FFFBF6FCF7FEFBF71A02041E00002900032300002304051B0000350F - 0F230000200000270708170000D9C5C48676770B0000FFFAFAFFFEFEFFFEFFFA - F2F3FFF7F9FFFDFFFFFDFFFFFEFFFFFFFEF7FAF8FFFFFEFFFFFEFFFFFEFFFFFE - 85807F070000FFF9F90C00001300001500001C00021B00001E00011C00001900 - 001F0707120000948583FFF8F60C00001000001300001A00001C000024000120 - 00002402031B00001B0101FFF9F8FFFAFAFFFEFEFFF0F03210102B0000460D0C - 3A00004502014100004808043900004A0D0B370000480A0A3900004201033D00 - 003E00004000014302044201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000420103390000 - 4A090B3900004C0B0D3900004706083E00004201033900004A090B3900004C0B - 0D3900004706084100004A00005100005901016302046D02047401047C000381 - 0003860002870002870001870001860001840001820001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001810000800100 - 7F00027F00038A00066B0108FFFDF9F8FFFBFBFFFCFFFFFC240C0E2300043307 - 0D2500012D0E0F1E00002B0505230000351012220203170000D8C4C38F7F8009 - 0000FDF5F5FFFFFEFFFEFFFFFDFEFFFEFFFFFAFBFEF6F7FFFDFEFFFFFEFEFFFD - FCFAF9F8F6F5FBF9F8FFFFFE928D8C110909FFFEFE1404051D080A1B03052409 - 0C1F000328070B2302062B0F0F1600001E0A09897A78FFFCFA0D00002D1B1A13 - 00002408082404052E090B2200002E0C0D1D0000250B0BFFFDFCFFFEFEFFF9F9 - FFFCFC1E00003C0B0D3300004808084100004502003A00004A0A093700004A0C - 0C3700004706083E00004302044201034000013D00003E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004201033E00004605073900004A090B39000049080A3A00004201033E00 - 004605073900004A090B39000049080A3A00004301024300004A00005101005C - 02026602027002047B0004820004860002890002890002870001860001840001 - 8200018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018100008001007F00027F00038A00066B0108FFFDF9F8FFFBF6FC - F7FDFAF61A02041E00002800022300002304051B00002D0707230000330E101D - 00001C0202D6C2C1928485070000FFFFFEFFFFFEFEFCFCFFFFFFFFFFFFFFFFFF - FDF8F9FFFDFEFFFBFAFFFFFEFFFFFEFFFEFDFFFFFEFEF9F87D7575090000FFF9 - F90E00001300001300001A00021900001E00011C00001900001B030312000027 - 1514FFFDFB0E00001000001601001C00001E00002400012000002402031B0000 - 1B0101FFF8F7FFFBFBFFFEFEFFF1F1310F0F2B0000440B0A3B00004502014100 - 00470703390000480B093700004709093A00004201033C00003E000040000143 - 02044100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004100023C00004605073900004706 - 083A00004403053F00004100023C00004605073900004706083A00004403053F - 00003E01004001004801005100005D00006A0002780004800005860004870002 - 8900028700028600018400018200018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018100008001007F00027F00038A00 - 066B0108FFFDF9F8FFFBFBFFFCFFFFFC240C0E23000433070D2500012D0E0F1E - 0000300A0A230000220000220304220808CAB8B7877B7B070201FFFFFEFFFFFE - F8F8F8F5F5F5FFFFFFFFFFFFFFFFFFFFFFFFFFFDFCFFFEFDFFFDFCFFFFFEFFFF - FEBAB5B4312929090000FFFEFE1204051B090A19030524090C1D000327080B22 - 0306290D0D170000230E0D100000FFFEFC0E0000231110170201260708260405 - 2E090B2200002E0C0D1E0000270B0BFFFDFCFFFEFEFFFCFCFFFCFC2000003706 - 083600004505054200004401003D00004606053700004507073800004403053F - 00004504064302044100023D00004000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000014000 - 014100023E00004201033E00004201033F00004000014000014100023E000042 - 01033E00004201033F00003E00003902003901003F0000480000550000630000 - 7100037C01058000048600048600028600028400028200018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018100 - 008001007F00027F00038A00066B0108FFFDF9F8FFFBF6FCF7FEFBF71A02041E - 00002900032300002304051B00002200002901022400011E0000150000D0BEBD - 8D8181050000F6F4F3FFFFFEFDFFFFFCFEFEFBFDFDFBFDFDF9FBFBFCFCFCFFFF - FEFFFFFEFFFFFEFAF5F48C87860803020700008A8282FFFAFA0C000010000112 - 00001901031700001C00021900001900001C0202190403100000FFFCFA1F100E - 1200001500001D00001E00002600012200002601031C00001E0202FFF9F8FFFC - FCFFFEFEFFF8F82907072E00003E05043F00004300004300004202003E000040 - 03013C00004002023F00004000013D00003E00004000014302044000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100024000014000013F00004201033E00004201033E000041000240 - 00014000013F00004201033E00004201033E00004100023C0000390401370200 - 3F04024300005301005900006600006D00007D02067F00048100037F00007D00 - 007D00007E00017F000280000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018100008001007F00027F00038A00066B0108FFFDF9F8 - FFFBFBFFFCFFFFFC230B0D23000432060C2500012C0D0E1E00002C0808240000 - 2E0C0D1D0000230B0BD5C3C28E82820B0605FFFFFEFFFFFEFDFFFFFBFFFFFBFF - FFF9FEFDFDFFFFFEFEFEFFFFFEFFFEFECDC5C50700001D1817080302C1BCBBFF - FEFEFFF9F9897D7D1F11121505061F0A0C1300002D1517160000270B0B250B0B - 261110867473FFFEFC0E00002E1A191500002607082503042F080A2400002F0A - 0C1E0000270B0BFFFDFCFFFDFDFFFEFEFFFCFC2402023201033A010042020242 - 00004300004000004202013C00004002023C0000410002400001430204420103 - 4000013D00003F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004100023F00004403053A000047 - 06083900004605073C00004100023F00004403053A0000470608390000460507 - 3C00003D01023701003A07043500004807064300005903035900006600007201 - 047700037A00037B00027C00017C00017D00027D00027F000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 018000018000018000018000018000018000018000018100008001007F00027F - 00038A00066B0108FFFDF9F8FFFBF6FCF7FEFBF71A02041E0000290003230000 - 2304051B0000230000220000240203190000180302C9BAB8857979050000FEFC - FBF4F5F3FDFFFFE5EAE9FBFFFFFDFFFFFCFEFEFAF8F8FDF8F7847C7C0700000D - 0807898483FCF7F6FFFEFDFFFFFEFFFCFCFFFEFEFFFBFB7B6D6E908081B09E9F - 8570728F797B8E7474947A7A968180FFFAF99B89881000001200001500001D00 - 002000002600012200002601031C00001D0101FFF9F8FFFBFBFFFEFEFFF4F42D - 0B0B2B00004108073D00004401004200004505013A0000450806370000440606 - 3C00004100023B00003D00003F00004302044201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004201033A000049080A3900004A090B3900004605073E00004201033A0000 - 49080A3900004A090B3900004605073C00003D0504330000430A083900005109 - 094500005A04045A00006500026A00026E00027401047800047A01057A02037B - 00027F0001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018100008001007F00027F00038A00066B0108FFFDF9F8FFFBFBFFFCFFFFFC - 240C0E23000433070D2500012D0E0F1E00002D09092300002C0C0D1C0000220D - 0CD3C4C28F83830B0605FFFFFEF3F4F2FAFCFCFDFFFFFBFDFDFFFFFFFFFFFF81 - 7F7F211C1B150D0D8F8A89FFFDFCFAF5F4FFFFFEFFFFFEFFFCFBFDF9F8FFFFFE - FFF9F9FFFBFBFFFEFEEDDFE0FFFDFEFFFCFEFFFCFCFFFCFCFFF2F2A28E8D200E - 0D1000003D292815000028080928030530090B240000300B0D200000290A0BFF - FDFCFFFEFEFFFAFAFFFCFC1E00003A090B3300004707074100004502003B0000 - 490908370000480A0A3700004605073E00004403054201034000013D00003E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004201033E00004706083900004C0B0D3900004A090B - 3900004201033E00004706083900004C0B0D3900004A090B3900004001033900 - 004209083500004A0D0B3A0000520A0A4500005402015700005D00006602026D - 02047103057502057902037901027F0001800001800001800001800001800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 00018000018000018000018000018100008001007F00027F00038A00066B0108 - FFFDF9F8FFFBF6FCF7FEFBF71A02041E00002900032300002304051900002100 - 00200000220203190000180302C9BAB8857979050000EBE9E8FFFFFEFBFBFBFE - FEFEFFFFFFBEBCBC04000004000005000075706FFFFFFEFAF6F5FFFDFCFDFBFA - FFFFFEFFFDFCFFFFFEFDF9F8FFFFFEFFFEFDFAF0F0FFFBFBFFFEFEFFF3F4FFF9 - F98C70702109091200001000001000001500002107071D000020000027000123 - 00002801031E00001F0001FFF9F8FFF9FAFFFEFEFFF0F03210102B0000460D0C - 3A00004502014100004808043900004A0D0B370000480A0A3900004201033D00 - 003E00004000014302044201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000420103390000 - 4A090B3900004C0B0D3900004706083E00004201033900004A090B3900004C0B - 0D3900004706083E0000420404390000490B0B3700004A0D0B39000049080744 - 00004A00005100005B01016201036B03047002047401047801027D0101800001 - 8000018000018000018000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001810000800100 - 7F00027F00038A00066B0108FFFDF9F8FFFBFBFFFCFFFFFC240C0E2300043307 - 0D2500012D0E0F1C00002B09092100002C0C0D1B0000210C0BD3C4C28F83830D - 0505FFFFFEFFFFFEECEAEAFFFFFF817C7D0500001C1415847C7DFFFFFEFCF7F6 - F8F3F2FFFFFEFFFFFEF7F8F6FFFFFEF6F7F5EDEEECF8F9F7F7F5F4FFFFFEFFFC - FBFFFFFEF4ECECDACCCD170000240808260E0E1200002E1C1B1000001D080717 - 000027070828030531090B250000320B0D200000290A0BFFFDFCFFFDFEFFF9F9 - FFFCFC1E00003C0B0D3300004808084100004502003A00004A0A093700004A0C - 0C3700004706083E00004302044201034000013D00003E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004201033E00004605073900004A090B39000049080A3A00004201033E00 - 004605073900004A090B39000049080A3A000042010341000048060739000048 - 0A0A350000430A08360000400503400000470000500000590101630101690102 - 6E00027500017D00028000018000018000018000018000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018100008001007F00027F00038A00066B0108FFFDF9F8FFFBF6FC - F7FDFAF61A02041E00002800022300002304051900002100001E000022020317 - 0000160201C9BAB8857979070000FDF8F7F8F4F39C97980500000B0506857D7E - D2C7C9FFFDFFE4DFDEFFFFFEFFFEFDF7F5F4FFFFFEFCFFFDF6F9F7FDFFFEFDFF - FEF8FBF9FDFFFEFFFFFEF9F7F6FFFFFE807C7B0C00001E06062307071500001D - 08071200001501001A05041700001F00002200002700012300002801031E0000 - 1F0001FFF7F7FFFAFBFFFEFEFFF1F1310F0F2B0000440B0A3B00004502014100 - 00470703390000480B093700004709093A00004201033C00003E000040000143 - 02044100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004100023C00004605073900004706 - 083A00004403053F00004100023C00004605073900004706083A000044030540 - 00004802034200004705063700004108073200003A07043702003A0200400100 - 4900005100005B00006400006B00007300007D00028000018000018000018000 - 0180000180000180000180000180000180000180000180000180000180000180 - 0001800001800001800001800001800001800001800001800001800001800001 - 8000018000018000018000018000018000018100008001007F00027F00038A00 - 066B0108FFFDF9F8FFFBFBFFFCFFFFFC240C0E23000433070D2500012D0E0F1C - 0000290A091F00002B0C0D190000200C0BD3C4C28F83830D0505C9C4C38E8988 - 0E08090E0607CDC2C4FFFDFFFFFDFFFFF4F6FFFFFEFEFAF9FFFFFEF7F5F4FFFF - FEEDF0EEFDFFFEFBFFFEE8EDEBF9FEFCFAFFFDF6F9F7898A8802000017151409 - 00001D05051900002F151519040324100F1200002914131700002907082A0305 - 31090B250000320B0D2200002A0A0BFFFCFCFFFDFEFFFCFCFFFCFC2000003706 - 083600004505054200004401003D00004606053700004507073800004403053F - 00004504064302044100023D00004000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000014000 - 014100023E00004201033E00004201033F00004000014000014100023E000042 - 01033E00004201033F00004100014600014802034000004103033800003C0403 - 3701003904013A03003E01004200004900005000005800005F00006500007202 - 027601027601027601027801027801027901027901027B00027B00027D00027D - 00027F00027F00027F00027F00027F00017F00017F00017F00017F00017F0001 - 7F00017F00017F00017F00017F00017F00017F00017F00017F00018000018100 - 008000017D00027C0003830008660208FFFCFBFDFFFBF8FCF7FFFAF71C010420 - 00002600032000002304051B00002300002000002503041900001A0202CCBAB9 - 8678790900000904030702017F797AFFFBFCFFFDFFFCF1F3FFF7F9FFFEFEFFFF - FEF3F4F2FFFFFEFFFFFEFDFFFEFDFFFEF4F7F5FFFFFEFFFFFEFFFFFEC4C2C104 - 00000904030700000900001002031800001C00001800001500001300001F0A09 - 1500001F03031E00002000002600012200002601031E0000210102FFF8F8FFFB - FCFFFEFEFFF8F82907072E00003E05043F00004300004300004202003E000040 - 03013C00004002023F00004000013D00003E00004000014302044000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100024000014000013F00004201033E00004201033E000041000240 - 00014000013F00004201033E00004201033E0000410002400001410001400000 - 4201033E00004001033C00003D01023C00003E00003F00004301024100004701 - 024500004A00014E00005500005A00005E02015C00006505056602026B05066E - 03057305077302057A05087700037D04087A00037F01067D00047C00017A0000 - 7D00027900007E01037900007D00027B00007C00017A00007D00027900007E01 - 037900007D00027D00007E00007D00017A020771000474010B580008FFFBFBFF - FFFCFFFFFEFFFEFE290A0B27000229090A1D00002C0E0D2100003A0D10290000 - 2D04092B060A331619C2ACAED8C8C9090000837E7DBFBBBAFBF7F6FFFFFEFFFF - FEFFFDFCFFFCFCFFFBFAF5FAF8F8FFFCFAFFFCF6FCF7FDFFFCF3F4F0FFFFFCFE - F9F6FFFDFA8A7E7C2A1B191000001F0A091C04042309091A0000270809210203 - 2509091C0000270B0B1E020224080820010226070823030429090A1E00002B0B - 0C1E0000290A0BFFFCFCFFFCFDFFFEFEFFFCFC2402023201033A010042020242 - 00004300004000004202013C00004002023C0000410002400001430204420103 - 4000013D00003F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004100023F00004403053A000047 - 06083900004605073C00004100023F00004403053A0000470608390000460507 - 3C00004100023F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004200014400004C010046000055 - 05044C00005B05055700005F01026500026D040768000076070B6D00007C060B - 7500027A02077700037A05067100007D08097000007C07087300007803047500 - 017A05067100007D08097000007C07087300007B02067B00018002086E000372 - 080F6300035A0A11FFF6F8FFFEFCFCFAF9FFF9F92101022200001F0100170000 - 2306022000002500002800002500021C0000170000E7D2D4C4B8B8837E7DFFFF - FEFFFFFEF9FCFAF5F8F6F9FAF8FFFFFEFFFFFEFFFFFEFAFFFCF4FEF8F6FDF8FB - FFFCF2F6F1FFFFFCFFF8F59185831809071000001300001700002405061C0000 - 2100001C00001E00001B00001E00001B00002001021B00001C00001B00001C00 - 001B00001F00011B00002102031B00001F0001FFF8F8FFFAFBFFFEFEFFF4F42D - 0B0B2B00004108073D00004401004200004505013A0000450806370000440606 - 3C00004100023B00003D00003F00004302044201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004201033A000049080A3900004A090B3900004605073E00004201033A0000 - 49080A3900004A090B3900004605073E00004201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073F - 00004300003E00004C07044000005308064700005604035100005A0000560000 - 6906085A000070090C61000072070A6B00036E0305660000750A0C620000760B - 0D6400007207096A00016E0305660000750A0C620000760B0D6400007207096D - 00017500026E000075090F5900006D0A12460000FFFBFCFFFFFCFFFFFEFFFEFE - 2B0B0C270002290B0A1900002E0F0C21000024040528090C2005081400011709 - 0A817979FFFFFEF5FAF8F1FAF7F4FFFCF6FFFEF6FFFEF8FFFEEFF8F5F5FCF9FA - FFFEF0F6F1F4FAF5FDFFFCFDFEFAFFFFFCC0BBB88A817E0D0000100000120000 - 2810101C02022001021D00002F0D0E22020328080922030428090A1E00002A0B - 0C200102270809210203270809230405290A0B1D00002B0C0D1D0000290A0BFF - FCFCFFFDFEFFFAFAFFFCFC1E00003A090B3300004707074100004502003B0000 - 490908370000480A0A3700004605073E00004403054201034000013D00003E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004201033E00004706083900004C0B0D3900004A090B - 3900004201033E00004706083900004C0B0D3900004A090B3900004201033E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004202023E00004809053900004E0E0A3C0000520B08 - 4200004F02004B00005704034C0000620A0A50000066090A5700006002035A00 - 00630605530000680B0A5300006609085500005F02015A000063060553000068 - 0B0A5300006609085500006300026400006D020555000064080D5000004F090F - FFF0F1FFFFFCF8FBF9FFFAF92101022200001F01001700002405021C00001F03 - 031500001200000E0000201616040000F3F6F4F9FFFDF6FFFEF0FEFAEEF9F6F3 - FEFBF6FFFEF8FFFEF6FDFAF2F7F5FFFFFCF0EFEBFFFEFAFFFFFC7B7471170E0B - 0E01001000001F0B0A1601001E04041900001B00001C00002301021E00001E00 - 001B00001E00001B00002001021B00001C00001B00001C00001B00001F00011B - 00002102031B00001F0001FFF8F8FFF9FAFFFEFEFFF0F03210102B0000460D0C - 3A00004502014100004808043900004A0D0B370000480A0A3900004201033D00 - 003E00004000014302044201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000420103390000 - 4A090B3900004C0B0D3900004706083E00004201033900004A090B3900004C0B - 0D3900004706083E00004201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083C00003F0604350000 - 460D0B3500004B0E0C390000490807410000470101400000530909430000580A - 0B4700005505064B000050000147000057070847000059090A4700005404054B - 000050000147000057070847000059090A4700005404054E00005B0000530000 - 5C080A4700005C080D370000FFFCFCFEFDF9FBFFFEFFFFFE2B0B0C270002290B - 0A1900002E0F0C1F00002E14141701031A05070E00002418180F0A09939190FD - FFFEF7FCFAFAFFFEFBFFFEF8FDFBFBFEFCFDFFFEFFFFFEFFFFFEFFFFFCFFFFFC - BFB3B11205031407050E0000210F0E1300001B03031700002105051E00002606 - 071F00002C0A0B22000128080923030429090A1F00002B0B0C21010227070822 - 02032707082404052A0A0B1E00002C0C0D1E00002A0A0BFFFCFCFFFDFEFFF9F9 - FFFCFC1E00003C0B0D3300004808084100004502003A00004A0A093700004A0C - 0C3700004706083E00004302044201034000013D00003E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004201033E00004605073900004A090B39000049080A3A00004201033E00 - 004605073900004A090B39000049080A3A00004201033E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004002023700003D0805320000430C093200004209073600004003013D00 - 004606053A00004D0A093C00004B08073E00004600004300004B05053E00004F - 09093E00004E08083F00004701014300004B05053E00004F09093E00004E0808 - 3F00004B01014E00005705044200004F090A420000440B0EFFF5F4FDFFFCF5FC - F9FDF9F82001022200001E00001700002405021C00001B00001900002E131619 - 03051402030E00000B00000900008C8484B4ACACD2CACACCC4C4C0B6B6C4B8B8 - CBBDBECCBEBFCABBB982706F1A08071200001200001C07061C0404170000280E - 0E1900001B00001B00001E00001C00002100001E00001E00001C00001F00001C - 00002101021C00001D00001C00001D00001C00002000011C00002202031C0000 - 200001FFF7F7FFFAFBFFFEFEFFF1F1310F0F2B0000440B0A3B00004502014100 - 00470703390000480B093700004709093A00004201033C00003E000040000143 - 02044100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004100023C00004605073900004706 - 083A00004403053F00004100023C00004605073900004706083A00004403053F - 00004100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053D00003A02013200003C07043000003E09 - 063300003D06033900003B02003800004207053700004508063900004306043E - 01004202023D00004706083A00004807093B00004504063F00004201033D0000 - 4706083A00004807093B00004504064000004800004400004707063700004906 - 09300000FFFEFCFBFFFCF8FFFEFFFFFE2A0B0C270002290B0A1900002D100C21 - 00003D161823000030080D2400031C00001B000045282B170000260B0E22070A - 1C01041B00012506092D0E1129080C1B0000250B0B230B0B220A0A1C02023F25 - 251700001900002408082307071B00002102032505063313142606072707081C - 000028080923030429090A1F00002B0B0C210102270708220203270708240405 - 2A0A0B1E00002C0C0D1E00002A0A0BFFFCFCFFFDFEFFFCFCFFFCFC2000003706 - 083600004505054200004401003D00004606053700004507073800004403053F - 00004504064302044100023D00004000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000014000 - 014100023E00004201033E00004201033F00004000014000014100023E000042 - 01033E00004201033F00004000014000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00003E00013A01 - 003B04013801003C05023801003D06033A03003C05023800003A01003700003D - 04023900003F06043C03013E05043B00003D01023A00003E02033900003E0203 - 3B00003C00013B00003D01023A00003E02033900003E02033B00003E00003F00 - 00410200360000390100390000330406FFF9F7FAFFFCF3FCF9FEFAF920010222 - 00001D01001700002306021E00002500002F0107270000280002260002220000 - 2100002000002200012000002200002200002300002500002500002500011C00 - 001900001B00001900001B00001B00003213141B00002001021B00002303041C - 00001C00001C00002404051E00001F00001C00001F00001C00002101021C0000 - 1E00001C00001E00001C00002000011C00002202031C0000210102FFF8F8FFFB - FCFFFEFEFFF8F82907072E00003E05043F00004300004300004202003E000040 - 03013C00004002023F00004000013D00003E00004000014302044000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100024000014000013F00004201033E00004201033E000041000240 - 00014000013F00004201033E00004201033E00004100024000014000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100023E00013E00003B00003E02023A00003E02023A00003D01013A - 01003C00003B00003E02023A00003C03023800003B02013A01003C00013D0002 - 4000053C00014000053C00013F00043E00033E00033D00024000053C00014000 - 053C00013F00043C00013F040232000045120F2E000043090A290000FFFEFCF5 - FBF6F4FBF8FFFFFE1F00012B0406311514150000280D0922030230080A2A0004 - 31050B250000330A0F2600032D050A2500022F070C2700042F060B2500003509 - 0F2B000332040A2800022B090A2001022808091B00002C0C0D2000012707081F - 000028090A2001022708091B00002B0C0D1F00012607081E000028090A200102 - 2708091B00002B0C0D1F00012607081E0000240506270809290A0B1B00001C00 - 002A0B0C1B0000FFFCFCFFFDFEFFFDFDFFF8F82100004211133600004A0A0A3C - 00004300004000004202013C00004002023C0000410002400001430204420103 - 4000013D00003F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004100023F00004403053A000047 - 06083900004605073C00004100023F00004403053A0000470608390000460507 - 3C00004100023F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004100023F00004404043A000047 - 07073900004406063A00003F01013D0000420404380000430707350000420606 - 3800003D01013D00004202073A000045050A3900004404093C00003F00043F00 - 024202073A000045050A3900004404093C00003F00023900003F0B052B00003C - 0B09330000491A1CFFF0EEFDFFFCFAFFFEFCF7F6200001220000230A08130000 - 1C03001900002000011E00002100021E00002401051E00001E00011C00002200 - 031E00002300022000002601052200002400012200002200011C00001F00001C - 00002202031B00001E00001B00001F00011B00001E0000190000210203190000 - 1D00001900001F00011900001E00001900002102031900001D00001900001B00 - 001900002506072509092B0C0D1900001B0000FFF4F4FFFDFEFFFEFEFFE9E930 - 0E0E2B0000370000390000520F0E4200004505013A0000450806370000440606 - 3C00004100023B00003D00003F00004302044201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004201033A000049080A3900004A090B3900004605073E00004201033A0000 - 49080A3900004A090B3900004605073E00004201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004301023B00004A08093A00004B090A3A00004705063E00004202023A0000 - 490909370000480A0A3700004406063E00004201033A00004A070A3900004B08 - 0B3900004704073E00004300033A00004A070A3900004B080B3900004704073C - 00003400003300004919152E00004E12132F0000FFEFEEFFFFFCFBFFFEEDE5E5 - 4222232200001C030112000028140F230E0C1B07061601031B06081400011D08 - 0A1601031A05071500021B06081601031C06081500011E080A1901031D05071A - 00022405061F00012405061D00002607081D01012304051C00002206061D0101 - 2206061900002408081B01012105051A00002206061B01012206061900002408 - 081B01012105051A00002C10101700001900001700001F0303190000472B2BFF - F5F4FFFBFBFFF8F8FFFCFC1E00004211133300004707073C00004502003B0000 - 490908370000480A0A3700004605073E00004403054201034000013D00003E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004201033E00004706083900004C0B0D3900004A090B - 3900004201033E00004706083900004C0B0D3900004A090B3900004201033E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004201033F00004A06073C00004F0B0C3C00004D090A - 3A00004301023F00004806073900004C0C0C3900004A0A0A3900004202023F00 - 004805083A00004D0A0D3A00004B080B3A00004300033F00004805083A00004D - 0A0D3A00004B080B3A00004202023D02003D06013906033200003F0000370205 - FFFDFCFFFFFCFAFBF9FFFEFEFFE9EAFFF6F8FFFDFBFFFCF9FFFCF7FFEFECFFFE - FCFFFEFEFFFEFEFFFEFEFFFEFEFFFEFEFFFDFEFFFEFEFFFDFEFFFDFEFFFDFEFF - FDFEFFFDFEFFFDFEFFFDFEFFFDFEFFFCFCFFFCFCFFFCFCFFFCFCFFFCFCFFFCFC - FFFCFCFFFCFCFFFCFCFFFCFCFFFCFCFFFCFCFFFCFCFFFCFCFFFCFCFFFCFCFFFC - FCFFFCFCFFFCFCFFFCFCFFFCFCFFFCFCFFFCFCFFFCFCFFF7F7FFFCFCFFFCFCFF - FCFCFFFCFCFFEDEDF7DFDFFFFDFCFFFEFEFFFEFEFFF5F52000002B00004A1110 - 3F00004704034100004808043900004A0D0B370000480A0A3900004201033D00 - 003E00004000014302044201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000420103390000 - 4A090B3900004C0B0D3900004706083E00004201033900004A090B3900004C0B - 0D3900004706083E00004201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E00004300033A0000 - 4B080B3A00004D0A0D3A00004805083F00004300033A00004B080B3A00004D0A - 0D3A00004805083F00004301023A00004B090A3A00004D0B0C3A00004806073F - 00004301023A00004B090A3A00004D0B0C3A00004806073E0000430302350000 - 3B0401370000510C0F320000FFFCFCEDE6E3FDFBFAFFFEFEFFFAFCFFF9FBFFFD - FBFFF8F5FFFFF9FFFEFBFFF9F7FFFAFAFFF9F9FFFBFBFFF8F8FFFBFBFFF9F9FF - FBFBFFF9F9FFFAFAFFF9F9FFFBFBFFF8F8FFFBFBFFF9F9FFFAFBFFF8F7FFF8F8 - FFF7F7FFF9F9FFF6F6FFF9F9FFF7F7FFF9F9FFF7F7FFF8F8FFF7F7FFFAF9FFF6 - F6FFFAF9FFF7F7FFFAF9FFF8F7FFF9F8FFF8F7FFFAF9FFF7F6FFFAF9FFF8F7FF - FAF9FFF6F5FFFDFCFFFAF9FFF1F0FFFDFCFFFDFCFFFDFCFFF9F8FFFEFEFFFBFB - FFFCFC2B09093F0E103500003C00004906054502003A00004A0A093700004A0C - 0C3700004706083E00004302044201034000013D00003E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004201033E00004605073900004A090B39000049080A3A00004201033E00 - 004605073900004A090B39000049080A3A00004201033E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004201033E00004605073900004A090B39000049080A3B00004201033F00 - 004605073A00004B080B3A00004A070A3B00004300033F00004705063A00004B - 090A3A00004A08093B00004301023F00004705063A00004B090A3A00004A0809 - 3B00004302013B00004203003A00004F1111410000420509FFFBFCFFFFFCFFFC - FBFFF9FAFFFAFCFFF8FAFFFBF9FFFBF8FFFBF5FFFEFAFFFEFCFFFDFEFFFDFEFF - FDFEFFFCFDFFFDFEFFFDFEFFFDFEFFFDFEFFFDFEFFFDFEFFFDFEFFFCFDFFFDFE - FFFDFEFFFDFEFFFDFCFFFDFCFFFDFCFFFDFCFFFCFBFFFDFCFFFDFCFFFDFCFFFD - FCFFFDFCFFFDFCFFFDFCFFFCFBFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFF - FDFCFFFCFBFFFDFCFFFDFCFFFDFCFFFAF9FFFDFCFFFBFAFFFDFCFFFBFAFFFDFC - FFFCFBFFF7F5F9EFEFFFFEFEFFFBFB2A08083100023500004808084401004100 - 00470703390000480B093700004709093A00004201033C00003E000040000143 - 02044100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004100023C00004605073900004706 - 083A00004403053F00004100023C00004605073900004706083A00004403053F - 00004100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00003F00023A00004405073700004506 - 083800004403053D00004100023A00004605073900004706083A00004403053F - 00004101013C00004606053900004707063A00004404033F00004101003C0000 - 4606053900004707063A00004404034000004D0A073F00005212113A00005407 - 0B400003FFE2E3FFFEFCFFFEFEFFFDFEFFFAFCFFFAFCFFFDFBFFFFFBFFF7F1FF - F9F6FFF5F4FFFBFDFFF4F7FFFBFEFFF1F4FFFBFEFFF5F8FFFBFEFFF3F6FFFAFD - FFF4F7FFFBFEFFF2F4FFFCFEFFF6F8FFFCFEFFF5F4FFFCFBFFF6F5FFFDFCFFF3 - F2FFFDFCFFF7F6FFFDFCFFF5F4FFFCFBFFF6F5FFFDFCFFF3F2FFFDFCFFF7F6FF - FDFCFFF5F4FFFDFBFFF6F5FFFEFCFFF3F2FFFEFCFFF7F6FFFEFCFFFDFCFFFEFC - FFF9F8FFFEFCFFF5F4FFFEFCFFF8F7FFFEFCFFFEFEFFFEFEFFFCFC1E00004918 - 1A3300005313133C00004401003D00004606053700004507073800004403053F - 00004504064302044100023D00004000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000014000 - 014100023E00004201033E00004201033F00004000014000014100023E000042 - 01033E00004201033F00004000014000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000013E00 - 013D01023C00004001033C00004001033D00003E00013E00013F00023C000040 - 01033E00004201033F00004000014000004101003E00004202013E0000420201 - 3F00004000004000004101003E00004202013E00004202013F00004100003C00 - 004A07063A00004C0809480000470409300607290D0D1300002408082A000031 - 02041D00002108061C03002C100F2300002D0608270001330B0D2300002F0709 - 2A000232070A2600002E0608270001330B0D2200002C07092700022B090A1E00 - 002408071D0101290D0C190000250908200102280A091E00002608071F00012B - 0D0C1B0000270908210102280A091C00002408071D0101290D0C190000250908 - 1E0202260A091D01012105041900002A0E0D1900002D11101900002208081500 - 002B11111E00002500003703034D1112390000500F0E4300004201003E000040 - 02023C00004002023F00004000013D00003E00004000014302044000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100024000014000013F00004201033E00004201033E000041000240 - 00014000013F00004201033E00004201033E00004100024000014000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100024000014000013D00004201033E00004201033E000041000240 - 00014000013F00004201033E00004201033E00004100024000014000013F0000 - 4201033E00004201033E00004100024000004000013F00004201033E00004201 - 033E00004100024000004100004000004202023F00004500033E00003A010235 - 00033301033400023C0105380000390303330000360202350101370003380002 - 3B02053700013B02053700013A01043900033900033800023B02053700013B02 - 053500013A010437000335000334000037020533000037020533000036010435 - 0101350003340000370205330000370205330000380104350101350003340000 - 3702053300003702053300003601043501013500033400003702053300003702 - 053300003601043500033301033400023902053700003E02033C000041000240 - 00004100003F00004202023E00004201033E0000410002400001430204420103 - 4000013D00003F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004100023F00004403053A000047 - 06083900004605073C00004100023F00004403053A0000470608390000460507 - 3C00004100023F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004100023F00004403053A000047 - 06083900004605073C00004100023F00004403053A0000470608390000460507 - 3C00004100023F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004100023F00004403053A000047 - 06083900004605073C00004100023F00004403053A0000470608390000460507 - 3C00004100023F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004100023F00004403053A000047 - 06083900004605073C00004100023F00004403053A0000470608390000460507 - 3C00004100023F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004100023F00004403053A000047 - 06083900004605073C00004100023F00004403053A0000470608390000460507 - 3C00004100023B00003D00003F00004302044201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004201033A000049080A3900004A090B3900004605073E00004201033A0000 - 49080A3900004A090B3900004605073E00004201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004201033A000049080A3900004A090B3900004605073E00004201033A0000 - 49080A3900004A090B3900004605073E00004201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004201033A000049080A3900004A090B3900004605073E00004201033A0000 - 49080A3900004A090B3900004605073E00004201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004201033A000049080A3900004A090B3900004605073E00004201033A0000 - 49080A3900004A090B3900004605073E00004201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004201033A000049080A3900004A090B3900004605073E00004201033A0000 - 49080A3900004A090B3900004605073E00004403054201034000013D00003E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004201033E00004706083900004C0B0D3900004A090B - 3900004201033E00004706083900004C0B0D3900004A090B3900004201033E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004201033E00004706083900004C0B0D3900004A090B - 3900004201033E00004706083900004C0B0D3900004A090B3900004201033E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004201033E00004706083900004C0B0D3900004A090B - 3900004201033E00004706083900004C0B0D3900004A090B3900004201033E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004201033E00004706083900004C0B0D3900004A090B - 3900004201033E00004706083900004C0B0D3900004A090B3900004201033E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004201033E00004706083900004C0B0D3900004A090B - 3900004201033E00004706083900004C0B0D3900004A090B3900004201033D00 - 003E00004000014302044201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000420103390000 - 4A090B3900004C0B0D3900004706083E00004201033900004A090B3900004C0B - 0D3900004706083E00004201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000420103390000 - 4A090B3900004C0B0D3900004706083E00004201033900004A090B3900004C0B - 0D3900004706083E00004201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000420103390000 - 4A090B3900004C0B0D3900004706083E00004201033900004A090B3900004C0B - 0D3900004706083E00004201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000420103390000 - 4A090B3900004C0B0D3900004706083E00004201033900004A090B3900004C0B - 0D3900004706083E00004201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000420103390000 - 4A090B3900004C0B0D3900004706083E00004201033900004A090B3900004C0B - 0D3900004706083E00004302044201034000013D00003E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004201033E00004605073900004A090B39000049080A3A00004201033E00 - 004605073900004A090B39000049080A3A00004201033E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004201033E00004605073900004A090B39000049080A3A00004201033E00 - 004605073900004A090B39000049080A3A00004201033E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004201033E00004605073900004A090B39000049080A3A00004201033E00 - 004605073900004A090B39000049080A3A00004201033E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004201033E00004605073900004A090B39000049080A3A00004201033E00 - 004605073900004A090B39000049080A3A00004201033E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004201033E00004605073900004A090B39000049080A3A00004201033E00 - 004605073900004A090B39000049080A3A00004201033C00003E000040000143 - 02044100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004100023C00004605073900004706 - 083A00004403053F00004100023C00004605073900004706083A00004403053F - 00004100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004100023C00004605073900004706 - 083A00004403053F00004100023C00004605073900004706083A00004403053F - 00004100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004100023C00004605073900004706 - 083A00004403053F00004100023C00004605073900004706083A00004403053F - 00004100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004100023C00004605073900004706 - 083A00004403053F00004100023C00004605073900004706083A00004403053F - 00004100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004100023C00004605073900004706 - 083A00004403053F00004100023C00004605073900004706083A00004403053F - 00004504064302044100023D00004000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000014000 - 014100023E00004201033E00004201033F00004000014000014100023E000042 - 01033E00004201033F00004000014000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000014000 - 014100023E00004201033E00004201033F00004000014000014100023E000042 - 01033E00004201033F00004000014000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000014000 - 014100023E00004201033E00004201033F00004000014000014100023E000042 - 01033E00004201033F00004000014000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000014000 - 014100023E00004201033E00004201033F00004000014000014100023E000042 - 01033E00004201033F00004000014000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000014000 - 014100023E00004201033E00004201033F00004000014000014100023E000042 - 01033E00004201033F00004000013D00003E00004000014302044000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100024000014000013F00004201033E00004201033E000041000240 - 00014000013F00004201033E00004201033E00004100024000014000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100024000014000013F00004201033E00004201033E000041000240 - 00014000013F00004201033E00004201033E00004100024000014000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100024000014000013F00004201033E00004201033E000041000240 - 00014000013F00004201033E00004201033E00004100024000014000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100024000014000013F00004201033E00004201033E000041000240 - 00014000013F00004201033E00004201033E00004100024000014000013F0000 - 4201033E00004201033E00004100024000014000013F00004201033E00004201 - 033E00004100024000014000013F00004201033E00004201033E000041000240 - 00014000013F00004201033E00004201033E0000410002400001430204420103 - 4000013D00003F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004100023F00004403053A000047 - 06083900004605073C00004100023F00004403053A0000470608390000460507 - 3C00004100023F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004100023F00004403053A000047 - 06083900004605073C00004100023F00004403053A0000470608390000460507 - 3C00004100023F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004100023F00004403053A000047 - 06083900004605073C00004100023F00004403053A0000470608390000460507 - 3C00004100023F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004100023F00004403053A000047 - 06083900004605073C00004100023F00004403053A0000470608390000460507 - 3C00004100023F00004403053A00004706083900004605073C00004100023F00 - 004403053A00004706083900004605073C00004100023F00004403053A000047 - 06083900004605073C00004100023F00004403053A0000470608390000460507 - 3C00004100023B00003D00003F00004302044201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004201033A000049080A3900004A090B3900004605073E00004201033A0000 - 49080A3900004A090B3900004605073E00004201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004201033A000049080A3900004A090B3900004605073E00004201033A0000 - 49080A3900004A090B3900004605073E00004201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004201033A000049080A3900004A090B3900004605073E00004201033A0000 - 49080A3900004A090B3900004605073E00004201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004201033A000049080A3900004A090B3900004605073E00004201033A0000 - 49080A3900004A090B3900004605073E00004201033A000049080A3900004A09 - 0B3900004605073E00004201033A000049080A3900004A090B3900004605073E - 00004201033A000049080A3900004A090B3900004605073E00004201033A0000 - 49080A3900004A090B3900004605073E00004403054201034000013D00003E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004201033E00004706083900004C0B0D3900004A090B - 3900004201033E00004706083900004C0B0D3900004A090B3900004201033E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004201033E00004706083900004C0B0D3900004A090B - 3900004201033E00004706083900004C0B0D3900004A090B3900004201033E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004201033E00004706083900004C0B0D3900004A090B - 3900004201033E00004706083900004C0B0D3900004A090B3900004201033E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004201033E00004706083900004C0B0D3900004A090B - 3900004201033E00004706083900004C0B0D3900004A090B3900004201033E00 - 004706083900004C0B0D3900004A090B3900004201033E00004706083900004C - 0B0D3900004A090B3900004201033E00004706083900004C0B0D3900004A090B - 3900004201033E00004706083900004C0B0D3900004A090B3900004201033D00 - 003E00004000014302044201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000420103390000 - 4A090B3900004C0B0D3900004706083E00004201033900004A090B3900004C0B - 0D3900004706083E00004201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000420103390000 - 4A090B3900004C0B0D3900004706083E00004201033900004A090B3900004C0B - 0D3900004706083E00004201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000420103390000 - 4A090B3900004C0B0D3900004706083E00004201033900004A090B3900004C0B - 0D3900004706083E00004201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000420103390000 - 4A090B3900004C0B0D3900004706083E00004201033900004A090B3900004C0B - 0D3900004706083E00004201033900004A090B3900004C0B0D3900004706083E - 00004201033900004A090B3900004C0B0D3900004706083E0000420103390000 - 4A090B3900004C0B0D3900004706083E00004201033900004A090B3900004C0B - 0D3900004706083E00004302044201034000013D00003E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004201033E00004605073900004A090B39000049080A3A00004201033E00 - 004605073900004A090B39000049080A3A00004201033E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004201033E00004605073900004A090B39000049080A3A00004201033E00 - 004605073900004A090B39000049080A3A00004201033E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004201033E00004605073900004A090B39000049080A3A00004201033E00 - 004605073900004A090B39000049080A3A00004201033E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004201033E00004605073900004A090B39000049080A3A00004201033E00 - 004605073900004A090B39000049080A3A00004201033E00004605073900004A - 090B39000049080A3A00004201033E00004605073900004A090B39000049080A - 3A00004201033E00004605073900004A090B39000049080A3A00004201033E00 - 004605073900004A090B39000049080A3A00004201033C00003E000040000143 - 02044100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004100023C00004605073900004706 - 083A00004403053F00004100023C00004605073900004706083A00004403053F - 00004100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004100023C00004605073900004706 - 083A00004403053F00004100023C00004605073900004706083A00004403053F - 00004100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004100023C00004605073900004706 - 083A00004403053F00004100023C00004605073900004706083A00004403053F - 00004100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004100023C00004605073900004706 - 083A00004403053F00004100023C00004605073900004706083A00004403053F - 00004100023C00004605073900004706083A00004403053F00004100023C0000 - 4605073900004706083A00004403053F00004100023C00004605073900004706 - 083A00004403053F00004100023C00004605073900004706083A00004403053F - 00004504064302044100023D00004000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000014000 - 014100023E00004201033E00004201033F00004000014000014100023E000042 - 01033E00004201033F00004000014000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000014000 - 014100023E00004201033E00004201033F00004000014000014100023E000042 - 01033E00004201033F00004000014000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000014000 - 014100023E00004201033E00004201033F00004000014000014100023E000042 - 01033E00004201033F00004000014000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000014000 - 014100023E00004201033E00004201033F00004000014000014100023E000042 - 01033E00004201033F00004000014000014100023E00004201033E0000420103 - 3F00004000014000014100023E00004201033E00004201033F00004000014000 - 014100023E00004201033E00004201033F00004000014000014100023E000042 - 01033E00004201033F00004000013D00003E0000400001430204} - end - object lblWelcome: TLabel - Left = 172 - Top = 10 - Width = 318 - Height = 50 - Caption = 'Welcome to the Metamod:Source (version) Setup Wizard' - Font.Charset = DEFAULT_CHARSET - Font.Color = clWindowText - Font.Height = -21 - Font.Name = 'Tahoma' - Font.Style = [] - ParentFont = False - WordWrap = True - end - object lblInfo1: TLabel - Left = 172 - Top = 82 - Width = 331 - Height = 26 - Caption = - 'This wizard will guide you through the installation of Metamod:S' + - 'ource (version).' - WordWrap = True - end - object lblInfo2: TLabel - Left = 172 - Top = 120 - Width = 335 - Height = 39 - Caption = - 'It is recommended that you close all other applications before s' + - 'tarting a setup for e.g. Half-Life 2 or other games. Otherwise y' + - 'ou should restart your system after this installation.' - WordWrap = True - end - object lblInfo3: TLabel - Left = 172 - Top = 176 - Width = 108 - Height = 13 - Caption = 'Click Next to continue.' - end - end - object jspLicense: TJvStandardPage - Left = 0 - Top = 0 - Width = 527 - Height = 314 - object pnlLicense: TPanel - Left = 0 - Top = 0 - Width = 527 - Height = 49 - Align = alTop - BevelOuter = bvNone - Color = clWhite - TabOrder = 0 - object imgIcon1: TImage - Left = 486 - Top = 8 - Width = 32 - Height = 32 - Picture.Data = { - 0A54504E474F626A65637489504E470D0A1A0A0000000D494844520000002000 - 0000200806000000737A7AF40000000467414D410000AFC837058AE900000019 - 74455874536F6674776172650041646F626520496D616765526561647971C965 - 3C000008ED4944415478DAD556096C54D7153D7FE6CFFC59BC321EE3F1162F60 - 833DB6C10B019C60410007D43649518480B64924BAD0D00401A58AD456EA42A4 - 268A4848216D43054A55910588484A020D2EE09D181BDB78C106DB638FEDB1F1 - 18DBE3F12C7FFED2FBBFC1402090B46AAB3EE96966DEBCE5DC7BCF3DF732AB57 - 3F8EFFE6D06AB5686C6C80CBE5527F33FF8F00CC34B9AF7340969529836120B1 - 2C3BDED07001C3C3C35F19004B7339CDB5744911DD9328430E67C02817D264EE - 7B58926408A20893914320C08B3A1DDBD9D3D3BDB7B3B3E3FDAF02600341DF29 - 8872BE286BC1EA39707AFA6419D5A2202F83E74380C883D5021A0D73D7E346A3 - 1E3F78E69B489D930247B71307DEF9580182CB97DBB7381C3D7FF832007134F7 - 0BA2F494ACE1101F6B4656BC0F732CE3B09A791875324472ABC7CF6060C288F6 - E128740C6AE1F54E41AF9566BC120886B0A2380BDF5B5F8ADFED3B8A977EB20E - 474FD4E2A393B5049819AFACACB0DF0B400645EC3819362F26D68255760F8A13 - 5D88B725C2146B87C69C044617465B44C8C1318426AEC0E36A419B730A7FBFFA - 102E748A80E023B269542F994D9C1227F294803FEEDE80831F36A0ACBC590D49 - 7D7DDDFA2F02502C3FC70B4CC6FC0C2B36E5B6213BD10073E626B0519960345A - C892A0D00A924C618086EE26DF0B531086CEC1DD7E0CA77A5270AC2E0281A949 - C54A8ABF043E24E1575B164267B6E2B7FBCB2189210A234B002E6CBE1D8086E6 - DFC8F235F6F9B3F1C385E7911C1B0EA3FD456828759A1D22AE793420C354F215 - A6F230734A9C152611109D19D24407BC4D7B503698834395B3C0FB271122BC1B - 4B6D5856908C1D7B9BE0A330190D3A088218AAAAAA58C19496AE515D45F35951 - 940FC6C55BB1BDA41369BA361873B781E1ACD02288CFDA67C1311E01032B4224 - 721526B8919B14002FDE229E863523D47F0ABEDE933836B00A7F39A34141860E - AF6F5F884FEAFCE8EC19414B970703435E0C0D0D5636355D5CCBE4E717107B35 - E6A8A8E866B0E6B4CDAB24AC8CFA94DC351BBAF4F58A79D03012DA5D61180B18 - 31EC35C0E531C0C28DE3E9FC6BE40D8AF50C021DE4C93EF08E0F302E5AF04A4D - 31A6A6043C5A10A7440D1CC7A2B27114DDCE71345EACFBB1DBED7E8BD1EBF588 - 8B8B5B3F37D3FE6E669A053B1757221A2E30FA30B0B615605813794702AB91C1 - E944B40E46E2484B32B990C7A6050EA4C70AAA17981B00C4894E88A3F5F4A084 - F29102BC713A1641BF173733D4C8E9303939DE535B5B53425E77AACB0B16E4BF - 1F13F7D0D31B96C978D2F6992A9732B15C634E80262243BD4C3141A79531E4D1 - 615F7506A67816453627BEF3F02802218DCA03884188D79B2841FCAAFC8DF251 - 78B972097A9C93D0B1D308585687E6E6C657FBFB9DBB542122361A962C296E8B - B6C6A5EE5CD98B1C632318AD7EDAADF4B0C6685179408B30E9451CA88C468533 - 0D0612244E1EC32F4ABB1161A444080520FB06200B816952D2F11089C581D665 - 38D940DE632525D42442018F42BE502854AF02309BCDC9458B96B627265A4D2F - 9534205ED74BABBADB845C525D6B301AD03164C42F4FCE87DE14AD7A64CA17C2 - F78B9AF18D6C377D0F4E8BBEE2094C678A4CE9F651DF221CAC88849EE1A1D3E9 - 70F5EA950F3A3A2E6FA42D82BA2F2C2C2CBBA070496366BA95DDB5B41A167644 - B5F6F6A1643C47ECFFD9311BCE0F6722D512443817428B2B02B931DD78EDDB0E - 08127B8B8CEA1905630865AE3CEC3F1307AD1C5016C4EAEAAA755EAFF7F8CC3E - 05402101C8488FB901C07D1700935E467927879F7F9A05D61085AD4BDB616405 - BC7ACE0E569AC09E275A30CF16425060EE02F00F572EF69DB141AF1194D43B7F - F162C36AFAC733B38F42904221684D4A8CA110D4C3A673DE118269F64AD8FA5E - 323A3D69C8B47AF1C6130D18F3EBF1E2F185182652AEB7B7E285E56E7883B780 - DF0CC1C7BD853848BC51F4A3AEEEFC0B947A6FDEE15D62BC69C9D2475A2DD6B8 - 949D8F75C16E6EA130EA67DC19669070B4DE88D7CA73603499F0D3925694660C - 931831D85D361FA7AFC623DE3088031B3A10499D829F57C8379D968A0CFFB9B5 - 18279BF4084E5DEFABA9A95652CF716778D5345C782CC696FAD4A64702F856FC - 594AC3E9782AB2EB0BCAF8D1BBE918E293B138D98DDF3CDEA23EAE5854E9B010 - 885C88C4FC67165CC2D098041BF173D3121EFEA084EB41135EAE5A8ADE411E1D - 979BF7F4F5F56DFF62E55301D86CF1DFCDCEC97F675E6A38763C5C812876420D - 8362FD818A701C6AB0233A9CC5AF57372327DE4379AF55C185A8F0ED3A9107E7 - 7818BC93E3F0F21C526679F1F6C6AB30698328776560EFD964F0BE715F7575E5 - 63C160B0F69E00480BA2480B9A4C1131C99B974F6265ECE7249B7A38DC1A3C7F - 641E021A1B9ECCEEC3B647AFC02F686F1E839974E17063320E5D9843592223DA - 2460EE2C379E2BEC22D594F14A55212E39240C3ABB4EB4B5B5AEA323C17B0250 - 466242E2D6ACECBC3767CF8EC08E920E6484F7E3D250241A5C5698382D4A5287 - 610DE311923433C754659C34128054E42578A8405D872D22A0880D8E74CCC3E1 - 9A704A046FB0A6A66A9DCFE73B817B8C1900D4C57054984E455BE24BEC734CD8 - B2A81D49E113D4824D133240960B92A270CCF42995E6D37D2129377542B21A92 - 50C087B37D09F853790C756A3CDADA2EBDD5D7D7BB8D4EF0F705A00C83C19051 - 54B4E834678C4A9A9F66C2B3454ECC891CA5326B80ACD1DDD87E03C08DEF37B1 - 2875C017E471BA2B0E876B23C0533BD6EFEC296B6D6D798EFE75E24BC65D2D2D - E9C262F2C47B9C3132D932CB88B5797E14278F20C6A474315AA57ADC925BF28D - D221F979115D6E033EA19EA1B6430B860468A0BFF72C3DFE3CA55D1BEE33EED9 - 53731C97939565FFBD35366E9944D9906065919714C2DCD800628907D4D0A81D - AF27C0A07F5C8F9601035AFBB5540F04305250E8EABAF2576ABD77D35557F080 - 71BFA63ED266B36D494949DB6C0E8B4C97C972C5039C9E514BAB4C0002216ACB - 69529347BF7969D47DEDF3EEEEAEB73D1ECF87747EEC418F3F08C04D72A6582C - 96353131D695111111597ABDC14A65D500E55951F005027ED7D8D858D3C8C8B5 - B2C9C9C9725AEF03EEA84BFF1E80DB23433396A47B360130290BA2284E499244 - E51354C1E0FB1A77FD4B00FE23E37F0EE09F19A8E321D9E34DB9000000004945 - 4E44AE426082} - Stretch = True - Transparent = True - end - object lblTitle1: TLabel - Left = 12 - Top = 8 - Width = 116 - Height = 14 - Caption = 'License Agreement' - Font.Charset = DEFAULT_CHARSET - Font.Color = clWindowText - Font.Height = -12 - Font.Name = 'Tahoma' - Font.Style = [fsBold] - ParentFont = False - end - object lblSubTitle1: TLabel - Left = 22 - Top = 28 - Width = 408 - Height = 13 - Caption = - 'Please review the following license terms before installing Meta' + - 'mod:Source (version).' - end - object bvlSpacer1: TBevel - Left = 0 - Top = 46 - Width = 527 - Height = 3 - Align = alBottom - Shape = bsBottomLine - end - end - object freLicense: TmxFlatRichEdit - Left = 10 - Top = 62 - Width = 507 - Height = 207 - Lines.Strings = ( - 'The zlib/libpng License' - '' - 'Copyright (c) 2006, AlliedModders' - '' - - 'This software is provided '#39'as-is'#39', without any express or implie' + - 'd warranty. In no event will the ' - - 'authors be held liable for any damages arising from the use of t' + - 'his software.' - '' - - 'Permission is granted to anyone to use this software for any pur' + - 'pose, including commercial ' - - 'applications, and to alter it and redistribute it freely, subjec' + - 't to the following restrictions:' - '' - - ' 1. The origin of this software must not be misrepresented; y' + - 'ou must not claim that you wrote the ' - - 'original software. If you use this software in a product, an ack' + - 'nowledgment in the product ' - 'documentation would be appreciated but is not required.' - '' - - ' 2. Altered source versions must be plainly marked as such, a' + - 'nd must not be misrepresented as ' - 'being the original software.' - '' - - ' 3. This notice may not be removed or altered from any source' + - ' distribution.' - '') - ReadOnly = True - ScrollBars = ssVertical - TabOrder = 1 - Activate = True - BorderColor = clBtnShadow - Flat = True - ShowBorder = True - Version = '1.26' - end - object frbAgree: TFlatRadioButton - Left = 10 - Top = 274 - Width = 231 - Height = 17 - Caption = 'I accept the terms in the License Agreement' - TabOrder = 2 - OnClick = CheckNext - end - object ftbDontAgree: TFlatRadioButton - Left = 10 - Top = 290 - Width = 265 - Height = 17 - Caption = 'I do not accept the terms in the License Agreement' - Checked = True - TabOrder = 3 - TabStop = True - OnClick = CheckNext - end - end - object jspInstallMethod: TJvStandardPage - Left = 0 - Top = 0 - Width = 527 - Height = 314 - object lblInstallMethod: TLabel - Left = 124 - Top = 124 - Width = 144 - Height = 13 - Caption = 'Please select a install method:' - end - object pnlHeader2: TPanel - Left = 0 - Top = 0 - Width = 527 - Height = 49 - Align = alTop - BevelOuter = bvNone - Color = clWhite - TabOrder = 0 - object imgIcon2: TImage - Left = 486 - Top = 8 - Width = 32 - Height = 32 - AutoSize = True - Picture.Data = { - 0A54504E474F626A65637489504E470D0A1A0A0000000D494844520000002000 - 0000200806000000737A7AF40000000467414D410000AFC837058AE900000019 - 74455874536F6674776172650041646F626520496D616765526561647971C965 - 3C000008ED4944415478DAD556096C54D7153D7FE6CFFC59BC321EE3F1162F60 - 833DB6C10B019C60410007D43649518480B64924BAD0D00401A58AD456EA42A4 - 268A4848216D43054A55910588484A020D2EE09D181BDB78C106DB638FEDB1F1 - 18DBE3F12C7FFED2FBBFC1402090B46AAB3EE96966DEBCE5DC7BCF3DF732AB57 - 3F8EFFE6D06AB5686C6C80CBE5527F33FF8F00CC34B9AF7340969529836120B1 - 2C3BDED07001C3C3C35F19004B7339CDB5744911DD9328430E67C02817D264EE - 7B58926408A20893914320C08B3A1DDBD9D3D3BDB7B3B3E3FDAF02600341DF29 - 8872BE286BC1EA39707AFA6419D5A2202F83E74380C883D5021A0D73D7E346A3 - 1E3F78E69B489D930247B71307DEF9580182CB97DBB7381C3D7FF832007134F7 - 0BA2F494ACE1101F6B4656BC0F732CE3B09A791875324472ABC7CF6060C288F6 - E128740C6AE1F54E41AF9566BC120886B0A2380BDF5B5F8ADFED3B8A977EB20E - 474FD4E2A393B5049819AFACACB0DF0B400645EC3819362F26D68255760F8A13 - 5D88B725C2146B87C69C044617465B44C8C1318426AEC0E36A419B730A7FBFFA - 102E748A80E023B269542F994D9C1227F294803FEEDE80831F36A0ACBC590D49 - 7D7DDDFA2F02502C3FC70B4CC6FC0C2B36E5B6213BD10073E626B0519960345A - C892A0D00A924C618086EE26DF0B531086CEC1DD7E0CA77A5270AC2E0281A949 - C54A8ABF043E24E1575B164267B6E2B7FBCB2189210A234B002E6CBE1D8086E6 - DFC8F235F6F9B3F1C385E7911C1B0EA3FD456828759A1D22AE793420C354F215 - A6F230734A9C152611109D19D24407BC4D7B503698834395B3C0FB271122BC1B - 4B6D5856908C1D7B9BE0A330190D3A088218AAAAAA58C19496AE515D45F35951 - 940FC6C55BB1BDA41369BA361873B781E1ACD02288CFDA67C1311E01032B4224 - 721526B8919B14002FDE229E863523D47F0ABEDE933836B00A7F39A34141860E - AF6F5F884FEAFCE8EC19414B970703435E0C0D0D5636355D5CCBE4E717107B35 - E6A8A8E866B0E6B4CDAB24AC8CFA94DC351BBAF4F58A79D03012DA5D61180B18 - 31EC35C0E531C0C28DE3E9FC6BE40D8AF50C021DE4C93EF08E0F302E5AF04A4D - 31A6A6043C5A10A7440D1CC7A2B27114DDCE71345EACFBB1DBED7E8BD1EBF588 - 8B8B5B3F37D3FE6E669A053B1757221A2E30FA30B0B615605813794702AB91C1 - E944B40E46E2484B32B990C7A6050EA4C70AAA17981B00C4894E88A3F5F4A084 - F29102BC713A1641BF173733D4C8E9303939DE535B5B53425E77AACB0B16E4BF - 1F13F7D0D31B96C978D2F6992A9732B15C634E80262243BD4C3141A79531E4D1 - 615F7506A67816453627BEF3F02802218DCA03884188D79B2841FCAAFC8DF251 - 78B972097A9C93D0B1D308585687E6E6C657FBFB9DBB542122361A962C296E8B - B6C6A5EE5CD98B1C632318AD7EDAADF4B0C6685179408B30E9451CA88C468533 - 0D0612244E1EC32F4ABB1161A444080520FB06200B816952D2F11089C581D665 - 38D940DE632525D42442018F42BE502854AF02309BCDC9458B96B627265A4D2F - 9534205ED74BABBADB845C525D6B301AD03164C42F4FCE87DE14AD7A64CA17C2 - F78B9AF18D6C377D0F4E8BBEE2094C678A4CE9F651DF221CAC88849EE1A1D3E9 - 70F5EA950F3A3A2E6FA42D82BA2F2C2C2CBBA070496366BA95DDB5B41A167644 - B5F6F6A1643C47ECFFD9311BCE0F6722D512443817428B2B02B931DD78EDDB0E - 08127B8B8CEA1905630865AE3CEC3F1307AD1C5016C4EAEAAA755EAFF7F8CC3E - 05402101C8488FB901C07D1700935E467927879F7F9A05D61085AD4BDB616405 - BC7ACE0E569AC09E275A30CF16425060EE02F00F572EF69DB141AF1194D43B7F - F162C36AFAC733B38F42904221684D4A8CA110D4C3A673DE118269F64AD8FA5E - 323A3D69C8B47AF1C6130D18F3EBF1E2F185182652AEB7B7E285E56E7883B780 - DF0CC1C7BD853848BC51F4A3AEEEFC0B947A6FDEE15D62BC69C9D2475A2DD6B8 - 949D8F75C16E6EA130EA67DC19669070B4DE88D7CA73603499F0D3925694660C - 931831D85D361FA7AFC623DE3088031B3A10499D829F57C8379D968A0CFFB9B5 - 18279BF4084E5DEFABA9A95652CF716778D5345C782CC696FAD4A64702F856FC - 594AC3E9782AB2EB0BCAF8D1BBE918E293B138D98DDF3CDEA23EAE5854E9B010 - 885C88C4FC67165CC2D098041BF173D3121EFEA084EB41135EAE5A8ADE411E1D - 979BF7F4F5F56DFF62E55301D86CF1DFCDCEC97F675E6A38763C5C812876420D - 8362FD818A701C6AB0233A9CC5AF57372327DE4379AF55C185A8F0ED3A9107E7 - 7818BC93E3F0F21C526679F1F6C6AB30698328776560EFD964F0BE715F7575E5 - 63C160B0F69E00480BA2480B9A4C1131C99B974F6265ECE7249B7A38DC1A3C7F - 641E021A1B9ECCEEC3B647AFC02F686F1E839974E17063320E5D9843592223DA - 2460EE2C379E2BEC22D594F14A55212E39240C3ABB4EB4B5B5AEA323C17B0250 - 466242E2D6ACECBC3767CF8EC08E920E6484F7E3D250241A5C5698382D4A5287 - 610DE311923433C754659C34128054E42578A8405D872D22A0880D8E74CCC3E1 - 9A704A046FB0A6A66A9DCFE73B817B8C1900D4C57054984E455BE24BEC734CD8 - B2A81D49E113D4824D133240960B92A270CCF42995E6D37D2129377542B21A92 - 50C087B37D09F853790C756A3CDADA2EBDD5D7D7BB8D4EF0F705A00C83C19051 - 54B4E834678C4A9A9F66C2B3454ECC891CA5326B80ACD1DDD87E03C08DEF37B1 - 2875C017E471BA2B0E876B23C0533BD6EFEC296B6D6D798EFE75E24BC65D2D2D - E9C262F2C47B9C3132D932CB88B5797E14278F20C6A474315AA57ADC925BF28D - D221F979115D6E033EA19EA1B6430B860468A0BFF72C3DFE3CA55D1BEE33EED9 - 53731C97939565FFBD35366E9944D9906065919714C2DCD800628907D4D0A81D - AF27C0A07F5C8F9601035AFBB5540F04305250E8EABAF2576ABD77D35557F080 - 71BFA63ED266B36D494949DB6C0E8B4C97C972C5039C9E514BAB4C0002216ACB - 69529347BF7969D47DEDF3EEEEAEB73D1ECF87747EEC418F3F08C04D72A6582C - 96353131D695111111597ABDC14A65D500E55951F005027ED7D8D858D3C8C8B5 - B2C9C9C9725AEF03EEA84BFF1E80DB23433396A47B360130290BA2284E499244 - E51354C1E0FB1A77FD4B00FE23E37F0EE09F19A8E321D9E34DB9000000004945 - 4E44AE426082} - Transparent = True - end - object lblTitle2: TLabel - Left = 12 - Top = 8 - Width = 137 - Height = 14 - Caption = 'Choose install method' - Font.Charset = DEFAULT_CHARSET - Font.Color = clWindowText - Font.Height = -12 - Font.Name = 'Tahoma' - Font.Style = [fsBold] - ParentFont = False - end - object lblSubTitle2: TLabel - Left = 22 - Top = 28 - Width = 263 - Height = 13 - Caption = 'Choose a install method for installing Metamod:Source.' - end - object bvlSpacer2: TBevel - Left = 0 - Top = 46 - Width = 527 - Height = 3 - Align = alBottom - Shape = bsBottomLine - end - end - object pnlInstallMethod: TPanel - Left = 122 - Top = 142 - Width = 267 - Height = 97 - BevelOuter = bvLowered - TabOrder = 1 - object frbDedicatedServer: TFlatRadioButton - Left = 4 - Top = 4 - Width = 135 - Height = 17 - Caption = 'Steam Dedicated Server' - Checked = True - TabOrder = 0 - TabStop = True - end - object frbListenServer: TFlatRadioButton - Left = 4 - Top = 22 - Width = 115 - Height = 17 - Caption = 'Steam Listen Server' - TabOrder = 1 - end - object frbSelectMod: TFlatRadioButton - Left = 4 - Top = 58 - Width = 117 - Height = 17 - Caption = 'Select mod directory' - TabOrder = 3 - end - object frbFTP: TFlatRadioButton - Left = 4 - Top = 76 - Width = 35 - Height = 17 - Caption = 'FTP' - TabOrder = 4 - end - object frbStandaloneServer: TFlatRadioButton - Left = 4 - Top = 40 - Width = 107 - Height = 17 - Caption = 'Standalone Server' - TabOrder = 2 - end - end - end - object jspSelectMod: TJvStandardPage - Left = 0 - Top = 0 - Width = 527 - Height = 314 - object lblInfo: TLabel - Left = 138 - Top = 114 - Width = 255 - Height = 26 - Caption = - 'The following mods were detected. Please select the mod you want' + - ' to install Metamod:Source to:' - WordWrap = True - end - object shpMods: TShape - Left = 136 - Top = 142 - Width = 255 - Height = 104 - Pen.Color = clBtnShadow - end - object pnlSelectMod: TPanel - Left = 0 - Top = 0 - Width = 527 - Height = 49 - Align = alTop - BevelOuter = bvNone - Color = clWhite - TabOrder = 0 - object imgIcon5: TImage - Left = 486 - Top = 8 - Width = 32 - Height = 32 - AutoSize = True - Picture.Data = { - 0A54504E474F626A65637489504E470D0A1A0A0000000D494844520000002000 - 0000200806000000737A7AF40000000467414D410000AFC837058AE900000019 - 74455874536F6674776172650041646F626520496D616765526561647971C965 - 3C000008ED4944415478DAD556096C54D7153D7FE6CFFC59BC321EE3F1162F60 - 833DB6C10B019C60410007D43649518480B64924BAD0D00401A58AD456EA42A4 - 268A4848216D43054A55910588484A020D2EE09D181BDB78C106DB638FEDB1F1 - 18DBE3F12C7FFED2FBBFC1402090B46AAB3EE96966DEBCE5DC7BCF3DF732AB57 - 3F8EFFE6D06AB5686C6C80CBE5527F33FF8F00CC34B9AF7340969529836120B1 - 2C3BDED07001C3C3C35F19004B7339CDB5744911DD9328430E67C02817D264EE - 7B58926408A20893914320C08B3A1DDBD9D3D3BDB7B3B3E3FDAF02600341DF29 - 8872BE286BC1EA39707AFA6419D5A2202F83E74380C883D5021A0D73D7E346A3 - 1E3F78E69B489D930247B71307DEF9580182CB97DBB7381C3D7FF832007134F7 - 0BA2F494ACE1101F6B4656BC0F732CE3B09A791875324472ABC7CF6060C288F6 - E128740C6AE1F54E41AF9566BC120886B0A2380BDF5B5F8ADFED3B8A977EB20E - 474FD4E2A393B5049819AFACACB0DF0B400645EC3819362F26D68255760F8A13 - 5D88B725C2146B87C69C044617465B44C8C1318426AEC0E36A419B730A7FBFFA - 102E748A80E023B269542F994D9C1227F294803FEEDE80831F36A0ACBC590D49 - 7D7DDDFA2F02502C3FC70B4CC6FC0C2B36E5B6213BD10073E626B0519960345A - C892A0D00A924C618086EE26DF0B531086CEC1DD7E0CA77A5270AC2E0281A949 - C54A8ABF043E24E1575B164267B6E2B7FBCB2189210A234B002E6CBE1D8086E6 - DFC8F235F6F9B3F1C385E7911C1B0EA3FD456828759A1D22AE793420C354F215 - A6F230734A9C152611109D19D24407BC4D7B503698834395B3C0FB271122BC1B - 4B6D5856908C1D7B9BE0A330190D3A088218AAAAAA58C19496AE515D45F35951 - 940FC6C55BB1BDA41369BA361873B781E1ACD02288CFDA67C1311E01032B4224 - 721526B8919B14002FDE229E863523D47F0ABEDE933836B00A7F39A34141860E - AF6F5F884FEAFCE8EC19414B970703435E0C0D0D5636355D5CCBE4E717107B35 - E6A8A8E866B0E6B4CDAB24AC8CFA94DC351BBAF4F58A79D03012DA5D61180B18 - 31EC35C0E531C0C28DE3E9FC6BE40D8AF50C021DE4C93EF08E0F302E5AF04A4D - 31A6A6043C5A10A7440D1CC7A2B27114DDCE71345EACFBB1DBED7E8BD1EBF588 - 8B8B5B3F37D3FE6E669A053B1757221A2E30FA30B0B615605813794702AB91C1 - E944B40E46E2484B32B990C7A6050EA4C70AAA17981B00C4894E88A3F5F4A084 - F29102BC713A1641BF173733D4C8E9303939DE535B5B53425E77AACB0B16E4BF - 1F13F7D0D31B96C978D2F6992A9732B15C634E80262243BD4C3141A79531E4D1 - 615F7506A67816453627BEF3F02802218DCA03884188D79B2841FCAAFC8DF251 - 78B972097A9C93D0B1D308585687E6E6C657FBFB9DBB542122361A962C296E8B - B6C6A5EE5CD98B1C632318AD7EDAADF4B0C6685179408B30E9451CA88C468533 - 0D0612244E1EC32F4ABB1161A444080520FB06200B816952D2F11089C581D665 - 38D940DE632525D42442018F42BE502854AF02309BCDC9458B96B627265A4D2F - 9534205ED74BABBADB845C525D6B301AD03164C42F4FCE87DE14AD7A64CA17C2 - F78B9AF18D6C377D0F4E8BBEE2094C678A4CE9F651DF221CAC88849EE1A1D3E9 - 70F5EA950F3A3A2E6FA42D82BA2F2C2C2CBBA070496366BA95DDB5B41A167644 - B5F6F6A1643C47ECFFD9311BCE0F6722D512443817428B2B02B931DD78EDDB0E - 08127B8B8CEA1905630865AE3CEC3F1307AD1C5016C4EAEAAA755EAFF7F8CC3E - 05402101C8488FB901C07D1700935E467927879F7F9A05D61085AD4BDB616405 - BC7ACE0E569AC09E275A30CF16425060EE02F00F572EF69DB141AF1194D43B7F - F162C36AFAC733B38F42904221684D4A8CA110D4C3A673DE118269F64AD8FA5E - 323A3D69C8B47AF1C6130D18F3EBF1E2F185182652AEB7B7E285E56E7883B780 - DF0CC1C7BD853848BC51F4A3AEEEFC0B947A6FDEE15D62BC69C9D2475A2DD6B8 - 949D8F75C16E6EA130EA67DC19669070B4DE88D7CA73603499F0D3925694660C - 931831D85D361FA7AFC623DE3088031B3A10499D829F57C8379D968A0CFFB9B5 - 18279BF4084E5DEFABA9A95652CF716778D5345C782CC696FAD4A64702F856FC - 594AC3E9782AB2EB0BCAF8D1BBE918E293B138D98DDF3CDEA23EAE5854E9B010 - 885C88C4FC67165CC2D098041BF173D3121EFEA084EB41135EAE5A8ADE411E1D - 979BF7F4F5F56DFF62E55301D86CF1DFCDCEC97F675E6A38763C5C812876420D - 8362FD818A701C6AB0233A9CC5AF57372327DE4379AF55C185A8F0ED3A9107E7 - 7818BC93E3F0F21C526679F1F6C6AB30698328776560EFD964F0BE715F7575E5 - 63C160B0F69E00480BA2480B9A4C1131C99B974F6265ECE7249B7A38DC1A3C7F - 641E021A1B9ECCEEC3B647AFC02F686F1E839974E17063320E5D9843592223DA - 2460EE2C379E2BEC22D594F14A55212E39240C3ABB4EB4B5B5AEA323C17B0250 - 466242E2D6ACECBC3767CF8EC08E920E6484F7E3D250241A5C5698382D4A5287 - 610DE311923433C754659C34128054E42578A8405D872D22A0880D8E74CCC3E1 - 9A704A046FB0A6A66A9DCFE73B817B8C1900D4C57054984E455BE24BEC734CD8 - B2A81D49E113D4824D133240960B92A270CCF42995E6D37D2129377542B21A92 - 50C087B37D09F853790C756A3CDADA2EBDD5D7D7BB8D4EF0F705A00C83C19051 - 54B4E834678C4A9A9F66C2B3454ECC891CA5326B80ACD1DDD87E03C08DEF37B1 - 2875C017E471BA2B0E876B23C0533BD6EFEC296B6D6D798EFE75E24BC65D2D2D - E9C262F2C47B9C3132D932CB88B5797E14278F20C6A474315AA57ADC925BF28D - D221F979115D6E033EA19EA1B6430B860468A0BFF72C3DFE3CA55D1BEE33EED9 - 53731C97939565FFBD35366E9944D9906065919714C2DCD800628907D4D0A81D - AF27C0A07F5C8F9601035AFBB5540F04305250E8EABAF2576ABD77D35557F080 - 71BFA63ED266B36D494949DB6C0E8B4C97C972C5039C9E514BAB4C0002216ACB - 69529347BF7969D47DEDF3EEEEAEB73D1ECF87747EEC418F3F08C04D72A6582C - 96353131D695111111597ABDC14A65D500E55951F005027ED7D8D858D3C8C8B5 - B2C9C9C9725AEF03EEA84BFF1E80DB23433396A47B360130290BA2284E499244 - E51354C1E0FB1A77FD4B00FE23E37F0EE09F19A8E321D9E34DB9000000004945 - 4E44AE426082} - Stretch = True - Transparent = True - end - object lblSelectMod: TLabel - Left = 12 - Top = 8 - Width = 68 - Height = 14 - Caption = 'Select Mod' - Font.Charset = DEFAULT_CHARSET - Font.Color = clWindowText - Font.Height = -12 - Font.Name = 'Tahoma' - Font.Style = [fsBold] - ParentFont = False - end - object lblSelectModInfo: TLabel - Left = 22 - Top = 28 - Width = 332 - Height = 13 - Caption = - 'Please select the mod Metamod:Source (version) shall be installe' + - 'd to.' - end - object bvlSelectMod: TBevel - Left = 0 - Top = 46 - Width = 527 - Height = 3 - Align = alBottom - Shape = bsBottomLine - end - end - object trvMods: TTreeView - Left = 137 - Top = 143 - Width = 253 - Height = 102 - BorderStyle = bsNone - Indent = 19 - MultiSelectStyle = [] - ReadOnly = True - RightClickSelect = True - RowSelect = True - TabOrder = 1 - OnClick = trvModsClick - end - end - object jspFTP: TJvStandardPage - Left = 0 - Top = 0 - Width = 527 - Height = 314 - object lblStep1: TLabel - Left = 44 - Top = 56 - Width = 100 - Height = 13 - Caption = '1. Set your FTP data' - end - object lblStep2: TLabel - Left = 44 - Top = 146 - Width = 244 - Height = 13 - Caption = '2. Connect to server and select the mod directory:' - end - object lblStep4: TLabel - Left = 44 - Top = 296 - Width = 64 - Height = 13 - Caption = '4. Click Next.' - end - object lblStep3: TLabel - Left = 44 - Top = 252 - Width = 223 - Height = 13 - Caption = '3. Select the operating system of your server:' - end - object pnlHeader3: TPanel - Left = 0 - Top = 0 - Width = 527 - Height = 49 - Align = alTop - BevelOuter = bvNone - Color = clWhite - TabOrder = 0 - object imgIcon3: TImage - Left = 486 - Top = 8 - Width = 32 - Height = 32 - AutoSize = True - Picture.Data = { - 0A54504E474F626A65637489504E470D0A1A0A0000000D494844520000002000 - 0000200806000000737A7AF40000000467414D410000AFC837058AE900000019 - 74455874536F6674776172650041646F626520496D616765526561647971C965 - 3C000008ED4944415478DAD556096C54D7153D7FE6CFFC59BC321EE3F1162F60 - 833DB6C10B019C60410007D43649518480B64924BAD0D00401A58AD456EA42A4 - 268A4848216D43054A55910588484A020D2EE09D181BDB78C106DB638FEDB1F1 - 18DBE3F12C7FFED2FBBFC1402090B46AAB3EE96966DEBCE5DC7BCF3DF732AB57 - 3F8EFFE6D06AB5686C6C80CBE5527F33FF8F00CC34B9AF7340969529836120B1 - 2C3BDED07001C3C3C35F19004B7339CDB5744911DD9328430E67C02817D264EE - 7B58926408A20893914320C08B3A1DDBD9D3D3BDB7B3B3E3FDAF02600341DF29 - 8872BE286BC1EA39707AFA6419D5A2202F83E74380C883D5021A0D73D7E346A3 - 1E3F78E69B489D930247B71307DEF9580182CB97DBB7381C3D7FF832007134F7 - 0BA2F494ACE1101F6B4656BC0F732CE3B09A791875324472ABC7CF6060C288F6 - E128740C6AE1F54E41AF9566BC120886B0A2380BDF5B5F8ADFED3B8A977EB20E - 474FD4E2A393B5049819AFACACB0DF0B400645EC3819362F26D68255760F8A13 - 5D88B725C2146B87C69C044617465B44C8C1318426AEC0E36A419B730A7FBFFA - 102E748A80E023B269542F994D9C1227F294803FEEDE80831F36A0ACBC590D49 - 7D7DDDFA2F02502C3FC70B4CC6FC0C2B36E5B6213BD10073E626B0519960345A - C892A0D00A924C618086EE26DF0B531086CEC1DD7E0CA77A5270AC2E0281A949 - C54A8ABF043E24E1575B164267B6E2B7FBCB2189210A234B002E6CBE1D8086E6 - DFC8F235F6F9B3F1C385E7911C1B0EA3FD456828759A1D22AE793420C354F215 - A6F230734A9C152611109D19D24407BC4D7B503698834395B3C0FB271122BC1B - 4B6D5856908C1D7B9BE0A330190D3A088218AAAAAA58C19496AE515D45F35951 - 940FC6C55BB1BDA41369BA361873B781E1ACD02288CFDA67C1311E01032B4224 - 721526B8919B14002FDE229E863523D47F0ABEDE933836B00A7F39A34141860E - AF6F5F884FEAFCE8EC19414B970703435E0C0D0D5636355D5CCBE4E717107B35 - E6A8A8E866B0E6B4CDAB24AC8CFA94DC351BBAF4F58A79D03012DA5D61180B18 - 31EC35C0E531C0C28DE3E9FC6BE40D8AF50C021DE4C93EF08E0F302E5AF04A4D - 31A6A6043C5A10A7440D1CC7A2B27114DDCE71345EACFBB1DBED7E8BD1EBF588 - 8B8B5B3F37D3FE6E669A053B1757221A2E30FA30B0B615605813794702AB91C1 - E944B40E46E2484B32B990C7A6050EA4C70AAA17981B00C4894E88A3F5F4A084 - F29102BC713A1641BF173733D4C8E9303939DE535B5B53425E77AACB0B16E4BF - 1F13F7D0D31B96C978D2F6992A9732B15C634E80262243BD4C3141A79531E4D1 - 615F7506A67816453627BEF3F02802218DCA03884188D79B2841FCAAFC8DF251 - 78B972097A9C93D0B1D308585687E6E6C657FBFB9DBB542122361A962C296E8B - B6C6A5EE5CD98B1C632318AD7EDAADF4B0C6685179408B30E9451CA88C468533 - 0D0612244E1EC32F4ABB1161A444080520FB06200B816952D2F11089C581D665 - 38D940DE632525D42442018F42BE502854AF02309BCDC9458B96B627265A4D2F - 9534205ED74BABBADB845C525D6B301AD03164C42F4FCE87DE14AD7A64CA17C2 - F78B9AF18D6C377D0F4E8BBEE2094C678A4CE9F651DF221CAC88849EE1A1D3E9 - 70F5EA950F3A3A2E6FA42D82BA2F2C2C2CBBA070496366BA95DDB5B41A167644 - B5F6F6A1643C47ECFFD9311BCE0F6722D512443817428B2B02B931DD78EDDB0E - 08127B8B8CEA1905630865AE3CEC3F1307AD1C5016C4EAEAAA755EAFF7F8CC3E - 05402101C8488FB901C07D1700935E467927879F7F9A05D61085AD4BDB616405 - BC7ACE0E569AC09E275A30CF16425060EE02F00F572EF69DB141AF1194D43B7F - F162C36AFAC733B38F42904221684D4A8CA110D4C3A673DE118269F64AD8FA5E - 323A3D69C8B47AF1C6130D18F3EBF1E2F185182652AEB7B7E285E56E7883B780 - DF0CC1C7BD853848BC51F4A3AEEEFC0B947A6FDEE15D62BC69C9D2475A2DD6B8 - 949D8F75C16E6EA130EA67DC19669070B4DE88D7CA73603499F0D3925694660C - 931831D85D361FA7AFC623DE3088031B3A10499D829F57C8379D968A0CFFB9B5 - 18279BF4084E5DEFABA9A95652CF716778D5345C782CC696FAD4A64702F856FC - 594AC3E9782AB2EB0BCAF8D1BBE918E293B138D98DDF3CDEA23EAE5854E9B010 - 885C88C4FC67165CC2D098041BF173D3121EFEA084EB41135EAE5A8ADE411E1D - 979BF7F4F5F56DFF62E55301D86CF1DFCDCEC97F675E6A38763C5C812876420D - 8362FD818A701C6AB0233A9CC5AF57372327DE4379AF55C185A8F0ED3A9107E7 - 7818BC93E3F0F21C526679F1F6C6AB30698328776560EFD964F0BE715F7575E5 - 63C160B0F69E00480BA2480B9A4C1131C99B974F6265ECE7249B7A38DC1A3C7F - 641E021A1B9ECCEEC3B647AFC02F686F1E839974E17063320E5D9843592223DA - 2460EE2C379E2BEC22D594F14A55212E39240C3ABB4EB4B5B5AEA323C17B0250 - 466242E2D6ACECBC3767CF8EC08E920E6484F7E3D250241A5C5698382D4A5287 - 610DE311923433C754659C34128054E42578A8405D872D22A0880D8E74CCC3E1 - 9A704A046FB0A6A66A9DCFE73B817B8C1900D4C57054984E455BE24BEC734CD8 - B2A81D49E113D4824D133240960B92A270CCF42995E6D37D2129377542B21A92 - 50C087B37D09F853790C756A3CDADA2EBDD5D7D7BB8D4EF0F705A00C83C19051 - 54B4E834678C4A9A9F66C2B3454ECC891CA5326B80ACD1DDD87E03C08DEF37B1 - 2875C017E471BA2B0E876B23C0533BD6EFEC296B6D6D798EFE75E24BC65D2D2D - E9C262F2C47B9C3132D932CB88B5797E14278F20C6A474315AA57ADC925BF28D - D221F979115D6E033EA19EA1B6430B860468A0BFF72C3DFE3CA55D1BEE33EED9 - 53731C97939565FFBD35366E9944D9906065919714C2DCD800628907D4D0A81D - AF27C0A07F5C8F9601035AFBB5540F04305250E8EABAF2576ABD77D35557F080 - 71BFA63ED266B36D494949DB6C0E8B4C97C972C5039C9E514BAB4C0002216ACB - 69529347BF7969D47DEDF3EEEEAEB73D1ECF87747EEC418F3F08C04D72A6582C - 96353131D695111111597ABDC14A65D500E55951F005027ED7D8D858D3C8C8B5 - B2C9C9C9725AEF03EEA84BFF1E80DB23433396A47B360130290BA2284E499244 - E51354C1E0FB1A77FD4B00FE23E37F0EE09F19A8E321D9E34DB9000000004945 - 4E44AE426082} - Transparent = True - end - object lblTitle3: TLabel - Left = 12 - Top = 8 - Width = 269 - Height = 14 - Caption = 'Installing Metamod:Source (version) via FTP' - Font.Charset = DEFAULT_CHARSET - Font.Color = clWindowText - Font.Height = -12 - Font.Name = 'Tahoma' - Font.Style = [fsBold] - ParentFont = False - end - object lblSubTitle3: TLabel - Left = 22 - Top = 28 - Width = 189 - Height = 13 - Caption = 'Do the following steps and press Next. ' - end - object bvlSpacer3: TBevel - Left = 0 - Top = 46 - Width = 527 - Height = 3 - Align = alBottom - Shape = bsBottomLine - end - end - object pnlFTPData: TPanel - Left = 44 - Top = 72 - Width = 441 - Height = 64 - BevelOuter = bvLowered - TabOrder = 1 - object lblHost: TLabel - Left = 4 - Top = 4 - Width = 26 - Height = 13 - Caption = 'Host:' - end - object lblUserName: TLabel - Left = 180 - Top = 6 - Width = 52 - Height = 13 - Caption = 'Username:' - end - object lblPassword: TLabel - Left = 308 - Top = 4 - Width = 50 - Height = 13 - Caption = 'Password:' - end - object lblPort: TLabel - Left = 132 - Top = 4 - Width = 24 - Height = 13 - Caption = 'Port:' - end - object txtHost: TFlatEdit - Left = 4 - Top = 20 - Width = 121 - Height = 19 - ColorFlat = clBtnFace - ParentColor = True - TabOrder = 0 - end - object txtUserName: TFlatEdit - Left = 180 - Top = 20 - Width = 121 - Height = 19 - ColorFlat = clBtnFace - ParentColor = True - TabOrder = 2 - end - object txtPassword: TFlatEdit - Left = 308 - Top = 20 - Width = 127 - Height = 19 - ColorFlat = clBtnFace - ParentColor = True - PasswordChar = '*' - TabOrder = 3 - end - object txtPort: TFlatEdit - Left = 132 - Top = 20 - Width = 43 - Height = 19 - ColorFlat = clBtnFace - ParentColor = True - MaxLength = 5 - TabOrder = 1 - Text = '21' - OnChange = txtPortChange - end - object chkPassive: TFlatCheckBox - Left = 4 - Top = 44 - Width = 139 - Height = 16 - Caption = 'Use PASV (Passive) Mode' - Checked = True - TabOrder = 4 - TabStop = True - end - object cmdProxySettings: TFlatButton - Left = 350 - Top = 42 - Width = 83 - Height = 18 - ColorFocused = 16245198 - ColorDown = 16245198 - ColorHighLight = 8623776 - ColorShadow = 8623776 - Caption = 'Proxy-Settings' - TabOrder = 5 - OnClick = cmdProxySettingsClick - end - end - object cmdConnect: TFlatButton - Left = 416 - Top = 161 - Width = 71 - Height = 20 - ColorFocused = 16245198 - ColorDown = 16245198 - ColorBorder = clBtnShadow - ColorHighLight = clBtnShadow - ColorShadow = clBtnShadow - Caption = 'Connect' - TabOrder = 3 - OnClick = cmdConnectClick - end - object pnlDirectory: TPanel - Left = 44 - Top = 162 - Width = 367 - Height = 83 - BevelOuter = bvLowered - TabOrder = 2 - object trvDirectories: TTreeView - Left = 1 - Top = 1 - Width = 365 - Height = 81 - Align = alClient - BorderStyle = bsNone - Images = ilImages - Indent = 19 - TabOrder = 0 - OnChange = trvDirectoriesChange - OnCollapsing = trvDirectoriesCollapsing - OnExpanding = trvDirectoriesExpanding - OnExpanded = trvDirectoriesExpanded - OnMouseDown = trvDirectoriesMouseDown - end - end - object pnlOS: TPanel - Left = 44 - Top = 268 - Width = 441 - Height = 21 - BevelOuter = bvLowered - TabOrder = 4 - object optWindows: TFlatRadioButton - Left = 1 - Top = 3 - Width = 62 - Height = 14 - Caption = 'Windows' - Checked = True - TabOrder = 0 - TabStop = True - end - object optLinux: TFlatRadioButton - Left = 173 - Top = 3 - Width = 82 - Height = 14 - Caption = 'Linux (32-bit)' - TabOrder = 1 - end - object FlatRadioButton1: TFlatRadioButton - Left = 353 - Top = 3 - Width = 82 - Height = 14 - Caption = 'Linux (64-bit)' - Enabled = False - TabOrder = 2 - end - end - end - object jspInstallProgress: TJvStandardPage - Left = 0 - Top = 0 - Width = 527 - Height = 314 - Caption = 'jspInstallProgress' - object ggeAll: TFlatGauge - Left = 8 - Top = 84 - Width = 509 - Height = 24 - AdvColorBorder = 0 - Color = clBtnFace - ColorBorder = 8623776 - MaxValue = 8 - Progress = 0 - Font.Charset = DEFAULT_CHARSET - Font.Color = clWindowText - Font.Height = -9 - Font.Name = 'Tahoma' - Font.Style = [] - ParentColor = False - ParentFont = False - end - object lblProgress: TLabel - Left = 8 - Top = 66 - Width = 46 - Height = 13 - Caption = 'Progress:' - end - object ggeItem: TFlatGauge - Left = 8 - Top = 112 - Width = 509 - Height = 24 - AdvColorBorder = 0 - Color = clBtnFace - ColorBorder = 8623776 - Progress = 0 - Font.Charset = DEFAULT_CHARSET - Font.Color = clWindowText - Font.Height = -9 - Font.Name = 'Tahoma' - Font.Style = [] - ParentColor = False - ParentFont = False - end - object lblDetails: TLabel - Left = 10 - Top = 152 - Width = 36 - Height = 13 - Caption = 'Details:' - end - object bvlSpace2: TBevel - Left = 4 - Top = 142 - Width = 519 - Height = 3 - Shape = bsTopLine - end - object pnlHeader5: TPanel - Left = 0 - Top = 0 - Width = 527 - Height = 49 - Align = alTop - BevelOuter = bvNone - Color = clWhite - TabOrder = 0 - object imgIcon4: TImage - Left = 486 - Top = 8 - Width = 32 - Height = 32 - AutoSize = True - Picture.Data = { - 0A54504E474F626A65637489504E470D0A1A0A0000000D494844520000002000 - 0000200806000000737A7AF40000000467414D410000AFC837058AE900000019 - 74455874536F6674776172650041646F626520496D616765526561647971C965 - 3C000008ED4944415478DAD556096C54D7153D7FE6CFFC59BC321EE3F1162F60 - 833DB6C10B019C60410007D43649518480B64924BAD0D00401A58AD456EA42A4 - 268A4848216D43054A55910588484A020D2EE09D181BDB78C106DB638FEDB1F1 - 18DBE3F12C7FFED2FBBFC1402090B46AAB3EE96966DEBCE5DC7BCF3DF732AB57 - 3F8EFFE6D06AB5686C6C80CBE5527F33FF8F00CC34B9AF7340969529836120B1 - 2C3BDED07001C3C3C35F19004B7339CDB5744911DD9328430E67C02817D264EE - 7B58926408A20893914320C08B3A1DDBD9D3D3BDB7B3B3E3FDAF02600341DF29 - 8872BE286BC1EA39707AFA6419D5A2202F83E74380C883D5021A0D73D7E346A3 - 1E3F78E69B489D930247B71307DEF9580182CB97DBB7381C3D7FF832007134F7 - 0BA2F494ACE1101F6B4656BC0F732CE3B09A791875324472ABC7CF6060C288F6 - E128740C6AE1F54E41AF9566BC120886B0A2380BDF5B5F8ADFED3B8A977EB20E - 474FD4E2A393B5049819AFACACB0DF0B400645EC3819362F26D68255760F8A13 - 5D88B725C2146B87C69C044617465B44C8C1318426AEC0E36A419B730A7FBFFA - 102E748A80E023B269542F994D9C1227F294803FEEDE80831F36A0ACBC590D49 - 7D7DDDFA2F02502C3FC70B4CC6FC0C2B36E5B6213BD10073E626B0519960345A - C892A0D00A924C618086EE26DF0B531086CEC1DD7E0CA77A5270AC2E0281A949 - C54A8ABF043E24E1575B164267B6E2B7FBCB2189210A234B002E6CBE1D8086E6 - DFC8F235F6F9B3F1C385E7911C1B0EA3FD456828759A1D22AE793420C354F215 - A6F230734A9C152611109D19D24407BC4D7B503698834395B3C0FB271122BC1B - 4B6D5856908C1D7B9BE0A330190D3A088218AAAAAA58C19496AE515D45F35951 - 940FC6C55BB1BDA41369BA361873B781E1ACD02288CFDA67C1311E01032B4224 - 721526B8919B14002FDE229E863523D47F0ABEDE933836B00A7F39A34141860E - AF6F5F884FEAFCE8EC19414B970703435E0C0D0D5636355D5CCBE4E717107B35 - E6A8A8E866B0E6B4CDAB24AC8CFA94DC351BBAF4F58A79D03012DA5D61180B18 - 31EC35C0E531C0C28DE3E9FC6BE40D8AF50C021DE4C93EF08E0F302E5AF04A4D - 31A6A6043C5A10A7440D1CC7A2B27114DDCE71345EACFBB1DBED7E8BD1EBF588 - 8B8B5B3F37D3FE6E669A053B1757221A2E30FA30B0B615605813794702AB91C1 - E944B40E46E2484B32B990C7A6050EA4C70AAA17981B00C4894E88A3F5F4A084 - F29102BC713A1641BF173733D4C8E9303939DE535B5B53425E77AACB0B16E4BF - 1F13F7D0D31B96C978D2F6992A9732B15C634E80262243BD4C3141A79531E4D1 - 615F7506A67816453627BEF3F02802218DCA03884188D79B2841FCAAFC8DF251 - 78B972097A9C93D0B1D308585687E6E6C657FBFB9DBB542122361A962C296E8B - B6C6A5EE5CD98B1C632318AD7EDAADF4B0C6685179408B30E9451CA88C468533 - 0D0612244E1EC32F4ABB1161A444080520FB06200B816952D2F11089C581D665 - 38D940DE632525D42442018F42BE502854AF02309BCDC9458B96B627265A4D2F - 9534205ED74BABBADB845C525D6B301AD03164C42F4FCE87DE14AD7A64CA17C2 - F78B9AF18D6C377D0F4E8BBEE2094C678A4CE9F651DF221CAC88849EE1A1D3E9 - 70F5EA950F3A3A2E6FA42D82BA2F2C2C2CBBA070496366BA95DDB5B41A167644 - B5F6F6A1643C47ECFFD9311BCE0F6722D512443817428B2B02B931DD78EDDB0E - 08127B8B8CEA1905630865AE3CEC3F1307AD1C5016C4EAEAAA755EAFF7F8CC3E - 05402101C8488FB901C07D1700935E467927879F7F9A05D61085AD4BDB616405 - BC7ACE0E569AC09E275A30CF16425060EE02F00F572EF69DB141AF1194D43B7F - F162C36AFAC733B38F42904221684D4A8CA110D4C3A673DE118269F64AD8FA5E - 323A3D69C8B47AF1C6130D18F3EBF1E2F185182652AEB7B7E285E56E7883B780 - DF0CC1C7BD853848BC51F4A3AEEEFC0B947A6FDEE15D62BC69C9D2475A2DD6B8 - 949D8F75C16E6EA130EA67DC19669070B4DE88D7CA73603499F0D3925694660C - 931831D85D361FA7AFC623DE3088031B3A10499D829F57C8379D968A0CFFB9B5 - 18279BF4084E5DEFABA9A95652CF716778D5345C782CC696FAD4A64702F856FC - 594AC3E9782AB2EB0BCAF8D1BBE918E293B138D98DDF3CDEA23EAE5854E9B010 - 885C88C4FC67165CC2D098041BF173D3121EFEA084EB41135EAE5A8ADE411E1D - 979BF7F4F5F56DFF62E55301D86CF1DFCDCEC97F675E6A38763C5C812876420D - 8362FD818A701C6AB0233A9CC5AF57372327DE4379AF55C185A8F0ED3A9107E7 - 7818BC93E3F0F21C526679F1F6C6AB30698328776560EFD964F0BE715F7575E5 - 63C160B0F69E00480BA2480B9A4C1131C99B974F6265ECE7249B7A38DC1A3C7F - 641E021A1B9ECCEEC3B647AFC02F686F1E839974E17063320E5D9843592223DA - 2460EE2C379E2BEC22D594F14A55212E39240C3ABB4EB4B5B5AEA323C17B0250 - 466242E2D6ACECBC3767CF8EC08E920E6484F7E3D250241A5C5698382D4A5287 - 610DE311923433C754659C34128054E42578A8405D872D22A0880D8E74CCC3E1 - 9A704A046FB0A6A66A9DCFE73B817B8C1900D4C57054984E455BE24BEC734CD8 - B2A81D49E113D4824D133240960B92A270CCF42995E6D37D2129377542B21A92 - 50C087B37D09F853790C756A3CDADA2EBDD5D7D7BB8D4EF0F705A00C83C19051 - 54B4E834678C4A9A9F66C2B3454ECC891CA5326B80ACD1DDD87E03C08DEF37B1 - 2875C017E471BA2B0E876B23C0533BD6EFEC296B6D6D798EFE75E24BC65D2D2D - E9C262F2C47B9C3132D932CB88B5797E14278F20C6A474315AA57ADC925BF28D - D221F979115D6E033EA19EA1B6430B860468A0BFF72C3DFE3CA55D1BEE33EED9 - 53731C97939565FFBD35366E9944D9906065919714C2DCD800628907D4D0A81D - AF27C0A07F5C8F9601035AFBB5540F04305250E8EABAF2576ABD77D35557F080 - 71BFA63ED266B36D494949DB6C0E8B4C97C972C5039C9E514BAB4C0002216ACB - 69529347BF7969D47DEDF3EEEEAEB73D1ECF87747EEC418F3F08C04D72A6582C - 96353131D695111111597ABDC14A65D500E55951F005027ED7D8D858D3C8C8B5 - B2C9C9C9725AEF03EEA84BFF1E80DB23433396A47B360130290BA2284E499244 - E51354C1E0FB1A77FD4B00FE23E37F0EE09F19A8E321D9E34DB9000000004945 - 4E44AE426082} - Transparent = True - end - object lblTitle5: TLabel - Left = 12 - Top = 8 - Width = 223 - Height = 14 - Caption = 'Installing Metamod:Source (version)' - Font.Charset = DEFAULT_CHARSET - Font.Color = clWindowText - Font.Height = -12 - Font.Name = 'Tahoma' - Font.Style = [fsBold] - ParentFont = False - end - object lblSubTitle5: TLabel - Left = 22 - Top = 28 - Width = 296 - Height = 13 - Caption = 'Please wait while Metamod:Source (version) is being installed.' - end - object bvlSpacer5: TBevel - Left = 0 - Top = 46 - Width = 527 - Height = 3 - Align = alBottom - Shape = bsBottomLine - end - end - object rtfDetails: TmxFlatRichEdit - Left = 8 - Top = 166 - Width = 509 - Height = 139 - ReadOnly = True - ScrollBars = ssVertical - TabOrder = 1 - Activate = True - BorderColor = clBtnShadow - Flat = True - ShowBorder = True - Version = '1.26' - end - end - end - object pnlButtons: TPanel - Left = 0 - Top = 317 - Width = 527 - Height = 38 - Align = alBottom - BevelOuter = bvNone - TabOrder = 1 - object cmdNext: TFlatButton - Left = 438 - Top = 7 - Width = 85 - Height = 25 - ColorFocused = 16245198 - ColorDown = 16245198 - ColorBorder = clBtnShadow - ColorHighLight = clBtnShadow - ColorShadow = clBtnShadow - Caption = '&Next >' - TabOrder = 0 - OnClick = cmdNextClick - end - object cmdCancel: TFlatButton - Left = 4 - Top = 7 - Width = 85 - Height = 25 - Color = clBtnFace - ColorFocused = 16245198 - ColorDown = 16245198 - ColorBorder = clBtnShadow - ColorHighLight = clBtnShadow - ColorShadow = clBtnShadow - Caption = '&Cancel' - ParentColor = False - TabOrder = 1 - OnClick = cmdCancelClick - end - object cmdBack: TFlatButton - Left = 348 - Top = 7 - Width = 85 - Height = 25 - ColorFocused = 16245198 - ColorDown = 16245198 - ColorBorder = clBtnShadow - ColorHighLight = clBtnShadow - ColorShadow = clBtnShadow - Caption = '< &Back' - TabOrder = 2 - Visible = False - OnClick = cmdBackClick - end - end - object ilImages: TImageList - Left = 154 - Top = 324 - Bitmap = { - 494C010102000400040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600 - 0000000000003600000028000000400000001000000001002000000000000010 - 00000000000000000000000000000000000000000000008CBD00008CBD00008C - BD00008CBD00008CBD00008CBD00008CBD00008CBD00008CBD00008CBD00008C - BD00008CBD00008CBD00000000000000000000000000008CBD00008CBD00008C - BD00008CBD00008CBD00008CBD00008CBD00008CBD00008CBD00008CBD00008C - BD00008CBD000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000008CBD0063CEF700008CBD00A5F7 - FF0063CEF70063CEF70063CEF70063CEF70063CEF70063CEF70063CEF70063CE - F70039ADDE00ADF7FF00008CBD0000000000008CBD0021A5CE005ACEEF0084E7 - FF0063CEF70063CEF70063CEF70063CEF70063CEF70063CEF70063CEF70063CE - F70039ADDE001094C60000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000008CBD006BD6F700008CBD00ADF7 - FF006BD6FF006BD6FF006BD6FF006BD6FF006BD6FF006BD6FF006BD6FF006BD6 - FF0039ADDE00BDEFF700008CBD0000000000008CBD004ABDE70031ADD60094EF - FF006BD6FF006BD6FF006BD6FF006BD6FF006BD6FF006BD6FF006BD6FF006BD6 - FF0039B5DE00CEF7FF00008CBD00000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000008CBD0073D6FF00008CBD00ADF7 - FF007BDEFF007BDEFF007BDEFF007BDEFF007BDEFF007BDEFF007BDEFF007BDE - FF0042B5DE00BDEFF700008CBD0000000000008CBD0073D6FF00008CBD00ADFF - FF007BDEFF007BDEFF007BDEFF007BDEFF007BDEFF007BDEFF007BDEFF007BDE - FF0042B5DE00CEF7FF00008CBD00000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000008CBD007BDEFF00008CBD00B5F7 - FF0084E7FF0084E7FF0084E7FF0084E7FF0084E7FF0084E7FF0084E7FF0084E7 - FF0042B5DE00C6F7F700008CBD0000000000008CBD007BDEFF001094C60094EF - FF0094EFFF0084E7FF0084E7FF0084E7FF0084E7FF0084E7FF0084E7FF0084E7 - FF004ABDE700CEF7FF001094C600000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000008CBD0084E7FF00008CBD00BDF7 - FF008CEFFF008CEFFF008CEFFF008CEFFF008CEFFF008CEFFF008CEFFF008CEF - FF004ABDE700BDF7FF00008CBD0000000000008CBD0084E7FF0042B5DE005AC6 - EF00ADFFFF008CEFFF008CEFFF008CEFFF008CEFFF008CEFFF008CEFFF008CEF - FF004ABDE700CEF7FF00CEF7FF00008CBD000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000008CBD008CEFFF00008CBD00D6F7 - FF00CEF7FF00CEF7FF00CEF7FF00CEF7FF00CEF7FF00CEF7FF00CEF7FF00CEF7 - FF00BDDEDE00D6F7FF00008CBD0000000000008CBD008CE7FF007BDEFF0021A5 - CE00E7FFFF00CEF7FF00CEF7FF00CEF7FF00CEF7FF00CEF7FF00CEF7FF00CEF7 - FF0094EFFF00E7FFFF00CEF7FF00008CBD000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000008CBD0094F7FF00008CBD00008C - BD00008CBD00008CBD00008CBD00008CBD00008CBD00008CBD00008CBD00008C - BD00008CBD00008CBD00008CBD0000000000008CBD0094F7FF0094F7FF001094 - C600008CBD00008CBD00008CBD00008CBD00008CBD00008CBD00008CBD00008C - BD00008CBD00008CBD00008CBD00008CBD000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000008CBD009CF7FF009CF7FF009CF7 - FF009CF7FF009CF7FF009CF7FF009CF7FF009CF7FF009CF7FF009CF7FF009CF7 - FF00008CBD00000000000000000000000000008CBD009CF7FF009CF7FF009CF7 - FF009CF7FF009CF7FF009CF7FF009CF7FF009CF7FF009CF7FF009CF7FF009CF7 - FF00088CBD000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000008CBD00D6F7FF00A5F7FF00A5F7 - FF00A5F7FF00A5F7FF00A5F7FF00A5F7FF00A5F7FF00A5F7FF00A5F7FF00A5F7 - FF00008CBD00000000000000000000000000008CBD00E7FFFF00A5FFFF00A5FF - FF00A5FFFF00A5FFFF00A5FFFF00A5FFFF00A5FFFF00A5FFFF00A5FFFF00A5FF - FF00088CBD000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000008CBD00D6F7FF00A5F7 - FF00A5F7FF00A5F7FF00008CBD00008CBD00008CBD00008CBD00008CBD00008C - BD000000000000000000000000000000000000000000008CBD00E7FFFF00A5FF - FF00A5FFFF00A5FFFF00008CBD00008CBD00008CBD00008CBD00008CBD00008C - BD00000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000008CBD00008C - BD00008CBD00008CBD0000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000008CBD00008C - BD00008CBD00008CBD0000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 000000000000000000000000000000000000424D3E000000000000003E000000 - 2800000040000000100000000100010000000000800000000000000000000000 - 000000000000000000000000FFFFFF0080038007000000000001000300000000 - 0001000100000000000100010000000000010001000000000001000000000000 - 0001000000000000000100000000000000070007000000000007000700000000 - 800F800F00000000C3FFC3FF00000000FFFFFFFF00000000FFFFFFFF00000000 - FFFFFFFF00000000FFFFFFFF0000000000000000000000000000000000000000 - 000000000000} - end - object IdFTP: TIdFTP - Intercept = IdLogFile - MaxLineAction = maException - ReadTimeout = 0 - RecvBufferSize = 1024 - SendBufferSize = 1024 - OnWork = IdFTPWork - ProxySettings.ProxyType = fpcmNone - ProxySettings.Port = 0 - Left = 274 - Top = 324 - end - object IdAntiFreeze: TIdAntiFreeze - IdleTimeOut = 150 - Left = 244 - Top = 324 - end - object tmrSpeed: TTimer - Enabled = False - OnTimer = tmrSpeedTimer - Left = 214 - Top = 324 - end - object IdLogFile: TIdLogFile - LogTime = False - Left = 184 - Top = 324 - end -end diff --git a/utils/mmsource/cruft/installer/UnitfrmMain.pas b/utils/mmsource/cruft/installer/UnitfrmMain.pas deleted file mode 100644 index e335bc5a5..000000000 --- a/utils/mmsource/cruft/installer/UnitfrmMain.pas +++ /dev/null @@ -1,804 +0,0 @@ -unit UnitfrmMain; - -interface - -uses - Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, - Dialogs, TFlatRadioButtonUnit, StdCtrls, ComCtrls, mxFlatControls, JvPageList, - ExtCtrls, JvExControls, JvComponent, TFlatButtonUnit, jpeg, TFlatEditUnit, - TFlatGaugeUnit, ImgList, FileCtrl, Registry, CheckLst, TFlatComboBoxUnit, - TFlatCheckBoxUnit, IdBaseComponent, IdComponent, IdTCPConnection, - IdTCPClient, IdFTP, IdException, IdAntiFreezeBase, IdAntiFreeze, - IdIntercept, IdLogBase, IdLogFile, pngimage; - -type - TfrmMain = class(TForm) - jplWizard: TJvPageList; - jspWelcome: TJvStandardPage; - pnlButtons: TPanel; - bvlSpace: TBevel; - cmdNext: TFlatButton; - cmdCancel: TFlatButton; - imgInstall: TImage; - lblWelcome: TLabel; - lblInfo1: TLabel; - lblInfo2: TLabel; - lblInfo3: TLabel; - jspLicense: TJvStandardPage; - pnlLicense: TPanel; - imgIcon1: TImage; - lblTitle1: TLabel; - lblSubTitle1: TLabel; - freLicense: TmxFlatRichEdit; - frbAgree: TFlatRadioButton; - ftbDontAgree: TFlatRadioButton; - jspInstallMethod: TJvStandardPage; - pnlHeader2: TPanel; - imgIcon2: TImage; - lblTitle2: TLabel; - lblSubTitle2: TLabel; - lblInstallMethod: TLabel; - pnlInstallMethod: TPanel; - frbDedicatedServer: TFlatRadioButton; - frbListenServer: TFlatRadioButton; - frbSelectMod: TFlatRadioButton; - frbFTP: TFlatRadioButton; - cmdBack: TFlatButton; - jspFTP: TJvStandardPage; - pnlHeader3: TPanel; - imgIcon3: TImage; - lblTitle3: TLabel; - lblSubTitle3: TLabel; - lblStep1: TLabel; - pnlFTPData: TPanel; - lblHost: TLabel; - txtHost: TFlatEdit; - lblUserName: TLabel; - txtUserName: TFlatEdit; - txtPassword: TFlatEdit; - lblPassword: TLabel; - txtPort: TFlatEdit; - lblPort: TLabel; - lblStep2: TLabel; - cmdConnect: TFlatButton; - pnlDirectory: TPanel; - trvDirectories: TTreeView; - lblStep4: TLabel; - jspInstallProgress: TJvStandardPage; - pnlHeader5: TPanel; - imgIcon4: TImage; - lblTitle5: TLabel; - lblSubTitle5: TLabel; - ggeAll: TFlatGauge; - lblProgress: TLabel; - ggeItem: TFlatGauge; - rtfDetails: TmxFlatRichEdit; - lblDetails: TLabel; - bvlSpace2: TBevel; - ilImages: TImageList; - bvlSpacer1: TBevel; - bvlSpacer2: TBevel; - bvlSpacer3: TBevel; - bvlSpacer5: TBevel; - jspSelectMod: TJvStandardPage; - pnlSelectMod: TPanel; - imgIcon5: TImage; - lblSelectMod: TLabel; - lblSelectModInfo: TLabel; - bvlSelectMod: TBevel; - lblInfo: TLabel; - chkPassive: TFlatCheckBox; - lblStep3: TLabel; - pnlOS: TPanel; - optWindows: TFlatRadioButton; - optLinux: TFlatRadioButton; - IdFTP: TIdFTP; - cmdProxySettings: TFlatButton; - IdAntiFreeze: TIdAntiFreeze; - frbStandaloneServer: TFlatRadioButton; - tmrSpeed: TTimer; - IdLogFile: TIdLogFile; - shpMods: TShape; - trvMods: TTreeView; - FlatRadioButton1: TFlatRadioButton; - procedure jvwStepsCancelButtonClick(Sender: TObject); - procedure cmdCancelClick(Sender: TObject); - procedure cmdNextClick(Sender: TObject); - procedure CheckNext(Sender: TObject); - procedure cmdBackClick(Sender: TObject); - procedure cmdConnectClick(Sender: TObject); - procedure jplWizardChange(Sender: TObject); - procedure FormCreate(Sender: TObject); - procedure cmdProxySettingsClick(Sender: TObject); - procedure txtPortChange(Sender: TObject); - procedure trvDirectoriesExpanded(Sender: TObject; Node: TTreeNode); - procedure trvDirectoriesChange(Sender: TObject; Node: TTreeNode); - procedure IdFTPWork(Sender: TObject; AWorkMode: TWorkMode; - const AWorkCount: Integer); - procedure FormClose(Sender: TObject; var Action: TCloseAction); - procedure tmrSpeedTimer(Sender: TObject); - procedure trvDirectoriesExpanding(Sender: TObject; Node: TTreeNode; - var AllowExpansion: Boolean); - procedure trvDirectoriesCollapsing(Sender: TObject; Node: TTreeNode; - var AllowCollapse: Boolean); - procedure trvModsClick(Sender: TObject); - procedure trvDirectoriesMouseDown(Sender: TObject; - Button: TMouseButton; Shift: TShiftState; X, Y: Integer); - private - OldProgress: Integer; - CurrProgress: Integer; - public - procedure ExceptionHandler(Sender: TObject; E: Exception); - end; - -var - frmMain: TfrmMain; - -var VERSION: String = ''; - -implementation - -uses UnitFunctions, UnitfrmProxy, UnitInstall, UnitSelectModPath; - -{$R *.dfm} - -procedure TfrmMain.jvwStepsCancelButtonClick(Sender: TObject); -begin - Close; -end; - -procedure TfrmMain.cmdCancelClick(Sender: TObject); -begin - Close; -end; - -procedure TfrmMain.cmdNextClick(Sender: TObject); -var ePath: String; - eRegistry: TRegistry; - eStr: TStringList; - CurNode: TTreeNode; - eOS: TOS; - i: integer; - Source: Boolean; -begin - { FTP } - if jplWizard.ActivePage = jspFTP then begin - if not IdFTP.Connected then - IdFTP.Connect; - eStr := TStringList.Create; - ePath := '/'; - CurNode := trvDirectories.Selected; - if (Assigned(CurNode)) then begin - repeat - ePath := '/' + CurNode.Text + ePath; - CurNode := CurNode.Parent; - until (not Assigned(CurNode)); - end; - IdFTP.ChangeDir(ePath); - IdFTP.List(eStr, '', False); - eStr.CaseSensitive := False; - // check if gameinfo.txt is in the directory -> valid installation - if (eStr.IndexOf('gameinfo.txt') = -1) then begin - MessageBox(Handle, 'Invalid directory. Please select your mod directory and try again.', PChar(Application.Title), MB_ICONWARNING); - eStr.Free; - exit; - end - else - eStr.Free; - // check for orangebox directory - Source := True; - if (AnsiSameText(ExtractFileName(trvDirectories.Selected.Text), 'tf')) then begin - case MessageBox(Handle, 'It looks like your server is using the OrangeBox engine. Would you like to install the appropriate binaries for it?', PChar(Application.Title), MB_ICONQUESTION + MB_YESNOCANCEL) of - mrYes: Source := False; - mrNo: Source := True; - mrCancel: begin - eStr.Free; - exit; - end; - end; - end; - // design stuff - trvDirectories.Enabled := False; - cmdConnect.Enabled := False; - optWindows.Enabled := False; - optLinux.Enabled := False; - Screen.Cursor := crHourGlass; - - if optWindows.Checked then - eOS := osWindows - else - eOS := osLinux; - - jspInstallProgress.Show; - // installation - Screen.Cursor := crAppStart; - InstallFTP(eOS, Source); - end - else if jplWizard.ActivePage = jspInstallProgress then - Close - else if jplWizard.ActivePage = jspSelectMod then begin - { Dedicated Server } - if frbDedicatedServer.Checked then begin - Source := True; - ePath := trvMods.Selected.Text; - if ePath = 'Counter-Strike:Source' then - ePath := trvMods.Selected.Parent.Text + '\source dedicated server\cstrike' - else if ePath = 'Day of Defeat:Source' then - ePath := trvMods.Selected.Parent.Text + '\source dedicated server\dod' - else if ePath = 'Half-Life 2 Deathmatch' then - ePath := trvMods.Selected.Parent.Text + '\source dedicated server\hl2mp' - else begin - { get games } - if ePath = 'Team Fortress 2' then - ePath := trvMods.Selected.Parent.Text + '\source 2007 dedicated server\tf'; - { ask user, just in case } - case MessageBox(Handle, 'It looks like your server is using the OrangeBox engine. Would you like to install the appropriate binaries for it?', PChar(Application.Title), MB_ICONQUESTION + MB_YESNOCANCEL) of - mrYes: Source := False; - mrNo: Source := True; - mrCancel: exit; - end; - end; - SteamPath := IncludeTrailingPathDelimiter(SteamPath) + 'steamapps\'; - // install it - if DirectoryExists(SteamPath + ePath) then begin - jspInstallProgress.Show; - InstallDedicated(IncludeTrailingPathDelimiter(SteamPath + ePath), True, Source); - end - else begin - MessageBox(Handle, 'Error: The directory of the mod you selected doesn''t exist any more. Run Dedicated Server with the chosen mod and try again.', PChar(Application.Title), MB_ICONERROR); - jspSelectMod.Show; - exit; - end; - end; - { Standalone Server } - if frbStandaloneServer.Checked then begin - Source := True; - ePath := trvMods.Selected.Text; - if ePath = 'Counter-Strike:Source' then - ePath := 'cstrike' - else if ePath = 'Day of Defeat:Source' then - ePath := 'dod' - else if ePath = 'Half-Life 2 Deathmatch' then - ePath := 'hl2mp' - else begin - { get games } - if ePath = 'Team Fortress 2' then - ePath := 'orangebox\tf'; - { ask user, just in case } - case MessageBox(Handle, 'It looks like your server is using the OrangeBox engine. Would you like to install the appropriate binaries for it?', PChar(Application.Title), MB_ICONQUESTION + MB_YESNOCANCEL) of - mrYes: Source := False; - mrNo: Source := True; - mrCancel: exit; - end; - end; - // install it - if DirectoryExists(StandaloneServer + ePath) then begin - jspInstallProgress.Show; - InstallDedicated(IncludeTrailingPathDelimiter(StandaloneServer + ePath), False, Source) - end - else begin - MessageBox(Handle, 'Error: The directory of the mod you selected doesn''t exist (any more). Run Half-Life Dedicated Server with the chosen mod again and restart.', PChar(Application.Title), MB_ICONERROR); - jspSelectMod.Show; - exit; - end; - end; - { Listen Server } - if frbListenServer.Checked then begin - Source := True; - ePath := trvMods.Selected.Text; - if ePath = 'Counter-Strike:Source' then - ePath := SteamPath + 'SteamApps\' + trvMods.Selected.Parent.Text + '\counter-strike source\cstrike' - else if ePath = 'Half-Life 2 Deathmatch' then - ePath := SteamPath + 'SteamApps\' + trvMods.Selected.Parent.Text + '\half-life 2 deathmatch\hl2mp' - else if ePath = 'Day of Defeat:Source' then - ePath := SteamPath + 'SteamApps\' + trvMods.Selected.Parent.Text + '\day of defeat source\dod' - else begin - { get games } - if ePath = 'Team Fortress 2' then - ePath := SteamPath + 'SteamApps\' + trvMods.Selected.Parent.Text + '\team fortress 2\tf'; - { ask user, just in case } - case MessageBox(Handle, 'It looks like your server is using the OrangeBox engine. Would you like to install the appropriate binaries for it?', PChar(Application.Title), MB_ICONQUESTION + MB_YESNOCANCEL) of - mrYes: Source := False; - mrNo: Source := True; - mrCancel: exit; - end; - end; - - if Pos(SteamPath, ePath) = 0 then - MessageBox(Handle, 'An error occured. Please report this bug to the Metamod:Source team and post a new thread on the forums of www.amxmodx.org.', PChar(Application.Title), MB_ICONSTOP) - else begin - if not FileExists(ePath + '\gameinfo.txt') then begin - MessageBox(Handle, 'You have to play this game once before installing Metamod:Source. Do that and try again.', PChar(Application.Title), MB_ICONWARNING); - exit; - end; - - jspInstallProgress.Show; - InstallListen(IncludeTrailingPathDelimiter(ePath), Source); - end; - end; - { Custom mod below } - end - else if jplWizard.ActivePage <> jspInstallMethod then - jplWizard.NextPage - else begin - if frbDedicatedServer.Checked then begin // Dedicated Server - eRegistry := TRegistry.Create(KEY_READ); - try - eRegistry.RootKey := HKEY_CURRENT_USER; - if eRegistry.OpenKey('Software\Valve\Steam', False) then begin - ePath := eRegistry.ReadString('SteamPath'); - ePath := IncludeTrailingPathDelimiter(StringReplace(ePath, '/', '\', [rfReplaceAll])); - SteamPath := ePath; - - ePath := ePath + 'SteamApps\'; - if DirectoryExists(ePath) then begin - trvMods.Items.Clear; - // Check Mods - eStr := GetAllFiles(ePath + '*.*', faDirectory, False, True, False); - for i := 0 to eStr.Count -1 do begin - CurNode := trvMods.Items.Add(nil, eStr[i]); - - if DirectoryExists(ePath + eStr[i] + '\source dedicated server\cstrike') then - trvMods.Items.AddChild(CurNode, 'Counter-Strike:Source'); - if DirectoryExists(ePath + eStr[i] + '\source dedicated server\dod') then - trvMods.Items.AddChild(CurNode, 'Day of Defeat:Source'); - if DirectoryExists(ePath + eStr[i] + '\source dedicated server\hl2mp') then - trvMods.Items.AddChild(CurNode, 'Half-Life 2 Deatmatch'); - if DirectoryExists(ePath + eStr[i] + '\source 2007 dedicated server\tf') then - trvMods.Items.AddChild(CurNode, 'Team Fortress 2'); - - if CurNode.Count = 0 then - CurNode.Free - else - CurNode.Expand(False); - end; - // Misc - jspSelectMod.Show; - trvMods.Selected := nil; - cmdNext.Enabled := False; - end - else - MessageBox(Handle, 'You have to run Dedicated Server once before installing Metamod:Source!', 'Error', MB_ICONWARNING); - end - else - MessageBox(Handle, 'You haven''t installed Steam yet! Download it at www.steampowered.com, install Dedicated Server and try again.', 'Error', MB_ICONWARNING); - finally - eRegistry.Free; - end; - end - else if frbListenServer.Checked then begin // Listen Server - eRegistry := TRegistry.Create(KEY_READ); - try - eRegistry.RootKey := HKEY_CURRENT_USER; - if eRegistry.OpenKey('Software\Valve\Steam', False) then begin - ePath := eRegistry.ReadString('SteamPath'); - ePath := IncludeTrailingPathDelimiter(StringReplace(ePath, '/', '\', [rfReplaceAll])); - SteamPath := ePath; - - ePath := ePath + 'SteamApps\'; - if DirectoryExists(ePath) then begin - trvMods.Items.Clear; - // Check Mods - eStr := GetAllFiles(ePath + '*.*', faDirectory, False, True, False); - for i := 0 to eStr.Count -1 do begin - CurNode := trvMods.Items.Add(nil, eStr[i]); - - if DirectoryExists(ePath + eStr[i] + '\counter-strike source') then - trvMods.Items.AddChild(CurNode, 'Counter-Strike:Source'); - if DirectoryExists(ePath + eStr[i] + '\day of defeat source') then - trvMods.Items.AddChild(CurNode, 'Day of Defeat:Source'); - if DirectoryExists(ePath + eStr[i] + '\half-life 2 deathmatch') then - trvMods.Items.AddChild(CurNode, 'Half-Life 2 Deatmatch'); - if DirectoryExists(ePath + eStr[i] + '\team fortress 2') then - trvMods.Items.AddChild(CurNode, 'Team Fortress 2'); - - if CurNode.Count = 0 then - CurNode.Free - else - CurNode.Expand(False); - end; - // Misc - jspSelectMod.Show; - trvMods.Selected := nil; - cmdNext.Enabled := False; - end - else - MessageBox(Handle, 'You haven''t installed Steam yet! Download it at www.steampowered.com, install Dedicated Server and try again.', 'Error', MB_ICONWARNING); - end - else - MessageBox(Handle, 'You haven''t installed Steam yet! Download it at www.steampowered.com, install Dedicated Server and try again.', 'Error', MB_ICONWARNING); - finally - eRegistry.Free; - end; - end - else if frbStandaloneServer.Checked then begin // Standalone Server - eRegistry := TRegistry.Create; - try - eRegistry.RootKey := HKEY_CURRENT_USER; - if eRegistry.OpenKey('Software\Valve\HLServer', False) then begin - StandaloneServer := IncludeTrailingPathDelimiter(eRegistry.ReadString('InstallPath')); - if DirectoryExists(StandaloneServer + 'cstrike') then - trvMods.Items.Add(nil, 'Counter-Strike:Source'); - if DirectoryExists(StandaloneServer + 'dod') then - trvMods.Items.Add(nil, 'Day of Defeat:Source'); - if DirectoryExists(StandaloneServer + 'hl2mp') then - trvMods.Items.Add(nil, 'Half-Life 2 Deatmatch'); - if DirectoryExists(StandaloneServer + 'orangebox\tf') then - trvMods.Items.Add(nil, 'Team Fortress 2'); - jspSelectMod.Show; - cmdNext.Enabled := False; - end - else - MessageBox(Handle, 'You haven''t installed Half-Life Dedicated Server yet!', 'Error', MB_ICONWARNING); - finally - eRegistry.Free; - end; - end - else if frbSelectMod.Checked then begin - { Custom mod } - if frmSelectModPath.ShowModal = mrOk then begin - ePath := frmSelectModPath.trvDirectory.SelectedFolder.PathName; - { check if this is an orangebox game } - Source := True; - if (AnsiSameText(ExtractFileName(ePath), 'tf')) then begin - case MessageBox(Handle, 'It looks like your server is using the OrangeBox engine. Would you like to install the appropriate binaries for it?', PChar(Application.Title), MB_ICONQUESTION + MB_YESNOCANCEL) of - mrYes: Source := False; - mrNo: Source := True; - mrCancel: exit; - end; - end; - { install now } - jspInstallProgress.Show; - InstallCustom(IncludeTrailingPathDelimiter(ePath), osWindows, Source); - end; - end - else if frbFTP.Checked then // FTP - jspFTP.Show; - end; -end; - -procedure TfrmMain.CheckNext(Sender: TObject); -begin - cmdNext.Enabled := frbAgree.Checked; -end; - -procedure TfrmMain.cmdBackClick(Sender: TObject); -begin - if jplWizard.ActivePage = jspFTP then - jspInstallMethod.Show - else begin - jplWizard.PrevPage; - cmdBack.Visible := jplWizard.ActivePageIndex <> 0; - end; -end; - -procedure TfrmMain.cmdConnectClick(Sender: TObject); -var i: integer; - eStr: TStringList; - CurNode: TTreeNode; - Path: String; -begin - if (Trim(txtHost.Text) = '') or (Trim(txtUsername.Text) = '') then - MessageBox(Handle, 'Please fill in each field!', PChar(Application.Title), MB_ICONWARNING) - else if cmdConnect.Caption = 'Connect' then begin - // ... design stuff ... - Screen.Cursor := crHourGlass; - cmdConnect.Enabled := False; - cmdProxySettings.Enabled := False; - txtHost.Enabled := False; - txtPort.Enabled := False; - txtUsername.Enabled := False; - txtPassword.Enabled := False; - chkPassive.Enabled := False; - cmdConnect.Caption := 'Connecting...'; - // ... set values ... - IdFTP.Host := txtHost.Text; - IdFTP.Port := StrToInt(txtPort.Text); - IdFTP.Username := txtUsername.Text; - IdFTP.Passive := chkPassive.Checked; - IdFTP.Password := txtPassword.Text; - // ... connect and check values etc ... - try - IdFTP.Connect(True, 15000); - // ... get initial directory ... - Path := IdFTP.RetrieveCurrentDir; - // ... "fix" path ... - eStr := TStringList.Create; - eStr.Text := StringReplace(Path, '/', #13, [rfReplaceAll]); - for i := eStr.Count -1 downto 0 do begin - if eStr[i] = '' then - eStr.Delete(i); - end; - if (Copy(Path, Length(Path) -1, 1) <> '/') then - Path := Path + '/'; - // ... connect successful, change captions ... - trvDirectories.Enabled := True; - cmdConnect.Enabled := True; - cmdConnect.Caption := 'Disconnect'; - // ... change to / and create all the directories ... - CurNode := nil; - if (Path <> '/') then begin - try - IdFTP.ChangeDir('/'); - with GetAllDirs do begin - for i := 0 to Count -1 do begin - if (Assigned(CurNode)) then - trvDirectories.Items.AddChild(trvDirectories.Items.Add(nil, Strings[i]), 'Scanning...') - else begin - CurNode := trvDirectories.Items.Add(nil, Strings[i]); - trvDirectories.Items.AddChild(CurNode, 'Scanning...'); - if (Pos('/' + CurNode.Text + '/', Path) = 0) then - CurNode := nil; - end - end; - Free; - end; - IdFTP.ChangeDir(Path); - except - if (IdFTP.Connected) then - IdFTP.ChangeDir(Path) - else - IdFTP.Connect; - end; - end; - // ... find directories in start path ... - if eStr.Count <> 0 then begin - for i := 0 to eStr.Count -1 do begin - if (not ((i = 0) and (Assigned(CurNode)))) then - CurNode := trvDirectories.Items.AddChild(CurNode, eStr[i]); - end; - end; - trvDirectories.Selected := CurNode; - eStr.Free; - // ... scan for directories ... - with GetAllDirs do begin - for i := 0 to Count -1 do - trvDirectories.Items.AddChild(trvDirectories.Items.AddChild(CurNode, Strings[i]), 'Scanning...'); - Free; - end; - - if Assigned(CurNode) then - CurNode.Expand(False); - except - on E: Exception do begin - // reset button properties - cmdConnect.Enabled := True; - txtHost.Enabled := True; - txtPort.Enabled := True; - txtUsername.Enabled := True; - txtPassword.Enabled := True; - chkPassive.Enabled := True; - cmdProxySettings.Enabled := True; - cmdNext.Enabled := False; - cmdConnect.Caption := 'Connect'; - // analyze messages - if Pos('Login incorrect.', E.Message) <> 0 then begin // login failed - MessageBox(Handle, 'Login incorrect. Check your FTP settings and try again.', PChar(Application.Title), MB_ICONWARNING); - txtUsername.SetFocus; - txtUsername.SelectAll; - end - else if Pos('Host not found.', E.Message) <> 0 then begin // host not found - MessageBox(Handle, 'The entered host couldn''t be found. Check your settings and try again.', PChar(Application.Title), MB_ICONWARNING); - txtHost.SetFocus; - txtHost.SelectAll; - end - else if Pos('Connection refused.', E.Message) <> 0 then begin // wrong port (?) - MessageBox(Handle, 'The host refused the connection. Check your port and try again.', PChar(Application.Title), MB_ICONWARNING); - txtPort.SetFocus; - txtPort.SelectAll; - end - else if E is EIdProtocolReplyError then begin // wrong port - MessageBox(Handle, 'The port you entered is definitely wrong. Check it and try again.', PChar(Application.Title), MB_ICONWARNING); - txtPort.SetFocus; - txtPort.SelectAll; - end - else - MessageBox(Handle, PChar(E.Message), PChar(Application.Title), MB_ICONWARNING); // unknown error - // ... connect failed, leave procedure ... - Screen.Cursor := crDefault; - exit; - end; - end; - - Screen.Cursor := crDefault; - end - else begin - Screen.Cursor := crHourGlass; - IdFTP.Quit; - trvDirectories.Items.Clear; - trvDirectories.Enabled := False; - cmdConnect.Enabled := True; - cmdProxySettings.Enabled := True; - txtHost.Enabled := True; - txtPort.Enabled := True; - txtUsername.Enabled := True; - txtPassword.Enabled := True; - chkPassive.Enabled := True; - cmdConnect.Caption := 'Connect'; - cmdNext.Enabled := False; - Screen.Cursor := crDefault; - end; -end; - -procedure TfrmMain.jplWizardChange(Sender: TObject); -begin - if (jplWizard.ActivePage = jspInstallProgress) then begin - cmdNext.Caption := '&Finish'; - cmdNext.Enabled := False; - cmdBack.Visible := False; - end - else begin - cmdNext.Caption := '&Next >'; - cmdNext.Enabled := True; - cmdBack.Visible := jplWizard.ActivePageIndex <> 0; - end; - - if (jplWizard.ActivePage = jspLicense) then - cmdNext.Enabled := frbAgree.Checked; - - if (jplWizard.ActivePage = jspFTP) then - cmdNext.Enabled := False; -end; - -procedure TfrmMain.FormCreate(Sender: TObject); -begin - if LowerCase(ParamStr(1)) = '-logftp' then begin - MessageBox(Handle, 'FTP installation will be logged to FTP.log!', PChar(Application.Title), MB_ICONINFORMATION); - IdLogFile.Filename := ExtractFilePath(ParamStr(0)) + 'FTP.log'; - IdLogFile.Active := True; - end; - - rtfDetails.Clear; -end; - -procedure TfrmMain.cmdProxySettingsClick(Sender: TObject); -begin - frmProxy.ShowModal; - // Apply Proxy Settings - case frmProxy.cboProxy.ItemIndex of - 0: IdFTP.ProxySettings.ProxyType := fpcmNone; // none - 1: IdFTP.ProxySettings.ProxyType := fpcmHttpProxyWithFtp; // HTTP Proxy with FTP - 2: IdFTP.ProxySettings.ProxyType := fpcmOpen; // Open - 3: IdFTP.ProxySettings.ProxyType := fpcmSite; // Site - 4: IdFTP.ProxySettings.ProxyType := fpcmTransparent; // Transparent - 5: IdFTP.ProxySettings.ProxyType := fpcmUserPass; // User (Password) - 6: IdFTP.ProxySettings.ProxyType := fpcmUserSite; // User (Site) - end; - - IdFTP.ProxySettings.Host := frmProxy.txtHost.Text; - IdFTP.ProxySettings.UserName := frmProxy.txtPort.Text; - IdFTP.ProxySettings.Password := frmProxy.txtPassword.Text; - IdFTP.ProxySettings.Port := StrToInt(frmProxy.txtPort.Text); -end; - -procedure TfrmMain.txtPortChange(Sender: TObject); -var i: integer; -begin - if txtPort.Text = '' then - txtPort.Text := '21' - else begin - // check if value is numeric... - for i := Length(txtPort.Text) downto 1 do begin - if Pos(txtPort.Text[i], '0123456789') = 0 then begin - txtPort.Text := '21'; - txtPort.SelStart := 4; - exit; - end; - end; - end; -end; - -procedure TfrmMain.trvDirectoriesExpanded(Sender: TObject; - Node: TTreeNode); -var ePath: String; - CurNode: TTreeNode; - i: integer; -begin - if Node.Item[0].Text = 'Scanning...' then begin // no directories added yet - Screen.Cursor := crHourGlass; - // get complete path - ePath := '/'; - CurNode := Node; - repeat - ePath := '/' + CurNode.Text + ePath; - CurNode := CurNode.Parent; - until (not Assigned(CurNode)); - // change dir and add directories in it - try - Repaint; - IdFTP.ChangeDir(ePath); - with GetAllDirs do begin - Node.Item[0].Free; - for i := 0 to Count -1 do begin - trvDirectories.Items.AddChild(trvDirectories.Items.AddChild(Node, Strings[i]), 'Scanning...'); - end; - Free; - end; - finally - Application.ProcessMessages; - end; - Screen.Cursor := crDefault; - end; -end; - -procedure TfrmMain.trvDirectoriesChange(Sender: TObject; Node: TTreeNode); -begin - cmdNext.Enabled := Assigned(trvDirectories.Selected); -end; - -procedure TfrmMain.IdFTPWork(Sender: TObject; AWorkMode: TWorkMode; - const AWorkCount: Integer); -begin - if AWorkCount > 15 then begin - ggeItem.Progress := AWorkCount; - CurrProgress := AWorkCount; - end; - - if Cancel then - IdFTP.Abort; - - Application.ProcessMessages; -end; - -procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction); -begin - if (jplWizard.ActivePage = jspFTP) and (IdFTP.Connected) then - IdFTP.Quit; - if (jplWizard.ActivePage = jspInstallProgress) and (ggeAll.Progress <> ggeAll.MaxValue) and (not Cancel) then begin - if MessageBox(Handle, 'Do you really want to cancel the installation?', PChar(Application.Title), MB_ICONQUESTION + MB_YESNO) = mrYes then begin - Screen.Cursor := crDefault; - Application.OnException := ExceptionHandler; - Cancel := True; - if IdFTP.Connected then - IdFTP.Quit; - end - else - Action := caNone; - end; -end; - -procedure TfrmMain.ExceptionHandler(Sender: TObject; E: Exception); -begin - // IF any exceptions were raised after close, nobody would want them so leave this empty -end; - -procedure TfrmMain.tmrSpeedTimer(Sender: TObject); -begin - Caption := CalcSpeed(OldProgress, CurrProgress); - OldProgress := CurrProgress; -end; - -procedure TfrmMain.trvDirectoriesExpanding(Sender: TObject; - Node: TTreeNode; var AllowExpansion: Boolean); -begin - Node.ImageIndex := 1; - Node.SelectedIndex := 1; -end; - -procedure TfrmMain.trvDirectoriesCollapsing(Sender: TObject; - Node: TTreeNode; var AllowCollapse: Boolean); -begin - Node.ImageIndex := 0; - Node.SelectedIndex := 0; -end; - -procedure TfrmMain.trvModsClick(Sender: TObject); -begin - if Assigned(trvMods.Selected) then - cmdNext.Enabled := Assigned(trvMods.Selected.Parent) - else - cmdNext.Enabled := False; -end; - -procedure TfrmMain.trvDirectoriesMouseDown(Sender: TObject; - Button: TMouseButton; Shift: TShiftState; X, Y: Integer); -var Node: TTreeNode; -begin - Node := trvDirectories.GetNodeAt(X, Y); - if (Assigned(Node)) then begin - if (Node.DisplayRect(True).Right < X) then - trvDirectories.Selected := nil; - end; -end; - -end. diff --git a/utils/mmsource/cruft/installer/UnitfrmProxy.dfm b/utils/mmsource/cruft/installer/UnitfrmProxy.dfm deleted file mode 100644 index 7ba9c06c5..000000000 Binary files a/utils/mmsource/cruft/installer/UnitfrmProxy.dfm and /dev/null differ diff --git a/utils/mmsource/cruft/installer/UnitfrmProxy.pas b/utils/mmsource/cruft/installer/UnitfrmProxy.pas deleted file mode 100644 index 1556226d3..000000000 --- a/utils/mmsource/cruft/installer/UnitfrmProxy.pas +++ /dev/null @@ -1,72 +0,0 @@ -unit UnitfrmProxy; - -interface - -uses - SysUtils, Windows, Messages, Classes, Graphics, Controls, - StdCtrls, ExtCtrls, Forms, TFlatButtonUnit, TFlatComboBoxUnit, - TFlatEditUnit; - -type - TfrmProxy = class(TForm) - cmdClose: TFlatButton; - lblProxy: TLabel; - txtHost: TFlatEdit; - cboProxy: TFlatComboBox; - lblHost: TLabel; - txtPort: TFlatEdit; - lblPort: TLabel; - lblUsername: TLabel; - txtUsername: TFlatEdit; - txtPassword: TFlatEdit; - lblPassword: TLabel; - procedure cboProxyChange(Sender: TObject); - procedure txtPortChange(Sender: TObject); - public - procedure EnableControls(Enable: Boolean); - end; - -var - frmProxy: TfrmProxy; - -implementation - -{$R *.DFM} - -{ TfrmProxy } - -procedure TfrmProxy.EnableControls(Enable: Boolean); -begin - lblHost.Enabled := Enable; - lblPassword.Enabled := Enable; - lblPort.Enabled := Enable; - lblUsername.Enabled := Enable; - txtHost.Enabled := Enable; - txtPassword.Enabled := Enable; - txtPort.Enabled := Enable; - txtUsername.Enabled := Enable; -end; - -procedure TfrmProxy.cboProxyChange(Sender: TObject); -begin - EnableControls(cboProxy.ItemIndex <> 0); // 0 = None -end; - -procedure TfrmProxy.txtPortChange(Sender: TObject); -var i: integer; -begin - if txtPort.Text = '' then - txtPort.Text := '8080' - else begin - // check if value is numeric... - for i := Length(txtPort.Text) downto 1 do begin - if Pos(txtPort.Text[i], '0123456789') = 0 then begin - txtPort.Text := '8080'; - txtPort.SelStart := 4; - exit; - end; - end; - end; -end; - -end. diff --git a/utils/mmsource/cruft/installer/del.bat b/utils/mmsource/cruft/installer/del.bat deleted file mode 100644 index 74a143bd5..000000000 --- a/utils/mmsource/cruft/installer/del.bat +++ /dev/null @@ -1,15 +0,0 @@ -del .\*.~pas -del .\*.dcu -del .\*.~ddp -del .\*.ddp -del .\*.~dpr -del .\*.~dfm -del .\*.~dpr -del .\*.map -del .\*.drc -del .\*.~xfm -del .\*.log -del .\*.dof -upx MMS_Installer.exe -upx Attach.exe -upx hl2launch.exe \ No newline at end of file diff --git a/utils/mmsource/cruft/installer/files/Readme.txt b/utils/mmsource/cruft/installer/files/Readme.txt deleted file mode 100644 index 807422142..000000000 --- a/utils/mmsource/cruft/installer/files/Readme.txt +++ /dev/null @@ -1,8 +0,0 @@ -This folder will be used by the attach binary. Make sure you have both the Source and OrangeBox binary in it. -Here are some instructions on how to prepare an upcoming release: - -1) Copy the latest MM:S dlls (Source+OrangeBox) and "hl2launch.exe" into this directory -2) Attach .source and .orangebox to the particular binaries. -3) Run Attach.exe -4) Test MMS_Installer.exe once (should work but nobody wants a buggy installer) -5) If everything worked fine, release it, otherwise pm me (Basic-Master) \ No newline at end of file diff --git a/utils/mmsource/cruft/installer/install.bmp b/utils/mmsource/cruft/installer/install.bmp deleted file mode 100644 index 39b905be4..000000000 Binary files a/utils/mmsource/cruft/installer/install.bmp and /dev/null differ diff --git a/utils/mmsource/loader/AMBuilder b/utils/mmsource/loader/AMBuilder deleted file mode 100644 index 7a4a991db..000000000 --- a/utils/mmsource/loader/AMBuilder +++ /dev/null @@ -1,28 +0,0 @@ -# vim: set ts=8 sts=2 sw=2 tw=99 et ft=python: -import os.path - -def configure_library(name, linux_defines, arch): - libname = name - binary = MMS.Library(builder, libname, arch) - binary.compiler.cxxincludes += [os.path.join(builder.sourcePath, 'core', 'sourcehook')] - binary.sources += [ - 'loader.cpp', - 'gamedll.cpp', - 'serverplugin.cpp', - 'utility.cpp', - ] - - if builder.target.platform == 'linux': - binary.compiler.defines += linux_defines - - nodes = builder.Add(binary) - MMS.binaries += [nodes] - -for arch in MMS.archs: - if builder.target.platform == 'linux': - if arch == 'x64': - configure_library('libserver', ['LIB_PREFIX="lib"', 'LIB_SUFFIX=".so"'], arch) - elif arch == 'x86': - configure_library('server_i486', ['LIB_PREFIX=""', 'LIB_SUFFIX="_i486.so"'], arch) - - configure_library('server', ['LIB_PREFIX="lib"', 'LIB_SUFFIX=".so"'], arch) diff --git a/utils/mmsource/loader/Makefile b/utils/mmsource/loader/Makefile deleted file mode 100644 index 97484f8cc..000000000 --- a/utils/mmsource/loader/Makefile +++ /dev/null @@ -1,90 +0,0 @@ -# (C)2004-2009 SourceMod Development Team -# Makefile written by David "BAILOPAN" Anderson - -##################################### -### EDIT BELOW FOR OTHER PROJECTS ### -##################################### - -OBJECTS = loader.cpp \ - utility.cpp \ - serverplugin.cpp \ - gamedll.cpp - -############################################## -### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ### -############################################## - -C_OPT_FLAGS = -DNDEBUG -O3 -funroll-loops -pipe -fno-strict-aliasing -C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3 -C_GCC4_FLAGS = -fvisibility=hidden -CPP_GCC4_FLAGS = -fvisibility-inlines-hidden -CPP = gcc-4.1 - -ifneq (,$(filter left4dead2 csgo,$(ENGINE))) - BINARY = server.so - CFLAGS += -DLIB_PREFIX=\"lib\" -DLIB_SUFFIX=\".so\" -else - BINARY = server_i486.so - CFLAGS += -DLIB_PREFIX=\"\" -DLIB_SUFFIX=\"_i486.so\" -endif - -LINK += -static-libgcc - -INCLUDE += -I. -I../core/sourcehook - -CFLAGS += -D_LINUX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp \ - -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca \ - -Dstrcmpi=strcasecmp -Wall -Werror -Wno-uninitialized -mfpmath=sse -msse -DHAVE_STDINT_H -m32 -CPPFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti - -################################################ -### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ### -################################################ - -ifeq "$(DEBUG)" "true" - ifeq "$(ENGINE)" "" - BIN_DIR = Debug - else - BIN_DIR = Debug.$(ENGINE) - endif - CFLAGS += $(C_DEBUG_FLAGS) -else - ifeq "$(ENGINE)" "" - BIN_DIR = Release - else - BIN_DIR = Release.$(ENGINE) - endif - CFLAGS += $(C_OPT_FLAGS) -endif - -GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1) -ifeq "$(GCC_VERSION)" "4" - CFLAGS += $(C_GCC4_FLAGS) - CPPFLAGS += $(CPP_GCC4_FLAGS) -endif - -OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o) -OBJ_LINUX := $(OBJ_LINUX:%.c=$(BIN_DIR)/%.o) - -$(BIN_DIR)/%.o: %.cpp - $(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $< - -$(BIN_DIR)/%.o: %.c - $(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $< - -all: - mkdir -p $(BIN_DIR) - $(MAKE) -f Makefile metamod - -metamod: $(OBJ_LINUX) - $(CPP) $(INCLUDE) $(OBJ_LINUX) $(LINK) -m32 -shared -ldl -lm -o$(BIN_DIR)/$(BINARY) - -debug: - $(MAKE) -f Makefile all DEBUG=true - -default: all - -clean: - rm -rf $(BIN_DIR)/*.o - rm -rf $(BIN_DIR)/$(BINARY) - diff --git a/utils/mmsource/loader/gamedll.cpp b/utils/mmsource/loader/gamedll.cpp deleted file mode 100644 index 66b9c5d3e..000000000 --- a/utils/mmsource/loader/gamedll.cpp +++ /dev/null @@ -1,874 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2015 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#include -#include -#include -#include -#include -#include -#include "loader.h" -#include -#include -#include "utility.h" -#include "gamedll.h" - -class IServerGameDLL; -class ISource2ServerConfig; - -#define MAX_GAMEDLL_PATHS 10 - -IGameDllBridge* gamedll_bridge = NULL; -static int game_info_detected = 0; -static char game_name[128]; -static char gamedll_paths[MAX_GAMEDLL_PATHS][PLATFORM_MAX_PATH]; -static void *gamedll_libs[MAX_GAMEDLL_PATHS]; -static unsigned int gamedll_path_count = 0; -static void *gamedll_lib = NULL; -static IServerGameDLL *gamedll_iface = NULL; -static ISource2ServerConfig *config_iface = NULL; -static QueryValveInterface gamedll_qvi = NULL; -static int gamedll_version = 0; -static int isgd_shutdown_index = -1; -#if defined _WIN32 -static int is2sc_allowdedi_index = 21; -#endif -static char mm_path[PLATFORM_MAX_PATH]; -static bool g_is_source2 = false; - -#if defined _WIN32 -#define SERVER_NAME "server.dll" -#if defined _WIN64 -#define PLATFORM_NAME "win64" -#else -#define PLATFORM_NAME "win32" -#endif -#elif defined __APPLE__ -#define SERVER_NAME "server.dylib" -#if defined __amd64__ -#define PLATFORM_NAME "osx64" -#else -#define PLATFORM_NAME "osx32" -#endif -#elif defined __linux__ -#if defined __amd64__ -// hackhack - source2 uses libserver as name on POSIX, but source1 x64 does not -// (but source1 x64 is also client-only right now so what-ev) -#define SERVER_NAME "libserver" LIB_SUFFIX -#define PLATFORM_NAME "linuxsteamrt64" -#else -#define SERVER_NAME "server" LIB_SUFFIX -#define PLATFORM_NAME "linuxsteamrt32" -#endif -#endif - -static bool -mm_DetectGameInformation() -{ - char game_path[PLATFORM_MAX_PATH]; - - if (game_info_detected) - return game_info_detected == 1 ? true : false; - - game_info_detected = -1; - - mm_GetGameName(game_name, sizeof(game_name)); - - if (!mm_GetFileOfAddress((void*)mm_DetectGameInformation, mm_path, sizeof(mm_path))) - { - mm_LogFatal("Could not locate Metamod loader library path"); - return false; - } - - if (!mm_ResolvePath(game_name, game_path, sizeof(game_path), g_is_source2)) - { - mm_LogFatal("Could not resolve path: %s", game_name); - return false; - } - - FILE *fp; - char gameinfo_path[PLATFORM_MAX_PATH]; - - bool is_source2 = false; - mm_PathFormat(gameinfo_path, sizeof(gameinfo_path), "%s/gameinfo.txt", game_path); - if ((fp = fopen(gameinfo_path, "rt")) == NULL) - { - // Try Source2 gameinfo - mm_PathFormat(gameinfo_path, sizeof(gameinfo_path), "%s/gameinfo.gi", game_path); - if ((fp = fopen(gameinfo_path, "rt")) == NULL) - { - mm_LogFatal("Could not read file: %s", gameinfo_path); - return false; - } - else - { - is_source2 = true; - } - } - - char temp_path[PLATFORM_MAX_PATH]; - char cur_path[PLATFORM_MAX_PATH]; - - char *ptr; - const char *lptr; - bool search = false; - char buffer[255], key[128], val[128]; - while (!feof(fp) && fgets(buffer, sizeof(buffer), fp) != NULL) - { - mm_TrimComments(buffer); - mm_TrimLeft(buffer); - mm_TrimRight(buffer); - - if (stricmp(buffer, "SearchPaths") == 0) - search = true; - - if (!search) - continue; - - mm_KeySplit(buffer, key, sizeof(key) - 1, val, sizeof(val) - 1); - if (stricmp(key, "Game") != 0 && stricmp(key, "GameBin") != 0) - continue; - - if (strncmp(val, "|gameinfo_path|", sizeof("|gameinfo_path|") - 1) == 0) - { - ptr = &val[sizeof("|gameinfo_path|") - 1]; - if (ptr[0] == '.') - ptr++; - lptr = game_path; - } - else - { - ptr = val; - if (getcwd(cur_path, sizeof(cur_path))) - lptr = cur_path; - else - lptr = ""; - } - - const char *pRelPath = is_source2 ? "../../" : ""; - const char *pOSDir = is_source2 ? PLATFORM_NAME "/" : ""; - if (stricmp(key, "GameBin") == 0) - mm_PathFormat(temp_path, sizeof(temp_path), "%s/%s%s/%s" SERVER_NAME, lptr, pRelPath, ptr, pOSDir); - else if (!ptr[0]) - mm_PathFormat(temp_path, sizeof(temp_path), "%s/%sbin/%s" SERVER_NAME, lptr, pRelPath, pOSDir); - else - mm_PathFormat(temp_path, sizeof(temp_path), "%s/%s%s/bin/%s" SERVER_NAME, lptr, pRelPath, ptr, pOSDir); - - if (mm_PathCmp(mm_path, temp_path)) - continue; - - FILE *exists = fopen(temp_path, "rb"); - if (!exists) - continue; - fclose(exists); - - /* exists is still non-NULL... use this as a flag */ - for (unsigned int i = 0; i < gamedll_path_count; i++) - { - if (mm_PathCmp(gamedll_paths[i], temp_path)) - { - exists = NULL; - break; - } - } - - if (!exists) - continue; - - mm_Format(gamedll_paths[gamedll_path_count], - PLATFORM_MAX_PATH, - "%s", - temp_path); - gamedll_path_count++; - - if (gamedll_path_count == MAX_GAMEDLL_PATHS) - break; - } - fclose(fp); - - game_info_detected = 1; - - if (gamedll_path_count == 0) - { - mm_LogFatal("Could not detect any valid game paths in gameinfo file"); - return false; - } - - return true; -} - -static void -mm_FreeCachedLibraries() -{ - for (unsigned int i = 0; i < gamedll_path_count; i++) - { - if (gamedll_libs[i] == NULL) - continue; - mm_UnloadLibrary(gamedll_libs[i]); - } -} - -static void -mm_PatchDllInit(bool patch); - -static void -mm_PatchDllShutdown(); - -#if defined _WIN32 -static void -mm_PatchAllowDedicated(bool patch); -#endif - -static void -mm_PatchConnect(bool patch); - -static void *isgd_orig_init = NULL; -static void *isgd_orig_shutdown = NULL; -#if defined _WIN32 -static void *is2sc_orig_allowdedi = NULL; -#endif -static void *is2sc_orig_connect = NULL; - -class VEmptyClass -{ -}; - -gamedll_bridge_info g_bridge_info; - -// Source2 - Rough start order -// CreateInterfaceFn (IS2SC) - hook Connect and AllowDedicatedServer -// IS2SC::Connect - save factory pointer. return orig. remove hook. -// IS2SC::AllowDedicatedServer - return true. remove hook. -// CreateInterfaceFn (IS2S) - hook Init and Shutdown -// IS2S::Init - do same as old ISGD::DLLInit, including core load. return orig. remove hook. -// IS2S::Shutdown - <-- this - -enum InitReturnVal_t -{ - INIT_FAILED = 0, - INIT_OK, - - INIT_LAST_VAL, -}; - -class ISource2ServerConfig -{ -public: - virtual bool Connect(QueryValveInterface factory) - { - g_bridge_info.engineFactory = factory; - g_bridge_info.fsFactory = factory; - g_bridge_info.physicsFactory = factory; - - - /* Call the original */ - bool result; - { - union - { - bool(VEmptyClass::*mfpnew)(QueryValveInterface factory); -#if defined _WIN32 - void *addr; - } u; - u.addr = is2sc_orig_connect; -#else - struct - { - void *addr; - intptr_t adjustor; - } s; - } u; - u.s.addr = is2sc_orig_connect; - u.s.adjustor = 0; -#endif - result = (((VEmptyClass *) config_iface)->*u.mfpnew)(factory); - } - - mm_PatchConnect(false); - - return result; - } -#if defined _WIN32 - virtual bool AllowDedicatedServers(int universe) const - { - mm_PatchAllowDedicated(false); - return true; - } -#endif -}; - -class ISource2Server -{ -public: - virtual bool Connect(QueryValveInterface factory) { return true; } - virtual void Disconnect() {} - virtual void *QueryInterface(const char *pInterfaceName) { return nullptr; } - - virtual InitReturnVal_t Init() - { - mm_backend = MMBackend_DOTA; - - char error[255]; - if (!mm_LoadMetamodLibrary(mm_backend, error, sizeof(error))) - { - mm_LogFatal("Detected engine %d but could not load: %s", mm_backend, error); - } - else - { - typedef IGameDllBridge *(*GetGameDllBridge)(); - GetGameDllBridge get_bridge = (GetGameDllBridge)mm_GetProcAddress("GetGameDllBridge"); - if (get_bridge == NULL) - { - mm_UnloadMetamodLibrary(); - mm_LogFatal("Detected engine %d but could not find GetGameDllBridge callback", mm_backend); - } - else - { - gamedll_bridge = get_bridge(); - } - } - - if (gamedll_bridge) - { - g_bridge_info.pGlobals = nullptr;// pGlobals; - g_bridge_info.dllVersion = gamedll_version; - g_bridge_info.isgd = gamedll_iface; - g_bridge_info.gsFactory = gamedll_qvi; - g_bridge_info.vsp_listener_path = mm_path; - - strcpy(error, "Unknown error"); - if (!gamedll_bridge->DLLInit_Pre(&g_bridge_info, error, sizeof(error))) - { - gamedll_bridge = NULL; - mm_UnloadMetamodLibrary(); - mm_LogFatal("Unknown error loading Metamod for engine %d: %s", mm_backend, error); - } - } - - /* Call the original */ - InitReturnVal_t result; - { - union - { - InitReturnVal_t(VEmptyClass::*mfpnew)(); -#if defined _WIN32 - void *addr; - } u; - u.addr = isgd_orig_init; -#else - struct - { - void *addr; - intptr_t adjustor; - } s; - } u; - u.s.addr = isgd_orig_init; - u.s.adjustor = 0; -#endif - result = (((VEmptyClass *)gamedll_iface)->*u.mfpnew)(); - } - - /** - * :TODO: possible logic hole here, what happens if the gamedll REALLY returns false? - * I'm pretty sure we'll die horribly. - */ - - if (!result) - { - gamedll_bridge->Unload(); - mm_UnloadMetamodLibrary(); - gamedll_bridge = NULL; - } - else if (gamedll_bridge != NULL) - { - gamedll_bridge->DLLInit_Post(&isgd_shutdown_index); - assert(isgd_shutdown_index != -1); - mm_PatchDllShutdown(); - } - - mm_PatchDllInit(false); - - return result; - } - - virtual void Shutdown() - { - gamedll_bridge->Unload(); - gamedll_bridge = NULL; - mm_UnloadMetamodLibrary(); - - /* Call original function */ - { - union - { - void (VEmptyClass::*mfpnew)(); -#if defined _WIN32 - void *addr; - } u; - u.addr = isgd_orig_shutdown; -#else - struct - { - void *addr; - intptr_t adjustor; - } s; - } u; - u.s.addr = isgd_orig_shutdown; - u.s.adjustor = 0; -#endif - (((VEmptyClass *)gamedll_iface)->*u.mfpnew)(); - } - - mm_UnloadLibrary(gamedll_lib); - gamedll_lib = NULL; - } -}; - -class IServerGameDLL -{ -public: - virtual bool DLLInit(QueryValveInterface engineFactory, - QueryValveInterface physicsFactory, - QueryValveInterface fileSystemFactory, - void *pGlobals) - { - mm_backend = mm_DetermineBackend(engineFactory, gamedll_qvi, game_name); - - char error[255]; - if (mm_backend == MMBackend_UNKNOWN) - { - mm_LogFatal("Could not detect engine version"); - } - else - { - if (!mm_LoadMetamodLibrary(mm_backend, error, sizeof(error))) - { - mm_LogFatal("Detected engine %d but could not load: %s", mm_backend, error); - } - else - { - typedef IGameDllBridge *(*GetGameDllBridge)(); - GetGameDllBridge get_bridge = (GetGameDllBridge)mm_GetProcAddress("GetGameDllBridge"); - if (get_bridge == NULL) - { - mm_UnloadMetamodLibrary(); - mm_LogFatal("Detected engine %d but could not find GetGameDllBridge callback", mm_backend); - } - else - { - gamedll_bridge = get_bridge(); - } - } - } - - if (gamedll_bridge) - { - g_bridge_info.engineFactory = (QueryValveInterface)engineFactory; - g_bridge_info.physicsFactory = (QueryValveInterface)physicsFactory; - g_bridge_info.fsFactory = (QueryValveInterface)fileSystemFactory; - g_bridge_info.pGlobals = pGlobals; - g_bridge_info.dllVersion = gamedll_version; - g_bridge_info.isgd = gamedll_iface; - g_bridge_info.gsFactory = gamedll_qvi; - g_bridge_info.vsp_listener_path = mm_path; - - strcpy(error, "Unknown error"); - if (!gamedll_bridge->DLLInit_Pre(&g_bridge_info, error, sizeof(error))) - { - gamedll_bridge = NULL; - mm_UnloadMetamodLibrary(); - mm_LogFatal("Unknown error loading Metamod for engine %d: %s", mm_backend, error); - } - } - - /* Call the original */ - bool result; - { - union - { - bool (VEmptyClass::*mfpnew)(QueryValveInterface engineFactory, - QueryValveInterface physicsFactory, - QueryValveInterface fileSystemFactory, - void *pGlobals); -#if defined _WIN32 - void *addr; - } u; - u.addr = isgd_orig_init; -#else - struct - { - void *addr; - intptr_t adjustor; - } s; - } u; - u.s.addr = isgd_orig_init; - u.s.adjustor = 0; -#endif - result = (((VEmptyClass *)gamedll_iface)->*u.mfpnew)(engineFactory, - physicsFactory, - fileSystemFactory, - pGlobals); - } - - /** - * :TODO: possible logic hole here, what happens if the gamedll REALLY returns false? - * I'm pretty sure we'll die horribly. - */ - - if (!result) - { - gamedll_bridge->Unload(); - mm_UnloadMetamodLibrary(); - gamedll_bridge = NULL; - } - else if (gamedll_bridge != NULL) - { - gamedll_bridge->DLLInit_Post(&isgd_shutdown_index); - assert(isgd_shutdown_index != -1); - mm_PatchDllShutdown(); - } - - mm_PatchDllInit(false); - - return result; - } - - virtual void DLLShutdown() - { - gamedll_bridge->Unload(); - gamedll_bridge = NULL; - mm_UnloadMetamodLibrary(); - - /* Call original function */ - { - union - { - void (VEmptyClass::*mfpnew)(); -#if defined _WIN32 - void *addr; - } u; - u.addr = isgd_orig_shutdown; -#else - struct - { - void *addr; - intptr_t adjustor; - } s; - } u; - u.s.addr = isgd_orig_shutdown; - u.s.adjustor = 0; -#endif - (((VEmptyClass *)gamedll_iface)->*u.mfpnew)(); - } - - mm_UnloadLibrary(gamedll_lib); - gamedll_lib = NULL; - } -}; - -static IServerGameDLL isgd_thunk; -static ISource2Server is2s_thunk; -static ISource2ServerConfig is2sc_thunk; - -static void -mm_PatchDllInit(bool patch) -{ - void **vtable_src; - void **vtable_dest; - SourceHook::MemFuncInfo mfp; - - if (g_is_source2) - { - SourceHook::GetFuncInfo(&ISource2Server::Init, mfp); - } - else - { - SourceHook::GetFuncInfo(&IServerGameDLL::DLLInit, mfp); - } - - assert(mfp.isVirtual); - assert(mfp.thisptroffs == 0); - assert(mfp.vtbloffs == 0); - - if (g_is_source2) - { - vtable_src = (void **)*(void **)&is2s_thunk; - } - else - { - vtable_src = (void **)*(void **)&isgd_thunk; - } - vtable_dest = (void **)*(void **)gamedll_iface; - - SourceHook::SetMemAccess(&vtable_dest[mfp.vtblindex], - sizeof(void*), - SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC); - - if (patch) - { - assert(isgd_orig_init == NULL); - isgd_orig_init = vtable_dest[mfp.vtblindex]; - vtable_dest[mfp.vtblindex] = vtable_src[mfp.vtblindex]; - } - else - { - assert(isgd_orig_init != NULL); - vtable_dest[mfp.vtblindex] = isgd_orig_init; - isgd_orig_init = NULL; - } -} - -static void -mm_PatchDllShutdown() -{ - void **vtable_src; - void **vtable_dest; - SourceHook::MemFuncInfo mfp; - - mfp.isVirtual = false; - if (g_is_source2) - { - SourceHook::GetFuncInfo(&ISource2Server::Shutdown, mfp); - } - else - { - SourceHook::GetFuncInfo(&IServerGameDLL::DLLShutdown, mfp); - } - assert(mfp.isVirtual); - assert(mfp.thisptroffs == 0); - assert(mfp.vtbloffs == 0); - - if (g_is_source2) - { - vtable_src = (void **)*(void **)&is2s_thunk; - } - else - { - vtable_src = (void **)*(void **)&isgd_thunk; - } - vtable_dest = (void **)*(void **)gamedll_iface; - - isgd_orig_shutdown = vtable_dest[isgd_shutdown_index]; - vtable_dest[isgd_shutdown_index] = vtable_src[mfp.vtblindex]; -} - -#if defined _WIN32 -static void -mm_PatchAllowDedicated(bool patch) -{ - void **vtable_src; - void **vtable_dest; - SourceHook::MemFuncInfo mfp; - - SourceHook::GetFuncInfo(&ISource2ServerConfig::AllowDedicatedServers, mfp); - - assert(mfp.isVirtual); - assert(mfp.thisptroffs == 0); - assert(mfp.vtbloffs == 0); - - vtable_src = (void **) *(void **) &is2sc_thunk; - vtable_dest = (void **) *(void **) config_iface; - - SourceHook::SetMemAccess(&vtable_dest[is2sc_allowdedi_index], - sizeof(void*), - SH_MEM_READ | SH_MEM_WRITE | SH_MEM_EXEC); - - if (patch) - { - assert(is2sc_orig_allowdedi == NULL); - is2sc_orig_allowdedi = vtable_dest[is2sc_allowdedi_index]; - vtable_dest[is2sc_allowdedi_index] = vtable_src[mfp.vtblindex]; - } - else - { - assert(is2sc_orig_allowdedi != NULL); - vtable_dest[is2sc_allowdedi_index] = is2sc_orig_allowdedi; - is2sc_orig_allowdedi = NULL; - } -} -#endif - -static void -mm_PatchConnect(bool patch) -{ - void **vtable_src; - void **vtable_dest; - SourceHook::MemFuncInfo mfp; - - SourceHook::GetFuncInfo(&ISource2ServerConfig::Connect, mfp); - - assert(mfp.isVirtual); - assert(mfp.thisptroffs == 0); - assert(mfp.vtbloffs == 0); - - vtable_src = (void **) *(void **) &is2sc_thunk; - vtable_dest = (void **) *(void **) config_iface; - - SourceHook::SetMemAccess(&vtable_dest[mfp.vtblindex], - sizeof(void*), - SH_MEM_READ | SH_MEM_WRITE | SH_MEM_EXEC); - - if (patch) - { - assert(is2sc_orig_connect == NULL); - is2sc_orig_connect = vtable_dest[mfp.vtblindex]; - vtable_dest[mfp.vtblindex] = vtable_src[mfp.vtblindex]; - } - else - { - assert(is2sc_orig_connect != NULL); - vtable_dest[mfp.vtblindex] = is2sc_orig_connect; - is2sc_orig_connect = NULL; - } -} - - -void * -mm_GameDllRequest(const char *name, int *ret) -{ - if (strncmp(name, "Source2ServerConfig", 19) == 0) - { - g_is_source2 = true; - if (!mm_DetectGameInformation()) - { - if (ret != NULL) - *ret = 1; - return NULL; - } - - void *lib; - char error[255]; - void *ptr = NULL; - QueryValveInterface qvi; - for (unsigned int i = 0; i < gamedll_path_count; i++) - { - if (gamedll_libs[i] == NULL) - { - lib = mm_LoadLibrary(gamedll_paths[i], error, sizeof(error)); - if (lib == NULL) - continue; - gamedll_libs[i] = lib; - } - lib = gamedll_libs[i]; - qvi = (QueryValveInterface)mm_GetLibAddress(lib, "CreateInterface"); - if (qvi == NULL) - continue; - ptr = qvi(name, ret); - if (ptr != NULL) - { - gamedll_libs[i] = NULL; - break; - } - } - - if (ptr != NULL) - { - mm_FreeCachedLibraries(); - gamedll_lib = lib; - config_iface = (ISource2ServerConfig *) ptr; - gamedll_qvi = qvi; - - mm_PatchConnect(true); -#if defined _WIN32 - mm_PatchAllowDedicated(true); -#endif - - if (ret != NULL) - *ret = 0; - return ptr; - } - } - else if (strncmp(name, "Source2Server0", 14) == 0) - { - gamedll_iface = (IServerGameDLL *)gamedll_qvi(name, ret); - gamedll_version = atoi(&name[13]); - mm_PatchDllInit(true); - - if (ret != NULL) - *ret = 0; - return gamedll_iface; - } - else if (strncmp(name, "ServerGameDLL", 13) == 0) - { - if (!mm_DetectGameInformation()) - { - if (ret != NULL) - *ret = 1; - return NULL; - } - - void *lib; - char error[255]; - void *ptr = NULL; - QueryValveInterface qvi; - for (unsigned int i = 0; i < gamedll_path_count; i++) - { - if (gamedll_libs[i] == NULL) - { - lib = mm_LoadLibrary(gamedll_paths[i], error, sizeof(error)); - if (lib == NULL) - continue; - gamedll_libs[i] = lib; - } - lib = gamedll_libs[i]; - qvi = (QueryValveInterface)mm_GetLibAddress(lib, "CreateInterface"); - if (qvi == NULL) - continue; - ptr = qvi(name, ret); - if (ptr != NULL) - { - gamedll_libs[i] = NULL; - break; - } - } - - if (ptr != NULL) - { - mm_FreeCachedLibraries(); - gamedll_lib = lib; - gamedll_iface = (IServerGameDLL *)ptr; - gamedll_qvi = qvi; - gamedll_version = atoi(&name[13]); - mm_PatchDllInit(true); - - if (ret != NULL) - *ret = 0; - return ptr; - } - } - else if (gamedll_lib != NULL && gamedll_bridge == NULL) - { - return gamedll_qvi(name, ret); - } - else if (game_info_detected == 0) - { - mm_LogFatal("Received interface request too early: %s", name); - } - - if (ret != NULL) - *ret = 1; - return NULL; -} - diff --git a/utils/mmsource/loader/gamedll.h b/utils/mmsource/loader/gamedll.h deleted file mode 100644 index 06f1189a2..000000000 --- a/utils/mmsource/loader/gamedll.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * vim: set ts=4 : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2008 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_METAMOD_SOURCE_GAMEDLLS_H_ -#define _INCLUDE_METAMOD_SOURCE_GAMEDLLS_H_ - -#include "loader_bridge.h" - -extern void * -mm_GameDllRequest(const char *name, int *ret); - -extern IGameDllBridge* gamedll_bridge; - -#endif /* _INCLUDE_METAMOD_SOURCE_GAMEDLLS_H_ */ - diff --git a/utils/mmsource/loader/loader.cpp b/utils/mmsource/loader/loader.cpp deleted file mode 100644 index e03d3d48d..000000000 --- a/utils/mmsource/loader/loader.cpp +++ /dev/null @@ -1,446 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2015 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#include -#include -#include -#include -#include -#include -#include "loader.h" -#include "serverplugin.h" -#include "gamedll.h" -#include "utility.h" -#if defined __APPLE__ -#include -#endif - -static HMODULE mm_library = NULL; -static char mm_fatal_logfile[PLATFORM_MAX_PATH] = "metamod-fatal.log"; -MetamodBackend mm_backend = MMBackend_UNKNOWN; - -extern void -mm_LogFatal(const char *message, ...) -{ - FILE *fp; - time_t t; - va_list ap; - char header[256]; - - fp = fopen(mm_fatal_logfile, "at"); - if (!fp && (fp = fopen("metamod-fatal.log", "at")) == NULL) - return; - - t = time(NULL); - strftime(header, sizeof(header), "%m/%d/%Y - %H:%M:%S", localtime(&t)); - fprintf(fp, "L %s: ", header); - - va_start(ap, message); - vfprintf(fp, message, ap); - va_end(ap); - - fprintf(fp, "\n"); - - fclose(fp); -} - -static const char *backend_names[] = -{ - "2.ep1", - "2.darkm", - "2.ep2", - "2.bgt", - "2.eye", - "2.css", - "2.ep2v", - "2.l4d", - "2.l4d2", - "2.swarm", - "2.portal2", - "2.csgo", - "2.dota", - "2.hl2dm", - "2.dods", - "2.tf2", - "2.nd", - "2.sdk2013", - "2.blade", - "2.insurgency", - "2.contagion", - "2.bms", - "2.doi", -}; - -#if defined _WIN32 -#define LIBRARY_EXT ".dll" -#define LIBRARY_MINEXT ".dll" -#elif defined __APPLE__ -#define LIBRARY_EXT ".dylib" -#define LIBRARY_MINEXT ".dylib" -#elif defined __linux__ -#define LIBRARY_EXT LIB_SUFFIX -#define LIBRARY_MINEXT ".so" -#endif - -bool -mm_LoadMetamodLibrary(MetamodBackend backend, char *buffer, size_t maxlength) -{ - size_t len, temp_len; - char mm_path[PLATFORM_MAX_PATH * 2]; - - /* Get our path */ - if (!mm_GetFileOfAddress((void*)mm_GetFileOfAddress, mm_path, sizeof(mm_path))) - return false; - - len = strlen(mm_path); - - const char *pLastSlash = strrchr(mm_path, PATH_SEP_CHAR); - if (!pLastSlash) - return false; - - temp_len = strlen(&pLastSlash[1]); - if (len < temp_len) - return false; - - /* Build log file name */ - mm_path[len - temp_len] = '\0'; - mm_Format(mm_fatal_logfile, - sizeof(mm_fatal_logfile), - "%smetamod-fatal.log", - mm_path); - - /* Replace server.dll with the new binary we want */ - mm_Format(&mm_path[len - temp_len], - sizeof(mm_path) - (len - temp_len), - "metamod.%s" LIBRARY_MINEXT, - backend_names[backend]); - - mm_library = (HMODULE)mm_LoadLibrary(mm_path, buffer, maxlength); - - return (mm_library != NULL); -} - -void -mm_UnloadMetamodLibrary() -{ - mm_UnloadLibrary(mm_library); - mm_library = NULL; -} - -#if defined _WIN32 -#define EXPORT extern "C" __declspec(dllexport) -#elif defined __GNUC__ -#define EXPORT extern "C" __attribute__ ((visibility("default"))) -#endif - -EXPORT void * -CreateInterface(const char *name, int *ret) -{ - /* If we've got a VSP bridge, do nothing. */ - if (vsp_bridge != NULL) - { - if (ret != NULL) - *ret = 1; - return NULL; - } - - void *ptr; - if (strncmp(name, "ISERVERPLUGINCALLBACKS", 22) == 0) - { - /* Either load as VSP or start VSP listener */ - ptr = mm_GetVspCallbacks(atoi(&name[22])); - } - else if (gamedll_bridge == NULL) - { - /* Load as gamedll */ - ptr = mm_GameDllRequest(name, ret); - } - else - { - /* If we've got a gamedll bridge, forward the request. */ - return gamedll_bridge->QueryInterface(name, ret); - } - - if (ret != NULL) - *ret = (ptr != NULL) ? 0 : 1; - - return ptr; -} - -void * -mm_GetProcAddress(const char *name) -{ - return mm_GetLibAddress(mm_library, name); -} - -void -mm_GetGameName(char *buffer, size_t size) -{ - buffer[0] = '\0'; - bool bHasDedicated = false; - -#if defined _WIN32 - static char game[128]; - - LPWSTR pCmdLine = GetCommandLineW(); - int argc; - LPWSTR *wargv = CommandLineToArgvW(pCmdLine, &argc); - for (int i = 0; i < argc; ++i) - { - if (wcscmp(wargv[i], L"-game") == 0) - { - if (++i >= argc) - break; - - wcstombs(buffer, wargv[i], size); - buffer[size-1] = '\0'; - } - else if (wcscmp(wargv[i], L"-dedicated") == 0) - { - bHasDedicated = true; - } - } - - LocalFree(wargv); - -#elif defined __APPLE__ - int argc = *_NSGetArgc(); - char **argv = *_NSGetArgv(); - for (int i = 0; i < argc; ++i) - { - if (strcmp(argv[i], "-game") == 0) - { - if (++i >= argc) - break; - - strncpy(buffer, argv[i], size); - buffer[size-1] = '\0'; - } - else if (strcmp(argv[i], "-dedicated") == 0) - { - bHasDedicated = true; - } - } - -#elif defined __linux__ - FILE *pFile = fopen("/proc/self/cmdline", "rb"); - if (pFile) - { - char *arg = NULL; - size_t argsize = 0; - bool bNextIsGame = false; - - while (getdelim(&arg, &argsize, 0, pFile) != -1) - { - if (bNextIsGame) - { - strncpy(buffer, arg, size); - buffer[size-1] = '\0'; - bNextIsGame = false; - } - - if (strcmp(arg, "-game") == 0) - { - bNextIsGame = true; - } - else if (strcmp(arg, "-dedicated") == 0) - { - bHasDedicated = true; - } - } - - free(arg); - fclose(pFile); - } -#else -#error unsupported platform -#endif - - if (buffer[0] == 0) - { - // HackHackHack - Different engines have different defaults if -game isn't specified - // we only use this for game detection, and not even in all cases. Old behavior was to - // give back ".", which was only really accurate for Dark Messiah. We'll add a special - // case for Source2 / Dota as well, since it only supports gameinfo loading, which relies - // on accuracy here more than VSP loading. - if (bHasDedicated) - { - strncpy(buffer, "dota", size); - } - else - { - strncpy(buffer, ".", size); - } - } -} - -MetamodBackend -mm_DetermineBackend(QueryValveInterface engineFactory, QueryValveInterface serverFactory, const char *game_name) -{ - if (engineFactory("VEngineServer023", NULL) != NULL) - { - if (engineFactory("EngineTraceServer004", NULL) == NULL) - { - goto TF2branch; - } - - if (engineFactory("IEngineSoundServer004", NULL) != NULL) - { - void *lib = (void *)serverFactory; - void *addr; - if (strcmp(game_name, "doi") == 0 - || (addr = mm_FindPattern(lib, "doi_gamerules_data", sizeof("doi_gamerules_data") - 1))) - { - return MMBackend_DOI; - } - - return MMBackend_Insurgency; - } - - if (serverFactory("ServerGameDLL010", NULL) != NULL) - { - return MMBackend_BMS; - } - - return MMBackend_CSGO; - } - else if (engineFactory("VEngineServer022", NULL) != NULL && - engineFactory("VEngineCvar007", NULL) != NULL) - { - if (engineFactory("EngineTraceServer004", NULL) != NULL) - { - if (engineFactory("XboxSystemInterface001", NULL) != NULL) - { - return MMBackend_AlienSwarm; - } - - void *lib = (void *)serverFactory; - void *addr; - if (strcmp(game_name, "portal2") == 0 - || (addr = mm_FindPattern(lib, "baseportalcombatweapon", sizeof("baseportalcombatweapon") - 1))) - { - return MMBackend_Portal2; - } - - return MMBackend_Blade; - } - else if (engineFactory("VPrecacheSystem001", NULL) != NULL) - { - if (serverFactory("ServerGameTags002", NULL) != NULL) - { - return MMBackend_NuclearDawn; - } - else - { - void *lib = (void *)serverFactory; - void *addr; - if (strcmp(game_name, "contagion") == 0 - || (addr = mm_FindPattern(lib, "Contagion_Chat_All", sizeof("Contagion_Chat_All") - 1))) - { - return MMBackend_Contagion; - } - else - { - return MMBackend_Left4Dead2; - } - } - } - - return MMBackend_Left4Dead; - } - else if (engineFactory("VEngineServer021", NULL) != NULL) - { - /* Check for OB */ - if (engineFactory("VEngineCvar004", NULL) != NULL) - { - if (engineFactory("VModelInfoServer002", NULL) != NULL) - { - /* BGT has same iface version numbers and libs as ep2 */ - void *lib = (void *)serverFactory; - void *addr; - if (strcmp(game_name, "pm") == 0 - || (addr = mm_FindPattern(lib, "DT_PMPlayerResource", sizeof("DT_PMPlayerResource") - 1))) - { - return MMBackend_BloodyGoodTime; - } - else - { - return MMBackend_Episode2; - } - } - else if (engineFactory("VModelInfoServer003", NULL) != NULL) - { - if (engineFactory("VFileSystem017", NULL) != NULL) - { - return MMBackend_EYE; - } - else - { - TF2branch: - void *lib = (void *)serverFactory; - void *addr; - if (strcmp(game_name, "cstrike") == 0 - || (addr = mm_FindPattern(lib, "DT_CSPlayerResource", sizeof("DT_CSPlayerResource") - 1))) - { - return MMBackend_CSS; - } - else if (strcmp(game_name, "tf") == 0 - || (addr = mm_FindPattern(lib, "DT_TFPlayerResource", sizeof("DT_TFPlayerResource") - 1))) - { - return MMBackend_TF2; - } - else if (strcmp(game_name, "dod") == 0 - || (addr = mm_FindPattern(lib, "DT_DODPlayerResource", sizeof("DT_DODPlayerResource") - 1))) - { - return MMBackend_DODS; - } - else if (strcmp(game_name, "hl2mp") == 0) - { - return MMBackend_HL2DM; - } - else - { - return MMBackend_SDK2013; - } - } - } - } - /* Check for Episode One/Old Engine */ - else if (engineFactory("VModelInfoServer001", NULL) != NULL && - (engineFactory("VEngineCvar003", NULL) != NULL || - engineFactory("VEngineCvar002", NULL) != NULL)) - { - /* Check for Dark Messiah which has a weird directory structure */ - if (strcmp(game_name, ".") == 0) - { - return MMBackend_DarkMessiah; - } - return MMBackend_Episode1; - } - } - - return MMBackend_UNKNOWN; -} - diff --git a/utils/mmsource/loader/loader.h b/utils/mmsource/loader/loader.h deleted file mode 100644 index ca2e01d83..000000000 --- a/utils/mmsource/loader/loader.h +++ /dev/null @@ -1,131 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2015 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#ifndef _INCLUDE_METAMOD_SOURCE_LOADER_H_ -#define _INCLUDE_METAMOD_SOURCE_LOADER_H_ - -// System -#define SH_SYS_WIN32 1 -#define SH_SYS_LINUX 2 -#define SH_SYS_APPLE 3 - -// Platform -#define SH_XP_POSIX 10 -#define SH_XP_WINAPI 20 - -// Compiler -#define SH_COMP_GCC 1 -#define SH_COMP_MSVC 2 - -#if defined WIN32 -#define SH_SYS SH_SYS_WIN32 -#define SH_XP SH_XP_WINAPI -#define SH_COMP SH_COMP_MSVC -#define WINDOWS_LEAN_AND_MEAN -#include -#include -#define PLATFORM_MAX_PATH MAX_PATH -#define PATH_SEP_STR "\\" -#define PATH_SEP_CHAR '\\' -#define ALT_SEP_CHAR '/' -#elif defined __linux__ || defined __APPLE__ -#if defined __linux__ -#define SH_SYS SH_SYS_LINUX -#elif defined __APPLE__ -#define SH_SYS SH_SYS_APPLE -#endif -#define SH_XP SH_XP_POSIX -#define SH_COMP SH_COMP_GCC -#include -#include -#include -#include -#if SH_SYS == SH_SYS_APPLE -#include -#endif -typedef void * HMODULE; -#define PLATFORM_MAX_PATH PATH_MAX -#define PATH_SEP_STR "/" -#define PATH_SEP_CHAR '/' -#define ALT_SEP_CHAR '\\' -#else -#error "OS detection failed" -#endif - -#include "loader_bridge.h" - -#define SH_PTRSIZE sizeof(void*) - -enum MetamodBackend -{ - MMBackend_Episode1 = 0, - MMBackend_DarkMessiah, - MMBackend_Episode2, - MMBackend_BloodyGoodTime, - MMBackend_EYE, - MMBackend_CSS, - MMBackend_Episode2Valve_OBSOLETE, - MMBackend_Left4Dead, - MMBackend_Left4Dead2, - MMBackend_AlienSwarm, - MMBackend_Portal2, - MMBackend_CSGO, - MMBackend_DOTA, - MMBackend_HL2DM, - MMBackend_DODS, - MMBackend_TF2, - MMBackend_NuclearDawn, - MMBackend_SDK2013, - MMBackend_Blade, - MMBackend_Insurgency, - MMBackend_Contagion, - MMBackend_BMS, - MMBackend_DOI, - - MMBackend_UNKNOWN -}; - -extern bool -mm_LoadMetamodLibrary(MetamodBackend backend, char *buffer, size_t maxlength); - -extern void * -mm_GetProcAddress(const char *name); - -extern void -mm_UnloadMetamodLibrary(); - -extern void -mm_LogFatal(const char *message, ...); - -extern void -mm_GetGameName(char *buffer, size_t size); - -extern MetamodBackend -mm_DetermineBackend(QueryValveInterface engineFactory, QueryValveInterface serverFactory, const char *game_name); - -extern MetamodBackend mm_backend; - -#endif /* _INCLUDE_METAMOD_SOURCE_LOADER_H_ */ - diff --git a/utils/mmsource/loader/loader_bridge.h b/utils/mmsource/loader/loader_bridge.h deleted file mode 100644 index 07570ce84..000000000 --- a/utils/mmsource/loader/loader_bridge.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2009 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#ifndef _INCLUDE_METAMOD_SOURCE_LOADER_BRIDGE_H_ -#define _INCLUDE_METAMOD_SOURCE_LOADER_BRIDGE_H_ - -typedef void* (*QueryValveInterface)(const char *pName, int *pReturnCode); -class IServerPluginCallbacks; - -struct vsp_bridge_info -{ - QueryValveInterface engineFactory; - QueryValveInterface gsFactory; - IServerPluginCallbacks * vsp_callbacks; - unsigned int vsp_version; -}; - -class IVspBridge -{ -public: - virtual bool Load(const vsp_bridge_info *info, char *buffer, size_t maxlength) = 0; - virtual void Unload() = 0; - virtual const char *GetDescription() = 0; -}; - -struct gamedll_bridge_info -{ - QueryValveInterface engineFactory; - QueryValveInterface fsFactory; - QueryValveInterface physicsFactory; - QueryValveInterface gsFactory; - void * pGlobals; - unsigned int dllVersion; - void * isgd; - const char * vsp_listener_path; -}; - -class IGameDllBridge -{ -public: - virtual bool DLLInit_Pre(const gamedll_bridge_info *info, char *buffer, size_t maxlength) = 0; - virtual void DLLInit_Post(int *isgdUnload) = 0; - virtual void *QueryInterface(const char *name, int *ret) = 0; - virtual void Unload() = 0; -}; - -#endif /* _INCLUDE_METAMOD_SOURCE_LOADER_BRIDGE_H_ */ - diff --git a/utils/mmsource/loader/msvc10/mm_loader.sln b/utils/mmsource/loader/msvc10/mm_loader.sln deleted file mode 100644 index a3b6c5826..000000000 --- a/utils/mmsource/loader/msvc10/mm_loader.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mm_loader", "mm_loader.vcxproj", "{B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug|Win32.ActiveCfg = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug|Win32.Build.0 = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release|Win32.ActiveCfg = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/utils/mmsource/loader/msvc10/mm_loader.vcxproj b/utils/mmsource/loader/msvc10/mm_loader.vcxproj deleted file mode 100644 index 27e5edc86..000000000 --- a/utils/mmsource/loader/msvc10/mm_loader.vcxproj +++ /dev/null @@ -1,129 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90} - mm_loader - Win32Proj - - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - - - - - - - - - - - - - <_ProjectFileVersion>10.0.40219.1 - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - true - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - false - - - server - - - server - - - - Disabled - ..\..\core\sourcehook;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;LOADER_EXPORTS;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(OutDir)$(TargetFileName) - true - Windows - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - MaxSpeed - true - ..\..\core\sourcehook;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;LOADER_EXPORTS;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - true - - - Level3 - ProgramDatabase - - - BINARY_NAME="\"$(TargetFileName)\"";%(PreprocessorDefinitions) - ..\..\public;%(AdditionalIncludeDirectories) - - - $(OutDir)$(TargetFileName) - true - Windows - true - true - MachineX86 - - - IF NOT "%MMSOUTDIR%"=="" copy /Y "$(TargetDir)$(TargetFileName)" "%MMSOUTDIR%\bin" - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/utils/mmsource/loader/msvc10/mm_loader.vcxproj.filters b/utils/mmsource/loader/msvc10/mm_loader.vcxproj.filters deleted file mode 100644 index 914cd69b2..000000000 --- a/utils/mmsource/loader/msvc10/mm_loader.vcxproj.filters +++ /dev/null @@ -1,56 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Resource Files - - - \ No newline at end of file diff --git a/utils/mmsource/loader/msvc9/mm_loader.sln b/utils/mmsource/loader/msvc9/mm_loader.sln deleted file mode 100644 index b6d0cc4cc..000000000 --- a/utils/mmsource/loader/msvc9/mm_loader.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mm_loader", "mm_loader.vcproj", "{B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug|Win32.ActiveCfg = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug|Win32.Build.0 = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release|Win32.ActiveCfg = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/utils/mmsource/loader/msvc9/mm_loader.vcproj b/utils/mmsource/loader/msvc9/mm_loader.vcproj deleted file mode 100644 index 1b3127285..000000000 --- a/utils/mmsource/loader/msvc9/mm_loader.vcproj +++ /dev/null @@ -1,239 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/utils/mmsource/loader/serverplugin.cpp b/utils/mmsource/loader/serverplugin.cpp deleted file mode 100644 index 9daff2625..000000000 --- a/utils/mmsource/loader/serverplugin.cpp +++ /dev/null @@ -1,306 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2009 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#include -#include -#include -#include -#include "loader.h" -#include -#include -#include "serverplugin.h" -#include "gamedll.h" - -typedef enum -{ - PLUGIN_CONTINUE = 0, - PLUGIN_OVERRIDE, - PLUGIN_STOP, -} PLUGIN_RESULT; - -typedef enum -{ - eQueryCvarValueStatus_ValueIntact=0, - eQueryCvarValueStatus_CvarNotFound=1, - eQueryCvarValueStatus_NotACvar=2, - eQueryCvarValueStatus_CvarProtected=3 -} EQueryCvarValueStatus; - -typedef int QueryCvarCookie_t; -class CCommand; -class IServerPluginCallbacks; -struct edict_t; - -class IRandomThings -{ -public: - virtual PLUGIN_RESULT ClientCommand(edict_t *pEntity, const CCommand& args) - { - return PLUGIN_CONTINUE; - } -}; - -IVspBridge *vsp_bridge = NULL; - -/** - * The vtable must match the general layout for ISPC. We modify the vtable - * based on what we get back. - */ -class ServerPlugin -{ - char game_name[128]; - unsigned int vsp_version; - bool load_allowed; -public: - ServerPlugin() - { - load_allowed = false; - } - virtual bool Load(QueryValveInterface engineFactory, QueryValveInterface gsFactory) - { - if (!load_allowed) - return false; - - load_allowed = false; - - /* Backend should already filled in if loaded as gamedll */ - if (gamedll_bridge == NULL) - { - mm_GetGameName(game_name, sizeof(game_name)); - - mm_backend = mm_DetermineBackend(engineFactory, gsFactory, game_name); - } - - if (mm_backend == MMBackend_UNKNOWN) - { - mm_LogFatal("Could not detect engine version"); - return false; - } - - void **this_vtable; - this_vtable = (void **)*(void **)this; - - if (mm_backend != MMBackend_Episode1 - && mm_backend != MMBackend_DarkMessiah) - { - /* We need to insert the right type of call into this vtable */ - void **vtable_src; - IRandomThings sample; - SourceHook::MemFuncInfo mfp_dest, mfp_src; - - mfp_dest.isVirtual = false; - mfp_src.isVirtual = false; - - SourceHook::GetFuncInfo(&ServerPlugin::ClientCommand, mfp_dest); - SourceHook::GetFuncInfo(&IRandomThings::ClientCommand, mfp_src); - - assert(mfp_dest.isVirtual); - assert(mfp_dest.thisptroffs == 0); - assert(mfp_dest.vtbloffs == 0); - assert(mfp_src.isVirtual); - assert(mfp_src.thisptroffs == 0); - assert(mfp_src.vtbloffs == 0); - - vtable_src = (void **)*(void **)&sample; - SourceHook::SetMemAccess(&this_vtable[mfp_dest.vtblindex], - sizeof(void*), - SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC); - this_vtable[mfp_dest.vtblindex] = vtable_src[mfp_src.vtblindex]; - } - - /* AS inserted ClientFullyConnect into vtable, so move entries up on older engines */ - if (mm_backend != MMBackend_AlienSwarm - && mm_backend != MMBackend_Portal2 - && mm_backend != MMBackend_Blade - && mm_backend != MMBackend_Insurgency - && mm_backend != MMBackend_DOI - && mm_backend != MMBackend_CSGO - && mm_backend != MMBackend_DOTA) - { - SourceHook::MemFuncInfo mfp_fconnect; - mfp_fconnect.isVirtual = false; - - SourceHook::GetFuncInfo(&ServerPlugin::ClientFullyConnect, mfp_fconnect); - - assert(mfp_fconnect.isVirtual); - assert(mfp_fconnect.thisptroffs == 0); - assert(mfp_fconnect.vtbloffs == 0); - - /* Shifting ClientDisconnect through OnQueryCvarValueFinished up into slot for - * ClientFullyConnect (8 entries) - */ - SourceHook::SetMemAccess(&this_vtable[mfp_fconnect.vtblindex], - sizeof(void *) * 8, - SH_MEM_READ|SH_MEM_WRITE|SH_MEM_EXEC); - memmove(&this_vtable[mfp_fconnect.vtblindex], - &this_vtable[mfp_fconnect.vtblindex + 1], - sizeof(void *) * 8); - } - - char error[255]; - if (gamedll_bridge == NULL) - { - if (!mm_LoadMetamodLibrary(mm_backend, error, sizeof(error))) - { - mm_LogFatal("Detected engine %d but could not load: %s", mm_backend, error); - return false; - } - } - - typedef IVspBridge *(*GetVspBridge)(); - GetVspBridge get_bridge = (GetVspBridge)mm_GetProcAddress("GetVspBridge"); - if (get_bridge == NULL) - { - if (gamedll_bridge == NULL) - { - mm_UnloadMetamodLibrary(); - } - mm_LogFatal("Detected engine %d but could not find GetVspBridge callback", mm_backend); - return false; - } - - vsp_bridge = get_bridge(); - - vsp_bridge_info info; - - info.engineFactory = engineFactory; - info.gsFactory = gsFactory; - info.vsp_callbacks = (IServerPluginCallbacks*)this; - info.vsp_version = vsp_version; - - strcpy(error, "Unknown error"); - if (!vsp_bridge->Load(&info, error, sizeof(error))) - { - vsp_bridge = NULL; - if (gamedll_bridge == NULL) - { - mm_UnloadMetamodLibrary(); - } - mm_LogFatal("Unknown error loading Metamod for engine %d: %s", mm_backend, error); - return false; - } - - return true; - } - virtual void Unload() - { - if (vsp_bridge == NULL) - return; - vsp_bridge->Unload(); - - if (gamedll_bridge == NULL) - { - mm_UnloadMetamodLibrary(); - } - } - virtual void Pause() - { - } - virtual void UnPause() - { - } - virtual const char *GetPluginDescription() - { - if (vsp_bridge == NULL) - return "Metamod:Source Loader Shim"; - return vsp_bridge->GetDescription(); - } - virtual void LevelInit(char const *pMapName) - { - } - virtual void ServerActivate(edict_t *pEdictList, int edictCount, int clientMax) - { - } - virtual void GameFrame(bool simulating) - { - } - virtual void LevelShutdown() - { - } - virtual void ClientActive(edict_t *pEntity) - { - } - virtual void ClientFullyConnect(edict_t *pEntity) - { - } - virtual void ClientDisconnect(edict_t *pEntity) - { - } - virtual void ClientPutInServer(edict_t *pEntity, char const *playername) - { - } - virtual void SetCommandClient(int index) - { - } - virtual void ClientSettingsChanged(edict_t *pEdict) - { - } - virtual PLUGIN_RESULT ClientConnect(bool *bAllowConnect, - edict_t *pEntity, - const char *pszName, - const char *pszAddress, - char *reject, - int maxrejectlen) - { - return PLUGIN_CONTINUE; - } - virtual PLUGIN_RESULT ClientCommand(edict_t *pEntity) - { - return PLUGIN_CONTINUE; - } - virtual PLUGIN_RESULT NetworkIDValidated(const char *pszUserName, const char *pszNetworkID) - { - return PLUGIN_CONTINUE; - } - virtual void OnQueryCvarValueFinished(QueryCvarCookie_t iCookie, - edict_t *pPlayerEntity, - EQueryCvarValueStatus eStatus, - const char *pCvarName, - const char *pCvarValue) - { - } - void PrepForLoad(unsigned int version) - { - vsp_version = version; - load_allowed = true; - } -}; - -ServerPlugin mm_vsp_callbacks; - -void *mm_GetVspCallbacks(unsigned int version) -{ - if (vsp_bridge != NULL) - return NULL; - - /* Only support versions 1 or 2 right now */ - if (version > 2) - return NULL; - - mm_vsp_callbacks.PrepForLoad(version); - - return &mm_vsp_callbacks; -} - diff --git a/utils/mmsource/loader/serverplugin.h b/utils/mmsource/loader/serverplugin.h deleted file mode 100644 index 12a68d275..000000000 --- a/utils/mmsource/loader/serverplugin.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * vim: set ts=4 : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2008 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_METAMOD_SOURCE_SERVERPLUGINS_H_ -#define _INCLUDE_METAMOD_SOURCE_SERVERPLUGINS_H_ - -#include "loader_bridge.h" - -extern void * -mm_GetVspCallbacks(unsigned int version); - -extern IVspBridge *vsp_bridge; - -#endif /* _INCLUDE_METAMOD_SOURCE_SERVERPLUGINS_H_ */ - diff --git a/utils/mmsource/loader/utility.cpp b/utils/mmsource/loader/utility.cpp deleted file mode 100644 index 3733f3947..000000000 --- a/utils/mmsource/loader/utility.cpp +++ /dev/null @@ -1,611 +0,0 @@ -/** - * vim: set ts=4 : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2015 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - * Version: $Id$ - */ - -#include -#include -#include -#include -#include -#include -#include "loader.h" -#include "utility.h" - -#if defined __linux__ -#include - -#define PAGE_SIZE 4096 -#define PAGE_ALIGN_UP(x) ((x + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) -#elif defined __APPLE__ -#include -#endif - -#if defined _WIN32 -static void -mm_GetPlatformError(char *buffer, size_t maxlength) -{ - DWORD dw = GetLastError(); - FormatMessageA( - FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - dw, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)buffer, - maxlength, - NULL); -} -#endif - - -size_t -mm_FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list params) -{ - size_t len = vsnprintf(buffer, maxlength, fmt, params); - - if (len >= maxlength) - { - len = maxlength - 1; - buffer[len] = '\0'; - } - - return len; -} - -size_t -mm_Format(char *buffer, size_t maxlength, const char *fmt, ...) -{ - size_t len; - va_list ap; - - va_start(ap, fmt); - len = mm_FormatArgs(buffer, maxlength, fmt, ap); - va_end(ap); - - return len; -} - -size_t -mm_PathFormat(char *buffer, size_t maxlen, const char *fmt, ...) -{ - size_t len; - va_list ap; - - va_start(ap, fmt); - len = mm_FormatArgs(buffer, maxlen, fmt, ap); - va_end(ap); - - for (size_t i = 0; i < len; i++) - { - if (buffer[i] == ALT_SEP_CHAR) - buffer[i] = PATH_SEP_CHAR; - } - - return len; -} - -void -mm_TrimLeft(char *buffer) -{ - /* Let's think of this as our iterator */ - char *i = buffer; - - /* Make sure the buffer isn't null */ - if (i && *i) - { - /* Add up number of whitespace characters */ - while(isspace((unsigned char) *i)) - i++; - - /* If whitespace chars in buffer then adjust string so first non-whitespace char is at start of buffer */ - if (i != buffer) - memmove(buffer, i, (strlen(i) + 1) * sizeof(char)); - } -} - -void -mm_TrimRight(char *buffer) -{ - /* Make sure buffer isn't null */ - if (buffer) - { - size_t len = strlen(buffer); - - /* Loop through buffer backwards while replacing whitespace chars with null chars */ - for (size_t i = len - 1; i < len; i--) - { - if (isspace((unsigned char) buffer[i])) - buffer[i] = '\0'; - else - break; - } - } -} - -/* :TODO: this should skip string literals */ -void -mm_TrimComments(char *buffer) -{ - int num_sc = 0; - size_t len = strlen(buffer); - if (buffer) - { - for (int i = len - 1; i >= 0; i--) - { - if (buffer[i] == '/') - { - if (++num_sc >= 2 && i==0) - { - buffer[i] = '\0'; - return; - } - } - else - { - if (num_sc >= 2) - { - buffer[i] = '\0'; - return; - } - num_sc = 0; - } - /* size_t won't go below 0, manually break out */ - if (i == 0) - break; - - } - } -} - -void -mm_KeySplit(const char *str, char *buf1, size_t len1, char *buf2, size_t len2) -{ - size_t start; - size_t len = strlen(str); - - for (start = 0; start < len; start++) - { - if (!isspace(str[start])) - break; - } - - size_t end; - for (end = start; end < len; end++) - { - if (isspace(str[end])) - break; - } - - size_t i, c = 0; - for (i = start; i < end; i++, c++) - { - if (c >= len1) - break; - buf1[c] = str[i]; - } - buf1[c] = '\0'; - - for (start = end; start < len; start++) - { - if (!isspace(str[start])) - break; - } - - for (c = 0; start < len; start++, c++) - { - if (c >= len2) - break; - buf2[c] = str[start]; - } - buf2[c] = '\0'; -} - -bool -mm_PathCmp(const char *path1, const char *path2) -{ -#ifdef _WIN32 - char szFullPath1[PLATFORM_MAX_PATH]; - char szFullPath2[PLATFORM_MAX_PATH]; - if (GetFullPathName(path1, sizeof(szFullPath1), szFullPath1, nullptr) != 0) - { - path1 = szFullPath1; - } - if (GetFullPathName(path2, sizeof(szFullPath2), szFullPath2, nullptr) != 0) - { - path2 = szFullPath2; - } -#else - char szFullPath1[PATH_MAX + 1]; - char szFullPath2[PATH_MAX + 1]; - if (realpath(path1, szFullPath1)) - { - path1 = szFullPath1; - } - if (realpath(path2, szFullPath2)) - { - path2 = szFullPath2; - } -#endif - - size_t pos1 = 0, pos2 = 0; - - while (true) - { - if (path1[pos1] == '\0' || path2[pos2] == '\0') - return (path1[pos1] == path2[pos2]); - - if (path1[pos1] == PATH_SEP_CHAR) - { - if (path2[pos2] != PATH_SEP_CHAR) - return false; - - /* Look for extra path chars */ - while (path1[++pos1]) - { - if (path1[pos1] != PATH_SEP_CHAR) - break; - } - while (path2[++pos2]) - { - if (path2[pos2] != PATH_SEP_CHAR) - break; - } - continue; - } - - /* If we're at a different non-alphanumeric, the next character MUST match */ - if ((((unsigned)path1[pos1] & 0x80) && path1[pos1] != path2[pos2]) - || - (!isalpha(path1[pos1]) && (path1[pos1] != path2[pos2])) - ) - { - return false; - } - - #ifdef WIN32 - if (toupper(path1[pos1]) != toupper(path2[pos2])) - #else - if (path1[pos1] != path2[pos2]) - #endif - { - return false; - } - - pos1++; - pos2++; - } -} - -bool -mm_ResolvePath(const char *path, char *buffer, size_t maxlength, bool bSource2) -{ - char tmp[PLATFORM_MAX_PATH]; - if (bSource2) - { - mm_Format(tmp, sizeof(tmp), "../../%s", path); - path = tmp; - } -#if defined _WIN32 - return _fullpath(buffer, path, maxlength) != NULL; -#elif defined __linux__ || defined __APPLE__ - assert(maxlength >= PATH_MAX); - return realpath(path, buffer) != NULL; -#endif -} - -void * -mm_LoadLibrary(const char *path, char *buffer, size_t maxlength) -{ - void *lib; - -#if defined _WIN32 - lib = (void*)LoadLibrary(path); - - if (lib == NULL) - { - mm_GetPlatformError(buffer, maxlength); - return NULL; - } -#elif defined __linux__ || defined __APPLE__ - lib = dlopen(path, RTLD_NOW); - - if (lib == NULL) - { - mm_Format(buffer, maxlength, "%s", dlerror()); - return NULL; - } -#endif - - return lib; -} - -void * -mm_GetLibAddress(void *lib, const char *name) -{ -#if defined _WIN32 - return GetProcAddress((HMODULE)lib, name); -#elif defined __linux__ || defined __APPLE__ - return dlsym(lib, name); -#endif -} - -void -mm_UnloadLibrary(void *lib) -{ -#if defined _WIN32 - FreeLibrary((HMODULE)lib); -#elif defined __linux__ || defined __APPLE__ - dlclose(lib); -#endif -} - -bool -mm_GetFileOfAddress(void *pAddr, char *buffer, size_t maxlength) -{ -#if defined _WIN32 - MEMORY_BASIC_INFORMATION mem; - if (!VirtualQuery(pAddr, &mem, sizeof(mem))) - return false; - if (mem.AllocationBase == NULL) - return false; - HMODULE dll = (HMODULE)mem.AllocationBase; - GetModuleFileName(dll, (LPTSTR)buffer, maxlength); -#elif defined __linux__ || defined __APPLE__ - Dl_info info; - if (!dladdr(pAddr, &info)) - return false; - if (!info.dli_fbase || !info.dli_fname) - return false; - const char *dllpath = info.dli_fname; - snprintf(buffer, maxlength, "%s", dllpath); -#endif - return true; -} - -struct DynLibInfo -{ - void *baseAddress; - size_t memorySize; -}; - -static bool -mm_GetLibraryInfo(const void *libPtr, DynLibInfo &lib) -{ - uintptr_t baseAddr; - - if (libPtr == NULL) - { - return false; - } - -#ifdef _WIN32 - - MEMORY_BASIC_INFORMATION info; - IMAGE_DOS_HEADER *dos; - IMAGE_NT_HEADERS *pe; - IMAGE_FILE_HEADER *file; - IMAGE_OPTIONAL_HEADER *opt; - - if (!VirtualQuery(libPtr, &info, sizeof(MEMORY_BASIC_INFORMATION))) - { - return false; - } - - baseAddr = reinterpret_cast(info.AllocationBase); - - /* All this is for our insane sanity checks :o */ - dos = reinterpret_cast(baseAddr); - pe = reinterpret_cast(baseAddr + dos->e_lfanew); - file = &pe->FileHeader; - opt = &pe->OptionalHeader; - - /* Check PE magic and signature */ - if (dos->e_magic != IMAGE_DOS_SIGNATURE || pe->Signature != IMAGE_NT_SIGNATURE || opt->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) - { - return false; - } - - /* Check architecture, which is 32-bit/x86 right now - * Should change this for 64-bit if Valve gets their act together - */ - if (file->Machine != IMAGE_FILE_MACHINE_I386) - { - return false; - } - - /* For our purposes, this must be a dynamic library */ - if ((file->Characteristics & IMAGE_FILE_DLL) == 0) - { - return false; - } - - /* Finally, we can do this */ - lib.memorySize = opt->SizeOfImage; - -#elif defined __linux__ - - Dl_info info; - Elf32_Ehdr *file; - Elf32_Phdr *phdr; - uint16_t phdrCount; - - if (!dladdr(libPtr, &info)) - { - return false; - } - - if (!info.dli_fbase || !info.dli_fname) - { - return false; - } - - /* This is for our insane sanity checks :o */ - baseAddr = reinterpret_cast(info.dli_fbase); - file = reinterpret_cast(baseAddr); - - /* Check ELF magic */ - if (memcmp(ELFMAG, file->e_ident, SELFMAG) != 0) - { - return false; - } - - /* Check ELF version */ - if (file->e_ident[EI_VERSION] != EV_CURRENT) - { - return false; - } - - /* Check ELF architecture, which is 32-bit/x86 right now - * Should change this for 64-bit if Valve gets their act together - */ - if (file->e_ident[EI_CLASS] != ELFCLASS32 || file->e_machine != EM_386 || file->e_ident[EI_DATA] != ELFDATA2LSB) - { - return false; - } - - /* For our purposes, this must be a dynamic library/shared object */ - if (file->e_type != ET_DYN) - { - return false; - } - - phdrCount = file->e_phnum; - phdr = reinterpret_cast(baseAddr + file->e_phoff); - - for (uint16_t i = 0; i < phdrCount; i++) - { - Elf32_Phdr &hdr = phdr[i]; - - /* We only really care about the segment with executable code */ - if (hdr.p_type == PT_LOAD && hdr.p_flags == (PF_X|PF_R)) - { - /* From glibc, elf/dl-load.c: - * c->mapend = ((ph->p_vaddr + ph->p_filesz + GLRO(dl_pagesize) - 1) - * & ~(GLRO(dl_pagesize) - 1)); - * - * In glibc, the segment file size is aligned up to the nearest page size and - * added to the virtual address of the segment. We just want the size here. - */ - lib.memorySize = PAGE_ALIGN_UP(hdr.p_filesz); - break; - } - } - -#elif defined __APPLE__ - - Dl_info info; - struct mach_header *file; - struct segment_command *seg; - uint32_t cmd_count; - - if (!dladdr(libPtr, &info)) - { - return false; - } - - if (!info.dli_fbase || !info.dli_fname) - { - return false; - } - - /* This is for our insane sanity checks :o */ - baseAddr = (uintptr_t)info.dli_fbase; - file = (struct mach_header *)baseAddr; - - /* Check Mach-O magic */ - if (file->magic != MH_MAGIC) - { - return false; - } - - /* Check architecture (32-bit/x86) */ - if (file->cputype != CPU_TYPE_I386 || file->cpusubtype != CPU_SUBTYPE_I386_ALL) - { - return false; - } - - /* For our purposes, this must be a dynamic library */ - if (file->filetype != MH_DYLIB) - { - return false; - } - - cmd_count = file->ncmds; - seg = (struct segment_command *)(baseAddr + sizeof(struct mach_header)); - - /* Add up memory sizes of mapped segments */ - for (uint32_t i = 0; i < cmd_count; i++) - { - if (seg->cmd == LC_SEGMENT) - { - lib.memorySize += seg->vmsize; - } - - seg = (struct segment_command *)((uintptr_t)seg + seg->cmdsize); - } - -#endif - - lib.baseAddress = reinterpret_cast(baseAddr); - - return true; -} - -void *mm_FindPattern(const void *libPtr, const char *pattern, size_t len) -{ - DynLibInfo lib; - bool found; - char *ptr, *end; - - memset(&lib, 0, sizeof(DynLibInfo)); - - if (!mm_GetLibraryInfo(libPtr, lib)) - { - return NULL; - } - - ptr = reinterpret_cast(lib.baseAddress); - end = ptr + lib.memorySize - len; - - while (ptr < end) - { - found = true; - for (register size_t i = 0; i < len; i++) - { - if (pattern[i] != '\x2A' && pattern[i] != ptr[i]) - { - found = false; - break; - } - } - - if (found) - return ptr; - - ptr++; - } - - return NULL; -} diff --git a/utils/mmsource/loader/utility.h b/utils/mmsource/loader/utility.h deleted file mode 100644 index 25be3e65a..000000000 --- a/utils/mmsource/loader/utility.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * vim: set ts=4 : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2015 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_METAMOD_SOURCE_LOADER_UTILITY_H_ -#define _INCLUDE_METAMOD_SOURCE_LOADER_UTILITY_H_ - -#include - -extern size_t -mm_Format(char *buffer, size_t maxlength, const char *fmt, ...); - -extern void * -mm_LoadLibrary(const char *path, char *buffer, size_t maxlength); - -extern void * -mm_GetLibAddress(void *lib, const char *name); - -extern void -mm_UnloadLibrary(void *lib); - -extern bool -mm_ResolvePath(const char *path, char *buffer, size_t maxlength, bool bSource2); - -extern size_t -mm_PathFormat(char *buffer, size_t len, const char *fmt, ...); - -extern void -mm_TrimLeft(char *buffer); - -extern void -mm_TrimRight(char *buffer); - -extern void -mm_TrimComments(char *buffer); - -extern void -mm_KeySplit(const char *str, char *buf1, size_t len1, char *buf2, size_t len2); - -extern bool -mm_PathCmp(const char *path1, const char *path2); - -extern bool -mm_GetFileOfAddress(void *pAddr, char *buffer, size_t maxlength); - -extern void * -mm_FindPattern(const void *libPtr, const char *pattern, size_t len); - -#endif /* _INCLUDE_METAMOD_SOURCE_LOADER_UTILITY_H_ */ - diff --git a/utils/mmsource/loader/version.rc b/utils/mmsource/loader/version.rc deleted file mode 100644 index 7de5c4d78..000000000 --- a/utils/mmsource/loader/version.rc +++ /dev/null @@ -1,101 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" -#include - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION MMS_VERSION_FILE - PRODUCTVERSION MMS_VERSION_FILE - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000004b0" - BEGIN - VALUE "Comments", "Metamod: Source Loader" - VALUE "FileDescription", "Metamod: Source Loader" - VALUE "FileVersion", MMS_VERSION_STRING - VALUE "InternalName", "mmsource" - VALUE "LegalCopyright", "Copyright (c) 2004-2010, Metamod: Source Development Team" - VALUE "OriginalFilename", BINARY_NAME - VALUE "ProductName", "Metamod:Source Loader" - VALUE "ProductVersion", MMS_VERSION_STRING - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0, 1200 - END -END - - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED diff --git a/utils/mmsource/msvc10/MMSource.sln b/utils/mmsource/msvc10/MMSource.sln deleted file mode 100644 index d38be354c..000000000 --- a/utils/mmsource/msvc10/MMSource.sln +++ /dev/null @@ -1,290 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mm_core", "..\core\msvc10\mm_core.vcxproj", "{F7D47743-73B3-49B5-9D76-2333C5DFD565}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mm_core-legacy", "..\core-legacy\msvc10\mm_core-legacy.vcxproj", "{03B77DF1-F59B-4A86-AD80-8A60BDA3F491}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mm_loader", "..\loader\msvc10\mm_loader.vcxproj", "{B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_mm", "..\sample_mm\msvc10\sample_mm.vcxproj", "{E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stub_mm", "..\stub_mm\msvc10\stub_mm.vcxproj", "{EA8E7106-8D09-46A1-881B-FFBC4B8532F2}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sample Plugins", "Sample Plugins", "{0F80E7CA-E38A-4E25-805A-65B0F60BC9AD}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug - Alien Swarm|Win32 = Debug - Alien Swarm|Win32 - Debug - Bloody Good Time|Win32 = Debug - Bloody Good Time|Win32 - Debug - CS GO|Win32 = Debug - CS GO|Win32 - Debug - CSS|Win32 = Debug - CSS|Win32 - Debug - Dark Messiah|Win32 = Debug - Dark Messiah|Win32 - Debug - EYE|Win32 = Debug - EYE|Win32 - Debug - Left 4 Dead 2|Win32 = Debug - Left 4 Dead 2|Win32 - Debug - Left 4 Dead|Win32 = Debug - Left 4 Dead|Win32 - Debug - Orange Box Valve|Win32 = Debug - Orange Box Valve|Win32 - Debug - Orange Box|Win32 = Debug - Orange Box|Win32 - Debug - Original|Win32 = Debug - Original|Win32 - Debug - Portal 2|Win32 = Debug - Portal 2|Win32 - Debug|Win32 = Debug|Win32 - Release - Alien Swarm|Win32 = Release - Alien Swarm|Win32 - Release - Bloody Good Time|Win32 = Release - Bloody Good Time|Win32 - Release - CS GO|Win32 = Release - CS GO|Win32 - Release - CSS|Win32 = Release - CSS|Win32 - Release - Dark Messiah|Win32 = Release - Dark Messiah|Win32 - Release - EYE|Win32 = Release - EYE|Win32 - Release - Left 4 Dead 2|Win32 = Release - Left 4 Dead 2|Win32 - Release - Left 4 Dead|Win32 = Release - Left 4 Dead|Win32 - Release - Orange Box Valve|Win32 = Release - Orange Box Valve|Win32 - Release - Orange Box|Win32 = Release - Orange Box|Win32 - Release - Original|Win32 = Release - Original|Win32 - Release - Portal 2|Win32 = Release - Portal 2|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Debug - Alien Swarm|Win32.ActiveCfg = Debug|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Debug - Bloody Good Time|Win32.ActiveCfg = Debug|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Debug - CS GO|Win32.ActiveCfg = Debug|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Debug - CSS|Win32.ActiveCfg = Release|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Debug - Dark Messiah|Win32.ActiveCfg = Debug|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Debug - EYE|Win32.ActiveCfg = Debug|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Debug - Left 4 Dead 2|Win32.ActiveCfg = Debug|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Debug - Left 4 Dead|Win32.ActiveCfg = Debug|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Debug - Orange Box Valve|Win32.ActiveCfg = Debug|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Debug - Orange Box|Win32.ActiveCfg = Debug|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Debug - Original|Win32.ActiveCfg = Debug|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Debug - Original|Win32.Build.0 = Debug|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Debug - Portal 2|Win32.ActiveCfg = Debug|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Debug|Win32.ActiveCfg = Debug|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Debug|Win32.Build.0 = Debug|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Release - Alien Swarm|Win32.ActiveCfg = Release|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Release - Bloody Good Time|Win32.ActiveCfg = Release|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Release - CS GO|Win32.ActiveCfg = Release|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Release - CSS|Win32.ActiveCfg = Release|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Release - Dark Messiah|Win32.ActiveCfg = Release|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Release - EYE|Win32.ActiveCfg = Release|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Release - Left 4 Dead 2|Win32.ActiveCfg = Release|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Release - Left 4 Dead|Win32.ActiveCfg = Release|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Release - Orange Box Valve|Win32.ActiveCfg = Release|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Release - Orange Box|Win32.ActiveCfg = Release|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Release - Original|Win32.ActiveCfg = Release|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Release - Original|Win32.Build.0 = Release|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Release - Portal 2|Win32.ActiveCfg = Release|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Release|Win32.ActiveCfg = Release|Win32 - {03B77DF1-F59B-4A86-AD80-8A60BDA3F491}.Release|Win32.Build.0 = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - Alien Swarm|Win32.ActiveCfg = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - Alien Swarm|Win32.Build.0 = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - Bloody Good Time|Win32.ActiveCfg = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - Bloody Good Time|Win32.Build.0 = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - CS GO|Win32.ActiveCfg = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - CS GO|Win32.Build.0 = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - CSS|Win32.ActiveCfg = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - CSS|Win32.Build.0 = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - Dark Messiah|Win32.ActiveCfg = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - Dark Messiah|Win32.Build.0 = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - EYE|Win32.ActiveCfg = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - EYE|Win32.Build.0 = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - Left 4 Dead 2|Win32.ActiveCfg = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - Left 4 Dead 2|Win32.Build.0 = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - Left 4 Dead|Win32.ActiveCfg = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - Left 4 Dead|Win32.Build.0 = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - Orange Box Valve|Win32.ActiveCfg = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - Orange Box Valve|Win32.Build.0 = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - Orange Box|Win32.ActiveCfg = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - Orange Box|Win32.Build.0 = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - Original|Win32.ActiveCfg = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - Original|Win32.Build.0 = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - Portal 2|Win32.ActiveCfg = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug - Portal 2|Win32.Build.0 = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug|Win32.ActiveCfg = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Debug|Win32.Build.0 = Debug|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - Alien Swarm|Win32.ActiveCfg = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - Alien Swarm|Win32.Build.0 = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - Bloody Good Time|Win32.ActiveCfg = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - Bloody Good Time|Win32.Build.0 = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - CS GO|Win32.ActiveCfg = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - CS GO|Win32.Build.0 = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - CSS|Win32.ActiveCfg = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - CSS|Win32.Build.0 = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - Dark Messiah|Win32.ActiveCfg = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - Dark Messiah|Win32.Build.0 = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - EYE|Win32.ActiveCfg = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - EYE|Win32.Build.0 = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - Left 4 Dead 2|Win32.ActiveCfg = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - Left 4 Dead 2|Win32.Build.0 = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - Left 4 Dead|Win32.ActiveCfg = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - Left 4 Dead|Win32.Build.0 = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - Orange Box Valve|Win32.ActiveCfg = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - Orange Box Valve|Win32.Build.0 = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - Orange Box|Win32.ActiveCfg = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - Orange Box|Win32.Build.0 = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - Original|Win32.ActiveCfg = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - Original|Win32.Build.0 = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - Portal 2|Win32.ActiveCfg = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release - Portal 2|Win32.Build.0 = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release|Win32.ActiveCfg = Release|Win32 - {B8EBE5D8-739A-4ED4-83F7-E68CDED09F90}.Release|Win32.Build.0 = Release|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Alien Swarm|Win32.ActiveCfg = Debug - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Alien Swarm|Win32.Build.0 = Debug - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Bloody Good Time|Win32.ActiveCfg = Debug - Bloody Good Time|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Bloody Good Time|Win32.Build.0 = Debug - Bloody Good Time|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - CS GO|Win32.ActiveCfg = Debug - CS GO|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - CS GO|Win32.Build.0 = Debug - CS GO|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - CSS|Win32.ActiveCfg = Debug - CSS|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - CSS|Win32.Build.0 = Debug - CSS|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Dark Messiah|Win32.ActiveCfg = Debug - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Dark Messiah|Win32.Build.0 = Debug - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - EYE|Win32.ActiveCfg = Debug - EYE|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - EYE|Win32.Build.0 = Debug - EYE|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead 2|Win32.ActiveCfg = Debug - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead 2|Win32.Build.0 = Debug - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead|Win32.ActiveCfg = Debug - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead|Win32.Build.0 = Debug - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box Valve|Win32.ActiveCfg = Debug - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box Valve|Win32.Build.0 = Debug - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box|Win32.ActiveCfg = Debug - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box|Win32.Build.0 = Debug - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Original|Win32.ActiveCfg = Debug - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Original|Win32.Build.0 = Debug - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Portal 2|Win32.ActiveCfg = Debug - Portal 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Portal 2|Win32.Build.0 = Debug - Portal 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug|Win32.ActiveCfg = Debug - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug|Win32.Build.0 = Debug - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Alien Swarm|Win32.ActiveCfg = Release - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Alien Swarm|Win32.Build.0 = Release - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Bloody Good Time|Win32.ActiveCfg = Release - Bloody Good Time|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Bloody Good Time|Win32.Build.0 = Release - Bloody Good Time|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - CS GO|Win32.ActiveCfg = Release - CS GO|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - CS GO|Win32.Build.0 = Release - CS GO|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - CSS|Win32.ActiveCfg = Release - CSS|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - CSS|Win32.Build.0 = Release - CSS|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Dark Messiah|Win32.ActiveCfg = Release - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Dark Messiah|Win32.Build.0 = Release - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - EYE|Win32.ActiveCfg = Release - EYE|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - EYE|Win32.Build.0 = Release - EYE|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead 2|Win32.ActiveCfg = Release - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead 2|Win32.Build.0 = Release - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead|Win32.ActiveCfg = Release - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead|Win32.Build.0 = Release - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box Valve|Win32.ActiveCfg = Release - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box Valve|Win32.Build.0 = Release - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box|Win32.ActiveCfg = Release - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box|Win32.Build.0 = Release - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Original|Win32.ActiveCfg = Release - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Original|Win32.Build.0 = Release - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Portal 2|Win32.ActiveCfg = Release - Portal 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Portal 2|Win32.Build.0 = Release - Portal 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release|Win32.ActiveCfg = Release - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release|Win32.Build.0 = Release - Original|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - Alien Swarm|Win32.ActiveCfg = Debug - Alien Swarm|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - Alien Swarm|Win32.Build.0 = Debug - Alien Swarm|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - Bloody Good Time|Win32.ActiveCfg = Debug - Bloody Good Time|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - Bloody Good Time|Win32.Build.0 = Debug - Bloody Good Time|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - CS GO|Win32.ActiveCfg = Debug - CS GO|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - CS GO|Win32.Build.0 = Debug - CS GO|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - CSS|Win32.ActiveCfg = Debug - CSS|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - CSS|Win32.Build.0 = Debug - CSS|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - Dark Messiah|Win32.ActiveCfg = Debug - Dark Messiah|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - Dark Messiah|Win32.Build.0 = Debug - Dark Messiah|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - EYE|Win32.ActiveCfg = Debug - EYE|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - EYE|Win32.Build.0 = Debug - EYE|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - Left 4 Dead 2|Win32.ActiveCfg = Debug - Left 4 Dead 2|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - Left 4 Dead 2|Win32.Build.0 = Debug - Left 4 Dead 2|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - Left 4 Dead|Win32.ActiveCfg = Debug - Left 4 Dead|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - Left 4 Dead|Win32.Build.0 = Debug - Left 4 Dead|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - Orange Box Valve|Win32.ActiveCfg = Debug - Orange Box Valve|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - Orange Box Valve|Win32.Build.0 = Debug - Orange Box Valve|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - Orange Box|Win32.ActiveCfg = Debug - Orange Box|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - Orange Box|Win32.Build.0 = Debug - Orange Box|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - Original|Win32.ActiveCfg = Debug - Original|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - Original|Win32.Build.0 = Debug - Original|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - Portal 2|Win32.ActiveCfg = Debug - Portal 2|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug - Portal 2|Win32.Build.0 = Debug - Portal 2|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug|Win32.ActiveCfg = Debug - Left 4 Dead|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Debug|Win32.Build.0 = Debug - Left 4 Dead|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - Alien Swarm|Win32.ActiveCfg = Release - Alien Swarm|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - Alien Swarm|Win32.Build.0 = Release - Alien Swarm|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - Bloody Good Time|Win32.ActiveCfg = Release - Bloody Good Time|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - Bloody Good Time|Win32.Build.0 = Release - Bloody Good Time|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - CS GO|Win32.ActiveCfg = Release - CS GO|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - CS GO|Win32.Build.0 = Release - CS GO|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - CSS|Win32.ActiveCfg = Release - CSS|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - CSS|Win32.Build.0 = Release - CSS|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - Dark Messiah|Win32.ActiveCfg = Release - Dark Messiah|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - Dark Messiah|Win32.Build.0 = Release - Dark Messiah|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - EYE|Win32.ActiveCfg = Release - EYE|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - EYE|Win32.Build.0 = Release - EYE|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - Left 4 Dead 2|Win32.ActiveCfg = Release - Left 4 Dead 2|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - Left 4 Dead 2|Win32.Build.0 = Release - Left 4 Dead 2|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - Left 4 Dead|Win32.ActiveCfg = Release - Left 4 Dead|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - Left 4 Dead|Win32.Build.0 = Release - Left 4 Dead|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - Orange Box Valve|Win32.ActiveCfg = Release - Orange Box Valve|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - Orange Box Valve|Win32.Build.0 = Release - Orange Box Valve|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - Orange Box|Win32.ActiveCfg = Release - Orange Box|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - Orange Box|Win32.Build.0 = Release - Orange Box|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - Original|Win32.ActiveCfg = Release - Original|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - Original|Win32.Build.0 = Release - Original|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - Portal 2|Win32.ActiveCfg = Release - Portal 2|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release - Portal 2|Win32.Build.0 = Release - Portal 2|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release|Win32.ActiveCfg = Release - Orange Box|Win32 - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2}.Release|Win32.Build.0 = Release - Orange Box|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Alien Swarm|Win32.ActiveCfg = Debug - Alien Swarm|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Alien Swarm|Win32.Build.0 = Debug - Alien Swarm|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Bloody Good Time|Win32.ActiveCfg = Debug - Bloody Good Time|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Bloody Good Time|Win32.Build.0 = Debug - Bloody Good Time|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - CS GO|Win32.ActiveCfg = Debug - CS GO|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - CS GO|Win32.Build.0 = Debug - CS GO|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - CSS|Win32.ActiveCfg = Debug - CSS|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - CSS|Win32.Build.0 = Debug - CSS|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Dark Messiah|Win32.ActiveCfg = Debug - Dark Messiah|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Dark Messiah|Win32.Build.0 = Debug - Dark Messiah|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - EYE|Win32.ActiveCfg = Debug - EYE|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - EYE|Win32.Build.0 = Debug - EYE|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Left 4 Dead 2|Win32.ActiveCfg = Debug - Left 4 Dead 2|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Left 4 Dead 2|Win32.Build.0 = Debug - Left 4 Dead 2|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Left 4 Dead|Win32.ActiveCfg = Debug - Left 4 Dead|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Left 4 Dead|Win32.Build.0 = Debug - Left 4 Dead|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Orange Box Valve|Win32.ActiveCfg = Debug - Orange Box Valve|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Orange Box Valve|Win32.Build.0 = Debug - Orange Box Valve|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Orange Box|Win32.ActiveCfg = Debug - Orange Box|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Orange Box|Win32.Build.0 = Debug - Orange Box|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Original|Win32.ActiveCfg = Debug - Orange Box|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Portal 2|Win32.ActiveCfg = Debug - Portal 2|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug - Portal 2|Win32.Build.0 = Debug - Portal 2|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug|Win32.ActiveCfg = Debug - Orange Box|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug|Win32.Build.0 = Debug - Orange Box|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Alien Swarm|Win32.ActiveCfg = Release - Alien Swarm|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Alien Swarm|Win32.Build.0 = Release - Alien Swarm|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Bloody Good Time|Win32.ActiveCfg = Release - Bloody Good Time|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Bloody Good Time|Win32.Build.0 = Release - Bloody Good Time|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - CS GO|Win32.ActiveCfg = Release - CS GO|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - CS GO|Win32.Build.0 = Release - CS GO|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - CSS|Win32.ActiveCfg = Release - CSS|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - CSS|Win32.Build.0 = Release - CSS|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Dark Messiah|Win32.ActiveCfg = Release - Dark Messiah|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Dark Messiah|Win32.Build.0 = Release - Dark Messiah|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - EYE|Win32.ActiveCfg = Release - EYE|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - EYE|Win32.Build.0 = Release - EYE|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Left 4 Dead 2|Win32.ActiveCfg = Release - Left 4 Dead 2|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Left 4 Dead 2|Win32.Build.0 = Release - Left 4 Dead 2|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Left 4 Dead|Win32.ActiveCfg = Release - Left 4 Dead|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Left 4 Dead|Win32.Build.0 = Release - Left 4 Dead|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Orange Box Valve|Win32.ActiveCfg = Release - Orange Box Valve|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Orange Box Valve|Win32.Build.0 = Release - Orange Box Valve|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Orange Box|Win32.ActiveCfg = Release - Orange Box|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Orange Box|Win32.Build.0 = Release - Orange Box|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Original|Win32.ActiveCfg = Release - Orange Box|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Portal 2|Win32.ActiveCfg = Release - Portal 2|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release - Portal 2|Win32.Build.0 = Release - Portal 2|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release|Win32.ActiveCfg = Release - Orange Box|Win32 - {F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release|Win32.Build.0 = Release - Orange Box|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9} = {0F80E7CA-E38A-4E25-805A-65B0F60BC9AD} - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2} = {0F80E7CA-E38A-4E25-805A-65B0F60BC9AD} - EndGlobalSection -EndGlobal diff --git a/utils/mmsource/product.version b/utils/mmsource/product.version deleted file mode 100644 index 1f724bf45..000000000 --- a/utils/mmsource/product.version +++ /dev/null @@ -1 +0,0 @@ -1.11.0-dev diff --git a/utils/mmsource/public/metamod_version.h b/utils/mmsource/public/metamod_version.h deleted file mode 100644 index 2fb3ac1e4..000000000 --- a/utils/mmsource/public/metamod_version.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2010 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#ifndef _INCLUDE_METAMOD_VERSION_INFORMATION_H_ -#define _INCLUDE_METAMOD_VERSION_INFORMATION_H_ - -/** - * @file Contains Metamod version information. - * @brief This file will redirect to an autogenerated version if being compiled via - * the build scripts. - */ - -#if defined MMS_GENERATED_BUILD -# if defined RC_COMPILE -# undef MMS_USE_VERSIONLIB -# endif -# if defined MMS_USE_VERSIONLIB -# include -# else -# include -# endif -#else -#define MMS_BUILD_TAG "manual" -#define MMS_BUILD_LOCAL_REV "0" -#define MMS_BUILD_CSET "0" -#define MMS_BUILD_MAJOR "1" -#define MMS_BUILD_MINOR "11" -#define MMS_BUILD_RELEASE "0" - -#define MMS_BUILD_UNIQUEID MMS_BUILD_LOCAL_REV ":" MMS_BUILD_CSET - -#define MMS_VERSION_STRING MMS_BUILD_MAJOR "." MMS_BUILD_MINOR "." MMS_BUILD_RELEASE "-" MMS_BUILD_TAG -#define MMS_VERSION_FILE 1,11,0,0 -#endif -#define MMS_BUILD_TIMESTAMP __DATE__ " " __TIME__ - -#if !defined(MMS_GENERATED_BUILD) || !defined(MMS_USE_VERSIONLIB) -# define METAMOD_VERSION MMS_VERSION_STRING -# define METAMOD_BUILD_ID MMS_BUILD_UNIQUEID -# define METAMOD_BUILD_TIME MMS_BUILD_TIMESTAMP -#endif - -#endif /* _INCLUDE_METAMOD_VERSION_INFORMATION_H_ */ - diff --git a/utils/mmsource/pushbuild.txt b/utils/mmsource/pushbuild.txt deleted file mode 100644 index c0bc98169..000000000 --- a/utils/mmsource/pushbuild.txt +++ /dev/null @@ -1,38 +0,0 @@ -MM:S and SM load on Portal on Mac OS X. How cool is that? -It would be cool if the OS X package uploaded though. -Burgledorfs and blaggermuffins are among the king's favorites. -Ten ticket takers tackled two terrible tyrants. -There once was a -Breaking builds, one push at a time. -Thanks for more IFileSystem breakage. -Bloody, missing sdk! -yur an IServerGameDLLLLL -hats -oh, i'll get it right this time -I'd be angry. -rum hom! -bees bees bees? -she calls it a mayonegg -Why is Windows so awful? -cleng cling clang clung clong -javaliabuf -egg. -pulled pork, yeah... -king of the javalias -ducks versus geese, who will win? -more like g_pBad -I didn't have any dreams. -Eat your potato, Ricky! -Buildbot shall pay the iron price. -BMO Chop! If this was a real attack, you'd be dead. -Hey Morty! -jam clam! -her? -Confused clams claim clowns clobber clans containing cloaked clients. -Beads -We've have it all! -dvander is one million ladies tall today... -Your tier1 tower is under attack.. -Christmas! -is Skinny Pete any relation to Sneaky Pete??? -where Travis? diff --git a/utils/mmsource/sample_mm/Makefile b/utils/mmsource/sample_mm/Makefile deleted file mode 100644 index e948f4d06..000000000 --- a/utils/mmsource/sample_mm/Makefile +++ /dev/null @@ -1,230 +0,0 @@ -# (C)2004-2010 Metamod:Source Development Team -# Makefile written by David "BAILOPAN" Anderson - -########################################### -### EDIT THESE PATHS FOR YOUR OWN SETUP ### -########################################### - -HL2SDK_ORIG = ../../hl2sdk -HL2SDK_OB = ../../hl2sdk-ob -HL2SDK_CSS = ../../hl2sdk-css -HL2SDK_OB_VALVE = ../../hl2sdk-ob-valve -HL2SDK_L4D = ../../hl2sdk-l4d -HL2SDK_L4D2 = ../../hl2sdk-l4d2 -HL2SDK_CSGO = ../../hl2sdk-csgo -MMSOURCE19 = .. - -##################################### -### EDIT BELOW FOR OTHER PROJECTS ### -##################################### - -PROJECT = sample_mm -OBJECTS = sample_mm.cpp - -############################################## -### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ### -############################################## - -OPT_FLAGS = -O3 -funroll-loops -pipe -GCC4_FLAGS = -fvisibility=hidden -fvisibility-inlines-hidden -std=c++11 -DEBUG_FLAGS = -g -ggdb3 -D_DEBUG -CPP = gcc -CPP_OSX = clang - -########################## -### SDK CONFIGURATIONS ### -########################## - -override ENGSET = false - -# Check for valid list of engines -ifneq (,$(filter original orangebox orangeboxvalve css left4dead left4dead2 csgo,$(ENGINE))) - override ENGSET = true -endif - -ifeq "$(ENGINE)" "original" - HL2SDK = $(HL2SDK_ORIG) - CFLAGS += -DSOURCE_ENGINE=1 -endif -ifeq "$(ENGINE)" "orangebox" - HL2SDK = $(HL2SDK_OB) - CFLAGS += -DSOURCE_ENGINE=3 -endif -ifeq "$(ENGINE)" "css" - HL2SDK = $(HL2SDK_CSS) - CFLAGS += -DSOURCE_ENGINE=6 -endif -ifeq "$(ENGINE)" "orangeboxvalve" - HL2SDK = $(HL2SDK_OB_VALVE) - CFLAGS += -DSOURCE_ENGINE=7 -endif -ifeq "$(ENGINE)" "left4dead" - HL2SDK = $(HL2SDK_L4D) - CFLAGS += -DSOURCE_ENGINE=8 -endif -ifeq "$(ENGINE)" "left4dead2" - HL2SDK = $(HL2SDK_L4D2) - CFLAGS += -DSOURCE_ENGINE=9 -endif -ifeq "$(ENGINE)" "csgo" - HL2SDK = $(HL2SDK_CSGO) - CFLAGS += -DSOURCE_ENGINE=12 -endif - -HL2PUB = $(HL2SDK)/public - -ifeq "$(ENGINE)" "original" - INCLUDE += -I$(HL2SDK)/public/dlls - METAMOD = $(MMSOURCE19)/core-legacy -else - INCLUDE += -I$(HL2SDK)/public/game/server - METAMOD = $(MMSOURCE19)/core -endif - -OS := $(shell uname -s) - -ifeq "$(OS)" "Darwin" - LIB_EXT = dylib - ifeq "$(ENGINE)" "csgo" - HL2LIB = $(HL2SDK)/lib/osx64 - else - HL2LIB = $(HL2SDK)/lib/mac - endif -else - LIB_EXT = so - ifeq "$(ENGINE)" "original" - HL2LIB = $(HL2SDK)/linux_sdk - else - HL2LIB = $(HL2SDK)/lib/linux - endif -endif - -# if ENGINE is original or OB -ifneq (,$(filter original orangebox,$(ENGINE))) - LIB_SUFFIX = _i486.$(LIB_EXT) -else - LIB_PREFIX = lib - ifneq (,$(filter orangeboxvalve css left4dead2,$(ENGINE))) - ifneq "$(OS)" "Darwin" - LIB_SUFFIX = _srv.$(LIB_EXT) - else - LIB_SUFFIX = .$(LIB_EXT) - endif - else - LIB_SUFFIX = .$(LIB_EXT) - endif -endif - -ifeq "$(OS)" "Darwin" - ifeq "$(ENGINE)" "csgo" - STATIC_SUFFIX = - LIB_SUFFIX = .x64.$(LIB_EXT) - else - STATIC_SUFFIX = _i486 - endif -else - STATIC_SUFFIX = _i486 -endif - -CFLAGS += -DSE_EPISODEONE=1 -DSE_DARKMESSIAH=2 -DSE_ORANGEBOX=3 -DSE_BLOODYGOODTIME=4 -DSE_EYE=5 \ - -DSE_CSS=6 -DSE_ORANGEBOXVALVE=7 -DSE_LEFT4DEAD=8 -DSE_LEFT4DEAD2=9 -DSE_ALIENSWARM=10 \ - -DSE_PORTAL2=11 -DSE_CSGO=12 - -LINK += $(HL2LIB)/tier1$(STATIC_SUFFIX).a $(LIB_PREFIX)vstdlib$(LIB_SUFFIX) $(LIB_PREFIX)tier0$(LIB_SUFFIX) - -ifeq "$(ENGINE)" "csgo" - LINK += $(HL2LIB)/interfaces$(STATIC_SUFFIX).a -endif - -INCLUDE += -I. -I.. -I$(HL2PUB) -I$(HL2PUB)/engine -I$(HL2PUB)/mathlib -I$(HL2PUB)/vstdlib \ - -I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 -I. -I$(METAMOD) -I$(METAMOD)/sourcehook - -################################################ -### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ### -################################################ - -BINARY = $(PROJECT).$(LIB_EXT) - -ifeq "$(DEBUG)" "true" - BIN_DIR = Debug.$(ENGINE) - CFLAGS += $(DEBUG_FLAGS) -else - BIN_DIR = Release.$(ENGINE) - CFLAGS += $(OPT_FLAGS) -endif - -ifeq "$(OS)" "Darwin" - CPP = $(CPP_OSX) - LIB_EXT = dylib - CFLAGS += -DOSX -D_OSX -mmacosx-version-min=10.9 - LINK += -dynamiclib -lc++ -mmacosx-version-min=10.9 - ifeq "$(ENGINE)" "csgo" - CFLAGS += -m64 -DX64BITS -DPLATFORM_64BITS - LINK += -m64 - else - CFLAGS += -m32 - LINK += -m32 - endif -else - LIB_EXT = so - CFLAGS += -D_LINUX -m32 - LINK += -shared -m32 -endif - -IS_CLANG := $(shell $(CPP) --version | head -1 | grep clang > /dev/null && echo "1" || echo "0") - -ifeq "$(IS_CLANG)" "1" - CPP_MAJOR := $(shell $(CPP) --version | grep clang | sed "s/.*version \([0-9]\)*\.[0-9]*.*/\1/") - CPP_MINOR := $(shell $(CPP) --version | grep clang | sed "s/.*version [0-9]*\.\([0-9]\)*.*/\1/") -else - CPP_MAJOR := $(shell $(CPP) -dumpversion >&1 | cut -b1) - CPP_MINOR := $(shell $(CPP) -dumpversion >&1 | cut -b3) -endif - -CFLAGS += -DPOSIX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp \ - -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca \ - -Dstrcmpi=strcasecmp -DCOMPILER_GCC -Wall -Wno-non-virtual-dtor -Wno-overloaded-virtual \ - -Werror -fPIC -fno-exceptions -fno-rtti -msse -fno-strict-aliasing - -# Clang || GCC >= 4 -ifeq "$(shell expr $(IS_CLANG) \| $(CPP_MAJOR) \>= 4)" "1" - CFLAGS += $(GCC4_FLAGS) -endif - -# Clang >= 3 || GCC >= 4.7 -ifeq "$(shell expr $(IS_CLANG) \& $(CPP_MAJOR) \>= 3 \| $(CPP_MAJOR) \>= 4 \& $(CPP_MINOR) \>= 7)" "1" - CFLAGS += -Wno-delete-non-virtual-dtor -Wno-unused-private-field -Wno-deprecated-register -endif - -# OS is Linux and not using clang -ifeq "$(shell expr $(OS) \= Linux \& $(IS_CLANG) \= 0)" "1" - LINK += -static-libgcc -endif - -OBJ_BIN := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o) - -$(BIN_DIR)/%.o: %.cpp - $(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $< - -all: check - mkdir -p $(BIN_DIR) - ln -sf $(HL2LIB)/$(LIB_PREFIX)vstdlib$(LIB_SUFFIX) - ln -sf $(HL2LIB)/$(LIB_PREFIX)tier0$(LIB_SUFFIX) - $(MAKE) -f Makefile sample_mm - -check: - if [ "$(ENGSET)" = "false" ]; then \ - echo "You must supply one of the following values for ENGINE:"; \ - echo "csgo, left4dead2, left4dead, css, orangeboxvalve, orangebox, or original"; \ - exit 1; \ - fi - -sample_mm: check $(OBJ_BIN) - $(CPP) $(INCLUDE) $(OBJ_BIN) $(LINK) -ldl -lm -o $(BIN_DIR)/$(BINARY) - -default: all - -clean: check - rm -rf $(BIN_DIR)/*.o - rm -rf $(BIN_DIR)/$(BINARY) - diff --git a/utils/mmsource/sample_mm/README.txt b/utils/mmsource/sample_mm/README.txt deleted file mode 100644 index aa8cbc133..000000000 --- a/utils/mmsource/sample_mm/README.txt +++ /dev/null @@ -1,4 +0,0 @@ -For more information on compiling and reading the plugin's source code, see: - - http://wiki.alliedmods.net/Category:Metamod:Source_Development - diff --git a/utils/mmsource/sample_mm/engine_wrappers.h b/utils/mmsource/sample_mm/engine_wrappers.h deleted file mode 100644 index 1f883e1c0..000000000 --- a/utils/mmsource/sample_mm/engine_wrappers.h +++ /dev/null @@ -1,98 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source Sample Plugin - * Written by AlliedModders LLC. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * This sample plugin is public domain. - */ - -#ifndef _INCLUDE_SOURCE_ENGINE_WRAPPERS_ -#define _INCLUDE_SOURCE_ENGINE_WRAPPERS_ - -#include - -extern IVEngineServer *engine; -extern CGlobalVars *gpGlobals; - -#if SOURCE_ENGINE == SE_EPISODEONE && defined METAMOD_PLAPI_VERSION -#error "Metamod:Source 1.6 API is not supported on the old engine." -#endif - -#define ENGINE_CALL(func) SH_CALL(engine, &IVEngineServer::func) - -/** - * Wrap some API calls for legacy MM:S. - */ -#if !defined METAMOD_PLAPI_VERSION -#define GetEngineFactory engineFactory -#define GetServerFactory serverFactory -#define MM_Format snprintf -#define GetCGlobals pGlobals -#else -#define MM_Format g_SMAPI->Format -#endif - -#if SOURCE_ENGINE <= SE_DARKMESSIAH -/** - * Wrap the CCommand class so our code looks the same on all engines. - */ -class CCommand -{ -public: - const char *ArgS() - { - return engine->Cmd_Args(); - } - int ArgC() - { - return engine->Cmd_Argc(); - } - - const char *Arg(int index) - { - return engine->Cmd_Argv(index); - } -}; - -#define CVAR_INTERFACE_VERSION VENGINE_CVAR_INTERFACE_VERSION -#endif - -/** - * Left 4 Dead engine removed these from IVEngineServer. - */ -#if SOURCE_ENGINE >= SE_LEFT4DEAD - -inline int IndexOfEdict(const edict_t *pEdict) -{ - return (int)(pEdict - gpGlobals->pEdicts); -} -inline edict_t *PEntityOfEntIndex(int iEntIndex) -{ - if (iEntIndex >= 0 && iEntIndex < gpGlobals->maxEntities) - { - return (edict_t *)(gpGlobals->pEdicts + iEntIndex); - } - return NULL; -} - -#else - -inline int IndexOfEdict(const edict_t *pEdict) -{ - return engine->IndexOfEdict(pEdict); -} -inline edict_t *PEntityOfEntIndex(int iEntIndex) -{ - return engine->PEntityOfEntIndex(iEntIndex); -} - -#endif - -#endif //_INCLUDE_SOURCE_ENGINE_WRAPPERS_ - diff --git a/utils/mmsource/sample_mm/msvc10/sample_mm.sln b/utils/mmsource/sample_mm/msvc10/sample_mm.sln deleted file mode 100644 index 14216110f..000000000 --- a/utils/mmsource/sample_mm/msvc10/sample_mm.sln +++ /dev/null @@ -1,56 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_mm", "sample_mm.vcxproj", "{E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug - Alien Swarm|Win32 = Debug - Alien Swarm|Win32 - Debug - Dark Messiah|Win32 = Debug - Dark Messiah|Win32 - Debug - Left 4 Dead 2|Win32 = Debug - Left 4 Dead 2|Win32 - Debug - Left 4 Dead|Win32 = Debug - Left 4 Dead|Win32 - Debug - Orange Box Valve|Win32 = Debug - Orange Box Valve|Win32 - Debug - Orange Box|Win32 = Debug - Orange Box|Win32 - Debug - Original|Win32 = Debug - Original|Win32 - Release - Alien Swarm|Win32 = Release - Alien Swarm|Win32 - Release - Dark Messiah|Win32 = Release - Dark Messiah|Win32 - Release - Left 4 Dead 2|Win32 = Release - Left 4 Dead 2|Win32 - Release - Left 4 Dead|Win32 = Release - Left 4 Dead|Win32 - Release - Orange Box Valve|Win32 = Release - Orange Box Valve|Win32 - Release - Orange Box|Win32 = Release - Orange Box|Win32 - Release - Original|Win32 = Release - Original|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Alien Swarm|Win32.ActiveCfg = Debug - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Alien Swarm|Win32.Build.0 = Debug - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Dark Messiah|Win32.ActiveCfg = Debug - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Dark Messiah|Win32.Build.0 = Debug - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead 2|Win32.ActiveCfg = Debug - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead 2|Win32.Build.0 = Debug - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead|Win32.ActiveCfg = Debug - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead|Win32.Build.0 = Debug - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box Valve|Win32.ActiveCfg = Debug - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box Valve|Win32.Build.0 = Debug - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box|Win32.ActiveCfg = Debug - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box|Win32.Build.0 = Debug - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Original|Win32.ActiveCfg = Debug - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Original|Win32.Build.0 = Debug - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Alien Swarm|Win32.ActiveCfg = Release - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Alien Swarm|Win32.Build.0 = Release - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Dark Messiah|Win32.ActiveCfg = Release - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Dark Messiah|Win32.Build.0 = Release - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead 2|Win32.ActiveCfg = Release - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead 2|Win32.Build.0 = Release - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead|Win32.ActiveCfg = Release - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead|Win32.Build.0 = Release - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box Valve|Win32.ActiveCfg = Release - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box Valve|Win32.Build.0 = Release - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box|Win32.ActiveCfg = Release - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box|Win32.Build.0 = Release - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Original|Win32.ActiveCfg = Release - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Original|Win32.Build.0 = Release - Original|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/utils/mmsource/sample_mm/msvc10/sample_mm.vcxproj b/utils/mmsource/sample_mm/msvc10/sample_mm.vcxproj deleted file mode 100644 index 4734b2028..000000000 --- a/utils/mmsource/sample_mm/msvc10/sample_mm.vcxproj +++ /dev/null @@ -1,1156 +0,0 @@ - - - - - Debug - Alien Swarm - Win32 - - - Debug - Bloody Good Time - Win32 - - - Debug - CS GO - Win32 - - - Debug - CSS - Win32 - - - Debug - Dark Messiah - Win32 - - - Debug - EYE - Win32 - - - Debug - Left 4 Dead 2 - Win32 - - - Debug - Left 4 Dead - Win32 - - - Debug - Orange Box Valve - Win32 - - - Debug - Orange Box - Win32 - - - Debug - Original - Win32 - - - Debug - Portal 2 - Win32 - - - Release - Alien Swarm - Win32 - - - Release - Bloody Good Time - Win32 - - - Release - CS GO - Win32 - - - Release - CSS - Win32 - - - Release - Dark Messiah - Win32 - - - Release - EYE - Win32 - - - Release - Left 4 Dead 2 - Win32 - - - Release - Left 4 Dead - Win32 - - - Release - Orange Box Valve - Win32 - - - Release - Orange Box - Win32 - - - Release - Original - Win32 - - - Release - Portal 2 - Win32 - - - - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9} - sample_mm - Win32Proj - - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - true - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - false - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - true - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - false - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - true - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - false - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - true - true - true - true - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - false - false - false - false - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - true - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - false - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - true - true - true - true - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - false - false - false - false - AllRules.ruleset - - - AllRules.ruleset - AllRules.ruleset - AllRules.ruleset - AllRules.ruleset - - - - - - - - - AllRules.ruleset - - - AllRules.ruleset - AllRules.ruleset - AllRules.ruleset - AllRules.ruleset - - - - - - - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - AllRules.ruleset - AllRules.ruleset - AllRules.ruleset - - - - - - - - - AllRules.ruleset - - - AllRules.ruleset - AllRules.ruleset - AllRules.ruleset - AllRules.ruleset - - - - - - - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE18)\core-legacy;$(MMSOURCE18)\core-legacy\sourcehook;$(HL2SDK)\public;$(HL2SDK)\public\dlls;$(HL2SDK)\public\engine;$(HL2SDK)\public\tier0;$(HL2SDK)\public\tier1;$(HL2SDK)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;SOURCE_ENGINE=1;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDK)\lib\public\tier0.lib;$(HL2SDK)\lib\public\tier1.lib;$(HL2SDK)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE18)\core-legacy;$(MMSOURCE18)\core-legacy\sourcehook;$(HL2SDK)\public;$(HL2SDK)\public\dlls;$(HL2SDK)\public\engine;$(HL2SDK)\public\tier0;$(HL2SDK)\public\tier1;$(HL2SDK)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;SOURCE_ENGINE=1;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDK)\lib\public\tier0.lib;$(HL2SDK)\lib\public\tier1.lib;$(HL2SDK)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDK-DARKM)\public;$(HL2SDK-DARKM)\public\engine;$(HL2SDK-DARKM)\public\dlls;$(HL2SDK-DARKM)\public\tier0;$(HL2SDK-DARKM)\public\tier1;$(HL2SDK-DARKM)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;SOURCE_ENGINE=2;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDK-DARKM)\lib\public\tier0.lib;$(HL2SDK-DARKM)\lib\public\tier1.lib;$(HL2SDK-DARKM)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDK-DARKM)\public;$(HL2SDK-DARKM)\public\engine;$(HL2SDK-DARKM)\public\dlls;$(HL2SDK-DARKM)\public\tier0;$(HL2SDK-DARKM)\public\tier1;$(HL2SDK-DARKM)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;SOURCE_ENGINE=2;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDK-DARKM)\lib\public\tier0.lib;$(HL2SDK-DARKM)\lib\public\tier1.lib;$(HL2SDK-DARKM)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDKOB)\public;$(HL2SDKOB)\public\engine;$(HL2SDKOB)\public\game\server;$(HL2SDKOB)\public\tier0;$(HL2SDKOB)\public\tier1;$(HL2SDKOB)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;SOURCE_ENGINE=3;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDKOB)\lib\public\tier0.lib;$(HL2SDKOB)\lib\public\tier1.lib;$(HL2SDKOB)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDKOB)\public;$(HL2SDKOB)\public\engine;$(HL2SDKOB)\public\game\server;$(HL2SDKOB)\public\tier0;$(HL2SDKOB)\public\tier1;$(HL2SDKOB)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;SOURCE_ENGINE=3;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDKOB)\lib\public\tier0.lib;$(HL2SDKOB)\lib\public\tier1.lib;$(HL2SDKOB)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDKOBVALVE)\public;$(HL2SDKOBVALVE)\public\engine;$(HL2SDKOBVALVE)\public\game\server;$(HL2SDKOBVALVE)\public\tier0;$(HL2SDKOBVALVE)\public\tier1;$(HL2SDKOBVALVE)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;SOURCE_ENGINE=7;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDKOBVALVE)\lib\public\tier0.lib;$(HL2SDKOBVALVE)\lib\public\tier1.lib;$(HL2SDKOBVALVE)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE19)\core;$(MMSOURCE19)\core\sourcehook;$(HL2SDKCSS)\public;$(HL2SDKCSS)\public\engine;$(HL2SDKCSS)\public\game\server;$(HL2SDKCSS)\public\tier0;$(HL2SDKCSS)\public\tier1;$(HL2SDKCSS)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;SOURCE_ENGINE=6;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDKCSS)\lib\public\tier0.lib;$(HL2SDKCSS)\lib\public\tier1.lib;$(HL2SDKCSS)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDK-EYE)\public;$(HL2SDK-EYE)\public\engine;$(HL2SDK-EYE)\public\game\server;$(HL2SDK-EYE)\public\tier0;$(HL2SDK-EYE)\public\tier1;$(HL2SDK-EYE)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;SOURCE_ENGINE=5;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDK-EYE)\lib\public\tier0.lib;$(HL2SDK-EYE)\lib\public\tier1.lib;$(HL2SDK-EYE)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDK-BGT)\public;$(HL2SDK-BGT)\public\engine;$(HL2SDK-BGT)\public\game\server;$(HL2SDK-BGT)\public\tier0;$(HL2SDK-BGT)\public\tier1;$(HL2SDK-BGT)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;SOURCE_ENGINE=4;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDK-BGT)\lib\public\tier0.lib;$(HL2SDK-BGT)\lib\public\tier1.lib;$(HL2SDK-BGT)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDKOBVALVE)\public;$(HL2SDKOBVALVE)\public\engine;$(HL2SDKOBVALVE)\public\game\server;$(HL2SDKOBVALVE)\public\tier0;$(HL2SDKOBVALVE)\public\tier1;$(HL2SDKOBVALVE)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;SOURCE_ENGINE=7;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDKOBVALVE)\lib\public\tier0.lib;$(HL2SDKOBVALVE)\lib\public\tier1.lib;$(HL2SDKOBVALVE)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE19)\core;$(MMSOURCE19)\core\sourcehook;$(HL2SDKCSS)\public;$(HL2SDKCSS)\public\engine;$(HL2SDKCSS)\public\game\server;$(HL2SDKCSS)\public\tier0;$(HL2SDKCSS)\public\tier1;$(HL2SDKCSS)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;SOURCE_ENGINE=6;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDKCSS)\lib\public\tier0.lib;$(HL2SDKCSS)\lib\public\tier1.lib;$(HL2SDKCSS)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDK-EYE)\public;$(HL2SDK-EYE)\public\engine;$(HL2SDK-EYE)\public\game\server;$(HL2SDK-EYE)\public\tier0;$(HL2SDK-EYE)\public\tier1;$(HL2SDK-EYE)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;SOURCE_ENGINE=5;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDK-EYE)\lib\public\tier0.lib;$(HL2SDK-EYE)\lib\public\tier1.lib;$(HL2SDK-EYE)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDK-BGT)\public;$(HL2SDK-BGT)\public\engine;$(HL2SDK-BGT)\public\game\server;$(HL2SDK-BGT)\public\tier0;$(HL2SDK-BGT)\public\tier1;$(HL2SDK-BGT)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;SOURCE_ENGINE=4;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDK-BGT)\lib\public\tier0.lib;$(HL2SDK-BGT)\lib\public\tier1.lib;$(HL2SDK-BGT)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDKL4D)\public;$(HL2SDKL4D)\public\engine;$(HL2SDKL4D)\public\game\server;$(HL2SDKL4D)\public\tier0;$(HL2SDKL4D)\public\tier1;$(HL2SDKL4D)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;SOURCE_ENGINE=8;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDKL4D)\lib\public\tier0.lib;$(HL2SDKL4D)\lib\public\tier1.lib;$(HL2SDKL4D)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDKL4D)\public;$(HL2SDKL4D)\public\engine;$(HL2SDKL4D)\public\game\server;$(HL2SDKL4D)\public\tier0;$(HL2SDKL4D)\public\tier1;$(HL2SDKL4D)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;SOURCE_ENGINE=8;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDKL4D)\lib\public\tier0.lib;$(HL2SDKL4D)\lib\public\tier1.lib;$(HL2SDKL4D)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDKL4D2)\public;$(HL2SDKL4D2)\public\engine;$(HL2SDKL4D2)\public\game\server;$(HL2SDKL4D2)\public\tier0;$(HL2SDKL4D2)\public\tier1;$(HL2SDKL4D2)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;SOURCE_ENGINE=9;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDKL4D2)\lib\public\tier0.lib;$(HL2SDKL4D2)\lib\public\tier1.lib;$(HL2SDKL4D2)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDK-SWARM)\public;$(HL2SDK-SWARM)\public\engine;$(HL2SDK-SWARM)\public\game\server;$(HL2SDK-SWARM)\public\tier0;$(HL2SDK-SWARM)\public\tier1;$(HL2SDK-SWARM)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;COMPILER_MSVC;COMPILER_MSVC32;SOURCE_ENGINE=10;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDK-SWARM)\lib\public\interfaces.lib;$(HL2SDK-SWARM)\lib\public\tier0.lib;$(HL2SDK-SWARM)\lib\public\tier1.lib;$(HL2SDK-SWARM)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE19)\core;$(MMSOURCE19)\core\sourcehook;$(HL2SDKCSGO)\public;$(HL2SDKCSGO)\public\engine;$(HL2SDKCSGO)\public\game\server;$(HL2SDKCSGO)\public\tier0;$(HL2SDKCSGO)\public\tier1;$(HL2SDKCSGO)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;COMPILER_MSVC;COMPILER_MSVC32;SOURCE_ENGINE=12;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDKCSGO)\lib\public\interfaces.lib;$(HL2SDKCSGO)\lib\public\tier0.lib;$(HL2SDKCSGO)\lib\public\tier1.lib;$(HL2SDKCSGO)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE19)\core;$(MMSOURCE19)\core\sourcehook;$(HL2SDKPORTAL2)\public;$(HL2SDKPORTAL2)\public\engine;$(HL2SDKPORTAL2)\public\game\server;$(HL2SDKPORTAL2)\public\tier0;$(HL2SDKPORTAL2)\public\tier1;$(HL2SDKPORTAL2)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;COMPILER_MSVC;COMPILER_MSVC32;SOURCE_ENGINE=11;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDKPORTAL2)\lib\public\interfaces.lib;$(HL2SDKPORTAL2)\lib\public\tier0.lib;$(HL2SDKPORTAL2)\lib\public\tier1.lib;$(HL2SDKPORTAL2)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDKL4D2)\public;$(HL2SDKL4D2)\public\engine;$(HL2SDKL4D2)\public\game\server;$(HL2SDKL4D2)\public\tier0;$(HL2SDKL4D2)\public\tier1;$(HL2SDKL4D2)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;SOURCE_ENGINE=9;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDKL4D2)\lib\public\tier0.lib;$(HL2SDKL4D2)\lib\public\tier1.lib;$(HL2SDKL4D2)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDK-SWARM)\public;$(HL2SDK-SWARM)\public\engine;$(HL2SDK-SWARM)\public\game\server;$(HL2SDK-SWARM)\public\tier0;$(HL2SDK-SWARM)\public\tier1;$(HL2SDK-SWARM)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;COMPILER_MSVC;COMPILER_MSVC32;SOURCE_ENGINE=10;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDK-SWARM)\lib\public\interfaces.lib;$(HL2SDK-SWARM)\lib\public\tier0.lib;$(HL2SDK-SWARM)\lib\public\tier1.lib;$(HL2SDK-SWARM)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE19)\core;$(MMSOURCE19)\core\sourcehook;$(HL2SDKCSGO)\public;$(HL2SDKCSGO)\public\engine;$(HL2SDKCSGO)\public\game\server;$(HL2SDKCSGO)\public\tier0;$(HL2SDKCSGO)\public\tier1;$(HL2SDKCSGO)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;COMPILER_MSVC;COMPILER_MSVC32;SOURCE_ENGINE=12;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDKCSGO)\lib\public\interfaces.lib;$(HL2SDKCSGO)\lib\public\tier0.lib;$(HL2SDKCSGO)\lib\public\tier1.lib;$(HL2SDKCSGO)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE19)\core;$(MMSOURCE19)\core\sourcehook;$(HL2SDKPORTAL2)\public;$(HL2SDKPORTAL2)\public\engine;$(HL2SDKPORTAL2)\public\game\server;$(HL2SDKPORTAL2)\public\tier0;$(HL2SDKPORTAL2)\public\tier1;$(HL2SDKPORTAL2)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS;COMPILER_MSVC;COMPILER_MSVC32;SOURCE_ENGINE=11;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDKPORTAL2)\lib\public\interfaces.lib;$(HL2SDKPORTAL2)\lib\public\tier0.lib;$(HL2SDKPORTAL2)\lib\public\tier1.lib;$(HL2SDKPORTAL2)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)sample_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/utils/mmsource/sample_mm/msvc10/sample_mm.vcxproj.filters b/utils/mmsource/sample_mm/msvc10/sample_mm.vcxproj.filters deleted file mode 100644 index 6680f772e..000000000 --- a/utils/mmsource/sample_mm/msvc10/sample_mm.vcxproj.filters +++ /dev/null @@ -1,30 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav - - - - - Source Files - - - - - Header Files - - - Header Files - - - \ No newline at end of file diff --git a/utils/mmsource/sample_mm/msvc8/sample_mm.sln b/utils/mmsource/sample_mm/msvc8/sample_mm.sln deleted file mode 100644 index c6da3ad46..000000000 --- a/utils/mmsource/sample_mm/msvc8/sample_mm.sln +++ /dev/null @@ -1,57 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_mm", "sample_mm.vcproj", "{E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug - Alien Swarm|Win32 = Debug - Alien Swarm|Win32 - Debug - Dark Messiah|Win32 = Debug - Dark Messiah|Win32 - Debug - Left 4 Dead 2|Win32 = Debug - Left 4 Dead 2|Win32 - Debug - Left 4 Dead|Win32 = Debug - Left 4 Dead|Win32 - Debug - Orange Box Valve|Win32 = Debug - Orange Box Valve|Win32 - Debug - Orange Box|Win32 = Debug - Orange Box|Win32 - Debug - Original|Win32 = Debug - Original|Win32 - Release - Alien Swarm|Win32 = Release - Alien Swarm|Win32 - Release - Dark Messiah|Win32 = Release - Dark Messiah|Win32 - Release - Left 4 Dead 2|Win32 = Release - Left 4 Dead 2|Win32 - Release - Left 4 Dead|Win32 = Release - Left 4 Dead|Win32 - Release - Orange Box Valve|Win32 = Release - Orange Box Valve|Win32 - Release - Orange Box|Win32 = Release - Orange Box|Win32 - Release - Original|Win32 = Release - Original|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Alien Swarm|Win32.ActiveCfg = Debug - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Alien Swarm|Win32.Build.0 = Debug - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Dark Messiah|Win32.ActiveCfg = Debug - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Dark Messiah|Win32.Build.0 = Debug - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead 2|Win32.ActiveCfg = Debug - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead 2|Win32.Build.0 = Debug - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead|Win32.ActiveCfg = Debug - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead|Win32.Build.0 = Debug - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box Valve|Win32.ActiveCfg = Debug - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box Valve|Win32.Build.0 = Debug - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box|Win32.ActiveCfg = Debug - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box|Win32.Build.0 = Debug - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Original|Win32.ActiveCfg = Debug - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Original|Win32.Build.0 = Debug - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Alien Swarm|Win32.ActiveCfg = Release - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Alien Swarm|Win32.Build.0 = Release - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Dark Messiah|Win32.ActiveCfg = Release - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Dark Messiah|Win32.Build.0 = Release - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead 2|Win32.ActiveCfg = Release - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead 2|Win32.Build.0 = Release - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead|Win32.ActiveCfg = Release - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead|Win32.Build.0 = Release - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box Valve|Win32.ActiveCfg = Release - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box Valve|Win32.Build.0 = Release - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box|Win32.ActiveCfg = Release - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box|Win32.Build.0 = Release - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Original|Win32.ActiveCfg = Release - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Original|Win32.Build.0 = Release - Original|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal - diff --git a/utils/mmsource/sample_mm/msvc8/sample_mm.vcproj b/utils/mmsource/sample_mm/msvc8/sample_mm.vcproj deleted file mode 100644 index 6115365e3..000000000 --- a/utils/mmsource/sample_mm/msvc8/sample_mm.vcproj +++ /dev/null @@ -1,1175 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/utils/mmsource/sample_mm/msvc9/sample_mm.sln b/utils/mmsource/sample_mm/msvc9/sample_mm.sln deleted file mode 100644 index b7c42522d..000000000 --- a/utils/mmsource/sample_mm/msvc9/sample_mm.sln +++ /dev/null @@ -1,56 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_mm", "sample_mm.vcproj", "{E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug - Alien Swarm|Win32 = Debug - Alien Swarm|Win32 - Debug - Dark Messiah|Win32 = Debug - Dark Messiah|Win32 - Debug - Left 4 Dead 2|Win32 = Debug - Left 4 Dead 2|Win32 - Debug - Left 4 Dead|Win32 = Debug - Left 4 Dead|Win32 - Debug - Orange Box Valve|Win32 = Debug - Orange Box Valve|Win32 - Debug - Orange Box|Win32 = Debug - Orange Box|Win32 - Debug - Original|Win32 = Debug - Original|Win32 - Release - Alien Swarm|Win32 = Release - Alien Swarm|Win32 - Release - Dark Messiah|Win32 = Release - Dark Messiah|Win32 - Release - Left 4 Dead 2|Win32 = Release - Left 4 Dead 2|Win32 - Release - Left 4 Dead|Win32 = Release - Left 4 Dead|Win32 - Release - Orange Box Valve|Win32 = Release - Orange Box Valve|Win32 - Release - Orange Box|Win32 = Release - Orange Box|Win32 - Release - Original|Win32 = Release - Original|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Alien Swarm|Win32.ActiveCfg = Debug - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Alien Swarm|Win32.Build.0 = Debug - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Dark Messiah|Win32.ActiveCfg = Debug - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Dark Messiah|Win32.Build.0 = Debug - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead 2|Win32.ActiveCfg = Debug - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead 2|Win32.Build.0 = Debug - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead|Win32.ActiveCfg = Debug - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead|Win32.Build.0 = Debug - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box Valve|Win32.ActiveCfg = Debug - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box Valve|Win32.Build.0 = Debug - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box|Win32.ActiveCfg = Debug - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box|Win32.Build.0 = Debug - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Original|Win32.ActiveCfg = Debug - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Original|Win32.Build.0 = Debug - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Alien Swarm|Win32.ActiveCfg = Release - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Alien Swarm|Win32.Build.0 = Release - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Dark Messiah|Win32.ActiveCfg = Release - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Dark Messiah|Win32.Build.0 = Release - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead 2|Win32.ActiveCfg = Release - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead 2|Win32.Build.0 = Release - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead|Win32.ActiveCfg = Release - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead|Win32.Build.0 = Release - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box Valve|Win32.ActiveCfg = Release - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box Valve|Win32.Build.0 = Release - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box|Win32.ActiveCfg = Release - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box|Win32.Build.0 = Release - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Original|Win32.ActiveCfg = Release - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Original|Win32.Build.0 = Release - Original|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/utils/mmsource/sample_mm/msvc9/sample_mm.vcproj b/utils/mmsource/sample_mm/msvc9/sample_mm.vcproj deleted file mode 100644 index 06b7bc97b..000000000 --- a/utils/mmsource/sample_mm/msvc9/sample_mm.vcproj +++ /dev/null @@ -1,1162 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/utils/mmsource/sample_mm/sample_mm.cpp b/utils/mmsource/sample_mm/sample_mm.cpp deleted file mode 100644 index 01951acae..000000000 --- a/utils/mmsource/sample_mm/sample_mm.cpp +++ /dev/null @@ -1,357 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source Sample Plugin - * Written by AlliedModders LLC. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * This sample plugin is public domain. - */ - -#include -#include "sample_mm.h" - -SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, 0, bool, char const *, char const *, char const *, char const *, bool, bool); -SH_DECL_HOOK3_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0, edict_t *, int, int); -SH_DECL_HOOK1_void(IServerGameDLL, GameFrame, SH_NOATTRIB, 0, bool); -SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, 0); -SH_DECL_HOOK2_void(IServerGameClients, ClientActive, SH_NOATTRIB, 0, edict_t *, bool); -SH_DECL_HOOK1_void(IServerGameClients, ClientDisconnect, SH_NOATTRIB, 0, edict_t *); -SH_DECL_HOOK2_void(IServerGameClients, ClientPutInServer, SH_NOATTRIB, 0, edict_t *, char const *); -SH_DECL_HOOK1_void(IServerGameClients, SetCommandClient, SH_NOATTRIB, 0, int); -SH_DECL_HOOK1_void(IServerGameClients, ClientSettingsChanged, SH_NOATTRIB, 0, edict_t *); -SH_DECL_HOOK5(IServerGameClients, ClientConnect, SH_NOATTRIB, 0, bool, edict_t *, const char*, const char *, char *, int); -SH_DECL_HOOK2(IGameEventManager2, FireEvent, SH_NOATTRIB, 0, bool, IGameEvent *, bool); - -#if SOURCE_ENGINE >= SE_ORANGEBOX -SH_DECL_HOOK2_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *, const CCommand &); -#else -SH_DECL_HOOK1_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *); -#endif - -SamplePlugin g_SamplePlugin; -IServerGameDLL *server = NULL; -IServerGameClients *gameclients = NULL; -IVEngineServer *engine = NULL; -IServerPluginHelpers *helpers = NULL; -IGameEventManager2 *gameevents = NULL; -IServerPluginCallbacks *vsp_callbacks = NULL; -IPlayerInfoManager *playerinfomanager = NULL; -ICvar *icvar = NULL; -CGlobalVars *gpGlobals = NULL; - -ConVar sample_cvar("sample_cvar", "42", 0); - -/** - * Something like this is needed to register cvars/CON_COMMANDs. - */ -class BaseAccessor : public IConCommandBaseAccessor -{ -public: - bool RegisterConCommandBase(ConCommandBase *pCommandBase) - { - /* Always call META_REGCVAR instead of going through the engine. */ - return META_REGCVAR(pCommandBase); - } -} s_BaseAccessor; - -PLUGIN_EXPOSE(SamplePlugin, g_SamplePlugin); -bool SamplePlugin::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late) -{ - PLUGIN_SAVEVARS(); - - GET_V_IFACE_CURRENT(GetEngineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER); - GET_V_IFACE_CURRENT(GetEngineFactory, gameevents, IGameEventManager2, INTERFACEVERSION_GAMEEVENTSMANAGER2); - GET_V_IFACE_CURRENT(GetEngineFactory, helpers, IServerPluginHelpers, INTERFACEVERSION_ISERVERPLUGINHELPERS); - GET_V_IFACE_CURRENT(GetEngineFactory, icvar, ICvar, CVAR_INTERFACE_VERSION); - GET_V_IFACE_ANY(GetServerFactory, server, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL); - GET_V_IFACE_ANY(GetServerFactory, gameclients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS); - GET_V_IFACE_ANY(GetServerFactory, playerinfomanager, IPlayerInfoManager, INTERFACEVERSION_PLAYERINFOMANAGER); - - gpGlobals = ismm->GetCGlobals(); - - META_LOG(g_PLAPI, "Starting plugin."); - - /* Load the VSP listener. This is usually needed for IServerPluginHelpers. */ - if ((vsp_callbacks = ismm->GetVSPInfo(NULL)) == NULL) - { - ismm->AddListener(this, this); - ismm->EnableVSPListener(); - } - - SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelInit, server, this, &SamplePlugin::Hook_LevelInit, true); - SH_ADD_HOOK_MEMFUNC(IServerGameDLL, ServerActivate, server, this, &SamplePlugin::Hook_ServerActivate, true); - SH_ADD_HOOK_MEMFUNC(IServerGameDLL, GameFrame, server, this, &SamplePlugin::Hook_GameFrame, true); - SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelShutdown, server, this, &SamplePlugin::Hook_LevelShutdown, false); - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientActive, gameclients, this, &SamplePlugin::Hook_ClientActive, true); - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, gameclients, this, &SamplePlugin::Hook_ClientDisconnect, true); - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientPutInServer, gameclients, this, &SamplePlugin::Hook_ClientPutInServer, true); - SH_ADD_HOOK_MEMFUNC(IServerGameClients, SetCommandClient, gameclients, this, &SamplePlugin::Hook_SetCommandClient, true); - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientSettingsChanged, gameclients, this, &SamplePlugin::Hook_ClientSettingsChanged, false); - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientConnect, gameclients, this, &SamplePlugin::Hook_ClientConnect, false); - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientCommand, gameclients, this, &SamplePlugin::Hook_ClientCommand, false); - - ENGINE_CALL(LogPrint)("All hooks started!\n"); - -#if SOURCE_ENGINE >= SE_ORANGEBOX - g_pCVar = icvar; - ConVar_Register(0, &s_BaseAccessor); -#else - ConCommandBaseMgr::OneTimeInit(&s_BaseAccessor); -#endif - - return true; -} - -bool SamplePlugin::Unload(char *error, size_t maxlen) -{ - SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, LevelInit, server, this, &SamplePlugin::Hook_LevelInit, true); - SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, ServerActivate, server, this, &SamplePlugin::Hook_ServerActivate, true); - SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, GameFrame, server, this, &SamplePlugin::Hook_GameFrame, true); - SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, LevelShutdown, server, this, &SamplePlugin::Hook_LevelShutdown, false); - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientActive, gameclients, this, &SamplePlugin::Hook_ClientActive, true); - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, gameclients, this, &SamplePlugin::Hook_ClientDisconnect, true); - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientPutInServer, gameclients, this, &SamplePlugin::Hook_ClientPutInServer, true); - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, SetCommandClient, gameclients, this, &SamplePlugin::Hook_SetCommandClient, true); - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientSettingsChanged, gameclients, this, &SamplePlugin::Hook_ClientSettingsChanged, false); - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientConnect, gameclients, this, &SamplePlugin::Hook_ClientConnect, false); - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientCommand, gameclients, this, &SamplePlugin::Hook_ClientCommand, false); - - return true; -} - -void SamplePlugin::OnVSPListening(IServerPluginCallbacks *iface) -{ - vsp_callbacks = iface; -} - -void SamplePlugin::Hook_ServerActivate(edict_t *pEdictList, int edictCount, int clientMax) -{ - META_LOG(g_PLAPI, "ServerActivate() called: edictCount = %d, clientMax = %d", edictCount, clientMax); -} - -void SamplePlugin::AllPluginsLoaded() -{ - /* This is where we'd do stuff that relies on the mod or other plugins - * being initialized (for example, cvars added and events registered). - */ -} - -void SamplePlugin::Hook_ClientActive(edict_t *pEntity, bool bLoadGame) -{ - META_LOG(g_PLAPI, "Hook_ClientActive(%d, %d)", IndexOfEdict(pEntity), bLoadGame); -} - -#if SOURCE_ENGINE >= SE_ORANGEBOX -void SamplePlugin::Hook_ClientCommand(edict_t *pEntity, const CCommand &args) -#else -void SamplePlugin::Hook_ClientCommand(edict_t *pEntity) -#endif -{ -#if SOURCE_ENGINE <= SE_DARKMESSIAH - CCommand args; -#endif - - if (!pEntity || pEntity->IsFree()) - { - return; - } - - const char *cmd = args.Arg(0); - if (strcmp(cmd, "menu") == 0) - { - KeyValues *kv = new KeyValues("menu"); - kv->SetString("title", "You've got options, hit ESC"); - kv->SetInt("level", 1); - kv->SetColor("color", Color(255, 0, 0, 255)); - kv->SetInt("time", 20); - kv->SetString("msg", "Pick an option\nOr don't."); - - for (int i = 1; i < 9; i++) - { - char num[10], msg[10], cmd[10]; - MM_Format( num, sizeof(num), "%i", i ); - MM_Format( msg, sizeof(msg), "Option %i", i ); - MM_Format( cmd, sizeof(cmd), "option %i", i ); - - KeyValues *item1 = kv->FindKey(num, true); - item1->SetString("msg", msg); - item1->SetString("command", cmd); - } - - helpers->CreateMessage(pEntity, DIALOG_MENU, kv, vsp_callbacks); - kv->deleteThis(); - RETURN_META(MRES_SUPERCEDE); - } - else if (strcmp(cmd, "rich") == 0) - { - KeyValues *kv = new KeyValues("menu"); - kv->SetString("title", "A rich message"); - kv->SetInt("level", 1); - kv->SetInt("time", 20); - kv->SetString("msg", "This is a long long long text string.\n\nIt also has line breaks."); - - helpers->CreateMessage(pEntity, DIALOG_TEXT, kv, vsp_callbacks); - kv->deleteThis(); - RETURN_META(MRES_SUPERCEDE); - } - else if (strcmp(cmd, "msg") == 0) - { - KeyValues *kv = new KeyValues("menu"); - kv->SetString("title", "Just a simple hello"); - kv->SetInt("level", 1); - kv->SetInt("time", 20); - - helpers->CreateMessage(pEntity, DIALOG_MSG, kv, vsp_callbacks); - kv->deleteThis(); - RETURN_META(MRES_SUPERCEDE); - } - else if (strcmp(cmd, "entry") == 0) - { - KeyValues *kv = new KeyValues("entry"); - kv->SetString("title", "Stuff"); - kv->SetString("msg", "Enter something"); - kv->SetString("command", "say"); // anything they enter into the dialog turns into a say command - kv->SetInt("level", 1); - kv->SetInt("time", 20); - - helpers->CreateMessage(pEntity, DIALOG_ENTRY, kv, vsp_callbacks); - kv->deleteThis(); - RETURN_META(MRES_SUPERCEDE); - } -} - -void SamplePlugin::Hook_ClientSettingsChanged(edict_t *pEdict) -{ - if (playerinfomanager) - { - IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo(pEdict); - - const char *name = engine->GetClientConVarValue(IndexOfEdict(pEdict), "name"); - - if (playerinfo != NULL - && name != NULL - && strcmp(engine->GetPlayerNetworkIDString(pEdict), "BOT") != 0 - && playerinfo->GetName() != NULL - && strcmp(name, playerinfo->GetName()) == 0) - { - char msg[128]; - MM_Format(msg, sizeof(msg), "Your name changed to \"%s\" (from \"%s\")\n", name, playerinfo->GetName()); - engine->ClientPrintf(pEdict, msg); - } - } -} - -bool SamplePlugin::Hook_ClientConnect(edict_t *pEntity, - const char *pszName, - const char *pszAddress, - char *reject, - int maxrejectlen) -{ - META_LOG(g_PLAPI, "Hook_ClientConnect(%d, \"%s\", \"%s\")", IndexOfEdict(pEntity), pszName, pszAddress); - - return true; -} - -void SamplePlugin::Hook_ClientPutInServer(edict_t *pEntity, char const *playername) -{ - KeyValues *kv = new KeyValues( "msg" ); - kv->SetString( "title", "Hello" ); - kv->SetString( "msg", "Hello there" ); - kv->SetColor( "color", Color( 255, 0, 0, 255 )); - kv->SetInt( "level", 5); - kv->SetInt( "time", 10); - helpers->CreateMessage(pEntity, DIALOG_MSG, kv, vsp_callbacks); - kv->deleteThis(); -} - -void SamplePlugin::Hook_ClientDisconnect(edict_t *pEntity) -{ - META_LOG(g_PLAPI, "Hook_ClientDisconnect(%d)", IndexOfEdict(pEntity)); -} - -void SamplePlugin::Hook_GameFrame(bool simulating) -{ - /** - * simulating: - * *********** - * true | game is ticking - * false | game is not ticking - */ -} - -bool SamplePlugin::Hook_LevelInit(const char *pMapName, - char const *pMapEntities, - char const *pOldLevel, - char const *pLandmarkName, - bool loadGame, - bool background) -{ - META_LOG(g_PLAPI, "Hook_LevelInit(%s)", pMapName); - - return true; -} - -void SamplePlugin::Hook_LevelShutdown() -{ - META_LOG(g_PLAPI, "Hook_LevelShutdown()"); -} - -void SamplePlugin::Hook_SetCommandClient(int index) -{ - META_LOG(g_PLAPI, "Hook_SetCommandClient(%d)", index); -} - -bool SamplePlugin::Pause(char *error, size_t maxlen) -{ - return true; -} - -bool SamplePlugin::Unpause(char *error, size_t maxlen) -{ - return true; -} - -const char *SamplePlugin::GetLicense() -{ - return "Public Domain"; -} - -const char *SamplePlugin::GetVersion() -{ - return "1.0.0.0"; -} - -const char *SamplePlugin::GetDate() -{ - return __DATE__; -} - -const char *SamplePlugin::GetLogTag() -{ - return "SAMPLE"; -} - -const char *SamplePlugin::GetAuthor() -{ - return "AlliedModders LLC"; -} - -const char *SamplePlugin::GetDescription() -{ - return "Sample basic plugin"; -} - -const char *SamplePlugin::GetName() -{ - return "Sample Plugin"; -} - -const char *SamplePlugin::GetURL() -{ - return "http://www.sourcemm.net/"; -} diff --git a/utils/mmsource/sample_mm/sample_mm.h b/utils/mmsource/sample_mm/sample_mm.h deleted file mode 100644 index 7268506bb..000000000 --- a/utils/mmsource/sample_mm/sample_mm.h +++ /dev/null @@ -1,78 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source Sample Plugin - * Written by AlliedModders LLC. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * This sample plugin is public domain. - */ - -#ifndef _INCLUDE_METAMOD_SOURCE_STUB_PLUGIN_H_ -#define _INCLUDE_METAMOD_SOURCE_STUB_PLUGIN_H_ - -#include -#include -#include -#include -#include "engine_wrappers.h" - -#if defined WIN32 && !defined snprintf -#define snprintf _snprintf -#endif - -class SamplePlugin : public ISmmPlugin, public IMetamodListener -{ -public: - bool Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late); - bool Unload(char *error, size_t maxlen); - bool Pause(char *error, size_t maxlen); - bool Unpause(char *error, size_t maxlen); - void AllPluginsLoaded(); -public: //IMetamodListener stuff - void OnVSPListening(IServerPluginCallbacks *iface); -public: //hooks - void Hook_ServerActivate(edict_t *pEdictList, int edictCount, int clientMax); - bool Hook_LevelInit(const char *pMapName, - char const *pMapEntities, - char const *pOldLevel, - char const *pLandmarkName, - bool loadGame, - bool background); - void Hook_GameFrame(bool simulating); - void Hook_LevelShutdown(void); - void Hook_ClientActive(edict_t *pEntity, bool bLoadGame); - void Hook_ClientDisconnect(edict_t *pEntity); - void Hook_ClientPutInServer(edict_t *pEntity, char const *playername); - void Hook_SetCommandClient(int index); - void Hook_ClientSettingsChanged(edict_t *pEdict); - bool Hook_ClientConnect(edict_t *pEntity, - const char *pszName, - const char *pszAddress, - char *reject, - int maxrejectlen); -#if SOURCE_ENGINE >= SE_ORANGEBOX - void Hook_ClientCommand(edict_t *pEntity, const CCommand &args); -#else - void Hook_ClientCommand(edict_t *pEntity); -#endif -public: - const char *GetAuthor(); - const char *GetName(); - const char *GetDescription(); - const char *GetURL(); - const char *GetLicense(); - const char *GetVersion(); - const char *GetDate(); - const char *GetLogTag(); -}; - -extern SamplePlugin g_SamplePlugin; - -PLUGIN_GLOBALVARS(); - -#endif //_INCLUDE_METAMOD_SOURCE_STUB_PLUGIN_H_ diff --git a/utils/mmsource/sample_mm/sample_mm.vdf b/utils/mmsource/sample_mm/sample_mm.vdf deleted file mode 100644 index 715ee3068..000000000 --- a/utils/mmsource/sample_mm/sample_mm.vdf +++ /dev/null @@ -1,5 +0,0 @@ -"Metamod Plugin" -{ - "alias" "sample" - "file" "addons/sample_mm" -} diff --git a/utils/mmsource/stub_mm/Makefile b/utils/mmsource/stub_mm/Makefile deleted file mode 100644 index 6060a30e5..000000000 --- a/utils/mmsource/stub_mm/Makefile +++ /dev/null @@ -1,229 +0,0 @@ -# (C)2004-2010 Metamod:Source Development Team -# Makefile written by David "BAILOPAN" Anderson - -########################################### -### EDIT THESE PATHS FOR YOUR OWN SETUP ### -########################################### - -HL2SDK_ORIG = ../../hl2sdk -HL2SDK_OB = ../../hl2sdk-ob -HL2SDK_CSS = ../../hl2sdk-css -HL2SDK_OB_VALVE = ../../hl2sdk-ob-valve -HL2SDK_L4D = ../../hl2sdk-l4d -HL2SDK_L4D2 = ../../hl2sdk-l4d2 -HL2SDK_CSGO = ../../hl2sdk-csgo -MMSOURCE19 = .. - -##################################### -### EDIT BELOW FOR OTHER PROJECTS ### -##################################### - -PROJECT = stub_mm -OBJECTS = stub_mm.cpp - -############################################## -### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ### -############################################## - -OPT_FLAGS = -O3 -funroll-loops -pipe -GCC4_FLAGS = -fvisibility=hidden -fvisibility-inlines-hidden -std=c++11 -DEBUG_FLAGS = -g -ggdb3 -D_DEBUG -CPP = gcc -CPP_OSX = clang - -########################## -### SDK CONFIGURATIONS ### -########################## - -override ENGSET = false - -# Check for valid list of engines -ifneq (,$(filter original orangebox orangeboxvalve css left4dead left4dead2 csgo,$(ENGINE))) - override ENGSET = true -endif - -ifeq "$(ENGINE)" "original" - HL2SDK = $(HL2SDK_ORIG) - CFLAGS += -DSOURCE_ENGINE=1 -endif -ifeq "$(ENGINE)" "orangebox" - HL2SDK = $(HL2SDK_OB) - CFLAGS += -DSOURCE_ENGINE=3 -endif -ifeq "$(ENGINE)" "css" - HL2SDK = $(HL2SDK_CSS) - CFLAGS += -DSOURCE_ENGINE=6 -endif -ifeq "$(ENGINE)" "orangeboxvalve" - HL2SDK = $(HL2SDK_OB_VALVE) - CFLAGS += -DSOURCE_ENGINE=7 -endif -ifeq "$(ENGINE)" "left4dead" - HL2SDK = $(HL2SDK_L4D) - CFLAGS += -DSOURCE_ENGINE=8 -endif -ifeq "$(ENGINE)" "left4dead2" - HL2SDK = $(HL2SDK_L4D2) - CFLAGS += -DSOURCE_ENGINE=9 -endif -ifeq "$(ENGINE)" "csgo" - HL2SDK = $(HL2SDK_CSGO) - CFLAGS += -DSOURCE_ENGINE=12 -endif - -HL2PUB = $(HL2SDK)/public - -ifeq "$(ENGINE)" "original" - INCLUDE += -I$(HL2SDK)/public/dlls - METAMOD = $(MMSOURCE19)/core-legacy -else - INCLUDE += -I$(HL2SDK)/public/game/server - METAMOD = $(MMSOURCE19)/core -endif - -OS := $(shell uname -s) - -ifeq "$(OS)" "Darwin" - LIB_EXT = dylib - ifeq "$(ENGINE)" "csgo" - HL2LIB = $(HL2SDK)/lib/osx64 - else - HL2LIB = $(HL2SDK)/lib/mac - endif -else - LIB_EXT = so - ifeq "$(ENGINE)" "original" - HL2LIB = $(HL2SDK)/linux_sdk - else - HL2LIB = $(HL2SDK)/lib/linux - endif -endif - -# if ENGINE is original or OB -ifneq (,$(filter original orangebox,$(ENGINE))) - LIB_SUFFIX = _i486.$(LIB_EXT) -else - LIB_PREFIX = lib - ifneq (,$(filter orangeboxvalve css left4dead2,$(ENGINE))) - ifneq "$(OS)" "Darwin" - LIB_SUFFIX = _srv.$(LIB_EXT) - else - LIB_SUFFIX = .$(LIB_EXT) - endif - else - LIB_SUFFIX = .$(LIB_EXT) - endif -endif - -ifeq "$(OS)" "Darwin" - ifeq "$(ENGINE)" "csgo" - STATIC_SUFFIX = - else - STATIC_SUFFIX = _i486 - endif -else - STATIC_SUFFIX = _i486 -endif - -CFLAGS += -DSE_EPISODEONE=1 -DSE_DARKMESSIAH=2 -DSE_ORANGEBOX=3 -DSE_BLOODYGOODTIME=4 -DSE_EYE=5 \ - -DSE_CSS=6 -DSE_ORANGEBOXVALVE=7 -DSE_LEFT4DEAD=8 -DSE_LEFT4DEAD2=9 -DSE_ALIENSWARM=10 \ - -DSE_PORTAL2=11 -DSE_CSGO=12 - -LINK += $(HL2LIB)/tier1$(STATIC_SUFFIX).a $(LIB_PREFIX)vstdlib$(LIB_SUFFIX) $(LIB_PREFIX)tier0$(LIB_SUFFIX) - -ifeq "$(ENGINE)" "csgo" - LINK += $(HL2LIB)/interfaces$(STATIC_SUFFIX).a -endif - -INCLUDE += -I. -I.. -I$(HL2PUB) -I$(HL2PUB)/engine -I$(HL2PUB)/mathlib -I$(HL2PUB)/vstdlib \ - -I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 -I. -I$(METAMOD) -I$(METAMOD)/sourcehook - -################################################ -### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ### -################################################ - -BINARY = $(PROJECT).$(LIB_EXT) - -ifeq "$(DEBUG)" "true" - BIN_DIR = Debug.$(ENGINE) - CFLAGS += $(DEBUG_FLAGS) -else - BIN_DIR = Release.$(ENGINE) - CFLAGS += $(OPT_FLAGS) -endif - -ifeq "$(OS)" "Darwin" - CPP = $(CPP_OSX) - LIB_EXT = dylib - CFLAGS += -DOSX -D_OSX -mmacosx-version-min=10.9 - LINK += -dynamiclib -lc++ -mmacosx-version-min=10.9 - ifeq "$(ENGINE)" "csgo" - CFLAGS += -m64 -DX64BITS -DPLATFORM_64BITS - LINK += -m64 - else - CFLAGS += -m32 - LINK += -m32 - endif -else - LIB_EXT = so - CFLAGS += -D_LINUX -m32 - LINK += -shared -m32 -endif - -IS_CLANG := $(shell $(CPP) --version | head -1 | grep clang > /dev/null && echo "1" || echo "0") - -ifeq "$(IS_CLANG)" "1" - CPP_MAJOR := $(shell $(CPP) --version | grep clang | sed "s/.*version \([0-9]\)*\.[0-9]*.*/\1/") - CPP_MINOR := $(shell $(CPP) --version | grep clang | sed "s/.*version [0-9]*\.\([0-9]\)*.*/\1/") -else - CPP_MAJOR := $(shell $(CPP) -dumpversion >&1 | cut -b1) - CPP_MINOR := $(shell $(CPP) -dumpversion >&1 | cut -b3) -endif - -CFLAGS += -DPOSIX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp \ - -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca \ - -Dstrcmpi=strcasecmp -DCOMPILER_GCC -Wall -Wno-non-virtual-dtor -Wno-overloaded-virtual \ - -Werror -fPIC -fno-exceptions -fno-rtti -msse -fno-strict-aliasing - -# Clang || GCC >= 4 -ifeq "$(shell expr $(IS_CLANG) \| $(CPP_MAJOR) \>= 4)" "1" - CFLAGS += $(GCC4_FLAGS) -endif - -# Clang >= 3 || GCC >= 4.7 -ifeq "$(shell expr $(IS_CLANG) \& $(CPP_MAJOR) \>= 3 \| $(CPP_MAJOR) \>= 4 \& $(CPP_MINOR) \>= 7)" "1" - CFLAGS += -Wno-delete-non-virtual-dtor -Wno-unused-private-field -Wno-deprecated-register -endif - -# OS is Linux and not using clang -ifeq "$(shell expr $(OS) \= Linux \& $(IS_CLANG) \= 0)" "1" - LINK += -static-libgcc -endif - -OBJ_BIN := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o) - -$(BIN_DIR)/%.o: %.cpp - $(CPP) $(INCLUDE) $(CFLAGS) -o $@ -c $< - -all: check - mkdir -p $(BIN_DIR) - ln -sf $(HL2LIB)/$(LIB_PREFIX)vstdlib$(LIB_SUFFIX) - ln -sf $(HL2LIB)/$(LIB_PREFIX)tier0$(LIB_SUFFIX) - $(MAKE) -f Makefile stub_mm - -check: - if [ "$(ENGSET)" = "false" ]; then \ - echo "You must supply one of the following values for ENGINE:"; \ - echo "csgo, left4dead2, left4dead, css, orangeboxvalve, orangebox, or original"; \ - exit 1; \ - fi - -stub_mm: check $(OBJ_BIN) - $(CPP) $(INCLUDE) $(OBJ_BIN) $(LINK) -ldl -lm -o $(BIN_DIR)/$(BINARY) - -default: all - -clean: check - rm -rf $(BIN_DIR)/*.o - rm -rf $(BIN_DIR)/$(BINARY) - diff --git a/utils/mmsource/stub_mm/README.txt b/utils/mmsource/stub_mm/README.txt deleted file mode 100644 index aa8cbc133..000000000 --- a/utils/mmsource/stub_mm/README.txt +++ /dev/null @@ -1,4 +0,0 @@ -For more information on compiling and reading the plugin's source code, see: - - http://wiki.alliedmods.net/Category:Metamod:Source_Development - diff --git a/utils/mmsource/stub_mm/msvc10/stub_mm.sln b/utils/mmsource/stub_mm/msvc10/stub_mm.sln deleted file mode 100644 index 2bbacd7a2..000000000 --- a/utils/mmsource/stub_mm/msvc10/stub_mm.sln +++ /dev/null @@ -1,56 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stub_mm", "stub_mm.vcxproj", "{E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug - Alien Swarm|Win32 = Debug - Alien Swarm|Win32 - Debug - Dark Messiah|Win32 = Debug - Dark Messiah|Win32 - Debug - Left 4 Dead 2|Win32 = Debug - Left 4 Dead 2|Win32 - Debug - Left 4 Dead|Win32 = Debug - Left 4 Dead|Win32 - Debug - Orange Box Valve|Win32 = Debug - Orange Box Valve|Win32 - Debug - Orange Box|Win32 = Debug - Orange Box|Win32 - Debug - Original|Win32 = Debug - Original|Win32 - Release - Alien Swarm|Win32 = Release - Alien Swarm|Win32 - Release - Dark Messiah|Win32 = Release - Dark Messiah|Win32 - Release - Left 4 Dead 2|Win32 = Release - Left 4 Dead 2|Win32 - Release - Left 4 Dead|Win32 = Release - Left 4 Dead|Win32 - Release - Orange Box Valve|Win32 = Release - Orange Box Valve|Win32 - Release - Orange Box|Win32 = Release - Orange Box|Win32 - Release - Original|Win32 = Release - Original|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Alien Swarm|Win32.ActiveCfg = Debug - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Alien Swarm|Win32.Build.0 = Debug - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Dark Messiah|Win32.ActiveCfg = Debug - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Dark Messiah|Win32.Build.0 = Debug - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead 2|Win32.ActiveCfg = Debug - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead 2|Win32.Build.0 = Debug - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead|Win32.ActiveCfg = Debug - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead|Win32.Build.0 = Debug - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box Valve|Win32.ActiveCfg = Debug - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box Valve|Win32.Build.0 = Debug - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box|Win32.ActiveCfg = Debug - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box|Win32.Build.0 = Debug - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Original|Win32.ActiveCfg = Debug - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Original|Win32.Build.0 = Debug - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Alien Swarm|Win32.ActiveCfg = Release - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Alien Swarm|Win32.Build.0 = Release - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Dark Messiah|Win32.ActiveCfg = Release - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Dark Messiah|Win32.Build.0 = Release - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead 2|Win32.ActiveCfg = Release - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead 2|Win32.Build.0 = Release - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead|Win32.ActiveCfg = Release - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead|Win32.Build.0 = Release - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box Valve|Win32.ActiveCfg = Release - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box Valve|Win32.Build.0 = Release - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box|Win32.ActiveCfg = Release - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box|Win32.Build.0 = Release - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Original|Win32.ActiveCfg = Release - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Original|Win32.Build.0 = Release - Original|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/utils/mmsource/stub_mm/msvc10/stub_mm.vcxproj b/utils/mmsource/stub_mm/msvc10/stub_mm.vcxproj deleted file mode 100644 index 9ef0f93ac..000000000 --- a/utils/mmsource/stub_mm/msvc10/stub_mm.vcxproj +++ /dev/null @@ -1,1155 +0,0 @@ - - - - - Debug - Alien Swarm - Win32 - - - Debug - Bloody Good Time - Win32 - - - Debug - CS GO - Win32 - - - Debug - CSS - Win32 - - - Debug - Dark Messiah - Win32 - - - Debug - EYE - Win32 - - - Debug - Left 4 Dead 2 - Win32 - - - Debug - Left 4 Dead - Win32 - - - Debug - Orange Box Valve - Win32 - - - Debug - Orange Box - Win32 - - - Debug - Original - Win32 - - - Debug - Portal 2 - Win32 - - - Release - Alien Swarm - Win32 - - - Release - Bloody Good Time - Win32 - - - Release - CS GO - Win32 - - - Release - CSS - Win32 - - - Release - Dark Messiah - Win32 - - - Release - EYE - Win32 - - - Release - Left 4 Dead 2 - Win32 - - - Release - Left 4 Dead - Win32 - - - Release - Orange Box Valve - Win32 - - - Release - Orange Box - Win32 - - - Release - Original - Win32 - - - Release - Portal 2 - Win32 - - - - {EA8E7106-8D09-46A1-881B-FFBC4B8532F2} - stub_mm - Win32Proj - - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - - - DynamicLibrary - MultiByte - true - - - DynamicLibrary - MultiByte - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - true - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - false - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - true - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - false - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - true - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - false - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - true - true - true - true - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - false - false - false - false - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - true - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - false - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - true - true - true - true - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - $(Configuration)\ - false - false - false - false - AllRules.ruleset - - - AllRules.ruleset - AllRules.ruleset - AllRules.ruleset - AllRules.ruleset - - - - - - - - - AllRules.ruleset - - - AllRules.ruleset - AllRules.ruleset - AllRules.ruleset - AllRules.ruleset - - - - - - - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - - - AllRules.ruleset - AllRules.ruleset - AllRules.ruleset - AllRules.ruleset - - - - - - - - - AllRules.ruleset - - - AllRules.ruleset - AllRules.ruleset - AllRules.ruleset - AllRules.ruleset - - - - - - - - - AllRules.ruleset - - - AllRules.ruleset - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE18)\core-legacy;$(MMSOURCE18)\core-legacy\sourcehook;$(HL2SDK)\public;$(HL2SDK)\public\dlls;$(HL2SDK)\public\engine;$(HL2SDK)\public\tier0;$(HL2SDK)\public\tier1;$(HL2SDK)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;SOURCE_ENGINE=1;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDK)\lib\public\tier0.lib;$(HL2SDK)\lib\public\tier1.lib;$(HL2SDK)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE18)\core-legacy;$(MMSOURCE18)\core-legacy\sourcehook;$(HL2SDK)\public;$(HL2SDK)\public\dlls;$(HL2SDK)\public\engine;$(HL2SDK)\public\tier0;$(HL2SDK)\public\tier1;$(HL2SDK)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;SOURCE_ENGINE=1;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDK)\lib\public\tier0.lib;$(HL2SDK)\lib\public\tier1.lib;$(HL2SDK)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDK-DARKM)\public;$(HL2SDK-DARKM)\public\engine;$(HL2SDK-DARKM)\public\dlls;$(HL2SDK-DARKM)\public\tier0;$(HL2SDK-DARKM)\public\tier1;$(HL2SDK-DARKM)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;SOURCE_ENGINE=2;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDK-DARKM)\lib\public\tier0.lib;$(HL2SDK-DARKM)\lib\public\tier1.lib;$(HL2SDK-DARKM)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDK-DARKM)\public;$(HL2SDK-DARKM)\public\engine;$(HL2SDK-DARKM)\public\dlls;$(HL2SDK-DARKM)\public\tier0;$(HL2SDK-DARKM)\public\tier1;$(HL2SDK-DARKM)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;SOURCE_ENGINE=2;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDK-DARKM)\lib\public\tier0.lib;$(HL2SDK-DARKM)\lib\public\tier1.lib;$(HL2SDK-DARKM)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDKOB)\public;$(HL2SDKOB)\public\engine;$(HL2SDKOB)\public\game\server;$(HL2SDKOB)\public\tier0;$(HL2SDKOB)\public\tier1;$(HL2SDKOB)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;SOURCE_ENGINE=3;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDKOB)\lib\public\tier0.lib;$(HL2SDKOB)\lib\public\tier1.lib;$(HL2SDKOB)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDKOB)\public;$(HL2SDKOB)\public\engine;$(HL2SDKOB)\public\game\server;$(HL2SDKOB)\public\tier0;$(HL2SDKOB)\public\tier1;$(HL2SDKOB)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;SOURCE_ENGINE=3;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDKOB)\lib\public\tier0.lib;$(HL2SDKOB)\lib\public\tier1.lib;$(HL2SDKOB)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDKOBVALVE)\public;$(HL2SDKOBVALVE)\public\engine;$(HL2SDKOBVALVE)\public\game\server;$(HL2SDKOBVALVE)\public\tier0;$(HL2SDKOBVALVE)\public\tier1;$(HL2SDKOBVALVE)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;SOURCE_ENGINE=7;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDKOBVALVE)\lib\public\tier0.lib;$(HL2SDKOBVALVE)\lib\public\tier1.lib;$(HL2SDKOBVALVE)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE19)\core;$(MMSOURCE19)\core\sourcehook;$(HL2SDKCSS)\public;$(HL2SDKCSS)\public\engine;$(HL2SDKCSS)\public\game\server;$(HL2SDKCSS)\public\tier0;$(HL2SDKCSS)\public\tier1;$(HL2SDKCSS)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;SOURCE_ENGINE=6;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDKCSS)\lib\public\tier0.lib;$(HL2SDKCSS)\lib\public\tier1.lib;$(HL2SDKCSS)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDK-EYE)\public;$(HL2SDK-EYE)\public\engine;$(HL2SDK-EYE)\public\game\server;$(HL2SDK-EYE)\public\tier0;$(HL2SDK-EYE)\public\tier1;$(HL2SDK-EYE)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;SOURCE_ENGINE=5;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDK-EYE)\lib\public\tier0.lib;$(HL2SDK-EYE)\lib\public\tier1.lib;$(HL2SDK-EYE)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDK-BGT)\public;$(HL2SDK-BGT)\public\engine;$(HL2SDK-BGT)\public\game\server;$(HL2SDK-BGT)\public\tier0;$(HL2SDK-BGT)\public\tier1;$(HL2SDK-BGT)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;SOURCE_ENGINE=4;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDK-BGT)\lib\public\tier0.lib;$(HL2SDK-BGT)\lib\public\tier1.lib;$(HL2SDK-BGT)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDKOBVALVE)\public;$(HL2SDKOBVALVE)\public\engine;$(HL2SDKOBVALVE)\public\game\server;$(HL2SDKOBVALVE)\public\tier0;$(HL2SDKOBVALVE)\public\tier1;$(HL2SDKOBVALVE)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;SOURCE_ENGINE=7;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDKOBVALVE)\lib\public\tier0.lib;$(HL2SDKOBVALVE)\lib\public\tier1.lib;$(HL2SDKOBVALVE)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE19)\core;$(MMSOURCE19)\core\sourcehook;$(HL2SDKCSS)\public;$(HL2SDKCSS)\public\engine;$(HL2SDKCSS)\public\game\server;$(HL2SDKCSS)\public\tier0;$(HL2SDKCSS)\public\tier1;$(HL2SDKCSS)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;SOURCE_ENGINE=6;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDKCSS)\lib\public\tier0.lib;$(HL2SDKCSS)\lib\public\tier1.lib;$(HL2SDKCSS)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDK-EYE)\public;$(HL2SDK-EYE)\public\engine;$(HL2SDK-EYE)\public\game\server;$(HL2SDK-EYE)\public\tier0;$(HL2SDK-EYE)\public\tier1;$(HL2SDK-EYE)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;SOURCE_ENGINE=5;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDK-EYE)\lib\public\tier0.lib;$(HL2SDK-EYE)\lib\public\tier1.lib;$(HL2SDK-EYE)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDK-BGT)\public;$(HL2SDK-BGT)\public\engine;$(HL2SDK-BGT)\public\game\server;$(HL2SDK-BGT)\public\tier0;$(HL2SDK-BGT)\public\tier1;$(HL2SDK-BGT)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;SOURCE_ENGINE=4;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDK-BGT)\lib\public\tier0.lib;$(HL2SDK-BGT)\lib\public\tier1.lib;$(HL2SDK-BGT)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDKL4D)\public;$(HL2SDKL4D)\public\engine;$(HL2SDKL4D)\public\game\server;$(HL2SDKL4D)\public\tier0;$(HL2SDKL4D)\public\tier1;$(HL2SDKL4D)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;SOURCE_ENGINE=8;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDKL4D)\lib\public\tier0.lib;$(HL2SDKL4D)\lib\public\tier1.lib;$(HL2SDKL4D)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDKL4D)\public;$(HL2SDKL4D)\public\engine;$(HL2SDKL4D)\public\game\server;$(HL2SDKL4D)\public\tier0;$(HL2SDKL4D)\public\tier1;$(HL2SDKL4D)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;SOURCE_ENGINE=8;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDKL4D)\lib\public\tier0.lib;$(HL2SDKL4D)\lib\public\tier1.lib;$(HL2SDKL4D)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDKL4D2)\public;$(HL2SDKL4D2)\public\engine;$(HL2SDKL4D2)\public\game\server;$(HL2SDKL4D2)\public\tier0;$(HL2SDKL4D2)\public\tier1;$(HL2SDKL4D2)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;SOURCE_ENGINE=9;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDKL4D2)\lib\public\tier0.lib;$(HL2SDKL4D2)\lib\public\tier1.lib;$(HL2SDKL4D2)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDK-SWARM)\public;$(HL2SDK-SWARM)\public\engine;$(HL2SDK-SWARM)\public\game\server;$(HL2SDK-SWARM)\public\tier0;$(HL2SDK-SWARM)\public\tier1;$(HL2SDK-SWARM)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;COMPILER_MSVC;COMPILER_MSVC32;SOURCE_ENGINE=10;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDK-SWARM)\lib\public\interfaces.lib;$(HL2SDK-SWARM)\lib\public\tier0.lib;$(HL2SDK-SWARM)\lib\public\tier1.lib;$(HL2SDK-SWARM)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE19)\core;$(MMSOURCE19)\core\sourcehook;$(HL2SDKCSGO)\public;$(HL2SDKCSGO)\public\engine;$(HL2SDKCSGO)\public\game\server;$(HL2SDKCSGO)\public\tier0;$(HL2SDKCSGO)\public\tier1;$(HL2SDKCSGO)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;COMPILER_MSVC;COMPILER_MSVC32;SOURCE_ENGINE=12;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDKCSGO)\lib\public\interfaces.lib;$(HL2SDKCSGO)\lib\public\tier0.lib;$(HL2SDKCSGO)\lib\public\tier1.lib;$(HL2SDKCSGO)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - Disabled - $(MMSOURCE19)\core;$(MMSOURCE19)\core\sourcehook;$(HL2SDKPORTAL2)\public;$(HL2SDKPORTAL2)\public\engine;$(HL2SDKPORTAL2)\public\game\server;$(HL2SDKPORTAL2)\public\tier0;$(HL2SDKPORTAL2)\public\tier1;$(HL2SDKPORTAL2)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;COMPILER_MSVC;COMPILER_MSVC32;SOURCE_ENGINE=11;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebug - - - Level3 - EditAndContinue - - - $(HL2SDKPORTAL2)\lib\public\interfaces.lib;$(HL2SDKPORTAL2)\lib\public\tier0.lib;$(HL2SDKPORTAL2)\lib\public\tier1.lib;$(HL2SDKPORTAL2)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMT;%(IgnoreSpecificDefaultLibraries) - true - Windows - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDKL4D2)\public;$(HL2SDKL4D2)\public\engine;$(HL2SDKL4D2)\public\game\server;$(HL2SDKL4D2)\public\tier0;$(HL2SDKL4D2)\public\tier1;$(HL2SDKL4D2)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;SOURCE_ENGINE=9;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDKL4D2)\lib\public\tier0.lib;$(HL2SDKL4D2)\lib\public\tier1.lib;$(HL2SDKL4D2)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE18)\core;$(MMSOURCE18)\core\sourcehook;$(HL2SDK-SWARM)\public;$(HL2SDK-SWARM)\public\engine;$(HL2SDK-SWARM)\public\game\server;$(HL2SDK-SWARM)\public\tier0;$(HL2SDK-SWARM)\public\tier1;$(HL2SDK-SWARM)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;COMPILER_MSVC;COMPILER_MSVC32;SOURCE_ENGINE=10;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDK-SWARM)\lib\public\interfaces.lib;$(HL2SDK-SWARM)\lib\public\tier0.lib;$(HL2SDK-SWARM)\lib\public\tier1.lib;$(HL2SDK-SWARM)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE19)\core;$(MMSOURCE19)\core\sourcehook;$(HL2SDKCSGO)\public;$(HL2SDKCSGO)\public\engine;$(HL2SDKCSGO)\public\game\server;$(HL2SDKCSGO)\public\tier0;$(HL2SDKCSGO)\public\tier1;$(HL2SDKCSGO)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;COMPILER_MSVC;COMPILER_MSVC32;SOURCE_ENGINE=12;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDKCSGO)\lib\public\interfaces.lib;$(HL2SDKCSGO)\lib\public\tier0.lib;$(HL2SDKCSGO)\lib\public\tier1.lib;$(HL2SDKCSGO)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - /D SE_EPISODE1=1 /D SE_DARKMESSIAH=2 /D SE_ORANGEBOX=3 /D SE_BLOODYGOODTIME=4 /D SE_EYE=5 /D SE_CSS=6 /D SE_ORANGEBOXVALVE=7 /D SE_LEFT4DEAD=8 /D SE_LEFT4DEAD2=9 /D SE_ALIENSWARM=10 /D SE_PORTAL2=1 /D SE_CSGO=12 %(AdditionalOptions) - $(MMSOURCE19)\core;$(MMSOURCE19)\core\sourcehook;$(HL2SDKPORTAL2)\public;$(HL2SDKPORTAL2)\public\engine;$(HL2SDKPORTAL2)\public\game\server;$(HL2SDKPORTAL2)\public\tier0;$(HL2SDKPORTAL2)\public\tier1;$(HL2SDKPORTAL2)\public\vstdlib;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_WINDOWS;_USRDLL;STUB_MM_EXPORTS;COMPILER_MSVC;COMPILER_MSVC32;SOURCE_ENGINE=11;%(PreprocessorDefinitions) - MultiThreaded - - - Level3 - ProgramDatabase - - - $(HL2SDKPORTAL2)\lib\public\interfaces.lib;$(HL2SDKPORTAL2)\lib\public\tier0.lib;$(HL2SDKPORTAL2)\lib\public\tier1.lib;$(HL2SDKPORTAL2)\lib\public\vstdlib.lib;%(AdditionalDependencies) - $(OutDir)stub_mm.dll - LIBC;LIBCD;LIBCMTD;%(IgnoreSpecificDefaultLibraries) - true - Windows - true - true - false - - - MachineX86 - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/utils/mmsource/stub_mm/msvc10/stub_mm.vcxproj.filters b/utils/mmsource/stub_mm/msvc10/stub_mm.vcxproj.filters deleted file mode 100644 index 5cce4617c..000000000 --- a/utils/mmsource/stub_mm/msvc10/stub_mm.vcxproj.filters +++ /dev/null @@ -1,27 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav - - - - - Source Files - - - - - Header Files - - - \ No newline at end of file diff --git a/utils/mmsource/stub_mm/msvc8/stub_mm.sln b/utils/mmsource/stub_mm/msvc8/stub_mm.sln deleted file mode 100644 index 9c7c7a531..000000000 --- a/utils/mmsource/stub_mm/msvc8/stub_mm.sln +++ /dev/null @@ -1,57 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stub_mm", "stub_mm.vcproj", "{E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug - Alien Swarm|Win32 = Debug - Alien Swarm|Win32 - Debug - Dark Messiah|Win32 = Debug - Dark Messiah|Win32 - Debug - Left 4 Dead 2|Win32 = Debug - Left 4 Dead 2|Win32 - Debug - Left 4 Dead|Win32 = Debug - Left 4 Dead|Win32 - Debug - Orange Box Valve|Win32 = Debug - Orange Box Valve|Win32 - Debug - Orange Box|Win32 = Debug - Orange Box|Win32 - Debug - Original|Win32 = Debug - Original|Win32 - Release - Alien Swarm|Win32 = Release - Alien Swarm|Win32 - Release - Dark Messiah|Win32 = Release - Dark Messiah|Win32 - Release - Left 4 Dead 2|Win32 = Release - Left 4 Dead 2|Win32 - Release - Left 4 Dead|Win32 = Release - Left 4 Dead|Win32 - Release - Orange Box Valve|Win32 = Release - Orange Box Valve|Win32 - Release - Orange Box|Win32 = Release - Orange Box|Win32 - Release - Original|Win32 = Release - Original|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Alien Swarm|Win32.ActiveCfg = Debug - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Alien Swarm|Win32.Build.0 = Debug - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Dark Messiah|Win32.ActiveCfg = Debug - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Dark Messiah|Win32.Build.0 = Debug - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead 2|Win32.ActiveCfg = Debug - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead 2|Win32.Build.0 = Debug - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead|Win32.ActiveCfg = Debug - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead|Win32.Build.0 = Debug - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box Valve|Win32.ActiveCfg = Debug - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box Valve|Win32.Build.0 = Debug - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box|Win32.ActiveCfg = Debug - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box|Win32.Build.0 = Debug - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Original|Win32.ActiveCfg = Debug - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Original|Win32.Build.0 = Debug - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Alien Swarm|Win32.ActiveCfg = Release - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Alien Swarm|Win32.Build.0 = Release - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Dark Messiah|Win32.ActiveCfg = Release - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Dark Messiah|Win32.Build.0 = Release - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead 2|Win32.ActiveCfg = Release - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead 2|Win32.Build.0 = Release - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead|Win32.ActiveCfg = Release - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead|Win32.Build.0 = Release - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box Valve|Win32.ActiveCfg = Release - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box Valve|Win32.Build.0 = Release - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box|Win32.ActiveCfg = Release - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box|Win32.Build.0 = Release - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Original|Win32.ActiveCfg = Release - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Original|Win32.Build.0 = Release - Original|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal - diff --git a/utils/mmsource/stub_mm/msvc8/stub_mm.vcproj b/utils/mmsource/stub_mm/msvc8/stub_mm.vcproj deleted file mode 100644 index 68e59507b..000000000 --- a/utils/mmsource/stub_mm/msvc8/stub_mm.vcproj +++ /dev/null @@ -1,1171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/utils/mmsource/stub_mm/msvc9/stub_mm.sln b/utils/mmsource/stub_mm/msvc9/stub_mm.sln deleted file mode 100644 index 7d1fce6f7..000000000 --- a/utils/mmsource/stub_mm/msvc9/stub_mm.sln +++ /dev/null @@ -1,56 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stub_mm", "stub_mm.vcproj", "{E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug - Alien Swarm|Win32 = Debug - Alien Swarm|Win32 - Debug - Dark Messiah|Win32 = Debug - Dark Messiah|Win32 - Debug - Left 4 Dead 2|Win32 = Debug - Left 4 Dead 2|Win32 - Debug - Left 4 Dead|Win32 = Debug - Left 4 Dead|Win32 - Debug - Orange Box Valve|Win32 = Debug - Orange Box Valve|Win32 - Debug - Orange Box|Win32 = Debug - Orange Box|Win32 - Debug - Original|Win32 = Debug - Original|Win32 - Release - Alien Swarm|Win32 = Release - Alien Swarm|Win32 - Release - Dark Messiah|Win32 = Release - Dark Messiah|Win32 - Release - Left 4 Dead 2|Win32 = Release - Left 4 Dead 2|Win32 - Release - Left 4 Dead|Win32 = Release - Left 4 Dead|Win32 - Release - Orange Box Valve|Win32 = Release - Orange Box Valve|Win32 - Release - Orange Box|Win32 = Release - Orange Box|Win32 - Release - Original|Win32 = Release - Original|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Alien Swarm|Win32.ActiveCfg = Debug - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Alien Swarm|Win32.Build.0 = Debug - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Dark Messiah|Win32.ActiveCfg = Debug - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Dark Messiah|Win32.Build.0 = Debug - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead 2|Win32.ActiveCfg = Debug - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead 2|Win32.Build.0 = Debug - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead|Win32.ActiveCfg = Debug - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Left 4 Dead|Win32.Build.0 = Debug - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box Valve|Win32.ActiveCfg = Debug - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box Valve|Win32.Build.0 = Debug - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box|Win32.ActiveCfg = Debug - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Orange Box|Win32.Build.0 = Debug - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Original|Win32.ActiveCfg = Debug - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Debug - Original|Win32.Build.0 = Debug - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Alien Swarm|Win32.ActiveCfg = Release - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Alien Swarm|Win32.Build.0 = Release - Alien Swarm|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Dark Messiah|Win32.ActiveCfg = Release - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Dark Messiah|Win32.Build.0 = Release - Dark Messiah|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead 2|Win32.ActiveCfg = Release - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead 2|Win32.Build.0 = Release - Left 4 Dead 2|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead|Win32.ActiveCfg = Release - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Left 4 Dead|Win32.Build.0 = Release - Left 4 Dead|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box Valve|Win32.ActiveCfg = Release - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box Valve|Win32.Build.0 = Release - Orange Box Valve|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box|Win32.ActiveCfg = Release - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Orange Box|Win32.Build.0 = Release - Orange Box|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Original|Win32.ActiveCfg = Release - Original|Win32 - {E62E5876-E1E2-41A0-85CA-1B41B9DA55F9}.Release - Original|Win32.Build.0 = Release - Original|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/utils/mmsource/stub_mm/msvc9/stub_mm.vcproj b/utils/mmsource/stub_mm/msvc9/stub_mm.vcproj deleted file mode 100644 index 9829fc2a9..000000000 --- a/utils/mmsource/stub_mm/msvc9/stub_mm.vcproj +++ /dev/null @@ -1,1158 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/utils/mmsource/stub_mm/stub_mm.cpp b/utils/mmsource/stub_mm/stub_mm.cpp deleted file mode 100644 index 965c3841a..000000000 --- a/utils/mmsource/stub_mm/stub_mm.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source Stub Plugin - * Written by AlliedModders LLC. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * This stub plugin is public domain. - */ - -#include -#include "stub_mm.h" - -SH_DECL_HOOK3_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0, edict_t *, int, int); - -StubPlugin g_StubPlugin; -IServerGameDLL *server = NULL; - -PLUGIN_EXPOSE(StubPlugin, g_StubPlugin); -bool StubPlugin::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late) -{ - PLUGIN_SAVEVARS(); - - /* Make sure we build on MM:S 1.4 */ -#if defined METAMOD_PLAPI_VERSION - GET_V_IFACE_ANY(GetServerFactory, server, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL); -#else - GET_V_IFACE_ANY(serverFactory, server, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL); -#endif - - SH_ADD_HOOK_STATICFUNC(IServerGameDLL, ServerActivate, server, Hook_ServerActivate, true); - - return true; -} - -bool StubPlugin::Unload(char *error, size_t maxlen) -{ - SH_REMOVE_HOOK_STATICFUNC(IServerGameDLL, ServerActivate, server, Hook_ServerActivate, true); - - return true; -} - -void Hook_ServerActivate(edict_t *pEdictList, int edictCount, int clientMax) -{ - META_LOG(g_PLAPI, "ServerActivate() called: edictCount = %d, clientMax = %d", edictCount, clientMax); -} - -void StubPlugin::AllPluginsLoaded() -{ - /* This is where we'd do stuff that relies on the mod or other plugins - * being initialized (for example, cvars added and events registered). - */ -} - -bool StubPlugin::Pause(char *error, size_t maxlen) -{ - return true; -} - -bool StubPlugin::Unpause(char *error, size_t maxlen) -{ - return true; -} - -const char *StubPlugin::GetLicense() -{ - return "Public Domain"; -} - -const char *StubPlugin::GetVersion() -{ - return "1.0.0.0"; -} - -const char *StubPlugin::GetDate() -{ - return __DATE__; -} - -const char *StubPlugin::GetLogTag() -{ - return "STUB"; -} - -const char *StubPlugin::GetAuthor() -{ - return "AlliedModders LLC"; -} - -const char *StubPlugin::GetDescription() -{ - return "Sample empty plugin"; -} - -const char *StubPlugin::GetName() -{ - return "Stub Plugin"; -} - -const char *StubPlugin::GetURL() -{ - return "http://www.sourcemm.net/"; -} diff --git a/utils/mmsource/stub_mm/stub_mm.h b/utils/mmsource/stub_mm/stub_mm.h deleted file mode 100644 index d0c238107..000000000 --- a/utils/mmsource/stub_mm/stub_mm.h +++ /dev/null @@ -1,49 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source Stub Plugin - * Written by AlliedModders LLC. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * This stub plugin is public domain. - */ - -#ifndef _INCLUDE_METAMOD_SOURCE_STUB_PLUGIN_H_ -#define _INCLUDE_METAMOD_SOURCE_STUB_PLUGIN_H_ - -#include - -#if defined WIN32 && !defined snprintf -#define snprintf _snprintf -#endif - -class StubPlugin : public ISmmPlugin -{ -public: - bool Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late); - bool Unload(char *error, size_t maxlen); - bool Pause(char *error, size_t maxlen); - bool Unpause(char *error, size_t maxlen); - void AllPluginsLoaded(); -public: - const char *GetAuthor(); - const char *GetName(); - const char *GetDescription(); - const char *GetURL(); - const char *GetLicense(); - const char *GetVersion(); - const char *GetDate(); - const char *GetLogTag(); -}; - -void Hook_ServerActivate(edict_t *pEdictList, int edictCount, int clientMax); - -extern StubPlugin g_StubPlugin; - -PLUGIN_GLOBALVARS(); - -#endif //_INCLUDE_METAMOD_SOURCE_STUB_PLUGIN_H_ diff --git a/utils/mmsource/stub_mm/stub_mm.vdf b/utils/mmsource/stub_mm/stub_mm.vdf deleted file mode 100644 index 0bbbf5826..000000000 --- a/utils/mmsource/stub_mm/stub_mm.vdf +++ /dev/null @@ -1,5 +0,0 @@ -"Metamod Plugin" -{ - "alias" "stub" - "file" "addons/stub_mm" -} diff --git a/utils/mmsource/support/README.txt b/utils/mmsource/support/README.txt deleted file mode 100644 index a54ccb551..000000000 --- a/utils/mmsource/support/README.txt +++ /dev/null @@ -1,7 +0,0 @@ -Visit: - - http://wiki.alliedmods.net/Category:Metamod:Source_Documentation - - for more information. - - diff --git a/utils/mmsource/support/SourceMM.Doxyfile b/utils/mmsource/support/SourceMM.Doxyfile deleted file mode 100644 index b7f2df79e..000000000 --- a/utils/mmsource/support/SourceMM.Doxyfile +++ /dev/null @@ -1,257 +0,0 @@ -# Doxyfile 1.4.2 - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -PROJECT_NAME = SourceMM -PROJECT_NUMBER = 1.00 -OUTPUT_DIRECTORY = c:\temp\smm-dox -CREATE_SUBDIRS = NO -OUTPUT_LANGUAGE = English -USE_WINDOWS_ENCODING = YES -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -ABBREVIATE_BRIEF = "The $name class" \ - "The $name widget" \ - "The $name file" \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the -ALWAYS_DETAILED_SEC = NO -INLINE_INHERITED_MEMB = NO -FULL_PATH_NAMES = YES -STRIP_FROM_PATH = "C:/Documents and Settings/dvander.WHITENIGHT/Desktop/code/" -STRIP_FROM_INC_PATH = -SHORT_NAMES = YES -JAVADOC_AUTOBRIEF = NO -MULTILINE_CPP_IS_BRIEF = NO -DETAILS_AT_TOP = NO -INHERIT_DOCS = YES -DISTRIBUTE_GROUP_DOC = NO -SEPARATE_MEMBER_PAGES = NO -TAB_SIZE = 8 -ALIASES = -OPTIMIZE_OUTPUT_FOR_C = NO -OPTIMIZE_OUTPUT_JAVA = NO -SUBGROUPING = YES -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- -EXTRACT_ALL = YES -EXTRACT_PRIVATE = YES -EXTRACT_STATIC = YES -EXTRACT_LOCAL_CLASSES = YES -EXTRACT_LOCAL_METHODS = NO -HIDE_UNDOC_MEMBERS = NO -HIDE_UNDOC_CLASSES = NO -HIDE_FRIEND_COMPOUNDS = NO -HIDE_IN_BODY_DOCS = NO -INTERNAL_DOCS = NO -CASE_SENSE_NAMES = NO -HIDE_SCOPE_NAMES = NO -SHOW_INCLUDE_FILES = YES -INLINE_INFO = YES -SORT_MEMBER_DOCS = YES -SORT_BRIEF_DOCS = NO -SORT_BY_SCOPE_NAME = NO -GENERATE_TODOLIST = YES -GENERATE_TESTLIST = YES -GENERATE_BUGLIST = YES -GENERATE_DEPRECATEDLIST= YES -ENABLED_SECTIONS = -MAX_INITIALIZER_LINES = 38 -SHOW_USED_FILES = YES -SHOW_DIRECTORIES = YES -FILE_VERSION_FILTER = -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- -QUIET = NO -WARNINGS = YES -WARN_IF_UNDOCUMENTED = YES -WARN_IF_DOC_ERROR = YES -WARN_NO_PARAMDOC = NO -WARN_FORMAT = "$file:$line: $text" -WARN_LOGFILE = -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = "C:/Documents and Settings/dvander.WHITENIGHT/Desktop/code/sourcemm" -FILE_PATTERNS = *.c \ - *.cc \ - *.cxx \ - *.cpp \ - *.c++ \ - *.d \ - *.java \ - *.ii \ - *.ixx \ - *.ipp \ - *.i++ \ - *.inl \ - *.h \ - *.hh \ - *.hxx \ - *.hpp \ - *.h++ \ - *.idl \ - *.odl \ - *.cs \ - *.php \ - *.php3 \ - *.inc \ - *.m \ - *.mm \ - *.dox -RECURSIVE = YES -EXCLUDE = -EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = test \ - sample_mm -EXAMPLE_PATH = -EXAMPLE_PATTERNS = * -EXAMPLE_RECURSIVE = NO -IMAGE_PATH = -INPUT_FILTER = -FILTER_PATTERNS = -FILTER_SOURCE_FILES = NO -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- -SOURCE_BROWSER = YES -INLINE_SOURCES = NO -STRIP_CODE_COMMENTS = NO -REFERENCED_BY_RELATION = YES -REFERENCES_RELATION = YES -VERBATIM_HEADERS = NO -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- -ALPHABETICAL_INDEX = NO -COLS_IN_ALPHA_INDEX = 5 -IGNORE_PREFIX = -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- -GENERATE_HTML = YES -HTML_OUTPUT = html -HTML_FILE_EXTENSION = .html -HTML_HEADER = -HTML_FOOTER = -HTML_STYLESHEET = -HTML_ALIGN_MEMBERS = YES -GENERATE_HTMLHELP = NO -CHM_FILE = -HHC_LOCATION = -GENERATE_CHI = NO -BINARY_TOC = NO -TOC_EXPAND = NO -DISABLE_INDEX = NO -ENUM_VALUES_PER_LINE = 4 -GENERATE_TREEVIEW = NO -TREEVIEW_WIDTH = 250 -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- -GENERATE_LATEX = NO -LATEX_OUTPUT = latex -LATEX_CMD_NAME = latex -MAKEINDEX_CMD_NAME = makeindex -COMPACT_LATEX = NO -PAPER_TYPE = a4wide -EXTRA_PACKAGES = -LATEX_HEADER = -PDF_HYPERLINKS = NO -USE_PDFLATEX = NO -LATEX_BATCHMODE = NO -LATEX_HIDE_INDICES = NO -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- -GENERATE_RTF = NO -RTF_OUTPUT = rtf -COMPACT_RTF = NO -RTF_HYPERLINKS = NO -RTF_STYLESHEET_FILE = -RTF_EXTENSIONS_FILE = -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- -GENERATE_MAN = NO -MAN_OUTPUT = man -MAN_EXTENSION = .3 -MAN_LINKS = NO -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- -GENERATE_XML = NO -XML_OUTPUT = xml -XML_SCHEMA = -XML_DTD = -XML_PROGRAMLISTING = YES -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- -GENERATE_AUTOGEN_DEF = NO -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- -GENERATE_PERLMOD = NO -PERLMOD_LATEX = NO -PERLMOD_PRETTY = YES -PERLMOD_MAKEVAR_PREFIX = -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- -ENABLE_PREPROCESSING = NO -MACRO_EXPANSION = NO -EXPAND_ONLY_PREDEF = NO -SEARCH_INCLUDES = YES -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = -PREDEFINED = -EXPAND_AS_DEFINED = -SKIP_FUNCTION_MACROS = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- -TAGFILES = -GENERATE_TAGFILE = -ALLEXTERNALS = NO -EXTERNAL_GROUPS = YES -PERL_PATH = /usr/bin/perl -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- -CLASS_DIAGRAMS = YES -HIDE_UNDOC_RELATIONS = YES -HAVE_DOT = NO -CLASS_GRAPH = YES -COLLABORATION_GRAPH = YES -GROUP_GRAPHS = YES -UML_LOOK = NO -TEMPLATE_RELATIONS = NO -INCLUDE_GRAPH = YES -INCLUDED_BY_GRAPH = YES -CALL_GRAPH = NO -GRAPHICAL_HIERARCHY = YES -DIRECTORY_GRAPH = YES -DOT_IMAGE_FORMAT = png -DOT_PATH = -DOTFILE_DIRS = -MAX_DOT_GRAPH_WIDTH = 1024 -MAX_DOT_GRAPH_HEIGHT = 1024 -MAX_DOT_GRAPH_DEPTH = 1000 -DOT_TRANSPARENT = NO -DOT_MULTI_TARGETS = NO -GENERATE_LEGEND = YES -DOT_CLEANUP = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- -SEARCHENGINE = YES diff --git a/utils/mmsource/support/buildbot/BreakpadSymbols b/utils/mmsource/support/buildbot/BreakpadSymbols deleted file mode 100644 index 0a7c11bde..000000000 --- a/utils/mmsource/support/buildbot/BreakpadSymbols +++ /dev/null @@ -1,43 +0,0 @@ -# vim: set ts=2 sw=2 tw=99 noet ft=python: -import os, sys - -builder.SetBuildFolder('symbols') - -UPLOAD_SCRIPT = os.path.join(builder.sourcePath, 'support', 'buildbot', 'upload_symbols.py') - -cxx_tasks = MMS.binaries -for cxx_task in cxx_tasks: - if builder.target.platform in ['windows']: - debug_entry = cxx_task.debug - else: - debug_entry = cxx_task.binary - - debug_file = os.path.join(builder.buildPath, debug_entry.path) - if builder.target.platform == 'linux': - argv = ['dump_syms', debug_file, os.path.dirname(debug_file)] - elif builder.target.platform == 'mac': - argv = ['dump_syms', debug_file + '.dSYM'] - elif builder.target.platform == 'windows': - argv = ['dump_syms.exe', debug_file] - - base_file = os.path.split(os.path.dirname(debug_file))[1] - symbol_file = base_file + '.breakpad' - - argv = [sys.executable, UPLOAD_SCRIPT, symbol_file] + argv - builder.AddCommand( - inputs = [UPLOAD_SCRIPT, debug_entry], - argv = argv, - outputs = [symbol_file] - ) - - def run(self, master, job): - ShellCommand.run(self, master, job) - if self.stdout != None and len(self.stdout) > 0: - request = urllib.Request(symbolServer, self.stdout.encode('utf-8')) - request.add_header("Content-Type", "text/plain") - self.serverResponse = urllib.urlopen(request).read().decode('utf-8') - def spew(self, runner): - if self.stderr != None and len(self.stderr) > 0: - runner.PrintOut(self.stderr) - if self.serverResponse != None and len(self.serverResponse) > 0: - runner.PrintOut(self.serverResponse) diff --git a/utils/mmsource/support/buildbot/PackageScript b/utils/mmsource/support/buildbot/PackageScript deleted file mode 100644 index d64412672..000000000 --- a/utils/mmsource/support/buildbot/PackageScript +++ /dev/null @@ -1,43 +0,0 @@ -# vim: set ts=2 sw=2 tw=99 noet ft=python: -import os - -builder.SetBuildFolder('package') - -addons_folder = builder.AddFolder('addons') -metamod_folder = builder.AddFolder(os.path.join('addons', 'metamod')) -bin_folder = builder.AddFolder(os.path.join('addons', 'metamod', 'bin')) - -for arch in MMS.archs: - if arch == 'x64': - if builder.target.platform == 'windows': - bin64_folder = builder.AddFolder(os.path.join('addons', 'metamod', 'bin', 'win64')) - builder.AddCopy(os.path.join(builder.sourcePath, 'support', 'metamod_win64.vdf'), - os.path.join('addons', 'metamod_x64.vdf')) - elif builder.target.platform == 'linux': - bin64_folder = builder.AddFolder(os.path.join('addons', 'metamod', 'bin', 'linux64')) - builder.AddCopy(os.path.join(builder.sourcePath, 'support', 'metamod_linux64.vdf'), - os.path.join('addons', 'metamod_x64.vdf')) - elif builder.target.platform == 'mac': - bin64_folder = builder.AddFolder(os.path.join('addons', 'metamod', 'bin', 'osx64')) - builder.AddCopy(os.path.join(builder.sourcePath, 'support', 'metamod_osx64.vdf'), - os.path.join('addons', 'metamod_x64.vdf')) - -builder.AddCopy(os.path.join(builder.sourcePath, 'support', 'metamod.vdf'), addons_folder) -builder.AddCopy(os.path.join(builder.sourcePath, 'support', 'metaplugins.ini'), metamod_folder) -builder.AddCopy(os.path.join(builder.sourcePath, 'support', 'README.txt'), metamod_folder) - -pdb_list = [] -for task in MMS.binaries: - if '.x64' + os.sep in task.binary.path: - builder.AddCopy(task.binary, bin64_folder) - else: - builder.AddCopy(task.binary, bin_folder) - - if task.debug: - pdb_list.append(task.debug) - -# Generate PDB info. -with open(os.path.join(builder.buildPath, 'pdblog.txt'), 'wt') as fp: - for line in pdb_list: - fp.write(line.path + '\n') - diff --git a/utils/mmsource/support/buildbot/Versioning b/utils/mmsource/support/buildbot/Versioning deleted file mode 100644 index 1b5410fb8..000000000 --- a/utils/mmsource/support/buildbot/Versioning +++ /dev/null @@ -1,44 +0,0 @@ -# vim: set ts=8 sts=2 sw=2 tw=99 et ft=python: -import os, sys -import re - -builder.SetBuildFolder('/') - -includes = builder.AddFolder('includes') - -argv = [ - sys.executable, - os.path.join(builder.sourcePath, 'support', 'buildbot', 'generate_headers.py'), - os.path.join(builder.sourcePath), - os.path.join(builder.buildPath, 'includes') -] -outputs = [ - os.path.join(builder.buildFolder, 'includes', 'metamod_version_auto.h') -] - -with open(os.path.join(builder.sourcePath, '.git', 'HEAD')) as fp: - head_contents = fp.read().strip() - if re.search('^[a-fA-F0-9]{40}$', head_contents): - git_head_path = os.path.join(builder.sourcePath, '.git', 'HEAD') - else: - git_state = head_contents.split(':')[1].strip() - git_head_path = os.path.join(builder.sourcePath, '.git', git_state) - if not os.path.exists(git_head_path): - git_head_path = os.path.join(builder.sourcePath, '.git', 'HEAD') - -sources = [ - os.path.join(builder.sourcePath, 'product.version'), - - # This is a hack, but we need some way to only run this script when Git changes. - git_head_path, - - # The script source is a dependency, of course... - argv[1] -] -cmd_node, output_nodes = builder.AddCommand( - inputs=sources, - argv=argv, - outputs=outputs -) - -rvalue = output_nodes diff --git a/utils/mmsource/support/buildbot/bootstrap.pl b/utils/mmsource/support/buildbot/bootstrap.pl deleted file mode 100644 index 740ee66ce..000000000 --- a/utils/mmsource/support/buildbot/bootstrap.pl +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/perl -# vim: set ts=2 sw=2 tw=99 noet: - -use strict; -use Cwd; -use File::Basename; -use File::Path; - -my ($myself, $path) = fileparse($0); -chdir($path); - -require 'helpers.pm'; - -#Go back above build dir -chdir(Build::PathFormat('../../..')); - -#Get the source path. -our ($root) = getcwd(); - -my $reconf = 0; - -if (!(-f 'OUTPUT/.ambuild2/graph') || !(-f 'OUTPUT/.ambuild2/vars')) { - rmtree('OUTPUT'); - mkdir('OUTPUT') or die("Failed to create output folder: $!\n"); -} -chdir('OUTPUT'); -my ($result, $argn); -$argn = $#ARGV + 1; - -print "Attempting to reconfigure...\n"; - -my @conf_argv = ( - '--enable-optimize', - '--breakpad-dump', - '--no-color', - '--symbol-files' -); - -if ($^O =~ /darwin/) { - push(@conf_argv, '--hl2sdk-root=/Volumes/hgshare'); -} elsif ($^O =~ /linux/) { - push(@conf_argv, '--hl2sdk-root=/hgshare'); -} elsif ($^O =~ /MSWin/) { - push(@conf_argv, '--hl2sdk-root=H:\\'); -} - -if ($^O !~ /MSWin/) { - push(@conf_argv, '--target-arch=x86,x64'); -} else { - push(@conf_argv, '--target-arch=x86'); -} - -my $conf_args = join(' ', @conf_argv); - -if ($argn > 0 && $^O !~ /MSWin/) { - $result = `CC=$ARGV[0] CXX=$ARGV[0] python ../build/configure.py $conf_args`; -} else { - if ($^O =~ /MSWin/) { - $result = `C:\\Python27\\Python.exe ..\\build\\configure.py $conf_args`; - } else { - $result = `CC=clang CXX=clang python ../build/configure.py $conf_args`; - } -} -print "$result\n"; -if ($? != 0) { - die("Could not configure: $!\n"); -} - -sub IsNewer -{ - my ($file, $time) = (@_); - - my @s = stat($file); - my $mtime = $s[9]; - return $mtime > $time; -} - -exit(0); - - diff --git a/utils/mmsource/support/buildbot/build_type b/utils/mmsource/support/buildbot/build_type deleted file mode 100644 index 38f8e886e..000000000 --- a/utils/mmsource/support/buildbot/build_type +++ /dev/null @@ -1 +0,0 @@ -dev diff --git a/utils/mmsource/support/buildbot/generate_headers.py b/utils/mmsource/support/buildbot/generate_headers.py deleted file mode 100644 index c730ee71c..000000000 --- a/utils/mmsource/support/buildbot/generate_headers.py +++ /dev/null @@ -1,86 +0,0 @@ -# vim: set ts=8 sts=2 sw=2 tw=99 et: -import re -import os, sys -import subprocess - -argv = sys.argv[1:] -if len(argv) < 2: - sys.stderr.write('Usage: generate_headers.py \n') - sys.exit(1) - -SourceFolder = os.path.abspath(os.path.normpath(argv[0])) -OutputFolder = os.path.normpath(argv[1]) - -class FolderChanger: - def __init__(self, folder): - self.old = os.getcwd() - self.new = folder - - def __enter__(self): - if self.new: - os.chdir(self.new) - - def __exit__(self, type, value, traceback): - os.chdir(self.old) - -def run_and_return(argv): - # Python 2.6 doesn't have check_output. - if hasattr(subprocess, 'check_output'): - text = subprocess.check_output(argv) - if str != bytes: - text = str(text, 'utf-8') - else: - p = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - output, ignored = p.communicate() - rval = p.poll() - if rval: - raise subprocess.CalledProcessError(rval, argv) - text = output.decode('utf8') - return text.strip() - -def get_git_version(): - revision_count = run_and_return(['git', 'rev-list', '--count', 'HEAD']) - revision_hash = run_and_return(['git', 'log', '--pretty=format:%h:%H', '-n', '1']) - shorthash, longhash = revision_hash.split(':') - - return revision_count, shorthash, longhash - -def output_version_header(): - with FolderChanger(SourceFolder): - count, shorthash, longhash = get_git_version() - - with open(os.path.join(SourceFolder, 'product.version')) as fp: - contents = fp.read() - m = re.match('(\d+)\.(\d+)\.(\d+)-?(.*)', contents) - if m == None: - raise Exception('Could not detremine product version') - major, minor, release, tag = m.groups() - product = "{0}.{1}.{2}".format(major, minor, release) - fullstring = product - if tag != "": - fullstring += "-{0}".format(tag) - if tag == "dev": - fullstring += "+{0}".format(count) - - with open(os.path.join(OutputFolder, 'metamod_version_auto.h'), 'w') as fp: - fp.write(""" -#ifndef _METAMOD_AUTO_VERSION_INFORMATION_H_ -#define _METAMOD_AUTO_VERSION_INFORMATION_H_ - -#define MMS_BUILD_TAG \"{0}\" -#define MMS_BUILD_CSET \"{1}\" -#define MMS_BUILD_MAJOR \"{2}\" -#define MMS_BUILD_MINOR \"{3}\" -#define MMS_BUILD_RELEASE \"{4}\" -#define MMS_BUILD_LOCAL_REV \"{6}\" - -#define MMS_BUILD_UNIQUEID "{6}:" MMS_BUILD_CSET - -#define MMS_VERSION_STRING \"{5}\" -#define MMS_VERSION_FILE {2},{3},{4},0 - -#endif /* _METAMOD_AUTO_VERSION_INFORMATION_H_ */ - """.format(tag, shorthash, major, minor, release, fullstring, count)) - -output_version_header() - diff --git a/utils/mmsource/support/buildbot/helpers.pm b/utils/mmsource/support/buildbot/helpers.pm deleted file mode 100644 index 1e3e13ea6..000000000 --- a/utils/mmsource/support/buildbot/helpers.pm +++ /dev/null @@ -1,174 +0,0 @@ -#!/usr/bin/perl - -use strict; -use Cwd; - -package Build; - -our $SVN = "/usr/bin/svn"; -our $SVN_USER = 'dvander'; -our $SVN_ARGS = ''; - -sub GitRevNum -{ - my ($path) = (@_); - my ($cd, $text, $rev); - - $cd = Cwd::cwd(); - chdir($path); - $text = `git rev-list --count HEAD`; - chdir($cd); - - chomp $text; - if ($text =~ /^(\d+)/) { - return $1; - } - - return 0; -} - -sub HgRevNum -{ - my ($path) = (@_); - my ($cd, $text, $rev); - - $cd = Cwd::cwd(); - chdir($path); - $text = `hg identify -n`; - chdir($cd); - - chomp $text; - if ($text =~ /^(\d+)/) - { - return $1; - } - - return 0; -} - -sub SvnRevNum -{ - my ($str)=(@_); - - my $data = Command('svnversion -c ' . $str); - if ($data =~ /(\d+):(\d+)/) - { - return $2; - } elsif ($data =~ /(\d+)/) { - return $1; - } else { - return 0; - } -} - -sub ProductVersion -{ - my ($file) = (@_); - my ($version); - open(FILE, $file) or die "Could not open $file: $!\n"; - $version = ; - close(FILE); - chomp $version; - return $version; -} - -sub Delete -{ - my ($str)=(@_); - if ($^O =~ /MSWin/) - { - Command("del /S /F /Q \"$str\""); - Command("rmdir /S /Q \"$str\""); - } else { - Command("rm -rf $str"); - } - return !(-e $str); -} - -sub Copy -{ - my ($src,$dest)=(@_); - if ($^O =~ /MSWin/) - { - Command("copy \"$src\" \"$dest\" /y"); - } else { - Command("cp \"$src\" \"$dest\""); - } - return (-e $dest); -} - -sub Move -{ - my ($src,$dest)=(@_); - if ($^O =~ /MSWin/) - { - Command("move \"$src\" \"$dest\""); - } else { - Command("mv \"$src\" \"$dest\""); - } - return (-e $dest); -} - -sub Command -{ - my($cmd)=(@_); - print "$cmd\n"; - return `$cmd`; -} - -sub PathFormat -{ - my ($str)=(@_); - if ($^O =~ /MSWin/) - { - $str =~ s#/#\\#g; - } else { - $str =~ s#\\#/#g; - } - return $str; -} - -sub SVN_Remove -{ - my ($file)=(@_); - my ($path, $name); - if ($^O =~ /MSWin/) - { - ($path, $name) = ($file =~ /(.+)\/([^\/]+)$/); - } else { - ($path, $name) = ($file =~ /(.+)\\([^\\]+)$/); - } - my $dir = Cwd::cwd(); - chdir($path); - Command($SVN . ' ' . $SVN_ARGS . ' delete ' . $name); - chdir($dir); -} - -sub SVN_Add -{ - my ($file)=(@_); - my ($path, $name); - if ($^O =~ /MSWin/) - { - ($path, $name) = ($file =~ /(.+)\/([^\/]+)$/); - } else { - ($path, $name) = ($file =~ /(.+)\\([^\\]+)$/); - } - my $dir = Cwd::cwd(); - chdir($path); - Command($SVN . ' ' . $SVN_ARGS . ' add ' . $name); - chdir($dir); -} - -sub GetBuildType -{ - my ($file)=(@_); - my ($type); - open(TYPE, $file) or die("Could not open file: $!\n"); - $type = ; - close(TYPE); - chomp $type; - return $type; -} - -return 1; diff --git a/utils/mmsource/support/buildbot/package.pl b/utils/mmsource/support/buildbot/package.pl deleted file mode 100644 index 3a420b9cf..000000000 --- a/utils/mmsource/support/buildbot/package.pl +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/perl - -use strict; -use Cwd; -use File::Basename; -use File::Temp qw/ tempfile :seekable/; -use Net::FTP; - -my ($ftp_file, $ftp_host, $ftp_user, $ftp_pass, $ftp_path, $tag); - -$ftp_file = shift; -$tag = shift; - -open(FTP, $ftp_file) or die "Unable to read FTP config file $ftp_file: $!\n"; -$ftp_host = ; -$ftp_user = ; -$ftp_pass = ; -$ftp_path = ; -close(FTP); - -chomp $ftp_host; -chomp $ftp_user; -chomp $ftp_pass; -chomp $ftp_path; - -my ($myself, $path) = fileparse($0); -chdir($path); - -require 'helpers.pm'; - -#Switch to the output folder. -chdir(Build::PathFormat('../../../OUTPUT/package')); - -my ($version); - -$version = Build::ProductVersion(Build::PathFormat('../../build/product.version')); -$version =~ s/-dev//g; -$version .= '-git' . Build::GitRevNum('../../build'); - -# Append OS to package version -if ($^O eq "darwin") -{ - $version .= '-mac'; -} -elsif ($^O =~ /MSWin/) -{ - $version .= '-windows'; -} -else -{ - $version .= '-' . $^O; -} - -if (defined $tag) -{ - $version .= '-' . $tag; -} - -my ($filename); -$filename = 'mmsource-' . $version; -if ($^O eq "linux") -{ - $filename .= '.tar.gz'; - print "tar zcvf $filename addons\n"; - system("tar zcvf $filename addons"); -} -else -{ - $filename .= '.zip'; - print "zip -r $filename addons\n"; - system("zip -r $filename addons"); -} - -my ($tmpfh, $tmpfile) = tempfile(); -print $tmpfh $filename; -$tmpfh->seek( 0, SEEK_END ); -my $latest = "mmsource-latest-"; -if ($^O eq "darwin") { - $latest .= "mac"; -} -elsif ($^O =~ /MSWin/) { - $latest .= "windows"; -} -else { - $latest .= $^O; -} - -my ($major,$minor) = ($version =~ /^(\d+)\.(\d+)/); -$ftp_path .= "/$major.$minor"; - -my ($ftp); - -$ftp = Net::FTP->new($ftp_host, Debug => 0, Passive => 1) - or die "Cannot connect to host $ftp_host: $@"; - -$ftp->login($ftp_user, $ftp_pass) - or die "Cannot connect to host $ftp_host as $ftp_user: " . $ftp->message . "\n"; - -if ($ftp_path ne '') -{ - $ftp->cwd($ftp_path) - or die "Cannot change to folder $ftp_path: " . $ftp->message . "\n"; -} - -$ftp->binary(); -$ftp->put($filename) - or die "Cannot drop file $filename ($ftp_path): " . $ftp->message . "\n"; -$ftp->put($tmpfile, $latest) - or die "Cannot drop file $latest ($ftp_path): " . $ftp->message . "\n"; - -$ftp->close(); - -print "File sent to drop site as $filename -- build succeeded.\n"; - -exit(0); - diff --git a/utils/mmsource/support/buildbot/startbuild.pl b/utils/mmsource/support/buildbot/startbuild.pl deleted file mode 100644 index 712ae630d..000000000 --- a/utils/mmsource/support/buildbot/startbuild.pl +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/perl -# vim: set ts=2 sw=2 tw=99 noet: - -use File::Basename; - -my ($myself, $path) = fileparse($0); -chdir($path); - -require 'helpers.pm'; - -chdir('../../../OUTPUT'); - -my $argn = $#ARGV + 1; -if ($argn > 0) { - $ENV{CC} = $ARGV[0]; - $ENV{CXX} = $ARGV[0]; -} - -system("ambuild --no-color 2>&1"); - -if ($? != 0) -{ - die "Build failed: $!\n"; -} -else -{ - exit(0); -} - diff --git a/utils/mmsource/support/buildbot/symstore.pl b/utils/mmsource/support/buildbot/symstore.pl deleted file mode 100644 index e8d0fcbe6..000000000 --- a/utils/mmsource/support/buildbot/symstore.pl +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/perl - -use File::Basename; - -my ($myself, $path) = fileparse($0); -chdir($path); - -require 'helpers.pm'; - -chdir('..'); -chdir('..'); - -open(PDBLOG, '../OUTPUT/pdblog.txt') or die "Could not open pdblog.txt: $!\n"; - -#Get version info -my ($version); -$version = Build::ProductVersion(Build::PathFormat('product.version')); -$version =~ s/-dev//g; -$version .= '-git' . Build::GitRevNum('.'); - -my ($build_type); -$build_type = Build::GetBuildType(Build::PathFormat('support/buildbot/build_type')); - -if ($build_type eq "dev") -{ - $build_type = "buildbot"; -} -elsif ($build_type eq "rel") -{ - $build_type = "release"; -} - -my ($line); -while () -{ - $line = $_; - $line =~ s/\.pdb/\*/; - chomp $line; - Build::Command("symstore add /r /f \"..\\OUTPUT\\$line\" /s \"S:\\mmsource\" /t \"Metamod:Source\" /v \"$version\" /c \"$build_type\""); -} - -close(PDBLOG); - -#Lowercase DLLs. Sigh. -my (@files); -opendir(DIR, "S:\\mmsource") or die "Could not open mmsource symbol folder: $!\n"; -@files = readdir(DIR); -closedir(DIR); - -my ($i, $j, $file, @subdirs); -for ($i = 0; $i <= $#files; $i++) -{ - $file = $files[$i]; - next unless ($file =~ /\.dll$/); - next unless (-d "S:\\mmsource\\$file"); - opendir(DIR, "S:\\mmsource\\$file") or die "Could not open S:\\mmsource\\$file: $!\n"; - @subdirs = readdir(DIR); - closedir(DIR); - for ($j = 0; $j <= $#subdirs; $j++) - { - next unless ($subdirs[$j] =~ /[A-Z]/); - Build::Command("rename S:\\mmsource\\$file\\" . $subdirs[$j] . " " . lc($subdirs[$j])); - } -} - diff --git a/utils/mmsource/support/buildbot/upload_symbols.py b/utils/mmsource/support/buildbot/upload_symbols.py deleted file mode 100644 index 9756fdb5c..000000000 --- a/utils/mmsource/support/buildbot/upload_symbols.py +++ /dev/null @@ -1,114 +0,0 @@ -# vim: ts=8 sts=2 sw=2 tw=99 et ft=python: -import sys -import subprocess -import os -try: - import urllib.request as urllib -except ImportError: - import urllib2 as urllib - -if len(sys.argv) < 3: - sys.stderr.write('Usage: \n') - sys.exit(1) - -SYMBOL_SERVER = os.environ['BREAKPAD_SYMBOL_SERVER'] -symbol_file = sys.argv[1] -cmd_argv = sys.argv[2:] - -sys.stdout.write(' '.join(cmd_argv)) -sys.stdout.write('\n') - -p = subprocess.Popen( - args = cmd_argv, - stdout = subprocess.PIPE, - stderr = subprocess.PIPE, - shell = False -) -stdout, stderr = p.communicate() -out = stdout.decode('utf8') -err = stdout.decode('utf8') - -with open(symbol_file, 'w') as fp: - fp.write(out) - fp.write(err) - -lines = out.splitlines() - -paths = set() -roots = {} - -# Lets not even talk about this. -def fixWindowsPath(path): - import ctypes - GetShortPathName = ctypes.windll.kernel32.GetShortPathNameW - shortp = ctypes.create_unicode_buffer(260) - rv = GetShortPathName(path.capitalize(), shortp, 260) - if rv == 0 or rv > 260: - return path - GetLongPathName = ctypes.windll.kernel32.GetLongPathNameW - longp = ctypes.create_unicode_buffer(260) - rv = GetLongPathName(shortp, longp, 260) - if rv == 0 or rv > 260: - return path - return longp.value - -for i, line in enumerate(lines): - line = line.strip().split(None, 2) - - if line[0] != 'FILE': - continue - - path = line[2] - - if os.name == 'nt' and os.path.exists(path): - path = fixWindowsPath(path) - line = ' '.join(['FILE', line[1], path]) - lines[i] = line - - path = os.path.dirname(path) - if path in paths: - continue - - paths.add(path) - - root = None - url = None - rev = None - - with open(os.devnull, 'w') as devnull: - def runCommand(argv): - proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=devnull, cwd=path, universal_newlines=True) - procout, procerr = proc.communicate() - if proc.returncode: - raise RuntimeError('Failed to execute \'' + ' '.join(argv) + '\' = ' + str(proc.returncode)) - return procout.strip() - - try: - root = runCommand(['git', 'rev-parse', '--show-toplevel']) - root = os.path.normpath(root) - - if root in roots: - continue - - url = runCommand(['git', 'ls-remote', '--get-url', 'origin']) - rev = runCommand(['git', 'log', '--pretty=format:%H', '-n', '1']) - except (OSError, RuntimeError) as e: - #sys.stderr.write(str(e) + '\n') - continue - - roots[root] = (url, rev) - -index = 1 -while lines[index].split(None, 1)[0] == 'INFO': - index += 1; - -for root, info in roots.items(): - lines.insert(index, 'INFO REPO ' + ' '.join([info[1], info[0], root])) - index += 1; - -out = os.linesep.join(lines).encode('utf8') - -request = urllib.Request(SYMBOL_SERVER, out) -request.add_header('Content-Type', 'text/plain') -server_response = urllib.urlopen(request).read().decode('utf8').strip() -print(server_response) diff --git a/utils/mmsource/support/changelog.txt b/utils/mmsource/support/changelog.txt deleted file mode 100644 index f83610cf5..000000000 --- a/utils/mmsource/support/changelog.txt +++ /dev/null @@ -1,230 +0,0 @@ -2009/12/19 1.8.0: - - Added support for the Source engine that runs Left 4 Dead 2 (bug 4078). - - Added VP hook support to legacy SourceHook (bug 4019). - - Backported GetSourceEngineBuild from the new API to the legacy API (bug - 4082). - - Backported GetVSPInfo from the new API to the legacy API (bug 4079). - - Backported OnUnlinkConCommandBase event from the new API to the legacy API - (bug 4018). - - Improved usermessage extraction code (bug 4117). - - Improved OS X support for SourceHook (bug 3514). - - Added separate build for the Orange Box engine (bug 4084). - - Added game path to ISmmPluginExt API. - -2009/02/25 1.7.1: - - Added support for the Source engine version that runs Dark Messiah. The - development of this feature would not be possible without the support of the - following people from the game's community: Dylan Riggs, Carl Pettengill, Ed - Moreland, and Christian. - - Fixed a bug where plugin aliases defined in VDF files were not working on the - Orange Box and Left 4 Dead engines. - - Fixed SourceHook passing invalid mprotect() values (bug 3642). - - Fixed "late" load parameter always being true in VSP mode (bug 3532). - - Added MSVC project templates for plugins, from Daedilus. - -2008/11/26 1.7.0: - - Metamod:Source now uses a unified package that will run on all supported - Source engines. This means you do not have to download a version based on - which Source engine or game you use. - - Added support for the Source engine version that runs Left 4 Dead. - - The 'meta refresh' command now handles plugins loaded from VDF files. - - Fixed amb1952: Crash when the first plugin listed in metaplugins.ini had an - alias and was not on the first line of the file. - -2008/07/26 1.6.2: - - Fixed a bug where VDF files were opened by MM:S even if the .vdf extension - was not at the very end of the filename. For example, "plugin.vdf.disabled" - would have been opened in previous versions. (amb1534) - - Removed FCVAR_REPLICATED from MM:S convars. The following message will no - longer appear in client consoles: ConVarRef metamod_version doesn't point to - an existing ConVar. (amb1480) - -2008/02/25 1.6.1: - - Fixed crash bug against mods compiled with GCC-4.2 -fvisibility=hidden - - API wrappers for GetUserMessageInfo() now have failsafe fallbacks - since the OrangeBox SDK fixed an older SDK's crash bug. - -2008/02/18 1.6.0: - - Added ability to load from a VDF file instead of gameinfo.txt. - - Added ability to load MM:S plugins from VDF files. - - Added new version of SourceHook with the following changes: - - Added API for hooking functions on a virtual table to all instances. - - SH_ADD_HOOK macros now return non-zero hook IDs. Additionally, - the old hook adding/removing syntax is deprecated (but still supported). - - Added SH_REMOVE_HOOK_ID to remove hooks by ID. - - CallClasses have been deprecated. The SH_CALL macro can now take a class - instance pointer rather than a callclass pointer. - - Can now generate dynamic, arbitrary hooks at runtime (see hookmangen). - - Metamod:Source has now received a large internal rewrite to improve coding - standards and to separate internal logic from engine specifics. - - Added mm_basedir cvar to specify Metamod's base folder. - - Added API for getting highest supported IServerPluginCallbacks interface - version. - - Added API for detecting the engine version. - - Added API for getting the VSP-simulation interface upon late loading. - - Added OnUnlinkConCommandBase to IMetamodListner to notify when Metamod:Source - is about to remove a concommand or convar. - - Added the ability for Metamod:Source to load as a VSP instead of through - gameinfo.txt. - - The output of the "meta list" command has been reformatted in order to allow - more space for plugins' name, version, and author fields. - - Sample/Stub plugins have improved building mechanism and code, and will - compile against both MM:S 1.6 for OrangeBox and MM:S 1.4 for Episode 1. - -2008/07/26 1.4.4: - - Fixed a bug where loading plugins built for MM:S 1.3 or older (API ver <= 9) - would cause a crash. - - Fixed a bug where loading plugins using VDF files caused Metamod:Source - to crash on The Ship. (bug 1523) - - Fixed a class of crashes caused by improper cvar removal handling. (bug 1416) - - Fixed a bug where VDF files were opened by MM:S even if the .vdf extension - was not at the very end of the filename. For example, "plugin.vdf.disabled" - would have been opened in previous versions. (bug 1534) - - Removed FCVAR_REPLICATED from MM:S convars. (bug 1479) - -2008/01/23 1.4.3: - - Metamod:Source can now be loaded via a .vdf instead of gameinfo.txt. - - Added new plugin loading mechanism via .vdf files in the metamod folder. - - Changed "meta list" output to look similar to Metamod:Source 1.6. - - Plugins which need a VSP pointer can now receive it on late load. - - Fixed a small memory leak when using recalls (RETURN_META_NEWPARAMS). - - Fixed a rare memory corruption bug in the CVector class. - -2007/06/26 1.4.2: - - Fixed a bug where unloading all plugins could crash if one plugin had child - plugins. - -2007/05/16 1.4.1: - - The client version of the "meta" command should now work with games using the - latest Source beta (srcds0407). - - Fixed amb233 (VSP listener didn't work with Steam dedicated version). - - Fixed amb277 (failed to get user message list in Kreedz Climbing). - -2007/04/05 1.4.0: - - Added API functions for retrieving User Message info without potentially - crashing. - - Added API functions for letting SourceMM plugins use Valve Server Plugin - callbacks. - - Added plugin status to client version of "meta list" command. Previously, it - did not differentiate between running and paused plugins. - - An experimental automatic gameinfo.txt fixer is now available. - - Changed version numbering to include the build number (SVN revision). - - Fixed amb93 (improved mod path detection). - - Fixed various rare string inconsistencies. - -2006/11/29 1.3d: - - Updated Metamod:Source to recognize the latest Source Engine version - (ServerGameDLL006) - -2006/09/06 1.3a: - - Fixed a building issue on Linux which caused unresolved symbol errors when - trying to load Metamod:Source on a game using an older set of engine - libraries. This fix should now allow Metamod:Source to run with The Ship on - Linux. - -2006/08/16 1.3: - - Added SourceHook support for functions that return references. - - Added some extra information to the "meta game" command: Description and - Interface. For example, CS:S would display "Counter-Strike: Source" and - "ServerGameDLL004." - - Added some extra functionality to ISmmPluginManager. - - Added compiling support for MSVC 8.0 (Visual Studio 2005) and GCC 4.x. - - Added another API helper function for formatting and searching for - interfaces. - - Updated project files and source tree to use the latest HL2SDK. - - Updated the sample plugins to be a bit cleaner and use newer API. - - Fixed bug where Metamod:Source could load the wrong GameDLL and/or load more - than one GameDLL. This issue occured in HL2 CTF, SourceForts, or any other - mod that relied on files from another mod directory. - - Fixed bug where ISmmAPI::MetaFactory() would return the wrong interface when - trying to retrieve ISmmPluginManager. - - Fixed bug where returning false in Load() after adding a Metamod event - listener or hooking a function could cause a crash instead of rejecting the - plugin. - - Fixed bug where trying to load Metamod:Source a second time as a SourceMM or - Valve server plugin could cause a crash. - - Fixed a bug in FormatIface() that caused InterfaceSearch() to infinite loop. - -2006/06/14 1.2.3: - - Added SourceHook API for manual recalls: RETURN_META_(VALUE_)MNEWPARAMS - - Added support for ServerGameDLL005 (latest HL2DM update) - -2006/05/25 1.2.2: - - Added the ability to "alias" plugin names in metaplugins.ini. - - Added "meta alias" command. - - Added SourceHook API for manual callclasses. - - Added support for the latest Source engine (ServerGameDLL005). - - Added API for printing text in a client's console with ClientConPrintf. This - does the same thing as IVEngineServer::ClientPrintf except that it allows - string formatting. - - Added client version of "meta" command in order to allow clients to view - version information and a list of loaded plugins. - - Fixed a bug causing old mods on newer engines to fail loading. - - Fixed issues with SourceHook's SH_CALL and reference parameters. - - Fixed a bug where the mm_pluginsfile cvar was being ignored. - - Fixed a memory leak when using ISmmAPI::InterfaceSearch. - -2006/02/15 1.2.1: - - Fixed bug where returning newparams in a post hook would cause infinite - recursion. - - Fixed bug where "meta load" could load the same plugin multiple times. - - Fixed bug where unloading a plugin could crash internal hook states. - - Fixed bug where unhooking a single hook would clear the hook chain. - -2006/01/07 1.2: - - Added SourceHook API for modifying parameters in the hook chain. - - Added SourceHook API for declaring and hooking manual vtable hooks. - - Added better API for querying an interface factory. - - Added API for formatting an OS-independent path. - - Added Listen Server Launcher to the graphical installer. - - Fixed bug where failed plugins could crash the plugin list. - - NOTE: SourceHook changes may require plugins to be recompiled against the new - API. - -2005/12/06 1.1.2: - - Added interface overriding/sharing examples to sample plugins. - - Added API to help guessing at Valve interface versions. - - Fixed various memory leaks. - - Fixed memory corruption bug on vector copying. - - Fixed other various template bugs. - -2005/10/21 1.1.1: - - Fixed a bug where AllPluginsLoaded() was not called after DLLInit(). - -2005/10/21 1.1: - - Rewrote GameDLL loading code to be API version generic. As such, SourceMM - will now easily support new API releases without an SDK release, such as the - case with Day of Defeat:Source. - - Added more flexibility to plugin control by supplying an event system. - - Removed dependency on libstdc++.so by supplying a small template library. - - SourceHook internal API is now interface-based, meaning that future updates - to the API will not break older plugins. This update, however, breaks older - plugins. - - SourceHook is now re-entrant. - - Added a basic automated installer (by Basic-Master). - - Fixed a bug where games with changing game names would not work. - - Fixed various bugs, including a cvarlist corruption bug on unloading plugins. - -2005/07/07 1.00-RC2: - - Added API for dealing with ConCommandBase registration (cvars/concmds). This - is to fix the fact that Valve API provides no way to unlist a cvar/cmd. - - Added two new commands - "meta cmds" and "meta cvars". - - Added API calls for correctly printing to the console such that rcon will - also receive messages that a plugin prints. This problem was mentioned on - hlcoders and Valve offered no reply. - - Added event hooking and cvar samples to sample_mm. - - Added new cvar, mm_pluginsfile, which defaults to - "addons/metamod/metaplugins.ini". - - Fixed a bug where multiple vtable patches on the same hook were not - re-patched when removed. This caused a crash when two hooks were declared on - one function, the first was removed, and the original function was then - called. - - Fixed "meta clear" not unloading all plugins. - - Fixed Metamod:Source loading plugins with a higher current API version. - - Fixed whitespace being parsed in metaplugins.ini. - - Fixed bug where SourceHook tried to patch already destroyed/unavailable - memory. - - Bumped Plugin API version to 6. - -2005/05/06 1.00-RC1: - - Initial release. diff --git a/utils/mmsource/support/checkout-deps.sh b/utils/mmsource/support/checkout-deps.sh deleted file mode 100644 index a45a40009..000000000 --- a/utils/mmsource/support/checkout-deps.sh +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env bash -# This should be run inside a folder that contains MM:S, otherwise, it will checkout things into "mms-dependencies". - -trap "exit" INT - -ismac=0 -iswin=0 - -archive_ext=tar.gz -decomp="tar zxf" - -if [ `uname` = "Darwin" ]; then - ismac=1 -elif [ `uname` != "Linux" ] && [ -n "${COMSPEC:+1}" ]; then - iswin=1 - archive_ext=zip - decomp=unzip -fi - -if [ ! -d "metamod-source" ]; then - echo "Could not find a Metamod:Source repository; make sure you aren't running this script inside it." - exit 1 -fi - -checkout () -{ - if [ ! -d "$name" ]; then - git clone $repo -b $branch $name - if [ -n "$origin" ]; then - cd $name - git remote rm origin - git remote add origin $origin - cd .. - fi - else - cd $name - git checkout $branch - git pull origin $branch - cd .. - fi -} - -sdks=( csgo hl2dm nucleardawn l4d2 dods l4d css tf2 insurgency sdk2013 dota ) - -if [ $ismac -eq 0 ]; then - # Add these SDKs for Windows or Linux - sdks+=( orangebox blade episode1 bms ) - - # Add more SDKs for Windows only - if [ $iswin -eq 1 ]; then - sdks+=( darkm swarm bgt eye contagion ) - fi -fi - -# Check out a local copy as a proxy. -if [ ! -d "hl2sdk-proxy-repo" ]; then - git clone --mirror https://github.com/alliedmodders/hl2sdk hl2sdk-proxy-repo -else - cd hl2sdk-proxy-repo - git fetch - cd .. -fi - -for sdk in "${sdks[@]}" -do - repo=hl2sdk-proxy-repo - origin="https://github.com/alliedmodders/hl2sdk" - name=hl2sdk-$sdk - branch=$sdk - checkout -done - -`python -c "import ambuild2"` -if [ $? -eq 1 ]; then - repo="https://github.com/alliedmodders/ambuild" - origin= - branch=master - name=ambuild - checkout - - cd ambuild - if [ $iswin -eq 1 ]; then - python setup.py install - else - python setup.py build - echo "Installing AMBuild at the user level. Location can be: ~/.local/bin" - python setup.py install --user - fi -fi diff --git a/utils/mmsource/support/metamod.vdf b/utils/mmsource/support/metamod.vdf deleted file mode 100644 index 5a8da1c35..000000000 --- a/utils/mmsource/support/metamod.vdf +++ /dev/null @@ -1,5 +0,0 @@ -"Plugin" -{ - "file" "addons/metamod/bin/server" -} - diff --git a/utils/mmsource/support/metamod_linux64.vdf b/utils/mmsource/support/metamod_linux64.vdf deleted file mode 100644 index c446fe053..000000000 --- a/utils/mmsource/support/metamod_linux64.vdf +++ /dev/null @@ -1,5 +0,0 @@ -"Plugin" -{ - "file" "addons/metamod/bin/linux64/server" -} - diff --git a/utils/mmsource/support/metamod_osx64.vdf b/utils/mmsource/support/metamod_osx64.vdf deleted file mode 100644 index 37a2d8632..000000000 --- a/utils/mmsource/support/metamod_osx64.vdf +++ /dev/null @@ -1,5 +0,0 @@ -"Plugin" -{ - "file" "addons/metamod/bin/osx64/server" -} - diff --git a/utils/mmsource/support/metamod_win64.vdf b/utils/mmsource/support/metamod_win64.vdf deleted file mode 100644 index 52c203469..000000000 --- a/utils/mmsource/support/metamod_win64.vdf +++ /dev/null @@ -1,5 +0,0 @@ -"Plugin" -{ - "file" "addons/metamod/bin/win64/server" -} - diff --git a/utils/mmsource/support/metaplugins.ini b/utils/mmsource/support/metaplugins.ini deleted file mode 100644 index 22fc04da6..000000000 --- a/utils/mmsource/support/metaplugins.ini +++ /dev/null @@ -1,14 +0,0 @@ -;If your plugin came with a .vdf file, you do not need to use this file. -; -;List one plugin per line. Each line should contain the path to the plugin's binary. -;Any line starting with a ';' character is a comment line, and is ignored. -; -;You do not need to include the _i486.so or .dll part of the file name. Example: -; addons/sourcemod/bin/sourcemod_mm -;You may also put an alias in front of the file, for example: -; sm addons/sourcemod/bin/sourcemod_mm -;Will allow you to use "meta load sm" from the console. -; -;********* LIST PLUGINS BELOW *********** - - diff --git a/utils/mmsource/support/msvc_project_templates/MMSProjectTemplate.2005.vcproj b/utils/mmsource/support/msvc_project_templates/MMSProjectTemplate.2005.vcproj deleted file mode 100644 index 97eb30ff1..000000000 --- a/utils/mmsource/support/msvc_project_templates/MMSProjectTemplate.2005.vcproj +++ /dev/null @@ -1,160 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/utils/mmsource/support/msvc_project_templates/MMSProjectTemplate.2008.vcproj b/utils/mmsource/support/msvc_project_templates/MMSProjectTemplate.2008.vcproj deleted file mode 100644 index f0b7616a5..000000000 --- a/utils/mmsource/support/msvc_project_templates/MMSProjectTemplate.2008.vcproj +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/utils/mmsource/support/msvc_project_templates/VC/VCProjects/MMSProjectTemplate.ico b/utils/mmsource/support/msvc_project_templates/VC/VCProjects/MMSProjectTemplate.ico deleted file mode 100644 index 9458598ff..000000000 Binary files a/utils/mmsource/support/msvc_project_templates/VC/VCProjects/MMSProjectTemplate.ico and /dev/null differ diff --git a/utils/mmsource/support/msvc_project_templates/VC/VCProjects/MMSProjectTemplate.vsz b/utils/mmsource/support/msvc_project_templates/VC/VCProjects/MMSProjectTemplate.vsz deleted file mode 100644 index 89c7e9a73..000000000 --- a/utils/mmsource/support/msvc_project_templates/VC/VCProjects/MMSProjectTemplate.vsz +++ /dev/null @@ -1,6 +0,0 @@ -VSWIZARD 7.0 -Wizard=VsWizard.VsWizardEngine.8.0 - -Param="WIZARD_NAME = MMSProjectTemplate" -Param="RELATIVE_PATH = VCWizards\AppWiz\Metamod" -Param="FALLBACK_LCID = 1033" diff --git a/utils/mmsource/support/msvc_project_templates/VC/VCProjects/Metamod/MMSProjectTemplate.vsdir b/utils/mmsource/support/msvc_project_templates/VC/VCProjects/Metamod/MMSProjectTemplate.vsdir deleted file mode 100644 index b1de26aec..000000000 --- a/utils/mmsource/support/msvc_project_templates/VC/VCProjects/Metamod/MMSProjectTemplate.vsdir +++ /dev/null @@ -1 +0,0 @@ -..\MMSProjectTemplate.vsz| |Metamod C++ Project|1|This wizard will create a Metamod Source Plugin Project.| |6777| | diff --git a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/1033/Images/DottedHori.gif b/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/1033/Images/DottedHori.gif deleted file mode 100644 index 67072b86b..000000000 Binary files a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/1033/Images/DottedHori.gif and /dev/null differ diff --git a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/1033/Images/DottedVert.gif b/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/1033/Images/DottedVert.gif deleted file mode 100644 index 72e0c7dcd..000000000 Binary files a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/1033/Images/DottedVert.gif and /dev/null differ diff --git a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/1033/Images/spacer.gif b/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/1033/Images/spacer.gif deleted file mode 100644 index 13acffe53..000000000 Binary files a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/1033/Images/spacer.gif and /dev/null differ diff --git a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/1033/NewStyles.css b/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/1033/NewStyles.css deleted file mode 100644 index 08c726add..000000000 --- a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/1033/NewStyles.css +++ /dev/null @@ -1,782 +0,0 @@ -/******************************************************************************/ -/*DEFAULT STYLES FOR ALL SECTIONS**********************************************/ -/******************************************************************************/ -body { font-family: Tahoma, MS Sans Serif, Arial, Sans Serif; - font-weight: normal; - font-size: 8pt; - color: buttontext; - background-color: buttonface; - margin-top: 0px; - margin-left: 0px; - margin-right: 0px; - margin-bottom: 0px; - overflow: auto; } - -a:link { color: captiontext; - text-decoration: none; } - -a:visited { color: captiontext; - text-decoration: none; } - -a:active { color: captiontext; - text-decoration: none; } - -a:hover { color: captiontext; - text-decoration: underline; } - -table { font-family: Tahoma, MS Sans Serif, Arial, Sans Serif; - font-weight: normal; - font-size: 8pt; - color: buttontext; - width: 100%; } - -table.one { table-layout: fixed; - height: 100%; - width: 100%; } - - -/*DEFAULT STYLES FOR THE 'INTRODUCTION' TABLE**********************************/ -/******************************************************************************/ -table.two { table-layout: fixed; - height: 79px; - width: 100%; - background-color: window; } - -td.image { text-align: right; } - - -/*DEFAULT STYLES FOR THE 'NAVIGATION' TABLE************************************/ -/******************************************************************************/ -table.linkText { line-height: 95%; - width: 1.7in; - height: 2.6em; - position: relative; - left: 0.1in; - z-index: 2; } - -span { position: relative; - z-index: 3; } - -span.horiLine1 { height: 30px; - width: 166px; - position: absolute; - top: -1px; - left: -1px; - bottom: -1px; - z-index: 2; } - - -/*DEFAULT STYLES FOR THE ALL BUTTONS AND THE 'BUTTONS' TABLE*******************/ -/******************************************************************************/ -button { font-family: Tahoma, MS Sans Serif, Arial, Sans Serif; - font-weight: normal; - font-size: 8pt; - height: 23px; - cursor: hand; } - -.buttons { width: 100%; } - -/*DEFAULT STYLES FOR THE 'CONTENT' TABLE***************************************/ -/******************************************************************************/ -table.fixedSize { table-layout: fixed; } - -table.content { table-layout: fixed; - height: 100%; - width: 100%; } - -ol { font-family: Tahoma, MS Sans Serif, Arial, Sans Serif; - font-weight: normal; - font-size: 8pt; - color: buttontext; - margin-top: -1px; - margin-bottom: 16px; } - -ul { font-family: Tahoma, MS Sans Serif, Arial, Sans Serif; - font-weight: normal; - font-size: 8pt; - color: buttontext; - margin-top: 3px; - margin-bottom: 16px; } - -li { font-family: Tahoma, MS Sans Serif, Arial, Sans Serif; - font-weight: normal; - font-size: 8pt; - color: buttontext; - position: relative; - left: -15px; - margin-bottom: 1px; } - -span.itemTextTop { position: relative; } - -span.itemText { font-family: Tahoma, MS Sans Serif, Arial, Sans Serif; - font-weight: normal; - font-size: 8pt; - line-height: 9pt; - position: relative; - top: -3px; } - -span.itemTextIndent { position: relative; - left: 17px; - top: -3px; } - -span.sideBtnHidden { width: 100%; - margin-top: 3px; - margin-bottom: 0px; } - -div.itemTextRadioAa { position: relative; - top: -17px; - left: 17px; - margin-bottom: -25px; } - -div.itemTextRadioA { position: relative; - top: -19px; - left: 17px; - margin-bottom: -25px; } - -div.itemTextRadioB { position: relative; - top: -19px; - left: 25px; - margin-bottom: -25px; } - -div.itemTextRadioIndentA { position: relative; - top: -17px; - left: 30px; - margin-bottom: -25px; } - -div.itemTextRadioIndentB { position: relative; - top: -17px; - left: 42px; - margin-bottom: -25px; } - -div.itemTextCheckboxA { position: relative; - top: -17px; - left: 17px; - margin-bottom: -23px; } - -div.itemTextCheckboxB { position: relative; - top: -18px; - left: 25px; - padding-top: 1px; - margin-bottom: -25px; } - -div.itemTextCheckboxIndentB { position: relative; - top: -16px; - left: 42px; - margin-bottom: -25px; } - -input { font-family: Tahoma, MS Sans Serif, Arial, Sans Serif; - font-weight: normal; - font-size: 8pt; - color: buttontext; } - -select { font-family: Tahoma, MS Sans Serif, Arial, Sans Serif; - font-weight: normal; - font-size: 8pt; - color: buttontext; } - -.radio { position: relative; - top: -2px; - left: 4px; } - -.radioA { position: relative; - top: -1px; - margin-left: -4px; - z-index: 2; } - -.radioIndent { margin-top: -2px; - margin-left: 17px; } - -.radioIndentA { margin-top: -2px; - margin-left: 9px; } - -.checkbox { position: relative; - top: -1px; - margin-left: -4px; - z-index: 2; } - -.checkboxA { position: relative; - top: -2px; - left: 4px; } - -.checkboxIndent { position:relative; - margin-top: -1px; - margin-left: 21px; } - -.comment { width: 578px; - position: relative; - top: 5px; - bottom: 6px; } - -.commentA { width: 398px; - position: relative; - top: 5px; - bottom: 6px; } - -.commentB { width: 578px; - position: relative; - top: 3px; - bottom: -3px; } - -/****THIS IS THE STANDARD TABBED WIZARD, TWO COLUMN INPUT BOX******************/ -input.sideBtn { width: 193px; - position: relative; - top: 3px; } - -/****THIS IS THE STANDARD THREE COLUMN WIZARD INPUT BOX************************/ -input.sideBtnThreeColumn { width: 185px; - position: relative; - top: 3px; } - -/****THIS IS THE DEFAULT INPUT BOX IN NON-TABBED AND 2 COLUMN WIZARD***********/ -input.itemTextTwoColumnLong { width: 283px; - position: relative; - top: 3px; } - -/****THIS IS AN INPUT BOX INDENTED UNDER A CHECKBOX SECTION********************/ -input.sideBtnIndent { width: 175px; - position: relative; - top: 3px; - left: 18px; - bottom: 6px; } - -/****THIS INPUT BOX HAS IS INDENTED UNDER A HEADING AND RULE SECTION***********/ -input.sideBtnB { width: 185px; - position: relative; - top: 3px; - bottom: 6px; } - -input.sideBtnBA { width: 175px; - position: relative; - top: 3px; - bottom: 6px; } - -/****THIS INPUT BOX HAS A "..." BUTTON BESIDE IT AND IT'S A TABBED WIZARD******/ -input.sideBtn2 { width: 169px; - position: relative; - top: 3px; - bottom: 6px; } - -/****"..." BUTTON IN A NON-TABBED, 3 COLUMN WIZARD*****************************/ -input.sideBtn2ThreeColumn { width: 161px; - position: relative; - top: 3px; - bottom: 6px; } - -/****THIS IS AN INPUT BOX IN NON-TABBED AND 2 COLUMN WIZARD WITH A BUTTON******/ -input.TwoColumnLongButton { width: 259px; - position: relative; - top: 3px; - bottom: 6px; } - -/****THIS INPUT BOX HAS A "..." BUTTON BESIDE IT AND IT'S UNDER A CHECKBOX*****/ -input.sidebtn2Indent { width: 151px; - position: relative; - top: 3px; - left: 18px; - bottom: 6px; } - -/****"..." BUTTON IS UNDER A SECTION IN A TWO COLUMN AND TABBED WIZARD*********/ -input.sidebtn21 { width: 161px; - position: relative; - top: 3px; - bottom: 6px; } - -/****"..." BUTTON IS UNDER A SECTION IN A THREE COLUMN AND TABBED WIZARD*********/ -input.sidebtn21A { width: 153px; - position: relative; - top: 3px; - bottom: 6px; } - -/****THIS IS THE STANDARD TABBED WIZARD, TWO COLUMN SELECTION BOX**************/ -select.sidebtn { width: 193px; - position: relative; - top: 4px; - bottom: -3px; } - -select.sidebtnNoWidth { position: relative; - top: 4px; - bottom: -3px; } - -/****THIS IS THE STANDARD TABBED WIZARD, ONE COLUMN SELECTION BOX**************/ -select.sideBtnOneCLong { width: 398px; - position: relative; - top: 3px; } - -/****THIS IS THE STANDARD THREE COLUMN WIZARD INPUT BOX************************/ -select.sideBtnThreeColumn { width: 185px; - position: relative; - top: 4px; - bottom: -3px; } - -/****THIS IS THE DEFAULT INPUT BOX IN NON-TABBED AND 2 COLUMN WIZARD***********/ -select.itemTextTwoColumnLong { width: 283px; - position: relative; - top: 4px; - bottom: -3px; } - -/****THIS SELECTION BOX IS INDENTED UNDER A HEADING AND RULE SECTION***********/ -select.sidebtnB { width: 164px; - position: relative; - top: 4px; - left: 8px; - bottom: -3px; } - -/****THIS SELECTION BOX IS BELOW AND ASSOCIATED WITH A CHECKBOX****************/ -select.sidebtn2 { width: 164px; - position: relative; - top: 11px; - left: 17px; - bottom: -3px; } - -select.sidebtnIndent { width: 175px; - position: relative; - top: 4px; - left: 18px; - bottom: -3px; } - -/****THIS SELECTION BOX IS BELOW AND ASSOCIATED WITH A CHECKBOX AND HEADING****/ -select.sidebtn2AShort { width: 168px; - position: relative; - top: 4px; - left: 25px; - bottom: -3px; } - -/****THIS SELECTION BOX IS IN A TABBED, TWO COLUM WIZARD AND FOR < << > >>*****/ -select.sidebtn3 { width: 177px; - position: relative; - top: 4px; - bottom: -3px; } - -/****THIS IS A SELECTION BOX IN NON-TABBED AND 2 COLUMN WIZARD WITH A BUTTON***/ -select.TwoColumnLongButton { width: 259px; - position: relative; - top: 4px; - bottom: -3px; } - -/****THIS IS A SELECTION BOX IN NON-TABBED AND 2 COLUMN WIZARD WITH A BUTTON***/ -select.IndentListBoxWithButton { width: 283px; - position: relative; - top: 4px; - bottom: -3px; - left: 18px; } - -/****THIS IS THE DEFAULT OBJECT DROP DOWN IN 2 COLUMN AND TABBED WIZARD********/ -object.itemtext { font-family: Tahoma, MS Sans Serif, Arial, Sans Serif; - font-weight: normal; - font-size: 8pt; - color: buttontext; - width: 193px; - height: 2em; - position: relative; - top: 4px; - margin-bottom: 0px; } - -/****THIS IS THE DEFAULT OBJECT DROP DOWN IN 3 COLUMN AND NON-TABBED WIZARD****/ -object.itemtextThreeColumn { font-family: Tahoma, MS Sans Serif, Arial, Sans Serif; - font-weight: normal; - font-size: 8pt; - color: buttontext; - width: 185px; - height: 2em; - position: relative; - top: 4px; - margin-bottom: 0px; } - -/****THIS IS THE DEFAULT OBJECT DROP DOWN IN NON-TABBED AND 2 COLUMN WIZARD****/ -object.itemTextTwoColumnLong{ font-family: Tahoma, MS Sans Serif, Arial, Sans Serif; - font-weight: normal; - font-size: 8pt; - color: buttontext; - width: 283px; - height: 2em; - position: relative; - top: 4px; - margin-bottom: 0px; } - -.dropdowncombo { font-family: Tahoma, MS Sans Serif, Arial, Sans Serif; - font-weight: normal; - font-size: 8pt; - color: buttontext; } - -/****MOVES RADIO TEXT UP A BIT WHEN INLINE*************************************/ -span.upABit { position: relative; - top: -2px; } - -/****THIS DEFINES A STANDARD BUTTON IN THE CONTENT SECTION*********************/ -.buttonClass { margin-top: 0px; - margin-bottom: -6px; } - -/****THIS DEFINES ADD/REMOVE BUTTONS IN THE CONTENT SECTION********************/ -.buttonClass2 { width: 75px; - padding-top: 1px; - margin-top: 7px; } - -/****THIS DEFINES A "..." BUTTON IN THE CONTENT SECTION OUT OF THE SPAN TAG****/ -.buttonClass3 { height: 19px; - width: 20px; - position: relative; - left: 1px; - top: 0px; } - -/****THIS DEFINES A "..." BUTTON IN THE CONTENT SECTION WITHIN THE SPAN TAG***/ -.buttonClass3Custom { height: 19px; - width: 20px; - position: relative; - left: 4px; - top: 3px; } - -/****THIS DEFINES A "..." BUTTON IN THE CONTENT SECTION AND UNDER A CHECKBOX***/ -.buttonClass3Indent { height: 19px; - width: 20px; - position: relative; - top: 0px; - left: 10px; } - -/****THIS DEFINES A ">>" BUTTON IN THE CONTENT SECTION************************/ -.buttonClass4 { margin-bottom: 4px; - width: 25px; } - -/****THIS DEFINES ADD/REMOVE BUTTONS HORIZONTALLY IN THE CONTENT SECTION******/ -.buttonClass5 { position: relative; - top: 4px; - width: 75px; } - -/****THIS SETS THE LEFT MARGIN FOR THE REMOVE BUTTON***************************/ -#removeBtn { margin-left: 4px; } - -/****THIS SETS THE LEFT MARGIN FOR INDENTED SECTION UNDER CHECKBOXES***********/ -label.indent { margin-left: 18px; } - -/****THIS SETS THE LEFT MARGIN FOR INDENTED SECTION UNDER CHECKBOXES***********/ -label.indent2 { margin-left: 25px; } - -/****THIS MOVES CHECK BOX AND RADIO TEXT UP A BIT******************************/ -label.upABit { position: relative; - top: -2px; } - -/****THIS BOLDS < << > >> BUTTONS**********************************************/ -b.bigFont { font-size: 135%; } - -/****THESE ARE CUSTOM VERTICAL SPACING ELEMENTS********************************/ -p.spacer { margin-bottom: -28px; } - -p.elementSpacer { margin-bottom: -12px; } - -p.elementSpacer2 { margin-bottom: -19px; } - -p.elementSpacer3 { margin-bottom: -3px; } - -p.elementSpacer4 { margin-bottom: 7px; } - -p.elementSpacer5 { margin-bottom: 5px; } - -p.elementSpacer6 { margin-bottom: -24px; } - -p.elementSpacer7 { margin-bottom: -11px; } - -p.elementSpacer8 { margin-bottom: -15px; } - -p.elementSpacer9 { margin-bottom: -7px; } - -p.elementSpacer10 { margin-bottom: 6px; } - -p.elementSpacer11 { margin-bottom: -1px; } - -p.elementSpacer12 { margin-bottom: -17px; } - -p.elementSpacer13 { margin-bottom: -23px; } - -p.elementSpacer14 { margin-bottom: -25px; } - -p.elementSpacer15 { margin-bottom: -13px; } - -p.elementSpacer16 { margin-bottom: -22px; } - -p.elementSpacer17 { margin-bottom: -32px; } - -p.elementSpacer18 { margin-bottom: -14px; } - -p.elementSpacer19 { margin-bottom: -10px; } - -p.elementSpacer21 { margin-bottom: -16px; } - -p.elementSpacer22 { margin-bottom: 3px; } - -/*CUSTOM STYLES FOR THE 'CONTENT' FRAME****************************************/ -/******************************************************************************/ - - /*CUSTOM SPACING FOR MFC UI PAGE - SET UP FOR LOC PURPOSES*******************/ - /**************************************************************************/ - p.elementSpacer20 { margin-bottom: -13px; } - - /*CUSTOM STYLE FOR MFC UI PAGE - SET UP FOR LOC PURPOSES*******************/ - /**************************************************************************/ - input.sideBtnLoc { width: 193px; - position: relative; - top: 3px; } - - /*PLACES SPACE BETWEEN ADD/REMOVE BUTTONS**********************************/ - /**************************************************************************/ - span.spacer8 { width: 1px; } - - /*SETS TEXT BOX TO APPROPRIATE WIDTH IN MFCAppWiz**************************/ - /**************************************************************************/ - #CLASS_NAMES { width: 399px; } - - /*MOVES SELECT BOX UP IN CSharpIndexerWiz, Interface, Method,**************/ - /*InterfaceMethod, AND MemFunctionWiz**************************************/ - #PARAMETER_LIST { margin-top: -1px; } - - /*MOVES SELECT BOX UP IN CSharpMethodWiz***********************************/ - /**************************************************************************/ - #PARAMETER_LIST1 { margin-top: -1px; } - - /*SETS SELECTION BOX WIDTH IN CSharpInterfaceMethod AND CSharpMethodWiz****/ - /**************************************************************************/ - #PARAMETER_MODIFIER { width: 58px; } - - /*SETS INDENT FOR ATLCustom AND MFCCustom Wizards**************************/ - /**************************************************************************/ - span.itemTextIndent1 { position: relative; - left: 8px; - top: -3px; } - - /*SETS INDENT ON OBJECT FOR CSharpMethodWiz********************************/ - /**************************************************************************/ - span.customObjectIndent { margin-left: 8px; } - - /*SETS CUSTOM INDENT FOR SECTION IN CSHARPMETHODWIZ************************/ - /**************************************************************************/ - span.sidebtn { position: relative; - top: 4px; - bottom: -3px; } - - /*SETS CUSTOM INDENT FOR SECTION IN CSHARPMETHODWIZ************************/ - /**************************************************************************/ - span.itemtextspecial { position: relative; - top: -20px; - left: 9px; - bottom: -3px; } - - /*SETS CUSTOM INDENT FOR SECTION IN CSHARPMETHODWIZ************************/ - /**************************************************************************/ - span.sidebtnspecial { position: relative; - top: -2px; - left: 53px; - bottom: -3px; } - - /**************************************************************************/ - - - - - /*MODIFIED POSITIONING*****************************************************/ - /**************************************************************************/ - /*Position and border change + link to the script file (absolutely needed)!!*/ - table.three { table-layout: fixed; - height: 100%; - position: absolute; - left: -1px; - border-right: solid 2px Window; } - - /*Color change*/ - span.activeLink { color: WindowText; - text-decoration: none; - word-wrap: break-word; - cursor: hand; - width: 100%; - padding-top: 1px; - padding-bottom: 1px; } - - /*Color change*/ - span.activeLink2 { color: WindowText; - text-decoration: underline; - word-wrap: break-word; - cursor: hand; - width: 100%; - padding-top: 1px; - padding-bottom: 1px; } - - /*Color change*/ - span.inactiveLink { color: GrayText; - text-decoration: none; - word-wrap: break-word; - cursor: default; - width: 100%; - padding-top: 1px; - padding-bottom: 1px; } - - /*Turned off dotted line*/ - span.vertLine1 { height: 100%; - width: 1px; - position: absolute; - top: 0px; - left: -1px; - bottom: 0px; - z-index: 2; } - - /*Style for width-control of the left-side links bar */ - .LinkPane { width: 1.9in; } - - /*Removed bolding of text*/ - table.linkTextSelected { line-height: 95%; - width: 1.7in; - height: 2.6em; - position: relative; - left: 0.1in; - z-index: 2; } - - /*Removed bolding of text and made width bigger*/ - table.linkTextSelectedIndent { line-height: 95%; - width: 1.7in; - height: 2.6em; - position: relative; - top: -2px; - left: 0.2in; - z-index: 2; } - - /*Changed left margin and position of top of element and made width bigger*/ - table.linkTextIndent { line-height: 95%; - width: 1.6in; - height: 2.6em; - position: relative; - top: -2px; - left: 0.2in; - z-index: 2; } - - /*Removed background color, changed top, and bottom margins*/ - div.linkSelected { height: 2.6em; - position: relative; - top: -6px; - left: 0px; - right: 0px; - z-index: 1; - margin-bottom: -.7em; } - - /*Changed top and bottom margins*/ - div.link { height: 2em; - position: relative; - top: -6px; - left: 0px; - right: 0px; - z-index: 1; - margin-bottom: -.7em; } - - /*Comment out - div.vertLine { background: url(Images/DottedVert.gif) repeat; - height: 125%; - width: 1px; - position: relative; - top: -12px; - left: -1px; }*/ - - /*Deleted dotted line*/ - span.vertLine1 { height: 100%; - width: 1px; - position: absolute; - top: 0px; - left: -1px; - bottom: 0px; - z-index: 2; } - - /*Changed background color and add alpha*/ - td.three { background-color: Window; - filter: Alpha(Opacity = 25); } - - /*Removed all background image modification elements and set image to 0 opacity*/ - td.threeCustom { filter: Alpha(Opacity = 0); } - - - /*Comment out - td.dottedline { background: url(Images/DottedHori.gif) repeat; }*/ - - /*Removed border color*/ - div.inlineA { position: relative; - top: 4px; - width: 100%; - height: 1px; } - - /*Changed border color*/ - div.inlineB { position: relative; - top: -9px; - margin-bottom: -20px; - width: 100%; - height: 1px; - border-top: solid ThreeDShadow 1px; } - - /*Changed position of element*/ - h4.head { font-weight: bold; - font-size: 10pt; - color: windowtext; - position: absolute; - top: 16px; - left: 120px; - height: 58px; } - - /*Hide element*/ - p.subhead { display: none; - color: windowtext; - position: relative; - top: -1.5em; - left: 1em; } - - /*Changed alignment to right*/ - td.image { text-align: left; } - - /*Added item to control positioning of element*/ - div.smallA { position: absolute; - top: 0px; - left: 12px; - height: 78px; - width: 110px; - vertical-align: bottom; } - - /*Added item to control positioning of element - 1 misspelling in html so dup of above*/ - div.smalA { position: absolute; - top: 0px; - left: 12px; - height: 78px; - width: 110px; - vertical-align: bottom; } - - /*Added item to control positioning of element*/ - div.small { position: absolute; - top: 0px; - left: 12px; - height: 78px; - width: 110px; - vertical-align: bottom; } - - /*Added all positioning informaiton*/ - img.smallest { background-color: activecaption; - position: relative; - bottom: 1px; } - - /*Added item to control positioning of element*/ - img.small { position: relative; - bottom: 1px; } - - /*Add height specification*/ - td.rule { background-color: window; - height: 1px; } - - /*Info for new button*/ - #PreviousBtn { position: relative; - right: -79px; } - /*Info for new button*/ - #NextBtn { position: relative; - right: -79px; } - - /*Reposition button*/ - #FinishBtn { position: relative; - right: -79px; } - - /*Reposition button*/ - #CancelBtn { position: relative; - right: -79px; } - - /*Hide button*/ - #HelpBtn { display: none; } - - - /**************************************************************************/ diff --git a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/HTML/1033/default.htm b/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/HTML/1033/default.htm deleted file mode 100644 index a16da20d6..000000000 --- a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/HTML/1033/default.htm +++ /dev/null @@ -1,571 +0,0 @@ - - - - 'MMSProjectTemplate' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
-   - -   - -   - -
- -
-
-   -
-   - - -

-

-
-   -
- - - - - -
- -
-
-
- - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
-   -
-   - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Author:  This is the name of the author.
-
-
- URL:  This is the URL to the author's web site
-
-
- License:  This is the plugin's license.
-
-
- Plugin Name:  This is the name of the plugin.
-
-
- Plugin Description:  This is the plugin's description.
-
- Plugin DLL:  This is the name of the plugin's .dll file.
-
- Plugin Class:   This is the name of the plugin's class.
-
-
- - - - - -
- Function Hooks:  These functions will be auto generated. 
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- -
-
-
-
-
-   -
-   -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - -
- -
-
-   -
-   - -   - - - -   - - - -   - - - -   -
-   -
- -
- -
- - - - - - - - - - - - - diff --git a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Images/MMSProjectTemplate.gif b/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Images/MMSProjectTemplate.gif deleted file mode 100644 index b0206c76b..000000000 Binary files a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Images/MMSProjectTemplate.gif and /dev/null differ diff --git a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Images/MMSProjectTemplate_Background.gif b/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Images/MMSProjectTemplate_Background.gif deleted file mode 100644 index 7615277ef..000000000 Binary files a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Images/MMSProjectTemplate_Background.gif and /dev/null differ diff --git a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Scripts/1033/default.js b/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Scripts/1033/default.js deleted file mode 100644 index 409535807..000000000 --- a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Scripts/1033/default.js +++ /dev/null @@ -1,554 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////// -// // -// // -// File: Default.js // -// // -// // -/////////////////////////////////////////////////////////////////////////////////////////// - - -/////////////////////////////////////////////////////////////////////////////////////////// -// Use wizard.ReportError to display a message box for debugging - -// wizard.ReportError("", true); - - -/////////////////////////////////////////////////////////////////////////////////////////// -// OnFinish - -function OnFinish(selProj, selObj) -{ - try - { - // Get the new project name and path - - var strProjectName = wizard.FindSymbol('PROJECT_NAME'); - var strProjectPath = wizard.FindSymbol('PROJECT_PATH'); - - var strProjectTemplateName = wizard.FindSymbol('PLUGIN_TEMPLATE_NAME'); // Defined in default.htm - - // Get the current date and add a symbol CURRENT_DATE - - var curr_time = new Date(); - - var month = curr_time.getMonth() + 1; - var day = curr_time.getDate(); - var year = curr_time.getFullYear(); - var today = year + '-' + month + '-' + day; - - wizard.AddSymbol('CURRENT_DATE', today); - - // Set the path to where the template is installed - - var strPluginPath = wizard.FindSymbol('PROJECT_TEMPLATE_PATH') + - "\\AppWiz\\Metamod\\" + - strProjectTemplateName + "\\"; - - wizard.AddSymbol('PLUGIN_INSTALL_PATH', strPluginPath); - wizard.AddSymbol('PLUGIN_SOURCE_FILES', "Plugin Source Files"); - wizard.AddSymbol('PLUGIN_HEADER_FILES', "Plugin Header Files"); - wizard.AddSymbol('PLUGIN_RESOURCE_FILES', "Resource Files"); - - // Create the custom project - - selProj = CreateCustomProject(strProjectName, strProjectPath); - - AddConfig(selProj, strProjectName); - AddFilters(selProj); - - // Create the custom .inf file - - var InfFile = CreateCustomInfFile(); - - AddFilesToCustomProj(selProj, strProjectName, strProjectPath, InfFile); - PchSettings(selProj); - - InfFile.Delete(); - - // Save the project - - selProj.Object.Save(); - } - - // Catch Exceptions - - catch(ex) - { - if(ex.description.length != 0) - { - SetErrorInfo(ex); - } - - return ex.number - } -} - -/////////////////////////////////////////////////////////////////////////////////////////// -// CreateCustomProject - -function CreateCustomProject(strProjectName, strProjectPath) -{ - try - { - // Create the project's solution - - var strInstallPath = wizard.FindSymbol('PLUGIN_INSTALL_PATH'); - var strProjTemplate = strInstallPath + '\\Templates\\1033\\plugin.vcproj'; - - if(wizard.FindSymbol("CLOSE_SOLUTION")) - { - var Solution = dte.Solution; - Solution.Close(); - - var strSolutionName = wizard.FindSymbol("VS_SOLUTION_NAME"); - - if(strSolutionName.length) - { - var strSolutionPath = strProjectPath.substr(0, strProjectPath.length - strProjectName.length); - - Solution.Create(strSolutionPath, strSolutionName); - } - } - - // Override the new solution with our custom plugin.vcproj file - - var oTarget = wizard.FindSymbol("TARGET"); - var strProjectNameWithExt = strProjectName + '.vcproj'; - - if(wizard.FindSymbol("WIZARD_TYPE") == vsWizardAddSubProject) - { - return oTarget.AddFromTemplate(strProjTemplate, strProjectNameWithExt).SubProject; - } - - return oTarget.AddFromTemplate(strProjTemplate, strProjectPath, strProjectNameWithExt); - } - - // Catch Exceptions - - catch(ex) - { - throw ex; - } -} - -/////////////////////////////////////////////////////////////////////////////////////////// -// CreateCustomInfFile - -function CreateCustomInfFile() -{ - try - { - var fso = new ActiveXObject('Scripting.FileSystemObject'); - var TemporaryFolder = 2; - - var tfolder = fso.GetSpecialFolder(TemporaryFolder); - var strTempFolder = tfolder.Drive + '\\' + tfolder.Name; - var strWizTempFile = strTempFolder + "\\" + fso.GetTempName(); - - var strTemplatePath = wizard.FindSymbol('TEMPLATES_PATH'); - var strInfFile = strTemplatePath + '\\Templates.inf'; - - wizard.RenderTemplate(strInfFile, strWizTempFile); - - return fso.GetFile(strWizTempFile); - } - - // Catch Exceptions - - catch(ex) - { - throw ex; - } -} - -/////////////////////////////////////////////////////////////////////////////////////////// -// DelFile - -function DelFile(fso, strWizTempFile) -{ - try - { - // Delete the file - - if(fso.FileExists(strWizTempFile)) - { - var tmpFile = fso.GetFile(strWizTempFile); - - tmpFile.Delete(); - } - } - - // Catch Exceptions - - catch(ex) - { - throw ex; - } -} - -/////////////////////////////////////////////////////////////////////////////////////////// -// AddFilters - -function AddFilters(proj) -{ - // Our plugin.vcproj has filters -} - -/////////////////////////////////////////////////////////////////////////////////////////// -// AddConfig - -function AddConfig(proj, strProjectName) -{ - try - { - // Get the plugin dll name - - var plugin_dll = wizard.FindSymbol('PLUGIN_DLL'); - - if(plugin_dll.indexOf(".dll") < 0) - { - plugin_dll = plugin_dll + ".dll"; - } - - var project_exports = strProjectName.toUpperCase() + "_EXPORTS"; - project_exports = project_exports.replace(/ /g, "_") + ";"; - - // Debug - Original -> Configuration Properties -> C/C++ -> Preprocessor - - var config = proj.Object.Configurations('Debug - Original'); - var CLTool = config.Tools('VCCLCompilerTool'); - var LinkTool = config.Tools('VCLinkerTool'); - - CLTool.PreprocessorDefinitions = project_exports + CLTool.PreprocessorDefinitions; - LinkTool.OutputFile = "$(ProjectDir)\\Bin\\$(ConfigurationName)\\" + plugin_dll; - - // Release - Original -> Configuration Properties -> C/C++ -> Preprocessor - - config = proj.Object.Configurations('Release - Original'); - CLTool = config.Tools('VCCLCompilerTool'); - LinkTool = config.Tools('VCLinkerTool'); - - CLTool.PreprocessorDefinitions = project_exports + CLTool.PreprocessorDefinitions; - LinkTool.OutputFile = "$(ProjectDir)\\Bin\\$(ConfigurationName)\\" + plugin_dll; - - - // Debug - Dark Messiah -> Configuration Properties -> C/C++ -> Preprocessor - - var config = proj.Object.Configurations('Debug - Dark Messiah'); - var CLTool = config.Tools('VCCLCompilerTool'); - var LinkTool = config.Tools('VCLinkerTool'); - - CLTool.PreprocessorDefinitions = project_exports + CLTool.PreprocessorDefinitions; - LinkTool.OutputFile = "$(ProjectDir)\\Bin\\$(ConfigurationName)\\" + plugin_dll; - - // Release - Dark Messiah -> Configuration Properties -> C/C++ -> Preprocessor - - config = proj.Object.Configurations('Release - Dark Messiah'); - CLTool = config.Tools('VCCLCompilerTool'); - LinkTool = config.Tools('VCLinkerTool'); - - CLTool.PreprocessorDefinitions = project_exports + CLTool.PreprocessorDefinitions; - LinkTool.OutputFile = "$(ProjectDir)\\Bin\\$(ConfigurationName)\\" + plugin_dll; - - - // Debug - Orange Box -> Configuration Properties -> C/C++ -> Preprocessor - - config = proj.Object.Configurations('Debug - Orange Box'); - CLTool = config.Tools('VCCLCompilerTool'); - LinkTool = config.Tools('VCLinkerTool'); - - CLTool.PreprocessorDefinitions = project_exports + CLTool.PreprocessorDefinitions; - LinkTool.OutputFile = "$(ProjectDir)\\Bin\\$(ConfigurationName)\\" + plugin_dll; - - // Release - Orange Box -> Configuration Properties -> C/C++ -> Preprocessor - - config = proj.Object.Configurations('Release - Orange Box'); - CLTool = config.Tools('VCCLCompilerTool'); - LinkTool = config.Tools('VCLinkerTool'); - - CLTool.PreprocessorDefinitions = project_exports + CLTool.PreprocessorDefinitions; - LinkTool.OutputFile = "$(ProjectDir)\\Bin\\$(ConfigurationName)\\" + plugin_dll; - - - // Debug - Orange Box Valve -> Configuration Properties -> C/C++ -> Preprocessor - - config = proj.Object.Configurations('Debug - Orange Box Valve'); - CLTool = config.Tools('VCCLCompilerTool'); - LinkTool = config.Tools('VCLinkerTool'); - - CLTool.PreprocessorDefinitions = project_exports + CLTool.PreprocessorDefinitions; - LinkTool.OutputFile = "$(ProjectDir)\\Bin\\$(ConfigurationName)\\" + plugin_dll; - - // Release - Orange Box Valve -> Configuration Properties -> C/C++ -> Preprocessor - - config = proj.Object.Configurations('Release - Orange Box Valve'); - CLTool = config.Tools('VCCLCompilerTool'); - LinkTool = config.Tools('VCLinkerTool'); - - CLTool.PreprocessorDefinitions = project_exports + CLTool.PreprocessorDefinitions; - LinkTool.OutputFile = "$(ProjectDir)\\Bin\\$(ConfigurationName)\\" + plugin_dll; - - - // Debug - Left 4 Dead -> Configuration Properties -> C/C++ -> Preprocessor - - config = proj.Object.Configurations('Debug - Left 4 Dead'); - CLTool = config.Tools('VCCLCompilerTool'); - LinkTool = config.Tools('VCLinkerTool'); - - CLTool.PreprocessorDefinitions = project_exports + CLTool.PreprocessorDefinitions; - LinkTool.OutputFile = "$(ProjectDir)\\Bin\\$(ConfigurationName)\\" + plugin_dll; - - // Release - Left 4 Dead -> Configuration Properties -> C/C++ -> Preprocessor - - config = proj.Object.Configurations('Release - Left 4 Dead'); - CLTool = config.Tools('VCCLCompilerTool'); - LinkTool = config.Tools('VCLinkerTool'); - - CLTool.PreprocessorDefinitions = project_exports + CLTool.PreprocessorDefinitions; - LinkTool.OutputFile = "$(ProjectDir)\\Bin\\$(ConfigurationName)\\" + plugin_dll; - - - // Debug - Left 4 Dead 2 -> Configuration Properties -> C/C++ -> Preprocessor - - config = proj.Object.Configurations('Debug - Left 4 Dead 2'); - CLTool = config.Tools('VCCLCompilerTool'); - LinkTool = config.Tools('VCLinkerTool'); - - CLTool.PreprocessorDefinitions = project_exports + CLTool.PreprocessorDefinitions; - LinkTool.OutputFile = "$(ProjectDir)\\Bin\\$(ConfigurationName)\\" + plugin_dll; - - // Release - Left 4 Dead 2 -> Configuration Properties -> C/C++ -> Preprocessor - - config = proj.Object.Configurations('Release - Left 4 Dead 2'); - CLTool = config.Tools('VCCLCompilerTool'); - LinkTool = config.Tools('VCLinkerTool'); - - CLTool.PreprocessorDefinitions = project_exports + CLTool.PreprocessorDefinitions; - LinkTool.OutputFile = "$(ProjectDir)\\Bin\\$(ConfigurationName)\\" + plugin_dll; - } - - // Catch Exceptions - - catch(ex) - { - throw ex; - } -} - -/////////////////////////////////////////////////////////////////////////////////////////// -// PchSettings - -function PchSettings(proj) -{ - // TODO: specify pch settings -} - -/////////////////////////////////////////////////////////////////////////////////////////// -// GetTargetName - -function GetTargetName(strName) -{ - try - { - var strTarget = strName; - var strPluginName = wizard.FindSymbol('PLUGIN_NAME'); - var strPluginClass = wizard.FindSymbol('PLUGIN_CLASS'); - - // Target ReadMe File - - if(strName == "ReadMe.txt") - { - strTarget = "ReadMe.txt"; - } - - // Target StdMMS File - - else if(strName == "StdMMS.h") - { - strTarget = "StdMMS.h"; - } - - // Target plugin_mm File - - else if(strName == "plugin_mm.h") - { - strTarget = "Plugin\\" + strPluginClass + ".h"; - } - - // Target plugin_mm File - - else if(strName == "plugin_mm.cpp") - { - strTarget = "Plugin\\" + strPluginClass + ".cpp"; - } - - // Target plugin_hooks File - - else if(strName == "plugin_hooks.h") - { - strTarget = "Plugin\\" + strPluginClass + "Hooks.h"; - } - - // Target plugin_hooks File - - else if(strName == "plugin_hooks.cpp") - { - strTarget = "Plugin\\" + strPluginClass + "Hooks.cpp"; - } - - // Target plugin_engine File - - else if(strName == "plugin_engine.h") - { - strTarget = "Plugin\\" + strPluginClass + "Engine.h"; - } - - // Target plugin_mm File - - else if(strName == "plugin.vdf") - { - if(strPluginName.length) - { - strPluginName = strPluginName.replace(/ /g, ""); - - strTarget = "Bin\\" + strPluginName + ".vdf"; - } - } - - return strTarget; - } - - // Catch Exceptions - - catch(ex) - { - throw ex; - } -} - -/////////////////////////////////////////////////////////////////////////////////////////// -// AddFilesToCustomProj - -function AddFilesToCustomProj(proj, strProjectName, strProjectPath, InfFile) -{ - try - { - var vcProjectItems = proj.ProjectItems; - var vcProjectFilters = proj.Object.Filters; - - // Get references to the filters of the project - - var vcFilterSource = vcProjectFilters.Item(wizard.FindSymbol('PLUGIN_SOURCE_FILES')); - var vcFilterHeader = vcProjectFilters.Item(wizard.FindSymbol('PLUGIN_HEADER_FILES')); - var vcFilterRez = vcProjectFilters.Item(wizard.FindSymbol('PLUGIN_RESOURCE_FILES')); - - var strTemplatePath = wizard.FindSymbol('PLUGIN_INSTALL_PATH') + "Templates\\1033\\"; - var FileStream = InfFile.OpenAsTextStream(1, -2); - - // Process the template files - - while(!FileStream.AtEndOfStream) - { - var strLine = FileStream.ReadLine(); - - if(strLine == '') - { - continue; - } - - // Retrieve the file parameters - - var strName = strLine; - var strTargetFile = GetTargetName(strName); - var strTemplateFile = strTemplatePath + '\\' + strLine; - var strProjectFile = strProjectPath + '\\' + strTargetFile; - - // "true" will only copy the file from template_file - // to target_file without rendering / adding to the project - - var bCopyOnly = false; - var strExt = strName.substr(strName.lastIndexOf(".")); - - if(strExt == ".bmp" || - strExt == ".ico" || - strExt == ".gif" || - strExt == ".rtf" || - strExt == ".css") - { - bCopyOnly = true; - } - - wizard.RenderTemplate(strTemplateFile, strProjectFile, bCopyOnly); - - if(!KeepOutsideProject(strName)) - { - // Add source files to the 'Plugin Source Files' filter - - if(strExt == '.cpp' || - strExt == '.cxx' || - strExt == '.c') - { - vcFilterSource.AddFile(strTargetFile); - } - - // Add header files to the 'Plugin Header Files' filter - - else if(strExt == '.hpp' || - strExt == '.h') - { - vcFilterHeader.AddFile(strTargetFile); - } - - // Add resource files to the 'Resource Files' filter - - else if(strExt == '.rc2' || strExt == '.ico' || - strExt == '.gif' || strExt == '.bmp' || - strExt == '.vdf' || strExt == '.rc') - { - vcFilterRez.AddFile(strTargetFile); - } - - // Just add the rest to the project - - else - { - proj.Object.AddFile(strTargetFile); - } - } - } - - FileStream.Close(); - } - - // Catch Exceptions - - catch(ex) - { - throw ex; - } -} - -/////////////////////////////////////////////////////////////////////////////////////////// -// KeepOutsideProject - -function KeepOutsideProject(strName) -{ - try - { - var bAdd = false; - - if(strName == "ReadMe.txt") - { - bAdd = true; - } - - return bAdd; - } - - // Catch Exceptions - - catch(ex) - { - throw ex; - } -} diff --git a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/ReadMe.txt b/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/ReadMe.txt deleted file mode 100644 index e81f92a94..000000000 --- a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/ReadMe.txt +++ /dev/null @@ -1,5 +0,0 @@ -======================================================================== - [!output PLUGIN_NAME] : Project Overview -======================================================================== - -MMS Plugin Project has created this [!output PLUGIN_NAME] project for you as a starting point. diff --git a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/StdMMS.h b/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/StdMMS.h deleted file mode 100644 index 8b04c5401..000000000 --- a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/StdMMS.h +++ /dev/null @@ -1,44 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// File: StdMMS.h -// Author: [!output PLUGIN_AUTHOR] -// Date: [!output CURRENT_DATE] -// -// License: [!output PLUGIN_LICENSE] -// -// This software is provided 'as-is', without any express or -// implied warranty. In no event will the authors be held liable -// for any damages arising from the use of this software. -// -// Based on code written by AlliedModders LLC. Sample Plugin -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _StdMMS_H -#define _StdMMS_H - -/////////////////////////////////////////////////////// -// Include Standard Headers - -#include - -/////////////////////////////////////////////////////// -// Include MetaMod Headers - -#include -#include -#include -#include - -/////////////////////////////////////////////////////// -// Include [!output PROJECT_NAME] Headers - -#include "Plugin/[!output PLUGIN_CLASS]Hooks.h" -#include "Plugin/[!output PLUGIN_CLASS].h" -#include "Plugin/[!output PLUGIN_CLASS]Engine.h" - -// TODO: Add your own headers here. - -// ex. #include "MyCode/MyInclude.h" - -#endif // _StdMMS_H diff --git a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/Templates.inf b/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/Templates.inf deleted file mode 100644 index c1b859f9a..000000000 --- a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/Templates.inf +++ /dev/null @@ -1,8 +0,0 @@ -StdMMS.h -plugin_mm.h -plugin_mm.cpp -plugin_hooks.h -plugin_hooks.cpp -plugin_engine.h -plugin.vdf -ReadMe.txt diff --git a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/plugin.vcproj b/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/plugin.vcproj deleted file mode 100644 index 523460a63..000000000 --- a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/plugin.vcproj +++ /dev/null @@ -1,386 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/plugin.vdf b/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/plugin.vdf deleted file mode 100644 index 60a590ba2..000000000 --- a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/plugin.vdf +++ /dev/null @@ -1,5 +0,0 @@ -"Metamod Plugin" -{ - "alias" "[!output PLUGIN_NAME]" - "file" "addons/metamod/plugins/[!output PLUGIN_NAME]/bin/[!output PLUGIN_DLL]" -} diff --git a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/plugin_engine.h b/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/plugin_engine.h deleted file mode 100644 index 5d1fc6b4d..000000000 --- a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/plugin_engine.h +++ /dev/null @@ -1,127 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// File: [!output PLUGIN_CLASS]Engine.h -// Author: [!output PLUGIN_AUTHOR] -// Date: [!output CURRENT_DATE] -// -// License: [!output PLUGIN_LICENSE] -// -// This software is provided 'as-is', without any express or -// implied warranty. In no event will the authors be held liable -// for any damages arising from the use of this software. -// -// Based on code written by AlliedModders LLC. Sample Plugin -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _MMS_ENGINE_H -#define _MMS_ENGINE_H - -#include - -///////////////////////////////////////////////////////////////////////// -// Class [!output PLUGIN_CLASS] - -class [!output PLUGIN_CLASS]; - -///////////////////////////////////////////////////////////////////////// -// Episode One - -#if SOURCE_ENGINE == SE_EPISODEONE && defined METAMOD_PLAPI_VERSION - -#error "Metamod:Source 1.6 API is not supported on the old engine." - -#endif - -///////////////////////////////////////////////////////////////////////// -// Wrap some API calls for legacy MM:S. - -#if !defined METAMOD_PLAPI_VERSION - -#define GetEngineFactory engineFactory -#define GetServerFactory serverFactory - -#define MM_Format snprintf -#define GetCGlobals pGlobals - -#else - -#define MM_Format g_SMAPI->Format - -#endif - -///////////////////////////////////////////////////////////////////////// -// Wrap the CCommand class so our code looks the same for both engines. - -#if SOURCE_ENGINE <= SE_DARKMESSIAH - -class CCommand -{ - public: - - const char *ArgS() - { - return [!output PLUGIN_CLASS]::EngineServer->Cmd_Args(); - } - - int ArgC() - { - return [!output PLUGIN_CLASS]::EngineServer->Cmd_Argc(); - } - - const char *Arg(int index) - { - return [!output PLUGIN_CLASS]::EngineServer->Cmd_Argv(index); - } -}; - -#define CVAR_INTERFACE_VERSION VENGINE_CVAR_INTERFACE_VERSION - -#endif - -///////////////////////////////////////////////////////////////////////// -// Left 4 Dead engine removed these from IVEngineServer - -#if SOURCE_ENGINE >= SE_LEFT4DEAD - -inline int IndexOfEdict(const edict_t* edict) -{ - return (int)(edict - [!output PLUGIN_CLASS]::GlobalVars->baseEdict); -} - -inline edict_t* PEntityOfEntIndex(int entity_index) -{ - if (entity_index >= 0 && entity_index < [!output PLUGIN_CLASS]::GlobalVars->maxEntities) - { - return (edict_t *)([!output PLUGIN_CLASS]::GlobalVars->baseEdict + entity_index); - } - return NULL; -} - -#else - -inline int IndexOfEdict(const edict_t* edict) -{ - return [!output PLUGIN_CLASS]::EngineServer->IndexOfEdict(edict); -} - -inline edict_t* PEntityOfEntIndex(int entity_index) -{ - return [!output PLUGIN_CLASS]::EngineServer->PEntityOfEntIndex(entity_index); -} - -#endif - -///////////////////////////////////////////////////////////////////////// -// Define snprintf - -#if defined WIN32 && !defined snprintf -#define snprintf _snprintf -#endif - -///////////////////////////////////////////////////////////////////////// -// Define ENGINE_CALL - -#define ENGINE_CALL(func) SH_CALL([!output PLUGIN_CLASS]::EngineServer, &IVEngineServer::func) - -#endif // _MMS_ENGINE_H diff --git a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/plugin_hooks.cpp b/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/plugin_hooks.cpp deleted file mode 100644 index f6a5a187d..000000000 --- a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/plugin_hooks.cpp +++ /dev/null @@ -1,675 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// File: [!output PLUGIN_CLASS]Hooks.cpp -// Author: [!output PLUGIN_AUTHOR] -// Date: [!output CURRENT_DATE] -// -// License: [!output PLUGIN_LICENSE] -// -// This software is provided 'as-is', without any express or -// implied warranty. In no event will the authors be held liable -// for any damages arising from the use of this software. -// -// Based on code written by AlliedModders LLC. Sample Plugin -// -/////////////////////////////////////////////////////////////////////////////// - -#include "StdMMS.h" - -///////////////////////////////////////////////////////////////////////// -// Declare the Hooks - -[!if IServerGameDLL_ServerActivate] -SH_DECL_HOOK3_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0, edict_t*, int, int); -[!endif] -[!if IServerGameDLL_GameInit] -SH_DECL_HOOK0(IServerGameDLL, GameInit, SH_NOATTRIB, 0, bool); -[!endif] -[!if IServerGameDLL_GameFrame] -SH_DECL_HOOK1_void(IServerGameDLL, GameFrame, SH_NOATTRIB, 0, bool); -[!endif] -[!if IServerGameDLL_GameShutdown] -SH_DECL_HOOK0_void(IServerGameDLL, GameShutdown, SH_NOATTRIB, 0); -[!endif] -[!if IServerGameDLL_LevelInit] -SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, 0, bool, char const*, char const*, char const*, char const*, bool, bool); -[!endif] -[!if IServerGameDLL_LevelShutdown] -SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, 0); -[!endif] -[!if IServerGameDLL_GetAllServerClasses] -SH_DECL_HOOK0(IServerGameDLL, GetAllServerClasses, SH_NOATTRIB, 0, ServerClass*); -[!endif] -[!if IServerGameDLL_GetTickInterval] -SH_DECL_HOOK0(IServerGameDLL, GetTickInterval, const, 0, float); -[!endif] -[!if IServerGameDLL_GetGameDescription] -SH_DECL_HOOK0(IServerGameDLL, GetGameDescription, SH_NOATTRIB, 0, const char*); -[!endif] - -[!if IServerGameClients_ClientActive] -SH_DECL_HOOK2_void(IServerGameClients, ClientActive, SH_NOATTRIB, 0, edict_t*, bool); -[!endif] -[!if IServerGameClients_ClientConnect] -SH_DECL_HOOK5(IServerGameClients, ClientConnect, SH_NOATTRIB, 0, bool, edict_t*, const char*, const char *, char *, int); -[!endif] -[!if IServerGameClients_ClientDisconnect] -SH_DECL_HOOK1_void(IServerGameClients, ClientDisconnect, SH_NOATTRIB, 0, edict_t*); -[!endif] -[!if IServerGameClients_ClientPutInServer] -SH_DECL_HOOK2_void(IServerGameClients, ClientPutInServer, SH_NOATTRIB, 0, edict_t*, char const *); -[!endif] -[!if IServerGameClients_ClientSettingsChanged] -SH_DECL_HOOK1_void(IServerGameClients, ClientSettingsChanged, SH_NOATTRIB, 0, edict_t*); -[!endif] -[!if IServerGameClients_ClientSetupVisibility] -SH_DECL_HOOK4_void(IServerGameClients, ClientSetupVisibility, SH_NOATTRIB, 0, edict_t*, edict_t*, unsigned char*, int); -[!endif] -[!if IServerGameClients_ClientEarPosition] -SH_DECL_HOOK2_void(IServerGameClients, ClientEarPosition, SH_NOATTRIB, 0, edict_t*, Vector*); -[!endif] -[!if IServerGameClients_PostClientMessagesSent] -SH_DECL_HOOK0_void(IServerGameClients, PostClientMessagesSent, SH_NOATTRIB, 0); -[!endif] -[!if IServerGameClients_ProcessUsercmds] -SH_DECL_HOOK7(IServerGameClients, ProcessUsercmds, SH_NOATTRIB, 0, float, edict_t*, bf_read*, int, int, int, bool, bool); -[!endif] -[!if IServerGameClients_GetPlayerLimits] -SH_DECL_HOOK3_void(IServerGameClients, GetPlayerLimits, const, 0, int&, int&, int&); -[!endif] -[!if IServerGameClients_GetPlayerState] -SH_DECL_HOOK1(IServerGameClients, GetPlayerState, SH_NOATTRIB, 0, CPlayerState*, edict_t*); -[!endif] -[!if IServerGameClients_GetReplayDelay] -SH_DECL_HOOK2(IServerGameClients, GetReplayDelay, SH_NOATTRIB, 0, int, edict_t*, int&); -[!endif] -[!if IServerGameClients_GetBugReportInfo] -SH_DECL_HOOK2_void(IServerGameClients, GetBugReportInfo, SH_NOATTRIB, 0, char*, int); -[!endif] -[!if IServerGameClients_SetCommandClient] -SH_DECL_HOOK1_void(IServerGameClients, SetCommandClient, SH_NOATTRIB, 0, int); -[!endif] -SH_DECL_HOOK2(IGameEventManager2, FireEvent, SH_NOATTRIB, 0, bool, IGameEvent*, bool); - -#if SOURCE_ENGINE >= SE_ORANGEBOX - -[!if IServerGameClients_NetworkIDValidated] -SH_DECL_HOOK2_void(IServerGameClients, NetworkIDValidated, SH_NOATTRIB, 0, const char *, const char *); -[!endif] -[!if IServerGameClients_ClientCommand] -SH_DECL_HOOK2_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t*, const CCommand&); -[!endif] - -#else - -[!if IServerGameClients_ClientCommand] -SH_DECL_HOOK1_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t*); -[!endif] - -#endif - - -///////////////////////////////////////////////////////////////////////// -// AddHooks - -void [!output PLUGIN_CLASS]::AddHooks() -{ - // Add the ServerGameDLL hooks - -[!if IServerGameDLL_ServerActivate] - SH_ADD_HOOK_MEMFUNC(IServerGameDLL, ServerActivate, [!output PLUGIN_CLASS]::GameServer, this, &[!output PLUGIN_CLASS]::HookedServerActivate, true); -[!endif] -[!if IServerGameDLL_GameInit] - SH_ADD_HOOK_MEMFUNC(IServerGameDLL, GameInit, [!output PLUGIN_CLASS]::GameServer, this, &[!output PLUGIN_CLASS]::HookedGameInit, true); -[!endif] -[!if IServerGameDLL_GameFrame] - SH_ADD_HOOK_MEMFUNC(IServerGameDLL, GameFrame, [!output PLUGIN_CLASS]::GameServer, this, &[!output PLUGIN_CLASS]::HookedGameFrame, true); -[!endif] -[!if IServerGameDLL_GameShutdown] - SH_ADD_HOOK_MEMFUNC(IServerGameDLL, GameShutdown, [!output PLUGIN_CLASS]::GameServer, this, &[!output PLUGIN_CLASS]::HookedGameShutdown, true); -[!endif] -[!if IServerGameDLL_LevelInit] - SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelInit, [!output PLUGIN_CLASS]::GameServer, this, &[!output PLUGIN_CLASS]::HookedLevelInit, true); -[!endif] -[!if IServerGameDLL_LevelShutdown] - SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelShutdown, [!output PLUGIN_CLASS]::GameServer, this, &[!output PLUGIN_CLASS]::HookedLevelShutdown, true); -[!endif] -[!if IServerGameDLL_GetAllServerClasses] - SH_ADD_HOOK_MEMFUNC(IServerGameDLL, GetAllServerClasses, [!output PLUGIN_CLASS]::GameServer, this, &[!output PLUGIN_CLASS]::HookedGetAllServerClasses, true); -[!endif] -[!if IServerGameDLL_GetTickInterval] - SH_ADD_HOOK_MEMFUNC(IServerGameDLL, GetTickInterval, [!output PLUGIN_CLASS]::GameServer, this, &[!output PLUGIN_CLASS]::HookedGetTickInterval, true); -[!endif] -[!if IServerGameDLL_GetGameDescription] - SH_ADD_HOOK_MEMFUNC(IServerGameDLL, GetGameDescription, [!output PLUGIN_CLASS]::GameServer, this, &[!output PLUGIN_CLASS]::HookedGetGameDescription, true); -[!endif] - - // Add the ServerGameClients hooks - -[!if IServerGameClients_ClientActive] - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientActive, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedClientActive, true); -[!endif] -[!if IServerGameClients_ClientConnect] - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientConnect, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedClientConnect, true); -[!endif] -[!if IServerGameClients_ClientDisconnect] - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedClientDisconnect, true); -[!endif] -[!if IServerGameClients_ClientCommand] - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientCommand, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedClientCommand, true); -[!endif] -[!if IServerGameClients_ClientPutInServer] - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientPutInServer, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedClientPutInServer, true); -[!endif] -[!if IServerGameClients_ClientSettingsChanged] - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientSettingsChanged, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedClientSettingsChanged, true); -[!endif] -[!if IServerGameClients_ClientSetupVisibility] - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientSetupVisibility, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedClientSetupVisibility, true); -[!endif] -[!if IServerGameClients_ClientEarPosition] - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ClientEarPosition, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedClientEarPosition, true); -[!endif] -[!if IServerGameClients_PostClientMessagesSent] - SH_ADD_HOOK_MEMFUNC(IServerGameClients, PostClientMessagesSent, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedPostClientMessagesSent, true); -[!endif] -[!if IServerGameClients_ProcessUsercmds] - SH_ADD_HOOK_MEMFUNC(IServerGameClients, ProcessUsercmds, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedProcessUsercmds, false); -[!endif] -[!if IServerGameClients_GetPlayerLimits] - SH_ADD_HOOK_MEMFUNC(IServerGameClients, GetPlayerLimits, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedGetPlayerLimits, true); -[!endif] -[!if IServerGameClients_GetPlayerState] - SH_ADD_HOOK_MEMFUNC(IServerGameClients, GetPlayerState, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedGetPlayerState, true); -[!endif] -[!if IServerGameClients_GetReplayDelay] - SH_ADD_HOOK_MEMFUNC(IServerGameClients, GetReplayDelay, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedGetReplayDelay, true); -[!endif] -[!if IServerGameClients_GetBugReportInfo] - SH_ADD_HOOK_MEMFUNC(IServerGameClients, GetBugReportInfo, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedGetBugReportInfo, true); -[!endif] -[!if IServerGameClients_SetCommandClient] - SH_ADD_HOOK_MEMFUNC(IServerGameClients, SetCommandClient, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedSetCommandClient, true); -[!endif] - -[!if IServerGameClients_NetworkIDValidated] - #if SOURCE_ENGINE >= SE_ORANGEBOX - - SH_ADD_HOOK_MEMFUNC(IServerGameClients, NetworkIDValidated, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedNetworkIDValidated, true); - - #endif -[!endif] -} - -///////////////////////////////////////////////////////////////////////// -// RemoveHooks - -void [!output PLUGIN_CLASS]::RemoveHooks() -{ - // Remove the ServerGameDLL hooks - -[!if IServerGameDLL_ServerActivate] - SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, ServerActivate, [!output PLUGIN_CLASS]::GameServer, this, &[!output PLUGIN_CLASS]::HookedServerActivate, true); -[!endif] -[!if IServerGameDLL_GameInit] - SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, GameInit, [!output PLUGIN_CLASS]::GameServer, this, &[!output PLUGIN_CLASS]::HookedGameInit, true); -[!endif] -[!if IServerGameDLL_GameFrame] - SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, GameFrame, [!output PLUGIN_CLASS]::GameServer, this, &[!output PLUGIN_CLASS]::HookedGameFrame, true); -[!endif] -[!if IServerGameDLL_GameShutdown] - SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, GameShutdown, [!output PLUGIN_CLASS]::GameServer, this, &[!output PLUGIN_CLASS]::HookedGameShutdown, true); -[!endif] -[!if IServerGameDLL_LevelInit] - SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, LevelInit, [!output PLUGIN_CLASS]::GameServer, this, &[!output PLUGIN_CLASS]::HookedLevelInit, true); -[!endif] -[!if IServerGameDLL_LevelShutdown] - SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, LevelShutdown, [!output PLUGIN_CLASS]::GameServer, this, &[!output PLUGIN_CLASS]::HookedLevelShutdown, true); -[!endif] -[!if IServerGameDLL_GetAllServerClasses] - SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, GetAllServerClasses, [!output PLUGIN_CLASS]::GameServer, this, &[!output PLUGIN_CLASS]::HookedGetAllServerClasses, true); -[!endif] -[!if IServerGameDLL_GetTickInterval] - SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, GetTickInterval, [!output PLUGIN_CLASS]::GameServer, this, &[!output PLUGIN_CLASS]::HookedGetTickInterval, true); -[!endif] -[!if IServerGameDLL_GetGameDescription] - SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, GetGameDescription, [!output PLUGIN_CLASS]::GameServer, this, &[!output PLUGIN_CLASS]::HookedGetGameDescription, true); -[!endif] - - // Remove the ServerGameClients hooks - -[!if IServerGameClients_ClientActive] - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientActive, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedClientActive, true); -[!endif] -[!if IServerGameClients_ClientConnect] - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientConnect, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedClientConnect, true); -[!endif] -[!if IServerGameClients_ClientDisconnect] - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientDisconnect, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedClientDisconnect, true); -[!endif] -[!if IServerGameClients_ClientCommand] - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientCommand, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedClientCommand, true); -[!endif] -[!if IServerGameClients_ClientPutInServer] - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientPutInServer, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedClientPutInServer, true); -[!endif] -[!if IServerGameClients_ClientSettingsChanged] - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientSettingsChanged, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedClientSettingsChanged, true); -[!endif] -[!if IServerGameClients_ClientSetupVisibility] - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientSetupVisibility, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedClientSetupVisibility, true); -[!endif] -[!if IServerGameClients_ClientEarPosition] - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ClientEarPosition, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedClientEarPosition, true); -[!endif] -[!if IServerGameClients_PostClientMessagesSent] - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, PostClientMessagesSent, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedPostClientMessagesSent, true); -[!endif] -[!if IServerGameClients_ProcessUsercmds] - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, ProcessUsercmds, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedProcessUsercmds, true); -[!endif] -[!if IServerGameClients_GetPlayerLimits] - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, GetPlayerLimits, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedGetPlayerLimits, true); -[!endif] -[!if IServerGameClients_GetPlayerState] - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, GetPlayerState, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedGetPlayerState, true); -[!endif] -[!if IServerGameClients_GetReplayDelay] - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, GetReplayDelay, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedGetReplayDelay, true); -[!endif] -[!if IServerGameClients_GetBugReportInfo] - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, GetBugReportInfo, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedGetBugReportInfo, true); -[!endif] -[!if IServerGameClients_SetCommandClient] - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, SetCommandClient, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedSetCommandClient, true); -[!endif] - -[!if IServerGameClients_NetworkIDValidated] - #if SOURCE_ENGINE >= SE_ORANGEBOX - - SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, NetworkIDValidated, [!output PLUGIN_CLASS]::GameClients, this, &[!output PLUGIN_CLASS]::HookedNetworkIDValidated, true); - - #endif -[!endif] -} - - -[!if IServerGameDLL_ServerActivate] -///////////////////////////////////////////////////////////////////////// -// HookedServerActivate - -// The server is about to activate - -void [!output PLUGIN_CLASS]::HookedServerActivate(edict_t* edict_list, int edict_count, int client_max) -{ - // TODO: Implement Method - - RETURN_META(MRES_IGNORED); -} - -[!endif] -[!if IServerGameDLL_GameInit] -///////////////////////////////////////////////////////////////////////// -// HookedGameInit - -// This is called when a new game is started. (restart, map) - -bool [!output PLUGIN_CLASS]::HookedGameInit() -{ - // TODO: Implement Method - - RETURN_META_VALUE(MRES_IGNORED, true); -} - -[!endif] -[!if IServerGameDLL_GameFrame] -///////////////////////////////////////////////////////////////////////// -// HookedGameFrame - -// The server should run physics / think on all edicts - -void [!output PLUGIN_CLASS]::HookedGameFrame(bool simulating) -{ - // TODO: Implement Method - - RETURN_META(MRES_IGNORED); -} - -[!endif] -[!if IServerGameDLL_GameShutdown] -///////////////////////////////////////////////////////////////////////// -// HookedGameShutdown - -// This is called when a game ends (server disconnect, death, -// restart, load). NOT on level transitions within a game - -void [!output PLUGIN_CLASS]::HookedGameShutdown() -{ - // TODO: Implement Method - - RETURN_META(MRES_IGNORED); -} - -[!endif] -[!if IServerGameDLL_LevelInit] -///////////////////////////////////////////////////////////////////////// -// HookedLevelInit - -// Called any time a new level is started (after -// GameInit() also on level transitions within a game) - -bool [!output PLUGIN_CLASS]::HookedLevelInit(const char* map_name, char const* map_entities, char const* old_level, - char const* landmark_name, bool load_game, bool bkgnd) -{ - // TODO: Implement Method - - RETURN_META_VALUE(MRES_IGNORED, true); -} - -[!endif] -[!if IServerGameDLL_LevelShutdown] -///////////////////////////////////////////////////////////////////////// -// HookedLevelShutdown - -// Called when a level is shutdown (including changing levels) - -void [!output PLUGIN_CLASS]::HookedLevelShutdown() -{ - // TODO: Implement Method - - RETURN_META(MRES_IGNORED); -} - -[!endif] -[!if IServerGameDLL_GetAllServerClasses] -///////////////////////////////////////////////////////////////////////// -// HookedGetAllServerClasses - -// Gets the list of datatable classes to the engine. The engine -// matches class names from here with edict_t::classname to figure -// out how to encode a class's data for networking - -ServerClass* [!output PLUGIN_CLASS]::HookedGetAllServerClasses() -{ - // TODO: Implement Method - - RETURN_META_VALUE(MRES_IGNORED, NULL); -} - -[!endif] -[!if IServerGameDLL_GetTickInterval] -///////////////////////////////////////////////////////////////////////// -// HookedGetTickInterval - -// Get the simulation interval (must be compiled with identical values -// into both client and game .dll for MOD!!!). Right now this is only -// requested at server startup time so it can't be changed on the fly, etc. - -float [!output PLUGIN_CLASS]::HookedGetTickInterval() const -{ - // TODO: Implement Method - - RETURN_META_VALUE(MRES_IGNORED, 0.0f); -} - -[!endif] -[!if IServerGameDLL_GetGameDescription] -///////////////////////////////////////////////////////////////////////// -// HookedGetGameDescription - -// Returns string describing current .dll. -// e.g. TeamFortress 2, Half-Life 2 - -const char* [!output PLUGIN_CLASS]::HookedGetGameDescription() -{ - // TODO: Implement Method - - RETURN_META_VALUE(MRES_IGNORED, ""); -} - -[!endif] -[!if IServerGameClients_ClientActive] -///////////////////////////////////////////////////////////////////////// -// HookedClientActive - -// Client is going active. If load_game is true, don't -// spawn the player because its state is already setup. - -void [!output PLUGIN_CLASS]::HookedClientActive(edict_t* entity, bool load_game) -{ - // TODO: Implement Method - - RETURN_META(MRES_IGNORED); -} - -[!endif] -[!if IServerGameClients_ClientConnect] -///////////////////////////////////////////////////////////////////////// -// HookedClientConnect - -// Client is connecting to server (return false to reject the connection) -// You can specify a rejection message by writing it into reject - -bool [!output PLUGIN_CLASS]::HookedClientConnect(edict_t* entity, const char* name, const char* address, char* reject, int reject_len) -{ - // TODO: Implement Method - - RETURN_META_VALUE(MRES_IGNORED, true); -} - -[!endif] -[!if IServerGameClients_ClientDisconnect] -///////////////////////////////////////////////////////////////////////// -// HookedClientDisconnect - -// Client is disconnecting from server - -void [!output PLUGIN_CLASS]::HookedClientDisconnect(edict_t* entity) -{ - // TODO: Implement Method - - RETURN_META(MRES_IGNORED); -} - -[!endif] -[!if IServerGameClients_ClientCommand] -///////////////////////////////////////////////////////////////////////// -// HookedClientCommand - -// The client has typed a command at the console - -#if SOURCE_ENGINE >= SE_ORANGEBOX -void [!output PLUGIN_CLASS]::HookedClientCommand(edict_t* entity, const CCommand& args) -#else -void [!output PLUGIN_CLASS]::HookedClientCommand(edict_t* entity) -#endif -{ - // Verify the parameters - - #if SOURCE_ENGINE <= SE_DARKMESSIAH - CCommand args; - #endif - - if(!entity || entity->IsFree()) - { - RETURN_META(MRES_IGNORED); - } - - // TODO: Implement Method - - RETURN_META(MRES_IGNORED); -} - -[!endif] -[!if IServerGameClients_ClientPutInServer] -///////////////////////////////////////////////////////////////////////// -// HookedClientPutInServer - -// Client is connected and should be put in the game - -void [!output PLUGIN_CLASS]::HookedClientPutInServer(edict_t* entity, char const* name) -{ - // TODO: Implement Method - - RETURN_META(MRES_IGNORED); -} - -[!endif] -[!if IServerGameClients_ClientSettingsChanged] -///////////////////////////////////////////////////////////////////////// -// HookedClientSettingsChanged - -// A player changed one / several replicated cvars (name etc...) - -void [!output PLUGIN_CLASS]::HookedClientSettingsChanged(edict_t* edict) -{ - // TODO: Implement Method - - RETURN_META(MRES_IGNORED); -} - -[!endif] -[!if IServerGameClients_ClientSetupVisibility] -///////////////////////////////////////////////////////////////////////// -// HookedClientSetupVisibility - -// Determine PVS origin and set PVS for the player / view entity - -void [!output PLUGIN_CLASS]::HookedClientSetupVisibility(edict_t* view_entity, edict_t* client, unsigned char *pvs, int pvs_size) -{ - // TODO: Implement Method - - RETURN_META(MRES_IGNORED); -} - -[!endif] -[!if IServerGameClients_ClientEarPosition] -///////////////////////////////////////////////////////////////////////// -// HookedClientEarPosition - -// Get the ear position for a specified client - -void [!output PLUGIN_CLASS]::HookedClientEarPosition(edict_t* entity, Vector* ear_origin) -{ - // TODO: Implement Method - - RETURN_META(MRES_IGNORED); -} - -[!endif] -[!if IServerGameClients_PostClientMessagesSent] -///////////////////////////////////////////////////////////////////////// -// HookedPostClientMessagesSent - -// Let the game .dll do stuff after messages have been sent -// to all of the clients once the server frame is complete - -void [!output PLUGIN_CLASS]::HookedPostClientMessagesSent() -{ - // TODO: Implement Method - - RETURN_META(MRES_IGNORED); -} - -[!endif] -[!if IServerGameClients_ProcessUsercmds] -///////////////////////////////////////////////////////////////////////// -// HookedProcessUsercmds - -// A block of CUserCmds has arrived from the user, decode -// them and buffer for execution during player simulation - -float [!output PLUGIN_CLASS]::HookedProcessUsercmds(edict_t* player, bf_read* buf, int num_cmds, int total_cmds, - int dropped_packets, bool ignore, bool paused) -{ - // TODO: Implement Method - - RETURN_META_VALUE(MRES_IGNORED, 0.0f); -} - -[!endif] -[!if IServerGameClients_NetworkIDValidated] -///////////////////////////////////////////////////////////////////////// -// HookedNetworkIDValidated - -// A user has had their network id setup and validated - -void [!output PLUGIN_CLASS]::HookedNetworkIDValidated(const char* user_name, const char* network_id) -{ - // TODO: Implement Method - - RETURN_META(MRES_IGNORED); -} - -[!endif] -[!if IServerGameClients_GetPlayerLimits] -///////////////////////////////////////////////////////////////////////// -// HookedGetPlayerLimits - -// Get server max players and lower bound for the same - -void [!output PLUGIN_CLASS]::HookedGetPlayerLimits(int& min_players, int& max_players, int& default_max) const -{ - // TODO: Implement Method - - RETURN_META(MRES_IGNORED); -} - -[!endif] -[!if IServerGameClients_GetPlayerState] -///////////////////////////////////////////////////////////////////////// -// HookedGetPlayerState - -// For players, looks up the CPlayerState structure corresponding to the player - -CPlayerState* [!output PLUGIN_CLASS]::HookedGetPlayerState(edict_t* player) -{ - // TODO: Implement Method - - RETURN_META_VALUE(MRES_IGNORED, NULL); -} - -[!endif] -[!if IServerGameClients_GetReplayDelay] -///////////////////////////////////////////////////////////////////////// -// HookedGetReplayDelay - -// Returns number of delay ticks if player is in Replay mode (0 = no delay) - -int [!output PLUGIN_CLASS]::HookedGetReplayDelay(edict_t* player, int& entity) -{ - // TODO: Implement Method - - RETURN_META_VALUE(MRES_IGNORED, 0); -} - -[!endif] -[!if IServerGameClients_GetBugReportInfo] -///////////////////////////////////////////////////////////////////////// -// HookedGetBugReportInfo - -// Anything this game .dll wants to add to the bug reporter text -//(e.g., the entity/model under the picker crosshair) can be added here - -void [!output PLUGIN_CLASS]::HookedGetBugReportInfo(char* buf, int size) -{ - // TODO: Implement Method - - RETURN_META(MRES_IGNORED); -} - -[!endif] -[!if IServerGameClients_SetCommandClient] -///////////////////////////////////////////////////////////////////////// -// HookedSetCommandClient - -// Sets the client index for the client who typed the command into his / her console - -void [!output PLUGIN_CLASS]::HookedSetCommandClient(int index) -{ - // TODO: Implement Method - - RETURN_META(MRES_IGNORED); -} - -[!endif] diff --git a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/plugin_hooks.h b/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/plugin_hooks.h deleted file mode 100644 index e9a9f1fdf..000000000 --- a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/plugin_hooks.h +++ /dev/null @@ -1,278 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// File: [!output PLUGIN_CLASS]Hooks.h -// Author: [!output PLUGIN_AUTHOR] -// Date: [!output CURRENT_DATE] -// -// License: [!output PLUGIN_LICENSE] -// -// This software is provided 'as-is', without any express or -// implied warranty. In no event will the authors be held liable -// for any damages arising from the use of this software. -// -// Based on code written by AlliedModders LLC. Sample Plugin -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _PLUGIN_HOOKS_H -#define _PLUGIN_HOOKS_H - -[!if IServerGameDLL_ServerActivate] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_SERVER_ACTIVATE - -#define DECL_HOOK_SERVER_ACTIVATE \ - \ - void HookedServerActivate(edict_t* edict_list, \ - int edict_count, \ - int client_max) - -[!endif] -[!if IServerGameDLL_GameInit] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_GAME_INIT - -#define DECL_HOOK_GAME_INIT \ - \ - bool HookedGameInit() - -[!endif] -[!if IServerGameDLL_GameFrame] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_GAME_FRAME - -#define DECL_HOOK_GAME_FRAME \ - \ - void HookedGameFrame(bool simulating) - -[!endif] -[!if IServerGameDLL_GameShutdown] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_GAME_SHUTDOWN - -#define DECL_HOOK_GAME_SHUTDOWN \ - \ - void HookedGameShutdown() - -[!endif] -[!if IServerGameDLL_LevelInit] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_LEVEL_INIT - -#define DECL_HOOK_LEVEL_INIT \ - \ - bool HookedLevelInit(const char* map_name, \ - char const* map_entities, \ - char const* old_level, \ - char const* landmark_name, \ - bool load_game, bool bkgnd) - -[!endif] -[!if IServerGameDLL_LevelShutdown] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_LEVEL_SHUTDOWN - -#define DECL_HOOK_LEVEL_SHUTDOWN \ - \ - void HookedLevelShutdown(); - -[!endif] -[!if IServerGameDLL_GetAllServerClasses] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_GET_ALL_SERVER_CLASSES - -#define DECL_HOOK_GET_ALL_SERVER_CLASSES \ - \ - ServerClass* HookedGetAllServerClasses() - -[!endif] -[!if IServerGameDLL_GetTickInterval] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_GET_TICK_INTERVAL - -#define DECL_HOOK_GET_TICK_INTERVAL \ - \ - float HookedGetTickInterval() const - -[!endif] -[!if IServerGameDLL_GetGameDescription] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_GET_GAME_DESC - -#define DECL_HOOK_GET_GAME_DESC \ - \ - const char* HookedGetGameDescription() - -[!endif] -[!if IServerGameClients_ClientActive] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_CLIENT_ACTIVE - -#define DECL_HOOK_CLIENT_ACTIVE \ - \ - void HookedClientActive(edict_t* entity, \ - bool load_game) - -[!endif] -[!if IServerGameClients_ClientConnect] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_CLIENT_CONNECT - -#define DECL_HOOK_CLIENT_CONNECT \ - \ - bool HookedClientConnect(edict_t* entity, \ - const char* name, \ - const char* address, \ - char* reject, \ - int reject_len) - -[!endif] -[!if IServerGameClients_ClientDisconnect] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_CLIENT_DISCONNECT - -#define DECL_HOOK_CLIENT_DISCONNECT \ - \ - void HookedClientDisconnect(edict_t* entity) - -[!endif] -[!if IServerGameClients_ClientCommand] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_CLIENT_COMMAND - -#if SOURCE_ENGINE >= SE_ORANGEBOX -#define DECL_HOOK_CLIENT_COMMAND \ - \ - void HookedClientCommand(edict_t* entity, \ - const CCommand& args) -#else -#define DECL_HOOK_CLIENT_COMMAND \ - \ - void HookedClientCommand(edict_t* entity) -#endif - -[!endif] -[!if IServerGameClients_ClientPutInServer] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_CLIENT_PUT_IN_SERVER - -#define DECL_HOOK_CLIENT_PUT_IN_SERVER \ - \ - void HookedClientPutInServer(edict_t* entity, \ - char const* name) - -[!endif] -[!if IServerGameClients_ClientSettingsChanged] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_CLIENT_SETTINGS_CHANGED - -#define DECL_HOOK_CLIENT_SETTINGS_CHANGED \ - \ - void HookedClientSettingsChanged(edict_t* edict) - -[!endif] -[!if IServerGameClients_ClientSetupVisibility] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_CLIENT_SETUP_VISIBILITY - -#define DECL_HOOK_CLIENT_SETUP_VISIBILITY \ - \ - void HookedClientSetupVisibility(edict_t* view_entity, \ - edict_t* client, \ - unsigned char *pvs, \ - int pvs_size) - -[!endif] -[!if IServerGameClients_ClientEarPosition] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_CLIENT_EAR_POSITION - -#define DECL_HOOK_CLIENT_EAR_POSITION \ - \ - void HookedClientEarPosition(edict_t* entity, \ - Vector* ear_origin) - -[!endif] -[!if IServerGameClients_PostClientMessagesSent] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_POST_CLIENT_MESSAGES_SENT - -#define DECL_HOOK_POST_CLIENT_MESSAGES_SENT \ - \ - void HookedPostClientMessagesSent() - -[!endif] -[!if IServerGameClients_ProcessUsercmds] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_PROCESS_USER_CMDS - -#define DECL_HOOK_PROCESS_USER_CMDS \ - \ - float HookedProcessUsercmds(edict_t* player, \ - bf_read* buf, \ - int num_cmds, \ - int total_cmds, \ - int dropped_packets, \ - bool ignore, \ - bool paused) - -[!endif] -[!if IServerGameClients_NetworkIDValidated] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_NETWORK_ID_VALIDATED - -#define DECL_HOOK_NETWORK_ID_VALIDATED \ - \ - void HookedNetworkIDValidated(const char* user_name, \ - const char* network_id) - -[!endif] -[!if IServerGameClients_GetPlayerLimits] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_GET_PLAYER_LIMITS - -#define DECL_HOOK_GET_PLAYER_LIMITS \ - \ - void HookedGetPlayerLimits(int& min_players, \ - int& max_players, \ - int& default_max) const - -[!endif] -[!if IServerGameClients_GetPlayerState] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_GET_PLAYER_STATE - -#define DECL_HOOK_GET_PLAYER_STATE \ - \ - CPlayerState* HookedGetPlayerState(edict_t* player) - -[!endif] -[!if IServerGameClients_GetReplayDelay] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_GET_REPLAY_DELAY - -#define DECL_HOOK_GET_REPLAY_DELAY \ - \ - int HookedGetReplayDelay(edict_t* player, \ - int& entity) - -[!endif] -[!if IServerGameClients_GetBugReportInfo] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_GET_BUG_REPORT_INFO - -#define DECL_HOOK_GET_BUG_REPORT_INFO \ - \ - void HookedGetBugReportInfo(char* buf, int size) - -[!endif] -[!if IServerGameClients_SetCommandClient] -///////////////////////////////////////////////////////////////////////// -// Define DECL_HOOK_SET_COMMAND_CLIENT - -#define DECL_HOOK_SET_COMMAND_CLIENT \ - \ - void HookedSetCommandClient(int index) - -[!endif] -#endif // _PLUGIN_HOOKS_H diff --git a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/plugin_mm.cpp b/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/plugin_mm.cpp deleted file mode 100644 index 5eeeed33e..000000000 --- a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/plugin_mm.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// File: [!output PLUGIN_CLASS].cpp -// Author: [!output PLUGIN_AUTHOR] -// Date: [!output CURRENT_DATE] -// -// License: [!output PLUGIN_LICENSE] -// -// This software is provided 'as-is', without any express or -// implied warranty. In no event will the authors be held liable -// for any damages arising from the use of this software. -// -// Based on code written by AlliedModders LLC. Sample Plugin -// -/////////////////////////////////////////////////////////////////////////////// - -#include "StdMMS.h" - -///////////////////////////////////////////////////////////////////////// -// Global Variables - -IServerGameDLL* [!output PLUGIN_CLASS]::GameServer(NULL); -IServerGameClients* [!output PLUGIN_CLASS]::GameClients(NULL); -IVEngineServer* [!output PLUGIN_CLASS]::EngineServer(NULL); -IServerPluginHelpers* [!output PLUGIN_CLASS]::PluginHelpers(NULL); -IGameEventManager2* [!output PLUGIN_CLASS]::GameEvents(NULL); -IServerPluginCallbacks* [!output PLUGIN_CLASS]::VspCallbacks(NULL); -IPlayerInfoManager* [!output PLUGIN_CLASS]::PlayerInfoManager(NULL); -ICvar* [!output PLUGIN_CLASS]::CVar(NULL); -CGlobalVars* [!output PLUGIN_CLASS]::GlobalVars(NULL); - - -///////////////////////////////////////////////////////////////////////// -// Class BaseAccessor - -// This is needed to register cvars / CON_COMMANDs - -class BaseAccessor : public IConCommandBaseAccessor -{ - public: - - bool RegisterConCommandBase(ConCommandBase *pCommandBase) - { - // Always call META_REGCVAR instead - // of going through the [!output PLUGIN_CLASS]::EngineServer - - return META_REGCVAR(pCommandBase); - } -} -s_BaseAccessor; - - -/////////////////////////////////////////////////////////////////////////////// -// Expose the Plugin - -[!output PLUGIN_CLASS] [!output PLUGIN_CLASS]::Global; - -PLUGIN_EXPOSE([!output PLUGIN_CLASS], [!output PLUGIN_CLASS]::Global); - - -///////////////////////////////////////////////////////////////////////// -// Load - -bool [!output PLUGIN_CLASS]::Load(PluginId id, ISmmAPI* ismm, char* error, size_t maxlen, bool late) -{ - PLUGIN_SAVEVARS(); - - // Get the current Enginefactory interfaces - - GET_V_IFACE_CURRENT(GetEngineFactory, [!output PLUGIN_CLASS]::EngineServer, IVEngineServer, INTERFACEVERSION_VENGINESERVER); - GET_V_IFACE_CURRENT(GetEngineFactory, [!output PLUGIN_CLASS]::GameEvents, IGameEventManager2, INTERFACEVERSION_GAMEEVENTSMANAGER2); - GET_V_IFACE_CURRENT(GetEngineFactory, [!output PLUGIN_CLASS]::PluginHelpers, IServerPluginHelpers, INTERFACEVERSION_ISERVERPLUGINHELPERS); - GET_V_IFACE_CURRENT(GetEngineFactory, [!output PLUGIN_CLASS]::CVar, ICvar, CVAR_INTERFACE_VERSION); - - // Get the current ServerFactory interfaces - - GET_V_IFACE_ANY(GetServerFactory, [!output PLUGIN_CLASS]::GameServer, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL); - GET_V_IFACE_ANY(GetServerFactory, [!output PLUGIN_CLASS]::GameClients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS); - GET_V_IFACE_ANY(GetServerFactory, [!output PLUGIN_CLASS]::PlayerInfoManager, IPlayerInfoManager, INTERFACEVERSION_PLAYERINFOMANAGER); - - // Get the current Globals interfaces - - [!output PLUGIN_CLASS]::GlobalVars = ismm->GetCGlobals(); - - // Load the VSP listener. This is usually needed for IServerPluginHelpers - - if (([!output PLUGIN_CLASS]::VspCallbacks = ismm->GetVSPInfo(NULL)) == NULL) - { - ismm->AddListener(this, this); - ismm->EnableVSPListener(); - } - - // Add the hooks - - AddHooks(); - - ENGINE_CALL(LogPrint)("All hooks started!\n"); - - // Register the base accessor - - #if SOURCE_ENGINE >= SE_ORANGEBOX - - g_pCVar = [!output PLUGIN_CLASS]::CVar; - ConVar_Register(0, &s_BaseAccessor); - - #else - - ConCommandBaseMgr::OneTimeInit(&s_BaseAccessor); - - #endif - - return true; -} - -///////////////////////////////////////////////////////////////////////// -// Unload - -bool [!output PLUGIN_CLASS]::Unload(char *error, size_t maxlen) -{ - // Remove the hooks - - RemoveHooks(); - - return true; -} - -///////////////////////////////////////////////////////////////////////// -// OnVSPListening - -void [!output PLUGIN_CLASS]::OnVSPListening(IServerPluginCallbacks* vsp_callbacks) -{ - [!output PLUGIN_CLASS]::VspCallbacks = vsp_callbacks; -} - -///////////////////////////////////////////////////////////////////////// -// GetVersion - -const char* [!output PLUGIN_CLASS]::GetVersion() -{ - return "1.0.0.0"; -} - -///////////////////////////////////////////////////////////////////////// -// GetDate - -const char* [!output PLUGIN_CLASS]::GetDate() -{ - return __DATE__; -} - -///////////////////////////////////////////////////////////////////////// -// GetLogTag - -const char* [!output PLUGIN_CLASS]::GetLogTag() -{ - return "[!output PLUGIN_NAME]Log"; -} - -///////////////////////////////////////////////////////////////////////// -// GetLicense - -const char* [!output PLUGIN_CLASS]::GetLicense() -{ - return "[!output PLUGIN_LICENSE]"; -} - -///////////////////////////////////////////////////////////////////////// -// GetAuthor - -const char* [!output PLUGIN_CLASS]::GetAuthor() -{ - return "[!output PLUGIN_AUTHOR]"; -} - -///////////////////////////////////////////////////////////////////////// -// GetDescription - -const char* [!output PLUGIN_CLASS]::GetDescription() -{ - return "[!output PLUGIN_DESC]"; -} - -///////////////////////////////////////////////////////////////////////// -// GetName - -const char* [!output PLUGIN_CLASS]::GetName() -{ - return "[!output PLUGIN_NAME]"; -} - -///////////////////////////////////////////////////////////////////////// -// GetURL - -const char* [!output PLUGIN_CLASS]::GetURL() -{ - return "[!output PLUGIN_URL]"; -} diff --git a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/plugin_mm.h b/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/plugin_mm.h deleted file mode 100644 index 2ca892e00..000000000 --- a/utils/mmsource/support/msvc_project_templates/VC/VCWizards/AppWiz/Metamod/MMSProjectTemplate/Templates/1033/plugin_mm.h +++ /dev/null @@ -1,164 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// -// File: [!output PLUGIN_CLASS].h -// Author: [!output PLUGIN_AUTHOR] -// Date: [!output CURRENT_DATE] -// -// License: [!output PLUGIN_LICENSE] -// -// This software is provided 'as-is', without any express or -// implied warranty. In no event will the authors be held liable -// for any damages arising from the use of this software. -// -// Based on code written by AlliedModders LLC. Sample Plugin -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _PLUGIN_H -#define _PLUGIN_H - -///////////////////////////////////////////////////////////////////////// - -class CCommand; - -///////////////////////////////////////////////////////////////////////// -// Class [!output PLUGIN_CLASS] - -class [!output PLUGIN_CLASS] : public ISmmPlugin, public IMetamodListener -{ - //////////////////////////////////////// - // Plugin Interface - - public: - - virtual bool Load(PluginId id, - ISmmAPI* ismm, - char* error, - size_t maxlen, - bool late); - - virtual bool Unload(char* error, size_t maxlen); - virtual void OnVSPListening(IServerPluginCallbacks* vsp_callbacks); - - //////////////////////////////////////// - // Plugin Info - - public: - - virtual const char* GetAuthor(); - virtual const char* GetName(); - virtual const char* GetDescription(); - virtual const char* GetURL(); - virtual const char* GetLicense(); - virtual const char* GetVersion(); - virtual const char* GetDate(); - virtual const char* GetLogTag(); - - //////////////////////////////////////// - // Plugin Globals - - public: - - static IServerGameDLL* GameServer; - static IServerGameClients* GameClients; - static IVEngineServer* EngineServer; - static IServerPluginHelpers* PluginHelpers; - static IGameEventManager2* GameEvents; - static IServerPluginCallbacks* VspCallbacks; - static IPlayerInfoManager* PlayerInfoManager; - static ICvar* CVar; - static CGlobalVars* GlobalVars; - - static [!output PLUGIN_CLASS] Global; - - //////////////////////////////////////// - // Hooks - - private: - - void AddHooks(); - void RemoveHooks(); - -[!if IServerGameDLL_ServerActivate] - DECL_HOOK_SERVER_ACTIVATE; -[!endif] -[!if IServerGameDLL_GameInit] - DECL_HOOK_GAME_INIT; -[!endif] -[!if IServerGameDLL_GameFrame] - DECL_HOOK_GAME_FRAME; -[!endif] -[!if IServerGameDLL_GameShutdown] - DECL_HOOK_GAME_SHUTDOWN; -[!endif] -[!if IServerGameDLL_LevelInit] - DECL_HOOK_LEVEL_INIT; -[!endif] -[!if IServerGameDLL_LevelShutdown] - DECL_HOOK_LEVEL_SHUTDOWN; -[!endif] -[!if IServerGameDLL_GetAllServerClasses] - DECL_HOOK_GET_ALL_SERVER_CLASSES; -[!endif] -[!if IServerGameDLL_GetTickInterval] - DECL_HOOK_GET_TICK_INTERVAL; -[!endif] -[!if IServerGameDLL_GetGameDescription] - DECL_HOOK_GET_GAME_DESC; -[!endif] -[!if IServerGameClients_ClientActive] - DECL_HOOK_CLIENT_ACTIVE; -[!endif] -[!if IServerGameClients_ClientConnect] - DECL_HOOK_CLIENT_CONNECT; -[!endif] -[!if IServerGameClients_ClientDisconnect] - DECL_HOOK_CLIENT_DISCONNECT; -[!endif] -[!if IServerGameClients_ClientCommand] - DECL_HOOK_CLIENT_COMMAND; -[!endif] -[!if IServerGameClients_ClientPutInServer] - DECL_HOOK_CLIENT_PUT_IN_SERVER; -[!endif] -[!if IServerGameClients_ClientSettingsChanged] - DECL_HOOK_CLIENT_SETTINGS_CHANGED; -[!endif] -[!if IServerGameClients_ClientSetupVisibility] - DECL_HOOK_CLIENT_SETUP_VISIBILITY; -[!endif] -[!if IServerGameClients_ClientEarPosition] - DECL_HOOK_CLIENT_EAR_POSITION; -[!endif] -[!if IServerGameClients_PostClientMessagesSent] - DECL_HOOK_POST_CLIENT_MESSAGES_SENT; -[!endif] -[!if IServerGameClients_ProcessUsercmds] - DECL_HOOK_PROCESS_USER_CMDS; -[!endif] -[!if IServerGameClients_NetworkIDValidated] - DECL_HOOK_NETWORK_ID_VALIDATED; -[!endif] -[!if IServerGameClients_GetPlayerLimits] - DECL_HOOK_GET_PLAYER_LIMITS; -[!endif] -[!if IServerGameClients_GetPlayerState] - DECL_HOOK_GET_PLAYER_STATE; -[!endif] -[!if IServerGameClients_GetReplayDelay] - DECL_HOOK_GET_REPLAY_DELAY; -[!endif] -[!if IServerGameClients_GetBugReportInfo] - DECL_HOOK_GET_BUG_REPORT_INFO; -[!endif] -[!if IServerGameClients_SetCommandClient] - DECL_HOOK_SET_COMMAND_CLIENT; -[!endif] -}; - -///////////////////////////////////////////////////////////////////////// -// Global Vars - -PLUGIN_GLOBALVARS(); - -#endif // _PLUGIN_H diff --git a/utils/mmsource/versionlib/AMBuildScript b/utils/mmsource/versionlib/AMBuildScript deleted file mode 100644 index 0e239e4a5..000000000 --- a/utils/mmsource/versionlib/AMBuildScript +++ /dev/null @@ -1,16 +0,0 @@ -# vim: sts=2 ts=8 sw=2 tw=99 et ft=python: - -rvalue = {} -for arch in MMS.archs: - libname = 'version' - lib = MMS.StaticLibrary(builder, libname, arch) - lib.compiler.defines.remove('MMS_USE_VERSIONLIB') - lib.compiler.sourcedeps += MMS.generated_headers - lib.sources += [ - 'versionlib.cpp' - ] - - cmd = builder.Add(lib) - - rvalue[arch] = cmd.binary - diff --git a/utils/mmsource/versionlib/versionlib.cpp b/utils/mmsource/versionlib/versionlib.cpp deleted file mode 100644 index df5d6879b..000000000 --- a/utils/mmsource/versionlib/versionlib.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2010 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#include -#include - -const char *METAMOD_LOCAL_REV = MMS_BUILD_LOCAL_REV; -const char *METAMOD_SHA = MMS_BUILD_CSET; -const char *METAMOD_VERSION = MMS_VERSION_STRING; -const char *METAMOD_BUILD_TIME = __DATE__ " " __TIME__; diff --git a/utils/mmsource/versionlib/versionlib.h b/utils/mmsource/versionlib/versionlib.h deleted file mode 100644 index 07a4c266a..000000000 --- a/utils/mmsource/versionlib/versionlib.h +++ /dev/null @@ -1,47 +0,0 @@ -/** - * vim: set ts=4 sw=4 tw=99 noet : - * ====================================================== - * Metamod:Source - * Copyright (C) 2004-2010 AlliedModders LLC and authors. - * All rights reserved. - * ====================================================== - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in a - * product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ -#ifndef _INCLUDE_METAMOD_VERSIONLIB_H_ -#define _INCLUDE_METAMOD_VERSIONLIB_H_ - -#if !defined(MMS_USE_VERSIONLIB) -// These get defined in metamod_version.h since -// versionlib does not use versionlib. -# undef METAMOD_LOCAL_REV -# undef METAMOD_CSET -# undef METAMOD_VERSION -# undef METAMOD_BUILD_TIME -#endif - -#ifdef __cplusplus -# define EXTERN_C extern "C" -#else -# define EXTERN_C extern -#endif -EXTERN_C const char *METAMOD_LOCAL_REV; -EXTERN_C const char *METAMOD_SHA; -EXTERN_C const char *METAMOD_VERSION; -EXTERN_C const char *METAMOD_BUILD_TIME; - -#endif // _INCLUDE_METAMOD_VERSIONLIB_H_ diff --git a/versioning/AMBuildScript b/versioning/AMBuildScript new file mode 100644 index 000000000..c7b34d307 --- /dev/null +++ b/versioning/AMBuildScript @@ -0,0 +1,42 @@ +# vim: set ts=8 sts=2 sw=2 tw=99 et ft=python: +import os, sys +import re + +builder.SetBuildFolder('/') + +includes = builder.AddFolder('includes/version') + +argv = [ + sys.executable, + os.path.join(builder.sourcePath, 'versioning', 'generate.py'), + os.path.join(builder.sourcePath), + os.path.join(builder.buildPath, 'includes'), +] +outputs = [ + os.path.join(builder.buildFolder, 'includes', 'build_version_auto.h'), +] + +with open(os.path.join(builder.sourcePath, '.git', 'HEAD')) as fp: + head_contents = fp.read().strip() + if re.search('^[a-fA-F0-9]{40}$', head_contents): + git_head_path = os.path.join(builder.sourcePath, '.git', 'HEAD') + else: + git_state = head_contents.split(':')[1].strip() + git_head_path = os.path.join(builder.sourcePath, '.git', git_state) + if not os.path.exists(git_head_path): + git_head_path = os.path.join(builder.sourcePath, '.git', 'HEAD') + +sources = [ + # This is a hack, but we need some way to only run this script when Git changes. + git_head_path, + + # The script source is a dependency, of course... + argv[1] +] +output_nodes = builder.AddCommand( + inputs=sources, + argv=argv, + outputs=outputs +) + +rvalue = output_nodes \ No newline at end of file diff --git a/versioning/build_info.cpp b/versioning/build_info.cpp new file mode 100644 index 000000000..67e883dec --- /dev/null +++ b/versioning/build_info.cpp @@ -0,0 +1,13 @@ +#include "build_info.h" +#include "rcbot/rb-platform.h" + +// generated with versioning/generate.py, AMBuild handles this +#include + +const char* build_info::authors = "Cheeseh, RoboCop, nosoop, pongo1231, caxanga334"; +const char* build_info::url = "http://rcbot.bots-united.com/"; + +const char* build_info::long_version = "APGRoboCop/rcbot2@" GIT_COMMIT_HASH; +const char* build_info::short_version = "2.0-alpha7 " RCBOT_ARCH_TAG " (apg)-" GIT_COMMIT_SHORT_HASH; + +const char* build_info::date = __DATE__; \ No newline at end of file diff --git a/versioning/build_info.h b/versioning/build_info.h new file mode 100644 index 000000000..a4b7625a6 --- /dev/null +++ b/versioning/build_info.h @@ -0,0 +1,14 @@ +#ifndef __RCBOT_VERSION_STUB_H__ +#define __RCBOT_VERSION_STUB_H__ + +namespace build_info { + extern const char* authors; + extern const char* url; + + extern const char* long_version; + extern const char* short_version; + + extern const char* date; +} + +#endif diff --git a/versioning/generate.py b/versioning/generate.py new file mode 100644 index 000000000..61f27c57e --- /dev/null +++ b/versioning/generate.py @@ -0,0 +1,37 @@ +#!/usr/bin/python3 + +import subprocess + +output_filename = 'build_version_auto.h' + +def git_version(): + return subprocess.check_output(['git', 'log', '--pretty=format:%H', '-n', '1']).decode('ascii') + +if __name__ == '__main__': + import argparse, re, collections, functools, os, textwrap + from string import Template + + parser = argparse.ArgumentParser(description = "Generates git snapshot headers.", + usage = "%(prog)s [options]") + + parser.add_argument('source_dir', help="Source directory") + parser.add_argument('output_dir', help="Output directory") + + args = parser.parse_args() + + source_directory = os.path.abspath(os.path.normpath(args.source_dir)) + output_directory = os.path.normpath(args.output_dir) + with open(os.path.join(output_directory, output_filename), 'wt') as f: + values = { + 'git_hash': git_version(), + 'git_short_hash': git_version()[:8] + } + f.write(textwrap.dedent(""" + #if defined _auto_version_included + #endinput + #endif + #define _auto_version_included + + #define GIT_COMMIT_HASH "{git_hash}" + #define GIT_COMMIT_SHORT_HASH "{git_short_hash}" + """.format(**values))[1:])